Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog: (21 commits)
  [WATCHDOG] at32ap700x_wdt.c - Fix compilation warnings
  [WATCHDOG] at32ap700x_wdt.c - Add spinlock support
  [WATCHDOG] at32ap700x_wdt.c - Add nowayout + MAGICCLOSE features
  [WATCHDOG] at32ap700x_wdt.c - timeout module parameter patch
  [WATCHDOG] at32ap700x_wdt.c - checkpatch.pl-0.05 clean-up's
  [WATCHDOG] change s3c2410_wdt to using dev_() macros for output
  [WATCHDOG] s3c2410_wdt announce initialisation
  [WATCHDOG] at32ap700x-wdt: add iounmap if probe function fails
  [WATCHDOG] at32ap700x-wdt: add missing iounmap in _remove
  [WATCHDOG] watchdog-driver-for-at32ap700x-devices-fix-2
  [WATCHDOG] watchdog-driver-for-at32ap700x-devices-fix
  [WATCHDOG] Watchdog driver for AT32AP700X devices
  [WATCHDOG] Mixcom Watchdog - CodingStyle clean-up
  [WATCHDOG] Mixcom Watchdog - clean-up printk's
  [WATCHDOG] Mixcom Watchdog - clean-up printk's
  [WATCHDOG] Mixcom Watchdog - checkcard part 2
  [WATCHDOG] Mixcom Watchdog - checkcard
  [WATCHDOG] Mixcom Watchdog - get rid of port offset's
  [WATCHDOG] Mixcom Watchdog - update "Documentation"
  [WATCHDOG] Remove the redundant check for pwrite() in EP93XXX watchdog.
  ...
diff --git a/.gitignore b/.gitignore
index 060a71d..8d15830 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,3 +45,6 @@
 
 # cscope files
 cscope.*
+
+*.orig
+*.rej
diff --git a/CREDITS b/CREDITS
index 273d72b..79fd13d 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3301,14 +3301,6 @@
 S: Beaverton, Oregon 97005
 S: USA
 
-N: Li Yang
-E: leoli@freescale.com
-D: Freescale Highspeed USB device driver
-D: Freescale QE SoC support and Ethernet driver
-S: B-1206 Jingmao Guojigongyu
-S: 16 Baliqiao Nanjie, Beijing 101100
-S: People's Repulic of China
-
 N: Marcelo Tosatti
 E: marcelo@kvack.org
 D: v2.4 kernel maintainer
@@ -3726,6 +3718,14 @@
 S: New York, New York 10025
 S: USA
 
+N: Li Yang
+E: leoli@freescale.com
+D: Freescale Highspeed USB device driver
+D: Freescale QE SoC support and Ethernet driver
+S: B-1206 Jingmao Guojigongyu
+S: 16 Baliqiao Nanjie, Beijing 101100
+S: People's Repulic of China
+
 N: Victor Yodaiken
 E: yodaiken@fsmlabs.com
 D: RTLinux (RealTime Linux)
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index f08ca95..8b05636 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -12,6 +12,8 @@
 
 00-INDEX
 	- this file.
+ABI/
+	- info on kernel <-> userspace ABI and relative interface stability.
 BUG-HUNTING
 	- brute force method of doing binary search of patches to find bug.
 Changes
@@ -25,37 +27,57 @@
 DocBook/
 	- directory with DocBook templates etc. for kernel documentation.
 HOWTO
-	- The process and procedures of how to do Linux kernel development.
+	- the process and procedures of how to do Linux kernel development.
 IO-mapping.txt
 	- how to access I/O mapped memory from within device drivers.
 IPMI.txt
 	- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
 IRQ-affinity.txt
 	- how to select which CPU(s) handle which interrupt events on SMP.
+IRQ.txt
+	- description of what an IRQ is.
 ManagementStyle
 	- how to (attempt to) manage kernel hackers.
 MSI-HOWTO.txt
 	- the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
+PCIEBUS-HOWTO.txt
+	- a guide describing the PCI Express Port Bus driver.
 RCU/
 	- directory with info on RCU (read-copy update).
 README.DAC960
 	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
+README.cycladesZ
+	- info on Cyclades-Z firmware loading.
 SAK.txt
 	- info on Secure Attention Keys.
+SecurityBugs
+	- procedure for reporting security bugs found in the kernel.
+SubmitChecklist
+	- Linux kernel patch submission checklist.
 SubmittingDrivers
 	- procedure to get a new driver source included into the kernel tree.
 SubmittingPatches
 	- procedure to get a source patch included into the kernel tree.
 VGA-softcursor.txt
 	- how to change your VGA cursor from a blinking underscore.
+accounting/
+	- documentation on accounting and taskstats.
+aoe/
+	- description of AoE (ATA over Ethernet) along with config examples.
 applying-patches.txt
 	- description of various trees and how to apply their patches.
 arm/
 	- directory with info about Linux on the ARM architecture.
+atomic_ops.txt
+	- semantics and behavior of atomic and bitmask operations.
+auxdisplay/
+	- misc. LCD driver documentation (cfag12864b, ks0108).
 basic_profiling.txt
 	- basic instructions for those who wants to profile Linux kernel.
 binfmt_misc.txt
 	- info on the kernel support for extra binary formats.
+blackfin/
+	- directory with documentation for the Blackfin arch.
 block/
 	- info on the Block I/O (BIO) layer.
 cachetlb.txt
@@ -68,16 +90,32 @@
 	- cli()/sti() removal guide.
 computone.txt
 	- info on Computone Intelliport II/Plus Multiport Serial Driver.
+connector/
+	- docs on the netlink based userspace<->kernel space communication mod.
+console/
+	- documentation on Linux console drivers.
 cpqarray.txt
 	- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
 cpu-freq/
 	- info on CPU frequency and voltage scaling.
+cpu-hotplug.txt
+	- document describing CPU hotplug support in the Linux kernel.
+cpu-load.txt
+	- document describing how CPU load statistics are collected.
+cpusets.txt
+	- documents the cpusets feature; assign CPUs and Mem to a set of tasks.
+cputopology.txt
+	- documentation on how CPU topology info is exported via sysfs.
 cris/
 	- directory with info about Linux on CRIS architecture.
 crypto/
 	- directory with info on the Crypto API.
+dcdbas.txt
+	- information on the Dell Systems Management Base Driver.
 debugging-modules.txt
 	- some notes on debugging modules after Linux 2.6.3.
+dell_rbu.txt
+	- document demonstrating the use of the Dell Remote BIOS Update driver.
 device-mapper/
 	- directory with info on Device Mapper.
 devices.txt
@@ -86,32 +124,52 @@
 	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
 dnotify.txt
 	- info about directory notification in Linux.
+dontdiff
+	- file containing a list of files that should never be diff'ed.
 driver-model/
 	- directory with info about Linux driver model.
+drivers/
+	- directory with driver documentation (currently only EDAC).
 dvb/
 	- info on Linux Digital Video Broadcast (DVB) subsystem.
 early-userspace/
 	- info about initramfs, klibc, and userspace early during boot.
+ecryptfs.txt
+	- docs on eCryptfs: stacked cryptographic filesystem for Linux.
 eisa.txt
 	- info on EISA bus support.
 exception.txt
 	- how Linux v2.2 handles exceptions without verify_area etc.
+fault-injection/
+	- dir with docs about the fault injection capabilities infrastructure.
 fb/
 	- directory with info on the frame buffer graphics abstraction layer.
+feature-removal-schedule.txt
+	- list of files and features that are going to be removed.
 filesystems/
 	- directory with info on the various filesystems that Linux supports.
 firmware_class/
 	- request_firmware() hotplug interface info.
 floppy.txt
 	- notes and driver options for the floppy disk driver.
+fujitsu/
+	- Fujitsu FR-V Linux documentation.
+gpio.txt
+	- overview of GPIO (General Purpose Input/Output) access conventions.
 hayes-esp.txt
 	- info on using the Hayes ESP serial driver.
 highuid.txt
 	- notes on the change from 16 bit to 32 bit user/group IDs.
 hpet.txt
 	- High Precision Event Timer Driver for Linux.
+hrtimer/
+	- info on the timer_stats debugging facility for timer (ab)use.
+hrtimers/
+	- info on the hrtimers subsystem for high-resolution kernel timers.
 hw_random.txt
 	- info on Linux support for random number generator in i8xx chipsets.
+hwmon/
+	- directory with docs on various hardware monitoring drivers.
 i2c/
 	- directory with info about the I2C bus/protocol (2 wire, kHz speed).
 i2o/
@@ -122,16 +180,22 @@
 	- directory with info about Linux on Intel 64 bit architecture.
 ide.txt
 	- important info for users of ATA devices (IDE/EIDE disks and CD-ROMS).
+infiniband/
+	- directory with documents concerning Linux InfiniBand support.
 initrd.txt
 	- how to use the RAM disk as an initial/temporary root filesystem.
 input/
 	- info on Linux input device support.
 io_ordering.txt
 	- info on ordering I/O writes to memory-mapped addresses.
+ioctl/
+	- directory with documents describing various IOCTL calls.
 ioctl-number.txt
 	- how to implement and register device/driver ioctl calls.
 iostats.txt
 	- info on I/O statistics Linux kernel provides.
+irqflags-tracing.txt
+	- how to use the irq-flags tracing feature.
 isapnp.txt
 	- info on Linux ISA Plug & Play support.
 isdn/
@@ -140,26 +204,40 @@
 	- info on the in-kernel binary support for Java(tm).
 kbuild/
 	- directory with info about the kernel build process.
-kdumpt.txt
-       - mini HowTo on getting the crash dump code to work.
+kdump/
+	- directory with mini HowTo on getting the crash dump code to work.
 kernel-doc-nano-HOWTO.txt
 	- mini HowTo on generation and location of kernel documentation files.
 kernel-docs.txt
 	- listing of various WWW + books that document kernel internals.
 kernel-parameters.txt
 	- summary listing of command line / boot prompt args for the kernel.
+keys-request-key.txt
+	- description of the kernel key request service.
+keys.txt
+	- description of the kernel key retention service.
 kobject.txt
 	- info of the kobject infrastructure of the Linux kernel.
+kprobes.txt
+	- documents the kernel probes debugging feature.
+kref.txt
+	- docs on adding reference counters (krefs) to kernel objects.
 laptop-mode.txt
-	- How to conserve battery power using laptop-mode.
+	- how to conserve battery power using laptop-mode.
 ldm.txt
 	- a brief description of LDM (Windows Dynamic Disks).
+leds-class.txt
+	- documents LED handling under Linux.
+local_ops.txt
+	- semantics and behavior of local atomic operations.
+lockdep-design.txt
+	- documentation on the runtime locking correctness validator.
 locks.txt
 	- info on file locking implementations, flock() vs. fcntl(), etc.
 logo.gif
-	- Full colour GIF image of Linux logo (penguin).
+	- full colour GIF image of Linux logo (penguin - Tux).
 logo.txt
-	- Info on creator of above logo & site to get additional images from.
+	- info on creator of above logo & site to get additional images from.
 m68k/
 	- directory with info about Linux on Motorola 68k architecture.
 magic-number.txt
@@ -170,6 +248,8 @@
 	- info on supporting Micro Channel Architecture (e.g. PS/2) systems.
 md.txt
 	- info on boot arguments for the multiple devices driver.
+memory-barriers.txt
+	- info on Linux kernel memory barriers.
 memory.txt
 	- info on typical Linux memory problems.
 mips/
@@ -177,9 +257,11 @@
 mono.txt
 	- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
 moxa-smartio
-	- info on installing/using Moxa multiport serial driver.
+	- file with info on installing/using Moxa multiport serial driver.
 mtrr.txt
 	- how to use PPro Memory Type Range Registers to increase performance.
+mutex-design.txt
+	- info on the generic mutex subsystem.
 nbd.txt
 	- info on a TCP implementation of a network block device.
 netlabel/
@@ -190,6 +272,8 @@
 	- short guide on setting up a diskless box with NFS root filesystem.
 nmi_watchdog.txt
 	- info on NMI watchdog for SMP systems.
+nommu-mmap.txt
+	- documentation about no-mmu memory mapping support.
 numastat.txt
 	- info on how to read Numa policy hit/miss statistics in sysfs.
 oops-tracing.txt
@@ -202,8 +286,16 @@
 	- how to use the parallel-port driver.
 parport-lowlevel.txt
 	- description and usage of the low level parallel port functions.
+pci-error-recovery.txt
+	- info on PCI error recovery.
 pci.txt
 	- info on the PCI subsystem for device driver authors.
+pcieaer-howto.txt
+	- the PCI Express Advanced Error Reporting Driver Guide HOWTO.
+pcmcia/
+	- info on the Linux PCMCIA driver.
+pi-futex.txt
+	- documentation on lightweight PI-futexes.
 pm.txt
 	- info on Linux power management support.
 pnp.txt
@@ -214,18 +306,32 @@
 	- directory with info on using Linux with the PowerPC.
 preempt-locking.txt
 	- info on locking under a preemptive kernel.
+prio_tree.txt
+	- info on radix-priority-search-tree use for indexing vmas.
 ramdisk.txt
 	- short guide on how to set up and use the RAM disk.
+rbtree.txt
+	- info on what red-black trees are and what they are for.
 riscom8.txt
 	- notes on using the RISCom/8 multi-port serial driver.
+robust-futex-ABI.txt
+	- documentation of the robust futex ABI.
+robust-futexes.txt
+	- a description of what robust futexes are.
 rocket.txt
 	- info on the Comtrol RocketPort multiport serial driver.
 rpc-cache.txt
 	- introduction to the caching mechanisms in the sunrpc layer.
+rt-mutex-design.txt
+	- description of the RealTime mutex implementation design.
+rt-mutex.txt
+	- desc. of RT-mutex subsystem with PI (Priority Inheritance) support.
 rtc.txt
 	- notes on how to use the Real Time Clock (aka CMOS clock) driver.
 s390/
 	- directory with info on using Linux on the IBM S390.
+sched-arch.txt
+	- CPU Scheduler implementation hints for architecture specific code.
 sched-coding.txt
 	- reference for various scheduler-related methods in the O(1) scheduler.
 sched-design.txt
@@ -240,22 +346,32 @@
 	- directory with info on the low level serial API.
 serial-console.txt
 	- how to set up Linux with a serial line console as the default.
+sgi-ioc4.txt
+	- description of the SGI IOC4 PCI (multi function) device.
 sgi-visws.txt
 	- short blurb on the SGI Visual Workstations.
 sh/
 	- directory with info on porting Linux to a new architecture.
+sharedsubtree.txt
+	- a description of shared subtrees for namespaces.
 smart-config.txt
 	- description of the Smart Config makefile feature.
 smp.txt
 	- a few notes on symmetric multi-processing.
+sony-laptop.txt
+	- Sony Notebook Control Driver (SNC) Readme.
 sonypi.txt
 	- info on Linux Sony Programmable I/O Device support.
 sound/
 	- directory with info on sound card support.
 sparc/
 	- directory with info on using Linux on Sparc architecture.
+sparse.txt
+	- info on how to obtain and use the sparse tool for typechecking.
 specialix.txt
 	- info on hardware/driver for specialix IO8+ multiport serial card.
+spi/
+	- overview of Linux kernel Serial Peripheral Interface (SPI) support.
 spinlocks.txt
 	- info on using spinlocks to provide exclusive access in kernel.
 stable_api_nonsense.txt
@@ -274,24 +390,32 @@
 	- info on the magic SysRq key.
 telephony/
 	- directory with info on telephony (e.g. voice over IP) support.
+thinkpad-acpi.txt
+	- information on the (IBM and Lenovo) ThinkPad ACPI Extras driver.
 time_interpolators.txt
 	- info on time interpolators.
 tipar.txt
 	- information about Parallel link cable for Texas Instruments handhelds.
 tty.txt
 	- guide to the locking policies of the tty layer.
-unicode.txt
-	- info on the Unicode character/font mapping used in Linux.
 uml/
 	- directory with information about User Mode Linux.
+unicode.txt
+	- info on the Unicode character/font mapping used in Linux.
+unshare.txt
+	- description of the Linux unshare system call.
 usb/
 	- directory with info regarding the Universal Serial Bus.
+video-output.txt
+	- sysfs class driver interface to enable/disable a video output device.
 video4linux/
 	- directory with info regarding video/TV/radio cards and linux.
 vm/
 	- directory with info on the Linux vm code.
 voyager.txt
 	- guide to running Linux on the Voyager architecture.
+w1/
+	- directory with documents regarding the 1-wire (w1) subsystem.
 watchdog/
 	- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
 x86_64/
diff --git a/Documentation/ABI/removed/raw1394_legacy_isochronous b/Documentation/ABI/removed/raw1394_legacy_isochronous
new file mode 100644
index 0000000..1b62962
--- /dev/null
+++ b/Documentation/ABI/removed/raw1394_legacy_isochronous
@@ -0,0 +1,16 @@
+What:		legacy isochronous ABI of raw1394 (1st generation iso ABI)
+Date:		June 2007 (scheduled), removed in kernel v2.6.23
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+	The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
+	been deprecated for quite some time.  They are very inefficient as they
+	come with high interrupt load and several layers of callbacks for each
+	packet.  Because of these deficiencies, the video1394 and dv1394 drivers
+	and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
+
+Users:
+	libraw1394 users via the long deprecated API raw1394_iso_write,
+	raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
+
+	libdc1394, which optionally uses these old libraw1394 calls
+	alternatively to the more efficient video1394 ABI
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index f9937ad..9734577 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -39,3 +39,16 @@
 		If you want to suspend a device immediately but leave it
 		free to wake up in response to I/O requests, you should
 		write "0" to power/autosuspend.
+
+What:		/sys/bus/usb/devices/.../power/persist
+Date:		May 2007
+KernelVersion:	2.6.23
+Contact:	Alan Stern <stern@rowland.harvard.edu>
+Description:
+		If CONFIG_USB_PERSIST is set, then each USB device directory
+		will contain a file named power/persist.  The file holds a
+		boolean value (0 or 1) indicating whether or not the
+		"USB-Persist" facility is enabled for the device.  Since the
+		facility is inherently dangerous, it is disabled by default
+		for all devices except hubs.  For more information, see
+		Documentation/usb/persist.txt.
diff --git a/Documentation/BUG-HUNTING b/Documentation/BUG-HUNTING
index 65b97e1..35f5bd2 100644
--- a/Documentation/BUG-HUNTING
+++ b/Documentation/BUG-HUNTING
@@ -191,6 +191,30 @@
 >        mov        0x8(%ebp), %ebx         ! %ebx = skb->sk
 >        mov        0x13c(%ebx), %eax       ! %eax = inet_sk(sk)->opt
 
+In addition, you can use GDB to figure out the exact file and line
+number of the OOPS from the vmlinux file. If you have
+CONFIG_DEBUG_INFO enabled, you can simply copy the EIP value from the
+OOPS:
+
+ EIP:    0060:[<c021e50e>]    Not tainted VLI
+
+And use GDB to translate that to human-readable form:
+
+  gdb vmlinux
+  (gdb) l *0xc021e50e
+
+If you don't have CONFIG_DEBUG_INFO enabled, you use the function
+offset from the OOPS:
+
+ EIP is at vt_ioctl+0xda8/0x1482
+
+And recompile the kernel with CONFIG_DEBUG_INFO enabled:
+
+  make vmlinux
+  gdb vmlinux
+  (gdb) p vt_ioctl
+  (gdb) l *(0x<address of vt_ioctl> + 0xda8)
+
 Another very useful option of the Kernel Hacking section in menuconfig is
 Debug memory allocations. This will help you see whether data has been
 initialised and not set before use etc. To see the values that get assigned
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index afc2867..a667eb1 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -218,6 +218,18 @@
 
 and no space around the '.' and "->" structure member operators.
 
+Do not leave trailing whitespace at the ends of lines.  Some editors with
+"smart" indentation will insert whitespace at the beginning of new lines as
+appropriate, so you can start typing the next line of code right away.
+However, some such editors do not remove the whitespace if you end up not
+putting a line of code there, such as if you leave a blank line.  As a result,
+you end up with lines containing trailing whitespace.
+
+Git will warn you about patches that introduce trailing whitespace, and can
+optionally strip the trailing whitespace for you; however, if applying a series
+of patches, this may make later patches in the series fail by changing their
+context lines.
+
 
 		Chapter 4: Naming
 
@@ -495,29 +507,40 @@
 remember: "indent" is not a fix for bad programming.
 
 
-		Chapter 10: Configuration-files
+		Chapter 10: Kconfig configuration files
 
-For configuration options (arch/xxx/Kconfig, and all the Kconfig files),
-somewhat different indentation is used.
+For all of the Kconfig* configuration files throughout the source tree,
+the indentation is somewhat different.  Lines under a "config" definition
+are indented with one tab, while help text is indented an additional two
+spaces.  Example:
 
-Help text is indented with 2 spaces.
-
-if CONFIG_EXPERIMENTAL
-	tristate CONFIG_BOOM
-	default n
+config AUDIT
+	bool "Auditing support"
+	depends on NET
 	help
-	  Apply nitroglycerine inside the keyboard (DANGEROUS)
-	bool CONFIG_CHEER
-	depends on CONFIG_BOOM
-	default y
-	help
-	  Output nice messages when you explode
-endif
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
 
-Generally, CONFIG_EXPERIMENTAL should surround all options not considered
-stable. All options that are known to trash data (experimental write-
-support for file-systems, for instance) should be denoted (DANGEROUS), other
-experimental options should be denoted (EXPERIMENTAL).
+Features that might still be considered unstable should be defined as
+dependent on "EXPERIMENTAL":
+
+config SLUB
+	depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
+	bool "SLUB (Unqueued Allocator)"
+	...
+
+while seriously dangerous features (such as write support for certain
+filesystems) should advertise this prominently in their prompt string:
+
+config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	...
+
+For full documentation on the configuration files, see the file
+Documentation/kbuild/kconfig-language.txt.
 
 
 		Chapter 11: Data structures
@@ -715,6 +738,33 @@
 defined that you shouldn't reproduce in your code.
 
 
+		Chapter 18:  Editor modelines and other cruft
+
+Some editors can interpret configuration information embedded in source files,
+indicated with special markers.  For example, emacs interprets lines marked
+like this:
+
+-*- mode: c -*-
+
+Or like this:
+
+/*
+Local Variables:
+compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+End:
+*/
+
+Vim interprets markers that look like this:
+
+/* vim:set sw=8 noet */
+
+Do not include any of these in source files.  People have their own personal
+editor configurations, and your source files should not override them.  This
+includes markers for indentation and mode configuration.  People may use their
+own custom mode, or may have some other magic method for making indentation
+work correctly.
+
+
 
 		Appendix I: References
 
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index 028614c..e07f253 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -664,109 +664,6 @@
 Well, not for some odd devices.  See the next section for information
 about that.
 
-	DAC Addressing for Address Space Hungry Devices
-
-There exists a class of devices which do not mesh well with the PCI
-DMA mapping API.  By definition these "mappings" are a finite
-resource.  The number of total available mappings per bus is platform
-specific, but there will always be a reasonable amount.
-
-What is "reasonable"?  Reasonable means that networking and block I/O
-devices need not worry about using too many mappings.
-
-As an example of a problematic device, consider compute cluster cards.
-They can potentially need to access gigabytes of memory at once via
-DMA.  Dynamic mappings are unsuitable for this kind of access pattern.
-
-To this end we've provided a small API by which a device driver
-may use DAC cycles to directly address all of physical memory.
-Not all platforms support this, but most do.  It is easy to determine
-whether the platform will work properly at probe time.
-
-First, understand that there may be a SEVERE performance penalty for
-using these interfaces on some platforms.  Therefore, you MUST only
-use these interfaces if it is absolutely required.  %99 of devices can
-use the normal APIs without any problems.
-
-Note that for streaming type mappings you must either use these
-interfaces, or the dynamic mapping interfaces above.  You may not mix
-usage of both for the same device.  Such an act is illegal and is
-guaranteed to put a banana in your tailpipe.
-
-However, consistent mappings may in fact be used in conjunction with
-these interfaces.  Remember that, as defined, consistent mappings are
-always going to be SAC addressable.
-
-The first thing your driver needs to do is query the PCI platform
-layer if it is capable of handling your devices DAC addressing
-capabilities:
-
-	int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
-
-You may not use the following interfaces if this routine fails.
-
-Next, DMA addresses using this API are kept track of using the
-dma64_addr_t type.  It is guaranteed to be big enough to hold any
-DAC address the platform layer will give to you from the following
-routines.  If you have consistent mappings as well, you still
-use plain dma_addr_t to keep track of those.
-
-All mappings obtained here will be direct.  The mappings are not
-translated, and this is the purpose of this dialect of the DMA API.
-
-All routines work with page/offset pairs.  This is the _ONLY_ way to 
-portably refer to any piece of memory.  If you have a cpu pointer
-(which may be validly DMA'd too) you may easily obtain the page
-and offset using something like this:
-
-	struct page *page = virt_to_page(ptr);
-	unsigned long offset = offset_in_page(ptr);
-
-Here are the interfaces:
-
-	dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-					 struct page *page,
-					 unsigned long offset,
-					 int direction);
-
-The DAC address for the tuple PAGE/OFFSET are returned.  The direction
-argument is the same as for pci_{map,unmap}_single().  The same rules
-for cpu/device access apply here as for the streaming mapping
-interfaces.  To reiterate:
-
-	The cpu may touch the buffer before pci_dac_page_to_dma.
-	The device may touch the buffer after pci_dac_page_to_dma
-	is made, but the cpu may NOT.
-
-When the DMA transfer is complete, invoke:
-
-	void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-					     dma64_addr_t dma_addr,
-					     size_t len, int direction);
-
-This must be done before the CPU looks at the buffer again.
-This interface behaves identically to pci_dma_sync_{single,sg}_for_cpu().
-
-And likewise, if you wish to let the device get back at the buffer after
-the cpu has read/written it, invoke:
-
-	void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-						dma64_addr_t dma_addr,
-						size_t len, int direction);
-
-before letting the device access the DMA area again.
-
-If you need to get back to the PAGE/OFFSET tuple from a dma64_addr_t
-the following interfaces are provided:
-
-	struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-					 dma64_addr_t dma_addr);
-	unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-					    dma64_addr_t dma_addr);
-
-This is possible with the DAC interfaces purely because they are
-not translated in any way.
-
 		Optimizing Unmap State Space Consumption
 
 On many platforms, pci_unmap_{single,page}() is simply a nop.
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index e7fc964..6996d97 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -52,7 +52,7 @@
 
 <toc></toc>
 
-<chapter><title>Introduction</title>
+<chapter id="intro"><title>Introduction</title>
 
 <para>This document presents a Linux-USB "Gadget"
 kernel mode
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 38f88b6..fd2ef4d 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -139,8 +139,10 @@
 !Elib/cmdline.c
      </sect1>
 
-     <sect1><title>CRC Functions</title>
+     <sect1 id="crc"><title>CRC Functions</title>
+!Elib/crc7.c
 !Elib/crc16.c
+!Elib/crc-itu-t.c
 !Elib/crc32.c
 !Elib/crc-ccitt.c
      </sect1>
@@ -643,4 +645,70 @@
 !Edrivers/spi/spi.c
   </chapter>
 
+  <chapter id="i2c">
+     <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
+
+     <para>
+	I<superscript>2</superscript>C (or without fancy typography, "I2C")
+	is an acronym for the "Inter-IC" bus, a simple bus protocol which is
+	widely used where low data rate communications suffice.
+	Since it's also a licensed trademark, some vendors use another
+	name (such as "Two-Wire Interface", TWI) for the same bus.
+	I2C only needs two signals (SCL for clock, SDA for data), conserving
+	board real estate and minimizing signal quality issues.
+	Most I2C devices use seven bit addresses, and bus speeds of up
+	to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
+	found wide use.
+	I2C is a multi-master bus; open drain signaling is used to
+	arbitrate between masters, as well as to handshake and to
+	synchronize clocks from slower clients.
+     </para>
+
+     <para>
+	The Linux I2C programming interfaces support only the master
+	side of bus interactions, not the slave side.
+	The programming interface is structured around two kinds of driver,
+	and two kinds of device.
+	An I2C "Adapter Driver" abstracts the controller hardware; it binds
+	to a physical device (perhaps a PCI device or platform_device) and
+	exposes a <structname>struct i2c_adapter</structname> representing
+	each I2C bus segment it manages.
+	On each I2C bus segment will be I2C devices represented by a
+	<structname>struct i2c_client</structname>.  Those devices will
+	be bound to a <structname>struct i2c_driver</structname>,
+	which should follow the standard Linux driver model.
+	(At this writing, a legacy model is more widely used.)
+	There are functions to perform various I2C protocol operations; at
+	this writing all such functions are usable only from task context.
+     </para>
+
+     <para>
+	The System Management Bus (SMBus) is a sibling protocol.  Most SMBus
+	systems are also I2C conformant.  The electrical constraints are
+	tighter for SMBus, and it standardizes particular protocol messages
+	and idioms.  Controllers that support I2C can also support most
+	SMBus operations, but SMBus controllers don't support all the protocol
+	options that an I2C controller will.
+	There are functions to perform various SMBus protocol operations,
+	either using I2C primitives or by issuing SMBus commands to
+	i2c_adapter devices which don't support those I2C operations.
+     </para>
+
+!Iinclude/linux/i2c.h
+!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
+!Edrivers/i2c/i2c-core.c
+  </chapter>
+
+  <chapter id="splice">
+      <title>splice API</title>
+  <para>)
+	splice is a method for moving blocks of data around inside the
+	kernel, without continually transferring it between the kernel
+	and user space.
+  </para>
+!Iinclude/linux/splice.h
+!Ffs/splice.c
+  </chapter>
+
+
 </book>
diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
index 45cad23..2de84dc 100644
--- a/Documentation/DocBook/procfs-guide.tmpl
+++ b/Documentation/DocBook/procfs-guide.tmpl
@@ -352,49 +352,93 @@
       <funcsynopsis>
 	<funcprototype>
 	  <funcdef>int <function>read_func</function></funcdef>
-	  <paramdef>char* <parameter>page</parameter></paramdef>
+	  <paramdef>char* <parameter>buffer</parameter></paramdef>
 	  <paramdef>char** <parameter>start</parameter></paramdef>
 	  <paramdef>off_t <parameter>off</parameter></paramdef>
 	  <paramdef>int <parameter>count</parameter></paramdef>
-	  <paramdef>int* <parameter>eof</parameter></paramdef>
+	  <paramdef>int* <parameter>peof</parameter></paramdef>
 	  <paramdef>void* <parameter>data</parameter></paramdef>
 	</funcprototype>
       </funcsynopsis>
 
       <para>
         The read function should write its information into the
-        <parameter>page</parameter>. For proper use, the function
-        should start writing at an offset of
-        <parameter>off</parameter> in <parameter>page</parameter> and
-        write at most <parameter>count</parameter> bytes, but because
-        most read functions are quite simple and only return a small
-        amount of information, these two parameters are usually
-        ignored (it breaks pagers like <literal>more</literal> and
-        <literal>less</literal>, but <literal>cat</literal> still
-        works).
+        <parameter>buffer</parameter>, which will be exactly
+        <literal>PAGE_SIZE</literal> bytes long.
       </para>
 
       <para>
-        If the <parameter>off</parameter> and
-        <parameter>count</parameter> parameters are properly used,
-        <parameter>eof</parameter> should be used to signal that the
+        The parameter
+        <parameter>peof</parameter> should be used to signal that the
         end of the file has been reached by writing
         <literal>1</literal> to the memory location
-        <parameter>eof</parameter> points to.
+        <parameter>peof</parameter> points to.
       </para>
 
       <para>
-        The parameter <parameter>start</parameter> doesn't seem to be
-        used anywhere in the kernel. The <parameter>data</parameter>
+        The <parameter>data</parameter>
         parameter can be used to create a single call back function for
         several files, see <xref linkend="usingdata"/>.
       </para>
 
       <para>
-        The <function>read_func</function> function must return the
-        number of bytes written into the <parameter>page</parameter>.
+        The rest of the parameters and the return value are described
+	by a comment in <filename>fs/proc/generic.c</filename> as follows:
       </para>
 
+      <blockquote>
+        <para>
+	You have three ways to return data:
+       	</para>
+        <orderedlist>
+          <listitem>
+            <para>
+	      Leave <literal>*start = NULL</literal>.  (This is the default.)
+	      Put the data of the requested offset at that
+	      offset within the buffer.  Return the number (<literal>n</literal>)
+	      of bytes there are from the beginning of the
+	      buffer up to the last byte of data.  If the
+	      number of supplied bytes (<literal>= n - offset</literal>) is
+	      greater than zero and you didn't signal eof
+	      and the reader is prepared to take more data
+	      you will be called again with the requested
+	      offset advanced by the number of bytes
+	      absorbed.  This interface is useful for files
+	      no larger than the buffer.
+	    </para>
+	  </listitem>
+	  <listitem>
+            <para>
+	      Set <literal>*start</literal> to an unsigned long value less than
+	      the buffer address but greater than zero.
+	      Put the data of the requested offset at the
+	      beginning of the buffer.  Return the number of
+	      bytes of data placed there.  If this number is
+	      greater than zero and you didn't signal eof
+	      and the reader is prepared to take more data
+	      you will be called again with the requested
+	      offset advanced by <literal>*start</literal>.  This interface is
+	      useful when you have a large file consisting
+	      of a series of blocks which you want to count
+	      and return as wholes.
+	      (Hack by Paul.Russell@rustcorp.com.au)
+	    </para>
+	  </listitem>
+	  <listitem>
+            <para>
+	      Set <literal>*start</literal> to an address within the buffer.
+	      Put the data of the requested offset at <literal>*start</literal>.
+	      Return the number of bytes of data placed there.
+	      If this number is greater than zero and you
+	      didn't signal eof and the reader is prepared to
+	      take more data you will be called again with the
+	      requested offset advanced by the number of bytes
+	      absorbed.
+	    </para>
+	  </listitem>
+	</orderedlist>
+      </blockquote>
+
       <para>
         <xref linkend="example"/> shows how to use a read call back
         function.
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index a2ebd65..af29360 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -185,7 +185,7 @@
 
     </chapter>
 
-<chapter><title>USB-Standard Types</title>
+<chapter id="types"><title>USB-Standard Types</title>
 
     <para>In <filename>&lt;linux/usb/ch9.h&gt;</filename> you will find
     the USB data types defined in chapter 9 of the USB specification.
@@ -197,7 +197,7 @@
 
     </chapter>
 
-<chapter><title>Host-Side Data Types and Macros</title>
+<chapter id="hostside"><title>Host-Side Data Types and Macros</title>
 
     <para>The host side API exposes several layers to drivers, some of
     which are more necessary than others.
@@ -211,7 +211,7 @@
 
     </chapter>
 
-    <chapter><title>USB Core APIs</title>
+    <chapter id="usbcore"><title>USB Core APIs</title>
 
     <para>There are two basic I/O models in the USB API.
     The most elemental one is asynchronous:  drivers submit requests
@@ -248,7 +248,7 @@
 !Edrivers/usb/core/hub.c
     </chapter>
 
-    <chapter><title>Host Controller APIs</title>
+    <chapter id="hcd"><title>Host Controller APIs</title>
 
     <para>These APIs are only for use by host controller drivers,
     most of which implement standard register interfaces such as
@@ -285,7 +285,7 @@
 !Idrivers/usb/core/buffer.c
     </chapter>
 
-    <chapter>
+    <chapter id="usbfs">
 	<title>The USB Filesystem (usbfs)</title>
 
 	<para>This chapter presents the Linux <emphasis>usbfs</emphasis>.
@@ -317,7 +317,7 @@
 	not it has a kernel driver.
 	</para>
 
-	<sect1>
+	<sect1 id="usbfs-files">
 	    <title>What files are in "usbfs"?</title>
 
 	    <para>Conventionally mounted at
@@ -356,7 +356,7 @@
 
 	</sect1>
 
-	<sect1>
+	<sect1 id="usbfs-fstab">
 	    <title>Mounting and Access Control</title>
 
 	    <para>There are a number of mount options for usbfs, which will
@@ -439,7 +439,7 @@
 
 	</sect1>
 
-	<sect1>
+	<sect1 id="usbfs-devices">
 	    <title>/proc/bus/usb/devices</title>
 
 	    <para>This file is handy for status viewing tools in user
@@ -473,7 +473,7 @@
 	    </para>
 	</sect1>
 
-	<sect1>
+	<sect1 id="usbfs-bbbddd">
 	    <title>/proc/bus/usb/BBB/DDD</title>
 
 	    <para>Use these files in one of these basic ways:
@@ -510,7 +510,7 @@
 	    </sect1>
 
 
-	<sect1>
+	<sect1 id="usbfs-lifecycle">
 	    <title>Life Cycle of User Mode Drivers</title>
 
 	    <para>Such a driver first needs to find a device file
@@ -565,7 +565,7 @@
 
 	    </sect1>
 
-	<sect1><title>The ioctl() Requests</title>
+	<sect1 id="usbfs-ioctl"><title>The ioctl() Requests</title>
 
 	    <para>To use these ioctls, you need to include the following
 	    headers in your userspace program:
@@ -604,7 +604,7 @@
 	    </para>
 
 
-	    <sect2>
+	    <sect2 id="usbfs-mgmt">
 		<title>Management/Status Requests</title>
 
 		<para>A number of usbfs requests don't deal very directly
@@ -736,7 +736,7 @@
 
 		</sect2>
 
-	    <sect2>
+	    <sect2 id="usbfs-sync">
 		<title>Synchronous I/O Support</title>
 
 		<para>Synchronous requests involve the kernel blocking
@@ -865,7 +865,7 @@
 		</variablelist>
 	    </sect2>
 
-	    <sect2>
+	    <sect2 id="usbfs-async">
 		<title>Asynchronous I/O Support</title>
 
 		<para>As mentioned above, there are situations where it may be
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 48123db..98e2701 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -322,39 +322,34 @@
 Here is a list of some of the different kernel trees available:
   git trees:
     - Kbuild development tree, Sam Ravnborg <sam@ravnborg.org>
-	kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
+	git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
 
     - ACPI development tree, Len Brown <len.brown@intel.com>
-	kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
+	git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
 
     - Block development tree, Jens Axboe <axboe@suse.de>
-	kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
+	git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
 
     - DRM development tree, Dave Airlie <airlied@linux.ie>
-	kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+	git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
 
     - ia64 development tree, Tony Luck <tony.luck@intel.com>
-	kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
-
-    - ieee1394 development tree, Jody McIntyre <scjody@modernduck.com>
-	kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
+	git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
 
     - infiniband, Roland Dreier <rolandd@cisco.com>
-	kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
+	git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
 
     - libata, Jeff Garzik <jgarzik@pobox.com>
-	kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
+	git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
 
     - network drivers, Jeff Garzik <jgarzik@pobox.com>
-	kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
+	git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
 
     - pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
-	kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
+	git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
 
     - SCSI, James Bottomley <James.Bottomley@SteelEye.com>
-	kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
-
-  Other git kernel trees can be found listed at http://kernel.org/git
+	git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
 
   quilt trees:
     - USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
@@ -362,6 +357,9 @@
     - x86-64, partly i386, Andi Kleen <ak@suse.de>
         ftp.firstfloor.org:/pub/ak/x86_64/quilt/
 
+  Other kernel trees can be found listed at http://git.kernel.org/ and in
+  the MAINTAINERS file.
+
 Bug Reporting
 -------------
 
@@ -396,26 +394,6 @@
 
 
 
-Managing bug reports
---------------------
-
-One of the best ways to put into practice your hacking skills is by fixing
-bugs reported by other people. Not only you will help to make the kernel
-more stable, you'll learn to fix real world problems and you will improve
-your skills, and other developers will be aware of your presence. Fixing
-bugs is one of the best ways to get merits among other developers, because
-not many people like wasting time fixing other people's bugs.
-
-To work in the already reported bug reports, go to http://bugzilla.kernel.org.
-If you want to be advised of the future bug reports, you can subscribe to the
-bugme-new mailing list (only new bug reports are mailed here) or to the
-bugme-janitor mailing list (every change in the bugzilla is mailed here)
-
-	http://lists.osdl.org/mailman/listinfo/bugme-new
-	http://lists.osdl.org/mailman/listinfo/bugme-janitors
-
-
-
 Mailing lists
 -------------
 
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index f4dffad..42b01bc 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -222,7 +222,15 @@
 	deadlock as soon as the RCU callback happens to interrupt that
 	acquisition's critical section.
 
-13.	SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu())
+13.	RCU callbacks can be and are executed in parallel.  In many cases,
+	the callback code simply wrappers around kfree(), so that this
+	is not an issue (or, more accurately, to the extent that it is
+	an issue, the memory-allocator locking handles it).  However,
+	if the callbacks do manipulate a shared data structure, they
+	must use whatever locking or other synchronization is required
+	to safely access and/or modify that data structure.
+
+14.	SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu())
 	may only be invoked from process context.  Unlike other forms of
 	RCU, it -is- permissible to block in an SRCU read-side critical
 	section (demarked by srcu_read_lock() and srcu_read_unlock()),
diff --git a/Documentation/SM501.txt b/Documentation/SM501.txt
new file mode 100644
index 0000000..3a1bd95
--- /dev/null
+++ b/Documentation/SM501.txt
@@ -0,0 +1,66 @@
+			SM501 Driver
+			============
+
+Copyright 2006, 2007 Simtec Electronics
+
+Core
+----
+
+The core driver in drivers/mfd provides common services for the
+drivers which manage the specific hardware blocks. These services
+include locking for common registers, clock control and resource
+management.
+
+The core registers drivers for both PCI and generic bus based
+chips via the platform device and driver system.
+
+On detection of a device, the core initialises the chip (which may
+be specified by the platform data) and then exports the selected
+peripheral set as platform devices for the specific drivers.
+
+The core re-uses the platform device system as the platform device
+system provides enough features to support the drivers without the
+need to create a new bus-type and the associated code to go with it.
+
+
+Resources
+---------
+
+Each peripheral has a view of the device which is implicitly narrowed to
+the specific set of resources that peripheral requires in order to
+function correctly.
+
+The centralised memory allocation allows the driver to ensure that the
+maximum possible resource allocation can be made to the video subsystem
+as this is by-far the most resource-sensitive of the on-chip functions.
+
+The primary issue with memory allocation is that of moving the video
+buffers once a display mode is chosen. Indeed when a video mode change
+occurs the memory footprint of the video subsystem changes.
+
+Since video memory is difficult to move without changing the display
+(unless sufficient contiguous memory can be provided for the old and new
+modes simultaneously) the video driver fully utilises the memory area
+given to it by aligning fb0 to the start of the area and fb1 to the end
+of it. Any memory left over in the middle is used for the acceleration
+functions, which are transient and thus their location is less critical
+as it can be moved.
+
+
+Configuration
+-------------
+
+The platform device driver uses a set of platform data to pass
+configurations through to the core and the subsidiary drivers
+so that there can be support for more than one system carrying
+an SM501 built into a single kernel image.
+
+The PCI driver assumes that the PCI card behaves as per the Silicon
+Motion reference design.
+
+There is an errata (AB-5) affecting the selection of the
+of the M1XCLK and M1CLK frequencies. These two clocks
+must be sourced from the same PLL, although they can then
+be divided down individually. If this is not set, then SM501 may
+lock and hang the whole system. The driver will refuse to
+attach if the PLL selection is different.
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 3af3e65..19e7f65 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -1,4 +1,4 @@
-Linux Kernel patch sumbittal checklist
+Linux Kernel patch submission checklist
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Here are some basic things that developers should do if they want to see their
@@ -9,7 +9,6 @@
 kernel patches.
 
 
-
 1: Builds cleanly with applicable or modified CONFIG options =y, =m, and
    =n.  No gcc warnings/errors, no linker warnings/errors.
 
@@ -84,3 +83,9 @@
 24: Avoid whitespace damage such as indenting with spaces or whitespace
     at the end of lines.  You can test this by feeding the patch to
     "git apply --check --whitespace=error-all"
+
+25: Check your patch for general style as detailed in
+    Documentation/CodingStyle.  Check for trivial violations with the
+    patch style checker prior to submission (scripts/checkpatch.pl).
+    You should be able to justify all violations that remain in
+    your patch.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index a417b25..3f9a791 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -118,7 +118,20 @@
 
 
 
-4) Select e-mail destination.
+4) Style check your changes.
+
+Check your patch for basic style violations, details of which can be
+found in Documentation/CodingStyle.  Failure to do so simply wastes
+the reviewers time and will get your patch rejected, probabally
+without even being read.
+
+At a minimum you should check your patches with the patch style
+checker prior to submission (scripts/patchcheck.pl).  You should
+be able to justify all violations that remain in your patch.
+
+
+
+5) Select e-mail destination.
 
 Look through the MAINTAINERS file and the source code, and determine
 if your change applies to a specific subsystem of the kernel, with
@@ -146,7 +159,7 @@
 
 
 
-5) Select your CC (e-mail carbon copy) list.
+6) Select your CC (e-mail carbon copy) list.
 
 Unless you have a reason NOT to do so, CC linux-kernel@vger.kernel.org.
 
@@ -187,8 +200,7 @@
 
 
 
-
-6) No MIME, no links, no compression, no attachments.  Just plain text.
+7) No MIME, no links, no compression, no attachments.  Just plain text.
 
 Linus and other kernel developers need to be able to read and comment
 on the changes you are submitting.  It is important for a kernel
@@ -223,9 +235,9 @@
 
 
 
-7) E-mail size.
+8) E-mail size.
 
-When sending patches to Linus, always follow step #6.
+When sending patches to Linus, always follow step #7.
 
 Large changes are not appropriate for mailing lists, and some
 maintainers.  If your patch, uncompressed, exceeds 40 kB in size,
@@ -234,7 +246,7 @@
 
 
 
-8) Name your kernel version.
+9) Name your kernel version.
 
 It is important to note, either in the subject line or in the patch
 description, the kernel version to which this patch applies.
@@ -244,7 +256,7 @@
 
 
 
-9) Don't get discouraged.  Re-submit.
+10) Don't get discouraged.  Re-submit.
 
 After you have submitted your change, be patient and wait.  If Linus
 likes your change and applies it, it will appear in the next version
@@ -270,7 +282,7 @@
 
 
 
-10) Include PATCH in the subject
+11) Include PATCH in the subject
 
 Due to high e-mail traffic to Linus, and to linux-kernel, it is common
 convention to prefix your subject line with [PATCH].  This lets Linus
@@ -279,7 +291,7 @@
 
 
 
-11) Sign your work
+12) Sign your work
 
 To improve tracking of who did what, especially with patches that can
 percolate to their final resting place in the kernel through several
@@ -328,7 +340,32 @@
 point out some special detail about the sign-off. 
 
 
-12) The canonical patch format
+13) When to use Acked-by:
+
+The Signed-off-by: tag indicates that the signer was involved in the
+development of the patch, or that he/she was in the patch's delivery path.
+
+If a person was not directly involved in the preparation or handling of a
+patch but wishes to signify and record their approval of it then they can
+arrange to have an Acked-by: line added to the patch's changelog.
+
+Acked-by: is often used by the maintainer of the affected code when that
+maintainer neither contributed to nor forwarded the patch.
+
+Acked-by: is not as formal as Signed-off-by:.  It is a record that the acker
+has at least reviewed the patch and has indicated acceptance.  Hence patch
+mergers will sometimes manually convert an acker's "yep, looks good to me"
+into an Acked-by:.
+
+Acked-by: does not necessarily indicate acknowledgement of the entire patch.
+For example, if a patch affects multiple subsystems and has an Acked-by: from
+one subsystem maintainer then this usually indicates acknowledgement of just
+the part which affects that maintainer's code.  Judgement should be used here.
+ When in doubt people should refer to the original discussion in the mailing
+list archives.
+
+
+14) The canonical patch format
 
 The canonical patch subject line is:
 
@@ -427,6 +464,26 @@
 Nuff said.  If your code deviates too much from this, it is likely
 to be rejected without further review, and without comment.
 
+Once significant exception is when moving code from one file to
+another in this case you should not modify the moved code at all in
+the same patch which moves it.  This clearly delineates the act of
+moving the code and your changes.  This greatly aids review of the
+actual differences and allows tools to better track the history of
+the code itself.
+
+Check your patches with the patch style checker prior to submission
+(scripts/checkpatch.pl).  The style checker should be viewed as
+a guide not as the final word.  If your code looks better with
+a violation then its probably best left alone.
+
+The checker reports at three levels:
+ - ERROR: things that are very likely to be wrong
+ - WARNING: things requiring careful review
+ - CHECK: things requiring thought
+
+You should be able to justify all violations that remain in your
+patch.
+
 
 
 2) #ifdefs are ugly
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index 71acc28..24c5aad 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -49,6 +49,7 @@
 int dbg;
 int print_delays;
 int print_io_accounting;
+int print_task_context_switch_counts;
 __u64 stime, utime;
 
 #define PRINTF(fmt, arg...) {			\
@@ -195,7 +196,7 @@
 	       "IO    %15s%15s\n"
 	       "      %15llu%15llu\n"
 	       "MEM   %15s%15s\n"
-	       "      %15llu%15llu\n\n",
+	       "      %15llu%15llu\n"
 	       "count", "real total", "virtual total", "delay total",
 	       t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
 	       t->cpu_delay_total,
@@ -204,6 +205,14 @@
 	       "count", "delay total", t->swapin_count, t->swapin_delay_total);
 }
 
+void task_context_switch_counts(struct taskstats *t)
+{
+	printf("\n\nTask   %15s%15s\n"
+	       "       %15lu%15lu\n",
+	       "voluntary", "nonvoluntary",
+	       t->nvcsw, t->nivcsw);
+}
+
 void print_ioacct(struct taskstats *t)
 {
 	printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
@@ -235,7 +244,7 @@
 	struct msgtemplate msg;
 
 	while (1) {
-		c = getopt(argc, argv, "diw:r:m:t:p:vl");
+		c = getopt(argc, argv, "qdiw:r:m:t:p:vl");
 		if (c < 0)
 			break;
 
@@ -248,6 +257,10 @@
 			printf("printing IO accounting\n");
 			print_io_accounting = 1;
 			break;
+		case 'q':
+			printf("printing task/process context switch rates\n");
+			print_task_context_switch_counts = 1;
+			break;
 		case 'w':
 			logfile = strdup(optarg);
 			printf("write to file %s\n", logfile);
@@ -389,6 +402,8 @@
 							print_delayacct((struct taskstats *) NLA_DATA(na));
 						if (print_io_accounting)
 							print_ioacct((struct taskstats *) NLA_DATA(na));
+						if (print_task_context_switch_counts)
+							task_context_switch_counts((struct taskstats *) NLA_DATA(na));
 						if (fd) {
 							if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
 								err(1,"write error\n");
diff --git a/Documentation/accounting/taskstats-struct.txt b/Documentation/accounting/taskstats-struct.txt
index 661c797..8aa7529 100644
--- a/Documentation/accounting/taskstats-struct.txt
+++ b/Documentation/accounting/taskstats-struct.txt
@@ -22,6 +22,8 @@
     /* Extended accounting fields end */
     Their values are collected if CONFIG_TASK_XACCT is set.
 
+4) Per-task and per-thread context switch count statistics
+
 Future extension should add fields to the end of the taskstats struct, and
 should not change the relative position of each field within the struct.
 
@@ -158,4 +160,8 @@
 
 	/* Extended accounting fields end */
 
+4) Per-task and per-thread statistics
+	__u64	nvcsw;			/* Context voluntary switch counter */
+	__u64	nivcsw;			/* Context involuntary switch counter */
+
 }
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt
index 2a63d56..05851e9 100644
--- a/Documentation/atomic_ops.txt
+++ b/Documentation/atomic_ops.txt
@@ -149,7 +149,7 @@
 	void smp_mb__before_atomic_dec(void);
 	void smp_mb__after_atomic_dec(void);
 	void smp_mb__before_atomic_inc(void);
-	void smp_mb__after_atomic_dec(void);
+	void smp_mb__after_atomic_inc(void);
 
 For example, smp_mb__before_atomic_dec() can be used like so:
 
diff --git a/Documentation/blackfin/kgdb.txt b/Documentation/blackfin/kgdb.txt
new file mode 100644
index 0000000..84f6a484
--- /dev/null
+++ b/Documentation/blackfin/kgdb.txt
@@ -0,0 +1,155 @@
+			A Simple Guide to Configure KGDB
+
+			Sonic Zhang <sonic.zhang@analog.com>
+				Aug. 24th 2006
+
+
+This KGDB patch enables the kernel developer to do source level debugging on
+the kernel for the Blackfin architecture.  The debugging works over either the
+ethernet interface or one of the uarts.  Both software breakpoints and
+hardware breakpoints are supported in this version.
+http://docs.blackfin.uclinux.org/doku.php?id=kgdb
+
+
+2 known issues:
+1. This bug:
+       http://blackfin.uclinux.org/tracker/index.php?func=detail&aid=544&group_id=18&atid=145
+   The GDB client for Blackfin uClinux causes incorrect values of local
+   variables to be displayed when the user breaks the running of kernel in GDB.
+2. Because of a hardware bug in Blackfin 533 v1.0.3:
+       05000067 - Watchpoints (Hardware Breakpoints) are not supported
+   Hardware breakpoints cannot be set properly.
+
+
+Debug over Ethernet:
+ 
+1. Compile and install the cross platform version of gdb for blackfin, which
+   can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
+   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+   With this selected, option "Full Symbolic/Source Debugging support" and 
+   "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over (Ethernet)".  Add "kgdboe=@target-IP/,@host-IP/" to
+   the option "Compiled-in Kernel Boot Parameter" under "Kernel hacking".
+
+4. Connect minicom to the serial port and boot the kernel image.
+
+5. Configure the IP "/> ifconfig eth0 target-IP"
+
+6. Start GDB client "bfin-elf-gdb vmlinux".
+
+7. Connect to the target "(gdb) target remote udp:target-IP:6443".
+
+8. Set software breakpoint "(gdb) break sys_open".
+
+9. Continue "(gdb) c".
+
+10. Run ls in the target console "/> ls".
+
+11. Breakpoint hits. "Breakpoint 1: sys_open(..."
+
+12. Display local variables and function paramters.
+    (*) This operation gives wrong results, see known issue 1.
+
+13. Single stepping "(gdb) si".
+
+14. Remove breakpoint 1. "(gdb) del 1"
+
+15. Set hardware breakpoint "(gdb) hbreak sys_open".
+
+16. Continue "(gdb) c".
+
+17. Run ls in the target console "/> ls".
+
+18. Hardware breakpoint hits. "Breakpoint 1: sys_open(...".
+    (*) This hardware breakpoint will not be hit, see known issue 2.
+
+19. Continue "(gdb) c".
+
+20. Interrupt the target in GDB "Ctrl+C".
+
+21. Detach from the target "(gdb) detach".
+
+22. Exit GDB "(gdb) quit".
+
+
+Debug over the UART:
+
+1. Compile and install the cross platform version of gdb for blackfin, which
+   can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
+   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+   With this selected, option "Full Symbolic/Source Debugging support" and 
+   "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over (UART)".  Set "KGDB: UART port number" to be
+   a different one from the console.  Don't forget to change the mode of
+   blackfin serial driver to PIO.  Otherwise kgdb works incorrectly on UART.
+ 
+4. If you want connect to kgdb when the kernel boots, enable
+   "KGDB: Wait for gdb connection early" 
+
+5. Compile kernel.
+
+6. Connect minicom to the serial port of the console and boot the kernel image.
+
+7. Start GDB client "bfin-elf-gdb vmlinux".
+
+8. Set the baud rate in GDB "(gdb) set remotebaud 57600".
+
+9. Connect to the target on the second serial port "(gdb) target remote /dev/ttyS1".
+
+10. Set software breakpoint "(gdb) break sys_open".
+
+11. Continue "(gdb) c". 
+
+12. Run ls in the target console "/> ls". 
+
+13. A breakpoint is hit. "Breakpoint 1: sys_open(..."
+
+14. All other operations are the same as that in KGDB over Ethernet. 
+
+
+Debug over the same UART as console:
+
+1. Compile and install the cross platform version of gdb for blackfin, which
+   can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
+   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+   With this selected, option "Full Symbolic/Source Debugging support" and 
+   "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over UART".  Set "KGDB: UART port number" to console.
+   Don't forget to change the mode of blackfin serial driver to PIO.
+   Otherwise kgdb works incorrectly on UART.
+ 
+4. If you want connect to kgdb when the kernel boots, enable
+   "KGDB: Wait for gdb connection early" 
+
+5. Connect minicom to the serial port and boot the kernel image. 
+
+6. (Optional) Ask target to wait for gdb connection by entering Ctrl+A. In minicom, you should enter Ctrl+A+A.
+
+7. Start GDB client "bfin-elf-gdb vmlinux".
+
+8. Set the baud rate in GDB "(gdb) set remotebaud 57600".
+
+9. Connect to the target "(gdb) target remote /dev/ttyS0".
+
+10. Set software breakpoint "(gdb) break sys_open".
+
+11. Continue "(gdb) c". Then enter Ctrl+C twice to stop GDB connection.
+
+12. Run ls in the target console "/> ls". Dummy string can be seen on the console.
+
+13. Then connect the gdb to target again. "(gdb) target remote /dev/ttyS0".
+    Now you will find a breakpoint is hit. "Breakpoint 1: sys_open(..."
+
+14. All other operations are the same as that in KGDB over Ethernet.  The only
+    difference is that after continue command in GDB, please stop GDB
+    connection by 2 "Ctrl+C"s and connect again after breakpoints are hit or
+    Ctrl+A is entered.
diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt
index a272c3d..7d279f2 100644
--- a/Documentation/block/barrier.txt
+++ b/Documentation/block/barrier.txt
@@ -82,23 +82,12 @@
 typedef void (prepare_flush_fn)(request_queue_t *q, struct request *rq);
 
 int blk_queue_ordered(request_queue_t *q, unsigned ordered,
-		      prepare_flush_fn *prepare_flush_fn,
-		      unsigned gfp_mask);
-
-int blk_queue_ordered_locked(request_queue_t *q, unsigned ordered,
-			     prepare_flush_fn *prepare_flush_fn,
-			     unsigned gfp_mask);
-
-The only difference between the two functions is whether or not the
-caller is holding q->queue_lock on entry.  The latter expects the
-caller is holding the lock.
+		      prepare_flush_fn *prepare_flush_fn);
 
 @q			: the queue in question
 @ordered		: the ordered mode the driver/device supports
 @prepare_flush_fn	: this function should prepare @rq such that it
 			  flushes cache to physical medium when executed
-@gfp_mask		: gfp_mask used when allocating data structures
-			  for ordered processing
 
 For example, SCSI disk driver's prepare_flush_fn looks like the
 following.
@@ -106,9 +95,10 @@
 static void sd_prepare_flush(request_queue_t *q, struct request *rq)
 {
 	memset(rq->cmd, 0, sizeof(rq->cmd));
-	rq->flags |= REQ_BLOCK_PC;
+	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->timeout = SD_TIMEOUT;
 	rq->cmd[0] = SYNCHRONIZE_CACHE;
+	rq->cmd_len = 10;
 }
 
 The following seven ordered modes are supported.  The following table
diff --git a/Documentation/block/capability.txt b/Documentation/block/capability.txt
new file mode 100644
index 0000000..2f17294
--- /dev/null
+++ b/Documentation/block/capability.txt
@@ -0,0 +1,15 @@
+Generic Block Device Capability
+===============================================================================
+This file documents the sysfs file block/<disk>/capability
+
+capability is a hex word indicating which capabilities a specific disk
+supports.  For more information on bits not listed here, see
+include/linux/genhd.h
+
+Capability				Value
+-------------------------------------------------------------------------------
+GENHD_FL_MEDIA_CHANGE_NOTIFY		4
+	When this bit is set, the disk supports Asynchronous Notification
+	of media change events.  These events will be broadcast to user
+	space via kernel uevent.
+
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index debf681..866b761 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -253,7 +253,7 @@
 
 	The first of these two routines is invoked after map_vm_area()
 	has installed the page table entries.  The second is invoked
-	before unmap_vm_area() deletes the page table entries.
+	before unmap_kernel_range() deletes the page table entries.
 
 There exists another whole class of cpu cache issues which currently
 require a whole different set of interfaces to handle properly.
diff --git a/Documentation/cdrom/00-INDEX b/Documentation/cdrom/00-INDEX
index 916dafe..433edf2 100644
--- a/Documentation/cdrom/00-INDEX
+++ b/Documentation/cdrom/00-INDEX
@@ -2,32 +2,10 @@
 	- this file (info on CD-ROMs and Linux)
 Makefile
 	- only used to generate TeX output from the documentation.
-aztcd
-	- info on Aztech/Orchid/Okano/Wearnes/Conrad/CyCDROM driver.
 cdrom-standard.tex
 	- LaTeX document on standardizing the CD-ROM programming interface.
-cdu31a
-	- info on the Sony CDU31A/CDU33A CD-ROM driver.
-cm206
-	- info on the Philips/LMS cm206/cm260 CD-ROM driver.
-gscd
-	- info on the Goldstar R420 CD-ROM driver.
 ide-cd
 	- info on setting up and using ATAPI (aka IDE) CD-ROMs.
-isp16
-	- info on the CD-ROM interface on ISP16, MAD16 or Mozart sound card.
-mcd
-	- info on limitations of standard Mitsumi CD-ROM driver.
-mcdx
-	- info on improved Mitsumi CD-ROM driver.
-optcd
-	- info on the Optics Storage 8000 AT CD-ROM driver
 packet-writing.txt
 	- Info on the CDRW packet writing module
-sbpcd
-	- info on the SoundBlaster/Panasonic CD-ROM interface driver.
-sjcd
-	- info on the SANYO CDR-H94A CD-ROM interface driver.
-sonycd535
-	- info on the Sony CDU-535 (and 531) CD-ROM driver.
 
diff --git a/Documentation/cdrom/aztcd b/Documentation/cdrom/aztcd
deleted file mode 100644
index 6bf0290..0000000
--- a/Documentation/cdrom/aztcd
+++ /dev/null
@@ -1,822 +0,0 @@
-$Id: README.aztcd,v 2.60 1997/11/29 09:51:25 root Exp root $
-          Readme-File Documentation/cdrom/aztcd
-           			for 
-	     AZTECH CD-ROM CDA268-01A, ORCHID CD-3110,
-      OKANO/WEARNES CDD110, CONRAD TXC, CyCDROM CR520, CR540
-                           CD-ROM Drives 
-                       Version 2.6 and newer
-                   (for other drives see 6.-8.)
-
-NOTE: THIS DRIVER WILL WORK WITH THE CD-ROM DRIVES LISTED, WHICH HAVE
-      A PROPRIETARY INTERFACE (implemented on a sound card or on an
-      ISA-AT-bus card). 
-      IT WILL DEFINITELY NOT WORK WITH CD-ROM DRIVES WITH *IDE*-INTERFACE,
-      such as the Aztech CDA269-031SE !!! (The only known exceptions are
-      'faked' IDE drives like the CyCDROM CR520ie which work with aztcd
-      under certain conditions, see 7.). IF YOU'RE USING A CD-ROM DRIVE
-      WITH IDE-INTERFACE, SOMETIMES ALSO CALLED ATAPI-COMPATIBLE, PLEASE 
-      USE THE ide-cd.c DRIVER, WRITTEN BY MARK LORD AND SCOTT SNYDER !
-      THE STANDARD-KERNEL 1.2.x NOW ALSO SUPPORTS IDE-CDROM-DRIVES, SEE THE
-      HARDDISK (!) SECTION OF make config, WHEN COMPILING A NEW KERNEL!!!
-----------------------------------------------------------------------------
-
-Contents of this file:
-                         1.  NOTE
-                         2.  INSTALLATION
-                         3.  CONFIGURING YOUR KERNEL
-                         4.  RECOMPILING YOUR KERNEL
-                         4.1   AZTCD AS A RUN-TIME LOADABLE MODULE
-                         4.2   CDROM CONNECTED TO A SOUNDCARD
-                         5.  KNOWN PROBLEMS, FUTURE DEVELOPMENTS
-			 5.1   MULTISESSION SUPPORT
-			 5.2   STATUS RECOGNITION
-			 5.3   DOSEMU's CDROM SUPPORT
-                         6.  BUG REPORTS
-                         7.  OTHER DRIVES
-                         8.  IF YOU DON'T SUCCEED ... DEBUGGING  
-                         9.  TECHNICAL HISTORY OF THE DRIVER
-                        10.  ACKNOWLEDGMENTS
-                        11.  PROGRAMMING ADD ONS: CDPLAY.C
-                        APPENDIX: Source code of cdplay.c
-----------------------------------------------------------------------------
-
-1. NOTE 
-This software has been successfully in alpha and beta test and is part of
-the standard kernel since kernel 1.1.8x since December 1994. It works with
-AZTECH CDA268-01A, ORCHID CDS-3110, ORCHID/WEARNES CDD110 and CONRAD TXC 
-(Nr.99 31 23 -series 04) and has proven to be stable with kernel 
-versions 1.0.9 and newer. But with any software there still may be bugs in it. 
-So if you encounter problems, you are invited to help us improve this software. 
-Please send me a detailed bug report (see chapter BUG REPORTS). You are also 
-invited in helping us to increase the number of drives, which are supported.
-
-Please read the README-files carefully and always keep a backup copy of your 
-old kernel, in order to reboot if something goes wrong!
-
-2. INSTALLATION
-The driver consists of a header file 'aztcd.h', which normally should reside 
-in /usr/src/linux/drivers/cdrom and the source code 'aztcd.c', which normally 
-resides in the same place. It uses /dev/aztcd (/dev/aztcd0 in some distri-
-butions), which must be a valid block device with major number 29 and reside 
-in directory /dev. To mount a CD-ROM, your kernel needs to have the ISO9660-
-filesystem support included.
-
-PLEASE NOTE: aztcd.c has been developed in parallel to the linux kernel,
-which had and is having many major and minor changes which are not backward
-compatible. Quite definitely aztcd.c version 1.80 and newer will NOT work
-in kernels older than 1.3.33. So please always use the most recent version
-of aztcd.c with the appropriate linux-kernel.
-
-3.  CONFIGURING YOUR KERNEL
-If your kernel is already configured for using the AZTECH driver you will
-see the following message while Linux boots:
-    Aztech CD-ROM Init: DriverVersion=<version number> BaseAddress=<baseaddress>
-    Aztech CD-ROM Init: FirmwareVersion=<firmware version id of your I/O-card>>>
-    Aztech CD-ROM Init: <drive type> detected
-    Aztech CD-ROM Init: End
-If the message looks different and you are sure to have a supported drive,
-it may have a different base address. The Aztech driver does look for the 
-CD-ROM drive at the base address specified in aztcd.h at compile time. This 
-address can be overwritten by boot parameter aztcd=....You should reboot and 
-start Linux with boot parameter aztcd=<base address>, e.g. aztcd=0x320. If 
-you do not know the base address, start your PC with DOS and look at the boot 
-message of your CD-ROM's DOS driver. If that still does not help, use boot
-parameter aztcd=<base address>,0x79 , this tells aztcd to try a little harder.
-aztcd may be configured to use autoprobing the base address by recompiling
-it (see chapter 4.).
-
-If the message looks correct, as user 'root' you should be able to mount the 
-drive by
-          mount -t iso9660 -r /dev/aztcd0 /mnt
-and use it as any other filesystem. (If this does not work, check if
-/dev/aztcd0 and /mnt do exist and create them, if necessary by doing
-      mknod /dev/aztcd0 b 29 0
-      mkdir /mnt                       
-
-If you still get a different message while Linux boots or when you get the 
-message, that the ISO9660-filesystem is not supported by your kernel, when
-you try to mount the CD-ROM drive, you have to recompile your kernel.
-
-If you do *not* have an Aztech/Orchid/Okano/Wearnes/TXC drive and want to 
-bypass drive detection during Linux boot up, start with boot parameter aztcd=0.
-
-Most distributions nowadays do contain a boot disk image containing aztcd.
-Please note, that this driver will not work with IDE/ATAPI drives! With these 
-you must use ide-cd.c instead.
-
-4. RECOMPILING YOUR KERNEL
-If your kernel is not yet configured for the AZTECH driver and the ISO9660-
-filesystem, you have to recompile your kernel: 
-
-- Edit aztcd.h to set the I/O-address to your I/O-Base address (AZT_BASE_ADDR), 
-  the driver does not use interrupts or DMA, so if you are using an AZTECH
-  CD268, an ORCHID CD-3110 or ORCHID/WEARNES CDD110 that's the only item you 
-  have to set up. If you have a soundcard, read chapter 4.2.
-  Users of other drives should read chapter OTHER DRIVES of this file.
-  You also can configure that address by kernel boot parameter aztcd=... 
-- aztcd may be configured to use autoprobing the base address by setting
-  AZT_BASE_ADDR to '-1'. In that case aztcd probes the addresses listed 
-  under AZT_BASE_AUTO. But please remember, that autoprobing always may 
-  incorrectly influence other hardware components too!
-- There are some other points, which may be configured, e.g. auto-eject the
-  CD when unmounting a drive, tray locking etc., see aztcd.h for details.
-- If you're using a linux kernel version prior to 2.1.0, in aztcd.h
-  uncomment the line '#define AZT_KERNEL_PRIOR_2_1'
-- Build a new kernel, configure it for 'Aztech/Orchid/Okano/Wearnes support' 
-  (if you want aztcd to be part of the kernel). Do not configure it for
-  'Aztech... support', if you want to use aztcd as a run time loadable module. 
-  But in any case you must have the ISO9660-filesystem included in your
-  kernel.
-- Activate the new kernel, normally this is done by running LILO (don't for-
-  get to configure it before and to keep a copy of your old kernel in case
-  something goes wrong!).
-- Reboot
-- If you've included aztcd in your kernel, you now should see during boot 
-  some messages like
-    Aztech CD-ROM Init: DriverVersion=<version number> BaseAddress=<baseaddress>
-    Aztech CD-ROM Init: FirmwareVersion=<firmware version id of your I/O-card>
-    Aztech CD-ROM Init: <drive type> detected
-    Aztech CD-ROM Init: End
-- If you have not included aztcd in your kernel, but want to load aztcd as a 
-  run time loadable module see 4.1. 
-- If the message looks correct, as user 'root' you should be able to mount 
-  the drive by
-          mount -t iso9660 -r /dev/aztcd0 /mnt
-  and use it as any other filesystem. (If this does not work, check if
-  /dev/aztcd0 and /mnt do exist and create them, if necessary by doing
-      mknod /dev/aztcd0 b 29 0
-      mkdir /mnt                       
-- If this still does not help, see chapters OTHER DRIVES and DEBUGGING.
-
-4.1 AZTCD AS A RUN-TIME LOADABLE MODULE
-If you do not need aztcd permanently, you can also load and remove the driver
-during runtime via insmod and rmmod. To build aztcd as a loadable module you 
-must configure your kernel for AZTECH module support (answer 'm' when con-
-figuring the kernel). Anyhow, you may run into problems, if the version of 
-your boot kernel is not the same than the source kernel version, from which 
-you create the modules. So rebuild your kernel, if necessary. 
-
-Now edit the base address of your AZTECH interface card in
-/usr/src/linux/drivers/cdrom/aztcd.h to the appropriate value. 
-aztcd may be configured to use autoprobing the base address by setting
-AZT_BASE_ADDR to '-1'. In that case aztcd probes the addresses listed 
-under AZT_BASE_AUTO. But please remember, that autoprobing always may 
-incorrectly influence other hardware components too!
-There are also some special features which may be configured, e.g. 
-auto-eject a CD when unmounting the drive etc; see aztcd.h for details. 
-Then change to /usr/src/linux and do a 
-                    make modules  
-	            make modules_install
-After that you can run-time load the driver via
-                    insmod /lib/modules/X.X.X/misc/aztcd.o
-and remove it via   rmmod  aztcd.
-If you did not set the correct base address in aztcd.h, you can also supply the
-base address when loading the driver via
-                    insmod /lib/modules/X.X.X/misc/aztcd.o aztcd=<base address>
-Again specifying aztcd=-1 will cause autoprobing.
-If you do not have the iso9660-filesystem in your boot kernel, you also have
-to load it before you can mount the CDROM:
-                    insmod /lib/modules/X.X.X/fs/isofs.o
-The mount procedure works as described in 4. above.
-(In all commands 'X.X.X' is the current linux kernel version number)
-
-4.2 CDROM CONNECTED TO A SOUNDCARD
-Most soundcards do have a bus interface to the CDROM-drive. In many cases
-this soundcard needs to be configured, before the CDROM can be used. This
-configuration procedure consists of writing some kind of initialization
-data to the soundcard registers. The AZTECH-CDROM driver in the moment does
-only support one type of soundcard (SoundWave32). Users of other soundcards
-should try to boot DOS first and let their DOS drivers initialize the
-soundcard and CDROM, then warm boot (or use loadlin) their PC to start
-Linux.
-Support for the CDROM-interface of SoundWave32-soundcards is directly
-implemented in the AZTECH driver. Please edit linux/drivers/cdrom/aztdc.h,
-uncomment line '#define AZT_SW32' and set the appropriate value for
-AZT_BASE_ADDR and AZT_SW32_BASE_ADDR. This support was tested with an Orchid
-CDS-3110 connected to a SoundWave32.
-If you want your soundcard to be supported, find out, how it needs to be
-configured and mail me (see 6.) the appropriate information. 
-
-5. KNOWN PROBLEMS, FUTURE DEVELOPMENTS
-5.1 MULTISESSION SUPPORT
-Multisession support for CD's still is a myth. I implemented and tested a basic
-support for multisession and XA CDs, but I still have not enough CDs and appli-
-cations to test it rigorously. So if you'd like to help me, please contact me
-(Email address see below). As of version 1.4 and newer you can enable the 
-multisession support in aztcd.h by setting AZT_MULTISESSION to 1. Doing so 
-will cause the ISO9660-filesystem to deal with multisession CDs, ie. redirect 
-requests to the Table of Contents (TOC) information from the last session, 
-which contains the info of all previous sessions etc.. If you do set 
-AZT_MULTISESSION to 0, you can use multisession CDs anyway. In that case the 
-drive's firmware will do automatic redirection. For the ISO9660-filesystem any 
-multisession CD  will then look like a 'normal' single session CD. But never-
-theless the data of all sessions are viewable and accessible. So with practical-
-ly all real world applications you won't notice the difference. But as future
-applications may make use of advanced multisession features, I've started to
-implement the interface for the ISO9660 multisession interface via ioctl
-CDROMMULTISESSION.
-
-5.2 STATUS RECOGNITION
-The drive status recognition does not work correctly in all cases. Changing
-a disk or having the door open, when a drive is already mounted, is detected 
-by the Aztech driver itself, but nevertheless causes multiple read attempts
-by the different layers of the ISO9660-filesystem driver, which finally timeout,
-so you have to wait quite a little... But isn't it bad style to change a disk 
-in a mounted drive, anyhow ?!
-
-The driver uses busy wait in most cases for the drive handshake (macros
-STEN_LOW and DTEN_LOW). I tested with a 486/DX2 at 66MHz and a Pentium at
-60MHz and 90MHz. Whenever you use a much faster machine you are likely to get 
-timeout messages. In that case edit aztcd.h and increase the timeout value 
-AZT_TIMEOUT. 
-
-For some 'slow' drive commands I implemented waiting with a timer waitqueue
-(macro STEN_LOW_WAIT). If you get this timeout message, you may also edit
-aztcd.h and increase the timeout value AZT_STATUS_DELAY. The waitqueue has
-shown to be a little critical. If you get kernel panic messages, edit aztcd.c
-and substitute STEN_LOW_WAIT by STEN_LOW. Busy waiting with STEN_LOW is more
-stable, but also causes CPU overhead.
-
-5.3 DOSEMU's CD-ROM SUPPORT
-With release 1.20 aztcd was modified to allow access to CD-ROMS when running
-under dosemu-0.60.0 aztcd-versions before 1.20 are most likely to crash
-Linux, when a CD-ROM is accessed under dosemu. This problem has partly been
-fixed, but still when accessing a directory for the first time the system
-might hang for some 30sec. So be patient, when using dosemu's CD-ROM support
-in combination with aztcd :-) ! 
-This problem has now (July 1995) been fixed by a modification to dosemu's
-CD-ROM driver. The new version came with dosemu-0.60.2, see dosemu's
-README.CDROM.
-
-6. BUG REPORTS
-Please send detailed bug reports and bug fixes via EMail to
-
-        Werner.Zimmermann@fht-esslingen.de
-
-Please include a description of your CD-ROM drive type and interface card, 
-the exact firmware message during Linux bootup, the version number of the 
-AZTECH-CDROM-driver and the Linux kernel version. Also a description of your 
-system's other hardware could be of interest, especially microprocessor type, 
-clock frequency, other interface cards such as soundcards, ethernet adapter, 
-game cards etc..
-
-I will try to collect the reports and make the necessary modifications from 
-time to time. I may also come back to you directly with some bug fixes and 
-ask you to do further testing and debugging.
-
-Editors of CD-ROMs are invited to send a 'cooperation' copy of their
-CD-ROMs to the volunteers, who provided the CD-ROM support for Linux. My
-snail mail address for such 'stuff' is
-           Prof. Dr. W. Zimmermann
-           Fachhochschule fuer Technik Esslingen
-           Fachbereich IT
-           Flandernstrasse 101
-           D-73732 Esslingen
-           Germany
-
-
-7. OTHER DRIVES
-The following drives ORCHID CDS3110, OKANO CDD110, WEARNES CDD110 and Conrad
-TXC Nr. 993123-series 04 nearly look the same as AZTECH CDA268-01A, especially 
-they seem to use the same command codes. So it was quite simple to make the 
-AZTECH driver work with these drives. 
-
-Unfortunately I do not have any of these drives available, so I couldn't test
-it myself. In some installations, it seems necessary to initialize the drive 
-with the DOS driver before (especially if combined with a sound card) and then 
-do a warm boot (CTRL-ALT-RESET) or start Linux from DOS, e.g. with 'loadlin'.
-
-If you do not succeed, read chapter DEBUGGING. Thanks in advance!
-
-Sorry for the inconvenience, but it is difficult to develop for hardware, 
-which you don't have available for testing. So if you like, please help us.
-
-If you do have a CyCDROM CR520ie thanks to Hilmar Berger's help your chances
-are good, that it will work with aztcd. The CR520ie is sold as an IDE-drive
-and really is connected to the IDE interface (primary at 0x1F0 or secondary
-at 0x170, configured as slave, not as master). Nevertheless it is not ATAPI
-compatible but still uses Aztech's command codes.
-
-
-8. DEBUGGING : IF YOU DON'T SUCCEED, TRY THE FOLLOWING
--reread the complete README file
--make sure, that your drive is hardware configured for 
-    transfer mode: polled
-    IRQ:           not used
-    DMA:           not used
-    Base Address:  something like 300, 320 ...
- You can check this, when you start the DOS driver, which came with your
- drive. By appropriately configuring the drive and the DOS driver you can
- check, whether your drive does operate in this mode correctly under DOS. If
- it does not operate under DOS, it won't under Linux.
- If your drive's base address is something like 0x170 or 0x1F0 (and it is
- not a CyCDROM CR520ie or CR 940ie) you most likely are having an IDE/ATAPI-
- compatible drive, which is not supported by aztcd.c, use ide-cd.c instead.
- Make sure the Base Address is configured correctly in aztcd.h, also make
- sure, that /dev/aztcd0 exists with the correct major number (compare it with
- the entry in file /usr/include/linux/major.h for the Aztech drive). 
--insert a CD-ROM and close the tray
--cold boot your PC (i.e. via the power on switch or the reset button)
--if you start Linux via DOS, e.g. using loadlin, make sure, that the DOS
- driver for the CD-ROM drive is not loaded (comment out the calling lines 
- in DOS' config.sys!)
--look for the aztcd: init message during Linux init and note them exactly
--log in as root and do a mount -t iso9660 /dev/aztcd0 /mnt
--if you don't succeed in the first time, try several times. Try also to open
- and close the tray, then mount again. Please note carefully all commands
- you typed in and the aztcd-messages, which you get.
--if you get an 'Aztech CD-ROM init: aborted' message, read the remarks about
- the version string below.
-
-If this does not help, do the same with the following differences 
--start DOS before; make now sure, that the DOS driver for the CD-ROM is 
- loaded under DOS (i.e. uncomment it again in config.sys)
--warm boot your PC (i.e. via CTRL-ALT-DEL)
- if you have it, you can also start via loadlin (try both).
- ...
- Again note all commands and the aztcd-messages.
-
-If you see STEN_LOW or STEN_LOW_WAIT error messages, increase the timeout
-values.
-
-If this still does not help, 
--look in aztcd.c for the lines  #if 0
-                                #define AZT_TEST1
-                                ...
-                                #endif
- and substitute '#if 0' by '#if 1'.
--recompile your kernel and repeat the above two procedures. You will now get 
- a bundle of debugging messages from the driver. Again note your commands
- and the appropriate messages. If you have syslogd running, these messages
- may also be found in syslogd's kernel log file. Nevertheless in some
- installations syslogd does not yet run, when init() is called, thus look for
- the aztcd-messages during init, before the login-prompt appears.
- Then look in aztcd.c, to find out, what happened. The normal calling sequence 
- is: aztcd_init() during Linux bootup procedure init()
- after doing a 'mount -t iso9660 /dev/aztcd0 /mnt' the normal calling sequence is
-     aztcd_open()    -> Status 2c after cold reboot with CDROM or audio CD inserted
-                     -> Status 8  after warm reboot with CDROM inserted          
-                     -> Status 2e after cold reboot with no disk, closed tray
-                     -> Status 6e after cold reboot, mount with door open
-     aztUpdateToc()
-     aztGetDiskInfo()
-     aztGetQChannelInfo()   repeated several times
-     aztGetToc()
-     aztGetQChannelInfo()   repeated several times
-     a list of track information
-     do_aztcd_request()  }  
-     azt_transfer()    } repeated several times
-     azt_poll          }
- Check, if there is a difference in the calling sequence or the status flags!
- 
- There are a lot of other messages, eg. the ACMD-command code (defined in
- aztcd.h), status info from the getAztStatus-command and the state sequence of
- the finite state machine in azt_poll(). The most important are the status
- messages, look how they are defined and try to understand, if they make
- sense in the context where they appear. With a CD-ROM inserted the status 
- should always be 8, except in aztcd_open(). Try to open the tray, insert an
- audio disk, insert no disk or reinsert the CD-ROM and check, if the status
- bits change accordingly. The status bits are the most likely point, where 
- the drive manufacturers may implement changes.
-            
-If you still don't succeed, a good point to start is to look in aztcd.c in 
-function aztcd_init, where the drive should be detected during init. Do the
-following:
--reboot the system with boot parameter 'aztcd=<your base address>,0x79'. With
- parameter 0x79 most of the drive version detection is bypassed. After that 
- you should see the complete version string including leading and trailing 
- blanks during init. 
- Now adapt the statement
-      if ((result[1]=='A')&&(result[2]=='Z' ...)
- in aztcd_init() to exactly match the first 3 or 4 letters you have seen.
--Another point is the 'smart' card detection feature in aztcd_init(). Normally
- the CD-ROM drive is ready, when aztcd_init is trying to read the version
- string and a time consuming ACMD_SOFT_RESET command can be avoided. This is
- detected by looking, if AFL_OP_OK can be read correctly. If the CD-ROM drive 
- hangs in some unknown state, e.g. because of an error before a warm start or 
- because you first operated under DOS, even the version string may be correct, 
- but the following commands will not. Then change the code in such a way, 
- that the ACMD_SOFT_RESET is issued in any case, by substituting the
- if-statement 'if ( ...=AFL_OP_OK)' by 'if (1)'.
-
-If you succeed, please mail me the exact version string of your drive and
-the code modifications, you have made together with a short explanation.
-If you don't succeed, you may mail me the output of the debugging messages.
-But remember, they are only useful, if they are exact and complete and you
-describe in detail your hardware setup and what you did (cold/warm reboot,
-with/without DOS, DOS-driver started/not started, which Linux-commands etc.)
-
-
-9. TECHNICAL HISTORY OF THE DRIVER
-The AZTECH-Driver is a rework of the Mitsumi-Driver. Four major items had to
-be reworked:
-
-a) The Mitsumi drive does issue complete status information acknowledging
-each command, the Aztech drive does only signal that the command was
-processed. So whenever the complete status information is needed, an extra
-ACMD_GET_STATUS command is issued. The handshake procedure for the drive
-can be found in the functions aztSendCmd(), sendAztCmd() and getAztStatus().
-
-b) The Aztech Drive does not have a ACMD_GET_DISK_INFO command, so the
-necessary info about the number of tracks (firstTrack, lastTrack), disk
-length etc. has to be read from the TOC in the lead in track (see function
-aztGetDiskInfo()).
-
-c) Whenever data is read from the drive, the Mitsumi drive is started with a
-command to read an indefinite (0xffffff) number of sectors. When the appropriate 
-number of sectors is read, the drive is stopped by a ACDM_STOP command. This
-does not work with the Aztech drive. I did not find a way to stop it. The
-stop and pause commands do only work in AUDIO mode but not in DATA mode.
-Therefore I had to modify the 'finite state machine' in function azt_poll to
-only read a certain number of sectors and then start a new read on demand. As I 
-have not completely understood, how the buffer/caching scheme of the Mitsumi 
-driver was implemented, I am not sure, if I have covered all cases correctly, 
-whenever you get timeout messages, the bug is most likely to be in that
-function azt_poll() around switch(cmd) .... case ACD_S_DATA. 
-
-d) I did not get information about changing drive mode. So I doubt, that the
-code around function azt_poll() case AZT_S_MODE does work. In my test I have
-not been able to switch to reading in raw mode. For reading raw mode, Aztech
-uses a different command than for cooked mode, which I only have implemen-
-ted in the ioctl-section but not in the section which is used by the ISO9660. 
-
-The driver was developed on an AST PC with Intel 486/DX2, 8MB RAM, 340MB IDE 
-hard disk and on an AST PC with Intel Pentium 60MHz, 16MB RAM, 520MB IDE 
-running Linux kernel version 1.0.9 from the LST 1.8 Distribution. The kernel 
-was compiled with gcc.2.5.8. My CD-ROM drive is an Aztech CDA268-01A. My
-drive says, that it has Firmware Version AZT26801A1.3. It came with an ISA-bus
-interface card and works with polled I/O without DMA and without interrupts.
-The code for all other drives was 'remote' tested and debugged by a number of 
-volunteers on the Internet.
-
-Points, where I feel that possible problems might be and all points where I 
-did not completely understand the drive's behaviour or trust my own code are 
-marked with /*???*/ in the source code. There are also some parts in the 
-Mitsumi driver, where I did not completely understand their code.
-
-
-10. ACKNOWLEDGMENTS
-Without the help of P.Bush, Aztech, who delivered technical information
-about the Aztech Drive and without the help of E.Moenkeberg, GWDG, who did a
-great job in analyzing the command structure of various CD-ROM drives, this
-work would not have been possible. E.Moenkeberg was also a great help in 
-making the software 'kernel ready' and in answering many of the CDROM-related 
-questions in the newsgroups. He really is *the* Linux CD-ROM guru. Thanks 
-also to all the guys on the Internet, who collected valuable technical 
-information about CDROMs. 
-
-Joe Nardone (joe@access.digex.net) was a patient tester even for my first
-trial, which was more than slow, and made suggestions for code improvement.
-Especially the 'finite state machine' azt_poll() was rewritten by Joe to get
-clean C code and avoid the ugly 'gotos', which I copied from mcd.c.
-
-Robby Schirmer (schirmer@fmi.uni-passau.de) tested the audio stuff (ioctls) 
-and suggested a lot of patches for them.
-
-Joseph Piskor and Peter Nugent were the first users with the ORCHID CD3110
-and also were very patient with the problems which occurred.
-
-Reinhard Max delivered the information for the CDROM-interface of the
-SoundWave32 soundcards.
-
-Jochen Kunz and Olaf Kaluza delivered the information for supporting Conrad's 
-TXC drive.
-
-Hilmar Berger delivered the patches for supporting CyCDROM CR520ie.
-
-Anybody, who is interested in these items should have a look at 'ftp.gwdg.de',
-directory 'pub/linux/cdrom' and at 'ftp.cdrom.com', directory 'pub/cdrom'.
-
-11. PROGRAMMING ADD ONs: cdplay.c
-You can use the ioctl-functions included in aztcd.c in your own programs. As
-an example on how to do this, you will find a tiny CD Player for audio CDs 
-named 'cdplay.c'. It allows you to play audio CDs. You can play a specified 
-track, pause and resume or skip tracks forward and backwards. If you quit the 
-program without stopping the  drive, playing is continued. You can also 
-(mis)use cdplay to read and hexdump data disks. You can find the code in the 
-APPENDIX of this file, which you should cut out with an editor and store in a 
-separate file 'cdplay.c'. To compile it and make it executable, do
-  gcc -s -Wall -O2 -L/usr/lib cdplay.c -o /usr/local/bin/cdplay # compiles it
-  chmod +755 /usr/local/bin/cdplay                              # makes it executable
-  ln -s /dev/aztcd0 /dev/cdrom                                  # creates a link
-   (for /usr/lib substitute the top level directory, where your include files 
-    reside,  and for /usr/local/bin the directory, where you want the executable 
-    binary to reside )
-
-You have to set the correct permissions for cdplay *and* for /dev/mcd0 or
-/dev/aztcd0 in order to use it. Remember, that you should not have /dev/cdrom 
-mounted, when you're playing audio CDs. 
-
-This program is just a hack for testing the ioctl-functions in aztcd.c. I will 
-not maintain it, so if you run into problems, discard it or have a look into 
-the source code 'cdplay.c'. The program does only contain a minimum of user 
-protection and input error detection. If you use the commands in the wrong 
-order or if you try to read a CD at wrong addresses, you may get error messages
-or even hang your machine. If you get STEN_LOW, STEN_LOW_WAIT or segment violation 
-error messages when using cdplay, after that, the system might not be stable 
-any more, so you'd better reboot. As the ioctl-functions run in kernel mode,
-most normal Linux-multitasking protection features do not work. By using
-uninitialized 'wild' pointers etc., it is easy to write to other users' data 
-and program areas, destroy kernel tables etc.. So if you experiment with ioctls
-as always when you are doing systems programming and kernel hacking, you
-should have a backup copy of your system in a safe place (and you also
-should try restoring from a backup copy first)!
-
-A reworked and improved version called 'cdtester.c', which has yet more
-features for testing CDROM-drives can be found in
-Documentation/cdrom/sbpcd, written by E.Moenkeberg.
-
-Werner Zimmermann
-Fachhochschule fuer Technik Esslingen
-(EMail: Werner.Zimmermann@fht-esslingen.de)
-October, 1997
-
----------------------------------------------------------------------------
-APPENDIX: Source code of cdplay.c
-
-/* Tiny Audio CD Player
-
-   Copyright 1994, 1995, 1996 Werner Zimmermann (Werner.Zimmermann@fht-esslingen.de)
-
-This program originally was written to test the audio functions of the
-AZTECH.CDROM-driver, but it should work with every CD-ROM drive. Before 
-using it, you should set a symlink from /dev/cdrom to your real CDROM
-device.
-
-The GNU General Public License applies to this program.
-
-History:  V0.1  W.Zimmermann: First release. Nov. 8, 1994
-          V0.2  W.Zimmermann: Enhanced functionality. Nov. 9, 1994
-          V0.3  W.Zimmermann: Additional functions. Nov. 28, 1994          
-          V0.4  W.Zimmermann: fixed some bugs. Dec. 17, 1994
-          V0.5  W.Zimmermann: clean 'scanf' commands without compiler warnings
-                              Jan. 6, 1995
-          V0.6  W.Zimmermann: volume control (still experimental). Jan. 24, 1995
-          V0.7  W.Zimmermann: read raw modified. July 26, 95
-*/
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <linux/cdrom.h>
-#include <linux/../../drivers/cdrom/aztcd.h>
-
-void help(void)
-{ printf("Available Commands:  STOP         s      EJECT/CLOSE  e       QUIT         q\n");
-  printf("                     PLAY TRACK   t      PAUSE        p       RESUME       r\n");
-  printf("                     NEXT TRACK   n      REPEAT LAST  l       HELP         h\n");
-  printf("                     SUB CHANNEL  c      TRACK INFO   i       PLAY AT      a\n");
-  printf("                     READ         d      READ RAW     w       VOLUME       v\n");
-}
-
-int main(void)
-{ int handle;
-  unsigned char command=' ', ini=0, first=1, last=1;
-  unsigned int cmd, i,j,k, arg1,arg2,arg3;
-  struct cdrom_ti       ti;
-  struct cdrom_tochdr   tocHdr;
-  struct cdrom_subchnl  subchnl;
-  struct cdrom_tocentry entry;
-  struct cdrom_msf      msf;
-  union  { struct cdrom_msf msf;
-           unsigned char buf[CD_FRAMESIZE_RAW];
-         } azt;
-  struct cdrom_volctrl  volctrl;
-
-  printf("\nMini-Audio CD-Player V0.72   (C) 1994,1995,1996  W.Zimmermann\n");
-  handle=open("/dev/cdrom",O_RDWR);
-  ioctl(handle,CDROMRESUME);
-  
-  if (handle<=0) 
-    { printf("Drive Error: already playing, no audio disk, door open\n");
-      printf("             or no permission (you must be ROOT in order to use this program)\n");
-    }
-  else
-    { help();
-      while (1)
-        { printf("Type command (h = help):  ");
-          scanf("%s",&command); 
-          switch (command)
-            { case 'e':   cmd=CDROMEJECT;
-                          ioctl(handle,cmd);
-                          break;  
-              case 'p':   if (!ini)
-                             { printf("Command not allowed - play track first\n");
-                             }
-                          else
-                             { cmd=CDROMPAUSE;
-                               if (ioctl(handle,cmd)) printf("Drive Error\n");
-                             }
-                          break;
-              case 'r':   if (!ini)
-                             { printf("Command not allowed - play track first\n");
-                             }
-                          else
-                             { cmd=CDROMRESUME;
-                               if (ioctl(handle,cmd)) printf("Drive Error\n");
-                             }
-                          break;
-              case 's':   cmd=CDROMPAUSE;
-                          if (ioctl(handle,cmd)) printf("Drive error or already stopped\n");
-                          cmd=CDROMSTOP;
-                          if (ioctl(handle,cmd)) printf("Drive error\n");
-                          break;
-              case 't':   cmd=CDROMREADTOCHDR;
-                          if (ioctl(handle,cmd,&tocHdr)) printf("Drive Error\n");
-                          first=tocHdr.cdth_trk0;
-                          last= tocHdr.cdth_trk1;
-                          if ((first==0)||(first>last))
-                            { printf ("--could not read TOC\n");
-                            }
-                          else
-                            { printf("--first track: %d   --last track: %d   --enter track number: ",first,last);
-                              cmd=CDROMPLAYTRKIND;
-                              scanf("%i",&arg1);
-                              ti.cdti_trk0=arg1;
-                              if (ti.cdti_trk0<first) ti.cdti_trk0=first;
-                              if (ti.cdti_trk0>last)  ti.cdti_trk0=last;
-                              ti.cdti_ind0=0;
-                              ti.cdti_trk1=last;
-                              ti.cdti_ind1=0;
-                              if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
-                              ini=1;
-                            } 
-                          break;
-              case 'n':   if (!ini++) 
-                            { if (ioctl(handle,CDROMREADTOCHDR,&tocHdr)) printf("Drive Error\n");
-                              first=tocHdr.cdth_trk0;
-                              last= tocHdr.cdth_trk1;
-                              ti.cdti_trk0=first-1;
-                            }
-                          if ((first==0)||(first>last))
-                            { printf ("--could not read TOC\n");
-                            }
-                          else
-                            { cmd=CDROMPLAYTRKIND;
-                              if (++ti.cdti_trk0 > last)  ti.cdti_trk0=last;
-                              ti.cdti_ind0=0;
-                              ti.cdti_trk1=last;
-                              ti.cdti_ind1=0;
-                              if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
-                              ini=1;
-                            }
-                          break;
-              case 'l':   if (!ini++)
-                            { if (ioctl(handle,CDROMREADTOCHDR,&tocHdr)) printf("Drive Error\n");
-                              first=tocHdr.cdth_trk0;
-                              last= tocHdr.cdth_trk1;
-                              ti.cdti_trk0=first+1;
-                            }
-                          if ((first==0)||(first>last))
-                            { printf ("--could not read TOC\n");
-                            }
-                          else
-                            { cmd=CDROMPLAYTRKIND;
-                              if (--ti.cdti_trk0 < first) ti.cdti_trk0=first;
-                              ti.cdti_ind0=0;
-                              ti.cdti_trk1=last;
-                              ti.cdti_ind1=0;
-                              if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
-                              ini=1;
-                            }  
-                          break;
-              case 'c':   subchnl.cdsc_format=CDROM_MSF;
-                          if (ioctl(handle,CDROMSUBCHNL,&subchnl)) 
-                            printf("Drive Error\n");
-                          else
-                            { printf("AudioStatus:%s   Track:%d  Mode:%d   MSF=%d:%d:%d\n", \
-                              subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY ? "PLAYING":"NOT PLAYING",\
-                              subchnl.cdsc_trk,subchnl.cdsc_adr, \
-                              subchnl.cdsc_absaddr.msf.minute, subchnl.cdsc_absaddr.msf.second, \
-                              subchnl.cdsc_absaddr.msf.frame);
-                            }
-                          break;              
-              case 'i':   if (!ini)
-                            { printf("Command not allowed - play track first\n");
-                            }
-                          else
-                            { cmd=CDROMREADTOCENTRY;
-                              printf("Track No.: ");
-                              scanf("%d",&arg1);
-                              entry.cdte_track=arg1;
-                              if (entry.cdte_track<first) entry.cdte_track=first;
-                              if (entry.cdte_track>last)  entry.cdte_track=last;
-			      entry.cdte_format=CDROM_MSF;
-                              if (ioctl(handle,cmd,&entry)) 
-                               { printf("Drive error or invalid track no.\n");
-                               }
-                              else
-                               { printf("Mode %d Track, starts at %d:%d:%d\n", \
-                               entry.cdte_adr,entry.cdte_addr.msf.minute, \
-                               entry.cdte_addr.msf.second,entry.cdte_addr.msf.frame);
-                               }
-                            }
-                          break;
-              case 'a':   cmd=CDROMPLAYMSF;
-                          printf("Address (min:sec:frame)  ");
-                          scanf("%d:%d:%d",&arg1,&arg2,&arg3);
-                          msf.cdmsf_min0  =arg1;
-                          msf.cdmsf_sec0  =arg2;
-                          msf.cdmsf_frame0=arg3;
-                          if (msf.cdmsf_sec0  > 59) msf.cdmsf_sec0  =59;
-                          if (msf.cdmsf_frame0> 74) msf.cdmsf_frame0=74;
-                          msf.cdmsf_min1=60;
-                          msf.cdmsf_sec1=00;
-                          msf.cdmsf_frame1=00;
-                          if (ioctl(handle,cmd,&msf)) 
-                           { printf("Drive error or invalid address\n");
-                           }
-                          break;
-#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/
-              case 'd':   cmd=CDROMREADCOOKED;
-                          printf("Address (min:sec:frame)  ");
-                          scanf("%d:%d:%d",&arg1,&arg2,&arg3);
-                          azt.msf.cdmsf_min0  =arg1;
-                          azt.msf.cdmsf_sec0  =arg2;
-                          azt.msf.cdmsf_frame0=arg3;
-                          if (azt.msf.cdmsf_sec0  > 59) azt.msf.cdmsf_sec0  =59;
-                          if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74;
-                          if (ioctl(handle,cmd,&azt.msf)) 
-                           { printf("Drive error, invalid address or unsupported command\n");
-                           }
-                          k=0;
-                          getchar();
-                          for (i=0;i<128;i++)
-                           { printf("%4d:",i*16);
-                             for (j=0;j<16;j++)
-                               { printf("%2x ",azt.buf[i*16+j]);
-                               }
-                             for (j=0;j<16;j++)
-                               { if (isalnum(azt.buf[i*16+j])) 
-                                   printf("%c",azt.buf[i*16+j]);
-                                 else
-                                   printf(".");
-                               }
-                             printf("\n"); 
-                             k++;
-                             if (k>=20)
-                              { printf("press ENTER to continue\n");
-                                getchar();
-                                k=0;
-                              }
-                           } 
-                          break;
-              case 'w':   cmd=CDROMREADRAW;
-                          printf("Address (min:sec:frame)  ");
-                          scanf("%d:%d:%d",&arg1,&arg2,&arg3);
-                          azt.msf.cdmsf_min0  =arg1;
-                          azt.msf.cdmsf_sec0  =arg2;
-                          azt.msf.cdmsf_frame0=arg3;                          
-                          if (azt.msf.cdmsf_sec0  > 59) azt.msf.cdmsf_sec0  =59;
-                          if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74;
-                          if (ioctl(handle,cmd,&azt)) 
-                           { printf("Drive error, invalid address or unsupported command\n");
-                           }
-                          k=0;
-                          for (i=0;i<147;i++)
-                           { printf("%4d:",i*16);
-                             for (j=0;j<16;j++)
-                               { printf("%2x ",azt.buf[i*16+j]);
-                               }
-                             for (j=0;j<16;j++)
-                               { if (isalnum(azt.buf[i*16+j])) 
-                                   printf("%c",azt.buf[i*16+j]);
-                                 else
-                                   printf(".");
-                               }
-                             printf("\n"); 
-                             k++;
-                             if (k>=20)
-                              { getchar();
-                                k=0;
-                              }
-                           } 
-                          break;
-#endif
-              case 'v':   cmd=CDROMVOLCTRL;
-                          printf("--Channel 0 Left  (0-255): ");
-                          scanf("%d",&arg1);
-                          printf("--Channel 1 Right (0-255): ");
-                          scanf("%d",&arg2);
-                          volctrl.channel0=arg1;
-                          volctrl.channel1=arg2;
-                          volctrl.channel2=0;
-                          volctrl.channel3=0;
-                          if (ioctl(handle,cmd,&volctrl)) 
-                           { printf("Drive error or unsupported command\n");
-                           }
-                          break;  
-              case 'q':   if (close(handle)) printf("Drive Error: CLOSE\n");
-                          exit(0);
-              case 'h':   help();
-                          break;
-              default:    printf("unknown command\n");
-                          break;
-            }
-       }
-    }
-  return 0;
-}
diff --git a/Documentation/cdrom/cdu31a b/Documentation/cdrom/cdu31a
deleted file mode 100644
index c0667da..0000000
--- a/Documentation/cdrom/cdu31a
+++ /dev/null
@@ -1,196 +0,0 @@
-
-		CDU31A/CDU33A Driver Info
-		-------------------------
-
-Information on the Sony CDU31A/CDU33A CDROM driver for the Linux
-kernel.
-
-   Corey Minyard (minyard@metronet.com)
-  
-   Colossians 3:17
-
-Crude Table of Contents
------------------------
-
-  Setting Up the Hardware
-  Configuring the Kernel
-  Configuring as a Module
-  Driver Special Features
-
-  
-This device driver handles Sony CDU31A/CDU33A CDROM drives and
-provides a complete block-level interface as well as an ioctl()
-interface as specified in include/linux/cdrom.h).  With this
-interface, CDROMs can be accessed, standard audio CDs can be played
-back normally, and CD audio information can be read off the drive.
-
-Note that this will only work for CDU31A/CDU33A drives.  Some vendors
-market their drives as CDU31A compatible.  They lie.  Their drives are
-really CDU31A hardware interface compatible (they can plug into the
-same card).  They are not software compatible.
-
-Setting Up the Hardware
------------------------
-
-The CDU31A driver is unable to safely tell if an interface card is
-present that it can use because the interface card does not announce
-its presence in any way besides placing 4 I/O locations in memory.  It
-used to just probe memory and attempt commands, but Linus wisely asked
-me to remove that because it could really screw up other hardware in
-the system.
-
-Because of this, you must tell the kernel where the drive interface
-is, what interrupts are used, and possibly if you are on a PAS-16
-soundcard.
-
-If you have the Sony CDU31A/CDU33A drive interface card, the following
-diagram will help you set it up.  If you have another card, you are on
-your own.  You need to make sure that the I/O address and interrupt is
-not used by another card in the system.  You will need to know the I/O
-address and interrupt you have set.  Note that use of interrupts is
-highly recommended, if possible, it really cuts down on CPU used.
-Unfortunately, most soundcards do not support interrupts for their
-CDROM interfaces.  By default, the Sony interface card comes with
-interrupts disabled.
-   
-        +----------+-----------------+----------------------+
-        |  JP1     |  34 Pin Conn    |                      |
-        |  JP2     +-----------------+                      |
-        |  JP3                                              |
-        |  JP4                                              |
-        |                                                   +--+
-        |                                                   |  +-+
-        |                                                   |  | |  External
-        |                                                   |  | |  Connector
-        |                                                   |  | |
-        |                                                   |  +-+
-        |                                                   +--+
-        |                                                   |
-        |                                          +--------+
-        |                                          |
-        +------------------------------------------+
-   
-      JP1 sets the Base Address, using the following settings:
-   
-        Address         Pin 1           Pin 2
-        -------         -----           -----
-        0x320           Short           Short
-        0x330           Short           Open
-        0x340           Open            Short
-        0x360           Open            Open
-   
-      JP2 and JP3 configure the DMA channel; they must be set the same.
-   
-        DMA             Pin 1           Pin 2           Pin 3
-        ---             -----           -----           -----
-        1               On              Off             On
-        2               Off             On              Off
-        3               Off             Off             On
-   
-      JP4 Configures the IRQ:
-   
-        IRQ     Pin 1           Pin 2           Pin 3           Pin 4
-        ---     -----           -----           -----           -----
-        3       Off             Off             On              Off
-        4       Off             Off*            Off             On
-        5       On              Off             Off             Off
-        6       Off             On              Off             Off
-   
-                  The documentation states to set this for interrupt
-                  4, but I think that is a mistake.
-
-Note that if you have another interface card, you will need to look at
-the documentation to find the I/O base address.  This is specified to
-the SLCD.SYS driver for DOS with the /B: parameter, so you can look at
-you DOS driver setup to find the address, if necessary.
-
-Configuring the Kernel
-----------------------
-
-You must tell the kernel where the drive is at boot time.  This can be
-done at the Linux boot prompt, by using LILO, or by using Bootlin.
-Note that this is no substitute for HOWTOs and LILO documentation, if
-you are confused please read those for info on bootline configuration
-and LILO.
-
-At the linux boot prompt, press the ALT key and add the following line
-after the boot name (you can let the kernel boot, it will tell you the
-default boot name while booting):
-
-	cdu31a=<base address>,<interrupt>[,PAS]
-
-The base address needs to have "0x" in front of it, since it is in
-hex.  For instance, to configure a drive at address 320 on interrupt 5,
-use the following:
-
-	cdu31a=0x320,5
-
-I use the following boot line:
-
-	cdu31a=0x1f88,0,PAS
-
-because I have a PAS-16 which does not support interrupt for the
-CDU31A interface.
-
-Adding this as an append line at the beginning of the /etc/lilo.conf
-file will set it for lilo configurations.  I have the following as the
-first line in my lilo.conf file:
-
-	append="cdu31a=0x1f88,0"
-
-I'm not sure how to set up Bootlin (I have never used it), if someone
-would like to fill in this section please do.
-
-
-Configuring as a Module
------------------------
-
-The driver supports loading as a module.  However, you must specify
-the boot address and interrupt on the boot line to insmod.  You can't
-use modprobe to load it, since modprobe doesn't support setting
-variables.
-
-Anyway, I use the following line to load my driver as a module
-
-  /sbin/insmod /lib/modules/`uname -r`/misc/cdu31a.o cdu31a_port=0x1f88
-
-You can set the following variables in the driver:
-
-  cdu31a_port=<I/O address> - sets the base I/O.  If hex, put 0x in
-			      front of it.  This must be specified.
-
-  cdu31a_irq=<interrupt> - Sets the interrupt number.  Leaving this
-			   off will turn interrupts off.
-
-
-Driver Special Features
------------------------
-
-This section describes features beyond the normal audio and CD-ROM
-functions of the drive.
-
-2048 byte buffer mode
-
-If a disk is mounted with -o block=2048, data is copied straight from
-the drive data port to the buffer.  Otherwise, the readahead buffer
-must be involved to hold the other 1K of data when a 1K block
-operation is done.  Note that with 2048 byte blocks you cannot execute
-files from the CD.
-
-XA compatibility
-
-The driver should support XA disks for both the CDU31A and CDU33A.  It
-does this transparently, the using program doesn't need to set it.
-
-Multi-Session
-
-A multi-session disk looks just like a normal disk to the user.  Just
-mount one normally, and all the data should be there.  A special
-thanks to Koen for help with this!
-
-Raw sector I/O
-
-Using the CDROMREADAUDIO it is possible to read raw audio and data
-tracks.  Both operations return 2352 bytes per sector.  On the data
-tracks, the first 12 bytes is not returned by the drive and the value
-of that data is indeterminate.
diff --git a/Documentation/cdrom/cm206 b/Documentation/cdrom/cm206
deleted file mode 100644
index 810368f..0000000
--- a/Documentation/cdrom/cm206
+++ /dev/null
@@ -1,185 +0,0 @@
-This is the readme file for the driver for the Philips/LMS cdrom drive
-cm206 in combination with the cm260 host adapter card. 
-
-				(c) 1995 David A. van Leeuwen
-   
-Changes since version 0.99
---------------------------
-- Interfacing to the kernel is routed though an extra interface layer, 
-  cdrom.c. This allows runtime-configurable `behavior' of the cdrom-drive, 
-  independent of the driver. 
-
-Features since version 0.33
----------------------------
-- Full audio support, that is, both  workman, workbone and cdp work
-  now reasonably. Reading TOC still takes some time. xmcd has been
-  reported to run successfully. 
-- Made auto-probe code a little better, I hope
-
-Features since version 0.28
----------------------------
-- Full speed transfer rate (300 kB/s).
-- Minimum kernel memory usage for buffering (less than 3 kB).
-- Multisession support.
-- Tray locking.
-- Statistics of driver accessible to the user.
-- Module support.
-- Auto-probing of adapter card's base port and irq line,
-  also configurable at boot time or module load time.
-
-
-Decide how you are going to use the driver. There are two
-options:
-
-   (a) installing the driver as a resident part of the kernel
-   (b) compiling the driver as a loadable module
-
-   Further, you must decide if you are going to specify the base port
-   address and the interrupt request line of the adapter card cm260 as
-   boot options for (a), module parameters for (b), use automatic
-   probing of these values, or hard-wire your adaptor card's settings
-   into the source code. If you don't care, you can choose 
-   autoprobing, which is the default. In that case you can move on to
-   the next step.
-
-Compiling the kernel
---------------------
-1) move to /usr/src/linux and do a 
-
-	make config
-
-   If you have chosen option (a), answer yes to CONFIG_CM206 and
-   CONFIG_ISO9660_FS.
-
-   If you have chosen option (b), answer yes to CONFIG_MODVERSIONS
-   and no (!) to CONFIG_CM206 and CONFIG_ISO9660_FS. 
-
-2) then do a 
-	
-	make clean; make zImage; make modules
-
-3) do the usual things to install a new image (backup the old one, run
-   `rdev -R zImage 1', copy the new image in place, run lilo).  Might
-   be `make zlilo'.
-
-Using the driver as a module
-----------------------------
-If you will only occasionally use the cd-rom driver, you can choose
-option (b), install as a loadable module. You may have to re-compile
-the module when you upgrade the kernel to a new version. 
-
-Since version 0.96, much of the functionality has been transferred to
-a generic cdrom interface in the file cdrom.c. The module cm206.o
-depends on cdrom.o. If the latter is not compiled into the kernel,
-you must explicitly load it before cm206.o:
-
-	 insmod /usr/src/linux/modules/cdrom.o
-
-To install the module, you use the command, as root
-
-	insmod /usr/src/linux/modules/cm206.o
-
-You can specify the base address on the command line as well as the irq 
-line to be used, e.g.
-
-	insmod /usr/src/linux/modules/cm206.o cm206=0x300,11
-
-The order of base port and irq line doesn't matter; if you specify only
-one, the other will have the value of the compiled-in default.  You
-may also have to install the file-system module `iso9660.o', if you
-didn't compile that into the kernel. 
-
-
-Using the driver as part of the kernel
---------------------------------------
-If you have chosen option (a), you can specify the base-port
-address and irq on the lilo boot command line, e.g.:
-
-	LILO: linux cm206=0x340,11
-
-This assumes that your linux kernel image keyword is `linux'. 
-If you specify either IRQ (3--11) or base port (0x300--0x370),
-auto probing is turned off for both settings, thus setting the 
-other value to the compiled-in default.
-
-Note that you can also put these parameters in the lilo configuration file:
-
-# linux config
-image = /vmlinuz
-   root = /dev/hda1
-   label = Linux
-   append = "cm206=0x340,11"
-   read-only
-
-
-If module parameters and LILO config options don't work
--------------------------------------------------------
-If autoprobing does not work, you can hard-wire the default values
-of the base port address (CM206_BASE) and interrupt request line
-(CM206_IRQ) into the file /usr/src/linux/drivers/cdrom/cm206.h. Change
-the defines of CM206_IRQ and CM206_BASE.
-
-
-Mounting the cdrom
-------------------
-1) Make sure that the right device is installed in /dev.
-
-  	mknod /dev/cm206cd b 32 0
-
-2) Make sure there is a mount point, e.g., /cdrom 
-
-	mkdir /cdrom
-
-3) mount using a command like this (run as root):
-
-	mount -rt iso9660 /dev/cm206cd /cdrom
-
-4) For user-mounts, add a line in /etc/fstab
-
-	/dev/cm206cd      /cdrom     iso9660 	ro,noauto,user
-
-   This will allow users to give the commands
-
-	mount /cdrom
-	umount /cdrom
-
-If things don't work
---------------------
-
-- Try to do a `dmesg' to find out if the driver said anything about
-  what is going wrong during the initialization.
-
-- Try to do a `dd if=/dev/cm206cd | od -tc | less' to read from the
-  CD.
-
-- Look in the /proc directory to see if `cm206' shows up under one of
-  `interrupts', `ioports', `devices' or `modules' (if applicable).
-
-
-DISCLAIMER 
----------- 
-I cannot guarantee that this driver works, or that the hardware will
-not be harmed, although I consider it most unlikely. 
-
-I hope that you'll find this driver in some way useful. 
-
-					David van Leeuwen
-					david@tm.tno.nl
-
-Note for Linux CDROM vendors
------------------------------
-You are encouraged to include this driver on your Linux CDROM. If
-you do, you might consider sending me a free copy of that cd-rom.
-You can contact me through my e-mail address, david@tm.tno.nl. 
-If this driver is compiled into a kernel to boot off a cdrom, 
-you should actually send me a free copy of that cd-rom. 
-
-Copyright
----------
-The copyright of the cm206 driver for Linux is 
-
-    (c) 1995 David A. van Leeuwen
-
-The driver is released under the conditions of the GNU general public
-license, which can be found in the file COPYING in the root of this
-source tree.
diff --git a/Documentation/cdrom/gscd b/Documentation/cdrom/gscd
deleted file mode 100644
index d01ca36..0000000
--- a/Documentation/cdrom/gscd
+++ /dev/null
@@ -1,60 +0,0 @@
-	Goldstar R420 CD-Rom device driver README
-
-For all kind of other information about the GoldStar R420 CDROM
-and this Linux device driver see the WWW page:
-
-        http://linux.rz.fh-hannover.de/~raupach        
-
-
-      If you are the editor of a Linux CD, you should
-      enable gscd.c within your boot floppy kernel. Please,
-      send me one of your CDs for free.
-
-
-This current driver version 0.4a only supports reading data from the disk.
-Currently we have no audio and no multisession or XA support.
-The polling interface is used, no DMA.
-
-
-Sometimes the GoldStar R420 is sold in a 'Reveal Multimedia Kit'. This kit's
-drive interface is compatible, too.
-
-
-Installation
-------------
-
-Change to '/usr/src/linux/drivers/cdrom' and edit the file 'gscd.h'. Insert
-the i/o address of your interface card.
-
-The default base address is 0x340. This will work for most applications. 
-Address selection is accomplished by jumpers PN801-1 to PN801-4 on the 
-GoldStar Interface Card.
-Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
-0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0             
-
-Then go back to '/usr/src/linux/' and 'make config' to build the new
-configuration for your kernel. If you want to use the GoldStar driver
-like a module, don't select 'GoldStar CDROM support'. By the way, you
-have to include the iso9660 filesystem.
-
-Now start compiling the kernel with 'make zImage'.
-If you want to use the driver as a module, you have to do 'make modules' 
-and 'make modules_install', additionally.
-Install your new kernel as usual - maybe you do it with 'make zlilo'.
-
-Before you can use the driver, you have to
-   mknod /dev/gscd0 b 16 0
-to create the appropriate device file (you only need to do this once).
-
-If you use modules, you can try to insert the driver.
-Say: 'insmod /usr/src/linux/modules/gscd.o'
-or:  'insmod /usr/src/linux/modules/gscd.o gscd=<address>'
-The driver should report its results.
-
-That's it! Mount a disk, i.e. 'mount -rt iso9660 /dev/gscd0 /cdrom'
-
-Feel free to report errors and suggestions to the following address.
-Be sure, I'm very happy to receive your comments!
- 
-        Oliver Raupach                                Hannover, Juni 1995
-(raupach@nwfs1.rz.fh-hannover.de)
diff --git a/Documentation/cdrom/isp16 b/Documentation/cdrom/isp16
deleted file mode 100644
index cc86533..0000000
--- a/Documentation/cdrom/isp16
+++ /dev/null
@@ -1,100 +0,0 @@
- -- Documentation/cdrom/isp16
-
-Docs by Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
-
-This is the README for version 0.6 of the cdrom interface on an
-ISP16, MAD16 or Mozart sound card.
-
-The detection and configuration of this interface used to be included
-in both the sjcd and optcd cdrom driver. Drives supported by these
-drivers came packed with Media Magic's multi media kit, which also
-included the ISP16 card. The idea (thanks Leo Spiekman)
-to move it from these drivers into a separate module and moreover, not to
-rely on the MAD16 sound driver, are as follows:
--duplication of code in the kernel is a waste of resources and should
- be avoided;
--however, kernels and notably those included with Linux distributions
- (cf Slackware 3.0 included version 0.5 of the isp16 configuration
- code included in the drivers) don't always come with sound support
- included. Especially when they already include a bunch of cdrom drivers.
- Hence, the cdrom interface should be configurable _independently_ of
- sound support.
-
-The ISP16, MAD16 and Mozart sound cards have an OPTi 82C928 or an
-OPTi 82C929 chip.  The interface on these cards should work with
-any cdrom attached to the card, which is 'electrically' compatible
-with Sanyo/Panasonic, Sony or Mitsumi non-ide drives. However, the
-command sets for any proprietary drives may differ
-(and hence may not be supported in the kernel) from these four types.
-For a fact I know the interface works and the way of configuration
-as described in this documentation works in combination with the
-sjcd (in Sanyo/Panasonic compatibility mode) cdrom drivers
-(probably with the optcd (in Sony compatibility mode) as well).
-If you have such an OPTi based sound card and you want to use the
-cdrom interface with a cdrom drive supported by any of the other cdrom
-drivers, it will probably work. Please let me know any experience you
-might have).
-I understand that cards based on the OPTi 82C929 chips may be configured
-(hardware jumpers that is) as an IDE interface. Initialisation of such a
-card in this mode is not supported (yet?).
-
-The suggestion to configure the ISP16 etc. sound card by booting DOS and 
-do a warm reboot to boot Linux somehow doesn't work, at least not
-on my machine (IPC P90), with the OPTi 82C928 based card.
-
-Booting the kernel through the boot manager LILO allows the use
-of some command line options on the 'LILO boot:' prompt. At boot time
-press Alt or Shift while the LILO prompt is written on the screen and enter
-any kernel options. Alternatively these options may be used in
-the appropriate section in /etc/lilo.conf. Adding 'append="<cmd_line_options>"'
-will do the trick as well.
-The syntax of 'cmd_line_options' is
-
-        isp16=[<port>[,<irq>[,<dma>]]][[,]<drive_type>]
-
-If there is no ISP16 or compatibles detected, there's probably no harm done.
-These options indicate the values that your cdrom drive has been (or will be)
-configured to use.
-Valid values for the base i/o address are:
-  port=0x340,0x320,0x330,0x360
-for the interrupt request number 
-  irq=0,3,5,7,9,10,11
-for the direct memory access line
-  dma=0,3,5,6,7
-and for the type of drive
-  drive_type=noisp16,Sanyo,Panasonic,Sony,Mitsumi.
-Note that these options are case sensitive.
-The values 0 for irq and dma indicate that they are not used, and
-the drive will be used in 'polling' mode. The values 5 and 7 for irq
-should be avoided in order to avoid any conflicts with optional
-sound card configuration.
-The syntax of the command line does not allow the specification of
-irq when there's nothing specified for the base address and no
-specification of dma when there is no specification of irq.
-The value 'noisp16' for drive_type, which may be used as the first
-non-integer option value (e.g. 'isp16=noisp16'), makes sure that probing
-for and subsequent configuration of an ISP16-compatible card is skipped
-all together. This can be useful to overcome possible conflicts which
-may arise while the kernel is probing your hardware.
-The default values are
-  port=0x340
-  irq=0
-  dma=0
-  drive_type=Sanyo
-reflecting my own configuration. The defaults can be changed in
-the file linux/drivers/cdrom/ips16.h.
-
-The cdrom interface can be configured at run time by loading the
-initialisation driver as a module. In that case, the interface
-parameters can be set by giving appropriate values on the command
-line. Configuring the driver can then be done by the following
-command (assuming you have iso16.o installed in a proper place):
-
-  insmod isp16.o isp16_cdrom_base=<port> isp16_cdrom_irq=<irq> \
-    isp16_cdrom_dma=<dma> isp16_cdrom_type=<drive_type>
-
-where port, irq, dma and drive_type can have any of the values mentioned
-above.
-
-
-Have fun!
diff --git a/Documentation/cdrom/mcdx b/Documentation/cdrom/mcdx
deleted file mode 100644
index 2bac4b7..0000000
--- a/Documentation/cdrom/mcdx
+++ /dev/null
@@ -1,29 +0,0 @@
-If you are using the driver as a module, you can specify your ports and IRQs
-like
-
- # insmod mcdx.o mcdx=0x300,11,0x304,5
-
-and so on ("address,IRQ" pairs).
-This will override the configuration in mcdx.h.
-
-This driver:
-
-    o   handles XA and (hopefully) multi session CDs as well as
-        ordinary CDs;
-    o   supports up to 5 drives (of course, you'll need free 
-        IRQs, i/o ports and slots);
-    o   plays audio
-
-This version doesn't support yet:
-
-    o   shared IRQs (but it seems to be possible - I've successfully
-                connected two drives to the same irq.  So it's `only' a 
-                problem of the driver.)
-
-This driver never will:
-
-    o   Read digital audio (i.e. copy directly), due to missing
-        hardware features. 
-
-
-heiko@lotte.sax.de
diff --git a/Documentation/cdrom/optcd b/Documentation/cdrom/optcd
deleted file mode 100644
index 6f46c7a..0000000
--- a/Documentation/cdrom/optcd
+++ /dev/null
@@ -1,57 +0,0 @@
-This is the README file for the Optics Storage 8000 AT CDROM device driver.
-
-This is the driver for the so-called 'DOLPHIN' drive, with the 34-pin
-Sony-compatible interface. For the IDE-compatible Optics Storage 8001
-drive, you will want the ATAPI CDROM driver. The driver also seems to
-work with the Lasermate CR328A. If you have a drive that works with
-this driver, and that doesn't report itself as DOLPHIN, please drop me
-a mail.
-
-The support for multisession CDs is in ALPHA stage. If you use it,
-please mail me your experiences. Multisession support can be disabled
-at compile time.
-
-You can find some older versions of the driver at
-      dutette.et.tudelft.nl:/pub/linux/
-and at Eberhard's mirror
-      ftp.gwdg.de:/pub/linux/cdrom/drivers/optics/
-
-Before you can use the driver, you have to create the device file once:
- # mknod /dev/optcd0 b 17 0
-
-To specify the base address if the driver is "compiled-in" to your kernel,
-you can use the kernel command line item (LILO option)
-             optcd=0x340
-with the right address.
-
-If you have compiled optcd as a module, you can load it with
- # insmod /usr/src/linux/modules/optcd.o
-or
- # insmod /usr/src/linux/modules/optcd.o optcd=0x340
-with the matching address value of your interface card.
-
-The driver employs a number of buffers to do read-ahead and block size
-conversion. The number of buffers is configurable in optcd.h, and has
-influence on the driver performance. For my machine (a P75), 6 buffers
-seems optimal, as can be seen from this table:
-
-#bufs	kb/s	%cpu
-1	97	0.1
-2	191	0.3
-3	188	0.2
-4	246	0.3
-5	189	19
-6	280	0.4
-7	281	7.0
-8	246	2.8
-16	281	3.4
-
-If you get a throughput significantly below 300 kb/s, try tweaking
-N_BUFS, and don't forget to mail me your results!
-
-I'd appreciate success/failure reports. If you find a bug, try
-recompiling the driver with some strategically chosen debug options
-(these can be found in optcd.h) and include the messages generated in
-your bug report. Good luck.
-
-Leo Spiekman (spiekman@dutette.et.tudelft.nl)
diff --git a/Documentation/cdrom/sbpcd b/Documentation/cdrom/sbpcd
deleted file mode 100644
index b3ba63f..0000000
--- a/Documentation/cdrom/sbpcd
+++ /dev/null
@@ -1,1061 +0,0 @@
-This README belongs to release 4.2 or newer of the SoundBlaster Pro
-(Matsushita, Kotobuki, Panasonic, CreativeLabs, Longshine and Teac)
-CD-ROM driver for Linux.
-
-sbpcd really, really is NOT for ANY IDE/ATAPI drive!
-Not even if you have an "original" SoundBlaster card with an IDE interface!
-So, you'd better have a look into README.ide if your port address is 0x1F0,
-0x170, 0x1E8, 0x168 or similar.
-I get tons of mails from IDE/ATAPI drive users - I really can't continue
-any more to answer them all. So, if your drive/interface information sheets
-mention "IDE" (primary, secondary, tertiary, quaternary) and the DOS driver
-invoking line within your CONFIG.SYS is using an address below 0x230:
-DON'T ROB MY LAST NERVE - jumper your interface to address 0x170 and IRQ 15
-(that is the "secondary IDE" configuration), set your drive to "master" and
-use ide-cd as your driver. If you do not have a second IDE hard disk, use the
-LILO commands
-   hdb=noprobe hdc=cdrom
-and get lucky.
-To make it fully clear to you: if you mail me about IDE/ATAPI drive problems,
-my answer is above, and I simply will discard your mail, hoping to stop the
-flood and to find time to lead my 12-year old son towards happy computing.
-
-The driver is able to drive the whole family of "traditional" AT-style (that
-is NOT the new "Enhanced IDE" or "ATAPI" drive standard) Matsushita,
-Kotobuki, Panasonic drives, sometimes labelled as "CreativeLabs". The
-well-known drives are CR-521, CR-522, CR-523, CR-562, CR-563.
-CR-574 is an IDE/ATAPI drive.
-
-The Longshine LCS-7260 is a double-speed drive which uses the "old"
-Matsushita command set. It is supported - with help by Serge Robyns.
-Vertos ("Elitegroup Computer Systems", ECS) has a similar drive - support
-has started; get in contact if you have such a "Vertos 100" or "ECS-AT"
-drive.
-
-There exists an "IBM External ISA CD-ROM Drive" which in fact is a CR-563
-with a special controller board. This drive is supported (the interface is
-of the "LaserMate" type), and it is possibly the best buy today (cheaper than
-an internal drive, and you can use it as an internal, too - e.g. plug it into
-a soundcard).
-
-CreativeLabs has a new drive "CD200" and a similar drive "CD200F". The latter
-is made by Funai and sometimes named "E2550UA", newer models may be named
-"MK4015". The CD200F drives should fully work.
-CD200 drives without "F" are still giving problems: drive detection and
-playing audio should work, data access will result in errors. I need qualified
-feedback about the bugs within the data functions or a drive (I never saw a
-CD200).
-
-The quad-speed Teac CD-55A drive is supported, but still does not reach "full
-speed". The data rate already reaches 500 kB/sec if you set SBP_BUFFER_FRAMES
-to 64 (it is not recommended to do that for normal "file access" usage, but it
-can speed up things a lot if you use something like "dd" to read from the
-drive; I use it for verifying self-written CDs this way).
-The drive itself is able to deliver 600 kB/sec, so this needs
-work; with the normal setup, the performance currently is not even as good as
-double-speed.
-
-This driver is NOT for Mitsumi or Sony or Aztech or Philips or XXX drives,
-and again: this driver is in no way usable for any IDE/ATAPI drive. If you 
-think your drive should work and it doesn't: send me the DOS driver for your
-beast (gzipped + uuencoded) and your CONFIG.SYS if you want to ask me for help,
-and include an original log message excerpt, and try to give all information
-a complete idiot needs to understand your hassle already with your first
-mail. And if you want to say "as I have mailed you before", be sure that I
-don't remember your "case" by such remarks; at the moment, I have some 
-hundreds of open correspondences about Linux CDROM questions (hope to reduce if
-the IDE/ATAPI user questions disappear). 
-
-
-This driver will work with the soundcard interfaces (SB Pro, SB 16, Galaxy,
-SoundFX, Mozart, MAD16 ...) and with the "no-sound" cards (Panasonic CI-101P,
-LaserMate, WDH-7001C, Longshine LCS-6853, Teac ...).
-
-It works with the "configurable" interface "Sequoia S-1000", too, which is 
-used on the Spea Media FX and Ensonic Soundscape sound cards. You have to
-specify the type "SBPRO 2" and the true CDROM port address with it, not the
-"configuration port" address.
-
-If you have a sound card which needs a "configuration driver" instead of
-jumpers for interface types and addresses (like Mozart cards) - those
-drivers get invoked before the DOS CDROM driver in your CONFIG.SYS, typical
-names are "cdsetup.sys" and "mztinit.sys" - let the sound driver do the
-CDROM port configuration (the leading comments in linux/drivers/sound/mad16.c
-are just for you!). Hannu Savolainen's mad16.c code is able to set up my
-Mozart card - I simply had to add
-   #define MAD16_CONF 0x06
-   #define MAD16_CDSEL 0x03
-to configure the CDROM interface for type "Panasonic" (LaserMate) and address
-0x340.
-
-The interface type has to get configured in linux/drivers/cdrom/sbpcd.h, 
-because the register layout is different between the "SoundBlaster" and the
-"LaserMate" type.
-
-I got a report that the Teac interface card "I/F E117098" is of type
-"SoundBlaster" (i.e. you have to set SBPRO to 1) even with the addresses
-0x300 and above. This is unusual, and it can't get covered by the auto
-probing scheme.
-The Teac 16-bit interface cards (like P/N E950228-00A, default address 0x2C0)
-need the SBPRO 3 setup.
-
-If auto-probing found the drive, the address is correct. The reported type
-may be wrong. A "mount" will give success only if the interface type is set
-right. Playing audio should work with a wrong set interface type, too.
-
-With some Teac and some CD200 drives I have seen interface cards which seem
-to lack the "drive select" lines; always drive 0 gets addressed. To avoid
-"mirror drives" (four drives detected where you only have one) with such
-interface cards, set MAX_DRIVES to 1 and jumper your drive to ID 0 (if
-possible).
-
-
-Up to 4 drives per interface card, and up to 4 interface cards are supported.
-All supported drive families can be mixed, but the CR-521 drives are 
-hard-wired to drive ID 0. The drives have to use different drive IDs, and each
-drive has to get a unique minor number (0...3), corresponding indirectly to 
-its drive ID.
-The drive IDs may be selected freely from 0 to 3 - they do not have to be in
-consecutive order.
-
-As Don Carroll, don@ds9.us.dell.com or FIDO 1:382/14, told me, it is possible
-to change old drives to any ID, too. He writes in this sense:
-   "In order to be able to use more than one single speed drive
-   (they do not have the ID jumpers) you must add a DIP switch
-   and two resistors. The pads are already on the board next to
-   the power connector. You will see the silkscreen for the
-   switch if you remove the top cover.
-                    1 2 3 4
-             ID 0 = x F F x             O = "on"
-             ID 1 = x O F x             F = "off"
-             ID 2 = x F O x             x = "don't care"
-             ID 3 = x O O x
-   Next to the switch are the positions for R76 (7k) and R78
-   (12k). I had to play around with the resistor values - ID 3
-   did not work with other values. If the values are not good,
-   ID 3 behaves like ID 0."
-
-To use more than 4 drives, you simply need a second controller card at a 
-different address and a second cable.
-
-The driver supports reading of data from the CD and playing of audio tracks.
-The audio part should run with WorkMan, xcdplayer, with the "non-X11" products
-CDplayer and WorkBone - tell me if it is not compatible with other software.
-The only accepted measure for correctness with the audio functions is the
-"cdtester" utility (appended) - most audio player programmers seem to be
-better musicians than programmers. ;-)
-
-With the CR-56x and the CD200 drives, the reading of audio frames is possible.
-This is implemented by an IOCTL function which reads READ_AUDIO frames of
-2352 bytes at once (configurable with the "READ_AUDIO" define, default is 0).
-Reading the same frame a second time gives different data; the frame data 
-start at a different position, but all read bytes are valid, and we always
-read 98 consecutive chunks (of 24 Bytes) as a frame. Reading more than 1 frame
-at once possibly misses some chunks at each frame boundary. This lack has to
-get corrected by external, "higher level" software which reads the same frame 
-again and tries to find and eliminate overlapping chunks (24-byte-pieces).
-
-The transfer rate with reading audio (1-frame-pieces) currently is very slow.
-This can be better reading bigger chunks, but the "missing" chunks possibly
-occur at the beginning of each single frame.
-The software interface possibly may change a bit the day the SCSI driver
-supports it too.
-
-With all but the CR-52x drives, MultiSession is supported.
-Photo CDs work (the "old" drives like CR-521 can access only the first
-session of a photoCD).
-At ftp.gwdg.de:/pub/linux/hpcdtoppm/ you will find Hadmut Danisch's package to
-convert photo CD image files and Gerd Knorr's viewing utility.
-
-The transfer rate will reach 150 kB/sec with CR-52x drives, 300 kB/sec with
-CR-56x drives, and currently not more than 500 kB/sec (usually less than
-250 kB/sec) with the Teac quad speed drives.
-XA (PhotoCD) disks with "old" drives give only 50 kB/sec.
-
-This release consists of
-- this README file
-- the driver file linux/drivers/cdrom/sbpcd.c
-- the stub files linux/drivers/cdrom/sbpcd[234].c
-- the header file linux/drivers/cdrom/sbpcd.h.
-
-
-To install:
------------
-
-1. Setup your hardware parameters. Though the driver does "auto-probing" at a
-   lot of (not all possible!) addresses, this step is recommended for
-   everyday use. You should let sbpcd auto-probe once and use the reported
-   address if a drive got found. The reported type may be incorrect; it is
-   correct if you can mount a data CD. There is no choice for you with the
-   type; only one is right, the others are deadly wrong.
-
-   a. Go into /usr/src/linux/drivers/cdrom/sbpcd.h and configure it for your
-      hardware (near the beginning):
-      a1. Set it up for the appropriate type of interface board.
-          "Original" CreativeLabs sound cards need "SBPRO 1".
-          Most "compatible" sound cards (almost all "non-CreativeLabs" cards)
-          need "SBPRO 0".
-          The "no-sound" board from OmniCd needs the "SBPRO 1" setup.
-          The Teac 8-bit "no-sound" boards need the "SBPRO 1" setup.
-          The Teac 16-bit "no-sound" boards need the "SBPRO 3" setup.
-          All other "no-sound" boards need the "SBPRO 0" setup.
-          The Spea Media FX and Ensoniq SoundScape cards need "SBPRO 2".
-          sbpcd.c holds some examples in its auto-probe list.
-          If you configure "SBPRO" wrong, the playing of audio CDs will work,
-          but you will not be able to mount a data CD.
-      a2. Tell the address of your CDROM_PORT (not of the sound port).
-      a3. If 4 drives get found, but you have only one, set MAX_DRIVES to 1.
-      a4. Set DISTRIBUTION to 0.
-   b. Additionally for 2.a1 and 2.a2, the setup may be done during
-      boot time (via the "kernel command line" or "LILO option"):
-          sbpcd=0x320,LaserMate
-      or
-          sbpcd=0x230,SoundBlaster
-      or
-          sbpcd=0x338,SoundScape
-      or
-          sbpcd=0x2C0,Teac16bit
-      This is especially useful if you install a fresh distribution.
-      If the second parameter is a number, it gets taken as the type
-      setting; 0 is "LaserMate", 1 is "SoundBlaster", 2 is "SoundScape",
-      3 is "Teac16bit".
-      So, for example
-          sbpcd=0x230,1
-      is equivalent to
-          sbpcd=0x230,SoundBlaster
-
-2. "cd /usr/src/linux" and do a "make config" and select "y" for Matsushita
-   CD-ROM support and for ISO9660 FileSystem support. If you do not have a
-   second, third, or fourth controller installed, do not say "y" to the 
-   secondary Matsushita CD-ROM questions.
-
-3. Then make the kernel image ("make zlilo" or similar).
-
-4. Make the device file(s). This step usually already has been done by the
-   MAKEDEV script.
-   The driver uses MAJOR 25, so, if necessary, do
-        mknod /dev/sbpcd  b 25 0       (if you have only one drive)
-   and/or
-        mknod /dev/sbpcd0 b 25 0
-        mknod /dev/sbpcd1 b 25 1
-        mknod /dev/sbpcd2 b 25 2
-        mknod /dev/sbpcd3 b 25 3
-   to make the node(s).
-
-   The "first found" drive gets MINOR 0 (regardless of its jumpered ID), the
-   "next found" (at the same cable) gets MINOR 1, ...
-   
-   For a second interface board, you have to make nodes like
-        mknod /dev/sbpcd4 b 26 0
-        mknod /dev/sbpcd5 b 26 1
-   and so on. Use the MAJORs 26, 27, 28.
-
-   If you further make a link like
-        ln -s sbpcd /dev/cdrom
-   you can use the name /dev/cdrom, too.
-
-5. Reboot with the new kernel.
-
-You should now be able to do
-              mkdir /CD
-and 
-              mount -rt iso9660 /dev/sbpcd /CD
-or
-              mount -rt iso9660 -o block=2048 /dev/sbpcd /CD
-and see the contents of your CD in the /CD directory.
-To use audio CDs, a mounting is not recommended (and it would fail if the
-first track is not a data track).
-
-
-Using sbpcd as a "loadable module":
------------------------------------
-
-If you do NOT select "Matsushita/Panasonic CDROM driver support" during the
-"make config" of your kernel, you can build the "loadable module" sbpcd.o.
-
-If sbpcd gets used as a module, the support of more than one interface
-card (i.e. drives 4...15) is disabled.
-
-You can specify interface address and type with the "insmod" command like:
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x340,0
-or
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x230,1
-or
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x338,2
-where the last number represents the SBPRO setting (no strings allowed here).
-
-
-Things of interest:
--------------------
-
-The driver is configured to try the LaserMate type of interface at I/O port
-0x0340 first. If this is not appropriate, sbpcd.h should get changed
-(you will find the right place - just at the beginning).
-
-No DMA and no IRQ is used.
-
-To reduce or increase the amount of kernel messages, edit sbpcd.c and play
-with the "DBG_xxx" switches (initialization of the variable "sbpcd_debug").
-Don't forget to reflect on what you do; enabling all DBG_xxx switches at once
-may crash your system, and each message line is accompanied by a delay.
-
-The driver uses the "variable BLOCK_SIZE" feature. To use it, you have to
-specify "block=2048" as a mount option. Doing this will disable the direct
-execution of a binary from the CD; you have to copy it to a device with the
-standard BLOCK_SIZE (1024) first. So, do not use this if your system is
-directly "running from the CDROM" (like some of Yggdrasil's installation
-variants). There are CDs on the market (like the German "unifix" Linux
-distribution) which MUST get handled with a block_size of 1024. Generally,
-one can say all the CDs which hold files of the name YMTRANS.TBL are defective;
-do not use block=2048 with those.
-
-Within sbpcd.h, you will find some "#define"s (e.g. EJECT and JUKEBOX). With
-these, you can configure the driver for some special things.
-You can use the appended program "cdtester" to set the auto-eject feature
-during runtime. Jeff Tranter's "eject" utility can do this, too (and more)
-for you.
-
-There is an ioctl CDROMMULTISESSION to obtain with a user program if
-the CD is an XA disk and - if it is - where the last session starts. The
-"cdtester" program illustrates how to call it.
-
-
-Auto-probing at boot time:
---------------------------
-
-The driver does auto-probing at many well-known interface card addresses,
-but not all:
-Some probings can cause a hang if an NE2000 ethernet card gets touched, because
-SBPCD's auto-probing happens before the initialization of the net drivers.
-Those "hazardous" addresses are excluded from auto-probing; the "kernel 
-command line" feature has to be used during installation if you have your 
-drive at those addresses. The "module" version is allowed to probe at those
-addresses, too.
-
-The auto-probing looks first at the configured address resp. the address
-submitted by the kernel command line. With this, it is possible to use this
-driver within installation boot floppies, and for any non-standard address,
-too.
-
-Auto-probing will make an assumption about the interface type ("SBPRO" or not),
-based upon the address. That assumption may be wrong (initialization will be
-o.k., but you will get I/O errors during mount). In that case, use the "kernel
-command line" feature and specify address & type at boot time to find out the
-right setup.
-
-For everyday use, address and type should get configured within sbpcd.h. That
-will stop the auto-probing due to success with the first try.
-
-The kernel command "sbpcd=0" suppresses each auto-probing and causes
-the driver not to find any drive; it is meant for people who love sbpcd
-so much that they do not want to miss it, even if they miss the drives. ;-)  
-
-If you configure "#define CDROM_PORT 0" in sbpcd.h, the auto-probing is
-initially disabled and needs an explicit kernel command to get activated.
-Once activated, it does not stop before success or end-of-list. This may be
-useful within "universal" CDROM installation boot floppies (but using the 
-loadable module would be better because it allows an "extended" auto-probing
-without fearing NE2000 cards).
-
-To shorten the auto-probing list to a single entry, set DISTRIBUTION 0 within
-sbpcd.h.
-
-
-Setting up address and interface type:
---------------------------------------
-
-If your I/O port address is not 0x340, you have to look for the #defines near
-the beginning of sbpcd.h and configure them: set SBPRO to 0 or 1 or 2, and
-change CDROM_PORT to the address of your CDROM I/O port.
-
-Almost all of the "SoundBlaster compatible" cards behave like the no-sound
-interfaces, i.e. need SBPRO 0! 
-
-With "original" SB Pro cards, an initial setting of CD_volume through the
-sound card's MIXER register gets done.
-If you are using a "compatible" sound card of types "LaserMate" or "SPEA",
-you can set SOUND_BASE (in sbpcd.h) to get it done with your card, too...
-
-
-Using audio CDs:
-----------------
-
-Workman, WorkBone, xcdplayer, cdplayer and the nice little tool "cdplay" (see
-README.aztcd from the Aztech driver package) should work.
-
-The program CDplayer likes to talk to "/dev/mcd" only, xcdplayer wants
-"/dev/rsr0", workman loves "/dev/sr0" or "/dev/cdrom" - so, make the 
-appropriate links to use them without the need to supply parameters.
-
-
-Copying audio tracks:
----------------------
-
-The following program will copy track 1 (or a piece of it) from an audio CD
-into the file "track01":
-
-/*=================== begin program ========================================*/
-/*
- * read an audio track from a CD
- *
- * (c) 1994 Eberhard Moenkeberg <emoenke@gwdg.de>
- *          may be used & enhanced freely
- *
- * Due to non-existent sync bytes at the beginning of each audio frame (or due
- * to a firmware bug within all known drives?), it is currently a kind of
- * fortune if two consecutive frames fit together.
- * Usually, they overlap, or a little piece is missing. This happens in units
- * of 24-byte chunks. It has to get fixed by higher-level software (reading
- * until an overlap occurs, and then eliminate the overlapping chunks). 
- * ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.*.tar.gz holds an example of
- * such an algorithm.
- * This example program further is missing to obtain the SubChannel data
- * which belong to each frame.
- *
- * This is only an example of the low-level access routine. The read data are
- * pure 16-bit CDDA values; they have to get converted to make sound out of
- * them.
- * It is no fun to listen to it without prior overlap/underlap correction!
- */
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <linux/cdrom.h>
-
-static struct cdrom_tochdr hdr;
-static struct cdrom_tocentry entry[101];
-static struct cdrom_read_audio arg;
-static u_char buffer[CD_FRAMESIZE_RAW];
-static int datafile, drive;
-static int i, j, limit, track, err;
-static char filename[32];
-
-int main(int argc, char *argv[])
-{
-/*
- * open /dev/cdrom
- */
-  drive=open("/dev/cdrom", 0);
-  if (drive<0)
-    {
-      fprintf(stderr, "can't open drive.\n");
-      exit (-1);
-    }
-/*
- * get TocHeader
- */
-  fprintf(stdout, "getting TocHeader...\n");
-  err=ioctl(drive, CDROMREADTOCHDR, &hdr);
-  if (err!=0)
-    {
-      fprintf(stderr, "can't get TocHeader (error %d).\n", err);
-      exit (-1);
-    }
-  else
-    fprintf(stdout, "TocHeader: %d %d\n", hdr.cdth_trk0, hdr.cdth_trk1);
-/*
- * get and display all TocEntries
- */
-  fprintf(stdout, "getting TocEntries...\n");
-  for (i=1;i<=hdr.cdth_trk1+1;i++)
-    {
-      if (i!=hdr.cdth_trk1+1) entry[i].cdte_track = i;
-      else entry[i].cdte_track = CDROM_LEADOUT;
-      entry[i].cdte_format = CDROM_LBA;
-      err=ioctl(drive, CDROMREADTOCENTRY, &entry[i]);
-      if (err!=0)
-	{
-	  fprintf(stderr, "can't get TocEntry #%d (error %d).\n", i, err);
-	  exit (-1);
-	}
-      else
-	{
-	  fprintf(stdout, "TocEntry #%d: %1X %1X %06X %02X\n",
-		 entry[i].cdte_track,
-		 entry[i].cdte_adr,
-		 entry[i].cdte_ctrl,
-		 entry[i].cdte_addr.lba,
-		 entry[i].cdte_datamode);
-	}
-    }
-  fprintf(stdout, "got all TocEntries.\n");
-/*
- * ask for track number (not implemented here)
- */
-track=1;
-#if 0 /* just read a little piece (4 seconds) */
-entry[track+1].cdte_addr.lba=entry[track].cdte_addr.lba+300;
-#endif
-/*
- * read track into file
- */
-  sprintf(filename, "track%02d\0", track);
-  datafile=creat(filename, 0755);
-  if (datafile<0)
-    {
-      fprintf(stderr, "can't open datafile %s.\n", filename);
-      exit (-1);
-    }
-  arg.addr.lba=entry[track].cdte_addr.lba;
-  arg.addr_format=CDROM_LBA; /* CDROM_MSF would be possible here, too. */
-  arg.nframes=1;
-  arg.buf=&buffer[0];
-  limit=entry[track+1].cdte_addr.lba;
-  for (;arg.addr.lba<limit;arg.addr.lba++)
-    {
-      err=ioctl(drive, CDROMREADAUDIO, &arg);
-      if (err!=0)
-	{
-	  fprintf(stderr, "can't read abs. frame #%d (error %d).\n", 
-		 arg.addr.lba, err);
-	}
-      j=write(datafile, &buffer[0], CD_FRAMESIZE_RAW);
-      if (j!=CD_FRAMESIZE_RAW)
-	{
-	  fprintf(stderr,"I/O error (datafile) at rel. frame %d\n",
-			 arg.addr.lba-entry[track].cdte_addr.lba);
-	}
-      arg.addr.lba++;
-    }
-    return 0;
-}
-/*===================== end program ========================================*/
-
-At ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.*.tar.gz is an adapted version of
-Heiko Eissfeldt's digital-audio to .WAV converter (the original is there, too).
-This is preliminary, as Heiko himself will care about it.
-
-
-Known problems:
----------------
-
-Currently, the detection of disk change or removal is actively disabled.
-
-Most attempts to read the UPC/EAN code result in a stream of zeroes. All my
-drives are mostly telling there is no UPC/EAN code on disk or there is, but it
-is an all-zero number. I guess now almost no CD holds such a number.
-
-Bug reports, comments, wishes, donations (technical information is a donation,
-too :-) etc. to emoenke@gwdg.de.
-
-SnailMail address, preferable for CD editors if they want to submit a free
-"cooperation" copy:
-                         Eberhard Moenkeberg
-                         Reinholdstr. 14
-                         D-37083 Goettingen
-                         Germany
----
-
-
-Appendix -- the "cdtester" utility:
-
-/*
- * cdtester.c -- test the audio functions of a CD driver
- *
- * (c) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
- *          published under the GPL
- *
- *          made under heavy use of the "Tiny Audio CD Player"
- *          from Werner Zimmermann <zimmerma@rz.fht-esslingen.de>
- *          (see linux/drivers/block/README.aztcd)
- */
-#undef AZT_PRIVATE_IOCTLS /* not supported by every CDROM driver */
-#define SBP_PRIVATE_IOCTLS /* not supported by every CDROM driver */
-
-#include <stdio.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <linux/cdrom.h>
-
-#ifdef AZT_PRIVATE_IOCTLS
-#include <linux/../../drivers/cdrom/aztcd.h>
-#endif /* AZT_PRIVATE_IOCTLS */
-#ifdef SBP_PRIVATE_IOCTLS
-#include <linux/../../drivers/cdrom/sbpcd.h>
-#include <linux/fs.h>
-#endif /* SBP_PRIVATE_IOCTLS */
-
-struct cdrom_tochdr hdr;
-struct cdrom_tochdr tocHdr;
-struct cdrom_tocentry TocEntry[101];
-struct cdrom_tocentry entry;
-struct cdrom_multisession ms_info;
-struct cdrom_read_audio read_audio;
-struct cdrom_ti ti;
-struct cdrom_subchnl subchnl;
-struct cdrom_msf msf;
-struct cdrom_volctrl volctrl;
-#ifdef AZT_PRIVATE_IOCTLS
-union
-{
-	struct cdrom_msf msf;
-	unsigned char buf[CD_FRAMESIZE_RAW];
-} azt;
-#endif /* AZT_PRIVATE_IOCTLS */
-int i, i1, i2, i3, j, k;
-unsigned char sequence=0;
-unsigned char command[80];
-unsigned char first=1, last=1;
-char *default_device="/dev/cdrom";
-char dev[20];
-char filename[20];
-int drive;
-int datafile;
-int rc;
-
-void help(void)
-{
-	printf("Available Commands:\n");
-	printf("STOP          s      EJECT        e       QUIT         q\n");
-	printf("PLAY TRACK    t      PAUSE        p       RESUME       r\n");
-	printf("NEXT TRACK    n      REPEAT LAST  l       HELP         h\n");
-	printf("SUBCHANNEL_Q  c      TRACK INFO   i       PLAY AT      a\n");
-	printf("READ          d      READ RAW     w       READ AUDIO   A\n");
-	printf("MS-INFO       M      TOC          T       START        S\n");
-	printf("SET EJECTSW   X      DEVICE       D       DEBUG        Y\n");
-	printf("AUDIO_BUFSIZ  Z      RESET        R       SET VOLUME   v\n");
-	printf("GET VOLUME    V\n");
-}
-
-/*
- *  convert MSF number (3 bytes only) to Logical_Block_Address 
- */
-int msf2lba(u_char *msf)
-{
-	int i;
-	
-	i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET;
-	if (i<0) return (0);
-	return (i);
-}
-/*
- *  convert logical_block_address to m-s-f_number (3 bytes only)
- */
-void lba2msf(int lba, unsigned char *msf)
-{
-	lba += CD_BLOCK_OFFSET;
-	msf[0] = lba / (CD_SECS*CD_FRAMES);
-	lba %= CD_SECS*CD_FRAMES;
-	msf[1] = lba / CD_FRAMES;
-	msf[2] = lba % CD_FRAMES;
-}
-
-int init_drive(char *dev)
-{
-	unsigned char msf_ent[3];
-
-	/*
-	 * open the device
-	 */
-	drive=open(dev,0);
-	if (drive<0) return (-1);
-	/*
-	 * get TocHeader
-	 */
-	printf("getting TocHeader...\n");
-	rc=ioctl(drive,CDROMREADTOCHDR,&hdr);
-	if (rc!=0)
-	{
-		printf("can't get TocHeader (error %d).\n",rc);
-		return (-2);
-	}
-	else
-		first=hdr.cdth_trk0;
-		last=hdr.cdth_trk1;
-		printf("TocHeader: %d %d\n",hdr.cdth_trk0,hdr.cdth_trk1);
-	/*
-	 * get and display all TocEntries
-	 */
-	printf("getting TocEntries...\n");
-	for (i=1;i<=hdr.cdth_trk1+1;i++)
-	{
-		if (i!=hdr.cdth_trk1+1) TocEntry[i].cdte_track = i;
-		else TocEntry[i].cdte_track = CDROM_LEADOUT;
-		TocEntry[i].cdte_format = CDROM_LBA;
-		rc=ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]);
-		if (rc!=0)
-		{
-			printf("can't get TocEntry #%d (error %d).\n",i,rc);
-		}
-		else
-		{
-			lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]);
-			if (TocEntry[i].cdte_track==CDROM_LEADOUT)
-			{
-				printf("TocEntry #%02X: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n",
-				       TocEntry[i].cdte_track,
-				       TocEntry[i].cdte_adr,
-				       TocEntry[i].cdte_ctrl,
-				       msf_ent[0],
-				       msf_ent[1],
-				       msf_ent[2],
-				       TocEntry[i].cdte_addr.lba,
-				       TocEntry[i].cdte_datamode);
-			}
-			else
-			{
-				printf("TocEntry #%02d: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n",
-				       TocEntry[i].cdte_track,
-				       TocEntry[i].cdte_adr,
-				       TocEntry[i].cdte_ctrl,
-				       msf_ent[0],
-				       msf_ent[1],
-				       msf_ent[2],
-				       TocEntry[i].cdte_addr.lba,
-				       TocEntry[i].cdte_datamode);
-			}
-		}
-	}
-	return (hdr.cdth_trk1); /* number of tracks */
-}
-
-void display(int size,unsigned char *buffer)
-{
-	k=0;
-	getchar();
-	for (i=0;i<(size+1)/16;i++)
-	{
-		printf("%4d:",i*16);
-		for (j=0;j<16;j++)
-		{
-			printf(" %02X",buffer[i*16+j]);
-		}
-		printf("  ");
-		for (j=0;j<16;j++)
-		{
-			if (isalnum(buffer[i*16+j])) 
-				printf("%c",buffer[i*16+j]);
-			else
-				printf(".");
-		}
-		printf("\n"); 
-		k++;
-		if (k>=20)
-		{
-			printf("press ENTER to continue\n");
-			getchar();
-			k=0;
-		}
-	} 
-} 
-
-int main(int argc, char *argv[])
-{
-	printf("\nTesting tool for a CDROM driver's audio functions V0.1\n");
-	printf("(C) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>\n");
-	printf("initializing...\n");
-	
-	rc=init_drive(default_device);
-	if (rc<0) printf("could not open %s (rc=%d).\n",default_device,rc);
-	help();
-	while (1)
-	{
-		printf("Give a one-letter command (h = help): ");
-		scanf("%s",command);
-		command[1]=0;
-		switch (command[0])
-		{
-		case 'D':
-			printf("device name (f.e. /dev/sbpcd3): ? ");
-			scanf("%s",&dev);
-			close(drive);
-			rc=init_drive(dev);
-			if (rc<0) printf("could not open %s (rc %d).\n",dev,rc);
-			break;
-		case 'e':
-			rc=ioctl(drive,CDROMEJECT);
-			if (rc<0) printf("CDROMEJECT: rc=%d.\n",rc);
-			break;
-		case 'p':
-			rc=ioctl(drive,CDROMPAUSE);
-			if (rc<0) printf("CDROMPAUSE: rc=%d.\n",rc);
-			break;
-		case 'r':
-			rc=ioctl(drive,CDROMRESUME);
-			if (rc<0) printf("CDROMRESUME: rc=%d.\n",rc);
-			break;
-		case 's':
-			rc=ioctl(drive,CDROMSTOP);
-			if (rc<0) printf("CDROMSTOP: rc=%d.\n",rc);
-			break;
-		case 'S':
-			rc=ioctl(drive,CDROMSTART);
-			if (rc<0) printf("CDROMSTART: rc=%d.\n",rc);
-			break;
-		case 't':
-			rc=ioctl(drive,CDROMREADTOCHDR,&tocHdr);
-			if (rc<0)
-			{
-				printf("CDROMREADTOCHDR: rc=%d.\n",rc);
-				break;
-			}
-			first=tocHdr.cdth_trk0;
-			last= tocHdr.cdth_trk1;
-			if ((first==0)||(first>last))
-			{
-				printf ("--got invalid TOC data.\n");
-			}
-			else
-			{
-				printf("--enter track number(first=%d, last=%d): ",first,last);
-				scanf("%d",&i1);
-				ti.cdti_trk0=i1;
-				if (ti.cdti_trk0<first) ti.cdti_trk0=first;
-				if (ti.cdti_trk0>last) ti.cdti_trk0=last;
-				ti.cdti_ind0=0;
-				ti.cdti_trk1=last;
-				ti.cdti_ind1=0;
-				rc=ioctl(drive,CDROMSTOP);
-				rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
-				if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
-			}
-			break;
-		case 'n':
-			rc=ioctl(drive,CDROMSTOP);
-			if (++ti.cdti_trk0>last) ti.cdti_trk0=last;
-			ti.cdti_ind0=0;
-			ti.cdti_trk1=last;
-			ti.cdti_ind1=0;
-			rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
-			if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
-			break;
-		case 'l':
-			rc=ioctl(drive,CDROMSTOP);
-			if (--ti.cdti_trk0<first) ti.cdti_trk0=first;
-			ti.cdti_ind0=0;
-			ti.cdti_trk1=last;
-			ti.cdti_ind1=0;
-			rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
-			if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
-			break;
-		case 'c':
-			subchnl.cdsc_format=CDROM_MSF;
-			rc=ioctl(drive,CDROMSUBCHNL,&subchnl);
-			if (rc<0) printf("CDROMSUBCHNL: rc=%d.\n",rc);
-			else
-			{
-				printf("AudioStatus:%s  Track:%d  Mode:%d  MSF=%02d:%02d:%02d\n",
-				       subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY ? "PLAYING":"NOT PLAYING",
-				       subchnl.cdsc_trk,subchnl.cdsc_adr, 
-				       subchnl.cdsc_absaddr.msf.minute,
-				       subchnl.cdsc_absaddr.msf.second,
-				       subchnl.cdsc_absaddr.msf.frame);
-			}
-			break;              
-		case 'i':
-			printf("Track No.: ");
-			scanf("%d",&i1);
-			entry.cdte_track=i1;
-			if (entry.cdte_track<first) entry.cdte_track=first;
-			if (entry.cdte_track>last)  entry.cdte_track=last;
-			entry.cdte_format=CDROM_MSF;
-			rc=ioctl(drive,CDROMREADTOCENTRY,&entry);
-			if (rc<0) printf("CDROMREADTOCENTRY: rc=%d.\n",rc);
-			else
-			{
-				printf("Mode %d Track, starts at %02d:%02d:%02d\n",
-				       entry.cdte_adr,
-				       entry.cdte_addr.msf.minute,
-				       entry.cdte_addr.msf.second,
-				       entry.cdte_addr.msf.frame);
-			}
-			break;
-		case 'a':
-			printf("Address (min:sec:frm)  ");
-			scanf("%d:%d:%d",&i1,&i2,&i3);
-			msf.cdmsf_min0=i1;
-			msf.cdmsf_sec0=i2;
-			msf.cdmsf_frame0=i3;
-			if (msf.cdmsf_sec0>59) msf.cdmsf_sec0=59;
-			if (msf.cdmsf_frame0>74) msf.cdmsf_frame0=74;
-			lba2msf(TocEntry[last+1].cdte_addr.lba-1,&msf.cdmsf_min1);
-			rc=ioctl(drive,CDROMSTOP);
-			rc=ioctl(drive,CDROMPLAYMSF,&msf);
-			if (rc<0) printf("CDROMPLAYMSF: rc=%d.\n",rc);
-			break;
-		case 'V':
-			rc=ioctl(drive,CDROMVOLREAD,&volctrl);
-			if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc);
-			printf("Volume: channel 0 (left) %d, channel 1 (right) %d\n",volctrl.channel0,volctrl.channel1);
-			break;  
-		case 'R':
-			rc=ioctl(drive,CDROMRESET);
-			if (rc<0) printf("CDROMRESET: rc=%d.\n",rc);
-			break;
-#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/
-		case 'd':
-			printf("Address (min:sec:frm)  ");
-			scanf("%d:%d:%d",&i1,&i2,&i3);
-			azt.msf.cdmsf_min0=i1;
-			azt.msf.cdmsf_sec0=i2;
-			azt.msf.cdmsf_frame0=i3;
-			if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59;
-			if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74;
-			rc=ioctl(drive,CDROMREADMODE1,&azt.msf);
-			if (rc<0) printf("CDROMREADMODE1: rc=%d.\n",rc);
-			else display(CD_FRAMESIZE,azt.buf);
-			break;
-		case 'w':
-			printf("Address (min:sec:frame)  ");
-			scanf("%d:%d:%d",&i1,&i2,&i3);
-			azt.msf.cdmsf_min0=i1;
-			azt.msf.cdmsf_sec0=i2;
-			azt.msf.cdmsf_frame0=i3;
-			if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59;
-			if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74;
-			rc=ioctl(drive,CDROMREADMODE2,&azt.msf);
-			if (rc<0) printf("CDROMREADMODE2: rc=%d.\n",rc);
-			else display(CD_FRAMESIZE_RAW,azt.buf); /* currently only 2336 */
-			break;  
-#endif
-		case 'v':
-			printf("--Channel 0 (Left)  (0-255): ");
-			scanf("%d",&i1);
-			volctrl.channel0=i1;
-			printf("--Channel 1 (Right) (0-255): ");
-			scanf("%d",&i1);
-			volctrl.channel1=i1;
-			volctrl.channel2=0;
-			volctrl.channel3=0;
-			rc=ioctl(drive,CDROMVOLCTRL,&volctrl);
-			if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc);
-			break;  
-		case 'q':
-			close(drive);
-			exit(0);
-		case 'h':
-			help();
-			break;
-		case 'T': /* display TOC entry - without involving the driver */
-			scanf("%d",&i);
-			if ((i<hdr.cdth_trk0)||(i>hdr.cdth_trk1))
-				printf("invalid track number.\n");
-			else
-				printf("TocEntry %02d: adr=%01X ctrl=%01X msf=%02d:%02d:%02d mode=%02X\n",
-				       TocEntry[i].cdte_track,
-				       TocEntry[i].cdte_adr,
-				       TocEntry[i].cdte_ctrl,
-				       TocEntry[i].cdte_addr.msf.minute,
-				       TocEntry[i].cdte_addr.msf.second,
-				       TocEntry[i].cdte_addr.msf.frame,
-				       TocEntry[i].cdte_datamode);
-			break;
-		case 'A': /* read audio data into file */
-			printf("Address (min:sec:frm) ? ");
-			scanf("%d:%d:%d",&i1,&i2,&i3);
-			read_audio.addr.msf.minute=i1;
-			read_audio.addr.msf.second=i2;
-			read_audio.addr.msf.frame=i3;
-			read_audio.addr_format=CDROM_MSF;
-			printf("# of frames ? ");
-			scanf("%d",&i1);
-			read_audio.nframes=i1;
-			k=read_audio.nframes*CD_FRAMESIZE_RAW;
-			read_audio.buf=malloc(k);
-			if (read_audio.buf==NULL)
-			{
-				printf("can't malloc %d bytes.\n",k);
-				break;
-			}
-			sprintf(filename,"audio_%02d%02d%02d_%02d.%02d\0",
-				read_audio.addr.msf.minute,
-				read_audio.addr.msf.second,
-				read_audio.addr.msf.frame,
-				read_audio.nframes,
-				++sequence);
-			datafile=creat(filename, 0755);
-			if (datafile<0)
-			{
-				printf("can't open datafile %s.\n",filename);
-				break;
-			}
-			rc=ioctl(drive,CDROMREADAUDIO,&read_audio);
-			if (rc!=0)
-			{
-				printf("CDROMREADAUDIO: rc=%d.\n",rc);
-			}
-			else
-			{
-				rc=write(datafile,&read_audio.buf,k);
-				if (rc!=k) printf("datafile I/O error (%d).\n",rc);
-			}
-			close(datafile);
-			break;
-		case 'X': /* set EJECT_SW (0: disable, 1: enable auto-ejecting) */
-			scanf("%d",&i);
-			rc=ioctl(drive,CDROMEJECT_SW,i);
-			if (rc!=0)
-				printf("CDROMEJECT_SW: rc=%d.\n",rc);
-			else
-				printf("EJECT_SW set to %d\n",i);
-			break;
-		case 'M': /* get the multisession redirection info */
-			ms_info.addr_format=CDROM_LBA;
-			rc=ioctl(drive,CDROMMULTISESSION,&ms_info);
-			if (rc!=0)
-			{
-				printf("CDROMMULTISESSION(lba): rc=%d.\n",rc);
-			}
-			else
-			{
-				if (ms_info.xa_flag) printf("MultiSession offset (lba): %d (0x%06X)\n",ms_info.addr.lba,ms_info.addr.lba);
-				else
-				{
-					printf("this CD is not an XA disk.\n");
-					break;
-				}
-			}
-			ms_info.addr_format=CDROM_MSF;
-			rc=ioctl(drive,CDROMMULTISESSION,&ms_info);
-			if (rc!=0)
-			{
-				printf("CDROMMULTISESSION(msf): rc=%d.\n",rc);
-			}
-			else
-			{
-				if (ms_info.xa_flag)
-					printf("MultiSession offset (msf): %02d:%02d:%02d (0x%02X%02X%02X)\n",
-					       ms_info.addr.msf.minute,
-					       ms_info.addr.msf.second,
-					       ms_info.addr.msf.frame,
-					       ms_info.addr.msf.minute,
-					       ms_info.addr.msf.second,
-					       ms_info.addr.msf.frame);
-				else printf("this CD is not an XA disk.\n");
-			}
-			break;
-#ifdef SBP_PRIVATE_IOCTLS
-		case 'Y': /* set the driver's message level */
-#if 0 /* not implemented yet */
-			printf("enter switch name (f.e. DBG_CMD): ");
-			scanf("%s",&dbg_switch);
-			j=get_dbg_num(dbg_switch);
-#else
-			printf("enter DDIOCSDBG switch number: ");
-			scanf("%d",&j);
-#endif
-			printf("enter 0 for \"off\", 1 for \"on\": ");
-			scanf("%d",&i);
-			if (i==0) j|=0x80;
-			printf("calling \"ioctl(drive,DDIOCSDBG,%d)\"\n",j);
-			rc=ioctl(drive,DDIOCSDBG,j);
-			printf("DDIOCSDBG: rc=%d.\n",rc);
-			break;
-		case 'Z': /* set the audio buffer size */
-			printf("# frames wanted: ? ");
-			scanf("%d",&j);
-			rc=ioctl(drive,CDROMAUDIOBUFSIZ,j);
-			printf("%d frames granted.\n",rc);
-			break;
-#endif /* SBP_PRIVATE_IOCTLS */
-		default:
-			printf("unknown command: \"%s\".\n",command);
-			break;
-		}
-	}
-	return 0;
-}
-/*==========================================================================*/
-
diff --git a/Documentation/cdrom/sjcd b/Documentation/cdrom/sjcd
deleted file mode 100644
index 74a1484..0000000
--- a/Documentation/cdrom/sjcd
+++ /dev/null
@@ -1,60 +0,0 @@
- -- Documentation/cdrom/sjcd
-				80% of the work takes 20% of the time,
-				20% of the work takes 80% of the time...
-						(Murphy's law)
-
-				Once started, training can not be stopped...
-						(Star Wars)
-
-This is the README for the sjcd cdrom driver, version 1.6.
-
-This file is meant as a tips & tricks edge for the usage of the SANYO CDR-H94A
-cdrom drive. It will grow as the questions arise. ;-)
-For info on configuring the ISP16 sound card look at Documentation/cdrom/isp16.
-
-The driver should work with any of the Panasonic, Sony or Mitsumi style
-CDROM interfaces.
-The cdrom interface on Media Magic's soft configurable sound card ISP16,
-which used to be included in the driver, is now supported in a separate module.
-This initialisation module will probably also work with other interfaces
-based on an OPTi 82C928 or 82C929 chip (like MAD16 and Mozart): see the
-documentation Documentation/cdrom/isp16.
-
-The device major for sjcd is 18, and minor is 0. Create a block special
-file in your /dev directory (e.g., /dev/sjcd) with these numbers.
-(For those who don't know, being root and doing the following should do
-the trick:
-  mknod -m 644 /dev/sjcd b 18 0
-and mount the cdrom by /dev/sjcd).
-
-The default configuration parameters are:
-  base address 0x340
-  no irq
-  no dma
-(Actually the CDR-H94A doesn't know how to use irq and dma.)
-As of version 1.2, setting base address at boot time is supported
-through the use of command line options: type at the "boot:" prompt:
-  linux sjcd=<base_address>
-(where you would use the kernel labeled "linux" in lilo's configuration
-file /etc/lilo.conf). You could also use 'append="sjcd=<configuration_info>"'
-in the appropriate section of /etc/lilo.conf
-If you're building a kernel yourself you can set your default base
-i/o address with SJCD_BASE_ADDR in /usr/src/linux/drivers/cdrom/sjcd.h.
-
-The sjcd driver supports being loaded as a module. The following
-command will set the base i/o address on the fly (assuming you
-have installed the module in an appropriate place).
-  insmod sjcd.o sjcd_base=<base_address>
-
-
-Have fun!
-
-If something is wrong, please email to		vadim@rbrf.ru
-					or 	vadim@ipsun.ras.ru
-					or	model@cecmow.enet.dec.com
-					or	H.T.M.v.d.Maarel@marin.nl
-
-It happens sometimes that Vadim is not reachable by mail. For these
-instances, Eric van der Maarel will help too.
-
-		Vadim V. Model, Eric van der Maarel, Eberhard Moenkeberg
diff --git a/Documentation/cdrom/sonycd535 b/Documentation/cdrom/sonycd535
deleted file mode 100644
index b81e109..0000000
--- a/Documentation/cdrom/sonycd535
+++ /dev/null
@@ -1,122 +0,0 @@
-              README FOR LINUX SONY CDU-535/531 DRIVER
-              ========================================
-
-This is the Sony CDU-535 (and 531) driver version 0.7 for Linux.
-I do not think I have the documentation to add features like DMA support
-so if anyone else wants to pursue it or help me with it, please do.
-(I need to see what was done for the CDU-31A driver -- perhaps I can
-steal some of that code.)
-
-This is a Linux device driver for the Sony CDU-535 CDROM drive.  This is
-one of the older Sony drives with its own interface card (Sony bus).
-The DOS driver for this drive is named SONY_CDU.SYS - when you boot DOS
-your drive should be identified as a SONY CDU-535.  The driver works
-with a CDU-531 also.  One user reported that the driver worked on drives
-OEM'ed by Procomm, drive and interface board were labelled Procomm.
-
-The Linux driver is based on Corey Minyard's sonycd 0.3 driver for
-the CDU-31A.  Ron Jeppesen just changed the commands that were sent
-to the drive to correspond to the CDU-535 commands and registers.
-There were enough changes to let bugs creep in but it seems to be stable.
-Ron was able to tar an entire CDROM (should read all blocks) and built
-ghostview and xfig off Walnut Creek's X11R5/GNU CDROM.  xcdplayer and
-workman work with the driver.  Others have used the driver without
-problems except those dealing with wait loops (fixed in third release).
-Like Minyard's original driver this one uses a polled interface (this
-is also the default setup for the DOS driver).  It has not been tried
-with interrupts or DMA enabled on the board.
-
-REQUIREMENTS
-============
-
-	- Sony CDU-535 drive, preferably without interrupts and DMA 
-	  enabled on the card.
-
-	- Drive must be set up as unit 1.  Only the first unit will be 
-	  recognized
-
-	- You must enter your interface address into 
-          /usr/src/linux/drivers/cdrom/sonycd535.h and build the
-          appropriate kernel or use the "kernel command line" parameter
-                sonycd535=0x320
-          with the correct interface address.
-
-NOTES:
-======
-
-1) The drive MUST be turned on when booting or it will not be recognized!
-   (but see comments on modularized version below)
-
-2) when the cdrom device is opened the eject button is disabled to keep the
-   user from ejecting a mounted disk and replacing it with another.
-   Unfortunately xcdplayer and workman also open the cdrom device so you
-   have to use the eject button in the software.  Keep this in mind if your
-   cdrom player refuses to give up its disk -- exit workman or xcdplayer, or
-   umount the drive if it has been mounted.
-
-THANKS
-======
-
-Many thanks to Ron Jeppesen (ronj.an@site007.saic.com) for getting
-this project off the ground.  He wrote the initial release
-and the first two patches to this driver (0.1, 0.2, and 0.3).
-Thanks also to Eberhard Moenkeberg (emoenke@gwdg.de) for prodding
-me to place this code into the mainstream Linux source tree
-(as of Linux version 1.1.91), as well as some patches to make
-it a better device citizen.  Further thanks to Joel Katz
-<joelkatz@webchat.org> for his MODULE patches (see details below),
-Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
-to make the driver work with the older CDU-510/515 series, and
-Heiko Eissfeldt <heiko@colossus.escape.de> for pointing out that
-the verify_area() checks were ignoring the results of said checks
-(note: verify_area() has since been replaced by access_ok()).
-
-(Acknowledgments from Ron Jeppesen in the 0.3 release:)
-Thanks to Corey Minyard who wrote the original CDU-31A driver on which
-this driver is based.  Thanks to Ken Pizzini and Bob Blair who provided 
-patches and feedback on the first release of this driver.
-
-Ken Pizzini
-ken@halcyon.com
-
-------------------------------------------------------------------------------
-(The following is from Joel Katz <joelkatz@webchat.org>.)
-
-	To build a version of sony535.o that can be installed as a module,
-use the following command:
-
-gcc -c -D__KERNEL__ -DMODULE -O2 sonycd535.c -o sonycd535.o
-
-	To install the module, simply type:
-
-insmod sony535.o
-	or
-insmod sony535.o sonycd535=<address>
-
-	And to remove it:
-
-rmmod sony535
-
-	The code checks to see if MODULE is defined and behaves as it used
-to if MODULE is not defined. That means your patched file should behave
-exactly as it used to if compiled into the kernel.
-
-	I have an external drive, and I usually leave it powered off. I used
-to have to reboot if I needed to use the CDROM drive. Now I don't.
-
-	Even if you have an internal drive, why waste the 96K of memory
-(unswappable) that the driver uses if you use your CD-ROM drive infrequently?
-
-	This driver will not install (whether compiled in or loaded as a
-module) if the CDROM drive is not available during its initialization. This
-means that you can have the driver compiled into the kernel and still load
-the module later (assuming the driver doesn't install itself during
-power-on). This only wastes 12K when you boot with the CDROM drive off.
-
-	This is what I usually do; I leave the driver compiled into the
-kernel, but load it as a module if I powered the system up with the drive
-off and then later decided to use the CDROM drive.
-
-	Since the driver only uses a single page to point to the chunks,
-attempting to set the buffer cache to more than 2 Megabytes would be very
-bad; don't do that.
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 64e9f6c..595a5ea 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -10,10 +10,12 @@
 *.grp
 *.gz
 *.html
+*.i
 *.jpeg
 *.ko
 *.log
 *.lst
+*.moc
 *.mod.c
 *.o
 *.orig
@@ -25,6 +27,9 @@
 *.s
 *.sgml
 *.so
+*.symtypes
+*.tab.c
+*.tab.h
 *.tex
 *.ver
 *.xml
@@ -32,9 +37,13 @@
 *_vga16.c
 *cscope*
 *~
+*.9
+*.9.gz
 .*
 .cscope
 53c700_d.h
+53c7xx_d.h
+53c7xx_u.h
 53c8xx_d.h*
 BitKeeper
 COPYING
@@ -70,9 +79,11 @@
 classlist.h*
 comp*.log
 compile.h*
+conf
 config
 config-*
 config_data.h*
+config_data.gz*
 conmakehash
 consolemap_deftbl.c*
 crc32table.h*
@@ -81,18 +92,23 @@
 devlist.h*
 docproc
 dummy_sym.c*
+elf2ecoff
 elfconfig.h*
 filelist
 fixdep
 fore200e_mkfirm
 fore200e_pca_fw.c*
+gconf
 gen-devlist
 gen-kdb_cmds.c*
 gen_crc32table
 gen_init_cpio
 genksyms
 gentbl
+*_gray256.c
 ikconfig.h*
+initramfs_data.cpio
+initramfs_data.cpio.gz
 initramfs_list
 kallsyms
 kconfig
@@ -100,19 +116,30 @@
 keywords.c*
 ksym.c*
 ksym.h*
+kxgettext
+lkc_defs.h
 lex.c*
+lex.*.c
+lk201-map.c
 logo_*.c
 logo_*_clut224.c
 logo_*_mono.c
 lxdialog
 mach-types
 mach-types.h
+machtypes.h
 make_times_h
 map
 maui_boot.h
+mconf
+miboot*
 mk_elfconfig
+mkboot
+mkbugboot
 mkdep
+mkprep
 mktables
+mktree
 modpost
 modversions.h*
 offset.h
@@ -120,18 +147,28 @@
 oui.c*
 parse.c*
 parse.h*
+patches*
+pca200e.bin
+pca200e_ecd.bin2
+piggy.gz
+piggyback
 pnmtologo
 ppc_defs.h*
 promcon_tbl.c*
 pss_boot.h
+qconf
 raid6altivec*.c
 raid6int*.c
 raid6tables.c
+relocs
+series
 setup
 sim710_d.h*
+sImage
 sm_tbl*
 split-include
 tags
+tftpboot.img
 times.h*
 tkparse
 trix_boot.h
@@ -139,8 +176,11 @@
 version.h*
 vmlinux
 vmlinux-*
+vmlinux.aout
 vmlinux.lds
 vsyscall.lds
 wanxlfw.inc
 uImage
-zImage
+unifdef
+zImage*
+zconf.hash.c
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
index 19c4a6e..2a97320 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -96,6 +96,46 @@
 calls to clk_get(&pdev->dev, clock_name) return them as needed.
 
 
+Legacy Drivers:  Device Probing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some drivers are not fully converted to the driver model, because they take
+on a non-driver role:  the driver registers its platform device, rather than
+leaving that for system infrastructure.  Such drivers can't be hotplugged
+or coldplugged, since those mechanisms require device creation to be in a
+different system component than the driver.
+
+The only "good" reason for this is to handle older system designs which, like
+original IBM PCs, rely on error-prone "probe-the-hardware" models for hardware
+configuration.  Newer systems have largely abandoned that model, in favor of
+bus-level support for dynamic configuration (PCI, USB), or device tables
+provided by the boot firmware (e.g. PNPACPI on x86).  There are too many
+conflicting options about what might be where, and even educated guesses by
+an operating system will be wrong often enough to make trouble.
+
+This style of driver is discouraged.  If you're updating such a driver,
+please try to move the device enumeration to a more appropriate location,
+outside the driver.  This will usually be cleanup, since such drivers
+tend to already have "normal" modes, such as ones using device nodes that
+were created by PNP or by platform device setup.
+
+None the less, there are some APIs to support such legacy drivers.  Avoid
+using these calls except with such hotplug-deficient drivers.
+
+	struct platform_device *platform_device_alloc(
+			char *name, unsigned id);
+
+You can use platform_device_alloc() to dynamically allocate a device, which
+you will then initialize with resources and platform_device_register().
+A better solution is usually:
+
+	struct platform_device *platform_device_register_simple(
+			char *name, unsigned id,
+			struct resource *res, unsigned nres);
+
+You can use platform_device_register_simple() as a one-step call to allocate
+and register a device.
+
+
 Device Naming and Driver Binding
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 The platform_device.dev.bus_id is the canonical name for the devices.
diff --git a/Documentation/fault-injection/failcmd.sh b/Documentation/fault-injection/failcmd.sh
deleted file mode 100644
index 63177ab..0000000
--- a/Documentation/fault-injection/failcmd.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-echo 1 > /proc/self/make-it-fail
-exec $*
diff --git a/Documentation/fault-injection/failmodule.sh b/Documentation/fault-injection/failmodule.sh
deleted file mode 100644
index 474a8b9..0000000
--- a/Documentation/fault-injection/failmodule.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-#
-# Usage: failmodule <failname> <modulename> [stacktrace-depth]
-#
-#	<failname>: "failslab", "fail_alloc_page", or "fail_make_request"
-#
-#	<modulename>: module name that you want to inject faults.
-#
-#	[stacktrace-depth]: the maximum number of stacktrace walking allowed
-#
-
-STACKTRACE_DEPTH=5
-if [ $# -gt 2 ]; then
-	STACKTRACE_DEPTH=$3
-fi
-
-if [ ! -d /debug/$1 ]; then
-	echo "Fault-injection $1 does not exist" >&2
-	exit 1
-fi
-if [ ! -d /sys/module/$2 ]; then
-	echo "Module $2 does not exist" >&2
-	exit 1
-fi
-
-# Disable any fault injection
-echo 0 > /debug/$1/stacktrace-depth
-
-echo `cat /sys/module/$2/sections/.text` > /debug/$1/require-start
-echo `cat /sys/module/$2/sections/.exit.text` > /debug/$1/require-end
-echo $STACKTRACE_DEPTH > /debug/$1/stacktrace-depth
diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt
index b7ca560..4bc374a 100644
--- a/Documentation/fault-injection/fault-injection.txt
+++ b/Documentation/fault-injection/fault-injection.txt
@@ -103,6 +103,11 @@
 	default is 'N', setting it to 'Y' will inject failures
 	only into non-sleep allocations (GFP_ATOMIC allocations).
 
+- /debug/fail_page_alloc/min-order:
+
+	specifies the minimum page allocation order to be injected
+	failures.
+
 o Boot option
 
 In order to inject faults while debugfs is not available (early boot time),
@@ -156,70 +161,77 @@
 Application Examples
 --------------------
 
-o inject slab allocation failures into module init/cleanup code
+o Inject slab allocation failures into module init/exit code
 
-------------------------------------------------------------------------------
 #!/bin/bash
 
-FAILCMD=Documentation/fault-injection/failcmd.sh
-BLACKLIST="root_plug evbug"
+FAILTYPE=failslab
+echo Y > /debug/$FAILTYPE/task-filter
+echo 10 > /debug/$FAILTYPE/probability
+echo 100 > /debug/$FAILTYPE/interval
+echo -1 > /debug/$FAILTYPE/times
+echo 0 > /debug/$FAILTYPE/space
+echo 2 > /debug/$FAILTYPE/verbose
+echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
 
-FAILNAME=failslab
-echo Y > /debug/$FAILNAME/task-filter
-echo 10 > /debug/$FAILNAME/probability
-echo 100 > /debug/$FAILNAME/interval
-echo -1 > /debug/$FAILNAME/times
-echo 2 > /debug/$FAILNAME/verbose
-echo 1 > /debug/$FAILNAME/ignore-gfp-wait
-
-blacklist()
+faulty_system()
 {
-	echo $BLACKLIST | grep $1 > /dev/null 2>&1
+	bash -c "echo 1 > /proc/self/make-it-fail && exec $*"
 }
 
-oops()
-{
-	dmesg | grep BUG > /dev/null 2>&1
-}
+if [ $# -eq 0 ]
+then
+	echo "Usage: $0 modulename [ modulename ... ]"
+	exit 1
+fi
 
-find /lib/modules/`uname -r` -name '*.ko' -exec basename {} .ko \; |
-	while read i
-	do
-		oops && exit 1
+for m in $*
+do
+	echo inserting $m...
+	faulty_system modprobe $m
 
-		if ! blacklist $i
-		then
-			echo inserting $i...
-			bash $FAILCMD modprobe $i
-		fi
-	done
-
-lsmod | awk '{ if ($3 == 0) { print $1 } }' |
-	while read i
-	do
-		oops && exit 1
-
-		if ! blacklist $i
-		then
-			echo removing $i...
-			bash $FAILCMD modprobe -r $i
-		fi
-	done
+	echo removing $m...
+	faulty_system modprobe -r $m
+done
 
 ------------------------------------------------------------------------------
 
-o inject slab allocation failures only for a specific module
+o Inject page allocation failures only for a specific module
 
-------------------------------------------------------------------------------
 #!/bin/bash
 
-FAILMOD=Documentation/fault-injection/failmodule.sh
+FAILTYPE=fail_page_alloc
+module=$1
 
-echo injecting errors into the module $1...
+if [ -z $module ]
+then
+	echo "Usage: $0 <modulename>"
+	exit 1
+fi
 
-modprobe $1
-bash $FAILMOD failslab $1 10
-echo 25 > /debug/failslab/probability
+modprobe $module
 
-------------------------------------------------------------------------------
+if [ ! -d /sys/module/$module/sections ]
+then
+	echo Module $module is not loaded
+	exit 1
+fi
+
+cat /sys/module/$module/sections/.text > /debug/$FAILTYPE/require-start
+cat /sys/module/$module/sections/.data > /debug/$FAILTYPE/require-end
+
+echo N > /debug/$FAILTYPE/task-filter
+echo 10 > /debug/$FAILTYPE/probability
+echo 100 > /debug/$FAILTYPE/interval
+echo -1 > /debug/$FAILTYPE/times
+echo 0 > /debug/$FAILTYPE/space
+echo 2 > /debug/$FAILTYPE/verbose
+echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
+echo 1 > /debug/$FAILTYPE/ignore-gfp-highmem
+echo 10 > /debug/$FAILTYPE/stacktrace-depth
+
+trap "echo 0 > /debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT
+
+echo "Injecting errors into the module $module... (interrupt to stop)"
+sleep 1000000
 
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 5c8695a..d05e624 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -41,28 +41,10 @@
 
 ---------------------------
 
-What:	RAW driver (CONFIG_RAW_DRIVER)
-When:	December 2005
-Why:	declared obsolete since kernel 2.6.3
-	O_DIRECT can be used instead
-Who:	Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
-What:	raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
-When:	June 2007
-Why:	Deprecated in favour of the more efficient and robust rawiso interface.
-	Affected are applications which use the deprecated part of libraw1394
-	(raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
-	raw1394_stop_iso_rcv) or bypass	libraw1394.
-Who:	Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
-
----------------------------
-
 What:	old NCR53C9x driver
 When:	October 2007
 Why:	Replaced by the much better esp_scsi driver.  Actual low-level
-	driver can ported over almost trivially.
+	driver can be ported over almost trivially.
 Who:	David Miller <davem@davemloft.net>
 	Christoph Hellwig <hch@lst.de>
 
@@ -70,6 +52,7 @@
 
 What:	Video4Linux API 1 ioctls and video_decoder.h from Video devices.
 When:	December 2006
+Files:	include/linux/video_decoder.h
 Why:	V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
 	series. The old API have lots of drawbacks and don't provide enough
 	means to work with all video and audio standards. The newer API is
@@ -103,6 +86,7 @@
 What:	remove EXPORT_SYMBOL(kernel_thread)
 When:	August 2006
 Files:	arch/*/kernel/*_ksyms.c
+Funcs:	kernel_thread
 Why:	kernel_thread is a low-level implementation detail.  Drivers should
         use the <linux/kthread.h> API instead which shields them from
 	implementation details and provides a higherlevel interface that
@@ -127,13 +111,6 @@
 
 ---------------------------
 
-What:  drivers depending on OSS_OBSOLETE_DRIVER
-When:  options in 2.6.20, code in 2.6.22
-Why:   OSS drivers with ALSA replacements
-Who:   Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
 What:	Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
 	(temporary transition config option provided until then)
 	The transition config option will also be removed at the same time.
@@ -204,28 +181,6 @@
 
 ---------------------------
 
-What:	ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver
-When:	December 2006
-Why:	Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are
-	functionally very much similar. They talk to ACPI in same way. Only
-	difference between them is the way they do frequency transitions.
-	One uses MSRs and the other one uses IO ports. Functionaliy of
-	speedstep_centrino with ACPI hooks is now merged into acpi-cpufreq.
-	That means one common driver will support all Intel Enhanced Speedstep
-	capable CPUs. That means less confusion over name of
-	speedstep-centrino driver (with that driver supposed to be used on
-	non-centrino platforms). That means less duplication of code and
-	less maintenance effort and no possibility of these two drivers
-	going out of sync.
-	Current users of speedstep_centrino with ACPI hooks are requested to
-	switch over to acpi-cpufreq driver. speedstep-centrino will continue
-	to work using older non-ACPI static table based scheme even after this
-	date.
-
-Who:	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
-
----------------------------
-
 What:	/sys/firmware/acpi/namespace
 When:	2.6.21
 Why:	The ACPI namespace is effectively the symbol list for
@@ -256,14 +211,6 @@
 
 ---------------------------
 
-What:   sk98lin network driver
-When:   July 2007
-Why:    In kernel tree version of driver is unmaintained. Sk98lin driver
-	replaced by the skge driver. 
-Who:    Stephen Hemminger <shemminger@osdl.org>
-
----------------------------
-
 What:	Compaq touchscreen device emulation
 When:	Oct 2007
 Files:	drivers/input/tsdev.c
@@ -278,25 +225,6 @@
 
 ---------------------------
 
-What:	Multipath cached routing support in ipv4
-When:	in 2.6.23
-Why:	Code was merged, then submitter immediately disappeared leaving
-	us with no maintainer and lots of bugs.  The code should not have
-	been merged in the first place, and many aspects of it's
-	implementation are blocking more critical core networking
-	development.  It's marked EXPERIMENTAL and no distribution
-	enables it because it cause obscure crashes due to unfixable bugs
-	(interfaces don't return errors so memory allocation can't be
-	handled, calling contexts of these interfaces make handling
-	errors impossible too because they get called after we've
-	totally commited to creating a route object, for example).
-	This problem has existed for years and no forward progress
-	has ever been made, and nobody steps up to try and salvage
-	this code, so we're going to finally just get rid of it.
-Who:	David S. Miller <davem@davemloft.net>
-
----------------------------
-
 What:	read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
 When:	December 2007
 Why:	These functions are a leftover from 2.4 times. They have several
@@ -321,6 +249,14 @@
 
 ---------------------------
 
+What:	'time' kernel boot parameter
+When:	January 2008
+Why:	replaced by 'printk.time=<value>' so that printk timestamps can be
+	enabled or disabled as needed
+Who:	Randy Dunlap <randy.dunlap@oracle.com>
+
+---------------------------
+
 What:  drivers depending on OSS_OBSOLETE
 When:  options in 2.6.23, code in 2.6.25
 Why:   obsolete OSS drivers
@@ -346,3 +282,31 @@
 
 ---------------------------
 
+What:	Legacy RTC drivers (under drivers/i2c/chips)
+When:	November 2007
+Why:	Obsolete. We have a RTC subsystem with better drivers.
+Who:	Jean Delvare <khali@linux-fr.org>
+
+---------------------------
+
+What:	iptables SAME target
+When:	1.1. 2008
+Files:	net/ipv4/netfilter/ipt_SAME.c, include/linux/netfilter_ipv4/ipt_SAME.h
+Why:	Obsolete for multiple years now, NAT core provides the same behaviour.
+	Unfixable broken wrt. 32/64 bit cleanness.
+Who:	Patrick McHardy <kaber@trash.net>
+
+---------------------------
+
+What: The arch/ppc and include/asm-ppc directories
+When: Jun 2008
+Why:  The arch/powerpc tree is the merged architecture for ppc32 and ppc64
+      platforms.  Currently there are efforts underway to port the remaining
+      arch/ppc platforms to the merged tree.  New submissions to the arch/ppc
+      tree have been frozen with the 2.6.22 kernel release and that tree will
+      remain in bug-fix only mode until its scheduled removal.  Platforms
+      that are not ported by June 2008 will be removed due to the lack of an
+      interested maintainer.
+Who:  linuxppc-dev@ozlabs.org
+
+---------------------------
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
index b34cdb5..d1b9825 100644
--- a/Documentation/filesystems/configfs/configfs.txt
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -238,6 +238,8 @@
 		struct config_group *(*make_group)(struct config_group *group,
 						   const char *name);
 		int (*commit_item)(struct config_item *item);
+		void (*disconnect_notify)(struct config_group *group,
+					  struct config_item *item);
 		void (*drop_item)(struct config_group *group,
 				  struct config_item *item);
 	};
@@ -268,6 +270,16 @@
 for the item to actually disappear from the subsystem's usage.  But it
 is gone from configfs.
 
+When drop_item() is called, the item's linkage has already been torn
+down.  It no longer has a reference on its parent and has no place in
+the item hierarchy.  If a client needs to do some cleanup before this
+teardown happens, the subsystem can implement the
+ct_group_ops->disconnect_notify() method.  The method is called after
+configfs has removed the item from the filesystem view but before the
+item is removed from its parent group.  Like drop_item(),
+disconnect_notify() is void and cannot fail.  Client subsystems should
+not drop any references here, as they still must do it in drop_item().
+
 A config_group cannot be removed while it still has child items.  This
 is implemented in the configfs rmdir(2) code.  ->drop_item() will not be
 called, as the item has not been dropped.  rmdir(2) will fail, as the
@@ -280,18 +292,18 @@
 
 	struct configfs_subsystem {
 		struct config_group	su_group;
-		struct semaphore	su_sem;
+		struct mutex		su_mutex;
 	};
 
 	int configfs_register_subsystem(struct configfs_subsystem *subsys);
 	void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
 
-	A subsystem consists of a toplevel config_group and a semaphore.
+	A subsystem consists of a toplevel config_group and a mutex.
 The group is where child config_items are created.  For a subsystem,
 this group is usually defined statically.  Before calling
 configfs_register_subsystem(), the subsystem must have initialized the
 group via the usual group _init() functions, and it must also have
-initialized the semaphore.
+initialized the mutex.
 	When the register call returns, the subsystem is live, and it
 will be visible via configfs.  At that point, mkdir(2) can be called and
 the subsystem must be ready for it.
@@ -303,7 +315,7 @@
 shows a trivial object displaying and storing an attribute, and a simple
 group creating and destroying these children.
 
-[Hierarchy Navigation and the Subsystem Semaphore]
+[Hierarchy Navigation and the Subsystem Mutex]
 
 There is an extra bonus that configfs provides.  The config_groups and
 config_items are arranged in a hierarchy due to the fact that they
@@ -314,19 +326,19 @@
 
 A subsystem can navigate the cg_children list and the ci_parent pointer
 to see the tree created by the subsystem.  This can race with configfs'
-management of the hierarchy, so configfs uses the subsystem semaphore to
+management of the hierarchy, so configfs uses the subsystem mutex to
 protect modifications.  Whenever a subsystem wants to navigate the
 hierarchy, it must do so under the protection of the subsystem
-semaphore.
+mutex.
 
-A subsystem will be prevented from acquiring the semaphore while a newly
+A subsystem will be prevented from acquiring the mutex while a newly
 allocated item has not been linked into this hierarchy.   Similarly, it
-will not be able to acquire the semaphore while a dropping item has not
+will not be able to acquire the mutex while a dropping item has not
 yet been unlinked.  This means that an item's ci_parent pointer will
 never be NULL while the item is in configfs, and that an item will only
 be in its parent's cg_children list for the same duration.  This allows
 a subsystem to trust ci_parent and cg_children while they hold the
-semaphore.
+mutex.
 
 [Item Aggregation Via symlink(2)]
 
@@ -386,6 +398,33 @@
 rmdir(2).  They also are not considered when rmdir(2) on the parent
 group is checking for children.
 
+[Dependant Subsystems]
+
+Sometimes other drivers depend on particular configfs items.  For
+example, ocfs2 mounts depend on a heartbeat region item.  If that
+region item is removed with rmdir(2), the ocfs2 mount must BUG or go
+readonly.  Not happy.
+
+configfs provides two additional API calls: configfs_depend_item() and
+configfs_undepend_item().  A client driver can call
+configfs_depend_item() on an existing item to tell configfs that it is
+depended on.  configfs will then return -EBUSY from rmdir(2) for that
+item.  When the item is no longer depended on, the client driver calls
+configfs_undepend_item() on it.
+
+These API cannot be called underneath any configfs callbacks, as
+they will conflict.  They can block and allocate.  A client driver
+probably shouldn't calling them of its own gumption.  Rather it should
+be providing an API that external subsystems call.
+
+How does this work?  Imagine the ocfs2 mount process.  When it mounts,
+it asks for a heartbeat region item.  This is done via a call into the
+heartbeat code.  Inside the heartbeat code, the region item is looked
+up.  Here, the heartbeat code calls configfs_depend_item().  If it
+succeeds, then heartbeat knows the region is safe to give to ocfs2.
+If it fails, it was being torn down anyway, and heartbeat can gracefully
+pass up an error.
+
 [Committable Items]
 
 NOTE: Committable items are currently unimplemented.
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example.c
index 2d6a14a..e56d492 100644
--- a/Documentation/filesystems/configfs/configfs_example.c
+++ b/Documentation/filesystems/configfs/configfs_example.c
@@ -453,7 +453,7 @@
 		subsys = example_subsys[i];
 
 		config_group_init(&subsys->su_group);
-		init_MUTEX(&subsys->su_sem);
+		mutex_init(&subsys->su_mutex);
 		ret = configfs_register_subsystem(subsys);
 		if (ret) {
 			printk(KERN_ERR "Error %d while registering subsystem %s\n",
diff --git a/Documentation/filesystems/directory-locking b/Documentation/filesystems/directory-locking
index d7099a9..ff7b611 100644
--- a/Documentation/filesystems/directory-locking
+++ b/Documentation/filesystems/directory-locking
@@ -1,5 +1,6 @@
 	Locking scheme used for directory operations is based on two
-kinds of locks - per-inode (->i_sem) and per-filesystem (->s_vfs_rename_sem).
+kinds of locks - per-inode (->i_mutex) and per-filesystem
+(->s_vfs_rename_mutex).
 
 	For our purposes all operations fall in 5 classes:
 
@@ -63,7 +64,7 @@
 attempt to acquire some lock and already holds at least one lock.  Let's
 consider the set of contended locks.  First of all, filesystem lock is
 not contended, since any process blocked on it is not holding any locks.
-Thus all processes are blocked on ->i_sem.
+Thus all processes are blocked on ->i_mutex.
 
 	Non-directory objects are not contended due to (3).  Thus link
 creation can't be a part of deadlock - it can't be blocked on source
diff --git a/Documentation/ecryptfs.txt b/Documentation/filesystems/ecryptfs.txt
similarity index 100%
rename from Documentation/ecryptfs.txt
rename to Documentation/filesystems/ecryptfs.txt
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index 5531694..dac45c9 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -107,7 +107,7 @@
 ---
 [informational]
 
-->link() callers hold ->i_sem on the object we are linking to.  Some of your
+->link() callers hold ->i_mutex on the object we are linking to.  Some of your
 problems might be over...
 
 ---
@@ -130,9 +130,9 @@
 ---
 [mandatory]
 
-->setattr() is called without BKL now.  Caller _always_ holds ->i_sem, so
-watch for ->i_sem-grabbing code that might be used by your ->setattr().
-Callers of notify_change() need ->i_sem now.
+->setattr() is called without BKL now.  Caller _always_ holds ->i_mutex, so
+watch for ->i_mutex-grabbing code that might be used by your ->setattr().
+Callers of notify_change() need ->i_mutex now.
 
 ---
 [recommended]
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 8756a07..ebffdff 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -171,7 +171,9 @@
 This shows you nearly the same information you would get if you viewed it with
 the ps  command.  In  fact,  ps  uses  the  proc  file  system  to  obtain its
 information. The  statm  file  contains  more  detailed  information about the
-process memory usage. Its seven fields are explained in Table 1-2.
+process memory usage. Its seven fields are explained in Table 1-2.  The stat
+file contains details information about the process itself.  Its fields are
+explained in Table 1-3.
 
 
 Table 1-2: Contents of the statm files (as of 2.6.8-rc3)
@@ -188,16 +190,65 @@
  dt       number of dirty pages			(always 0 on 2.6)
 ..............................................................................
 
+
+Table 1-3: Contents of the stat files (as of 2.6.22-rc3)
+..............................................................................
+ Field          Content
+  pid           process id
+  tcomm         filename of the executable
+  state         state (R is running, S is sleeping, D is sleeping in an
+                uninterruptible wait, Z is zombie, T is traced or stopped)
+  ppid          process id of the parent process
+  pgrp          pgrp of the process
+  sid           session id
+  tty_nr        tty the process uses
+  tty_pgrp      pgrp of the tty
+  flags         task flags
+  min_flt       number of minor faults
+  cmin_flt      number of minor faults with child's
+  maj_flt       number of major faults
+  cmaj_flt      number of major faults with child's
+  utime         user mode jiffies
+  stime         kernel mode jiffies
+  cutime        user mode jiffies with child's
+  cstime        kernel mode jiffies with child's
+  priority      priority level
+  nice          nice level
+  num_threads   number of threads
+  start_time    time the process started after system boot
+  vsize         virtual memory size
+  rss           resident set memory size
+  rsslim        current limit in bytes on the rss
+  start_code    address above which program text can run
+  end_code      address below which program text can run
+  start_stack   address of the start of the stack
+  esp           current value of ESP
+  eip           current value of EIP
+  pending       bitmap of pending signals (obsolete)
+  blocked       bitmap of blocked signals (obsolete)
+  sigign        bitmap of ignored signals (obsolete)
+  sigcatch      bitmap of catched signals (obsolete)
+  wchan         address where process went to sleep
+  0             (place holder)
+  0             (place holder)
+  exit_signal   signal to send to parent thread on exit
+  task_cpu      which CPU the task is scheduled on
+  rt_priority   realtime priority
+  policy        scheduling policy (man sched_setscheduler)
+  blkio_ticks   time spent waiting for block IO
+..............................................................................
+
+
 1.2 Kernel data
 ---------------
 
 Similar to  the  process entries, the kernel data files give information about
 the running kernel. The files used to obtain this information are contained in
-/proc and  are  listed  in Table 1-3. Not all of these will be present in your
+/proc and  are  listed  in Table 1-4. Not all of these will be present in your
 system. It  depends  on the kernel configuration and the loaded modules, which
 files are there, and which are missing.
 
-Table 1-3: Kernel info in /proc 
+Table 1-4: Kernel info in /proc
 ..............................................................................
  File        Content                                           
  apm         Advanced power management info                    
@@ -473,10 +524,10 @@
 
 More detailed  information  can  be  found  in  the  controller  specific
 subdirectories. These  are  named  ide0,  ide1  and  so  on.  Each  of  these
-directories contains the files shown in table 1-4.
+directories contains the files shown in table 1-5.
 
 
-Table 1-4: IDE controller info in  /proc/ide/ide? 
+Table 1-5: IDE controller info in  /proc/ide/ide?
 ..............................................................................
  File    Content                                 
  channel IDE channel (0 or 1)                    
@@ -486,11 +537,11 @@
 ..............................................................................
 
 Each device  connected  to  a  controller  has  a separate subdirectory in the
-controllers directory.  The  files  listed in table 1-5 are contained in these
+controllers directory.  The  files  listed in table 1-6 are contained in these
 directories.
 
 
-Table 1-5: IDE device information 
+Table 1-6: IDE device information
 ..............................................................................
  File             Content                                    
  cache            The cache                                  
@@ -1297,6 +1348,21 @@
 hugetlb_shm_group contains group id that is allowed to create SysV shared
 memory segment using hugetlb page.
 
+hugepages_treat_as_movable
+--------------------------
+
+This parameter is only useful when kernelcore= is specified at boot time to
+create ZONE_MOVABLE for pages that may be reclaimed or migrated. Huge pages
+are not movable so are not normally allocated from ZONE_MOVABLE. A non-zero
+value written to hugepages_treat_as_movable allows huge pages to be allocated
+from ZONE_MOVABLE.
+
+Once enabled, the ZONE_MOVABLE is treated as an area of memory the huge
+pages pool can easily grow or shrink within. Assuming that applications are
+not running that mlock() a lot of memory, it is likely the huge pages pool
+can grow to the size of ZONE_MOVABLE by repeatedly entering the desired value
+into nr_hugepages and triggering page reclaim.
+
 laptop_mode
 -----------
 
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 6dd0508..145e440 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -94,10 +94,10 @@
 
 Note that trying to mount a tmpfs with an mpol option will fail if the
 running kernel does not support NUMA; and will fail if its nodelist
-specifies a node >= MAX_NUMNODES.  If your system relies on that tmpfs
-being mounted, but from time to time runs a kernel built without NUMA
-capability (perhaps a safe recovery kernel), or configured to support
-fewer nodes, then it is advisable to omit the mpol option from automatic
+specifies a node which is not online.  If your system relies on that
+tmpfs being mounted, but from time to time runs a kernel built without
+NUMA capability (perhaps a safe recovery kernel), or with fewer nodes
+online, then it is advisable to omit the mpol option from automatic
 mount options.  It can be added later, when the tmpfs is already mounted
 on MountPoint, by 'mount -o remount,mpol=Policy:NodeList MountPoint'.
 
@@ -121,4 +121,4 @@
 Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
 Updated:
-   Hugh Dickins <hugh@veritas.com>, 19 February 2006
+   Hugh Dickins <hugh@veritas.com>, 4 June 2007
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index a47cc81..045f3e0 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -3,7 +3,7 @@
 
 	Original author: Richard Gooch <rgooch@atnf.csiro.au>
 
-		  Last updated on October 28, 2005
+		  Last updated on June 24, 2007.
 
   Copyright (C) 1999 Richard Gooch
   Copyright (C) 2005 Pekka Enberg
@@ -107,7 +107,7 @@
 struct file_system_type
 -----------------------
 
-This describes the filesystem. As of kernel 2.6.13, the following
+This describes the filesystem. As of kernel 2.6.22, the following
 members are defined:
 
 struct file_system_type {
@@ -119,6 +119,8 @@
         struct module *owner;
         struct file_system_type * next;
         struct list_head fs_supers;
+	struct lock_class_key s_lock_key;
+	struct lock_class_key s_umount_key;
 };
 
   name: the name of the filesystem type, such as "ext2", "iso9660",
@@ -137,11 +139,12 @@
 
   next: for internal VFS use: you should initialize this to NULL
 
+  s_lock_key, s_umount_key: lockdep-specific
+
 The get_sb() method has the following arguments:
 
-  struct super_block *sb: the superblock structure. This is partially
-	initialized by the VFS and the rest must be initialized by the
-	get_sb() method
+  struct file_system_type *fs_type: decribes the filesystem, partly initialized
+  	by the specific filesystem code
 
   int flags: mount flags
 
@@ -150,12 +153,13 @@
   void *data: arbitrary mount options, usually comes as an ASCII
 	string
 
-  int silent: whether or not to be silent on error
+  struct vfsmount *mnt: a vfs-internal representation of a mount point
 
 The get_sb() method must determine if the block device specified
-in the superblock contains a filesystem of the type the method
-supports. On success the method returns the superblock pointer, on
-failure it returns NULL.
+in the dev_name and fs_type contains a filesystem of the type the method
+supports. If it succeeds in opening the named block device, it initializes a
+struct super_block descriptor for the filesystem contained by the block device.
+On failure it returns an error.
 
 The most interesting member of the superblock structure that the
 get_sb() method fills in is the "s_op" field. This is a pointer to
@@ -193,7 +197,7 @@
 -----------------------
 
 This describes how the VFS can manipulate the superblock of your
-filesystem. As of kernel 2.6.13, the following members are defined:
+filesystem. As of kernel 2.6.22, the following members are defined:
 
 struct super_operations {
         struct inode *(*alloc_inode)(struct super_block *sb);
@@ -216,8 +220,6 @@
         void (*clear_inode) (struct inode *);
         void (*umount_begin) (struct super_block *);
 
-        void (*sync_inodes) (struct super_block *sb,
-                                struct writeback_control *wbc);
         int (*show_options)(struct seq_file *, struct vfsmount *);
 
         ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
@@ -300,9 +302,6 @@
 
   umount_begin: called when the VFS is unmounting a filesystem.
 
-  sync_inodes: called when the VFS is writing out dirty data associated with
-  	a superblock.
-
   show_options: called by the VFS to show mount options for /proc/<pid>/mounts.
 
   quota_read: called by the VFS to read from filesystem quota file.
@@ -324,7 +323,7 @@
 -----------------------
 
 This describes how the VFS can manipulate an inode in your
-filesystem. As of kernel 2.6.13, the following members are defined:
+filesystem. As of kernel 2.6.22, the following members are defined:
 
 struct inode_operations {
 	int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
@@ -348,6 +347,7 @@
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
+	void (*truncate_range)(struct inode *, loff_t, loff_t);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -444,6 +444,9 @@
   removexattr: called by the VFS to remove an extended attribute from
   	a file. This method is called by removexattr(2) system call.
 
+  truncate_range: a method provided by the underlying filesystem to truncate a
+  	range of blocks , i.e. punch a hole somewhere in a file.
+
 
 The Address Space Object
 ========================
@@ -522,7 +525,7 @@
 -------------------------------
 
 This describes how the VFS can manipulate mapping of a file to page cache in
-your filesystem. As of kernel 2.6.16, the following members are defined:
+your filesystem. As of kernel 2.6.22, the following members are defined:
 
 struct address_space_operations {
 	int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -543,6 +546,7 @@
 			int);
 	/* migrate the contents of a page to the specified target */
 	int (*migratepage) (struct page *, struct page *);
+	int (*launder_page) (struct page *);
 };
 
   writepage: called by the VM to write a dirty page to backing store.
@@ -689,6 +693,10 @@
 	transfer any private data across and update any references
         that it has to the page.
 
+  launder_page: Called before freeing a page - it writes back the dirty page. To
+  	prevent redirtying the page, it is kept locked during the whole
+	operation.
+
 The File Object
 ===============
 
@@ -699,9 +707,10 @@
 ----------------------
 
 This describes how the VFS can manipulate an open file. As of kernel
-2.6.17, the following members are defined:
+2.6.22, the following members are defined:
 
 struct file_operations {
+	struct module *owner;
 	loff_t (*llseek) (struct file *, loff_t, int);
 	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
 	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
@@ -728,10 +737,8 @@
 	int (*check_flags)(int);
 	int (*dir_notify)(struct file *filp, unsigned long arg);
 	int (*flock) (struct file *, int, struct file_lock *);
-	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned 
-int);
-	ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned  
-int);
+	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int);
+	ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int);
 };
 
 Again, all methods are called without any locks being held, unless
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index e9cc8bb..c3480aa 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -1,7 +1,7 @@
 
  request_firmware() hotplug interface:
  ------------------------------------
-	Copyright (C) 2003 Manuel Estrada Sainz <ranty@debian.org>
+	Copyright (C) 2003 Manuel Estrada Sainz
 
  Why:
  ---
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index 87feccd..6865cbe 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -1,7 +1,7 @@
 /*
  * firmware_sample_driver.c -
  *
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
  *
  * Sample code on how to use request_firmware() from drivers.
  *
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
index 9e1b0e4..fba943a 100644
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c
@@ -1,7 +1,7 @@
 /*
  * firmware_sample_firmware_class.c -
  *
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
  *
  * NOTE: This is just a probe of concept, if you think that your driver would
  * be well served by this mechanism please contact me first.
@@ -19,7 +19,7 @@
 #include <linux/firmware.h>
 
 
-MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
+MODULE_AUTHOR("Manuel Estrada Sainz");
 MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
 MODULE_LICENSE("GPL");
 
@@ -78,6 +78,7 @@
 			 firmware_loading_show, firmware_loading_store);
 
 static ssize_t firmware_data_read(struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
 				  char *buffer, loff_t offset, size_t count)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
@@ -88,6 +89,7 @@
 	return count;
 }
 static ssize_t firmware_data_write(struct kobject *kobj,
+				   struct bin_attribute *bin_attr,
 				   char *buffer, loff_t offset, size_t count)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
index 27f782e..20d368c 100644
--- a/Documentation/hrtimer/timer_stats.txt
+++ b/Documentation/hrtimer/timer_stats.txt
@@ -2,9 +2,10 @@
 ------------------------------------
 
 timer_stats is a debugging facility to make the timer (ab)usage in a Linux
-system visible to kernel and userspace developers. It is not intended for
-production usage as it adds significant overhead to the (hr)timer code and the
-(hr)timer data structures.
+system visible to kernel and userspace developers. If enabled in the config
+but not used it has almost zero runtime overhead, and a relatively small
+data structure overhead. Even if collection is enabled runtime all the
+locking is per-CPU and lookup is hashed.
 
 timer_stats should be used by kernel and userspace developers to verify that
 their code does not make unduly use of timers. This helps to avoid unnecessary
@@ -66,3 +67,7 @@
 
     Thomas, Ingo
 
+Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
+timer will appear as follows
+  10D,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index c34f0db..fe6406f 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -5,8 +5,8 @@
     '810' and '810E' chipsets)
   * Intel 82801BA (ICH2 - part of the '815E' chipset)
   * Intel 82801CA/CAM (ICH3)
-  * Intel 82801DB (ICH4) (HW PEC supported, 32 byte buffer not supported)
-  * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
+  * Intel 82801DB (ICH4) (HW PEC supported)
+  * Intel 82801EB/ER (ICH5) (HW PEC supported)
   * Intel 6300ESB
   * Intel 82801FB/FR/FW/FRW (ICH6)
   * Intel 82801G (ICH7)
diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
index 7cbe43f..fa0c786 100644
--- a/Documentation/i2c/busses/i2c-piix4
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -6,7 +6,7 @@
     Datasheet: Publicly available at the Intel website
   * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
     Datasheet: Only available via NDA from ServerWorks
-  * ATI IXP200, IXP300, IXP400 and SB600 southbridges
+  * ATI IXP200, IXP300, IXP400, SB600 and SB700 southbridges
     Datasheet: Not publicly available
   * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
     Datasheet: Publicly available at the SMSC website http://www.smsc.com
diff --git a/Documentation/i2c/busses/i2c-taos-evm b/Documentation/i2c/busses/i2c-taos-evm
new file mode 100644
index 0000000..9146e33
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-taos-evm
@@ -0,0 +1,46 @@
+Kernel driver i2c-taos-evm
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+This is a driver for the evaluation modules for TAOS I2C/SMBus chips.
+The modules include an SMBus master with limited capabilities, which can
+be controlled over the serial port. Virtually all evaluation modules
+are supported, but a few lines of code need to be added for each new
+module to instantiate the right I2C chip on the bus. Obviously, a driver
+for the chip in question is also needed.
+
+Currently supported devices are:
+
+* TAOS TSL2550 EVM
+
+For addtional information on TAOS products, please see
+  http://www.taosinc.com/
+
+
+Using this driver
+-----------------
+
+In order to use this driver, you'll need the serport driver, and the
+inputattach tool, which is part of the input-utils package. The following
+commands will tell the kernel that you have a TAOS EVM on the first
+serial port:
+
+# modprobe serport
+# inputattach --taos-evm /dev/ttyS0
+
+
+Technical details
+-----------------
+
+Only 4 SMBus transaction types are supported by the TAOS evaluation
+modules:
+* Receive Byte
+* Send Byte
+* Read Byte
+* Write Byte
+
+The communication protocol is text-based and pretty simple. It is
+described in a PDF document on the CD which comes with the evaluation
+module. The communication is rather slow, because the serial port has
+to operate at 1200 bps. However, I don't think this is a big concern in
+practice, as these modules are meant for evaluation and testing only.
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
index 96fec56..a0cd8af 100644
--- a/Documentation/i2c/chips/max6875
+++ b/Documentation/i2c/chips/max6875
@@ -99,7 +99,7 @@
 
   or
 
-  count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
+  count = i2c_smbus_read_i2c_block_data(fd, 0x84, 16, buffer);
 
 The block read should read 16 bytes.
 0x84 is the block read command.
diff --git a/Documentation/i2c/chips/x1205 b/Documentation/i2c/chips/x1205
deleted file mode 100644
index 09407c9..0000000
--- a/Documentation/i2c/chips/x1205
+++ /dev/null
@@ -1,38 +0,0 @@
-Kernel driver x1205
-===================
-
-Supported chips:
-  * Xicor X1205 RTC
-    Prefix: 'x1205'
-    Addresses scanned: none
-    Datasheet: http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
-
-Authors:
-	Karen Spearel <kas11@tampabay.rr.com>,
-	Alessandro Zummo <a.zummo@towertech.it>
-
-Description
------------
-
-This module aims to provide complete access to the Xicor X1205 RTC.
-Recently Xicor has merged with Intersil, but the chip is
-still sold under the Xicor brand.
-
-This chip is located at address 0x6f and uses a 2-byte register addressing.
-Two bytes need to be written to read a single register, while most
-other chips just require one and take the second one as the data
-to be written. To prevent corrupting unknown chips, the user must
-explicitely set the probe parameter.
-
-example:
-
-modprobe x1205 probe=0,0x6f
-
-The module supports one more option, hctosys, which is used to set the
-software clock from the x1205. On systems where the x1205 is the
-only hardware rtc, this parameter could be used to achieve a correct
-date/time earlier in the system boot sequence.
-
-example:
-
-modprobe x1205 probe=0,0x6f hctosys=1
diff --git a/Documentation/i2c/summary b/Documentation/i2c/summary
index aea60bf..003c731 100644
--- a/Documentation/i2c/summary
+++ b/Documentation/i2c/summary
@@ -67,7 +67,6 @@
 Algorithm drivers
 -----------------
 
-i2c-algo-8xx:    An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT)
 i2c-algo-bit:    A bit-banging algorithm
 i2c-algo-pcf:    A PCF 8584 style algorithm
 i2c-algo-ibm_ocp: An algorithm for the I2C device in IBM 4xx processors (NOT BUILT BY DEFAULT)
@@ -81,6 +80,5 @@
 i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit)
 i2c-adap-ibm_ocp: IBM 4xx processor I2C device (uses i2c-algo-ibm_ocp) (NOT BUILT BY DEFAULT)
 i2c-pport:       Primitive parallel port adapter (uses i2c-algo-bit)
-i2c-rpx:         RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT)
 i2c-velleman:    Velleman K8000 parallel port adapter (uses i2c-algo-bit)
 
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 3d8d36b..2c17003 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -571,7 +571,7 @@
                                         u8 command, u8 length,
                                         u8 *values);
   extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
-                                           u8 command, u8 *values);
+                                           u8 command, u8 length, u8 *values);
 
 These ones were removed in Linux 2.6.10 because they had no users, but could
 be added back later if needed:
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
index 66fa67f..35985b3 100644
--- a/Documentation/i386/boot.txt
+++ b/Documentation/i386/boot.txt
@@ -2,7 +2,7 @@
 		     ----------------------------
 
 		    H. Peter Anvin <hpa@zytor.com>
-			Last update 2007-05-16
+			Last update 2007-05-23
 
 On the i386 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
@@ -202,6 +202,8 @@
 nonstandard address should fill in the fields marked (reloc); other
 boot loaders can ignore those fields.
 
+The byte order of all fields is littleendian (this is x86, after all.)
+
 Field name:	setup_secs
 Type:		read
 Offset/size:	0x1f1/1
@@ -280,14 +282,16 @@
 Offset/size:	0x206/2
 Protocol:	2.00+
 
-  Contains the boot protocol version, e.g. 0x0204 for version 2.04.
+  Contains the boot protocol version, in (major << 8)+minor format,
+  e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version
+  10.17.
 
 Field name:	readmode_swtch
 Type:		modify (optional)
 Offset/size:	0x208/4
 Protocol:	2.00+
 
-  Boot loader hook (see separate chapter.)
+  Boot loader hook (see ADVANCED BOOT LOADER HOOKS below.)
 
 Field name:	start_sys
 Type:		read
@@ -304,10 +308,17 @@
   If set to a nonzero value, contains a pointer to a NUL-terminated
   human-readable kernel version number string, less 0x200.  This can
   be used to display the kernel version to the user.  This value
-  should be less than (0x200*setup_sects).  For example, if this value
-  is set to 0x1c00, the kernel version number string can be found at
-  offset 0x1e00 in the kernel file.  This is a valid value if and only
-  if the "setup_sects" field contains the value 14 or higher.
+  should be less than (0x200*setup_sects).
+
+  For example, if this value is set to 0x1c00, the kernel version
+  number string can be found at offset 0x1e00 in the kernel file.
+  This is a valid value if and only if the "setup_sects" field
+  contains the value 15 or higher, as:
+
+	0x1c00  < 15*0x200 (= 0x1e00) but
+	0x1c00 >= 14*0x200 (= 0x1c00)
+
+	0x1c00 >> 9 = 14, so the minimum value for setup_secs is 15.
 
 Field name:	type_of_loader
 Type:		write (obligatory)
@@ -377,7 +388,7 @@
 
   This field can be modified for two purposes:
 
-  1. as a boot loader hook (see separate chapter.)
+  1. as a boot loader hook (see ADVANCED BOOT LOADER HOOKS below.)
 
   2. if a bootloader which does not install a hook loads a
      relocatable kernel at a nonstandard address it will have to modify
@@ -715,7 +726,7 @@
 a demand-loaded module!
 
 
-**** ADVANCED BOOT TIME HOOKS
+**** ADVANCED BOOT LOADER HOOKS
 
 If the boot loader runs in a particularly hostile environment (such as
 LOADLIN, which runs under DOS) it may be impossible to follow the
@@ -740,4 +751,5 @@
 	set them up to BOOT_DS (0x18) yourself.
 
 	After completing your hook, you should jump to the address
-	that was in this field before your boot loader overwrote it.
+	that was in this field before your boot loader overwrote it
+	(relocated, if appropriate.)
diff --git a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt
index c04a421..75b3680 100644
--- a/Documentation/i386/zero-page.txt
+++ b/Documentation/i386/zero-page.txt
@@ -37,6 +37,7 @@
 0x1d0	unsigned long	EFI memory descriptor map pointer
 0x1d4	unsigned long	EFI memory descriptor map size
 0x1e0	unsigned long	ALT_MEM_K, alternative mem check, in Kb
+0x1e4	unsigned long	Scratch field for the kernel setup code
 0x1e8	char		number of entries in E820MAP (below)
 0x1e9	unsigned char	number of entries in EDDBUF (below)
 0x1ea	unsigned char	number of entries in EDD_MBR_SIG_BUFFER (below)
diff --git a/Documentation/ia64/aliasing-test.c b/Documentation/ia64/aliasing-test.c
index 3153167..773a814 100644
--- a/Documentation/ia64/aliasing-test.c
+++ b/Documentation/ia64/aliasing-test.c
@@ -19,6 +19,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <linux/pci.h>
 
 int sum;
 
@@ -34,13 +35,19 @@
 		return -1;
 	}
 
+	if (fnmatch("/proc/bus/pci/*", path, 0) == 0) {
+		rc = ioctl(fd, PCIIOC_MMAP_IS_MEM);
+		if (rc == -1)
+			perror("PCIIOC_MMAP_IS_MEM ioctl");
+	}
+
 	addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
 	if (addr == MAP_FAILED)
 		return 1;
 
 	if (touch) {
 		c = (int *) addr;
-		while (c < (int *) (offset + length))
+		while (c < (int *) (addr + length))
 			sum += *c++;
 	}
 
@@ -54,7 +61,7 @@
 	return 0;
 }
 
-int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
+int scan_tree(char *path, char *file, off_t offset, size_t length, int touch)
 {
 	struct dirent **namelist;
 	char *name, *path2;
@@ -93,7 +100,7 @@
 		} else {
 			r = lstat(path2, &buf);
 			if (r == 0 && S_ISDIR(buf.st_mode)) {
-				rc = scan_sysfs(path2, file, offset, length, touch);
+				rc = scan_tree(path2, file, offset, length, touch);
 				if (rc < 0)
 					return rc;
 			}
@@ -197,7 +204,7 @@
 	return rc;
 }
 
-main()
+int main()
 {
 	int rc;
 
@@ -238,10 +245,15 @@
 	else
 		fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
 
-	scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
-	scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
-	scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
-	scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
+	scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
+	scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
+	scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
+	scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
 
 	scan_rom("/sys/devices", "rom");
+
+	scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1);
+	scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
+	scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
+	scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
 }
diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt
index 9a431a7..aa3e953 100644
--- a/Documentation/ia64/aliasing.txt
+++ b/Documentation/ia64/aliasing.txt
@@ -112,6 +112,18 @@
 
 	The /dev/mem mmap constraints apply.
 
+    mmap of /proc/bus/pci/.../??.?
+
+    	This is an MMIO mmap of PCI functions, which additionally may or
+	may not be requested as using the WC attribute.
+
+	If WC is requested, and the region in kern_memmap is either WC
+	or UC, and the EFI memory map designates the region as WC, then
+	the WC mapping is allowed.
+
+	Otherwise, the user mapping must use the same attribute as the
+	kernel mapping.
+
     read/write of /dev/mem
 
 	This uses copy_from_user(), which implicitly uses a kernel
diff --git a/Documentation/initrd.txt b/Documentation/initrd.txt
index 15f1b35..d3dc505 100644
--- a/Documentation/initrd.txt
+++ b/Documentation/initrd.txt
@@ -27,16 +27,20 @@
   1) the boot loader loads the kernel and the initial RAM disk
   2) the kernel converts initrd into a "normal" RAM disk and
      frees the memory used by initrd
-  3) initrd is mounted read-write as root
-  4) /linuxrc is executed (this can be any valid executable, including
+  3) if the root device is not /dev/ram0, the old (deprecated)
+     change_root procedure is followed. see the "Obsolete root change
+     mechanism" section below.
+  4) root device is mounted. if it is /dev/ram0, the initrd image is
+     then mounted as root
+  5) /sbin/init is executed (this can be any valid executable, including
      shell scripts; it is run with uid 0 and can do basically everything
-     init can do)
-  5) linuxrc mounts the "real" root file system
-  6) linuxrc places the root file system at the root directory using the
+     init can do).
+  6) init mounts the "real" root file system
+  7) init places the root file system at the root directory using the
      pivot_root system call
-  7) the usual boot sequence (e.g. invocation of /sbin/init) is performed
-     on the root file system
-  8) the initrd file system is removed
+  8) init execs the /sbin/init on the new root filesystem, performing
+     the usual boot sequence
+  9) the initrd file system is removed
 
 Note that changing the root directory does not involve unmounting it.
 It is therefore possible to leave processes running on initrd during that
@@ -70,7 +74,7 @@
   root=/dev/ram0
 
     initrd is mounted as root, and the normal boot procedure is followed,
-    with the RAM disk still mounted as root.
+    with the RAM disk mounted as root.
 
 Compressed cpio images
 ----------------------
@@ -137,11 +141,11 @@
     # mkdir /mnt/dev
     # mknod /mnt/dev/console c 5 1
  5) copy all the files that are needed to properly use the initrd
-    environment. Don't forget the most important file, /linuxrc
-    Note that /linuxrc's permissions must include "x" (execute).
+    environment. Don't forget the most important file, /sbin/init
+    Note that /sbin/init's permissions must include "x" (execute).
  6) correct operation the initrd environment can frequently be tested
     even without rebooting with the command
-    # chroot /mnt /linuxrc
+    # chroot /mnt /sbin/init
     This is of course limited to initrds that do not interfere with the
     general system state (e.g. by reconfiguring network interfaces,
     overwriting mounted devices, trying to start already running demons,
@@ -154,7 +158,7 @@
     # gzip -9 initrd
 
 For experimenting with initrd, you may want to take a rescue floppy and
-only add a symbolic link from /linuxrc to /bin/sh. Alternatively, you
+only add a symbolic link from /sbin/init to /bin/sh. Alternatively, you
 can try the experimental newlib environment [2] to create a small
 initrd.
 
@@ -163,15 +167,14 @@
 with an older mechanism, the following boot command line parameters
 have to be given:
 
-  root=/dev/ram0 init=/linuxrc rw
+  root=/dev/ram0 rw
 
 (rw is only necessary if writing to the initrd file system.)
 
 With LOADLIN, you simply execute
 
      LOADLIN <kernel> initrd=<disk_image>
-e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0
-       init=/linuxrc rw
+e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 rw
 
 With LILO, you add the option INITRD=<path> to either the global section
 or to the section of the respective kernel in /etc/lilo.conf, and pass
@@ -179,7 +182,7 @@
 
   image = /bzImage
     initrd = /boot/initrd.gz
-    append = "root=/dev/ram0 init=/linuxrc rw"
+    append = "root=/dev/ram0 rw"
 
 and run /sbin/lilo
 
@@ -191,7 +194,7 @@
 Changing the root device
 ------------------------
 
-When finished with its duties, linuxrc typically changes the root device
+When finished with its duties, init typically changes the root device
 and proceeds with starting the Linux system on the "real" root device.
 
 The procedure involves the following steps:
@@ -217,7 +220,7 @@
 # mkdir initrd
 # pivot_root . initrd
 
-Now, the linuxrc process may still access the old root via its
+Now, the init process may still access the old root via its
 executable, shared libraries, standard input/output/error, and its
 current root directory. All these references are dropped by the
 following command:
@@ -249,10 +252,6 @@
 It is also possible to use initrd with an NFS-mounted root, see the
 pivot_root(8) man page for details.
 
-Note: if linuxrc or any program exec'ed from it terminates for some
-reason, the old change_root mechanism is invoked (see section "Obsolete
-root change mechanism").
-
 
 Usage scenarios
 ---------------
@@ -264,15 +263,15 @@
   1) system boots from floppy or other media with a minimal kernel
      (e.g. support for RAM disks, initrd, a.out, and the Ext2 FS) and
      loads initrd
-  2) /linuxrc determines what is needed to (1) mount the "real" root FS
+  2) /sbin/init determines what is needed to (1) mount the "real" root FS
      (i.e. device type, device drivers, file system) and (2) the
      distribution media (e.g. CD-ROM, network, tape, ...). This can be
      done by asking the user, by auto-probing, or by using a hybrid
      approach.
-  3) /linuxrc loads the necessary kernel modules
-  4) /linuxrc creates and populates the root file system (this doesn't
+  3) /sbin/init loads the necessary kernel modules
+  4) /sbin/init creates and populates the root file system (this doesn't
      have to be a very usable system yet)
-  5) /linuxrc invokes pivot_root to change the root file system and
+  5) /sbin/init invokes pivot_root to change the root file system and
      execs - via chroot - a program that continues the installation
   6) the boot loader is installed
   7) the boot loader is configured to load an initrd with the set of
@@ -291,7 +290,7 @@
 such cases, it is desirable to generate only a small set of kernels
 (ideally only one) and to keep the system-specific part of configuration
 information as small as possible. In this case, a common initrd could be
-generated with all the necessary modules. Then, only /linuxrc or a file
+generated with all the necessary modules. Then, only /sbin/init or a file
 read by it would have to be different.
 
 A third scenario are more convenient recovery disks, because information
@@ -337,6 +336,25 @@
 the new, supported mechanism is called "pivot_root".
 
 
+Mixed change_root and pivot_root mechanism
+------------------------------------------
+
+In case you did not want to use root=/dev/ram0 to trig the pivot_root mechanism,
+you may create both /linuxrc and /sbin/init in your initrd image.
+
+/linuxrc would contain only the following:
+
+#! /bin/sh
+mount -n -t proc proc /proc
+echo 0x0100 >/proc/sys/kernel/real-root-dev
+umount -n /proc
+
+Once linuxrc exited, the kernel would mount again your initrd as root,
+this time executing /sbin/init. Again, it would be duty of this init
+to build the right environment (maybe using the root= device passed on
+the cmdline) before the final execution of the real /sbin/init.
+
+
 Resources
 ---------
 
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index 3de7d37..5c7fbf9 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -67,7 +67,7 @@
 0x00	00-1F	linux/wavefront.h	conflict!
 0x02	all	linux/fd.h
 0x03	all	linux/hdreg.h
-0x04	all	linux/umsdos_fs.h
+0x04	D2-DC	linux/umsdos_fs.h	Dead since 2.6.11, but don't reuse these.
 0x06	all	linux/lp.h
 0x09	all	linux/md.h
 0x12	all	linux/fs.h
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 09220a1..9a54148 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -34,7 +34,6 @@
 	APIC	APIC support is enabled.
 	APM	Advanced Power Management support is enabled.
 	AX25	Appropriate AX.25 support is enabled.
-	CD	Appropriate CD support is enabled.
 	DRM	Direct Rendering Management support is enabled.
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
 	EFI	EFI Partitioning (GPT) is enabled
@@ -170,7 +169,10 @@
 	acpi_os_name=	[HW,ACPI] Tell ACPI BIOS the name of the OS
 			Format: To spoof as Windows 98: ="Microsoft Windows"
 
-	acpi_osi=	[HW,ACPI] empty param disables _OSI
+	acpi_osi=	[HW,ACPI] Modify list of supported OS interface strings
+			acpi_osi="string1"	# add string1 -- only one string
+			acpi_osi="!string2"	# remove built-in string2
+			acpi_osi=		# disable all strings
 
 	acpi_serialize	[HW,ACPI] force serialization of AML methods
 
@@ -220,11 +222,6 @@
 
 	acpi_fake_ecdt	[HW,ACPI] Workaround failure due to BIOS lacking ECDT
 
-	acpi_generic_hotkey [HW,ACPI]
-			Allow consolidated generic hotkey driver to
-			override platform specific driver.
-			See also Documentation/acpi-hotkey.txt.
-
 	acpi_pm_good	[IA-32,X86-64]
 			Override the pmtimer bug detection: force the kernel
 			to assume that this machine's pmtimer latches its value
@@ -240,16 +237,9 @@
 			Disable PIN 1 of APIC timer
 			Can be useful to work around chipset bugs.
 
-	ad1816=		[HW,OSS]
-			Format: <io>,<irq>,<dma>,<dma2>
-			See also Documentation/sound/oss/AD1816.
-
 	ad1848=		[HW,OSS]
 			Format: <io>,<irq>,<dma>,<dma2>,<type>
 
-	adlib=		[HW,OSS]
-			Format: <io>
-
 	advansys=	[HW,SCSI]
 			See header of drivers/scsi/advansys.c.
 
@@ -328,9 +318,6 @@
 
 	autotest	[IA64]
 
-	aztcd=		[HW,CD] Aztech CD268 CDROM driver
-			Format: <io>,0x79 (?)
-
 	baycom_epp=	[HW,AX25]
 			Format: <io>,<mode>
 
@@ -373,10 +360,6 @@
 			possible to determine what the correct size should be.
 			This option provides an override for these situations.
 
-	cdu31a=		[HW,CD]
-			Format: <io>,<irq>[,PAS]
-			See header of drivers/cdrom/cdu31a.c.
-
 	chandev=	[HW,NET] Generic channel device initialisation
 
 	checkreqprot	[SELINUX] Set initial checkreqprot flag value.
@@ -396,6 +379,26 @@
 			clocksource is not available, it defaults to PIT.
 			Format: { pit | tsc | cyclone | pmtmr }
 
+	clocksource=	[GENERIC_TIME] Override the default clocksource
+			Format: <string>
+			Override the default clocksource and use the clocksource
+			with the name specified.
+			Some clocksource names to choose from, depending on
+			the platform:
+			[all] jiffies (this is the base, fallback clocksource)
+			[ACPI] acpi_pm
+			[ARM] imx_timer1,OSTS,netx_timer,mpu_timer2,
+				pxa_timer,timer3,32k_counter,timer0_1
+			[AVR32] avr32
+			[IA-32] pit,hpet,tsc,vmi-timer;
+				scx200_hrt on Geode; cyclone on IBM x440
+			[MIPS] MIPS
+			[PARISC] cr16
+			[S390] tod
+			[SH] SuperH
+			[SPARC64] tick
+			[X86-64] hpet,tsc
+
 	code_bytes	[IA32] How many bytes of object code to print in an
 			oops report.
 			Range: 0 - 8192
@@ -410,9 +413,6 @@
 	hpet=		[IA-32,HPET] option to disable HPET and use PIT.
 			Format: disable
 
-	cm206=		[HW,CD]
-			Format: { auto | [<io>,][<irq>] }
-
 	com20020=	[HW,NET] ARCnet - COM20020 chipset
 			Format:
 			<io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
@@ -444,13 +444,20 @@
 			Documentation/networking/netconsole.txt for an
 			alternative.
 
-		uart,io,<addr>[,options]
-		uart,mmio,<addr>[,options]
+		uart[8250],io,<addr>[,options]
+		uart[8250],mmio,<addr>[,options]
 			Start an early, polled-mode console on the 8250/16550
 			UART at the specified I/O port or MMIO address,
 			switching to the matching ttyS device later.  The
 			options are the same as for ttyS, above.
 
+	earlycon=	[KNL] Output early console device and options.
+		uart[8250],io,<addr>[,options]
+		uart[8250],mmio,<addr>[,options]
+			Start an early, polled-mode console on the 8250/16550
+			UART at the specified I/O port or MMIO address.
+			The options are the same as for ttyS, above.
+
 	cpcihp_generic=	[HW,PCI] Generic port I/O CompactPCI driver
 			Format:
 			<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
@@ -642,9 +649,6 @@
 	gpt		[EFI] Forces disk with valid GPT signature but
 			invalid Protective MBR to be treated as GPT.
 
-	gscd=		[HW,CD]
-			Format: <io>
-
 	gvp11=		[HW,SCSI]
 
 	hashdist=	[KNL,NUMA] Large hashes allocated during boot
@@ -808,14 +812,37 @@
 			tasks in the system -- can cause problems and
 			suboptimal load balancer performance.
 
-	isp16=		[HW,CD]
-			Format: <io>,<irq>,<dma>,<setup>
-
 	iucv=		[HW,NET]
 
 	js=		[HW,JOY] Analog joystick
 			See Documentation/input/joystick.txt.
 
+	kernelcore=nn[KMG]	[KNL,IA-32,IA-64,PPC,X86-64] This parameter
+			specifies the amount of memory usable by the kernel
+			for non-movable allocations.  The requested amount is
+			spread evenly throughout all nodes in the system. The
+			remaining memory in each node is used for Movable
+			pages. In the event, a node is too small to have both
+			kernelcore and Movable pages, kernelcore pages will
+			take priority and other nodes will have a larger number
+			of kernelcore pages.  The Movable zone is used for the
+			allocation of pages that may be reclaimed or moved
+			by the page migration subsystem.  This means that
+			HugeTLB pages may not be allocated from this zone.
+			Note that allocations like PTEs-from-HighMem still
+			use the HighMem zone if it exists, and the Normal
+			zone if it does not.
+
+	movablecore=nn[KMG]	[KNL,IA-32,IA-64,PPC,X86-64] This parameter
+			is similar to kernelcore except it specifies the
+			amount of memory used for migratable allocations.
+			If both kernelcore and movablecore is specified,
+			then kernelcore will be at *least* the specified
+			value but may be more. If movablecore on its own
+			is specified, the administrator must be careful
+			that the amount of memory usable for all allocations
+			is not too small.
+
 	keepinitrd	[HW,ARM]
 
 	kstack=N	[IA-32,X86-64] Print N words from the kernel stack
@@ -949,11 +976,6 @@
 
 	mcatest=	[IA-64]
 
-	mcd=		[HW,CD]
-			Format: <port>,<irq>,<mitsumi_bug_93_wait>
-
-	mcdx=		[HW,CD]
-
 	mce		[IA-32] Machine Check Exception
 
 	md=		[HW] RAID subsystems devices and level
@@ -996,49 +1018,6 @@
 
 	mga=		[HW,DRM]
 
-	migration_cost=
-			[KNL,SMP] debug: override scheduler migration costs
-			Format: <level-1-usecs>,<level-2-usecs>,...
-			This debugging option can be used to override the
-			default scheduler migration cost matrix. The numbers
-			are indexed by 'CPU domain distance'.
-			E.g. migration_cost=1000,2000,3000 on an SMT NUMA
-			box will set up an intra-core migration cost of
-			1 msec, an inter-core migration cost of 2 msecs,
-			and an inter-node migration cost of 3 msecs.
-
-			WARNING: using the wrong values here can break
-			scheduler performance, so it's only for scheduler
-			development purposes, not production environments.
-
-	migration_debug=
-			[KNL,SMP] migration cost auto-detect verbosity
-			Format=<0|1|2>
-			If a system's migration matrix reported at bootup
-			seems erroneous then this option can be used to
-			increase verbosity of the detection process.
-			We default to 0 (no extra messages), 1 will print
-			some more information, and 2 will be really
-			verbose (probably only useful if you also have a
-			serial console attached to the system).
-
-	migration_factor=
-			[KNL,SMP] multiply/divide migration costs by a factor
-			Format=<percent>
-			This debug option can be used to proportionally
-			increase or decrease the auto-detected migration
-			costs for all entries of the migration matrix.
-			E.g. migration_factor=150 will increase migration
-			costs by 50%. (and thus the scheduler will be less
-			eager migrating cache-hot tasks)
-			migration_factor=80 will decrease migration costs
-			by 20%. (thus the scheduler will be more eager to
-			migrate tasks)
-
-			WARNING: using the wrong values here can break
-			scheduler performance, so it's only for scheduler
-			development purposes, not production environments.
-
 	mousedev.tap_time=
 			[MOUSE] Maximum time between finger touching and
 			leaving touchpad surface for touch to be considered
@@ -1112,9 +1091,9 @@
 			when set.
 			Format: <int>
 
-	noaliencache	[MM, NUMA] Disables the allcoation of alien caches in
-			the slab allocator.  Saves per-node memory, but will
-			impact performance on real NUMA hardware.
+	noaliencache	[MM, NUMA, SLAB] Disables the allocation of alien
+			caches in the slab allocator.  Saves per-node memory,
+			but will impact performance.
 
 	noalign		[KNL,ARM]
 
@@ -1206,6 +1185,8 @@
 
 	nosmp		[SMP] Tells an SMP kernel to act as a UP kernel.
 
+	nosoftlockup	[KNL] Disable the soft-lockup detector.
+
 	nosync		[HW,M68K] Disables sync negotiation for all devices.
 
 	notsc		[BUGS=IA-32] Disable Time Stamp Counter
@@ -1214,20 +1195,19 @@
 
 	nowb		[ARM]
 
+	numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
+			one of ['zone', 'node', 'default'] can be specified
+			This can be set from sysctl after boot.
+			See Documentation/sysctl/vm.txt for details.
+
 	nr_uarts=	[SERIAL] maximum number of UARTs to be registered.
 
 	opl3=		[HW,OSS]
 			Format: <io>
 
-	opl3sa2=	[HW,OSS] Format:
-			<io>,<irq>,<dma>,<dma2>,<mss_io>,<mpu_io>,<ymode>,<loopback>[,<isapnp>,<multiple]
-
 	oprofile.timer=	[HW]
 			Use timer interrupt instead of performance counters
 
-	optcd=		[HW,CD]
-			Format: <io>
-
 	osst=		[HW,SCSI] SCSI Tape Driver
 			Format: <buffer_size>,<write_threshold>
 			See also Documentation/scsi/st.txt.
@@ -1406,6 +1386,15 @@
 			autoconfiguration.
 			Ranges are in pairs (memory base and size).
 
+	print-fatal-signals=
+			[KNL] debug: print fatal signals
+			print-fatal-signals=1: print segfault info to
+			the kernel console.
+			default: off.
+
+	printk.time=	Show timing data prefixed to each printk message line
+			Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
+
 	profile=	[KNL] Enable kernel profiling via /proc/profile
 			Format: [schedule,]<number>
 			Param: "schedule" - profile schedule points.
@@ -1518,6 +1507,10 @@
 
 	rootfstype=	[KNL] Set root filesystem type
 
+	rootwait	[KNL] Wait (indefinitely) for root device to show up.
+			Useful for devices that are detected asynchronously
+			(e.g. USB and MMC devices).
+
 	rw		[KNL] Mount root device read-write on boot
 
 	S		[KNL] Run init in single mode
@@ -1530,11 +1523,6 @@
 
 	sbni=		[NET] Granch SBNI12 leased line adapter
 
-	sbpcd=		[HW,CD] Soundblaster CD adapter
-			Format: <io>,<type>
-			See a comment before function sbpcd_setup() in
-			drivers/cdrom/sbpcd.c.
-
 	sc1200wdt=	[HW,WDT] SC1200 WDT (watchdog) driver
 			Format: <io>[,<timeout>[,<isapnp>]]
 
@@ -1587,12 +1575,43 @@
 	simeth=		[IA-64]
 	simscsi=
 
-	sjcd=		[HW,CD]
-			Format: <io>,<irq>,<dma>
-			See header of drivers/cdrom/sjcd.c.
-
 	slram=		[HW,MTD]
 
+	slub_debug[=options[,slabs]]	[MM, SLUB]
+			Enabling slub_debug allows one to determine the
+			culprit if slab objects become corrupted. Enabling
+			slub_debug can create guard zones around objects and
+			may poison objects when not in use. Also tracks the
+			last alloc / free. For more information see
+			Documentation/vm/slub.txt.
+
+	slub_max_order= [MM, SLUB]
+			Determines the maximum allowed order for slabs.
+			A high setting may cause OOMs due to memory
+			fragmentation. For more information see
+			Documentation/vm/slub.txt.
+
+	slub_min_objects=	[MM, SLUB]
+			The minimum number of objects per slab. SLUB will
+			increase the slab order up to slub_max_order to
+			generate a sufficiently large slab able to contain
+			the number of objects indicated. The higher the number
+			of objects the smaller the overhead of tracking slabs
+			and the less frequently locks need to be acquired.
+			For more information see Documentation/vm/slub.txt.
+
+	slub_min_order=	[MM, SLUB]
+			Determines the mininum page order for slabs. Must be
+			lower than slub_max_order.
+			For more information see Documentation/vm/slub.txt.
+
+	slub_nomerge	[MM, SLUB]
+			Disable merging of slabs with similar size. May be
+			necessary if there is some reason to distinguish
+			allocs to different slabs. Debug options disable
+			merging on their own.
+			For more information see Documentation/vm/slub.txt.
+
 	smart2=		[HW]
 			Format: <io1>[,<io2>[,...,<io8>]]
 
@@ -1732,9 +1751,6 @@
 
 	snd-ymfpci=	[HW,ALSA]
 
-	sonycd535=	[HW,CD]
-			Format: <io>[,<irq>]
-
 	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
 			See Documentation/sonypi.txt
 
@@ -1806,10 +1822,7 @@
 			Set number of hash buckets for TCP connection
 
 	time		Show timing data prefixed to each printk message line
-
-	clocksource=	[GENERIC_TIME] Override the default clocksource
-			Override the default clocksource and use the clocksource
-			with the name specified.
+			[deprecated, see 'printk.time']
 
 	tipar.timeout=	[HW,PPT]
 			Set communications timeout in tenths of a second
diff --git a/Documentation/ldm.txt b/Documentation/ldm.txt
index e266e11..718085b 100644
--- a/Documentation/ldm.txt
+++ b/Documentation/ldm.txt
@@ -2,10 +2,13 @@
             LDM - Logical Disk Manager (Dynamic Disks)
             ------------------------------------------
 
+Originally Written by FlatCap - Richard Russon <ldm@flatcap.org>.
+Last Updated by Anton Altaparmakov on 30 March 2007 for Windows Vista.
+
 Overview
 --------
 
-Windows 2000 and XP use a new partitioning scheme.  It is a complete
+Windows 2000, XP, and Vista use a new partitioning scheme.  It is a complete
 replacement for the MSDOS style partitions.  It stores its information in a
 1MiB journalled database at the end of the physical disk.  The size of
 partitions is limited only by disk space.  The maximum number of partitions is
@@ -23,7 +26,11 @@
 assemble any multi-partition volumes, e.g.  Stripes, RAID5.
 
 To prevent legacy applications from repartitioning the disk, the LDM creates a
-dummy MSDOS partition containing one disk-sized partition.
+dummy MSDOS partition containing one disk-sized partition.  This is what is
+supported with the Linux LDM driver.
+
+A newer approach that has been implemented with Vista is to put LDM on top of a
+GPT label disk.  This is not supported by the Linux LDM driver yet.
 
 
 Example
@@ -88,13 +95,13 @@
 More Documentation
 ------------------
 
-There is an Overview of the LDM online together with complete Technical
-Documentation.  It can also be downloaded in html.
+There is an Overview of the LDM together with complete Technical Documentation.
+It is available for download.
 
-  http://linux-ntfs.sourceforge.net/ldm/index.html
-  http://linux-ntfs.sourceforge.net/downloads.html
+  http://www.linux-ntfs.org/content/view/19/37/
 
-If you have any LDM questions that aren't answered on the website, email me.
+If you have any LDM questions that aren't answered in the documentation, email
+me.
 
 Cheers,
     FlatCap - Richard Russon
diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt
index 1c41db2..59108ce 100644
--- a/Documentation/m68k/kernel-options.txt
+++ b/Documentation/m68k/kernel-options.txt
@@ -82,13 +82,6 @@
   /dev/fd : -> 0x0200 (floppy disk)
   /dev/xda: -> 0x0c00 (first XT disk, unused in Linux/m68k)
   /dev/xdb: -> 0x0c40 (second XT disk, unused in Linux/m68k)
-  /dev/ada: -> 0x1c00 (first ACSI device)
-  /dev/adb: -> 0x1c10 (second ACSI device)
-  /dev/adc: -> 0x1c20 (third ACSI device)
-  /dev/add: -> 0x1c30 (forth ACSI device)
-
-The last four names are available only if the kernel has been compiled
-with Atari and ACSI support.
 
   The name must be followed by a decimal number, that stands for the
 partition number. Internally, the value of the number is just
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 58408dd..650657c 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -24,7 +24,7 @@
  (*) Explicit kernel barriers.
 
      - Compiler barrier.
-     - The CPU memory barriers.
+     - CPU memory barriers.
      - MMIO write barrier.
 
  (*) Implicit kernel memory barriers.
@@ -265,7 +265,7 @@
 ordering over the memory operations on either side of the barrier.
 
 Such enforcement is important because the CPUs and other devices in a system
-can use a variety of tricks to improve performance - including reordering,
+can use a variety of tricks to improve performance, including reordering,
 deferral and combination of memory operations; speculative loads; speculative
 branch prediction and various types of caching.  Memory barriers are used to
 override or suppress these tricks, allowing the code to sanely control the
@@ -457,7 +457,7 @@
 	(Q == &A) implies (D == 1)
 	(Q == &B) implies (D == 4)
 
-But! CPU 2's perception of P may be updated _before_ its perception of B, thus
+But!  CPU 2's perception of P may be updated _before_ its perception of B, thus
 leading to the following situation:
 
 	(Q == &B) and (D == 2) ????
@@ -573,7 +573,7 @@
 the "weaker" type.
 
 [!] Note that the stores before the write barrier would normally be expected to
-match the loads after the read barrier or data dependency barrier, and vice
+match the loads after the read barrier or the data dependency barrier, and vice
 versa:
 
 	CPU 1                           CPU 2
@@ -588,7 +588,7 @@
 EXAMPLES OF MEMORY BARRIER SEQUENCES
 ------------------------------------
 
-Firstly, write barriers act as a partial orderings on store operations.
+Firstly, write barriers act as partial orderings on store operations.
 Consider the following sequence of events:
 
 	CPU 1
@@ -608,15 +608,15 @@
 	+-------+       :      :
 	|       |       +------+
 	|       |------>| C=3  |     }     /\
-	|       |  :    +------+     }-----  \  -----> Events perceptible
-	|       |  :    | A=1  |     }        \/       to rest of system
+	|       |  :    +------+     }-----  \  -----> Events perceptible to
+	|       |  :    | A=1  |     }        \/       the rest of the system
 	|       |  :    +------+     }
 	| CPU 1 |  :    | B=2  |     }
 	|       |       +------+     }
 	|       |   wwwwwwwwwwwwwwww }   <--- At this point the write barrier
 	|       |       +------+     }        requires all stores prior to the
 	|       |  :    | E=5  |     }        barrier to be committed before
-	|       |  :    +------+     }        further stores may be take place.
+	|       |  :    +------+     }        further stores may take place
 	|       |------>| D=4  |     }
 	|       |       +------+
 	+-------+       :      :
@@ -626,7 +626,7 @@
 	                   V
 
 
-Secondly, data dependency barriers act as a partial orderings on data-dependent
+Secondly, data dependency barriers act as partial orderings on data-dependent
 loads.  Consider the following sequence of events:
 
 	CPU 1			CPU 2
@@ -975,7 +975,7 @@
 
 	barrier();
 
-This a general barrier - lesser varieties of compiler barrier do not exist.
+This is a general barrier - lesser varieties of compiler barrier do not exist.
 
 The compiler barrier has no direct effect on the CPU, which may then reorder
 things however it wishes.
@@ -997,7 +997,7 @@
 All CPU memory barriers unconditionally imply compiler barriers.
 
 SMP memory barriers are reduced to compiler barriers on uniprocessor compiled
-systems because it is assumed that a CPU will be appear to be self-consistent,
+systems because it is assumed that a CPU will appear to be self-consistent,
 and will order overlapping accesses correctly with respect to itself.
 
 [!] Note that SMP memory barriers _must_ be used to control the ordering of
@@ -1146,9 +1146,9 @@
 Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is
 equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
 
-[!] Note: one of the consequence of LOCKs and UNLOCKs being only one-way
-    barriers is that the effects instructions outside of a critical section may
-    seep into the inside of the critical section.
+[!] Note: one of the consequences of LOCKs and UNLOCKs being only one-way
+    barriers is that the effects of instructions outside of a critical section
+    may seep into the inside of the critical section.
 
 A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
 because it is possible for an access preceding the LOCK to happen after the
@@ -1239,7 +1239,7 @@
 	UNLOCK M			UNLOCK Q
 	*D = d;				*H = h;
 
-Then there is no guarantee as to what order CPU #3 will see the accesses to *A
+Then there is no guarantee as to what order CPU 3 will see the accesses to *A
 through *H occur in, other than the constraints imposed by the separate locks
 on the separate CPUs. It might, for example, see:
 
@@ -1269,12 +1269,12 @@
 					UNLOCK M	[2]
 					*H = h;
 
-CPU #3 might see:
+CPU 3 might see:
 
 	*E, LOCK M [1], *C, *B, *A, UNLOCK M [1],
 		LOCK M [2], *H, *F, *G, UNLOCK M [2], *D
 
-But assuming CPU #1 gets the lock first, it won't see any of:
+But assuming CPU 1 gets the lock first, CPU 3 won't see any of:
 
 	*B, *C, *D, *F, *G or *H preceding LOCK M [1]
 	*A, *B or *C following UNLOCK M [1]
@@ -1327,12 +1327,12 @@
 					mmiowb();
 					spin_unlock(Q);
 
-this will ensure that the two stores issued on CPU #1 appear at the PCI bridge
-before either of the stores issued on CPU #2.
+this will ensure that the two stores issued on CPU 1 appear at the PCI bridge
+before either of the stores issued on CPU 2.
 
 
-Furthermore, following a store by a load to the same device obviates the need
-for an mmiowb(), because the load forces the store to complete before the load
+Furthermore, following a store by a load from the same device obviates the need
+for the mmiowb(), because the load forces the store to complete before the load
 is performed:
 
 	CPU 1				CPU 2
@@ -1363,7 +1363,7 @@
 
  (*) Atomic operations.
 
- (*) Accessing devices (I/O).
+ (*) Accessing devices.
 
  (*) Interrupts.
 
@@ -1399,7 +1399,7 @@
  (1) read the next pointer from this waiter's record to know as to where the
      next waiter record is;
 
- (4) read the pointer to the waiter's task structure;
+ (2) read the pointer to the waiter's task structure;
 
  (3) clear the task pointer to tell the waiter it has been given the semaphore;
 
@@ -1407,7 +1407,7 @@
 
  (5) release the reference held on the waiter's task struct.
 
-In otherwords, it has to perform this sequence of events:
+In other words, it has to perform this sequence of events:
 
 	LOAD waiter->list.next;
 	LOAD waiter->task;
@@ -1502,7 +1502,7 @@
 such the implicit memory barrier effects are necessary.
 
 
-The following operation are potential problems as they do _not_ imply memory
+The following operations are potential problems as they do _not_ imply memory
 barriers, but might be used for implementing such things as UNLOCK-class
 operations:
 
@@ -1517,7 +1517,7 @@
 
 The following also do _not_ imply memory barriers, and so may require explicit
 memory barriers under some circumstances (smp_mb__before_atomic_dec() for
-instance)):
+instance):
 
 	atomic_add();
 	atomic_sub();
@@ -1641,8 +1641,8 @@
      indeed have special I/O space access cycles and instructions, but many
      CPUs don't have such a concept.
 
-     The PCI bus, amongst others, defines an I/O space concept - which on such
-     CPUs as i386 and x86_64 cpus readily maps to the CPU's concept of I/O
+     The PCI bus, amongst others, defines an I/O space concept which - on such
+     CPUs as i386 and x86_64 - readily maps to the CPU's concept of I/O
      space.  However, it may also be mapped as a virtual I/O space in the CPU's
      memory map, particularly on those CPUs that don't support alternate I/O
      spaces.
@@ -1664,7 +1664,7 @@
      i386 architecture machines, for example, this is controlled by way of the
      MTRR registers.
 
-     Ordinarily, these will be guaranteed to be fully ordered and uncombined,,
+     Ordinarily, these will be guaranteed to be fully ordered and uncombined,
      provided they're not accessing a prefetchable device.
 
      However, intermediary hardware (such as a PCI bridge) may indulge in
@@ -1689,7 +1689,7 @@
 
  (*) ioreadX(), iowriteX()
 
-     These will perform as appropriate for the type of access they're actually
+     These will perform appropriately for the type of access they're actually
      doing, be it inX()/outX() or readX()/writeX().
 
 
@@ -1705,7 +1705,7 @@
 
 This means that it must be considered that the CPU will execute its instruction
 stream in any order it feels like - or even in parallel - provided that if an
-instruction in the stream depends on the an earlier instruction, then that
+instruction in the stream depends on an earlier instruction, then that
 earlier instruction must be sufficiently complete[*] before the later
 instruction may proceed; in other words: provided that the appearance of
 causality is maintained.
@@ -1795,8 +1795,8 @@
 become apparent in the same order on those other CPUs.
 
 
-Consider dealing with a system that has pair of CPUs (1 & 2), each of which has
-a pair of parallel data caches (CPU 1 has A/B, and CPU 2 has C/D):
+Consider dealing with a system that has a pair of CPUs (1 & 2), each of which
+has a pair of parallel data caches (CPU 1 has A/B, and CPU 2 has C/D):
 
 	            :
 	            :                          +--------+
@@ -1835,7 +1835,7 @@
 
  (*) the coherency queue is not flushed by normal loads to lines already
      present in the cache, even though the contents of the queue may
-     potentially effect those loads.
+     potentially affect those loads.
 
 Imagine, then, that two writes are made on the first CPU, with a write barrier
 between them to guarantee that they will appear to reach that CPU's caches in
@@ -1845,7 +1845,7 @@
 	===============	===============	=======================================
 					u == 0, v == 1 and p == &u, q == &u
 	v = 2;
-	smp_wmb();			Make sure change to v visible before
+	smp_wmb();			Make sure change to v is visible before
 					 change to p
 	<A:modify v=2>			v is now in cache A exclusively
 	p = &v;
@@ -1853,7 +1853,7 @@
 
 The write memory barrier forces the other CPUs in the system to perceive that
 the local CPU's caches have apparently been updated in the correct order.  But
-now imagine that the second CPU that wants to read those values:
+now imagine that the second CPU wants to read those values:
 
 	CPU 1		CPU 2		COMMENT
 	===============	===============	=======================================
@@ -1861,7 +1861,7 @@
 			q = p;
 			x = *q;
 
-The above pair of reads may then fail to happen in expected order, as the
+The above pair of reads may then fail to happen in the expected order, as the
 cacheline holding p may get updated in one of the second CPU's caches whilst
 the update to the cacheline holding v is delayed in the other of the second
 CPU's caches by some other cache event:
@@ -1916,7 +1916,7 @@
 
 Other CPUs may also have split caches, but must coordinate between the various
 cachelets for normal memory accesses.  The semantics of the Alpha removes the
-need for coordination in absence of memory barriers.
+need for coordination in the absence of memory barriers.
 
 
 CACHE COHERENCY VS DMA
@@ -1931,10 +1931,10 @@
 
 In addition, the data DMA'd to RAM by a device may be overwritten by dirty
 cache lines being written back to RAM from a CPU's cache after the device has
-installed its own data, or cache lines simply present in a CPUs cache may
-simply obscure the fact that RAM has been updated, until at such time as the
-cacheline is discarded from the CPU's cache and reloaded.  To deal with this,
-the appropriate part of the kernel must invalidate the overlapping bits of the
+installed its own data, or cache lines present in the CPU's cache may simply
+obscure the fact that RAM has been updated, until at such time as the cacheline
+is discarded from the CPU's cache and reloaded.  To deal with this, the
+appropriate part of the kernel must invalidate the overlapping bits of the
 cache on each CPU.
 
 See Documentation/cachetlb.txt for more information on cache management.
@@ -1944,7 +1944,7 @@
 -----------------------
 
 Memory mapped I/O usually takes place through memory locations that are part of
-a window in the CPU's memory space that have different properties assigned than
+a window in the CPU's memory space that has different properties assigned than
 the usual RAM directed window.
 
 Amongst these properties is usually the fact that such accesses bypass the
@@ -1960,7 +1960,7 @@
 =========================
 
 A programmer might take it for granted that the CPU will perform memory
-operations in exactly the order specified, so that if a CPU is, for example,
+operations in exactly the order specified, so that if the CPU is, for example,
 given the following piece of code to execute:
 
 	a = *A;
@@ -1969,7 +1969,7 @@
 	d = *D;
 	*E = e;
 
-They would then expect that the CPU will complete the memory operation for each
+they would then expect that the CPU will complete the memory operation for each
 instruction before moving on to the next one, leading to a definite sequence of
 operations as seen by external observers in the system:
 
@@ -1986,8 +1986,8 @@
  (*) loads may be done speculatively, and the result discarded should it prove
      to have been unnecessary;
 
- (*) loads may be done speculatively, leading to the result having being
-     fetched at the wrong time in the expected sequence of events;
+ (*) loads may be done speculatively, leading to the result having been fetched
+     at the wrong time in the expected sequence of events;
 
  (*) the order of the memory accesses may be rearranged to promote better use
      of the CPU buses and caches;
@@ -2069,12 +2069,12 @@
 
 The DEC Alpha CPU is one of the most relaxed CPUs there is.  Not only that,
 some versions of the Alpha CPU have a split data cache, permitting them to have
-two semantically related cache lines updating at separate times.  This is where
+two semantically-related cache lines updated at separate times.  This is where
 the data dependency barrier really becomes necessary as this synchronises both
 caches with the memory coherence system, thus making it seem like pointer
 changes vs new data occur in the right order.
 
-The Alpha defines the Linux's kernel's memory barrier model.
+The Alpha defines the Linux kernel's memory barrier model.
 
 See the subsection on "Cache Coherency" above.
 
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index e06b6e3..d63f480 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -32,6 +32,8 @@
 	- info on the COPS LocalTalk Linux driver
 cs89x0.txt
 	- the Crystal LAN (CS8900/20-based) Ethernet ISA adapter driver
+cxacru.txt
+	- Conexant AccessRunner USB ADSL Modem
 de4x5.txt
 	- the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
 decnet.txt
@@ -94,9 +96,6 @@
 	- the new routing mechanism
 shaper.txt
 	- info on the module that can shape/limit transmitted traffic.
-sk98lin.txt
-	- Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit
-	  Ethernet Adapter family driver info
 skfp.txt
 	- SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
 smc9.txt
diff --git a/Documentation/networking/cxacru.txt b/Documentation/networking/cxacru.txt
new file mode 100644
index 0000000..b074681
--- /dev/null
+++ b/Documentation/networking/cxacru.txt
@@ -0,0 +1,84 @@
+Firmware is required for this device: http://accessrunner.sourceforge.net/
+
+While it is capable of managing/maintaining the ADSL connection without the
+module loaded, the device will sometimes stop responding after unloading the
+driver and it is necessary to unplug/remove power to the device to fix this.
+
+Detected devices will appear as ATM devices named "cxacru". In /sys/class/atm/
+these are directories named cxacruN where N is the device number. A symlink
+named device points to the USB interface device's directory which contains
+several sysfs attribute files for retrieving device statistics:
+
+* adsl_controller_version
+
+* adsl_headend
+* adsl_headend_environment
+	Information about the remote headend.
+
+* downstream_attenuation (dB)
+* downstream_bits_per_frame
+* downstream_rate (kbps)
+* downstream_snr_margin (dB)
+	Downstream stats.
+
+* upstream_attenuation (dB)
+* upstream_bits_per_frame
+* upstream_rate (kbps)
+* upstream_snr_margin (dB)
+* transmitter_power (dBm/Hz)
+	Upstream stats.
+
+* downstream_crc_errors
+* downstream_fec_errors
+* downstream_hec_errors
+* upstream_crc_errors
+* upstream_fec_errors
+* upstream_hec_errors
+	Error counts.
+
+* line_startable
+	Indicates that ADSL support on the device
+	is/can be enabled, see adsl_start.
+
+* line_status
+	"initialising"
+	"down"
+	"attempting to activate"
+	"training"
+	"channel analysis"
+	"exchange"
+	"waiting"
+	"up"
+
+	Changes between "down" and "attempting to activate"
+	if there is no signal.
+
+* link_status
+	"not connected"
+	"connected"
+	"lost"
+
+* mac_address
+
+* modulation
+	"ANSI T1.413"
+	"ITU-T G.992.1 (G.DMT)"
+	"ITU-T G.992.2 (G.LITE)"
+
+* startup_attempts
+	Count of total attempts to initialise ADSL.
+
+To enable/disable ADSL, the following can be written to the adsl_state file:
+	"start"
+	"stop
+	"restart" (stops, waits 1.5s, then starts)
+	"poll" (used to resume status polling if it was disabled due to failure)
+
+Changes in adsl/line state are reported via kernel log messages:
+	[4942145.150704] ATM dev 0: ADSL state: running
+	[4942243.663766] ATM dev 0: ADSL line: down
+	[4942249.665075] ATM dev 0: ADSL line: attempting to activate
+	[4942253.654954] ATM dev 0: ADSL line: training
+	[4942255.666387] ATM dev 0: ADSL line: channel analysis
+	[4942259.656262] ATM dev 0: ADSL line: exchange
+	[2635357.696901] ATM dev 0: ADSL line: up (8128 kb/s down | 832 kb/s up)
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index af6a63a..32c2e9d 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -433,6 +433,12 @@
 	not receive a window scaling option from them.
 	Default: 0
 
+tcp_dma_copybreak - INTEGER
+	Lower limit, in bytes, of the size of socket reads that will be
+	offloaded to a DMA copy engine, if one is present in the system
+	and CONFIG_NET_DMA is enabled.
+	Default: 4096
+
 CIPSOv4 Variables:
 
 cipso_cache_enable - BOOLEAN
@@ -874,8 +880,7 @@
 accept_source_route - INTEGER
 	Accept source routing (routing extension header).
 
-	> 0: Accept routing header.
-	= 0: Accept only routing header type 2.
+	>= 0: Accept only routing header type 2.
 	< 0: Do not accept routing header.
 
 	Default: 0
diff --git a/Documentation/networking/l2tp.txt b/Documentation/networking/l2tp.txt
new file mode 100644
index 0000000..2451f55
--- /dev/null
+++ b/Documentation/networking/l2tp.txt
@@ -0,0 +1,169 @@
+This brief document describes how to use the kernel's PPPoL2TP driver
+to provide L2TP functionality. L2TP is a protocol that tunnels one or
+more PPP sessions over a UDP tunnel. It is commonly used for VPNs
+(L2TP/IPSec) and by ISPs to tunnel subscriber PPP sessions over an IP
+network infrastructure.
+
+Design
+======
+
+The PPPoL2TP driver, drivers/net/pppol2tp.c, provides a mechanism by
+which PPP frames carried through an L2TP session are passed through
+the kernel's PPP subsystem. The standard PPP daemon, pppd, handles all
+PPP interaction with the peer. PPP network interfaces are created for
+each local PPP endpoint.
+
+The L2TP protocol http://www.faqs.org/rfcs/rfc2661.html defines L2TP
+control and data frames. L2TP control frames carry messages between
+L2TP clients/servers and are used to setup / teardown tunnels and
+sessions. An L2TP client or server is implemented in userspace and
+will use a regular UDP socket per tunnel. L2TP data frames carry PPP
+frames, which may be PPP control or PPP data. The kernel's PPP
+subsystem arranges for PPP control frames to be delivered to pppd,
+while data frames are forwarded as usual.
+
+Each tunnel and session within a tunnel is assigned a unique tunnel_id
+and session_id. These ids are carried in the L2TP header of every
+control and data packet. The pppol2tp driver uses them to lookup
+internal tunnel and/or session contexts. Zero tunnel / session ids are
+treated specially - zero ids are never assigned to tunnels or sessions
+in the network. In the driver, the tunnel context keeps a pointer to
+the tunnel UDP socket. The session context keeps a pointer to the
+PPPoL2TP socket, as well as other data that lets the driver interface
+to the kernel PPP subsystem.
+
+Note that the pppol2tp kernel driver handles only L2TP data frames;
+L2TP control frames are simply passed up to userspace in the UDP
+tunnel socket. The kernel handles all datapath aspects of the
+protocol, including data packet resequencing (if enabled).
+
+There are a number of requirements on the userspace L2TP daemon in
+order to use the pppol2tp driver.
+
+1. Use a UDP socket per tunnel.
+
+2. Create a single PPPoL2TP socket per tunnel bound to a special null
+   session id. This is used only for communicating with the driver but
+   must remain open while the tunnel is active. Opening this tunnel
+   management socket causes the driver to mark the tunnel socket as an
+   L2TP UDP encapsulation socket and flags it for use by the
+   referenced tunnel id. This hooks up the UDP receive path via
+   udp_encap_rcv() in net/ipv4/udp.c. PPP data frames are never passed
+   in this special PPPoX socket.
+
+3. Create a PPPoL2TP socket per L2TP session. This is typically done
+   by starting pppd with the pppol2tp plugin and appropriate
+   arguments. A PPPoL2TP tunnel management socket (Step 2) must be
+   created before the first PPPoL2TP session socket is created.
+
+When creating PPPoL2TP sockets, the application provides information
+to the driver about the socket in a socket connect() call. Source and
+destination tunnel and session ids are provided, as well as the file
+descriptor of a UDP socket. See struct pppol2tp_addr in
+include/linux/if_ppp.h. Note that zero tunnel / session ids are
+treated specially. When creating the per-tunnel PPPoL2TP management
+socket in Step 2 above, zero source and destination session ids are
+specified, which tells the driver to prepare the supplied UDP file
+descriptor for use as an L2TP tunnel socket.
+
+Userspace may control behavior of the tunnel or session using
+setsockopt and ioctl on the PPPoX socket. The following socket
+options are supported:-
+
+DEBUG     - bitmask of debug message categories. See below.
+SENDSEQ   - 0 => don't send packets with sequence numbers
+            1 => send packets with sequence numbers
+RECVSEQ   - 0 => receive packet sequence numbers are optional
+            1 => drop receive packets without sequence numbers
+LNSMODE   - 0 => act as LAC.
+            1 => act as LNS.
+REORDERTO - reorder timeout (in millisecs). If 0, don't try to reorder.
+
+Only the DEBUG option is supported by the special tunnel management
+PPPoX socket.
+
+In addition to the standard PPP ioctls, a PPPIOCGL2TPSTATS is provided
+to retrieve tunnel and session statistics from the kernel using the
+PPPoX socket of the appropriate tunnel or session.
+
+Debugging
+=========
+
+The driver supports a flexible debug scheme where kernel trace
+messages may be optionally enabled per tunnel and per session. Care is
+needed when debugging a live system since the messages are not
+rate-limited and a busy system could be swamped. Userspace uses
+setsockopt on the PPPoX socket to set a debug mask.
+
+The following debug mask bits are available:
+
+PPPOL2TP_MSG_DEBUG    verbose debug (if compiled in)
+PPPOL2TP_MSG_CONTROL  userspace - kernel interface
+PPPOL2TP_MSG_SEQ      sequence numbers handling
+PPPOL2TP_MSG_DATA     data packets
+
+Sample Userspace Code
+=====================
+
+1. Create tunnel management PPPoX socket
+
+        kernel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
+        if (kernel_fd >= 0) {
+                struct sockaddr_pppol2tp sax;
+                struct sockaddr_in const *peer_addr;
+
+                peer_addr = l2tp_tunnel_get_peer_addr(tunnel);
+                memset(&sax, 0, sizeof(sax));
+                sax.sa_family = AF_PPPOX;
+                sax.sa_protocol = PX_PROTO_OL2TP;
+                sax.pppol2tp.fd = udp_fd;       /* fd of tunnel UDP socket */
+                sax.pppol2tp.addr.sin_addr.s_addr = peer_addr->sin_addr.s_addr;
+                sax.pppol2tp.addr.sin_port = peer_addr->sin_port;
+                sax.pppol2tp.addr.sin_family = AF_INET;
+                sax.pppol2tp.s_tunnel = tunnel_id;
+                sax.pppol2tp.s_session = 0;     /* special case: mgmt socket */
+                sax.pppol2tp.d_tunnel = 0;
+                sax.pppol2tp.d_session = 0;     /* special case: mgmt socket */
+
+                if(connect(kernel_fd, (struct sockaddr *)&sax, sizeof(sax) ) < 0 ) {
+                        perror("connect failed");
+                        result = -errno;
+                        goto err;
+                }
+        }
+
+2. Create session PPPoX data socket
+
+        struct sockaddr_pppol2tp sax;
+        int fd;
+
+        /* Note, the target socket must be bound already, else it will not be ready */
+        sax.sa_family = AF_PPPOX;
+        sax.sa_protocol = PX_PROTO_OL2TP;
+        sax.pppol2tp.fd = tunnel_fd;
+        sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr;
+        sax.pppol2tp.addr.sin_port = addr->sin_port;
+        sax.pppol2tp.addr.sin_family = AF_INET;
+        sax.pppol2tp.s_tunnel  = tunnel_id;
+        sax.pppol2tp.s_session = session_id;
+        sax.pppol2tp.d_tunnel  = peer_tunnel_id;
+        sax.pppol2tp.d_session = peer_session_id;
+
+        /* session_fd is the fd of the session's PPPoL2TP socket.
+         * tunnel_fd is the fd of the tunnel UDP socket.
+         */
+        fd = connect(session_fd, (struct sockaddr *)&sax, sizeof(sax));
+        if (fd < 0 )    {
+                return -errno;
+        }
+        return 0;
+
+Miscellanous
+============
+
+The PPPoL2TP driver was developed as part of the OpenL2TP project by
+Katalix Systems Ltd. OpenL2TP is a full-featured L2TP client / server,
+designed from the ground up to have the L2TP datapath in the
+kernel. The project also implemented the pppol2tp plugin for pppd
+which allows pppd to use the kernel driver. Details can be found at
+http://openl2tp.sourceforge.net.
diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt
new file mode 100644
index 0000000..53ef7a0
--- /dev/null
+++ b/Documentation/networking/mac80211-injection.txt
@@ -0,0 +1,59 @@
+How to use packet injection with mac80211
+=========================================
+
+mac80211 now allows arbitrary packets to be injected down any Monitor Mode
+interface from userland.  The packet you inject needs to be composed in the
+following format:
+
+ [ radiotap header  ]
+ [ ieee80211 header ]
+ [ payload ]
+
+The radiotap format is discussed in
+./Documentation/networking/radiotap-headers.txt.
+
+Despite 13 radiotap argument types are currently defined, most only make sense
+to appear on received packets.  Currently three kinds of argument are used by
+the injection code, although it knows to skip any other arguments that are
+present (facilitating replay of captured radiotap headers directly):
+
+ - IEEE80211_RADIOTAP_RATE - u8 arg in 500kbps units (0x02 --> 1Mbps)
+
+ - IEEE80211_RADIOTAP_ANTENNA - u8 arg, 0x00 = ant1, 0x01 = ant2
+
+ - IEEE80211_RADIOTAP_DBM_TX_POWER - u8 arg, dBm
+
+Here is an example valid radiotap header defining these three parameters
+
+	0x00, 0x00, // <-- radiotap version
+	0x0b, 0x00, // <- radiotap header length
+	0x04, 0x0c, 0x00, 0x00, // <-- bitmap
+	0x6c, // <-- rate
+	0x0c, //<-- tx power
+	0x01 //<-- antenna
+
+The ieee80211 header follows immediately afterwards, looking for example like
+this:
+
+	0x08, 0x01, 0x00, 0x00,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
+	0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
+	0x10, 0x86
+
+Then lastly there is the payload.
+
+After composing the packet contents, it is sent by send()-ing it to a logical
+mac80211 interface that is in Monitor mode.  Libpcap can also be used,
+(which is easier than doing the work to bind the socket to the right
+interface), along the following lines:
+
+	ppcap = pcap_open_live(szInterfaceName, 800, 1, 20, szErrbuf);
+...
+	r = pcap_inject(ppcap, u8aSendBuffer, nLength);
+
+You can also find sources for a complete inject test applet here:
+
+http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer
+
+Andy Green <andy@warmcat.com>
diff --git a/Documentation/networking/multiqueue.txt b/Documentation/networking/multiqueue.txt
new file mode 100644
index 0000000..00b60cc
--- /dev/null
+++ b/Documentation/networking/multiqueue.txt
@@ -0,0 +1,111 @@
+
+		HOWTO for multiqueue network device support
+		===========================================
+
+Section 1: Base driver requirements for implementing multiqueue support
+Section 2: Qdisc support for multiqueue devices
+Section 3: Brief howto using PRIO or RR for multiqueue devices
+
+
+Intro: Kernel support for multiqueue devices
+---------------------------------------------------------
+
+Kernel support for multiqueue devices is only an API that is presented to the
+netdevice layer for base drivers to implement.  This feature is part of the
+core networking stack, and all network devices will be running on the
+multiqueue-aware stack.  If a base driver only has one queue, then these
+changes are transparent to that driver.
+
+
+Section 1: Base driver requirements for implementing multiqueue support
+-----------------------------------------------------------------------
+
+Base drivers are required to use the new alloc_etherdev_mq() or
+alloc_netdev_mq() functions to allocate the subqueues for the device.  The
+underlying kernel API will take care of the allocation and deallocation of
+the subqueue memory, as well as netdev configuration of where the queues
+exist in memory.
+
+The base driver will also need to manage the queues as it does the global
+netdev->queue_lock today.  Therefore base drivers should use the
+netif_{start|stop|wake}_subqueue() functions to manage each queue while the
+device is still operational.  netdev->queue_lock is still used when the device
+comes online or when it's completely shut down (unregister_netdev(), etc.).
+
+Finally, the base driver should indicate that it is a multiqueue device.  The
+feature flag NETIF_F_MULTI_QUEUE should be added to the netdev->features
+bitmap on device initialization.  Below is an example from e1000:
+
+#ifdef CONFIG_E1000_MQ
+	if ( (adapter->hw.mac.type == e1000_82571) ||
+	     (adapter->hw.mac.type == e1000_82572) ||
+	     (adapter->hw.mac.type == e1000_80003es2lan))
+		netdev->features |= NETIF_F_MULTI_QUEUE;
+#endif
+
+
+Section 2: Qdisc support for multiqueue devices
+-----------------------------------------------
+
+Currently two qdiscs support multiqueue devices.  A new round-robin qdisc,
+sch_rr, and sch_prio. The qdisc is responsible for classifying the skb's to
+bands and queues, and will store the queue mapping into skb->queue_mapping.
+Use this field in the base driver to determine which queue to send the skb
+to.
+
+sch_rr has been added for hardware that doesn't want scheduling policies from
+software, so it's a straight round-robin qdisc.  It uses the same syntax and
+classification priomap that sch_prio uses, so it should be intuitive to
+configure for people who've used sch_prio.
+
+The PRIO qdisc naturally plugs into a multiqueue device.  If PRIO has been
+built with NET_SCH_PRIO_MQ, then upon load, it will make sure the number of
+bands requested is equal to the number of queues on the hardware.  If they
+are equal, it sets a one-to-one mapping up between the queues and bands.  If
+they're not equal, it will not load the qdisc.  This is the same behavior
+for RR.  Once the association is made, any skb that is classified will have
+skb->queue_mapping set, which will allow the driver to properly queue skb's
+to multiple queues.
+
+
+Section 3: Brief howto using PRIO and RR for multiqueue devices
+---------------------------------------------------------------
+
+The userspace command 'tc,' part of the iproute2 package, is used to configure
+qdiscs.  To add the PRIO qdisc to your network device, assuming the device is
+called eth0, run the following command:
+
+# tc qdisc add dev eth0 root handle 1: prio bands 4 multiqueue
+
+This will create 4 bands, 0 being highest priority, and associate those bands
+to the queues on your NIC.  Assuming eth0 has 4 Tx queues, the band mapping
+would look like:
+
+band 0 => queue 0
+band 1 => queue 1
+band 2 => queue 2
+band 3 => queue 3
+
+Traffic will begin flowing through each queue if your TOS values are assigning
+traffic across the various bands.  For example, ssh traffic will always try to
+go out band 0 based on TOS -> Linux priority conversion (realtime traffic),
+so it will be sent out queue 0.  ICMP traffic (pings) fall into the "normal"
+traffic classification, which is band 1.  Therefore pings will be send out
+queue 1 on the NIC.
+
+Note the use of the multiqueue keyword.  This is only in versions of iproute2
+that support multiqueue networking devices; if this is omitted when loading
+a qdisc onto a multiqueue device, the qdisc will load and operate the same
+if it were loaded onto a single-queue device (i.e. - sends all traffic to
+queue 0).
+
+Another alternative to multiqueue band allocation can be done by using the
+multiqueue option and specify 0 bands.  If this is the case, the qdisc will
+allocate the number of bands to equal the number of queues that the device
+reports, and bring the qdisc online.
+
+The behavior of tc filters remains the same, where it will override TOS priority
+classification.
+
+
+Author: Peter P. Waskiewicz Jr. <peter.p.waskiewicz.jr@intel.com>
diff --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt
index 0b27863..98c4392 100644
--- a/Documentation/networking/net-modules.txt
+++ b/Documentation/networking/net-modules.txt
@@ -146,12 +146,6 @@
 	irq = 0
 	(Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300)
 
-atari_bionet.c:
-	Supports full autoprobing. (m68k/Atari)
-
-atari_pamsnet.c:
-	Supports full autoprobing. (m68k/Atari)
-
 atarilance.c:
 	Supports full autoprobing. (m68k/Atari)
 
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index ce1361f..3786929 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -20,6 +20,30 @@
 separately allocated data is attached to the network device
 (dev->priv) then it is up to the module exit handler to free that.
 
+MTU
+===
+Each network device has a Maximum Transfer Unit. The MTU does not
+include any link layer protocol overhead. Upper layer protocols must
+not pass a socket buffer (skb) to a device to transmit with more data
+than the mtu. The MTU does not include link layer header overhead, so
+for example on Ethernet if the standard MTU is 1500 bytes used, the
+actual skb will contain up to 1514 bytes because of the Ethernet
+header. Devices should allow for the 4 byte VLAN header as well.
+
+Segmentation Offload (GSO, TSO) is an exception to this rule.  The
+upper layer protocol may pass a large socket buffer to the device
+transmit routine, and the device will break that up into separate
+packets based on the current MTU.
+
+MTU is symmetrical and applies both to receive and transmit. A device
+must be able to receive at least the maximum size packet allowed by
+the MTU. A network device may use the MTU as mechanism to size receive
+buffers, but the device should allow packets with VLAN header. With
+standard Ethernet mtu of 1500 bytes, the device should allow up to
+1518 byte packets (1500 + 14 header + 4 tag).  The device may either:
+drop, truncate, or pass up oversize packets, but dropping oversize
+packets is preferred.
+
 
 struct net_device synchronization rules
 =======================================
@@ -43,16 +67,17 @@
 
 dev->hard_start_xmit:
 	Synchronization: netif_tx_lock spinlock.
+
 	When the driver sets NETIF_F_LLTX in dev->features this will be
 	called without holding netif_tx_lock. In this case the driver
 	has to lock by itself when needed. It is recommended to use a try lock
-	for this and return -1 when the spin lock fails. 
+	for this and return NETDEV_TX_LOCKED when the spin lock fails.
 	The locking there should also properly protect against 
-	set_multicast_list
-	Context: Process with BHs disabled or BH (timer).
-	Notes: netif_queue_stopped() is guaranteed false
-               Interrupts must be enabled when calling hard_start_xmit.
-                (Interrupts must also be enabled when enabling the BH handler.)
+	set_multicast_list.
+
+	Context: Process with BHs disabled or BH (timer),
+	         will be called with interrupts disabled by netconsole.
+
 	Return codes: 
 	o NETDEV_TX_OK everything ok. 
 	o NETDEV_TX_BUSY Cannot transmit packet, try later 
@@ -74,4 +99,5 @@
 	Synchronization: __LINK_STATE_RX_SCHED bit in dev->state.  See
 		dev_close code and comments in net/core/dev.c for more info.
 	Context: softirq
+	         will be called with interrupts disabled by netconsole.
 
diff --git a/Documentation/networking/radiotap-headers.txt b/Documentation/networking/radiotap-headers.txt
new file mode 100644
index 0000000..953331c
--- /dev/null
+++ b/Documentation/networking/radiotap-headers.txt
@@ -0,0 +1,152 @@
+How to use radiotap headers
+===========================
+
+Pointer to the radiotap include file
+------------------------------------
+
+Radiotap headers are variable-length and extensible, you can get most of the
+information you need to know on them from:
+
+./include/net/ieee80211_radiotap.h
+
+This document gives an overview and warns on some corner cases.
+
+
+Structure of the header
+-----------------------
+
+There is a fixed portion at the start which contains a u32 bitmap that defines
+if the possible argument associated with that bit is present or not.  So if b0
+of the it_present member of ieee80211_radiotap_header is set, it means that
+the header for argument index 0 (IEEE80211_RADIOTAP_TSFT) is present in the
+argument area.
+
+   < 8-byte ieee80211_radiotap_header >
+   [ <possible argument bitmap extensions ... > ]
+   [ <argument> ... ]
+
+At the moment there are only 13 possible argument indexes defined, but in case
+we run out of space in the u32 it_present member, it is defined that b31 set
+indicates that there is another u32 bitmap following (shown as "possible
+argument bitmap extensions..." above), and the start of the arguments is moved
+forward 4 bytes each time.
+
+Note also that the it_len member __le16 is set to the total number of bytes
+covered by the ieee80211_radiotap_header and any arguments following.
+
+
+Requirements for arguments
+--------------------------
+
+After the fixed part of the header, the arguments follow for each argument
+index whose matching bit is set in the it_present member of
+ieee80211_radiotap_header.
+
+ - the arguments are all stored little-endian!
+
+ - the argument payload for a given argument index has a fixed size.  So
+   IEEE80211_RADIOTAP_TSFT being present always indicates an 8-byte argument is
+   present.  See the comments in ./include/net/ieee80211_radiotap.h for a nice
+   breakdown of all the argument sizes
+
+ - the arguments must be aligned to a boundary of the argument size using
+   padding.  So a u16 argument must start on the next u16 boundary if it isn't
+   already on one, a u32 must start on the next u32 boundary and so on.
+
+ - "alignment" is relative to the start of the ieee80211_radiotap_header, ie,
+   the first byte of the radiotap header.  The absolute alignment of that first
+   byte isn't defined.  So even if the whole radiotap header is starting at, eg,
+   address 0x00000003, still the first byte of the radiotap header is treated as
+   0 for alignment purposes.
+
+ - the above point that there may be no absolute alignment for multibyte
+   entities in the fixed radiotap header or the argument region means that you
+   have to take special evasive action when trying to access these multibyte
+   entities.  Some arches like Blackfin cannot deal with an attempt to
+   dereference, eg, a u16 pointer that is pointing to an odd address.  Instead
+   you have to use a kernel API get_unaligned() to dereference the pointer,
+   which will do it bytewise on the arches that require that.
+
+ - The arguments for a given argument index can be a compound of multiple types
+   together.  For example IEEE80211_RADIOTAP_CHANNEL has an argument payload
+   consisting of two u16s of total length 4.  When this happens, the padding
+   rule is applied dealing with a u16, NOT dealing with a 4-byte single entity.
+
+
+Example valid radiotap header
+-----------------------------
+
+	0x00, 0x00, // <-- radiotap version + pad byte
+	0x0b, 0x00, // <- radiotap header length
+	0x04, 0x0c, 0x00, 0x00, // <-- bitmap
+	0x6c, // <-- rate (in 500kHz units)
+	0x0c, //<-- tx power
+	0x01 //<-- antenna
+
+
+Using the Radiotap Parser
+-------------------------
+
+If you are having to parse a radiotap struct, you can radically simplify the
+job by using the radiotap parser that lives in net/wireless/radiotap.c and has
+its prototypes available in include/net/cfg80211.h.  You use it like this:
+
+#include <net/cfg80211.h>
+
+/* buf points to the start of the radiotap header part */
+
+int MyFunction(u8 * buf, int buflen)
+{
+	int pkt_rate_100kHz = 0, antenna = 0, pwr = 0;
+	struct ieee80211_radiotap_iterator iterator;
+	int ret = ieee80211_radiotap_iterator_init(&iterator, buf, buflen);
+
+	while (!ret) {
+
+		ret = ieee80211_radiotap_iterator_next(&iterator);
+
+		if (ret)
+			continue;
+
+		/* see if this argument is something we can use */
+
+		switch (iterator.this_arg_index) {
+		/*
+		 * You must take care when dereferencing iterator.this_arg
+		 * for multibyte types... the pointer is not aligned.  Use
+		 * get_unaligned((type *)iterator.this_arg) to dereference
+		 * iterator.this_arg for type "type" safely on all arches.
+		 */
+		case IEEE80211_RADIOTAP_RATE:
+			/* radiotap "rate" u8 is in
+			 * 500kbps units, eg, 0x02=1Mbps
+			 */
+			pkt_rate_100kHz = (*iterator.this_arg) * 5;
+			break;
+
+		case IEEE80211_RADIOTAP_ANTENNA:
+			/* radiotap uses 0 for 1st ant */
+			antenna = *iterator.this_arg);
+			break;
+
+		case IEEE80211_RADIOTAP_DBM_TX_POWER:
+			pwr = *iterator.this_arg;
+			break;
+
+		default:
+			break;
+		}
+	}  /* while more rt headers */
+
+	if (ret != -ENOENT)
+		return TXRX_DROP;
+
+	/* discard the radiotap header part */
+	buf += iterator.max_length;
+	buflen -= iterator.max_length;
+
+	...
+
+}
+
+Andy Green <andy@warmcat.com>
diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt
deleted file mode 100644
index 8590a95..0000000
--- a/Documentation/networking/sk98lin.txt
+++ /dev/null
@@ -1,568 +0,0 @@
-(C)Copyright 1999-2004 Marvell(R).
-All rights reserved
-===========================================================================
-
-sk98lin.txt created 13-Feb-2004
-
-Readme File for sk98lin v6.23
-Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX
-
-This file contains
- 1  Overview
- 2  Required Files
- 3  Installation
-    3.1  Driver Installation
-    3.2  Inclusion of adapter at system start
- 4  Driver Parameters
-    4.1  Per-Port Parameters
-    4.2  Adapter Parameters
- 5  Large Frame Support
- 6  VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
- 7  Troubleshooting
-
-===========================================================================
-
-
-1  Overview
-===========
-
-The sk98lin driver supports the Marvell Yukon and SysKonnect 
-SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter on Linux. It has 
-been tested with Linux on Intel/x86 machines.
-***
-
-
-2  Required Files
-=================
-
-The linux kernel source.
-No additional files required.
-***
-
-
-3  Installation
-===============
-
-It is recommended to download the latest version of the driver from the 
-SysKonnect web site www.syskonnect.com. If you have downloaded the latest
-driver, the Linux kernel has to be patched before the driver can be 
-installed. For details on how to patch a Linux kernel, refer to the 
-patch.txt file.
-
-3.1  Driver Installation
-------------------------
-
-The following steps describe the actions that are required to install
-the driver and to start it manually. These steps should be carried
-out for the initial driver setup. Once confirmed to be ok, they can
-be included in the system start.
-
-NOTE 1: To perform the following tasks you need 'root' access.
-
-NOTE 2: In case of problems, please read the section "Troubleshooting" 
-        below.
-
-The driver can either be integrated into the kernel or it can be compiled 
-as a module. Select the appropriate option during the kernel 
-configuration.
-
-Compile/use the driver as a module
-----------------------------------
-To compile the driver, go to the directory /usr/src/linux and
-execute the command "make menuconfig" or "make xconfig" and proceed as 
-follows:
-
-To integrate the driver permanently into the kernel, proceed as follows:
-
-1. Select the menu "Network device support" and then "Ethernet(1000Mbit)"
-2. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support" 
-   with (*) 
-3. Build a new kernel when the configuration of the above options is 
-   finished.
-4. Install the new kernel.
-5. Reboot your system.
-
-To use the driver as a module, proceed as follows:
-
-1. Enable 'loadable module support' in the kernel.
-2. For automatic driver start, enable the 'Kernel module loader'.
-3. Select the menu "Network device support" and then "Ethernet(1000Mbit)"
-4. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support" 
-   with (M)
-5. Execute the command "make modules".
-6. Execute the command "make modules_install".
-   The appropriate modules will be installed.
-7. Reboot your system.
-
-
-Load the module manually
-------------------------
-To load the module manually, proceed as follows:
-
-1. Enter "modprobe sk98lin".
-2. If a Marvell Yukon or SysKonnect SK-98xx adapter is installed in 
-   your computer and you have a /proc file system, execute the command:
-   "ls /proc/net/sk98lin/" 
-   This should produce an output containing a line with the following 
-   format:
-   eth0   eth1  ...
-   which indicates that your adapter has been found and initialized.
-   
-   NOTE 1: If you have more than one Marvell Yukon or SysKonnect SK-98xx 
-           adapter installed, the adapters will be listed as 'eth0', 
-                   'eth1', 'eth2', etc.
-                   For each adapter, repeat steps 3 and 4 below.
-
-   NOTE 2: If you have other Ethernet adapters installed, your Marvell
-           Yukon or SysKonnect SK-98xx adapter will be mapped to the 
-                   next available number, e.g. 'eth1'. The mapping is executed 
-                   automatically.
-           The module installation message (displayed either in a system
-           log file or on the console) prints a line for each adapter 
-           found containing the corresponding 'ethX'.
-
-3. Select an IP address and assign it to the respective adapter by 
-   entering:
-   ifconfig eth0 <ip-address>
-   With this command, the adapter is connected to the Ethernet. 
-   
-   SK-98xx Gigabit Ethernet Server Adapters: The yellow LED on the adapter 
-   is now active, the link status LED of the primary port is active and 
-   the link status LED of the secondary port (on dual port adapters) is 
-   blinking (if the ports are connected to a switch or hub).
-   SK-98xx V2.0 Gigabit Ethernet Adapters: The link status LED is active.
-   In addition, you will receive a status message on the console stating
-   "ethX: network connection up using port Y" and showing the selected 
-   connection parameters (x stands for the ethernet device number 
-   (0,1,2, etc), y stands for the port name (A or B)).
-
-   NOTE: If you are in doubt about IP addresses, ask your network
-         administrator for assistance.
-  
-4. Your adapter should now be fully operational.
-   Use 'ping <otherstation>' to verify the connection to other computers 
-   on your network.
-5. To check the adapter configuration view /proc/net/sk98lin/[devicename].
-   For example by executing:    
-   "cat /proc/net/sk98lin/eth0" 
-
-Unload the module
------------------
-To stop and unload the driver modules, proceed as follows:
-
-1. Execute the command "ifconfig eth0 down".
-2. Execute the command "rmmod sk98lin".
-
-3.2  Inclusion of adapter at system start
------------------------------------------
-
-Since a large number of different Linux distributions are 
-available, we are unable to describe a general installation procedure
-for the driver module.
-Because the driver is now integrated in the kernel, installation should
-be easy, using the standard mechanism of your distribution.
-Refer to the distribution's manual for installation of ethernet adapters.
-
-***
-
-4  Driver Parameters
-====================
-
-Parameters can be set at the command line after the module has been 
-loaded with the command 'modprobe'.
-In some distributions, the configuration tools are able to pass parameters
-to the driver module.
-
-If you use the kernel module loader, you can set driver parameters
-in the file /etc/modprobe.conf (or /etc/modules.conf in 2.4 or earlier).
-To set the driver parameters in this file, proceed as follows:
-
-1. Insert a line of the form :
-   options sk98lin ...
-   For "...", the same syntax is required as described for the command
-   line parameters of modprobe below.
-2. To activate the new parameters, either reboot your computer
-   or 
-   unload and reload the driver.
-   The syntax of the driver parameters is:
-
-        modprobe sk98lin parameter=value1[,value2[,value3...]]
-
-   where value1 refers to the first adapter, value2 to the second etc.
-
-NOTE: All parameters are case sensitive. Write them exactly as shown 
-      below.
-
-Example:
-Suppose you have two adapters. You want to set auto-negotiation
-on the first adapter to ON and on the second adapter to OFF.
-You also want to set DuplexCapabilities on the first adapter
-to FULL, and on the second adapter to HALF.
-Then, you must enter:
-
-        modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half
-
-NOTE: The number of adapters that can be configured this way is
-      limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM).
-      The current limit is 16. If you happen to install
-      more adapters, adjust this and recompile.
-
-
-4.1  Per-Port Parameters
-------------------------
-
-These settings are available for each port on the adapter.
-In the following description, '?' stands for the port for
-which you set the parameter (A or B).
-
-Speed
------
-Parameter:    Speed_?
-Values:       10, 100, 1000, Auto
-Default:      Auto
-
-This parameter is used to set the speed capabilities. It is only valid 
-for the SK-98xx V2.0 copper adapters.
-Usually, the speed is negotiated between the two ports during link 
-establishment. If this fails, a port can be forced to a specific setting
-with this parameter.
-
-Auto-Negotiation
-----------------
-Parameter:    AutoNeg_?
-Values:       On, Off, Sense
-Default:      On
-  
-The "Sense"-mode automatically detects whether the link partner supports
-auto-negotiation or not.
-
-Duplex Capabilities
--------------------
-Parameter:    DupCap_?
-Values:       Half, Full, Both
-Default:      Both
-
-This parameters is only relevant if auto-negotiation for this port is 
-not set to "Sense". If auto-negotiation is set to "On", all three values
-are possible. If it is set to "Off", only "Full" and "Half" are allowed.
-This parameter is useful if your link partner does not support all
-possible combinations.
-
-Flow Control
-------------
-Parameter:    FlowCtrl_?
-Values:       Sym, SymOrRem, LocSend, None
-Default:      SymOrRem
-
-This parameter can be used to set the flow control capabilities the 
-port reports during auto-negotiation. It can be set for each port 
-individually.
-Possible modes:
-   -- Sym      = Symmetric: both link partners are allowed to send 
-                  PAUSE frames
-   -- SymOrRem = SymmetricOrRemote: both or only remote partner 
-                  are allowed to send PAUSE frames
-   -- LocSend  = LocalSend: only local link partner is allowed 
-                  to send PAUSE frames
-   -- None     = no link partner is allowed to send PAUSE frames
-  
-NOTE: This parameter is ignored if auto-negotiation is set to "Off".
-
-Role in Master-Slave-Negotiation (1000Base-T only)
---------------------------------------------------
-Parameter:    Role_?
-Values:       Auto, Master, Slave
-Default:      Auto
-
-This parameter is only valid for the SK-9821 and SK-9822 adapters.
-For two 1000Base-T ports to communicate, one must take the role of the
-master (providing timing information), while the other must be the 
-slave. Usually, this is negotiated between the two ports during link 
-establishment. If this fails, a port can be forced to a specific setting
-with this parameter.
-
-
-4.2  Adapter Parameters
------------------------
-
-Connection Type (SK-98xx V2.0 copper adapters only)
----------------
-Parameter:    ConType
-Values:       Auto, 100FD, 100HD, 10FD, 10HD
-Default:      Auto
-
-The parameter 'ConType' is a combination of all five per-port parameters
-within one single parameter. This simplifies the configuration of both ports
-of an adapter card! The different values of this variable reflect the most 
-meaningful combinations of port parameters.
-
-The following table shows the values of 'ConType' and the corresponding
-combinations of the per-port parameters:
-
-    ConType   |  DupCap   AutoNeg   FlowCtrl   Role             Speed
-    ----------+------------------------------------------------------
-    Auto      |  Both     On        SymOrRem   Auto             Auto
-    100FD     |  Full     Off       None       Auto (ignored)   100
-    100HD     |  Half     Off       None       Auto (ignored)   100
-    10FD      |  Full     Off       None       Auto (ignored)   10
-    10HD      |  Half     Off       None       Auto (ignored)   10
-
-Stating any other port parameter together with this 'ConType' variable
-will result in a merged configuration of those settings. This due to 
-the fact, that the per-port parameters (e.g. Speed_? ) have a higher
-priority than the combined variable 'ConType'.
-
-NOTE: This parameter is always used on both ports of the adapter card.
-
-Interrupt Moderation
---------------------
-Parameter:    Moderation
-Values:       None, Static, Dynamic
-Default:      None
-
-Interrupt moderation is employed to limit the maximum number of interrupts
-the driver has to serve. That is, one or more interrupts (which indicate any
-transmit or receive packet to be processed) are queued until the driver 
-processes them. When queued interrupts are to be served, is determined by the
-'IntsPerSec' parameter, which is explained later below.
-
-Possible modes:
-
-   -- None - No interrupt moderation is applied on the adapter card. 
-      Therefore, each transmit or receive interrupt is served immediately
-      as soon as it appears on the interrupt line of the adapter card.
-
-   -- Static - Interrupt moderation is applied on the adapter card. 
-      All transmit and receive interrupts are queued until a complete
-      moderation interval ends. If such a moderation interval ends, all
-      queued interrupts are processed in one big bunch without any delay.
-      The term 'static' reflects the fact, that interrupt moderation is
-      always enabled, regardless how much network load is currently 
-      passing via a particular interface. In addition, the duration of
-      the moderation interval has a fixed length that never changes while
-      the driver is operational.
-
-   -- Dynamic - Interrupt moderation might be applied on the adapter card,
-      depending on the load of the system. If the driver detects that the
-      system load is too high, the driver tries to shield the system against 
-      too much network load by enabling interrupt moderation. If - at a later
-      time - the CPU utilization decreases again (or if the network load is 
-      negligible) the interrupt moderation will automatically be disabled.
-
-Interrupt moderation should be used when the driver has to handle one or more
-interfaces with a high network load, which - as a consequence - leads also to a
-high CPU utilization. When moderation is applied in such high network load 
-situations, CPU load might be reduced by 20-30%.
-
-NOTE: The drawback of using interrupt moderation is an increase of the round-
-trip-time (RTT), due to the queueing and serving of interrupts at dedicated
-moderation times.
-
-Interrupts per second
----------------------
-Parameter:    IntsPerSec
-Values:       30...40000 (interrupts per second)
-Default:      2000
-
-This parameter is only used if either static or dynamic interrupt moderation
-is used on a network adapter card. Using this parameter if no moderation is
-applied will lead to no action performed.
-
-This parameter determines the length of any interrupt moderation interval. 
-Assuming that static interrupt moderation is to be used, an 'IntsPerSec' 
-parameter value of 2000 will lead to an interrupt moderation interval of
-500 microseconds. 
-
-NOTE: The duration of the moderation interval is to be chosen with care.
-At first glance, selecting a very long duration (e.g. only 100 interrupts per 
-second) seems to be meaningful, but the increase of packet-processing delay 
-is tremendous. On the other hand, selecting a very short moderation time might
-compensate the use of any moderation being applied.
-
-
-Preferred Port
---------------
-Parameter:    PrefPort
-Values:       A, B
-Default:      A
-
-This is used to force the preferred port to A or B (on dual-port network 
-adapters). The preferred port is the one that is used if both are detected
-as fully functional.
-
-RLMT Mode (Redundant Link Management Technology)
-------------------------------------------------
-Parameter:    RlmtMode
-Values:       CheckLinkState,CheckLocalPort, CheckSeg, DualNet
-Default:      CheckLinkState
-
-RLMT monitors the status of the port. If the link of the active port 
-fails, RLMT switches immediately to the standby link. The virtual link is 
-maintained as long as at least one 'physical' link is up. 
-
-Possible modes:
-
-   -- CheckLinkState - Check link state only: RLMT uses the link state
-      reported by the adapter hardware for each individual port to 
-      determine whether a port can be used for all network traffic or 
-      not.
-
-   -- CheckLocalPort - In this mode, RLMT monitors the network path 
-      between the two ports of an adapter by regularly exchanging packets
-      between them. This mode requires a network configuration in which 
-      the two ports are able to "see" each other (i.e. there must not be 
-      any router between the ports).
-
-   -- CheckSeg - Check local port and segmentation: This mode supports the
-      same functions as the CheckLocalPort mode and additionally checks 
-      network segmentation between the ports. Therefore, this mode is only
-      to be used if Gigabit Ethernet switches are installed on the network
-      that have been configured to use the Spanning Tree protocol. 
-
-   -- DualNet - In this mode, ports A and B are used as separate devices. 
-      If you have a dual port adapter, port A will be configured as eth0 
-      and port B as eth1. Both ports can be used independently with 
-      distinct IP addresses. The preferred port setting is not used. 
-      RLMT is turned off.
-   
-NOTE: RLMT modes CLP and CLPSS are designed to operate in configurations 
-      where a network path between the ports on one adapter exists. 
-      Moreover, they are not designed to work where adapters are connected
-      back-to-back.
-***
-
-
-5  Large Frame Support
-======================
-
-The driver supports large frames (also called jumbo frames). Using large 
-frames can result in an improved throughput if transferring large amounts 
-of data.
-To enable large frames, set the MTU (maximum transfer unit) of the 
-interface to the desired value (up to 9000), execute the following 
-command:
-      ifconfig eth0 mtu 9000
-This will only work if you have two adapters connected back-to-back
-or if you use a switch that supports large frames. When using a switch, 
-it should be configured to allow large frames and auto-negotiation should  
-be set to OFF. The setting must be configured on all adapters that can be 
-reached by the large frames. If one adapter is not set to receive large 
-frames, it will simply drop them.
-
-You can switch back to the standard ethernet frame size by executing the 
-following command:
-      ifconfig eth0 mtu 1500
-
-To permanently configure this setting, add a script with the 'ifconfig' 
-line to the system startup sequence (named something like "S99sk98lin" 
-in /etc/rc.d/rc2.d).
-***
-
-
-6  VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
-==================================================================
-
-The Marvell Yukon/SysKonnect Linux drivers are able to support VLAN and 
-Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. 
-These features are only available after installation of open source 
-modules available on the Internet:
-For VLAN go to: http://www.candelatech.com/~greear/vlan.html
-For Link Aggregation go to: http://www.st.rim.or.jp/~yumo
-
-NOTE: SysKonnect GmbH does not offer any support for these open source 
-      modules and does not take the responsibility for any kind of 
-      failures or problems arising in connection with these modules.
-
-NOTE: Configuring Link Aggregation on a SysKonnect dual link adapter may 
-      cause problems when unloading the driver.
-
-
-7  Troubleshooting
-==================
-
-If any problems occur during the installation process, check the 
-following list:
-
-
-Problem:  The SK-98xx adapter cannot be found by the driver.
-Solution: In /proc/pci search for the following entry:
-             'Ethernet controller: SysKonnect SK-98xx ...'
-          If this entry exists, the SK-98xx or SK-98xx V2.0 adapter has 
-          been found by the system and should be operational.
-          If this entry does not exist or if the file '/proc/pci' is not 
-          found, there may be a hardware problem or the PCI support may 
-          not be enabled in your kernel.
-          The adapter can be checked using the diagnostics program which 
-          is available on the SysKonnect web site:
-          www.syskonnect.com
-          
-          Some COMPAQ machines have problems dealing with PCI under Linux.
-          This problem is described in the 'PCI howto' document
-          (included in some distributions or available from the
-          web, e.g. at 'www.linux.org'). 
-
-
-Problem:  Programs such as 'ifconfig' or 'route' cannot be found or the 
-          error message 'Operation not permitted' is displayed.
-Reason:   You are not logged in as user 'root'.
-Solution: Logout and login as 'root' or change to 'root' via 'su'.
-
-
-Problem:  Upon use of the command 'ping <address>' the message
-          "ping: sendto: Network is unreachable" is displayed.
-Reason:   Your route is not set correctly.
-Solution: If you are using RedHat, you probably forgot to set up the 
-          route in the 'network configuration'.
-          Check the existing routes with the 'route' command and check 
-          if an entry for 'eth0' exists, and if so, if it is set correctly.
-
-
-Problem:  The driver can be started, the adapter is connected to the 
-          network, but you cannot receive or transmit any packets; 
-          e.g. 'ping' does not work.
-Reason:   There is an incorrect route in your routing table.
-Solution: Check the routing table with the command 'route' and read the 
-          manual help pages dealing with routes (enter 'man route').
-
-NOTE: Although the 2.2.x kernel versions generate the routing entry 
-      automatically, problems of this kind may occur here as well. We've 
-      come across a situation in which the driver started correctly at 
-      system start, but after the driver has been removed and reloaded,
-      the route of the adapter's network pointed to the 'dummy0'device 
-      and had to be corrected manually.
-
-
-Problem:  Your computer should act as a router between multiple 
-          IP subnetworks (using multiple adapters), but computers in 
-          other subnetworks cannot be reached.
-Reason:   Either the router's kernel is not configured for IP forwarding 
-          or the routing table and gateway configuration of at least one 
-          computer is not working.
-
-Problem:  Upon driver start, the following error message is displayed:
-          "eth0: -- ERROR --
-          Class: internal Software error
-          Nr:    0xcc
-          Msg:   SkGeInitPort() cannot init running ports"
-Reason:   You are using a driver compiled for single processor machines 
-          on a multiprocessor machine with SMP (Symmetric MultiProcessor) 
-          kernel.
-Solution: Configure your kernel appropriately and recompile the kernel or
-          the modules.
-
-
-
-If your problem is not listed here, please contact SysKonnect's technical
-support for help (linux@syskonnect.de).
-When contacting our technical support, please ensure that the following 
-information is available:
-- System Manufacturer and HW Informations (CPU, Memory... )
-- PCI-Boards in your system
-- Distribution
-- Kernel version
-- Driver version
-***
-
-
-
-***End of Readme File***
diff --git a/Documentation/networking/spider_net.txt b/Documentation/networking/spider_net.txt
new file mode 100644
index 0000000..4b4adb8
--- /dev/null
+++ b/Documentation/networking/spider_net.txt
@@ -0,0 +1,204 @@
+
+            The Spidernet Device Driver
+            ===========================
+
+Written by Linas Vepstas <linas@austin.ibm.com>
+
+Version of 7 June 2007
+
+Abstract
+========
+This document sketches the structure of portions of the spidernet
+device driver in the Linux kernel tree. The spidernet is a gigabit
+ethernet device built into the Toshiba southbridge commonly used
+in the SONY Playstation 3 and the IBM QS20 Cell blade.
+
+The Structure of the RX Ring.
+=============================
+The receive (RX) ring is a circular linked list of RX descriptors,
+together with three pointers into the ring that are used to manage its
+contents.
+
+The elements of the ring are called "descriptors" or "descrs"; they
+describe the received data. This includes a pointer to a buffer
+containing the received data, the buffer size, and various status bits.
+
+There are three primary states that a descriptor can be in: "empty",
+"full" and "not-in-use".  An "empty" or "ready" descriptor is ready
+to receive data from the hardware. A "full" descriptor has data in it,
+and is waiting to be emptied and processed by the OS. A "not-in-use"
+descriptor is neither empty or full; it is simply not ready. It may
+not even have a data buffer in it, or is otherwise unusable.
+
+During normal operation, on device startup, the OS (specifically, the
+spidernet device driver) allocates a set of RX descriptors and RX
+buffers. These are all marked "empty", ready to receive data. This
+ring is handed off to the hardware, which sequentially fills in the
+buffers, and marks them "full". The OS follows up, taking the full
+buffers, processing them, and re-marking them empty.
+
+This filling and emptying is managed by three pointers, the "head"
+and "tail" pointers, managed by the OS, and a hardware current
+descriptor pointer (GDACTDPA). The GDACTDPA points at the descr
+currently being filled. When this descr is filled, the hardware
+marks it full, and advances the GDACTDPA by one.  Thus, when there is
+flowing RX traffic, every descr behind it should be marked "full",
+and everything in front of it should be "empty".  If the hardware
+discovers that the current descr is not empty, it will signal an
+interrupt, and halt processing.
+
+The tail pointer tails or trails the hardware pointer. When the
+hardware is ahead, the tail pointer will be pointing at a "full"
+descr. The OS will process this descr, and then mark it "not-in-use",
+and advance the tail pointer.  Thus, when there is flowing RX traffic,
+all of the descrs in front of the tail pointer should be "full", and
+all of those behind it should be "not-in-use". When RX traffic is not
+flowing, then the tail pointer can catch up to the hardware pointer.
+The OS will then note that the current tail is "empty", and halt
+processing.
+
+The head pointer (somewhat mis-named) follows after the tail pointer.
+When traffic is flowing, then the head pointer will be pointing at
+a "not-in-use" descr. The OS will perform various housekeeping duties
+on this descr. This includes allocating a new data buffer and
+dma-mapping it so as to make it visible to the hardware. The OS will
+then mark the descr as "empty", ready to receive data. Thus, when there
+is flowing RX traffic, everything in front of the head pointer should
+be "not-in-use", and everything behind it should be "empty". If no
+RX traffic is flowing, then the head pointer can catch up to the tail
+pointer, at which point the OS will notice that the head descr is
+"empty", and it will halt processing.
+
+Thus, in an idle system, the GDACTDPA, tail and head pointers will
+all be pointing at the same descr, which should be "empty". All of the
+other descrs in the ring should be "empty" as well.
+
+The show_rx_chain() routine will print out the the locations of the
+GDACTDPA, tail and head pointers. It will also summarize the contents
+of the ring, starting at the tail pointer, and listing the status
+of the descrs that follow.
+
+A typical example of the output, for a nearly idle system, might be
+
+net eth1: Total number of descrs=256
+net eth1: Chain tail located at descr=20
+net eth1: Chain head is at 20
+net eth1: HW curr desc (GDACTDPA) is at 21
+net eth1: Have 1 descrs with stat=x40800101
+net eth1: HW next desc (GDACNEXTDA) is at 22
+net eth1: Last 255 descrs with stat=xa0800000
+
+In the above, the hardware has filled in one descr, number 20. Both
+head and tail are pointing at 20, because it has not yet been emptied.
+Meanwhile, hw is pointing at 21, which is free.
+
+The "Have nnn decrs" refers to the descr starting at the tail: in this
+case, nnn=1 descr, starting at descr 20. The "Last nnn descrs" refers
+to all of the rest of the descrs, from the last status change. The "nnn"
+is a count of how many descrs have exactly the same status.
+
+The status x4... corresponds to "full" and status xa... corresponds
+to "empty". The actual value printed is RXCOMST_A.
+
+In the device driver source code, a different set of names are
+used for these same concepts, so that
+
+"empty" == SPIDER_NET_DESCR_CARDOWNED == 0xa
+"full"  == SPIDER_NET_DESCR_FRAME_END == 0x4
+"not in use" == SPIDER_NET_DESCR_NOT_IN_USE == 0xf
+
+
+The RX RAM full bug/feature
+===========================
+
+As long as the OS can empty out the RX buffers at a rate faster than
+the hardware can fill them, there is no problem. If, for some reason,
+the OS fails to empty the RX ring fast enough, the hardware GDACTDPA
+pointer will catch up to the head, notice the not-empty condition,
+ad stop. However, RX packets may still continue arriving on the wire.
+The spidernet chip can save some limited number of these in local RAM.
+When this local ram fills up, the spider chip will issue an interrupt
+indicating this (GHIINT0STS will show ERRINT, and the GRMFLLINT bit
+will be set in GHIINT1STS).  When the RX ram full condition occurs,
+a certain bug/feature is triggered that has to be specially handled.
+This section describes the special handling for this condition.
+
+When the OS finally has a chance to run, it will empty out the RX ring.
+In particular, it will clear the descriptor on which the hardware had
+stopped. However, once the hardware has decided that a certain
+descriptor is invalid, it will not restart at that descriptor; instead
+it will restart at the next descr. This potentially will lead to a
+deadlock condition, as the tail pointer will be pointing at this descr,
+which, from the OS point of view, is empty; the OS will be waiting for
+this descr to be filled. However, the hardware has skipped this descr,
+and is filling the next descrs. Since the OS doesn't see this, there
+is a potential deadlock, with the OS waiting for one descr to fill,
+while the hardware is waiting for a different set of descrs to become
+empty.
+
+A call to show_rx_chain() at this point indicates the nature of the
+problem. A typical print when the network is hung shows the following:
+
+net eth1: Spider RX RAM full, incoming packets might be discarded!
+net eth1: Total number of descrs=256
+net eth1: Chain tail located at descr=255
+net eth1: Chain head is at 255
+net eth1: HW curr desc (GDACTDPA) is at 0
+net eth1: Have 1 descrs with stat=xa0800000
+net eth1: HW next desc (GDACNEXTDA) is at 1
+net eth1: Have 127 descrs with stat=x40800101
+net eth1: Have 1 descrs with stat=x40800001
+net eth1: Have 126 descrs with stat=x40800101
+net eth1: Last 1 descrs with stat=xa0800000
+
+Both the tail and head pointers are pointing at descr 255, which is
+marked xa... which is "empty". Thus, from the OS point of view, there
+is nothing to be done. In particular, there is the implicit assumption
+that everything in front of the "empty" descr must surely also be empty,
+as explained in the last section. The OS is waiting for descr 255 to
+become non-empty, which, in this case, will never happen.
+
+The HW pointer is at descr 0. This descr is marked 0x4.. or "full".
+Since its already full, the hardware can do nothing more, and thus has
+halted processing. Notice that descrs 0 through 254 are all marked
+"full", while descr 254 and 255 are empty. (The "Last 1 descrs" is
+descr 254, since tail was at 255.) Thus, the system is deadlocked,
+and there can be no forward progress; the OS thinks there's nothing
+to do, and the hardware has nowhere to put incoming data.
+
+This bug/feature is worked around with the spider_net_resync_head_ptr()
+routine. When the driver receives RX interrupts, but an examination
+of the RX chain seems to show it is empty, then it is probable that
+the hardware has skipped a descr or two (sometimes dozens under heavy
+network conditions). The spider_net_resync_head_ptr() subroutine will
+search the ring for the next full descr, and the driver will resume
+operations there.  Since this will leave "holes" in the ring, there
+is also a spider_net_resync_tail_ptr() that will skip over such holes.
+
+As of this writing, the spider_net_resync() strategy seems to work very
+well, even under heavy network loads.
+
+
+The TX ring
+===========
+The TX ring uses a low-watermark interrupt scheme to make sure that
+the TX queue is appropriately serviced for large packet sizes.
+
+For packet sizes greater than about 1KBytes, the kernel can fill
+the TX ring quicker than the device can drain it. Once the ring
+is full, the netdev is stopped. When there is room in the ring,
+the netdev needs to be reawakened, so that more TX packets are placed
+in the ring. The hardware can empty the ring about four times per jiffy,
+so its not appropriate to wait for the poll routine to refill, since
+the poll routine runs only once per jiffy.  The low-watermark mechanism
+marks a descr about 1/4th of the way from the bottom of the queue, so
+that an interrupt is generated when the descr is processed. This
+interrupt wakes up the netdev, which can then refill the queue.
+For large packets, this mechanism generates a relatively small number
+of interrupts, about 1K/sec. For smaller packets, this will drop to zero
+interrupts, as the hardware can empty the queue faster than the kernel
+can fill it.
+
+
+ ======= END OF DOCUMENT ========
+
diff --git a/Documentation/networking/xfrm_sysctl.txt b/Documentation/networking/xfrm_sysctl.txt
new file mode 100644
index 0000000..5bbd167
--- /dev/null
+++ b/Documentation/networking/xfrm_sysctl.txt
@@ -0,0 +1,4 @@
+/proc/sys/net/core/xfrm_* Variables:
+
+xfrm_acq_expires - INTEGER
+	default 30 - hard timeout in seconds for acquire requests
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 7d5b60d..7f60dfe 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -86,6 +86,20 @@
 and do a replace of spaces to "\x" - that's what I do, as I'm too lazy 
 to write a program to automate this all).
 
+Alternatively, you can use the shell script in scripts/decodecode.
+Its usage is:  decodecode < oops.txt
+
+The hex bytes that follow "Code:" may (in some architectures) have a series
+of bytes that precede the current instruction pointer as well as bytes at and
+following the current instruction pointer.  In some cases, one instruction
+byte or word is surrounded by <> or (), as in "<86>" or "(f00d)".  These
+<> or () markings indicate the current instruction pointer.  Example from
+i386, split into multiple lines for readability:
+
+Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
+64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
+7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
+
 Finally, if you want to see where the code comes from, you can do
 
 	cd /usr/src/linux
@@ -237,6 +251,8 @@
   7: 'U' if a user or user application specifically requested that the
      Tainted flag be set, ' ' otherwise.
 
+  8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent: even if an offending module is
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index d38261b..7754f5a 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -113,9 +113,6 @@
 		(Please see Documentation/power/pci.txt for descriptions
 		of PCI Power Management and the related functions.)
 
-	enable_wake	Enable device to generate wake events from a low power
-			state.
-
 	shutdown	Hook into reboot_notifier_list (kernel/sys.c).
 			Intended to stop any idling DMA operations.
 			Useful for enabling wake-on-lan (NIC) or changing
@@ -299,7 +296,10 @@
 call pci_set_mwi().  This enables the PCI_COMMAND bit for Mem-Wr-Inval
 and also ensures that the cache line size register is set correctly.
 Check the return value of pci_set_mwi() as not all architectures
-or chip-sets may support Memory-Write-Invalidate.
+or chip-sets may support Memory-Write-Invalidate.  Alternatively,
+if Mem-Wr-Inval would be nice to have but is not required, call
+pci_try_set_mwi() to have the system do its best effort at enabling
+Mem-Wr-Inval.
 
 
 3.2 Request MMIO/IOP resources
diff --git a/Documentation/power/freezing-of-tasks.txt b/Documentation/power/freezing-of-tasks.txt
new file mode 100644
index 0000000..af1a282
--- /dev/null
+++ b/Documentation/power/freezing-of-tasks.txt
@@ -0,0 +1,160 @@
+Freezing of tasks
+	(C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
+
+I. What is the freezing of tasks?
+
+The freezing of tasks is a mechanism by which user space processes and some
+kernel threads are controlled during hibernation or system-wide suspend (on some
+architectures).
+
+II. How does it work?
+
+There are four per-task flags used for that, PF_NOFREEZE, PF_FROZEN, TIF_FREEZE
+and PF_FREEZER_SKIP (the last one is auxiliary).  The tasks that have
+PF_NOFREEZE unset (all user space processes and some kernel threads) are
+regarded as 'freezable' and treated in a special way before the system enters a
+suspend state as well as before a hibernation image is created (in what follows
+we only consider hibernation, but the description also applies to suspend).
+
+Namely, as the first step of the hibernation procedure the function
+freeze_processes() (defined in kernel/power/process.c) is called.  It executes
+try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
+sends a fake signal to each of them.  A task that receives such a signal and has
+TIF_FREEZE set, should react to it by calling the refrigerator() function
+(defined in kernel/power/process.c), which sets the task's PF_FROZEN flag,
+changes its state to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is
+cleared for it.  Then, we say that the task is 'frozen' and therefore the set of
+functions handling this mechanism is called 'the freezer' (these functions are
+defined in kernel/power/process.c and include/linux/freezer.h).  User space
+processes are generally frozen before kernel threads.
+
+It is not recommended to call refrigerator() directly.  Instead, it is
+recommended to use the try_to_freeze() function (defined in
+include/linux/freezer.h), that checks the task's TIF_FREEZE flag and makes the
+task enter refrigerator() if the flag is set.
+
+For user space processes try_to_freeze() is called automatically from the
+signal-handling code, but the freezable kernel threads need to call it
+explicitly in suitable places.  The code to do this may look like the following:
+
+	do {
+		hub_events();
+		wait_event_interruptible(khubd_wait,
+					!list_empty(&hub_event_list));
+		try_to_freeze();
+	} while (!signal_pending(current));
+
+(from drivers/usb/core/hub.c::hub_thread()).
+
+If a freezable kernel thread fails to call try_to_freeze() after the freezer has
+set TIF_FREEZE for it, the freezing of tasks will fail and the entire
+hibernation operation will be cancelled.  For this reason, freezable kernel
+threads must call try_to_freeze() somewhere.
+
+After the system memory state has been restored from a hibernation image and
+devices have been reinitialized, the function thaw_processes() is called in
+order to clear the PF_FROZEN flag for each frozen task.  Then, the tasks that
+have been frozen leave refrigerator() and continue running.
+
+III. Which kernel threads are freezable?
+
+Kernel threads are not freezable by default.  However, a kernel thread may clear
+PF_NOFREEZE for itself by calling set_freezable() (the resetting of PF_NOFREEZE
+directly is strongly discouraged).  From this point it is regarded as freezable
+and must call try_to_freeze() in a suitable place.
+
+IV. Why do we do that?
+
+Generally speaking, there is a couple of reasons to use the freezing of tasks:
+
+1. The principal reason is to prevent filesystems from being damaged after
+hibernation.  At the moment we have no simple means of checkpointing
+filesystems, so if there are any modifications made to filesystem data and/or
+metadata on disks, we cannot bring them back to the state from before the
+modifications.  At the same time each hibernation image contains some
+filesystem-related information that must be consistent with the state of the
+on-disk data and metadata after the system memory state has been restored from
+the image (otherwise the filesystems will be damaged in a nasty way, usually
+making them almost impossible to repair).  We therefore freeze tasks that might
+cause the on-disk filesystems' data and metadata to be modified after the
+hibernation image has been created and before the system is finally powered off.
+The majority of these are user space processes, but if any of the kernel threads
+may cause something like this to happen, they have to be freezable.
+
+2. The second reason is to prevent user space processes and some kernel threads
+from interfering with the suspending and resuming of devices.  A user space
+process running on a second CPU while we are suspending devices may, for
+example, be troublesome and without the freezing of tasks we would need some
+safeguards against race conditions that might occur in such a case.
+
+Although Linus Torvalds doesn't like the freezing of tasks, he said this in one
+of the discussions on LKML (http://lkml.org/lkml/2007/4/27/608):
+
+"RJW:> Why we freeze tasks at all or why we freeze kernel threads?
+
+Linus: In many ways, 'at all'.
+
+I _do_ realize the IO request queue issues, and that we cannot actually do
+s2ram with some devices in the middle of a DMA.  So we want to be able to
+avoid *that*, there's no question about that.  And I suspect that stopping
+user threads and then waiting for a sync is practically one of the easier
+ways to do so.
+
+So in practice, the 'at all' may become a 'why freeze kernel threads?' and
+freezing user threads I don't find really objectionable."
+
+Still, there are kernel threads that may want to be freezable.  For example, if
+a kernel that belongs to a device driver accesses the device directly, it in
+principle needs to know when the device is suspended, so that it doesn't try to
+access it at that time.  However, if the kernel thread is freezable, it will be
+frozen before the driver's .suspend() callback is executed and it will be
+thawed after the driver's .resume() callback has run, so it won't be accessing
+the device while it's suspended.
+
+3. Another reason for freezing tasks is to prevent user space processes from
+realizing that hibernation (or suspend) operation takes place.  Ideally, user
+space processes should not notice that such a system-wide operation has occurred
+and should continue running without any problems after the restore (or resume
+from suspend).  Unfortunately, in the most general case this is quite difficult
+to achieve without the freezing of tasks.  Consider, for example, a process
+that depends on all CPUs being online while it's running.  Since we need to
+disable nonboot CPUs during the hibernation, if this process is not frozen, it
+may notice that the number of CPUs has changed and may start to work incorrectly
+because of that.
+
+V. Are there any problems related to the freezing of tasks?
+
+Yes, there are.
+
+First of all, the freezing of kernel threads may be tricky if they depend one
+on another.  For example, if kernel thread A waits for a completion (in the
+TASK_UNINTERRUPTIBLE state) that needs to be done by freezable kernel thread B
+and B is frozen in the meantime, then A will be blocked until B is thawed, which
+may be undesirable.  That's why kernel threads are not freezable by default.
+
+Second, there are the following two problems related to the freezing of user
+space processes:
+1. Putting processes into an uninterruptible sleep distorts the load average.
+2. Now that we have FUSE, plus the framework for doing device drivers in
+userspace, it gets even more complicated because some userspace processes are
+now doing the sorts of things that kernel threads do
+(https://lists.linux-foundation.org/pipermail/linux-pm/2007-May/012309.html).
+
+The problem 1. seems to be fixable, although it hasn't been fixed so far.  The
+other one is more serious, but it seems that we can work around it by using
+hibernation (and suspend) notifiers (in that case, though, we won't be able to
+avoid the realization by the user space processes that the hibernation is taking
+place).
+
+There are also problems that the freezing of tasks tends to expose, although
+they are not directly related to it.  For example, if request_firmware() is
+called from a device driver's .resume() routine, it will timeout and eventually
+fail, because the user land process that should respond to the request is frozen
+at this point.  So, seemingly, the failure is due to the freezing of tasks.
+Suppose, however, that the firmware file is located on a filesystem accessible
+only through another device that hasn't been resumed yet.  In that case,
+request_firmware() will fail regardless of whether or not the freezing of tasks
+is used.  Consequently, the problem is not really related to the freezing of
+tasks, since it generally exists anyway.  [The solution to this particular
+problem is to keep the firmware in memory after it's loaded for the first time
+and upload if from memory to the device whenever necessary.]
diff --git a/Documentation/power/kernel_threads.txt b/Documentation/power/kernel_threads.txt
deleted file mode 100644
index fb57784..0000000
--- a/Documentation/power/kernel_threads.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-KERNEL THREADS
-
-
-Freezer
-
-Upon entering a suspended state the system will freeze all
-tasks. This is done by delivering pseudosignals. This affects
-kernel threads, too. To successfully freeze a kernel thread
-the thread has to check for the pseudosignal and enter the
-refrigerator. Code to do this looks like this:
-
-	do {
-		hub_events();
-		wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
-		try_to_freeze();
-	} while (!signal_pending(current));
-
-from drivers/usb/core/hub.c::hub_thread()
-
-
-The Unfreezable
-
-Some kernel threads however, must not be frozen. The kernel must
-be able to finish pending IO operations and later on be able to
-write the memory image to disk. Kernel threads needed to do IO
-must stay awake. Such threads must mark themselves unfreezable
-like this:
-
-	/*
-	 * This thread doesn't need any user-level access,
-	 * so get rid of all our resources.
-	 */
-	daemonize("usb-storage");
-
-	current->flags |= PF_NOFREEZE;
-
-from drivers/usb/storage/usb.c::usb_stor_control_thread()
-
-Such drivers are themselves responsible for staying quiet during
-the actual snapshotting.
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index e00b099..dd8fe43 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -164,7 +164,6 @@
 
         int  (*suspend) (struct pci_dev *dev, pm_message_t state);
         int  (*resume) (struct pci_dev *dev);
-        int  (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable);
 
 
 suspend
@@ -251,42 +250,6 @@
 this function, except for PM-capable devices when pci_set_power_state is used.
 
 
-enable_wake
------------
-
-Usage:
-
-if (dev->driver && dev->driver->enable_wake)
-	dev->driver->enable_wake(dev,state,enable);
-
-This callback is generally only relevant for devices that support the PCI PM
-spec and have the ability to generate a PME# (Power Management Event Signal)
-to wake the system up. (However, it is possible that a device may support 
-some non-standard way of generating a wake event on sleep.)
-
-Bits 15:11 of the PMC (Power Mgmt Capabilities) Register in a device's
-PM Capabilities describe what power states the device supports generating a 
-wake event from:
-
-+------------------+
-|  Bit  |  State   |
-+------------------+
-|  11   |   D0     |
-|  12   |   D1     |
-|  13   |   D2     |
-|  14   |   D3hot  |
-|  15   |   D3cold |
-+------------------+
-
-A device can use this to enable wake events:
-
-	 pci_enable_wake(dev,state,enable);
-
-Note that to enable PME# from D3cold, a value of 4 should be passed to 
-pci_enable_wake (since it uses an index into a bitmask). If a driver gets
-a request to enable wake events from D3, two calls should be made to 
-pci_enable_wake (one for both D3hot and D3cold).
-
 
 A reference implementation
 -------------------------
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 5b8d695..aea7e92 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -140,21 +140,11 @@
 website, and not to the Linux Kernel Mailing List. We are working
 toward merging suspend2 into the mainline kernel.
 
-Q: A kernel thread must voluntarily freeze itself (call 'refrigerator').
-I found some kernel threads that don't do it, and they don't freeze
-so the system can't sleep. Is this a known behavior?
+Q: What is the freezing of tasks and why are we using it?
 
-A: All such kernel threads need to be fixed, one by one. Select the
-place where the thread is safe to be frozen (no kernel semaphores
-should be held at that point and it must be safe to sleep there), and
-add:
-
-       try_to_freeze();
-
-If the thread is needed for writing the image to storage, you should
-instead set the PF_NOFREEZE process flag when creating the thread (and
-be very careful).
-
+A: The freezing of tasks is a mechanism by which user space processes and some
+kernel threads are controlled during hibernation or system-wide suspend (on some
+architectures).  See freezing-of-tasks.txt for details.
 
 Q: What is the difference between "platform" and "shutdown"?
 
@@ -393,6 +383,9 @@
 Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays)
 before suspending; then remount them after resuming.
 
+There is a work-around for this problem.  For more information, see
+Documentation/usb/persist.txt.
+
 Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
 compiled with the similar configuration files. Anyway I found that
 suspend to disk (and resume) is much slower on 2.6.16 compared to
diff --git a/Documentation/power_supply_class.txt b/Documentation/power_supply_class.txt
new file mode 100644
index 0000000..9758cf4
--- /dev/null
+++ b/Documentation/power_supply_class.txt
@@ -0,0 +1,167 @@
+Linux power supply class
+========================
+
+Synopsis
+~~~~~~~~
+Power supply class used to represent battery, UPS, AC or DC power supply
+properties to user-space.
+
+It defines core set of attributes, which should be applicable to (almost)
+every power supply out there. Attributes are available via sysfs and uevent
+interfaces.
+
+Each attribute has well defined meaning, up to unit of measure used. While
+the attributes provided are believed to be universally applicable to any
+power supply, specific monitoring hardware may not be able to provide them
+all, so any of them may be skipped.
+
+Power supply class is extensible, and allows to define drivers own attributes.
+The core attribute set is subject to the standard Linux evolution (i.e.
+if it will be found that some attribute is applicable to many power supply
+types or their drivers, it can be added to the core set).
+
+It also integrates with LED framework, for the purpose of providing
+typically expected feedback of battery charging/fully charged status and
+AC/USB power supply online status. (Note that specific details of the
+indication (including whether to use it at all) are fully controllable by
+user and/or specific machine defaults, per design principles of LED
+framework).
+
+
+Attributes/properties
+~~~~~~~~~~~~~~~~~~~~~
+Power supply class has predefined set of attributes, this eliminates code
+duplication across drivers. Power supply class insist on reusing its
+predefined attributes *and* their units.
+
+So, userspace gets predictable set of attributes and their units for any
+kind of power supply, and can process/present them to a user in consistent
+manner. Results for different power supplies and machines are also directly
+comparable.
+
+See drivers/power/ds2760_battery.c and drivers/power/pda_power.c for the
+example how to declare and handle attributes.
+
+
+Units
+~~~~~
+Quoting include/linux/power_supply.h:
+
+  All voltages, currents, charges, energies, time and temperatures in µV,
+  µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+  stated. It's driver's job to convert its raw values to units in which
+  this class operates.
+
+
+Attributes/properties detailed
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+~ ~ ~ ~ ~ ~ ~  Charge/Energy/Capacity - how to not confuse  ~ ~ ~ ~ ~ ~ ~
+~                                                                       ~
+~ Because both "charge" (µAh) and "energy" (µWh) represents "capacity"  ~
+~ of battery, this class distinguish these terms. Don't mix them!       ~
+~                                                                       ~
+~ CHARGE_* attributes represents capacity in µAh only.                  ~
+~ ENERGY_* attributes represents capacity in µWh only.                  ~
+~ CAPACITY attribute represents capacity in *percents*, from 0 to 100.  ~
+~                                                                       ~
+~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+Postfixes:
+_AVG - *hardware* averaged value, use it if your hardware is really able to
+report averaged values.
+_NOW - momentary/instantaneous values.
+
+STATUS - this attribute represents operating status (charging, full,
+discharging (i.e. powering a load), etc.). This corresponds to
+BATTERY_STATUS_* values, as defined in battery.h.
+
+HEALTH - represents health of the battery, values corresponds to
+POWER_SUPPLY_HEALTH_*, defined in battery.h.
+
+VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and
+minimal power supply voltages. Maximal/minimal means values of voltages
+when battery considered "full"/"empty" at normal conditions. Yes, there is
+no direct relation between voltage and battery capacity, but some dumb
+batteries use voltage for very approximated calculation of capacity.
+Battery driver also can use this attribute just to inform userspace
+about maximal and minimal voltage thresholds of a given battery.
+
+CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when
+battery considered full/empty.
+
+ENERGY_FULL_DESIGN, ENERGY_EMPTY_DESIGN - same as above but for energy.
+
+CHARGE_FULL, CHARGE_EMPTY - These attributes means "last remembered value
+of charge when battery became full/empty". It also could mean "value of
+charge when battery considered full/empty at given conditions (temperature,
+age)". I.e. these attributes represents real thresholds, not design values.
+
+ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
+
+CAPACITY - capacity in percents.
+CAPACITY_LEVEL - capacity level. This corresponds to
+POWER_SUPPLY_CAPACITY_LEVEL_*.
+
+TEMP - temperature of the power supply.
+TEMP_AMBIENT - ambient temperature.
+
+TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
+while battery powers a load)
+TIME_TO_FULL - seconds left for battery to be considered full (i.e.
+while battery is charging)
+
+
+Battery <-> external power supply interaction
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Often power supplies are acting as supplies and supplicants at the same
+time. Batteries are good example. So, batteries usually care if they're
+externally powered or not.
+
+For that case, power supply class implements notification mechanism for
+batteries.
+
+External power supply (AC) lists supplicants (batteries) names in
+"supplied_to" struct member, and each power_supply_changed() call
+issued by external power supply will notify supplicants via
+external_power_changed callback.
+
+
+QA
+~~
+Q: Where is POWER_SUPPLY_PROP_XYZ attribute?
+A: If you cannot find attribute suitable for your driver needs, feel free
+   to add it and send patch along with your driver.
+
+   The attributes available currently are the ones currently provided by the
+   drivers written.
+
+   Good candidates to add in future: model/part#, cycle_time, manufacturer,
+   etc.
+
+
+Q: I have some very specific attribute (e.g. battery color), should I add
+   this attribute to standard ones?
+A: Most likely, no. Such attribute can be placed in the driver itself, if
+   it is useful. Of course, if the attribute in question applicable to
+   large set of batteries, provided by many drivers, and/or comes from
+   some general battery specification/standard, it may be a candidate to
+   be added to the core attribute set.
+
+
+Q: Suppose, my battery monitoring chip/firmware does not provides capacity
+   in percents, but provides charge_{now,full,empty}. Should I calculate
+   percentage capacity manually, inside the driver, and register CAPACITY
+   attribute? The same question about time_to_empty/time_to_full.
+A: Most likely, no. This class is designed to export properties which are
+   directly measurable by the specific hardware available.
+
+   Inferring not available properties using some heuristics or mathematical
+   model is not subject of work for a battery driver. Such functionality
+   should be factored out, and in fact, apm_power, the driver to serve
+   legacy APM API on top of power supply class, uses a simple heuristic of
+   approximating remaining battery capacity based on its charge, current,
+   voltage and so on. But full-fledged battery model is likely not subject
+   for kernel at all, as it would require floating point calculation to deal
+   with things like differential equations and Kalman filters. This is
+   better be handled by batteryd/libbattery, yet to be written.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index b49ce16..0c24348 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1,7 +1,6 @@
            Booting the Linux/ppc kernel without Open Firmware
            --------------------------------------------------
 
-
 (c) 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>,
     IBM Corp.
 (c) 2005 Becky Bruce <becky.bruce at freescale.com>,
@@ -9,6 +8,63 @@
 (c) 2006 MontaVista Software, Inc.
     Flash chip node definition
 
+Table of Contents
+=================
+
+  I - Introduction
+    1) Entry point for arch/powerpc
+    2) Board support
+
+  II - The DT block format
+    1) Header
+    2) Device tree generalities
+    3) Device tree "structure" block
+    4) Device tree "strings" block
+
+  III - Required content of the device tree
+    1) Note about cells and address representation
+    2) Note about "compatible" properties
+    3) Note about "name" properties
+    4) Note about node and property names and character set
+    5) Required nodes and properties
+      a) The root node
+      b) The /cpus node
+      c) The /cpus/* nodes
+      d) the /memory node(s)
+      e) The /chosen node
+      f) the /soc<SOCname> node
+
+  IV - "dtc", the device tree compiler
+
+  V - Recommendations for a bootloader
+
+  VI - System-on-a-chip devices and nodes
+    1) Defining child nodes of an SOC
+    2) Representing devices without a current OF specification
+      a) MDIO IO device
+      b) Gianfar-compatible ethernet nodes
+      c) PHY nodes
+      d) Interrupt controllers
+      e) I2C
+      f) Freescale SOC USB controllers
+      g) Freescale SOC SEC Security Engines
+      h) Board Control and Status (BCSR)
+      i) Freescale QUICC Engine module (QE)
+      j) Flash chip nodes
+      k) Global Utilities Block
+
+  VII - Specifying interrupt information for devices
+    1) interrupts property
+    2) interrupt-parent property
+    3) OpenPIC Interrupt Controllers
+    4) ISA Interrupt Controllers
+
+  Appendix A - Sample SOC node for MPC8540
+
+
+Revision Information
+====================
+
    May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.
 
    May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or
@@ -571,6 +627,14 @@
 a list of properties, a list of child nodes, and an end token. Every
 child node is a full node structure itself as defined above.
 
+NOTE: The above definition requires that all property definitions for
+a particular node MUST precede any subnode definitions for that node.
+Although the structure would not be ambiguous if properties and
+subnodes were intermingled, the kernel parser requires that the
+properties come first (up until at least 2.6.22).  Any tools
+manipulating a flattened tree must take care to preserve this
+constraint.
+
 4) Device tree "strings" block
 
 In order to save space, property names, which are generally redundant,
@@ -1687,7 +1751,7 @@
 		};
 	};
 
-    g) Flash chip nodes
+    j) Flash chip nodes
 
     Flash chips (Memory Technology Devices) are often used for solid state
     file systems on embedded devices.
@@ -1727,6 +1791,33 @@
  		partition-names = "fs\0firmware";
  	};
 
+   k) Global Utilities Block
+
+   The global utilities block controls power management, I/O device
+   enabling, power-on-reset configuration monitoring, general-purpose
+   I/O signal configuration, alternate function selection for multiplexed
+   signals, and clock control.
+
+   Required properties:
+
+    - compatible : Should define the compatible device type for
+      global-utilities.
+    - reg : Offset and length of the register set for the device.
+
+  Recommended properties:
+
+    - fsl,has-rstcr : Indicates that the global utilities register set
+      contains a functioning "reset control register" (i.e. the board
+      is wired to reset upon setting the HRESET_REQ bit in this register).
+
+    Example:
+
+	global-utilities@e0000 {	/* global utilities block */
+		compatible = "fsl,mpc8548-guts";
+		reg = <e0000 1000>;
+		fsl,has-rstcr;
+	};
+
    More devices will be defined as this spec matures.
 
 VII - Specifying interrupt information for devices
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 7c701b8..c931d61 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -385,7 +385,7 @@
 		/* not all RTCs support periodic IRQs */
 		if (errno == ENOTTY) {
 			fprintf(stderr, "\nNo periodic IRQ support\n");
-			return 0;
+			goto done;
 		}
 		perror("RTC_IRQP_READ ioctl");
 		exit(errno);
diff --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt
index 05a2b4f..58919d6 100644
--- a/Documentation/s390/cds.txt
+++ b/Documentation/s390/cds.txt
@@ -51,13 +51,8 @@
 * The interrupt handlers must be adapted to use a ccw_device as argument.
   Moreover, they don't return a devstat, but an irb.
 * Before initiating an io, the options must be set via ccw_device_set_options().
-
-read_dev_chars()	
-   read device characteristics
-   
-read_conf_data()
-read_conf_data_lpm()
-   read configuration data.
+* Instead of calling read_dev_chars()/read_conf_data(), the driver issues
+  the channel program and handles the interrupt itself.
 
 ccw_device_get_ciw()
    get commands from extended sense data.
@@ -130,11 +125,6 @@
 has to call every single device driver registered on this IRQ in order to
 determine the device driver owning the device that raised the interrupt.
 
-In order not to introduce a new I/O concept to the common Linux code,
-Linux/390 preserves the IRQ concept and semantically maps the ESA/390
-subchannels to Linux as IRQs. This allows Linux/390 to support up to 64k
-different IRQs, uniquely representing a single device each.
-
 Up to kernel 2.4, Linux/390 used to provide interfaces via the IRQ (subchannel).
 For internal use of the common I/O layer, these are still there. However, 
 device drivers should use the new calling interface via the ccw_device only.
@@ -151,9 +141,8 @@
 support using the information saved in the struct ccw_device given to them.
 This methods implies that Linux/390 doesn't require to probe for free (not
 armed) interrupt request lines (IRQs) to drive its devices with. Where
-applicable, the device drivers can use the read_dev_chars() to retrieve device
-characteristics. This can be done without having to request device ownership
-previously.
+applicable, the device drivers can use issue the READ DEVICE CHARACTERISTICS
+ccw to retrieve device characteristics in its online routine.
 
 In order to allow for easy I/O initiation the CDS layer provides a
 ccw_device_start() interface that takes a device specific channel program (one
@@ -170,69 +159,6 @@
 also covered by ccw_device_halt().
 
 
-read_dev_chars() - Read Device Characteristics
-
-This routine returns the characteristics for the device specified.
-
-The function is meant to be called with the device already enabled; that is,
-at earliest during set_online() processing.
-
-The ccw_device must not be locked prior to calling read_dev_chars().
-
-The function may be called enabled or disabled.
-
-int read_dev_chars(struct ccw_device *cdev, void **buffer, int length );
-
-cdev   - the ccw_device the information is requested for.
-buffer - pointer to a buffer pointer. The buffer pointer itself
-         must contain a valid buffer area.
-length - length of the buffer provided.
-
-The read_dev_chars() function returns :
-
-      0 - successful completion
--ENODEV - cdev invalid
--EINVAL - an invalid parameter was detected, or the function was called early.
--EBUSY  - an irrecoverable I/O error occurred or the device is not
-          operational.
-
-
-read_conf_data(), read_conf_data_lpm() - Read Configuration Data
-
-Retrieve the device dependent configuration data. Please have a look at your 
-device dependent I/O commands for the device specific layout of the node 
-descriptor elements. read_conf_data_lpm() will retrieve the configuration data
-for a specific path.
-
-The function is meant to be called with the device already enabled; that is,
-at earliest during set_online() processing.
-
-The function may be called enabled or disabled, but the device must not be
-locked
-
-int read_conf_data(struct ccw_device, void **buffer, int *length);
-int read_conf_data_lpm(struct ccw_device, void **buffer, int *length, __u8 lpm);
-
-cdev   - the ccw_device the data is requested for.
-buffer - Pointer to a buffer pointer. The read_conf_data() routine
-         will allocate a buffer and initialize the buffer pointer
-         accordingly. It's the device driver's responsibility to
-         release the kernel memory if no longer needed. 
-length - Length of the buffer allocated and retrieved.
-lpm    - Logical path mask to be used for retrieving the data. If
-         zero the data is retrieved on the next path available.
-
-The read_conf_data() function returns :
-          0 - Successful completion
--ENODEV     - cdev invalid.
--EINVAL     - An invalid parameter was detected, or the function was called early.
--EIO        - An irrecoverable I/O error occurred or the device is
-              not operational.
--ENOMEM     - The read_conf_data() routine couldn't obtain storage.
--EOPNOTSUPP - The device doesn't support the read configuration 
-              data command.
-
-
 get_ciw() - get command information word
 
 This call enables a device driver to get information about supported commands
diff --git a/Documentation/sched-design-CFS.txt b/Documentation/sched-design-CFS.txt
new file mode 100644
index 0000000..16feebb
--- /dev/null
+++ b/Documentation/sched-design-CFS.txt
@@ -0,0 +1,119 @@
+
+This is the CFS scheduler.
+
+80% of CFS's design can be summed up in a single sentence: CFS basically
+models an "ideal, precise multi-tasking CPU" on real hardware.
+
+"Ideal multi-tasking CPU" is a (non-existent  :-))  CPU that has 100%
+physical power and which can run each task at precise equal speed, in
+parallel, each at 1/nr_running speed. For example: if there are 2 tasks
+running then it runs each at 50% physical power - totally in parallel.
+
+On real hardware, we can run only a single task at once, so while that
+one task runs, the other tasks that are waiting for the CPU are at a
+disadvantage - the current task gets an unfair amount of CPU time. In
+CFS this fairness imbalance is expressed and tracked via the per-task
+p->wait_runtime (nanosec-unit) value. "wait_runtime" is the amount of
+time the task should now run on the CPU for it to become completely fair
+and balanced.
+
+( small detail: on 'ideal' hardware, the p->wait_runtime value would
+  always be zero - no task would ever get 'out of balance' from the
+  'ideal' share of CPU time. )
+
+CFS's task picking logic is based on this p->wait_runtime value and it
+is thus very simple: it always tries to run the task with the largest
+p->wait_runtime value. In other words, CFS tries to run the task with
+the 'gravest need' for more CPU time. So CFS always tries to split up
+CPU time between runnable tasks as close to 'ideal multitasking
+hardware' as possible.
+
+Most of the rest of CFS's design just falls out of this really simple
+concept, with a few add-on embellishments like nice levels,
+multiprocessing and various algorithm variants to recognize sleepers.
+
+In practice it works like this: the system runs a task a bit, and when
+the task schedules (or a scheduler tick happens) the task's CPU usage is
+'accounted for': the (small) time it just spent using the physical CPU
+is deducted from p->wait_runtime. [minus the 'fair share' it would have
+gotten anyway]. Once p->wait_runtime gets low enough so that another
+task becomes the 'leftmost task' of the time-ordered rbtree it maintains
+(plus a small amount of 'granularity' distance relative to the leftmost
+task so that we do not over-schedule tasks and trash the cache) then the
+new leftmost task is picked and the current task is preempted.
+
+The rq->fair_clock value tracks the 'CPU time a runnable task would have
+fairly gotten, had it been runnable during that time'. So by using
+rq->fair_clock values we can accurately timestamp and measure the
+'expected CPU time' a task should have gotten. All runnable tasks are
+sorted in the rbtree by the "rq->fair_clock - p->wait_runtime" key, and
+CFS picks the 'leftmost' task and sticks to it. As the system progresses
+forwards, newly woken tasks are put into the tree more and more to the
+right - slowly but surely giving a chance for every task to become the
+'leftmost task' and thus get on the CPU within a deterministic amount of
+time.
+
+Some implementation details:
+
+ - the introduction of Scheduling Classes: an extensible hierarchy of
+   scheduler modules. These modules encapsulate scheduling policy
+   details and are handled by the scheduler core without the core
+   code assuming about them too much.
+
+ - sched_fair.c implements the 'CFS desktop scheduler': it is a
+   replacement for the vanilla scheduler's SCHED_OTHER interactivity
+   code.
+
+   I'd like to give credit to Con Kolivas for the general approach here:
+   he has proven via RSDL/SD that 'fair scheduling' is possible and that
+   it results in better desktop scheduling. Kudos Con!
+
+   The CFS patch uses a completely different approach and implementation
+   from RSDL/SD. My goal was to make CFS's interactivity quality exceed
+   that of RSDL/SD, which is a high standard to meet :-) Testing
+   feedback is welcome to decide this one way or another. [ and, in any
+   case, all of SD's logic could be added via a kernel/sched_sd.c module
+   as well, if Con is interested in such an approach. ]
+
+   CFS's design is quite radical: it does not use runqueues, it uses a
+   time-ordered rbtree to build a 'timeline' of future task execution,
+   and thus has no 'array switch' artifacts (by which both the vanilla
+   scheduler and RSDL/SD are affected).
+
+   CFS uses nanosecond granularity accounting and does not rely on any
+   jiffies or other HZ detail. Thus the CFS scheduler has no notion of
+   'timeslices' and has no heuristics whatsoever. There is only one
+   central tunable:
+
+         /proc/sys/kernel/sched_granularity_ns
+
+   which can be used to tune the scheduler from 'desktop' (low
+   latencies) to 'server' (good batching) workloads. It defaults to a
+   setting suitable for desktop workloads. SCHED_BATCH is handled by the
+   CFS scheduler module too.
+
+   Due to its design, the CFS scheduler is not prone to any of the
+   'attacks' that exist today against the heuristics of the stock
+   scheduler: fiftyp.c, thud.c, chew.c, ring-test.c, massive_intr.c all
+   work fine and do not impact interactivity and produce the expected
+   behavior.
+
+   the CFS scheduler has a much stronger handling of nice levels and
+   SCHED_BATCH: both types of workloads should be isolated much more
+   agressively than under the vanilla scheduler.
+
+   ( another detail: due to nanosec accounting and timeline sorting,
+     sched_yield() support is very simple under CFS, and in fact under
+     CFS sched_yield() behaves much better than under any other
+     scheduler i have tested so far. )
+
+ - sched_rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler
+   way than the vanilla scheduler does. It uses 100 runqueues (for all
+   100 RT priority levels, instead of 140 in the vanilla scheduler)
+   and it needs no expired array.
+
+ - reworked/sanitized SMP load-balancing: the runqueue-walking
+   assumptions are gone from the load-balancing code now, and
+   iterators of the scheduling modules are used. The balancing code got
+   quite a bit simpler as a result.
+
diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
index ce3cb42..cc12b55 100644
--- a/Documentation/scsi/aacraid.txt
+++ b/Documentation/scsi/aacraid.txt
@@ -50,6 +50,9 @@
 	9005:0285:9005:02be	Adaptec	31605 (Marauder160)
 	9005:0285:9005:02c3	Adaptec	51205 (Voodoo120)
 	9005:0285:9005:02c4	Adaptec	51605 (Voodoo160)
+	9005:0285:9005:02ce	Adaptec	51245 (Voodoo124)
+	9005:0285:9005:02cf	Adaptec	51645 (Voodoo164)
+	9005:0285:9005:02d0	Adaptec	52445 (Voodoo244)
 	1011:0046:9005:0364	Adaptec	5400S (Mustang)
 	9005:0287:9005:0800	Adaptec	Themisto (Jupiter)
 	9005:0200:9005:0200	Adaptec	Themisto (Jupiter)
diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.txt
new file mode 100644
index 0000000..d403e46
--- /dev/null
+++ b/Documentation/scsi/scsi_fc_transport.txt
@@ -0,0 +1,450 @@
+                             SCSI FC Tansport
+                 =============================================
+
+Date:  4/12/2007
+Kernel Revisions for features:
+  rports : <<TBS>>
+  vports : 2.6.22 (? TBD)
+
+
+Introduction
+============
+This file documents the features and components of the SCSI FC Transport.
+It also provides documents the API between the transport and FC LLDDs.
+The FC transport can be found at:
+  drivers/scsi/scsi_transport_fc.c
+  include/scsi/scsi_transport_fc.h
+  include/scsi/scsi_netlink_fc.h
+
+This file is found at Documentation/scsi/scsi_fc_transport.txt
+
+
+FC Remote Ports (rports)
+========================================================================
+<< To Be Supplied >>
+
+
+FC Virtual Ports (vports)
+========================================================================
+
+Overview:
+-------------------------------
+
+  New FC standards have defined mechanisms which allows for a single physical
+  port to appear on as multiple communication ports. Using the N_Port Id
+  Virtualization (NPIV) mechanism, a point-to-point connection to a Fabric
+  can be assigned more than 1 N_Port_ID.  Each N_Port_ID appears as a
+  separate port to other endpoints on the fabric, even though it shares one
+  physical link to the switch for communication. Each N_Port_ID can have a
+  unique view of the fabric based on fabric zoning and array lun-masking
+  (just like a normal non-NPIV adapter).  Using the Virtual Fabric (VF)
+  mechanism, adding a fabric header to each frame allows the port to
+  interact with the Fabric Port to join multiple fabrics. The port will
+  obtain an N_Port_ID on each fabric it joins. Each fabric will have its
+  own unique view of endpoints and configuration parameters.  NPIV may be
+  used together with VF so that the port can obtain multiple N_Port_IDs
+  on each virtual fabric.
+
+  The FC transport is now recognizing a new object - a vport.  A vport is
+  an entity that has a world-wide unique World Wide Port Name (wwpn) and
+  World Wide Node Name (wwnn). The transport also allows for the FC4's to
+  be specified for the vport, with FCP_Initiator being the primary role
+  expected. Once instantiated by one of the above methods, it will have a
+  distinct N_Port_ID and view of fabric endpoints and storage entities.
+  The fc_host associated with the physical adapter will export the ability
+  to create vports. The transport will create the vport object within the
+  Linux device tree, and instruct the fc_host's driver to instantiate the
+  virtual port. Typically, the driver will create a new scsi_host instance
+  on the vport, resulting in a unique <H,C,T,L> namespace for the vport.
+  Thus, whether a FC port is based on a physical port or on a virtual port,
+  each will appear as a unique scsi_host with its own target and lun space.
+
+  Note: At this time, the transport is written to create only NPIV-based
+    vports. However, consideration was given to VF-based vports and it
+    should be a minor change to add support if needed.  The remaining
+    discussion will concentrate on NPIV.
+
+  Note: World Wide Name assignment (and uniqueness guarantees) are left
+    up to an administrative entity controling the vport. For example,
+    if vports are to be associated with virtual machines, a XEN mgmt
+    utility would be responsible for creating wwpn/wwnn's for the vport,
+    using it's own naming authority and OUI. (Note: it already does this
+    for virtual MAC addresses).
+
+
+Device Trees and Vport Objects:
+-------------------------------
+
+  Today, the device tree typically contains the scsi_host object,
+  with rports and scsi target objects underneath it. Currently the FC
+  transport creates the vport object and places it under the scsi_host
+  object corresponding to the physical adapter.  The LLDD will allocate
+  a new scsi_host for the vport and link it's object under the vport.
+  The remainder of the tree under the vports scsi_host is the same
+  as the non-NPIV case. The transport is written currently to easily
+  allow the parent of the vport to be something other than the scsi_host.
+  This could be used in the future to link the object onto a vm-specific
+  device tree. If the vport's parent is not the physical port's scsi_host,
+  a symbolic link to the vport object will be placed in the physical
+  port's scsi_host.
+
+  Here's what to expect in the device tree :
+   The typical Physical Port's Scsi_Host:
+     /sys/devices/.../host17/
+   and it has the typical decendent tree:
+     /sys/devices/.../host17/rport-17:0-0/target17:0:0/17:0:0:0:
+   and then the vport is created on the Physical Port:
+     /sys/devices/.../host17/vport-17:0-0
+   and the vport's Scsi_Host is then created:
+     /sys/devices/.../host17/vport-17:0-0/host18
+   and then the rest of the tree progresses, such as:
+     /sys/devices/.../host17/vport-17:0-0/host18/rport-18:0-0/target18:0:0/18:0:0:0:
+
+  Here's what to expect in the sysfs tree :
+   scsi_hosts:
+     /sys/class/scsi_host/host17                physical port's scsi_host
+     /sys/class/scsi_host/host18                vport's scsi_host
+   fc_hosts:
+     /sys/class/fc_host/host17                  physical port's fc_host
+     /sys/class/fc_host/host18                  vport's fc_host
+   fc_vports:
+     /sys/class/fc_vports/vport-17:0-0          the vport's fc_vport
+   fc_rports:
+     /sys/class/fc_remote_ports/rport-17:0-0    rport on the physical port
+     /sys/class/fc_remote_ports/rport-18:0-0    rport on the vport
+
+
+Vport Attributes:
+-------------------------------
+
+  The new fc_vport class object has the following attributes
+
+     node_name:                                                 Read_Only
+       The WWNN of the vport
+
+     port_name:                                                 Read_Only
+       The WWPN of the vport
+
+     roles:                                                     Read_Only
+       Indicates the FC4 roles enabled on the vport.
+
+     symbolic_name:                                             Read_Write
+       A string, appended to the driver's symbolic port name string, which
+       is registered with the switch to identify the vport. For example,
+       a hypervisor could set this string to "Xen Domain 2 VM 5 Vport 2",
+       and this set of identifiers can be seen on switch management screens
+       to identify the port.
+
+     vport_delete:                                              Write_Only
+       When written with a "1", will tear down the vport.
+
+     vport_disable:                                             Write_Only
+       When written with a "1", will transition the vport to a disabled.
+       state.  The vport will still be instantiated with the Linux kernel,
+       but it will not be active on the FC link.
+       When written with a "0", will enable the vport.
+
+     vport_last_state:                                          Read_Only
+       Indicates the previous state of the vport.  See the section below on
+       "Vport States".
+
+     vport_state:                                               Read_Only
+       Indicates the state of the vport.  See the section below on
+       "Vport States".
+
+     vport_type:                                                Read_Only
+       Reflects the FC mechanism used to create the virtual port.
+       Only NPIV is supported currently.
+
+
+  For the fc_host class object, the following attributes are added for vports:
+
+     max_npiv_vports:                                           Read_Only
+       Indicates the maximum number of NPIV-based vports that the
+       driver/adapter can support on the fc_host.
+
+     npiv_vports_inuse:                                         Read_Only
+       Indicates how many NPIV-based vports have been instantiated on the
+       fc_host.
+
+     vport_create:                                              Write_Only
+       A "simple" create interface to instantiate a vport on an fc_host.
+       A "<WWPN>:<WWNN>" string is written to the attribute. The transport
+       then instantiates the vport object and calls the LLDD to create the
+       vport with the role of FCP_Initiator.  Each WWN is specified as 16
+       hex characters and may *not* contain any prefixes (e.g. 0x, x, etc).
+
+     vport_delete:                                              Write_Only
+        A "simple" delete interface to teardown a vport. A "<WWPN>:<WWNN>"
+        string is written to the attribute. The transport will locate the
+        vport on the fc_host with the same WWNs and tear it down.  Each WWN
+        is specified as 16 hex characters and may *not* contain any prefixes
+        (e.g. 0x, x, etc).
+
+
+Vport States:
+-------------------------------
+
+  Vport instantiation consists of two parts:
+    - Creation with the kernel and LLDD. This means all transport and
+      driver data structures are built up, and device objects created.
+      This is equivalent to a driver "attach" on an adapter, which is
+      independent of the adapter's link state.
+    - Instantiation of the vport on the FC link via ELS traffic, etc.
+      This is equivalent to a "link up" and successfull link initialization.
+  Futher information can be found in the interfaces section below for
+  Vport Creation.
+
+  Once a vport has been instantiated with the kernel/LLDD, a vport state
+  can be reported via the sysfs attribute. The following states exist:
+
+    FC_VPORT_UNKNOWN            - Unknown
+      An temporary state, typically set only while the vport is being
+      instantiated with the kernel and LLDD.
+
+    FC_VPORT_ACTIVE             - Active
+      The vport has been successfully been created on the FC link.
+      It is fully functional.
+
+    FC_VPORT_DISABLED           - Disabled
+      The vport instantiated, but "disabled". The vport is not instantiated
+      on the FC link. This is equivalent to a physical port with the
+      link "down".
+
+    FC_VPORT_LINKDOWN           - Linkdown
+      The vport is not operational as the physical link is not operational.
+
+    FC_VPORT_INITIALIZING       - Initializing
+      The vport is in the process of instantiating on the FC link.
+      The LLDD will set this state just prior to starting the ELS traffic
+      to create the vport. This state will persist until the vport is
+      successfully created (state becomes FC_VPORT_ACTIVE) or it fails
+      (state is one of the values below).  As this state is transitory,
+      it will not be preserved in the "vport_last_state".
+
+    FC_VPORT_NO_FABRIC_SUPP     - No Fabric Support
+      The vport is not operational. One of the following conditions were
+      encountered:
+       - The FC topology is not Point-to-Point
+       - The FC port is not connected to an F_Port
+       - The F_Port has indicated that NPIV is not supported.
+
+    FC_VPORT_NO_FABRIC_RSCS     - No Fabric Resources
+      The vport is not operational. The Fabric failed FDISC with a status
+      indicating that it does not have sufficient resources to complete
+      the operation.
+
+    FC_VPORT_FABRIC_LOGOUT      - Fabric Logout
+      The vport is not operational. The Fabric has LOGO'd the N_Port_ID
+      associated with the vport.
+
+    FC_VPORT_FABRIC_REJ_WWN     - Fabric Rejected WWN
+      The vport is not operational. The Fabric failed FDISC with a status
+      indicating that the WWN's are not valid.
+
+    FC_VPORT_FAILED             - VPort Failed
+      The vport is not operational. This is a catchall for all other
+      error conditions.
+
+
+  The following state table indicates the different state transitions:
+
+    State              Event                            New State
+    --------------------------------------------------------------------
+     n/a                Initialization                  Unknown
+    Unknown:            Link Down                       Linkdown
+                        Link Up & Loop                  No Fabric Support
+                        Link Up & no Fabric             No Fabric Support
+                        Link Up & FLOGI response        No Fabric Support
+                          indicates no NPIV support
+                        Link Up & FDISC being sent      Initializing
+                        Disable request                 Disable
+    Linkdown:           Link Up                         Unknown
+    Initializing:       FDISC ACC                       Active
+                        FDISC LS_RJT w/ no resources    No Fabric Resources
+                        FDISC LS_RJT w/ invalid         Fabric Rejected WWN
+                          pname or invalid nport_id
+                        FDISC LS_RJT failed for         Vport Failed
+                          other reasons
+                        Link Down                       Linkdown
+                        Disable request                 Disable
+    Disable:            Enable request                  Unknown
+    Active:             LOGO received from fabric       Fabric Logout
+                        Link Down                       Linkdown
+                        Disable request                 Disable
+    Fabric Logout:      Link still up                   Unknown
+
+         The following 4 error states all have the same transitions:
+    No Fabric Support:
+    No Fabric Resources:
+    Fabric Rejected WWN:
+    Vport Failed:
+                        Disable request                 Disable
+                        Link goes down                  Linkdown
+
+
+Transport <-> LLDD Interfaces :
+-------------------------------
+
+Vport support by LLDD:
+
+  The LLDD indicates support for vports by supplying a vport_create()
+  function in the transport template.  The presense of this function will
+  cause the creation of the new attributes on the fc_host.  As part of
+  the physical port completing its initialization relative to the
+  transport, it should set the max_npiv_vports attribute to indicate the
+  maximum number of vports the driver and/or adapter supports.
+
+
+Vport Creation:
+
+  The LLDD vport_create() syntax is:
+
+      int vport_create(struct fc_vport *vport, bool disable)
+
+    where:
+      vport:    Is the newly allocated vport object
+      disable:  If "true", the vport is to be created in a disabled stated.
+                If "false", the vport is to be enabled upon creation.
+
+  When a request is made to create a new vport (via sgio/netlink, or the
+  vport_create fc_host attribute), the transport will validate that the LLDD
+  can support another vport (e.g. max_npiv_vports > npiv_vports_inuse).
+  If not, the create request will be failed.  If space remains, the transport
+  will increment the vport count, create the vport object, and then call the
+  LLDD's vport_create() function with the newly allocated vport object.
+
+  As mentioned above, vport creation is divided into two parts:
+    - Creation with the kernel and LLDD. This means all transport and
+      driver data structures are built up, and device objects created.
+      This is equivalent to a driver "attach" on an adapter, which is
+      independent of the adapter's link state.
+    - Instantiation of the vport on the FC link via ELS traffic, etc.
+      This is equivalent to a "link up" and successfull link initialization.
+
+  The LLDD's vport_create() function will not synchronously wait for both
+  parts to be fully completed before returning. It must validate that the
+  infrastructure exists to support NPIV, and complete the first part of
+  vport creation (data structure build up) before returning.  We do not
+  hinge vport_create() on the link-side operation mainly because:
+    - The link may be down. It is not a failure if it is. It simply
+      means the vport is in an inoperable state until the link comes up.
+      This is consistent with the link bouncing post vport creation.
+    - The vport may be created in a disabled state.
+    - This is consistent with a model where:  the vport equates to a
+      FC adapter. The vport_create is synonymous with driver attachment
+      to the adapter, which is independent of link state.
+
+    Note: special error codes have been defined to delineate infrastructure
+      failure cases for quicker resolution.
+
+  The expected behavior for the LLDD's vport_create() function is:
+    - Validate Infrastructure:
+        - If the driver or adapter cannot support another vport, whether
+            due to improper firmware, (a lie about) max_npiv, or a lack of
+            some other resource - return VPCERR_UNSUPPORTED.
+        - If the driver validates the WWN's against those already active on
+            the adapter and detects an overlap - return VPCERR_BAD_WWN.
+        - If the driver detects the topology is loop, non-fabric, or the
+            FLOGI did not support NPIV - return VPCERR_NO_FABRIC_SUPP.
+    - Allocate data structures. If errors are encountered, such as out
+        of memory conditions, return the respective negative Exxx error code.
+    - If the role is FCP Initiator, the LLDD is to :
+        - Call scsi_host_alloc() to allocate a scsi_host for the vport.
+        - Call scsi_add_host(new_shost, &vport->dev) to start the scsi_host
+          and bind it as a child of the vport device.
+        - Initializes the fc_host attribute values.
+    - Kick of further vport state transitions based on the disable flag and
+        link state - and return success (zero).
+
+  LLDD Implementers Notes:
+  - It is suggested that there be a different fc_function_templates for
+    the physical port and the virtual port.  The physical port's template
+    would have the vport_create, vport_delete, and vport_disable functions,
+    while the vports would not.
+  - It is suggested that there be different scsi_host_templates
+    for the physical port and virtual port. Likely, there are driver
+    attributes, embedded into the scsi_host_template, that are applicable
+    for the physical port only (link speed, topology setting, etc). This
+    ensures that the attributes are applicable to the respective scsi_host.
+
+
+Vport Disable/Enable:
+
+  The LLDD vport_disable() syntax is:
+
+      int vport_disable(struct fc_vport *vport, bool disable)
+
+    where:
+      vport:    Is vport to to be enabled or disabled
+      disable:  If "true", the vport is to be disabled.
+                If "false", the vport is to be enabled.
+
+  When a request is made to change the disabled state on a vport, the
+  transport will validate the request against the existing vport state.
+  If the request is to disable and the vport is already disabled, the
+  request will fail. Similarly, if the request is to enable, and the
+  vport is not in a disabled state, the request will fail.  If the request
+  is valid for the vport state, the transport will call the LLDD to
+  change the vport's state.
+
+  Within the LLDD, if a vport is disabled, it remains instantiated with
+  the kernel and LLDD, but it is not active or visible on the FC link in
+  any way. (see Vport Creation and the 2 part instantiation discussion).
+  The vport will remain in this state until it is deleted or re-enabled.
+  When enabling a vport, the LLDD reinstantiates the vport on the FC
+  link - essentially restarting the LLDD statemachine (see Vport States
+  above).
+
+
+Vport Deletion:
+
+  The LLDD vport_delete() syntax is:
+
+      int vport_delete(struct fc_vport *vport)
+
+    where:
+      vport:    Is vport to delete
+
+  When a request is made to delete a vport (via sgio/netlink, or via the
+  fc_host or fc_vport vport_delete attributes), the transport will call
+  the LLDD to terminate the vport on the FC link, and teardown all other
+  datastructures and references.  If the LLDD completes successfully,
+  the transport will teardown the vport objects and complete the vport
+  removal.  If the LLDD delete request fails, the vport object will remain,
+  but will be in an indeterminate state.
+
+  Within the LLDD, the normal code paths for a scsi_host teardown should
+  be followed. E.g. If the vport has a FCP Initiator role, the LLDD
+  will call fc_remove_host() for the vports scsi_host, followed by
+  scsi_remove_host() and scsi_host_put() for the vports scsi_host.
+
+
+Other:
+  fc_host port_type attribute:
+    There is a new fc_host port_type value - FC_PORTTYPE_NPIV. This value
+    must be set on all vport-based fc_hosts.  Normally, on a physical port,
+    the port_type attribute would be set to NPORT, NLPORT, etc based on the
+    topology type and existence of the fabric. As this is not applicable to
+    a vport, it makes more sense to report the FC mechanism used to create
+    the vport.
+
+  Driver unload:
+    FC drivers are required to call fc_remove_host() prior to calling
+    scsi_remove_host().  This allows the fc_host to tear down all remote
+    ports prior the scsi_host being torn down.  The fc_remove_host() call
+    was updated to remove all vports for the fc_host as well.
+
+
+Credits
+=======
+The following people have contributed to this document:
+
+
+
+
+
+
+James Smart
+james.smart@emulex.com
+
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 57b878c..355ff0a 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -917,6 +917,7 @@
 	  ref		Reference board, base config
 	  m2-2		Some Gateway MX series laptops
 	  m6		Some Gateway NX series laptops
+	  pa6		Gateway NX860 series
 
 	STAC9227/9228/9229/927x
 	  ref		Reference board
diff --git a/Documentation/sound/oss/AD1816 b/Documentation/sound/oss/AD1816
deleted file mode 100644
index 14bd8f2..0000000
--- a/Documentation/sound/oss/AD1816
+++ /dev/null
@@ -1,84 +0,0 @@
-Documentation for the AD1816(A) sound driver
-============================================
-
-Installation:
--------------
-
-To get your AD1816(A) based sound card work, you'll have to enable support for
-experimental code ("Prompt for development and/or incomplete code/drivers")
-and isapnp ("Plug and Play support", "ISA Plug and Play support"). Enable
-"Sound card support", "OSS modules support" and "Support for AD1816(A) based
-cards (EXPERIMENTAL)" in the sound configuration menu, too. Now build, install
-and reboot the new kernel as usual.
-
-Features:
----------
-
-List of features supported by this driver:
-- full-duplex support
-- supported audio formats: unsigned 8bit, signed 16bit little endian, 
-                           signed 16bit big endian, µ-law, A-law
-- supported channels: mono and stereo
-- supported recording sources: Master, CD, Line, Line1, Line2, Mic
-- supports phat 3d stereo circuit (Line 3)
-
-
-Supported cards:
-----------------
-
-The following cards are known to work with this driver:
-- Terratec Base 1 
-- Terratec Base 64 
-- HP Kayak 
-- Acer FX-3D
-- SY-1816 
-- Highscreen Sound-Boostar 32 Wave 3D
-- Highscreen Sound-Boostar 16 
-- AVM Apex Pro card 
-- (Aztech SC-16 3D) 
-- (Newcom SC-16 3D) 
-- (Terratec EWS64S) 
-
-Cards listed in brackets are not supported reliable. If you have such a card 
-you should add the extra parameter:
-  options=1
-when loading the ad1816 module via modprobe. 
-
-
-Troubleshooting:
-----------------
-
-First of all you should check, if the driver has been loaded
-properly.
-
-If loading of the driver succeeds, but playback/capture fails, check
-if you used the correct values for irq, dma and dma2 when loading the module.
-If one of them is wrong you usually get the following error message:
-
-Nov  6 17:06:13 tek01 kernel: Sound: DMA (output) timed out - IRQ/DRQ config error?
-
-If playback/capture is too fast or to slow, you should have a look at
-the clock chip of your sound card. The AD1816 was designed for a 33MHz
-oscillator, however most sound card manufacturer use slightly
-different oscillators as they are cheaper than 33MHz oscillators. If
-you have such a card you have to adjust the ad1816_clockfreq parameter
-above. For example: For a card using a 32.875MHz oscillator use
-ad1816_clockfreq=32875 instead of ad1816_clockfreq=33000.
-
-
-Updates, bugfixes and bugreports:
---------------------------------
-
-As the driver is still experimental and under development, you should
-watch out for updates.  Updates of the driver are available on the
-Internet from one of my home pages:
-  http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
-or:
-  http://www.tu-darmstadt.de/~tek01/projects/linux.html
-
-Bugreports, bugfixes and related questions should be sent via E-Mail to:
-  tek@rbg.informatik.tu-darmstadt.de
-
-Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
-Christoph Hellwig <hch@infradead.org>
-	Last modified: 2000/09/20
diff --git a/Documentation/sound/oss/NM256 b/Documentation/sound/oss/NM256
deleted file mode 100644
index b503217..0000000
--- a/Documentation/sound/oss/NM256
+++ /dev/null
@@ -1,280 +0,0 @@
-=======================================================
-Documentation for the NeoMagic 256AV/256ZX sound driver
-=======================================================
-
-You're looking at version 1.1 of the driver.  (Woohoo!) It has been
-successfully tested against the following laptop models:
-
-	Sony Z505S/Z505SX/Z505DX/Z505RX
-	Sony F150, F160, F180, F250, F270, F280, PCG-F26
-	Dell Latitude CPi, CPt (various submodels)
-
-There are a few caveats, which is why you should read the entirety of
-this document first.
-
-This driver was developed without any support or assistance from
-NeoMagic.  There is no warranty, expressed, implied, or otherwise.  It
-is free software in the public domain; feel free to use it, sell it,
-give it to your best friends, even claim that you wrote it (but why?!)
-but don't go whining to me, NeoMagic, Sony, Dell, or anyone else
-when it blows up your computer.
-
-Version 1.1 contains a change to try and detect non-AC97 versions of
-the hardware, and not install itself appropriately.  It should also
-reinitialize the hardware on an APM resume event, assuming that APM
-was configured into your kernel.
-
-============
-Installation
-============
-
-Enable the sound drivers, the OSS sound drivers, and then the NM256
-driver.  The NM256 driver *must* be configured as a module (it won't
-give you any other choice).
-
-Next, do the usual "make modules" and "make modules_install".
-Finally, insmod the soundcore, sound and nm256 modules.
-
-When the nm256 driver module is loaded, you should see a couple of
-confirmation messages in the kernel logfile indicating that it found
-the device (the device does *not* use any I/O ports or DMA channels).
-Now try playing a wav file, futz with the CD-ROM if you have one, etc.
-
-The NM256 is entirely a PCI-based device, and all the necessary
-information is automatically obtained from the card.  It can only be
-configured as a module in a vain attempt to prevent people from
-hurting themselves.  It works correctly if it shares an IRQ with
-another device (it normally shares IRQ 9 with the builtin eepro100
-ethernet on the Sony Z505 laptops). 
-
-It does not run the card in any sort of compatibility mode. It will
-not work on laptops that have the SB16-compatible, AD1848-compatible
-or CS4232-compatible codec/mixer; you will want to use the appropriate
-compatible OSS driver with these chipsets.  I cannot provide any
-assistance with machines using the SB16, AD1848 or CS4232 compatible
-versions.  (The driver now attempts to detect the mixer version, and
-will refuse to load if it believes the hardware is not
-AC97-compatible.)
-
-The sound support is very basic, but it does include simultaneous
-playback and record capability.  The mixer support is also quite
-simple, although this is in keeping with the rather limited
-functionality of the chipset.
-
-There is no hardware synthesizer available, as the Losedows OPL-3 and
-MIDI support is done via hardware emulation.
-
-Only three recording devices are available on the Sony: the
-microphone, the CD-ROM input, and the volume device (which corresponds
-to the stereo output).  (Other devices may be available on other
-models of laptops.)  The Z505 series does not have a builtin CD-ROM,
-so of course the CD-ROM input doesn't work.  It does work on laptops
-with a builtin CD-ROM drive.
-
-The mixer device does not appear to have any tone controls, at least
-on the Z505 series.  The mixer module checks for tone controls in the
-AC97 mixer, and will enable them if they are available.
-
-==============
-Known problems
-==============
-
-  * There are known problems with PCMCIA cards and the eepro100 ethernet 
-    driver on the Z505S/Z505SX/Z505DX.  Keep reading.
-
-  * There are also potential problems with using a virtual X display, and
-    also problems loading the module after the X server has been started. 
-    Keep reading.
-
-  * The volume control isn't anywhere near linear.  Sorry.  This will be
-    fixed eventually, when I get sufficiently annoyed with it.  (I doubt
-    it will ever be fixed now, since I've never gotten sufficiently
-    annoyed with it and nobody else seems to care.)
-
-  * There are reports that the CD-ROM volume is very low.  Since I do not
-    have a CD-ROM equipped laptop, I cannot test this (it's kinda hard to
-    do remotely).
-
-  * Only 8 fixed-rate speeds are supported.  This is mainly a chipset
-    limitation.  It may be possible to support other speeds in the future.
-
-  * There is no support for the telephone mixer/codec.  There is support
-    for a phonein/phoneout device in the mixer driver;  whether or not 
-    it does anything is anyone's guess.  (Reports on this would be
-    appreciated.  You'll have to figure out how to get the phone to
-    go off-hook before it'll work, tho.)
-
-  * This driver was not written with any cooperation or support from
-    NeoMagic.  If you have any questions about this, see their website
-    for their official stance on supporting open source drivers.
-
-============
-Video memory
-============
-
-The NeoMagic sound engine uses a portion of the display memory to hold
-the sound buffer.  (Crazy, eh?)  The NeoMagic video BIOS sets up a
-special pointer at the top of video RAM to indicate where the top of
-the audio buffer should be placed.
-
-At the present time XFree86 is apparently not aware of this.  It will
-thus write over either the pointer or the sound buffer with abandon.
-(Accelerated-X seems to do a better job here.)
-
-This implies a few things:
-
-  * Sometimes the NM256 driver has to guess at where the buffer 
-    should be placed, especially if the module is loaded after the
-    X server is started.  It's usually correct, but it will consistently
-    fail on the Sony F250.
-
-  * Virtual screens greater than 1024x768x16 under XFree86 are
-    problematic on laptops with only 2.5MB of screen RAM. This
-    includes all of the 256AV-equipped laptops.  (Virtual displays
-    may or may not work on the 256ZX, which has at least 4MB of
-    video RAM.)
-
-If you start having problems with random noise being output either
-constantly (this is the usual symptom on the F250), or when windows
-are moved around (this is the usual symptom when using a virtual
-screen), the best fix is to
-
-  * Don't use a virtual frame buffer.
-  * Make sure you load the NM256 module before the X server is
-    started.
-
-On the F250, it is possible to force the driver to load properly even
-after the XFree86 server is started by doing:
-
-	insmod nm256 buffertop=0x25a800
-
-This forces the audio buffers to the correct offset in screen RAM.
-
-One user has reported a similar problem on the Sony F270, although
-others apparently aren't seeing any problems.  His suggested command
-is
-
-	insmod nm256 buffertop=0x272800
-
-=================
-Official WWW site
-=================
-
-The official site for the NM256 driver is:
-
-	http://www.uglx.org/sony.html
-
-You should always be able to get the latest version of the driver there,
-and the driver will be supported for the foreseeable future.
-
-==============
-Z505RX and IDE
-==============
-
-There appears to be a problem with the IDE chipset on the Z505RX; one
-of the symptoms is that sound playback periodically hangs (when the
-disk is accessed).  The user reporting the problem also reported that
-enabling all of the IDE chipset workarounds in the kernel solved the
-problem, tho obviously only one of them should be needed--if someone
-can give me more details I would appreciate it.
-
-==============================
-Z505S/Z505SX on-board Ethernet
-==============================
-
-If you're using the on-board Ethernet Pro/100 ethernet support on the Z505
-series, I strongly encourage you to download the latest eepro100 driver from
-Donald Becker's site:
-
-	ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/test/eepro100.c
-
-There was a reported problem on the Z505SX that if the ethernet
-interface is disabled and reenabled while the sound driver is loaded,
-the machine would lock up.  I have included a workaround that is
-working satisfactorily.  However, you may occasionally see a message
-about "Releasing interrupts, over 1000 bad interrupts" which indicates
-that the workaround is doing its job.
-
-==================================
-PCMCIA and the Z505S/Z505SX/Z505DX
-==================================
-
-There is also a known problem with the Sony Z505S and Z505SX hanging
-if a PCMCIA card is inserted while the ethernet driver is loaded, or
-in some cases if the laptop is suspended.  This is caused by tons of
-spurious IRQ 9s, probably generated from the PCMCIA or ACPI bridges.
-
-There is currently no fix for the problem that works in every case.
-The only known workarounds are to disable the ethernet interface
-before inserting or removing a PCMCIA card, or with some cards
-disabling the PCMCIA card before ejecting it will also help the
-problem with the laptop hanging when the card is ejected.
-
-One user has reported that setting the tcic's cs_irq to some value
-other than 9 (like 11) fixed the problem.  This doesn't work on my
-Z505S, however--changing the value causes the cardmgr to stop seeing
-card insertions and removals, cards don't seem to work correctly, and
-I still get hangs if a card is inserted when the kernel is booted.
-
-Using the latest ethernet driver and pcmcia package allows me to
-insert an Adaptec 1480A SlimScsi card without the laptop hanging,
-although I still have to shut down the card before ejecting or
-powering down the laptop.  However, similar experiments with a DE-660
-ethernet card still result in hangs when the card is inserted.  I am
-beginning to think that the interrupts are CardBus-related, since the
-Adaptec card is a CardBus card, and the DE-660 is not; however, I
-don't have any other CardBus cards to test with.
-
-======
-Thanks
-======
-
-First, I want to thank everyone (except NeoMagic of course) for their
-generous support and encouragement.  I'd like to list everyone's name
-here that replied during the development phase, but the list is
-amazingly long.
-
-I will be rather unfair and single out a few people, however:
-
-	Justin Maurer, for being the first random net.person to try it,
-	and for letting me login to his Z505SX to get it working there
-
-	Edi Weitz for trying out several different versions, and giving
-	me a lot of useful feedback
-
-	Greg Rumple for letting me login remotely to get the driver 
-	functional on the 256ZX, for his assistance on tracking
-	down all sorts of random stuff, and for trying out Accel-X
-
-	Zach Brown, for the initial AC97 mixer interface design
-
-	Jeff Garzik, for various helpful suggestions on the AC97
-	interface
-
-	"Mr. Bumpy" for feedback on the Z505RX
-
-	Bill Nottingham, for generous assistance in getting the mixer ID
-	code working
-
-=================
-Previous versions
-=================
-
-Versions prior to 0.3 (aka `noname') had problems with weird artifacts
-in the output and failed to set the recording rate properly.  These
-problems have long since been fixed.
-
-Versions prior to 0.5 had problems with clicks in the output when
-anything other than 16-bit stereo sound was being played, and also had
-periodic clicks when recording.
-
-Version 0.7 first incorporated support for the NM256ZX chipset, which
-is found on some Dell Latitude laptops (the CPt, and apparently
-some CPi models as well).  It also included the generic AC97
-mixer module.
-
-Version 0.75 renamed all the functions and files with slightly more
-generic names.
-
-Note that previous versions of this document claimed that recording was
-8-bit only; it actually has been working for 16-bits all along.
diff --git a/Documentation/sound/oss/OPL3-SA2 b/Documentation/sound/oss/OPL3-SA2
deleted file mode 100644
index d8b6d2b..0000000
--- a/Documentation/sound/oss/OPL3-SA2
+++ /dev/null
@@ -1,210 +0,0 @@
-Documentation for the OPL3-SA2, SA3, and SAx driver (opl3sa2.o)
----------------------------------------------------------------
-
-Scott Murray, scott@spiteful.org
-January 7, 2001
-
-NOTE: All trade-marked terms mentioned below are properties of their
-      respective owners.
-
-
-Supported Devices
------------------
-
-This driver is for PnP soundcards based on the following Yamaha audio
-controller chipsets:
-
-YMF711 aka OPL3-SA2
-YMF715 and YMF719 aka OPL3-SA3
-
-Up until recently (December 2000), I'd thought the 719 to be a
-different chipset, the OPL3-SAx.  After an email exhange with
-Yamaha, however, it turns out that the 719 is just a re-badged
-715, and the chipsets are identical.  The chipset detection code
-has been updated to reflect this.
-
-Anyways, all of these chipsets implement the following devices:
-
-OPL3 FM synthesizer
-Soundblaster Pro
-Microsoft/Windows Sound System
-MPU401 MIDI interface
-
-Note that this driver uses the MSS device, and to my knowledge these
-chipsets enforce an either/or situation with the Soundblaster Pro
-device and the MSS device.  Since the MSS device has better
-capabilities, I have implemented the driver to use it.
-
-
-Mixer Channels
---------------
-
-Older versions of this driver (pre-December 2000) had two mixers,
-an OPL3-SA2 or SA3 mixer and a MSS mixer.  The OPL3-SA[23] mixer
-device contained a superset of mixer channels consisting of its own
-channels and all of the MSS mixer channels.  To simplify the driver
-considerably, and to partition functionality better, the OPL3-SA[23]
-mixer device now contains has its own specific mixer channels.  They
-are:
-
-Volume     - Hardware master volume control
-Bass       - SA3 only, now supports left and right channels
-Treble     - SA3 only, now supports left and right channels
-Microphone - Hardware microphone input volume control
-Digital1   - Yamaha 3D enhancement "Wide" mixer
-
-All other mixer channels (e.g. "PCM", "CD", etc.) now have to be
-controlled via the "MS Sound System (CS4231)" mixer.  To facilitate
-this, the mixer device creation order has been switched so that
-the MSS mixer is created first.  This allows accessing the majority
-of the useful mixer channels even via single mixer-aware tools
-such as "aumix".
-
-
-Plug 'n Play
-------------
-
-In previous kernels (2.2.x), some configuration was required to
-get the driver to talk to the card.  Being the new millennium and
-all, the 2.4.x kernels now support auto-configuration if ISA PnP
-support is configured in.  Theoretically, the driver even supports
-having more than one card in this case.
-
-With the addition of PnP support to the driver, two new parameters
-have been added to control it:
-
-isapnp   - set to 0 to disable ISA PnP card detection
-
-multiple - set to 0 to disable multiple PnP card detection
-
-
-Optional Parameters
--------------------
-
-Recent (December 2000) additions to the driver (based on a patch
-provided by Peter Englmaier) are two new parameters:
-
-ymode -    Set Yamaha 3D enhancement mode:
-           0 = Desktop/Normal  5-12 cm speakers
-           1 = Notebook PC (1) 3 cm speakers
-           2 = Notebook PC (2) 1.5 cm speakers
-           3 = Hi-Fi           16-38 cm speakers
-
-loopback - Set A/D input source. Useful for echo cancellation:
-           0 = Mic Right channel (default)
-           1 = Mono output loopback
-
-The ymode parameter has been tested and does work.  The loopback
-parameter, however, is untested.  Any feedback on its usefulness
-would be appreciated.
-
-
-Manual Configuration
---------------------
-
-If for some reason you decide not to compile ISA PnP support into
-your kernel, or disabled the driver's usage of it by setting the
-isapnp parameter as discussed above, then you will need to do some
-manual configuration.  There are two ways of doing this.  The most
-common is to use the isapnptools package to initialize the card, and
-use the kernel module form of the sound subsystem and sound drivers.
-Alternatively, some BIOS's allow manual configuration of installed
-PnP devices in a BIOS menu, which should allow using the non-modular
-sound drivers, i.e. built into the kernel.
-
-I personally use isapnp and modules, and do not have access to a PnP
-BIOS machine to test.  If you have such a beast, configuring the
-driver to be built into the kernel should just work (thanks to work
-done by David Luyer <luyer@ucs.uwa.edu.au>).  You will still need
-to specify settings, which can be done by adding:
-
-opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>
-
-to the kernel command line.  For example:
-
-opl3sa2=0x370,5,0,1,0x530,0x330
-
-If you are instead using the isapnp tools (as most people have been
-before Linux 2.4.x), follow the directions in their documentation to
-produce a configuration file.  Here is the relevant excerpt I used to
-use for my SA3 card from my isapnp.conf:
-
-(CONFIGURE YMH0800/-1 (LD 0
-
-# NOTE: IO 0 is for the unused SoundBlaster part of the chipset.
-(IO 0 (BASE 0x0220))
-(IO 1 (BASE 0x0530))
-(IO 2 (BASE 0x0388))
-(IO 3 (BASE 0x0330))
-(IO 4 (BASE 0x0370))
-(INT 0 (IRQ 5 (MODE +E)))
-(DMA 0 (CHANNEL 0))
-(DMA 1 (CHANNEL 1))
-
-Here, note that:
-
-Port  Acceptable Range  Purpose
-----  ----------------  -------
-IO 0  0x0220 - 0x0280   SB base address, unused.
-IO 1  0x0530 - 0x0F48   MSS base address
-IO 2  0x0388 - 0x03F8   OPL3 base address
-IO 3  0x0300 - 0x0334   MPU base address
-IO 4  0x0100 - 0x0FFE   card's own base address for its control I/O ports
-
-The IRQ and DMA values can be any that are considered acceptable for a
-MSS.  Assuming you've got isapnp all happy, then you should be able to
-do something like the following (which matches up with the isapnp
-configuration above):
-
-modprobe mpu401
-modprobe ad1848
-modprobe opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=5 dma=0 dma2=1
-modprobe opl3 io=0x388
-
-See the section "Automatic Module Loading" below for how to set up
-/etc/modprobe.conf to automate this.
-
-An important thing to remember that the opl3sa2 module's io argument is
-for it's own control port, which handles the card's master mixer for
-volume (on all cards), and bass and treble (on SA3 cards).
-
-
-Troubleshooting
----------------
-
-If all goes well and you see no error messages, you should be able to
-start using the sound capabilities of your system.  If you get an
-error message while trying to insert the opl3sa2 module, then make
-sure that the values of the various arguments match what you specified
-in your isapnp configuration file, and that there is no conflict with
-another device for an I/O port or interrupt.  Checking the contents of
-/proc/ioports and /proc/interrupts can be useful to see if you're
-butting heads with another device.
-
-If you still cannot get the module to load, look at the contents of
-your system log file, usually /var/log/messages.  If you see the
-message "opl3sa2: Unknown Yamaha audio controller version", then you
-have a different chipset version than I've encountered so far.  Look
-for all messages in the log file that start with "opl3sa2: " and see
-if they provide any clues.  If you do not see the chipset version
-message, and none of the other messages present in the system log are
-helpful, email me some details and I'll try my best to help.
-
-
-Automatic Module Loading
-------------------------
-
-Lastly, if you're using modules and want to set up automatic module
-loading with kmod, the kernel module loader, here is the section I
-currently use in my modprobe.conf file:
-
-# Sound
-alias sound-slot-0 opl3sa2
-options opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=7 dma=0 dma2=3
-options opl3 io=0x388
-
-That's all it currently takes to get an OPL3-SA3 card working on my
-system.  Once again, if you have any other problems, email me at the
-address listed above.
-
-Scott
diff --git a/Documentation/sound/oss/VIA-chipset b/Documentation/sound/oss/VIA-chipset
deleted file mode 100644
index 3786523..0000000
--- a/Documentation/sound/oss/VIA-chipset
+++ /dev/null
@@ -1,43 +0,0 @@
-Running sound cards on VIA chipsets
-
-o	There are problems with VIA chipsets and sound cards that appear to
-	lock the hardware solidly. Test programs under DOS have verified the
-	problem exists on at least some (but apparently not all) VIA boards
-
-o	VIA have so far failed to bother to answer support mail on the subject
-	so if you are a VIA engineer feeling aggrieved as you read this 
-	document go chase your own people. If there is a workaround please
-	let us know so we can implement it.
-
-
-Certain patterns of ISA DMA access used for most PC sound cards cause the
-VIA chipsets to lock up. From the collected reports this appears to cover a
-wide range of boards. Some also lock up with sound cards under Win* as well.
-
-Linux implements a workaround providing your chipset is PCI and you compiled
-with PCI Quirks enabled. If so you will see a message
-	"Activating ISA DMA bug workarounds"
-
-during booting. If you have a VIA PCI chipset that hangs when you use the
-sound and is not generating this message even with PCI quirks enabled
-please report the information to the linux-kernel list (see REPORTING-BUGS).
-
-If you are one of the tiny number of unfortunates with a 486 ISA/VLB VIA
-chipset board you need to do the following to build a special kernel for
-your board
-
-	edit linux/include/asm-i386/dma.h
-
-change
-
-#define isa_dma_bridge_buggy 	(0)
-
-to
-
-#define isa_dma_bridge_buggy 	(1)
-
-and rebuild a kernel without PCI quirk support.
-
-
-Other than this particular glitch the VIA [M]VP* chipsets appear to work
-perfectly with Linux.
diff --git a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx
deleted file mode 100644
index b544327..0000000
--- a/Documentation/sound/oss/cs46xx
+++ /dev/null
@@ -1,138 +0,0 @@
-
-Documentation for the Cirrus Logic/Crystal SoundFusion cs46xx/cs4280 audio 
-controller chips (2001/05/11)
-
-The cs46xx audio driver supports the DSP line of Cirrus controllers. 
-Specifically, the cs4610, cs4612, cs4614, cs4622, cs4624, cs4630 and the cs4280
-products.  This driver uses the generic ac97_codec driver for AC97 codec
-support.  
-
-
-Features:
-
-Full Duplex Playback/Capture supported from 8k-48k.
-16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported.
-
-APM/PM - 2.2.x PM is enabled and functional. APM can also
-be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
-definition.
-
-DMA playback buffer size is configurable from 16k (defaultorder=2) up to 2Meg 
-(defaultorder=11).  DMA capture buffer size is fixed at a single 4k page as
-two 2k fragments.
-
-MMAP seems to work well with QuakeIII, and test XMMS plugin.
-
-Myth2 works, but the polling logic is not fully correct, but is functional.
-
-The 2.4.4-ac6 gameport code in the cs461x joystick driver has been tested 
-with a Microsoft Sidewinder joystick (cs461x.o and sidewinder.o).  This 
-audio driver must be loaded prior to the joystick driver to enable the
-DSP task image supporting the joystick device.
-
-
-Limitations:
-
-SPDIF is currently not supported.
-
-Primary codec support only.  No secondary codec support is implemented.
-
-
-
-NOTES:
-
-Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
-and has been tested.
-Module parameter hercules_egpio_disable set to 1, will force a 0 to EGPIODR
-to disable the external amplifier.
-
-VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
-the external amplifier for the "back" speakers, since we do not
-support the secondary codec then this external amp is not
-turned on.  The primary codec external amplifier is supported but
-note that the AC97 EAPD bit is inverted logic (amp_voyetra()).
-
-DMA buffer size - there are issues with many of the Linux applications
-concerning the optimal buffer size.  Several applications request a 
-certain fragment size and number and then do not verify that the driver
-has the ability to support the requested configuration.  
-SNDCTL_DSP_SETFRAGMENT ioctl is used to request a fragment size and
-number of fragments.  Some applications exit if an error is returned
-on this particular ioctl. Therefore, in alignment with the other OSS audio 
-drivers, no error is returned when a SETFRAGs IOCTL is received, but the 
-values passed from the app are not used in any buffer calculation 
-(ossfragshift/ossmaxfrags are not used).
-Use the "defaultorder=N" module parameter to change the buffer size if
-you have an application that requires a specific number of fragments
-or a specific buffer size (see below).
-
-Debug Interface
----------------
-There is an ioctl debug interface to allow runtime modification of the 
-debug print levels.  This debug interface code can be disabled from the 
-compilation process with commenting the following define:
-#define CSDEBUG_INTERFACE 1
-There is also a debug print methodolgy to select printf statements from
-different areas of the driver.  A debug print level is also used to allow
-additional printfs to be active.  Comment out the following line in the
-driver to disable compilation of the CS_DBGOUT print statements:
-#define CSDEBUG 1
- 
-Please see the definitions for cs_debuglevel and cs_debugmask for additional
-information on the debug levels and sections.
-
-There is also a csdbg executable to allow runtime manipulation of these 
-parameters.  for a copy email: twoller@crystal.cirrus.com
-
-
-
-MODULE_PARMS definitions
-------------------------
-module_param(defaultorder, ulong, 0);
-defaultorder=N
-where N is a value from 1 to 12
-The buffer order determines the size of the dma buffer for the driver.
-under Linux, a smaller buffer allows more responsiveness from many of the 
-applications (e.g. games).  A larger buffer allows some of the apps (esound) 
-to not underrun the dma buffer as easily.  As default, use 32k (order=3)
-rather than 64k as some of the games work more responsively.
-(2^N) * PAGE_SIZE = allocated buffer size
-
-module_param(cs_debuglevel, ulong, 0644);
-module_param(cs_debugmask, ulong, 0644);
-cs_debuglevel=N
-cs_debugmask=0xMMMMMMMM
-where N is a value from 0 (no debug printfs), to 9 (maximum)
-0xMMMMMMMM is a debug mask corresponding to the CS_xxx bits (see driver source).
-
-module_param(hercules_egpio_disable, ulong, 0);
-hercules_egpio_disable=N
-where N is a 0 (enable egpio), or a 1 (disable egpio support)
-
-module_param(initdelay, ulong, 0);
-initdelay=N
-This value is used to determine the millescond delay during the initialization
-code prior to powering up the PLL.  On laptops this value can be used to
-assist with errors on resume, mostly with IBM laptops.  Basically, if the 
-system is booted under battery power then the mdelay()/udelay() functions fail to 
-properly delay the required time.  Also, if the system is booted under AC power
-and then the power removed, the mdelay()/udelay() functions will not delay properly.
- 
-module_param(powerdown, ulong, 0);
-powerdown=N
-where N is 0 (disable any powerdown of the internal blocks) or 1 (enable powerdown)
-
-
-module_param(external_amp, bool, 0);
-external_amp=1
-if N is set to 1, then force enabling the EAPD support in the primary AC97 codec.
-override the detection logic and force the external amp bit in the AC97 0x26 register
-to be reset (0).  EAPD should be 0 for powerup, and 1 for powerdown.  The VTB Santa Cruz
-card has inverted logic, so there is a special function for these cards.
-
-module_param(thinkpad, bool, 0);
-thinkpad=1
-if N is set to 1, then force enabling the clkrun functionality.
-Currently, when the part is being used, then clkrun is disabled for the entire system,
-but re-enabled when the driver is released or there is no outstanding open count.
-
diff --git a/Documentation/spi/spi-lm70llp b/Documentation/spi/spi-lm70llp
new file mode 100644
index 0000000..154bd02
--- /dev/null
+++ b/Documentation/spi/spi-lm70llp
@@ -0,0 +1,69 @@
+spi_lm70llp :  LM70-LLP parport-to-SPI adapter
+==============================================
+
+Supported board/chip:
+  * National Semiconductor LM70 LLP evaluation board
+    Datasheet: http://www.national.com/pf/LM/LM70.html
+
+Author:
+        Kaiwan N Billimoria <kaiwan@designergraphix.com>
+
+Description
+-----------
+This driver provides glue code connecting a National Semiconductor LM70 LLP
+temperature sensor evaluation board to the kernel's SPI core subsystem.
+
+In effect, this driver turns the parallel port interface on the eval board
+into a SPI bus with a single device, which will be driven by the generic
+LM70 driver (drivers/hwmon/lm70.c).
+
+The hardware interfacing on the LM70 LLP eval board is as follows:
+
+   Parallel                 LM70 LLP
+     Port      Direction   JP2 Header
+   ----------- --------- ----------------
+      D0     2      -         -
+      D1     3     -->      V+   5
+      D2     4     -->      V+   5
+      D3     5     -->      V+   5
+      D4     6     -->      V+   5
+      D5     7     -->      nCS  8
+      D6     8     -->      SCLK 3
+      D7     9     -->      SI/O 5
+     GND    25      -       GND  7
+    Select  13     <--      SI/O 1
+   ----------- --------- ----------------
+
+Note that since the LM70 uses a "3-wire" variant of SPI, the SI/SO pin
+is connected to both pin D7 (as Master Out) and Select (as Master In)
+using an arrangment that lets either the parport or the LM70 pull the
+pin low.  This can't be shared with true SPI devices, but other 3-wire
+devices might share the same SI/SO pin.
+
+The bitbanger routine in this driver (lm70_txrx) is called back from
+the bound "hwmon/lm70" protocol driver through its sysfs hook, using a
+spi_write_then_read() call.  It performs Mode 0 (SPI/Microwire) bitbanging.
+The lm70 driver then inteprets the resulting digital temperature value
+and exports it through sysfs.
+
+A "gotcha": National Semiconductor's LM70 LLP eval board circuit schematic
+shows that the SI/O line from the LM70 chip is connected to the base of a
+transistor Q1 (and also a pullup, and a zener diode to D7); while the
+collector is tied to VCC.
+
+Interpreting this circuit, when the LM70 SI/O line is High (or tristate
+and not grounded by the host via D7), the transistor conducts and switches
+the collector to zero, which is reflected on pin 13 of the DB25 parport
+connector.  When SI/O is Low (driven by the LM70 or the host) on the other
+hand, the transistor is cut off and the voltage tied to it's collector is
+reflected on pin 13 as a High level.
+
+So: the getmiso inline routine in this driver takes this fact into account,
+inverting the value read at pin 13.
+
+
+Thanks to
+---------
+o David Brownell for mentoring the SPI-side driver development.
+o Dr.Craig Hollabaugh for the (early) "manual" bitbanging driver version.
+o Nadir Billimoria for help interpreting the circuit schematic.
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index 795fbb4..76ea6c8 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -1,26 +1,30 @@
 Overview of Linux kernel SPI support
 ====================================
 
-02-Dec-2005
+21-May-2007
 
 What is SPI?
 ------------
 The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial
 link used to connect microcontrollers to sensors, memory, and peripherals.
+It's a simple "de facto" standard, not complicated enough to acquire a
+standardization body.  SPI uses a master/slave configuration.
 
 The three signal wires hold a clock (SCK, often on the order of 10 MHz),
 and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In,
 Slave Out" (MISO) signals.  (Other names are also used.)  There are four
 clocking modes through which data is exchanged; mode-0 and mode-3 are most
 commonly used.  Each clock cycle shifts data out and data in; the clock
-doesn't cycle except when there is data to shift.
+doesn't cycle except when there is a data bit to shift.  Not all data bits
+are used though; not every protocol uses those full duplex capabilities.
 
-SPI masters may use a "chip select" line to activate a given SPI slave
+SPI masters use a fourth "chip select" line to activate a given SPI slave
 device, so those three signal wires may be connected to several chips
-in parallel.  All SPI slaves support chipselects.  Some devices have
+in parallel.  All SPI slaves support chipselects; they are usually active
+low signals, labeled nCSx for slave 'x' (e.g. nCS0).  Some devices have
 other signals, often including an interrupt to the master.
 
-Unlike serial busses like USB or SMBUS, even low level protocols for
+Unlike serial busses like USB or SMBus, even low level protocols for
 SPI slave functions are usually not interoperable between vendors
 (except for commodities like SPI memory chips).
 
@@ -33,6 +37,11 @@
   - Some devices may use eight bit words.  Others may different word
     lengths, such as streams of 12-bit or 20-bit digital samples.
 
+  - Words are usually sent with their most significant bit (MSB) first,
+    but sometimes the least significant bit (LSB) goes first instead.
+
+  - Sometimes SPI is used to daisy-chain devices, like shift registers.
+
 In the same way, SPI slaves will only rarely support any kind of automatic
 discovery/enumeration protocol.  The tree of slave devices accessible from
 a given SPI master will normally be set up manually, with configuration
@@ -44,6 +53,14 @@
 Serial Protocol"), PSP ("Programmable Serial Protocol"), and other
 related protocols.
 
+Some chips eliminate a signal line by combining MOSI and MISO, and
+limiting themselves to half-duplex at the hardware level.  In fact
+some SPI chips have this signal mode as a strapping option.  These
+can be accessed using the same programming interface as SPI, but of
+course they won't handle full duplex transfers.  You may find such
+chips described as using "three wire" signaling: SCK, data, nCSx.
+(That data line is sometimes called MOMI or SISO.)
+
 Microcontrollers often support both master and slave sides of the SPI
 protocol.  This document (and Linux) currently only supports the master
 side of SPI interactions.
@@ -74,6 +91,32 @@
 cards without needing a special purpose MMC/SD/SDIO controller.
 
 
+I'm confused.  What are these four SPI "clock modes"?
+-----------------------------------------------------
+It's easy to be confused here, and the vendor documentation you'll
+find isn't necessarily helpful.  The four modes combine two mode bits:
+
+ - CPOL indicates the initial clock polarity.  CPOL=0 means the
+   clock starts low, so the first (leading) edge is rising, and
+   the second (trailing) edge is falling.  CPOL=1 means the clock
+   starts high, so the first (leading) edge is falling.
+
+ - CPHA indicates the clock phase used to sample data; CPHA=0 says
+   sample on the leading edge, CPHA=1 means the trailing edge.
+
+   Since the signal needs to stablize before it's sampled, CPHA=0
+   implies that its data is written half a clock before the first
+   clock edge.  The chipselect may have made it become available.
+
+Chip specs won't always say "uses SPI mode X" in as many words,
+but their timing diagrams will make the CPOL and CPHA modes clear.
+
+In the SPI mode number, CPOL is the high order bit and CPHA is the
+low order bit.  So when a chip's timing diagram shows the clock
+starting low (CPOL=0) and data stabilized for sampling during the
+trailing clock edge (CPHA=1), that's SPI mode 1.
+
+
 How do these driver programming interfaces work?
 ------------------------------------------------
 The <linux/spi/spi.h> header file includes kerneldoc, as does the
diff --git a/Documentation/spinlocks.txt b/Documentation/spinlocks.txt
index a661d68..471e753 100644
--- a/Documentation/spinlocks.txt
+++ b/Documentation/spinlocks.txt
@@ -1,7 +1,12 @@
-UPDATE March 21 2005 Amit Gud <gud@eth.net>
+SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED defeat lockdep state tracking and
+are hence deprecated.
 
-Macros SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated and will be
-removed soon. So for any new code dynamic initialization should be used:
+Please use DEFINE_SPINLOCK()/DEFINE_RWLOCK() or
+__SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED() as appropriate for static
+initialization.
+
+Dynamic initialization, when necessary, may be performed as
+demonstrated below.
 
    spinlock_t xxx_lock;
    rwlock_t xxx_rw_lock;
@@ -15,12 +20,9 @@
 
    module_init(xxx_init);
 
-Reasons for deprecation
-  - it hurts automatic lock validators
-  - it becomes intrusive for the realtime preemption patches
-
-Following discussion is still valid, however, with the dynamic initialization
-of spinlocks instead of static.
+The following discussion is still valid, however, with the dynamic
+initialization of spinlocks or with DEFINE_SPINLOCK, etc., used
+instead of SPIN_LOCK_UNLOCKED.
 
 -----------------------
 
diff --git a/Documentation/sysctl/ctl_unnumbered.txt b/Documentation/sysctl/ctl_unnumbered.txt
new file mode 100644
index 0000000..23003a8e
--- /dev/null
+++ b/Documentation/sysctl/ctl_unnumbered.txt
@@ -0,0 +1,22 @@
+
+Except for a few extremely rare exceptions user space applications do not use
+the binary sysctl interface.  Instead everyone uses /proc/sys/...  with
+readable ascii names.
+
+Recently the kernel has started supporting setting the binary sysctl value to
+CTL_UNNUMBERED so we no longer need to assign a binary sysctl path to allow
+sysctls to show up in /proc/sys.
+
+Assigning binary sysctl numbers is an endless source of conflicts in sysctl.h,
+breaking of the user space ABI (because of those conflicts), and maintenance
+problems.  A complete pass through all of the sysctl users revealed multiple
+instances where the sysctl binary interface was broken and had gone undetected
+for years.
+
+So please do not add new binary sysctl numbers.  They are unneeded and
+problematic.
+
+If you really need a new binary sysctl number please first merge your sysctl
+into the kernel and then as a separate patch allocate a binary sysctl number.
+
+(ebiederm@xmission.com, June 2007)
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 1d19256..a0ccc5b 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -31,12 +31,15 @@
 - min_unmapped_ratio
 - min_slab_ratio
 - panic_on_oom
+- mmap_min_address
+- numa_zonelist_order
 
 ==============================================================
 
 dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
 dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode,
-block_dump, swap_token_timeout, drop-caches:
+block_dump, swap_token_timeout, drop-caches,
+hugepages_treat_as_movable:
 
 See Documentation/filesystems/proc.txt
 
@@ -216,3 +219,61 @@
 The default value is 0.
 1 and 2 are for failover of clustering. Please select either
 according to your policy of failover.
+
+==============================================================
+
+mmap_min_addr
+
+This file indicates the amount of address space  which a user process will
+be restricted from mmaping.  Since kernel null dereference bugs could
+accidentally operate based on the information in the first couple of pages
+of memory userspace processes should not be allowed to write to them.  By
+default this value is set to 0 and no protections will be enforced by the
+security module.  Setting this value to something like 64k will allow the
+vast majority of applications to work correctly and provide defense in depth
+against future potential kernel bugs.
+
+==============================================================
+
+numa_zonelist_order
+
+This sysctl is only for NUMA.
+'where the memory is allocated from' is controlled by zonelists.
+(This documentation ignores ZONE_HIGHMEM/ZONE_DMA32 for simple explanation.
+ you may be able to read ZONE_DMA as ZONE_DMA32...)
+
+In non-NUMA case, a zonelist for GFP_KERNEL is ordered as following.
+ZONE_NORMAL -> ZONE_DMA
+This means that a memory allocation request for GFP_KERNEL will
+get memory from ZONE_DMA only when ZONE_NORMAL is not available.
+
+In NUMA case, you can think of following 2 types of order.
+Assume 2 node NUMA and below is zonelist of Node(0)'s GFP_KERNEL
+
+(A) Node(0) ZONE_NORMAL -> Node(0) ZONE_DMA -> Node(1) ZONE_NORMAL
+(B) Node(0) ZONE_NORMAL -> Node(1) ZONE_NORMAL -> Node(0) ZONE_DMA.
+
+Type(A) offers the best locality for processes on Node(0), but ZONE_DMA
+will be used before ZONE_NORMAL exhaustion. This increases possibility of
+out-of-memory(OOM) of ZONE_DMA because ZONE_DMA is tend to be small.
+
+Type(B) cannot offer the best locality but is more robust against OOM of
+the DMA zone.
+
+Type(A) is called as "Node" order. Type (B) is "Zone" order.
+
+"Node order" orders the zonelists by node, then by zone within each node.
+Specify "[Nn]ode" for zone order
+
+"Zone Order" orders the zonelists by zone type, then by node within each
+zone.  Specify "[Zz]one"for zode order.
+
+Specify "[Dd]efault" to request automatic configuration.  Autoconfiguration
+will select "node" order in following case.
+(1) if the DMA zone does not exist or
+(2) if the DMA zone comprises greater than 50% of the available memory or
+(3) if any node's DMA zone comprises greater than 60% of its local memory and
+    the amount of local memory is big enough.
+
+Otherwise, "zone" order will be selected. Default order is recommended unless
+this is causing problems for your system/application.
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
new file mode 100644
index 0000000..42861bb
--- /dev/null
+++ b/Documentation/sysfs-rules.txt
@@ -0,0 +1,166 @@
+Rules on how to access information in the Linux kernel sysfs
+
+The kernel exported sysfs exports internal kernel implementation-details
+and depends on internal kernel structures and layout. It is agreed upon
+by the kernel developers that the Linux kernel does not provide a stable
+internal API. As sysfs is a direct export of kernel internal
+structures, the sysfs interface can not provide a stable interface eighter,
+it may always change along with internal kernel changes.
+
+To minimize the risk of breaking users of sysfs, which are in most cases
+low-level userspace applications, with a new kernel release, the users
+of sysfs must follow some rules to use an as abstract-as-possible way to
+access this filesystem. The current udev and HAL programs already
+implement this and users are encouraged to plug, if possible, into the
+abstractions these programs provide instead of accessing sysfs
+directly.
+
+But if you really do want or need to access sysfs directly, please follow
+the following rules and then your programs should work with future
+versions of the sysfs interface.
+
+- Do not use libsysfs
+  It makes assumptions about sysfs which are not true. Its API does not
+  offer any abstraction, it exposes all the kernel driver-core
+  implementation details in its own API. Therefore it is not better than
+  reading directories and opening the files yourself.
+  Also, it is not actively maintained, in the sense of reflecting the
+  current kernel-development. The goal of providing a stable interface
+  to sysfs has failed, it causes more problems, than it solves. It
+  violates many of the rules in this document.
+
+- sysfs is always at /sys
+  Parsing /proc/mounts is a waste of time. Other mount points are a
+  system configuration bug you should not try to solve. For test cases,
+  possibly support a SYSFS_PATH environment variable to overwrite the
+  applications behavior, but never try to search for sysfs. Never try
+  to mount it, if you are not an early boot script.
+
+- devices are only "devices"
+  There is no such thing like class-, bus-, physical devices,
+  interfaces, and such that you can rely on in userspace. Everything is
+  just simply a "device". Class-, bus-, physical, ... types are just
+  kernel implementation details, which should not be expected by
+  applications that look for devices in sysfs.
+
+  The properties of a device are:
+    o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0)
+      - identical to the DEVPATH value in the event sent from the kernel
+        at device creation and removal
+      - the unique key to the device at that point in time
+      - the kernels path to the device-directory without the leading
+        /sys, and always starting with with a slash
+      - all elements of a devpath must be real directories. Symlinks
+        pointing to /sys/devices must always be resolved to their real
+        target, and the target path must be used to access the device.
+        That way the devpath to the device matches the devpath of the
+        kernel used at event time.
+      - using or exposing symlink values as elements in a devpath string
+        is a bug in the application
+
+    o kernel name (sda, tty, 0000:00:1f.2, ...)
+      - a directory name, identical to the last element of the devpath
+      - applications need to handle spaces and characters like '!' in
+        the name
+
+    o subsystem (block, tty, pci, ...)
+      - simple string, never a path or a link
+      - retrieved by reading the "subsystem"-link and using only the
+        last element of the target path
+
+    o driver (tg3, ata_piix, uhci_hcd)
+      - a simple string, which may contain spaces, never a path or a
+        link
+      - it is retrieved by reading the "driver"-link and using only the
+        last element of the target path
+      - devices which do not have "driver"-link, just do not have a
+        driver; copying the driver value in a child device context, is a
+        bug in the application
+
+    o attributes
+      - the files in the device directory or files below a subdirectories
+        of the same device directory
+      - accessing attributes reached by a symlink pointing to another device,
+        like the "device"-link, is a bug in the application
+
+  Everything else is just a kernel driver-core implementation detail,
+  that should not be assumed to be stable across kernel releases.
+
+- Properties of parent devices never belong into a child device.
+  Always look at the parent devices themselves for determining device
+  context properties. If the device 'eth0' or 'sda' does not have a
+  "driver"-link, then this device does not have a driver. Its value is empty.
+  Never copy any property of the parent-device into a child-device. Parent
+  device-properties may change dynamically without any notice to the
+  child device.
+
+- Hierarchy in a single device-tree
+  There is only one valid place in sysfs where hierarchy can be examined
+  and this is below: /sys/devices.
+  It is planned, that all device directories will end up in the tree
+  below this directory.
+
+- Classification by subsystem
+  There are currently three places for classification of devices:
+  /sys/block, /sys/class and /sys/bus. It is planned that these will
+  not contain any device-directories themselves, but only flat lists of
+  symlinks pointing to the unified /sys/devices tree.
+  All three places have completely different rules on how to access
+  device information. It is planned to merge all three
+  classification-directories into one place at /sys/subsystem,
+  following the layout of the bus-directories. All buses and
+  classes, including the converted block-subsystem, will show up
+  there.
+  The devices belonging to a subsystem will create a symlink in the
+  "devices" directory at /sys/subsystem/<name>/devices.
+
+  If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
+  ignored. If it does not exist, you have always to scan all three
+  places, as the kernel is free to move a subsystem from one place to
+  the other, as long as the devices are still reachable by the same
+  subsystem name.
+
+  Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or
+  /sys/block and /sys/class/block are not interchangeable, is a bug in
+  the application.
+
+- Block
+  The converted block-subsystem at /sys/class/block, or
+  /sys/subsystem/block will contain the links for disks and partitions
+  at the same level, never in a hierarchy. Assuming the block-subsytem to
+  contain only disks and not partition-devices in the same flat list is
+  a bug in the application.
+
+- "device"-link and <subsystem>:<kernel name>-links
+  Never depend on the "device"-link. The "device"-link is a workaround
+  for the old layout, where class-devices are not created in
+  /sys/devices/ like the bus-devices. If the link-resolving of a
+  device-directory does not end in /sys/devices/, you can use the
+  "device"-link to find the parent devices in /sys/devices/. That is the
+  single valid use of the "device"-link, it must never appear in any
+  path as an element. Assuming the existence of the "device"-link for
+  a device in /sys/devices/ is a bug in the application.
+  Accessing /sys/class/net/eth0/device is a bug in the application.
+
+  Never depend on the class-specific links back to the /sys/class
+  directory.  These links are also a workaround for the design mistake
+  that class-devices are not created in /sys/devices. If a device
+  directory does not contain directories for child devices, these links
+  may be used to find the child devices in /sys/class. That is the single
+  valid use of these links, they must never appear in any path as an
+  element. Assuming the existence of these links for devices which are
+  real child device directories in the /sys/devices tree, is a bug in
+  the application.
+
+  It is planned to remove all these links when when all class-device
+  directories live in /sys/devices.
+
+- Position of devices along device chain can change.
+  Never depend on a specific parent device position in the devpath,
+  or the chain of parent devices. The kernel is free to insert devices into
+  the chain. You must always request the parent device you are looking for
+  by its subsystem value. You need to walk up the chain until you find
+  the device that matches the expected subsystem. Depending on a specific
+  position of a parent device, or exposing relative paths, using "../" to
+  access the chain of parents, is a bug in the application.
+
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt
index 2d48033..9e6b94f 100644
--- a/Documentation/thinkpad-acpi.txt
+++ b/Documentation/thinkpad-acpi.txt
@@ -138,7 +138,7 @@
 --------
 
 procfs: /proc/acpi/ibm/hotkey
-sysfs device attribute: hotkey/*
+sysfs device attribute: hotkey_*
 
 Without this driver, only the Fn-F4 key (sleep button) generates an
 ACPI event. With the driver loaded, the hotkey feature enabled and the
@@ -196,10 +196,7 @@
 
 sysfs notes:
 
-	The hot keys attributes are in a hotkey/ subdirectory off the
-	thinkpad device.
-
-	bios_enabled:
+	hotkey_bios_enabled:
 		Returns the status of the hot keys feature when
 		thinkpad-acpi was loaded.  Upon module unload, the hot
 		key feature status will be restored to this value.
@@ -207,19 +204,19 @@
 		0: hot keys were disabled
 		1: hot keys were enabled
 
-	bios_mask:
+	hotkey_bios_mask:
 		Returns the hot keys mask when thinkpad-acpi was loaded.
 		Upon module unload, the hot keys mask will be restored
 		to this value.
 
-	enable:
+	hotkey_enable:
 		Enables/disables the hot keys feature, and reports
 		current status of the hot keys feature.
 
 		0: disables the hot keys feature / feature disabled
 		1: enables the hot keys feature / feature enabled
 
-	mask:
+	hotkey_mask:
 		bit mask to enable ACPI event generation for each hot
 		key (see above).  Returns the current status of the hot
 		keys mask, and allows one to modify it.
@@ -229,7 +226,7 @@
 ---------
 
 procfs: /proc/acpi/ibm/bluetooth
-sysfs device attribute: bluetooth/enable
+sysfs device attribute: bluetooth_enable
 
 This feature shows the presence and current state of a ThinkPad
 Bluetooth device in the internal ThinkPad CDC slot.
@@ -244,7 +241,7 @@
 Sysfs notes:
 
 	If the Bluetooth CDC card is installed, it can be enabled /
-	disabled through the "bluetooth/enable" thinkpad-acpi device
+	disabled through the "bluetooth_enable" thinkpad-acpi device
 	attribute, and its current status can also be queried.
 
 	enable:
@@ -252,7 +249,7 @@
 		1: enables Bluetooth / Bluetooth is enabled.
 
 	Note: this interface will be probably be superseeded by the
-	generic rfkill class.
+	generic rfkill class, so it is NOT to be considered stable yet.
 
 Video output control -- /proc/acpi/ibm/video
 --------------------------------------------
@@ -898,7 +895,7 @@
 -----------------
 
 procfs: /proc/acpi/ibm/wan
-sysfs device attribute: wwan/enable
+sysfs device attribute: wwan_enable
 
 This feature is marked EXPERIMENTAL because the implementation
 directly accesses hardware registers and may not work as expected. USE
@@ -921,7 +918,7 @@
 Sysfs notes:
 
 	If the W-WAN card is installed, it can be enabled /
-	disabled through the "wwan/enable" thinkpad-acpi device
+	disabled through the "wwan_enable" thinkpad-acpi device
 	attribute, and its current status can also be queried.
 
 	enable:
@@ -929,7 +926,7 @@
 		1: enables WWAN card / WWAN card is enabled.
 
 	Note: this interface will be probably be superseeded by the
-	generic rfkill class.
+	generic rfkill class, so it is NOT to be considered stable yet.
 
 Multiple Commands, Module Parameters
 ------------------------------------
diff --git a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt
index 62844ae..e8b50b7 100644
--- a/Documentation/usb/dma.txt
+++ b/Documentation/usb/dma.txt
@@ -32,12 +32,15 @@
 It's good to avoid making CPUs copy data needlessly.  The costs can add up,
 and effects like cache-trashing can impose subtle penalties.
 
-- When you're allocating a buffer for DMA purposes anyway, use the buffer
-  primitives.  Think of them as kmalloc and kfree that give you the right
-  kind of addresses to store in urb->transfer_buffer and urb->transfer_dma,
-  while guaranteeing that no hidden copies through DMA "bounce" buffers will
-  slow things down.  You'd also set URB_NO_TRANSFER_DMA_MAP in
-  urb->transfer_flags:
+- If you're doing lots of small data transfers from the same buffer all
+  the time, that can really burn up resources on systems which use an
+  IOMMU to manage the DMA mappings.  It can cost MUCH more to set up and
+  tear down the IOMMU mappings with each request than perform the I/O!
+
+  For those specific cases, USB has primitives to allocate less expensive
+  memory.  They work like kmalloc and kfree versions that give you the right
+  kind of addresses to store in urb->transfer_buffer and urb->transfer_dma.
+  You'd also set URB_NO_TRANSFER_DMA_MAP in urb->transfer_flags:
 
 	void *usb_buffer_alloc (struct usb_device *dev, size_t size,
 		int mem_flags, dma_addr_t *dma);
@@ -45,6 +48,10 @@
 	void usb_buffer_free (struct usb_device *dev, size_t size,
 		void *addr, dma_addr_t dma);
 
+  Most drivers should *NOT* be using these primitives; they don't need
+  to use this type of memory ("dma-coherent"), and memory returned from
+  kmalloc() will work just fine.
+
   For control transfers you can use the buffer primitives or not for each
   of the transfer buffer and setup buffer independently.  Set the flag bits
   URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP to indicate which
@@ -54,29 +61,39 @@
   The memory buffer returned is "dma-coherent"; sometimes you might need to
   force a consistent memory access ordering by using memory barriers.  It's
   not using a streaming DMA mapping, so it's good for small transfers on
-  systems where the I/O would otherwise tie up an IOMMU mapping.  (See
+  systems where the I/O would otherwise thrash an IOMMU mapping.  (See
   Documentation/DMA-mapping.txt for definitions of "coherent" and "streaming"
   DMA mappings.)
 
   Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
   space-efficient.
 
+  On most systems the memory returned will be uncached, because the
+  semantics of dma-coherent memory require either bypassing CPU caches
+  or using cache hardware with bus-snooping support.  While x86 hardware
+  has such bus-snooping, many other systems use software to flush cache
+  lines to prevent DMA conflicts.
+
 - Devices on some EHCI controllers could handle DMA to/from high memory.
-  Driver probe() routines can notice this using a generic DMA call, then
-  tell higher level code (network, scsi, etc) about it like this:
 
-	if (dma_supported (&intf->dev, 0xffffffffffffffffULL))
-		net->features |= NETIF_F_HIGHDMA;
+  Unfortunately, the current Linux DMA infrastructure doesn't have a sane
+  way to expose these capabilities ... and in any case, HIGHMEM is mostly a
+  design wart specific to x86_32.  So your best bet is to ensure you never
+  pass a highmem buffer into a USB driver.  That's easy; it's the default
+  behavior.  Just don't override it; e.g. with NETIF_F_HIGHDMA.
 
-  That can eliminate dma bounce buffering of requests that originate (or
-  terminate) in high memory, in cases where the buffers aren't allocated
-  with usb_buffer_alloc() but instead are dma-mapped.
+  This may force your callers to do some bounce buffering, copying from
+  high memory to "normal" DMA memory.  If you can come up with a good way
+  to fix this issue (for x86_32 machines with over 1 GByte of memory),
+  feel free to submit patches.
 
 
 WORKING WITH EXISTING BUFFERS
 
 Existing buffers aren't usable for DMA without first being mapped into the
-DMA address space of the device.
+DMA address space of the device.  However, most buffers passed to your
+driver can safely be used with such DMA mapping.  (See the first section
+of DMA-mapping.txt, titled "What memory is DMA-able?")
 
 - When you're using scatterlists, you can map everything at once.  On some
   systems, this kicks in an IOMMU and turns the scatterlists into single
@@ -114,3 +131,8 @@
   The calls manage urb->transfer_dma for you, and set URB_NO_TRANSFER_DMA_MAP
   so that usbcore won't map or unmap the buffer.  The same goes for
   urb->setup_dma and URB_NO_SETUP_DMA_MAP for control requests.
+
+Note that several of those interfaces are currently commented out, since
+they don't have current users.  See the source code.  Other than the dmasync
+calls (where the underlying DMA primitives have changed), most of them can
+easily be commented back in if you want to use them.
diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
new file mode 100644
index 0000000..df54d64
--- /dev/null
+++ b/Documentation/usb/persist.txt
@@ -0,0 +1,156 @@
+		USB device persistence during system suspend
+
+		   Alan Stern <stern@rowland.harvard.edu>
+
+		 September 2, 2006 (Updated May 29, 2007)
+
+
+	What is the problem?
+
+According to the USB specification, when a USB bus is suspended the
+bus must continue to supply suspend current (around 1-5 mA).  This
+is so that devices can maintain their internal state and hubs can
+detect connect-change events (devices being plugged in or unplugged).
+The technical term is "power session".
+
+If a USB device's power session is interrupted then the system is
+required to behave as though the device has been unplugged.  It's a
+conservative approach; in the absence of suspend current the computer
+has no way to know what has actually happened.  Perhaps the same
+device is still attached or perhaps it was removed and a different
+device plugged into the port.  The system must assume the worst.
+
+By default, Linux behaves according to the spec.  If a USB host
+controller loses power during a system suspend, then when the system
+wakes up all the devices attached to that controller are treated as
+though they had disconnected.  This is always safe and it is the
+"officially correct" thing to do.
+
+For many sorts of devices this behavior doesn't matter in the least.
+If the kernel wants to believe that your USB keyboard was unplugged
+while the system was asleep and a new keyboard was plugged in when the
+system woke up, who cares?  It'll still work the same when you type on
+it.
+
+Unfortunately problems _can_ arise, particularly with mass-storage
+devices.  The effect is exactly the same as if the device really had
+been unplugged while the system was suspended.  If you had a mounted
+filesystem on the device, you're out of luck -- everything in that
+filesystem is now inaccessible.  This is especially annoying if your
+root filesystem was located on the device, since your system will
+instantly crash.
+
+Loss of power isn't the only mechanism to worry about.  Anything that
+interrupts a power session will have the same effect.  For example,
+even though suspend current may have been maintained while the system
+was asleep, on many systems during the initial stages of wakeup the
+firmware (i.e., the BIOS) resets the motherboard's USB host
+controllers.  Result: all the power sessions are destroyed and again
+it's as though you had unplugged all the USB devices.  Yes, it's
+entirely the BIOS's fault, but that doesn't do _you_ any good unless
+you can convince the BIOS supplier to fix the problem (lots of luck!).
+
+On many systems the USB host controllers will get reset after a
+suspend-to-RAM.  On almost all systems, no suspend current is
+available during hibernation (also known as swsusp or suspend-to-disk).
+You can check the kernel log after resuming to see if either of these
+has happened; look for lines saying "root hub lost power or was reset".
+
+In practice, people are forced to unmount any filesystems on a USB
+device before suspending.  If the root filesystem is on a USB device,
+the system can't be suspended at all.  (All right, it _can_ be
+suspended -- but it will crash as soon as it wakes up, which isn't
+much better.)
+
+
+	What is the solution?
+
+Setting CONFIG_USB_PERSIST will cause the kernel to work around these
+issues.  It enables a mode in which the core USB device data
+structures are allowed to persist across a power-session disruption.
+It works like this.  If the kernel sees that a USB host controller is
+not in the expected state during resume (i.e., if the controller was
+reset or otherwise had lost power) then it applies a persistence check
+to each of the USB devices below that controller for which the
+"persist" attribute is set.  It doesn't try to resume the device; that
+can't work once the power session is gone.  Instead it issues a USB
+port reset and then re-enumerates the device.  (This is exactly the
+same thing that happens whenever a USB device is reset.)  If the
+re-enumeration shows that the device now attached to that port has the
+same descriptors as before, including the Vendor and Product IDs, then
+the kernel continues to use the same device structure.  In effect, the
+kernel treats the device as though it had merely been reset instead of
+unplugged.
+
+If no device is now attached to the port, or if the descriptors are
+different from what the kernel remembers, then the treatment is what
+you would expect.  The kernel destroys the old device structure and
+behaves as though the old device had been unplugged and a new device
+plugged in, just as it would without the CONFIG_USB_PERSIST option.
+
+The end result is that the USB device remains available and usable.
+Filesystem mounts and memory mappings are unaffected, and the world is
+now a good and happy place.
+
+Note that even when CONFIG_USB_PERSIST is set, the "persist" feature
+will be applied only to those devices for which it is enabled.  You
+can enable the feature by doing (as root):
+
+	echo 1 >/sys/bus/usb/devices/.../power/persist
+
+where the "..." should be filled in the with the device's ID.  Disable
+the feature by writing 0 instead of 1.  For hubs the feature is
+automatically and permanently enabled, so you only have to worry about
+setting it for devices where it really matters.
+
+
+	Is this the best solution?
+
+Perhaps not.  Arguably, keeping track of mounted filesystems and
+memory mappings across device disconnects should be handled by a
+centralized Logical Volume Manager.  Such a solution would allow you
+to plug in a USB flash device, create a persistent volume associated
+with it, unplug the flash device, plug it back in later, and still
+have the same persistent volume associated with the device.  As such
+it would be more far-reaching than CONFIG_USB_PERSIST.
+
+On the other hand, writing a persistent volume manager would be a big
+job and using it would require significant input from the user.  This
+solution is much quicker and easier -- and it exists now, a giant
+point in its favor!
+
+Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
+just mass-storage devices.  It might turn out to be equally useful for
+other device types, such as network interfaces.
+
+
+	WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
+
+When recovering an interrupted power session the kernel does its best
+to make sure the USB device hasn't been changed; that is, the same
+device is still plugged into the port as before.  But the checks
+aren't guaranteed to be 100% accurate.
+
+If you replace one USB device with another of the same type (same
+manufacturer, same IDs, and so on) there's an excellent chance the
+kernel won't detect the change.  Serial numbers and other strings are
+not compared.  In many cases it wouldn't help if they were, because
+manufacturers frequently omit serial numbers entirely in their
+devices.
+
+Furthermore it's quite possible to leave a USB device exactly the same
+while changing its media.  If you replace the flash memory card in a
+USB card reader while the system is asleep, the kernel will have no
+way to know you did it.  The kernel will assume that nothing has
+happened and will continue to use the partition tables, inodes, and
+memory mappings for the old card.
+
+If the kernel gets fooled in this way, it's almost certain to cause
+data corruption and to crash your system.  You'll have no one to blame
+but yourself.
+
+YOU HAVE BEEN WARNED!  USE AT YOUR OWN RISK!
+
+That having been said, most of the time there shouldn't be any trouble
+at all.  The "persist" feature can be extremely useful.  Make the most
+of it.
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 687104b..51ccc48 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -77,8 +77,9 @@
 call, then it is required that system administrator mount a file system of
 type hugetlbfs:
 
-	mount none /mnt/huge -t hugetlbfs <uid=value> <gid=value> <mode=value>
-		 <size=value> <nr_inodes=value>
+  mount -t hugetlbfs \
+	-o uid=<value>,gid=<value>,mode=<value>,size=<value>,nr_inodes=<value> \
+	none /mnt/huge
 
 This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
 /mnt/huge.  Any files created on /mnt/huge uses hugepages.  The uid and gid
@@ -88,11 +89,10 @@
 By default the value 0755 is picked. The size option sets the maximum value of
 memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
 rounded down to HPAGE_SIZE.  The option nr_inodes sets the maximum number of
-inodes that /mnt/huge can use.  If the size or nr_inodes options are not
+inodes that /mnt/huge can use.  If the size or nr_inodes option is not
 provided on command line then no limits are set.  For size and nr_inodes
 options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
-example, size=2K has the same meaning as size=2048. An example is given at
-the end of this document.
+example, size=2K has the same meaning as size=2048.
 
 read and write system calls are not supported on files that reside on hugetlb
 file systems.
diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt
index 727c8d8..d17f324 100644
--- a/Documentation/vm/slub.txt
+++ b/Documentation/vm/slub.txt
@@ -1,13 +1,9 @@
 Short users guide for SLUB
 --------------------------
 
-First of all slub should transparently replace SLAB. If you enable
-SLUB then everything should work the same (Note the word "should".
-There is likely not much value in that word at this point).
-
 The basic philosophy of SLUB is very different from SLAB. SLAB
 requires rebuilding the kernel to activate debug options for all
-SLABS. SLUB always includes full debugging but its off by default.
+slab caches. SLUB always includes full debugging but it is off by default.
 SLUB can enable debugging only for selected slabs in order to avoid
 an impact on overall system performance which may make a bug more
 difficult to find.
@@ -45,6 +41,8 @@
 	P		Poisoning (object and padding)
 	U		User tracking (free and alloc)
 	T		Trace (please only use on single slabs)
+	-		Switch all debugging off (useful if the kernel is
+			configured with CONFIG_SLUB_DEBUG_ON)
 
 F.e. in order to boot just with sanity checks and red zoning one would specify:
 
@@ -76,13 +74,28 @@
 Careful with tracing: It may spew out lots of information and never stop if
 used on the wrong slab.
 
-SLAB Merging
+Slab merging
 ------------
 
-If no debugging is specified then SLUB may merge similar slabs together
+If no debug options are specified then SLUB may merge similar slabs together
 in order to reduce overhead and increase cache hotness of objects.
 slabinfo -a displays which slabs were merged together.
 
+Slab validation
+---------------
+
+SLUB can validate all object if the kernel was booted with slub_debug. In
+order to do so you must have the slabinfo tool. Then you can do
+
+slabinfo -v
+
+which will test all objects. Output will be generated to the syslog.
+
+This also works in a more limited way if boot was without slab debug.
+In that case slabinfo -v simply tests all reachable objects. Usually
+these are in the cpu slabs and the partial slabs. Full slabs are not
+tracked by SLUB in a non debug situation.
+
 Getting more performance
 ------------------------
 
@@ -91,9 +104,9 @@
 governed by the order of the allocation for each slab. The allocations
 can be influenced by kernel parameters:
 
-slub_min_objects=x		(default 8)
+slub_min_objects=x		(default 4)
 slub_min_order=x		(default 0)
-slub_max_order=x		(default 4)
+slub_max_order=x		(default 1)
 
 slub_min_objects allows to specify how many objects must at least fit
 into one slab in order for the allocation order to be acceptable.
@@ -109,5 +122,148 @@
 super large order pages to fit slub_min_objects of a slab cache with
 large object sizes into one high order page.
 
+SLUB Debug output
+-----------------
 
-Christoph Lameter, <clameter@sgi.com>, April 10, 2007
+Here is a sample of slub debug output:
+
+====================================================================
+BUG kmalloc-8: Redzone overwritten
+--------------------------------------------------------------------
+
+INFO: 0xc90f6d28-0xc90f6d2b. First byte 0x00 instead of 0xcc
+INFO: Slab 0xc528c530 flags=0x400000c3 inuse=61 fp=0xc90f6d58
+INFO: Object 0xc90f6d20 @offset=3360 fp=0xc90f6d58
+INFO: Allocated in get_modalias+0x61/0xf5 age=53 cpu=1 pid=554
+
+Bytes b4 0xc90f6d10:  00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ
+  Object 0xc90f6d20:  31 30 31 39 2e 30 30 35                         1019.005
+ Redzone 0xc90f6d28:  00 cc cc cc                                     .
+ Padding 0xc90f6d50:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
+
+  [<c010523d>] dump_trace+0x63/0x1eb
+  [<c01053df>] show_trace_log_lvl+0x1a/0x2f
+  [<c010601d>] show_trace+0x12/0x14
+  [<c0106035>] dump_stack+0x16/0x18
+  [<c017e0fa>] object_err+0x143/0x14b
+  [<c017e2cc>] check_object+0x66/0x234
+  [<c017eb43>] __slab_free+0x239/0x384
+  [<c017f446>] kfree+0xa6/0xc6
+  [<c02e2335>] get_modalias+0xb9/0xf5
+  [<c02e23b7>] dmi_dev_uevent+0x27/0x3c
+  [<c027866a>] dev_uevent+0x1ad/0x1da
+  [<c0205024>] kobject_uevent_env+0x20a/0x45b
+  [<c020527f>] kobject_uevent+0xa/0xf
+  [<c02779f1>] store_uevent+0x4f/0x58
+  [<c027758e>] dev_attr_store+0x29/0x2f
+  [<c01bec4f>] sysfs_write_file+0x16e/0x19c
+  [<c0183ba7>] vfs_write+0xd1/0x15a
+  [<c01841d7>] sys_write+0x3d/0x72
+  [<c0104112>] sysenter_past_esp+0x5f/0x99
+  [<b7f7b410>] 0xb7f7b410
+  =======================
+
+FIX kmalloc-8: Restoring Redzone 0xc90f6d28-0xc90f6d2b=0xcc
+
+If SLUB encounters a corrupted object (full detection requires the kernel
+to be booted with slub_debug) then the following output will be dumped
+into the syslog:
+
+1. Description of the problem encountered
+
+This will be a message in the system log starting with
+
+===============================================
+BUG <slab cache affected>: <What went wrong>
+-----------------------------------------------
+
+INFO: <corruption start>-<corruption_end> <more info>
+INFO: Slab <address> <slab information>
+INFO: Object <address> <object information>
+INFO: Allocated in <kernel function> age=<jiffies since alloc> cpu=<allocated by
+	cpu> pid=<pid of the process>
+INFO: Freed in <kernel function> age=<jiffies since free> cpu=<freed by cpu>
+	 pid=<pid of the process>
+
+(Object allocation / free information is only available if SLAB_STORE_USER is
+set for the slab. slub_debug sets that option)
+
+2. The object contents if an object was involved.
+
+Various types of lines can follow the BUG SLUB line:
+
+Bytes b4 <address> : <bytes>
+	Shows a few bytes before the object where the problem was detected.
+	Can be useful if the corruption does not stop with the start of the
+	object.
+
+Object <address> : <bytes>
+	The bytes of the object. If the object is inactive then the bytes
+	typically contain poison values. Any non-poison value shows a
+	corruption by a write after free.
+
+Redzone <address> : <bytes>
+	The Redzone following the object. The Redzone is used to detect
+	writes after the object. All bytes should always have the same
+	value. If there is any deviation then it is due to a write after
+	the object boundary.
+
+	(Redzone information is only available if SLAB_RED_ZONE is set.
+	slub_debug sets that option)
+
+Padding <address> : <bytes>
+	Unused data to fill up the space in order to get the next object
+	properly aligned. In the debug case we make sure that there are
+	at least 4 bytes of padding. This allows the detection of writes
+	before the object.
+
+3. A stackdump
+
+The stackdump describes the location where the error was detected. The cause
+of the corruption is may be more likely found by looking at the function that
+allocated or freed the object.
+
+4. Report on how the problem was dealt with in order to ensure the continued
+operation of the system.
+
+These are messages in the system log beginning with
+
+FIX <slab cache affected>: <corrective action taken>
+
+In the above sample SLUB found that the Redzone of an active object has
+been overwritten. Here a string of 8 characters was written into a slab that
+has the length of 8 characters. However, a 8 character string needs a
+terminating 0. That zero has overwritten the first byte of the Redzone field.
+After reporting the details of the issue encountered the FIX SLUB message
+tell us that SLUB has restored the Redzone to its proper value and then
+system operations continue.
+
+Emergency operations:
+---------------------
+
+Minimal debugging (sanity checks alone) can be enabled by booting with
+
+	slub_debug=F
+
+This will be generally be enough to enable the resiliency features of slub
+which will keep the system running even if a bad kernel component will
+keep corrupting objects. This may be important for production systems.
+Performance will be impacted by the sanity checks and there will be a
+continual stream of error messages to the syslog but no additional memory
+will be used (unlike full debugging).
+
+No guarantees. The kernel component still needs to be fixed. Performance
+may be optimized further by locating the slab that experiences corruption
+and enabling debugging only for that cache
+
+I.e.
+
+	slub_debug=F,dentry
+
+If the corruption occurs by writing after the end of the object then it
+may be advisable to enable a Redzone to avoid corrupting the beginning
+of other objects.
+
+	slub_debug=FZ,dentry
+
+Christoph Lameter, <clameter@sgi.com>, May 30, 2007
diff --git a/Documentation/volatile-considered-harmful.txt b/Documentation/volatile-considered-harmful.txt
new file mode 100644
index 0000000..10c2e41
--- /dev/null
+++ b/Documentation/volatile-considered-harmful.txt
@@ -0,0 +1,119 @@
+Why the "volatile" type class should not be used
+------------------------------------------------
+
+C programmers have often taken volatile to mean that the variable could be
+changed outside of the current thread of execution; as a result, they are
+sometimes tempted to use it in kernel code when shared data structures are
+being used.  In other words, they have been known to treat volatile types
+as a sort of easy atomic variable, which they are not.  The use of volatile in
+kernel code is almost never correct; this document describes why.
+
+The key point to understand with regard to volatile is that its purpose is
+to suppress optimization, which is almost never what one really wants to
+do.  In the kernel, one must protect shared data structures against
+unwanted concurrent access, which is very much a different task.  The
+process of protecting against unwanted concurrency will also avoid almost
+all optimization-related problems in a more efficient way.
+
+Like volatile, the kernel primitives which make concurrent access to data
+safe (spinlocks, mutexes, memory barriers, etc.) are designed to prevent
+unwanted optimization.  If they are being used properly, there will be no
+need to use volatile as well.  If volatile is still necessary, there is
+almost certainly a bug in the code somewhere.  In properly-written kernel
+code, volatile can only serve to slow things down.
+
+Consider a typical block of kernel code:
+
+    spin_lock(&the_lock);
+    do_something_on(&shared_data);
+    do_something_else_with(&shared_data);
+    spin_unlock(&the_lock);
+
+If all the code follows the locking rules, the value of shared_data cannot
+change unexpectedly while the_lock is held.  Any other code which might
+want to play with that data will be waiting on the lock.  The spinlock
+primitives act as memory barriers - they are explicitly written to do so -
+meaning that data accesses will not be optimized across them.  So the
+compiler might think it knows what will be in shared_data, but the
+spin_lock() call, since it acts as a memory barrier, will force it to
+forget anything it knows.  There will be no optimization problems with
+accesses to that data.
+
+If shared_data were declared volatile, the locking would still be
+necessary.  But the compiler would also be prevented from optimizing access
+to shared_data _within_ the critical section, when we know that nobody else
+can be working with it.  While the lock is held, shared_data is not
+volatile.  When dealing with shared data, proper locking makes volatile
+unnecessary - and potentially harmful.
+
+The volatile storage class was originally meant for memory-mapped I/O
+registers.  Within the kernel, register accesses, too, should be protected
+by locks, but one also does not want the compiler "optimizing" register
+accesses within a critical section.  But, within the kernel, I/O memory
+accesses are always done through accessor functions; accessing I/O memory
+directly through pointers is frowned upon and does not work on all
+architectures.  Those accessors are written to prevent unwanted
+optimization, so, once again, volatile is unnecessary.
+
+Another situation where one might be tempted to use volatile is
+when the processor is busy-waiting on the value of a variable.  The right
+way to perform a busy wait is:
+
+    while (my_variable != what_i_want)
+        cpu_relax();
+
+The cpu_relax() call can lower CPU power consumption or yield to a
+hyperthreaded twin processor; it also happens to serve as a memory barrier,
+so, once again, volatile is unnecessary.  Of course, busy-waiting is
+generally an anti-social act to begin with.
+
+There are still a few rare situations where volatile makes sense in the
+kernel:
+
+  - The above-mentioned accessor functions might use volatile on
+    architectures where direct I/O memory access does work.  Essentially,
+    each accessor call becomes a little critical section on its own and
+    ensures that the access happens as expected by the programmer.
+
+  - Inline assembly code which changes memory, but which has no other
+    visible side effects, risks being deleted by GCC.  Adding the volatile
+    keyword to asm statements will prevent this removal.
+
+  - The jiffies variable is special in that it can have a different value
+    every time it is referenced, but it can be read without any special
+    locking.  So jiffies can be volatile, but the addition of other
+    variables of this type is strongly frowned upon.  Jiffies is considered
+    to be a "stupid legacy" issue (Linus's words) in this regard; fixing it
+    would be more trouble than it is worth.
+
+  - Pointers to data structures in coherent memory which might be modified
+    by I/O devices can, sometimes, legitimately be volatile.  A ring buffer
+    used by a network adapter, where that adapter changes pointers to
+    indicate which descriptors have been processed, is an example of this
+    type of situation.
+
+For most code, none of the above justifications for volatile apply.  As a
+result, the use of volatile is likely to be seen as a bug and will bring
+additional scrutiny to the code.  Developers who are tempted to use
+volatile should take a step back and think about what they are truly trying
+to accomplish.
+
+Patches to remove volatile variables are generally welcome - as long as
+they come with a justification which shows that the concurrency issues have
+been properly thought through.
+
+
+NOTES
+-----
+
+[1] http://lwn.net/Articles/233481/
+[2] http://lwn.net/Articles/233482/
+
+CREDITS
+-------
+
+Original impetus and research by Randy Dunlap
+Written by Jonathan Corbet
+Improvements via coments from Satyam Sharma, Johannes Stezenbach, Jesper
+	Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, and Stefan
+	Richter.
diff --git a/MAINTAINERS b/MAINTAINERS
index 4c3277c..368a718 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -30,8 +30,11 @@
 	job the maintainers (and especially Linus) do is to keep things
 	looking the same. Sometimes this means that the clever hack in
 	your driver to get around a problem actually needs to become a
-	generalized kernel feature ready for next time. See
-	Documentation/CodingStyle for guidance here.
+	generalized kernel feature ready for next time.
+
+	PLEASE check your patch with the automated style checker
+	(scripts/checkpatch.pl) to catch trival style violations.
+	See Documentation/CodingStyle for guidance here.
 
 	PLEASE try to include any credit lines you want added with the
 	patch. It avoids people being missed off by mistake and makes
@@ -191,13 +194,6 @@
 L:	linux-acenic@sunsite.dk
 S:	Maintained
 
-ACI MIXER DRIVER
-P:	Robert Siemer
-M:	Robert.Siemer@gmx.de
-L:	linux-sound@vger.kernel.org
-W:	http://www.stud.uni-karlsruhe.de/~uh1b/
-S:	Maintained
-
 IPS SCSI RAID DRIVER
 P:	Adaptec OEM Raid Solutions
 M:	aacraid@adaptec.com
@@ -269,21 +265,6 @@
 W:	http://acpi.sourceforge.net/
 S:	Supported
 
-AD1816 SOUND DRIVER
-P:	Thorsten Knabe
-M:	Thorsten Knabe <linux@thorsten-knabe.de>
-W:	http://linux.thorsten-knabe.de
-S:	Maintained
-
-AD1889 SOUND DRIVER
-P:	Kyle McMartin
-M:	kyle@parisc-linux.org
-P:	Thibaut Varene
-M:	T-Bone@parisc-linux.org
-W:	http://wiki.parisc-linux.org/AD1889
-L:	parisc-linux@lists.parisc-linux.org
-S:	Maintained
-
 ADM1025 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
@@ -312,10 +293,9 @@
 S:	Maintained
 
 AGPGART DRIVER
-P:	Dave Jones
-M:	davej@codemonkey.org.uk
-W:	http://www.codemonkey.org.uk/projects/agp/
-T:	git kernel.org:/pub/scm/linux/kernel/git/davej/agpgart.git
+P:	David Airlie
+M:	airlied@linux.ie
+T:	git kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
 S:	Maintained
 
 AHA152X SCSI DRIVER
@@ -332,6 +312,9 @@
 W:	http://www.linux-usb.org/SpeedTouch/
 S:	Maintained
 
+ALCHEMY AU1XX0 MMC DRIVER
+S:	Orphan
+
 ALI1563 I2C DRIVER
 P:	Rudolf Marek
 M:	r.marek@assembler.cz
@@ -365,7 +348,7 @@
 M:	tom@opengridcomputing.com
 P:	Steve Wise
 M:	swise@opengridcomputing.com
-L:	openib-general@openib.org
+L:	general@lists.openfabrics.org
 S:	Maintained
 
 AOA (Apple Onboard Audio) ALSA DRIVER
@@ -418,6 +401,12 @@
 M:	spyro@f2s.com
 S:	Maintained
 
+ARM PRIMECELL MMCI PL180/1 DRIVER
+P:	Russell King
+M:	rmk@arm.linux.org.uk
+L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S:	Maintained
+
 ARM/ADI ROADRUNNER MACHINE SUPPORT
 P:	Lennert Buytenhek
 M:	kernel@wantstofly.org
@@ -649,6 +638,9 @@
 W:	http://linux-atm.sourceforge.net
 S:	Maintained
 
+ATMEL AT91 MCI DRIVER
+S:	Orphan
+
 ATMEL MACB ETHERNET DRIVER
 P:	Haavard Skinnemoen
 M:	hskinnemoen@atmel.com
@@ -708,42 +700,52 @@
 S:	Maintained
 
 BLACKFIN ARCHITECTURE
-P:     Aubrey Li
-M:     aubrey.li@analog.com
-P:     Bernd Schmidt
-M:     bernd.schmidt@analog.com
-P:     Bryan Wu
-M:     bryan.wu@analog.com
-P:     Grace Pan
-M:     grace.pan@analog.com
-P:     Michael Hennerich
-M:     michael.hennerich@analog.com
-P:     Mike Frysinger
-M:     michael.frysinger@analog.com
-P:     Jane Lv
-M:     jane.lv@analog.com
-P:     Jerry Zeng
-M:     jerry.zeng@analog.com
-P:     Jie Zhang
-M:     jie.zhang@analog.com
-P:     Robin Getz
-M:     robin.getz@analog.com
-P:     Roy Huang
-M:     roy.huang@analog.com
-P:     Sonic Zhang
-M:     sonic.zhang@analog.com
-P:     Yi Li
-M:     yi.li@analog.com
-L:     uclinux-dist-devel@blackfin.uclinux.org
-W:     http://blackfin.uclinux.org
-S:     Supported
+P:	Aubrey Li
+M:	aubrey.li@analog.com
+P:	Bernd Schmidt
+M:	bernd.schmidt@analog.com
+P:	Bryan Wu
+M:	bryan.wu@analog.com
+P:	Grace Pan
+M:	grace.pan@analog.com
+P:	Marc Hoffman
+M:	marc.hoffman@analog.com
+P:	Michael Hennerich
+M:	michael.hennerich@analog.com
+P:	Mike Frysinger
+M:	michael.frysinger@analog.com
+P:	Jerry Zeng
+M:	jerry.zeng@analog.com
+P:	Jie Zhang
+M:	jie.zhang@analog.com
+P:	Robin Getz
+M:	robin.getz@analog.com
+P:	Roy Huang
+M:	roy.huang@analog.com
+P:	Sonic Zhang
+M:	sonic.zhang@analog.com
+P:	Vivi Li
+M:	vivi.li@analog.com
+P:	Yi Li
+M:	yi.li@analog.com
+L:	uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W:	http://blackfin.uclinux.org
+S:	Supported
+
+BLACKFIN RTC DRIVER
+P:	Mike Frysinger
+M:	michael.frysinger@analog.com
+M:	vapier.adi@gmail.com
+L:	uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W:	http://blackfin.uclinux.org
+S:	Supported
 
 BLACKFIN SERIAL DRIVER
-P:     Aubrey Li
-M:     aubrey.li@analog.com
-L:     uclinux-dist-devel@blackfin.uclinux.org
-W:     http://blackfin.uclinux.org
-S:     Supported
+P:	Aubrey Li
+M:	aubrey.li@analog.com
+L:	uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W:	http://blackfin.uclinux.org
+S:	Supported
 
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
 P:	Thomas Sailer
@@ -767,11 +769,6 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
-BERKSHIRE PRODUCTS PC WATCHDOG DRIVER
-P:	Kenji Hollis
-W:	http://ftp.bitgate.com/pcwd/
-S:	Maintained
-
 BFS FILE SYSTEM
 P:	Tigran A. Aivazian
 M:	tigran@aivazian.fsnet.co.uk
@@ -916,6 +913,12 @@
 L:	netdev@vger.kernel.org
 S:	Supported
 
+BSG (block layer generic sg v4 driver)
+P:	FUJITA Tomonori
+M:	fujita.tomonori@lab.ntt.co.jp
+L:	linux-scsi@vger.kernel.org
+S:	Supported
+
 BTTV VIDEO4LINUX DRIVER
 P:	Mauro Carvalho Chehab
 M:	mchehab@infradead.org
@@ -960,6 +963,15 @@
 L:	linux-wireless@vger.kernel.org
 S:	Maintained
 
+CHECKPATCH
+P:	Andy Whitcroft
+M:	apw@shadowen.org
+P:	Randy Dunlap
+M:	rdunlap@xenotime.net
+P:	Joel Schopp
+M:	jschopp@austin.ibm.com
+S:	Supported
+
 COMMON INTERNET FILE SYSTEM (CIFS)
 P:	Steve French
 M:	sfrench@samba.org
@@ -1248,6 +1260,12 @@
 L:	netdev@vger.kernel.org
 S:	Maintained
 
+DMA GENERIC MEMCPY SUBSYSTEM
+P:	Shannon Nelson
+M:	shannon.nelson@intel.com
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 DOCBOOK FOR DOCUMENTATION
 P:	Randy Dunlap
 M:	rdunlap@xenotime.net
@@ -1367,16 +1385,9 @@
 M:	hnguyen@de.ibm.com
 P:	Christoph Raisch
 M:	raisch@de.ibm.com
-L:	openib-general@openib.org
+L:	general@lists.openfabrics.org
 S:	Supported
 
-EMU10K1 SOUND DRIVER
-P:	James Courtier-Dutton
-M:	James@superbug.demon.co.uk
-L:	emu10k1-devel@lists.sourceforge.net
-W:	http://sourceforge.net/projects/emu10k1/
-S:	Maintained
-
 EMULEX LPFC FC SCSI DRIVER
 P:	James Smart
 M:	james.smart@emulex.com
@@ -1463,6 +1474,13 @@
 L:	linuxppc-embedded@ozlabs.org
 S:	Maintained
 
+FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
+P:	Li Yang
+M:	leoli@freescale.com
+L:	netdev@vger.kernel.org
+L:	linuxppc-embedded@ozlabs.org
+S:	Maintained
+
 FILE LOCKING (flock() and fcntl()/lockf())
 P:	Matthew Wilcox
 M:	matthew@wil.cx
@@ -1474,6 +1492,14 @@
 M:	viro@zeniv.linux.org.uk
 S:	Maintained
 
+FIREWIRE SUBSYSTEM
+P:	Kristian Hoegsberg, Stefan Richter
+M:	krh@redhat.com, stefanr@s5r6.in-berlin.de
+L:	linux1394-devel@lists.sourceforge.net
+W:	http://www.linux1394.org/
+T:	git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
+S:	Maintained
+
 FIRMWARE LOADER (request_firmware)
 L:	linux-kernel@vger.kernel.org
 S:	Orphan
@@ -1706,8 +1732,8 @@
 S:	Maintained
 
 i386 BOOT CODE
-P:	Riley H. Williams
-M:	Riley@Williams.Name
+P:	H. Peter Anvin
+M:	hpa@zytor.com
 L:	Linux-Kernel@vger.kernel.org
 S:	Maintained
 
@@ -1806,13 +1832,13 @@
 P:	Sean Hefty
 M:	mshefty@ichips.intel.com
 P:	Hal Rosenstock
-M:	halr@voltaire.com
-L:	openib-general@openib.org
+M:	hal.rosenstock@gmail.com 
+L:	general@lists.openfabrics.org
 W:	http://www.openib.org/
 T:	git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
 S:	Supported
 
-INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
+INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
 P:	Dmitry Torokhov
 M:	dmitry.torokhov@gmail.com
 M:	dtor@mail.ru
@@ -1857,6 +1883,12 @@
 M:	tigran@aivazian.fsnet.co.uk
 S:	Maintained
 
+INTEL I/OAT DMA DRIVER
+P:	Shannon Nelson
+M:	shannon.nelson@intel.com
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+
 INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
 P:	Deepak Saxena
 M:	dsaxena@plexity.net
@@ -1945,9 +1977,10 @@
 S:	Maintained
 
 IPATH DRIVER:
-P:	Bryan O'Sullivan
-M:	support@pathscale.com
-L:	openib-general@openib.org
+P:	Arthur Jones
+M:	infinipath@qlogic.com
+L:	general@lists.openfabrics.org
+T:	git git://git.qlogic.com/ipath-linux-2.6
 S:	Supported
 
 IPMI SUBSYSTEM
@@ -2057,7 +2090,7 @@
 
 KERNEL JANITORS
 P:	Several
-L:	kernel-janitors@lists.linux-foundation.org
+L:	kernel-janitors@vger.kernel.org
 W:	http://www.kerneljanitors.org/
 S:	Maintained
 
@@ -2231,11 +2264,11 @@
 L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
-LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks)
+LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
 P:	Richard Russon (FlatCap)
 M:	ldm@flatcap.org
-L:	ldm-devel@lists.sourceforge.net
-W:	http://ldm.sourceforge.net
+L:	linux-ntfs-dev@lists.sourceforge.net
+W:	http://www.linux-ntfs.org/content/view/19/37/
 S:	Maintained
 
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
@@ -2253,6 +2286,14 @@
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
+M32R ARCHITECTURE
+P:	Hirokazu Takata
+M:	takata@linux-m32r.org
+L:	linux-m32r@ml.linux-m32r.org
+L:	linux-m32r-ja@ml.linux-m32r.org (in Japanese)
+W:	http://www.linux-m32r.org/
+S:	Maintained
+
 M68K ARCHITECTURE
 P:	Geert Uytterhoeven
 M:	geert@linux-m68k.org
@@ -2286,6 +2327,12 @@
 T:	git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git
 S:	Maintained
 
+MACVLAN DRIVER
+P:	Patrick McHardy
+M:	kaber@trash.net
+L:	netdev@vger.kernel.org
+S:	Maintained
+
 MARVELL YUKON / SYSKONNECT DRIVER
 P:	Mirko Lindner
 M: 	mlindner@syskonnect.de
@@ -2322,7 +2369,7 @@
 
 MEGARAID SCSI DRIVERS
 P:	Neela Syam Kolli
-M:	Neela.Kolli@engenio.com
+M:	megaraidlinux@lsi.com
 S:	linux-scsi@vger.kernel.org
 W:	http://megaraid.lsilogic.com
 S:	Maintained
@@ -2380,6 +2427,13 @@
 W:	http://popies.net/meye/
 S:	Maintained
 
+MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
+P:	Pavel Pisa
+M:	ppisa@pikron.com
+L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:	http://mmc.drzeus.cx/wiki/Controllers/Freescale/SDHC
+S:	Maintained
+
 MOUSE AND MISC DEVICES [GENERAL]
 P:	Alessandro Rubini
 M:	rubini@ipvvis.unipv.it
@@ -2565,12 +2619,6 @@
 W:	http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
 S:	Maintained
 
-NON-IDE/NON-SCSI CDROM DRIVERS [GENERAL] (come on, crew - mark your responsibility)
-P:	Eberhard Moenkeberg
-M:	emoenke@gwdg.de
-L:	linux-kernel@vger.kernel.org
-S:	Maintained
-
 NTFS FILESYSTEM
 P:	Anton Altaparmakov
 M:	aia21@cantab.net
@@ -2653,12 +2701,6 @@
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
-OPL3-SA2, SA3, and SAx DRIVER
-P:	Zwane Mwaikambo
-M:	zwane@arm.linux.org.uk
-L:	linux-sound@vger.kernel.org
-S:	Maintained
-
 OPROFILE
 P:	Philippe Elie
 M:	phil.el@wanadoo.fr
@@ -2763,11 +2805,6 @@
 M:	kristen.c.accardi@intel.com
 S:	Supported
 
-PCI HOTPLUG COMPAQ DRIVER
-P:	Greg Kroah-Hartman
-M:	greg@kroah.com
-S:	Maintained
-
 PCIE HOTPLUG DRIVER
 P:	Kristen Carlson Accardi
 M:	kristen.c.accardi@intel.com
@@ -2817,6 +2854,16 @@
 L:	linux-kernel@vger.kernel.org
 S:	Supported
 
+POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
+P:	Anton Vorontsov
+M:	cbou@mail.ru
+P:	David Woodhouse
+M:	dwmw2@infradead.org
+L:	linux-kernel@vger.kernel.org
+L:	kernel-discuss@handhelds.org
+T:	git git.infradead.org/battery-2.6.git
+S:	Maintained
+
 POWERPC 4xx EMAC DRIVER
 P:	Eugene Surovegin
 M:	ebs@ebshome.net
@@ -2852,6 +2899,11 @@
 M:	mostrows@speakeasy.net
 S:	Maintained
 
+PPP OVER L2TP
+P:	James Chapman
+M:	jchapman@katalix.com
+S:	Maintained
+
 PREEMPTIBLE KERNEL
 P:	Robert Love
 M:	rml@tech9.net
@@ -2861,8 +2913,8 @@
 S:	Supported
 
 PRISM54 WIRELESS DRIVER
-P:	Prism54 Development Team
-M:	developers@islsm.org
+P:	Luis R. Rodriguez
+M:	mcgrof@gmail.com
 L:	linux-wireless@vger.kernel.org
 W:	http://prism54.org
 S:	Maintained
@@ -2879,6 +2931,13 @@
 L:	linux-ide@vger.kernel.org
 S:	Maintained
 
+PS3 NETWORK SUPPORT
+P:	Masakazu Mokuno
+M:	mokuno@sm.sony.co.jp
+L:	netdev@vger.kernel.org
+L:	cbe-oss-dev@ozlabs.org
+S:	Supported
+
 PS3 PLATFORM SUPPORT
 P:	Geoff Levand
 M:	geoffrey.levand@am.sony.com
@@ -2900,6 +2959,9 @@
 L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 S:	Maintained
 
+PXA MMCI DRIVER
+S:	Orphan
+
 QLOGIC QLA2XXX FC-SCSI DRIVER
 P:	Andrew Vasquez
 M:	linux-driver@qlogic.com
@@ -2976,7 +3038,7 @@
 REISERFS FILE SYSTEM
 P:	Hans Reiser
 M:	reiserfs-dev@namesys.com
-L:	reiserfs-list@namesys.com
+L:	reiserfs-devel@vger.kernel.org
 W:	http://www.namesys.com
 S:	Supported
 
@@ -2995,6 +3057,16 @@
 RISCOM8 DRIVER
 S:	Orphan
 
+RTL818X WIRELESS DRIVER
+P:	Michael Wu
+M:	flamingice@sourmilk.net
+P:	Andrea Merello
+M:	andreamrl@tiscali.it
+L:	linux-wireless@vger.kernel.org
+W:	http://linuxwireless.org/
+T:	git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
+S:	Maintained
+
 S3 SAVAGE FRAMEBUFFER DRIVER
 P:	Antonino Daplas
 M:	adaplas@gmail.com
@@ -3033,12 +3105,6 @@
 W:	http://www.mihu.de/linux/saa7146
 S:	Maintained
 
-SBPCD CDROM DRIVER
-P:	Eberhard Moenkeberg
-M:	emoenke@gwdg.de
-L:	linux-kernel@vger.kernel.org
-S:	Maintained
-
 SC1200 WDT DRIVER
 P:	Zwane Mwaikambo
 M:	zwane@arm.linux.org.uk
@@ -3416,6 +3482,13 @@
 M:      oakad@yahoo.com
 S:      Maintained
 
+TI OMAP MMC INTERFACE DRIVER
+P:	Carlos Aguiar, Anderson Briglia and Syed Khasim
+M:	linux-omap-open-source@linux.omap.com 
+W:	http://linux.omap.com
+W:	http://www.muru.com/linux/omap/
+S:	Maintained
+
 TI OMAP RANDOM NUMBER GENERATOR SUPPORT
 P:	Deepak Saxena
 M:	dsaxena@plexity.net
@@ -3496,7 +3569,7 @@
 
 TULIP NETWORK DRIVER
 P:	Valerie Henson
-M:	val_henson@linux.intel.com
+M:	val@nmt.edu
 L:	tulip-users@lists.sourceforge.net
 W:	http://sourceforge.net/projects/tulip/
 S:	Maintained
@@ -3557,7 +3630,7 @@
 USB DAVICOM DM9601 DRIVER
 P:	Peter Korsgaard
 M:	jacmet@sunsite.dk
-L:	linux-usb-devel@lists.sourceforge.net
+L:	netdev@vger.kernel.org
 W:	http://www.linux-usb.org/usbnet
 S:	Maintained
 
@@ -3641,23 +3714,23 @@
 USB PEGASUS DRIVER
 P:	Petko Manolov
 M:	petkan@users.sourceforge.net
-L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
+L:	netdev@vger.kernel.org
 W:	http://pegasus2.sourceforge.net/
 S:	Maintained
 
-USB PRINTER DRIVER
-P:	Vojtech Pavlik
-M:	vojtech@suse.cz
+USB PRINTER DRIVER (usblp)
+P:	Pete Zaitcev
+M:	zaitcev@redhat.com
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
-S:	Maintained
+S:	Supported
 
 USB RTL8150 DRIVER
 P:	Petko Manolov
 M:	petkan@users.sourceforge.net
-L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
+L:	netdev@vger.kernel.org
 W:	http://pegasus2.sourceforge.net/
 S:	Maintained
 
@@ -3768,7 +3841,7 @@
 USB "USBNET" DRIVER FRAMEWORK
 P:	David Brownell
 M:	dbrownell@users.sourceforge.net
-L:	linux-usb-devel@lists.sourceforge.net
+L:	netdev@vger.kernel.org
 W:	http://www.linux-usb.org/usbnet
 S:	Maintained
 
@@ -3848,10 +3921,6 @@
 
 UCLINUX FOR NEC V850
 P:	Miles Bader
-M:	uclinux-v850@lsi.nec.co.jp
-W:	http://www.ic.nec.co.jp/micro/uclinux/eng/
-W:	http://www.ee.nec.de/uclinux/
-S:	Supported
 
 UCLINUX FOR RENESAS H8/300
 P:	Yoshinori Sato
@@ -3860,10 +3929,10 @@
 S:	Supported
 
 UFS FILESYSTEM
-P: Evgeniy Dushistov
-M: dushistov@mail.ru
-L: linux-kernel@vger.kernel.org
-S: Maintained
+P:	Evgeniy Dushistov
+M:	dushistov@mail.ru
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
 
 USB DIAMOND RIO500 DRIVER
 P:	Cesar Miquel
@@ -3965,11 +4034,11 @@
 
 XFS FILESYSTEM
 P:	Silicon Graphics Inc
-P:	Tim Shimmin, David Chatterton
+P:	Tim Shimmin
 M:	xfs-masters@oss.sgi.com
 L:	xfs@oss.sgi.com
 W:	http://oss.sgi.com/projects/xfs
-T:	git git://oss.sgi.com:8090/xfs/xfs-2.6
+T:	git git://oss.sgi.com:8090/xfs/xfs-2.6.git
 S:	Supported
 
 XILINX UARTLITE SERIAL DRIVER
diff --git a/Makefile b/Makefile
index 34210af..ddbfcac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 22
-EXTRAVERSION = -rc2
-NAME = Nocturnal Monster Puppy
+EXTRAVERSION =
+NAME = Holy Dancing Manatees, Batman!
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -313,7 +313,8 @@
 CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
 CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-                   -fno-strict-aliasing -fno-common
+		   -fno-strict-aliasing -fno-common \
+		   -Werror-implicit-function-declaration
 AFLAGS          := -D__ASSEMBLY__
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 770f717..2a85dc3 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -83,22 +83,20 @@
 	  check out the Linux/Alpha FAQ, accessible on the WWW from
 	  <http://www.alphalinux.org/>. In summary:
 
-	  Alcor/Alpha-XLT     AS 600
+	  Alcor/Alpha-XLT     AS 600, AS 500, XL-300, XL-366
 	  Alpha-XL            XL-233, XL-266
 	  AlphaBook1          Alpha laptop
 	  Avanti              AS 200, AS 205, AS 250, AS 255, AS 300, AS 400
 	  Cabriolet           AlphaPC64, AlphaPCI64
-	  DP264               DP264
+	  DP264               DP264 / DS20 / ES40 / DS10 / DS10L
 	  EB164               EB164 21164 evaluation board
 	  EB64+               EB64+ 21064 evaluation board
 	  EB66                EB66 21066 evaluation board
 	  EB66+               EB66+ 21066 evaluation board
-	  Jensen              DECpc 150, DEC 2000 model 300,
-	  DEC 2000 model 500
+	  Jensen              DECpc 150, DEC 2000 models 300, 500
 	  LX164               AlphaPC164-LX
 	  Lynx                AS 2100A
-	  Miata               Personal Workstation 433a, 433au, 500a,
-	  500au, 600a, or 600au
+	  Miata               Personal Workstation 433/500/600 a/au
 	  Marvel              AlphaServer ES47 / ES80 / GS1280
 	  Mikasa              AS 1000
 	  Noname              AXPpci33, UDB (Multia)
@@ -108,9 +106,9 @@
 	  Ruffian             RPX164-2, AlphaPC164-UX, AlphaPC164-BX
 	  SX164               AlphaPC164-SX
 	  Sable               AS 2000, AS 2100
-	  Shark		      DS 20L
-	  Takara              Takara
-	  Titan               AlphaServer ES45 / DS25
+	  Shark               DS 20L
+	  Takara              Takara (OEM)
+	  Titan               AlphaServer ES45 / DS25 / DS15
 	  Wildfire            AlphaServer GS 40/80/160/320
 
 	  If you don't know what to do, choose "generic".
@@ -329,6 +327,9 @@
 	bool
 	default y
 
+config PCI_SYSCALL
+	def_bool PCI
+
 config ALPHA_CORE_AGP
 	bool
 	depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
@@ -481,6 +482,15 @@
 	depends on ALPHA_GENERIC || ALPHA_PC164
 	default y
 
+config VGA_HOSE
+	bool
+	depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL || ALPHA_TSUNAMI
+	default y
+	help
+	  Support VGA on an arbitrary hose; needed for several platforms
+	  which always have multiple hoses, and whose consoles support it.
+
+
 config ALPHA_SRM
 	bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME
 	default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
@@ -537,10 +547,14 @@
 	default y
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-64)"
-	range 2 64
+	int "Maximum number of CPUs (2-32)"
+	range 2 32
 	depends on SMP
-	default "64"
+	default "32" if ALPHA_GENERIC || ALPHA_MARVEL
+	default "4" if !ALPHA_GENERIC && !ALPHA_MARVEL
+	help
+	  MARVEL support can handle a maximum of 32 CPUs, all the others
+          with working support have a maximum of 4 CPUs.
 
 config ARCH_DISCONTIGMEM_ENABLE
 	bool "Discontiguous Memory Support (EXPERIMENTAL)"
@@ -644,6 +658,13 @@
 
 source "arch/alpha/Kconfig.debug"
 
+# DUMMY_CONSOLE may be defined in drivers/video/console/Kconfig
+# but we also need it if VGA_HOSE is set
+config DUMMY_CONSOLE
+	bool
+	depends on VGA_HOSE
+	default y
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff --git a/arch/alpha/boot/tools/mkbb.c b/arch/alpha/boot/tools/mkbb.c
index 23c7190..632a7fd 100644
--- a/arch/alpha/boot/tools/mkbb.c
+++ b/arch/alpha/boot/tools/mkbb.c
@@ -81,7 +81,7 @@
 #define	bootblock_label		__u1.__label
 #define bootblock_checksum	__u2.__checksum
 
-main(int argc, char ** argv)
+int main(int argc, char ** argv)
 {
     bootblock		bootblock_from_disk;
     bootblock		bootloader_image;
diff --git a/arch/alpha/kernel/console.c b/arch/alpha/kernel/console.c
index f313b34..da711e3 100644
--- a/arch/alpha/kernel/console.c
+++ b/arch/alpha/kernel/console.c
@@ -9,16 +9,20 @@
 #include <linux/init.h>
 #include <linux/tty.h>
 #include <linux/console.h>
+#include <linux/vt.h>
 #include <asm/vga.h>
 #include <asm/machvec.h>
 
+#include "pci_impl.h"
+
 #ifdef CONFIG_VGA_HOSE
 
-/*
- * Externally-visible vga hose bases
- */
-unsigned long __vga_hose_io_base = 0;	/* base for default hose */
-unsigned long __vga_hose_mem_base = 0;	/* base for default hose */
+struct pci_controller *pci_vga_hose;
+static struct resource alpha_vga = {
+	.name	= "alpha-vga+",
+	.start	= 0x3C0,
+	.end	= 0x3DF
+};
 
 static struct pci_controller * __init 
 default_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
@@ -30,36 +34,58 @@
 }
 
 void __init 
-set_vga_hose(struct pci_controller *hose)
-{
-	if (hose) {
-		__vga_hose_io_base = hose->io_space->start;
-		__vga_hose_mem_base = hose->mem_space->start;
-	}
-}
-
-void __init 
 locate_and_init_vga(void *(*sel_func)(void *, void *))
 {
 	struct pci_controller *hose = NULL;
 	struct pci_dev *dev = NULL;
 
+	/* Default the select function */
 	if (!sel_func) sel_func = (void *)default_vga_hose_select;
 
+	/* Find the console VGA device */
 	for(dev=NULL; (dev=pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, dev));) {
-		if (!hose) hose = dev->sysdata;
-		else hose = sel_func(hose, dev->sysdata);
+		if (!hose)
+			hose = dev->sysdata;
+		else
+			hose = sel_func(hose, dev->sysdata);
 	}
 
-	/* Did we already inititialize the correct one? */
-	if (conswitchp == &vga_con &&
-	    __vga_hose_io_base == hose->io_space->start &&
-	    __vga_hose_mem_base == hose->mem_space->start)
+	/* Did we already initialize the correct one? Is there one? */
+	if (!hose || (conswitchp == &vga_con && pci_vga_hose == hose))
 		return;
 
-	/* Set the VGA hose and init the new console */
-	set_vga_hose(hose);
+	/* Create a new VGA ioport resource WRT the hose it is on. */
+	alpha_vga.start += hose->io_space->start;
+	alpha_vga.end += hose->io_space->start;
+	request_resource(hose->io_space, &alpha_vga);
+
+	/* Set the VGA hose and init the new console. */
+	pci_vga_hose = hose;
 	take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1);
 }
 
+void __init
+find_console_vga_hose(void)
+{
+	u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
+
+	if (pu64[7] == 3) {	/* TERM_TYPE == graphics */
+		struct pci_controller *hose;
+		int h = (pu64[30] >> 24) & 0xff;	/* console hose # */
+
+		/*
+		 * Our hose numbering DOES match the console's, so find
+		 * the right one...
+		 */
+		for (hose = hose_head; hose; hose = hose->next) {
+			if (hose->index == h) break;
+		}
+
+		if (hose) {
+			printk("Console graphics on hose %d\n", h);
+			pci_vga_hose = hose;
+		}
+	}
+}
+
 #endif
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
index 7f6a984..f10d2ed 100644
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -25,6 +25,7 @@
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/rtc.h>
+#include <asm/vga.h>
 
 #include "proto.h"
 #include "pci_impl.h"
@@ -367,9 +368,8 @@
 }
 
 static void __init
-marvel_init_vga_hose(void)
+marvel_find_console_vga_hose(void)
 {
-#ifdef CONFIG_VGA_HOSE
 	u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
 
 	if (pu64[7] == 3) {	/* TERM_TYPE == graphics */
@@ -403,7 +403,6 @@
 			pci_vga_hose = hose;
 		}
 	}
-#endif /* CONFIG_VGA_HOSE */
 }
 
 gct6_search_struct gct_wanted_node_list[] = {
@@ -459,7 +458,7 @@
 		marvel_init_io7(io7);
 
 	/* Check for graphic console location (if any).  */
-	marvel_init_vga_hose();
+	marvel_find_console_vga_hose();
 }
 
 void
@@ -684,9 +683,6 @@
 /*
  * IO map support.
  */
-
-#define __marvel_is_mem_vga(a)	(((a) >= 0xa0000) && ((a) <= 0xc0000))
-
 void __iomem *
 marvel_ioremap(unsigned long addr, unsigned long size)
 {
@@ -698,13 +694,9 @@
 	unsigned long pfn;
 
 	/*
-	 * Adjust the addr.
+	 * Adjust the address.
 	 */ 
-#ifdef CONFIG_VGA_HOSE
-	if (pci_vga_hose && __marvel_is_mem_vga(addr)) {
-		addr += pci_vga_hose->mem_space->start;
-	}
-#endif
+	FIXUP_MEMADDR_VGA(addr);
 
 	/*
 	 * Find the hose.
@@ -781,7 +773,9 @@
 		return (void __iomem *) vaddr;
 	}
 
-	return NULL;
+	/* Assume it was already a reasonable address */
+	vaddr = baddr + hose->mem_space->start;
+	return (void __iomem *) vaddr;
 }
 
 void
@@ -803,21 +797,12 @@
 		return (addr & 0xFF000000UL) == 0;
 }
 
-#define __marvel_is_port_vga(a)	\
-  (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
 #define __marvel_is_port_kbd(a)	(((a) == 0x60) || ((a) == 0x64))
 #define __marvel_is_port_rtc(a)	(((a) == 0x70) || ((a) == 0x71))
 
 void __iomem *marvel_ioportmap (unsigned long addr)
 {
-	if (__marvel_is_port_rtc (addr) || __marvel_is_port_kbd(addr))
-		;
-#ifdef CONFIG_VGA_HOSE
-	else if (__marvel_is_port_vga (addr) && pci_vga_hose)
-		addr += pci_vga_hose->io_space->start;
-#endif
-	else
-		return NULL;
+	FIXUP_IOADDR_VGA(addr);
 	return (void __iomem *)addr;
 }
 
@@ -829,8 +814,14 @@
 		return 0;
 	else if (__marvel_is_port_rtc(addr))
 		return __marvel_rtc_io(0, addr, 0);
-	else
+	else if (marvel_is_ioaddr(addr))
 		return __kernel_ldbu(*(vucp)addr);
+	else
+		/* this should catch other legacy addresses
+		   that would normally fail on MARVEL,
+		   because there really is nothing there...
+		*/
+		return ~0;
 }
 
 void
@@ -841,7 +832,7 @@
 		return;
 	else if (__marvel_is_port_rtc(addr)) 
 		__marvel_rtc_io(b, addr, 1);
-	else
+	else if (marvel_is_ioaddr(addr))
 		__kernel_stb(b, *(vucp)addr);
 }
 
diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
index 3662fef..8193266 100644
--- a/arch/alpha/kernel/core_titan.c
+++ b/arch/alpha/kernel/core_titan.c
@@ -21,6 +21,7 @@
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
+#include <asm/vga.h>
 
 #include "proto.h"
 #include "pci_impl.h"
@@ -35,6 +36,11 @@
 } saved_config[4] __attribute__((common));
 
 /*
+ * Is PChip 1 present? No need to query it more than once.
+ */
+static int titan_pchip1_present;
+
+/*
  * BIOS32-style PCI interface:
  */
 
@@ -344,43 +350,17 @@
 static void __init
 titan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
 {
-	int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
+	titan_pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
 
 	/* Init the ports in hose order... */
 	titan_init_one_pachip_port(&pachip0->g_port, 0);	/* hose 0 */
-	if (pchip1_present)
+	if (titan_pchip1_present)
 		titan_init_one_pachip_port(&pachip1->g_port, 1);/* hose 1 */
 	titan_init_one_pachip_port(&pachip0->a_port, 2);	/* hose 2 */
-	if (pchip1_present)
+	if (titan_pchip1_present)
 		titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */
 }
 
-static void __init
-titan_init_vga_hose(void)
-{
-#ifdef CONFIG_VGA_HOSE
-	u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
-
-	if (pu64[7] == 3) {	/* TERM_TYPE == graphics */
-		struct pci_controller *hose;
-		int h = (pu64[30] >> 24) & 0xff;	/* console hose # */
-
-		/*
-		 * Our hose numbering matches the console's, so just find
-		 * the right one...
-		 */
-		for (hose = hose_head; hose; hose = hose->next) {
-			if (hose->index == h) break;
-		}
-
-		if (hose) {
-			printk("Console graphics on hose %d\n", hose->index);
-			pci_vga_hose = hose;
-		}
-	}
-#endif /* CONFIG_VGA_HOSE */
-}
-
 void __init
 titan_init_arch(void)
 {
@@ -406,6 +386,7 @@
 
 	/* With multiple PCI busses, we play with I/O as physical addrs.  */
 	ioport_resource.end = ~0UL;
+	iomem_resource.end = ~0UL;
 
 	/* PCI DMA Direct Mapping is 1GB at 2GB.  */
 	__direct_map_base = 0x80000000;
@@ -415,7 +396,7 @@
 	titan_init_pachips(TITAN_pachip0, TITAN_pachip1);
 
 	/* Check for graphic console location (if any).  */
-	titan_init_vga_hose();
+	find_console_vga_hose();
 }
 
 static void
@@ -441,9 +422,7 @@
 static void
 titan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
 {
-	int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
-
-	if (pchip1_present) {
+	if (titan_pchip1_present) {
 		titan_kill_one_pachip_port(&pachip1->g_port, 1);
 		titan_kill_one_pachip_port(&pachip1->a_port, 3);
 	}
@@ -463,6 +442,14 @@
  */
 
 void __iomem *
+titan_ioportmap(unsigned long addr)
+{
+	FIXUP_IOADDR_VGA(addr);
+	return (void __iomem *)(addr + TITAN_IO_BIAS);
+}
+
+
+void __iomem *
 titan_ioremap(unsigned long addr, unsigned long size)
 {
 	int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT;
@@ -475,14 +462,12 @@
 	unsigned long pfn;
 
 	/*
-	 * Adjust the addr.
+	 * Adjust the address and hose, if necessary.
 	 */ 
-#ifdef CONFIG_VGA_HOSE
-	if (pci_vga_hose && __titan_is_mem_vga(addr)) {
+	if (pci_vga_hose && __is_mem_vga(addr)) {
 		h = pci_vga_hose->index;
 		addr += pci_vga_hose->mem_space->start;
 	}
-#endif
 
 	/*
 	 * Find the hose.
@@ -521,8 +506,10 @@
 		 * Map it
 		 */
 		area = get_vm_area(size, VM_IOREMAP);
-		if (!area)
+		if (!area) {
+			printk("ioremap failed... no vm_area...\n");
 			return NULL;
+		}
 
 		ptes = hose->sg_pci->ptes;
 		for (vaddr = (unsigned long)area->addr; 
@@ -539,7 +526,7 @@
 			if (__alpha_remap_area_pages(vaddr,
 						     pfn << PAGE_SHIFT, 
 						     PAGE_SIZE, 0)) {
-				printk("FAILED to map...\n");
+				printk("FAILED to remap_area_pages...\n");
 				vfree(area->addr);
 				return NULL;
 			}
@@ -551,7 +538,8 @@
 		return (void __iomem *) vaddr;
 	}
 
-	return NULL;
+	/* Assume a legacy (read: VGA) address, and return appropriately. */
+	return (void __iomem *)(addr + TITAN_MEM_BIAS);
 }
 
 void
@@ -574,6 +562,7 @@
 }
 
 #ifndef CONFIG_ALPHA_GENERIC
+EXPORT_SYMBOL(titan_ioportmap);
 EXPORT_SYMBOL(titan_ioremap);
 EXPORT_SYMBOL(titan_iounmap);
 EXPORT_SYMBOL(titan_is_mmio);
@@ -750,6 +739,7 @@
 	if (titan_query_agp(port))
 		hosenum = 2;
 	if (hosenum < 0 && 
+	    titan_pchip1_present &&
 	    titan_query_agp(port = &TITAN_pachip1->a_port)) 
 		hosenum = 3;
 	
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index ce623c6..ef91e09 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -19,6 +19,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/smp.h>
+#include <asm/vga.h>
 
 #include "proto.h"
 #include "pci_impl.h"
@@ -349,6 +350,26 @@
 	tsunami_pci_tbi(hose, 0, -1);
 }
 
+
+void __iomem *
+tsunami_ioportmap(unsigned long addr)
+{
+	FIXUP_IOADDR_VGA(addr);
+	return (void __iomem *)(addr + TSUNAMI_IO_BIAS);
+}
+
+void __iomem *
+tsunami_ioremap(unsigned long addr, unsigned long size)
+{
+	FIXUP_MEMADDR_VGA(addr);
+	return (void __iomem *)(addr + TSUNAMI_MEM_BIAS);
+}
+
+#ifndef CONFIG_ALPHA_GENERIC
+EXPORT_SYMBOL(tsunami_ioportmap);
+EXPORT_SYMBOL(tsunami_ioremap);
+#endif
+
 void __init
 tsunami_init_arch(void)
 {
@@ -393,6 +414,9 @@
 	tsunami_init_one_pchip(TSUNAMI_pchip0, 0);
 	if (TSUNAMI_cchip->csc.csr & 1L<<14)
 		tsunami_init_one_pchip(TSUNAMI_pchip1, 1);
+
+	/* Check for graphic console location (if any).  */
+	find_console_vga_hose();
 }
 
 static void
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index c95e95e..debc8f0 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -391,11 +391,10 @@
 	bne	$2, $work_resched
 
 $work_notifysig:
-	mov	$sp, $17
+	mov	$sp, $16
 	br	$1, do_switch_stack
-	mov	$5, $21
-	mov	$sp, $18
-	mov	$31, $16
+	mov	$sp, $17
+	mov	$5, $18
 	jsr	$26, do_notify_resume
 	bsr	$1, undo_switch_stack
 	br	restore_all
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 6e7d1fe..6b07f89 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -7,6 +7,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/bootmem.h>
+#include <linux/log2.h>
 
 #include <asm/io.h>
 #include <asm/hwrpb.h>
@@ -53,7 +54,7 @@
 {
 	unsigned long mem = max_low_pfn << PAGE_SHIFT;
 	if (mem < max)
-		max = 1UL << ceil_log2(mem);
+		max = roundup_pow_of_two(mem);
 	return max;
 }
 
@@ -206,6 +207,10 @@
 		p[i] = 0;
 }
 
+/* True if the machine supports DAC addressing, and DEV can
+   make use of it given MASK.  */
+static int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
+
 /* Map a single buffer of the indicated size for PCI DMA in streaming
    mode.  The 32-bit PCI bus mastering address to use is returned.
    Once the device is given the dma address, the device owns this memory
@@ -896,7 +901,7 @@
 /* True if the machine supports DAC addressing, and DEV can
    make use of it given MASK.  */
 
-int
+static int
 pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
 {
 	dma64_addr_t dac_offset = alpha_mv.pci_dac_offset;
@@ -916,32 +921,6 @@
 
 	return ok;
 }
-EXPORT_SYMBOL(pci_dac_dma_supported);
-
-dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page,
-		    unsigned long offset, int direction)
-{
-	return (alpha_mv.pci_dac_offset
-		+ __pa(page_address(page)) 
-		+ (dma64_addr_t) offset);
-}
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	unsigned long paddr = (dma_addr & PAGE_MASK) - alpha_mv.pci_dac_offset;
-	return virt_to_page(__va(paddr));
-}
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	return (dma_addr & ~PAGE_MASK);
-}
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
 
 /* Helper for generic DMA-mapping functions. */
 
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 95912ec..708d5ca 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -108,6 +108,15 @@
 extern unsigned long wildfire_node_mem_start(int);
 extern unsigned long wildfire_node_mem_size(int);
 
+/* console.c */
+#ifdef CONFIG_VGA_HOSE
+extern void find_console_vga_hose(void);
+extern void locate_and_init_vga(void *(*)(void *, void *));
+#else
+static inline void find_console_vga_hose(void) { }
+static inline void locate_and_init_vga(void *(*sel_func)(void *, void *)) { }
+#endif
+
 /* setup.c */
 extern unsigned long srm_hae;
 extern int boot_cpuid;
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 0cd0605..83a7818 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -315,9 +315,7 @@
 	/* When I and D space are separate, this will have to be fixed.  */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		tmp = data;
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
-		ret = (copied == sizeof(tmp)) ? 0 : -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the specified register */
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 915f263..bd5e68c 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -43,6 +43,7 @@
 #include <linux/notifier.h>
 #include <asm/setup.h>
 #include <asm/io.h>
+#include <linux/log2.h>
 
 extern struct atomic_notifier_head panic_notifier_list;
 static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
@@ -1303,7 +1304,7 @@
 	long size = minsize, maxsize = MAX_BCACHE_SIZE * 2;
 
 	if (maxsize > (max_low_pfn + 1) << PAGE_SHIFT)
-		maxsize = 1 << (floor_log2(max_low_pfn + 1) + PAGE_SHIFT);
+		maxsize = 1 << (ilog2(max_low_pfn + 1) + PAGE_SHIFT);
 
 	/* Get the first block cached. */
 	read_mem_block(__va(0), stride, size);
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 7f64aa7..410af4f 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -32,8 +32,8 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 asmlinkage void ret_from_sys_call(void);
-static int do_signal(sigset_t *, struct pt_regs *, struct switch_stack *,
-		     unsigned long, unsigned long);
+static void do_signal(struct pt_regs *, struct switch_stack *,
+		      unsigned long, unsigned long);
 
 
 /*
@@ -146,11 +146,9 @@
 asmlinkage int
 do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
 {
-	sigset_t oldset;
-
 	mask &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	oldset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
@@ -160,19 +158,17 @@
 	regs->r0 = EINTR;
 	regs->r19 = 1;
 
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&oldset, regs, sw, 0, 0))
-			return -EINTR;
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 
 asmlinkage int
 do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
 		 struct pt_regs *regs, struct switch_stack *sw)
 {
-	sigset_t oldset, set;
+	sigset_t set;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
 	if (sigsetsize != sizeof(sigset_t))
@@ -182,7 +178,7 @@
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	spin_lock_irq(&current->sighand->siglock);
-	oldset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	current->blocked = set;
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
@@ -192,12 +188,10 @@
 	regs->r0 = EINTR;
 	regs->r19 = 1;
 
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&oldset, regs, sw, 0, 0))
-			return -EINTR;
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 
 asmlinkage int
@@ -436,7 +430,7 @@
 	return err;
 }
 
-static void
+static int
 setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 	    struct pt_regs *regs, struct switch_stack * sw)
 {
@@ -481,13 +475,14 @@
 		current->comm, current->pid, frame, regs->pc, regs->r26);
 #endif
 
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return -EFAULT;
 }
 
-static void
+static int
 setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	       sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
 {
@@ -543,34 +538,38 @@
 		current->comm, current->pid, frame, regs->pc, regs->r26);
 #endif
 
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return -EFAULT;
 }
 
 
 /*
  * OK, we're invoking a handler.
  */
-static inline void
+static inline int
 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
 	      sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
 {
+	int ret;
+
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame(sig, ka, info, oldset, regs, sw);
+		ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
 	else
-		setup_frame(sig, ka, oldset, regs, sw);
+		ret = setup_frame(sig, ka, oldset, regs, sw);
 
-	if (ka->sa.sa_flags & SA_RESETHAND)
-		ka->sa.sa_handler = SIG_DFL;
+	if (ret == 0) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		if (!(ka->sa.sa_flags & SA_NODEFER)) 
+			sigaddset(&current->blocked,sig);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
 
-	spin_lock_irq(&current->sighand->siglock);
-	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-	if (!(ka->sa.sa_flags & SA_NODEFER)) 
-		sigaddset(&current->blocked,sig);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	return ret;
 }
 
 static inline void
@@ -611,30 +610,42 @@
  * restart. "r0" is also used as an indicator whether we can restart at
  * all (if we get here from anything but a syscall return, it will be 0)
  */
-static int
-do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
+static void
+do_signal(struct pt_regs * regs, struct switch_stack * sw,
 	  unsigned long r0, unsigned long r19)
 {
 	siginfo_t info;
 	int signr;
 	unsigned long single_stepping = ptrace_cancel_bpt(current);
 	struct k_sigaction ka;
+	sigset_t *oldset;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	/* This lets the debugger run, ... */
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
 	/* ... so re-check the single stepping. */
 	single_stepping |= ptrace_cancel_bpt(current);
 
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		if (r0) syscall_restart(r0, r19, regs, &ka);
-		handle_signal(signr, &ka, &info, oldset, regs, sw);
+		if (r0)
+			syscall_restart(r0, r19, regs, &ka);
+		if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
+			/* A signal was successfully delivered, and the
+			   saved sigmask was stored on the signal frame,
+			   and will be restored by sigreturn.  So we can
+			   simply clear the restore sigmask flag.  */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
 		if (single_stepping) 
 			ptrace_set_bpt(current); /* re-set bpt */
-		return 1;
+		return;
 	}
 
 	if (r0) {
@@ -654,17 +665,22 @@
 			break;
 		}
 	}
+
+	/* If there's no signal to deliver, we just restore the saved mask.  */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
+
 	if (single_stepping)
 		ptrace_set_bpt(current);	/* re-set breakpoint */
-
-	return 0;
 }
 
 void
-do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
-		 struct switch_stack *sw, unsigned long r0,
-		 unsigned long r19, unsigned long thread_info_flags)
+do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
+		 unsigned long thread_info_flags,
+		 unsigned long r0, unsigned long r19)
 {
-	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(oldset, regs, sw, r0, r19);
+	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+		do_signal(regs, sw, r0, r19);
 }
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 80cfb75..b287314 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -65,7 +65,7 @@
 };
 
 /* Set to a secondary's cpuid when it comes online.  */
-static int smp_secondary_alive __initdata = 0;
+static int smp_secondary_alive __devinitdata = 0;
 
 /* Which cpus ids came online.  */
 cpumask_t cpu_online_map;
@@ -173,7 +173,7 @@
 }
 
 /* Wait until hwrpb->txrdy is clear for cpu.  Return -1 on timeout.  */
-static int __init
+static int __devinit
 wait_for_txrdy (unsigned long cpumask)
 {
 	unsigned long timeout;
@@ -358,7 +358,7 @@
 /*
  * Bring one cpu online.
  */
-static int __init
+static int __devinit
 smp_boot_one_cpu(int cpuid)
 {
 	struct task_struct *idle;
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index 930cedc..783f4e5 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -289,7 +289,7 @@
 	return srmcons_driver;
 }
 
-static int __init
+static int
 srm_console_setup(struct console *co, char *options)
 {
 	return 0;
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 85d2f93..c71b0fd 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -543,6 +543,7 @@
 {
 	common_init_pci();
 	SMC669_Init(0);
+	locate_and_init_vga(NULL);
 }
 
 static void __init
@@ -551,6 +552,14 @@
 	common_init_pci();
 	SMC669_Init(1);
 	es1888_init();
+	locate_and_init_vga(NULL);
+}
+
+static void __init
+clipper_init_pci(void)
+{
+	common_init_pci();
+	locate_and_init_vga(NULL);
 }
 
 static void __init
@@ -655,7 +664,7 @@
 	.init_arch		= tsunami_init_arch,
 	.init_irq		= clipper_init_irq,
 	.init_rtc		= common_init_rtc,
-	.init_pci		= common_init_pci,
+	.init_pci		= clipper_init_pci,
 	.kill_arch		= tsunami_kill_arch,
 	.pci_map_irq		= clipper_map_irq,
 	.pci_swizzle		= common_swizzle,
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index e349f03..922143e 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -22,6 +22,7 @@
 #include <asm/core_marvel.h>
 #include <asm/hwrpb.h>
 #include <asm/tlbflush.h>
+#include <asm/vga.h>
 
 #include "proto.h"
 #include "err_impl.h"
@@ -412,17 +413,14 @@
 
 	pci_probe_only = 1;
 	common_init_pci();
-
-#ifdef CONFIG_VGA_HOSE
 	locate_and_init_vga(NULL);
-#endif
 
 	/* Clear any io7 errors.  */
 	for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) 
 		io7_clear_errors(io7);
 }
 
-static void
+static void __init
 marvel_init_rtc(void)
 {
 	init_rtc_irq();
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
index f009b7b..1d3c139 100644
--- a/arch/alpha/kernel/sys_titan.c
+++ b/arch/alpha/kernel/sys_titan.c
@@ -331,9 +331,7 @@
 	pci_probe_only = 1;
 	common_init_pci();
 	SMC669_Init(0);
-#ifdef CONFIG_VGA_HOSE
 	locate_and_init_vga(NULL);
-#endif
 }
 
 
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index f6cfe8c..79de99e3 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -465,6 +465,38 @@
 	.quad sys_inotify_init
 	.quad sys_inotify_add_watch		/* 445 */
 	.quad sys_inotify_rm_watch
+	.quad sys_fdatasync
+	.quad sys_kexec_load
+	.quad sys_migrate_pages
+	.quad sys_openat			/* 450 */
+	.quad sys_mkdirat
+	.quad sys_mknodat
+	.quad sys_fchownat
+	.quad sys_futimesat
+	.quad sys_fstatat64			/* 455 */
+	.quad sys_unlinkat
+	.quad sys_renameat
+	.quad sys_linkat
+	.quad sys_symlinkat
+	.quad sys_readlinkat			/* 460 */
+	.quad sys_fchmodat
+	.quad sys_faccessat
+	.quad sys_pselect6
+	.quad sys_ppoll
+	.quad sys_unshare			/* 465 */
+	.quad sys_set_robust_list
+	.quad sys_get_robust_list
+	.quad sys_splice
+	.quad sys_sync_file_range
+	.quad sys_tee				/* 470 */
+	.quad sys_vmsplice
+	.quad sys_move_pages
+	.quad sys_getcpu
+	.quad sys_epoll_pwait
+	.quad sys_utimensat			/* 475 */
+	.quad sys_signalfd
+	.quad sys_timerfd
+	.quad sys_eventfd
 
 	.size sys_call_table, . - sys_call_table
 	.type sys_call_table, @object
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 4748e14..1dd50d0 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -144,7 +144,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+void __init
 common_init_rtc(void)
 {
 	unsigned char x;
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index d6e665d..ec0f05e 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -184,6 +184,7 @@
 #endif
 	printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
 	dik_show_regs(regs, r9_15);
+	add_taint(TAINT_DIE);
 	dik_show_trace((unsigned long *)(regs+1));
 	dik_show_code((unsigned int *)regs->pc);
 
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index cf1e6fc..449e76f 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -15,7 +15,7 @@
 
   _text = .;					/* Text and read-only data */
   .text : { 
-	*(.text) 
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	*(.fixup)
@@ -89,7 +89,7 @@
 
   _data = .;
   .data : {					/* Data */
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
   }
 
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index ea098f3..266f78e 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -37,7 +37,8 @@
 	$(ev6-y)clear_page.o \
 	$(ev6-y)copy_page.o \
 	fpreg.o \
-	callback_srm.o srm_puts.o srm_printk.o
+	callback_srm.o srm_puts.o srm_printk.o \
+	fls.o
 
 lib-$(CONFIG_SMP) += dec_and_lock.o
 
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
index ab3761c..8698e07 100644
--- a/arch/alpha/lib/checksum.c
+++ b/arch/alpha/lib/checksum.c
@@ -69,6 +69,7 @@
 	result = (result & 0xffffffff) + (result >> 32);
 	return (__force __wsum)result;
 }
+EXPORT_SYMBOL(csum_tcpudp_nofold);
 
 /*
  * Do a 64-bit checksum on an arbitrary memory area..
diff --git a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S
index e09748d..2c2acb9 100644
--- a/arch/alpha/lib/csum_ipv6_magic.S
+++ b/arch/alpha/lib/csum_ipv6_magic.S
@@ -7,6 +7,9 @@
  *                                __u32 len,
  *                                unsigned short proto,
  *                                unsigned int csum);
+ *
+ * Misalignment handling (which costs 16 instructions / 8 cycles)
+ * added by Ivan Kokshaysky <ink@jurassic.park.msu.ru>
  */
 
 	.globl csum_ipv6_magic
@@ -16,37 +19,57 @@
 csum_ipv6_magic:
 	.prologue 0
 
-	ldq	$0,0($16)	# e0    : load src & dst addr words
+	ldq_u	$0,0($16)	# e0    : load src & dst addr words
 	zapnot	$20,15,$20	# .. e1 : zero extend incoming csum
 	extqh	$18,1,$4	# e0    : byte swap len & proto while we wait
-	ldq	$1,8($16)	# .. e1 :
+	ldq_u	$21,7($16)	# .. e1 : handle misalignment
 
 	extbl	$18,1,$5	# e0	:
-	ldq	$2,0($17)	# .. e1 :
+	ldq_u	$1,8($16)	# .. e1 :
 	extbl	$18,2,$6	# e0 	:
-	ldq	$3,8($17)	# .. e1 :
+	ldq_u	$22,15($16)	# .. e1 :
 
 	extbl	$18,3,$18	# e0	:
+	ldq_u	$2,0($17)	# .. e1 :
 	sra	$4,32,$4	# e0	:
+	ldq_u	$23,7($17)	# .. e1 :
+
+	extql	$0,$16,$0	# e0	:
+	ldq_u	$3,8($17)	# .. e1 :
+	extqh	$21,$16,$21	# e0	:
+	ldq_u	$24,15($17)	# .. e1 :
+
 	sll	$5,16,$5	# e0	:
+	or	$0,$21,$0	# .. e1 : 1st src word complete
+	extql	$1,$16,$1	# e0	:
 	addq	$20,$0,$20	# .. e1 : begin summing the words
 
-	sll	$6,8,$6		# e0	:
+	extqh	$22,$16,$22	# e0	:
 	cmpult	$20,$0,$0	# .. e1 :
-	extwh	$19,7,$7	# e0    :
+	sll	$6,8,$6		# e0	:
+	or	$1,$22,$1	# .. e1 : 2nd src word complete
+
+	extql	$2,$17,$2	# e0	:
 	or	$4,$18,$18	# .. e1 :
-
-	extbl	$19,1,$19	# e0    :
+	extqh	$23,$17,$23	# e0	:
 	or	$5,$6,$5	# .. e1 :
-	or	$18,$5,$18	# e0    : len complete
-	or	$19,$7,$19	# .. e1 :
 
-	sll	$19,48,$19	# e0    :
+	extql	$3,$17,$3	# e0	:
+	or	$2,$23,$2	# .. e1 : 1st dst word complete
+	extqh	$24,$17,$24	# e0	:
+	or	$18,$5,$18	# .. e1 : len complete
+
+	extwh	$19,7,$7	# e0    :
+	or	$3,$24,$3	# .. e1 : 2nd dst word complete
+	extbl	$19,1,$19	# e0    :
 	addq	$20,$1,$20	# .. e1 :
-	sra	$19,32,$19	# e0    : proto complete
-	cmpult	$20,$1,$1	# .. e1 :
 
-	nop			# e0    :
+	or	$19,$7,$19	# e0    :
+	cmpult	$20,$1,$1	# .. e1 :
+	sll	$19,48,$19	# e0    :
+	nop			# .. e0 :
+
+	sra	$19,32,$19	# e0    : proto complete
 	addq	$20,$2,$20	# .. e1 :
 	cmpult	$20,$2,$2	# e0    :
 	addq	$20,$3,$20	# .. e1 :
@@ -84,7 +107,7 @@
 	extwl	$0,2,$1		# e0    : fold 17-bit value
 	zapnot	$0,3,$0		# .. e1 :
 	addq	$0,$1,$0	# e0    :
-	not	$0,$0		# e1    : and complement.
+	not	$0,$0		# .. e1 : and complement.
 
 	zapnot	$0,3,$0		# e0    :
 	ret			# .. e1 :
diff --git a/arch/alpha/lib/ev6-csum_ipv6_magic.S b/arch/alpha/lib/ev6-csum_ipv6_magic.S
index de1948a..fc0bc39 100644
--- a/arch/alpha/lib/ev6-csum_ipv6_magic.S
+++ b/arch/alpha/lib/ev6-csum_ipv6_magic.S
@@ -46,6 +46,10 @@
  * add the 3 low ushorts together, generating a uint
  * a final add of the 2 lower ushorts
  * truncating the result.
+ *
+ * Misalignment handling added by Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+ * The cost is 16 instructions (~8 cycles), including two extra loads which
+ * may cause additional delay in rare cases (load-load replay traps).
  */
 
 	.globl csum_ipv6_magic
@@ -55,25 +59,45 @@
 csum_ipv6_magic:
 	.prologue 0
 
-	ldq	$0,0($16)	# L : Latency: 3
+	ldq_u	$0,0($16)	# L : Latency: 3
 	inslh	$18,7,$4	# U : 0000000000AABBCC
-	ldq	$1,8($16)	# L : Latency: 3
+	ldq_u	$1,8($16)	# L : Latency: 3
 	sll	$19,8,$7	# U : U L U L : 0x00000000 00aabb00
 
+	and	$16,7,$6	# E : src misalignment
+	ldq_u	$5,15($16)	# L : Latency: 3
 	zapnot	$20,15,$20	# U : zero extend incoming csum
-	ldq	$2,0($17)	# L : Latency: 3
-	sll	$19,24,$19	# U : U L L U : 0x000000aa bb000000
+	ldq_u	$2,0($17)	# L : U L U L : Latency: 3
+
+	extql	$0,$6,$0	# U :
+	extqh	$1,$6,$22	# U :
+	ldq_u	$3,8($17)	# L : Latency: 3
+	sll	$19,24,$19	# U : U U L U : 0x000000aa bb000000
+
+	cmoveq	$6,$31,$22	# E : src aligned?
+	ldq_u	$23,15($17)	# L : Latency: 3
 	inswl	$18,3,$18	# U : 000000CCDD000000
+	addl	$19,$7,$19	# E : U L U L : <sign bits>bbaabb00
 
-	ldq	$3,8($17)	# L : Latency: 3
-	bis	$18,$4,$18	# E : 000000CCDDAABBCC
-	addl	$19,$7,$19	# E : <sign bits>bbaabb00
-	nop			# E : U L U L
+	or	$0,$22,$0	# E : 1st src word complete
+	extql	$1,$6,$1	# U :
+	or	$18,$4,$18	# E : 000000CCDDAABBCC
+	extqh	$5,$6,$5	# U : L U L U
 
+	and	$17,7,$6	# E : dst misalignment
+	extql	$2,$6,$2	# U :
+	or	$1,$5,$1	# E : 2nd src word complete
+	extqh	$3,$6,$22	# U : L U L U :
+
+	cmoveq	$6,$31,$22	# E : dst aligned?
+	extql	$3,$6,$3	# U :
 	addq	$20,$0,$20	# E : begin summing the words
+	extqh	$23,$6,$23	# U : L U L U :
+
 	srl	$18,16,$4	# U : 0000000000CCDDAA
+	or	$2,$22,$2	# E : 1st dst word complete
 	zap	$19,0x3,$19	# U : <sign bits>bbaa0000
-	nop			# E : L U U L
+	or	$3,$23,$3	# E : U L U L : 2nd dst word complete
 
 	cmpult	$20,$0,$0	# E :
 	addq	$20,$1,$20	# E :
diff --git a/arch/alpha/lib/fls.c b/arch/alpha/lib/fls.c
new file mode 100644
index 0000000..7ad84ea
--- /dev/null
+++ b/arch/alpha/lib/fls.c
@@ -0,0 +1,38 @@
+/* 
+ * arch/alpha/lib/fls.c
+ */
+
+#include <linux/module.h>
+#include <asm/bitops.h>
+
+/* This is fls(x)-1, except zero is held to zero.  This allows most
+   efficent input into extbl, plus it allows easy handling of fls(0)=0.  */
+
+const unsigned char __flsm1_tab[256] = 
+{
+  0,
+  0,
+  1, 1,
+  2, 2, 2, 2,
+  3, 3, 3, 3, 3, 3, 3, 3,
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+
+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+
+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+};
+
+EXPORT_SYMBOL(__flsm1_tab);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e55bbd3..a44c6da 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -241,6 +241,9 @@
 
 config ARCH_IMX
 	bool "IMX"
+	select GENERIC_GPIO
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
 	help
 	  Support for Motorola's i.MX family of processors (MX1, MXL).
 
@@ -287,6 +290,7 @@
 config ARCH_IXP4XX
 	bool "IXP4xx-based"
 	depends on MMU
+	select GENERIC_GPIO
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	help
@@ -307,6 +311,7 @@
 
 config ARCH_KS8695
 	bool "Micrel/Kendin KS8695"
+	select GENERIC_GPIO
 	help
 	  Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
 	  System-on-Chip devices.
@@ -383,6 +388,7 @@
 	bool "TI DaVinci"
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
 	help
 	  Support for TI's DaVinci platform.
 
@@ -530,6 +536,9 @@
 	  information about which PCI hardware does work under Linux and which
 	  doesn't.
 
+config PCI_SYSCALL
+	def_bool PCI
+
 # Select the host bridge type
 config PCI_HOST_VIA82C505
 	bool
@@ -1033,6 +1042,8 @@
 
 source "drivers/rtc/Kconfig"
 
+source "drivers/dma/Kconfig"
+
 endmenu
 
 source "fs/Kconfig"
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
index 171a085..ce1c5ff 100644
--- a/arch/arm/boot/.gitignore
+++ b/arch/arm/boot/.gitignore
@@ -1,2 +1,5 @@
 Image
 zImage
+xipImage
+bootpImage
+uImage
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index aefee20..b15f927 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -1 +1,2 @@
 piggy.gz
+font.c
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index adddc71..a1f1691 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -6,15 +6,13 @@
 
 HEAD	= head.o
 OBJS	= misc.o
-FONTC	= drivers/video/console/font_acorn_8x8.c
-
-FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o)
+FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 #
 # Architecture dependencies
 #
 ifeq ($(CONFIG_ARCH_ACORN),y)
-OBJS		+= ll_char_wr.o $(FONT)
+OBJS		+= ll_char_wr.o font.o
 endif
 
 ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -73,7 +71,7 @@
 
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-targets       := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \
+targets       := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
 		 head.o misc.o $(OBJS)
 EXTRA_CFLAGS  := -fpic
 EXTRA_AFLAGS  :=
@@ -105,7 +103,10 @@
 
 $(obj)/piggy.o:  $(obj)/piggy.gz FORCE
 
-CFLAGS_font_acorn_8x8.o := -Dstatic=
+CFLAGS_font.o := -Dstatic=
+
+$(obj)/font.c: $(FONTC)
+	$(call cmd,shipped)
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
 	@sed "$(SEDFLAGS)" < $< > $@
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
index 73c5d9e..236bbe5 100644
--- a/arch/arm/boot/compressed/head-xscale.S
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -41,11 +41,6 @@
 		mov	r7, #MACH_TYPE_COTULLA_IDP
 #endif
 
-#ifdef  CONFIG_MACH_GTWX5715
-               mov     r7, #(MACH_TYPE_GTWX5715 & 0xff)
-               orr     r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
-#endif
-
 #ifdef CONFIG_ARCH_IXP2000
 		mov	r1, #-1
 		mov	r0, #0xd6000000
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 2568d31..d7fb5ee1 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -247,7 +247,7 @@
 		mov	r3, r7
 		bl	decompress_kernel
 
-		add	r0, r0, #127
+		add	r0, r0, #127 + 128	@ alignment + stack
 		bic	r0, r0, #127		@ align the kernel length
 /*
  * r0     = decompressed kernel length
@@ -269,6 +269,7 @@
 		stmia	r1!, {r9 - r14}
 		cmp	r2, r3
 		blo	1b
+		add	sp, r1, #128		@ relocate the stack
 
 		bl	cache_clean_flush
 		add	pc, r5, r0		@ call relocation code
@@ -435,6 +436,28 @@
 		mcr	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
 		mov	pc, r12
 
+__armv7_mmu_cache_on:
+		mov	r12, lr
+		mrc	p15, 0, r11, c0, c1, 4	@ read ID_MMFR0
+		tst	r11, #0xf		@ VMSA
+		blne	__setup_mmu
+		mov	r0, #0
+		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
+		tst	r11, #0xf		@ VMSA
+		mcrne	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
+		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
+		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
+		orr	r0, r0, #0x003c		@ write buffer
+		orrne	r0, r0, #1		@ MMU enabled
+		movne	r1, #-1
+		mcrne	p15, 0, r3, c2, c0, 0	@ load page table pointer
+		mcrne	p15, 0, r1, c3, c0, 0	@ load domain access control
+		mcr	p15, 0, r0, c1, c0, 0	@ load control register
+		mrc	p15, 0, r0, c1, c0, 0	@ and read it back
+		mov	r0, #0
+		mcr	p15, 0, r0, c7, c5, 4	@ ISB
+		mov	pc, r12
+
 __arm6_mmu_cache_on:
 		mov	r12, lr
 		bl	__setup_mmu
@@ -476,6 +499,7 @@
  */
 		.align	5
 reloc_start:	add	r9, r5, r0
+		sub	r9, r9, #128		@ do not copy the stack
 		debug_reloc_start
 		mov	r1, r4
 1:
@@ -486,6 +510,7 @@
 
 		cmp	r5, r9
 		blo	1b
+		add	sp, r1, #128		@ relocate the stack
 		debug_reloc_end
 
 call_kernel:	bl	cache_clean_flush
@@ -619,11 +644,17 @@
 		b	__armv4_mmu_cache_flush
 
 		.word	0x0007b000		@ ARMv6
-		.word	0x0007f000
+		.word	0x000ff000
 		b	__armv4_mmu_cache_on
 		b	__armv4_mmu_cache_off
 		b	__armv6_mmu_cache_flush
 
+		.word	0x000f0000		@ new CPU Id
+		.word	0x000f0000
+		b	__armv7_mmu_cache_on
+		b	__armv7_mmu_cache_off
+		b	__armv7_mmu_cache_flush
+
 		.word	0			@ unrecognised type
 		.word	0
 		mov	pc, lr
@@ -671,6 +702,16 @@
 		mcr	p15, 0, r0, c8, c7	@ invalidate whole TLB v4
 		mov	pc, lr
 
+__armv7_mmu_cache_off:
+		mrc	p15, 0, r0, c1, c0
+		bic	r0, r0, #0x000d
+		mcr	p15, 0, r0, c1, c0	@ turn MMU and cache off
+		mov	r12, lr
+		bl	__armv7_mmu_cache_flush
+		mov	r0, #0
+		mcr	p15, 0, r0, c8, c7, 0	@ invalidate whole TLB
+		mov	pc, r12
+
 __arm6_mmu_cache_off:
 		mov	r0, #0x00000030		@ ARM6 control reg.
 		b	__armv3_mmu_cache_off
@@ -727,6 +768,59 @@
 		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
 		mov	pc, lr
 
+__armv7_mmu_cache_flush:
+		mrc	p15, 0, r10, c0, c1, 5	@ read ID_MMFR1
+		tst	r10, #0xf << 16		@ hierarchical cache (ARMv7)
+		beq	hierarchical
+		mov	r10, #0
+		mcr	p15, 0, r10, c7, c14, 0	@ clean+invalidate D
+		b	iflush
+hierarchical:
+		stmfd	sp!, {r0-r5, r7, r9-r11}
+		mrc	p15, 1, r0, c0, c0, 1	@ read clidr
+		ands	r3, r0, #0x7000000	@ extract loc from clidr
+		mov	r3, r3, lsr #23		@ left align loc bit field
+		beq	finished		@ if loc is 0, then no need to clean
+		mov	r10, #0			@ start clean at cache level 0
+loop1:
+		add	r2, r10, r10, lsr #1	@ work out 3x current cache level
+		mov	r1, r0, lsr r2		@ extract cache type bits from clidr
+		and	r1, r1, #7		@ mask of the bits for current cache only
+		cmp	r1, #2			@ see what cache we have at this level
+		blt	skip			@ skip if no cache, or just i-cache
+		mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
+		mcr	p15, 0, r10, c7, c5, 4	@ isb to sych the new cssr&csidr
+		mrc	p15, 1, r1, c0, c0, 0	@ read the new csidr
+		and	r2, r1, #7		@ extract the length of the cache lines
+		add	r2, r2, #4		@ add 4 (line length offset)
+		ldr	r4, =0x3ff
+		ands	r4, r4, r1, lsr #3	@ find maximum number on the way size
+		.word	0xe16f5f14		@ clz r5, r4 - find bit position of way size increment
+		ldr	r7, =0x7fff
+		ands	r7, r7, r1, lsr #13	@ extract max number of the index size
+loop2:
+		mov	r9, r4			@ create working copy of max way size
+loop3:
+		orr	r11, r10, r9, lsl r5	@ factor way and cache number into r11
+		orr	r11, r11, r7, lsl r2	@ factor index number into r11
+		mcr	p15, 0, r11, c7, c14, 2	@ clean & invalidate by set/way
+		subs	r9, r9, #1		@ decrement the way
+		bge	loop3
+		subs	r7, r7, #1		@ decrement the index
+		bge	loop2
+skip:
+		add	r10, r10, #2		@ increment cache number
+		cmp	r3, r10
+		bgt	loop1
+finished:
+		mov	r10, #0			@ swith back to cache level 0
+		mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
+		ldmfd	sp!, {r0-r5, r7, r9-r11}
+iflush:
+		mcr	p15, 0, r10, c7, c5, 0	@ invalidate I+BTB
+		mcr	p15, 0, r10, c7, c10, 4	@ drain WB
+		mov	pc, lr
+
 __armv4_mmu_cache_flush:
 		mov	r2, #64*1024		@ default: 32K dcache size (*2)
 		mov	r11, #32		@ default: 32 byte line size
@@ -833,6 +927,7 @@
 		mov	pc, r10
 #endif
 
+		.ltorg
 reloc_end:
 
 		.align
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 6fbe772..b36b1e8 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -6,7 +6,7 @@
  *  copy data to/from buffers located outside the DMA region. This
  *  only works for systems in which DMA memory is at the bottom of
  *  RAM, the remainder of memory is at the top and the DMA memory
- *  can be marked as ZONE_DMA. Anything beyond that such as discontigous
+ *  can be marked as ZONE_DMA. Anything beyond that such as discontiguous
  *  DMA windows will require custom implementations that reserve memory
  *  areas at early bootup.
  *
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 4deece5..0c89bd3 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -72,7 +72,7 @@
  * unmask it, in the same way we need to unmask an interrupt when
  * we first enable it.
  *
- * The GIC has a seperate notion of "end of interrupt" to re-enable
+ * The GIC has a separate notion of "end of interrupt" to re-enable
  * an interrupt after handling, in order to support hardware
  * prioritisation.
  *
@@ -125,12 +125,11 @@
 }
 #endif
 
-static void fastcall gic_handle_cascade_irq(unsigned int irq,
-					    struct irq_desc *desc)
+static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 {
 	struct gic_chip_data *chip_data = get_irq_data(irq);
 	struct irq_chip *chip = get_irq_chip(irq);
-	unsigned int cascade_irq;
+	unsigned int cascade_irq, gic_irq;
 	unsigned long status;
 
 	/* primary controller ack'ing */
@@ -140,16 +139,15 @@
 	status = readl(chip_data->cpu_base + GIC_CPU_INTACK);
 	spin_unlock(&irq_controller_lock);
 
-	cascade_irq = (status & 0x3ff);
-	if (cascade_irq > 1020)
+	gic_irq = (status & 0x3ff);
+	if (gic_irq == 1023)
 		goto out;
-	if (cascade_irq < 32 || cascade_irq >= NR_IRQS) {
-		do_bad_IRQ(cascade_irq, desc);
-		goto out;
-	}
 
-	cascade_irq += chip_data->irq_offset;
-	generic_handle_irq(cascade_irq);
+	cascade_irq = gic_irq + chip_data->irq_offset;
+	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
+		do_bad_IRQ(cascade_irq, desc);
+	else
+		generic_handle_irq(cascade_irq);
 
  out:
 	/* primary controller unmasking */
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index cfe6f46..ae21755 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -60,6 +60,9 @@
 	unsigned int irq;
 	spinlock_t lock;
 	void __iomem *base;
+#ifdef CONFIG_PM
+	void *saved_state;
+#endif
 };
 
 struct locomo_dev_info {
@@ -565,7 +568,7 @@
 	if (!save)
 		return -ENOMEM;
 
-	dev->dev.power.saved_state = (void *) save;
+	lchip->saved_state = save;
 
 	spin_lock_irqsave(&lchip->lock, flags);
 
@@ -605,8 +608,8 @@
 	struct locomo_save_data *save;
 	unsigned long r;
 	unsigned long flags;
-	
-	save = (struct locomo_save_data *) dev->dev.power.saved_state;
+
+	save = lchip->saved_state;
 	if (!save)
 		return 0;
 
@@ -628,6 +631,8 @@
 	locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
 
 	spin_unlock_irqrestore(&lchip->lock, flags);
+
+	lchip->saved_state = NULL;
 	kfree(save);
 
 	return 0;
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 798bbfc..eb06d0b 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -51,6 +51,9 @@
 	int		irq;
 	spinlock_t	lock;
 	void __iomem	*base;
+#ifdef CONFIG_PM
+	void		*saved_state;
+#endif
 };
 
 /*
@@ -822,7 +825,7 @@
 	save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
 	if (!save)
 		return -ENOMEM;
-	dev->dev.power.saved_state = save;
+	sachip->saved_state = save;
 
 	spin_lock_irqsave(&sachip->lock, flags);
 
@@ -878,7 +881,7 @@
 	unsigned long flags, id;
 	void __iomem *base;
 
-	save = (struct sa1111_save_data *)dev->dev.power.saved_state;
+	save = sachip->saved_state;
 	if (!save)
 		return 0;
 
@@ -923,7 +926,7 @@
 
 	spin_unlock_irqrestore(&sachip->lock, flags);
 
-	dev->dev.power.saved_state = NULL;
+	sachip->saved_state = NULL;
 	kfree(save);
 
 	return 0;
@@ -958,8 +961,8 @@
 		platform_set_drvdata(pdev, NULL);
 
 #ifdef CONFIG_PM
-		kfree(pdev->dev.power.saved_state);
-		pdev->dev.power.saved_state = NULL;
+		kfree(sachip->saved_state);
+		sachip->saved_state = NULL;
 #endif
 	}
 
diff --git a/arch/arm/common/sharpsl_param.c b/arch/arm/common/sharpsl_param.c
index c94864c..aad4d94 100644
--- a/arch/arm/common/sharpsl_param.c
+++ b/arch/arm/common/sharpsl_param.c
@@ -20,7 +20,7 @@
  * typically including LCD parameters are loaded by the bootloader at the
  * address PARAM_BASE. As the kernel will overwrite them, we need to store
  * them early in the boot process, then pass them to the appropriate drivers.
- * Not all devices use all paramaters but the format is common to all.
+ * Not all devices use all parameters but the format is common to all.
  */
 #ifdef CONFIG_ARCH_SA1100
 #define PARAM_BASE	0xe8ffc000
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 5972df2..111a7fa5 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -153,7 +153,7 @@
 		sharpsl_pm.battstat.mainbat_percent = percent;
 	}
 
-	dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %d\n", voltage,
+	dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage,
 			sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
 
 	/* If battery is low. limit backlight intensity to save power. */
@@ -291,7 +291,7 @@
 }
 
 /* Charging Finished Interrupt (Not present on Corgi) */
-/* Can trigger at the same time as an AC staus change so
+/* Can trigger at the same time as an AC status change so
    delay until after that has been processed */
 irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id)
 {
@@ -625,7 +625,7 @@
 	}
 
 	temp = get_select_val(buff);
-	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
+	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
 
 	if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
 			(!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
@@ -635,7 +635,7 @@
 
 static int sharpsl_off_charge_error(void)
 {
-	dev_err(sharpsl_pm.dev, "Offline Charger: Error occured.\n");
+	dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n");
 	sharpsl_pm.machinfo->charge(0);
 	sharpsl_pm_led(SHARPSL_LED_ERROR);
 	sharpsl_pm.charge_mode = CHRG_ERROR;
@@ -691,14 +691,14 @@
 
 		time = RCNR;
 		while(1) {
-			/* Check if any wakeup event had occured */
+			/* Check if any wakeup event had occurred */
 			if (sharpsl_pm.machinfo->charger_wakeup() != 0)
 				return 0;
 			/* Check for timeout */
 			if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
 				return 1;
 			if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
-				dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n");
+				dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n");
 	   			sharpsl_pm.full_count++;
 				sharpsl_pm.machinfo->charge(0);
 				mdelay(SHARPSL_CHARGE_WAIT_TIME);
@@ -714,7 +714,7 @@
 
 	time = RCNR;
 	while(1) {
-		/* Check if any wakeup event had occured */
+		/* Check if any wakeup event had occurred */
 		if (sharpsl_pm.machinfo->charger_wakeup() != 0)
 			return 0;
 		/* Check for timeout */
@@ -766,14 +766,14 @@
 }
 
 static struct pm_ops sharpsl_pm_ops = {
-	.prepare	= pxa_pm_prepare,
 	.enter		= corgi_pxa_pm_enter,
-	.finish		= pxa_pm_finish,
 	.valid		= pm_valid_only_mem,
 };
 
 static int __init sharpsl_pm_probe(struct platform_device *pdev)
 {
+	int ret;
+
 	if (!pdev->dev.platform_data)
 		return -EINVAL;
 
@@ -792,8 +792,10 @@
 
 	sharpsl_pm.machinfo->init();
 
-	device_create_file(&pdev->dev, &dev_attr_battery_percentage);
-	device_create_file(&pdev->dev, &dev_attr_battery_voltage);
+	ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage);
+	ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage);
+	if (ret != 0)
+		dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret);
 
 	apm_get_power_status = sharpsl_apm_get_power_status;
 
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 9179e82..f73d62e 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -57,7 +57,7 @@
 #define EXPORT_SYMBOL_ALIAS(sym,orig)		\
  EXPORT_CRC_ALIAS(sym)				\
  static const struct kernel_symbol __ksymtab_##sym	\
-  __attribute_used__ __attribute__((section("__ksymtab"))) =	\
+  __used __attribute__((section("__ksymtab"))) =	\
     { (unsigned long)&orig, #sym };
 
 /*
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 3c078e3..3278e71 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -85,7 +85,7 @@
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
-#if __LINUX_ARM_ARCH__ >= 6
+#ifdef CONFIG_CPU_HAS_ASID
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
   BLANK();
 #endif
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index ae89cdd..a98d0c9 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -350,13 +350,17 @@
 		CALL(sys_set_robust_list)
 		CALL(sys_get_robust_list)
 /* 340 */	CALL(sys_splice)
-		CALL(sys_arm_sync_file_range)
+		CALL(sys_sync_file_range2)
 		CALL(sys_tee)
 		CALL(sys_vmsplice)
 		CALL(sys_move_pages)
 /* 345 */	CALL(sys_getcpu)
 		CALL(sys_ni_syscall)		/* eventually epoll_pwait */
 		CALL(sys_kexec_load)
+		CALL(sys_utimensat)
+		CALL(sys_signalfd)
+/* 350 */	CALL(sys_timerfd)
+		CALL(sys_eventfd)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index a52da0d..024a9cf 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -20,7 +20,8 @@
 	.long	_end				@ r7
 	.long	processor_id			@ r4
 	.long	__machine_arch_type		@ r5
-	.long	cr_alignment			@ r6
+	.long	__atags_pointer			@ r6
+	.long	cr_alignment			@ r7
 	.long	init_thread_union + THREAD_START_SP @ sp
 
 /*
@@ -29,6 +30,7 @@
  *
  *  r0  = cp#15 control register
  *  r1  = machine ID
+ *  r2  = atags pointer
  *  r9  = processor ID
  */
 	.type	__mmap_switched, %function
@@ -47,11 +49,12 @@
 	strcc	fp, [r6],#4
 	bcc	1b
 
-	ldmia	r3, {r4, r5, r6, sp}
+	ldmia	r3, {r4, r5, r6, r7, sp}
 	str	r9, [r4]			@ Save processor ID
 	str	r1, [r5]			@ Save machine type
+	str	r2, [r6]			@ Save atags pointer
 	bic	r4, r0, #CR_A			@ Clear 'A' bit
-	stmia	r6, {r0, r4}			@ Save control register values
+	stmia	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
 
 /*
@@ -215,3 +218,34 @@
 	bl	__lookup_machine_type
 	mov	r0, r5
 	ldmfd	sp!, {r4 - r6, pc}
+
+/* Determine validity of the r2 atags pointer.  The heuristic requires
+ * that the pointer be aligned, in the first 16k of physical RAM and
+ * that the ATAG_CORE marker is first and present.  Future revisions
+ * of this function may be more lenient with the physical address and
+ * may also be able to move the ATAGS block if necessary.
+ *
+ * r8  = machinfo
+ *
+ * Returns:
+ *  r2 either valid atags pointer, or zero
+ *  r5, r6 corrupted
+ */
+
+	.type	__vet_atags, %function
+__vet_atags:
+	tst	r2, #0x3			@ aligned?
+	bne	1f
+
+	ldr	r5, [r2, #0]			@ is first tag ATAG_CORE?
+	subs	r5, r5, #ATAG_CORE_SIZE
+	bne	1f
+	ldr	r5, [r2, #4]
+	ldr	r6, =ATAG_CORE
+	cmp	r5, r6
+	bne	1f
+
+	mov	pc, lr				@ atag pointer is ok
+
+1:	mov	r2, #0
+	mov	pc, lr
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 41f98b4..7898cbc 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -29,6 +29,10 @@
 #define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
 #define KERNEL_RAM_PADDR	(PHYS_OFFSET + TEXT_OFFSET)
 
+#define ATAG_CORE 0x54410001
+#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
+
+
 /*
  * swapper_pg_dir is the virtual address of the initial page table.
  * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must
@@ -61,7 +65,7 @@
  *
  * This is normally called from the decompressor code.  The requirements
  * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
- * r1 = machine nr.
+ * r1 = machine nr, r2 = atags pointer.
  *
  * This code is mostly position independent, so if you link the kernel at
  * 0xc0008000, you call this at __pa(0xc0008000).
@@ -85,6 +89,7 @@
 	bl	__lookup_machine_type		@ r5=machinfo
 	movs	r8, r5				@ invalid machine (r5=0)?
 	beq	__error_a			@ yes, error 'a'
+	bl	__vet_atags
 	bl	__create_page_tables
 
 	/*
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 5d6e652..93b7f8e 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -28,6 +28,7 @@
 #include <linux/elfcore.h>
 #include <linux/pm.h>
 #include <linux/tick.h>
+#include <linux/utsname.h>
 
 #include <asm/leds.h>
 #include <asm/processor.h>
@@ -43,6 +44,10 @@
   "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
 };
 
+static const char *isa_modes[] = {
+  "ARM" , "Thumb" , "Jazelle", "ThumbEE"
+};
+
 extern void setup_mm_for_reboot(char mode);
 
 static volatile int hlt_counter;
@@ -199,16 +204,19 @@
 
 void __show_regs(struct pt_regs *regs)
 {
-	unsigned long flags = condition_codes(regs);
+	unsigned long flags;
+	char buf[64];
 
-	printk("CPU: %d\n", smp_processor_id());
+	printk("CPU: %d    %s  (%s %.*s)\n",
+		smp_processor_id(), print_tainted(), init_utsname()->release,
+		(int)strcspn(init_utsname()->version, " "),
+		init_utsname()->version);
 	print_symbol("PC is at %s\n", instruction_pointer(regs));
 	print_symbol("LR is at %s\n", regs->ARM_lr);
-	printk("pc : [<%08lx>]    lr : [<%08lx>]    %s\n"
+	printk("pc : [<%08lx>]    lr : [<%08lx>]    psr: %08lx\n"
 	       "sp : %08lx  ip : %08lx  fp : %08lx\n",
-		instruction_pointer(regs),
-		regs->ARM_lr, print_tainted(), regs->ARM_sp,
-		regs->ARM_ip, regs->ARM_fp);
+		regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr,
+		regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
 	printk("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
 		regs->ARM_r10, regs->ARM_r9,
 		regs->ARM_r8);
@@ -218,36 +226,39 @@
 	printk("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
 		regs->ARM_r3, regs->ARM_r2,
 		regs->ARM_r1, regs->ARM_r0);
-	printk("Flags: %c%c%c%c",
-		flags & PSR_N_BIT ? 'N' : 'n',
-		flags & PSR_Z_BIT ? 'Z' : 'z',
-		flags & PSR_C_BIT ? 'C' : 'c',
-		flags & PSR_V_BIT ? 'V' : 'v');
-	printk("  IRQs o%s  FIQs o%s  Mode %s%s  Segment %s\n",
-		interrupts_enabled(regs) ? "n" : "ff",
+
+	flags = regs->ARM_cpsr;
+	buf[0] = flags & PSR_N_BIT ? 'N' : 'n';
+	buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
+	buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
+	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
+	buf[4] = '\0';
+
+	printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s  ISA %s  Segment %s\n",
+		buf, interrupts_enabled(regs) ? "n" : "ff",
 		fast_interrupts_enabled(regs) ? "n" : "ff",
 		processor_modes[processor_mode(regs)],
-		thumb_mode(regs) ? " (T)" : "",
+		isa_modes[isa_mode(regs)],
 		get_fs() == get_ds() ? "kernel" : "user");
-#if CONFIG_CPU_CP15
+#ifdef CONFIG_CPU_CP15
 	{
 		unsigned int ctrl;
-		  __asm__ (
-		"	mrc p15, 0, %0, c1, c0\n"
-		: "=r" (ctrl));
-		printk("Control: %04X\n", ctrl);
-	}
+
+		buf[0] = '\0';
 #ifdef CONFIG_CPU_CP15_MMU
-	{
-		unsigned int transbase, dac;
-		  __asm__ (
-		"	mrc p15, 0, %0, c2, c0\n"
-		"	mrc p15, 0, %1, c3, c0\n"
-		: "=r" (transbase), "=r" (dac));
-		printk("Table: %08X  DAC: %08X\n",
-		  	transbase, dac);
-	}
+		{
+			unsigned int transbase, dac;
+			asm("mrc p15, 0, %0, c2, c0\n\t"
+			    "mrc p15, 0, %1, c3, c0\n"
+			    : "=r" (transbase), "=r" (dac));
+			snprintf(buf, sizeof(buf), "  Table: %08x  DAC: %08x",
+			  	transbase, dac);
+		}
 #endif
+		asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl));
+
+		printk("Control: %08x%s\n", ctrl, buf);
+	}
 #endif
 }
 
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 6f2f46c..78c9f1a 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -657,7 +657,6 @@
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long tmp;
 	int ret;
 
 	switch (request) {
@@ -666,12 +665,7 @@
 		 */
 		case PTRACE_PEEKTEXT:
 		case PTRACE_PEEKDATA:
-			ret = access_process_vm(child, addr, &tmp,
-						sizeof(unsigned long), 0);
-			if (ret == sizeof(unsigned long))
-				ret = put_user(tmp, (unsigned long __user *) data);
-			else
-				ret = -EIO;
+			ret = generic_ptrace_peekdata(child, addr, data);
 			break;
 
 		case PTRACE_PEEKUSR:
@@ -683,12 +677,7 @@
 		 */
 		case PTRACE_POKETEXT:
 		case PTRACE_POKEDATA:
-			ret = access_process_vm(child, addr, &data,
-						sizeof(unsigned long), 1);
-			if (ret == sizeof(unsigned long))
-				ret = 0;
-			else
-				ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
 		case PTRACE_POKEUSR:
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 0453dcc..5be2e98 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -63,6 +63,8 @@
 unsigned int __machine_arch_type;
 EXPORT_SYMBOL(__machine_arch_type);
 
+unsigned int __atags_pointer __initdata;
+
 unsigned int system_rev;
 EXPORT_SYMBOL(system_rev);
 
@@ -780,7 +782,9 @@
 	if (mdesc->soft_reboot)
 		reboot_setup("s");
 
-	if (mdesc->boot_params)
+	if (__atags_pointer)
+		tags = phys_to_virt(__atags_pointer);
+	else if (mdesc->boot_params)
 		tags = phys_to_virt(mdesc->boot_params);
 
 	/*
@@ -918,7 +922,7 @@
 
 	if ((processor_id & 0x0008f000) == 0x00000000) {
 		/* pre-ARM7 */
-		seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
+		seq_printf(m, "CPU part\t: %07x\n", processor_id >> 4);
 	} else {
 		if ((processor_id & 0x0008f000) == 0x00007000) {
 			/* ARM7 */
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index 8b63ad8..ae31deb 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -13,7 +13,7 @@
 		/*
 		 * Check current frame pointer is within bounds
 		 */
-		if ((fp - 12) < low || fp + 4 >= high)
+		if (fp < (low + 12) || fp + 4 >= high)
 			break;
 
 		frame = (struct stackframe *)(fp - 12);
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 3d4fcbc..4d25e49 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -320,7 +320,7 @@
 EXPORT_SYMBOL(kernel_execve);
 
 /*
- * Since loff_t is a 64 bit type we avoid a lot of ABI hastle
+ * Since loff_t is a 64 bit type we avoid a lot of ABI hassle
  * with a different argument ordering.
  */
 asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
@@ -328,16 +328,3 @@
 {
 	return sys_fadvise64_64(fd, offset, len, advice);
 }
-
-/*
- * Yet more syscall fsckage - we can't fit sys_sync_file_range's
- * arguments into the available registers with EABI.  So, let's
- * create an ARM specific syscall for this which has _sane_
- * arguments.  (This incidentally also has an ABI-independent
- * argument layout.)
- */
-asmlinkage long sys_arm_sync_file_range(int fd, unsigned int flags,
-					loff_t offset, loff_t nbytes)
-{
-	return sys_sync_file_range(fd, offset, nbytes, flags);
-}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 10ff36e..f2114bc 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -181,9 +181,7 @@
 
 void dump_stack(void)
 {
-#ifdef CONFIG_DEBUG_ERRORS
 	__backtrace();
-#endif
 }
 
 EXPORT_SYMBOL(dump_stack);
@@ -204,12 +202,24 @@
 	barrier();
 }
 
+#ifdef CONFIG_PREEMPT
+#define S_PREEMPT " PREEMPT"
+#else
+#define S_PREEMPT ""
+#endif
+#ifdef CONFIG_SMP
+#define S_SMP " SMP"
+#else
+#define S_SMP ""
+#endif
+
 static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
 {
 	struct task_struct *tsk = thread->task;
 	static int die_counter;
 
-	printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter);
+	printk("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
+	       str, err, ++die_counter);
 	print_modules();
 	__show_regs(regs);
 	printk("Process %s (pid: %d, stack limit = 0x%p)\n",
@@ -232,16 +242,23 @@
 {
 	struct thread_info *thread = current_thread_info();
 
+	oops_enter();
+
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 	__die(str, err, thread, regs);
 	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
 	if (panic_on_oops)
 		panic("Fatal exception");
 
+	oops_exit();
 	do_exit(SIGSEGV);
 }
 
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index e4156e7..2b7a8f5 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -90,7 +90,7 @@
 			__exception_text_start = .;
 			*(.exception.text)
 			__exception_text_end = .;
-			*(.text)
+			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
 #ifdef CONFIG_MMU
@@ -158,7 +158,7 @@
 		/*
 		 * and the usual data section
 		 */
-		*(.data)
+		DATA_DATA
 		CONSTRUCTORS
 
 		_edata = .;
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index 5422510..2e787d4 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -47,7 +47,7 @@
  * @store: store instruction
  *
  * Note: we can trivially conditionalise the store instruction
- * to avoid dirting the data cache.
+ * to avoid dirtying the data cache.
  */
 	.macro	testop, instr, store
 	add	r1, r1, r0, lsr #3
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index b451861..76ec856 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -79,7 +79,7 @@
 	.pullup_pin	= AT91_PIN_PD9,
 };
 
-/* FIXME: user dependend */
+/* FIXME: user dependant */
 // static struct at91_cf_data __initdata carmeva_cf_data = {
 //	.det_pin	= AT91_PIN_PB0,
 //	.rst_pin	= AT91_PIN_PC5,
@@ -100,17 +100,17 @@
 		.chip_select  = 0,
 		.max_speed_hz = 10 * 1000 * 1000,
 	},
-	{ /* User accessable spi - cs1 (250KHz) */
+	{ /* User accessible spi - cs1 (250KHz) */
 		.modalias = "spi-cs1",
 		.chip_select  = 1,
 		.max_speed_hz = 250 *  1000,
 	},
-	{ /* User accessable spi - cs2 (1MHz) */
+	{ /* User accessible spi - cs2 (1MHz) */
 		.modalias = "spi-cs2",
 		.chip_select  = 2,
 		.max_speed_hz = 1 * 1000 *  1000,
 	},
-	{ /* User accessable spi - cs3 (10MHz) */
+	{ /* User accessible spi - cs3 (10MHz) */
 		.modalias = "spi-cs3",
 		.chip_select  = 3,
 		.max_speed_hz = 10 * 1000 *  1000,
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index e18a41e..dde0899 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -23,6 +23,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/mtd/physmap.h>
 
@@ -83,6 +84,13 @@
 	.pullup_pin	= AT91_PIN_PA24,
 };
 
+static struct i2c_board_info __initdata csb337_i2c_devices[] = {
+	{ I2C_BOARD_INFO("rtc-ds1307", 0x68),
+	  .type = "ds1307",
+	},
+};
+
+
 static struct at91_cf_data __initdata csb337_cf_data = {
 	/*
 	 * connector P4 on the CSB 337 mates to
@@ -161,6 +169,8 @@
 	at91_add_device_udc(&csb337_udc_data);
 	/* I2C */
 	at91_add_device_i2c();
+	i2c_register_board_info(0, csb337_i2c_devices,
+			ARRAY_SIZE(csb337_i2c_devices));
 	/* Compact Flash */
 	at91_set_gpio_input(AT91_PIN_PB22, 1);		/* IOIS16 */
 	at91_add_device_cf(&csb337_cf_data);
diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c
index 6043c38..af49789 100644
--- a/arch/arm/mach-at91/board-dk.c
+++ b/arch/arm/mach-at91/board-dk.c
@@ -132,7 +132,7 @@
 	},
 };
 
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
 {
 	*num_partitions = ARRAY_SIZE(dk_nand_partition);
 	return dk_nand_partition;
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 76f6e1e..7d9b1a2 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -96,7 +96,7 @@
 	},
 };
 
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
 {
 	*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
 	return kb9202_nand_partition;
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 1f0c8a4..42e172c 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -27,6 +27,11 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/dm9000.h>
+#include <linux/fb.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <video/atmel_lcdc.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -178,7 +183,7 @@
 	},
 };
 
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
 {
 	*num_partitions = ARRAY_SIZE(ek_nand_partition);
 	return ek_nand_partition;
@@ -271,6 +276,127 @@
 };
 
 
+/*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+	{
+	        .name           = "TX09D50VM1CCA @ 60",
+		.refresh	= 60,
+		.xres		= 240,		.yres		= 320,
+		.pixclock	= KHZ2PICOS(4965),
+
+		.left_margin	= 1,		.right_margin	= 33,
+		.upper_margin	= 1,		.lower_margin	= 0,
+		.hsync_len	= 5,		.vsync_len	= 1,
+
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+	.manufacturer	= "HIT",
+	.monitor        = "TX09D50VM1CCA",
+
+	.modedb		= at91_tft_vga_modes,
+	.modedb_len	= ARRAY_SIZE(at91_tft_vga_modes),
+	.hfmin		= 15000,
+	.hfmax		= 64000,
+	.vfmin		= 50,
+	.vfmax		= 150,
+};
+
+#define AT91SAM9261_DEFAULT_LCDCON2 	(ATMEL_LCDC_MEMOR_LITTLE \
+					| ATMEL_LCDC_DISTYPE_TFT    \
+					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+	if (on)
+		at91_set_gpio_value(AT91_PIN_PA12, 0);	/* power up */
+	else
+		at91_set_gpio_value(AT91_PIN_PA12, 1);	/* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+	.default_bpp			= 16,
+	.default_dmacon			= ATMEL_LCDC_DMAEN,
+	.default_lcdcon2		= AT91SAM9261_DEFAULT_LCDCON2,
+	.default_monspecs		= &at91fb_default_monspecs,
+	.atmel_lcdfb_power_control	= at91_lcdc_power_control,
+	.guard_time			= 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+	{
+		.gpio		= AT91_PIN_PA27,
+		.keycode	= BTN_0,
+		.desc		= "Button 0",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= AT91_PIN_PA26,
+		.keycode	= BTN_1,
+		.desc		= "Button 1",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= AT91_PIN_PA25,
+		.keycode	= BTN_2,
+		.desc		= "Button 2",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= AT91_PIN_PA24,
+		.keycode	= BTN_3,
+		.desc		= "Button 3",
+		.active_low	= 1,
+	}
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+	.buttons	= ek_buttons,
+	.nbuttons	= ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &ek_button_data,
+	}
+};
+
+static void __init ek_add_device_buttons(void)
+{
+	at91_set_gpio_input(AT91_PIN_PB27, 0);	/* btn0 */
+	at91_set_deglitch(AT91_PIN_PB27, 1);
+	at91_set_gpio_input(AT91_PIN_PB26, 0);	/* btn1 */
+	at91_set_deglitch(AT91_PIN_PB26, 1);
+	at91_set_gpio_input(AT91_PIN_PB25, 0);	/* btn2 */
+	at91_set_deglitch(AT91_PIN_PB25, 1);
+	at91_set_gpio_input(AT91_PIN_PB24, 0);	/* btn3 */
+	at91_set_deglitch(AT91_PIN_PB24, 1);
+
+	platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
 static void __init ek_board_init(void)
 {
 	/* Serial */
@@ -296,6 +422,10 @@
 	/* MMC */
 	at91_add_device_mmc(0, &ek_mmc_data);
 #endif
+	/* LCD Controller */
+	at91_add_device_lcdc(&ek_lcdc_data);
+	/* Push Buttons */
+	ek_add_device_buttons();
 }
 
 MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index f574585..2a1cc73 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -26,6 +26,9 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/fb.h>
+
+#include <video/atmel_lcdc.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -180,7 +183,7 @@
 	},
 };
 
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
 {
 	*num_partitions = ARRAY_SIZE(ek_nand_partition);
 	return ek_nand_partition;
@@ -202,6 +205,65 @@
 
 
 /*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+	{
+	        .name           = "TX09D50VM1CCA @ 60",
+		.refresh	= 60,
+		.xres		= 240,		.yres		= 320,
+		.pixclock	= KHZ2PICOS(4965),
+
+		.left_margin	= 1,		.right_margin	= 33,
+		.upper_margin	= 1,		.lower_margin	= 0,
+		.hsync_len	= 5,		.vsync_len	= 1,
+
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+	.manufacturer	= "HIT",
+	.monitor        = "TX09D70VM1CCA",
+
+	.modedb		= at91_tft_vga_modes,
+	.modedb_len	= ARRAY_SIZE(at91_tft_vga_modes),
+	.hfmin		= 15000,
+	.hfmax		= 64000,
+	.vfmin		= 50,
+	.vfmax		= 150,
+};
+
+#define AT91SAM9263_DEFAULT_LCDCON2 	(ATMEL_LCDC_MEMOR_LITTLE \
+					| ATMEL_LCDC_DISTYPE_TFT    \
+					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+	if (on)
+		at91_set_gpio_value(AT91_PIN_PD12, 0);	/* power up */
+	else
+		at91_set_gpio_value(AT91_PIN_PD12, 1);	/* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+	.default_bpp			= 16,
+	.default_dmacon			= ATMEL_LCDC_DMAEN,
+	.default_lcdcon2		= AT91SAM9263_DEFAULT_LCDCON2,
+	.default_monspecs		= &at91fb_default_monspecs,
+	.atmel_lcdfb_power_control	= at91_lcdc_power_control,
+	.guard_time			= 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
+/*
  * AC97
  */
 static struct atmel_ac97_data ek_ac97_data = {
@@ -230,6 +292,8 @@
 	at91_add_device_nand(&ek_nand_data);
 	/* I2C */
 	at91_add_device_i2c();
+	/* LCD Controller */
+	at91_add_device_lcdc(&ek_lcdc_data);
 	/* AC97 */
 	at91_add_device_ac97(&ek_ac97_data);
 }
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 30c79ac..9b61320 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -87,7 +87,7 @@
 	},
 };
 
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
 {
 	*num_partitions = ARRAY_SIZE(ek_nand_partition);
 	return ek_nand_partition;
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 06c9a05..848efb2 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -364,19 +364,14 @@
 {
 	u32		scsr, pcsr, sr;
 	struct clk	*clk;
-	unsigned	i;
 
 	seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
 	seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR));
-
 	seq_printf(s, "MOR  = %8x\n", at91_sys_read(AT91_CKGR_MOR));
 	seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
 	seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
 	seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
-
 	seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
-	for (i = 0; i < 4; i++)
-		seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i)));
 	seq_printf(s, "SR   = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
 
 	seq_printf(s, "\n");
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index ff8db29..ddf9184 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -53,7 +53,7 @@
 /*
  * Called after processes are frozen, but before we shutdown devices.
  */
-static int at91_pm_prepare(suspend_state_t state)
+static int at91_pm_set_target(suspend_state_t state)
 {
 	target_state = state;
 	return 0;
@@ -76,12 +76,11 @@
 			pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
 			return 0;
 		}
-	} else if (cpu_is_at91sam9260()) {
-#warning "Check SAM9260 USB clocks"
-	} else if (cpu_is_at91sam9261()) {
-#warning "Check SAM9261 USB clocks"
-	} else if (cpu_is_at91sam9263()) {
-#warning "Check SAM9263 USB clocks"
+	} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
+		if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) {
+			pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+			return 0;
+		}
 	}
 
 #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
@@ -202,7 +201,7 @@
 
 static struct pm_ops at91_pm_ops ={
 	.valid		= at91_pm_valid_state,
-	.prepare	= at91_pm_prepare,
+	.set_target	= at91_pm_set_target,
 	.enter		= at91_pm_enter,
 };
 
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index a8f88cd..99ac2e5 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -4,7 +4,8 @@
 #
 
 # Common objects
-obj-y 			:= time.o irq.o serial.o io.o id.o psc.o
+obj-y 			:= time.o irq.o clock.o serial.o io.o id.o psc.o \
+			   gpio.o mux.o
 
 # Board specific
 obj-$(CONFIG_MACH_DAVINCI_EVM)  += board-evm.o
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c
index 633c12e..9e4024c 100644
--- a/arch/arm/mach-davinci/board-evm.c
+++ b/arch/arm/mach-davinci/board-evm.c
@@ -32,6 +32,7 @@
 void __init davinci_psc_init(void);
 void __init davinci_irq_init(void);
 void __init davinci_map_common_io(void);
+void __init davinci_init_common_hw(void);
 
 /* NOR Flash base address set to CS0 by default */
 #define NOR_FLASH_PHYS 0x02000000
@@ -116,6 +117,7 @@
 
 static __init void davinci_evm_irq_init(void)
 {
+	davinci_init_common_hw();
 	davinci_irq_init();
 }
 
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
new file mode 100644
index 0000000..139ceaa
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.c
@@ -0,0 +1,323 @@
+/*
+ * TI DaVinci clock config file
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/psc.h>
+#include "clock.h"
+
+/* PLL/Reset register offsets */
+#define PLLM		0x110
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clockfw_lock);
+
+static unsigned int commonrate;
+static unsigned int armrate;
+static unsigned int fixedrate = 27000000;	/* 27 MHZ */
+
+extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
+
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p, *clk = ERR_PTR(-ENOENT);
+	int idno;
+
+	if (dev == NULL || dev->bus != &platform_bus_type)
+		idno = -1;
+	else
+		idno = to_platform_device(dev)->id;
+
+	mutex_lock(&clocks_mutex);
+
+	list_for_each_entry(p, &clocks, node) {
+		if (p->id == idno &&
+		    strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			goto found;
+		}
+	}
+
+	list_for_each_entry(p, &clocks, node) {
+		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+
+found:
+	mutex_unlock(&clocks_mutex);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	if (clk && !IS_ERR(clk))
+		module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+static int __clk_enable(struct clk *clk)
+{
+	if (clk->flags & ALWAYS_ENABLED)
+		return 0;
+
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
+	return 0;
+}
+
+static void __clk_disable(struct clk *clk)
+{
+	if (clk->usecount)
+		return;
+
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
+}
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	if (clk->usecount++ == 0) {
+		spin_lock_irqsave(&clockfw_lock, flags);
+		ret = __clk_enable(clk);
+		spin_unlock_irqrestore(&clockfw_lock, flags);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
+	if (clk->usecount > 0 && !(--clk->usecount)) {
+		spin_lock_irqsave(&clockfw_lock, flags);
+		__clk_disable(clk);
+		spin_unlock_irqrestore(&clockfw_lock, flags);
+	}
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	/* changing the clk rate is not supported */
+	return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+	list_add(&clk->node, &clocks);
+	mutex_unlock(&clocks_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
+	mutex_lock(&clocks_mutex);
+	list_del(&clk->node);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static struct clk davinci_clks[] = {
+	{
+		.name = "ARMCLK",
+		.rate = &armrate,
+		.lpsc = -1,
+		.flags = ALWAYS_ENABLED,
+	},
+	{
+		.name = "UART",
+		.rate = &fixedrate,
+		.lpsc = DAVINCI_LPSC_UART0,
+	},
+	{
+		.name = "EMACCLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
+	},
+	{
+		.name = "I2CCLK",
+		.rate = &fixedrate,
+		.lpsc = DAVINCI_LPSC_I2C,
+	},
+	{
+		.name = "IDECLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_ATA,
+	},
+	{
+		.name = "McBSPCLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_McBSP,
+	},
+	{
+		.name = "MMCSDCLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_MMC_SD,
+	},
+	{
+		.name = "SPICLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_SPI,
+	},
+	{
+		.name = "gpio",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_GPIO,
+	},
+	{
+		.name = "AEMIFCLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_AEMIF,
+		.usecount = 1,
+	}
+};
+
+int __init davinci_clk_init(void)
+{
+	struct clk *clkp;
+	int count = 0;
+	u32 pll_mult;
+
+	pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
+	commonrate = ((pll_mult + 1) * 27000000) / 6;
+	armrate = ((pll_mult + 1) * 27000000) / 2;
+
+	for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
+	     count++, clkp++) {
+		clk_register(clkp);
+
+		/* Turn on clocks that have been enabled in the
+		 * table above */
+		if (clkp->usecount)
+			clk_enable(clkp);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+
+static void davinci_ck_stop(struct seq_file *m, void *v)
+{
+}
+
+static int davinci_ck_show(struct seq_file *m, void *v)
+{
+	struct clk *cp;
+
+	list_for_each_entry(cp, &clocks, node)
+		seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
+
+	return 0;
+}
+
+static struct seq_operations davinci_ck_op = {
+	.start	= davinci_ck_start,
+	.next	= davinci_ck_next,
+	.stop	= davinci_ck_stop,
+	.show	= davinci_ck_show
+};
+
+static int davinci_ck_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &davinci_ck_op);
+}
+
+static struct file_operations proc_davinci_ck_operations = {
+	.open		= davinci_ck_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int __init davinci_ck_proc_init(void)
+{
+	struct proc_dir_entry *entry;
+
+	entry = create_proc_entry("davinci_clocks", 0, NULL);
+	if (entry)
+		entry->proc_fops = &proc_davinci_ck_operations;
+	return 0;
+
+}
+__initcall(davinci_ck_proc_init);
+#endif	/* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
new file mode 100644
index 0000000..ed47079
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.h
@@ -0,0 +1,33 @@
+/*
+ * TI DaVinci clock definitions
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_DAVINCI_CLOCK_H
+#define __ARCH_ARM_DAVINCI_CLOCK_H
+
+struct clk {
+	struct list_head	node;
+	struct module		*owner;
+	const char		*name;
+	unsigned int		*rate;
+	int			id;
+	__s8			usecount;
+	__u8			flags;
+	__u8			lpsc;
+};
+
+/* Clock flags */
+#define RATE_CKCTL		1
+#define RATE_FIXED		2
+#define RATE_PROPAGATES		4
+#define VIRTUAL_CLOCK		8
+#define ALWAYS_ENABLED		16
+#define ENABLE_REG_32BIT	32
+
+#endif
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
new file mode 100644
index 0000000..9c67886
--- /dev/null
+++ b/arch/arm/mach-davinci/gpio.c
@@ -0,0 +1,286 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+
+#include <asm/mach/irq.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
+
+int gpio_request(unsigned gpio, const char *tag)
+{
+	if (gpio >= DAVINCI_N_GPIO)
+		return -EINVAL;
+
+	if (test_and_set_bit(gpio, gpio_in_use))
+		return -EBUSY;
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+	if (gpio >= DAVINCI_N_GPIO)
+		return;
+
+	clear_bit(gpio, gpio_in_use);
+}
+EXPORT_SYMBOL(gpio_free);
+
+/* create a non-inlined version */
+static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
+{
+	return __gpio_to_controller(gpio);
+}
+
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+void __gpio_set(unsigned gpio, int value)
+{
+	struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+	__raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
+}
+EXPORT_SYMBOL(__gpio_set);
+
+
+/*
+ * Read the pin's value (works even if it's set up as output);
+ * returns zero/nonzero.
+ *
+ * Note that changes are synched to the GPIO clock, so reading values back
+ * right after you've set them may give old values.
+ */
+int __gpio_get(unsigned gpio)
+{
+	struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+	return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+EXPORT_SYMBOL(__gpio_get);
+
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * board setup code *MUST* set PINMUX0 and PINMUX1 as
+ * needed, and enable the GPIO clock.
+ */
+
+int gpio_direction_input(unsigned gpio)
+{
+	struct gpio_controller *__iomem g = gpio2controller(gpio);
+	u32 temp;
+	u32 mask;
+
+	if (!g)
+		return -EINVAL;
+
+	spin_lock(&gpio_lock);
+	mask = __gpio_mask(gpio);
+	temp = __raw_readl(&g->dir);
+	temp |= mask;
+	__raw_writel(temp, &g->dir);
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+	struct gpio_controller *__iomem g = gpio2controller(gpio);
+	u32 temp;
+	u32 mask;
+
+	if (!g)
+		return -EINVAL;
+
+	spin_lock(&gpio_lock);
+	mask = __gpio_mask(gpio);
+	temp = __raw_readl(&g->dir);
+	temp &= ~mask;
+	__raw_writel(mask, value ? &g->set_data : &g->clr_data);
+	__raw_writel(temp, &g->dir);
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+ * We expect irqs will normally be set up as input pins, but they can also be
+ * used as output pins ... which is convenient for testing.
+ *
+ * NOTE:  GPIO0..GPIO7 also have direct INTC hookups, which work in addition
+ * to their GPIOBNK0 irq (but with a bit less overhead).  But we don't have
+ * a good way to hook those up ...
+ *
+ * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
+ * serve as EDMA event triggers.
+ */
+
+static void gpio_irq_disable(unsigned irq)
+{
+	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+	u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+	__raw_writel(mask, &g->clr_falling);
+	__raw_writel(mask, &g->clr_rising);
+}
+
+static void gpio_irq_enable(unsigned irq)
+{
+	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+	u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+	if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
+		__raw_writel(mask, &g->set_falling);
+	if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
+		__raw_writel(mask, &g->set_rising);
+}
+
+static int gpio_irq_type(unsigned irq, unsigned trigger)
+{
+	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+	u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		return -EINVAL;
+
+	irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
+	irq_desc[irq].status |= trigger;
+
+	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
+		     ? &g->set_falling : &g->clr_falling);
+	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
+		     ? &g->set_rising : &g->clr_rising);
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.enable		= gpio_irq_enable,
+	.disable	= gpio_irq_disable,
+	.set_type	= gpio_irq_type,
+};
+
+static void
+gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+	u32 mask = 0xffff;
+
+	/* we only care about one bank */
+	if (irq & 1)
+		mask <<= 16;
+
+	/* temporarily mask (level sensitive) parent IRQ */
+	desc->chip->ack(irq);
+	while (1) {
+		u32		status;
+		struct irq_desc	*gpio;
+		int		n;
+		int		res;
+
+		/* ack any irqs */
+		status = __raw_readl(&g->intstat) & mask;
+		if (!status)
+			break;
+		__raw_writel(status, &g->intstat);
+		if (irq & 1)
+			status >>= 16;
+
+		/* now demux them to the right lowlevel handler */
+		n = (int)get_irq_data(irq);
+		gpio = &irq_desc[n];
+		while (status) {
+			res = ffs(status);
+			n += res;
+			gpio += res;
+			desc_handle_irq(n - 1, gpio - 1);
+			status >>= res;
+		}
+	}
+	desc->chip->unmask(irq);
+	/* now it may re-trigger */
+}
+
+/*
+ * NOTE:  for suspend/resume, probably best to make a sysdev (and class)
+ * with its suspend/resume calls hooking into the results of the set_wake()
+ * calls ... so if no gpios are wakeup events the clock can be disabled,
+ * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
+ * can be set appropriately for GPIOV33 pins.
+ */
+
+static int __init davinci_gpio_irq_setup(void)
+{
+	unsigned	gpio, irq, bank;
+	struct clk	*clk;
+
+	clk = clk_get(NULL, "gpio");
+	if (IS_ERR(clk)) {
+		printk(KERN_ERR "Error %ld getting gpio clock?\n",
+		       PTR_ERR(clk));
+		return 0;
+	}
+
+	clk_enable(clk);
+
+	for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
+	     gpio < DAVINCI_N_GPIO; bank++) {
+		struct gpio_controller	*__iomem g = gpio2controller(gpio);
+		unsigned		i;
+
+		__raw_writel(~0, &g->clr_falling);
+		__raw_writel(~0, &g->clr_rising);
+
+		/* set up all irqs in this bank */
+		set_irq_chained_handler(bank, gpio_irq_handler);
+		set_irq_chip_data(bank, g);
+		set_irq_data(bank, (void *)irq);
+
+		for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
+		     i++, irq++, gpio++) {
+			set_irq_chip(irq, &gpio_irqchip);
+			set_irq_chip_data(irq, g);
+			set_irq_handler(irq, handle_simple_irq);
+			set_irq_flags(irq, IRQF_VALID);
+		}
+	}
+
+	/* BINTEN -- per-bank interrupt enable. genirq would also let these
+	 * bits be set/cleared dynamically.
+	 */
+	__raw_writel(0x1f, (void *__iomem)
+		     IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
+
+	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
+
+	return 0;
+}
+
+arch_initcall(davinci_gpio_irq_setup);
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
index 87fae6f..47787ff 100644
--- a/arch/arm/mach-davinci/io.c
+++ b/arch/arm/mach-davinci/io.c
@@ -17,6 +17,7 @@
 #include <asm/memory.h>
 
 #include <asm/mach/map.h>
+#include <asm/arch/clock.h>
 
 extern void davinci_check_revision(void);
 
@@ -49,3 +50,8 @@
 	 */
 	davinci_check_revision();
 }
+
+void __init davinci_init_common_hw(void)
+{
+	davinci_clk_init();
+}
diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c
new file mode 100644
index 0000000..92d26bd
--- /dev/null
+++ b/arch/arm/mach-davinci/mux.c
@@ -0,0 +1,41 @@
+/*
+ * DaVinci pin multiplexing configurations
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+
+#include <asm/arch/mux.h>
+
+/* System control register offsets */
+#define PINMUX0         0x00
+#define PINMUX1         0x04
+
+static DEFINE_SPINLOCK(mux_lock);
+
+void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
+{
+	u32 pinmux, muxreg = PINMUX0;
+
+	if (mux >= DAVINCI_MUX_LEVEL2) {
+		muxreg = PINMUX1;
+		mux -= DAVINCI_MUX_LEVEL2;
+	}
+
+	spin_lock(&mux_lock);
+	pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+	if (enable)
+		pinmux |= (1 << mux);
+	else
+		pinmux &= ~(1 << mux);
+	davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+	spin_unlock(&mux_lock);
+}
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index e1b0050..1334416 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -25,39 +25,40 @@
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/arch/psc.h>
+#include <asm/arch/mux.h>
 
-#define PTCMD	     __REG(0x01C41120)
-#define PDSTAT	     __REG(0x01C41200)
-#define PDCTL1	     __REG(0x01C41304)
-#define EPCPR	     __REG(0x01C41070)
-#define PTSTAT	     __REG(0x01C41128)
+/* PSC register offsets */
+#define EPCPR		0x070
+#define PTCMD		0x120
+#define PTSTAT		0x128
+#define PDSTAT		0x200
+#define PDCTL1		0x304
+#define MDSTAT		0x800
+#define MDCTL		0xA00
 
-#define MDSTAT	     IO_ADDRESS(0x01C41800)
-#define MDCTL	     IO_ADDRESS(0x01C41A00)
-
-#define PINMUX0	     __REG(0x01c40000)
-#define PINMUX1	     __REG(0x01c40004)
-#define VDD3P3V_PWDN __REG(0x01C40048)
+/* System control register offsets */
+#define VDD3P3V_PWDN	0x48
 
 static void davinci_psc_mux(unsigned int id)
 {
 	switch (id) {
 	case DAVINCI_LPSC_ATA:
-		PINMUX0 |= (1 << 17) | (1 << 16);
+		davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
+		davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
 		break;
 	case DAVINCI_LPSC_MMC_SD:
 		/* VDD power manupulations are done in U-Boot for CPMAC
 		 * so applies to MMC as well
 		 */
 		/*Set up the pull regiter for MMC */
-		VDD3P3V_PWDN = 0x0;
-		PINMUX1 &= (~(1 << 9));
+		davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
+		davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
 		break;
 	case DAVINCI_LPSC_I2C:
-		PINMUX1 |= (1 << 7);
+		davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
 		break;
 	case DAVINCI_LPSC_McBSP:
-		PINMUX1 |= (1 << 10);
+		davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
 		break;
 	default:
 		break;
@@ -67,33 +68,59 @@
 /* Enable or disable a PSC domain */
 void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
 {
-	volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id);
-	volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
+	u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
 
 	if (id < 0)
 		return;
 
+	mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
 	if (enable)
-		*mdctl |= 0x00000003;	/* Enable Module */
+		mdctl |= 0x00000003;	/* Enable Module */
 	else
-		*mdctl &= 0xFFFFFFF2;	/* Disable Module */
+		mdctl &= 0xFFFFFFF2;	/* Disable Module */
+	davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
 
-	if ((PDSTAT & 0x00000001) == 0) {
-		PDCTL1 |= 0x1;
-		PTCMD = (1 << domain);
-		while ((((EPCPR >> domain) & 1) == 0));
+	pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
+	if ((pdstat & 0x00000001) == 0) {
+		pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+		pdctl1 |= 0x1;
+		davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
 
-		PDCTL1 |= 0x100;
-		while (!(((PTSTAT >> domain) & 1) == 0));
+		ptcmd = 1 << domain;
+		davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+
+		do {
+			epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+					      EPCPR);
+		} while ((((epcpr >> domain) & 1) == 0));
+
+		pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+		pdctl1 |= 0x100;
+		davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+
+		do {
+			ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+					       PTSTAT);
+		} while (!(((ptstat >> domain) & 1) == 0));
 	} else {
-		PTCMD = (1 << domain);
-		while (!(((PTSTAT >> domain) & 1) == 0));
+		ptcmd = 1 << domain;
+		davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+
+		do {
+			ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+					       PTSTAT);
+		} while (!(((ptstat >> domain) & 1) == 0));
 	}
 
 	if (enable)
-		while (!((*mdstat & 0x0000001F) == 0x3));
+		mdstat_mask = 0x3;
 	else
-		while (!((*mdstat & 0x0000001F) == 0x2));
+		mdstat_mask = 0x2;
+
+	do {
+		mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+				       MDSTAT + 4 * id);
+	} while (!((mdstat & 0x0000001F) == mdstat_mask));
 
 	if (enable)
 		davinci_psc_mux(id);
diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c
index 4f984fd..35eb232 100644
--- a/arch/arm/mach-footbridge/cats-pci.c
+++ b/arch/arm/mach-footbridge/cats-pci.c
@@ -45,7 +45,7 @@
 	.postinit		= dc21285_postinit,
 };
 
-static int cats_pci_init(void)
+static int __init cats_pci_init(void)
 {
 	if (machine_is_cats())
 		pci_common_init(&cats_pci);
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
index 82e420d..0a1a25f 100644
--- a/arch/arm/mach-h720x/cpu-h7202.c
+++ b/arch/arm/mach-h720x/cpu-h7202.c
@@ -143,7 +143,7 @@
 }
 
 /*
- * mask multiplexed timer irq's
+ * mask multiplexed timer IRQs
  */
 static void inline mask_timerx_irq (u32 irq)
 {
@@ -153,7 +153,7 @@
 }
 
 /*
- * unmask multiplexed timer irq's
+ * unmask multiplexed timer IRQs
  */
 static void inline unmask_timerx_irq (u32 irq)
 {
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c
index 7e70e0b..467d899 100644
--- a/arch/arm/mach-imx/cpufreq.c
+++ b/arch/arm/mach-imx/cpufreq.c
@@ -245,7 +245,7 @@
 	if(mpctl0) {
 		CSCR |= CSCR_MPLL_RESTART;
 
-		/* Wait until MPLL is stablized */
+		/* Wait until MPLL is stabilized */
 		while( CSCR & CSCR_MPLL_RESTART );
 
 		imx_set_async_mode();
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 6d50d85..bc6fb02 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -131,7 +131,7 @@
  * The function setups DMA channel source and destination addresses for transfer
  * specified by provided parameters. The scatter-gather emulation is disabled,
  * because linear data block
- * form the physical address range is transfered.
+ * form the physical address range is transferred.
  * Return value: if incorrect parameters are provided -%EINVAL.
  *		Zero indicates success.
  */
@@ -192,7 +192,7 @@
  * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
  *           or %DMA_MODE_WRITE from memory to the device
  *
- * The function setups DMA channel state and registers to be ready for transfer
+ * The function sets up DMA channel state and registers to be ready for transfer
  * specified by provided parameters. The scatter-gather emulation is set up
  * according to the parameters.
  *
@@ -212,7 +212,7 @@
  *
  * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x
  *
- * Be carefull there and do not mistakenly mix source and target device
+ * Be careful here and do not mistakenly mix source and target device
  * port sizes constants, they are really different:
  * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32,
  * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32
@@ -495,7 +495,7 @@
 		/*
 		 * The cleaning of @sg field would be questionable
 		 * there, because its value can help to compute
-		 * remaining/transfered bytes count in the handler
+		 * remaining/transferred bytes count in the handler
 		 */
 		/*imx_dma_channels[i].sg = NULL;*/
 
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 7a7fa51..a58b678 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -28,12 +28,16 @@
 #include <linux/module.h>
 #include <linux/string.h>
 
+#include <asm/errno.h>
 #include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 #include <asm/arch/imx-regs.h>
 
 #include <asm/mach/map.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
 
 void imx_gpio_mode(int gpio_mode)
 {
@@ -95,6 +99,120 @@
 
 EXPORT_SYMBOL(imx_gpio_mode);
 
+int imx_gpio_request(unsigned gpio, const char *label)
+{
+	if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+		printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
+			gpio, label ? label : "?");
+		return -EINVAL;
+
+	if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
+		printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
+			gpio, label ? label : "?");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_request);
+
+void imx_gpio_free(unsigned gpio)
+{
+	if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+		return;
+
+	clear_bit(gpio, imx_gpio_alloc_map);
+}
+
+EXPORT_SYMBOL(imx_gpio_free);
+
+int imx_gpio_direction_input(unsigned gpio)
+{
+	imx_gpio_mode(gpio| GPIO_IN);
+	return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_input);
+
+int imx_gpio_direction_output(unsigned gpio, int value)
+{
+	imx_gpio_set_value(gpio, value);
+	imx_gpio_mode(gpio| GPIO_OUT);
+	return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_output);
+
+int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+				int alloc_mode, const char *label)
+{
+	const int *p = pin_list;
+	int i;
+	unsigned gpio;
+	unsigned mode;
+
+	for (i = 0; i < count; i++) {
+		gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+		mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+		if (gpio >= (GPIO_PORT_MAX + 1) * 32)
+			goto setup_error;
+
+		if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
+			imx_gpio_free(gpio);
+		else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
+			if (imx_gpio_request(gpio, label))
+				if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+					goto setup_error;
+
+		if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
+				    IMX_GPIO_ALLOC_MODE_RELEASE)))
+			imx_gpio_mode(gpio | mode);
+
+		p++;
+	}
+	return 0;
+
+setup_error:
+	if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
+		         IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+		return -EINVAL;
+
+	while (p != pin_list) {
+		p--;
+		gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+		imx_gpio_free(gpio);
+	}
+
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
+
+void __imx_gpio_set_value(unsigned gpio, int value)
+{
+	imx_gpio_set_value_inline(gpio, value);
+}
+
+EXPORT_SYMBOL(__imx_gpio_set_value);
+
+int imx_gpio_to_irq(unsigned gpio)
+{
+	return IRQ_GPIOA(0) + gpio;
+}
+
+EXPORT_SYMBOL(imx_gpio_to_irq);
+
+int imx_irq_to_gpio(unsigned irq)
+{
+	if (irq < IRQ_GPIOA(0))
+		return -EINVAL;
+	return irq - IRQ_GPIOA(0);
+}
+
+EXPORT_SYMBOL(imx_irq_to_gpio);
+
 /*
  *  get the system pll clock in Hz
  *
@@ -201,7 +319,6 @@
 {
 	imx_mmc_device.dev.platform_data = info;
 }
-EXPORT_SYMBOL(imx_set_mmc_info);
 
 static struct imxfb_mach_info imx_fb_info;
 
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 6960a9d..010f6fa 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2000-2001 Deep Blue Solutions
  *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +16,7 @@
 #include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -25,7 +27,8 @@
 /* Use timer 1 as system timer */
 #define TIMER_BASE IMX_TIM1_BASE
 
-static unsigned long evt_diff;
+static struct clock_event_device clockevent_imx;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
 /*
  * IRQ handler for the timer
@@ -33,25 +36,20 @@
 static irqreturn_t
 imx_timer_interrupt(int irq, void *dev_id)
 {
+	struct clock_event_device *evt = &clockevent_imx;
 	uint32_t tstat;
+	irqreturn_t ret = IRQ_NONE;
 
 	/* clear the interrupt */
 	tstat = IMX_TSTAT(TIMER_BASE);
 	IMX_TSTAT(TIMER_BASE) = 0;
 
 	if (tstat & TSTAT_COMP) {
-		do {
-
-			write_seqlock(&xtime_lock);
-			timer_tick();
-			write_sequnlock(&xtime_lock);
-			IMX_TCMP(TIMER_BASE) += evt_diff;
-
-		} while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
-					- IMX_TCN(TIMER_BASE)) < 0));
+		evt->event_handler(evt);
+		ret = IRQ_HANDLED;
 	}
 
-	return IRQ_HANDLED;
+	return ret;
 }
 
 static struct irqaction imx_timer_irq = {
@@ -70,10 +68,8 @@
 	 */
 	IMX_TCTL(TIMER_BASE) = 0;
 	IMX_TPRER(TIMER_BASE) = 0;
-	IMX_TCMP(TIMER_BASE) = LATCH - 1;
 
-	IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN;
-	evt_diff = LATCH;
+	IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN;
 }
 
 cycle_t imx_get_cycles(void)
@@ -99,11 +95,108 @@
 	return 0;
 }
 
+static int imx_set_next_event(unsigned long evt,
+				  struct clock_event_device *unused)
+{
+	unsigned long tcmp;
+
+	tcmp = IMX_TCN(TIMER_BASE) + evt;
+	IMX_TCMP(TIMER_BASE) = tcmp;
+
+	return (int32_t)(tcmp - IMX_TCN(TIMER_BASE)) < 0 ? -ETIME : 0;
+}
+
+#ifdef DEBUG
+static const char *clock_event_mode_label[]={
+	[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
+	[CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
+	[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
+	[CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
+};
+#endif /*DEBUG*/
+
+static void imx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
+{
+	unsigned long flags;
+
+	/*
+	 * The timer interrupt generation is disabled at least
+	 * for enough time to call imx_set_next_event()
+	 */
+	local_irq_save(flags);
+	/* Disable interrupt in GPT module */
+	IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN;
+	if (mode != clockevent_mode) {
+		/* Set event time into far-far future */
+		IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3;
+		/* Clear pending interrupt */
+		IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP;
+	}
+
+#ifdef DEBUG
+	printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n",
+		clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]);
+#endif /*DEBUG*/
+
+	/* Remember timer mode */
+	clockevent_mode = mode;
+	local_irq_restore(flags);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n");
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/*
+		 * Do not put overhead of interrupt enable/disable into
+		 * imx_set_next_event(), the core has about 4 minutes
+		 * to call imx_set_next_event() or shutdown clock after
+		 * mode switching
+		 */
+		local_irq_save(flags);
+		IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN;
+		local_irq_restore(flags);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		/* Left event sources disabled, no more interrupts appears */
+		break;
+	}
+}
+
+static struct clock_event_device clockevent_imx = {
+	.name		= "imx_timer1",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_mode	= imx_set_mode,
+	.set_next_event	= imx_set_next_event,
+	.rating		= 200,
+};
+
+static int __init imx_clockevent_init(void)
+{
+	clockevent_imx.mult = div_sc(imx_get_perclk1(), NSEC_PER_SEC,
+					clockevent_imx.shift);
+	clockevent_imx.max_delta_ns =
+		clockevent_delta2ns(0xfffffffe, &clockevent_imx);
+	clockevent_imx.min_delta_ns =
+		clockevent_delta2ns(0xf, &clockevent_imx);
+
+	clockevent_imx.cpumask = cpumask_of_cpu(0);
+
+	clockevents_register_device(&clockevent_imx);
+
+	return 0;
+}
+
+
 static void __init imx_timer_init(void)
 {
 	imx_timer_hardware_init();
 	imx_clocksource_init();
 
+	imx_clockevent_init();
+
 	/*
 	 * Make irqs happen for the system timer
 	 */
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
index ebb255b..158daaf 100644
--- a/arch/arm/mach-integrator/Makefile
+++ b/arch/arm/mach-integrator/Makefile
@@ -12,4 +12,3 @@
 obj-$(CONFIG_PCI)			+= pci_v3.o pci.o
 obj-$(CONFIG_CPU_FREQ_INTEGRATOR)	+= cpu.o
 obj-$(CONFIG_INTEGRATOR_IMPD1)		+= impd1.o
-obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 897c21c..e9c82de 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -257,23 +257,7 @@
 	 */
 	writel(1, TIMER1_VA_BASE + TIMER_INTCLR);
 
-	/*
-	 * the clock tick routines are only processed on the
-	 * primary CPU
-	 */
-	if (hard_smp_processor_id() == 0) {
-		timer_tick();
-#ifdef CONFIG_SMP
-		smp_send_timer();
-#endif
-	}
-
-#ifdef CONFIG_SMP
-	/*
-	 * this is the ARM equivalent of the APIC timer interrupt
-	 */
-	update_process_times(user_mode(get_irq_regs()));
-#endif /* CONFIG_SMP */
+	timer_tick();
 
 	write_sequnlock(&xtime_lock);
 
diff --git a/arch/arm/mach-integrator/headsmp.S b/arch/arm/mach-integrator/headsmp.S
deleted file mode 100644
index ceaa88e..0000000
--- a/arch/arm/mach-integrator/headsmp.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  linux/arch/arm/mach-integrator/headsmp.S
- *
- *  Copyright (c) 2003 ARM Limited
- *  All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-
-	__INIT
-
-/*
- * Integrator specific entry point for secondary CPUs.  This provides
- * a "holding pen" into which all secondary cores are held until we're
- * ready for them to initialise.
- */
-ENTRY(integrator_secondary_startup)
-	adr	r4, 1f
-	ldmia	r4, {r5, r6}
-	sub	r4, r4, r5
-	ldr	r6, [r6, r4]
-pen:	ldr	r7, [r6]
-	cmp	r7, r0
-	bne	pen
-
-	/*
-	 * we've been released from the holding pen: secondary_stack
-	 * should now contain the SVC stack for this core
-	 */
-	b	secondary_startup
-
-1:	.long	.
-	.long	phys_pen_release
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index af9ebcc..d4d8134 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -33,6 +33,7 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/mach/pci.h>
+#include <asm/irq_regs.h>
 
 #include <asm/hardware/pci_v3.h>
 
diff --git a/arch/arm/mach-integrator/platsmp.c b/arch/arm/mach-integrator/platsmp.c
deleted file mode 100644
index 613b841..0000000
--- a/arch/arm/mach-integrator/platsmp.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- *  linux/arch/arm/mach-cintegrator/platsmp.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-
-#include <asm/atomic.h>
-#include <asm/cacheflush.h>
-#include <asm/delay.h>
-#include <asm/mmu_context.h>
-#include <asm/ptrace.h>
-#include <asm/smp.h>
-
-extern void integrator_secondary_startup(void);
-
-/*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-volatile int __cpuinitdata pen_release = -1;
-unsigned long __cpuinitdata phys_pen_release = 0;
-
-static DEFINE_SPINLOCK(boot_lock);
-
-void __cpuinit platform_secondary_init(unsigned int cpu)
-{
-	/*
-	 * the primary core may have used a "cross call" soft interrupt
-	 * to get this processor out of WFI in the BootMonitor - make
-	 * sure that we are no longer being sent this soft interrupt
-	 */
-	smp_cross_call_done(cpumask_of_cpu(cpu));
-
-	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	secondary_scan_irqs();
-
-	/*
-	 * let the primary processor know we're out of the
-	 * pen, then head off into the C entry point
-	 */
-	pen_release = -1;
-
-	/*
-	 * Synchronise with the boot thread.
-	 */
-	spin_lock(&boot_lock);
-	spin_unlock(&boot_lock);
-}
-
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-	unsigned long timeout;
-
-	/*
-	 * set synchronisation state between this boot processor
-	 * and the secondary one
-	 */
-	spin_lock(&boot_lock);
-
-	/*
-	 * The secondary processor is waiting to be released from
-	 * the holding pen - release it, then wait for it to flag
-	 * that it has been released by resetting pen_release.
-	 *
-	 * Note that "pen_release" is the hardware CPU ID, whereas
-	 * "cpu" is Linux's internal ID.
-	 */
-	pen_release = cpu;
-	flush_cache_all();
-
-	/*
-	 * XXX
-	 *
-	 * This is a later addition to the booting protocol: the
-	 * bootMonitor now puts secondary cores into WFI, so
-	 * poke_milo() no longer gets the cores moving; we need
-	 * to send a soft interrupt to wake the secondary core.
-	 * Use smp_cross_call() for this, since there's little
-	 * point duplicating the code here
-	 */
-	smp_cross_call(cpumask_of_cpu(cpu));
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		if (pen_release == -1)
-			break;
-
-		udelay(10);
-	}
-
-	/*
-	 * now the secondary core is starting up let it run its
-	 * calibrations, then wait for it to finish
-	 */
-	spin_unlock(&boot_lock);
-
-	return pen_release != -1 ? -ENOSYS : 0;
-}
-
-static void __init poke_milo(void)
-{
-	extern void secondary_startup(void);
-
-	/* nobody is to be released from the pen yet */
-	pen_release = -1;
-
-	phys_pen_release = virt_to_phys(&pen_release);
-
-	/*
-	 * write the address of secondary startup into the system-wide
-	 * flags register, then clear the bottom two bits, which is what
-	 * BootMonitor is waiting for
-	 */
-#if 1
-#define CINTEGRATOR_HDR_FLAGSS_OFFSET 0x30
-	__raw_writel(virt_to_phys(integrator_secondary_startup),
-		     (IO_ADDRESS(INTEGRATOR_HDR_BASE) +
-		      CINTEGRATOR_HDR_FLAGSS_OFFSET));
-#define CINTEGRATOR_HDR_FLAGSC_OFFSET 0x34
-	__raw_writel(3,
-		     (IO_ADDRESS(INTEGRATOR_HDR_BASE) +
-		      CINTEGRATOR_HDR_FLAGSC_OFFSET));
-#endif
-
-	mb();
-}
-
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-void __init smp_init_cpus(void)
-{
-	unsigned int i, ncores = get_core_count();
-
-	for (i = 0; i < ncores; i++)
-		cpu_set(i, cpu_possible_map);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-	unsigned int ncores = get_core_count();
-	unsigned int cpu = smp_processor_id();
-	int i;
-
-	/* sanity check */
-	if (ncores == 0) {
-		printk(KERN_ERR
-		       "Integrator/CP: strange CM count of 0? Default to 1\n");
-
-		ncores = 1;
-	}
-
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "Integrator/CP: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
-	}
-
-	/*
-	 * start with some more config for the Boot CPU, now that
-	 * the world is a bit more alive (which was not the case
-	 * when smp_prepare_boot_cpu() was called)
-	 */
-	smp_store_cpu_info(cpu);
-
-	/*
-	 * are we trying to boot more cores than exist?
-	 */
-	if (max_cpus > ncores)
-		max_cpus = ncores;
-
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		cpu_set(i, cpu_present_map);
-
-	/*
-	 * Do we need any more CPUs? If so, then let them know where
-	 * to start. Note that, on modern versions of MILO, the "poke"
-	 * doesn't actually do anything until each individual core is
-	 * sent a soft interrupt to get it out of WFI
-	 */
-	if (max_cpus > 1)
-		poke_milo();
-}
diff --git a/arch/arm/mach-iop13xx/irq.c b/arch/arm/mach-iop13xx/irq.c
index 5791add..69f07b2 100644
--- a/arch/arm/mach-iop13xx/irq.c
+++ b/arch/arm/mach-iop13xx/irq.c
@@ -30,77 +30,65 @@
 
 /* INTCTL0 CP6 R0 Page 4
  */
-static inline u32 read_intctl_0(void)
+static u32 read_intctl_0(void)
 {
 	u32 val;
 	asm volatile("mrc p6, 0, %0, c0, c4, 0":"=r" (val));
 	return val;
 }
-static inline void write_intctl_0(u32 val)
+static void write_intctl_0(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c0, c4, 0"::"r" (val));
 }
 
 /* INTCTL1 CP6 R1 Page 4
  */
-static inline u32 read_intctl_1(void)
+static u32 read_intctl_1(void)
 {
 	u32 val;
 	asm volatile("mrc p6, 0, %0, c1, c4, 0":"=r" (val));
 	return val;
 }
-static inline void write_intctl_1(u32 val)
+static void write_intctl_1(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c1, c4, 0"::"r" (val));
 }
 
 /* INTCTL2 CP6 R2 Page 4
  */
-static inline u32 read_intctl_2(void)
+static u32 read_intctl_2(void)
 {
 	u32 val;
 	asm volatile("mrc p6, 0, %0, c2, c4, 0":"=r" (val));
 	return val;
 }
-static inline void write_intctl_2(u32 val)
+static void write_intctl_2(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c2, c4, 0"::"r" (val));
 }
 
 /* INTCTL3 CP6 R3 Page 4
  */
-static inline u32 read_intctl_3(void)
+static u32 read_intctl_3(void)
 {
 	u32 val;
 	asm volatile("mrc p6, 0, %0, c3, c4, 0":"=r" (val));
 	return val;
 }
-static inline void write_intctl_3(u32 val)
+static void write_intctl_3(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c3, c4, 0"::"r" (val));
 }
 
 /* INTSTR0 CP6 R0 Page 5
  */
-static inline u32 read_intstr_0(void)
-{
-	u32 val;
-	asm volatile("mrc p6, 0, %0, c0, c5, 0":"=r" (val));
-	return val;
-}
-static inline void write_intstr_0(u32 val)
+static void write_intstr_0(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c0, c5, 0"::"r" (val));
 }
 
 /* INTSTR1 CP6 R1 Page 5
  */
-static inline u32 read_intstr_1(void)
-{
-	u32 val;
-	asm volatile("mrc p6, 0, %0, c1, c5, 0":"=r" (val));
-	return val;
-}
 static void write_intstr_1(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c1, c5, 0"::"r" (val));
@@ -108,12 +96,6 @@
 
 /* INTSTR2 CP6 R2 Page 5
  */
-static inline u32 read_intstr_2(void)
-{
-	u32 val;
-	asm volatile("mrc p6, 0, %0, c2, c5, 0":"=r" (val));
-	return val;
-}
 static void write_intstr_2(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c2, c5, 0"::"r" (val));
@@ -121,12 +103,6 @@
 
 /* INTSTR3 CP6 R3 Page 5
  */
-static inline u32 read_intstr_3(void)
-{
-	u32 val;
-	asm volatile("mrc p6, 0, %0, c3, c5, 0":"=r" (val));
-	return val;
-}
 static void write_intstr_3(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c3, c5, 0"::"r" (val));
@@ -134,12 +110,6 @@
 
 /* INTBASE CP6 R0 Page 2
  */
-static inline u32 read_intbase(void)
-{
-	u32 val;
-	asm volatile("mrc p6, 0, %0, c0, c2, 0":"=r" (val));
-	return val;
-}
 static void write_intbase(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c0, c2, 0"::"r" (val));
@@ -147,12 +117,6 @@
 
 /* INTSIZE CP6 R2 Page 2
  */
-static inline u32 read_intsize(void)
-{
-	u32 val;
-	asm volatile("mrc p6, 0, %0, c2, c2, 0":"=r" (val));
-	return val;
-}
 static void write_intsize(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c2, c2, 0"::"r" (val));
diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c
index 2d23693..63ef1124c 100644
--- a/arch/arm/mach-iop13xx/msi.c
+++ b/arch/arm/mach-iop13xx/msi.c
@@ -30,52 +30,52 @@
 
 /* IMIPR0 CP6 R8 Page 1
  */
-static inline u32 read_imipr_0(void)
+static u32 read_imipr_0(void)
 {
 	u32 val;
 	asm volatile("mrc p6, 0, %0, c8, c1, 0":"=r" (val));
 	return val;
 }
-static inline void write_imipr_0(u32 val)
+static void write_imipr_0(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c8, c1, 0"::"r" (val));
 }
 
 /* IMIPR1 CP6 R9 Page 1
  */
-static inline u32 read_imipr_1(void)
+static u32 read_imipr_1(void)
 {
 	u32 val;
 	asm volatile("mrc p6, 0, %0, c9, c1, 0":"=r" (val));
 	return val;
 }
-static inline void write_imipr_1(u32 val)
+static void write_imipr_1(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c9, c1, 0"::"r" (val));
 }
 
 /* IMIPR2 CP6 R10 Page 1
  */
-static inline u32 read_imipr_2(void)
+static u32 read_imipr_2(void)
 {
 	u32 val;
 	asm volatile("mrc p6, 0, %0, c10, c1, 0":"=r" (val));
 	return val;
 }
-static inline void write_imipr_2(u32 val)
+static void write_imipr_2(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c10, c1, 0"::"r" (val));
 }
 
 /* IMIPR3 CP6 R11 Page 1
  */
-static inline u32 read_imipr_3(void)
+static u32 read_imipr_3(void)
 {
 	u32 val;
 	asm volatile("mrc p6, 0, %0, c11, c1, 0":"=r" (val));
 	return val;
 }
-static inline void write_imipr_3(u32 val)
+static void write_imipr_3(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c11, c1, 0"::"r" (val));
 }
@@ -190,5 +190,5 @@
 	write_msi_msg(irq, &msg);
 	set_irq_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq);
 
-	return irq;
+	return 0;
 }
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
index 1c9e94c..9d63d7f 100644
--- a/arch/arm/mach-iop13xx/pci.c
+++ b/arch/arm/mach-iop13xx/pci.c
@@ -19,10 +19,11 @@
 
 #include <linux/pci.h>
 #include <linux/delay.h>
-
+#include <linux/jiffies.h>
 #include <asm/irq.h>
 #include <asm/hardware.h>
 #include <asm/sizes.h>
+#include <asm/signal.h>
 #include <asm/mach/pci.h>
 #include <asm/arch/pci.h>
 
@@ -144,7 +145,7 @@
 	}
 }
 
-static inline int iop13xx_atu_function(int atu)
+static int iop13xx_atu_function(int atu)
 {
 	int func = 0;
 	/* the function number depends on the value of the
@@ -259,7 +260,7 @@
  * data.  Note that the data dependency on %0 encourages an abort
  * to be detected before we return.
  */
-static inline u32 iop13xx_atux_read(unsigned long addr)
+static u32 iop13xx_atux_read(unsigned long addr)
 {
 	u32 val;
 
@@ -387,7 +388,7 @@
 	return err;
 }
 
-static inline int __init
+static int
 iop13xx_pcie_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
 {
 	WARN_ON(idsel != 0);
@@ -401,7 +402,7 @@
 	}
 }
 
-static inline u32 iop13xx_atue_read(unsigned long addr)
+static u32 iop13xx_atue_read(unsigned long addr)
 {
 	u32 val;
 
@@ -989,7 +990,7 @@
 			"imprecise external abort");
 }
 
-/* intialize the pci memory space.  handle any combination of
+/* initialize the pci memory space.  handle any combination of
  * atue and atux enabled/disabled
  */
 int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index bc48715..bfe0c87 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -25,6 +25,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/hardware/iop_adma.h>
 
 #define IOP13XX_UART_XTAL 33334000
 #define IOP13XX_SETUP_DEBUG 0
@@ -236,19 +237,143 @@
 }
 #endif
 
+/* ADMA Channels */
+static struct resource iop13xx_adma_0_resources[] = {
+	[0] = {
+		.start = IOP13XX_ADMA_PHYS_BASE(0),
+		.end = IOP13XX_ADMA_UPPER_PA(0),
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_IOP13XX_ADMA0_EOT,
+		.end = IRQ_IOP13XX_ADMA0_EOT,
+		.flags = IORESOURCE_IRQ
+	},
+	[2] = {
+		.start = IRQ_IOP13XX_ADMA0_EOC,
+		.end = IRQ_IOP13XX_ADMA0_EOC,
+		.flags = IORESOURCE_IRQ
+	},
+	[3] = {
+		.start = IRQ_IOP13XX_ADMA0_ERR,
+		.end = IRQ_IOP13XX_ADMA0_ERR,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource iop13xx_adma_1_resources[] = {
+	[0] = {
+		.start = IOP13XX_ADMA_PHYS_BASE(1),
+		.end = IOP13XX_ADMA_UPPER_PA(1),
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_IOP13XX_ADMA1_EOT,
+		.end = IRQ_IOP13XX_ADMA1_EOT,
+		.flags = IORESOURCE_IRQ
+	},
+	[2] = {
+		.start = IRQ_IOP13XX_ADMA1_EOC,
+		.end = IRQ_IOP13XX_ADMA1_EOC,
+		.flags = IORESOURCE_IRQ
+	},
+	[3] = {
+		.start = IRQ_IOP13XX_ADMA1_ERR,
+		.end = IRQ_IOP13XX_ADMA1_ERR,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource iop13xx_adma_2_resources[] = {
+	[0] = {
+		.start = IOP13XX_ADMA_PHYS_BASE(2),
+		.end = IOP13XX_ADMA_UPPER_PA(2),
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_IOP13XX_ADMA2_EOT,
+		.end = IRQ_IOP13XX_ADMA2_EOT,
+		.flags = IORESOURCE_IRQ
+	},
+	[2] = {
+		.start = IRQ_IOP13XX_ADMA2_EOC,
+		.end = IRQ_IOP13XX_ADMA2_EOC,
+		.flags = IORESOURCE_IRQ
+	},
+	[3] = {
+		.start = IRQ_IOP13XX_ADMA2_ERR,
+		.end = IRQ_IOP13XX_ADMA2_ERR,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static u64 iop13xx_adma_dmamask = DMA_64BIT_MASK;
+static struct iop_adma_platform_data iop13xx_adma_0_data = {
+	.hw_id = 0,
+	.pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop13xx_adma_1_data = {
+	.hw_id = 1,
+	.pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop13xx_adma_2_data = {
+	.hw_id = 2,
+	.pool_size = PAGE_SIZE,
+};
+
+/* The ids are fixed up later in iop13xx_platform_init */
+static struct platform_device iop13xx_adma_0_channel = {
+	.name = "iop-adma",
+	.id = 0,
+	.num_resources = 4,
+	.resource = iop13xx_adma_0_resources,
+	.dev = {
+		.dma_mask = &iop13xx_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &iop13xx_adma_0_data,
+	},
+};
+
+static struct platform_device iop13xx_adma_1_channel = {
+	.name = "iop-adma",
+	.id = 0,
+	.num_resources = 4,
+	.resource = iop13xx_adma_1_resources,
+	.dev = {
+		.dma_mask = &iop13xx_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &iop13xx_adma_1_data,
+	},
+};
+
+static struct platform_device iop13xx_adma_2_channel = {
+	.name = "iop-adma",
+	.id = 0,
+	.num_resources = 4,
+	.resource = iop13xx_adma_2_resources,
+	.dev = {
+		.dma_mask = &iop13xx_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &iop13xx_adma_2_data,
+	},
+};
+
 void __init iop13xx_map_io(void)
 {
 	/* Initialize the Static Page Table maps */
 	iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc));
 }
 
-static int init_uart = 0;
-static int init_i2c = 0;
+static int init_uart;
+static int init_i2c;
+static int init_adma;
 
 void __init iop13xx_platform_init(void)
 {
 	int i;
-	u32 uart_idx, i2c_idx, plat_idx;
+	u32 uart_idx, i2c_idx, adma_idx, plat_idx;
 	struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES];
 
 	/* set the bases so we can read the device id */
@@ -294,6 +419,12 @@
 		}
 	}
 
+	if (init_adma == IOP13XX_INIT_ADMA_DEFAULT) {
+		init_adma |= IOP13XX_INIT_ADMA_0;
+		init_adma |= IOP13XX_INIT_ADMA_1;
+		init_adma |= IOP13XX_INIT_ADMA_2;
+	}
+
 	plat_idx = 0;
 	uart_idx = 0;
 	i2c_idx = 0;
@@ -332,6 +463,56 @@
 		}
 	}
 
+	/* initialize adma channel ids and capabilities */
+	adma_idx = 0;
+	for (i = 0; i < IQ81340_NUM_ADMA; i++) {
+		struct iop_adma_platform_data *plat_data;
+		if ((init_adma & (1 << i)) && IOP13XX_SETUP_DEBUG)
+			printk(KERN_INFO
+				"Adding adma%d to platform device list\n", i);
+		switch (init_adma & (1 << i)) {
+		case IOP13XX_INIT_ADMA_0:
+			iop13xx_adma_0_channel.id = adma_idx++;
+			iop13xx_devices[plat_idx++] = &iop13xx_adma_0_channel;
+			plat_data = &iop13xx_adma_0_data;
+			dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+			dma_cap_set(DMA_XOR, plat_data->cap_mask);
+			dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+			dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+			dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+			dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+			dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+			break;
+		case IOP13XX_INIT_ADMA_1:
+			iop13xx_adma_1_channel.id = adma_idx++;
+			iop13xx_devices[plat_idx++] = &iop13xx_adma_1_channel;
+			plat_data = &iop13xx_adma_1_data;
+			dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+			dma_cap_set(DMA_XOR, plat_data->cap_mask);
+			dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+			dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+			dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+			dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+			dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+			break;
+		case IOP13XX_INIT_ADMA_2:
+			iop13xx_adma_2_channel.id = adma_idx++;
+			iop13xx_devices[plat_idx++] = &iop13xx_adma_2_channel;
+			plat_data = &iop13xx_adma_2_data;
+			dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+			dma_cap_set(DMA_XOR, plat_data->cap_mask);
+			dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+			dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+			dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+			dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+			dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+			dma_cap_set(DMA_PQ_XOR, plat_data->cap_mask);
+			dma_cap_set(DMA_PQ_UPDATE, plat_data->cap_mask);
+			dma_cap_set(DMA_PQ_ZERO_SUM, plat_data->cap_mask);
+			break;
+		}
+	}
+
 #ifdef CONFIG_MTD_PHYSMAP
 	iq8134x_flash_resource.end = iq8134x_flash_resource.start +
 				iq8134x_probe_flash_size() - 1;
@@ -399,5 +580,35 @@
 	return 1;
 }
 
+static int __init iop13xx_init_adma_setup(char *str)
+{
+	if (str)	{
+		while (*str != '\0') {
+			switch (*str) {
+			case '0':
+				init_adma |= IOP13XX_INIT_ADMA_0;
+				break;
+			case '1':
+				init_adma |= IOP13XX_INIT_ADMA_1;
+				break;
+			case '2':
+				init_adma |= IOP13XX_INIT_ADMA_2;
+				break;
+			case ',':
+			case '=':
+				break;
+			default:
+				PRINTK("\"iop13xx_init_adma\" malformed"
+					    " at character: \'%c\'", *str);
+				*(str + 1) = '\0';
+				init_adma = IOP13XX_INIT_ADMA_DEFAULT;
+			}
+			str++;
+		}
+	}
+	return 1;
+}
+
+__setup("iop13xx_init_adma", iop13xx_init_adma_setup);
 __setup("iop13xx_init_uart", iop13xx_init_uart_setup);
 __setup("iop13xx_init_i2c", iop13xx_init_i2c_setup);
diff --git a/arch/arm/mach-iop13xx/tpmi.c b/arch/arm/mach-iop13xx/tpmi.c
index d3dc278..2476347 100644
--- a/arch/arm/mach-iop13xx/tpmi.c
+++ b/arch/arm/mach-iop13xx/tpmi.c
@@ -29,13 +29,15 @@
 #define IOP13XX_TPMI_MMR(dev) 	IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
 #define IOP13XX_TPMI_MEM(dev) 	IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
 #define IOP13XX_TPMI_CTRL(dev)	IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
+#define IOP13XX_TPMI_IOP_CTRL(dev) (IOP13XX_TPMI_CTRL(dev) + 0x2000)
 #define IOP13XX_TPMI_MMR_SIZE	    (SZ_4K - 1)
 #define IOP13XX_TPMI_MEM_SIZE	    (255)
 #define IOP13XX_TPMI_MEM_CTRL	    (SZ_1K - 1)
 #define IOP13XX_TPMI_RESOURCE_MMR  0
 #define IOP13XX_TPMI_RESOURCE_MEM  1
 #define IOP13XX_TPMI_RESOURCE_CTRL 2
-#define IOP13XX_TPMI_RESOURCE_IRQ  3
+#define IOP13XX_TPMI_RESOURCE_IOP_CTRL 3
+#define IOP13XX_TPMI_RESOURCE_IRQ  4
 
 static struct resource iop13xx_tpmi_0_resources[] = {
 	[IOP13XX_TPMI_RESOURCE_MMR] = {
@@ -53,6 +55,11 @@
 		.end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
 		.flags = IORESOURCE_MEM,
 	},
+	[IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+		.start = IOP13XX_TPMI_IOP_CTRL(0),
+		.end = IOP13XX_TPMI_IOP_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
+		.flags = IORESOURCE_MEM,
+	},
 	[IOP13XX_TPMI_RESOURCE_IRQ] = {
 		.start = IRQ_IOP13XX_TPMI0_OUT,
 		.end = IRQ_IOP13XX_TPMI0_OUT,
@@ -76,6 +83,11 @@
 		.end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
 		.flags = IORESOURCE_MEM,
 	},
+	[IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+		.start = IOP13XX_TPMI_IOP_CTRL(1),
+		.end = IOP13XX_TPMI_IOP_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
+		.flags = IORESOURCE_MEM,
+	},
 	[IOP13XX_TPMI_RESOURCE_IRQ] = {
 		.start = IRQ_IOP13XX_TPMI1_OUT,
 		.end = IRQ_IOP13XX_TPMI1_OUT,
@@ -99,6 +111,11 @@
 		.end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
 		.flags = IORESOURCE_MEM,
 	},
+	[IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+		.start = IOP13XX_TPMI_IOP_CTRL(2),
+		.end = IOP13XX_TPMI_IOP_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
+		.flags = IORESOURCE_MEM,
+	},
 	[IOP13XX_TPMI_RESOURCE_IRQ] = {
 		.start = IRQ_IOP13XX_TPMI2_OUT,
 		.end = IRQ_IOP13XX_TPMI2_OUT,
@@ -122,6 +139,11 @@
 		.end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
 		.flags = IORESOURCE_MEM,
 	},
+	[IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+		.start = IOP13XX_TPMI_IOP_CTRL(3),
+		.end = IOP13XX_TPMI_IOP_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
+		.flags = IORESOURCE_MEM,
+	},
 	[IOP13XX_TPMI_RESOURCE_IRQ] = {
 		.start = IRQ_IOP13XX_TPMI3_OUT,
 		.end = IRQ_IOP13XX_TPMI3_OUT,
@@ -133,7 +155,7 @@
 static struct platform_device iop13xx_tpmi_0_device = {
 	.name = "iop-tpmi",
 	.id = 0,
-	.num_resources = 4,
+	.num_resources = ARRAY_SIZE(iop13xx_tpmi_0_resources),
 	.resource = iop13xx_tpmi_0_resources,
 	.dev = {
 		.dma_mask          = &iop13xx_tpmi_mask,
@@ -144,7 +166,7 @@
 static struct platform_device iop13xx_tpmi_1_device = {
 	.name = "iop-tpmi",
 	.id = 1,
-	.num_resources = 4,
+	.num_resources = ARRAY_SIZE(iop13xx_tpmi_1_resources),
 	.resource = iop13xx_tpmi_1_resources,
 	.dev = {
 		.dma_mask          = &iop13xx_tpmi_mask,
@@ -155,7 +177,7 @@
 static struct platform_device iop13xx_tpmi_2_device = {
 	.name = "iop-tpmi",
 	.id = 2,
-	.num_resources = 4,
+	.num_resources = ARRAY_SIZE(iop13xx_tpmi_2_resources),
 	.resource = iop13xx_tpmi_2_resources,
 	.dev = {
 		.dma_mask          = &iop13xx_tpmi_mask,
@@ -166,7 +188,7 @@
 static struct platform_device iop13xx_tpmi_3_device = {
 	.name = "iop-tpmi",
 	.id = 3,
-	.num_resources = 4,
+	.num_resources = ARRAY_SIZE(iop13xx_tpmi_3_resources),
 	.resource = iop13xx_tpmi_3_resources,
 	.dev = {
 		.dma_mask          = &iop13xx_tpmi_mask,
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 45f4f13..2b086ab 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -75,7 +75,7 @@
 #define INTC	IRQ_IOP32X_XINT2
 #define INTD	IRQ_IOP32X_XINT3
 
-static inline int __init
+static int __init
 glantank_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static int pci_irq_table[][4] = {
@@ -180,6 +180,8 @@
 	platform_device_register(&iop3xx_i2c1_device);
 	platform_device_register(&glantank_flash_device);
 	platform_device_register(&glantank_serial_device);
+	platform_device_register(&iop3xx_dma_0_channel);
+	platform_device_register(&iop3xx_dma_1_channel);
 
 	pm_power_off = glantank_power_off;
 }
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index 7b21c6e..98cfa1c 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -104,7 +104,7 @@
 /*
  * EP80219/IQ31244 PCI.
  */
-static inline int __init
+static int __init
 ep80219_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq;
@@ -140,7 +140,7 @@
 	.map_irq	= ep80219_pci_map_irq,
 };
 
-static inline int __init
+static int __init
 iq31244_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq;
@@ -298,9 +298,14 @@
 	platform_device_register(&iop3xx_i2c1_device);
 	platform_device_register(&iq31244_flash_device);
 	platform_device_register(&iq31244_serial_device);
+	platform_device_register(&iop3xx_dma_0_channel);
+	platform_device_register(&iop3xx_dma_1_channel);
 
 	if (is_ep80219())
 		pm_power_off = ep80219_power_off;
+
+	if (!is_80219())
+		platform_device_register(&iop3xx_aau_channel);
 }
 
 static int __init force_ep80219_setup(char *str)
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index bc25fb9..18ad29f 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -72,7 +72,7 @@
 /*
  * IQ80321 PCI.
  */
-static inline int __init
+static int __init
 iq80321_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq;
@@ -181,6 +181,9 @@
 	platform_device_register(&iop3xx_i2c1_device);
 	platform_device_register(&iq80321_flash_device);
 	platform_device_register(&iq80321_serial_device);
+	platform_device_register(&iop3xx_dma_0_channel);
+	platform_device_register(&iop3xx_dma_1_channel);
+	platform_device_register(&iop3xx_aau_channel);
 }
 
 MACHINE_START(IQ80321, "Intel IQ80321")
diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
index 82598dc1..c971171 100644
--- a/arch/arm/mach-iop32x/irq.c
+++ b/arch/arm/mach-iop32x/irq.c
@@ -21,12 +21,12 @@
 
 static u32 iop32x_mask;
 
-static inline void intctl_write(u32 val)
+static void intctl_write(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
 }
 
-static inline void intstr_write(u32 val)
+static void intstr_write(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c4, c0, 0" : : "r" (val));
 }
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 5f07344..1873bd8 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -25,6 +25,7 @@
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 #include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <asm/hardware.h>
@@ -76,7 +77,7 @@
 /*
  * N2100 PCI.
  */
-static inline int __init
+static int __init
 n2100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq;
@@ -199,6 +200,12 @@
 	.resource	= &n2100_uart_resource,
 };
 
+static struct i2c_board_info __initdata n2100_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
+		.type = "rs5c372b",
+	},
+};
 
 /*
  * Pull PCA9532 GPIO #8 low to power off the machine.
@@ -245,6 +252,11 @@
 	platform_device_register(&iop3xx_i2c0_device);
 	platform_device_register(&n2100_flash_device);
 	platform_device_register(&n2100_serial_device);
+	platform_device_register(&iop3xx_dma_0_channel);
+	platform_device_register(&iop3xx_dma_1_channel);
+
+	i2c_register_board_info(0, n2100_i2c_devices,
+		ARRAY_SIZE(n2100_i2c_devices));
 
 	pm_power_off = n2100_power_off;
 
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index 376c932..433188e 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -55,7 +55,7 @@
 /*
  * IQ80331 PCI.
  */
-static inline int __init
+static int __init
 iq80331_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq;
@@ -136,6 +136,9 @@
 	platform_device_register(&iop33x_uart0_device);
 	platform_device_register(&iop33x_uart1_device);
 	platform_device_register(&iq80331_flash_device);
+	platform_device_register(&iop3xx_dma_0_channel);
+	platform_device_register(&iop3xx_dma_1_channel);
+	platform_device_register(&iop3xx_aau_channel);
 }
 
 MACHINE_START(IQ80331, "Intel IQ80331")
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index 58c8149..416c095 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -55,7 +55,7 @@
 /*
  * IQ80332 PCI.
  */
-static inline int __init
+static int __init
 iq80332_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq;
@@ -136,6 +136,9 @@
 	platform_device_register(&iop33x_uart0_device);
 	platform_device_register(&iop33x_uart1_device);
 	platform_device_register(&iq80332_flash_device);
+	platform_device_register(&iop3xx_dma_0_channel);
+	platform_device_register(&iop3xx_dma_1_channel);
+	platform_device_register(&iop3xx_aau_channel);
 }
 
 MACHINE_START(IQ80332, "Intel IQ80332")
diff --git a/arch/arm/mach-iop33x/irq.c b/arch/arm/mach-iop33x/irq.c
index c65ea78..f09dd05 100644
--- a/arch/arm/mach-iop33x/irq.c
+++ b/arch/arm/mach-iop33x/irq.c
@@ -22,32 +22,32 @@
 static u32 iop33x_mask0;
 static u32 iop33x_mask1;
 
-static inline void intctl0_write(u32 val)
+static void intctl0_write(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
 }
 
-static inline void intctl1_write(u32 val)
+static void intctl1_write(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c1, c0, 0" : : "r" (val));
 }
 
-static inline void intstr0_write(u32 val)
+static void intstr0_write(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c2, c0, 0" : : "r" (val));
 }
 
-static inline void intstr1_write(u32 val)
+static void intstr1_write(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c3, c0, 0" : : "r" (val));
 }
 
-static inline void intbase_write(u32 val)
+static void intbase_write(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c12, c0, 0" : : "r" (val));
 }
 
-static inline void intsize_write(u32 val)
+static void intsize_write(u32 val)
 {
 	asm volatile("mcr p6, 0, %0, c13, c0, 0" : : "r" (val));
 }
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 500e997..9c49435 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -198,7 +198,7 @@
 
 
 /*************************************************************************
- * ENP-2611 Machine Intialization
+ * ENP-2611 Machine Initialization
  *************************************************************************/
 static struct flash_platform_data enp2611_flash_platform_data = {
 	.map_name	= "cfi_probe",
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index 0fdd03a..ce7c15c 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -164,7 +164,7 @@
 
 subsys_initcall(ixdp2400_pci_init);
 
-void ixdp2400_init_irq(void)
+void __init ixdp2400_init_irq(void)
 {
 	ixdp2x00_init_irq(IXDP2400_CPLD_INT_STAT, IXDP2400_CPLD_INT_MASK, IXDP2400_NR_IRQS);
 }
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index 70d247f..14f09b80 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -279,7 +279,7 @@
 
 subsys_initcall(ixdp2800_pci_init);
 
-void ixdp2800_init_irq(void)
+void __init ixdp2800_init_irq(void)
 {
 	ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2800_NR_IRQS);
 }
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index 52b368b..73c651e 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -145,7 +145,7 @@
 	.unmask	= ixdp2x00_irq_unmask
 };
 
-void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs)
+void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs)
 {
 	unsigned int irq;
 
@@ -195,7 +195,7 @@
  * instances  of the kernel. So far so good. Peers on the PCI bus running 
  * Linux is a common design in telecom systems. The problem is that instead 
  * of all the devices being controlled by a single host, different
- * devices are controlles by different NPUs on the same bus, leading to
+ * devices are controlled by different NPUs on the same bus, leading to
  * multiple hosts on the bus. The exact bus layout looks like:
  *
  *                   Bus 0
@@ -211,7 +211,7 @@
  *                  |      |         |         |      |
  *             ... Dev    PMC       Media     Eth0   Eth1 ...
  *
- * The master controlls all but Eth1, which is controlled by the
+ * The master controls all but Eth1, which is controlled by the
  * slave. What this means is that the both the master and the slave
  * have to scan the bus, but only one of them can enumerate the bus.
  * In addition, after the bus is scanned, each kernel must remove
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 3084a5f..d3d730d 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -276,7 +276,7 @@
 	/* Device is located after first MB bridge */
 	case 0x0008:
 		if (tmp_bus == dev->bus) {
-			/* Device is located directy after first MB bridge */
+			/* Device is located directly after first MB bridge */
 			switch (devpin) {
 			case DEVPIN(1, 1):	/* Onboard 82546 ch 0 */
 				if (machine_is_ixdp2401())
@@ -299,7 +299,7 @@
 		break;
 	case 0x0010:
 		if (tmp_bus == dev->bus) {
-			/* Device is located directy after second MB bridge */
+			/* Device is located directly after second MB bridge */
 			/* Secondary bus of second bridge */
 			switch (devpin) {
 			case DEVPIN(0, 1):	/* DB#0 */
@@ -348,7 +348,7 @@
 subsys_initcall(ixdp2x01_pci_init);
 
 /*************************************************************************
- * IXDP2x01 Machine Intialization
+ * IXDP2x01 Machine Initialization
  *************************************************************************/
 static struct flash_platform_data ixdp2x01_flash_platform_data = {
 	.map_name	= "cfi_probe",
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
index 5a09a90..03f4cf7 100644
--- a/arch/arm/mach-ixp2000/pci.c
+++ b/arch/arm/mach-ixp2000/pci.c
@@ -102,7 +102,7 @@
 }
 
 /*
- * We don't do error checks by callling clear_master_aborts() b/c the
+ * We don't do error checks by calling clear_master_aborts() b/c the
  * assumption is that the caller did a read first to make sure a device
  * exists.
  */
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
index b644bba..16356ff 100644
--- a/arch/arm/mach-ixp23xx/core.c
+++ b/arch/arm/mach-ixp23xx/core.c
@@ -389,7 +389,7 @@
 
 
 /*************************************************************************
- * IXP23xx Platform Initializaion
+ * IXP23xx Platform Initialization
  *************************************************************************/
 static struct resource ixp23xx_uart_resources[] = {
 	{
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index 7a86a25..c41a6b5 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -124,7 +124,7 @@
 	.unmask	= ixdp2351_intb_unmask
 };
 
-void ixdp2351_init_irq(void)
+void __init ixdp2351_init_irq(void)
 {
 	int irq;
 
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index ac7d43d..227f808 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -284,7 +284,7 @@
 	return 1;
 }
 
-void ixp23xx_pci_slave_init(void)
+void __init ixp23xx_pci_slave_init(void)
 {
 	ixp23xx_pci_common_init();
 }
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
index d06e21b..e3564496 100644
--- a/arch/arm/mach-ixp23xx/roadrunner.c
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -110,7 +110,7 @@
 	return NO_IRQ;
 }
 
-static void roadrunner_pci_preinit(void)
+static void __init roadrunner_pci_preinit(void)
 {
 	set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQT_LOW);
 	set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQT_LOW);
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 9715ef5..61b2dfc 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -41,6 +41,22 @@
 	  Engineering Coyote Gateway Reference Platform. For more
 	  information on this platform, see <file:Documentation/arm/IXP4xx>.
 
+config MACH_GATEWAY7001
+	bool "Gateway 7001"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Gateway's
+	  7001 Access Point. For more information on this platform,
+	  see http://openwrt.org
+
+config MACH_WG302V2
+	bool "Netgear WG302 v2 / WAG302 v2"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Netgear's
+	  WG302 v2 or WAG302 v2 Access Points. For more information
+	  on this platform, see http://openwrt.org
+
 config ARCH_IXDP425
 	bool "IXDP425"
 	help
@@ -104,9 +120,6 @@
 	  DSM-G600 RevA device. For more information on this platform,
 	  see http://www.nslu2-linux.org/wiki/DSMG600/HomePage
 
-#
-# Avila and IXDP share the same source for now. Will change in future
-#
 config	ARCH_IXDP4XX
 	bool
 	depends on ARCH_IXDP425 || MACH_IXDP465 || MACH_KIXRP435
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 3b87c47..77e00ad 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -13,6 +13,8 @@
 obj-pci-$(CONFIG_MACH_NSLU2)		+= nslu2-pci.o
 obj-pci-$(CONFIG_MACH_NAS100D)		+= nas100d-pci.o
 obj-pci-$(CONFIG_MACH_DSMG600)		+= dsmg600-pci.o
+obj-pci-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-pci.o
+obj-pci-$(CONFIG_MACH_WG302V2)		+= wg302v2-pci.o
 
 obj-y	+= common.o
 
@@ -24,5 +26,7 @@
 obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o nslu2-power.o
 obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o nas100d-power.o
 obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o dsmg600-power.o
+obj-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-setup.o
+obj-$(CONFIG_MACH_WG302V2)	+= wg302v2-setup.o
 
 obj-$(CONFIG_PCI)		+= $(obj-pci-$(CONFIG_PCI)) common-pci.o
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 64685da..8112f72 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -283,7 +283,7 @@
 	.handler	= ixp4xx_timer_interrupt,
 };
 
-static void __init ixp4xx_timer_init(void)
+void __init ixp4xx_timer_init(void)
 {
 	/* Reset/disable counter */
 	*IXP4XX_OSRT1 = 0;
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index 7bc94f3..ad2e5b9 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -25,10 +25,6 @@
 
 #include <asm/mach/pci.h>
 
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
 void __init coyote_pci_preinit(void)
 {
 	set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 1caff65..1e75e10 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -18,6 +18,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
+#include <asm/mach/time.h>
 
 static struct flash_platform_data dsmg600_flash_data = {
 	.map_name		= "cfi_probe",
@@ -128,6 +129,19 @@
 	gpio_line_set(DSMG600_PO_GPIO, IXP4XX_GPIO_HIGH);
 }
 
+static void __init dsmg600_timer_init(void)
+{
+    /* The xtal on this machine is non-standard. */
+    ixp4xx_timer_freq = DSMG600_FREQ;
+
+    /* Call standard timer_init function. */
+    ixp4xx_timer_init();
+}
+
+static struct sys_timer dsmg600_timer = {
+    .init   = dsmg600_timer_init,
+};
+
 static void __init dsmg600_init(void)
 {
 	ixp4xx_sys_init();
@@ -155,21 +169,13 @@
 #endif
 }
 
-static void __init dsmg600_fixup(struct machine_desc *desc,
-                struct tag *tags, char **cmdline, struct meminfo *mi)
-{
-       /* The xtal on this machine is non-standard. */
-        ixp4xx_timer_freq = DSMG600_FREQ;
-}
-
 MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
 	/* Maintainer: www.nslu2-linux.org */
 	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
 	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
-	.fixup          = dsmg600_fixup,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
-	.timer          = &ixp4xx_timer,
+	.timer          = &dsmg600_timer,
 	.init_machine	= dsmg600_init,
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c
new file mode 100644
index 0000000..6abf568
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/gateway7001-pci.c
+ *
+ * PCI setup routines for Gateway 7001
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *	Copyright (C) 2002 Jungo Software Technologies.
+ *	Copyright (C) 2003 MontaVista Softwrae, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init gateway7001_pci_preinit(void)
+{
+	set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW);
+	set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW);
+
+	ixp4xx_pci_preinit();
+}
+
+static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (slot == 1)
+		return IRQ_IXP4XX_GPIO11;
+	else if (slot == 2)
+		return IRQ_IXP4XX_GPIO10;
+	else return -1;
+}
+
+struct hw_pci gateway7001_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit =        gateway7001_pci_preinit,
+	.swizzle =        pci_std_swizzle,
+	.setup =          ixp4xx_setup,
+	.scan =           ixp4xx_scan_bus,
+	.map_irq =        gateway7001_map_irq,
+};
+
+int __init gateway7001_pci_init(void)
+{
+	if (machine_is_gateway7001())
+		pci_common_init(&gateway7001_pci);
+	return 0;
+}
+
+subsys_initcall(gateway7001_pci_init);
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
new file mode 100644
index 0000000..3787683
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ixp4xx/gateway7001-setup.c
+ *
+ * Board setup for the Gateway 7001 board
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <Kaloz@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data gateway7001_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource gateway7001_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device gateway7001_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &gateway7001_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gateway7001_flash_resource,
+};
+
+static struct resource gateway7001_uart_resource = {
+	.start	= IXP4XX_UART2_BASE_PHYS,
+	.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port gateway7001_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device gateway7001_uart = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= gateway7001_uart_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gateway7001_uart_resource,
+};
+
+static struct platform_device *gateway7001_devices[] __initdata = {
+	&gateway7001_flash,
+	&gateway7001_uart
+};
+
+static void __init gateway7001_init(void)
+{
+	ixp4xx_sys_init();
+
+	gateway7001_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	gateway7001_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	platform_add_devices(gateway7001_devices, ARRAY_SIZE(gateway7001_devices));
+}
+
+#ifdef CONFIG_MACH_GATEWAY7001
+MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
+	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
+	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer		= &ixp4xx_timer,
+	.boot_params	= 0x0100,
+	.init_machine	= gateway7001_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
index a66484b6..0d5a424 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
@@ -25,17 +25,13 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
+
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
-#include <asm/irq.h>
 #include <asm/arch/gtwx5715.h>
 #include <asm/mach/pci.h>
 
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
-
 /*
  * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
  * Slot 0 isn't actually populated with a card connector but
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 30f1300..dc6725b 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-ixp4xx/gtwx5715-setup.c
  *
- * Gemtek GTWX5715 (Linksys WRV54G) board settup
+ * Gemtek GTWX5715 (Linksys WRV54G) board setup
  *
  * Copyright (C) 2004 George T. Joseph
  * Derived from Coyote
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index ec4f079..d5008d8 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -15,6 +15,10 @@
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -24,6 +28,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
+#include <asm/delay.h>
 
 static struct flash_platform_data ixdp425_flash_data = {
 	.map_name	= "cfi_probe",
@@ -44,6 +49,77 @@
 	.resource	= &ixdp425_flash_resource,
 };
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition ixdp425_partitions[] = {
+	{
+		.name	= "ixp400 NAND FS 0",
+		.offset	= 0,
+		.size 	= SZ_8M
+	}, {
+		.name	= "ixp400 NAND FS 1",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL
+	},
+};
+#endif
+
+static void
+ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *this = mtd->priv;
+	int offset = (int)this->priv;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		if (ctrl & NAND_NCE) {
+			gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_LOW);
+			udelay(5);
+		} else
+			gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_HIGH);
+
+		offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
+		offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
+		this->priv = (void *)offset;
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, this->IO_ADDR_W + offset);
+}
+
+static struct platform_nand_data ixdp425_flash_nand_data = {
+	.chip = {
+		.chip_delay		= 30,
+		.options		= NAND_NO_AUTOINCR,
+#ifdef CONFIG_MTD_PARTITIONS
+		.part_probe_types 	= part_probes,
+		.partitions	 	= ixdp425_partitions,
+		.nr_partitions	 	= ARRAY_SIZE(ixdp425_partitions),
+#endif
+	},
+	.ctrl = {
+		.cmd_ctrl 		= ixdp425_flash_nand_cmd_ctrl
+	}
+};
+
+static struct resource ixdp425_flash_nand_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp425_flash_nand = {
+	.name		= "gen_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &ixdp425_flash_nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp425_flash_nand_resource,
+};
+#endif	/* CONFIG_MTD_NAND_PLATFORM */
+
 static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = {
 	.sda_pin	= IXDP425_SDA_PIN,
 	.scl_pin	= IXDP425_SCL_PIN,
@@ -104,6 +180,10 @@
 static struct platform_device *ixdp425_devices[] __initdata = {
 	&ixdp425_i2c_controller,
 	&ixdp425_flash,
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+	&ixdp425_flash_nand,
+#endif
 	&ixdp425_uart
 };
 
@@ -115,6 +195,22 @@
 	ixdp425_flash_resource.end =
 		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+	ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3),
+	ixdp425_flash_nand_resource.end   = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1;
+
+	gpio_line_config(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_OUT);
+
+	/* Configure expansion bus for NAND Flash */
+	*IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
+			  IXP4XX_EXP_BUS_STROBE_T(1) |	/* extend by 1 clock */
+			  IXP4XX_EXP_BUS_CYCLES(0) |	/* Intel cycles */
+			  IXP4XX_EXP_BUS_SIZE(0) |	/* 512bytes addr space*/
+			  IXP4XX_EXP_BUS_WR_EN |
+			  IXP4XX_EXP_BUS_BYTE_EN;	/* 8 bit data bus */
+#endif
+
 	if (cpu_is_ixp43x()) {
 		ixdp425_uart.num_resources = 1;
 		ixdp425_uart_data[1].flags = 0;
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index 509a95a..d1e75b7 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -23,10 +23,6 @@
 
 #include <asm/mach/pci.h>
 
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
 void __init ixdpg425_pci_preinit(void)
 {
 	set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 9a31444..78a1741 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -155,7 +155,8 @@
 
 	pm_power_off = nas100d_power_off;
 
-	/* This is only useful on a modified machine, but it is valuable
+	/*
+	 * This is only useful on a modified machine, but it is valuable
 	 * to have it first in order to see debug messages, and so that
 	 * it does *not* get removed if platform_add_devices fails!
 	 */
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 162c266..9bf8ccb 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -22,6 +22,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
+#include <asm/mach/time.h>
 
 static struct flash_platform_data nslu2_flash_data = {
 	.map_name		= "cfi_probe",
@@ -49,26 +50,26 @@
 static struct resource nslu2_led_resources[] = {
 	{
 		.name		= "ready",  /* green led */
-		.start		= NSLU2_LED_GRN,
-		.end		= NSLU2_LED_GRN,
+		.start		= NSLU2_LED_GRN_GPIO,
+		.end		= NSLU2_LED_GRN_GPIO,
 		.flags		= IXP4XX_GPIO_HIGH,
 	},
 	{
 		.name		= "status", /* red led */
-		.start		= NSLU2_LED_RED,
-		.end		= NSLU2_LED_RED,
+		.start		= NSLU2_LED_RED_GPIO,
+		.end		= NSLU2_LED_RED_GPIO,
 		.flags		= IXP4XX_GPIO_HIGH,
 	},
 	{
 		.name		= "disk-1",
-		.start		= NSLU2_LED_DISK1,
-		.end		= NSLU2_LED_DISK1,
+		.start		= NSLU2_LED_DISK1_GPIO,
+		.end		= NSLU2_LED_DISK1_GPIO,
 		.flags		= IXP4XX_GPIO_LOW,
 	},
 	{
 		.name		= "disk-2",
-		.start		= NSLU2_LED_DISK2,
-		.end		= NSLU2_LED_DISK2,
+		.start		= NSLU2_LED_DISK2_GPIO,
+		.end		= NSLU2_LED_DISK2_GPIO,
 		.flags		= IXP4XX_GPIO_LOW,
 	},
 };
@@ -157,10 +158,21 @@
 	gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH);
 }
 
+static void __init nslu2_timer_init(void)
+{
+    /* The xtal on this machine is non-standard. */
+    ixp4xx_timer_freq = NSLU2_FREQ;
+
+    /* Call standard timer_init function. */
+    ixp4xx_timer_init();
+}
+
+static struct sys_timer nslu2_timer = {
+    .init   = nslu2_timer_init,
+};
+
 static void __init nslu2_init(void)
 {
-	ixp4xx_timer_freq = NSLU2_FREQ;
-
 	ixp4xx_sys_init();
 
 	nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
@@ -169,7 +181,8 @@
 
 	pm_power_off = nslu2_power_off;
 
-	/* This is only useful on a modified machine, but it is valuable
+	/*
+	 * This is only useful on a modified machine, but it is valuable
 	 * to have it first in order to see debug messages, and so that
 	 * it does *not* get removed if platform_add_devices fails!
 	 */
@@ -185,6 +198,6 @@
 	.boot_params	= 0x00000100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
-	.timer          = &ixp4xx_timer,
+	.timer          = &nslu2_timer,
 	.init_machine	= nslu2_init,
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c
new file mode 100644
index 0000000..6588f2c
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/wg302v2-pci.c
+ *
+ * PCI setup routines for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *	Copyright (C) 2002 Jungo Software Technologies.
+ *	Copyright (C) 2003 MontaVista Software, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init wg302v2_pci_preinit(void)
+{
+	set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW);
+	set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW);
+
+	ixp4xx_pci_preinit();
+}
+
+static int __init wg302v2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (slot == 1)
+		return IRQ_IXP4XX_GPIO8;
+	else if (slot == 2)
+		return IRQ_IXP4XX_GPIO9;
+	else return -1;
+}
+
+struct hw_pci wg302v2_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit =        wg302v2_pci_preinit,
+	.swizzle =        pci_std_swizzle,
+	.setup =          ixp4xx_setup,
+	.scan =           ixp4xx_scan_bus,
+	.map_irq =        wg302v2_map_irq,
+};
+
+int __init wg302v2_pci_init(void)
+{
+	if (machine_is_wg302v2())
+		pci_common_init(&wg302v2_pci);
+	return 0;
+}
+
+subsys_initcall(wg302v2_pci_init);
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
new file mode 100644
index 0000000..f7e09ad
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -0,0 +1,109 @@
+/*
+ * arch/arm/mach-ixp4xx/wg302-setup.c
+ *
+ * Board setup for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <kaloz@openwrt.org>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data wg302v2_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource wg302v2_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device wg302v2_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &wg302v2_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &wg302v2_flash_resource,
+};
+
+static struct resource wg302v2_uart_resource = {
+	.start	= IXP4XX_UART2_BASE_PHYS,
+	.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port wg302v2_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device wg302v2_uart = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= wg302v2_uart_data,
+	},
+	.num_resources	= 1,
+	.resource	= &wg302v2_uart_resource,
+};
+
+static struct platform_device *wg302v2_devices[] __initdata = {
+	&wg302v2_flash,
+	&wg302v2_uart,
+};
+
+static void __init wg302v2_init(void)
+{
+	ixp4xx_sys_init();
+
+	wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices));
+}
+
+#ifdef CONFIG_MACH_WG302V2
+MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
+	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
+	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer		= &ixp4xx_timer,
+	.boot_params	= 0x0100,
+	.init_machine	= wg302v2_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
index 56b7d33..2a07a28 100644
--- a/arch/arm/mach-ks8695/Makefile
+++ b/arch/arm/mach-ks8695/Makefile
@@ -3,7 +3,7 @@
 # Makefile for KS8695 architecture support
 #
 
-obj-y				:= cpu.o irq.o time.o devices.o
+obj-y				:= cpu.o irq.o time.o gpio.o devices.o
 obj-m				:=
 obj-n				:=
 obj-				:=
diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c
new file mode 100644
index 0000000..b1aa3cb
--- /dev/null
+++ b/arch/arm/mach-ks8695/gpio.c
@@ -0,0 +1,218 @@
+/*
+ * arch/arm/mach-ks8695/gpio.c
+ *
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/gpio.h>
+
+/*
+ * Configure a GPIO line for either GPIO function, or its internal
+ * function (Interrupt, Timer, etc).
+ */
+static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio)
+{
+	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_5)	/* only GPIO 0..5 have internal functions */
+		return;
+
+	local_irq_save(flags);
+
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
+	if (gpio)			/* GPIO: set bit to 0 */
+		x &= ~enable[pin];
+	else				/* Internal function: set bit to 1 */
+		x |= enable[pin];
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
+
+	local_irq_restore(flags);
+}
+
+
+static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	/* set pin as input */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x &= ~IOPM_(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	/* Set IRQ triggering type */
+	set_irq_type(gpio_irq[pin], type);
+
+	/* enable interrupt mode */
+	ks8695_gpio_mode(pin, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL(ks8695_gpio_interrupt);
+
+
+
+/* .... Generic GPIO interface .............................................. */
+
+/*
+ * Configure the GPIO line as an input.
+ */
+int __init_or_module gpio_direction_input(unsigned int pin)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	/* set pin to GPIO mode */
+	ks8695_gpio_mode(pin, 1);
+
+	local_irq_save(flags);
+
+	/* set pin as input */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x &= ~IOPM_(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	/* set pin to GPIO mode */
+	ks8695_gpio_mode(pin, 1);
+
+	local_irq_save(flags);
+
+	/* set line state */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	if (state)
+		x |= (1 << pin);
+	else
+		x &= ~(1 << pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+	/* set pin as output */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x |= IOPM_(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+
+/*
+ * Set the state of an output GPIO line.
+ */
+void gpio_set_value(unsigned int pin, unsigned int state)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return;
+
+	local_irq_save(flags);
+
+	/* set output line state */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	if (state)
+		x |= (1 << pin);
+	else
+		x &= ~(1 << pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+
+/*
+ * Read the state of a GPIO line.
+ */
+int gpio_get_value(unsigned int pin)
+{
+	unsigned long x;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	return (x & (1 << pin)) != 0;
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+int gpio_to_irq(unsigned int pin)
+{
+	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
+		return -EINVAL;
+
+	return gpio_irq[pin];
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq)
+{
+	if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
+		return -EINVAL;
+
+	return (irq - KS8695_IRQ_EXTERN0);
+}
+EXPORT_SYMBOL(irq_to_gpio);
diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h
index 4fb2efc..df6e38e 100644
--- a/arch/arm/mach-lh7a40x/lcd-panel.h
+++ b/arch/arm/mach-lh7a40x/lcd-panel.h
@@ -126,7 +126,7 @@
 
  */
 
-/* The full horozontal cycle (Th) is clock/360/400/450. */
+/* The full horizontal cycle (Th) is clock/360/400/450. */
 /* The full vertical   cycle (Tv) is line/251/262/280. */
 
 #define PIX_CLOCK_TARGET	(6300000) /* -/6.3/7 MHz */
@@ -162,7 +162,7 @@
 	/* Logic Product Development LCD 6.4" VGA -10 */
 	/* Sharp PN LQ64D343 */
 
-/* The full horozontal cycle (Th) is clock/750/800/900. */
+/* The full horizontal cycle (Th) is clock/750/800/900. */
 /* The full vertical   cycle (Tv) is line/515/525/560. */
 
 #define PIX_CLOCK_TARGET	(28330000)
@@ -243,7 +243,7 @@
  * (fdisk, e2fsck).  And, at that speed the display may have a visible
  * flicker. */
 
-/* The full horozontal cycle (Th) is clock/832/1056/1395. */
+/* The full horizontal cycle (Th) is clock/832/1056/1395. */
 
 #define PIX_CLOCK_TARGET	(20000000)
 #define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
diff --git a/arch/arm/mach-ns9xxx/time.c b/arch/arm/mach-ns9xxx/time.c
index dd25708..b97d0c5 100644
--- a/arch/arm/mach-ns9xxx/time.c
+++ b/arch/arm/mach-ns9xxx/time.c
@@ -35,7 +35,7 @@
 {
 	/* return the microseconds which have passed since the last interrupt
 	 * was _serviced_.  That is, if an interrupt is pending or the counter
-	 * reloads, return one periode more. */
+	 * reloads, return one period more. */
 
 	u32 counter1 = SYS_TR(0);
 	int pending = SYS_ISR & (1 << IRQ_TIMER0);
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 856c681..f6ecdd3 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -38,7 +38,7 @@
 config MACH_OMAP_H3
 	bool "TI H3 Support"
 	depends on ARCH_OMAP1 && ARCH_OMAP16XX
-	select GPIOEXPANDER_OMAP
+#	select GPIOEXPANDER_OMAP
     	help
 	  TI OMAP 1710 H3 board support. Say Y here if you have such
 	  a board.
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 7d0cf7a..e713029 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -385,7 +385,7 @@
 	/* Workaround for wrong CS3 (NOR flash) timing
 	 * There are some U-Boot versions out there which configure
 	 * wrong CS3 memory timings. This mainly leads to CRC
-	 * or similiar errors if you use NOR flash (e.g. with JFFS2)
+	 * or similar errors if you use NOR flash (e.g. with JFFS2)
 	 */
 	if (EMIFS_CCS(3) != EMIFS_CS3_VAL)
 		EMIFS_CCS(3) = EMIFS_CS3_VAL;
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 4bc8a62..0158241 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -7,7 +7,7 @@
  *
  * Original version : Laurent Gonzalez
  *
- * Maintainters : http://palmtelinux.sf.net
+ * Maintainers : http://palmtelinux.sf.net
  *                palmtelinux-developpers@lists.sf.net
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 8caee68..5bb348e 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -438,7 +438,7 @@
 		omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
 
 	/*
-	 * Reenable interrupts
+	 * Re-enable interrupts
 	 */
 
 	local_irq_enable();
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 5170481..588adb5 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -443,7 +443,7 @@
 
 /*
  * Check the DLL lock state, and return tue if running in unlock mode.
- * This is needed to compenste for the shifted DLL value in unlock mode.
+ * This is needed to compensate for the shifted DLL value in unlock mode.
  */
 static u32 omap2_dll_force_needed(void)
 {
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 162978f..4f79186 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -338,7 +338,7 @@
 /*
  * These represent optimal values for common parts, it won't work for all.
  * As long as you scale down, most parameters are still work, they just
- * become sub-optimal. The RFR value goes in the oppisite direction. If you
+ * become sub-optimal. The RFR value goes in the opposite direction. If you
  * don't adjust it down as your clock period increases the refresh interval
  * will not be met. Setting all parameters for complete worst case may work,
  * but may cut memory performance by 2x. Due to errata the DLLs need to be
@@ -384,7 +384,7 @@
  * Filling in table based on H4 boards and 2430-SDPs variants available.
  * There are quite a few more rates combinations which could be defined.
  *
- * When multiple values are defiend the start up will try and choose the
+ * When multiple values are defined the start up will try and choose the
  * fastest one. If a 'fast' value is defined, then automatically, the /2
  * one should be included as it can be used.	Generally having more that
  * one fast set does not make sense, as static timings need to be changed
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 8f7c90a..34a31ca 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -12,7 +12,6 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/hardware.h>
-#include <asm/semaphore.h>
 
 struct clk {
 	struct list_head	node;
@@ -25,21 +24,21 @@
 };
 
 static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clocks_lock);
 
 struct clk *clk_get(struct device *dev, const char *id)
 {
 	struct clk *p, *clk = ERR_PTR(-ENOENT);
 
-	down(&clocks_sem);
+	mutex_lock(&clocks_mutex);
 	list_for_each_entry(p, &clocks, node) {
 		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
 			clk = p;
 			break;
 		}
 	}
-	up(&clocks_sem);
+	mutex_unlock(&clocks_mutex);
 
 	return clk;
 }
@@ -101,18 +100,18 @@
 
 int clk_register(struct clk *clk)
 {
-	down(&clocks_sem);
+	mutex_lock(&clocks_mutex);
 	list_add(&clk->node, &clocks);
-	up(&clocks_sem);
+	mutex_unlock(&clocks_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(clk_register);
 
 void clk_unregister(struct clk *clk)
 {
-	down(&clocks_sem);
+	mutex_lock(&clocks_mutex);
 	list_del(&clk->node);
-	up(&clocks_sem);
+	mutex_unlock(&clocks_mutex);
 }
 EXPORT_SYMBOL(clk_unregister);
 
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index a1a900d..aab2729 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -44,6 +44,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 
@@ -368,7 +369,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -380,7 +381,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -392,7 +393,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
index a72476c..365b943 100644
--- a/arch/arm/mach-pxa/corgi_lcd.c
+++ b/arch/arm/mach-pxa/corgi_lcd.c
@@ -40,7 +40,7 @@
 #define PICTRL_ADRS     0x06
 #define POLCTRL_ADRS    0x07
 
-/* Resgister Bit Definitions */
+/* Register Bit Definitions */
 #define RESCTL_QVGA     0x01
 #define RESCTL_VGA      0x00
 
@@ -55,11 +55,11 @@
 #define POWER0_COM_DCLK 0x01  /* COM Voltage DC Bias DAC Serial Data Clock */
 #define POWER0_COM_DOUT 0x02  /* COM Voltage DC Bias DAC Serial Data Out */
 #define POWER0_DAC_ON   0x04  /* DAC Power Supply ON */
-#define POWER0_COM_ON   0x08  /* COM Powewr Supply ON */
+#define POWER0_COM_ON   0x08  /* COM Power Supply ON */
 #define POWER0_VCC5_ON  0x10  /* VCC5 Power Supply ON */
 
 #define POWER0_DAC_OFF  0x00  /* DAC Power Supply OFF */
-#define POWER0_COM_OFF  0x00  /* COM Powewr Supply OFF */
+#define POWER0_COM_OFF  0x00  /* COM Power Supply OFF */
 #define POWER0_VCC5_OFF 0x00  /* VCC5 Power Supply OFF */
 
 #define PICTRL_INIT_STATE      0x01
@@ -145,7 +145,7 @@
 	lcdtg_i2c_send_stop(base_data);
 }
 
-/* Set Phase Adjuct */
+/* Set Phase Adjust */
 static void lcdtg_set_phadadj(int mode)
 {
 	int adj;
@@ -226,7 +226,7 @@
 		/* Signals output enable */
 		corgi_ssp_lcdtg_send(PICTRL_ADRS, 0);
 
-		/* Set Phase Adjuct */
+		/* Set Phase Adjust */
 		lcdtg_set_phadadj(mode);
 
 		/* Initialize for Input Signals from ATI */
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index ff6b4ee..40dea3d5 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -32,7 +32,7 @@
  * There are three devices connected to the SSP interface:
  *   1. A touchscreen controller (TI ADS7846 compatible)
  *   2. An LCD contoller (with some Backlight functionality)
- *   3. A battery moinitoring IC (Maxim MAX1111)
+ *   3. A battery monitoring IC (Maxim MAX1111)
  *
  * Each device uses a different speed/mode of communication.
  *
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
new file mode 100644
index 0000000..9a6faff
--- /dev/null
+++ b/arch/arm/mach-pxa/devices.h
@@ -0,0 +1,11 @@
+extern struct platform_device pxamci_device;
+extern struct platform_device pxaudc_device;
+extern struct platform_device pxafb_device;
+extern struct platform_device ffuart_device;
+extern struct platform_device btuart_device;
+extern struct platform_device stuart_device;
+extern struct platform_device hwuart_device;
+extern struct platform_device pxai2c_device;
+extern struct platform_device pxai2s_device;
+extern struct platform_device pxaficp_device;
+extern struct platform_device pxartc_device;
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 4440bab..93c4f31 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -25,12 +25,15 @@
 
 #include <asm/arch/pxa-regs.h>
 
-static struct dma_channel {
+struct dma_channel {
 	char *name;
+	pxa_dma_prio prio;
 	void (*irq_handler)(int, void *);
 	void *data;
-} dma_channels[PXA_DMA_CHANNELS];
+};
 
+static struct dma_channel *dma_channels;
+static int num_dma_channels;
 
 int pxa_request_dma (char *name, pxa_dma_prio prio,
 			 void (*irq_handler)(int, void *),
@@ -47,8 +50,9 @@
 
 	do {
 		/* try grabbing a DMA channel with the requested priority */
-		pxa_for_each_dma_prio (i, prio) {
-			if (!dma_channels[i].name) {
+		for (i = 0; i < num_dma_channels; i++) {
+			if ((dma_channels[i].prio == prio) &&
+			    !dma_channels[i].name) {
 				found = 1;
 				break;
 			}
@@ -91,7 +95,7 @@
 {
 	int i, dint = DINT;
 
-	for (i = 0; i < PXA_DMA_CHANNELS; i++) {
+	for (i = 0; i < num_dma_channels; i++) {
 		if (dint & (1 << i)) {
 			struct dma_channel *channel = &dma_channels[i];
 			if (channel->name && channel->irq_handler) {
@@ -109,18 +113,32 @@
 	return IRQ_HANDLED;
 }
 
-static int __init pxa_dma_init (void)
+int __init pxa_init_dma(int num_ch)
 {
-	int ret;
+	int i, ret;
 
-	ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
-	if (ret)
+	dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);
+	if (dma_channels == NULL)
+		return -ENOMEM;
+
+	ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
+	if (ret) {
 		printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-	return ret;
-}
+		kfree(dma_channels);
+		return ret;
+	}
 
-arch_initcall(pxa_dma_init);
+	/* dma channel priorities on pxa2xx processors:
+	 * ch 0 - 3,  16 - 19  <--> (0) DMA_PRIO_HIGH
+	 * ch 4 - 7,  20 - 23  <--> (1) DMA_PRIO_MEDIUM
+	 * ch 8 - 15, 24 - 31  <--> (2) DMA_PRIO_LOW
+	 */
+	for (i = 0; i < num_ch; i++)
+		dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
+
+	num_dma_channels = num_ch;
+	return 0;
+}
 
 EXPORT_SYMBOL(pxa_request_dma);
 EXPORT_SYMBOL(pxa_free_dma);
-
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 64b08b7..296539b 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -43,6 +43,7 @@
 #include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 
+#include "devices.h"
 #include "generic.h"
 
 /*
@@ -242,7 +243,7 @@
 
 static u64 pxamci_dmamask = 0xffffffffUL;
 
-static struct platform_device pxamci_device = {
+struct platform_device pxamci_device = {
 	.name		= "pxa2xx-mci",
 	.id		= -1,
 	.dev		= {
@@ -281,7 +282,7 @@
 
 static u64 udc_dma_mask = ~(u32)0;
 
-static struct platform_device udc_device = {
+struct platform_device pxaudc_device = {
 	.name		= "pxa2xx-udc",
 	.id		= -1,
 	.resource	= pxa2xx_udc_resources,
@@ -307,7 +308,7 @@
 
 static u64 fb_dma_mask = ~(u64)0;
 
-static struct platform_device pxafb_device = {
+struct platform_device pxafb_device = {
 	.name		= "pxa2xx-fb",
 	.id		= -1,
 	.dev		= {
@@ -328,24 +329,24 @@
 	pxafb_device.dev.parent = parent_dev;
 }
 
-static struct platform_device ffuart_device = {
+struct platform_device ffuart_device = {
 	.name		= "pxa2xx-uart",
 	.id		= 0,
 };
-static struct platform_device btuart_device = {
+struct platform_device btuart_device = {
 	.name		= "pxa2xx-uart",
 	.id		= 1,
 };
-static struct platform_device stuart_device = {
+struct platform_device stuart_device = {
 	.name		= "pxa2xx-uart",
 	.id		= 2,
 };
-static struct platform_device hwuart_device = {
+struct platform_device hwuart_device = {
 	.name		= "pxa2xx-uart",
 	.id		= 3,
 };
 
-static struct resource i2c_resources[] = {
+static struct resource pxai2c_resources[] = {
 	{
 		.start	= 0x40301680,
 		.end	= 0x403016a3,
@@ -357,40 +358,19 @@
 	},
 };
 
-static struct platform_device i2c_device = {
+struct platform_device pxai2c_device = {
 	.name		= "pxa2xx-i2c",
 	.id		= 0,
-	.resource	= i2c_resources,
-	.num_resources	= ARRAY_SIZE(i2c_resources),
+	.resource	= pxai2c_resources,
+	.num_resources	= ARRAY_SIZE(pxai2c_resources),
 };
 
-#ifdef CONFIG_PXA27x
-static struct resource i2c_power_resources[] = {
-	{
-		.start	= 0x40f00180,
-		.end	= 0x40f001a3,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= IRQ_PWRI2C,
-		.end	= IRQ_PWRI2C,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device i2c_power_device = {
-	.name		= "pxa2xx-i2c",
-	.id		= 1,
-	.resource	= i2c_power_resources,
-	.num_resources	= ARRAY_SIZE(i2c_resources),
-};
-#endif
-
 void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
 {
-	i2c_device.dev.platform_data = info;
+	pxai2c_device.dev.platform_data = info;
 }
 
-static struct resource i2s_resources[] = {
+static struct resource pxai2s_resources[] = {
 	{
 		.start	= 0x40400000,
 		.end	= 0x40400083,
@@ -402,16 +382,16 @@
 	},
 };
 
-static struct platform_device i2s_device = {
+struct platform_device pxai2s_device = {
 	.name		= "pxa2xx-i2s",
 	.id		= -1,
-	.resource	= i2s_resources,
-	.num_resources	= ARRAY_SIZE(i2s_resources),
+	.resource	= pxai2s_resources,
+	.num_resources	= ARRAY_SIZE(pxai2s_resources),
 };
 
 static u64 pxaficp_dmamask = ~(u32)0;
 
-static struct platform_device pxaficp_device = {
+struct platform_device pxaficp_device = {
 	.name		= "pxa2xx-ir",
 	.id		= -1,
 	.dev		= {
@@ -425,42 +405,7 @@
 	pxaficp_device.dev.platform_data = info;
 }
 
-static struct platform_device pxartc_device = {
+struct platform_device pxartc_device = {
 	.name		= "sa1100-rtc",
 	.id		= -1,
 };
-
-static struct platform_device *devices[] __initdata = {
-	&pxamci_device,
-	&udc_device,
-	&pxafb_device,
-	&ffuart_device,
-	&btuart_device,
-	&stuart_device,
-	&pxaficp_device,
-	&i2c_device,
-#ifdef CONFIG_PXA27x
-	&i2c_power_device,
-#endif
-	&i2s_device,
-	&pxartc_device,
-};
-
-static int __init pxa_init(void)
-{
-	int cpuid, ret;
-
-	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
-	if (ret)
-		return ret;
-
-	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
-	cpuid = read_cpuid(CPUID_ID);
-	if (((cpuid >> 4) & 0xfff) == 0x2d0 ||
-	    ((cpuid >> 4) & 0xfff) == 0x290)
-		ret = platform_device_register(&hwuart_device);
-
-	return ret;
-}
-
-subsys_initcall(pxa_init);
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index e54a8dd..91ab2ad8 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -12,8 +12,12 @@
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
+extern void __init pxa_init_irq_low(void);
+extern void __init pxa_init_irq_high(void);
+extern void __init pxa_init_irq_gpio(int gpio_nr);
+extern void __init pxa25x_init_irq(void);
+extern void __init pxa27x_init_irq(void);
 extern void __init pxa_map_io(void);
-extern void __init pxa_init_irq(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
 
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 64df440..465108d 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -38,6 +38,7 @@
 #include <asm/arch/mmc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /* TODO:
  * - add pxa2xx_audio_ops_t device structure
@@ -152,7 +153,7 @@
 static void __init idp_init_irq(void)
 {
 
-	pxa_init_irq();
+	pxa25x_init_irq();
 
 	set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
 }
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 4619d5f..4b867b0 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -30,12 +30,12 @@
 
 static void pxa_mask_low_irq(unsigned int irq)
 {
-	ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+	ICMR &= ~(1 << irq);
 }
 
 static void pxa_unmask_low_irq(unsigned int irq)
 {
-	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
+	ICMR |= (1 << irq);
 }
 
 static int pxa_set_wake(unsigned int irq, unsigned int on)
@@ -67,7 +67,27 @@
 	.set_wake	= pxa_set_wake,
 };
 
-#if PXA_INTERNAL_IRQS > 32
+void __init pxa_init_irq_low(void)
+{
+	int irq;
+
+	/* disable all IRQs */
+	ICMR = 0;
+
+	/* all IRQs are IRQ, not FIQ */
+	ICLR = 0;
+
+	/* only unmasked interrupts kick us out of idle */
+	ICCR = 1;
+
+	for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
+		set_irq_chip(irq, &pxa_internal_chip_low);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+}
+
+#ifdef CONFIG_PXA27x
 
 /*
  * This is for the second set of internal IRQs as found on the PXA27x.
@@ -75,12 +95,12 @@
 
 static void pxa_mask_high_irq(unsigned int irq)
 {
-	ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
+	ICMR2 &= ~(1 << (irq - 32));
 }
 
 static void pxa_unmask_high_irq(unsigned int irq)
 {
-	ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
+	ICMR2 |= (1 << (irq - 32));
 }
 
 static struct irq_chip pxa_internal_chip_high = {
@@ -90,6 +110,19 @@
 	.unmask		= pxa_unmask_high_irq,
 };
 
+void __init pxa_init_irq_high(void)
+{
+	int irq;
+
+	ICMR2 = 0;
+	ICLR2 = 0;
+
+	for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
+		set_irq_chip(irq, &pxa_internal_chip_high);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+}
 #endif
 
 /* Note that if an input/irq line ever gets changed to an output during
@@ -217,7 +250,7 @@
 	do {
 		loop = 0;
 
-		mask = GEDR0 & ~3;
+		mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
 		if (mask) {
 			GEDR0 = mask;
 			irq = IRQ_GPIO(2);
@@ -233,7 +266,7 @@
 			loop = 1;
 		}
 
-		mask = GEDR1;
+		mask = GEDR1 & GPIO_IRQ_mask[1];
 		if (mask) {
 			GEDR1 = mask;
 			irq = IRQ_GPIO(32);
@@ -248,7 +281,7 @@
 			loop = 1;
 		}
 
-		mask = GEDR2;
+		mask = GEDR2 & GPIO_IRQ_mask[2];
 		if (mask) {
 			GEDR2 = mask;
 			irq = IRQ_GPIO(64);
@@ -263,8 +296,7 @@
 			loop = 1;
 		}
 
-#if PXA_LAST_GPIO >= 96
-		mask = GEDR3;
+		mask = GEDR3 & GPIO_IRQ_mask[3];
 		if (mask) {
 			GEDR3 = mask;
 			irq = IRQ_GPIO(96);
@@ -278,7 +310,6 @@
 			} while (mask);
 			loop = 1;
 		}
-#endif
 	} while (loop);
 }
 
@@ -314,64 +345,27 @@
 	.set_wake	= pxa_set_gpio_wake,
 };
 
-
-void __init pxa_init_irq(void)
+void __init pxa_init_irq_gpio(int gpio_nr)
 {
-	int irq;
-
-	/* disable all IRQs */
-	ICMR = 0;
-
-	/* all IRQs are IRQ, not FIQ */
-	ICLR = 0;
+	int irq, i;
 
 	/* clear all GPIO edge detects */
-	GFER0 = 0;
-	GFER1 = 0;
-	GFER2 = 0;
-	GRER0 = 0;
-	GRER1 = 0;
-	GRER2 = 0;
-	GEDR0 = GEDR0;
-	GEDR1 = GEDR1;
-	GEDR2 = GEDR2;
-
-#ifdef CONFIG_PXA27x
-	/* And similarly for the extra regs on the PXA27x */
-	ICMR2 = 0;
-	ICLR2 = 0;
-	GFER3 = 0;
-	GRER3 = 0;
-	GEDR3 = GEDR3;
-#endif
-
-	/* only unmasked interrupts kick us out of idle */
-	ICCR = 1;
+	for (i = 0; i < gpio_nr; i += 32) {
+		GFER(i) = 0;
+		GRER(i) = 0;
+		GEDR(i) = GEDR(i);
+	}
 
 	/* GPIO 0 and 1 must have their mask bit always set */
 	GPIO_IRQ_mask[0] = 3;
 
-	for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-		set_irq_chip(irq, &pxa_internal_chip_low);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-#if PXA_INTERNAL_IRQS > 32
-	for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
-		set_irq_chip(irq, &pxa_internal_chip_high);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-#endif
-
 	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
 		set_irq_chip(irq, &pxa_low_gpio_chip);
 		set_irq_handler(irq, handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
+	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(gpio_nr); irq++) {
 		set_irq_chip(irq, &pxa_muxed_gpio_chip);
 		set_irq_handler(irq, handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index e309766..2611644 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -46,6 +46,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 static unsigned int lpd270_irq_enabled;
@@ -97,7 +98,7 @@
 {
 	int irq;
 
-	pxa_init_irq();
+	pxa27x_init_irq();
 
 	__raw_writew(0, LPD270_INT_MASK);
 	__raw_writew(0, LPD270_INT_STATUS);
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 6377b2e..e70048f 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -48,6 +48,7 @@
 #include <asm/arch/mmc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 #define LUB_MISC_WR		__LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
@@ -103,7 +104,7 @@
 {
 	int irq;
 
-	pxa_init_irq();
+	pxa25x_init_irq();
 
 	/* setup extra lubbock irqs */
 	for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index ed99a81..b02c79c 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -46,6 +46,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 static unsigned long mainstone_irq_enabled;
@@ -89,7 +90,7 @@
 {
 	int irq;
 
-	pxa_init_irq();
+	pxa27x_init_irq();
 
 	/* setup extra Mainstone irqs */
 	for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 6bf15ae..e66dbc2 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -77,7 +77,6 @@
 {
 	unsigned long sleep_save[SLEEP_SAVE_SIZE];
 	unsigned long checksum = 0;
-	struct timespec delta, rtc;
 	int i;
 	extern void pxa_cpu_pm_enter(suspend_state_t state);
 
@@ -87,11 +86,6 @@
 		iwmmxt_task_disable(NULL);
 #endif
 
-	/* preserve current time */
-	rtc.tv_sec = RCNR;
-	rtc.tv_nsec = 0;
-	save_time_delta(&delta, &rtc);
-
 	SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
 	SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
 	SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
@@ -183,10 +177,6 @@
 
 	RESTORE(PSTR);
 
-	/* restore current time */
-	rtc.tv_sec = RCNR;
-	restore_time_delta(&delta, &rtc);
-
 #ifdef DEBUG
 	printk(KERN_DEBUG "*** made it back from resume\n");
 #endif
@@ -200,40 +190,3 @@
 {
 	return virt_to_phys(sp);
 }
-
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-int pxa_pm_prepare(suspend_state_t state)
-{
-	extern int pxa_cpu_pm_prepare(suspend_state_t state);
-
-	return pxa_cpu_pm_prepare(state);
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_prepare);
-
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-int pxa_pm_finish(suspend_state_t state)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_finish);
-
-static struct pm_ops pxa_pm_ops = {
-	.prepare	= pxa_pm_prepare,
-	.enter		= pxa_pm_enter,
-	.finish		= pxa_pm_finish,
-	.valid		= pm_valid_only_mem,
-};
-
-static int __init pxa_pm_init(void)
-{
-	pm_set_ops(&pxa_pm_ops);
-	return 0;
-}
-
-device_initcall(pxa_pm_init);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 34fb80b..655668d 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -45,6 +45,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 static struct resource poodle_scoop_resources[] = {
@@ -412,7 +413,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_poodle,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= poodle_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index c1f2173..f36ca44 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -19,12 +19,17 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/pm.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/irqs.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /*
  * Various clock factors driven by the CCCR register.
@@ -105,18 +110,6 @@
 
 #ifdef CONFIG_PM
 
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_MEM:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 void pxa_cpu_pm_enter(suspend_state_t state)
 {
 	extern void pxa_cpu_suspend(unsigned int);
@@ -133,4 +126,49 @@
 	}
 }
 
+static struct pm_ops pxa25x_pm_ops = {
+	.enter		= pxa_pm_enter,
+	.valid		= pm_valid_only_mem,
+};
 #endif
+
+void __init pxa25x_init_irq(void)
+{
+	pxa_init_irq_low();
+	pxa_init_irq_gpio(85);
+}
+
+static struct platform_device *pxa25x_devices[] __initdata = {
+	&pxamci_device,
+	&pxaudc_device,
+	&pxafb_device,
+	&ffuart_device,
+	&btuart_device,
+	&stuart_device,
+	&pxai2c_device,
+	&pxai2s_device,
+	&pxaficp_device,
+	&pxartc_device,
+};
+
+static int __init pxa25x_init(void)
+{
+	int ret = 0;
+
+	if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
+		if ((ret = pxa_init_dma(16)))
+			return ret;
+#ifdef CONFIG_PM
+		pm_set_ops(&pxa25x_pm_ops);
+#endif
+		ret = platform_add_devices(pxa25x_devices,
+					   ARRAY_SIZE(pxa25x_devices));
+	}
+	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
+	if (cpu_is_pxa25x())
+		ret = platform_device_register(&hwuart_device);
+
+	return ret;
+}
+
+subsys_initcall(pxa25x_init);
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index c64bab4..aa5bb02 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -19,10 +19,14 @@
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/arch/irqs.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/ohci.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /* Crystal clock: 13MHz */
 #define BASE_CLK	13000000
@@ -122,17 +126,6 @@
 
 #ifdef CONFIG_PM
 
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_MEM:
-	case PM_SUSPEND_STANDBY:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
 void pxa_cpu_pm_enter(suspend_state_t state)
 {
 	extern void pxa_cpu_standby(void);
@@ -140,9 +133,9 @@
 	extern void pxa_cpu_resume(void);
 
 	if (state == PM_SUSPEND_STANDBY)
-		CKEN = CKEN_MEMC | CKEN_OSTIMER | CKEN_LCD | CKEN_PWM0;
+		CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) | (1 << CKEN_LCD) | (1 << CKEN_PWM0);
 	else
-		CKEN = CKEN_MEMC | CKEN_OSTIMER;
+		CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER);
 
 	/* ensure voltage-change sequencer not initiated, which hangs */
 	PCFR &= ~PCFR_FVC;
@@ -162,6 +155,15 @@
 	}
 }
 
+static int pxa27x_pm_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
+}
+
+static struct pm_ops pxa27x_pm_ops = {
+	.enter		= pxa_pm_enter,
+	.valid		= pxa27x_pm_valid,
+};
 #endif
 
 /*
@@ -183,7 +185,7 @@
 	},
 };
 
-static struct platform_device ohci_device = {
+static struct platform_device pxaohci_device = {
 	.name		= "pxa27x-ohci",
 	.id		= -1,
 	.dev		= {
@@ -196,16 +198,62 @@
 
 void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
 {
-	ohci_device.dev.platform_data = info;
+	pxaohci_device.dev.platform_data = info;
 }
 
-static struct platform_device *devices[] __initdata = {
-	&ohci_device,
+static struct resource i2c_power_resources[] = {
+	{
+		.start	= 0x40f00180,
+		.end	= 0x40f001a3,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_PWRI2C,
+		.end	= IRQ_PWRI2C,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
+static struct platform_device pxai2c_power_device = {
+	.name		= "pxa2xx-i2c",
+	.id		= 1,
+	.resource	= i2c_power_resources,
+	.num_resources	= ARRAY_SIZE(i2c_power_resources),
+};
+
+static struct platform_device *devices[] __initdata = {
+	&pxamci_device,
+	&pxaudc_device,
+	&pxafb_device,
+	&ffuart_device,
+	&btuart_device,
+	&stuart_device,
+	&pxai2c_device,
+	&pxai2c_power_device,
+	&pxai2s_device,
+	&pxaficp_device,
+	&pxartc_device,
+	&pxaohci_device,
+};
+
+void __init pxa27x_init_irq(void)
+{
+	pxa_init_irq_low();
+	pxa_init_irq_high();
+	pxa_init_irq_gpio(128);
+}
+
 static int __init pxa27x_init(void)
 {
-	return platform_add_devices(devices, ARRAY_SIZE(devices));
+	int ret = 0;
+	if (cpu_is_pxa27x()) {
+		if ((ret = pxa_init_dma(32)))
+			return ret;
+#ifdef CONFIG_PM
+		pm_set_ops(&pxa27x_pm_ops);
+#endif
+		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+	}
+	return ret;
 }
 
 subsys_initcall(pxa27x_init);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 3cbac63..bae47e1 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -48,6 +48,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 /*
@@ -560,7 +561,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_spitz,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa27x_init_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -572,7 +573,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_spitz,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa27x_init_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -584,7 +585,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_spitz,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa27x_init_irq,
 	.init_machine	= akita_init,
 	.timer		= &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 5248abe..6f91fd2 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -30,11 +30,6 @@
 #include <asm/arch/pxa-regs.h>
 
 
-static inline unsigned long pxa_get_rtc_time(void)
-{
-	return RCNR;
-}
-
 static int pxa_set_rtc(void)
 {
 	unsigned long current_time = xtime.tv_sec;
@@ -122,10 +117,6 @@
 
 	set_rtc = pxa_set_rtc;
 
-	tv.tv_nsec = 0;
-	tv.tv_sec = pxa_get_rtc_time();
-	do_settimeofday(&tv);
-
 	OIER = 0;		/* disable any timer interrupts */
 	OSSR = 0xf;		/* clear status on all timers */
 	setup_irq(IRQ_OST0, &pxa_timer_irq);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 7273877..240fd04 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -42,7 +42,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /*
  * SCOOP Device
@@ -332,7 +332,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup          = fixup_tosa,
 	.map_io         = pxa_map_io,
-	.init_irq       = pxa_init_irq,
+	.init_irq       = pxa25x_init_irq,
 	.init_machine   = tosa_init,
 	.timer          = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 28c79bd..e4ba43b 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -49,6 +49,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /********************************************************************************************
  * ONBOARD FLASH
@@ -503,7 +504,7 @@
 	.boot_params	= TRIZEPS4_SDRAM_BASE + 0x100,
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 
diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c
index caf6b8b..c7bdf04 100644
--- a/arch/arm/mach-realview/localtimer.c
+++ b/arch/arm/mach-realview/localtimer.c
@@ -30,7 +30,7 @@
 /*
  * local_timer_ack: checks for a local timer interrupt.
  *
- * If a local timer interrupt has occured, acknowledge and return 1.
+ * If a local timer interrupt has occurred, acknowledge and return 1.
  * Otherwise, return 0.
  */
 int local_timer_ack(void)
diff --git a/arch/arm/mach-s3c2410/bast.h b/arch/arm/mach-s3c2410/bast.h
deleted file mode 100644
index e985437..0000000
--- a/arch/arm/mach-s3c2410/bast.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/bast.h
-extern void bast_init_irq(void);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index bc308ce..435adcc 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -160,7 +160,7 @@
 #endif
 };
 
-void __init amlm5900_map_io(void)
+static void __init amlm5900_map_io(void)
 {
 	s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
 	s3c24xx_init_clocks(0);
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index f01de80..8b52ea9 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -20,6 +20,8 @@
 #include <linux/platform_device.h>
 #include <linux/dm9000.h>
 
+#include <net/ax88796.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -409,6 +411,61 @@
 	.max_freq	= 130*1000,
 };
 
+/* Asix AX88796 10/100 ethernet controller */
+
+static struct ax_plat_data bast_asix_platdata = {
+	.flags		= AXFLG_MAC_FROMDEV,
+	.wordlength	= 2,
+	.dcr_val	= 0x48,
+	.rcr_val	= 0x40,
+};
+
+static struct resource bast_asix_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5 + BAST_PA_ASIXNET,
+		.end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20) - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
+		.end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
+		.flags = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start = IRQ_ASIX,
+		.end   = IRQ_ASIX,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device bast_device_asix = {
+	.name		= "ax88796",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(bast_asix_resource),
+	.resource	= bast_asix_resource,
+	.dev		= {
+		.platform_data = &bast_asix_platdata
+	}
+};
+
+/* Asix AX88796 10/100 ethernet controller parallel port */
+
+static struct resource bast_asixpp_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20),
+		.end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1b * 0x20) - 1,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device bast_device_axpp = {
+	.name		= "ax88796-pp",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(bast_asixpp_resource),
+	.resource	= bast_asixpp_resource,
+};
+
+/* LCD/VGA controller */
 
 static struct s3c2410fb_mach_info __initdata bast_lcd_info = {
 	.width		= 640,
@@ -453,6 +510,8 @@
 	&s3c_device_nand,
 	&bast_device_nor,
 	&bast_device_dm9k,
+	&bast_device_asix,
+	&bast_device_axpp,
 	&bast_sio,
 };
 
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 5ccd0be..5c9bcea 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index 9cc4253..d86e6f1 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/spi/spi.h>
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index d0f4695..668ccce 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -59,8 +59,8 @@
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels	= MAP(S3C2412_DMAREQSEL_SPI1TX),
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2412_SPI1  + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
index aafe0bc..782b581 100644
--- a/arch/arm/mach-s3c2412/s3c2412.c
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
@@ -29,6 +30,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
+#include <asm/arch/reset.h>
 #include <asm/arch/idle.h>
 
 #include <asm/arch/regs-clock.h>
@@ -37,6 +39,8 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-gpioj.h>
 #include <asm/arch/regs-dsc.h>
+#include <asm/arch/regs-spi.h>
+#include <asm/arch/regs-s3c2412.h>
 
 #include <asm/plat-s3c24xx/s3c2412.h>
 #include <asm/plat-s3c24xx/cpu.h>
@@ -74,6 +78,14 @@
 	s3c_device_sdi.name  = "s3c2412-sdi";
 	s3c_device_lcd.name  = "s3c2412-lcd";
 	s3c_device_nand.name = "s3c2412-nand";
+
+	/* spi channel related changes, s3c2412/13 specific */
+	s3c_device_spi0.name = "s3c2412-spi";
+	s3c_device_spi0.resource[0].end = S3C24XX_PA_SPI + 0x24;
+	s3c_device_spi1.name = "s3c2412-spi";
+	s3c_device_spi1.resource[0].start = S3C24XX_PA_SPI + S3C2412_SPI1;
+	s3c_device_spi1.resource[0].end = S3C24XX_PA_SPI + S3C2412_SPI1 + 0x24;
+
 }
 
 /* s3c2412_idle
@@ -97,6 +109,23 @@
 	cpu_do_idle();
 }
 
+static void s3c2412_hard_reset(void)
+{
+	/* errata "Watch-dog/Software Reset Problem" specifies that
+	 * this reset must be done with the SYSCLK sourced from
+	 * EXTCLK instead of FOUT to avoid a glitch in the reset
+	 * mechanism.
+	 *
+	 * See the watchdog section of the S3C2412 manual for more
+	 * information on this fix.
+	 */
+
+	__raw_writel(0x00, S3C2412_CLKSRC);
+	__raw_writel(S3C2412_SWRST_RESET, S3C2412_SWRST);
+
+	mdelay(1);
+}
+
 /* s3c2412_map_io
  *
  * register the standard cpu IO areas, and any passed in from the
@@ -113,6 +142,10 @@
 
 	s3c24xx_idle = s3c2412_idle;
 
+	/* set custom reset hook */
+
+	s3c24xx_reset_hook = s3c2412_hard_reset;
+
 	/* register our io-tables */
 
 	iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index b5d387e..29c163d 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -18,6 +18,9 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -42,6 +45,8 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
+#include <net/ax88796.h>
+
 #include <asm/plat-s3c24xx/clock.h>
 #include <asm/plat-s3c24xx/devs.h>
 #include <asm/plat-s3c24xx/cpu.h>
@@ -76,8 +81,8 @@
 	.length		= SZ_4K,
 	.type		= MT_DEVICE,
   }, {
-	.virtual	= (u32)ANUBIS_VA_CTRL2,
-	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL2),
+	.virtual	= (u32)ANUBIS_VA_IDREG,
+	.pfn		= __phys_to_pfn(ANUBIS_PA_IDREG),
 	.length		= SZ_4K,
 	.type		= MT_DEVICE,
   },
@@ -153,6 +158,29 @@
 	}
 };
 
+static struct mtd_partition anubis_default_nand_part_large[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= SZ_128K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "/boot",
+		.size	= SZ_4M - SZ_128K,
+		.offset	= SZ_128K,
+	},
+	[2] = {
+		.name	= "user1",
+		.offset	= SZ_4M,
+		.size	= SZ_32M - SZ_4M,
+	},
+	[3] = {
+		.name	= "user2",
+		.offset	= SZ_32M,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
 /* the Anubis has 3 selectable slots for nand-flash, the two
  * on-board chip areas, as well as the external slot.
  *
@@ -260,6 +288,104 @@
 	.resource	= anubis_ide1_resource,
 };
 
+/* Asix AX88796 10/100 ethernet controller */
+
+static struct ax_plat_data anubis_asix_platdata = {
+	.flags		= AXFLG_MAC_FROMDEV,
+	.wordlength	= 2,
+	.dcr_val	= 0x48,
+	.rcr_val	= 0x40,
+};
+
+static struct resource anubis_asix_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5,
+		.end   = S3C2410_CS5 + (0x20 * 0x20) -1,
+		.flags = IORESOURCE_MEM
+	},
+	[1] = {
+		.start = IRQ_ASIX,
+		.end   = IRQ_ASIX,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device anubis_device_asix = {
+	.name		= "ax88796",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(anubis_asix_resource),
+	.resource	= anubis_asix_resource,
+	.dev		= {
+		.platform_data = &anubis_asix_platdata,
+	}
+};
+
+/* SM501 */
+
+static struct resource anubis_sm501_resource[] = {
+	[0] = {
+		.start	= S3C2410_CS2,
+		.end	= S3C2410_CS2 + SZ_8M,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= S3C2410_CS2 + SZ_64M - SZ_2M,
+		.end	= S3C2410_CS2 + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		.start	= IRQ_EINT0,
+		.end	= IRQ_EINT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct sm501_initdata anubis_sm501_initdata = {
+	.gpio_high	= {
+		.set	= 0x3F000000,		/* 24bit panel */
+		.mask	= 0x0,
+	},
+	.misc_timing	= {
+		.set	= 0x010100,		/* SDRAM timing */
+		.mask	= 0x1F1F00,
+	},
+	.misc_control	= {
+		.set	= SM501_MISC_PNL_24BIT,
+		.mask	= 0,
+	},
+
+	/* set the SDRAM and bus clocks */
+	.mclk		= 72 * MHZ,
+	.m1xclk		= 144 * MHZ,
+};
+
+static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = {
+	[0] = {
+		.pin_scl	= 44,
+		.pin_sda	= 45,
+	},
+	[1] = {
+		.pin_scl	= 40,
+		.pin_sda	= 41,
+	},
+};
+
+static struct sm501_platdata anubis_sm501_platdata = {
+	.init		= &anubis_sm501_initdata,
+	.gpio_i2c	= anubis_sm501_gpio_i2c,
+	.gpio_i2c_nr	= ARRAY_SIZE(anubis_sm501_gpio_i2c),
+};
+
+static struct platform_device anubis_device_sm501 = {
+	.name		= "sm501",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(anubis_sm501_resource),
+	.resource	= anubis_sm501_resource,
+	.dev		= {
+		.platform_data = &anubis_sm501_platdata,
+	},
+};
+
 /* Standard Anubis devices */
 
 static struct platform_device *anubis_devices[] __initdata = {
@@ -271,6 +397,8 @@
 	&s3c_device_nand,
 	&anubis_device_ide0,
 	&anubis_device_ide1,
+	&anubis_device_asix,
+	&anubis_device_sm501,
 };
 
 static struct clk *anubis_clocks[] = {
@@ -304,8 +432,17 @@
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
 
-	/* ensure that the GPIO is setup */
-	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+	/* check for the newer revision boards with large page nand */
+
+	if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) {
+		printk(KERN_INFO "ANUBIS-B detected (revision %d)\n",
+		       __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK);
+		anubis_nand_sets[0].partitions = anubis_default_nand_part_large;
+		anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
+	} else {
+		/* ensure that the GPIO is setup */
+		s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+	}
 }
 
 static void __init anubis_init(void)
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 324f5a2..89f4c9c 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -16,6 +16,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/sysdev.h>
 #include <linux/serial_core.h>
 
 #include <asm/mach/arch.h>
@@ -45,7 +46,7 @@
 #include <asm/plat-s3c24xx/devs.h>
 #include <asm/plat-s3c24xx/cpu.h>
 
-/* onboard perihpheral map */
+/* onboard perihperal map */
 
 static struct map_desc osiris_iodesc[] __initdata = {
   /* ISA IO areas (may be over-written later) */
@@ -65,6 +66,11 @@
   /* CPLD control registers */
 
   {
+	  .virtual	= (u32)OSIRIS_VA_CTRL0,
+	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL0),
+	  .length	= SZ_16K,
+	  .type		= MT_DEVICE,
+  }, {
 	  .virtual	= (u32)OSIRIS_VA_CTRL1,
 	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL1),
 	  .length	= SZ_16K,
@@ -74,6 +80,11 @@
 	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL2),
 	  .length	= SZ_16K,
 	  .type		= MT_DEVICE,
+  }, {
+	  .virtual	= (u32)OSIRIS_VA_IDREG,
+	  .pfn		= __phys_to_pfn(OSIRIS_PA_IDREG),
+	  .length	= SZ_16K,
+	  .type		= MT_DEVICE,
   },
 };
 
@@ -155,6 +166,29 @@
 	}
 };
 
+static struct mtd_partition osiris_default_nand_part_large[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= SZ_128K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "/boot",
+		.size	= SZ_4M - SZ_128K,
+		.offset	= SZ_128K,
+	},
+	[2] = {
+		.name	= "user1",
+		.offset	= SZ_4M,
+		.size	= SZ_32M - SZ_4M,
+	},
+	[3] = {
+		.name	= "user2",
+		.offset	= SZ_32M,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
 /* the Osiris has 3 selectable slots for nand-flash, the two
  * on-board chip areas, as well as the external slot.
  *
@@ -195,13 +229,13 @@
 	pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n",
 		 slot, set, set->nr_map);
 
-	tmp = __raw_readb(OSIRIS_VA_CTRL1);
-	tmp &= ~OSIRIS_CTRL1_NANDSEL;
+	tmp = __raw_readb(OSIRIS_VA_CTRL0);
+	tmp &= ~OSIRIS_CTRL0_NANDSEL;
 	tmp |= slot;
 
-	pr_debug("osiris_nand: ctrl1 now %02x\n", tmp);
+	pr_debug("osiris_nand: ctrl0 now %02x\n", tmp);
 
-	__raw_writeb(tmp, OSIRIS_VA_CTRL1);
+	__raw_writeb(tmp, OSIRIS_VA_CTRL0);
 }
 
 static struct s3c2410_platform_nand osiris_nand_info = {
@@ -235,10 +269,45 @@
 	.resource	= osiris_pcmcia_resource,
 };
 
+/* Osiris power management device */
+
+#ifdef CONFIG_PM
+static unsigned char pm_osiris_ctrl0;
+
+static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
+{
+	pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0);
+	return 0;
+}
+
+static int osiris_pm_resume(struct sys_device *sd)
+{
+	if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8)
+		__raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1);
+
+	return 0;
+}
+
+#else
+#define osiris_pm_suspend NULL
+#define osiris_pm_resume NULL
+#endif
+
+static struct sysdev_class osiris_pm_sysclass = {
+	set_kset_name("mach-osiris"),
+	.suspend	= osiris_pm_suspend,
+	.resume		= osiris_pm_resume,
+};
+
+static struct sys_device osiris_pm_sysdev = {
+	.cls		= &osiris_pm_sysclass,
+};
+
 /* Standard Osiris devices */
 
 static struct platform_device *osiris_devices[] __initdata = {
 	&s3c_device_i2c,
+	&s3c_device_wdt,
 	&s3c_device_nand,
 	&osiris_pcmcia,
 };
@@ -276,18 +345,30 @@
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
 
+	/* check for the newer revision boards with large page nand */
+
+	if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) {
+		printk(KERN_INFO "OSIRIS-B detected (revision %d)\n",
+		       __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK);
+		osiris_nand_sets[0].partitions = osiris_default_nand_part_large;
+		osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
+	} else {
+		/* write-protect line to the NAND */
+		s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+	}
+
 	/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
 
 	local_irq_save(flags);
 	__raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
 	local_irq_restore(flags);
-
-	/* write-protect line to the NAND */
-	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
 }
 
 static void __init osiris_init(void)
 {
+	sysdev_class_register(&osiris_pm_sysclass);
+	sysdev_register(&osiris_pm_sysdev);
+
 	platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));
 };
 
@@ -299,5 +380,6 @@
 	.map_io		= osiris_map_io,
 	.init_machine	= osiris_init,
 	.init_irq	= s3c24xx_init_irq,
+	.init_machine	= osiris_init,
 	.timer		= &s3c24xx_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index c3cc4bf..866ff71 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/tty.h>
 #include <linux/console.h>
+#include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index 0b6e360..5840294 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -394,7 +394,7 @@
 	return 0;
 }
 
-struct clk clk_usb_bus_host = {
+static struct clk clk_usb_bus_host = {
 	.name		= "usb-bus-host-parent",
 	.id		= -1,
 	.parent		= &clk_esysclk,
@@ -747,6 +747,24 @@
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_USBD,
 	}, {
+		.name		= "hsmmc",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_HSMMC,
+	}, {
+		.name		= "cfc",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_CFC,
+	}, {
+		.name		= "ssmc",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_SSMC,
+	}, {
 		.name		= "timers",
 		.id		= -1,
 		.parent		= &clk_p,
@@ -791,7 +809,8 @@
 		.name		= "usb-bus-host",
 		.id		= -1,
 		.parent		= &clk_usb_bus_host,
-	}, {	.name		= "ac97",
+	}, {
+		.name		= "ac97",
 		.id		= -1,
 		.parent		= &clk_p,
 		.ctrlbit	= S3C2443_PCLKCON_AC97,
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
index b71ee53..b1eb709 100644
--- a/arch/arm/mach-s3c2443/mach-smdk2443.c
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -104,6 +104,7 @@
 static struct platform_device *smdk2443_devices[] __initdata = {
 	&s3c_device_wdt,
 	&s3c_device_i2c,
+	&s3c_device_hsmmc,
 };
 
 static void __init smdk2443_map_io(void)
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
index 11b1d0b..8d81171 100644
--- a/arch/arm/mach-s3c2443/s3c2443.c
+++ b/arch/arm/mach-s3c2443/s3c2443.c
@@ -63,6 +63,10 @@
 
 	s3c_device_nand.name = "s3c2412-nand";
 
+	/* change WDT IRQ number */
+	s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT;
+	s3c_device_wdt.resource[1].end   = IRQ_S3C2443_WDT;
+
 	return sysdev_register(&s3c2443_sysdev);
 }
 
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index d7c038a..3a0a1ee 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -139,12 +139,12 @@
 	return ret;
 }
 
-static struct sa1100_port_fns neponset_port_fns __initdata = {
+static struct sa1100_port_fns neponset_port_fns __devinitdata = {
 	.set_mctrl	= neponset_set_mctrl,
 	.get_mctrl	= neponset_get_mctrl,
 };
 
-static int neponset_probe(struct platform_device *dev)
+static int __devinit neponset_probe(struct platform_device *dev)
 {
 	sa1100_register_uart_fns(&neponset_port_fns);
 
@@ -185,28 +185,21 @@
 /*
  * LDM power management.
  */
+static unsigned int neponset_saved_state;
+
 static int neponset_suspend(struct platform_device *dev, pm_message_t state)
 {
 	/*
 	 * Save state.
 	 */
-	if (!dev->dev.power.saved_state)
-		dev->dev.power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
-	if (!dev->dev.power.saved_state)
-		return -ENOMEM;
-
-	*(unsigned int *)dev->dev.power.saved_state = NCR_0;
+	neponset_saved_state = NCR_0;
 
 	return 0;
 }
 
 static int neponset_resume(struct platform_device *dev)
 {
-	if (dev->dev.power.saved_state) {
-		NCR_0 = *(unsigned int *)dev->dev.power.saved_state;
-		kfree(dev->dev.power.saved_state);
-		dev->dev.power.saved_state = NULL;
-	}
+	NCR_0 = neponset_saved_state;
 
 	return 0;
 }
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index d674cf3..01a37d3 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -57,12 +57,7 @@
 static int sa11x0_pm_enter(suspend_state_t state)
 {
 	unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
-	struct timespec delta, rtc;
 
-	/* preserve current time */
-	rtc.tv_sec = RCNR;
-	rtc.tv_nsec = 0;
-	save_time_delta(&delta, &rtc);
 	gpio = GPLR;
 
 	/* save vital registers */
@@ -119,10 +114,6 @@
 	 */
 	PSSR = PSSR_PH;
 
-	/* restore current time */
-	rtc.tv_sec = RCNR;
-	restore_time_delta(&delta, &rtc);
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 416e277..fdf7b01 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -21,25 +21,6 @@
 #define RTC_DEF_DIVIDER		(32768 - 1)
 #define RTC_DEF_TRIM            0
 
-static unsigned long __init sa1100_get_rtc_time(void)
-{
-	/*
-	 * According to the manual we should be able to let RTTR be zero
-	 * and then a default diviser for a 32.768KHz clock is used.
-	 * Apparently this doesn't work, at least for my SA1110 rev 5.
-	 * If the clock divider is uninitialized then reset it to the
-	 * default value to get the 1Hz clock.
-	 */
-	if (RTTR == 0) {
-		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-		printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
-		/* The current RTC value probably doesn't make sense either */
-		RCNR = 0;
-		return 0;
-	}
-	return RCNR;
-}
-
 static int sa1100_set_rtc(void)
 {
 	unsigned long current_time = xtime.tv_sec;
@@ -117,15 +98,10 @@
 
 static void __init sa1100_timer_init(void)
 {
-	struct timespec tv;
 	unsigned long flags;
 
 	set_rtc = sa1100_set_rtc;
 
-	tv.tv_nsec = 0;
-	tv.tv_sec = sa1100_get_rtc_time();
-	do_settimeofday(&tv);
-
 	OIER = 0;		/* disable any timer interrupts */
 	OSSR = 0xf;		/* clear status on all timers */
 	setup_irq(IRQ_OST0, &sa1100_timer_irq);
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index ba58223..ca82901 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -117,7 +117,10 @@
 	} else {
 		switch (size) {
 		case 1:
-			v = __raw_readb(addr);
+			v = __raw_readl(addr);
+			if (where & 2) v >>= 16;
+			if (where & 1) v >>= 8;
+ 			v &= 0xff;
 			break;
 
 		case 2:
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 15f0284..e7904bc9 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -351,6 +351,7 @@
 	select CPU_CACHE_V6
 	select CPU_CACHE_VIPT
 	select CPU_CP15_MMU
+	select CPU_HAS_ASID
 	select CPU_COPY_V6 if MMU
 	select CPU_TLB_V6 if MMU
 
@@ -376,8 +377,9 @@
 	select CPU_CACHE_V7
 	select CPU_CACHE_VIPT
 	select CPU_CP15_MMU
+	select CPU_HAS_ASID
 	select CPU_COPY_V6 if MMU
-	select CPU_TLB_V6 if MMU
+	select CPU_TLB_V7 if MMU
 
 # Figure out what processor architecture version we should be using.
 # This defines the compiler instruction set which depends on the machine type.
@@ -496,8 +498,17 @@
 config CPU_TLB_V6
 	bool
 
+config CPU_TLB_V7
+	bool
+
 endif
 
+config CPU_HAS_ASID
+	bool
+	help
+	  This indicates whether the CPU has the ASID register; used to
+	  tag TLB and possibly cache entries.
+
 config CPU_CP15
 	bool
 	help
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index b5bd335..7627027 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -46,6 +46,7 @@
 obj-$(CONFIG_CPU_TLB_V4WB)	+= tlb-v4wb.o
 obj-$(CONFIG_CPU_TLB_V4WBI)	+= tlb-v4wbi.o
 obj-$(CONFIG_CPU_TLB_V6)	+= tlb-v6.o
+obj-$(CONFIG_CPU_TLB_V7)	+= tlb-v7.o
 
 obj-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o
 obj-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 19ca333..074b7cb 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1995  Linus Torvalds
  *  Modifications for ARM processor (c) 1995-2001 Russell King
- *  Thumb aligment fault fixups (c) 2004 MontaVista Software, Inc.
+ *  Thumb alignment fault fixups (c) 2004 MontaVista Software, Inc.
  *  - Adapted from gdb/sim/arm/thumbemu.c -- Thumb instruction emulation.
  *    Copyright (C) 1996, Cygnus Software Technologies Ltd.
  *
@@ -630,7 +630,7 @@
 
 	fs = get_fs();
 	set_fs(KERNEL_DS);
-	if thumb_mode(regs) {
+	if (thumb_mode(regs)) {
 		fault = __get_user(tinstr, (u16 *)(instrptr & ~1));
 		if (!(fault))
 			instr = thumb2arm(tinstr);
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index d6167ad..7595277 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -280,7 +280,10 @@
 	if (!type)
 		return NULL;
 
-	size = PAGE_ALIGN(size);
+	/*
+	 * Page align the mapping size, taking account of any offset.
+	 */
+	size = PAGE_ALIGN(offset + size);
 
  	area = get_vm_area(size, VM_IOREMAP);
  	if (!area)
@@ -325,11 +328,6 @@
 	if (!size || last_addr < phys_addr)
 		return NULL;
 
-	/*
- 	 * Page align the mapping size
-	 */
-	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
  	return __arm_ioremap_pfn(pfn, offset, size, mtype);
 }
 EXPORT_SYMBOL(__arm_ioremap);
@@ -346,7 +344,7 @@
 #ifndef CONFIG_SMP
 	/*
 	 * If this is a section based mapping we need to handle it
-	 * specially as the VM subysystem does not know how to handle
+	 * specially as the VM subsystem does not know how to handle
 	 * such a beast. We need the lock here b/c we need to clear
 	 * all the mappings before the area can be reclaimed
 	 * by someone else.
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 2c4c242..2728b0e 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -5,7 +5,7 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/shm.h>
-
+#include <linux/sched.h>
 #include <asm/system.h>
 
 #define COLOUR_ALIGN(addr,pgoff)		\
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 2ba1530..3b5e47d 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -92,7 +92,7 @@
 };
 
 /*
- * These are useful for identifing cache coherency
+ * These are useful for identifying cache coherency
  * problems by allowing the cache or the cache and
  * writebuffer to be turned off.  (Note: the write
  * buffer should not be on and the cache off).
@@ -527,9 +527,9 @@
 		return;
 	}
 
-	addr = md->virtual;
+	addr = md->virtual & PAGE_MASK;
 	phys = (unsigned long)__pfn_to_phys(md->pfn);
-	length = PAGE_ALIGN(md->length);
+	length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
 
 	if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
 		printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index dd823dd..718f478 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -256,7 +256,7 @@
 	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
 	.long	cpu_v7_name
 	.long	v7_processor_functions
-	.long	v6wbi_tlb_fns
+	.long	v7wbi_tlb_fns
 	.long	v6_user_fns
 	.long	v7_cache_fns
 	.size	__v7_proc_info, . - __v7_proc_info
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
new file mode 100644
index 0000000..b56dda8
--- /dev/null
+++ b/arch/arm/mm/tlb-v7.S
@@ -0,0 +1,88 @@
+/*
+ *  linux/arch/arm/mm/tlb-v7.S
+ *
+ *  Copyright (C) 1997-2002 Russell King
+ *  Modified for ARMv7 by Catalin Marinas
+ *
+ * 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.
+ *
+ *  ARM architecture version 6 TLB handling functions.
+ *  These assume a split I/D TLB.
+ */
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+#include "proc-macros.S"
+
+/*
+ *	v7wbi_flush_user_tlb_range(start, end, vma)
+ *
+ *	Invalidate a range of TLB entries in the specified address space.
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ *	- vma   - vma_struct describing address range
+ *
+ *	It is assumed that:
+ *	- the "Invalidate single entry" instruction will invalidate
+ *	  both the I and the D TLBs on Harvard-style TLBs
+ */
+ENTRY(v7wbi_flush_user_tlb_range)
+	vma_vm_mm r3, r2			@ get vma->vm_mm
+	mmid	r3, r3				@ get vm_mm->context.id
+	dsb
+	mov	r0, r0, lsr #PAGE_SHIFT		@ align address
+	mov	r1, r1, lsr #PAGE_SHIFT
+	asid	r3, r3				@ mask ASID
+	orr	r0, r3, r0, lsl #PAGE_SHIFT	@ Create initial MVA
+	mov	r1, r1, lsl #PAGE_SHIFT
+	vma_vm_flags r2, r2			@ get vma->vm_flags
+1:
+	mcr	p15, 0, r0, c8, c6, 1		@ TLB invalidate D MVA (was 1)
+	tst	r2, #VM_EXEC			@ Executable area ?
+	mcrne	p15, 0, r0, c8, c5, 1		@ TLB invalidate I MVA (was 1)
+	add	r0, r0, #PAGE_SZ
+	cmp	r0, r1
+	blo	1b
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c5, 6		@ flush BTAC/BTB
+	dsb
+	mov	pc, lr
+
+/*
+ *	v7wbi_flush_kern_tlb_range(start,end)
+ *
+ *	Invalidate a range of kernel TLB entries
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ */
+ENTRY(v7wbi_flush_kern_tlb_range)
+	dsb
+	mov	r0, r0, lsr #PAGE_SHIFT		@ align address
+	mov	r1, r1, lsr #PAGE_SHIFT
+	mov	r0, r0, lsl #PAGE_SHIFT
+	mov	r1, r1, lsl #PAGE_SHIFT
+1:
+	mcr	p15, 0, r0, c8, c6, 1		@ TLB invalidate D MVA
+	mcr	p15, 0, r0, c8, c5, 1		@ TLB invalidate I MVA
+	add	r0, r0, #PAGE_SZ
+	cmp	r0, r1
+	blo	1b
+	mov	r2, #0
+	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
+	dsb
+	isb
+	mov	pc, lr
+
+	.section ".text.init", #alloc, #execinstr
+
+	.type	v7wbi_tlb_fns, #object
+ENTRY(v7wbi_tlb_fns)
+	.long	v7wbi_flush_user_tlb_range
+	.long	v7wbi_flush_kern_tlb_range
+	.long	v6wbi_tlb_flags
+	.size	v7wbi_tlb_fns, . - v7wbi_tlb_fns
diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h
index 0a30674..260fe29 100644
--- a/arch/arm/nwfpe/softfloat.h
+++ b/arch/arm/nwfpe/softfloat.h
@@ -273,4 +273,7 @@
 extern flag float32_is_nan( float32 a );
 extern flag float64_is_nan( float64 a );
 
+extern int32 float64_to_uint32( struct roundingData *roundData, float64 a );
+extern int32 float64_to_uint32_round_to_zero( float64 a );
+
 #endif
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
index 8985007..75bae06 100644
--- a/arch/arm/oprofile/op_model_mpcore.c
+++ b/arch/arm/oprofile/op_model_mpcore.c
@@ -200,8 +200,10 @@
 	data.fn = fn;
 	data.ret = 0;
 
+	preempt_disable();
 	smp_call_function(em_func, &data, 1, 1);
 	em_func(&data);
+	preempt_enable();
 
 	return data.ret;
 }
@@ -257,8 +259,13 @@
  */
 static void em_route_irq(int irq, unsigned int cpu)
 {
-	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
-	irq_desc[irq].chip->set_affinity(irq, cpumask_of_cpu(cpu));
+	struct irq_desc *desc = irq_desc + irq;
+	cpumask_t mask = cpumask_of_cpu(cpu);
+
+	spin_lock_irq(&desc->lock);
+	desc->affinity = mask;
+	desc->chip->set_affinity(irq, mask);
+	spin_unlock_irq(&desc->lock);
 }
 
 static int em_setup(void)
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
index 4d2b1da..36bff03 100644
--- a/arch/arm/plat-iop/Makefile
+++ b/arch/arm/plat-iop/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_ARCH_IOP32X) += time.o
 obj-$(CONFIG_ARCH_IOP32X) += io.o
 obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+obj-$(CONFIG_ARCH_IOP32X) += adma.o
 
 # IOP33X
 obj-$(CONFIG_ARCH_IOP33X) += gpio.o
@@ -21,6 +22,7 @@
 obj-$(CONFIG_ARCH_IOP33X) += time.o
 obj-$(CONFIG_ARCH_IOP33X) += io.o
 obj-$(CONFIG_ARCH_IOP33X) += cp6.o
+obj-$(CONFIG_ARCH_IOP33X) += adma.o
 
 # IOP13XX
 obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
diff --git a/arch/arm/plat-iop/adma.c b/arch/arm/plat-iop/adma.c
new file mode 100644
index 0000000..53c5e9a
--- /dev/null
+++ b/arch/arm/plat-iop/adma.c
@@ -0,0 +1,209 @@
+/*
+ * platform device definitions for the iop3xx dma/xor engines
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/platform_device.h>
+#include <asm/hardware/iop3xx.h>
+#include <linux/dma-mapping.h>
+#include <asm/arch/adma.h>
+#include <asm/hardware/iop_adma.h>
+
+#ifdef CONFIG_ARCH_IOP32X
+#define IRQ_DMA0_EOT IRQ_IOP32X_DMA0_EOT
+#define IRQ_DMA0_EOC IRQ_IOP32X_DMA0_EOC
+#define IRQ_DMA0_ERR IRQ_IOP32X_DMA0_ERR
+
+#define IRQ_DMA1_EOT IRQ_IOP32X_DMA1_EOT
+#define IRQ_DMA1_EOC IRQ_IOP32X_DMA1_EOC
+#define IRQ_DMA1_ERR IRQ_IOP32X_DMA1_ERR
+
+#define IRQ_AA_EOT IRQ_IOP32X_AA_EOT
+#define IRQ_AA_EOC IRQ_IOP32X_AA_EOC
+#define IRQ_AA_ERR IRQ_IOP32X_AA_ERR
+#endif
+#ifdef CONFIG_ARCH_IOP33X
+#define IRQ_DMA0_EOT IRQ_IOP33X_DMA0_EOT
+#define IRQ_DMA0_EOC IRQ_IOP33X_DMA0_EOC
+#define IRQ_DMA0_ERR IRQ_IOP33X_DMA0_ERR
+
+#define IRQ_DMA1_EOT IRQ_IOP33X_DMA1_EOT
+#define IRQ_DMA1_EOC IRQ_IOP33X_DMA1_EOC
+#define IRQ_DMA1_ERR IRQ_IOP33X_DMA1_ERR
+
+#define IRQ_AA_EOT IRQ_IOP33X_AA_EOT
+#define IRQ_AA_EOC IRQ_IOP33X_AA_EOC
+#define IRQ_AA_ERR IRQ_IOP33X_AA_ERR
+#endif
+/* AAU and DMA Channels */
+static struct resource iop3xx_dma_0_resources[] = {
+	[0] = {
+		.start = IOP3XX_DMA_PHYS_BASE(0),
+		.end = IOP3XX_DMA_UPPER_PA(0),
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_DMA0_EOT,
+		.end = IRQ_DMA0_EOT,
+		.flags = IORESOURCE_IRQ
+	},
+	[2] = {
+		.start = IRQ_DMA0_EOC,
+		.end = IRQ_DMA0_EOC,
+		.flags = IORESOURCE_IRQ
+	},
+	[3] = {
+		.start = IRQ_DMA0_ERR,
+		.end = IRQ_DMA0_ERR,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource iop3xx_dma_1_resources[] = {
+	[0] = {
+		.start = IOP3XX_DMA_PHYS_BASE(1),
+		.end = IOP3XX_DMA_UPPER_PA(1),
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_DMA1_EOT,
+		.end = IRQ_DMA1_EOT,
+		.flags = IORESOURCE_IRQ
+	},
+	[2] = {
+		.start = IRQ_DMA1_EOC,
+		.end = IRQ_DMA1_EOC,
+		.flags = IORESOURCE_IRQ
+	},
+	[3] = {
+		.start = IRQ_DMA1_ERR,
+		.end = IRQ_DMA1_ERR,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+
+static struct resource iop3xx_aau_resources[] = {
+	[0] = {
+		.start = IOP3XX_AAU_PHYS_BASE,
+		.end = IOP3XX_AAU_UPPER_PA,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_AA_EOT,
+		.end = IRQ_AA_EOT,
+		.flags = IORESOURCE_IRQ
+	},
+	[2] = {
+		.start = IRQ_AA_EOC,
+		.end = IRQ_AA_EOC,
+		.flags = IORESOURCE_IRQ
+	},
+	[3] = {
+		.start = IRQ_AA_ERR,
+		.end = IRQ_AA_ERR,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static u64 iop3xx_adma_dmamask = DMA_32BIT_MASK;
+
+static struct iop_adma_platform_data iop3xx_dma_0_data = {
+	.hw_id = DMA0_ID,
+	.pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop3xx_dma_1_data = {
+	.hw_id = DMA1_ID,
+	.pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop3xx_aau_data = {
+	.hw_id = AAU_ID,
+	.pool_size = 3 * PAGE_SIZE,
+};
+
+struct platform_device iop3xx_dma_0_channel = {
+	.name = "iop-adma",
+	.id = 0,
+	.num_resources = 4,
+	.resource = iop3xx_dma_0_resources,
+	.dev = {
+		.dma_mask = &iop3xx_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &iop3xx_dma_0_data,
+	},
+};
+
+struct platform_device iop3xx_dma_1_channel = {
+	.name = "iop-adma",
+	.id = 1,
+	.num_resources = 4,
+	.resource = iop3xx_dma_1_resources,
+	.dev = {
+		.dma_mask = &iop3xx_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &iop3xx_dma_1_data,
+	},
+};
+
+struct platform_device iop3xx_aau_channel = {
+	.name = "iop-adma",
+	.id = 2,
+	.num_resources = 4,
+	.resource = iop3xx_aau_resources,
+	.dev = {
+		.dma_mask = &iop3xx_adma_dmamask,
+		.coherent_dma_mask = DMA_64BIT_MASK,
+		.platform_data = (void *) &iop3xx_aau_data,
+	},
+};
+
+static int __init iop3xx_adma_cap_init(void)
+{
+	#ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
+	dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
+	dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
+	#else
+	dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
+	dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_0_data.cap_mask);
+	dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
+	#endif
+
+	#ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
+	dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
+	dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
+	#else
+	dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
+	dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_1_data.cap_mask);
+	dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
+	#endif
+
+	#ifdef CONFIG_ARCH_IOP32X /* the 32x AAU does not perform zero sum */
+	dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
+	dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
+	dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
+	#else
+	dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
+	dma_cap_set(DMA_ZERO_SUM, iop3xx_aau_data.cap_mask);
+	dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
+	dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
+	#endif
+
+	return 0;
+}
+
+arch_initcall(iop3xx_adma_cap_init);
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
index e2744b7..2b5aa11 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/plat-iop/pci.c
@@ -19,6 +19,7 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/signal.h>
 #include <asm/system.h>
 #include <asm/hardware.h>
 #include <asm/mach/pci.h>
@@ -85,10 +86,10 @@
 
 /*
  * Simply write the address register and read the configuration
- * data.  Note that the 4 nop's ensure that we are able to handle
+ * data.  Note that the 4 nops ensure that we are able to handle
  * a delayed abort (in theory.)
  */
-static inline u32 iop3xx_read(unsigned long addr)
+static u32 iop3xx_read(unsigned long addr)
 {
 	u32 val;
 
@@ -321,7 +322,7 @@
 /* Flag to determine whether the ATU is initialized and the PCI bus scanned */
 int init_atu;
 
-void iop3xx_pci_preinit(void)
+void __init iop3xx_pci_preinit(void)
 {
 	if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
 		iop3xx_atu_disable();
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index dd8708a..7987aa6 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -73,7 +73,7 @@
 	}
 	if (info != NULL) {
 		/* Check the length as a lame attempt to check for
-		 * binary inconsistancy. */
+		 * binary inconsistency. */
 		if (len != NO_LENGTH_CHECK) {
 			/* Word-align len */
 			if (len & 0x03)
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 55a4d3b..88d5b6d 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1172,7 +1172,7 @@
 		break;
 	default:
 		BUG();
-		return;	/* Supress warning about uninitialized vars */
+		return;	/* Suppress warning about uninitialized vars */
 	}
 
 	if (omap_dma_in_1510_mode()) {
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index bc46f33..1f23f04 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -59,8 +59,8 @@
 
 /*
  * Depending on the target RAMFS firewall setup, the public usable amount of
- * SRAM varies.  The default accessable size for all device types is 2k. A GP
- * device allows ARM11 but not other initators for full size. This
+ * SRAM varies.  The default accessible size for all device types is 2k. A GP
+ * device allows ARM11 but not other initiators for full size. This
  * functionality seems ok until some nice security API happens.
  */
 static int is_sram_locked(void)
@@ -71,7 +71,7 @@
 		type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK;
 
 	if (type == GP_DEVICE) {
-		/* RAMFW: R/W access to all initators for all qualifier sets */
+		/* RAMFW: R/W access to all initiators for all qualifier sets */
 		if (cpu_is_omap242x()) {
 			__raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */
 			__raw_writel(0xCFDE, VA_READPERM0);  /* all i-read */
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index 25489aa..a5aedf9 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -177,7 +177,7 @@
 
 	/* NOTE:  SPEED and SUSP aren't configured here.  OTG hosts
 	 * may be able to use I2C requests to set those bits along
-	 * with VBUS switching and overcurrent detction.
+	 * with VBUS switching and overcurrent detection.
 	 */
 
 	if (cpu_class_is_omap1() && nwires != 6)
diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c
index 908efa7..7ed19b2 100644
--- a/arch/arm/plat-s3c24xx/common-smdk.c
+++ b/arch/arm/plat-s3c24xx/common-smdk.c
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/sysdev.h>
 #include <linux/platform_device.h>
 
 #include <linux/mtd/mtd.h>
@@ -29,6 +30,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -192,6 +194,9 @@
 	s3c2410_gpio_setpin(S3C2410_GPF6, 1);
 	s3c2410_gpio_setpin(S3C2410_GPF7, 1);
 
+	if (machine_is_smdk2443())
+		smdk_nand_info.twrph0 = 50;
+
 	s3c_device_nand.dev.platform_data = &smdk_nand_info;
 
 	platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 0fe53b3..5875da0 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -33,6 +33,7 @@
 
 #include <asm/plat-s3c24xx/devs.h>
 #include <asm/plat-s3c24xx/cpu.h>
+#include <asm/arch/regs-spi.h>
 
 /* Serial port registrations */
 
@@ -402,6 +403,36 @@
 
 EXPORT_SYMBOL(s3c_device_sdi);
 
+/* High-speed MMC/SD */
+
+static struct resource s3c_hsmmc_resource[] = {
+	[0] = {
+		.start = S3C2443_PA_HSMMC,
+		.end   = S3C2443_PA_HSMMC + S3C2443_SZ_HSMMC - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3C2443_HSMMC,
+		.end   = IRQ_S3C2443_HSMMC,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_hsmmc = {
+	.name		  = "s3c-sdhci",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_hsmmc_resource),
+	.resource	  = s3c_hsmmc_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_hsmmc_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+
+
 /* SPI (0) */
 
 static struct resource s3c_spi0_resource[] = {
@@ -437,8 +468,8 @@
 
 static struct resource s3c_spi1_resource[] = {
 	[0] = {
-		.start = S3C24XX_PA_SPI + 0x20,
-		.end   = S3C24XX_PA_SPI + 0x20 + 0x1f,
+		.start = S3C24XX_PA_SPI + S3C2410_SPI1,
+		.end   = S3C24XX_PA_SPI + S3C2410_SPI1 + 0x1f,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 6f03c93..08d80f2 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1153,7 +1153,7 @@
  *
  * hwcfg:     the value for xxxSTCn register,
  *            bit 0: 0=increment pointer, 1=leave pointer
- *            bit 1: 0=soucre is AHB, 1=soucre is APB
+ *            bit 1: 0=source is AHB, 1=source is APB
  *
  * devaddr:   physical address of the source
 */
diff --git a/arch/arm/plat-s3c24xx/pm-simtec.c b/arch/arm/plat-s3c24xx/pm-simtec.c
index bd965f2..cb0b3a4 100644
--- a/arch/arm/plat-s3c24xx/pm-simtec.c
+++ b/arch/arm/plat-s3c24xx/pm-simtec.c
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/sysdev.h>
 #include <linux/device.h>
 
 #include <asm/mach/arch.h>
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
index c6b03f8..5692ecc 100644
--- a/arch/arm/plat-s3c24xx/pm.c
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -555,7 +555,7 @@
 	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
 	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
 
-	/* call cpu specific preperation */
+	/* call cpu specific preparation */
 
 	pm_cpu_prep();
 
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index ca2a5ad..806ce26 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -29,6 +29,10 @@
 	add	r10, r10, #TI_VFPSTATE	@ r10 = workspace
 	ldr	pc, [r4]		@ call VFP entry point
 
+ENTRY(vfp_null_entry)
+	mov	pc, lr
+ENDPROC(vfp_null_entry)
+
 .LCvfp:
 	.word	vfp_vector
 
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index f1e5951..1106b5f 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -26,8 +26,9 @@
  */
 void vfp_testing_entry(void);
 void vfp_support_entry(void);
+void vfp_null_entry(void);
 
-void (*vfp_vector)(void) = vfp_testing_entry;
+void (*vfp_vector)(void) = vfp_null_entry;
 union vfp_state *last_VFP_context[NR_CPUS];
 
 /*
@@ -321,8 +322,10 @@
 	 * The handler is already setup to just log calls, so
 	 * we just need to read the VFPSID register.
 	 */
+	vfp_vector = vfp_testing_entry;
 	vfpsid = fmrx(FPSID);
 	barrier();
+	vfp_vector = vfp_null_entry;
 
 	printk(KERN_INFO "VFP support v0.3: ");
 	if (VFP_arch) {
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 20688bc..9044f33 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -17,6 +17,9 @@
 	bool
 	default y
 
+config NO_DMA
+	def_bool y
+
 config ARCH_ACORN
         bool
         default y
diff --git a/arch/arm26/defconfig b/arch/arm26/defconfig
index c4a8970..2b7d44b 100644
--- a/arch/arm26/defconfig
+++ b/arch/arm26/defconfig
@@ -248,7 +248,6 @@
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index 4169279..0fefb869 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -531,7 +531,6 @@
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long tmp;
 	int ret;
 
 	switch (request) {
@@ -540,12 +539,7 @@
 		 */
 		case PTRACE_PEEKTEXT:
 		case PTRACE_PEEKDATA:
-			ret = access_process_vm(child, addr, &tmp,
-						sizeof(unsigned long), 0);
-			if (ret == sizeof(unsigned long))
-				ret = put_user(tmp, (unsigned long *) data);
-			else
-				ret = -EIO;
+			ret = generic_ptrace_peekdata(child, addr, data);
 			break;
 
 		case PTRACE_PEEKUSR:
@@ -557,12 +551,7 @@
 		 */
 		case PTRACE_POKETEXT:
 		case PTRACE_POKEDATA:
-			ret = access_process_vm(child, addr, &data,
-						sizeof(unsigned long), 1);
-			if (ret == sizeof(unsigned long))
-				ret = 0;
-			else
-				ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
 		case PTRACE_POKEUSR:
diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c
index d594fb5..2911e2e 100644
--- a/arch/arm26/kernel/traps.c
+++ b/arch/arm26/kernel/traps.c
@@ -185,6 +185,7 @@
 	printk("Internal error: %s: %x\n", str, err);
 	printk("CPU: %d\n", smp_processor_id());
 	show_regs(regs);
+	add_taint(TAINT_DIE);
 	printk("Process %s (pid: %d, stack limit = 0x%p)\n",
 		current->comm, current->pid, end_of_stack(tsk));
 
diff --git a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
index 046a850..4ec715c 100644
--- a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
+++ b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
@@ -64,7 +64,7 @@
 
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
-			*(.text)
+			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT       /* FIXME - borrowed from arm32 - check*/
 			*(.fixup)
@@ -111,7 +111,7 @@
 		/*
 		 * and the usual data section
 		 */
-		*(.data)
+		DATA_DATA
 		CONSTRUCTORS
 
 		*(.init.data)
diff --git a/arch/arm26/kernel/vmlinux-arm26.lds.in b/arch/arm26/kernel/vmlinux-arm26.lds.in
index 1d2949e..6c44f6a 100644
--- a/arch/arm26/kernel/vmlinux-arm26.lds.in
+++ b/arch/arm26/kernel/vmlinux-arm26.lds.in
@@ -65,7 +65,7 @@
 
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
-			*(.text)
+			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
 			*(.fixup)
@@ -106,7 +106,7 @@
 		/*
 		 * and the usual data section
 		 */
-		*(.data)
+		DATA_DATA
 		CONSTRUCTORS
 
 		_edata = .;
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
index 562fac1..36e7ee3 100644
--- a/arch/arm26/mm/init.c
+++ b/arch/arm26/mm/init.c
@@ -33,9 +33,6 @@
 
 #include <asm/map.h>
 
-
-#define TABLE_SIZE	PTRS_PER_PTE * sizeof(pte_t))
-
 struct mmu_gather mmu_gathers[NR_CPUS];
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c
index 9bc37d4..6c4dc0a 100644
--- a/arch/avr32/boards/atngw100/setup.c
+++ b/arch/avr32/boards/atngw100/setup.c
@@ -94,9 +94,6 @@
 	clk_put(pclk);
 }
 
-struct platform_device *at32_usart_map[1];
-unsigned int at32_nr_usarts = 1;
-
 void __init setup_board(void)
 {
 	at32_map_usart(1, 0);	/* USART 1: /dev/ttyS0, DB9 */
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index fe1dbe2..e253e86 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -42,6 +42,7 @@
 		.modalias	= "ltv350qv",
 		.max_speed_hz	= 16000000,
 		.chip_select	= 1,
+		.mode		= SPI_MODE_3,
 	},
 };
 
diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig
index c254ffc..49493ad 100644
--- a/arch/avr32/configs/atngw100_defconfig
+++ b/arch/avr32/configs/atngw100_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc6
-# Thu Apr 12 16:35:07 2007
+# Linux kernel version: 2.6.22-rc5
+# Sat Jun 23 15:40:05 2007
 #
 CONFIG_AVR32=y
 CONFIG_GENERIC_GPIO=y
@@ -40,6 +40,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -57,14 +58,20 @@
 CONFIG_ELF_CORE=y
 # CONFIG_BASE_FULL is not set
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -148,6 +155,7 @@
 #
 # Bus options
 #
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -168,7 +176,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -212,14 +219,11 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
 CONFIG_INET6_AH=y
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
@@ -242,8 +246,6 @@
 #
 # CONFIG_NETFILTER_NETLINK is not set
 CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CT_ACCT=y
 CONFIG_NF_CONNTRACK_MARK=y
@@ -357,20 +359,8 @@
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_RAW=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -397,7 +387,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -417,10 +416,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
@@ -464,7 +459,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -492,16 +486,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -530,10 +521,7 @@
 #
 # Misc devices
 #
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -542,10 +530,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -554,19 +538,6 @@
 # CONFIG_MD is not set
 
 #
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -574,10 +545,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -586,27 +553,14 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_MACB=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 CONFIG_PPP=m
 # CONFIG_PPP_MULTILINK is not set
@@ -671,15 +625,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -687,10 +636,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -710,17 +655,13 @@
 # SPI Protocol Masters
 #
 # CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
 
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
 # Multifunction device drivers
@@ -731,16 +672,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -763,10 +707,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -809,14 +749,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -911,6 +843,7 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
@@ -993,11 +926,9 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1044,6 +975,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
@@ -1072,6 +1004,7 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
@@ -1083,3 +1016,4 @@
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index 77dace9..3b977fd 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -1,9 +1,10 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc6
-# Fri Jan 26 13:12:59 2007
+# Linux kernel version: 2.6.22-rc5
+# Sat Jun 23 15:32:08 2007
 #
 CONFIG_AVR32=y
+CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -13,6 +14,7 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_BUG=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -30,19 +32,22 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_TASKSTATS=y
 CONFIG_TASK_DELAY_ACCT=y
+# CONFIG_TASK_XACCT is not set
 # CONFIG_UTS_NS is not set
 CONFIG_AUDIT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-# CONFIG_TASK_XACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
@@ -55,14 +60,20 @@
 CONFIG_ELF_CORE=y
 # CONFIG_BASE_FULL is not set
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -105,7 +116,15 @@
 CONFIG_CPU_AT32AP7000=y
 CONFIG_BOARD_ATSTK1002=y
 CONFIG_BOARD_ATSTK1000=y
+# CONFIG_BOARD_ATNGW100 is not set
 CONFIG_LOADER_U_BOOT=y
+
+#
+# Atmel AVR32 AP options
+#
+# CONFIG_AP7000_32_BIT_SMC is not set
+CONFIG_AP7000_16_BIT_SMC=y
+# CONFIG_AP7000_8_BIT_SMC is not set
 CONFIG_LOAD_ADDRESS=0x10000000
 CONFIG_ENTRY_ADDRESS=0x90000000
 CONFIG_PHYS_OFFSET=0x10000000
@@ -127,6 +146,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 # CONFIG_OWNERSHIP_TRACE is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
@@ -138,6 +158,7 @@
 #
 # Bus options
 #
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -158,7 +179,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -194,20 +214,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -233,7 +241,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -246,16 +263,13 @@
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
@@ -299,7 +313,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -325,16 +338,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -344,6 +354,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -356,18 +367,13 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -376,10 +382,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -388,19 +390,6 @@
 # CONFIG_MD is not set
 
 #
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -408,10 +397,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -420,27 +405,14 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_MACB=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 CONFIG_PPP=m
 # CONFIG_PPP_MULTILINK is not set
@@ -505,15 +477,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -521,10 +488,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -537,31 +500,33 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
 # Sound
 #
 # CONFIG_SOUND is not set
@@ -581,10 +546,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -627,10 +588,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -712,8 +669,20 @@
 #
 # Network File Systems
 #
-# CONFIG_NFS_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -787,15 +756,14 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -806,6 +774,7 @@
 CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 # CONFIG_KPROBES is not set
 
 #
@@ -825,10 +794,13 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_AUDIT_GENERIC=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c
index 3c36c2d..39060cb 100644
--- a/arch/avr32/kernel/ptrace.c
+++ b/arch/avr32/kernel/ptrace.c
@@ -153,7 +153,6 @@
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long tmp;
 	int ret;
 
 	pr_debug("arch_ptrace(%ld, %d, %#lx, %#lx)\n",
@@ -166,11 +165,7 @@
 	/* Read the word at location addr in the child process */
 	case PTRACE_PEEKTEXT:
 	case PTRACE_PEEKDATA:
-		ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (ret == sizeof(tmp))
-			ret = put_user(tmp, (unsigned long __user *)data);
-		else
-			ret = -EIO;
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
 
 	case PTRACE_PEEKUSR:
@@ -181,11 +176,7 @@
 	/* Write the word in data at location addr */
 	case PTRACE_POKETEXT:
 	case PTRACE_POKEDATA:
-		ret = access_process_vm(child, addr, &data, sizeof(data), 1);
-		if (ret == sizeof(data))
-			ret = 0;
-		else
-			ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR:
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index 86d1075..9a73ce7 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -56,6 +56,7 @@
 	show_regs_log_lvl(regs, KERN_EMERG);
 	show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
 	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
 	if (in_interrupt())
@@ -184,7 +185,7 @@
 	if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) {
 		enum bug_trap_type type;
 
-		type = report_bug(regs->pc);
+		type = report_bug(regs->pc, regs);
 		switch (type) {
 		case BUG_TRAP_TYPE_NONE:
 			break;
diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c
index e7f72c9..db0438f 100644
--- a/arch/avr32/kernel/vmlinux.lds.c
+++ b/arch/avr32/kernel/vmlinux.lds.c
@@ -76,7 +76,7 @@
 		. = 0x100;
 		*(.scall.text)
 		*(.irq.text)
-		*(.text)
+		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
@@ -112,7 +112,7 @@
 
 		/* And the rest... */
 		*(.data.rel*)
-		*(.data)
+		DATA_DATA
 		CONSTRUCTORS
 
 		_edata = .;
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 1d2bf34..4dda42d 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -9,6 +9,7 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 #include <linux/spi/spi.h>
 
 #include <asm/io.h>
@@ -45,19 +46,30 @@
 		.flags		= IORESOURCE_IRQ,	\
 	}
 
+/* REVISIT these assume *every* device supports DMA, but several
+ * don't ... tc, smc, pio, rtc, watchdog, pwm, ps2, and more.
+ */
 #define DEFINE_DEV(_name, _id)					\
-static struct platform_device _name##_id##_device = {		\
-	.name		= #_name,				\
-	.id		= _id,					\
-	.resource	= _name##_id##_resource,		\
-	.num_resources	= ARRAY_SIZE(_name##_id##_resource),	\
-}
-#define DEFINE_DEV_DATA(_name, _id)				\
+static u64 _name##_id##_dma_mask = DMA_32BIT_MASK;		\
 static struct platform_device _name##_id##_device = {		\
 	.name		= #_name,				\
 	.id		= _id,					\
 	.dev		= {					\
+		.dma_mask = &_name##_id##_dma_mask,		\
+		.coherent_dma_mask = DMA_32BIT_MASK,		\
+	},							\
+	.resource	= _name##_id##_resource,		\
+	.num_resources	= ARRAY_SIZE(_name##_id##_resource),	\
+}
+#define DEFINE_DEV_DATA(_name, _id)				\
+static u64 _name##_id##_dma_mask = DMA_32BIT_MASK;		\
+static struct platform_device _name##_id##_device = {		\
+	.name		= #_name,				\
+	.id		= _id,					\
+	.dev		= {					\
+		.dma_mask = &_name##_id##_dma_mask,		\
 		.platform_data	= &_name##_id##_data,		\
+		.coherent_dma_mask = DMA_32BIT_MASK,		\
 	},							\
 	.resource	= _name##_id##_resource,		\
 	.num_resources	= ARRAY_SIZE(_name##_id##_resource),	\
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c
index 8f7b1c3..c1233c6 100644
--- a/arch/avr32/mm/cache.c
+++ b/arch/avr32/mm/cache.c
@@ -23,7 +23,6 @@
 void invalidate_dcache_region(void *start, size_t size)
 {
 	unsigned long v, begin, end, linesz, mask;
-	int flush = 0;
 
 	linesz = boot_cpu_data.dcache.linesz;
 	mask = linesz - 1;
@@ -32,24 +31,21 @@
 	 * instead of invalidating ... never discard valid data!
 	 */
 	begin = (unsigned long)start;
-	end = begin + size - 1;
+	end = begin + size;
 
 	if (begin & mask) {
 		flush_dcache_line(start);
 		begin += linesz;
-		flush = 1;
 	}
-	if ((end & mask) != mask) {
+	if (end & mask) {
 		flush_dcache_line((void *)end);
-		end -= linesz;
-		flush = 1;
+		end &= ~mask;
 	}
 
 	/* remaining cachelines only need invalidation */
-	for (v = begin; v <= end; v += linesz)
+	for (v = begin; v < end; v += linesz)
 		invalidate_dcache_line((void *)v);
-	if (flush)
-		flush_write_buffer();
+	flush_write_buffer();
 }
 
 void clean_dcache_region(void *start, size_t size)
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
index e011f1c..4b24952 100644
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -158,7 +158,7 @@
 	up_read(&mm->mmap_sem);
 
 	if (user_mode(regs)) {
-		if (exception_trace)
+		if (exception_trace && printk_ratelimit())
 			printk("%s%s[%d]: segfault at %08lx pc %08lx "
 			       "sp %08lx ecr %lu\n",
 			       is_init(tsk) ? KERN_EMERG : KERN_INFO,
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index d80e5b1..017defa 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -25,6 +25,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 config BFIN
 	bool
 	default y
@@ -67,6 +71,7 @@
 
 config IRQCHIP_DEMUX_GPIO
 	bool
+	depends on (BF53x || BF561 || BF54x)
 	default y
 
 source "init/Kconfig"
@@ -110,6 +115,26 @@
 	help
 	  BF537 Processor Support.
 
+config BF542
+	bool "BF542"
+	help
+	  BF542 Processor Support.
+
+config BF544
+	bool "BF544"
+	help
+	  BF544 Processor Support.
+
+config BF548
+	bool "BF548"
+	help
+	  BF548 Processor Support.
+
+config BF549
+	bool "BF549"
+	help
+	  BF549 Processor Support.
+
 config BF561
 	bool "BF561"
 	help
@@ -121,6 +146,11 @@
 	prompt "Silicon Rev"
 	default BF_REV_0_2 if BF537
 	default BF_REV_0_3 if BF533
+	default BF_REV_0_0 if BF549
+
+config BF_REV_0_0
+	bool "0.0"
+	depends on (BF549)
 
 config BF_REV_0_2
 	bool "0.2"
@@ -138,8 +168,24 @@
 	bool "0.5"
 	depends on (BF561 || BF533 || BF532 || BF531)
 
+config BF_REV_ANY
+	bool "any"
+
+config BF_REV_NONE
+	bool "none"
+
 endchoice
 
+config BF53x
+	bool
+	depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
+	default y
+
+config BF54x
+	bool
+	depends on (BF542 || BF544 || BF548 || BF549)
+	default y
+
 config BFIN_DUAL_CORE
 	bool
 	depends on (BF561)
@@ -188,8 +234,14 @@
 	help
 	  CM-BF537 support for EVAL- and DEV-Board.
 
+config BFIN548_EZKIT
+	bool "BF548-EZKIT"
+	depends on (BF548 || BF549)
+	  help
+	  BFIN548-EZKIT board Support.
+
 config BFIN561_BLUETECHNIX_CM
-	bool "BF561-CM"
+	bool "Bluetechnix CM-BF561"
 	depends on (BF561)
 	help
 	  CM-BF561 support for EVAL- and DEV-Board.
@@ -200,6 +252,12 @@
 	help
 	  BF561-EZKIT-LITE board Support.
 
+config BFIN561_TEPLA
+	bool "BF561-TEPLA"
+	depends on (BF561)
+	help
+	 BF561-TEPLA board Support.
+
 config PNAV10
 	bool "PNAV 1.0 board"
 	depends on (BF537)
@@ -249,6 +307,7 @@
 source "arch/blackfin/mach-bf533/Kconfig"
 source "arch/blackfin/mach-bf561/Kconfig"
 source "arch/blackfin/mach-bf537/Kconfig"
+source "arch/blackfin/mach-bf548/Kconfig"
 
 menu "Board customizations"
 
@@ -384,41 +443,6 @@
 	default 0x08 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 2)
 	default 0x10 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 3)
 
-comment "Console UART Setup"
-
-choice
-	prompt "Baud Rate"
-	default BAUD_57600
-config BAUD_9600
-	bool "9600"
-config BAUD_19200
-	bool "19200"
-config BAUD_38400
-	bool "38400"
-config BAUD_57600
-	bool "57600"
-config BAUD_115200
-	bool "115200"
-endchoice
-
-choice
-	prompt "Parity"
-	default BAUD_NO_PARITY
-config  BAUD_NO_PARITY
-	bool "No Parity"
-config  BAUD_PARITY
-	bool "Parity"
-endchoice
-
-choice
-	prompt "Stop Bits"
-	default BAUD_1_STOPBIT
-config  BAUD_1_STOPBIT
-	bool "1"
-config  BAUD_2_STOPBIT
-	bool "2"
-endchoice
-
 endmenu
 
 
@@ -516,7 +540,8 @@
 
 config CACHELINE_ALIGNED_L1
 	bool "Locate cacheline_aligned data to L1 Data Memory"
-	default y
+	default y if !BF54x
+	default n if BF54x
 	depends on !BF531
 	help
 	  If enabled cacheline_anligned data is linked
@@ -560,9 +585,17 @@
 
 source "mm/Kconfig"
 
+config LARGE_ALLOCS
+	bool "Allow allocating large blocks (> 1MB) of memory"
+	help
+	  Allow the slab memory allocator to keep chains for very large
+	  memory sizes - upto 32MB. You may need this if your system has
+	  a lot of RAM, and you need to able to allocate very large
+	  contiguous chunks. If unsure, say N.
+
 config BFIN_DMA_5XX
 	bool "Enable DMA Support"
-	depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561)
+	depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561 || BF54x)
 	default y
 	help
 	  DMA driver for BF5xx.
@@ -705,6 +738,7 @@
 
 config C_CDPRIO
 	bool "DMA has priority over core for ext. accesses"
+	depends on !BF54x
 	default n
 
 config C_B0PEN
@@ -858,7 +892,7 @@
 
 endmenu
 
-if (BF537 || BF533)
+if (BF537 || BF533 || BF54x)
 
 menu "CPU Frequency scaling"
 
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index 52d4dbd..1b75672 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -15,6 +15,7 @@
 CFLAGS_MODULE    += -mlong-calls
 KALLSYMS         += --symbol-prefix=_
 
+KBUILD_DEFCONFIG := BF537-STAMP_defconfig
 
 # setup the machine name and the machine dependent settings
 machine-$(CONFIG_BF531) := bf533
@@ -23,10 +24,33 @@
 machine-$(CONFIG_BF534) := bf537
 machine-$(CONFIG_BF536) := bf537
 machine-$(CONFIG_BF537) := bf537
+machine-$(CONFIG_BF548) := bf548
+machine-$(CONFIG_BF549) := bf548
 machine-$(CONFIG_BF561) := bf561
 MACHINE := $(machine-y)
 export MACHINE
 
+cpu-$(CONFIG_BF531) := bf531
+cpu-$(CONFIG_BF532) := bf532
+cpu-$(CONFIG_BF533) := bf533
+cpu-$(CONFIG_BF534) := bf534
+cpu-$(CONFIG_BF536) := bf536
+cpu-$(CONFIG_BF537) := bf537
+cpu-$(CONFIG_BF548) := bf548
+cpu-$(CONFIG_BF549) := bf549
+cpu-$(CONFIG_BF561) := bf561
+
+rev-$(CONFIG_BF_REV_0_0)  := 0.0
+rev-$(CONFIG_BF_REV_0_1)  := 0.1
+rev-$(CONFIG_BF_REV_0_2)  := 0.2
+rev-$(CONFIG_BF_REV_0_3)  := 0.3
+rev-$(CONFIG_BF_REV_0_4)  := 0.4
+rev-$(CONFIG_BF_REV_0_5)  := 0.5
+rev-$(CONFIG_BF_REV_NONE) := none
+rev-$(CONFIG_BF_REV_ANY)  := any
+
+CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
+AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
 
 head-y   := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
 
diff --git a/arch/blackfin/boot/Makefile b/arch/blackfin/boot/Makefile
index 49e8098..8cd3356 100644
--- a/arch/blackfin/boot/Makefile
+++ b/arch/blackfin/boot/Makefile
@@ -13,7 +13,8 @@
 
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
-                   -C gzip -a $(CONFIG_BOOT_LOAD) -e $(CONFIG_BOOT_LOAD) -n 'Linux-$(KERNELRELEASE)' \
+                   -C gzip -n 'Linux-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \
+                   -e $(shell $(NM) vmlinux | awk '$$NF == "__start" {print $$1}') \
                    -d $< $@
 
 $(obj)/vmlinux.bin: vmlinux FORCE
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
new file mode 100644
index 0000000..1cf1ab2
--- /dev/null
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -0,0 +1,1163 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21.5
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+CONFIG_BUDDY=y
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+CONFIG_BF533=y
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_2 is not set
+CONFIG_BF_REV_0_3=y
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+CONFIG_BFIN533_EZKIT=y
+# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BFIN537_STAMP is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_MEM_MT48LC16M16A2TG_75=y
+
+#
+# BF533/2/1 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_UART_ERROR=7
+CONFIG_SPORT0_ERROR=7
+CONFIG_SPI_ERROR=7
+CONFIG_SPORT1_ERROR=7
+CONFIG_PPI_ERROR=7
+CONFIG_DMA_ERROR=7
+CONFIG_PLLWAKE_ERROR=7
+CONFIG_RTC_ERROR=8
+CONFIG_DMA0_PPI=8
+CONFIG_DMA1_SPORT0RX=9
+CONFIG_DMA2_SPORT0TX=9
+CONFIG_DMA3_SPORT1RX=9
+CONFIG_DMA4_SPORT1TX=9
+CONFIG_DMA5_SPI=10
+CONFIG_DMA6_UARTRX=10
+CONFIG_DMA7_UARTTX=10
+CONFIG_TIMER0=11
+CONFIG_TIMER1=11
+CONFIG_TIMER2=11
+CONFIG_PFA=12
+CONFIG_PFB=12
+CONFIG_MEMDMA0=13
+CONFIG_MEMDMA1=13
+CONFIG_WDTIMER=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=27000000
+CONFIG_MEM_SIZE=32
+CONFIG_MEM_ADD_WIDTH=9
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_DCACHE_BANKA is not set
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+# CONFIG_BLKFIN_WB is not set
+CONFIG_BLKFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+# CONFIG_PM_WAKEUP_GPIO_API is not set
+CONFIG_PM_WAKEUP_SIC_IWR=0x100000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_MW320D=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_SIZE=0x400000
+CONFIG_EBIU_FLASH_BASE=0x20000000
+
+#
+# FLASH_EBIU_AMBCTL Control
+#
+CONFIG_BFIN_FLASH_BANK_0=0x7BB0
+CONFIG_BFIN_FLASH_BANK_1=0x7BB0
+CONFIG_BFIN_FLASH_BANK_2=0x7BB0
+CONFIG_BFIN_FLASH_BANK_3=0x7BB0
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_FBDMA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+CONFIG_BLACKFIN_DPMC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_SPI_MMC is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
new file mode 100644
index 0000000..64b7f1b
--- /dev/null
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -0,0 +1,1340 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21.5
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+CONFIG_BUDDY=y
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+CONFIG_BF533=y
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_2 is not set
+CONFIG_BF_REV_0_3=y
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN533_EZKIT is not set
+CONFIG_BFIN533_STAMP=y
+# CONFIG_BFIN537_STAMP is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_MEM_MT48LC64M4A2FB_7E=y
+CONFIG_BFIN_SHARED_FLASH_ENET=y
+
+#
+# BF533/2/1 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_UART_ERROR=7
+CONFIG_SPORT0_ERROR=7
+CONFIG_SPI_ERROR=7
+CONFIG_SPORT1_ERROR=7
+CONFIG_PPI_ERROR=7
+CONFIG_DMA_ERROR=7
+CONFIG_PLLWAKE_ERROR=7
+CONFIG_RTC_ERROR=8
+CONFIG_DMA0_PPI=8
+CONFIG_DMA1_SPORT0RX=9
+CONFIG_DMA2_SPORT0TX=9
+CONFIG_DMA3_SPORT1RX=9
+CONFIG_DMA4_SPORT1TX=9
+CONFIG_DMA5_SPI=10
+CONFIG_DMA6_UARTRX=10
+CONFIG_DMA7_UARTTX=10
+CONFIG_TIMER0=11
+CONFIG_TIMER1=11
+CONFIG_TIMER2=11
+CONFIG_PFA=12
+CONFIG_PFB=12
+CONFIG_MEMDMA0=13
+CONFIG_MEMDMA1=13
+CONFIG_WDTIMER=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=11059200
+CONFIG_MEM_SIZE=128
+CONFIG_MEM_ADD_WIDTH=11
+CONFIG_ENET_FLASH_PIN=0
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# LED Status Indicators
+#
+# CONFIG_BFIN_ALIVE_LED is not set
+# CONFIG_BFIN_IDLE_LED is not set
+CONFIG_BFIN_ALIVE_LED_PORT=0xFFC00700
+CONFIG_BFIN_ALIVE_LED_DPORT=0xFFC00730
+CONFIG_BFIN_IDLE_LED_PORT=0xFFC00700
+CONFIG_BFIN_IDLE_LED_DPORT=0xFFC00730
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_DCACHE_BANKA is not set
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+# CONFIG_BLKFIN_WB is not set
+CONFIG_BLKFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+# CONFIG_PM_WAKEUP_GPIO_API is not set
+CONFIG_PM_WAKEUP_SIC_IWR=0x100000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_MW320D=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_SIZE=0x400000
+CONFIG_EBIU_FLASH_BASE=0x20000000
+
+#
+# FLASH_EBIU_AMBCTL Control
+#
+CONFIG_BFIN_FLASH_BANK_0=0x7BB0
+CONFIG_BFIN_FLASH_BANK_1=0x7BB0
+CONFIG_BFIN_FLASH_BANK_2=0x7BB0
+CONFIG_BFIN_FLASH_BANK_3=0x7BB0
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_BF53X_PFBUTTONS is not set
+CONFIG_TWI_KEYPAD=m
+CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=39
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+CONFIG_TWI_LCD=m
+CONFIG_TWI_LCD_SLAVE_ADDR=34
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_TEA5764 is not set
+# CONFIG_BF5xx_FBDMA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+CONFIG_BLACKFIN_DPMC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_BLACKFIN_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_AD5252 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_SENSORS_PCA9543 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_FB=m
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_BFIN_7171=m
+CONFIG_FB_BFIN_7393=m
+CONFIG_NTSC=y
+# CONFIG_PAL is not set
+# CONFIG_NTSC_640x480 is not set
+# CONFIG_PAL_640x480 is not set
+# CONFIG_NTSC_YCBCR is not set
+# CONFIG_PAL_YCBCR is not set
+CONFIG_ADV7393_1XMEM=y
+# CONFIG_ADV7393_2XMEM is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA Blackfin devices
+#
+CONFIG_SND_BLACKFIN_AD1836=m
+CONFIG_SND_BLACKFIN_AD1836_TDM=y
+# CONFIG_SND_BLACKFIN_AD1836_I2S is not set
+CONFIG_SND_BLACKFIN_AD1836_MULSUB=y
+# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set
+CONFIG_SND_BLACKFIN_AD1981B=m
+CONFIG_SND_BLACKFIN_SPORT=0
+CONFIG_SND_BLACKFIN_SPI_PFBIT=4
+CONFIG_SND_BFIN_AD73311=m
+CONFIG_SND_BFIN_SPORT=0
+CONFIG_SND_BFIN_AD73311_SE=4
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_SPI_MMC is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
new file mode 100644
index 0000000..ccf09dc
--- /dev/null
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -0,0 +1,1374 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21.5
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+CONFIG_BUDDY=y
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+CONFIG_BF537=y
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+CONFIG_BF_REV_0_2=y
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+CONFIG_BFIN537_STAMP=y
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_MEM_MT48LC32M8A2_75=y
+CONFIG_IRQ_PLL_WAKEUP=7
+
+#
+# BF537 Specific Configuration
+#
+
+#
+# PORT F/G Selection
+#
+CONFIG_BF537_PORT_F=y
+# CONFIG_BF537_PORT_G is not set
+# CONFIG_BF537_PORT_H is not set
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA_ERROR=7
+CONFIG_IRQ_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_CAN_RX=11
+CONFIG_IRQ_CAN_TX=11
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PROG_INTA=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=25000000
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=10
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_DCACHE_BANKA is not set
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+# CONFIG_BLKFIN_WB is not set
+CONFIG_BLKFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+# CONFIG_PM_WAKEUP_GPIO_API is not set
+CONFIG_PM_WAKEUP_SIC_IWR=0x80000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_MW320D=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_SIZE=0x400000
+CONFIG_EBIU_FLASH_BASE=0x20000000
+
+#
+# FLASH_EBIU_AMBCTL Control
+#
+CONFIG_BFIN_FLASH_BANK_0=0x7BB0
+CONFIG_BFIN_FLASH_BANK_1=0x7BB0
+CONFIG_BFIN_FLASH_BANK_2=0x7BB0
+CONFIG_BFIN_FLASH_BANK_3=0x7BB0
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_BFIN=m
+CONFIG_BFIN_NAND_BASE=0x20212000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=3
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_MAC_USE_L1=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+# CONFIG_BFIN_MAC_RMII is not set
+# CONFIG_SMSC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_BF53X_PFBUTTONS is not set
+CONFIG_TWI_KEYPAD=m
+CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+CONFIG_TWI_LCD=m
+CONFIG_TWI_LCD_SLAVE_ADDR=34
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_TEA5764 is not set
+# CONFIG_BF5xx_FBDMA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART1 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+CONFIG_CAN4LINUX=y
+
+#
+# linux embedded drivers
+#
+# CONFIG_CAN_MCF5282 is not set
+# CONFIG_CAN_UNCTWINCAN is not set
+CONFIG_CAN_BLACKFIN=m
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+CONFIG_BLACKFIN_DPMC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_BLACKFIN_GPIO is not set
+CONFIG_I2C_BLACKFIN_TWI=m
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_AD5252=m
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_SENSORS_PCA9543 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_FB=m
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_BFIN_7171=m
+CONFIG_FB_BFIN_7393=m
+CONFIG_NTSC=y
+# CONFIG_PAL is not set
+# CONFIG_NTSC_640x480 is not set
+# CONFIG_PAL_640x480 is not set
+# CONFIG_NTSC_YCBCR is not set
+# CONFIG_PAL_YCBCR is not set
+CONFIG_ADV7393_1XMEM=y
+# CONFIG_ADV7393_2XMEM is not set
+CONFIG_FB_BF537_LQ035=m
+CONFIG_LQ035_SLAVE_ADDR=0x58
+# CONFIG_FB_BFIN_LANDSCAPE is not set
+# CONFIG_FB_BFIN_BGR is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA Blackfin devices
+#
+CONFIG_SND_BLACKFIN_AD1836=m
+CONFIG_SND_BLACKFIN_AD1836_TDM=y
+# CONFIG_SND_BLACKFIN_AD1836_I2S is not set
+CONFIG_SND_BLACKFIN_AD1836_MULSUB=y
+# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set
+CONFIG_SND_BLACKFIN_AD1981B=m
+CONFIG_SND_BLACKFIN_SPORT=0
+CONFIG_SND_BLACKFIN_SPI_PFBIT=4
+CONFIG_SND_BFIN_AD73311=m
+CONFIG_SND_BFIN_SPORT=0
+CONFIG_SND_BFIN_AD73311_SE=4
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_SPI_MMC is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
new file mode 100644
index 0000000..ac8390f
--- /dev/null
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -0,0 +1,1100 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21.5
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+CONFIG_BF549=y
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF54x=y
+CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BFIN537_STAMP is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+CONFIG_BFIN548_EZKIT=y
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_TIMER0=11
+CONFIG_IRQ_TIMER1=11
+CONFIG_IRQ_TIMER2=11
+CONFIG_IRQ_TIMER3=11
+CONFIG_IRQ_TIMER4=11
+CONFIG_IRQ_TIMER5=11
+CONFIG_IRQ_TIMER6=11
+CONFIG_IRQ_TIMER7=11
+CONFIG_IRQ_TIMER8=11
+CONFIG_IRQ_TIMER9=11
+CONFIG_IRQ_TIMER10=11
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+
+#
+# BF548 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMAC0_ERR=7
+CONFIG_IRQ_EPPI0_ERR=7
+CONFIG_IRQ_SPORT0_ERR=7
+CONFIG_IRQ_SPORT1_ERR=7
+CONFIG_IRQ_SPI0_ERR=7
+CONFIG_IRQ_UART0_ERR=7
+CONFIG_IRQ_EPPI0=8
+CONFIG_IRQ_SPI0=10
+CONFIG_IRQ_PINT0=12
+CONFIG_IRQ_PINT1=12
+CONFIG_IRQ_MDMAS0=13
+CONFIG_IRQ_MDMAS1=13
+CONFIG_IRQ_WATCHDOG=13
+CONFIG_IRQ_DMAC1_ERR=7
+CONFIG_IRQ_SPORT2_ERR=7
+CONFIG_IRQ_SPORT3_ERR=7
+CONFIG_IRQ_MXVR_DATA=7
+CONFIG_IRQ_SPI1_ERR=7
+CONFIG_IRQ_SPI2_ERR=7
+CONFIG_IRQ_UART1_ERR=7
+CONFIG_IRQ_UART2_ERR=7
+CONFIG_IRQ_CAN0_ERR=7
+CONFIG_IRQ_SPORT2_RX=9
+CONFIG_IRQ_SPORT2_TX=9
+CONFIG_IRQ_SPORT3_RX=9
+CONFIG_IRQ_SPORT3_TX=9
+CONFIG_IRQ_EPPI1=9
+CONFIG_IRQ_EPPI2=9
+CONFIG_IRQ_SPI1=10
+CONFIG_IRQ_SPI2=10
+CONFIG_IRQ_ATAPI_RX=10
+CONFIG_IRQ_ATAPI_TX=10
+CONFIG_IRQ_TWI0=11
+CONFIG_IRQ_TWI1=11
+CONFIG_IRQ_CAN0_RX=11
+CONFIG_IRQ_CAN0_TX=11
+CONFIG_IRQ_MDMAS2=13
+CONFIG_IRQ_MDMAS3=13
+CONFIG_IRQ_MXVR_ERR=11
+CONFIG_IRQ_MXVR_MSG=11
+CONFIG_IRQ_MXVR_PKT=11
+CONFIG_IRQ_EPPI1_ERR=7
+CONFIG_IRQ_EPPI2_ERR=7
+CONFIG_IRQ_UART3_ERR=7
+CONFIG_IRQ_HOST_ERR=7
+CONFIG_IRQ_PIXC_ERR=7
+CONFIG_IRQ_NFC_ERR=7
+CONFIG_IRQ_ATAPI_ERR=7
+CONFIG_IRQ_CAN1_ERR=7
+CONFIG_IRQ_HS_DMA_ERR=7
+CONFIG_IRQ_PIXC_IN0=8
+CONFIG_IRQ_PIXC_IN1=8
+CONFIG_IRQ_PIXC_OUT=8
+CONFIG_IRQ_SDH=8
+CONFIG_IRQ_CNT=8
+CONFIG_IRQ_KEY=8
+CONFIG_IRQ_CAN1_RX=11
+CONFIG_IRQ_CAN1_TX=11
+CONFIG_IRQ_SDH_MASK0=11
+CONFIG_IRQ_SDH_MASK1=11
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+CONFIG_IRQ_OTPSEC=11
+CONFIG_IRQ_PINT2=11
+CONFIG_IRQ_PINT3=11
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=25000000
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=10
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_DCACHE_BANKA is not set
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+# CONFIG_BLKFIN_WB is not set
+CONFIG_BLKFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_BF5xx is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMSC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_BF53X_PFBUTTONS is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_BF5xx_FBDMA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+# CONFIG_SERIAL_BFIN_DMA is not set
+CONFIG_SERIAL_BFIN_PIO=y
+# CONFIG_SERIAL_BFIN_UART0 is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART2 is not set
+# CONFIG_SERIAL_BFIN_UART3 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_YAFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_DEBUG_HWERR=y
+# CONFIG_DEBUG_ICACHE_CHECK is not set
+# CONFIG_DEBUG_KERNEL_START is not set
+# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
new file mode 100644
index 0000000..51c0b6f
--- /dev/null
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -0,0 +1,1177 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21.5
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+CONFIG_BUDDY=y
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+CONFIG_BF561=y
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_2 is not set
+CONFIG_BF_REV_0_3=y
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BFIN_DUAL_CORE=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BFIN537_STAMP is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+CONFIG_BFIN561_EZKIT=y
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_MEM_MT48LC16M16A2TG_75=y
+
+#
+# BF561 Specific Configuration
+#
+
+#
+# Core B Support
+#
+
+#
+# Core B Support
+#
+CONFIG_BF561_COREB=y
+CONFIG_BF561_COREB_RESET=y
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_DMA1_ERROR=7
+CONFIG_IRQ_DMA2_ERROR=7
+CONFIG_IRQ_IMDMA_ERROR=7
+CONFIG_IRQ_PPI0_ERROR=7
+CONFIG_IRQ_PPI1_ERROR=7
+CONFIG_IRQ_SPORT0_ERROR=7
+CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_SPI_ERROR=7
+CONFIG_IRQ_UART_ERROR=7
+CONFIG_IRQ_RESERVED_ERROR=7
+CONFIG_IRQ_DMA1_0=8
+CONFIG_IRQ_DMA1_1=8
+CONFIG_IRQ_DMA1_2=8
+CONFIG_IRQ_DMA1_3=8
+CONFIG_IRQ_DMA1_4=8
+CONFIG_IRQ_DMA1_5=8
+CONFIG_IRQ_DMA1_6=8
+CONFIG_IRQ_DMA1_7=8
+CONFIG_IRQ_DMA1_8=8
+CONFIG_IRQ_DMA1_9=8
+CONFIG_IRQ_DMA1_10=8
+CONFIG_IRQ_DMA1_11=8
+CONFIG_IRQ_DMA2_0=9
+CONFIG_IRQ_DMA2_1=9
+CONFIG_IRQ_DMA2_2=9
+CONFIG_IRQ_DMA2_3=9
+CONFIG_IRQ_DMA2_4=9
+CONFIG_IRQ_DMA2_5=9
+CONFIG_IRQ_DMA2_6=9
+CONFIG_IRQ_DMA2_7=9
+CONFIG_IRQ_DMA2_8=9
+CONFIG_IRQ_DMA2_9=9
+CONFIG_IRQ_DMA2_10=9
+CONFIG_IRQ_DMA2_11=9
+CONFIG_IRQ_TIMER0=10
+CONFIG_IRQ_TIMER1=10
+CONFIG_IRQ_TIMER2=10
+CONFIG_IRQ_TIMER3=10
+CONFIG_IRQ_TIMER4=10
+CONFIG_IRQ_TIMER5=10
+CONFIG_IRQ_TIMER6=10
+CONFIG_IRQ_TIMER7=10
+CONFIG_IRQ_TIMER8=10
+CONFIG_IRQ_TIMER9=10
+CONFIG_IRQ_TIMER10=10
+CONFIG_IRQ_TIMER11=10
+CONFIG_IRQ_PROG0_INTA=11
+CONFIG_IRQ_PROG0_INTB=11
+CONFIG_IRQ_PROG1_INTA=11
+CONFIG_IRQ_PROG1_INTB=11
+CONFIG_IRQ_PROG2_INTA=11
+CONFIG_IRQ_PROG2_INTB=11
+CONFIG_IRQ_DMA1_WRRD0=8
+CONFIG_IRQ_DMA1_WRRD1=8
+CONFIG_IRQ_DMA2_WRRD0=9
+CONFIG_IRQ_DMA2_WRRD1=9
+CONFIG_IRQ_IMDMA_WRRD0=12
+CONFIG_IRQ_IMDMA_WRRD1=12
+CONFIG_IRQ_WDTIMER=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=30000000
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=9
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_DCACHE_BANKA is not set
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+# CONFIG_BLKFIN_WB is not set
+CONFIG_BLKFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+CONFIG_C_B0PEN=y
+CONFIG_C_B1PEN=y
+CONFIG_C_B2PEN=y
+# CONFIG_C_B3PEN is not set
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_MW320D=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_EZKIT561 is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_SIZE=0x0400000
+CONFIG_EBIU_FLASH_BASE=0x20000000
+
+#
+# FLASH_EBIU_AMBCTL Control
+#
+CONFIG_BFIN_FLASH_BANK_0=0x7BB0
+CONFIG_BFIN_FLASH_BANK_1=0x7BB0
+CONFIG_BFIN_FLASH_BANK_2=0x7BB0
+CONFIG_BFIN_FLASH_BANK_3=0x7BB0
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_FBDMA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_SPI_MMC is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_DUAL_CORE_TEST_MODULE is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
new file mode 100644
index 0000000..983ed18
--- /dev/null
+++ b/arch/blackfin/configs/PNAV-10_defconfig
@@ -0,0 +1,1291 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21.5
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=9
+CONFIG_BUDDY=y
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+CONFIG_BF537=y
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+CONFIG_BF_REV_0_2=y
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BFIN537_STAMP is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+CONFIG_PNAV10=y
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_MEM_MT48LC32M8A2_75=y
+CONFIG_IRQ_PLL_WAKEUP=7
+
+#
+# BF537 Specific Configuration
+#
+
+#
+# PORT F/G Selection
+#
+CONFIG_BF537_PORT_F=y
+# CONFIG_BF537_PORT_G is not set
+# CONFIG_BF537_PORT_H is not set
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA_ERROR=7
+CONFIG_IRQ_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_CAN_RX=11
+CONFIG_IRQ_CAN_TX=11
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PROG_INTA=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=24576000
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=10
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+CONFIG_IP_CHECKSUM_L1=y
+CONFIG_CACHELINE_ALIGNED_L1=y
+CONFIG_SYSCALL_TAB_L1=y
+CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_DCACHE_BANKA is not set
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+CONFIG_BLKFIN_WB=y
+# CONFIG_BLKFIN_WT is not set
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x33B0
+CONFIG_BANK_2=0x33B0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_BF5xx is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_BFIN=y
+CONFIG_BFIN_NAND_BASE=0x20100000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=44
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_BFIN_MAC=y
+# CONFIG_BFIN_MAC_USE_L1 is not set
+CONFIG_BFIN_TX_DESC_NUM=100
+CONFIG_BFIN_RX_DESC_NUM=100
+CONFIG_BFIN_MAC_RMII=y
+# CONFIG_SMSC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_TSDEV=y
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+CONFIG_TOUCHSCREEN_AD7877=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_BF53X_PFBUTTONS is not set
+# CONFIG_TWI_KEYPAD is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+CONFIG_TWI_LCD=m
+CONFIG_TWI_LCD_SLAVE_ADDR=34
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_TEA5764 is not set
+# CONFIG_BF5xx_FBDMA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+CONFIG_CAN4LINUX=y
+
+#
+# linux embedded drivers
+#
+# CONFIG_CAN_MCF5282 is not set
+# CONFIG_CAN_UNCTWINCAN is not set
+CONFIG_CAN_BLACKFIN=m
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_BLACKFIN_GPIO is not set
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_AD5252 is not set
+# CONFIG_SENSORS_EEPROM is not set
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCF8575=y
+# CONFIG_SENSORS_PCA9543 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_BFIN_7171 is not set
+# CONFIG_FB_BFIN_7393 is not set
+CONFIG_FB_BF537_LQ035=y
+CONFIG_LQ035_SLAVE_ADDR=0x58
+CONFIG_FB_BFIN_LANDSCAPE=y
+# CONFIG_FB_BFIN_BGR is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA Blackfin devices
+#
+# CONFIG_SND_BLACKFIN_AD1836 is not set
+CONFIG_SND_BLACKFIN_AD1981B=m
+# CONFIG_SND_BFIN_AD73311 is not set
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_OBSOLETE_OSS is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+
+#
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_SPI_MMC is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
+# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_CPLB_INFO is not set
+# CONFIG_ACCESS_CHECK is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/defconfig b/arch/blackfin/defconfig
deleted file mode 100644
index d5904ca..0000000
--- a/arch/blackfin/defconfig
+++ /dev/null
@@ -1,1314 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-#
-# CONFIG_MMU is not set
-# CONFIG_FPU is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-CONFIG_BFIN=y
-CONFIG_SEMAPHORE_SLEEPERS=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_UCLINUX=y
-CONFIG_FORCE_MAX_ZONEORDER=14
-CONFIG_IRQCHIP_DEMUX_GPIO=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-# CONFIG_LIMIT_PAGECACHE is not set
-CONFIG_BUDDY=y
-# CONFIG_NP2 is not set
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Blackfin Processor Options
-#
-
-#
-# Processor and Board Settings
-#
-# CONFIG_BF531 is not set
-# CONFIG_BF532 is not set
-# CONFIG_BF533 is not set
-# CONFIG_BF534 is not set
-# CONFIG_BF535 is not set
-# CONFIG_BF536 is not set
-CONFIG_BF537=y
-# CONFIG_BF561 is not set
-CONFIG_BF_REV_0_2=y
-# CONFIG_BF_REV_0_3 is not set
-# CONFIG_BF_REV_0_4 is not set
-# CONFIG_BF_REV_0_5 is not set
-CONFIG_BLACKFIN=y
-CONFIG_BFIN_SINGLE_CORE=y
-# CONFIG_BFIN533_EZKIT is not set
-# CONFIG_BFIN533_STAMP is not set
-CONFIG_BFIN537_STAMP=y
-# CONFIG_BFIN533_BLUETECHNIX_CM is not set
-# CONFIG_BFIN537_BLUETECHNIX_CM is not set
-# CONFIG_BFIN561_BLUETECHNIX_CM is not set
-# CONFIG_BFIN561_EZKIT is not set
-# CONFIG_PNAV10 is not set
-# CONFIG_GENERIC_BOARD is not set
-CONFIG_MEM_MT48LC32M8A2_75=y
-CONFIG_IRQ_PLL_WAKEUP=7
-
-#
-# BF537 Specific Configuration
-#
-
-#
-# PORT F/G Selection
-#
-CONFIG_BF537_PORT_F=y
-# CONFIG_BF537_PORT_G is not set
-# CONFIG_BF537_PORT_H is not set
-
-#
-# Interrupt Priority Assignment
-#
-
-#
-# Priority
-#
-CONFIG_IRQ_DMA_ERROR=7
-CONFIG_IRQ_ERROR=7
-CONFIG_IRQ_RTC=8
-CONFIG_IRQ_PPI=8
-CONFIG_IRQ_SPORT0_RX=9
-CONFIG_IRQ_SPORT0_TX=9
-CONFIG_IRQ_SPORT1_RX=9
-CONFIG_IRQ_SPORT1_TX=9
-CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
-CONFIG_IRQ_UART0_RX=10
-CONFIG_IRQ_UART0_TX=10
-CONFIG_IRQ_UART1_RX=10
-CONFIG_IRQ_UART1_TX=10
-CONFIG_IRQ_CAN_RX=11
-CONFIG_IRQ_CAN_TX=11
-CONFIG_IRQ_MAC_RX=11
-CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
-CONFIG_IRQ_PROG_INTA=12
-CONFIG_IRQ_PORTG_INTB=12
-CONFIG_IRQ_MEM_DMA0=13
-CONFIG_IRQ_MEM_DMA1=13
-CONFIG_IRQ_WATCH=13
-
-#
-# Board customizations
-#
-
-#
-# Board Setup
-#
-CONFIG_CLKIN_HZ=25000000
-CONFIG_MEM_SIZE=64
-CONFIG_MEM_ADD_WIDTH=10
-CONFIG_BOOT_LOAD=0x1000
-
-#
-# Console UART Setup
-#
-# CONFIG_BAUD_9600 is not set
-# CONFIG_BAUD_19200 is not set
-# CONFIG_BAUD_38400 is not set
-CONFIG_BAUD_57600=y
-# CONFIG_BAUD_115200 is not set
-CONFIG_BAUD_NO_PARITY=y
-# CONFIG_BAUD_PARITY is not set
-CONFIG_BAUD_1_STOPBIT=y
-# CONFIG_BAUD_2_STOPBIT is not set
-
-#
-# Blackfin Kernel Optimizations
-#
-
-#
-# Timer Tick
-#
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-
-#
-# Memory Optimizations
-#
-CONFIG_I_ENTRY_L1=y
-CONFIG_RAMKERNEL=y
-# CONFIG_ROMKERNEL is not set
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_LARGE_ALLOCS=y
-CONFIG_BFIN_DMA_5XX=y
-# CONFIG_DMA_UNCACHED_2M is not set
-CONFIG_DMA_UNCACHED_1M=y
-# CONFIG_DMA_UNCACHED_NONE is not set
-
-#
-# Cache Support
-#
-CONFIG_BLKFIN_CACHE=y
-CONFIG_BLKFIN_DCACHE=y
-# CONFIG_BLKFIN_CACHE_LOCK is not set
-# CONFIG_BLKFIN_WB is not set
-CONFIG_BLKFIN_WT=y
-CONFIG_L1_MAX_PIECE=16
-
-#
-# Clock Settings
-#
-# CONFIG_BFIN_KERNEL_CLOCK is not set
-
-#
-# Asynchonous Memory Configuration
-#
-
-#
-# EBIU_AMBCTL Global Control
-#
-CONFIG_C_AMCKEN=y
-CONFIG_C_CDPRIO=y
-# CONFIG_C_AMBEN is not set
-# CONFIG_C_AMBEN_B0 is not set
-# CONFIG_C_AMBEN_B0_B1 is not set
-# CONFIG_C_AMBEN_B0_B1_B2 is not set
-CONFIG_C_AMBEN_ALL=y
-
-#
-# EBIU_AMBCTL Control
-#
-CONFIG_BANK_0=0x7BB0
-CONFIG_BANK_1=0x7BB0
-CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0x99B3
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF_FDPIC=y
-CONFIG_BINFMT_FLAT=y
-CONFIG_BINFMT_ZFLAT=y
-# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Power management options
-#
-CONFIG_PM=y
-CONFIG_PM_LEGACY=y
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
-# CONFIG_PM_WAKEUP_GPIO_API is not set
-CONFIG_PM_WAKEUP_SIC_IWR=0x80000000
-
-#
-# CPU Frequency scaling
-#
-# CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_NETLABEL is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-# CONFIG_IRDA_FAST_RR is not set
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-CONFIG_IRTTY_SIR=m
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
-# CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=m
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_GEN_PROBE=m
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_MW320D=m
-CONFIG_MTD_RAM=y
-CONFIG_MTD_ROM=m
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-CONFIG_MTD_COMPLEX_MAPPINGS=y
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_BF5xx=m
-CONFIG_BFIN_FLASH_SIZE=0x400000
-CONFIG_EBIU_FLASH_BASE=0x20000000
-
-#
-# FLASH_EBIU_AMBCTL Control
-#
-CONFIG_BFIN_FLASH_BANK_0=0x7BB0
-CONFIG_BFIN_FLASH_BANK_1=0x7BB0
-CONFIG_BFIN_FLASH_BANK_2=0x7BB0
-CONFIG_BFIN_FLASH_BANK_3=0x7BB0
-CONFIG_MTD_UCLINUX=y
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_DATAFLASH is not set
-# CONFIG_MTD_M25P80 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-CONFIG_MTD_NAND=m
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-# CONFIG_MTD_NAND_ECC_SMC is not set
-CONFIG_MTD_NAND_BFIN=m
-CONFIG_BFIN_NAND_BASE=0x20212000
-CONFIG_BFIN_NAND_CLE=2
-CONFIG_BFIN_NAND_ALE=1
-CONFIG_BFIN_NAND_READY=3
-CONFIG_MTD_NAND_IDS=m
-# CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
-# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_SMC91X is not set
-CONFIG_BFIN_MAC=y
-CONFIG_BFIN_MAC_USE_L1=y
-CONFIG_BFIN_TX_DESC_NUM=10
-CONFIG_BFIN_RX_DESC_NUM=20
-# CONFIG_BFIN_MAC_RMII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=m
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_UINPUT is not set
-# CONFIG_BF53X_PFBUTTONS is not set
-CONFIG_TWI_KEYPAD=m
-CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF533_PFLAGS is not set
-# CONFIG_BF5xx_PPIFCD is not set
-# CONFIG_BF5xx_TIMERS is not set
-# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_SPORT=y
-# CONFIG_BFIN_TIMER_LATENCY is not set
-CONFIG_TWI_LCD=m
-CONFIG_TWI_LCD_SLAVE_ADDR=34
-# CONFIG_AD5304 is not set
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_BFIN=y
-CONFIG_SERIAL_BFIN_CONSOLE=y
-CONFIG_SERIAL_BFIN_DMA=y
-# CONFIG_SERIAL_BFIN_PIO is not set
-CONFIG_SERIAL_BFIN_UART0=y
-# CONFIG_BFIN_UART0_CTSRTS is not set
-# CONFIG_SERIAL_BFIN_UART1 is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_BFIN_SPORT is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# CAN, the car bus and industrial fieldbus
-#
-CONFIG_CAN4LINUX=y
-
-#
-# linux embedded drivers
-#
-# CONFIG_CAN_MCF5282 is not set
-# CONFIG_CAN_UNCTWINCAN is not set
-CONFIG_CAN_BLACKFIN=m
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-CONFIG_BLACKFIN_DPMC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_BFIN_GPIO is not set
-CONFIG_I2C_BFIN_TWI=m
-CONFIG_TWICLK_KHZ=50
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_AD5252=m
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
-CONFIG_SPI=y
-CONFIG_SPI_MASTER=y
-
-#
-# SPI Master Controller Drivers
-#
-# CONFIG_SPI_BITBANG is not set
-CONFIG_SPI_BFIN=y
-
-#
-# SPI Protocol Masters
-#
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB=m
-CONFIG_FB_CFB_FILLRECT=m
-CONFIG_FB_CFB_COPYAREA=m
-CONFIG_FB_CFB_IMAGEBLIT=m
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-CONFIG_FB_BFIN_7171=m
-CONFIG_FB_BFIN_7393=m
-CONFIG_NTSC=y
-# CONFIG_PAL is not set
-# CONFIG_NTSC_640x480 is not set
-# CONFIG_PAL_640x480 is not set
-# CONFIG_NTSC_YCBCR is not set
-# CONFIG_PAL_YCBCR is not set
-CONFIG_ADV7393_1XMEM=y
-# CONFIG_ADV7393_2XMEM is not set
-CONFIG_FB_BF537_LQ035=m
-CONFIG_LQ035_SLAVE_ADDR=0x58
-# CONFIG_FB_BFIN_LANDSCAPE is not set
-# CONFIG_FB_BFIN_BGR is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-# CONFIG_SND_SEQUENCER is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_PCM_OSS_PLUGINS=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
-CONFIG_SND_VERBOSE_PROCFS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# HID Devices
-#
-CONFIG_HID=y
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_SPI_MMC is not set
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
-# CONFIG_RTC_DEBUG is not set
-
-#
-# RTC interfaces
-#
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
-
-#
-# RTC drivers
-#
-# CONFIG_RTC_DRV_X1205 is not set
-# CONFIG_RTC_DRV_DS1307 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
-# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
-# CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
-# CONFIG_RTC_DRV_MAX6902 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-CONFIG_RTC_DRV_BFIN=y
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Virtualization
-#
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
-CONFIG_JFFS2_FS=m
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=m
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
-# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_HUNT_FOR_ZERO=y
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_BOOTPARAM is not set
-# CONFIG_NO_KERNEL_MSG is not set
-CONFIG_CPLB_INFO=y
-# CONFIG_NO_ACCESS_CHECK is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-CONFIG_SECURITY=y
-# CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-# CONFIG_CRC16 is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index f3b7d2f..f429ebc 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -6,9 +6,12 @@
 
 obj-y := \
 	entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
-	sys_bfin.o time.o traps.o irqchip.o dma-mapping.o bfin_gpio.o \
-	flat.o
+	sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
+	fixed_code.o cplbinit.o cacheinit.o
 
+obj-$(CONFIG_BF53x)		     += bfin_gpio.o
+obj-$(CONFIG_BF561)		     += bfin_gpio.o
 obj-$(CONFIG_MODULES)                += module.o
 obj-$(CONFIG_BFIN_DMA_5XX)           += bfin_dma_5xx.o
 obj-$(CONFIG_DUAL_CORE_TEST_MODULE)  += dualcore_test.o
+obj-$(CONFIG_KGDB)                   += kgdb.o
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
index e455f45..b56b274 100644
--- a/arch/blackfin/kernel/asm-offsets.c
+++ b/arch/blackfin/kernel/asm-offsets.c
@@ -32,11 +32,10 @@
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
 #include <linux/hardirq.h>
-#include <asm/irq.h>
-#include <asm/thread_info.h>
+#include <linux/irq.h>
+#include <linux/thread_info.h>
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
 
 int main(void)
 {
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 8ea079e..7cf02f0 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 
+#include <asm/blackfin.h>
 #include <asm/dma.h>
 #include <asm/cacheflush.h>
 
@@ -45,67 +46,6 @@
 ***************************************************************************/
 
 static struct dma_channel dma_ch[MAX_BLACKFIN_DMA_CHANNEL];
-#if defined (CONFIG_BF561)
-static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
-	(struct dma_register *) DMA1_0_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_1_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_2_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_3_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_4_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_5_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_6_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_7_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_8_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_9_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_10_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_11_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_0_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_1_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_2_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_3_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_4_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_5_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_6_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_7_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_8_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_9_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_10_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_11_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
-	(struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
-	(struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
-	(struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
-	(struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
-};
-#else
-static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
-	(struct dma_register *) DMA0_NEXT_DESC_PTR,
-	(struct dma_register *) DMA1_NEXT_DESC_PTR,
-	(struct dma_register *) DMA2_NEXT_DESC_PTR,
-	(struct dma_register *) DMA3_NEXT_DESC_PTR,
-	(struct dma_register *) DMA4_NEXT_DESC_PTR,
-	(struct dma_register *) DMA5_NEXT_DESC_PTR,
-	(struct dma_register *) DMA6_NEXT_DESC_PTR,
-	(struct dma_register *) DMA7_NEXT_DESC_PTR,
-#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
-	(struct dma_register *) DMA8_NEXT_DESC_PTR,
-	(struct dma_register *) DMA9_NEXT_DESC_PTR,
-	(struct dma_register *) DMA10_NEXT_DESC_PTR,
-	(struct dma_register *) DMA11_NEXT_DESC_PTR,
-#endif
-	(struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
-};
-#endif
 
 /*------------------------------------------------------------------------------
  *       Set the Buffer Clear bit in the Configuration register of specific DMA
@@ -119,7 +59,7 @@
 	SSYNC();
 }
 
-int __init blackfin_dma_init(void)
+static int __init blackfin_dma_init(void)
 {
 	int i;
 
@@ -130,155 +70,14 @@
 		dma_ch[i].regs = base_addr[i];
 		mutex_init(&(dma_ch[i].dmalock));
 	}
-
+	/* Mark MEMDMA Channel 0 as requested since we're using it internally */
+	dma_ch[CH_MEM_STREAM0_DEST].chan_status = DMA_CHANNEL_REQUESTED;
+	dma_ch[CH_MEM_STREAM0_SRC].chan_status = DMA_CHANNEL_REQUESTED;
 	return 0;
 }
 
 arch_initcall(blackfin_dma_init);
 
-/*
- *	Form the channel find the irq number for that channel.
- */
-#if !defined(CONFIG_BF561)
-
-static int bf533_channel2irq(unsigned int channel)
-{
-	int ret_irq = -1;
-
-	switch (channel) {
-	case CH_PPI:
-		ret_irq = IRQ_PPI;
-		break;
-
-#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
-	case CH_EMAC_RX:
-		ret_irq = IRQ_MAC_RX;
-		break;
-
-	case CH_EMAC_TX:
-		ret_irq = IRQ_MAC_TX;
-		break;
-
-	case CH_UART1_RX:
-		ret_irq = IRQ_UART1_RX;
-		break;
-
-	case CH_UART1_TX:
-		ret_irq = IRQ_UART1_TX;
-		break;
-#endif
-
-	case CH_SPORT0_RX:
-		ret_irq = IRQ_SPORT0_RX;
-		break;
-
-	case CH_SPORT0_TX:
-		ret_irq = IRQ_SPORT0_TX;
-		break;
-
-	case CH_SPORT1_RX:
-		ret_irq = IRQ_SPORT1_RX;
-		break;
-
-	case CH_SPORT1_TX:
-		ret_irq = IRQ_SPORT1_TX;
-		break;
-
-	case CH_SPI:
-		ret_irq = IRQ_SPI;
-		break;
-
-	case CH_UART_RX:
-		ret_irq = IRQ_UART_RX;
-		break;
-
-	case CH_UART_TX:
-		ret_irq = IRQ_UART_TX;
-		break;
-
-	case CH_MEM_STREAM0_SRC:
-	case CH_MEM_STREAM0_DEST:
-		ret_irq = IRQ_MEM_DMA0;
-		break;
-
-	case CH_MEM_STREAM1_SRC:
-	case CH_MEM_STREAM1_DEST:
-		ret_irq = IRQ_MEM_DMA1;
-		break;
-	}
-	return ret_irq;
-}
-
-# define channel2irq(channel) bf533_channel2irq(channel)
-
-#else
-
-static int bf561_channel2irq(unsigned int channel)
-{
-	int ret_irq = -1;
-
-	switch (channel) {
-	case CH_PPI0:
-		ret_irq = IRQ_PPI0;
-		break;
-	case CH_PPI1:
-		ret_irq = IRQ_PPI1;
-		break;
-	case CH_SPORT0_RX:
-		ret_irq = IRQ_SPORT0_RX;
-		break;
-	case CH_SPORT0_TX:
-		ret_irq = IRQ_SPORT0_TX;
-		break;
-	case CH_SPORT1_RX:
-		ret_irq = IRQ_SPORT1_RX;
-		break;
-	case CH_SPORT1_TX:
-		ret_irq = IRQ_SPORT1_TX;
-		break;
-	case CH_SPI:
-		ret_irq = IRQ_SPI;
-		break;
-	case CH_UART_RX:
-		ret_irq = IRQ_UART_RX;
-		break;
-	case CH_UART_TX:
-		ret_irq = IRQ_UART_TX;
-		break;
-
-	case CH_MEM_STREAM0_SRC:
-	case CH_MEM_STREAM0_DEST:
-		ret_irq = IRQ_MEM_DMA0;
-		break;
-	case CH_MEM_STREAM1_SRC:
-	case CH_MEM_STREAM1_DEST:
-		ret_irq = IRQ_MEM_DMA1;
-		break;
-	case CH_MEM_STREAM2_SRC:
-	case CH_MEM_STREAM2_DEST:
-		ret_irq = IRQ_MEM_DMA2;
-		break;
-	case CH_MEM_STREAM3_SRC:
-	case CH_MEM_STREAM3_DEST:
-		ret_irq = IRQ_MEM_DMA3;
-		break;
-
-	case CH_IMEM_STREAM0_SRC:
-	case CH_IMEM_STREAM0_DEST:
-		ret_irq = IRQ_IMEM_DMA0;
-		break;
-	case CH_IMEM_STREAM1_SRC:
-	case CH_IMEM_STREAM1_DEST:
-		ret_irq = IRQ_IMEM_DMA1;
-		break;
-	}
-	return ret_irq;
-}
-
-# define channel2irq(channel) bf561_channel2irq(channel)
-
-#endif
-
 /*------------------------------------------------------------------------------
  *	Request the specific DMA channel from the system.
  *-----------------------------------------------------------------------------*/
@@ -533,7 +332,7 @@
 }
 EXPORT_SYMBOL(set_bfin_dma_config);
 
-void set_dma_sg(unsigned int channel, struct dmasg * sg, int nr_sg)
+void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg)
 {
 	BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
 	       && channel < MAX_BLACKFIN_DMA_CHANNEL));
@@ -593,15 +392,18 @@
 }
 EXPORT_SYMBOL(get_dma_curr_ycount);
 
-void *dma_memcpy(void *dest, const void *src, size_t size)
+static void *__dma_memcpy(void *dest, const void *src, size_t size)
 {
 	int direction;	/* 1 - address decrease, 0 - address increase */
 	int flag_align;	/* 1 - address aligned,  0 - address unaligned */
 	int flag_2D;	/* 1 - 2D DMA needed,	 0 - 1D DMA needed */
+	unsigned long flags;
 
 	if (size <= 0)
 		return NULL;
 
+	local_irq_save(flags);
+
 	if ((unsigned long)src < memory_end)
 		blackfin_dcache_flush_range((unsigned int)src,
 					    (unsigned int)(src + size));
@@ -725,18 +527,222 @@
 	if ((unsigned long)dest < memory_end)
 		blackfin_dcache_invalidate_range((unsigned int)dest,
 						 (unsigned int)(dest + size));
+	local_irq_restore(flags);
 
 	return dest;
 }
+
+void *dma_memcpy(void *dest, const void *src, size_t size)
+{
+	size_t bulk;
+	size_t rest;
+	void * addr;
+
+	bulk = (size >> 16) << 16;
+	rest = size - bulk;
+	if (bulk)
+		__dma_memcpy(dest, src, bulk);
+	addr = __dma_memcpy(dest+bulk, src+bulk, rest);
+	return addr;
+}
 EXPORT_SYMBOL(dma_memcpy);
 
 void *safe_dma_memcpy(void *dest, const void *src, size_t size)
 {
-	int flags = 0;
 	void *addr;
-	local_irq_save(flags);
 	addr = dma_memcpy(dest, src, size);
-	local_irq_restore(flags);
 	return addr;
 }
 EXPORT_SYMBOL(safe_dma_memcpy);
+
+void dma_outsb(void __iomem *addr, const void *buf, unsigned short len)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+	bfin_write_MDMA_D0_START_ADDR(addr);
+	bfin_write_MDMA_D0_X_COUNT(len);
+	bfin_write_MDMA_D0_X_MODIFY(0);
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_START_ADDR(buf);
+	bfin_write_MDMA_S0_X_COUNT(len);
+	bfin_write_MDMA_S0_X_MODIFY(1);
+	bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
+	bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
+
+	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_D0_CONFIG(0);
+	local_irq_restore(flags);
+
+}
+EXPORT_SYMBOL(dma_outsb);
+
+
+void dma_insb(const void __iomem *addr, void *buf, unsigned short len)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	bfin_write_MDMA_D0_START_ADDR(buf);
+	bfin_write_MDMA_D0_X_COUNT(len);
+	bfin_write_MDMA_D0_X_MODIFY(1);
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_START_ADDR(addr);
+	bfin_write_MDMA_S0_X_COUNT(len);
+	bfin_write_MDMA_S0_X_MODIFY(0);
+	bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
+	bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
+
+	blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_D0_CONFIG(0);
+	local_irq_restore(flags);
+
+}
+EXPORT_SYMBOL(dma_insb);
+
+void dma_outsw(void __iomem *addr, const void  *buf, unsigned short len)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+	bfin_write_MDMA_D0_START_ADDR(addr);
+	bfin_write_MDMA_D0_X_COUNT(len);
+	bfin_write_MDMA_D0_X_MODIFY(0);
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_START_ADDR(buf);
+	bfin_write_MDMA_S0_X_COUNT(len);
+	bfin_write_MDMA_S0_X_MODIFY(2);
+	bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
+	bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
+
+	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_D0_CONFIG(0);
+	local_irq_restore(flags);
+
+}
+EXPORT_SYMBOL(dma_outsw);
+
+void dma_insw(const void __iomem *addr, void *buf, unsigned short len)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	bfin_write_MDMA_D0_START_ADDR(buf);
+	bfin_write_MDMA_D0_X_COUNT(len);
+	bfin_write_MDMA_D0_X_MODIFY(2);
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_START_ADDR(addr);
+	bfin_write_MDMA_S0_X_COUNT(len);
+	bfin_write_MDMA_S0_X_MODIFY(0);
+	bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
+	bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
+
+	blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_D0_CONFIG(0);
+	local_irq_restore(flags);
+
+}
+EXPORT_SYMBOL(dma_insw);
+
+void dma_outsl(void __iomem *addr, const void *buf, unsigned short len)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+	bfin_write_MDMA_D0_START_ADDR(addr);
+	bfin_write_MDMA_D0_X_COUNT(len);
+	bfin_write_MDMA_D0_X_MODIFY(0);
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_START_ADDR(buf);
+	bfin_write_MDMA_S0_X_COUNT(len);
+	bfin_write_MDMA_S0_X_MODIFY(4);
+	bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
+	bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
+
+	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_D0_CONFIG(0);
+	local_irq_restore(flags);
+
+}
+EXPORT_SYMBOL(dma_outsl);
+
+void dma_insl(const void __iomem *addr, void *buf, unsigned short len)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	bfin_write_MDMA_D0_START_ADDR(buf);
+	bfin_write_MDMA_D0_X_COUNT(len);
+	bfin_write_MDMA_D0_X_MODIFY(4);
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_START_ADDR(addr);
+	bfin_write_MDMA_S0_X_COUNT(len);
+	bfin_write_MDMA_S0_X_MODIFY(0);
+	bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
+	bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
+
+	blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_D0_CONFIG(0);
+	local_irq_restore(flags);
+
+}
+EXPORT_SYMBOL(dma_insl);
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index e9f24a9..bafcfa5 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -138,13 +138,13 @@
 
 inline int check_gpio(unsigned short gpio)
 {
-	if (gpio > MAX_BLACKFIN_GPIOS)
+	if (gpio >= MAX_BLACKFIN_GPIOS)
 		return -EINVAL;
 	return 0;
 }
 
 #ifdef BF537_FAMILY
-void port_setup(unsigned short gpio, unsigned short usage)
+static void port_setup(unsigned short gpio, unsigned short usage)
 {
 	if (usage == GPIO_USAGE) {
 		if (*port_fer[gpio_bank(gpio)] & gpio_bit(gpio))
@@ -160,9 +160,9 @@
 #endif
 
 
-void default_gpio(unsigned short gpio)
+static void default_gpio(unsigned short gpio)
 {
-	unsigned short bank,bitmask;
+	unsigned short bank, bitmask;
 
 	bank = gpio_bank(gpio);
 	bitmask = gpio_bit(gpio);
@@ -177,21 +177,20 @@
 	gpio_bankb[bank]->edge &= ~bitmask;
 }
 
-
-int __init bfin_gpio_init(void)
+static int __init bfin_gpio_init(void)
 {
 	int i;
 
 	printk(KERN_INFO "Blackfin GPIO Controller\n");
 
-	for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE)
+	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE)
 		reserved_map[gpio_bank(i)] = 0;
 
 #if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
 # if defined(CONFIG_BFIN_MAC_RMII)
-	reserved_map[PORT_H] = 0xC373;
+	reserved_map[gpio_bank(PORT_H)] = 0xC373;
 # else
-	reserved_map[PORT_H] = 0xFFFF;
+	reserved_map[gpio_bank(PORT_H)] = 0xFFFF;
 # endif
 #endif
 
@@ -479,7 +478,7 @@
 	u32 sic_iwr = 0;
 	u16 bank, mask, i, gpio;
 
-	for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
 		mask = wakeup_map[gpio_bank(i)];
 		bank = gpio_bank(i);
 
@@ -495,19 +494,24 @@
 			gpio_bank_saved[bank].dir   = gpio_bankb[bank]->dir;
 			gpio_bank_saved[bank].edge  = gpio_bankb[bank]->edge;
 			gpio_bank_saved[bank].both  = gpio_bankb[bank]->both;
+			gpio_bank_saved[bank].reserved = reserved_map[bank];
 
 			gpio = i;
 
 			while (mask) {
 				if (mask & 1) {
-					bfin_gpio_wakeup_type(gpio, wakeup_flags_map[gpio]);
+					reserved_map[gpio_bank(gpio)] |=
+							gpio_bit(gpio);
+					bfin_gpio_wakeup_type(gpio,
+						wakeup_flags_map[gpio]);
 					set_gpio_data(gpio, 0); /*Clear*/
 				}
 				gpio++;
 				mask >>= 1;
 			}
 
-			sic_iwr |= 1 << (sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));
+			sic_iwr |= 1 <<
+				(sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));
 			gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];
 		}
 	}
@@ -518,12 +522,11 @@
 		return IWR_ENABLE_ALL;
 }
 
-
 void gpio_pm_restore(void)
 {
 	u16 bank, mask, i;
 
-	for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
 		mask = wakeup_map[gpio_bank(i)];
 		bank = gpio_bank(i);
 
@@ -536,6 +539,9 @@
 			gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
 			gpio_bankb[bank]->edge  = gpio_bank_saved[bank].edge;
 			gpio_bankb[bank]->both  = gpio_bank_saved[bank].both;
+
+			reserved_map[bank] = gpio_bank_saved[bank].reserved;
+
 		}
 
 		gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;
@@ -584,7 +590,6 @@
 }
 EXPORT_SYMBOL(gpio_request);
 
-
 void gpio_free(unsigned short gpio)
 {
 	unsigned long flags;
@@ -609,7 +614,6 @@
 }
 EXPORT_SYMBOL(gpio_free);
 
-
 void gpio_direction_input(unsigned short gpio)
 {
 	unsigned long flags;
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c
index f64ecb6..7045594 100644
--- a/arch/blackfin/kernel/bfin_ksyms.c
+++ b/arch/blackfin/kernel/bfin_ksyms.c
@@ -28,10 +28,11 @@
  */
 
 #include <linux/module.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
+#include <linux/uaccess.h>
+
 #include <asm/checksum.h>
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
 
 /* platform dependent support */
 
diff --git a/arch/blackfin/kernel/cacheinit.c b/arch/blackfin/kernel/cacheinit.c
new file mode 100644
index 0000000..4d41a40
--- /dev/null
+++ b/arch/blackfin/kernel/cacheinit.c
@@ -0,0 +1,66 @@
+/*
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/cpu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+
+#if defined(CONFIG_BLKFIN_CACHE)
+void bfin_icache_init(void)
+{
+	unsigned long *table = icplb_table;
+	unsigned long ctrl;
+	int i;
+
+	for (i = 0; i < MAX_CPLBS; i++) {
+		unsigned long addr = *table++;
+		unsigned long data = *table++;
+		if (addr == (unsigned long)-1)
+			break;
+		bfin_write32(ICPLB_ADDR0 + i * 4, addr);
+		bfin_write32(ICPLB_DATA0 + i * 4, data);
+	}
+	ctrl = bfin_read_IMEM_CONTROL();
+	ctrl |= IMC | ENICPLB;
+	bfin_write_IMEM_CONTROL(ctrl);
+}
+#endif
+
+#if defined(CONFIG_BLKFIN_DCACHE)
+void bfin_dcache_init(void)
+{
+	unsigned long *table = dcplb_table;
+	unsigned long ctrl;
+	int i;
+
+	for (i = 0; i < MAX_CPLBS; i++) {
+		unsigned long addr = *table++;
+		unsigned long data = *table++;
+		if (addr == (unsigned long)-1)
+			break;
+		bfin_write32(DCPLB_ADDR0 + i * 4, addr);
+		bfin_write32(DCPLB_DATA0 + i * 4, data);
+	}
+	ctrl = bfin_read_DMEM_CONTROL();
+	ctrl |= DMEM_CNTR;
+	bfin_write_DMEM_CONTROL(ctrl);
+}
+#endif
diff --git a/arch/blackfin/kernel/cplbinit.c b/arch/blackfin/kernel/cplbinit.c
new file mode 100644
index 0000000..bbdb403
--- /dev/null
+++ b/arch/blackfin/kernel/cplbinit.c
@@ -0,0 +1,433 @@
+/*
+ * Blackfin CPLB initialization
+ *
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/module.h>
+
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+
+u_long icplb_table[MAX_CPLBS+1];
+u_long dcplb_table[MAX_CPLBS+1];
+
+#ifdef CONFIG_CPLB_SWITCH_TAB_L1
+u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
+u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
+
+#ifdef CONFIG_CPLB_INFO
+u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
+u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
+#endif /* CONFIG_CPLB_INFO */
+
+#else
+
+u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
+u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
+
+#ifdef CONFIG_CPLB_INFO
+u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
+u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
+#endif /* CONFIG_CPLB_INFO */
+
+#endif /*CONFIG_CPLB_SWITCH_TAB_L1*/
+
+struct s_cplb {
+	struct cplb_tab init_i;
+	struct cplb_tab init_d;
+	struct cplb_tab switch_i;
+	struct cplb_tab switch_d;
+};
+
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+static struct cplb_desc cplb_data[] = {
+	{
+		.start = 0,
+		.end = SIZE_1K,
+		.psize = SIZE_1K,
+		.attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
+		.i_conf = SDRAM_OOPS,
+		.d_conf = SDRAM_OOPS,
+#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
+		.valid = 1,
+#else
+		.valid = 0,
+#endif
+		.name = "ZERO Pointer Saveguard",
+	},
+	{
+		.start = L1_CODE_START,
+		.end = L1_CODE_START + L1_CODE_LENGTH,
+		.psize = SIZE_4M,
+		.attr = INITIAL_T | SWITCH_T | I_CPLB,
+		.i_conf = L1_IMEMORY,
+		.d_conf = 0,
+		.valid = 1,
+		.name = "L1 I-Memory",
+	},
+	{
+		.start = L1_DATA_A_START,
+		.end = L1_DATA_B_START + L1_DATA_B_LENGTH,
+		.psize = SIZE_4M,
+		.attr = INITIAL_T | SWITCH_T | D_CPLB,
+		.i_conf = 0,
+		.d_conf = L1_DMEMORY,
+#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
+		.valid = 1,
+#else
+		.valid = 0,
+#endif
+		.name = "L1 D-Memory",
+	},
+	{
+		.start = 0,
+		.end = 0,  /* dynamic */
+		.psize = 0,
+		.attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
+		.i_conf =  SDRAM_IGENERIC,
+		.d_conf =  SDRAM_DGENERIC,
+		.valid = 1,
+		.name = "SDRAM Kernel",
+	},
+	{
+		.start = 0, /* dynamic */
+		.end = 0, /* dynamic */
+		.psize = 0,
+		.attr = INITIAL_T | SWITCH_T | D_CPLB,
+		.i_conf =  SDRAM_IGENERIC,
+		.d_conf =  SDRAM_DNON_CHBL,
+		.valid = 1,
+		.name = "SDRAM RAM MTD",
+	},
+	{
+		.start = 0, /* dynamic */
+		.end = 0,   /* dynamic */
+		.psize = SIZE_1M,
+		.attr = INITIAL_T | SWITCH_T | D_CPLB,
+		.d_conf = SDRAM_DNON_CHBL,
+		.valid = 1,
+		.name = "SDRAM Uncached DMA ZONE",
+	},
+	{
+		.start = 0, /* dynamic */
+		.end = 0, /* dynamic */
+		.psize = 0,
+		.attr = SWITCH_T | D_CPLB,
+		.i_conf = 0, /* dynamic */
+		.d_conf = 0, /* dynamic */
+		.valid = 1,
+		.name = "SDRAM Reserved Memory",
+	},
+	{
+		.start = ASYNC_BANK0_BASE,
+		.end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
+		.psize = 0,
+		.attr = SWITCH_T | D_CPLB,
+		.d_conf = SDRAM_EBIU,
+		.valid = 1,
+		.name = "ASYNC Memory",
+	},
+	{
+#if defined(CONFIG_BF561)
+		.start = L2_SRAM,
+		.end = L2_SRAM_END,
+		.psize = SIZE_1M,
+		.attr = SWITCH_T | D_CPLB,
+		.i_conf = L2_MEMORY,
+		.d_conf = L2_MEMORY,
+		.valid = 1,
+#else
+		.valid = 0,
+#endif
+		.name = "L2 Memory",
+	}
+};
+
+static u16 __init lock_kernel_check(u32 start, u32 end)
+{
+	if ((start <= (u32) _stext && end >= (u32) _end)
+	    || (start >= (u32) _stext && end <= (u32) _end))
+		return IN_KERNEL;
+	return 0;
+}
+
+static unsigned short __init
+fill_cplbtab(struct cplb_tab *table,
+	     unsigned long start, unsigned long end,
+	     unsigned long block_size, unsigned long cplb_data)
+{
+	int i;
+
+	switch (block_size) {
+	case SIZE_4M:
+		i = 3;
+		break;
+	case SIZE_1M:
+		i = 2;
+		break;
+	case SIZE_4K:
+		i = 1;
+		break;
+	case SIZE_1K:
+	default:
+		i = 0;
+		break;
+	}
+
+	cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
+
+	while ((start < end) && (table->pos < table->size)) {
+
+		table->tab[table->pos++] = start;
+
+		if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
+			table->tab[table->pos++] =
+			    cplb_data | CPLB_LOCK | CPLB_DIRTY;
+		else
+			table->tab[table->pos++] = cplb_data;
+
+		start += block_size;
+	}
+	return 0;
+}
+
+static unsigned short __init
+close_cplbtab(struct cplb_tab *table)
+{
+
+	while (table->pos < table->size) {
+
+		table->tab[table->pos++] = 0;
+		table->tab[table->pos++] = 0; /* !CPLB_VALID */
+	}
+	return 0;
+}
+
+/* helper function */
+static void __fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+{
+	if (cplb_data[i].psize) {
+		fill_cplbtab(t,
+				cplb_data[i].start,
+				cplb_data[i].end,
+				cplb_data[i].psize,
+				cplb_data[i].i_conf);
+	} else {
+#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+		if (i == SDRAM_KERN) {
+			fill_cplbtab(t,
+					cplb_data[i].start,
+					cplb_data[i].end,
+					SIZE_4M,
+					cplb_data[i].i_conf);
+		} else
+#endif
+		{
+			fill_cplbtab(t,
+					cplb_data[i].start,
+					a_start,
+					SIZE_1M,
+					cplb_data[i].i_conf);
+			fill_cplbtab(t,
+					a_start,
+					a_end,
+					SIZE_4M,
+					cplb_data[i].i_conf);
+			fill_cplbtab(t, a_end,
+					cplb_data[i].end,
+					SIZE_1M,
+					cplb_data[i].i_conf);
+		}
+	}
+}
+
+static void __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+{
+	if (cplb_data[i].psize) {
+		fill_cplbtab(t,
+				cplb_data[i].start,
+				cplb_data[i].end,
+				cplb_data[i].psize,
+				cplb_data[i].d_conf);
+	} else {
+		fill_cplbtab(t,
+				cplb_data[i].start,
+				a_start, SIZE_1M,
+				cplb_data[i].d_conf);
+		fill_cplbtab(t, a_start,
+				a_end, SIZE_4M,
+				cplb_data[i].d_conf);
+		fill_cplbtab(t, a_end,
+				cplb_data[i].end,
+				SIZE_1M,
+				cplb_data[i].d_conf);
+	}
+}
+
+void __init generate_cpl_tables(void)
+{
+
+	u16 i, j, process;
+	u32 a_start, a_end, as, ae, as_1m;
+
+	struct cplb_tab *t_i = NULL;
+	struct cplb_tab *t_d = NULL;
+	struct s_cplb cplb;
+
+	cplb.init_i.size = MAX_CPLBS;
+	cplb.init_d.size = MAX_CPLBS;
+	cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
+	cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
+
+	cplb.init_i.pos = 0;
+	cplb.init_d.pos = 0;
+	cplb.switch_i.pos = 0;
+	cplb.switch_d.pos = 0;
+
+	cplb.init_i.tab = icplb_table;
+	cplb.init_d.tab = dcplb_table;
+	cplb.switch_i.tab = ipdt_table;
+	cplb.switch_d.tab = dpdt_table;
+
+	cplb_data[SDRAM_KERN].end = memory_end;
+
+#ifdef CONFIG_MTD_UCLINUX
+	cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
+	cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
+	cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
+# if defined(CONFIG_ROMFS_FS)
+	cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
+
+	/*
+	 * The ROMFS_FS size is often not multiple of 1MB.
+	 * This can cause multiple CPLB sets covering the same memory area.
+	 * This will then cause multiple CPLB hit exceptions.
+	 * Workaround: We ensure a contiguous memory area by extending the kernel
+	 * memory section over the mtd section.
+	 * For ROMFS_FS memory must be covered with ICPLBs anyways.
+	 * So there is no difference between kernel and mtd memory setup.
+	 */
+
+	cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
+	cplb_data[SDRAM_RAM_MTD].valid = 0;
+
+# endif
+#else
+	cplb_data[SDRAM_RAM_MTD].valid = 0;
+#endif
+
+	cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
+	cplb_data[SDRAM_DMAZ].end = _ramend;
+
+	cplb_data[RES_MEM].start = _ramend;
+	cplb_data[RES_MEM].end = physical_mem_end;
+
+	if (reserved_mem_dcache_on)
+		cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
+	else
+		cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
+
+	if (reserved_mem_icache_on)
+		cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
+	else
+		cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
+
+	for (i = ZERO_P; i <= L2_MEM; i++) {
+		if (!cplb_data[i].valid)
+			continue;
+
+		as_1m = cplb_data[i].start % SIZE_1M;
+
+		/* We need to make sure all sections are properly 1M aligned
+		 * However between Kernel Memory and the Kernel mtd section, depending on the
+		 * rootfs size, there can be overlapping memory areas.
+		 */
+
+		if (as_1m && i != L1I_MEM && i != L1D_MEM) {
+#ifdef CONFIG_MTD_UCLINUX
+			if (i == SDRAM_RAM_MTD) {
+				if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
+					cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
+				else
+					cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
+			} else
+#endif
+				printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
+				       cplb_data[i].name, cplb_data[i].start);
+		}
+
+		as = cplb_data[i].start % SIZE_4M;
+		ae = cplb_data[i].end % SIZE_4M;
+
+		if (as)
+			a_start = cplb_data[i].start + (SIZE_4M - (as));
+		else
+			a_start = cplb_data[i].start;
+
+		a_end = cplb_data[i].end - ae;
+
+		for (j = INITIAL_T; j <= SWITCH_T; j++) {
+
+			switch (j) {
+			case INITIAL_T:
+				if (cplb_data[i].attr & INITIAL_T) {
+					t_i = &cplb.init_i;
+					t_d = &cplb.init_d;
+					process = 1;
+				} else
+					process = 0;
+				break;
+			case SWITCH_T:
+				if (cplb_data[i].attr & SWITCH_T) {
+					t_i = &cplb.switch_i;
+					t_d = &cplb.switch_d;
+					process = 1;
+				} else
+					process = 0;
+				break;
+			default:
+					process = 0;
+				break;
+			}
+
+			if (!process)
+				continue;
+			if (cplb_data[i].attr & I_CPLB)
+				__fill_code_cplbtab(t_i, i, a_start, a_end);
+
+			if (cplb_data[i].attr & D_CPLB)
+				__fill_data_cplbtab(t_d, i, a_start, a_end);
+		}
+	}
+
+/* close tables */
+
+	close_cplbtab(&cplb.init_i);
+	close_cplbtab(&cplb.init_d);
+
+	cplb.init_i.tab[cplb.init_i.pos] = -1;
+	cplb.init_d.tab[cplb.init_d.pos] = -1;
+	cplb.switch_i.tab[cplb.switch_i.pos] = -1;
+	cplb.switch_d.tab[cplb.switch_d.pos] = -1;
+
+}
+
+#endif
+
diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c
index 539eb24..ea48d5b1 100644
--- a/arch/blackfin/kernel/dma-mapping.c
+++ b/arch/blackfin/kernel/dma-mapping.c
@@ -34,8 +34,8 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/io.h>
 #include <asm/cacheflush.h>
-#include <asm/io.h>
 #include <asm/bfin-global.h>
 
 static spinlock_t dma_page_lock;
@@ -159,10 +159,13 @@
 
 	BUG_ON(direction == DMA_NONE);
 
-	for (i = 0; i < nents; i++)
-		invalidate_dcache_range(sg_dma_address(&sg[i]),
-					sg_dma_address(&sg[i]) +
-					sg_dma_len(&sg[i]));
+	for (i = 0; i < nents; i++, sg++) {
+		sg->dma_address = page_address(sg->page) + sg->offset;
+
+		invalidate_dcache_range(sg_dma_address(sg),
+					sg_dma_address(sg) +
+					sg_dma_len(sg));
+	}
 
 	return nents;
 }
diff --git a/arch/blackfin/kernel/dualcore_test.c b/arch/blackfin/kernel/dualcore_test.c
index 8b89c99..0fcba74 100644
--- a/arch/blackfin/kernel/dualcore_test.c
+++ b/arch/blackfin/kernel/dualcore_test.c
@@ -30,19 +30,19 @@
 #include <linux/init.h>
 #include <linux/module.h>
 
-static int *testarg = (int*)0xfeb00000;
+static int *testarg = (int *)0xfeb00000;
 
 static int test_init(void)
 {
 	*testarg = 1;
-	printk("Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
+	printk(KERN_INFO "Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
 	       *testarg, testarg);
 	return 0;
 }
 
 static void test_exit(void)
 {
-	printk("Dual core test module removed: testarg = [%d]\n", *testarg);
+	printk(KERN_INFO "Dual core test module removed: testarg = [%d]\n", *testarg);
 }
 
 module_init(test_init);
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index 5880b27..65c5ba4 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -58,10 +58,12 @@
 	RESTORE_ALL_SYS
 	p0 = reti;
 	jump (p0);
+ENDPROC(_ret_from_fork)
 
 ENTRY(_sys_fork)
 	r0 = -EINVAL;
 	rts;
+ENDPROC(_sys_fork)
 
 ENTRY(_sys_vfork)
 	r0 = sp;
@@ -72,6 +74,7 @@
 	SP += 12;
 	rets = [sp++];
 	rts;
+ENDPROC(_sys_vfork)
 
 ENTRY(_sys_clone)
 	r0 = sp;
@@ -82,6 +85,7 @@
 	SP += 12;
 	rets = [sp++];
 	rts;
+ENDPROC(_sys_clone)
 
 ENTRY(_sys_rt_sigreturn)
 	r0 = sp;
@@ -92,3 +96,4 @@
 	SP += 12;
 	rets = [sp++];
 	rts;
+ENDPROC(_sys_rt_sigreturn)
diff --git a/arch/blackfin/kernel/fixed_code.S b/arch/blackfin/kernel/fixed_code.S
new file mode 100644
index 0000000..d8b1ebc7
--- /dev/null
+++ b/arch/blackfin/kernel/fixed_code.S
@@ -0,0 +1,132 @@
+/*
+ * This file contains sequences of code that will be copied to a
+ * fixed location, defined in <asm/atomic_seq.h>.  The interrupt
+ * handlers ensure that these sequences appear to be atomic when
+ * executed from userspace.
+ * These are aligned to 16 bytes, so that we have some space to replace
+ * these sequences with something else (e.g. kernel traps if we ever do
+ * BF561 SMP).
+ */
+#include <linux/linkage.h>
+#include <linux/unistd.h>
+#include <asm/entry.h>
+
+.text
+ENTRY(_fixed_code_start)
+
+.align 16
+ENTRY(_sigreturn_stub)
+	P0 = __NR_rt_sigreturn;
+	EXCPT 0;
+	/* Speculative execution paranoia.  */
+0:	JUMP.S 0b;
+ENDPROC (_sigreturn_stub)
+
+.align 16
+	/*
+	 * Atomic swap, 8 bit.
+	 * Inputs:	P0: memory address to use
+	 *		R1: value to store
+	 * Output:	R0: old contents of the memory address, zero extended.
+	 */
+ENTRY(_atomic_xchg32)
+	R0 = [P0];
+	[P0] = R1;
+	rts;
+ENDPROC (_atomic_xchg32)
+
+.align 16
+	/*
+	 * Compare and swap, 32 bit.
+	 * Inputs:	P0: memory address to use
+	 *		R1: compare value
+	 *		R2: new value to store
+	 * The new value is stored if the contents of the memory
+	 * address is equal to the compare value.
+	 * Output:	R0: old contents of the memory address.
+	 */
+ENTRY(_atomic_cas32)
+	R0 = [P0];
+	CC = R0 == R1;
+	IF !CC JUMP 1f;
+	[P0] = R2;
+1:
+	rts;
+ENDPROC (_atomic_cas32)
+
+.align 16
+	/*
+	 * Atomic add, 32 bit.
+	 * Inputs:	P0: memory address to use
+	 *		R0: value to add
+	 * Outputs:	R0: new contents of the memory address.
+	 *		R1: previous contents of the memory address.
+	 */
+ENTRY(_atomic_add32)
+	R1 = [P0];
+	R0 = R1 + R0;
+	[P0] = R0;
+	rts;
+ENDPROC (_atomic_add32)
+
+.align 16
+	/*
+	 * Atomic sub, 32 bit.
+	 * Inputs:	P0: memory address to use
+	 *		R0: value to subtract
+	 * Outputs:	R0: new contents of the memory address.
+	 *		R1: previous contents of the memory address.
+	 */
+ENTRY(_atomic_sub32)
+	R1 = [P0];
+	R0 = R1 - R0;
+	[P0] = R0;
+	rts;
+ENDPROC (_atomic_sub32)
+
+.align 16
+	/*
+	 * Atomic ior, 32 bit.
+	 * Inputs:	P0: memory address to use
+	 *		R0: value to ior
+	 * Outputs:	R0: new contents of the memory address.
+	 *		R1: previous contents of the memory address.
+	 */
+ENTRY(_atomic_ior32)
+	R1 = [P0];
+	R0 = R1 | R0;
+	[P0] = R0;
+	rts;
+ENDPROC (_atomic_ior32)
+
+.align 16
+	/*
+	 * Atomic ior, 32 bit.
+	 * Inputs:	P0: memory address to use
+	 *		R0: value to ior
+	 * Outputs:	R0: new contents of the memory address.
+	 *		R1: previous contents of the memory address.
+	 */
+ENTRY(_atomic_and32)
+	R1 = [P0];
+	R0 = R1 & R0;
+	[P0] = R0;
+	rts;
+ENDPROC (_atomic_ior32)
+
+.align 16
+	/*
+	 * Atomic ior, 32 bit.
+	 * Inputs:	P0: memory address to use
+	 *		R0: value to ior
+	 * Outputs:	R0: new contents of the memory address.
+	 *		R1: previous contents of the memory address.
+	 */
+ENTRY(_atomic_xor32)
+	R1 = [P0];
+	R0 = R1 ^ R0;
+	[P0] = R0;
+	rts;
+ENDPROC (_atomic_ior32)
+
+ENTRY(_fixed_code_end)
diff --git a/arch/blackfin/kernel/flat.c b/arch/blackfin/kernel/flat.c
index a92587b..d188b24 100644
--- a/arch/blackfin/kernel/flat.c
+++ b/arch/blackfin/kernel/flat.c
@@ -36,24 +36,22 @@
 	unsigned long val;
 
 	switch (type) {
-		case FLAT_BFIN_RELOC_TYPE_16_BIT:
-		case FLAT_BFIN_RELOC_TYPE_16H_BIT:
-			usptr = (unsigned short *)ptr;
-			pr_debug("*usptr = %x", get_unaligned(usptr));
-			val = get_unaligned(usptr);
-			val += *persistent;
-			break;
+	case FLAT_BFIN_RELOC_TYPE_16_BIT:
+	case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+		usptr = (unsigned short *)ptr;
+		pr_debug("*usptr = %x", get_unaligned(usptr));
+		val = get_unaligned(usptr);
+		val += *persistent;
+		break;
 
-		case FLAT_BFIN_RELOC_TYPE_32_BIT:
-			pr_debug("*ptr = %lx", get_unaligned(ptr));
-			val = get_unaligned(ptr);
-			break;
+	case FLAT_BFIN_RELOC_TYPE_32_BIT:
+		pr_debug("*ptr = %lx", get_unaligned(ptr));
+		val = get_unaligned(ptr);
+		break;
 
-		default:
-			pr_debug("BINFMT_FLAT: Unknown relocation type %x\n",
-				type);
-
-			return 0;
+	default:
+		pr_debug("BINFMT_FLAT: Unknown relocation type %x\n", type);
+		return 0;
 	}
 
 	/*
@@ -81,21 +79,20 @@
 	int type = (relval >> 26) & 7;
 
 	switch (type) {
-		case FLAT_BFIN_RELOC_TYPE_16_BIT:
-			put_unaligned(addr, usptr);
-			pr_debug("new value %x at %p", get_unaligned(usptr),
-				usptr);
-			break;
+	case FLAT_BFIN_RELOC_TYPE_16_BIT:
+		put_unaligned(addr, usptr);
+		pr_debug("new value %x at %p", get_unaligned(usptr), usptr);
+		break;
 
-		case FLAT_BFIN_RELOC_TYPE_16H_BIT:
-			put_unaligned(addr >> 16, usptr);
-			pr_debug("new value %x", get_unaligned(usptr));
-			break;
+	case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+		put_unaligned(addr >> 16, usptr);
+		pr_debug("new value %x", get_unaligned(usptr));
+		break;
 
-		case FLAT_BFIN_RELOC_TYPE_32_BIT:
-			put_unaligned(addr, ptr);
-			pr_debug("new ptr =%lx", get_unaligned(ptr));
-			break;
+	case FLAT_BFIN_RELOC_TYPE_32_BIT:
+		put_unaligned(addr, ptr);
+		pr_debug("new ptr =%lx", get_unaligned(ptr));
+		break;
 	}
 }
 EXPORT_SYMBOL(bfin_put_addr_at_rp);
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
index df5bf02..1fc001c7 100644
--- a/arch/blackfin/kernel/irqchip.c
+++ b/arch/blackfin/kernel/irqchip.c
@@ -82,7 +82,7 @@
 			seq_printf(p, ", %s", action->name);
 
 		seq_putc(p, '\n');
-	      unlock:
+ unlock:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "Err: %10lu\n", irq_err_count);
@@ -91,7 +91,7 @@
 }
 
 /*
- * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
+ * do_IRQ handles all hardware IRQs.  Decoded IRQs should not
  * come via this function.  Instead, they should provide their
  * own 'handler'
  */
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
new file mode 100644
index 0000000..a9c1551
--- /dev/null
+++ b/arch/blackfin/kernel/kgdb.c
@@ -0,0 +1,421 @@
+/*
+ * File:         arch/blackfin/kernel/kgdb.c
+ * Based on:
+ * Author:       Sonic Zhang
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:          $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
+ *
+ * Modified:
+ *               Copyright 2005-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ptrace.h>		/* for linux pt_regs struct */
+#include <linux/kgdb.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/debugger.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/blackfin.h>
+
+/* Put the error code here just in case the user cares.  */
+int gdb_bf533errcode;
+/* Likewise, the vector number here (since GDB only gets the signal
+   number through the usual means, and that's not very specific).  */
+int gdb_bf533vector = -1;
+
+#if KGDB_MAX_NO_CPUS != 8
+#error change the definition of slavecpulocks
+#endif
+
+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	gdb_regs[BFIN_R0] = regs->r0;
+	gdb_regs[BFIN_R1] = regs->r1;
+	gdb_regs[BFIN_R2] = regs->r2;
+	gdb_regs[BFIN_R3] = regs->r3;
+	gdb_regs[BFIN_R4] = regs->r4;
+	gdb_regs[BFIN_R5] = regs->r5;
+	gdb_regs[BFIN_R6] = regs->r6;
+	gdb_regs[BFIN_R7] = regs->r7;
+	gdb_regs[BFIN_P0] = regs->p0;
+	gdb_regs[BFIN_P1] = regs->p1;
+	gdb_regs[BFIN_P2] = regs->p2;
+	gdb_regs[BFIN_P3] = regs->p3;
+	gdb_regs[BFIN_P4] = regs->p4;
+	gdb_regs[BFIN_P5] = regs->p5;
+	gdb_regs[BFIN_SP] = regs->reserved;
+	gdb_regs[BFIN_FP] = regs->fp;
+	gdb_regs[BFIN_I0] = regs->i0;
+	gdb_regs[BFIN_I1] = regs->i1;
+	gdb_regs[BFIN_I2] = regs->i2;
+	gdb_regs[BFIN_I3] = regs->i3;
+	gdb_regs[BFIN_M0] = regs->m0;
+	gdb_regs[BFIN_M1] = regs->m1;
+	gdb_regs[BFIN_M2] = regs->m2;
+	gdb_regs[BFIN_M3] = regs->m3;
+	gdb_regs[BFIN_B0] = regs->b0;
+	gdb_regs[BFIN_B1] = regs->b1;
+	gdb_regs[BFIN_B2] = regs->b2;
+	gdb_regs[BFIN_B3] = regs->b3;
+	gdb_regs[BFIN_L0] = regs->l0;
+	gdb_regs[BFIN_L1] = regs->l1;
+	gdb_regs[BFIN_L2] = regs->l2;
+	gdb_regs[BFIN_L3] = regs->l3;
+	gdb_regs[BFIN_A0_DOT_X] = regs->a0x;
+	gdb_regs[BFIN_A0_DOT_W] = regs->a0w;
+	gdb_regs[BFIN_A1_DOT_X] = regs->a1x;
+	gdb_regs[BFIN_A1_DOT_W] = regs->a1w;
+	gdb_regs[BFIN_ASTAT] = regs->astat;
+	gdb_regs[BFIN_RETS] = regs->rets;
+	gdb_regs[BFIN_LC0] = regs->lc0;
+	gdb_regs[BFIN_LT0] = regs->lt0;
+	gdb_regs[BFIN_LB0] = regs->lb0;
+	gdb_regs[BFIN_LC1] = regs->lc1;
+	gdb_regs[BFIN_LT1] = regs->lt1;
+	gdb_regs[BFIN_LB1] = regs->lb1;
+	gdb_regs[BFIN_CYCLES] = 0;
+	gdb_regs[BFIN_CYCLES2] = 0;
+	gdb_regs[BFIN_USP] = regs->usp;
+	gdb_regs[BFIN_SEQSTAT] = regs->seqstat;
+	gdb_regs[BFIN_SYSCFG] = regs->syscfg;
+	gdb_regs[BFIN_RETI] = regs->pc;
+	gdb_regs[BFIN_RETX] = regs->retx;
+	gdb_regs[BFIN_RETN] = regs->retn;
+	gdb_regs[BFIN_RETE] = regs->rete;
+	gdb_regs[BFIN_PC] = regs->pc;
+	gdb_regs[BFIN_CC] = 0;
+	gdb_regs[BFIN_EXTRA1] = 0;
+	gdb_regs[BFIN_EXTRA2] = 0;
+	gdb_regs[BFIN_EXTRA3] = 0;
+	gdb_regs[BFIN_IPEND] = regs->ipend;
+}
+
+/*
+ * Extracts ebp, esp and eip values understandable by gdb from the values
+ * saved by switch_to.
+ * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
+ * prior to entering switch_to is 8 greater then the value that is saved.
+ * If switch_to changes, change following code appropriately.
+ */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+{
+	gdb_regs[BFIN_SP] = p->thread.ksp;
+	gdb_regs[BFIN_PC] = p->thread.pc;
+	gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat;
+}
+
+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	regs->r0 = gdb_regs[BFIN_R0];
+	regs->r1 = gdb_regs[BFIN_R1];
+	regs->r2 = gdb_regs[BFIN_R2];
+	regs->r3 = gdb_regs[BFIN_R3];
+	regs->r4 = gdb_regs[BFIN_R4];
+	regs->r5 = gdb_regs[BFIN_R5];
+	regs->r6 = gdb_regs[BFIN_R6];
+	regs->r7 = gdb_regs[BFIN_R7];
+	regs->p0 = gdb_regs[BFIN_P0];
+	regs->p1 = gdb_regs[BFIN_P1];
+	regs->p2 = gdb_regs[BFIN_P2];
+	regs->p3 = gdb_regs[BFIN_P3];
+	regs->p4 = gdb_regs[BFIN_P4];
+	regs->p5 = gdb_regs[BFIN_P5];
+	regs->fp = gdb_regs[BFIN_FP];
+	regs->i0 = gdb_regs[BFIN_I0];
+	regs->i1 = gdb_regs[BFIN_I1];
+	regs->i2 = gdb_regs[BFIN_I2];
+	regs->i3 = gdb_regs[BFIN_I3];
+	regs->m0 = gdb_regs[BFIN_M0];
+	regs->m1 = gdb_regs[BFIN_M1];
+	regs->m2 = gdb_regs[BFIN_M2];
+	regs->m3 = gdb_regs[BFIN_M3];
+	regs->b0 = gdb_regs[BFIN_B0];
+	regs->b1 = gdb_regs[BFIN_B1];
+	regs->b2 = gdb_regs[BFIN_B2];
+	regs->b3 = gdb_regs[BFIN_B3];
+	regs->l0 = gdb_regs[BFIN_L0];
+	regs->l1 = gdb_regs[BFIN_L1];
+	regs->l2 = gdb_regs[BFIN_L2];
+	regs->l3 = gdb_regs[BFIN_L3];
+	regs->a0x = gdb_regs[BFIN_A0_DOT_X];
+	regs->a0w = gdb_regs[BFIN_A0_DOT_W];
+	regs->a1x = gdb_regs[BFIN_A1_DOT_X];
+	regs->a1w = gdb_regs[BFIN_A1_DOT_W];
+	regs->rets = gdb_regs[BFIN_RETS];
+	regs->lc0 = gdb_regs[BFIN_LC0];
+	regs->lt0 = gdb_regs[BFIN_LT0];
+	regs->lb0 = gdb_regs[BFIN_LB0];
+	regs->lc1 = gdb_regs[BFIN_LC1];
+	regs->lt1 = gdb_regs[BFIN_LT1];
+	regs->lb1 = gdb_regs[BFIN_LB1];
+	regs->usp = gdb_regs[BFIN_USP];
+	regs->syscfg = gdb_regs[BFIN_SYSCFG];
+	regs->retx = gdb_regs[BFIN_PC];
+	regs->retn = gdb_regs[BFIN_RETN];
+	regs->rete = gdb_regs[BFIN_RETE];
+	regs->pc = gdb_regs[BFIN_PC];
+
+#if 0				/* can't change these */
+	regs->astat = gdb_regs[BFIN_ASTAT];
+	regs->seqstat = gdb_regs[BFIN_SEQSTAT];
+	regs->ipend = gdb_regs[BFIN_IPEND];
+#endif
+}
+
+struct hw_breakpoint {
+	unsigned int occupied:1;
+	unsigned int skip:1;
+	unsigned int enabled:1;
+	unsigned int type:1;
+	unsigned int dataacc:2;
+	unsigned short count;
+	unsigned int addr;
+} breakinfo[HW_BREAKPOINT_NUM];
+
+int kgdb_arch_init(void)
+{
+	kgdb_remove_all_hw_break();
+	return 0;
+}
+
+int kgdb_set_hw_break(unsigned long addr)
+{
+	int breakno;
+	for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
+		if (!breakinfo[breakno].occupied) {
+			breakinfo[breakno].occupied = 1;
+			breakinfo[breakno].enabled = 1;
+			breakinfo[breakno].type = 1;
+			breakinfo[breakno].addr = addr;
+			return 0;
+		}
+
+	return -ENOSPC;
+}
+
+int kgdb_remove_hw_break(unsigned long addr)
+{
+	int breakno;
+	for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
+		if (breakinfo[breakno].addr == addr)
+			memset(&(breakinfo[breakno]), 0, sizeof(struct hw_breakpoint));
+
+	return 0;
+}
+
+void kgdb_remove_all_hw_break(void)
+{
+	memset(breakinfo, 0, sizeof(struct hw_breakpoint)*8);
+}
+
+/*
+void kgdb_show_info(void)
+{
+	printk(KERN_DEBUG "hwd: wpia0=0x%x, wpiacnt0=%d, wpiactl=0x%x, wpstat=0x%x\n",
+		bfin_read_WPIA0(), bfin_read_WPIACNT0(),
+		bfin_read_WPIACTL(), bfin_read_WPSTAT());
+}
+*/
+
+void kgdb_correct_hw_break(void)
+{
+	int breakno;
+	int correctit;
+	uint32_t wpdactl = bfin_read_WPDACTL();
+
+	correctit = 0;
+	for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) {
+		if (breakinfo[breakno].type == 1) {
+			switch (breakno) {
+			case 0:
+				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) {
+					correctit = 1;
+					wpdactl &= ~(WPIREN01|EMUSW0);
+					wpdactl |= WPIAEN0|WPICNTEN0;
+					bfin_write_WPIA0(breakinfo[breakno].addr);
+					bfin_write_WPIACNT0(breakinfo[breakno].skip);
+				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) {
+					correctit = 1;
+					wpdactl &= ~WPIAEN0;
+				}
+				break;
+
+			case 1:
+				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) {
+					correctit = 1;
+					wpdactl &= ~(WPIREN01|EMUSW1);
+					wpdactl |= WPIAEN1|WPICNTEN1;
+					bfin_write_WPIA1(breakinfo[breakno].addr);
+					bfin_write_WPIACNT1(breakinfo[breakno].skip);
+				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) {
+					correctit = 1;
+					wpdactl &= ~WPIAEN1;
+				}
+				break;
+
+			case 2:
+				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) {
+					correctit = 1;
+					wpdactl &= ~(WPIREN23|EMUSW2);
+					wpdactl |= WPIAEN2|WPICNTEN2;
+					bfin_write_WPIA2(breakinfo[breakno].addr);
+					bfin_write_WPIACNT2(breakinfo[breakno].skip);
+				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) {
+					correctit = 1;
+					wpdactl &= ~WPIAEN2;
+				}
+				break;
+
+			case 3:
+				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) {
+					correctit = 1;
+					wpdactl &= ~(WPIREN23|EMUSW3);
+					wpdactl |= WPIAEN3|WPICNTEN3;
+					bfin_write_WPIA3(breakinfo[breakno].addr);
+					bfin_write_WPIACNT3(breakinfo[breakno].skip);
+				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) {
+					correctit = 1;
+					wpdactl &= ~WPIAEN3;
+				}
+				break;
+			case 4:
+				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) {
+					correctit = 1;
+					wpdactl &= ~(WPIREN45|EMUSW4);
+					wpdactl |= WPIAEN4|WPICNTEN4;
+					bfin_write_WPIA4(breakinfo[breakno].addr);
+					bfin_write_WPIACNT4(breakinfo[breakno].skip);
+				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) {
+					correctit = 1;
+					wpdactl &= ~WPIAEN4;
+				}
+				break;
+			case 5:
+				if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) {
+					correctit = 1;
+					wpdactl &= ~(WPIREN45|EMUSW5);
+					wpdactl |= WPIAEN5|WPICNTEN5;
+					bfin_write_WPIA5(breakinfo[breakno].addr);
+					bfin_write_WPIACNT5(breakinfo[breakno].skip);
+				} else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) {
+					correctit = 1;
+					wpdactl &= ~WPIAEN5;
+				}
+				break;
+			}
+		}
+	}
+	if (correctit) {
+		wpdactl &= ~WPAND;
+		wpdactl |= WPPWR;
+		/*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/
+		bfin_write_WPDACTL(wpdactl);
+		CSYNC();
+		/*kgdb_show_info();*/
+	}
+}
+
+void kgdb_disable_hw_debug(struct pt_regs *regs)
+{
+	/* Disable hardware debugging while we are in kgdb */
+	bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1);
+	CSYNC();
+}
+
+void kgdb_post_master_code(struct pt_regs *regs, int eVector, int err_code)
+{
+	/* Master processor is completely in the debugger */
+	gdb_bf533vector = eVector;
+	gdb_bf533errcode = err_code;
+}
+
+int kgdb_arch_handle_exception(int exceptionVector, int signo,
+			       int err_code, char *remcom_in_buffer,
+			       char *remcom_out_buffer,
+			       struct pt_regs *linux_regs)
+{
+	long addr;
+	long breakno;
+	char *ptr;
+	int newPC;
+	int wp_status;
+
+	switch (remcom_in_buffer[0]) {
+	case 'c':
+	case 's':
+		if (kgdb_contthread && kgdb_contthread != current) {
+			strcpy(remcom_out_buffer, "E00");
+			break;
+		}
+
+		kgdb_contthread = NULL;
+
+		/* try to read optional parameter, pc unchanged if no parm */
+		ptr = &remcom_in_buffer[1];
+		if (kgdb_hex2long(&ptr, &addr)) {
+			linux_regs->retx = addr;
+		}
+		newPC = linux_regs->retx;
+
+		/* clear the trace bit */
+		linux_regs->syscfg &= 0xfffffffe;
+
+		/* set the trace bit if we're stepping */
+		if (remcom_in_buffer[0] == 's') {
+			linux_regs->syscfg |= 0x1;
+			debugger_step = 1;
+		}
+
+		wp_status = bfin_read_WPSTAT();
+		CSYNC();
+
+		if (exceptionVector == VEC_WATCH) {
+			for (breakno = 0; breakno < 6; ++breakno) {
+				if (wp_status & (1 << breakno)) {
+					breakinfo->skip = 1;
+					break;
+				}
+			}
+		}
+		kgdb_correct_hw_break();
+
+		bfin_write_WPSTAT(0);
+
+		return 0;
+	}			/* switch */
+	return -1;		/* this means that we do not want to exit from the handler */
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+	.gdb_bpt_instr = {0xa1},
+	.flags = KGDB_HW_BREAKPOINT,
+};
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index 372f756..8b9fe29 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -165,8 +165,8 @@
 
 	for (s = sechdrs; s < sechdrs_end; ++s) {
 		if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
-			((strcmp(".text", secstrings + s->sh_name)==0) &&
-			 (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) {
+		    ((strcmp(".text", secstrings + s->sh_name) == 0) &&
+		     (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) {
 			mod->arch.text_l1 = s;
 			dest = l1_inst_sram_alloc(s->sh_size);
 			if (dest == NULL) {
@@ -179,9 +179,9 @@
 			s->sh_flags &= ~SHF_ALLOC;
 			s->sh_addr = (unsigned long)dest;
 		}
-		if ((strcmp(".l1.data", secstrings + s->sh_name) == 0)||
-			((strcmp(".data", secstrings + s->sh_name)==0) &&
-			 (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+		if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) ||
+		    ((strcmp(".data", secstrings + s->sh_name) == 0) &&
+		     (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
 			mod->arch.data_a_l1 = s;
 			dest = l1_data_sram_alloc(s->sh_size);
 			if (dest == NULL) {
@@ -195,8 +195,8 @@
 			s->sh_addr = (unsigned long)dest;
 		}
 		if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
-			((strcmp(".bss", secstrings + s->sh_name)==0) &&
-			 (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+		    ((strcmp(".bss", secstrings + s->sh_name) == 0) &&
+		     (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
 			mod->arch.bss_a_l1 = s;
 			dest = l1_data_sram_alloc(s->sh_size);
 			if (dest == NULL) {
@@ -326,7 +326,7 @@
 			pr_debug("before %x after %x\n", *location16,
 				       (value & 0xffff));
 			tmp = (value & 0xffff);
-			if((unsigned long)location16 >= L1_CODE_START) {
+			if ((unsigned long)location16 >= L1_CODE_START) {
 				dma_memcpy(location16, &tmp, 2);
 			} else
 				*location16 = tmp;
@@ -335,7 +335,7 @@
 			pr_debug("before %x after %x\n", *location16,
 				       ((value >> 16) & 0xffff));
 			tmp = ((value >> 16) & 0xffff);
-			if((unsigned long)location16 >= L1_CODE_START) {
+			if ((unsigned long)location16 >= L1_CODE_START) {
 				dma_memcpy(location16, &tmp, 2);
 			} else
 				*location16 = tmp;
@@ -404,8 +404,8 @@
 			continue;
 
 		if ((sechdrs[i].sh_type == SHT_RELA) &&
-		    ((strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0)||
-			((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
+		    ((strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
+		    ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
 			 (hdr->e_flags & FLG_CODE_IN_L1)))) {
 			apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
 					   symindex, i, mod);
@@ -417,13 +417,13 @@
 void module_arch_cleanup(struct module *mod)
 {
 	if ((mod->arch.text_l1) && (mod->arch.text_l1->sh_addr))
-		l1_inst_sram_free((void*)mod->arch.text_l1->sh_addr);
+		l1_inst_sram_free((void *)mod->arch.text_l1->sh_addr);
 	if ((mod->arch.data_a_l1) && (mod->arch.data_a_l1->sh_addr))
-		l1_data_sram_free((void*)mod->arch.data_a_l1->sh_addr);
+		l1_data_sram_free((void *)mod->arch.data_a_l1->sh_addr);
 	if ((mod->arch.bss_a_l1) && (mod->arch.bss_a_l1->sh_addr))
-		l1_data_sram_free((void*)mod->arch.bss_a_l1->sh_addr);
+		l1_data_sram_free((void *)mod->arch.bss_a_l1->sh_addr);
 	if ((mod->arch.data_b_l1) && (mod->arch.data_b_l1->sh_addr))
-		l1_data_B_sram_free((void*)mod->arch.data_b_l1->sh_addr);
+		l1_data_B_sram_free((void *)mod->arch.data_b_l1->sh_addr);
 	if ((mod->arch.bss_b_l1) && (mod->arch.bss_b_l1->sh_addr))
-		l1_data_B_sram_free((void*)mod->arch.bss_b_l1->sh_addr);
+		l1_data_B_sram_free((void *)mod->arch.bss_b_l1->sh_addr);
 }
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 3eff743..5a51dd6 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -32,9 +32,10 @@
 #include <linux/unistd.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
+#include <linux/uaccess.h>
 
 #include <asm/blackfin.h>
-#include <asm/uaccess.h>
+#include <asm/fixed_code.h>
 
 #define	LED_ON	0
 #define	LED_OFF	1
@@ -173,8 +174,8 @@
 	printk(KERN_NOTICE "R4: %08lx  R5: %08lx  R6: %08lx  R7: %08lx\n",
 	       regs->r4, regs->r5, regs->r6, regs->r7);
 
-	if (!(regs->ipend))
-		printk("USP: %08lx\n", rdusp());
+	if (!regs->ipend)
+		printk(KERN_NOTICE "USP: %08lx\n", rdusp());
 }
 
 /* Fill in the fpu structure for a core dump.  */
@@ -322,7 +323,7 @@
 		goto out;
 	error = do_execve(filename, argv, envp, regs);
 	putname(filename);
-      out:
+ out:
 	unlock_kernel();
 	return error;
 }
@@ -350,13 +351,77 @@
 	return 0;
 }
 
+void finish_atomic_sections (struct pt_regs *regs)
+{
+	if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
+		return;
+
+	switch (regs->pc) {
+	case ATOMIC_XCHG32 + 2:
+		put_user(regs->r1, (int *)regs->p0);
+		regs->pc += 2;
+		break;
+
+	case ATOMIC_CAS32 + 2:
+	case ATOMIC_CAS32 + 4:
+		if (regs->r0 == regs->r1)
+			put_user(regs->r2, (int *)regs->p0);
+		regs->pc = ATOMIC_CAS32 + 8;
+		break;
+	case ATOMIC_CAS32 + 6:
+		put_user(regs->r2, (int *)regs->p0);
+		regs->pc += 2;
+		break;
+
+	case ATOMIC_ADD32 + 2:
+		regs->r0 = regs->r1 + regs->r0;
+		/* fall through */
+	case ATOMIC_ADD32 + 4:
+		put_user(regs->r0, (int *)regs->p0);
+		regs->pc = ATOMIC_ADD32 + 6;
+		break;
+
+	case ATOMIC_SUB32 + 2:
+		regs->r0 = regs->r1 - regs->r0;
+		/* fall through */
+	case ATOMIC_SUB32 + 4:
+		put_user(regs->r0, (int *)regs->p0);
+		regs->pc = ATOMIC_SUB32 + 6;
+		break;
+
+	case ATOMIC_IOR32 + 2:
+		regs->r0 = regs->r1 | regs->r0;
+		/* fall through */
+	case ATOMIC_IOR32 + 4:
+		put_user(regs->r0, (int *)regs->p0);
+		regs->pc = ATOMIC_IOR32 + 6;
+		break;
+
+	case ATOMIC_AND32 + 2:
+		regs->r0 = regs->r1 & regs->r0;
+		/* fall through */
+	case ATOMIC_AND32 + 4:
+		put_user(regs->r0, (int *)regs->p0);
+		regs->pc = ATOMIC_AND32 + 6;
+		break;
+
+	case ATOMIC_XOR32 + 2:
+		regs->r0 = regs->r1 ^ regs->r0;
+		/* fall through */
+	case ATOMIC_XOR32 + 4:
+		put_user(regs->r0, (int *)regs->p0);
+		regs->pc = ATOMIC_XOR32 + 6;
+		break;
+	}
+}
+
 #if defined(CONFIG_ACCESS_CHECK)
 int _access_ok(unsigned long addr, unsigned long size)
 {
 
 	if (addr > (addr + size))
 		return 0;
-	if (segment_eq(get_fs(),KERNEL_DS))
+	if (segment_eq(get_fs(), KERNEL_DS))
 		return 1;
 #ifdef CONFIG_MTD_UCLINUX
 	if (addr >= memory_start && (addr + size) <= memory_end)
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index e718bb4..ed800c7 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -36,8 +36,8 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/signal.h>
+#include <linux/uaccess.h>
 
-#include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -122,7 +122,7 @@
 static inline int
 put_reg(struct task_struct *task, int regno, unsigned long data)
 {
-	char * reg_ptr;
+	char *reg_ptr;
 
 	struct pt_regs *regs =
 	    (struct pt_regs *)((unsigned long)task_stack_page(task) +
@@ -146,7 +146,7 @@
 		break;
 	default:
 		if (regno <= 216)
-		        *(long *)(reg_ptr + regno) = data;
+			*(long *)(reg_ptr + regno) = data;
 	}
 	return 0;
 }
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 342bb8d..f59dcee 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -33,7 +33,6 @@
 #include <linux/seq_file.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
-#include <linux/console.h>
 #include <linux/tty.h>
 
 #include <linux/ext2_fs.h>
@@ -43,6 +42,9 @@
 #include <asm/cacheflush.h>
 #include <asm/blackfin.h>
 #include <asm/cplbinit.h>
+#include <asm/fixed_code.h>
+
+u16 _bfin_swrst;
 
 unsigned long memory_start, memory_end, physical_mem_end;
 unsigned long reserved_mem_dcache_on;
@@ -60,11 +62,7 @@
 EXPORT_SYMBOL(mtd_size);
 #endif
 
-char command_line[COMMAND_LINE_SIZE];
-
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-static void generate_cpl_tables(void);
-#endif
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 void __init bf53x_cache_init(void)
 {
@@ -89,7 +87,7 @@
 #endif
 }
 
-void bf53x_relocate_l1_mem(void)
+void __init bf53x_relocate_l1_mem(void)
 {
 	unsigned long l1_code_length;
 	unsigned long l1_data_a_length;
@@ -175,6 +173,9 @@
 	unsigned long mtd_phys = 0;
 #endif
 
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
 	cclk = get_cclk();
 	sclk = get_sclk();
 
@@ -193,6 +194,17 @@
 	/* this give a chance to get printk() working before crash. */
 #endif
 
+	printk(KERN_INFO "Hardware Trace ");
+	if (bfin_read_TBUFCTL() & 0x1 )
+		printk("Active ");
+	else
+		printk("Off ");
+	if (bfin_read_TBUFCTL() & 0x2)
+		printk("and Enabled\n");
+	else
+	printk("and Disabled\n");
+
+
 #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
 	/* we need to initialize the Flashrom device here since we might
 	 * do things with flash early on in the boot
@@ -201,7 +213,6 @@
 #endif
 
 #if defined(CONFIG_CMDLINE_BOOL)
-	memset(command_line, 0, sizeof(command_line));
 	strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line));
 	command_line[sizeof(command_line) - 1] = 0;
 #endif
@@ -209,7 +220,7 @@
 	/* Keep a copy of command line */
 	*cmdline_p = &command_line[0];
 	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
-	boot_command_line[COMMAND_LINE_SIZE - 1] = 0;
+	boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
 
 	/* setup memory defaults from the user config */
 	physical_mem_end = 0;
@@ -304,10 +315,20 @@
 	init_leds();
 
 	printk(KERN_INFO "Blackfin support (C) 2004-2007 Analog Devices, Inc.\n");
-	printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid());
-	if (bfin_revid() != bfin_compiled_revid())
-		printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
-		       bfin_compiled_revid(), bfin_revid());
+	if (bfin_compiled_revid() == 0xffff)
+		printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU);
+	else if (bfin_compiled_revid() == -1)
+		printk(KERN_INFO "Compiled for ADSP-%s Rev none\n", CPU);
+	else
+		printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid());
+	if (bfin_revid() != bfin_compiled_revid()) {
+		if (bfin_compiled_revid() == -1)
+			printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n",
+			       bfin_revid());
+		else if (bfin_compiled_revid() != 0xffff)
+			printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
+			       bfin_compiled_revid(), bfin_revid());
+	}
 	if (bfin_revid() < SUPPORTED_REVID)
 		printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
 		       CPU, bfin_revid());
@@ -326,9 +347,10 @@
 
 	printk(KERN_INFO "Memory map:\n"
 	       KERN_INFO "  text      = 0x%p-0x%p\n"
-	       KERN_INFO "  init      = 0x%p-0x%p\n"
+	       KERN_INFO "  rodata    = 0x%p-0x%p\n"
 	       KERN_INFO "  data      = 0x%p-0x%p\n"
-	       KERN_INFO "  stack     = 0x%p-0x%p\n"
+	       KERN_INFO "    stack   = 0x%p-0x%p\n"
+	       KERN_INFO "  init      = 0x%p-0x%p\n"
 	       KERN_INFO "  bss       = 0x%p-0x%p\n"
 	       KERN_INFO "  available = 0x%p-0x%p\n"
 #ifdef CONFIG_MTD_UCLINUX
@@ -338,16 +360,17 @@
 	       KERN_INFO "  DMA Zone  = 0x%p-0x%p\n"
 #endif
 	       , _stext, _etext,
-	       __init_begin, __init_end,
+	       __start_rodata, __end_rodata,
 	       _sdata, _edata,
-	       (void*)&init_thread_union, (void*)((int)(&init_thread_union) + 0x2000),
+	       (void *)&init_thread_union, (void *)((int)(&init_thread_union) + 0x2000),
+	       __init_begin, __init_end,
 	       __bss_start, __bss_stop,
-	       (void*)_ramstart, (void*)memory_end
+	       (void *)_ramstart, (void *)memory_end
 #ifdef CONFIG_MTD_UCLINUX
-	       , (void*)memory_mtd_start, (void*)(memory_mtd_start + mtd_size)
+	       , (void *)memory_mtd_start, (void *)(memory_mtd_start + mtd_size)
 #endif
 #if DMA_UNCACHED_REGION > 0
-	       , (void*)(_ramend - DMA_UNCACHED_REGION), (void*)(_ramend)
+	       , (void *)(_ramend - DMA_UNCACHED_REGION), (void *)(_ramend)
 #endif
 	       );
 
@@ -373,321 +396,58 @@
 	/* check the size of the l1 area */
 	l1_length = _etext_l1 - _stext_l1;
 	if (l1_length > L1_CODE_LENGTH)
-		panic("L1 memory overflow\n");
+		panic("L1 code memory overflow\n");
 
 	l1_length = _ebss_l1 - _sdata_l1;
 	if (l1_length > L1_DATA_A_LENGTH)
-		panic("L1 memory overflow\n");
+		panic("L1 data memory overflow\n");
+
+#ifdef BF561_FAMILY
+	_bfin_swrst = bfin_read_SICA_SWRST();
+#else
+	_bfin_swrst = bfin_read_SWRST();
+#endif
+
+	/* Copy atomic sequences to their fixed location, and sanity check that
+	   these locations are the ones that we advertise to userspace.  */
+	memcpy((void *)FIXED_CODE_START, &fixed_code_start,
+	       FIXED_CODE_END - FIXED_CODE_START);
+	BUG_ON((char *)&sigreturn_stub - (char *)&fixed_code_start
+	       != SIGRETURN_STUB - FIXED_CODE_START);
+	BUG_ON((char *)&atomic_xchg32 - (char *)&fixed_code_start
+	       != ATOMIC_XCHG32 - FIXED_CODE_START);
+	BUG_ON((char *)&atomic_cas32 - (char *)&fixed_code_start
+	       != ATOMIC_CAS32 - FIXED_CODE_START);
+	BUG_ON((char *)&atomic_add32 - (char *)&fixed_code_start
+	       != ATOMIC_ADD32 - FIXED_CODE_START);
+	BUG_ON((char *)&atomic_sub32 - (char *)&fixed_code_start
+	       != ATOMIC_SUB32 - FIXED_CODE_START);
+	BUG_ON((char *)&atomic_ior32 - (char *)&fixed_code_start
+	       != ATOMIC_IOR32 - FIXED_CODE_START);
+	BUG_ON((char *)&atomic_and32 - (char *)&fixed_code_start
+	       != ATOMIC_AND32 - FIXED_CODE_START);
+	BUG_ON((char *)&atomic_xor32 - (char *)&fixed_code_start
+	       != ATOMIC_XOR32 - FIXED_CODE_START);
 
 	bf53x_cache_init();
-
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-# if defined(CONFIG_BFIN_SHARED_FLASH_ENET) && defined(CONFIG_BFIN533_STAMP)
-	/* setup BF533_STAMP CPLD to route AMS3 to Ethernet MAC */
-	bfin_write_FIO_DIR(bfin_read_FIO_DIR() | (1 << CONFIG_ENET_FLASH_PIN));
-	bfin_write_FIO_FLAG_S(1 << CONFIG_ENET_FLASH_PIN);
-	SSYNC();
-# endif
-# if defined (CONFIG_BFIN561_EZKIT)
-	bfin_write_FIO0_DIR(bfin_read_FIO0_DIR() | (1 << 12));
-	SSYNC();
-# endif /* defined (CONFIG_BFIN561_EZKIT) */
-#endif
-
-	printk(KERN_INFO "Hardware Trace Enabled\n");
-	bfin_write_TBUFCTL(0x03);
 }
 
-#if defined(CONFIG_BF561)
-static struct cpu cpu[2];
-#else
-static struct cpu cpu[1];
-#endif
 static int __init topology_init(void)
 {
 #if defined (CONFIG_BF561)
+	static struct cpu cpu[2];
 	register_cpu(&cpu[0], 0);
 	register_cpu(&cpu[1], 1);
 	return 0;
 #else
+	static struct cpu cpu[1];
 	return register_cpu(cpu, 0);
 #endif
 }
 
 subsys_initcall(topology_init);
 
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-u16 lock_kernel_check(u32 start, u32 end)
-{
-	if ((start <= (u32) _stext && end >= (u32) _end)
-	    || (start >= (u32) _stext && end <= (u32) _end))
-		return IN_KERNEL;
-	return 0;
-}
-
-static unsigned short __init
-fill_cplbtab(struct cplb_tab *table,
-	     unsigned long start, unsigned long end,
-	     unsigned long block_size, unsigned long cplb_data)
-{
-	int i;
-
-	switch (block_size) {
-	case SIZE_4M:
-		i = 3;
-		break;
-	case SIZE_1M:
-		i = 2;
-		break;
-	case SIZE_4K:
-		i = 1;
-		break;
-	case SIZE_1K:
-	default:
-		i = 0;
-		break;
-	}
-
-	cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
-
-	while ((start < end) && (table->pos < table->size)) {
-
-		table->tab[table->pos++] = start;
-
-		if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
-			table->tab[table->pos++] =
-			    cplb_data | CPLB_LOCK | CPLB_DIRTY;
-		else
-			table->tab[table->pos++] = cplb_data;
-
-		start += block_size;
-	}
-	return 0;
-}
-
-static unsigned short __init
-close_cplbtab(struct cplb_tab *table)
-{
-
-	while (table->pos < table->size) {
-
-		table->tab[table->pos++] = 0;
-		table->tab[table->pos++] = 0; /* !CPLB_VALID */
-	}
-	return 0;
-}
-
-static void __init generate_cpl_tables(void)
-{
-
-	u16 i, j, process;
-	u32 a_start, a_end, as, ae, as_1m;
-
-	struct cplb_tab *t_i = NULL;
-	struct cplb_tab *t_d = NULL;
-	struct s_cplb cplb;
-
-	cplb.init_i.size = MAX_CPLBS;
-	cplb.init_d.size = MAX_CPLBS;
-	cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
-	cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
-
-	cplb.init_i.pos = 0;
-	cplb.init_d.pos = 0;
-	cplb.switch_i.pos = 0;
-	cplb.switch_d.pos = 0;
-
-	cplb.init_i.tab = icplb_table;
-	cplb.init_d.tab = dcplb_table;
-	cplb.switch_i.tab = ipdt_table;
-	cplb.switch_d.tab = dpdt_table;
-
-	cplb_data[SDRAM_KERN].end = memory_end;
-
-#ifdef CONFIG_MTD_UCLINUX
-	cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
-	cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
-	cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
-# if defined(CONFIG_ROMFS_FS)
-	cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
-
-	/*
-	 * The ROMFS_FS size is often not multiple of 1MB.
-	 * This can cause multiple CPLB sets covering the same memory area.
-	 * This will then cause multiple CPLB hit exceptions.
-	 * Workaround: We ensure a contiguous memory area by extending the kernel
-	 * memory section over the mtd section.
-	 * For ROMFS_FS memory must be covered with ICPLBs anyways.
-	 * So there is no difference between kernel and mtd memory setup.
-	 */
-
-	cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
-	cplb_data[SDRAM_RAM_MTD].valid = 0;
-
-# endif
-#else
-	cplb_data[SDRAM_RAM_MTD].valid = 0;
-#endif
-
-	cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
-	cplb_data[SDRAM_DMAZ].end = _ramend;
-
-	cplb_data[RES_MEM].start = _ramend;
-	cplb_data[RES_MEM].end = physical_mem_end;
-
-	if (reserved_mem_dcache_on)
-		cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
-	else
-		cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
-
-	if (reserved_mem_icache_on)
-		cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
-	else
-		cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
-
-	for (i = ZERO_P; i <= L2_MEM; i++) {
-
-		if (cplb_data[i].valid) {
-
-			as_1m = cplb_data[i].start % SIZE_1M;
-
-			/* We need to make sure all sections are properly 1M aligned
-			 * However between Kernel Memory and the Kernel mtd section, depending on the
-			 * rootfs size, there can be overlapping memory areas.
-			 */
-
-			if (as_1m &&  i!=L1I_MEM && i!=L1D_MEM) {
-#ifdef CONFIG_MTD_UCLINUX
-				if (i == SDRAM_RAM_MTD) {
-					if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
-						cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
-					else
-						cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
-				} else
-#endif
-					printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
-					       cplb_data[i].name, cplb_data[i].start);
-			}
-
-			as = cplb_data[i].start % SIZE_4M;
-			ae = cplb_data[i].end % SIZE_4M;
-
-			if (as)
-				a_start = cplb_data[i].start + (SIZE_4M - (as));
-			else
-				a_start = cplb_data[i].start;
-
-			a_end = cplb_data[i].end - ae;
-
-			for (j = INITIAL_T; j <= SWITCH_T; j++) {
-
-				switch (j) {
-				case INITIAL_T:
-					if (cplb_data[i].attr & INITIAL_T) {
-						t_i = &cplb.init_i;
-						t_d = &cplb.init_d;
-						process = 1;
-					} else
-						process = 0;
-					break;
-				case SWITCH_T:
-					if (cplb_data[i].attr & SWITCH_T) {
-						t_i = &cplb.switch_i;
-						t_d = &cplb.switch_d;
-						process = 1;
-					} else
-						process = 0;
-					break;
-				default:
-						process = 0;
-					break;
-				}
-
-	if (process) {
-				if (cplb_data[i].attr & I_CPLB) {
-
-					if (cplb_data[i].psize) {
-						fill_cplbtab(t_i,
-							     cplb_data[i].start,
-							     cplb_data[i].end,
-							     cplb_data[i].psize,
-							     cplb_data[i].i_conf);
-					} else {
-						/*icplb_table */
-#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
-						if (i == SDRAM_KERN) {
-							fill_cplbtab(t_i,
-								     cplb_data[i].start,
-								     cplb_data[i].end,
-								     SIZE_4M,
-								     cplb_data[i].i_conf);
-						} else
-#endif
-						{
-							fill_cplbtab(t_i,
-								     cplb_data[i].start,
-								     a_start,
-								     SIZE_1M,
-								     cplb_data[i].i_conf);
-							fill_cplbtab(t_i,
-								     a_start,
-								     a_end,
-								     SIZE_4M,
-								     cplb_data[i].i_conf);
-							fill_cplbtab(t_i, a_end,
-								     cplb_data[i].end,
-								     SIZE_1M,
-								     cplb_data[i].i_conf);
-						}
-					}
-
-				}
-				if (cplb_data[i].attr & D_CPLB) {
-
-					if (cplb_data[i].psize) {
-						fill_cplbtab(t_d,
-							     cplb_data[i].start,
-							     cplb_data[i].end,
-							     cplb_data[i].psize,
-							     cplb_data[i].d_conf);
-					} else {
-/*dcplb_table*/
-						fill_cplbtab(t_d,
-							     cplb_data[i].start,
-							     a_start, SIZE_1M,
-							     cplb_data[i].d_conf);
-						fill_cplbtab(t_d, a_start,
-							     a_end, SIZE_4M,
-							     cplb_data[i].d_conf);
-						fill_cplbtab(t_d, a_end,
-							     cplb_data[i].end,
-							     SIZE_1M,
-							     cplb_data[i].d_conf);
-
-					}
-
-				}
-			}
-			}
-
-		}
-	}
-
-/* close tables */
-
-	close_cplbtab(&cplb.init_i);
-	close_cplbtab(&cplb.init_d);
-
-	cplb.init_i.tab[cplb.init_i.pos] = -1;
-	cplb.init_d.tab[cplb.init_d.pos] = -1;
-	cplb.switch_i.tab[cplb.switch_i.pos] = -1;
-	cplb.switch_d.tab[cplb.switch_d.pos] = -1;
-
-}
-
-#endif
-
-static inline u_long get_vco(void)
+static u_long get_vco(void)
 {
 	u_long msel;
 	u_long vco;
@@ -716,7 +476,6 @@
 		return get_vco() / ssel;
 	return get_vco() >> csel;
 }
-
 EXPORT_SYMBOL(get_cclk);
 
 /* Get the System clock */
@@ -735,7 +494,6 @@
 
 	return get_vco() / ssel;
 }
-
 EXPORT_SYMBOL(get_sclk);
 
 /*
@@ -790,23 +548,23 @@
 		seq_printf(m, "D-CACHE:\tOFF\n");
 
 
-	switch(bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
-		case ACACHE_BSRAM:
-			seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
-			dcache_size = 16;
-			dsup_banks = 1;
-			break;
-		case ACACHE_BCACHE:
-			seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
-			dcache_size = 32;
-			dsup_banks = 2;
-			break;
-		case ASRAM_BSRAM:
-			seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
-			dcache_size = 0;
-			dsup_banks = 0;
-			break;
-		default:
+	switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
+	case ACACHE_BSRAM:
+		seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
+		dcache_size = 16;
+		dsup_banks = 1;
+		break;
+	case ACACHE_BCACHE:
+		seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
+		dcache_size = 32;
+		dsup_banks = 2;
+		break;
+	case ASRAM_BSRAM:
+		seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
+		dcache_size = 0;
+		dsup_banks = 0;
+		break;
+	default:
 		break;
 	}
 
@@ -895,8 +653,8 @@
 	.show = show_cpuinfo,
 };
 
-void cmdline_init(unsigned long r0)
+void __init cmdline_init(const char *r0)
 {
 	if (r0)
-		strncpy(command_line, (char *)r0, COMMAND_LINE_SIZE);
+		strncpy(command_line, r0, COMMAND_LINE_SIZE);
 }
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
index 316e65c..5564c95 100644
--- a/arch/blackfin/kernel/signal.c
+++ b/arch/blackfin/kernel/signal.c
@@ -34,8 +34,8 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/freezer.h>
+#include <linux/uaccess.h>
 
-#include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
 
@@ -124,7 +124,7 @@
 
 	return r0;
 
-      badframe:
+ badframe:
 	force_sig(SIGSEGV, current);
 	return 0;
 }
@@ -239,7 +239,7 @@
 
 	return 0;
 
-      give_sigsegv:
+ give_sigsegv:
 	if (sig == SIGSEGV)
 		ka->sa.sa_handler = SIG_DFL;
 	force_sig(SIGSEGV, current);
@@ -263,7 +263,7 @@
 		}
 		/* fallthrough */
 	case -ERESTARTNOINTR:
-	      do_restart:
+ do_restart:
 		regs->p0 = regs->orig_p0;
 		regs->r0 = regs->orig_r0;
 		regs->pc -= 2;
@@ -341,7 +341,7 @@
 		return;
 	}
 
-no_signal:
+ no_signal:
 	/* Did we come from a system call? */
 	if (regs->orig_p0 >= 0)
 		/* Restart the system call - no handlers present */
diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c
index f436e67..f5e1ae3 100644
--- a/arch/blackfin/kernel/sys_bfin.c
+++ b/arch/blackfin/kernel/sys_bfin.c
@@ -37,12 +37,12 @@
 #include <linux/syscalls.h>
 #include <linux/mman.h>
 #include <linux/file.h>
+#include <linux/uaccess.h>
+#include <linux/ipc.h>
+#include <linux/unistd.h>
 
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
-#include <asm/ipc.h>
 #include <asm/dma.h>
-#include <asm/unistd.h>
 
 /*
  * sys_pipe() is the normal C calling standard for creating
@@ -83,7 +83,7 @@
 
 	if (file)
 		fput(file);
-      out:
+ out:
 	return error;
 }
 
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index f578176..beef057 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -87,7 +87,7 @@
 static inline void do_leds(void)
 {
 	static unsigned int count = 50;
-	static int flag = 0;
+	static int flag;
 	unsigned short tmp = 0;
 
 	if (--count == 0) {
@@ -200,7 +200,7 @@
 irqreturn_t timer_interrupt(int irq, void *dummy)
 {
 	/* last time the cmos clock got updated */
-	static long last_rtc_update = 0;
+	static long last_rtc_update;
 
 	write_seqlock(&xtime_lock);
 
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 9556b73..3909f5b 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -27,15 +27,15 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/cacheflush.h>
-#include <asm/blackfin.h>
-#include <asm/uaccess.h>
-#include <asm/irq_handler.h>
+#include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <asm/traps.h>
+#include <asm/cacheflush.h>
+#include <asm/blackfin.h>
+#include <asm/irq_handler.h>
+#include <asm/trace.h>
 
 #ifdef CONFIG_KGDB
 # include <linux/debugger.h>
@@ -59,9 +59,10 @@
 	struct vm_list_struct *vml;
 	struct task_struct *p;
 	struct mm_struct *mm;
+	unsigned long offset;
 
 #ifdef CONFIG_KALLSYMS
-	unsigned long offset = 0, symsize;
+	unsigned long symsize;
 	const char *symname;
 	char *modname;
 	char *delim = ":";
@@ -75,7 +76,7 @@
 		if (!modname)
 			modname = delim = "";
 		return printk("<0x%p> { %s%s%s%s + 0x%lx }",
-		              (void*)address, delim, modname, delim, symname,
+		              (void *)address, delim, modname, delim, symname,
 		              (unsigned long)offset);
 
 	}
@@ -106,12 +107,19 @@
 					              sizeof(_tmpbuf));
 				}
 
+				/* FLAT does not have its text aligned to the start of
+				 * the map while FDPIC ELF does ...
+				 */
+				if (current->mm &&
+				    (address > current->mm->start_code) &&
+				    (address < current->mm->end_code))
+					offset = address - current->mm->start_code;
+				else
+					offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+
 				write_unlock_irq(&tasklist_lock);
 				return printk("<0x%p> [ %s + 0x%lx ]",
-				              (void*)address, name,
-				              (unsigned long)
-				                ((address - vma->vm_start) +
-				                 (vma->vm_pgoff << PAGE_SHIFT)));
+				              (void *)address, name, offset);
 			}
 
 			vml = vml->next;
@@ -120,19 +128,9 @@
 	write_unlock_irq(&tasklist_lock);
 
 	/* we were unable to find this address anywhere */
-	return printk("[<0x%p>]", (void*)address);
+	return printk("[<0x%p>]", (void *)address);
 }
 
-#define trace_buffer_save(x) \
-	do { \
-		(x) = bfin_read_TBUFCTL(); \
-		bfin_write_TBUFCTL((x) & ~TBUFEN); \
-	} while (0)
-#define trace_buffer_restore(x) \
-	do { \
-		bfin_write_TBUFCTL((x));	\
-	} while (0)
-
 asmlinkage void trap_c(struct pt_regs *fp)
 {
 	int j, sig = 0;
@@ -140,8 +138,15 @@
 	unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
 
 #ifdef CONFIG_KGDB
-# define CHK_DEBUGGER_TRAP() do { CHK_DEBUGGER(trapnr, sig, info.si_code, fp,); } while (0)
-# define CHK_DEBUGGER_TRAP_MAYBE() do { if (kgdb_connected) CHK_DEBUGGER_TRAP(); } while (0)
+# define CHK_DEBUGGER_TRAP() \
+	do { \
+		CHK_DEBUGGER(trapnr, sig, info.si_code, fp); \
+	} while (0)
+# define CHK_DEBUGGER_TRAP_MAYBE() \
+	do { \
+		if (kgdb_connected) \
+			CHK_DEBUGGER_TRAP(); \
+	} while (0)
 #else
 # define CHK_DEBUGGER_TRAP() do { } while (0)
 # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
@@ -188,15 +193,14 @@
 #else
 	/* 0x02 - User Defined, Caught by default */
 #endif
-	/* 0x03  - Atomic test and set */
+	/* 0x03 - User Defined, userspace stack overflow */
 	case VEC_EXCPT03:
 		info.si_code = SEGV_STACKFLOW;
 		sig = SIGSEGV;
 		printk(KERN_EMERG EXC_0x03);
 		CHK_DEBUGGER_TRAP();
 		break;
-	/* 0x04 - spinlock - handled by _ex_spinlock,
-		getting here is an error */
+	/* 0x04 - User Defined, Caught by default */
 	/* 0x05 - User Defined, Caught by default */
 	/* 0x06 - User Defined, Caught by default */
 	/* 0x07 - User Defined, Caught by default */
@@ -289,7 +293,8 @@
 		info.si_code = ILL_CPLB_MULHIT;
 #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
 		sig = SIGSEGV;
-		printk(KERN_EMERG "\n\nNULL pointer access (probably)\n");
+		printk(KERN_EMERG "\n"
+			KERN_EMERG "NULL pointer access (probably)\n");
 #else
 		sig = SIGILL;
 		printk(KERN_EMERG EXC_0x27);
@@ -410,7 +415,9 @@
 		if (current->mm) {
 			fp->pc = current->mm->start_code;
 		} else {
-			printk(KERN_EMERG "I can't return to memory that doesn't exist - bad things happen\n");
+			printk(KERN_EMERG
+				"I can't return to memory that doesn't exist"
+				" - bad things happen\n");
 			panic("Help - I've fallen and can't get up\n");
 		}
 	}
@@ -514,92 +521,113 @@
 void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
 {
 	if (current->pid) {
-		printk("\nCURRENT PROCESS:\n\n");
-		printk("COMM=%s PID=%d\n", current->comm, current->pid);
+		printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n"
+			KERN_EMERG "\n");
+		printk(KERN_EMERG "COMM=%s PID=%d\n",
+			current->comm, current->pid);
 	} else {
 		printk
-		    ("\nNo Valid pid - Either things are really messed up, or you are in the kernel\n");
+		    (KERN_EMERG "\n" KERN_EMERG
+		     "No Valid pid - Either things are really messed up,"
+		     " or you are in the kernel\n");
 	}
 
 	if (current->mm) {
-		printk("TEXT = 0x%p-0x%p  DATA = 0x%p-0x%p\n"
-		       "BSS = 0x%p-0x%p   USER-STACK = 0x%p\n\n",
-		       (void*)current->mm->start_code,
-		       (void*)current->mm->end_code,
-		       (void*)current->mm->start_data,
-		       (void*)current->mm->end_data,
-		       (void*)current->mm->end_data,
-		       (void*)current->mm->brk,
-		       (void*)current->mm->start_stack);
+		printk(KERN_EMERG "TEXT = 0x%p-0x%p  DATA = 0x%p-0x%p\n"
+		       KERN_EMERG "BSS = 0x%p-0x%p   USER-STACK = 0x%p\n"
+		       KERN_EMERG "\n",
+		       (void *)current->mm->start_code,
+		       (void *)current->mm->end_code,
+		       (void *)current->mm->start_data,
+		       (void *)current->mm->end_data,
+		       (void *)current->mm->end_data,
+		       (void *)current->mm->brk,
+		       (void *)current->mm->start_stack);
 	}
 
-	printk("return address: 0x%p; contents of [PC-16...PC+8]:\n", retaddr);
-	if (retaddr != 0 && retaddr <= (void*)physical_mem_end
+	printk(KERN_EMERG "return address: [0x%p]; contents of:", retaddr);
+	if (retaddr != 0 && retaddr <= (void *)physical_mem_end
 #if L1_CODE_LENGTH != 0
 	    /* FIXME: Copy the code out of L1 Instruction SRAM through dma
 	       memcpy.  */
-	    && !(retaddr >= (void*)L1_CODE_START
-	         && retaddr < (void*)(L1_CODE_START + L1_CODE_LENGTH))
+	    && !(retaddr >= (void *)L1_CODE_START
+	         && retaddr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
 #endif
 	) {
-		int i = 0;
+		int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32;
 		unsigned short x = 0;
-		for (i = -16; i < 8; i++) {
-			if (get_user(x, (unsigned short *)retaddr + i))
+		for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) {
+			if (!(i & 0xF))
+				printk(KERN_EMERG "\n" KERN_EMERG
+					"0x%08x: ", i);
+
+			if (get_user(x, (unsigned short *)i))
 				break;
 #ifndef CONFIG_DEBUG_HWERR
 			/* If one of the last few instructions was a STI
-			 * it is likily that the error occured awhile ago
+			 * it is likely that the error occured awhile ago
 			 * and we just noticed
 			 */
 			if (x >= 0x0040 && x <= 0x0047 && i <= 0)
-				panic("\n\nWARNING : You should reconfigure the kernel to turn on\n"
-					" 'Hardware error interrupt debugging'\n"
-					" The rest of this error is meanless\n");
+				panic("\n\nWARNING : You should reconfigure"
+					" the kernel to turn on\n"
+					" 'Hardware error interrupt"
+					" debugging'\n"
+					" The rest of this error"
+					" is meanless\n");
 #endif
-
-			if (i == -8)
-				printk("\n");
-			if (i == 0)
-				printk("X\n");
-			printk("%04x ", x);
+			if (i == (unsigned int)retaddr)
+				printk("[%04x]", x);
+			else
+				printk(" %04x ", x);
 		}
+		printk("\n" KERN_EMERG "\n");
 	} else
-		printk("Cannot look at the [PC] for it is in unreadable L1 SRAM - sorry\n");
+		printk(KERN_EMERG
+			"Cannot look at the [PC] for it is"
+			"in unreadable L1 SRAM - sorry\n");
 
-	printk("\n\n");
 
-	printk("RETE:  %08lx  RETN: %08lx  RETX: %08lx  RETS: %08lx\n",
-	       fp->rete, fp->retn, fp->retx, fp->rets);
-	printk("IPEND: %04lx  SYSCFG: %04lx\n", fp->ipend, fp->syscfg);
-	printk("SEQSTAT: %08lx    SP: %08lx\n", (long)fp->seqstat, (long)fp);
-	printk("R0: %08lx    R1: %08lx    R2: %08lx    R3: %08lx\n",
-	       fp->r0, fp->r1, fp->r2, fp->r3);
-	printk("R4: %08lx    R5: %08lx    R6: %08lx    R7: %08lx\n",
-	       fp->r4, fp->r5, fp->r6, fp->r7);
-	printk("P0: %08lx    P1: %08lx    P2: %08lx    P3: %08lx\n",
-	       fp->p0, fp->p1, fp->p2, fp->p3);
-	printk("P4: %08lx    P5: %08lx    FP: %08lx\n", fp->p4, fp->p5, fp->fp);
-	printk("A0.w: %08lx    A0.x: %08lx    A1.w: %08lx    A1.x: %08lx\n",
-	       fp->a0w, fp->a0x, fp->a1w, fp->a1x);
+	printk(KERN_EMERG
+		"RETE:  %08lx  RETN: %08lx  RETX: %08lx  RETS: %08lx\n",
+		fp->rete, fp->retn, fp->retx, fp->rets);
+	printk(KERN_EMERG "IPEND: %04lx  SYSCFG: %04lx\n",
+		fp->ipend, fp->syscfg);
+	printk(KERN_EMERG "SEQSTAT: %08lx    SP: %08lx\n",
+		(long)fp->seqstat, (long)fp);
+	printk(KERN_EMERG "R0: %08lx    R1: %08lx    R2: %08lx    R3: %08lx\n",
+		fp->r0, fp->r1, fp->r2, fp->r3);
+	printk(KERN_EMERG "R4: %08lx    R5: %08lx    R6: %08lx    R7: %08lx\n",
+		fp->r4, fp->r5, fp->r6, fp->r7);
+	printk(KERN_EMERG "P0: %08lx    P1: %08lx    P2: %08lx    P3: %08lx\n",
+		fp->p0, fp->p1, fp->p2, fp->p3);
+	printk(KERN_EMERG
+		"P4: %08lx    P5: %08lx    FP: %08lx\n",
+		fp->p4, fp->p5, fp->fp);
+	printk(KERN_EMERG
+		"A0.w: %08lx    A0.x: %08lx    A1.w: %08lx    A1.x: %08lx\n",
+		fp->a0w, fp->a0x, fp->a1w, fp->a1x);
 
-	printk("LB0: %08lx  LT0: %08lx  LC0: %08lx\n", fp->lb0, fp->lt0,
-	       fp->lc0);
-	printk("LB1: %08lx  LT1: %08lx  LC1: %08lx\n", fp->lb1, fp->lt1,
-	       fp->lc1);
-	printk("B0: %08lx  L0: %08lx  M0: %08lx  I0: %08lx\n", fp->b0, fp->l0,
-	       fp->m0, fp->i0);
-	printk("B1: %08lx  L1: %08lx  M1: %08lx  I1: %08lx\n", fp->b1, fp->l1,
-	       fp->m1, fp->i1);
-	printk("B2: %08lx  L2: %08lx  M2: %08lx  I2: %08lx\n", fp->b2, fp->l2,
-	       fp->m2, fp->i2);
-	printk("B3: %08lx  L3: %08lx  M3: %08lx  I3: %08lx\n", fp->b3, fp->l3,
-	       fp->m3, fp->i3);
+	printk(KERN_EMERG "LB0: %08lx  LT0: %08lx  LC0: %08lx\n",
+		fp->lb0, fp->lt0, fp->lc0);
+	printk(KERN_EMERG "LB1: %08lx  LT1: %08lx  LC1: %08lx\n",
+		fp->lb1, fp->lt1, fp->lc1);
+	printk(KERN_EMERG "B0: %08lx  L0: %08lx  M0: %08lx  I0: %08lx\n",
+		fp->b0, fp->l0, fp->m0, fp->i0);
+	printk(KERN_EMERG "B1: %08lx  L1: %08lx  M1: %08lx  I1: %08lx\n",
+		fp->b1, fp->l1, fp->m1, fp->i1);
+	printk(KERN_EMERG "B2: %08lx  L2: %08lx  M2: %08lx  I2: %08lx\n",
+		fp->b2, fp->l2, fp->m2, fp->i2);
+	printk(KERN_EMERG "B3: %08lx  L3: %08lx  M3: %08lx  I3: %08lx\n",
+		fp->b3, fp->l3, fp->m3, fp->i3);
 
-	printk("\nUSP: %08lx   ASTAT: %08lx\n", rdusp(), fp->astat);
+	printk(KERN_EMERG "\n" KERN_EMERG "USP: %08lx   ASTAT: %08lx\n",
+		rdusp(), fp->astat);
 	if ((long)fp->seqstat & SEQSTAT_EXCAUSE) {
-		printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
-		printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
+		printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n",
+			(void *)bfin_read_DCPLB_FAULT_ADDR());
+		printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n",
+			(void *)bfin_read_ICPLB_FAULT_ADDR());
 	}
 
 	printk("\n\n");
@@ -641,8 +669,8 @@
 		break;
 	}
 
-	printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
-	printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
+	printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
+	printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
 	dump_bfin_regs(fp, (void *)fp->retx);
 	dump_stack();
 	panic("Unrecoverable event\n");
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 6ae9ebb..d06f860 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -7,7 +7,7 @@
  * Description:  Master linker script for blackfin architecture
  *
  * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
+ *               Copyright 2004-2007 Analog Devices Inc.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -31,98 +31,56 @@
 
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/mem_map.h>
-
+#include <asm/page.h>
 
 OUTPUT_FORMAT("elf32-bfin")
 ENTRY(__start)
 _jiffies = _jiffies_64;
 
-MEMORY
-{
-	ram         : ORIGIN = CONFIG_BOOT_LOAD, LENGTH = (CONFIG_MEM_SIZE * 1024 * 1024) - (CONFIG_BOOT_LOAD)
-	l1_data_a   : ORIGIN = L1_DATA_A_START,  LENGTH = L1_DATA_A_LENGTH
-	l1_data_b   : ORIGIN = L1_DATA_B_START,  LENGTH = L1_DATA_B_LENGTH
-	l1_code     : ORIGIN = L1_CODE_START,    LENGTH = L1_CODE_LENGTH
-	l1_scratch  : ORIGIN = L1_SCRATCH_START, LENGTH = L1_SCRATCH_LENGTH
-}
-
 SECTIONS
 {
 	. = CONFIG_BOOT_LOAD;
-
 	.text :
 	{
-		 _text = .;
-		 __stext = .;
-		*(.text)
+		__text = .;
+		_text = .;
+		__stext = .;
+		TEXT_TEXT
 		SCHED_TEXT
+		LOCK_TEXT
 		*(.text.lock)
-		. = ALIGN(16);
-		  ___start___ex_table = .;
-		*(__ex_table)
-		 ___stop___ex_table = .;
-
-		*($code)
-		*(.rodata)
-		*(.rodata.*)
-		*(__vermagic)		/* Kernel version magic */
-		*(.rodata1)
 		*(.fixup)
-		*(.spinlock.text)
 
-		/* Kernel symbol table: Normal symbols */
+		. = ALIGN(16);
+		___start___ex_table = .;
+		*(__ex_table)
+		___stop___ex_table = .;
+
 		. = ALIGN(4);
-		___start___ksymtab = .;
-		*(__ksymtab)
-		___stop___ksymtab = .;
-
-		/* Kernel symbol table: GPL-only symbols */
-		___start___ksymtab_gpl = .;
-		*(__ksymtab_gpl)
-		___stop___ksymtab_gpl = .;
-
-		/* Kernel symbol table: Normal unused symbols */		\
-		___start___ksymtab_unused = .;
-		*(__ksymtab_unused)
-		___stop___ksymtab_unused = .;
-
-		/* Kernel symbol table: GPL-only unused symbols */
-		___start___ksymtab_unused_gpl = .;
-		*(__ksymtab_unused_gpl)
-		___stop___ksymtab_unused_gpl = .;
-
-
-		/* Kernel symbol table: GPL-future symbols */
-		___start___ksymtab_gpl_future = .;
-		*(__ksymtab_gpl_future)
-		___stop___ksymtab_gpl_future = .;
-
-		/* Kernel symbol table: Normal symbols */
-		___start___kcrctab = .;
-		*(__kcrctab)
-		___stop___kcrctab = .;
-
-		/* Kernel symbol table: GPL-only symbols */
-		___start___kcrctab_gpl = .;
-		*(__kcrctab_gpl)
-		___stop___kcrctab_gpl = .;
-
-		/* Kernel symbol table: GPL-future symbols */
-		___start___kcrctab_gpl_future = .;
-		*(__kcrctab_gpl_future)
-		___stop___kcrctab_gpl_future = .;
-
-		/* Kernel symbol table: strings */
-		*(__ksymtab_strings)
-
-		 . = ALIGN(4);
 		__etext = .;
-	} > ram
+	}
 
+	RODATA
+
+	.data :
+	{
+		. = ALIGN(PAGE_SIZE);
+		__sdata = .;
+		*(.data.init_task)
+		DATA_DATA
+		CONSTRUCTORS
+
+		. = ALIGN(32);
+		*(.data.cacheline_aligned)
+
+		. = ALIGN(PAGE_SIZE);
+		__edata = .;
+	}
+
+	. = ALIGN(PAGE_SIZE);
+	___init_begin = .;
 	.init :
 	{
-		. = ALIGN(4096);
-		___init_begin = .;
 		__sinittext = .;
 		*(.init.text)
 		__einittext = .;
@@ -148,39 +106,39 @@
 		*(.init.ramfs)
 		___initramfs_end = .;
 		. = ALIGN(4);
-		___init_end = .;
-	} > ram
+	}
 
-	 __l1_lma_start = .;
+	__l1_lma_start = .;
 
-	.text_l1 :
+	.text_l1 L1_CODE_START : AT(LOADADDR(.init) + SIZEOF(.init))
 	{
 		. = ALIGN(4);
-		 __stext_l1 = .;
+		__stext_l1 = .;
 		*(.l1.text)
 
 		. = ALIGN(4);
-		 __etext_l1 = .;
-	} > l1_code AT > ram
+		__etext_l1 = .;
+	}
 
-	.data_l1 :
+	.data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1))
 	{
 		. = ALIGN(4);
-		 __sdata_l1 = .;
+		__sdata_l1 = .;
 		*(.l1.data)
-		 __edata_l1 = .;
+		__edata_l1 = .;
 
 		. = ALIGN(4);
-		 __sbss_l1 = .;
+		__sbss_l1 = .;
 		*(.l1.bss)
 
 		. = ALIGN(32);
 		*(.data_l1.cacheline_aligned)
 
 		. = ALIGN(4);
-		 __ebss_l1 = .;
-	} > l1_data_a AT > ram
-	.data_b_l1 :
+		__ebss_l1 = .;
+	}
+
+	.data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
 	{
 		. = ALIGN(4);
 		__sdata_b_l1 = .;
@@ -193,36 +151,26 @@
 
 		. = ALIGN(4);
 		__ebss_b_l1 = .;
-	} > l1_data_b AT > ram
+	}
 
-	.data :
-	{
-		 __sdata = .;
-		. = ALIGN(0x2000);
-		*(.data.init_task)
-		*(.data)
+	. = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
+	___init_end = ALIGN(PAGE_SIZE);
 
-		. = ALIGN(32);
-		*(.data.cacheline_aligned)
-
-		. = ALIGN(0x2000);
-		__edata = .;
-	} > ram
-
-	/DISCARD/ : {			/* Exit code and data*/
-		*(.exit.text)
-		*(.exit.data)
-		*(.exitcall.exit)
-	} > ram
-
-	.bss :
+	.bss ___init_end :
 	{
 		. = ALIGN(4);
-		 ___bss_start = .;
+		___bss_start = .;
 		*(.bss)
 		*(COMMON)
 		. = ALIGN(4);
-		 ___bss_stop = .;
-		 __end = .	;
-	} > ram
+		___bss_stop = .;
+		__end = .;
+	}
+
+	/DISCARD/ :
+	{
+		*(.exit.text)
+		*(.exit.data)
+		*(.exitcall.exit)
+	}
 }
diff --git a/arch/blackfin/lib/divsi3.S b/arch/blackfin/lib/divsi3.S
index 3e29861..2ac59c7 100644
--- a/arch/blackfin/lib/divsi3.S
+++ b/arch/blackfin/lib/divsi3.S
@@ -44,6 +44,7 @@
  */
 
 .global   ___divsi3;
+.type ___divsi3, STT_FUNC;
 
 #ifdef CONFIG_ARITHMETIC_OPS_L1
 .section .l1.text
@@ -214,3 +215,5 @@
 .Lret_zero:
   R0 = 0;
   RTS;
+
+.size ___divsi3, .-___divsi3
diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S
index 730d2b4..a17cc77 100644
--- a/arch/blackfin/lib/ins.S
+++ b/arch/blackfin/lib/ins.S
@@ -29,6 +29,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/blackfin.h>
 
 .align 2
 
@@ -39,10 +40,13 @@
 	P2 = R2;	/* P2 = count */
 	SSYNC;
 	LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
-.Llong_loop_s: R0 = [P0];
-.Llong_loop_e: [P1++] = R0;
+.Llong_loop_s:  R0 = [P0];
+		[P1++] = R0;
+		NOP;
+.Llong_loop_e: 	NOP;
 	sti R3;
 	RTS;
+ENDPROC(_insl)
 
 ENTRY(_insw)
 	P0 = R0;	/* P0 = port */
@@ -51,10 +55,13 @@
 	P2 = R2;	/* P2 = count */
 	SSYNC;
 	LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
-.Lword_loop_s: R0 = W[P0];
-.Lword_loop_e: W[P1++] = R0;
+.Lword_loop_s:  R0 = W[P0];
+		W[P1++] = R0;
+		NOP;
+.Lword_loop_e: 	NOP;
 	sti R3;
 	RTS;
+ENDPROC(_insw)
 
 ENTRY(_insb)
 	P0 = R0;	/* P0 = port */
@@ -63,7 +70,10 @@
 	P2 = R2;	/* P2 = count */
 	SSYNC;
 	LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
-.Lbyte_loop_s: R0 = B[P0];
-.Lbyte_loop_e: B[P1++] = R0;
+.Lbyte_loop_s:  R0 = B[P0];
+		B[P1++] = R0;
+		NOP;
+.Lbyte_loop_e:  NOP;
 	sti R3;
 	RTS;
+ENDPROC(_insb)
diff --git a/arch/blackfin/lib/memchr.S b/arch/blackfin/lib/memchr.S
index 4981222..5da4281 100644
--- a/arch/blackfin/lib/memchr.S
+++ b/arch/blackfin/lib/memchr.S
@@ -67,4 +67,4 @@
 	R0 += -1;
 	RTS;
 
-.size _memchr,.-_memchr
+ENDPROC(_memchr)
diff --git a/arch/blackfin/lib/memcmp.S b/arch/blackfin/lib/memcmp.S
index 5b95023..b88c5d2 100644
--- a/arch/blackfin/lib/memcmp.S
+++ b/arch/blackfin/lib/memcmp.S
@@ -61,7 +61,12 @@
 
 	LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1;
 .Lquad_loop_s:
+#ifdef ANOMALY_05000202
+	R0 = [P0++];
+	R1 = [I0++];
+#else
 	MNOP || R0 = [P0++] || R1 = [I0++];
+#endif
 	CC = R0 == R1;
 	IF !CC JUMP .Lquad_different;
 .Lquad_loop_e:
@@ -107,4 +112,4 @@
 	P3 = I1;
 	RTS;
 
-.size _memcmp,.-_memcmp
+ENDPROC(_memcmp)
diff --git a/arch/blackfin/lib/memcpy.S b/arch/blackfin/lib/memcpy.S
index c1e00ef..14a5585 100644
--- a/arch/blackfin/lib/memcpy.S
+++ b/arch/blackfin/lib/memcpy.S
@@ -94,13 +94,20 @@
 .Lmore_than_seven:
 	/* There's at least eight bytes to copy. */
 	P2 += -1;	/* because we unroll one iteration */
-	LSETUP(.Lword_loop, .Lword_loop) LC0=P2;
+	LSETUP(.Lword_loops, .Lword_loope) LC0=P2;
 	R0 = R1;
 	I1 = P1;
 	R3 = [I1++];
-.Lword_loop:
+#ifdef ANOMALY_05000202
+.Lword_loops:
+	[P0++] = R3;
+.Lword_loope:
+	R3 = [I1++];
+#else
+.Lword_loops:
+.Lword_loope:
 	MNOP || [P0++] = R3 || R3 = [I1++];
-
+#endif
 	[P0++] = R3;
 	/* Any remaining bytes to copy? */
 	R3 = 0x3;
@@ -140,3 +147,5 @@
 	B[P0--] = R1;
 
 	RTS;
+
+ENDPROC(_memcpy)
diff --git a/arch/blackfin/lib/memmove.S b/arch/blackfin/lib/memmove.S
index 2e5fb7f..6ee6e20 100644
--- a/arch/blackfin/lib/memmove.S
+++ b/arch/blackfin/lib/memmove.S
@@ -69,8 +69,17 @@
 	P2 = R2;                  /* set remainder */
 	R1 = [I0++];
 
-	LSETUP (.Lquad_loop, .Lquad_loop) LC0=P1;
-.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++];
+	LSETUP (.Lquad_loops, .Lquad_loope) LC0=P1;
+#ifdef ANOMALY_05000202
+.Lquad_loops:
+	[P0++] = R1;
+.Lquad_loope:
+	R1 = [I0++];
+#else
+.Lquad_loops:
+.Lquad_loope:
+	 MNOP || [P0++] = R1 || R1 = [I0++];
+#endif
 	[P0++] = R1;
 
 	CC = P2 == 0;             /* any remaining bytes? */
@@ -93,6 +102,10 @@
 	R1 = B[P3--] (Z);
 	CC = P2 == 0;
 	IF CC JUMP .Lno_loop;
+#ifdef ANOMALY_05000245
+	NOP;
+	NOP;
+#endif
 	LSETUP (.Lol_s, .Lol_e) LC0 = P2;
 .Lol_s:    B[P0--] = R1;
 .Lol_e:    R1 = B[P3--] (Z);
@@ -100,4 +113,4 @@
 	P3 = I1;
 	RTS;
 
-.size _memmove,.-_memmove
+ENDPROC(_memmove)
diff --git a/arch/blackfin/lib/memset.S b/arch/blackfin/lib/memset.S
index ba6d047..8159136 100644
--- a/arch/blackfin/lib/memset.S
+++ b/arch/blackfin/lib/memset.S
@@ -106,4 +106,4 @@
 	B[P0++] = R1;
 	JUMP .Laligned;
 
-.size _memset,.-_memset
+ENDPROC(_memset)
diff --git a/arch/blackfin/lib/modsi3.S b/arch/blackfin/lib/modsi3.S
index 528b8b1..ca1dd39 100644
--- a/arch/blackfin/lib/modsi3.S
+++ b/arch/blackfin/lib/modsi3.S
@@ -77,3 +77,5 @@
 	R0 = 0;
 .LRETURN_R0:
 	RTS;
+
+.size ___modsi3, .-___modsi3
diff --git a/arch/blackfin/lib/outs.S b/arch/blackfin/lib/outs.S
index f8c876f..4c3da8a 100644
--- a/arch/blackfin/lib/outs.S
+++ b/arch/blackfin/lib/outs.S
@@ -40,6 +40,7 @@
 .Llong_loop_s: R0 = [P1++];
 .Llong_loop_e: [P0] = R0;
 	RTS;
+ENDPROC(_outsl)
 
 ENTRY(_outsw)
 	P0 = R0;	/* P0 = port */
@@ -50,6 +51,7 @@
 .Lword_loop_s: R0 = W[P1++];
 .Lword_loop_e: W[P0] = R0;
 	RTS;
+ENDPROC(_outsw)
 
 ENTRY(_outsb)
 	P0 = R0;	/* P0 = port */
@@ -60,3 +62,4 @@
 .Lbyte_loop_s: R0 = B[P1++];
 .Lbyte_loop_e: B[P0] = R0;
 	RTS;
+ENDPROC(_outsb)
diff --git a/arch/blackfin/lib/smulsi3_highpart.S b/arch/blackfin/lib/smulsi3_highpart.S
index 10b8f8d..e383cd3 100644
--- a/arch/blackfin/lib/smulsi3_highpart.S
+++ b/arch/blackfin/lib/smulsi3_highpart.S
@@ -28,3 +28,5 @@
 
 	R0 = R0 + R1;
 	RTS;
+
+.size ___smulsi3_highpart, .-___smulsi3_highpart
diff --git a/arch/blackfin/lib/strcmp.c b/arch/blackfin/lib/strcmp.c
index 2ad47c4..4eeefd8 100644
--- a/arch/blackfin/lib/strcmp.c
+++ b/arch/blackfin/lib/strcmp.c
@@ -6,6 +6,5 @@
 
 int strcmp(const char *dest, const char *src)
 {
-	        return __inline_strcmp(dest, src);
+	return __inline_strcmp(dest, src);
 }
-
diff --git a/arch/blackfin/lib/strcpy.c b/arch/blackfin/lib/strcpy.c
index 4dc835a..534589d 100644
--- a/arch/blackfin/lib/strcpy.c
+++ b/arch/blackfin/lib/strcpy.c
@@ -6,6 +6,5 @@
 
 char *strcpy(char *dest, const char *src)
 {
-	        return __inline_strcpy(dest, src);
+	return __inline_strcpy(dest, src);
 }
-
diff --git a/arch/blackfin/lib/strncmp.c b/arch/blackfin/lib/strncmp.c
index 947bcfe..d791f12 100644
--- a/arch/blackfin/lib/strncmp.c
+++ b/arch/blackfin/lib/strncmp.c
@@ -6,6 +6,5 @@
 
 int strncmp(const char *cs, const char *ct, size_t count)
 {
-	        return __inline_strncmp(cs, ct, count);
+	return __inline_strncmp(cs, ct, count);
 }
-
diff --git a/arch/blackfin/lib/strncpy.c b/arch/blackfin/lib/strncpy.c
index 77a9b2e..1fecb5c 100644
--- a/arch/blackfin/lib/strncpy.c
+++ b/arch/blackfin/lib/strncpy.c
@@ -6,6 +6,5 @@
 
 char *strncpy(char *dest, const char *src, size_t n)
 {
-	        return __inline_strncpy(dest, src, n);
+	return __inline_strncpy(dest, src, n);
 }
-
diff --git a/arch/blackfin/lib/udivsi3.S b/arch/blackfin/lib/udivsi3.S
index d39a129..58fd96d 100644
--- a/arch/blackfin/lib/udivsi3.S
+++ b/arch/blackfin/lib/udivsi3.S
@@ -296,3 +296,5 @@
   R1 = R0 - R3;
   IF CC R0 = R1;
   RTS;
+
+ENDPROC(___udivsi3)
diff --git a/arch/blackfin/lib/umodsi3.S b/arch/blackfin/lib/umodsi3.S
index b55ce96..4f2b76e 100644
--- a/arch/blackfin/lib/umodsi3.S
+++ b/arch/blackfin/lib/umodsi3.S
@@ -34,7 +34,9 @@
 #endif
 
 .extern ___udivsi3;
+.type ___udivsi3, STT_FUNC;
 .globl	___umodsi3
+.type ___umodsi3, STT_FUNC;
 ___umodsi3:
 
 	CC=R0==0;
@@ -64,3 +66,5 @@
 	R0 = 0;
 .LRETURN_R0:
 	RTS;
+
+.size ___umodsi3, .-___umodsi3
diff --git a/arch/blackfin/lib/umulsi3_highpart.S b/arch/blackfin/lib/umulsi3_highpart.S
index aac8218..67b7993 100644
--- a/arch/blackfin/lib/umulsi3_highpart.S
+++ b/arch/blackfin/lib/umulsi3_highpart.S
@@ -21,3 +21,5 @@
 	R1 = PACK(R1.l,R0.h);
 	R0 = R1 + R2;
 	RTS;
+
+.size ___umulsi3_highpart, .-___umulsi3_highpart
diff --git a/arch/blackfin/mach-bf533/Makefile b/arch/blackfin/mach-bf533/Makefile
index 76d2c2b..8cce173 100644
--- a/arch/blackfin/mach-bf533/Makefile
+++ b/arch/blackfin/mach-bf533/Makefile
@@ -4,6 +4,6 @@
 
 extra-y := head.o
 
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
 
-obj-$(CONFIG_CPU_FREQ_BF533) += cpu.o
+obj-$(CONFIG_CPU_FREQ)   += cpu.o
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index 23a7f60..4545f36 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -1,7 +1,7 @@
 /*
  * File:         arch/blackfin/mach-bf533/boards/cm_bf533.c
  * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au> Copright 2005
+ * Author:       Aidan Williams <aidan@nicta.com.au> Copyright 2005
  *
  * Created:      2005
  * Description:  Board description file
@@ -34,7 +34,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -51,11 +51,11 @@
 		.size = 0x00020000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
-	},{
+	}, {
 		.name = "kernel",
 		.size = 0xe0000,
 		.offset = 0x20000
-	},{
+	}, {
 		.name = "file system",
 		.size = 0x700000,
 		.offset = 0x00100000,
@@ -98,7 +98,7 @@
 		.platform_data = &bfin_spi_flash_data,
 		.controller_data = &spi_flash_chip_info,
 		.mode = SPI_MODE_3,
-	},{
+	}, {
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 1,               /* Framework bus number */
@@ -145,7 +145,7 @@
 		.start = 0x20200300,
 		.end = 0x20200300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF0,
 		.end = IRQ_PF0,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -194,11 +194,11 @@
 		.start = 0x20308000,
 		.end = 0x20308000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x20308004,
 		.end = 0x20308004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF4,
 		.end = IRQ_PF4,
 		.flags = IORESOURCE_IRQ,
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index 747298e..0000b8f 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -1,6 +1,6 @@
 /*
  * File:         arch/blackfin/mach-bf533/ezkit.c
- * Based on:     Orginal Work
+ * Based on:     Original Work
  * Author:       Aidan Williams <aidan@nicta.com.au>
  *
  * Created:      2005
@@ -35,7 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -61,7 +61,7 @@
 		.start = 0x20310300,
 		.end = 0x20310300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF9,
 		.end = IRQ_PF9,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -85,11 +85,11 @@
 		.size = 0x00020000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
-	},{
+	}, {
 		.name = "kernel",
 		.size = 0xe0000,
 		.offset = 0x20000
-	},{
+	}, {
 		.name = "file system",
 		.size = 0x700000,
 		.offset = 0x00100000,
diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c
index c0f43cc..9bc1f0d 100644
--- a/arch/blackfin/mach-bf533/boards/generic_board.c
+++ b/arch/blackfin/mach-bf533/boards/generic_board.c
@@ -30,7 +30,7 @@
 
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -53,11 +53,11 @@
 		.start = 0x20300300,
 		.end = 0x20300300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PROG_INTB,
 		.end = IRQ_PROG_INTB,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},{
+	}, {
 		/*
 		 *  denotes the flag pin and is used directly if
 		 *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index d7b3a5d..a9143c4 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -37,7 +37,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb_isp1362.h>
 #endif
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -62,7 +62,7 @@
 		.start = 0x20300300,
 		.end = 0x20300300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -83,7 +83,7 @@
 		.start = 0x20300000,
 		.end = 0x20300000 + 0x100,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF10,
 		.end = IRQ_PF10,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -108,11 +108,11 @@
 		.size = 0x00020000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
-	},{
+	}, {
 		.name = "kernel",
 		.size = 0xe0000,
 		.offset = 0x20000
-	},{
+	}, {
 		.name = "file system",
 		.size = 0x700000,
 		.offset = 0x00100000,
@@ -164,6 +164,13 @@
 };
 #endif
 
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+	.enable_dma = 1,
+	.bits_per_word = 8,
+};
+#endif
+
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
 	{
@@ -199,21 +206,42 @@
 	},
 #endif
 
-#if defined(CONFIG_PBX)
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
 	{
-		.modalias	= "fxs-spi",
-		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num	= 1,
-		.chip_select	= 3,
-		.controller_data= &spi_si3xxx_chip_info,
+		.modalias = "spi_mmc_dummy",
+		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = 0,
+		.platform_data = NULL,
+		.controller_data = &spi_mmc_chip_info,
 		.mode = SPI_MODE_3,
 	},
 	{
-		.modalias	= "fxo-spi",
-		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num	= 1,
-		.chip_select	= 2,
-		.controller_data= &spi_si3xxx_chip_info,
+		.modalias = "spi_mmc",
+		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
+		.platform_data = NULL,
+		.controller_data = &spi_mmc_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+
+#if defined(CONFIG_PBX)
+	{
+		.modalias = "fxs-spi",
+		.max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = 3,
+		.controller_data = &spi_si3xxx_chip_info,
+		.mode = SPI_MODE_3,
+	},
+	{
+		.modalias = "fxo-spi",
+		.max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = 2,
+		.controller_data = &spi_si3xxx_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -310,12 +338,25 @@
 
 static int __init stamp_init(void)
 {
+	int ret;
+
 	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
-	platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
-#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
-	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+	ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+	if (ret < 0)
+		return ret;
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+# if defined(CONFIG_BFIN_SHARED_FLASH_ENET)
+	/* setup BF533_STAMP CPLD to route AMS3 to Ethernet MAC */
+	bfin_write_FIO_DIR(bfin_read_FIO_DIR() | (1 << CONFIG_ENET_FLASH_PIN));
+	bfin_write_FIO_FLAG_S(1 << CONFIG_ENET_FLASH_PIN);
+	SSYNC();
+# endif
 #endif
-	return 0;
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+	return spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
 }
 
 arch_initcall(stamp_init);
diff --git a/arch/blackfin/mach-bf533/cpu.c b/arch/blackfin/mach-bf533/cpu.c
index 99547c4..6fd9cfd 100644
--- a/arch/blackfin/mach-bf533/cpu.c
+++ b/arch/blackfin/mach-bf533/cpu.c
@@ -79,8 +79,7 @@
 	int i;
 
 	struct cpufreq_freqs freqs;
-	if (cpufreq_frequency_table_target
-	    (policy, bf533_freq_table, target_freq, relation, &index))
+	if (cpufreq_frequency_table_target(policy, bf533_freq_table, target_freq, relation, &index))
 		return -EINVAL;
 	cclk_mhz = bf533_freq_table[index].frequency;
 	vco_mhz = bf533_freq_table[index].index;
diff --git a/arch/blackfin/mach-bf533/dma.c b/arch/blackfin/mach-bf533/dma.c
new file mode 100644
index 0000000..6c909cf
--- /dev/null
+++ b/arch/blackfin/mach-bf533/dma.c
@@ -0,0 +1,95 @@
+/*
+ * File:         arch/blackfin/mach-bf533/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+	(struct dma_register *) DMA0_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_NEXT_DESC_PTR,
+	(struct dma_register *) DMA3_NEXT_DESC_PTR,
+	(struct dma_register *) DMA4_NEXT_DESC_PTR,
+	(struct dma_register *) DMA5_NEXT_DESC_PTR,
+	(struct dma_register *) DMA6_NEXT_DESC_PTR,
+	(struct dma_register *) DMA7_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+	int ret_irq = -1;
+
+	switch (channel) {
+	case CH_PPI:
+		ret_irq = IRQ_PPI;
+		break;
+
+	case CH_SPORT0_RX:
+		ret_irq = IRQ_SPORT0_RX;
+		break;
+
+	case CH_SPORT0_TX:
+		ret_irq = IRQ_SPORT0_TX;
+		break;
+
+	case CH_SPORT1_RX:
+		ret_irq = IRQ_SPORT1_RX;
+		break;
+
+	case CH_SPORT1_TX:
+		ret_irq = IRQ_SPORT1_TX;
+		break;
+
+	case CH_SPI:
+		ret_irq = IRQ_SPI;
+		break;
+
+	case CH_UART_RX:
+		ret_irq = IRQ_UART_RX;
+		break;
+
+	case CH_UART_TX:
+		ret_irq = IRQ_UART_TX;
+		break;
+
+	case CH_MEM_STREAM0_SRC:
+	case CH_MEM_STREAM0_DEST:
+		ret_irq = IRQ_MEM_DMA0;
+		break;
+
+	case CH_MEM_STREAM1_SRC:
+	case CH_MEM_STREAM1_DEST:
+		ret_irq = IRQ_MEM_DMA1;
+		break;
+	}
+	return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf533/head.S b/arch/blackfin/mach-bf533/head.S
index 4808edb..7dd0e9c 100644
--- a/arch/blackfin/mach-bf533/head.S
+++ b/arch/blackfin/mach-bf533/head.S
@@ -28,7 +28,9 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/init.h>
 #include <asm/blackfin.h>
+#include <asm/trace.h>
 #if CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach/mem_init.h>
 #endif
@@ -45,19 +47,19 @@
 
 #define INITIAL_STACK	0xFFB01000
 
-.text
+__INIT
 
 ENTRY(__start)
-ENTRY(__stext)
 	/* R0: argument of command line string, passed from uboot, save it */
 	R7 = R0;
-	/* Set the SYSCFG register */
+	/* Set the SYSCFG register:
+	 * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit)
+	 */
 	R0 = 0x36;
-	/*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
 	SYSCFG = R0;
 	R0 = 0;
 
-	/*Clear Out All the data and pointer  Registers*/
+	/* Clear Out All the data and pointer Registers */
 	R1 = R0;
 	R2 = R0;
 	R3 = R0;
@@ -79,7 +81,7 @@
 	L2 = r0;
 	L3 = r0;
 
-	/* Clear Out All the DAG Registers*/
+	/* Clear Out All the DAG Registers */
 	B0 = r0;
 	B1 = r0;
 	B2 = r0;
@@ -95,6 +97,10 @@
 	M2 = r0;
 	M3 = r0;
 
+	trace_buffer_start(p0,r0);
+	P0 = R1;
+	R0 = R1;
+
 #if CONFIG_DEBUG_KERNEL_START
 
 /*
@@ -173,7 +179,8 @@
 	STI R2;
 #endif
 
-	/* Initialise UART */
+	/* Initialise UART - when booting from u-boot, the UART is not disabled
+	 * so if we dont initalize here, our serial console gets hosed */
 	p0.h = hi(UART_LCR);
 	p0.l = lo(UART_LCR);
 	r0 = 0x0(Z);
@@ -264,6 +271,7 @@
 
 .LWAIT_HERE:
 	jump .LWAIT_HERE;
+ENDPROC(__start)
 
 ENTRY(_real_start)
 	[ -- sp ] = reti;
@@ -302,7 +310,7 @@
 .L_clear_zero:
 	W[p1++] = r0;
 
-/* pass the uboot arguments to the global value command line */
+	/* pass the uboot arguments to the global value command line */
 	R0 = R7;
 	call _cmdline_init;
 
@@ -321,7 +329,7 @@
 	[p1] = r1;
 
 	/*
-	 *  load the current thread pointer and stack
+	 * load the current thread pointer and stack
 	 */
 	r1.l = _init_thread_union;
 	r1.h = _init_thread_union;
@@ -332,9 +340,10 @@
 	sp = r1;
 	usp = sp;
 	fp = sp;
-	call _start_kernel;
-.L_exit:
-	jump.s	.L_exit;
+	jump.l _start_kernel;
+ENDPROC(_real_start)
+
+__FINIT
 
 .section .l1.text
 #if CONFIG_BFIN_KERNEL_CLOCK
@@ -438,12 +447,13 @@
 
 	p0.h = hi(SIC_IWR);
 	p0.l = lo(SIC_IWR);
-	r0.l = lo(IWR_ENABLE_ALL)
-	r0.h = hi(IWR_ENABLE_ALL)
+	r0.l = lo(IWR_ENABLE_ALL);
+	r0.h = hi(IWR_ENABLE_ALL);
 	[p0] = r0;
 	SSYNC;
 
 	RTS;
+ENDPROC(_start_dma_code)
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
 
 ENTRY(_bfin_reset)
@@ -468,12 +478,6 @@
 	w[p0] = r0.l;
 #endif
 
-	/* Clear the bits 13-15 in SWRST if they werent cleared */
-	p0.h = hi(SWRST);
-	p0.l = lo(SWRST);
-	csync;
-	r0.l = w[p0];
-
 	/* Clear the IMASK register */
 	p0.h = hi(IMASK);
 	p0.l = lo(IMASK);
@@ -487,66 +491,30 @@
 	[p0] = r0;
 	SSYNC;
 
-	/* Disable the WDOG TIMER */
-	p0.h = hi(WDOG_CTL);
-	p0.l = lo(WDOG_CTL);
-	r0.l = 0xAD6;
-	w[p0] = r0.l;
+	/* make sure SYSCR is set to use BMODE */
+	P0.h = hi(SYSCR);
+	P0.l = lo(SYSCR);
+	R0.l = 0x0;
+	W[P0] = R0.l;
 	SSYNC;
 
-	/* Clear the sticky bit incase it is already set */
-	p0.h = hi(WDOG_CTL);
-	p0.l = lo(WDOG_CTL);
-	r0.l = 0x8AD6;
-	w[p0] = r0.l;
+	/* issue a system soft reset */
+	P1.h = hi(SWRST);
+	P1.l = lo(SWRST);
+	R1.l = 0x0007;
+	W[P1] = R1;
 	SSYNC;
 
-	/* Program the count value */
-	R0.l = 0x100;
-	R0.h = 0x0;
-	P0.h = hi(WDOG_CNT);
-	P0.l = lo(WDOG_CNT);
-	[P0] = R0;
+	/* clear system soft reset */
+	R0.l = 0x0000;
+	W[P0] = R0;
 	SSYNC;
 
-	/* Program WDOG_STAT if necessary */
-	P0.h = hi(WDOG_CTL);
-	P0.l = lo(WDOG_CTL);
-	R0 = W[P0](Z);
-	CC = BITTST(R0,1);
-	if !CC JUMP .LWRITESTAT;
-	CC = BITTST(R0,2);
-	if !CC JUMP .LWRITESTAT;
-	JUMP .LSKIP_WRITE;
-
-.LWRITESTAT:
-	/* When watch dog timer is enabled, a write to STAT will load the contents of CNT to STAT */
-	R0 = 0x0000(z);
-	P0.h = hi(WDOG_STAT);
-	P0.l = lo(WDOG_STAT)
-	[P0] = R0;
-	SSYNC;
-
-.LSKIP_WRITE:
-	/* Enable the reset event */
-	P0.h = hi(WDOG_CTL);
-	P0.l = lo(WDOG_CTL);
-	R0 = W[P0](Z);
-	BITCLR(R0,1);
-	BITCLR(R0,2);
-	W[P0] = R0.L;
-	SSYNC;
-	NOP;
-
-	/* Enable the wdog counter */
-	R0 = W[P0](Z);
-	BITCLR(R0,4);
-	W[P0] = R0.L;
-	SSYNC;
-
-	IDLE;
+	/* issue core reset */
+	raise 1;
 
 	RTS;
+ENDPROC(_bfin_reset)
 
 #if CONFIG_DEBUG_KERNEL_START
 debug_kernel_start_trap:
diff --git a/arch/blackfin/mach-bf533/ints-priority.c b/arch/blackfin/mach-bf533/ints-priority.c
index 36a6933..7d79e0f 100644
--- a/arch/blackfin/mach-bf533/ints-priority.c
+++ b/arch/blackfin/mach-bf533/ints-priority.c
@@ -4,7 +4,7 @@
  * Author:       Michael Hennerich
  *
  * Created:      ?
- * Description:  Set up the interupt priorities
+ * Description:  Set up the interrupt priorities
  *
  * Modified:
  *               Copyright 2004-2006 Analog Devices Inc.
@@ -28,8 +28,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
 
 void program_IAR(void)
 {
diff --git a/arch/blackfin/mach-bf537/Makefile b/arch/blackfin/mach-bf537/Makefile
index f32d442..7e7c9c8 100644
--- a/arch/blackfin/mach-bf537/Makefile
+++ b/arch/blackfin/mach-bf537/Makefile
@@ -4,6 +4,6 @@
 
 extra-y := head.o
 
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
 
 obj-$(CONFIG_CPU_FREQ)   += cpu.o
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
index 6a60618..a8f947b 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -35,7 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -53,11 +53,11 @@
 		.size = 0x00020000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
-	},{
+	}, {
 		.name = "kernel",
 		.size = 0xe0000,
 		.offset = 0x20000
-	},{
+	}, {
 		.name = "file system",
 		.size = 0x700000,
 		.offset = 0x00100000,
@@ -202,7 +202,7 @@
 		.start = 0x20200300,
 		.end = 0x20200300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF14,
 		.end = IRQ_PF14,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -223,11 +223,11 @@
 		.start = 0x20308000,
 		.end = 0x20308000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x20308004,
 		.end = 0x20308004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PG15,
 		.end = IRQ_PG15,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -262,7 +262,7 @@
 		.start = 0x20200000,
 		.end = 0x20200000 + 0x100,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -283,7 +283,7 @@
 		.start = 0xFFC00400,
 		.end = 0xFFC004FF,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0xFFC02000,
 		.end = 0xFFC020FF,
 		.flags = IORESOURCE_MEM,
diff --git a/arch/blackfin/mach-bf537/boards/eth_mac.c b/arch/blackfin/mach-bf537/boards/eth_mac.c
index e129a08..a725cc8 100644
--- a/arch/blackfin/mach-bf537/boards/eth_mac.c
+++ b/arch/blackfin/mach-bf537/boards/eth_mac.c
@@ -20,8 +20,7 @@
 #include <linux/module.h>
 #include <asm/blackfin.h>
 
-#if	defined(CONFIG_GENERIC_BOARD) \
-	|| defined(CONFIG_BFIN537_STAMP)
+#if	defined(CONFIG_GENERIC_BOARD) || defined(CONFIG_BFIN537_STAMP)
 
 /*
  * Currently the MAC address is saved in Flash by U-Boot
@@ -43,7 +42,7 @@
  */
 void get_bf537_ether_addr(char *addr)
 {
-	printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n",__FILE__);
+	printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n", __FILE__);
 }
 
 #endif
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 9019c0e..648d984 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -35,9 +35,9 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
-#include <asm/bfin5xx_spi.h>
+#include <linux/irq.h>
 #include <linux/usb_sl811.h>
+#include <asm/bfin5xx_spi.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -54,19 +54,19 @@
 		.start = 0x20310000, /* IO PORT */
 		.end = 0x20312000,
 		.flags = IORESOURCE_MEM,
-	},{
-		.start = 0x20311000, /* Attribute Memeory */
+	}, {
+		.start = 0x20311000, /* Attribute Memory */
 		.end = 0x20311FFF,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PROG_INTA,
 		.end = IRQ_PROG_INTA,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},{
+	}, {
 		.start = IRQ_PF4,
 		.end = IRQ_PF4,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},{
+	}, {
 		.start = 6, /* Card Detect PF6 */
 		.end = 6,
 		.flags = IORESOURCE_IRQ,
@@ -95,11 +95,11 @@
 		.start = 0x20300300,
 		.end = 0x20300300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PROG_INTB,
 		.end = IRQ_PROG_INTB,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},{
+	}, {
 		/*
 		 *  denotes the flag pin and is used directly if
 		 *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
@@ -123,15 +123,15 @@
 		.start = 0x20340000,
 		.end = 0x20340000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x20340004,
 		.end = 0x20340004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PROG_INTA,
 		.end = IRQ_PROG_INTA,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},{
+	}, {
 		.start = IRQ_PF0 + CONFIG_USB_SL811_BFIN_GPIO,
 		.end = IRQ_PF0 + CONFIG_USB_SL811_BFIN_GPIO,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -179,15 +179,15 @@
 		.start = 0x20360000,
 		.end = 0x20360000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x20360004,
 		.end = 0x20360004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PROG_INTA,
 		.end = IRQ_PROG_INTA,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},{
+	}, {
 		.start = IRQ_PF0 + CONFIG_USB_ISP1362_BFIN_GPIO,
 		.end = IRQ_PF0 + CONFIG_USB_ISP1362_BFIN_GPIO,
 		.flags = IORESOURCE_IRQ,
@@ -228,7 +228,7 @@
 		.start = 0x20300000,
 		.end = 0x20300000 + 0x100,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -253,11 +253,11 @@
 		.size = 0x00020000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
-	},{
+	}, {
 		.name = "kernel",
 		.size = 0xe0000,
 		.offset = 0x20000
-	},{
+	}, {
 		.name = "file system",
 		.size = 0x700000,
 		.offset = 0x00100000,
@@ -375,7 +375,7 @@
 		.start = 0xFFC00400,
 		.end = 0xFFC004FF,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0xFFC02000,
 		.end = 0xFFC020FF,
 		.flags = IORESOURCE_MEM,
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 40d3a1b..8806f12 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -37,7 +37,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb_isp1362.h>
 #endif
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 #include <linux/usb_sl811.h>
 
@@ -58,15 +58,15 @@
 		.start = 0x20310000, /* IO PORT */
 		.end = 0x20312000,
 		.flags = IORESOURCE_MEM,
-	},{
-		.start = 0x20311000, /* Attribute Memeory */
+	}, {
+		.start = 0x20311000, /* Attribute Memory */
 		.end = 0x20311FFF,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF4,
 		.end = IRQ_PF4,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},{
+	}, {
 		.start = 6, /* Card Detect PF6 */
 		.end = 6,
 		.flags = IORESOURCE_IRQ,
@@ -95,7 +95,7 @@
 		.start = 0x20300300,
 		.end = 0x20300300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
@@ -116,11 +116,11 @@
 		.start = 0x20340000,
 		.end = 0x20340000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x20340004,
 		.end = 0x20340004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = CONFIG_USB_SL811_BFIN_IRQ,
 		.end = CONFIG_USB_SL811_BFIN_IRQ,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -167,11 +167,11 @@
 		.start = 0x20360000,
 		.end = 0x20360000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x20360004,
 		.end = 0x20360004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
 		.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -212,7 +212,7 @@
 		.start = 0x20300000,
 		.end = 0x20300000 + 0x100,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -238,11 +238,11 @@
 		.size = 0x00020000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
-	},{
+	}, {
 		.name = "kernel",
 		.size = 0xe0000,
 		.offset = 0x20000
-	},{
+	}, {
 		.name = "file system",
 		.size = 0x700000,
 		.offset = 0x00100000,
@@ -294,16 +294,6 @@
 };
 #endif
 
-#if defined(CONFIG_PBX)
-static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
-	.ctl_reg	= 0x4, /* send zero */
-	.enable_dma	= 0,
-	.bits_per_word	= 8,
-	.cs_change_per_word = 1,
-};
-#endif
-
-
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
 	.cs_change_per_word = 1,
@@ -392,24 +382,6 @@
 		.mode = SPI_MODE_3,
 	},
 #endif
-#if defined(CONFIG_PBX)
-	{
-		.modalias	= "fxs-spi",
-		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num	= 1,
-		.chip_select	= 3,
-		.controller_data= &spi_si3xxx_chip_info,
-		.mode = SPI_MODE_3,
-	},
-	{
-		.modalias	= "fxo-spi",
-		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num	= 1,
-		.chip_select	= 2,
-		.controller_data= &spi_si3xxx_chip_info,
-		.mode = SPI_MODE_3,
-	},
-#endif
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 {
 	.modalias		= "ad7877",
@@ -451,7 +423,7 @@
 		.start = 0xFFC00400,
 		.end = 0xFFC004FF,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0xFFC02000,
 		.end = 0xFFC020FF,
 		.flags = IORESOURCE_MEM,
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index ba2f875..9c43d77 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -37,12 +37,10 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb_isp1362.h>
 #endif
-#include <asm/irq.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/bfin5xx_spi.h>
 #include <linux/usb_sl811.h>
-
+#include <asm/bfin5xx_spi.h>
 #include <linux/spi/ad7877.h>
 
 /*
@@ -85,7 +83,7 @@
 
 int __init bfin_isp1761_init(void)
 {
-	unsigned int num_devices=ARRAY_SIZE(bfin_isp1761_devices);
+	unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
 
 	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
 	set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
@@ -107,15 +105,15 @@
 		.start = 0x20310000, /* IO PORT */
 		.end = 0x20312000,
 		.flags = IORESOURCE_MEM,
-	},{
-		.start = 0x20311000, /* Attribute Memeory */
+	}, {
+		.start = 0x20311000, /* Attribute Memory */
 		.end = 0x20311FFF,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF4,
 		.end = IRQ_PF4,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},{
+	}, {
 		.start = 6, /* Card Detect PF6 */
 		.end = 6,
 		.flags = IORESOURCE_IRQ,
@@ -144,7 +142,7 @@
 		.start = 0x20300300,
 		.end = 0x20300300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
@@ -159,17 +157,39 @@
 };
 #endif
 
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource dm9000_resources[] = {
+	[0] = {
+		.start	= 0x203FB800,
+		.end	= 0x203FB800 + 8,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_PF9,
+		.end	= IRQ_PF9,
+		.flags	= (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
+	},
+};
+
+static struct platform_device dm9000_device = {
+	.name		= "dm9000",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(dm9000_resources),
+	.resource	= dm9000_resources,
+};
+#endif
+
 #if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
 static struct resource sl811_hcd_resources[] = {
 	{
 		.start = 0x20340000,
 		.end = 0x20340000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x20340004,
 		.end = 0x20340004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = CONFIG_USB_SL811_BFIN_IRQ,
 		.end = CONFIG_USB_SL811_BFIN_IRQ,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -216,11 +236,11 @@
 		.start = 0x20360000,
 		.end = 0x20360000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x20360004,
 		.end = 0x20360004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
 		.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -261,7 +281,7 @@
 		.start = 0x20300000,
 		.end = 0x20300000 + 0x100,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -287,11 +307,11 @@
 		.size = 0x00020000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
-	},{
+	}, {
 		.name = "kernel",
 		.size = 0xe0000,
 		.offset = 0x20000
-	},{
+	}, {
 		.name = "file system",
 		.size = 0x700000,
 		.offset = 0x00100000,
@@ -361,7 +381,6 @@
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-//	.cs_change_per_word = 1,
 	.enable_dma = 0,
 	.bits_per_word = 16,
 };
@@ -449,19 +468,19 @@
 #endif
 #if defined(CONFIG_PBX)
 	{
-		.modalias	= "fxs-spi",
-		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num	= 1,
-		.chip_select	= 3,
-		.controller_data= &spi_si3xxx_chip_info,
+		.modalias = "fxs-spi",
+		.max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = 3,
+		.controller_data = &spi_si3xxx_chip_info,
 		.mode = SPI_MODE_3,
 	},
 	{
-		.modalias	= "fxo-spi",
-		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num	= 1,
-		.chip_select	= 2,
-		.controller_data= &spi_si3xxx_chip_info,
+		.modalias = "fxo-spi",
+		.max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = 2,
+		.controller_data = &spi_si3xxx_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -516,7 +535,7 @@
 		.start = 0xFFC00400,
 		.end = 0xFFC004FF,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0xFFC02000,
 		.end = 0xFFC020FF,
 		.flags = IORESOURCE_MEM,
@@ -571,6 +590,10 @@
 	&smc91x_device,
 #endif
 
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+	&dm9000_device,
+#endif
+
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 	&bfin_mac_device,
 #endif
diff --git a/arch/blackfin/mach-bf537/cpu.c b/arch/blackfin/mach-bf537/cpu.c
index 2d83b7e..0442c4c 100644
--- a/arch/blackfin/mach-bf537/cpu.c
+++ b/arch/blackfin/mach-bf537/cpu.c
@@ -43,13 +43,13 @@
 #define VCO1 (CONFIG_CLKIN_HZ*9)	/*99532800 */
 #define VCO(x) VCO##x
 
-#define FREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
 /* frequency */
 static struct cpufreq_frequency_table bf537_freq_table[] = {
-	FREQ(1),
-	FREQ(3),
+	MFREQ(1),
+	MFREQ(3),
 	{VCO4, VCO4 / 2}, {VCO4, VCO4},
-	FREQ(5),
+	MFREQ(5),
 	{0, CPUFREQ_TABLE_END},
 };
 
@@ -59,13 +59,14 @@
  */
 static int bf537_getfreq(unsigned int cpu)
 {
-	unsigned long cclk_mhz, vco_mhz;
+	unsigned long cclk_mhz;
 
 	/* The driver only support single cpu */
 	if (cpu == 0)
 		dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
 	else
 		cclk_mhz = -1;
+
 	return cclk_mhz;
 }
 
@@ -75,13 +76,12 @@
 	unsigned long cclk_mhz;
 	unsigned long vco_mhz;
 	unsigned long flags;
-	unsigned int index, vco_index;
-	int i;
-
+	unsigned int index;
 	struct cpufreq_freqs freqs;
-	if (cpufreq_frequency_table_target
-	    (policy, bf537_freq_table, target_freq, relation, &index))
+
+	if (cpufreq_frequency_table_target(policy, bf537_freq_table, target_freq, relation, &index))
 		return -EINVAL;
+
 	cclk_mhz = bf537_freq_table[index].frequency;
 	vco_mhz = bf537_freq_table[index].index;
 
@@ -114,8 +114,6 @@
 
 static int __init __bf537_cpu_init(struct cpufreq_policy *policy)
 {
-	int result;
-
 	if (policy->cpu != 0)
 		return -EINVAL;
 
diff --git a/arch/blackfin/mach-bf537/dma.c b/arch/blackfin/mach-bf537/dma.c
new file mode 100644
index 0000000..706cb97
--- /dev/null
+++ b/arch/blackfin/mach-bf537/dma.c
@@ -0,0 +1,115 @@
+/*
+ * File:         arch/blackfin/mach-bf537/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+	(struct dma_register *) DMA0_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_NEXT_DESC_PTR,
+	(struct dma_register *) DMA3_NEXT_DESC_PTR,
+	(struct dma_register *) DMA4_NEXT_DESC_PTR,
+	(struct dma_register *) DMA5_NEXT_DESC_PTR,
+	(struct dma_register *) DMA6_NEXT_DESC_PTR,
+	(struct dma_register *) DMA7_NEXT_DESC_PTR,
+	(struct dma_register *) DMA8_NEXT_DESC_PTR,
+	(struct dma_register *) DMA9_NEXT_DESC_PTR,
+	(struct dma_register *) DMA10_NEXT_DESC_PTR,
+	(struct dma_register *) DMA11_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+	int ret_irq = -1;
+
+	switch (channel) {
+	case CH_PPI:
+		ret_irq = IRQ_PPI;
+		break;
+
+	case CH_EMAC_RX:
+		ret_irq = IRQ_MAC_RX;
+		break;
+
+	case CH_EMAC_TX:
+		ret_irq = IRQ_MAC_TX;
+		break;
+
+	case CH_UART1_RX:
+		ret_irq = IRQ_UART1_RX;
+		break;
+
+	case CH_UART1_TX:
+		ret_irq = IRQ_UART1_TX;
+		break;
+
+	case CH_SPORT0_RX:
+		ret_irq = IRQ_SPORT0_RX;
+		break;
+
+	case CH_SPORT0_TX:
+		ret_irq = IRQ_SPORT0_TX;
+		break;
+
+	case CH_SPORT1_RX:
+		ret_irq = IRQ_SPORT1_RX;
+		break;
+
+	case CH_SPORT1_TX:
+		ret_irq = IRQ_SPORT1_TX;
+		break;
+
+	case CH_SPI:
+		ret_irq = IRQ_SPI;
+		break;
+
+	case CH_UART_RX:
+		ret_irq = IRQ_UART_RX;
+		break;
+
+	case CH_UART_TX:
+		ret_irq = IRQ_UART_TX;
+		break;
+
+	case CH_MEM_STREAM0_SRC:
+	case CH_MEM_STREAM0_DEST:
+		ret_irq = IRQ_MEM_DMA0;
+		break;
+
+	case CH_MEM_STREAM1_SRC:
+	case CH_MEM_STREAM1_DEST:
+		ret_irq = IRQ_MEM_DMA1;
+		break;
+	}
+	return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf537/head.S b/arch/blackfin/mach-bf537/head.S
index d104e1d8..429c8a1 100644
--- a/arch/blackfin/mach-bf537/head.S
+++ b/arch/blackfin/mach-bf537/head.S
@@ -28,7 +28,10 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/init.h>
 #include <asm/blackfin.h>
+#include <asm/trace.h>
+
 #if CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach/mem_init.h>
 #endif
@@ -40,20 +43,21 @@
 .extern ___bss_start
 .extern _bf53x_relocate_l1_mem
 
-#define INITIAL_STACK   0xFFB01000
+#define INITIAL_STACK	0xFFB01000
 
-.text
+__INIT
 
 ENTRY(__start)
-ENTRY(__stext)
 	/* R0: argument of command line string, passed from uboot, save it */
 	R7 = R0;
-	/* Set the SYSCFG register */
+	/* Set the SYSCFG register:
+	 * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit)
+	 */
 	R0 = 0x36;
-	SYSCFG = R0;   /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+	SYSCFG = R0;
 	R0 = 0;
 
-	/* Clear Out All the data and pointer  Registers*/
+	/* Clear Out All the data and pointer Registers */
 	R1 = R0;
 	R2 = R0;
 	R3 = R0;
@@ -75,7 +79,7 @@
 	L2 = r0;
 	L3 = r0;
 
-	/* Clear Out All the DAG Registers*/
+	/* Clear Out All the DAG Registers */
 	B0 = r0;
 	B1 = r0;
 	B2 = r0;
@@ -91,6 +95,10 @@
 	M2 = r0;
 	M3 = r0;
 
+	trace_buffer_start(p0,r0);
+	P0 = R1;
+	R0 = R1;
+
 	/* Turn off the icache */
 	p0.l = (IMEM_CONTROL & 0xFFFF);
 	p0.h = (IMEM_CONTROL >> 16);
@@ -181,7 +189,8 @@
 	SSYNC;
 #endif
 
-	/*Initialise UART*/
+	/* Initialise UART - when booting from u-boot, the UART is not disabled
+	 * so if we dont initalize here, our serial console gets hosed */
 	p0.h = hi(UART_LCR);
 	p0.l = lo(UART_LCR);
 	r0 = 0x0(Z);
@@ -190,7 +199,7 @@
 
 	p0.h = hi(UART_DLL);
 	p0.l = lo(UART_DLL);
-	r0 = 0x00(Z);
+	r0 = 0x0(Z);
 	w[p0] = r0.L;
 	ssync;
 
@@ -217,6 +226,7 @@
 #if CONFIG_BFIN_KERNEL_CLOCK
 	call _start_dma_code;
 #endif
+
 	/* Code for initializing Async memory banks */
 
 	p2.h = hi(EBIU_AMBCTL1);
@@ -271,6 +281,7 @@
 
 .LWAIT_HERE:
 	jump .LWAIT_HERE;
+ENDPROC(__start)
 
 ENTRY(_real_start)
 	[ -- sp ] = reti;
@@ -290,7 +301,7 @@
 	p2.h = ___bss_stop;
 	r0 = 0;
 	p2 -= p1;
-	lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+	lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
 .L_clear_bss:
 	B[p1++] = r0;
 
@@ -305,7 +316,7 @@
 	r0 = r0 >> 1;
 	p2 = r0;
 	r0 = 0;
-	lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+	lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
 .L_clear_zero:
 	W[p1++] = r0;
 
@@ -327,9 +338,8 @@
 	r1 = p3;
 	[p1] = r1;
 
-
 	/*
-	 *  load the current thread pointer and stack
+	 * load the current thread pointer and stack
 	 */
 	r1.l = _init_thread_union;
 	r1.h = _init_thread_union;
@@ -340,9 +350,10 @@
 	sp = r1;
 	usp = sp;
 	fp = sp;
-	call _start_kernel;
-.L_exit:
-	jump.s	.L_exit;
+	jump.l _start_kernel;
+ENDPROC(_real_start)
+
+__FINIT
 
 .section .l1.text
 #if CONFIG_BFIN_KERNEL_CLOCK
@@ -461,6 +472,7 @@
 	SSYNC;
 
 	RTS;
+ENDPROC(_start_dma_code)
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
 
 ENTRY(_bfin_reset)
@@ -469,47 +481,41 @@
 	SSYNC;
 
 #if defined(CONFIG_MTD_M25P80)
-/*
- * The following code fix the SPI flash reboot issue,
- * /CS signal of the chip which is using PF10 return to GPIO mode
- */
+	/*
+	 * The following code fix the SPI flash reboot issue,
+	 * /CS signal of the chip which is using PF10 return to GPIO mode
+	 */
 	p0.h = hi(PORTF_FER);
 	p0.l = lo(PORTF_FER);
 	r0.l = 0x0000;
 	w[p0] = r0.l;
 	SSYNC;
 
-/* /CS return to high */
+	/* /CS return to high */
 	p0.h = hi(PORTFIO);
 	p0.l = lo(PORTFIO);
 	r0.l = 0xFFFF;
 	w[p0] = r0.l;
 	SSYNC;
 
-/* Delay some time, This is necessary */
+	/* Delay some time, This is necessary */
 	r1.h = 0;
 	r1.l = 0x400;
 	p1   = r1;
-	lsetup (_delay_lab1,_delay_lab1_end ) lc1 = p1;
-_delay_lab1:
+	lsetup (.L_delay_lab1, .L_delay_lab1_end) lc1 = p1;
+.L_delay_lab1:
 	r0.h = 0;
 	r0.l = 0x8000;
 	p0   = r0;
-	lsetup (_delay_lab0,_delay_lab0_end ) lc0 = p0;
-_delay_lab0:
+	lsetup (.L_delay_lab0, .L_delay_lab0_end) lc0 = p0;
+.L_delay_lab0:
 	nop;
-_delay_lab0_end:
+.L_delay_lab0_end:
 	nop;
-_delay_lab1_end:
+.L_delay_lab1_end:
 	nop;
 #endif
 
-	/* Clear the bits 13-15 in SWRST if they werent cleared */
-	p0.h = hi(SWRST);
-	p0.l = lo(SWRST);
-	csync;
-	r0.l = w[p0];
-
 	/* Clear the IMASK register */
 	p0.h = hi(IMASK);
 	p0.l = lo(IMASK);
@@ -523,68 +529,30 @@
 	[p0] = r0;
 	SSYNC;
 
-	/* Disable the WDOG TIMER */
-	p0.h = hi(WDOG_CTL);
-	p0.l = lo(WDOG_CTL);
-	r0.l = 0xAD6;
-	w[p0] = r0.l;
+	/* make sure SYSCR is set to use BMODE */
+	P0.h = hi(SYSCR);
+	P0.l = lo(SYSCR);
+	R0.l = 0x0;
+	W[P0] = R0.l;
 	SSYNC;
 
-	/* Clear the sticky bit incase it is already set */
-	p0.h = hi(WDOG_CTL);
-	p0.l = lo(WDOG_CTL);
-	r0.l = 0x8AD6;
-	w[p0] = r0.l;
+	/* issue a system soft reset */
+	P1.h = hi(SWRST);
+	P1.l = lo(SWRST);
+	R1.l = 0x0007;
+	W[P1] = R1;
 	SSYNC;
 
-	/* Program the count value */
-	R0.l = 0x100;
-	R0.h = 0x0;
-	P0.h = hi(WDOG_CNT);
-	P0.l = lo(WDOG_CNT);
-	[P0] = R0;
+	/* clear system soft reset */
+	R0.l = 0x0000;
+	W[P0] = R0;
 	SSYNC;
 
-	/* Program WDOG_STAT if necessary */
-	P0.h = hi(WDOG_CTL);
-	P0.l = lo(WDOG_CTL);
-	R0 = W[P0](Z);
-	CC = BITTST(R0,1);
-	if !CC JUMP .LWRITESTAT;
-	CC = BITTST(R0,2);
-	if !CC JUMP .LWRITESTAT;
-	JUMP .LSKIP_WRITE;
-
-.LWRITESTAT:
-	/* When watch dog timer is enabled,
-	 * a write to STAT will load the contents of CNT to STAT
-	 */
-	R0 = 0x0000(z);
-	P0.h = hi(WDOG_STAT);
-	P0.l = lo(WDOG_STAT)
-	[P0] = R0;
-	SSYNC;
-
-.LSKIP_WRITE:
-	/* Enable the reset event */
-	P0.h = hi(WDOG_CTL);
-	P0.l = lo(WDOG_CTL);
-	R0 = W[P0](Z);
-	BITCLR(R0,1);
-	BITCLR(R0,2);
-	W[P0] = R0.L;
-	SSYNC;
-	NOP;
-
-	/* Enable the wdog counter */
-	R0 = W[P0](Z);
-	BITCLR(R0,4);
-	W[P0] = R0.L;
-	SSYNC;
-
-	IDLE;
+	/* issue core reset */
+	raise 1;
 
 	RTS;
+ENDPROC(_bfin_reset)
 
 .data
 
diff --git a/arch/blackfin/mach-bf537/ints-priority.c b/arch/blackfin/mach-bf537/ints-priority.c
index fd6308e..a8b915f 100644
--- a/arch/blackfin/mach-bf537/ints-priority.c
+++ b/arch/blackfin/mach-bf537/ints-priority.c
@@ -4,7 +4,7 @@
  * Author:       Michael Hennerich
  *
  * Created:
- * Description:  Set up the interupt priorities
+ * Description:  Set up the interrupt priorities
  *
  * Modified:
  *               Copyright 2004-2006 Analog Devices Inc.
@@ -28,8 +28,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
 
 void program_IAR(void)
 {
diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig
new file mode 100644
index 0000000..e78b03d
--- /dev/null
+++ b/arch/blackfin/mach-bf548/Kconfig
@@ -0,0 +1,316 @@
+if (BF54x)
+
+menu "BF548 Specific Configuration"
+
+comment "Interrupt Priority Assignment"
+menu "Priority"
+
+config IRQ_PLL_WAKEUP
+	int "IRQ_PLL_WAKEUP"
+	default 7
+config IRQ_DMAC0_ERR
+	int "IRQ_DMAC0_ERR"
+	default 7
+config IRQ_EPPI0_ERR
+	int "IRQ_EPPI0_ERR"
+	default 7
+config IRQ_SPORT0_ERR
+	int "IRQ_SPORT0_ERR"
+	default 7
+config IRQ_SPORT1_ERR
+	int "IRQ_SPORT1_ERR"
+	default 7
+config IRQ_SPI0_ERR
+	int "IRQ_SPI0_ERR"
+	default 7
+config IRQ_UART0_ERR
+	int "IRQ_UART0_ERR"
+	default 7
+config IRQ_RTC
+	int "IRQ_RTC"
+	default 8
+config IRQ_EPPI0
+	int "IRQ_EPPI0"
+	default 8
+config IRQ_SPORT0_RX
+	int "IRQ_SPORT0_RX"
+	default 9
+config IRQ_SPORT0_TX
+	int "IRQ_SPORT0_TX"
+	default 9
+config IRQ_SPORT1_RX
+	int "IRQ_SPORT1_RX"
+	default 9
+config IRQ_SPORT1_TX
+	int "IRQ_SPORT1_TX"
+	default 9
+config IRQ_SPI0
+	int "IRQ_SPI0"
+	default 10
+config IRQ_UART0_RX
+	int "IRQ_UART0_RX"
+	default 10
+config IRQ_UART0_TX
+	int "IRQ_UART0_TX"
+	default 10
+config IRQ_TIMER8
+	int "IRQ_TIMER8"
+	default 11
+config IRQ_TIMER9
+	int "IRQ_TIMER9"
+	default 11
+config IRQ_TIMER10
+	int "IRQ_TIMER10"
+	default 11
+config IRQ_PINT0
+	int "IRQ_PINT0"
+	default 12
+config IRQ_PINT1
+	int "IRQ_PINT0"
+	default 12
+config IRQ_MDMAS0
+	int "IRQ_MDMAS0"
+	default 13
+config IRQ_MDMAS1
+	int "IRQ_DMDMAS1"
+	default 13
+config IRQ_WATCHDOG
+	int "IRQ_WATCHDOG"
+	default 13
+config IRQ_DMAC1_ERR
+	int "IRQ_DMAC1_ERR"
+	default 7
+config IRQ_SPORT2_ERR
+	int "IRQ_SPORT2_ERR"
+	default 7
+config IRQ_SPORT3_ERR
+	int "IRQ_SPORT3_ERR"
+	default 7
+config IRQ_MXVR_DATA
+	int "IRQ MXVR Data"
+	default 7
+config IRQ_SPI1_ERR
+	int "IRQ_SPI1_ERR"
+	default 7
+config IRQ_SPI2_ERR
+	int "IRQ_SPI2_ERR"
+	default 7
+config IRQ_UART1_ERR
+	int "IRQ_UART1_ERR"
+	default 7
+config IRQ_UART2_ERR
+	int "IRQ_UART2_ERR"
+	default 7
+config IRQ_CAN0_ERR
+	int "IRQ_CAN0_ERR"
+	default 7
+config IRQ_SPORT2_RX
+	int "IRQ_SPORT2_RX"
+	default 9
+config IRQ_SPORT2_TX
+	int "IRQ_SPORT2_TX"
+	default 9
+config IRQ_SPORT3_RX
+	int "IRQ_SPORT3_RX"
+	default 9
+config IRQ_SPORT3_TX
+	int "IRQ_SPORT3_TX"
+	default 9
+config IRQ_EPPI1
+	int "IRQ_EPPI1"
+	default 9
+config IRQ_EPPI2
+	int "IRQ_EPPI2"
+	default 9
+config IRQ_SPI1
+	int "IRQ_SPI1"
+	default 10
+config IRQ_SPI2
+	int "IRQ_SPI2"
+	default 10
+config IRQ_UART1_RX
+	int "IRQ_UART1_RX"
+	default 10
+config IRQ_UART1_TX
+	int "IRQ_UART1_TX"
+	default 10
+config IRQ_ATAPI_RX
+	int "IRQ_ATAPI_RX"
+	default 10
+config IRQ_ATAPI_TX
+	int "IRQ_ATAPI_TX"
+	default 10
+config IRQ_TWI0
+	int "IRQ_TWI0"
+	default 11
+config IRQ_TWI1
+	int "IRQ_TWI1"
+	default 11
+config IRQ_CAN0_RX
+	int "IRQ_CAN_RX"
+	default 11
+config IRQ_CAN0_TX
+	int "IRQ_CAN_TX"
+	default 11
+config IRQ_MDMAS2
+	int "IRQ_MDMAS2"
+	default 13
+config IRQ_MDMAS3
+	int "IRQ_DMMAS3"
+	default 13
+config IRQ_MXVR_ERR
+	int "IRQ_MXVR_ERR"
+	default 11
+config IRQ_MXVR_MSG
+	int "IRQ_MXVR_MSG"
+	default 11
+config IRQ_MXVR_PKT
+	int "IRQ_MXVR_PKT"
+	default 11
+config IRQ_EPPI1_ERR
+	int "IRQ_EPPI1_ERR"
+	default 7
+config IRQ_EPPI2_ERR
+	int "IRQ_EPPI2_ERR"
+	default 7
+config IRQ_UART3_ERR
+	int "IRQ_UART3_ERR"
+	default 7
+config IRQ_HOST_ERR
+	int "IRQ_HOST_ERR"
+	default 7
+config IRQ_PIXC_ERR
+	int "IRQ_PIXC_ERR"
+	default 7
+config IRQ_NFC_ERR
+	int "IRQ_NFC_ERR"
+	default 7
+config IRQ_ATAPI_ERR
+	int "IRQ_ATAPI_ERR"
+	default 7
+config IRQ_CAN1_ERR
+	int "IRQ_CAN1_ERR"
+	default 7
+config IRQ_HS_DMA_ERR
+	int "IRQ Handshake DMA Status"
+	default 7
+config IRQ_PIXC_IN0
+	int "IRQ PIXC IN0"
+	default 8
+config IRQ_PIXC_IN1
+	int "IRQ PIXC IN1"
+	default 8
+config IRQ_PIXC_OUT
+	int "IRQ PIXC OUT"
+	default 8
+config IRQ_SDH
+	int "IRQ SDH"
+	default 8
+config IRQ_CNT
+	int "IRQ CNT"
+	default 8
+config IRQ_KEY
+	int "IRQ KEY"
+	default 8
+config IRQ_CAN1_RX
+	int "IRQ CAN1 RX"
+	default 11
+config IRQ_CAN1_TX
+	int "IRQ_CAN1_TX"
+	default 11
+config IRQ_SDH_MASK0
+	int "IRQ_SDH_MASK0"
+	default 11
+config IRQ_SDH_MASK1
+	int "IRQ_SDH_MASK1"
+	default 11
+config IRQ_USB_INT0
+	int "IRQ USB INT0"
+	default 11
+config IRQ_USB_INT1
+	int "IRQ USB INT1"
+	default 11
+config IRQ_USB_INT2
+	int "IRQ USB INT2"
+	default 11
+config IRQ_USB_DMA
+	int "IRQ USB DMA"
+	default 11
+config IRQ_OTPSEC
+	int "IRQ OPTSEC"
+	default 11
+config IRQ_TIMER0
+	int "IRQ_TIMER0"
+	default 11
+config IRQ_TIMER1
+	int "IRQ_TIMER1"
+	default 11
+config IRQ_TIMER2
+	int "IRQ_TIMER2"
+	default 11
+config IRQ_TIMER3
+	int "IRQ_TIMER3"
+	default 11
+config IRQ_TIMER4
+	int "IRQ_TIMER4"
+	default 11
+config IRQ_TIMER5
+	int "IRQ_TIMER5"
+	default 11
+config IRQ_TIMER6
+	int "IRQ_TIMER6"
+	default 11
+config IRQ_TIMER7
+	int "IRQ_TIMER7"
+	default 11
+config IRQ_PINT2
+	int "IRQ_PIN2"
+	default 11
+config IRQ_PINT3
+	int "IRQ_PIN3"
+	default 11
+
+	help
+	  Enter the priority numbers between 7-13 ONLY.  Others are Reserved.
+	  This applies to all the above.  It is not recommended to assign the
+	  highest priority number 7 to UART or any other device.
+
+endmenu
+
+comment "Pin Interrupt to Port Assignment"
+menu "Assignment"
+
+config PINTx_REASSIGN
+	bool "Reprogram PINT Assignment"
+	default n
+	help
+	  The interrupt assignment registers controls the pin-to-interrupt
+	  assignment in a byte-wide manner. Each option allows you to select
+	  a set of pins (High/Low Byte) of an specific Port being mapped
+	  to one of the four PIN Interrupts IRQ_PINTx.
+
+	  You shouldn't change any of these unless you know exactly what you're doing.
+	  Please consult the Blackfin BF54x Processor Hardware Reference Manual.
+
+config PINT0_ASSIGN
+	hex "PINT0_ASSIGN"
+	depends on PINTx_REASSIGN
+	default 0x00000101
+config PINT1_ASSIGN
+	hex "PINT1_ASSIGN"
+	depends on PINTx_REASSIGN
+	default 0x01010000
+config PINT2_ASSIGN
+	hex "PINT2_ASSIGN"
+	depends on PINTx_REASSIGN
+	default 0x00000101
+config PINT3_ASSIGN
+	hex "PINT3_ASSIGN"
+	depends on PINTx_REASSIGN
+	default 0x02020303
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf548/Makefile b/arch/blackfin/mach-bf548/Makefile
new file mode 100644
index 0000000..060ad78
--- /dev/null
+++ b/arch/blackfin/mach-bf548/Makefile
@@ -0,0 +1,9 @@
+#
+# arch/blackfin/mach-bf537/Makefile
+#
+
+extra-y := head.o
+
+obj-y := ints-priority.o dma.o gpio.o
+
+obj-$(CONFIG_CPU_FREQ)   += cpu.o
diff --git a/arch/blackfin/mach-bf548/boards/Makefile b/arch/blackfin/mach-bf548/boards/Makefile
new file mode 100644
index 0000000..486e07c
--- /dev/null
+++ b/arch/blackfin/mach-bf548/boards/Makefile
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mach-bf548/boards/Makefile
+#
+
+obj-$(CONFIG_BFIN548_EZKIT)		+= ezkit.o led.o
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
new file mode 100644
index 0000000..96ad95f
--- /dev/null
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -0,0 +1,114 @@
+/*
+ * File:         arch/blackfin/mach-bf548/boards/ezkit.c
+ * Based on:     arch/blackfin/mach-bf537/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/irq.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "ADSP-BF548-EZKIT";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+	.name = "rtc-bfin",
+	.id   = -1,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	{
+		.start = 0xFFC00400,
+		.end = 0xFFC004FF,
+		.flags = IORESOURCE_MEM,
+	},
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+	{
+		.start = 0xFFC02000,
+		.end = 0xFFC020FF,
+		.flags = IORESOURCE_MEM,
+	},
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART2
+	{
+		.start = 0xFFC02100,
+		.end = 0xFFC021FF,
+		.flags = IORESOURCE_MEM,
+	},
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART3
+	{
+		.start = 0xFFC03100,
+		.end = 0xFFC031FF,
+	},
+#endif
+};
+
+static struct platform_device bfin_uart_device = {
+	.name = "bfin-uart",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_uart_resources),
+	.resource = bfin_uart_resources,
+};
+#endif
+
+static struct platform_device *ezkit_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+	&rtc_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+	&bfin_uart_device,
+#endif
+};
+
+static int __init stamp_init(void)
+{
+	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+	platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+	return 0;
+}
+
+arch_initcall(stamp_init);
diff --git a/arch/blackfin/mach-bf548/boards/led.S b/arch/blackfin/mach-bf548/boards/led.S
new file mode 100644
index 0000000..f47daf3
--- /dev/null
+++ b/arch/blackfin/mach-bf548/boards/led.S
@@ -0,0 +1,172 @@
+/****************************************************
+ * LED1 ---- PG6        LED2 ---- PG7               *
+ * LED3 ---- PG8        LED4 ---- PG9               *
+ * LED5 ---- PG10       LED6 ---- PG11              *
+ ****************************************************/
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+
+/* All functions in this file save the registers they uses.
+   So there is no need to save any registers before calling them.  */
+
+	.text;
+
+/* Initialize LEDs.  */
+
+ENTRY(_led_init)
+	LINK 0;
+	[--SP] = P0;
+	[--SP] = R0;
+	[--SP] = R1;
+	[--SP] = R2;
+	R1 = (PG6|PG7|PG8|PG9|PG10|PG11)(Z);
+	R2 = ~R1;
+
+	P0.H = hi(PORTG_FER);
+	P0.L = lo(PORTG_FER);
+	R0 = W[P0](Z);
+	SSYNC;
+	R0 = R0 & R2;
+	W[P0] = R0.L;
+	SSYNC;
+
+	P0.H = hi(PORTG_DIR_SET);
+	P0.L = lo(PORTG_DIR_SET);
+	W[P0] = R1.L;
+	SSYNC;
+
+	P0.H = hi(PORTG_INEN);
+	P0.L = lo(PORTG_INEN);
+	R0 = W[P0](Z);
+	SSYNC;
+	R0 = R0 & R2;
+	W[P0] = R0.L;
+	SSYNC;
+
+	R2 = [SP++];
+	R1 = [SP++];
+	R0 = [SP++];
+	P0 = [SP++];
+	RTS;
+	.size	_led_init, .-_led_init
+
+/* Set one LED on. Leave other LEDs unchanged.
+   It expects the LED number passed through R0.  */
+
+ENTRY(_led_on)
+	LINK 0;
+	[--SP] = P0;
+	[--SP] = R1;
+	CALL _led_init;
+	R1 = 1;
+	R0 += 5;
+	R1 <<= R0;
+	P0.H = hi(PORTG_SET);
+	P0.L = lo(PORTG_SET);
+	W[P0] = R1.L;
+	SSYNC;
+	R1 = [SP++];
+	P0 = [SP++];
+	UNLINK;
+	RTS;
+	.size	_led_on, .-_led_on
+
+/* Set one LED off. Leave other LEDs unchanged.  */
+
+ENTRY(_led_off)
+	LINK 0;
+	[--SP] = P0;
+	[--SP] = R1;
+	CALL _led_init;
+	R1 = 1;
+	R0 += 5;
+	R1 <<= R0;
+	P0.H = hi(PORTG_CLEAR);
+	P0.L = lo(PORTG_CLEAR);
+	W[P0] = R1.L;
+	SSYNC;
+	R1 = [SP++];
+	P0 = [SP++];
+	UNLINK;
+	RTS;
+	.size	_led_off, .-_led_off
+
+/* Toggle one LED. Leave other LEDs unchanged.  */
+
+ENTRY(_led_toggle)
+	LINK 0;
+	[--SP] = P0;
+	[--SP] = R1;
+	CALL _led_init;
+	R1 = 1;
+	R0 += 5;
+	R1 <<= R0;
+	P0.H = hi(PORTG);
+	P0.L = lo(PORTG);
+	R0 = W[P0](Z);
+	SSYNC;
+	R0 = R0 ^ R1;
+	W[P0] = R0.L;
+	SSYNC;
+	R1 = [SP++];
+	P0 = [SP++];
+	UNLINK;
+	RTS;
+	.size	_led_toggle, .-_led_toggle
+
+/* Display the number using LEDs in binary format.  */
+
+ENTRY(_led_disp_num)
+	LINK 0;
+	[--SP] = P0;
+	[--SP] = R1;
+	[--SP] = R2;
+	CALL _led_init;
+	R1 = 0x3f(X);
+	R0 = R0 & R1;
+	R2 = 6(X);
+	R0 <<= R2;
+	R1 <<= R2;
+	P0.H = hi(PORTG);
+	P0.L = lo(PORTG);
+	R2 = W[P0](Z);
+	SSYNC;
+	R1 = ~R1;
+	R2 = R2 & R1;
+	R2 = R2 | R0;
+	W[P0] = R2.L;
+	SSYNC;
+	R2 = [SP++];
+	R1 = [SP++];
+	P0 = [SP++];
+	UNLINK;
+	RTS;
+	.size	_led_disp_num, .-_led_disp_num
+
+/* Toggle the number using LEDs in binary format.  */
+
+ENTRY(_led_toggle_num)
+	LINK 0;
+	[--SP] = P0;
+	[--SP] = R1;
+	[--SP] = R2;
+	CALL _led_init;
+	R1 = 0x3f(X);
+	R0 = R0 & R1;
+	R1 = 6(X);
+	R0 <<= R1;
+	P0.H = hi(PORTG);
+	P0.L = lo(PORTG);
+	R1 = W[P0](Z);
+	SSYNC;
+	R1 = R1 ^ R0;
+	W[P0] = R1.L;
+	SSYNC;
+	R2 = [SP++];
+	R1 = [SP++];
+	P0 = [SP++];
+	UNLINK;
+	RTS;
+	.size	_led_toggle_num, .-_led_toggle_num
+
diff --git a/arch/blackfin/mach-bf548/cpu.c b/arch/blackfin/mach-bf548/cpu.c
new file mode 100644
index 0000000..4298a3c
--- /dev/null
+++ b/arch/blackfin/mach-bf548/cpu.c
@@ -0,0 +1,159 @@
+/*
+ * File:         arch/blackfin/mach-bf548/cpu.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  clock scaling for the bf54x
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <asm/dpmc.h>
+#include <linux/fs.h>
+#include <asm/bfin-global.h>
+
+/* CONFIG_CLKIN_HZ=25000000 */
+#define VCO5 (CONFIG_CLKIN_HZ*45)
+#define VCO4 (CONFIG_CLKIN_HZ*36)
+#define VCO3 (CONFIG_CLKIN_HZ*27)
+#define VCO2 (CONFIG_CLKIN_HZ*18)
+#define VCO1 (CONFIG_CLKIN_HZ*9)
+#define VCO(x) VCO##x
+
+#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+/* frequency */
+static struct cpufreq_frequency_table bf548_freq_table[] = {
+	MFREQ(1),
+	MFREQ(3),
+	{VCO4, VCO4 / 2}, {VCO4, VCO4},
+	MFREQ(5),
+	{0, CPUFREQ_TABLE_END},
+};
+
+/*
+ * dpmc_fops->ioctl()
+ * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ */
+static int bf548_getfreq(unsigned int cpu)
+{
+	unsigned long cclk_mhz;
+
+	/* The driver only support single cpu */
+	if (cpu == 0)
+		dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+	else
+		cclk_mhz = -1;
+
+	return cclk_mhz;
+}
+
+static int bf548_target(struct cpufreq_policy *policy,
+			    unsigned int target_freq, unsigned int relation)
+{
+	unsigned long cclk_mhz;
+	unsigned long vco_mhz;
+	unsigned long flags;
+	unsigned int index;
+	struct cpufreq_freqs freqs;
+
+	if (cpufreq_frequency_table_target(policy, bf548_freq_table, target_freq, relation, &index))
+		return -EINVAL;
+
+	cclk_mhz = bf548_freq_table[index].frequency;
+	vco_mhz = bf548_freq_table[index].index;
+
+	dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+	freqs.old = bf548_getfreq(0);
+	freqs.new = cclk_mhz;
+	freqs.cpu = 0;
+
+	pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+	         cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	local_irq_save(flags);
+	dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+	local_irq_restore(flags);
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	vco_mhz = get_vco();
+	cclk_mhz = get_cclk();
+	return 0;
+}
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
+ */
+static int bf548_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, &bf548_freq_table);
+}
+
+static int __init __bf548_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	/*Now ,only support one cpu */
+	policy->cur = bf548_getfreq(0);
+	cpufreq_frequency_table_get_attr(bf548_freq_table, policy->cpu);
+	return cpufreq_frequency_table_cpuinfo(policy, bf548_freq_table);
+}
+
+static struct freq_attr *bf548_freq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+static struct cpufreq_driver bf548_driver = {
+	.verify = bf548_verify_speed,
+	.target = bf548_target,
+	.get = bf548_getfreq,
+	.init = __bf548_cpu_init,
+	.name = "bf548",
+	.owner = THIS_MODULE,
+	.attr = bf548_freq_attr,
+};
+
+static int __init bf548_cpu_init(void)
+{
+	return cpufreq_register_driver(&bf548_driver);
+}
+
+static void __exit bf548_cpu_exit(void)
+{
+	cpufreq_unregister_driver(&bf548_driver);
+}
+
+MODULE_AUTHOR("Mickael Kang");
+MODULE_DESCRIPTION("cpufreq driver for BF548 CPU");
+MODULE_LICENSE("GPL");
+
+module_init(bf548_cpu_init);
+module_exit(bf548_cpu_exit);
diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
new file mode 100644
index 0000000..a818411
--- /dev/null
+++ b/arch/blackfin/mach-bf548/dma.c
@@ -0,0 +1,156 @@
+/*
+ * File:         arch/blackfin/mach-bf561/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+	(struct dma_register *) DMA0_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_NEXT_DESC_PTR,
+	(struct dma_register *) DMA3_NEXT_DESC_PTR,
+	(struct dma_register *) DMA4_NEXT_DESC_PTR,
+	(struct dma_register *) DMA5_NEXT_DESC_PTR,
+	(struct dma_register *) DMA6_NEXT_DESC_PTR,
+	(struct dma_register *) DMA7_NEXT_DESC_PTR,
+	(struct dma_register *) DMA8_NEXT_DESC_PTR,
+	(struct dma_register *) DMA9_NEXT_DESC_PTR,
+	(struct dma_register *) DMA10_NEXT_DESC_PTR,
+	(struct dma_register *) DMA11_NEXT_DESC_PTR,
+	(struct dma_register *) DMA12_NEXT_DESC_PTR,
+	(struct dma_register *) DMA13_NEXT_DESC_PTR,
+	(struct dma_register *) DMA14_NEXT_DESC_PTR,
+	(struct dma_register *) DMA15_NEXT_DESC_PTR,
+	(struct dma_register *) DMA16_NEXT_DESC_PTR,
+	(struct dma_register *) DMA17_NEXT_DESC_PTR,
+	(struct dma_register *) DMA18_NEXT_DESC_PTR,
+	(struct dma_register *) DMA19_NEXT_DESC_PTR,
+	(struct dma_register *) DMA20_NEXT_DESC_PTR,
+	(struct dma_register *) DMA21_NEXT_DESC_PTR,
+	(struct dma_register *) DMA22_NEXT_DESC_PTR,
+	(struct dma_register *) DMA23_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D2_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S2_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+	int ret_irq = -1;
+
+	switch (channel) {
+	case CH_SPORT0_RX:
+		ret_irq = IRQ_SPORT0_RX;
+		break;
+	case CH_SPORT0_TX:
+		ret_irq = IRQ_SPORT0_TX;
+		break;
+	case CH_SPORT1_RX:
+		ret_irq = IRQ_SPORT1_RX;
+		break;
+	case CH_SPORT1_TX:
+		ret_irq = IRQ_SPORT1_TX;
+	case CH_SPI0:
+		ret_irq = IRQ_SPI0;
+		break;
+	case CH_SPI1:
+		ret_irq = IRQ_SPI1;
+		break;
+	case CH_UART0_RX:
+		ret_irq = IRQ_UART_RX;
+		break;
+	case CH_UART0_TX:
+		ret_irq = IRQ_UART_TX;
+		break;
+	case CH_UART1_RX:
+		ret_irq = IRQ_UART_RX;
+		break;
+	case CH_UART1_TX:
+		ret_irq = IRQ_UART_TX;
+		break;
+	case CH_EPPI0:
+		ret_irq = IRQ_EPPI0;
+		break;
+	case CH_EPPI1:
+		ret_irq = IRQ_EPPI1;
+		break;
+	case CH_EPPI2:
+		ret_irq = IRQ_EPPI2;
+		break;
+	case CH_PIXC_IMAGE:
+		ret_irq = IRQ_PIXC_IN0;
+		break;
+	case CH_PIXC_OVERLAY:
+		ret_irq = IRQ_PIXC_IN1;
+		break;
+	case CH_PIXC_OUTPUT:
+		ret_irq = IRQ_PIXC_OUT;
+		break;
+	case CH_SPORT2_RX:
+		ret_irq = IRQ_SPORT2_RX;
+		break;
+	case CH_SPORT2_TX:
+		ret_irq = IRQ_SPORT2_TX;
+		break;
+	case CH_SPORT3_RX:
+		ret_irq = IRQ_SPORT3_RX;
+		break;
+	case CH_SPORT3_TX:
+		ret_irq = IRQ_SPORT3_TX;
+		break;
+	case CH_SDH:
+		ret_irq = IRQ_SDH;
+		break;
+	case CH_SPI2:
+		ret_irq = IRQ_SPI2;
+		break;
+	case CH_MEM_STREAM0_SRC:
+	case CH_MEM_STREAM0_DEST:
+		ret_irq = IRQ_MDMAS0;
+		break;
+	case CH_MEM_STREAM1_SRC:
+	case CH_MEM_STREAM1_DEST:
+		ret_irq = IRQ_MDMAS1;
+		break;
+	case CH_MEM_STREAM2_SRC:
+	case CH_MEM_STREAM2_DEST:
+		ret_irq = IRQ_MDMAS2;
+		break;
+	case CH_MEM_STREAM3_SRC:
+	case CH_MEM_STREAM3_DEST:
+		ret_irq = IRQ_MDMAS3;
+		break;
+	}
+	return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf548/gpio.c b/arch/blackfin/mach-bf548/gpio.c
new file mode 100644
index 0000000..0da5f00
--- /dev/null
+++ b/arch/blackfin/mach-bf548/gpio.c
@@ -0,0 +1,323 @@
+/*
+ * File:         arch/blackfin/mach-bf548/gpio.c
+ * Based on:
+ * Author:       Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description:  GPIO Abstraction Layer
+ *
+ * Modified:
+ *               Copyright 2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
+#include <linux/irq.h>
+
+static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+	(struct gpio_port_t *)PORTA_FER,
+	(struct gpio_port_t *)PORTB_FER,
+	(struct gpio_port_t *)PORTC_FER,
+	(struct gpio_port_t *)PORTD_FER,
+	(struct gpio_port_t *)PORTE_FER,
+	(struct gpio_port_t *)PORTF_FER,
+	(struct gpio_port_t *)PORTG_FER,
+	(struct gpio_port_t *)PORTH_FER,
+	(struct gpio_port_t *)PORTI_FER,
+	(struct gpio_port_t *)PORTJ_FER,
+};
+
+static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+inline int check_gpio(unsigned short gpio)
+{
+	if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
+	    || gpio == GPIO_PH14 || gpio == GPIO_PH15
+	    || gpio == GPIO_PJ14 || gpio == GPIO_PJ15
+	    || gpio > MAX_BLACKFIN_GPIOS)
+		return -EINVAL;
+	return 0;
+}
+
+inline void portmux_setup(unsigned short portno, unsigned short function)
+{
+	u32 pmux;
+
+	pmux = gpio_array[gpio_bank(portno)]->port_mux;
+
+	pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
+	pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
+
+	gpio_array[gpio_bank(portno)]->port_mux = pmux;
+
+}
+
+inline u16 get_portmux(unsigned short portno)
+{
+	u32 pmux;
+
+	pmux = gpio_array[gpio_bank(portno)]->port_mux;
+
+	return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
+
+}
+
+static void port_setup(unsigned short gpio, unsigned short usage)
+{
+	if (usage == GPIO_USAGE) {
+		if (gpio_array[gpio_bank(gpio)]->port_fer & gpio_bit(gpio))
+			printk(KERN_WARNING
+			       "bfin-gpio: Possible Conflict with Peripheral "
+			       "usage and GPIO %d detected!\n", gpio);
+		gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
+	} else
+		gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
+	SSYNC();
+}
+
+static int __init bfin_gpio_init(void)
+{
+	printk(KERN_INFO "Blackfin GPIO Controller\n");
+
+	return 0;
+}
+
+arch_initcall(bfin_gpio_init);
+
+int peripheral_request(unsigned short per, const char *label)
+{
+	unsigned long flags;
+	unsigned short ident = P_IDENT(per);
+
+	if (!(per & P_DEFINED))
+		return -ENODEV;
+
+	if (check_gpio(ident) < 0)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+		printk(KERN_ERR
+		       "%s: Peripheral %d is already reserved as GPIO!\n",
+		       __FUNCTION__, per);
+		dump_stack();
+		local_irq_restore(flags);
+		return -EBUSY;
+	}
+
+	if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
+
+		u16 funct = get_portmux(ident);
+
+		if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
+			printk(KERN_ERR
+			       "%s: Peripheral %d is already reserved!\n",
+			       __FUNCTION__, per);
+			dump_stack();
+			local_irq_restore(flags);
+			return -EBUSY;
+		}
+	}
+
+	reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
+
+	portmux_setup(ident, P_FUNCT2MUX(per));
+	port_setup(ident, PERIPHERAL_USAGE);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(peripheral_request);
+
+int peripheral_request_list(unsigned short per[], const char *label)
+{
+
+	u16 cnt;
+	int ret;
+
+	for (cnt = 0; per[cnt] != 0; cnt++) {
+		ret = peripheral_request(per[cnt], label);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(peripheral_request_list);
+
+void peripheral_free(unsigned short per)
+{
+	unsigned long flags;
+	unsigned short ident = P_IDENT(per);
+
+	if (!(per & P_DEFINED))
+		return;
+
+	if (check_gpio(ident) < 0)
+		return;
+
+	local_irq_save(flags);
+
+	if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
+		printk(KERN_ERR "bfin-gpio: Peripheral %d wasn't reserved!\n", per);
+		dump_stack();
+		local_irq_restore(flags);
+		return;
+	}
+
+	if (!(per & P_MAYSHARE)) {
+		port_setup(ident, GPIO_USAGE);
+	}
+
+	reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
+
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(peripheral_free);
+
+void peripheral_free_list(unsigned short per[])
+{
+	u16 cnt;
+
+	for (cnt = 0; per[cnt] != 0; cnt++) {
+		peripheral_free(per[cnt]);
+	}
+
+}
+EXPORT_SYMBOL(peripheral_free_list);
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin GPIO Driver
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: Blackfin GPIO Driver API
+*
+* CAUTION:
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+int gpio_request(unsigned short gpio, const char *label)
+{
+	unsigned long flags;
+
+	if (check_gpio(gpio) < 0)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+		printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio);
+		dump_stack();
+		local_irq_restore(flags);
+		return -EBUSY;
+	}
+
+	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+		printk(KERN_ERR
+		       "bfin-gpio: GPIO %d is already reserved as Peripheral!\n", gpio);
+		dump_stack();
+		local_irq_restore(flags);
+		return -EBUSY;
+	}
+
+	reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+
+	local_irq_restore(flags);
+
+	port_setup(gpio, GPIO_USAGE);
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned short gpio)
+{
+	unsigned long flags;
+
+	if (check_gpio(gpio) < 0)
+		return;
+
+	local_irq_save(flags);
+
+	if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+		printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
+		dump_stack();
+		local_irq_restore(flags);
+		return;
+	}
+
+	reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_free);
+
+void gpio_direction_input(unsigned short gpio)
+{
+	unsigned long flags;
+
+	BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+	local_irq_save(flags);
+	gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
+	gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+void gpio_direction_output(unsigned short gpio)
+{
+	unsigned long flags;
+
+	BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+	local_irq_save(flags);
+	gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
+	gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+void gpio_set_value(unsigned short gpio, unsigned short arg)
+{
+	if (arg)
+		gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);
+	else
+		gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);
+
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+unsigned short gpio_get_value(unsigned short gpio)
+{
+	return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));
+}
+EXPORT_SYMBOL(gpio_get_value);
diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S
new file mode 100644
index 0000000..06751ae
--- /dev/null
+++ b/arch/blackfin/mach-bf548/head.S
@@ -0,0 +1,512 @@
+/*
+ * File:         arch/blackfin/mach-bf548/head.S
+ * Based on:     arch/blackfin/mach-bf537/head.S
+ * Author:       Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
+ *
+ * Created:      1998
+ * Description:  Startup code for Blackfin BF548
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/trace.h>
+#if CONFIG_BFIN_KERNEL_CLOCK
+#include <asm/mach/mem_init.h>
+#endif
+
+.global __rambase
+.global __ramstart
+.global __ramend
+.extern ___bss_stop
+.extern ___bss_start
+.extern _bf53x_relocate_l1_mem
+
+#define INITIAL_STACK   0xFFB01000
+
+.text
+
+ENTRY(__start)
+ENTRY(__stext)
+	/* R0: argument of command line string, passed from uboot, save it */
+	R7 = R0;
+	/* Set the SYSCFG register */
+	R0 = 0x36;
+	SYSCFG = R0;   /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+	R0 = 0;
+
+	/* Clear Out All the data and pointer  Registers*/
+	R1 = R0;
+	R2 = R0;
+	R3 = R0;
+	R4 = R0;
+	R5 = R0;
+	R6 = R0;
+
+	P0 = R0;
+	P1 = R0;
+	P2 = R0;
+	P3 = R0;
+	P4 = R0;
+	P5 = R0;
+
+	LC0 = r0;
+	LC1 = r0;
+	L0 = r0;
+	L1 = r0;
+	L2 = r0;
+	L3 = r0;
+
+	/* Clear Out All the DAG Registers*/
+	B0 = r0;
+	B1 = r0;
+	B2 = r0;
+	B3 = r0;
+
+	I0 = r0;
+	I1 = r0;
+	I2 = r0;
+	I3 = r0;
+
+	M0 = r0;
+	M1 = r0;
+	M2 = r0;
+	M3 = r0;
+
+	trace_buffer_start(p0,r0);
+	P0 = R1;
+	R0 = R1;
+
+	/* Turn off the icache */
+	p0.l = (IMEM_CONTROL & 0xFFFF);
+	p0.h = (IMEM_CONTROL >> 16);
+	R1 = [p0];
+	R0 = ~ENICPLB;
+	R0 = R0 & R1;
+	[p0] = R0;
+	SSYNC;
+
+	/* Turn off the dcache */
+	p0.l = (DMEM_CONTROL & 0xFFFF);
+	p0.h = (DMEM_CONTROL >> 16);
+	R1 = [p0];
+	R0 = ~ENDCPLB;
+	R0 = R0 & R1;
+	[p0] = R0;
+	SSYNC;
+
+	/* Initialize stack pointer */
+	SP.L = LO(INITIAL_STACK);
+	SP.H = HI(INITIAL_STACK);
+	FP = SP;
+	USP = SP;
+
+	/* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
+	call _bf53x_relocate_l1_mem;
+#if CONFIG_BFIN_KERNEL_CLOCK
+	call _start_dma_code;
+#endif
+	/* Code for initializing Async memory banks */
+
+	p2.h = hi(EBIU_AMBCTL1);
+	p2.l = lo(EBIU_AMBCTL1);
+	r0.h = hi(AMBCTL1VAL);
+	r0.l = lo(AMBCTL1VAL);
+	[p2] = r0;
+	ssync;
+
+	p2.h = hi(EBIU_AMBCTL0);
+	p2.l = lo(EBIU_AMBCTL0);
+	r0.h = hi(AMBCTL0VAL);
+	r0.l = lo(AMBCTL0VAL);
+	[p2] = r0;
+	ssync;
+
+	p2.h = hi(EBIU_AMGCTL);
+	p2.l = lo(EBIU_AMGCTL);
+	r0 = AMGCTLVAL;
+	w[p2] = r0;
+	ssync;
+
+	/* This section keeps the processor in supervisor mode
+	 * during kernel boot.  Switches to user mode at end of boot.
+	 * See page 3-9 of Hardware Reference manual for documentation.
+	 */
+
+	/* EVT15 = _real_start */
+
+	p0.l = lo(EVT15);
+	p0.h = hi(EVT15);
+	p1.l = _real_start;
+	p1.h = _real_start;
+	[p0] = p1;
+	csync;
+
+	p0.l = lo(IMASK);
+	p0.h = hi(IMASK);
+	p1.l = IMASK_IVG15;
+	p1.h = 0x0;
+	[p0] = p1;
+	csync;
+
+	raise 15;
+	p0.l = .LWAIT_HERE;
+	p0.h = .LWAIT_HERE;
+	reti = p0;
+#if defined (ANOMALY_05000281)
+	nop;
+	nop;
+	nop;
+#endif
+	rti;
+
+.LWAIT_HERE:
+	jump .LWAIT_HERE;
+
+ENTRY(_real_start)
+	[ -- sp ] = reti;
+	p0.l = lo(WDOG_CTL);
+	p0.h = hi(WDOG_CTL);
+	r0 = 0xAD6(z);
+	w[p0] = r0;	/* watchdog off for now */
+	ssync;
+
+	/* Code update for BSS size == 0
+	 * Zero out the bss region.
+	 */
+
+	p1.l = ___bss_start;
+	p1.h = ___bss_start;
+	p2.l = ___bss_stop;
+	p2.h = ___bss_stop;
+	r0 = 0;
+	p2 -= p1;
+	lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+.L_clear_bss:
+	B[p1++] = r0;
+
+	/* In case there is a NULL pointer reference
+	 * Zero out region before stext
+	 */
+
+	p1.l = 0x0;
+	p1.h = 0x0;
+	r0.l = __stext;
+	r0.h = __stext;
+	r0 = r0 >> 1;
+	p2 = r0;
+	r0 = 0;
+	lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+.L_clear_zero:
+	W[p1++] = r0;
+
+	/* pass the uboot arguments to the global value command line */
+	R0 = R7;
+	call _cmdline_init;
+
+	p1.l = __rambase;
+	p1.h = __rambase;
+	r0.l = __sdata;
+	r0.h = __sdata;
+	[p1] = r0;
+
+	p1.l = __ramstart;
+	p1.h = __ramstart;
+	p3.l = ___bss_stop;
+	p3.h = ___bss_stop;
+
+	r1 = p3;
+	[p1] = r1;
+
+
+	/*
+	 *  load the current thread pointer and stack
+	 */
+	r1.l = _init_thread_union;
+	r1.h = _init_thread_union;
+
+	r2.l = 0x2000;
+	r2.h = 0x0000;
+	r1 = r1 + r2;
+	sp = r1;
+	usp = sp;
+	fp = sp;
+	call _start_kernel;
+.L_exit:
+	jump.s	.L_exit;
+
+.section .l1.text
+#if CONFIG_BFIN_KERNEL_CLOCK
+ENTRY(_start_dma_code)
+
+	/* Enable PHY CLK buffer output */
+	p0.h = hi(VR_CTL);
+	p0.l = lo(VR_CTL);
+	r0.l = w[p0];
+	bitset(r0, 14);
+	w[p0] = r0.l;
+	ssync;
+
+	p0.h = hi(SIC_IWR);
+	p0.l = lo(SIC_IWR);
+	r0.l = 0x1;
+	r0.h = 0x0;
+	[p0] = r0;
+	SSYNC;
+
+	/*
+	 *  Set PLL_CTL
+	 *   - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
+	 *   - [8]     = BYPASS    : BYPASS the PLL, run CLKIN into CCLK/SCLK
+	 *   - [7]     = output delay (add 200ps of delay to mem signals)
+	 *   - [6]     = input delay (add 200ps of input delay to mem signals)
+	 *   - [5]     = PDWN      : 1=All Clocks off
+	 *   - [3]     = STOPCK    : 1=Core Clock off
+	 *   - [1]     = PLL_OFF   : 1=Disable Power to PLL
+	 *   - [0]     = DF        : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
+	 *   all other bits set to zero
+	 */
+
+	p0.h = hi(PLL_LOCKCNT);
+	p0.l = lo(PLL_LOCKCNT);
+	r0 = 0x300(Z);
+	w[p0] = r0.l;
+	ssync;
+
+	P2.H = hi(EBIU_SDGCTL);
+	P2.L = lo(EBIU_SDGCTL);
+	R0 = [P2];
+	BITSET (R0, 24);
+	[P2] = R0;
+	SSYNC;
+
+	r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
+	r0 = r0 << 9;                    /* Shift it over,                  */
+	r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
+	r0 = r1 | r0;
+	r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
+	r1 = r1 << 8;                    /* Shift it over                   */
+	r0 = r1 | r0;                    /* add them all together           */
+
+	p0.h = hi(PLL_CTL);
+	p0.l = lo(PLL_CTL);              /* Load the address                */
+	cli r2;                          /* Disable interrupts              */
+	ssync;
+	w[p0] = r0.l;                    /* Set the value                   */
+	idle;                            /* Wait for the PLL to stablize    */
+	sti r2;                          /* Enable interrupts               */
+
+.Lcheck_again:
+	p0.h = hi(PLL_STAT);
+	p0.l = lo(PLL_STAT);
+	R0 = W[P0](Z);
+	CC = BITTST(R0,5);
+	if ! CC jump .Lcheck_again;
+
+	/* Configure SCLK & CCLK Dividers */
+	r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+	p0.h = hi(PLL_DIV);
+	p0.l = lo(PLL_DIV);
+	w[p0] = r0.l;
+	ssync;
+
+	p0.l = lo(EBIU_SDRRC);
+	p0.h = hi(EBIU_SDRRC);
+	r0 = mem_SDRRC;
+	w[p0] = r0.l;
+	ssync;
+
+	p0.l = (EBIU_SDBCTL & 0xFFFF);
+	p0.h = (EBIU_SDBCTL >> 16);     /* SDRAM Memory Bank Control Register */
+	r0 = mem_SDBCTL;
+	w[p0] = r0.l;
+	ssync;
+
+	P2.H = hi(EBIU_SDGCTL);
+	P2.L = lo(EBIU_SDGCTL);
+	R0 = [P2];
+	BITCLR (R0, 24);
+	p0.h = hi(EBIU_SDSTAT);
+	p0.l = lo(EBIU_SDSTAT);
+	r2.l = w[p0];
+	cc = bittst(r2,3);
+	if !cc jump .Lskip;
+	NOP;
+	BITSET (R0, 23);
+.Lskip:
+	[P2] = R0;
+	SSYNC;
+
+	R0.L = lo(mem_SDGCTL);
+	R0.H = hi(mem_SDGCTL);
+	R1 = [p2];
+	R1 = R1 | R0;
+	[P2] = R1;
+	SSYNC;
+
+	p0.h = hi(SIC_IWR);
+	p0.l = lo(SIC_IWR);
+	r0.l = lo(IWR_ENABLE_ALL);
+	r0.h = hi(IWR_ENABLE_ALL);
+	[p0] = r0;
+	SSYNC;
+
+	RTS;
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+ENTRY(_bfin_reset)
+	/* No more interrupts to be handled*/
+	CLI R6;
+	SSYNC;
+
+#if defined(CONFIG_MTD_M25P80)
+/*
+ * The following code fix the SPI flash reboot issue,
+ * /CS signal of the chip which is using PF10 return to GPIO mode
+ */
+	p0.h = hi(PORTF_FER);
+	p0.l = lo(PORTF_FER);
+	r0.l = 0x0000;
+	w[p0] = r0.l;
+	SSYNC;
+
+/* /CS return to high */
+	p0.h = hi(PORTFIO);
+	p0.l = lo(PORTFIO);
+	r0.l = 0xFFFF;
+	w[p0] = r0.l;
+	SSYNC;
+
+/* Delay some time, This is necessary */
+	r1.h = 0;
+	r1.l = 0x400;
+	p1   = r1;
+	lsetup (_delay_lab1,_delay_lab1_end ) lc1 = p1;
+_delay_lab1:
+	r0.h = 0;
+	r0.l = 0x8000;
+	p0   = r0;
+	lsetup (_delay_lab0,_delay_lab0_end ) lc0 = p0;
+_delay_lab0:
+	nop;
+_delay_lab0_end:
+	nop;
+_delay_lab1_end:
+	nop;
+#endif
+
+	/* Clear the bits 13-15 in SWRST if they werent cleared */
+	p0.h = hi(SWRST);
+	p0.l = lo(SWRST);
+	csync;
+	r0.l = w[p0];
+
+	/* Clear the IMASK register */
+	p0.h = hi(IMASK);
+	p0.l = lo(IMASK);
+	r0 = 0x0;
+	[p0] = r0;
+
+	/* Clear the ILAT register */
+	p0.h = hi(ILAT);
+	p0.l = lo(ILAT);
+	r0 = [p0];
+	[p0] = r0;
+	SSYNC;
+
+	/* Disable the WDOG TIMER */
+	p0.h = hi(WDOG_CTL);
+	p0.l = lo(WDOG_CTL);
+	r0.l = 0xAD6;
+	w[p0] = r0.l;
+	SSYNC;
+
+	/* Clear the sticky bit incase it is already set */
+	p0.h = hi(WDOG_CTL);
+	p0.l = lo(WDOG_CTL);
+	r0.l = 0x8AD6;
+	w[p0] = r0.l;
+	SSYNC;
+
+	/* Program the count value */
+	R0.l = 0x100;
+	R0.h = 0x0;
+	P0.h = hi(WDOG_CNT);
+	P0.l = lo(WDOG_CNT);
+	[P0] = R0;
+	SSYNC;
+
+	/* Program WDOG_STAT if necessary */
+	P0.h = hi(WDOG_CTL);
+	P0.l = lo(WDOG_CTL);
+	R0 = W[P0](Z);
+	CC = BITTST(R0,1);
+	if !CC JUMP .LWRITESTAT;
+	CC = BITTST(R0,2);
+	if !CC JUMP .LWRITESTAT;
+	JUMP .LSKIP_WRITE;
+
+.LWRITESTAT:
+	/* When watch dog timer is enabled,
+	 * a write to STAT will load the contents of CNT to STAT
+	 */
+	R0 = 0x0000(z);
+	P0.h = hi(WDOG_STAT);
+	P0.l = lo(WDOG_STAT)
+	[P0] = R0;
+	SSYNC;
+
+.LSKIP_WRITE:
+	/* Enable the reset event */
+	P0.h = hi(WDOG_CTL);
+	P0.l = lo(WDOG_CTL);
+	R0 = W[P0](Z);
+	BITCLR(R0,1);
+	BITCLR(R0,2);
+	W[P0] = R0.L;
+	SSYNC;
+	NOP;
+
+	/* Enable the wdog counter */
+	R0 = W[P0](Z);
+	BITCLR(R0,4);
+	W[P0] = R0.L;
+	SSYNC;
+
+	IDLE;
+
+	RTS;
+
+.data
+
+/*
+ * Set up the usable of RAM stuff. Size of RAM is determined then
+ * an initial stack set up at the end.
+ */
+
+.align 4
+__rambase:
+.long   0
+__ramstart:
+.long   0
+__ramend:
+.long   0
diff --git a/arch/blackfin/mach-bf548/ints-priority.c b/arch/blackfin/mach-bf548/ints-priority.c
new file mode 100644
index 0000000..cb0ebac
--- /dev/null
+++ b/arch/blackfin/mach-bf548/ints-priority.c
@@ -0,0 +1,137 @@
+/*
+ * File:         arch/blackfin/mach-bf537/ints-priority.c
+ * Based on:     arch/blackfin/mach-bf533/ints-priority.c
+ * Author:       Michael Hennerich
+ *
+ * Created:
+ * Description:  Set up the interupt priorities
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <asm/blackfin.h>
+
+void program_IAR(void)
+{
+	/* Program the IAR0 Register with the configured priority */
+	bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+			    ((CONFIG_IRQ_DMAC0_ERR - 7) << IRQ_DMAC0_ERR_POS) |
+			    ((CONFIG_IRQ_EPPI0_ERR - 7) << IRQ_EPPI0_ERR_POS) |
+			    ((CONFIG_IRQ_SPORT0_ERR - 7) << IRQ_SPORT0_ERR_POS) |
+			    ((CONFIG_IRQ_SPORT1_ERR - 7) << IRQ_SPORT1_ERR_POS) |
+			    ((CONFIG_IRQ_SPI0_ERR - 7) << IRQ_SPI0_ERR_POS) |
+			    ((CONFIG_IRQ_UART0_ERR - 7) << IRQ_UART0_ERR_POS) |
+			    ((CONFIG_IRQ_RTC - 7) << IRQ_RTC_POS));
+
+	bfin_write_SIC_IAR1(((CONFIG_IRQ_EPPI0 - 7) << IRQ_EPPI0_POS) |
+			    ((CONFIG_IRQ_SPORT0_RX - 7) << IRQ_SPORT0_RX_POS) |
+			    ((CONFIG_IRQ_SPORT0_TX - 7) << IRQ_SPORT0_TX_POS) |
+			    ((CONFIG_IRQ_SPORT1_RX - 7) << IRQ_SPORT1_RX_POS) |
+			    ((CONFIG_IRQ_SPORT1_TX - 7) << IRQ_SPORT1_TX_POS) |
+			    ((CONFIG_IRQ_SPI0 - 7) << IRQ_SPI0_POS) |
+			    ((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) |
+			    ((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS));
+
+	bfin_write_SIC_IAR2(((CONFIG_IRQ_TIMER8 - 7) << IRQ_TIMER8_POS) |
+			    ((CONFIG_IRQ_TIMER9 - 7) << IRQ_TIMER9_POS) |
+			    ((CONFIG_IRQ_PINT0 - 7) << IRQ_PINT0_POS) |
+			    ((CONFIG_IRQ_PINT1 - 7) << IRQ_PINT1_POS) |
+			    ((CONFIG_IRQ_MDMAS0 - 7) << IRQ_MDMAS0_POS) |
+			    ((CONFIG_IRQ_MDMAS1 - 7) << IRQ_MDMAS1_POS) |
+			    ((CONFIG_IRQ_WATCHDOG - 7) << IRQ_WATCHDOG_POS));
+
+	bfin_write_SIC_IAR3(((CONFIG_IRQ_DMAC1_ERR - 7) << IRQ_DMAC1_ERR_POS) |
+			    ((CONFIG_IRQ_SPORT2_ERR - 7) << IRQ_SPORT2_ERR_POS) |
+			    ((CONFIG_IRQ_SPORT3_ERR - 7) << IRQ_SPORT3_ERR_POS) |
+			    ((CONFIG_IRQ_MXVR_DATA - 7) << IRQ_MXVR_DATA_POS) |
+			    ((CONFIG_IRQ_SPI1_ERR - 7) << IRQ_SPI1_ERR_POS) |
+			    ((CONFIG_IRQ_SPI2_ERR - 7) << IRQ_SPI2_ERR_POS) |
+			    ((CONFIG_IRQ_UART1_ERR - 7) << IRQ_UART1_ERR_POS) |
+			    ((CONFIG_IRQ_UART2_ERR - 7) << IRQ_UART2_ERR_POS));
+
+	bfin_write_SIC_IAR4(((CONFIG_IRQ_CAN0_ERR - 7) << IRQ_CAN0_ERR_POS) |
+			    ((CONFIG_IRQ_SPORT2_RX - 7) << IRQ_SPORT2_RX_POS) |
+			    ((CONFIG_IRQ_SPORT2_TX - 7) << IRQ_SPORT2_TX_POS) |
+			    ((CONFIG_IRQ_SPORT3_RX - 7) << IRQ_SPORT3_RX_POS) |
+			    ((CONFIG_IRQ_SPORT3_TX - 7) << IRQ_SPORT3_TX_POS) |
+			    ((CONFIG_IRQ_EPPI1 - 7) << IRQ_EPPI1_POS) |
+			    ((CONFIG_IRQ_EPPI2 - 7) << IRQ_EPPI2_POS) |
+			    ((CONFIG_IRQ_SPI1 - 7) << IRQ_SPI1_POS));
+
+	bfin_write_SIC_IAR5(((CONFIG_IRQ_SPI2 - 7) << IRQ_SPI2_POS) |
+			    ((CONFIG_IRQ_UART1_RX - 7) << IRQ_UART1_RX_POS) |
+			    ((CONFIG_IRQ_UART1_TX - 7) << IRQ_UART1_TX_POS) |
+			    ((CONFIG_IRQ_ATAPI_RX - 7) << IRQ_ATAPI_RX_POS) |
+			    ((CONFIG_IRQ_ATAPI_TX - 7) << IRQ_ATAPI_TX_POS) |
+			    ((CONFIG_IRQ_TWI0 - 7) << IRQ_TWI0_POS) |
+			    ((CONFIG_IRQ_TWI1 - 7) << IRQ_TWI1_POS) |
+			    ((CONFIG_IRQ_CAN0_RX - 7) << IRQ_CAN0_RX_POS));
+
+	bfin_write_SIC_IAR6(((CONFIG_IRQ_CAN0_TX - 7) << IRQ_CAN0_TX_POS) |
+			    ((CONFIG_IRQ_MDMAS2 - 7) << IRQ_MDMAS2_POS) |
+			    ((CONFIG_IRQ_MDMAS3 - 7) << IRQ_MDMAS3_POS) |
+			    ((CONFIG_IRQ_MXVR_ERR - 7) << IRQ_MXVR_ERR_POS) |
+			    ((CONFIG_IRQ_MXVR_MSG - 7) << IRQ_MXVR_MSG_POS) |
+			    ((CONFIG_IRQ_MXVR_PKT - 7) << IRQ_MXVR_PKT_POS) |
+			    ((CONFIG_IRQ_EPPI1_ERR - 7) << IRQ_EPPI1_ERR_POS) |
+			    ((CONFIG_IRQ_EPPI2_ERR - 7) << IRQ_EPPI2_ERR_POS));
+
+	bfin_write_SIC_IAR7(((CONFIG_IRQ_UART3_ERR - 7) << IRQ_UART3_ERR_POS) |
+			    ((CONFIG_IRQ_HOST_ERR - 7) << IRQ_HOST_ERR_POS) |
+			    ((CONFIG_IRQ_PIXC_ERR - 7) << IRQ_PIXC_ERR_POS) |
+			    ((CONFIG_IRQ_NFC_ERR - 7) << IRQ_NFC_ERR_POS) |
+			    ((CONFIG_IRQ_ATAPI_ERR - 7) << IRQ_ATAPI_ERR_POS) |
+			    ((CONFIG_IRQ_CAN1_ERR - 7) << IRQ_CAN1_ERR_POS) |
+			    ((CONFIG_IRQ_HS_DMA_ERR - 7) << IRQ_HS_DMA_ERR_POS));
+
+	bfin_write_SIC_IAR8(((CONFIG_IRQ_PIXC_IN0 - 7) << IRQ_PIXC_IN1_POS) |
+			    ((CONFIG_IRQ_PIXC_IN1 - 7) << IRQ_PIXC_IN1_POS) |
+			    ((CONFIG_IRQ_PIXC_OUT - 7) << IRQ_PIXC_OUT_POS) |
+			    ((CONFIG_IRQ_SDH - 7) << IRQ_SDH_POS) |
+			    ((CONFIG_IRQ_CNT - 7) << IRQ_CNT_POS) |
+			    ((CONFIG_IRQ_KEY - 7) << IRQ_KEY_POS) |
+			    ((CONFIG_IRQ_CAN1_RX - 7) << IRQ_CAN1_RX_POS) |
+			    ((CONFIG_IRQ_CAN1_TX - 7) << IRQ_CAN1_TX_POS));
+
+	bfin_write_SIC_IAR9(((CONFIG_IRQ_SDH_MASK0 - 7) << IRQ_SDH_MASK0_POS) |
+			    ((CONFIG_IRQ_SDH_MASK1 - 7) << IRQ_SDH_MASK1_POS) |
+			    ((CONFIG_IRQ_USB_INT0 - 7) << IRQ_USB_INT0_POS) |
+			    ((CONFIG_IRQ_USB_INT1 - 7) << IRQ_USB_INT1_POS) |
+			    ((CONFIG_IRQ_USB_INT2 - 7) << IRQ_USB_INT2_POS) |
+			    ((CONFIG_IRQ_USB_DMA - 7) << IRQ_USB_DMA_POS) |
+			    ((CONFIG_IRQ_OTPSEC - 7) << IRQ_OTPSEC_POS));
+
+	bfin_write_SIC_IAR10(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+			     ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS));
+
+	bfin_write_SIC_IAR11(((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+			     ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+			     ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS) |
+			     ((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+			     ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+			     ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |
+			     ((CONFIG_IRQ_PINT2 - 7) << IRQ_PINT2_POS) |
+			     ((CONFIG_IRQ_PINT3 - 7) << IRQ_PINT3_POS));
+
+	SSYNC();
+}
diff --git a/arch/blackfin/mach-bf561/Makefile b/arch/blackfin/mach-bf561/Makefile
index 57f475a..f39235a 100644
--- a/arch/blackfin/mach-bf561/Makefile
+++ b/arch/blackfin/mach-bf561/Makefile
@@ -4,6 +4,6 @@
 
 extra-y := head.o
 
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
 
 obj-$(CONFIG_BF561_COREB) += coreb.o
diff --git a/arch/blackfin/mach-bf561/boards/Makefile b/arch/blackfin/mach-bf561/boards/Makefile
index 886edc7..495a1cf 100644
--- a/arch/blackfin/mach-bf561/boards/Makefile
+++ b/arch/blackfin/mach-bf561/boards/Makefile
@@ -3,5 +3,6 @@
 #
 
 obj-$(CONFIG_GENERIC_BOARD)            += generic_board.o
-obj-$(CONFIG_BFIN561_EZKIT)            += ezkit.o
 obj-$(CONFIG_BFIN561_BLUETECHNIX_CM)   += cm_bf561.o
+obj-$(CONFIG_BFIN561_EZKIT)            += ezkit.o
+obj-$(CONFIG_BFIN561_TEPLA)            += tepla.o
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 6824e95..5b2b544 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -1,7 +1,7 @@
 /*
  * File:         arch/blackfin/mach-bf533/boards/cm_bf561.c
  * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au> Copright 2005
+ * Author:       Aidan Williams <aidan@nicta.com.au> Copyright 2005
  *
  * Created:      2006
  * Description:  Board description file
@@ -34,7 +34,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -43,7 +43,7 @@
 char *bfin_board_name = "Bluetechnix CM BF561";
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
-/* all SPI perpherals info goes here */
+/* all SPI peripherals info goes here */
 
 #if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
 static struct mtd_partition bfin_spi_flash_partitions[] = {
@@ -52,11 +52,11 @@
 		.size = 0x00020000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
-	},{
+	}, {
 		.name = "kernel",
 		.size = 0xe0000,
 		.offset = 0x20000
-	},{
+	}, {
 		.name = "file system",
 		.size = 0x700000,
 		.offset = 0x00100000,
@@ -186,7 +186,7 @@
 		.start = 0x28000300,
 		.end = 0x28000300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF0,
 		.end = IRQ_PF0,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -206,11 +206,11 @@
 		.start = 0x24008000,
 		.end = 0x24008000,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = 0x24008004,
 		.end = 0x24008004,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PF47,
 		.end = IRQ_PF47,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -241,25 +241,25 @@
 
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
-        {
-                .start = 0xFFC00400,
-                .end = 0xFFC004FF,
-                .flags = IORESOURCE_MEM,
-        },
+	{
+		.start = 0xFFC00400,
+		.end = 0xFFC004FF,
+		.flags = IORESOURCE_MEM,
+	},
 };
 
 static struct platform_device bfin_uart_device = {
-        .name = "bfin-uart",
-        .id = 1,
-        .num_resources = ARRAY_SIZE(bfin_uart_resources),
-        .resource = bfin_uart_resources,
+	.name = "bfin-uart",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_uart_resources),
+	.resource = bfin_uart_resources,
 };
 #endif
 
 static struct platform_device *cm_bf561_devices[] __initdata = {
 
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
-        &bfin_uart_device,
+	&bfin_uart_device,
 #endif
 
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 14eb4f9..724191d 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -30,7 +30,8 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <asm/bfin5xx_spi.h>
 
 /*
@@ -38,6 +39,53 @@
  */
 char *bfin_board_name = "ADDS-BF561-EZKIT";
 
+#define ISP1761_BASE       0x2C0F0000
+#define ISP1761_IRQ        IRQ_PF10
+
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+static struct resource bfin_isp1761_resources[] = {
+	{
+		.name	= "isp1761-regs",
+		.start  = ISP1761_BASE + 0x00000000,
+		.end    = ISP1761_BASE + 0x000fffff,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = ISP1761_IRQ,
+		.end    = ISP1761_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_isp1761_device = {
+	.name           = "isp1761",
+	.id             = 0,
+	.num_resources  = ARRAY_SIZE(bfin_isp1761_resources),
+	.resource       = bfin_isp1761_resources,
+};
+
+static struct platform_device *bfin_isp1761_devices[] = {
+	&bfin_isp1761_device,
+};
+
+int __init bfin_isp1761_init(void)
+{
+	unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+
+	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+	set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+
+	return platform_add_devices(bfin_isp1761_devices, num_devices);
+}
+
+void __exit bfin_isp1761_exit(void)
+{
+	platform_device_unregister(&bfin_isp1761_device);
+}
+
+arch_initcall(bfin_isp1761_init);
+#endif
+
 /*
  *  USB-LAN EzExtender board
  *  Driver needs to know address, irq and flag pin.
@@ -49,7 +97,7 @@
 		.start = 0x2C010300,
 		.end = 0x2C010300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 
 		.start = IRQ_PF9,
 		.end = IRQ_PF9,
@@ -67,18 +115,18 @@
 
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
-        {
-                .start = 0xFFC00400,
-                .end = 0xFFC004FF,
-                .flags = IORESOURCE_MEM,
-        },
+	{
+		.start = 0xFFC00400,
+		.end = 0xFFC004FF,
+		.flags = IORESOURCE_MEM,
+	},
 };
 
 static struct platform_device bfin_uart_device = {
-        .name = "bfin-uart",
-        .id = 1,
-        .num_resources = ARRAY_SIZE(bfin_uart_resources),
-        .resource = bfin_uart_resources,
+	.name = "bfin-uart",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_uart_resources),
+	.resource = bfin_uart_resources,
 };
 #endif
 
@@ -127,7 +175,7 @@
 	&spi_bfin_master_device,
 #endif
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
-        &bfin_uart_device,
+	&bfin_uart_device,
 #endif
 };
 
@@ -135,13 +183,18 @@
 {
 	int ret;
 
-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
-	ret = platform_add_devices(ezkit_devices,
-		 ARRAY_SIZE(ezkit_devices));
+	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+
+	ret = platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
 	if (ret < 0)
 		return ret;
-	return spi_register_board_info(bfin_spi_board_info,
-				ARRAY_SIZE(bfin_spi_board_info));
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+	bfin_write_FIO0_DIR(bfin_read_FIO0_DIR() | (1 << 12));
+	SSYNC();
+#endif
+
+	return spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 }
 
 arch_initcall(ezkit_init);
diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c
index 585ecdd..4dfea5d 100644
--- a/arch/blackfin/mach-bf561/boards/generic_board.c
+++ b/arch/blackfin/mach-bf561/boards/generic_board.c
@@ -30,7 +30,7 @@
 
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 
 char *bfin_board_name = "UNKNOWN BOARD";
 
@@ -43,11 +43,11 @@
 		.start = 0x2C010300,
 		.end = 0x2C010300 + 16,
 		.flags = IORESOURCE_MEM,
-	},{
+	}, {
 		.start = IRQ_PROG_INTB,
 		.end = IRQ_PROG_INTB,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},{
+	}, {
 		/*
 		 *  denotes the flag pin and is used directly if
 		 *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
diff --git a/arch/blackfin/mach-bf561/boards/tepla.c b/arch/blackfin/mach-bf561/boards/tepla.c
new file mode 100644
index 0000000..c442eb2
--- /dev/null
+++ b/arch/blackfin/mach-bf561/boards/tepla.c
@@ -0,0 +1,61 @@
+/*
+ *  File: arch/blackfin/mach-bf561/tepla.c
+ *
+ *  Copyright 2004-2007 Analog Devices Inc.
+ *  Only SMSC91C1111 was registered, may do more later.
+ *
+ *  Copyright 2005 National ICT Australia (NICTA), Aidan Williams <aidan@nicta.com.au>
+ *  Thanks to Jamey Hicks.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+char *bfin_board_name = "Tepla-BF561";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+static struct resource smc91x_resources[] = {
+	{
+		.start	= 0x2C000300,
+		.end	= 0x2C000320,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_PROG_INTB,
+		.end	= IRQ_PROG_INTB,
+		.flags	= IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHLEVEL,
+	}, {
+		/*
+		 *  denotes the flag pin and is used directly if
+		 *  CONFIG_IRQCHIP_DEMUX_GPIO is defined.
+		 */
+		.start	= IRQ_PF7,
+		.end	= IRQ_PF7,
+		.flags	= IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHLEVEL,
+	},
+};
+
+static struct platform_device smc91x_device = {
+	.name          = "smc91x",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(smc91x_resources),
+	.resource      = smc91x_resources,
+};
+
+static struct platform_device *tepla_devices[] __initdata = {
+	&smc91x_device,
+};
+
+static int __init tepla_init(void)
+{
+	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+	return platform_add_devices(tepla_devices, ARRAY_SIZE(tepla_devices));
+}
+
+arch_initcall(tepla_init);
diff --git a/arch/blackfin/mach-bf561/coreb.c b/arch/blackfin/mach-bf561/coreb.c
index b28582f..5d1d21b 100644
--- a/arch/blackfin/mach-bf561/coreb.c
+++ b/arch/blackfin/mach-bf561/coreb.c
@@ -32,8 +32,8 @@
 #include <linux/device.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/uaccess.h>
 #include <asm/dma.h>
-#include <asm/uaccess.h>
 
 #define MODULE_VER		"v0.1"
 
@@ -202,7 +202,7 @@
 	spin_unlock_irq(&coreb_lock);
 	return 0;
 
-      out_busy:
+ out_busy:
 	spin_unlock_irq(&coreb_lock);
 	return -EBUSY;
 }
@@ -365,19 +365,19 @@
 	printk(KERN_INFO "BF561 Core B driver %s initialized.\n", MODULE_VER);
 	return 0;
 
-      release_dma_src:
+ release_dma_src:
 	free_dma(CH_MEM_STREAM2_SRC);
-      release_dma_dest:
+ release_dma_dest:
 	free_dma(CH_MEM_STREAM2_DEST);
-      release_data_a_sram:
+ release_data_a_sram:
 	release_mem_region(0xff400000, 0x8000);
-      release_data_b_sram:
+ release_data_b_sram:
 	release_mem_region(0xff500000, 0x8000);
-      release_instruction_b_sram:
+ release_instruction_b_sram:
 	release_mem_region(0xff610000, 0x4000);
-      release_instruction_a_sram:
+ release_instruction_a_sram:
 	release_mem_region(0xff600000, 0x4000);
-      exit:
+ exit:
 	return -ENOMEM;
 }
 
diff --git a/arch/blackfin/mach-bf561/dma.c b/arch/blackfin/mach-bf561/dma.c
new file mode 100644
index 0000000..89c65bb
--- /dev/null
+++ b/arch/blackfin/mach-bf561/dma.c
@@ -0,0 +1,131 @@
+/*
+ * File:         arch/blackfin/mach-bf561/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+	(struct dma_register *) DMA1_0_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_1_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_2_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_3_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_4_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_5_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_6_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_7_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_8_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_9_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_10_NEXT_DESC_PTR,
+	(struct dma_register *) DMA1_11_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_0_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_1_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_2_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_3_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_4_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_5_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_6_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_7_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_8_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_9_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_10_NEXT_DESC_PTR,
+	(struct dma_register *) DMA2_11_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
+	(struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
+	(struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
+	(struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
+	(struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+	int ret_irq = -1;
+
+	switch (channel) {
+	case CH_PPI0:
+		ret_irq = IRQ_PPI0;
+		break;
+	case CH_PPI1:
+		ret_irq = IRQ_PPI1;
+		break;
+	case CH_SPORT0_RX:
+		ret_irq = IRQ_SPORT0_RX;
+		break;
+	case CH_SPORT0_TX:
+		ret_irq = IRQ_SPORT0_TX;
+		break;
+	case CH_SPORT1_RX:
+		ret_irq = IRQ_SPORT1_RX;
+		break;
+	case CH_SPORT1_TX:
+		ret_irq = IRQ_SPORT1_TX;
+		break;
+	case CH_SPI:
+		ret_irq = IRQ_SPI;
+		break;
+	case CH_UART_RX:
+		ret_irq = IRQ_UART_RX;
+		break;
+	case CH_UART_TX:
+		ret_irq = IRQ_UART_TX;
+		break;
+
+	case CH_MEM_STREAM0_SRC:
+	case CH_MEM_STREAM0_DEST:
+		ret_irq = IRQ_MEM_DMA0;
+		break;
+	case CH_MEM_STREAM1_SRC:
+	case CH_MEM_STREAM1_DEST:
+		ret_irq = IRQ_MEM_DMA1;
+		break;
+	case CH_MEM_STREAM2_SRC:
+	case CH_MEM_STREAM2_DEST:
+		ret_irq = IRQ_MEM_DMA2;
+		break;
+	case CH_MEM_STREAM3_SRC:
+	case CH_MEM_STREAM3_DEST:
+		ret_irq = IRQ_MEM_DMA3;
+		break;
+
+	case CH_IMEM_STREAM0_SRC:
+	case CH_IMEM_STREAM0_DEST:
+		ret_irq = IRQ_IMEM_DMA0;
+		break;
+	case CH_IMEM_STREAM1_SRC:
+	case CH_IMEM_STREAM1_DEST:
+		ret_irq = IRQ_IMEM_DMA1;
+		break;
+	}
+	return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf561/head.S b/arch/blackfin/mach-bf561/head.S
index 7bca478..2f08bcb 100644
--- a/arch/blackfin/mach-bf561/head.S
+++ b/arch/blackfin/mach-bf561/head.S
@@ -28,7 +28,10 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/init.h>
 #include <asm/blackfin.h>
+#include <asm/trace.h>
+
 #if CONFIG_BFIN_KERNEL_CLOCK
 #include <asm/mach/mem_init.h>
 #endif
@@ -42,18 +45,19 @@
 
 #define INITIAL_STACK	0xFFB01000
 
-.text
+__INIT
 
 ENTRY(__start)
-ENTRY(__stext)
-	/*  R0: argument of command line string, passed from uboot, save it */
+	/* R0: argument of command line string, passed from uboot, save it */
 	R7 = R0;
-	/* Set the SYSCFG register */
+	/* Set the SYSCFG register:
+	 * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit)
+	 */
 	R0 = 0x36;
-	SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+	SYSCFG = R0;
 	R0 = 0;
 
-	/*Clear Out All the data and pointer  Registers*/
+	/* Clear Out All the data and pointer Registers */
 	R1 = R0;
 	R2 = R0;
 	R3 = R0;
@@ -75,7 +79,7 @@
 	L2 = r0;
 	L3 = r0;
 
-	/* Clear Out All the DAG Registers*/
+	/* Clear Out All the DAG Registers */
 	B0 = r0;
 	B1 = r0;
 	B2 = r0;
@@ -91,6 +95,10 @@
 	M2 = r0;
 	M3 = r0;
 
+	trace_buffer_start(p0,r0);
+	P0 = R1;
+	R0 = R1;
+
 	/* Turn off the icache */
 	p0.l = (IMEM_CONTROL & 0xFFFF);
 	p0.h = (IMEM_CONTROL >> 16);
@@ -127,7 +135,8 @@
 	STI R2;
 #endif
 
-	/* Initialise UART*/
+	/* Initialise UART - when booting from u-boot, the UART is not disabled
+	 * so if we dont initalize here, our serial console gets hosed */
 	p0.h = hi(UART_LCR);
 	p0.l = lo(UART_LCR);
 	r0 = 0x0(Z);
@@ -218,6 +227,7 @@
 
 .LWAIT_HERE:
 	jump .LWAIT_HERE;
+ENDPROC(__start)
 
 ENTRY(_real_start)
 	[ -- sp ] = reti;
@@ -237,7 +247,7 @@
 	p2.h = ___bss_stop;
 	r0 = 0;
 	p2 -= p1;
-	lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+	lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
 .L_clear_bss:
 	B[p1++] = r0;
 
@@ -252,11 +262,11 @@
 	r0 = r0 >> 1;
 	p2 = r0;
 	r0 = 0;
-	lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+	lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
 .L_clear_zero:
 	W[p1++] = r0;
 
-/* pass the uboot arguments to the global value command line */
+	/* pass the uboot arguments to the global value command line */
 	R0 = R7;
 	call _cmdline_init;
 
@@ -286,9 +296,10 @@
 	sp = r1;
 	usp = sp;
 	fp = sp;
-	call _start_kernel;
-.L_exit:
-	jump.s	.L_exit;
+	jump.l _start_kernel;
+ENDPROC(_real_start)
+
+__FINIT
 
 .section .l1.text
 #if CONFIG_BFIN_KERNEL_CLOCK
@@ -349,7 +360,7 @@
 	if ! CC jump .Lcheck_again;
 
 	/* Configure SCLK & CCLK Dividers */
-	   	r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+	r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
 	p0.h = hi(PLL_DIV);
 	p0.l = lo(PLL_DIV);
 	w[p0] = r0.l;
@@ -390,6 +401,7 @@
 	SSYNC;
 
 	RTS;
+ENDPROC(_start_dma_code)
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
 
 ENTRY(_bfin_reset)
@@ -414,12 +426,6 @@
 	w[p0] = r0.l;
 #endif
 
-	/* Clear the bits 13-15 in SWRST if they werent cleared */
-	p0.h = hi(SICA_SWRST);
-	p0.l = lo(SICA_SWRST);
-	csync;
-	r0.l = w[p0];
-
 	/* Clear the IMASK register */
 	p0.h = hi(IMASK);
 	p0.l = lo(IMASK);
@@ -433,68 +439,30 @@
 	[p0] = r0;
 	SSYNC;
 
-	/* Disable the WDOG TIMER */
-	p0.h = hi(WDOGA_CTL);
-	p0.l = lo(WDOGA_CTL);
-	r0.l = 0xAD6;
-	w[p0] = r0.l;
+	/* make sure SYSCR is set to use BMODE */
+	P0.h = hi(SICA_SYSCR);
+	P0.l = lo(SICA_SYSCR);
+	R0.l = 0x20;
+	W[P0] = R0.l;
 	SSYNC;
 
-	/* Clear the sticky bit incase it is already set */
-	p0.h = hi(WDOGA_CTL);
-	p0.l = lo(WDOGA_CTL);
-	r0.l = 0x8AD6;
-	w[p0] = r0.l;
+	/* issue a system soft reset */
+	P1.h = hi(SICA_SWRST);
+	P1.l = lo(SICA_SWRST);
+	R1.l = 0x0007;
+	W[P1] = R1;
 	SSYNC;
 
-	/* Program the count value */
-	R0.l = 0x100;
-	R0.h = 0x0;
-	P0.h = hi(WDOGA_CNT);
-	P0.l = lo(WDOGA_CNT);
-	[P0] = R0;
+	/* clear system soft reset */
+	R0.l = 0x0000;
+	W[P0] = R0;
 	SSYNC;
 
-	/* Program WDOG_STAT if necessary */
-	P0.h = hi(WDOGA_CTL);
-	P0.l = lo(WDOGA_CTL);
-	R0 = W[P0](Z);
-	CC = BITTST(R0,1);
-	if !CC JUMP .LWRITESTAT;
-	CC = BITTST(R0,2);
-	if !CC JUMP .LWRITESTAT;
-	JUMP .LSKIP_WRITE;
-
-.LWRITESTAT:
-	/* When watch dog timer is enabled,
-	 * a write to STAT will load the contents of CNT to STAT
-	 */
-	R0 = 0x0000(z);
-	P0.h = hi(WDOGA_STAT);
-	P0.l = lo(WDOGA_STAT)
-	[P0] = R0;
-	SSYNC;
-
-.LSKIP_WRITE:
-	/* Enable the reset event */
-	P0.h = hi(WDOGA_CTL);
-	P0.l = lo(WDOGA_CTL);
-	R0 = W[P0](Z);
-	BITCLR(R0,1);
-	BITCLR(R0,2);
-	W[P0] = R0.L;
-	SSYNC;
-	NOP;
-
-	/* Enable the wdog counter */
-	R0 = W[P0](Z);
-	BITCLR(R0,4);
-	W[P0] = R0.L;
-	SSYNC;
-
-	IDLE;
+	/* issue core reset */
+	raise 1;
 
 	RTS;
+ENDPROC(_bfin_reset)
 
 .data
 
diff --git a/arch/blackfin/mach-bf561/ints-priority.c b/arch/blackfin/mach-bf561/ints-priority.c
index 89c52ff..09b541b 100644
--- a/arch/blackfin/mach-bf561/ints-priority.c
+++ b/arch/blackfin/mach-bf561/ints-priority.c
@@ -4,7 +4,7 @@
  * Author:       Michael Hennerich
  *
  * Created:
- * Description:  Set up the interupt priorities
+ * Description:  Set up the interrupt priorities
  *
  * Modified:
  *               Copyright 2004-2006 Analog Devices Inc.
@@ -28,8 +28,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
 
 void program_IAR(void)
 {
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
index d3a4907..0279ede 100644
--- a/arch/blackfin/mach-common/Makefile
+++ b/arch/blackfin/mach-common/Makefile
@@ -4,9 +4,9 @@
 
 obj-y := \
 	cache.o cacheinit.o cplbhdlr.o cplbmgr.o entry.o \
-	interrupt.o lock.o dpmc.o irqpanic.o
+	interrupt.o lock.o irqpanic.o
 
 obj-$(CONFIG_CPLB_INFO)          += cplbinfo.o
 obj-$(CONFIG_BFIN_SINGLE_CORE)   += ints-priority-sc.o
 obj-$(CONFIG_BFIN_DUAL_CORE)     += ints-priority-dc.o
-obj-$(CONFIG_PM)                 += pm.o
+obj-$(CONFIG_PM)                 += pm.o dpmc.o
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S
index bb9446e..7063795 100644
--- a/arch/blackfin/mach-common/cache.S
+++ b/arch/blackfin/mach-common/cache.S
@@ -70,6 +70,7 @@
 .Lno_dcache_b:
 	R7 = [SP++];
 	RTS;
+ENDPROC(_cache_invalidate)
 
 /* Invalidate the Entire Instruction cache by
  * disabling IMC bit
@@ -106,6 +107,8 @@
 
 	( R7:5) = [SP++];
 	RTS;
+ENDPROC(_invalidate_entire_icache)
+ENDPROC(_icache_invalidate)
 
 /*
  * blackfin_cache_flush_range(start, end)
@@ -120,15 +123,16 @@
 	R2 = R0 & R2;
 	P0 = R2;
 	P1 = R1;
-	CSYNC;
+	CSYNC(R3);
 	IFLUSH [P0];
 1:
 	IFLUSH [P0++];
 	CC = P0 < P1 (iu);
 	IF CC JUMP 1b (bp);
 	IFLUSH [P0];
-	SSYNC;
+	SSYNC(R3);
 	RTS;
+ENDPROC(_blackfin_icache_flush_range)
 
 /*
  * blackfin_icache_dcache_flush_range(start, end)
@@ -144,7 +148,7 @@
 	R2 = R0 & R2;
 	P0 = R2;
 	P1 = R1;
-	CSYNC;
+	CSYNC(R3);
 	IFLUSH [P0];
 1:
 	FLUSH [P0];
@@ -153,8 +157,9 @@
 	IF CC JUMP 1b (bp);
 	IFLUSH [P0];
 	FLUSH [P0];
-	SSYNC;
+	SSYNC(R3);
 	RTS;
+ENDPROC(_blackfin_icache_dcache_flush_range)
 
 /* Throw away all D-cached data in specified region without any obligation to
  * write them back. However, we must clean the D-cached entries around the
@@ -169,7 +174,7 @@
 	R2 = R0 & R2;
 	P0 = R2;
 	P1 = R1;
-	CSYNC;
+	CSYNC(R3);
 	FLUSHINV[P0];
 1:
 	FLUSHINV[P0++];
@@ -181,8 +186,9 @@
 	 * so do one more.
 	 */
 	FLUSHINV[P0];
-	SSYNC;
+	SSYNC(R3);
 	RTS;
+ENDPROC(_blackfin_dcache_invalidate_range)
 
 /* Invalidate the Entire Data cache by
  * clearing DMC[1:0] bits
@@ -221,13 +227,15 @@
 
 	( R7:6) = [SP++];
 	RTS;
+ENDPROC(_dcache_invalidate)
+ENDPROC(_invalidate_entire_dcache)
 
 ENTRY(_blackfin_dcache_flush_range)
 	R2 = -L1_CACHE_BYTES;
 	R2 = R0 & R2;
 	P0 = R2;
 	P1 = R1;
-	CSYNC;
+	CSYNC(R3);
 	FLUSH[P0];
 1:
 	FLUSH[P0++];
@@ -239,15 +247,17 @@
 	 * one more.
 	 */
 	FLUSH[P0];
-	SSYNC;
+	SSYNC(R3);
 	RTS;
+ENDPROC(_blackfin_dcache_flush_range)
 
 ENTRY(_blackfin_dflush_page)
 	P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT);
 	P0 = R0;
-	CSYNC;
+	CSYNC(R3);
 	FLUSH[P0];
 	LSETUP (.Lfl1, .Lfl1) LC0 = P1;
 .Lfl1:	FLUSH [P0++];
-	SSYNC;
+	SSYNC(R3);
 	RTS;
+ENDPROC(_blackfin_dflush_page)
diff --git a/arch/blackfin/mach-common/cacheinit.S b/arch/blackfin/mach-common/cacheinit.S
index 8c17f09..9d47562 100644
--- a/arch/blackfin/mach-common/cacheinit.S
+++ b/arch/blackfin/mach-common/cacheinit.S
@@ -38,100 +38,37 @@
 
 .text
 
+#ifdef ANOMALY_05000125
 #if defined(CONFIG_BLKFIN_CACHE)
-ENTRY(_bfin_icache_init)
+ENTRY(_bfin_write_IMEM_CONTROL)
 
-	/* Initialize Instruction CPLBS */
-
-	I0.L = (ICPLB_ADDR0 & 0xFFFF);
-	I0.H = (ICPLB_ADDR0 >> 16);
-
-	I1.L = (ICPLB_DATA0 & 0xFFFF);
-	I1.H = (ICPLB_DATA0 >> 16);
-
-	I2.L = _icplb_table;
-	I2.H = _icplb_table;
-
-	r1 = -1;	/* end point comparison */
-	r3 = 15;	/* max counter */
-
-/* read entries from table */
-
-.Lread_iaddr:
-	R0 = [I2++];
-	CC = R0 == R1;
-	IF CC JUMP .Lidone;
-	[I0++] = R0;
-
-.Lread_idata:
-	R2 = [I2++];
-	[I1++] = R2;
-	R3 = R3 + R1;
-	CC = R3 == R1;
-	IF !CC JUMP .Lread_iaddr;
-
-.Lidone:
 	/* Enable Instruction Cache */
 	P0.l = (IMEM_CONTROL & 0xFFFF);
 	P0.h = (IMEM_CONTROL >> 16);
-	R1 = [P0];
-	R0 = (IMC | ENICPLB);
-	R0 = R0 | R1;
 
 	/* Anomaly 05000125 */
-	CLI R2;
+	CLI R1;
 	SSYNC;		/* SSYNC required before writing to IMEM_CONTROL. */
 	.align 8;
 	[P0] = R0;
 	SSYNC;
-	STI R2;
+	STI R1;
 	RTS;
+
+ENDPROC(_bfin_write_IMEM_CONTROL)
 #endif
 
 #if defined(CONFIG_BLKFIN_DCACHE)
-ENTRY(_bfin_dcache_init)
-
-	/* Initialize Data CPLBS */
-
-	I0.L = (DCPLB_ADDR0 & 0xFFFF);
-	I0.H = (DCPLB_ADDR0 >> 16);
-
-	I1.L = (DCPLB_DATA0 & 0xFFFF);
-	I1.H = (DCPLB_DATA0 >> 16);
-
-	I2.L = _dcplb_table;
-	I2.H = _dcplb_table;
-
-	R1 = -1;	/* end point comparison */
-	R3 = 15;	/* max counter */
-
-	/* read entries from table */
-.Lread_daddr:
-	R0 = [I2++];
-	cc = R0 == R1;
-	IF CC JUMP .Lddone;
-	[I0++] = R0;
-
-.Lread_ddata:
-	R2 = [I2++];
-	[I1++] = R2;
-	R3 = R3 + R1;
-	CC = R3 == R1;
-	IF !CC JUMP .Lread_daddr;
-.Lddone:
-	P0.L = (DMEM_CONTROL & 0xFFFF);
-	P0.H = (DMEM_CONTROL >> 16);
-	R1 = [P0];
-
-	R0 = DMEM_CNTR;
-
-	R0 = R0 | R1;
-	/* Anomaly 05000125 */
-	CLI R2;
+ENTRY(_bfin_write_DMEM_CONTROL)
+	CLI R1;
 	SSYNC;		/* SSYNC required before writing to DMEM_CONTROL. */
 	.align 8;
 	[P0] = R0;
 	SSYNC;
-	STI R2;
+	STI R1;
 	RTS;
+
+ENDPROC(_bfin_write_DMEM_CONTROL)
+#endif
+
 #endif
diff --git a/arch/blackfin/mach-common/cplbhdlr.S b/arch/blackfin/mach-common/cplbhdlr.S
index b979067..2f3c72c 100644
--- a/arch/blackfin/mach-common/cplbhdlr.S
+++ b/arch/blackfin/mach-common/cplbhdlr.S
@@ -42,8 +42,6 @@
 
 .align 2
 
-.global __cplb_hdr;
-.type __cplb_hdr, STT_FUNC;
 ENTRY(__cplb_hdr)
 	R2 = SEQSTAT;
 
@@ -128,3 +126,5 @@
 	call _panic_cplb_error;
 	SP += 12;
 	JUMP _handle_bad_cplb;
+
+ENDPROC(__cplb_hdr)
diff --git a/arch/blackfin/mach-common/cplbinfo.c b/arch/blackfin/mach-common/cplbinfo.c
index d65fac3..785ca98 100644
--- a/arch/blackfin/mach-common/cplbinfo.c
+++ b/arch/blackfin/mach-common/cplbinfo.c
@@ -31,11 +31,10 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/uaccess.h>
 
 #include <asm/current.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
-
 #include <asm/cplb.h>
 #include <asm/blackfin.h>
 
@@ -82,7 +81,7 @@
 	int entry = 0, used_cplb = 0;
 
 	if (type == CPLB_I) {
-		buf += sprintf(buf, "Instrction CPLB entry:\n");
+		buf += sprintf(buf, "Instruction CPLB entry:\n");
 		p_addr = ipdt_table;
 		p_data = ipdt_table + 1;
 		p_icount = ipdt_swapcount_table;
@@ -92,8 +91,7 @@
 	} else
 		buf += sprintf(buf, "Data CPLB entry:\n");
 
-	buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\
-\tiCount\toCount\n");
+	buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\n\tiCount\toCount\n");
 
 	while (*p_addr != 0xffffffff) {
 		entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data);
@@ -144,8 +142,7 @@
 
 	p = buf;
 
-	p += sprintf(p,
-		     "------------------ CPLB Information ------------------\n\n");
+	p += sprintf(p, "------------------ CPLB Information ------------------\n\n");
 
 	if (bfin_read_IMEM_CONTROL() & ENICPLB)
 		p = cplb_print_entry(p, CPLB_I);
@@ -191,9 +188,9 @@
 {
 	struct proc_dir_entry *entry;
 
-	if ((entry = create_proc_entry("cplbinfo", 0, NULL)) == NULL) {
+	entry = create_proc_entry("cplbinfo", 0, NULL);
+	if (!entry)
 		return -ENOMEM;
-	}
 
 	entry->read_proc = cplbinfo_read_proc;
 	entry->write_proc = cplbinfo_write_proc;
diff --git a/arch/blackfin/mach-common/cplbmgr.S b/arch/blackfin/mach-common/cplbmgr.S
index f5efc4b..e4b47e0 100644
--- a/arch/blackfin/mach-common/cplbmgr.S
+++ b/arch/blackfin/mach-common/cplbmgr.S
@@ -592,6 +592,7 @@
 	( R7:4,P5:3 ) = [SP++];
 	R0 = CPLB_RELOADED;
 	RTS;
+ENDPROC(_cplb_mgr)
 
 .data
 .align 4;
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 8eb0a90..d61bba98 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -49,34 +49,15 @@
 
 
 #include <linux/linkage.h>
+#include <linux/unistd.h>
 #include <asm/blackfin.h>
-#include <asm/unistd.h>
 #include <asm/errno.h>
 #include <asm/thread_info.h>  /* TIF_NEED_RESCHED */
 #include <asm/asm-offsets.h>
+#include <asm/trace.h>
 
 #include <asm/mach-common/context.S>
 
-#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
-	/*
-	 * TODO: this should be proper save/restore, but for now
-	 * we'll just cheat and use 0x1/0x13
-	 */
-# define DEBUG_START_HWTRACE \
-	P5.l = LO(TBUFCTL); \
-	P5.h = HI(TBUFCTL); \
-	R7 = 0x13; \
-	[P5] = R7;
-# define DEBUG_STOP_HWTRACE \
-	P5.l = LO(TBUFCTL); \
-	P5.h = HI(TBUFCTL); \
-	R7 = 0x01; \
-	[P5] = R7;
-#else
-# define DEBUG_START_HWTRACE
-# define DEBUG_STOP_HWTRACE
-#endif
-
 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
 .section .l1.text
 #else
@@ -103,59 +84,34 @@
 	if !cc jump _return_from_exception;
 	/* fall through */
 #endif
+ENDPROC(_ex_dcplb)
 
 ENTRY(_ex_icplb)
 	(R7:6,P5:4) = [sp++];
 	ASTAT = [sp++];
 	SAVE_ALL_SYS
 	call __cplb_hdr;
-	DEBUG_START_HWTRACE
+	DEBUG_START_HWTRACE(p5, r7)
 	RESTORE_ALL_SYS
 	SP = RETN;
 	rtx;
-
-ENTRY(_ex_spinlock)
-	/* Transform this into a syscall - twiddle the syscall vector.  */
-	p5.l = lo(EVT15);
-	p5.h = hi(EVT15);
-	r7.l = _spinlock_bh;
-	r7.h = _spinlock_bh;
-	[p5] = r7;
-	csync;
-	/* Fall through.  */
+ENDPROC(_ex_icplb)
 
 ENTRY(_ex_syscall)
-	DEBUG_START_HWTRACE
+	DEBUG_START_HWTRACE(p5, r7)
 	(R7:6,P5:4) = [sp++];
 	ASTAT = [sp++];
 	raise 15;		/* invoked by TRAP #0, for sys call */
 	sp = retn;
 	rtx
-
-ENTRY(_spinlock_bh)
-	SAVE_ALL_SYS
-	/* To end up here, vector 15 was changed - so we have to change it
-	 * back.
-	 */
-	p0.l = lo(EVT15);
-	p0.h = hi(EVT15);
-	p1.l = _evt_system_call;
-	p1.h = _evt_system_call;
-	[p0] = p1;
-	csync;
-	r0 = [sp + PT_R0];
-	sp += -12;
-	call _sys_bfin_spinlock;
-	sp += 12;
-	[SP + PT_R0] = R0;
-	RESTORE_ALL_SYS
-	rti;
+ENDPROC(_ex_syscall)
 
 ENTRY(_ex_soft_bp)
 	r7 = retx;
 	r7 += -2;
 	retx = r7;
 	jump.s _ex_trap_c;
+ENDPROC(_ex_soft_bp)
 
 ENTRY(_ex_single_step)
 	r7 = retx;
@@ -180,11 +136,18 @@
 	if !cc jump _ex_trap_c;
 
 _return_from_exception:
-	DEBUG_START_HWTRACE
+	DEBUG_START_HWTRACE(p5, r7)
+#ifdef ANOMALY_05000257
+	R7=LC0;
+	LC0=R7;
+	R7=LC1;
+	LC1=R7;
+#endif
 	(R7:6,P5:4) = [sp++];
 	ASTAT = [sp++];
 	sp = retn;
 	rtx;
+ENDPROC(_ex_soft_bp)
 
 ENTRY(_handle_bad_cplb)
 	/* To get here, we just tried and failed to change a CPLB
@@ -195,7 +158,7 @@
 	 * need to make a CPLB exception look like a normal exception
 	 */
 
-	DEBUG_START_HWTRACE
+	DEBUG_START_HWTRACE(p5, r7)
 	RESTORE_ALL_SYS
 	[--sp] = ASTAT;
 	[--sp] = (R7:6, P5:4);
@@ -238,12 +201,13 @@
 	R6 = SEQSTAT;
 	[P5] = R6;
 
-	DEBUG_START_HWTRACE
+	DEBUG_START_HWTRACE(p5, r7)
 	(R7:6,P5:4) = [sp++];
 	ASTAT = [sp++];
 	SP = RETN;
 	raise 5;
 	rtx;
+ENDPROC(_ex_trap_c)
 
 ENTRY(_exception_to_level5)
 	SAVE_ALL_SYS
@@ -308,6 +272,7 @@
 	call _ret_from_exception;
 	RESTORE_ALL_SYS
 	rti;
+ENDPROC(_exception_to_level5)
 
 ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
 	/* Since the kernel stack can be anywhere, it's not guaranteed to be
@@ -320,7 +285,7 @@
 	/* Try to deal with syscalls quickly.  */
 	[--sp] = ASTAT;
 	[--sp] = (R7:6, P5:4);
-	DEBUG_STOP_HWTRACE
+	DEBUG_STOP_HWTRACE(p5, r7)
 	r7 = SEQSTAT;		/* reason code is in bit 5:0 */
 	r6.l = lo(SEQSTAT_EXCAUSE);
 	r6.h = hi(SEQSTAT_EXCAUSE);
@@ -336,6 +301,7 @@
 	r7 = -ENOSYS; 		/* signextending enough */
 	[sp + PT_R0] = r7;	/* return value from system call */
 	jump .Lsyscall_really_exit;
+ENDPROC(_trap)
 
 ENTRY(_kernel_execve)
 	link SIZEOF_PTREGS;
@@ -390,6 +356,7 @@
 1:
 	unlink;
 	rts;
+ENDPROC(_kernel_execve)
 
 ENTRY(_system_call)
 	/* Store IPEND */
@@ -497,6 +464,7 @@
 	r5 = [sp + PT_RESERVED];
 	rets = r5;
 	rts;
+ENDPROC(_system_call)
 
 _sys_trace:
 	call _syscall_trace;
@@ -525,6 +493,7 @@
 
 	call _syscall_trace;
 	jump .Lresume_userspace;
+ENDPROC(_sys_trace)
 
 ENTRY(_resume)
 	/*
@@ -574,6 +543,7 @@
 	 * in "new" task.
 	 */
 	rts;
+ENDPROC(_resume)
 
 ENTRY(_ret_from_exception)
 	p2.l = lo(IPEND);
@@ -632,6 +602,7 @@
 	syscfg = r0;
 5:
 	rts;
+ENDPROC(_ret_from_exception)
 
 ENTRY(_return_from_int)
 	/* If someone else already raised IRQ 15, do nothing.  */
@@ -674,6 +645,7 @@
 	rti;
 2:
 	rts;
+ENDPROC(_return_from_int)
 
 ENTRY(_lower_to_irq14)
 #if defined(ANOMALY_05000281)
@@ -706,6 +678,11 @@
 	p1.h = _evt_system_call;
 	[p0] = p1;
 	csync;
+
+	/* Set orig_p0 to -1 to indicate this isn't the end of a syscall.  */
+	r0 = -1 (x);
+	[sp + PT_ORIG_P0] = r0;
+
 	p1 = rets;
 	[sp + PT_RESERVED] = p1;
 
@@ -714,6 +691,10 @@
 	r0 = [p0];
 	sti r0;
 
+	r0 = sp;
+	sp += -12;
+	call _finish_atomic_sections;
+	sp += 12;
 	jump.s .Lresume_userspace;
 
 _schedule_and_signal:
@@ -734,6 +715,7 @@
 1:
 	RESTORE_CONTEXT
 	rti;
+ENDPROC(_lower_to_irq14)
 
 /* Make sure when we start, that the circular buffer is initialized properly
  * R0 and P0 are call clobbered, so we can use them here.
@@ -747,6 +729,7 @@
 	p0.l = _out_ptr_excause;
 	[p0] = r0;
 	rts;
+ENDPROC(_init_exception_buff)
 
 /*
  * Put these in the kernel data section - that should always be covered by
@@ -761,14 +744,14 @@
 ALIGN
 _extable:
 	/* entry for each EXCAUSE[5:0]
-	 * This table bmust be in sync with the table in ./kernel/traps.c
+	 * This table must be in sync with the table in ./kernel/traps.c
 	 * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
 	 */
 	.long _ex_syscall;      /* 0x00 - User Defined - Linux Syscall */
 	.long _ex_soft_bp       /* 0x01 - User Defined - Software breakpoint */
 	.long _ex_trap_c        /* 0x02 - User Defined */
-	.long _ex_trap_c        /* 0x03 - User Defined  - Atomic test and set service */
-	.long _ex_spinlock      /* 0x04 - User Defined */
+	.long _ex_trap_c        /* 0x03 - User Defined - userspace stack overflow */
+	.long _ex_trap_c        /* 0x04 - User Defined */
 	.long _ex_trap_c        /* 0x05 - User Defined */
 	.long _ex_trap_c        /* 0x06 - User Defined */
 	.long _ex_trap_c        /* 0x07 - User Defined */
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index dd45664..203e207 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -34,6 +34,7 @@
 #include <linux/linkage.h>
 #include <asm/entry.h>
 #include <asm/asm-offsets.h>
+#include <asm/trace.h>
 
 #include <asm/mach-common/context.S>
 
@@ -66,6 +67,7 @@
 	SP += 12;
 	/* - GDB stub fills this in by itself (if defined) */
 	rte;
+ENDPROC(_evt_emulation)
 #endif
 
 /* Common interrupt entry code.	 First we do CLI, then push
@@ -138,7 +140,7 @@
 	fp = 0;
 #endif
 
-#ifdef	ANOMALY_05000283
+#if defined (ANOMALY_05000283) || defined (ANOMALY_05000315)
 	cc = r7 == r7;
 	p5.h = 0xffc0;
 	p5.l = 0x0014;
@@ -169,10 +171,9 @@
 	r7.l = W[p5];
 1:
 #endif
-	p0.l = lo(TBUFCTL);
-	p0.h = hi(TBUFCTL);
-	r0 = 1;
-	[p0] = r0;
+
+	trace_buffer_stop(p0, r0);
+
 	r0 = IRQ_HWERR;
 	r1 = sp;
 
@@ -251,3 +252,4 @@
 #endif
 	call _system_call;
 	jump .Lcommon_restore_context;
+ENDPROC(_evt_system_call)
diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c
index f3cf070..6b9fd03 100644
--- a/arch/blackfin/mach-common/ints-priority-dc.c
+++ b/arch/blackfin/mach-common/ints-priority-dc.c
@@ -4,7 +4,7 @@
  * Author:
  *
  * Created:      ?
- * Description:  Set up the interupt priorities
+ * Description:  Set up the interrupt priorities
  *
  * Modified:
  *               1996 Roman Zippel
@@ -183,7 +183,7 @@
 {
 	u16 gpionr = irq - IRQ_PF0;
 
-	if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+	if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
 		set_gpio_data(gpionr, 0);
 		SSYNC();
 	}
@@ -193,7 +193,7 @@
 {
 	u16 gpionr = irq - IRQ_PF0;
 
-	if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+	if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
 		set_gpio_data(gpionr, 0);
 		SSYNC();
 	}
@@ -222,7 +222,7 @@
 	if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
 
 		ret = gpio_request(gpionr, NULL);
-		if(ret)
+		if (ret)
 			return ret;
 
 	}
@@ -262,7 +262,7 @@
 		if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
 
 			ret = gpio_request(gpionr, NULL);
-			if(ret)
+			if (ret)
 				return ret;
 
 		}
@@ -371,6 +371,9 @@
 	bfin_write_SICA_IMASK1(SIC_UNMASK_ALL);
 	SSYNC();
 
+	bfin_write_SICA_IWR0(IWR_ENABLE_ALL);
+	bfin_write_SICA_IWR1(IWR_ENABLE_ALL);
+
 	local_irq_disable();
 
 	init_exception_buff();
@@ -393,7 +396,7 @@
 	bfin_write_EVT15(evt_system_call);
 	CSYNC();
 
-	for (irq = 0; irq < SYS_IRQS; irq++) {
+	for (irq = 0; irq <= SYS_IRQS; irq++) {
 		if (irq <= IRQ_CORETMR)
 			set_irq_chip(irq, &bf561_core_irqchip);
 		else
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c
index 34b6228..28a878c 100644
--- a/arch/blackfin/mach-common/ints-priority-sc.c
+++ b/arch/blackfin/mach-common/ints-priority-sc.c
@@ -4,7 +4,7 @@
  * Author:
  *
  * Created:      ?
- * Description:  Set up the interupt priorities
+ * Description:  Set up the interrupt priorities
  *
  * Modified:
  *               1996 Roman Zippel
@@ -13,7 +13,7 @@
  *               2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
  *               2003 Metrowerks/Motorola
  *               2003 Bas Vermeulen <bas@buyways.nl>
- *               Copyright 2004-2006 Analog Devices Inc.
+ *               Copyright 2004-2007 Analog Devices Inc.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -65,9 +65,9 @@
 
 struct ivgx {
 	/* irq number for request_irq, available in mach-bf533/irq.h */
-	int irqno;
+	unsigned int irqno;
 	/* corresponding bit in the SIC_ISR register */
-	int isrflag;
+	unsigned int isrflag;
 } ivg_table[NR_PERI_INTS];
 
 struct ivg_slice {
@@ -88,17 +88,16 @@
 	for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
 		int irqn;
 
-		ivg7_13[ivg].istop = ivg7_13[ivg].ifirst =
-		    &ivg_table[irq_pos];
+		ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
 
 		for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
 			int iar_shift = (irqn & 7) * 4;
 			if (ivg ==
 			    (0xf &
-			     bfin_read32((unsigned long *) SIC_IAR0 +
+			     bfin_read32((unsigned long *)SIC_IAR0 +
 					 (irqn >> 3)) >> iar_shift)) {
 				ivg_table[irq_pos].irqno = IVG7 + irqn;
-				ivg_table[irq_pos].isrflag = 1 << irqn;
+				ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
 				ivg7_13[ivg].istop++;
 				irq_pos++;
 			}
@@ -141,15 +140,31 @@
 
 static void bfin_internal_mask_irq(unsigned int irq)
 {
+#ifndef CONFIG_BF54x
 	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
 			     ~(1 << (irq - (IRQ_CORETMR + 1))));
+#else
+	unsigned mask_bank, mask_bit;
+	mask_bank = (irq - (IRQ_CORETMR + 1)) / 32;
+	mask_bit = (irq - (IRQ_CORETMR + 1)) % 32;
+	bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
+			     ~(1 << mask_bit));
+#endif
 	SSYNC();
 }
 
 static void bfin_internal_unmask_irq(unsigned int irq)
 {
+#ifndef CONFIG_BF54x
 	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
 			     (1 << (irq - (IRQ_CORETMR + 1))));
+#else
+	unsigned mask_bank, mask_bit;
+	mask_bank = (irq - (IRQ_CORETMR + 1)) / 32;
+	mask_bit = (irq - (IRQ_CORETMR + 1)) % 32;
+	bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) |
+			     (1 << mask_bit));
+#endif
 	SSYNC();
 }
 
@@ -206,7 +221,7 @@
 };
 
 static void bfin_demux_error_irq(unsigned int int_err_irq,
-				  struct irq_desc *intb_desc)
+				 struct irq_desc *intb_desc)
 {
 	int irq = 0;
 
@@ -270,8 +285,8 @@
 			}
 
 			pr_debug("IRQ %d:"
-				" MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
-				irq);
+				 " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
+				 irq);
 		}
 	} else
 		printk(KERN_ERR
@@ -279,11 +294,10 @@
 		       " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
 		       __FUNCTION__, __FILE__, __LINE__);
 
-
 }
 #endif				/* BF537_GENERIC_ERROR_INT_DEMUX */
 
-#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && !defined(CONFIG_BF54x)
 
 static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
 static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -361,8 +375,7 @@
 	}
 
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
-	            IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-	{
+		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
 		if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
 			ret = gpio_request(gpionr, NULL);
 			if (ret)
@@ -407,6 +420,247 @@
 	return 0;
 }
 
+static struct irq_chip bfin_gpio_irqchip = {
+	.ack = bfin_gpio_ack_irq,
+	.mask = bfin_gpio_mask_irq,
+	.mask_ack = bfin_gpio_mask_ack_irq,
+	.unmask = bfin_gpio_unmask_irq,
+	.set_type = bfin_gpio_irq_type,
+	.startup = bfin_gpio_irq_startup,
+	.shutdown = bfin_gpio_irq_shutdown
+};
+
+static void bfin_demux_gpio_irq(unsigned int intb_irq,
+				struct irq_desc *intb_desc)
+{
+	u16 i;
+	struct irq_desc *desc;
+
+	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) {
+		int irq = IRQ_PF0 + i;
+		int flag_d = get_gpiop_data(i);
+		int mask =
+		    flag_d & (gpio_enabled[gpio_bank(i)] & get_gpiop_maska(i));
+
+		while (mask) {
+			if (mask & 1) {
+				desc = irq_desc + irq;
+				desc->handle_irq(irq, desc);
+			}
+			irq++;
+			mask >>= 1;
+		}
+	}
+}
+
+#else				/* CONFIG_IRQCHIP_DEMUX_GPIO */
+
+#define NR_PINT_SYS_IRQS	4
+#define NR_PINT_BITS		32
+#define NR_PINTS		160
+#define IRQ_NOT_AVAIL		0xFF
+
+#define PINT_2_BANK(x)		((x) >> 5)
+#define PINT_2_BIT(x)		((x) & 0x1F)
+#define PINT_BIT(x)		(1 << (PINT_2_BIT(x)))
+
+static unsigned char irq2pint_lut[NR_PINTS];
+static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
+
+struct pin_int_t {
+	unsigned int mask_set;
+	unsigned int mask_clear;
+	unsigned int request;
+	unsigned int assign;
+	unsigned int edge_set;
+	unsigned int edge_clear;
+	unsigned int invert_set;
+	unsigned int invert_clear;
+	unsigned int pinstate;
+	unsigned int latch;
+};
+
+static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
+	(struct pin_int_t *)PINT0_MASK_SET,
+	(struct pin_int_t *)PINT1_MASK_SET,
+	(struct pin_int_t *)PINT2_MASK_SET,
+	(struct pin_int_t *)PINT3_MASK_SET,
+};
+
+unsigned short get_irq_base(u8 bank, u8 bmap)
+{
+
+	u16 irq_base;
+
+	if (bank < 2) {		/*PA-PB */
+		irq_base = IRQ_PA0 + bmap * 16;
+	} else {		/*PC-PJ */
+		irq_base = IRQ_PC0 + bmap * 16;
+	}
+
+	return irq_base;
+
+}
+
+	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
+void init_pint_lut(void)
+{
+	u16 bank, bit, irq_base, bit_pos;
+	u32 pint_assign;
+	u8 bmap;
+
+	memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut));
+
+	for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {
+
+		pint_assign = pint[bank]->assign;
+
+		for (bit = 0; bit < NR_PINT_BITS; bit++) {
+
+			bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF;
+
+			irq_base = get_irq_base(bank, bmap);
+
+			irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0);
+			bit_pos = bit + bank * NR_PINT_BITS;
+
+			pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;
+			irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;
+
+		}
+
+	}
+
+}
+
+static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+static void bfin_gpio_ack_irq(unsigned int irq)
+{
+	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+	pint[PINT_2_BANK(pint_val)]->request = PINT_BIT(pint_val);
+	SSYNC();
+}
+
+static void bfin_gpio_mask_ack_irq(unsigned int irq)
+{
+	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pintbit = PINT_BIT(pint_val);
+	u8 bank = PINT_2_BANK(pint_val);
+
+	pint[bank]->request = pintbit;
+	pint[bank]->mask_clear = pintbit;
+	SSYNC();
+}
+
+static void bfin_gpio_mask_irq(unsigned int irq)
+{
+	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+	pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
+	SSYNC();
+}
+
+static void bfin_gpio_unmask_irq(unsigned int irq)
+{
+	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pintbit = PINT_BIT(pint_val);
+	u8 bank = PINT_2_BANK(pint_val);
+
+	pint[bank]->request = pintbit;
+	pint[bank]->mask_set = pintbit;
+	SSYNC();
+}
+
+static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+{
+	unsigned int ret;
+	u16 gpionr = irq - IRQ_PA0;
+	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+	if (pint_val == IRQ_NOT_AVAIL)
+		return -ENODEV;
+
+	if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+		ret = gpio_request(gpionr, NULL);
+		if (ret)
+			return ret;
+	}
+
+	gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+	bfin_gpio_unmask_irq(irq);
+
+	return ret;
+}
+
+static void bfin_gpio_irq_shutdown(unsigned int irq)
+{
+	bfin_gpio_mask_irq(irq);
+	gpio_free(irq - IRQ_PA0);
+	gpio_enabled[gpio_bank(irq - IRQ_PA0)] &= ~gpio_bit(irq - IRQ_PA0);
+}
+
+static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+{
+
+	unsigned int ret;
+	u16 gpionr = irq - IRQ_PA0;
+	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pintbit = PINT_BIT(pint_val);
+	u8 bank = PINT_2_BANK(pint_val);
+
+	if (pint_val == IRQ_NOT_AVAIL)
+		return -ENODEV;
+
+	if (type == IRQ_TYPE_PROBE) {
+		/* only probe unenabled GPIO interrupt lines */
+		if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))
+			return 0;
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+		if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+			ret = gpio_request(gpionr, NULL);
+			if (ret)
+				return ret;
+		}
+
+		gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+	} else {
+		gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+		return 0;
+	}
+
+	gpio_direction_input(gpionr);
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+		pint[bank]->edge_set = pintbit;
+	} else {
+		pint[bank]->edge_clear = pintbit;
+	}
+
+	if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+		pint[bank]->invert_set = pintbit;	/* low or falling edge denoted by one */
+	else
+		pint[bank]->invert_set = pintbit;	/* high or rising edge denoted by zero */
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+		pint[bank]->invert_set = pintbit;
+	else
+		pint[bank]->invert_set = pintbit;
+
+	SSYNC();
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+		set_irq_handler(irq, handle_edge_irq);
+	else
+		set_irq_handler(irq, handle_level_irq);
+
+	return 0;
+}
 
 static struct irq_chip bfin_gpio_irqchip = {
 	.ack = bfin_gpio_ack_irq,
@@ -419,28 +673,44 @@
 };
 
 static void bfin_demux_gpio_irq(unsigned int intb_irq,
-				 struct irq_desc *intb_desc)
+				struct irq_desc *intb_desc)
 {
-	u16 i;
+	u8 bank, pint_val;
+	u32 request, irq;
+	struct irq_desc *desc;
 
-	for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=16) {
-		int irq = IRQ_PF0 + i;
-		int flag_d = get_gpiop_data(i);
-		int mask =
-			flag_d & (gpio_enabled[gpio_bank(i)] &
-			      get_gpiop_maska(i));
-
-		while (mask) {
-			if (mask & 1) {
-				struct irq_desc *desc = irq_desc + irq;
-				desc->handle_irq(irq, desc);
-			}
-			irq++;
-			mask >>= 1;
-		}
+	switch (intb_irq) {
+	case IRQ_PINT0:
+		bank = 0;
+		break;
+	case IRQ_PINT2:
+		bank = 2;
+		break;
+	case IRQ_PINT3:
+		bank = 3;
+		break;
+	case IRQ_PINT1:
+		bank = 1;
+		break;
+	default:
+		return;
 	}
-}
 
+	pint_val = bank * NR_PINT_BITS;
+
+	request = pint[bank]->request;
+
+	while (request) {
+		if (request & 1) {
+			irq = pint2irq_lut[pint_val] + SYS_IRQS;
+			desc = irq_desc + irq;
+			desc->handle_irq(irq, desc);
+		}
+		pint_val++;
+		request >>= 1;
+	}
+
+}
 #endif				/* CONFIG_IRQCHIP_DEMUX_GPIO */
 
 /*
@@ -452,7 +722,18 @@
 	int irq;
 	unsigned long ilat = 0;
 	/*  Disable all the peripheral intrs  - page 4-29 HW Ref manual */
+#ifdef CONFIG_BF54x
+	bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
+	bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
+	bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
+	bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
+	bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
+	bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
+#else
 	bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
+	bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+#endif
+
 	SSYNC();
 
 	local_irq_disable();
@@ -475,7 +756,18 @@
 	bfin_write_EVT15(evt_system_call);
 	CSYNC();
 
-	for (irq = 0; irq < SYS_IRQS; irq++) {
+#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && defined(CONFIG_BF54x)
+#ifdef CONFIG_PINTx_REASSIGN
+	pint[0]->assign = CONFIG_PINT0_ASSIGN;
+	pint[1]->assign = CONFIG_PINT1_ASSIGN;
+	pint[2]->assign = CONFIG_PINT2_ASSIGN;
+	pint[3]->assign = CONFIG_PINT3_ASSIGN;
+#endif
+	/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
+	init_pint_lut();
+#endif
+
+	for (irq = 0; irq <= SYS_IRQS; irq++) {
 		if (irq <= IRQ_CORETMR)
 			set_irq_chip(irq, &bfin_core_irqchip);
 		else
@@ -484,20 +776,42 @@
 		if (irq != IRQ_GENERIC_ERROR) {
 #endif
 
+			switch (irq) {
 #ifdef CONFIG_IRQCHIP_DEMUX_GPIO
-			if ((irq != IRQ_PROG_INTA) /*PORT F & G MASK_A Interrupt*/
-# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
-				&& (irq != IRQ_MAC_RX) /*PORT H MASK_A Interrupt*/
-# endif
-			    ) {
-#endif
-				set_irq_handler(irq, handle_simple_irq);
-#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
-			} else {
+#ifndef CONFIG_BF54x
+			case IRQ_PROG_INTA:
 				set_irq_chained_handler(irq,
 							bfin_demux_gpio_irq);
-			}
+				break;
+#if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
+			case IRQ_MAC_RX:
+				set_irq_chained_handler(irq,
+							bfin_demux_gpio_irq);
+				break;
 #endif
+#else
+			case IRQ_PINT0:
+				set_irq_chained_handler(irq,
+							bfin_demux_gpio_irq);
+				break;
+			case IRQ_PINT1:
+				set_irq_chained_handler(irq,
+							bfin_demux_gpio_irq);
+				break;
+			case IRQ_PINT2:
+				set_irq_chained_handler(irq,
+							bfin_demux_gpio_irq);
+				break;
+			case IRQ_PINT3:
+				set_irq_chained_handler(irq,
+							bfin_demux_gpio_irq);
+				break;
+#endif				/*CONFIG_BF54x */
+#endif
+			default:
+				set_irq_handler(irq, handle_simple_irq);
+				break;
+			}
 
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 		} else {
@@ -513,7 +827,11 @@
 #endif
 
 #ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#ifndef CONFIG_BF54x
 	for (irq = IRQ_PF0; irq < NR_IRQS; irq++) {
+#else
+	for (irq = IRQ_PA0; irq < NR_IRQS; irq++) {
+#endif
 		set_irq_chip(irq, &bfin_gpio_irqchip);
 		/* if configured as edge, then will be changed to do_edge_IRQ */
 		set_irq_handler(irq, handle_level_irq);
@@ -526,8 +844,7 @@
 	bfin_write_ILAT(ilat);
 	CSYNC();
 
-	printk(KERN_INFO
-	       "Configuring Blackfin Priority Driven Interrupts\n");
+	printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
 	/* IMASK=xxx is equivalent to STI xx or irq_flags=xx,
 	 * local_irq_enable()
 	 */
@@ -538,14 +855,13 @@
 	/* Enable interrupts IVG7-15 */
 	irq_flags = irq_flags | IMASK_IVG15 |
 	    IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
-	    IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 |
-	    IMASK_IVGHW;
+	    IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
 
 	return 0;
 }
 
 #ifdef CONFIG_DO_IRQ_L1
-void do_irq(int vec, struct pt_regs *fp)__attribute__((l1_text));
+void do_irq(int vec, struct pt_regs *fp) __attribute__((l1_text));
 #endif
 
 void do_irq(int vec, struct pt_regs *fp)
@@ -555,9 +871,25 @@
 	} else {
 		struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
 		struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
-		unsigned long sic_status;
+#ifdef CONFIG_BF54x
+		unsigned long sic_status[3];
 
 		SSYNC();
+		sic_status[0] = bfin_read_SIC_ISR(0) & bfin_read_SIC_IMASK(0);
+		sic_status[1] = bfin_read_SIC_ISR(1) & bfin_read_SIC_IMASK(1);
+		sic_status[2] = bfin_read_SIC_ISR(2) & bfin_read_SIC_IMASK(2);
+
+		for (;; ivg++) {
+			if (ivg >= ivg_stop) {
+				atomic_inc(&num_spurious);
+				return;
+			}
+			if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
+				break;
+		}
+#else
+		unsigned long sic_status;
+		SSYNC();
 		sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
 
 		for (;; ivg++) {
@@ -567,6 +899,7 @@
 			} else if (sic_status & ivg->isrflag)
 				break;
 		}
+#endif
 		vec = ivg->irqno;
 	}
 	asm_do_IRQ(vec, fp);
diff --git a/arch/blackfin/mach-common/lock.S b/arch/blackfin/mach-common/lock.S
index 2cbb15b..386ac8d 100644
--- a/arch/blackfin/mach-common/lock.S
+++ b/arch/blackfin/mach-common/lock.S
@@ -155,6 +155,7 @@
 	( R7:0,P5:0 ) = [SP++];
 
 	RTS;
+ENDPROC(_cache_grab_lock)
 
 /* After the execution of critical code, the code is now locked into
  * the cache way. Now we need to set ILOC.
@@ -186,6 +187,7 @@
 
 	( R7:0,P5:0 ) = [SP++];
 	RTS;
+ENDPROC(_cache_lock)
 
 #endif	/* BLKFIN_CACHE_LOCK */
 
@@ -193,7 +195,6 @@
  */
 
 ENTRY(_read_iloc)
-
 	P1.H = (IMEM_CONTROL >> 16);
 	P1.L = (IMEM_CONTROL & 0xFFFF);
 	R1 = 0xF;
@@ -202,3 +203,4 @@
 	R0 = R0 & R1;
 
 	RTS;
+ENDPROC(_read_iloc)
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index deb2727..1772d8d 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -35,11 +35,11 @@
 #include <linux/pm.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 
-#include <asm/io.h>
 #include <asm/dpmc.h>
-#include <asm/irq.h>
-
+#include <asm/gpio.h>
 
 #ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H
 #define WAKEUP_TYPE	PM_WAKE_HIGH
@@ -102,10 +102,8 @@
 	switch (state) {
 	case PM_SUSPEND_STANDBY:
 		break;
-	case PM_SUSPEND_MEM:
-		return -ENOTSUPP;
 
-	case PM_SUSPEND_DISK:
+	case PM_SUSPEND_MEM:
 		return -ENOTSUPP;
 
 	default:
@@ -126,10 +124,8 @@
 	case PM_SUSPEND_STANDBY:
 		bfin_pm_suspend_standby_enter();
 		break;
-	case PM_SUSPEND_MEM:
-		return -ENOTSUPP;
 
-	case PM_SUSPEND_DISK:
+	case PM_SUSPEND_MEM:
 		return -ENOTSUPP;
 
 	default:
@@ -155,9 +151,6 @@
 	case PM_SUSPEND_MEM:
 		return -ENOTSUPP;
 
-	case PM_SUSPEND_DISK:
-		return -ENOTSUPP;
-
 	default:
 		return -EINVAL;
 	}
@@ -166,7 +159,6 @@
 }
 
 struct pm_ops bfin_pm_ops = {
-	.pm_disk_mode = PM_DISK_PLATFORM,
 	.prepare = bfin_pm_prepare,
 	.enter = bfin_pm_enter,
 	.finish = bfin_pm_finish,
diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c
index dd0c650..16c6169 100644
--- a/arch/blackfin/mm/blackfin_sram.c
+++ b/arch/blackfin/mm/blackfin_sram.c
@@ -7,7 +7,7 @@
  * Description:  SRAM driver for Blackfin ADSP-BF5xx
  *
  * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
+ *               Copyright 2004-2007 Analog Devices Inc.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -63,6 +63,7 @@
 	void *paddr;
 	int size;
 	int flag;
+	pid_t pid;
 };
 
 static struct l1_sram_piece l1_ssram[CONFIG_L1_MAX_PIECE];
@@ -80,13 +81,13 @@
 #endif
 
 /* L1 Scratchpad SRAM initialization function */
-void l1sram_init(void)
+void __init l1sram_init(void)
 {
 	printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
 	       L1_SCRATCH_LENGTH >> 10);
 
 	memset(&l1_ssram, 0x00, sizeof(l1_ssram));
-	l1_ssram[0].paddr = (void*)L1_SCRATCH_START;
+	l1_ssram[0].paddr = (void *)L1_SCRATCH_START;
 	l1_ssram[0].size = L1_SCRATCH_LENGTH;
 	l1_ssram[0].flag = SRAM_SLT_FREE;
 
@@ -94,42 +95,43 @@
 	spin_lock_init(&l1sram_lock);
 }
 
-void l1_data_sram_init(void)
+void __init l1_data_sram_init(void)
 {
 #if L1_DATA_A_LENGTH != 0
-	printk(KERN_INFO "Blackfin DATA_A SRAM: %d KB\n",
-	       L1_DATA_A_LENGTH >> 10);
-
 	memset(&l1_data_A_sram, 0x00, sizeof(l1_data_A_sram));
-	l1_data_A_sram[0].paddr = (void*)L1_DATA_A_START +
-		(_ebss_l1 - _sdata_l1);
+	l1_data_A_sram[0].paddr = (void *)L1_DATA_A_START +
+					(_ebss_l1 - _sdata_l1);
 	l1_data_A_sram[0].size = L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
 	l1_data_A_sram[0].flag = SRAM_SLT_FREE;
+
+	printk(KERN_INFO "Blackfin Data A SRAM: %d KB (%d KB free)\n",
+	       L1_DATA_A_LENGTH >> 10, l1_data_A_sram[0].size >> 10);
 #endif
 #if L1_DATA_B_LENGTH != 0
-	printk(KERN_INFO "Blackfin DATA_B SRAM: %d KB\n",
-	       L1_DATA_B_LENGTH >> 10);
-
 	memset(&l1_data_B_sram, 0x00, sizeof(l1_data_B_sram));
-	l1_data_B_sram[0].paddr = (void*)L1_DATA_B_START;
-	l1_data_B_sram[0].size = L1_DATA_B_LENGTH;
+	l1_data_B_sram[0].paddr = (void *)L1_DATA_B_START +
+				(_ebss_b_l1 - _sdata_b_l1);
+	l1_data_B_sram[0].size = L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
 	l1_data_B_sram[0].flag = SRAM_SLT_FREE;
+
+	printk(KERN_INFO "Blackfin Data B SRAM: %d KB (%d KB free)\n",
+	       L1_DATA_B_LENGTH >> 10, l1_data_B_sram[0].size >> 10);
 #endif
 
 	/* mutex initialize */
 	spin_lock_init(&l1_data_sram_lock);
 }
 
-void l1_inst_sram_init(void)
+void __init l1_inst_sram_init(void)
 {
 #if L1_CODE_LENGTH != 0
-	printk(KERN_INFO "Blackfin Instruction SRAM: %d KB\n",
-	       L1_CODE_LENGTH >> 10);
-
 	memset(&l1_inst_sram, 0x00, sizeof(l1_inst_sram));
-	l1_inst_sram[0].paddr = (void*)L1_CODE_START + (_etext_l1 - _stext_l1);
+	l1_inst_sram[0].paddr = (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
 	l1_inst_sram[0].size = L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
 	l1_inst_sram[0].flag = SRAM_SLT_FREE;
+
+	printk(KERN_INFO "Blackfin Instruction SRAM: %d KB (%d KB free)\n",
+	       L1_CODE_LENGTH >> 10, l1_inst_sram[0].size >> 10);
 #endif
 
 	/* mutex initialize */
@@ -149,12 +151,13 @@
 	size = (size + 3) & ~3;
 
 	/* not use the good method to match the best slot !!! */
-	/* search an available memeory slot */
+	/* search an available memory slot */
 	for (i = 0; i < count; i++) {
 		if ((pfree[i].flag == SRAM_SLT_FREE)
 		    && (pfree[i].size >= size)) {
 			addr = pfree[i].paddr;
 			pfree[i].flag = SRAM_SLT_ALLOCATED;
+			pfree[i].pid = current->pid;
 			index = i;
 			break;
 		}
@@ -162,10 +165,11 @@
 	if (i >= count)
 		return NULL;
 
-	/* updated the NULL memeory slot !!! */
+	/* updated the NULL memory slot !!! */
 	if (pfree[i].size > size) {
 		for (i = 0; i < count; i++) {
 			if (pfree[i].flag == SRAM_SLT_NULL) {
+				pfree[i].pid = 0;
 				pfree[i].flag = SRAM_SLT_FREE;
 				pfree[i].paddr = addr + size;
 				pfree[i].size = pfree[index].size - size;
@@ -186,7 +190,7 @@
 	int i, index = -1;
 	void *addr = NULL;
 
-	/* search an available memeory slot */
+	/* search an available memory slot */
 	for (i = 0; i < count; i++) {
 		if (pfree[i].flag == SRAM_SLT_FREE && pfree[i].size > best) {
 			addr = pfree[i].paddr;
@@ -198,13 +202,15 @@
 		return NULL;
 	*psize = best;
 
+	pfree[index].pid = current->pid;
 	pfree[index].flag = SRAM_SLT_ALLOCATED;
 	return addr;
 }
 
 /* L1 memory free function */
 static int _l1_sram_free(const void *addr,
-			 struct l1_sram_piece *pfree, int count)
+			struct l1_sram_piece *pfree,
+			int count)
 {
 	int i, index = 0;
 
@@ -222,12 +228,14 @@
 	if (i >= count)
 		return -1;
 
+	pfree[index].pid = 0;
 	pfree[index].flag = SRAM_SLT_FREE;
 
 	/* link the next address slot */
 	for (i = 0; i < count; i++) {
 		if (((pfree[index].paddr + pfree[index].size) == pfree[i].paddr)
 		    && (pfree[i].flag == SRAM_SLT_FREE)) {
+			pfree[i].pid = 0;
 			pfree[i].flag = SRAM_SLT_NULL;
 			pfree[index].size += pfree[i].size;
 			pfree[index].flag = SRAM_SLT_FREE;
@@ -538,3 +546,64 @@
 	return addr;
 }
 EXPORT_SYMBOL(sram_alloc_with_lsl);
+
+#ifdef CONFIG_PROC_FS
+/* Once we get a real allocator, we'll throw all of this away.
+ * Until then, we need some sort of visibility into the L1 alloc.
+ */
+static void _l1sram_proc_read(char *buf, int *len, const char *desc,
+		struct l1_sram_piece *pfree, const int array_size)
+{
+	int i;
+
+	*len += sprintf(&buf[*len], "--- L1 %-14s Size  PID State\n", desc);
+	for (i = 0; i < array_size; ++i) {
+		const char *alloc_type;
+		switch (pfree[i].flag) {
+		case SRAM_SLT_NULL:      alloc_type = "NULL"; break;
+		case SRAM_SLT_FREE:      alloc_type = "FREE"; break;
+		case SRAM_SLT_ALLOCATED: alloc_type = "ALLOCATED"; break;
+		default:                 alloc_type = "????"; break;
+		}
+		*len += sprintf(&buf[*len], "%p-%p %8i %4i %s\n",
+			pfree[i].paddr, pfree[i].paddr + pfree[i].size,
+			pfree[i].size, pfree[i].pid, alloc_type);
+	}
+}
+static int l1sram_proc_read(char *buf, char **start, off_t offset, int count,
+		int *eof, void *data)
+{
+	int len = 0;
+
+	_l1sram_proc_read(buf, &len, "Scratchpad",
+			l1_ssram, ARRAY_SIZE(l1_ssram));
+#if L1_DATA_A_LENGTH != 0
+	_l1sram_proc_read(buf, &len, "Data A",
+			l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
+#endif
+#if L1_DATA_B_LENGTH != 0
+	_l1sram_proc_read(buf, &len, "Data B",
+			l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
+#endif
+#if L1_CODE_LENGTH != 0
+	_l1sram_proc_read(buf, &len, "Instruction",
+			l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
+#endif
+
+	return len;
+}
+
+static int __init l1sram_proc_init(void)
+{
+	struct proc_dir_entry *ptr;
+	ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL);
+	if (!ptr) {
+		printk(KERN_WARNING "unable to create /proc/sram\n");
+		return -1;
+	}
+	ptr->owner = THIS_MODULE;
+	ptr->read_proc = l1sram_proc_read;
+	return 0;
+}
+late_initcall(l1sram_proc_init);
+#endif
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index 73f72ab..68459cc 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -7,7 +7,7 @@
  * Description:
  *
  * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
+ *               Copyright 2004-2007 Analog Devices Inc.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -29,8 +29,8 @@
 
 #include <linux/swap.h>
 #include <linux/bootmem.h>
+#include <linux/uaccess.h>
 #include <asm/bfin-global.h>
-#include <asm/uaccess.h>
 #include <asm/l1layout.h>
 #include "blackfin_sram.h"
 
@@ -53,7 +53,7 @@
 
 unsigned long empty_zero_page;
 
-void show_mem(void)
+void __init show_mem(void)
 {
 	unsigned long i;
 	int free = 0, total = 0, reserved = 0, shared = 0;
@@ -86,7 +86,7 @@
  * The parameters are pointers to where to stick the starting and ending
  * addresses  of available kernel virtual memory.
  */
-void paging_init(void)
+void __init paging_init(void)
 {
 	/*
 	 * make sure start_mem is page aligned,  otherwise bootmem and
@@ -116,7 +116,8 @@
 	{
 		unsigned long zones_size[MAX_NR_ZONES] = { 0, };
 
-		zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
+		zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
+		zones_size[ZONE_NORMAL] = 0;
 #ifdef CONFIG_HIGHMEM
 		zones_size[ZONE_HIGHMEM] = 0;
 #endif
@@ -124,7 +125,7 @@
 	}
 }
 
-void mem_init(void)
+void __init mem_init(void)
 {
 	unsigned int codek = 0, datak = 0, initk = 0;
 	unsigned long tmp;
@@ -167,42 +168,31 @@
 	}
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
+static __init void free_init_pages(const char *what, unsigned long begin, unsigned long end)
 {
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	printk(KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
-}
-#endif
-
-void free_initmem(void)
-{
-#ifdef CONFIG_RAMKERNEL
 	unsigned long addr;
-/*
- *	the following code should be cool even if these sections
- *	are not page aligned.
- */
-	addr = PAGE_ALIGN((unsigned long)(__init_begin));
 	/* next to check that the page we free is not a partial page */
-	for (; addr + PAGE_SIZE < (unsigned long)(__init_end);
-	     addr += PAGE_SIZE) {
+	for (addr = begin; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
 		init_page_count(virt_to_page(addr));
 		free_page(addr);
 		totalram_pages++;
 	}
-	printk(KERN_NOTICE
-	       "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
-	       (addr - PAGE_ALIGN((long)__init_begin)) >> 10,
-	       (int)(PAGE_ALIGN((unsigned long)(__init_begin))),
-	       (int)(addr - PAGE_SIZE));
+	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init free_initrd_mem(unsigned long start, unsigned long end)
+{
+	free_init_pages("initrd memory", start, end);
+}
+#endif
+
+void __init free_initmem(void)
+{
+#ifdef CONFIG_RAMKERNEL
+	free_init_pages("unused kernel memory",
+			(unsigned long)(&__init_begin),
+			(unsigned long)(&__init_end));
 #endif
 }
diff --git a/arch/blackfin/oprofile/common.c b/arch/blackfin/oprofile/common.c
index 009a170..cb8b8d5 100644
--- a/arch/blackfin/oprofile/common.c
+++ b/arch/blackfin/oprofile/common.c
@@ -33,12 +33,12 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <linux/mutex.h>
+#include <linux/ptrace.h>
+#include <linux/irq.h>
+#include <linux/io.h>
 
-#include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/io.h>
 
 #include "op_blackfin.h"
 
diff --git a/arch/blackfin/oprofile/op_model_bf533.c b/arch/blackfin/oprofile/op_model_bf533.c
index b7a20a0..872dffe 100644
--- a/arch/blackfin/oprofile/op_model_bf533.c
+++ b/arch/blackfin/oprofile/op_model_bf533.c
@@ -32,12 +32,12 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <asm/ptrace.h>
+#include <linux/ptrace.h>
+#include <linux/irq.h>
+#include <linux/io.h>
 #include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/io.h>
 
 #include "op_blackfin.h"
 
diff --git a/arch/blackfin/oprofile/timer_int.c b/arch/blackfin/oprofile/timer_int.c
index 8fba16c..6c6f860 100644
--- a/arch/blackfin/oprofile/timer_int.c
+++ b/arch/blackfin/oprofile/timer_int.c
@@ -31,8 +31,7 @@
 #include <linux/smp.h>
 #include <linux/irq.h>
 #include <linux/oprofile.h>
-
-#include <asm/ptrace.h>
+#include <linux/ptrace.h>
 
 static void enable_sys_timer0()
 {
diff --git a/arch/cris/arch-v10/defconfig b/arch/cris/arch-v10/defconfig
index 2a3411ea..710c20b 100644
--- a/arch/cris/arch-v10/defconfig
+++ b/arch/cris/arch-v10/defconfig
@@ -429,7 +429,6 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index fd2129a..f4f9db69 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -83,19 +83,9 @@
 	switch (request) {
 		/* Read word at location address. */ 
 		case PTRACE_PEEKTEXT:
-		case PTRACE_PEEKDATA: {
-			unsigned long tmp;
-			int copied;
-
-			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-			ret = -EIO;
-			
-			if (copied != sizeof(tmp))
-				break;
-			
-			ret = put_user(tmp,datap);
+		case PTRACE_PEEKDATA:
+			ret = generic_ptrace_peekdata(child, addr, data);
 			break;
-		}
 
 		/* Read the word at location address in the USER area. */
 		case PTRACE_PEEKUSR: {
@@ -113,12 +103,7 @@
 		/* Write the word at location address. */
 		case PTRACE_POKETEXT:
 		case PTRACE_POKEDATA:
-			ret = 0;
-			
-			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-				break;
-			
-			ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
  
  		/* Write the word at location address in the USER area. */
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index 1a071f1..e8914d4 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -267,10 +267,10 @@
 
 
 const struct file_operations cryptocop_fops = {
-	owner: THIS_MODULE,
-	open: cryptocop_open,
-	release: cryptocop_release,
-	ioctl: cryptocop_ioctl
+	.owner =	THIS_MODULE,
+	.open =		cryptocop_open,
+	.release =	cryptocop_release,
+	.ioctl =	cryptocop_ioctl
 };
 
 
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 5d6c527..e12f6cc 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -574,10 +574,10 @@
 }
 
 static const struct file_operations i2c_fops = {
-	owner:    THIS_MODULE,
-	ioctl:    i2c_ioctl,
-	open:     i2c_open,
-	release:  i2c_release,
+	.owner =    THIS_MODULE,
+	.ioctl =    i2c_ioctl,
+	.open =     i2c_open,
+	.release =  i2c_release,
 };
 
 int __init
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index 24b919b..fa8d500 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -51,10 +51,10 @@
 int pcf8563_release(struct inode *, struct file *);
 
 static const struct file_operations pcf8563_fops = {
-	owner: THIS_MODULE,
-	ioctl: pcf8563_ioctl,
-	open: pcf8563_open,
-	release: pcf8563_release,
+	.owner =	THIS_MODULE,
+	.ioctl =	pcf8563_ioctl,
+	.open =		pcf8563_open,
+	.release =	pcf8563_release,
 };
 
 unsigned char
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index d4d57b7..38ece0c 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -146,12 +146,7 @@
 		/* Write the word at location address. */
 		case PTRACE_POKETEXT:
 		case PTRACE_POKEDATA:
-			ret = 0;
-
-			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-				break;
-
-			ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
  		/* Write the word at location address in the USER area. */
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 43dc08e..275673c 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1492,6 +1492,10 @@
 	.long sys_move_pages
 	.long sys_getcpu
 	.long sys_epoll_pwait
+	.long sys_utimensat		/* 320 */
+	.long sys_signalfd
+	.long sys_timerfd
+	.long sys_eventfd
 
 
 syscall_table_size = (. - sys_call_table)
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
index 1e7a101..e89cad1 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -647,17 +647,11 @@
 }
 #endif
 
-#ifdef CONFIG_GDBSTUB_CONSOLE
-
-static kdev_t gdbstub_console_dev(struct console *con)
-{
-	return MKDEV(1,3); /* /dev/null */
-}
+#ifdef CONFIG_GDB_CONSOLE
 
 static struct console gdbstub_console = {
 	.name	= "gdb",
 	.write	= gdbstub_console_write,	/* in break.S */
-	.device	= gdbstub_console_dev,
 	.flags	= CON_PRINTBUFFER,
 	.index	= -1,
 };
@@ -2021,7 +2015,7 @@
 	ptr = mem2hex(gdbstub_banner, ptr, sizeof(gdbstub_banner) - 1, 0);
 	gdbstub_send_packet(output_buffer);
 #endif
-#if defined(CONFIG_GDBSTUB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
+#if defined(CONFIG_GDB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
 	register_console(&gdbstub_console);
 #endif
 
@@ -2031,7 +2025,7 @@
 /*
  * register the console at a more appropriate time
  */
-#if defined (CONFIG_GDBSTUB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
+#if defined (CONFIG_GDB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
 static int __init gdbstub_postinit(void)
 {
 	printk("registering console\n");
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index ce88fb9..709e9bd 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -112,20 +112,12 @@
 	switch (request) {
 		/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
-	case PTRACE_PEEKDATA: {
-		int copied;
-
+	case PTRACE_PEEKDATA:
 		ret = -EIO;
 		if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
 			break;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (copied != sizeof(tmp))
-			break;
-
-		ret = put_user(tmp,(unsigned long *) data);
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 		/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -176,9 +168,7 @@
 		ret = -EIO;
 		if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
 			break;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
-			break;
-		ret = 0;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index aa3c795..c1c32e4 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -60,10 +60,6 @@
 static void __init setup_uclinux_memory(void);
 #endif
 
-#ifdef CONFIG_CONSOLE
-extern struct consw *conswitchp;
-#endif
-
 #ifdef CONFIG_MB93090_MB00
 static char __initdata mb93090_banner[] = "FJ/RH FR-V Linux";
 static char __initdata mb93090_version[] = UTS_RELEASE;
@@ -795,13 +791,6 @@
 #endif
 #endif
 
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
-	/* we need to initialize the Flashrom device here since we might
-	 * do things with flash early on in the boot
-	 */
-	flash_probe();
-#endif
-
 	/* deal with the command line - RedBoot may have passed one to the kernel */
 	memcpy(command_line, boot_command_line, sizeof(command_line));
 	*cmdline_p = &command_line[0];
@@ -837,11 +826,6 @@
 #endif
 #endif
 
-#ifdef CONFIG_BLK_DEV_BLKMEM
-	ROOT_DEV = MKDEV(BLKMEM_MAJOR,0);
-#endif
-	/*rom_length = (unsigned long)&_flashend - (unsigned long)&_romvec;*/
-
 #ifdef CONFIG_MMU
 	setup_linux_memory();
 #else
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index 28eae97..481dc13 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -101,13 +101,14 @@
   _stext = .;
   .text : {
 	*(
-		.text.start .text .text.*
+		.text.start .text.*
 #ifdef CONFIG_DEBUG_INFO
 	.init.text
 	.exit.text
 	.exitcall.exit
 #endif
 	)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	*(.fixup)
@@ -135,7 +136,8 @@
 
   _sdata = .;
   .data : {			/* Data */
-	*(.data .data.*)
+	DATA_DATA
+	*(.data.*)
 	*(.exit.data)
 	CONSTRUCTORS
 	}
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 618dbad..e35f74e 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -68,6 +68,9 @@
 config NO_IOPORT
 	def_bool y
 
+config NO_DMA
+	def_bool y
+
 config ISA
 	bool
 	default y
diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile
index b2d896a..53b5c1e 100644
--- a/arch/h8300/Makefile
+++ b/arch/h8300/Makefile
@@ -61,10 +61,11 @@
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
-vmlinux.srec vmlinux.bin: vmlinux
+vmlinux.srec vmlinux.bin zImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 define archhelp
-  echo  'vmlinux.bin  - Create raw binary'
-  echo  'vmlinux.srec - Create srec binary'
+  @echo  'vmlinux.bin  - Create raw binary'
+  @echo  'vmlinux.srec - Create srec binary'
+  @echo  'zImage       - Compressed kernel image'
 endef
diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile
index 71aac82..d6189e0 100644
--- a/arch/h8300/boot/compressed/Makefile
+++ b/arch/h8300/boot/compressed/Makefile
@@ -15,10 +15,10 @@
 # in order to suppress error message.
 #
 CONFIG_MEMORY_START     ?= 0x00400000
-CONFIG_BOOT_LINK_OFFSET ?= 0x00400000
+CONFIG_BOOT_LINK_OFFSET ?= 0x00140000
 IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
 
-LDFLAGS_vmlinux := -T $(obj)/vmlinux.lds
+LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup $(obj)/vmlinux.lds
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S
index b8e90d1..985a81a 100644
--- a/arch/h8300/boot/compressed/head.S
+++ b/arch/h8300/boot/compressed/head.S
@@ -4,7 +4,7 @@
  *  Copyright (C) 2006 Yoshinori Sato
  */
 
-.h8300h
+	.h8300h
 #include <linux/linkage.h>
 
 #define SRAM_START 0xff4000
diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds
new file mode 100644
index 0000000..65e2a0d
--- /dev/null
+++ b/arch/h8300/boot/compressed/vmlinux.lds
@@ -0,0 +1,32 @@
+SECTIONS
+{
+        .text :
+        {
+        __stext = . ;
+	__text = .;
+	       *(.text.startup)
+	       *(.text)
+        __etext = . ;
+        }
+
+	.rodata :
+	{
+		*(.rodata)
+	}
+        .data :
+
+        {
+        __sdata = . ;
+        ___data_start = . ;
+                *(.data.*)
+	}
+        .bss :
+        {
+        . = ALIGN(0x4) ;
+        __sbss = . ;
+                *(.bss*)
+        . = ALIGN(0x4) ;
+        __ebss = . ;
+        __end = . ;
+        }
+}
diff --git a/arch/h8300/boot/compressed/vmlinux.scr b/arch/h8300/boot/compressed/vmlinux.scr
new file mode 100644
index 0000000..a0f6962
--- /dev/null
+++ b/arch/h8300/boot/compressed/vmlinux.scr
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  .data : {
+	_input_len = .;
+	LONG(_input_data_end - _input_data) _input_data = .;
+	*(.data)
+	_input_data_end = .;
+	}
+}
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index ccc1a7f..874f6ae 100644
--- a/arch/h8300/kernel/Makefile
+++ b/arch/h8300/kernel/Makefile
@@ -6,6 +6,7 @@
 
 obj-y := process.o traps.o ptrace.o irq.o \
 	 sys_h8300.o time.o semaphore.o signal.o \
-         setup.o gpio.o init_task.o syscalls.o
+         setup.o gpio.o init_task.o syscalls.o \
+	 entry.o
 
 obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o 
diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S
new file mode 100644
index 0000000..ca74316
--- /dev/null
+++ b/arch/h8300/kernel/entry.S
@@ -0,0 +1,393 @@
+/* -*- mode: asm -*-
+ *
+ *  linux/arch/h8300/platform/h8300h/entry.S
+ *
+ *  Yoshinori Sato <ysato@users.sourceforge.jp>
+ *  David McCullough <davidm@snapgear.com>
+ *
+ */
+
+/*
+ *  entry.S
+ *  include exception/interrupt gateway
+ *          system call entry
+ */
+
+#include <linux/sys.h>
+#include <asm/unistd.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+
+#if defined(CONFIG_CPU_H8300H)
+#define USERRET 8
+INTERRUPTS = 64
+	.h8300h
+	.macro	SHLL2 reg
+	shll.l	\reg
+	shll.l	\reg
+	.endm
+	.macro	SHLR2 reg
+	shlr.l	\reg
+	shlr.l	\reg
+	.endm
+	.macro	SAVEREGS
+	mov.l	er0,@-sp
+	mov.l	er1,@-sp
+	mov.l	er2,@-sp
+	mov.l	er3,@-sp
+	.endm
+	.macro	RESTOREREGS
+	mov.l	@sp+,er3
+	mov.l	@sp+,er2
+	.endm
+	.macro	SAVEEXR
+	.endm
+	.macro	RESTOREEXR
+	.endm
+#endif
+#if defined(CONFIG_CPU_H8S)
+#define USERRET 10
+#define USEREXR 8
+INTERRUPTS = 128
+	.h8300s
+	.macro	SHLL2 reg
+	shll.l	#2,\reg
+	.endm
+	.macro	SHLR2 reg
+	shlr.l	#2,\reg
+	.endm
+	.macro	SAVEREGS
+	stm.l	er0-er3,@-sp
+	.endm
+	.macro	RESTOREREGS
+	ldm.l	@sp+,er2-er3
+	.endm
+	.macro	SAVEEXR
+	mov.w	@(USEREXR:16,er0),r1
+	mov.w	r1,@(LEXR-LER3:16,sp)		/* copy EXR */
+	.endm
+	.macro	RESTOREEXR
+	mov.w	@(LEXR-LER1:16,sp),r1		/* restore EXR */
+	mov.b	r1l,r1h
+	mov.w	r1,@(USEREXR:16,er0)
+	.endm
+#endif
+
+
+/* CPU context save/restore macros. */
+
+	.macro	SAVE_ALL
+	mov.l	er0,@-sp
+	stc	ccr,r0l				/* check kernel mode */
+	btst	#4,r0l
+	bne	5f
+
+	/* user mode */
+	mov.l	sp,@SYMBOL_NAME(sw_usp)
+	mov.l	@sp,er0				/* restore saved er0 */
+	orc	#0x10,ccr			/* switch kernel stack */
+	mov.l	@SYMBOL_NAME(sw_ksp),sp
+	sub.l	#(LRET-LORIG),sp		/* allocate LORIG - LRET */
+	SAVEREGS
+	mov.l   @SYMBOL_NAME(sw_usp),er0
+	mov.l   @(USERRET:16,er0),er1           /* copy the RET addr */
+	mov.l   er1,@(LRET-LER3:16,sp)
+	SAVEEXR
+
+	mov.l	@(LORIG-LER3:16,sp),er0
+	mov.l	er0,@(LER0-LER3:16,sp)		/* copy ER0 */
+	mov.w	e1,r1				/* e1 highbyte = ccr */
+	and	#0xef,r1h			/* mask mode? flag */
+	bra	6f
+5:
+	/* kernel mode */
+	mov.l	@sp,er0				/* restore saved er0 */
+	subs	#2,sp				/* set dummy ccr */
+	SAVEREGS
+	mov.w	@(LRET-LER3:16,sp),r1		/* copy old ccr */
+6:
+	mov.b	r1h,r1l
+	mov.b	#0,r1h
+	mov.w	r1,@(LCCR-LER3:16,sp)		/* set ccr */
+	mov.l	er6,@-sp			/* syscall arg #6 */
+	mov.l	er5,@-sp			/* syscall arg #5 */
+	mov.l	er4,@-sp			/* syscall arg #4 */
+	.endm					/* r1 = ccr */
+
+	.macro	RESTORE_ALL
+	mov.l	@sp+,er4
+	mov.l	@sp+,er5
+	mov.l	@sp+,er6
+	RESTOREREGS
+	mov.w	@(LCCR-LER1:16,sp),r0		/* check kernel mode */
+	btst	#4,r0l
+	bne	7f
+
+	orc	#0x80,ccr
+	mov.l	@SYMBOL_NAME(sw_usp),er0
+	mov.l	@(LER0-LER1:16,sp),er1		/* restore ER0 */
+	mov.l	er1,@er0
+	RESTOREEXR
+	mov.w	@(LCCR-LER1:16,sp),r1		/* restore the RET addr */
+	mov.b	r1l,r1h
+	mov.b	@(LRET+1-LER1:16,sp),r1l
+	mov.w	r1,e1
+	mov.w	@(LRET+2-LER1:16,sp),r1
+	mov.l	er1,@(USERRET:16,er0)
+
+	mov.l	@sp+,er1
+	add.l	#(LRET-LER1),sp			/* remove LORIG - LRET */
+	mov.l	sp,@SYMBOL_NAME(sw_ksp)
+	andc	#0xef,ccr			/* switch to user mode */
+	mov.l	er0,sp
+	bra	8f
+7:
+	mov.l	@sp+,er1
+	adds	#4,sp
+	adds	#2,sp
+8:
+	mov.l	@sp+,er0
+	adds	#4,sp				/* remove the sw created LVEC */
+	rte
+	.endm
+
+.globl SYMBOL_NAME(system_call)
+.globl SYMBOL_NAME(ret_from_exception)
+.globl SYMBOL_NAME(ret_from_fork)
+.globl SYMBOL_NAME(ret_from_interrupt)
+.globl SYMBOL_NAME(interrupt_redirect_table)
+.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
+.globl SYMBOL_NAME(resume)
+.globl SYMBOL_NAME(interrupt_entry)
+.globl SYMBOL_NAME(trace_break)
+
+#if defined(CONFIG_ROMKERNEL)
+	.section .int_redirect,"ax"
+SYMBOL_NAME_LABEL(interrupt_redirect_table)
+#if defined(CONFIG_CPU_H8300H)
+	.rept	7
+	.long	0
+	.endr
+#endif
+#if defined(CONFIG_CPU_H8S)
+	.rept	5
+	.long	0
+	.endr
+	jmp	@SYMBOL_NAME(trace_break)
+	.long	0
+#endif
+
+	jsr	@SYMBOL_NAME(interrupt_entry)	/* NMI */
+	jmp	@SYMBOL_NAME(system_call)	/* TRAPA #0 (System call) */
+	.long	0
+	.long	0
+	jmp	@SYMBOL_NAME(trace_break)	/* TRAPA #3 (breakpoint) */
+	.rept	INTERRUPTS-12
+	jsr	@SYMBOL_NAME(interrupt_entry)
+	.endr
+#endif
+#if defined(CONFIG_RAMKERNEL)
+.globl SYMBOL_NAME(interrupt_redirect_table)
+	.section .bss
+SYMBOL_NAME_LABEL(interrupt_redirect_table)
+	.space	4
+#endif
+
+	.section .text
+	.align	2
+SYMBOL_NAME_LABEL(interrupt_entry)
+	SAVE_ALL
+	mov.l	sp,er0
+	add.l	#LVEC,er0
+	btst	#4,r1l
+	bne	1f
+	/* user LVEC */
+	mov.l	@SYMBOL_NAME(sw_usp),er0
+	adds	#4,er0
+1:
+	mov.l	@er0,er0			/* LVEC address */
+#if defined(CONFIG_ROMKERNEL)
+	sub.l	#SYMBOL_NAME(interrupt_redirect_table),er0
+#endif
+#if defined(CONFIG_RAMKERNEL)
+	mov.l	@SYMBOL_NAME(interrupt_redirect_table),er1
+	sub.l	er1,er0
+#endif
+	SHLR2	er0
+	dec.l	#1,er0
+	mov.l	sp,er1
+	subs	#4,er1				/* adjust ret_pc */
+	jsr	@SYMBOL_NAME(do_IRQ)
+	jmp	@SYMBOL_NAME(ret_from_interrupt)
+
+SYMBOL_NAME_LABEL(system_call)
+	subs	#4,sp				/* dummy LVEC */
+	SAVE_ALL
+	andc	#0x7f,ccr
+	mov.l	er0,er4
+
+	/* save top of frame */
+	mov.l	sp,er0
+	jsr	@SYMBOL_NAME(set_esp0)
+	mov.l	sp,er2
+	and.w	#0xe000,r2
+	mov.b	@((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
+	btst	#(TIF_SYSCALL_TRACE & 7),r2l
+	beq	1f
+	jsr	@SYMBOL_NAME(do_syscall_trace)
+1:
+	cmp.l	#NR_syscalls,er4
+	bcc	badsys
+	SHLL2	er4
+	mov.l	#SYMBOL_NAME(sys_call_table),er0
+	add.l	er4,er0
+	mov.l	@er0,er4
+	beq	SYMBOL_NAME(ret_from_exception):16
+	mov.l	@(LER1:16,sp),er0
+	mov.l	@(LER2:16,sp),er1
+	mov.l	@(LER3:16,sp),er2
+	jsr	@er4
+	mov.l	er0,@(LER0:16,sp)		/* save the return value */
+	mov.l	sp,er2
+	and.w	#0xe000,r2
+	mov.b	@((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
+	btst	#(TIF_SYSCALL_TRACE & 7),r2l
+	beq	2f
+	jsr	@SYMBOL_NAME(do_syscall_trace)
+2:
+#if defined(CONFIG_SYSCALL_PRINT)
+	jsr	@SYMBOL_NAME(syscall_print)
+#endif
+	orc	#0x80,ccr
+	bra	resume_userspace
+
+badsys:
+	mov.l	#-ENOSYS,er0
+	mov.l	er0,@(LER0:16,sp)
+	bra	resume_userspace
+
+#if !defined(CONFIG_PREEMPT)
+#define resume_kernel restore_all
+#endif
+
+SYMBOL_NAME_LABEL(ret_from_exception)
+#if defined(CONFIG_PREEMPT)
+	orc	#0x80,ccr
+#endif
+SYMBOL_NAME_LABEL(ret_from_interrupt)
+	mov.b	@(LCCR+1:16,sp),r0l
+	btst	#4,r0l
+	bne	resume_kernel:8		/* return from kernel */
+resume_userspace:
+	andc	#0x7f,ccr
+	mov.l	sp,er4
+	and.w	#0xe000,r4		/* er4 <- current thread info */
+	mov.l	@(TI_FLAGS:16,er4),er1
+	and.l	#_TIF_WORK_MASK,er1
+	beq	restore_all:8
+work_pending:
+	btst	#TIF_NEED_RESCHED,r1l
+	bne	work_resched:8
+	/* work notifysig */
+	mov.l	sp,er0
+	subs	#4,er0			/* er0: pt_regs */
+	jsr	@SYMBOL_NAME(do_notify_resume)
+	bra	restore_all:8
+work_resched:
+	mov.l	sp,er0
+	jsr	@SYMBOL_NAME(set_esp0)
+	jsr	@SYMBOL_NAME(schedule)
+	bra	resume_userspace:8
+restore_all:
+	RESTORE_ALL			/* Does RTE */
+
+#if defined(CONFIG_PREEMPT)
+resume_kernel:
+	mov.l	@(TI_PRE_COUNT:16,er4),er0
+	bne	restore_all:8
+need_resched:
+	mov.l	@(TI_FLAGS:16,er4),er0
+	btst	#TIF_NEED_RESCHED,r0l
+	beq	restore_all:8
+	mov.b	@(LCCR+1:16,sp),r0l	/* Interrupt Enabled? */
+	bmi	restore_all:8
+	mov.l	#PREEMPT_ACTIVE,er0
+	mov.l	er0,@(TI_PRE_COUNT:16,er4)
+	andc	#0x7f,ccr
+	mov.l	sp,er0
+	jsr	@SYMBOL_NAME(set_esp0)
+	jsr	@SYMBOL_NAME(schedule)
+	orc	#0x80,ccr
+	bra	need_resched:8
+#endif
+
+SYMBOL_NAME_LABEL(ret_from_fork)
+	mov.l	er2,er0
+	jsr	@SYMBOL_NAME(schedule_tail)
+	jmp	@SYMBOL_NAME(ret_from_exception)
+
+SYMBOL_NAME_LABEL(resume)
+	/*
+	 * Beware - when entering resume, offset of tss is in d1,
+	 * prev (the current task) is in a0, next (the new task)
+	 * is in a1 and d2.b is non-zero if the mm structure is
+	 * shared between the tasks, so don't change these
+	 * registers until their contents are no longer needed.
+	 */
+
+	/* save sr */
+	sub.w	r3,r3
+	stc	ccr,r3l
+	mov.w	r3,@(THREAD_CCR+2:16,er0)
+
+	/* disable interrupts */
+	orc	#0x80,ccr
+	mov.l	@SYMBOL_NAME(sw_usp),er3
+	mov.l	er3,@(THREAD_USP:16,er0)
+	mov.l	sp,@(THREAD_KSP:16,er0)
+
+	/* Skip address space switching if they are the same. */
+	/* FIXME: what did we hack out of here, this does nothing! */
+
+	mov.l	@(THREAD_USP:16,er1),er0
+	mov.l	er0,@SYMBOL_NAME(sw_usp)
+	mov.l	@(THREAD_KSP:16,er1),sp
+
+	/* restore status register */
+	mov.w	@(THREAD_CCR+2:16,er1),r3
+
+	ldc	r3l,ccr
+	rts
+
+SYMBOL_NAME_LABEL(trace_break)
+	subs	#4,sp
+	SAVE_ALL
+	sub.l	er1,er1
+	dec.l	#1,er1
+	mov.l	er1,@(LORIG,sp)
+	mov.l	sp,er0
+	jsr	@SYMBOL_NAME(set_esp0)
+	mov.l	@SYMBOL_NAME(sw_usp),er0
+	mov.l	@er0,er1
+	mov.w	@(-2:16,er1),r2
+	cmp.w	#0x5730,r2
+	beq	1f
+	subs	#2,er1
+	mov.l	er1,@er0
+1:
+	and.w	#0xff,e1
+	mov.l	er1,er0
+	jsr	@SYMBOL_NAME(trace_trap)
+	jmp	@SYMBOL_NAME(ret_from_exception)
+
+	.section	.bss
+SYMBOL_NAME_LABEL(sw_ksp)
+	.space	4
+SYMBOL_NAME_LABEL(sw_usp)
+	.space	4
+
+	.end
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
deleted file mode 100644
index 3e4f479..0000000
--- a/arch/h8300/kernel/ints.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * linux/arch/h8300/kernel/ints.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- * Copyright 1996 Roman Zippel
- * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <linux/bootmem.h>
-#include <linux/hardirq.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/traps.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/errno.h>
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-typedef struct irq_handler {
-	irqreturn_t (*handler)(int, void *, struct pt_regs *);
-	int         flags;
-	int         count;
-	void	    *dev_id;
-	const char  *devname;
-} irq_handler_t;
-
-static irq_handler_t *irq_list[NR_IRQS];
-static int use_kmalloc;
-
-extern unsigned long *interrupt_redirect_table;
-extern const int h8300_saved_vectors[];
-extern const unsigned long h8300_trap_table[];
-int h8300_enable_irq_pin(unsigned int irq);
-void h8300_disable_irq_pin(unsigned int irq);
-
-#define CPU_VECTOR ((unsigned long *)0x000000)
-#define ADDR_MASK (0xffffff)
-
-#if defined(CONFIG_RAMKERNEL)
-static unsigned long __init *get_vector_address(void)
-{
-	unsigned long *rom_vector = CPU_VECTOR;
-	unsigned long base,tmp;
-	int vec_no;
-
-	base = rom_vector[EXT_IRQ0] & ADDR_MASK;
-	
-	/* check romvector format */
-	for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
-		if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
-			return NULL;
-	}
-
-	/* ramvector base address */
-	base -= EXT_IRQ0*4;
-
-	/* writerble check */
-	tmp = ~(*(volatile unsigned long *)base);
-	(*(volatile unsigned long *)base) = tmp;
-	if ((*(volatile unsigned long *)base) != tmp)
-		return NULL;
-	return (unsigned long *)base;
-}
-#endif
-
-void __init init_IRQ(void)
-{
-#if defined(CONFIG_RAMKERNEL)
-	int i;
-	unsigned long *ramvec,*ramvec_p;
-	const unsigned long *trap_entry;
-	const int *saved_vector;
-
-	ramvec = get_vector_address();
-	if (ramvec == NULL)
-		panic("interrupt vector serup failed.");
-	else
-		printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
-
-	/* create redirect table */
-	ramvec_p = ramvec;
-	trap_entry = h8300_trap_table;
-	saved_vector = h8300_saved_vectors;
-	for ( i = 0; i < NR_IRQS; i++) {
-		if (i == *saved_vector) {
-			ramvec_p++;
-			saved_vector++;
-		} else {
-			if ( i < NR_TRAPS ) {
-				if (*trap_entry)
-					*ramvec_p = VECTOR(*trap_entry);
-				ramvec_p++;
-				trap_entry++;
-			} else
-				*ramvec_p++ = REDIRECT(interrupt_entry);
-		}
-	}
-	interrupt_redirect_table = ramvec;
-#ifdef DUMP_VECTOR
-	ramvec_p = ramvec;
-	for (i = 0; i < NR_IRQS; i++) {
-		if ((i % 8) == 0)
-			printk(KERN_DEBUG "\n%p: ",ramvec_p);
-		printk(KERN_DEBUG "%p ",*ramvec_p);
-		ramvec_p++;
-	}
-	printk(KERN_DEBUG "\n");
-#endif
-#endif
-}
-
-int request_irq(unsigned int irq, 
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                unsigned long flags, const char *devname, void *dev_id)
-{
-	irq_handler_t *irq_handle;
-	if (irq < 0 || irq >= NR_IRQS) {
-		printk(KERN_ERR "Incorrect IRQ %d from %s\n", irq, devname);
-		return -EINVAL;
-	}
-
-	if (irq_list[irq] || (h8300_enable_irq_pin(irq) == -EBUSY))
-		return -EBUSY;
-
-	if (use_kmalloc)
-		irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
-	else {
-		/* use bootmem allocater */
-		irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
-		irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000);
-	}
-
-	if (irq_handle == NULL)
-		return -ENOMEM;
-
-	irq_handle->handler = handler;
-	irq_handle->flags   = flags;
-	irq_handle->count   = 0;
-	irq_handle->dev_id  = dev_id;
-	irq_handle->devname = devname;
-	irq_list[irq] = irq_handle;
-
-	if (irq_handle->flags & IRQF_SAMPLE_RANDOM)
-		rand_initialize_irq(irq);
-
-	enable_irq(irq);
-	return 0;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	if (irq >= NR_IRQS)
-		return;
-
-	if (!irq_list[irq] || irq_list[irq]->dev_id != dev_id)
-		printk(KERN_WARNING "Removing probably wrong IRQ %d from %s\n",
-		       irq, irq_list[irq]->devname);
-	disable_irq(irq);
-	h8300_disable_irq_pin(irq);
-	if (((unsigned long)irq_list[irq] & 0x80000000) == 0) {
-		kfree(irq_list[irq]);
-		irq_list[irq] = NULL;
-	}
-}
-
-EXPORT_SYMBOL(free_irq);
-
-/*
- * Do we need these probe functions on the m68k?
- */
-unsigned long probe_irq_on (void)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-int probe_irq_off (unsigned long irqs)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-void enable_irq(unsigned int irq)
-{
-	if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS))
-		IER_REGS |= 1 << (irq - EXT_IRQ0);
-}
-
-void disable_irq(unsigned int irq)
-{
-	if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS))
-		IER_REGS &= ~(1 << (irq - EXT_IRQ0));
-}
-
-asmlinkage void process_int(int irq, struct pt_regs *fp)
-{
-	irq_enter();
-	h8300_clear_isr(irq);
-	if (irq >= NR_TRAPS && irq < NR_IRQS) {
-		if (irq_list[irq]) {
-			irq_list[irq]->handler(irq, irq_list[irq]->dev_id, fp);
-			irq_list[irq]->count++;
-			if (irq_list[irq]->flags & IRQF_SAMPLE_RANDOM)
-				add_interrupt_randomness(irq);
-		}
-	} else {
-		BUG();
-	}
-	irq_exit();
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v;
-
-	if ((i < NR_IRQS) && (irq_list[i]!=NULL)) {
-		seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
-		seq_printf(p, "%s\n", irq_list[i]->devname);
-	}
-
-	return 0;
-}
-
-void init_irq_proc(void)
-{
-}
-
-static int __init enable_kmalloc(void)
-{
-	use_kmalloc = 1;
-	return 0;
-}
-core_initcall(enable_kmalloc);
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index 8f2411d..d32bbf0 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -111,10 +111,7 @@
       /* when I and D space are separate, this will have to be fixed. */
 		case PTRACE_POKETEXT: /* write the word at location addr. */
 		case PTRACE_POKEDATA:
-			ret = 0;
-			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-				break;
-			ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
 		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
@@ -219,7 +216,7 @@
 	return ret;
 }
 
-asmlinkage void syscall_trace(void)
+asmlinkage void do_syscall_trace(void)
 {
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return;
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 0295560..62ea12d 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -547,3 +547,9 @@
 	}
 	return 0;
 }
+
+asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
+{
+	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+		do_signal(regs, NULL);
+}
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
index 11ba75a..de7688c 100644
--- a/arch/h8300/kernel/sys_h8300.c
+++ b/arch/h8300/kernel/sys_h8300.c
@@ -288,9 +288,9 @@
 int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 {
 	register long res __asm__("er0");
+	register char *const *_c __asm__("er3") = envp;
+	register char *const *_b __asm__("er2") = argv;
 	register const char * _a __asm__("er1") = filename;
-	register void *_b __asm__("er2") = argv;
-	register void *_c __asm__("er3") = envp;
 	__asm__ __volatile__ ("mov.l %1,er0\n\t"
 			"trapa	#0\n\t"
 			: "=r" (res)
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c
index 300e327..f971830 100644
--- a/arch/h8300/kernel/traps.c
+++ b/arch/h8300/kernel/traps.c
@@ -136,7 +136,7 @@
 	printk("\nCall Trace:");
 	i = 0;
 	stack = esp;
-	while (((unsigned long)stack & (THREAD_SIZE - 1)) == 0) {
+	while (((unsigned long)stack & (THREAD_SIZE - 1)) != 0) {
 		addr = *stack++;
 		/*
 		 * If the address is either in the text segment of the
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
index 65f1cdc..a2e72d4 100644
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ b/arch/h8300/kernel/vmlinux.lds.S
@@ -75,7 +75,7 @@
 	*(.int_redirect)
 #endif
 	__stext = . ;
-        	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	__etext = . ;
@@ -103,7 +103,7 @@
 	. = ALIGN(0x2000) ;
 		*(.data.init_task)
 	. = ALIGN(0x4) ;
-		*(.data)
+		DATA_DATA
 	. = ALIGN(0x4) ;
 		*(.data.*)	
 
diff --git a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile
index b24ea08..c509636 100644
--- a/arch/h8300/platform/h8300h/Makefile
+++ b/arch/h8300/platform/h8300h/Makefile
@@ -4,4 +4,4 @@
 # Reuse any files we can from the H8/300H
 #
 
-obj-y := entry.o irq_pin.o ptrace_h8300h.o
+obj-y := irq_pin.o ptrace_h8300h.o
diff --git a/arch/h8300/platform/h8300h/entry.S b/arch/h8300/platform/h8300h/entry.S
deleted file mode 100644
index f86ac3b..0000000
--- a/arch/h8300/platform/h8300h/entry.S
+++ /dev/null
@@ -1,332 +0,0 @@
-/* -*- mode: asm -*-
- *
- *  linux/arch/h8300/platform/h8300h/entry.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *  David McCullough <davidm@snapgear.com>
- *
- */
-
-/*
- *  entry.S
- *  include exception/interrupt gateway
- *          system call entry
- */
-
-#include <linux/sys.h>
-#include <asm/unistd.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/errno.h>
-
-	.h8300h
-
-/* CPU context save/restore macros. */
-	
-	.macro	SAVE_ALL
-	mov.l	er0,@-sp
-
-	stc	ccr,r0l				/* check kernel mode */
-	btst	#4,r0l
-	bne	5f
-
-	mov.l	sp,@SYMBOL_NAME(sw_usp)		/* user mode */
-	mov.l	@sp,er0
-	orc	#0x10,ccr
-	mov.l	@SYMBOL_NAME(sw_ksp),sp
-	sub.l	#(LRET-LORIG),sp		/* allocate LORIG - LRET */ 
-	mov.l	er0,@-sp
-	mov.l	er1,@-sp
-	mov.l   @SYMBOL_NAME(sw_usp),er0
-	mov.l   @(8:16,er0),er1                 /* copy the RET addr */
-	mov.l   er1,@(LRET-LER1:16,sp)
-
-	mov.w	e1,r1				/* e1 highbyte = ccr */
-	and	#0xef,r1h			/* mask mode? flag */
-	sub.w	r0,r0
-	mov.b	r1h,r0l
-	mov.w	r0,@(LCCR-LER1:16,sp)		/* copy ccr */
-	mov.l	@(LORIG-LER1:16,sp),er0
-	mov.l	er0,@(LER0-LER1:16,sp)		/* copy ER0 */
-	bra	6f
-5:
-	mov.l	@sp,er0				/* kernel mode */
-	subs	#2,sp				/* dummy ccr */
-	mov.l	er0,@-sp
-	mov.l	er1,@-sp
-	mov.w	@(LRET-LER1:16,sp),r1		/* copy old ccr */
-	mov.b	r1h,r1l
-	mov.b	#0,r1h
-	mov.w	r1,@(LCCR-LER1:16,sp)		/* set ccr */
-6:
-	mov.l	er2,@-sp
-	mov.l	er3,@-sp
-	mov.l	er6,@-sp			/* syscall arg #6 */
-	mov.l	er5,@-sp			/* syscall arg #5 */
-	mov.l	er4,@-sp			/* syscall arg #4 */
-	.endm
-
-	.macro	RESTORE_ALL
-	mov.l	@sp+,er4
-	mov.l	@sp+,er5
-	mov.l	@sp+,er6
-	mov.l	@sp+,er3
-	mov.l	@sp+,er2
-	mov.w	@(LCCR-LER1:16,sp),r0		/* check kernel mode */
-	btst	#4,r0l
-	bne	7f
-
-	orc	#0x80,ccr
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(LER0-LER1:16,sp),er1		/* restore ER0 */
-	mov.l	er1,@er0
-	mov.w	@(LCCR-LER1:16,sp),r1		/* restore the RET addr */
-	mov.b	r1l,r1h
-	mov.b	@(LRET+1-LER1:16,sp),r1l
-	mov.w	r1,e1
-	mov.w	@(LRET+2-LER1:16,sp),r1
-	mov.l	er1,@(8:16,er0)
-
-	mov.l	@sp+,er1
-	add.l	#(LRET-LER1),sp			/* remove LORIG - LRET */ 
-	mov.l	sp,@SYMBOL_NAME(sw_ksp)
-	mov.l	er0,sp
-	bra	8f
-7:
-	mov.l	@sp+,er1
-	adds	#4,sp
-	adds	#2,sp
-8:
-	mov.l	@sp+,er0
-	adds	#4,sp				/* remove the sw created LVEC */
-	rte
-	.endm
-	
-.globl SYMBOL_NAME(system_call)
-.globl SYMBOL_NAME(ret_from_exception)
-.globl SYMBOL_NAME(ret_from_fork)
-.globl SYMBOL_NAME(ret_from_interrupt)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
-.globl SYMBOL_NAME(resume)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-.globl SYMBOL_NAME(interrupt_entry)
-.globl SYMBOL_NAME(system_call)
-.globl SYMBOL_NAME(trace_break)
-
-#if defined(CONFIG_ROMKERNEL)
-INTERRUPTS = 64		
-	.section .int_redirect,"ax"
-SYMBOL_NAME_LABEL(interrupt_redirect_table)
-	.rept	7
-	.long	0
-	.endr
-	jsr	@SYMBOL_NAME(interrupt_entry)	/* NMI */
-	jmp	@SYMBOL_NAME(system_call)	/* TRAPA #0 (System call) */
-	.long	0
-	.long	0
-	jmp	@SYMBOL_NAME(trace_break)	/* TRAPA #3 (breakpoint) */
-	.rept	INTERRUPTS-12
-	jsr	@SYMBOL_NAME(interrupt_entry)
-	.endr
-#endif
-#if defined(CONFIG_RAMKERNEL)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-	.section .bss
-SYMBOL_NAME_LABEL(interrupt_redirect_table)
-	.space	4
-#endif
-
-	.section .text
-	.align	2
-SYMBOL_NAME_LABEL(interrupt_entry)
-	SAVE_ALL
-	mov.w	@(LCCR,sp),r0
-	btst	#4,r0l
-	bne	1f
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(4:16,er0),er0
-	bra	2f
-1:
-	mov.l	@(LVEC,sp),er0
-2:
-#if defined(CONFIG_ROMKERNEL)
-	sub.l	#SYMBOL_NAME(interrupt_redirect_table),er0
-#endif
-#if defined(CONFIG_RAMKERNEL)
-	mov.l	@SYMBOL_NAME(interrupt_redirect_table),er1
-	sub.l	er1,er0
-#endif
-	shlr.l	er0
-	shlr.l	er0
-	dec.l	#1,er0
-	mov.l	sp,er1
-	subs	#4,er1				/* adjust ret_pc */
-	jsr	@SYMBOL_NAME(do_IRQ)
-	mov.l	@SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
-	beq	1f
-	jsr	@SYMBOL_NAME(do_softirq)
-1:
-	jmp	@SYMBOL_NAME(ret_from_interrupt)
-	
-SYMBOL_NAME_LABEL(system_call)
-	subs	#4,sp				/* dummy LVEC */
-	SAVE_ALL
-	mov.w	@(LCCR:16,sp),r1
-	bset	#4,r1l
-	ldc	r1l,ccr
-	mov.l	er0,er4
-	mov.l	#-ENOSYS,er0
-	mov.l	er0,@(LER0:16,sp)
-
-	/* save top of frame */
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	cmp.l	#NR_syscalls,er4
-	bcc	SYMBOL_NAME(ret_from_exception):16
-	shll.l	er4
-	shll.l	er4
-	mov.l	#SYMBOL_NAME(sys_call_table),er0
-	add.l	er4,er0
-	mov.l	@er0,er4
-	beq	SYMBOL_NAME(ret_from_exception):16	
-	mov.l	sp,er2
-	and.w	#0xe000,r2
-	mov.b	@((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
-	btst	#(TIF_SYSCALL_TRACE & 7),r2l
-	bne	1f
-	mov.l	@(LER1:16,sp),er0
-	mov.l	@(LER2:16,sp),er1
-	mov.l	@(LER3:16,sp),er2
-	jsr	@er4
-	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-#if defined(CONFIG_SYSCALL_PRINT)
-	jsr	@SYMBOL_NAME(syscall_print)
-#endif
-	bra	SYMBOL_NAME(ret_from_exception):8
-1:
-	jsr	SYMBOL_NAME(syscall_trace)
-	mov.l	@(LER1:16,sp),er0
-	mov.l	@(LER2:16,sp),er1
-	mov.l	@(LER3:16,sp),er2
-	jsr	@er4
-	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-	jsr	@SYMBOL_NAME(syscall_trace)
-	bra	SYMBOL_NAME(ret_from_exception):8
-
-SYMBOL_NAME_LABEL(ret_from_fork)
-	mov.l	er2,er0
-	jsr	@SYMBOL_NAME(schedule_tail)
-	bra	SYMBOL_NAME(ret_from_exception):8
-
-SYMBOL_NAME_LABEL(reschedule)
-	/* save top of frame */
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	jsr	@SYMBOL_NAME(schedule)
-
-SYMBOL_NAME_LABEL(ret_from_exception)
-#if defined(CONFIG_PREEMPT)
-	orc	#0x80,ccr
-#endif
-SYMBOL_NAME_LABEL(ret_from_interrupt)
-	mov.b	@(LCCR+1:16,sp),r0l
-	btst	#4,r0l			/* check if returning to kernel */
-	bne	done:8			/* if so, skip resched, signals */
-	andc	#0x7f,ccr
-	mov.l	sp,er4
-	and.w	#0xe000,r4
-	mov.l	@(TI_FLAGS:16,er4),er1
-	and.l	#_TIF_WORK_MASK,er1
-	beq	done:8
-1:
-	mov.l	@(TI_FLAGS:16,er4),er1
-	btst	#TIF_NEED_RESCHED,r1l
-	bne	SYMBOL_NAME(reschedule):16
-	mov.l	sp,er0
-	subs	#4,er0			/* adjust retpc */
-	mov.l	er2,er1
-	jsr	@SYMBOL_NAME(do_signal)
-#if defined(CONFIG_PREEMPT)
-	bra	done:8			/* userspace thoru */
-3:
-	btst	#4,r0l
-	beq	done:8			/* userspace thoru */
-4:
-	mov.l	@(TI_PRE_COUNT:16,er4),er1
-	bne	done:8
-	mov.l	@(TI_FLAGS:16,er4),er1
-	btst	#TIF_NEED_RESCHED,r1l
-	beq	done:8
-	mov.b	r0l,r0l
-	bpl	done:8			/* interrupt off (exception path?) */
-	mov.l	#PREEMPT_ACTIVE,er1
-	mov.l	er1,@(TI_PRE_COUNT:16,er4)
-	andc	#0x7f,ccr
-	jsr	@SYMBOL_NAME(schedule)
-	sub.l	er1,er1
-	mov.l	er1,@(TI_PRE_COUNT:16,er4)
-	orc	#0x80,ccr
-	bra	4b:8
-#endif
-done:
-	RESTORE_ALL			/* Does RTE */
-
-SYMBOL_NAME_LABEL(resume)
-	/*
-	 * Beware - when entering resume, offset of tss is in d1,
-	 * prev (the current task) is in a0, next (the new task)
-	 * is in a1 and d2.b is non-zero if the mm structure is
-	 * shared between the tasks, so don't change these
-	 * registers until their contents are no longer needed.
-	 */
-
-	/* save sr */
-	sub.w	r3,r3
-	stc	ccr,r3l
-	mov.w	r3,@(THREAD_CCR+2:16,er0)
-
-	/* disable interrupts */
-	orc	#0x80,ccr
-	mov.l	@SYMBOL_NAME(sw_usp),er3
-	mov.l	er3,@(THREAD_USP:16,er0)
-	mov.l	sp,@(THREAD_KSP:16,er0)
-
-	/* Skip address space switching if they are the same. */
-	/* FIXME: what did we hack out of here, this does nothing! */
-
-	mov.l	@(THREAD_USP:16,er1),er0
-	mov.l	er0,@SYMBOL_NAME(sw_usp)
-	mov.l	@(THREAD_KSP:16,er1),sp
-			
-	/* restore status register */
-	mov.w	@(THREAD_CCR+2:16,er1),r3
-
-	ldc	r3l,ccr
-	rts
-	
-SYMBOL_NAME_LABEL(trace_break)
-	subs	#4,sp
-	SAVE_ALL
-	sub.l	er1,er1
-	dec.l	#1,er1
-	mov.l	er1,@(LORIG,sp)	
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@er0,er1
-	subs	#2,er1
-	mov.l	er1,@er0	
-	and.w	#0xff,e1
-	mov.l	er1,er0
-	jsr	@SYMBOL_NAME(trace_trap)
-	jmp	@SYMBOL_NAME(ret_from_exception)	
-
-	.section	.bss
-SYMBOL_NAME_LABEL(sw_ksp)
-	.space	4	
-SYMBOL_NAME_LABEL(sw_usp)
-	.space	4	
diff --git a/arch/h8300/platform/h8s/Makefile b/arch/h8300/platform/h8s/Makefile
index 0847b15..bf12418 100644
--- a/arch/h8300/platform/h8s/Makefile
+++ b/arch/h8300/platform/h8s/Makefile
@@ -4,4 +4,4 @@
 # Reuse any files we can from the H8S
 #
 
-obj-y := entry.o ints_h8s.o ptrace_h8s.o
+obj-y := ints_h8s.o ptrace_h8s.o
diff --git a/arch/h8300/platform/h8s/entry.S b/arch/h8300/platform/h8s/entry.S
deleted file mode 100644
index f3d6b8e..0000000
--- a/arch/h8300/platform/h8s/entry.S
+++ /dev/null
@@ -1,331 +0,0 @@
-/* -*- mode: asm -*-
- *
- *  linux/arch/h8300/platform/h8s/entry.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *	fairly heavy changes to fix syscall args and signal processing
- *	by David McCullough <davidm@snapgear.com>
- */
-
-/*
- *  entry.S
- *  include exception/interrupt gateway
- *          system call entry
- */
-
-#include <linux/sys.h>
-#include <asm/unistd.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/errno.h>
-
-	.h8300s
-
-/* CPU context save/restore macros. */
-	
-	.macro	SAVE_ALL
-	mov.l	er0,@-sp
-
-	stc	ccr,r0l				/* check kernel mode */
-	btst	#4,r0l
-	bne	5f
-
-	/* user mode */
-	mov.l	sp,@SYMBOL_NAME(sw_usp)
-	mov.l	@sp,er0				/* restore saved er0 */
-	orc	#0x10,ccr			/* switch kernel stack */
-	mov.l	@SYMBOL_NAME(sw_ksp),sp
-	sub.l	#(LRET-LORIG),sp		/* allocate LORIG - LRET */ 
-	stm.l	er0-er3,@-sp
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(10:16,er0),er1		/* copy the RET addr */
-	mov.l	er1,@(LRET-LER3:16,sp)
-	mov.w	@(8:16,er0),r1
-	mov.w	r1,@(LEXR-LER3:16,sp)		/* copy EXR */
-
-	mov.w	e1,r1				/* e1 highbyte = ccr */
-	and	#0xef,r1h			/* mask mode? flag */
-	sub.w	r0,r0
-	mov.b	r1h,r0l
-	mov.w	r0,@(LCCR-LER3:16,sp)		/* copy ccr */
-	mov.l	@(LORIG-LER3:16,sp),er0
-	mov.l	er0,@(LER0-LER3:16,sp)		/* copy ER0 */
-	bra	6f
-5:
-	/* kernel mode */
-	mov.l	@sp,er0				/* restore saved er0 */
-	subs	#2,sp				/* set dummy ccr */
-	stm.l	er0-er3,@-sp
-	mov.w	@(LRET-LER3:16,sp),r1		/* copy old ccr */
-	mov.b	r1h,r1l
-	mov.b	#0,r1h
-	mov.w	r1,@(LCCR-LER3:16,sp)
-6:	
-	mov.l	er6,@-sp			/* syscall arg #6 */
-	mov.l	er5,@-sp			/* syscall arg #5 */
-	mov.l	er4,@-sp			/* syscall arg #4 */
-	.endm
-
-	.macro	RESTORE_ALL
-	mov.l	@sp+,er4
-	mov.l	@sp+,er5
-	mov.l	@sp+,er6
-	ldm.l	@sp+,er2-er3
-	mov.w	@(LCCR-LER1:16,sp),r0		/* check kernel mode */
-	btst	#4,r0l
-	bne	7f
-
-	orc	#0x80,ccr
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(LER0-LER1:16,sp),er1		/* restore ER0 */
-	mov.l	er1,@er0
-	mov.w	@(LEXR-LER1:16,sp),r1		/* restore EXR */
-	mov.b	r1l,r1h
-	mov.w	r1,@(8:16,er0)
-	mov.w	@(LCCR-LER1:16,sp),r1		/* restore the RET addr */
-	mov.b	r1l,r1h
-	mov.b	@(LRET+1-LER1:16,sp),r1l
-	mov.w	r1,e1
-	mov.w	@(LRET+2-LER1:16,sp),r1
-	mov.l	er1,@(10:16,er0)
-
-	mov.l	@sp+,er1
-	add.l	#(LRET-LER1),sp			/* remove LORIG - LRET */ 
-	mov.l	sp,@SYMBOL_NAME(sw_ksp)
-	andc	#0xef,ccr			/* switch to user mode */
-	mov.l	er0,sp
-	bra	8f
-7:
-	mov.l	@sp+,er1
-	adds	#4,sp
-	adds	#2,sp
-8:
-	mov.l	@sp+,er0
-	adds	#4,sp				/* remove the sw created LVEC */
-	rte
-	.endm
-	
-.globl SYMBOL_NAME(system_call)
-.globl SYMBOL_NAME(ret_from_exception)
-.globl SYMBOL_NAME(ret_from_fork)
-.globl SYMBOL_NAME(ret_from_interrupt)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
-.globl SYMBOL_NAME(resume)
-.globl SYMBOL_NAME(trace_break)
-.globl SYMBOL_NAME(interrupt_entry)
-		
-INTERRUPTS = 128
-#if defined(CONFIG_ROMKERNEL)
-	.section .int_redirect,"ax"
-SYMBOL_NAME_LABEL(interrupt_redirect_table)
-	.rept	7
-	.long	0
-	.endr
-	jsr	@SYMBOL_NAME(interrupt_entry)	/* NMI */
-	jmp	@SYMBOL_NAME(system_call)	/* TRAPA #0 (System call) */
-	.long	0
-	.long	0
-	jmp	@SYMBOL_NAME(trace_break)	/* TRAPA #3 (breakpoint) */
-	.rept	INTERRUPTS-12
-	jsr	@SYMBOL_NAME(interrupt_entry)
-	.endr
-#endif
-#if defined(CONFIG_RAMKERNEL)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-	.section .bss
-SYMBOL_NAME_LABEL(interrupt_redirect_table)
-	.space	4
-#endif
-	
-	.section .text
-	.align	2
-SYMBOL_NAME_LABEL(interrupt_entry)
-	SAVE_ALL
-	mov.w	@(LCCR,sp),r0
-	btst	#4,r0l
-	bne	1f
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@(4:16,er0),er0
-	bra	2f
-1:
-	mov.l	@(LVEC:16,sp),er0
-2:
-#if defined(CONFIG_ROMKERNEL)
-	sub.l	#SYMBOL_NAME(interrupt_redirect_table),er0
-#endif
-#if defined(CONFIG_RAMKERNEL)
-	mov.l	@SYMBOL_NAME(interrupt_redirect_table),er1
-	sub.l	er1,er0
-#endif
-	shlr.l	#2,er0
-	dec.l	#1,er0
-	mov.l	sp,er1
-	subs	#4,er1				/* adjust ret_pc */
-	jsr	@SYMBOL_NAME(process_int)
-	mov.l	@SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
-	beq	1f
-	jsr	@SYMBOL_NAME(do_softirq)
-1:
-	jmp	@SYMBOL_NAME(ret_from_exception)
-
-SYMBOL_NAME_LABEL(system_call)
-	subs	#4,sp				/* dummy LVEC */
-	SAVE_ALL
-	mov.l	er0,er4
-	mov.l	#-ENOSYS,er0
-	mov.l	er0,@(LER0:16,sp)
-
-	/* save top of frame */
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	cmp.l	#NR_syscalls,er4
-	bcc	SYMBOL_NAME(ret_from_exception):16
-	shll.l	#2,er4
-	mov.l	#SYMBOL_NAME(sys_call_table),er0
-	add.l	er4,er0
-	mov.l	@er0,er0
-	mov.l	er0,er4
-	beq	SYMBOL_NAME(ret_from_exception):16	
-	mov.l	sp,er2
-	and.w	#0xe000,r2
-	mov.b	@((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
-	btst	#(TIF_SYSCALL_TRACE & 7),r2l
-	mov.l	@(LER1:16,sp),er0
-	mov.l	@(LER2:16,sp),er1
-	mov.l	@(LER3:16,sp),er2
-	andc	#0x7f,ccr
-	jsr	@er4
-	mov.l	er0,@(LER0:16,sp)			/* save the return value */
-#if defined(CONFIG_SYSCALL_PRINT)
-	jsr	@SYMBOL_NAME(syscall_print)
-#endif
-	bra	SYMBOL_NAME(ret_from_exception):8
-1:
-	jsr	SYMBOL_NAME(syscall_trace)
-	mov.l	@(LER1:16,sp),er0
-	mov.l	@(LER2:16,sp),er1
-	mov.l	@(LER3:16,sp),er2
-	jsr	@er4
-	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-	jsr	@SYMBOL_NAME(syscall_trace)
-	bra	SYMBOL_NAME(ret_from_exception):8
-
-SYMBOL_NAME_LABEL(ret_from_fork)
-	mov.l	er2,er0
-	jsr	@SYMBOL_NAME(schedule_tail)
-	bra	SYMBOL_NAME(ret_from_exception):8
-
-SYMBOL_NAME_LABEL(reschedule)
-	/* save top of frame */
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	jsr	@SYMBOL_NAME(schedule)
-
-SYMBOL_NAME_LABEL(ret_from_exception)
-#if defined(CONFIG_PREEMPT)
-	orc	#0x80,ccr
-#endif
-SYMBOL_NAME_LABEL(ret_from_interrupt)
-	mov.b	@(LCCR+1:16,sp),r0l
-	btst	#4,r0l			/* check if returning to kernel */
-	bne	done:8			/* if so, skip resched, signals */
-	andc	#0x7f,ccr
-	mov.l	sp,er4
-	and.w	#0xe000,r4
-	mov.l	@(TI_FLAGS:16,er4),er1
-	and.l	#_TIF_WORK_MASK,er1
-	beq	done:8
-1:
-	mov.l	@(TI_FLAGS:16,er4),er1
-	btst	#TIF_NEED_RESCHED,r1l
-	bne	SYMBOL_NAME(reschedule):16
-	mov.l	sp,er0
-	subs	#4,er0			/* adjust retpc */
-	mov.l	er2,er1
-	jsr	@SYMBOL_NAME(do_signal)
-#if defined(CONFIG_PREEMPT)
-	bra	done:8			/* userspace thoru */
-3:
-	btst	#4,r0l
-	beq	done:8			/* userspace thoru */
-4:
-	mov.l	@(TI_PRE_COUNT:16,er4),er1
-	bne	done:8
-	mov.l	@(TI_FLAGS:16,er4),er1
-	btst	#TIF_NEED_RESCHED,r1l
-	beq	done:8
-	mov.b	r0l,r0l
-	bpl	done:8			/* interrupt off (exception path?) */
-	mov.l	#PREEMPT_ACTIVE,er1
-	mov.l	er1,@(TI_PRE_COUNT:16,er4)
-	andc	#0x7f,ccr
-	jsr	@SYMBOL_NAME(schedule)
-	sub.l	er1,er1
-	mov.l	er1,@(TI_PRE_COUNT:16,er4)
-	orc	#0x80,ccr
-	bra	4b:8
-#endif
-done:
-	RESTORE_ALL			/* Does RTE */
-
-SYMBOL_NAME_LABEL(resume)
-	/*
-	 *	er0 = prev
-	 *	er1 = next
-	 *	return last in er2
-	 */
-
-	/* save sr */
-	sub.w	r3,r3
-	stc	ccr,r3l
-	stc	exr,r3h
-	mov.w	r3,@(THREAD_CCR+2:16,er0)
-
-	/* disable interrupts */
-	orc	#0x80,ccr
-	mov.l	@SYMBOL_NAME(sw_usp),er3
-	mov.l	er3,@(THREAD_USP:16,er0)
-	mov.l	sp,@(THREAD_KSP:16,er0)
-	
-	/* Skip address space switching if they are the same. */
-	/* FIXME: what did we hack out of here, this does nothing! */
-
-	mov.l	@(THREAD_USP:16,er1),er0
-	mov.l	er0,@SYMBOL_NAME(sw_usp)
-	mov.l	@(THREAD_KSP:16,er1),sp
-			
-	/* restore status register */
-	mov.w	@(THREAD_CCR+2:16,er1),r3
-
-	ldc	r3l,ccr
-	ldc	r3h,exr
-
-	rts
-
-SYMBOL_NAME_LABEL(trace_break)
-	subs	#4,sp			/* dummy LVEC */
-	SAVE_ALL
-	sub.l	er1,er1
-	dec.l	#1,er1
-	mov.l	er1,@(LORIG,sp)	
-	mov.l	sp,er0
-	jsr	@SYMBOL_NAME(set_esp0)
-	mov.l	@SYMBOL_NAME(sw_usp),er0
-	mov.l	@er0,er1
-	subs	#2,er1
-	mov.l	er1,@er0	
-	and.w	#0xff,e1
-	mov.l	er1,er0
-	jsr	@SYMBOL_NAME(trace_trap)
-	jmp	@SYMBOL_NAME(ret_from_exception)	
-
-	.section	.bss
-SYMBOL_NAME_LABEL(sw_ksp)
-	.space	4	
-SYMBOL_NAME_LABEL(sw_usp)
-	.space	4	
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index c2d54b8..c7c9c2a 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -441,8 +441,8 @@
 	  this config is intended, is when reboot ends with a stalled/hung
 	  system.
 
-	  Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1.
-	  combination.
+	  Currently, the only fixup is for the Geode machines using
+	  CS5530A and CS5536 chipsets.
 
 	  Say Y if you want to enable the fixup. Currently, it's safe to
 	  enable this option even if you don't need it.
@@ -541,7 +541,7 @@
 
 config HIGHMEM64G
 	bool "64GB"
-	depends on X86_CMPXCHG64
+	depends on !M386 && !M486
 	help
 	  Select this if you have a 32-bit processor and more than 4
 	  gigabytes of physical RAM.
@@ -891,7 +891,7 @@
 	  Don't change this unless you know what you are doing.
 
 config HOTPLUG_CPU
-	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+	bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)"
 	depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER
 	---help---
 	  Say Y here to experiment with turning CPUs off and on, and to
@@ -1212,21 +1212,26 @@
 
 source "fs/Kconfig"
 
-menu "Instrumentation Support"
+menuconfig INSTRUMENTATION
+	bool "Instrumentation Support"
 	depends on EXPERIMENTAL
+	default y
+
+if INSTRUMENTATION
 
 source "arch/i386/oprofile/Kconfig"
 
 config KPROBES
-	bool "Kprobes (EXPERIMENTAL)"
-	depends on KALLSYMS && EXPERIMENTAL && MODULES
+	bool "Kprobes"
+	depends on KALLSYMS && MODULES
 	help
 	  Kprobes allows you to trap at almost any kernel address and
 	  execute a callback function.  register_kprobe() establishes
 	  a probepoint and specifies the callback.  Kprobes is useful
 	  for kernel debugging, non-intrusive instrumentation and testing.
 	  If in doubt, say "N".
-endmenu
+
+endif # INSTRUMENTATION
 
 source "arch/i386/Kconfig.debug"
 
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index d7f6fb0..9cbe76c 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -299,7 +299,7 @@
 
 config X86_CMPXCHG64
 	bool
-	depends on !M386 && !M486
+	depends on X86_PAE
 	default y
 
 config X86_ALIGNMENT_16
@@ -344,8 +344,8 @@
 	depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
 	default y
 
-config X86_MINIMUM_CPU_MODEL
+config X86_MINIMUM_CPU_FAMILY
 	int
-	default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP
-	default "0"
+	default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK
+	default "3"
 
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index bd28f9f..181cc29 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -108,6 +108,7 @@
 # must be linked after kernel/
 drivers-$(CONFIG_OPROFILE)		+= arch/i386/oprofile/
 drivers-$(CONFIG_PM)			+= arch/i386/power/
+drivers-$(CONFIG_FB)                    += arch/i386/video/
 
 CFLAGS += $(mflags-y)
 AFLAGS += $(mflags-y)
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index bfbc320..08678a0a 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -25,27 +25,56 @@
 
 #RAMDISK := -DRAMDISK=512
 
-targets		:= vmlinux.bin bootsect bootsect.o \
-		   setup setup.o zImage bzImage
+targets		:= vmlinux.bin setup.bin setup.elf zImage bzImage
 subdir- 	:= compressed
 
+setup-y		+= a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+setup-y		+= header.o main.o mca.o memory.o pm.o pmjump.o
+setup-y		+= printf.o string.o tty.o video.o version.o voyager.o
+
+# The link order of the video-*.o modules can matter.  In particular,
+# video-vga.o *must* be listed first, followed by video-vesa.o.
+# Hardware-specific drivers should follow in the order they should be
+# probed, and video-bios.o should typically be last.
+setup-y		+= video-vga.o
+setup-y		+= video-vesa.o
+setup-y		+= video-bios.o
+
 hostprogs-y	:= tools/build
 
 HOSTCFLAGS_build.o := $(LINUXINCLUDE)
 
 # ---------------------------------------------------------------------------
 
+# How to compile the 16-bit code.  Note we always compile for -march=i386,
+# that way we can complain to the user if the CPU is insufficient.
+cflags-i386   := 
+cflags-x86_64 := -m32
+CFLAGS		:= $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+		   $(cflags-$(ARCH)) \
+		   -Wall -Wstrict-prototypes \
+		   -march=i386 -mregparm=3 \
+		   -include $(srctree)/$(src)/code16gcc.h \
+		   -fno-strict-aliasing -fomit-frame-pointer \
+		   $(call cc-option, -ffreestanding) \
+		   $(call cc-option, -fno-toplevel-reorder,\
+			$(call cc-option, -fno-unit-at-a-time)) \
+		   $(call cc-option, -fno-stack-protector) \
+		   $(call cc-option, -mpreferred-stack-boundary=2)
+AFLAGS		:= $(CFLAGS) -D__ASSEMBLY__
+
 $(obj)/zImage:  IMAGE_OFFSET := 0x1000
 $(obj)/zImage:  EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK)
 $(obj)/bzImage: IMAGE_OFFSET := 0x100000
+$(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__
 $(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
 $(obj)/bzImage: BUILDFLAGS   := -b
 
 quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
+cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \
 	    $(obj)/vmlinux.bin $(ROOT_DEV) > $@
 
-$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
+$(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \
 			      $(obj)/vmlinux.bin $(obj)/tools/build FORCE
 	$(call if_changed,image)
 	@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
@@ -53,12 +82,17 @@
 $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
 	$(call if_changed,objcopy)
 
-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
-LDFLAGS_setup	 := -Ttext 0x0 -s --oformat binary -e begtext
+SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
 
-$(obj)/setup $(obj)/bootsect: %: %.o FORCE
+LDFLAGS_setup.elf	:= -T
+$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
 	$(call if_changed,ld)
 
+OBJCOPYFLAGS_setup.bin	:= -O binary
+
+$(obj)/setup.bin: $(obj)/setup.elf FORCE
+	$(call if_changed,objcopy)
+
 $(obj)/compressed/vmlinux: FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
 
diff --git a/arch/i386/boot/a20.c b/arch/i386/boot/a20.c
new file mode 100644
index 0000000..31348d0
--- /dev/null
+++ b/arch/i386/boot/a20.c
@@ -0,0 +1,161 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/a20.c
+ *
+ * Enable A20 gate (return -1 on failure)
+ */
+
+#include "boot.h"
+
+#define MAX_8042_LOOPS	100000
+
+static int empty_8042(void)
+{
+	u8 status;
+	int loops = MAX_8042_LOOPS;
+
+	while (loops--) {
+		io_delay();
+
+		status = inb(0x64);
+		if (status & 1) {
+			/* Read and discard input data */
+			io_delay();
+			(void)inb(0x60);
+		} else if (!(status & 2)) {
+			/* Buffers empty, finished! */
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+/* Returns nonzero if the A20 line is enabled.  The memory address
+   used as a test is the int $0x80 vector, which should be safe. */
+
+#define A20_TEST_ADDR	(4*0x80)
+#define A20_TEST_SHORT  32
+#define A20_TEST_LONG	2097152	/* 2^21 */
+
+static int a20_test(int loops)
+{
+	int ok = 0;
+	int saved, ctr;
+
+	set_fs(0x0000);
+	set_gs(0xffff);
+
+	saved = ctr = rdfs32(A20_TEST_ADDR);
+
+	while (loops--) {
+		wrfs32(++ctr, A20_TEST_ADDR);
+		io_delay();	/* Serialize and make delay constant */
+		ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr;
+		if (ok)
+			break;
+	}
+
+	wrfs32(saved, A20_TEST_ADDR);
+	return ok;
+}
+
+/* Quick test to see if A20 is already enabled */
+static int a20_test_short(void)
+{
+	return a20_test(A20_TEST_SHORT);
+}
+
+/* Longer test that actually waits for A20 to come on line; this
+   is useful when dealing with the KBC or other slow external circuitry. */
+static int a20_test_long(void)
+{
+	return a20_test(A20_TEST_LONG);
+}
+
+static void enable_a20_bios(void)
+{
+	asm volatile("pushfl; int $0x15; popfl"
+		     : : "a" ((u16)0x2401));
+}
+
+static void enable_a20_kbc(void)
+{
+	empty_8042();
+
+	outb(0xd1, 0x64);	/* Command write */
+	empty_8042();
+
+	outb(0xdf, 0x60);	/* A20 on */
+	empty_8042();
+}
+
+static void enable_a20_fast(void)
+{
+	u8 port_a;
+
+	port_a = inb(0x92);	/* Configuration port A */
+	port_a |=  0x02;	/* Enable A20 */
+	port_a &= ~0x01;	/* Do not reset machine */
+	outb(port_a, 0x92);
+}
+
+/*
+ * Actual routine to enable A20; return 0 on ok, -1 on failure
+ */
+
+#define A20_ENABLE_LOOPS 255	/* Number of times to try */
+
+int enable_a20(void)
+{
+	int loops = A20_ENABLE_LOOPS;
+
+#if defined(CONFIG_X86_ELAN)
+	/* Elan croaks if we try to touch the KBC */
+	enable_a20_fast();
+	while (!a20_test_long())
+		;
+	return 0;
+#elif defined(CONFIG_X86_VOYAGER)
+	/* On Voyager, a20_test() is unsafe? */
+	enable_a20_kbc();
+	return 0;
+#else
+	while (loops--) {
+		/* First, check to see if A20 is already enabled
+		   (legacy free, etc.) */
+		if (a20_test_short())
+			return 0;
+
+		/* Next, try the BIOS (INT 0x15, AX=0x2401) */
+		enable_a20_bios();
+		if (a20_test_short())
+			return 0;
+
+		/* Try enabling A20 through the keyboard controller */
+		empty_8042();
+		if (a20_test_short())
+			return 0; /* BIOS worked, but with delayed reaction */
+
+		enable_a20_kbc();
+		if (a20_test_long())
+			return 0;
+
+		/* Finally, try enabling the "fast A20 gate" */
+		enable_a20_fast();
+		if (a20_test_long())
+			return 0;
+	}
+
+	return -1;
+#endif
+}
diff --git a/arch/i386/boot/apm.c b/arch/i386/boot/apm.c
new file mode 100644
index 0000000..a34087c
--- /dev/null
+++ b/arch/i386/boot/apm.c
@@ -0,0 +1,97 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   Original APM BIOS checking by Stephen Rothwell, May 1994
+ *   (sfr@canb.auug.org.au)
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/apm.c
+ *
+ * Get APM BIOS information
+ */
+
+#include "boot.h"
+
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+
+int query_apm_bios(void)
+{
+	u16 ax, bx, cx, dx, di;
+	u32 ebx, esi;
+	u8 err;
+
+	/* APM BIOS installation check */
+	ax = 0x5300;
+	bx = cx = 0;
+	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
+		     : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
+		     : : "esi", "edi");
+
+	if (err)
+		return -1;		/* No APM BIOS */
+
+	if (bx != 0x504d)	/* "PM" signature */
+		return -1;
+
+	if (cx & 0x02)		/* 32 bits supported? */
+		return -1;
+
+	/* Disconnect first, just in case */
+	ax = 0x5304;
+	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
+		     : "+a" (ax)
+		     : : "ebx", "ecx", "edx", "esi", "edi");
+
+	/* Paranoia */
+	ebx = esi = 0;
+	cx = dx = di = 0;
+
+	/* 32-bit connect */
+	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6"
+		     : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx),
+		       "+S" (esi), "+D" (di), "=m" (err)
+		     : "a" (0x5303));
+
+	boot_params.apm_bios_info.cseg = ax;
+	boot_params.apm_bios_info.offset = ebx;
+	boot_params.apm_bios_info.cseg_16 = cx;
+	boot_params.apm_bios_info.dseg = dx;
+	boot_params.apm_bios_info.cseg_len = (u16)esi;
+	boot_params.apm_bios_info.cseg_16_len = esi >> 16;
+	boot_params.apm_bios_info.dseg_len = di;
+
+	if (err)
+		return -1;
+
+	/* Redo the installation check as the 32-bit connect;
+	   some BIOSes return different flags this way... */
+
+	ax = 0x5300;
+	bx = cx = 0;
+	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
+		     : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
+		     : : "esi", "edi");
+
+	if (err || bx != 0x504d) {
+		/* Failure with 32-bit connect, try to disconect and ignore */
+		ax = 0x5304;
+		bx = 0;
+		asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
+			     : "+a" (ax), "+b" (bx)
+			     : : "ecx", "edx", "esi", "edi");
+		return -1;
+	}
+
+	boot_params.apm_bios_info.version = ax;
+	boot_params.apm_bios_info.flags = cx;
+	return 0;
+}
+
+#endif
diff --git a/arch/i386/boot/bitops.h b/arch/i386/boot/bitops.h
new file mode 100644
index 0000000..8dcc8dc
--- /dev/null
+++ b/arch/i386/boot/bitops.h
@@ -0,0 +1,45 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/bitops.h
+ *
+ * Very simple bitops for the boot code.
+ */
+
+#ifndef BOOT_BITOPS_H
+#define BOOT_BITOPS_H
+#define _LINUX_BITOPS_H		/* Inhibit inclusion of <linux/bitops.h> */
+
+static inline int constant_test_bit(int nr, const void *addr)
+{
+	const u32 *p = (const u32 *)addr;
+	return ((1UL << (nr & 31)) & (p[nr >> 5])) != 0;
+}
+static inline int variable_test_bit(int nr, const void *addr)
+{
+	u8 v;
+	const u32 *p = (const u32 *)addr;
+
+	asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr));
+	return v;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
+static inline void set_bit(int nr, void *addr)
+{
+	asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr));
+}
+
+#endif /* BOOT_BITOPS_H */
diff --git a/arch/i386/boot/boot.h b/arch/i386/boot/boot.h
new file mode 100644
index 0000000..0329c4f
--- /dev/null
+++ b/arch/i386/boot/boot.h
@@ -0,0 +1,296 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/boot.h
+ *
+ * Header file for the real-mode kernel code
+ */
+
+#ifndef BOOT_BOOT_H
+#define BOOT_BOOT_H
+
+#ifndef __ASSEMBLY__
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/edd.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+/* Useful macros */
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+
+extern struct setup_header hdr;
+extern struct boot_params boot_params;
+
+/* Basic port I/O */
+static inline void outb(u8 v, u16 port)
+{
+	asm volatile("outb %0,%1" : : "a" (v), "dN" (port));
+}
+static inline u8 inb(u16 port)
+{
+	u8 v;
+	asm volatile("inb %1,%0" : "=a" (v) : "dN" (port));
+	return v;
+}
+
+static inline void outw(u16 v, u16 port)
+{
+	asm volatile("outw %0,%1" : : "a" (v), "dN" (port));
+}
+static inline u16 inw(u16 port)
+{
+	u16 v;
+	asm volatile("inw %1,%0" : "=a" (v) : "dN" (port));
+	return v;
+}
+
+static inline void outl(u32 v, u16 port)
+{
+	asm volatile("outl %0,%1" : : "a" (v), "dn" (port));
+}
+static inline u32 inl(u32 port)
+{
+	u32 v;
+	asm volatile("inl %1,%0" : "=a" (v) : "dN" (port));
+	return v;
+}
+
+static inline void io_delay(void)
+{
+	const u16 DELAY_PORT = 0x80;
+	asm volatile("outb %%al,%0" : : "dN" (DELAY_PORT));
+}
+
+/* These functions are used to reference data in other segments. */
+
+static inline u16 ds(void)
+{
+	u16 seg;
+	asm("movw %%ds,%0" : "=rm" (seg));
+	return seg;
+}
+
+static inline void set_fs(u16 seg)
+{
+	asm volatile("movw %0,%%fs" : : "rm" (seg));
+}
+static inline u16 fs(void)
+{
+	u16 seg;
+	asm("movw %%fs,%0" : "=rm" (seg));
+	return seg;
+}
+
+static inline void set_gs(u16 seg)
+{
+	asm volatile("movw %0,%%gs" : : "rm" (seg));
+}
+static inline u16 gs(void)
+{
+	u16 seg;
+	asm("movw %%gs,%0" : "=rm" (seg));
+	return seg;
+}
+
+typedef unsigned int addr_t;
+
+static inline u8 rdfs8(addr_t addr)
+{
+	u8 v;
+	asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
+	return v;
+}
+static inline u16 rdfs16(addr_t addr)
+{
+	u16 v;
+	asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+	return v;
+}
+static inline u32 rdfs32(addr_t addr)
+{
+	u32 v;
+	asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+	return v;
+}
+
+static inline void wrfs8(u8 v, addr_t addr)
+{
+	asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v));
+}
+static inline void wrfs16(u16 v, addr_t addr)
+{
+	asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v));
+}
+static inline void wrfs32(u32 v, addr_t addr)
+{
+	asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v));
+}
+
+static inline u8 rdgs8(addr_t addr)
+{
+	u8 v;
+	asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
+	return v;
+}
+static inline u16 rdgs16(addr_t addr)
+{
+	u16 v;
+	asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+	return v;
+}
+static inline u32 rdgs32(addr_t addr)
+{
+	u32 v;
+	asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+	return v;
+}
+
+static inline void wrgs8(u8 v, addr_t addr)
+{
+	asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v));
+}
+static inline void wrgs16(u16 v, addr_t addr)
+{
+	asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v));
+}
+static inline void wrgs32(u32 v, addr_t addr)
+{
+	asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v));
+}
+
+/* Note: these only return true/false, not a signed return value! */
+static inline int memcmp(const void *s1, const void *s2, size_t len)
+{
+	u8 diff;
+	asm("repe; cmpsb; setnz %0"
+	    : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+	return diff;
+}
+
+static inline int memcmp_fs(const void *s1, addr_t s2, size_t len)
+{
+	u8 diff;
+	asm("fs; repe; cmpsb; setnz %0"
+	    : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+	return diff;
+}
+static inline int memcmp_gs(const void *s1, addr_t s2, size_t len)
+{
+	u8 diff;
+	asm("gs; repe; cmpsb; setnz %0"
+	    : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+	return diff;
+}
+
+static inline int isdigit(int ch)
+{
+	return (ch >= '0') && (ch <= '9');
+}
+
+/* Heap -- available for dynamic lists. */
+#define STACK_SIZE	512	/* Minimum number of bytes for stack */
+
+extern char _end[];
+extern char *HEAP;
+extern char *heap_end;
+#define RESET_HEAP() ((void *)( HEAP = _end ))
+static inline char *__get_heap(size_t s, size_t a, size_t n)
+{
+	char *tmp;
+
+	HEAP = (char *)(((size_t)HEAP+(a-1)) & ~(a-1));
+	tmp = HEAP;
+	HEAP += s*n;
+	return tmp;
+}
+#define GET_HEAP(type, n) \
+	((type *)__get_heap(sizeof(type),__alignof__(type),(n)))
+
+static inline int heap_free(void)
+{
+	return heap_end-HEAP;
+}
+
+/* copy.S */
+
+void copy_to_fs(addr_t dst, void *src, size_t len);
+void *copy_from_fs(void *dst, addr_t src, size_t len);
+void copy_to_gs(addr_t dst, void *src, size_t len);
+void *copy_from_gs(void *dst, addr_t src, size_t len);
+void *memcpy(void *dst, void *src, size_t len);
+void *memset(void *dst, int c, size_t len);
+
+#define memcpy(d,s,l) __builtin_memcpy(d,s,l)
+#define memset(d,c,l) __builtin_memset(d,c,l)
+
+/* a20.c */
+int enable_a20(void);
+
+/* apm.c */
+int query_apm_bios(void);
+
+/* cmdline.c */
+int cmdline_find_option(const char *option, char *buffer, int bufsize);
+
+/* cpu.c, cpucheck.c */
+int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
+int validate_cpu(void);
+
+/* edd.c */
+void query_edd(void);
+
+/* header.S */
+void __attribute__((noreturn)) die(void);
+
+/* mca.c */
+int query_mca(void);
+
+/* memory.c */
+int detect_memory(void);
+
+/* pm.c */
+void __attribute__((noreturn)) go_to_protected_mode(void);
+
+/* pmjump.S */
+void __attribute__((noreturn))
+	protected_mode_jump(u32 entrypoint, u32 bootparams);
+
+/* printf.c */
+int sprintf(char *buf, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list args);
+int printf(const char *fmt, ...);
+
+/* string.c */
+int strcmp(const char *str1, const char *str2);
+size_t strnlen(const char *s, size_t maxlen);
+unsigned int atou(const char *s);
+
+/* tty.c */
+void puts(const char *);
+void putchar(int);
+int getchar(void);
+void kbd_flush(void);
+int getchar_timeout(void);
+
+/* video.c */
+void set_video(void);
+
+/* video-vesa.c */
+void vesa_store_edid(void);
+
+/* voyager.c */
+int query_voyager(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* BOOT_BOOT_H */
diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
deleted file mode 100644
index 011b7a4..0000000
--- a/arch/i386/boot/bootsect.S
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *	bootsect.S		Copyright (C) 1991, 1992 Linus Torvalds
- *
- *	modified by Drew Eckhardt
- *	modified by Bruce Evans (bde)
- *	modified by Chris Noe (May 1999) (as86 -> gas)
- *	gutted by H. Peter Anvin (Jan 2003)
- *
- * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
- * addresses must be multiplied by 16 to obtain their respective linear
- * addresses. To avoid confusion, linear addresses are written using leading
- * hex while segment addresses are written as segment:offset.
- *
- */
-
-#include <asm/boot.h>
-
-SETUPSECTS	= 4			/* default nr of setup-sectors */
-BOOTSEG		= 0x07C0		/* original address of boot-sector */
-INITSEG		= DEF_INITSEG		/* we move boot here - out of the way */
-SETUPSEG	= DEF_SETUPSEG		/* setup starts here */
-SYSSEG		= DEF_SYSSEG		/* system loaded at 0x10000 (65536) */
-SYSSIZE		= DEF_SYSSIZE		/* system size: # of 16-byte clicks */
-					/* to be loaded */
-ROOT_DEV	= 0 			/* ROOT_DEV is now written by "build" */
-SWAP_DEV	= 0			/* SWAP_DEV is now written by "build" */
-
-#ifndef SVGA_MODE
-#define SVGA_MODE ASK_VGA
-#endif
-
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif
-
-#ifndef ROOT_RDONLY
-#define ROOT_RDONLY 1
-#endif
-
-.code16
-.text
-
-.global _start
-_start:
-
-	# Normalize the start address
-	jmpl	$BOOTSEG, $start2
-
-start2:
-	movw	%cs, %ax
-	movw	%ax, %ds
-	movw	%ax, %es
-	movw	%ax, %ss
-	movw	$0x7c00, %sp
-	sti
-	cld
-
-	movw	$bugger_off_msg, %si
-
-msg_loop:
-	lodsb
-	andb	%al, %al
-	jz	die
-	movb	$0xe, %ah
-	movw	$7, %bx
-	int	$0x10
-	jmp	msg_loop
-
-die:
-	# Allow the user to press a key, then reboot
-	xorw	%ax, %ax
-	int	$0x16
-	int	$0x19
-
-	# int 0x19 should never return.  In case it does anyway,
-	# invoke the BIOS reset code...
-	ljmp	$0xf000,$0xfff0
-
-
-bugger_off_msg:
-	.ascii	"Direct booting from floppy is no longer supported.\r\n"
-	.ascii	"Please use a boot loader program instead.\r\n"
-	.ascii	"\n"
-	.ascii	"Remove disk and press any key to reboot . . .\r\n"
-	.byte	0
-
-
-	# Kernel attributes; used by setup
-
-	.org 497
-setup_sects:	.byte SETUPSECTS
-root_flags:	.word ROOT_RDONLY
-syssize:	.word SYSSIZE
-swap_dev:	.word SWAP_DEV
-ram_size:	.word RAMDISK
-vid_mode:	.word SVGA_MODE
-root_dev:	.word ROOT_DEV
-boot_flag:	.word 0xAA55
diff --git a/arch/i386/boot/cmdline.c b/arch/i386/boot/cmdline.c
new file mode 100644
index 0000000..34bb778
--- /dev/null
+++ b/arch/i386/boot/cmdline.c
@@ -0,0 +1,97 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cmdline.c
+ *
+ * Simple command-line parser for early boot.
+ */
+
+#include "boot.h"
+
+static inline int myisspace(u8 c)
+{
+	return c <= ' ';	/* Close enough approximation */
+}
+
+/*
+ * Find a non-boolean option, that is, "option=argument".  In accordance
+ * with standard Linux practice, if this option is repeated, this returns
+ * the last instance on the command line.
+ *
+ * Returns the length of the argument (regardless of if it was
+ * truncated to fit in the buffer), or -1 on not found.
+ */
+int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+	u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
+	addr_t cptr;
+	char c;
+	int len = -1;
+	const char *opptr = NULL;
+	char *bufptr = buffer;
+	enum {
+		st_wordstart,	/* Start of word/after whitespace */
+		st_wordcmp,	/* Comparing this word */
+		st_wordskip,	/* Miscompare, skip */
+		st_bufcpy	/* Copying this to buffer */
+	} state = st_wordstart;
+
+	if (!cmdline_ptr || cmdline_ptr >= 0x100000)
+		return -1;	/* No command line, or inaccessible */
+
+	cptr = cmdline_ptr & 0xf;
+	set_fs(cmdline_ptr >> 4);
+
+	while (cptr < 0x10000 && (c = rdfs8(cptr++))) {
+		switch (state) {
+		case st_wordstart:
+			if (myisspace(c))
+				break;
+
+			/* else */
+			state = st_wordcmp;
+			opptr = option;
+			/* fall through */
+
+		case st_wordcmp:
+			if (c == '=' && !*opptr) {
+				len = 0;
+				bufptr = buffer;
+				state = st_bufcpy;
+			} else if (myisspace(c)) {
+				state = st_wordstart;
+			} else if (c != *opptr++) {
+				state = st_wordskip;
+			}
+			break;
+
+		case st_wordskip:
+			if (myisspace(c))
+				state = st_wordstart;
+			break;
+
+		case st_bufcpy:
+			if (myisspace(c)) {
+				state = st_wordstart;
+			} else {
+				if (len < bufsize-1)
+					*bufptr++ = c;
+				len++;
+			}
+			break;
+		}
+	}
+
+	if (bufsize)
+		*bufptr = '\0';
+
+	return len;
+}
diff --git a/arch/i386/boot/code16gcc.h b/arch/i386/boot/code16gcc.h
new file mode 100644
index 0000000..3bd8480
--- /dev/null
+++ b/arch/i386/boot/code16gcc.h
@@ -0,0 +1,15 @@
+/*
+ * code16gcc.h
+ *
+ * This file is -include'd when compiling 16-bit C code.
+ * Note: this asm() needs to be emitted before gcc omits any code.
+ * Depending on gcc version, this requires -fno-unit-at-a-time or
+ * -fno-toplevel-reorder.
+ *
+ * Hopefully gcc will eventually have a real -m16 option so we can
+ * drop this hack long term.
+ */
+
+#ifndef __ASSEMBLY__
+asm(".code16gcc");
+#endif
diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
index a661217..189fa1d 100644
--- a/arch/i386/boot/compressed/Makefile
+++ b/arch/i386/boot/compressed/Makefile
@@ -9,9 +9,14 @@
 EXTRA_AFLAGS	:= -traditional
 
 LDFLAGS_vmlinux := -T
-CFLAGS_misc.o += -fPIC
 hostprogs-y	:= relocs
 
+CFLAGS  := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
+	   -fno-strict-aliasing -fPIC \
+	   $(call cc-option,-ffreestanding) \
+	   $(call cc-option,-fno-stack-protector)
+LDFLAGS := -m elf_i386
+
 $(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
 	@:
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index 3517a32..f35ea22 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -45,10 +45,10 @@
  * at and where we were actually loaded at.  This can only be done
  * with a short local call on x86.  Nothing  else will tell us what
  * address we are running at.  The reserved chunk of the real-mode
- * data at 0x34-0x3f are used as the stack for this calculation.
- * Only 4 bytes are needed.
+ * data at 0x1e4 (defined as a scratch field) are used as the stack
+ * for this calculation. Only 4 bytes are needed.
  */
-	leal 0x40(%esi), %esp
+	leal (0x1e4+4)(%esi), %esp
 	call 1f
 1:	popl %ebp
 	subl $1b, %ebp
diff --git a/arch/i386/boot/copy.S b/arch/i386/boot/copy.S
new file mode 100644
index 0000000..ef127e5
--- /dev/null
+++ b/arch/i386/boot/copy.S
@@ -0,0 +1,101 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/copy.S
+ *
+ * Memory copy routines
+ */
+
+	.code16gcc
+	.text
+
+	.globl	memcpy
+	.type	memcpy, @function
+memcpy:
+	pushw	%si
+	pushw	%di
+	movw	%ax, %di
+	movw	%dx, %si
+	pushw	%cx
+	shrw	$2, %cx
+	rep; movsl
+	popw	%cx
+	andw	$3, %cx
+	rep; movsb
+	popw	%di
+	popw	%si
+	ret
+	.size	memcpy, .-memcpy
+
+	.globl	memset
+	.type	memset, @function
+memset:
+	pushw	%di
+	movw	%ax, %di
+	movzbl	%dl, %eax
+	imull	$0x01010101,%eax
+	pushw	%cx
+	shrw	$2, %cx
+	rep; stosl
+	popw	%cx
+	andw	$3, %cx
+	rep; stosb
+	popw	%di
+	ret
+	.size	memset, .-memset
+
+	.globl	copy_from_fs
+	.type	copy_from_fs, @function
+copy_from_fs:
+	pushw	%ds
+	pushw	%fs
+	popw	%ds
+	call	memcpy
+	popw	%ds
+	ret
+	.size	copy_from_fs, .-copy_from_fs
+
+	.globl	copy_to_fs
+	.type	copy_to_fs, @function
+copy_to_fs:
+	pushw	%es
+	pushw	%fs
+	popw	%es
+	call	memcpy
+	popw	%es
+	ret
+	.size	copy_to_fs, .-copy_to_fs
+
+#if 0 /* Not currently used, but can be enabled as needed */
+
+	.globl	copy_from_gs
+	.type	copy_from_gs, @function
+copy_from_gs:
+	pushw	%ds
+	pushw	%gs
+	popw	%ds
+	call	memcpy
+	popw	%ds
+	ret
+	.size	copy_from_gs, .-copy_from_gs
+	.globl	copy_to_gs
+
+	.type	copy_to_gs, @function
+copy_to_gs:
+	pushw	%es
+	pushw	%gs
+	popw	%es
+	call	memcpy
+	popw	%es
+	ret
+	.size	copy_to_gs, .-copy_to_gs
+
+#endif
diff --git a/arch/i386/boot/cpu.c b/arch/i386/boot/cpu.c
new file mode 100644
index 0000000..2a5c32d
--- /dev/null
+++ b/arch/i386/boot/cpu.c
@@ -0,0 +1,69 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cpu.c
+ *
+ * Check for obligatory CPU features and abort if the features are not
+ * present.
+ */
+
+#include "boot.h"
+#include "bitops.h"
+#include <asm/cpufeature.h>
+
+static char *cpu_name(int level)
+{
+	static char buf[6];
+
+	if (level == 64) {
+		return "x86-64";
+	} else {
+		sprintf(buf, "i%d86", level);
+		return buf;
+	}
+}
+
+int validate_cpu(void)
+{
+	u32 *err_flags;
+	int cpu_level, req_level;
+
+	check_cpu(&cpu_level, &req_level, &err_flags);
+
+	if (cpu_level < req_level) {
+		printf("This kernel requires an %s CPU, ",
+		       cpu_name(req_level));
+		printf("but only detected an %s CPU.\n",
+		       cpu_name(cpu_level));
+		return -1;
+	}
+
+	if (err_flags) {
+		int i, j;
+		puts("This kernel requires the following features "
+		     "not present on the CPU:\n");
+
+		for (i = 0; i < NCAPINTS; i++) {
+			u32 e = err_flags[i];
+
+			for (j = 0; j < 32; j++) {
+				if (e & 1)
+					printf("%d:%d ", i, j);
+
+				e >>= 1;
+			}
+		}
+		putchar('\n');
+		return -1;
+	} else {
+		return 0;
+	}
+}
diff --git a/arch/i386/boot/cpucheck.c b/arch/i386/boot/cpucheck.c
new file mode 100644
index 0000000..8b0f447
--- /dev/null
+++ b/arch/i386/boot/cpucheck.c
@@ -0,0 +1,267 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cpucheck.c
+ *
+ * Check for obligatory CPU features and abort if the features are not
+ * present.  This code should be compilable as 16-, 32- or 64-bit
+ * code, so be very careful with types and inline assembly.
+ *
+ * This code should not contain any messages; that requires an
+ * additional wrapper.
+ *
+ * As written, this code is not safe for inclusion into the kernel
+ * proper (after FPU initialization, in particular).
+ */
+
+#ifdef _SETUP
+# include "boot.h"
+# include "bitops.h"
+#endif
+#include <linux/types.h>
+#include <asm/cpufeature.h>
+#include <asm/processor-flags.h>
+#include <asm/required-features.h>
+#include <asm/msr-index.h>
+
+struct cpu_features {
+	int level;		/* Family, or 64 for x86-64 */
+	int model;
+	u32 flags[NCAPINTS];
+};
+
+static struct cpu_features cpu;
+static u32 cpu_vendor[3];
+static u32 err_flags[NCAPINTS];
+
+#ifdef CONFIG_X86_64
+static const int req_level = 64;
+#elif defined(CONFIG_X86_MINIMUM_CPU_FAMILY)
+static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
+#else
+static const int req_level = 3;
+#endif
+
+static const u32 req_flags[NCAPINTS] =
+{
+	REQUIRED_MASK0,
+	REQUIRED_MASK1,
+	REQUIRED_MASK2,
+	REQUIRED_MASK3,
+	REQUIRED_MASK4,
+	REQUIRED_MASK5,
+	REQUIRED_MASK6,
+	REQUIRED_MASK7,
+};
+
+#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
+
+static int is_amd(void)
+{
+	return cpu_vendor[0] == A32('A','u','t','h') &&
+	       cpu_vendor[1] == A32('e','n','t','i') &&
+	       cpu_vendor[2] == A32('c','A','M','D');
+}
+
+static int is_centaur(void)
+{
+	return cpu_vendor[0] == A32('C','e','n','t') &&
+	       cpu_vendor[1] == A32('a','u','r','H') &&
+	       cpu_vendor[2] == A32('a','u','l','s');
+}
+
+static int is_transmeta(void)
+{
+	return cpu_vendor[0] == A32('G','e','n','u') &&
+	       cpu_vendor[1] == A32('i','n','e','T') &&
+	       cpu_vendor[2] == A32('M','x','8','6');
+}
+
+static int has_fpu(void)
+{
+	u16 fcw = -1, fsw = -1;
+	u32 cr0;
+
+	asm("movl %%cr0,%0" : "=r" (cr0));
+	if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
+		cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
+		asm volatile("movl %0,%%cr0" : : "r" (cr0));
+	}
+
+	asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw));
+
+	return fsw == 0 && (fcw & 0x103f) == 0x003f;
+}
+
+static int has_eflag(u32 mask)
+{
+	u32 f0, f1;
+
+	asm("pushfl ; "
+	    "pushfl ; "
+	    "popl %0 ; "
+	    "movl %0,%1 ; "
+	    "xorl %2,%1 ; "
+	    "pushl %1 ; "
+	    "popfl ; "
+	    "pushfl ; "
+	    "popl %1 ; "
+	    "popfl"
+	    : "=r" (f0), "=r" (f1)
+	    : "g" (mask));
+
+	return !!((f0^f1) & mask);
+}
+
+static void get_flags(void)
+{
+	u32 max_intel_level, max_amd_level;
+	u32 tfms;
+
+	if (has_fpu())
+		set_bit(X86_FEATURE_FPU, cpu.flags);
+
+	if (has_eflag(X86_EFLAGS_ID)) {
+		asm("cpuid"
+		    : "=a" (max_intel_level),
+		      "=b" (cpu_vendor[0]),
+		      "=d" (cpu_vendor[1]),
+		      "=c" (cpu_vendor[2])
+		    : "a" (0));
+
+		if (max_intel_level >= 0x00000001 &&
+		    max_intel_level <= 0x0000ffff) {
+			asm("cpuid"
+			    : "=a" (tfms),
+			      "=c" (cpu.flags[4]),
+			      "=d" (cpu.flags[0])
+			    : "a" (0x00000001)
+			    : "ebx");
+			cpu.level = (tfms >> 8) & 15;
+			cpu.model = (tfms >> 4) & 15;
+			if (cpu.level >= 6)
+				cpu.model += ((tfms >> 16) & 0xf) << 4;
+		}
+
+		asm("cpuid"
+		    : "=a" (max_amd_level)
+		    : "a" (0x80000000)
+		    : "ebx", "ecx", "edx");
+
+		if (max_amd_level >= 0x80000001 &&
+		    max_amd_level <= 0x8000ffff) {
+			u32 eax = 0x80000001;
+			asm("cpuid"
+			    : "+a" (eax),
+			      "=c" (cpu.flags[6]),
+			      "=d" (cpu.flags[1])
+			    : : "ebx");
+		}
+	}
+}
+
+/* Returns a bitmask of which words we have error bits in */
+static int check_flags(void)
+{
+	u32 err;
+	int i;
+
+	err = 0;
+	for (i = 0; i < NCAPINTS; i++) {
+		err_flags[i] = req_flags[i] & ~cpu.flags[i];
+		if (err_flags[i])
+			err |= 1 << i;
+	}
+
+	return err;
+}
+
+/*
+ * Returns -1 on error.
+ *
+ * *cpu_level is set to the current CPU level; *req_level to the required
+ * level.  x86-64 is considered level 64 for this purpose.
+ *
+ * *err_flags_ptr is set to the flags error array if there are flags missing.
+ */
+int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
+{
+	int err;
+
+	memset(&cpu.flags, 0, sizeof cpu.flags);
+	cpu.level = 3;
+
+	if (has_eflag(X86_EFLAGS_AC))
+		cpu.level = 4;
+
+	get_flags();
+	err = check_flags();
+
+	if (test_bit(X86_FEATURE_LM, cpu.flags))
+		cpu.level = 64;
+
+	if (err == 0x01 &&
+	    !(err_flags[0] &
+	      ~((1 << X86_FEATURE_XMM)|(1 << X86_FEATURE_XMM2))) &&
+	    is_amd()) {
+		/* If this is an AMD and we're only missing SSE+SSE2, try to
+		   turn them on */
+
+		u32 ecx = MSR_K7_HWCR;
+		u32 eax, edx;
+
+		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+		eax &= ~(1 << 15);
+		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+		get_flags();	/* Make sure it really did something */
+		err = check_flags();
+	} else if (err == 0x01 &&
+		   !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) &&
+		   is_centaur() && cpu.model >= 6) {
+		/* If this is a VIA C3, we might have to enable CX8
+		   explicitly */
+
+		u32 ecx = MSR_VIA_FCR;
+		u32 eax, edx;
+
+		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+		eax |= (1<<1)|(1<<7);
+		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+		set_bit(X86_FEATURE_CX8, cpu.flags);
+		err = check_flags();
+	} else if (err == 0x01 && is_transmeta()) {
+		/* Transmeta might have masked feature bits in word 0 */
+
+		u32 ecx = 0x80860004;
+		u32 eax, edx;
+		u32 level = 1;
+
+		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+		asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
+		asm("cpuid"
+		    : "+a" (level), "=d" (cpu.flags[0])
+		    : : "ecx", "ebx");
+		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+		err = check_flags();
+	}
+
+	if (err_flags_ptr)
+		*err_flags_ptr = err ? err_flags : NULL;
+	if (cpu_level_ptr)
+		*cpu_level_ptr = cpu.level;
+	if (req_level_ptr)
+		*req_level_ptr = req_level;
+
+	return (cpu.level < req_level || err) ? -1 : 0;
+}
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
deleted file mode 100644
index 3432136..0000000
--- a/arch/i386/boot/edd.S
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * BIOS Enhanced Disk Drive support
- * Copyright (C) 2002, 2003, 2004 Dell, Inc.
- * by Matt Domsch <Matt_Domsch@dell.com> October 2002
- * conformant to T13 Committee www.t13.org
- *   projects 1572D, 1484D, 1386D, 1226DT
- * disk signature read by Matt Domsch <Matt_Domsch@dell.com>
- *	and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
- * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net>
- *      March 2004
- * Command line option parsing, Matt Domsch, November 2004
- */
-
-#include <linux/edd.h>
-#include <asm/setup.h>
-
-#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
-
-# It is assumed that %ds == INITSEG here
-
-	movb	$0, (EDD_MBR_SIG_NR_BUF)
-	movb	$0, (EDDNR)
-
-# Check the command line for options:
-# edd=of  disables EDD completely  (edd=off)
-# edd=sk  skips the MBR test    (edd=skipmbr)
-# edd=on  re-enables EDD (edd=on)
-
-	pushl	%esi
-	movw	$edd_mbr_sig_start, %di	# Default to edd=on
-
-	movl	%cs:(cmd_line_ptr), %esi
-	andl	%esi, %esi
-	jz	old_cl			# Old boot protocol?
-
-# Convert to a real-mode pointer in fs:si
-	movl	%esi, %eax
-	shrl	$4, %eax
-	movw	%ax, %fs
-	andw	$0xf, %si
-	jmp	have_cl_pointer
-
-# Old-style boot protocol?
-old_cl:
-	push	%ds			# aka INITSEG
-	pop	%fs
-
-	cmpw	$0xa33f, (0x20)
-	jne	done_cl			# No command line at all?
-	movw	(0x22), %si		# Pointer relative to INITSEG
-
-# fs:si has the pointer to the command line now
-have_cl_pointer:
-
-# Loop through kernel command line one byte at a time.  Just in
-# case the loader is buggy and failed to null-terminate the command line
-# terminate if we get close enough to the end of the segment that we
-# cannot fit "edd=XX"...
-cl_atspace:
-	cmpw	$-5, %si		# Watch for segment wraparound
-	jae	done_cl
-	movl	%fs:(%si), %eax
-	andb	%al, %al		# End of line?
-	jz	done_cl
-	cmpl	$EDD_CL_EQUALS, %eax
-	jz	found_edd_equals
-	cmpb	$0x20, %al		# <= space consider whitespace
-	ja	cl_skipword
-	incw	%si
-	jmp	cl_atspace
-
-cl_skipword:
-	cmpw	$-5, %si		# Watch for segment wraparound
-	jae	done_cl
-	movb	%fs:(%si), %al		# End of string?
-	andb	%al, %al
-	jz	done_cl
-	cmpb	$0x20, %al
-	jbe	cl_atspace
-	incw	%si
-	jmp	cl_skipword
-
-found_edd_equals:
-# only looking at first two characters after equals
-# late overrides early on the command line, so keep going after finding something
-	movw	%fs:4(%si), %ax
-	cmpw	$EDD_CL_OFF, %ax	# edd=of
-	je	do_edd_off
-	cmpw	$EDD_CL_SKIP, %ax	# edd=sk
-	je	do_edd_skipmbr
-	cmpw	$EDD_CL_ON, %ax		# edd=on
-	je	do_edd_on
-	jmp	cl_skipword
-do_edd_skipmbr:
-	movw	$edd_start, %di
-	jmp	cl_skipword
-do_edd_off:
-	movw	$edd_done, %di
-	jmp	cl_skipword
-do_edd_on:
-	movw	$edd_mbr_sig_start, %di
-	jmp	cl_skipword
-
-done_cl:
-	popl	%esi
-	jmpw	*%di
-
-# Read the first sector of each BIOS disk device and store the 4-byte signature
-edd_mbr_sig_start:
-	movb	$0x80, %dl			# from device 80
-	movw	$EDD_MBR_SIG_BUF, %bx		# store buffer ptr in bx
-edd_mbr_sig_read:
-	movl	$0xFFFFFFFF, %eax
-	movl	%eax, (%bx)			# assume failure
-	pushw	%bx
-	movb	$READ_SECTORS, %ah
-	movb	$1, %al				# read 1 sector
-	movb	$0, %dh				# at head 0
-	movw	$1, %cx				# cylinder 0, sector 0
-	pushw	%es
-	pushw	%ds
-	popw	%es
-    	movw	$EDDBUF, %bx			# disk's data goes into EDDBUF
-	pushw	%dx             # work around buggy BIOSes
-	stc                     # work around buggy BIOSes
-	int	$0x13
-	sti                     # work around buggy BIOSes
-	popw	%dx
-	popw	%es
-	popw	%bx
-	jc	edd_mbr_sig_done		# on failure, we're done.
-	cmpb	$0, %ah		# some BIOSes do not set CF
-	jne	edd_mbr_sig_done		# on failure, we're done.
-	movl	(EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR
-	movl	%eax, (%bx)			# store success
-	incb	(EDD_MBR_SIG_NR_BUF)		# note that we stored something
-	incb	%dl				# increment to next device
-	addw	$4, %bx				# increment sig buffer ptr
-	cmpb	$EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF)	# Out of space?
-	jb	edd_mbr_sig_read		# keep looping
-edd_mbr_sig_done:
-
-# Do the BIOS Enhanced Disk Drive calls
-# This consists of two calls:
-#    int 13h ah=41h "Check Extensions Present"
-#    int 13h ah=48h "Get Device Parameters"
-#    int 13h ah=08h "Legacy Get Device Parameters"
-#
-# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use
-# in the boot_params at EDDBUF.  The first four bytes of which are
-# used to store the device number, interface support map and version
-# results from fn41.  The next four bytes are used to store the legacy
-# cylinders, heads, and sectors from fn08. The following 74 bytes are used to
-# store the results from fn48.  Starting from device 80h, fn41, then fn48
-# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE).
-# Then the pointer is incremented to store the data for the next call.
-# This repeats until either a device doesn't exist, or until EDDMAXNR
-# devices have been stored.
-# The one tricky part is that ds:si always points EDDEXTSIZE bytes into
-# the structure, and the fn41 and fn08 results are stored at offsets
-# from there.  This removes the need to increment the pointer for
-# every store, and leaves it ready for the fn48 call.
-# A second one-byte buffer, EDDNR, in the boot_params stores
-# the number of BIOS devices which exist, up to EDDMAXNR.
-# In setup.c, copy_edd() stores both boot_params buffers away
-# for later use, as they would get overwritten otherwise.
-# This code is sensitive to the size of the structs in edd.h
-edd_start:
-						# %ds points to the bootsector
-       						# result buffer for fn48
-	movw	$EDDBUF+EDDEXTSIZE, %si		# in ds:si, fn41 results
-						# kept just before that
-	movb	$0x80, %dl			# BIOS device 0x80
-
-edd_check_ext:
-	movb	$CHECKEXTENSIONSPRESENT, %ah    # Function 41
-	movw	$EDDMAGIC1, %bx			# magic
-	int	$0x13				# make the call
-	jc	edd_done			# no more BIOS devices
-
-	cmpw	$EDDMAGIC2, %bx			# is magic right?
-	jne	edd_next			# nope, next...
-
-	movb	%dl, %ds:-8(%si)		# store device number
-	movb	%ah, %ds:-7(%si)		# store version
-	movw	%cx, %ds:-6(%si)		# store extensions
-	incb	(EDDNR)				# note that we stored something
-
-edd_get_device_params:
-	movw	$EDDPARMSIZE, %ds:(%si)		# put size
-	movw	$0x0, %ds:2(%si)		# work around buggy BIOSes
-	movb	$GETDEVICEPARAMETERS, %ah	# Function 48
-	int	$0x13				# make the call
-						# Don't check for fail return
-						# it doesn't matter.
-edd_get_legacy_chs:
-	xorw    %ax, %ax
-	movw    %ax, %ds:-4(%si)
-	movw    %ax, %ds:-2(%si)
-        # Ralf Brown's Interrupt List says to set ES:DI to
-	# 0000h:0000h "to guard against BIOS bugs"
-	pushw   %es
-	movw    %ax, %es
-	movw    %ax, %di
-	pushw   %dx                             # legacy call clobbers %dl
-	movb    $LEGACYGETDEVICEPARAMETERS, %ah # Function 08
-	int     $0x13                           # make the call
-	jc      edd_legacy_done                 # failed
-	movb    %cl, %al                        # Low 6 bits are max
-	andb    $0x3F, %al                      #   sector number
-	movb	%al, %ds:-1(%si)                # Record max sect
-	movb    %dh, %ds:-2(%si)                # Record max head number
-	movb    %ch, %al                        # Low 8 bits of max cyl
-	shr     $6, %cl
-	movb    %cl, %ah                        # High 2 bits of max cyl
-	movw    %ax, %ds:-4(%si)
-
-edd_legacy_done:
-	popw    %dx
-	popw    %es
-	movw	%si, %ax			# increment si
-	addw	$EDDPARMSIZE+EDDEXTSIZE, %ax
-	movw	%ax, %si
-
-edd_next:
-	incb	%dl				# increment to next device
-	cmpb	$EDDMAXNR, (EDDNR) 		# Out of space?
-	jb	edd_check_ext			# keep looping
-
-edd_done:
-#endif
diff --git a/arch/i386/boot/edd.c b/arch/i386/boot/edd.c
new file mode 100644
index 0000000..25a2824
--- /dev/null
+++ b/arch/i386/boot/edd.c
@@ -0,0 +1,196 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/edd.c
+ *
+ * Get EDD BIOS disk information
+ */
+
+#include "boot.h"
+#include <linux/edd.h>
+
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+
+struct edd_dapa {
+	u8	pkt_size;
+	u8	rsvd;
+	u16	sector_cnt;
+	u16	buf_off, buf_seg;
+	u64	lba;
+	u64	buf_lin_addr;
+};
+
+/*
+ * Read the MBR (first sector) from a specific device.
+ */
+static int read_mbr(u8 devno, void *buf)
+{
+	struct edd_dapa dapa;
+	u16 ax, bx, cx, dx, si;
+
+	memset(&dapa, 0, sizeof dapa);
+	dapa.pkt_size = sizeof(dapa);
+	dapa.sector_cnt = 1;
+	dapa.buf_off = (size_t)buf;
+	dapa.buf_seg = ds();
+	/* dapa.lba = 0; */
+
+	ax = 0x4200;		/* Extended Read */
+	si = (size_t)&dapa;
+	dx = devno;
+	asm("pushfl; stc; int $0x13; setc %%al; popfl"
+	    : "+a" (ax), "+S" (si), "+d" (dx)
+	    : "m" (dapa)
+	    : "ebx", "ecx", "edi", "memory");
+
+	if (!(u8)ax)
+		return 0;	/* OK */
+
+	ax = 0x0201;		/* Legacy Read, one sector */
+	cx = 0x0001;		/* Sector 0-0-1 */
+	dx = devno;
+	bx = (size_t)buf;
+	asm("pushfl; stc; int $0x13; setc %%al; popfl"
+	    : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx)
+	    : : "esi", "edi", "memory");
+
+	return -(u8)ax;		/* 0 or -1 */
+}
+
+static u32 read_mbr_sig(u8 devno, struct edd_info *ei)
+{
+	int sector_size;
+	char *mbrbuf_ptr, *mbrbuf_end;
+	u32 mbrsig;
+	u32 buf_base, mbr_base;
+	extern char _end[];
+	static char mbr_buf[1024];
+
+	sector_size = ei->params.bytes_per_sector;
+	if (!sector_size)
+		sector_size = 512; /* Best available guess */
+
+	buf_base = (ds() << 4) + (u32)&_end;
+	mbr_base = (buf_base+sector_size-1) & ~(sector_size-1);
+	mbrbuf_ptr = mbr_buf + (mbr_base-buf_base);
+	mbrbuf_end = mbrbuf_ptr + sector_size;
+
+	if (!(boot_params.hdr.loadflags & CAN_USE_HEAP))
+		return 0;
+	if (mbrbuf_end > (char *)(size_t)boot_params.hdr.heap_end_ptr)
+		return 0;
+
+	if (read_mbr(devno, mbrbuf_ptr))
+		return 0;
+
+	mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_SIG_OFFSET];
+	return mbrsig;
+}
+
+static int get_edd_info(u8 devno, struct edd_info *ei)
+{
+	u16 ax, bx, cx, dx, di;
+
+	memset(ei, 0, sizeof *ei);
+
+	/* Check Extensions Present */
+
+	ax = 0x4100;
+	bx = EDDMAGIC1;
+	dx = devno;
+	asm("pushfl; stc; int $0x13; setc %%al; popfl"
+	    : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx)
+	    : : "esi", "edi");
+
+	if ((u8)ax)
+		return -1;	/* No extended information */
+
+	if (bx != EDDMAGIC2)
+		return -1;
+
+	ei->device  = devno;
+	ei->version = ax >> 8;	/* EDD version number */
+	ei->interface_support = cx; /* EDD functionality subsets */
+
+	/* Extended Get Device Parameters */
+
+	ei->params.length = sizeof(ei->params);
+	ax = 0x4800;
+	dx = devno;
+	asm("pushfl; int $0x13; popfl"
+	    : "+a" (ax), "+d" (dx)
+	    : "S" (&ei->params)
+	    : "ebx", "ecx", "edi");
+
+	/* Get legacy CHS parameters */
+
+	/* Ralf Brown recommends setting ES:DI to 0:0 */
+	ax = 0x0800;
+	dx = devno;
+	di = 0;
+	asm("pushw %%es; "
+	    "movw %%di,%%es; "
+	    "pushfl; stc; int $0x13; setc %%al; popfl; "
+	    "popw %%es"
+	    : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di)
+	    : : "esi");
+
+	if ((u8)ax == 0) {
+		ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2);
+		ei->legacy_max_head = dx >> 8;
+		ei->legacy_sectors_per_track = cx & 0x3f;
+	}
+
+	return 0;
+}
+
+void query_edd(void)
+{
+	char eddarg[8];
+	int do_mbr = 1;
+	int do_edd = 1;
+	int devno;
+	struct edd_info ei, *edp;
+
+	if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) {
+		if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip"))
+			do_mbr = 0;
+		else if (!strcmp(eddarg, "off"))
+			do_edd = 0;
+	}
+
+	edp = (struct edd_info *)boot_params.eddbuf;
+
+	if (!do_edd)
+		return;
+
+	for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) {
+		/*
+		 * Scan the BIOS-supported hard disks and query EDD
+		 * information...
+		 */
+		get_edd_info(devno, &ei);
+
+		if (boot_params.eddbuf_entries < EDDMAXNR) {
+			memcpy(edp, &ei, sizeof ei);
+			edp++;
+			boot_params.eddbuf_entries++;
+		}
+
+		if (do_mbr) {
+			u32 mbr_sig;
+			mbr_sig = read_mbr_sig(devno, &ei);
+			boot_params.edd_mbr_sig_buffer[devno-0x80] = mbr_sig;
+		}
+	}
+}
+
+#endif
diff --git a/arch/i386/boot/header.S b/arch/i386/boot/header.S
new file mode 100644
index 0000000..6b9923fb
--- /dev/null
+++ b/arch/i386/boot/header.S
@@ -0,0 +1,283 @@
+/*
+ *	header.S
+ *
+ *	Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ *	Based on bootsect.S and setup.S
+ *	modified by more people than can be counted
+ *
+ *	Rewritten as a common file by H. Peter Anvin (Apr 2007)
+ *
+ * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
+ * addresses must be multiplied by 16 to obtain their respective linear
+ * addresses. To avoid confusion, linear addresses are written using leading
+ * hex while segment addresses are written as segment:offset.
+ *
+ */
+
+#include <asm/segment.h>
+#include <linux/utsrelease.h>
+#include <asm/boot.h>
+#include <asm/e820.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include "boot.h"
+
+SETUPSECTS	= 4			/* default nr of setup-sectors */
+BOOTSEG		= 0x07C0		/* original address of boot-sector */
+SYSSEG		= DEF_SYSSEG		/* system loaded at 0x10000 (65536) */
+SYSSIZE		= DEF_SYSSIZE		/* system size: # of 16-byte clicks */
+					/* to be loaded */
+ROOT_DEV	= 0			/* ROOT_DEV is now written by "build" */
+SWAP_DEV	= 0			/* SWAP_DEV is now written by "build" */
+
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
+
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif
+
+#ifndef ROOT_RDONLY
+#define ROOT_RDONLY 1
+#endif
+
+	.code16
+	.section ".bstext", "ax"
+
+	.global bootsect_start
+bootsect_start:
+
+	# Normalize the start address
+	ljmp	$BOOTSEG, $start2
+
+start2:
+	movw	%cs, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %ss
+	xorw	%sp, %sp
+	sti
+	cld
+
+	movw	$bugger_off_msg, %si
+
+msg_loop:
+	lodsb
+	andb	%al, %al
+	jz	bs_die
+	movb	$0xe, %ah
+	movw	$7, %bx
+	int	$0x10
+	jmp	msg_loop
+
+bs_die:
+	# Allow the user to press a key, then reboot
+	xorw	%ax, %ax
+	int	$0x16
+	int	$0x19
+
+	# int 0x19 should never return.  In case it does anyway,
+	# invoke the BIOS reset code...
+	ljmp	$0xf000,$0xfff0
+
+	.section ".bsdata", "a"
+bugger_off_msg:
+	.ascii	"Direct booting from floppy is no longer supported.\r\n"
+	.ascii	"Please use a boot loader program instead.\r\n"
+	.ascii	"\n"
+	.ascii	"Remove disk and press any key to reboot . . .\r\n"
+	.byte	0
+
+
+	# Kernel attributes; used by setup.  This is part 1 of the
+	# header, from the old boot sector.
+
+	.section ".header", "a"
+	.globl	hdr
+hdr:
+setup_sects:	.byte SETUPSECTS
+root_flags:	.word ROOT_RDONLY
+syssize:	.long SYSSIZE
+ram_size:	.word RAMDISK
+vid_mode:	.word SVGA_MODE
+root_dev:	.word ROOT_DEV
+boot_flag:	.word 0xAA55
+
+	# offset 512, entry point
+
+	.globl	_start
+_start:
+		# Explicitly enter this as bytes, or the assembler
+		# tries to generate a 3-byte jump here, which causes
+		# everything else to push off to the wrong offset.
+		.byte	0xeb		# short (2-byte) jump
+		.byte	start_of_setup-1f
+1:
+
+	# Part 2 of the header, from the old setup.S
+
+		.ascii	"HdrS"		# header signature
+		.word	0x0206		# header version number (>= 0x0105)
+					# or else old loadlin-1.5 will fail)
+		.globl realmode_swtch
+realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
+start_sys_seg:	.word	SYSSEG
+		.word	kernel_version-512 # pointing to kernel version string
+					# above section of header is compatible
+					# with loadlin-1.5 (header v1.5). Don't
+					# change it.
+
+type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
+					#      Bootlin, SYSLX, bootsect...)
+					# See Documentation/i386/boot.txt for
+					# assigned ids
+
+# flags, unused bits must be zero (RFU) bit within loadflags
+loadflags:
+LOADED_HIGH	= 1			# If set, the kernel is loaded high
+CAN_USE_HEAP	= 0x80			# If set, the loader also has set
+					# heap_end_ptr to tell how much
+					# space behind setup.S can be used for
+					# heap purposes.
+					# Only the loader knows what is free
+#ifndef __BIG_KERNEL__
+		.byte	0
+#else
+		.byte	LOADED_HIGH
+#endif
+
+setup_move_size: .word  0x8000		# size to move, when setup is not
+					# loaded at 0x90000. We will move setup
+					# to 0x90000 then just before jumping
+					# into the kernel. However, only the
+					# loader knows how much data behind
+					# us also needs to be loaded.
+
+code32_start:				# here loaders can put a different
+					# start address for 32-bit code.
+#ifndef __BIG_KERNEL__
+		.long	0x1000		#   0x1000 = default for zImage
+#else
+		.long	0x100000	# 0x100000 = default for big kernel
+#endif
+
+ramdisk_image:	.long	0		# address of loaded ramdisk image
+					# Here the loader puts the 32-bit
+					# address where it loaded the image.
+					# This only will be read by the kernel.
+
+ramdisk_size:	.long	0		# its size in bytes
+
+bootsect_kludge:
+		.long	0		# obsolete
+
+heap_end_ptr:	.word	_end+1024	# (Header version 0x0201 or later)
+					# space from here (exclusive) down to
+					# end of setup code can be used by setup
+					# for local heap purposes.
+
+pad1:		.word	0
+cmd_line_ptr:	.long	0		# (Header version 0x0202 or later)
+					# If nonzero, a 32-bit pointer
+					# to the kernel command line.
+					# The command line should be
+					# located between the start of
+					# setup and the end of low
+					# memory (0xa0000), or it may
+					# get overwritten before it
+					# gets read.  If this field is
+					# used, there is no longer
+					# anything magical about the
+					# 0x90000 segment; the setup
+					# can be located anywhere in
+					# low memory 0x10000 or higher.
+
+ramdisk_max:	.long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
+					# (Header version 0x0203 or later)
+					# The highest safe address for
+					# the contents of an initrd
+
+kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN	#physical addr alignment
+						#required for protected mode
+						#kernel
+#ifdef CONFIG_RELOCATABLE
+relocatable_kernel:    .byte 1
+#else
+relocatable_kernel:    .byte 0
+#endif
+pad2:			.byte 0
+pad3:			.word 0
+
+cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
+                                                #added with boot protocol
+                                                #version 2.06
+
+# End of setup header #####################################################
+
+	.section ".inittext", "ax"
+start_of_setup:
+#ifdef SAFE_RESET_DISK_CONTROLLER
+# Reset the disk controller.
+	movw	$0x0000, %ax		# Reset disk controller
+	movb	$0x80, %dl		# All disks
+	int	$0x13
+#endif
+
+# We will have entired with %cs = %ds+0x20, normalize %cs so
+# it is on par with the other segments.
+	pushw	%ds
+	pushw	$setup2
+	lretw
+
+setup2:
+# Force %es = %ds
+	movw	%ds, %ax
+	movw	%ax, %es
+	cld
+
+# Stack paranoia: align the stack and make sure it is good
+# for both 16- and 32-bit references.  In particular, if we
+# were meant to have been using the full 16-bit segment, the
+# caller might have set %sp to zero, which breaks %esp-based
+# references.
+	andw	$~3, %sp	# dword align (might as well...)
+	jnz	1f
+	movw	$0xfffc, %sp	# Make sure we're not zero
+1:	movzwl	%sp, %esp	# Clear upper half of %esp
+	sti
+
+# Check signature at end of setup
+	cmpl	$0x5a5aaa55, setup_sig
+	jne	setup_bad
+
+# Zero the bss
+	movw	$__bss_start, %di
+	movw	$_end+3, %cx
+	xorl	%eax, %eax
+	subw	%di, %cx
+	shrw	$2, %cx
+	rep; stosl
+
+# Jump to C code (should not return)
+	calll	main
+
+# Setup corrupt somehow...
+setup_bad:
+	movl	$setup_corrupt, %eax
+	calll	puts
+	# Fall through...
+
+	.globl	die
+	.type	die, @function
+die:
+	hlt
+	jmp	die
+
+	.size	die, .-due
+
+	.section ".initdata", "a"
+setup_corrupt:
+	.byte	7
+	.string	"No setup signature found..."
diff --git a/arch/i386/boot/main.c b/arch/i386/boot/main.c
new file mode 100644
index 0000000..7f01f96
--- /dev/null
+++ b/arch/i386/boot/main.c
@@ -0,0 +1,161 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/main.c
+ *
+ * Main module for the real-mode kernel code
+ */
+
+#include "boot.h"
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+char *HEAP = _end;
+char *heap_end = _end;		/* Default end of heap = no heap */
+
+/*
+ * Copy the header into the boot parameter block.  Since this
+ * screws up the old-style command line protocol, adjust by
+ * filling in the new-style command line pointer instead.
+ */
+#define OLD_CL_MAGIC	0xA33F
+#define OLD_CL_ADDRESS	0x20
+
+static void copy_boot_params(void)
+{
+	struct old_cmdline {
+		u16 cl_magic;
+		u16 cl_offset;
+	};
+	const struct old_cmdline * const oldcmd =
+		(const struct old_cmdline *)OLD_CL_ADDRESS;
+
+	BUILD_BUG_ON(sizeof boot_params != 4096);
+	memcpy(&boot_params.hdr, &hdr, sizeof hdr);
+
+	if (!boot_params.hdr.cmd_line_ptr &&
+	    oldcmd->cl_magic == OLD_CL_MAGIC) {
+		/* Old-style command line protocol. */
+		u16 cmdline_seg;
+
+		/* Figure out if the command line falls in the region
+		   of memory that an old kernel would have copied up
+		   to 0x90000... */
+		if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)
+			cmdline_seg = ds();
+		else
+			cmdline_seg = 0x9000;
+
+		boot_params.hdr.cmd_line_ptr =
+			(cmdline_seg << 4) + oldcmd->cl_offset;
+	}
+}
+
+/*
+ * Set the keyboard repeat rate to maximum.  Unclear why this
+ * is done here; this might be possible to kill off as stale code.
+ */
+static void keyboard_set_repeat(void)
+{
+	u16 ax = 0x0305;
+	u16 bx = 0;
+	asm volatile("int $0x16"
+		     : "+a" (ax), "+b" (bx)
+		     : : "ecx", "edx", "esi", "edi");
+}
+
+/*
+ * Get Intel SpeedStep IST information.
+ */
+static void query_speedstep_ist(void)
+{
+	asm("int $0x15"
+	    : "=a" (boot_params.speedstep_info[0]),
+	      "=b" (boot_params.speedstep_info[1]),
+	      "=c" (boot_params.speedstep_info[2]),
+	      "=d" (boot_params.speedstep_info[3])
+	    : "a" (0x0000e980),	 /* IST Support */
+	      "d" (0x47534943)); /* Request value */
+}
+
+/*
+ * Tell the BIOS what CPU mode we intend to run in.
+ */
+static void set_bios_mode(void)
+{
+#ifdef CONFIG_X86_64
+	u32 eax, ebx;
+
+	eax = 0xec00;
+	ebx = 2;
+	asm volatile("int $0x15"
+		     : "+a" (eax), "+b" (ebx)
+		     : : "ecx", "edx", "esi", "edi");
+#endif
+}
+
+void main(void)
+{
+	/* First, copy the boot header into the "zeropage" */
+	copy_boot_params();
+
+	/* End of heap check */
+	if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
+		heap_end = (char *)(boot_params.hdr.heap_end_ptr
+				    +0x200-STACK_SIZE);
+	} else {
+		/* Boot protocol 2.00 only, no heap available */
+		puts("WARNING: Ancient bootloader, some functionality "
+		     "may be limited!\n");
+	}
+
+	/* Make sure we have all the proper CPU support */
+	if (validate_cpu()) {
+		puts("Unable to boot - please use a kernel appropriate "
+		     "for your CPU.\n");
+		die();
+	}
+
+	/* Tell the BIOS what CPU mode we intend to run in. */
+	set_bios_mode();
+
+	/* Detect memory layout */
+	detect_memory();
+
+	/* Set keyboard repeat rate (why?) */
+	keyboard_set_repeat();
+
+	/* Set the video mode */
+	set_video();
+
+	/* Query MCA information */
+	query_mca();
+
+	/* Voyager */
+#ifdef CONFIG_X86_VOYAGER
+	query_voyager();
+#endif
+
+	/* Query SpeedStep IST information */
+	query_speedstep_ist();
+
+	/* Query APM information */
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+	query_apm_bios();
+#endif
+
+	/* Query EDD information */
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+	query_edd();
+#endif
+	/* Do the last things and invoke protected mode */
+	go_to_protected_mode();
+}
diff --git a/arch/i386/boot/mca.c b/arch/i386/boot/mca.c
new file mode 100644
index 0000000..9b68bd1
--- /dev/null
+++ b/arch/i386/boot/mca.c
@@ -0,0 +1,43 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/mca.c
+ *
+ * Get the MCA system description table
+ */
+
+#include "boot.h"
+
+int query_mca(void)
+{
+	u8 err;
+	u16 es, bx, len;
+
+	asm("pushw %%es ; "
+	    "int $0x15 ; "
+	    "setc %0 ; "
+	    "movw %%es, %1 ; "
+	    "popw %%es"
+	    : "=acdSDm" (err), "=acdSDm" (es), "=b" (bx)
+	    : "a" (0xc000));
+
+	if (err)
+		return -1;	/* No MCA present */
+
+	set_fs(es);
+	len = rdfs16(bx);
+
+	if (len > sizeof(boot_params.sys_desc_table))
+		len = sizeof(boot_params.sys_desc_table);
+
+	copy_from_fs(&boot_params.sys_desc_table, bx, len);
+	return 0;
+}
diff --git a/arch/i386/boot/memory.c b/arch/i386/boot/memory.c
new file mode 100644
index 0000000..1a2e62d
--- /dev/null
+++ b/arch/i386/boot/memory.c
@@ -0,0 +1,99 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/memory.c
+ *
+ * Memory detection code
+ */
+
+#include "boot.h"
+
+#define SMAP	0x534d4150	/* ASCII "SMAP" */
+
+static int detect_memory_e820(void)
+{
+	u32 next = 0;
+	u32 size, id;
+	u8 err;
+	struct e820entry *desc = boot_params.e820_map;
+
+	do {
+		size = sizeof(struct e820entry);
+		id = SMAP;
+		asm("int $0x15; setc %0"
+		    : "=am" (err), "+b" (next), "+d" (id), "+c" (size),
+		      "=m" (*desc)
+		    : "D" (desc), "a" (0xe820));
+
+		if (err || id != SMAP)
+			break;
+
+		boot_params.e820_entries++;
+		desc++;
+	} while (next && boot_params.e820_entries < E820MAX);
+
+	return boot_params.e820_entries;
+}
+
+static int detect_memory_e801(void)
+{
+	u16 ax, bx, cx, dx;
+	u8 err;
+
+	bx = cx = dx = 0;
+	ax = 0xe801;
+	asm("stc; int $0x15; setc %0"
+	    : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
+
+	if (err)
+		return -1;
+
+	/* Do we really need to do this? */
+	if (cx || dx) {
+		ax = cx;
+		bx = dx;
+	}
+
+	if (ax > 15*1024)
+		return -1;	/* Bogus! */
+
+	/* This ignores memory above 16MB if we have a memory hole
+	   there.  If someone actually finds a machine with a memory
+	   hole at 16MB and no support for 0E820h they should probably
+	   generate a fake e820 map. */
+	boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax;
+
+	return 0;
+}
+
+static int detect_memory_88(void)
+{
+	u16 ax;
+	u8 err;
+
+	ax = 0x8800;
+	asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax));
+
+	boot_params.screen_info.ext_mem_k = ax;
+
+	return -err;
+}
+
+int detect_memory(void)
+{
+	if (detect_memory_e820() > 0)
+		return 0;
+
+	if (!detect_memory_e801())
+		return 0;
+
+	return detect_memory_88();
+}
diff --git a/arch/i386/boot/pm.c b/arch/i386/boot/pm.c
new file mode 100644
index 0000000..3fa53e1
--- /dev/null
+++ b/arch/i386/boot/pm.c
@@ -0,0 +1,170 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/pm.c
+ *
+ * Prepare the machine for transition to protected mode.
+ */
+
+#include "boot.h"
+#include <asm/segment.h>
+
+/*
+ * Invoke the realmode switch hook if present; otherwise
+ * disable all interrupts.
+ */
+static void realmode_switch_hook(void)
+{
+	if (boot_params.hdr.realmode_swtch) {
+		asm volatile("lcallw *%0"
+			     : : "m" (boot_params.hdr.realmode_swtch)
+			     : "eax", "ebx", "ecx", "edx");
+	} else {
+		asm volatile("cli");
+		outb(0x80, 0x70); /* Disable NMI */
+		io_delay();
+	}
+}
+
+/*
+ * A zImage kernel is loaded at 0x10000 but wants to run at 0x1000.
+ * A bzImage kernel is loaded and runs at 0x100000.
+ */
+static void move_kernel_around(void)
+{
+	/* Note: rely on the compile-time option here rather than
+	   the LOADED_HIGH flag.  The Qemu kernel loader unconditionally
+	   sets the loadflags to zero. */
+#ifndef __BIG_KERNEL__
+	u16 dst_seg, src_seg;
+	u32 syssize;
+
+	dst_seg =  0x1000 >> 4;
+	src_seg = 0x10000 >> 4;
+	syssize = boot_params.hdr.syssize; /* Size in 16-byte paragraphs */
+
+	while (syssize) {
+		int paras  = (syssize >= 0x1000) ? 0x1000 : syssize;
+		int dwords = paras << 2;
+
+		asm volatile("pushw %%es ; "
+			     "pushw %%ds ; "
+			     "movw %1,%%es ; "
+			     "movw %2,%%ds ; "
+			     "xorw %%di,%%di ; "
+			     "xorw %%si,%%si ; "
+			     "rep;movsl ; "
+			     "popw %%ds ; "
+			     "popw %%es"
+			     : "+c" (dwords)
+			     : "rm" (dst_seg), "rm" (src_seg)
+			     : "esi", "edi");
+
+		syssize -= paras;
+		dst_seg += paras;
+		src_seg += paras;
+	}
+#endif
+}
+
+/*
+ * Disable all interrupts at the legacy PIC.
+ */
+static void mask_all_interrupts(void)
+{
+	outb(0xff, 0xa1);	/* Mask all interrupts on the seconday PIC */
+	io_delay();
+	outb(0xfb, 0x21);	/* Mask all but cascade on the primary PIC */
+	io_delay();
+}
+
+/*
+ * Reset IGNNE# if asserted in the FPU.
+ */
+static void reset_coprocessor(void)
+{
+	outb(0, 0xf0);
+	io_delay();
+	outb(0, 0xf1);
+	io_delay();
+}
+
+/*
+ * Set up the GDT
+ */
+#define GDT_ENTRY(flags,base,limit)		\
+	(((u64)(base & 0xff000000) << 32) |	\
+	 ((u64)flags << 40) |			\
+	 ((u64)(limit & 0x00ff0000) << 32) |	\
+	 ((u64)(base & 0x00ffff00) << 16) |	\
+	 ((u64)(limit & 0x0000ffff)))
+
+struct gdt_ptr {
+	u16 len;
+	u32 ptr;
+} __attribute__((packed));
+
+static void setup_gdt(void)
+{
+	/* There are machines which are known to not boot with the GDT
+	   being 8-byte unaligned.  Intel recommends 16 byte alignment. */
+	static const u64 boot_gdt[] __attribute__((aligned(16))) = {
+		/* CS: code, read/execute, 4 GB, base 0 */
+		[GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+		/* DS: data, read/write, 4 GB, base 0 */
+		[GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
+	};
+	struct gdt_ptr gdt;
+
+	gdt.len = sizeof(boot_gdt)-1;
+	gdt.ptr = (u32)&boot_gdt + (ds() << 4);
+
+	asm volatile("lgdtl %0" : : "m" (gdt));
+}
+
+/*
+ * Set up the IDT
+ */
+static void setup_idt(void)
+{
+	static const struct gdt_ptr null_idt = {0, 0};
+	asm volatile("lidtl %0" : : "m" (null_idt));
+}
+
+/*
+ * Actual invocation sequence
+ */
+void go_to_protected_mode(void)
+{
+	/* Hook before leaving real mode, also disables interrupts */
+	realmode_switch_hook();
+
+	/* Move the kernel/setup to their final resting places */
+	move_kernel_around();
+
+	/* Enable the A20 gate */
+	if (enable_a20()) {
+		puts("A20 gate not responding, unable to boot...\n");
+		die();
+	}
+
+	/* Reset coprocessor (IGNNE#) */
+	reset_coprocessor();
+
+	/* Mask all interrupts in the PIC */
+	mask_all_interrupts();
+
+	/* Actual transition to protected mode... */
+	setup_idt();
+	setup_gdt();
+	protected_mode_jump(boot_params.hdr.code32_start,
+			    (u32)&boot_params + (ds() << 4));
+}
diff --git a/arch/i386/boot/pmjump.S b/arch/i386/boot/pmjump.S
new file mode 100644
index 0000000..2e55923
--- /dev/null
+++ b/arch/i386/boot/pmjump.S
@@ -0,0 +1,54 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/pmjump.S
+ *
+ * The actual transition into protected mode
+ */
+
+#include <asm/boot.h>
+#include <asm/segment.h>
+
+	.text
+
+	.globl	protected_mode_jump
+	.type	protected_mode_jump, @function
+
+	.code16
+
+/*
+ * void protected_mode_jump(u32 entrypoint, u32 bootparams);
+ */
+protected_mode_jump:
+	xorl	%ebx, %ebx		# Flag to indicate this is a boot
+	movl	%edx, %esi		# Pointer to boot_params table
+	movl	%eax, 2f		# Patch ljmpl instruction
+	jmp	1f			# Short jump to flush instruction q.
+
+1:
+	movw	$__BOOT_DS, %cx
+
+	movl	%cr0, %edx
+	orb	$1, %dl			# Protected mode (PE) bit
+	movl	%edx, %cr0
+
+	movw	%cx, %ds
+	movw	%cx, %es
+	movw	%cx, %fs
+	movw	%cx, %gs
+	movw	%cx, %ss
+
+	# Jump to the 32-bit entrypoint
+	.byte	0x66, 0xea		# ljmpl opcode
+2:	.long	0			# offset
+	.word	__BOOT_CS		# segment
+
+	.size	protected_mode_jump, .-protected_mode_jump
diff --git a/arch/i386/boot/printf.c b/arch/i386/boot/printf.c
new file mode 100644
index 0000000..1a09f93
--- /dev/null
+++ b/arch/i386/boot/printf.c
@@ -0,0 +1,307 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/printf.c
+ *
+ * Oh, it's a waste of space, but oh-so-yummy for debugging.  This
+ * version of printf() does not include 64-bit support.  "Live with
+ * it."
+ *
+ */
+
+#include "boot.h"
+
+static int skip_atoi(const char **s)
+{
+	int i = 0;
+
+	while (isdigit(**s))
+		i = i * 10 + *((*s)++) - '0';
+	return i;
+}
+
+#define ZEROPAD	1		/* pad with zero */
+#define SIGN	2		/* unsigned/signed long */
+#define PLUS	4		/* show plus */
+#define SPACE	8		/* space if plus */
+#define LEFT	16		/* left justified */
+#define SPECIAL	32		/* 0x */
+#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char *number(char *str, long num, int base, int size, int precision,
+		    int type)
+{
+	char c, sign, tmp[66];
+	const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+	int i;
+
+	if (type & LARGE)
+		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	if (type & LEFT)
+		type &= ~ZEROPAD;
+	if (base < 2 || base > 36)
+		return 0;
+	c = (type & ZEROPAD) ? '0' : ' ';
+	sign = 0;
+	if (type & SIGN) {
+		if (num < 0) {
+			sign = '-';
+			num = -num;
+			size--;
+		} else if (type & PLUS) {
+			sign = '+';
+			size--;
+		} else if (type & SPACE) {
+			sign = ' ';
+			size--;
+		}
+	}
+	if (type & SPECIAL) {
+		if (base == 16)
+			size -= 2;
+		else if (base == 8)
+			size--;
+	}
+	i = 0;
+	if (num == 0)
+		tmp[i++] = '0';
+	else
+		while (num != 0)
+			tmp[i++] = digits[do_div(num, base)];
+	if (i > precision)
+		precision = i;
+	size -= precision;
+	if (!(type & (ZEROPAD + LEFT)))
+		while (size-- > 0)
+			*str++ = ' ';
+	if (sign)
+		*str++ = sign;
+	if (type & SPECIAL) {
+		if (base == 8)
+			*str++ = '0';
+		else if (base == 16) {
+			*str++ = '0';
+			*str++ = digits[33];
+		}
+	}
+	if (!(type & LEFT))
+		while (size-- > 0)
+			*str++ = c;
+	while (i < precision--)
+		*str++ = '0';
+	while (i-- > 0)
+		*str++ = tmp[i];
+	while (size-- > 0)
+		*str++ = ' ';
+	return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	int len;
+	unsigned long num;
+	int i, base;
+	char *str;
+	const char *s;
+
+	int flags;		/* flags to number() */
+
+	int field_width;	/* width of output field */
+	int precision;		/* min. # of digits for integers; max
+				   number of chars for from string */
+	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
+
+	for (str = buf; *fmt; ++fmt) {
+		if (*fmt != '%') {
+			*str++ = *fmt;
+			continue;
+		}
+
+		/* process flags */
+		flags = 0;
+	      repeat:
+		++fmt;		/* this also skips first '%' */
+		switch (*fmt) {
+		case '-':
+			flags |= LEFT;
+			goto repeat;
+		case '+':
+			flags |= PLUS;
+			goto repeat;
+		case ' ':
+			flags |= SPACE;
+			goto repeat;
+		case '#':
+			flags |= SPECIAL;
+			goto repeat;
+		case '0':
+			flags |= ZEROPAD;
+			goto repeat;
+		}
+
+		/* get field width */
+		field_width = -1;
+		if (isdigit(*fmt))
+			field_width = skip_atoi(&fmt);
+		else if (*fmt == '*') {
+			++fmt;
+			/* it's the next argument */
+			field_width = va_arg(args, int);
+			if (field_width < 0) {
+				field_width = -field_width;
+				flags |= LEFT;
+			}
+		}
+
+		/* get the precision */
+		precision = -1;
+		if (*fmt == '.') {
+			++fmt;
+			if (isdigit(*fmt))
+				precision = skip_atoi(&fmt);
+			else if (*fmt == '*') {
+				++fmt;
+				/* it's the next argument */
+				precision = va_arg(args, int);
+			}
+			if (precision < 0)
+				precision = 0;
+		}
+
+		/* get the conversion qualifier */
+		qualifier = -1;
+		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+			qualifier = *fmt;
+			++fmt;
+		}
+
+		/* default base */
+		base = 10;
+
+		switch (*fmt) {
+		case 'c':
+			if (!(flags & LEFT))
+				while (--field_width > 0)
+					*str++ = ' ';
+			*str++ = (unsigned char)va_arg(args, int);
+			while (--field_width > 0)
+				*str++ = ' ';
+			continue;
+
+		case 's':
+			s = va_arg(args, char *);
+			len = strnlen(s, precision);
+
+			if (!(flags & LEFT))
+				while (len < field_width--)
+					*str++ = ' ';
+			for (i = 0; i < len; ++i)
+				*str++ = *s++;
+			while (len < field_width--)
+				*str++ = ' ';
+			continue;
+
+		case 'p':
+			if (field_width == -1) {
+				field_width = 2 * sizeof(void *);
+				flags |= ZEROPAD;
+			}
+			str = number(str,
+				     (unsigned long)va_arg(args, void *), 16,
+				     field_width, precision, flags);
+			continue;
+
+		case 'n':
+			if (qualifier == 'l') {
+				long *ip = va_arg(args, long *);
+				*ip = (str - buf);
+			} else {
+				int *ip = va_arg(args, int *);
+				*ip = (str - buf);
+			}
+			continue;
+
+		case '%':
+			*str++ = '%';
+			continue;
+
+			/* integer number formats - set up the flags and "break" */
+		case 'o':
+			base = 8;
+			break;
+
+		case 'X':
+			flags |= LARGE;
+		case 'x':
+			base = 16;
+			break;
+
+		case 'd':
+		case 'i':
+			flags |= SIGN;
+		case 'u':
+			break;
+
+		default:
+			*str++ = '%';
+			if (*fmt)
+				*str++ = *fmt;
+			else
+				--fmt;
+			continue;
+		}
+		if (qualifier == 'l')
+			num = va_arg(args, unsigned long);
+		else if (qualifier == 'h') {
+			num = (unsigned short)va_arg(args, int);
+			if (flags & SIGN)
+				num = (short)num;
+		} else if (flags & SIGN)
+			num = va_arg(args, int);
+		else
+			num = va_arg(args, unsigned int);
+		str = number(str, num, base, field_width, precision, flags);
+	}
+	*str = '\0';
+	return str - buf;
+}
+
+int sprintf(char *buf, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i = vsprintf(buf, fmt, args);
+	va_end(args);
+	return i;
+}
+
+int printf(const char *fmt, ...)
+{
+	char printf_buf[1024];
+	va_list args;
+	int printed;
+
+	va_start(args, fmt);
+	printed = vsprintf(printf_buf, fmt, args);
+	va_end(args);
+
+	puts(printf_buf);
+
+	return printed;
+}
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
deleted file mode 100644
index f8b3b9c..0000000
--- a/arch/i386/boot/setup.S
+++ /dev/null
@@ -1,1073 +0,0 @@
-/*
- *	setup.S		Copyright (C) 1991, 1992 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- * Move PS/2 aux init code to psaux.c
- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *
- * some changes and additional features by Christoph Niemann,
- * March 1993/June 1994 (Christoph.Niemann@linux.org)
- *
- * add APM BIOS checking by Stephen Rothwell, May 1994
- * (sfr@canb.auug.org.au)
- *
- * High load stuff, initrd support and position independency
- * by Hans Lermen & Werner Almesberger, February 1996
- * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
- *
- * Video handling moved to video.S by Martin Mares, March 1996
- * <mj@k332.feld.cvut.cz>
- *
- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
- * parsons) to avoid loadlin confusion, July 1997
- *
- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
- * <stiker@northlink.com>
- *
- * Fix to work around buggy BIOSes which don't use carry bit correctly
- * and/or report extended memory in CX/DX for e801h memory size detection 
- * call.  As a result the kernel got wrong figures.  The int15/e801h docs
- * from Ralf Brown interrupt list seem to indicate AX/BX should be used
- * anyway.  So to avoid breaking many machines (presumably there was a reason
- * to orginally use CX/DX instead of AX/BX), we do a kludge to see
- * if CX/DX have been changed in the e801 call and if so use AX/BX .
- * Michael Miller, April 2001 <michaelm@mjmm.org>
- *
- * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
- * by Robert Schwebel, December 2001 <robert@schwebel.de>
- */
-
-#include <asm/segment.h>
-#include <linux/utsrelease.h>
-#include <linux/compile.h>
-#include <asm/boot.h>
-#include <asm/e820.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-	
-/* Signature words to ensure LILO loaded us right */
-#define SIG1	0xAA55
-#define SIG2	0x5A5A
-
-INITSEG  = DEF_INITSEG		# 0x9000, we move boot here, out of the way
-SYSSEG   = DEF_SYSSEG		# 0x1000, system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG		# 0x9020, this is the current segment
-				# ... and the former contents of CS
-
-DELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020
-
-.code16
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-start:
-	jmp	trampoline
-
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
-		.ascii	"HdrS"		# header signature
-		.word	0x0206		# header version number (>= 0x0105)
-					# or else old loadlin-1.5 will fail)
-realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
-start_sys_seg:	.word	SYSSEG
-		.word	kernel_version	# pointing to kernel version string
-					# above section of header is compatible
-					# with loadlin-1.5 (header v1.5). Don't
-					# change it.
-
-type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
-					#      Bootlin, SYSLX, bootsect...)
-					# See Documentation/i386/boot.txt for
-					# assigned ids
-	
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH	= 1			# If set, the kernel is loaded high
-CAN_USE_HEAP	= 0x80			# If set, the loader also has set
-					# heap_end_ptr to tell how much
-					# space behind setup.S can be used for
-					# heap purposes.
-					# Only the loader knows what is free
-#ifndef __BIG_KERNEL__
-		.byte	0
-#else
-		.byte	LOADED_HIGH
-#endif
-
-setup_move_size: .word  0x8000		# size to move, when setup is not
-					# loaded at 0x90000. We will move setup 
-					# to 0x90000 then just before jumping
-					# into the kernel. However, only the
-					# loader knows how much data behind
-					# us also needs to be loaded.
-
-code32_start:				# here loaders can put a different
-					# start address for 32-bit code.
-#ifndef __BIG_KERNEL__
-		.long	0x1000		#   0x1000 = default for zImage
-#else
-		.long	0x100000	# 0x100000 = default for big kernel
-#endif
-
-ramdisk_image:	.long	0		# address of loaded ramdisk image
-					# Here the loader puts the 32-bit
-					# address where it loaded the image.
-					# This only will be read by the kernel.
-
-ramdisk_size:	.long	0		# its size in bytes
-
-bootsect_kludge:
-		.long	0		# obsolete
-
-heap_end_ptr:	.word	modelist+1024	# (Header version 0x0201 or later)
-					# space from here (exclusive) down to
-					# end of setup code can be used by setup
-					# for local heap purposes.
-
-pad1:		.word	0
-cmd_line_ptr:	.long 0			# (Header version 0x0202 or later)
-					# If nonzero, a 32-bit pointer
-					# to the kernel command line.
-					# The command line should be
-					# located between the start of
-					# setup and the end of low
-					# memory (0xa0000), or it may
-					# get overwritten before it
-					# gets read.  If this field is
-					# used, there is no longer
-					# anything magical about the
-					# 0x90000 segment; the setup
-					# can be located anywhere in
-					# low memory 0x10000 or higher.
-
-ramdisk_max:	.long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
-					# (Header version 0x0203 or later)
-					# The highest safe address for
-					# the contents of an initrd
-
-kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN 	#physical addr alignment
-						#required for protected mode
-						#kernel
-#ifdef CONFIG_RELOCATABLE
-relocatable_kernel:    .byte 1
-#else
-relocatable_kernel:    .byte 0
-#endif
-pad2:			.byte 0
-pad3:			.word 0
-
-cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
-                                                #added with boot protocol
-                                                #version 2.06
-
-trampoline:	call	start_of_setup
-		.align 16
-					# The offset at this point is 0x240
-		.space	(0xeff-0x240+1) # E820 & EDD space (ending at 0xeff)
-# End of setup header #####################################################
-
-start_of_setup:
-# Bootlin depends on this being done early
-	movw	$0x01500, %ax
-	movb	$0x81, %dl
-	int	$0x13
-
-#ifdef SAFE_RESET_DISK_CONTROLLER
-# Reset the disk controller.
-	movw	$0x0000, %ax
-	movb	$0x80, %dl
-	int	$0x13
-#endif
-
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
-	movw	%cs, %ax		# aka SETUPSEG
-	movw	%ax, %ds
-# Check signature at end of setup
-	cmpw	$SIG1, setup_sig1
-	jne	bad_sig
-
-	cmpw	$SIG2, setup_sig2
-	jne	bad_sig
-
-	jmp	good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
-	lodsb
-	andb	%al, %al
-	jz	fin
-
-	call	prtchr
-	jmp	prtstr
-
-fin:	ret
-
-# Space printing
-prtsp2:	call	prtspc		# Print double space
-prtspc:	movb	$0x20, %al	# Print single space (note: fall-thru)
-
-# Part of above routine, this one just prints ascii al
-prtchr:	pushw	%ax
-	pushw	%cx
-	movw	$7,%bx
-	movw	$0x01, %cx
-	movb	$0x0e, %ah
-	int	$0x10
-	popw	%cx
-	popw	%ax
-	ret
-
-beep:	movb	$0x07, %al
-	jmp	prtchr
-	
-no_sig_mess: .string	"No setup signature found ..."
-
-good_sig1:
-	jmp	good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
-	movw	%cs, %ax			# SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# INITSEG
-	movw	%ax, %ds
-	xorb	%bh, %bh
-	movb	(497), %bl			# get setup sect from bootsect
-	subw	$4, %bx				# LILO loads 4 sectors of setup
-	shlw	$8, %bx				# convert to words (1sect=2^8 words)
-	movw	%bx, %cx
-	shrw	$3, %bx				# convert to segment
-	addw	$SYSSEG, %bx
-	movw	%bx, %cs:start_sys_seg
-# Move rest of setup code/data to here
-	movw	$2048, %di			# four sectors loaded by LILO
-	subw	%si, %si
-	pushw	%cs
-	popw	%es
-	movw	$SYSSEG, %ax
-	movw	%ax, %ds
-	rep
-	movsw
-	movw	%cs, %ax			# aka SETUPSEG
-	movw	%ax, %ds
-	cmpw	$SIG1, setup_sig1
-	jne	no_sig
-
-	cmpw	$SIG2, setup_sig2
-	jne	no_sig
-
-	jmp	good_sig
-
-no_sig:
-	lea	no_sig_mess, %si
-	call	prtstr
-
-no_sig_loop:
-	hlt
-	jmp	no_sig_loop
-
-good_sig:
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
-	movw	%ax, %ds
-# Check if an old loader tries to load a big-kernel
-	testb	$LOADED_HIGH, %cs:loadflags	# Do we have a big kernel?
-	jz	loader_ok			# No, no danger for old loaders.
-
-	cmpb	$0, %cs:type_of_loader 		# Do we have a loader that
-						# can deal with us?
-	jnz	loader_ok			# Yes, continue.
-
-	pushw	%cs				# No, we have an old loader,
-	popw	%ds				# die. 
-	lea	loader_panic_mess, %si
-	call	prtstr
-
-	jmp	no_sig_loop
-
-loader_panic_mess: .string "Wrong loader, giving up..."
-
-# check minimum cpuid
-# we do this here because it is the last place we can actually
-# show a user visible error message. Later the video modus
-# might be already messed up.
-loader_ok:
-	call verify_cpu
-	testl  %eax,%eax
-	jz	cpu_ok
-	lea	cpu_panic_mess,%si
-	call	prtstr
-1:	jmp	1b
-
-cpu_panic_mess:
-	.asciz  "PANIC: CPU too old for this kernel."
-
-#include "../kernel/verify_cpu.S"
-
-cpu_ok:
-# Get memory size (extended mem, kB)
-
-	xorl	%eax, %eax
-	movl	%eax, (0x1e0)
-#ifndef STANDARD_MEMORY_BIOS_CALL
-	movb	%al, (E820NR)
-# Try three different memory detection schemes.  First, try
-# e820h, which lets us assemble a memory map, then try e801h,
-# which returns a 32-bit memory size, and finally 88h, which
-# returns 0-64m
-
-# method E820H:
-# the memory map from hell.  e820h returns memory classified into
-# a whole bunch of different types, and allows memory holes and
-# everything.  We scan through this memory map and build a list
-# of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
-
-#define SMAP  0x534d4150
-
-meme820:
-	xorl	%ebx, %ebx			# continuation counter
-	movw	$E820MAP, %di			# point into the whitelist
-						# so we can have the bios
-						# directly write into it.
-
-jmpe820:
-	movl	$0x0000e820, %eax		# e820, upper word zeroed
-	movl	$SMAP, %edx			# ascii 'SMAP'
-	movl	$20, %ecx			# size of the e820rec
-	pushw	%ds				# data record.
-	popw	%es
-	int	$0x15				# make the call
-	jc	bail820				# fall to e801 if it fails
-
-	cmpl	$SMAP, %eax			# check the return is `SMAP'
-	jne	bail820				# fall to e801 if it fails
-
-#	cmpl	$1, 16(%di)			# is this usable memory?
-#	jne	again820
-
-	# If this is usable memory, we save it by simply advancing %di by
-	# sizeof(e820rec).
-	#
-good820:
-	movb	(E820NR), %al			# up to 128 entries
-	cmpb	$E820MAX, %al
-	jae	bail820
-
-	incb	(E820NR)
-	movw	%di, %ax
-	addw	$20, %ax
-	movw	%ax, %di
-again820:
-	cmpl	$0, %ebx			# check to see if
-	jne	jmpe820				# %ebx is set to EOF
-bail820:
-
-
-# method E801H:
-# memory size is in 1k chunksizes, to avoid confusing loadlin.
-# we store the 0xe801 memory size in a completely different place,
-# because it will most likely be longer than 16 bits.
-# (use 1e0 because that's what Larry Augustine uses in his
-# alternative new memory detection scheme, and it's sensible
-# to write everything into the same place.)
-
-meme801:
-	stc					# fix to work around buggy
-	xorw	%cx,%cx				# BIOSes which don't clear/set
-	xorw	%dx,%dx				# carry on pass/error of
-						# e801h memory size call
-						# or merely pass cx,dx though
-						# without changing them.
-	movw	$0xe801, %ax
-	int	$0x15
-	jc	mem88
-
-	cmpw	$0x0, %cx			# Kludge to handle BIOSes
-	jne	e801usecxdx			# which report their extended
-	cmpw	$0x0, %dx			# memory in AX/BX rather than
-	jne	e801usecxdx			# CX/DX.  The spec I have read
-	movw	%ax, %cx			# seems to indicate AX/BX 
-	movw	%bx, %dx			# are more reasonable anyway...
-
-e801usecxdx:
-	andl	$0xffff, %edx			# clear sign extend
-	shll	$6, %edx			# and go from 64k to 1k chunks
-	movl	%edx, (0x1e0)			# store extended memory size
-	andl	$0xffff, %ecx			# clear sign extend
- 	addl	%ecx, (0x1e0)			# and add lower memory into
-						# total size.
-
-# Ye Olde Traditional Methode.  Returns the memory size (up to 16mb or
-# 64mb, depending on the bios) in ax.
-mem88:
-
-#endif
-	movb	$0x88, %ah
-	int	$0x15
-	movw	%ax, (2)
-
-# Set the keyboard repeat rate to the max
-	movw	$0x0305, %ax
-	xorw	%bx, %bx
-	int	$0x16
-
-# Check for video adapter and its parameters and allow the
-# user to browse video modes.
-	call	video				# NOTE: we need %ds pointing
-						# to bootsector
-
-# Get hd0 data...
-	xorw	%ax, %ax
-	movw	%ax, %ds
-	ldsw	(4 * 0x41), %si
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	pushw	%ax
-	movw	%ax, %es
-	movw	$0x0080, %di
-	movw	$0x10, %cx
-	pushw	%cx
-	cld
-	rep
- 	movsb
-# Get hd1 data...
-	xorw	%ax, %ax
-	movw	%ax, %ds
-	ldsw	(4 * 0x46), %si
-	popw	%cx
-	popw	%es
-	movw	$0x0090, %di
-	rep
-	movsb
-# Check that there IS a hd1 :-)
-	movw	$0x01500, %ax
-	movb	$0x81, %dl
-	int	$0x13
-	jc	no_disk1
-	
-	cmpb	$3, %ah
-	je	is_disk1
-
-no_disk1:
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
-	movw	%ax, %es
-	movw	$0x0090, %di
-	movw	$0x10, %cx
-	xorw	%ax, %ax
-	cld
-	rep
-	stosb
-is_disk1:
-# check for Micro Channel (MCA) bus
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	movw	%ax, %ds
-	xorw	%ax, %ax
-	movw	%ax, (0xa0)			# set table length to 0
-	movb	$0xc0, %ah
-	stc
-	int	$0x15				# moves feature table to es:bx
-	jc	no_mca
-
-	pushw	%ds
-	movw	%es, %ax
-	movw	%ax, %ds
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	movw	%ax, %es
-	movw	%bx, %si
-	movw	$0xa0, %di
-	movw	(%si), %cx
-	addw	$2, %cx				# table length is a short
-	cmpw	$0x10, %cx
-	jc	sysdesc_ok
-
-	movw	$0x10, %cx			# we keep only first 16 bytes
-sysdesc_ok:
-	rep
-	movsb
-	popw	%ds
-no_mca:
-#ifdef CONFIG_X86_VOYAGER
-	movb	$0xff, 0x40	# flag on config found
-	movb	$0xc0, %al
-	mov	$0xff, %ah
-	int	$0x15		# put voyager config info at es:di
-	jc	no_voyager
-	movw	$0x40, %si	# place voyager info in apm table
-	cld
-	movw	$7, %cx
-voyager_rep:
-	movb	%es:(%di), %al
-	movb	%al,(%si)
-	incw	%di
-	incw	%si
-	decw	%cx
-	jnz	voyager_rep
-no_voyager:	
-#endif
-# Check for PS/2 pointing device
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	movw	%ax, %ds
-	movb	$0, (0x1ff)			# default is no pointing device
-	int	$0x11				# int 0x11: equipment list
-	testb	$0x04, %al			# check if mouse installed
-	jz	no_psmouse
-
-	movb	$0xAA, (0x1ff)			# device present
-no_psmouse:
-
-#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
-	movl	$0x0000E980, %eax		# IST Support 
-	movl	$0x47534943, %edx		# Request value
-	int	$0x15
-
-	movl	%eax, (96)
-	movl	%ebx, (100)
-	movl	%ecx, (104)
-	movl	%edx, (108)
-#endif
-
-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
-# Then check for an APM BIOS...
-						# %ds points to the bootsector
-	movw	$0, 0x40			# version = 0 means no APM BIOS
-	movw	$0x05300, %ax			# APM BIOS installation check
-	xorw	%bx, %bx
-	int	$0x15
-	jc	done_apm_bios			# Nope, no APM BIOS
-	
-	cmpw	$0x0504d, %bx			# Check for "PM" signature
-	jne	done_apm_bios			# No signature, no APM BIOS
-
-	andw	$0x02, %cx			# Is 32 bit supported?
-	je	done_apm_bios			# No 32-bit, no (good) APM BIOS
-
-	movw	$0x05304, %ax			# Disconnect first just in case
-	xorw	%bx, %bx
-	int	$0x15				# ignore return code
-	movw	$0x05303, %ax			# 32 bit connect
-	xorl	%ebx, %ebx
-	xorw	%cx, %cx			# paranoia :-)
-	xorw	%dx, %dx			#   ...
-	xorl	%esi, %esi			#   ...
-	xorw	%di, %di			#   ...
-	int	$0x15
-	jc	no_32_apm_bios			# Ack, error. 
-
-	movw	%ax,  (66)			# BIOS code segment
-	movl	%ebx, (68)			# BIOS entry point offset
-	movw	%cx,  (72)			# BIOS 16 bit code segment
-	movw	%dx,  (74)			# BIOS data segment
-	movl	%esi, (78)			# BIOS code segment lengths
-	movw	%di,  (82)			# BIOS data segment length
-# Redo the installation check as the 32 bit connect
-# modifies the flags returned on some BIOSs
-	movw	$0x05300, %ax			# APM BIOS installation check
-	xorw	%bx, %bx
-	xorw	%cx, %cx			# paranoia
-	int	$0x15
-	jc	apm_disconnect			# error -> shouldn't happen
-
-	cmpw	$0x0504d, %bx			# check for "PM" signature
-	jne	apm_disconnect			# no sig -> shouldn't happen
-
-	movw	%ax, (64)			# record the APM BIOS version
-	movw	%cx, (76)			# and flags
-	jmp	done_apm_bios
-
-apm_disconnect:					# Tidy up
-	movw	$0x05304, %ax			# Disconnect
-	xorw	%bx, %bx
-	int	$0x15				# ignore return code
-
-	jmp	done_apm_bios
-
-no_32_apm_bios:
-	andw	$0xfffd, (76)			# remove 32 bit support bit
-done_apm_bios:
-#endif
-
-#include "edd.S"
-
-# Now we want to move to protected mode ...
-	cmpw	$0, %cs:realmode_swtch
-	jz	rmodeswtch_normal
-
-	lcall	*%cs:realmode_swtch
-
-	jmp	rmodeswtch_end
-
-rmodeswtch_normal:
-        pushw	%cs
-	call	default_switch
-
-rmodeswtch_end:
-# Now we move the system to its rightful place ... but we check if we have a
-# big-kernel. In that case we *must* not move it ...
-	testb	$LOADED_HIGH, %cs:loadflags
-	jz	do_move0			# .. then we have a normal low
-						# loaded zImage
-						# .. or else we have a high
-						# loaded bzImage
-	jmp	end_move			# ... and we skip moving
-
-do_move0:
-	movw	$0x100, %ax			# start of destination segment
-	movw	%cs, %bp			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %bp		# aka INITSEG
-	movw	%cs:start_sys_seg, %bx		# start of source segment
-	cld
-do_move:
-	movw	%ax, %es			# destination segment
-	incb	%ah				# instead of add ax,#0x100
-	movw	%bx, %ds			# source segment
-	addw	$0x100, %bx
-	subw	%di, %di
-	subw	%si, %si
-	movw 	$0x800, %cx
-	rep
-	movsw
-	cmpw	%bp, %bx			# assume start_sys_seg > 0x200,
-						# so we will perhaps read one
-						# page more than needed, but
-						# never overwrite INITSEG
-						# because destination is a
-						# minimum one page below source
-	jb	do_move
-
-end_move:
-# then we load the segment descriptors
-	movw	%cs, %ax			# aka SETUPSEG
-	movw	%ax, %ds
-		
-# Check whether we need to be downward compatible with version <=201
-	cmpl	$0, cmd_line_ptr
-	jne	end_move_self		# loader uses version >=202 features
-	cmpb	$0x20, type_of_loader
-	je	end_move_self		# bootsect loader, we know of it
-
-# Boot loader doesnt support boot protocol version 2.02.
-# If we have our code not at 0x90000, we need to move it there now.
-# We also then need to move the params behind it (commandline)
-# Because we would overwrite the code on the current IP, we move
-# it in two steps, jumping high after the first one.
-	movw	%cs, %ax
-	cmpw	$SETUPSEG, %ax
-	je	end_move_self
-
-	cli					# make sure we really have
-						# interrupts disabled !
-						# because after this the stack
-						# should not be used
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	movw	%ss, %dx
-	cmpw	%ax, %dx
-	jb	move_self_1
-
-	addw	$INITSEG, %dx
-	subw	%ax, %dx			# this will go into %ss after
-						# the move
-move_self_1:
-	movw	%ax, %ds
-	movw	$INITSEG, %ax			# real INITSEG
-	movw	%ax, %es
-	movw	%cs:setup_move_size, %cx
-	std					# we have to move up, so we use
-						# direction down because the
-						# areas may overlap
-	movw	%cx, %di
-	decw	%di
-	movw	%di, %si
-	subw	$move_self_here+0x200, %cx
-	rep
-	movsb
-	ljmp	$SETUPSEG, $move_self_here
-
-move_self_here:
-	movw	$move_self_here+0x200, %cx
-	rep
-	movsb
-	movw	$SETUPSEG, %ax
-	movw	%ax, %ds
-	movw	%dx, %ss
-end_move_self:					# now we are at the right place
-
-#
-# Enable A20.  This is at the very best an annoying procedure.
-# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
-# AMD Elan bug fix by Robert Schwebel.
-#
-
-#if defined(CONFIG_X86_ELAN)
-	movb $0x02, %al			# alternate A20 gate
-	outb %al, $0x92			# this works on SC410/SC520
-a20_elan_wait:
-	call a20_test
-	jz a20_elan_wait
-	jmp a20_done
-#endif
-
-
-A20_TEST_LOOPS		=  32		# Iterations per wait
-A20_ENABLE_LOOPS	= 255		# Total loops to try		
-
-
-#ifndef CONFIG_X86_VOYAGER
-a20_try_loop:
-
-	# First, see if we are on a system with no A20 gate.
-a20_none:
-	call	a20_test
-	jnz	a20_done
-
-	# Next, try the BIOS (INT 0x15, AX=0x2401)
-a20_bios:
-	movw	$0x2401, %ax
-	pushfl					# Be paranoid about flags
-	int	$0x15
-	popfl
-
-	call	a20_test
-	jnz	a20_done
-
-	# Try enabling A20 through the keyboard controller
-#endif /* CONFIG_X86_VOYAGER */
-a20_kbc:
-	call	empty_8042
-
-#ifndef CONFIG_X86_VOYAGER
-	call	a20_test			# Just in case the BIOS worked
-	jnz	a20_done			# but had a delayed reaction.
-#endif
-
-	movb	$0xD1, %al			# command write
-	outb	%al, $0x64
-	call	empty_8042
-
-	movb	$0xDF, %al			# A20 on
-	outb	%al, $0x60
-	call	empty_8042
-
-#ifndef CONFIG_X86_VOYAGER
-	# Wait until a20 really *is* enabled; it can take a fair amount of
-	# time on certain systems; Toshiba Tecras are known to have this
-	# problem.
-a20_kbc_wait:
-	xorw	%cx, %cx
-a20_kbc_wait_loop:
-	call	a20_test
-	jnz	a20_done
-	loop	a20_kbc_wait_loop
-
-	# Final attempt: use "configuration port A"
-a20_fast:
-	inb	$0x92, %al			# Configuration Port A
-	orb	$0x02, %al			# "fast A20" version
-	andb	$0xFE, %al			# don't accidentally reset
-	outb	%al, $0x92
-
-	# Wait for configuration port A to take effect
-a20_fast_wait:
-	xorw	%cx, %cx
-a20_fast_wait_loop:
-	call	a20_test
-	jnz	a20_done
-	loop	a20_fast_wait_loop
-
-	# A20 is still not responding.  Try frobbing it again.
-	# 
-	decb	(a20_tries)
-	jnz	a20_try_loop
-	
-	movw	$a20_err_msg, %si
-	call	prtstr
-
-a20_die:
-	hlt
-	jmp	a20_die
-
-a20_tries:
-	.byte	A20_ENABLE_LOOPS
-
-a20_err_msg:
-	.ascii	"linux: fatal error: A20 gate not responding!"
-	.byte	13, 10, 0
-
-	# If we get here, all is good
-a20_done:
-
-#endif /* CONFIG_X86_VOYAGER */
-# set up gdt and idt and 32bit start address
-	lidt	idt_48				# load idt with 0,0
-	xorl	%eax, %eax			# Compute gdt_base
-	movw	%ds, %ax			# (Convert %ds:gdt to a linear ptr)
-	shll	$4, %eax
-	addl	%eax, code32
-	addl	$gdt, %eax
-	movl	%eax, (gdt_48+2)
-	lgdt	gdt_48				# load gdt with whatever is
-						# appropriate
-
-# make sure any possible coprocessor is properly reset..
-	xorw	%ax, %ax
-	outb	%al, $0xf0
-	call	delay
-
-	outb	%al, $0xf1
-	call	delay
-
-# well, that went ok, I hope. Now we mask all interrupts - the rest
-# is done in init_IRQ().
-	movb	$0xFF, %al			# mask all interrupts for now
-	outb	%al, $0xA1
-	call	delay
-	
-	movb	$0xFB, %al			# mask all irq's but irq2 which
-	outb	%al, $0x21			# is cascaded
-
-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-# need no steenking BIOS anyway (except for the initial loading :-).
-# The BIOS-routine wants lots of unnecessary data, and it's less
-# "interesting" anyway. This is how REAL programmers do it.
-#
-# Well, now's the time to actually move into protected mode. To make
-# things as simple as possible, we do no register set-up or anything,
-# we let the gnu-compiled 32-bit programs do that. We just jump to
-# absolute address 0x1000 (or the loader supplied one),
-# in 32-bit protected mode.
-#
-# Note that the short jump isn't strictly needed, although there are
-# reasons why it might be a good idea. It won't hurt in any case.
-	movw	$1, %ax				# protected mode (PE) bit
-	lmsw	%ax				# This is it!
-	jmp	flush_instr
-
-flush_instr:
-	xorw	%bx, %bx			# Flag to indicate a boot
-	xorl	%esi, %esi			# Pointer to real-mode code
-	movw	%cs, %si
-	subw	$DELTA_INITSEG, %si
-	shll	$4, %esi			# Convert to 32-bit pointer
-
-# jump to startup_32 in arch/i386/boot/compressed/head.S
-#	
-# NOTE: For high loaded big kernels we need a
-#	jmpi    0x100000,__BOOT_CS
-#
-#	but we yet haven't reloaded the CS register, so the default size 
-#	of the target offset still is 16 bit.
-#	However, using an operand prefix (0x66), the CPU will properly
-#	take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
-#	Manual, Mixing 16-bit and 32-bit code, page 16-6)
-
-	.byte 0x66, 0xea			# prefix + jmpi-opcode
-code32:	.long	startup_32			# will be set to %cs+startup_32
-	.word	__BOOT_CS
-.code32
-startup_32:
-	movl $(__BOOT_DS), %eax
-	movl %eax, %ds
-	movl %eax, %es
-	movl %eax, %fs
-	movl %eax, %gs
-	movl %eax, %ss
-
-	xorl %eax, %eax
-1:	incl %eax				# check that A20 really IS enabled
-	movl %eax, 0x00000000			# loop forever if it isn't
-	cmpl %eax, 0x00100000
-	je 1b
-
-	# Jump to the 32bit entry point
-	jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi)
-.code16
-
-# Here's a bunch of information about your current kernel..
-kernel_version:	.ascii	UTS_RELEASE
-		.ascii	" ("
-		.ascii	LINUX_COMPILE_BY
-		.ascii	"@"
-		.ascii	LINUX_COMPILE_HOST
-		.ascii	") "
-		.ascii	UTS_VERSION
-		.byte	0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
-	cli					# no interrupts allowed !
-	movb	$0x80, %al			# disable NMI for bootup
-						# sequence
-	outb	%al, $0x70
-	lret
-
-
-#ifndef CONFIG_X86_VOYAGER
-# This routine tests whether or not A20 is enabled.  If so, it
-# exits with zf = 0.
-#
-# The memory address used, 0x200, is the int $0x80 vector, which
-# should be safe.
-
-A20_TEST_ADDR = 4*0x80
-
-a20_test:
-	pushw	%cx
-	pushw	%ax
-	xorw	%cx, %cx
-	movw	%cx, %fs			# Low memory
-	decw	%cx
-	movw	%cx, %gs			# High memory area
-	movw	$A20_TEST_LOOPS, %cx
-	movw	%fs:(A20_TEST_ADDR), %ax
-	pushw	%ax
-a20_test_wait:
-	incw	%ax
-	movw	%ax, %fs:(A20_TEST_ADDR)
-	call	delay				# Serialize and make delay constant
-	cmpw	%gs:(A20_TEST_ADDR+0x10), %ax
-	loope	a20_test_wait
-
-	popw	%fs:(A20_TEST_ADDR)
-	popw	%ax
-	popw	%cx
-	ret	
-
-#endif /* CONFIG_X86_VOYAGER */
-
-# This routine checks that the keyboard command queue is empty
-# (after emptying the output buffers)
-#
-# Some machines have delusions that the keyboard buffer is always full
-# with no keyboard attached...
-#
-# If there is no keyboard controller, we will usually get 0xff
-# to all the reads.  With each IO taking a microsecond and
-# a timeout of 100,000 iterations, this can take about half a
-# second ("delay" == outb to port 0x80). That should be ok,
-# and should also be plenty of time for a real keyboard controller
-# to empty.
-#
-
-empty_8042:
-	pushl	%ecx
-	movl	$100000, %ecx
-
-empty_8042_loop:
-	decl	%ecx
-	jz	empty_8042_end_loop
-
-	call	delay
-
-	inb	$0x64, %al			# 8042 status port
-	testb	$1, %al				# output buffer?
-	jz	no_output
-
-	call	delay
-	inb	$0x60, %al			# read it
-	jmp	empty_8042_loop
-
-no_output:
-	testb	$2, %al				# is input buffer full?
-	jnz	empty_8042_loop			# yes - loop
-empty_8042_end_loop:
-	popl	%ecx
-	ret
-
-# Read the cmos clock. Return the seconds in al
-gettime:
-	pushw	%cx
-	movb	$0x02, %ah
-	int	$0x1a
-	movb	%dh, %al			# %dh contains the seconds
-	andb	$0x0f, %al
-	movb	%dh, %ah
-	movb	$0x04, %cl
-	shrb	%cl, %ah
-	aad
-	popw	%cx
-	ret
-
-# Delay is needed after doing I/O
-delay:
-	outb	%al,$0x80
-	ret
-
-# Descriptor tables
-#
-# NOTE: The intel manual says gdt should be sixteen bytes aligned for
-# efficiency reasons.  However, there are machines which are known not
-# to boot with misaligned GDTs, so alter this at your peril!  If you alter
-# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
-# empty GDT entries (one for NULL and one reserved).
-#
-# NOTE:	On some CPUs, the GDT must be 8 byte aligned.  This is
-# true for the Voyager Quad CPU card which will not boot without
-# This directive.  16 byte aligment is recommended by intel.
-#
-	.align 16
-gdt:
-	.fill GDT_ENTRY_BOOT_CS,8,0
-
-	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
-	.word	0				# base address = 0
-	.word	0x9A00				# code read/exec
-	.word	0x00CF				# granularity = 4096, 386
-						#  (+5th nibble of limit)
-
-	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
-	.word	0				# base address = 0
-	.word	0x9200				# data read/write
-	.word	0x00CF				# granularity = 4096, 386
-						#  (+5th nibble of limit)
-gdt_end:
-	.align	4
-	
-	.word	0				# alignment byte
-idt_48:
-	.word	0				# idt limit = 0
-	.word	0, 0				# idt base = 0L
-
-	.word	0				# alignment byte
-gdt_48:
-	.word	gdt_end - gdt - 1		# gdt limit
-	.word	0, 0				# gdt base (filled in later)
-
-# Include video setup & detection code
-
-#include "video.S"
-
-# Setup signature -- must be last
-setup_sig1:	.word	SIG1
-setup_sig2:	.word	SIG2
-
-# After this point, there is some free space which is used by the video mode
-# handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/arch/i386/boot/setup.ld b/arch/i386/boot/setup.ld
new file mode 100644
index 0000000..df9234b
--- /dev/null
+++ b/arch/i386/boot/setup.ld
@@ -0,0 +1,54 @@
+/*
+ * setup.ld
+ *
+ * Linker script for the i386 setup code
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+	. = 0;
+	.bstext		: { *(.bstext) }
+	.bsdata		: { *(.bsdata) }
+
+	. = 497;
+	.header		: { *(.header) }
+	.inittext	: { *(.inittext) }
+	.initdata	: { *(.initdata) }
+	.text		: { *(.text*) }
+
+	. = ALIGN(16);
+	.rodata		: { *(.rodata*) }
+
+	.videocards	: {
+		video_cards = .;
+		*(.videocards)
+		video_cards_end = .;
+	}
+
+	. = ALIGN(16);
+	.data		: { *(.data*) }
+
+	.signature	: {
+		setup_sig = .;
+		LONG(0x5a5aaa55)
+	}
+
+
+	. = ALIGN(16);
+	.bss		:
+	{
+		__bss_start = .;
+		*(.bss)
+		__bss_end = .;
+	}
+	. = ALIGN(16);
+	_end = .;
+
+	/DISCARD/ : { *(.note*) }
+
+	. = ASSERT(_end <= 0x8000, "Setup too big!");
+	. = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!");
+}
diff --git a/arch/i386/boot/string.c b/arch/i386/boot/string.c
new file mode 100644
index 0000000..481a220
--- /dev/null
+++ b/arch/i386/boot/string.c
@@ -0,0 +1,52 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/string.c
+ *
+ * Very basic string functions
+ */
+
+#include "boot.h"
+
+int strcmp(const char *str1, const char *str2)
+{
+	const unsigned char *s1 = (const unsigned char *)str1;
+	const unsigned char *s2 = (const unsigned char *)str2;
+	int delta = 0;
+
+	while (*s1 || *s2) {
+		delta = *s2 - *s1;
+		if (delta)
+			return delta;
+		s1++;
+		s2++;
+	}
+	return 0;
+}
+
+size_t strnlen(const char *s, size_t maxlen)
+{
+	const char *es = s;
+	while (*es && maxlen) {
+		es++;
+		maxlen--;
+	}
+
+	return (es - s);
+}
+
+unsigned int atou(const char *s)
+{
+	unsigned int i = 0;
+	while (isdigit(*s))
+		i = i * 10 + (*s++ - '0');
+	return i;
+}
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
index 0579841..886f47d8 100644
--- a/arch/i386/boot/tools/build.c
+++ b/arch/i386/boot/tools/build.c
@@ -1,13 +1,12 @@
 /*
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 1997 Martin Mares
+ *  Copyright (C) 2007 H. Peter Anvin
  */
 
 /*
  * This file builds a disk-image from three different files:
  *
- * - bootsect: compatibility mbr which prints an error message if
- *             someone tries to boot the kernel directly.
  * - setup: 8086 machine code, sets up system parm
  * - system: 80386 code for actual system
  *
@@ -21,6 +20,7 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  * Cross compiling fixes by Gertjan van Wingerde, July 1996
  * Rewritten by Martin Mares, April 1997
+ * Substantially overhauled by H. Peter Anvin, April 2007
  */
 
 #include <stdio.h>
@@ -32,23 +32,25 @@
 #include <sys/sysmacros.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/mman.h>
 #include <asm/boot.h>
 
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long u32;
+typedef unsigned char  u8;
+typedef unsigned short u16;
+typedef unsigned long  u32;
 
 #define DEFAULT_MAJOR_ROOT 0
 #define DEFAULT_MINOR_ROOT 0
 
-/* Minimal number of setup sectors (see also bootsect.S) */
-#define SETUP_SECTS 4
+/* Minimal number of setup sectors */
+#define SETUP_SECT_MIN 5
+#define SETUP_SECT_MAX 64
 
-byte buf[1024];
-int fd;
+/* This must be large enough to hold the entire setup */
+u8 buf[SETUP_SECT_MAX*512];
 int is_big_kernel;
 
-void die(const char * str, ...)
+static void die(const char * str, ...)
 {
 	va_list args;
 	va_start(args, str);
@@ -57,15 +59,9 @@
 	exit(1);
 }
 
-void file_open(const char *name)
+static void usage(void)
 {
-	if ((fd = open(name, O_RDONLY, 0)) < 0)
-		die("Unable to open `%s': %m", name);
-}
-
-void usage(void)
-{
-	die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
+	die("Usage: build [-b] setup system [rootdev] [> image]");
 }
 
 int main(int argc, char ** argv)
@@ -73,27 +69,30 @@
 	unsigned int i, sz, setup_sectors;
 	int c;
 	u32 sys_size;
-	byte major_root, minor_root;
+	u8 major_root, minor_root;
 	struct stat sb;
+	FILE *file;
+	int fd;
+	void *kernel;
 
 	if (argc > 2 && !strcmp(argv[1], "-b"))
 	  {
 	    is_big_kernel = 1;
 	    argc--, argv++;
 	  }
-	if ((argc < 4) || (argc > 5))
+	if ((argc < 3) || (argc > 4))
 		usage();
-	if (argc > 4) {
-		if (!strcmp(argv[4], "CURRENT")) {
+	if (argc > 3) {
+		if (!strcmp(argv[3], "CURRENT")) {
 			if (stat("/", &sb)) {
 				perror("/");
 				die("Couldn't stat /");
 			}
 			major_root = major(sb.st_dev);
 			minor_root = minor(sb.st_dev);
-		} else if (strcmp(argv[4], "FLOPPY")) {
-			if (stat(argv[4], &sb)) {
-				perror(argv[4]);
+		} else if (strcmp(argv[3], "FLOPPY")) {
+			if (stat(argv[3], &sb)) {
+				perror(argv[3]);
 				die("Couldn't stat root device.");
 			}
 			major_root = major(sb.st_rdev);
@@ -108,79 +107,62 @@
 	}
 	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
 
-	file_open(argv[1]);
-	i = read(fd, buf, sizeof(buf));
-	fprintf(stderr,"Boot sector %d bytes.\n",i);
-	if (i != 512)
-		die("Boot block must be exactly 512 bytes");
+	/* Copy the setup code */
+	file = fopen(argv[1], "r");
+	if (!file)
+		die("Unable to open `%s': %m", argv[1]);
+	c = fread(buf, 1, sizeof(buf), file);
+	if (ferror(file))
+		die("read-error on `setup'");
+	if (c < 1024)
+		die("The setup must be at least 1024 bytes");
 	if (buf[510] != 0x55 || buf[511] != 0xaa)
 		die("Boot block hasn't got boot flag (0xAA55)");
+	fclose(file);
+
+	/* Pad unused space with zeros */
+	setup_sectors = (c + 511) / 512;
+	if (setup_sectors < SETUP_SECT_MIN)
+		setup_sectors = SETUP_SECT_MIN;
+	i = setup_sectors*512;
+	memset(buf+c, 0, i-c);
+
+	/* Set the default root device */
 	buf[508] = minor_root;
 	buf[509] = major_root;
-	if (write(1, buf, 512) != 512)
-		die("Write call failed");
-	close (fd);
 
-	file_open(argv[2]);				    /* Copy the setup code */
-	for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
-		if (write(1, buf, c) != c)
-			die("Write call failed");
-	if (c != 0)
-		die("read-error on `setup'");
-	close (fd);
+	fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
 
-	setup_sectors = (i + 511) / 512;	/* Pad unused space with zeros */
-	/* for compatibility with ancient versions of LILO. */
-	if (setup_sectors < SETUP_SECTS)
-		setup_sectors = SETUP_SECTS;
-	fprintf(stderr, "Setup is %d bytes.\n", i);
-	memset(buf, 0, sizeof(buf));
-	while (i < setup_sectors * 512) {
-		c = setup_sectors * 512 - i;
-		if (c > sizeof(buf))
-			c = sizeof(buf);
-		if (write(1, buf, c) != c)
-			die("Write call failed");
-		i += c;
-	}
-
-	file_open(argv[3]);
-	if (fstat (fd, &sb))
-		die("Unable to stat `%s': %m", argv[3]);
+	/* Open and stat the kernel file */
+	fd = open(argv[2], O_RDONLY);
+	if (fd < 0)
+		die("Unable to open `%s': %m", argv[2]);
+	if (fstat(fd, &sb))
+		die("Unable to stat `%s': %m", argv[2]);
 	sz = sb.st_size;
-	fprintf (stderr, "System is %d kB\n", sz/1024);
+	fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
+	kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
+	if (kernel == MAP_FAILED)
+		die("Unable to mmap '%s': %m", argv[2]);
 	sys_size = (sz + 15) / 16;
 	if (!is_big_kernel && sys_size > DEF_SYSSIZE)
 		die("System is too big. Try using bzImage or modules.");
-	while (sz > 0) {
-		int l, n;
 
-		l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
-		if ((n=read(fd, buf, l)) != l) {
-			if (n < 0)
-				die("Error reading %s: %m", argv[3]);
-			else
-				die("%s: Unexpected EOF", argv[3]);
-		}
-		if (write(1, buf, l) != l)
-			die("Write failed");
-		sz -= l;
-	}
+	/* Patch the setup code with the appropriate size parameters */
+	buf[0x1f1] = setup_sectors-1;
+	buf[0x1f4] = sys_size;
+	buf[0x1f5] = sys_size >> 8;
+	buf[0x1f6] = sys_size >> 16;
+	buf[0x1f7] = sys_size >> 24;
+
+	if (fwrite(buf, 1, i, stdout) != i)
+		die("Writing setup failed");
+
+	/* Copy the kernel code */
+	if (fwrite(kernel, 1, sz, stdout) != sz)
+		die("Writing kernel failed");
 	close(fd);
 
-	if (lseek(1, 497, SEEK_SET) != 497)		    /* Write sizes to the bootsector */
-		die("Output: seek failed");
-	buf[0] = setup_sectors;
-	if (write(1, buf, 1) != 1)
-		die("Write of setup sector count failed");
-	if (lseek(1, 500, SEEK_SET) != 500)
-		die("Output: seek failed");
-	buf[0] = (sys_size & 0xff);
-	buf[1] = ((sys_size >> 8) & 0xff);
-	buf[2] = ((sys_size >> 16) & 0xff);
-	buf[3] = ((sys_size >> 24) & 0xff);
-	if (write(1, buf, 4) != 4)
-		die("Write of image length failed");
-
-	return 0;					    /* Everything is OK */
+	/* Everything is OK */
+	return 0;
 }
diff --git a/arch/i386/boot/tty.c b/arch/i386/boot/tty.c
new file mode 100644
index 0000000..a8db787
--- /dev/null
+++ b/arch/i386/boot/tty.c
@@ -0,0 +1,112 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/tty.c
+ *
+ * Very simple screen I/O
+ * XXX: Probably should add very simple serial I/O?
+ */
+
+#include "boot.h"
+
+/*
+ * These functions are in .inittext so they can be used to signal
+ * error during initialization.
+ */
+
+void __attribute__((section(".inittext"))) putchar(int ch)
+{
+	unsigned char c = ch;
+
+	if (c == '\n')
+		putchar('\r');	/* \n -> \r\n */
+
+	/* int $0x10 is known to have bugs involving touching registers
+	   it shouldn't.  Be extra conservative... */
+	asm volatile("pushal; int $0x10; popal"
+		     : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch));
+}
+
+void __attribute__((section(".inittext"))) puts(const char *str)
+{
+	int n = 0;
+	while (*str) {
+		putchar(*str++);
+		n++;
+	}
+}
+
+/*
+ * Read the CMOS clock through the BIOS, and return the
+ * seconds in BCD.
+ */
+
+static u8 gettime(void)
+{
+	u16 ax = 0x0200;
+	u16 cx, dx;
+
+	asm("int $0x1a"
+	    : "+a" (ax), "=c" (cx), "=d" (dx)
+	    : : "ebx", "esi", "edi");
+
+	return dx >> 8;
+}
+
+/*
+ * Read from the keyboard
+ */
+int getchar(void)
+{
+	u16 ax = 0;
+	asm("int $0x16" : "+a" (ax));
+
+	return ax & 0xff;
+}
+
+static int kbd_pending(void)
+{
+	u8 pending;
+	asm("int $0x16; setnz %0"
+	    : "=rm" (pending)
+	    : "a" (0x0100));
+	return pending;
+}
+
+void kbd_flush(void)
+{
+	for (;;) {
+		if (!kbd_pending())
+			break;
+		getchar();
+	}
+}
+
+int getchar_timeout(void)
+{
+	int cnt = 30;
+	int t0, t1;
+
+	t0 = gettime();
+
+	while (cnt) {
+		if (kbd_pending())
+			return getchar();
+
+		t1 = gettime();
+		if (t0 != t1) {
+			cnt--;
+			t0 = t1;
+		}
+	}
+
+	return 0;		/* Timeout! */
+}
diff --git a/arch/i386/boot/version.c b/arch/i386/boot/version.c
new file mode 100644
index 0000000..c61462f
--- /dev/null
+++ b/arch/i386/boot/version.c
@@ -0,0 +1,23 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/version.c
+ *
+ * Kernel version string
+ */
+
+#include "boot.h"
+#include <linux/utsrelease.h>
+#include <linux/compile.h>
+
+const char kernel_version[] =
+	UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") "
+	UTS_VERSION;
diff --git a/arch/i386/boot/vesa.h b/arch/i386/boot/vesa.h
new file mode 100644
index 0000000..ff5b73c
--- /dev/null
+++ b/arch/i386/boot/vesa.h
@@ -0,0 +1,79 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 1999-2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef BOOT_VESA_H
+#define BOOT_VESA_H
+
+typedef struct {
+	u16 off, seg;
+} far_ptr;
+
+/* VESA General Information table */
+struct vesa_general_info {
+	u32 signature;		/* 0 Magic number = "VESA" */
+	u16 version;		/* 4 */
+	far_ptr vendor_string;	/* 6 */
+	u32 capabilities;	/* 10 */
+	far_ptr video_mode_ptr;	/* 14 */
+	u16 total_memory;	/* 18 */
+
+	u16 oem_software_rev;	/* 20 */
+	far_ptr oem_vendor_name_ptr;	/* 22 */
+	far_ptr oem_product_name_ptr;	/* 26 */
+	far_ptr oem_product_rev_ptr;	/* 30 */
+
+	u8 reserved[222];	/* 34 */
+	u8 oem_data[256];	/* 256 */
+} __attribute__ ((packed));
+
+#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24))
+#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24))
+
+struct vesa_mode_info {
+	u16 mode_attr;		/* 0 */
+	u8 win_attr[2];		/* 2 */
+	u16 win_grain;		/* 4 */
+	u16 win_size;		/* 6 */
+	u16 win_seg[2];		/* 8 */
+	far_ptr win_scheme;	/* 12 */
+	u16 logical_scan;	/* 16 */
+
+	u16 h_res;		/* 18 */
+	u16 v_res;		/* 20 */
+	u8 char_width;		/* 22 */
+	u8 char_height;		/* 23 */
+	u8 memory_planes;	/* 24 */
+	u8 bpp;			/* 25 */
+	u8 banks;		/* 26 */
+	u8 memory_layout;	/* 27 */
+	u8 bank_size;		/* 28 */
+	u8 image_planes;	/* 29 */
+	u8 page_function;	/* 30 */
+
+	u8 rmask;		/* 31 */
+	u8 rpos;		/* 32 */
+	u8 gmask;		/* 33 */
+	u8 gpos;		/* 34 */
+	u8 bmask;		/* 35 */
+	u8 bpos;		/* 36 */
+	u8 resv_mask;		/* 37 */
+	u8 resv_pos;		/* 38 */
+	u8 dcm_info;		/* 39 */
+
+	u32 lfb_ptr;		/* 40 Linear frame buffer address */
+	u32 offscreen_ptr;	/* 44 Offscreen memory address */
+	u16 offscreen_size;	/* 48 */
+
+	u8 reserved[206];	/* 50 */
+} __attribute__ ((packed));
+
+#endif				/* LIB_SYS_VESA_H */
diff --git a/arch/i386/boot/video-bios.c b/arch/i386/boot/video-bios.c
new file mode 100644
index 0000000..afea46c
--- /dev/null
+++ b/arch/i386/boot/video-bios.c
@@ -0,0 +1,125 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-bios.c
+ *
+ * Standard video BIOS modes
+ *
+ * We have two options for this; silent and scanned.
+ */
+
+#include "boot.h"
+#include "video.h"
+
+__videocard video_bios;
+
+/* Set a conventional BIOS mode */
+static int set_bios_mode(u8 mode);
+
+static int bios_set_mode(struct mode_info *mi)
+{
+	return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS);
+}
+
+static int set_bios_mode(u8 mode)
+{
+	u16 ax;
+	u8 new_mode;
+
+	ax = mode;		/* AH=0x00 Set Video Mode */
+	asm volatile(INT10
+		     : "+a" (ax)
+		     : : "ebx", "ecx", "edx", "esi", "edi");
+
+	ax = 0x0f00;		/* Get Current Video Mode */
+	asm volatile(INT10
+		     : "+a" (ax)
+		     : : "ebx", "ecx", "edx", "esi", "edi");
+
+	do_restore = 1;		/* Assume video contents was lost */
+	new_mode = ax & 0x7f;	/* Not all BIOSes are clean with the top bit */
+
+	if (new_mode == mode)
+		return 0;	/* Mode change OK */
+
+	if (new_mode != boot_params.screen_info.orig_video_mode) {
+		/* Mode setting failed, but we didn't end up where we
+		   started.  That's bad.  Try to revert to the original
+		   video mode. */
+		ax = boot_params.screen_info.orig_video_mode;
+		asm volatile(INT10
+			     : "+a" (ax)
+			     : : "ebx", "ecx", "edx", "esi", "edi");
+	}
+	return -1;
+}
+
+static int bios_probe(void)
+{
+	u8 mode;
+	u8 saved_mode = boot_params.screen_info.orig_video_mode;
+	u16 crtc;
+	struct mode_info *mi;
+	int nmodes = 0;
+
+	if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
+		return 0;
+
+	set_fs(0);
+	crtc = vga_crtc();
+
+	video_bios.modes = GET_HEAP(struct mode_info, 0);
+
+	for (mode = 0x14; mode <= 0x7f; mode++) {
+		if (heap_free() < sizeof(struct mode_info))
+			break;
+
+		if (mode_defined(VIDEO_FIRST_BIOS+mode))
+			continue;
+
+		if (set_bios_mode(mode))
+			continue;
+
+		/* Try to verify that it's a text mode. */
+
+		/* Attribute Controller: make graphics controller disabled */
+		if (in_idx(0x3c0, 0x10) & 0x01)
+			continue;
+
+		/* Graphics Controller: verify Alpha addressing enabled */
+		if (in_idx(0x3ce, 0x06) & 0x01)
+			continue;
+
+		/* CRTC cursor location low should be zero(?) */
+		if (in_idx(crtc, 0x0f))
+			continue;
+
+		mi = GET_HEAP(struct mode_info, 1);
+		mi->mode = VIDEO_FIRST_BIOS+mode;
+		mi->x = rdfs16(0x44a);
+		mi->y = rdfs8(0x484)+1;
+		nmodes++;
+	}
+
+	set_bios_mode(saved_mode);
+
+	return nmodes;
+}
+
+__videocard video_bios =
+{
+	.card_name	= "BIOS (scanned)",
+	.probe		= bios_probe,
+	.set_mode	= bios_set_mode,
+	.unsafe		= 1,
+	.xmode_first	= VIDEO_FIRST_BIOS,
+	.xmode_n	= 0x80,
+};
diff --git a/arch/i386/boot/video-vesa.c b/arch/i386/boot/video-vesa.c
new file mode 100644
index 0000000..e6aa9eb
--- /dev/null
+++ b/arch/i386/boot/video-vesa.c
@@ -0,0 +1,284 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-vesa.c
+ *
+ * VESA text modes
+ */
+
+#include "boot.h"
+#include "video.h"
+#include "vesa.h"
+
+/* VESA information */
+static struct vesa_general_info vginfo;
+static struct vesa_mode_info vminfo;
+
+__videocard video_vesa;
+
+static void vesa_store_mode_params_graphics(void);
+
+static int vesa_probe(void)
+{
+#if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID)
+	u16 ax;
+	u16 mode;
+	addr_t mode_ptr;
+	struct mode_info *mi;
+	int nmodes = 0;
+
+	video_vesa.modes = GET_HEAP(struct mode_info, 0);
+
+	vginfo.signature = VBE2_MAGIC;
+
+	/* Optimistically assume a VESA BIOS is register-clean... */
+	ax = 0x4f00;
+	asm("int $0x10" : "+a" (ax), "=m" (vginfo) : "D" (&vginfo));
+
+	if (ax != 0x004f ||
+	    vginfo.signature != VESA_MAGIC ||
+	    vginfo.version < 0x0102)
+		return 0;	/* Not present */
+#endif /* CONFIG_VIDEO_VESA || CONFIG_FIRMWARE_EDID */
+#ifdef CONFIG_VIDEO_VESA
+	set_fs(vginfo.video_mode_ptr.seg);
+	mode_ptr = vginfo.video_mode_ptr.off;
+
+	while ((mode = rdfs16(mode_ptr)) != 0xffff) {
+		mode_ptr += 2;
+
+		if (heap_free() < sizeof(struct mode_info))
+			break;	/* Heap full, can't save mode info */
+
+		if (mode & ~0x1ff)
+			continue;
+
+		memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
+
+		ax = 0x4f01;
+		asm("int $0x10"
+		    : "+a" (ax), "=m" (vminfo)
+		    : "c" (mode), "D" (&vminfo));
+
+		if (ax != 0x004f)
+			continue;
+
+		if ((vminfo.mode_attr & 0x15) == 0x05) {
+			/* Text Mode, TTY BIOS supported,
+			   supported by hardware */
+			mi = GET_HEAP(struct mode_info, 1);
+			mi->mode = mode + VIDEO_FIRST_VESA;
+			mi->x    = vminfo.h_res;
+			mi->y    = vminfo.v_res;
+			nmodes++;
+		} else if ((vminfo.mode_attr & 0x99) == 0x99) {
+#ifdef CONFIG_FB
+			/* Graphics mode, color, linear frame buffer
+			   supported -- register the mode but hide from
+			   the menu.  Only do this if framebuffer is
+			   configured, however, otherwise the user will
+			   be left without a screen. */
+			mi = GET_HEAP(struct mode_info, 1);
+			mi->mode = mode + VIDEO_FIRST_VESA;
+			mi->x = mi->y = 0;
+			nmodes++;
+#endif
+		}
+	}
+
+	return nmodes;
+#else
+	return 0;
+#endif /* CONFIG_VIDEO_VESA */
+}
+
+static int vesa_set_mode(struct mode_info *mode)
+{
+	u16 ax;
+	int is_graphic;
+	u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA;
+
+	memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
+
+	ax = 0x4f01;
+	asm("int $0x10"
+	    : "+a" (ax), "=m" (vminfo)
+	    : "c" (vesa_mode), "D" (&vminfo));
+
+	if (ax != 0x004f)
+		return -1;
+
+	if ((vminfo.mode_attr & 0x15) == 0x05) {
+		/* It's a supported text mode */
+		is_graphic = 0;
+	} else if ((vminfo.mode_attr & 0x99) == 0x99) {
+		/* It's a graphics mode with linear frame buffer */
+		is_graphic = 1;
+		vesa_mode |= 0x4000; /* Request linear frame buffer */
+	} else {
+		return -1;	/* Invalid mode */
+	}
+
+
+	ax = 0x4f02;
+	asm volatile("int $0x10"
+		     : "+a" (ax)
+		     : "b" (vesa_mode), "D" (0));
+
+	if (ax != 0x004f)
+		return -1;
+
+	graphic_mode = is_graphic;
+	if (!is_graphic) {
+		/* Text mode */
+		force_x = mode->x;
+		force_y = mode->y;
+		do_restore = 1;
+	} else {
+		/* Graphics mode */
+		vesa_store_mode_params_graphics();
+	}
+
+	return 0;
+}
+
+
+/* Switch DAC to 8-bit mode */
+static void vesa_dac_set_8bits(void)
+{
+	u8 dac_size = 6;
+
+	/* If possible, switch the DAC to 8-bit mode */
+	if (vginfo.capabilities & 1) {
+		u16 ax, bx;
+
+		ax = 0x4f08;
+		bx = 0x0800;
+		asm volatile(INT10
+			     : "+a" (ax), "+b" (bx)
+			     : : "ecx", "edx", "esi", "edi");
+
+		if (ax == 0x004f)
+			dac_size = bx >> 8;
+	}
+
+	/* Set the color sizes to the DAC size, and offsets to 0 */
+	boot_params.screen_info.red_size = dac_size;
+	boot_params.screen_info.green_size = dac_size;
+	boot_params.screen_info.blue_size = dac_size;
+	boot_params.screen_info.rsvd_size = dac_size;
+
+	boot_params.screen_info.red_pos = 0;
+	boot_params.screen_info.green_pos = 0;
+	boot_params.screen_info.blue_pos = 0;
+	boot_params.screen_info.rsvd_pos = 0;
+}
+
+/* Save the VESA protected mode info */
+static void vesa_store_pm_info(void)
+{
+	u16 ax, bx, di, es;
+
+	ax = 0x4f0a;
+	bx = di = 0;
+	asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es"
+	    : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di)
+	    : : "ecx", "esi");
+
+	if (ax != 0x004f)
+		return;
+
+	boot_params.screen_info.vesapm_seg = es;
+	boot_params.screen_info.vesapm_off = di;
+}
+
+/*
+ * Save video mode parameters for graphics mode
+ */
+static void vesa_store_mode_params_graphics(void)
+{
+	/* Tell the kernel we're in VESA graphics mode */
+	boot_params.screen_info.orig_video_isVGA = 0x23;
+
+	/* Mode parameters */
+	boot_params.screen_info.vesa_attributes = vminfo.mode_attr;
+	boot_params.screen_info.lfb_linelength = vminfo.logical_scan;
+	boot_params.screen_info.lfb_width = vminfo.h_res;
+	boot_params.screen_info.lfb_height = vminfo.v_res;
+	boot_params.screen_info.lfb_depth = vminfo.bpp;
+	boot_params.screen_info.pages = vminfo.image_planes;
+	boot_params.screen_info.lfb_base = vminfo.lfb_ptr;
+	memcpy(&boot_params.screen_info.red_size,
+	       &vminfo.rmask, 8);
+
+	/* General parameters */
+	boot_params.screen_info.lfb_size = vginfo.total_memory;
+
+	if (vminfo.bpp <= 8)
+		vesa_dac_set_8bits();
+
+	vesa_store_pm_info();
+}
+
+/*
+ * Save EDID information for the kernel; this is invoked, separately,
+ * after mode-setting.
+ */
+void vesa_store_edid(void)
+{
+#ifdef CONFIG_FIRMWARE_EDID
+	u16 ax, bx, cx, dx, di;
+
+	/* Apparently used as a nonsense token... */
+	memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info);
+
+	if (vginfo.version < 0x0200)
+		return;		/* EDID requires VBE 2.0+ */
+
+	ax = 0x4f15;		/* VBE DDC */
+	bx = 0x0000;		/* Report DDC capabilities */
+	cx = 0;			/* Controller 0 */
+	di = 0;			/* ES:DI must be 0 by spec */
+
+	/* Note: The VBE DDC spec is different from the main VESA spec;
+	   we genuinely have to assume all registers are destroyed here. */
+
+	asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es"
+	    : "+a" (ax), "+b" (bx)
+	    :  "c" (cx), "D" (di)
+	    : "esi");
+
+	if (ax != 0x004f)
+		return;		/* No EDID */
+
+	/* BH = time in seconds to transfer EDD information */
+	/* BL = DDC level supported */
+
+	ax = 0x4f15;		/* VBE DDC */
+	bx = 0x0001;		/* Read EDID */
+	cx = 0;			/* Controller 0 */
+	dx = 0;			/* EDID block number */
+	di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */
+	asm(INT10
+	    : "+a" (ax), "+b" (bx), "+d" (dx)
+	    : "c" (cx), "D" (di)
+	    : "esi");
+#endif /* CONFIG_FIRMWARE_EDID */
+}
+
+__videocard video_vesa =
+{
+	.card_name	= "VESA",
+	.probe		= vesa_probe,
+	.set_mode	= vesa_set_mode,
+	.xmode_first	= VIDEO_FIRST_VESA,
+	.xmode_n	= 0x200,
+};
diff --git a/arch/i386/boot/video-vga.c b/arch/i386/boot/video-vga.c
new file mode 100644
index 0000000..700d09a
--- /dev/null
+++ b/arch/i386/boot/video-vga.c
@@ -0,0 +1,260 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-vga.c
+ *
+ * Common all-VGA modes
+ */
+
+#include "boot.h"
+#include "video.h"
+
+static struct mode_info vga_modes[] = {
+	{ VIDEO_80x25,  80, 25 },
+	{ VIDEO_8POINT, 80, 50 },
+	{ VIDEO_80x43,  80, 43 },
+	{ VIDEO_80x28,  80, 28 },
+	{ VIDEO_80x30,  80, 30 },
+	{ VIDEO_80x34,  80, 34 },
+	{ VIDEO_80x60,  80, 60 },
+};
+
+static struct mode_info ega_modes[] = {
+	{ VIDEO_80x25,  80, 25 },
+	{ VIDEO_8POINT, 80, 43 },
+};
+
+static struct mode_info cga_modes[] = {
+	{ VIDEO_80x25,  80, 25 },
+};
+
+__videocard video_vga;
+
+/* Set basic 80x25 mode */
+static u8 vga_set_basic_mode(void)
+{
+	u16 ax;
+	u8 rows;
+	u8 mode;
+
+#ifdef CONFIG_VIDEO_400_HACK
+	if (adapter >= ADAPTER_VGA) {
+		asm(INT10
+		    : : "a" (0x1202), "b" (0x0030)
+		    : "ecx", "edx", "esi", "edi");
+	}
+#endif
+
+	ax = 0x0f00;
+	asm(INT10
+	    : "+a" (ax)
+	    : : "ebx", "ecx", "edx", "esi", "edi");
+
+	mode = (u8)ax;
+
+	set_fs(0);
+	rows = rdfs8(0x484);	/* rows minus one */
+
+#ifndef CONFIG_VIDEO_400_HACK
+	if ((ax == 0x5003 || ax == 0x5007) &&
+	    (rows == 0 || rows == 24))
+		return mode;
+#endif
+
+	if (mode != 3 && mode != 7)
+		mode = 3;
+
+	/* Set the mode */
+	asm volatile(INT10
+		     : : "a" (mode)
+		     : "ebx", "ecx", "edx", "esi", "edi");
+	do_restore = 1;
+	return mode;
+}
+
+static void vga_set_8font(void)
+{
+	/* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */
+
+	/* Set 8x8 font */
+	asm volatile(INT10 : : "a" (0x1112), "b" (0));
+
+	/* Use alternate print screen */
+	asm volatile(INT10 : : "a" (0x1200), "b" (0x20));
+
+	/* Turn off cursor emulation */
+	asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+
+	/* Cursor is scan lines 6-7 */
+	asm volatile(INT10 : : "a" (0x0100), "c" (0x0607));
+}
+
+static void vga_set_14font(void)
+{
+	/* Set 9x14 font - 80x28 on VGA */
+
+	/* Set 9x14 font */
+	asm volatile(INT10 : : "a" (0x1111), "b" (0));
+
+	/* Turn off cursor emulation */
+	asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+
+	/* Cursor is scan lines 11-12 */
+	asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c));
+}
+
+static void vga_set_80x43(void)
+{
+	/* Set 80x43 mode on VGA (not EGA) */
+
+	/* Set 350 scans */
+	asm volatile(INT10 : : "a" (0x1201), "b" (0x30));
+
+	/* Reset video mode */
+	asm volatile(INT10 : : "a" (0x0003));
+
+	vga_set_8font();
+}
+
+/* I/O address of the VGA CRTC */
+u16 vga_crtc(void)
+{
+	return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4;
+}
+
+static void vga_set_480_scanlines(int end)
+{
+	u16 crtc;
+	u8  csel;
+
+	crtc = vga_crtc();
+
+	out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */
+	out_idx(0x0b, crtc, 0x06); /* Vertical total */
+	out_idx(0x3e, crtc, 0x07); /* Vertical overflow */
+	out_idx(0xea, crtc, 0x10); /* Vertical sync start */
+	out_idx(end, crtc, 0x12); /* Vertical display end */
+	out_idx(0xe7, crtc, 0x15); /* Vertical blank start */
+	out_idx(0x04, crtc, 0x16); /* Vertical blank end */
+	csel = inb(0x3cc);
+	csel &= 0x0d;
+	csel |= 0xe2;
+	outb(csel, 0x3cc);
+}
+
+static void vga_set_80x30(void)
+{
+	vga_set_480_scanlines(0xdf);
+}
+
+static void vga_set_80x34(void)
+{
+	vga_set_14font();
+	vga_set_480_scanlines(0xdb);
+}
+
+static void vga_set_80x60(void)
+{
+	vga_set_8font();
+	vga_set_480_scanlines(0xdf);
+}
+
+static int vga_set_mode(struct mode_info *mode)
+{
+	/* Set the basic mode */
+	vga_set_basic_mode();
+
+	/* Override a possibly broken BIOS */
+	force_x = mode->x;
+	force_y = mode->y;
+
+	switch (mode->mode) {
+	case VIDEO_80x25:
+		break;
+	case VIDEO_8POINT:
+		vga_set_8font();
+		break;
+	case VIDEO_80x43:
+		vga_set_80x43();
+		break;
+	case VIDEO_80x28:
+		vga_set_14font();
+		break;
+	case VIDEO_80x30:
+		vga_set_80x30();
+		break;
+	case VIDEO_80x34:
+		vga_set_80x34();
+		break;
+	case VIDEO_80x60:
+		vga_set_80x60();
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * Note: this probe includes basic information required by all
+ * systems.  It should be executed first, by making sure
+ * video-vga.c is listed first in the Makefile.
+ */
+static int vga_probe(void)
+{
+	static const char *card_name[] = {
+		"CGA/MDA/HGC", "EGA", "VGA"
+	};
+	static struct mode_info *mode_lists[] = {
+		cga_modes,
+		ega_modes,
+		vga_modes,
+	};
+	static int mode_count[] = {
+		sizeof(cga_modes)/sizeof(struct mode_info),
+		sizeof(ega_modes)/sizeof(struct mode_info),
+		sizeof(vga_modes)/sizeof(struct mode_info),
+	};
+	u8 vga_flag;
+
+	asm(INT10
+	    : "=b" (boot_params.screen_info.orig_video_ega_bx)
+	    : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
+	    : "ecx", "edx", "esi", "edi");
+
+	/* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
+	if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) {
+		/* EGA/VGA */
+		asm(INT10
+		    : "=a" (vga_flag)
+		    : "a" (0x1a00)
+		    : "ebx", "ecx", "edx", "esi", "edi");
+
+		if (vga_flag == 0x1a) {
+			adapter = ADAPTER_VGA;
+			boot_params.screen_info.orig_video_isVGA = 1;
+		} else {
+			adapter = ADAPTER_EGA;
+		}
+	} else {
+		adapter = ADAPTER_CGA;
+	}
+
+	video_vga.modes = mode_lists[adapter];
+	video_vga.card_name = card_name[adapter];
+	return mode_count[adapter];
+}
+
+__videocard video_vga =
+{
+	.card_name	= "VGA",
+	.probe		= vga_probe,
+	.set_mode	= vga_set_mode,
+};
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
deleted file mode 100644
index 8143c95..0000000
--- a/arch/i386/boot/video.S
+++ /dev/null
@@ -1,2043 +0,0 @@
-/*	video.S
- *
- *	Display adapter & video mode setup, version 2.13 (14-May-99)
- *
- *	Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz>
- *	Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
- *
- *	Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999
- *
- *	For further information, look at Documentation/svga.txt.
- *
- */
-
-/* Enable autodetection of SVGA adapters and modes. */
-#undef CONFIG_VIDEO_SVGA
-
-/* Enable autodetection of VESA modes */
-#define CONFIG_VIDEO_VESA
-
-/* Enable compacting of mode table */
-#define CONFIG_VIDEO_COMPACT
-
-/* Retain screen contents when switching modes */
-#define CONFIG_VIDEO_RETAIN
-
-/* Enable local mode list */
-#undef CONFIG_VIDEO_LOCAL
-
-/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
-#undef CONFIG_VIDEO_400_HACK
-
-/* Hack that lets you force specific BIOS mode ID and specific dimensions */
-#undef CONFIG_VIDEO_GFX_HACK
-#define VIDEO_GFX_BIOS_AX 0x4f02	/* 800x600 on ThinkPad */
-#define VIDEO_GFX_BIOS_BX 0x0102
-#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425	/* 100x37 */
-
-/* This code uses an extended set of video mode numbers. These include:
- * Aliases for standard modes
- *	NORMAL_VGA (-1)
- *	EXTENDED_VGA (-2)
- *	ASK_VGA (-3)
- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
- * of compatibility when extending the table. These are between 0x00 and 0xff.
- */
-#define VIDEO_FIRST_MENU 0x0000
-
-/* Standard BIOS video modes (BIOS number + 0x0100) */
-#define VIDEO_FIRST_BIOS 0x0100
-
-/* VESA BIOS video modes (VESA number + 0x0200) */
-#define VIDEO_FIRST_VESA 0x0200
-
-/* Video7 special modes (BIOS number + 0x0900) */
-#define VIDEO_FIRST_V7 0x0900
-
-/* Special video modes */
-#define VIDEO_FIRST_SPECIAL 0x0f00
-#define VIDEO_80x25 0x0f00
-#define VIDEO_8POINT 0x0f01
-#define VIDEO_80x43 0x0f02
-#define VIDEO_80x28 0x0f03
-#define VIDEO_CURRENT_MODE 0x0f04
-#define VIDEO_80x30 0x0f05
-#define VIDEO_80x34 0x0f06
-#define VIDEO_80x60 0x0f07
-#define VIDEO_GFX_HACK 0x0f08
-#define VIDEO_LAST_SPECIAL 0x0f09
-
-/* Video modes given by resolution */
-#define VIDEO_FIRST_RESOLUTION 0x1000
-
-/* The "recalculate timings" flag */
-#define VIDEO_RECALC 0x8000
-
-/* Positions of various video parameters passed to the kernel */
-/* (see also include/linux/tty.h) */
-#define PARAM_CURSOR_POS	0x00
-#define PARAM_VIDEO_PAGE	0x04
-#define PARAM_VIDEO_MODE	0x06
-#define PARAM_VIDEO_COLS	0x07
-#define PARAM_VIDEO_EGA_BX	0x0a
-#define PARAM_VIDEO_LINES	0x0e
-#define PARAM_HAVE_VGA		0x0f
-#define PARAM_FONT_POINTS	0x10
-
-#define PARAM_LFB_WIDTH		0x12
-#define PARAM_LFB_HEIGHT	0x14
-#define PARAM_LFB_DEPTH		0x16
-#define PARAM_LFB_BASE		0x18
-#define PARAM_LFB_SIZE		0x1c
-#define PARAM_LFB_LINELENGTH	0x24
-#define PARAM_LFB_COLORS	0x26
-#define PARAM_VESAPM_SEG	0x2e
-#define PARAM_VESAPM_OFF	0x30
-#define PARAM_LFB_PAGES		0x32
-#define PARAM_VESA_ATTRIB	0x34
-#define PARAM_CAPABILITIES	0x36
-
-/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
-#ifdef CONFIG_VIDEO_RETAIN
-#define DO_STORE call store_screen
-#else
-#define DO_STORE
-#endif /* CONFIG_VIDEO_RETAIN */
-
-# This is the main entry point called by setup.S
-# %ds *must* be pointing to the bootsector
-video:	pushw	%ds		# We use different segments
-	pushw	%ds		# FS contains original DS
-	popw	%fs
-	pushw	%cs		# DS is equal to CS
-	popw	%ds
-	pushw	%cs		# ES is equal to CS
-	popw	%es
-	xorw	%ax, %ax
-	movw	%ax, %gs	# GS is zero
-	cld
-	call	basic_detect	# Basic adapter type testing (EGA/VGA/MDA/CGA)
-#ifdef CONFIG_VIDEO_SELECT
-	movw	%fs:(0x01fa), %ax		# User selected video mode
-	cmpw	$ASK_VGA, %ax			# Bring up the menu
-	jz	vid2
-
-	call	mode_set			# Set the mode
-	jc	vid1
-
-	leaw	badmdt, %si			# Invalid mode ID
-	call	prtstr
-vid2:	call	mode_menu
-vid1:
-#ifdef CONFIG_VIDEO_RETAIN
-	call	restore_screen			# Restore screen contents
-#endif /* CONFIG_VIDEO_RETAIN */
-	call	store_edid
-#endif /* CONFIG_VIDEO_SELECT */
-	call	mode_params			# Store mode parameters
-	popw	%ds				# Restore original DS
-	ret
-
-# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
-basic_detect:
-	movb	$0, %fs:(PARAM_HAVE_VGA)
-	movb	$0x12, %ah	# Check EGA/VGA
-	movb	$0x10, %bl
-	int	$0x10
-	movw	%bx, %fs:(PARAM_VIDEO_EGA_BX)	# Identifies EGA to the kernel
-	cmpb	$0x10, %bl			# No, it's a CGA/MDA/HGA card.
-	je	basret
-
-	incb	adapter
-	movw	$0x1a00, %ax			# Check EGA or VGA?
-	int	$0x10
-	cmpb	$0x1a, %al			# 1a means VGA...
-	jne	basret				# anything else is EGA.
-	
-	incb	%fs:(PARAM_HAVE_VGA)		# We've detected a VGA
-	incb	adapter
-basret:	ret
-
-# Store the video mode parameters for later usage by the kernel.
-# This is done by asking the BIOS except for the rows/columns
-# parameters in the default 80x25 mode -- these are set directly,
-# because some very obscure BIOSes supply insane values.
-mode_params:
-#ifdef CONFIG_VIDEO_SELECT
-	cmpb	$0, graphic_mode
-	jnz	mopar_gr
-#endif
-	movb	$0x03, %ah			# Read cursor position
-	xorb	%bh, %bh
-	int	$0x10
-	movw	%dx, %fs:(PARAM_CURSOR_POS)
-	movb	$0x0f, %ah			# Read page/mode/width
-	int	$0x10
-	movw	%bx, %fs:(PARAM_VIDEO_PAGE)
-	movw	%ax, %fs:(PARAM_VIDEO_MODE)	# Video mode and screen width
-	cmpb	$0x7, %al			# MDA/HGA => segment differs
-	jnz	mopar0
-
-	movw	$0xb000, video_segment
-mopar0: movw	%gs:(0x485), %ax		# Font size
-	movw	%ax, %fs:(PARAM_FONT_POINTS)	# (valid only on EGA/VGA)
-	movw	force_size, %ax			# Forced size?
-	orw	%ax, %ax
-	jz	mopar1
-
-	movb	%ah, %fs:(PARAM_VIDEO_COLS)
-	movb	%al, %fs:(PARAM_VIDEO_LINES)
-	ret
-
-mopar1:	movb	$25, %al
-	cmpb	$0, adapter			# If we are on CGA/MDA/HGA, the
-	jz	mopar2				# screen must have 25 lines.
-
-	movb	%gs:(0x484), %al		# On EGA/VGA, use the EGA+ BIOS
-	incb	%al				# location of max lines.
-mopar2: movb	%al, %fs:(PARAM_VIDEO_LINES)
-	ret
-
-#ifdef CONFIG_VIDEO_SELECT
-# Fetching of VESA frame buffer parameters
-mopar_gr:
-	leaw	modelist+1024, %di
-	movb	$0x23, %fs:(PARAM_HAVE_VGA)
-	movw	16(%di), %ax
-	movw	%ax, %fs:(PARAM_LFB_LINELENGTH)
-	movw	18(%di), %ax
-	movw	%ax, %fs:(PARAM_LFB_WIDTH)
-	movw	20(%di), %ax
-	movw	%ax, %fs:(PARAM_LFB_HEIGHT)
-	movb	25(%di), %al
-	movb	$0, %ah
-	movw	%ax, %fs:(PARAM_LFB_DEPTH)
-	movb	29(%di), %al	
-	movb	$0, %ah
-	movw	%ax, %fs:(PARAM_LFB_PAGES)
-	movl	40(%di), %eax
-	movl	%eax, %fs:(PARAM_LFB_BASE)
-	movl	31(%di), %eax
-	movl	%eax, %fs:(PARAM_LFB_COLORS)
-	movl	35(%di), %eax
-	movl	%eax, %fs:(PARAM_LFB_COLORS+4)
-	movw	0(%di), %ax
-	movw	%ax, %fs:(PARAM_VESA_ATTRIB)
-
-# get video mem size
-	leaw	modelist+1024, %di
-	movw	$0x4f00, %ax
-	int	$0x10
-	xorl	%eax, %eax
-	movw	18(%di), %ax
-	movl	%eax, %fs:(PARAM_LFB_SIZE)
-
-# store mode capabilities
-	movl 10(%di), %eax
-	movl %eax, %fs:(PARAM_CAPABILITIES)
-
-# switching the DAC to 8-bit is for <= 8 bpp only
-	movw	%fs:(PARAM_LFB_DEPTH), %ax
-	cmpw	$8, %ax
-	jg	dac_done
-
-# get DAC switching capability
-	xorl	%eax, %eax
-	movb	10(%di), %al
-	testb	$1, %al
-	jz	dac_set
-
-# attempt to switch DAC to 8-bit
-	movw	$0x4f08, %ax
-	movw	$0x0800, %bx
-	int	$0x10
-	cmpw	$0x004f, %ax
-	jne     dac_set
-	movb    %bh, dac_size		# store actual DAC size
-
-dac_set:
-# set color size to DAC size
-	movb	dac_size, %al
-	movb	%al, %fs:(PARAM_LFB_COLORS+0)
-	movb	%al, %fs:(PARAM_LFB_COLORS+2)
-	movb	%al, %fs:(PARAM_LFB_COLORS+4)
-	movb	%al, %fs:(PARAM_LFB_COLORS+6)
-
-# set color offsets to 0
-	movb	$0, %fs:(PARAM_LFB_COLORS+1)
-	movb	$0, %fs:(PARAM_LFB_COLORS+3)
-	movb	$0, %fs:(PARAM_LFB_COLORS+5)
-	movb	$0, %fs:(PARAM_LFB_COLORS+7)
-
-dac_done:
-# get protected mode interface informations
-	movw	$0x4f0a, %ax
-	xorw	%bx, %bx
-	xorw	%di, %di
-	int	$0x10
-	cmp	$0x004f, %ax
-	jnz	no_pm
-
-	movw	%es, %fs:(PARAM_VESAPM_SEG)
-	movw	%di, %fs:(PARAM_VESAPM_OFF)
-no_pm:	ret
-
-# The video mode menu
-mode_menu:
-	leaw	keymsg, %si			# "Return/Space/Timeout" message
-	call	prtstr
-	call	flush
-nokey:	call	getkt
-
-	cmpb	$0x0d, %al			# ENTER ?
-	je	listm				# yes - manual mode selection
-
-	cmpb	$0x20, %al			# SPACE ?
-	je	defmd1				# no - repeat
-
-	call 	beep
-	jmp	nokey
-
-defmd1:	ret					# No mode chosen? Default 80x25
-
-listm:	call	mode_table			# List mode table
-listm0:	leaw	name_bann, %si			# Print adapter name
-	call	prtstr
-	movw	card_name, %si
-	orw	%si, %si
-	jnz	an2
-
-	movb	adapter, %al
-	leaw	old_name, %si
-	orb	%al, %al
-	jz	an1
-
-	leaw	ega_name, %si
-	decb	%al
-	jz	an1
-
-	leaw	vga_name, %si
-	jmp	an1
-
-an2:	call	prtstr
-	leaw	svga_name, %si
-an1:	call	prtstr
-	leaw	listhdr, %si			# Table header
-	call	prtstr
-	movb	$0x30, %dl			# DL holds mode number
-	leaw	modelist, %si
-lm1:	cmpw	$ASK_VGA, (%si)			# End?
-	jz	lm2
-
-	movb	%dl, %al			# Menu selection number
-	call	prtchr
-	call	prtsp2
-	lodsw
-	call	prthw				# Mode ID
-	call	prtsp2
-	movb	0x1(%si), %al
-	call	prtdec				# Rows
-	movb	$0x78, %al			# the letter 'x'
-	call	prtchr
-	lodsw
-	call	prtdec				# Columns
-	movb	$0x0d, %al			# New line
-	call	prtchr
-	movb	$0x0a, %al
-	call	prtchr
-	incb	%dl				# Next character
-	cmpb	$0x3a, %dl
-	jnz	lm1
-
-	movb	$0x61, %dl
-	jmp	lm1
-
-lm2:	leaw	prompt, %si			# Mode prompt
-	call	prtstr
-	leaw	edit_buf, %di			# Editor buffer
-lm3:	call	getkey
-	cmpb	$0x0d, %al			# Enter?
-	jz	lment
-
-	cmpb	$0x08, %al			# Backspace?
-	jz	lmbs
-
-	cmpb	$0x20, %al			# Printable?
-	jc	lm3
-
-	cmpw	$edit_buf+4, %di		# Enough space?
-	jz	lm3
-
-	stosb
-	call	prtchr
-	jmp	lm3
-
-lmbs:	cmpw	$edit_buf, %di			# Backspace
-	jz	lm3
-
-	decw	%di
-	movb	$0x08, %al
-	call	prtchr
-	call	prtspc
-	movb	$0x08, %al
-	call	prtchr
-	jmp	lm3
-	
-lment:	movb	$0, (%di)
-	leaw	crlft, %si
-	call	prtstr
-	leaw	edit_buf, %si
-	cmpb	$0, (%si)			# Empty string = default mode
-	jz	lmdef
-
-	cmpb	$0, 1(%si)			# One character = menu selection
-	jz	mnusel
-
-	cmpw	$0x6373, (%si)			# "scan" => mode scanning
-	jnz	lmhx
-
-	cmpw	$0x6e61, 2(%si)
-	jz	lmscan
-
-lmhx:	xorw	%bx, %bx			# Else => mode ID in hex
-lmhex:	lodsb
-	orb	%al, %al
-	jz	lmuse1
-
-	subb	$0x30, %al
-	jc	lmbad
-
-	cmpb	$10, %al
-	jc	lmhx1
-
-	subb	$7, %al
-	andb	$0xdf, %al
-	cmpb	$10, %al
-	jc	lmbad
-
-	cmpb	$16, %al
-	jnc	lmbad
-
-lmhx1:	shlw	$4, %bx
-	orb	%al, %bl
-	jmp	lmhex
-
-lmuse1:	movw	%bx, %ax
-	jmp	lmuse
-
-mnusel:	lodsb					# Menu selection
-	xorb	%ah, %ah
-	subb	$0x30, %al
-	jc	lmbad
-
-	cmpb	$10, %al
-	jc	lmuse
-	
-	cmpb	$0x61-0x30, %al
-	jc	lmbad
-	
-	subb	$0x61-0x30-10, %al
-	cmpb	$36, %al
-	jnc	lmbad
-
-lmuse:	call	mode_set
-	jc	lmdef
-
-lmbad:	leaw	unknt, %si
-	call	prtstr
-	jmp	lm2
-lmscan:	cmpb	$0, adapter			# Scanning only on EGA/VGA
-	jz	lmbad
-
-	movw	$0, mt_end			# Scanning of modes is
-	movb	$1, scanning			# done as new autodetection.
-	call	mode_table
-	jmp	listm0
-lmdef:	ret
-
-# Additional parts of mode_set... (relative jumps, you know)
-setv7:						# Video7 extended modes
-	DO_STORE
-	subb	$VIDEO_FIRST_V7>>8, %bh
-	movw	$0x6f05, %ax
-	int	$0x10
-	stc
-	ret
-
-_setrec:	jmp	setrec			# Ugly...
-_set_80x25:	jmp	set_80x25
-
-# Aliases for backward compatibility.
-setalias:
-	movw	$VIDEO_80x25, %ax
-	incw	%bx
-	jz	mode_set
-
-	movb	$VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
-	incw	%bx
-	jnz	setbad				# Fall-through!
-
-# Setting of user mode (AX=mode ID) => CF=success
-mode_set:
-	movw	%ax, %fs:(0x01fa)		# Store mode for use in acpi_wakeup.S
-	movw	%ax, %bx
-	cmpb	$0xff, %ah
-	jz	setalias
-
-	testb	$VIDEO_RECALC>>8, %ah
-	jnz	_setrec
-
-	cmpb	$VIDEO_FIRST_RESOLUTION>>8, %ah
-	jnc	setres
-	
-	cmpb	$VIDEO_FIRST_SPECIAL>>8, %ah
-	jz	setspc
-	
-	cmpb	$VIDEO_FIRST_V7>>8, %ah
-	jz	setv7
-	
-	cmpb	$VIDEO_FIRST_VESA>>8, %ah
-	jnc	check_vesa
-	
-	orb	%ah, %ah
-	jz	setmenu
-	
-	decb	%ah
-	jz	setbios
-
-setbad:	clc
-	movb	$0, do_restore			# The screen needn't be restored
-	ret
-
-setvesa:
-	DO_STORE
-	subb	$VIDEO_FIRST_VESA>>8, %bh
-	movw	$0x4f02, %ax			# VESA BIOS mode set call
-	int	$0x10
-	cmpw	$0x004f, %ax			# AL=4f if implemented
-	jnz	setbad				# AH=0 if OK
-
-	stc
-	ret
-
-setbios:
-	DO_STORE
-	int	$0x10				# Standard BIOS mode set call
-	pushw	%bx
-	movb	$0x0f, %ah			# Check if really set
-	int	$0x10
-	popw	%bx
-	cmpb	%bl, %al
-	jnz	setbad
-	
-	stc
-	ret
-
-setspc:	xorb	%bh, %bh			# Set special mode
-	cmpb	$VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
-	jnc	setbad
-	
-	addw	%bx, %bx
-	jmp	*spec_inits(%bx)
-
-setmenu:
-	orb	%al, %al			# 80x25 is an exception
-	jz	_set_80x25
-	
-	pushw	%bx				# Set mode chosen from menu
-	call	mode_table			# Build the mode table
-	popw	%ax
-	shlw	$2, %ax
-	addw	%ax, %si
-	cmpw	%di, %si
-	jnc	setbad
-	
-	movw	(%si), %ax			# Fetch mode ID
-_m_s:	jmp	mode_set
-
-setres:	pushw	%bx				# Set mode chosen by resolution
-	call	mode_table
-	popw	%bx
-	xchgb	%bl, %bh
-setr1:	lodsw
-	cmpw	$ASK_VGA, %ax			# End of the list?
-	jz	setbad
-	
-	lodsw
-	cmpw	%bx, %ax
-	jnz	setr1
-	
-	movw	-4(%si), %ax			# Fetch mode ID
-	jmp	_m_s
-
-check_vesa:
-#ifdef CONFIG_FIRMWARE_EDID
-	leaw	modelist+1024, %di
-	movw	$0x4f00, %ax
-	int	$0x10
-	cmpw	$0x004f, %ax
-	jnz	setbad
-
-	movw	4(%di), %ax
-	movw	%ax, vbe_version
-#endif
-	leaw	modelist+1024, %di
-	subb	$VIDEO_FIRST_VESA>>8, %bh
-	movw	%bx, %cx			# Get mode information structure
-	movw	$0x4f01, %ax
-	int	$0x10
-	addb	$VIDEO_FIRST_VESA>>8, %bh
-	cmpw	$0x004f, %ax
-	jnz	setbad
-
-	movb	(%di), %al			# Check capabilities.
-	andb	$0x19, %al
-	cmpb	$0x09, %al
-	jz	setvesa				# This is a text mode
-
-	movb	(%di), %al			# Check capabilities.
-	andb	$0x99, %al
-	cmpb	$0x99, %al
-	jnz	_setbad				# Doh! No linear frame buffer.
-
-	subb	$VIDEO_FIRST_VESA>>8, %bh
-	orw	$0x4000, %bx			# Use linear frame buffer
-	movw	$0x4f02, %ax			# VESA BIOS mode set call
-	int	$0x10
-	cmpw	$0x004f, %ax			# AL=4f if implemented
-	jnz	_setbad				# AH=0 if OK
-
-	movb	$1, graphic_mode		# flag graphic mode
-	movb	$0, do_restore			# no screen restore
-	stc
-	ret
-
-_setbad:	jmp	setbad          	# Ugly...
-
-# Recalculate vertical display end registers -- this fixes various
-# inconsistencies of extended modes on many adapters. Called when
-# the VIDEO_RECALC flag is set in the mode ID.
-
-setrec:	subb	$VIDEO_RECALC>>8, %ah		# Set the base mode
-	call	mode_set
-	jnc	rct3
-
-	movw	%gs:(0x485), %ax		# Font size in pixels
-	movb	%gs:(0x484), %bl		# Number of rows
-	incb	%bl
-	mulb	%bl				# Number of visible
-	decw	%ax				# scan lines - 1
-	movw	$0x3d4, %dx
-	movw	%ax, %bx
-	movb	$0x12, %al			# Lower 8 bits
-	movb	%bl, %ah
-	outw	%ax, %dx
-	movb	$0x07, %al		# Bits 8 and 9 in the overflow register
-	call	inidx
-	xchgb	%al, %ah
-	andb	$0xbd, %ah
-	shrb	%bh
-	jnc	rct1
-	orb	$0x02, %ah
-rct1:	shrb	%bh
-	jnc	rct2
-	orb	$0x40, %ah
-rct2:	movb	$0x07, %al
-	outw	%ax, %dx
-	stc
-rct3:	ret
-
-# Table of routines for setting of the special modes.
-spec_inits:
-	.word	set_80x25
-	.word	set_8pixel
-	.word	set_80x43
-	.word	set_80x28
-	.word	set_current
-	.word	set_80x30
-	.word	set_80x34
-	.word	set_80x60
-	.word	set_gfx
-
-# Set the 80x25 mode. If already set, do nothing.
-set_80x25:
-	movw	$0x5019, force_size		# Override possibly broken BIOS
-use_80x25:
-#ifdef CONFIG_VIDEO_400_HACK
-	movw	$0x1202, %ax			# Force 400 scan lines
-	movb	$0x30, %bl
-	int	$0x10
-#else
-	movb	$0x0f, %ah			# Get current mode ID
-	int	$0x10
-	cmpw	$0x5007, %ax	# Mode 7 (80x25 mono) is the only one available
-	jz	st80		# on CGA/MDA/HGA and is also available on EGAM
-
-	cmpw	$0x5003, %ax	# Unknown mode, force 80x25 color
-	jnz	force3
-
-st80:	cmpb	$0, adapter	# CGA/MDA/HGA => mode 3/7 is always 80x25
-	jz	set80
-
-	movb	%gs:(0x0484), %al	# This is EGA+ -- beware of 80x50 etc.
-	orb	%al, %al		# Some buggy BIOS'es set 0 rows
-	jz	set80
-	
-	cmpb	$24, %al		# It's hopefully correct
-	jz	set80
-#endif /* CONFIG_VIDEO_400_HACK */
-force3:	DO_STORE
-	movw	$0x0003, %ax			# Forced set
-	int	$0x10
-set80:	stc
-	ret
-
-# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
-set_8pixel:
-	DO_STORE
-	call	use_80x25			# The base is 80x25
-set_8pt:
-	movw	$0x1112, %ax			# Use 8x8 font
-	xorb	%bl, %bl
-	int	$0x10
-	movw	$0x1200, %ax			# Use alternate print screen
-	movb	$0x20, %bl
-	int	$0x10
-	movw	$0x1201, %ax			# Turn off cursor emulation
-	movb	$0x34, %bl
-	int	$0x10
-	movb	$0x01, %ah			# Define cursor scan lines 6-7
-	movw	$0x0607, %cx
-	int	$0x10
-set_current:
-	stc
-	ret
-
-# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
-# 80x25 mode with 14-point fonts instead of 16-point.
-set_80x28:
-	DO_STORE
-	call	use_80x25			# The base is 80x25
-set14:	movw	$0x1111, %ax			# Use 9x14 font
-	xorb	%bl, %bl
-	int	$0x10
-	movb	$0x01, %ah			# Define cursor scan lines 11-12
-	movw	$0x0b0c, %cx
-	int	$0x10
-	stc
-	ret
-
-# Set the 80x43 mode. This mode is works on all VGA's.
-# It's a 350-scanline mode with 8-pixel font.
-set_80x43:
-	DO_STORE
-	movw	$0x1201, %ax			# Set 350 scans
-	movb	$0x30, %bl
-	int	$0x10
-	movw	$0x0003, %ax			# Reset video mode
-	int	$0x10
-	jmp	set_8pt				# Use 8-pixel font
-
-# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
-set_80x30:
-	call	use_80x25			# Start with real 80x25
-	DO_STORE
-	movw	$0x3cc, %dx			# Get CRTC port
-	inb	%dx, %al
-	movb	$0xd4, %dl
-	rorb	%al				# Mono or color?
-	jc	set48a
-
-	movb	$0xb4, %dl
-set48a:	movw	$0x0c11, %ax		# Vertical sync end (also unlocks CR0-7)
- 	call	outidx
-	movw	$0x0b06, %ax			# Vertical total
- 	call	outidx
-	movw	$0x3e07, %ax			# (Vertical) overflow
- 	call	outidx
-	movw	$0xea10, %ax			# Vertical sync start
- 	call	outidx
-	movw	$0xdf12, %ax			# Vertical display end
-	call	outidx
-	movw	$0xe715, %ax			# Vertical blank start
- 	call	outidx
-	movw	$0x0416, %ax			# Vertical blank end
- 	call	outidx
-	pushw	%dx
-	movb	$0xcc, %dl			# Misc output register (read)
- 	inb	%dx, %al
- 	movb	$0xc2, %dl			# (write)
- 	andb	$0x0d, %al	# Preserve clock select bits and color bit
- 	orb	$0xe2, %al			# Set correct sync polarity
- 	outb	%al, %dx
-	popw	%dx
-	movw	$0x501e, force_size
-	stc					# That's all.
-	ret
-
-# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
-set_80x34:
-	call	set_80x30			# Set 480 scans
-	call	set14				# And 14-pt font
-	movw	$0xdb12, %ax			# VGA vertical display end
-	movw	$0x5022, force_size
-setvde:	call	outidx
-	stc
-	ret
-
-# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
-set_80x60:
-	call	set_80x30			# Set 480 scans
-	call	set_8pt				# And 8-pt font
-	movw	$0xdf12, %ax			# VGA vertical display end
-	movw	$0x503c, force_size
-	jmp	setvde
-
-# Special hack for ThinkPad graphics
-set_gfx:
-#ifdef CONFIG_VIDEO_GFX_HACK
-	movw	$VIDEO_GFX_BIOS_AX, %ax
-	movw	$VIDEO_GFX_BIOS_BX, %bx
-	int	$0x10
-	movw	$VIDEO_GFX_DUMMY_RESOLUTION, force_size
-	stc
-#endif
-	ret
-
-#ifdef CONFIG_VIDEO_RETAIN
-
-# Store screen contents to temporary buffer.
-store_screen:
-	cmpb	$0, do_restore			# Already stored?
-	jnz	stsr
-
-	testb	$CAN_USE_HEAP, loadflags	# Have we space for storing?
-	jz	stsr
-	
-	pushw	%ax
-	pushw	%bx
-	pushw	force_size			# Don't force specific size
-	movw	$0, force_size
-	call	mode_params			# Obtain params of current mode
-	popw	force_size
-	movb	%fs:(PARAM_VIDEO_LINES), %ah
-	movb	%fs:(PARAM_VIDEO_COLS), %al
-	movw	%ax, %bx			# BX=dimensions
-	mulb	%ah
-	movw	%ax, %cx			# CX=number of characters
-	addw	%ax, %ax			# Calculate image size
-	addw	$modelist+1024+4, %ax
-	cmpw	heap_end_ptr, %ax
-	jnc	sts1				# Unfortunately, out of memory
-
-	movw	%fs:(PARAM_CURSOR_POS), %ax	# Store mode params
-	leaw	modelist+1024, %di
-	stosw
-	movw	%bx, %ax
-	stosw
-	pushw	%ds				# Store the screen
-	movw	video_segment, %ds
-	xorw	%si, %si
-	rep
-	movsw
-	popw	%ds
-	incb	do_restore			# Screen will be restored later
-sts1:	popw	%bx
-	popw	%ax
-stsr:	ret
-
-# Restore screen contents from temporary buffer.
-restore_screen:
-	cmpb	$0, do_restore			# Has the screen been stored?
-	jz	res1
-
-	call	mode_params			# Get parameters of current mode
-	movb	%fs:(PARAM_VIDEO_LINES), %cl
-	movb	%fs:(PARAM_VIDEO_COLS), %ch
-	leaw	modelist+1024, %si		# Screen buffer
-	lodsw					# Set cursor position
-	movw	%ax, %dx
-	cmpb	%cl, %dh
-	jc	res2
-	
-	movb	%cl, %dh
-	decb	%dh
-res2:	cmpb	%ch, %dl
-	jc	res3
-	
-	movb	%ch, %dl
-	decb	%dl
-res3:	movb	$0x02, %ah
-	movb	$0x00, %bh
-	int	$0x10
-	lodsw					# Display size
-	movb	%ah, %dl			# DL=number of lines
-	movb	$0, %ah				# BX=phys. length of orig. line
-	movw	%ax, %bx
-	cmpb	%cl, %dl			# Too many?
-	jc	res4
-
-	pushw	%ax
-	movb	%dl, %al
-	subb	%cl, %al
-	mulb	%bl
-	addw	%ax, %si
-	addw	%ax, %si
-	popw	%ax
-	movb	%cl, %dl
-res4:	cmpb	%ch, %al			# Too wide?
-	jc	res5
-	
-	movb	%ch, %al			# AX=width of src. line
-res5:	movb	$0, %cl
-	xchgb	%ch, %cl
-	movw	%cx, %bp			# BP=width of dest. line
-	pushw	%es
-	movw	video_segment, %es
-	xorw	%di, %di			# Move the data
-	addw	%bx, %bx			# Convert BX and BP to _bytes_
-	addw	%bp, %bp
-res6:	pushw	%si
-	pushw	%di
-	movw	%ax, %cx
-	rep
-	movsw
-	popw	%di
-	popw	%si
-	addw	%bp, %di
-	addw	%bx, %si
-	decb	%dl
-	jnz	res6
-	
-	popw	%es				# Done
-res1:	ret
-#endif /* CONFIG_VIDEO_RETAIN */
-
-# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
-outidx:	outb	%al, %dx
-	pushw	%ax
-	movb	%ah, %al
-	incw	%dx
-	outb	%al, %dx
-	decw	%dx
-	popw	%ax
-	ret
-
-# Build the table of video modes (stored after the setup.S code at the
-# `modelist' label. Each video mode record looks like:
-#	.word	MODE-ID		(our special mode ID (see above))
-#	.byte	rows		(number of rows)
-#	.byte	columns		(number of columns)
-# Returns address of the end of the table in DI, the end is marked
-# with a ASK_VGA ID.
-mode_table:
-	movw	mt_end, %di			# Already filled?
-	orw	%di, %di
-	jnz	mtab1x
-	
-	leaw	modelist, %di			# Store standard modes:
-	movl	$VIDEO_80x25 + 0x50190000, %eax	# The 80x25 mode (ALL)
-	stosl
-	movb	adapter, %al			# CGA/MDA/HGA -- no more modes
-	orb	%al, %al
-	jz	mtabe
-	
-	decb	%al
-	jnz	mtabv
-	
-	movl	$VIDEO_8POINT + 0x502b0000, %eax	# The 80x43 EGA mode
-	stosl
-	jmp	mtabe
-
-mtab1x:	jmp	mtab1
-
-mtabv:	leaw	vga_modes, %si			# All modes for std VGA
-	movw	$vga_modes_end-vga_modes, %cx
-	rep	# I'm unable to use movsw as I don't know how to store a half
-	movsb	# of the expression above to cx without using explicit shr.
-
-	cmpb	$0, scanning			# Mode scan requested?
-	jz	mscan1
-	
-	call	mode_scan
-mscan1:
-
-#ifdef CONFIG_VIDEO_LOCAL
-	call	local_modes
-#endif /* CONFIG_VIDEO_LOCAL */
-
-#ifdef CONFIG_VIDEO_VESA
-	call	vesa_modes			# Detect VESA VGA modes
-#endif /* CONFIG_VIDEO_VESA */
-
-#ifdef CONFIG_VIDEO_SVGA
-	cmpb	$0, scanning			# Bypass when scanning
-	jnz	mscan2
-	
-	call	svga_modes			# Detect SVGA cards & modes
-mscan2:
-#endif /* CONFIG_VIDEO_SVGA */
-
-mtabe:
-
-#ifdef CONFIG_VIDEO_COMPACT
-	leaw	modelist, %si
-	movw	%di, %dx
-	movw	%si, %di
-cmt1:	cmpw	%dx, %si			# Scan all modes
-	jz	cmt2
-
-	leaw	modelist, %bx			# Find in previous entries
-	movw	2(%si), %cx
-cmt3:	cmpw	%bx, %si
-	jz	cmt4
-
-	cmpw	2(%bx), %cx			# Found => don't copy this entry
-	jz	cmt5
-
-	addw	$4, %bx
-	jmp	cmt3
-
-cmt4:	movsl					# Copy entry
-	jmp	cmt1
-
-cmt5:	addw	$4, %si				# Skip entry
-	jmp	cmt1
-
-cmt2:
-#endif	/* CONFIG_VIDEO_COMPACT */
-
-	movw	$ASK_VGA, (%di)			# End marker
-	movw	%di, mt_end
-mtab1:	leaw	modelist, %si			# SI=mode list, DI=list end
-ret0:	ret
-
-# Modes usable on all standard VGAs
-vga_modes:
-	.word	VIDEO_8POINT
-	.word	0x5032				# 80x50
-	.word	VIDEO_80x43
-	.word	0x502b				# 80x43
-	.word	VIDEO_80x28
-	.word	0x501c				# 80x28
-	.word	VIDEO_80x30
-	.word	0x501e				# 80x30
-	.word	VIDEO_80x34
-	.word	0x5022				# 80x34
-	.word	VIDEO_80x60
-	.word	0x503c				# 80x60
-#ifdef CONFIG_VIDEO_GFX_HACK
-	.word	VIDEO_GFX_HACK
-	.word	VIDEO_GFX_DUMMY_RESOLUTION
-#endif
-
-vga_modes_end:
-# Detect VESA modes.
-
-#ifdef CONFIG_VIDEO_VESA
-vesa_modes:
-	cmpb	$2, adapter			# VGA only
-	jnz	ret0
-
-	movw	%di, %bp			# BP=original mode table end
-	addw	$0x200, %di			# Buffer space
-	movw	$0x4f00, %ax			# VESA Get card info call
-	int	$0x10
-	movw	%bp, %di
-	cmpw	$0x004f, %ax			# Successful?
-	jnz	ret0
-	
-	cmpw	$0x4556, 0x200(%di)
-	jnz	ret0
-	
-	cmpw	$0x4153, 0x202(%di)
-	jnz	ret0
-	
-	movw	$vesa_name, card_name		# Set name to "VESA VGA"
-	pushw	%gs
-	lgsw	0x20e(%di), %si			# GS:SI=mode list
-	movw	$128, %cx			# Iteration limit
-vesa1:
-# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
-# XXX:	lodsw	%gs:(%si), %ax			# Get next mode in the list
-	gs; lodsw
-	cmpw	$0xffff, %ax			# End of the table?
-	jz	vesar
-	
-	cmpw	$0x0080, %ax			# Check validity of mode ID
-	jc	vesa2
-	
-	orb	%ah, %ah		# Valid IDs: 0x0000-0x007f/0x0100-0x07ff
-	jz	vesan			# Certain BIOSes report 0x80-0xff!
-
-	cmpw	$0x0800, %ax
-	jnc	vesae
-
-vesa2:	pushw	%cx
-	movw	%ax, %cx			# Get mode information structure
-	movw	$0x4f01, %ax
-	int	$0x10
-	movw	%cx, %bx			# BX=mode number
-	addb	$VIDEO_FIRST_VESA>>8, %bh
-	popw	%cx
-	cmpw	$0x004f, %ax
-	jnz	vesan			# Don't report errors (buggy BIOSES)
-
-	movb	(%di), %al			# Check capabilities. We require
-	andb	$0x19, %al			# a color text mode.
-	cmpb	$0x09, %al
-	jnz	vesan
-	
-	cmpw	$0xb800, 8(%di)		# Standard video memory address required
-	jnz	vesan
-
-	testb	$2, (%di)			# Mode characteristics supplied?
-	movw	%bx, (%di)			# Store mode number
-	jz	vesa3
-	
-	xorw	%dx, %dx
-	movw	0x12(%di), %bx			# Width
-	orb	%bh, %bh
-	jnz	vesan
-	
-	movb	%bl, 0x3(%di)
-	movw	0x14(%di), %ax			# Height
-	orb	%ah, %ah
-	jnz	vesan
-	
-	movb	%al, 2(%di)
-	mulb	%bl
-	cmpw	$8193, %ax		# Small enough for Linux console driver?
-	jnc	vesan
-
-	jmp	vesaok
-
-vesa3:	subw	$0x8108, %bx	# This mode has no detailed info specified,
-	jc	vesan		# so it must be a standard VESA mode.
-
-	cmpw	$5, %bx
-	jnc	vesan
-
-	movw	vesa_text_mode_table(%bx), %ax
-	movw	%ax, 2(%di)
-vesaok:	addw	$4, %di				# The mode is valid. Store it.
-vesan:	loop	vesa1			# Next mode. Limit exceeded => error
-vesae:	leaw	vesaer, %si
-	call	prtstr
-	movw	%bp, %di			# Discard already found modes.
-vesar:	popw	%gs
-	ret
-
-# Dimensions of standard VESA text modes
-vesa_text_mode_table:
-	.byte	60, 80				# 0108
-	.byte	25, 132				# 0109
-	.byte	43, 132				# 010A
-	.byte	50, 132				# 010B
-	.byte	60, 132				# 010C
-#endif	/* CONFIG_VIDEO_VESA */
-
-# Scan for video modes. A bit dirty, but should work.
-mode_scan:
-	movw	$0x0100, %cx			# Start with mode 0
-scm1:	movb	$0, %ah				# Test the mode
-	movb	%cl, %al
-	int	$0x10
-	movb	$0x0f, %ah
-	int	$0x10
-	cmpb	%cl, %al
-	jnz	scm2				# Mode not set
-
-	movw	$0x3c0, %dx			# Test if it's a text mode
-	movb	$0x10, %al			# Mode bits
-	call	inidx
-	andb	$0x03, %al
-	jnz	scm2
-	
-	movb	$0xce, %dl			# Another set of mode bits
-	movb	$0x06, %al
-	call	inidx
-	shrb	%al
-	jc	scm2
-	
-	movb	$0xd4, %dl			# Cursor location
-	movb	$0x0f, %al
-	call	inidx
-	orb	%al, %al
-	jnz	scm2
-	
-	movw	%cx, %ax			# Ok, store the mode
-	stosw
-	movb	%gs:(0x484), %al		# Number of rows
-	incb	%al
-	stosb
-	movw	%gs:(0x44a), %ax		# Number of columns
-	stosb
-scm2:	incb	%cl
-	jns	scm1
-	
-	movw	$0x0003, %ax			# Return back to mode 3
-	int	$0x10
-	ret
-
-tstidx:	outw	%ax, %dx			# OUT DX,AX and inidx
-inidx:	outb	%al, %dx			# Read from indexed VGA register
-	incw	%dx			# AL=index, DX=index reg port -> AL=data
-	inb	%dx, %al
-	decw	%dx
-	ret
-
-# Try to detect type of SVGA card and supply (usually approximate) video
-# mode table for it.
-
-#ifdef CONFIG_VIDEO_SVGA
-svga_modes:
-	leaw	svga_table, %si			# Test all known SVGA adapters
-dosvga:	lodsw
-	movw	%ax, %bp			# Default mode table
-	orw	%ax, %ax
-	jz	didsv1
-
-	lodsw					# Pointer to test routine
-	pushw	%si
-	pushw	%di
-	pushw	%es
-	movw	$0xc000, %bx
-	movw	%bx, %es
-	call	*%ax				# Call test routine
-	popw	%es
-	popw	%di
-	popw	%si
-	orw	%bp, %bp
-	jz	dosvga
-	
-	movw	%bp, %si			# Found, copy the modes
-	movb	svga_prefix, %ah
-cpsvga:	lodsb
-	orb	%al, %al
-	jz	didsv
-	
-	stosw
-	movsw
-	jmp	cpsvga
-
-didsv:	movw	%si, card_name			# Store pointer to card name
-didsv1:	ret
-
-# Table of all known SVGA cards. For each card, we store a pointer to
-# a table of video modes supported by the card and a pointer to a routine
-# used for testing of presence of the card. The video mode table is always
-# followed by the name of the card or the chipset.
-svga_table:
-	.word	ati_md, ati_test
-	.word	oak_md, oak_test
-	.word	paradise_md, paradise_test
-	.word	realtek_md, realtek_test
-	.word	s3_md, s3_test
-	.word	chips_md, chips_test
-	.word	video7_md, video7_test
-	.word	cirrus5_md, cirrus5_test
-	.word	cirrus6_md, cirrus6_test
-	.word	cirrus1_md, cirrus1_test
-	.word	ahead_md, ahead_test
-	.word	everex_md, everex_test
-	.word	genoa_md, genoa_test
-	.word	trident_md, trident_test
-	.word	tseng_md, tseng_test
-	.word	0
-
-# Test routines and mode tables:
-
-# S3 - The test algorithm was taken from the SuperProbe package
-# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
-s3_test:
-	movw	$0x0f35, %cx	# we store some constants in cl/ch
-	movw	$0x03d4, %dx
-	movb	$0x38, %al
-	call	inidx
-	movb	%al, %bh	# store current CRT-register 0x38
-	movw	$0x0038, %ax
-	call	outidx		# disable writing to special regs
-	movb	%cl, %al	# check whether we can write special reg 0x35
-	call	inidx
-	movb	%al, %bl	# save the current value of CRT reg 0x35
-	andb	$0xf0, %al	# clear bits 0-3
-	movb	%al, %ah
-	movb	%cl, %al	# and write it to CRT reg 0x35
-	call	outidx
-	call	inidx		# now read it back
-	andb	%ch, %al	# clear the upper 4 bits
-	jz	s3_2		# the first test failed. But we have a
-
-	movb	%bl, %ah	# second chance
-	movb	%cl, %al
-	call	outidx
-	jmp	s3_1		# do the other tests
-
-s3_2:	movw	%cx, %ax	# load ah with 0xf and al with 0x35
-	orb	%bl, %ah	# set the upper 4 bits of ah with the orig value
-	call	outidx		# write ...
-	call	inidx		# ... and reread 
-	andb	%cl, %al	# turn off the upper 4 bits
-	pushw	%ax
-	movb	%bl, %ah	# restore old value in register 0x35
-	movb	%cl, %al
-	call	outidx
-	popw	%ax
-	cmpb	%ch, %al	# setting lower 4 bits was successful => bad
-	je	no_s3		# writing is allowed => this is not an S3
-
-s3_1:	movw	$0x4838, %ax	# allow writing to special regs by putting
-	call	outidx		# magic number into CRT-register 0x38
-	movb	%cl, %al	# check whether we can write special reg 0x35
-	call	inidx
-	movb	%al, %bl
-	andb	$0xf0, %al
-	movb	%al, %ah
-	movb	%cl, %al
-	call	outidx
-	call	inidx
-	andb	%ch, %al
-	jnz	no_s3		# no, we can't write => no S3
-
-	movw	%cx, %ax
-	orb	%bl, %ah
-	call	outidx
-	call	inidx
-	andb	%ch, %al
-	pushw	%ax
-	movb	%bl, %ah	# restore old value in register 0x35
-	movb	%cl, %al
-	call	outidx
-	popw	%ax
-	cmpb	%ch, %al
-	jne	no_s31		# writing not possible => no S3
-	movb	$0x30, %al
-	call	inidx		# now get the S3 id ...
-	leaw	idS3, %di
-	movw	$0x10, %cx
-	repne
-	scasb
-	je	no_s31
-
-	movb	%bh, %ah
-	movb	$0x38, %al
-	jmp	s3rest
-
-no_s3:	movb	$0x35, %al	# restore CRT register 0x35
-	movb	%bl, %ah
-	call	outidx
-no_s31:	xorw	%bp, %bp	# Detection failed
-s3rest:	movb	%bh, %ah
-	movb	$0x38, %al	# restore old value of CRT register 0x38
-	jmp	outidx
-
-idS3:	.byte	0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
-	.byte	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
-
-s3_md:	.byte	0x54, 0x2b, 0x84
-	.byte	0x55, 0x19, 0x84
-	.byte	0
-	.ascii	"S3"
-	.byte	0
-
-# ATI cards.
-ati_test:
-	leaw 	idati, %si
-	movw	$0x31, %di
-	movw	$0x09, %cx
-	repe
-	cmpsb
-	je	atiok
-
-	xorw	%bp, %bp
-atiok:	ret
-
-idati:	.ascii	"761295520"
-
-ati_md:	.byte	0x23, 0x19, 0x84
-	.byte	0x33, 0x2c, 0x84
-	.byte	0x22, 0x1e, 0x64
-	.byte	0x21, 0x19, 0x64
-	.byte	0x58, 0x21, 0x50
-	.byte	0x5b, 0x1e, 0x50
-	.byte	0
-	.ascii	"ATI"
-	.byte	0
-
-# AHEAD
-ahead_test:
-	movw	$0x200f, %ax
-	movw	$0x3ce, %dx
-	outw	%ax, %dx
-	incw	%dx
-	inb	%dx, %al
-	cmpb	$0x20, %al
-	je	isahed
-
-	cmpb	$0x21, %al
-	je	isahed
-	
-	xorw	%bp, %bp
-isahed:	ret
-
-ahead_md:
-	.byte	0x22, 0x2c, 0x84
-	.byte	0x23, 0x19, 0x84
-	.byte	0x24, 0x1c, 0x84
-	.byte	0x2f, 0x32, 0xa0
-	.byte	0x32, 0x22, 0x50
-	.byte	0x34, 0x42, 0x50
-	.byte	0
-	.ascii	"Ahead"
-	.byte	0
-
-# Chips & Tech.
-chips_test:
-	movw	$0x3c3, %dx
-	inb	%dx, %al
-	orb	$0x10, %al
-	outb	%al, %dx
-	movw	$0x104, %dx
-	inb	%dx, %al
-	movb	%al, %bl
-	movw	$0x3c3, %dx
-	inb	%dx, %al
-	andb	$0xef, %al
-	outb	%al, %dx
-	cmpb	$0xa5, %bl
-	je	cantok
-	
-	xorw	%bp, %bp
-cantok:	ret
-
-chips_md:
-	.byte	0x60, 0x19, 0x84
-	.byte	0x61, 0x32, 0x84
-	.byte	0
-	.ascii	"Chips & Technologies"
-	.byte	0
-
-# Cirrus Logic 5X0
-cirrus1_test:
-	movw	$0x3d4, %dx
-	movb	$0x0c, %al
-	outb	%al, %dx
-	incw	%dx
-	inb	%dx, %al
-	movb	%al, %bl
-	xorb	%al, %al
-	outb	%al, %dx
-	decw	%dx
-	movb	$0x1f, %al
-	outb	%al, %dx
-	incw	%dx
-	inb	%dx, %al
-	movb	%al, %bh
-	xorb	%ah, %ah
-	shlb	$4, %al
-	movw	%ax, %cx
-	movb	%bh, %al
-	shrb	$4, %al
-	addw	%ax, %cx
-	shlw	$8, %cx
-	addw	$6, %cx
-	movw	%cx, %ax
-	movw	$0x3c4, %dx
-	outw	%ax, %dx
-	incw	%dx
-	inb	%dx, %al
-	andb	%al, %al
-	jnz	nocirr
-	
-	movb	%bh, %al
-	outb	%al, %dx
-	inb	%dx, %al
-	cmpb	$0x01, %al
-	je	iscirr
-
-nocirr:	xorw	%bp, %bp
-iscirr: movw	$0x3d4, %dx
-	movb	%bl, %al
-	xorb	%ah, %ah
-	shlw	$8, %ax
-	addw	$0x0c, %ax
-	outw	%ax, %dx
-	ret
-
-cirrus1_md:
-	.byte	0x1f, 0x19, 0x84
-	.byte	0x20, 0x2c, 0x84
-	.byte	0x22, 0x1e, 0x84
-	.byte	0x31, 0x25, 0x64
-	.byte	0
-	.ascii	"Cirrus Logic 5X0"
-	.byte	0
-
-# Cirrus Logic 54XX
-cirrus5_test:
-	movw	$0x3c4, %dx
-	movb	$6, %al
-	call	inidx
-	movb	%al, %bl			# BL=backup
-	movw	$6, %ax
-	call	tstidx
-	cmpb	$0x0f, %al
-	jne	c5fail
-	
-	movw	$0x1206, %ax
-	call	tstidx
-	cmpb	$0x12, %al
-	jne	c5fail
-	
-	movb	$0x1e, %al
-	call	inidx
-	movb	%al, %bh
-	movb	%bh, %ah
-	andb	$0xc0, %ah
-	movb	$0x1e, %al
-	call	tstidx
-	andb	$0x3f, %al
-	jne	c5xx
-	
-	movb	$0x1e, %al
-	movb	%bh, %ah
-	orb	$0x3f, %ah
-	call	tstidx
-	xorb	$0x3f, %al
-	andb	$0x3f, %al
-c5xx:	pushf
-	movb	$0x1e, %al
-	movb	%bh, %ah
-	outw	%ax, %dx
-	popf
-	je	c5done
-
-c5fail:	xorw	%bp, %bp
-c5done:	movb	$6, %al
-	movb	%bl, %ah
-	outw	%ax, %dx
-	ret
-
-cirrus5_md:
-	.byte	0x14, 0x19, 0x84
-	.byte	0x54, 0x2b, 0x84
-	.byte	0
-	.ascii	"Cirrus Logic 54XX"
-	.byte	0
-
-# Cirrus Logic 64XX -- no known extra modes, but must be identified, because
-# it's misidentified by the Ahead test.
-cirrus6_test:
-	movw	$0x3ce, %dx
-	movb	$0x0a, %al
-	call	inidx
-	movb	%al, %bl	# BL=backup
-	movw	$0xce0a, %ax
-	call	tstidx
-	orb	%al, %al
-	jne	c2fail
-	
-	movw	$0xec0a, %ax
-	call	tstidx
-	cmpb	$0x01, %al
-	jne	c2fail
-	
-	movb	$0xaa, %al
-	call	inidx		# 4X, 5X, 7X and 8X are valid 64XX chip ID's. 
-	shrb	$4, %al
-	subb	$4, %al
-	jz	c6done
-	
-	decb	%al
-	jz	c6done
-	
-	subb	$2, %al
-	jz	c6done
-	
-	decb	%al
-	jz	c6done
-	
-c2fail:	xorw	%bp, %bp
-c6done:	movb	$0x0a, %al
-	movb	%bl, %ah
-	outw	%ax, %dx
-	ret
-
-cirrus6_md:
-	.byte	0
-	.ascii	"Cirrus Logic 64XX"
-	.byte	0
-
-# Everex / Trident
-everex_test:
-	movw	$0x7000, %ax
-	xorw	%bx, %bx
-	int	$0x10
-	cmpb	$0x70, %al
-	jne	noevrx
-	
-	shrw	$4, %dx
-	cmpw	$0x678, %dx
-	je	evtrid
-	
-	cmpw	$0x236, %dx
-	jne	evrxok
-
-evtrid:	leaw	trident_md, %bp
-evrxok:	ret
-
-noevrx:	xorw	%bp, %bp
-	ret
-
-everex_md:
-	.byte	0x03, 0x22, 0x50
-	.byte	0x04, 0x3c, 0x50
-	.byte	0x07, 0x2b, 0x64
-	.byte	0x08, 0x4b, 0x64
-	.byte	0x0a, 0x19, 0x84
-	.byte	0x0b, 0x2c, 0x84
-	.byte	0x16, 0x1e, 0x50
-	.byte	0x18, 0x1b, 0x64
-	.byte	0x21, 0x40, 0xa0
-	.byte	0x40, 0x1e, 0x84
-	.byte	0
-	.ascii	"Everex/Trident"
-	.byte	0
-
-# Genoa.
-genoa_test:
-	leaw	idgenoa, %si			# Check Genoa 'clues'
-	xorw	%ax, %ax
-	movb	%es:(0x37), %al
-	movw	%ax, %di
-	movw	$0x04, %cx
-	decw	%si
-	decw	%di
-l1:	incw	%si
-	incw	%di
-	movb	(%si), %al
-	testb	%al, %al
-	jz	l2
-
-	cmpb	%es:(%di), %al
-l2:	loope 	l1
-	orw	%cx, %cx
-	je	isgen
-	
-	xorw	%bp, %bp
-isgen:	ret
-
-idgenoa: .byte	0x77, 0x00, 0x99, 0x66
-
-genoa_md:
-	.byte	0x58, 0x20, 0x50
-	.byte	0x5a, 0x2a, 0x64
-	.byte	0x60, 0x19, 0x84
-	.byte	0x61, 0x1d, 0x84
-	.byte	0x62, 0x20, 0x84
-	.byte	0x63, 0x2c, 0x84
-	.byte	0x64, 0x3c, 0x84
-	.byte	0x6b, 0x4f, 0x64
-	.byte	0x72, 0x3c, 0x50
-	.byte	0x74, 0x42, 0x50
-	.byte	0x78, 0x4b, 0x64
-	.byte	0
-	.ascii	"Genoa"
-	.byte	0
-
-# OAK
-oak_test:
-	leaw	idoakvga, %si
-	movw	$0x08, %di
-	movw	$0x08, %cx
-	repe
-	cmpsb
-	je	isoak
-	
-	xorw	%bp, %bp
-isoak:	ret
-
-idoakvga: .ascii  "OAK VGA "
-
-oak_md: .byte	0x4e, 0x3c, 0x50
-	.byte	0x4f, 0x3c, 0x84
-	.byte	0x50, 0x19, 0x84
-	.byte	0x51, 0x2b, 0x84
-	.byte	0
-	.ascii	"OAK"
-	.byte	0
-
-# WD Paradise.
-paradise_test:
-	leaw	idparadise, %si
-	movw	$0x7d, %di
-	movw	$0x04, %cx
-	repe
-	cmpsb
-	je	ispara
-	
-	xorw	%bp, %bp
-ispara:	ret
-
-idparadise:	.ascii	"VGA="
-
-paradise_md:
-	.byte	0x41, 0x22, 0x50
-	.byte	0x47, 0x1c, 0x84
-	.byte	0x55, 0x19, 0x84
-	.byte	0x54, 0x2c, 0x84
-	.byte	0
-	.ascii	"Paradise"
-	.byte	0
-
-# Trident.
-trident_test:
-	movw	$0x3c4, %dx
-	movb	$0x0e, %al
-	outb	%al, %dx
-	incw	%dx
-	inb	%dx, %al
-	xchgb	%al, %ah
-	xorb	%al, %al
-	outb	%al, %dx
-	inb	%dx, %al
-	xchgb	%ah, %al
-	movb	%al, %bl	# Strange thing ... in the book this wasn't
-	andb	$0x02, %bl	# necessary but it worked on my card which
-	jz	setb2		# is a trident. Without it the screen goes
-				# blurred ...
-	andb	$0xfd, %al
-	jmp	clrb2		
-
-setb2:	orb	$0x02, %al	
-clrb2:	outb	%al, %dx
-	andb	$0x0f, %ah
-	cmpb	$0x02, %ah
-	je	istrid
-
-	xorw	%bp, %bp
-istrid:	ret
-
-trident_md:
-	.byte	0x50, 0x1e, 0x50
-	.byte	0x51, 0x2b, 0x50
-	.byte	0x52, 0x3c, 0x50
-	.byte	0x57, 0x19, 0x84
-	.byte	0x58, 0x1e, 0x84
-	.byte	0x59, 0x2b, 0x84
-	.byte	0x5a, 0x3c, 0x84
-	.byte	0
-	.ascii	"Trident"
-	.byte	0
-
-# Tseng.
-tseng_test:
-	movw	$0x3cd, %dx
-	inb	%dx, %al	# Could things be this simple ! :-)
-	movb	%al, %bl
-	movb	$0x55, %al
-	outb	%al, %dx
-	inb	%dx, %al
-	movb	%al, %ah
-	movb	%bl, %al
-	outb	%al, %dx
-	cmpb	$0x55, %ah
- 	je	istsen
-
-isnot:	xorw	%bp, %bp
-istsen:	ret
-
-tseng_md:
-	.byte	0x26, 0x3c, 0x50
-	.byte	0x2a, 0x28, 0x64
-	.byte	0x23, 0x19, 0x84
-	.byte	0x24, 0x1c, 0x84
-	.byte	0x22, 0x2c, 0x84
-	.byte	0x21, 0x3c, 0x84
-	.byte	0
-	.ascii	"Tseng"
-	.byte	0
-
-# Video7.
-video7_test:
-	movw	$0x3cc, %dx
-	inb	%dx, %al
-	movw	$0x3b4, %dx
-	andb	$0x01, %al
-	jz	even7
-
-	movw	$0x3d4, %dx
-even7:	movb	$0x0c, %al
-	outb	%al, %dx
-	incw	%dx
-	inb	%dx, %al
-	movb	%al, %bl
-	movb	$0x55, %al
-	outb	%al, %dx
-	inb	%dx, %al
-	decw	%dx
-	movb	$0x1f, %al
-	outb	%al, %dx
-	incw	%dx
-	inb	%dx, %al
-	movb	%al, %bh
-	decw	%dx
-	movb	$0x0c, %al
-	outb	%al, %dx
-	incw	%dx
-	movb	%bl, %al
-	outb	%al, %dx
-	movb	$0x55, %al
-	xorb	$0xea, %al
-	cmpb	%bh, %al
-	jne	isnot
-	
-	movb	$VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
-	ret
-
-video7_md:
-	.byte	0x40, 0x2b, 0x50
-	.byte	0x43, 0x3c, 0x50
-	.byte	0x44, 0x3c, 0x64
-	.byte	0x41, 0x19, 0x84
-	.byte	0x42, 0x2c, 0x84
-	.byte	0x45, 0x1c, 0x84
-	.byte	0
-	.ascii	"Video 7"
-	.byte	0
-
-# Realtek VGA
-realtek_test:
-	leaw	idrtvga, %si
-	movw	$0x45, %di
-	movw	$0x0b, %cx
-	repe
-	cmpsb
-	je	isrt
-	
-	xorw	%bp, %bp
-isrt:	ret
-
-idrtvga:	.ascii	"REALTEK VGA"
-
-realtek_md:
-	.byte	0x1a, 0x3c, 0x50
-	.byte	0x1b, 0x19, 0x84
-	.byte	0x1c, 0x1e, 0x84
-	.byte	0x1d, 0x2b, 0x84
-	.byte	0x1e, 0x3c, 0x84
-	.byte	0
-	.ascii	"REALTEK"
-	.byte	0
-
-#endif	/* CONFIG_VIDEO_SVGA */
-
-# User-defined local mode table (VGA only)
-#ifdef CONFIG_VIDEO_LOCAL
-local_modes:
-	leaw	local_mode_table, %si
-locm1:	lodsw
-	orw	%ax, %ax
-	jz	locm2
-	
-	stosw
-	movsw
-	jmp	locm1
-
-locm2:	ret
-
-# This is the table of local video modes which can be supplied manually
-# by the user. Each entry consists of mode ID (word) and dimensions
-# (byte for column count and another byte for row count). These modes
-# are placed before all SVGA and VESA modes and override them if table
-# compacting is enabled. The table must end with a zero word followed
-# by NUL-terminated video adapter name.
-local_mode_table:
-	.word	0x0100				# Example: 40x25
-	.byte	25,40
-	.word	0
-	.ascii	"Local"
-	.byte	0
-#endif	/* CONFIG_VIDEO_LOCAL */
-
-# Read a key and return the ASCII code in al, scan code in ah
-getkey:	xorb	%ah, %ah
-	int	$0x16
-	ret
-
-# Read a key with a timeout of 30 seconds.
-# The hardware clock is used to get the time.
-getkt:	call	gettime
-	addb	$30, %al			# Wait 30 seconds
-	cmpb	$60, %al
-	jl	lminute
-
-	subb	$60, %al
-lminute:
-	movb	%al, %cl
-again:	movb	$0x01, %ah
-	int	$0x16
-	jnz	getkey				# key pressed, so get it
-
-	call	gettime
-	cmpb	%cl, %al
-	jne	again
-
-	movb	$0x20, %al			# timeout, return `space'
-	ret
-
-# Flush the keyboard buffer
-flush:	movb	$0x01, %ah
-	int	$0x16
-	jz	empty
-	
-	xorb	%ah, %ah
-	int	$0x16
-	jmp	flush
-
-empty:	ret
-
-# Print hexadecimal number.
-prthw:	pushw	%ax
-	movb	%ah, %al
-	call	prthb
-	popw	%ax
-prthb:	pushw	%ax
-	shrb	$4, %al
-	call	prthn
-	popw	%ax
-	andb	$0x0f, %al
-prthn:	cmpb	$0x0a, %al
-	jc	prth1
-
-	addb	$0x07, %al
-prth1:	addb	$0x30, %al
-	jmp	prtchr
-
-# Print decimal number in al
-prtdec:	pushw	%ax
-	pushw	%cx
-	xorb	%ah, %ah
-	movb	$0x0a, %cl
-	idivb	%cl
-	cmpb	$0x09, %al
-	jbe	lt100
-
-	call	prtdec
-	jmp	skip10
-
-lt100:	addb	$0x30, %al
-	call	prtchr
-skip10:	movb	%ah, %al
-	addb	$0x30, %al
-	call	prtchr	
-	popw	%cx
-	popw	%ax
-	ret
-
-store_edid:
-#ifdef CONFIG_FIRMWARE_EDID
-	pushw	%es				# just save all registers
-	pushw	%ax
-	pushw	%bx
-	pushw   %cx
-	pushw	%dx
-	pushw   %di
-
-	pushw	%fs
-	popw    %es
-
-	movl	$0x13131313, %eax		# memset block with 0x13
-	movw    $32, %cx
-	movw	$0x140, %di
-	cld
-	rep
-	stosl
-
-	cmpw	$0x0200, vbe_version		# only do EDID on >= VBE2.0
-	jl	no_edid
-
-	pushw   %es				# save ES
-	xorw    %di, %di                        # Report Capability
-	pushw   %di
-	popw    %es                             # ES:DI must be 0:0
-	movw	$0x4f15, %ax
-	xorw	%bx, %bx
-	xorw	%cx, %cx
-	int	$0x10
-	popw    %es                             # restore ES
-
-	cmpb    $0x00, %ah                      # call successful
-	jne     no_edid
-
-	cmpb    $0x4f, %al                      # function supported
-	jne     no_edid
-
-	movw	$0x4f15, %ax                    # do VBE/DDC
-	movw	$0x01, %bx
-	movw	$0x00, %cx
-	movw    $0x00, %dx
-	movw	$0x140, %di
-	int	$0x10
-
-no_edid:
-	popw	%di				# restore all registers
-	popw	%dx
-	popw	%cx
-	popw	%bx
-	popw	%ax
-	popw	%es
-#endif
-	ret
-
-# VIDEO_SELECT-only variables
-mt_end:		.word	0	# End of video mode table if built
-edit_buf:	.space	6	# Line editor buffer
-card_name:	.word	0	# Pointer to adapter name
-scanning:	.byte	0	# Performing mode scan
-do_restore:	.byte	0	# Screen contents altered during mode change
-svga_prefix:	.byte	VIDEO_FIRST_BIOS>>8	# Default prefix for BIOS modes
-graphic_mode:	.byte	0	# Graphic mode with a linear frame buffer
-dac_size:	.byte	6	# DAC bit depth
-vbe_version:	.word	0	# VBE bios version
-
-# Status messages
-keymsg:		.ascii	"Press <RETURN> to see video modes available, "
-		.ascii	"<SPACE> to continue or wait 30 secs"
-		.byte	0x0d, 0x0a, 0
-
-listhdr:	.byte	0x0d, 0x0a
-		.ascii	"Mode:    COLSxROWS:"
-
-crlft:		.byte	0x0d, 0x0a, 0
-
-prompt:		.byte	0x0d, 0x0a
-		.asciz	"Enter mode number or `scan': "
-
-unknt:		.asciz	"Unknown mode ID. Try again."
-
-badmdt:		.ascii	"You passed an undefined mode number."
-		.byte	0x0d, 0x0a, 0
-
-vesaer:		.ascii	"Error: Scanning of VESA modes failed. Please "
-		.ascii	"report to <mj@ucw.cz>."
-		.byte	0x0d, 0x0a, 0
-
-old_name:	.asciz	"CGA/MDA/HGA"
-
-ega_name:	.asciz	"EGA"
-
-svga_name:	.ascii	" "
-
-vga_name:	.asciz	"VGA"
-
-vesa_name:	.asciz	"VESA"
-
-name_bann:	.asciz	"Video adapter: "
-#endif /* CONFIG_VIDEO_SELECT */
-
-# Other variables:
-adapter:	.byte	0	# Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
-video_segment:	.word	0xb800	# Video memory segment
-force_size:	.word	0	# Use this size instead of the one in BIOS vars
diff --git a/arch/i386/boot/video.c b/arch/i386/boot/video.c
new file mode 100644
index 0000000..3bb3573
--- /dev/null
+++ b/arch/i386/boot/video.c
@@ -0,0 +1,456 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video.c
+ *
+ * Select video mode
+ */
+
+#include "boot.h"
+#include "video.h"
+#include "vesa.h"
+
+/*
+ * Mode list variables
+ */
+static struct card_info cards[];    /* List of cards to probe for */
+
+/*
+ * Common variables
+ */
+int adapter;			/* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
+u16 video_segment;
+int force_x, force_y;	/* Don't query the BIOS for cols/rows */
+
+int do_restore = 0;	/* Screen contents changed during mode flip */
+int graphic_mode;	/* Graphic mode with linear frame buffer */
+
+static void store_cursor_position(void)
+{
+	u16 curpos;
+	u16 ax, bx;
+
+	ax = 0x0300;
+	bx = 0;
+	asm(INT10
+	    : "=d" (curpos), "+a" (ax), "+b" (bx)
+	    : : "ecx", "esi", "edi");
+
+	boot_params.screen_info.orig_x = curpos;
+	boot_params.screen_info.orig_y = curpos >> 8;
+}
+
+static void store_video_mode(void)
+{
+	u16 ax, page;
+
+	/* N.B.: the saving of the video page here is a bit silly,
+	   since we pretty much assume page 0 everywhere. */
+	ax = 0x0f00;
+	asm(INT10
+	    : "+a" (ax), "=b" (page)
+	    : : "ecx", "edx", "esi", "edi");
+
+	/* Not all BIOSes are clean with respect to the top bit */
+	boot_params.screen_info.orig_video_mode = ax & 0x7f;
+	boot_params.screen_info.orig_video_page = page;
+}
+
+/*
+ * Store the video mode parameters for later usage by the kernel.
+ * This is done by asking the BIOS except for the rows/columns
+ * parameters in the default 80x25 mode -- these are set directly,
+ * because some very obscure BIOSes supply insane values.
+ */
+static void store_mode_params(void)
+{
+	u16 font_size;
+	int x, y;
+
+	/* For graphics mode, it is up to the mode-setting driver
+	   (currently only video-vesa.c) to store the parameters */
+	if (graphic_mode)
+		return;
+
+	store_cursor_position();
+	store_video_mode();
+
+	if (boot_params.screen_info.orig_video_mode == 0x07) {
+		/* MDA, HGC, or VGA in monochrome mode */
+		video_segment = 0xb000;
+	} else {
+		/* CGA, EGA, VGA and so forth */
+		video_segment = 0xb800;
+	}
+
+	set_fs(0);
+	font_size = rdfs16(0x485); /* Font size, BIOS area */
+	boot_params.screen_info.orig_video_points = font_size;
+
+	x = rdfs16(0x44a);
+	y = (adapter == ADAPTER_CGA) ? 25 : rdfs8(0x484)+1;
+
+	if (force_x)
+		x = force_x;
+	if (force_y)
+		y = force_y;
+
+	boot_params.screen_info.orig_video_cols  = x;
+	boot_params.screen_info.orig_video_lines = y;
+}
+
+/* Probe the video drivers and have them generate their mode lists. */
+static void probe_cards(int unsafe)
+{
+	struct card_info *card;
+	static u8 probed[2];
+
+	if (probed[unsafe])
+		return;
+
+	probed[unsafe] = 1;
+
+	for (card = video_cards; card < video_cards_end; card++) {
+		if (card->unsafe == unsafe) {
+			if (card->probe)
+				card->nmodes = card->probe();
+			else
+				card->nmodes = 0;
+		}
+	}
+}
+
+/* Test if a mode is defined */
+int mode_defined(u16 mode)
+{
+	struct card_info *card;
+	struct mode_info *mi;
+	int i;
+
+	for (card = video_cards; card < video_cards_end; card++) {
+		mi = card->modes;
+		for (i = 0; i < card->nmodes; i++, mi++) {
+			if (mi->mode == mode)
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+/* Set mode (without recalc) */
+static int raw_set_mode(u16 mode)
+{
+	int nmode, i;
+	struct card_info *card;
+	struct mode_info *mi;
+
+	/* Drop the recalc bit if set */
+	mode &= ~VIDEO_RECALC;
+
+	/* Scan for mode based on fixed ID, position, or resolution */
+	nmode = 0;
+	for (card = video_cards; card < video_cards_end; card++) {
+		mi = card->modes;
+		for (i = 0; i < card->nmodes; i++, mi++) {
+			int visible = mi->x || mi->y;
+
+			if ((mode == nmode && visible) ||
+			    mode == mi->mode ||
+			    mode == (mi->y << 8)+mi->x)
+				return card->set_mode(mi);
+
+			if (visible)
+				nmode++;
+		}
+	}
+
+	/* Nothing found?  Is it an "exceptional" (unprobed) mode? */
+	for (card = video_cards; card < video_cards_end; card++) {
+		if (mode >= card->xmode_first &&
+		    mode < card->xmode_first+card->xmode_n) {
+			struct mode_info mix;
+			mix.mode = mode;
+			mix.x = mix.y = 0;
+			return card->set_mode(&mix);
+		}
+	}
+
+	/* Otherwise, failure... */
+	return -1;
+}
+
+/*
+ * Recalculate the vertical video cutoff (hack!)
+ */
+static void vga_recalc_vertical(void)
+{
+	unsigned int font_size, rows;
+	u16 crtc;
+	u8 ov;
+
+	set_fs(0);
+	font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
+	rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
+
+	rows *= font_size;	/* Visible scan lines */
+	rows--;			/* ... minus one */
+
+	crtc = vga_crtc();
+
+	out_idx((u8)rows, crtc, 0x12); /* Lower height register */
+	ov = in_idx(crtc, 0x07); /* Overflow register */
+	ov &= 0xbd;
+	ov |= (rows >> (8-1)) & 0x02;
+	ov |= (rows >> (9-6)) & 0x40;
+	out_idx(ov, crtc, 0x07);
+}
+
+/* Set mode (with recalc if specified) */
+static int set_mode(u16 mode)
+{
+	int rv;
+
+	/* Very special mode numbers... */
+	if (mode == VIDEO_CURRENT_MODE)
+		return 0;	/* Nothing to do... */
+	else if (mode == NORMAL_VGA)
+		mode = VIDEO_80x25;
+	else if (mode == EXTENDED_VGA)
+		mode = VIDEO_8POINT;
+
+	rv = raw_set_mode(mode);
+	if (rv)
+		return rv;
+
+	if (mode & VIDEO_RECALC)
+		vga_recalc_vertical();
+
+	return 0;
+}
+
+static unsigned int get_entry(void)
+{
+	char entry_buf[4];
+	int i, len = 0;
+	int key;
+	unsigned int v;
+
+	do {
+		key = getchar();
+
+		if (key == '\b') {
+			if (len > 0) {
+				puts("\b \b");
+				len--;
+			}
+		} else if ((key >= '0' && key <= '9') ||
+			   (key >= 'A' && key <= 'Z') ||
+			   (key >= 'a' && key <= 'z')) {
+			if (len < sizeof entry_buf) {
+				entry_buf[len++] = key;
+				putchar(key);
+			}
+		}
+	} while (key != '\r');
+	putchar('\n');
+
+	if (len == 0)
+		return VIDEO_CURRENT_MODE; /* Default */
+
+	v = 0;
+	for (i = 0; i < len; i++) {
+		v <<= 4;
+		key = entry_buf[i] | 0x20;
+		v += (key > '9') ? key-'a'+10 : key-'0';
+	}
+
+	return v;
+}
+
+static void display_menu(void)
+{
+	struct card_info *card;
+	struct mode_info *mi;
+	char ch;
+	int i;
+
+	puts("Mode:    COLSxROWS:\n");
+
+	ch = '0';
+	for (card = video_cards; card < video_cards_end; card++) {
+		mi = card->modes;
+		for (i = 0; i < card->nmodes; i++, mi++) {
+			int visible = mi->x && mi->y;
+			u16 mode_id = mi->mode ? mi->mode :
+				(mi->y << 8)+mi->x;
+
+			if (!visible)
+				continue; /* Hidden mode */
+
+			printf("%c  %04X  %3dx%-3d  %s\n",
+			       ch, mode_id, mi->x, mi->y, card->card_name);
+
+			if (ch == '9')
+				ch = 'a';
+			else if (ch == 'z' || ch == ' ')
+				ch = ' '; /* Out of keys... */
+			else
+				ch++;
+		}
+	}
+}
+
+#define H(x)	((x)-'a'+10)
+#define SCAN	((H('s')<<12)+(H('c')<<8)+(H('a')<<4)+H('n'))
+
+static unsigned int mode_menu(void)
+{
+	int key;
+	unsigned int sel;
+
+	puts("Press <ENTER> to see video modes available, "
+	     "<SPACE> to continue, or wait 30 sec\n");
+
+	kbd_flush();
+	while (1) {
+		key = getchar_timeout();
+		if (key == ' ' || key == 0)
+			return VIDEO_CURRENT_MODE; /* Default */
+		if (key == '\r')
+			break;
+		putchar('\a');	/* Beep! */
+	}
+
+
+	for (;;) {
+		display_menu();
+
+		puts("Enter a video mode or \"scan\" to scan for "
+		     "additional modes: ");
+		sel = get_entry();
+		if (sel != SCAN)
+			return sel;
+
+		probe_cards(1);
+	}
+}
+
+#ifdef CONFIG_VIDEO_RETAIN
+/* Save screen content to the heap */
+struct saved_screen {
+	int x, y;
+	int curx, cury;
+	u16 *data;
+} saved;
+
+static void save_screen(void)
+{
+	/* Should be called after store_mode_params() */
+	saved.x = boot_params.screen_info.orig_video_cols;
+	saved.y = boot_params.screen_info.orig_video_lines;
+	saved.curx = boot_params.screen_info.orig_x;
+	saved.cury = boot_params.screen_info.orig_y;
+
+	if (heap_free() < saved.x*saved.y*sizeof(u16)+512)
+		return;		/* Not enough heap to save the screen */
+
+	saved.data = GET_HEAP(u16, saved.x*saved.y);
+
+	set_fs(video_segment);
+	copy_from_fs(saved.data, 0, saved.x*saved.y*sizeof(u16));
+}
+
+static void restore_screen(void)
+{
+	/* Should be called after store_mode_params() */
+	int xs = boot_params.screen_info.orig_video_cols;
+	int ys = boot_params.screen_info.orig_video_lines;
+	int y;
+	addr_t dst = 0;
+	u16 *src = saved.data;
+	u16 ax, bx, dx;
+
+	if (graphic_mode)
+		return;		/* Can't restore onto a graphic mode */
+
+	if (!src)
+		return;		/* No saved screen contents */
+
+	/* Restore screen contents */
+
+	set_fs(video_segment);
+	for (y = 0; y < ys; y++) {
+		int npad;
+
+		if (y < saved.y) {
+			int copy = (xs < saved.x) ? xs : saved.x;
+			copy_to_fs(dst, src, copy*sizeof(u16));
+			dst += copy*sizeof(u16);
+			src += saved.x;
+			npad = (xs < saved.x) ? 0 : xs-saved.x;
+		} else {
+			npad = xs;
+		}
+
+		/* Writes "npad" blank characters to
+		   video_segment:dst and advances dst */
+		asm volatile("pushw %%es ; "
+			     "movw %2,%%es ; "
+			     "shrw %%cx ; "
+			     "jnc 1f ; "
+			     "stosw \n\t"
+			     "1: rep;stosl ; "
+			     "popw %%es"
+			     : "+D" (dst), "+c" (npad)
+			     : "bdSm" (video_segment),
+			       "a" (0x07200720));
+	}
+
+	/* Restore cursor position */
+	ax = 0x0200;		/* Set cursor position */
+	bx = 0;			/* Page number (<< 8) */
+	dx = (saved.cury << 8)+saved.curx;
+	asm volatile(INT10
+		     : "+a" (ax), "+b" (bx), "+d" (dx)
+		     : : "ecx", "esi", "edi");
+}
+#else
+#define save_screen()		((void)0)
+#define restore_screen()	((void)0)
+#endif
+
+void set_video(void)
+{
+	u16 mode = boot_params.hdr.vid_mode;
+
+	RESET_HEAP();
+
+	store_mode_params();
+	save_screen();
+	probe_cards(0);
+
+	for (;;) {
+		if (mode == ASK_VGA)
+			mode = mode_menu();
+
+		if (!set_mode(mode))
+			break;
+
+		printf("Undefined video mode number: %x\n", mode);
+		mode = ASK_VGA;
+	}
+	vesa_store_edid();
+	store_mode_params();
+
+	if (do_restore)
+		restore_screen();
+}
diff --git a/arch/i386/boot/video.h b/arch/i386/boot/video.h
new file mode 100644
index 0000000..29eca17
--- /dev/null
+++ b/arch/i386/boot/video.h
@@ -0,0 +1,145 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video.h
+ *
+ * Header file for the real-mode video probing code
+ */
+
+#ifndef BOOT_VIDEO_H
+#define BOOT_VIDEO_H
+
+#include <linux/types.h>
+
+/* Enable autodetection of SVGA adapters and modes. */
+#undef CONFIG_VIDEO_SVGA
+
+/* Enable autodetection of VESA modes */
+#define CONFIG_VIDEO_VESA
+
+/* Retain screen contents when switching modes */
+#define CONFIG_VIDEO_RETAIN
+
+/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
+#undef CONFIG_VIDEO_400_HACK
+
+/* This code uses an extended set of video mode numbers. These include:
+ * Aliases for standard modes
+ *      NORMAL_VGA (-1)
+ *      EXTENDED_VGA (-2)
+ *      ASK_VGA (-3)
+ * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+ * of compatibility when extending the table. These are between 0x00 and 0xff.
+ */
+#define VIDEO_FIRST_MENU 0x0000
+
+/* Standard BIOS video modes (BIOS number + 0x0100) */
+#define VIDEO_FIRST_BIOS 0x0100
+
+/* VESA BIOS video modes (VESA number + 0x0200) */
+#define VIDEO_FIRST_VESA 0x0200
+
+/* Video7 special modes (BIOS number + 0x0900) */
+#define VIDEO_FIRST_V7 0x0900
+
+/* Special video modes */
+#define VIDEO_FIRST_SPECIAL 0x0f00
+#define VIDEO_80x25 0x0f00
+#define VIDEO_8POINT 0x0f01
+#define VIDEO_80x43 0x0f02
+#define VIDEO_80x28 0x0f03
+#define VIDEO_CURRENT_MODE 0x0f04
+#define VIDEO_80x30 0x0f05
+#define VIDEO_80x34 0x0f06
+#define VIDEO_80x60 0x0f07
+#define VIDEO_GFX_HACK 0x0f08
+#define VIDEO_LAST_SPECIAL 0x0f09
+
+/* Video modes given by resolution */
+#define VIDEO_FIRST_RESOLUTION 0x1000
+
+/* The "recalculate timings" flag */
+#define VIDEO_RECALC 0x8000
+
+/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
+#ifdef CONFIG_VIDEO_RETAIN
+void store_screen(void);
+#define DO_STORE() store_screen()
+#else
+#define DO_STORE() ((void)0)
+#endif /* CONFIG_VIDEO_RETAIN */
+
+/*
+ * Mode table structures
+ */
+
+struct mode_info {
+	u16 mode;		/* Mode number (vga= style) */
+	u8  x, y;		/* Width, height */
+};
+
+struct card_info {
+	const char *card_name;
+	int (*set_mode)(struct mode_info *mode);
+	int (*probe)(void);
+	struct mode_info *modes;
+	int nmodes;		/* Number of probed modes so far */
+	int unsafe;		/* Probing is unsafe, only do after "scan" */
+	u16 xmode_first;	/* Unprobed modes to try to call anyway */
+	u16 xmode_n;		/* Size of unprobed mode range */
+};
+
+#define __videocard struct card_info __attribute__((section(".videocards")))
+extern struct card_info video_cards[], video_cards_end[];
+
+int mode_defined(u16 mode);	/* video.c */
+
+/* Basic video information */
+#define ADAPTER_CGA	0	/* CGA/MDA/HGC */
+#define ADAPTER_EGA	1
+#define ADAPTER_VGA	2
+
+extern int adapter;
+extern u16 video_segment;
+extern int force_x, force_y;	/* Don't query the BIOS for cols/rows */
+extern int do_restore;		/* Restore screen contents */
+extern int graphic_mode;	/* Graphics mode with linear frame buffer */
+
+/*
+ * int $0x10 is notorious for touching registers it shouldn't.
+ * gcc doesn't like %ebp being clobbered, so define it as a push/pop
+ * sequence here.
+ */
+#define INT10 "pushl %%ebp; int $0x10; popl %%ebp"
+
+/* Accessing VGA indexed registers */
+static inline u8 in_idx(u16 port, u8 index)
+{
+	outb(index, port);
+	return inb(port+1);
+}
+
+static inline void out_idx(u8 v, u16 port, u8 index)
+{
+	outw(index+(v << 8), port);
+}
+
+/* Writes a value to an indexed port and then reads the port again */
+static inline u8 tst_idx(u8 v, u16 port, u8 index)
+{
+	out_idx(port, index, v);
+	return in_idx(port, index);
+}
+
+/* Get the I/O port of the VGA CRTC */
+u16 vga_crtc(void);		/* video-vga.c */
+
+#endif /* BOOT_VIDEO_H */
diff --git a/arch/i386/boot/voyager.c b/arch/i386/boot/voyager.c
new file mode 100644
index 0000000..9221614
--- /dev/null
+++ b/arch/i386/boot/voyager.c
@@ -0,0 +1,46 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/voyager.c
+ *
+ * Get the Voyager config information
+ */
+
+#include "boot.h"
+
+#ifdef CONFIG_X86_VOYAGER
+
+int query_voyager(void)
+{
+	u8 err;
+	u16 es, di;
+	/* Abuse the apm_bios_info area for this */
+	u8 *data_ptr = (u8 *)&boot_params.apm_bios_info;
+
+	data_ptr[0] = 0xff;	/* Flag on config not found(?) */
+
+	asm("pushw %%es ; "
+	    "int $0x15 ; "
+	    "setc %0 ; "
+	    "movw %%es, %1 ; "
+	    "popw %%es"
+	    : "=qm" (err), "=rm" (es), "=D" (di)
+	    : "a" (0xffc0));
+
+	if (err)
+		return -1;	/* Not Voyager */
+
+	set_fs(es);
+	copy_from_fs(data_ptr, di, 7);	/* Table is 7 bytes apparently */
+	return 0;
+}
+
+#endif /* CONFIG_X86_VOYAGER */
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 9da8441..1a3a221 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-git3
-# Tue May  1 07:30:51 2007
+# Linux kernel version: 2.6.22-rc2
+# Mon May 21 13:23:44 2007
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -14,6 +14,7 @@
 CONFIG_X86=y
 CONFIG_MMU=y
 CONFIG_ZONE_DMA=y
+CONFIG_QUICKLIST=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_GENERIC_BUG=y
@@ -45,6 +46,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
@@ -64,14 +66,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -165,7 +172,7 @@
 CONFIG_X86_USE_PPRO_CHECKSUM=y
 CONFIG_X86_TSC=y
 CONFIG_X86_CMOV=y
-CONFIG_X86_MINIMUM_CPU_MODEL=4
+CONFIG_X86_MINIMUM_CPU_FAMILY=4
 CONFIG_HPET_TIMER=y
 CONFIG_HPET_EMULATE_RTC=y
 CONFIG_NR_CPUS=32
@@ -211,6 +218,7 @@
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
 CONFIG_ZONE_DMA_FLAG=1
+CONFIG_NR_QUICK=1
 # CONFIG_HIGHPTE is not set
 # CONFIG_MATH_EMULATION is not set
 CONFIG_MTRR=y
@@ -237,7 +245,7 @@
 CONFIG_PM=y
 CONFIG_PM_LEGACY=y
 # CONFIG_PM_DEBUG is not set
-CONFIG_PM_SYSFS_DEPRECATED=y
+# CONFIG_PM_SYSFS_DEPRECATED is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
@@ -277,7 +285,7 @@
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
 
 #
 # CPUFreq processor drivers
@@ -315,9 +323,10 @@
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
-# CONFIG_HT_IRQ is not set
+CONFIG_HT_IRQ=y
 CONFIG_ISA_DMA_API=y
 # CONFIG_ISA is not set
 # CONFIG_MCA is not set
@@ -328,10 +337,6 @@
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -377,7 +382,7 @@
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
-# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -396,7 +401,7 @@
 # CONFIG_INET6_TUNNEL is not set
 CONFIG_INET6_XFRM_MODE_TRANSPORT=y
 CONFIG_INET6_XFRM_MODE_TUNNEL=y
-# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_INET6_XFRM_MODE_BEET=y
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_SIT=y
 # CONFIG_IPV6_TUNNEL is not set
@@ -450,7 +455,9 @@
 #
 # CONFIG_CFG80211 is not set
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -513,14 +520,12 @@
 # Misc devices
 #
 # CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_SONY_LAPTOP is not set
 # CONFIG_THINKPAD_ACPI is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -537,6 +542,7 @@
 # CONFIG_BLK_DEV_IDESCSI is not set
 CONFIG_BLK_DEV_IDEACPI=y
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -546,6 +552,7 @@
 # CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
@@ -600,9 +607,8 @@
 CONFIG_BLK_DEV_SD=y
 # CONFIG_CHR_DEV_ST is not set
 # CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
 
 #
@@ -612,6 +618,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -640,7 +647,6 @@
 CONFIG_SCSI_AIC79XX=y
 CONFIG_AIC79XX_CMDS_PER_DEVICE=32
 CONFIG_AIC79XX_RESET_DELAY_MS=4000
-# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
 # CONFIG_AIC79XX_DEBUG_ENABLE is not set
 CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
@@ -662,7 +668,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_QLA_ISCSI is not set
@@ -673,79 +678,12 @@
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-CONFIG_ATA=y
-# CONFIG_ATA_NONSTANDARD is not set
-CONFIG_SATA_AHCI=y
-CONFIG_SATA_SVW=y
-CONFIG_ATA_PIIX=y
-# CONFIG_SATA_MV is not set
-CONFIG_SATA_NV=y
-# CONFIG_PDC_ADMA is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-CONFIG_SATA_SIL=y
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-CONFIG_SATA_VIA=y
-# CONFIG_SATA_VITESSE is not set
-# CONFIG_SATA_INIC162X is not set
-CONFIG_SATA_ACPI=y
-# CONFIG_PATA_ALI is not set
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CS5520 is not set
-# CONFIG_PATA_CS5530 is not set
-# CONFIG_PATA_CS5535 is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_ATA_GENERIC is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NS87410 is not set
-# CONFIG_PATA_OPTI is not set
-# CONFIG_PATA_OPTIDMA is not set
-# CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RZ1000 is not set
-# CONFIG_PATA_SC1200 is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
 #
-CONFIG_MD=y
-# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_DEBUG is not set
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
-# CONFIG_DM_MULTIPATH is not set
+# CONFIG_MD is not set
 
 #
 # Fusion MPT device support
@@ -760,6 +698,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 CONFIG_IEEE1394=y
 
 #
@@ -790,11 +729,7 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -810,10 +745,6 @@
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -824,9 +755,7 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
-CONFIG_NET_VENDOR_3COM=y
-CONFIG_VORTEX=y
-# CONFIG_TYPHOON is not set
+# CONFIG_NET_VENDOR_3COM is not set
 
 #
 # Tulip family network device support
@@ -867,10 +796,7 @@
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -890,16 +816,14 @@
 CONFIG_BNX2=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
 
 #
 # Token Ring devices
@@ -913,8 +837,14 @@
 # CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -967,9 +897,17 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -1019,10 +957,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_INTEL=y
@@ -1031,7 +965,6 @@
 CONFIG_HW_RANDOM_VIA=y
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_SONYPI is not set
@@ -1056,17 +989,14 @@
 CONFIG_HPET=y
 # CONFIG_HPET_RTC_IRQ is not set
 CONFIG_HPET_MMAP=y
-# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_HANGCHECK_TIMER=y
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
 # CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -1079,12 +1009,7 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
 # Multifunction device drivers
@@ -1095,17 +1020,20 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 # CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -1114,7 +1042,7 @@
 CONFIG_VGA_CONSOLE=y
 CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=128
-CONFIG_VIDEO_SELECT=y
+# CONFIG_VIDEO_SELECT is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -1131,14 +1059,10 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
-CONFIG_OBSOLETE_OSS=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_ES1371 is not set
-CONFIG_SOUND_ICH=y
+# CONFIG_OSS_OBSOLETE is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 
 #
@@ -1217,37 +1141,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1291,10 +1188,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1339,10 +1232,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
 # Virtualization
 #
 # CONFIG_KVM is not set
@@ -1383,7 +1272,6 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 # CONFIG_FUSE_FS is not set
-CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1411,7 +1299,7 @@
 CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1453,6 +1341,7 @@
 CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1529,17 +1418,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_UNUSED_SYMBOLS=y
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
-CONFIG_TIMER_STATS=y
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1556,6 +1444,7 @@
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
@@ -1586,12 +1475,14 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 280898b..a574cd2 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -621,8 +621,6 @@
 static int __init acpi_parse_hpet(struct acpi_table_header *table)
 {
 	struct acpi_table_hpet *hpet_tbl;
-	struct resource *hpet_res;
-	resource_size_t res_start;
 
 	hpet_tbl = (struct acpi_table_hpet *)table;
 	if (!hpet_tbl) {
@@ -636,29 +634,10 @@
 		return -1;
 	}
 
-#define HPET_RESOURCE_NAME_SIZE 9
-	hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
-	if (hpet_res) {
-		memset(hpet_res, 0, sizeof(*hpet_res));
-		hpet_res->name = (void *)&hpet_res[1];
-		hpet_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-		snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE,
-			 "HPET %u", hpet_tbl->sequence);
-		hpet_res->end = (1 * 1024) - 1;
-	}
-
 	hpet_address = hpet_tbl->address.address;
 	printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
 	       hpet_tbl->id, hpet_address);
 
-	res_start = hpet_address;
-
-	if (hpet_res) {
-		hpet_res->start = res_start;
-		hpet_res->end += res_start;
-		insert_resource(&iomem_resource, hpet_res);
-	}
-
 	return 0;
 }
 #else
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
index b781b38..a2295a3 100644
--- a/arch/i386/kernel/acpi/wakeup.S
+++ b/arch/i386/kernel/acpi/wakeup.S
@@ -230,6 +230,7 @@
 #
 ENTRY(acpi_copy_wakeup_routine)
 
+	pushl	%ebx
 	sgdt	saved_gdt
 	sidt	saved_idt
 	sldt	saved_ldt
@@ -263,6 +264,7 @@
 	movl	%edx, video_flags - wakeup_start (%eax)
 	movl	$0x12345678, real_magic - wakeup_start (%eax)
 	movl	$0x12345678, saved_magic
+	popl	%ebx
 	ret
 
 save_registers:
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 4112afe..47001d5 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -222,6 +222,7 @@
 #include <linux/capability.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
+#include <linux/freezer.h>
 #include <linux/smp.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
@@ -2311,7 +2312,6 @@
 		remove_proc_entry("apm", NULL);
 		return err;
 	}
-	kapmd_task->flags |= PF_NOFREEZE;
 	wake_up_process(kapmd_task);
 
 	if (num_online_cpus() > 1 && !smp ) {
diff --git a/arch/i386/kernel/cpu/Makefile b/arch/i386/kernel/cpu/Makefile
index 74f27a4..0b6a855 100644
--- a/arch/i386/kernel/cpu/Makefile
+++ b/arch/i386/kernel/cpu/Makefile
@@ -8,7 +8,7 @@
 obj-y	+=	cyrix.o
 obj-y	+=	centaur.o
 obj-y	+=	transmeta.o
-obj-y	+=	intel.o intel_cacheinfo.o
+obj-y	+=	intel.o intel_cacheinfo.o addon_cpuid_features.o
 obj-y	+=	rise.o
 obj-y	+=	nexgen.o
 obj-y	+=	umc.o
diff --git a/arch/i386/kernel/cpu/addon_cpuid_features.c b/arch/i386/kernel/cpu/addon_cpuid_features.c
new file mode 100644
index 0000000..3e91d3ee
--- /dev/null
+++ b/arch/i386/kernel/cpu/addon_cpuid_features.c
@@ -0,0 +1,50 @@
+
+/*
+ *	Routines to indentify additional cpu features that are scattered in
+ *	cpuid space.
+ */
+
+#include <linux/cpu.h>
+
+#include <asm/processor.h>
+
+struct cpuid_bit {
+	u16 feature;
+	u8 reg;
+	u8 bit;
+	u32 level;
+};
+
+enum cpuid_regs {
+	CR_EAX = 0,
+	CR_ECX,
+	CR_EDX,
+	CR_EBX
+};
+
+void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
+{
+	u32 max_level;
+	u32 regs[4];
+	const struct cpuid_bit *cb;
+
+	static const struct cpuid_bit cpuid_bits[] = {
+		{ X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
+		{ 0, 0, 0, 0 }
+	};
+
+	for (cb = cpuid_bits; cb->feature; cb++) {
+
+		/* Verify that the level is valid */
+		max_level = cpuid_eax(cb->level & 0xffff0000);
+		if (max_level < cb->level ||
+		    max_level > (cb->level | 0xffff))
+			continue;
+
+		cpuid(cb->level, &regs[CR_EAX], &regs[CR_EBX],
+			&regs[CR_ECX], &regs[CR_EDX]);
+
+		if (regs[cb->reg] & (1 << cb->bit))
+			set_bit(cb->feature, c->x86_capability);
+	}
+}
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 4fec702..6f47eee 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -280,6 +280,10 @@
 
 	if (c->x86 == 0x10 && !force_mwait)
 		clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
+
+	/* K6s reports MCEs but don't actually have all the MSRs */
+	if (c->x86 < 6)
+		clear_bit(X86_FEATURE_MCE, c->x86_capability);
 }
 
 static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 794d593..e5419a9 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -353,6 +353,8 @@
 			if ( xlvl >= 0x80000004 )
 				get_model_name(c); /* Default name */
 		}
+
+		init_scattered_cpuid_features(c);
 	}
 
 	early_intel_workaround(c);
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index e912aae..094118b 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -90,10 +90,17 @@
 	  If in doubt, say N.
 
 config X86_POWERNOW_K8_ACPI
-	bool
-	depends on X86_POWERNOW_K8 && ACPI_PROCESSOR
-	depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
+	bool "ACPI Support"
+	select ACPI_PROCESSOR
+	depends on X86_POWERNOW_K8
 	default y
+	help
+	  This provides access to the K8s Processor Performance States via ACPI.
+	  This driver is probably required for CPUFreq to work with multi-socket and
+	  SMP systems.  It is not required on at least some single-socket yet
+	  multi-core systems, even if SMP is enabled.
+
+	  It is safe to say Y here.
 
 config X86_GX_SUSPMOD
 	tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
@@ -109,7 +116,7 @@
 config X86_SPEEDSTEP_CENTRINO
 	tristate "Intel Enhanced SpeedStep"
 	select CPU_FREQ_TABLE
-	select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI)
+	select X86_SPEEDSTEP_CENTRINO_TABLE
 	help
 	  This adds the CPUFreq driver for Enhanced SpeedStep enabled
 	  mobile CPUs.  This means Intel Pentium M (Centrino) CPUs. However,
@@ -121,20 +128,6 @@
 
 	  If in doubt, say N.
 
-config X86_SPEEDSTEP_CENTRINO_ACPI
-	bool "Use ACPI tables to decode valid frequency/voltage (deprecated)"
-	depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR
-	depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m)
-	help
-	  This is deprecated and this functionality is now merged into
-	  acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
-	  speedstep_centrino.
-	  Use primarily the information provided in the BIOS ACPI tables
-	  to determine valid CPU frequency and voltage pairings. It is
-	  required for the driver to work on non-Banias CPUs.
-
-	  If in doubt, say Y.
-
 config X86_SPEEDSTEP_CENTRINO_TABLE
 	bool "Built-in tables for Banias CPUs"
 	depends on X86_SPEEDSTEP_CENTRINO
@@ -230,7 +223,7 @@
 config X86_ACPI_CPUFREQ_PROC_INTF
 	bool "/proc/acpi/processor/../performance interface (deprecated)"
 	depends on PROC_FS
-	depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
+	depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
 	help
 	  This enables the deprecated /proc/acpi/processor/../performance
 	  interface. While it is helpful for debugging, the generic,
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 10baa35..18c8b67 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -167,11 +167,13 @@
 
 static void do_drv_write(struct drv_cmd *cmd)
 {
-	u32 h = 0;
+	u32 lo, hi;
 
 	switch (cmd->type) {
 	case SYSTEM_INTEL_MSR_CAPABLE:
-		wrmsr(cmd->addr.msr.reg, cmd->val, h);
+		rdmsr(cmd->addr.msr.reg, lo, hi);
+		lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE);
+		wrmsr(cmd->addr.msr.reg, lo, hi);
 		break;
 	case SYSTEM_IO_CAPABLE:
 		acpi_os_write_port((acpi_io_address)cmd->addr.io.port,
@@ -372,7 +374,6 @@
 	struct cpufreq_freqs freqs;
 	cpumask_t online_policy_cpus;
 	struct drv_cmd cmd;
-	unsigned int msr;
 	unsigned int next_state = 0; /* Index into freq_table */
 	unsigned int next_perf_state = 0; /* Index into perf table */
 	unsigned int i;
@@ -417,11 +418,7 @@
 	case SYSTEM_INTEL_MSR_CAPABLE:
 		cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
 		cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
-		msr =
-		    (u32) perf->states[next_perf_state].
-		    control & INTEL_MSR_RANGE;
-		cmd.val = get_cur_val(online_policy_cpus);
-		cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr;
+		cmd.val = (u32) perf->states[next_perf_state].control;
 		break;
 	case SYSTEM_IO_CAPABLE:
 		cmd.type = SYSTEM_IO_CAPABLE;
diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
index 0d49d73..66acd50 100644
--- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -391,8 +391,6 @@
  */
 static unsigned int nforce2_detect_chipset(void)
 {
-	u8 revision;
-
 	nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
 					PCI_DEVICE_ID_NVIDIA_NFORCE2,
 					PCI_ANY_ID, PCI_ANY_ID, NULL);
@@ -400,10 +398,8 @@
 	if (nforce2_chipset_dev == NULL)
 		return -ENODEV;
 
-	pci_read_config_byte(nforce2_chipset_dev, PCI_REVISION_ID, &revision);
-
 	printk(KERN_INFO "cpufreq: Detected nForce2 chipset revision %X\n",
-	       revision);
+	       nforce2_chipset_dev->revision);
 	printk(KERN_INFO
 	       "cpufreq: FSB changing is maybe unstable and can lead to crashes and data loss.\n");
 
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
index 6667e9c..1941445 100644
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
@@ -115,7 +115,6 @@
 	u8 pci_suscfg;
 	u8 pci_pmer1;
 	u8 pci_pmer2;
-	u8 pci_rev;
 	struct pci_dev *cs55x0;
 };
 
@@ -276,7 +275,7 @@
 			pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */
 			pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1);
 
-			if (gx_params->pci_rev < 0x10) {   /* CS5530(rev 1.2, 1.3) */
+			if (gx_params->cs55x0->revision < 0x10) {   /* CS5530(rev 1.2, 1.3) */
 				suscfg = gx_params->pci_suscfg | SUSMOD;
 			} else {                           /* CS5530A,B.. */
 				suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE;
@@ -471,7 +470,6 @@
 	pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2));
 	pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration));
 	pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration));
-	pci_read_config_byte(params->cs55x0, PCI_REVISION_ID, &params->pci_rev);
 
 	if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
 		kfree(params);
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index a3df9c0..ef8f0bc 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,6 +29,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/delay.h>
 
 #include <asm/msr.h>
 #include <asm/timex.h>
@@ -55,7 +56,6 @@
 /* Flags */
 #define USE_ACPI_C3		(1 << 1)
 #define USE_NORTHBRIDGE		(1 << 2)
-#define USE_VT8235		(1 << 3)
 
 static int cpu_model;
 static unsigned int numscales=16;
@@ -63,22 +63,19 @@
 
 static const struct mV_pos *vrm_mV_table;
 static const unsigned char *mV_vrm_table;
-struct f_msr {
-	u8 vrm;
-	u8 pos;
-};
-static struct f_msr f_msr_table[32];
 
 static unsigned int highest_speed, lowest_speed; /* kHz */
 static unsigned int minmult, maxmult;
 static int can_scale_voltage;
 static struct acpi_processor *pr = NULL;
 static struct acpi_processor_cx *cx = NULL;
+static u32 acpi_regs_addr;
 static u8 longhaul_flags;
-static u8 longhaul_pos;
+static unsigned int longhaul_index;
 
 /* Module parameters */
 static int scale_voltage;
+static int disable_acpi_c3;
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
 
@@ -144,7 +141,7 @@
 	rdmsrl(MSR_VIA_BCR2, bcr2.val);
 	/* Enable software clock multiplier */
 	bcr2.bits.ESOFTBF = 1;
-	bcr2.bits.CLOCKMUL = clock_ratio_index;
+	bcr2.bits.CLOCKMUL = clock_ratio_index & 0xff;
 
 	/* Sync to timer tick */
 	safe_halt();
@@ -163,14 +160,12 @@
 
 /* For processor with Longhaul MSR */
 
-static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
+static void do_powersaver(int cx_address, unsigned int clock_ratio_index,
+			  unsigned int dir)
 {
 	union msr_longhaul longhaul;
-	u8 dest_pos;
 	u32 t;
 
-	dest_pos = f_msr_table[clock_ratio_index].pos;
-
 	rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 	/* Setup new frequency */
 	longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
@@ -178,11 +173,11 @@
 	longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
 	/* Setup new voltage */
 	if (can_scale_voltage)
-		longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
+		longhaul.bits.SoftVID = (clock_ratio_index >> 8) & 0x1f;
 	/* Sync to timer tick */
 	safe_halt();
 	/* Raise voltage if necessary */
-	if (can_scale_voltage && longhaul_pos < dest_pos) {
+	if (can_scale_voltage && dir) {
 		longhaul.bits.EnableSoftVID = 1;
 		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 		/* Change voltage */
@@ -199,7 +194,6 @@
 		}
 		longhaul.bits.EnableSoftVID = 0;
 		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul_pos = dest_pos;
 	}
 
 	/* Change frequency on next halt or sleep */
@@ -220,7 +214,7 @@
 	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 
 	/* Reduce voltage if necessary */
-	if (can_scale_voltage && longhaul_pos > dest_pos) {
+	if (can_scale_voltage && !dir) {
 		longhaul.bits.EnableSoftVID = 1;
 		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 		/* Change voltage */
@@ -237,7 +231,6 @@
 		}
 		longhaul.bits.EnableSoftVID = 0;
 		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul_pos = dest_pos;
 	}
 }
 
@@ -248,25 +241,28 @@
  * Sets a new clock ratio.
  */
 
-static void longhaul_setstate(unsigned int clock_ratio_index)
+static void longhaul_setstate(unsigned int table_index)
 {
+	unsigned int clock_ratio_index;
 	int speed, mult;
 	struct cpufreq_freqs freqs;
-	static unsigned int old_ratio=-1;
 	unsigned long flags;
 	unsigned int pic1_mask, pic2_mask;
+	u16 bm_status = 0;
+	u32 bm_timeout = 1000;
+	unsigned int dir = 0;
 
-	if (old_ratio == clock_ratio_index)
-		return;
-	old_ratio = clock_ratio_index;
-
-	mult = clock_ratio[clock_ratio_index];
+	clock_ratio_index = longhaul_table[table_index].index;
+	/* Safety precautions */
+	mult = clock_ratio[clock_ratio_index & 0x1f];
 	if (mult == -1)
 		return;
-
 	speed = calc_speed(mult);
 	if ((speed > highest_speed) || (speed < lowest_speed))
 		return;
+	/* Voltage transition before frequency transition? */
+	if (can_scale_voltage && longhaul_index < table_index)
+		dir = 1;
 
 	freqs.old = calc_speed(longhaul_get_cpu_mult());
 	freqs.new = speed;
@@ -285,11 +281,24 @@
 	outb(0xFF,0xA1);	/* Overkill */
 	outb(0xFE,0x21);	/* TMR0 only */
 
+	/* Wait while PCI bus is busy. */
+	if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE
+	    || ((pr != NULL) && pr->flags.bm_control))) {
+		bm_status = inw(acpi_regs_addr);
+		bm_status &= 1 << 4;
+		while (bm_status && bm_timeout) {
+			outw(1 << 4, acpi_regs_addr);
+			bm_timeout--;
+			bm_status = inw(acpi_regs_addr);
+			bm_status &= 1 << 4;
+		}
+	}
+
 	if (longhaul_flags & USE_NORTHBRIDGE) {
 		/* Disable AGP and PCI arbiters */
 		outb(3, 0x22);
 	} else if ((pr != NULL) && pr->flags.bm_control) {
- 		/* Disable bus master arbitration */
+		/* Disable bus master arbitration */
 		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
 	}
 	switch (longhaul_version) {
@@ -314,9 +323,9 @@
 		if (longhaul_flags & USE_ACPI_C3) {
 			/* Don't allow wakeup */
 			acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
-			do_powersaver(cx->address, clock_ratio_index);
+			do_powersaver(cx->address, clock_ratio_index, dir);
 		} else {
-			do_powersaver(0, clock_ratio_index);
+			do_powersaver(0, clock_ratio_index, dir);
 		}
 		break;
 	}
@@ -336,6 +345,9 @@
 
 	freqs.new = calc_speed(longhaul_get_cpu_mult());
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	if (!bm_timeout)
+		printk(KERN_INFO PFX "Warning: Timeout while waiting for idle PCI bus.\n");
 }
 
 /*
@@ -369,7 +381,8 @@
 
 static int __init longhaul_get_ranges(void)
 {
-	unsigned int j, k = 0;
+	unsigned int i, j, k = 0;
+	unsigned int ratio;
 	int mult;
 
 	/* Get current frequency */
@@ -423,8 +436,7 @@
 	if(!longhaul_table)
 		return -ENOMEM;
 
-	for (j=0; j < numscales; j++) {
-		unsigned int ratio;
+	for (j = 0; j < numscales; j++) {
 		ratio = clock_ratio[j];
 		if (ratio == -1)
 			continue;
@@ -434,13 +446,41 @@
 		longhaul_table[k].index	= j;
 		k++;
 	}
-
-	longhaul_table[k].frequency = CPUFREQ_TABLE_END;
-	if (!k) {
-		kfree (longhaul_table);
-		return -EINVAL;
+	if (k <= 1) {
+		kfree(longhaul_table);
+		return -ENODEV;
+	}
+	/* Sort */
+	for (j = 0; j < k - 1; j++) {
+		unsigned int min_f, min_i;
+		min_f = longhaul_table[j].frequency;
+		min_i = j;
+		for (i = j + 1; i < k; i++) {
+			if (longhaul_table[i].frequency < min_f) {
+				min_f = longhaul_table[i].frequency;
+				min_i = i;
+			}
+		}
+		if (min_i != j) {
+			unsigned int temp;
+			temp = longhaul_table[j].frequency;
+			longhaul_table[j].frequency = longhaul_table[min_i].frequency;
+			longhaul_table[min_i].frequency = temp;
+			temp = longhaul_table[j].index;
+			longhaul_table[j].index = longhaul_table[min_i].index;
+			longhaul_table[min_i].index = temp;
+		}
 	}
 
+	longhaul_table[k].frequency = CPUFREQ_TABLE_END;
+
+	/* Find index we are running on */
+	for (j = 0; j < k; j++) {
+		if (clock_ratio[longhaul_table[j].index & 0x1f] == mult) {
+			longhaul_index = j;
+			break;
+		}
+	}
 	return 0;
 }
 
@@ -448,7 +488,7 @@
 static void __init longhaul_setup_voltagescaling(void)
 {
 	union msr_longhaul longhaul;
-	struct mV_pos minvid, maxvid;
+	struct mV_pos minvid, maxvid, vid;
 	unsigned int j, speed, pos, kHz_step, numvscales;
 	int min_vid_speed;
 
@@ -459,11 +499,11 @@
 	}
 
 	if (!longhaul.bits.VRMRev) {
-		printk (KERN_INFO PFX "VRM 8.5\n");
+		printk(KERN_INFO PFX "VRM 8.5\n");
 		vrm_mV_table = &vrm85_mV[0];
 		mV_vrm_table = &mV_vrm85[0];
 	} else {
-		printk (KERN_INFO PFX "Mobile VRM\n");
+		printk(KERN_INFO PFX "Mobile VRM\n");
 		if (cpu_model < CPU_NEHEMIAH)
 			return;
 		vrm_mV_table = &mobilevrm_mV[0];
@@ -523,7 +563,6 @@
 	/* Calculate kHz for one voltage step */
 	kHz_step = (highest_speed - min_vid_speed) / numvscales;
 
-
 	j = 0;
 	while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
 		speed = longhaul_table[j].frequency;
@@ -531,15 +570,14 @@
 			pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
 		else
 			pos = minvid.pos;
-		f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
-		f_msr_table[longhaul_table[j].index].pos = pos;
+		longhaul_table[j].index |= mV_vrm_table[pos] << 8;
+		vid = vrm_mV_table[mV_vrm_table[pos]];
+		printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", speed, j, vid.mV);
 		j++;
 	}
 
-	longhaul_pos = maxvid.pos;
 	can_scale_voltage = 1;
-	printk(KERN_INFO PFX "Voltage scaling enabled. "
-		"Use of \"conservative\" governor is highly recommended.\n");
+	printk(KERN_INFO PFX "Voltage scaling enabled.\n");
 }
 
 
@@ -553,15 +591,44 @@
 			    unsigned int target_freq, unsigned int relation)
 {
 	unsigned int table_index = 0;
-	unsigned int new_clock_ratio = 0;
+	unsigned int i;
+	unsigned int dir = 0;
+	u8 vid, current_vid;
 
 	if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
 		return -EINVAL;
 
-	new_clock_ratio = longhaul_table[table_index].index & 0xFF;
+	/* Don't set same frequency again */
+	if (longhaul_index == table_index)
+		return 0;
 
-	longhaul_setstate(new_clock_ratio);
-
+	if (!can_scale_voltage)
+		longhaul_setstate(table_index);
+	else {
+		/* On test system voltage transitions exceeding single
+		 * step up or down were turning motherboard off. Both
+		 * "ondemand" and "userspace" are unsafe. C7 is doing
+		 * this in hardware, C3 is old and we need to do this
+		 * in software. */
+		i = longhaul_index;
+		current_vid = (longhaul_table[longhaul_index].index >> 8) & 0x1f;
+		if (table_index > longhaul_index)
+			dir = 1;
+		while (i != table_index) {
+			vid = (longhaul_table[i].index >> 8) & 0x1f;
+			if (vid != current_vid) {
+				longhaul_setstate(i);
+				current_vid = vid;
+				msleep(200);
+			}
+			if (dir)
+				i++;
+			else
+				i--;
+		}
+		longhaul_setstate(table_index);
+	}
+	longhaul_index = table_index;
 	return 0;
 }
 
@@ -590,11 +657,10 @@
 static int enable_arbiter_disable(void)
 {
 	struct pci_dev *dev;
-	int status;
+	int status = 1;
 	int reg;
 	u8 pci_cmd;
 
-	status = 1;
 	/* Find PLE133 host bridge */
 	reg = 0x78;
 	dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
@@ -627,13 +693,17 @@
 	return 0;
 }
 
-static int longhaul_setup_vt8235(void)
+static int longhaul_setup_southbridge(void)
 {
 	struct pci_dev *dev;
 	u8 pci_cmd;
 
 	/* Find VT8235 southbridge */
 	dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
+	if (dev == NULL)
+	/* Find VT8237 southbridge */
+		dev = pci_get_device(PCI_VENDOR_ID_VIA,
+				     PCI_DEVICE_ID_VIA_8237, NULL);
 	if (dev != NULL) {
 		/* Set transition time to max */
 		pci_read_config_byte(dev, 0xec, &pci_cmd);
@@ -645,6 +715,14 @@
 		pci_read_config_byte(dev, 0xe5, &pci_cmd);
 		pci_cmd |= 1 << 7;
 		pci_write_config_byte(dev, 0xe5, pci_cmd);
+		/* Get address of ACPI registers block*/
+		pci_read_config_byte(dev, 0x81, &pci_cmd);
+		if (pci_cmd & 1 << 7) {
+			pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
+			acpi_regs_addr &= 0xff00;
+			printk(KERN_INFO PFX "ACPI I/O at 0x%x\n", acpi_regs_addr);
+		}
+
 		pci_dev_put(dev);
 		return 1;
 	}
@@ -657,7 +735,6 @@
 	char *cpuname=NULL;
 	int ret;
 	u32 lo, hi;
-	int vt8235_present;
 
 	/* Check what we have on this motherboard */
 	switch (c->x86_model) {
@@ -755,7 +832,7 @@
 	};
 
 	/* Doesn't hurt */
-	vt8235_present = longhaul_setup_vt8235();
+	longhaul_setup_southbridge();
 
 	/* Find ACPI data for processor */
 	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
@@ -765,35 +842,29 @@
 	/* Check ACPI support for C3 state */
 	if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
 		cx = &pr->power.states[ACPI_STATE_C3];
-		if (cx->address > 0 && cx->latency <= 1000) {
+		if (cx->address > 0 && cx->latency <= 1000)
 			longhaul_flags |= USE_ACPI_C3;
-			goto print_support_type;
-		}
 	}
+	/* Disable if it isn't working */
+	if (disable_acpi_c3)
+		longhaul_flags &= ~USE_ACPI_C3;
 	/* Check if northbridge is friendly */
-	if (enable_arbiter_disable()) {
+	if (enable_arbiter_disable())
 		longhaul_flags |= USE_NORTHBRIDGE;
-		goto print_support_type;
-	}
-	/* Use VT8235 southbridge if present */
-	if (longhaul_version == TYPE_POWERSAVER && vt8235_present) {
-		longhaul_flags |= USE_VT8235;
-		goto print_support_type;
-	}
+
 	/* Check ACPI support for bus master arbiter disable */
-	if ((pr == NULL) || !(pr->flags.bm_control)) {
+	if (!(longhaul_flags & USE_ACPI_C3
+	     || longhaul_flags & USE_NORTHBRIDGE)
+	    && ((pr == NULL) || !(pr->flags.bm_control))) {
 		printk(KERN_ERR PFX
 			"No ACPI support. Unsupported northbridge.\n");
 		return -ENODEV;
 	}
 
-print_support_type:
 	if (longhaul_flags & USE_NORTHBRIDGE)
-		printk (KERN_INFO PFX "Using northbridge support.\n");
-	else if (longhaul_flags & USE_VT8235)
-		printk (KERN_INFO PFX "Using VT8235 support.\n");
-	else
-		printk (KERN_INFO PFX "Using ACPI support.\n");
+		printk(KERN_INFO PFX "Using northbridge support.\n");
+	if (longhaul_flags & USE_ACPI_C3)
+		printk(KERN_INFO PFX "Using ACPI support.\n");
 
 	ret = longhaul_get_ranges();
 	if (ret != 0)
@@ -885,6 +956,9 @@
 	kfree(longhaul_table);
 }
 
+module_param (disable_acpi_c3, int, 0644);
+MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
+
 module_param (scale_voltage, int, 0644);
 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
 
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h
index 102548f..4fcc320 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.h
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h
@@ -180,7 +180,7 @@
 
 	-1,  /* 0000 -> RESERVED (10.0x) */
 	110, /* 0001 -> 11.0x */
-	120, /* 0010 -> 12.0x */
+	-1, /* 0010 -> 12.0x */
 	-1,  /* 0011 -> RESERVED (9.0x)*/
 	105, /* 0100 -> 10.5x */
 	115, /* 0101 -> 11.5x */
@@ -237,7 +237,7 @@
 
 static const int __initdata  nehemiah_clock_ratio[32] = {
 	100, /* 0000 -> 10.0x */
-	160, /* 0001 -> 16.0x */
+	-1, /* 0001 -> 16.0x */
 	40,  /* 0010 ->  4.0x */
 	90,  /* 0011 ->  9.0x */
 	95,  /* 0100 ->  9.5x */
@@ -252,10 +252,10 @@
 	75,  /* 1101 ->  7.5x */
 	85,  /* 1110 ->  8.5x */
 	120, /* 1111 -> 12.0x */
-	100, /* 0000 -> 10.0x */
+	-1, /* 0000 -> 10.0x */
 	110, /* 0001 -> 11.0x */
-	120, /* 0010 -> 12.0x */
-	90,  /* 0011 ->  9.0x */
+	-1, /* 0010 -> 12.0x */
+	-1,  /* 0011 ->  9.0x */
 	105, /* 0100 -> 10.5x */
 	115, /* 0101 -> 11.5x */
 	125, /* 0110 -> 12.5x */
@@ -267,7 +267,7 @@
 	145, /* 1100 -> 14.5x */
 	155, /* 1101 -> 15.5x */
 	-1,  /* 1110 -> RESERVED (13.0x) */
-	120, /* 1111 -> 12.0x */
+	-1, /* 1111 -> 12.0x */
 };
 
 static const int __initdata nehemiah_eblcr[32] = {
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 4ade55c..34ed53a 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -599,14 +599,17 @@
 	for (j = 0; j < data->numps; j++) {
 		if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
 			if (cpu_family == CPU_HW_PSTATE) {
-			printk(KERN_INFO PFX "   %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8,
-				(data->powernow_table[j].index & 0xff0000) >> 16,
-				data->powernow_table[j].frequency/1000);
+				printk(KERN_INFO PFX "   %d : fid 0x%x did 0x%x (%d MHz)\n",
+					j,
+					(data->powernow_table[j].index & 0xff00) >> 8,
+					(data->powernow_table[j].index & 0xff0000) >> 16,
+					data->powernow_table[j].frequency/1000);
 			} else {
-			printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
-				data->powernow_table[j].index & 0xff,
-				data->powernow_table[j].frequency/1000,
-				data->powernow_table[j].index >> 8);
+				printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x\n",
+					j,
+					data->powernow_table[j].index & 0xff,
+					data->powernow_table[j].frequency/1000,
+					data->powernow_table[j].index >> 8);
 			}
 		}
 	}
@@ -1086,7 +1089,7 @@
 
 	if (cpu_family == CPU_HW_PSTATE)
 		dprintk("targ: curr fid 0x%x, did 0x%x\n",
-			data->currfid, data->currvid);
+			data->currfid, data->currdid);
 	else {
 		dprintk("targ: curr fid 0x%x, vid 0x%x\n",
 		data->currfid, data->currvid);
@@ -1322,16 +1325,22 @@
 static int __cpuinit powernowk8_init(void)
 {
 	unsigned int i, supported_cpus = 0;
+	unsigned int booted_cores = 1;
 
 	for_each_online_cpu(i) {
 		if (check_supported_cpu(i))
 			supported_cpus++;
 	}
 
+#ifdef CONFIG_SMP
+	booted_cores = cpu_data[0].booted_cores;
+#endif
+
 	if (supported_cpus == num_online_cpus()) {
 		printk(KERN_INFO PFX "Found %d %s "
-			"processors (" VERSION ")\n", supported_cpus,
-			boot_cpu_data.x86_model_id);
+			"processors (%d cpu cores) (" VERSION ")\n",
+			supported_cpus/booted_cores,
+			boot_cpu_data.x86_model_id, supported_cpus);
 		return cpufreq_register_driver(&cpufreq_amd64_driver);
 	}
 
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 35489fd..6c5dc2c 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -21,12 +21,6 @@
 #include <linux/delay.h>
 #include <linux/compiler.h>
 
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-#include <linux/acpi.h>
-#include <linux/dmi.h>
-#include <acpi/processor.h>
-#endif
-
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
@@ -257,9 +251,7 @@
 		/* Matched a non-match */
 		dprintk("no table support for CPU model \"%s\"\n",
 		       cpu->x86_model_id);
-#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-		dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
-#endif
+		dprintk("try using the acpi-cpufreq driver\n");
 		return -ENOENT;
 	}
 
@@ -346,213 +338,6 @@
 }
 
 
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-
-static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
-
-/*
- * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States
- * library
- *
- * Before doing the actual init, we need to do _PSD related setup whenever
- * supported by the BIOS. These are handled by this early_init routine.
- */
-static int centrino_cpu_early_init_acpi(void)
-{
-	unsigned int	i, j;
-	struct acpi_processor_performance	*data;
-
-	for_each_possible_cpu(i) {
-		data = kzalloc(sizeof(struct acpi_processor_performance), 
-				GFP_KERNEL);
-		if (!data) {
-			for_each_possible_cpu(j) {
-				kfree(acpi_perf_data[j]);
-				acpi_perf_data[j] = NULL;
-			}
-			return (-ENOMEM);
-		}
-		acpi_perf_data[i] = data;
-	}
-
-	acpi_processor_preregister_performance(acpi_perf_data);
-	return 0;
-}
-
-
-#ifdef CONFIG_SMP
-/*
- * Some BIOSes do SW_ANY coordination internally, either set it up in hw
- * or do it in BIOS firmware and won't inform about it to OS. If not
- * detected, this has a side effect of making CPU run at a different speed
- * than OS intended it to run at. Detect it and handle it cleanly.
- */
-static int bios_with_sw_any_bug;
-static int sw_any_bug_found(struct dmi_system_id *d)
-{
-	bios_with_sw_any_bug = 1;
-	return 0;
-}
-
-static struct dmi_system_id sw_any_bug_dmi_table[] = {
-	{
-		.callback = sw_any_bug_found,
-		.ident = "Supermicro Server X6DLP",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
-			DMI_MATCH(DMI_BIOS_VERSION, "080010"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
-		},
-	},
-	{ }
-};
-#endif
-
-/*
- * centrino_cpu_init_acpi - register with ACPI P-States library
- *
- * Register with the ACPI P-States library (part of drivers/acpi/processor.c)
- * in order to determine correct frequency and voltage pairings by reading
- * the _PSS of the ACPI DSDT or SSDT tables.
- */
-static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
-{
-	unsigned long			cur_freq;
-	int				result = 0, i;
-	unsigned int			cpu = policy->cpu;
-	struct acpi_processor_performance	*p;
-
-	p = acpi_perf_data[cpu];
-
-	/* register with ACPI core */
-	if (acpi_processor_register_performance(p, cpu)) {
-		dprintk(PFX "obtaining ACPI data failed\n");
-		return -EIO;
-	}
-
-	policy->shared_type = p->shared_type;
-	/*
-	 * Will let policy->cpus know about dependency only when software 
-	 * coordination is required.
-	 */
-	if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
-	    policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
-		policy->cpus = p->shared_cpu_map;
-	}
-
-#ifdef CONFIG_SMP
-	dmi_check_system(sw_any_bug_dmi_table);
-	if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
-		policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
-		policy->cpus = cpu_core_map[cpu];
-	}
-#endif
-
-	/* verify the acpi_data */
-	if (p->state_count <= 1) {
-		dprintk("No P-States\n");
-		result = -ENODEV;
-		goto err_unreg;
-	}
-
-	if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
-	    (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
-		dprintk("Invalid control/status registers (%x - %x)\n",
-			p->control_register.space_id, p->status_register.space_id);
-		result = -EIO;
-		goto err_unreg;
-	}
-
-	for (i=0; i<p->state_count; i++) {
-		if ((p->states[i].control & INTEL_MSR_RANGE) !=
-		    (p->states[i].status & INTEL_MSR_RANGE)) {
-			dprintk("Different MSR bits in control (%llu) and status (%llu)\n",
-				p->states[i].control, p->states[i].status);
-			result = -EINVAL;
-			goto err_unreg;
-		}
-
-		if (!p->states[i].core_frequency) {
-			dprintk("Zero core frequency for state %u\n", i);
-			result = -EINVAL;
-			goto err_unreg;
-		}
-
-		if (p->states[i].core_frequency > p->states[0].core_frequency) {
-			dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i,
-				p->states[i].core_frequency, p->states[0].core_frequency);
-			p->states[i].core_frequency = 0;
-			continue;
-		}
-	}
-
-	centrino_model[cpu] = kzalloc(sizeof(struct cpu_model), GFP_KERNEL);
-	if (!centrino_model[cpu]) {
-		result = -ENOMEM;
-		goto err_unreg;
-	}
-
-	centrino_model[cpu]->model_name=NULL;
-	centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000;
-	centrino_model[cpu]->op_points =  kmalloc(sizeof(struct cpufreq_frequency_table) *
-					     (p->state_count + 1), GFP_KERNEL);
-        if (!centrino_model[cpu]->op_points) {
-                result = -ENOMEM;
-                goto err_kfree;
-        }
-
-        for (i=0; i<p->state_count; i++) {
-		centrino_model[cpu]->op_points[i].index = p->states[i].control & INTEL_MSR_RANGE;
-		centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000;
-		dprintk("adding state %i with frequency %u and control value %04x\n", 
-			i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
-	}
-	centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END;
-
-	cur_freq = get_cur_freq(cpu);
-
-	for (i=0; i<p->state_count; i++) {
-		if (!p->states[i].core_frequency) {
-			dprintk("skipping state %u\n", i);
-			centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
-			continue;
-		}
-		
-		if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) !=
-		    (centrino_model[cpu]->op_points[i].frequency)) {
-			dprintk("Invalid encoded frequency (%u vs. %u)\n",
-				extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0),
-				centrino_model[cpu]->op_points[i].frequency);
-			result = -EINVAL;
-			goto err_kfree_all;
-		}
-
-		if (cur_freq == centrino_model[cpu]->op_points[i].frequency)
-			p->state = i;
-	}
-
-	/* notify BIOS that we exist */
-	acpi_processor_notify_smm(THIS_MODULE);
-	printk("speedstep-centrino with X86_SPEEDSTEP_CENTRINO_ACPI "
-	       "config is deprecated.\n "
-	       "Use X86_ACPI_CPUFREQ (acpi-cpufreq) instead.\n" );
-
-	return 0;
-
- err_kfree_all:
-	kfree(centrino_model[cpu]->op_points);
- err_kfree:
-	kfree(centrino_model[cpu]);
- err_unreg:
-	acpi_processor_unregister_performance(p, cpu);
-	dprintk(PFX "invalid ACPI data\n");
-	return (result);
-}
-#else
-static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; }
-static inline int centrino_cpu_early_init_acpi(void) { return 0; }
-#endif
-
 static int centrino_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
@@ -568,27 +353,25 @@
 	if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
 		centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
 
-	if (centrino_cpu_init_acpi(policy)) {
-		if (policy->cpu != 0)
-			return -ENODEV;
+	if (policy->cpu != 0)
+		return -ENODEV;
 
-		for (i = 0; i < N_IDS; i++)
-			if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
-				break;
+	for (i = 0; i < N_IDS; i++)
+		if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
+			break;
 
-		if (i != N_IDS)
-			centrino_cpu[policy->cpu] = &cpu_ids[i];
+	if (i != N_IDS)
+		centrino_cpu[policy->cpu] = &cpu_ids[i];
 
-		if (!centrino_cpu[policy->cpu]) {
-			dprintk("found unsupported CPU with "
-			"Enhanced SpeedStep: send /proc/cpuinfo to "
-			MAINTAINER "\n");
-			return -ENODEV;
-		}
+	if (!centrino_cpu[policy->cpu]) {
+		dprintk("found unsupported CPU with "
+		"Enhanced SpeedStep: send /proc/cpuinfo to "
+		MAINTAINER "\n");
+		return -ENODEV;
+	}
 
-		if (centrino_cpu_init_table(policy)) {
-			return -ENODEV;
-		}
+	if (centrino_cpu_init_table(policy)) {
+		return -ENODEV;
 	}
 
 	/* Check to see if Enhanced SpeedStep is enabled, and try to
@@ -634,20 +417,6 @@
 
 	cpufreq_frequency_table_put_attr(cpu);
 
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-	if (!centrino_model[cpu]->model_name) {
-		static struct acpi_processor_performance *p;
-
-		if (acpi_perf_data[cpu]) {
-			p = acpi_perf_data[cpu];
-			dprintk("unregistering and freeing ACPI data\n");
-			acpi_processor_unregister_performance(p, cpu);
-			kfree(centrino_model[cpu]->op_points);
-			kfree(centrino_model[cpu]);
-		}
-	}
-#endif
-
 	centrino_model[cpu] = NULL;
 
 	return 0;
@@ -849,25 +618,12 @@
 	if (!cpu_has(cpu, X86_FEATURE_EST))
 		return -ENODEV;
 
-	centrino_cpu_early_init_acpi();
-
 	return cpufreq_register_driver(&centrino_driver);
 }
 
 static void __exit centrino_exit(void)
 {
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-	unsigned int j;
-#endif
-	
 	cpufreq_unregister_driver(&centrino_driver);
-
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-	for_each_possible_cpu(j) {
-		kfree(acpi_perf_data[j]);
-		acpi_perf_data[j] = NULL;
-	}
-#endif
 }
 
 MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>");
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
index b425cd3d1..a5b2346 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
@@ -24,6 +24,7 @@
 #include <linux/cpufreq.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 
 #include "speedstep-lib.h"
 
@@ -204,7 +205,6 @@
 		 * host brige. Abort on these systems.
 		 */
 		static struct pci_dev *hostbridge;
-		u8 rev = 0;
 
 		hostbridge  = pci_get_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82815_MC,
@@ -215,8 +215,7 @@
 		if (!hostbridge)
 			return 2; /* 2-M */
 
-		pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
-		if (rev < 5) {
+		if (hostbridge->revision < 5) {
 			dprintk("hostbridge does not support speedstep\n");
 			speedstep_chipset_dev = NULL;
 			pci_dev_put(hostbridge);
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index 0b8411a..e88d2fb 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -7,6 +7,7 @@
 #include <asm/processor.h>
 #include <asm/timer.h>
 #include <asm/pci-direct.h>
+#include <asm/tsc.h>
 
 #include "cpu.h"
 
diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c
index f9fa414..eef63e3 100644
--- a/arch/i386/kernel/cpu/mcheck/k7.c
+++ b/arch/i386/kernel/cpu/mcheck/k7.c
@@ -72,12 +72,12 @@
 	u32 l, h;
 	int i;
 
-	machine_check_vector = k7_machine_check;
-	wmb();
-
 	if (!cpu_has(c, X86_FEATURE_MCE))
 		return;
 
+	machine_check_vector = k7_machine_check;
+	wmb();
+
 	printk (KERN_INFO "Intel machine check architecture supported.\n");
 	rdmsr (MSR_IA32_MCG_CAP, l, h);
 	if (l & (1<<8))	/* Control register present ? */
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c
index 7ba7c3a..1203dc5 100644
--- a/arch/i386/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c
@@ -134,19 +134,21 @@
 	int err;
 
 	sys_dev = get_cpu_sysdev(cpu);
-	mutex_lock(&therm_cpu_lock);
 	switch (action) {
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
+		mutex_lock(&therm_cpu_lock);
 		err = thermal_throttle_add_dev(sys_dev);
+		mutex_unlock(&therm_cpu_lock);
 		WARN_ON(err);
 		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
+		mutex_lock(&therm_cpu_lock);
 		thermal_throttle_remove_dev(sys_dev);
+		mutex_unlock(&therm_cpu_lock);
 		break;
 	}
-	mutex_unlock(&therm_cpu_lock);
 	return NOTIFY_OK;
 }
 
diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c
index 0737a59..1001f1e 100644
--- a/arch/i386/kernel/cpu/mtrr/cyrix.c
+++ b/arch/i386/kernel/cpu/mtrr/cyrix.c
@@ -136,7 +136,7 @@
 	/*  Save value of CR4 and clear Page Global Enable (bit 7)  */
 	if ( cpu_has_pge ) {
 		cr4 = read_cr4();
-		write_cr4(cr4 & (unsigned char) ~(1 << 7));
+		write_cr4(cr4 & ~X86_CR4_PGE);
 	}
 
 	/*  Disable and flush caches. Note that wbinvd flushes the TLBs as
@@ -233,12 +233,12 @@
 	mtrr_type type;
 } arr_state_t;
 
-static arr_state_t arr_state[8] __devinitdata = {
+static arr_state_t arr_state[8] = {
 	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
 	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
 };
 
-static unsigned char ccr_state[7] __devinitdata = { 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char ccr_state[7] = { 0, 0, 0, 0, 0, 0, 0 };
 
 static void cyrix_set_all(void)
 {
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index c4ebb51..f6e4694 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -42,7 +42,7 @@
 module_param_named(show, mtrr_show, bool, 0);
 
 /*  Get the MSR pair relating to a var range  */
-static void __init
+static void
 get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
 {
 	rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
@@ -65,10 +65,11 @@
 
 void mtrr_save_fixed_ranges(void *info)
 {
-	get_fixed_ranges(mtrr_state.fixed_ranges);
+	if (cpu_has_mtrr)
+		get_fixed_ranges(mtrr_state.fixed_ranges);
 }
 
-static void __cpuinit print_fixed(unsigned base, unsigned step, const mtrr_type*types)
+static void print_fixed(unsigned base, unsigned step, const mtrr_type*types)
 {
 	unsigned i;
 
@@ -469,11 +470,6 @@
 		}
 	}
 
-	if (base < 0x100) {
-		printk(KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
-		       base, size);
-		return -EINVAL;
-	}
 	/*  Check upper bits of base and last are equal and lower bits are 0
 	    for base and 1 for last  */
 	last = base + size - 1;
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index 1cf466d..75dc6d5 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -229,6 +229,8 @@
 	data.smp_size = size;
 	data.smp_type = type;
 	atomic_set(&data.count, num_booting_cpus() - 1);
+	/* make sure data.count is visible before unleashing other CPUs */
+	smp_wmb();
 	atomic_set(&data.gate,0);
 
 	/*  Start the ball rolling on other CPUs  */
@@ -242,6 +244,7 @@
 
 	/* ok, reset count and toggle gate */
 	atomic_set(&data.count, num_booting_cpus() - 1);
+	smp_wmb();
 	atomic_set(&data.gate,1);
 
 	/* do our MTRR business */
@@ -260,6 +263,7 @@
 		cpu_relax();
 
 	atomic_set(&data.count, num_booting_cpus() - 1);
+	smp_wmb();
 	atomic_set(&data.gate,0);
 
 	/*
@@ -639,7 +643,7 @@
  * initialized (i.e. before smp_init()).
  * 
  */
-void mtrr_bp_init(void)
+__init void mtrr_bp_init(void)
 {
 	init_ifs();
 
@@ -734,10 +738,13 @@
  */
 void mtrr_save_state(void)
 {
-	if (smp_processor_id() == 0)
+	int cpu = get_cpu();
+
+	if (cpu == 0)
 		mtrr_save_fixed_ranges(NULL);
 	else
 		smp_call_function_single(0, mtrr_save_fixed_ranges, NULL, 1, 1);
+	put_cpu();
 }
 
 static int __init mtrr_init_finialize(void)
diff --git a/arch/i386/kernel/cpu/mtrr/state.c b/arch/i386/kernel/cpu/mtrr/state.c
index f62ecd1..7b39a2f9 100644
--- a/arch/i386/kernel/cpu/mtrr/state.c
+++ b/arch/i386/kernel/cpu/mtrr/state.c
@@ -19,7 +19,7 @@
 		/*  Save value of CR4 and clear Page Global Enable (bit 7)  */
 		if ( cpu_has_pge ) {
 			ctxt->cr4val = read_cr4();
-			write_cr4(ctxt->cr4val & (unsigned char) ~(1 << 7));
+			write_cr4(ctxt->cr4val & ~X86_CR4_PGE);
 		}
 
 		/*  Disable and flush caches. Note that wbinvd flushes the TLBs as
diff --git a/arch/i386/kernel/cpu/perfctr-watchdog.c b/arch/i386/kernel/cpu/perfctr-watchdog.c
index 2b04c8f..4d26d51 100644
--- a/arch/i386/kernel/cpu/perfctr-watchdog.c
+++ b/arch/i386/kernel/cpu/perfctr-watchdog.c
@@ -28,7 +28,7 @@
 	void (*unreserve)(void);
 	int (*setup)(unsigned nmi_hz);
 	void (*rearm)(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz);
-	void (*stop)(void *);
+	void (*stop)(void);
 	unsigned perfctr;
 	unsigned evntsel;
 	u64 checkbit;
@@ -55,14 +55,45 @@
 /* converts an msr to an appropriate reservation bit */
 static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
 {
-	return wd_ops ? msr - wd_ops->perfctr : 0;
+	/* returns the bit offset of the performance counter register */
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_AMD:
+		return (msr - MSR_K7_PERFCTR0);
+	case X86_VENDOR_INTEL:
+		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+			return (msr - MSR_ARCH_PERFMON_PERFCTR0);
+
+		switch (boot_cpu_data.x86) {
+		case 6:
+			return (msr - MSR_P6_PERFCTR0);
+		case 15:
+			return (msr - MSR_P4_BPU_PERFCTR0);
+		}
+	}
+	return 0;
 }
 
 /* converts an msr to an appropriate reservation bit */
 /* returns the bit offset of the event selection register */
 static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
 {
-	return wd_ops ? msr - wd_ops->evntsel : 0;
+	/* returns the bit offset of the event selection register */
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_AMD:
+		return (msr - MSR_K7_EVNTSEL0);
+	case X86_VENDOR_INTEL:
+		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+			return (msr - MSR_ARCH_PERFMON_EVENTSEL0);
+
+		switch (boot_cpu_data.x86) {
+		case 6:
+			return (msr - MSR_P6_EVNTSEL0);
+		case 15:
+			return (msr - MSR_P4_BSU_ESCR0);
+		}
+	}
+	return 0;
+
 }
 
 /* checks for a bit availability (hack for oprofile) */
@@ -142,7 +173,7 @@
 	if (atomic_read(&nmi_active) <= 0)
 		return;
 
-	on_each_cpu(wd_ops->stop, NULL, 0, 1);
+	on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
 	wd_ops->unreserve();
 
 	BUG_ON(atomic_read(&nmi_active) != 0);
@@ -255,7 +286,7 @@
 	return 1;
 }
 
-static void single_msr_stop_watchdog(void *arg)
+static void single_msr_stop_watchdog(void)
 {
 	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
@@ -276,8 +307,8 @@
 
 static void single_msr_unreserve(void)
 {
-	release_evntsel_nmi(wd_ops->perfctr);
-	release_perfctr_nmi(wd_ops->evntsel);
+	release_evntsel_nmi(wd_ops->evntsel);
+	release_perfctr_nmi(wd_ops->perfctr);
 }
 
 static void single_msr_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
@@ -442,7 +473,7 @@
 	return 1;
 }
 
-static void stop_p4_watchdog(void *arg)
+static void stop_p4_watchdog(void)
 {
 	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 	wrmsr(wd->cccr_msr, 0, 0);
@@ -475,10 +506,10 @@
 {
 #ifdef CONFIG_SMP
 	if (smp_num_siblings > 1)
-		release_evntsel_nmi(MSR_P4_IQ_PERFCTR1);
+		release_perfctr_nmi(MSR_P4_IQ_PERFCTR1);
 #endif
-	release_evntsel_nmi(MSR_P4_IQ_PERFCTR0);
-	release_perfctr_nmi(MSR_P4_CRU_ESCR0);
+	release_evntsel_nmi(MSR_P4_CRU_ESCR0);
+	release_perfctr_nmi(MSR_P4_IQ_PERFCTR0);
 }
 
 static void p4_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
@@ -614,6 +645,12 @@
 		probe_nmi_watchdog();
 		if (!wd_ops)
 			return -1;
+
+		if (!wd_ops->reserve()) {
+			printk(KERN_ERR
+				"NMI watchdog: cannot reserve perfctrs\n");
+			return -1;
+		}
 	}
 
 	if (!(wd_ops->setup(nmi_hz))) {
@@ -628,7 +665,7 @@
 void lapic_watchdog_stop(void)
 {
 	if (wd_ops)
-		wd_ops->stop(NULL);
+		wd_ops->stop();
 }
 
 unsigned lapic_adjust_nmi_hz(unsigned hz)
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 89d91e6..1e31b6c 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -29,7 +29,8 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
-		NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow",
+		NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm",
+		"3dnowext", "3dnow",
 
 		/* Transmeta-defined */
 		"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -40,8 +41,9 @@
 		/* Other (Linux-defined) */
 		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
 		NULL, NULL, NULL, NULL,
-		"constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		"constant_tsc", "up", NULL, "arch_perfmon",
+		"pebs", "bts", NULL, "sync_rdtsc",
+		"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Intel-defined (#2) */
@@ -57,9 +59,16 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* AMD-defined (#2) */
-		"lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm",
-		"sse4a", "misalignsse",
-		"3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL,
+		"lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
+		"altmovcr8", "abm", "sse4a",
+		"misalignsse", "3dnowprefetch",
+		"osvw", "ibs", NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+		/* Auxiliary (Linux-defined) */
+		"ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
diff --git a/arch/i386/kernel/e820.c b/arch/i386/kernel/e820.c
index 9645bb51..fc822a4 100644
--- a/arch/i386/kernel/e820.c
+++ b/arch/i386/kernel/e820.c
@@ -734,7 +734,7 @@
 		case E820_NVS:
 				printk("(ACPI NVS)\n");
 				break;
-		default:	printk("type %lu\n", e820.map[i].type);
+		default:	printk("type %u\n", e820.map[i].type);
 				break;
 		}
 	}
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index a180802..2452c6f 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -278,7 +278,7 @@
 	struct range {
 		unsigned long start;
 		unsigned long end;
-	} prev, curr;
+	} uninitialized_var(prev), curr;
 	efi_memory_desc_t *md;
 	unsigned long start, end;
 	void *p;
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index b1f16ee..3c3c220 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -367,10 +367,6 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
-	testl $TF_MASK,PT_EFLAGS(%esp)
-	jz no_singlestep
-	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
-no_singlestep:
 					# system call tracing in operation / emulation
 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
 	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
@@ -385,6 +381,10 @@
 					# setting need_resched or sigpending
 					# between sampling and the iret
 	TRACE_IRQS_OFF
+	testl $TF_MASK,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
+	jz no_singlestep
+	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+no_singlestep:
 	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx	# current->work
 	jne syscall_exit_work
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index f74dfc4..8271466 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -168,6 +168,12 @@
 .section .init.text,"ax",@progbits
 #endif
 
+	/* Do an early initialization of the fixmap area */
+	movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
+	movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax
+	addl $0x007, %eax			/* 0x007 = PRESENT+RW+USER */
+	movl %eax, 4092(%edx)
+
 #ifdef CONFIG_SMP
 ENTRY(startup_32_smp)
 	cld
@@ -507,6 +513,8 @@
 .section ".bss.page_aligned","w"
 ENTRY(swapper_pg_dir)
 	.fill 1024,4,0
+ENTRY(swapper_pg_pmd)
+	.fill 1024,4,0
 ENTRY(empty_zero_page)
 	.fill 4096,1,0
 
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 7f8b7af..21db8f5 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -667,6 +667,7 @@
 		set_pending_irq(i, cpumask_of_cpu(0));
 	}
 
+	set_freezable();
 	for ( ; ; ) {
 		time_remaining = schedule_timeout_interruptible(time_remaining);
 		try_to_freeze();
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 83f825f..d865d04 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -478,7 +478,7 @@
 	return 0;
 }
 
-static void __exit microcode_dev_exit (void)
+static void microcode_dev_exit (void)
 {
 	misc_deregister(&microcode_dev);
 }
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index fba121f..03b7f55 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -295,7 +295,7 @@
 	last_irq_sums [NR_CPUS],
 	alert_counter [NR_CPUS];
 
-void touch_nmi_watchdog (void)
+void touch_nmi_watchdog(void)
 {
 	if (nmi_watchdog > 0) {
 		unsigned cpu;
@@ -304,8 +304,10 @@
 		 * Just reset the alert counters, (other CPUs might be
 		 * spinning on locks we hold):
 		 */
-		for_each_present_cpu (cpu)
-			alert_counter[cpu] = 0;
+		for_each_present_cpu(cpu) {
+			if (alert_counter[cpu])
+				alert_counter[cpu] = 0;
+		}
 	}
 
 	/*
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 30b754f..048f09b 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -12,6 +12,7 @@
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 
 struct dma_coherent_mem {
@@ -148,3 +149,29 @@
 	return mem->virt_base + (pos << PAGE_SHIFT);
 }
 EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
+
+#ifdef CONFIG_PCI
+/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+
+int forbid_dac;
+EXPORT_SYMBOL(forbid_dac);
+
+static __devinit void via_no_dac(struct pci_dev *dev)
+{
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+		printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+		forbid_dac = 1;
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+
+static int check_iommu(char *s)
+{
+	if (!strcmp(s, "usedac")) {
+		forbid_dac = -1;
+		return 1;
+	}
+	return 0;
+}
+__setup("iommu=", check_iommu);
+#endif
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 06dfa65..6c49acb 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -538,8 +538,31 @@
 	return 1;
 }
 
-static noinline void __switch_to_xtra(struct task_struct *next_p,
-				    struct tss_struct *tss)
+#ifdef CONFIG_SECCOMP
+void hard_disable_TSC(void)
+{
+	write_cr4(read_cr4() | X86_CR4_TSD);
+}
+void disable_TSC(void)
+{
+	preempt_disable();
+	if (!test_and_set_thread_flag(TIF_NOTSC))
+		/*
+		 * Must flip the CPU state synchronously with
+		 * TIF_NOTSC in the current running context.
+		 */
+		hard_disable_TSC();
+	preempt_enable();
+}
+void hard_enable_TSC(void)
+{
+	write_cr4(read_cr4() & ~X86_CR4_TSD);
+}
+#endif /* CONFIG_SECCOMP */
+
+static noinline void
+__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+		 struct tss_struct *tss)
 {
 	struct thread_struct *next;
 
@@ -555,6 +578,17 @@
 		set_debugreg(next->debugreg[7], 7);
 	}
 
+#ifdef CONFIG_SECCOMP
+	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+		/* prev and next are different */
+		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
+			hard_disable_TSC();
+		else
+			hard_enable_TSC();
+	}
+#endif
+
 	if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
 		/*
 		 * Disable the bitmap via an invalid offset. We still cache
@@ -586,33 +620,6 @@
 }
 
 /*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
-			       struct task_struct *next_p)
-{
-	struct thread_info *prev, *next;
-
-	/*
-	 * gcc should eliminate the ->thread_info dereference if
-	 * has_secure_computing returns 0 at compile time (SECCOMP=n).
-	 */
-	prev = task_thread_info(prev_p);
-	next = task_thread_info(next_p);
-
-	if (has_secure_computing(prev) || has_secure_computing(next)) {
-		/* slow path here */
-		if (has_secure_computing(prev) &&
-		    !has_secure_computing(next)) {
-			write_cr4(read_cr4() & ~X86_CR4_TSD);
-		} else if (!has_secure_computing(prev) &&
-			   has_secure_computing(next))
-			write_cr4(read_cr4() | X86_CR4_TSD);
-	}
-}
-
-/*
  *	switch_to(x,yn) should switch tasks from x to y.
  *
  * We fsave/fwait so that an exception goes off at the right time
@@ -689,11 +696,9 @@
 	/*
 	 * Now maybe handle debug registers and/or IO bitmaps
 	 */
-	if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)
-	    || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)))
-		__switch_to_xtra(next_p, tss);
-
-	disable_tsc(prev_p, next_p);
+	if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
+		     task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
+		__switch_to_xtra(prev_p, next_p, tss);
 
 	/*
 	 * Leave lazy mode, flushing any hypercalls made here.
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 0c0ceec..1c075f5 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -358,17 +358,9 @@
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp, datap);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -395,10 +387,7 @@
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-			break;
-		ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c
index 9f6ab17..6722469 100644
--- a/arch/i386/kernel/quirks.c
+++ b/arch/i386/kernel/quirks.c
@@ -20,8 +20,6 @@
 	if (rev > 0x9)
 		return;
 
-	printk(KERN_INFO "Intel E7520/7320/7525 detected.");
-
 	/* enable access to config space*/
 	pci_read_config_byte(dev, 0xf4, &config);
 	pci_write_config_byte(dev, 0xf4, config|0x2);
@@ -30,7 +28,8 @@
 	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
 
 	if (!(word & (1 << 13))) {
-		printk(KERN_INFO "Disabling irq balancing and affinity\n");
+		printk(KERN_INFO "Intel E7520/7320/7525 detected. "
+			"Disabling irq balancing and affinity\n");
 #ifdef CONFIG_IRQBALANCE
 		irqbalance_disable("");
 #endif
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 50dfc65..5513f8d 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -89,6 +89,14 @@
 }
 
 static struct dmi_system_id __initdata reboot_dmi_table[] = {
+	{	/* Handle problems with rebooting on Dell E520's */
+		.callback = set_bios_reboot,
+		.ident = "Dell E520",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
+		},
+	},
 	{	/* Handle problems with rebooting on Dell 1300's */
 		.callback = set_bios_reboot,
 		.ident = "Dell PowerEdge 1300",
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 2d78d91..03e1cce 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -5,12 +5,14 @@
  *
  * List of supported fixups:
  * geode-gx1/cs5530a - Jaya Kumar <jayalk@intworks.biz>
+ * geode-gx/lx/cs5536 - Andres Salomon <dilinger@debian.org>
  *
  */
 
 #include <asm/delay.h>
 #include <linux/pci.h>
 #include <asm/reboot_fixups.h>
+#include <asm/msr.h>
 
 static void cs5530a_warm_reset(struct pci_dev *dev)
 {
@@ -21,6 +23,16 @@
 	return;
 }
 
+static void cs5536_warm_reset(struct pci_dev *dev)
+{
+	/*
+	 * 6.6.2.12 Soft Reset (DIVIL_SOFT_RESET)
+	 * writing 1 to the LSB of this MSR causes a hard reset.
+	 */
+	wrmsrl(0x51400017, 1ULL);
+	udelay(50); /* shouldn't get here but be safe and spin a while */
+}
+
 struct device_fixup {
 	unsigned int vendor;
 	unsigned int device;
@@ -29,6 +41,7 @@
 
 static struct device_fixup fixups_table[] = {
 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
+{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset },
 };
 
 /*
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 698c24f..2d61e65 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -102,19 +102,10 @@
 /*
  * Setup options
  */
-struct drive_info_struct { char dummy[32]; } drive_info;
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \
-    defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
-EXPORT_SYMBOL(drive_info);
-#endif
 struct screen_info screen_info;
 EXPORT_SYMBOL(screen_info);
 struct apm_info apm_info;
 EXPORT_SYMBOL(apm_info);
-struct sys_desc_table_struct {
-	unsigned short length;
-	unsigned char table[0];
-};
 struct edid_info edid_info;
 EXPORT_SYMBOL_GPL(edid_info);
 struct ist_info ist_info;
@@ -134,7 +125,7 @@
 
 static char __initdata command_line[COMMAND_LINE_SIZE];
 
-unsigned char __initdata boot_params[PARAM_SIZE];
+struct boot_params __initdata boot_params;
 
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 struct edd edd;
@@ -528,7 +519,6 @@
 #endif
 
  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
- 	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
 	edid_info = EDID_INFO;
 	apm_info.bios = APM_BIOS_INFO;
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 08f07a7..0b29545 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -941,18 +941,6 @@
 }
 #endif
 
-static void smp_tune_scheduling(void)
-{
-	unsigned long cachesize;       /* kB   */
-
-	if (cpu_khz) {
-		cachesize = boot_cpu_data.x86_cache_size;
-
-		if (cachesize > 0)
-			max_cache_size = cachesize * 1024;
-	}
-}
-
 /*
  * Cycle through the processors sending APIC IPIs to boot each.
  */
@@ -981,7 +969,6 @@
 	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
 
 	current_thread_info()->cpu = 0;
-	smp_tune_scheduling();
 
 	set_cpu_sibling_map(0);
 
diff --git a/arch/i386/kernel/smpcommon.c b/arch/i386/kernel/smpcommon.c
index 1868ae1..bbfe85a 100644
--- a/arch/i386/kernel/smpcommon.c
+++ b/arch/i386/kernel/smpcommon.c
@@ -47,7 +47,7 @@
 EXPORT_SYMBOL(smp_call_function);
 
 /**
- * smp_call_function_single - Run a function on another CPU
+ * smp_call_function_single - Run a function on a specific CPU
  * @cpu: The target CPU.  Cannot be the calling CPU.
  * @func: The function to run. This must be fast and non-blocking.
  * @info: An arbitrary pointer to pass to the function.
@@ -66,9 +66,11 @@
 	int ret;
 	int me = get_cpu();
 	if (cpu == me) {
-		WARN_ON(1);
+		local_irq_disable();
+		func(info);
+		local_irq_enable();
 		put_cpu();
-		return -EBUSY;
+		return 0;
 	}
 
 	ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 90da057..18c1c28 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -390,7 +390,7 @@
 		unsigned long esp;
 		unsigned short ss;
 
-		report_bug(regs->eip);
+		report_bug(regs->eip, regs);
 
 		printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
@@ -433,6 +433,7 @@
 
 	bust_spinlocks(0);
 	die.lock_owner = -1;
+	add_taint(TAINT_DIE);
 	spin_unlock_irqrestore(&die.lock, flags);
 
 	if (!regs)
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index f64b81f..ea63a30 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -4,6 +4,7 @@
  * See comments there for proper credits.
  */
 
+#include <linux/sched.h>
 #include <linux/clocksource.h>
 #include <linux/workqueue.h>
 #include <linux/cpufreq.h>
@@ -106,8 +107,13 @@
 
 	/*
 	 * Fall back to jiffies if there's no TSC available:
+	 * ( But note that we still use it if the TSC is marked
+	 *   unstable. We do this because unlike Time Of Day,
+	 *   the scheduler clock tolerates small errors and it's
+	 *   very important for it to be as fast as the platform
+	 *   can achive it. )
 	 */
-	if (unlikely(!tsc_enabled))
+	if (unlikely(!tsc_enabled && !tsc_unstable))
 		/* No locking but a rare wrong value is not a big deal: */
 		return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
 
@@ -277,6 +283,7 @@
 
 void mark_tsc_unstable(char *reason)
 {
+	sched_clock_unstable_event();
 	if (!tsc_unstable) {
 		tsc_unstable = 1;
 		tsc_enabled = 0;
diff --git a/arch/i386/kernel/verify_cpu.S b/arch/i386/kernel/verify_cpu.S
deleted file mode 100644
index b2a9d80..0000000
--- a/arch/i386/kernel/verify_cpu.S
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Check if CPU has some minimum CPUID bits
-   This runs in 16bit mode so that the caller can still use the BIOS
-   to output errors on the screen */
-#include <asm/cpufeature.h>
-
-verify_cpu:
-	pushfl				# Save caller passed flags
-	pushl	$0			# Kill any dangerous flags
-	popfl
-
-#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4
-	pushfl
-	pop	%eax
-	orl	$(1<<18),%eax		# try setting AC
-	push	%eax
-	popfl
-	pushfl
-	popl    %eax
-	testl	$(1<<18),%eax
-	jz	bad
-#endif
-#if REQUIRED_MASK1 != 0
-	pushfl				# standard way to check for cpuid
-	popl	%eax
-	movl	%eax,%ebx
-	xorl	$0x200000,%eax
-	pushl	%eax
-	popfl
-	pushfl
-	popl	%eax
-	cmpl	%eax,%ebx
-	pushfl				# standard way to check for cpuid
-	popl	%eax
-	movl	%eax,%ebx
-	xorl	$0x200000,%eax
-	pushl	%eax
-	popfl
-	pushfl
-	popl	%eax
-	cmpl	%eax,%ebx
-	jz	bad			# REQUIRED_MASK1 != 0 requires CPUID
-
-	movl	$0x0,%eax		# See if cpuid 1 is implemented
-	cpuid
-	cmpl	$0x1,%eax
-	jb	bad			# no cpuid 1
-
-	movl    $0x1,%eax		# Does the cpu have what it takes
-	cpuid
-
-#if CONFIG_X86_MINIMUM_CPU_MODEL > 4
-#error	add proper model checking here
-#endif
-
-	andl	$REQUIRED_MASK1,%edx
-	xorl	$REQUIRED_MASK1,%edx
-	jnz	bad
-#endif /* REQUIRED_MASK1 */
-
-	popfl
-	xor	%eax,%eax
-	ret
-
-bad:
-	popfl
-	movl	$1,%eax
-	ret
diff --git a/arch/i386/kernel/vmi.c b/arch/i386/kernel/vmi.c
index c8726c4..c12720d 100644
--- a/arch/i386/kernel/vmi.c
+++ b/arch/i386/kernel/vmi.c
@@ -27,6 +27,7 @@
 #include <linux/bootmem.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
+#include <linux/sched.h>
 #include <asm/vmi.h>
 #include <asm/io.h>
 #include <asm/fixmap.h>
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 80bec66..aa87b06 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -44,7 +44,7 @@
 
   /* read-only */
   .text : AT(ADDR(.text) - LOAD_OFFSET) {
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	KPROBES_TEXT
@@ -74,7 +74,7 @@
   /* writeable */
   . = ALIGN(4096);
   .data : AT(ADDR(.data) - LOAD_OFFSET) {	/* Data */
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
 	} :data
 
diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
index 9be6cea..ab99072 100644
--- a/arch/i386/mach-es7000/es7000plat.c
+++ b/arch/i386/mach-es7000/es7000plat.c
@@ -40,6 +40,7 @@
 #include <asm/smp.h>
 #include <asm/apicdef.h>
 #include "es7000.h"
+#include <mach_mpparse.h>
 
 /*
  * ES7000 Globals
@@ -174,6 +175,53 @@
 }
 #endif
 
+/*
+ * This file also gets compiled if CONFIG_X86_GENERICARCH is set. Generic
+ * arch already has got following function definitions (asm-generic/es7000.c)
+ * hence no need to define these for that case.
+ */
+#ifndef CONFIG_X86_GENERICARCH
+void es7000_sw_apic(void);
+void __init enable_apic_mode(void)
+{
+	es7000_sw_apic();
+	return;
+}
+
+__init int mps_oem_check(struct mp_config_table *mpc, char *oem,
+		char *productid)
+{
+	if (mpc->mpc_oemptr) {
+		struct mp_config_oemtable *oem_table =
+			(struct mp_config_oemtable *)mpc->mpc_oemptr;
+		if (!strncmp(oem, "UNISYS", 6))
+			return parse_unisys_oem((char *)oem_table);
+	}
+	return 0;
+}
+#ifdef CONFIG_ACPI
+/* Hook from generic ACPI tables.c */
+int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+	unsigned long oem_addr;
+	if (!find_unisys_acpi_oem_table(&oem_addr)) {
+		if (es7000_check_dsdt())
+			return parse_unisys_oem((char *)oem_addr);
+		else {
+			setup_unisys();
+			return 1;
+		}
+	}
+	return 0;
+}
+#else
+int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+	return 0;
+}
+#endif
+#endif /* COFIG_X86_GENERICARCH */
+
 static void
 es7000_spin(int n)
 {
diff --git a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c
index e932d34..58a477b 100644
--- a/arch/i386/mach-generic/bigsmp.c
+++ b/arch/i386/mach-generic/bigsmp.c
@@ -21,7 +21,7 @@
 
 static int dmi_bigsmp; /* can be set by dmi scanners */
 
-static __init int hp_ht_bigsmp(struct dmi_system_id *d)
+static int hp_ht_bigsmp(struct dmi_system_id *d)
 {
 #ifdef CONFIG_X86_GENERICARCH
 	printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
@@ -31,7 +31,7 @@
 }
 
 
-static struct dmi_system_id __initdata bigsmp_dmi_table[] = {
+static struct dmi_system_id bigsmp_dmi_table[] = {
 	{ hp_ht_bigsmp, "HP ProLiant DL760 G2", {
 		DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
 		DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
@@ -45,7 +45,7 @@
 };
 
 
-static int __init probe_bigsmp(void)
+static int probe_bigsmp(void)
 { 
 	if (def_to_bigsmp)
         	dmi_bigsmp = 1;
diff --git a/arch/i386/mach-visws/traps.c b/arch/i386/mach-visws/traps.c
index 5199bd0..843b67a 100644
--- a/arch/i386/mach-visws/traps.c
+++ b/arch/i386/mach-visws/traps.c
@@ -23,13 +23,13 @@
 	set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
 
 	if ((li_pcia_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
-	    (li_pcia_read16(PCI_DEVICE_ID) != PCI_VENDOR_ID_SGI_LITHIUM)) {
+	    (li_pcia_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
 		printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'A');
 		panic("This machine is not SGI Visual Workstation 320/540");
 	}
 
 	if ((li_pcib_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
-	    (li_pcib_read16(PCI_DEVICE_ID) != PCI_VENDOR_ID_SGI_LITHIUM)) {
+	    (li_pcib_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
 		printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'B');
 		panic("This machine is not SGI Visual Workstation 320/540");
 	}
diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c
index ddf8fa3..1853524 100644
--- a/arch/i386/math-emu/fpu_entry.c
+++ b/arch/i386/math-emu/fpu_entry.c
@@ -754,7 +754,7 @@
     return -1;
   if ( offset )
     if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
-      return -1
+      return -1;
   RE_ENTRANT_CHECK_ON;
 
   return 1;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 29d7d61..1ecb3e4 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -458,6 +458,11 @@
 bad_area_nosemaphore:
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & 4) {
+		/*
+		 * It's possible to have interrupts off here.
+		 */
+		local_irq_enable();
+
 		/* 
 		 * Valid to do another page fault here because this one came 
 		 * from user space.
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index b22ce8d..7135946 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -799,6 +799,7 @@
 	unsigned long start = PFN_ALIGN(_text);
 	unsigned long size = PFN_ALIGN(_etext) - start;
 
+#ifndef CONFIG_KPROBES
 #ifdef CONFIG_HOTPLUG_CPU
 	/* It must still be possible to apply SMP alternatives. */
 	if (num_possible_cpus() <= 1)
@@ -808,7 +809,7 @@
 		                 size >> PAGE_SHIFT, PAGE_KERNEL_RX);
 		printk("Write protecting the kernel text: %luk\n", size >> 10);
 	}
-
+#endif
 	start += size;
 	size = (unsigned long)__end_rodata - start;
 	change_page_attr(virt_to_page(start),
diff --git a/arch/i386/mm/mmap.c b/arch/i386/mm/mmap.c
index e4730a1..552e084 100644
--- a/arch/i386/mm/mmap.c
+++ b/arch/i386/mm/mmap.c
@@ -27,6 +27,7 @@
 #include <linux/personality.h>
 #include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 
 /*
  * Top of mmap area (just below the process stack).
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index 47bd477..2eb14a7 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -68,14 +68,23 @@
 	return base;
 } 
 
-static void flush_kernel_map(void *arg)
+static void cache_flush_page(struct page *p)
 { 
-	unsigned long adr = (unsigned long)arg;
+	unsigned long adr = (unsigned long)page_address(p);
+	int i;
+	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+		asm volatile("clflush (%0)" :: "r" (adr + i));
+}
 
-	if (adr && cpu_has_clflush) {
-		int i;
-		for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
-			asm volatile("clflush (%0)" :: "r" (adr + i));
+static void flush_kernel_map(void *arg)
+{
+	struct list_head *lh = (struct list_head *)arg;
+	struct page *p;
+
+	/* High level code is not ready for clflush yet */
+	if (0 && cpu_has_clflush) {
+		list_for_each_entry (p, lh, lru)
+			cache_flush_page(p);
 	} else if (boot_cpu_data.x86_model >= 4)
 		wbinvd();
 
@@ -181,9 +190,9 @@
 	return 0;
 } 
 
-static inline void flush_map(void *adr)
+static inline void flush_map(struct list_head *l)
 {
-	on_each_cpu(flush_kernel_map, adr, 1, 1);
+	on_each_cpu(flush_kernel_map, l, 1, 1);
 }
 
 /*
@@ -225,11 +234,8 @@
 	spin_lock_irq(&cpa_lock);
 	list_replace_init(&df_list, &l);
 	spin_unlock_irq(&cpa_lock);
-	if (!cpu_has_clflush)
-		flush_map(NULL);
+	flush_map(&l);
 	list_for_each_entry_safe(pg, next, &l, lru) {
-		if (cpu_has_clflush)
-			flush_map(page_address(pg));
 		__free_page(pg);
 	}
 }
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 8e18520..11b7a51 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -131,7 +131,6 @@
 {
 	int cpu = smp_processor_id();
 	struct op_msrs * msrs = &cpu_msrs[cpu];
-	model->fill_in_addresses(msrs);
 	nmi_cpu_save_registers(msrs);
 }
 
@@ -155,7 +154,7 @@
 	size_t counters_size = sizeof(struct op_msr) * model->num_counters;
 
 	int i;
-	for_each_online_cpu(i) {
+	for_each_possible_cpu(i) {
 		cpu_msrs[i].counters = kmalloc(counters_size, GFP_KERNEL);
 		if (!cpu_msrs[i].counters) {
 			success = 0;
@@ -195,6 +194,7 @@
 static int nmi_setup(void)
 {
 	int err=0;
+	int cpu;
 
 	if (!allocate_msrs())
 		return -ENOMEM;
@@ -207,6 +207,19 @@
 	/* We need to serialize save and setup for HT because the subset
 	 * of msrs are distinct for save and setup operations
 	 */
+
+	/* Assume saved/restored counters are the same on all CPUs */
+	model->fill_in_addresses(&cpu_msrs[0]);
+	for_each_possible_cpu (cpu) {
+		if (cpu != 0) {
+			memcpy(cpu_msrs[cpu].counters, cpu_msrs[0].counters,
+				sizeof(struct op_msr) * model->num_counters);
+
+			memcpy(cpu_msrs[cpu].controls, cpu_msrs[0].controls,
+				sizeof(struct op_msr) * model->num_controls);
+		}
+
+	}
 	on_each_cpu(nmi_save_registers, NULL, 0, 1);
 	on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
 	nmi_enabled = 1;
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index b62eafb..e7306db 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -118,12 +118,9 @@
 static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
 {
 	u8 v;
-	u8 revision;
 	int where = 0x55;
 	int mask = 0x1f; /* clear bits 5, 6, 7 by default */
 
-	pci_read_config_byte(d, PCI_REVISION_ID, &revision);
-
 	if (d->device == PCI_DEVICE_ID_VIA_8367_0) {
 		/* fix pci bus latency issues resulted by NB bios error
 		   it appears on bug free^Wreduced kt266x's bios forces
@@ -133,8 +130,8 @@
 		where = 0x95; /* the memory write queue timer register is 
 				different for the KT266x's: 0x95 not 0x55 */
 	} else if (d->device == PCI_DEVICE_ID_VIA_8363_0 &&
-			(revision == VIA_8363_KL133_REVISION_ID || 
-			revision == VIA_8363_KM133_REVISION_ID)) {
+			(d->revision == VIA_8363_KL133_REVISION_ID ||
+			d->revision == VIA_8363_KM133_REVISION_ID)) {
 			mask = 0x3f; /* clear only bits 6 and 7; clearing bit 5
 					causes screen corruption on the KL133/KM133 */
 	}
@@ -142,7 +139,7 @@
 	pci_read_config_byte(d, where, &v);
 	if (v & ~mask) {
 		printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
-			d->device, revision, where, v, mask, v & mask);
+			d->device, d->revision, where, v, mask, v & mask);
 		v &= mask;
 		pci_write_config_byte(d, where, v);
 	}
@@ -436,3 +433,14 @@
 			pci_early_fixup_cyrix_5530);
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
 			pci_early_fixup_cyrix_5530);
+
+/*
+ * Siemens Nixdorf AG FSC Multiprocessor Interrupt Controller:
+ * prevent update of the BAR0, which doesn't look like a normal BAR.
+ */
+static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev)
+{
+	dev->resource[0].flags |= IORESOURCE_PCI_FIXED;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015,
+			  pci_siemens_interrupt_controller);
diff --git a/arch/i386/video/Makefile b/arch/i386/video/Makefile
new file mode 100644
index 0000000..2c447c9
--- /dev/null
+++ b/arch/i386/video/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_FB)               += fbdev.o
diff --git a/arch/i386/video/fbdev.c b/arch/i386/video/fbdev.c
new file mode 100644
index 0000000..48fb38d
--- /dev/null
+++ b/arch/i386/video/fbdev.c
@@ -0,0 +1,32 @@
+/*
+ * arch/i386/video/fbdev.c - i386 Framebuffer
+ *
+ * Copyright (C) 2007 Antonino Daplas <adaplas@gmail.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/fb.h>
+#include <linux/pci.h>
+
+int fb_is_primary_device(struct fb_info *info)
+{
+	struct device *device = info->device;
+	struct pci_dev *pci_dev = NULL;
+	struct resource *res = NULL;
+	int retval = 0;
+
+	if (device)
+		pci_dev = to_pci_dev(device);
+
+	if (pci_dev)
+		res = &pci_dev->resource[PCI_ROM_RESOURCE];
+
+	if (res && res->flags & IORESOURCE_ROM_SHADOW)
+		retval = 1;
+
+	return retval;
+}
+EXPORT_SYMBOL(fb_is_primary_device);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index de1bff6..616c96e 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -520,8 +520,10 @@
 	  here unless you are using a simulator without PCI support.
 
 config PCI_DOMAINS
-	bool
-	default PCI
+	def_bool PCI
+
+config PCI_SYSCALL
+	def_bool PCI
 
 source "drivers/pci/pcie/Kconfig"
 
@@ -580,8 +582,8 @@
 source "arch/ia64/oprofile/Kconfig"
 
 config KPROBES
-	bool "Kprobes (EXPERIMENTAL)"
-	depends on KALLSYMS && EXPERIMENTAL && MODULES
+	bool "Kprobes"
+	depends on KALLSYMS && MODULES
 	help
 	  Kprobes allows you to trap at almost any kernel address and
 	  execute a callback function.  register_kprobe() establishes
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index c1dca22..cd4adf5 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -34,6 +34,7 @@
 #include <linux/efi.h>
 #include <linux/nodemask.h>
 #include <linux/bitops.h>         /* hweight64() */
+#include <linux/crash_dump.h>
 
 #include <asm/delay.h>		/* ia64_get_itc() */
 #include <asm/io.h>
@@ -43,6 +44,8 @@
 
 #include <asm/acpi-ext.h>
 
+extern int swiotlb_late_init_with_default_size (size_t size);
+
 #define PFX "IOC: "
 
 /*
@@ -2026,11 +2029,24 @@
 	if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb"))
 		return 0;
 
+#if defined(CONFIG_IA64_GENERIC) && defined(CONFIG_CRASH_DUMP)
+	/* If we are booting a kdump kernel, the sba_iommu will
+	 * cause devices that were not shutdown properly to MCA
+	 * as soon as they are turned back on.  Our only option for
+	 * a successful kdump kernel boot is to use the swiotlb.
+	 */
+	if (elfcorehdr_addr < ELFCORE_ADDR_MAX) {
+		if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
+			panic("Unable to initialize software I/O TLB:"
+				  " Try machvec=dig boot option");
+		machvec_init("dig");
+		return 0;
+	}
+#endif
+
 	acpi_bus_register_driver(&acpi_sba_ioc_driver);
 	if (!ioc_list) {
 #ifdef CONFIG_IA64_GENERIC
-		extern int swiotlb_late_init_with_default_size (size_t size);
-
 		/*
 		 * If we didn't find something sba_iommu can claim, we
 		 * need to setup the swiotlb and switch to the dig machvec.
diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c
index 300acd9..1189d03 100644
--- a/arch/ia64/hp/sim/boot/fw-emu.c
+++ b/arch/ia64/hp/sim/boot/fw-emu.c
@@ -329,11 +329,6 @@
 	strcpy(sal_systab->product_id, "HP-simulator");
 #endif
 
-#ifdef CONFIG_IA64_SDV
-	strcpy(sal_systab->oem_id, "Intel");
-	strcpy(sal_systab->product_id, "SDV");
-#endif
-
 	/* fill in an entry point: */
 	sal_ed->type = SAL_DESC_ENTRY_POINT;
 	sal_ed->pal_proc = __pa(pal_desc[0]);
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 324ea75..ef252df 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -36,10 +36,6 @@
 #include <asm/hw_irq.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_KDB
-# include <linux/kdb.h>
-#endif
-
 #undef SIMSERIAL_DEBUG	/* define this to get some debug information */
 
 #define KEYBOARD_INTR	3	/* must match with simulator! */
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index c05bda6..6f4d3d0 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -261,7 +261,7 @@
 }
 
 static unsigned long
-elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
 {
 	unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
 
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 99b665e..06efd1f 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -304,7 +304,7 @@
 	data8 sys_ni_syscall	/* init_module */
 	data8 sys_ni_syscall	/* delete_module */
 	data8 sys_ni_syscall	/* get_kernel_syms */  /* 130 */
-	data8 sys_quotactl
+	data8 sys32_quotactl
 	data8 sys_getpgid
 	data8 sys_fchdir
 	data8 sys_ni_syscall	/* sys_bdflush */
diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c
index 4d4993a..5a216c0 100644
--- a/arch/ia64/kernel/acpi-processor.c
+++ b/arch/ia64/kernel/acpi-processor.c
@@ -44,7 +44,7 @@
 
 	buf[0] = ACPI_PDC_REVISION_ID;
 	buf[1] = 1;
-	buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
+	buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
 
 	obj->type = ACPI_TYPE_BUFFER;
 	obj->buffer.length = 12;
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index c478449..103dd8e 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -67,7 +67,8 @@
 unsigned int acpi_cpei_override;
 unsigned int acpi_cpei_phys_cpuid;
 
-const char *acpi_get_sysname(void)
+const char __init *
+acpi_get_sysname(void)
 {
 #ifdef CONFIG_IA64_GENERIC
 	unsigned long rsdp_phys;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 75ec347..73ca86d 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -28,6 +28,7 @@
 #include <linux/time.h>
 #include <linux/efi.h>
 #include <linux/kexec.h>
+#include <linux/mm.h>
 
 #include <asm/io.h>
 #include <asm/kregs.h>
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 8589e84..3f926c2 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -247,6 +247,9 @@
 .time_redo:
 	.pred.rel.mutex p8,p9,p10
 	ld4.acq r28 = [r29]	// xtime_lock.sequence. Must come first for locking purposes
+	;;
+	and r28 = ~1,r28	// Make sequence even to force retry if odd
+	;;
 (p8)	mov r2 = ar.itc		// CPU_TIMER. 36 clocks latency!!!
 	add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20
 (p9)	ld8 r2 = [r30]		// readq(ti->address). Could also have latency issues..
@@ -284,7 +287,6 @@
 (p15)	ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET
 (p7)	cmp.ne p7,p0 = r25,r3	// if cmpxchg not successful redo
 	// simulate tbit.nz.or p7,p0 = r28,0
-	and r28 = ~1,r28	// Make sequence even to force retry if odd
 	getf.sig r2 = f8
 	mf
 	add r8 = r8,r18		// Add time interpolator offset
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
index 3274850..74b1ccc 100644
--- a/arch/ia64/kernel/gate.S
+++ b/arch/ia64/kernel/gate.S
@@ -30,6 +30,7 @@
 	.previous
 #define BRL_COND_FSYS_BUBBLE_DOWN(pr)			\
 [1:](pr)brl.cond.sptk 0;				\
+	;;						\
 	.xdata4 ".data.patch.brl_fsys_bubble_down", 1b-.
 
 GLOBAL_ENTRY(__kernel_syscall_via_break)
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 1ead5ea..4b5daa3 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -57,6 +57,9 @@
  *
  * 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
  * 	      Add printing support for MCA/INIT.
+ *
+ * 2007-04-27 Russ Anderson <rja@sgi.com>
+ *	      Support multiple cpus going through OS_MCA in the same event.
  */
 #include <linux/types.h>
 #include <linux/init.h>
@@ -96,7 +99,6 @@
 #endif
 
 /* Used by mca_asm.S */
-u32				ia64_mca_serialize;
 DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
 DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
 DEFINE_PER_CPU(u64, ia64_mca_pal_pte);	    /* PTE to map PAL code */
@@ -963,11 +965,12 @@
 		goto no_mod;
 	}
 
+	if (r13 != sos->prev_IA64_KR_CURRENT) {
+		msg = "inconsistent previous current and r13";
+		goto no_mod;
+	}
+
 	if (!mca_recover_range(ms->pmsa_iip)) {
-		if (r13 != sos->prev_IA64_KR_CURRENT) {
-			msg = "inconsistent previous current and r13";
-			goto no_mod;
-		}
 		if ((r12 - r13) >= KERNEL_STACK_SIZE) {
 			msg = "inconsistent r12 and r13";
 			goto no_mod;
@@ -1187,6 +1190,13 @@
  *	further MCA logging is enabled by clearing logs.
  *	Monarch also has the duty of sending wakeup-IPIs to pull the
  *	slave processors out of rendezvous spinloop.
+ *
+ *	If multiple processors call into OS_MCA, the first will become
+ *	the monarch.  Subsequent cpus will be recorded in the mca_cpu
+ *	bitmask.  After the first monarch has processed its MCA, it
+ *	will wake up the next cpu in the mca_cpu bitmask and then go
+ *	into the rendezvous loop.  When all processors have serviced
+ *	their MCA, the last monarch frees up the rest of the processors.
  */
 void
 ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
@@ -1196,16 +1206,32 @@
 	struct task_struct *previous_current;
 	struct ia64_mca_notify_die nd =
 		{ .sos = sos, .monarch_cpu = &monarch_cpu };
+	static atomic_t mca_count;
+	static cpumask_t mca_cpu;
 
+	if (atomic_add_return(1, &mca_count) == 1) {
+		monarch_cpu = cpu;
+		sos->monarch = 1;
+	} else {
+		cpu_set(cpu, mca_cpu);
+		sos->monarch = 0;
+	}
 	mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d "
 		"monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch);
 
 	previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
-	monarch_cpu = cpu;
+
 	if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
-	ia64_wait_for_slaves(cpu, "MCA");
+	if (sos->monarch) {
+		ia64_wait_for_slaves(cpu, "MCA");
+	} else {
+		ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
+		while (cpu_isset(cpu, mca_cpu))
+			cpu_relax();	/* spin until monarch wakes us */
+		ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+        }
 
 	/* Wakeup all the processors which are spinning in the rendezvous loop.
 	 * They will leave SAL, then spin in the OS with interrupts disabled
@@ -1244,6 +1270,26 @@
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
+
+	if (atomic_dec_return(&mca_count) > 0) {
+		int i;
+
+		/* wake up the next monarch cpu,
+		 * and put this cpu in the rendez loop.
+		 */
+		ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
+		for_each_online_cpu(i) {
+			if (cpu_isset(i, mca_cpu)) {
+				monarch_cpu = i;
+				cpu_clear(i, mca_cpu);	/* wake next cpu */
+				while (monarch_cpu != -1)
+					cpu_relax();	/* spin until last cpu leaves */
+				ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+				set_curr_task(cpu, previous_current);
+				return;
+			}
+		}
+	}
 	set_curr_task(cpu, previous_current);
 	monarch_cpu = -1;
 }
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 8c9c26a..0f5965f 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -133,14 +133,6 @@
 //StartMain////////////////////////////////////////////////////////////////////
 
 ia64_os_mca_dispatch:
-	// Serialize all MCA processing
-	mov	r3=1;;
-	LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
-ia64_os_mca_spin:
-	xchg4	r4=[r2],r3;;
-	cmp.ne	p6,p0=r4,r0
-(p6)	br ia64_os_mca_spin
-
 	mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET	// use the MCA stack
 	LOAD_PHYSICAL(p0,r2,1f)			// return address
 	mov r19=1				// All MCA events are treated as monarch (for now)
@@ -291,10 +283,6 @@
 
 	mov		b0=r12			// SAL_CHECK return address
 
-	// release lock
-	LOAD_PHYSICAL(p0,r3,ia64_mca_serialize);;
-	st4.rel		[r3]=r0
-
 	br		b0
 
 //EndMain//////////////////////////////////////////////////////////////////////
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index f2d4900..3bccb06 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -40,7 +40,11 @@
 	mov	b6=loc1
 	;;
 	mov	loc1=rp
-	ssm	psr.i | psr.ic
+	ssm	psr.ic
+	;;
+	srlz.i
+	;;
+	ssm	psr.i
 	br.call.sptk.many rp=b6		// does not return ...
 	;;
 	mov	ar.pfs=loc0
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index d1c3ed9..fa40cba 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -513,7 +513,8 @@
 static void
 do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg)
 {
-	unsigned long mask, sp, nat_bits = 0, ip, ar_rnat, urbs_end, cfm;
+	unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm;
+	unsigned long uninitialized_var(ip);	/* GCC be quiet */
 	elf_greg_t *dst = arg;
 	struct pt_regs *pt;
 	char nat;
@@ -763,6 +764,9 @@
 	unsigned long ip;
 	int count = 0;
 
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
 	/*
 	 * Note: p may not be a blocked task (it could be current or
 	 * another process running on some other CPU.  Rather than
@@ -773,6 +777,8 @@
 	 */
 	unw_init_from_blocked_task(&info, p);
 	do {
+		if (p->state == TASK_RUNNING)
+			return 0;
 		if (unw_unwind(&info) < 0)
 			return 0;
 		unw_get_ip(&info, &ip);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index eaa6a24..4d9864c 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -390,10 +390,6 @@
 	if (!efi_setup_pcdp_console(cmdline))
 		earlycons++;
 #endif
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-	if (!early_serial_console_init(cmdline))
-		earlycons++;
-#endif
 
 	return (earlycons) ? 0 : -1;
 }
@@ -805,7 +801,6 @@
 get_max_cacheline_size (void)
 {
 	unsigned long line_size, max = 1;
-	unsigned int cache_size = 0;
 	u64 l, levels, unique_caches;
         pal_cache_config_info_t cci;
         s64 status;
@@ -835,8 +830,6 @@
 		line_size = 1 << cci.pcci_line_size;
 		if (line_size > max)
 			max = line_size;
-		if (cache_size < cci.pcci_cache_size)
-			cache_size = cci.pcci_cache_size;
 		if (!cci.pcci_unified) {
 			status = ia64_pal_cache_config_info(l,
 						    /* cache_type (instruction)= */ 1,
@@ -853,9 +846,6 @@
 			ia64_i_cache_stride_shift = cci.pcci_stride;
 	}
   out:
-#ifdef CONFIG_SMP
-	max_cache_size = max(max_cache_size, cache_size);
-#endif
 	if (max > ia64_max_cacheline_size)
 		ia64_max_cacheline_size = max;
 }
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 5429580..3c9d8e6 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -370,7 +370,7 @@
 {
 }
 
-static void __devinit
+static void __cpuinit
 smp_callin (void)
 {
 	int cpuid, phys_id, itc_master;
@@ -456,7 +456,7 @@
 /*
  * Activate a secondary processor.  head.S calls this.
  */
-int __devinit
+int __cpuinit
 start_secondary (void *unused)
 {
 	/* Early console may use I/O ports */
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index a06667c..3486fe7 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -18,7 +18,6 @@
 #include <linux/time.h>
 #include <linux/interrupt.h>
 #include <linux/efi.h>
-#include <linux/profile.h>
 #include <linux/timex.h>
 
 #include <asm/machvec.h>
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 15ad85d..3aeaf15 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -69,6 +69,7 @@
 
 	bust_spinlocks(0);
 	die.lock_owner = -1;
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die.lock);
 
 	if (panic_on_oops)
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index 7d3dd6c..c1bdb51 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1856,6 +1856,14 @@
 	return 0;
 }
 
+static int
+unw_valid(const struct unw_frame_info *info, unsigned long* p)
+{
+	unsigned long loc = (unsigned long)p;
+	return (loc >= info->regstk.limit && loc < info->regstk.top) ||
+	       (loc >= info->memstk.top && loc < info->memstk.limit);
+}
+
 int
 unw_unwind (struct unw_frame_info *info)
 {
@@ -1870,14 +1878,15 @@
 	prev_sp = info->sp;
 	prev_bsp = info->bsp;
 
-	/* restore the ip */
-	if (!info->rp_loc) {
+	/* validate the return IP pointer */
+	if (!unw_valid(info, info->rp_loc)) {
 		/* FIXME: should really be level 0 but it occurs too often. KAO */
 		UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
 			   __FUNCTION__, info->ip);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
+	/* restore the ip */
 	ip = info->ip = *info->rp_loc;
 	if (ip < GATE_ADDR) {
 		UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
@@ -1885,12 +1894,13 @@
 		return -1;
 	}
 
-	/* restore the cfm: */
-	if (!info->pfs_loc) {
+	/* validate the previous stack frame pointer */
+	if (!unw_valid(info, info->pfs_loc)) {
 		UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
+	/* restore the cfm: */
 	info->cfm_loc = info->pfs_loc;
 
 	/* restore the bsp: */
@@ -1992,13 +2002,16 @@
 	memset(info, 0, sizeof(*info));
 
 	rbslimit = (unsigned long) t + IA64_RBS_OFFSET;
+	stklimit = (unsigned long) t + IA64_STK_OFFSET;
+
 	rbstop   = sw->ar_bspstore;
-	if (rbstop - (unsigned long) t >= IA64_STK_OFFSET)
+	if (rbstop > stklimit || rbstop < rbslimit)
 		rbstop = rbslimit;
 
-	stklimit = (unsigned long) t + IA64_STK_OFFSET;
 	if (stktop <= rbstop)
 		stktop = rbstop;
+	if (stktop > stklimit)
+		stktop = stklimit;
 
 	info->regstk.limit = rbslimit;
 	info->regstk.top   = rbstop;
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 6923826..5a65965 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -44,7 +44,7 @@
   .text : AT(ADDR(.text) - LOAD_OFFSET)
     {
 	IVT_TEXT
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	KPROBES_TEXT
@@ -214,7 +214,12 @@
 
   data : { } :data
   .data : AT(ADDR(.data) - LOAD_OFFSET)
-	{ *(.data) *(.data1) *(.gnu.linkonce.d*) CONSTRUCTORS }
+	{
+		DATA_DATA
+		*(.data1)
+		*(.gnu.linkonce.d*)
+		CONSTRUCTORS
+	}
 
   . = ALIGN(16);	/* gp must be 16-byte aligned for exc. table */
   .got : AT(ADDR(.got) - LOAD_OFFSET)
diff --git a/arch/ia64/lib/checksum.c b/arch/ia64/lib/checksum.c
index 4411d9b..9fc9550 100644
--- a/arch/ia64/lib/checksum.c
+++ b/arch/ia64/lib/checksum.c
@@ -60,6 +60,7 @@
 	result = (result & 0xffffffff) + (result >> 32);
 	return (__force __wsum)result;
 }
+EXPORT_SYMBOL(csum_tcpudp_nofold);
 
 extern unsigned long do_csum (const unsigned char *, long);
 
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index 1346b7f..d22861c 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -15,6 +15,7 @@
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/log2.h>
 #include <asm/mman.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
@@ -182,7 +183,7 @@
 		tr_pages = 0x15557000UL;
 
 	size = memparse(str, &str);
-	if (*str || (size & (size-1)) || !(tr_pages & size) ||
+	if (*str || !is_power_of_2(size) || !(tr_pages & size) ||
 		size <= PAGE_SIZE ||
 		size >= (1UL << PAGE_SHIFT << MAX_ORDER)) {
 		printk(KERN_WARNING "Invalid huge page size specified\n");
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index fa4e6d4..1682fc6 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -175,7 +175,7 @@
 void __devinit
 ia64_tlb_init (void)
 {
-	ia64_ptce_info_t ptce_info;
+	ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
 	unsigned long tr_pgbits;
 	long status;
 
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 3549f3b..07d0e92 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -354,10 +354,13 @@
 
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
 			&windows);
-	controller->window = kmalloc_node(sizeof(*controller->window) * windows,
-			GFP_KERNEL, controller->node);
-	if (!controller->window)
-		goto out2;
+	if (windows) {
+		controller->window =
+			kmalloc_node(sizeof(*controller->window) * windows,
+				     GFP_KERNEL, controller->node);
+		if (!controller->window)
+			goto out2;
+	}
 
 	name = kmalloc(16, GFP_KERNEL);
 	if (!name)
@@ -588,6 +591,9 @@
 pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
 		     enum pci_mmap_state mmap_state, int write_combine)
 {
+	unsigned long size = vma->vm_end - vma->vm_start;
+	pgprot_t prot;
+
 	/*
 	 * I/O space cannot be accessed via normal processor loads and
 	 * stores on this platform.
@@ -601,15 +607,24 @@
 		 */
 		return -EINVAL;
 
+	if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
+		return -EINVAL;
+
+	prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
+				    vma->vm_page_prot);
+
 	/*
-	 * Leave vm_pgoff as-is, the PCI space address is the physical
-	 * address on this platform.
+	 * If the user requested WC, the kernel uses UC or WC for this region,
+	 * and the chipset supports WC, we can use WC. Otherwise, we have to
+	 * use the same attribute the kernel uses.
 	 */
-	if (write_combine && efi_range_is_wc(vma->vm_start,
-					     vma->vm_end - vma->vm_start))
+	if (write_combine &&
+	    ((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC ||
+	     (pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) &&
+	    efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
 		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 	else
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+		vma->vm_page_prot = prot;
 
 	if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
 			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
index c6216f4..3c7178f 100644
--- a/arch/ia64/sn/kernel/io_acpi_init.c
+++ b/arch/ia64/sn/kernel/io_acpi_init.c
@@ -418,7 +418,7 @@
 	void __iomem *addr;
 	struct pcidev_info *pcidev_info = NULL;
 	struct sn_irq_info *sn_irq_info = NULL;
-	size_t size;
+	size_t image_size, size;
 
 	if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
 		panic("%s:  Failure obtaining pcidev_info for %s\n",
@@ -428,17 +428,16 @@
 	if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
 		/*
 		 * A valid ROM image exists and has been shadowed by the
-		 * PROM. Setup the pci_dev ROM resource to point to
-		 * the shadowed copy.
+		 * PROM. Setup the pci_dev ROM resource with the address
+		 * of the shadowed copy, and the actual length of the ROM image.
 		 */
-		size = dev->resource[PCI_ROM_RESOURCE].end -
-				dev->resource[PCI_ROM_RESOURCE].start;
-		addr =
-		     ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
-			     size);
+		size = pci_resource_len(dev, PCI_ROM_RESOURCE);
+		addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
+			       size);
+		image_size = pci_get_rom_size(addr, size);
 		dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
 		dev->resource[PCI_ROM_RESOURCE].end =
-						(unsigned long) addr + size;
+					(unsigned long) addr + image_size - 1;
 		dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
 	}
 	sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 6b10e5d..906b936 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -259,9 +259,23 @@
 			insert_resource(&ioport_resource, &dev->resource[idx]);
 		else
 			insert_resource(&iomem_resource, &dev->resource[idx]);
-		/* If ROM, mark as shadowed in PROM */
-		if (idx == PCI_ROM_RESOURCE)
-			dev->resource[idx].flags |= IORESOURCE_ROM_BIOS_COPY;
+		/*
+		 * If ROM, set the actual ROM image size, and mark as
+		 * shadowed in PROM.
+		 */
+		if (idx == PCI_ROM_RESOURCE) {
+			size_t image_size;
+			void __iomem *rom;
+
+			rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
+				      size + 1);
+			image_size = pci_get_rom_size(rom, size + 1);
+			dev->resource[PCI_ROM_RESOURCE].end =
+				dev->resource[PCI_ROM_RESOURCE].start +
+				image_size - 1;
+			dev->resource[PCI_ROM_RESOURCE].flags |=
+						 IORESOURCE_ROM_BIOS_COPY;
+		}
 	}
 	/* Create a pci_window in the pci_controller struct for
 	 * each device resource.
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index a574fcd..684b1c9 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -194,7 +194,7 @@
 }
 
 extern int platform_intr_list[];
-static int __initdata shub_1_1_found;
+static int __cpuinitdata shub_1_1_found;
 
 /*
  * sn_check_for_wars
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 6da98547..df8d5be 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -750,9 +750,10 @@
 			goto error;
 		} else
 		if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
+			int cpuobj_index = 0;
+
 			memset(p, 0, a.sz);
 			for (i = 0; i < nobj; i++) {
-				int cpuobj_index = 0;
 				if (!SN_HWPERF_IS_NODE(objs + i))
 					continue;
 				node = sn_hwperf_obj_to_cnode(objs + i);
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 493380b..5a289e4 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -369,7 +369,7 @@
 
 static int is_fpga_tio(int nasid, int *bt)
 {
-	u16 ioboard_type;
+	u16 uninitialized_var(ioboard_type);	/* GCC be quiet */
 	s64 rc;
 
 	rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
index b772543..54e8973 100644
--- a/arch/ia64/sn/kernel/xp_nofault.S
+++ b/arch/ia64/sn/kernel/xp_nofault.S
@@ -21,7 +21,8 @@
 xp_nofault_PIOR:
 	mov	r8=r0			// Stage a success return value
 	ld8.acq	r9=[r32];;		// PIO Read the specified register
-	adds	r9=1,r9			// Add to force a consume
+	adds	r9=1,r9;;		// Add to force consumption
+	or	r9=r9,r9;;		// Or to force consumption
 	br.ret.sptk.many b0;;		// Return success
 
 	.global xp_error_PIOR
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 04a82560..42485ad 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -15,6 +15,7 @@
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/sn_sal.h>
+#include <asm/sn/pic.h>
 #include <asm/sn/sn2/sn_hwperf.h>
 #include "xtalk/xwidgetdev.h"
 #include "xtalk/hubdev.h"
@@ -79,7 +80,7 @@
 u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus)
 {
 	s64 rc;
-	u16 ioboard;
+	u16 uninitialized_var(ioboard);		/* GCC be quiet */
 	nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
 
 	rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard);
@@ -130,9 +131,9 @@
 	}
 
 	memcpy(soft, prom_bussoft, sizeof(struct pcibus_info));
-	soft->pbi_buscommon.bs_base =
-	    (((u64) soft->pbi_buscommon.
-	      bs_base << 4) >> 4) | __IA64_UNCACHED_OFFSET;
+	soft->pbi_buscommon.bs_base = (unsigned long)
+		ioremap(REGION_OFFSET(soft->pbi_buscommon.bs_base),
+			sizeof(struct pic));
 
 	spin_lock_init(&soft->pbi_lock);
 
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index b9bedbd..d798dd4 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -610,7 +610,9 @@
 		return NULL;
 
 	memcpy(tioca_common, prom_bussoft, sizeof(struct tioca_common));
-	tioca_common->ca_common.bs_base |= __IA64_UNCACHED_OFFSET;
+	tioca_common->ca_common.bs_base = (unsigned long)
+		ioremap(REGION_OFFSET(tioca_common->ca_common.bs_base),
+			sizeof(struct tioca_common));
 
 	/* init kernel-private area */
 
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index f4c0b96..84b72b2 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -1002,7 +1002,9 @@
 		return NULL;
 
 	memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common));
-	tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET;
+	tioce_common->ce_pcibus.bs_base = (unsigned long)
+		ioremap(REGION_OFFSET(tioce_common->ce_pcibus.bs_base),
+			sizeof(struct tioce_common));
 
 	tioce_kern = tioce_kern_init(tioce_common);
 	if (tioce_kern == NULL) {
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index c3bb8a75..8ccf3e4 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -31,6 +31,9 @@
 config NO_IOPORT
 	def_bool y
 
+config NO_DMA
+	def_bool y
+
 source "init/Kconfig"
 
 
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 5f02b31..57a92ef 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -595,7 +595,6 @@
 static int
 do_ptrace(long request, struct task_struct *child, long addr, long data)
 {
-	unsigned long tmp;
 	int ret;
 
 	switch (request) {
@@ -604,11 +603,7 @@
 	 */
 	case PTRACE_PEEKTEXT:
 	case PTRACE_PEEKDATA:
-		ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (ret == sizeof(tmp))
-			ret = put_user(tmp,(unsigned long __user *) data);
-		else
-			ret = -EIO;
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
 
 	/*
@@ -624,15 +619,9 @@
 	 */
 	case PTRACE_POKETEXT:
 	case PTRACE_POKEDATA:
-		ret = access_process_vm(child, addr, &data, sizeof(data), 1);
-		if (ret == sizeof(data)) {
-			ret = 0;
-			if (request == PTRACE_POKETEXT) {
-				invalidate_cache();
-			}
-		} else {
-			ret = -EIO;
-		}
+		ret = generic_ptrace_pokedata(child, addr, data);
+		if (ret == 0 && request == PTRACE_POKETEXT)
+			invalidate_cache();
 		break;
 
 	/*
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index 6c73bca3..4e2d5b9 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -27,7 +27,7 @@
   _text = .;			/* Text and read-only data */
   .boot : { *(.boot) } = 0
   .text : {
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	*(.fixup)
@@ -50,7 +50,7 @@
   .data : {			/* Data */
 	*(.spu)
 	*(.spi)
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
 	}
 
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index b8536c7c..a86e2e9 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -355,8 +355,9 @@
 	  adventurous.
 
 config SINGLE_MEMORY_CHUNK
-	bool "Use one physical chunk of memory only"
-	depends on ADVANCED && !SUN3
+	bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
+	default y if SUN3
+	select NEED_MULTIPLE_NODES
 	help
 	  Ignore all but the first contiguous chunk of physical memory for VM
 	  purposes.  This will save a few bytes kernel size and may speed up
@@ -377,6 +378,14 @@
 	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
 	  this problem.
 
+config ARCH_DISCONTIGMEM_ENABLE
+	def_bool !SINGLE_MEMORY_CHUNK
+
+config NODES_SHIFT
+	int
+	default "3"
+	depends on !SINGLE_MEMORY_CHUNK
+
 source "mm/Kconfig"
 
 endmenu
@@ -409,9 +418,6 @@
 	help
 	  Say Y here to report ST-RAM usage statistics in /proc/stram.
 
-config ATARI_KBD_CORE
-	bool
-
 config HEARTBEAT
 	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
 	default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index c20831a..aa383a5 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -19,6 +19,7 @@
 # override top level makefile
 AS += -m68020
 LDFLAGS := -m m68kelf
+LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
 ifneq ($(COMPILE_ARCH),$(ARCH))
 	# prefix for cross-compiling binaries
 	CROSS_COMPILE = m68k-linux-gnu-
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 0b68ab8..a806208 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -9,13 +9,12 @@
 endif
 extra-y	+= vmlinux.lds
 
-obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o \
+obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
 	   sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o
 
 devres-y = ../../../kernel/irq/devres.o
 
 obj-$(CONFIG_PCI)	+= bios32.o
-obj-$(CONFIG_MODULES)	+= module.o
 obj-y$(CONFIG_MMU_SUN3) += dma.o	# no, it's not a typo
 
 EXTRA_AFLAGS := -traditional
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c
index 3b1a2ff..774862b 100644
--- a/arch/m68k/kernel/module.c
+++ b/arch/m68k/kernel/module.c
@@ -1,3 +1,9 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
 #include <linux/moduleloader.h>
 #include <linux/elf.h>
 #include <linux/vmalloc.h>
@@ -11,6 +17,8 @@
 #define DEBUGP(fmt...)
 #endif
 
+#ifdef CONFIG_MODULES
+
 void *module_alloc(unsigned long size)
 {
 	if (size == 0)
@@ -118,11 +126,32 @@
 
 int module_finalize(const Elf_Ehdr *hdr,
 		    const Elf_Shdr *sechdrs,
-		    struct module *me)
+		    struct module *mod)
 {
+	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
+
 	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
 }
+
+#endif /* CONFIG_MODULES */
+
+void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+		  struct m68k_fixup_info *end)
+{
+	struct m68k_fixup_info *fixup;
+
+	for (fixup = start; fixup < end; fixup++) {
+		switch (fixup->type) {
+		case m68k_fixup_memoffset:
+			*(u32 *)fixup->addr = m68k_memoffset;
+			break;
+		case m68k_fixup_vnode_shift:
+			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
+			break;
+		}
+	}
+}
diff --git a/arch/m68k/kernel/module.lds b/arch/m68k/kernel/module.lds
new file mode 100644
index 0000000..fda94fa
--- /dev/null
+++ b/arch/m68k/kernel/module.lds
@@ -0,0 +1,7 @@
+SECTIONS {
+	.m68k_fixup : {
+		__start_fixup = .;
+		*(.m68k_fixup)
+		__stop_fixup = .;
+	}
+}
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index cdba9fd..2cf0690 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -128,10 +128,7 @@
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT:	/* read word at location addr. */
 	case PTRACE_PEEKDATA:
-		i = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (i != sizeof(tmp))
-			goto out_eio;
-		ret = put_user(tmp, (unsigned long *)data);
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
 
 	/* read the word at location addr in the USER area. */
@@ -160,8 +157,7 @@
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT:	/* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
-			goto out_eio;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR:	/* write the word at location addr in the USER area */
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 6103193..215c7bd 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -60,14 +60,12 @@
 int m68k_num_memory;
 int m68k_realnum_memory;
 EXPORT_SYMBOL(m68k_realnum_memory);
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
 unsigned long m68k_memoffset;
 EXPORT_SYMBOL(m68k_memoffset);
-#endif
 struct mem_info m68k_memory[NUM_MEMINFO];
 EXPORT_SYMBOL(m68k_memory);
 
-static struct mem_info m68k_ramdisk;
+struct mem_info m68k_ramdisk;
 
 static char m68k_command_line[CL_SIZE];
 
@@ -208,9 +206,6 @@
 void __init setup_arch(char **cmdline_p)
 {
 	extern int _etext, _edata, _end;
-#ifndef CONFIG_SUN3
-	unsigned long endmem, startmem;
-#endif
 	int i;
 
 	/* The bootinfo is located right after the kernel bss */
@@ -320,30 +315,16 @@
 		panic("No configuration setup");
 	}
 
+	paging_init();
+
 #ifndef CONFIG_SUN3
-	startmem= m68k_memory[0].addr;
-	endmem = startmem + m68k_memory[0].size;
-	high_memory = (void *)PAGE_OFFSET;
-	for (i = 0; i < m68k_num_memory; i++) {
-		m68k_memory[i].size &= MASK_256K;
-		if (m68k_memory[i].addr < startmem)
-			startmem = m68k_memory[i].addr;
-		if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
-			endmem = m68k_memory[i].addr+m68k_memory[i].size;
-		high_memory += m68k_memory[i].size;
-	}
-
-	availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
-				      startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);
-
-	for (i = 0; i < m68k_num_memory; i++)
-		free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);
-
-	reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
-
+	for (i = 1; i < m68k_num_memory; i++)
+		free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
+				  m68k_memory[i].size);
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (m68k_ramdisk.size) {
-		reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
+		reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
+				     m68k_ramdisk.addr, m68k_ramdisk.size);
 		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
 		initrd_end = initrd_start + m68k_ramdisk.size;
 		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
@@ -362,8 +343,6 @@
 
 #endif /* !CONFIG_SUN3 */
 
-	paging_init();
-
 /* set ISA defs early as possible */
 #if defined(CONFIG_ISA) && defined(MULTI_ISA)
 #if defined(CONFIG_Q40)
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index a27a4fa..4e2752a 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -1170,6 +1170,7 @@
 	console_verbose();
 	printk("%s: %08x\n",str,nr);
 	show_registers(fp);
+	add_taint(TAINT_DIE);
 	do_exit(SIGSEGV);
 }
 
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index 437b4f8..40f02b1 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -11,7 +11,7 @@
   . = 0x1000;
   _text = .;			/* Text and read-only data */
   .text : {
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	*(.fixup)
@@ -28,7 +28,7 @@
   _etext = .;			/* End of text section */
 
   .data : {			/* Data */
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
 	}
 
@@ -60,6 +60,11 @@
   __con_initcall_start = .;
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
+  .m68k_fixup : {
+	__start_fixup = .;
+	*(.m68k_fixup)
+	__stop_fixup = .;
+  }
   SECURITY_INIT
 #ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(8192);
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 2868e20..f06425b 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -12,7 +12,7 @@
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.head)
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	*(.fixup)
@@ -23,7 +23,7 @@
   _etext = .;			/* End of text section */
 
   .data : {			/* Data */
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
 	. = ALIGN(16);		/* Exception table */
 	__start___ex_table = .;
@@ -54,6 +54,11 @@
 	__con_initcall_start = .;
 	.con_initcall.init : { *(.con_initcall.init) }
 	__con_initcall_end = .;
+	.m68k_fixup : {
+		__start_fixup = .;
+		*(.m68k_fixup)
+		__stop_fixup = .;
+	}
 	SECURITY_INIT
 #ifdef CONFIG_BLK_DEV_INITRD
 	. = ALIGN(8192);
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
index cf6bb51..6216f12 100644
--- a/arch/m68k/lib/checksum.c
+++ b/arch/m68k/lib/checksum.c
@@ -422,3 +422,4 @@
 	    );
     return(sum);
 }
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
index 7a5bed5..e8a5713 100644
--- a/arch/m68k/mac/debug.c
+++ b/arch/m68k/mac/debug.c
@@ -71,7 +71,7 @@
 
 	/* calculate current offset */
 	pengoffset = (unsigned char *)mac_videobase +
-		(150+line*2) * mac_rowbytes) + 80 * peng;
+		(150+line*2) * mac_rowbytes + 80 * peng;
 
 	pptr = pengoffset;
 
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index ab90213..f1de19e 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -7,6 +7,7 @@
  *  to motorola.c and sun3mmu.c
  */
 
+#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -31,6 +32,37 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
+static bootmem_data_t __initdata bootmem_data[MAX_NUMNODES];
+
+pg_data_t pg_data_map[MAX_NUMNODES];
+EXPORT_SYMBOL(pg_data_map);
+
+int m68k_virt_to_node_shift;
+
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+pg_data_t *pg_data_table[65];
+EXPORT_SYMBOL(pg_data_table);
+#endif
+
+void m68k_setup_node(int node)
+{
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+	struct mem_info *info = m68k_memory + node;
+	int i, end;
+
+	i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
+	end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
+	for (; i <= end; i++) {
+		if (pg_data_table[i])
+			printk("overlap at %u for chunk %u\n", i, node);
+		pg_data_table[i] = pg_data_map + node;
+	}
+#endif
+	pg_data_map[node].bdata = bootmem_data + node;
+	node_set_online(node);
+}
+
+
 /*
  * ZERO_PAGE is a special page that is used for zero-initialized
  * data and COW.
@@ -40,52 +72,51 @@
 
 void show_mem(void)
 {
-    unsigned long i;
-    int free = 0, total = 0, reserved = 0, shared = 0;
-    int cached = 0;
+	pg_data_t *pgdat;
+	int free = 0, total = 0, reserved = 0, shared = 0;
+	int cached = 0;
+	int i;
 
-    printk("\nMem-info:\n");
-    show_free_areas();
-    printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-    i = max_mapnr;
-    while (i-- > 0) {
-	total++;
-	if (PageReserved(mem_map+i))
-	    reserved++;
-	else if (PageSwapCache(mem_map+i))
-	    cached++;
-	else if (!page_count(mem_map+i))
-	    free++;
-	else
-	    shared += page_count(mem_map+i) - 1;
-    }
-    printk("%d pages of RAM\n",total);
-    printk("%d free pages\n",free);
-    printk("%d reserved pages\n",reserved);
-    printk("%d pages shared\n",shared);
-    printk("%d pages swap cached\n",cached);
+	printk("\nMem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+	for_each_online_pgdat(pgdat) {
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
+			struct page *page = pgdat->node_mem_map + i;
+			total++;
+			if (PageReserved(page))
+				reserved++;
+			else if (PageSwapCache(page))
+				cached++;
+			else if (!page_count(page))
+				free++;
+			else
+				shared += page_count(page) - 1;
+		}
+	}
+	printk("%d pages of RAM\n",total);
+	printk("%d free pages\n",free);
+	printk("%d reserved pages\n",reserved);
+	printk("%d pages shared\n",shared);
+	printk("%d pages swap cached\n",cached);
 }
 
 extern void init_pointer_table(unsigned long ptable);
 
 /* References to section boundaries */
 
-extern char _text, _etext, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
+extern char _text[], _etext[];
+extern char __init_begin[], __init_end[];
 
 extern pmd_t *zero_pgtable;
 
 void __init mem_init(void)
 {
+	pg_data_t *pgdat;
 	int codepages = 0;
 	int datapages = 0;
 	int initpages = 0;
-	unsigned long tmp;
-#ifndef CONFIG_SUN3
 	int i;
-#endif
-
-	max_mapnr = num_physpages = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT);
 
 #ifdef CONFIG_ATARI
 	if (MACH_IS_ATARI)
@@ -93,19 +124,25 @@
 #endif
 
 	/* this will put all memory onto the freelists */
-	totalram_pages = free_all_bootmem();
+	totalram_pages = num_physpages = 0;
+	for_each_online_pgdat(pgdat) {
+		num_physpages += pgdat->node_present_pages;
 
-	for (tmp = PAGE_OFFSET ; tmp < (unsigned long)high_memory; tmp += PAGE_SIZE) {
-		if (PageReserved(virt_to_page(tmp))) {
-			if (tmp >= (unsigned long)&_text
-			    && tmp < (unsigned long)&_etext)
+		totalram_pages += free_all_bootmem_node(pgdat);
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
+			struct page *page = pgdat->node_mem_map + i;
+			char *addr = page_to_virt(page);
+
+			if (!PageReserved(page))
+				continue;
+			if (addr >= _text &&
+			    addr < _etext)
 				codepages++;
-			else if (tmp >= (unsigned long) &__init_begin
-				 && tmp < (unsigned long) &__init_end)
+			else if (addr >= __init_begin &&
+				 addr < __init_end)
 				initpages++;
 			else
 				datapages++;
-			continue;
 		}
 	}
 
@@ -124,7 +161,7 @@
 
 	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
 	       (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
-	       max_mapnr << (PAGE_SHIFT-10),
+	       totalram_pages << (PAGE_SHIFT-10),
 	       codepages << (PAGE_SHIFT-10),
 	       datapages << (PAGE_SHIFT-10),
 	       initpages << (PAGE_SHIFT-10));
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index 13c0b4a..b747352 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -127,67 +127,6 @@
 	return 0;
 }
 
-#ifdef DEBUG_INVALID_PTOV
-int mm_inv_cnt = 5;
-#endif
-
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-/*
- * The following two routines map from a physical address to a kernel
- * virtual address and vice versa.
- */
-unsigned long mm_vtop(unsigned long vaddr)
-{
-	int i=0;
-	unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET;
-
-	do {
-		if (voff < m68k_memory[i].size) {
-#ifdef DEBUGPV
-			printk ("VTOP(%p)=%lx\n", vaddr,
-				m68k_memory[i].addr + voff);
-#endif
-			return m68k_memory[i].addr + voff;
-		}
-		voff -= m68k_memory[i].size;
-	} while (++i < m68k_num_memory);
-
-	/* As a special case allow `__pa(high_memory)'.  */
-	if (voff == 0)
-		return m68k_memory[i-1].addr + m68k_memory[i-1].size;
-
-	return -1;
-}
-EXPORT_SYMBOL(mm_vtop);
-
-unsigned long mm_ptov (unsigned long paddr)
-{
-	int i = 0;
-	unsigned long poff, voff = PAGE_OFFSET;
-
-	do {
-		poff = paddr - m68k_memory[i].addr;
-		if (poff < m68k_memory[i].size) {
-#ifdef DEBUGPV
-			printk ("PTOV(%lx)=%lx\n", paddr, poff + voff);
-#endif
-			return poff + voff;
-		}
-		voff += m68k_memory[i].size;
-	} while (++i < m68k_num_memory);
-
-#ifdef DEBUG_INVALID_PTOV
-	if (mm_inv_cnt > 0) {
-		mm_inv_cnt--;
-		printk("Invalid use of phys_to_virt(0x%lx) at 0x%p!\n",
-			paddr, __builtin_return_address(0));
-	}
-#endif
-	return -1;
-}
-EXPORT_SYMBOL(mm_ptov);
-#endif
-
 /* invalidate page in both caches */
 static inline void clear040(unsigned long paddr)
 {
@@ -354,15 +293,3 @@
 }
 EXPORT_SYMBOL(cache_push);
 
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-int mm_end_of_chunk (unsigned long addr, int len)
-{
-	int i;
-
-	for (i = 0; i < m68k_num_memory; i++)
-		if (m68k_memory[i].addr + m68k_memory[i].size == addr + len)
-			return 1;
-	return 0;
-}
-EXPORT_SYMBOL(mm_end_of_chunk);
-#endif
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index afcccdc..7d571a2 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -43,6 +43,11 @@
 EXPORT_SYMBOL(mm_cachebits);
 #endif
 
+/* size of memory already mapped in head.S */
+#define INIT_MAPPED_SIZE	(4UL<<20)
+
+extern unsigned long availmem;
+
 static pte_t * __init kernel_page_table(void)
 {
 	pte_t *ptablep;
@@ -98,19 +103,20 @@
 	return last_pgtable;
 }
 
-static unsigned long __init
-map_chunk (unsigned long addr, long size)
+static void __init map_node(int node)
 {
 #define PTRTREESIZE (256*1024)
 #define ROOTTREESIZE (32*1024*1024)
-	static unsigned long virtaddr = PAGE_OFFSET;
-	unsigned long physaddr;
+	unsigned long physaddr, virtaddr, size;
 	pgd_t *pgd_dir;
 	pmd_t *pmd_dir;
 	pte_t *pte_dir;
 
-	physaddr = (addr | m68k_supervisor_cachemode |
-		    _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+	size = m68k_memory[node].size;
+	physaddr = m68k_memory[node].addr;
+	virtaddr = (unsigned long)phys_to_virt(physaddr);
+	physaddr |= m68k_supervisor_cachemode |
+		    _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY;
 	if (CPU_IS_040_OR_060)
 		physaddr |= _PAGE_GLOBAL040;
 
@@ -190,8 +196,6 @@
 #ifdef DEBUG
 	printk("\n");
 #endif
-
-	return virtaddr;
 }
 
 /*
@@ -200,15 +204,16 @@
  */
 void __init paging_init(void)
 {
-	int chunk;
-	unsigned long mem_avail = 0;
 	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+	unsigned long min_addr, max_addr;
+	unsigned long addr, size, end;
+	int i;
 
 #ifdef DEBUG
 	{
 		extern unsigned long availmem;
-		printk ("start of paging_init (%p, %lx, %lx, %lx)\n",
-			kernel_pg_dir, availmem, start_mem, end_mem);
+		printk ("start of paging_init (%p, %lx)\n",
+			kernel_pg_dir, availmem);
 	}
 #endif
 
@@ -222,24 +227,62 @@
 			pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
 	}
 
-	/*
-	 * Map the physical memory available into the kernel virtual
-	 * address space.  It may allocate some memory for page
-	 * tables and thus modify availmem.
-	 */
+	min_addr = m68k_memory[0].addr;
+	max_addr = min_addr + m68k_memory[0].size;
+	for (i = 1; i < m68k_num_memory;) {
+		if (m68k_memory[i].addr < min_addr) {
+			printk("Ignoring memory chunk at 0x%lx:0x%lx before the first chunk\n",
+				m68k_memory[i].addr, m68k_memory[i].size);
+			printk("Fix your bootloader or use a memfile to make use of this area!\n");
+			m68k_num_memory--;
+			memmove(m68k_memory + i, m68k_memory + i + 1,
+				(m68k_num_memory - i) * sizeof(struct mem_info));
+			continue;
+		}
+		addr = m68k_memory[i].addr + m68k_memory[i].size;
+		if (addr > max_addr)
+			max_addr = addr;
+		i++;
+	}
+	m68k_memoffset = min_addr - PAGE_OFFSET;
+	m68k_virt_to_node_shift = fls(max_addr - min_addr - 1) - 6;
 
-	for (chunk = 0; chunk < m68k_num_memory; chunk++) {
-		mem_avail = map_chunk (m68k_memory[chunk].addr,
-				       m68k_memory[chunk].size);
+	module_fixup(NULL, __start_fixup, __stop_fixup);
+	flush_icache();
 
+	high_memory = phys_to_virt(max_addr);
+
+	min_low_pfn = availmem >> PAGE_SHIFT;
+	max_low_pfn = max_addr >> PAGE_SHIFT;
+
+	for (i = 0; i < m68k_num_memory; i++) {
+		addr = m68k_memory[i].addr;
+		end = addr + m68k_memory[i].size;
+		m68k_setup_node(i);
+		availmem = PAGE_ALIGN(availmem);
+		availmem += init_bootmem_node(NODE_DATA(i),
+					      availmem >> PAGE_SHIFT,
+					      addr >> PAGE_SHIFT,
+					      end >> PAGE_SHIFT);
 	}
 
+	/*
+	 * Map the physical memory available into the kernel virtual
+	 * address space. First initialize the bootmem allocator with
+	 * the memory we already mapped, so map_node() has something
+	 * to allocate.
+	 */
+	addr = m68k_memory[0].addr;
+	size = m68k_memory[0].size;
+	free_bootmem_node(NODE_DATA(0), availmem, min(INIT_MAPPED_SIZE, size) - (availmem - addr));
+	map_node(0);
+	if (size > INIT_MAPPED_SIZE)
+		free_bootmem_node(NODE_DATA(0), addr + INIT_MAPPED_SIZE, size - INIT_MAPPED_SIZE);
+
+	for (i = 1; i < m68k_num_memory; i++)
+		map_node(i);
+
 	flush_tlb_all();
-#ifdef DEBUG
-	printk ("memory available is %ldKB\n", mem_avail >> 10);
-	printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
-		start_mem, end_mem);
-#endif
 
 	/*
 	 * initialize the bad page table and bad page to point
@@ -256,14 +299,11 @@
 #ifdef DEBUG
 	printk ("before free_area_init\n");
 #endif
-	zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ?
-				(mach_max_dma_address+1) : (unsigned long)high_memory);
-	zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0];
-
-	zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT;
-	zones_size[ZONE_NORMAL] >>= PAGE_SHIFT;
-
-	free_area_init(zones_size);
+	for (i = 0; i < m68k_num_memory; i++) {
+		zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
+		free_area_init_node(i, pg_data_map + i, zones_size,
+				    m68k_memory[i].addr >> PAGE_SHIFT, NULL);
+	}
 }
 
 extern char __init_begin, __init_end;
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 4851b84..c0fbd27 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -21,6 +21,7 @@
 #include <asm/contregs.h>
 #include <asm/movs.h>
 #include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 #include <asm/sun3-head.h>
 #include <asm/sun3mmu.h>
 #include <asm/rtc.h>
@@ -127,6 +128,7 @@
 	high_memory = (void *)memory_end;
 	availmem = memory_start;
 
+	m68k_setup_node(0);
 	availmem += init_bootmem_node(NODE_DATA(0), start_page, 0, num_pages);
 	availmem = (availmem + (PAGE_SIZE-1)) & PAGE_MASK;
 
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 941955d..846f975 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -377,7 +377,7 @@
 	fp = ((struct switch_stack *)p->thread.ksp)->a6;
 	do {
 		if (fp < stack_page+sizeof(struct thread_info) ||
-		    fp >= 8184+stack_page)
+		    fp >= THREAD_SIZE-8+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
 		if (!in_sched_functions(pc))
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index f54b6a3..ef70ca0 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -106,17 +106,9 @@
 	switch (request) {
 		/* when I and D space are separate, these will need to be fixed. */
 		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-		case PTRACE_PEEKDATA: {
-			unsigned long tmp;
-			int copied;
-
-			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-			ret = -EIO;
-			if (copied != sizeof(tmp))
-				break;
-			ret = put_user(tmp,(unsigned long *) data);
+		case PTRACE_PEEKDATA:
+			ret = generic_ptrace_peekdata(child, addr, data);
 			break;
-		}
 
 		/* read the word at location addr in the USER area. */
 		case PTRACE_PEEKUSR: {
@@ -159,10 +151,7 @@
 		/* when I and D space are separate, this will have to be fixed. */
 		case PTRACE_POKETEXT: /* write the word at location addr. */
 		case PTRACE_POKEDATA:
-			ret = 0;
-			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-				break;
-			ret = -EIO;
+			ret = generic_ptrace_pokedata(child, addr, data);
 			break;
 
 		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 8133b10..80f4e9d 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -1,8 +1,8 @@
 /*
  *  linux/arch/m68knommu/kernel/setup.c
  *
- *  Copyright (C) 1999-2004  Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@lineo.ca>
+ *  Copyright (C) 1999-2007  Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@uClinux.org>
  *  Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com}
  *  Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
  *  Copyright (C) 1995       Hamish Macdonald
@@ -20,17 +20,13 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/fs.h>
 #include <linux/fb.h>
 #include <linux/module.h>
 #include <linux/console.h>
-#include <linux/genhd.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/major.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 #include <linux/init.h>
 
 #include <asm/setup.h>
@@ -46,34 +42,19 @@
 
 char __initdata command_line[COMMAND_LINE_SIZE];
 
-/* setup some dummy routines */
-static void dummy_waitbut(void)
-{
-}
+void (*mach_trap_init)(void);
 
-void (*mach_sched_init) (irq_handler_t handler);
-void (*mach_tick)( void );
-/* machine dependent keyboard functions */
-int (*mach_keyb_init) (void);
-int (*mach_kbdrate) (struct kbd_repeat *);
-void (*mach_kbd_leds) (unsigned int);
-/* machine dependent irq functions */
-void (*mach_init_IRQ) (void);
-irq_handler_t mach_default_handler;
-int (*mach_get_irq_list) (struct seq_file *, void *);
-void (*mach_process_int) (int irq, struct pt_regs *fp);
-void (*mach_trap_init) (void);
 /* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
-void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
-int (*mach_hwclk) (int, struct rtc_time*);
-int (*mach_set_clock_mmss) (unsigned long);
-void (*mach_mksound)( unsigned int count, unsigned int ticks );
-void (*mach_reset)( void );
-void (*waitbut)(void) = dummy_waitbut;
-void (*mach_debug_init)(void);
-void (*mach_halt)( void );
-void (*mach_power_off)( void );
+void (*mach_sched_init)(irq_handler_t handler);
+void (*mach_tick)(void);
+void (*mach_gettod)(int*, int*, int*, int*, int*, int*);
+int (*mach_set_clock_mmss)(unsigned long);
+unsigned long (*mach_gettimeoffset)(void);
+
+/* machine dependent reboot functions */
+void (*mach_reset)(void);
+void (*mach_halt)(void);
+void (*mach_power_off)(void);
 
 
 #ifdef CONFIG_M68000
@@ -134,13 +115,6 @@
 	#define	CPU "UNKNOWN"
 #endif
 
-/* (es) */
-/* note: why is this defined here?  the must be a better place to put this */
-#if defined( CONFIG_TELOS) || defined( CONFIG_UCDIMM ) || defined( CONFIG_UCSIMM ) || defined(CONFIG_DRAGEN2) || (defined( CONFIG_PILOT ) && defined( CONFIG_M68328 ))
-#define CAT_ROMARRAY
-#endif
-/* (/es) */
-
 extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
 extern int _ramstart, _ramend;
 
@@ -148,15 +122,8 @@
 {
 	int bootmap_size;
 
-#if defined(CAT_ROMARRAY) && defined(DEBUG)
-	extern int __data_rom_start;
-	extern int __data_start;
-	int *romarray = (int *)((int) &__data_rom_start +
-			      (int)&_edata - (int)&__data_start);
-#endif
-
 	memory_start = PAGE_ALIGN(_ramstart);
-	memory_end = _ramend; /* by now the stack is part of the init task */
+	memory_end = _ramend;
 
 	init_mm.start_code = (unsigned long) &_stext;
 	init_mm.end_code = (unsigned long) &_etext;
@@ -220,11 +187,7 @@
 		(int) &_sbss, (int) &_ebss);
 	printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
 		"STACK=0x%06x-0x%06x\n",
-#ifdef CAT_ROMARRAY
-		(int) romarray, ((int) romarray) + romarray[2],
-#else
 		(int) &_ebss, (int) memory_start,
-#endif
 		(int) memory_start, (int) memory_end,
 		(int) memory_end, (int) _ramend);
 #endif
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index bed5f47..fde04e1 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -83,6 +83,7 @@
 	printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
 		current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
 	show_stack(NULL, (unsigned long *)fp);
+	add_taint(TAINT_DIE);
 	do_exit(SIGSEGV);
 }
 
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index c86a1bf..07a0055 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -62,7 +62,7 @@
 	.text : {
 		_text = .;
 		_stext = . ;
-        	*(.text)
+		TEXT_TEXT
 		SCHED_TEXT
         	*(.text.lock)
 
@@ -133,7 +133,7 @@
 	.data DATA_ADDR : {
 		. = ALIGN(4);
 		_sdata = . ;
-		*(.data)
+		DATA_DATA
 		. = ALIGN(8192) ;
 		*(.data.init_task)
 		_edata = . ;
diff --git a/arch/m68knommu/mm/memory.c b/arch/m68knommu/mm/memory.c
index 411e452..1a66b71 100644
--- a/arch/m68knommu/mm/memory.c
+++ b/arch/m68knommu/mm/memory.c
@@ -17,90 +17,14 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 
-#include <asm/setup.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
-#include <asm/traps.h>
-#include <asm/io.h>
 
 /*
- * cache_clear() semantics: Clear any cache entries for the area in question,
- * without writing back dirty entries first. This is useful if the data will
- * be overwritten anyway, e.g. by DMA to memory. The range is defined by a
- * _physical_ address.
- */
-
-void cache_clear (unsigned long paddr, int len)
-{
-}
-
-
-/*
- *	Define cache invalidate functions. The ColdFire 5407 is really
- *	the only processor that needs to do some work here. Anything
- *	that has separate data and instruction caches will be a problem.
- */
-#ifdef CONFIG_M5407
-
-static __inline__ void cache_invalidate_lines(unsigned long paddr, int len)
-{
-	unsigned long	sset, eset;
-
-	sset = (paddr & 0x00000ff0);
-	eset = ((paddr + len) & 0x0000ff0) + 0x10;
-
-	__asm__ __volatile__ (
-		"nop\n\t"
-		"clrl	%%d0\n\t"
-		"1:\n\t"
-		"movel	%0,%%a0\n\t"
-		"addl	%%d0,%%a0\n\t"
-		"2:\n\t"
-		".word	0xf4e8\n\t"
-		"addl	#0x10,%%a0\n\t"
-		"cmpl	%1,%%a0\n\t"
-		"blt	2b\n\t"
-		"addql	#1,%%d0\n\t"
-		"cmpil	#4,%%d0\n\t"
-		"bne	1b"
-		: : "a" (sset), "a" (eset) : "d0", "a0" );
-}
-
-#else
-#define	cache_invalidate_lines(a,b)
-#endif
-
-
-/*
- * cache_push() semantics: Write back any dirty cache data in the given area,
- * and invalidate the range in the instruction cache. It needs not (but may)
- * invalidate those entries also in the data cache. The range is defined by a
- * _physical_ address.
- */
-
-void cache_push (unsigned long paddr, int len)
-{
-	cache_invalidate_lines(paddr, len);
-}
-
-
-/*
- * cache_push_v() semantics: Write back any dirty cache data in the given
- * area, and invalidate those entries at least in the instruction cache. This
- * is intended to be used after data has been written that can be executed as
- * code later. The range is defined by a _user_mode_ _virtual_ address  (or,
- * more exactly, the space is defined by the %sfc/%dfc register.)
- */
-
-void cache_push_v (unsigned long vaddr, int len)
-{
-	cache_invalidate_lines(vaddr, len);
-}
-
-/* Map some physical address range into the kernel address space. The
- * code is copied and adapted from map_chunk().
+ * Map some physical address range into the kernel address space.
+ * The code is copied and adapted from map_chunk().
  */
 
 unsigned long kernel_map(unsigned long paddr, unsigned long size,
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index 92e5807..fb66ead 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -62,10 +62,13 @@
 
 /***************************************************************************/
 
+static int ticks_per_intr;
+
 void coldfire_timer_init(irq_handler_t handler)
 {
 	__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
-	__raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
+	ticks_per_intr = (MCF_BUSCLK / 16) / HZ;
+	__raw_writetrr(ticks_per_intr - 1, TA(MCFTIMER_TRR));
 	__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
 		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
 
@@ -81,11 +84,10 @@
 
 unsigned long coldfire_timer_offset(void)
 {
-	unsigned long trr, tcn, offset;
+	unsigned long tcn, offset;
 
 	tcn = __raw_readw(TA(MCFTIMER_TCN));
-	trr = __raw_readtrr(TA(MCFTIMER_TRR));
-	offset = (tcn * (1000000 / HZ)) / trr;
+	offset = ((tcn + 1) * (1000000 / HZ)) / ticks_per_intr;
 
 	/* Check if we just wrapped the counters and maybe missed a tick */
 	if ((offset < (1000000 / HZ / 2)) && mcf_timerirqpending(1))
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0f09412..5c863bc 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -15,6 +15,29 @@
 	prompt "System type"
 	default SGI_IP22
 
+config LEMOTE_FULONG
+	bool "Lemote Fulong mini-PC"
+	select ARCH_SPARSEMEM_ENABLE
+	select SYS_HAS_CPU_LOONGSON2
+	select DMA_NONCOHERENT
+	select BOOT_ELF32
+	select BOARD_SCACHE
+	select HAVE_STD_PC_SERIAL_PORT
+	select HW_HAS_PCI
+	select I8259
+	select ISA
+	select IRQ_CPU
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_HAS_EARLY_PRINTK
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select CPU_HAS_WB
+	help
+	  Lemote Fulong mini-PC board based on the Chinese Loongson-2E CPU and
+	  an FPGA northbridge
+
 config MACH_ALCHEMY
 	bool "Alchemy processor based machines"
 
@@ -63,7 +86,7 @@
 	bool "DECstations"
 	select BOOT_ELF32
 	select DMA_NONCOHERENT
-	select SYS_HAS_EARLY_PRINTK
+	select NO_IOPORT
 	select IRQ_CPU
 	select SYS_HAS_CPU_R3000
 	select SYS_HAS_CPU_R4X00
@@ -88,33 +111,15 @@
 
 	  otherwise choose R3000.
 
-config MIPS_EV64120
-	bool "Galileo EV64120 Evaluation board (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select PCI_GT64XXX_PCI0
-	select SYS_HAS_CPU_R5000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select SYS_SUPPORTS_KGDB
-	help
-	  This is an evaluation board based on the Galileo GT-64120
-	  single-chip system controller that contains a MIPS R5000 compatible
-	  core running at 75/100MHz.  Their website is located at
-	  <http://www.marvell.com/>.  Say Y here if you wish to build a
-	  kernel for this platform.
-
 config MACH_JAZZ
 	bool "Jazz family of machines"
 	select ARC
 	select ARC32
 	select ARCH_MAY_HAVE_PC_FDC
 	select GENERIC_ISA_DMA
-	select I8253
 	select I8259
 	select ISA
+	select PCSPEAKER
 	select SYS_HAS_CPU_R4X00
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
@@ -126,20 +131,6 @@
 	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
 	 Olivetti M700-10 workstations.
 
-config LASAT
-	bool "LASAT Networks platforms"
-	select DMA_NONCOHERENT
-	select SYS_HAS_EARLY_PRINTK
-	select HW_HAS_PCI
-	select PCI_GT64XXX_PCI0
-	select MIPS_NILE4
-	select R5000_CPU_SCACHE
-	select SYS_HAS_CPU_R5000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
-
 config MIPS_ATLAS
 	bool "MIPS Atlas board"
 	select BOOT_ELF32
@@ -173,7 +164,6 @@
 	bool "MIPS Malta board"
 	select ARCH_MAY_HAVE_PC_FDC
 	select BOOT_ELF32
-	select HAVE_STD_PC_SERIAL_PORT
 	select DMA_NONCOHERENT
 	select GENERIC_ISA_DMA
 	select IRQ_CPU
@@ -246,11 +236,13 @@
 	select DMA_NONCOHERENT
 	select SYS_HAS_EARLY_PRINTK
 	select IRQ_CPU
+	select BOOT_RAW
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R2
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_MULTITHREADING
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	help
 	  This option enables support for MIPS Technologies MIPSsim software
@@ -274,50 +266,13 @@
 	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
 	  Momentum Computer <http://www.momenco.com/>.
 
-config MOMENCO_OCELOT_3
-	bool "Momentum Ocelot-3 board"
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select IRQ_MV64340
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_HAS_CPU_RM9000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	help
-	  The Ocelot-3 is based off Discovery III System Controller and
-	  PMC-Sierra Rm79000 core.
-
-config MOMENCO_OCELOT_C
-	bool "Momentum Ocelot-C board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_MV64340
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_HAS_CPU_RM7000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
-	help
-	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
-	  Momentum Computer <http://www.momenco.com/>.
-
 config PNX8550_JBS
 	bool "Philips PNX8550 based JBS board"
 	select PNX8550
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config PNX8550_STB810
-	bool "Support for Philips PNX8550 based STB810 board"
+	bool "Philips PNX8550 based STB810 board"
 	select PNX8550
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
@@ -346,6 +301,27 @@
 	select SYS_HAS_CPU_VR41XX
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 
+config PMC_MSP
+	bool "PMC-Sierra MSP chipsets"
+	depends on EXPERIMENTAL
+	select DMA_NONCOHERENT
+	select SWAP_IO_SPACE
+	select NO_EXCEPT_FILL
+	select BOOT_RAW
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
+	select IRQ_CPU
+	select SERIAL_8250
+	select SERIAL_8250_CONSOLE
+	help
+	  This adds support for the PMC-Sierra family of Multi-Service
+	  Processor System-On-A-Chips.  These parts include a number
+	  of integrated peripherals, interfaces and DSPs in addition to
+	  a variety of MIPS cores.
+
 config PMC_YOSEMITE
 	bool "PMC-Sierra Yosemite eval board"
 	select DMA_COHERENT
@@ -371,9 +347,9 @@
 	select DMA_COHERENT
 	select GENERIC_ISA_DMA
 	select HAVE_STD_PC_SERIAL_PORT
-	select I8253
 	select I8259
 	select ISA
+	select PCSPEAKER
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
@@ -392,7 +368,7 @@
 	  can be found at http://www.linux-mips.org/wiki/Qemu.
 
 config MARKEINS
-	bool "Support for NEC EMMA2RH Mark-eins"
+	bool "NEC EMMA2RH Mark-eins"
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
@@ -450,8 +426,7 @@
 	  here.
 
 config SGI_IP32
-	bool "SGI IP32 (O2) (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "SGI IP32 (O2)"
 	select ARC
 	select ARC32
 	select BOOT_ELF32
@@ -587,9 +562,9 @@
 	select HW_HAS_EISA
 	select HW_HAS_PCI
 	select IRQ_CPU
-	select I8253
 	select I8259
 	select ISA
+	select PCSPEAKER
 	select SWAP_IO_SPACE if CPU_BIG_ENDIAN
 	select SYS_HAS_CPU_R4X00
 	select SYS_HAS_CPU_R5000
@@ -652,6 +627,7 @@
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_KGDB
 	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select GENERIC_GPIO
 	help
 	  This Toshiba board is based on the TX4938 processor. Say Y here to
 	  support this machine type
@@ -660,9 +636,7 @@
 
 source "arch/mips/au1000/Kconfig"
 source "arch/mips/ddb5xxx/Kconfig"
-source "arch/mips/gt64120/ev64120/Kconfig"
 source "arch/mips/jazz/Kconfig"
-source "arch/mips/lasat/Kconfig"
 source "arch/mips/pmc-sierra/Kconfig"
 source "arch/mips/sgi-ip27/Kconfig"
 source "arch/mips/sibyte/Kconfig"
@@ -721,6 +695,9 @@
 config ARCH_MAY_HAVE_PC_FDC
 	bool
 
+config BOOT_RAW
+	bool
+
 config DMA_COHERENT
 	bool
 
@@ -747,9 +724,9 @@
 	  to print messages very early in the bootup process.
 
 	  This is useful for kernel debugging when your machine crashes very
-	  early before the console code is initialized. For normal operation
-	  it is not recommended because it looks on some machines ugly and
-	  oesn't cooperate with an X server. You should normally N here,
+	  early before the console code is initialized. For normal operation,
+	  it is not recommended because it looks ugly on some machines and
+	  doesn't cooperate with an X server. You should normally say N here,
 	  unless you want to debug such a crash.
 
 config SYS_HAS_EARLY_PRINTK
@@ -768,16 +745,19 @@
 config MIPS_MSC
 	bool
 
-config MIPS_NILE4
-	bool
-
 config MIPS_DISABLE_OBSOLETE_IDE
 	bool
 
+config NO_IOPORT
+	def_bool n
+
 config GENERIC_ISA_DMA_SUPPORT_BROKEN
 	bool
 	select ZONE_DMA
 
+config GENERIC_GPIO
+	bool
+
 #
 # Endianess selection.  Sufficiently obscure so many users don't know what to
 # answer,so we try hard to limit the available choices.  Also the use of a
@@ -821,7 +801,10 @@
 config IRQ_CPU_RM9K
 	bool
 
-config IRQ_MV64340
+config IRQ_MSP_SLP
+	bool
+
+config IRQ_MSP_CIC
 	bool
 
 config DDB5XXX_COMMON
@@ -834,6 +817,9 @@
 config PCI_GT64XXX_PCI0
 	bool
 
+config NO_EXCEPT_FILL
+	bool
+
 config MIPS_TX3927
 	bool
 	select HAS_TXX9_SERIAL
@@ -841,14 +827,6 @@
 config MIPS_RM9122
 	bool
 	select SERIAL_RM9000
-	select GPI_RM9000
-	select WDT_RM9000
-
-config PCI_MARVELL
-	bool
-
-config SERIAL_RM9000
-	bool
 
 config PNX8550
 	bool
@@ -863,6 +841,7 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 	select SYS_SUPPORTS_KGDB
+	select GENERIC_GPIO
 
 config SWAP_IO_SPACE
 	bool
@@ -875,31 +854,17 @@
 config SERIAL_RM9000
 	bool
 
-config GPI_RM9000
-	bool
-
-config WDT_RM9000
-	bool
-
 #
 # Unfortunately not all GT64120 systems run the chip at the same clock.
 # As the user for the clock rate and try to minimize the available options.
 #
 choice
 	prompt "Galileo Chip Clock"
-	#default SYSCLK_83 if MIPS_EV64120
-	depends on MIPS_EV64120 || MOMENCO_OCELOT
-	default SYSCLK_83 if MIPS_EV64120
+	depends on MOMENCO_OCELOT
 	default SYSCLK_100 if MOMENCO_OCELOT
 
-config SYSCLK_75
-	bool "75" if MIPS_EV64120
-
-config SYSCLK_83
-	bool "83.3" if MIPS_EV64120
-
 config SYSCLK_100
-	bool "100" if MIPS_EV64120 || MOMENCO_OCELOT
+	bool "100" if MOMENCO_OCELOT
 
 endchoice
 
@@ -911,8 +876,9 @@
 
 config MIPS_L1_CACHE_SHIFT
 	int
-	default "4" if MACH_DECSTATION || SNI_RM
-	default "7" if SGI_IP27
+	default "4" if MACH_DECSTATION
+	default "7" if SGI_IP27 || SNI_RM
+	default "4" if PMC_MSP4200_EVAL
 	default "5"
 
 config HAVE_STD_PC_SERIAL_PORT
@@ -944,6 +910,16 @@
 	prompt "CPU type"
 	default CPU_R4X00
 
+config CPU_LOONGSON2
+	bool "Loongson 2"
+	depends on SYS_HAS_CPU_LOONGSON2
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	help
+	  The Loongson 2E processor implements the MIPS III instruction set
+	  with many extensions.
+
 config CPU_MIPS32_R1
 	bool "MIPS32 Release 1"
 	depends on SYS_HAS_CPU_MIPS32_R1
@@ -1154,6 +1130,9 @@
 
 endchoice
 
+config SYS_HAS_CPU_LOONGSON2
+	bool
+
 config SYS_HAS_CPU_MIPS32_R1
 	bool
 
@@ -1392,6 +1371,7 @@
 	depends on SYS_SUPPORTS_MULTITHREADING
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_EI
+	select CPU_MIPSR2_SRS
 	select MIPS_MT
 	help
 	  Includes a loader for loading an elf relocatable object
@@ -1424,6 +1404,19 @@
 	  it off), but ensures that IPIs are handled promptly even under
 	  heavy I/O interrupt load.
 
+config MIPS_MT_SMTC_IM_BACKSTOP
+	bool "Use per-TC register bits as backstop for inhibited IM bits"
+	depends on MIPS_MT_SMTC
+	default y
+	help
+	  To support multiple TC microthreads acting as "CPUs" within
+	  a VPE, VPE-wide interrupt mask bits must be specially manipulated
+	  during interrupt handling. To support legacy drivers and interrupt
+	  controller management code, SMTC has a "backstop" to track and
+	  if necessary restore the interrupt mask. This has some performance
+	  impact on interrupt service overhead. Disable it only if you know
+	  what you are doing.
+
 config MIPS_VPE_LOADER_TOM
 	bool "Load VPE program into memory hidden from linux"
 	depends on MIPS_VPE_LOADER
@@ -1487,6 +1480,15 @@
 config CPU_HAS_WB
 	bool
 
+config 64BIT_CONTEXT
+	bool "Save 64bit integer registers"
+	depends on 32BIT && CPU_LOONGSON2
+	help
+	  Loongson2 CPU is 64bit , when used in 32BIT mode, its integer
+	  registers can still be accessed as 64bit, mainly for multimedia
+	  instructions. We must have all 64bit save/restored to make sure
+	  those instructions to get correct result.
+
 #
 # Vectored interrupt mode is an R2 feature
 #
@@ -1862,7 +1864,7 @@
 	bool
 	default y
 
-config I8253
+config PCSPEAKER
 	bool
 
 source "drivers/pcmcia/Kconfig"
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 72d5c19..3efe117 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -37,7 +37,7 @@
 
 	  This option will slow down process creation somewhat.
 
-config CONFIG_SMTC_IDLE_HOOK_DEBUG
+config SMTC_IDLE_HOOK_DEBUG
 	bool "Enable additional debug checks before going into CPU idle loop"
 	depends on DEBUG_KERNEL && MIPS_MT_SMTC
 	help
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index f450066..20d19c9 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -118,6 +118,7 @@
 cflags-$(CONFIG_CPU_VR41XX)	+= -march=r4100 -Wa,--trap
 cflags-$(CONFIG_CPU_R4X00)	+= -march=r4600 -Wa,--trap
 cflags-$(CONFIG_CPU_TX49XX)	+= -march=r4600 -Wa,--trap
+cflags-$(CONFIG_CPU_LOONGSON2)	+= -march=r4600 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
 			-Wa,-mips32 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS32_R2)	+= $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
@@ -283,14 +284,6 @@
 CLEAN_FILES			+= drivers/tc/lk201-map.c
 
 #
-# Galileo EV64120 Board
-#
-core-$(CONFIG_MIPS_EV64120)	+= arch/mips/gt64120/ev64120/
-core-$(CONFIG_MIPS_EV64120)	+= arch/mips/gt64120/common/
-cflags-$(CONFIG_MIPS_EV64120)	+= -Iinclude/asm-mips/mach-ev64120
-load-$(CONFIG_MIPS_EV64120)	+= 0xffffffff80100000
-
-#
 # Wind River PPMC Board (4KC + GT64120)
 #
 core-$(CONFIG_WR_PPMC)		+= arch/mips/gt64120/wrppmc/
@@ -298,6 +291,13 @@
 load-$(CONFIG_WR_PPMC)		+= 0xffffffff80100000
 
 #
+# lemote fulong mini-PC board
+#
+core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/
+load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000
+cflags-$(CONFIG_LEMOTE_FULONG) += -Iinclude/asm-mips/mach-lemote
+
+#
 # For all MIPS, Inc. eval boards
 #
 core-$(CONFIG_MIPS_BOARDS_GEN)	+= arch/mips/mips-boards/generic/
@@ -327,7 +327,7 @@
 #
 # MIPS SIM
 #
-core-$(CONFIG_MIPS_SIM)		+= arch/mips/mips-boards/sim/
+core-$(CONFIG_MIPS_SIM)		+= arch/mips/mipssim/
 cflags-$(CONFIG_MIPS_SIM)	+= -Iinclude/asm-mips/mach-sim
 load-$(CONFIG_MIPS_SIM)		+= 0x80100000
 
@@ -343,12 +343,12 @@
 load-$(CONFIG_MOMENCO_OCELOT)	+= 0xffffffff80100000
 
 #
-# Momentum Ocelot-C and -CS boards
+# PMC-Sierra MSP SOCs
 #
-# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the
-# mips_io_port_base.
-core-$(CONFIG_MOMENCO_OCELOT_C)	+= arch/mips/momentum/ocelot_c/
-load-$(CONFIG_MOMENCO_OCELOT_C)	+= 0xffffffff80100000
+core-$(CONFIG_PMC_MSP)		+= arch/mips/pmc-sierra/msp71xx/
+cflags-$(CONFIG_PMC_MSP)	+= -Iinclude/asm-mips/pmc-sierra/msp71xx \
+					-mno-branch-likely
+load-$(CONFIG_PMC_MSP)		+= 0xffffffff80100000
 
 #
 # PMC-Sierra Yosemite
@@ -365,13 +365,6 @@
 load-$(CONFIG_QEMU)		+= 0xffffffff80010000
 
 #
-# Momentum Ocelot-3
-#
-core-$(CONFIG_MOMENCO_OCELOT_3) 	+= arch/mips/momentum/ocelot_3/
-cflags-$(CONFIG_MOMENCO_OCELOT_3)	+= -Iinclude/asm-mips/mach-ocelot3
-load-$(CONFIG_MOMENCO_OCELOT_3) 	+= 0xffffffff80100000
-
-#
 # Basler eXcite
 #
 core-$(CONFIG_BASLER_EXCITE)	+= arch/mips/basler/excite/
@@ -389,10 +382,6 @@
 core-$(CONFIG_DDB5477)		+= arch/mips/ddb5xxx/ddb5477/
 load-$(CONFIG_DDB5477)		+= 0xffffffff80100000
 
-core-$(CONFIG_LASAT)		+= arch/mips/lasat/
-cflags-$(CONFIG_LASAT)		+= -Iinclude/asm-mips/mach-lasat
-load-$(CONFIG_LASAT)		+= 0xffffffff80000000
-
 #
 # Common VR41xx
 #
@@ -580,6 +569,7 @@
 #
 core-$(CONFIG_TOSHIBA_RBTX4927)	+= arch/mips/tx4927/toshiba_rbtx4927/
 core-$(CONFIG_TOSHIBA_RBTX4927)	+= arch/mips/tx4927/common/
+cflags-$(CONFIG_TOSHIBA_RBTX4927) += -Iinclude/asm-mips/mach-tx49xx
 load-$(CONFIG_TOSHIBA_RBTX4927)	+= 0xffffffff80020000
 
 #
@@ -587,6 +577,7 @@
 #
 core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/toshiba_rbtx4938/
 core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/common/
+cflags-$(CONFIG_TOSHIBA_RBTX4938) += -Iinclude/asm-mips/mach-tx49xx
 load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000
 
 cflags-y			+= -Iinclude/asm-mips/mach-generic
@@ -603,7 +594,8 @@
 endif
 
 AFLAGS		+= $(cflags-y)
-CFLAGS		+= $(cflags-y)
+CFLAGS		+= $(cflags-y) \
+			-D"VMLINUX_LOAD_ADDRESS=$(load-y)"
 
 LDFLAGS			+= -m $(ld-emul)
 
@@ -633,18 +625,11 @@
 head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
 
 libs-y			+= arch/mips/lib/
-libs-$(CONFIG_32BIT)	+= arch/mips/lib-32/
-libs-$(CONFIG_64BIT)	+= arch/mips/lib-64/
 
 core-y			+= arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/
 
 drivers-$(CONFIG_OPROFILE)	+= arch/mips/oprofile/
 
-ifdef CONFIG_LASAT
-rom.bin rom.sw: vmlinux
-	$(Q)$(MAKE) $(build)=arch/mips/lasat/image $@
-endif
-
 #
 # Some machines like the Indy need 32-bit ELF binaries for booting purposes.
 # Other need ECOFF, so we build a 32-bit ELF binary for them which we then
@@ -702,32 +687,19 @@
 CLEAN_FILES += vmlinux.ecoff \
 	       vmlinux.srec
 
+archprepare:
+ifdef CONFIG_MIPS32_N32
+	@echo '  Checking missing-syscalls for N32'
+	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32"
+endif
+ifdef CONFIG_MIPS32_O32
+	@echo '  Checking missing-syscalls for O32'
+	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32"
+endif
+
 archclean:
 	@$(MAKE) $(clean)=arch/mips/boot
-	@$(MAKE) $(clean)=arch/mips/lasat
 
 CLEAN_FILES += vmlinux.32 \
 	       vmlinux.64 \
 	       vmlinux.ecoff
-
-quiet_cmd_syscalls_n32 = CALL-N32 $<
-      cmd_syscalls_n32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=n32
-
-quiet_cmd_syscalls_o32 = CALL-O32 $<
-      cmd_syscalls_o32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=32
-
-PHONY += missing-syscalls-n32 missing-syscalls-o32
-
-missing-syscalls-n32: scripts/checksyscalls.sh FORCE
-	$(call cmd,syscalls_n32)
-
-missing-syscalls-o32: scripts/checksyscalls.sh FORCE
-	$(call cmd,syscalls_o32)
-
-archprepare:
-ifdef CONFIG_MIPS32_N32
-	$(Q)$(MAKE) $(build)=arch/mips missing-syscalls-n32
-endif
-ifdef CONFIG_MIPS32_O32
-	$(Q)$(MAKE) $(build)=arch/mips missing-syscalls-o32
-endif
diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
index ce55297..7abe420 100644
--- a/arch/mips/au1000/common/gpio.c
+++ b/arch/mips/au1000/common/gpio.c
@@ -1,4 +1,7 @@
 /*
+ *  Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ *  	Architecture specific GPIO support
+ *
  *  This program is free software; you can redistribute	 it and/or modify it
  *  under  the terms of	 the GNU General  Public License as published by the
  *  Free Software Foundation;  either version 2 of the	License, or (at your
@@ -18,101 +21,136 @@
  *  You should have received a copy of the  GNU General Public License along
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Notes :
+ * 	au1000 SoC have only one GPIO line : GPIO1
+ * 	others have a second one : GPIO2
  */
+
+#include <linux/autoconf.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
 #include <linux/module.h>
-#include <au1000.h>
-#include <au1xxx_gpio.h>
+
+#include <asm/addrspace.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/gpio.h>
 
 #define gpio1 sys
 #if !defined(CONFIG_SOC_AU1000)
-static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE;
 
-#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
+static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE;
+#define GPIO2_OUTPUT_ENABLE_MASK 	0x00010000
 
-int au1xxx_gpio2_read(int signal)
+static int au1xxx_gpio2_read(unsigned gpio)
 {
-	signal -= 200;
-/*	gpio2->dir &= ~(0x01 << signal);						//Set GPIO to input */
-	return ((gpio2->pinstate >> signal) & 0x01);
+	gpio -= AU1XXX_GPIO_BASE;
+	return ((gpio2->pinstate >> gpio) & 0x01);
 }
 
-void au1xxx_gpio2_write(int signal, int value)
+static void au1xxx_gpio2_write(unsigned gpio, int value)
 {
-	signal -= 200;
+	gpio -= AU1XXX_GPIO_BASE;
 
-	gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) |
-		(value << signal);
+	gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio);
 }
 
-void au1xxx_gpio2_tristate(int signal)
+static int au1xxx_gpio2_direction_input(unsigned gpio)
 {
-	signal -= 200;
-	gpio2->dir &= ~(0x01 << signal); 	/* Set GPIO to input */
-}
-#endif
-
-int au1xxx_gpio1_read(int signal)
-{
-/*	gpio1->trioutclr |= (0x01 << signal); */
-	return ((gpio1->pinstaterd >> signal) & 0x01);
+	gpio -= AU1XXX_GPIO_BASE;
+	gpio2->dir &= ~(0x01 << gpio);
+	return 0;
 }
 
-void au1xxx_gpio1_write(int signal, int value)
+static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
 {
-	if(value)
-		gpio1->outputset = (0x01 << signal);
+	gpio -= AU1XXX_GPIO_BASE;
+	gpio2->dir = (0x01 << gpio) | (value << gpio);
+	return 0;
+}
+
+#endif /* !defined(CONFIG_SOC_AU1000) */
+
+static int au1xxx_gpio1_read(unsigned gpio)
+{
+	return ((gpio1->pinstaterd >> gpio) & 0x01);
+}
+
+static void au1xxx_gpio1_write(unsigned gpio, int value)
+{
+	if (value)
+		gpio1->outputset = (0x01 << gpio);
 	else
-		gpio1->outputclr = (0x01 << signal);	/* Output a Zero */
+		/* Output a zero */
+		gpio1->outputclr = (0x01 << gpio);
 }
 
-void au1xxx_gpio1_tristate(int signal)
+static int au1xxx_gpio1_direction_input(unsigned gpio)
 {
-	gpio1->trioutclr = (0x01 << signal);		/* Tristate signal */
+	gpio1->pininputen = (0x01 << gpio);
+	return 0;
 }
 
-
-int au1xxx_gpio_read(int signal)
+static int au1xxx_gpio1_direction_output(unsigned gpio, int value)
 {
-	if(signal >= 200)
+	gpio1->trioutclr = (0x01 & gpio);
+	return 0;
+}
+
+int au1xxx_gpio_get_value(unsigned gpio)
+{
+	if (gpio >= AU1XXX_GPIO_BASE)
 #if defined(CONFIG_SOC_AU1000)
 		return 0;
 #else
-		return au1xxx_gpio2_read(signal);
+		return au1xxx_gpio2_read(gpio);
 #endif
 	else
-		return au1xxx_gpio1_read(signal);
+		return au1xxx_gpio1_read(gpio);
 }
 
-void au1xxx_gpio_write(int signal, int value)
+EXPORT_SYMBOL(au1xxx_gpio_get_value);
+
+void au1xxx_gpio_set_value(unsigned gpio, int value)
 {
-	if(signal >= 200)
+	if (gpio >= AU1XXX_GPIO_BASE)
 #if defined(CONFIG_SOC_AU1000)
 		;
 #else
-		au1xxx_gpio2_write(signal, value);
+		au1xxx_gpio2_write(gpio, value);
 #endif
 	else
-		au1xxx_gpio1_write(signal, value);
+		au1xxx_gpio1_write(gpio, value);
 }
 
-void au1xxx_gpio_tristate(int signal)
+EXPORT_SYMBOL(au1xxx_gpio_set_value);
+
+int au1xxx_gpio_direction_input(unsigned gpio)
 {
-	if(signal >= 200)
+	if (gpio >= AU1XXX_GPIO_BASE)
 #if defined(CONFIG_SOC_AU1000)
 		;
 #else
-		au1xxx_gpio2_tristate(signal);
+		return au1xxx_gpio2_direction_input(gpio);
 #endif
 	else
-		au1xxx_gpio1_tristate(signal);
+		return au1xxx_gpio1_direction_input(gpio);
 }
 
-void au1xxx_gpio1_set_inputs(void)
+EXPORT_SYMBOL(au1xxx_gpio_direction_input);
+
+int au1xxx_gpio_direction_output(unsigned gpio, int value)
 {
-	gpio1->pininputen = 0;
+	if (gpio >= AU1XXX_GPIO_BASE)
+#if defined(CONFIG_SOC_AU1000)
+		;
+#else
+		return au1xxx_gpio2_direction_output(gpio, value);
+#endif
+	else
+		return au1xxx_gpio1_direction_output(gpio, value);
 }
 
-EXPORT_SYMBOL(au1xxx_gpio1_set_inputs);
-EXPORT_SYMBOL(au1xxx_gpio_tristate);
-EXPORT_SYMBOL(au1xxx_gpio_write);
-EXPORT_SYMBOL(au1xxx_gpio_read);
+EXPORT_SYMBOL(au1xxx_gpio_direction_output);
diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
index 8fd203d..d51e18f 100644
--- a/arch/mips/au1000/common/platform.c
+++ b/arch/mips/au1000/common/platform.c
@@ -289,7 +289,7 @@
 #endif
 };
 
-int au1xxx_platform_init(void)
+int __init au1xxx_platform_init(void)
 {
 	return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices));
 }
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index 13fe187..a95b377 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -100,18 +100,9 @@
         argptr = prom_getcmdline();
         /* default panel */
         /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
-#ifdef CONFIG_MIPS_HYDROGEN3
-         strcat(argptr, " video=au1100fb:panel:Hydrogen_3_NEC_panel_320x240,nohwcursor");
-#endif
     }
 #endif
 
-#ifdef CONFIG_FB_XPERT98
-	if ((argptr = strstr(argptr, "video=")) == NULL) {
-		argptr = prom_getcmdline();
-		strcat(argptr, " video=atyfb:1024x768-8@70");
-	}
-#endif
 
 #if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
 	/* au1000 does not support vra, au1500 and au1100 do */
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index fa1c62f..8fc2998 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -203,11 +203,7 @@
 /* I haven't found anyone that doesn't use a 12 MHz source clock,
  * but just in case.....
  */
-#ifdef CONFIG_AU1000_SRC_CLK
-#define AU1000_SRC_CLK	CONFIG_AU1000_SRC_CLK
-#else
 #define AU1000_SRC_CLK	12000000
-#endif
 
 /*
  * We read the real processor speed from the PLL.  This is important
@@ -247,33 +243,8 @@
 		au_writel (0, SYS_TOYWRITE);
 		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
 
-#if defined(CONFIG_AU1000_USE32K)
-		{
-			unsigned long start, end, count;
-
-			start = au_readl(SYS_RTCREAD);
-			start += 2;
-			/* wait for the beginning of a new tick
-			*/
-			while (au_readl(SYS_RTCREAD) < start);
-
-			/* Start r4k counter.
-			*/
-			write_c0_count(0);
-
-			/* Wait 0.5 seconds.
-			*/
-			end = start + (32768 / trim_divide)/2;
-
-			while (end > au_readl(SYS_RTCREAD));
-
-			count = read_c0_count();
-			cpu_speed = count * 2;
-		}
-#else
 		cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) *
 			AU1000_SRC_CLK;
-#endif
 	}
 	else {
 		/* The 32KHz oscillator isn't running, so assume there
diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c
index 1fae39a..6131b56 100644
--- a/arch/mips/au1000/pb1100/init.c
+++ b/arch/mips/au1000/pb1100/init.c
@@ -53,7 +53,7 @@
 
 	prom_argc = fw_arg0;
 	prom_argv = (char **) fw_arg1;
-	prom_envp = (int *) fw_arg3;
+	prom_envp = (char **) fw_arg3;
 
 	mips_machgroup = MACH_GROUP_ALCHEMY;
 	mips_machtype = MACH_PB1100;
diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c
index 043302b..eea2092 100644
--- a/arch/mips/au1000/pb1200/board_setup.c
+++ b/arch/mips/au1000/pb1200/board_setup.c
@@ -131,14 +131,7 @@
 	/* The Pb1200 development board uses external MUX for PSC0 to
 	support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
 	*/
-#if defined(CONFIG_AU1XXX_PSC_SPI) && defined(CONFIG_I2C_AU1550)
-	#error I2C and SPI are mutually exclusive. Both are physically connected to PSC0.\
-			Refer to Pb1200/Db1200 documentation.
-#elif defined( CONFIG_AU1XXX_PSC_SPI )
-	bcsr->resets |= BCSR_RESETS_PCS0MUX;
-	/*Hard Coding Value to enable Temp Sensors [bit 14] Value for SOC Au1200. Pls refer documentation*/
-	  bcsr->resets =0x900f;
-#elif defined( CONFIG_I2C_AU1550 )
+#ifdef CONFIG_I2C_AU1550
 	bcsr->resets &= (~BCSR_RESETS_PCS0MUX);
 #endif
 	au_sync();
diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c
index 0ffdb4f..c9b6556 100644
--- a/arch/mips/au1000/pb1500/board_setup.c
+++ b/arch/mips/au1000/pb1500/board_setup.c
@@ -125,7 +125,7 @@
 		au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
 	}
 	/* Put the clock in BCD mode */
-	if (readl(0xac00002C) & 0x4) { /* reg B */
+	if (au_readl(0xac00002C) & 0x4) { /* reg B */
 		au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
 		au_sync();
 	}
diff --git a/arch/mips/cobalt/pci.c b/arch/mips/cobalt/pci.c
index d91027f..cfce7af 100644
--- a/arch/mips/cobalt/pci.c
+++ b/arch/mips/cobalt/pci.c
@@ -35,6 +35,7 @@
 	.mem_resource	= &cobalt_mem_resource,
 	.io_resource	= &cobalt_io_resource,
 	.io_offset	= 0 - GT_DEF_PCI0_IO_BASE,
+	.io_map_base	= CKSEG1ADDR(GT_DEF_PCI0_IO_BASE),
 };
 
 static int __init cobalt_pci_init(void)
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 39e2513..129e2c9 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 CONFIG_MIPS_ATLAS=y
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 4713a13..dc3e1bf 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 5e7ae56..4c70312 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 631b213..c8c0578 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,44 +1,24 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc7
-# Wed Apr 18 14:25:45 2007
+# Linux kernel version: 2.6.22-rc2
+# Fri May 25 11:17:29 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MACH_ALCHEMY is not set
 # CONFIG_BASLER_EXCITE is not set
 CONFIG_MIPS_COBALT=y
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
 # CONFIG_WR_PPMC is not set
 # CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
@@ -138,7 +118,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+CONFIG_ZONE_DMA_FLAG=0
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -178,6 +158,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 # CONFIG_BLK_DEV_INITRD is not set
@@ -193,14 +174,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -233,16 +219,13 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_MMU=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -268,7 +251,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -300,11 +282,11 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -345,13 +327,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -370,10 +355,6 @@
 #
 CONFIG_CONNECTOR=y
 CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
@@ -418,7 +399,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -445,16 +425,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -479,87 +456,145 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-CONFIG_SGI_IOC4=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=y
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_BLK_DEV_TC86C001=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
 
 #
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+# SCSI support type (disk, tape, CD-ROM)
 #
-# CONFIG_ATA is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+CONFIG_PATA_VIA=y
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -570,10 +605,14 @@
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -594,24 +633,7 @@
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -639,35 +661,8 @@
 # CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Token Ring devices
@@ -675,18 +670,16 @@
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -711,10 +704,7 @@
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
@@ -726,18 +716,23 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_COBALT_BTNS=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_INPUT_POLLDEV=y
 
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -754,7 +749,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -773,16 +768,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 CONFIG_COBALT_LCD=y
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_DRM is not set
@@ -792,10 +782,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -808,12 +795,7 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
 # Multifunction device drivers
@@ -824,16 +806,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -868,10 +853,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -912,18 +893,30 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
 #
 CONFIG_RTC_DRV_CMOS=y
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+
+#
 # DMA Engine support
 #
 # CONFIG_DMA_ENGINE is not set
@@ -937,14 +930,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -952,8 +937,13 @@
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
 # CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
@@ -969,7 +959,7 @@
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
+# CONFIG_FUSE_FS is not set
 CONFIG_GENERIC_ACL=y
 
 #
@@ -1003,7 +993,6 @@
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -1021,13 +1010,23 @@
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_ACL_SUPPORT=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1051,10 +1050,7 @@
 #
 # Distributed Lock Manager
 #
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
 
 #
 # Profiling support
@@ -1072,72 +1068,30 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 10f6af4..ec60beb 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 4b08629..f3c25f0 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 820659e..6d400be 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 4050b9b..82aea6e 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 7b35190..8269771 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 5b502a2..a42ab9a 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 4bbdab0..d6e3fff 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 CONFIG_MACH_DECSTATION=y
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index b5714a6a..78f5004 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
index 3044579..b29bff0 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
@@ -951,8 +947,7 @@
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_RTC=m
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
deleted file mode 100644
index c10e4e0..0000000
--- a/arch/mips/configs/ev64120_defconfig
+++ /dev/null
@@ -1,985 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:30 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-CONFIG_MIPS_EV64120=y
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-# CONFIG_EVB_PCI1 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_MIPS_GT64120=y
-# CONFIG_SYSCLK_75 is not set
-# CONFIG_SYSCLK_83 is not set
-CONFIG_SYSCLK_100=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_KMOD is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-CONFIG_SLHC=y
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
-CONFIG_SYS_SUPPORTS_KGDB=y
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=m
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
index 460d7a2..6981059 100644
--- a/arch/mips/configs/excite_defconfig
+++ b/arch/mips/configs/excite_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE_PROTOTYPE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/fulong_defconfig b/arch/mips/configs/fulong_defconfig
new file mode 100644
index 0000000..6ab94d8
--- /dev/null
+++ b/arch/mips/configs/fulong_defconfig
@@ -0,0 +1,1765 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Mon Jun 11 00:23:51 2007
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_LEMOTE_FULONG=y
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_LOONGSON2=y
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_LOONGSON2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+# CONFIG_PAGE_SIZE_4KB is not set
+# CONFIG_PAGE_SIZE_8KB is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_BOARD_SCACHE=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_CPU_HAS_WB=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION="lm32"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_ISA=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_IEEE80211_SOFTMAC is not set
+# CONFIG_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x1fc00000
+CONFIG_MTD_PHYSMAP_LEN=0x80000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# Misc devices
+#
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TC35815 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_IVTV is not set
+# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=y
+# CONFIG_FB_RADEON_I2C is not set
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_VIA82XX=m
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=y
+CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=936
+CONFIG_FAT_DEFAULT_IOCHARSET="utf8"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp936"
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_DEBUG2=y
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+CONFIG_NLS_CODEPAGE_936=y
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 7ec618f..405c9f505 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 9ddc3ef..a9dcbcf 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 8fc1880..a040459 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 9331cb0..8a0b4ac 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 CONFIG_MACH_JAZZ=y
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
@@ -245,7 +241,7 @@
 #
 CONFIG_ISA=y
 CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 1b364cf..9a25e77 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
deleted file mode 100644
index fd4272c..0000000
--- a/arch/mips/configs/lasat200_defconfig
+++ /dev/null
@@ -1,1118 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:34 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-CONFIG_LASAT=y
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_PICVUE=y
-CONFIG_PICVUE_PROC=y
-CONFIG_DS1603=y
-CONFIG_LASAT_SYSCTL=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_MIPS_NILE4=y
-# CONFIG_CPU_BIG_ENDIAN is not set
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
-CONFIG_MIPS_GT64120=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_R5000_CPU_SCACHE=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_LASAT=y
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=m
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 1f64d76..546cb24 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 CONFIG_MIPS_MALTA=y
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index a2db5c2..6abad6f 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 CONFIG_MIPS_SIM=y
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
@@ -496,36 +492,23 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
-# CONFIG_NET_ETHERNET is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_SIM_NET=y
+# CONFIG_DM9000 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index ad5c0bf..4981ce4 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/msp71xx_defconfig b/arch/mips/configs/msp71xx_defconfig
new file mode 100644
index 0000000..adca5f7
--- /dev/null
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -0,0 +1,1493 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21-rc4
+# Thu Apr 26 18:11:29 2007
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+CONFIG_PMC_MSP=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_PMC_MSP4200_EVAL is not set
+# CONFIG_PMC_MSP4200_GW is not set
+# CONFIG_PMC_MSP7120_EVAL is not set
+CONFIG_PMC_MSP7120_GW=y
+# CONFIG_PMC_MSP7120_FPGA is not set
+
+#
+# Options for PMC-Sierra MSP chipsets
+#
+CONFIG_PMC_MSP_EMBEDDED_ROOTFS=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
+CONFIG_BOOT_RAW=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_NO_EXCEPT_FILL=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_MSP_CIC=y
+CONFIG_MSP_USB=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_BKL is not set
+# CONFIG_KEXEC is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION="-pmc"
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PMC_MSP_EVM=y
+CONFIG_MSP_FLASH_MAP_LIMIT_32M=y
+CONFIG_MSP_FLASH_MAP_LIMIT=0x02000000
+CONFIG_MTD_PMC_MSP_RAMROOT=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MSPETH=y
+CONFIG_MSPETH_NAPI=y
+# CONFIG_MSPETH_SKB_RECYCLE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_PMCMSP_GPIO=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_PMCMSP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+CONFIG_PMCTWILED=y
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_SQUASHFS_VMALLOC=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
deleted file mode 100644
index 2854731..0000000
--- a/arch/mips/configs/ocelot_3_defconfig
+++ /dev/null
@@ -1,1283 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:35 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-CONFIG_MOMENCO_OCELOT_3=y
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_RM9000=y
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM9000=y
-CONFIG_WEAK_ORDERING=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-CONFIG_IPV6_MIP6=y
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
-#
-CONFIG_NF_CONNTRACK_IPV6=m
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-CONFIG_FIB_RULES=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
-CONFIG_SCSI_NETLINK=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-# CONFIG_BLK_DEV_SD is not set
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-CONFIG_SCSI_SCAN_ASYNC=y
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-CONFIG_SCSI_FC_ATTRS=m
-CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SCSI_SAS_ATTRS=m
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-
-#
-# SCSI low-level drivers
-#
-CONFIG_ISCSI_TCP=m
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_AIC94XX=m
-# CONFIG_AIC94XX_DEBUG is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-CONFIG_E100=y
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_MV643XX_ETH=y
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-CONFIG_SLHC=m
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EFS_FS=y
-CONFIG_CRAMFS=y
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=m
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="ip=any root=nfs"
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
deleted file mode 100644
index 82ff6fc..0000000
--- a/arch/mips/configs/ocelot_c_defconfig
+++ /dev/null
@@ -1,982 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:36 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-CONFIG_MOMENCO_OCELOT_C=y
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM7000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-# CONFIG_32BIT is not set
-CONFIG_64BIT=y
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_BUILD_ELF64 is not set
-CONFIG_MIPS32_COMPAT=y
-CONFIG_COMPAT=y
-CONFIG_SYSVIPC_COMPAT=y
-CONFIG_MIPS32_O32=y
-CONFIG_MIPS32_N32=y
-CONFIG_BINFMT_ELF32=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=y
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 15a027e..e1db1fb 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 CONFIG_MOMENCO_OCELOT=y
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 37d696c..0028aef 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index b11f0e8..8a1d588 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 2927f38..5581ad2 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index fae16c5..821c1ce 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 CONFIG_PNX8550_JBS=y
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
index cd821e5..0e8bd92 100644
--- a/arch/mips/configs/pnx8550-stb810_defconfig
+++ b/arch/mips/configs/pnx8550-stb810_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 8e8d031..703de00 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
@@ -225,7 +221,7 @@
 #
 CONFIG_ISA=y
 CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
diff --git a/arch/mips/configs/rbhma4200_defconfig b/arch/mips/configs/rbhma4200_defconfig
index 35d6426..20a3852 100644
--- a/arch/mips/configs/rbhma4200_defconfig
+++ b/arch/mips/configs/rbhma4200_defconfig
@@ -24,17 +24,13 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
 # CONFIG_WR_PPMC is not set
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 41011f7..5dbb250 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:39 2007
+# Linux kernel version: 2.6.22-rc5
+# Fri Jun 22 21:39:45 2007
 #
 CONFIG_MIPS=y
 
@@ -9,40 +9,23 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MACH_ALCHEMY is not set
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
 # CONFIG_WR_PPMC is not set
 # CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_MSP is not set
 # CONFIG_PMC_YOSEMITE is not set
 # CONFIG_QEMU is not set
 # CONFIG_MARKEINS is not set
@@ -82,6 +65,8 @@
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
@@ -93,6 +78,7 @@
 #
 # CPU selection
 #
+# CONFIG_CPU_LOONGSON2 is not set
 # CONFIG_CPU_MIPS32_R1 is not set
 # CONFIG_CPU_MIPS32_R2 is not set
 # CONFIG_CPU_MIPS64_R1 is not set
@@ -149,12 +135,12 @@
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
 # CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
 # CONFIG_HZ_1024 is not set
 CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -186,28 +172,35 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
+# CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -244,17 +237,12 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_MMU=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -266,10 +254,7 @@
 #
 # Power management options
 #
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_PM is not set
 
 #
 # Networking
@@ -279,14 +264,9 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -294,7 +274,7 @@
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
@@ -305,130 +285,23 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-CONFIG_IPV6_MIP6=y
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
-#
-CONFIG_NF_CONNTRACK_IPV6=m
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -446,7 +319,6 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -455,15 +327,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-CONFIG_FIB_RULES=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -474,94 +347,13 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
 
 #
 # Parallel port support
@@ -583,93 +375,30 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-CONFIG_SGI_IOC4=m
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=m
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
-CONFIG_RAID_ATTRS=m
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -685,6 +414,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -699,36 +429,15 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
+# CONFIG_TUN is not set
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
@@ -747,6 +456,7 @@
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
+CONFIG_TC35815=y
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
@@ -761,91 +471,20 @@
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-CONFIG_IPW2200=m
-# CONFIG_IPW2200_MONITOR is not set
-# CONFIG_IPW2200_QOS is not set
-# CONFIG_IPW2200_DEBUG is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_BCM43XX is not set
-# CONFIG_ZD1211RW is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
+# CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -864,57 +503,18 @@
 #
 # Input device support
 #
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
 
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
 # Character devices
 #
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -926,11 +526,12 @@
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_TXX9=y
 CONFIG_HAS_TXX9_SERIAL=y
 CONFIG_SERIAL_TXX9_NR_UARTS=6
-# CONFIG_SERIAL_TXX9_CONSOLE is not set
-# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+CONFIG_SERIAL_TXX9_CONSOLE=y
+CONFIG_SERIAL_TXX9_STDSERIAL=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -940,15 +541,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_DRM is not set
@@ -958,229 +554,78 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
 # SPI support
 #
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_TXX9=y
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_AT25=y
+# CONFIG_SPI_SPIDEV is not set
 
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-CONFIG_FB_ATY=y
-CONFIG_FB_ATY_CT=y
-# CONFIG_FB_ATY_GENERIC_LCD is not set
-# CONFIG_FB_ATY_GX is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
 # Sound
 #
 # CONFIG_SOUND is not set
 
 #
-# HID Devices
-#
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-
-#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_OHCI_HCD is not set
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
+# CONFIG_USB is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
-#
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-CONFIG_USB_YEALINK=m
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=y
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
-
-#
-# USB DSL modem support
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1208,7 +653,43 @@
 #
 # Real Time Clock
 #
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_RS5C348=y
+# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
 
 #
 # DMA Engine support
@@ -1224,38 +705,15 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
 # CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
+# CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1265,26 +723,21 @@
 # CONFIG_QUOTA is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
 #
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+# CONFIG_ISO9660_FS is not set
 # CONFIG_UDF_FS is not set
 
 #
 # DOS/FAT/NT Filesystems
 #
-CONFIG_FAT_FS=y
 # CONFIG_MSDOS_FS is not set
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1298,7 +751,7 @@
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1310,16 +763,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -1334,19 +778,16 @@
 # CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+# CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1362,54 +803,12 @@
 #
 # Native Language Support
 #
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
 
 #
 # Distributed Lock Manager
 #
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
 
 #
 # Profiling support
@@ -1427,7 +826,6 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 CONFIG_SYS_SUPPORTS_KGDB=y
@@ -1441,62 +839,17 @@
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
+# CONFIG_LIBCRC32C is not set
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 5593cde..a5dc5cb 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
@@ -255,7 +251,7 @@
 CONFIG_ISA=y
 # CONFIG_EISA is not set
 CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 6c4f09a..98a9140 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 988b9cd..69c08b2 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 CONFIG_MIPS_SEAD=y
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig
index 8b1675c..5d4fc0e 100644
--- a/arch/mips/configs/tb0219_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index b5be8b74..1b92b48 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 8bb6be4..5b77c7a 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 8f019ff..94a4f94 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index 52b48c0..e38bd9b 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 6824606..f342d8c 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
@@ -596,8 +592,6 @@
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index 23fd3b8..4864b8a 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,8 @@
 # Makefile for NEC DDB-Vrc5477 board
 #
 
-obj-y	 		+= irq.o irq_5477.o setup.o lcd44780.o
+obj-y	 		+= ddb5477-platform.o irq.o irq_5477.o setup.o \
+			   lcd44780.o
 
 obj-$(CONFIG_RUNTIME_DEBUG) 	+= debug.o
 obj-$(CONFIG_KGDB)		+= kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c b/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c
new file mode 100644
index 0000000..c16020a
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c
@@ -0,0 +1,49 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ddb5xxx/ddb5477.h>
+
+#define DDB_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+#define DDB5477_PORT(base, int)						\
+{									\
+	.mapbase	= base,						\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_MEM,					\
+	.flags		= DDB_UART_FLAGS,				\
+	.regshift	= 3,						\
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+	DDB5477_PORT(0xbfa04200, VRC5477_IRQ_UART0),
+	DDB5477_PORT(0xbfa04240, VRC5477_IRQ_UART1),
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the NEC DDB5477");
diff --git a/arch/mips/dec/prom/console.c b/arch/mips/dec/prom/console.c
index 65419bf..078e1a1 100644
--- a/arch/mips/dec/prom/console.c
+++ b/arch/mips/dec/prom/console.c
@@ -3,7 +3,7 @@
  *
  *	DECstation PROM-based early console support.
  *
- *	Copyright (C) 2004  Maciej W. Rozycki
+ *	Copyright (C) 2004, 2007  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -13,15 +13,35 @@
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #include <asm/dec/prom.h>
 
-void prom_putchar(char c)
+static void __init prom_console_write(struct console *con, const char *s,
+				      unsigned int c)
 {
-	char s[2];
+	char buf[81];
+	unsigned int chunk = sizeof(buf) - 1;
 
-	s[0] = c;
-	s[1] = '\0';
+	while (c > 0) {
+		if (chunk > c)
+			chunk = c;
+		memcpy(buf, s, chunk);
+		buf[chunk] = '\0';
+		prom_printf("%s", buf);
+		s += chunk;
+		c -= chunk;
+	}
+}
 
-	prom_printf( s);
+static struct console promcons __initdata = {
+	.name	= "prom",
+	.write	= prom_console_write,
+	.flags	= CON_BOOT | CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+void __init register_prom_console(void)
+{
+	register_console(&promcons);
 }
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
index a217aaf..808c182 100644
--- a/arch/mips/dec/prom/init.c
+++ b/arch/mips/dec/prom/init.c
@@ -86,7 +86,7 @@
 
 void __init prom_init(void)
 {
-	extern void ATTRIB_NORET dec_machine_halt(void);
+	extern void dec_machine_halt(void);
 	static char cpu_msg[] __initdata =
 		"Sorry, this kernel is compiled for a wrong CPU type!\n";
 	s32 argc = fw_arg0;
@@ -103,6 +103,9 @@
 	if (prom_is_rex(magic))
 		rex_clear_cache();
 
+	/* Register the early console.  */
+	register_prom_console();
+
 	/* Were we compiled with the right CPU option? */
 #if defined(CONFIG_CPU_R3000)
 	if ((current_cpu_data.cputype == CPU_R4000SC) ||
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
index 5639722..c15a879 100644
--- a/arch/mips/dec/reset.c
+++ b/arch/mips/dec/reset.c
@@ -9,26 +9,26 @@
 
 #include <asm/addrspace.h>
 
-typedef void ATTRIB_NORET (* noret_func_t)(void);
+typedef void __noreturn (* noret_func_t)(void);
 
-static inline void ATTRIB_NORET back_to_prom(void)
+static inline void __noreturn back_to_prom(void)
 {
 	noret_func_t func = (void *)CKSEG1ADDR(0x1fc00000);
 
 	func();
 }
 
-void ATTRIB_NORET dec_machine_restart(char *command)
+void __noreturn dec_machine_restart(char *command)
 {
 	back_to_prom();
 }
 
-void ATTRIB_NORET dec_machine_halt(void)
+void __noreturn dec_machine_halt(void)
 {
 	back_to_prom();
 }
 
-void ATTRIB_NORET dec_machine_power_off(void)
+void __noreturn dec_machine_power_off(void)
 {
     /* DECstations don't have a software power switch */
 	back_to_prom();
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 41211f8..b3b6e58 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c
index b29a447..2f060e1 100644
--- a/arch/mips/emma2rh/markeins/setup.c
+++ b/arch/mips/emma2rh/markeins/setup.c
@@ -115,30 +115,6 @@
 
 static void inline __init markeins_sio_setup(void)
 {
-#ifdef CONFIG_KGDB_8250
-	struct uart_port emma_port;
-
-	memset(&emma_port, 0, sizeof(emma_port));
-
-	emma_port.flags =
-	    UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	emma_port.iotype = UPIO_MEM;
-	emma_port.regshift = 4;	/* I/O addresses are every 8 bytes */
-	emma_port.uartclk = 18544000;	/* Clock rate of the chip */
-
-	emma_port.line = 0;
-	emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3);
-	emma_port.membase = (u8*)emma_port.mapbase;
-	early_serial_setup(&emma_port);
-
-	emma_port.line = 1;
-	emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3);
-	emma_port.membase = (u8*)emma_port.mapbase;
-	early_serial_setup(&emma_port);
-
-	emma_port.irq = EMMA2RH_IRQ_PFUR1;
-	kgdb8250_add_port(1, &emma_port);
-#endif
 }
 
 void __init plat_mem_setup(void)
diff --git a/arch/mips/gt64120/ev64120/Kconfig b/arch/mips/gt64120/ev64120/Kconfig
deleted file mode 100644
index d691762..0000000
--- a/arch/mips/gt64120/ev64120/Kconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-config EVB_PCI1
-	bool "Enable Second PCI (PCI1)"
-	depends on MIPS_EV64120
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
deleted file mode 100644
index 323b2ce..0000000
--- a/arch/mips/gt64120/ev64120/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-#  Copyright 2000 RidgeRun, Inc.
-#  Author: RidgeRun, Inc.
-#     	glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
-#
-# Makefile for the Galileo EV64120 board.
-#
-
-obj-y	+= irq.o promcon.o reset.o serialGT.o setup.o
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
deleted file mode 100644
index 64e4c80..0000000
--- a/arch/mips/gt64120/ev64120/irq.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Code to handle irqs on GT64120A boards
- *  Derived from mips/orion and Cort <cort@fsmlabs.com>
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/gt64120.h>
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-
-	if (pending & STATUSF_IP4)		/* int2 hardware line (timer) */
-		do_IRQ(4);
-	else if (pending & STATUSF_IP2)		/* int0 hardware line */
-		do_IRQ(GT_INTA);
-	else if (pending & STATUSF_IP5)		/* int3 hardware line */
-		do_IRQ(GT_INTD);
-	else if (pending & STATUSF_IP6)		/* int4 hardware line */
-		do_IRQ(6);
-	else if (pending & STATUSF_IP7)		/* compare int */
-		do_IRQ(7);
-	else
-		spurious_interrupt();
-}
-
-static void disable_ev64120_irq(unsigned int irq_nr)
-{
-	if (irq_nr >= 8) {	// All PCI interrupts are on line 5 or 2
-		clear_c0_status(9 << 10);
-	} else {
-		clear_c0_status(1 << (irq_nr + 8));
-	}
-}
-
-static void enable_ev64120_irq(unsigned int irq_nr)
-{
-	if (irq_nr >= 8)	// All PCI interrupts are on line 5 or 2
-		set_c0_status(9 << 10);
-	else
-		set_c0_status(1 << (irq_nr + 8));
-}
-
-static void end_ev64120_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_ev64120_irq(irq);
-}
-
-static struct irq_chip ev64120_irq_type = {
-	.name		= "EV64120",
-	.ack		= disable_ev64120_irq,
-	.mask		= disable_ev64120_irq,
-	.mask_ack	= disable_ev64120_irq,
-	.unmask		= enable_ev64120_irq,
-	.end		= end_ev64120_irq,
-};
-
-void gt64120_irq_setup(void)
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 */
-	clear_c0_status(ST0_IM);
-
-	/*
-	 * Enable timer.  Other interrupts will be enabled as they are
-	 * registered.
-	 */
-	set_c0_status(IE_IRQ2);
-}
-
-void __init arch_init_irq(void)
-{
-	gt64120_irq_setup();
-}
diff --git a/arch/mips/gt64120/ev64120/promcon.c b/arch/mips/gt64120/ev64120/promcon.c
deleted file mode 100644
index 6e0ecfe..0000000
--- a/arch/mips/gt64120/ev64120/promcon.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Wrap-around code for a console using the
- * SGI PROM io-routines.
- *
- * Copyright (c) 1999 Ulf Carlsson
- *
- * Derived from DECstation promcon.c
- * Copyright (c) 1998 Harald Koerfgen
- */
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-static void prom_console_write(struct console *co, const char *s,
-			       unsigned count)
-{
-	extern int CONSOLE_CHANNEL;	// The default serial port
-	unsigned i;
-
-	for (i = 0; i < count; i++) {
-		if (*s == 10)
-			serial_putc(CONSOLE_CHANNEL, 13);
-		serial_putc(CONSOLE_CHANNEL, *s++);
-	}
-}
-
-static struct console sercons = {
-    .name	= "ttyS",
-    .write	= prom_console_write,
-    .flags	= CON_PRINTBUFFER,
-    .index	= -1,
-};
-
-/*
- *    Register console.
- */
-
-static int gal_serial_console_init(void)
-{
-	//  serial_init();
-	//serial_set(115200);
-
-	register_console(&sercons);
-
-	return 0;
-}
-
-console_initcall(gal_serial_console_init);
diff --git a/arch/mips/gt64120/ev64120/reset.c b/arch/mips/gt64120/ev64120/reset.c
deleted file mode 100644
index 7b9f5e5..0000000
--- a/arch/mips/gt64120/ev64120/reset.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1997 Ralf Baechle
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void galileo_machine_restart(char *command)
-{
-	*(volatile char *) 0xbc000000 = 0x0f;
-	/*
-	 * Ouch, we're still alive ... This time we take the silver bullet ...
-	 * ... and find that we leave the hardware in a state in which the
-	 * kernel in the flush locks up somewhen during of after the PCI
-	 * detection stuff.
-	 */
-	set_c0_status(ST0_BEV | ST0_ERL);
-	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-	flush_cache_all();
-	write_c0_wired(0);
-	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-}
-
-void galileo_machine_halt(void)
-{
-	printk(KERN_NOTICE "You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-
-}
-
-void galileo_machine_power_off(void)
-{
-	galileo_machine_halt();
-}
diff --git a/arch/mips/gt64120/ev64120/serialGT.c b/arch/mips/gt64120/ev64120/serialGT.c
deleted file mode 100644
index 8f0d835..0000000
--- a/arch/mips/gt64120/ev64120/serialGT.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * serialGT.c
- *
- * BRIEF MODULE DESCRIPTION
- *  Low Level Serial Port control for use
- *  with the Galileo EVB64120A MIPS eval board and
- *  its on board two channel 16552 Uart.
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-// Note:
-//   Serial CHANNELS - 0 is the bottom connector of evb64120A.
-//                       (The one that maps to the "B" channel of the
-//                       board's uart)
-//                     1 is the top connector of evb64120A.
-//                       (The one that maps to the "A" channel of the
-//                       board's uart)
-int DEBUG_CHANNEL = 0;		// See Note Above
-int CONSOLE_CHANNEL = 1;	// See Note Above
-
-#define DUART 0xBD000000	/* Base address of Uart. */
-#define CHANNELOFFSET 0x20	/* DUART+CHANNELOFFSET gets you to the ChanA
-				   register set of the 16552 Uart device.
-				   DUART+0 gets you to the ChanB register set.
-				 */
-#define DUART_DELTA 0x4
-#define FIFO_ENABLE 0x07
-#define INT_ENABLE  0x04	/* default interrupt mask */
-
-#define RBR 0x00
-#define THR 0x00
-#define DLL 0x00
-#define IER 0x01
-#define DLM 0x01
-#define IIR 0x02
-#define FCR 0x02
-#define LCR 0x03
-#define MCR 0x04
-#define LSR 0x05
-#define MSR 0x06
-#define SCR 0x07
-
-#define LCR_DLAB 0x80
-#define XTAL 1843200
-#define LSR_THRE 0x20
-#define LSR_BI   0x10
-#define LSR_DR   0x01
-#define MCR_LOOP 0x10
-#define ACCESS_DELAY 0x10000
-
-/******************************
- Routine:
- Description:
- ******************************/
-int inreg(int channel, int reg)
-{
-	int val;
-	val =
-	    *((volatile unsigned char *) DUART +
-	      (channel * CHANNELOFFSET) + (reg * DUART_DELTA));
-	return val;
-}
-
-/******************************
- Routine:
- Description:
- ******************************/
-void outreg(int channel, int reg, unsigned char val)
-{
-	*((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
-	  + (reg * DUART_DELTA)) = val;
-}
-
-/******************************
- Routine:
- Description:
-   Initialize the device driver.
- ******************************/
-void serial_init(int channel)
-{
-	/*
-	 * Configure active port, (CHANNELOFFSET already set.)
-	 *
-	 * Set 8 bits, 1 stop bit, no parity.
-	 *
-	 * LCR<7>       0       divisor latch access bit
-	 * LCR<6>       0       break control (1=send break)
-	 * LCR<5>       0       stick parity (0=space, 1=mark)
-	 * LCR<4>       0       parity even (0=odd, 1=even)
-	 * LCR<3>       0       parity enable (1=enabled)
-	 * LCR<2>       0       # stop bits (0=1, 1=1.5)
-	 * LCR<1:0>     11      bits per character(00=5, 01=6, 10=7, 11=8)
-	 */
-	outreg(channel, LCR, 0x3);
-
-	outreg(channel, FCR, FIFO_ENABLE);	/* Enable the FIFO */
-
-	outreg(channel, IER, INT_ENABLE);	/* Enable appropriate interrupts */
-}
-
-/******************************
- Routine:
- Description:
-   Set the baud rate.
- ******************************/
-void serial_set(int channel, unsigned long baud)
-{
-	unsigned char sav_lcr;
-
-	/*
-	 * Enable access to the divisor latches by setting DLAB in LCR.
-	 *
-	 */
-	sav_lcr = inreg(channel, LCR);
-
-#if 0
-	/*
-	 * Set baud rate
-	 */
-	outreg(channel, LCR, LCR_DLAB | sav_lcr);
-	//  outreg(DLL,(XTAL/(16*2*(baud))-2));
-	outreg(channel, DLL, XTAL / (16 * baud));
-	//  outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
-	outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
-#else
-	/*
-	 * Note: Set baud rate, hardcoded here for rate of 115200
-	 * since became unsure of above "baud rate" algorithm (??).
-	 */
-	outreg(channel, LCR, 0x83);
-	outreg(channel, DLM, 0x00);	// See note above
-	outreg(channel, DLL, 0x02);	// See note above.
-	outreg(channel, LCR, 0x03);
-#endif
-
-	/*
-	 * Restore line control register
-	 */
-	outreg(channel, LCR, sav_lcr);
-}
-
-
-/******************************
- Routine:
- Description:
-   Transmit a character.
- ******************************/
-void serial_putc(int channel, int c)
-{
-	while ((inreg(channel, LSR) & LSR_THRE) == 0);
-	outreg(channel, THR, c);
-}
-
-/******************************
- Routine:
- Description:
-    Read a received character if one is
-    available.  Return -1 otherwise.
- ******************************/
-int serial_getc(int channel)
-{
-	if (inreg(channel, LSR) & LSR_DR) {
-		return inreg(channel, RBR);
-	}
-	return -1;
-}
-
-/******************************
- Routine:
- Description:
-   Used by embedded gdb client. (example; gdb-stub.c)
- ******************************/
-char getDebugChar()
-{
-	int val;
-	while ((val = serial_getc(DEBUG_CHANNEL)) == -1);	// loop until we get a character in.
-	return (char) val;
-}
-
-/******************************
- Routine:
- Description:
-   Used by embedded gdb target. (example; gdb-stub.c)
- ******************************/
-void putDebugChar(char c)
-{
-	serial_putc(DEBUG_CHANNEL, (int) c);
-}
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
deleted file mode 100644
index 477848c..0000000
--- a/arch/mips/gt64120/ev64120/setup.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/pm.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/time.h>
-#include <asm/reboot.h>
-#include <asm/traps.h>
-#include <linux/bootmem.h>
-
-unsigned long gt64120_base = KSEG1ADDR(0x14000000);
-
-/* These functions are used for rebooting or halting the machine*/
-extern void galileo_machine_restart(char *command);
-extern void galileo_machine_halt(void);
-extern void galileo_machine_power_off(void);
-/*
- *This structure holds pointers to the pci configuration space accesses
- *and interrupts allocating routine for device over the PCI
- */
-extern struct pci_ops galileo_pci_ops;
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-/*
- * Initializes basic routines and structures pointers, memory size (as
- * given by the bios and saves the command line.
- */
-
-void __init plat_mem_setup(void)
-{
-	_machine_restart = galileo_machine_restart;
-	_machine_halt = galileo_machine_halt;
-	pm_power_off = galileo_machine_power_off;
-
-	set_io_port_base(KSEG1);
-}
-
-const char *get_system_type(void)
-{
-	return "Galileo EV64120A";
-}
-
-/*
- * Kernel arguments passed by the firmware
- *
- * $a0 - nothing
- * $a1 - holds a pointer to the eprom parameters
- * $a2 - nothing
- */
-
-void __init prom_init(void)
-{
-	mips_machgroup = MACH_GROUP_GALILEO;
-	mips_machtype = MACH_EV64120A;
-
-	add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
index 9f9a33f..1df5fe2 100644
--- a/arch/mips/gt64120/momenco_ocelot/Makefile
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -2,6 +2,6 @@
 # Makefile for Momentum's Ocelot board.
 #
 
-obj-y	 		+= irq.o prom.o reset.o setup.o
+obj-y	 		+= irq.o ocelot-platform.o prom.o reset.o setup.o
 
 obj-$(CONFIG_KGDB)	+= dbg_io.o
diff --git a/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c b/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c
new file mode 100644
index 0000000..81d9031
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c
@@ -0,0 +1,46 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * A NS16552 DUART with a 20MHz crystal.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define OCELOT_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+	{
+		.mapbase	= 0xe0001020,
+		.irq		= 4,
+		.uartclk	= 20000000,
+		.iotype		= UPIO_MEM,
+		.flags		= OCELOT_UART_FLAGS,
+		.regshift	= 2,
+	},
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Momenco Ocelot");
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
index 121188d..ea96552 100644
--- a/arch/mips/gt64120/wrppmc/setup.c
+++ b/arch/mips/gt64120/wrppmc/setup.c
@@ -158,8 +158,8 @@
  */
 void __init prom_init(void)
 {
-	mips_machgroup = MACH_GROUP_GALILEO;
-	mips_machtype = MACH_EV64120A;
+	mips_machgroup = MACH_GROUP_WINDRIVER;
+	mips_machtype = MACH_WRPPMC;
 
 	add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM);
 	add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA);
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index dd9d99b..ae4c402 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the Jazz family specific parts of the kernel
 #
 
-obj-y	 	:= irq.o jazzdma.o reset.o setup.o
+obj-y	 	:= irq.o jazzdma.o jazz-platform.o reset.o setup.o
diff --git a/arch/mips/jazz/jazz-platform.c b/arch/mips/jazz/jazz-platform.c
new file mode 100644
index 0000000..fd73670
--- /dev/null
+++ b/arch/mips/jazz/jazz-platform.c
@@ -0,0 +1,60 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+
+#include <asm/jazz.h>
+
+/*
+ * Confusion ...  It seems the original Microsoft Jazz machine used to have a
+ * 4.096MHz clock for its UART while the MIPS Magnum and Millenium systems
+ * had 8MHz.  The Olivetti M700-10 and the Acer PICA have 1.8432MHz like PCs.
+ */
+#ifdef CONFIG_OLIVETTI_M700
+#define JAZZ_BASE_BAUD 1843200
+#else
+#define JAZZ_BASE_BAUD	8000000	/* 3072000 */
+#endif
+
+#define JAZZ_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+#define JAZZ_PORT(base, int)						\
+{									\
+	.mapbase	= base,						\
+	.irq		= int,						\
+	.uartclk	= JAZZ_BASE_BAUD,				\
+	.iotype		= UPIO_MEM,					\
+	.flags		= JAZZ_UART_FLAGS,				\
+	.regshift	= 0,						\
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+	JAZZ_PORT(JAZZ_SERIAL1_BASE, JAZZ_SERIAL1_IRQ),
+	JAZZ_PORT(JAZZ_SERIAL2_BASE, JAZZ_SERIAL2_IRQ),
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Jazz family");
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index d848f1a..81ec559 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -54,7 +54,7 @@
 		.start	= 0x40,
 		.end	= 0x5f,
 		.name	= "timer",
-		.end	= IORESOURCE_BUSY
+		.flags	= IORESOURCE_BUSY
 	}, {
 		.start	= 0x80,
 		.end	= 0x8f,
diff --git a/arch/mips/jmr3927/rbhma3100/kgdb_io.c b/arch/mips/jmr3927/rbhma3100/kgdb_io.c
index 2604f2c..342579c 100644
--- a/arch/mips/jmr3927/rbhma3100/kgdb_io.c
+++ b/arch/mips/jmr3927/rbhma3100/kgdb_io.c
@@ -36,7 +36,7 @@
 #define TIMEOUT       0xffffff
 
 static int remoteDebugInitialized = 0;
-static void debugInit(int baud)
+static void debugInit(int baud);
 
 int putDebugChar(unsigned char c)
 {
diff --git a/arch/mips/kernel/8250-platform.c b/arch/mips/kernel/8250-platform.c
new file mode 100644
index 0000000..cbf3fe2
--- /dev/null
+++ b/arch/mips/kernel/8250-platform.c
@@ -0,0 +1,47 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(base, int)							\
+{									\
+	.iobase		= base,						\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_PORT,					\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,		\
+	.regshift	= 0,						\
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+	PORT(0x3F8, 4),
+	PORT(0x2F8, 3),
+	PORT(0x3E8, 4),
+	PORT(0x2E8, 3),
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250 UART probe driver");
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 4924626..5c8085b 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -14,14 +14,15 @@
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
+obj-$(CONFIG_CPU_LOONGSON2)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS32)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS64)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R3000)		+= r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_TX49XX)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R4000)		+= r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_VR41XX)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R4300)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R4X00)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R5000)		+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R6000)		+= r6000_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R5432)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R8000)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_RM7000)	+= r4k_fpu.o r4k_switch.o
@@ -29,13 +30,14 @@
 obj-$(CONFIG_CPU_NEVADA)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R10000)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_SB1)		+= r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_MIPS32)	+= r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_MIPS64)	+= r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_R6000)		+= r6000_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
+obj-$(CONFIG_CPU_TX49XX)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_VR41XX)	+= r4k_fpu.o r4k_switch.o
 
 obj-$(CONFIG_SMP)		+= smp.o
 
 obj-$(CONFIG_MIPS_MT)		+= mips-mt.o
+obj-$(CONFIG_MIPS_MT_FPAFF)	+= mips-mt-fpaff.o
 obj-$(CONFIG_MIPS_MT_SMTC)	+= smtc.o smtc-asm.o smtc-proc.o
 obj-$(CONFIG_MIPS_MT_SMP)	+= smp-mt.o
 
@@ -47,7 +49,6 @@
 obj-$(CONFIG_IRQ_CPU)		+= irq_cpu.o
 obj-$(CONFIG_IRQ_CPU_RM7K)	+= irq-rm7000.o
 obj-$(CONFIG_IRQ_CPU_RM9K)	+= irq-rm9000.o
-obj-$(CONFIG_IRQ_MV64340)	+= irq-mv6434x.o
 obj-$(CONFIG_MIPS_BOARDS_GEN)	+= irq-msc01.o
 
 obj-$(CONFIG_32BIT)		+= scall32-o32.o
@@ -62,9 +63,11 @@
 
 obj-$(CONFIG_64BIT)		+= cpu-bugs64.o
 
-obj-$(CONFIG_I8253)		+= i8253.o
+obj-$(CONFIG_PCSPEAKER)		+= pcspeaker.o
 
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
+
+obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)	+= 8250-platform.o
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 76fd3f2..6b5df8b 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -22,7 +22,8 @@
  */
 int __compute_return_epc(struct pt_regs *regs)
 {
-	unsigned int *addr, bit, fcr31, dspcontrol;
+	unsigned int __user *addr;
+	unsigned int bit, fcr31, dspcontrol;
 	long epc;
 	union mips_instruction insn;
 
@@ -33,7 +34,7 @@
 	/*
 	 * Read the instruction
 	 */
-	addr = (unsigned int *) epc;
+	addr = (unsigned int __user *) epc;
 	if (__get_user(insn.word, addr)) {
 		force_sig(SIGSEGV, current);
 		return -EFAULT;
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index ab755ea..c6b8b07 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -137,14 +137,24 @@
 	case CPU_4KEC:
 	case CPU_4KSC:
 	case CPU_5KC:
-/*	case CPU_20KC:*/
-	case CPU_24K:
 	case CPU_25KF:
-	case CPU_34K:
-	case CPU_74K:
- 	case CPU_PR4450:
+	case CPU_PR4450:
 		cpu_wait = r4k_wait;
 		break;
+
+	case CPU_24K:
+	case CPU_34K:
+		cpu_wait = r4k_wait;
+		if (read_c0_config7() & MIPS_CONF7_WII)
+			cpu_wait = r4k_wait_irqoff;
+		break;
+
+	case CPU_74K:
+		cpu_wait = r4k_wait;
+		if ((c->processor_id & 0xff) >= PRID_REV_ENCODE_332(2, 1, 0))
+			cpu_wait = r4k_wait_irqoff;
+		break;
+
 	case CPU_TX49XX:
 		cpu_wait = r4k_wait_irqoff;
 		break;
@@ -156,6 +166,17 @@
 		if (allow_au1k_wait)
 			cpu_wait = au1k_wait;
 		break;
+	case CPU_20KC:
+		/*
+		 * WAIT on Rev1.0 has E1, E2, E3 and E16.
+		 * WAIT on Rev2.0 and Rev3.0 has E16.
+		 * Rev3.1 WAIT is nop, why bother
+		 */
+		if ((c->processor_id & 0xff) <= 0x64)
+			break;
+
+		cpu_wait = r4k_wait;
+		break;
 	case CPU_RM9000:
 		if ((c->processor_id & 0x00ff) >= 0x40)
 			cpu_wait = r4k_wait;
@@ -165,9 +186,29 @@
 	}
 }
 
+static inline void check_errata(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	switch (c->cputype) {
+	case CPU_34K:
+		/*
+		 * Erratum "RPS May Cause Incorrect Instruction Execution"
+		 * This code only handles VPE0, any SMP/SMTC/RTOS code
+		 * making use of VPE1 will be responsable for that VPE.
+		 */
+		if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2)
+			write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS);
+		break;
+	default:
+		break;
+	}
+}
+
 void __init check_bugs32(void)
 {
 	check_wait();
+	check_errata();
 }
 
 /*
@@ -464,6 +505,14 @@
 		             MIPS_CPU_LLSC;
 		c->tlbsize = 64;
 		break;
+	case PRID_IMP_LOONGSON2:
+		c->cputype = CPU_LOONGSON2;
+		c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS |
+			     MIPS_CPU_FPU | MIPS_CPU_LLSC |
+			     MIPS_CPU_32FPR;
+		c->tlbsize = 64;
+		break;
 	}
 }
 
@@ -567,6 +616,8 @@
 		c->options |= MIPS_CPU_VEIC;
 	if (config3 & MIPS_CONF3_MT)
 	        c->ases |= MIPS_ASE_MIPSMT;
+	if (config3 & MIPS_CONF3_ULRI)
+		c->options |= MIPS_CPU_ULRI;
 
 	return config3 & MIPS_CONF_M;
 }
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 686249c..e29598a 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -84,6 +84,7 @@
 	LONG_S	sp, TI_REGS($28)
 	jal	deferred_smtc_ipi
 	LONG_S	s0, TI_REGS($28)
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 /* Re-arm any temporarily masked interrupts not explicitly "acked" */
 	mfc0	v0, CP0_TCSTATUS
 	ori	v1, v0, TCSTATUS_IXMT
@@ -110,6 +111,7 @@
 	_ehb
 	xor	t0, t0, t3
 	mtc0	t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
 #endif /* CONFIG_MIPS_MT_SMTC */
 	.set	noat
 	RESTORE_TEMP
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 297bd56..c0f19d6 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -243,9 +243,11 @@
 	 */
 	mfc0	t1, CP0_STATUS
 	and	t0, a0, t1
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 	mfc0	t2, CP0_TCCONTEXT
 	or	t0, t0, t2
 	mtc0	t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
 	xor	t1, t1, t0
 	mtc0	t1, CP0_STATUS
 	_ehb
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 6f57ca4..f78538e 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/threads.h>
 
+#include <asm/addrspace.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/irqflags.h>
@@ -129,24 +130,25 @@
 #endif
 	.endm
 
+#ifndef CONFIG_NO_EXCEPT_FILL
 	/*
 	 * Reserved space for exception handlers.
 	 * Necessary for machines which link their kernels at KSEG0.
 	 */
 	.fill	0x400
+#endif
 
 EXPORT(stext)					# used for profiling
 EXPORT(_stext)
 
-#ifdef CONFIG_MIPS_SIM
+#ifdef CONFIG_BOOT_RAW
 	/*
 	 * Give us a fighting chance of running if execution beings at the
 	 * kernel load address.  This is needed because this platform does
 	 * not have a ELF loader yet.
 	 */
-	j	kernel_entry
-#endif
 	__INIT
+#endif
 
 NESTED(kernel_entry, 16, sp)			# kernel entry point
 
@@ -197,9 +199,7 @@
 	j		start_kernel
 	END(kernel_entry)
 
-#ifdef CONFIG_QEMU
 	__INIT
-#endif
 
 #ifdef CONFIG_SMP
 /*
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
deleted file mode 100644
index 3dd5618..0000000
--- a/arch/mips/kernel/irq-mv6434x.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/mv643xx.h>
-#include <linux/sched.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/marvell.h>
-
-static unsigned int irq_base;
-
-static inline int ls1bit32(unsigned int x)
-{
-	int b = 31, s;
-
-	s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
-	s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
-	s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
-	s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
-	s =  1; if (x <<  1 == 0) s = 0; b -= s;
-
-        return b;
-}
-
-/* mask off an interrupt -- 1 is enable, 0 is disable */
-static inline void mask_mv64340_irq(unsigned int irq)
-{
-	uint32_t value;
-
-	if (irq < (irq_base + 32)) {
-		value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
-		value &= ~(1 << (irq - irq_base));
-		MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
-	} else {
-		value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
-		value &= ~(1 << (irq - irq_base - 32));
-		MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
-	}
-}
-
-/* unmask an interrupt -- 1 is enable, 0 is disable */
-static inline void unmask_mv64340_irq(unsigned int irq)
-{
-	uint32_t value;
-
-	if (irq < (irq_base + 32)) {
-		value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
-		value |= 1 << (irq - irq_base);
-		MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
-	} else {
-		value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
-		value |= 1 << (irq - irq_base - 32);
-		MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
-	}
-}
-
-/*
- * Interrupt handler for interrupts coming from the Marvell chip.
- * It could be built in ethernet ports etc...
- */
-void ll_mv64340_irq(void)
-{
-	unsigned int irq_src_low, irq_src_high;
- 	unsigned int irq_mask_low, irq_mask_high;
-
-	/* read the interrupt status registers */
-	irq_mask_low = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
-	irq_mask_high = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
-	irq_src_low = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW);
-	irq_src_high = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH);
-
-	/* mask for just the interrupts we want */
-	irq_src_low &= irq_mask_low;
-	irq_src_high &= irq_mask_high;
-
-	if (irq_src_low)
-		do_IRQ(ls1bit32(irq_src_low) + irq_base);
-	else
-		do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
-}
-
-struct irq_chip mv64340_irq_type = {
-	.name = "MV-64340",
-	.ack = mask_mv64340_irq,
-	.mask = mask_mv64340_irq,
-	.mask_ack = mask_mv64340_irq,
-	.unmask = unmask_mv64340_irq,
-};
-
-void __init mv64340_irq_init(unsigned int base)
-{
-	int i;
-
-	for (i = base; i < base + 64; i++)
-		set_irq_chip_and_handler(i, &mv64340_irq_type,
-					 handle_level_irq);
-
-	irq_base = base;
-}
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 37849ed..06e04da 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -556,6 +556,16 @@
 			flags);
 }
 
+asmlinkage long sys32_fadvise64_64(int fd, int __pad,
+	unsigned long a2, unsigned long a3,
+	unsigned long a4, unsigned long a5,
+	int flags)
+{
+	return sys_fadvise64_64(fd,
+			merge_64(a2, a3), merge_64(a4, a5),
+			flags);
+}
+
 save_static_function(sys32_clone);
 __attribute_used__ noinline static int
 _sys32_clone(nabi_no_regargs struct pt_regs regs)
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
new file mode 100644
index 0000000..ede5d73d
--- /dev/null
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -0,0 +1,176 @@
+/*
+ * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/security.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+
+/*
+ * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
+ */
+cpumask_t mt_fpu_cpumask;
+
+static int fpaff_threshold = -1;
+unsigned long mt_fpemul_threshold = 0;
+
+/*
+ * Replacement functions for the sys_sched_setaffinity() and
+ * sys_sched_getaffinity() system calls, so that we can integrate
+ * FPU affinity with the user's requested processor affinity.
+ * This code is 98% identical with the sys_sched_setaffinity()
+ * and sys_sched_getaffinity() system calls, and should be
+ * updated when kernel/sched.c changes.
+ */
+
+/*
+ * find_process_by_pid - find a process with a matching PID value.
+ * used in sys_sched_set/getaffinity() in kernel/sched.c, so
+ * cloned here.
+ */
+static inline struct task_struct *find_process_by_pid(pid_t pid)
+{
+	return pid ? find_task_by_pid(pid) : current;
+}
+
+
+/*
+ * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	cpumask_t new_mask;
+	cpumask_t effective_mask;
+	int retval;
+	struct task_struct *p;
+
+	if (len < sizeof(new_mask))
+		return -EINVAL;
+
+	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+		return -EFAULT;
+
+	lock_cpu_hotplug();
+	read_lock(&tasklist_lock);
+
+	p = find_process_by_pid(pid);
+	if (!p) {
+		read_unlock(&tasklist_lock);
+		unlock_cpu_hotplug();
+		return -ESRCH;
+	}
+
+	/*
+	 * It is not safe to call set_cpus_allowed with the
+	 * tasklist_lock held.  We will bump the task_struct's
+	 * usage count and drop tasklist_lock before invoking
+	 * set_cpus_allowed.
+	 */
+	get_task_struct(p);
+
+	retval = -EPERM;
+	if ((current->euid != p->euid) && (current->euid != p->uid) &&
+			!capable(CAP_SYS_NICE)) {
+		read_unlock(&tasklist_lock);
+		goto out_unlock;
+	}
+
+	retval = security_task_setscheduler(p, 0, NULL);
+	if (retval)
+		goto out_unlock;
+
+	/* Record new user-specified CPU set for future reference */
+	p->thread.user_cpus_allowed = new_mask;
+
+	/* Unlock the task list */
+	read_unlock(&tasklist_lock);
+
+	/* Compute new global allowed CPU set if necessary */
+	if ((p->thread.mflags & MF_FPUBOUND)
+	&& cpus_intersects(new_mask, mt_fpu_cpumask)) {
+		cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
+		retval = set_cpus_allowed(p, effective_mask);
+	} else {
+		p->thread.mflags &= ~MF_FPUBOUND;
+		retval = set_cpus_allowed(p, new_mask);
+	}
+
+
+out_unlock:
+	put_task_struct(p);
+	unlock_cpu_hotplug();
+	return retval;
+}
+
+/*
+ * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	unsigned int real_len;
+	cpumask_t mask;
+	int retval;
+	struct task_struct *p;
+
+	real_len = sizeof(mask);
+	if (len < real_len)
+		return -EINVAL;
+
+	lock_cpu_hotplug();
+	read_lock(&tasklist_lock);
+
+	retval = -ESRCH;
+	p = find_process_by_pid(pid);
+	if (!p)
+		goto out_unlock;
+	retval = security_task_getscheduler(p);
+	if (retval)
+		goto out_unlock;
+
+	cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+
+out_unlock:
+	read_unlock(&tasklist_lock);
+	unlock_cpu_hotplug();
+	if (retval)
+		return retval;
+	if (copy_to_user(user_mask_ptr, &mask, real_len))
+		return -EFAULT;
+	return real_len;
+}
+
+
+static int __init fpaff_thresh(char *str)
+{
+	get_option(&str, &fpaff_threshold);
+	return 1;
+}
+__setup("fpaff=", fpaff_thresh);
+
+/*
+ * FPU Use Factor empirically derived from experiments on 34K
+ */
+#define FPUSEFACTOR 333
+
+static __init int mt_fp_affinity_init(void)
+{
+	if (fpaff_threshold >= 0) {
+		mt_fpemul_threshold = fpaff_threshold;
+	} else {
+		mt_fpemul_threshold =
+			(FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
+	}
+	printk(KERN_DEBUG "FPU Affinity set after %ld emulations\n",
+	       mt_fpemul_threshold);
+
+	return 0;
+}
+arch_initcall(mt_fp_affinity_init);
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index ba01800..1a7d892 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -6,7 +6,6 @@
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/cpumask.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/security.h>
@@ -23,149 +22,6 @@
 #include <asm/cacheflush.h>
 
 /*
- * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
- */
-
-cpumask_t mt_fpu_cpumask;
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-
-#include <linux/cpu.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-
-unsigned long mt_fpemul_threshold = 0;
-
-/*
- * Replacement functions for the sys_sched_setaffinity() and
- * sys_sched_getaffinity() system calls, so that we can integrate
- * FPU affinity with the user's requested processor affinity.
- * This code is 98% identical with the sys_sched_setaffinity()
- * and sys_sched_getaffinity() system calls, and should be
- * updated when kernel/sched.c changes.
- */
-
-/*
- * find_process_by_pid - find a process with a matching PID value.
- * used in sys_sched_set/getaffinity() in kernel/sched.c, so
- * cloned here.
- */
-static inline struct task_struct *find_process_by_pid(pid_t pid)
-{
-	return pid ? find_task_by_pid(pid) : current;
-}
-
-
-/*
- * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
- */
-asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
-				      unsigned long __user *user_mask_ptr)
-{
-	cpumask_t new_mask;
-	cpumask_t effective_mask;
-	int retval;
-	struct task_struct *p;
-
-	if (len < sizeof(new_mask))
-		return -EINVAL;
-
-	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
-		return -EFAULT;
-
-	lock_cpu_hotplug();
-	read_lock(&tasklist_lock);
-
-	p = find_process_by_pid(pid);
-	if (!p) {
-		read_unlock(&tasklist_lock);
-		unlock_cpu_hotplug();
-		return -ESRCH;
-	}
-
-	/*
-	 * It is not safe to call set_cpus_allowed with the
-	 * tasklist_lock held.  We will bump the task_struct's
-	 * usage count and drop tasklist_lock before invoking
-	 * set_cpus_allowed.
-	 */
-	get_task_struct(p);
-
-	retval = -EPERM;
-	if ((current->euid != p->euid) && (current->euid != p->uid) &&
-			!capable(CAP_SYS_NICE)) {
-		read_unlock(&tasklist_lock);
-		goto out_unlock;
-	}
-
-	retval = security_task_setscheduler(p, 0, NULL);
-	if (retval)
-		goto out_unlock;
-
-	/* Record new user-specified CPU set for future reference */
-	p->thread.user_cpus_allowed = new_mask;
-
-	/* Unlock the task list */
-	read_unlock(&tasklist_lock);
-
-	/* Compute new global allowed CPU set if necessary */
-	if( (p->thread.mflags & MF_FPUBOUND)
-	&& cpus_intersects(new_mask, mt_fpu_cpumask)) {
-		cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
-		retval = set_cpus_allowed(p, effective_mask);
-	} else {
-		p->thread.mflags &= ~MF_FPUBOUND;
-		retval = set_cpus_allowed(p, new_mask);
-	}
-
-
-out_unlock:
-	put_task_struct(p);
-	unlock_cpu_hotplug();
-	return retval;
-}
-
-/*
- * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
- */
-asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
-				      unsigned long __user *user_mask_ptr)
-{
-	unsigned int real_len;
-	cpumask_t mask;
-	int retval;
-	struct task_struct *p;
-
-	real_len = sizeof(mask);
-	if (len < real_len)
-		return -EINVAL;
-
-	lock_cpu_hotplug();
-	read_lock(&tasklist_lock);
-
-	retval = -ESRCH;
-	p = find_process_by_pid(pid);
-	if (!p)
-		goto out_unlock;
-	retval = security_task_getscheduler(p);
-	if (retval)
-		goto out_unlock;
-
-	cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
-
-out_unlock:
-	read_unlock(&tasklist_lock);
-	unlock_cpu_hotplug();
-	if (retval)
-		return retval;
-	if (copy_to_user(user_mask_ptr, &mask, real_len))
-		return -EFAULT;
-	return real_len;
-}
-
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
-/*
  * Dump new MIPS MT state for the core. Does not leave TCs halted.
  * Takes an argument which taken to be a pre-call MVPControl value.
  */
@@ -195,27 +51,31 @@
 	nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
 	ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
 	printk("-- per-VPE State --\n");
-	for(i = 0; i < nvpe; i++) {
-	    for(tc = 0; tc < ntc; tc++) {
+	for (i = 0; i < nvpe; i++) {
+		for (tc = 0; tc < ntc; tc++) {
 			settc(tc);
-		if((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
-		    printk("  VPE %d\n", i);
-		    printk("   VPEControl : %08lx\n", read_vpe_c0_vpecontrol());
-		    printk("   VPEConf0 : %08lx\n", read_vpe_c0_vpeconf0());
-		    printk("   VPE%d.Status : %08lx\n",
-				i, read_vpe_c0_status());
-		    printk("   VPE%d.EPC : %08lx\n", i, read_vpe_c0_epc());
-		    printk("   VPE%d.Cause : %08lx\n", i, read_vpe_c0_cause());
-		    printk("   VPE%d.Config7 : %08lx\n",
-				i, read_vpe_c0_config7());
-		    break; /* Next VPE */
+			if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
+				printk("  VPE %d\n", i);
+				printk("   VPEControl : %08lx\n",
+				       read_vpe_c0_vpecontrol());
+				printk("   VPEConf0 : %08lx\n",
+				       read_vpe_c0_vpeconf0());
+				printk("   VPE%d.Status : %08lx\n",
+				       i, read_vpe_c0_status());
+				printk("   VPE%d.EPC : %08lx\n",
+				       i, read_vpe_c0_epc());
+				printk("   VPE%d.Cause : %08lx\n",
+				       i, read_vpe_c0_cause());
+				printk("   VPE%d.Config7 : %08lx\n",
+				       i, read_vpe_c0_config7());
+				break; /* Next VPE */
+			}
 		}
-	    }
 	}
 	printk("-- per-TC State --\n");
-	for(tc = 0; tc < ntc; tc++) {
+	for (tc = 0; tc < ntc; tc++) {
 		settc(tc);
-		if(read_tc_c0_tcbind() == read_c0_tcbind()) {
+		if (read_tc_c0_tcbind() == read_c0_tcbind()) {
 			/* Are we dumping ourself?  */
 			haltval = 0; /* Then we're not halted, and mustn't be */
 			tcstatval = flags; /* And pre-dump TCStatus is flags */
@@ -310,17 +170,6 @@
 	return 1;
 }
 __setup("ndflush=", ndflush);
-#ifdef CONFIG_MIPS_MT_FPAFF
-static int fpaff_threshold = -1;
-
-static int __init fpaff_thresh(char *str)
-{
-	get_option(&str, &fpaff_threshold);
-	return 1;
-}
-
-__setup("fpaff=", fpaff_thresh);
-#endif /* CONFIG_MIPS_MT_FPAFF */
 
 static unsigned int itc_base = 0;
 
@@ -376,20 +225,6 @@
 	if (mt_n_dflushes != 1)
 		printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes);
 
-#ifdef CONFIG_MIPS_MT_FPAFF
-	/* FPU Use Factor empirically derived from experiments on 34K */
-#define FPUSEFACTOR 333
-
-	if (fpaff_threshold >= 0) {
-		mt_fpemul_threshold = fpaff_threshold;
-	} else {
-		mt_fpemul_threshold =
-			(FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
-	}
-	printk("FPU Affinity set after %ld emulations\n",
-			mt_fpemul_threshold);
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
 	if (itc_base != 0) {
 		/*
 		 * Configure ITC mapping.  This code is very
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/pcspeaker.c
similarity index 100%
rename from arch/mips/kernel/i8253.c
rename to arch/mips/kernel/pcspeaker.c
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 5ddc2e9..ec04f5a 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -14,7 +14,6 @@
 #include <asm/cpu-features.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
-#include <asm/watch.h>
 
 unsigned int vced_count, vcei_count;
 
@@ -84,6 +83,7 @@
 	[CPU_VR4181A]	= "NEC VR4181A",
 	[CPU_SR71000]	= "Sandcraft SR71000",
 	[CPU_PR4450]	= "Philips PR4450",
+	[CPU_LOONGSON2]	= "ICT Loongson-2",
 };
 
 
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 6bdfb5a..8f4cf27c 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -46,7 +46,7 @@
  * power and have a low exit latency (ie sit in a loop waiting for somebody to
  * say that they'd like to reschedule)
  */
-ATTRIB_NORET void cpu_idle(void)
+void __noreturn cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
@@ -213,7 +213,7 @@
 /*
  * Create a kernel thread
  */
-static ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
+static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
 {
 	do_exit(fn(arg));
 }
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index b5a7b46..893e7bc 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -174,17 +174,9 @@
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
-	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp,(unsigned long __user *) data);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* Read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -313,11 +305,7 @@
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1)
-		    == sizeof(data))
-			break;
-		ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: {
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index cc566cf..d9bfae5 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -85,12 +85,7 @@
 	move	$28, a2
 	cpu_restore_nonscratch a1
 
-#if (_THREAD_SIZE - 32) < 0x10000
-	PTR_ADDIU	t0, $28, _THREAD_SIZE - 32
-#else
-	PTR_LI		t0, _THREAD_SIZE - 32
-	PTR_ADDU	t0, $28
-#endif
+	PTR_ADDU	t0, $28, _THREAD_SIZE - 32
 	set_saved_sp	t0, t1, t2
 #ifdef CONFIG_MIPS_MT_SMTC
 	/* Read-modify-writes of Status must be atomic on a VPE */
@@ -174,7 +169,7 @@
 	or	t0, t1
 	mtc0	t0, CP0_STATUS
 #endif /* CONFIG_MIPS_MT_SMTC */
-	fpu_enable_hazard
+	enable_fpu_hazard
 
 	li	t1, FPU_DEFAULT
 	ctc1	t1, fcr31
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 0c9a9ff..ae985d1 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -657,7 +657,11 @@
 	sys	sys_getcpu		3
 	sys	sys_epoll_pwait		6
 	sys	sys_ioprio_set		3
-	sys	sys_ioprio_get		2
+	sys	sys_ioprio_get		2	/* 4315 */
+	sys	sys_utimensat		4
+	sys	sys_signalfd		3
+	sys	sys_timerfd		4
+	sys	sys_eventfd		1
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 23f3b11..7bcd5a1 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -473,4 +473,8 @@
 	PTR	sys_epoll_pwait
 	PTR	sys_ioprio_set
 	PTR	sys_ioprio_get
+	PTR	sys_utimensat			/* 5275 */
+	PTR	sys_signalfd
+	PTR	sys_timerfd
+	PTR	sys_eventfd
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 6eac283..532a2f3 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -299,7 +299,7 @@
 	PTR	sys_ni_syscall			/* res. for afs_syscall */
 	PTR	sys_ni_syscall			/* res. for security */
 	PTR	sys_gettid
-	PTR	sys32_readahead
+	PTR	sys_readahead
 	PTR	sys_setxattr			/* 6180 */
 	PTR	sys_lsetxattr
 	PTR	sys_fsetxattr
@@ -399,4 +399,8 @@
 	PTR	compat_sys_epoll_pwait
 	PTR	sys_ioprio_set
 	PTR	sys_ioprio_get
+	PTR	compat_sys_utimensat
+	PTR	compat_sys_signalfd		/* 5280 */
+	PTR	compat_sys_timerfd
+	PTR	sys_eventfd
 	.size	sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 7e74b41..6bbe0f4 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -459,7 +459,7 @@
 	PTR	sys_remap_file_pages
 	PTR	sys_set_tid_address
 	PTR	sys_restart_syscall
-	PTR	sys_fadvise64_64
+	PTR	sys32_fadvise64_64
 	PTR	compat_sys_statfs64		/* 4255 */
 	PTR	compat_sys_fstatfs64
 	PTR	compat_sys_timer_create
@@ -521,4 +521,8 @@
 	PTR	compat_sys_epoll_pwait
 	PTR	sys_ioprio_set
 	PTR	sys_ioprio_get			/* 4315 */
+	PTR	compat_sys_utimensat
+	PTR	compat_sys_signalfd
+	PTR	compat_sys_timerfd
+	PTR	sys_eventfd
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 4975da0..316685f 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -20,6 +20,7 @@
 #include <linux/highmem.h>
 #include <linux/console.h>
 #include <linux/pfn.h>
+#include <linux/debugfs.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -574,3 +575,18 @@
 
 unsigned long kernelsp[NR_CPUS];
 unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *mips_debugfs_dir;
+static int __init debugfs_mips(void)
+{
+	struct dentry *d;
+
+	d = debugfs_create_dir("mips", NULL);
+	if (IS_ERR(d))
+		return PTR_ERR(d);
+	mips_debugfs_dir = d;
+	return 0;
+}
+arch_initcall(debugfs_mips);
+#endif
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 003f815..486b8e5 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -36,68 +36,6 @@
 
 #include "signal-common.h"
 
-#define SI_PAD_SIZE32   ((SI_MAX_SIZE/sizeof(int)) - 3)
-
-typedef struct compat_siginfo {
-	int si_signo;
-	int si_code;
-	int si_errno;
-
-	union {
-		int _pad[SI_PAD_SIZE32];
-
-		/* kill() */
-		struct {
-			compat_pid_t _pid;	/* sender's pid */
-			compat_uid_t _uid;	/* sender's uid */
-		} _kill;
-
-		/* SIGCHLD */
-		struct {
-			compat_pid_t _pid;	/* which child */
-			compat_uid_t _uid;	/* sender's uid */
-			int _status;		/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* IRIX SIGCHLD */
-		struct {
-			compat_pid_t _pid;	/* which child */
-			compat_clock_t _utime;
-			int _status;		/* exit code */
-			compat_clock_t _stime;
-		} _irix_sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-		struct {
-			s32 _addr; /* faulting insn/memory ref. */
-		} _sigfault;
-
-		/* SIGPOLL, SIGXFSZ (To do ...)  */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-
-		/* POSIX.1b timers */
-		struct {
-			timer_t _tid;		/* timer id */
-			int _overrun;		/* overrun count */
-			compat_sigval_t _sigval;/* same as below */
-			int _sys_private;       /* not to be passed to user */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			compat_pid_t _pid;	/* sender's pid */
-			compat_uid_t _uid;	/* sender's uid */
-			compat_sigval_t _sigval;
-		} _rt;
-
-	} _sifields;
-} compat_siginfo_t;
-
 /*
  * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  */
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 4cf9ff2..eb7e059 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -72,7 +72,7 @@
 struct rt_sigframe_n32 {
 	u32 rs_ass[4];			/* argument save space for o32 */
 	u32 rs_code[2];			/* signal trampoline */
-	struct siginfo rs_info;
+	struct compat_siginfo rs_info;
 	struct ucontextn32 rs_uc;
 };
 
@@ -81,7 +81,7 @@
 struct rt_sigframe_n32 {
 	u32 rs_ass[4];			/* argument save space for o32 */
 	u32 rs_pad[2];
-	struct siginfo rs_info;
+	struct compat_siginfo rs_info;
 	struct ucontextn32 rs_uc;
 	u32 rs_code[8] ____cacheline_aligned;		/* signal trampoline */
 };
@@ -187,7 +187,7 @@
 	install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
 
 	/* Create siginfo.  */
-	err |= copy_siginfo_to_user(&frame->rs_info, info);
+	err |= copy_siginfo_to_user32(&frame->rs_info, info);
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->rs_uc.uc_flags);
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 64b62bd..19b30d6 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -129,13 +129,13 @@
 
 static struct irqaction irq_resched = {
 	.handler	= ipi_resched_interrupt,
-	.flags		= IRQF_DISABLED,
+	.flags		= IRQF_DISABLED|IRQF_PERCPU,
 	.name		= "IPI_resched"
 };
 
 static struct irqaction irq_call = {
 	.handler	= ipi_call_interrupt,
-	.flags		= IRQF_DISABLED,
+	.flags		= IRQF_DISABLED|IRQF_PERCPU,
 	.name		= "IPI_call"
 };
 
@@ -236,8 +236,6 @@
 	dvpe();
 	dmt();
 
-	mips_mt_set_cpuoptions();
-
 	/* Put MVPE's into 'configuration state' */
 	set_c0_mvpcontrol(MVPCONTROL_VPC);
 
@@ -263,6 +261,8 @@
 
 void __init plat_prepare_cpus(unsigned int max_cpus)
 {
+	mips_mt_set_cpuoptions();
+
 	/* set up ipi interrupts */
 	if (cpu_has_vint) {
 		set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
@@ -275,10 +275,7 @@
 	setup_irq(cpu_ipi_resched_irq, &irq_resched);
 	setup_irq(cpu_ipi_call_irq, &irq_call);
 
-	/* need to mark IPI's as IRQ_PER_CPU */
-	irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU;
 	set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
-	irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU;
 	set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
 }
 
@@ -326,8 +323,11 @@
 
 void prom_init_secondary(void)
 {
+	/* Enable per-cpu interrupts */
+
+	/* This is Malta specific: IPI,performance and timer inetrrupts */
 	write_c0_status((read_c0_status() & ~ST0_IM ) |
-	                (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7));
+	                (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7));
 }
 
 void prom_smp_finish(void)
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index c46e479..be7362b 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -51,24 +51,14 @@
 EXPORT_SYMBOL(phys_cpu_present_map);
 EXPORT_SYMBOL(cpu_online_map);
 
-/* This happens early in bootup, can't really do it better */
-static void smp_tune_scheduling (void)
-{
-	struct cache_desc *cd = &current_cpu_data.scache;
-	unsigned long cachesize = cd->linesz * cd->sets * cd->ways;
-
-	if (cachesize > max_cache_size)
-		max_cache_size = cachesize;
-}
-
 extern void __init calibrate_delay(void);
-extern ATTRIB_NORET void cpu_idle(void);
+extern void cpu_idle(void);
 
 /*
  * First C code run on the secondary CPUs after being started up by
  * the master.
  */
-asmlinkage void start_secondary(void)
+asmlinkage __cpuinit void start_secondary(void)
 {
 	unsigned int cpu;
 
@@ -228,7 +218,6 @@
 {
 	init_new_context(current, &init_mm);
 	current_thread_info()->cpu = 0;
-	smp_tune_scheduling();
 	plat_prepare_cpus(max_cpus);
 #ifndef CONFIG_HOTPLUG_CPU
 	cpu_present_map = cpu_possible_map;
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
index 921207c..20938a4 100644
--- a/arch/mips/kernel/smtc-asm.S
+++ b/arch/mips/kernel/smtc-asm.S
@@ -121,10 +121,7 @@
 	subu	t1,sp,PT_SIZE
 	sw	ra,PT_EPC(t1)
 	sw	a0,PT_PADSLOT4(t1)
-	LONG_L	s0, TI_REGS($28)
-	LONG_S	sp, TI_REGS($28)
 	la	t2,ipi_decode
-	LONG_S	s0, TI_REGS($28)
 	sw	t2,PT_PADSLOT5(t1)
 	/* Save pre-disable value of TCStatus */
 	sw	t0,PT_TCSTATUS(t1)
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index b361edb..342d873 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -13,9 +13,9 @@
 #include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/hazards.h>
+#include <asm/irq.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
-#include <asm/mips-boards/maltaint.h>
 #include <asm/mipsregs.h>
 #include <asm/cacheflush.h>
 #include <asm/time.h>
@@ -611,12 +611,12 @@
 int setup_irq_smtc(unsigned int irq, struct irqaction * new,
 			unsigned long hwmask)
 {
+#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
 	unsigned int vpe = current_cpu_data.vpe_id;
 
-	irq_hwmask[irq] = hwmask;
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
-	vpemask[vpe][irq - MIPSCPU_INT_BASE] = 1;
+	vpemask[vpe][irq - MIPS_CPU_IRQ_BASE] = 1;
 #endif
+	irq_hwmask[irq] = hwmask;
 
 	return setup_irq(irq, new);
 }
@@ -822,7 +822,7 @@
 	switch (type_copy) {
 	case SMTC_CLOCK_TICK:
 		irq_enter();
-		kstat_this_cpu.irqs[MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR]++;
+		kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + cp0_compare_irq]++;
 		/* Invoke Clock "Interrupt" */
 		ipi_timer_latch[dest_copy] = 0;
 #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
@@ -1104,7 +1104,7 @@
 	mtflags = dmt();
 	pdb_msg = &id_ho_db_msg[0];
 	im = read_c0_status();
-	vpe = cpu_data[smp_processor_id()].vpe_id;
+	vpe = current_cpu_data.vpe_id;
 	for (bit = 0; bit < 8; bit++) {
 		/*
 		 * In current prototype, I/O interrupts
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 9dd5a2d..b947c61 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -272,9 +272,8 @@
 	struct thread_info *ti = task_thread_info(current);
 
 	ti->tp_value = addr;
-
-	/* If some future MIPS implementation has this register in hardware,
-	 * we will need to update it here (and in context switches).  */
+	if (cpu_has_userlocal)
+		write_c0_userlocal(addr);
 
 	return 0;
 }
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 751b4a1..d48d1d5 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -199,6 +199,35 @@
 EXPORT_SYMBOL(null_perf_irq);
 EXPORT_SYMBOL(perf_irq);
 
+/*
+ * Timer interrupt
+ */
+int cp0_compare_irq;
+
+/*
+ * Performance counter IRQ or -1 if shared with timer
+ */
+int cp0_perfcount_irq;
+EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
+
+/*
+ * Possibly handle a performance counter interrupt.
+ * Return true if the timer interrupt should not be checked
+ */
+static inline int handle_perf_irq (int r2)
+{
+	/*
+	 * The performance counter overflow interrupt may be shared with the
+	 * timer interrupt (cp0_perfcount_irq < 0). If it is and a
+	 * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
+	 * and we can't reliably determine if a counter interrupt has also
+	 * happened (!r2) then don't check for a timer interrupt.
+	 */
+	return (cp0_perfcount_irq < 0) &&
+		perf_irq() == IRQ_HANDLED &&
+		!r2;
+}
+
 asmlinkage void ll_timer_interrupt(int irq)
 {
 	int r2 = cpu_has_mips_r2;
@@ -206,19 +235,13 @@
 	irq_enter();
 	kstat_this_cpu.irqs[irq]++;
 
-	/*
-	 * Suckage alert:
-	 * Before R2 of the architecture there was no way to see if a
-	 * performance counter interrupt was pending, so we have to run the
-	 * performance counter interrupt handler anyway.
-	 */
-	if (!r2 || (read_c0_cause() & (1 << 26)))
-		if (perf_irq())
-			goto out;
+	if (handle_perf_irq(r2))
+		goto out;
 
-	/* we keep interrupt disabled all the time */
-	if (!r2 || (read_c0_cause() & (1 << 30)))
-		timer_interrupt(irq, NULL);
+	if (r2 && ((read_c0_cause() & (1 << 30)) == 0))
+		goto out;
+
+	timer_interrupt(irq, NULL);
 
 out:
 	irq_exit();
@@ -258,7 +281,7 @@
 
 static struct irqaction timer_irqaction = {
 	.handler = timer_interrupt,
-	.flags = IRQF_DISABLED,
+	.flags = IRQF_DISABLED | IRQF_PERCPU,
 	.name = "timer",
 };
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 200de02..ce277cb 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -11,6 +11,7 @@
  * Copyright (C) 2000, 01 MIPS Technologies, Inc.
  * Copyright (C) 2002, 2003, 2004, 2005  Maciej W. Rozycki
  */
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -38,7 +39,6 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
-#include <asm/watch.h>
 #include <asm/types.h>
 #include <asm/stacktrace.h>
 
@@ -69,6 +69,7 @@
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
 	struct mips_fpu_struct *ctx, int has_fpu);
 
+void (*board_watchpoint_handler)(struct pt_regs *regs);
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
 void (*board_nmi_handler_setup)(void);
@@ -130,7 +131,7 @@
 	const int field = 2 * sizeof(unsigned long);
 	long stackdata;
 	int i;
-	unsigned long *sp = (unsigned long *)regs->regs[29];
+	unsigned long __user *sp = (unsigned long __user *)regs->regs[29];
 
 	printk("Stack :");
 	i = 0;
@@ -186,7 +187,7 @@
 
 EXPORT_SYMBOL(dump_stack);
 
-void show_code(unsigned int *pc)
+static void show_code(unsigned int __user *pc)
 {
 	long i;
 
@@ -304,13 +305,13 @@
 	printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
 	        current->comm, current->pid, current_thread_info(), current);
 	show_stacktrace(current, regs);
-	show_code((unsigned int *) regs->cp0_epc);
+	show_code((unsigned int __user *) regs->cp0_epc);
 	printk("\n");
 }
 
 static DEFINE_SPINLOCK(die_lock);
 
-NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
+void __noreturn die(const char * str, struct pt_regs * regs)
 {
 	static int die_counter;
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -325,6 +326,7 @@
 #endif /* CONFIG_MIPS_MT_SMTC */
 	printk("%s[#%d]:\n", str, ++die_counter);
 	show_registers(regs);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
 	if (in_interrupt())
@@ -372,7 +374,7 @@
 		action = MIPS_BE_FIXUP;
 
 	if (board_be_handler)
-		action = board_be_handler(regs, fixup != 0);
+		action = board_be_handler(regs, fixup != NULL);
 
 	switch (action) {
 	case MIPS_BE_DISCARD:
@@ -752,6 +754,33 @@
 	force_sig(SIGILL, current);
 }
 
+/*
+ * MIPS MT processors may have fewer FPU contexts than CPU threads. If we've
+ * emulated more than some threshold number of instructions, force migration to
+ * a "CPU" that has FP support.
+ */
+static void mt_ase_fp_affinity(void)
+{
+#ifdef CONFIG_MIPS_MT_FPAFF
+	if (mt_fpemul_threshold > 0 &&
+	     ((current->thread.emulated_fp++ > mt_fpemul_threshold))) {
+		/*
+		 * If there's no FPU present, or if the application has already
+		 * restricted the allowed set to exclude any CPUs with FPUs,
+		 * we'll skip the procedure.
+		 */
+		if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {
+			cpumask_t tmask;
+
+			cpus_and(tmask, current->thread.user_cpus_allowed,
+			         mt_fpu_cpumask);
+			set_cpus_allowed(current, tmask);
+			current->thread.mflags |= MF_FPUBOUND;
+		}
+	}
+#endif /* CONFIG_MIPS_MT_FPAFF */
+}
+
 asmlinkage void do_cpu(struct pt_regs *regs)
 {
 	unsigned int cpid;
@@ -785,36 +814,8 @@
 						&current->thread.fpu, 0);
 			if (sig)
 				force_sig(sig, current);
-#ifdef CONFIG_MIPS_MT_FPAFF
-			else {
-			/*
-			 * MIPS MT processors may have fewer FPU contexts
-			 * than CPU threads. If we've emulated more than
-			 * some threshold number of instructions, force
-			 * migration to a "CPU" that has FP support.
-			 */
-			 if(mt_fpemul_threshold > 0
-			 && ((current->thread.emulated_fp++
-			    > mt_fpemul_threshold))) {
-			  /*
-			   * If there's no FPU present, or if the
-			   * application has already restricted
-			   * the allowed set to exclude any CPUs
-			   * with FPUs, we'll skip the procedure.
-			   */
-			  if (cpus_intersects(current->cpus_allowed,
-			  			mt_fpu_cpumask)) {
-			    cpumask_t tmask;
-
-			    cpus_and(tmask,
-					current->thread.user_cpus_allowed,
-					mt_fpu_cpumask);
-			    set_cpus_allowed(current, tmask);
-			    current->thread.mflags |= MF_FPUBOUND;
-			  }
-			 }
-			}
-#endif /* CONFIG_MIPS_MT_FPAFF */
+			else
+				mt_ase_fp_affinity();
 		}
 
 		return;
@@ -834,6 +835,11 @@
 
 asmlinkage void do_watch(struct pt_regs *regs)
 {
+	if (board_watchpoint_handler) {
+		(*board_watchpoint_handler)(regs);
+		return;
+	}
+
 	/*
 	 * We use the watch exception where available to detect stack
 	 * overflows.
@@ -860,7 +866,7 @@
 		dump_tlb_all();
 	}
 
-	show_code((unsigned int *) regs->cp0_epc);
+	show_code((unsigned int __user *) regs->cp0_epc);
 
 	/*
 	 * Some chips may have other causes of machine check (e.g. SB1
@@ -927,12 +933,6 @@
 	      (regs->cp0_cause & 0x7f) >> 2);
 }
 
-static asmlinkage void do_default_vi(void)
-{
-	show_regs(get_irq_regs());
-	panic("Caught unexpected vectored interrupt.");
-}
-
 /*
  * Some MIPS CPUs can enable/disable for cache parity detection, but do
  * it different ways.
@@ -1128,6 +1128,12 @@
 	clear_bit(set, &sr->sr_allocated);
 }
 
+static asmlinkage void do_default_vi(void)
+{
+	show_regs(get_irq_regs());
+	panic("Caught unexpected vectored interrupt.");
+}
+
 static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
 {
 	unsigned long handler;
@@ -1190,8 +1196,8 @@
 
 		memcpy (b, &except_vec_vi, handler_len);
 #ifdef CONFIG_MIPS_MT_SMTC
-		if (n > 7)
-			printk("Vector index %d exceeds SMTC maximum\n", n);
+		BUG_ON(n > 7);	/* Vector index %d exceeds SMTC maximum. */
+
 		w = (u32 *)(b + mori_offset);
 		*w = (*w & 0xffff0000) | (0x100 << n);
 #endif /* CONFIG_MIPS_MT_SMTC */
@@ -1342,16 +1348,20 @@
 		set_c0_status(ST0_MX);
 
 #ifdef CONFIG_CPU_MIPSR2
-	write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
+	if (cpu_has_mips_r2) {
+		unsigned int enable = 0x0000000f;
+
+		if (cpu_has_userlocal)
+			enable |= (1 << 29);
+
+		write_c0_hwrena(enable);
+	}
 #endif
 
 #ifdef CONFIG_MIPS_MT_SMTC
 	if (!secondaryTC) {
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-	/*
-	 * Interrupt handling.
-	 */
 	if (cpu_has_veic || cpu_has_vint) {
 		write_c0_ebase (ebase);
 		/* Setting vector spacing enables EI/VI mode  */
@@ -1365,6 +1375,23 @@
 		} else
 			set_c0_cause(CAUSEF_IV);
 	}
+
+	/*
+	 * Before R2 both interrupt numbers were fixed to 7, so on R2 only:
+	 *
+	 *  o read IntCtl.IPTI to determine the timer interrupt
+	 *  o read IntCtl.IPPCI to determine the performance counter interrupt
+	 */
+	if (cpu_has_mips_r2) {
+		cp0_compare_irq = (read_c0_intctl () >> 29) & 7;
+		cp0_perfcount_irq = (read_c0_intctl () >> 26) & 7;
+		if (cp0_perfcount_irq == cp0_compare_irq)
+			cp0_perfcount_irq = -1;
+	} else {
+		cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
+		cp0_perfcount_irq = -1;
+	}
+
 #ifdef CONFIG_MIPS_MT_SMTC
 	}
 #endif /* CONFIG_MIPS_MT_SMTC */
@@ -1383,6 +1410,13 @@
 		cpu_cache_init();
 		tlb_init();
 #ifdef CONFIG_MIPS_MT_SMTC
+	} else if (!secondaryTC) {
+		/*
+		 * First TC in non-boot VPE must do subset of tlb_init()
+		 * for MMU countrol registers.
+		 */
+		write_c0_pagemask(PM_DEFAULT_MASK);
+		write_c0_wired(0);
 	}
 #endif /* CONFIG_MIPS_MT_SMTC */
 }
@@ -1531,8 +1565,7 @@
 	if (cpu_has_mipsmt)
 		set_except_vector(25, handle_mt);
 
-	if (cpu_has_dsp)
-		set_except_vector(26, handle_dsp);
+	set_except_vector(26, handle_dsp);
 
 	if (cpu_has_vce)
 		/* Special exception: R4[04]00 uses also the divec space. */
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index a7d49ae..8b9c34f 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -76,7 +76,8 @@
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
-
+#include <linux/sched.h>
+#include <linux/debugfs.h>
 #include <asm/asm.h>
 #include <asm/branch.h>
 #include <asm/byteorder.h>
@@ -87,9 +88,18 @@
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
 
-#ifdef CONFIG_PROC_FS
-unsigned long unaligned_instructions;
+enum {
+	UNALIGNED_ACTION_QUIET,
+	UNALIGNED_ACTION_SIGNAL,
+	UNALIGNED_ACTION_SHOW,
+};
+#ifdef CONFIG_DEBUG_FS
+static u32 unaligned_instructions;
+static u32 unaligned_action;
+#else
+#define unaligned_action UNALIGNED_ACTION_QUIET
 #endif
+extern void show_registers(struct pt_regs *regs);
 
 static inline int emulate_load_store_insn(struct pt_regs *regs,
 	void __user *addr, unsigned int __user *pc,
@@ -459,7 +469,7 @@
 		goto sigill;
 	}
 
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_DEBUG_FS
 	unaligned_instructions++;
 #endif
 
@@ -516,6 +526,10 @@
 	pc = (unsigned int __user *) exception_epc(regs);
 	if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0)
 		goto sigbus;
+	if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
+		goto sigbus;
+	else if (unaligned_action == UNALIGNED_ACTION_SHOW)
+		show_registers(regs);
 
 	/*
 	 * Do branch emulation only if we didn't forward the exception.
@@ -546,3 +560,24 @@
 	 * XXX On return from the signal handler we should advance the epc
 	 */
 }
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_unaligned(void)
+{
+	struct dentry *d;
+
+	if (!mips_debugfs_dir)
+		return -ENODEV;
+	d = debugfs_create_u32("unaligned_instructions", S_IRUGO,
+			       mips_debugfs_dir, &unaligned_instructions);
+	if (IS_ERR(d))
+		return PTR_ERR(d);
+	d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR,
+			       mips_debugfs_dir, &unaligned_action);
+	if (IS_ERR(d))
+		return PTR_ERR(d);
+	return 0;
+}
+__initcall(debugfs_unaligned);
+#endif
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 043f637..9b9992c 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -27,7 +27,7 @@
   /* read-only */
   _text = .;			/* Text and read-only data */
   .text : {
-    *(.text)
+    TEXT_TEXT
     SCHED_TEXT
     LOCK_TEXT
     *(.fixup)
@@ -62,7 +62,7 @@
     . = ALIGN(_PAGE_SIZE);
     *(.data.init_task)
 
-    *(.data)
+    DATA_DATA
 
     CONSTRUCTORS
   }
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index c9ee9d2..9e66354 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1436,10 +1436,6 @@
 			write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
 
 			if (i != 0) {
-				write_vpe_c0_status((read_c0_status() &
-						     ~(ST0_IM | ST0_IE | ST0_KSU))
-						    | ST0_CU0);
-
 				/*
 				 * Set config to be the same as vpe0,
 				 * particularly kseg0 coherency alg
diff --git a/arch/mips/lasat/Kconfig b/arch/mips/lasat/Kconfig
deleted file mode 100644
index 1d2ee8a..0000000
--- a/arch/mips/lasat/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config PICVUE
-	tristate "PICVUE LCD display driver"
-	depends on LASAT
-
-config PICVUE_PROC
-	tristate "PICVUE LCD display driver /proc interface"
-	depends on PICVUE
-
-config DS1603
-	bool "DS1603 RTC driver"
-	depends on LASAT
-
-config LASAT_SYSCTL
-	bool "LASAT sysctl interface"
-	depends on LASAT
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
deleted file mode 100644
index 99f5046..0000000
--- a/arch/mips/lasat/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the LASAT specific kernel interface routines under Linux.
-#
-
-obj-y	 			+= reset.o setup.o prom.o lasat_board.o \
-				   at93c.o interrupt.o
-
-obj-$(CONFIG_LASAT_SYSCTL)	+= sysctl.o
-obj-$(CONFIG_DS1603)		+= ds1603.o
-obj-$(CONFIG_PICVUE)		+= picvue.o
-obj-$(CONFIG_PICVUE_PROC)	+= picvue_proc.o
-
-clean:
-	make -C image clean
diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c
deleted file mode 100644
index ca26e55..0000000
--- a/arch/mips/lasat/at93c.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Atmel AT93C46 serial eeprom driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/lasat/lasat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "at93c.h"
-
-#define AT93C_ADDR_SHIFT	7
-#define AT93C_ADDR_MAX		((1 << AT93C_ADDR_SHIFT) - 1)
-#define AT93C_RCMD		(0x6 << AT93C_ADDR_SHIFT)
-#define AT93C_WCMD		(0x5 << AT93C_ADDR_SHIFT)
-#define AT93C_WENCMD		0x260
-#define AT93C_WDSCMD		0x200
-
-struct at93c_defs *at93c;
-
-static void at93c_reg_write(u32 val)
-{
-	*at93c->reg = val;
-}
-
-static u32 at93c_reg_read(void)
-{
-	u32 tmp = *at93c->reg;
-	return tmp;
-}
-
-static u32 at93c_datareg_read(void)
-{
-	u32 tmp = *at93c->rdata_reg;
-	return tmp;
-}
-
-static void at93c_cycle_clk(u32 data)
-{
-	at93c_reg_write(data | at93c->clk);
-	lasat_ndelay(250);
-	at93c_reg_write(data & ~at93c->clk);
-	lasat_ndelay(250);
-}
-
-static void at93c_write_databit(u8 bit)
-{
-	u32 data = at93c_reg_read();
-	if (bit)
-		data |= 1 << at93c->wdata_shift;
-	else
-		data &= ~(1 << at93c->wdata_shift);
-
-	at93c_reg_write(data);
-	lasat_ndelay(100);
-	at93c_cycle_clk(data);
-}
-
-static unsigned int at93c_read_databit(void)
-{
-	u32 data;
-
-	at93c_cycle_clk(at93c_reg_read());
-	data = (at93c_datareg_read() >> at93c->rdata_shift) & 1;
-	return data;
-}
-
-static u8 at93c_read_byte(void)
-{
-	int i;
-	u8 data = 0;
-
-	for (i = 0; i<=7; i++) {
-		data <<= 1;
-		data |= at93c_read_databit();
-	}
-	return data;
-}
-
-static void at93c_write_bits(u32 data, int size)
-{
-	int i;
-	int shift = size - 1;
-	u32 mask = (1 << shift);
-
-	for (i = 0; i < size; i++) {
-		at93c_write_databit((data & mask) >> shift);
-		data <<= 1;
-	}
-}
-
-static void at93c_init_op(void)
-{
-	at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift));
-	lasat_ndelay(50);
-}
-
-static void at93c_end_op(void)
-{
-	at93c_reg_write(at93c_reg_read() & ~at93c->cs);
-	lasat_ndelay(250);
-}
-
-static void at93c_wait(void)
-{
-	at93c_init_op();
-	while (!at93c_read_databit())
-		;
-	at93c_end_op();
-};
-
-static void at93c_disable_wp(void)
-{
-	at93c_init_op();
-	at93c_write_bits(AT93C_WENCMD, 10);
-	at93c_end_op();
-}
-
-static void at93c_enable_wp(void)
-{
-	at93c_init_op();
-	at93c_write_bits(AT93C_WDSCMD, 10);
-	at93c_end_op();
-}
-
-u8 at93c_read(u8 addr)
-{
-	u8 byte;
-	at93c_init_op();
-	at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10);
-	byte = at93c_read_byte();
-	at93c_end_op();
-	return byte;
-}
-
-void at93c_write(u8 addr, u8 data)
-{
-	at93c_disable_wp();
-	at93c_init_op();
-	at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10);
-	at93c_write_bits(data, 8);
-	at93c_end_op();
-	at93c_wait();
-	at93c_enable_wp();
-}
diff --git a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h
deleted file mode 100644
index cfe2f99..0000000
--- a/arch/mips/lasat/at93c.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Atmel AT93C46 serial eeprom driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-
-extern struct at93c_defs {
-	volatile u32 *reg;
-	volatile u32 *rdata_reg;
-	int rdata_shift;
-	int wdata_shift;
-	u32 cs;
-	u32 clk;
-} *at93c;
-
-u8 at93c_read(u8 addr);
-void at93c_write(u8 addr, u8 data);
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
deleted file mode 100644
index 7dced67..0000000
--- a/arch/mips/lasat/ds1603.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#include <linux/kernel.h>
-#include <asm/lasat/lasat.h>
-#include <linux/delay.h>
-#include <asm/lasat/ds1603.h>
-#include <asm/time.h>
-
-#include "ds1603.h"
-
-#define READ_TIME_CMD 0x81
-#define SET_TIME_CMD 0x80
-#define TRIMMER_SET_CMD 0xC0
-#define TRIMMER_VALUE_MASK 0x38
-#define TRIMMER_SHIFT 3
-
-struct ds_defs *ds1603 = NULL;
-
-/* HW specific register functions */
-static void rtc_reg_write(unsigned long val)
-{
-	*ds1603->reg = val;
-}
-
-static unsigned long rtc_reg_read(void)
-{
-	unsigned long tmp = *ds1603->reg;
-	return tmp;
-}
-
-static unsigned long rtc_datareg_read(void)
-{
-	unsigned long tmp = *ds1603->data_reg;
-	return tmp;
-}
-
-static void rtc_nrst_high(void)
-{
-	rtc_reg_write(rtc_reg_read() | ds1603->rst);
-}
-
-static void rtc_nrst_low(void)
-{
-	rtc_reg_write(rtc_reg_read() & ~ds1603->rst);
-}
-
-static void rtc_cycle_clock(unsigned long data)
-{
-	data |= ds1603->clk;
-	rtc_reg_write(data);
-	lasat_ndelay(250);
-	if (ds1603->data_reversed)
-		data &= ~ds1603->data;
-	else
-		data |= ds1603->data;
-	data &= ~ds1603->clk;
-	rtc_reg_write(data);
-	lasat_ndelay(250 + ds1603->huge_delay);
-}
-
-static void rtc_write_databit(unsigned int bit)
-{
-	unsigned long data = rtc_reg_read();
-	if (ds1603->data_reversed)
-		bit = !bit;
-	if (bit)
-		data |= ds1603->data;
-	else
-		data &= ~ds1603->data;
-
-	rtc_reg_write(data);
-	lasat_ndelay(50 + ds1603->huge_delay);
-	rtc_cycle_clock(data);
-}
-
-static unsigned int rtc_read_databit(void)
-{
-	unsigned int data;
-
-	data = (rtc_datareg_read() & (1 << ds1603->data_read_shift))
-		>> ds1603->data_read_shift;
-	rtc_cycle_clock(rtc_reg_read());
-	return data;
-}
-
-static void rtc_write_byte(unsigned int byte)
-{
-	int i;
-
-	for (i = 0; i<=7; i++) {
-		rtc_write_databit(byte & 1L);
-		byte >>= 1;
-	}
-}
-
-static void rtc_write_word(unsigned long word)
-{
-	int i;
-
-	for (i = 0; i<=31; i++) {
-		rtc_write_databit(word & 1L);
-		word >>= 1;
-	}
-}
-
-static unsigned long rtc_read_word(void)
-{
-	int i;
-	unsigned long word = 0;
-	unsigned long shift = 0;
-
-	for (i = 0; i<=31; i++) {
-		word |= rtc_read_databit() << shift;
-		shift++;
-	}
-	return word;
-}
-
-static void rtc_init_op(void)
-{
-	rtc_nrst_high();
-
-	rtc_reg_write(rtc_reg_read() & ~ds1603->clk);
-
-	lasat_ndelay(50);
-}
-
-static void rtc_end_op(void)
-{
-	rtc_nrst_low();
-	lasat_ndelay(1000);
-}
-
-/* interface */
-unsigned long ds1603_read(void)
-{
-	unsigned long word;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	rtc_init_op();
-	rtc_write_byte(READ_TIME_CMD);
-	word = rtc_read_word();
-	rtc_end_op();
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return word;
-}
-
-int ds1603_set(unsigned long time)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	rtc_init_op();
-	rtc_write_byte(SET_TIME_CMD);
-	rtc_write_word(time);
-	rtc_end_op();
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-void ds1603_set_trimmer(unsigned int trimval)
-{
-	rtc_init_op();
-	rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK)
-			| (TRIMMER_SET_CMD));
-	rtc_end_op();
-}
-
-void ds1603_disable(void)
-{
-	ds1603_set_trimmer(TRIMMER_DISABLE_RTC);
-}
-
-void ds1603_enable(void)
-{
-	ds1603_set_trimmer(TRIMMER_DEFAULT);
-}
diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h
deleted file mode 100644
index c2e5c76..0000000
--- a/arch/mips/lasat/ds1603.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#ifndef __DS1603_H
-#define __DS1603_H
-
-struct ds_defs {
-	volatile u32 *reg;
-	volatile u32 *data_reg;
-	u32 rst;
-	u32 clk;
-	u32 data;
-	u32 data_read_shift;
-	char data_reversed;
-	u32 huge_delay;
-};
-
-extern struct ds_defs *ds1603;
-
-unsigned long ds1603_read(void);
-int ds1603_set(unsigned long);
-void ds1603_set_trimmer(unsigned int);
-void ds1603_enable(void);
-void ds1603_disable(void);
-void ds1603_init(struct ds_defs *);
-
-#define TRIMMER_DEFAULT	3
-#define TRIMMER_DISABLE_RTC 0
-
-#endif
diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile
deleted file mode 100644
index 35ecd64..0000000
--- a/arch/mips/lasat/image/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER
-#
-# i-data Networks
-#
-# Author: Thomas Horsten <thh@i-data.com>
-#
-
-ifndef Version
- Version = "$(USER)-test"
-endif
-
-MKLASATIMG = mklasatimg
-MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200
-KERNEL_IMAGE = $(TOPDIR)/vmlinux
-KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ )
-KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ )
-
-LDSCRIPT= -L$(obj) -Tromscript.normal
-
-HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \
-		-D_kernel_entry=0x$(KERNEL_ENTRY) \
-		-D VERSION="\"$(Version)\"" \
-		-D TIMESTAMP=$(shell date +%s)
-
-$(obj)/head.o: $(obj)/head.S $(KERNEL_IMAGE)
-	$(CC) -fno-pic $(HEAD_DEFINES) -I$(TOPDIR)/include -c -o $@ $<
-
-OBJECTS = head.o kImage.o
-
-rom.sw:	$(obj)/rom.sw
-
-$(obj)/rom.sw:	$(obj)/rom.bin
-	$(MKLASATIMG) -o $@ -k $^ -m $(MKLASATIMG_ARCH)
-
-$(obj)/rom.bin: $(obj)/rom
-	$(OBJCOPY) -O binary -S $^ $@
-
-# Rule to make the bootloader
-$(obj)/rom: $(addprefix $(obj)/,$(OBJECTS))
-	$(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^
-
-$(obj)/%.o: $(obj)/%.gz
-	$(LD) -r -o $@ -b binary $<
-
-$(obj)/%.gz: $(obj)/%.bin
-	gzip -cf -9 $< > $@
-
-$(obj)/kImage.bin: $(KERNEL_IMAGE)
-	$(OBJCOPY) -O binary -S $^ $@
-
-clean:
-	rm -f rom rom.bin rom.sw kImage.bin kImage.o
diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S
deleted file mode 100644
index efb95f2..0000000
--- a/arch/mips/lasat/image/head.S
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <asm/lasat/head.h>
-
-	.text
-	.section .text.start, "ax"
-	.set noreorder
-	.set mips3
-
-	/* Magic words identifying a software image */
-	.word	LASAT_K_MAGIC0_VAL
-	.word 	LASAT_K_MAGIC1_VAL
-
-	/* Image header version */
-	.word	0x00000002
-
-	/* image start and size */
-	.word	_image_start
-	.word	_image_size
-
-	/* start of kernel and entrypoint in uncompressed image */
-	.word	_kernel_start
-	.word	_kernel_entry
-
-	/* Here we have room for future flags */
-
-	.org	0x40
-reldate:
-	.word	TIMESTAMP
-
-	.org	0x50
-release:
-	.string VERSION
diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal
deleted file mode 100644
index 988f8ad..0000000
--- a/arch/mips/lasat/image/romscript.normal
+++ /dev/null
@@ -1,23 +0,0 @@
-OUTPUT_ARCH(mips)
-
-SECTIONS
-{
-  .text :
-  {
-    *(.text.start)
-  }
-
-  /* Data in ROM */
-
-  .data ALIGN(0x10) :
-  {
-    *(.data)
-  }
-  _image_start = ADDR(.data);
-  _image_size = SIZEOF(.data);
-
-  .other :
-  {
-    *(.*)
-  }
-}
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
deleted file mode 100644
index 9a622b9..0000000
--- a/arch/mips/lasat/interrupt.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines for generic manipulation of the interrupts found on the
- * Lasat boards.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/lasat/lasatint.h>
-#include <asm/time.h>
-#include <asm/gdb-stub.h>
-
-static volatile int *lasat_int_status = NULL;
-static volatile int *lasat_int_mask = NULL;
-static volatile int lasat_int_mask_shift;
-
-void disable_lasat_irq(unsigned int irq_nr)
-{
-	*lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
-}
-
-void enable_lasat_irq(unsigned int irq_nr)
-{
-	*lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
-}
-
-static struct irq_chip lasat_irq_type = {
-	.name = "Lasat",
-	.ack = disable_lasat_irq,
-	.mask = disable_lasat_irq,
-	.mask_ack = disable_lasat_irq,
-	.unmask = enable_lasat_irq,
-};
-
-static inline int ls1bit32(unsigned int x)
-{
-	int b = 31, s;
-
-	s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
-	s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
-	s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
-	s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
-	s =  1; if (x <<  1 == 0) s = 0; b -= s;
-
-	return b;
-}
-
-static unsigned long (* get_int_status)(void);
-
-static unsigned long get_int_status_100(void)
-{
-	return *lasat_int_status & *lasat_int_mask;
-}
-
-static unsigned long get_int_status_200(void)
-{
-	unsigned long int_status;
-
-	int_status = *lasat_int_status;
-	int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff;
-	return int_status;
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned long int_status;
-	unsigned int cause = read_c0_cause();
-	int irq;
-
-	if (cause & CAUSEF_IP7) {	/* R4000 count / compare IRQ */
-		ll_timer_interrupt(7);
-		return;
-	}
-
-	int_status = get_int_status();
-
-	/* if int_status == 0, then the interrupt has already been cleared */
-	if (int_status) {
-		irq = ls1bit32(int_status);
-
-		do_IRQ(irq);
-	}
-}
-
-void __init arch_init_irq(void)
-{
-	int i;
-
-	switch (mips_machtype) {
-	case MACH_LASAT_100:
-		lasat_int_status = (void *)LASAT_INT_STATUS_REG_100;
-		lasat_int_mask = (void *)LASAT_INT_MASK_REG_100;
-		lasat_int_mask_shift = LASATINT_MASK_SHIFT_100;
-		get_int_status = get_int_status_100;
-		*lasat_int_mask = 0;
-		break;
-	case MACH_LASAT_200:
-		lasat_int_status = (void *)LASAT_INT_STATUS_REG_200;
-		lasat_int_mask = (void *)LASAT_INT_MASK_REG_200;
-		lasat_int_mask_shift = LASATINT_MASK_SHIFT_200;
-		get_int_status = get_int_status_200;
-		*lasat_int_mask &= 0xffff;
-		break;
-	default:
-		panic("arch_init_irq: mips_machtype incorrect");
-	}
-
-	for (i = 0; i <= LASATINT_END; i++)
-		set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c
deleted file mode 100644
index fbe9a87..0000000
--- a/arch/mips/lasat/lasat_board.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines specific to the LASAT boards
- */
-#include <linux/types.h>
-#include <linux/crc32.h>
-#include <asm/lasat/lasat.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <asm/bootinfo.h>
-#include <asm/addrspace.h>
-#include "at93c.h"
-/* New model description table */
-#include "lasat_models.h"
-
-#define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len))
-
-struct lasat_info lasat_board_info;
-
-void update_bcastaddr(void);
-
-int EEPROMRead(unsigned int pos, unsigned char *data, int len)
-{
-	int i;
-
-	for (i=0; i<len; i++)
-		*data++ = at93c_read(pos++);
-
-	return 0;
-}
-int EEPROMWrite(unsigned int pos, unsigned char *data, int len)
-{
-	int i;
-
-	for (i=0; i<len; i++)
-		at93c_write(pos++, *data++);
-
-	return 0;
-}
-
-static void init_flash_sizes(void)
-{
-	int i;
-	unsigned long *lb = lasat_board_info.li_flashpart_base;
-	unsigned long *ls = lasat_board_info.li_flashpart_size;
-
-	ls[LASAT_MTD_BOOTLOADER] = 0x40000;
-	ls[LASAT_MTD_SERVICE] = 0xC0000;
-	ls[LASAT_MTD_NORMAL] = 0x100000;
-
-	if (mips_machtype == MACH_LASAT_100) {
-		lasat_board_info.li_flash_base = 0x1e000000;
-
-		lb[LASAT_MTD_BOOTLOADER] = 0x1e400000;
-
-		if (lasat_board_info.li_flash_size > 0x200000) {
-			ls[LASAT_MTD_CONFIG] = 0x100000;
-			ls[LASAT_MTD_FS] = 0x500000;
-		}
-	} else {
-		lasat_board_info.li_flash_base = 0x10000000;
-
-		if (lasat_board_info.li_flash_size < 0x1000000) {
-			lb[LASAT_MTD_BOOTLOADER] = 0x10000000;
-			ls[LASAT_MTD_CONFIG] = 0x100000;
-			if (lasat_board_info.li_flash_size >= 0x400000) {
-				ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000;
-			}
-		}
-	}
-
-	for (i = 1; i < LASAT_MTD_LAST; i++)
-		lb[i] = lb[i-1] + ls[i-1];
-}
-
-int lasat_init_board_info(void)
-{
-	int c;
-	unsigned long crc;
-	unsigned long cfg0, cfg1;
-	const product_info_t   *ppi;
-	int i_n_base_models = N_BASE_MODELS;
-	const char * const * i_txt_base_models = txt_base_models;
-	int i_n_prids = N_PRIDS;
-
-	memset(&lasat_board_info, 0, sizeof(lasat_board_info));
-
-	/* First read the EEPROM info */
-	EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
-		   sizeof(struct lasat_eeprom_struct));
-
-	/* Check the CRC */
-	crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
-		    sizeof(struct lasat_eeprom_struct) - 4);
-
-	if (crc != lasat_board_info.li_eeprom_info.crc32) {
-		printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM CRC does "
-		       "not match calculated, attempting to soldier on...\n");
-	}
-
-	if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) {
-		printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM version "
-		       "%d, wanted version %d, attempting to soldier on...\n",
-		       (unsigned int)lasat_board_info.li_eeprom_info.version,
-		       LASAT_EEPROM_VERSION);
-	}
-
-	cfg0 = lasat_board_info.li_eeprom_info.cfg[0];
-	cfg1 = lasat_board_info.li_eeprom_info.cfg[1];
-
-	if ( LASAT_W0_DSCTYPE(cfg0) != 1) {
-		printk(KERN_WARNING "WARNING...\nWARNING...\n"
-		       "Invalid configuration read from EEPROM, attempting to "
-		       "soldier on...");
-	}
-	/* We have a valid configuration */
-
-	switch (LASAT_W0_SDRAMBANKSZ(cfg0)) {
-	case 0:
-		lasat_board_info.li_memsize = 0x0800000;
-		break;
-	case 1:
-		lasat_board_info.li_memsize = 0x1000000;
-		break;
-	case 2:
-		lasat_board_info.li_memsize = 0x2000000;
-		break;
-	case 3:
-		lasat_board_info.li_memsize = 0x4000000;
-		break;
-	case 4:
-		lasat_board_info.li_memsize = 0x8000000;
-		break;
-	default:
-		lasat_board_info.li_memsize = 0;
-	}
-
-	switch (LASAT_W0_SDRAMBANKS(cfg0)) {
-	case 0:
-		break;
-	case 1:
-		lasat_board_info.li_memsize *= 2;
-		break;
-	default:
-		break;
-	}
-
-	switch (LASAT_W0_BUSSPEED(cfg0)) {
-	case 0x0:
-		lasat_board_info.li_bus_hz = 60000000;
-		break;
-	case 0x1:
-		lasat_board_info.li_bus_hz = 66000000;
-		break;
-	case 0x2:
-		lasat_board_info.li_bus_hz = 66666667;
-		break;
-	case 0x3:
-		lasat_board_info.li_bus_hz = 80000000;
-		break;
-	case 0x4:
-		lasat_board_info.li_bus_hz = 83333333;
-		break;
-	case 0x5:
-		lasat_board_info.li_bus_hz = 100000000;
-		break;
-	}
-
-	switch (LASAT_W0_CPUCLK(cfg0)) {
-	case 0x0:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz;
-		break;
-	case 0x1:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz +
-			(lasat_board_info.li_bus_hz >> 1);
-		break;
-	case 0x2:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz +
-			lasat_board_info.li_bus_hz;
-		break;
-	case 0x3:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz +
-			lasat_board_info.li_bus_hz +
-			(lasat_board_info.li_bus_hz >> 1);
-		break;
-	case 0x4:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz +
-			lasat_board_info.li_bus_hz +
-			lasat_board_info.li_bus_hz;
-		break;
-	}
-
-	/* Flash size */
-	switch (LASAT_W1_FLASHSIZE(cfg1)) {
-	case 0:
-		lasat_board_info.li_flash_size = 0x200000;
-		break;
-	case 1:
-		lasat_board_info.li_flash_size = 0x400000;
-		break;
-	case 2:
-		lasat_board_info.li_flash_size = 0x800000;
-		break;
-	case 3:
-		lasat_board_info.li_flash_size = 0x1000000;
-		break;
-	case 4:
-		lasat_board_info.li_flash_size = 0x2000000;
-		break;
-	}
-
-	init_flash_sizes();
-
-	lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0);
-	lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid;
-	if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0)
-		lasat_board_info.li_prid = lasat_board_info.li_bmid;
-
-	/* Base model stuff */
-	if (lasat_board_info.li_bmid > i_n_base_models)
-		lasat_board_info.li_bmid = i_n_base_models;
-	strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]);
-
-	/* Product ID dependent values */
-	c = lasat_board_info.li_prid;
-	if (c >= i_n_prids) {
-		strcpy(lasat_board_info.li_namestr, "Unknown Model");
-		strcpy(lasat_board_info.li_typestr, "Unknown Type");
-	} else {
-		ppi = &vendor_info_table[0].vi_product_info[c];
-		strcpy(lasat_board_info.li_namestr, ppi->pi_name);
-		if (ppi->pi_type)
-			strcpy(lasat_board_info.li_typestr, ppi->pi_type);
-		else
-			sprintf(lasat_board_info.li_typestr, "%d",10*c);
-	}
-
-#if defined(CONFIG_INET) && defined(CONFIG_SYSCTL)
-	update_bcastaddr();
-#endif
-
-	return 0;
-}
-
-void lasat_write_eeprom_info(void)
-{
-	unsigned long crc;
-
-	/* Generate the CRC */
-	crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
-		    sizeof(struct lasat_eeprom_struct) - 4);
-	lasat_board_info.li_eeprom_info.crc32 = crc;
-
-	/* Write the EEPROM info */
-	EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
-		    sizeof(struct lasat_eeprom_struct));
-}
-
diff --git a/arch/mips/lasat/lasat_models.h b/arch/mips/lasat/lasat_models.h
deleted file mode 100644
index ae0c5d0..0000000
--- a/arch/mips/lasat/lasat_models.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Model description tables
- */
-
-typedef struct product_info_t {
-	const char     *pi_name;
-	const char     *pi_type;
-} product_info_t;
-
-typedef struct vendor_info_t {
-	const char     *vi_name;
-	const product_info_t *vi_product_info;
-} vendor_info_t;
-
-/*
- * Base models
- */
-static const char * const txt_base_models[] = {
-  "MQ 2", "MQ Pro", "SP 25", "SP 50", "SP 100", "SP 5000", "SP 7000", "SP 1000", "Unknown"
-};
-#define N_BASE_MODELS (sizeof(txt_base_models)/sizeof(char*)-1)
-
-/*
- * Eicon Networks
- */
-static const char txt_en_mq[] = "Masquerade";
-static const char txt_en_sp[] = "Safepipe";
-
-static const product_info_t product_info_eicon[] = {
-  { txt_en_mq, "II"   }, /*  0 */
-  { txt_en_mq, "Pro"  }, /*  1 */
-  { txt_en_sp, "25"   }, /*  2 */
-  { txt_en_sp, "50"   }, /*  3 */
-  { txt_en_sp, "100"  }, /*  4 */
-  { txt_en_sp, "5000" }, /*  5 */
-  { txt_en_sp, "7000" }, /*  6 */
-  { txt_en_sp, "30"   }, /*  7 */
-  { txt_en_sp, "5100" }, /*  8 */
-  { txt_en_sp, "7100" }, /*  9 */
-  { txt_en_sp, "1110" }, /* 10 */
-  { txt_en_sp, "3020" }, /* 11 */
-  { txt_en_sp, "3030" }, /* 12 */
-  { txt_en_sp, "5020" }, /* 13 */
-  { txt_en_sp, "5030" }, /* 14 */
-  { txt_en_sp, "1120" }, /* 15 */
-  { txt_en_sp, "1130" }, /* 16 */
-  { txt_en_sp, "6010" }, /* 17 */
-  { txt_en_sp, "6110" }, /* 18 */
-  { txt_en_sp, "6210" }, /* 19 */
-  { txt_en_sp, "1020" }, /* 20 */
-  { txt_en_sp, "1040" }, /* 21 */
-  { txt_en_sp, "1050" }, /* 22 */
-  { txt_en_sp, "1060" }, /* 23 */
-};
-#define N_PRIDS (sizeof(product_info_eicon)/sizeof(product_info_t))
-
-/*
- * The vendor table
- */
-static vendor_info_t const vendor_info_table[] = {
-  { "Eicon Networks",	product_info_eicon   },
-};
-#define N_VENDORS (sizeof(vendor_info_table)/sizeof(vendor_info_t))
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c
deleted file mode 100644
index 9ae82c3..0000000
--- a/arch/mips/lasat/picvue.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/bootinfo.h>
-#include <asm/lasat/lasat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include "picvue.h"
-
-#define PVC_BUSY		0x80
-#define PVC_NLINES		2
-#define PVC_DISPMEM		80
-#define PVC_LINELEN		PVC_DISPMEM / PVC_NLINES
-
-struct pvc_defs *picvue = NULL;
-
-DECLARE_MUTEX(pvc_sem);
-
-static void pvc_reg_write(u32 val)
-{
-	*picvue->reg = val;
-}
-
-static u32 pvc_reg_read(void)
-{
-	u32 tmp = *picvue->reg;
-	return tmp;
-}
-
-static void pvc_write_byte(u32 data, u8 byte)
-{
-	data |= picvue->e;
-	pvc_reg_write(data);
-	data &= ~picvue->data_mask;
-	data |= byte << picvue->data_shift;
-	pvc_reg_write(data);
-	ndelay(220);
-	pvc_reg_write(data & ~picvue->e);
-	ndelay(220);
-}
-
-static u8 pvc_read_byte(u32 data)
-{
-	u8 byte;
-
-	data |= picvue->e;
-	pvc_reg_write(data);
-	ndelay(220);
-	byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift;
-	data &= ~picvue->e;
-	pvc_reg_write(data);
-	ndelay(220);
-	return byte;
-}
-
-static u8 pvc_read_data(void)
-{
-	u32 data = pvc_reg_read();
-	u8 byte;
-	data |= picvue->rw;
-	data &= ~picvue->rs;
-	pvc_reg_write(data);
-	ndelay(40);
-	byte = pvc_read_byte(data);
-	data |= picvue->rs;
-	pvc_reg_write(data);
-	return byte;
-}
-
-#define TIMEOUT 1000
-static int pvc_wait(void)
-{
-	int i = TIMEOUT;
-	int err = 0;
-
-	while ((pvc_read_data() & PVC_BUSY) && i)
-		i--;
-	if (i == 0)
-		err = -ETIME;
-
-	return err;
-}
-
-#define MODE_INST 0
-#define MODE_DATA 1
-static void pvc_write(u8 byte, int mode)
-{
-	u32 data = pvc_reg_read();
-	data &= ~picvue->rw;
-	if (mode == MODE_DATA)
-		data |= picvue->rs;
-	else
-		data &= ~picvue->rs;
-	pvc_reg_write(data);
-	ndelay(40);
-	pvc_write_byte(data, byte);
-	if (mode == MODE_DATA)
-		data &= ~picvue->rs;
-	else
-		data |= picvue->rs;
-	pvc_reg_write(data);
-	pvc_wait();
-}
-
-void pvc_write_string(const unsigned char *str, u8 addr, int line)
-{
-	int i = 0;
-
-	if (line > 0 && (PVC_NLINES > 1))
-		addr += 0x40 * line;
-	pvc_write(0x80 | addr, MODE_INST);
-
-	while (*str != 0 && i < PVC_LINELEN) {
-		pvc_write(*str++, MODE_DATA);
-		i++;
-	}
-}
-
-void pvc_write_string_centered(const unsigned char *str, int line)
-{
-	int len = strlen(str);
-	u8 addr;
-
-	if (len > PVC_VISIBLE_CHARS)
-		addr = 0;
-	else
-		addr = (PVC_VISIBLE_CHARS - strlen(str))/2;
-
-	pvc_write_string(str, addr, line);
-}
-
-void pvc_dump_string(const unsigned char *str)
-{
-	int len = strlen(str);
-
-	pvc_write_string(str, 0, 0);
-	if (len > PVC_VISIBLE_CHARS)
-		pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1);
-}
-
-#define BM_SIZE			8
-#define MAX_PROGRAMMABLE_CHARS	8
-int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE])
-{
-	int i;
-	int addr;
-
-	if (charnum > MAX_PROGRAMMABLE_CHARS)
-		return -ENOENT;
-
-	addr = charnum * 8;
-	pvc_write(0x40 | addr, MODE_INST);
-
-	for (i=0; i<BM_SIZE; i++)
-		pvc_write(bitmap[i], MODE_DATA);
-	return 0;
-}
-
-#define FUNC_SET_CMD	0x20
-#define  EIGHT_BYTE	(1 << 4)
-#define  FOUR_BYTE	0
-#define  TWO_LINES	(1 << 3)
-#define  ONE_LINE	0
-#define  LARGE_FONT	(1 << 2)
-#define  SMALL_FONT	0
-static void pvc_funcset(u8 cmd)
-{
-	pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)), MODE_INST);
-}
-
-#define ENTRYMODE_CMD		0x4
-#define  AUTO_INC		(1 << 1)
-#define  AUTO_DEC		0
-#define  CURSOR_FOLLOWS_DISP	(1 << 0)
-static void pvc_entrymode(u8 cmd)
-{
-	pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)), MODE_INST);
-}
-
-#define DISP_CNT_CMD	0x08
-#define  DISP_OFF	0
-#define  DISP_ON	(1 << 2)
-#define  CUR_ON		(1 << 1)
-#define  CUR_BLINK	(1 << 0)
-void pvc_dispcnt(u8 cmd)
-{
-	pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST);
-}
-
-#define MOVE_CMD	0x10
-#define  DISPLAY	(1 << 3)
-#define  CURSOR		0
-#define  RIGHT		(1 << 2)
-#define  LEFT		0
-void pvc_move(u8 cmd)
-{
-	pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST);
-}
-
-#define CLEAR_CMD	0x1
-void pvc_clear(void)
-{
-	pvc_write(CLEAR_CMD, MODE_INST);
-}
-
-#define HOME_CMD	0x2
-void pvc_home(void)
-{
-	pvc_write(HOME_CMD, MODE_INST);
-}
-
-int pvc_init(void)
-{
-	u8 cmd = EIGHT_BYTE;
-
-	if (PVC_NLINES == 2)
-		cmd |= (SMALL_FONT|TWO_LINES);
-	else
-		cmd |= (LARGE_FONT|ONE_LINE);
-	pvc_funcset(cmd);
-	pvc_dispcnt(DISP_ON);
-	pvc_entrymode(AUTO_INC);
-
-	pvc_clear();
-	pvc_write_string_centered("Display", 0);
-	pvc_write_string_centered("Initialized", 1);
-
-	return 0;
-}
-
-module_init(pvc_init);
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/picvue.h b/arch/mips/lasat/picvue.h
deleted file mode 100644
index 2a96bf9..0000000
--- a/arch/mips/lasat/picvue.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <asm/semaphore.h>
-
-struct pvc_defs {
-	volatile u32 *reg;
-	u32 data_shift;
-	u32 data_mask;
-	u32 e;
-	u32 rw;
-	u32 rs;
-};
-
-extern struct pvc_defs *picvue;
-
-#define PVC_NLINES		2
-#define PVC_DISPMEM		80
-#define PVC_LINELEN		PVC_DISPMEM / PVC_NLINES
-#define PVC_VISIBLE_CHARS	16
-
-void pvc_write_string(const unsigned char *str, u8 addr, int line);
-void pvc_write_string_centered(const unsigned char *str, int line);
-void pvc_dump_string(const unsigned char *str);
-
-#define BM_SIZE			8
-#define MAX_PROGRAMMABLE_CHARS	8
-int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]);
-
-void pvc_dispcnt(u8 cmd);
-#define  DISP_OFF	0
-#define  DISP_ON	(1 << 2)
-#define  CUR_ON		(1 << 1)
-#define  CUR_BLINK	(1 << 0)
-
-void pvc_move(u8 cmd);
-#define  DISPLAY	(1 << 3)
-#define  CURSOR		0
-#define  RIGHT		(1 << 2)
-#define  LEFT		0
-
-void pvc_clear(void);
-void pvc_home(void);
-
-extern struct semaphore pvc_sem;
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
deleted file mode 100644
index cce7cdd..0000000
--- a/arch/mips/lasat/picvue_proc.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-
-#include <linux/timer.h>
-
-#include "picvue.h"
-
-static char pvc_lines[PVC_NLINES][PVC_LINELEN+1];
-static int pvc_linedata[PVC_NLINES];
-static struct proc_dir_entry *pvc_display_dir;
-static char *pvc_linename[PVC_NLINES] = {"line1", "line2"};
-#define DISPLAY_DIR_NAME "display"
-static int scroll_dir = 0, scroll_interval = 0;
-
-static struct timer_list timer;
-
-static void pvc_display(unsigned long data) {
-	int i;
-
-	pvc_clear();
-	for (i=0; i<PVC_NLINES; i++)
-		pvc_write_string(pvc_lines[i], 0, i);
-}
-
-static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
-
-static int pvc_proc_read_line(char *page, char **start,
-                             off_t off, int count,
-                             int *eof, void *data)
-{
-        char *origpage = page;
-	int lineno = *(int *)data;
-
-	if (lineno < 0 || lineno > PVC_NLINES) {
-		printk("proc_read_line: invalid lineno %d\n", lineno);
-		return 0;
-	}
-
-	down(&pvc_sem);
-        page += sprintf(page, "%s\n", pvc_lines[lineno]);
-	up(&pvc_sem);
-
-        return page - origpage;
-}
-
-static int pvc_proc_write_line(struct file *file, const char *buffer,
-                           unsigned long count, void *data)
-{
-        int origcount = count;
-	int lineno = *(int *)data;
-
-	if (lineno < 0 || lineno > PVC_NLINES) {
-		printk("proc_write_line: invalid lineno %d\n", lineno);
-		return origcount;
-	}
-
-	if (count > PVC_LINELEN)
-		count = PVC_LINELEN;
-
-	if (buffer[count-1] == '\n')
-		count--;
-
-	down(&pvc_sem);
-	strncpy(pvc_lines[lineno], buffer, count);
-	pvc_lines[lineno][count] = '\0';
-	up(&pvc_sem);
-
-	tasklet_schedule(&pvc_display_tasklet);
-
-        return origcount;
-}
-
-static int pvc_proc_write_scroll(struct file *file, const char *buffer,
-                           unsigned long count, void *data)
-{
-        int origcount = count;
-	int cmd = simple_strtol(buffer, NULL, 10);
-
-	down(&pvc_sem);
-	if (scroll_interval != 0)
-		del_timer(&timer);
-
-	if (cmd == 0) {
-		scroll_dir = 0;
-		scroll_interval = 0;
-	} else {
-		if (cmd < 0) {
-			scroll_dir = -1;
-			scroll_interval = -cmd;
-		} else {
-			scroll_dir = 1;
-			scroll_interval = cmd;
-		}
-		add_timer(&timer);
-	}
-	up(&pvc_sem);
-
-        return origcount;
-}
-
-static int pvc_proc_read_scroll(char *page, char **start,
-                             off_t off, int count,
-                             int *eof, void *data)
-{
-        char *origpage = page;
-
-	down(&pvc_sem);
-        page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
-	up(&pvc_sem);
-
-        return page - origpage;
-}
-
-
-void pvc_proc_timerfunc(unsigned long data)
-{
-	if (scroll_dir < 0)
-		pvc_move(DISPLAY|RIGHT);
-	else if (scroll_dir > 0)
-		pvc_move(DISPLAY|LEFT);
-
-	timer.expires = jiffies + scroll_interval;
-	add_timer(&timer);
-}
-
-static void pvc_proc_cleanup(void)
-{
-	int i;
-	for (i=0; i<PVC_NLINES; i++)
-		remove_proc_entry(pvc_linename[i], pvc_display_dir);
-	remove_proc_entry("scroll", pvc_display_dir);
-	remove_proc_entry(DISPLAY_DIR_NAME, NULL);
-
-	del_timer(&timer);
-}
-
-static int __init pvc_proc_init(void)
-{
-	struct proc_dir_entry *proc_entry;
-	int i;
-
-	pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL);
-	if (pvc_display_dir == NULL)
-		goto error;
-
-	for (i=0; i<PVC_NLINES; i++) {
-		strcpy(pvc_lines[i], "");
-		pvc_linedata[i] = i;
-	}
-	for (i=0; i<PVC_NLINES; i++) {
-		proc_entry = create_proc_entry(pvc_linename[i], 0644, pvc_display_dir);
-		if (proc_entry == NULL)
-			goto error;
-		proc_entry->read_proc = pvc_proc_read_line;
-		proc_entry->write_proc = pvc_proc_write_line;
-		proc_entry->data = &pvc_linedata[i];
-	}
-	proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir);
-	if (proc_entry == NULL)
-		goto error;
-	proc_entry->write_proc = pvc_proc_write_scroll;
-	proc_entry->read_proc = pvc_proc_read_scroll;
-
-	init_timer(&timer);
-	timer.function = pvc_proc_timerfunc;
-
-	return 0;
-error:
-	pvc_proc_cleanup();
-	return -ENOMEM;
-}
-
-module_init(pvc_proc_init);
-module_exit(pvc_proc_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
deleted file mode 100644
index 812c6ac3..0000000
--- a/arch/mips/lasat/prom.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * PROM interface routines.
- */
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/ioport.h>
-#include <asm/bootinfo.h>
-#include <asm/lasat/lasat.h>
-#include <asm/cpu.h>
-
-#include "at93c.h"
-#include <asm/lasat/eeprom.h>
-#include "prom.h"
-
-#define RESET_VECTOR	0xbfc00000
-#define PROM_JUMP_TABLE_ENTRY(n) (*((u32 *)(RESET_VECTOR + 0x20) + n))
-#define PROM_DISPLAY_ADDR	PROM_JUMP_TABLE_ENTRY(0)
-#define PROM_PUTC_ADDR		PROM_JUMP_TABLE_ENTRY(1)
-#define PROM_MONITOR_ADDR	PROM_JUMP_TABLE_ENTRY(2)
-
-static void null_prom_display(const char *string, int pos, int clear)
-{
-}
-
-static void null_prom_monitor(void)
-{
-}
-
-static void null_prom_putc(char c)
-{
-}
-
-/* these are functions provided by the bootloader */
-static void (* __prom_putc)(char c) = null_prom_putc;
-
-void prom_putchar(char c)
-{
-	__prom_putc(c);
-}
-
-void (* prom_display)(const char *string, int pos, int clear) =
-		null_prom_display;
-void (* prom_monitor)(void) = null_prom_monitor;
-
-unsigned int lasat_ndelay_divider;
-
-static void setup_prom_vectors(void)
-{
-	u32 version = *(u32 *)(RESET_VECTOR + 0x90);
-
-	if (version >= 307) {
-		prom_display = (void *)PROM_DISPLAY_ADDR;
-		__prom_putc = (void *)PROM_PUTC_ADDR;
-		prom_monitor = (void *)PROM_MONITOR_ADDR;
-	}
-	printk("prom vectors set up\n");
-}
-
-static struct at93c_defs at93c_defs[N_MACHTYPES] = {
-	{(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100,
-	AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100},
-	{(void *)AT93C_REG_200, (void *)AT93C_RDATA_REG_200, AT93C_RDATA_SHIFT_200,
-	AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200},
-};
-
-void __init prom_init(void)
-{
-	int argc = fw_arg0;
-	char **argv = (char **) fw_arg1;
-
-	setup_prom_vectors();
-
-	if (current_cpu_data.cputype == CPU_R5000) {
-	        printk("LASAT 200 board\n");
-		mips_machtype = MACH_LASAT_200;
-                lasat_ndelay_divider = LASAT_200_DIVIDER;
-        } else {
-	        printk("LASAT 100 board\n");
-		mips_machtype = MACH_LASAT_100;
-                lasat_ndelay_divider = LASAT_100_DIVIDER;
-        }
-
-	at93c = &at93c_defs[mips_machtype];
-
-	lasat_init_board_info();		/* Read info from EEPROM */
-
-	mips_machgroup = MACH_GROUP_LASAT;
-
-	/* Get the command line */
-	if (argc > 0) {
-		strncpy(arcs_cmdline, argv[0], CL_SIZE-1);
-		arcs_cmdline[CL_SIZE-1] = '\0';
-	}
-
-	/* Set the I/O base address */
-	set_io_port_base(KSEG1);
-
-	/* Set memory regions */
-	ioport_resource.start = 0;
-	ioport_resource.end = 0xffffffff;	/* Wrong, fixme.  */
-
-	add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM);
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-const char *get_system_type(void)
-{
-	return lasat_board_info.li_bmstr;
-}
diff --git a/arch/mips/lasat/prom.h b/arch/mips/lasat/prom.h
deleted file mode 100644
index 019d45f..0000000
--- a/arch/mips/lasat/prom.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef PROM_H
-#define PROM_H
-extern void (* prom_display)(const char *string, int pos, int clear);
-extern void (* prom_monitor)(void);
-#endif
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c
deleted file mode 100644
index 9e22acf..0000000
--- a/arch/mips/lasat/reset.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Reset the LASAT board.
- */
-#include <linux/kernel.h>
-#include <linux/pm.h>
-
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/lasat/lasat.h>
-
-#include "picvue.h"
-#include "prom.h"
-
-static void lasat_machine_restart(char *command);
-static void lasat_machine_halt(void);
-
-/* Used to set machine to boot in service mode via /proc interface */
-int lasat_boot_to_service = 0;
-
-static void lasat_machine_restart(char *command)
-{
-	local_irq_disable();
-
-	if (lasat_boot_to_service) {
-		printk("machine_restart: Rebooting to service mode\n");
-		*(volatile unsigned int *)0xa0000024 = 0xdeadbeef;
-		*(volatile unsigned int *)0xa00000fc = 0xfedeabba;
-	}
-	*lasat_misc->reset_reg = 0xbedead;
-	for (;;) ;
-}
-
-#define MESSAGE "System halted"
-static void lasat_machine_halt(void)
-{
-	local_irq_disable();
-
-	/* Disable interrupts and loop forever */
-	printk(KERN_NOTICE MESSAGE "\n");
-#ifdef CONFIG_PICVUE
-	pvc_clear();
-	pvc_write_string(MESSAGE, 0, 0);
-#endif
-	prom_monitor();
-	for (;;) ;
-}
-
-void lasat_reboot_setup(void)
-{
-	_machine_restart = lasat_machine_restart;
-	_machine_halt = lasat_machine_halt;
-	pm_power_off = lasat_machine_halt;
-}
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
deleted file mode 100644
index 488007f..0000000
--- a/arch/mips/lasat/setup.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
- *
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * Brian Murphy <brian@murphy.dk>
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Lasat specific setup.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-
-#include <asm/time.h>
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/lasat/lasat.h>
-#include <asm/lasat/serial.h>
-
-#ifdef CONFIG_PICVUE
-#include <linux/notifier.h>
-#endif
-
-#include "ds1603.h"
-#include <asm/lasat/ds1603.h>
-#include <asm/lasat/picvue.h>
-#include <asm/lasat/eeprom.h>
-
-#include "prom.h"
-
-int lasat_command_line = 0;
-void lasatint_init(void);
-
-extern void lasat_reboot_setup(void);
-extern void pcisetup(void);
-extern void edhac_init(void *, void *, void *);
-extern void addrflt_init(void);
-
-struct lasat_misc lasat_misc_info[N_MACHTYPES] = {
-	{(void *)KSEG1ADDR(0x1c840000), (void *)KSEG1ADDR(0x1c800000), 2},
-	{(void *)KSEG1ADDR(0x11080000), (void *)KSEG1ADDR(0x11000000), 6}
-};
-
-struct lasat_misc *lasat_misc = NULL;
-
-#ifdef CONFIG_DS1603
-static struct ds_defs ds_defs[N_MACHTYPES] = {
-	{ (void *)DS1603_REG_100, (void *)DS1603_REG_100,
-		DS1603_RST_100, DS1603_CLK_100, DS1603_DATA_100,
-		DS1603_DATA_SHIFT_100, 0, 0 },
-	{ (void *)DS1603_REG_200, (void *)DS1603_DATA_REG_200,
-		DS1603_RST_200, DS1603_CLK_200, DS1603_DATA_200,
-		DS1603_DATA_READ_SHIFT_200, 1, 2000 }
-};
-#endif
-
-#ifdef CONFIG_PICVUE
-#include "picvue.h"
-static struct pvc_defs pvc_defs[N_MACHTYPES] = {
-	{ (void *)PVC_REG_100, PVC_DATA_SHIFT_100, PVC_DATA_M_100,
-		PVC_E_100, PVC_RW_100, PVC_RS_100 },
-	{ (void *)PVC_REG_200, PVC_DATA_SHIFT_200, PVC_DATA_M_200,
-		PVC_E_200, PVC_RW_200, PVC_RS_200 }
-};
-#endif
-
-static int lasat_panic_display(struct notifier_block *this,
-			     unsigned long event, void *ptr)
-{
-#ifdef CONFIG_PICVUE
-	unsigned char *string = ptr;
-	if (string == NULL)
-		string = "Kernel Panic";
-	pvc_dump_string(string);
-#endif
-	return NOTIFY_DONE;
-}
-
-static int lasat_panic_prom_monitor(struct notifier_block *this,
-			     unsigned long event, void *ptr)
-{
-	prom_monitor();
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block lasat_panic_block[] =
-{
-	{ lasat_panic_display, NULL, INT_MAX },
-	{ lasat_panic_prom_monitor, NULL, INT_MIN }
-};
-
-static void lasat_time_init(void)
-{
-	mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
-}
-
-#define DYNAMIC_SERIAL_INIT
-#ifdef DYNAMIC_SERIAL_INIT
-void __init serial_init(void)
-{
-#ifdef CONFIG_SERIAL_8250
-	struct uart_port s;
-
-	memset(&s, 0, sizeof(s));
-
-	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	s.iotype = UPIO_MEM;
-
-	if (mips_machtype == MACH_LASAT_100) {
-		s.uartclk = LASAT_BASE_BAUD_100 * 16;
-		s.irq = LASATINT_UART_100;
-		s.regshift = LASAT_UART_REGS_SHIFT_100;
-		s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_100);
-	} else {
-		s.uartclk = LASAT_BASE_BAUD_200 * 16;
-		s.irq = LASATINT_UART_200;
-		s.regshift = LASAT_UART_REGS_SHIFT_200;
-		s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_200);
-	}
-
-	if (early_serial_setup(&s) != 0)
-		printk(KERN_ERR "Serial setup failed!\n");
-#endif
-}
-#endif
-
-void __init plat_mem_setup(void)
-{
-	int i;
-	lasat_misc  = &lasat_misc_info[mips_machtype];
-#ifdef CONFIG_PICVUE
-	picvue = &pvc_defs[mips_machtype];
-#endif
-
-	/* Set up panic notifier */
-	for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
-		atomic_notifier_chain_register(&panic_notifier_list,
-				&lasat_panic_block[i]);
-
-	lasat_reboot_setup();
-
-	board_time_init = lasat_time_init;
-
-#ifdef CONFIG_DS1603
-	ds1603 = &ds_defs[mips_machtype];
-	rtc_mips_get_time = ds1603_read;
-	rtc_mips_set_time = ds1603_set;
-#endif
-
-#ifdef DYNAMIC_SERIAL_INIT
-	serial_init();
-#endif
-	/* Switch from prom exception handler to normal mode */
-	change_c0_status(ST0_BEV,0);
-
-	pr_info("Lasat specific initialization complete\n");
-}
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
deleted file mode 100644
index 699ab18..0000000
--- a/arch/mips/lasat/sysctl.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines specific to the LASAT boards
- */
-#include <linux/types.h>
-#include <asm/lasat/lasat.h>
-
-#include <linux/module.h>
-#include <linux/sysctl.h>
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/net.h>
-#include <linux/inet.h>
-#include <linux/mutex.h>
-#include <asm/uaccess.h>
-
-#include "sysctl.h"
-#include "ds1603.h"
-
-static DEFINE_MUTEX(lasat_info_mutex);
-
-/* Strategy function to write EEPROM after changing string entry */
-int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
-		void *oldval, size_t *oldlenp,
-		void *newval, size_t newlen)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = sysctl_string(table, name,
-			  nlen, oldval, oldlenp, newval, newlen);
-	if (r < 0) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	if (newval && newlen) {
-		lasat_write_eeprom_info();
-	}
-	mutex_unlock(&lasat_info_mutex);
-	return 1;
-}
-
-
-/* And the same for proc */
-int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = proc_dostring(table, write, filp, buffer, lenp, ppos);
-	if ( (!write) || r) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	lasat_write_eeprom_info();
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-
-/* proc function to write EEPROM after changing int entry */
-int proc_dolasatint(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
-	if ( (!write) || r) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	lasat_write_eeprom_info();
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-
-static int rtctmp;
-
-#ifdef CONFIG_DS1603
-/* proc function to read/write RealTime Clock */
-int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	if (!write) {
-		rtctmp = ds1603_read();
-		/* check for time < 0 and set to 0 */
-		if (rtctmp < 0)
-			rtctmp = 0;
-	}
-	r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
-	if ( (!write) || r) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	ds1603_set(rtctmp);
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-#endif
-
-/* Sysctl for setting the IP addresses */
-int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
-		    void *oldval, size_t *oldlenp,
-		    void *newval, size_t newlen)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
-	if (r < 0) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	if (newval && newlen) {
-		lasat_write_eeprom_info();
-	}
-	mutex_unlock(&lasat_info_mutex);
-	return 1;
-}
-
-#ifdef CONFIG_DS1603
-/* Same for RTC */
-int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
-		    void *oldval, size_t *oldlenp,
-		    void *newval, size_t newlen)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	rtctmp = ds1603_read();
-	if (rtctmp < 0)
-		rtctmp = 0;
-	r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
-	if (r < 0) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	if (newval && newlen) {
-		ds1603_set(rtctmp);
-	}
-	mutex_unlock(&lasat_info_mutex);
-	return 1;
-}
-#endif
-
-#ifdef CONFIG_INET
-static char lasat_bcastaddr[16];
-
-void update_bcastaddr(void)
-{
-	unsigned int ip;
-
-	ip = (lasat_board_info.li_eeprom_info.ipaddr &
-		lasat_board_info.li_eeprom_info.netmask) |
-		~lasat_board_info.li_eeprom_info.netmask;
-
-	sprintf(lasat_bcastaddr, "%d.%d.%d.%d",
-			(ip      ) & 0xff,
-			(ip >>  8) & 0xff,
-			(ip >> 16) & 0xff,
-			(ip >> 24) & 0xff);
-}
-
-static char proc_lasat_ipbuf[32];
-/* Parsing of IP address */
-int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int len;
-        unsigned int ip;
-	char *p, c;
-
-	if (!table->data || !table->maxlen || !*lenp ||
-	    (*ppos && !write)) {
-		*lenp = 0;
-		return 0;
-	}
-
-	mutex_lock(&lasat_info_mutex);
-	if (write) {
-		len = 0;
-		p = buffer;
-		while (len < *lenp) {
-			if(get_user(c, p++)) {
-				mutex_unlock(&lasat_info_mutex);
-				return -EFAULT;
-			}
-			if (c == 0 || c == '\n')
-				break;
-			len++;
-		}
-		if (len >= sizeof(proc_lasat_ipbuf)-1)
-			len = sizeof(proc_lasat_ipbuf) - 1;
-		if (copy_from_user(proc_lasat_ipbuf, buffer, len))
-		{
-			mutex_unlock(&lasat_info_mutex);
-			return -EFAULT;
-		}
-		proc_lasat_ipbuf[len] = 0;
-		*ppos += *lenp;
-		/* Now see if we can convert it to a valid IP */
-		ip = in_aton(proc_lasat_ipbuf);
-		*(unsigned int *)(table->data) = ip;
-		lasat_write_eeprom_info();
-	} else {
-		ip = *(unsigned int *)(table->data);
-		sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d",
-			(ip      ) & 0xff,
-			(ip >>  8) & 0xff,
-			(ip >> 16) & 0xff,
-			(ip >> 24) & 0xff);
-		len = strlen(proc_lasat_ipbuf);
-		if (len > *lenp)
-			len = *lenp;
-		if (len)
-			if(copy_to_user(buffer, proc_lasat_ipbuf, len)) {
-				mutex_unlock(&lasat_info_mutex);
-				return -EFAULT;
-			}
-		if (len < *lenp) {
-			if(put_user('\n', ((char *) buffer) + len)) {
-				mutex_unlock(&lasat_info_mutex);
-				return -EFAULT;
-			}
-			len++;
-		}
-		*lenp = len;
-		*ppos += len;
-	}
-	update_bcastaddr();
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-#endif /* defined(CONFIG_INET) */
-
-static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
-				     void *oldval, size_t *oldlenp,
-				     void *newval, size_t newlen)
-{
-	int r;
-
-	mutex_lock(&lasat_info_mutex);
-	r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
-	if (r < 0) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-
-	if (newval && newlen)
-	{
-		if (name && *name == LASAT_PRID)
-			lasat_board_info.li_eeprom_info.prid = *(int*)newval;
-
-		lasat_write_eeprom_info();
-		lasat_init_board_info();
-	}
-	mutex_unlock(&lasat_info_mutex);
-
-	return 0;
-}
-
-int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
-	if ( (!write) || r) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	if (filp && filp->f_path.dentry)
-	{
-		if (!strcmp(filp->f_path.dentry->d_name.name, "prid"))
-			lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid;
-		if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess"))
-			lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
-	}
-	lasat_write_eeprom_info();
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-
-extern int lasat_boot_to_service;
-
-#ifdef CONFIG_SYSCTL
-
-static ctl_table lasat_table[] = {
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "cpu-hz",
-		.data		= &lasat_board_info.li_cpu_hz,
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "bus-hz",
-		.data		= &lasat_board_info.li_bus_hz,
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "bmid",
-		.data		= &lasat_board_info.li_bmid,
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "prid",
-		.data		= &lasat_board_info.li_prid,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_lasat_eeprom_value,
-		.strategy	= &sysctl_lasat_eeprom_value
-	},
-#ifdef CONFIG_INET
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "ipaddr",
-		.data		= &lasat_board_info.li_eeprom_info.ipaddr,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_lasat_ip,
-		.strategy	= &sysctl_lasat_intvec
-	},
-	{
-		.ctl_name	= LASAT_NETMASK,
-		.procname	= "netmask",
-		.data		= &lasat_board_info.li_eeprom_info.netmask,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_lasat_ip,
-		.strategy	= &sysctl_lasat_intvec
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "bcastaddr",
-		.data		= &lasat_bcastaddr,
-		.maxlen		= sizeof(lasat_bcastaddr),
-		.mode		= 0600,
-		.proc_handler	= &proc_dostring,
-		.strategy	= &sysctl_string
-	},
-#endif
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "passwd_hash",
-		.data		= &lasat_board_info.li_eeprom_info.passwd_hash,
-		.maxlen		= sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
-		.mode		= 0600,
-		.proc_handler	= &proc_dolasatstring,
-		.strategy	= &sysctl_lasatstring
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "boot-service",
-		.data		= &lasat_boot_to_service,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
-	},
-#ifdef CONFIG_DS1603
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "rtc",
-		.data		= &rtctmp,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dolasatrtc,
-		.strategy	= &sysctl_lasat_rtc
-	},
-#endif
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "namestr",
-		.data		= &lasat_board_info.li_namestr,
-		.maxlen		= sizeof(lasat_board_info.li_namestr),
-		.mode		= 0444,
-		.proc_handler	=  &proc_dostring,
-		.strategy	= &sysctl_string
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "typestr",
-		.data		= &lasat_board_info.li_typestr,
-		.maxlen		= sizeof(lasat_board_info.li_typestr),
-		.mode		= 0444,
-		.proc_handler	= &proc_dostring,
-		.strategy	= &sysctl_string
-	},
-	{}
-};
-
-static ctl_table lasat_root_table[] = {
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "lasat",
-		.mode		=  0555,
-		.child		= lasat_table
-	},
-	{}
-};
-
-static int __init lasat_register_sysctl(void)
-{
-	struct ctl_table_header *lasat_table_header;
-
-	lasat_table_header =
-		register_sysctl_table(lasat_root_table);
-
-	return 0;
-}
-
-__initcall(lasat_register_sysctl);
-#endif /* CONFIG_SYSCTL */
diff --git a/arch/mips/lasat/sysctl.h b/arch/mips/lasat/sysctl.h
deleted file mode 100644
index 4d139d2..0000000
--- a/arch/mips/lasat/sysctl.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * LASAT sysctl values
- */
-
-#ifndef _LASAT_SYSCTL_H
-#define _LASAT_SYSCTL_H
-
-/* /proc/sys/lasat */
-enum {
-	LASAT_CPU_HZ=1,
-	LASAT_BUS_HZ,
-	LASAT_MODEL,
-	LASAT_PRID,
-	LASAT_IPADDR,
-	LASAT_NETMASK,
-	LASAT_BCAST,
-	LASAT_PASSWORD,
-	LASAT_SBOOT,
-	LASAT_RTC,
-	LASAT_NAMESTR,
-	LASAT_TYPESTR,
-};
-
-#endif /* _LASAT_SYSCTL_H */
diff --git a/arch/mips/lemote/lm2e/Makefile b/arch/mips/lemote/lm2e/Makefile
new file mode 100644
index 0000000..fb1b48c
--- /dev/null
+++ b/arch/mips/lemote/lm2e/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Lemote Fulong mini-PC board.
+#
+
+obj-y += setup.o prom.o reset.o irq.o pci.o bonito-irq.o dbg_io.o mem.o
+EXTRA_AFLAGS := $(CFLAGS)
+
diff --git a/arch/mips/lemote/lm2e/bonito-irq.c b/arch/mips/lemote/lm2e/bonito-irq.c
new file mode 100644
index 0000000..8fc3bce
--- /dev/null
+++ b/arch/mips/lemote/lm2e/bonito-irq.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+
+static inline void bonito_irq_enable(unsigned int irq)
+{
+	BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE));
+	mmiowb();
+}
+
+static inline void bonito_irq_disable(unsigned int irq)
+{
+	BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE));
+	mmiowb();
+}
+
+static struct irq_chip bonito_irq_type = {
+	.name	= "bonito_irq",
+	.ack	= bonito_irq_disable,
+	.mask	= bonito_irq_disable,
+	.mask_ack = bonito_irq_disable,
+	.unmask	= bonito_irq_enable,
+};
+
+static struct irqaction dma_timeout_irqaction = {
+	.handler	= no_action,
+	.name		= "dma_timeout",
+};
+
+void bonito_irq_init(void)
+{
+	u32 i;
+
+	for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++) {
+		set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
+	}
+
+	setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction);
+}
diff --git a/arch/mips/lemote/lm2e/dbg_io.c b/arch/mips/lemote/lm2e/dbg_io.c
new file mode 100644
index 0000000..6c95da3
--- /dev/null
+++ b/arch/mips/lemote/lm2e/dbg_io.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <asm/serial.h>
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+#ifdef CONFIG_64BIT
+#define         BASE                    (0xffffffffbfd003f8)
+#else
+#define         BASE                    (0xbfd003f8)
+#endif
+
+#define         MAX_BAUD                BASE_BAUD
+/* === END OF CONFIG === */
+
+#define         REG_OFFSET              1
+
+/* register offset */
+#define         OFS_RCV_BUFFER          0
+#define         OFS_TRANS_HOLD          0
+#define         OFS_SEND_BUFFER         0
+#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
+#define         OFS_INTR_ID             (2*REG_OFFSET)
+#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
+#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
+#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
+#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
+#define         OFS_LINE_STATUS         (5*REG_OFFSET)
+#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
+#define         OFS_RS232_INPUT         (6*REG_OFFSET)
+#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
+
+#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
+#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
+
+/* memory-mapped read/write of the port */
+#define         UART16550_READ(y)	readb((char *)BASE + (y))
+#define         UART16550_WRITE(y, z)	writeb(z, (char *)BASE + (y))
+
+void debugInit(u32 baud, u8 data, u8 parity, u8 stop)
+{
+	u32 divisor;
+
+	/* disable interrupts */
+	UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+	/* set up buad rate */
+	/* set DIAB bit */
+	UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+	/* set divisor */
+	divisor = MAX_BAUD / baud;
+	UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+	UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+	/* clear DIAB bit */
+	UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+
+	/* set data format */
+	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized;
+
+u8 getDebugChar(void)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_115200,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0) ;
+	return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+int putDebugChar(u8 byte)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		/*
+		   debugInit(UART16550_BAUD_115200,
+		   UART16550_DATA_8BIT,
+		   UART16550_PARITY_NONE, UART16550_STOP_1BIT); */
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0) ;
+	UART16550_WRITE(OFS_SEND_BUFFER, byte);
+	return 1;
+}
diff --git a/arch/mips/lemote/lm2e/irq.c b/arch/mips/lemote/lm2e/irq.c
new file mode 100644
index 0000000..05693bc
--- /dev/null
+++ b/arch/mips/lemote/lm2e/irq.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+#include <asm/mips-boards/bonito64.h>
+
+
+/*
+ * the first level int-handler will jump here if it is a bonito irq
+ */
+static void bonito_irqdispatch(void)
+{
+	u32 int_status;
+	int i;
+
+	/* workaround the IO dma problem: let cpu looping to allow DMA finish */
+	int_status = BONITO_INTISR;
+	if (int_status & (1 << 10)) {
+		while (int_status & (1 << 10)) {
+			udelay(1);
+			int_status = BONITO_INTISR;
+		}
+	}
+
+	/* Get pending sources, masked by current enables */
+	int_status = BONITO_INTISR & BONITO_INTEN;
+
+	if (int_status != 0) {
+		i = __ffs(int_status);
+		int_status &= ~(1 << i);
+		do_IRQ(BONITO_IRQ_BASE + i);
+	}
+}
+
+static void i8259_irqdispatch(void)
+{
+	int irq;
+
+	irq = i8259_irq();
+	if (irq >= 0) {
+		do_IRQ(irq);
+	} else {
+		spurious_interrupt();
+	}
+
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (pending & CAUSEF_IP7) {
+		do_IRQ(MIPS_CPU_IRQ_BASE + 7);
+	} else if (pending & CAUSEF_IP5) {
+		i8259_irqdispatch();
+	} else if (pending & CAUSEF_IP2) {
+		bonito_irqdispatch();
+	} else {
+		spurious_interrupt();
+	}
+}
+
+static struct irqaction cascade_irqaction = {
+	.handler = no_action,
+	.mask = CPU_MASK_NONE,
+	.name = "cascade",
+};
+
+void __init arch_init_irq(void)
+{
+	extern void bonito_irq_init(void);
+
+	/*
+	 * Clear all of the interrupts while we change the able around a bit.
+	 * int-handler is not on bootstrap
+	 */
+	clear_c0_status(ST0_IM | ST0_BEV);
+	local_irq_disable();
+
+	/* most bonito irq should be level triggered */
+	BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR |
+		BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES;
+	BONITO_INTSTEER = 0;
+
+	/*
+	 * Mask out all interrupt by writing "1" to all bit position in
+	 * the interrupt reset reg.
+	 */
+	BONITO_INTENCLR = ~0;
+
+	/* init all controller
+	 *   0-15         ------> i8259 interrupt
+	 *   16-23        ------> mips cpu interrupt
+	 *   32-63        ------> bonito irq
+	 */
+
+	/* Sets the first-level interrupt dispatcher. */
+	mips_cpu_irq_init();
+	init_i8259_irqs();
+	bonito_irq_init();
+
+	/*
+	printk("GPIODATA=%x, GPIOIE=%x\n", BONITO_GPIODATA, BONITO_GPIOIE);
+	printk("INTEN=%x, INTSET=%x, INTCLR=%x, INTISR=%x\n",
+			BONITO_INTEN, BONITO_INTENSET,
+			BONITO_INTENCLR, BONITO_INTISR);
+	*/
+
+	/* bonito irq at IP2 */
+	setup_irq(MIPS_CPU_IRQ_BASE + 2, &cascade_irqaction);
+	/* 8259 irq at IP5 */
+	setup_irq(MIPS_CPU_IRQ_BASE + 5, &cascade_irqaction);
+
+}
diff --git a/arch/mips/lemote/lm2e/mem.c b/arch/mips/lemote/lm2e/mem.c
new file mode 100644
index 0000000..16cd215
--- /dev/null
+++ b/arch/mips/lemote/lm2e/mem.c
@@ -0,0 +1,23 @@
+/*
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+
+/* override of arch/mips/mm/cache.c: __uncached_access */
+int __uncached_access(struct file *file, unsigned long addr)
+{
+	if (file->f_flags & O_SYNC)
+		return 1;
+
+	/*
+	 * On the Lemote Loongson 2e system, the peripheral registers
+	 * reside between 0x1000:0000 and 0x2000:0000.
+	 */
+	return addr >= __pa(high_memory) ||
+		((addr >= 0x10000000) && (addr < 0x20000000));
+}
diff --git a/arch/mips/lemote/lm2e/pci.c b/arch/mips/lemote/lm2e/pci.c
new file mode 100644
index 0000000..1ade1ce
--- /dev/null
+++ b/arch/mips/lemote/lm2e/pci.c
@@ -0,0 +1,93 @@
+/*
+ * pci.c
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/mips-boards/bonito64.h>
+
+extern struct pci_ops bonito64_pci_ops;
+
+static struct resource loongson2e_pci_mem_resource = {
+	.name   = "LOONGSON2E PCI MEM",
+	.start  = 0x14000000UL,
+	.end    = 0x1fffffffUL,
+	.flags  = IORESOURCE_MEM,
+};
+
+static struct resource loongson2e_pci_io_resource = {
+	.name   = "LOONGSON2E PCI IO MEM",
+	.start  = 0x00004000UL,
+	.end    = IO_SPACE_LIMIT,
+	.flags  = IORESOURCE_IO,
+};
+
+static struct pci_controller  loongson2e_pci_controller = {
+	.pci_ops        = &bonito64_pci_ops,
+	.io_resource    = &loongson2e_pci_io_resource,
+	.mem_resource   = &loongson2e_pci_mem_resource,
+	.mem_offset     = 0x00000000UL,
+	.io_offset      = 0x00000000UL,
+};
+
+static void __init ict_pcimap(void)
+{
+	/*
+	 * local to PCI mapping: [256M,512M] -> [256M,512M]; differ from PMON
+	 *
+	 * CPU address space [256M,448M] is window for accessing pci space
+	 * we set pcimap_lo[0,1,2] to map it to pci space [256M,448M]
+	 * pcimap: bit18,pcimap_2; bit[17-12],lo2;bit[11-6],lo1;bit[5-0],lo0
+	 */
+	/* 1,00 0110 ,0001 01,00 0000 */
+	BONITO_PCIMAP = 0x46140;
+
+	/* 1, 00 0010, 0000,01, 00 0000 */
+	/* BONITO_PCIMAP = 0x42040; */
+
+	/*
+	 * PCI to local mapping: [2G,2G+256M] -> [0,256M]
+	 */
+	BONITO_PCIBASE0 = 0x80000000;
+	BONITO_PCIBASE1 = 0x00800000;
+	BONITO_PCIBASE2 = 0x90000000;
+
+}
+
+static int __init pcibios_init(void)
+{
+	extern int pci_probe_only;
+	pci_probe_only = 0;
+
+	ict_pcimap();
+	register_pci_controller(&loongson2e_pci_controller);
+
+	return 0;
+}
+
+arch_initcall(pcibios_init);
diff --git a/arch/mips/lemote/lm2e/prom.c b/arch/mips/lemote/lm2e/prom.c
new file mode 100644
index 0000000..67312d7
--- /dev/null
+++ b/arch/mips/lemote/lm2e/prom.c
@@ -0,0 +1,104 @@
+/*
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright 2003 ICT CAS
+ * Author: Michael Guo <guoyi@ict.ac.cn>
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+extern unsigned long bus_clock;
+extern unsigned long cpu_clock;
+extern unsigned int memsize, highmemsize;
+extern int putDebugChar(unsigned char byte);
+
+static int argc;
+/* pmon passes arguments in 32bit pointers */
+static int *arg;
+static int *env;
+
+const char *get_system_type(void)
+{
+	return "lemote-fulong";
+}
+
+void __init prom_init_cmdline(void)
+{
+	int i;
+	long l;
+
+	/* arg[0] is "g", the rest is boot parameters */
+	arcs_cmdline[0] = '\0';
+	for (i = 1; i < argc; i++) {
+		l = (long)arg[i];
+		if (strlen(arcs_cmdline) + strlen(((char *)l) + 1)
+		    >= sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, ((char *)l));
+		strcat(arcs_cmdline, " ");
+	}
+}
+
+void __init prom_init(void)
+{
+	long l;
+	argc = fw_arg0;
+	arg = (int *)fw_arg1;
+	env = (int *)fw_arg2;
+
+	mips_machgroup = MACH_GROUP_LEMOTE;
+	mips_machtype = MACH_LEMOTE_FULONG;
+
+	prom_init_cmdline();
+
+	if ((strstr(arcs_cmdline, "console=")) == NULL)
+		strcat(arcs_cmdline, " console=ttyS0,115200");
+	if ((strstr(arcs_cmdline, "root=")) == NULL)
+		strcat(arcs_cmdline, " root=/dev/hda1");
+
+#define parse_even_earlier(res, option, p)				\
+do {									\
+	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
+		res = simple_strtol((char *)p + strlen(option"="),	\
+				    NULL, 10);				\
+} while (0)
+
+	l = (long)*env;
+	while (l != 0) {
+		parse_even_earlier(bus_clock, "busclock", l);
+		parse_even_earlier(cpu_clock, "cpuclock", l);
+		parse_even_earlier(memsize, "memsize", l);
+		parse_even_earlier(highmemsize, "highmemsize", l);
+		env++;
+		l = (long)*env;
+	}
+	if (memsize == 0)
+		memsize = 256;
+
+	pr_info("busclock=%ld, cpuclock=%ld,memsize=%d,highmemsize=%d\n",
+	       bus_clock, cpu_clock, memsize, highmemsize);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void prom_putchar(char c)
+{
+	putDebugChar(c);
+}
diff --git a/arch/mips/lemote/lm2e/reset.c b/arch/mips/lemote/lm2e/reset.c
new file mode 100644
index 0000000..099387a
--- /dev/null
+++ b/arch/mips/lemote/lm2e/reset.c
@@ -0,0 +1,41 @@
+/*
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ */
+#include <linux/pm.h>
+
+#include <asm/reboot.h>
+
+static void loongson2e_restart(char *command)
+{
+#ifdef CONFIG_32BIT
+	*(unsigned long *)0xbfe00104 &= ~(1 << 2);
+	*(unsigned long *)0xbfe00104 |= (1 << 2);
+#else
+	*(unsigned long *)0xffffffffbfe00104 &= ~(1 << 2);
+	*(unsigned long *)0xffffffffbfe00104 |= (1 << 2);
+#endif
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+static void loongson2e_halt(void)
+{
+	while (1) ;
+}
+
+static void loongson2e_power_off(void)
+{
+	loongson2e_halt();
+}
+
+void mips_reboot_setup(void)
+{
+	_machine_restart = loongson2e_restart;
+	_machine_halt = loongson2e_halt;
+	pm_power_off = loongson2e_power_off;
+}
diff --git a/arch/mips/lemote/lm2e/setup.c b/arch/mips/lemote/lm2e/setup.c
new file mode 100644
index 0000000..0e4d1fa
--- /dev/null
+++ b/arch/mips/lemote/lm2e/setup.c
@@ -0,0 +1,134 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * setup.c - board dependent boot routines
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/time.h>
+#include <asm/wbflush.h>
+
+#ifdef CONFIG_VT
+#include <linux/console.h>
+#include <linux/screen_info.h>
+#endif
+
+extern void mips_reboot_setup(void);
+
+#ifdef CONFIG_64BIT
+#define PTR_PAD(p) ((0xffffffff00000000)|((unsigned long long)(p)))
+#else
+#define PTR_PAD(p) (p)
+#endif
+
+unsigned long cpu_clock;
+unsigned long bus_clock;
+unsigned int memsize;
+unsigned int highmemsize = 0;
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+	setup_irq(MIPS_CPU_IRQ_BASE + 7, irq);
+}
+
+static void __init loongson2e_time_init(void)
+{
+	/* setup mips r4k timer */
+	mips_hpt_frequency = cpu_clock / 2;
+}
+
+static unsigned long __init mips_rtc_get_time(void)
+{
+	return mc146818_get_cmos_time();
+}
+
+void (*__wbflush)(void);
+EXPORT_SYMBOL(__wbflush);
+
+static void wbflush_loongson2e(void)
+{
+	asm(".set\tpush\n\t"
+	    ".set\tnoreorder\n\t"
+	    ".set mips3\n\t"
+	    "sync\n\t"
+	    "nop\n\t"
+	    ".set\tpop\n\t"
+	    ".set mips0\n\t");
+}
+
+void __init plat_mem_setup(void)
+{
+	set_io_port_base(PTR_PAD(0xbfd00000));
+
+	mips_reboot_setup();
+
+	board_time_init = loongson2e_time_init;
+	rtc_mips_get_time = mips_rtc_get_time;
+
+	__wbflush = wbflush_loongson2e;
+
+	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
+#ifdef CONFIG_64BIT
+	if (highmemsize > 0) {
+		add_memory_region(0x20000000, highmemsize << 20, BOOT_MEM_RAM);
+	}
+#endif
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+
+	screen_info = (struct screen_info) {
+		0, 25,		/* orig-x, orig-y */
+		    0,		/* unused */
+		    0,		/* orig-video-page */
+		    0,		/* orig-video-mode */
+		    80,		/* orig-video-cols */
+		    0, 0, 0,	/* ega_ax, ega_bx, ega_cx */
+		    25,		/* orig-video-lines */
+		    VIDEO_TYPE_VGAC,	/* orig-video-isVGA */
+		    16		/* orig-video-points */
+	};
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+
+}
diff --git a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile
deleted file mode 100644
index 8b94d4c..0000000
--- a/arch/mips/lib-32/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for MIPS-specific library files..
-#
-
-lib-y	+= watch.o
-
-obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
-obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
-obj-$(CONFIG_CPU_NEVADA)	+= dump_tlb.o
-obj-$(CONFIG_CPU_R10000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_R3000)		+= r3k_dump_tlb.o
-obj-$(CONFIG_CPU_R4300)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R4X00)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R5000)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R5432)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R6000)		+=
-obj-$(CONFIG_CPU_R8000)		+=
-obj-$(CONFIG_CPU_RM7000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_RM9000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_SB1)		+= dump_tlb.o
-obj-$(CONFIG_CPU_TX39XX)	+= r3k_dump_tlb.o
-obj-$(CONFIG_CPU_TX49XX)	+= dump_tlb.o
-obj-$(CONFIG_CPU_VR41XX)	+= dump_tlb.o
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
deleted file mode 100644
index 6a68deb..0000000
--- a/arch/mips/lib-32/dump_tlb.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Dump R4x00 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-static inline const char *msk2str(unsigned int mask)
-{
-	switch (mask) {
-	case PM_4K:
-		return "4kb";
-	case PM_16K:
-		return "16kb";
-	case PM_64K:
-		return "64kb";
-	case PM_256K:
-		return "256kb";
-#ifndef CONFIG_CPU_VR41XX
-	case PM_1M:
-		return "1Mb";
-	case PM_4M:
-		return "4Mb";
-	case PM_16M:
-		return "16Mb";
-	case PM_64M:
-		return "64Mb";
-	case PM_256M:
-		return "256Mb";
-#endif
-	}
-
-	return "unknown";
-}
-
-#define BARRIER()					\
-	__asm__ __volatile__(				\
-		".set\tnoreorder\n\t"			\
-		"nop;nop;nop;nop;nop;nop;nop\n\t"	\
-		".set\treorder");
-
-void dump_tlb(int first, int last)
-{
-	unsigned int pagemask, c0, c1, asid;
-	unsigned long long entrylo0, entrylo1;
-	unsigned long entryhi;
-	int i;
-
-	asid = read_c0_entryhi() & 0xff;
-
-	printk("\n");
-	for (i = first; i <= last; i++) {
-		write_c0_index(i);
-		BARRIER();
-		tlb_read();
-		BARRIER();
-		pagemask = read_c0_pagemask();
-		entryhi = read_c0_entryhi();
-		entrylo0 = read_c0_entrylo0();
-		entrylo1 = read_c0_entrylo1();
-
-		/* Unused entries have a virtual address in KSEG0.  */
-		if ((entryhi & 0xf0000000) != 0x80000000
-		    && (entryhi & 0xff) == asid) {
-			/*
-			 * Only print entries in use
-			 */
-			printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
-
-			c0 = (entrylo0 >> 3) & 7;
-			c1 = (entrylo1 >> 3) & 7;
-
-			printk("va=%08lx asid=%02lx\n",
-			       (entryhi & 0xffffe000), (entryhi & 0xff));
-			printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
-			       (entrylo0 << 6) & PAGE_MASK, c0,
-			       (entrylo0 & 4) ? 1 : 0,
-			       (entrylo0 & 2) ? 1 : 0, (entrylo0 & 1));
-			printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
-			       (entrylo1 << 6) & PAGE_MASK, c1,
-			       (entrylo1 & 4) ? 1 : 0,
-			       (entrylo1 & 2) ? 1 : 0, (entrylo1 & 1));
-			printk("\n");
-		}
-	}
-
-	write_c0_entryhi(asid);
-}
-
-void dump_tlb_all(void)
-{
-	dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
-	int wired;
-
-	wired = read_c0_wired();
-	printk("Wired: %d", wired);
-	dump_tlb(0, read_c0_wired());
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
-	unsigned int flags, oldpid;
-	int index;
-
-	local_irq_save(flags);
-	oldpid = read_c0_entryhi() & 0xff;
-	BARRIER();
-	write_c0_entryhi((addr & PAGE_MASK) | oldpid);
-	BARRIER();
-	tlb_probe();
-	BARRIER();
-	index = read_c0_index();
-	write_c0_entryhi(oldpid);
-	local_irq_restore(flags);
-
-	if (index < 0) {
-		printk("No entry for address 0x%08lx in TLB\n", addr);
-		return;
-	}
-
-	printk("Entry %d maps address 0x%08lx\n", index, addr);
-	dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
-	dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
-	pgd_t *page_dir, *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte, page;
-	unsigned long addr, val;
-
-	addr = (unsigned long) address;
-
-	printk("Addr                 == %08lx\n", addr);
-	printk("task                 == %8p\n", t);
-	printk("task->mm             == %8p\n", t->mm);
-	//printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
-
-	if (addr > KSEG0) {
-		page_dir = pgd_offset_k(0);
-		pgd = pgd_offset_k(addr);
-	} else if (t->mm) {
-		page_dir = pgd_offset(t->mm, 0);
-		pgd = pgd_offset(t->mm, addr);
-	} else {
-		printk("Current thread has no mm\n");
-		return;
-	}
-	printk("page_dir == %08x\n", (unsigned int) page_dir);
-	printk("pgd == %08x, ", (unsigned int) pgd);
-	pud = pud_offset(pgd, addr);
-	printk("pud == %08x, ", (unsigned int) pud);
-
-	pmd = pmd_offset(pud, addr);
-	printk("pmd == %08x, ", (unsigned int) pmd);
-
-	pte = pte_offset(pmd, addr);
-	printk("pte == %08x, ", (unsigned int) pte);
-
-	page = *pte;
-#ifdef CONFIG_64BIT_PHYS_ADDR
-	printk("page == %08Lx\n", pte_val(page));
-#else
-	printk("page == %08lx\n", pte_val(page));
-#endif
-
-	val = pte_val(page);
-	if (val & _PAGE_PRESENT)
-		printk("present ");
-	if (val & _PAGE_READ)
-		printk("read ");
-	if (val & _PAGE_WRITE)
-		printk("write ");
-	if (val & _PAGE_ACCESSED)
-		printk("accessed ");
-	if (val & _PAGE_MODIFIED)
-		printk("modified ");
-	if (val & _PAGE_R4KBUG)
-		printk("r4kbug ");
-	if (val & _PAGE_GLOBAL)
-		printk("global ");
-	if (val & _PAGE_VALID)
-		printk("valid ");
-	printk("\n");
-}
-
-void dump_list_current(void *address)
-{
-	dump_list_process(current, address);
-}
-
-unsigned int vtop(void *address)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	unsigned int addr, paddr;
-
-	addr = (unsigned long) address;
-	pgd = pgd_offset(current->mm, addr);
-	pud = pud_offset(pgd, addr);
-	pmd = pmd_offset(pud, addr);
-	pte = pte_offset(pmd, addr);
-	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
-	paddr |= (addr & ~PAGE_MASK);
-
-	return paddr;
-}
-
-void dump16(unsigned long *p)
-{
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		printk("*%08lx == %08lx, ", (unsigned long) p, *p);
-		p++;
-		printk("*%08lx == %08lx\n", (unsigned long) p, *p);
-		p++;
-	}
-}
diff --git a/arch/mips/lib-32/r3k_dump_tlb.c b/arch/mips/lib-32/r3k_dump_tlb.c
deleted file mode 100644
index 4f2cb74..0000000
--- a/arch/mips/lib-32/r3k_dump_tlb.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Dump R3000 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- * Copyright (C) 1999 by Harald Koerfgen
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-extern int r3k_have_wired_reg;	/* defined in tlb-r3k.c */
-
-void dump_tlb(int first, int last)
-{
-	int	i;
-	unsigned int asid;
-	unsigned long entryhi, entrylo0;
-
-	asid = read_c0_entryhi() & 0xfc0;
-
-	for (i = first; i <= last; i++) {
-		write_c0_index(i<<8);
-		__asm__ __volatile__(
-			".set\tnoreorder\n\t"
-			"tlbr\n\t"
-			"nop\n\t"
-			".set\treorder");
-		entryhi  = read_c0_entryhi();
-		entrylo0 = read_c0_entrylo0();
-
-		/* Unused entries have a virtual address of KSEG0.  */
-		if ((entryhi & 0xffffe000) != 0x80000000
-		    && (entryhi & 0xfc0) == asid) {
-			/*
-			 * Only print entries in use
-			 */
-			printk("Index: %2d ", i);
-
-			printk("va=%08lx asid=%08lx"
-			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
-			       (entryhi & 0xffffe000),
-			       entryhi & 0xfc0,
-			       entrylo0 & PAGE_MASK,
-			       (entrylo0 & (1 << 11)) ? 1 : 0,
-			       (entrylo0 & (1 << 10)) ? 1 : 0,
-			       (entrylo0 & (1 << 9)) ? 1 : 0,
-			       (entrylo0 & (1 << 8)) ? 1 : 0);
-		}
-	}
-	printk("\n");
-
-	write_c0_entryhi(asid);
-}
-
-void dump_tlb_all(void)
-{
-	dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
-	int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
-
-	printk("Wired: %d", wired);
-	dump_tlb(0, wired - 1);
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
-	unsigned long flags, oldpid;
-	int index;
-
-	local_irq_save(flags);
-	oldpid = read_c0_entryhi() & 0xff;
-	write_c0_entryhi((addr & PAGE_MASK) | oldpid);
-	tlb_probe();
-	index = read_c0_index();
-	write_c0_entryhi(oldpid);
-	local_irq_restore(flags);
-
-	if (index < 0) {
-		printk("No entry for address 0x%08lx in TLB\n", addr);
-		return;
-	}
-
-	printk("Entry %d maps address 0x%08lx\n", index, addr);
-	dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
-	int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
-	dump_tlb(wired, current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
-	pgd_t	*page_dir, *pgd;
-	pud_t	*pud;
-	pmd_t	*pmd;
-	pte_t	*pte, page;
-	unsigned int addr;
-	unsigned long val;
-
-	addr = (unsigned int) address;
-
-	printk("Addr                 == %08x\n", addr);
-	printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
-
-	page_dir = pgd_offset(t->mm, 0);
-	printk("page_dir == %08x\n", (unsigned int) page_dir);
-
-	pgd = pgd_offset(t->mm, addr);
-	printk("pgd == %08x, ", (unsigned int) pgd);
-
-	pud = pud_offset(pgd, addr);
-	printk("pud == %08x, ", (unsigned int) pud);
-
-	pmd = pmd_offset(pud, addr);
-	printk("pmd == %08x, ", (unsigned int) pmd);
-
-	pte = pte_offset(pmd, addr);
-	printk("pte == %08x, ", (unsigned int) pte);
-
-	page = *pte;
-	printk("page == %08x\n", (unsigned int) pte_val(page));
-
-	val = pte_val(page);
-	if (val & _PAGE_PRESENT) printk("present ");
-	if (val & _PAGE_READ) printk("read ");
-	if (val & _PAGE_WRITE) printk("write ");
-	if (val & _PAGE_ACCESSED) printk("accessed ");
-	if (val & _PAGE_MODIFIED) printk("modified ");
-	if (val & _PAGE_GLOBAL) printk("global ");
-	if (val & _PAGE_VALID) printk("valid ");
-	printk("\n");
-}
-
-void dump_list_current(void *address)
-{
-	dump_list_process(current, address);
-}
-
-unsigned int vtop(void *address)
-{
-	pgd_t	*pgd;
-	pud_t	*pud;
-	pmd_t	*pmd;
-	pte_t	*pte;
-	unsigned int addr, paddr;
-
-	addr = (unsigned long) address;
-	pgd = pgd_offset(current->mm, addr);
-	pud = pud_offset(pgd, addr);
-	pmd = pmd_offset(pud, addr);
-	pte = pte_offset(pmd, addr);
-	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
-	paddr |= (addr & ~PAGE_MASK);
-
-	return paddr;
-}
-
-void dump16(unsigned long *p)
-{
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
-		p++;
-		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
-		p++;
-	}
-}
diff --git a/arch/mips/lib-32/watch.S b/arch/mips/lib-32/watch.S
deleted file mode 100644
index 808b3af..0000000
--- a/arch/mips/lib-32/watch.S
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Kernel debug stuff to use the Watch registers.
- * Useful to find stack overflows, dangling pointers etc.
- *
- * Copyright (C) 1995, 1996, 1999 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-
-		.set	noreorder
-/*
- * Parameter: a0 - logic address to watch
- *                 Currently only KSEG0 addresses are allowed!
- *            a1 - set bit #1 to trap on load references
- *                     bit #0 to trap on store references
- * Results  : none
- */
-		LEAF(__watch_set)
-		li	t0, 0x80000000
-		subu	a0, t0
-		ori	a0, 7
-		xori	a0, 7
-		or	a0, a1
-		mtc0	a0, CP0_WATCHLO
-		sw	a0, watch_savelo
-
-		jr	ra
-		 mtc0	zero, CP0_WATCHHI
-		END(__watch_set)
-
-/*
- * Parameter: none
- * Results  : none
- */
-		LEAF(__watch_clear)
-		jr	ra
-		 mtc0	zero, CP0_WATCHLO
-		END(__watch_clear)
-
-/*
- * Parameter: none
- * Results  : none
- */
-		LEAF(__watch_reenable)
-		lw	t0, watch_savelo
-		jr	ra
-		 mtc0	t0, CP0_WATCHLO
-		END(__watch_reenable)
-
-/*
- * Saved value of the c0_watchlo register for watch_reenable()
- */
-		.data
-watch_savelo:	.word	0
-		.text
diff --git a/arch/mips/lib-64/Makefile b/arch/mips/lib-64/Makefile
deleted file mode 100644
index 8b94d4c..0000000
--- a/arch/mips/lib-64/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for MIPS-specific library files..
-#
-
-lib-y	+= watch.o
-
-obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
-obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
-obj-$(CONFIG_CPU_NEVADA)	+= dump_tlb.o
-obj-$(CONFIG_CPU_R10000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_R3000)		+= r3k_dump_tlb.o
-obj-$(CONFIG_CPU_R4300)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R4X00)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R5000)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R5432)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R6000)		+=
-obj-$(CONFIG_CPU_R8000)		+=
-obj-$(CONFIG_CPU_RM7000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_RM9000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_SB1)		+= dump_tlb.o
-obj-$(CONFIG_CPU_TX39XX)	+= r3k_dump_tlb.o
-obj-$(CONFIG_CPU_TX49XX)	+= dump_tlb.o
-obj-$(CONFIG_CPU_VR41XX)	+= dump_tlb.o
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
deleted file mode 100644
index 594df1a..0000000
--- a/arch/mips/lib-64/dump_tlb.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Dump R4x00 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-static inline const char *msk2str(unsigned int mask)
-{
-	switch (mask) {
-	case PM_4K:	return "4kb";
-	case PM_16K:	return "16kb";
-	case PM_64K:	return "64kb";
-	case PM_256K:	return "256kb";
-#ifndef CONFIG_CPU_VR41XX
-	case PM_1M:	return "1Mb";
-	case PM_4M:	return "4Mb";
-	case PM_16M:	return "16Mb";
-	case PM_64M:	return "64Mb";
-	case PM_256M:	return "256Mb";
-#endif
-	}
-
-	return "unknown";
-}
-
-#define BARRIER()					\
-	__asm__ __volatile__(				\
-		".set\tnoreorder\n\t"			\
-		"nop;nop;nop;nop;nop;nop;nop\n\t"	\
-		".set\treorder");
-
-void dump_tlb(int first, int last)
-{
-	unsigned long s_entryhi, entryhi, entrylo0, entrylo1, asid;
-	unsigned int s_index, pagemask, c0, c1, i;
-
-	s_entryhi = read_c0_entryhi();
-	s_index = read_c0_index();
-	asid = s_entryhi & 0xff;
-
-	for (i = first; i <= last; i++) {
-		write_c0_index(i);
-		BARRIER();
-		tlb_read();
-		BARRIER();
-		pagemask = read_c0_pagemask();
-		entryhi  = read_c0_entryhi();
-		entrylo0 = read_c0_entrylo0();
-		entrylo1 = read_c0_entrylo1();
-
-		/* Unused entries have a virtual address of CKSEG0.  */
-		if ((entryhi & ~0x1ffffUL) != CKSEG0
-		    && (entryhi & 0xff) == asid) {
-			/*
-			 * Only print entries in use
-			 */
-			printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
-
-			c0 = (entrylo0 >> 3) & 7;
-			c1 = (entrylo1 >> 3) & 7;
-
-			printk("va=%011lx asid=%02lx\n",
-			       (entryhi & ~0x1fffUL),
-			       entryhi & 0xff);
-			printk("\t[pa=%011lx c=%d d=%d v=%d g=%ld] ",
-			       (entrylo0 << 6) & PAGE_MASK, c0,
-			       (entrylo0 & 4) ? 1 : 0,
-			       (entrylo0 & 2) ? 1 : 0,
-			       (entrylo0 & 1));
-			printk("[pa=%011lx c=%d d=%d v=%d g=%ld]\n",
-			       (entrylo1 << 6) & PAGE_MASK, c1,
-			       (entrylo1 & 4) ? 1 : 0,
-			       (entrylo1 & 2) ? 1 : 0,
-			       (entrylo1 & 1));
-		}
-	}
-	printk("\n");
-
-	write_c0_entryhi(s_entryhi);
-	write_c0_index(s_index);
-}
-
-void dump_tlb_all(void)
-{
-	dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
-	int	wired;
-
-	wired = read_c0_wired();
-	printk("Wired: %d", wired);
-	dump_tlb(0, read_c0_wired());
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
-	unsigned int flags, oldpid;
-	int index;
-
-	local_irq_save(flags);
-	oldpid = read_c0_entryhi() & 0xff;
-	BARRIER();
-	write_c0_entryhi((addr & PAGE_MASK) | oldpid);
-	BARRIER();
-	tlb_probe();
-	BARRIER();
-	index = read_c0_index();
-	write_c0_entryhi(oldpid);
-	local_irq_restore(flags);
-
-	if (index < 0) {
-		printk("No entry for address 0x%08lx in TLB\n", addr);
-		return;
-	}
-
-	printk("Entry %d maps address 0x%08lx\n", index, addr);
-	dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
-	dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
-	pgd_t	*page_dir, *pgd;
-	pud_t	*pud;
-	pmd_t	*pmd;
-	pte_t	*pte, page;
-	unsigned long addr, val;
-
-	addr = (unsigned long) address;
-
-	printk("Addr                 == %08lx\n", addr);
-	printk("tasks->mm.pgd        == %08lx\n", (unsigned long) t->mm->pgd);
-
-	page_dir = pgd_offset(t->mm, 0UL);
-	printk("page_dir == %016lx\n", (unsigned long) page_dir);
-
-	pgd = pgd_offset(t->mm, addr);
-	printk("pgd == %016lx\n", (unsigned long) pgd);
-
-	pud = pud_offset(pgd, addr);
-	printk("pud == %016lx\n", (unsigned long) pud);
-
-	pmd = pmd_offset(pud, addr);
-	printk("pmd == %016lx\n", (unsigned long) pmd);
-
-	pte = pte_offset(pmd, addr);
-	printk("pte == %016lx\n", (unsigned long) pte);
-
-	page = *pte;
-	printk("page == %08lx\n", pte_val(page));
-
-	val = pte_val(page);
-	if (val & _PAGE_PRESENT) printk("present ");
-	if (val & _PAGE_READ) printk("read ");
-	if (val & _PAGE_WRITE) printk("write ");
-	if (val & _PAGE_ACCESSED) printk("accessed ");
-	if (val & _PAGE_MODIFIED) printk("modified ");
-	if (val & _PAGE_R4KBUG) printk("r4kbug ");
-	if (val & _PAGE_GLOBAL) printk("global ");
-	if (val & _PAGE_VALID) printk("valid ");
-	printk("\n");
-}
-
-void dump_list_current(void *address)
-{
-	dump_list_process(current, address);
-}
-
-unsigned long vtop(void *address)
-{
-	pgd_t	*pgd;
-	pud_t	*pud;
-	pmd_t	*pmd;
-	pte_t	*pte;
-	unsigned long addr, paddr;
-
-	addr = (unsigned long) address;
-	pgd = pgd_offset(current->mm, addr);
-	pud = pud_offset(pgd, addr);
-	pmd = pmd_offset(pud, addr);
-	pte = pte_offset(pmd, addr);
-	paddr = (CKSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
-	paddr |= (addr & ~PAGE_MASK);
-
-	return paddr;
-}
-
-void dump16(unsigned long *p)
-{
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
-		p++;
-		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
-		p++;
-	}
-}
diff --git a/arch/mips/lib-64/watch.S b/arch/mips/lib-64/watch.S
deleted file mode 100644
index f914340..0000000
--- a/arch/mips/lib-64/watch.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Kernel debug stuff to use the Watch registers.
- * Useful to find stack overflows, dangling pointers etc.
- *
- * Copyright (C) 1995, 1996, 1999, 2001 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-
-		.set	noreorder
-/*
- * Parameter: a0 - physical address to watch
- *            a1 - set bit #1 to trap on load references
- *                     bit #0 to trap on store references
- * Results  : none
- */
-		LEAF(__watch_set)
-		ori	a0, 7
-		xori	a0, 7
-		or	a0, a1
-		mtc0	a0, CP0_WATCHLO
-		sd	a0, watch_savelo
-		dsrl32	a0, a0, 0
-
-		jr	ra
-		 mtc0	zero, CP0_WATCHHI
-		END(__watch_set)
-
-/*
- * Parameter: none
- * Results  : none
- */
-		LEAF(__watch_clear)
-		jr	ra
-		 mtc0	zero, CP0_WATCHLO
-		END(__watch_clear)
-
-/*
- * Parameter: none
- * Results  : none
- */
-		LEAF(__watch_reenable)
-		ld	t0, watch_savelo
-		jr	ra
-		 mtc0	t0, CP0_WATCHLO
-		END(__watch_reenable)
-
-/*
- * Saved value of the c0_watchlo register for watch_reenable()
- */
-		.local	watch_savelo
-		.comm	watch_savelo, 8, 8
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 5dad13e..91ed1eb 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -8,5 +8,24 @@
 obj-y			+= iomap.o
 obj-$(CONFIG_PCI)	+= iomap-pci.o
 
+obj-$(CONFIG_CPU_LOONGSON2)	+= dump_tlb.o
+obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
+obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
+obj-$(CONFIG_CPU_NEVADA)	+= dump_tlb.o
+obj-$(CONFIG_CPU_R10000)	+= dump_tlb.o
+obj-$(CONFIG_CPU_R3000)		+= r3k_dump_tlb.o
+obj-$(CONFIG_CPU_R4300)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R4X00)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R5000)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R5432)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R6000)		+=
+obj-$(CONFIG_CPU_R8000)		+=
+obj-$(CONFIG_CPU_RM7000)	+= dump_tlb.o
+obj-$(CONFIG_CPU_RM9000)	+= dump_tlb.o
+obj-$(CONFIG_CPU_SB1)		+= dump_tlb.o
+obj-$(CONFIG_CPU_TX39XX)	+= r3k_dump_tlb.o
+obj-$(CONFIG_CPU_TX49XX)	+= dump_tlb.o
+obj-$(CONFIG_CPU_VR41XX)	+= dump_tlb.o
+
 # libgcc-style stuff needed in the kernel
-lib-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
+obj-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
new file mode 100644
index 0000000..465ff0e
--- /dev/null
+++ b/arch/mips/lib/dump_tlb.c
@@ -0,0 +1,101 @@
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbdebug.h>
+
+static inline const char *msk2str(unsigned int mask)
+{
+	switch (mask) {
+	case PM_4K:	return "4kb";
+	case PM_16K:	return "16kb";
+	case PM_64K:	return "64kb";
+	case PM_256K:	return "256kb";
+#ifndef CONFIG_CPU_VR41XX
+	case PM_1M:	return "1Mb";
+	case PM_4M:	return "4Mb";
+	case PM_16M:	return "16Mb";
+	case PM_64M:	return "64Mb";
+	case PM_256M:	return "256Mb";
+#endif
+	}
+	return "";
+}
+
+#define BARRIER()					\
+	__asm__ __volatile__(				\
+		".set\tnoreorder\n\t"			\
+		"nop;nop;nop;nop;nop;nop;nop\n\t"	\
+		".set\treorder");
+
+static void dump_tlb(int first, int last)
+{
+	unsigned long s_entryhi, entryhi, asid;
+	unsigned long long entrylo0, entrylo1;
+	unsigned int s_index, pagemask, c0, c1, i;
+
+	s_entryhi = read_c0_entryhi();
+	s_index = read_c0_index();
+	asid = s_entryhi & 0xff;
+
+	for (i = first; i <= last; i++) {
+		write_c0_index(i);
+		BARRIER();
+		tlb_read();
+		BARRIER();
+		pagemask = read_c0_pagemask();
+		entryhi  = read_c0_entryhi();
+		entrylo0 = read_c0_entrylo0();
+		entrylo1 = read_c0_entrylo1();
+
+		/* Unused entries have a virtual address of CKSEG0.  */
+		if ((entryhi & ~0x1ffffUL) != CKSEG0
+		    && (entryhi & 0xff) == asid) {
+#ifdef CONFIG_32BIT
+			int width = 8;
+#else
+			int width = 11;
+#endif
+			/*
+			 * Only print entries in use
+			 */
+			printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
+
+			c0 = (entrylo0 >> 3) & 7;
+			c1 = (entrylo1 >> 3) & 7;
+
+			printk("va=%0*lx asid=%02lx\n",
+			       width, (entryhi & ~0x1fffUL),
+			       entryhi & 0xff);
+			printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
+			       width,
+			       (entrylo0 << 6) & PAGE_MASK, c0,
+			       (entrylo0 & 4) ? 1 : 0,
+			       (entrylo0 & 2) ? 1 : 0,
+			       (entrylo0 & 1) ? 1 : 0);
+			printk("[pa=%0*llx c=%d d=%d v=%d g=%d]\n",
+			       width,
+			       (entrylo1 << 6) & PAGE_MASK, c1,
+			       (entrylo1 & 4) ? 1 : 0,
+			       (entrylo1 & 2) ? 1 : 0,
+			       (entrylo1 & 1) ? 1 : 0);
+		}
+	}
+	printk("\n");
+
+	write_c0_entryhi(s_entryhi);
+	write_c0_index(s_index);
+}
+
+void dump_tlb_all(void)
+{
+	dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c
new file mode 100644
index 0000000..9cee907
--- /dev/null
+++ b/arch/mips/lib/r3k_dump_tlb.c
@@ -0,0 +1,63 @@
+/*
+ * Dump R3000 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 1999 by Harald Koerfgen
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbdebug.h>
+
+extern int r3k_have_wired_reg;	/* defined in tlb-r3k.c */
+
+static void dump_tlb(int first, int last)
+{
+	int	i;
+	unsigned int asid;
+	unsigned long entryhi, entrylo0;
+
+	asid = read_c0_entryhi() & 0xfc0;
+
+	for (i = first; i <= last; i++) {
+		write_c0_index(i<<8);
+		__asm__ __volatile__(
+			".set\tnoreorder\n\t"
+			"tlbr\n\t"
+			"nop\n\t"
+			".set\treorder");
+		entryhi  = read_c0_entryhi();
+		entrylo0 = read_c0_entrylo0();
+
+		/* Unused entries have a virtual address of KSEG0.  */
+		if ((entryhi & 0xffffe000) != 0x80000000
+		    && (entryhi & 0xfc0) == asid) {
+			/*
+			 * Only print entries in use
+			 */
+			printk("Index: %2d ", i);
+
+			printk("va=%08lx asid=%08lx"
+			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
+			       (entryhi & 0xffffe000),
+			       entryhi & 0xfc0,
+			       entrylo0 & PAGE_MASK,
+			       (entrylo0 & (1 << 11)) ? 1 : 0,
+			       (entrylo0 & (1 << 10)) ? 1 : 0,
+			       (entrylo0 & (1 << 9)) ? 1 : 0,
+			       (entrylo0 & (1 << 8)) ? 1 : 0);
+		}
+	}
+	printk("\n");
+
+	write_c0_entryhi(asid);
+}
+
+void dump_tlb_all(void)
+{
+	dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c
index e9ff258..e2ff607 100644
--- a/arch/mips/lib/ucmpdi2.c
+++ b/arch/mips/lib/ucmpdi2.c
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-word_type __ucmpdi2 (unsigned long a, unsigned long b)
+word_type __ucmpdi2 (unsigned long long a, unsigned long long b)
 {
 	const DWunion au = {.ll = a};
 	const DWunion bu = {.ll = b};
diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c
index 2388f7f..58d14f4 100644
--- a/arch/mips/lib/uncached.c
+++ b/arch/mips/lib/uncached.c
@@ -12,6 +12,7 @@
 
 #include <asm/addrspace.h>
 #include <asm/bug.h>
+#include <asm/cacheflush.h>
 
 #ifndef CKSEG2
 #define CKSEG2 CKSSEG
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 80531b3..17419e11 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -35,6 +35,7 @@
  * better performance by compiling with -msoft-float!
  */
 #include <linux/sched.h>
+#include <linux/debugfs.h>
 
 #include <asm/inst.h>
 #include <asm/bootinfo.h>
@@ -204,7 +205,7 @@
 static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 {
 	mips_instruction ir;
-	void * emulpc, *contpc;
+	unsigned long emulpc, contpc;
 	unsigned int cond;
 
 	if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
@@ -229,7 +230,7 @@
 		 * Linux MIPS branch emulator operates on context, updating the
 		 * cp0_epc.
 		 */
-		emulpc = (void *) (xcp->cp0_epc + 4);	/* Snapshot emulation target */
+		emulpc = xcp->cp0_epc + 4;	/* Snapshot emulation target */
 
 		if (__compute_return_epc(xcp)) {
 #ifdef CP1DBG
@@ -243,12 +244,12 @@
 			return SIGBUS;
 		}
 		/* __compute_return_epc() will have updated cp0_epc */
-		contpc = (void *)  xcp->cp0_epc;
+		contpc = xcp->cp0_epc;
 		/* In order not to confuse ptrace() et al, tweak context */
-		xcp->cp0_epc = (unsigned long) emulpc - 4;
+		xcp->cp0_epc = emulpc - 4;
 	} else {
-		emulpc = (void *)  xcp->cp0_epc;
-		contpc = (void *) (xcp->cp0_epc + 4);
+		emulpc = xcp->cp0_epc;
+		contpc = xcp->cp0_epc + 4;
 	}
 
       emul:
@@ -426,8 +427,7 @@
 				 * instruction
 				 */
 				xcp->cp0_epc += 4;
-				contpc = (void *)
-					(xcp->cp0_epc +
+				contpc = (xcp->cp0_epc +
 					(MIPSInst_SIMM(ir) << 2));
 
 				if (get_user(ir,
@@ -461,7 +461,7 @@
 				 * Single step the non-cp1
 				 * instruction in the dslot
 				 */
-				return mips_dsemul(xcp, ir, (unsigned long) contpc);
+				return mips_dsemul(xcp, ir, contpc);
 			}
 			else {
 				/* branch not taken */
@@ -520,7 +520,7 @@
 	}
 
 	/* we did it !! */
-	xcp->cp0_epc = (unsigned long) contpc;
+	xcp->cp0_epc = contpc;
 	xcp->cp0_cause &= ~CAUSEF_BD;
 
 	return 0;
@@ -1277,3 +1277,36 @@
 
 	return sig;
 }
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_fpuemu(void)
+{
+	struct dentry *d, *dir;
+	int i;
+	static struct {
+		const char *name;
+		unsigned int *v;
+	} vars[] __initdata = {
+		{ "emulated", &fpuemustats.emulated },
+		{ "loads",    &fpuemustats.loads },
+		{ "stores",   &fpuemustats.stores },
+		{ "cp1ops",   &fpuemustats.cp1ops },
+		{ "cp1xops",  &fpuemustats.cp1xops },
+		{ "errors",   &fpuemustats.errors },
+	};
+
+	if (!mips_debugfs_dir)
+		return -ENODEV;
+	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
+	if (IS_ERR(dir))
+		return PTR_ERR(dir);
+	for (i = 0; i < ARRAY_SIZE(vars); i++) {
+		d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
+		if (IS_ERR(d))
+			return PTR_ERR(d);
+	}
+	return 0;
+}
+__initcall(debugfs_fpuemu);
+#endif
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index ea6ba72..653e325 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -54,8 +54,7 @@
 int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 {
 	extern asmlinkage void handle_dsemulret(void);
-	mips_instruction *dsemul_insns;
-	struct emuframe *fr;
+	struct emuframe __user *fr;
 	int err;
 
 	if (ir == 0) {		/* a nop is easy */
@@ -87,8 +86,8 @@
 	 */
 
 	/* Ensure that the two instructions are in the same cache line */
-	dsemul_insns = (mips_instruction *) ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
-	fr = (struct emuframe *) dsemul_insns;
+	fr = (struct emuframe __user *)
+		((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
 
 	/* Verify that the stack pointer is not competely insane */
 	if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))
@@ -113,12 +112,13 @@
 
 int do_dsemulret(struct pt_regs *xcp)
 {
-	struct emuframe *fr;
+	struct emuframe __user *fr;
 	unsigned long epc;
 	u32 insn, cookie;
 	int err = 0;
 
-	fr = (struct emuframe *) (xcp->cp0_epc - sizeof(mips_instruction));
+	fr = (struct emuframe __user *)
+		(xcp->cp0_epc - sizeof(mips_instruction));
 
 	/*
 	 * If we can't even access the area, something is very wrong, but we'll
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index dfa0acb..6c8f025 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -189,7 +189,7 @@
 	if (irq == MIPSCPU_INT_ATLAS)
 		atlas_hw0_irqdispatch();
 	else if (irq >= 0)
-		do_IRQ(MIPSCPU_INT_BASE + irq);
+		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
 	else
 		spurious_interrupt();
 }
@@ -248,25 +248,24 @@
 	case MIPS_REVISION_CORID_CORE_24K:
 	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 		if (cpu_has_veic)
-			init_msc_irqs (MSC01E_INT_BASE,
+			init_msc_irqs (MSC01E_INT_BASE, MSC01E_INT_BASE,
 				       msc_eicirqmap, msc_nr_eicirqs);
 		else
-			init_msc_irqs (MSC01C_INT_BASE,
+			init_msc_irqs (MSC01E_INT_BASE, MSC01C_INT_BASE,
 				       msc_irqmap, msc_nr_irqs);
 	}
 
-
 	if (cpu_has_veic) {
 		set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch);
 		setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq);
 	} else if (cpu_has_vint) {
 		set_vi_handler (MIPSCPU_INT_ATLAS, atlas_hw0_irqdispatch);
 #ifdef CONFIG_MIPS_MT_SMTC
-		setup_irq_smtc (MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS,
+		setup_irq_smtc (MIPS_CPU_IRQ_BASE + MIPSCPU_INT_ATLAS,
 				&atlasirq, (0x100 << MIPSCPU_INT_ATLAS));
 #else /* Not SMTC */
-		setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+		setup_irq(MIPS_CPU_IRQ_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
 #endif /* CONFIG_MIPS_MT_SMTC */
 	} else
-		setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+		setup_irq(MIPS_CPU_IRQ_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
 }
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index 0c6b0ce..1cc6ebb 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -48,6 +48,8 @@
 	return "MIPS Atlas";
 }
 
+const char display_string[] = "        LINUX ON ATLAS       ";
+
 void __init plat_mem_setup(void)
 {
 	mips_pcibios_init();
diff --git a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c
index 548dbe5..5d60005 100644
--- a/arch/mips/mips-boards/generic/display.c
+++ b/arch/mips/mips-boards/generic/display.c
@@ -19,9 +19,14 @@
  */
 
 #include <linux/compiler.h>
+#include <linux/timer.h>
 #include <asm/io.h>
 #include <asm/mips-boards/generic.h>
 
+extern const char display_string[];
+static unsigned int display_count;
+static unsigned int max_display_count;
+
 void mips_display_message(const char *str)
 {
 	static unsigned int __iomem *display = NULL;
@@ -37,3 +42,22 @@
 		         writel(' ', display + i);
 	}
 }
+
+static void scroll_display_message(unsigned long data);
+static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0);
+
+static void scroll_display_message(unsigned long data)
+{
+	mips_display_message(&display_string[display_count++]);
+	if (display_count == max_display_count)
+		display_count = 0;
+
+	mod_timer(&mips_scroll_timer, jiffies + HZ);
+}
+
+void mips_scroll_message(void)
+{
+	del_timer_sync(&mips_scroll_timer);
+	max_display_count = strlen(display_string) + 1 - 8;
+	mod_timer(&mips_scroll_timer, jiffies + 1);
+}
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index 88e9c2a..4eabc1e 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -57,7 +57,8 @@
 
 int init_debug = 0;
 
-unsigned int mips_revision_corid;
+int mips_revision_corid;
+int mips_revision_sconid;
 
 /* Bonito64 system controller register base. */
 unsigned long _pcictrl_bonito;
@@ -275,13 +276,38 @@
 		else
 			mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
 	}
-	switch(mips_revision_corid) {
+
+	mips_revision_sconid = MIPS_REVISION_SCONID;
+	if (mips_revision_sconid == MIPS_REVISION_SCON_OTHER) {
+		switch (mips_revision_corid) {
+		case MIPS_REVISION_CORID_QED_RM5261:
+		case MIPS_REVISION_CORID_CORE_LV:
+		case MIPS_REVISION_CORID_CORE_FPGA:
+		case MIPS_REVISION_CORID_CORE_FPGAR2:
+			mips_revision_sconid = MIPS_REVISION_SCON_GT64120;
+			break;
+		case MIPS_REVISION_CORID_CORE_EMUL_BON:
+		case MIPS_REVISION_CORID_BONITO64:
+		case MIPS_REVISION_CORID_CORE_20K:
+			mips_revision_sconid = MIPS_REVISION_SCON_BONITO;
+			break;
+		case MIPS_REVISION_CORID_CORE_MSC:
+		case MIPS_REVISION_CORID_CORE_FPGA2:
+		case MIPS_REVISION_CORID_CORE_FPGA3:
+		case MIPS_REVISION_CORID_CORE_24K:
+		case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+			mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;
+			break;
+		default:
+			mips_display_message("CC Error");
+			while (1);   /* We die here... */
+		}
+	}
+
+	switch (mips_revision_sconid) {
 		u32 start, map, mask, data;
 
-	case MIPS_REVISION_CORID_QED_RM5261:
-	case MIPS_REVISION_CORID_CORE_LV:
-	case MIPS_REVISION_CORID_CORE_FPGA:
-	case MIPS_REVISION_CORID_CORE_FPGAR2:
+	case MIPS_REVISION_SCON_GT64120:
 		/*
 		 * Setup the North bridge to do Master byte-lane swapping
 		 * when running in bigendian.
@@ -305,9 +331,7 @@
 		set_io_port_base(MALTA_GT_PORT_BASE);
 		break;
 
-	case MIPS_REVISION_CORID_CORE_EMUL_BON:
-	case MIPS_REVISION_CORID_BONITO64:
-	case MIPS_REVISION_CORID_CORE_20K:
+	case MIPS_REVISION_SCON_BONITO:
 		_pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
 
 		/*
@@ -334,13 +358,10 @@
 		set_io_port_base(MALTA_BONITO_PORT_BASE);
 		break;
 
-	case MIPS_REVISION_CORID_CORE_MSC:
-	case MIPS_REVISION_CORID_CORE_FPGA2:
-	case MIPS_REVISION_CORID_CORE_FPGA3:
-	case MIPS_REVISION_CORID_CORE_24K:
-	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+	case MIPS_REVISION_SCON_SOCIT:
+	case MIPS_REVISION_SCON_ROCIT:
 		_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
-
+	mips_pci_controller:
 		mb();
 		MSC_READ(MSC01_PCI_CFG, data);
 		MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT);
@@ -374,10 +395,15 @@
 		set_io_port_base(MALTA_MSC_PORT_BASE);
 		break;
 
+	case MIPS_REVISION_SCON_SOCITSC:
+	case MIPS_REVISION_SCON_SOCITSCP:
+		_pcictrl_msc = (unsigned long)ioremap(MIPS_SOCITSC_PCI_REG_BASE, 0x2000);
+		goto mips_pci_controller;
+
 	default:
-		/* Unknown Core card */
-		mips_display_message("CC Error");
-		while(1);   /* We die here... */
+		/* Unknown system controller */
+		mips_display_message("SC Error");
+		while (1);   /* We die here... */
 	}
 #endif
 	board_nmi_handler_setup = mips_nmi_setup;
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
index f98d60f..c985220 100644
--- a/arch/mips/mips-boards/generic/pci.c
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -92,11 +92,8 @@
 	struct pci_controller *controller;
 	resource_size_t start, end, map, start1, end1, map1, map2, map3, mask;
 
-	switch (mips_revision_corid) {
-	case MIPS_REVISION_CORID_QED_RM5261:
-	case MIPS_REVISION_CORID_CORE_LV:
-	case MIPS_REVISION_CORID_CORE_FPGA:
-	case MIPS_REVISION_CORID_CORE_FPGAR2:
+	switch (mips_revision_sconid) {
+	case MIPS_REVISION_SCON_GT64120:
 		/*
 		 * Due to a bug in the Galileo system controller, we need
 		 * to setup the PCI BAR for the Galileo internal registers.
@@ -161,9 +158,7 @@
 		controller = &gt64120_controller;
 		break;
 
-	case MIPS_REVISION_CORID_BONITO64:
-	case MIPS_REVISION_CORID_CORE_20K:
-	case MIPS_REVISION_CORID_CORE_EMUL_BON:
+	case MIPS_REVISION_SCON_BONITO:
 		/* Set up resource ranges from the controller's registers.  */
 		map = BONITO_PCIMAP;
 		map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
@@ -195,11 +190,10 @@
 		controller = &bonito64_controller;
 		break;
 
-	case MIPS_REVISION_CORID_CORE_MSC:
-	case MIPS_REVISION_CORID_CORE_FPGA2:
-	case MIPS_REVISION_CORID_CORE_FPGA3:
-	case MIPS_REVISION_CORID_CORE_24K:
-	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+	case MIPS_REVISION_SCON_SOCIT:
+	case MIPS_REVISION_SCON_ROCIT:
+	case MIPS_REVISION_SCON_SOCITSC:
+	case MIPS_REVISION_SCON_SOCITSCP:
 		/* Set up resource ranges from the controller's registers.  */
 		MSC_READ(MSC01_PCI_SC2PMBASL, start);
 		MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index df2a2bd..c45d556 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -53,42 +53,20 @@
 
 unsigned long cpu_khz;
 
-#if defined(CONFIG_MIPS_ATLAS)
-static char display_string[] = "        LINUX ON ATLAS       ";
-#endif
-#if defined(CONFIG_MIPS_MALTA)
-#if defined(CONFIG_MIPS_MT_SMTC)
-static char display_string[] = "       SMTC LINUX ON MALTA       ";
-#else
-static char display_string[] = "        LINUX ON MALTA       ";
-#endif /* CONFIG_MIPS_MT_SMTC */
-#endif
-#if defined(CONFIG_MIPS_SEAD)
-static char display_string[] = "        LINUX ON SEAD       ";
-#endif
-static unsigned int display_count;
-#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
-
-#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
-
-static unsigned int timer_tick_count;
 static int mips_cpu_timer_irq;
+extern int cp0_perfcount_irq;
 extern void smtc_timer_broadcast(int);
 
-static inline void scroll_display_message(void)
-{
-	if ((timer_tick_count++ % HZ) == 0) {
-		mips_display_message(&display_string[display_count++]);
-		if (display_count == MAX_DISPLAY_COUNT)
-			display_count = 0;
-	}
-}
-
 static void mips_timer_dispatch(void)
 {
 	do_IRQ(mips_cpu_timer_irq);
 }
 
+static void mips_perf_dispatch(void)
+{
+	do_IRQ(cp0_perfcount_irq);
+}
+
 /*
  * Redeclare until I get around mopping the timer code insanity on MIPS.
  */
@@ -96,6 +74,24 @@
 
 extern int (*perf_irq)(void);
 
+/*
+ * Possibly handle a performance counter interrupt.
+ * Return true if the timer interrupt should not be checked
+ */
+static inline int handle_perf_irq (int r2)
+{
+	/*
+	 * The performance counter overflow interrupt may be shared with the
+	 * timer interrupt (cp0_perfcount_irq < 0). If it is and a
+	 * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
+	 * and we can't reliably determine if a counter interrupt has also
+	 * happened (!r2) then don't check for a timer interrupt.
+	 */
+	return (cp0_perfcount_irq < 0) &&
+		perf_irq() == IRQ_HANDLED &&
+		!r2;
+}
+
 irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
 {
 	int cpu = smp_processor_id();
@@ -114,25 +110,13 @@
 	 *  the general MIPS timer_interrupt routine.
 	 */
 
-	int vpflags;
-
 	/*
 	 * We could be here due to timer interrupt,
 	 * perf counter overflow, or both.
 	 */
-	if (read_c0_cause() & (1 << 26))
-		perf_irq();
+	(void) handle_perf_irq(1);
 
 	if (read_c0_cause() & (1 << 30)) {
-		/* If timer interrupt, make it de-assert */
-		write_c0_compare (read_c0_count() - 1);
-		/*
-		 * DVPE is necessary so long as cross-VPE interrupts
-		 * are done via read-modify-write of Cause register.
-		 */
-		vpflags = dvpe();
-		clear_c0_cause(CPUCTR_IMASKBIT);
-		evpe(vpflags);
 		/*
 		 * There are things we only want to do once per tick
 		 * in an "MP" system.   One TC of each VPE will take
@@ -141,34 +125,30 @@
 		 * the tick on VPE 0 to run the full timer_interrupt().
 		 */
 		if (cpu_data[cpu].vpe_id == 0) {
-				timer_interrupt(irq, NULL);
-				smtc_timer_broadcast(cpu_data[cpu].vpe_id);
-				scroll_display_message();
+			timer_interrupt(irq, NULL);
 		} else {
 			write_c0_compare(read_c0_count() +
 			                 (mips_hpt_frequency/HZ));
 			local_timer_interrupt(irq, dev_id);
-			smtc_timer_broadcast(cpu_data[cpu].vpe_id);
 		}
+		smtc_timer_broadcast(cpu_data[cpu].vpe_id);
 	}
 #else /* CONFIG_MIPS_MT_SMTC */
 	int r2 = cpu_has_mips_r2;
 
+	if (handle_perf_irq(r2))
+		goto out;
+
+	if (r2 && ((read_c0_cause() & (1 << 30)) == 0))
+		goto out;
+
 	if (cpu == 0) {
 		/*
 		 * CPU 0 handles the global timer interrupt job and process
 		 * accounting resets count/compare registers to trigger next
 		 * timer int.
 		 */
-		if (!r2 || (read_c0_cause() & (1 << 26)))
-			if (perf_irq())
-				goto out;
-
-		/* we keep interrupt disabled all the time */
-		if (!r2 || (read_c0_cause() & (1 << 30)))
-			timer_interrupt(irq, NULL);
-
-		scroll_display_message();
+		timer_interrupt(irq, NULL);
 	} else {
 		/* Everyone else needs to reset the timer int here as
 		   ll_local_timer_interrupt doesn't */
@@ -262,6 +242,44 @@
 	       (est_freq%1000000)*100/1000000);
 
         cpu_khz = est_freq / 1000;
+
+	mips_scroll_message();
+}
+
+irqreturn_t mips_perf_interrupt(int irq, void *dev_id)
+{
+	return perf_irq();
+}
+
+static struct irqaction perf_irqaction = {
+	.handler = mips_perf_interrupt,
+	.flags = IRQF_DISABLED | IRQF_PERCPU,
+	.name = "performance",
+};
+
+void __init plat_perf_setup(struct irqaction *irq)
+{
+	cp0_perfcount_irq = -1;
+
+#ifdef MSC01E_INT_BASE
+	if (cpu_has_veic) {
+		set_vi_handler (MSC01E_INT_PERFCTR, mips_perf_dispatch);
+		cp0_perfcount_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
+	} else
+#endif
+	if (cp0_perfcount_irq >= 0) {
+		if (cpu_has_vint)
+			set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
+#ifdef CONFIG_MIPS_MT_SMTC
+		setup_irq_smtc(cp0_perfcount_irq, irq,
+		               0x100 << cp0_perfcount_irq);
+#else
+		setup_irq(cp0_perfcount_irq, irq);
+#endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_SMP
+		set_irq_handler(cp0_perfcount_irq, handle_percpu_irq);
+#endif
+	}
 }
 
 void __init plat_timer_setup(struct irqaction *irq)
@@ -270,29 +288,25 @@
 	if (cpu_has_veic) {
 		set_vi_handler (MSC01E_INT_CPUCTR, mips_timer_dispatch);
 		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
-	} else
+	}
+	else
 #endif
 	{
 		if (cpu_has_vint)
-			set_vi_handler (MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
-		mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
+			set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
+		mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
 	}
 
-
 	/* we are using the cpu counter for timer interrupts */
 	irq->handler = mips_timer_interrupt;	/* we use our own handler */
 #ifdef CONFIG_MIPS_MT_SMTC
-	setup_irq_smtc(mips_cpu_timer_irq, irq, CPUCTR_IMASKBIT);
+	setup_irq_smtc(mips_cpu_timer_irq, irq, 0x100 << cp0_compare_irq);
 #else
 	setup_irq(mips_cpu_timer_irq, irq);
 #endif /* CONFIG_MIPS_MT_SMTC */
-
 #ifdef CONFIG_SMP
-	/* irq_desc(riptor) is a global resource, when the interrupt overlaps
-	   on seperate cpu's the first one tries to handle the second interrupt.
-	   The effect is that the int remains disabled on the second cpu.
-	   Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
-	irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
 	set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
 #endif
+
+	plat_perf_setup(&perf_irqaction);
 }
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index 377d9e8..a242b0f 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -19,6 +19,7 @@
 # under Linux.
 #
 
-obj-y := malta_int.o malta_setup.o
+obj-y := malta_int.o malta_platform.o malta_setup.o
+
 obj-$(CONFIG_MTD) += malta_mtd.o
 obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index 1cd830e..c78d4834 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -53,25 +53,19 @@
 	 * Determine highest priority pending interrupt by performing
 	 * a PCI Interrupt Acknowledge cycle.
 	 */
-	switch(mips_revision_corid) {
-	case MIPS_REVISION_CORID_CORE_MSC:
-	case MIPS_REVISION_CORID_CORE_FPGA2:
-	case MIPS_REVISION_CORID_CORE_FPGA3:
-	case MIPS_REVISION_CORID_CORE_24K:
-	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+	switch (mips_revision_sconid) {
+	case MIPS_REVISION_SCON_SOCIT:
+	case MIPS_REVISION_SCON_ROCIT:
+	case MIPS_REVISION_SCON_SOCITSC:
+	case MIPS_REVISION_SCON_SOCITSCP:
 	        MSC_READ(MSC01_PCI_IACK, irq);
 		irq &= 0xff;
 		break;
-	case MIPS_REVISION_CORID_QED_RM5261:
-	case MIPS_REVISION_CORID_CORE_LV:
-	case MIPS_REVISION_CORID_CORE_FPGA:
-	case MIPS_REVISION_CORID_CORE_FPGAR2:
+	case MIPS_REVISION_SCON_GT64120:
 		irq = GT_READ(GT_PCI0_IACK_OFS);
 		irq &= 0xff;
 		break;
-	case MIPS_REVISION_CORID_BONITO64:
-	case MIPS_REVISION_CORID_CORE_20K:
-	case MIPS_REVISION_CORID_CORE_EMUL_BON:
+	case MIPS_REVISION_SCON_BONITO:
 		/* The following will generate a PCI IACK cycle on the
 		 * Bonito controller. It's a little bit kludgy, but it
 		 * was the easiest way to implement it in hardware at
@@ -89,7 +83,7 @@
 		BONITO_PCIMAP_CFG = 0;
 		break;
 	default:
-	        printk("Unknown Core card, don't know the system controller.\n");
+	        printk("Unknown system controller.\n");
 		return -1;
 	}
 	return irq;
@@ -144,27 +138,21 @@
 	   Do it for the others too.
 	*/
 
-        switch(mips_revision_corid) {
-        case MIPS_REVISION_CORID_CORE_MSC:
-        case MIPS_REVISION_CORID_CORE_FPGA2:
-        case MIPS_REVISION_CORID_CORE_FPGA3:
-        case MIPS_REVISION_CORID_CORE_24K:
-        case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+	switch (mips_revision_sconid) {
+        case MIPS_REVISION_SCON_SOCIT:
+	case MIPS_REVISION_SCON_ROCIT:
+	case MIPS_REVISION_SCON_SOCITSC:
+	case MIPS_REVISION_SCON_SOCITSCP:
                 ll_msc_irq();
                 break;
-        case MIPS_REVISION_CORID_QED_RM5261:
-        case MIPS_REVISION_CORID_CORE_LV:
-        case MIPS_REVISION_CORID_CORE_FPGA:
-        case MIPS_REVISION_CORID_CORE_FPGAR2:
+        case MIPS_REVISION_SCON_GT64120:
                 intrcause = GT_READ(GT_INTRCAUSE_OFS);
                 datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
                 datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
                 printk("GT_INTRCAUSE = %08x\n", intrcause);
                 printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo);
                 break;
-        case MIPS_REVISION_CORID_BONITO64:
-        case MIPS_REVISION_CORID_CORE_20K:
-        case MIPS_REVISION_CORID_CORE_EMUL_BON:
+        case MIPS_REVISION_SCON_BONITO:
                 pcibadaddr = BONITO_PCIBADADDR;
                 pcimstat = BONITO_PCIMSTAT;
                 intisr = BONITO_INTISR;
@@ -269,7 +257,7 @@
 	if (irq == MIPSCPU_INT_I8259A)
 		malta_hw0_irqdispatch();
 	else if (irq > 0)
-		do_IRQ(MIPSCPU_INT_BASE + irq);
+		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
 	else
 		spurious_interrupt();
 }
@@ -338,17 +326,17 @@
 		set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
 		set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch);
 #ifdef CONFIG_MIPS_MT_SMTC
-		setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq,
+		setup_irq_smtc (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq,
 			(0x100 << MIPSCPU_INT_I8259A));
-		setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI,
+		setup_irq_smtc (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
 			&corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
 #else /* Not SMTC */
-		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
-		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+		setup_irq (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
+		setup_irq (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
 #endif /* CONFIG_MIPS_MT_SMTC */
 	}
 	else {
-		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
-		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+		setup_irq (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
+		setup_irq (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
 	}
 }
diff --git a/arch/mips/mips-boards/malta/malta_platform.c b/arch/mips/mips-boards/malta/malta_platform.c
new file mode 100644
index 0000000..83b9bab
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_platform.c
@@ -0,0 +1,65 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ *   written by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Probe driver for the Malta's UART ports:
+ *
+ *   o 2 ports in the SMC SuperIO
+ *   o 1 port in the CBUS UART, a discrete 16550 which normally is only used
+ *     for bringups.
+ *
+ * We don't use 8250_platform.c on Malta as it would result in the CBUS
+ * UART becoming ttyS0.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define SMC_PORT(base, int)						\
+{									\
+	.iobase		= base,						\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_PORT,					\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,		\
+	.regshift	= 0,						\
+}
+
+#define CBUS_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+	SMC_PORT(0x3F8, 4),
+	SMC_PORT(0x2F8, 3),
+	{
+		.mapbase	= 0x1f000900,	/* The CBUS UART */
+		.irq		= MIPS_CPU_IRQ_BASE + 2,
+		.uartclk	= 3686400,	/* Twice the usual clk! */
+		.iotype		= UPIO_MEM32,
+		.flags		= CBUS_UART_FLAGS,
+		.regshift	= 3,
+	},
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM2,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Malta CBUS UART");
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 7873932..8f1b78d 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -56,6 +56,12 @@
 	return "MIPS Malta";
 }
 
+#if defined(CONFIG_MIPS_MT_SMTC)
+const char display_string[] = "       SMTC LINUX ON MALTA       ";
+#else
+const char display_string[] = "        LINUX ON MALTA       ";
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 #ifdef CONFIG_BLK_DEV_FD
 void __init fd_activate(void)
 {
@@ -97,9 +103,7 @@
 	kgdb_config ();
 #endif
 
-	if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) ||
-	    (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) ||
-	    (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) {
+	if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
 		char *argptr;
 
 		argptr = prom_getcmdline();
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index c4b9de3..9ca0f82 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -106,7 +106,7 @@
 	irq = irq_ffs(pending);
 
 	if (irq >= 0)
-		do_IRQ(MIPSCPU_INT_BASE + irq);
+		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
 	else
 		spurious_interrupt();
 }
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
index a189dec..bb80140 100644
--- a/arch/mips/mips-boards/sead/sead_setup.c
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -43,6 +43,8 @@
 	return "MIPS SEAD";
 }
 
+const char display_string[] = "        LINUX ON SEAD       ";
+
 void __init plat_mem_setup(void)
 {
 	ioport_resource.end = 0x7fffffff;
@@ -66,7 +68,7 @@
 #else
 	s.iobase = SEAD_UART0_REGS_BASE+3;
 #endif
-	s.irq = MIPSCPU_INT_BASE + MIPSCPU_INT_UART0;
+	s.irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_UART0;
 	s.uartclk = SEAD_BASE_BAUD * 16;
 	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ;
 	s.iotype = UPIO_PORT;
diff --git a/arch/mips/mips-boards/sim/sim_console.c b/arch/mips/mips-boards/sim/sim_console.c
deleted file mode 100644
index de595a9..0000000
--- a/arch/mips/mips-boards/sim/sim_console.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- * Copyright (C) 2007 MIPS Technologies, Inc.
- *   written by Ralf Baechle
- */
-#include <linux/init.h>
-#include <linux/serial_reg.h>
-#include <asm/io.h>
-
-static inline unsigned int serial_in(int offset)
-{
-	return inb(0x3f8 + offset);
-}
-
-static inline void serial_out(int offset, int value)
-{
-	outb(value, 0x3f8 + offset);
-}
-
-void __init prom_putchar(char c)
-{
-	while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
-		;
-
-	serial_out(UART_TX, c);
-}
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
index 15ac065..766e015 100644
--- a/arch/mips/mips-boards/sim/sim_int.c
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -77,7 +77,7 @@
 	irq = irq_ffs(pending);
 
 	if (irq > 0)
-		do_IRQ(MIPSCPU_INT_BASE + irq);
+		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
 	else
 		spurious_interrupt();
 }
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
deleted file mode 100644
index e408ef0b..0000000
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/pfn.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/sections.h>
-
-#include <asm/mips-boards/prom.h>
-
-/*#define DEBUG*/
-
-enum simmem_memtypes {
-	simmem_reserved = 0,
-	simmem_free,
-};
-struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
-
-#ifdef DEBUG
-static char *mtypes[3] = {
-	"SIM reserved memory",
-	"SIM free memory",
-};
-#endif
-
-struct prom_pmemblock * __init prom_getmdesc(void)
-{
-	unsigned int memsize;
-
-	memsize = 0x02000000;
-	pr_info("Setting default memory size 0x%08x\n", memsize);
-
-	memset(mdesc, 0, sizeof(mdesc));
-
-	mdesc[0].type = simmem_reserved;
-	mdesc[0].base = 0x00000000;
-	mdesc[0].size = 0x00001000;
-
-	mdesc[1].type = simmem_free;
-	mdesc[1].base = 0x00001000;
-	mdesc[1].size = 0x000ff000;
-
-	mdesc[2].type = simmem_reserved;
-	mdesc[2].base = 0x00100000;
-	mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
-
-	mdesc[3].type = simmem_free;
-	mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
-	mdesc[3].size = memsize - mdesc[3].base;
-
-	return &mdesc[0];
-}
-
-static int __init prom_memtype_classify (unsigned int type)
-{
-	switch (type) {
-	case simmem_free:
-		return BOOT_MEM_RAM;
-	case simmem_reserved:
-	default:
-		return BOOT_MEM_RESERVED;
-	}
-}
-
-void __init prom_meminit(void)
-{
-	struct prom_pmemblock *p;
-
-	p = prom_getmdesc();
-
-	while (p->size) {
-		long type;
-		unsigned long base, size;
-
-		type = prom_memtype_classify (p->type);
-		base = p->base;
-		size = p->size;
-
-		add_memory_region(base, size, type);
-                p++;
-	}
-}
-
-void __init prom_free_prom_memory(void)
-{
-	int i;
-	unsigned long addr;
-
-	for (i = 0; i < boot_mem_map.nr_map; i++) {
-		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
-			continue;
-
-		addr = boot_mem_map.map[i].addr;
-		free_init_pages("prom memory",
-				addr, addr + boot_mem_map.map[i].size);
-	}
-}
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c
deleted file mode 100644
index b705f09..0000000
--- a/arch/mips/mips-boards/sim/sim_setup.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- */
-
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mips-boards/generic.h>
-#include <asm/mips-boards/prom.h>
-#include <asm/serial.h>
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/mips-boards/sim.h>
-#include <asm/mips-boards/simint.h>
-
-
-extern void sim_time_init(void);
-static void __init serial_init(void);
-unsigned int _isbonito = 0;
-
-extern void __init sanitize_tlb_entries(void);
-
-
-const char *get_system_type(void)
-{
-	return "MIPSsim";
-}
-
-void __init plat_mem_setup(void)
-{
-	set_io_port_base(0xbfd00000);
-
-	serial_init();
-
-	board_time_init = sim_time_init;
-	pr_info("Linux started...\n");
-
-#ifdef CONFIG_MIPS_MT_SMP
-	sanitize_tlb_entries();
-#endif
-}
-
-void prom_init(void)
-{
-	set_io_port_base(0xbfd00000);
-
-	pr_info("\nLINUX started...\n");
-	prom_init_cmdline();
-	prom_meminit();
-}
-
-
-static void __init serial_init(void)
-{
-#ifdef CONFIG_SERIAL_8250
-	struct uart_port s;
-
-	memset(&s, 0, sizeof(s));
-
-	s.iobase = 0x3f8;
-
-	/* hardware int 4 - the serial int, is CPU int 6
-	 but poll for now */
-	s.irq =  0;
-	s.uartclk = BASE_BAUD * 16;
-	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	s.iotype = UPIO_PORT;
-	s.regshift = 0;
-	s.timeout = 4;
-
-	if (early_serial_setup(&s) != 0) {
-		printk(KERN_ERR "Serial setup failed!\n");
-	}
-
-#endif
-}
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
deleted file mode 100644
index cb47863..0000000
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- */
-/*
- * Simulator Platform-specific hooks for SMP operation
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-#include <asm/atomic.h>
-#include <asm/cpu.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/hardirq.h>
-#include <asm/mmu_context.h>
-#include <asm/smp.h>
-#ifdef CONFIG_MIPS_MT_SMTC
-#include <asm/smtc_ipi.h>
-#endif /* CONFIG_MIPS_MT_SMTC */
-
-/* VPE/SMP Prototype implements platform interfaces directly */
-#if !defined(CONFIG_MIPS_MT_SMP)
-
-/*
- * Cause the specified action to be performed on a targeted "CPU"
- */
-
-void core_send_ipi(int cpu, unsigned int action)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-	smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
-#endif /* CONFIG_MIPS_MT_SMTC */
-/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
-
-}
-
-/*
- * Platform "CPU" startup hook
- */
-
-void prom_boot_secondary(int cpu, struct task_struct *idle)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-	smtc_boot_secondary(cpu, idle);
-#endif /* CONFIG_MIPS_MT_SMTC */
-}
-
-/*
- * Post-config but pre-boot cleanup entry point
- */
-
-void prom_init_secondary(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-	void smtc_init_secondary(void);
-
-	smtc_init_secondary();
-#endif /* CONFIG_MIPS_MT_SMTC */
-}
-
-/*
- * Platform SMP pre-initialization
- */
-
-void prom_prepare_cpus(unsigned int max_cpus)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-	/*
-	 * As noted above, we can assume a single CPU for now
-	 * but it may be multithreaded.
-	 */
-
-	if (read_c0_config3() & (1<<2)) {
-		mipsmt_prepare_cpus(max_cpus);
-	}
-#endif /* CONFIG_MIPS_MT_SMTC */
-}
-
-/*
- * SMP initialization finalization entry point
- */
-
-void prom_smp_finish(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-	smtc_smp_finish();
-#endif /* CONFIG_MIPS_MT_SMTC */
-}
-
-/*
- * Hook for after all CPUs are online
- */
-
-void prom_cpus_done(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-
-#endif /* CONFIG_MIPS_MT_SMTC */
-}
-#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c
deleted file mode 100644
index d3a21c7..0000000
--- a/arch/mips/mips-boards/sim/sim_time.c
+++ /dev/null
@@ -1,202 +0,0 @@
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/mc146818rtc.h>
-#include <linux/timex.h>
-
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
-#include <asm/hardirq.h>
-#include <asm/div64.h>
-#include <asm/cpu.h>
-#include <asm/time.h>
-#include <asm/irq.h>
-#include <asm/mc146818-time.h>
-#include <asm/msc01_ic.h>
-#include <asm/smp.h>
-
-#include <asm/mips-boards/generic.h>
-#include <asm/mips-boards/prom.h>
-#include <asm/mips-boards/simint.h>
-
-
-unsigned long cpu_khz;
-
-irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
-{
-#ifdef CONFIG_SMP
-	int cpu = smp_processor_id();
-
-	/*
-	 * CPU 0 handles the global timer interrupt job
-	 * resets count/compare registers to trigger next timer int.
-	 */
-#ifndef CONFIG_MIPS_MT_SMTC
-	if (cpu == 0) {
-		timer_interrupt(irq, dev_id);
-	}
-	else {
-		/* Everyone else needs to reset the timer int here as
-		   ll_local_timer_interrupt doesn't */
-		/*
-		 * FIXME: need to cope with counter underflow.
-		 * More support needs to be added to kernel/time for
-		 * counter/timer interrupts on multiple CPU's
-		 */
-		write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
-	}
-#else /* SMTC */
-	/*
-	 *  In SMTC system, one Count/Compare set exists per VPE.
-	 *  Which TC within a VPE gets the interrupt is essentially
-	 *  random - we only know that it shouldn't be one with
-	 *  IXMT set. Whichever TC gets the interrupt needs to
-	 *  send special interprocessor interrupts to the other
-	 *  TCs to make sure that they schedule, etc.
-	 *
-	 *  That code is specific to the SMTC kernel, not to
-	 *  the simulation platform, so it's invoked from
-	 *  the general MIPS timer_interrupt routine.
-	 *
-	 * We have a problem in that the interrupt vector code
-	 * had to turn off the timer IM bit to avoid redundant
-	 * entries, but we may never get to mips_cpu_irq_end
-	 * to turn it back on again if the scheduler gets
-	 * involved.  So we clear the pending timer here,
-	 * and re-enable the mask...
-	 */
-
-	int vpflags = dvpe();
-	write_c0_compare (read_c0_count() - 1);
-	clear_c0_cause(0x100 << MIPSCPU_INT_CPUCTR);
-	set_c0_status(0x100 << MIPSCPU_INT_CPUCTR);
-	irq_enable_hazard();
-	evpe(vpflags);
-
-	if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id);
-	else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
-	smtc_timer_broadcast(cpu_data[cpu].vpe_id);
-
-#endif /* CONFIG_MIPS_MT_SMTC */
-
-	/*
-	 * every CPU should do profiling and process accounting
-	 */
- 	local_timer_interrupt (irq, dev_id);
-	return IRQ_HANDLED;
-#else
-	return timer_interrupt (irq, dev_id);
-#endif
-}
-
-
-
-/*
- * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
- */
-static unsigned int __init estimate_cpu_frequency(void)
-{
-	unsigned int prid = read_c0_prid() & 0xffff00;
-	unsigned int count;
-
-#if 1
-	/*
-	 * hardwire the board frequency to 12MHz.
-	 */
-
-	if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
-	    (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
-		count = 12000000;
-	else
-		count =  6000000;
-#else
-	unsigned int flags;
-
-	local_irq_save(flags);
-
-	/* Start counter exactly on falling edge of update flag */
-	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
-	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
-
-	/* Start r4k counter. */
-	write_c0_count(0);
-
-	/* Read counter exactly on falling edge of update flag */
-	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
-	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
-
-	count = read_c0_count();
-
-	/* restore interrupts */
-	local_irq_restore(flags);
-#endif
-
-	mips_hpt_frequency = count;
-
-	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
-	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
-		count *= 2;
-
-	count += 5000;    /* round */
-	count -= count%10000;
-
-	return count;
-}
-
-void __init sim_time_init(void)
-{
-	unsigned int est_freq, flags;
-
-	local_irq_save(flags);
-
-
-        /* Set Data mode - binary. */
-	CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
-
-
-	est_freq = estimate_cpu_frequency ();
-
-	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
-	       (est_freq%1000000)*100/1000000);
-
-        cpu_khz = est_freq / 1000;
-
-	local_irq_restore(flags);
-}
-
-static int mips_cpu_timer_irq;
-
-static void mips_timer_dispatch(void)
-{
-	do_IRQ(mips_cpu_timer_irq);
-}
-
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	if (cpu_has_veic) {
-		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
-		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
-	}
-	else {
-		if (cpu_has_vint)
-			set_vi_handler(MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
-		mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
-	}
-
-	/* we are using the cpu counter for timer interrupts */
-	irq->handler = sim_timer_interrupt;
-	setup_irq(mips_cpu_timer_irq, irq);
-
-#ifdef CONFIG_SMP
-	/* irq_desc(riptor) is a global resource, when the interrupt overlaps
-	   on seperate cpu's the first one tries to handle the second interrupt.
-	   The effect is that the int remains disabled on the second cpu.
-	   Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
-	irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU;
-	set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
-#endif
-}
diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mipssim/Makefile
similarity index 100%
rename from arch/mips/mips-boards/sim/Makefile
rename to arch/mips/mipssim/Makefile
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c
similarity index 100%
rename from arch/mips/mips-boards/sim/sim_cmdline.c
rename to arch/mips/mipssim/sim_cmdline.c
diff --git a/arch/mips/mipssim/sim_console.c b/arch/mips/mipssim/sim_console.c
new file mode 100644
index 0000000..a2f4167
--- /dev/null
+++ b/arch/mips/mipssim/sim_console.c
@@ -0,0 +1,40 @@
+/*
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ *   written by Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/serial_reg.h>
+
+static inline unsigned int serial_in(int offset)
+{
+	return inb(0x3f8 + offset);
+}
+
+static inline void serial_out(int offset, int value)
+{
+	outb(value, 0x3f8 + offset);
+}
+
+void __init prom_putchar(char c)
+{
+	while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
+		;
+
+	serial_out(UART_TX, c);
+}
diff --git a/arch/mips/mipssim/sim_int.c b/arch/mips/mipssim/sim_int.c
new file mode 100644
index 0000000..5cbc350
--- /dev/null
+++ b/arch/mips/mipssim/sim_int.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 1999, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <asm/mips-boards/simint.h>
+#include <asm/irq_cpu.h>
+
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	/* t0 = t0 << 2; */
+	a0 = a0 - t0;
+	/* s0 = s0 << t0; */
+
+	return a0;
+#endif
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq > 0)
+		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
+	else
+		spurious_interrupt();
+}
+
+void __init arch_init_irq(void)
+{
+	mips_cpu_irq_init();
+}
diff --git a/arch/mips/mipssim/sim_mem.c b/arch/mips/mipssim/sim_mem.c
new file mode 100644
index 0000000..2312483
--- /dev/null
+++ b/arch/mips/mipssim/sim_mem.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mips-boards/prom.h>
+
+/*#define DEBUG*/
+
+enum simmem_memtypes {
+	simmem_reserved = 0,
+	simmem_free,
+};
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+#ifdef DEBUG
+static char *mtypes[3] = {
+	"SIM reserved memory",
+	"SIM free memory",
+};
+#endif
+
+struct prom_pmemblock * __init prom_getmdesc(void)
+{
+	unsigned int memsize;
+
+	memsize = 0x02000000;
+	pr_info("Setting default memory size 0x%08x\n", memsize);
+
+	memset(mdesc, 0, sizeof(mdesc));
+
+	mdesc[0].type = simmem_reserved;
+	mdesc[0].base = 0x00000000;
+	mdesc[0].size = 0x00001000;
+
+	mdesc[1].type = simmem_free;
+	mdesc[1].base = 0x00001000;
+	mdesc[1].size = 0x000ff000;
+
+	mdesc[2].type = simmem_reserved;
+	mdesc[2].base = 0x00100000;
+	mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
+
+	mdesc[3].type = simmem_free;
+	mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
+	mdesc[3].size = memsize - mdesc[3].base;
+
+	return &mdesc[0];
+}
+
+static int __init prom_memtype_classify (unsigned int type)
+{
+	switch (type) {
+	case simmem_free:
+		return BOOT_MEM_RAM;
+	case simmem_reserved:
+	default:
+		return BOOT_MEM_RESERVED;
+	}
+}
+
+void __init prom_meminit(void)
+{
+	struct prom_pmemblock *p;
+
+	p = prom_getmdesc();
+
+	while (p->size) {
+		long type;
+		unsigned long base, size;
+
+		type = prom_memtype_classify (p->type);
+		base = p->base;
+		size = p->size;
+
+		add_memory_region(base, size, type);
+		p++;
+	}
+}
+
+void __init prom_free_prom_memory(void)
+{
+	int i;
+	unsigned long addr;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+			continue;
+
+		addr = boot_mem_map.map[i].addr;
+		free_init_pages("prom memory",
+				addr, addr + boot_mem_map.map[i].size);
+	}
+}
diff --git a/arch/mips/mips-boards/sim/sim_platform.c b/arch/mips/mipssim/sim_platform.c
similarity index 100%
rename from arch/mips/mips-boards/sim/sim_platform.c
rename to arch/mips/mipssim/sim_platform.c
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
new file mode 100644
index 0000000..60e6690
--- /dev/null
+++ b/arch/mips/mipssim/sim_setup.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/ioport.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/time.h>
+#include <asm/mips-boards/sim.h>
+#include <asm/mips-boards/simint.h>
+
+
+extern void sim_time_init(void);
+static void __init serial_init(void);
+unsigned int _isbonito = 0;
+
+extern void __init sanitize_tlb_entries(void);
+
+
+const char *get_system_type(void)
+{
+	return "MIPSsim";
+}
+
+void __init plat_mem_setup(void)
+{
+	set_io_port_base(0xbfd00000);
+
+	serial_init();
+
+	board_time_init = sim_time_init;
+	pr_info("Linux started...\n");
+
+#ifdef CONFIG_MIPS_MT_SMP
+	sanitize_tlb_entries();
+#endif
+}
+
+void __init prom_init(void)
+{
+	set_io_port_base(0xbfd00000);
+
+	pr_info("\nLINUX started...\n");
+	prom_init_cmdline();
+	prom_meminit();
+}
+
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+	struct uart_port s;
+
+	memset(&s, 0, sizeof(s));
+
+	s.iobase = 0x3f8;
+
+	/* hardware int 4 - the serial int, is CPU int 6
+	 but poll for now */
+	s.irq =  0;
+	s.uartclk = 1843200;
+	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	s.iotype = UPIO_PORT;
+	s.regshift = 0;
+	s.timeout = 4;
+
+	if (early_serial_setup(&s) != 0) {
+		printk(KERN_ERR "Serial setup failed!\n");
+	}
+
+#endif
+}
diff --git a/arch/mips/mipssim/sim_smp.c b/arch/mips/mipssim/sim_smp.c
new file mode 100644
index 0000000..38fa807
--- /dev/null
+++ b/arch/mips/mipssim/sim_smp.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+/*
+ * Simulator Platform-specific hooks for SMP operation
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/smtc_ipi.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+/* VPE/SMP Prototype implements platform interfaces directly */
+#if !defined(CONFIG_MIPS_MT_SMP)
+
+/*
+ * Cause the specified action to be performed on a targeted "CPU"
+ */
+
+void core_send_ipi(int cpu, unsigned int action)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
+#endif /* CONFIG_MIPS_MT_SMTC */
+/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
+
+}
+
+/*
+ * Platform "CPU" startup hook
+ */
+
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	smtc_boot_secondary(cpu, idle);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Post-config but pre-boot cleanup entry point
+ */
+
+void prom_init_secondary(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	void smtc_init_secondary(void);
+
+	smtc_init_secondary();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+void plat_smp_setup(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	if (read_c0_config3() & (1 << 2))
+		mipsmt_build_cpu_map(0);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform SMP pre-initialization
+ */
+
+void plat_prepare_cpus(unsigned int max_cpus)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * As noted above, we can assume a single CPU for now
+	 * but it may be multithreaded.
+	 */
+
+	if (read_c0_config3() & (1 << 2)) {
+		mipsmt_prepare_cpus();
+	}
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * SMP initialization finalization entry point
+ */
+
+void prom_smp_finish(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	smtc_smp_finish();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Hook for after all CPUs are online
+ */
+
+void prom_cpus_done(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c
new file mode 100644
index 0000000..a0f5a5d
--- /dev/null
+++ b/arch/mips/mipssim/sim_time.c
@@ -0,0 +1,199 @@
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/smp.h>
+#include <linux/timex.h>
+
+#include <asm/hardirq.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/mc146818-time.h>
+#include <asm/msc01_ic.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/simint.h>
+
+
+unsigned long cpu_khz;
+
+irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
+{
+#ifdef CONFIG_SMP
+	int cpu = smp_processor_id();
+
+	/*
+	 * CPU 0 handles the global timer interrupt job
+	 * resets count/compare registers to trigger next timer int.
+	 */
+#ifndef CONFIG_MIPS_MT_SMTC
+	if (cpu == 0) {
+		timer_interrupt(irq, dev_id);
+	} else {
+		/* Everyone else needs to reset the timer int here as
+		   ll_local_timer_interrupt doesn't */
+		/*
+		 * FIXME: need to cope with counter underflow.
+		 * More support needs to be added to kernel/time for
+		 * counter/timer interrupts on multiple CPU's
+		 */
+		write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+	}
+#else /* SMTC */
+	/*
+	 *  In SMTC system, one Count/Compare set exists per VPE.
+	 *  Which TC within a VPE gets the interrupt is essentially
+	 *  random - we only know that it shouldn't be one with
+	 *  IXMT set. Whichever TC gets the interrupt needs to
+	 *  send special interprocessor interrupts to the other
+	 *  TCs to make sure that they schedule, etc.
+	 *
+	 *  That code is specific to the SMTC kernel, not to
+	 *  the simulation platform, so it's invoked from
+	 *  the general MIPS timer_interrupt routine.
+	 *
+	 * We have a problem in that the interrupt vector code
+	 * had to turn off the timer IM bit to avoid redundant
+	 * entries, but we may never get to mips_cpu_irq_end
+	 * to turn it back on again if the scheduler gets
+	 * involved.  So we clear the pending timer here,
+	 * and re-enable the mask...
+	 */
+
+	int vpflags = dvpe();
+	write_c0_compare (read_c0_count() - 1);
+	clear_c0_cause(0x100 << cp0_compare_irq);
+	set_c0_status(0x100 << cp0_compare_irq);
+	irq_enable_hazard();
+	evpe(vpflags);
+
+	if (cpu_data[cpu].vpe_id == 0)
+		timer_interrupt(irq, dev_id);
+	else
+		write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+	smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+	/*
+	 * every CPU should do profiling and process accounting
+	 */
+	local_timer_interrupt (irq, dev_id);
+
+	return IRQ_HANDLED;
+#else
+	return timer_interrupt (irq, dev_id);
+#endif
+}
+
+
+
+/*
+ * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
+ */
+static unsigned int __init estimate_cpu_frequency(void)
+{
+	unsigned int prid = read_c0_prid() & 0xffff00;
+	unsigned int count;
+
+#if 1
+	/*
+	 * hardwire the board frequency to 12MHz.
+	 */
+
+	if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
+	    (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
+		count = 12000000;
+	else
+		count =  6000000;
+#else
+	unsigned int flags;
+
+	local_irq_save(flags);
+
+	/* Start counter exactly on falling edge of update flag */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+	/* Start r4k counter. */
+	write_c0_count(0);
+
+	/* Read counter exactly on falling edge of update flag */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+	count = read_c0_count();
+
+	/* restore interrupts */
+	local_irq_restore(flags);
+#endif
+
+	mips_hpt_frequency = count;
+
+	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+		count *= 2;
+
+	count += 5000;    /* round */
+	count -= count%10000;
+
+	return count;
+}
+
+void __init sim_time_init(void)
+{
+	unsigned int est_freq, flags;
+
+	local_irq_save(flags);
+
+	/* Set Data mode - binary. */
+	CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+	est_freq = estimate_cpu_frequency ();
+
+	printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
+	       (est_freq % 1000000) * 100 / 1000000);
+
+	cpu_khz = est_freq / 1000;
+
+	local_irq_restore(flags);
+}
+
+static int mips_cpu_timer_irq;
+
+static void mips_timer_dispatch(void)
+{
+	do_IRQ(mips_cpu_timer_irq);
+}
+
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+	if (cpu_has_veic) {
+		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
+		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
+	} else {
+		if (cpu_has_vint)
+			set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
+		mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+	}
+
+	/* we are using the cpu counter for timer interrupts */
+	irq->handler = sim_timer_interrupt;
+	setup_irq(mips_cpu_timer_irq, irq);
+
+#ifdef CONFIG_SMP
+	/* irq_desc(riptor) is a global resource, when the interrupt overlaps
+	   on seperate cpu's the first one tries to handle the second interrupt.
+	   The effect is that the int remains disabled on the second cpu.
+	   Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
+	irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU;
+	set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
+#endif
+}
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 293697b..19a0e54 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
 obj-$(CONFIG_HIGHMEM)		+= highmem.o
 
+obj-$(CONFIG_CPU_LOONGSON2)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_MIPS32)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_MIPS64)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_NEVADA)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index df04a31..be96231 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -335,6 +335,10 @@
 
 static inline void local_r4k___flush_cache_all(void * args)
 {
+#if defined(CONFIG_CPU_LOONGSON2)
+	r4k_blast_scache();
+	return;
+#endif
 	r4k_blast_dcache();
 	r4k_blast_icache();
 
@@ -848,6 +852,24 @@
 		c->options |= MIPS_CPU_PREFETCH;
 		break;
 
+	case CPU_LOONGSON2:
+		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+		if (prid & 0x3)
+			c->icache.ways = 4;
+		else
+			c->icache.ways = 2;
+		c->icache.waybit = 0;
+
+		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+		if (prid & 0x3)
+			c->dcache.ways = 4;
+		else
+			c->dcache.ways = 2;
+		c->dcache.waybit = 0;
+		break;
+
 	default:
 		if (!(config & MIPS_CONF_M))
 			panic("Don't know how to probe P-caches on this cpu.");
@@ -963,6 +985,14 @@
 		break;
 	}
 
+#ifdef  CONFIG_CPU_LOONGSON2
+	/*
+	 * LOONGSON2 has 4 way icache, but when using indexed cache op,
+	 * one op will act on all 4 ways
+	 */
+	c->icache.ways = 1;
+#endif
+
 	printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
 	       icache_size >> 10,
 	       cpu_has_vtag_icache ? "virtually tagged" : "physically tagged",
@@ -1036,6 +1066,24 @@
 	return 1;
 }
 
+#if defined(CONFIG_CPU_LOONGSON2)
+static void __init loongson2_sc_init(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	scache_size = 512*1024;
+	c->scache.linesz = 32;
+	c->scache.ways = 4;
+	c->scache.waybit = 0;
+	c->scache.waysize = scache_size / (c->scache.ways);
+	c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
+	pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
+	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+
+	c->options |= MIPS_CPU_INCLUSIVE_CACHES;
+}
+#endif
+
 extern int r5k_sc_init(void);
 extern int rm7k_sc_init(void);
 extern int mips_sc_init(void);
@@ -1085,6 +1133,12 @@
 #endif
 		return;
 
+#if defined(CONFIG_CPU_LOONGSON2)
+	case CPU_LOONGSON2:
+		loongson2_sc_init();
+		return;
+#endif
+
 	default:
 		if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
 		    c->isa_level == MIPS_CPU_ISA_M32R2 ||
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 9ea460b..6f9bd7f 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -476,7 +476,7 @@
  * memory management function pointers, as well as initialize
  * the caches and tlbs
  */
-void sb1_cache_init(void)
+void __init sb1_cache_init(void)
 {
 	extern char except_vec2_sb1;
 
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index abf99b1..81f925a 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -6,6 +6,8 @@
  * Copyright (C) 1994 - 2003, 07 by Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2007 MIPS Technologies, Inc.
  */
+#include <linux/fs.h>
+#include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -164,3 +166,11 @@
 
 	panic(cache_panic);
 }
+
+int __weak __uncached_access(struct file *file, unsigned long addr)
+{
+	if (file->f_flags & O_SYNC)
+		return 1;
+
+	return addr >= __pa(high_memory);
+}
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index f0eb299..76903c7 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -168,8 +168,9 @@
 		addr = (unsigned long) page_address(sg->page);
 		if (!plat_device_is_coherent(dev) && addr)
 			__dma_sync(addr + sg->offset, sg->length, direction);
-		sg->dma_address = plat_map_dma_mem_page(dev, sg->page) +
-		                  sg->offset;
+		sg->dma_address = plat_map_dma_mem(dev,
+				                   (void *)(addr + sg->offset),
+						   sg->length);
 	}
 
 	return nents;
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index cea7d0e..59945b9 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -9,7 +9,7 @@
 #include <linux/module.h>
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
-
+#include <linux/sched.h>
 #include <linux/vmalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/io.h>
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 65160d4..dcd6913 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -48,6 +48,22 @@
 
 #endif /* CONFIG_MIPS_MT_SMTC */
 
+#if defined(CONFIG_CPU_LOONGSON2)
+/*
+ * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
+ * unfortrunately, itlb is not totally transparent to software.
+ */
+#define FLUSH_ITLB write_c0_diag(4);
+
+#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC)  write_c0_diag(4); }
+
+#else
+
+#define FLUSH_ITLB
+#define FLUSH_ITLB_VM(vma)
+
+#endif
+
 void local_flush_tlb_all(void)
 {
 	unsigned long flags;
@@ -73,6 +89,7 @@
 	}
 	tlbw_use_hazard();
 	write_c0_entryhi(old_ctx);
+	FLUSH_ITLB;
 	EXIT_CRITICAL(flags);
 }
 
@@ -136,6 +153,7 @@
 		} else {
 			drop_mmu_context(mm, cpu);
 		}
+		FLUSH_ITLB;
 		EXIT_CRITICAL(flags);
 	}
 }
@@ -178,6 +196,7 @@
 	} else {
 		local_flush_tlb_all();
 	}
+	FLUSH_ITLB;
 	EXIT_CRITICAL(flags);
 }
 
@@ -210,6 +229,7 @@
 
 	finish:
 		write_c0_entryhi(oldpid);
+		FLUSH_ITLB_VM(vma);
 		EXIT_CRITICAL(flags);
 	}
 }
@@ -241,7 +261,7 @@
 		tlbw_use_hazard();
 	}
 	write_c0_entryhi(oldpid);
-
+	FLUSH_ITLB;
 	EXIT_CRITICAL(flags);
 }
 
@@ -293,6 +313,7 @@
 	else
 		tlb_write_indexed();
 	tlbw_use_hazard();
+	FLUSH_ITLB_VM(vma);
 	EXIT_CRITICAL(flags);
 }
 
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index e714929..4ec0964 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -893,6 +893,7 @@
 	case CPU_4KSC:
 	case CPU_20KC:
 	case CPU_25KF:
+	case CPU_LOONGSON2:
 		tlbw(p);
 		break;
 
@@ -1276,7 +1277,8 @@
 	 * need three, with the second nop'ed and the third being
 	 * unused.
 	 */
-#ifdef CONFIG_32BIT
+	/* Loongson2 ebase is different than r4k, we have more space */
+#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
 	if ((p - tlb_handler) > 64)
 		panic("TLB refill handler space exceeded");
 #else
@@ -1289,7 +1291,7 @@
 	/*
 	 * Now fold the handler in the TLB refill handler space.
 	 */
-#ifdef CONFIG_32BIT
+#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
 	f = final_handler;
 	/* Simplest case, just copy the handler. */
 	copy_handler(relocs, labels, tlb_handler, p, f);
@@ -1336,7 +1338,7 @@
 		final_len);
 
 	f = final_handler;
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2)
 	if (final_len > 32)
 		final_len = 64;
 	else
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
deleted file mode 100644
index d5a090a..0000000
--- a/arch/mips/momentum/ocelot_3/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-3 board.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-obj-y	 += irq.o platform.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
deleted file mode 100644
index 3862d1d..0000000
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Copyright (C) 2004 MontaVista Software Inc.
- *  Author: Manish Lachwani, mlachwani@mvista.com
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-static struct irqaction cascade_mv64340 = {
-	no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
-};
-
-void __init arch_init_irq(void)
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 * int-handler is not on bootstrap
-	 */
-	clear_c0_status(ST0_IM | ST0_BEV);
-
-	rm7k_cpu_irq_init();
-
-	/* set up the cascading interrupts */
-	setup_irq(8, &cascade_mv64340);		/* unmask intControl IM8, IRQ 9 */
-	mv64340_irq_init(16);
-
-	set_c0_status(ST0_IM); /* IE in the status register */
-
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status();
-
-	if (pending & STATUSF_IP0)
-		do_IRQ(0);
-	else if (pending & STATUSF_IP1)
-		do_IRQ(1);
-	else if (pending & STATUSF_IP2)
-		do_IRQ(2);
-	else if (pending & STATUSF_IP3)
-		do_IRQ(3);
-	else if (pending & STATUSF_IP4)
-		do_IRQ(4);
-	else if (pending & STATUSF_IP5)
-		do_IRQ(5);
-	else if (pending & STATUSF_IP6)
-		do_IRQ(6);
-	else if (pending & STATUSF_IP7)
-		do_IRQ(7);
-	else {
-		/*
-		 * Now look at the extended interrupts
-		 */
-		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
-
-		if (pending & STATUSF_IP8)
-			ll_mv64340_irq();
-		else
-			spurious_interrupt();
-	}
-}
diff --git a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h b/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h
deleted file mode 100644
index 5710a90..0000000
--- a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Ocelot-3 Board Register Definitions
- *
- * (C) 2002 Momentum Computer Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Louis Hamilton, Red Hat, Inc.
- *    hamilton@redhat.com  [MIPS64 modifications]
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- */
-
-#ifndef __OCELOT_3_FPGA_H__
-#define __OCELOT_3_FPGA_H__
-
-#define OCELOT_3_REG_BOARDREV		0x0
-#define OCELOT_3_REG_FPGA_REV		0x1
-#define OCELOT_3_REG_FPGA_TYPE		0x2
-#define OCELOT_3_REG_RESET_STATUS	0x3
-#define OCELOT_3_REG_BOARD_STATUS	0x4
-#define OCELOT_3_REG_CPCI_ID		0x5
-#define OCELOT_3_REG_SET		0x6
-#define OCELOT_3_REG_CLR		0x7
-#define OCELOT_3_REG_EEPROM_MODE	0x9
-#define OCELOT_3_REG_INTMASK		0xa
-#define OCELOT_3_REG_INTSTAT		0xb
-#define OCELOT_3_REG_UART_INTMASK	0xc
-#define OCELOT_3_REG_UART_INTSTAT	0xd
-#define OCELOT_3_REG_INTSET		0xe
-#define OCELOT_3_REG_INTCLR		0xf
-
-extern unsigned long ocelot_fpga_base;
-
-#define __FPGA_REG_TO_ADDR(reg)						\
-	((void *) ocelot_fpga_base + OCELOT_3_REG_##reg)
-#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
-
-#endif
diff --git a/arch/mips/momentum/ocelot_3/platform.c b/arch/mips/momentum/ocelot_3/platform.c
deleted file mode 100644
index 44e4c3f..0000000
--- a/arch/mips/momentum/ocelot_3/platform.c
+++ /dev/null
@@ -1,208 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "ocelot_3_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
-	[0] = {
-		.name   = "ethernet shared base",
-		.start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
-		.end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
-		                       MV643XX_ETH_SHARED_REGS_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
-	.name		= MV643XX_ETH_SHARED_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
-	.resource	= mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE			0xfe000000UL
-#define MV_SRAM_SIZE			(256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE		(MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE		(MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0		MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1		(MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-#define MV64x60_IRQ_ETH_2 50
-
-static struct resource mv64x60_eth0_resources[] = {
-	[0] = {
-		.name	= "eth0 irq",
-		.start	= MV64x60_IRQ_ETH_0,
-		.end	= MV64x60_IRQ_ETH_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
-	.port_number	= 0,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH0,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth0_resources),
-	.resource	= mv64x60_eth0_resources,
-	.dev = {
-		.platform_data = &eth0_pd,
-	},
-};
-
-static struct resource mv64x60_eth1_resources[] = {
-	[0] = {
-		.name	= "eth1 irq",
-		.start	= MV64x60_IRQ_ETH_1,
-		.end	= MV64x60_IRQ_ETH_1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
-	.port_number	= 1,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH1,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth1_resources),
-	.resource	= mv64x60_eth1_resources,
-	.dev = {
-		.platform_data = &eth1_pd,
-	},
-};
-
-static struct resource mv64x60_eth2_resources[] = {
-	[0] = {
-		.name	= "eth2 irq",
-		.start	= MV64x60_IRQ_ETH_2,
-		.end	= MV64x60_IRQ_ETH_2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth2_pd = {
-	.port_number	= 2,
-};
-
-static struct platform_device eth2_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth2_resources),
-	.resource	= mv64x60_eth2_resources,
-	.dev = {
-		.platform_data = &eth2_pd,
-	},
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
-	&mv643xx_eth_shared_device,
-	&eth0_device,
-	&eth1_device,
-	&eth2_device,
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
-	/* place the data */
-	OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock on */
-	OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock off and read-strobe */
-	OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
-	/* return the data */
-	return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
-	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	int i,j;
-
-	for (i = 0; i < 12; i++)
-		exchange_bit(read_opcode[i], 1);
-
-	for (j = 0; j < 6; j++) {
-		dest[j] = 0;
-		for (i = 0; i < 8; i++) {
-			dest[j] <<= 1;
-			dest[j] |= exchange_bit(0, 1);
-		}
-	}
-
-	/* turn off CS */
-	exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
-	unsigned int add)
-{
-	int i;
-
-	BUG_ON(add >= 256);
-
-	for (i = ETH_ALEN; i >= 0; i--) {
-		dst[i] = src[i] + add;
-		add = dst[i] < src[i];		/* compute carry */
-	}
-
-	WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
-	unsigned char mac[ETH_ALEN];
-	int ret;
-
-	get_mac(mac);
-	eth_mac_add(eth0_pd.mac_addr, mac, 0);
-	eth_mac_add(eth1_pd.mac_addr, mac, 1);
-	eth_mac_add(eth2_pd.mac_addr, mac, 2);
-	ret = platform_add_devices(mv643xx_eth_pd_devs,
-			ARRAY_SIZE(mv643xx_eth_pd_devs));
-
-	return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c
deleted file mode 100644
index 8e02df6..0000000
--- a/arch/mips/momentum/ocelot_3/prom.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- */
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-#include "ocelot_3_fpga.h"
-
-struct callvectors* debug_vectors;
-extern unsigned long marvell_base;
-extern unsigned long cpu_clock;
-
-const char *get_system_type(void)
-{
-	return "Momentum Ocelot-3";
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
-	addr &= 0xffffffff;
-	return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
-	unsigned long ul;
-	unsigned char *puc, uc;
-
-	args += (arc * 4);
-	ul = (unsigned long)signext(args);
-	puc = (unsigned char *)ul;
-	if (puc == 0)
-		return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-	uc = *puc++;
-	ul = (unsigned long)uc;
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 8);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 16);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 24);
-#else  /* CONFIG_CPU_LITTLE_ENDIAN */
-	uc = *puc++;
-	ul = ((unsigned long)uc) << 24;
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 16);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 8);
-	uc = *puc++;
-	ul |= ((unsigned long)uc);
-#endif  /* CONFIG_CPU_LITTLE_ENDIAN */
-	ul = signext(ul);
-	return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
-	unsigned long args;
-	char *p;
-
-	args = signext(addrin);
-	p = (char *)get_arg(args, arg_index);
-
-	return p;
-}
-#endif  /* CONFIG_64BIT */
-
-void __init prom_init(void)
-{
-	int argc = fw_arg0;
-	char **arg = (char **) fw_arg1;
-	char **env = (char **) fw_arg2;
-	struct callvectors *cv = (struct callvectors *) fw_arg3;
-	int i;
-
-#ifdef CONFIG_64BIT
-	char *ptr;
-	printk("prom_init - MIPS64\n");
-
-	/* save the PROM vectors for debugging use */
-	debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-
-	for (i = 1; i < argc; i++) {
-		ptr = (char *)arg64((unsigned long)arg, i);
-		if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
-		    sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, ptr);
-		strcat(arcs_cmdline, " ");
-	}
-	i = 0;
-
-	while (1) {
-		ptr = (char *)arg64((unsigned long)env, i);
-		if (! ptr)
-			break;
-
-		if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(ptr + strlen("gtbase="),
-							NULL, 16);
-
-			if ((marvell_base & 0xffffffff00000000) == 0)
-				marvell_base |= 0xffffffff00000000;
-
-			printk("marvell_base set to 0x%016lx\n", marvell_base);
-		}
-		if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
-							NULL, 10);
-			printk("cpu_clock set to %d\n", cpu_clock);
-		}
-		i++;
-	}
-	printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else   /* CONFIG_64BIT */
-
-	/* save the PROM vectors for debugging use */
-	debug_vectors = cv;
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
-		    >= sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, arg[i]);
-		strcat(arcs_cmdline, " ");
-	}
-
-	while (*env) {
-		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(*env + strlen("gtbase="),
-							NULL, 16);
-		}
-		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(*env + strlen("cpuclock="),
-							NULL, 10);
-		}
-		env++;
-	}
-#endif /* CONFIG_64BIT */
-
-	mips_machgroup = MACH_GROUP_MOMENCO;
-	mips_machtype = MACH_MOMENCO_OCELOT_3;
-
-#ifndef CONFIG_64BIT
-	debug_vectors->printf("Booting Linux kernel...\n");
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-}
diff --git a/arch/mips/momentum/ocelot_3/reset.c b/arch/mips/momentum/ocelot_3/reset.c
deleted file mode 100644
index 9d86d24..0000000
--- a/arch/mips/momentum/ocelot_3/reset.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 01, 05 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com  [MIPS64 modifications]
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void momenco_ocelot_restart(char *command)
-{
-	/* base address of timekeeper portion of part */
-	void *nvram = (void *) 0xfc807000L;
-
-	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
-	writeb(0x84, nvram + 0xff7);
-
-	/* wait for the watchdog to go off */
-	mdelay(100+(1000/16));
-
-	/* if the watchdog fails for some reason, let people know */
-	printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
-	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
-	momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
deleted file mode 100644
index ff0829f..0000000
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * setup.c
- *
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-3 board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 01, 05 - 06  Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- *   mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mc146818rtc.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-#include <linux/pm.h>
-#include <linux/bcd.h>
-
-#include <asm/time.h>
-#include <asm/page.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/mc146818rtc.h>
-#include <asm/tlbflush.h>
-#include "ocelot_3_fpga.h"
-
-/* Marvell Discovery Register Base */
-unsigned long marvell_base = (signed)0xf4000000;
-
-/* CPU clock */
-unsigned long cpu_clock;
-
-/* RTC/NVRAM */
-unsigned char* rtc_base = (unsigned char*)(signed)0xfc800000;
-
-/* FPGA Base */
-unsigned long ocelot_fpga_base = (signed)0xfc000000;
-
-/* Serial base */
-unsigned long uart_base = (signed)0xfd000000;
-
-/*
- * Marvell Discovery SRAM. This is one place where Ethernet
- * Tx and Rx descriptors can be placed to improve performance
- */
-extern unsigned long mv64340_sram_base;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-void momenco_time_init(void);
-static char reset_reason;
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
-		     unsigned long entryhi, unsigned long pagemask);
-
-static inline unsigned long ENTRYLO(unsigned long paddr)
-{
-	return ((paddr & PAGE_MASK) |
-		(_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
-		_CACHE_UNCACHED)) >> 6;
-}
-
-void __init bus_error_init(void)
-{
-	/* nothing */
-}
-
-/*
- * setup code for a handoff from a version 2 PMON 2000 PROM
- */
-void setup_wired_tlb_entries(void)
-{
-	write_c0_wired(0);
-	local_flush_tlb_all();
-
-	/* marvell and extra space */
-	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), (signed)0xf4000000, PM_64K);
-
-	/* fpga, rtc, and uart */
-	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M);
-}
-
-unsigned long m48t37y_get_time(void)
-{
-	unsigned int year, month, day, hour, min, sec;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* stop the update */
-	rtc_base[0x7ff8] = 0x40;
-
-	year = BCD2BIN(rtc_base[0x7fff]);
-	year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
-	month = BCD2BIN(rtc_base[0x7ffe]);
-
-	day = BCD2BIN(rtc_base[0x7ffd]);
-
-	hour = BCD2BIN(rtc_base[0x7ffb]);
-	min = BCD2BIN(rtc_base[0x7ffa]);
-	sec = BCD2BIN(rtc_base[0x7ff9]);
-
-	/* start the update */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
-	struct rtc_time tm;
-	unsigned long flags;
-
-	/* convert to a more useful format -- note months count from 0 */
-	to_tm(sec, &tm);
-	tm.tm_mon += 1;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* enable writing */
-	rtc_base[0x7ff8] = 0x80;
-
-	/* year */
-	rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
-	rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
-	/* month */
-	rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
-	/* day */
-	rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
-	/* hour/min/sec */
-	rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
-	rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
-	rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
-	/* day of week -- not really used, but let's keep it up-to-date */
-	rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
-	/* disable writing */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	setup_irq(7, irq);	/* Timer interrupt, unmask status IM7 */
-}
-
-void momenco_time_init(void)
-{
-	setup_wired_tlb_entries();
-
-	/*
-	 * Ocelot-3 board has been built with both
-	 * the Rm7900 and the Rm7065C
-	 */
-	mips_hpt_frequency = cpu_clock / 2;
-
-	rtc_mips_get_time = m48t37y_get_time;
-	rtc_mips_set_time = m48t37y_set_time;
-}
-
-/*
- * PCI Support for Ocelot-3
- */
-
-/* Bus #0 IO and MEM space */
-#define	OCELOT_3_PCI_IO_0_START		0xe0000000
-#define	OCELOT_3_PCI_IO_0_SIZE		0x08000000
-#define	OCELOT_3_PCI_MEM_0_START	0xc0000000
-#define	OCELOT_3_PCI_MEM_0_SIZE		0x10000000
-
-/* Bus #1 IO and MEM space */
-#define	OCELOT_3_PCI_IO_1_START		0xe8000000
-#define	OCELOT_3_PCI_IO_1_SIZE		0x08000000
-#define	OCELOT_3_PCI_MEM_1_START	0xd0000000
-#define	OCELOT_3_PCI_MEM_1_SIZE		0x10000000
-
-static struct resource mv_pci_io_mem0_resource = {
-	.name	= "MV64340 PCI0 IO MEM",
-	.start	= OCELOT_3_PCI_IO_0_START,
-	.end	= OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE - 1,
-	.flags  = IORESOURCE_IO,
-};
-
-static struct resource mv_pci_io_mem1_resource = {
-	.name	= "MV64340 PCI1 IO MEM",
-	.start	= OCELOT_3_PCI_IO_1_START,
-	.end	= OCELOT_3_PCI_IO_1_START + OCELOT_3_PCI_IO_1_SIZE - 1,
-	.flags	= IORESOURCE_IO,
-};
-
-static struct resource mv_pci_mem0_resource = {
-	.name	= "MV64340 PCI0 MEM",
-	.start	= OCELOT_3_PCI_MEM_0_START,
-	.end	= OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct resource mv_pci_mem1_resource = {
-	.name	= "MV64340 PCI1 MEM",
-	.start	= OCELOT_3_PCI_MEM_1_START,
-	.end	= OCELOT_3_PCI_MEM_1_START + OCELOT_3_PCI_MEM_1_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
-	.pcic = {
-		 .pci_ops	= &mv_pci_ops,
-		 .mem_resource	= &mv_pci_mem0_resource,
-		 .io_resource	= &mv_pci_io_mem0_resource,
-	},
-	.config_addr	= MV64340_PCI_0_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
-	.pcic = {
-		 .pci_ops	= &mv_pci_ops,
-		 .mem_resource	= &mv_pci_mem1_resource,
-		 .io_resource	= &mv_pci_io_mem1_resource,
-	},
-	.config_addr	= MV64340_PCI_1_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init int __init ja_pci_init(void)
-{
-	uint32_t enable;
-	extern int pci_probe_only;
-
-	/* PMON will assign PCI resources */
-	pci_probe_only = 1;
-
-	enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
-	/*
-	 * We require at least one enabled I/O or PCI memory window or we
-	 * will ignore this PCI bus.  We ignore PCI windows 1, 2 and 3.
-	 */
-	if (enable & (0x01 <<  9) || enable & (0x01 << 10))
-		register_pci_controller(&mv_bus0_controller.pcic);
-
-	if (enable & (0x01 << 14) || enable & (0x01 << 15))
-		register_pci_controller(&mv_bus1_controller.pcic);
-
-	ioport_resource.end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE +
-					OCELOT_3_PCI_IO_1_SIZE - 1;
-
-	iomem_resource.end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE +
-					OCELOT_3_PCI_MEM_1_SIZE - 1;
-
-	set_io_port_base(OCELOT_3_PCI_IO_0_START); /* mips_io_port_base */
-
-	return 0;
-}
-
-arch_initcall(ja_pci_init);
-
-void __init plat_mem_setup(void)
-{
-	unsigned int tmpword;
-
-	board_time_init = momenco_time_init;
-
-	_machine_restart = momenco_ocelot_restart;
-	_machine_halt = momenco_ocelot_halt;
-	pm_power_off = momenco_ocelot_power_off;
-
-	/* Wired TLB entries */
-	setup_wired_tlb_entries();
-
-	/* shut down ethernet ports, just to be sure our memory doesn't get
-	 * corrupted by random ethernet traffic.
-	 */
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
-	do {}
-	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
-		 MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
-		 MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-
-	/* Turn off the Bit-Error LED */
-	OCELOT_FPGA_WRITE(0x80, CLR);
-
-	tmpword = OCELOT_FPGA_READ(BOARDREV);
-	if (tmpword < 26)
-		printk("Momenco Ocelot-3: Board Assembly Rev. %c\n",
-			'A'+tmpword);
-	else
-		printk("Momenco Ocelot-3: Board Assembly Revision #0x%x\n",
-			tmpword);
-
-	tmpword = OCELOT_FPGA_READ(FPGA_REV);
-	printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
-	tmpword = OCELOT_FPGA_READ(RESET_STATUS);
-	printk("Reset reason: 0x%x\n", tmpword);
-	switch (tmpword) {
-		case 0x1:
-			printk("  - Power-up reset\n");
-			break;
-		case 0x2:
-			printk("  - Push-button reset\n");
-			break;
-		case 0x4:
-			printk("  - cPCI bus reset\n");
-			break;
-		case 0x8:
-			printk("  - Watchdog reset\n");
-			break;
-		case 0x10:
-			printk("  - Software reset\n");
-			break;
-		default:
-			printk("  - Unknown reset cause\n");
-	}
-	reset_reason = tmpword;
-	OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
-
-	tmpword = OCELOT_FPGA_READ(CPCI_ID);
-	printk("cPCI ID register: 0x%02x\n", tmpword);
-	printk("  - Slot number: %d\n", tmpword & 0x1f);
-	printk("  - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
-	printk("  - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
-
-	tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
-	printk("Board Status register: 0x%02x\n", tmpword);
-	printk("  - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
-	printk("  - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
-	printk("  - L3 cache size: %d MB\n", (1<<((tmpword&12) >> 2))&~1);
-
-	/* Support for 128 MB memory */
-	add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
deleted file mode 100644
index d69161a..0000000
--- a/arch/mips/momentum/ocelot_c/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-C and -CS boards.
-#
-
-obj-y	 		+= cpci-irq.o irq.o platform.o prom.o reset.o \
-			   setup.o uart-irq.o
-
-obj-$(CONFIG_KGDB)	+= dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
deleted file mode 100644
index 186a140..0000000
--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_c/cpci-irq.c
- *     Interrupt routines for cpci.  Interrupt numbers are assigned from
- *     CPCI_IRQ_BASE to CPCI_IRQ_BASE+8 (8 interrupt sources).
- *
- * Note that the high-level software will need to be careful about using
- * these interrupts.  If this board is asserting a cPCI interrupt, it will
- * also see the asserted interrupt.  Care must be taken to avoid an
- * interrupt flood.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include "ocelot_c_fpga.h"
-
-#define CPCI_IRQ_BASE	8
-
-static inline int ls1bit8(unsigned int x)
-{
-        int b = 7, s;
-
-        s =  4; if (((unsigned char)(x <<  4)) == 0) s = 0; b -= s; x <<= s;
-        s =  2; if (((unsigned char)(x <<  2)) == 0) s = 0; b -= s; x <<= s;
-        s =  1; if (((unsigned char)(x <<  1)) == 0) s = 0; b -= s;
-
-        return b;
-}
-
-/* mask off an interrupt -- 0 is enable, 1 is disable */
-static inline void mask_cpci_irq(unsigned int irq)
-{
-	uint32_t value;
-
-	value = OCELOT_FPGA_READ(INTMASK);
-	value |= 1 << (irq - CPCI_IRQ_BASE);
-	OCELOT_FPGA_WRITE(value, INTMASK);
-
-	/* read the value back to assure that it's really been written */
-	value = OCELOT_FPGA_READ(INTMASK);
-}
-
-/* unmask an interrupt -- 0 is enable, 1 is disable */
-static inline void unmask_cpci_irq(unsigned int irq)
-{
-	uint32_t value;
-
-	value = OCELOT_FPGA_READ(INTMASK);
-	value &= ~(1 << (irq - CPCI_IRQ_BASE));
-	OCELOT_FPGA_WRITE(value, INTMASK);
-
-	/* read the value back to assure that it's really been written */
-	value = OCELOT_FPGA_READ(INTMASK);
-}
-
-/*
- * Interrupt handler for interrupts coming from the FPGA chip.
- * It could be built in ethernet ports etc...
- */
-void ll_cpci_irq(void)
-{
-	unsigned int irq_src, irq_mask;
-
-	/* read the interrupt status registers */
-	irq_src = OCELOT_FPGA_READ(INTSTAT);
-	irq_mask = OCELOT_FPGA_READ(INTMASK);
-
-	/* mask for just the interrupts we want */
-	irq_src &= ~irq_mask;
-
-	do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE);
-}
-
-struct irq_chip cpci_irq_type = {
-	.name = "CPCI/FPGA",
-	.ack = mask_cpci_irq,
-	.mask = mask_cpci_irq,
-	.mask_ack = mask_cpci_irq,
-	.unmask = unmask_cpci_irq,
-};
-
-void cpci_irq_init(void)
-{
-	int i;
-
-	for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++)
-		set_irq_chip_and_handler(i, &cpci_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c
deleted file mode 100644
index 32d6fb4..0000000
--- a/arch/mips/momentum/ocelot_c/dbg_io.c
+++ /dev/null
@@ -1,121 +0,0 @@
-
-#include <asm/serial.h> /* For the serial port location and base baud */
-
-/* --- CONFIG --- */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-/* --- END OF CONFIG --- */
-
-#define         UART16550_BAUD_2400             2400
-#define         UART16550_BAUD_4800             4800
-#define         UART16550_BAUD_9600             9600
-#define         UART16550_BAUD_19200            19200
-#define         UART16550_BAUD_38400            38400
-#define         UART16550_BAUD_57600            57600
-#define         UART16550_BAUD_115200           115200
-
-#define         UART16550_PARITY_NONE           0
-#define         UART16550_PARITY_ODD            0x08
-#define         UART16550_PARITY_EVEN           0x18
-#define         UART16550_PARITY_MARK           0x28
-#define         UART16550_PARITY_SPACE          0x38
-
-#define         UART16550_DATA_5BIT             0x0
-#define         UART16550_DATA_6BIT             0x1
-#define         UART16550_DATA_7BIT             0x2
-#define         UART16550_DATA_8BIT             0x3
-
-#define         UART16550_STOP_1BIT             0x0
-#define         UART16550_STOP_2BIT             0x4
-
-/* ----------------------------------------------------- */
-
-/* === CONFIG === */
-
-/* [jsun] we use the second serial port for kdb */
-#define         BASE                    OCELOT_SERIAL1_BASE
-#define         MAX_BAUD                OCELOT_BASE_BAUD
-
-/* === END OF CONFIG === */
-
-#define         REG_OFFSET              4
-
-/* register offset */
-#define         OFS_RCV_BUFFER          0
-#define         OFS_TRANS_HOLD          0
-#define         OFS_SEND_BUFFER         0
-#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
-#define         OFS_INTR_ID             (2*REG_OFFSET)
-#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
-#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
-#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
-#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
-#define         OFS_LINE_STATUS         (5*REG_OFFSET)
-#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
-#define         OFS_RS232_INPUT         (6*REG_OFFSET)
-#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
-
-#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
-#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
-#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
-	/* disable interrupts */
-	UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
-	/* set up baud rate */
-	{
-		uint32 divisor;
-
-		/* set DIAB bit */
-		UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
-		/* set divisor */
-		divisor = MAX_BAUD / baud;
-		UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
-		UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
-		/* clear DIAB bit */
-		UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
-	}
-
-	/* set data format */
-	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-static int remoteDebugInitialized = 0;
-
-uint8 getDebugChar(void)
-{
-	if (!remoteDebugInitialized) {
-		remoteDebugInitialized = 1;
-		debugInit(UART16550_BAUD_38400,
-			  UART16550_DATA_8BIT,
-			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-	}
-
-	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
-	return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
-	if (!remoteDebugInitialized) {
-		remoteDebugInitialized = 1;
-		debugInit(UART16550_BAUD_38400,
-			  UART16550_DATA_8BIT,
-			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-	}
-
-	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
-	UART16550_WRITE(OFS_SEND_BUFFER, byte);
-	return 1;
-}
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
deleted file mode 100644
index 844d566..0000000
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <linux/mv643xx.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-extern void uart_irq_init(void);
-extern void cpci_irq_init(void);
-
-static struct irqaction cascade_fpga = {
-	no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via FPGA", NULL, NULL
-};
-
-static struct irqaction cascade_mv64340 = {
-	no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
-};
-
-extern void ll_uart_irq(void);
-extern void ll_cpci_irq(void);
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-
-	if (pending & STATUSF_IP0)
-		do_IRQ(0);
-	else if (pending & STATUSF_IP1)
-		do_IRQ(1);
-	else if (pending & STATUSF_IP2)
-		do_IRQ(2);
-	else if (pending & STATUSF_IP3)
-		ll_uart_irq();
-	else if (pending & STATUSF_IP4)
-		do_IRQ(4);
-	else if (pending & STATUSF_IP5)
-		ll_cpci_irq();
-	else if (pending & STATUSF_IP6)
-		ll_mv64340_irq();
-	else if (pending & STATUSF_IP7)
-		do_IRQ(7);
-	else
-		spurious_interrupt();
-}
-
-void __init arch_init_irq(void)
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 * int-handler is not on bootstrap
-	 */
-	clear_c0_status(ST0_IM);
-
-	mips_cpu_irq_init();
-
-	/* set up the cascading interrupts */
-	setup_irq(3, &cascade_fpga);
-	setup_irq(5, &cascade_fpga);
-	setup_irq(6, &cascade_mv64340);
-
-	mv64340_irq_init(16);
-	uart_irq_init();
-	cpci_irq_init();
-}
diff --git a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
deleted file mode 100644
index f0f5581..0000000
--- a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Ocelot-C Board Register Definitions
- *
- * (C) 2002 Momentum Computer Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Louis Hamilton, Red Hat, Inc.
- *    hamilton@redhat.com  [MIPS64 modifications]
- */
-
-#ifndef __OCELOT_C_FPGA_H__
-#define __OCELOT_C_FPGA_H__
-
-
-#ifdef CONFIG_64BIT
-#define OCELOT_C_CS0_ADDR       (0xfffffffffc000000)
-#else
-#define OCELOT_C_CS0_ADDR               (0xfc000000)
-#endif
-
-#define OCELOT_C_REG_BOARDREV		0x0
-#define OCELOT_C_REG_FPGA_REV		0x1
-#define OCELOT_C_REG_FPGA_TYPE		0x2
-#define OCELOT_C_REG_RESET_STATUS	0x3
-#define OCELOT_C_REG_BOARD_STATUS	0x4
-#define OCELOT_C_REG_CPCI_ID		0x5
-#define OCELOT_C_REG_SET		0x6
-#define OCELOT_C_REG_CLR		0x7
-#define OCELOT_C_REG_EEPROM_MODE	0x9
-#define OCELOT_C_REG_INTMASK		0xa
-#define OCELOT_C_REG_INTSTAT		0xb
-#define OCELOT_C_REG_UART_INTMASK	0xc
-#define OCELOT_C_REG_UART_INTSTAT	0xd
-#define OCELOT_C_REG_INTSET		0xe
-#define OCELOT_C_REG_INTCLR		0xf
-
-#define __FPGA_REG_TO_ADDR(reg)						\
-	((void *) OCELOT_C_CS0_ADDR + OCELOT_C_REG_##reg)
-#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
-
-#endif
diff --git a/arch/mips/momentum/ocelot_c/platform.c b/arch/mips/momentum/ocelot_c/platform.c
deleted file mode 100644
index 7780aa0..0000000
--- a/arch/mips/momentum/ocelot_c/platform.c
+++ /dev/null
@@ -1,183 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "ocelot_c_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
-	[0] = {
-		.name   = "ethernet shared base",
-		.start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
-		.end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
-		                       MV643XX_ETH_SHARED_REGS_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
-	.name		= MV643XX_ETH_SHARED_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
-	.resource	= mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE			0xfe000000UL
-#define MV_SRAM_SIZE			(256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE		(MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE		(MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0		MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1		(MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-
-static struct resource mv64x60_eth0_resources[] = {
-	[0] = {
-		.name	= "eth0 irq",
-		.start	= MV64x60_IRQ_ETH_0,
-		.end	= MV64x60_IRQ_ETH_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
-	.port_number	= 0,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH0,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth0_resources),
-	.resource	= mv64x60_eth0_resources,
-	.dev = {
-		.platform_data = &eth0_pd,
-	},
-};
-
-static struct resource mv64x60_eth1_resources[] = {
-	[0] = {
-		.name	= "eth1 irq",
-		.start	= MV64x60_IRQ_ETH_1,
-		.end	= MV64x60_IRQ_ETH_1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
-	.port_number	= 1,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH1,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth1_resources),
-	.resource	= mv64x60_eth1_resources,
-	.dev = {
-		.platform_data = &eth1_pd,
-	},
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
-	&mv643xx_eth_shared_device,
-	&eth0_device,
-	&eth1_device,
-	/* The third port is not wired up on the Ocelot C */
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
-	/* place the data */
-	OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock on */
-	OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock off and read-strobe */
-	OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
-	/* return the data */
-	return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
-	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	int i,j;
-
-	for (i = 0; i < 12; i++)
-		exchange_bit(read_opcode[i], 1);
-
-	for (j = 0; j < 6; j++) {
-		dest[j] = 0;
-		for (i = 0; i < 8; i++) {
-			dest[j] <<= 1;
-			dest[j] |= exchange_bit(0, 1);
-		}
-	}
-
-	/* turn off CS */
-	exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
-	unsigned int add)
-{
-	int i;
-
-	BUG_ON(add >= 256);
-
-	for (i = ETH_ALEN; i >= 0; i--) {
-		dst[i] = src[i] + add;
-		add = dst[i] < src[i];		/* compute carry */
-	}
-
-	WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
-	unsigned char mac[ETH_ALEN];
-	int ret;
-
-	get_mac(mac);
-	eth_mac_add(eth0_pd.mac_addr, mac, 0);
-	eth_mac_add(eth1_pd.mac_addr, mac, 1);
-	ret = platform_add_devices(mv643xx_eth_pd_devs,
-			ARRAY_SIZE(mv643xx_eth_pd_devs));
-
-	return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
deleted file mode 100644
index b689cee..0000000
--- a/arch/mips/momentum/ocelot_c/prom.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-
-#include "ocelot_c_fpga.h"
-
-struct callvectors* debug_vectors;
-
-extern unsigned long marvell_base;
-extern unsigned int cpu_clock;
-
-const char *get_system_type(void)
-{
-#ifdef CONFIG_CPU_SR71000
-	return "Momentum Ocelot-CS";
-#else
-	return "Momentum Ocelot-C";
-#endif
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
-  addr &= 0xffffffff;
-  return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
-  unsigned long ul;
-  unsigned char *puc, uc;
-
-  args += (arc * 4);
-  ul = (unsigned long)signext(args);
-  puc = (unsigned char *)ul;
-  if (puc == 0)
-    return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-  uc = *puc++;
-  ul = (unsigned long)uc;
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 8);
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 16);
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 24);
-#else  /* CONFIG_CPU_LITTLE_ENDIAN */
-  uc = *puc++;
-  ul = ((unsigned long)uc) << 24;
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 16);
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 8);
-  uc = *puc++;
-  ul |= ((unsigned long)uc);
-#endif  /* CONFIG_CPU_LITTLE_ENDIAN */
-  ul = signext(ul);
-  return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
-  unsigned long args;
-  char *p;
-  args = signext(addrin);
-  p = (char *)get_arg(args, arg_index);
-  return p;
-}
-#endif  /* CONFIG_64BIT */
-
-
-void __init prom_init(void)
-{
-	int argc = fw_arg0;
-	char **arg = (char **) fw_arg1;
-	char **env = (char **) fw_arg2;
-	struct callvectors *cv = (struct callvectors *) fw_arg3;
-	int i;
-
-#ifdef CONFIG_64BIT
-	char *ptr;
-
-	printk("prom_init - MIPS64\n");
-	/* save the PROM vectors for debugging use */
-	debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-
-	for (i = 1; i < argc; i++) {
-		ptr = (char *)arg64((unsigned long)arg, i);
-		if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
-		    sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, ptr);
-		strcat(arcs_cmdline, " ");
-	}
-	i = 0;
-	while (1) {
-		ptr = (char *)arg64((unsigned long)env, i);
-		if (! ptr)
-			break;
-
-		if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(ptr + strlen("gtbase="),
-							NULL, 16);
-
-			if ((marvell_base & 0xffffffff00000000) == 0)
-				marvell_base |= 0xffffffff00000000;
-
-			printk("marvell_base set to 0x%016lx\n", marvell_base);
-		}
-		if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
-							NULL, 10);
-			printk("cpu_clock set to %d\n", cpu_clock);
-		}
-		i++;
-	}
-	printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else   /* CONFIG_64BIT */
-	/* save the PROM vectors for debugging use */
-	debug_vectors = cv;
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
-		    >= sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, arg[i]);
-		strcat(arcs_cmdline, " ");
-	}
-
-	while (*env) {
-		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(*env + strlen("gtbase="),
-							NULL, 16);
-		}
-		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(*env + strlen("cpuclock="),
-							NULL, 10);
-		}
-		env++;
-	}
-#endif /* CONFIG_64BIT */
-
-	mips_machgroup = MACH_GROUP_MOMENCO;
-	mips_machtype = MACH_MOMENCO_OCELOT_C;
-
-#ifndef CONFIG_64BIT
-	debug_vectors->printf("Booting Linux kernel...\n");
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
diff --git a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c
deleted file mode 100644
index 3fdcb64..0000000
--- a/arch/mips/momentum/ocelot_c/reset.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com  [MIPS64 modifications]
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-
-void momenco_ocelot_restart(char *command)
-{
-	/* base address of timekeeper portion of part */
-	void *nvram = (void *)
-#ifdef CONFIG_64BIT
-		0xfffffffffc807000;
-#else
-		0xfc807000;
-#endif
-
-	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
-	writeb(0x84, nvram + 0xff7);
-
-	/* wait for the watchdog to go off */
-	mdelay(100+(1000/16));
-
-	/* if the watchdog fails for some reason, let people know */
-	printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
-	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
-	momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
deleted file mode 100644
index 0b6b233..0000000
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-C and -CS board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 2001  Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- *   mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-#include <linux/timex.h>
-#include <linux/vmalloc.h>
-#include <linux/mv643xx.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/marvell.h>
-#include <linux/bootmem.h>
-#include <linux/blkdev.h>
-#include "ocelot_c_fpga.h"
-
-unsigned long marvell_base;
-unsigned int cpu_clock;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-void momenco_time_init(void);
-
-static char reset_reason;
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask);
-
-static unsigned long ENTRYLO(unsigned long paddr)
-{
-	return ((paddr & PAGE_MASK) |
-	       (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
-		_CACHE_UNCACHED)) >> 6;
-}
-
-/* setup code for a handoff from a version 2 PMON 2000 PROM */
-void PMON_v2_setup(void)
-{
-	/* Some wired TLB entries for the MV64340 and perhiperals. The
-	   MV64340 is going to be hit on every IRQ anyway - there's
-	   absolutely no point in letting it be a random TLB entry, as
-	   it'll just cause needless churning of the TLB. And we use
-	   the other half for the serial port, which is just a PITA
-	   otherwise :)
-
-		Device			Physical	Virtual
-		MV64340 Internal Regs	0xf4000000	0xf4000000
-		Ocelot-C[S] PLD (CS0)	0xfc000000	0xfc000000
-		NVRAM (CS1)		0xfc800000	0xfc800000
-		UARTs (CS2)		0xfd000000	0xfd000000
-		Internal SRAM		0xfe000000	0xfe000000
-		M-Systems DOC (CS3)	0xff000000	0xff000000
-	*/
-  printk("PMON_v2_setup\n");
-
-#ifdef CONFIG_64BIT
-	/* marvell and extra space */
-	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K);
-	/* fpga, rtc, and uart */
-	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M);
-	/* m-sys and internal SRAM */
-	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M);
-
-	marvell_base = 0xfffffffff4000000;
-#else
-	/* marvell and extra space */
-	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K);
-	/* fpga, rtc, and uart */
-	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfc000000, PM_16M);
-	/* m-sys and internal SRAM */
-	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M);
-
-	marvell_base = 0xf4000000;
-#endif
-}
-
-unsigned long m48t37y_get_time(void)
-{
-#ifdef CONFIG_64BIT
-	unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
-#else
-	unsigned char* rtc_base = (unsigned char*)0xfc800000;
-#endif
-	unsigned int year, month, day, hour, min, sec;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* stop the update */
-	rtc_base[0x7ff8] = 0x40;
-
-	year = BCD2BIN(rtc_base[0x7fff]);
-	year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
-	month = BCD2BIN(rtc_base[0x7ffe]);
-
-	day = BCD2BIN(rtc_base[0x7ffd]);
-
-	hour = BCD2BIN(rtc_base[0x7ffb]);
-	min = BCD2BIN(rtc_base[0x7ffa]);
-	sec = BCD2BIN(rtc_base[0x7ff9]);
-
-	/* start the update */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
-#ifdef CONFIG_64BIT
-	unsigned char* rtc_base = (unsigned char*)0xfffffffffc800000;
-#else
-	unsigned char* rtc_base = (unsigned char*)0xfc800000;
-#endif
-	struct rtc_time tm;
-	unsigned long flags;
-
-	/* convert to a more useful format -- note months count from 0 */
-	to_tm(sec, &tm);
-	tm.tm_mon += 1;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* enable writing */
-	rtc_base[0x7ff8] = 0x80;
-
-	/* year */
-	rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
-	rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
-	/* month */
-	rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
-	/* day */
-	rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
-	/* hour/min/sec */
-	rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
-	rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
-	rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
-	/* day of week -- not really used, but let's keep it up-to-date */
-	rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
-	/* disable writing */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	setup_irq(7, irq);
-}
-
-void momenco_time_init(void)
-{
-#ifdef CONFIG_CPU_SR71000
-	mips_hpt_frequency = cpu_clock;
-#elif defined(CONFIG_CPU_RM7000)
-	mips_hpt_frequency = cpu_clock / 2;
-#else
-#error Unknown CPU for this board
-#endif
-	printk("momenco_time_init cpu_clock=%d\n", cpu_clock);
-
-	rtc_mips_get_time = m48t37y_get_time;
-	rtc_mips_set_time = m48t37y_set_time;
-}
-
-void __init plat_mem_setup(void)
-{
-	unsigned int tmpword;
-
-	board_time_init = momenco_time_init;
-
-	_machine_restart = momenco_ocelot_restart;
-	_machine_halt = momenco_ocelot_halt;
-	pm_power_off = momenco_ocelot_power_off;
-
-	/*
-	 * initrd_start = (unsigned long)ocelot_initrd_start;
-	 * initrd_end = (unsigned long)ocelot_initrd_start + (ulong)ocelot_initrd_size;
-	 * initrd_below_start_ok = 1;
-	 */
-
-	/* do handoff reconfiguration */
-	PMON_v2_setup();
-
-	/* shut down ethernet ports, just to be sure our memory doesn't get
-	 * corrupted by random ethernet traffic.
-	 */
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
-	do {}
-	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
-	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
-	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-
-	/* Turn off the Bit-Error LED */
-	OCELOT_FPGA_WRITE(0x80, CLR);
-
-	tmpword = OCELOT_FPGA_READ(BOARDREV);
-#ifdef CONFIG_CPU_SR71000
-	if (tmpword < 26)
-		printk("Momenco Ocelot-CS: Board Assembly Rev. %c\n",
-			'A'+tmpword);
-	else
-		printk("Momenco Ocelot-CS: Board Assembly Revision #0x%x\n",
-			tmpword);
-#else
-	if (tmpword < 26)
-		printk("Momenco Ocelot-C: Board Assembly Rev. %c\n",
-			'A'+tmpword);
-	else
-		printk("Momenco Ocelot-C: Board Assembly Revision #0x%x\n",
-			tmpword);
-#endif
-
-	tmpword = OCELOT_FPGA_READ(FPGA_REV);
-	printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
-	tmpword = OCELOT_FPGA_READ(RESET_STATUS);
-	printk("Reset reason: 0x%x\n", tmpword);
-	switch (tmpword) {
-		case 0x1:
-			printk("  - Power-up reset\n");
-			break;
-		case 0x2:
-			printk("  - Push-button reset\n");
-			break;
-		case 0x4:
-			printk("  - cPCI bus reset\n");
-			break;
-		case 0x8:
-			printk("  - Watchdog reset\n");
-			break;
-		case 0x10:
-			printk("  - Software reset\n");
-			break;
-		default:
-			printk("  - Unknown reset cause\n");
-	}
-	reset_reason = tmpword;
-	OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
-
-	tmpword = OCELOT_FPGA_READ(CPCI_ID);
-	printk("cPCI ID register: 0x%02x\n", tmpword);
-	printk("  - Slot number: %d\n", tmpword & 0x1f);
-	printk("  - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
-	printk("  - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
-
-	tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
-	printk("Board Status register: 0x%02x\n", tmpword);
-	printk("  - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
-	printk("  - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
-	printk("  - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
-	printk("  - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
-
-	switch(tmpword &3) {
-	case 3:
-		/* 512MiB */
-		add_memory_region(0x0, 0x200<<20, BOOT_MEM_RAM);
-		break;
-	case 2:
-		/* 256MiB */
-		add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
-		break;
-	case 1:
-		/* 128MiB */
-		add_memory_region(0x0,  0x80<<20, BOOT_MEM_RAM);
-		break;
-	case 0:
-		/* 1GiB -- needs CONFIG_HIGHMEM */
-		add_memory_region(0x0, 0x400<<20, BOOT_MEM_RAM);
-		break;
-	}
-}
-
-/*
- * This needs to be one of the first initcalls, because no I/O port access
- * can work before this
- */
-static int io_base_ioremap(void)
-{
-	void __iomem * io_remap_range = ioremap(0xc0000000UL, 0x10000);
-
-	if (!io_remap_range)
-		panic("Could not ioremap I/O port range");
-
-	set_io_port_base((unsigned long) io_remap_range);
-
-	return 0;
-}
-
-module_init(io_base_ioremap);
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
deleted file mode 100644
index de1a31e..0000000
--- a/arch/mips/momentum/ocelot_c/uart-irq.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_c/uart-irq.c
- *     Interrupt routines for UARTs.  Interrupt numbers are assigned from
- *     80 to 81 (2 interrupt sources).
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "ocelot_c_fpga.h"
-
-static inline int ls1bit8(unsigned int x)
-{
-        int b = 7, s;
-
-        s =  4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s;
-        s =  2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s;
-        s =  1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s;
-
-        return b;
-}
-
-/* mask off an interrupt -- 0 is enable, 1 is disable */
-static inline void mask_uart_irq(unsigned int irq)
-{
-	uint8_t value;
-
-	value = OCELOT_FPGA_READ(UART_INTMASK);
-	value |= 1 << (irq - 74);
-	OCELOT_FPGA_WRITE(value, UART_INTMASK);
-
-	/* read the value back to assure that it's really been written */
-	value = OCELOT_FPGA_READ(UART_INTMASK);
-}
-
-/* unmask an interrupt -- 0 is enable, 1 is disable */
-static inline void unmask_uart_irq(unsigned int irq)
-{
-	uint8_t value;
-
-	value = OCELOT_FPGA_READ(UART_INTMASK);
-	value &= ~(1 << (irq - 74));
-	OCELOT_FPGA_WRITE(value, UART_INTMASK);
-
-	/* read the value back to assure that it's really been written */
-	value = OCELOT_FPGA_READ(UART_INTMASK);
-}
-
-/*
- * Interrupt handler for interrupts coming from the FPGA chip.
- */
-void ll_uart_irq(void)
-{
-	unsigned int irq_src, irq_mask;
-
-	/* read the interrupt status registers */
-	irq_src = OCELOT_FPGA_READ(UART_INTSTAT);
-	irq_mask = OCELOT_FPGA_READ(UART_INTMASK);
-
-	/* mask for just the interrupts we want */
-	irq_src &= ~irq_mask;
-
-	do_IRQ(ls1bit8(irq_src) + 74);
-}
-
-struct irq_chip uart_irq_type = {
-	.name = "UART/FPGA",
-	.ack = mask_uart_irq,
-	.mask = mask_uart_irq,
-	.mask_ack = mask_uart_irq,
-	.unmask = unmask_uart_irq,
-};
-
-void uart_irq_init(void)
-{
-	set_irq_chip_and_handler(80, &uart_irq_type, handle_level_irq);
-	set_irq_chip_and_handler(81, &uart_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 4f94fa2..1ea5c9c 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -177,7 +177,10 @@
 	unsigned int counters = op_model_mipsxx_ops.num_counters;
 	unsigned int control;
 	unsigned int counter;
-	int handled = 0;
+	int handled = IRQ_NONE;
+
+	if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26)))
+		return handled;
 
 	switch (counters) {
 #define HANDLE_COUNTER(n)						\
@@ -188,7 +191,7 @@
 		    (counter & M_COUNTER_OVERFLOW)) {			\
 			oprofile_add_sample(get_irq_regs(), n);		\
 			w_c0_perfcntr ## n(reg.counter[n]);		\
-			handled = 1;					\
+			handled = IRQ_HANDLED;				\
 		}
 	HANDLE_COUNTER(3)
 	HANDLE_COUNTER(2)
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index aba3dbf..c58bd3d 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -2,16 +2,14 @@
 # Makefile for the PCI specific kernel interface routines under Linux.
 #
 
-obj-y				+= pci.o pci-dac.o
+obj-y				+= pci.o
 
 #
 # PCI bus host bridge specific code
 #
 obj-$(CONFIG_MIPS_BONITO64)	+= ops-bonito64.o
 obj-$(CONFIG_PCI_GT64XXX_PCI0)	+= ops-gt64xxx_pci0.o
-obj-$(CONFIG_PCI_MARVELL)	+= ops-marvell.o
 obj-$(CONFIG_MIPS_MSC)		+= ops-msc.o
-obj-$(CONFIG_MIPS_NILE4)	+= ops-nile4.o
 obj-$(CONFIG_MIPS_TX3927)	+= ops-tx3927.o
 obj-$(CONFIG_PCI_VR41XX)	+= ops-vr41xx.o pci-vr41xx.o
 obj-$(CONFIG_NEC_CMBVR4133)	+= fixup-vr4133.o
@@ -22,17 +20,17 @@
 #
 obj-$(CONFIG_BASLER_EXCITE)	+= ops-titan.o pci-excite.o fixup-excite.o
 obj-$(CONFIG_DDB5477)		+= fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
-obj-$(CONFIG_LASAT)		+= pci-lasat.o
 obj-$(CONFIG_MIPS_ATLAS)	+= fixup-atlas.o
 obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
-obj-$(CONFIG_MIPS_EV64120)	+= pci-ev64120.o
 obj-$(CONFIG_SOC_AU1500)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_AU1550)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_PNX8550)	+= fixup-pnx8550.o ops-pnx8550.o
+obj-$(CONFIG_LEMOTE_FULONG)	+= fixup-lm2e.o ops-bonito64.o
 obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o
 obj-$(CONFIG_MOMENCO_OCELOT)	+= fixup-ocelot.o pci-ocelot.o
-obj-$(CONFIG_MOMENCO_OCELOT_3)	+= fixup-ocelot3.o
-obj-$(CONFIG_MOMENCO_OCELOT_C)	+= fixup-ocelot-c.o pci-ocelot-c.o
+obj-$(CONFIG_PMC_MSP7120_GW)	+= fixup-pmcmsp.o ops-pmcmsp.o
+obj-$(CONFIG_PMC_MSP7120_EVAL)	+= fixup-pmcmsp.o ops-pmcmsp.o
+obj-$(CONFIG_PMC_MSP7120_FPGA)	+= fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_YOSEMITE)	+= fixup-yosemite.o ops-titan.o ops-titan-ht.o \
 				   pci-yosemite.o
 obj-$(CONFIG_SGI_IP27)		+= ops-bridge.o pci-ip27.o
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
index c6cd6e9..45224fd 100644
--- a/arch/mips/pci/fixup-atlas.c
+++ b/arch/mips/pci/fixup-atlas.c
@@ -58,7 +58,7 @@
 	{0,	0,	0,	0,	0 }	/* 21: Unused */
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
index c2f8304..ca0276c 100644
--- a/arch/mips/pci/fixup-au1000.c
+++ b/arch/mips/pci/fixup-au1000.c
@@ -35,7 +35,7 @@
 
 extern char irq_tab_alchemy[][5];
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab_alchemy[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
index 1e53075..1416bca 100644
--- a/arch/mips/pci/fixup-capcella.c
+++ b/arch/mips/pci/fixup-capcella.c
@@ -38,7 +38,7 @@
  [14] = { -1, INTA, INTB, INTC, INTD }
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab_capcella[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index d57ffd7..76b4f0f 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -58,8 +58,6 @@
 
 static void qube_raq_galileo_fixup(struct pci_dev *dev)
 {
-	unsigned short galileo_id;
-
 	if (dev->devfn != PCI_DEVFN(0, 0))
 		return;
 
@@ -84,16 +82,14 @@
 	 * Therefore we must set the disconnect/retry cycle values to
 	 * something sensible when using the new Galileo.
 	 */
-	pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id);
-	galileo_id &= 0xff;	/* mask off class info */
 
- 	printk(KERN_INFO "Galileo: revision %u\n", galileo_id);
+ 	printk(KERN_INFO "Galileo: revision %u\n", dev->revision);
 
 #if 0
-	if (galileo_id >= 0x10) {
+	if (dev->revision >= 0x10) {
 		/* New Galileo, assumes PCI stop line to VIA is connected. */
 		GT_WRITE(GT_PCI0_TOR_OFS, 0x4020);
-	} else if (galileo_id == 0x1 || galileo_id == 0x2)
+	} else if (dev->revision == 0x1 || dev->revision == 0x2)
 #endif
 	{
 		signed int timeo;
@@ -161,7 +157,7 @@
   [COBALT_PCICONF_ETH1]    = COBALT_ETH1_IRQ
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (cobalt_board_id < COBALT_BRD_ID_QUBE2)
 		return irq_tab_qube1[slot];
diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c
index 7abcfd1..a270589 100644
--- a/arch/mips/pci/fixup-emma2rh.c
+++ b/arch/mips/pci/fixup-emma2rh.c
@@ -89,7 +89,7 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
 			 emma2rh_pci_host_fixup);
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_map[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
index 1da696d..cd64d9f 100644
--- a/arch/mips/pci/fixup-excite.c
+++ b/arch/mips/pci/fixup-excite.c
@@ -21,7 +21,7 @@
 #include <linux/pci.h>
 #include <excite.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (pin == 0)
 		return -1;
diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c
index 3e66b0a..190fffd 100644
--- a/arch/mips/pci/fixup-ip32.c
+++ b/arch/mips/pci/fixup-ip32.c
@@ -39,7 +39,7 @@
  * irqs.  I suppose a device without a pin A will thank us for doing it
  * right if there exists such a broken piece of crap.
  */
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab_mace[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c
index 73d1850..e974394 100644
--- a/arch/mips/pci/fixup-jmr3927.c
+++ b/arch/mips/pci/fixup-jmr3927.c
@@ -33,7 +33,7 @@
 
 #include <asm/jmr3927/jmr3927.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char irq = pin;
 
diff --git a/arch/mips/pci/fixup-lm2e.c b/arch/mips/pci/fixup-lm2e.c
new file mode 100644
index 0000000..e18ae4f
--- /dev/null
+++ b/arch/mips/pci/fixup-lm2e.c
@@ -0,0 +1,242 @@
+/*
+ * fixup-lm2e.c
+ *
+ * Copyright (C) 2004 ICT CAS
+ * Author: Li xiaoyu, ICT CAS
+ *   lixy@ict.ac.cn
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mips-boards/bonito64.h>
+
+/* South bridge slot number is set by the pci probe process */
+static u8 sb_slot = 5;
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq = 0;
+
+	if (slot == sb_slot) {
+		switch (PCI_FUNC(dev->devfn)) {
+		case 2:
+			irq = 10;
+			break;
+		case 3:
+			irq = 11;
+			break;
+		case 5:
+			irq = 9;
+			break;
+		}
+	} else {
+		irq = BONITO_IRQ_BASE + 25 + pin;
+	}
+	return irq;
+
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
+
+static void __init loongson2e_nec_fixup(struct pci_dev *pdev)
+{
+	unsigned int val;
+
+	/* Configues port 1, 2, 3, 4 to be validate*/
+	pci_read_config_dword(pdev, 0xe0, &val);
+	pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x4);
+
+	/* System clock is 48-MHz Oscillator. */
+	pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+
+static void __init loongson2e_686b_func0_fixup(struct pci_dev *pdev)
+{
+	unsigned char c;
+
+	sb_slot = PCI_SLOT(pdev->devfn);
+
+	printk(KERN_INFO "via686b fix: ISA bridge\n");
+
+	/*  Enable I/O Recovery time */
+	pci_write_config_byte(pdev, 0x40, 0x08);
+
+	/*  Enable ISA refresh */
+	pci_write_config_byte(pdev, 0x41, 0x01);
+
+	/*  disable ISA line buffer */
+	pci_write_config_byte(pdev, 0x45, 0x00);
+
+	/*  Gate INTR, and flush line buffer */
+	pci_write_config_byte(pdev, 0x46, 0xe0);
+
+	/*  Disable PCI Delay Transaction, Enable EISA ports 4D0/4D1. */
+	/* pci_write_config_byte(pdev, 0x47, 0x20); */
+
+	/*
+	 *  enable PCI Delay Transaction, Enable EISA ports 4D0/4D1.
+	 *  enable time-out timer
+	 */
+	pci_write_config_byte(pdev, 0x47, 0xe6);
+
+	/*
+	 * enable level trigger on pci irqs: 9,10,11,13
+	 * important! without this PCI interrupts won't work
+	 */
+	outb(0x2e, 0x4d1);
+
+	/*  512 K PCI Decode */
+	pci_write_config_byte(pdev, 0x48, 0x01);
+
+	/*  Wait for PGNT before grant to ISA Master/DMA */
+	pci_write_config_byte(pdev, 0x4a, 0x84);
+
+	/*
+	 * Plug'n'Play
+	 *
+	 *  Parallel DRQ 3, Floppy DRQ 2 (default)
+	 */
+	pci_write_config_byte(pdev, 0x50, 0x0e);
+
+	/*
+	 * IRQ Routing for Floppy and Parallel port
+	 *
+	 *  IRQ 6 for floppy, IRQ 7 for parallel port
+	 */
+	pci_write_config_byte(pdev, 0x51, 0x76);
+
+	/* IRQ Routing for serial ports (take IRQ 3 and 4) */
+	pci_write_config_byte(pdev, 0x52, 0x34);
+
+	/*  All IRQ's level triggered. */
+	pci_write_config_byte(pdev, 0x54, 0x00);
+
+	/* route PIRQA-D irq */
+	pci_write_config_byte(pdev, 0x55, 0x90);	/* bit 7-4, PIRQA */
+	pci_write_config_byte(pdev, 0x56, 0xba);	/* bit 7-4, PIRQC; */
+							/* 3-0, PIRQB */
+	pci_write_config_byte(pdev, 0x57, 0xd0);	/* bit 7-4, PIRQD */
+
+	/* enable function 5/6, audio/modem */
+	pci_read_config_byte(pdev, 0x85, &c);
+	c &= ~(0x3 << 2);
+	pci_write_config_byte(pdev, 0x85, c);
+
+	printk(KERN_INFO"via686b fix: ISA bridge done\n");
+}
+
+static void __init loongson2e_686b_func1_fixup(struct pci_dev *pdev)
+{
+	printk(KERN_INFO"via686b fix: IDE\n");
+
+	/* Modify IDE controller setup */
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 48);
+	pci_write_config_byte(pdev, PCI_COMMAND,
+			      PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+			      PCI_COMMAND_MASTER);
+	pci_write_config_byte(pdev, 0x40, 0x0b);
+	/* legacy mode */
+	pci_write_config_byte(pdev, 0x42, 0x09);
+
+#if 1/* play safe, otherwise we may see notebook's usb keyboard lockup */
+	/* disable read prefetch/write post buffers */
+	pci_write_config_byte(pdev, 0x41, 0x02);
+
+	/* use 3/4 as fifo thresh hold  */
+	pci_write_config_byte(pdev, 0x43, 0x0a);
+	pci_write_config_byte(pdev, 0x44, 0x00);
+
+	pci_write_config_byte(pdev, 0x45, 0x00);
+#else
+	pci_write_config_byte(pdev, 0x41, 0xc2);
+	pci_write_config_byte(pdev, 0x43, 0x35);
+	pci_write_config_byte(pdev, 0x44, 0x1c);
+
+	pci_write_config_byte(pdev, 0x45, 0x10);
+#endif
+
+	printk(KERN_INFO"via686b fix: IDE done\n");
+}
+
+static void __init loongson2e_686b_func2_fixup(struct pci_dev *pdev)
+{
+	/* irq routing */
+	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 10);
+}
+
+static void __init loongson2e_686b_func3_fixup(struct pci_dev *pdev)
+{
+	/* irq routing */
+	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 11);
+}
+
+static void __init loongson2e_686b_func5_fixup(struct pci_dev *pdev)
+{
+	unsigned int val;
+	unsigned char c;
+
+	/* enable IO */
+	pci_write_config_byte(pdev, PCI_COMMAND,
+			      PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+			      PCI_COMMAND_MASTER);
+	pci_read_config_dword(pdev, 0x4, &val);
+	pci_write_config_dword(pdev, 0x4, val | 1);
+
+	/* route ac97 IRQ */
+	pci_write_config_byte(pdev, 0x3c, 9);
+
+	pci_read_config_byte(pdev, 0x8, &c);
+
+	/* link control: enable link & SGD PCM output */
+	pci_write_config_byte(pdev, 0x41, 0xcc);
+
+	/* disable game port, FM, midi, sb, enable write to reg2c-2f */
+	pci_write_config_byte(pdev, 0x42, 0x20);
+
+	/* we are using Avance logic codec */
+	pci_write_config_word(pdev, 0x2c, 0x1005);
+	pci_write_config_word(pdev, 0x2e, 0x4710);
+	pci_read_config_dword(pdev, 0x2c, &val);
+
+	pci_write_config_byte(pdev, 0x42, 0x0);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686,
+			 loongson2e_686b_func0_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+			 loongson2e_686b_func1_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2,
+			 loongson2e_686b_func2_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3,
+			 loongson2e_686b_func3_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5,
+			 loongson2e_686b_func5_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+			 loongson2e_nec_fixup);
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index bf2c41d..0f48498 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -36,7 +36,7 @@
 	{0,	PCID,	PCIA,	PCIB,	PCIC }	/* 21: PCI Slot 4 */
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int virq;
 	virq = irq_tab[slot][pin];
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
index 3c9ae41..5911596 100644
--- a/arch/mips/pci/fixup-mpc30x.c
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -34,7 +34,7 @@
  [29] = MQ200_IRQ,
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (slot == 30)
 		return internal_func_irqs[PCI_FUNC(dev->devfn)];
diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c
deleted file mode 100644
index d454948..0000000
--- a/arch/mips/pci/fixup-ocelot-c.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work for the Linux port to the Ocelot board, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/momentum/ocelot_g/pci.c
- *     Board-specific PCI routines for mv64340 controller.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int bus = dev->bus->number;
-
-	if (bus == 0 && slot == 1)
-		return 2;       /* PCI-X A */
-	if (bus == 1 && slot == 1)
-		return 12;      /* PCI-X B */
-	if (bus == 1 && slot == 2)
-		return 4;       /* PCI B */
-
-return 0;
-	panic("Whooops in pcibios_map_irq");
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/fixup-ocelot3.c b/arch/mips/pci/fixup-ocelot3.c
deleted file mode 100644
index ececc03..0000000
--- a/arch/mips/pci/fixup-ocelot3.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 Montavista Software Inc.
- * Author: Manish Lachwani (mlachwani@mvista.com)
- *
- * Looking at the schematics for the Ocelot-3 board, there are
- * two PCI busses and each bus has two PCI slots.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/mipsregs.h>
-
-/*
- * Do platform specific device initialization at
- * pci_enable_device() time
- */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int bus = dev->bus->number;
-
-	if (bus == 0 && slot == 1)
-		return 2;	/* PCI-X A */
-	if (bus == 0 && slot == 2)
-		return 3;	/* PCI-X B */
-	if (bus == 1 && slot == 1)
-		return 4;	/* PCI A */
-	if (bus == 1 && slot == 2)
-		return 5;	/* PCI B */
-
-return 0;
-	panic("Whooops in pcibios_map_irq");
-}
diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c
new file mode 100644
index 0000000..0026121
--- /dev/null
+++ b/arch/mips/pci/fixup-pmcmsp.c
@@ -0,0 +1,216 @@
+/*
+ * PMC-Sierra MSP board specific pci fixups.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2005-2007 PMC-Sierra, Inc
+ *
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+
+#include <msp_pci.h>
+#include <msp_cic_int.h>
+
+/* PCI interrupt pins */
+#define IRQ4	MSP_INT_EXT4
+#define IRQ5	MSP_INT_EXT5
+#define IRQ6	MSP_INT_EXT6
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+/* Garibaldi Board IRQ wiring to PCI slots */
+static char irq_tab[][5] __initdata = {
+	/* INTA    INTB    INTC    INTD */
+	{0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[2]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[3]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[4]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[5]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[6]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[7]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[8]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[9]): Unused */
+	{0,     0,      0,      0,      0 },    /*  0 (AD[10]): Unused */
+	{0,     0,      0,      0,      0 },    /*  1 (AD[11]): Unused */
+	{0,     0,      0,      0,      0 },    /*  2 (AD[12]): Unused */
+	{0,     0,      0,      0,      0 },    /*  3 (AD[13]): Unused */
+	{0,     0,      0,      0,      0 },    /*  4 (AD[14]): Unused */
+	{0,     0,      0,      0,      0 },    /*  5 (AD[15]): Unused */
+	{0,     0,      0,      0,      0 },    /*  6 (AD[16]): Unused */
+	{0,     0,      0,      0,      0 },    /*  7 (AD[17]): Unused */
+	{0,     0,      0,      0,      0 },    /*  8 (AD[18]): Unused */
+	{0,     0,      0,      0,      0 },    /*  9 (AD[19]): Unused */
+	{0,     0,      0,      0,      0 },    /* 10 (AD[20]): Unused */
+	{0,     0,      0,      0,      0 },    /* 11 (AD[21]): Unused */
+	{0,     0,      0,      0,      0 },    /* 12 (AD[22]): Unused */
+	{0,     0,      0,      0,      0 },    /* 13 (AD[23]): Unused */
+	{0,     0,      0,      0,      0 },    /* 14 (AD[24]): Unused */
+	{0,     0,      0,      0,      0 },    /* 15 (AD[25]): Unused */
+	{0,     0,      0,      0,      0 },    /* 16 (AD[26]): Unused */
+	{0,     0,      0,      0,      0 },    /* 17 (AD[27]): Unused */
+	{0,     IRQ4,   IRQ4,   0,      0 },    /* 18 (AD[28]): slot 0 */
+	{0,     0,      0,      0,      0 },    /* 19 (AD[29]): Unused */
+	{0,     IRQ5,   IRQ5,   0,      0 },    /* 20 (AD[30]): slot 1 */
+	{0,     IRQ6,   IRQ6,   0,      0 }     /* 21 (AD[31]): slot 2 */
+};
+
+#elif defined(CONFIG_PMC_MSP7120_EVAL)
+
+/* MSP7120 Eval Board IRQ wiring to PCI slots */
+static char irq_tab[][5] __initdata = {
+	/* INTA    INTB    INTC    INTD */
+	{0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[2]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[3]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[4]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[5]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[6]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[7]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[8]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[9]): Unused */
+	{0,     0,      0,      0,      0 },    /*  0 (AD[10]): Unused */
+	{0,     0,      0,      0,      0 },    /*  1 (AD[11]): Unused */
+	{0,     0,      0,      0,      0 },    /*  2 (AD[12]): Unused */
+	{0,     0,      0,      0,      0 },    /*  3 (AD[13]): Unused */
+	{0,     0,      0,      0,      0 },    /*  4 (AD[14]): Unused */
+	{0,     0,      0,      0,      0 },    /*  5 (AD[15]): Unused */
+	{0,     IRQ6,   IRQ6,   0,      0 },    /*  6 (AD[16]): slot 3 (mini) */
+	{0,     IRQ5,   IRQ5,   0,      0 },    /*  7 (AD[17]): slot 2 (mini) */
+	{0,     IRQ4,   IRQ4,   IRQ4,   IRQ4},  /*  8 (AD[18]): slot 0 (PCI) */
+	{0,     IRQ5,   IRQ5,   IRQ5,   IRQ5},  /*  9 (AD[19]): slot 1 (PCI) */
+	{0,     0,      0,      0,      0 },    /* 10 (AD[20]): Unused */
+	{0,     0,      0,      0,      0 },    /* 11 (AD[21]): Unused */
+	{0,     0,      0,      0,      0 },    /* 12 (AD[22]): Unused */
+	{0,     0,      0,      0,      0 },    /* 13 (AD[23]): Unused */
+	{0,     0,      0,      0,      0 },    /* 14 (AD[24]): Unused */
+	{0,     0,      0,      0,      0 },    /* 15 (AD[25]): Unused */
+	{0,     0,      0,      0,      0 },    /* 16 (AD[26]): Unused */
+	{0,     0,      0,      0,      0 },    /* 17 (AD[27]): Unused */
+	{0,     0,      0,      0,      0 },    /* 18 (AD[28]): Unused */
+	{0,     0,      0,      0,      0 },    /* 19 (AD[29]): Unused */
+	{0,     0,      0,      0,      0 },    /* 20 (AD[30]): Unused */
+	{0,     0,      0,      0,      0 }     /* 21 (AD[31]): Unused */
+};
+
+#else
+
+/* Unknown board -- don't assign any IRQs */
+static char irq_tab[][5] __initdata = {
+	/* INTA    INTB    INTC    INTD */
+	{0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[2]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[3]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[4]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[5]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[6]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[7]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[8]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[9]): Unused */
+	{0,     0,      0,      0,      0 },    /*  0 (AD[10]): Unused */
+	{0,     0,      0,      0,      0 },    /*  1 (AD[11]): Unused */
+	{0,     0,      0,      0,      0 },    /*  2 (AD[12]): Unused */
+	{0,     0,      0,      0,      0 },    /*  3 (AD[13]): Unused */
+	{0,     0,      0,      0,      0 },    /*  4 (AD[14]): Unused */
+	{0,     0,      0,      0,      0 },    /*  5 (AD[15]): Unused */
+	{0,     0,      0,      0,      0 },    /*  6 (AD[16]): Unused */
+	{0,     0,      0,      0,      0 },    /*  7 (AD[17]): Unused */
+	{0,     0,      0,      0,      0 },    /*  8 (AD[18]): Unused */
+	{0,     0,      0,      0,      0 },    /*  9 (AD[19]): Unused */
+	{0,     0,      0,      0,      0 },    /* 10 (AD[20]): Unused */
+	{0,     0,      0,      0,      0 },    /* 11 (AD[21]): Unused */
+	{0,     0,      0,      0,      0 },    /* 12 (AD[22]): Unused */
+	{0,     0,      0,      0,      0 },    /* 13 (AD[23]): Unused */
+	{0,     0,      0,      0,      0 },    /* 14 (AD[24]): Unused */
+	{0,     0,      0,      0,      0 },    /* 15 (AD[25]): Unused */
+	{0,     0,      0,      0,      0 },    /* 16 (AD[26]): Unused */
+	{0,     0,      0,      0,      0 },    /* 17 (AD[27]): Unused */
+	{0,     0,      0,      0,      0 },    /* 18 (AD[28]): Unused */
+	{0,     0,      0,      0,      0 },    /* 19 (AD[29]): Unused */
+	{0,     0,      0,      0,      0 },    /* 20 (AD[30]): Unused */
+	{0,     0,      0,      0,      0 }     /* 21 (AD[31]): Unused */
+};
+#endif
+
+/*****************************************************************************
+ *
+ *  FUNCTION: pcibios_plat_dev_init
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Perform platform specific device initialization at
+ *               pci_enable_device() time.
+ *               None are needed for the MSP7120 PCI Controller.
+ *
+ *  INPUTS:      dev     - structure describing the PCI device
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL
+ *
+ ****************************************************************************/
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: pcibios_map_irq
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Perform board supplied PCI IRQ mapping routine.
+ *
+ *  INPUTS:      dev     - unused
+ *               slot    - PCI slot. Identified by which bit of the AD[] bus
+ *                         drives the IDSEL line. AD[10] is 0, AD[31] is
+ *                         slot 21.
+ *               pin     - numbered using the scheme of the PCI_INTERRUPT_PIN
+ *                         field of the config header.
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     IRQ number
+ *
+ ****************************************************************************/
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+#if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL)
+	printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n");
+#endif
+	printk(KERN_WARNING "PCI: irq_tab returned %d for slot=%d pin=%d\n",
+		irq_tab[slot][pin], slot, pin);
+
+	return irq_tab[slot][pin];
+}
+
+#endif	/* CONFIG_PCI */
diff --git a/arch/mips/pci/fixup-pnx8550.c b/arch/mips/pci/fixup-pnx8550.c
index 50546da..96857ac 100644
--- a/arch/mips/pci/fixup-pnx8550.c
+++ b/arch/mips/pci/fixup-pnx8550.c
@@ -45,7 +45,7 @@
 	/* nothing to do here */
 }
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return pnx8550_irq_tab[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c
index ceeb186..3cdbecb 100644
--- a/arch/mips/pci/fixup-rbtx4927.c
+++ b/arch/mips/pci/fixup-rbtx4927.c
@@ -119,7 +119,7 @@
 	return irq;
 }
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char irq;
 
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index 36e5fb1..a45bedd 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -120,7 +120,7 @@
 	return (csmsr & 0xa0) == 0x20;
 }
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	switch (sni_brd_type) {
 	case SNI_BRD_PCI_TOWER:
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index 734f2b7..720a2b7 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -23,7 +23,7 @@
 
 #include <asm/vr41xx/tb0219.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq = -1;
 
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
index c9e7cb4..e3eedf4 100644
--- a/arch/mips/pci/fixup-tb0226.c
+++ b/arch/mips/pci/fixup-tb0226.c
@@ -23,7 +23,7 @@
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/tb0226.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq = -1;
 
diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c
index fbe6bcb..267ab3d 100644
--- a/arch/mips/pci/fixup-tb0287.c
+++ b/arch/mips/pci/fixup-tb0287.c
@@ -22,7 +22,7 @@
 
 #include <asm/vr41xx/tb0287.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char bus;
 	int irq = -1;
diff --git a/arch/mips/pci/fixup-tx4938.c b/arch/mips/pci/fixup-tx4938.c
index f455520..2485f47 100644
--- a/arch/mips/pci/fixup-tx4938.c
+++ b/arch/mips/pci/fixup-tx4938.c
@@ -69,7 +69,7 @@
 	return irq;
 }
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char irq = 0;
 
diff --git a/arch/mips/pci/fixup-vr4133.c b/arch/mips/pci/fixup-vr4133.c
index a8d9d22..de5e5f6 100644
--- a/arch/mips/pci/fixup-vr4133.c
+++ b/arch/mips/pci/fixup-vr4133.c
@@ -169,7 +169,7 @@
 }
 #endif
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	extern int pci_probe_only;
 	pci_probe_only = 1;
diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c
index 3357c13..3d27754 100644
--- a/arch/mips/pci/fixup-wrppmc.c
+++ b/arch/mips/pci/fixup-wrppmc.c
@@ -25,7 +25,7 @@
 	[6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0},
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return pci_irq_tab[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c
index 81d77a5..fdafb13 100644
--- a/arch/mips/pci/fixup-yosemite.c
+++ b/arch/mips/pci/fixup-yosemite.c
@@ -26,7 +26,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (pin == 0)
 		return -1;
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
index dc35270..f742c51 100644
--- a/arch/mips/pci/ops-bonito64.c
+++ b/arch/mips/pci/ops-bonito64.c
@@ -29,83 +29,60 @@
 #define PCI_ACCESS_READ  0
 #define PCI_ACCESS_WRITE 1
 
-/*
- *  PCI configuration cycle AD bus definition
- */
-/* Type 0 */
-#define PCI_CFG_TYPE0_REG_SHF           0
-#define PCI_CFG_TYPE0_FUNC_SHF          8
+#ifdef CONFIG_LEMOTE_FULONG
+#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(BONITO_PCICFG_BASE | (offset))
+#define ID_SEL_BEGIN 11
+#else
+#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset))
+#define ID_SEL_BEGIN 10
+#endif
+#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
 
-/* Type 1 */
-#define PCI_CFG_TYPE1_REG_SHF           0
-#define PCI_CFG_TYPE1_FUNC_SHF          8
-#define PCI_CFG_TYPE1_DEV_SHF           11
-#define PCI_CFG_TYPE1_BUS_SHF           16
 
 static int bonito64_pcibios_config_access(unsigned char access_type,
 				      struct pci_bus *bus,
 				      unsigned int devfn, int where,
 				      u32 * data)
 {
-	unsigned char busnum = bus->number;
+	u32 busnum = bus->number;
+	u32 addr, type;
 	u32 dummy;
-	u64 pci_addr;
-
-	/* Algorithmics Bonito64 system controller. */
-
-	if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) {
-		/* We number bus 0 devices from 0..21 */
-		return -1;
-	}
-
-	/* Clear cause register bits */
-	BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
-			  BONITO_PCICMD_MTABORT_CLR);
-
-	/*
-	 * Setup pattern to be used as PCI "address" for
-	 * Type 0 cycle
-	 */
-	if (busnum == 0) {
-		/* IDSEL */
-		pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10);
-	} else {
-		/* Bus number */
-		pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF;
-
-		/* Device number */
-		pci_addr |=
-		    PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF;
-	}
-
-	/* Function (same for Type 0/1) */
-	pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF;
-
-	/* Register number (same for Type 0/1) */
-	pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
+	void *addrp;
+	int device = PCI_SLOT(devfn);
+	int function = PCI_FUNC(devfn);
+	int reg = where & ~3;
 
 	if (busnum == 0) {
-		/* Type 0 */
-		BONITO_PCIMAP_CFG = pci_addr >> 16;
+		/* Type 0 configuration for onboard PCI bus */
+		if (device > MAX_DEV_NUM)
+			return -1;
+
+		addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
+		type = 0;
 	} else {
-		/* Type 1 */
-		BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
+		/* Type 1 configuration for offboard PCI bus */
+		addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+		type = 0x10000;
 	}
 
-	pci_addr &= 0xffff;
+	/* Clear aborts */
+	BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR;
+
+	BONITO_PCIMAP_CFG = (addr >> 16) | type;
 
 	/* Flush Bonito register block */
 	dummy = BONITO_PCIMAP_CFG;
-	iob();		/* sync */
+	mmiowb();
 
-	/* Perform access */
+	addrp = CFG_SPACE_REG(addr & 0xffff);
 	if (access_type == PCI_ACCESS_WRITE) {
-		*(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data;
-
+		writel(cpu_to_le32(*data), addrp);
+#ifndef CONFIG_LEMOTE_FULONG
 		/* Wait till done */
 		while (BONITO_PCIMSTAT & 0xF);
+#endif
 	} else {
-		*(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr);
+		*data = le32_to_cpu(readl(addrp));
 	}
 
 	/* Detect Master/Target abort */
@@ -121,6 +98,7 @@
 	}
 
 	return 0;
+
 }
 
 
diff --git a/arch/mips/pci/ops-marvell.c b/arch/mips/pci/ops-marvell.c
deleted file mode 100644
index 1ac5c59..0000000
--- a/arch/mips/pci/ops-marvell.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/marvell.h>
-
-static int mv_read_config(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 * val)
-{
-	struct mv_pci_controller *mvbc = bus->sysdata;
-	unsigned long address_reg, data_reg;
-	u32 address;
-
-	address_reg = mvbc->config_addr;
-	data_reg = mvbc->config_vreg;
-
-	/* Accessing device 31 crashes those Marvells.  Since years.
-	   Will they ever make sane controllers ... */
-	if (PCI_SLOT(devfn) == 31)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	address = (bus->number << 16) | (devfn << 8) |
-	          (where & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	switch (size) {
-	case 1:
-		*val = MV_READ_8(data_reg + (where & 0x3));
-		break;
-
-	case 2:
-		*val = MV_READ_16(data_reg + (where & 0x3));
-		break;
-
-	case 4:
-		*val = MV_READ(data_reg);
-		break;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int mv_write_config(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 val)
-{
-	struct mv_pci_controller *mvbc = bus->sysdata;
-	unsigned long address_reg, data_reg;
-	u32 address;
-
-	address_reg = mvbc->config_addr;
-	data_reg = mvbc->config_vreg;
-
-	/* Accessing device 31 crashes those Marvells.  Since years.
-	   Will they ever make sane controllers ... */
-	if (PCI_SLOT(devfn) == 31)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	address = (bus->number << 16) | (devfn << 8) |
-	          (where & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	switch (size) {
-	case 1:
-		MV_WRITE_8(data_reg + (where & 0x3), val);
-		break;
-
-	case 2:
-		MV_WRITE_16(data_reg + (where & 0x3), val);
-		break;
-
-	case 4:
-		MV_WRITE(data_reg, val);
-		break;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops mv_pci_ops = {
-	.read	= mv_read_config,
-	.write	= mv_write_config
-};
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
deleted file mode 100644
index a8d38dc..0000000
--- a/arch/mips/pci/ops-nile4.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/bootinfo.h>
-
-#include <asm/lasat/lasat.h>
-#include <asm/gt64120.h>
-#include <asm/nile4.h>
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-#define LO(reg) (reg / 4)
-#define HI(reg) (reg / 4 + 1)
-
-volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
-
-static DEFINE_SPINLOCK(nile4_pci_lock);
-
-static int nile4_pcibios_config_access(unsigned char access_type,
-	struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
-{
-	unsigned char busnum = bus->number;
-	u32 adr, mask, err;
-
-	if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
-		/* The addressing scheme chosen leaves room for just
-		 * 8 devices on the first busnum (besides the PCI
-		 * controller itself) */
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
-		/* Access controller registers directly */
-		if (access_type == PCI_ACCESS_WRITE) {
-			vrc_pciregs[(0x200 + where) >> 2] = *val;
-		} else {
-			*val = vrc_pciregs[(0x200 + where) >> 2];
-		}
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	/* Temporarily map PCI Window 1 to config space */
-	mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
-	vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0);
-
-	/* Clear PCI Error register. This also clears the Error Type
-	 * bits in the Control register */
-	vrc_pciregs[LO(NILE4_PCIERR)] = 0;
-	vrc_pciregs[HI(NILE4_PCIERR)] = 0;
-
-	/* Setup address */
-	if (busnum == 0)
-		adr =
-		    KSEG1ADDR(PCI_WINDOW1) +
-		    ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
-		     | (where & ~3));
-	else
-		adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) |
-		      (where & ~3);
-
-	if (access_type == PCI_ACCESS_WRITE)
-		*(u32 *) adr = *val;
-	else
-		*val = *(u32 *) adr;
-
-	/* Check for master or target abort */
-	err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
-
-	/* Restore PCI Window 1 */
-	vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
-
-	if (err)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 * val)
-{
-	unsigned long flags;
-	u32 data = 0;
-	int err;
-
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	spin_lock_irqsave(&nile4_pci_lock, flags);
-	err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
-					&data);
-	spin_unlock_irqrestore(&nile4_pci_lock, flags);
-
-	if (err)
-		return err;
-
-	if (size == 1)
-		*val = (data >> ((where & 3) << 3)) & 0xff;
-	else if (size == 2)
-		*val = (data >> ((where & 3) << 3)) & 0xffff;
-	else
-		*val = data;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 val)
-{
-	unsigned long flags;
-	u32 data = 0;
-	int err;
-
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	spin_lock_irqsave(&nile4_pci_lock, flags);
-	err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
-	                                  &data);
-	spin_unlock_irqrestore(&nile4_pci_lock, flags);
-
-	if (err)
-		return err;
-
-	if (size == 1)
-		data = (data & ~(0xff << ((where & 3) << 3))) |
-		    (val << ((where & 3) << 3));
-	else if (size == 2)
-		data = (data & ~(0xffff << ((where & 3) << 3))) |
-		    (val << ((where & 3) << 3));
-	else
-		data = val;
-
-	if (nile4_pcibios_config_access
-	    (PCI_ACCESS_WRITE, bus, devfn, where, &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops nile4_pci_ops = {
-	.read = nile4_pcibios_read,
-	.write = nile4_pcibios_write,
-};
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c
new file mode 100644
index 0000000..09fa007
--- /dev/null
+++ b/arch/mips/pci/ops-pmcmsp.c
@@ -0,0 +1,994 @@
+/*
+ * PMC-Sierra MSP board specific pci_ops
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2005-2007 PMC-Sierra, Inc
+ *
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#define PCI_COUNTERS	1
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+#include <asm/mipsmtregs.h>
+#endif
+
+#include <msp_prom.h>
+#include <msp_cic_int.h>
+#include <msp_pci.h>
+#include <msp_regs.h>
+#include <msp_regops.h>
+
+#define PCI_ACCESS_READ		0
+#define PCI_ACCESS_WRITE	1
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+static char proc_init;
+extern struct proc_dir_entry *proc_bus_pci_dir;
+unsigned int pci_int_count[32];
+
+static void pci_proc_init(void);
+
+/*****************************************************************************
+ *
+ *  FUNCTION: read_msp_pci_counts
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Prints the count of how many times each PCI
+ *               interrupt has asserted. Can be invoked by the
+ *               /proc filesystem.
+ *
+ *  INPUTS:      page    - part of STDOUT calculation
+ *               off     - part of STDOUT calculation
+ *               count   - part of STDOUT calculation
+ *               data    - unused
+ *
+ *  OUTPUTS:     start   - new start location
+ *               eof     - end of file pointer
+ *
+ *  RETURNS:     len     - STDOUT length
+ *
+ ****************************************************************************/
+static int read_msp_pci_counts(char *page, char **start, off_t off,
+				int count, int *eof, void *data)
+{
+	int i;
+	int len = 0;
+	unsigned int intcount, total = 0;
+
+	for (i = 0; i < 32; ++i) {
+		intcount = pci_int_count[i];
+		if (intcount != 0) {
+			len += sprintf(page + len, "[%d] = %u\n", i, intcount);
+			total += intcount;
+		}
+	}
+
+	len += sprintf(page + len, "total = %u\n", total);
+	if (len <= off+count)
+		*eof = 1;
+
+	*start = page + off;
+	len -= off;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: gen_pci_cfg_wr
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Generates a configuration write cycle for debug purposes.
+ *               The IDSEL line asserted and location and data written are
+ *               immaterial. Just want to be able to prove that a
+ *               configuration write can be correctly generated on the
+ *               PCI bus.  Intent is that this function by invocable from
+ *               the /proc filesystem.
+ *
+ *  INPUTS:      page    - part of STDOUT calculation
+ *               off     - part of STDOUT calculation
+ *               count   - part of STDOUT calculation
+ *               data    - unused
+ *
+ *  OUTPUTS:     start   - new start location
+ *               eof     - end of file pointer
+ *
+ *  RETURNS:     len     - STDOUT length
+ *
+ ****************************************************************************/
+static int gen_pci_cfg_wr(char *page, char **start, off_t off,
+				int count, int *eof, void *data)
+{
+	unsigned char where = 0; /* Write to static Device/Vendor ID */
+	unsigned char bus_num = 0; /* Bus 0 */
+	unsigned char dev_fn = 0xF; /* Arbitrary device number */
+	u32 wr_data = 0xFF00AA00; /* Arbitrary data */
+	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+	int len = 0;
+	unsigned long value;
+	int intr;
+
+	len += sprintf(page + len, "PMC MSP PCI: Beginning\n");
+
+	if (proc_init == 0) {
+		pci_proc_init();
+		proc_init = ~0;
+	}
+
+	len += sprintf(page + len, "PMC MSP PCI: Before Cfg Wr\n");
+
+	/*
+	 * Generate PCI Configuration Write Cycle
+	 */
+
+	/* Clear cause register bits */
+	preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+	/* Setup address that is to appear on PCI bus */
+	preg->config_addr = BPCI_CFGADDR_ENABLE |
+		(bus_num << BPCI_CFGADDR_BUSNUM_SHF) |
+		(dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |
+		(where & 0xFC);
+
+	value = cpu_to_le32(wr_data);
+
+	/* Launch the PCI configuration write cycle */
+	*PCI_CONFIG_SPACE_REG = value;
+
+	/*
+	 * Check if the PCI configuration cycle (rd or wr) succeeded, by
+	 * checking the status bits for errors like master or target abort.
+	 */
+	intr = preg->if_status;
+
+	len += sprintf(page + len, "PMC MSP PCI: After Cfg Wr\n");
+
+	/* Handle STDOUT calculations */
+	if (len <= off+count)
+		*eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: pci_proc_init
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Create entries in the /proc filesystem for debug access.
+ *
+ *  INPUTS:      none
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     none
+ *
+ ****************************************************************************/
+static void pci_proc_init(void)
+{
+	create_proc_read_entry("pmc_msp_pci_rd_cnt", 0, NULL,
+				read_msp_pci_counts, NULL);
+	create_proc_read_entry("pmc_msp_pci_cfg_wr", 0, NULL,
+				gen_pci_cfg_wr, NULL);
+}
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+spinlock_t bpci_lock = SPIN_LOCK_UNLOCKED;
+
+/*****************************************************************************
+ *
+ *  STRUCT: pci_io_resource
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Defines the address range that pciauto() will use to
+ *               assign to the I/O BARs of PCI devices.
+ *
+ *               Use the start and end addresses of the MSP7120 PCI Host
+ *               Controller I/O space, in the form that they appear on the
+ *               PCI bus AFTER MSP7120 has performed address translation.
+ *
+ *               For I/O accesses, MSP7120 ignores OATRAN and maps I/O
+ *               accesses into the bottom 0xFFF region of address space,
+ *               so that is the range to put into the pci_io_resource
+ *               struct.
+ *
+ *               In MSP4200, the start address was 0x04 instead of the
+ * 		 expected 0x00. Will just assume there was a good reason
+ * 		 for this!
+ *
+ *  NOTES:       Linux, by default, will assign I/O space to the lowest
+ *               region of address space. Since MSP7120 and Linux,
+ *               by default, have no offset in between how they map, the
+ *               io_offset element of pci_controller struct should be set
+ *               to zero.
+ *  ELEMENTS:
+ *    name       - String used for a meaningful name.
+ *
+ *    start      - Start address of MSP7120's I/O space, as MSP7120 presents
+ *                 the address on the PCI bus.
+ *
+ *    end        - End address of MSP7120's I/O space, as MSP7120 presents
+ *                 the address on the PCI bus.
+ *
+ *    flags      - Attributes indicating the type of resource. In this case,
+ *                 indicate I/O space.
+ *
+ ****************************************************************************/
+static struct resource pci_io_resource = {
+	.name	= "pci IO space",
+	.start	= 0x04,
+	.end	= 0x0FFF,
+	.flags	= IORESOURCE_IO	/* I/O space */
+};
+
+/*****************************************************************************
+ *
+ *  STRUCT: pci_mem_resource
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Defines the address range that pciauto() will use to
+ *               assign to the memory BARs of PCI devices.
+ *
+ *               The .start and .end values are dependent upon how address
+ *               translation is performed by the OATRAN regiser.
+ *
+ *               The values to use for .start and .end are the values
+ *               in the form they appear on the PCI bus AFTER MSP7120 has
+ *               performed OATRAN address translation.
+ *
+ *  ELEMENTS:
+ *    name       - String used for a meaningful name.
+ *
+ *    start      - Start address of MSP7120's memory space, as MSP7120 presents
+ *                 the address on the PCI bus.
+ *
+ *    end        - End address of MSP7120's memory space, as MSP7120 presents
+ *                 the address on the PCI bus.
+ *
+ *    flags      - Attributes indicating the type of resource. In this case,
+ *                 indicate memory space.
+ *
+ ****************************************************************************/
+static struct resource pci_mem_resource = {
+	.name	= "pci memory space",
+	.start	= MSP_PCI_SPACE_BASE,
+	.end	= MSP_PCI_SPACE_END,
+	.flags	= IORESOURCE_MEM	 /* memory space */
+};
+
+/*****************************************************************************
+ *
+ *  FUNCTION: bpci_interrupt
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: PCI status interrupt handler. Updates the count of how
+ *               many times each status bit has been set, then clears
+ *               the status bits. If the appropriate macros are defined,
+ *               these counts can be viewed via the /proc filesystem.
+ *
+ *  INPUTS:      irq     - unused
+ *               dev_id  - unused
+ *               pt_regs - unused
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
+ *
+ ****************************************************************************/
+static int bpci_interrupt(int irq, void *dev_id)
+{
+	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+	unsigned int stat = preg->if_status;
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+	int i;
+	for (i = 0; i < 32; ++i) {
+		if ((1 << i) & stat)
+			++pci_int_count[i];
+	}
+#endif /* PROC_FS && PCI_COUNTERS */
+
+	/* printk("PCI ISR: Status=%08X\n", stat); */
+
+	/* write to clear all asserted interrupts */
+	preg->if_status = stat;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_config_access
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Performs a PCI configuration access (rd or wr), then
+ *               checks that the access succeeded by querying MSP7120's
+ *               PCI status bits.
+ *
+ *  INPUTS:
+ *               access_type  - kind of PCI configuration cycle to perform
+ *                              (read or write). Legal values are
+ *                              PCI_ACCESS_WRITE and PCI_ACCESS_READ.
+ *
+ *               bus          - pointer to the bus number of the device to
+ *                              be targetted for the configuration cycle.
+ *                              The only element of the pci_bus structure
+ *                              used is bus->number. This argument determines
+ *                              if the configuration access will be Type 0 or
+ *                              Type 1. Since MSP7120 assumes itself to be the
+ *                              PCI Host, any non-zero bus->number generates
+ *                              a Type 1 access.
+ *
+ *               devfn        - this is an 8-bit field. The lower three bits
+ *                              specify the function number of the device to
+ *                              be targetted for the configuration cycle, with
+ *                              all three-bit combinations being legal. The
+ *                              upper five bits specify the device number,
+ *                              with legal values being 10 to 31.
+ *
+ *               where        - address within the Configuration Header
+ *                              space to access.
+ *
+ *               data         - for write accesses, contains the data to
+ *                              write.
+ *
+ *  OUTPUTS:
+ *               data         - for read accesses, contains the value read.
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
+ *               -1                  - access failure
+ *
+ ****************************************************************************/
+int msp_pcibios_config_access(unsigned char access_type,
+				struct pci_bus *bus,
+				unsigned int devfn,
+				unsigned char where,
+				u32 *data)
+{
+	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+	unsigned char bus_num = bus->number;
+	unsigned char dev_fn = (unsigned char)devfn;
+	unsigned long flags;
+	unsigned long intr;
+	unsigned long value;
+	static char pciirqflag;
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+	unsigned int	vpe_status;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+	if (proc_init == 0) {
+		pci_proc_init();
+		proc_init = ~0;
+	}
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+	/*
+	 * Just the first time this function invokes, allocate
+	 * an interrupt line for PCI host status interrupts. The
+	 * allocation assigns an interrupt handler to the interrupt.
+	 */
+	if (pciirqflag == 0) {
+		request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */
+				bpci_interrupt,
+				SA_SHIRQ | SA_INTERRUPT,
+				"PMC MSP PCI Host",
+				preg);
+		pciirqflag = ~0;
+	}
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+	local_irq_save(flags);
+	vpe_status = dvpe();
+#else
+	spin_lock_irqsave(&bpci_lock, flags);
+#endif
+
+	/*
+	 * Clear PCI cause register bits.
+	 *
+	 * In Polo, the PCI Host had a dedicated DMA called the
+	 * Block Copy (not to be confused with the general purpose Block
+	 * Copy Engine block). There appear to have been special interrupts
+	 * for this Block Copy, called Block Copy 0 Fault (BC0F) and
+	 * Block Copy 1 Fault (BC1F). MSP4200 and MSP7120 don't have this
+	 * dedicated Block Copy block, so these two interrupts are now
+	 * marked reserved. In case the  Block Copy is resurrected in a
+	 * future design, maintain the code that treats these two interrupts
+	 * specially.
+	 *
+	 * Write to clear all interrupts in the PCI status register, aside
+	 * from BC0F and BC1F.
+	 */
+	preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+	/* Setup address that is to appear on PCI bus */
+	preg->config_addr = BPCI_CFGADDR_ENABLE	|
+		(bus_num << BPCI_CFGADDR_BUSNUM_SHF) |
+		(dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |
+		(where & 0xFC);
+
+	/* IF access is a PCI configuration write */
+	if (access_type == PCI_ACCESS_WRITE) {
+		value = cpu_to_le32(*data);
+		*PCI_CONFIG_SPACE_REG = value;
+	} else {
+		/* ELSE access is a PCI configuration read */
+		value = le32_to_cpu(*PCI_CONFIG_SPACE_REG);
+		*data = value;
+	}
+
+	/*
+	 * Check if the PCI configuration cycle (rd or wr) succeeded, by
+	 * checking the status bits for errors like master or target abort.
+	 */
+	intr = preg->if_status;
+
+	/* Clear config access */
+	preg->config_addr = 0;
+
+	/* IF error occurred */
+	if (intr & ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F)) {
+		/* Clear status bits */
+		preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+		evpe(vpe_status);
+		local_irq_restore(flags);
+#else
+		spin_unlock_irqrestore(&bpci_lock, flags);
+#endif
+
+		return -1;
+	}
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+	evpe(vpe_status);
+	local_irq_restore(flags);
+#else
+	spin_unlock_irqrestore(&bpci_lock, flags);
+#endif
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_read_config_byte
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Read a byte from PCI configuration address spac
+ *               Since the hardware can't address 8 bit chunks
+ *               directly, read a 32-bit chunk, then mask off extraneous
+ *               bits.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the read is destined for.
+ *               devfn  - device/function combination that the read is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *
+ *  OUTPUTS      val    - read data
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
+ *               -1                  - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_byte(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u32 *val)
+{
+	u32 data = 0;
+
+	/*
+	 * If the config access did not complete normally (e.g., underwent
+	 * master abort) do the PCI compliant thing, which is to supply an
+	 * all ones value.
+	 */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data)) {
+		*val = 0xFFFFFFFF;
+		return -1;
+	}
+
+	*val = (data >> ((where & 3) << 3)) & 0x0ff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_read_config_word
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Read a word (16 bits) from PCI configuration address space.
+ *               Since the hardware can't address 16 bit chunks
+ *               directly, read a 32-bit chunk, then mask off extraneous
+ *               bits.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the read is destined for.
+ *               devfn  - device/function combination that the read is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *
+ *  OUTPUTS      val    - read data
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL           - success
+ *               PCIBIOS_BAD_REGISTER_NUMBER  - bad register address
+ *               -1                           - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_word(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u32 *val)
+{
+	u32 data = 0;
+
+	/* if (where & 1) */	/* Commented out non-compliant code.
+				 * Should allow word access to configuration
+				 * registers, with only exception being when
+				 * the word access would wrap around into
+				 * the next dword.
+				 */
+	if ((where & 3) == 3) {
+		*val = 0xFFFFFFFF;
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	/*
+	 * If the config access did not complete normally (e.g., underwent
+	 * master abort) do the PCI compliant thing, which is to supply an
+	 * all ones value.
+	 */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data)) {
+		*val = 0xFFFFFFFF;
+		return -1;
+	}
+
+	*val = (data >> ((where & 3) << 3)) & 0x0ffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_read_config_dword
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Read a double word (32 bits) from PCI configuration
+ *               address space.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the read is destined for.
+ *               devfn  - device/function combination that the read is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *
+ *  OUTPUTS      val    - read data
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL           - success
+ *               PCIBIOS_BAD_REGISTER_NUMBER  - bad register address
+ *               -1                           - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_dword(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u32 *val)
+{
+	u32 data = 0;
+
+	/* Address must be dword aligned. */
+	if (where & 3) {
+		*val = 0xFFFFFFFF;
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	/*
+	 * If the config access did not complete normally (e.g., underwent
+	 * master abort) do the PCI compliant thing, which is to supply an
+	 * all ones value.
+	 */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data)) {
+		*val = 0xFFFFFFFF;
+		return -1;
+	}
+
+	*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_write_config_byte
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Write a byte to PCI configuration address space.
+ *               Since the hardware can't address 8 bit chunks
+ *               directly, a read-modify-write is performed.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               val    - value to write
+ *
+ *  OUTPUTS      none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
+ *               -1                  - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_byte(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u8 val)
+{
+	u32 data = 0;
+
+	/* read config space */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data))
+		return -1;
+
+	/* modify the byte within the dword */
+	data = (data & ~(0xff << ((where & 3) << 3))) |
+			(val << ((where & 3) << 3));
+
+	/* write back the full dword */
+	if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+					where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_write_config_word
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Write a word (16-bits) to PCI configuration address space.
+ *               Since the hardware can't address 16 bit chunks
+ *               directly, a read-modify-write is performed.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               val    - value to write
+ *
+ *  OUTPUTS      none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL           - success
+ *               PCIBIOS_BAD_REGISTER_NUMBER  - bad register address
+ *               -1                           - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_word(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u16 val)
+{
+	u32 data = 0;
+
+	/* Fixed non-compliance: if (where & 1) */
+	if ((where & 3) == 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	/* read config space */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data))
+		return -1;
+
+	/* modify the word within the dword */
+	data = (data & ~(0xffff << ((where & 3) << 3))) |
+			(val << ((where & 3) << 3));
+
+	/* write back the full dword */
+	if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+					where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_write_config_dword
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Write a double word (32-bits) to PCI configuration address
+ *               space.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               val    - value to write
+ *
+ *  OUTPUTS      none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL           - success
+ *               PCIBIOS_BAD_REGISTER_NUMBER  - bad register address
+ *               -1                           - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_dword(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u32 val)
+{
+	/* check that address is dword aligned */
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	/* perform write */
+	if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+					where, &val))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_read_config
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Interface the PCI configuration read request with
+ *               the appropriate function, based on how many bytes
+ *               the read request is.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               size   - in units of bytes, should be 1, 2, or 4.
+ *
+ *  OUTPUTS      val    - value read, with any extraneous bytes masked
+ *                        to zero.
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL   - success
+ *               -1                   - failure
+ *
+ ****************************************************************************/
+int
+msp_pcibios_read_config(struct pci_bus *bus,
+			unsigned int	devfn,
+			int where,
+			int size,
+			u32 *val)
+{
+	if (size == 1) {
+		if (msp_pcibios_read_config_byte(bus, devfn, where, val)) {
+			return -1;
+		}
+	} else if (size == 2) {
+		if (msp_pcibios_read_config_word(bus, devfn, where, val)) {
+			return -1;
+		}
+	} else if (size == 4) {
+		if (msp_pcibios_read_config_dword(bus, devfn, where, val)) {
+			return -1;
+		}
+	} else {
+		*val = 0xFFFFFFFF;
+		return -1;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_write_config
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Interface the PCI configuration write request with
+ *               the appropriate function, based on how many bytes
+ *               the read request is.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               size   - in units of bytes, should be 1, 2, or 4.
+ *               val    - value to write
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL   - success
+ *               -1                   - failure
+ *
+ ****************************************************************************/
+int
+msp_pcibios_write_config(struct pci_bus *bus,
+			unsigned int devfn,
+			int where,
+			int size,
+			u32 val)
+{
+	if (size == 1) {
+		if (msp_pcibios_write_config_byte(bus, devfn,
+						where, (u8)(0xFF & val))) {
+			return -1;
+		}
+	} else if (size == 2) {
+		if (msp_pcibios_write_config_word(bus, devfn,
+						where, (u16)(0xFFFF & val))) {
+			return -1;
+		}
+	} else if (size == 4) {
+		if (msp_pcibios_write_config_dword(bus, devfn, where, val)) {
+			return -1;
+		}
+	} else {
+		return -1;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  STRUCTURE: msp_pci_ops
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: structure to abstract the hardware specific PCI
+ *               configuration accesses.
+ *
+ *  ELEMENTS:
+ *    read      - function for Linux to generate PCI Configuration reads.
+ *    write     - function for Linux to generate PCI Configuration writes.
+ *
+ ****************************************************************************/
+struct pci_ops msp_pci_ops = {
+	.read = msp_pcibios_read_config,
+	.write = msp_pcibios_write_config
+};
+
+/*****************************************************************************
+ *
+ *  STRUCTURE: msp_pci_controller
+ *  _________________________________________________________________________
+ *
+ *  Describes the attributes of the MSP7120 PCI Host Controller
+ *
+ *  ELEMENTS:
+ *    pci_ops      - abstracts the hardware specific PCI configuration
+ *                   accesses.
+ *
+ *    mem_resource - address range pciauto() uses to assign to PCI device
+ *                   memory BARs.
+ *
+ *    mem_offset   - offset between how MSP7120 outbound PCI memory
+ *                   transaction addresses appear on the PCI bus and how Linux
+ *                   wants to configure memory BARs of the PCI devices.
+ *                   MSP7120 does nothing funky, so just set to zero.
+ *
+ *    io_resource  - address range pciauto() uses to assign to PCI device
+ *                   I/O BARs.
+ *
+ *    io_offset    - offset between how MSP7120 outbound PCI I/O
+ *                   transaction addresses appear on the PCI bus and how
+ *                   Linux defaults to configure I/O BARs of the PCI devices.
+ *                   MSP7120 maps outbound I/O accesses into the bottom
+ *                   bottom 4K of PCI address space (and ignores OATRAN).
+ *                   Since the Linux default is to configure I/O BARs to the
+ *                   bottom 4K, no special offset is needed. Just set to zero.
+ *
+ ****************************************************************************/
+static struct pci_controller msp_pci_controller = {
+	.pci_ops	= &msp_pci_ops,
+	.mem_resource	= &pci_mem_resource,
+	.mem_offset	= 0,
+	.io_resource	= &pci_io_resource,
+	.io_offset	= 0
+};
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pci_init
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Initialize the PCI Host Controller and register it with
+ *               Linux so Linux can seize control of the PCI bus.
+ *
+ ****************************************************************************/
+void __init msp_pci_init(void)
+{
+	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+	u32 id;
+
+	/* Extract Device ID */
+	id = read_reg32(PCI_JTAG_DEVID_REG, 0xFFFF) >> 12;
+
+	/* Check if JTAG ID identifies MSP7120 */
+	if (!MSP_HAS_PCI(id)) {
+		printk(KERN_WARNING "PCI: No PCI; id reads as %x\n", id);
+		goto no_pci;
+	}
+
+	/*
+	 * Enable flushing of the PCI-SDRAM queue upon a read
+	 * of the SDRAM's Memory Configuration Register.
+	 */
+	*(unsigned long *)QFLUSH_REG_1 = 3;
+
+	/* Configure PCI Host Controller. */
+	preg->if_status	= ~0;		/* Clear cause register bits */
+	preg->config_addr = 0;		/* Clear config access */
+	preg->oatran	= MSP_PCI_OATRAN; /* PCI outbound addr translation */
+	preg->if_mask	= 0xF8BF87C0;	/* Enable all PCI status interrupts */
+
+	/* configure so inb(), outb(), and family are functional */
+	set_io_port_base(MSP_PCI_IOSPACE_BASE);
+
+	/* Tell Linux the details of the MSP7120 PCI Host Controller */
+	register_pci_controller(&msp_pci_controller);
+
+	return;
+
+no_pci:
+	/* Disable PCI channel */
+	printk(KERN_WARNING "PCI: no host PCI bus detected\n");
+}
diff --git a/arch/mips/pci/ops-tx4938.c b/arch/mips/pci/ops-tx4938.c
index 4450070..a450c40 100644
--- a/arch/mips/pci/ops-tx4938.c
+++ b/arch/mips/pci/ops-tx4938.c
@@ -46,50 +46,63 @@
 	.flags	= IORESOURCE_MEM
 };
 
-static int mkaddr(int bus, int dev_fn, int where, int *flagsp)
+static int mkaddr(int bus, int dev_fn, int where,
+		  struct tx4938_pcic_reg *pcicptr)
 {
 	if (bus > 0) {
 		/* Type 1 configuration */
-		tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
 		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
 	} else {
 		if (dev_fn >= PCI_DEVFN(TX4938_PCIC_MAX_DEVNU, 0))
 			return -1;
 
 		/* Type 0 configuration */
-		tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
 		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
 	}
 	/* clear M_ABORT and Disable M_ABORT Int. */
-	tx4938_pcicptr->pcistatus =
-	    (tx4938_pcicptr->pcistatus & 0x0000ffff) |
+	pcicptr->pcistatus =
+	    (pcicptr->pcistatus & 0x0000ffff) |
 	    (PCI_STATUS_REC_MASTER_ABORT << 16);
-	tx4938_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
+	pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
 
 	return 0;
 }
 
-static int check_abort(int flags)
+static int check_abort(struct tx4938_pcic_reg *pcicptr)
 {
 	int code = PCIBIOS_SUCCESSFUL;
 	/* wait write cycle completion before checking error status */
-	while (tx4938_pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
+	while (pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
 				;
-	if (tx4938_pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
-		tx4938_pcicptr->pcistatus =
-		    (tx4938_pcicptr->
+	if (pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+		pcicptr->pcistatus =
+		    (pcicptr->
 		     pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
 						<< 16);
-		tx4938_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
+		pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
 		code = PCIBIOS_DEVICE_NOT_FOUND;
 	}
 	return code;
 }
 
+extern struct pci_controller tx4938_pci_controller[];
+extern struct tx4938_pcic_reg *get_tx4938_pcicptr(int ch);
+
+static struct tx4938_pcic_reg *pci_bus_to_pcicptr(struct pci_bus *bus)
+{
+	struct pci_controller *channel = bus->sysdata;
+	return get_tx4938_pcicptr(channel - &tx4938_pci_controller[0]);
+}
+
 static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
 					int where, int size, u32 * val)
 {
-	int flags, retval, dev, busno, func;
+	int retval, dev, busno, func;
+	struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
+	void __iomem *cfgdata =
+		(void __iomem *)(unsigned long)&pcicptr->g2pcfgdata;
 
 	dev = PCI_SLOT(devfn);
 	func = PCI_FUNC(devfn);
@@ -101,32 +114,32 @@
 		busno = 0;
 	}
 
-	if (mkaddr(busno, devfn, where, &flags))
+	if (mkaddr(busno, devfn, where, pcicptr))
 		return -1;
 
 	switch (size) {
 	case 1:
-		*val = *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
-			      ((where & 3) ^ 3));
+		cfgdata += (where & 3) ^ 3;
 #else
-			      (where & 3));
+		cfgdata += where & 3;
 #endif
+		*val = __raw_readb(cfgdata);
 		break;
 	case 2:
-		*val = *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
-				((where & 3) ^ 2));
+		cfgdata += (where & 2) ^ 2;
 #else
-				(where & 3));
+		cfgdata += where & 2;
 #endif
+		*val = __raw_readw(cfgdata);
 		break;
 	case 4:
-		*val = tx4938_pcicptr->g2pcfgdata;
+		*val = __raw_readl(cfgdata);
 		break;
 	}
 
-	retval = check_abort(flags);
+	retval = check_abort(pcicptr);
 	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
 		*val = 0xffffffff;
 
@@ -136,7 +149,10 @@
 static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 						int size, u32 val)
 {
-	int flags, dev, busno, func;
+	int dev, busno, func;
+	struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
+	void __iomem *cfgdata =
+		(void __iomem *)(unsigned long)&pcicptr->g2pcfgdata;
 
 	busno = bus->number;
 	dev = PCI_SLOT(devfn);
@@ -149,32 +165,32 @@
 		busno = 0;
 	}
 
-	if (mkaddr(busno, devfn, where, &flags))
+	if (mkaddr(busno, devfn, where, pcicptr))
 		return -1;
 
 	switch (size) {
 	case 1:
-		*(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
-			  ((where & 3) ^ 3)) = val;
+		cfgdata += (where & 3) ^ 3;
 #else
-			  (where & 3)) = val;
+		cfgdata += where & 3;
 #endif
+		__raw_writeb(val, cfgdata);
 		break;
 	case 2:
-		*(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
-			((where & 0x3) ^ 0x2)) = val;
+		cfgdata += (where & 2) ^ 2;
 #else
-			(where & 3)) = val;
+		cfgdata += where & 2;
 #endif
+		__raw_writew(val, cfgdata);
 		break;
 	case 4:
-		tx4938_pcicptr->g2pcfgdata = val;
+		__raw_writel(val, cfgdata);
 		break;
 	}
 
-	return check_abort(flags);
+	return check_abort(pcicptr);
 }
 
 struct pci_ops tx4938_pci_ops = {
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c
index d7b9e13..2b4e30c 100644
--- a/arch/mips/pci/pci-bcm1480.c
+++ b/arch/mips/pci/pci-bcm1480.c
@@ -74,8 +74,9 @@
 	*(u32 *)(cfg_space + (addr & ~3)) = data;
 }
 
-int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
+	This is b0rked.
 	return dev->irq;
 }
 
diff --git a/arch/mips/pci/pci-dac.c b/arch/mips/pci/pci-dac.c
deleted file mode 100644
index 0f0ea1b..0000000
--- a/arch/mips/pci/pci-dac.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001, 06  Ralf Baechle <ralf@linux-mips.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-#include <dma-coherence.h>
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-	struct page *page, unsigned long offset, int direction)
-{
-	struct device *dev = &pdev->dev;
-
-	BUG_ON(direction == DMA_NONE);
-
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = (unsigned long) page_address(page) + offset;
-		dma_cache_wback_inv(addr, PAGE_SIZE);
-	}
-
-	return plat_map_dma_mem_page(dev, page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	return pfn_to_page(plat_dma_addr_to_phys(dma_addr) >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-	if (!plat_device_is_coherent(&pdev->dev))
-		dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-	if (!plat_device_is_coherent(&pdev->dev))
-		dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c
index d071bc3..7363e18 100644
--- a/arch/mips/pci/pci-ddb5477.c
+++ b/arch/mips/pci/pci-ddb5477.c
@@ -131,7 +131,7 @@
 	/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int slot_num;
 	unsigned char *slot_irq_map;
diff --git a/arch/mips/pci/pci-ev64120.c b/arch/mips/pci/pci-ev64120.c
deleted file mode 100644
index a84f594..0000000
--- a/arch/mips/pci/pci-ev64120.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <linux/pci.h>
-#include <asm/irq.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int irq;
-
-	if (!pin)
-		return 0;
-
-	irq = allocate_irqno();
-	if (irq < 0)
-		return 0;
-
-	return irq;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 405ce01..a322543 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -134,7 +134,7 @@
  * A given PCI device, in general, should be able to intr any of the cpus
  * on any one of the hubs connected to its xbow.
  */
-int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
 	int irq = bc->pci_int[slot];
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c
deleted file mode 100644
index 985784a..0000000
--- a/arch/mips/pci/pci-lasat.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000, 2001, 04 Keith M Wesolowski
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-
-extern struct pci_ops nile4_pci_ops;
-extern struct pci_ops gt64xxx_pci0_ops;
-static struct resource lasat_pci_mem_resource = {
-	.name	= "LASAT PCI MEM",
-	.start	= 0x18000000,
-	.end	= 0x19ffffff,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct resource lasat_pci_io_resource = {
-	.name	= "LASAT PCI IO",
-	.start	= 0x1a000000,
-	.end	= 0x1bffffff,
-	.flags	= IORESOURCE_IO,
-};
-
-static struct pci_controller lasat_pci_controller = {
-	.mem_resource	= &lasat_pci_mem_resource,
-	.io_resource	= &lasat_pci_io_resource,
-};
-
-static int __init lasat_pci_setup(void)
-{
-	printk("PCI: starting\n");
-
-	switch (mips_machtype) {
-	case MACH_LASAT_100:
-                lasat_pci_controller.pci_ops = &gt64xxx_pci0_ops;
-                break;
-	case MACH_LASAT_200:
-                lasat_pci_controller.pci_ops = &nile4_pci_ops;
-                break;
-	default:
-                panic("pcibios_init: mips_machtype incorrect");
-        }
-
-	register_pci_controller(&lasat_pci_controller);
-
-	return 0;
-}
-
-arch_initcall(lasat_pci_setup);
-
-#define LASATINT_ETH1   0
-#define LASATINT_ETH0   1
-#define LASATINT_HDC    2
-#define LASATINT_COMP   3
-#define LASATINT_HDLC   4
-#define LASATINT_PCIA   5
-#define LASATINT_PCIB   6
-#define LASATINT_PCIC   7
-#define LASATINT_PCID   8
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	switch (slot) {
-	case 1:
-	case 2:
-	case 3:
-		return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4);
-	case 4:
-		return LASATINT_ETH1;   /* Ethernet 1 (LAN 2) */
-	case 5:
-		return LASATINT_ETH0;   /* Ethernet 0 (LAN 1) */
-	case 6:
-		return LASATINT_HDC;    /* IDE controller */
-	default:
-		return 0xff;            /* Illegal */
-	}
-
-	return -1;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c
deleted file mode 100644
index 027759f..0000000
--- a/arch/mips/pci/pci-ocelot-c.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004, 06 by Ralf Baechle (ralf@linux-mips.org)
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/mv643xx.h>
-
-#include <linux/init.h>
-
-#include <asm/marvell.h>
-
-/*
- * We assume the address ranges have already been setup appropriately by
- * the firmware.  PMON in case of the Ocelot C does that.
- */
-static struct resource mv_pci_io_mem0_resource = {
-	.name	= "MV64340 PCI0 IO MEM",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem0_resource = {
-	.name	= "MV64340 PCI0 MEM",
-	.flags	= IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
-	.pcic = {
-		.pci_ops	= &mv_pci_ops,
-		.mem_resource	= &mv_pci_mem0_resource,
-		.io_resource	= &mv_pci_io_mem0_resource,
-	},
-	.config_addr	= MV64340_PCI_0_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static uint32_t mv_io_base, mv_io_size;
-
-static void mv64340_pci0_init(void)
-{
-	uint32_t mem0_base, mem0_size;
-	uint32_t io_base, io_size;
-
-	io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
-	io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
-	mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
-	mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
-
-	mv_pci_io_mem0_resource.start		= 0;
-	mv_pci_io_mem0_resource.end		= io_size - 1;
-	mv_pci_mem0_resource.start		= mem0_base;
-	mv_pci_mem0_resource.end		= mem0_base + mem0_size - 1;
-	mv_bus0_controller.pcic.mem_offset	= mem0_base;
-	mv_bus0_controller.pcic.io_offset	= 0;
-
-	ioport_resource.end		= io_size - 1;
-
-	register_pci_controller(&mv_bus0_controller.pcic);
-
-	mv_io_base = io_base;
-	mv_io_size = io_size;
-}
-
-static struct resource mv_pci_io_mem1_resource = {
-	.name	= "MV64340 PCI1 IO MEM",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem1_resource = {
-	.name	= "MV64340 PCI1 MEM",
-	.flags	= IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
-	.pcic = {
-		.pci_ops	= &mv_pci_ops,
-		.mem_resource	= &mv_pci_mem1_resource,
-		.io_resource	= &mv_pci_io_mem1_resource,
-	},
-	.config_addr	= MV64340_PCI_1_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init void mv64340_pci1_init(void)
-{
-	uint32_t mem0_base, mem0_size;
-	uint32_t io_base, io_size;
-
-	io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
-	io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
-	mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
-	mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
-
-	/*
-	 * Here we assume the I/O window of second bus to be contiguous with
-	 * the first.  A gap is no problem but would waste address space for
-	 * remapping the port space.
-	 */
-	mv_pci_io_mem1_resource.start		= mv_io_size;
-	mv_pci_io_mem1_resource.end		= mv_io_size + io_size - 1;
-	mv_pci_mem1_resource.start		= mem0_base;
-	mv_pci_mem1_resource.end		= mem0_base + mem0_size - 1;
-	mv_bus1_controller.pcic.mem_offset	= mem0_base;
-	mv_bus1_controller.pcic.io_offset	= 0;
-
-	ioport_resource.end		= io_base + io_size -mv_io_base - 1;
-
-	register_pci_controller(&mv_bus1_controller.pcic);
-
-	mv_io_size = io_base + io_size - mv_io_base;
-}
-
-static __init int __init ocelot_c_pci_init(void)
-{
-	unsigned long io_v_base;
-	uint32_t enable;
-
-	enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
-
-	/*
-	 * We require at least one enabled I/O or PCI memory window or we
-	 * will ignore this PCI bus.  We ignore PCI windows 1, 2 and 3.
-	 */
-	if (enable & (0x01 <<  9) || enable & (0x01 << 10))
-		mv64340_pci0_init();
-
-	if (enable & (0x01 << 14) || enable & (0x01 << 15))
-		mv64340_pci1_init();
-
-	if (mv_io_size) {
-		io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
-		if (!io_v_base)
-			panic("Could not ioremap I/O port range");
-
-		set_io_port_base(io_v_base);
-	}
-
-	return 0;
-}
-
-arch_initcall(ocelot_c_pci_init);
diff --git a/arch/mips/pci/pci-ocelot.c b/arch/mips/pci/pci-ocelot.c
index 7f94f26..1421d34 100644
--- a/arch/mips/pci/pci-ocelot.c
+++ b/arch/mips/pci/pci-ocelot.c
@@ -71,19 +71,19 @@
 }
 
 static struct resource ocelot_mem_resource = {
-	start	= GT_PCI_MEM_BASE;
-	end	= GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
+	.start	= GT_PCI_MEM_BASE,
+	.end	= GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1,
 };
 
 static struct resource ocelot_io_resource = {
-	start	= GT_PCI_IO_BASE;
-	end	= GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+	.start	= GT_PCI_IO_BASE,
+	.end	= GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1,
 };
 
 static struct pci_controller ocelot_pci_controller = {
-	.pci_ops	= gt64xxx_pci0_ops;
-	.mem_resource	= &ocelot_mem_resource;
-	.io_resource	= &ocelot_io_resource;
+	.pci_ops	= gt64xxx_pci0_ops,
+	.mem_resource	= &ocelot_mem_resource,
+	.io_resource	= &ocelot_io_resource,
 };
 
 static int __init ocelot_pcibios_init(void)
diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c
index 75c1246..c1ac649 100644
--- a/arch/mips/pci/pci-sb1250.c
+++ b/arch/mips/pci/pci-sb1250.c
@@ -84,7 +84,7 @@
 	*(u32 *) (cfg_space + (addr & ~3)) = data;
 }
 
-int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return dev->irq;
 }
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 8108231..99d8f4f 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -269,7 +269,7 @@
 	}
 
 	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-		struct pci_dev *dev = pci_dev_b(ln);
+		dev = pci_dev_b(ln);
 
 		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
 			pcibios_fixup_device_resources(dev, bus);
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
index d43f56e..c839436 100644
--- a/arch/mips/philips/pnx8550/common/platform.c
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -123,7 +123,7 @@
 	&pnx8550_uart_device,
 };
 
-int pnx8550_platform_init(void)
+static int __init pnx8550_platform_init(void)
 {
 	return platform_add_devices(pnx8550_platform_devices,
 			            ARRAY_SIZE(pnx8550_platform_devices));
diff --git a/arch/mips/philips/pnx8550/common/proc.c b/arch/mips/philips/pnx8550/common/proc.c
index 3f09755..92311e9 100644
--- a/arch/mips/philips/pnx8550/common/proc.c
+++ b/arch/mips/philips/pnx8550/common/proc.c
@@ -78,29 +78,33 @@
 {
 
 	// Create /proc/pnx8550
-        pnx8550_dir = create_proc_entry("pnx8550", S_IFDIR|S_IRUGO, NULL);
+        pnx8550_dir = proc_mkdir("pnx8550", NULL);
         if (!pnx8550_dir) {
                 printk(KERN_ERR "Can't create pnx8550 proc dir\n");
                 return -1;
         }
 
 	// Create /proc/pnx8550/timers
-        pnx8550_timers = create_proc_entry("timers", S_IFREG|S_IRUGO, pnx8550_dir );
-        if (pnx8550_timers){
-                pnx8550_timers->read_proc = pnx8550_timers_read;
-        }
-        else {
+        pnx8550_timers = create_proc_read_entry(
+		"timers",
+		0,
+		pnx8550_dir,
+		pnx8550_timers_read,
+		NULL);
+
+        if (!pnx8550_timers)
                 printk(KERN_ERR "Can't create pnx8550 timers proc file\n");
-        }
 
 	// Create /proc/pnx8550/registers
-        pnx8550_registers = create_proc_entry("registers", S_IFREG|S_IRUGO, pnx8550_dir );
-        if (pnx8550_registers){
-                pnx8550_registers->read_proc = pnx8550_registers_read;
-        }
-        else {
+        pnx8550_registers = create_proc_read_entry(
+		"registers",
+		0,
+		pnx8550_dir,
+		pnx8550_registers_read,
+		NULL);
+
+        if (!pnx8550_registers)
                 printk(KERN_ERR "Can't create pnx8550 registers proc file\n");
-        }
 
 	return 0;
 }
diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig
index 24d514c..abbd0bb 100644
--- a/arch/mips/pmc-sierra/Kconfig
+++ b/arch/mips/pmc-sierra/Kconfig
@@ -1,3 +1,49 @@
+choice
+	prompt "PMC-Sierra MSP SOC type"
+	depends on PMC_MSP
+
+config PMC_MSP4200_EVAL
+	bool "PMC-Sierra MSP4200 Eval Board"
+	select IRQ_MSP_SLP
+	select HW_HAS_PCI
+
+config PMC_MSP4200_GW
+	bool "PMC-Sierra MSP4200 VoIP Gateway"
+	select IRQ_MSP_SLP
+	select HW_HAS_PCI
+
+config PMC_MSP7120_EVAL
+	bool "PMC-Sierra MSP7120 Eval Board"
+	select SYS_SUPPORTS_MULTITHREADING
+	select IRQ_MSP_CIC
+	select HW_HAS_PCI
+
+config PMC_MSP7120_GW
+	bool "PMC-Sierra MSP7120 Residential Gateway"
+	select SYS_SUPPORTS_MULTITHREADING
+	select IRQ_MSP_CIC
+	select HW_HAS_PCI
+
+config PMC_MSP7120_FPGA
+	bool "PMC-Sierra MSP7120 FPGA"
+	select SYS_SUPPORTS_MULTITHREADING
+	select IRQ_MSP_CIC
+	select HW_HAS_PCI
+
+endchoice
+
+menu "Options for PMC-Sierra MSP chipsets"
+	depends on PMC_MSP
+
+config PMC_MSP_EMBEDDED_ROOTFS
+	bool "Root filesystem embedded in kernel image"
+	select MTD
+	select MTD_BLOCK
+	select MTD_PMC_MSP_RAMROOT
+	select MTD_RAM
+
+endmenu
+
 config HYPERTRANSPORT
 	bool "Hypertransport Support for PMC-Sierra Yosemite"
 	depends on PMC_YOSEMITE
diff --git a/arch/mips/pmc-sierra/msp71xx/Makefile b/arch/mips/pmc-sierra/msp71xx/Makefile
new file mode 100644
index 0000000..4bba79c
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the PMC-Sierra MSP SOCs
+#
+obj-y += msp_prom.o msp_setup.o msp_irq.o \
+	 msp_time.o msp_serial.o msp_elb.o
+obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o
+obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o
+obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o
+obj-$(CONFIG_PCI) += msp_pci.o
+obj-$(CONFIG_MSPETH) += msp_eth.o
+obj-$(CONFIG_USB_MSP71XX) += msp_usb.o
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_elb.c b/arch/mips/pmc-sierra/msp71xx/msp_elb.c
new file mode 100644
index 0000000..3e96410
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_elb.c
@@ -0,0 +1,46 @@
+/*
+ * Sets up the proper Chip Select configuration registers.  It is assumed that
+ * PMON sets up the ADDR and MASK registers properly.
+ *
+ * Copyright 2005-2006 PMC-Sierra, Inc.
+ * Author: Marc St-Jean, Marc_St-Jean@pmc-sierra.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <msp_regs.h>
+
+static int __init msp_elb_setup(void)
+{
+#if defined(CONFIG_PMC_MSP7120_GW) \
+ || defined(CONFIG_PMC_MSP7120_EVAL)
+	/*
+	 * Force all CNFG to be identical and equal to CS0,
+	 * according to OPS doc
+	 */
+	*CS1_CNFG_REG = *CS2_CNFG_REG = *CS3_CNFG_REG = *CS0_CNFG_REG;
+#endif
+	return 0;
+}
+
+subsys_initcall(msp_elb_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c
new file mode 100644
index 0000000..6fa8572
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c
@@ -0,0 +1,179 @@
+/*
+ * Sets up interrupt handlers for various hardware switches which are
+ * connected to interrupt lines.
+ *
+ * Copyright 2005-2207 PMC-Sierra, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <msp_int.h>
+#include <msp_regs.h>
+#include <msp_regops.h>
+#ifdef CONFIG_PMCTWILED
+#include <msp_led_macros.h>
+#endif
+
+/* For hwbutton_interrupt->initial_state */
+#define HWBUTTON_HI	0x1
+#define HWBUTTON_LO	0x2
+
+/*
+ * This struct describes a hardware button
+ */
+struct hwbutton_interrupt {
+	char *name;			/* Name of button */
+	int irq;			/* Actual LINUX IRQ */
+	int eirq;			/* Extended IRQ number (0-7) */
+	int initial_state;		/* The "normal" state of the switch */
+	void (*handle_hi)(void *);	/* Handler: switch input has gone HI */
+	void (*handle_lo)(void *);	/* Handler: switch input has gone LO */
+	void *data;			/* Optional data to pass to handler */
+};
+
+#ifdef CONFIG_PMC_MSP7120_GW
+extern void msp_restart(char *);
+
+static void softreset_push(void *data)
+{
+	printk(KERN_WARNING "SOFTRESET switch was pushed\n");
+
+	/*
+	 * In the future you could move this to the release handler,
+	 * timing the difference between the 'push' and 'release', and only
+	 * doing this ungraceful restart if the button has been down for
+	 * a certain amount of time; otherwise doing a graceful restart.
+	 */
+
+	msp_restart(NULL);
+}
+
+static void softreset_release(void *data)
+{
+	printk(KERN_WARNING "SOFTRESET switch was released\n");
+
+	/* Do nothing */
+}
+
+static void standby_on(void *data)
+{
+	printk(KERN_WARNING "STANDBY switch was set to ON (not implemented)\n");
+
+	/* TODO: Put board in standby mode */
+#ifdef CONFIG_PMCTWILED
+	msp_led_turn_off(MSP_LED_PWRSTANDBY_GREEN);
+	msp_led_turn_on(MSP_LED_PWRSTANDBY_RED);
+#endif
+}
+
+static void standby_off(void *data)
+{
+	printk(KERN_WARNING
+		"STANDBY switch was set to OFF (not implemented)\n");
+
+	/* TODO: Take out of standby mode */
+#ifdef CONFIG_PMCTWILED
+	msp_led_turn_on(MSP_LED_PWRSTANDBY_GREEN);
+	msp_led_turn_off(MSP_LED_PWRSTANDBY_RED);
+#endif
+}
+
+static struct hwbutton_interrupt softreset_sw = {
+	.name = "Softreset button",
+	.irq = MSP_INT_EXT0,
+	.eirq = 0,
+	.initial_state = HWBUTTON_HI,
+	.handle_hi = softreset_release,
+	.handle_lo = softreset_push,
+	.data = NULL,
+};
+
+static struct hwbutton_interrupt standby_sw = {
+	.name = "Standby switch",
+	.irq = MSP_INT_EXT1,
+	.eirq = 1,
+	.initial_state = HWBUTTON_HI,
+	.handle_hi = standby_off,
+	.handle_lo = standby_on,
+	.data = NULL,
+};
+#endif /* CONFIG_PMC_MSP7120_GW */
+
+static irqreturn_t hwbutton_handler(int irq, void *data)
+{
+	struct hwbutton_interrupt *hirq = data;
+	unsigned long cic_ext = *CIC_EXT_CFG_REG;
+
+	if (irq != hirq->irq)
+		return IRQ_NONE;
+
+	if (CIC_EXT_IS_ACTIVE_HI(cic_ext, hirq->eirq)) {
+		/* Interrupt: pin is now HI */
+		CIC_EXT_SET_ACTIVE_LO(cic_ext, hirq->eirq);
+		hirq->handle_hi(hirq->data);
+	} else {
+		/* Interrupt: pin is now LO */
+		CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq);
+		hirq->handle_lo(hirq->data);
+	}
+
+	/*
+	 * Invert the POLARITY of this level interrupt to ack the interrupt
+	 * Thus next state change will invoke the opposite message
+	 */
+	*CIC_EXT_CFG_REG = cic_ext;
+
+	return IRQ_HANDLED;
+}
+
+static int msp_hwbutton_register(struct hwbutton_interrupt *hirq)
+{
+	unsigned long cic_ext;
+
+	if (hirq->handle_hi == NULL || hirq->handle_lo == NULL)
+		return -EINVAL;
+
+	cic_ext = *CIC_EXT_CFG_REG;
+	CIC_EXT_SET_TRIGGER_LEVEL(cic_ext, hirq->eirq);
+	if (hirq->initial_state == HWBUTTON_HI)
+		CIC_EXT_SET_ACTIVE_LO(cic_ext, hirq->eirq);
+	else
+		CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq);
+	*CIC_EXT_CFG_REG = cic_ext;
+
+	return request_irq(hirq->irq, hwbutton_handler, SA_INTERRUPT,
+				hirq->name, (void *)hirq);
+}
+
+static int __init msp_hwbutton_setup(void)
+{
+#ifdef CONFIG_PMC_MSP7120_GW
+	msp_hwbutton_register(&softreset_sw);
+	msp_hwbutton_register(&standby_sw);
+#endif
+	return 0;
+}
+
+subsys_initcall(msp_hwbutton_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq.c b/arch/mips/pmc-sierra/msp71xx/msp_irq.c
new file mode 100644
index 0000000..734d598
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq.c
@@ -0,0 +1,124 @@
+/*
+ * IRQ vector handles
+ *
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/time.h>
+
+#include <asm/irq_cpu.h>
+
+#include <msp_int.h>
+
+extern void msp_int_handle(void);
+
+/* SLP bases systems */
+extern void msp_slp_irq_init(void);
+extern void msp_slp_irq_dispatch(void);
+
+/* CIC based systems */
+extern void msp_cic_irq_init(void);
+extern void msp_cic_irq_dispatch(void);
+
+/*
+ * The PMC-Sierra MSP interrupts are arranged in a 3 level cascaded
+ * hierarchical system.  The first level are the direct MIPS interrupts
+ * and are assigned the interrupt range 0-7.  The second level is the SLM
+ * interrupt controller and is assigned the range 8-39.  The third level
+ * comprises the Peripherial block, the PCI block, the PCI MSI block and
+ * the SLP.  The PCI interrupts and the SLP errors are handled by the
+ * relevant subsystems so the core interrupt code needs only concern
+ * itself with the Peripheral block.  These are assigned interrupts in
+ * the range 40-71.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	u32 pending;
+
+	pending = read_c0_status() & read_c0_cause();
+
+	/*
+	 * jump to the correct interrupt routine
+	 * These are arranged in priority order and the timer
+	 * comes first!
+	 */
+
+#ifdef CONFIG_IRQ_MSP_CIC	/* break out the CIC stuff for now */
+	if (pending & C_IRQ4)	/* do the peripherals first, that's the timer */
+		msp_cic_irq_dispatch();
+
+	else if (pending & C_IRQ0)
+		do_IRQ(MSP_INT_MAC0);
+
+	else if (pending & C_IRQ1)
+		do_IRQ(MSP_INT_MAC1);
+
+	else if (pending & C_IRQ2)
+		do_IRQ(MSP_INT_USB);
+
+	else if (pending & C_IRQ3)
+		do_IRQ(MSP_INT_SAR);
+
+	else if (pending & C_IRQ5)
+		do_IRQ(MSP_INT_SEC);
+
+#else
+	if (pending & C_IRQ5)
+		do_IRQ(MSP_INT_TIMER);
+
+	else if (pending & C_IRQ0)
+		do_IRQ(MSP_INT_MAC0);
+
+	else if (pending & C_IRQ1)
+		do_IRQ(MSP_INT_MAC1);
+
+	else if (pending & C_IRQ3)
+		do_IRQ(MSP_INT_VE);
+
+	else if (pending & C_IRQ4)
+		msp_slp_irq_dispatch();
+#endif
+
+	else if (pending & C_SW0)	/* do software after hardware */
+		do_IRQ(MSP_INT_SW0);
+
+	else if (pending & C_SW1)
+		do_IRQ(MSP_INT_SW1);
+}
+
+static struct irqaction cascade_msp = {
+	.handler = no_action,
+	.name	 = "MSP cascade"
+};
+
+
+void __init arch_init_irq(void)
+{
+	/* initialize the 1st-level CPU based interrupt controller */
+	mips_cpu_irq_init();
+
+#ifdef CONFIG_IRQ_MSP_CIC
+	msp_cic_irq_init();
+
+	/* setup the cascaded interrupts */
+	setup_irq(MSP_INT_CIC, &cascade_msp);
+	setup_irq(MSP_INT_PER, &cascade_msp);
+#else
+	/* setup the 2nd-level SLP register based interrupt controller */
+	msp_slp_irq_init();
+
+	/* setup the cascaded SLP/PER interrupts */
+	setup_irq(MSP_INT_SLP, &cascade_msp);
+	setup_irq(MSP_INT_PER, &cascade_msp);
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
new file mode 100644
index 0000000..5175357
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
@@ -0,0 +1,134 @@
+/*
+ * This file define the irq handler for MSP SLM subsystem interrupts.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc, derived from irq_cpu.c
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+
+#include <msp_cic_int.h>
+#include <msp_regs.h>
+
+/*
+ * NOTE: We are only enabling support for VPE0 right now.
+ */
+
+static inline void unmask_msp_cic_irq(unsigned int irq)
+{
+
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*CIC_VPE0_MSK_REG |= (1 << (irq - MSP_CIC_INTBASE));
+	else
+		*PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+}
+
+static inline void mask_msp_cic_irq(unsigned int irq)
+{
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*CIC_VPE0_MSK_REG &= ~(1 << (irq - MSP_CIC_INTBASE));
+	else
+		*PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues.  Same for msp_cic_irq_end.
+ */
+static inline void ack_msp_cic_irq(unsigned int irq)
+{
+	mask_msp_cic_irq(irq);
+
+	/*
+	 * only really necessary for 18, 16-14 and sometimes 3:0 (since
+	 * these can be edge sensitive) but it doesn't hurt for the others.
+	 */
+
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*CIC_STS_REG = (1 << (irq - MSP_CIC_INTBASE));
+	else
+		*PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
+}
+
+static struct irq_chip msp_cic_irq_controller = {
+	.name = "MSP_CIC",
+	.ack = ack_msp_cic_irq,
+	.mask = ack_msp_cic_irq,
+	.mask_ack = ack_msp_cic_irq,
+	.unmask = unmask_msp_cic_irq,
+};
+
+
+void __init msp_cic_irq_init(void)
+{
+	int i;
+
+	/* Mask/clear interrupts. */
+	*CIC_VPE0_MSK_REG = 0x00000000;
+	*PER_INT_MSK_REG  = 0x00000000;
+	*CIC_STS_REG      = 0xFFFFFFFF;
+	*PER_INT_STS_REG  = 0xFFFFFFFF;
+
+#if defined(CONFIG_PMC_MSP7120_GW) || \
+    defined(CONFIG_PMC_MSP7120_EVAL)
+	/*
+	 * The MSP7120 RG and EVBD boards use IRQ[6:4] for PCI.
+	 * These inputs map to EXT_INT_POL[6:4] inside the CIC.
+	 * They are to be active low, level sensitive.
+	 */
+	*CIC_EXT_CFG_REG &= 0xFFFF8F8F;
+#endif
+
+	/* initialize all the IRQ descriptors */
+	for (i = MSP_CIC_INTBASE; i < MSP_PER_INTBASE + 32; i++)
+		set_irq_chip_and_handler(i, &msp_cic_irq_controller,
+					 handle_level_irq);
+}
+
+void msp_cic_irq_dispatch(void)
+{
+	u32 pending;
+	int intbase;
+
+	intbase = MSP_CIC_INTBASE;
+	pending = *CIC_STS_REG & *CIC_VPE0_MSK_REG;
+
+	/* check for PER interrupt */
+	if (pending == (1 << (MSP_INT_PER - MSP_CIC_INTBASE))) {
+		intbase = MSP_PER_INTBASE;
+		pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
+	}
+
+	/* check for spurious interrupt */
+	if (pending == 0x00000000) {
+		printk(KERN_ERR
+			"Spurious %s interrupt? status %08x, mask %08x\n",
+			(intbase == MSP_CIC_INTBASE) ? "CIC" : "PER",
+			(intbase == MSP_CIC_INTBASE) ?
+				*CIC_STS_REG : *PER_INT_STS_REG,
+			(intbase == MSP_CIC_INTBASE) ?
+				*CIC_VPE0_MSK_REG : *PER_INT_MSK_REG);
+		return;
+	}
+
+	/* check for the timer and dispatch it first */
+	if ((intbase == MSP_CIC_INTBASE) &&
+	    (pending & (1 << (MSP_INT_VPE0_TIMER - MSP_CIC_INTBASE))))
+		do_IRQ(MSP_INT_VPE0_TIMER);
+	else
+		do_IRQ(ffs(pending) + intbase - 1);
+}
+
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
new file mode 100644
index 0000000..f5f1b8d
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
@@ -0,0 +1,109 @@
+/*
+ * This file define the irq handler for MSP SLM subsystem interrupts.
+ *
+ * Copyright 2005-2006 PMC-Sierra, Inc, derived from irq_cpu.c
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <msp_slp_int.h>
+#include <msp_regs.h>
+
+static inline void unmask_msp_slp_irq(unsigned int irq)
+{
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*SLP_INT_MSK_REG |= (1 << (irq - MSP_SLP_INTBASE));
+	else
+		*PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+}
+
+static inline void mask_msp_slp_irq(unsigned int irq)
+{
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*SLP_INT_MSK_REG &= ~(1 << (irq - MSP_SLP_INTBASE));
+	else
+		*PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues.  Same for msp_slp_irq_end.
+ */
+static inline void ack_msp_slp_irq(unsigned int irq)
+{
+	mask_slp_irq(irq);
+
+	/*
+	 * only really necessary for 18, 16-14 and sometimes 3:0 (since
+	 * these can be edge sensitive) but it doesn't hurt  for the others.
+	 */
+
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*SLP_INT_STS_REG = (1 << (irq - MSP_SLP_INTBASE));
+	else
+		*PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
+}
+
+static struct irq_chip msp_slp_irq_controller = {
+	.name = "MSP_SLP",
+	.ack = ack_msp_slp_irq,
+	.mask = ack_msp_slp_irq,
+	.mask_ack = ack_msp_slp_irq,
+	.unmask = unmask_msp_slp_irq,
+};
+
+void __init msp_slp_irq_init(void)
+{
+	int i;
+
+	/* Mask/clear interrupts. */
+	*SLP_INT_MSK_REG = 0x00000000;
+	*PER_INT_MSK_REG = 0x00000000;
+	*SLP_INT_STS_REG = 0xFFFFFFFF;
+	*PER_INT_STS_REG = 0xFFFFFFFF;
+
+	/* initialize all the IRQ descriptors */
+	for (i = MSP_SLP_INTBASE; i < MSP_PER_INTBASE + 32; i++)
+		set_irq_chip_and_handler(i, &msp_slp_irq_controller
+					 handle_level_irq);
+}
+
+void msp_slp_irq_dispatch(void)
+{
+	u32 pending;
+	int intbase;
+
+	intbase = MSP_SLP_INTBASE;
+	pending = *SLP_INT_STS_REG & *SLP_INT_MSK_REG;
+
+	/* check for PER interrupt */
+	if (pending == (1 << (MSP_INT_PER - MSP_SLP_INTBASE))) {
+		intbase = MSP_PER_INTBASE;
+		pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
+	}
+
+	/* check for spurious interrupt */
+	if (pending == 0x00000000) {
+		printk(KERN_ERR "Spurious %s interrupt?\n",
+			(intbase == MSP_SLP_INTBASE) ? "SLP" : "PER");
+		return;
+	}
+
+	/* dispatch the irq */
+	do_IRQ(ffs(pending) + intbase - 1);
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_pci.c b/arch/mips/pmc-sierra/msp71xx/msp_pci.c
new file mode 100644
index 0000000..f764fe7
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_pci.c
@@ -0,0 +1,50 @@
+/*
+ * The setup file for PCI related hardware on PMC-Sierra MSP processors.
+ *
+ * Copyright 2005-2006 PMC-Sierra, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+extern void msp_pci_init(void);
+
+static int __init msp_pci_setup(void)
+{
+#if 0 /* Linux 2.6 initialization code to be completed */
+	if (getdeviceid() & DEV_ID_SINGLE_PC) {
+		/* If single card mode */
+		slmRegs	*sreg = (slmRegs *) SREG_BASE;
+
+		sreg->single_pc_enable = SINGLE_PCCARD;
+	}
+#endif
+
+	msp_pci_init();
+
+	return 0;
+}
+
+subsys_initcall(msp_pci_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_prom.c b/arch/mips/pmc-sierra/msp71xx/msp_prom.c
new file mode 100644
index 0000000..e5bd548
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_prom.c
@@ -0,0 +1,566 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *    PROM library initialisation code, assuming a version of
+ *    pmon is the boot code.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#ifdef CONFIG_CRAMFS
+#include <linux/cramfs_fs.h>
+#endif
+#ifdef CONFIG_SQUASHFS
+#include <linux/squashfs_fs.h>
+#endif
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm-generic/sections.h>
+#include <asm/page.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+/* global PROM environment variables and pointers */
+int prom_argc;
+char **prom_argv, **prom_envp;
+int *prom_vec;
+
+/* debug flag */
+int init_debug = 1;
+
+/* memory blocks */
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+/* default feature sets */
+static char msp_default_features[] =
+#if defined(CONFIG_PMC_MSP4200_EVAL) \
+ || defined(CONFIG_PMC_MSP4200_GW)
+	"ERER";
+#elif defined(CONFIG_PMC_MSP7120_EVAL) \
+ || defined(CONFIG_PMC_MSP7120_GW)
+	"EMEMSP";
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+	"EMEM";
+#endif
+
+/* conversion functions */
+static inline unsigned char str2hexnum(unsigned char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	return 0; /* foo */
+}
+
+static inline int str2eaddr(unsigned char *ea, unsigned char *str)
+{
+	int index = 0;
+	unsigned char num = 0;
+
+	while (*str != '\0') {
+		if ((*str == '.') || (*str == ':')) {
+			ea[index++] = num;
+			num = 0;
+			str++;
+		} else {
+			num = num << 4;
+			num |= str2hexnum(*str++);
+		}
+	}
+
+	if (index == 5)	{
+		ea[index++] = num;
+		return 0;
+	} else
+		return -1;
+}
+EXPORT_SYMBOL(str2eaddr);
+
+static inline unsigned long str2hex(unsigned char *str)
+{
+	int value = 0;
+
+	while (*str) {
+		value = value << 4;
+		value |= str2hexnum(*str++);
+	}
+
+	return value;
+}
+
+/* function to query the system information */
+const char *get_system_type(void)
+{
+#if defined(CONFIG_PMC_MSP4200_EVAL)
+	return "PMC-Sierra MSP4200 Eval Board";
+#elif defined(CONFIG_PMC_MSP4200_GW)
+	return "PMC-Sierra MSP4200 VoIP Gateway";
+#elif defined(CONFIG_PMC_MSP7120_EVAL)
+	return "PMC-Sierra MSP7120 Eval Board";
+#elif defined(CONFIG_PMC_MSP7120_GW)
+	return "PMC-Sierra MSP7120 Residential Gateway";
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+	return "PMC-Sierra MSP7120 FPGA";
+#else
+	#error "What is the type of *your* MSP?"
+#endif
+}
+
+int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr)
+{
+	char *ethaddr_str;
+
+	ethaddr_str = prom_getenv(ethaddr_name);
+	if (!ethaddr_str) {
+		printk(KERN_WARNING "%s not set in boot prom\n", ethaddr_name);
+		return -1;
+	}
+
+	if (str2eaddr(ethernet_addr, ethaddr_str) == -1) {
+		printk(KERN_WARNING "%s badly formatted-<%s>\n",
+			ethaddr_name, ethaddr_str);
+		return -1;
+	}
+
+	if (init_debug > 1) {
+		int i;
+		printk(KERN_DEBUG "get_ethernet_addr: for %s ", ethaddr_name);
+		for (i = 0; i < 5; i++)
+			printk(KERN_DEBUG "%02x:",
+				(unsigned char)*(ethernet_addr+i));
+		printk(KERN_DEBUG "%02x\n", *(ethernet_addr+i));
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(get_ethernet_addr);
+
+static char *get_features(void)
+{
+	char *feature = prom_getenv(FEATURES);
+
+	if (feature == NULL) {
+		/* default features based on MACHINE_TYPE */
+		feature = msp_default_features;
+	}
+
+	return feature;
+}
+
+static char test_feature(char c)
+{
+	char *feature = get_features();
+
+	while (*feature) {
+		if (*feature++ == c)
+			return *feature;
+		feature++;
+	}
+
+	return FEATURE_NOEXIST;
+}
+
+unsigned long get_deviceid(void)
+{
+	char *deviceid = prom_getenv(DEVICEID);
+
+	if (deviceid == NULL)
+		return *DEV_ID_REG;
+	else
+		return str2hex(deviceid);
+}
+
+char identify_pci(void)
+{
+	return test_feature(PCI_KEY);
+}
+EXPORT_SYMBOL(identify_pci);
+
+char identify_pcimux(void)
+{
+	return test_feature(PCIMUX_KEY);
+}
+
+char identify_sec(void)
+{
+	return test_feature(SEC_KEY);
+}
+EXPORT_SYMBOL(identify_sec);
+
+char identify_spad(void)
+{
+	return test_feature(SPAD_KEY);
+}
+EXPORT_SYMBOL(identify_spad);
+
+char identify_tdm(void)
+{
+	return test_feature(TDM_KEY);
+}
+EXPORT_SYMBOL(identify_tdm);
+
+char identify_zsp(void)
+{
+	return test_feature(ZSP_KEY);
+}
+EXPORT_SYMBOL(identify_zsp);
+
+static char identify_enetfeature(char key, unsigned long interface_num)
+{
+	char *feature = get_features();
+
+	while (*feature) {
+		if (*feature++ == key && interface_num-- == 0)
+			return *feature;
+		feature++;
+	}
+
+	return FEATURE_NOEXIST;
+}
+
+char identify_enet(unsigned long interface_num)
+{
+	return identify_enetfeature(ENET_KEY, interface_num);
+}
+EXPORT_SYMBOL(identify_enet);
+
+char identify_enetTxD(unsigned long interface_num)
+{
+	return identify_enetfeature(ENETTXD_KEY, interface_num);
+}
+EXPORT_SYMBOL(identify_enetTxD);
+
+unsigned long identify_family(void)
+{
+	unsigned long deviceid;
+
+	deviceid = get_deviceid();
+
+	return deviceid & CPU_DEVID_FAMILY;
+}
+EXPORT_SYMBOL(identify_family);
+
+unsigned long identify_revision(void)
+{
+	unsigned long deviceid;
+
+	deviceid = get_deviceid();
+
+	return deviceid & CPU_DEVID_REVISION;
+}
+EXPORT_SYMBOL(identify_revision);
+
+/* PROM environment functions */
+char *prom_getenv(char *env_name)
+{
+	/*
+	 * Return a pointer to the given environment variable.  prom_envp
+	 * points to a null terminated array of pointers to variables.
+	 * Environment variables are stored in the form of "memsize=64"
+	 */
+
+	char **var = prom_envp;
+	int i = strlen(env_name);
+
+	while (*var) {
+		if (strncmp(env_name, *var, i) == 0) {
+			return (*var + strlen(env_name) + 1);
+		}
+		var++;
+	}
+
+	return NULL;
+}
+
+/* PROM commandline functions */
+char *prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+EXPORT_SYMBOL(prom_getcmdline);
+
+void  __init prom_init_cmdline(void)
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while (actr < prom_argc) {
+		strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	*cp = '\0';
+}
+
+/* memory allocation functions */
+static int __init prom_memtype_classify(unsigned int type)
+{
+	switch (type) {
+	case yamon_free:
+		return BOOT_MEM_RAM;
+	case yamon_prom:
+		return BOOT_MEM_ROM_DATA;
+	default:
+		return BOOT_MEM_RESERVED;
+	}
+}
+
+void __init prom_meminit(void)
+{
+	struct prom_pmemblock *p;
+
+	p = prom_getmdesc();
+
+	while (p->size) {
+		long type;
+		unsigned long base, size;
+
+		type = prom_memtype_classify(p->type);
+		base = p->base;
+		size = p->size;
+
+		add_memory_region(base, size, type);
+		p++;
+	}
+}
+
+void __init prom_free_prom_memory(void)
+{
+	int	argc;
+	char	**argv;
+	char	**envp;
+	char	*ptr;
+	int	len = 0;
+	int	i;
+	unsigned long addr;
+
+	/*
+	 * preserve environment variables and command line from pmon/bbload
+	 * first preserve the command line
+	 */
+	for (argc = 0; argc < prom_argc; argc++) {
+		len += sizeof(char *);			/* length of pointer */
+		len += strlen(prom_argv[argc]) + 1;	/* length of string */
+	}
+	len += sizeof(char *);		/* plus length of null pointer */
+
+	argv = kmalloc(len, GFP_KERNEL);
+	ptr = (char *) &argv[prom_argc + 1];	/* strings follow array */
+
+	for (argc = 0; argc < prom_argc; argc++) {
+		argv[argc] = ptr;
+		strcpy(ptr, prom_argv[argc]);
+		ptr += strlen(prom_argv[argc]) + 1;
+	}
+	argv[prom_argc] = NULL;		/* end array with null pointer */
+	prom_argv = argv;
+
+	/* next preserve the environment variables */
+	len = 0;
+	i = 0;
+	for (envp = prom_envp; *envp != NULL; envp++) {
+		i++;		/* count number of environment variables */
+		len += sizeof(char *);		/* length of pointer */
+		len += strlen(*envp) + 1;	/* length of string */
+	}
+	len += sizeof(char *);		/* plus length of null pointer */
+
+	envp = kmalloc(len, GFP_KERNEL);
+	ptr = (char *) &envp[i+1];
+
+	for (argc = 0; argc < i; argc++) {
+		envp[argc] = ptr;
+		strcpy(ptr, prom_envp[argc]);
+		ptr += strlen(prom_envp[argc]) + 1;
+	}
+	envp[i] = NULL;			/* end array with null pointer */
+	prom_envp = envp;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+			continue;
+
+		addr = boot_mem_map.map[i].addr;
+		free_init_pages("prom memory",
+				addr, addr + boot_mem_map.map[i].size);
+	}
+}
+
+struct prom_pmemblock *__init prom_getmdesc(void)
+{
+	static char	memsz_env[] __initdata = "memsize";
+	static char	heaptop_env[] __initdata = "heaptop";
+	char		*str;
+	unsigned int	memsize;
+	unsigned int	heaptop;
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+	void		*ramroot_start;
+	unsigned long	ramroot_size;
+#endif
+	int i;
+
+	str = prom_getenv(memsz_env);
+	if (!str) {
+		ppfinit("memsize not set in boot prom, "
+			"set to default (32Mb)\n");
+		memsize = 0x02000000;
+	} else {
+		memsize = simple_strtol(str, NULL, 0);
+
+		if (memsize == 0) {
+			/* if memsize is a bad size, use reasonable default */
+			memsize = 0x02000000;
+		}
+
+		/* convert to physical address (removing caching bits, etc) */
+		memsize = CPHYSADDR(memsize);
+	}
+
+	str = prom_getenv(heaptop_env);
+	if (!str) {
+		heaptop = CPHYSADDR((u32)&_text);
+		ppfinit("heaptop not set in boot prom, "
+			"set to default 0x%08x\n", heaptop);
+	} else {
+		heaptop = simple_strtol(str, NULL, 16);
+		if (heaptop == 0) {
+			/* heaptop conversion bad, might have 0xValue */
+			heaptop = simple_strtol(str, NULL, 0);
+
+			if (heaptop == 0) {
+				/* heaptop still bad, use reasonable default */
+				heaptop = CPHYSADDR((u32)&_text);
+			}
+		}
+
+		/* convert to physical address (removing caching bits, etc) */
+		heaptop = CPHYSADDR((u32)heaptop);
+	}
+
+	/* the base region */
+	i = 0;
+	mdesc[i].type = BOOT_MEM_RESERVED;
+	mdesc[i].base = 0x00000000;
+	mdesc[i].size = PAGE_ALIGN(0x300 + 0x80);
+		/* jtag interrupt vector + sizeof vector */
+
+	/* PMON data */
+	if (heaptop > mdesc[i].base + mdesc[i].size) {
+		i++;			/* 1 */
+		mdesc[i].type = BOOT_MEM_ROM_DATA;
+		mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
+		mdesc[i].size = heaptop - mdesc[i].base;
+	}
+
+	/* end of PMON data to start of kernel -- probably zero .. */
+	if (heaptop != CPHYSADDR((u32)_text)) {
+		i++;	/* 2 */
+		mdesc[i].type = BOOT_MEM_RAM;
+		mdesc[i].base = heaptop;
+		mdesc[i].size = CPHYSADDR((u32)_text) - mdesc[i].base;
+	}
+
+	/*  kernel proper */
+	i++;			/* 3 */
+	mdesc[i].type = BOOT_MEM_RESERVED;
+	mdesc[i].base = CPHYSADDR((u32)_text);
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+	if (get_ramroot(&ramroot_start, &ramroot_size)) {
+		/*
+		 * Rootfs in RAM -- follows kernel
+		 * Combine rootfs image with kernel block so a
+		 * page (4k) isn't wasted between memory blocks
+		 */
+		mdesc[i].size = CPHYSADDR(PAGE_ALIGN(
+			(u32)ramroot_start + ramroot_size)) - mdesc[i].base;
+	} else
+#endif
+		mdesc[i].size = CPHYSADDR(PAGE_ALIGN(
+			(u32)_end)) - mdesc[i].base;
+
+	/* Remainder of RAM -- under memsize */
+	i++;			/* 5 */
+	mdesc[i].type = yamon_free;
+	mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
+	mdesc[i].size = memsize - mdesc[i].base;
+
+	return &mdesc[0];
+}
+
+/* rootfs functions */
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+bool get_ramroot(void **start, unsigned long *size)
+{
+	extern char _end[];
+
+	/* Check for start following the end of the kernel */
+	void *check_start = (void *)_end;
+
+	/* Check for supported rootfs types */
+#ifdef CONFIG_CRAMFS
+	if (*(__u32 *)check_start == CRAMFS_MAGIC) {
+		/* Get CRAMFS size */
+		*start = check_start;
+		*size = PAGE_ALIGN(((struct cramfs_super *)
+				   check_start)->size);
+
+		return true;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS
+	if (*((unsigned int *)check_start) == SQUASHFS_MAGIC) {
+		/* Get SQUASHFS size */
+		*start = check_start;
+		*size = PAGE_ALIGN(((struct squashfs_super_block *)
+				   check_start)->bytes_used);
+
+		return true;
+	}
+#endif
+
+	return false;
+}
+EXPORT_SYMBOL(get_ramroot);
+#endif
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
new file mode 100644
index 0000000..8f69b78
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
@@ -0,0 +1,256 @@
+/*
+ * The generic setup file for PMC-Sierra MSP processors
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc,
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bootinfo.h>
+#include <asm/cacheflush.h>
+#include <asm/r4kcache.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+#include <msp_regops.h>
+#include <msp_gpio.h>
+#define MSP_BOARD_RESET_GPIO	9
+#endif
+
+extern void msp_timer_init(void);
+extern void msp_serial_setup(void);
+extern void pmctwiled_setup(void);
+
+#if defined(CONFIG_PMC_MSP7120_EVAL) || \
+    defined(CONFIG_PMC_MSP7120_GW) || \
+    defined(CONFIG_PMC_MSP7120_FPGA)
+/*
+ * Performs the reset for MSP7120-based boards
+ */
+void msp7120_reset(void)
+{
+	void *start, *end, *iptr;
+	register int i;
+
+	/* Diasble all interrupts */
+	local_irq_disable();
+#ifdef CONFIG_SYS_SUPPORTS_MULTITHREADING
+	dvpe();
+#endif
+
+	/* Cache the reset code of this function */
+	__asm__ __volatile__ (
+		"	.set	push				\n"
+		"	.set	mips3				\n"
+		"	la	%0,startpoint			\n"
+		"	la	%1,endpoint			\n"
+		"	.set	pop				\n"
+		: "=r" (start), "=r" (end)
+		:
+	);
+
+	for (iptr = (void *)((unsigned int)start & ~(L1_CACHE_BYTES - 1));
+	     iptr < end; iptr += L1_CACHE_BYTES)
+		cache_op(Fill, iptr);
+
+	__asm__ __volatile__ (
+		"startpoint:					\n"
+	);
+
+	/* Put the DDRC into self-refresh mode */
+	DDRC_INDIRECT_WRITE(DDRC_CTL(10), 0xb, 1 << 16);
+
+	/*
+	 * IMPORTANT!
+	 * DO NOT do anything from here on out that might even
+	 * think about fetching from RAM - i.e., don't call any
+	 * non-inlined functions, and be VERY sure that any inline
+	 * functions you do call do NOT access any sort of RAM
+	 * anywhere!
+	 */
+
+	/* Wait a bit for the DDRC to settle */
+	for (i = 0; i < 100000000; i++);
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+	/*
+	 * Set GPIO 9 HI, (tied to board reset logic)
+	 * GPIO 9 is the 4th GPIO of register 3
+	 *
+	 * NOTE: We cannot use the higher-level msp_gpio_mode()/out()
+	 * as GPIO char driver may not be enabled and it would look up
+	 * data inRAM!
+	 */
+	set_value_reg32(GPIO_CFG3_REG,
+			basic_mode_mask(MSP_BOARD_RESET_GPIO),
+			basic_mode(MSP_GPIO_OUTPUT, MSP_BOARD_RESET_GPIO));
+	set_reg32(GPIO_DATA3_REG,
+			basic_data_mask(MSP_BOARD_RESET_GPIO));
+
+	/*
+	 * In case GPIO9 doesn't reset the board (jumper configurable!)
+	 * fallback to device reset below.
+	 */
+#endif
+	/* Set bit 1 of the MSP7120 reset register */
+	*RST_SET_REG = 0x00000001;
+
+	__asm__ __volatile__ (
+		"endpoint:					\n"
+	);
+}
+#endif
+
+void msp_restart(char *command)
+{
+	printk(KERN_WARNING "Now rebooting .......\n");
+
+#if defined(CONFIG_PMC_MSP7120_EVAL) || \
+    defined(CONFIG_PMC_MSP7120_GW) || \
+    defined(CONFIG_PMC_MSP7120_FPGA)
+	msp7120_reset();
+#else
+	/* No chip-specific reset code, just jump to the ROM reset vector */
+	set_c0_status(ST0_BEV | ST0_ERL);
+	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_c0_wired(0);
+
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+#endif
+}
+
+void msp_halt(void)
+{
+	printk(KERN_WARNING "\n** You can safely turn off the power\n");
+	while (1)
+		/* If possible call official function to get CPU WARs */
+		if (cpu_wait)
+			(*cpu_wait)();
+		else
+			__asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
+}
+
+void msp_power_off(void)
+{
+	msp_halt();
+}
+
+void __init plat_mem_setup(void)
+{
+	_machine_restart = msp_restart;
+	_machine_halt = msp_halt;
+	pm_power_off = msp_power_off;
+
+	board_time_init = msp_timer_init;
+}
+
+void __init prom_init(void)
+{
+	unsigned long family;
+	unsigned long revision;
+
+	prom_argc = fw_arg0;
+	prom_argv = (char **)fw_arg1;
+	prom_envp = (char **)fw_arg2;
+
+	/*
+	 * Someday we can use this with PMON2000 to get a
+	 * platform call prom routines for output etc. without
+	 * having to use grody hacks.  For now it's unused.
+	 *
+	 * struct callvectors *cv = (struct callvectors *) fw_arg3;
+	 */
+	family = identify_family();
+	revision = identify_revision();
+
+	switch (family)	{
+	case FAMILY_FPGA:
+		if (FPGA_IS_MSP4200(revision)) {
+			/* Old-style revision ID */
+			mips_machgroup = MACH_GROUP_MSP;
+			mips_machtype = MACH_MSP4200_FPGA;
+		} else {
+			mips_machgroup = MACH_GROUP_MSP;
+			mips_machtype = MACH_MSP_OTHER;
+		}
+		break;
+
+	case FAMILY_MSP4200:
+		mips_machgroup = MACH_GROUP_MSP;
+#if defined(CONFIG_PMC_MSP4200_EVAL)
+		mips_machtype  = MACH_MSP4200_EVAL;
+#elif defined(CONFIG_PMC_MSP4200_GW)
+		mips_machtype  = MACH_MSP4200_GW;
+#else
+		mips_machtype = MACH_MSP_OTHER;
+#endif
+		break;
+
+	case FAMILY_MSP4200_FPGA:
+		mips_machgroup = MACH_GROUP_MSP;
+		mips_machtype  = MACH_MSP4200_FPGA;
+		break;
+
+	case FAMILY_MSP7100:
+		mips_machgroup = MACH_GROUP_MSP;
+#if defined(CONFIG_PMC_MSP7120_EVAL)
+		mips_machtype = MACH_MSP7120_EVAL;
+#elif defined(CONFIG_PMC_MSP7120_GW)
+		mips_machtype = MACH_MSP7120_GW;
+#else
+		mips_machtype = MACH_MSP_OTHER;
+#endif
+		break;
+
+	case FAMILY_MSP7100_FPGA:
+		mips_machgroup = MACH_GROUP_MSP;
+		mips_machtype  = MACH_MSP7120_FPGA;
+		break;
+
+	default:
+		/* we don't recognize the machine */
+		mips_machgroup = MACH_GROUP_UNKNOWN;
+		mips_machtype  = MACH_UNKNOWN;
+		break;
+	}
+
+	/* make sure we have the right initialization routine - sanity */
+	if (mips_machgroup != MACH_GROUP_MSP) {
+		ppfinit("Unknown machine group in a "
+			"MSP initialization routine\n");
+		panic("***Bogosity factor five***, exiting\n");
+	}
+
+	prom_init_cmdline();
+
+	prom_meminit();
+
+	/*
+	 * Sub-system setup follows.
+	 * Setup functions can  either be called here or using the
+	 * subsys_initcall mechanism (i.e. see msp_pci_setup). The
+	 * order in which they are called can be changed by using the
+	 * link order in arch/mips/pmc-sierra/msp71xx/Makefile.
+	 *
+	 * NOTE: Please keep sub-system specific initialization code
+	 * in separate specific files.
+	 */
+	msp_serial_setup();
+
+#ifdef CONFIG_PMCTWILED
+	/*
+	 * Setup LED states before the subsys_initcall loads other
+	 * dependant drivers/modules.
+	 */
+	pmctwiled_setup();
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c
new file mode 100644
index 0000000..2a2beac5
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c
@@ -0,0 +1,94 @@
+/*
+ * Setting up the clock on MSP SOCs.  No RTC typically.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+
+#include <asm/mipsregs.h>
+#include <asm/time.h>
+
+#include <msp_prom.h>
+#include <msp_int.h>
+#include <msp_regs.h>
+
+void __init msp_timer_init(void)
+{
+	char    *endp, *s;
+	unsigned long cpu_rate = 0;
+
+	if (cpu_rate == 0) {
+		s = prom_getenv("clkfreqhz");
+		cpu_rate = simple_strtoul(s, &endp, 10);
+		if (endp != NULL && *endp != 0) {
+			printk(KERN_ERR
+				"Clock rate in Hz parse error: %s\n", s);
+			cpu_rate = 0;
+		}
+	}
+
+	if (cpu_rate == 0) {
+		s = prom_getenv("clkfreq");
+		cpu_rate = 1000 * simple_strtoul(s, &endp, 10);
+		if (endp != NULL && *endp != 0) {
+			printk(KERN_ERR
+				"Clock rate in MHz parse error: %s\n", s);
+			cpu_rate = 0;
+		}
+	}
+
+	if (cpu_rate == 0) {
+#if defined(CONFIG_PMC_MSP7120_EVAL) \
+ || defined(CONFIG_PMC_MSP7120_GW)
+		cpu_rate = 400000000;
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+		cpu_rate = 25000000;
+#else
+		cpu_rate = 150000000;
+#endif
+		printk(KERN_ERR
+			"Failed to determine CPU clock rate, "
+			"assuming %ld hz ...\n", cpu_rate);
+	}
+
+	printk(KERN_WARNING "Clock rate set to %ld\n", cpu_rate);
+
+	/* timer frequency is 1/2 clock rate */
+	mips_hpt_frequency = cpu_rate/2;
+}
+
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+#ifdef CONFIG_IRQ_MSP_CIC
+	/* we are using the vpe0 counter for timer interrupts */
+	setup_irq(MSP_INT_VPE0_TIMER, irq);
+#else
+	/* we are using the mips counter for timer interrupts */
+	setup_irq(MSP_INT_TIMER, irq);
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_usb.c b/arch/mips/pmc-sierra/msp71xx/msp_usb.c
new file mode 100644
index 0000000..21f9c70
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_usb.c
@@ -0,0 +1,150 @@
+/*
+ * The setup file for USB related hardware on PMC-Sierra MSP processors.
+ *
+ * Copyright 2006-2007 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/mipsregs.h>
+
+#include <msp_regs.h>
+#include <msp_int.h>
+#include <msp_prom.h>
+
+#if defined(CONFIG_USB_EHCI_HCD)
+static struct resource msp_usbhost_resources [] = {
+	[0] = {
+		.start	= MSP_USB_BASE_START,
+		.end	= MSP_USB_BASE_END,
+		.flags 	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_USB,
+		.end	= MSP_INT_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 msp_usbhost_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device msp_usbhost_device = {
+	.name	= "pmcmsp-ehci",
+	.id	= 0,
+	.dev	= {
+		.dma_mask = &msp_usbhost_dma_mask,
+		.coherent_dma_mask = DMA_32BIT_MASK,
+	},
+	.num_resources 	= ARRAY_SIZE (msp_usbhost_resources),
+	.resource	= msp_usbhost_resources,
+};
+#endif /* CONFIG_USB_EHCI_HCD */
+
+#if defined(CONFIG_USB_GADGET)
+static struct resource msp_usbdev_resources [] = {
+	[0] = {
+		.start	= MSP_USB_BASE,
+		.end	= MSP_USB_BASE_END,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_USB,
+		.end	= MSP_INT_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 msp_usbdev_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device msp_usbdev_device = {
+	.name	= "msp71xx_udc",
+	.id	= 0,
+	.dev	= {
+		.dma_mask = &msp_usbdev_dma_mask,
+		.coherent_dma_mask = DMA_32BIT_MASK,
+	},
+	.num_resources	= ARRAY_SIZE (msp_usbdev_resources),
+	.resource	= msp_usbdev_resources,
+};
+#endif /* CONFIG_USB_GADGET */
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
+static struct platform_device *msp_devs[1];
+#endif
+
+
+static int __init msp_usb_setup(void)
+{
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
+	char *strp;
+	char envstr[32];
+	unsigned int val = 0;
+	int result = 0;
+
+	/*
+	 * construct environment name usbmode
+	 * set usbmode <host/device> as pmon environment var
+	 */
+	snprintf((char *)&envstr[0], sizeof(envstr), "usbmode");
+
+#if defined(CONFIG_USB_EHCI_HCD)
+	/* default to host mode */
+	val = 1;
+#endif
+
+	/* get environment string */
+	strp = prom_getenv((char *)&envstr[0]);
+	if (strp) {
+		if (!strcmp(strp, "device"))
+			val = 0;
+	}
+
+	if (val) {
+#if defined(CONFIG_USB_EHCI_HCD)
+		/* get host mode device */
+		msp_devs[0] = &msp_usbhost_device;
+		ppfinit("platform add USB HOST done %s.\n",
+			    msp_devs[0]->name);
+
+		result = platform_add_devices(msp_devs, ARRAY_SIZE (msp_devs));
+#endif /* CONFIG_USB_EHCI_HCD */
+	}
+#if defined(CONFIG_USB_GADGET)
+	else {
+		/* get device mode structure */
+		msp_devs[0] = &msp_usbdev_device;
+		ppfinit("platform add USB DEVICE done %s.\n",
+			    msp_devs[0]->name);
+
+		result = platform_add_devices(msp_devs, ARRAY_SIZE (msp_devs));
+	}
+#endif /* CONFIG_USB_GADGET */
+#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */
+
+	return result;
+}
+
+subsys_initcall(msp_usb_setup);
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 305491e..d83c4ad 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -77,7 +77,7 @@
  * stack so the first thing we do is throw away that stuff and load useful
  * values into the registers ...
  */
-void prom_boot_secondary(int cpu, struct task_struct *idle)
+void __init prom_boot_secondary(int cpu, struct task_struct *idle)
 {
 	unsigned long gp = (unsigned long) task_thread_info(idle);
 	unsigned long sp = __KSTK_TOS(idle);
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index f5ea2fe..89891e9 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -7,8 +7,6 @@
 #include <asm/system.h>
 #include <asm/time.h>
 
-extern asmlinkage void qemu_handle_int(void);
-
 asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 66df5ac..63afd7e 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -46,7 +46,7 @@
 
 static int machine_state;
 
-static void ATTRIB_NORET sgi_machine_power_off(void)
+static void __noreturn sgi_machine_power_off(void)
 {
 	unsigned int tmp;
 
@@ -68,7 +68,7 @@
 	}
 }
 
-static void ATTRIB_NORET sgi_machine_restart(char *command)
+static void __noreturn sgi_machine_restart(char *command)
 {
 	if (machine_state & MACHINE_SHUTTING_DOWN)
 		sgi_machine_power_off();
@@ -76,7 +76,7 @@
 	while (1);
 }
 
-static void ATTRIB_NORET sgi_machine_halt(void)
+static void __noreturn sgi_machine_halt(void)
 {
 	if (machine_state & MACHINE_SHUTTING_DOWN)
 		sgi_machine_power_off();
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c
index ce907ed..123141a 100644
--- a/arch/mips/sgi-ip27/ip27-berr.c
+++ b/arch/mips/sgi-ip27/ip27-berr.c
@@ -21,7 +21,6 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 
-extern void dump_tlb_addr(unsigned long addr);
 extern void dump_tlb_all(void);
 
 static void dump_hub_information(unsigned long errst0, unsigned long errst1)
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index fe8a106..e5e023f 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -517,7 +517,7 @@
 		pfn_t start_pfn = slot_getbasepfn(node, 0);
 		pfn_t end_pfn = node_getmaxclick(node) + 1;
 
-		zones_size[ZONE_DMA] = end_pfn - start_pfn;
+		zones_size[ZONE_NORMAL] = end_pfn - start_pfn;
 		free_area_init_node(node, NODE_DATA(node),
 				zones_size, start_pfn, NULL);
 
diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile
index 7e14167..60f0227 100644
--- a/arch/mips/sgi-ip32/Makefile
+++ b/arch/mips/sgi-ip32/Makefile
@@ -3,5 +3,5 @@
 # under Linux.
 #
 
-obj-y	+= ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \
+obj-y	+= ip32-berr.o ip32-irq.o ip32-platform.o ip32-setup.o ip32-reset.o \
 	   crime.o ip32-memory.o
diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c
new file mode 100644
index 0000000..ba3697e
--- /dev/null
+++ b/arch/mips/sgi-ip32/ip32-platform.c
@@ -0,0 +1,72 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+/*
+ * .iobase isn't a constant (in the sense of C) so we fill it in at runtime.
+ */
+#define MACE_PORT(int)							\
+{									\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_MEM,					\
+	.flags		= UPF_SKIP_TEST,				\
+	.regshift	= 8,						\
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+	MACE_PORT(MACEISA_SERIAL1_IRQ),
+	MACE_PORT(MACEISA_SERIAL2_IRQ),
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	uart8250_data[0].iobase = (unsigned long) &mace->isa.serial1;
+	uart8250_data[1].iobase = (unsigned long) &mace->isa.serial1;
+
+	return platform_device_register(&uart8250_device);
+}
+
+device_initcall(uart8250_init);
+
+static __init int meth_devinit(void)
+{
+	struct platform_device *pd;
+	int ret;
+
+	pd = platform_device_alloc("meth", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	ret = platform_device_add(pd);
+	if (ret)
+		platform_device_put(pd);
+
+	return ret;
+}
+
+device_initcall(meth_devinit);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for SGI IP32 aka O2");
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index 57708fe..bbba066 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -62,12 +62,6 @@
 }
 #endif
 
-#ifdef CONFIG_SERIAL_8250
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#endif /* CONFIG_SERIAL_8250 */
-
 /* An arbitrary time; this can be decreased if reliability looks good */
 #define WAIT_MS 10
 
@@ -96,36 +90,6 @@
 
 	board_time_init = ip32_time_init;
 
-#ifdef CONFIG_SERIAL_8250
-	{
-		static struct uart_port o2_serial[2];
-
-		memset(o2_serial, 0, sizeof(o2_serial));
-		o2_serial[0].type	= PORT_16550A;
-		o2_serial[0].line	= 0;
-		o2_serial[0].irq	= MACEISA_SERIAL1_IRQ;
-		o2_serial[0].flags	= UPF_SKIP_TEST;
-		o2_serial[0].uartclk	= 1843200;
-		o2_serial[0].iotype	= UPIO_MEM;
-		o2_serial[0].membase	= (char *)&mace->isa.serial1;
-		o2_serial[0].fifosize	= 14;
-                /* How much to shift register offset by. Each UART register
-		 * is replicated over 256 byte space */
-		o2_serial[0].regshift	= 8;
-		o2_serial[1].type	= PORT_16550A;
-		o2_serial[1].line	= 1;
-		o2_serial[1].irq	= MACEISA_SERIAL2_IRQ;
-		o2_serial[1].flags	= UPF_SKIP_TEST;
-		o2_serial[1].uartclk	= 1843200;
-		o2_serial[1].iotype	= UPIO_MEM;
-		o2_serial[1].membase	= (char *)&mace->isa.serial2;
-		o2_serial[1].fifosize	= 14;
-		o2_serial[1].regshift	= 8;
-
-		early_serial_setup(&o2_serial[0]);
-		early_serial_setup(&o2_serial[1]);
-	}
-#endif
 #ifdef CONFIG_SGI_O2MACE_ETH
 	{
 		char *mac = ArcGetEnvironmentVariable("eaddr");
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
index bdaac34..89f2923 100644
--- a/arch/mips/sibyte/bcm1480/setup.c
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -31,6 +31,7 @@
 unsigned int sb1_pass;
 unsigned int soc_pass;
 unsigned int soc_type;
+EXPORT_SYMBOL(soc_type);
 unsigned int periph_rev;
 unsigned int zbbus_mhz;
 
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
index ae4a92c..51898dd 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -62,7 +62,7 @@
 extern int kgdb_port;
 #endif
 
-static void ATTRIB_NORET cfe_linux_exit(void *arg)
+static void __noreturn cfe_linux_exit(void *arg)
 {
 	int warm = *(int *)arg;
 
@@ -83,14 +83,14 @@
 	while (1);
 }
 
-static void ATTRIB_NORET cfe_linux_restart(char *command)
+static void __noreturn cfe_linux_restart(char *command)
 {
 	static const int zero;
 
 	cfe_linux_exit((void *)&zero);
 }
 
-static void ATTRIB_NORET cfe_linux_halt(void)
+static void __noreturn cfe_linux_halt(void)
 {
 	static const int one = 1;
 
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index f4a6169..2d5c6d8b 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -31,6 +31,7 @@
 unsigned int sb1_pass;
 unsigned int soc_pass;
 unsigned int soc_type;
+EXPORT_SYMBOL(soc_type);
 unsigned int periph_rev;
 unsigned int zbbus_mhz;
 EXPORT_SYMBOL(zbbus_mhz);
diff --git a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c
deleted file mode 100644
index 97c73c7..0000000
--- a/arch/mips/sibyte/swarm/time.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * Time routines for the swarm board.  We pass all the hard stuff
- * through to the sb1250 handling code.  Only thing we really keep
- * track of here is what time of day we think it is.  And we don't
- * really even do a good job of that...
- */
-
-
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <asm/addrspace.h>
-#include <asm/io.h>
-
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_smbus.h>
-
-static unsigned long long sec_bias = 0;
-static unsigned int usec_bias = 0;
-
-/* Xicor 1241 definitions */
-
-/*
- * Register bits
- */
-
-#define X1241REG_SR_BAT	0x80		/* currently on battery power */
-#define X1241REG_SR_RWEL 0x04		/* r/w latch is enabled, can write RTC */
-#define X1241REG_SR_WEL 0x02		/* r/w latch is unlocked, can enable r/w now */
-#define X1241REG_SR_RTCF 0x01		/* clock failed */
-#define X1241REG_BL_BP2 0x80		/* block protect 2 */
-#define X1241REG_BL_BP1 0x40		/* block protect 1 */
-#define X1241REG_BL_BP0 0x20		/* block protect 0 */
-#define X1241REG_BL_WD1	0x10
-#define X1241REG_BL_WD0	0x08
-#define X1241REG_HR_MIL 0x80		/* military time format */
-
-/*
- * Register numbers
- */
-
-#define X1241REG_BL	0x10		/* block protect bits */
-#define X1241REG_INT	0x11		/*  */
-#define X1241REG_SC	0x30		/* Seconds */
-#define X1241REG_MN	0x31		/* Minutes */
-#define X1241REG_HR	0x32		/* Hours */
-#define X1241REG_DT	0x33		/* Day of month */
-#define X1241REG_MO	0x34		/* Month */
-#define X1241REG_YR	0x35		/* Year */
-#define X1241REG_DW	0x36		/* Day of Week */
-#define X1241REG_Y2K	0x37		/* Year 2K */
-#define X1241REG_SR	0x3F		/* Status register */
-
-#define X1241_CCR_ADDRESS	0x6F
-
-#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
-
-static int xicor_read(uint8_t addr)
-{
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-	__raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
-	__raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA));
-	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
-		     SMB_CSR(R_SMB_START));
-
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
-		     SMB_CSR(R_SMB_START));
-
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
-                /* Clear error bit by writing a 1 */
-                __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
-                return -1;
-        }
-
-	return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
-}
-
-static int xicor_write(uint8_t addr, int b)
-{
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-	__raw_writeq(addr, SMB_CSR(R_SMB_CMD));
-	__raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
-	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
-		     SMB_CSR(R_SMB_START));
-
-        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
-                /* Clear error bit by writing a 1 */
-                __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
-                return -1;
-        } else {
-		return 0;
-	}
-}
-
-/*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
- * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- *      sets the minutes. Usually you'll only notice that after reboot!
- */
-int set_rtc_mmss(unsigned long nowtime)
-{
-	int retval = 0;
-	int real_seconds, real_minutes, cmos_minutes;
-
-	cmos_minutes = xicor_read(X1241REG_MN);
-	cmos_minutes = BCD2BIN(cmos_minutes);
-
-	/*
-	 * since we're only adjusting minutes and seconds,
-	 * don't interfere with hour overflow. This avoids
-	 * messing with unknown time zones but requires your
-	 * RTC not to be off by more than 15 minutes
-	 */
-	real_seconds = nowtime % 60;
-	real_minutes = nowtime / 60;
-	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-		real_minutes += 30;		/* correct for half hour time zone */
-	real_minutes %= 60;
-
-	/* unlock writes to the CCR */
-	xicor_write(X1241REG_SR, X1241REG_SR_WEL);
-	xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
-
-	if (abs(real_minutes - cmos_minutes) < 30) {
-		real_seconds = BIN2BCD(real_seconds);
-		real_minutes = BIN2BCD(real_minutes);
-		xicor_write(X1241REG_SC, real_seconds);
-		xicor_write(X1241REG_MN, real_minutes);
-	} else {
-		printk(KERN_WARNING
-		       "set_rtc_mmss: can't update from %d to %d\n",
-		       cmos_minutes, real_minutes);
-		retval = -1;
-	}
-
-	xicor_write(X1241REG_SR, 0);
-
-	printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds);
-
-	return retval;
-}
-
-static unsigned long __init get_swarm_time(void)
-{
-	unsigned int year, mon, day, hour, min, sec, y2k;
-
-	sec = xicor_read(X1241REG_SC);
-	min = xicor_read(X1241REG_MN);
-	hour = xicor_read(X1241REG_HR);
-
-	if (hour & X1241REG_HR_MIL) {
-		hour &= 0x3f;
-	} else {
-		if (hour & 0x20)
-			hour = (hour & 0xf) + 0x12;
-	}
-
-	sec = BCD2BIN(sec);
-	min = BCD2BIN(min);
-	hour = BCD2BIN(hour);
-
-	day = xicor_read(X1241REG_DT);
-	mon = xicor_read(X1241REG_MO);
-	year = xicor_read(X1241REG_YR);
-	y2k = xicor_read(X1241REG_Y2K);
-
-	day = BCD2BIN(day);
-	mon = BCD2BIN(mon);
-	year = BCD2BIN(year);
-	y2k = BCD2BIN(y2k);
-
-	year += (y2k * 100);
-
-	return mktime(year, mon, day, hour, min, sec);
-}
-
-/*
- *  Bring up the timer at 100 Hz.
- */
-void __init swarm_time_init(void)
-{
-	unsigned int flags;
-	int status;
-
-	/* Set up the scd general purpose timer 0 to cpu 0 */
-	sb1250_time_init();
-
-	/* Establish communication with the Xicor 1241 RTC */
-	/* XXXKW how do I share the SMBus with the I2C subsystem? */
-
-	__raw_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
-	__raw_writeq(0, SMB_CSR(R_SMB_CONTROL));
-
-	if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) {
-		printk("x1241: couldn't detect on SWARM SMBus 1\n");
-	} else {
-		if (status & X1241REG_SR_RTCF)
-			printk("x1241: battery failed -- time is probably wrong\n");
-		write_seqlock_irqsave(&xtime_lock, flags);
-		xtime.tv_sec = get_swarm_time();
-		xtime.tv_nsec = 0;
-		write_sequnlock_irqrestore(&xtime_lock, flags);
-	}
-}
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index e5777b7..471418e 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,5 +2,5 @@
 # Makefile for the SNI specific part of the kernel
 #
 
-obj-y += irq.o reset.o setup.o ds1216.o a20r.o rm200.o pcimt.o pcit.o time.o
+obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o
 obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index 31ab80f..acc9ba7 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -15,7 +15,6 @@
 
 #include <asm/sni.h>
 #include <asm/time.h>
-#include <asm/ds1216.h>
 
 #define PORT(_base,_irq)				\
 	{						\
@@ -40,20 +39,34 @@
 	},
 };
 
+static struct resource a20r_ds1216_rsrc[] = {
+        {
+                .start = 0x1c081ffc,
+                .end   = 0x1c081fff,
+                .flags = IORESOURCE_MEM
+        }
+};
+
+static struct platform_device a20r_ds1216_device = {
+        .name           = "rtc-ds1216",
+        .num_resources  = ARRAY_SIZE(a20r_ds1216_rsrc),
+        .resource       = a20r_ds1216_rsrc
+};
+
 static struct resource snirm_82596_rsrc[] = {
 	{
-		.start = 0xb8000000,
-		.end   = 0xb8000004,
+		.start = 0x18000000,
+		.end   = 0x18000004,
 		.flags = IORESOURCE_MEM
 	},
 	{
-		.start = 0xb8010000,
-		.end   = 0xb8010004,
+		.start = 0x18010000,
+		.end   = 0x18010004,
 		.flags = IORESOURCE_MEM
 	},
 	{
-		.start = 0xbff00000,
-		.end   = 0xbff00020,
+		.start = 0x1ff00000,
+		.end   = 0x1ff00020,
 		.flags = IORESOURCE_MEM
 	},
 	{
@@ -74,8 +87,8 @@
 
 static struct resource snirm_53c710_rsrc[] = {
 	{
-		.start = 0xb9000000,
-		.end   = 0xb90fffff,
+		.start = 0x19000000,
+		.end   = 0x190fffff,
 		.flags = IORESOURCE_MEM
 	},
 	{
@@ -93,8 +106,8 @@
 
 static struct resource sc26xx_rsrc[] = {
 	{
-		.start = 0xbc070000,
-		.end   = 0xbc0700ff,
+		.start = 0x1c070000,
+		.end   = 0x1c0700ff,
 		.flags = IORESOURCE_MEM
 	},
 	{
@@ -205,8 +218,7 @@
 
 void sni_a20r_init(void)
 {
-	ds1216_base = (volatile unsigned char *) SNI_DS1216_A20R_BASE;
-	rtc_mips_get_time = ds1216_get_cmos_time;
+	/* FIXME, remove if not needed */
 }
 
 static int __init snirm_a20r_setup_devinit(void)
@@ -218,6 +230,7 @@
 	        platform_device_register(&snirm_53c710_pdev);
 	        platform_device_register(&sc26xx_pdev);
 	        platform_device_register(&a20r_serial8250_device);
+	        platform_device_register(&a20r_ds1216_device);
 	        break;
 	}
 
diff --git a/arch/mips/sni/ds1216.c b/arch/mips/sni/ds1216.c
deleted file mode 100644
index 1d92732..0000000
--- a/arch/mips/sni/ds1216.c
+++ /dev/null
@@ -1,81 +0,0 @@
-
-#include <linux/bcd.h>
-#include <linux/time.h>
-
-#include <asm/ds1216.h>
-
-volatile unsigned char *ds1216_base;
-
-/*
- * Read the 64 bit we'd like to have - It a series
- * of 64 bits showing up in the LSB of the base register.
- *
- */
-static unsigned char *ds1216_read(void)
-{
-	static unsigned char	rdbuf[8];
-	unsigned char		c;
-	int			i, j;
-
-	for (i = 0; i < 8; i++) {
-		c = 0x0;
-		for (j = 0; j < 8; j++) {
-			c |= (*ds1216_base & 0x1) << j;
-		}
-		rdbuf[i] = c;
-	}
-
-	return rdbuf;
-}
-
-static void ds1216_switch_ds_to_clock(void)
-{
-	unsigned char magic[] = {
-		0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
-	};
-	int i,j,c;
-
-	/* Reset magic pointer */
-	c = *ds1216_base;
-
-	/* Write 64 bit magic to DS1216 */
-	for (i = 0; i < 8; i++) {
-		c = magic[i];
-		for (j = 0; j < 8; j++) {
-			*ds1216_base = c;
-			c = c >> 1;
-		}
-	}
-}
-
-unsigned long ds1216_get_cmos_time(void)
-{
-	unsigned char	*rdbuf;
-	unsigned int	year, month, date, hour, min, sec;
-
-	ds1216_switch_ds_to_clock();
-	rdbuf = ds1216_read();
-
-	sec = BCD2BIN(DS1216_SEC(rdbuf));
-	min = BCD2BIN(DS1216_MIN(rdbuf));
-	hour = BCD2BIN(DS1216_HOUR(rdbuf));
-	date = BCD2BIN(DS1216_DATE(rdbuf));
-	month = BCD2BIN(DS1216_MONTH(rdbuf));
-	year = BCD2BIN(DS1216_YEAR(rdbuf));
-
-	if (DS1216_1224(rdbuf) && DS1216_AMPM(rdbuf))
-		hour+=12;
-
-	if (year < 70)
-		year += 2000;
-	else
-		year += 1900;
-
-	return mktime(year, month, date, hour, min, sec);
-}
-
-int ds1216_set_rtc_mmss(unsigned long nowtime)
-{
-	printk("ds1216_set_rtc_mmss called but not implemented\n");
-	return -1;
-}
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 9ee208d..44b1ae6 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -6,7 +6,7 @@
  * for more details.
  *
  * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  */
 
 #include <linux/init.h>
@@ -14,7 +14,6 @@
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 
-#include <asm/mc146818-time.h>
 #include <asm/sni.h>
 #include <asm/time.h>
 #include <asm/i8259.h>
@@ -90,6 +89,26 @@
 	},
 };
 
+static struct resource pcimt_cmos_rsrc[] = {
+        {
+                .start = 0x70,
+                .end   = 0x71,
+                .flags = IORESOURCE_IO
+        },
+        {
+                .start = 8,
+                .end   = 8,
+                .flags = IORESOURCE_IRQ
+        }
+};
+
+static struct platform_device pcimt_cmos_device = {
+        .name           = "rtc_cmos",
+        .num_resources  = ARRAY_SIZE(pcimt_cmos_rsrc),
+        .resource       = pcimt_cmos_rsrc
+};
+
+
 static struct resource sni_io_resource = {
 	.start	= 0x00000000UL,
 	.end	= 0x03bfffffUL,
@@ -131,6 +150,19 @@
 	}
 };
 
+static struct resource pcimt_mem_resources[] = {
+	{
+		/*
+		 * this region should only be 4 bytes long,
+		 * but it's 16MB on all RM300C I've checked
+		 */
+		.start	= 0x1a000000,
+		.end	= 0x1affffff,
+		.name	= "PCI INT ACK",
+		.flags	= IORESOURCE_BUSY
+	}
+};
+
 static struct resource sni_mem_resource = {
 	.start	= 0x18000000UL,
 	.end	= 0x1fbfffffUL,
@@ -145,6 +177,9 @@
 	/* request I/O space for devices used on all i[345]86 PCs */
 	for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
 		request_resource(&sni_io_resource, pcimt_io_resources + i);
+	/* request MEM space for devices used on all i[345]86 PCs */
+	for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
+		request_resource(&sni_mem_resource, pcimt_mem_resources + i);
 }
 
 extern struct pci_ops sni_pcimt_ops;
@@ -274,12 +309,10 @@
 	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
 }
 
-void sni_pcimt_init(void)
+void __init sni_pcimt_init(void)
 {
 	sni_pcimt_detect();
 	sni_pcimt_sc_init();
-	rtc_mips_get_time = mc146818_get_cmos_time;
-	rtc_mips_set_time = mc146818_set_rtc_mmss;
 	board_time_init = sni_cpu_time_init;
 	ioport_resource.end = sni_io_resource.end;
 #ifdef CONFIG_PCI
@@ -296,6 +329,7 @@
 	case SNI_BRD_PCI_DESKTOP:
 	case SNI_BRD_PCI_MTOWER_CPLUS:
 	        platform_device_register(&pcimt_serial8250_device);
+	        platform_device_register(&pcimt_cmos_device);
 	        break;
 	}
 
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index 00d151f..2480c47 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -13,7 +13,6 @@
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 
-#include <asm/mc146818-time.h>
 #include <asm/sni.h>
 #include <asm/time.h>
 #include <asm/irq_cpu.h>
@@ -58,6 +57,25 @@
 	},
 };
 
+static struct resource pcit_cmos_rsrc[] = {
+        {
+                .start = 0x70,
+                .end   = 0x71,
+                .flags = IORESOURCE_IO
+        },
+        {
+                .start = 8,
+                .end   = 8,
+                .flags = IORESOURCE_IRQ
+        }
+};
+
+static struct platform_device pcit_cmos_device = {
+        .name           = "rtc_cmos",
+        .num_resources  = ARRAY_SIZE(pcit_cmos_rsrc),
+        .resource       = pcit_cmos_rsrc
+};
+
 static struct resource sni_io_resource = {
 	.start	= 0x00000000UL,
 	.end	= 0x03bfffffUL,
@@ -243,10 +261,8 @@
 	setup_irq (MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq);
 }
 
-void sni_pcit_init(void)
+void __init sni_pcit_init(void)
 {
-	rtc_mips_get_time = mc146818_get_cmos_time;
-	rtc_mips_set_time = mc146818_set_rtc_mmss;
 	board_time_init = sni_cpu_time_init;
 	ioport_resource.end = sni_io_resource.end;
 #ifdef CONFIG_PCI
@@ -261,10 +277,12 @@
 	switch (sni_brd_type) {
 	case SNI_BRD_PCI_TOWER:
 	        platform_device_register(&pcit_serial8250_device);
+	        platform_device_register(&pcit_cmos_device);
 	        break;
 
 	case SNI_BRD_PCI_TOWER_CPLUS:
 	        platform_device_register(&pcit_cplus_serial8250_device);
+	        platform_device_register(&pcit_cmos_device);
 	        break;
 	}
 	return 0;
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index b82ff12..28a11d8 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -15,7 +15,6 @@
 
 #include <asm/sni.h>
 #include <asm/time.h>
-#include <asm/ds1216.h>
 #include <asm/irq_cpu.h>
 
 #define PORT(_base,_irq)				\
@@ -41,20 +40,34 @@
 	},
 };
 
+static struct resource rm200_ds1216_rsrc[] = {
+        {
+                .start = 0x1cd41ffc,
+                .end   = 0x1cd41fff,
+                .flags = IORESOURCE_MEM
+        }
+};
+
+static struct platform_device rm200_ds1216_device = {
+        .name           = "rtc-ds1216",
+        .num_resources  = ARRAY_SIZE(rm200_ds1216_rsrc),
+        .resource       = rm200_ds1216_rsrc
+};
+
 static struct resource snirm_82596_rm200_rsrc[] = {
 	{
-		.start = 0xb8000000,
-		.end   = 0xb80fffff,
+		.start = 0x18000000,
+		.end   = 0x180fffff,
 		.flags = IORESOURCE_MEM
 	},
 	{
-		.start = 0xbb000000,
-		.end   = 0xbb000004,
+		.start = 0x1b000000,
+		.end   = 0x1b000004,
 		.flags = IORESOURCE_MEM
 	},
 	{
-		.start = 0xbff00000,
-		.end   = 0xbff00020,
+		.start = 0x1ff00000,
+		.end   = 0x1ff00020,
 		.flags = IORESOURCE_MEM
 	},
 	{
@@ -75,8 +88,8 @@
 
 static struct resource snirm_53c710_rm200_rsrc[] = {
 	{
-		.start = 0xb9000000,
-		.end   = 0xb90fffff,
+		.start = 0x19000000,
+		.end   = 0x190fffff,
 		.flags = IORESOURCE_MEM
 	},
 	{
@@ -96,6 +109,7 @@
 {
 	if (sni_brd_type == SNI_BRD_RM200) {
 		platform_device_register(&rm200_serial8250_device);
+		platform_device_register(&rm200_ds1216_device);
 		platform_device_register(&snirm_82596_rm200_pdev);
 		platform_device_register(&snirm_53c710_rm200_pdev);
 	}
@@ -176,11 +190,9 @@
 	setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq);
 }
 
-void sni_rm200_init(void)
+void __init sni_rm200_init(void)
 {
 	set_io_port_base(SNI_PORT_BASE + 0x02000000);
 	ioport_resource.end += 0x02000000;
-	ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE;
-	rtc_mips_get_time = ds1216_get_cmos_time;
 	board_time_init = sni_cpu_time_init;
 }
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 68d7cf6..4fedfbd 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -6,7 +6,7 @@
  * for more details.
  *
  * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  */
 #include <linux/eisa.h>
 #include <linux/init.h>
@@ -92,3 +92,34 @@
 
 	sni_display_setup();
 }
+
+#if CONFIG_PCI
+
+#include <linux/pci.h>
+#include <video/vga.h>
+#include <video/cirrus.h>
+
+static void __devinit quirk_cirrus_ram_size(struct pci_dev *dev)
+{
+	u16 cmd;
+
+	/*
+	 * firmware doesn't set the ram size correct, so we
+	 * need to do it here, otherwise we get screen corruption
+	 * on older Cirrus chips
+	 */
+	pci_read_config_word (dev, PCI_COMMAND, &cmd);
+	if ((cmd & (PCI_COMMAND_IO|PCI_COMMAND_MEMORY))
+	        == (PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) {
+		vga_wseq (NULL, CL_SEQR6, 0x12);	/* unlock all extension registers */
+		vga_wseq (NULL, CL_SEQRF, 0x18);
+	}
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5434_8,
+                        quirk_cirrus_ram_size);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5436,
+                        quirk_cirrus_ram_size);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446,
+                        quirk_cirrus_ram_size);
+#endif
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
index 643366e..00a03a6 100644
--- a/arch/mips/sni/sniprom.c
+++ b/arch/mips/sni/sniprom.c
@@ -146,7 +146,10 @@
 		}
 		if (baud)
 			strcpy(options, baud);
-		add_preferred_console("ttyS", port, baud ? options : NULL);
+		if (strncmp (cdev, "tty552", 6) == 0)
+			add_preferred_console("ttyS", port, baud ? options : NULL);
+		else
+			add_preferred_console("ttySC", port, baud ? options : NULL);
 	}
 }
 
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index a0c11ef..40c7c3e 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -138,7 +138,6 @@
 char *prom_getcmdline(void);
 
 #ifdef CONFIG_PCI
-#define CONFIG_TX4927BUG_WORKAROUND
 #undef TX4927_SUPPORT_COMMAND_IO
 #undef  TX4927_SUPPORT_PCI_66
 int tx4927_cpu_clock = 100000000;	/* 100MHz */
@@ -669,15 +668,7 @@
 
 	/* PCI->GB mappings (MEM 16MB) -not used */
 	tx4927_pcicptr->p2gm1plbase = 0xffffffff;
-#ifdef CONFIG_TX4927BUG_WORKAROUND
-	/*
-	 * TX4927-PCIC-BUG: P2GM1PUBASE must be 0
-	 * if P2GM0PUBASE was 0.
-	 */
-	tx4927_pcicptr->p2gm1pubase = 0;
-#else
 	tx4927_pcicptr->p2gm1pubase = 0xffffffff;
-#endif
 	tx4927_pcicptr->p2gmgbase[1] = 0;
 
 	/* PCI->GB mappings (MEM 1MB) -not used */
@@ -910,16 +901,6 @@
 	if (tx4927_ccfg_toeon)
 		tx4927_ccfgptr->ccfg |= TX4927_CCFG_TOE;
 
-	/* SDRAMC fixup */
-#ifdef CONFIG_TX4927BUG_WORKAROUND
-	/*
-	 * TX4927-BUG: INF 01-01-18/ BUG 01-01-22
-	 * G-bus timeout error detection is incorrect
-	 */
-	if (tx4927_ccfg_toeon)
-		tx4927_sdramcptr->tr |= 0x02000000;	/* RCD:3tck */
-#endif
-
 	tx4927_pci_setup();
 	if (tx4927_using_backplane == 1)
 		printk("backplane board IS installed\n");
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
index 2033ae7..83cda51 100644
--- a/arch/mips/tx4938/common/Makefile
+++ b/arch/mips/tx4938/common/Makefile
@@ -6,6 +6,6 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y	+= prom.o setup.o irq.o rtc_rx5c348.o
+obj-y	+= prom.o setup.o irq.o
 obj-$(CONFIG_KGDB) += dbgio.o
 
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c
deleted file mode 100644
index 07f782f..0000000
--- a/arch/mips/tx4938/common/rtc_rx5c348.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * RTC routines for RICOH Rx5C348 SPI chip.
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/rtc.h>
-#include <linux/time.h>
-#include <linux/bcd.h>
-#include <asm/time.h>
-#include <asm/tx4938/spi.h>
-
-#define	EPOCH		2000
-
-/* registers */
-#define Rx5C348_REG_SECOND	0
-#define Rx5C348_REG_MINUTE	1
-#define Rx5C348_REG_HOUR	2
-#define Rx5C348_REG_WEEK	3
-#define Rx5C348_REG_DAY	4
-#define Rx5C348_REG_MONTH	5
-#define Rx5C348_REG_YEAR	6
-#define Rx5C348_REG_ADJUST	7
-#define Rx5C348_REG_ALARM_W_MIN	8
-#define Rx5C348_REG_ALARM_W_HOUR	9
-#define Rx5C348_REG_ALARM_W_WEEK	10
-#define Rx5C348_REG_ALARM_D_MIN	11
-#define Rx5C348_REG_ALARM_D_HOUR	12
-#define Rx5C348_REG_CTL1	14
-#define Rx5C348_REG_CTL2	15
-
-/* register bits */
-#define Rx5C348_BIT_PM	0x20	/* REG_HOUR */
-#define Rx5C348_BIT_Y2K	0x80	/* REG_MONTH */
-#define Rx5C348_BIT_24H	0x20	/* REG_CTL1 */
-#define Rx5C348_BIT_XSTP	0x10	/* REG_CTL2 */
-
-/* commands */
-#define Rx5C348_CMD_W(addr)	(((addr) << 4) | 0x08)	/* single write */
-#define Rx5C348_CMD_R(addr)	(((addr) << 4) | 0x0c)	/* single read */
-#define Rx5C348_CMD_MW(addr)	(((addr) << 4) | 0x00)	/* burst write */
-#define Rx5C348_CMD_MR(addr)	(((addr) << 4) | 0x04)	/* burst read */
-
-static struct spi_dev_desc srtc_dev_desc = {
-	.baud 		= 1000000,	/* 1.0Mbps @ Vdd 2.0V */
-	.tcss		= 31,
-	.tcsh		= 1,
-	.tcsr		= 62,
-	/* 31us for Tcss (62us for Tcsr) is required for carry operation) */
-	.byteorder	= 1,		/* MSB-First */
-	.polarity	= 0,		/* High-Active */
-	.phase		= 1,		/* Shift-Then-Sample */
-
-};
-static int srtc_chipid;
-static int srtc_24h;
-
-static inline int
-spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
-{
-	unsigned char *inbufs[1], *outbufs[1];
-	unsigned int incounts[2], outcounts[2];
-	inbufs[0] = inbuf;
-	incounts[0] = count;
-	incounts[1] = 0;
-	outbufs[0] = outbuf;
-	outcounts[0] = count;
-	outcounts[1] = 0;
-	return txx9_spi_io(srtc_chipid, &srtc_dev_desc,
-			   inbufs, incounts, outbufs, outcounts, 0);
-}
-
-/* RTC-dependent code for time.c */
-
-static int
-rtc_rx5c348_set_time(unsigned long t)
-{
-	unsigned char inbuf[8];
-	struct rtc_time tm;
-	u8 year, month, day, hour, minute, second, century;
-
-	/* convert */
-	to_tm(t, &tm);
-
-	year = tm.tm_year % 100;
-	month = tm.tm_mon+1;	/* tm_mon starts from 0 to 11 */
-	day = tm.tm_mday;
-	hour = tm.tm_hour;
-	minute = tm.tm_min;
-	second = tm.tm_sec;
-	century = tm.tm_year / 100;
-
-	inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND);
-	BIN_TO_BCD(second);
-	inbuf[1] = second;
-	BIN_TO_BCD(minute);
-	inbuf[2] = minute;
-
-	if (srtc_24h) {
-		BIN_TO_BCD(hour);
-		inbuf[3] = hour;
-	} else {
-		/* hour 0 is AM12, noon is PM12 */
-		inbuf[3] = 0;
-		if (hour >= 12)
-			inbuf[3] = Rx5C348_BIT_PM;
-		hour = (hour + 11) % 12 + 1;
-		BIN_TO_BCD(hour);
-		inbuf[3] |= hour;
-	}
-	inbuf[4] = 0;	/* ignore week */
-	BIN_TO_BCD(day);
-	inbuf[5] = day;
-	BIN_TO_BCD(month);
-	inbuf[6] = month;
-	if (century >= 20)
-		inbuf[6] |= Rx5C348_BIT_Y2K;
-	BIN_TO_BCD(year);
-	inbuf[7] = year;
-	/* write in one transfer to avoid data inconsistency */
-	return spi_rtc_io(inbuf, NULL, 8);
-}
-
-static unsigned long
-rtc_rx5c348_get_time(void)
-{
-	unsigned char inbuf[8], outbuf[8];
-	unsigned int year, month, day, hour, minute, second;
-
-	inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND);
-	memset(inbuf + 1, 0, 7);
-	/* read in one transfer to avoid data inconsistency */
-	if (spi_rtc_io(inbuf, outbuf, 8))
-		return 0;
-	second = outbuf[1];
-	BCD_TO_BIN(second);
-	minute = outbuf[2];
-	BCD_TO_BIN(minute);
-	if (srtc_24h) {
-		hour = outbuf[3];
-		BCD_TO_BIN(hour);
-	} else {
-		hour = outbuf[3] & ~Rx5C348_BIT_PM;
-		BCD_TO_BIN(hour);
-		hour %= 12;
-		if (outbuf[3] & Rx5C348_BIT_PM)
-			hour += 12;
-	}
-	day = outbuf[5];
-	BCD_TO_BIN(day);
-	month = outbuf[6] & ~Rx5C348_BIT_Y2K;
-	BCD_TO_BIN(month);
-	year = outbuf[7];
-	BCD_TO_BIN(year);
-	year += EPOCH;
-
-	return mktime(year, month, day, hour, minute, second);
-}
-
-void __init
-rtc_rx5c348_init(int chipid)
-{
-	unsigned char inbuf[2], outbuf[2];
-	srtc_chipid = chipid;
-	/* turn on RTC if it is not on */
-	inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2);
-	inbuf[1] = 0;
-	spi_rtc_io(inbuf, outbuf, 2);
-	if (outbuf[1] & Rx5C348_BIT_XSTP) {
-		inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2);
-		inbuf[1] = 0;
-		spi_rtc_io(inbuf, NULL, 2);
-	}
-
-	inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1);
-	inbuf[1] = 0;
-	spi_rtc_io(inbuf, outbuf, 2);
-	if (outbuf[1] & Rx5C348_BIT_24H)
-		srtc_24h = 1;
-
-	/* set the function pointers */
-	rtc_mips_get_time = rtc_rx5c348_get_time;
-	rtc_mips_set_time = rtc_rx5c348_set_time;
-}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/Makefile b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
index 2269412..10c94e6 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/Makefile
+++ b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
@@ -6,4 +6,4 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y	+= prom.o setup.o irq.o spi_eeprom.o spi_txx9.o
+obj-y	+= prom.o setup.o irq.o spi_eeprom.o
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
index 2e96dbb..91aea7af 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
@@ -165,8 +165,6 @@
 	TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
 }
 
-extern void __init txx9_spi_irqinit(int irc_irq);
-
 void __init arch_init_irq(void)
 {
 	extern void tx4938_irq_init(void);
@@ -185,9 +183,5 @@
 	/* Onboard 10M Ether: High Active */
 	TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000040);
 
-	if (tx4938_ccfgptr->pcfg & TX4938_PCFG_SPI_SEL) {
-		txx9_spi_irqinit(RBTX4938_IRQ_IRC_SPI);
-        }
-
 	wbflush();
 }
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index f5d1ce7..6ed39a5 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -14,13 +14,13 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
-#include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/console.h>
 #include <linux/pci.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 
 #include <asm/wbflush.h>
 #include <asm/reboot.h>
@@ -35,6 +35,9 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #endif
+#include <linux/spi/spi.h>
+#include <asm/tx4938/spi.h>
+#include <asm/gpio.h>
 
 extern void rbtx4938_time_init(void) __init;
 extern char * __init prom_getcmdline(void);
@@ -349,7 +352,7 @@
 	static struct pci_dev dev;
 	static struct pci_bus bus;
 
-	dev.sysdata = (void *)hose;
+	dev.sysdata = bus.sysdata = hose;
 	dev.devfn = devfn;
 	bus.number = busnr;
 	bus.ops = hose->pci_ops;
@@ -382,8 +385,10 @@
 	printk("PCI: Checking 66MHz capabilities...\n");
 
 	for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
-		early_read_config_word(hose, top_bus, current_bus, pci_devfn,
-				       PCI_VENDOR_ID, &vid);
+		if (early_read_config_word(hose, top_bus, current_bus,
+					   pci_devfn, PCI_VENDOR_ID,
+					   &vid) != PCIBIOS_SUCCESSFUL)
+			continue;
 
 		if (vid == 0xffff) continue;
 
@@ -460,7 +465,6 @@
 	int extarb = !(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB);
 
 	PCIBIOS_MIN_IO = 0x00001000UL;
-	PCIBIOS_MIN_MEM = 0x01000000UL;
 
 	mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]);
 	io_base[0] = txboard_request_phys_region_shrink(&io_size[0]);
@@ -574,82 +578,43 @@
 #define	SEEPROM3_CS	1	/* IOC */
 #define	SRTC_CS	2	/* IOC */
 
-static int rbtx4938_spi_cs_func(int chipid, int on)
-{
-	unsigned char bit;
-	switch (chipid) {
-	case RBTX4938_SEEPROM1_CHIPID:
-		if (on)
-			tx4938_pioptr->dout &= ~(1 << SEEPROM1_CS);
-		else
-			tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
-		return 0;
-		break;
-	case RBTX4938_SEEPROM2_CHIPID:
-		bit = (1 << SEEPROM2_CS);
-		break;
-	case RBTX4938_SEEPROM3_CHIPID:
-		bit = (1 << SEEPROM3_CS);
-		break;
-	case RBTX4938_SRTC_CHIPID:
-		bit = (1 << SRTC_CS);
-		break;
-	default:
-		return -ENODEV;
-	}
-	/* bit1,2,4 are low active, bit3 is high active */
-	*rbtx4938_spics_ptr =
-		(*rbtx4938_spics_ptr & ~bit) |
-		((on ? (bit ^ 0x0b) : ~(bit ^ 0x0b)) & bit);
-	return 0;
-}
-
 #ifdef CONFIG_PCI
-extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
-
-int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr)
+static int __init rbtx4938_ethaddr_init(void)
 {
-	struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata;
-	static unsigned char dat[17];
-	static int read_dat = 0;
-	int ch = 0;
+	unsigned char dat[17];
+	unsigned char sum;
+	int i;
 
-	if (channel != &tx4938_pci_controller[1])
+	/* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
+	if (spi_eeprom_read(SEEPROM1_CS, 0, dat, sizeof(dat))) {
+		printk(KERN_ERR "seeprom: read error.\n");
 		return -ENODEV;
-	/* TX4938 PCIC1 */
-	switch (PCI_SLOT(dev->devfn)) {
-	case TX4938_PCIC_IDSEL_AD_TO_SLOT(31):
-		ch = 0;
-		break;
-	case TX4938_PCIC_IDSEL_AD_TO_SLOT(30):
-		ch = 1;
-		break;
-	default:
-		return -ENODEV;
+	} else {
+		if (strcmp(dat, "MAC") != 0)
+			printk(KERN_WARNING "seeprom: bad signature.\n");
+		for (i = 0, sum = 0; i < sizeof(dat); i++)
+			sum += dat[i];
+		if (sum)
+			printk(KERN_WARNING "seeprom: bad checksum.\n");
 	}
-	if (!read_dat) {
-		unsigned char sum;
-		int i;
-		read_dat = 1;
-		/* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
-		if (spi_eeprom_read(RBTX4938_SEEPROM1_CHIPID,
-				    0, dat, sizeof(dat))) {
-			printk(KERN_ERR "seeprom: read error.\n");
-		} else {
-			if (strcmp(dat, "MAC") != 0)
-				printk(KERN_WARNING "seeprom: bad signature.\n");
-			for (i = 0, sum = 0; i < sizeof(dat); i++)
-				sum += dat[i];
-			if (sum)
-				printk(KERN_WARNING "seeprom: bad checksum.\n");
-		}
+	for (i = 0; i < 2; i++) {
+		unsigned int slot = TX4938_PCIC_IDSEL_AD_TO_SLOT(31 - i);
+		unsigned int id = (1 << 8) | PCI_DEVFN(slot, 0); /* bus 1 */
+		struct platform_device *pdev;
+		if (!(tx4938_ccfgptr->pcfg &
+		      (i ? TX4938_PCFG_ETH1_SEL : TX4938_PCFG_ETH0_SEL)))
+			continue;
+		pdev = platform_device_alloc("tc35815-mac", id);
+		if (!pdev ||
+		    platform_device_add_data(pdev, &dat[4 + 6 * i], 6) ||
+		    platform_device_add(pdev))
+			platform_device_put(pdev);
 	}
-	memcpy(addr, &dat[4 + 6 * ch], 6);
 	return 0;
 }
+device_initcall(rbtx4938_ethaddr_init);
 #endif /* CONFIG_PCI */
 
-extern void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on));
 static void __init rbtx4938_spi_setup(void)
 {
 	/* set SPI_SEL */
@@ -657,7 +622,6 @@
 	/* chip selects for SPI devices */
 	tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
 	tx4938_pioptr->dir |= (1 << SEEPROM1_CS);
-	txx9_spi_init(TX4938_SPI_REG, rbtx4938_spi_cs_func);
 }
 
 static struct resource rbtx4938_fpga_resource;
@@ -896,10 +860,8 @@
 /* We use onchip r4k counter or TMR timer as our system wide timer
  * interrupt running at 100HZ. */
 
-extern void __init rtc_rx5c348_init(int chipid);
 void __init rbtx4938_time_init(void)
 {
-	rtc_rx5c348_init(RBTX4938_SRTC_CHIPID);
 	mips_hpt_frequency = txx9_cpu_clock / 2;
 }
 
@@ -1016,29 +978,6 @@
 	       *rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr);
 }
 
-#ifdef CONFIG_PROC_FS
-extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid);
-static int __init tx4938_spi_proc_setup(void)
-{
-	struct proc_dir_entry *tx4938_spi_eeprom_dir;
-
-	tx4938_spi_eeprom_dir = proc_mkdir("spi_eeprom", 0);
-
-	if (!tx4938_spi_eeprom_dir)
-		return -ENOMEM;
-
-	/* don't allow user access to RBTX4938_SEEPROM1_CHIPID
-	 * as it contains eth0 and eth1 MAC addresses
-	 */
-	spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM2_CHIPID);
-	spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM3_CHIPID);
-
-	return 0;
-}
-
-__initcall(tx4938_spi_proc_setup);
-#endif
-
 static int __init rbtx4938_ne_init(void)
 {
 	struct resource res[] = {
@@ -1057,3 +996,176 @@
 	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 device_initcall(rbtx4938_ne_init);
+
+/* GPIO support */
+
+static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock);
+
+static void rbtx4938_spi_gpio_set(unsigned gpio, int value)
+{
+	u8 val;
+	unsigned long flags;
+	gpio -= 16;
+	spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags);
+	val = *rbtx4938_spics_ptr;
+	if (value)
+		val |= 1 << gpio;
+	else
+		val &= ~(1 << gpio);
+	*rbtx4938_spics_ptr = val;
+	mmiowb();
+	spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags);
+}
+
+static int rbtx4938_spi_gpio_dir_out(unsigned gpio, int value)
+{
+	rbtx4938_spi_gpio_set(gpio, value);
+	return 0;
+}
+
+static DEFINE_SPINLOCK(tx4938_gpio_lock);
+
+static int tx4938_gpio_get(unsigned gpio)
+{
+	return tx4938_pioptr->din & (1 << gpio);
+}
+
+static void tx4938_gpio_set_raw(unsigned gpio, int value)
+{
+	u32 val;
+	val = tx4938_pioptr->dout;
+	if (value)
+		val |= 1 << gpio;
+	else
+		val &= ~(1 << gpio);
+	tx4938_pioptr->dout = val;
+}
+
+static void tx4938_gpio_set(unsigned gpio, int value)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&tx4938_gpio_lock, flags);
+	tx4938_gpio_set_raw(gpio, value);
+	mmiowb();
+	spin_unlock_irqrestore(&tx4938_gpio_lock, flags);
+}
+
+static int tx4938_gpio_dir_in(unsigned gpio)
+{
+	spin_lock_irq(&tx4938_gpio_lock);
+	tx4938_pioptr->dir &= ~(1 << gpio);
+	mmiowb();
+	spin_unlock_irq(&tx4938_gpio_lock);
+	return 0;
+}
+
+static int tx4938_gpio_dir_out(unsigned int gpio, int value)
+{
+	spin_lock_irq(&tx4938_gpio_lock);
+	tx4938_gpio_set_raw(gpio, value);
+	tx4938_pioptr->dir |= 1 << gpio;
+	mmiowb();
+	spin_unlock_irq(&tx4938_gpio_lock);
+	return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+	if (gpio < 16)
+		return tx4938_gpio_dir_in(gpio);
+	return -EINVAL;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+	if (gpio < 16)
+		return tx4938_gpio_dir_out(gpio, value);
+	if (gpio < 16 + 3)
+		return rbtx4938_spi_gpio_dir_out(gpio, value);
+	return -EINVAL;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+	if (gpio < 16)
+		return tx4938_gpio_get(gpio);
+	return 0;
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+	if (gpio < 16)
+		tx4938_gpio_set(gpio, value);
+	else
+		rbtx4938_spi_gpio_set(gpio, value);
+}
+
+/* SPI support */
+
+static void __init txx9_spi_init(unsigned long base, int irq)
+{
+	struct resource res[] = {
+		{
+			.start	= base,
+			.end	= base + 0x20 - 1,
+			.flags	= IORESOURCE_MEM,
+			.parent	= &tx4938_reg_resource,
+		}, {
+			.start	= irq,
+			.flags	= IORESOURCE_IRQ,
+		},
+	};
+	platform_device_register_simple("txx9spi", 0,
+					res, ARRAY_SIZE(res));
+}
+
+static int __init rbtx4938_spi_init(void)
+{
+	struct spi_board_info srtc_info = {
+		.modalias = "rs5c348",
+		.max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */
+		.bus_num = 0,
+		.chip_select = 16 + SRTC_CS,
+		/* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS  */
+		.mode = SPI_MODE_1 | SPI_CS_HIGH,
+	};
+	spi_register_board_info(&srtc_info, 1);
+	spi_eeprom_register(SEEPROM1_CS);
+	spi_eeprom_register(16 + SEEPROM2_CS);
+	spi_eeprom_register(16 + SEEPROM3_CS);
+	txx9_spi_init(TX4938_SPI_REG & 0xfffffffffULL, RBTX4938_IRQ_IRC_SPI);
+	return 0;
+}
+arch_initcall(rbtx4938_spi_init);
+
+/* Minimum CLK support */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	if (!strcmp(id, "spi-baseclk"))
+		return (struct clk *)(txx9_gbus_clock / 2 / 4);
+	return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return (unsigned long)clk;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
index 89596e6..4d6b4ad 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
@@ -10,209 +10,90 @@
  * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
  */
 #include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
 #include <asm/tx4938/spi.h>
-#include <asm/tx4938/tx4938.h>
 
-/* ATMEL 250x0 instructions */
-#define	ATMEL_WREN	0x06
-#define	ATMEL_WRDI	0x04
-#define ATMEL_RDSR	0x05
-#define ATMEL_WRSR	0x01
-#define	ATMEL_READ	0x03
-#define	ATMEL_WRITE	0x02
+#define AT250X0_PAGE_SIZE	8
 
-#define ATMEL_SR_BSY	0x01
-#define ATMEL_SR_WEN	0x02
-#define ATMEL_SR_BP0	0x04
-#define ATMEL_SR_BP1	0x08
+/* register board information for at25 driver */
+int __init spi_eeprom_register(int chipid)
+{
+	static struct spi_eeprom eeprom = {
+		.name = "at250x0",
+		.byte_len = 128,
+		.page_size = AT250X0_PAGE_SIZE,
+		.flags = EE_ADDR1,
+	};
+	struct spi_board_info info = {
+		.modalias = "at25",
+		.max_speed_hz = 1500000,	/* 1.5Mbps */
+		.bus_num = 0,
+		.chip_select = chipid,
+		.platform_data = &eeprom,
+		/* Mode 0: High-Active, Sample-Then-Shift */
+	};
 
-DEFINE_SPINLOCK(spi_eeprom_lock);
+	return spi_register_board_info(&info, 1);
+}
 
-static struct spi_dev_desc seeprom_dev_desc = {
-	.baud 		= 1500000,	/* 1.5Mbps */
-	.tcss		= 1,
-	.tcsh		= 1,
-	.tcsr		= 1,
-	.byteorder	= 1,		/* MSB-First */
-	.polarity	= 0,		/* High-Active */
-	.phase		= 0,		/* Sample-Then-Shift */
+/* simple temporary spi driver to provide early access to seeprom. */
 
+static struct read_param {
+	int chipid;
+	int address;
+	unsigned char *buf;
+	int len;
+} *read_param;
+
+static int __init early_seeprom_probe(struct spi_device *spi)
+{
+	int stat = 0;
+	u8 cmd[2];
+	int len = read_param->len;
+	char *buf = read_param->buf;
+	int address = read_param->address;
+
+	dev_info(&spi->dev, "spiclk %u KHz.\n",
+		 (spi->max_speed_hz + 500) / 1000);
+	if (read_param->chipid != spi->chip_select)
+		return -ENODEV;
+	while (len > 0) {
+		/* spi_write_then_read can only work with small chunk */
+		int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE;
+		cmd[0] = 0x03;	/* AT25_READ */
+		cmd[1] = address;
+		stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c);
+		buf += c;
+		len -= c;
+		address += c;
+	}
+	return stat;
+}
+
+static struct spi_driver early_seeprom_driver __initdata = {
+	.driver = {
+		.name	= "at25",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= early_seeprom_probe,
 };
-static inline int
-spi_eeprom_io(int chipid,
-	      unsigned char **inbufs, unsigned int *incounts,
-	      unsigned char **outbufs, unsigned int *outcounts)
+
+int __init spi_eeprom_read(int chipid, int address,
+			   unsigned char *buf, int len)
 {
-	return txx9_spi_io(chipid, &seeprom_dev_desc,
-			   inbufs, incounts, outbufs, outcounts, 0);
+	int ret;
+	struct read_param param = {
+		.chipid = chipid,
+		.address = address,
+		.buf = buf,
+		.len = len
+	};
+
+	read_param = &param;
+	ret = spi_register_driver(&early_seeprom_driver);
+	if (!ret)
+		spi_unregister_driver(&early_seeprom_driver);
+	return ret;
 }
-
-int spi_eeprom_write_enable(int chipid, int enable)
-{
-	unsigned char inbuf[1];
-	unsigned char *inbufs[1];
-	unsigned int incounts[2];
-	unsigned long flags;
-	int stat;
-	inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;
-	inbufs[0] = inbuf;
-	incounts[0] = sizeof(inbuf);
-	incounts[1] = 0;
-	spin_lock_irqsave(&spi_eeprom_lock, flags);
-	stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	return stat;
-}
-
-static int spi_eeprom_read_status_nolock(int chipid)
-{
-	unsigned char inbuf[2], outbuf[2];
-	unsigned char *inbufs[1], *outbufs[1];
-	unsigned int incounts[2], outcounts[2];
-	int stat;
-	inbuf[0] = ATMEL_RDSR;
-	inbuf[1] = 0;
-	inbufs[0] = inbuf;
-	incounts[0] = sizeof(inbuf);
-	incounts[1] = 0;
-	outbufs[0] = outbuf;
-	outcounts[0] = sizeof(outbuf);
-	outcounts[1] = 0;
-	stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
-	if (stat < 0)
-		return stat;
-	return outbuf[1];
-}
-
-int spi_eeprom_read_status(int chipid)
-{
-	unsigned long flags;
-	int stat;
-	spin_lock_irqsave(&spi_eeprom_lock, flags);
-	stat = spi_eeprom_read_status_nolock(chipid);
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	return stat;
-}
-
-int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
-{
-	unsigned char inbuf[2];
-	unsigned char *inbufs[2], *outbufs[2];
-	unsigned int incounts[2], outcounts[3];
-	unsigned long flags;
-	int stat;
-	inbuf[0] = ATMEL_READ;
-	inbuf[1] = address;
-	inbufs[0] = inbuf;
-	inbufs[1] = NULL;
-	incounts[0] = sizeof(inbuf);
-	incounts[1] = 0;
-	outbufs[0] = NULL;
-	outbufs[1] = buf;
-	outcounts[0] = 2;
-	outcounts[1] = len;
-	outcounts[2] = 0;
-	spin_lock_irqsave(&spi_eeprom_lock, flags);
-	stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	return stat;
-}
-
-int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
-{
-	unsigned char inbuf[2];
-	unsigned char *inbufs[2];
-	unsigned int incounts[3];
-	unsigned long flags;
-	int i, stat;
-
-	if (address / 8 != (address + len - 1) / 8)
-		return -EINVAL;
-	stat = spi_eeprom_write_enable(chipid, 1);
-	if (stat < 0)
-		return stat;
-	stat = spi_eeprom_read_status(chipid);
-	if (stat < 0)
-		return stat;
-	if (!(stat & ATMEL_SR_WEN))
-		return -EPERM;
-
-	inbuf[0] = ATMEL_WRITE;
-	inbuf[1] = address;
-	inbufs[0] = inbuf;
-	inbufs[1] = buf;
-	incounts[0] = sizeof(inbuf);
-	incounts[1] = len;
-	incounts[2] = 0;
-	spin_lock_irqsave(&spi_eeprom_lock, flags);
-	stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
-	if (stat < 0)
-		goto unlock_return;
-
-	/* write start.  max 10ms */
-	for (i = 10; i > 0; i--) {
-		int stat = spi_eeprom_read_status_nolock(chipid);
-		if (stat < 0)
-			goto unlock_return;
-		if (!(stat & ATMEL_SR_BSY))
-			break;
-		mdelay(1);
-	}
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	if (i == 0)
-		return -EIO;
-	return len;
- unlock_return:
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	return stat;
-}
-
-#ifdef CONFIG_PROC_FS
-#define MAX_SIZE	0x80	/* for ATMEL 25010 */
-static int spi_eeprom_read_proc(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
-{
-	unsigned int size = MAX_SIZE;
-	if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)
-		size = 0;
-	return size;
-}
-
-static int spi_eeprom_write_proc(struct file *file, const char *buffer,
-				 unsigned long count, void *data)
-{
-	unsigned int size = MAX_SIZE;
-	int i;
-	if (file->f_pos >= size)
-		return -EIO;
-	if (file->f_pos + count > size)
-		count = size - file->f_pos;
-	for (i = 0; i < count; i += 8) {
-		int len = count - i < 8 ? count - i : 8;
-		if (spi_eeprom_write((int)data, file->f_pos,
-				     (unsigned char *)buffer, len) < 0) {
-			count = -EIO;
-			break;
-		}
-		buffer += len;
-		file->f_pos += len;
-	}
-	return count;
-}
-
-__init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
-{
-	struct proc_dir_entry *entry;
-	char name[128];
-	sprintf(name, "seeprom-%d", chipid);
-	entry = create_proc_entry(name, 0600, dir);
-	if (entry) {
-		entry->read_proc = spi_eeprom_read_proc;
-		entry->write_proc = spi_eeprom_write_proc;
-		entry->data = (void *)chipid;
-	}
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
deleted file mode 100644
index 08b20cd..0000000
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <asm/tx4938/spi.h>
-#include <asm/tx4938/tx4938.h>
-
-static int (*txx9_spi_cs_func)(int chipid, int on);
-static DEFINE_SPINLOCK(txx9_spi_lock);
-
-extern unsigned int txx9_gbus_clock;
-
-#define SPI_FIFO_SIZE	4
-
-void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on))
-{
-	txx9_spi_cs_func = cs_func;
-	/* enter config mode */
-	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
-}
-
-static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait);
-
-static irqreturn_t txx9_spi_interrupt(int irq, void *dev_id)
-{
-	/* disable rx intr */
-	tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE;
-	wake_up(&txx9_spi_wait);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction txx9_spi_action = {
-	.handler	= txx9_spi_interrupt,
-	.name		= "spi",
-};
-
-void __init txx9_spi_irqinit(int irc_irq)
-{
-	setup_irq(irc_irq, &txx9_spi_action);
-}
-
-int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
-		unsigned char **inbufs, unsigned int *incounts,
-		unsigned char **outbufs, unsigned int *outcounts,
-		int cansleep)
-{
-	unsigned int incount, outcount;
-	unsigned char *inp, *outp;
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&txx9_spi_lock, flags);
-	if ((tx4938_spiptr->mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE) {
-		spin_unlock_irqrestore(&txx9_spi_lock, flags);
-		return -EBUSY;
-	}
-	/* enter config mode */
-	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
-	tx4938_spiptr->cr0 =
-		(desc->byteorder ? TXx9_SPCR0_SBOS : 0) |
-		(desc->polarity ? TXx9_SPCR0_SPOL : 0) |
-		(desc->phase ? TXx9_SPCR0_SPHA : 0) |
-		0x08;
-	tx4938_spiptr->cr1 =
-		(((TXX9_IMCLK + desc->baud) / (2 * desc->baud) - 1) << 8) |
-		0x08 /* 8 bit only */;
-	/* enter active mode */
-	tx4938_spiptr->mcr = TXx9_SPMCR_ACTIVE;
-	spin_unlock_irqrestore(&txx9_spi_lock, flags);
-
-	/* CS ON */
-	if ((ret = txx9_spi_cs_func(chipid, 1)) < 0) {
-		spin_unlock_irqrestore(&txx9_spi_lock, flags);
-		return ret;
-	}
-	udelay(desc->tcss);
-
-	/* do scatter IO */
-	inp = inbufs ? *inbufs : NULL;
-	outp = outbufs ? *outbufs : NULL;
-	incount = 0;
-	outcount = 0;
-	while (1) {
-		unsigned char data;
-		unsigned int count;
-		int i;
-		if (!incount) {
-			incount = incounts ? *incounts++ : 0;
-			inp = (incount && inbufs) ? *inbufs++ : NULL;
-		}
-		if (!outcount) {
-			outcount = outcounts ? *outcounts++ : 0;
-			outp = (outcount && outbufs) ? *outbufs++ : NULL;
-		}
-		if (!inp && !outp)
-			break;
-		count = SPI_FIFO_SIZE;
-		if (incount)
-			count = min(count, incount);
-		if (outcount)
-			count = min(count, outcount);
-
-		/* now tx must be idle... */
-		while (!(tx4938_spiptr->sr & TXx9_SPSR_SIDLE))
-			;
-
-		tx4938_spiptr->cr0 =
-			(tx4938_spiptr->cr0 & ~TXx9_SPCR0_RXIFL_MASK) |
-			((count - 1) << 12);
-		if (cansleep) {
-			/* enable rx intr */
-			tx4938_spiptr->cr0 |= TXx9_SPCR0_RBSIE;
-		}
-		/* send */
-		for (i = 0; i < count; i++)
-			tx4938_spiptr->dr = inp ? *inp++ : 0;
-		/* wait all rx data */
-		if (cansleep) {
-			wait_event(txx9_spi_wait,
-				   tx4938_spiptr->sr & TXx9_SPSR_SRRDY);
-		} else {
-			while (!(tx4938_spiptr->sr & TXx9_SPSR_RBSI))
-				;
-		}
-		/* receive */
-		for (i = 0; i < count; i++) {
-			data = tx4938_spiptr->dr;
-			if (outp)
-				*outp++ = data;
-		}
-		if (incount)
-			incount -= count;
-		if (outcount)
-			outcount -= count;
-	}
-
-	/* CS OFF */
-	udelay(desc->tcsh);
-	txx9_spi_cs_func(chipid, 0);
-	udelay(desc->tcsr);
-
-	spin_lock_irqsave(&txx9_spi_lock, flags);
-	/* enter config mode */
-	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
-	spin_unlock_irqrestore(&txx9_spi_lock, flags);
-
-	return 0;
-}
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index f842783..d0d84ec 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -2,4 +2,4 @@
 # Makefile for common code of the NEC VR4100 series.
 #
 
-obj-y	+= bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
+obj-y	+= bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o rtc.o siu.o type.o
diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c
new file mode 100644
index 0000000..d21f6f2
--- /dev/null
+++ b/arch/mips/vr41xx/common/giu.c
@@ -0,0 +1,122 @@
+/*
+ *  NEC VR4100 series GIU platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/irq.h>
+
+static struct resource giu_50pins_pullupdown_resource[] __initdata = {
+	{
+		.start	= 0x0b000100,
+		.end	= 0x0b00011f,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= 0x0b0002e0,
+		.end	= 0x0b0002e3,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= GIUINT_IRQ,
+		.end	= GIUINT_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource giu_36pins_resource[] __initdata = {
+	{
+		.start	= 0x0f000140,
+		.end	= 0x0f00015f,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= GIUINT_IRQ,
+		.end	= GIUINT_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource giu_48pins_resource[] __initdata = {
+	{
+		.start	= 0x0f000140,
+		.end	= 0x0f000167,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= GIUINT_IRQ,
+		.end	= GIUINT_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static int __init vr41xx_giu_add(void)
+{
+	struct platform_device *pdev;
+	struct resource *res;
+	unsigned int num;
+	int retval;
+
+	pdev = platform_device_alloc("GIU", -1);
+	if (!pdev)
+		return -ENOMEM;
+
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		pdev->id = GPIO_50PINS_PULLUPDOWN;
+		res = giu_50pins_pullupdown_resource;
+		num = ARRAY_SIZE(giu_50pins_pullupdown_resource);
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+		pdev->id = GPIO_36PINS;
+		res = giu_36pins_resource;
+		num = ARRAY_SIZE(giu_36pins_resource);
+		break;
+	case CPU_VR4133:
+		pdev->id = GPIO_48PINS_EDGE_SELECT;
+		res = giu_48pins_resource;
+		num = ARRAY_SIZE(giu_48pins_resource);
+		break;
+	default:
+		retval = -ENODEV;
+		goto err_free_device;
+	}
+
+	retval = platform_device_add_resources(pdev, res, num);
+	if (retval)
+		goto err_free_device;
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto err_free_device;
+
+	return 0;
+
+err_free_device:
+	platform_device_put(pdev);
+
+	return retval;
+}
+device_initcall(vr41xx_giu_add);
diff --git a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c
new file mode 100644
index 0000000..cce605b
--- /dev/null
+++ b/arch/mips/vr41xx/common/rtc.c
@@ -0,0 +1,117 @@
+/*
+ *  NEC VR4100 series RTC platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/irq.h>
+
+static struct resource rtc_type1_resource[] __initdata = {
+	{
+		.start	= 0x0b0000c0,
+		.end	= 0x0b0000df,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= 0x0b0001c0,
+		.end	= 0x0b0001df,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= ELAPSEDTIME_IRQ,
+		.end	= ELAPSEDTIME_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= RTCLONG1_IRQ,
+		.end	= RTCLONG1_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource rtc_type2_resource[] __initdata = {
+	{
+		.start	= 0x0f000100,
+		.end	= 0x0f00011f,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= 0x0f000120,
+		.end	= 0x0f00013f,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= ELAPSEDTIME_IRQ,
+		.end	= ELAPSEDTIME_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= RTCLONG1_IRQ,
+		.end	= RTCLONG1_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static int __init vr41xx_rtc_add(void)
+{
+	struct platform_device *pdev;
+	struct resource *res;
+	unsigned int num;
+	int retval;
+
+	pdev = platform_device_alloc("RTC", -1);
+	if (!pdev)
+		return -ENOMEM;
+
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		res = rtc_type1_resource;
+		num = ARRAY_SIZE(rtc_type1_resource);
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		res = rtc_type2_resource;
+		num = ARRAY_SIZE(rtc_type2_resource);
+		break;
+	default:
+		retval = -ENODEV;
+		goto err_free_device;
+	}
+
+	retval = platform_device_add_resources(pdev, res, num);
+	if (retval)
+		goto err_free_device;
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto err_free_device;
+
+	return 0;
+
+err_free_device:
+	platform_device_put(pdev);
+
+	return retval;
+}
+device_initcall(vr41xx_rtc_add);
diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c
new file mode 100644
index 0000000..a1e7741
--- /dev/null
+++ b/arch/mips/vr41xx/common/siu.c
@@ -0,0 +1,120 @@
+/*
+ *  NEC VR4100 series SIU platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/siu.h>
+
+static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = {
+	PORT_VR41XX_SIU,
+	PORT_UNKNOWN,
+};
+
+static struct resource siu_type1_resource[] __initdata = {
+	{
+		.start	= 0x0c000000,
+		.end	= 0x0c00000a,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= SIU_IRQ,
+		.end	= SIU_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = {
+	PORT_VR41XX_SIU,
+	PORT_VR41XX_DSIU,
+};
+
+static struct resource siu_type2_resource[] __initdata = {
+	{
+		.start	= 0x0f000800,
+		.end	= 0x0f00080a,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= 0x0f000820,
+		.end	= 0x0f000829,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= SIU_IRQ,
+		.end	= SIU_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= DSIU_IRQ,
+		.end	= DSIU_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static int __init vr41xx_siu_add(void)
+{
+	struct platform_device *pdev;
+	struct resource *res;
+	unsigned int num;
+	int retval;
+
+	pdev = platform_device_alloc("SIU", -1);
+	if (!pdev)
+		return -ENOMEM;
+
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		pdev->dev.platform_data = siu_type1_ports;
+		res = siu_type1_resource;
+		num = ARRAY_SIZE(siu_type1_resource);
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		pdev->dev.platform_data = siu_type2_ports;
+		res = siu_type2_resource;
+		num = ARRAY_SIZE(siu_type2_resource);
+		break;
+	default:
+		retval = -ENODEV;
+		goto err_free_device;
+	}
+
+	retval = platform_device_add_resources(pdev, res, num);
+	if (retval)
+		goto err_free_device;
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto err_free_device;
+
+	return 0;
+
+err_free_device:
+	platform_device_put(pdev);
+
+	return retval;
+}
+device_initcall(vr41xx_siu_add);
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
index d86e157..f2042e6 100644
--- a/arch/parisc/hpux/fs.c
+++ b/arch/parisc/hpux/fs.c
@@ -21,6 +21,7 @@
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/file.h>
@@ -69,7 +70,6 @@
 };
 
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
 
 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
 		u64 ino, unsigned d_type)
@@ -77,7 +77,7 @@
 	struct hpux_dirent __user * dirent;
 	struct getdents_callback * buf = (struct getdents_callback *) __buf;
 	ino_t d_ino;
-	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+	int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(long));
 
 	buf->error = -EINVAL;	/* only used if we fail.. */
 	if (reclen > buf->count)
@@ -102,7 +102,6 @@
 }
 
 #undef NAME_OFFSET
-#undef ROUND_UP
 
 int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned int count)
 {
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 0dc924cc..395bbce 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/pagemap.h>
-
+#include <linux/sched.h>
 #include <asm/pdc.h>
 #include <asm/cache.h>
 #include <asm/cacheflush.h>
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 8474f9e..42598ab 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -954,21 +954,6 @@
 	/* NOTE: Need to enable interrupts incase we schedule. */
 	ssm     PSW_SM_I, %r0
 
-	/* Check for software interrupts */
-
-	.import irq_stat,data
-
-	load32	irq_stat,%r19
-#ifdef CONFIG_SMP
-	mfctl   %cr30,%r1
-	ldw	TI_CPU(%r1),%r1 /* get cpu # - int */
-	/* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
-	** irq_stat[] is defined using ____cacheline_aligned.
-	*/
-	SHLREG	%r1,L1_CACHE_SHIFT,%r20
-	add     %r19,%r20,%r19	/* now have &irq_stat[smp_processor_id()] */
-#endif /* CONFIG_SMP */
-
 intr_check_resched:
 
 	/* check for reschedule */
@@ -2034,10 +2019,9 @@
 	STREG     %r28,TASK_PT_GR28(%r1)
 
 #ifdef CONFIG_HPUX
-
 /* <linux/personality.h> cannot be easily included */
 #define PER_HPUX 0x10
-	LDREG     TASK_PERSONALITY(%r1),%r19
+	ldw	TASK_PERSONALITY(%r1),%r19
 
 	/* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
 	ldo	  -PER_HPUX(%r19), %r19
@@ -2055,24 +2039,6 @@
 	 */
 	loadgp
 
-syscall_check_bh:
-
-	/* Check for software interrupts */
-
-	.import irq_stat,data
-
-	load32	irq_stat,%r19
-
-#ifdef CONFIG_SMP
-	/* sched.h: int processor */
-	/* %r26 is used as scratch register to index into irq_stat[] */
-	ldw     TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
-
-	/* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
-	SHLREG	%r26,L1_CACHE_SHIFT,%r20
-	add     %r19,%r20,%r19	/* now have &irq_stat[smp_processor_id()] */
-#endif /* CONFIG_SMP */
-
 syscall_check_resched:
 
 	/* check for reschedule */
@@ -2114,7 +2080,7 @@
 	/* Are we being ptraced? */
 	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
 
-	LDREG	TASK_PTRACE(%r1), %r19
+	ldw	TASK_PTRACE(%r1), %r19
 	bb,<	%r19,31,syscall_restore_rfi
 	nop
 
@@ -2244,7 +2210,7 @@
 #else
 	nop
 #endif
-	b       syscall_check_bh  /* if resched, we start over again */
+	b	syscall_check_resched	/* if resched, we start over again */
 	nop
 ENDPROC(syscall_exit)
 
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 39dc835..fd6552c 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -634,7 +634,7 @@
  * pdc_stable_read - Read data from Stable Storage.
  * @staddr: Stable Storage address to access.
  * @memaddr: The memory address where Stable Storage data shall be copied.
- * @count: number of bytes to transfert. count is multiple of 4.
+ * @count: number of bytes to transfer. count is multiple of 4.
  *
  * This PDC call reads from the Stable Storage address supplied in staddr
  * and copies count bytes to the memory address memaddr.
@@ -660,7 +660,7 @@
  * pdc_stable_write - Write data to Stable Storage.
  * @staddr: Stable Storage address to access.
  * @memaddr: The memory address where Stable Storage data shall be read from.
- * @count: number of bytes to transfert. count is multiple of 4.
+ * @count: number of bytes to transfer. count is multiple of 4.
  *
  * This PDC call reads count bytes from the supplied memaddr address,
  * and copies count bytes to the Stable Storage address staddr.
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
index 18ba4cb..04848b2 100644
--- a/arch/parisc/kernel/hardware.c
+++ b/arch/parisc/kernel/hardware.c
@@ -38,7 +38,7 @@
  *	so don't reference this table after starting the init process
  */
  
-static struct hp_hardware hp_hardware_list[] __initdata = {
+static struct hp_hardware hp_hardware_list[] __devinitdata = {
 	{HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
 	{HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
 	{HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
@@ -1219,7 +1219,7 @@
 	unsigned short model;
 	unsigned short mask;
 	enum cpu_type cpu;
-} hp_cpu_type_mask_list[] __initdata = {
+} hp_cpu_type_mask_list[] __devinitdata = {
 
 	{ 0x0000, 0x0ff0, pcx    },  /* 0x0000 - 0x000f */
 	{ 0x0048, 0x0ff0, pcxl   },  /* 0x0040 - 0x004f */
@@ -1296,10 +1296,11 @@
 	{ 0x05f0, 0x0ff0, pcxw2  },  /* 0x05f0 - 0x05ff */
 	{ 0x0600, 0x0fe0, pcxl   },  /* 0x0600 - 0x061f */
 	{ 0x0880, 0x0ff0, mako   },  /* 0x0880 - 0x088f */
+	{ 0x0890, 0x0ff0, mako2  },  /* 0x0890 - 0x089f */
 	{ 0x0000, 0x0000, pcx    }	/* terminate table */
 };
 
-char *cpu_name_version[][2] = {
+const char * const cpu_name_version[][2] = {
 	[pcx]	= { "PA7000 (PCX)",	"1.0" },
 	[pcxs]	= { "PA7000 (PCX-S)",	"1.1a" },
 	[pcxt]	= { "PA7100 (PCX-T)",	"1.1b" },
@@ -1311,10 +1312,11 @@
 	[pcxw]	= { "PA8500 (PCX-W)",	"2.0" },
 	[pcxw_]	= { "PA8600 (PCX-W+)",	"2.0" },
 	[pcxw2]	= { "PA8700 (PCX-W2)",	"2.0" },
-	[mako]	= { "PA8800 (Mako)",	"2.0" }
+	[mako]	= { "PA8800 (Mako)",	"2.0" },
+	[mako2] = { "PA8900 (Shortfin)",	"2.0" }
 };
 
-const char * __init
+const char * __devinit
 parisc_hardware_description(struct parisc_device_id *id)
 {
 	struct hp_hardware *listptr;
@@ -1353,7 +1355,7 @@
 
 
 /* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */
-enum cpu_type __init
+enum cpu_type __cpuinit
 parisc_get_cpu_type(unsigned long hversion)
 {
 	struct hp_cpu_type_mask *ptr;
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
index d8baa15..43b41df 100644
--- a/arch/parisc/kernel/hpmc.S
+++ b/arch/parisc/kernel/hpmc.S
@@ -295,8 +295,5 @@
 	b .
 	nop
 ENDPROC(os_hpmc)
-
-	/* this label used to compute os_hpmc checksum */
-ENTRY(os_hpmc_end)
-
+ENTRY(os_hpmc_end)	/* this label used to compute os_hpmc checksum */
 	nop
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index c5c9125..76ce5e3 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -46,14 +46,10 @@
 static volatile unsigned long cpu_eiem = 0;
 
 /*
-** ack bitmap ... habitually set to 1, but reset to zero
+** local ACK bitmap ... habitually set to 1, but reset to zero
 ** between ->ack() and ->end() of the interrupt to prevent
 ** re-interruption of a processing interrupt.
 */
-static volatile unsigned long global_ack_eiem = ~0UL;
-/*
-** Local bitmap, same as above but for per-cpu interrupts
-*/
 static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL;
 
 static void cpu_disable_irq(unsigned int irq)
@@ -94,13 +90,11 @@
 	int cpu = smp_processor_id();
 
 	/* Clear in EIEM so we can no longer process */
-	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
-		per_cpu(local_ack_eiem, cpu) &= ~mask;
-	else
-		global_ack_eiem &= ~mask;
+	per_cpu(local_ack_eiem, cpu) &= ~mask;
 
 	/* disable the interrupt */
-	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+	set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
+
 	/* and now ack it */
 	mtctl(mask, 23);
 }
@@ -111,13 +105,10 @@
 	int cpu = smp_processor_id();
 
 	/* set it in the eiems---it's no longer in process */
-	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
-		per_cpu(local_ack_eiem, cpu) |= mask;
-	else
-		global_ack_eiem |= mask;
+	per_cpu(local_ack_eiem, cpu) |= mask;
 
 	/* enable the interrupt */
-	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+	set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
 }
 
 #ifdef CONFIG_SMP
@@ -354,8 +345,7 @@
 	local_irq_disable();
 	irq_enter();
 
-	eirr_val = mfctl(23) & cpu_eiem & global_ack_eiem &
-		per_cpu(local_ack_eiem, cpu);
+	eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu);
 	if (!eirr_val)
 		goto set_out;
 	irq = eirr_to_irq(eirr_val);
@@ -381,7 +371,7 @@
 	return;
 
  set_out:
-	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+	set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
 	goto out;
 }
 
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index 0c3aecb..23c1388 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -34,7 +35,6 @@
 #include <asm/tlbflush.h>	/* for purge_tlb_*() macros */
 
 static struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
-static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
 static unsigned long pcxl_used_bytes __read_mostly = 0;
 static unsigned long pcxl_used_pages __read_mostly = 0;
 
@@ -330,6 +330,54 @@
 	dump_resmap();
 }
 
+static int proc_pcxl_dma_show(struct seq_file *m, void *v)
+{
+#if 0
+	u_long i = 0;
+	unsigned long *res_ptr = (u_long *)pcxl_res_map;
+#endif
+	unsigned long total_pages = pcxl_res_size << 3;   /* 8 bits per byte */
+
+	seq_printf(m, "\nDMA Mapping Area size    : %d bytes (%ld pages)\n",
+		PCXL_DMA_MAP_SIZE, total_pages);
+
+	seq_printf(m, "Resource bitmap : %d bytes\n", pcxl_res_size);
+
+	seq_puts(m,  "     	  total:    free:    used:   % used:\n");
+	seq_printf(m, "blocks  %8d %8ld %8ld %8ld%%\n", pcxl_res_size,
+		pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes,
+		(pcxl_used_bytes * 100) / pcxl_res_size);
+
+	seq_printf(m, "pages   %8ld %8ld %8ld %8ld%%\n", total_pages,
+		total_pages - pcxl_used_pages, pcxl_used_pages,
+		(pcxl_used_pages * 100 / total_pages));
+
+#if 0
+	seq_puts(m, "\nResource bitmap:");
+
+	for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
+		if ((i & 7) == 0)
+		    seq_puts(m,"\n   ");
+		seq_printf(m, "%s %08lx", buf, *res_ptr);
+	}
+#endif
+	seq_putc(m, '\n');
+	return 0;
+}
+
+static int proc_pcxl_dma_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_pcxl_dma_show, NULL);
+}
+
+static const struct file_operations proc_pcxl_dma_ops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_pcxl_dma_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static int __init
 pcxl_dma_init(void)
 {
@@ -348,9 +396,10 @@
 			"pcxl_dma_init: Unable to create gsc /proc dir entry\n");
 	else {
 		struct proc_dir_entry* ent;
-		ent = create_proc_info_entry("pcxl_dma", 0,
-				proc_gsc_root, pcxl_proc_info);
-		if (!ent)
+		ent = create_proc_entry("pcxl_dma", 0, proc_gsc_root);
+		if (ent)
+			ent->proc_fops = &proc_pcxl_dma_ops;
+		else
 			printk(KERN_WARNING
 				"pci-dma.c: Unable to create pcxl_dma /proc entry.\n");
 	}
@@ -551,40 +600,3 @@
 	.dma_sync_sg_for_cpu =		pa11_dma_sync_sg_for_cpu,
 	.dma_sync_sg_for_device =	pa11_dma_sync_sg_for_device,
 };
-
-
-static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
-{
-#if 0
-	u_long i = 0;
-	unsigned long *res_ptr = (u_long *)pcxl_res_map;
-#endif
-	unsigned long total_pages = pcxl_res_size << 3;   /* 8 bits per byte */
-
-	sprintf(buf, "\nDMA Mapping Area size    : %d bytes (%ld pages)\n",
-		PCXL_DMA_MAP_SIZE, total_pages);
-	
-	sprintf(buf, "%sResource bitmap : %d bytes\n", buf, pcxl_res_size);
-
-	strcat(buf,  "     	  total:    free:    used:   % used:\n");
-	sprintf(buf, "%sblocks  %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size,
-		pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes,
-		(pcxl_used_bytes * 100) / pcxl_res_size);
-
-	sprintf(buf, "%spages   %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
-		total_pages - pcxl_used_pages, pcxl_used_pages,
-		(pcxl_used_pages * 100 / total_pages));
-
-#if 0
-	strcat(buf, "\nResource bitmap:");
-
-	for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
-		if ((i & 7) == 0)
-		    strcat(buf,"\n   ");
-		sprintf(buf, "%s %08lx", buf, *res_ptr);
-	}
-#endif
-	strcat(buf, "\n");
-	return strlen(buf);
-}
-
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index a46bc62b..89d6d5a 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -171,7 +171,7 @@
 
 /*
  * Write control bitmasks for Pa-8700 processor given
- * somethings have changed slightly.
+ * some things have changed slightly.
  */
 static const uint64_t perf_bitmasks_piranha[] = {
 	0x0000000000000000ul,     /* first dbl word must be zero */
@@ -511,10 +511,12 @@
 	} else if (boot_cpu_data.cpu_type == pcxw ||
 		 boot_cpu_data.cpu_type == pcxw_ ||
 		 boot_cpu_data.cpu_type == pcxw2 ||
-		 boot_cpu_data.cpu_type == mako) {
+		 boot_cpu_data.cpu_type == mako ||
+		 boot_cpu_data.cpu_type == mako2) {
 		perf_processor_interface = CUDA_INTF;
 		if (boot_cpu_data.cpu_type == pcxw2 ||
-		    boot_cpu_data.cpu_type == mako) 
+		    boot_cpu_data.cpu_type == mako ||
+		    boot_cpu_data.cpu_type == mako2)
 			bitmask_array = perf_bitmasks_piranha;
 	} else {
 		perf_processor_interface = UNKNOWN_INTF;
@@ -574,27 +576,27 @@
 		if (!perf_rdr_read_ubuf(16, userbuf))
 			return -13;
 
-		/* Counter0 is bits 1398 thru 1429 */
+		/* Counter0 is bits 1398 to 1429 */
 		tmp64 =  (userbuf[21] << 22) & 0x00000000ffc00000;
 		tmp64 |= (userbuf[22] >> 42) & 0x00000000003fffff;
 		/* OR sticky0 (bit 1430) to counter0 bit 32 */
 		tmp64 |= (userbuf[22] >> 10) & 0x0000000080000000;
 		raddr[0] = (uint32_t)tmp64;
 
-		/* Counter1 is bits 1431 thru 1462 */
+		/* Counter1 is bits 1431 to 1462 */
 		tmp64 =  (userbuf[22] >> 9) & 0x00000000ffffffff;
 		/* OR sticky1 (bit 1463) to counter1 bit 32 */
 		tmp64 |= (userbuf[22] << 23) & 0x0000000080000000;
 		raddr[1] = (uint32_t)tmp64;
 
-		/* Counter2 is bits 1464 thru 1495 */
+		/* Counter2 is bits 1464 to 1495 */
 		tmp64 =  (userbuf[22] << 24) & 0x00000000ff000000;
 		tmp64 |= (userbuf[23] >> 40) & 0x0000000000ffffff;
 		/* OR sticky2 (bit 1496) to counter2 bit 32 */
 		tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000;
 		raddr[2] = (uint32_t)tmp64;
 		
-		/* Counter3 is bits 1497 thru 1528 */
+		/* Counter3 is bits 1497 to 1528 */
 		tmp64 =  (userbuf[23] >> 7) & 0x00000000ffffffff;
 		/* OR sticky3 (bit 1529) to counter3 bit 32 */
 		tmp64 |= (userbuf[23] << 25) & 0x0000000080000000;
@@ -616,7 +618,7 @@
 		userbuf[23] = 0;
 
 		/* 
-		 * Write back the zero'ed bytes + the image given
+		 * Write back the zeroed bytes + the image given
 		 * the read was destructive.
 		 */
 		perf_rdr_write(16, userbuf);
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 0dd3847..3556648 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -381,6 +381,10 @@
 	struct unwind_frame_info info;
 	unsigned long ip;
 	int count = 0;
+
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
 	/*
 	 * These bracket the sleeping functions..
 	 */
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index dd5d0cb..549f548 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -33,7 +33,7 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
-
+#include <asm/param.h>
 #include <asm/cache.h>
 #include <asm/hardware.h>	/* for register_parisc_driver() stuff */
 #include <asm/processor.h>
@@ -63,7 +63,7 @@
 ** will call register_parisc_driver(&cpu_driver) before calling do_inventory().
 **
 ** The goal of consolidating CPU initialization into one place is
-** to make sure all CPU's get initialized the same way.
+** to make sure all CPUs get initialized the same way.
 ** The code path not shared is how PDC hands control of the CPU to the OS.
 ** The initialization of OS data structures is the same (done below).
 */
@@ -76,7 +76,7 @@
  * (return 1).  If so, initialize the chip and tell other partners in crime 
  * they have work to do.
  */
-static int __init processor_probe(struct parisc_device *dev)
+static int __cpuinit processor_probe(struct parisc_device *dev)
 {
 	unsigned long txn_addr;
 	unsigned long cpuid;
@@ -166,7 +166,7 @@
 #endif
 
 	/*
-	** CONFIG_SMP: init_smp_config() will attempt to get CPU's into
+	** CONFIG_SMP: init_smp_config() will attempt to get CPUs into
 	** OS control. RENDEZVOUS is the default state - see mem_set above.
 	**	p->state = STATE_RENDEZVOUS;
 	*/
@@ -334,7 +334,7 @@
 }
 
 /*
- * Display cpu info for all cpu's.
+ * Display CPU info for all CPUs.
  */
 int
 show_cpuinfo (struct seq_file *m, void *v)
@@ -381,19 +381,19 @@
 	return 0;
 }
 
-static struct parisc_device_id processor_tbl[] __read_mostly = {
+static const struct parisc_device_id processor_tbl[] = {
 	{ HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID },
 	{ 0, }
 };
 
-static struct parisc_driver cpu_driver __read_mostly = {
+static struct parisc_driver cpu_driver = {
 	.name		= "CPU",
 	.id_table	= processor_tbl,
 	.probe		= processor_probe
 };
 
 /**
- * processor_init - Processor initalization procedure.
+ * processor_init - Processor initialization procedure.
  *
  * Register this driver.
  */
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 8a0db37..26ec774 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -87,10 +87,9 @@
 	switch (request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
-		int copied;
-
 #ifdef CONFIG_64BIT
 		if (__is_compat_task(child)) {
+			int copied;
 			unsigned int tmp;
 
 			addr &= 0xffffffffL;
@@ -105,15 +104,7 @@
 		}
 		else
 #endif
-		{
-			unsigned long tmp;
-
-			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-			ret = -EIO;
-			if (copied != sizeof(tmp))
-				goto out_tsk;
-			ret = put_user(tmp,(unsigned long *) data);
-		}
+			ret = generic_ptrace_peekdata(child, addr, data);
 		goto out_tsk;
 	}
 
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 9818919..c44b8c5 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -45,7 +45,7 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 
-char	__initdata command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
 struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
@@ -162,7 +162,7 @@
 }
 
 /*
- * Display cpu info for all cpu's.
+ * Display CPU info for all CPUs.
  * for parisc this is in processor.c
  */
 extern int show_cpuinfo (struct seq_file *m, void *v);
@@ -225,6 +225,7 @@
                 }
                 break;
 	case mako:
+	case mako2:
                 if (NULL == proc_mckinley_root)
                 {
                         proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
index e39b38a..c780084 100644
--- a/arch/parisc/kernel/signal32.h
+++ b/arch/parisc/kernel/signal32.h
@@ -113,7 +113,7 @@
 /* In a deft move of uber-hackery, we decide to carry the top half of all
  * 64-bit registers in a non-portable, non-ABI, hidden structure.
  * Userspace can read the hidden structure if it *wants* but is never
- * guaranteed to be in the same place. Infact the uc_sigmask from the
+ * guaranteed to be in the same place. In fact the uc_sigmask from the
  * ucontext_t structure may push the hidden register file downards
  */
 struct compat_regfile {
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 6ba9257..04c7e1d 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -8,7 +8,7 @@
 ** Lots of stuff stolen from arch/alpha/kernel/smp.c
 ** ...and then parisc stole from arch/ia64/kernel/smp.c. Thanks David! :^)
 **
-** Thanks to John Curry and Ullas Ponnadi. I learned alot from their work.
+** Thanks to John Curry and Ullas Ponnadi. I learned a lot from their work.
 ** -grant (1/12/2001)
 **
 **	This program is free software; you can redistribute it and/or modify
@@ -419,7 +419,7 @@
 		BUG();
 	enter_lazy_tlb(&init_mm, current);
 
-	init_IRQ();   /* make sure no IRQ's are enabled or pending */
+	init_IRQ();   /* make sure no IRQs are enabled or pending */
 	start_cpu_itimer();
 }
 
@@ -461,7 +461,7 @@
 /*
  * Bring one cpu online.
  */
-int __init smp_boot_one_cpu(int cpuid)
+int __cpuinit smp_boot_one_cpu(int cpuid)
 {
 	struct task_struct *idle;
 	long timeout;
@@ -552,7 +552,7 @@
 
 /*
 ** inventory.c:do_inventory() hasn't yet been run and thus we
-** don't 'discover' the additional CPU's until later.
+** don't 'discover' the additional CPUs until later.
 */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index ce3245f..bb23ff7 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -311,14 +311,13 @@
 	int count;
 };
 
-#define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
 static int filldir32 (void *__buf, const char *name, int namlen,
 			loff_t offset, u64 ino, unsigned int d_type)
 {
 	struct linux32_dirent __user * dirent;
 	struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
-	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
+	int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, 4);
 	u32 d_ino;
 
 	buf->error = -EINVAL;	/* only used if we fail.. */
@@ -350,6 +349,10 @@
 	struct getdents32_callback buf;
 	int error;
 
+	error = -EFAULT;
+	if (!access_ok(VERIFY_WRITE, dirent, count))
+		goto out;
+
 	error = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -366,8 +369,10 @@
 	error = buf.error;
 	lastdirent = buf.previous;
 	if (lastdirent) {
-		put_user(file->f_pos, &lastdirent->d_off);
-		error = count - buf.count;
+		if (put_user(file->f_pos, &lastdirent->d_off))
+			error = -EFAULT;
+		else
+			error = count - buf.count;
 	}
 
 out_putf:
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 10859f5..56f6231 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -181,7 +181,7 @@
 	/* Are we being ptraced? */
 	mfctl	%cr30, %r1
 	LDREG	TI_TASK(%r1),%r1
-	LDREG	TASK_PTRACE(%r1), %r1
+	ldw	TASK_PTRACE(%r1), %r1
 	bb,<,n	%r1,31,.Ltracesys
 	
 	/* Note!  We cannot use the syscall table that is mapped
@@ -198,7 +198,7 @@
 	ldil	L%sys_call_table, %r1
 	ldo     R%sys_call_table(%r1), %r19
 #endif	
-	comiclr,>>=	__NR_Linux_syscalls, %r20, %r0
+	comiclr,>>	__NR_Linux_syscalls, %r20, %r0
 	b,n	.Lsyscall_nosys
 	
 	LDREGX  %r20(%r19), %r19
@@ -501,7 +501,7 @@
 	shlw	%r20, 4, %r20
 	add	%r20, %r28, %r20
 
-# ifdef ENABLE_LWS_DEBUG
+# if ENABLE_LWS_DEBUG
 	/*	
 		DEBUG, check for deadlock! 
 		If the thread register values are the same
@@ -550,7 +550,7 @@
 		perspective
 	*/
 cas_action:
-#if defined CONFIG_SMP && defined ENABLE_LWS_DEBUG
+#if defined CONFIG_SMP && ENABLE_LWS_DEBUG
 	/* DEBUG */
 	mfctl	%cr27, %r1
 	stw	%r1, 4(%sr2,%r20)
@@ -562,7 +562,7 @@
 #ifdef CONFIG_SMP
 	/* Free lock */
 	stw	%r20, 0(%sr2,%r20)
-# ifdef ENABLE_LWS_DEBUG
+# if ENABLE_LWS_DEBUG
 	/* Clear thread register indicator */
 	stw	%r0, 4(%sr2,%r20)
 # endif
@@ -576,7 +576,7 @@
 #ifdef CONFIG_SMP
 	/* Free lock */
 	stw	%r20, 0(%sr2,%r20)
-# ifdef ENABLE_LWS_DEBUG
+# if ENABLE_LWS_DEBUG
 	stw	%r0, 4(%sr2,%r20)
 # endif
 #endif
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 8bf87e5..627f3c2 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -30,11 +30,6 @@
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#undef ENTRY_SAME
-#undef ENTRY_DIFF
-#undef ENTRY_UHOH
-#undef ENTRY_COMP
-#undef ENTRY_OURS
 #if defined(CONFIG_64BIT) && !defined(SYSCALL_TABLE_64BIT)
 /* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
  * narrow palinux.  Use ENTRY_DIFF for those where a 32-bit specific
@@ -405,5 +400,16 @@
 	ENTRY_SAME(epoll_pwait)
 	ENTRY_COMP(statfs64)
 	ENTRY_COMP(fstatfs64)
+	ENTRY_COMP(kexec_load)		/* 300 */
+	ENTRY_COMP(utimensat)
+	ENTRY_COMP(signalfd)
+	ENTRY_COMP(timerfd)
+	ENTRY_SAME(eventfd)
+
 	/* Nothing yet */
 
+#undef ENTRY_SAME
+#undef ENTRY_DIFF
+#undef ENTRY_UHOH
+#undef ENTRY_COMP
+#undef ENTRY_OURS
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 07a991a..8b3062a 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -191,7 +191,7 @@
 {
 	int change = 0;
 
-	/* since the cr16 cycle counters are not syncronized across CPUs,
+	/* since the cr16 cycle counters are not synchronized across CPUs,
 	   we'll check if we should switch to a safe clocksource: */
 	if (clocksource_cr16.rating != 0 && num_online_cpus() > 1) {
 		clocksource_change_rating(&clocksource_cr16, 0);
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 745ff74..bbf029a 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -264,6 +264,7 @@
 
 	show_regs(regs);
 	dump_stack();
+	add_taint(TAINT_DIE);
 
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
@@ -302,7 +303,7 @@
 	if (unlikely(iir == PARISC_BUG_BREAK_INSN && !user_mode(regs))) {
 		/* check if a BUG() or WARN() trapped here.  */
 		enum bug_trap_type tt;
-		tt = report_bug(regs->iaoq[0] & ~3);
+		tt = report_bug(regs->iaoq[0] & ~3, regs);
 		if (tt == BUG_TRAP_TYPE_WARN) {
 			regs->iaoq[0] += 4;
 			regs->iaoq[1] += 4;
@@ -615,7 +616,7 @@
 		
 	case 13:
 		/* Conditional Trap
-		   The condition succees in an instruction which traps 
+		   The condition succeeds in an instruction which traps
 		   on condition  */
 		if(user_mode(regs)){
 			si.si_signo = SIGFPE;
@@ -802,13 +803,14 @@
 
 int __init check_ivt(void *iva)
 {
+	extern const u32 os_hpmc[];
+	extern const u32 os_hpmc_end[];
+
 	int i;
 	u32 check = 0;
 	u32 *ivap;
 	u32 *hpmcp;
 	u32 length;
-	extern void os_hpmc(void);
-	extern void os_hpmc_end(void);
 
 	if (strcmp((char *)iva, "cows can fly"))
 		return -1;
@@ -820,7 +822,7 @@
 
 	/* Compute Checksum for HPMC handler */
 
-	length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);
+	length = os_hpmc_end - os_hpmc;
 	ivap[7] = length;
 
 	hpmcp = (u32 *)os_hpmc;
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 89c0370..cf780cb 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -16,6 +16,8 @@
 
 #include <asm/uaccess.h>
 #include <asm/assembly.h>
+#include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
 
 #include <asm/unwind.h>
 
@@ -26,6 +28,8 @@
 #define dbg(x...)
 #endif
 
+#define KERNEL_START (KERNEL_BINARY_TEXT_START - 0x1000)
+
 extern struct unwind_table_entry __start___unwind[];
 extern struct unwind_table_entry __stop___unwind[];
 
@@ -197,6 +201,29 @@
 	return 0;
 }
 
+#ifdef CONFIG_64BIT
+#define get_func_addr(fptr) fptr[2]
+#else
+#define get_func_addr(fptr) fptr[0]
+#endif
+
+static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
+{
+	void handle_interruption(int, struct pt_regs *);
+	static unsigned long *hi = (unsigned long)&handle_interruption;
+
+	if (pc == get_func_addr(hi)) {
+		struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
+		dbg("Unwinding through handle_interruption()\n");
+		info->prev_sp = regs->gr[30];
+		info->prev_ip = regs->iaoq[0];
+
+		return 1;
+	}
+
+	return 0;
+}
+
 static void unwind_frame_regs(struct unwind_frame_info *info)
 {
 	const struct unwind_table_entry *e;
@@ -215,9 +242,11 @@
 #ifdef CONFIG_KALLSYMS
 		/* Handle some frequent special cases.... */
 		{
-			char symname[KSYM_NAME_LEN+1];
+			char symname[KSYM_NAME_LEN];
+			char *modname;
 
-			kallsyms_lookup(info->ip, NULL, NULL, NULL, symname);
+			kallsyms_lookup(info->ip, NULL, NULL, &modname,
+				symname);
 
 			dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname);
 
@@ -308,13 +337,15 @@
 			}
 		}
 
-		info->prev_sp = info->sp - frame_size;
-		if (e->Millicode)
-			info->rp = info->r31;
-		else if (rpoffset)
-			info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
-		info->prev_ip = info->rp;
-		info->rp = 0;
+		if (!unwind_special(info, e->region_start, frame_size)) {
+			info->prev_sp = info->sp - frame_size;
+			if (e->Millicode)
+				info->rp = info->r31;
+			else if (rpoffset)
+				info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
+			info->prev_ip = info->rp;
+			info->rp = 0;
+		}
 
 		dbg("analyzing func @ %lx, setting prev_sp=%lx "
 		    "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, 
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index c745859..4d96ba4 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -51,7 +51,7 @@
 
   _text = .;			/* Text and read-only data */
   .text ALIGN(16) : {
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	*(.text.do_softirq)
@@ -91,7 +91,7 @@
 
   . = ALIGN(L1_CACHE_BYTES);
   .data : {			/* Data */
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
 	}
 
diff --git a/arch/parisc/math-emu/dbl_float.h b/arch/parisc/math-emu/dbl_float.h
index 1570e2e..0c2fa9a 100644
--- a/arch/parisc/math-emu/dbl_float.h
+++ b/arch/parisc/math-emu/dbl_float.h
@@ -22,7 +22,7 @@
     PA header file -- do not include this header file for non-PA builds.
 #endif
 
-/* 32-bit word grabing functions */
+/* 32-bit word grabbing functions */
 #define Dbl_firstword(value) Dallp1(value)
 #define Dbl_secondword(value) Dallp2(value)
 #define Dbl_thirdword(value) dummy_location
@@ -37,7 +37,7 @@
 #define Dbl_allp1(object) Dallp1(object)
 #define Dbl_allp2(object) Dallp2(object)
 
-/* dbl_and_signs ands the sign bits of each argument and puts the result
+/* dbl_and_signs ANDs the sign bits of each argument and puts the result
  * into the first argument. dbl_or_signs ors those same sign bits */
 #define Dbl_and_signs( src1dst, src2)		\
     Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst)
diff --git a/arch/parisc/math-emu/dfsqrt.c b/arch/parisc/math-emu/dfsqrt.c
index b6ed106..9542c6d 100644
--- a/arch/parisc/math-emu/dfsqrt.c
+++ b/arch/parisc/math-emu/dfsqrt.c
@@ -76,7 +76,7 @@
                 }
                 /*
                  * Return quiet NaN or positive infinity.
-		 *  Fall thru to negative test if negative infinity.
+		 *  Fall through to negative test if negative infinity.
                  */
 		if (Dbl_iszero_sign(srcp1) || 
 		    Dbl_isnotzero_mantissa(srcp1,srcp2)) {
diff --git a/arch/parisc/math-emu/sfsqrt.c b/arch/parisc/math-emu/sfsqrt.c
index cd3f6db..4657a12 100644
--- a/arch/parisc/math-emu/sfsqrt.c
+++ b/arch/parisc/math-emu/sfsqrt.c
@@ -76,7 +76,7 @@
                 }
                 /*
                  * Return quiet NaN or positive infinity.
-		 *  Fall thru to negative test if negative infinity.
+		 *  Fall through to negative test if negative infinity.
                  */
 		if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) {
                 	*dstptr = src;
diff --git a/arch/parisc/math-emu/sgl_float.h b/arch/parisc/math-emu/sgl_float.h
index 82519a5..4ee4cc9 100644
--- a/arch/parisc/math-emu/sgl_float.h
+++ b/arch/parisc/math-emu/sgl_float.h
@@ -23,7 +23,7 @@
     PA header file -- do not include this header file for non-PA builds.
 #endif
 
-/* 32-bit word grabing functions */
+/* 32-bit word grabbing functions */
 #define Sgl_firstword(value) Sall(value)
 #define Sgl_secondword(value) dummy_location
 #define Sgl_thirdword(value) dummy_location
@@ -36,7 +36,7 @@
 #define Sgl_exponentmantissa(object) Sexponentmantissa(object)
 #define Sgl_all(object) Sall(object)
 
-/* sgl_and_signs ands the sign bits of each argument and puts the result
+/* sgl_and_signs ANDs the sign bits of each argument and puts the result
  * into the first argument. sgl_or_signs ors those same sign bits */
 #define Sgl_and_signs( src1dst, src2)		\
     Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst)
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 75ea9f2..e724b36 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -890,7 +890,7 @@
 #ifdef CONFIG_PA20
 
 /*
- * Currently, all PA20 chips have 18 bit protection id's, which is the
+ * Currently, all PA20 chips have 18 bit protection IDs, which is the
  * limiting factor (space ids are 32 bits).
  */
 
@@ -899,10 +899,10 @@
 #else
 
 /*
- * Currently we have a one-to-one relationship between space id's and
- * protection id's. Older parisc chips (PCXS, PCXT, PCXL, PCXL2) only
- * support 15 bit protection id's, so that is the limiting factor.
- * PCXT' has 18 bit protection id's, but only 16 bit spaceids, so it's
+ * Currently we have a one-to-one relationship between space IDs and
+ * protection IDs. Older parisc chips (PCXS, PCXT, PCXL, PCXL2) only
+ * support 15 bit protection IDs, so that is the limiting factor.
+ * PCXT' has 18 bit protection IDs, but only 16 bit spaceids, so it's
  * probably not worth the effort for a special case here.
  */
 
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 56d3c0d..d860b64 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -4,17 +4,7 @@
 
 mainmenu "Linux/PowerPC Kernel Configuration"
 
-config PPC64
-	bool "64-bit kernel"
-	default n
-	help
-	  This option selects whether a 32-bit or a 64-bit kernel
-	  will be built.
-
-config PPC_PM_NEEDS_RTC_LIB
-	bool
-	select RTC_LIB
-	default y if PM
+source "arch/powerpc/platforms/Kconfig.cputype"
 
 config PPC32
 	bool
@@ -66,6 +56,9 @@
 	bool
 	default y
 
+config ARCH_NO_VIRT_TO_BUS
+	def_bool PPC64
+
 config PPC
 	bool
 	default y
@@ -118,6 +111,7 @@
 	depends on BUG
 
 config SYS_SUPPORTS_APM_EMULATION
+	default y if PMAC_APM_EMU
 	bool
 
 config DEFAULT_UIMAGE
@@ -131,123 +125,6 @@
 	depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
 	default y
 
-menu "Processor support"
-choice
-	prompt "Processor Type"
-	depends on PPC32
-	default 6xx
-
-config CLASSIC32
-	bool "52xx/6xx/7xx/74xx"
-	select PPC_FPU
-	select 6xx
-	help
-	  There are four families of PowerPC chips supported.  The more common
-	  types (601, 603, 604, 740, 750, 7400), the Motorola embedded
-	  versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
-	  embedded versions (403 and 405) and the high end 64 bit Power
-	  processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
-
-	  This option is the catch-all for 6xx types, including some of the
-	  embedded versions.  Unless there is see an option for the specific
-	  chip family you are using, you want this option.
-	  
-	  You do not want this if you are building a kernel for a 64 bit
-	  IBM RS/6000 or an Apple G5, choose 6xx.
-	  
-	  If unsure, select this option
-	  
-	  Note that the kernel runs in 32-bit mode even on 64-bit chips.
-
-config PPC_82xx
-	bool "Freescale 82xx"
-	select 6xx
-	select PPC_FPU
-
-config PPC_83xx
-	bool "Freescale 83xx"
-	select 6xx
-	select FSL_SOC
-	select 83xx
-	select PPC_FPU
-	select WANT_DEVICE_TREE
-
-config PPC_85xx
-	bool "Freescale 85xx"
-	select E500
-	select FSL_SOC
-	select 85xx
-	select WANT_DEVICE_TREE
-
-config PPC_86xx
-	bool "Freescale 86xx"
-	select 6xx
-	select FSL_SOC
-	select FSL_PCIE
-	select PPC_FPU
-	select ALTIVEC
-	help
-	  The Freescale E600 SoCs have 74xx cores.
-
-config PPC_8xx
-	bool "Freescale 8xx"
-	select FSL_SOC
-	select 8xx
-
-config 40x
-	bool "AMCC 40x"
-	select PPC_DCR_NATIVE
-
-config 44x
-	bool "AMCC 44x"
-	select PPC_DCR_NATIVE
-	select WANT_DEVICE_TREE
-
-config E200
-	bool "Freescale e200"
-
-endchoice
-
-config POWER4_ONLY
-	bool "Optimize for POWER4"
-	depends on PPC64
-	default n
-	---help---
-	  Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
-	  The resulting binary will not work on POWER3 or RS64 processors
-	  when compiled with binutils 2.15 or later.
-
-config POWER3
-	bool
-	depends on PPC64
-	default y if !POWER4_ONLY
-
-config POWER4
-	depends on PPC64
-	def_bool y
-
-config 6xx
-	bool
-
-# this is temp to handle compat with arch=ppc
-config 8xx
-	bool
-
-# this is temp to handle compat with arch=ppc
-config 83xx
-	bool
-
-# this is temp to handle compat with arch=ppc
-config 85xx
-	bool
-
-config E500
-	bool
-
-config PPC_FPU
-	bool
-	default y if PPC64
-
 config PPC_DCR_NATIVE
 	bool
 	default n
@@ -266,134 +143,6 @@
 	depends on PPC64 # not supported on 32 bits yet
 	default n
 
-config 4xx
-	bool
-	depends on 40x || 44x
-	default y
-
-config BOOKE
-	bool
-	depends on E200 || E500 || 44x
-	default y
-
-config FSL_BOOKE
-	bool
-	depends on E200 || E500
-	default y
-
-config PTE_64BIT
-	bool
-	depends on 44x || E500
-	default y if 44x
-	default y if E500 && PHYS_64BIT
-
-config PHYS_64BIT
-	bool 'Large physical address support' if E500
-	depends on 44x || E500
-	select RESOURCES_64BIT
-	default y if 44x
-	---help---
-	  This option enables kernel support for larger than 32-bit physical
-	  addresses.  This features is not be available on all e500 cores.
-
-	  If in doubt, say N here.
-
-config ALTIVEC
-	bool "AltiVec Support"
-	depends on CLASSIC32 || POWER4
-	---help---
-	  This option enables kernel support for the Altivec extensions to the
-	  PowerPC processor. The kernel currently supports saving and restoring
-	  altivec registers, and turning on the 'altivec enable' bit so user
-	  processes can execute altivec instructions.
-
-	  This option is only usefully if you have a processor that supports
-	  altivec (G4, otherwise known as 74xx series), but does not have
-	  any affect on a non-altivec cpu (it does, however add code to the
-	  kernel).
-
-	  If in doubt, say Y here.
-
-config SPE
-	bool "SPE Support"
-	depends on E200 || E500
-	default y
-	---help---
-	  This option enables kernel support for the Signal Processing
-	  Extensions (SPE) to the PowerPC processor. The kernel currently
-	  supports saving and restoring SPE registers, and turning on the
-	  'spe enable' bit so user processes can execute SPE instructions.
-
-	  This option is only useful if you have a processor that supports
-	  SPE (e500, otherwise known as 85xx series), but does not have any
-	  effect on a non-spe cpu (it does, however add code to the kernel).
-
-	  If in doubt, say Y here.
-
-config PPC_STD_MMU
-	bool
-	depends on 6xx || POWER3 || POWER4 || PPC64
-	default y
-
-config PPC_STD_MMU_32
-	def_bool y
-	depends on PPC_STD_MMU && PPC32
-
-config PPC_MM_SLICES
-	bool
-	default y if HUGETLB_PAGE
-	default n
-
-config VIRT_CPU_ACCOUNTING
-	bool "Deterministic task and CPU time accounting"
-	depends on PPC64
-	default y
-	help
-	  Select this option to enable more accurate task and CPU time
-	  accounting.  This is done by reading a CPU counter on each
-	  kernel entry and exit and on transitions within the kernel
-	  between system, softirq and hardirq state, so there is a
-	  small performance impact.  This also enables accounting of
-	  stolen time on logically-partitioned systems running on
-	  IBM POWER5-based machines.
-
-	  If in doubt, say Y here.
-
-config SMP
-	depends on PPC_STD_MMU
-	bool "Symmetric multi-processing support"
-	---help---
-	  This enables support for systems with more than one CPU. If you have
-	  a system with only one CPU, say N. If you have a system with more
-	  than one CPU, say Y.  Note that the kernel does not currently
-	  support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
-	  since they have inadequate hardware support for multiprocessor
-	  operation.
-
-	  If you say N here, the kernel will run on single and multiprocessor
-	  machines, but will use only one CPU of a multiprocessor machine. If
-	  you say Y here, the kernel will run on single-processor machines.
-	  On a single-processor machine, the kernel will run faster if you say
-	  N here.
-
-	  If you don't know what to do here, say N.
-
-config NR_CPUS
-	int "Maximum number of CPUs (2-128)"
-	range 2 128
-	depends on SMP
-	default "32" if PPC64
-	default "4"
-
-config NOT_COHERENT_CACHE
-	bool
-	depends on 4xx || 8xx || E200
-	default y
-
-config CONFIG_CHECK_CACHE_COHERENCY
-	bool
-endmenu
-
 source "init/Kconfig"
 
 source "arch/powerpc/platforms/Kconfig"
@@ -673,10 +422,6 @@
 config FSL_SOC
 	bool
 
-config FSL_PCIE
-	bool
-	depends on PPC_86xx
-
 # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
 config MCA
 	bool
@@ -684,10 +429,10 @@
 config PCI
 	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
 		|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
-		|| MPC7448HPC2 || PPC_PS3 || PPC_HOLLY
-	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
+		|| PPC_PS3
+	default y if !40x && !CPM2 && !8xx && !PPC_83xx \
 		&& !PPC_85xx && !PPC_86xx
-	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
+	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
 	select ARCH_SUPPORTS_MSI
 	help
@@ -697,8 +442,10 @@
 	  infrastructure code to support PCI bus devices.
 
 config PCI_DOMAINS
-	bool
-	default PCI
+	def_bool PCI
+
+config PCI_SYSCALL
+	def_bool PCI
 
 config PCI_QSPAN
 	bool "QSpan PCI"
@@ -893,8 +640,8 @@
 source "arch/powerpc/oprofile/Kconfig"
 
 config KPROBES
-	bool "Kprobes (EXPERIMENTAL)"
-	depends on !BOOKE && !4xx && KALLSYMS && EXPERIMENTAL && MODULES
+	bool "Kprobes"
+	depends on !BOOKE && !4xx && KALLSYMS && MODULES
 	help
 	  Kprobes allows you to trap at almost any kernel address and
 	  execute a callback function.  register_kprobe() establishes
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 6238b58..187a39a 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -142,14 +142,13 @@
 
 # Default to zImage, override when needed
 defaultimage-y			:= zImage
-defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
 defaultimage-$(CONFIG_DEFAULT_UIMAGE) := uImage
 KBUILD_IMAGE := $(defaultimage-y)
 all: $(KBUILD_IMAGE)
 
 CPPFLAGS_vmlinux.lds	:= -Upowerpc
 
-BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage
+BOOT_TARGETS = zImage zImage.initrd uImage
 
 PHONY += $(BOOT_TARGETS)
 
diff --git a/arch/powerpc/boot/44x.c b/arch/powerpc/boot/44x.c
index d51377d9..9f64e84 100644
--- a/arch/powerpc/boot/44x.c
+++ b/arch/powerpc/boot/44x.c
@@ -38,3 +38,48 @@
 
 	dt_fixup_memory(0, memsize);
 }
+
+#define SPRN_DBCR0		0x134
+#define   DBCR0_RST_SYSTEM	0x30000000
+
+void ibm44x_dbcr_reset(void)
+{
+	unsigned long tmp;
+
+	asm volatile (
+		"mfspr	%0,%1\n"
+		"oris	%0,%0,%2@h\n"
+		"mtspr	%1,%0"
+		: "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
+		);
+
+}
+
+/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
+ * banks into the OPB address space */
+void ibm4xx_fixup_ebc_ranges(const char *ebc)
+{
+	void *devp;
+	u32 bxcr;
+	u32 ranges[EBC_NUM_BANKS*4];
+	u32 *p = ranges;
+	int i;
+
+	for (i = 0; i < EBC_NUM_BANKS; i++) {
+		mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
+		bxcr = mfdcr(DCRN_EBC0_CFGDATA);
+
+		if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
+			*p++ = i;
+			*p++ = 0;
+			*p++ = bxcr & EBC_BXCR_BAS;
+			*p++ = EBC_BXCR_BANK_SIZE(bxcr);
+		}
+	}
+
+	devp = finddevice(ebc);
+	if (! devp)
+		fatal("Couldn't locate EBC node %s\n\r", ebc);
+
+	setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
+}
diff --git a/arch/powerpc/boot/44x.h b/arch/powerpc/boot/44x.h
index 7b129ad..577982c 100644
--- a/arch/powerpc/boot/44x.h
+++ b/arch/powerpc/boot/44x.h
@@ -11,6 +11,9 @@
 #define _PPC_BOOT_44X_H_
 
 void ibm44x_fixup_memsize(void);
+void ibm4xx_fixup_ebc_ranges(const char *ebc);
+
+void ibm44x_dbcr_reset(void);
 void ebony_init(void *mac0, void *mac1);
 
 #endif /* _PPC_BOOT_44X_H_ */
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 8378898..61a6f34 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -11,20 +11,18 @@
 #	bootloader and increase compatibility with OpenFirmware.
 #
 #	To this end we need to define BOOTCC, etc, as the tools
-#	needed to build the 32 bit image.  These are normally HOSTCC,
-#	but may be a third compiler if, for example, you are cross
-#	compiling from an intel box.  Once the 64bit ppc gcc is
-#	stable it will probably simply be a compiler switch to
-#	compile for 32bit mode.
+#	needed to build the 32 bit image.  That's normally the same
+#	compiler for the rest of the kernel, with the -m32 flag added.
 #	To make it easier to setup a cross compiler,
 #	CROSS32_COMPILE is setup as a prefix just like CROSS_COMPILE
 #	in the toplevel makefile.
 
 all: $(obj)/zImage
 
-HOSTCC		:= gcc
-BOOTCFLAGS	:= $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \
-		   $(shell $(CROSS32CC) -print-file-name=include) -fPIC
+BOOTCFLAGS    := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
+		 -fno-strict-aliasing -Os -msoft-float -pipe \
+		 -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
+		 -isystem $(shell $(CROSS32CC) -print-file-name=include)
 BOOTAFLAGS	:= -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
 
 ifeq ($(call cc-option-yn, -fstack-protector),y)
@@ -33,8 +31,8 @@
 
 BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(obj)
 
-$(obj)/44x.o: BOOTCFLAGS += -Wa,-mbooke
-$(obj)/ebony.o: BOOTCFLAGS += -Wa,-mbooke
+$(obj)/44x.o: BOOTCFLAGS += -mcpu=440
+$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
 
 zlib       := inffast.c inflate.c inftrees.c
 zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
@@ -45,10 +43,11 @@
 
 src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
 		ns16550.c serial.c simple_alloc.c div64.S util.S \
-		gunzip_util.c elf_util.c $(zlib) devtree.c \
-		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c
+		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
+		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
 src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
-		cuboot-ebony.c treeboot-ebony.c prpmc2800.c
+		cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
+		ps3-head.S ps3-hvcall.S ps3.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -77,11 +76,11 @@
 $(obj)/empty.c:
 	@touch $@
 
-$(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
+$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S
 	@cp $< $@
 
 clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
-		empty.c zImage.coff.lds zImage.lds
+		empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds
 
 quiet_cmd_bootcc = BOOTCC  $@
       cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -104,7 +103,7 @@
 
 targets		+= $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
 extra-y		:= $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
-		   $(obj)/zImage.lds $(obj)/zImage.coff.lds
+		   $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
 
 wrapper		:=$(srctree)/$(src)/wrapper
 wrapperbits	:= $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
@@ -134,8 +133,9 @@
 image-$(CONFIG_PPC_CHRP)		+= zImage.chrp
 image-$(CONFIG_PPC_EFIKA)		+= zImage.chrp
 image-$(CONFIG_PPC_PMAC)		+= zImage.pmac
-image-$(CONFIG_PPC_HOLLY)		+= zImage.holly-elf
+image-$(CONFIG_PPC_HOLLY)		+= zImage.holly
 image-$(CONFIG_PPC_PRPMC2800)		+= zImage.prpmc2800
+image-$(CONFIG_PPC_ISERIES)		+= zImage.iseries
 image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
 
 ifneq ($(CONFIG_DEVICE_TREE),"")
@@ -158,52 +158,43 @@
 
 $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
 
-dts-  := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-))
-dts-y := $(patsubst zImage%, zImage.dts%, $(image-y))
-dts-y := $(filter-out $(image-y), $(dts-y))
-targets	+= $(image-y) $(dts-y)
-
-dts_initrd-  := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-))
-dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y))
-dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y))
-targets	+= $(image-y) $(dts_initrd-y)
-
-$(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz
+# If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an
+# empty string, define 'dts' to be path to the dts
+# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
+ifeq ($(CONFIG_WANT_DEVICE_TREE),y)
+ifneq ($(CONFIG_DEVICE_TREE),"")
+dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
+	,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
+endif
+endif
 
 # Don't put the ramdisk on the pattern rule; when its missing make will try
 # the pattern rule with less dependencies that also matches (even with the
 # hard dependency listed).
-$(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz
+$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts)
 	$(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz)
 
-$(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts)
+$(obj)/zImage.%: vmlinux $(wrapperbits) $(dts)
 	$(call if_changed,wrap,$*,$(dts))
 
-$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
-	$(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
-
-$(obj)/zImage.%: vmlinux $(wrapperbits)
-	$(call if_changed,wrap,$*)
-
-$(obj)/zImage.ps3: vmlinux
+# This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
+# prefix
+$(obj)/vmlinux.strip: vmlinux
 	$(STRIP) -s -R .comment $< -o $@
 
-$(obj)/zImage.initrd.ps3: vmlinux
-	@echo "  WARNING zImage.initrd.ps3 not supported (yet)"
+$(obj)/zImage.iseries: vmlinux
+	$(STRIP) -s -R .comment $< -o $@
 
-$(obj)/zImage.holly-elf: vmlinux $(wrapperbits)
-	$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,)
+$(obj)/zImage.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
+	$(STRIP) -s -R .comment $< -o vmlinux.strip
+	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
 
-$(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz
-	$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz)
+$(obj)/zImage.initrd.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz
+	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz)
 
 $(obj)/uImage: vmlinux $(wrapperbits)
 	$(call if_changed,wrap,uboot)
 
-# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
-dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
-	,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
-
 $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits)
 	$(call if_changed,wrap,cuboot-$*,$(dts))
 
@@ -213,22 +204,22 @@
 $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits)
 	$(call if_changed,wrap,treeboot-$*,$(dts))
 
+# If there isn't a platform selected then just strip the vmlinux.
+ifeq (,$(image-y))
+image-y := vmlinux.strip
+endif
+
 $(obj)/zImage:		$(addprefix $(obj)/, $(image-y))
 	@rm -f $@; ln $< $@
 $(obj)/zImage.initrd:	$(addprefix $(obj)/, $(initrd-y))
 	@rm -f $@; ln $< $@
-$(obj)/zImage.dts:	$(addprefix $(obj)/, $(dts-y))
-	@rm -f $@; ln $< $@
-$(obj)/zImage.dts_initrd:	$(addprefix $(obj)/, $(dts_initrd-y))
-	@rm -f $@; ln $< $@
-
 
 install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
 	sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
 
 # anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \
-	treeImage.* zImage.dts zImage.dts_initrd
+clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
+	otheros.bld
 
 # clean up files cached by wrapper
 clean-kernel := vmlinux.strip vmlinux.bin
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index 5a4215c..f1c4dfc 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -13,6 +13,7 @@
 
 	.text
 	/* a procedure descriptor used when booting this as a COFF file */
+	.globl	_zimage_start_opd
 _zimage_start_opd:
 	.long	_zimage_start, 0, 0, 0
 
diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c
index 9af554e..296025d 100644
--- a/arch/powerpc/boot/cuboot-83xx.c
+++ b/arch/powerpc/boot/cuboot-83xx.c
@@ -12,12 +12,12 @@
 
 #include "ops.h"
 #include "stdio.h"
+#include "cuboot.h"
 
 #define TARGET_83xx
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
 extern char _dtb_start[], _dtb_end[];
 
 static void platform_fixups(void)
@@ -52,16 +52,7 @@
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-	unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-	memcpy(&bd, (bd_t *)r3, sizeof(bd));
-	loader_info.initrd_addr = r4;
-	loader_info.initrd_size = r4 ? r5 - r4 : 0;
-	loader_info.cmdline = (char *)r6;
-	loader_info.cmdline_len = r7 - r6;
-
-	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+	CUBOOT_INIT();
 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c
index e256031..10f0f69 100644
--- a/arch/powerpc/boot/cuboot-85xx.c
+++ b/arch/powerpc/boot/cuboot-85xx.c
@@ -12,12 +12,12 @@
 
 #include "ops.h"
 #include "stdio.h"
+#include "cuboot.h"
 
 #define TARGET_85xx
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
 extern char _dtb_start[], _dtb_end[];
 
 static void platform_fixups(void)
@@ -53,16 +53,7 @@
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-	unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-	memcpy(&bd, (bd_t *)r3, sizeof(bd));
-	loader_info.initrd_addr = r4;
-	loader_info.initrd_size = r4 ? r5 - r4 : 0;
-	loader_info.cmdline = (char *)r6;
-	loader_info.cmdline_len = r7 - r6;
-
-	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+	CUBOOT_INIT();
 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
diff --git a/arch/powerpc/boot/cuboot-ebony.c b/arch/powerpc/boot/cuboot-ebony.c
index 4464c5f..c5f37ce 100644
--- a/arch/powerpc/boot/cuboot-ebony.c
+++ b/arch/powerpc/boot/cuboot-ebony.c
@@ -15,28 +15,16 @@
 #include "ops.h"
 #include "stdio.h"
 #include "44x.h"
+#include "cuboot.h"
 
 #define TARGET_44x
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
-
-BSS_STACK(4096);
 
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-	unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-	memcpy(&bd, (bd_t *)r3, sizeof(bd));
-	loader_info.initrd_addr = r4;
-	loader_info.initrd_size = r4 ? r5 : 0;
-	loader_info.cmdline = (char *)r6;
-	loader_info.cmdline_len = r7 - r6;
-
-	simple_alloc_init(_end, avail_ram, 32, 64);
-
+	CUBOOT_INIT();
 	ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr);
 }
diff --git a/arch/powerpc/boot/cuboot.c b/arch/powerpc/boot/cuboot.c
new file mode 100644
index 0000000..6579546
--- /dev/null
+++ b/arch/powerpc/boot/cuboot.c
@@ -0,0 +1,35 @@
+/*
+ * Compatibility for old (not device tree aware) U-Boot versions
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au>
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "stdio.h"
+
+#include "ppcboot.h"
+
+extern char _end[];
+extern char _dtb_start[], _dtb_end[];
+
+void cuboot_init(unsigned long r4, unsigned long r5,
+		 unsigned long r6, unsigned long r7,
+		 unsigned long end_of_ram)
+{
+	unsigned long avail_ram = end_of_ram - (unsigned long)_end;
+
+	loader_info.initrd_addr = r4;
+	loader_info.initrd_size = r4 ? r5 - r4 : 0;
+	loader_info.cmdline = (char *)r6;
+	loader_info.cmdline_len = r7 - r6;
+
+	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+}
diff --git a/arch/powerpc/boot/cuboot.h b/arch/powerpc/boot/cuboot.h
new file mode 100644
index 0000000..cd2aa7f
--- /dev/null
+++ b/arch/powerpc/boot/cuboot.h
@@ -0,0 +1,14 @@
+#ifndef _PPC_BOOT_CUBOOT_H_
+#define _PPC_BOOT_CUBOOT_H_
+
+void cuboot_init(unsigned long r4, unsigned long r5,
+		 unsigned long r6, unsigned long r7,
+		 unsigned long end_of_ram);
+
+#define CUBOOT_INIT() \
+	do { \
+		memcpy(&bd, (bd_t *)r3, sizeof(bd)); \
+		cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \
+	} while (0)
+
+#endif /* _PPC_BOOT_CUBOOT_H_ */
diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h
index 877bc97..14b44aa 100644
--- a/arch/powerpc/boot/dcr.h
+++ b/arch/powerpc/boot/dcr.h
@@ -26,6 +26,43 @@
 #define			SDRAM_CONFIG_BANK_SIZE(reg)	\
 	(0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17))
 
+/* 440GP External Bus Controller (EBC) */
+#define DCRN_EBC0_CFGADDR				0x012
+#define DCRN_EBC0_CFGDATA				0x013
+#define   EBC_NUM_BANKS					  8
+#define   EBC_B0CR					  0x00
+#define   EBC_B1CR					  0x01
+#define   EBC_B2CR					  0x02
+#define   EBC_B3CR					  0x03
+#define   EBC_B4CR					  0x04
+#define   EBC_B5CR					  0x05
+#define   EBC_B6CR					  0x06
+#define   EBC_B7CR					  0x07
+#define   EBC_BXCR(n)					  (n)
+#define	    EBC_BXCR_BAS				    0xfff00000
+#define	    EBC_BXCR_BS				  	    0x000e0000
+#define	    EBC_BXCR_BANK_SIZE(reg) \
+	(0x100000 << (((reg) & EBC_BXCR_BS) >> 17))
+#define	    EBC_BXCR_BU				  	    0x00018000
+#define	      EBC_BXCR_BU_OFF			  	      0x00000000
+#define	      EBC_BXCR_BU_RO			  	      0x00008000
+#define	      EBC_BXCR_BU_WO			  	      0x00010000
+#define	      EBC_BXCR_BU_RW			  	      0x00018000
+#define	    EBC_BXCR_BW				  	    0x00006000
+#define   EBC_B0AP					  0x10
+#define   EBC_B1AP					  0x11
+#define   EBC_B2AP					  0x12
+#define   EBC_B3AP					  0x13
+#define   EBC_B4AP					  0x14
+#define   EBC_B5AP					  0x15
+#define   EBC_B6AP					  0x16
+#define   EBC_B7AP					  0x17
+#define   EBC_BXAP(n)					  (0x10+(n))
+#define   EBC_BEAR					  0x20
+#define   EBC_BESR					  0x21
+#define   EBC_CFG					  0x23
+#define   EBC_CID					  0x24
+
 /* 440GP Clock, PM, chip control */
 #define DCRN_CPC0_SR					0x0b0
 #define DCRN_CPC0_ER					0x0b1
diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts
index 0ec02f4..c5f9961 100644
--- a/arch/powerpc/boot/dts/ebony.dts
+++ b/arch/powerpc/boot/dts/ebony.dts
@@ -31,8 +31,8 @@
 			reg = <0>;
 			clock-frequency = <0>; // Filled in by zImage
 			timebase-frequency = <0>; // Filled in by zImage
-			i-cache-line-size = <32>;
-			d-cache-line-size = <32>;
+			i-cache-line-size = <20>;
+			d-cache-line-size = <20>;
 			i-cache-size = <8000>; /* 32 kB */
 			d-cache-size = <8000>; /* 32 kB */
 			dcr-controller;
@@ -135,11 +135,9 @@
 				#address-cells = <2>;
 				#size-cells = <1>;
 				clock-frequency = <0>; // Filled in by zImage
-				ranges = <0 00000000 fff00000 100000
-					  1 00000000 48000000 100000
-					  2 00000000 ff800000 400000
-					  3 00000000 48200000 100000
-					  7 00000000 48300000 100000>;
+				// ranges property is supplied by zImage
+				// based on firmware's configuration of the
+				// EBC bridge
 				interrupts = <5 4>;
 				interrupt-parent = <&UIC1>;
 
diff --git a/arch/powerpc/boot/dts/holly.dts b/arch/powerpc/boot/dts/holly.dts
index 254499b..80a4fab 100644
--- a/arch/powerpc/boot/dts/holly.dts
+++ b/arch/powerpc/boot/dts/holly.dts
@@ -46,7 +46,7 @@
 
   	tsi109@c0000000 {
 		device_type = "tsi-bridge";
-		compatible = "tsi-bridge";
+		compatible = "tsi109-bridge", "tsi108-bridge";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <00000000 c0000000 00010000>;
@@ -54,52 +54,55 @@
 
 		i2c@7000 {
 			device_type = "i2c";
-			compatible  = "tsi-i2c";
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			compatible  = "tsi109-i2c", "tsi108-i2c";
+			interrupt-parent = <&MPIC>;
 			interrupts = <e 2>;
 			reg = <7000 400>;
 		};
 
-		mdio@6000 {
+		MDIO: mdio@6000 {
 			device_type = "mdio";
-			compatible = "tsi-ethernet";
+			compatible = "tsi109-mdio", "tsi108-mdio";
+			reg = <6000 50>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 
-			PHY1: ethernet-phy@6000 {
-				device_type = "ethernet-phy";
-				compatible = "bcm54xx";
-				reg = <6000 50>;
-				phy-id = <1>;
+			PHY1: ethernet-phy@1 {
+				compatible = "bcm5461a";
+				reg = <1>;
+				txc-rxc-delay-disable;
 			};
 
-			PHY2: ethernet-phy@6400 {
-				device_type = "ethernet-phy";
-				compatible = "bcm54xx";
-				reg = <6000 50>;
-				phy-id = <2>;
+			PHY2: ethernet-phy@2 {
+				compatible = "bcm5461a";
+				reg = <2>;
+				txc-rxc-delay-disable;
 			};
 		};
 
 		ethernet@6200 {
 			device_type = "network";
-			compatible = "tsi-ethernet";
+			compatible = "tsi109-ethernet", "tsi108-ethernet";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <6000 200>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <10 2>;
+			mdio-handle = <&MDIO>;
 			phy-handle = <&PHY1>;
 		};
 
 		ethernet@6600 {
 			device_type = "network";
-			compatible = "tsi-ethernet";
+			compatible = "tsi109-ethernet", "tsi108-ethernet";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <6400 200>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <11 2>;
+			mdio-handle = <&MDIO>;
 			phy-handle = <&PHY2>;
 		};
 
@@ -110,7 +113,7 @@
 			virtual-reg = <c0007808>;
 			clock-frequency = <3F9C6000>;
 			current-speed = <1c200>;
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <c 2>;
 		};
 
@@ -121,7 +124,7 @@
 			virtual-reg = <c0007c08>;
 			clock-frequency = <3F9C6000>;
 			current-speed = <1c200>;
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <d 2>;
 		};
 
@@ -136,7 +139,7 @@
 
 		pci@1000 {
 			device_type = "pci";
-			compatible = "tsi109";
+			compatible = "tsi109-pci", "tsi108-pci";
 			#interrupt-cells = <1>;
 			#size-cells = <2>;
 			#address-cells = <3>;
@@ -150,7 +153,7 @@
 			ranges = <02000000 0 40000000 40000000 0 10000000
 				  01000000 0 00000000 7e000000 0 00010000>;
 			clock-frequency = <7f28154>;
-			interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+			interrupt-parent = <&MPIC>;
 			interrupts = <17 2>;
 			interrupt-map-mask = <f800 0 0 7>;
 			/*----------------------------------------------------+
@@ -186,13 +189,12 @@
  				#address-cells = <0>;
  				#interrupt-cells = <2>;
  				interrupts = <17 2>;
-				interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+				interrupt-parent = <&MPIC>;
 			};
 		};
 	};
 
 	chosen {
 		linux,stdout-path = "/tsi109@c0000000/serial@7808";
-		bootargs = "console=ttyS0,115200";
 	};
 };
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index eae68ab..d29308f 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -67,7 +67,7 @@
 			interrupt-controller;
 			#interrupt-cells = <3>;
 			device_type = "interrupt-controller";
-			compatible = "mpc5200_pic";
+			compatible = "mpc5200-pic";
 			reg = <500 80>;
 			built-in;
 		};
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index 5185625..f242531 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -67,7 +67,7 @@
 			interrupt-controller;
 			#interrupt-cells = <3>;
 			device_type = "interrupt-controller";
-			compatible = "mpc5200b-pic\0mpc5200_pic";
+			compatible = "mpc5200b-pic\0mpc5200-pic";
 			reg = <500 80>;
 			built-in;
 		};
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index 765c306..0e3d314 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -45,7 +45,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		#interrupt-cells = <2>;
-		device_type = "tsi-bridge";
+		device_type = "tsi108-bridge";
 		ranges = <00000000 c0000000 00010000>;
 		reg = <c0000000 00010000>;
 		bus-frequency = <0>;
@@ -55,27 +55,26 @@
 			interrupts = <E 0>;
 			reg = <7000 400>;
 			device_type = "i2c";
-			compatible  = "tsi-i2c";
+			compatible  = "tsi108-i2c";
 		};
 
-		mdio@6000 {
+		MDIO: mdio@6000 {
 			device_type = "mdio";
-			compatible = "tsi-ethernet";
+			compatible = "tsi108-mdio";
+			reg = <6000 50>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 
-			phy8: ethernet-phy@6000 {
+			phy8: ethernet-phy@8 {
 				interrupt-parent = <&mpic>;
 				interrupts = <2 1>;
-				reg = <6000 50>;
-				phy-id = <8>;
-				device_type = "ethernet-phy";
+				reg = <8>;
 			};
 
-			phy9: ethernet-phy@6400 {
+			phy9: ethernet-phy@9 {
 				interrupt-parent = <&mpic>;
 				interrupts = <2 1>;
-				reg = <6000 50>;
-				phy-id = <9>;
-				device_type = "ethernet-phy";
+				reg = <9>;
 			};
 
 		};
@@ -83,12 +82,12 @@
 		ethernet@6200 {
 			#size-cells = <0>;
 			device_type = "network";
-			model = "TSI-ETH";
-			compatible = "tsi-ethernet";
+			compatible = "tsi108-ethernet";
 			reg = <6000 200>;
 			address = [ 00 06 D2 00 00 01 ];
 			interrupts = <10 2>;
 			interrupt-parent = <&mpic>;
+			mdio-handle = <&MDIO>;
 			phy-handle = <&phy8>;
 		};
 
@@ -96,12 +95,12 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			device_type = "network";
-			model = "TSI-ETH";
-			compatible = "tsi-ethernet";
+			compatible = "tsi108-ethernet";
 			reg = <6400 200>;
 			address = [ 00 06 D2 00 00 02 ];
 			interrupts = <11 2>;
 			interrupt-parent = <&mpic>;
+			mdio-handle = <&MDIO>;
 			phy-handle = <&phy9>;
 		};
 
@@ -135,7 +134,7 @@
                        	big-endian;
 		};
 		pci@1000 {
-			compatible = "tsi10x";
+			compatible = "tsi108-pci";
 			device_type = "pci";
 			#interrupt-cells = <1>;
 			#size-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
index 423eedc..1934b80 100644
--- a/arch/powerpc/boot/dts/mpc8272ads.dts
+++ b/arch/powerpc/boot/dts/mpc8272ads.dts
@@ -14,12 +14,10 @@
        compatible = "MPC8260ADS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8272@0 {
                        device_type = "cpu";
@@ -32,12 +30,10 @@
                        bus-frequency = <0>;
                        clock-frequency = <0>;
                        32-bit;
-                       linux,phandle = <201>;
                };
        };
 
-       interrupt-controller@f8200000 {
-               linux,phandle = <f8200000>;
+		pci_pic: interrupt-controller@f8200000 {
                #address-cells = <0>;
                #interrupt-cells = <2>;
                interrupt-controller;
@@ -47,15 +43,13 @@
        };
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 4000000 f4500000 00000020>;
        };
 
        chosen {
                name = "chosen";
                linux,platform = <0>;
-               interrupt-controller = <10c00>;
-               linux,phandle = <400>;
+		interrupt-controller = <&Cpm_pic>;
        };
 
        soc8272@f0000000 {
@@ -70,20 +64,17 @@
                        device_type = "mdio";
                        compatible = "fs_enet";
                        reg = <0 0>;
-                       linux,phandle = <24520>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <10c00>;
+			phy0:ethernet-phy@0 {
+				interrupt-parent = <&Cpm_pic>;
                                interrupts = <17 4>;
                                reg = <0>;
                                bitbang = [ 12 12 13 02 02 01 ];
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <10c00>;
+			phy1:ethernet-phy@1 {
+				interrupt-parent = <&Cpm_pic>;
                                interrupts = <17 4>;
                                bitbang = [ 12 12 13 02 02 01 ];
                                reg = <3>;
@@ -101,8 +92,8 @@
                        reg = <11300 20 8400 100 11380 30>;
                        mac-address = [ 00 11 2F 99 43 54 ];
                        interrupts = <20 2>;
-                       interrupt-parent = <10c00>;
-                       phy-handle = <2452000>;
+			interrupt-parent = <&Cpm_pic>;
+			phy-handle = <&Phy0>;
                        rx-clock = <13>;
                        tx-clock = <12>;
                };
@@ -115,14 +106,13 @@
                        reg = <11320 20 8500 100 113b0 30>;
                        mac-address = [ 00 11 2F 99 44 54 ];
                        interrupts = <21 2>;
-                       interrupt-parent = <10c00>;
-                       phy-handle = <2452001>;
+			interrupt-parent = <&Cpm_pic>;
+			phy-handle = <&Phy1>;
                        rx-clock = <17>;
                        tx-clock = <18>;
                };
 
                cpm@f0000000 {
-                       linux,phandle = <f0000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        #interrupt-cells = <2>;
@@ -142,7 +132,7 @@
                                reg = <11a00 20 8000 100>;
                                current-speed = <1c200>;
                                interrupts = <28 2>;
-                               interrupt-parent = <10c00>;
+				interrupt-parent = <&Cpm_pic>;
                                clock-setup = <0 00ffffff>;
                                rx-clock = <1>;
                                tx-clock = <1>;
@@ -156,15 +146,14 @@
                                reg = <11a60 20 8300 100>;
                                current-speed = <1c200>;
                                interrupts = <2b 2>;
-                               interrupt-parent = <10c00>;
+				interrupt-parent = <&Cpm_pic>;
                                clock-setup = <1b ffffff00>;
                                rx-clock = <4>;
                                tx-clock = <4>;
                        };
 
                };
-               interrupt-controller@10c00 {
-                       linux,phandle = <10c00>;
+			cpm_pic:interrupt-controller@10c00 {
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
                        interrupt-controller;
@@ -174,7 +163,6 @@
 		       compatible = "CPM2";
                };
                pci@0500 {
-                       linux,phandle = <0500>;
                        #interrupt-cells = <1>;
                        #size-cells = <2>;
                        #address-cells = <3>;
@@ -202,7 +190,7 @@
                                         c000 0 0 2 f8200000 43 8
                                         c000 0 0 3 f8200000 40 8
                                         c000 0 0 4 f8200000 41 8>;
-                       interrupt-parent = <10c00>;
+			interrupt-parent = <&Cpm_pic>;
                        interrupts = <14 8>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 40000000
@@ -216,7 +204,7 @@
                        compatible = "talitos";
                        reg = <30000 10000>;
                        interrupts = <b 2>;
-                       interrupt-parent = <10c00>;
+			interrupt-parent = <&Cpm_pic>;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        exec-units-mask = <0000007e>;
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index 112dd51..4fc0c4d 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -272,7 +272,13 @@
 			reg = <2200 200>;
 			interrupts = <22>;
 			interrupt-parent = < &qeic >;
-			mac-address = [ 00 04 9f 00 23 23 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <19>;
 			tx-clock = <1a>;
 			phy-handle = < &phy3 >;
@@ -287,7 +293,13 @@
 			reg = <3000 200>;
 			interrupts = <23>;
 			interrupt-parent = < &qeic >;
-			mac-address = [ 00 11 22 33 44 55 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <17>;
 			tx-clock = <18>;
 			phy-handle = < &phy4 >;
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index be4c357..447c03f 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -231,7 +231,13 @@
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = <&qeic>;
-			mac-address = [ 00 04 9f ef 03 02 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <20>;
 			tx-clock = <13>;
 			phy-handle = <&phy00>;
@@ -246,7 +252,13 @@
 			reg = <2200 200>;
 			interrupts = <22>;
 			interrupt-parent = <&qeic>;
-			mac-address = [ 00 04 9f ef 03 01 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <19>;
 			tx-clock = <1a>;
 			phy-handle = <&phy04>;
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index db0d003..ae9bca5 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -131,6 +131,11 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <20 8 21 8 22 8>;
@@ -145,6 +150,11 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 8 24 8 25 8>;
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index df773fa..310e877 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -136,6 +136,11 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <20 8 21 8 22 8>;
@@ -150,6 +155,11 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 8 24 8 25 8>;
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 38c8594..1e914f31 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -301,7 +301,13 @@
 			reg = <2000 200>;
 			interrupts = <20>;
 			interrupt-parent = < &qeic >;
-			mac-address = [ 00 04 9f 00 23 23 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <0>;
 			tx-clock = <19>;
 			phy-handle = < &phy0 >;
@@ -317,7 +323,13 @@
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = < &qeic >;
-			mac-address = [ 00 11 22 33 44 55 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <0>;
 			tx-clock = <14>;
 			phy-handle = < &phy1 >;
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index d91e81c..364a969 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8540-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,19 +81,19 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 1>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 1>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <37 1>;
+				interrupts = <7 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -106,9 +106,14 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			address = [ 00 E0 0C 00 73 00 ];
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -120,9 +125,14 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			address = [ 00 E0 0C 00 73 01 ];
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -134,9 +144,14 @@
 			model = "FEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			address = [ 00 E0 0C 00 73 02 ];
-			local-mac-address = [ 00 E0 0C 00 73 02 ];
-			interrupts = <19 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 		};
@@ -146,7 +161,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -155,7 +170,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 		pci@8000 {
@@ -163,78 +178,78 @@
 			interrupt-map = <
 
 				/* IDSEL 0x02 */
-				1000 0 0 1 &mpic 31 1
-				1000 0 0 2 &mpic 32 1
-				1000 0 0 3 &mpic 33 1
-				1000 0 0 4 &mpic 34 1
+				1000 0 0 1 &mpic 1 1
+				1000 0 0 2 &mpic 2 1
+				1000 0 0 3 &mpic 3 1
+				1000 0 0 4 &mpic 4 1
 
 				/* IDSEL 0x03 */
-				1800 0 0 1 &mpic 34 1
-				1800 0 0 2 &mpic 31 1
-				1800 0 0 3 &mpic 32 1
-				1800 0 0 4 &mpic 33 1
+				1800 0 0 1 &mpic 4 1
+				1800 0 0 2 &mpic 1 1
+				1800 0 0 3 &mpic 2 1
+				1800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x04 */
-				2000 0 0 1 &mpic 33 1
-				2000 0 0 2 &mpic 34 1
-				2000 0 0 3 &mpic 31 1
-				2000 0 0 4 &mpic 32 1
+				2000 0 0 1 &mpic 3 1
+				2000 0 0 2 &mpic 4 1
+				2000 0 0 3 &mpic 1 1
+				2000 0 0 4 &mpic 2 1
 
 				/* IDSEL 0x05 */
-				2800 0 0 1 &mpic 32 1
-				2800 0 0 2 &mpic 33 1
-				2800 0 0 3 &mpic 34 1
-				2800 0 0 4 &mpic 31 1
+				2800 0 0 1 &mpic 2 1
+				2800 0 0 2 &mpic 3 1
+				2800 0 0 3 &mpic 4 1
+				2800 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x0c */
-				6000 0 0 1 &mpic 31 1
-				6000 0 0 2 &mpic 32 1
-				6000 0 0 3 &mpic 33 1
-				6000 0 0 4 &mpic 34 1
+				6000 0 0 1 &mpic 1 1
+				6000 0 0 2 &mpic 2 1
+				6000 0 0 3 &mpic 3 1
+				6000 0 0 4 &mpic 4 1
 
 				/* IDSEL 0x0d */
-				6800 0 0 1 &mpic 34 1
-				6800 0 0 2 &mpic 31 1
-				6800 0 0 3 &mpic 32 1
-				6800 0 0 4 &mpic 33 1
+				6800 0 0 1 &mpic 4 1
+				6800 0 0 2 &mpic 1 1
+				6800 0 0 3 &mpic 2 1
+				6800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x0e */
-				7000 0 0 1 &mpic 33 1
-				7000 0 0 2 &mpic 34 1
-				7000 0 0 3 &mpic 31 1
-				7000 0 0 4 &mpic 32 1
+				7000 0 0 1 &mpic 3 1
+				7000 0 0 2 &mpic 4 1
+				7000 0 0 3 &mpic 1 1
+				7000 0 0 4 &mpic 2 1
 
 				/* IDSEL 0x0f */
-				7800 0 0 1 &mpic 32 1
-				7800 0 0 2 &mpic 33 1
-				7800 0 0 3 &mpic 34 1
-				7800 0 0 4 &mpic 31 1
+				7800 0 0 1 &mpic 2 1
+				7800 0 0 2 &mpic 3 1
+				7800 0 0 3 &mpic 4 1
+				7800 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x12 */
-				9000 0 0 1 &mpic 31 1
-				9000 0 0 2 &mpic 32 1
-				9000 0 0 3 &mpic 33 1
-				9000 0 0 4 &mpic 34 1
+				9000 0 0 1 &mpic 1 1
+				9000 0 0 2 &mpic 2 1
+				9000 0 0 3 &mpic 3 1
+				9000 0 0 4 &mpic 4 1
 
 				/* IDSEL 0x13 */
-				9800 0 0 1 &mpic 34 1
-				9800 0 0 2 &mpic 31 1
-				9800 0 0 3 &mpic 32 1
-				9800 0 0 4 &mpic 33 1
+				9800 0 0 1 &mpic 4 1
+				9800 0 0 2 &mpic 1 1
+				9800 0 0 3 &mpic 2 1
+				9800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x14 */
-				a000 0 0 1 &mpic 33 1
-				a000 0 0 2 &mpic 34 1
-				a000 0 0 3 &mpic 31 1
-				a000 0 0 4 &mpic 32 1
+				a000 0 0 1 &mpic 3 1
+				a000 0 0 2 &mpic 4 1
+				a000 0 0 3 &mpic 1 1
+				a000 0 0 4 &mpic 2 1
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 &mpic 32 1
-				a800 0 0 2 &mpic 33 1
-				a800 0 0 3 &mpic 34 1
-				a800 0 0 4 &mpic 31 1>;
+				a800 0 0 1 &mpic 2 1
+				a800 0 0 2 &mpic 3 1
+				a800 0 0 3 &mpic 4 1
+				a800 0 0 4 &mpic 1 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <08 2>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index 4f2c3af..070206f 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8541-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,13 +81,13 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
@@ -100,8 +100,8 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -113,8 +113,8 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -124,7 +124,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -133,7 +133,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -142,49 +142,49 @@
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 &mpic 30 1
-				08000 0 0 2 &mpic 31 1
-				08000 0 0 3 &mpic 32 1
-				08000 0 0 4 &mpic 33 1
+				08000 0 0 1 &mpic 0 1
+				08000 0 0 2 &mpic 1 1
+				08000 0 0 3 &mpic 2 1
+				08000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 &mpic 30 1
-				08800 0 0 2 &mpic 31 1
-				08800 0 0 3 &mpic 32 1
-				08800 0 0 4 &mpic 33 1
+				08800 0 0 1 &mpic 0 1
+				08800 0 0 2 &mpic 1 1
+				08800 0 0 3 &mpic 2 1
+				08800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 &mpic 30 1
-				09000 0 0 2 &mpic 31 1
-				09000 0 0 3 &mpic 32 1
-				09000 0 0 4 &mpic 33 1
+				09000 0 0 1 &mpic 0 1
+				09000 0 0 2 &mpic 1 1
+				09000 0 0 3 &mpic 2 1
+				09000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 &mpic 31 1
-				09800 0 0 2 &mpic 32 1
-				09800 0 0 3 &mpic 33 1
-				09800 0 0 4 &mpic 30 1
+				09800 0 0 1 &mpic 1 1
+				09800 0 0 2 &mpic 2 1
+				09800 0 0 3 &mpic 3 1
+				09800 0 0 4 &mpic 0 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 &mpic 32 1
-				0a000 0 0 2 &mpic 33 1
-				0a000 0 0 3 &mpic 30 1
-				0a000 0 0 4 &mpic 31 1
+				0a000 0 0 1 &mpic 2 1
+				0a000 0 0 2 &mpic 3 1
+				0a000 0 0 3 &mpic 0 1
+				0a000 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 &mpic 33 1
-				0a800 0 0 2 &mpic 30 1
-				0a800 0 0 3 &mpic 31 1
-				0a800 0 0 4 &mpic 32 1
+				0a800 0 0 1 &mpic 3 1
+				0a800 0 0 2 &mpic 0 1
+				0a800 0 0 3 &mpic 1 1
+				0a800 0 0 4 &mpic 2 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 &mpic 30 1
-				19000 0 0 2 &mpic 31 1
-				19000 0 0 3 &mpic 32 1
-				19000 0 0 4 &mpic 33 1>;
+				19000 0 0 1 &mpic 0 1
+				19000 0 0 2 &mpic 1 1
+				19000 0 0 3 &mpic 2 1
+				19000 0 0 4 &mpic 3 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <08 2>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
@@ -216,12 +216,12 @@
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 &mpic 3b 1
-				a800 0 0 2 &mpic 3b 1
-				a800 0 0 3 &mpic 3b 1
-				a800 0 0 4 &mpic 3b 1>;
+				a800 0 0 1 &mpic b 1
+				a800 0 0 2 &mpic b 1
+				a800 0 0 3 &mpic b 1
+				a800 0 0 4 &mpic b 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <09 2>;
+			interrupts = <19 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
 				  01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index 3033599..8285925 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8544-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,13 +81,13 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <3a 1>;
+				interrupts = <a 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <3a 1>;
+				interrupts = <a 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
@@ -101,7 +101,7 @@
 			compatible = "gianfar";
 			reg = <24000 1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -114,7 +114,7 @@
 			compatible = "gianfar";
 			reg = <26000 1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <f 2 10 2 11 2>;
+			interrupts = <1f 2 20 2 21 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -124,7 +124,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>;
 			clock-frequency = <0>;
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -133,7 +133,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;
 			clock-frequency = <0>;
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index ad96381..9d0b84b 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8548-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <80000>;	// L2, 512K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,25 +81,25 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy2: ethernet-phy@2 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -112,8 +112,8 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -125,8 +125,8 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -139,8 +139,8 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 02 ];
-			interrupts = <f 2 10 2 11 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1f 2 20 2 21 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy2>;
 		};
@@ -152,8 +152,8 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <27000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 03 ];
-			interrupts = <15 2 16 2 17 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <25 2 26 2 27 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 		};
@@ -164,7 +164,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -173,58 +173,64 @@
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
+		global-utilities@e0000 {	//global utilities reg
+			compatible = "fsl,mpc8548-guts";
+			reg = <e0000 1000>;
+			fsl,has-rstcr;
+		};
+
 		pci1: pci@8000 {
 			interrupt-map-mask = <1f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 &mpic 30 1
-				08000 0 0 2 &mpic 31 1
-				08000 0 0 3 &mpic 32 1
-				08000 0 0 4 &mpic 33 1
+				08000 0 0 1 &mpic 0 1
+				08000 0 0 2 &mpic 1 1
+				08000 0 0 3 &mpic 2 1
+				08000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 &mpic 30 1
-				08800 0 0 2 &mpic 31 1
-				08800 0 0 3 &mpic 32 1
-				08800 0 0 4 &mpic 33 1
+				08800 0 0 1 &mpic 0 1
+				08800 0 0 2 &mpic 1 1
+				08800 0 0 3 &mpic 2 1
+				08800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 &mpic 30 1
-				09000 0 0 2 &mpic 31 1
-				09000 0 0 3 &mpic 32 1
-				09000 0 0 4 &mpic 33 1
+				09000 0 0 1 &mpic 0 1
+				09000 0 0 2 &mpic 1 1
+				09000 0 0 3 &mpic 2 1
+				09000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 &mpic 31 1
-				09800 0 0 2 &mpic 32 1
-				09800 0 0 3 &mpic 33 1
-				09800 0 0 4 &mpic 30 1
+				09800 0 0 1 &mpic 1 1
+				09800 0 0 2 &mpic 2 1
+				09800 0 0 3 &mpic 3 1
+				09800 0 0 4 &mpic 0 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 &mpic 32 1
-				0a000 0 0 2 &mpic 33 1
-				0a000 0 0 3 &mpic 30 1
-				0a000 0 0 4 &mpic 31 1
+				0a000 0 0 1 &mpic 2 1
+				0a000 0 0 2 &mpic 3 1
+				0a000 0 0 3 &mpic 0 1
+				0a000 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 &mpic 33 1
-				0a800 0 0 2 &mpic 30 1
-				0a800 0 0 3 &mpic 31 1
-				0a800 0 0 4 &mpic 32 1
+				0a800 0 0 1 &mpic 3 1
+				0a800 0 0 2 &mpic 0 1
+				0a800 0 0 3 &mpic 1 1
+				0a800 0 0 4 &mpic 2 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 &mpic 30 1
-				19000 0 0 2 &mpic 31 1
-				19000 0 0 3 &mpic 32 1
-				19000 0 0 4 &mpic 33 1>;
+				19000 0 0 1 &mpic 0 1
+				19000 0 0 2 &mpic 1 1
+				19000 0 0 3 &mpic 2 1
+				19000 0 0 4 &mpic 3 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <08 2>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
@@ -256,12 +262,12 @@
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 &mpic 3b 1
-				a800 0 0 2 &mpic 3b 1
-				a800 0 0 3 &mpic 3b 1
-				a800 0 0 4 &mpic 3b 1>;
+				a800 0 0 1 &mpic b 1
+				a800 0 0 2 &mpic b 1
+				a800 0 0 3 &mpic b 1
+				a800 0 0 4 &mpic b 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <09 2>;
+			interrupts = <19 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
 				  01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 951ed92..17e45d9 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8555-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -81,13 +81,13 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 0>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
@@ -100,8 +100,8 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <0d 2 0e 2 12 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -113,8 +113,8 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -124,7 +124,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -133,7 +133,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -142,49 +142,49 @@
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 &mpic 30 1
-				08000 0 0 2 &mpic 31 1
-				08000 0 0 3 &mpic 32 1
-				08000 0 0 4 &mpic 33 1
+				08000 0 0 1 &mpic 0 1
+				08000 0 0 2 &mpic 1 1
+				08000 0 0 3 &mpic 2 1
+				08000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 &mpic 30 1
-				08800 0 0 2 &mpic 31 1
-				08800 0 0 3 &mpic 32 1
-				08800 0 0 4 &mpic 33 1
+				08800 0 0 1 &mpic 0 1
+				08800 0 0 2 &mpic 1 1
+				08800 0 0 3 &mpic 2 1
+				08800 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 &mpic 30 1
-				09000 0 0 2 &mpic 31 1
-				09000 0 0 3 &mpic 32 1
-				09000 0 0 4 &mpic 33 1
+				09000 0 0 1 &mpic 0 1
+				09000 0 0 2 &mpic 1 1
+				09000 0 0 3 &mpic 2 1
+				09000 0 0 4 &mpic 3 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 &mpic 31 1
-				09800 0 0 2 &mpic 32 1
-				09800 0 0 3 &mpic 33 1
-				09800 0 0 4 &mpic 30 1
+				09800 0 0 1 &mpic 1 1
+				09800 0 0 2 &mpic 2 1
+				09800 0 0 3 &mpic 3 1
+				09800 0 0 4 &mpic 0 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 &mpic 32 1
-				0a000 0 0 2 &mpic 33 1
-				0a000 0 0 3 &mpic 30 1
-				0a000 0 0 4 &mpic 31 1
+				0a000 0 0 1 &mpic 2 1
+				0a000 0 0 2 &mpic 3 1
+				0a000 0 0 3 &mpic 0 1
+				0a000 0 0 4 &mpic 1 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 &mpic 33 1
-				0a800 0 0 2 &mpic 30 1
-				0a800 0 0 3 &mpic 31 1
-				0a800 0 0 4 &mpic 32 1
+				0a800 0 0 1 &mpic 3 1
+				0a800 0 0 2 &mpic 0 1
+				0a800 0 0 3 &mpic 1 1
+				0a800 0 0 4 &mpic 2 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 &mpic 30 1
-				19000 0 0 2 &mpic 31 1
-				19000 0 0 3 &mpic 32 1
-				19000 0 0 4 &mpic 33 1>;
+				19000 0 0 1 &mpic 0 1
+				19000 0 0 2 &mpic 1 1
+				19000 0 0 3 &mpic 2 1
+				19000 0 0 4 &mpic 3 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <08 2>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
@@ -216,12 +216,12 @@
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 &mpic 3b 1
-				a800 0 0 2 &mpic 3b 1
-				a800 0 0 3 &mpic 3b 1
-				a800 0 0 4 &mpic 3b 1>;
+				a800 0 0 1 &mpic b 1
+				a800 0 0 2 &mpic b 1
+				a800 0 0 3 &mpic b 1
+				a800 0 0 4 &mpic b 1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <09 2>;
+			interrupts = <19 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
 				  01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 8068215..21ccaaa 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -52,7 +52,7 @@
 			compatible = "fsl,8540-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -61,7 +61,7 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <40000>;	// L2, 256K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		mdio@24520 {
@@ -72,25 +72,25 @@
 			#size-cells = <0>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 1>;
+				interrupts = <5 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <35 1>;
+				interrupts = <5 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy2: ethernet-phy@2 {
 				interrupt-parent = <&mpic>;
-				interrupts = <37 1>;
+				interrupts = <7 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <37 1>;
+				interrupts = <7 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -101,8 +101,14 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			address = [ 00 00 0C 00 00 FD ];
-			interrupts = <d 2 e 2 12 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
@@ -114,8 +120,14 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			address = [ 00 00 0C 00 01 FD ];
-			interrupts = <13 2 14 2 18 2>;
+			/*
+			 * address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
@@ -132,79 +144,79 @@
 			interrupt-map = <
 
 					/* IDSEL 0x2 */
-					 1000 0 0 1 &mpic 31 1
-					 1000 0 0 2 &mpic 32 1
-					 1000 0 0 3 &mpic 33 1
-					 1000 0 0 4 &mpic 34 1
+					 1000 0 0 1 &mpic 1 1
+					 1000 0 0 2 &mpic 2 1
+					 1000 0 0 3 &mpic 3 1
+					 1000 0 0 4 &mpic 4 1
 
 					/* IDSEL 0x3 */
-					 1800 0 0 1 &mpic 34 1
-					 1800 0 0 2 &mpic 31 1
-					 1800 0 0 3 &mpic 32 1
-					 1800 0 0 4 &mpic 33 1
+					 1800 0 0 1 &mpic 4 1
+					 1800 0 0 2 &mpic 1 1
+					 1800 0 0 3 &mpic 2 1
+					 1800 0 0 4 &mpic 3 1
 
 					/* IDSEL 0x4 */
-					 2000 0 0 1 &mpic 33 1
-					 2000 0 0 2 &mpic 34 1
-					 2000 0 0 3 &mpic 31 1
-					 2000 0 0 4 &mpic 32 1
+					 2000 0 0 1 &mpic 3 1
+					 2000 0 0 2 &mpic 4 1
+					 2000 0 0 3 &mpic 1 1
+					 2000 0 0 4 &mpic 2 1
 
 					/* IDSEL 0x5  */
-					 2800 0 0 1 &mpic 32 1
-					 2800 0 0 2 &mpic 33 1
-					 2800 0 0 3 &mpic 34 1
-					 2800 0 0 4 &mpic 31 1
+					 2800 0 0 1 &mpic 2 1
+					 2800 0 0 2 &mpic 3 1
+					 2800 0 0 3 &mpic 4 1
+					 2800 0 0 4 &mpic 1 1
 
 					/* IDSEL 12 */
-					 6000 0 0 1 &mpic 31 1
-					 6000 0 0 2 &mpic 32 1
-					 6000 0 0 3 &mpic 33 1
-					 6000 0 0 4 &mpic 34 1
+					 6000 0 0 1 &mpic 1 1
+					 6000 0 0 2 &mpic 2 1
+					 6000 0 0 3 &mpic 3 1
+					 6000 0 0 4 &mpic 4 1
 
 					/* IDSEL 13 */
-					 6800 0 0 1 &mpic 34 1
-					 6800 0 0 2 &mpic 31 1
-					 6800 0 0 3 &mpic 32 1
-					 6800 0 0 4 &mpic 33 1
+					 6800 0 0 1 &mpic 4 1
+					 6800 0 0 2 &mpic 1 1
+					 6800 0 0 3 &mpic 2 1
+					 6800 0 0 4 &mpic 3 1
 
 					/* IDSEL 14*/
-					 7000 0 0 1 &mpic 33 1
-					 7000 0 0 2 &mpic 34 1
-					 7000 0 0 3 &mpic 31 1
-					 7000 0 0 4 &mpic 32 1
+					 7000 0 0 1 &mpic 3 1
+					 7000 0 0 2 &mpic 4 1
+					 7000 0 0 3 &mpic 1 1
+					 7000 0 0 4 &mpic 2 1
 
 					/* IDSEL 15 */
-					 7800 0 0 1 &mpic 32 1
-					 7800 0 0 2 &mpic 33 1
-					 7800 0 0 3 &mpic 34 1
-					 7800 0 0 4 &mpic 31 1
+					 7800 0 0 1 &mpic 2 1
+					 7800 0 0 2 &mpic 3 1
+					 7800 0 0 3 &mpic 4 1
+					 7800 0 0 4 &mpic 1 1
 
 					/* IDSEL 18 */
-					 9000 0 0 1 &mpic 31 1
-					 9000 0 0 2 &mpic 32 1
-					 9000 0 0 3 &mpic 33 1
-					 9000 0 0 4 &mpic 34 1
+					 9000 0 0 1 &mpic 1 1
+					 9000 0 0 2 &mpic 2 1
+					 9000 0 0 3 &mpic 3 1
+					 9000 0 0 4 &mpic 4 1
 
 					/* IDSEL 19 */
-					 9800 0 0 1 &mpic 34 1
-					 9800 0 0 2 &mpic 31 1
-					 9800 0 0 3 &mpic 32 1
-					 9800 0 0 4 &mpic 33 1
+					 9800 0 0 1 &mpic 4 1
+					 9800 0 0 2 &mpic 1 1
+					 9800 0 0 3 &mpic 2 1
+					 9800 0 0 4 &mpic 3 1
 
 					/* IDSEL 20 */
-					 a000 0 0 1 &mpic 33 1
-					 a000 0 0 2 &mpic 34 1
-					 a000 0 0 3 &mpic 31 1
-					 a000 0 0 4 &mpic 32 1
+					 a000 0 0 1 &mpic 3 1
+					 a000 0 0 2 &mpic 4 1
+					 a000 0 0 3 &mpic 1 1
+					 a000 0 0 4 &mpic 2 1
 
 					/* IDSEL 21 */
-					 a800 0 0 1 &mpic 32 1
-					 a800 0 0 2 &mpic 33 1
-					 a800 0 0 3 &mpic 34 1
-					 a800 0 0 4 &mpic 31 1>;
+					 a800 0 0 1 &mpic 2 1
+					 a800 0 0 2 &mpic 3 1
+					 a800 0 0 3 &mpic 4 1
+					 a800 0 0 4 &mpic 1 1>;
 
 			interrupt-parent = <&mpic>;
-			interrupts = <8 0>;
+			interrupts = <18 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 01000000>;
@@ -234,7 +246,7 @@
 				interrupt-controller;
 				#address-cells = <0>;
 				#interrupt-cells = <2>;
-				interrupts = <1e 0>;
+				interrupts = <2e 2>;
 				interrupt-parent = <&mpic>;
 				reg = <90c00 80>;
 				built-in;
@@ -275,7 +287,13 @@
 				model = "FCC";
 				device-id = <2>;
 				reg = <91320 20 88500 100 913a0 30>;
-				mac-address = [ 00 00 0C 00 02 FD ];
+				/*
+				 * mac-address is deprecated and will be removed
+				 * in 2.6.25.  Only recent versions of
+				 * U-Boot support local-mac-address, however.
+				 */
+				mac-address = [ 00 00 00 00 00 00 ];
+				local-mac-address = [ 00 00 00 00 00 00 ];
 				clock-setup = <ff00ffff 250000>;
 				rx-clock = <15>;
 				tx-clock = <16>;
@@ -290,7 +308,13 @@
 				model = "FCC";
 				device-id = <3>;
 				reg = <91340 20 88600 100 913d0 30>;
-				mac-address = [ 00 00 0C 00 03 FD ];
+				/*
+				 * mac-address is deprecated and will be removed
+				 * in 2.6.25.  Only recent versions of
+				 * U-Boot support local-mac-address, however.
+				 */
+				mac-address = [ 00 00 00 00 00 00 ];
+				local-mac-address = [ 00 00 00 00 00 00 ];
 				clock-setup = <ffff00ff 3700>;
 				rx-clock = <17>;
 				tx-clock = <18>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index a123ec9..6bb18f2 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -61,7 +61,7 @@
 			compatible = "fsl,8568-memory-controller";
 			reg = <2000 1000>;
 			interrupt-parent = <&mpic>;
-			interrupts = <2 2>;
+			interrupts = <12 2>;
 		};
 
 		l2-cache-controller@20000 {
@@ -70,14 +70,14 @@
 			cache-line-size = <20>;	// 32 bytes
 			cache-size = <80000>;	// L2, 512K
 			interrupt-parent = <&mpic>;
-			interrupts = <0 2>;
+			interrupts = <10 2>;
 		};
 
 		i2c@3000 {
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -86,7 +86,7 @@
 			device_type = "i2c";
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
-			interrupts = <1b 2>;
+			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
@@ -99,25 +99,25 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <31 1>;
+				interrupts = <1 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <32 1>;
+				interrupts = <2 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy2: ethernet-phy@2 {
 				interrupt-parent = <&mpic>;
-				interrupts = <31 1>;
+				interrupts = <1 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <32 1>;
+				interrupts = <2 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -130,8 +130,14 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
 			mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <d 2 e 2 12 2>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy2>;
 		};
@@ -143,8 +149,14 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			mac-address = [ 00 00 00 00 00 00];
-			interrupts = <13 2 14 2 18 2>;
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 		};
@@ -154,7 +166,7 @@
 			compatible = "ns16550";
 			reg = <4500 100>;
 			clock-frequency = <0>;
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -163,7 +175,7 @@
 			compatible = "ns16550";
 			reg = <4600 100>;
 			clock-frequency = <0>;
-			interrupts = <1a 2>;
+			interrupts = <2a 2>;
 			interrupt-parent = <&mpic>;
 		};
 
@@ -172,7 +184,7 @@
 			model = "SEC2";
 			compatible = "talitos";
 			reg = <30000 f000>;
-			interrupts = <1d 2>;
+			interrupts = <2d 2>;
 			interrupt-parent = <&mpic>;
 			num-channels = <4>;
 			channel-fifo-len = <18>;
@@ -300,7 +312,13 @@
 			reg = <2000 200>;
 			interrupts = <20>;
 			interrupt-parent = <&qeic>;
-			mac-address = [ 00 04 9f 00 23 23 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <0>;
 			tx-clock = <19>;
 			phy-handle = <&qe_phy0>;
@@ -316,7 +334,13 @@
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = <&qeic>;
-			mac-address = [ 00 11 22 33 44 55 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			rx-clock = <0>;
 			tx-clock = <14>;
 			phy-handle = <&qe_phy1>;
@@ -335,25 +359,25 @@
 			 * gianfar's MDIO bus */
 			qe_phy0: ethernet-phy@00 {
 				interrupt-parent = <&mpic>;
-				interrupts = <31 1>;
+				interrupts = <1 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			qe_phy1: ethernet-phy@01 {
 				interrupt-parent = <&mpic>;
-				interrupts = <32 1>;
+				interrupts = <2 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			qe_phy2: ethernet-phy@02 {
 				interrupt-parent = <&mpic>;
-				interrupts = <31 1>;
+				interrupts = <1 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			qe_phy3: ethernet-phy@03 {
 				interrupt-parent = <&mpic>;
-				interrupts = <32 1>;
+				interrupts = <2 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -367,7 +391,7 @@
 			reg = <80 80>;
 			built-in;
 			big-endian;
-			interrupts = <1e 2 1e 2>; //high:30 low:30
+			interrupts = <2e 2 2e 2>; //high:30 low:30
 			interrupt-parent = <&mpic>;
 		};
 
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index 260b264..db56a02 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -56,8 +56,12 @@
 		#size-cells = <1>;
 		#interrupt-cells = <2>;
 		device_type = "soc";
-		ranges = <0 f8000000 00100000>;
-		reg = <f8000000 00100000>;	// CCSRBAR 1M
+		ranges = <00001000 f8001000 000ff000
+			  80000000 80000000 20000000
+			  e2000000 e2000000 00100000
+			  a0000000 a0000000 20000000
+			  e3000000 e3000000 00100000>;
+		reg = <f8000000 00001000>;	// CCSRBAR
 		bus-frequency = <0>;
 
 		i2c@3000 {
@@ -86,25 +90,25 @@
 			reg = <24520 20>;
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
-				interrupts = <4a 1>;
+				interrupts = <a 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
 			phy1: ethernet-phy@1 {
 				interrupt-parent = <&mpic>;
-				interrupts = <4a 1>;
+				interrupts = <a 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
 			phy2: ethernet-phy@2 {
 				interrupt-parent = <&mpic>;
-				interrupts = <4a 1>;
+				interrupts = <a 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
 			phy3: ethernet-phy@3 {
 				interrupt-parent = <&mpic>;
-				interrupts = <4a 1>;
+				interrupts = <a 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
 			};
@@ -117,7 +121,13 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			mac-address = [ 00 E0 0C 00 73 00 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
@@ -130,7 +140,13 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			mac-address = [ 00 E0 0C 00 73 01 ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
@@ -143,7 +159,13 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			mac-address = [ 00 E0 0C 00 02 FD ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <1F 2 20 2 21 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy2>;
@@ -156,7 +178,13 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <27000 1000>;
-			mac-address = [ 00 E0 0C 00 03 FD ];
+			/*
+			 * mac-address is deprecated and will be removed
+			 * in 2.6.25.  Only recent versions of
+			 * U-Boot support local-mac-address, however.
+			 */
+			mac-address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <25 2 26 2 27 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
@@ -186,7 +214,7 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			reg = <8000 1000>;
-			bus-range = <0 fe>;
+			bus-range = <0 ff>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
 			clock-frequency = <1fca055>;
@@ -285,17 +313,84 @@
 				f800 0 0 3 &i8259 0 0
 				f800 0 0 4 &i8259 0 0
 				>;
-			i8259: i8259@4d0 {
-				clock-frequency = <0>;
-				interrupt-controller;
-				device_type = "interrupt-controller";
-				#address-cells = <0>;
-				#interrupt-cells = <2>;
-				built-in;
-				compatible = "chrp,iic";
-                	        big-endian;
-				interrupts = <49 2>;
-				interrupt-parent = <&mpic>;
+			uli1575@0 {
+				reg = <0 0 0 0 0>;
+				#size-cells = <2>;
+				#address-cells = <3>;
+				ranges = <02000000 0 80000000
+					  02000000 0 80000000
+					  0 20000000
+					  01000000 0 00000000
+					  01000000 0 00000000
+					  0 00100000>;
+
+				pci_bridge@0 {
+					reg = <0 0 0 0 0>;
+					#size-cells = <2>;
+					#address-cells = <3>;
+					ranges = <02000000 0 80000000
+						  02000000 0 80000000
+						  0 20000000
+						  01000000 0 00000000
+						  01000000 0 00000000
+						  0 00100000>;
+
+					isa@1e {
+						device_type = "isa";
+						#interrupt-cells = <2>;
+						#size-cells = <1>;
+						#address-cells = <2>;
+						reg = <f000 0 0 0 0>;
+						ranges = <1 0 01000000 0 0
+							  00001000>;
+						interrupt-parent = <&i8259>;
+
+						i8259: interrupt-controller@20 {
+							reg = <1 20 2
+							       1 a0 2
+							       1 4d0 2>;
+							clock-frequency = <0>;
+							interrupt-controller;
+							device_type = "interrupt-controller";
+							#address-cells = <0>;
+							#interrupt-cells = <2>;
+							built-in;
+							compatible = "chrp,iic";
+							interrupts = <9 2>;
+							interrupt-parent =
+								<&mpic>;
+						};
+
+						i8042@60 {
+							#size-cells = <0>;
+							#address-cells = <1>;
+							reg = <1 60 1 1 64 1>;
+							interrupts = <1 3 c 3>;
+							interrupt-parent =
+								<&i8259>;
+
+							keyboard@0 {
+								reg = <0>;
+								compatible = "pnpPNP,303";
+							};
+
+							mouse@1 {
+								reg = <1>;
+								compatible = "pnpPNP,f03";
+							};
+						};
+
+						rtc@70 {
+							compatible =
+								"pnpPNP,b00";
+							reg = <1 70 2>;
+						};
+
+						gpio@400 {
+							reg = <1 400 80>;
+						};
+					};
+				};
 			};
 
 		};
@@ -316,10 +411,10 @@
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 44 1
-				0000 0 0 2 &mpic 45 1
-				0000 0 0 3 &mpic 46 1
-				0000 0 0 4 &mpic 47 1
+				0000 0 0 1 &mpic 4 1
+				0000 0 0 2 &mpic 5 1
+				0000 0 0 3 &mpic 6 1
+				0000 0 0 4 &mpic 7 1
 				>;
 		};
 
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
index c0d06fd..e5e7726 100644
--- a/arch/powerpc/boot/dts/mpc866ads.dts
+++ b/arch/powerpc/boot/dts/mpc866ads.dts
@@ -15,12 +15,10 @@
 	compatible = "mpc8xx";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,866@0 {
 			device_type = "cpu";
@@ -34,14 +32,12 @@
 			clock-frequency = <0>;
 			32-bit;
 			interrupts = <f 2>;	// decrementer interrupt
-			interrupt-parent = <ff000000>;
-			linux,phandle = <201>;
+			interrupt-parent = <&Mpc8xx_pic>;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 800000>;
 	};
 
@@ -57,11 +53,9 @@
 			device_type = "mdio";
 			compatible = "fs_enet";
 			reg = <e80 8>;
-			linux,phandle = <e80>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			ethernet-phy@f {
-				linux,phandle = <e800f>;
+			phy: ethernet-phy@f {
 				reg = <f>;
 				device_type = "ethernet-phy";
 			};
@@ -75,12 +69,11 @@
 			reg = <e00 188>;
 			mac-address = [ 00 00 0C 00 01 FD ];
 			interrupts = <3 1>;
-			interrupt-parent = <ff000000>;
-			phy-handle = <e800f>;
+			interrupt-parent = <&Mpc8xx_pic>;
+			phy-handle = <&Phy>;
 		};
 
-		pic@ff000000 {
-			linux,phandle = <ff000000>;
+		mpc8xx_pic: pic@ff000000 {
 			interrupt-controller;
 			#address-cells = <0>;
 			#interrupt-cells = <2>;
@@ -91,7 +84,6 @@
 		};
 
 		cpm@ff000000 {
-			linux,phandle = <ff000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			#interrupt-cells = <2>;
@@ -102,15 +94,14 @@
 			command-proc = <9c0>;
 			brg-frequency = <0>;
 			interrupts = <0 2>;	// cpm error interrupt
-			interrupt-parent = <930>;
+			interrupt-parent = <&Cpm_pic>;
 
-			pic@930 {
-				linux,phandle = <930>;
+			cpm_pic: pic@930 {
 				interrupt-controller;
 				#address-cells = <0>;
 				#interrupt-cells = <2>;
 				interrupts = <5 2 0 2>;
-				interrupt-parent = <ff000000>;
+				interrupt-parent = <&Mpc8xx_pic>;
 				reg = <930 20>;
 				built-in;
 				device_type = "cpm-pic";
@@ -128,7 +119,7 @@
 				tx-clock = <1>;
 				current-speed = <0>;
 				interrupts = <4 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 
 			smc@a90 {
@@ -142,7 +133,7 @@
 				tx-clock = <2>;
 				current-speed = <0>;
 				interrupts = <3 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 
 			scc@a00 {
@@ -153,7 +144,7 @@
 				reg = <a00 18 3c00 80>;
 				mac-address = [ 00 00 0C 00 03 FD ];
 				interrupts = <1e 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 		};
 	};
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index 110bf61..dc7ab9c 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -15,12 +15,10 @@
 	compatible = "mpc8xx";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,885@0 {
 			device_type = "cpu";
@@ -34,14 +32,12 @@
 			clock-frequency = <0>;
 			32-bit;
 			interrupts = <f 2>;	// decrementer interrupt
-			interrupt-parent = <ff000000>;
-			linux,phandle = <201>;
+			interrupt-parent = <&Mpc8xx_pic>;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 800000>;
 	};
 
@@ -57,21 +53,17 @@
 			device_type = "mdio";
 			compatible = "fs_enet";
 			reg = <e80 8>;
-			linux,phandle = <e80>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			ethernet-phy@0 {
-				linux,phandle = <e8000>;
+			Phy0: ethernet-phy@0 {
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@1 {
-				linux,phandle = <e8001>;
+			Phy1: ethernet-phy@1 {
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@2 {
-				linux,phandle = <e8002>;
+			Phy2: ethernet-phy@2 {
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
@@ -85,8 +77,8 @@
 			reg = <e00 188>;
 			mac-address = [ 00 00 0C 00 01 FD ];
 			interrupts = <3 1>;
-			interrupt-parent = <ff000000>;
-			phy-handle = <e8000>;
+			interrupt-parent = <&Mpc8xx_pic>;
+			phy-handle = <&Phy1>;
 		};
 
 		fec@1e00 {
@@ -97,12 +89,11 @@
 			reg = <1e00 188>;
 			mac-address = [ 00 00 0C 00 02 FD ];
 			interrupts = <7 1>;
-			interrupt-parent = <ff000000>;
-			phy-handle = <e8001>;
+			interrupt-parent = <&Mpc8xx_pic>;
+			phy-handle = <&Phy2>;
 		};
 
-		pic@ff000000 {
-			linux,phandle = <ff000000>;
+		Mpc8xx_pic: pic@ff000000 {
 			interrupt-controller;
 			#address-cells = <0>;
 			#interrupt-cells = <2>;
@@ -112,8 +103,18 @@
 			compatible = "CPM";
 		};
 
+		pcmcia@0080 {
+			#address-cells = <3>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			compatible = "fsl,pq-pcmcia";
+			device_type = "pcmcia";
+			reg = <80 80>;
+			interrupt-parent = <&Mpc8xx_pic>;
+			interrupts = <d 1>;
+		};
+
 		cpm@ff000000 {
-			linux,phandle = <ff000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			#interrupt-cells = <2>;
@@ -124,15 +125,14 @@
 			command-proc = <9c0>;
 			brg-frequency = <0>;
 			interrupts = <0 2>;	// cpm error interrupt
-			interrupt-parent = <930>;
+			interrupt-parent = <&Cpm_pic>;
 
-			pic@930 {
-				linux,phandle = <930>;
+			Cpm_pic: pic@930 {
 				interrupt-controller;
 				#address-cells = <0>;
 				#interrupt-cells = <2>;
 				interrupts = <5 2 0 2>;
-				interrupt-parent = <ff000000>;
+				interrupt-parent = <&Mpc8xx_pic>;
 				reg = <930 20>;
 				built-in;
 				device_type = "cpm-pic";
@@ -150,7 +150,7 @@
 				tx-clock = <1>;
 				current-speed = <0>;
 				interrupts = <4 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 
 			smc@a90 {
@@ -164,7 +164,7 @@
 				tx-clock = <2>;
 				current-speed = <0>;
 				interrupts = <3 3>;
-				interrupt-parent = <930>;
+				interrupt-parent = <&Cpm_pic>;
 			};
 
 			scc@a40 {
@@ -175,8 +175,8 @@
 				reg = <a40 18 3e00 80>;
 				mac-address = [ 00 00 0C 00 03 FD ];
 				interrupts = <1c 3>;
-				interrupt-parent = <930>;
-				phy-handle = <e8002>;
+				interrupt-parent = <&Cpm_pic>;
+				phy-handle = <&Phy2>;
 			};
 		};
 	};
diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts
index 568965a..699d0df 100644
--- a/arch/powerpc/boot/dts/prpmc2800.dts
+++ b/arch/powerpc/boot/dts/prpmc2800.dts
@@ -309,7 +309,7 @@
 	};
 
 	chosen {
-		bootargs = "ip=on console=ttyMM0";
+		bootargs = "ip=on";
 		linux,stdout-path = "/mv64x60@f1000000/mpsc@8000";
 	};
 };
diff --git a/arch/powerpc/boot/dts/ps3.dts b/arch/powerpc/boot/dts/ps3.dts
new file mode 100644
index 0000000..379ded2
--- /dev/null
+++ b/arch/powerpc/boot/dts/ps3.dts
@@ -0,0 +1,68 @@
+/*
+ *  PS3 Game Console device tree.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/ {
+	model = "SonyPS3";
+	compatible = "sony,ps3";
+	#size-cells = <2>;
+	#address-cells = <2>;
+
+	chosen {
+	};
+
+	/*
+	 * We'll get the size of the bootmem block from lv1 after startup,
+	 * so we'll put a null entry here.
+	 */
+
+	memory {
+		device_type = "memory";
+		reg = <0 0 0 0>;
+	};
+
+	/*
+	 * The boot cpu is always zero for PS3.
+	 *
+	 * dtc expects a clock-frequency and timebase-frequency entries, so
+	 * we'll put a null entries here.  These will be initialized after
+	 * startup with data from lv1.
+	 *
+	 * Seems the only way currently to indicate a processor has multiple
+	 * threads is with an ibm,ppc-interrupt-server#s entry.  We'll put one
+	 * here so we can bring up both of ours.  See smp_setup_cpu_maps().
+	 */
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			ibm,ppc-interrupt-server#s = <0 1>;
+			clock-frequency = <0>;
+			timebase-frequency = <0>;
+			i-cache-size = <8000>;
+			d-cache-size = <8000>;
+			i-cache-line-size = <80>;
+			d-cache-line-size = <80>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c
index b1251ee..75daeda 100644
--- a/arch/powerpc/boot/ebony.c
+++ b/arch/powerpc/boot/ebony.c
@@ -100,28 +100,13 @@
 	ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
 	ibm44x_fixup_memsize();
 	dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
-}
-
-#define SPRN_DBCR0		0x134
-#define   DBCR0_RST_SYSTEM	0x30000000
-
-static void ebony_exit(void)
-{
-	unsigned long tmp;
-
-	asm volatile (
-		"mfspr	%0,%1\n"
-		"oris	%0,%0,%2@h\n"
-		"mtspr	%1,%0"
-		: "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
-		);
-
+	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
 }
 
 void ebony_init(void *mac0, void *mac1)
 {
 	platform_ops.fixups = ebony_fixups;
-	platform_ops.exit = ebony_exit;
+	platform_ops.exit = ibm44x_dbcr_reset;
 	ebony_mac0 = mac0;
 	ebony_mac1 = mac1;
 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 56b56a8..416dc38 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -36,8 +36,6 @@
 	unsigned long size;
 };
 
-typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
-
 #undef DEBUG
 
 static struct addr_range prep_kernel(void)
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index d16ee3e..385e08b 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -15,8 +15,7 @@
 #include "page.h"
 #include "ops.h"
 
-typedef void *ihandle;
-typedef void *phandle;
+#include "of.h"
 
 extern char _end[];
 
@@ -25,154 +24,10 @@
 #define RAM_END		(512<<20)	/* Fixme: use OF */
 #define	ONE_MB		0x100000
 
-int (*prom) (void *);
 
 
 static unsigned long claim_base;
 
-static int call_prom(const char *service, int nargs, int nret, ...)
-{
-	int i;
-	struct prom_args {
-		const char *service;
-		int nargs;
-		int nret;
-		unsigned int args[12];
-	} args;
-	va_list list;
-
-	args.service = service;
-	args.nargs = nargs;
-	args.nret = nret;
-
-	va_start(list, nret);
-	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, unsigned int);
-	va_end(list);
-
-	for (i = 0; i < nret; i++)
-		args.args[nargs+i] = 0;
-
-	if (prom(&args) < 0)
-		return -1;
-
-	return (nret > 0)? args.args[nargs]: 0;
-}
-
-static int call_prom_ret(const char *service, int nargs, int nret,
-		  unsigned int *rets, ...)
-{
-	int i;
-	struct prom_args {
-		const char *service;
-		int nargs;
-		int nret;
-		unsigned int args[12];
-	} args;
-	va_list list;
-
-	args.service = service;
-	args.nargs = nargs;
-	args.nret = nret;
-
-	va_start(list, rets);
-	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, unsigned int);
-	va_end(list);
-
-	for (i = 0; i < nret; i++)
-		args.args[nargs+i] = 0;
-
-	if (prom(&args) < 0)
-		return -1;
-
-	if (rets != (void *) 0)
-		for (i = 1; i < nret; ++i)
-			rets[i-1] = args.args[nargs+i];
-
-	return (nret > 0)? args.args[nargs]: 0;
-}
-
-/*
- * Older OF's require that when claiming a specific range of addresses,
- * we claim the physical space in the /memory node and the virtual
- * space in the chosen mmu node, and then do a map operation to
- * map virtual to physical.
- */
-static int need_map = -1;
-static ihandle chosen_mmu;
-static phandle memory;
-
-/* returns true if s2 is a prefix of s1 */
-static int string_match(const char *s1, const char *s2)
-{
-	for (; *s2; ++s2)
-		if (*s1++ != *s2)
-			return 0;
-	return 1;
-}
-
-static int check_of_version(void)
-{
-	phandle oprom, chosen;
-	char version[64];
-
-	oprom = finddevice("/openprom");
-	if (oprom == (phandle) -1)
-		return 0;
-	if (getprop(oprom, "model", version, sizeof(version)) <= 0)
-		return 0;
-	version[sizeof(version)-1] = 0;
-	printf("OF version = '%s'\r\n", version);
-	if (!string_match(version, "Open Firmware, 1.")
-	    && !string_match(version, "FirmWorks,3."))
-		return 0;
-	chosen = finddevice("/chosen");
-	if (chosen == (phandle) -1) {
-		chosen = finddevice("/chosen@0");
-		if (chosen == (phandle) -1) {
-			printf("no chosen\n");
-			return 0;
-		}
-	}
-	if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
-		printf("no mmu\n");
-		return 0;
-	}
-	memory = (ihandle) call_prom("open", 1, 1, "/memory");
-	if (memory == (ihandle) -1) {
-		memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
-		if (memory == (ihandle) -1) {
-			printf("no memory node\n");
-			return 0;
-		}
-	}
-	printf("old OF detected\r\n");
-	return 1;
-}
-
-static void *claim(unsigned long virt, unsigned long size, unsigned long align)
-{
-	int ret;
-	unsigned int result;
-
-	if (need_map < 0)
-		need_map = check_of_version();
-	if (align || !need_map)
-		return (void *) call_prom("claim", 3, 1, virt, size, align);
-
-	ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
-			    align, size, virt);
-	if (ret != 0 || result == -1)
-		return (void *) -1;
-	ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
-			    align, size, virt);
-	/* 0x12 == coherent + read/write */
-	ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
-			0x12, size, virt, virt);
-	return (void *) virt;
-}
-
 static void *of_try_claim(unsigned long size)
 {
 	unsigned long addr = 0;
@@ -184,7 +39,7 @@
 #ifdef DEBUG
 		printf("    trying: 0x%08lx\n\r", claim_base);
 #endif
-		addr = (unsigned long)claim(claim_base, size, 0);
+		addr = (unsigned long)of_claim(claim_base, size, 0);
 		if ((void *)addr != (void *)-1)
 			break;
 	}
@@ -208,64 +63,6 @@
 	}
 }
 
-static void *of_vmlinux_alloc(unsigned long size)
-{
-	void *p = malloc(size);
-
-	if (!p)
-		fatal("Can't allocate memory for kernel image!\n\r");
-
-	return p;
-}
-
-static void of_exit(void)
-{
-	call_prom("exit", 0, 0);
-}
-
-/*
- * OF device tree routines
- */
-static void *of_finddevice(const char *name)
-{
-	return (phandle) call_prom("finddevice", 1, 1, name);
-}
-
-static int of_getprop(const void *phandle, const char *name, void *buf,
-		const int buflen)
-{
-	return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
-}
-
-static int of_setprop(const void *phandle, const char *name, const void *buf,
-		const int buflen)
-{
-	return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
-}
-
-/*
- * OF console routines
- */
-static void *of_stdout_handle;
-
-static int of_console_open(void)
-{
-	void *devp;
-
-	if (((devp = finddevice("/chosen")) != NULL)
-			&& (getprop(devp, "stdout", &of_stdout_handle,
-				sizeof(of_stdout_handle))
-				== sizeof(of_stdout_handle)))
-		return 0;
-
-	return -1;
-}
-
-static void of_console_write(char *buf, int len)
-{
-	call_prom("write", 3, 1, of_stdout_handle, buf, len);
-}
-
 void platform_init(unsigned long a1, unsigned long a2, void *promptr)
 {
 	platform_ops.image_hdr = of_image_hdr;
@@ -277,10 +74,9 @@
 	dt_ops.getprop = of_getprop;
 	dt_ops.setprop = of_setprop;
 
-	console_ops.open = of_console_open;
-	console_ops.write = of_console_write;
+	of_console_init();
 
-	prom = (int (*)(void *))promptr;
+	of_init(promptr);
 	loader_info.promptr = promptr;
 	if (a1 && a2 && a2 != 0xdeadbeef) {
 		loader_info.initrd_addr = a1;
diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
new file mode 100644
index 0000000..e4c68f7
--- /dev/null
+++ b/arch/powerpc/boot/of.h
@@ -0,0 +1,21 @@
+#ifndef _PPC_BOOT_OF_H_
+#define _PPC_BOOT_OF_H_
+
+typedef void *phandle;
+typedef void *ihandle;
+
+void of_init(void *promptr);
+int of_call_prom(const char *service, int nargs, int nret, ...);
+void *of_claim(unsigned long virt, unsigned long size, unsigned long align);
+void *of_vmlinux_alloc(unsigned long size);
+void of_exit(void);
+void *of_finddevice(const char *name);
+int of_getprop(const void *phandle, const char *name, void *buf,
+	       const int buflen);
+int of_setprop(const void *phandle, const char *name, const void *buf,
+	       const int buflen);
+
+/* Console functions */
+void of_console_init(void);
+
+#endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/ofconsole.c b/arch/powerpc/boot/ofconsole.c
new file mode 100644
index 0000000..ce0e024
--- /dev/null
+++ b/arch/powerpc/boot/ofconsole.c
@@ -0,0 +1,45 @@
+/*
+ * OF console routines
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#include "of.h"
+
+static void *of_stdout_handle;
+
+static int of_console_open(void)
+{
+	void *devp;
+
+	if (((devp = of_finddevice("/chosen")) != NULL)
+	    && (of_getprop(devp, "stdout", &of_stdout_handle,
+			   sizeof(of_stdout_handle))
+		== sizeof(of_stdout_handle)))
+		return 0;
+
+	return -1;
+}
+
+static void of_console_write(const char *buf, int len)
+{
+	of_call_prom("write", 3, 1, of_stdout_handle, buf, len);
+}
+
+void of_console_init(void)
+{
+	console_ops.open = of_console_open;
+	console_ops.write = of_console_write;
+}
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
new file mode 100644
index 0000000..95b8fd6
--- /dev/null
+++ b/arch/powerpc/boot/oflib.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#include "of.h"
+
+static int (*prom) (void *);
+
+void of_init(void *promptr)
+{
+	prom = (int (*)(void *))promptr;
+}
+
+int of_call_prom(const char *service, int nargs, int nret, ...)
+{
+	int i;
+	struct prom_args {
+		const char *service;
+		int nargs;
+		int nret;
+		unsigned int args[12];
+	} args;
+	va_list list;
+
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
+
+	va_start(list, nret);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
+
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
+
+	if (prom(&args) < 0)
+		return -1;
+
+	return (nret > 0)? args.args[nargs]: 0;
+}
+
+static int of_call_prom_ret(const char *service, int nargs, int nret,
+			    unsigned int *rets, ...)
+{
+	int i;
+	struct prom_args {
+		const char *service;
+		int nargs;
+		int nret;
+		unsigned int args[12];
+	} args;
+	va_list list;
+
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
+
+	va_start(list, rets);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
+
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
+
+	if (prom(&args) < 0)
+		return -1;
+
+	if (rets != (void *) 0)
+		for (i = 1; i < nret; ++i)
+			rets[i-1] = args.args[nargs+i];
+
+	return (nret > 0)? args.args[nargs]: 0;
+}
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+	for (; *s2; ++s2)
+		if (*s1++ != *s2)
+			return 0;
+	return 1;
+}
+
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+static int check_of_version(void)
+{
+	phandle oprom, chosen;
+	char version[64];
+
+	oprom = of_finddevice("/openprom");
+	if (oprom == (phandle) -1)
+		return 0;
+	if (of_getprop(oprom, "model", version, sizeof(version)) <= 0)
+		return 0;
+	version[sizeof(version)-1] = 0;
+	printf("OF version = '%s'\r\n", version);
+	if (!string_match(version, "Open Firmware, 1.")
+	    && !string_match(version, "FirmWorks,3."))
+		return 0;
+	chosen = of_finddevice("/chosen");
+	if (chosen == (phandle) -1) {
+		chosen = of_finddevice("/chosen@0");
+		if (chosen == (phandle) -1) {
+			printf("no chosen\n");
+			return 0;
+		}
+	}
+	if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+		printf("no mmu\n");
+		return 0;
+	}
+	memory = (ihandle) of_call_prom("open", 1, 1, "/memory");
+	if (memory == (ihandle) -1) {
+		memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0");
+		if (memory == (ihandle) -1) {
+			printf("no memory node\n");
+			return 0;
+		}
+	}
+	printf("old OF detected\r\n");
+	return 1;
+}
+
+void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+	int ret;
+	unsigned int result;
+
+	if (need_map < 0)
+		need_map = check_of_version();
+	if (align || !need_map)
+		return (void *) of_call_prom("claim", 3, 1, virt, size, align);
+
+	ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+			       align, size, virt);
+	if (ret != 0 || result == -1)
+		return (void *) -1;
+	ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+			       align, size, virt);
+	/* 0x12 == coherent + read/write */
+	ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu,
+			   0x12, size, virt, virt);
+	return (void *) virt;
+}
+
+void *of_vmlinux_alloc(unsigned long size)
+{
+	void *p = malloc(size);
+
+	if (!p)
+		fatal("Can't allocate memory for kernel image!\n\r");
+
+	return p;
+}
+
+void of_exit(void)
+{
+	of_call_prom("exit", 0, 0);
+}
+
+/*
+ * OF device tree routines
+ */
+void *of_finddevice(const char *name)
+{
+	return (phandle) of_call_prom("finddevice", 1, 1, name);
+}
+
+int of_getprop(const void *phandle, const char *name, void *buf,
+	       const int buflen)
+{
+	return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
+int of_setprop(const void *phandle, const char *name, const void *buf,
+	       const int buflen)
+{
+	return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 959124f..8607706 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -19,6 +19,8 @@
 #define	MAX_PATH_LEN		256
 #define	MAX_PROP_LEN		256 /* What should this be? */
 
+typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5);
+
 /* Platform specific operations */
 struct platform_ops {
 	void	(*fixups)(void);
@@ -51,7 +53,7 @@
 /* Console operations */
 struct console_ops {
 	int	(*open)(void);
-	void	(*write)(char *buf, int len);
+	void	(*write)(const char *buf, int len);
 	void	(*edit_cmdline)(char *buf, int len);
 	void	(*close)(void);
 	void	*data;
diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S
new file mode 100644
index 0000000..1a6d64a
--- /dev/null
+++ b/arch/powerpc/boot/ps3-head.S
@@ -0,0 +1,80 @@
+/*
+ *  PS3 bootwrapper entry.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ppc_asm.h"
+
+	.text
+
+/*
+ * __system_reset_overlay - The PS3 first stage entry.
+ *
+ * The bootwraper build script copies the 0x100 bytes at symbol
+ * __system_reset_overlay to offset 0x100 of the rom image.
+ *
+ * The PS3 has a single processor with two threads.
+ */
+
+	.globl __system_reset_overlay
+__system_reset_overlay:
+
+	/* Switch to 32-bit mode. */
+
+	mfmsr	r9
+	clrldi	r9,r9,1
+	mtmsrd	r9
+	nop
+
+	/* Get thread number in r3 and branch. */
+
+	mfspr	r3, 0x88
+	cntlzw.	r3, r3
+	li	r4, 0
+	li	r5, 0
+	beq	1f
+
+	/* Secondary goes to __secondary_hold in kernel. */
+
+	li	r4, 0x60
+	mtctr	r4
+	bctr
+
+	/* Primary delays then goes to _zimage_start in wrapper. */
+1:
+	or	31, 31, 31 /* db16cyc */
+	or	31, 31, 31 /* db16cyc */
+
+	lis	r4, _zimage_start@ha
+	addi	r4, r4, _zimage_start@l
+	mtctr	r4
+	bctr
+
+/*
+ * __system_reset_kernel - Place holder for the kernel reset vector.
+ *
+ * The bootwrapper build script copies 0x100 bytes from offset 0x100
+ * of the rom image to the symbol __system_reset_kernel.  At runtime
+ * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
+ * to ram address 0x100.  This symbol must occupy 0x100 bytes.
+ */
+
+	.globl __system_reset_kernel
+__system_reset_kernel:
+
+	. = __system_reset_kernel + 0x100
diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S
new file mode 100644
index 0000000..c8b7df3
--- /dev/null
+++ b/arch/powerpc/boot/ps3-hvcall.S
@@ -0,0 +1,184 @@
+/*
+ *  PS3 bootwrapper hvcalls.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ppc_asm.h"
+
+/*
+ * The PS3 hypervisor uses a 64 bit "C" language calling convention.
+ * The routines here marshal arguments between the 32 bit wrapper
+ * program and the 64 bit hvcalls.
+ *
+ *  wrapper           lv1
+ *  32-bit (h,l)      64-bit
+ *
+ *  1: r3,r4          <-> r3
+ *  2: r5,r6          <-> r4
+ *  3: r7,r8          <-> r5
+ *  4: r9,r10         <-> r6
+ *  5: 8(r1),12(r1)   <-> r7
+ *  6: 16(r1),20(r1)  <-> r8
+ *  7: 24(r1),28(r1)  <-> r9
+ *  8: 32(r1),36(r1)  <-> r10
+ *
+ */
+
+.macro GLOBAL name
+	.section ".text"
+	.balign 4
+	.globl \name
+\name:
+.endm
+
+.macro NO_SUPPORT name
+	GLOBAL \name
+	b ps3_no_support
+.endm
+
+.macro HVCALL num
+	li r11, \num
+	.long 0x44000022
+	extsw r3, r3
+.endm
+
+.macro SAVE_LR offset=4
+	mflr r0
+	stw r0, \offset(r1)
+.endm
+
+.macro LOAD_LR offset=4
+	lwz r0, \offset(r1)
+	mtlr r0
+.endm
+
+.macro LOAD_64_REG target,high,low
+	sldi r11, \high, 32
+	or \target, r11, \low
+.endm
+
+.macro LOAD_64_STACK target,offset
+	ld \target, \offset(r1)
+.endm
+
+.macro LOAD_R3
+	LOAD_64_REG r3,r3,r4
+.endm
+
+.macro LOAD_R4
+	LOAD_64_REG r4,r5,r6
+.endm
+
+.macro LOAD_R5
+	LOAD_64_REG r5,r7,r8
+.endm
+
+.macro LOAD_R6
+	LOAD_64_REG r6,r9,r10
+.endm
+
+.macro LOAD_R7
+	LOAD_64_STACK r7,8
+.endm
+
+.macro LOAD_R8
+	LOAD_64_STACK r8,16
+.endm
+
+.macro LOAD_R9
+	LOAD_64_STACK r9,24
+.endm
+
+.macro LOAD_R10
+	LOAD_64_STACK r10,32
+.endm
+
+.macro LOAD_REGS_0
+	stwu 1,-16(1)
+	stw 3, 8(1)
+.endm
+
+.macro LOAD_REGS_5
+	LOAD_R3
+	LOAD_R4
+	LOAD_R5
+	LOAD_R6
+	LOAD_R7
+.endm
+
+.macro LOAD_REGS_6
+	LOAD_REGS_5
+	LOAD_R8
+.endm
+
+.macro LOAD_REGS_8
+	LOAD_REGS_6
+	LOAD_R9
+	LOAD_R10
+.endm
+
+.macro STORE_REGS_0_1
+	lwz r11, 8(r1)
+	std r4, 0(r11)
+	mr r4, r3
+	li r3, 0
+	addi r1,r1,16
+.endm
+
+.macro STORE_REGS_5_2
+	lwz r11, 16(r1)
+	std r4, 0(r11)
+	lwz r11, 24(r1)
+	std r5, 0(r11)
+.endm
+
+.macro STORE_REGS_6_1
+	lwz r11, 24(r1)
+	std r4, 0(r11)
+.endm
+
+GLOBAL lv1_get_logical_ppe_id
+	SAVE_LR
+	LOAD_REGS_0
+	HVCALL 69
+	STORE_REGS_0_1
+	LOAD_LR
+	blr
+
+GLOBAL lv1_get_logical_partition_id
+	SAVE_LR
+	LOAD_REGS_0
+	HVCALL 74
+	STORE_REGS_0_1
+	LOAD_LR
+	blr
+
+GLOBAL lv1_get_repository_node_value
+	SAVE_LR
+	LOAD_REGS_5
+	HVCALL 91
+	STORE_REGS_5_2
+	LOAD_LR
+	blr
+
+GLOBAL lv1_panic
+	SAVE_LR
+	LOAD_REGS_8
+	HVCALL 255
+	LOAD_LR
+	blr
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
new file mode 100644
index 0000000..893d593
--- /dev/null
+++ b/arch/powerpc/boot/ps3.c
@@ -0,0 +1,161 @@
+/*
+ *  PS3 bootwrapper support.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+extern s64 lv1_panic(u64 in_1);
+extern s64 lv1_get_logical_partition_id(u64 *out_1);
+extern s64 lv1_get_logical_ppe_id(u64 *out_1);
+extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
+	u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
+
+#ifdef DEBUG
+#define DBG(fmt...) printf(fmt)
+#else
+static inline int __attribute__ ((format (printf, 1, 2))) DBG(
+	const char *fmt, ...) {return 0;}
+#endif
+
+BSS_STACK(4096);
+
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char cmdline[COMMAND_LINE_SIZE]
+	__attribute__((__section__("__builtin_cmdline")));
+
+static void prep_cmdline(void *chosen)
+{
+	if (cmdline[0] == '\0')
+		getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
+	else
+		setprop_str(chosen, "bootargs", cmdline);
+
+	printf("cmdline: '%s'\n", cmdline);
+}
+
+static void ps3_console_write(const char *buf, int len)
+{
+}
+
+static void ps3_exit(void)
+{
+	printf("ps3_exit\n");
+
+	/* lv1_panic will shutdown the lpar. */
+
+	lv1_panic(0); /* zero = do not reboot */
+	while (1);
+}
+
+static int ps3_repository_read_rm_size(u64 *rm_size)
+{
+	s64 result;
+	u64 lpar_id;
+	u64 ppe_id;
+	u64 v2;
+
+	result = lv1_get_logical_partition_id(&lpar_id);
+
+	if (result)
+		return -1;
+
+	result = lv1_get_logical_ppe_id(&ppe_id);
+
+	if (result)
+		return -1;
+
+	/*
+	 * n1: 0000000062690000 : ....bi..
+	 * n2: 7075000000000000 : pu......
+	 * n3: 0000000000000001 : ........
+	 * n4: 726d5f73697a6500 : rm_size.
+	*/
+
+	result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL,
+		0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size,
+		&v2);
+
+	printf("%s:%d: ppe_id  %lu \n", __func__, __LINE__,
+		(unsigned long)ppe_id);
+	printf("%s:%d: lpar_id %lu \n", __func__, __LINE__,
+		(unsigned long)lpar_id);
+	printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size);
+
+	return result ? -1 : 0;
+}
+
+void ps3_copy_vectors(void)
+{
+	extern char __system_reset_kernel[];
+
+	memcpy((void *)0x100, __system_reset_kernel, 0x100);
+	flush_cache((void *)0x100, 0x100);
+}
+
+void platform_init(void)
+{
+	extern char _end[];
+	extern char _dtb_start[];
+	extern char _initrd_start[];
+	extern char _initrd_end[];
+	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
+	void *chosen;
+	unsigned long ft_addr;
+	u64 rm_size;
+
+	console_ops.write = ps3_console_write;
+	platform_ops.exit = ps3_exit;
+
+	printf("\n-- PS3 bootwrapper --\n");
+
+	simple_alloc_init(_end, heapsize, 32, 64);
+	ft_init(_dtb_start, 0, 4);
+
+	chosen = finddevice("/chosen");
+
+	ps3_repository_read_rm_size(&rm_size);
+	dt_fixup_memory(0, rm_size);
+
+	if (_initrd_end > _initrd_start) {
+		setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start));
+		setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end));
+	}
+
+	prep_cmdline(chosen);
+
+	ft_addr = dt_ops.finalize();
+
+	ps3_copy_vectors();
+
+	printf(" flat tree at 0x%lx\n\r", ft_addr);
+
+	((kernel_entry_t)0)(ft_addr, 0, NULL);
+
+	ps3_exit();
+}
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
index 7fd3233..eaa0d3a 100644
--- a/arch/powerpc/boot/serial.c
+++ b/arch/powerpc/boot/serial.c
@@ -27,7 +27,7 @@
 	return scdp->open();
 }
 
-static void serial_write(char *buf, int len)
+static void serial_write(const char *buf, int len)
 {
 	struct serial_console_data *scdp = console_ops.data;
 
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 0a9feeb..5b57800 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -190,7 +190,11 @@
 
 		/* get the conversion qualifier */
 		qualifier = -1;
-		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+		if (*fmt == 'l' && *(fmt + 1) == 'l') {
+			qualifier = 'q';
+			fmt += 2;
+		} else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
+			|| *fmt == 'Z') {
 			qualifier = *fmt;
 			++fmt;
 		}
@@ -281,6 +285,10 @@
 			num = va_arg(args, unsigned long);
 			if (flags & SIGN)
 				num = (signed long) num;
+		} else if (qualifier == 'q') {
+			num = va_arg(args, unsigned long long);
+			if (flags & SIGN)
+				num = (signed long long) num;
 		} else if (qualifier == 'Z') {
 			num = va_arg(args, size_t);
 		} else if (qualifier == 'h') {
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h
index 79d26e7..31393d1 100644
--- a/arch/powerpc/boot/types.h
+++ b/arch/powerpc/boot/types.h
@@ -7,6 +7,10 @@
 typedef unsigned short		u16;
 typedef unsigned int		u32;
 typedef unsigned long long	u64;
+typedef signed char		s8;
+typedef short			s16;
+typedef int			s32;
+typedef long long		s64;
 
 #define min(x,y) ({ \
 	typeof(x) _x = (x);	\
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 2ed8b8b..65f6854 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -129,7 +129,7 @@
 pmac|pseries|chrp)
     platformo=$object/of.o
     ;;
-pmaccoff)
+coff)
     platformo=$object/of.o
     lds=$object/zImage.coff.lds
     ;;
@@ -144,6 +144,15 @@
 cuboot*)
     gzip=
     ;;
+ps3)
+    platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
+    lds=$object/zImage.ps3.lds
+    gzip=
+    ext=bin
+    objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data"
+    ksection=.kernel:vmlinux.bin
+    isection=.kernel:initrd
+    ;;
 esac
 
 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
@@ -220,7 +229,7 @@
 pseries|chrp)
     $object/addnote "$ofile"
     ;;
-pmaccoff)
+coff)
     ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
     $object/hack-coff "$ofile"
     ;;
@@ -239,4 +248,50 @@
     fi
     exit 0
     ;;
+ps3)
+    # The ps3's loader supports loading gzipped binary images from flash
+    # rom to addr zero. The loader enters the image at addr 0x100.  A
+    # bootwrapper overlay is use to arrange for the kernel to be loaded
+    # to addr zero and to have a suitable bootwrapper entry at 0x100.
+    # To construct the rom image, 0x100 bytes from offset 0x100 in the
+    # kernel is copied to the bootwrapper symbol __system_reset_kernel.
+    # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
+    # then copied to offset 0x100.  At runtime the bootwrapper program
+    # copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
+
+    system_reset_overlay=0x`${CROSS}nm "$ofile" \
+        | grep ' __system_reset_overlay$'       \
+        | cut -d' ' -f1`
+    system_reset_overlay=`printf "%d" $system_reset_overlay`
+    system_reset_kernel=0x`${CROSS}nm "$ofile" \
+        | grep ' __system_reset_kernel$'       \
+        | cut -d' ' -f1`
+    system_reset_kernel=`printf "%d" $system_reset_kernel`
+    overlay_dest="256"
+    overlay_size="256"
+
+    rm -f "$object/otheros.bld"
+
+    ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
+
+    msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+        skip=$overlay_dest seek=$system_reset_kernel      \
+        count=$overlay_size bs=1 2>&1)
+
+    if [ $? -ne "0" ]; then
+       echo $msg
+       exit 1
+    fi
+
+    msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+        skip=$system_reset_overlay seek=$overlay_dest     \
+        count=$overlay_size bs=1 2>&1)
+
+    if [ $? -ne "0" ]; then
+       echo $msg
+       exit 2
+    fi
+
+    gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
+    ;;
 esac
diff --git a/arch/powerpc/boot/zImage.ps3.lds.S b/arch/powerpc/boot/zImage.ps3.lds.S
new file mode 100644
index 0000000..aaa469c
--- /dev/null
+++ b/arch/powerpc/boot/zImage.ps3.lds.S
@@ -0,0 +1,50 @@
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_zimage_start)
+EXTERN(_zimage_start)
+SECTIONS
+{
+  _vmlinux_start =  .;
+  .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) }
+  _vmlinux_end =  .;
+
+  . = ALIGN(4096);
+  _dtb_start = .;
+  .kernel:dtb : { *(.kernel:dtb) }
+  _dtb_end = .;
+
+  . = ALIGN(4096);
+  _initrd_start =  .;
+  .kernel:initrd : { *(.kernel:initrd) }
+  _initrd_end =  .;
+
+  _start = .;
+  .text      :
+  {
+    *(.text)
+    *(.fixup)
+  }
+  _etext = .;
+  . = ALIGN(4096);
+  .data    :
+  {
+    *(.rodata*)
+    *(.data*)
+    *(.sdata*)
+    __got2_start = .;
+    *(.got2)
+    __got2_end = .;
+  }
+
+  . = ALIGN(4096);
+  _edata  =  .;
+
+  . = ALIGN(4096);
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss)
+   *(.bss)
+  }
+  . = ALIGN(4096);
+  _end = . ;
+}
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 02c428a..74f83f4 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc6
-# Mon Apr 23 20:46:48 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:32:34 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -41,6 +41,7 @@
 CONFIG_PPC_OF_PLATFORM_PCI=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
@@ -69,6 +70,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
 CONFIG_CPUSETS=y
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
@@ -87,14 +89,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -163,9 +170,14 @@
 CONFIG_SPU_BASE=y
 CONFIG_CBE_RAS=y
 CONFIG_CBE_THERM=m
+CONFIG_CBE_CPUFREQ=m
+# CONFIG_PQ2ADS is not set
 CONFIG_PPC_NATIVE=y
 CONFIG_UDBG_RTAS_CONSOLE=y
 CONFIG_PPC_UDBG_BEAT=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
 # CONFIG_U3_DART is not set
 CONFIG_PPC_RTAS=y
 # CONFIG_RTAS_ERROR_LOGGING is not set
@@ -177,9 +189,23 @@
 # CONFIG_PPC_970_NAP is not set
 CONFIG_PPC_INDIRECT_IO=y
 CONFIG_GENERIC_IOMAP=y
-# CONFIG_CPU_FREQ_PMAC64 is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+
+#
+# CPU Frequency drivers
+#
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -224,12 +250,14 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ARCH_MEMORY_PROBE=y
 CONFIG_NODES_SPAN_OTHER_NODES=y
+CONFIG_PPC_HAS_HASH_64K=y
 CONFIG_PPC_64K_PAGES=y
 CONFIG_SCHED_SMT=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
@@ -237,22 +265,18 @@
 #
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCIEPORTBUS=y
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 CONFIG_KERNEL_START=0xc000000000000000
 
@@ -264,7 +288,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -300,14 +323,11 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
@@ -332,6 +352,7 @@
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
 # CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
@@ -389,20 +410,8 @@
 #
 # CONFIG_IP6_NF_QUEUE is not set
 # CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -429,7 +438,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -449,10 +467,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -489,12 +503,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -509,6 +521,7 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -516,6 +529,7 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
@@ -580,6 +594,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -626,10 +641,6 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
@@ -652,6 +663,7 @@
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -705,6 +717,7 @@
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 # CONFIG_DM_MULTIPATH_EMC is not set
+# CONFIG_DM_DELAY is not set
 
 #
 # Fusion MPT device support
@@ -719,18 +732,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -740,15 +749,7 @@
 CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=y
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -767,10 +768,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
@@ -784,15 +782,13 @@
 CONFIG_SKGE=m
 CONFIG_SKY2=m
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
 CONFIG_SPIDER_NET=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
@@ -800,20 +796,24 @@
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_PASEMI_MAC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -840,6 +840,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -859,6 +860,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -933,10 +935,6 @@
 CONFIG_IPMI_SI=m
 CONFIG_IPMI_WATCHDOG=m
 CONFIG_IPMI_POWEROFF=m
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -959,7 +957,6 @@
 # CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -971,11 +968,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
 
 #
@@ -999,17 +994,17 @@
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -1036,12 +1031,7 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
 # Multifunction device drivers
@@ -1052,17 +1042,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -1084,6 +1076,17 @@
 # CONFIG_HID_DEBUG is not set
 
 #
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1096,6 +1099,7 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 
@@ -1147,44 +1151,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1228,10 +1198,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1253,10 +1219,12 @@
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_MAD=m
 CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
 CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
 # CONFIG_INFINIBAND_AMSO1100 is not set
+# CONFIG_MLX4_INFINIBAND is not set
 CONFIG_INFINIBAND_IPOIB=m
 # CONFIG_INFINIBAND_IPOIB_CM is not set
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
@@ -1287,14 +1255,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1389,6 +1349,7 @@
 CONFIG_NFS_ACL_SUPPORT=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1418,6 +1379,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1468,7 +1430,6 @@
 #
 # CONFIG_DLM is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -1476,6 +1437,7 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=m
@@ -1487,6 +1449,7 @@
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1506,7 +1469,6 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1565,6 +1527,7 @@
 CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig
index 91b657b..0dc9874 100644
--- a/arch/powerpc/configs/celleb_defconfig
+++ b/arch/powerpc/configs/celleb_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Tue May  8 12:32:16 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:33:17 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -40,6 +40,7 @@
 CONFIG_PPC_OF_PLATFORM_PCI=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
@@ -68,6 +69,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
@@ -86,14 +88,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -148,6 +155,7 @@
 # Cell Broadband Engine options
 #
 CONFIG_SPU_FS=y
+CONFIG_SPU_FS_64K_LS=y
 CONFIG_SPU_BASE=y
 # CONFIG_PQ2ADS is not set
 CONFIG_PPC_UDBG_BEAT=y
@@ -206,6 +214,7 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ARCH_MEMORY_PROBE=y
 CONFIG_NODES_SPAN_OTHER_NODES=y
+CONFIG_PPC_HAS_HASH_64K=y
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
@@ -224,16 +233,14 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 CONFIG_KERNEL_START=0xc000000000000000
 
@@ -277,10 +284,6 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
@@ -323,20 +326,8 @@
 #
 # CONFIG_IP6_NF_QUEUE is not set
 # CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -369,7 +360,9 @@
 #
 # CONFIG_CFG80211 is not set
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -425,12 +418,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -445,6 +436,7 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -452,6 +444,7 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
@@ -516,6 +509,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -560,12 +554,7 @@
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -588,6 +577,7 @@
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 # CONFIG_DM_MULTIPATH_EMC is not set
+# CONFIG_DM_DELAY is not set
 
 #
 # Fusion MPT device support
@@ -600,6 +590,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -616,15 +607,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -643,10 +626,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -658,15 +638,13 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_SPIDER_NET=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
@@ -674,10 +652,7 @@
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_PASEMI_MAC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
@@ -687,8 +662,14 @@
 # CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -715,6 +696,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -734,6 +716,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -797,10 +780,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -822,7 +801,6 @@
 # CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -834,11 +812,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
 
 #
@@ -864,14 +840,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -898,12 +875,7 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
 # Multifunction device drivers
@@ -914,17 +886,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -1015,37 +989,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1089,10 +1036,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1136,14 +1079,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1246,6 +1181,7 @@
 CONFIG_NFS_ACL_SUPPORT=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1275,6 +1211,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1325,7 +1262,6 @@
 #
 # CONFIG_DLM is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -1333,6 +1269,7 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
@@ -1340,6 +1277,7 @@
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1358,7 +1296,6 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=15
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1395,6 +1332,7 @@
 # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
 # CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
 CONFIG_PPC_EARLY_DEBUG_BEAT=y
+# CONFIG_PPC_EARLY_DEBUG_44x is not set
 
 #
 # Security options
@@ -1425,6 +1363,7 @@
 CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_BLOWFISH=m
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
index 029c9a0e..7a747c4 100644
--- a/arch/powerpc/configs/chrp32_defconfig
+++ b/arch/powerpc/configs/chrp32_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:12:58 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:36:45 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
@@ -45,6 +45,7 @@
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -64,6 +65,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -71,9 +73,11 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -88,14 +92,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -137,13 +146,18 @@
 # CONFIG_APUS is not set
 CONFIG_PPC_CHRP=y
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 # CONFIG_PPC_EFIKA is not set
 # CONFIG_PPC_LITE5200 is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 CONFIG_PPC_NATIVE=y
 # CONFIG_UDBG_RTAS_CONSOLE is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
 CONFIG_PPC_RTAS=y
 # CONFIG_RTAS_ERROR_LOGGING is not set
 CONFIG_RTAS_PROC=y
@@ -154,8 +168,7 @@
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_TAU is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -186,33 +199,33 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
 CONFIG_ISA=y
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -237,7 +250,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -266,10 +278,6 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
@@ -283,8 +291,6 @@
 #
 # CONFIG_NETFILTER_NETLINK is not set
 CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
 CONFIG_NF_CONNTRACK=m
 # CONFIG_NF_CT_ACCT is not set
 # CONFIG_NF_CONNTRACK_MARK is not set
@@ -296,9 +302,37 @@
 CONFIG_NF_CONNTRACK_IRC=m
 # CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
 # CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
-# CONFIG_NETFILTER_XTABLES is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
 
 #
 # IP: Netfilter Configuration
@@ -306,20 +340,38 @@
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+CONFIG_NF_NAT_SIP=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -345,7 +397,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -358,16 +419,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -379,6 +437,7 @@
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -399,19 +458,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -426,6 +482,7 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -433,12 +490,12 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -453,6 +510,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -463,11 +521,11 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 # CONFIG_IDE_CHIPSETS is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -497,6 +555,7 @@
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -562,10 +621,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -589,18 +644,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -610,15 +661,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -677,10 +720,8 @@
 CONFIG_VIA_RHINE=y
 # CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_VIA_RHINE_NAPI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -696,33 +737,33 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_MV643XX_ETH=y
-# CONFIG_MV643XX_ETH_0 is not set
-# CONFIG_MV643XX_ETH_1 is not set
-# CONFIG_MV643XX_ETH_2 is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -758,6 +799,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -783,15 +825,28 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_INPORT is not set
 # CONFIG_MOUSE_LOGIBM is not set
 # CONFIG_MOUSE_PC110PAD is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
 # CONFIG_INPUT_PCSPKR is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
 CONFIG_INPUT_UINPUT=y
 
 #
@@ -831,6 +886,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -841,10 +897,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_NVRAM=y
@@ -861,11 +913,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
 
 #
@@ -893,10 +943,12 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -928,37 +980,56 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+# CONFIG_VGASTATE is not set
 CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
 CONFIG_FB_MACMODES=y
-# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_BACKLIGHT=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -978,12 +1049,15 @@
 # CONFIG_FB_MATROX_MULTIHEAD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
 # CONFIG_FB_RADEON_DEBUG is not set
 # CONFIG_FB_ATY128 is not set
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY_CT=y
 # CONFIG_FB_ATY_GENERIC_LCD is not set
 CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -991,7 +1065,10 @@
 CONFIG_FB_3DFX=y
 # CONFIG_FB_3DFX_ACCEL is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_FB_VIRTUAL is not set
 
@@ -1007,15 +1084,10 @@
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
 CONFIG_LOGO=y
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1026,6 +1098,15 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
 
 #
 # USB support
@@ -1040,9 +1121,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1052,9 +1132,12 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -1088,40 +1171,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1143,6 +1196,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1153,6 +1207,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1163,10 +1218,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1210,10 +1261,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1323,6 +1370,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1372,6 +1420,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1379,17 +1428,21 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
 #
 # CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
 
 #
 # Kernel hacking
@@ -1401,15 +1454,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1420,6 +1473,10 @@
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
@@ -1454,8 +1511,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1469,6 +1529,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/ebony_defconfig b/arch/powerpc/configs/ebony_defconfig
index c3b96ef..5762cddf 100644
--- a/arch/powerpc/configs/ebony_defconfig
+++ b/arch/powerpc/configs/ebony_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Fri May  4 13:47:08 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:38:33 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 CONFIG_BOOKE=y
 CONFIG_PTE_64BIT=y
 CONFIG_PHYS_64BIT=y
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_NOT_COHERENT_CACHE=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -70,6 +71,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -87,14 +89,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -193,16 +200,14 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -264,20 +269,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -310,7 +303,9 @@
 #
 # CONFIG_CFG80211 is not set
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -365,12 +360,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -379,10 +372,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -398,6 +387,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -414,35 +404,21 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
 
 #
-# PHY device support
-#
-
-#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=128
-CONFIG_IBM_NEW_EMAC_TXB=64
-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
-CONFIG_IBM_NEW_EMAC_ZMII=y
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=128
+CONFIG_IBM_EMAC_TXB=64
+CONFIG_IBM_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_EMAC_DEBUG is not set
+CONFIG_IBM_EMAC_ZMII=y
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -454,24 +430,19 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
@@ -479,10 +450,6 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-
-#
-# Wan interfaces
-#
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -550,15 +517,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -569,10 +531,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -585,12 +544,7 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
 # Multifunction device drivers
@@ -601,16 +555,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -635,10 +592,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -682,14 +635,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -770,6 +715,7 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -795,7 +741,6 @@
 #
 # CONFIG_DLM is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -803,12 +748,14 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -826,7 +773,6 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -851,7 +797,6 @@
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -882,6 +827,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=y
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 3ccf19d..a217f4e 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:15:04 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:38:34 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -27,6 +27,7 @@
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC64_SWSUSP=y
 
 #
 # Processor support
@@ -39,6 +40,7 @@
 # CONFIG_PPC_OF_PLATFORM_PCI is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
@@ -59,6 +61,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -66,9 +69,11 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
@@ -83,14 +88,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -131,15 +141,21 @@
 # CONFIG_PPC_PSERIES is not set
 # CONFIG_PPC_ISERIES is not set
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PMAC64=y
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_PASEMI is not set
+# CONFIG_PPC_CELLEB is not set
+# CONFIG_PPC_PS3 is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_PPC_PS3 is not set
+# CONFIG_PQ2ADS is not set
 CONFIG_PPC_NATIVE=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
 CONFIG_U3_DART=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
@@ -160,9 +176,12 @@
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
 # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPU Frequency drivers
+#
 CONFIG_CPU_FREQ_PMAC64=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -199,34 +218,34 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_PPC_HAS_HASH_64K is not set
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 CONFIG_KERNEL_START=0xc000000000000000
 
@@ -238,14 +257,15 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -270,10 +290,6 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
@@ -287,8 +303,6 @@
 #
 # CONFIG_NETFILTER_NETLINK is not set
 CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
 CONFIG_NF_CONNTRACK=m
 # CONFIG_NF_CT_ACCT is not set
 CONFIG_NF_CONNTRACK_MARK=y
@@ -300,6 +314,7 @@
 CONFIG_NF_CONNTRACK_IRC=m
 # CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
 # CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
 # CONFIG_NF_CONNTRACK_SIP is not set
 CONFIG_NF_CONNTRACK_TFTP=m
 # CONFIG_NETFILTER_XTABLES is not set
@@ -310,20 +325,10 @@
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -350,7 +355,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -363,16 +377,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -383,6 +394,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -402,7 +414,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -411,12 +422,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -431,6 +440,7 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -438,12 +448,12 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -458,6 +468,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -468,13 +479,13 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -504,6 +515,7 @@
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -550,11 +562,8 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
 CONFIG_SATA_SVW=y
 # CONFIG_ATA_PIIX is not set
@@ -570,10 +579,12 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -585,6 +596,7 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -624,6 +636,7 @@
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
 # CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
 
 #
 # Fusion MPT device support
@@ -636,28 +649,26 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 CONFIG_IEEE1394=y
 
 #
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-CONFIG_IEEE1394_OUI_DB=y
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
 
 #
-# Device Drivers
+# Controllers
 #
 # CONFIG_IEEE1394_PCILYNX is not set
 CONFIG_IEEE1394_OHCI1394=y
 
 #
-# Protocol Drivers
+# Protocols
 #
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
 CONFIG_IEEE1394_ETH1394=m
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=y
@@ -666,10 +677,7 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
+CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_ADB_PMU=y
 # CONFIG_ADB_PMU_LED is not set
 CONFIG_PMAC_SMU=y
@@ -689,15 +697,7 @@
 CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -716,10 +716,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 CONFIG_ACENIC=y
 CONFIG_ACENIC_OMIT_TIGON_I=y
 # CONFIG_DL2K is not set
@@ -734,35 +731,50 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_PASEMI_MAC is not set
+# CONFIG_MLX4_CORE is not set
 CONFIG_TR=y
 CONFIG_IBMOL=y
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET_MII is not set
+CONFIG_USB_USBNET=m
+# CONFIG_USB_NET_AX8817X is not set
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_GL620A is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_ZAURUS is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -798,6 +810,7 @@
 #
 CONFIG_INPUT=y
 CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -824,8 +837,10 @@
 CONFIG_INPUT_MOUSE=y
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -866,15 +881,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 CONFIG_AGP=m
@@ -888,11 +898,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -919,14 +927,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -953,37 +962,53 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 # CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+CONFIG_VGASTATE=y
 CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
 CONFIG_FB_MACMODES=y
-# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_BACKLIGHT=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -994,20 +1019,27 @@
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_NVIDIA=y
 CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
 # CONFIG_FB_RADEON_DEBUG is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_FB_VIRTUAL is not set
 
@@ -1021,19 +1053,10 @@
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
 CONFIG_LOGO=y
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -1152,6 +1175,12 @@
 #
 CONFIG_SND_USB_AUDIO=m
 # CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
 
 #
 # Open Sound System
@@ -1162,6 +1191,20 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_THRUSTMASTER_FF=y
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_HIDDEV=y
 
 #
 # USB support
@@ -1176,9 +1219,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1188,9 +1230,15 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -1224,53 +1272,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-CONFIG_HID_FF=y
-CONFIG_HID_PID=y
-CONFIG_LOGITECH_FF=y
-CONFIG_THRUSTMASTER_FF=y
-# CONFIG_ZEROPLUS_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-# CONFIG_USB_USBNET_MII is not set
-CONFIG_USB_USBNET=m
-# CONFIG_USB_NET_AX8817X is not set
-CONFIG_USB_NET_CDCETHER=m
-# CONFIG_USB_NET_GL620A is not set
-# CONFIG_USB_NET_NET1080 is not set
-# CONFIG_USB_NET_PLUSB is not set
-# CONFIG_USB_NET_MCS7830 is not set
-# CONFIG_USB_NET_RNDIS_HOST is not set
-# CONFIG_USB_NET_CDC_SUBSET is not set
-# CONFIG_USB_NET_ZAURUS is not set
 CONFIG_USB_MON=y
 
 #
@@ -1343,6 +1348,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1353,6 +1359,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1363,10 +1370,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1410,10 +1413,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1461,7 +1460,6 @@
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1527,6 +1525,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1561,6 +1560,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1610,6 +1610,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1617,12 +1618,15 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1641,15 +1645,15 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1659,8 +1663,10 @@
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
 CONFIG_BOOTX_TEXT=y
@@ -1693,8 +1699,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1709,6 +1718,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
 CONFIG_CRYPTO_TEST=m
 
 #
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig
index be633b9..04b94f8 100644
--- a/arch/powerpc/configs/holly_defconfig
+++ b/arch/powerpc/configs/holly_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Sat May  5 11:02:35 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:22:36 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -70,6 +71,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -87,14 +89,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -140,6 +147,7 @@
 # CONFIG_LINKSTATION is not set
 # CONFIG_MPC7448HPC2 is not set
 CONFIG_PPC_HOLLY=y
+# CONFIG_PPC_PRPMC2800 is not set
 CONFIG_TSI108_BRIDGE=y
 CONFIG_MPIC=y
 CONFIG_MPIC_WEIRD=y
@@ -182,10 +190,12 @@
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
-# CONFIG_WANT_DEVICE_TREE is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE="holly.dts"
 CONFIG_ISA_DMA_API=y
 
 #
@@ -197,16 +207,14 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -271,20 +279,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -317,7 +313,9 @@
 #
 # CONFIG_CFG80211 is not set
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -372,12 +370,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -406,6 +402,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -453,12 +450,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
@@ -531,6 +523,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -547,15 +540,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -589,10 +574,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -604,25 +586,20 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_TSI108_ETH=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
@@ -630,10 +607,6 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-
-#
-# Wan interfaces
-#
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -660,6 +633,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -676,6 +650,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -721,16 +696,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -741,10 +711,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -757,16 +724,15 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -778,16 +744,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -818,10 +787,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -865,14 +830,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -957,6 +914,7 @@
 CONFIG_LOCKD=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -986,6 +944,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -997,7 +956,6 @@
 #
 # CONFIG_DLM is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -1005,11 +963,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1028,7 +988,6 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index af25118..8e33674 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22-rc1
-# Mon May 14 14:27:46 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:22:39 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -281,10 +281,6 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
@@ -387,25 +383,13 @@
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 CONFIG_IP_SCTP=m
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
 # CONFIG_SCTP_HMAC_NONE is not set
 # CONFIG_SCTP_HMAC_SHA1 is not set
 CONFIG_SCTP_HMAC_MD5=y
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -501,10 +485,6 @@
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
 # CONFIG_IDE is not set
 
 #
@@ -581,7 +561,6 @@
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
 # CONFIG_ATA is not set
 
@@ -634,10 +613,6 @@
 CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
 # CONFIG_PHYLIB is not set
 
@@ -705,11 +680,6 @@
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_PASEMI_MAC is not set
 # CONFIG_MLX4_CORE is not set
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
 CONFIG_TR=y
 CONFIG_IBMOL=y
 # CONFIG_3C359 is not set
@@ -757,6 +727,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -1139,7 +1110,6 @@
 CONFIG_DLM=m
 # CONFIG_DLM_DEBUG is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index dde66a5..78fd07c 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc6
-# Sun Jan 28 23:13:56 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:25:19 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -24,7 +24,7 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
-# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
@@ -34,9 +34,9 @@
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
@@ -45,6 +45,7 @@
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -63,6 +64,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -70,8 +72,10 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -86,14 +90,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -133,8 +142,20 @@
 CONFIG_EMBEDDED6xx=y
 # CONFIG_APUS is not set
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_LINKSTATION=y
+# CONFIG_MPC7448HPC2 is not set
+# CONFIG_PPC_HOLLY is not set
+# CONFIG_PPC_PRPMC2800 is not set
+CONFIG_MPC10X_BRIDGE=y
+CONFIG_MPC10X_OPENPIC=y
+# CONFIG_MPC10X_STORE_GATHERING is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 # CONFIG_PPC_MPC106 is not set
@@ -143,39 +164,7 @@
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_TAU is not set
-# CONFIG_KATANA is not set
-# CONFIG_WILLOW is not set
-# CONFIG_CPCI690 is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_CHESTNUT is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_HDPU is not set
-# CONFIG_EV64260 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-CONFIG_LINKSTATION=y
-# CONFIG_MPC7448HPC2 is not set
-# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBC82xx is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX8260 is not set
-# CONFIG_TQM8260 is not set
-# CONFIG_ADS8272 is not set
-# CONFIG_PQ2FADS is not set
-# CONFIG_EV64360 is not set
-CONFIG_PPC_GEN550=y
-CONFIG_MPC10X_BRIDGE=y
-CONFIG_MPC10X_OPENPIC=y
-# CONFIG_MPC10X_STORE_GATHERING is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -203,33 +192,33 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -254,13 +243,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -289,10 +278,6 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
@@ -306,8 +291,6 @@
 #
 # CONFIG_NETFILTER_NETLINK is not set
 CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
 CONFIG_NF_CONNTRACK=m
 # CONFIG_NF_CT_ACCT is not set
 # CONFIG_NF_CONNTRACK_MARK is not set
@@ -320,16 +303,21 @@
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
 CONFIG_NF_CONNTRACK_PPTP=m
+# CONFIG_NF_CONNTRACK_SANE is not set
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XTABLES=m
 # CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
 # CONFIG_NETFILTER_XT_TARGET_DSCP is not set
 # CONFIG_NETFILTER_XT_TARGET_MARK is not set
 # CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
 # CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
 # CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
 # CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
 # CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
 # CONFIG_NETFILTER_XT_MATCH_DCCP is not set
 # CONFIG_NETFILTER_XT_MATCH_DSCP is not set
@@ -370,7 +358,6 @@
 CONFIG_IP_NF_TARGET_REJECT=m
 # CONFIG_IP_NF_TARGET_LOG is not set
 # CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
 CONFIG_NF_NAT=m
 CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -390,24 +377,13 @@
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
 CONFIG_IP_NF_RAW=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -433,6 +409,14 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
 CONFIG_IEEE80211=m
 CONFIG_IEEE80211_DEBUG=y
 CONFIG_IEEE80211_CRYPT_WEP=m
@@ -440,7 +424,7 @@
 CONFIG_IEEE80211_CRYPT_TKIP=m
 CONFIG_IEEE80211_SOFTMAC=m
 CONFIG_IEEE80211_SOFTMAC_DEBUG=y
-CONFIG_WIRELESS_EXT=y
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -453,16 +437,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
@@ -511,7 +492,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -539,17 +519,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -559,6 +535,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -578,19 +555,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=2
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -619,6 +593,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -667,11 +642,8 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
 # CONFIG_ATA_PIIX is not set
@@ -687,10 +659,12 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -702,6 +676,7 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 CONFIG_PATA_IT821X=y
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -738,18 +713,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -759,15 +730,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -795,10 +758,7 @@
 # CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -811,58 +771,36 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Obsolete Wireless cards support (pre-802.11)
+# USB Network Adapters
 #
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
-# CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_BCM43XX is not set
-CONFIG_ZD1211RW=m
-# CONFIG_ZD1211RW_DEBUG is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
-#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -872,7 +810,6 @@
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
 # CONFIG_NETPOLL_TRAP is not set
 CONFIG_NET_POLL_CONTROLLER=y
 
@@ -891,6 +828,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -910,8 +848,14 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
 CONFIG_INPUT_UINPUT=m
 
 #
@@ -950,6 +894,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -958,15 +903,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -977,11 +917,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -1008,14 +946,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -1043,16 +982,14 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -1075,6 +1012,7 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
@@ -1094,20 +1032,27 @@
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -1116,7 +1061,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1127,6 +1071,18 @@
 # HID Devices
 #
 CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
 
 #
 # USB support
@@ -1141,7 +1097,7 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 
@@ -1152,9 +1108,15 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -1187,43 +1149,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1283,6 +1212,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1293,6 +1223,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1303,10 +1234,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1347,24 +1274,37 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
 #
-# CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_DS1307 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+CONFIG_RTC_DRV_RS5C372=y
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
-CONFIG_RTC_DRV_RS5C372=y
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+
+#
 # DMA Engine support
 #
 # CONFIG_DMA_ENGINE is not set
@@ -1378,10 +1318,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1421,7 +1357,6 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1489,6 +1424,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1557,6 +1493,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1564,6 +1501,7 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
@@ -1571,13 +1509,16 @@
 CONFIG_TEXTSEARCH=y
 CONFIG_TEXTSEARCH_KMP=m
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
 #
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
+# CONFIG_KPROBES is not set
 
 #
 # Kernel hacking
@@ -1589,15 +1530,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1607,10 +1548,13 @@
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1639,8 +1583,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1655,6 +1602,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/lite5200_defconfig b/arch/powerpc/configs/lite5200_defconfig
index 8cbd87d..d12a981 100644
--- a/arch/powerpc/configs/lite5200_defconfig
+++ b/arch/powerpc/configs/lite5200_defconfig
@@ -1,9 +1,10 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:18:18 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:26:09 2007
 #
 # CONFIG_PPC64 is not set
+CONFIG_PPC_PM_NEEDS_RTC_LIB=y
 CONFIG_PPC32=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
@@ -34,9 +35,9 @@
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
@@ -45,6 +46,7 @@
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -63,14 +65,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -83,14 +88,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -131,11 +141,17 @@
 # CONFIG_APUS is not set
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_MPC52xx=y
+CONFIG_PPC_MPC5200=y
+CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_EFIKA is not set
 CONFIG_PPC_LITE5200=y
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 # CONFIG_PPC_MPC106 is not set
@@ -144,8 +160,7 @@
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_TAU is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-# CONFIG_MPIC is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -174,6 +189,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 CONFIG_PM=y
@@ -182,28 +198,27 @@
 # CONFIG_PM_SYSFS_DEPRECATED is not set
 # CONFIG_SOFTWARE_SUSPEND is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -228,13 +243,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -268,20 +283,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -307,7 +310,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -320,16 +332,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -340,6 +349,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -358,19 +368,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -399,6 +406,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -447,11 +455,8 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
 # CONFIG_ATA_PIIX is not set
@@ -467,10 +472,12 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -482,9 +489,11 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
+CONFIG_PATA_MPC52xx=y
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
 # CONFIG_PATA_NETCELL is not set
@@ -519,18 +528,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -540,24 +545,13 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
 
 #
-# PHY device support
-#
-
-#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -569,33 +563,27 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -657,15 +645,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -676,10 +659,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -692,30 +672,32 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -738,10 +720,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -769,6 +747,7 @@
 #
 # Real Time Clock
 #
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 
 #
@@ -785,10 +764,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -888,16 +863,20 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 # CONFIG_CRC32 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -914,15 +893,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -932,10 +911,13 @@
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 15366f0..eb3d9ad 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:19:02 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:27:35 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -39,6 +39,7 @@
 # CONFIG_PPC_OF_PLATFORM_PCI is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
@@ -59,6 +60,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -66,10 +68,11 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
@@ -83,14 +86,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -131,29 +139,34 @@
 # CONFIG_PPC_PSERIES is not set
 # CONFIG_PPC_ISERIES is not set
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_MAPLE=y
 # CONFIG_PPC_PASEMI is not set
+# CONFIG_PPC_CELLEB is not set
+# CONFIG_PPC_PS3 is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_PPC_PS3 is not set
+# CONFIG_PQ2ADS is not set
 CONFIG_PPC_NATIVE=y
 CONFIG_UDBG_RTAS_CONSOLE=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
 CONFIG_U3_DART=y
 CONFIG_PPC_RTAS=y
 # CONFIG_RTAS_ERROR_LOGGING is not set
 CONFIG_RTAS_PROC=y
 # CONFIG_RTAS_FLASH is not set
-# CONFIG_MMIO_NVRAM is not set
+CONFIG_MMIO_NVRAM=y
 CONFIG_MPIC_U3_HT_IRQS=y
 # CONFIG_PPC_MPC106 is not set
 CONFIG_PPC_970_NAP=y
 # CONFIG_PPC_INDIRECT_IO is not set
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -189,34 +202,34 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_PPC_HAS_HASH_64K is not set
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 CONFIG_KERNEL_START=0xc000000000000000
 
@@ -228,13 +241,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -268,20 +281,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -307,7 +308,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -320,16 +330,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -340,6 +347,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -358,19 +366,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -384,6 +389,7 @@
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -391,12 +397,12 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -411,6 +417,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -421,10 +428,10 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -433,10 +440,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -452,18 +455,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -473,15 +472,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -518,10 +509,8 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -539,29 +528,33 @@
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_PASEMI_MAC is not set
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=y
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -587,6 +580,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -606,6 +600,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -640,6 +635,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -650,15 +646,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -670,11 +661,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -700,14 +689,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -734,28 +724,30 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -764,7 +756,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -775,6 +766,15 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
 
 #
 # USB support
@@ -789,9 +789,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -801,9 +800,12 @@
 CONFIG_USB_EHCI_SPLIT_ISO=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -824,39 +826,9 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-CONFIG_USB_PEGASUS=y
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -929,6 +901,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -939,6 +912,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -949,10 +923,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -996,10 +966,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1090,6 +1056,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1119,6 +1086,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1168,6 +1136,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1175,11 +1144,14 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1197,16 +1169,16 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 CONFIG_DEBUG_SLAB=y
 # CONFIG_DEBUG_SLAB_LEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1216,8 +1188,10 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
@@ -1252,8 +1226,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1267,6 +1244,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
index fdf09ea..174a290 100644
--- a/arch/powerpc/configs/mpc7448_hpc2_defconfig
+++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:20:53 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:54 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
@@ -45,6 +45,7 @@
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -63,14 +64,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -84,14 +88,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -126,8 +135,18 @@
 CONFIG_EMBEDDED6xx=y
 # CONFIG_APUS is not set
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_LINKSTATION is not set
+CONFIG_MPC7448HPC2=y
+# CONFIG_PPC_HOLLY is not set
+# CONFIG_PPC_PRPMC2800 is not set
+CONFIG_TSI108_BRIDGE=y
+CONFIG_MPIC=y
+CONFIG_MPIC_WEIRD=y
+# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 # CONFIG_PPC_MPC106 is not set
@@ -136,36 +155,7 @@
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_TAU is not set
-# CONFIG_KATANA is not set
-# CONFIG_WILLOW is not set
-# CONFIG_CPCI690 is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_CHESTNUT is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_HDPU is not set
-# CONFIG_EV64260 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_LINKSTATION is not set
-CONFIG_MPC7448HPC2=y
-# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBC82xx is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX8260 is not set
-# CONFIG_TQM8260 is not set
-# CONFIG_ADS8272 is not set
-# CONFIG_PQ2FADS is not set
-# CONFIG_EV64360 is not set
-CONFIG_TSI108_BRIDGE=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -193,31 +183,30 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-CONFIG_MPIC_WEIRD=y
-# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -242,13 +231,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -282,20 +271,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -321,7 +298,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -339,10 +325,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -353,6 +335,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -371,19 +354,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=131072
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -460,11 +440,8 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
 # CONFIG_ATA_PIIX is not set
@@ -480,10 +457,12 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -495,6 +474,7 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -532,18 +512,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -553,15 +529,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -615,10 +583,8 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -635,29 +601,22 @@
 # CONFIG_BNX2 is not set
 CONFIG_TSI108_ETH=y
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -684,6 +643,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -700,6 +660,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -732,6 +693,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -740,16 +702,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -760,10 +717,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -776,35 +730,41 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -815,6 +775,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -832,10 +793,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -879,10 +836,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -967,6 +920,7 @@
 CONFIG_LOCKD=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -996,6 +950,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1006,6 +961,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1013,10 +969,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1033,7 +992,6 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff --git a/arch/powerpc/configs/mpc8272_ads_defconfig b/arch/powerpc/configs/mpc8272_ads_defconfig
index 2af4502..4a42929 100644
--- a/arch/powerpc/configs/mpc8272_ads_defconfig
+++ b/arch/powerpc/configs/mpc8272_ads_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc5
-# Fri Jul 14 20:36:35 2006
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:55 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,25 +22,31 @@
 CONFIG_PPC_OF=y
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
-# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 CONFIG_PPC_82xx=y
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -55,14 +62,21 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
@@ -72,12 +86,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -87,6 +108,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -103,17 +125,29 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PQ2ADS=y
-CONFIG_8260=y
-CONFIG_8272=y
-CONFIG_CPM2=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_EMBEDDEDBOOT=y
 
 #
 # Platform support
 #
-CONFIG_ADS8272=y
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_MPC82xx_ADS=y
+CONFIG_PQ2ADS=y
+CONFIG_8260=y
+CONFIG_8272=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_CPM2=y
 
 #
 # Kernel options
@@ -121,6 +155,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -128,26 +163,30 @@
 # CONFIG_PREEMPT is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
-# CONFIG_PC_KEYBOARD is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
-# CONFIG_SOFTWARE_SUSPEND is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
 CONFIG_FSL_SOC=y
 # CONFIG_PCI is not set
 # CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -155,10 +194,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Advanced setup
 #
 # CONFIG_ADVANCED_OPTIONS is not set
@@ -180,10 +215,11 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -201,15 +237,15 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
@@ -219,7 +255,12 @@
 # CONFIG_INET6_IPCOMP is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+CONFIG_IPV6_SIT=y
 # CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -227,13 +268,16 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
 # CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
 # CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
@@ -253,7 +297,14 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -266,15 +317,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -285,6 +334,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -295,14 +345,15 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
-# ATA/ATAPI/MFM/RLL support
+# Misc devices
 #
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -314,14 +365,15 @@
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
 #
 # CONFIG_IDE_GENERIC is not set
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
 # CONFIG_IDE_ARM is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -329,29 +381,14 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -361,10 +398,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=y
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -375,6 +408,9 @@
 # CONFIG_QSEMI_PHY is not set
 # CONFIG_LXT_PHY is not set
 # CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -385,27 +421,14 @@
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FCC=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 CONFIG_PPP=y
 # CONFIG_PPP_FILTER is not set
@@ -414,6 +437,7 @@
 CONFIG_PPP_DEFLATE=y
 # CONFIG_PPP_BSDCOMP is not set
 # CONFIG_SLIP is not set
+CONFIG_SLHC=y
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
 
@@ -431,6 +455,8 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -453,11 +479,19 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -485,6 +519,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_CPM=y
@@ -503,29 +538,16 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_AGP is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -538,32 +560,32 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
+# Multifunction device drivers
 #
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 
 #
 # Sound
@@ -571,6 +593,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -586,6 +614,7 @@
 #
 CONFIG_USB_GADGET=y
 # CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_PXA2XX is not set
 # CONFIG_USB_GADGET_GOKU is not set
@@ -594,10 +623,6 @@
 # CONFIG_USB_GADGET_AT91 is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 # CONFIG_USB_GADGET_DUALSPEED is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -626,6 +651,19 @@
 #
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -645,9 +683,12 @@
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -672,8 +713,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -694,6 +737,7 @@
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
@@ -727,6 +771,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -771,37 +816,55 @@
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=y
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_KGDB_CONSOLE is not set
 CONFIG_BDI_SWITCH=y
@@ -818,6 +881,9 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
@@ -827,7 +893,12 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -841,7 +912,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 
 #
 # Hardware crypto devices
diff --git a/arch/powerpc/configs/mpc8313_rdb_defconfig b/arch/powerpc/configs/mpc8313_rdb_defconfig
index f875237..b7d3dff 100644
--- a/arch/powerpc/configs/mpc8313_rdb_defconfig
+++ b/arch/powerpc/configs/mpc8313_rdb_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Wed Feb  7 22:08:04 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:55 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -63,14 +64,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -83,14 +87,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -122,19 +131,33 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 CONFIG_MPC8313_RDB=y
 # CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
 # CONFIG_MPC834x_ITX is not set
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
 CONFIG_PPC_MPC831x=y
 # CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -162,33 +185,34 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -213,13 +237,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -253,20 +277,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -292,7 +304,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -305,16 +326,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
@@ -357,7 +375,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -387,17 +404,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -407,6 +420,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -426,19 +440,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -467,6 +478,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -514,10 +526,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -545,18 +553,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -566,15 +570,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -624,10 +620,8 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -645,29 +639,32 @@
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -694,6 +691,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -710,6 +708,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -742,6 +741,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -750,10 +750,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -776,7 +772,6 @@
 CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -787,11 +782,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -818,14 +811,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -859,21 +853,21 @@
 #
 # SPI Protocol Masters
 #
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
 
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -897,6 +891,7 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
@@ -916,23 +911,30 @@
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 # CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -943,6 +945,18 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
 
 #
 # USB support
@@ -957,7 +971,7 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 
@@ -968,9 +982,15 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -1002,43 +1022,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1060,6 +1047,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1070,6 +1058,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1082,6 +1071,7 @@
 CONFIG_USB_GADGET=y
 # CONFIG_USB_GADGET_DEBUG_FILES is not set
 CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_FSL_USB2 is not set
 CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_NET2280=y
 # CONFIG_USB_GADGET_PXA2XX is not set
@@ -1098,10 +1088,6 @@
 # CONFIG_USB_FILE_STORAGE is not set
 # CONFIG_USB_G_SERIAL is not set
 # CONFIG_USB_MIDI_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1142,26 +1128,39 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
 #
-# CONFIG_RTC_DRV_X1205 is not set
 CONFIG_RTC_DRV_DS1307=y
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
+
+#
+# SPI RTC drivers
+#
 # CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+
+#
 # DMA Engine support
 #
 CONFIG_DMA_ENGINE=y
@@ -1177,10 +1176,6 @@
 CONFIG_INTEL_IOATDMA=y
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1269,6 +1264,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1298,6 +1294,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1308,6 +1305,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1315,10 +1313,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1335,15 +1336,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1353,12 +1354,13 @@
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1387,8 +1389,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_ECB is not set
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1402,6 +1407,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/mpc832x_mds_defconfig b/arch/powerpc/configs/mpc832x_mds_defconfig
index 83192c0..75ce781 100644
--- a/arch/powerpc/configs/mpc832x_mds_defconfig
+++ b/arch/powerpc/configs/mpc832x_mds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc5
-# Mon Apr  9 16:09:16 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:55 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -70,6 +71,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -85,14 +87,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -124,12 +131,15 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_QUICC_ENGINE=y
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 # CONFIG_MPC8313_RDB is not set
 CONFIG_MPC832x_MDS=y
 # CONFIG_MPC832x_RDB is not set
@@ -138,6 +148,17 @@
 # CONFIG_MPC836x_MDS is not set
 CONFIG_PPC_MPC832x=y
 # CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -171,6 +192,8 @@
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
@@ -178,22 +201,19 @@
 #
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -218,7 +238,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -259,20 +278,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -298,7 +305,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -316,10 +332,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -355,12 +367,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -389,6 +399,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -436,10 +447,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -458,18 +465,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -479,15 +482,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -501,7 +496,6 @@
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
 # CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -520,10 +514,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -535,6 +526,7 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_GIANFAR is not set
@@ -542,33 +534,24 @@
 # CONFIG_UGETH_NAPI is not set
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_FILTERING is not set
-# CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -595,6 +578,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -611,6 +595,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -652,10 +637,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -674,7 +655,6 @@
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -685,11 +665,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -714,9 +692,9 @@
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -724,7 +702,6 @@
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -752,13 +729,10 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -785,6 +759,7 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
@@ -812,16 +787,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -852,10 +830,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -899,14 +873,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -994,6 +960,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1019,6 +986,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1039,11 +1007,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1060,7 +1030,6 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -1093,6 +1062,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc832x_rdb_defconfig b/arch/powerpc/configs/mpc832x_rdb_defconfig
index 4a4da87..6a83b66 100644
--- a/arch/powerpc/configs/mpc832x_rdb_defconfig
+++ b/arch/powerpc/configs/mpc832x_rdb_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc5
-# Mon Apr  9 16:12:43 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:56 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -70,6 +71,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -85,14 +87,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -124,12 +131,15 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_QUICC_ENGINE=y
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 # CONFIG_MPC8313_RDB is not set
 # CONFIG_MPC832x_MDS is not set
 CONFIG_MPC832x_RDB=y
@@ -138,6 +148,17 @@
 # CONFIG_MPC836x_MDS is not set
 CONFIG_PPC_MPC832x=y
 # CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -171,6 +192,8 @@
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
@@ -178,22 +201,19 @@
 #
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -218,7 +238,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -259,20 +278,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -298,7 +305,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -316,10 +332,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -356,12 +368,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -390,6 +400,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -437,10 +448,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -459,18 +466,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -480,15 +483,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -502,7 +497,6 @@
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
 # CONFIG_BROADCOM_PHY is not set
-CONFIG_ICPLUS_PHY=y
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -521,10 +515,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -538,6 +529,7 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_GIANFAR is not set
@@ -545,33 +537,34 @@
 CONFIG_UGETH_NAPI=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_FILTERING is not set
-# CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -598,6 +591,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -614,6 +608,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -655,10 +650,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -682,7 +673,6 @@
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -693,11 +683,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -722,17 +710,17 @@
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -760,13 +748,10 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -793,6 +778,7 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
@@ -820,17 +806,20 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 # CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -846,6 +835,17 @@
 # CONFIG_HID_DEBUG is not set
 
 #
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -858,6 +858,7 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 
@@ -908,44 +909,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -989,10 +956,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1036,14 +999,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1134,6 +1089,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1164,6 +1120,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1223,11 +1180,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1244,7 +1203,6 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -1277,6 +1235,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
index 23d8964..85470b8 100644
--- a/arch/powerpc/configs/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/mpc834x_itx_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Wed Feb  7 13:12:18 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:56 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -63,14 +64,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -83,14 +87,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -122,18 +131,33 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPC8313_RDB is not set
 # CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
 CONFIG_MPC834x_ITX=y
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
 CONFIG_MPC834x=y
 # CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -161,32 +185,33 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -211,13 +236,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -251,20 +276,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -290,7 +303,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -308,10 +330,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
@@ -354,7 +372,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -384,17 +401,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -404,6 +417,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -423,19 +437,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_IDE_MAX_HWIFS=4
 # CONFIG_BLK_DEV_IDE is not set
@@ -468,6 +479,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -516,10 +528,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
@@ -537,10 +545,12 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -552,6 +562,7 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -598,18 +609,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -619,15 +626,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -647,10 +646,7 @@
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -662,34 +658,38 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -745,6 +745,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -753,10 +754,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -779,7 +776,6 @@
 CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -790,11 +786,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -821,14 +815,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -861,36 +856,40 @@
 #
 # SPI Protocol Masters
 #
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
 
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 # CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -910,7 +909,7 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 
@@ -921,6 +920,7 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_OHCI_HCD is not set
 # CONFIG_USB_UHCI_HCD is not set
@@ -953,28 +953,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-
-#
-# USB HID Boot Protocol drivers
-#
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -996,6 +978,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1006,6 +989,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1016,10 +1000,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1060,26 +1040,39 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
 #
-# CONFIG_RTC_DRV_X1205 is not set
 CONFIG_RTC_DRV_DS1307=y
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
+
+#
+# SPI RTC drivers
+#
 # CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+
+#
 # DMA Engine support
 #
 CONFIG_DMA_ENGINE=y
@@ -1095,10 +1088,6 @@
 CONFIG_INTEL_IOATDMA=y
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1190,6 +1179,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1219,6 +1209,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1268,6 +1259,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1275,10 +1267,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1295,10 +1290,8 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1327,8 +1320,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_ECB is not set
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1342,6 +1338,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/mpc834x_itxgp_defconfig b/arch/powerpc/configs/mpc834x_itxgp_defconfig
index 4aa666c..704ee8b 100644
--- a/arch/powerpc/configs/mpc834x_itxgp_defconfig
+++ b/arch/powerpc/configs/mpc834x_itxgp_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Fri Feb  9 13:28:19 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:56 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -63,14 +64,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -83,14 +87,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -122,18 +131,33 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPC8313_RDB is not set
 # CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
 CONFIG_MPC834x_ITX=y
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
 CONFIG_MPC834x=y
 # CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -161,32 +185,33 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -211,13 +236,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -251,20 +276,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -290,7 +303,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -308,10 +330,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
@@ -354,7 +372,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -384,17 +401,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -404,6 +417,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -422,19 +436,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -463,6 +474,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -510,10 +522,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -532,18 +540,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -553,15 +557,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -581,10 +577,7 @@
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -596,34 +589,28 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -679,6 +666,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -687,10 +675,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -708,7 +692,6 @@
 CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -719,11 +702,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -750,6 +731,7 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -757,7 +739,6 @@
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -790,35 +771,39 @@
 #
 # SPI Protocol Masters
 #
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
 
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -841,10 +826,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -885,26 +866,39 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
 #
-# CONFIG_RTC_DRV_X1205 is not set
 CONFIG_RTC_DRV_DS1307=y
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
+
+#
+# SPI RTC drivers
+#
 # CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+
+#
 # DMA Engine support
 #
 CONFIG_DMA_ENGINE=y
@@ -920,10 +914,6 @@
 CONFIG_INTEL_IOATDMA=y
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1015,6 +1005,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1044,6 +1035,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1093,6 +1085,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1100,10 +1093,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1120,10 +1116,8 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1152,8 +1146,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_ECB is not set
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1167,6 +1164,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
index 2e3f8ef..c28b3ee 100644
--- a/arch/powerpc/configs/mpc834x_mds_defconfig
+++ b/arch/powerpc/configs/mpc834x_mds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Thu Feb  8 01:00:48 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:57 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -63,14 +64,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -83,14 +87,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -122,19 +131,33 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 # CONFIG_MPC8313_RDB is not set
 # CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
 CONFIG_MPC834x_MDS=y
 # CONFIG_MPC834x_ITX is not set
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
 CONFIG_MPC834x=y
 # CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -162,32 +185,33 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -212,13 +236,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -252,20 +276,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -291,7 +303,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -309,10 +330,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -323,6 +340,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -341,19 +359,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -362,10 +377,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -381,18 +392,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -402,15 +409,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -460,10 +459,8 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -481,29 +478,22 @@
 CONFIG_GIANFAR=y
 # CONFIG_GFAR_NAPI is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -529,6 +519,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -545,6 +536,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -577,6 +569,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -585,10 +578,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -607,7 +596,6 @@
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -618,11 +606,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -649,6 +635,7 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -656,7 +643,6 @@
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -684,16 +670,14 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -716,6 +700,7 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
@@ -735,22 +720,29 @@
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -761,6 +753,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -778,10 +771,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -825,10 +814,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -916,6 +901,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -941,6 +927,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -951,6 +938,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -958,10 +946,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -978,10 +969,8 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1010,8 +999,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1025,6 +1017,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/mpc836x_mds_defconfig b/arch/powerpc/configs/mpc836x_mds_defconfig
index 921a151..bcbbc16 100644
--- a/arch/powerpc/configs/mpc836x_mds_defconfig
+++ b/arch/powerpc/configs/mpc836x_mds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc5
-# Mon Apr  9 16:14:05 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:57 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -45,6 +45,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -70,6 +71,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -85,14 +87,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -124,12 +131,15 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_QUICC_ENGINE=y
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 # CONFIG_MPC8313_RDB is not set
 # CONFIG_MPC832x_MDS is not set
 # CONFIG_MPC832x_RDB is not set
@@ -138,6 +148,17 @@
 CONFIG_MPC836x_MDS=y
 CONFIG_PPC_MPC836x=y
 # CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -170,6 +191,8 @@
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
@@ -177,22 +200,19 @@
 #
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -217,7 +237,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -258,20 +277,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -297,7 +304,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -315,10 +331,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -354,12 +366,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -388,6 +398,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -435,10 +446,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -457,18 +464,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -478,15 +481,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -500,7 +495,6 @@
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
 # CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -519,10 +513,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -534,6 +525,7 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_GIANFAR is not set
@@ -541,33 +533,24 @@
 # CONFIG_UGETH_NAPI is not set
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_FILTERING is not set
-# CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -594,6 +577,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -610,6 +594,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -651,10 +636,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -673,7 +654,6 @@
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -684,11 +664,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -713,9 +691,9 @@
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -723,7 +701,6 @@
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -751,13 +728,10 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -784,6 +758,7 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
@@ -811,16 +786,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -851,10 +829,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -898,14 +872,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -993,6 +959,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1018,6 +985,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1038,11 +1006,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1059,7 +1029,6 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -1092,6 +1061,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
index 17120c4..faedcf8 100644
--- a/arch/powerpc/configs/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/mpc8540_ads_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:25:24 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:58 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@
 # CONFIG_PPC_83xx is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_85xx=y
 CONFIG_E500=y
@@ -46,6 +46,7 @@
 CONFIG_FSL_BOOKE=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -63,14 +64,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -85,14 +89,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -119,17 +128,33 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 CONFIG_MPC8540_ADS=y
 # CONFIG_MPC8560_ADS is not set
 # CONFIG_MPC85xx_CDS is not set
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC8544_DS is not set
 CONFIG_MPC8540=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPC85xx=y
 CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -158,21 +183,25 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
 CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_FSL_SOC=y
 # CONFIG_PCI is not set
 # CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -180,10 +209,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Advanced setup
 #
 # CONFIG_ADVANCED_OPTIONS is not set
@@ -205,13 +230,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -245,20 +270,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -284,7 +297,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -297,16 +319,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -317,6 +336,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -330,18 +350,13 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -350,35 +365,13 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -388,10 +381,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -412,29 +401,16 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (10000 Mbit)
+# Wireless LAN
 #
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -458,6 +434,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -474,6 +451,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -497,6 +475,7 @@
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
 
 #
 # Non-8250 serial port support
@@ -504,6 +483,7 @@
 # CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -512,16 +492,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -529,10 +504,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -545,35 +516,41 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -584,6 +561,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -600,10 +578,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -646,10 +620,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -734,6 +704,7 @@
 CONFIG_LOCKD=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -759,6 +730,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -769,6 +741,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -776,10 +749,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -796,15 +772,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -813,7 +789,10 @@
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
diff --git a/arch/powerpc/configs/mpc8544_ds_defconfig b/arch/powerpc/configs/mpc8544_ds_defconfig
index b563513..c40a25a 100644
--- a/arch/powerpc/configs/mpc8544_ds_defconfig
+++ b/arch/powerpc/configs/mpc8544_ds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc3
-# Mon Mar 19 17:18:49 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:58 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -46,6 +46,7 @@
 CONFIG_FSL_BOOKE=y
 # CONFIG_PHYS_64BIT is not set
 # CONFIG_SPE is not set
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -73,6 +74,7 @@
 # CONFIG_AUDITSYSCALL is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -90,14 +92,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -129,19 +136,32 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 # CONFIG_MPC8540_ADS is not set
 # CONFIG_MPC8560_ADS is not set
 # CONFIG_MPC85xx_CDS is not set
 # CONFIG_MPC85xx_MDS is not set
 CONFIG_MPC8544_DS=y
 CONFIG_MPC85xx=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -176,28 +196,26 @@
 CONFIG_CMDLINE="root=/dev/sda3 rw console=ttyS0,115200"
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
 CONFIG_ZONE_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_FSL_SOC=y
 # CONFIG_PCI is not set
 # CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Advanced setup
 #
 # CONFIG_ADVANCED_OPTIONS is not set
@@ -219,7 +237,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -270,25 +287,13 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 CONFIG_IP_SCTP=m
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
 # CONFIG_SCTP_HMAC_NONE is not set
 # CONFIG_SCTP_HMAC_SHA1 is not set
 CONFIG_SCTP_HMAC_MD5=y
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -314,10 +319,19 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_AF_RXRPC is not set
 CONFIG_FIB_RULES=y
 
 #
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+
+#
 # Device Drivers
 #
 
@@ -334,10 +348,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -368,10 +378,7 @@
 #
 # Misc devices
 #
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -400,6 +407,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -415,10 +423,6 @@
 #
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_PATA_PLATFORM is not set
@@ -427,25 +431,7 @@
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -455,10 +441,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -479,29 +461,16 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (10000 Mbit)
+# Wireless LAN
 #
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -525,6 +494,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -541,6 +511,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -571,6 +542,7 @@
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
 
 #
 # Non-8250 serial port support
@@ -587,16 +559,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_NVRAM=y
 CONFIG_GEN_RTC=y
 CONFIG_GEN_RTC_X=y
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -604,10 +571,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -620,12 +583,7 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
 # Multifunction device drivers
@@ -636,13 +594,9 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-CONFIG_DVB=y
 CONFIG_DVB_CORE=m
 # CONFIG_DVB_CORE_ATTACH is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
 
 #
 # Supported DVB Frontends
@@ -676,11 +630,18 @@
 #
 # Miscellaneous devices
 #
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -716,10 +677,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -759,17 +716,29 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
 #
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+
+#
 # DMA Engine support
 #
 # CONFIG_DMA_ENGINE is not set
@@ -783,14 +752,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -890,6 +851,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -919,6 +881,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -968,6 +931,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -975,12 +939,14 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -998,7 +964,6 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1020,6 +985,7 @@
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
@@ -1054,6 +1020,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc8560_ads_defconfig b/arch/powerpc/configs/mpc8560_ads_defconfig
index ecaa267..a30bc6f 100644
--- a/arch/powerpc/configs/mpc8560_ads_defconfig
+++ b/arch/powerpc/configs/mpc8560_ads_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:25:53 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:58 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -20,7 +20,7 @@
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_PPC_OF=y
-# CONFIG_PPC_UDBG_16550 is not set
+CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
@@ -34,9 +34,9 @@
 # CONFIG_PPC_83xx is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_85xx=y
 CONFIG_E500=y
@@ -46,6 +46,7 @@
 CONFIG_FSL_BOOKE=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -63,14 +64,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -85,14 +89,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -119,18 +128,33 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CPM2=y
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 # CONFIG_MPC8540_ADS is not set
 CONFIG_MPC8560_ADS=y
 # CONFIG_MPC85xx_CDS is not set
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC8544_DS is not set
 CONFIG_MPC8560=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPC85xx=y
 CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_CPM2=y
 
 #
 # Kernel options
@@ -148,7 +172,6 @@
 CONFIG_BINFMT_MISC=y
 # CONFIG_MATH_EMULATION is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-# CONFIG_PC_KEYBOARD is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -160,32 +183,33 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_PROC_DEVICETREE is not set
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
 CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 CONFIG_PCI_DEBUG=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -210,13 +234,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -250,20 +274,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -289,7 +301,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -302,16 +323,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -322,6 +340,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -340,19 +359,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -361,10 +377,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -380,18 +392,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -401,15 +409,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -444,10 +444,7 @@
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FCC=y
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -461,34 +458,28 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -514,6 +505,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -530,6 +522,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -573,16 +566,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -593,10 +581,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -609,35 +594,41 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -648,6 +639,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -665,10 +657,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -712,10 +700,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -800,6 +784,7 @@
 CONFIG_LOCKD=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -825,6 +810,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -835,6 +821,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -842,10 +829,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -862,15 +852,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -879,7 +869,10 @@
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_KGDB_CONSOLE is not set
 # CONFIG_BDI_SWITCH is not set
diff --git a/arch/powerpc/configs/mpc8568mds_defconfig b/arch/powerpc/configs/mpc8568mds_defconfig
index 7b38006..6451d4d 100644
--- a/arch/powerpc/configs/mpc8568mds_defconfig
+++ b/arch/powerpc/configs/mpc8568mds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Sat Feb 17 16:26:53 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:59 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -46,6 +46,7 @@
 CONFIG_FSL_BOOKE=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -70,8 +71,10 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -84,14 +87,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -123,18 +131,32 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 # CONFIG_MPC8540_ADS is not set
 # CONFIG_MPC8560_ADS is not set
 # CONFIG_MPC85xx_CDS is not set
 CONFIG_MPC85xx_MDS=y
+# CONFIG_MPC8544_DS is not set
 CONFIG_MPC85xx=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -168,18 +190,20 @@
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
 CONFIG_ZONE_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_FSL_SOC=y
 # CONFIG_PCI is not set
 # CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -187,10 +211,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Advanced setup
 #
 # CONFIG_ADVANCED_OPTIONS is not set
@@ -212,7 +232,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -253,20 +272,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -292,7 +299,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -312,10 +328,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -326,6 +338,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -339,17 +352,13 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -378,6 +387,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -393,35 +403,13 @@
 #
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -431,10 +419,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -455,29 +439,16 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (10000 Mbit)
+# Wireless LAN
 #
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -501,6 +472,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -517,6 +489,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -540,6 +513,7 @@
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
 
 #
 # Non-8250 serial port support
@@ -556,10 +530,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -572,7 +542,6 @@
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -580,11 +549,8 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -600,8 +566,8 @@
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -629,16 +595,14 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -661,6 +625,7 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
@@ -677,22 +642,29 @@
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -720,10 +692,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -766,14 +734,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -861,6 +821,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -886,6 +847,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -896,6 +858,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -903,11 +866,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -926,9 +891,9 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -943,8 +908,10 @@
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_DEBUGGER=y
 # CONFIG_XMON is not set
 # CONFIG_BDI_SWITCH is not set
@@ -958,6 +925,7 @@
 # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
 # CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
 # CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+# CONFIG_PPC_EARLY_DEBUG_44x is not set
 
 #
 # Security options
@@ -987,6 +955,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
index 1f61bce..d9afe70 100644
--- a/arch/powerpc/configs/mpc85xx_cds_defconfig
+++ b/arch/powerpc/configs/mpc85xx_cds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:26:46 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:56:59 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@
 # CONFIG_PPC_83xx is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_85xx=y
 CONFIG_E500=y
@@ -46,6 +46,7 @@
 CONFIG_FSL_BOOKE=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -63,14 +64,17 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -85,14 +89,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -119,17 +128,33 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 # CONFIG_MPC8540_ADS is not set
 # CONFIG_MPC8560_ADS is not set
 CONFIG_MPC85xx_CDS=y
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC8544_DS is not set
 CONFIG_MPC8540=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPC85xx=y
 CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -158,32 +183,33 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
 CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_FSL_SOC=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -208,13 +234,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -248,20 +274,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -287,7 +301,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -300,16 +323,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -320,6 +340,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -338,19 +359,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
@@ -365,6 +383,7 @@
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -372,12 +391,13 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -391,6 +411,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -401,10 +422,10 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -413,10 +434,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -432,18 +449,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -453,15 +466,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -493,10 +498,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -510,34 +512,28 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -563,6 +559,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -579,6 +576,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -603,6 +601,7 @@
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
 
 #
 # Non-8250 serial port support
@@ -611,6 +610,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -619,16 +619,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -639,10 +634,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -655,35 +647,41 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -694,6 +692,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -711,10 +710,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -758,10 +753,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -846,6 +837,7 @@
 CONFIG_LOCKD=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -871,6 +863,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -881,6 +874,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -888,10 +882,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -908,15 +905,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -925,7 +922,10 @@
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
index 53fcd69..1ac94a6 100644
--- a/arch/powerpc/configs/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:27:14 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:57:00 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -24,7 +24,7 @@
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
-# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
@@ -34,9 +34,9 @@
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_86xx=y
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
@@ -45,6 +45,7 @@
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -70,9 +71,11 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -87,14 +90,19 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -121,15 +129,28 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="deadline"
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_PPC_INDIRECT_PCI_BE=y
-CONFIG_MPIC=y
 
 #
-# Platform Support
+# Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 CONFIG_MPC8641_HPCN=y
 CONFIG_MPC8641=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -159,33 +180,34 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
 CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_FSL_SOC=y
+CONFIG_FSL_PCIE=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -210,13 +232,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -234,7 +256,7 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
@@ -247,6 +269,7 @@
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
@@ -262,20 +285,8 @@
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -301,7 +312,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -314,16 +334,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -334,6 +351,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -352,19 +370,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=131072
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -373,10 +388,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -392,18 +403,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -413,15 +420,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -453,10 +452,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -468,34 +464,28 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 # CONFIG_GFAR_NAPI is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -521,6 +511,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -537,6 +528,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -581,6 +573,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 
@@ -588,15 +581,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -607,11 +595,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
 
 #
@@ -638,13 +624,13 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -672,27 +658,30 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -702,7 +691,6 @@
 CONFIG_VGA_CONSOLE=y
 # CONFIG_VGACON_SOFT_SCROLLBACK is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -713,6 +701,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -730,10 +719,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -777,10 +762,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -869,6 +850,7 @@
 CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -899,6 +881,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -948,6 +931,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -955,10 +939,13 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -975,15 +962,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -993,7 +980,10 @@
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
diff --git a/arch/powerpc/configs/mpc866_ads_defconfig b/arch/powerpc/configs/mpc866_ads_defconfig
index 539d9e3..e6b18ea 100644
--- a/arch/powerpc/configs/mpc866_ads_defconfig
+++ b/arch/powerpc/configs/mpc866_ads_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc6
-# Fri Nov 24 21:13:55 2006
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:57:00 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -28,7 +29,6 @@
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
@@ -40,6 +40,7 @@
 CONFIG_8xx=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_NOT_COHERENT_CACHE=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -58,14 +59,17 @@
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -78,14 +82,19 @@
 CONFIG_ELF_CORE=y
 # CONFIG_BASE_FULL is not set
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 # CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -112,13 +121,14 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_EMBEDDEDBOOT=y
-# CONFIG_MPIC is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
 CONFIG_CPM1=y
 # CONFIG_MPC8XXFADS is not set
 CONFIG_MPC86XADS=y
@@ -137,6 +147,18 @@
 # CONFIG_USB_SOF_UCODE_PATCH is not set
 # CONFIG_I2C_SPI_UCODE_PATCH is not set
 # CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -144,6 +166,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 CONFIG_HZ_1000=y
 CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
@@ -164,31 +187,29 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_PROC_DEVICETREE is not set
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
 CONFIG_FSL_SOC=y
 # CONFIG_PCI is not set
 # CONFIG_PCI_DOMAINS is not set
 # CONFIG_PCI_QSPAN is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Advanced setup
 #
 # CONFIG_ADVANCED_OPTIONS is not set
@@ -212,13 +233,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -246,25 +267,14 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -290,7 +300,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -307,10 +326,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -321,6 +336,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -331,18 +347,13 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -351,34 +362,13 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -388,10 +378,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -404,6 +390,7 @@
 # CONFIG_CICADA_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 CONFIG_FIXED_PHY=y
 CONFIG_FIXED_MII_10_FDX=y
 CONFIG_FIXED_MII_100_FDX=y
@@ -417,27 +404,14 @@
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
 CONFIG_FS_ENET_HAS_FEC=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -461,6 +435,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -486,9 +461,16 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -516,6 +498,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_CPM=y
@@ -533,31 +516,18 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -570,40 +540,54 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+
+#
 # Sound
 #
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -618,10 +602,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -752,6 +732,7 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -781,6 +762,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -788,14 +770,25 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -809,11 +802,9 @@
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
diff --git a/arch/powerpc/configs/mpc885_ads_defconfig b/arch/powerpc/configs/mpc885_ads_defconfig
index e2c17d8..fc4f9b7 100644
--- a/arch/powerpc/configs/mpc885_ads_defconfig
+++ b/arch/powerpc/configs/mpc885_ads_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Fri Nov 10 21:30:40 2006
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul  1 23:57:01 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -28,7 +29,6 @@
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
@@ -38,6 +38,9 @@
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_8xx=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_MM_SLICES is not set
 CONFIG_NOT_COHERENT_CACHE=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -56,14 +59,17 @@
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -76,14 +82,19 @@
 CONFIG_ELF_CORE=y
 # CONFIG_BASE_FULL is not set
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 # CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -110,19 +121,27 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_EMBEDDEDBOOT=y
-# CONFIG_MPIC is not set
 
 #
 # Platform support
 #
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
 CONFIG_CPM1=y
 # CONFIG_MPC8XXFADS is not set
 # CONFIG_MPC86XADS is not set
 CONFIG_MPC885ADS=y
 
 #
+# Freescale Ethernet driver platform-specific options
+#
+CONFIG_MPC8xx_SECOND_ETH=y
+CONFIG_MPC8xx_SECOND_ETH_FEC2=y
+# CONFIG_MPC8xx_SECOND_ETH_SCC3 is not set
+
+#
 # MPC8xx CPM Options
 #
 
@@ -135,6 +154,18 @@
 # CONFIG_USB_SOF_UCODE_PATCH is not set
 # CONFIG_I2C_SPI_UCODE_PATCH is not set
 # CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -142,6 +173,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 CONFIG_HZ_1000=y
 CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
@@ -162,31 +194,29 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_PROC_DEVICETREE is not set
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
 CONFIG_FSL_SOC=y
 # CONFIG_PCI is not set
 # CONFIG_PCI_DOMAINS is not set
 # CONFIG_PCI_QSPAN is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Advanced setup
 #
 # CONFIG_ADVANCED_OPTIONS is not set
@@ -210,13 +240,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -244,25 +274,14 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -288,7 +307,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -305,10 +333,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -319,6 +343,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -329,18 +354,13 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -349,34 +369,13 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -386,10 +385,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -402,6 +397,7 @@
 # CONFIG_CICADA_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 CONFIG_FIXED_PHY=y
 CONFIG_FIXED_MII_10_FDX=y
 # CONFIG_FIXED_MII_100_FDX is not set
@@ -415,27 +411,14 @@
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
 CONFIG_FS_ENET_HAS_FEC=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -459,6 +442,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -484,9 +468,16 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -514,6 +505,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_CPM=y
@@ -531,31 +523,18 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -568,40 +547,54 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+
+#
 # Sound
 #
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -616,10 +609,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -750,6 +739,7 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -779,6 +769,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -786,14 +777,25 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -807,11 +809,9 @@
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig
index 0507c8f..905998b 100644
--- a/arch/powerpc/configs/pasemi_defconfig
+++ b/arch/powerpc/configs/pasemi_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Mon May 14 12:55:04 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:51:39 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -295,20 +295,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -466,10 +454,6 @@
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -571,7 +555,6 @@
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
 
 #
@@ -580,10 +563,6 @@
 # CONFIG_PCMCIA_FDOMAIN is not set
 # CONFIG_PCMCIA_QLOGIC is not set
 # CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
@@ -694,15 +673,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -752,10 +723,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -774,10 +742,7 @@
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
@@ -786,11 +751,6 @@
 # CONFIG_NETXEN_NIC is not set
 CONFIG_PASEMI_MAC=y
 # CONFIG_MLX4_CORE is not set
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
 # CONFIG_TR is not set
 
 #
@@ -808,15 +768,7 @@
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
-
-#
-# PCMCIA network device support
-#
 # CONFIG_NET_PCMCIA is not set
-
-#
-# Wan interfaces
-#
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -843,6 +795,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -1661,7 +1614,6 @@
 #
 # CONFIG_DLM is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index f611df4..0d8ba62 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1,9 +1,10 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:28:56 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:11:36 2007
 #
 # CONFIG_PPC64 is not set
+CONFIG_PPC_PM_NEEDS_RTC_LIB=y
 CONFIG_PPC32=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
@@ -24,6 +25,7 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -34,9 +36,9 @@
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
@@ -45,6 +47,7 @@
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
 # CONFIG_SMP is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -63,6 +66,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -70,8 +74,10 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -86,14 +92,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -134,12 +145,17 @@
 # CONFIG_APUS is not set
 # CONFIG_PPC_CHRP is not set
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 # CONFIG_PPC_EFIKA is not set
 # CONFIG_PPC_LITE5200 is not set
 CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
 CONFIG_PPC_NATIVE=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_PPC_MPC106=y
@@ -158,11 +174,14 @@
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
 # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPU Frequency drivers
+#
 CONFIG_CPU_FREQ_PMAC=y
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_TAU is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -191,6 +210,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 CONFIG_PM=y
@@ -200,19 +220,23 @@
 CONFIG_PM_SYSFS_DEPRECATED=y
 CONFIG_SOFTWARE_SUSPEND=y
 CONFIG_PM_STD_PARTITION=""
+CONFIG_APM_EMULATION=y
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -237,10 +261,6 @@
 # CONFIG_PD6729 is not set
 # CONFIG_I82092 is not set
 CONFIG_PCCARD_NONSTATIC=m
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -265,14 +285,15 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -297,10 +318,6 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
@@ -314,8 +331,6 @@
 #
 # CONFIG_NETFILTER_NETLINK is not set
 CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
 CONFIG_NF_CONNTRACK=m
 # CONFIG_NF_CT_ACCT is not set
 # CONFIG_NF_CONNTRACK_MARK is not set
@@ -327,16 +342,21 @@
 CONFIG_NF_CONNTRACK_IRC=m
 # CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
 # CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
 # CONFIG_NF_CONNTRACK_SIP is not set
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
 # CONFIG_NETFILTER_XT_TARGET_DSCP is not set
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
@@ -377,7 +397,6 @@
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_NF_NAT=m
 CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -396,14 +415,11 @@
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
 CONFIG_IP_NF_RAW=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 CONFIG_IP_DCCP=m
 CONFIG_INET_DCCP_DIAG=m
 CONFIG_IP_DCCP_ACKVEC=y
@@ -422,15 +438,7 @@
 # DCCP Kernel Hacking
 #
 # CONFIG_IP_DCCP_DEBUG is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -448,6 +456,7 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_SCH_FIFO=y
 CONFIG_NET_CLS_ROUTE=y
 
 #
@@ -485,6 +494,7 @@
 # Dongle support
 #
 # CONFIG_DONGLE is not set
+# CONFIG_KINGSUN_DONGLE is not set
 
 #
 # Old SIR device drivers
@@ -532,13 +542,23 @@
 # CONFIG_BT_HCIBLUECARD is not set
 # CONFIG_BT_HCIBTUART is not set
 # CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+CONFIG_CFG80211=m
+CONFIG_WIRELESS_EXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUG is not set
 CONFIG_IEEE80211=m
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
 # CONFIG_IEEE80211_SOFTMAC is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -551,6 +571,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -558,10 +579,6 @@
 #
 CONFIG_CONNECTOR=y
 CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -572,6 +589,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -592,19 +610,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -615,11 +630,13 @@
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_DELKIN is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=y
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -627,12 +644,12 @@
 # CONFIG_IDE_GENERIC is not set
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -647,6 +664,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -657,13 +675,13 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -693,6 +711,7 @@
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -762,10 +781,6 @@
 # CONFIG_PCMCIA_NINJA_SCSI is not set
 # CONFIG_PCMCIA_QLOGIC is not set
 # CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -787,6 +802,7 @@
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
 # CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
 
 #
 # Fusion MPT device support
@@ -799,28 +815,26 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 CONFIG_IEEE1394=m
 
 #
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
 
 #
-# Device Drivers
+# Controllers
 #
 # CONFIG_IEEE1394_PCILYNX is not set
 CONFIG_IEEE1394_OHCI1394=m
 
 #
-# Protocol Drivers
+# Protocols
 #
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
 # CONFIG_IEEE1394_ETH1394 is not set
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=m
@@ -829,10 +843,7 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
+CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_ADB=y
 CONFIG_ADB_CUDA=y
 CONFIG_ADB_PMU=y
@@ -858,15 +869,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -907,10 +910,8 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -927,77 +928,62 @@
 # CONFIG_BNX2 is not set
 # CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
-#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
 # CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
 # CONFIG_IPW2100 is not set
 # CONFIG_IPW2200 is not set
+# CONFIG_LIBERTAS is not set
 # CONFIG_AIRO is not set
 CONFIG_HERMES=m
 CONFIG_APPLE_AIRPORT=m
 # CONFIG_PLX_HERMES is not set
 # CONFIG_TMD_HERMES is not set
 # CONFIG_NORTEL_HERMES is not set
-# CONFIG_PCI_HERMES is not set
+CONFIG_PCI_HERMES=m
 # CONFIG_ATMEL is not set
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-# CONFIG_PCMCIA_HERMES is not set
+CONFIG_PCMCIA_HERMES=m
 # CONFIG_PCMCIA_SPECTRUM is not set
 # CONFIG_AIRO_CS is not set
 # CONFIG_PCMCIA_WL3501 is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
 CONFIG_PRISM54=m
 # CONFIG_USB_ZD1201 is not set
 # CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
 
 #
-# PCMCIA network device support
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET_MII=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
 # CONFIG_NET_PCMCIA is not set
-
-#
-# Wan interfaces
-#
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -1033,6 +1019,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -1059,8 +1046,10 @@
 CONFIG_INPUT_MOUSE=y
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -1100,6 +1089,7 @@
 CONFIG_SERIAL_CORE=m
 CONFIG_SERIAL_PMACZILOG=m
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -1108,16 +1098,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_NVRAM=y
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 CONFIG_AGP=m
@@ -1143,11 +1128,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=m
 
 #
@@ -1175,14 +1158,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -1210,37 +1194,56 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+CONFIG_VGASTATE=y
 CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
 CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
 CONFIG_FB_MACMODES=y
 CONFIG_FB_BACKLIGHT=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -1255,6 +1258,7 @@
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_NVIDIA=y
 CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
 CONFIG_FB_NVIDIA_BACKLIGHT=y
 # CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
@@ -1274,6 +1278,7 @@
 # CONFIG_FB_ATY_GENERIC_LCD is not set
 CONFIG_FB_ATY_GX=y
 CONFIG_FB_ATY_BACKLIGHT=y
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -1281,7 +1286,10 @@
 CONFIG_FB_3DFX=y
 # CONFIG_FB_3DFX_ACCEL is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_FB_VIRTUAL is not set
 
@@ -1295,26 +1303,15 @@
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
 CONFIG_LOGO=y
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
 
 #
 # Sound
 #
 CONFIG_SOUND=m
-CONFIG_DMASOUND_PMAC=m
-CONFIG_DMASOUND=m
 
 #
 # Advanced Linux Sound Architecture
@@ -1428,6 +1425,7 @@
 #
 CONFIG_SND_USB_AUDIO=m
 # CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
 
 #
 # PCMCIA devices
@@ -1436,6 +1434,11 @@
 # CONFIG_SND_PDAUDIOCF is not set
 
 #
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
 # Open Sound System
 #
 # CONFIG_SOUND_PRIME is not set
@@ -1444,6 +1447,15 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
 
 #
 # USB support
@@ -1458,10 +1470,9 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 CONFIG_USB_DYNAMIC_MINORS=y
 # CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1471,9 +1482,12 @@
 CONFIG_USB_EHCI_SPLIT_ISO=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -1506,49 +1520,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT_POWERBOOK=y
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-CONFIG_USB_APPLETOUCH=y
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-CONFIG_USB_USBNET_MII=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_NET_AX8817X=m
-CONFIG_USB_NET_CDCETHER=m
-# CONFIG_USB_NET_GL620A is not set
-CONFIG_USB_NET_NET1080=m
-# CONFIG_USB_NET_PLUSB is not set
-# CONFIG_USB_NET_MCS7830 is not set
-# CONFIG_USB_NET_RNDIS_HOST is not set
-# CONFIG_USB_NET_CDC_SUBSET is not set
-CONFIG_USB_NET_ZAURUS=m
 CONFIG_USB_MON=y
 
 #
@@ -1620,6 +1595,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1630,6 +1606,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1640,10 +1617,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1676,6 +1649,7 @@
 #
 # Real Time Clock
 #
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 
 #
@@ -1692,10 +1666,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1731,7 +1701,6 @@
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1796,6 +1765,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
@@ -1826,6 +1796,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1875,6 +1846,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1882,6 +1854,7 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
@@ -1891,13 +1864,16 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
 #
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
+# CONFIG_KPROBES is not set
 
 #
 # Kernel hacking
@@ -1909,15 +1885,15 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1927,6 +1903,9 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
@@ -1962,8 +1941,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1978,6 +1960,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 126b9f8..6e503d9 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:28:58 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:15:02 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -27,6 +27,7 @@
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC64_SWSUSP=y
 
 #
 # Processor support
@@ -41,6 +42,7 @@
 CONFIG_PPC_OF_PLATFORM_PCI=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
@@ -61,20 +63,23 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_TASKSTATS=y
 CONFIG_TASK_DELAY_ACCT=y
+# CONFIG_TASK_XACCT is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
 CONFIG_CPUSETS=y
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-# CONFIG_TASK_XACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_SYSCTL_SYSCALL=y
@@ -87,14 +92,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -133,24 +143,54 @@
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
 CONFIG_PPC_PSERIES=y
+CONFIG_PPC_SPLPAR=y
+CONFIG_EEH=y
+CONFIG_SCANLOG=m
+CONFIG_LPARCFG=y
 CONFIG_PPC_ISERIES=y
+
+#
+# iSeries device drivers
+#
+CONFIG_VIODASD=y
+CONFIG_VIOCD=m
+CONFIG_VIOTAPE=m
+CONFIG_VIOPATH=y
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PMAC64=y
 CONFIG_PPC_MAPLE=y
 # CONFIG_PPC_PASEMI is not set
+CONFIG_PPC_CELLEB=y
+# CONFIG_PPC_PS3 is not set
 CONFIG_PPC_CELL=y
 CONFIG_PPC_CELL_NATIVE=y
 CONFIG_PPC_IBM_CELL_BLADE=y
-# CONFIG_PPC_PS3 is not set
+
+#
+# Cell Broadband Engine options
+#
+CONFIG_SPU_FS=m
+CONFIG_SPU_FS_64K_LS=y
+CONFIG_SPU_BASE=y
+CONFIG_CBE_RAS=y
+CONFIG_CBE_THERM=m
+CONFIG_CBE_CPUFREQ=m
+# CONFIG_PQ2ADS is not set
 CONFIG_PPC_NATIVE=y
 CONFIG_UDBG_RTAS_CONSOLE=y
+CONFIG_PPC_UDBG_BEAT=y
 CONFIG_XICS=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
 CONFIG_U3_DART=y
 CONFIG_PPC_RTAS=y
 CONFIG_RTAS_ERROR_LOGGING=y
 CONFIG_RTAS_PROC=y
 CONFIG_RTAS_FLASH=m
+CONFIG_PPC_PMI=m
 CONFIG_MMIO_NVRAM=y
 CONFIG_MPIC_U3_HT_IRQS=y
 CONFIG_IBMVIO=y
@@ -171,18 +211,12 @@
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
 # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
-CONFIG_CPU_FREQ_PMAC64=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
 
 #
-# Cell Broadband Engine options
+# CPU Frequency drivers
 #
-CONFIG_SPU_FS=m
-CONFIG_SPU_BASE=y
-CONFIG_CBE_RAS=y
-CONFIG_CBE_THERM=m
-CONFIG_CBE_CPUFREQ=m
+CONFIG_CPU_FREQ_PMAC64=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -205,10 +239,6 @@
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
-CONFIG_PPC_SPLPAR=y
-CONFIG_EEH=y
-CONFIG_SCANLOG=m
-CONFIG_LPARCFG=y
 # CONFIG_NUMA is not set
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
@@ -227,35 +257,35 @@
 CONFIG_MEMORY_HOTPLUG_SPARSE=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ARCH_MEMORY_PROBE=y
+CONFIG_PPC_HAS_HASH_64K=y
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 CONFIG_HOTPLUG_PCI=m
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
@@ -272,14 +302,15 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -304,10 +335,6 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
@@ -323,8 +350,6 @@
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
 CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CT_ACCT=y
 CONFIG_NF_CONNTRACK_MARK=y
@@ -337,10 +362,42 @@
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
 CONFIG_NF_CONNTRACK_PPTP=m
+# CONFIG_NF_CONNTRACK_SANE is not set
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
-# CONFIG_NETFILTER_XTABLES is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
@@ -348,20 +405,45 @@
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -380,6 +462,7 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -388,7 +471,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -401,16 +493,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -421,6 +510,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -440,19 +530,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -467,6 +554,7 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -474,12 +562,12 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -494,6 +582,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -504,13 +593,14 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_CELLEB=y
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -540,6 +630,7 @@
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -593,11 +684,8 @@
 # CONFIG_SCSI_DC390T is not set
 CONFIG_SCSI_DEBUG=m
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
+CONFIG_ATA_NONSTANDARD=y
 # CONFIG_SATA_AHCI is not set
 CONFIG_SATA_SVW=y
 # CONFIG_ATA_PIIX is not set
@@ -613,10 +701,12 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -628,6 +718,7 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -647,6 +738,7 @@
 # CONFIG_PATA_SIS is not set
 # CONFIG_PATA_VIA is not set
 CONFIG_PATA_WINBOND=y
+CONFIG_PATA_SCC=y
 
 #
 # Multi-device support (RAID and LVM)
@@ -669,6 +761,7 @@
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_DELAY is not set
 
 #
 # Fusion MPT device support
@@ -681,28 +774,26 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 CONFIG_IEEE1394=y
 
 #
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
 
 #
-# Device Drivers
+# Controllers
 #
 # CONFIG_IEEE1394_PCILYNX is not set
 CONFIG_IEEE1394_OHCI1394=y
 
 #
-# Protocol Drivers
+# Protocols
 #
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
 CONFIG_IEEE1394_ETH1394=m
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=y
@@ -711,10 +802,7 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
+CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_ADB_PMU=y
 # CONFIG_ADB_PMU_LED is not set
 CONFIG_PMAC_SMU=y
@@ -734,16 +822,23 @@
 CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
+CONFIG_PHYLIB=m
 
 #
-# PHY device support
+# MII PHY device drivers
 #
-# CONFIG_PHYLIB is not set
+CONFIG_MARVELL_PHY=m
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+CONFIG_BROADCOM_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
 
 #
 # Ethernet (10 or 100Mbit)
@@ -782,10 +877,8 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
 CONFIG_ACENIC=y
 CONFIG_ACENIC_OMIT_TIGON_I=y
 # CONFIG_DL2K is not set
@@ -805,33 +898,37 @@
 # CONFIG_BNX2 is not set
 CONFIG_SPIDER_NET=m
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+CONFIG_PASEMI_MAC=m
+# CONFIG_MLX4_CORE is not set
 CONFIG_TR=y
 CONFIG_IBMOL=y
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 CONFIG_ISERIES_VETH=m
 # CONFIG_FDDI is not set
@@ -851,7 +948,6 @@
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
 CONFIG_NETPOLL_TRAP=y
 CONFIG_NET_POLL_CONTROLLER=y
 
@@ -870,6 +966,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -895,12 +992,25 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
 # CONFIG_INPUT_UINPUT is not set
 
 #
@@ -940,7 +1050,12 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_PMACZILOG is not set
 CONFIG_SERIAL_ICOM=m
+CONFIG_SERIAL_TXX9=y
+CONFIG_HAS_TXX9_SERIAL=y
+CONFIG_SERIAL_TXX9_NR_UARTS=6
+CONFIG_SERIAL_TXX9_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -948,21 +1063,17 @@
 CONFIG_HVC_CONSOLE=y
 CONFIG_HVC_ISERIES=y
 CONFIG_HVC_RTAS=y
+CONFIG_HVC_BEAT=y
 CONFIG_HVCS=m
 
 #
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -975,11 +1086,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
 
 #
@@ -1006,14 +1115,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -1040,37 +1150,56 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+# CONFIG_VGASTATE is not set
 CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
 CONFIG_FB_MACMODES=y
-# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_BACKLIGHT=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -1090,16 +1219,21 @@
 CONFIG_FB_MATROX_MULTIHEAD=y
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
 # CONFIG_FB_RADEON_DEBUG is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 CONFIG_FB_IBM_GXT4500=y
 # CONFIG_FB_VIRTUAL is not set
 
@@ -1113,19 +1247,10 @@
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
 CONFIG_LOGO=y
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -1242,6 +1367,12 @@
 #
 # CONFIG_SND_USB_AUDIO is not set
 # CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
 
 #
 # Open Sound System
@@ -1252,6 +1383,15 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
 
 #
 # USB support
@@ -1266,9 +1406,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1278,9 +1417,12 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -1314,40 +1456,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 # CONFIG_USB_MON is not set
 
 #
@@ -1369,6 +1481,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1379,6 +1492,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1389,10 +1503,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1417,8 +1527,11 @@
 CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_IPATH is not set
 # CONFIG_INFINIBAND_AMSO1100 is not set
+# CONFIG_MLX4_INFINIBAND is not set
 CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
 # CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
 # CONFIG_INFINIBAND_SRP is not set
@@ -1447,10 +1560,6 @@
 #
 
 #
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1567,6 +1676,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
@@ -1602,6 +1712,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -1651,15 +1762,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
-
-#
-# iSeries device drivers
-#
-# CONFIG_VIOCONS is not set
-CONFIG_VIODASD=y
-CONFIG_VIOCD=m
-CONFIG_VIOTAPE=m
-CONFIG_VIOPATH=y
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1667,14 +1770,19 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_TEXTSEARCH=y
 CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1693,15 +1801,15 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1711,8 +1819,10 @@
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_HCALL_STATS is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
@@ -1749,8 +1859,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1765,6 +1878,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
 CONFIG_CRYPTO_TEST=m
 
 #
diff --git a/arch/powerpc/configs/prpmc2800_defconfig b/arch/powerpc/configs/prpmc2800_defconfig
index c70a730..fb504a7 100644
--- a/arch/powerpc/configs/prpmc2800_defconfig
+++ b/arch/powerpc/configs/prpmc2800_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Wed May  9 09:42:46 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:15:11 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -90,7 +90,11 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
@@ -274,20 +278,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -383,7 +375,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -454,10 +445,6 @@
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -472,6 +459,7 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -479,6 +467,7 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
@@ -588,12 +577,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
@@ -665,6 +649,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -683,15 +668,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 CONFIG_PHYLIB=y
 
 #
@@ -746,10 +723,7 @@
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -769,20 +743,14 @@
 CONFIG_MV643XX_ETH=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
@@ -792,8 +760,14 @@
 # CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -820,6 +794,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -880,16 +855,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -1023,12 +993,8 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
@@ -1124,16 +1090,6 @@
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1261,14 +1217,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1396,7 +1344,6 @@
 #
 # CONFIG_DLM is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -1404,6 +1351,7 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 4779345..d0b43df 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Fri May 11 10:16:27 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:15:19 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -87,7 +87,11 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
@@ -152,7 +156,11 @@
 CONFIG_PS3_USE_LPAR_ADDR=y
 CONFIG_PS3_VUART=y
 CONFIG_PS3_PS3AV=y
-CONFIG_PS3_SYS_MANAGER=y
+CONFIG_PS3_SYS_MANAGER=m
+CONFIG_PS3_STORAGE=y
+CONFIG_PS3_DISK=y
+CONFIG_PS3_ROM=y
+CONFIG_PS3_FLASH=y
 CONFIG_PPC_CELL=y
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
@@ -301,20 +309,8 @@
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -343,7 +339,7 @@
 CONFIG_BT_L2CAP=m
 CONFIG_BT_SCO=m
 CONFIG_BT_RFCOMM=m
-# CONFIG_BT_RFCOMM_TTY is not set
+CONFIG_BT_RFCOMM_TTY=y
 # CONFIG_BT_BNEP is not set
 CONFIG_BT_HIDP=m
 
@@ -352,7 +348,9 @@
 #
 CONFIG_BT_HCIUSB=m
 CONFIG_BT_HCIUSB_SCO=y
-# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
 # CONFIG_BT_HCIBFUSB is not set
@@ -418,10 +416,6 @@
 # Misc devices
 #
 # CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
 # CONFIG_IDE is not set
 
 #
@@ -447,7 +441,7 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
@@ -467,11 +461,6 @@
 #
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -490,27 +479,13 @@
 # CONFIG_TUN is not set
 
 #
-# PHY device support
-#
-
-#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
 CONFIG_MII=m
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+CONFIG_GELIC_NET=y
 
 #
 # Wireless LAN
@@ -536,10 +511,6 @@
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
-
-#
-# Wan interfaces
-#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -563,6 +534,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -581,7 +553,27 @@
 #
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+# CONFIG_JOYSTICK_XPAD is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
@@ -598,7 +590,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -652,12 +644,8 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
@@ -672,13 +660,13 @@
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+CONFIG_FB_SYS_FOPS=y
 CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
@@ -751,9 +739,10 @@
 #
 # CONFIG_SND_USB_AUDIO is not set
 # CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
 
 #
-# SoC audio support
+# System on Chip audio support
 #
 # CONFIG_SND_SOC is not set
 
@@ -1098,7 +1087,6 @@
 #
 # CONFIG_DLM is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -1125,7 +1113,7 @@
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1155,16 +1143,7 @@
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 6e96e50..0caf0dd 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:31:27 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:17:45 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -40,6 +40,7 @@
 # CONFIG_PPC_OF_PLATFORM_PCI is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=128
@@ -60,16 +61,23 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
 # CONFIG_UTS_NS is not set
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
 CONFIG_CPUSETS=y
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
@@ -84,14 +92,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -130,18 +143,28 @@
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
 CONFIG_PPC_PSERIES=y
+CONFIG_PPC_SPLPAR=y
+CONFIG_EEH=y
+CONFIG_SCANLOG=m
+CONFIG_LPARCFG=y
 # CONFIG_PPC_ISERIES is not set
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_PASEMI is not set
+# CONFIG_PPC_CELLEB is not set
+# CONFIG_PPC_PS3 is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_PPC_PS3 is not set
+# CONFIG_PQ2ADS is not set
 CONFIG_PPC_NATIVE=y
 # CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_XICS=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
 # CONFIG_U3_DART is not set
 CONFIG_PPC_RTAS=y
 CONFIG_RTAS_ERROR_LOGGING=y
@@ -155,8 +178,7 @@
 # CONFIG_PPC_INDIRECT_IO is not set
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -179,10 +201,6 @@
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
-CONFIG_PPC_SPLPAR=y
-CONFIG_EEH=y
-CONFIG_SCANLOG=m
-CONFIG_LPARCFG=y
 CONFIG_NUMA=y
 CONFIG_NODES_SHIFT=4
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
@@ -202,35 +220,35 @@
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_NODES_SPAN_OTHER_NODES=y
+# CONFIG_PPC_HAS_HASH_64K is not set
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_SCHED_SMT=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 CONFIG_HOTPLUG_PCI=m
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
@@ -247,14 +265,15 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -279,10 +298,6 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
@@ -298,10 +313,8 @@
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
 CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
 CONFIG_NF_CONNTRACK=m
-# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CT_ACCT=y
 CONFIG_NF_CONNTRACK_MARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 # CONFIG_NF_CT_PROTO_SCTP is not set
@@ -311,10 +324,39 @@
 CONFIG_NF_CONNTRACK_IRC=m
 # CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
 # CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
 # CONFIG_NF_CONNTRACK_SIP is not set
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
-# CONFIG_NETFILTER_XTABLES is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
@@ -322,20 +364,38 @@
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -354,6 +414,7 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -363,7 +424,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -376,16 +446,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -403,6 +470,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -423,19 +491,16 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -450,6 +515,7 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -457,12 +523,12 @@
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -477,6 +543,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -487,10 +554,10 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -520,6 +587,7 @@
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -575,11 +643,8 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
 # CONFIG_ATA_PIIX is not set
@@ -595,10 +660,12 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -610,6 +677,7 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -650,6 +718,7 @@
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_DELAY is not set
 
 #
 # Fusion MPT device support
@@ -662,18 +731,14 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -683,15 +748,7 @@
 CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -731,11 +788,9 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 # CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 CONFIG_ACENIC=y
 CONFIG_ACENIC_OMIT_TIGON_I=y
 # CONFIG_DL2K is not set
@@ -754,11 +809,10 @@
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 CONFIG_EHEA=m
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
@@ -766,23 +820,28 @@
 # CONFIG_S2IO_NAPI is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_PASEMI_MAC is not set
+# CONFIG_MLX4_CORE is not set
 CONFIG_TR=y
 CONFIG_IBMOL=y
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -802,7 +861,6 @@
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
 CONFIG_NETPOLL_TRAP=y
 CONFIG_NET_POLL_CONTROLLER=y
 
@@ -821,6 +879,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -846,12 +905,25 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
 # CONFIG_INPUT_UINPUT is not set
 
 #
@@ -892,6 +964,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_ICOM=m
 CONFIG_SERIAL_JSM=m
+# CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -907,15 +980,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_AGP is not set
@@ -928,11 +996,9 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
 
 #
@@ -959,14 +1025,15 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -993,37 +1060,56 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+# CONFIG_VGASTATE is not set
 CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
 CONFIG_FB_MACMODES=y
-# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_BACKLIGHT=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -1042,16 +1128,21 @@
 CONFIG_FB_MATROX_MULTIHEAD=y
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
 # CONFIG_FB_RADEON_DEBUG is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 CONFIG_FB_IBM_GXT4500=y
 # CONFIG_FB_VIRTUAL is not set
 
@@ -1065,19 +1156,10 @@
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
 CONFIG_LOGO=y
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -1088,6 +1170,15 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
 
 #
 # USB support
@@ -1102,9 +1193,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1114,9 +1204,12 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -1149,40 +1242,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1205,6 +1268,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1215,6 +1279,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1225,10 +1290,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1250,13 +1311,16 @@
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_MAD=m
 CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
 CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_IPATH is not set
 CONFIG_INFINIBAND_EHCA=m
-CONFIG_INFINIBAND_EHCA_SCALING=y
 # CONFIG_INFINIBAND_AMSO1100 is not set
+# CONFIG_MLX4_INFINIBAND is not set
 CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
 # CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
 CONFIG_INFINIBAND_SRP=m
@@ -1285,8 +1349,9 @@
 #
 
 #
-# Virtualization
+# Auxiliary Display support
 #
+# CONFIG_KS0108 is not set
 
 #
 # File systems
@@ -1341,7 +1406,6 @@
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1407,6 +1471,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
@@ -1476,6 +1541,7 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
 
 #
 # Library routines
@@ -1483,12 +1549,19 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
 
 #
 # Instrumentation Support
@@ -1507,15 +1580,15 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1526,8 +1599,10 @@
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HCALL_STATS=y
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
@@ -1564,8 +1639,11 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1580,6 +1658,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
 CONFIG_CRYPTO_TEST=m
 
 #
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 3e779f0..42c42ec 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,7 +12,8 @@
 
 obj-y				:= semaphore.o cputable.o ptrace.o syscalls.o \
 				   irq.o align.o signal_32.o pmc.o vdso.o \
-				   init_task.o process.o systbl.o idle.o
+				   init_task.o process.o systbl.o idle.o \
+				   signal.o
 obj-y				+= vdso32/
 obj-$(CONFIG_PPC64)		+= setup_64.o binfmt_elf32.o sys_ppc32.o \
 				   signal_64.o ptrace32.o \
@@ -65,9 +66,9 @@
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
 
-pci64-$(CONFIG_PPC64)		+= pci_64.o pci_dn.o
+pci64-$(CONFIG_PPC64)		+= pci_64.o pci_dn.o isa-bridge.o
 pci32-$(CONFIG_PPC32)		:= pci_32.o
-obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y)
+obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y) pci-common.o
 obj-$(CONFIG_PCI_MSI)		+= msi.o
 kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o
 kexec-$(CONFIG_PPC32)		:= machine_kexec_32.o
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 6ef87fb..b1f8000 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -235,6 +235,7 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
+		.pmc_type		= PPC_PMC_IBM,
 		.cpu_setup		= __setup_cpu_ppc970,
 		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970MP",
@@ -251,6 +252,7 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
+		.pmc_type		= PPC_PMC_IBM,
 		.cpu_setup		= __setup_cpu_ppc970MP,
 		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970MP",
@@ -292,6 +294,21 @@
 		.oprofile_mmcra_sipr	= MMCRA_SIPR,
 		.platform		= "power5",
 	},
+	{	/* Power5++ */
+		.pvr_mask		= 0xffffff00,
+		.pvr_value		= 0x003b0300,
+		.cpu_name		= "POWER5+ (gs)",
+		.cpu_features		= CPU_FTRS_POWER5,
+		.cpu_user_features	= COMMON_USER_POWER5_PLUS,
+		.icache_bsize		= 128,
+		.dcache_bsize		= 128,
+		.num_pmcs		= 6,
+		.oprofile_cpu_type	= "ppc64/power5++",
+		.oprofile_type		= PPC_OPROFILE_POWER4,
+		.oprofile_mmcra_sihv	= MMCRA_SIHV,
+		.oprofile_mmcra_sipr	= MMCRA_SIPR,
+		.platform		= "power5+",
+	},
 	{	/* Power5 GS */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x003b0000,
@@ -317,6 +334,7 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
+		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/power6",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.oprofile_mmcra_sihv	= POWER6_MMCRA_SIHV,
@@ -335,6 +353,7 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
+		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/power6",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.oprofile_mmcra_sihv	= POWER6_MMCRA_SIHV,
@@ -1174,8 +1193,8 @@
 		.platform		= "ppc440",
 	},
 	{ /* 440SP Rev. A */
-		.pvr_mask		= 0xff000fff,
-		.pvr_value		= 0x53000891,
+		.pvr_mask		= 0xfff00fff,
+		.pvr_value		= 0x53200891,
 		.cpu_name		= "440SP Rev. A",
 		.cpu_features		= CPU_FTRS_44X,
 		.cpu_user_features	= COMMON_USER_BOOKE,
@@ -1184,9 +1203,19 @@
 		.platform		= "ppc440",
 	},
 	{ /* 440SPe Rev. A */
-		.pvr_mask		= 0xff000fff,
-		.pvr_value		= 0x53000890,
-		.cpu_name		= "440SPe Rev. A",
+		.pvr_mask               = 0xfff00fff,
+		.pvr_value              = 0x53400890,
+		.cpu_name               = "440SPe Rev. A",
+		.cpu_features		= CPU_FTRS_44X,
+		.cpu_user_features      = COMMON_USER_BOOKE,
+		.icache_bsize           = 32,
+		.dcache_bsize           = 32,
+		.platform               = "ppc440",
+	},
+	{ /* 440SPe Rev. B */
+		.pvr_mask		= 0xfff00fff,
+		.pvr_value		= 0x53400891,
+		.cpu_name		= "440SPe Rev. B",
 		.cpu_features		= CPU_FTRS_44X,
 		.cpu_user_features	= COMMON_USER_BOOKE,
 		.icache_bsize		= 32,
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index c897203..7d73a13 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -9,7 +9,6 @@
  *  rewritten by Paul Mackerras.
  *    Copyright (C) 1996 Paul Mackerras.
  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  This file contains the low-level support and setup for the
  *  PowerPC platform, including trap and interrupt dispatch.
@@ -32,10 +31,6 @@
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 
-#ifdef CONFIG_APUS
-#include <asm/amigappc.h>
-#endif
-
 /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
 #define LOAD_BAT(n, reg, RA, RB)	\
 	/* see the comment for clear_bats() -- Cort */ \
@@ -92,11 +87,6 @@
  *  r4: virtual address of boot_infos_t
  *  r5: 0
  *
- * APUS
- *   r3: 'APUS'
- *   r4: physical address of memory base
- *   Linux/m68k style BootInfo structure at &_end.
- *
  * PREP
  * This is jumped to on prep systems right after the kernel is relocated
  * to its proper place in memory by the boot loader.  The expected layout
@@ -150,14 +140,6 @@
  */
 	bl	early_init
 
-#ifdef CONFIG_APUS
-/* On APUS the __va/__pa constants need to be set to the correct
- * values before continuing.
- */
-	mr	r4,r30
-	bl	fix_mem_constants
-#endif /* CONFIG_APUS */
-
 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
  * the physical address we are running at, returned by early_init()
  */
@@ -167,7 +149,7 @@
 	bl	flush_tlbs
 
 	bl	initial_bats
-#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+#if defined(CONFIG_BOOTX_TEXT)
 	bl	setup_disp_bat
 #endif
 
@@ -183,7 +165,6 @@
 #endif /* CONFIG_6xx */
 
 
-#ifndef CONFIG_APUS
 /*
  * We need to run with _start at physical address 0.
  * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
@@ -196,7 +177,6 @@
 	addis	r4,r3,KERNELBASE@h	/* current address of _start */
 	cmpwi	0,r4,0			/* are we already running at 0? */
 	bne	relocate_kernel
-#endif /* CONFIG_APUS */
 /*
  * we now have the 1st 16M of ram mapped with the bats.
  * prep needs the mmu to be turned on here, but pmac already has it on.
@@ -881,85 +861,6 @@
 	addi	r6,r6,4
 	blr
 
-#ifdef CONFIG_APUS
-/*
- * On APUS the physical base address of the kernel is not known at compile
- * time, which means the __pa/__va constants used are incorrect. In the
- * __init section is recorded the virtual addresses of instructions using
- * these constants, so all that has to be done is fix these before
- * continuing the kernel boot.
- *
- * r4 = The physical address of the kernel base.
- */
-fix_mem_constants:
-	mr	r10,r4
-	addis	r10,r10,-KERNELBASE@h    /* virt_to_phys constant */
-	neg	r11,r10	                 /* phys_to_virt constant */
-
-	lis	r12,__vtop_table_begin@h
-	ori	r12,r12,__vtop_table_begin@l
-	add	r12,r12,r10	         /* table begin phys address */
-	lis	r13,__vtop_table_end@h
-	ori	r13,r13,__vtop_table_end@l
-	add	r13,r13,r10	         /* table end phys address */
-	subi	r12,r12,4
-	subi	r13,r13,4
-1:	lwzu	r14,4(r12)               /* virt address of instruction */
-	add     r14,r14,r10              /* phys address of instruction */
-	lwz     r15,0(r14)               /* instruction, now insert top */
-	rlwimi  r15,r10,16,16,31         /* half of vp const in low half */
-	stw	r15,0(r14)               /* of instruction and restore. */
-	dcbst	r0,r14			 /* write it to memory */
-	sync
-	icbi	r0,r14			 /* flush the icache line */
-	cmpw	r12,r13
-	bne     1b
-	sync				/* additional sync needed on g4 */
-	isync
-
-/*
- * Map the memory where the exception handlers will
- * be copied to when hash constants have been patched.
- */
-#ifdef CONFIG_APUS_FAST_EXCEPT
-	lis	r8,0xfff0
-#else
-	lis	r8,0
-#endif
-	ori	r8,r8,0x2		/* 128KB, supervisor */
-	mtspr	SPRN_DBAT3U,r8
-	mtspr	SPRN_DBAT3L,r8
-
-	lis	r12,__ptov_table_begin@h
-	ori	r12,r12,__ptov_table_begin@l
-	add	r12,r12,r10	         /* table begin phys address */
-	lis	r13,__ptov_table_end@h
-	ori	r13,r13,__ptov_table_end@l
-	add	r13,r13,r10	         /* table end phys address */
-	subi	r12,r12,4
-	subi	r13,r13,4
-1:	lwzu	r14,4(r12)               /* virt address of instruction */
-	add     r14,r14,r10              /* phys address of instruction */
-	lwz     r15,0(r14)               /* instruction, now insert top */
-	rlwimi  r15,r11,16,16,31         /* half of pv const in low half*/
-	stw	r15,0(r14)               /* of instruction and restore. */
-	dcbst	r0,r14			 /* write it to memory */
-	sync
-	icbi	r0,r14			 /* flush the icache line */
-	cmpw	r12,r13
-	bne     1b
-
-	sync				/* additional sync needed on g4 */
-	isync				/* No speculative loading until now */
-	blr
-
-/***********************************************************************
- *  Please note that on APUS the exception handlers are located at the
- *  physical address 0xfff0000. For this reason, the exception handlers
- *  cannot use relative branches to access the code below.
- ***********************************************************************/
-#endif /* CONFIG_APUS */
-
 #ifdef CONFIG_SMP
 #ifdef CONFIG_GEMINI
 	.globl	__secondary_start_gemini
@@ -1135,19 +1036,6 @@
 	bl	__save_cpu_setup
 	bl	MMU_init
 
-#ifdef CONFIG_APUS
-	/* Copy exception code to exception vector base on APUS. */
-	lis	r4,KERNELBASE@h
-#ifdef CONFIG_APUS_FAST_EXCEPT
-	lis	r3,0xfff0		/* Copy to 0xfff00000 */
-#else
-	lis	r3,0			/* Copy to 0x00000000 */
-#endif
-	li	r5,0x4000		/* # bytes of memory to copy */
-	li	r6,0
-	bl	copy_and_flush		/* copy the first 0x4000 bytes */
-#endif  /* CONFIG_APUS */
-
 /*
  * Go back to running unmapped so we can load up new values
  * for SDR1 (hash table pointer) and the segment registers
@@ -1324,11 +1212,7 @@
 #else
 	ori	r8,r8,2			/* R/W access */
 #endif /* CONFIG_SMP */
-#ifdef CONFIG_APUS
-	ori	r11,r11,BL_8M<<2|0x2	/* set up 8MB BAT registers for 604 */
-#else
 	ori	r11,r11,BL_256M<<2|0x2	/* set up BAT registers for 604 */
-#endif /* CONFIG_APUS */
 
 	mtspr	SPRN_DBAT0L,r8		/* N.B. 6xx (not 601) have valid */
 	mtspr	SPRN_DBAT0U,r11		/* bit in upper BAT register */
@@ -1338,7 +1222,7 @@
 	blr
 
 
-#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+#ifdef CONFIG_BOOTX_TEXT
 setup_disp_bat:
 	/*
 	 * setup the display bat prepared for us in prom.c
@@ -1362,7 +1246,7 @@
 1:	mtspr	SPRN_IBAT3L,r8
 	mtspr	SPRN_IBAT3U,r11
 	blr
-#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
+#endif /* CONFIG_BOOTX_TEXT */
 
 #ifdef CONFIG_8260
 /* Jump into the system reset for the rom.
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 1111fce..8cdd48e 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -103,8 +103,8 @@
 
 	. = 0x60
 /*
- * The following code is used on pSeries to hold secondary processors
- * in a spin loop after they have been freed from OpenFirmware, but
+ * The following code is used to hold secondary processors
+ * in a spin loop after they have entered the kernel, but
  * before the bulk of the kernel has been relocated.  This code
  * is relocated to physical address 0x60 before prom_init is run.
  * All of it must fit below the first exception vector at 0x100.
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c
index 34ae114..e31aca92 100644
--- a/arch/powerpc/kernel/io.c
+++ b/arch/powerpc/kernel/io.c
@@ -35,7 +35,7 @@
 	asm volatile("sync");
 	do {
 		tmp = *port;
-		asm volatile("eieio");
+		eieio();
 		*tbuf++ = tmp;
 	} while (--count != 0);
 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -66,7 +66,7 @@
 	asm volatile("sync");
 	do {
 		tmp = *port;
-		asm volatile("eieio");
+		eieio();
 		*tbuf++ = tmp;
 	} while (--count != 0);
 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -97,7 +97,7 @@
 	asm volatile("sync");
 	do {
 		tmp = *port;
-		asm volatile("eieio");
+		eieio();
 		*tbuf++ = tmp;
 	} while (--count != 0);
 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -155,21 +155,21 @@
 	__asm__ __volatile__ ("sync" : : : "memory");
 	while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) {
 		*((u8 *)dest) = *((volatile u8 *)vsrc);
-		__asm__ __volatile__ ("eieio" : : : "memory");
+		eieio();
 		vsrc++;
 		dest++;
 		n--;
 	}
 	while(n > 4) {
 		*((u32 *)dest) = *((volatile u32 *)vsrc);
-		__asm__ __volatile__ ("eieio" : : : "memory");
+		eieio();
 		vsrc += 4;
 		dest += 4;
 		n -= 4;
 	}
 	while(n) {
 		*((u8 *)dest) = *((volatile u8 *)vsrc);
-		__asm__ __volatile__ ("eieio" : : : "memory");
+		eieio();
 		vsrc++;
 		dest++;
 		n--;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 068377a..2fc8786 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -7,7 +7,6 @@
  *    Copyright (C) 1996-2001 Cort Dougan
  *  Adapted for Power Macintosh by Paul Mackerras
  *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -337,7 +336,8 @@
 
 void __init init_IRQ(void)
 {
-	ppc_md.init_IRQ();
+	if (ppc_md.init_IRQ)
+		ppc_md.init_IRQ();
 #ifdef CONFIG_PPC64
 	irq_ctx_init();
 #endif
@@ -412,6 +412,12 @@
 static unsigned int irq_virq_count = NR_IRQS;
 static struct irq_host *irq_default_host;
 
+irq_hw_number_t virq_to_hw(unsigned int virq)
+{
+	return irq_map[virq].hwirq;
+}
+EXPORT_SYMBOL_GPL(virq_to_hw);
+
 struct irq_host *irq_alloc_host(unsigned int revmap_type,
 				unsigned int revmap_arg,
 				struct irq_host_ops *ops,
@@ -489,7 +495,7 @@
 	case IRQ_HOST_MAP_LINEAR:
 		rmap = (unsigned int *)(host + 1);
 		for (i = 0; i < revmap_arg; i++)
-			rmap[i] = IRQ_NONE;
+			rmap[i] = NO_IRQ;
 		host->revmap_data.linear.size = revmap_arg;
 		smp_wmb();
 		host->revmap_data.linear.revmap = rmap;
@@ -591,6 +597,49 @@
 	local_irq_restore(flags);
 }
 
+static int irq_setup_virq(struct irq_host *host, unsigned int virq,
+			    irq_hw_number_t hwirq)
+{
+	/* Clear IRQ_NOREQUEST flag */
+	get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
+
+	/* map it */
+	smp_wmb();
+	irq_map[virq].hwirq = hwirq;
+	smp_mb();
+
+	if (host->ops->map(host, virq, hwirq)) {
+		pr_debug("irq: -> mapping failed, freeing\n");
+		irq_free_virt(virq, 1);
+		return -1;
+	}
+
+	return 0;
+}
+
+unsigned int irq_create_direct_mapping(struct irq_host *host)
+{
+	unsigned int virq;
+
+	if (host == NULL)
+		host = irq_default_host;
+
+	BUG_ON(host == NULL);
+	WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
+
+	virq = irq_alloc_virt(host, 1, 0);
+	if (virq == NO_IRQ) {
+		pr_debug("irq: create_direct virq allocation failed\n");
+		return NO_IRQ;
+	}
+
+	pr_debug("irq: create_direct obtained virq %d\n", virq);
+
+	if (irq_setup_virq(host, virq, virq))
+		return NO_IRQ;
+
+	return virq;
+}
 
 unsigned int irq_create_mapping(struct irq_host *host,
 				irq_hw_number_t hwirq)
@@ -614,7 +663,7 @@
 	 * host->ops->map() to update the flags
 	 */
 	virq = irq_find_mapping(host, hwirq);
-	if (virq != IRQ_NONE) {
+	if (virq != NO_IRQ) {
 		if (host->ops->remap)
 			host->ops->remap(host, virq, hwirq);
 		pr_debug("irq: -> existing mapping on virq %d\n", virq);
@@ -639,18 +688,9 @@
 	}
 	pr_debug("irq: -> obtained virq %d\n", virq);
 
-	/* Clear IRQ_NOREQUEST flag */
-	get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
-
-	/* map it */
-	smp_wmb();
-	irq_map[virq].hwirq = hwirq;
-	smp_mb();
-	if (host->ops->map(host, virq, hwirq)) {
-		pr_debug("irq: -> mapping failed, freeing\n");
-		irq_free_virt(virq, 1);
+	if (irq_setup_virq(host, virq, hwirq))
 		return NO_IRQ;
-	}
+
 	return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_mapping);
@@ -741,7 +781,7 @@
 	switch(host->revmap_type) {
 	case IRQ_HOST_MAP_LINEAR:
 		if (hwirq < host->revmap_data.linear.size)
-			host->revmap_data.linear.revmap[hwirq] = IRQ_NONE;
+			host->revmap_data.linear.revmap[hwirq] = NO_IRQ;
 		break;
 	case IRQ_HOST_MAP_TREE:
 		/* Check if radix tree allocated yet */
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
new file mode 100644
index 0000000..f0f49d1
--- /dev/null
+++ b/arch/powerpc/kernel/isa-bridge.c
@@ -0,0 +1,271 @@
+/*
+ * Routines for tracking a legacy ISA bridge
+ *
+ * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ *
+ * Some bits and pieces moved over from pci_64.c
+ *
+ * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+
+unsigned long isa_io_base;	/* NULL if no ISA bus */
+EXPORT_SYMBOL(isa_io_base);
+
+/* Cached ISA bridge dev. */
+static struct device_node *isa_bridge_devnode;
+struct pci_dev *isa_bridge_pcidev;
+EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
+
+#define ISA_SPACE_MASK 0x1
+#define ISA_SPACE_IO 0x1
+
+static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+						unsigned long phb_io_base_phys)
+{
+	/* We should get some saner parsing here and remove these structs */
+	struct pci_address {
+		u32 a_hi;
+		u32 a_mid;
+		u32 a_lo;
+	};
+
+	struct isa_address {
+		u32 a_hi;
+		u32 a_lo;
+	};
+
+	struct isa_range {
+		struct isa_address isa_addr;
+		struct pci_address pci_addr;
+		unsigned int size;
+	};
+
+	const struct isa_range *range;
+	unsigned long pci_addr;
+	unsigned int isa_addr;
+	unsigned int size;
+	int rlen = 0;
+
+	range = of_get_property(isa_node, "ranges", &rlen);
+	if (range == NULL || (rlen < sizeof(struct isa_range)))
+		goto inval_range;
+
+	/* From "ISA Binding to 1275"
+	 * The ranges property is laid out as an array of elements,
+	 * each of which comprises:
+	 *   cells 0 - 1:	an ISA address
+	 *   cells 2 - 4:	a PCI address
+	 *			(size depending on dev->n_addr_cells)
+	 *   cell 5:		the size of the range
+	 */
+	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
+		range++;
+		rlen -= sizeof(struct isa_range);
+		if (rlen < sizeof(struct isa_range))
+			goto inval_range;
+	}
+	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
+		goto inval_range;
+
+	isa_addr = range->isa_addr.a_lo;
+	pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
+		range->pci_addr.a_lo;
+
+	/* Assume these are both zero. Note: We could fix that and
+	 * do a proper parsing instead ... oh well, that will do for
+	 * now as nobody uses fancy mappings for ISA bridges
+	 */
+	if ((pci_addr != 0) || (isa_addr != 0)) {
+		printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+		       __FUNCTION__);
+		return;
+	}
+
+	/* Align size and make sure it's cropped to 64K */
+	size = PAGE_ALIGN(range->size);
+	if (size > 0x10000)
+		size = 0x10000;
+
+	printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+	       "mapping 64k\n");
+
+	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+		     size, _PAGE_NO_CACHE|_PAGE_GUARDED);
+	return;
+
+inval_range:
+	printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+	       "mapping 64k\n");
+	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+		     0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
+}
+
+
+/**
+ * isa_bridge_find_early - Find and map the ISA IO space early before
+ *                         main PCI discovery. This is optionally called by
+ *                         the arch code when adding PCI PHBs to get early
+ *                         access to ISA IO ports
+ */
+void __init isa_bridge_find_early(struct pci_controller *hose)
+{
+	struct device_node *np, *parent = NULL, *tmp;
+
+	/* If we already have an ISA bridge, bail off */
+	if (isa_bridge_devnode != NULL)
+		return;
+
+	/* For each "isa" node in the system. Note : we do a search by
+	 * type and not by name. It might be better to do by name but that's
+	 * what the code used to do and I don't want to break too much at
+	 * once. We can look into changing that separately
+	 */
+	for_each_node_by_type(np, "isa") {
+		/* Look for our hose being a parent */
+		for (parent = of_get_parent(np); parent;) {
+			if (parent == hose->arch_data) {
+				of_node_put(parent);
+				break;
+			}
+			tmp = parent;
+			parent = of_get_parent(parent);
+			of_node_put(tmp);
+		}
+		if (parent != NULL)
+			break;
+	}
+	if (np == NULL)
+		return;
+	isa_bridge_devnode = np;
+
+	/* Now parse the "ranges" property and setup the ISA mapping */
+	pci_process_ISA_OF_ranges(np, hose->io_base_phys);
+
+	/* Set the global ISA io base to indicate we have an ISA bridge */
+	isa_io_base = ISA_IO_BASE;
+
+	pr_debug("ISA bridge (early) is %s\n", np->full_name);
+}
+
+/**
+ * isa_bridge_find_late - Find and map the ISA IO space upon discovery of
+ *                        a new ISA bridge
+ */
+static void __devinit isa_bridge_find_late(struct pci_dev *pdev,
+					   struct device_node *devnode)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+
+	/* Store ISA device node and PCI device */
+	isa_bridge_devnode = of_node_get(devnode);
+	isa_bridge_pcidev = pdev;
+
+	/* Now parse the "ranges" property and setup the ISA mapping */
+	pci_process_ISA_OF_ranges(devnode, hose->io_base_phys);
+
+	/* Set the global ISA io base to indicate we have an ISA bridge */
+	isa_io_base = ISA_IO_BASE;
+
+	pr_debug("ISA bridge (late) is %s on %s\n",
+		 devnode->full_name, pci_name(pdev));
+}
+
+/**
+ * isa_bridge_remove - Remove/unmap an ISA bridge
+ */
+static void isa_bridge_remove(void)
+{
+	pr_debug("ISA bridge removed !\n");
+
+	/* Clear the global ISA io base to indicate that we have no more
+	 * ISA bridge. Note that drivers don't quite handle that, though
+	 * we should probably do something about it. But do we ever really
+	 * have ISA bridges being removed on machines using legacy devices ?
+	 */
+	isa_io_base = ISA_IO_BASE;
+
+	/* Clear references to the bridge */
+	of_node_put(isa_bridge_devnode);
+	isa_bridge_devnode = NULL;
+	isa_bridge_pcidev = NULL;
+
+	/* Unmap the ISA area */
+	__iounmap_at((void *)ISA_IO_BASE, 0x10000);
+}
+
+/**
+ * isa_bridge_notify - Get notified of PCI devices addition/removal
+ */
+static int __devinit isa_bridge_notify(struct notifier_block *nb,
+				       unsigned long action, void *data)
+{
+	struct device *dev = data;
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct device_node *devnode = pci_device_to_OF_node(pdev);
+
+	switch(action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		/* Check if we have an early ISA device, without PCI dev */
+		if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
+		    !isa_bridge_pcidev) {
+			pr_debug("ISA bridge PCI attached: %s\n",
+				 pci_name(pdev));
+			isa_bridge_pcidev = pdev;
+		}
+
+		/* Check if we have no ISA device, and this happens to be one,
+		 * register it as such if it has an OF device
+		 */
+		if (!isa_bridge_devnode && devnode && devnode->type &&
+		    !strcmp(devnode->type, "isa"))
+			isa_bridge_find_late(pdev, devnode);
+
+		return 0;
+	case BUS_NOTIFY_DEL_DEVICE:
+		/* Check if this our existing ISA device */
+		if (pdev == isa_bridge_pcidev ||
+		    (devnode && devnode == isa_bridge_devnode))
+			isa_bridge_remove();
+		return 0;
+	}
+	return 0;
+}
+
+static struct notifier_block isa_bridge_notifier = {
+	.notifier_call = isa_bridge_notify
+};
+
+/**
+ * isa_bridge_init - register to be notified of ISA bridge addition/removal
+ *
+ */
+static int __init isa_bridge_init(void)
+{
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+	bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
+	return 0;
+}
+arch_initcall(isa_bridge_init);
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 98decf8..e708ab7 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -392,7 +392,7 @@
 	mtspr   SPRN_L1CSR0,r3
 	isync
 	blr
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
 	mfspr	r3,SPRN_L1CSR1
 	ori	r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
 	mtspr	SPRN_L1CSR1,r3
@@ -419,7 +419,7 @@
 _GLOBAL(__flush_icache_range)
 BEGIN_FTR_SECTION
 	blr				/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	li	r5,L1_CACHE_BYTES-1
 	andc	r3,r3,r5
 	subf	r4,r3,r4
@@ -514,8 +514,8 @@
  */
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
-	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+	blr
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	rlwinm	r3,r3,0,0,19			/* Get page base address */
 	li	r4,4096/L1_CACHE_BYTES	/* Number of lines in a page */
 	mtctr	r4
@@ -543,7 +543,7 @@
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
 	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	mfmsr	r10
 	rlwinm	r0,r10,0,28,26			/* clear DR */
 	mtmsr	r0
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 519861d..bbb3ba5 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -646,6 +646,19 @@
 	/* turn off mmu */
 	bl	real_mode
 
+	/* copy  0x100 bytes starting at start to 0 */
+	li	r3,0
+	mr	r4,r30		/* start, aka phys mem offset */
+	li	r5,0x100
+	li	r6,0
+	bl	.copy_and_flush	/* (dest, src, copy limit, start offset) */
+1:	/* assume normal blr return */
+
+	/* release other cpus to the new kernel secondary start at 0x60 */
+	mflr	r5
+	li	r6,1
+	stw	r6,kexec_flag-1b(5)
+
 	/* clear out hardware hash page table and tlb */
 	ld	r5,0(r27)		/* deref function descriptor */
 	mtctr	r5
@@ -676,19 +689,6 @@
  *    are the boot cpu ?????
  *    other device tree differences (prop sizes, va vs pa, etc)...
  */
-
-	/* copy  0x100 bytes starting at start to 0 */
-	li	r3,0
-	mr	r4,r30
-	li	r5,0x100
-	li	r6,0
-	bl	.copy_and_flush	/* (dest, src, copy limit, start offset) */
-1:	/* assume normal blr return */
-
-	/* release other cpus to the new kernel secondary start at 0x60 */
-	mflr	r5
-	li	r6,1
-	stw	r6,kexec_flag-1b(5)
 	mr	r3,r25	# my phys cpu
 	mr	r4,r30	# start, aka phys mem offset
 	mtlr	4
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index d501c23..9536ed7 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -427,14 +427,6 @@
 	/* Process "ranges" property */
 	pci_process_bridge_OF_ranges(phb, dev->node, 0);
 
-	/* Setup IO space. We use the non-dynamic version of that code here,
-	 * which doesn't quite support unplugging. Next kernel release will
-	 * have a better fix for this.
-	 * Note also that we don't do ISA, this will also be fixed with a
-	 * more massive rework.
-	 */
-	pci_setup_phb_io(phb, 0);
-
 	/* Init pci_dn data structures */
 	pci_devs_phb_init_dynamic(phb);
 
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
new file mode 100644
index 0000000..faf5ef3
--- /dev/null
+++ b/arch/powerpc/kernel/pci-common.c
@@ -0,0 +1,454 @@
+/*
+ * Contains common pci routines for ALL ppc platform
+ * (based on pci_32.c and pci_64.c)
+ *
+ * Port for PPC64 David Engebretsen, IBM Corp.
+ * Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
+ *
+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
+ *   Rework, based on alpha PCI code.
+ *
+ * Common pmac/prep/chrp pci routines. -- Cort
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/syscalls.h>
+#include <linux/irq.h>
+#include <linux/vmalloc.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/byteorder.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static DEFINE_SPINLOCK(hose_spinlock);
+
+/* XXX kill that some day ... */
+int global_phb_number;		/* Global phb counter */
+
+extern struct list_head hose_list;
+
+/*
+ * pci_controller(phb) initialized common variables.
+ */
+static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
+{
+	memset(hose, 0, sizeof(struct pci_controller));
+
+	spin_lock(&hose_spinlock);
+	hose->global_number = global_phb_number++;
+	list_add_tail(&hose->list_node, &hose_list);
+	spin_unlock(&hose_spinlock);
+}
+
+struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+{
+	struct pci_controller *phb;
+
+	if (mem_init_done)
+		phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+	else
+		phb = alloc_bootmem(sizeof (struct pci_controller));
+	if (phb == NULL)
+		return NULL;
+	pci_setup_pci_controller(phb);
+	phb->arch_data = dev;
+	phb->is_dynamic = mem_init_done;
+#ifdef CONFIG_PPC64
+	if (dev) {
+		int nid = of_node_to_nid(dev);
+
+		if (nid < 0 || !node_online(nid))
+			nid = -1;
+
+		PHB_SET_NODE(phb, nid);
+	}
+#endif
+	return phb;
+}
+
+void pcibios_free_controller(struct pci_controller *phb)
+{
+	spin_lock(&hose_spinlock);
+	list_del(&phb->list_node);
+	spin_unlock(&hose_spinlock);
+
+	if (phb->is_dynamic)
+		kfree(phb);
+}
+
+/*
+ * Return the domain number for this bus.
+ */
+int pci_domain_nr(struct pci_bus *bus)
+{
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+	else {
+		struct pci_controller *hose = pci_bus_to_host(bus);
+
+		return hose->global_number;
+	}
+}
+
+EXPORT_SYMBOL(pci_domain_nr);
+
+#ifdef CONFIG_PPC_OF
+
+/* This routine is meant to be used early during boot, when the
+ * PCI bus numbers have not yet been assigned, and you need to
+ * issue PCI config cycles to an OF device.
+ * It could also be used to "fix" RTAS config cycles if you want
+ * to set pci_assign_all_buses to 1 and still use RTAS for PCI
+ * config cycles.
+ */
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
+{
+	if (!have_of)
+		return NULL;
+	while(node) {
+		struct pci_controller *hose, *tmp;
+		list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+			if (hose->arch_data == node)
+				return hose;
+		node = node->parent;
+	}
+	return NULL;
+}
+
+static ssize_t pci_show_devspec(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pci_dev *pdev;
+	struct device_node *np;
+
+	pdev = to_pci_dev (dev);
+	np = pci_device_to_OF_node(pdev);
+	if (np == NULL || np->full_name == NULL)
+		return 0;
+	return sprintf(buf, "%s", np->full_name);
+}
+static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
+#endif /* CONFIG_PPC_OF */
+
+/* Add sysfs properties */
+void pcibios_add_platform_entries(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PPC_OF
+	device_create_file(&pdev->dev, &dev_attr_devspec);
+#endif /* CONFIG_PPC_OF */
+}
+
+char __init *pcibios_setup(char *str)
+{
+	return str;
+}
+
+/*
+ * Reads the interrupt pin to determine if interrupt is use by card.
+ * If the interrupt is used, then gets the interrupt line from the
+ * openfirmware and sets it in the pci_dev and pci_config line.
+ */
+int pci_read_irq_line(struct pci_dev *pci_dev)
+{
+	struct of_irq oirq;
+	unsigned int virq;
+
+	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
+
+#ifdef DEBUG
+	memset(&oirq, 0xff, sizeof(oirq));
+#endif
+	/* Try to get a mapping from the device-tree */
+	if (of_irq_map_pci(pci_dev, &oirq)) {
+		u8 line, pin;
+
+		/* If that fails, lets fallback to what is in the config
+		 * space and map that through the default controller. We
+		 * also set the type to level low since that's what PCI
+		 * interrupts are. If your platform does differently, then
+		 * either provide a proper interrupt tree or don't use this
+		 * function.
+		 */
+		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
+			return -1;
+		if (pin == 0)
+			return -1;
+		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
+		    line == 0xff) {
+			return -1;
+		}
+		DBG(" -> no map ! Using irq line %d from PCI config\n", line);
+
+		virq = irq_create_mapping(NULL, line);
+		if (virq != NO_IRQ)
+			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+	} else {
+		DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+		    oirq.size, oirq.specifier[0], oirq.specifier[1],
+		    oirq.controller->full_name);
+
+		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+					     oirq.size);
+	}
+	if(virq == NO_IRQ) {
+		DBG(" -> failed to map !\n");
+		return -1;
+	}
+
+	DBG(" -> mapped to linux irq %d\n", virq);
+
+	pci_dev->irq = virq;
+
+	return 0;
+}
+EXPORT_SYMBOL(pci_read_irq_line);
+
+/*
+ * Platform support for /proc/bus/pci/X/Y mmap()s,
+ * modelled on the sparc64 implementation by Dave Miller.
+ *  -- paulus.
+ */
+
+/*
+ * Adjust vm_pgoff of VMA such that it is the physical page offset
+ * corresponding to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap.  They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
+					       resource_size_t *offset,
+					       enum pci_mmap_state mmap_state)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	unsigned long io_offset = 0;
+	int i, res_bit;
+
+	if (hose == 0)
+		return NULL;		/* should never happen */
+
+	/* If memory, add on the PCI bridge address offset */
+	if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
+		*offset += hose->pci_mem_offset;
+#endif
+		res_bit = IORESOURCE_MEM;
+	} else {
+		io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+		*offset += io_offset;
+		res_bit = IORESOURCE_IO;
+	}
+
+	/*
+	 * Check that the offset requested corresponds to one of the
+	 * resources of the device.
+	 */
+	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+		struct resource *rp = &dev->resource[i];
+		int flags = rp->flags;
+
+		/* treat ROM as memory (should be already) */
+		if (i == PCI_ROM_RESOURCE)
+			flags |= IORESOURCE_MEM;
+
+		/* Active and same type? */
+		if ((flags & res_bit) == 0)
+			continue;
+
+		/* In the range of this resource? */
+		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
+			continue;
+
+		/* found it! construct the final physical address */
+		if (mmap_state == pci_mmap_io)
+			*offset += hose->io_base_phys - io_offset;
+		return rp;
+	}
+
+	return NULL;
+}
+
+/*
+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
+				      pgprot_t protection,
+				      enum pci_mmap_state mmap_state,
+				      int write_combine)
+{
+	unsigned long prot = pgprot_val(protection);
+
+	/* Write combine is always 0 on non-memory space mappings. On
+	 * memory space, if the user didn't pass 1, we check for a
+	 * "prefetchable" resource. This is a bit hackish, but we use
+	 * this to workaround the inability of /sysfs to provide a write
+	 * combine bit
+	 */
+	if (mmap_state != pci_mmap_mem)
+		write_combine = 0;
+	else if (write_combine == 0) {
+		if (rp->flags & IORESOURCE_PREFETCH)
+			write_combine = 1;
+	}
+
+	/* XXX would be nice to have a way to ask for write-through */
+	prot |= _PAGE_NO_CACHE;
+	if (write_combine)
+		prot &= ~_PAGE_GUARDED;
+	else
+		prot |= _PAGE_GUARDED;
+
+	return __pgprot(prot);
+}
+
+/*
+ * This one is used by /dev/mem and fbdev who have no clue about the
+ * PCI device, it tries to find the PCI device first and calls the
+ * above routine
+ */
+pgprot_t pci_phys_mem_access_prot(struct file *file,
+				  unsigned long pfn,
+				  unsigned long size,
+				  pgprot_t protection)
+{
+	struct pci_dev *pdev = NULL;
+	struct resource *found = NULL;
+	unsigned long prot = pgprot_val(protection);
+	unsigned long offset = pfn << PAGE_SHIFT;
+	int i;
+
+	if (page_is_ram(pfn))
+		return __pgprot(prot);
+
+	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+
+	for_each_pci_dev(pdev) {
+		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+			struct resource *rp = &pdev->resource[i];
+			int flags = rp->flags;
+
+			/* Active and same type? */
+			if ((flags & IORESOURCE_MEM) == 0)
+				continue;
+			/* In the range of this resource? */
+			if (offset < (rp->start & PAGE_MASK) ||
+			    offset > rp->end)
+				continue;
+			found = rp;
+			break;
+		}
+		if (found)
+			break;
+	}
+	if (found) {
+		if (found->flags & IORESOURCE_PREFETCH)
+			prot &= ~_PAGE_GUARDED;
+		pci_dev_put(pdev);
+	}
+
+	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
+
+	return __pgprot(prot);
+}
+
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture.  The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state, int write_combine)
+{
+	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
+	struct resource *rp;
+	int ret;
+
+	rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
+	if (rp == NULL)
+		return -EINVAL;
+
+	vma->vm_pgoff = offset >> PAGE_SHIFT;
+	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
+						  vma->vm_page_prot,
+						  mmap_state, write_combine);
+
+	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+	return ret;
+}
+
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+			  const struct resource *rsrc,
+			  resource_size_t *start, resource_size_t *end)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	resource_size_t offset = 0;
+
+	if (hose == NULL)
+		return;
+
+	if (rsrc->flags & IORESOURCE_IO)
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+
+	/* We pass a fully fixed up address to userland for MMIO instead of
+	 * a BAR value because X is lame and expects to be able to use that
+	 * to pass to /dev/mem !
+	 *
+	 * That means that we'll have potentially 64 bits values where some
+	 * userland apps only expect 32 (like X itself since it thinks only
+	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+	 * 32 bits CHRPs :-(
+	 *
+	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
+	 * has been fixed (and the fix spread enough), we can re-enable the
+	 * 2 lines below and pass down a BAR value to userland. In that case
+	 * we'll also have to re-enable the matching code in
+	 * __pci_mmap_make_offset().
+	 *
+	 * BenH.
+	 */
+#if 0
+	else if (rsrc->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+#endif
+
+	*start = rsrc->start - offset;
+	*end = rsrc->end - offset;
+}
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index e66064b..0adf077 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -55,8 +55,7 @@
  */
 int pci_assign_all_buses;
 
-struct pci_controller* hose_head;
-struct pci_controller** hose_tail = &hose_head;
+LIST_HEAD(hose_list);
 
 static int pci_bus_count;
 
@@ -573,58 +572,6 @@
 	}
 }
 
-
-int
-pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx=0; idx<6; idx++) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1<<idx)))
-			continue;
-	
-		r = &dev->resource[idx];
-		if (r->flags & IORESOURCE_UNSET) {
-			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (dev->resource[PCI_ROM_RESOURCE].start)
-		cmd |= PCI_COMMAND_MEMORY;
-	if (cmd != old_cmd) {
-		printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
-static int next_controller_index;
-
-struct pci_controller * __init
-pcibios_alloc_controller(void)
-{
-	struct pci_controller *hose;
-
-	hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
-	memset(hose, 0, sizeof(struct pci_controller));
-
-	*hose_tail = hose;
-	hose_tail = &hose->next;
-
-	hose->index = next_controller_index++;
-
-	return hose;
-}
-
 #ifdef CONFIG_PPC_OF
 /*
  * Functions below are used on OpenFirmware machines.
@@ -670,7 +617,7 @@
 pcibios_make_OF_bus_map(void)
 {
 	int i;
-	struct pci_controller* hose;
+	struct pci_controller *hose, *tmp;
 	struct property *map_prop;
 	struct device_node *dn;
 
@@ -687,7 +634,7 @@
 		pci_to_OF_bus_map[i] = 0xff;
 
 	/* For each hose, we begin searching bridges */
-	for(hose=hose_head; hose; hose=hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		struct device_node* node;	
 		node = (struct device_node *)hose->arch_data;
 		if (!node)
@@ -765,7 +712,7 @@
 
 	/* Are we a root bus ? */
 	if (bus->self == NULL || bus->parent == NULL) {
-		struct pci_controller *hose = pci_bus_to_hose(bus->number);
+		struct pci_controller *hose = pci_bus_to_host(bus);
 		if (hose == NULL)
 			return NULL;
 		return of_node_get(hose->arch_data);
@@ -818,27 +765,6 @@
 }
 EXPORT_SYMBOL(pci_device_to_OF_node);
 
-/* This routine is meant to be used early during boot, when the
- * PCI bus numbers have not yet been assigned, and you need to
- * issue PCI config cycles to an OF device.
- * It could also be used to "fix" RTAS config cycles if you want
- * to set pci_assign_all_buses to 1 and still use RTAS for PCI
- * config cycles.
- */
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
-	if (!have_of)
-		return NULL;
-	while(node) {
-		struct pci_controller* hose;
-		for (hose=hose_head;hose;hose=hose->next)
-			if (hose->arch_data == node)
-				return hose;
-		node=node->parent;
-	}
-	return NULL;
-}
-
 static int
 find_OF_pci_device_filter(struct device_node* node, void* data)
 {
@@ -1027,34 +953,12 @@
 	}
 }
 
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pci_dev *pdev;
-	struct device_node *np;
-
-	pdev = to_pci_dev (dev);
-	np = pci_device_to_OF_node(pdev);
-	if (np == NULL || np->full_name == NULL)
-		return 0;
-	return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
 #else /* CONFIG_PPC_OF */
 void pcibios_make_OF_bus_map(void)
 {
 }
 #endif /* CONFIG_PPC_OF */
 
-/* Add sysfs properties */
-void pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-#ifdef CONFIG_PPC_OF
-	device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_OF */
-}
-
-
 #ifdef CONFIG_PPC_PMAC
 /*
  * This set of routines checks for PCI<->PCI bridges that have closed
@@ -1269,14 +1173,14 @@
 static int __init
 pcibios_init(void)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose, *tmp;
 	struct pci_bus *bus;
-	int next_busno;
+	int next_busno = 0;
 
 	printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
-	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		if (pci_assign_all_buses)
 			hose->first_busno = next_busno;
 		hose->last_busno = 0xff;
@@ -1319,12 +1223,6 @@
 
 subsys_initcall(pcibios_init);
 
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
-			     unsigned long start, unsigned long size)
-{
-	return start;
-}
-
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
@@ -1342,7 +1240,7 @@
 		if (!res->flags) {
 			if (io_offset)
 				printk(KERN_ERR "I/O resource not set for host"
-				       " bridge %d\n", hose->index);
+				       " bridge %d\n", hose->global_number);
 			res->start = 0;
 			res->end = IO_SPACE_LIMIT;
 			res->flags = IORESOURCE_IO;
@@ -1356,7 +1254,7 @@
 				if (i > 0)
 					continue;
 				printk(KERN_ERR "Memory resource not set for "
-				       "host bridge %d\n", hose->index);
+				       "host bridge %d\n", hose->global_number);
 				res->start = hose->pci_mem_offset;
 				res->end = ~0U;
 				res->flags = IORESOURCE_MEM;
@@ -1370,7 +1268,7 @@
 		for (i = 0; i < 4; ++i) {
 			if ((res = bus->resource[i]) == NULL)
 				continue;
-			if (!res->flags)
+			if (!res->flags || bus->self->transparent)
 				continue;
 			if (io_offset && (res->flags & IORESOURCE_IO)) {
 				res->start += io_offset;
@@ -1395,11 +1293,6 @@
 	}
 }
 
-char __init *pcibios_setup(char *str)
-{
-	return str;
-}
-
 /* the next one is stolen from the alpha port... */
 void __init
 pcibios_update_irq(struct pci_dev *dev, int irq)
@@ -1408,64 +1301,6 @@
 	/* XXX FIXME - update OF device tree node interrupt property */
 }
 
-#ifdef CONFIG_PPC_MERGE
-/* XXX This is a copy of the ppc64 version. This is temporary until we start
- * merging the 2 PCI layers
- */
-/*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-	struct of_irq oirq;
-	unsigned int virq;
-
-	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
-
-	/* Try to get a mapping from the device-tree */
-	if (of_irq_map_pci(pci_dev, &oirq)) {
-		u8 line, pin;
-
-		/* If that fails, lets fallback to what is in the config
-		 * space and map that through the default controller. We
-		 * also set the type to level low since that's what PCI
-		 * interrupts are. If your platform does differently, then
-		 * either provide a proper interrupt tree or don't use this
-		 * function.
-		 */
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
-			return -1;
-		if (pin == 0)
-			return -1;
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-		    line == 0xff) {
-			return -1;
-		}
-		DBG(" -> no map ! Using irq line %d from PCI config\n", line);
-
-		virq = irq_create_mapping(NULL, line);
-		if (virq != NO_IRQ)
-			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-	} else {
-		DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
-		    oirq.size, oirq.specifier[0], oirq.controller->full_name);
-
-		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-					     oirq.size);
-	}
-	if(virq == NO_IRQ) {
-		DBG(" -> failed to map !\n");
-		return -1;
-	}
-	pci_dev->irq = virq;
-
-	return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-#endif /* CONFIG_PPC_MERGE */
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	u16 cmd, old_cmd;
@@ -1497,281 +1332,17 @@
 	return 0;
 }
 
-struct pci_controller*
+static struct pci_controller*
 pci_bus_to_hose(int bus)
 {
-	struct pci_controller* hose = hose_head;
+	struct pci_controller *hose, *tmp;
 
-	for (; hose; hose = hose->next)
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
 		if (bus >= hose->first_busno && bus <= hose->last_busno)
 			return hose;
 	return NULL;
 }
 
-void __iomem *
-pci_bus_io_base(unsigned int bus)
-{
-	struct pci_controller *hose;
-
-	hose = pci_bus_to_hose(bus);
-	if (!hose)
-		return NULL;
-	return hose->io_base_virt;
-}
-
-unsigned long
-pci_bus_io_base_phys(unsigned int bus)
-{
-	struct pci_controller *hose;
-
-	hose = pci_bus_to_hose(bus);
-	if (!hose)
-		return 0;
-	return hose->io_base_phys;
-}
-
-unsigned long
-pci_bus_mem_base_phys(unsigned int bus)
-{
-	struct pci_controller *hose;
-
-	hose = pci_bus_to_hose(bus);
-	if (!hose)
-		return 0;
-	return hose->pci_mem_offset;
-}
-
-unsigned long
-pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
-{
-	/* Hack alert again ! See comments in chrp_pci.c
-	 */
-	struct pci_controller* hose =
-		(struct pci_controller *)pdev->sysdata;
-	if (hose && res->flags & IORESOURCE_MEM)
-		return res->start - hose->pci_mem_offset;
-	/* We may want to do something with IOs here... */
-	return res->start;
-}
-
-
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-					       resource_size_t *offset,
-					       enum pci_mmap_state mmap_state)
-{
-	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-	unsigned long io_offset = 0;
-	int i, res_bit;
-
-	if (hose == 0)
-		return NULL;		/* should never happen */
-
-	/* If memory, add on the PCI bridge address offset */
-	if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
-		*offset += hose->pci_mem_offset;
-#endif
-		res_bit = IORESOURCE_MEM;
-	} else {
-		io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
-		*offset += io_offset;
-		res_bit = IORESOURCE_IO;
-	}
-
-	/*
-	 * Check that the offset requested corresponds to one of the
-	 * resources of the device.
-	 */
-	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-		struct resource *rp = &dev->resource[i];
-		int flags = rp->flags;
-
-		/* treat ROM as memory (should be already) */
-		if (i == PCI_ROM_RESOURCE)
-			flags |= IORESOURCE_MEM;
-
-		/* Active and same type? */
-		if ((flags & res_bit) == 0)
-			continue;
-
-		/* In the range of this resource? */
-		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
-			continue;
-
-		/* found it! construct the final physical address */
-		if (mmap_state == pci_mmap_io)
-			*offset += hose->io_base_phys - io_offset;
-		return rp;
-	}
-
-	return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
-				      pgprot_t protection,
-				      enum pci_mmap_state mmap_state,
-				      int write_combine)
-{
-	unsigned long prot = pgprot_val(protection);
-
-	/* Write combine is always 0 on non-memory space mappings. On
-	 * memory space, if the user didn't pass 1, we check for a
-	 * "prefetchable" resource. This is a bit hackish, but we use
-	 * this to workaround the inability of /sysfs to provide a write
-	 * combine bit
-	 */
-	if (mmap_state != pci_mmap_mem)
-		write_combine = 0;
-	else if (write_combine == 0) {
-		if (rp->flags & IORESOURCE_PREFETCH)
-			write_combine = 1;
-	}
-
-	/* XXX would be nice to have a way to ask for write-through */
-	prot |= _PAGE_NO_CACHE;
-	if (write_combine)
-		prot &= ~_PAGE_GUARDED;
-	else
-		prot |= _PAGE_GUARDED;
-
-	return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
-				  unsigned long pfn,
-				  unsigned long size,
-				  pgprot_t protection)
-{
-	struct pci_dev *pdev = NULL;
-	struct resource *found = NULL;
-	unsigned long prot = pgprot_val(protection);
-	unsigned long offset = pfn << PAGE_SHIFT;
-	int i;
-
-	if (page_is_ram(pfn))
-		return __pgprot(prot);
-
-	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
-	for_each_pci_dev(pdev) {
-		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-			struct resource *rp = &pdev->resource[i];
-			int flags = rp->flags;
-
-			/* Active and same type? */
-			if ((flags & IORESOURCE_MEM) == 0)
-				continue;
-			/* In the range of this resource? */
-			if (offset < (rp->start & PAGE_MASK) ||
-			    offset > rp->end)
-				continue;
-			found = rp;
-			break;
-		}
-		if (found)
-			break;
-	}
-	if (found) {
-		if (found->flags & IORESOURCE_PREFETCH)
-			prot &= ~_PAGE_GUARDED;
-		pci_dev_put(pdev);
-	}
-
-	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
-	return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture.  The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-			enum pci_mmap_state mmap_state,
-			int write_combine)
-{
-	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
-	struct resource *rp;
-	int ret;
-
-	rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
-	if (rp == NULL)
-		return -EINVAL;
-
-	vma->vm_pgoff = offset >> PAGE_SHIFT;
-	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
-						  vma->vm_page_prot,
-						  mmap_state, write_combine);
-
-	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
-	return ret;
-}
-
-/* Obsolete functions. Should be removed once the symbios driver
- * is fixed
- */
-unsigned long
-phys_to_bus(unsigned long pa)
-{
-	struct pci_controller *hose;
-	int i;
-
-	for (hose = hose_head; hose; hose = hose->next) {
-		for (i = 0; i < 3; ++i) {
-			if (pa >= hose->mem_resources[i].start
-			    && pa <= hose->mem_resources[i].end) {
-				/*
-				 * XXX the hose->pci_mem_offset really
-				 * only applies to mem_resources[0].
-				 * We need a way to store an offset for
-				 * the others.  -- paulus
-				 */
-				if (i == 0)
-					pa -= hose->pci_mem_offset;
-				return pa;
-			}
-		}
-	}
-	/* hmmm, didn't find it */
-	return 0;
-}
-
-unsigned long
-pci_phys_to_bus(unsigned long pa, int busnr)
-{
-	struct pci_controller* hose = pci_bus_to_hose(busnr);
-	if (!hose)
-		return pa;
-	return pa - hose->pci_mem_offset;
-}
-
-unsigned long
-pci_bus_to_phys(unsigned int ba, int busnr)
-{
-	struct pci_controller* hose = pci_bus_to_hose(busnr);
-	if (!hose)
-		return ba;
-	return ba + hose->pci_mem_offset;
-}
-
 /* Provide information on locations of various I/O regions in physical
  * memory.  Do this on a per-card basis so that we choose the right
  * root bridge.
@@ -1814,62 +1385,11 @@
 	return result;
 }
 
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
-			  const struct resource *rsrc,
-			  resource_size_t *start, resource_size_t *end)
-{
-	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-	resource_size_t offset = 0;
-
-	if (hose == NULL)
-		return;
-
-	if (rsrc->flags & IORESOURCE_IO)
-		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
-	/* We pass a fully fixed up address to userland for MMIO instead of
-	 * a BAR value because X is lame and expects to be able to use that
-	 * to pass to /dev/mem !
-	 *
-	 * That means that we'll have potentially 64 bits values where some
-	 * userland apps only expect 32 (like X itself since it thinks only
-	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
-	 * 32 bits CHRPs :-(
-	 *
-	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
-	 * has been fixed (and the fix spread enough), we can re-enable the
-	 * 2 lines below and pass down a BAR value to userland. In that case
-	 * we'll also have to re-enable the matching code in
-	 * __pci_mmap_make_offset().
-	 *
-	 * BenH.
-	 */
-#if 0
-	else if (rsrc->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-#endif
-
-	*start = rsrc->start - offset;
-	*end = rsrc->end - offset;
-}
-
-void __init pci_init_resource(struct resource *res, resource_size_t start,
-			      resource_size_t end, int flags, char *name)
-{
-	res->start = start;
-	res->end = end;
-	res->flags = flags;
-	res->name = name;
-	res->parent = NULL;
-	res->sibling = NULL;
-	res->child = NULL;
-}
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
-	struct pci_controller* hose = hose_head;
+	struct pci_controller *hose, *tmp;
 
-	for (; hose; hose = hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		unsigned int size = hose->io_resource.end -
 			hose->io_resource.start + 1;
 		if (address >= hose->io_base_phys &&
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 249cca2..a97e23a 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <linux/syscalls.h>
 #include <linux/irq.h>
+#include <linux/vmalloc.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -41,35 +42,23 @@
 
 unsigned long pci_probe_only = 1;
 int pci_assign_all_buses = 0;
-static int pci_initial_scan_done;
 
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
-static void phbs_remap_io(void);
 
 /* pci_io_base -- the base address from which io bars are offsets.
  * This is the lowest I/O base address (so bar values are always positive),
  * and it *must* be the start of ISA space if an ISA bus exists because
- * ISA drivers use hard coded offsets.  If no ISA bus exists a dummy
- * page is mapped and isa_io_limit prevents access to it.
+ * ISA drivers use hard coded offsets.  If no ISA bus exists nothing
+ * is mapped on the first 64K of IO space
  */
-unsigned long isa_io_base;	/* NULL if no ISA bus */
-EXPORT_SYMBOL(isa_io_base);
-unsigned long pci_io_base;
+unsigned long pci_io_base = ISA_IO_BASE;
 EXPORT_SYMBOL(pci_io_base);
 
-void iSeries_pcibios_init(void);
-
 LIST_HEAD(hose_list);
 
 static struct dma_mapping_ops *pci_dma_ops;
 
-int global_phb_number;		/* Global phb counter */
-
-/* Cached ISA bridge dev. */
-struct pci_dev *ppc64_isabridge_dev = NULL;
-EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
-
 void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
 {
 	pci_dma_ops = dma_ops;
@@ -100,7 +89,7 @@
 		return;
 
 	if (res->flags & IORESOURCE_IO)
-	        offset = (unsigned long)hose->io_base_virt - pci_io_base;
+	        offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 
 	if (res->flags & IORESOURCE_MEM)
 		offset = hose->pci_mem_offset;
@@ -119,7 +108,7 @@
 		return;
 
 	if (res->flags & IORESOURCE_IO)
-	        offset = (unsigned long)hose->io_base_virt - pci_io_base;
+	        offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 
 	if (res->flags & IORESOURCE_MEM)
 		offset = hose->pci_mem_offset;
@@ -156,7 +145,7 @@
 
 	if (res->flags & IORESOURCE_IO) {
 	        unsigned long offset = (unsigned long)hose->io_base_virt -
-					pci_io_base;
+					_IO_BASE;
 		/* Make sure we start at our min on all hoses */
 		if (start - offset < PCIBIOS_MIN_IO)
 			start = PCIBIOS_MIN_IO + offset;
@@ -180,55 +169,6 @@
 	res->start = start;
 }
 
-static DEFINE_SPINLOCK(hose_spinlock);
-
-/*
- * pci_controller(phb) initialized common variables.
- */
-static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
-{
-	memset(hose, 0, sizeof(struct pci_controller));
-
-	spin_lock(&hose_spinlock);
-	hose->global_number = global_phb_number++;
-	list_add_tail(&hose->list_node, &hose_list);
-	spin_unlock(&hose_spinlock);
-}
-
-struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
-{
-	struct pci_controller *phb;
-
-	if (mem_init_done)
-		phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
-	else
-		phb = alloc_bootmem(sizeof (struct pci_controller));
-	if (phb == NULL)
-		return NULL;
-	pci_setup_pci_controller(phb);
-	phb->arch_data = dev;
-	phb->is_dynamic = mem_init_done;
-	if (dev) {
-		int nid = of_node_to_nid(dev);
-
-		if (nid < 0 || !node_online(nid))
-			nid = -1;
-
-		PHB_SET_NODE(phb, nid);
-	}
-	return phb;
-}
-
-void pcibios_free_controller(struct pci_controller *phb)
-{
-	spin_lock(&hose_spinlock);
-	list_del(&phb->list_node);
-	spin_unlock(&hose_spinlock);
-
-	if (phb->is_dynamic)
-		kfree(phb);
-}
-
 void __devinit pcibios_claim_one_bus(struct pci_bus *b)
 {
 	struct pci_dev *dev;
@@ -291,7 +231,6 @@
 	return flags;
 }
 
-#define GET_64BIT(prop, i)	((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
 
 static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
 {
@@ -310,8 +249,8 @@
 		flags = pci_parse_of_flags(addrs[0]);
 		if (!flags)
 			continue;
-		base = GET_64BIT(addrs, 1);
-		size = GET_64BIT(addrs, 3);
+		base = of_read_number(&addrs[1], 2);
+		size = of_read_number(&addrs[3], 2);
 		if (!size)
 			continue;
 		i = addrs[0] & 0xff;
@@ -367,8 +306,10 @@
 	sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
 		dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
 	dev->class = get_int_prop(node, "class-code", 0);
+	dev->revision = get_int_prop(node, "revision-id", 0);
 
 	DBG("    class: 0x%x\n", dev->class);
+	DBG("    revision: 0x%x\n", dev->revision);
 
 	dev->current_state = 4;		/* unknown power state */
 	dev->error_state = pci_channel_io_normal;
@@ -477,7 +418,7 @@
 	i = 1;
 	for (; len >= 32; len -= 32, ranges += 8) {
 		flags = pci_parse_of_flags(ranges[0]);
-		size = GET_64BIT(ranges, 6);
+		size = of_read_number(&ranges[6], 2);
 		if (flags == 0 || size == 0)
 			continue;
 		if (flags & IORESOURCE_IO) {
@@ -496,7 +437,7 @@
 			res = bus->resource[i];
 			++i;
 		}
-		res->start = GET_64BIT(ranges, 1);
+		res->start = of_read_number(&ranges[1], 2);
 		res->end = res->start + size - 1;
 		res->flags = flags;
 		fixup_resource(res, dev);
@@ -535,10 +476,16 @@
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		pcibios_map_io_space(bus);
+
 	bus->resource[0] = res = &hose->io_resource;
-	if (res->flags && request_resource(&ioport_resource, res))
+	if (res->flags && request_resource(&ioport_resource, res)) {
 		printk(KERN_ERR "Failed to request PCI IO region "
 		       "on PCI domain %04x\n", hose->global_number);
+		DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
+		    res->start, res->end);
+	}
 
 	for (i = 0; i < 3; ++i) {
 		res = &hose->mem_resources[i];
@@ -596,17 +543,6 @@
 	if (ppc_md.pcibios_fixup)
 		ppc_md.pcibios_fixup();
 
-	/* Cache the location of the ISA bridge (if we have one) */
-	ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-	if (ppc64_isabridge_dev != NULL)
-		printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
-
-	if (!firmware_has_feature(FW_FEATURE_ISERIES))
-		/* map in PCI I/O space */
-		phbs_remap_io();
-
-	pci_initial_scan_done = 1;
-
 	printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
 	return 0;
@@ -614,11 +550,6 @@
 
 subsys_initcall(pcibios_init);
 
-char __init *pcibios_setup(char *str)
-{
-	return str;
-}
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	u16 cmd, oldcmd;
@@ -649,22 +580,6 @@
 	return 0;
 }
 
-/*
- * Return the domain number for this bus.
- */
-int pci_domain_nr(struct pci_bus *bus)
-{
-	if (firmware_has_feature(FW_FEATURE_ISERIES))
-		return 0;
-	else {
-		struct pci_controller *hose = pci_bus_to_host(bus);
-
-		return hose->global_number;
-	}
-}
-
-EXPORT_SYMBOL(pci_domain_nr);
-
 /* Decide whether to display the domain number in /proc */
 int pci_proc_domain(struct pci_bus *bus)
 {
@@ -676,281 +591,6 @@
 	}
 }
 
-/*
- * Platform support for /proc/bus/pci/X/Y mmap()s,
- * modelled on the sparc64 implementation by Dave Miller.
- *  -- paulus.
- */
-
-/*
- * Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap.  They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-					       resource_size_t *offset,
-					       enum pci_mmap_state mmap_state)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned long io_offset = 0;
-	int i, res_bit;
-
-	if (hose == 0)
-		return NULL;		/* should never happen */
-
-	/* If memory, add on the PCI bridge address offset */
-	if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
-		*offset += hose->pci_mem_offset;
-#endif
-		res_bit = IORESOURCE_MEM;
-	} else {
-		io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-		*offset += io_offset;
-		res_bit = IORESOURCE_IO;
-	}
-
-	/*
-	 * Check that the offset requested corresponds to one of the
-	 * resources of the device.
-	 */
-	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-		struct resource *rp = &dev->resource[i];
-		int flags = rp->flags;
-
-		/* treat ROM as memory (should be already) */
-		if (i == PCI_ROM_RESOURCE)
-			flags |= IORESOURCE_MEM;
-
-		/* Active and same type? */
-		if ((flags & res_bit) == 0)
-			continue;
-
-		/* In the range of this resource? */
-		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
-			continue;
-
-		/* found it! construct the final physical address */
-		if (mmap_state == pci_mmap_io)
-		       	*offset += hose->io_base_phys - io_offset;
-		return rp;
-	}
-
-	return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
-				      pgprot_t protection,
-				      enum pci_mmap_state mmap_state,
-				      int write_combine)
-{
-	unsigned long prot = pgprot_val(protection);
-
-	/* Write combine is always 0 on non-memory space mappings. On
-	 * memory space, if the user didn't pass 1, we check for a
-	 * "prefetchable" resource. This is a bit hackish, but we use
-	 * this to workaround the inability of /sysfs to provide a write
-	 * combine bit
-	 */
-	if (mmap_state != pci_mmap_mem)
-		write_combine = 0;
-	else if (write_combine == 0) {
-		if (rp->flags & IORESOURCE_PREFETCH)
-			write_combine = 1;
-	}
-
-	/* XXX would be nice to have a way to ask for write-through */
-	prot |= _PAGE_NO_CACHE;
-	if (write_combine)
-		prot &= ~_PAGE_GUARDED;
-	else
-		prot |= _PAGE_GUARDED;
-
-	return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
-				  unsigned long pfn,
-				  unsigned long size,
-				  pgprot_t protection)
-{
-	struct pci_dev *pdev = NULL;
-	struct resource *found = NULL;
-	unsigned long prot = pgprot_val(protection);
-	unsigned long offset = pfn << PAGE_SHIFT;
-	int i;
-
-	if (page_is_ram(pfn))
-		return __pgprot(prot);
-
-	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
-	for_each_pci_dev(pdev) {
-		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-			struct resource *rp = &pdev->resource[i];
-			int flags = rp->flags;
-
-			/* Active and same type? */
-			if ((flags & IORESOURCE_MEM) == 0)
-				continue;
-			/* In the range of this resource? */
-			if (offset < (rp->start & PAGE_MASK) ||
-			    offset > rp->end)
-				continue;
-			found = rp;
-			break;
-		}
-		if (found)
-			break;
-	}
-	if (found) {
-		if (found->flags & IORESOURCE_PREFETCH)
-			prot &= ~_PAGE_GUARDED;
-		pci_dev_put(pdev);
-	}
-
-	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
-	return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture.  The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-			enum pci_mmap_state mmap_state, int write_combine)
-{
-	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
-	struct resource *rp;
-	int ret;
-
-	rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
-	if (rp == NULL)
-		return -EINVAL;
-
-	vma->vm_pgoff = offset >> PAGE_SHIFT;
-	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
-						  vma->vm_page_prot,
-						  mmap_state, write_combine);
-
-	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
-	return ret;
-}
-
-static ssize_t pci_show_devspec(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct pci_dev *pdev;
-	struct device_node *np;
-
-	pdev = to_pci_dev (dev);
-	np = pci_device_to_OF_node(pdev);
-	if (np == NULL || np->full_name == NULL)
-		return 0;
-	return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
-void pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-	device_create_file(&pdev->dev, &dev_attr_devspec);
-}
-
-#define ISA_SPACE_MASK 0x1
-#define ISA_SPACE_IO 0x1
-
-static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
-				      unsigned long phb_io_base_phys,
-				      void __iomem * phb_io_base_virt)
-{
-	/* Remove these asap */
-
-	struct pci_address {
-		u32 a_hi;
-		u32 a_mid;
-		u32 a_lo;
-	};
-
-	struct isa_address {
-		u32 a_hi;
-		u32 a_lo;
-	};
-
-	struct isa_range {
-		struct isa_address isa_addr;
-		struct pci_address pci_addr;
-		unsigned int size;
-	};
-
-	const struct isa_range *range;
-	unsigned long pci_addr;
-	unsigned int isa_addr;
-	unsigned int size;
-	int rlen = 0;
-
-	range = of_get_property(isa_node, "ranges", &rlen);
-	if (range == NULL || (rlen < sizeof(struct isa_range))) {
-		printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
-		       "mapping 64k\n");
-		__ioremap_explicit(phb_io_base_phys,
-				   (unsigned long)phb_io_base_virt,
-				   0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED);
-		return;	
-	}
-	
-	/* From "ISA Binding to 1275"
-	 * The ranges property is laid out as an array of elements,
-	 * each of which comprises:
-	 *   cells 0 - 1:	an ISA address
-	 *   cells 2 - 4:	a PCI address 
-	 *			(size depending on dev->n_addr_cells)
-	 *   cell 5:		the size of the range
-	 */
-	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
-		isa_addr = range->isa_addr.a_lo;
-		pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | 
-			range->pci_addr.a_lo;
-
-		/* Assume these are both zero */
-		if ((pci_addr != 0) || (isa_addr != 0)) {
-			printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
-					__FUNCTION__);
-			return;
-		}
-		
-		size = PAGE_ALIGN(range->size);
-
-		__ioremap_explicit(phb_io_base_phys, 
-				   (unsigned long) phb_io_base_virt, 
-				   size, _PAGE_NO_CACHE | _PAGE_GUARDED);
-	}
-}
-
 void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
 					    struct device_node *dev, int prim)
 {
@@ -1045,155 +685,122 @@
 	}
 }
 
-void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary)
+#ifdef CONFIG_HOTPLUG
+
+int pcibios_unmap_io_space(struct pci_bus *bus)
 {
-	unsigned long size = hose->pci_io_size;
-	unsigned long io_virt_offset;
-	struct resource *res;
-	struct device_node *isa_dn;
+	struct pci_controller *hose;
 
-	if (size == 0)
-		return;
+	WARN_ON(bus == NULL);
 
-	hose->io_base_virt = reserve_phb_iospace(size);
-	DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
-		hose->global_number, hose->io_base_phys,
-		(unsigned long) hose->io_base_virt);
-
-	if (primary) {
-		pci_io_base = (unsigned long)hose->io_base_virt;
-		isa_dn = of_find_node_by_type(NULL, "isa");
-		if (isa_dn) {
-			isa_io_base = pci_io_base;
-			pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
-						hose->io_base_virt);
-			of_node_put(isa_dn);
-		}
-	}
-
-	io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-	res = &hose->io_resource;
-	res->start += io_virt_offset;
-	res->end += io_virt_offset;
-
-	/* If this is called after the initial PCI scan, then we need to
-	 * proceed to IO mappings now
+	/* If this is not a PHB, we only flush the hash table over
+	 * the area mapped by this bridge. We don't play with the PTE
+	 * mappings since we might have to deal with sub-page alignemnts
+	 * so flushing the hash table is the only sane way to make sure
+	 * that no hash entries are covering that removed bridge area
+	 * while still allowing other busses overlapping those pages
 	 */
-	if (pci_initial_scan_done)
-		__ioremap_explicit(hose->io_base_phys,
-				   (unsigned long)hose->io_base_virt,
-				   hose->pci_io_size,
-				   _PAGE_NO_CACHE | _PAGE_GUARDED);
-}
+	if (bus->self) {
+		struct resource *res = bus->resource[0];
 
-void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
-					int primary)
+		DBG("IO unmapping for PCI-PCI bridge %s\n",
+		    pci_name(bus->self));
+
+		__flush_hash_table_range(&init_mm, res->start + _IO_BASE,
+					 res->end - res->start + 1);
+		return 0;
+	}
+
+	/* Get the host bridge */
+	hose = pci_bus_to_host(bus);
+
+	/* Check if we have IOs allocated */
+	if (hose->io_base_alloc == 0)
+		return 0;
+
+	DBG("IO unmapping for PHB %s\n",
+	    ((struct device_node *)hose->arch_data)->full_name);
+	DBG("  alloc=0x%p\n", hose->io_base_alloc);
+
+	/* This is a PHB, we fully unmap the IO area */
+	vunmap(hose->io_base_alloc);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
+
+#endif /* CONFIG_HOTPLUG */
+
+int __devinit pcibios_map_io_space(struct pci_bus *bus)
 {
-	unsigned long size = hose->pci_io_size;
+	struct vm_struct *area;
+	unsigned long phys_page;
+	unsigned long size_page;
 	unsigned long io_virt_offset;
-	struct resource *res;
+	struct pci_controller *hose;
 
-	if (size == 0)
-		return;
+	WARN_ON(bus == NULL);
 
-	hose->io_base_virt = __ioremap(hose->io_base_phys, size,
-					_PAGE_NO_CACHE | _PAGE_GUARDED);
-	DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
-		hose->global_number, hose->io_base_phys,
-		(unsigned long) hose->io_base_virt);
-
-	if (primary)
-		pci_io_base = (unsigned long)hose->io_base_virt;
-
-	io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-	res = &hose->io_resource;
-	res->start += io_virt_offset;
-	res->end += io_virt_offset;
-}
-
-
-static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
-				unsigned long *start_virt, unsigned long *size)
-{
-	struct pci_controller *hose = pci_bus_to_host(bus);
-	struct resource *res;
-
-	if (bus->self)
-		res = bus->resource[0];
-	else
-		/* Root Bus */
-		res = &hose->io_resource;
-
-	if (res->end == 0 && res->start == 0)
-		return 1;
-
-	*start_virt = pci_io_base + res->start;
-	*start_phys = *start_virt + hose->io_base_phys
-		- (unsigned long) hose->io_base_virt;
-
-	if (res->end > res->start)
-		*size = res->end - res->start + 1;
-	else {
-		printk("%s(): unexpected region 0x%lx->0x%lx\n",
-		       __FUNCTION__, res->start, res->end);
-		return 1;
+	/* If this not a PHB, nothing to do, page tables still exist and
+	 * thus HPTEs will be faulted in when needed
+	 */
+	if (bus->self) {
+		DBG("IO mapping for PCI-PCI bridge %s\n",
+		    pci_name(bus->self));
+		DBG("  virt=0x%016lx...0x%016lx\n",
+		    bus->resource[0]->start + _IO_BASE,
+		    bus->resource[0]->end + _IO_BASE);
+		return 0;
 	}
 
+	/* Get the host bridge */
+	hose = pci_bus_to_host(bus);
+	phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
+	size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
+
+	/* Make sure IO area address is clear */
+	hose->io_base_alloc = NULL;
+
+	/* If there's no IO to map on that bus, get away too */
+	if (hose->pci_io_size == 0 || hose->io_base_phys == 0)
+		return 0;
+
+	/* Let's allocate some IO space for that guy. We don't pass
+	 * VM_IOREMAP because we don't care about alignment tricks that
+	 * the core does in that case. Maybe we should due to stupid card
+	 * with incomplete address decoding but I'd rather not deal with
+	 * those outside of the reserved 64K legacy region.
+	 */
+	area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
+	if (area == NULL)
+		return -ENOMEM;
+	hose->io_base_alloc = area->addr;
+	hose->io_base_virt = (void __iomem *)(area->addr +
+					      hose->io_base_phys - phys_page);
+
+	DBG("IO mapping for PHB %s\n",
+	    ((struct device_node *)hose->arch_data)->full_name);
+	DBG("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
+	    hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
+	DBG("  size=0x%016lx (alloc=0x%016lx)\n",
+	    hose->pci_io_size, size_page);
+
+	/* Establish the mapping */
+	if (__ioremap_at(phys_page, area->addr, size_page,
+			 _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
+		return -ENOMEM;
+
+	/* Fixup hose IO resource */
+	io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+	hose->io_resource.start += io_virt_offset;
+	hose->io_resource.end += io_virt_offset;
+
+	DBG("  hose->io_resource=0x%016lx...0x%016lx\n",
+	    hose->io_resource.start, hose->io_resource.end);
+
 	return 0;
 }
-
-int unmap_bus_range(struct pci_bus *bus)
-{
-	unsigned long start_phys;
-	unsigned long start_virt;
-	unsigned long size;
-
-	if (!bus) {
-		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
-		return 1;
-	}
-	
-	if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
-		return 1;
-	if (__iounmap_explicit((void __iomem *) start_virt, size))
-		return 1;
-
-	return 0;
-}
-EXPORT_SYMBOL(unmap_bus_range);
-
-int remap_bus_range(struct pci_bus *bus)
-{
-	unsigned long start_phys;
-	unsigned long start_virt;
-	unsigned long size;
-
-	if (!bus) {
-		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
-		return 1;
-	}
-	
-	
-	if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
-		return 1;
-	if (start_phys == 0)
-		return 1;
-	printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
-	if (__ioremap_explicit(start_phys, start_virt, size,
-			       _PAGE_NO_CACHE | _PAGE_GUARDED))
-		return 1;
-
-	return 0;
-}
-EXPORT_SYMBOL(remap_bus_range);
-
-static void phbs_remap_io(void)
-{
-	struct pci_controller *hose, *tmp;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-		remap_bus_range(hose->bus);
-}
+EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
 static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
 {
@@ -1201,8 +808,7 @@
 	unsigned long offset;
 
 	if (res->flags & IORESOURCE_IO) {
-		offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 		res->start += offset;
 		res->end += offset;
 	} else if (res->flags & IORESOURCE_MEM) {
@@ -1217,9 +823,20 @@
 	/* Update device resources.  */
 	int i;
 
-	for (i = 0; i < PCI_NUM_RESOURCES; i++)
-		if (dev->resource[i].flags)
-			fixup_resource(&dev->resource[i], dev);
+	DBG("%s: Fixup resources:\n", pci_name(dev));
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		struct resource *res = &dev->resource[i];
+		if (!res->flags)
+			continue;
+
+		DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n",
+		    i, res->flags, res->start, res->end);
+
+		fixup_resource(res, dev);
+
+		DBG("       > %08lx:0x%016lx...0x%016lx\n",
+		    res->flags, res->start, res->end);
+	}
 }
 EXPORT_SYMBOL(pcibios_fixup_device_resources);
 
@@ -1289,119 +906,6 @@
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
-/*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the 
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-	struct of_irq oirq;
-	unsigned int virq;
-
-	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
-
-#ifdef DEBUG
-	memset(&oirq, 0xff, sizeof(oirq));
-#endif
-	/* Try to get a mapping from the device-tree */
-	if (of_irq_map_pci(pci_dev, &oirq)) {
-		u8 line, pin;
-
-		/* If that fails, lets fallback to what is in the config
-		 * space and map that through the default controller. We
-		 * also set the type to level low since that's what PCI
-		 * interrupts are. If your platform does differently, then
-		 * either provide a proper interrupt tree or don't use this
-		 * function.
-		 */
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
-			return -1;
-		if (pin == 0)
-			return -1;
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-		    line == 0xff) {
-			return -1;
-		}
-		DBG(" -> no map ! Using irq line %d from PCI config\n", line);
-
-		virq = irq_create_mapping(NULL, line);
-		if (virq != NO_IRQ)
-			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-	} else {
-		DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
-		    oirq.size, oirq.specifier[0], oirq.specifier[1],
-		    oirq.controller->full_name);
-
-		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-					     oirq.size);
-	}
-	if(virq == NO_IRQ) {
-		DBG(" -> failed to map !\n");
-		return -1;
-	}
-
-	DBG(" -> mapped to linux irq %d\n", virq);
-
-	pci_dev->irq = virq;
-
-	return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
-			  const struct resource *rsrc,
-			  resource_size_t *start, resource_size_t *end)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	resource_size_t offset = 0;
-
-	if (hose == NULL)
-		return;
-
-	if (rsrc->flags & IORESOURCE_IO)
-		offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
-	/* We pass a fully fixed up address to userland for MMIO instead of
-	 * a BAR value because X is lame and expects to be able to use that
-	 * to pass to /dev/mem !
-	 *
-	 * That means that we'll have potentially 64 bits values where some
-	 * userland apps only expect 32 (like X itself since it thinks only
-	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on
-	 * 32 bits CHRPs :-(
-	 *
-	 * Hopefully, the sysfs insterface is immune to that gunk. Once X
-	 * has been fixed (and the fix spread enough), we can re-enable the
-	 * 2 lines below and pass down a BAR value to userland. In that case
-	 * we'll also have to re-enable the matching code in
-	 * __pci_mmap_make_offset().
-	 *
-	 * BenH.
-	 */
-#if 0
-	else if (rsrc->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-#endif
-
-	*start = rsrc->start - offset;
-	*end = rsrc->end - offset;
-}
-
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
-	if (!have_of)
-		return NULL;
-	while(node) {
-		struct pci_controller *hose, *tmp;
-		list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-			if (hose->arch_data == node)
-				return hose;
-		node = node->parent;
-	}
-	return NULL;
-}
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
 	struct pci_controller *hose, *tmp;
@@ -1410,7 +914,7 @@
 		if (address >= hose->io_base_phys &&
 		    address < (hose->io_base_phys + hose->pci_io_size)) {
 			unsigned long base =
-				(unsigned long)hose->io_base_virt - pci_io_base;
+				(unsigned long)hose->io_base_virt - _IO_BASE;
 			return base + (address - hose->io_base_phys);
 		}
 	}
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c
index 24d7b7c..ea04e0a 100644
--- a/arch/powerpc/kernel/pmc.c
+++ b/arch/powerpc/kernel/pmc.c
@@ -20,8 +20,8 @@
 #include <asm/cputable.h>
 #include <asm/pmc.h>
 
-#ifndef MMCR0_PMA0
-#define MMCR0_PMA0	0
+#ifndef MMCR0_PMAO
+#define MMCR0_PMAO	0
 #endif
 
 static void dummy_perf(struct pt_regs *regs)
@@ -30,7 +30,7 @@
 	mtpmr(PMRN_PMGC0, mfpmr(PMRN_PMGC0) & ~PMGC0_PMIE);
 #elif defined(CONFIG_PPC64) || defined(CONFIG_6xx)
 	if (cur_cpu_spec->pmc_type == PPC_PMC_IBM)
-		mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~(MMCR0_PMXE|MMCR0_PMA0));
+		mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~(MMCR0_PMXE|MMCR0_PMAO));
 #else
 	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_PMXE);
 #endif
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index c96fa9b..a20f195 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -67,7 +67,6 @@
 EXPORT_SYMBOL(DMA_MODE_READ);
 EXPORT_SYMBOL(DMA_MODE_WRITE);
 
-EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(transfer_to_handler);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(machine_check_exception);
@@ -106,10 +105,6 @@
 EXPORT_SYMBOL(pci_dram_offset);
 EXPORT_SYMBOL(pci_alloc_consistent);
 EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pci_bus_io_base);
-EXPORT_SYMBOL(pci_bus_io_base_phys);
-EXPORT_SYMBOL(pci_bus_mem_base_phys);
-EXPORT_SYMBOL(pci_bus_to_hose);
 #endif /* CONFIG_PCI */
 
 EXPORT_SYMBOL(start_thread);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 6e2f035..84f000a 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -219,22 +219,26 @@
 }
 #endif /* CONFIG_SMP */
 
-#ifdef CONFIG_PPC_MERGE		/* XXX for now */
 int set_dabr(unsigned long dabr)
 {
+#ifdef CONFIG_PPC_MERGE		/* XXX for now */
 	if (ppc_md.set_dabr)
 		return ppc_md.set_dabr(dabr);
+#endif
 
+	/* XXX should we have a CPU_FTR_HAS_DABR ? */
+#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
 	mtspr(SPRN_DABR, dabr);
+#endif
 	return 0;
 }
-#endif
 
 #ifdef CONFIG_PPC64
 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
-static DEFINE_PER_CPU(unsigned long, current_dabr);
 #endif
 
+static DEFINE_PER_CPU(unsigned long, current_dabr);
+
 struct task_struct *__switch_to(struct task_struct *prev,
 	struct task_struct *new)
 {
@@ -299,12 +303,10 @@
 
 #endif /* CONFIG_SMP */
 
-#ifdef CONFIG_PPC64	/* for now */
 	if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
 		set_dabr(new->thread.dabr);
 		__get_cpu_var(current_dabr) = new->thread.dabr;
 	}
-#endif /* CONFIG_PPC64 */
 
 	new_thread = &new->thread;
 	old_thread = &current->thread;
@@ -473,12 +475,10 @@
 
 	discard_lazy_cpu_state();
 
-#ifdef CONFIG_PPC64	/* for now */
 	if (current->thread.dabr) {
 		current->thread.dabr = 0;
 		set_dabr(0);
 	}
-#endif
 }
 
 void
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 066a6a7..37ff99b 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -52,6 +52,7 @@
 #include <asm/pSeries_reconfig.h>
 #include <asm/pci-bridge.h>
 #include <asm/kexec.h>
+#include <asm/system.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) printk(KERN_ERR fmt)
@@ -1005,7 +1006,7 @@
 
 void __init early_init_devtree(void *params)
 {
-	DBG(" -> early_init_devtree()\n");
+	DBG(" -> early_init_devtree(%p)\n", params);
 
 	/* Setup flat device-tree pointer */
 	initial_boot_params = params;
@@ -1055,8 +1056,6 @@
 	DBG(" <- early_init_devtree()\n");
 }
 
-#undef printk
-
 int of_n_addr_cells(struct device_node* np)
 {
 	const int *ip;
@@ -1171,11 +1170,12 @@
 
 /**
  *	of_find_node_by_type - Find a node by its "device_type" property
- *	@from:	The node to start searching from or NULL, the node
- *		you pass will not be searched, only the next one
- *		will; typically, you pass what the previous call
- *		returned. of_node_put() will be called on it
- *	@name:	The type string to match against
+ *	@from:	The node to start searching from, or NULL to start searching
+ *		the entire device tree. The node you pass will not be
+ *		searched, only the next one will; typically, you pass
+ *		what the previous call returned. of_node_put() will be
+ *		called on from for you.
+ *	@type:	The type string to match against
  *
  *	Returns a node pointer with refcount incremented, use
  *	of_node_put() on it when done.
@@ -1374,8 +1374,17 @@
 	struct device_node *node = kref_to_device_node(kref);
 	struct property *prop = node->properties;
 
-	if (!OF_IS_DYNAMIC(node))
+	/* We should never be releasing nodes that haven't been detached. */
+	if (!of_node_check_flag(node, OF_DETACHED)) {
+		printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
+		dump_stack();
+		kref_init(&node->kref);
 		return;
+	}
+
+	if (!of_node_check_flag(node, OF_DYNAMIC))
+		return;
+
 	while (prop) {
 		struct property *next = prop->next;
 		kfree(prop->name);
@@ -1431,6 +1440,8 @@
 	write_lock(&devtree_lock);
 
 	parent = np->parent;
+	if (!parent)
+		goto out_unlock;
 
 	if (allnodes == np)
 		allnodes = np->allnext;
@@ -1454,6 +1465,9 @@
 		prevsib->sibling = np->sibling;
 	}
 
+	of_node_set_flag(np, OF_DETACHED);
+
+out_unlock:
 	write_unlock(&devtree_lock);
 }
 
@@ -1715,22 +1729,18 @@
 }
 EXPORT_SYMBOL(of_get_cpu_node);
 
-#ifdef DEBUG
+#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
 static struct debugfs_blob_wrapper flat_dt_blob;
 
 static int __init export_flat_device_tree(void)
 {
 	struct dentry *d;
 
-	d = debugfs_create_dir("powerpc", NULL);
-	if (!d)
-		return 1;
-
 	flat_dt_blob.data = initial_boot_params;
 	flat_dt_blob.size = initial_boot_params->totalsize;
 
 	d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
-				d, &flat_dt_blob);
+				powerpc_debugfs_root, &flat_dt_blob);
 	if (!d)
 		return 1;
 
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index d6047c4..a1d582e 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -635,6 +635,7 @@
 /* ibm,dynamic-reconfiguration-memory property supported */
 #define OV5_DRCONF_MEMORY	0x20
 #define OV5_LARGE_PAGES		0x10	/* large pages supported */
+#define OV5_DONATE_DEDICATE_CPU 0x02	/* donate dedicated CPU support */
 /* PCIe/MSI support.  Without MSI full PCIe is not supported */
 #ifdef CONFIG_PCI_MSI
 #define OV5_MSI			0x01	/* PCIe/MSI support */
@@ -685,7 +686,8 @@
 	/* option vector 5: PAPR/OF options */
 	3 - 2,				/* length */
 	0,				/* don't ignore, don't halt */
-	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
+	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
+	OV5_DONATE_DEDICATE_CPU | OV5_MSI,
 };
 
 /* Old method - ELF header with PT_NOTE sections */
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h
deleted file mode 100644
index 8797ae7..0000000
--- a/arch/powerpc/kernel/ptrace-common.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- *    Copyright (c) 2002 Stephen Rothwell, IBM Coproration
- *    Extracted from ptrace.c and ptrace32.c
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file README.legal in the main directory of
- * this archive for more details.
- */
-
-#ifndef _PPC64_PTRACE_COMMON_H
-#define _PPC64_PTRACE_COMMON_H
-
-#include <asm/system.h>
-
-/*
- * Set of msr bits that gdb can change on behalf of a process.
- */
-#define MSR_DEBUGCHANGE	(MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
-
-/*
- * Get contents of register REGNO in task TASK.
- */
-static inline unsigned long get_reg(struct task_struct *task, int regno)
-{
-	unsigned long tmp = 0;
-
-	/*
-	 * Put the correct FP bits in, they might be wrong as a result
-	 * of our lazy FP restore.
-	 */
-	if (regno == PT_MSR) {
-		tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
-		tmp |= task->thread.fpexc_mode;
-	} else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
-		tmp = ((unsigned long *)task->thread.regs)[regno];
-	}
-
-	return tmp;
-}
-
-/*
- * Write contents of register REGNO in task TASK.
- */
-static inline int put_reg(struct task_struct *task, int regno,
-			  unsigned long data)
-{
-	if (regno < PT_SOFTE) {
-		if (regno == PT_MSR)
-			data = (data & MSR_DEBUGCHANGE)
-				| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
-		((unsigned long *)task->thread.regs)[regno] = data;
-		return 0;
-	}
-	return -EIO;
-}
-
-static inline void set_single_step(struct task_struct *task)
-{
-	struct pt_regs *regs = task->thread.regs;
-	if (regs != NULL)
-		regs->msr |= MSR_SE;
-	set_tsk_thread_flag(task, TIF_SINGLESTEP);
-}
-
-static inline void clear_single_step(struct task_struct *task)
-{
-	struct pt_regs *regs = task->thread.regs;
-	if (regs != NULL)
-		regs->msr &= ~MSR_SE;
-	clear_tsk_thread_flag(task, TIF_SINGLESTEP);
-}
-
-#ifdef CONFIG_ALTIVEC
-/*
- * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
- * The transfer totals 34 quadword.  Quadwords 0-31 contain the
- * corresponding vector registers.  Quadword 32 contains the vscr as the
- * last word (offset 12) within that quadword.  Quadword 33 contains the
- * vrsave as the first word (offset 0) within the quadword.
- *
- * This definition of the VMX state is compatible with the current PPC32
- * ptrace interface.  This allows signal handling and ptrace to use the
- * same structures.  This also simplifies the implementation of a bi-arch
- * (combined (32- and 64-bit) gdb.
- */
-
-/*
- * Get contents of AltiVec register state in task TASK
- */
-static inline int get_vrregs(unsigned long __user *data,
-			     struct task_struct *task)
-{
-	unsigned long regsize;
-
-	/* copy AltiVec registers VR[0] .. VR[31] */
-	regsize = 32 * sizeof(vector128);
-	if (copy_to_user(data, task->thread.vr, regsize))
-		return -EFAULT;
-	data += (regsize / sizeof(unsigned long));
-
-	/* copy VSCR */
-	regsize = 1 * sizeof(vector128);
-	if (copy_to_user(data, &task->thread.vscr, regsize))
-		return -EFAULT;
-	data += (regsize / sizeof(unsigned long));
-
-	/* copy VRSAVE */
-	if (put_user(task->thread.vrsave, (u32 __user *)data))
-		return -EFAULT;
-
-	return 0;
-}
-
-/*
- * Write contents of AltiVec register state into task TASK.
- */
-static inline int set_vrregs(struct task_struct *task,
-			     unsigned long __user *data)
-{
-	unsigned long regsize;
-
-	/* copy AltiVec registers VR[0] .. VR[31] */
-	regsize = 32 * sizeof(vector128);
-	if (copy_from_user(task->thread.vr, data, regsize))
-		return -EFAULT;
-	data += (regsize / sizeof(unsigned long));
-
-	/* copy VSCR */
-	regsize = 1 * sizeof(vector128);
-	if (copy_from_user(&task->thread.vscr, data, regsize))
-		return -EFAULT;
-	data += (regsize / sizeof(unsigned long));
-
-	/* copy VRSAVE */
-	if (get_user(task->thread.vrsave, (u32 __user *)data))
-		return -EFAULT;
-
-	return 0;
-}
-#endif
-
-static inline int ptrace_set_debugreg(struct task_struct *task,
-				      unsigned long addr, unsigned long data)
-{
-	/* We only support one DABR and no IABRS at the moment */
-	if (addr > 0)
-		return -EINVAL;
-
-	/* The bottom 3 bits are flags */
-	if ((data & ~0x7UL) >= TASK_SIZE)
-		return -EIO;
-
-	/* Ensure translation is on */
-	if (data && !(data & DABR_TRANSLATION))
-		return -EIO;
-
-	task->thread.dabr = data;
-	return 0;
-}
-
-#endif /* _PPC64_PTRACE_COMMON_H */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index f4f391c..8a177bd 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -35,11 +35,11 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_PPC64
-#include "ptrace-common.h"
-#endif
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
 
-#ifdef CONFIG_PPC32
 /*
  * Set of msr bits that gdb can change on behalf of a process.
  */
@@ -48,65 +48,117 @@
 #else
 #define MSR_DEBUGCHANGE	(MSR_SE | MSR_BE)
 #endif
-#endif /* CONFIG_PPC32 */
 
 /*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
+ * Max register writeable via put_reg
  */
-
 #ifdef CONFIG_PPC32
+#define PT_MAX_PUT_REG	PT_MQ
+#else
+#define PT_MAX_PUT_REG	PT_CCR
+#endif
+
 /*
  * Get contents of register REGNO in task TASK.
  */
-static inline unsigned long get_reg(struct task_struct *task, int regno)
+unsigned long ptrace_get_reg(struct task_struct *task, int regno)
 {
-	if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
-	    && task->thread.regs != NULL)
+	unsigned long tmp = 0;
+
+	if (task->thread.regs == NULL)
+		return -EIO;
+
+	if (regno == PT_MSR) {
+		tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
+		return tmp | task->thread.fpexc_mode;
+	}
+
+	if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
 		return ((unsigned long *)task->thread.regs)[regno];
-	return (0);
+
+	return -EIO;
 }
 
 /*
  * Write contents of register REGNO in task TASK.
  */
-static inline int put_reg(struct task_struct *task, int regno,
-			  unsigned long data)
+int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
 {
-	if (regno <= PT_MQ && task->thread.regs != NULL) {
+	if (task->thread.regs == NULL)
+		return -EIO;
+
+	if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
 		if (regno == PT_MSR)
 			data = (data & MSR_DEBUGCHANGE)
 				| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
+		/* We prevent mucking around with the reserved area of trap
+		 * which are used internally by the kernel
+		 */
+		if (regno == PT_TRAP)
+			data &= 0xfff0;
 		((unsigned long *)task->thread.regs)[regno] = data;
 		return 0;
 	}
 	return -EIO;
 }
 
+
+static int get_fpregs(void __user *data, struct task_struct *task,
+		      int has_fpscr)
+{
+	unsigned int count = has_fpscr ? 33 : 32;
+
+	if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_fpregs(void __user *data, struct task_struct *task,
+		      int has_fpscr)
+{
+	unsigned int count = has_fpscr ? 33 : 32;
+
+	if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
+		return -EFAULT;
+	return 0;
+}
+
+
 #ifdef CONFIG_ALTIVEC
 /*
+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+ * The transfer totals 34 quadword.  Quadwords 0-31 contain the
+ * corresponding vector registers.  Quadword 32 contains the vscr as the
+ * last word (offset 12) within that quadword.  Quadword 33 contains the
+ * vrsave as the first word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface.  This allows signal handling and ptrace to use the
+ * same structures.  This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ */
+
+/*
  * Get contents of AltiVec register state in task TASK
  */
-static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
+static int get_vrregs(unsigned long __user *data, struct task_struct *task)
 {
-	int i, j;
-
-	if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
-		return -EFAULT;
+	unsigned long regsize;
 
 	/* copy AltiVec registers VR[0] .. VR[31] */
-	for (i = 0; i < 32; i++)
-		for (j = 0; j < 4; j++, data++)
-			if (__put_user(task->thread.vr[i].u[j], data))
-				return -EFAULT;
+	regsize = 32 * sizeof(vector128);
+	if (copy_to_user(data, task->thread.vr, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
 
 	/* copy VSCR */
-	for (i = 0; i < 4; i++, data++)
-		if (__put_user(task->thread.vscr.u[i], data))
-			return -EFAULT;
+	regsize = 1 * sizeof(vector128);
+	if (copy_to_user(data, &task->thread.vscr, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
 
-        /* copy VRSAVE */
-	if (__put_user(task->thread.vrsave, data))
+	/* copy VRSAVE */
+	if (put_user(task->thread.vrsave, (u32 __user *)data))
 		return -EFAULT;
 
 	return 0;
@@ -115,31 +167,29 @@
 /*
  * Write contents of AltiVec register state into task TASK.
  */
-static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
+static int set_vrregs(struct task_struct *task, unsigned long __user *data)
 {
-	int i, j;
-
-	if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
-		return -EFAULT;
+	unsigned long regsize;
 
 	/* copy AltiVec registers VR[0] .. VR[31] */
-	for (i = 0; i < 32; i++)
-		for (j = 0; j < 4; j++, data++)
-			if (__get_user(task->thread.vr[i].u[j], data))
-				return -EFAULT;
+	regsize = 32 * sizeof(vector128);
+	if (copy_from_user(task->thread.vr, data, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
 
 	/* copy VSCR */
-	for (i = 0; i < 4; i++, data++)
-		if (__get_user(task->thread.vscr.u[i], data))
-			return -EFAULT;
+	regsize = 1 * sizeof(vector128);
+	if (copy_from_user(&task->thread.vscr, data, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
 
 	/* copy VRSAVE */
-	if (__get_user(task->thread.vrsave, data))
+	if (get_user(task->thread.vrsave, (u32 __user *)data))
 		return -EFAULT;
 
 	return 0;
 }
-#endif
+#endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_SPE
 
@@ -156,7 +206,7 @@
 /*
  * Get contents of SPE register state in task TASK.
  */
-static inline int get_evrregs(unsigned long *data, struct task_struct *task)
+static int get_evrregs(unsigned long *data, struct task_struct *task)
 {
 	int i;
 
@@ -182,7 +232,7 @@
 /*
  * Write contents of SPE register state into task TASK.
  */
-static inline int set_evrregs(struct task_struct *task, unsigned long *data)
+static int set_evrregs(struct task_struct *task, unsigned long *data)
 {
 	int i;
 
@@ -205,8 +255,8 @@
 }
 #endif /* CONFIG_SPE */
 
-static inline void
-set_single_step(struct task_struct *task)
+
+static void set_single_step(struct task_struct *task)
 {
 	struct pt_regs *regs = task->thread.regs;
 
@@ -218,10 +268,10 @@
 		regs->msr |= MSR_SE;
 #endif
 	}
+	set_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
 
-static inline void
-clear_single_step(struct task_struct *task)
+static void clear_single_step(struct task_struct *task)
 {
 	struct pt_regs *regs = task->thread.regs;
 
@@ -233,8 +283,27 @@
 		regs->msr &= ~MSR_SE;
 #endif
 	}
+	clear_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
-#endif /* CONFIG_PPC32 */
+
+static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
+			       unsigned long data)
+{
+	/* We only support one DABR and no IABRS at the moment */
+	if (addr > 0)
+		return -EINVAL;
+
+	/* The bottom 3 bits are flags */
+	if ((data & ~0x7UL) >= TASK_SIZE)
+		return -EIO;
+
+	/* Ensure translation is on */
+	if (data && !(data & DABR_TRANSLATION))
+		return -EIO;
+
+	task->thread.dabr = data;
+	return 0;
+}
 
 /*
  * Called by kernel/ptrace.c when detaching..
@@ -247,6 +316,62 @@
 	clear_single_step(child);
 }
 
+/*
+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+ * we mark them as obsolete now, they will be removed in a future version
+ */
+static long arch_ptrace_old(struct task_struct *child, long request, long addr,
+			    long data)
+{
+	int ret = -EPERM;
+
+	switch(request) {
+	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+		unsigned long __user *tmp = (unsigned long __user *)addr;
+
+		for (i = 0; i < 32; i++) {
+			ret = put_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
+		break;
+	}
+
+	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+		unsigned long __user *tmp = (unsigned long __user *)addr;
+
+		for (i = 0; i < 32; i++) {
+			ret = get_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
+		break;
+	}
+
+	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
+		flush_fp_to_thread(child);
+		ret = get_fpregs((void __user *)addr, child, 0);
+		break;
+	}
+
+	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
+		flush_fp_to_thread(child);
+		ret = set_fpregs((void __user *)addr, child, 0);
+		break;
+	}
+
+	}
+	return ret;
+}
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
 	int ret = -EPERM;
@@ -254,17 +379,9 @@
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
-	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp,(unsigned long __user *) data);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -282,11 +399,9 @@
 #endif
 			break;
 
-#ifdef CONFIG_PPC32
 		CHECK_FULL_REGS(child->thread.regs);
-#endif
 		if (index < PT_FPR0) {
-			tmp = get_reg(child, (int) index);
+			tmp = ptrace_get_reg(child, (int) index);
 		} else {
 			flush_fp_to_thread(child);
 			tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
@@ -298,11 +413,7 @@
 	/* If I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1)
-				== sizeof(data))
-			break;
-		ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	/* write the word at location addr in the USER area */
@@ -321,13 +432,9 @@
 #endif
 			break;
 
-#ifdef CONFIG_PPC32
 		CHECK_FULL_REGS(child->thread.regs);
-#endif
-		if (index == PT_ORIG_R3)
-			break;
 		if (index < PT_FPR0) {
-			ret = put_reg(child, index, data);
+			ret = ptrace_put_reg(child, index, data);
 		} else {
 			flush_fp_to_thread(child);
 			((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
@@ -382,7 +489,6 @@
 		break;
 	}
 
-#ifdef CONFIG_PPC64
 	case PTRACE_GET_DEBUGREG: {
 		ret = -EINVAL;
 		/* We only support one DABR and no IABRS at the moment */
@@ -396,73 +502,61 @@
 	case PTRACE_SET_DEBUGREG:
 		ret = ptrace_set_debugreg(child, addr, data);
 		break;
-#endif
 
 	case PTRACE_DETACH:
 		ret = ptrace_detach(child, data);
 		break;
 
-	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
-		int i;
-		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-		unsigned long __user *tmp = (unsigned long __user *)addr;
-
-		for (i = 0; i < 32; i++) {
-			ret = put_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
+#ifdef CONFIG_PPC64
+	case PTRACE_GETREGS64:
+#endif
+	case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+		int ui;
+	  	if (!access_ok(VERIFY_WRITE, (void __user *)data,
+			       sizeof(struct pt_regs))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+			ret |= __put_user(ptrace_get_reg(child, ui),
+					  (unsigned long __user *) data);
+			data += sizeof(long);
 		}
 		break;
 	}
 
-	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
-		int i;
-		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-		unsigned long __user *tmp = (unsigned long __user *)addr;
-
-		for (i = 0; i < 32; i++) {
-			ret = get_user(*reg, tmp);
+#ifdef CONFIG_PPC64
+	case PTRACE_SETREGS64:
+#endif
+	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+		unsigned long tmp;
+		int ui;
+	  	if (!access_ok(VERIFY_READ, (void __user *)data,
+			       sizeof(struct pt_regs))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+			ret = __get_user(tmp, (unsigned long __user *) data);
 			if (ret)
 				break;
-			reg++;
-			tmp++;
+			ptrace_put_reg(child, ui, tmp);
+			data += sizeof(long);
 		}
 		break;
 	}
 
-	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
-		int i;
-		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-		unsigned long __user *tmp = (unsigned long __user *)addr;
-
+	case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
 		flush_fp_to_thread(child);
-
-		for (i = 0; i < 32; i++) {
-			ret = put_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
-		}
+		ret = get_fpregs((void __user *)data, child, 1);
 		break;
 	}
 
-	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
-		int i;
-		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-		unsigned long __user *tmp = (unsigned long __user *)addr;
-
+	case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
 		flush_fp_to_thread(child);
-
-		for (i = 0; i < 32; i++) {
-			ret = get_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
-		}
+		ret = set_fpregs((void __user *)data, child, 1);
 		break;
 	}
 
@@ -497,11 +591,18 @@
 		break;
 #endif
 
+	/* Old reverse args ptrace callss */
+	case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+	case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+	case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
+	case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
+		ret = arch_ptrace_old(child, request, addr, data);
+		break;
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-
 	return ret;
 }
 
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 9b9a230..9e6baea 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -33,13 +33,55 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
-#include "ptrace-common.h"
-
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
  */
 
+/*
+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+ * we mark them as obsolete now, they will be removed in a future version
+ */
+static long compat_ptrace_old(struct task_struct *child, long request,
+			      long addr, long data)
+{
+	int ret = -EPERM;
+
+	switch(request) {
+	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+		unsigned int __user *tmp = (unsigned int __user *)addr;
+
+		for (i = 0; i < 32; i++) {
+			ret = put_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
+		break;
+	}
+
+	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+		int i;
+		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+		unsigned int __user *tmp = (unsigned int __user *)addr;
+
+		for (i = 0; i < 32; i++) {
+			ret = get_user(*reg, tmp);
+			if (ret)
+				break;
+			reg++;
+			tmp++;
+		}
+		break;
+	}
+
+	}
+	return ret;
+}
+
 long compat_sys_ptrace(int request, int pid, unsigned long addr,
 		       unsigned long data)
 {
@@ -123,7 +165,7 @@
 			break;
 
 		if (index < PT_FPR0) {
-			tmp = get_reg(child, index);
+			tmp = ptrace_get_reg(child, index);
 		} else {
 			flush_fp_to_thread(child);
 			/*
@@ -162,7 +204,9 @@
 		else
 			part = 0;  /* want the 1st half of the register (left-most). */
 
-		/* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
+		/* Validate the input - check to see if address is on the wrong boundary
+		 * or beyond the end of the user area
+		 */
 		if ((addr & 3) || numReg > PT_FPSCR)
 			break;
 
@@ -170,7 +214,7 @@
 			flush_fp_to_thread(child);
 			tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
 		} else { /* register within PT_REGS struct */
-			tmp = get_reg(child, numReg);
+			tmp = ptrace_get_reg(child, numReg);
 		} 
 		reg32bits = ((u32*)&tmp)[part];
 		ret = put_user(reg32bits, (u32 __user *)data);
@@ -226,10 +270,8 @@
 		if ((addr & 3) || (index > PT_FPSCR32))
 			break;
 
-		if (index == PT_ORIG_R3)
-			break;
 		if (index < PT_FPR0) {
-			ret = put_reg(child, index, data);
+			ret = ptrace_put_reg(child, index, data);
 		} else {
 			flush_fp_to_thread(child);
 			/*
@@ -258,70 +300,25 @@
 		/* Determine which register the user wants */
 		index = (u64)addr >> 2;
 		numReg = index / 2;
+
 		/*
 		 * Validate the input - check to see if address is on the
 		 * wrong boundary or beyond the end of the user area
 		 */
 		if ((addr & 3) || (numReg > PT_FPSCR))
 			break;
-		/* Insure it is a register we let them change */
-		if ((numReg == PT_ORIG_R3)
-				|| ((numReg > PT_CCR) && (numReg < PT_FPR0)))
-			break;
-		if (numReg >= PT_FPR0) {
+		if (numReg < PT_FPR0) {
+			unsigned long freg = ptrace_get_reg(child, numReg);
+			if (index % 2)
+				freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
+			else
+				freg = (freg & 0xfffffffful) | (data << 32);
+			ret = ptrace_put_reg(child, numReg, freg);
+		} else {
 			flush_fp_to_thread(child);
+			((unsigned int *)child->thread.regs)[index] = data;
+			ret = 0;
 		}
-		if (numReg == PT_MSR)
-			data = (data & MSR_DEBUGCHANGE)
-				| (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
-		((u32*)child->thread.regs)[index] = data;
-		ret = 0;
-		break;
-	}
-
-	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-	case PTRACE_CONT: { /* restart after signal. */
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		/* make sure the single step bit is not set. */
-		clear_single_step(child);
-		wake_up_process(child);
-		ret = 0;
-		break;
-	}
-
-	/*
-	 * make the child exit.  Best I can do is send it a sigkill.
-	 * perhaps it should be put in the status that it wants to
-	 * exit.
-	 */
-	case PTRACE_KILL: {
-		ret = 0;
-		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
-			break;
-		child->exit_code = SIGKILL;
-		/* make sure the single step bit is not set. */
-		clear_single_step(child);
-		wake_up_process(child);
-		break;
-	}
-
-	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		set_single_step(child);
-		child->exit_code = data;
-		/* give it a chance to run. */
-		wake_up_process(child);
-		ret = 0;
 		break;
 	}
 
@@ -334,95 +331,67 @@
 		break;
 	}
 
-	case PTRACE_SET_DEBUGREG:
-		ret = ptrace_set_debugreg(child, addr, data);
-		break;
-
-	case PTRACE_DETACH:
-		ret = ptrace_detach(child, data);
-		break;
-
-	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
-		int i;
-		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-		unsigned int __user *tmp = (unsigned int __user *)addr;
-
-		for (i = 0; i < 32; i++) {
-			ret = put_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
-		}
-		break;
-	}
-
-	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
-		int i;
-		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-		unsigned int __user *tmp = (unsigned int __user *)addr;
-
-		for (i = 0; i < 32; i++) {
-			ret = get_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
-		}
-		break;
-	}
-
-	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
-		int i;
-		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-		unsigned int __user *tmp = (unsigned int __user *)addr;
-
-		flush_fp_to_thread(child);
-
-		for (i = 0; i < 32; i++) {
-			ret = put_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
-		}
-		break;
-	}
-
-	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
-		int i;
-		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-		unsigned int __user *tmp = (unsigned int __user *)addr;
-
-		flush_fp_to_thread(child);
-
-		for (i = 0; i < 32; i++) {
-			ret = get_user(*reg, tmp);
-			if (ret)
-				break;
-			reg++;
-			tmp++;
-		}
-		break;
-	}
-
 	case PTRACE_GETEVENTMSG:
 		ret = put_user(child->ptrace_message, (unsigned int __user *) data);
 		break;
 
-#ifdef CONFIG_ALTIVEC
+	case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+		int ui;
+	  	if (!access_ok(VERIFY_WRITE, (void __user *)data,
+			       PT_REGS_COUNT * sizeof(int))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+			ret |= __put_user(ptrace_get_reg(child, ui),
+					  (unsigned int __user *) data);
+			data += sizeof(int);
+		}
+		break;
+	}
+
+	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+		unsigned long tmp;
+		int ui;
+	  	if (!access_ok(VERIFY_READ, (void __user *)data,
+			       PT_REGS_COUNT * sizeof(int))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+			ret = __get_user(tmp, (unsigned int __user *) data);
+			if (ret)
+				break;
+			ptrace_put_reg(child, ui, tmp);
+			data += sizeof(int);
+		}
+		break;
+	}
+
+	case PTRACE_GETFPREGS:
+	case PTRACE_SETFPREGS:
 	case PTRACE_GETVRREGS:
-		/* Get the child altivec register state. */
-		flush_altivec_to_thread(child);
-		ret = get_vrregs((unsigned long __user *)data, child);
+	case PTRACE_SETVRREGS:
+	case PTRACE_GETREGS64:
+	case PTRACE_SETREGS64:
+	case PPC_PTRACE_GETFPREGS:
+	case PPC_PTRACE_SETFPREGS:
+	case PTRACE_KILL:
+	case PTRACE_SINGLESTEP:
+	case PTRACE_DETACH:
+	case PTRACE_SET_DEBUGREG:
+	case PTRACE_SYSCALL:
+	case PTRACE_CONT:
+		ret = arch_ptrace(child, request, addr, data);
 		break;
 
-	case PTRACE_SETVRREGS:
-		/* Set the child altivec register state. */
-		flush_altivec_to_thread(child);
-		ret = set_vrregs(child, (unsigned long __user *)data);
+	/* Old reverse args ptrace callss */
+	case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+	case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+		ret = compat_ptrace_old(child, request, addr, data);
 		break;
-#endif
 
 	default:
 		ret = ptrace_request(child, request, addr, data);
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index f228682..a5de621 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -278,10 +278,8 @@
 {
 	struct device_node *node;
 	struct pci_controller *phb;
-	unsigned int index;
 	struct device_node *root = of_find_node_by_path("/");
 
-	index = 0;
 	for (node = of_get_next_child(root, NULL);
 	     node != NULL;
 	     node = of_get_next_child(root, node)) {
@@ -295,8 +293,7 @@
 			continue;
 		rtas_setup_phb(phb);
 		pci_process_bridge_OF_ranges(phb, node, 0);
-		pci_setup_phb_io(phb, index == 0);
-		index++;
+		isa_bridge_find_early(phb);
 	}
 
 	of_node_put(root);
@@ -335,7 +332,7 @@
 		return 1;
 	}
 
-	rc = unmap_bus_range(b);
+	rc = pcibios_unmap_io_space(b);
 	if (rc) {
 		printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
 			__FUNCTION__, b->name);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index ed07a19..4924c48 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -32,6 +32,7 @@
 #include <linux/unistd.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/debugfs.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -486,6 +487,14 @@
 
 	switch(base_port) {
 	case I8042_DATA_REG:
+		if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303")))
+			np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03");
+		if (np) {
+			parent = of_get_parent(np);
+			of_node_put(np);
+			np = parent;
+			break;
+		}
 		np = of_find_node_by_type(NULL, "8042");
 		break;
 	case FDC_BASE: /* FDC1 */
@@ -571,3 +580,15 @@
 
 late_initcall(check_cache_coherency);
 #endif /* CONFIG_CHECK_CACHE_COHERENCY */
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *powerpc_debugfs_root;
+
+static int powerpc_debugfs_init(void)
+{
+	powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL);
+
+	return powerpc_debugfs_root == NULL;
+}
+arch_initcall(powerpc_debugfs_init);
+#endif
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 35f8f44..7ec6ba5 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -262,13 +262,11 @@
 	 * Systems with OF can look in the properties on the cpu node(s)
 	 * for a possibly more accurate value.
 	 */
-	if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
-		dcache_bsize = cur_cpu_spec->dcache_bsize;
-		icache_bsize = cur_cpu_spec->icache_bsize;
-		ucache_bsize = 0;
-	} else
-		ucache_bsize = dcache_bsize = icache_bsize
-			= cur_cpu_spec->dcache_bsize;
+	dcache_bsize = cur_cpu_spec->dcache_bsize;
+	icache_bsize = cur_cpu_spec->icache_bsize;
+	ucache_bsize = 0;
+	if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
+		ucache_bsize = icache_bsize = dcache_bsize;
 
 	/* reboot on panic */
 	panic_timeout = 180;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6018178..bc43bba 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -350,13 +350,11 @@
 {
 	DBG(" -> setup_system()\n");
 
-	/* Apply the CPUs-specific and firmware specific fixups to kernel
-	 * text (nop out sections not relevant to this CPU or this firmware)
+	/* Apply CPUs-specific fixups to kernel text (nop out sections
+	 * not relevant to this CPU)
 	 */
 	do_feature_fixups(cur_cpu_spec->cpu_features,
 			  &__start___ftr_fixup, &__stop___ftr_fixup);
-	do_feature_fixups(powerpc_firmware_features,
-			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 
 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
@@ -394,6 +392,12 @@
 	if (ppc_md.init_early)
 		ppc_md.init_early();
 
+	/* Apply firmware specific fixups to kernel text (nop out
+	 * sections not relevant to this firmware)
+	 */
+	do_feature_fixups(powerpc_firmware_features,
+			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
+
  	/*
 	 * We can discover serial ports now since the above did setup the
 	 * hash table management for us, thus ioremap works. We do that early
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
new file mode 100644
index 0000000..c434d6c
--- /dev/null
+++ b/arch/powerpc/kernel/signal.c
@@ -0,0 +1,180 @@
+/*
+ * Common signal handling code for both 32 and 64 bits
+ *
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Extracted from signal_32.c and signal_64.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+#include "signal.h"
+
+/*
+ * Allocate space for the signal frame
+ */
+void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+			   size_t frame_size)
+{
+        unsigned long oldsp, newsp;
+
+        /* Default to using normal stack */
+        oldsp = regs->gpr[1];
+
+	/* Check for alt stack */
+	if ((ka->sa.sa_flags & SA_ONSTACK) &&
+	    current->sas_ss_size && !on_sig_stack(oldsp))
+		oldsp = (current->sas_ss_sp + current->sas_ss_size);
+
+	/* Get aligned frame */
+	newsp = (oldsp - frame_size) & ~0xFUL;
+
+	/* Check access */
+	if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
+		return NULL;
+
+        return (void __user *)newsp;
+}
+
+
+/*
+ * Restore the user process's signal mask
+ */
+void restore_sigmask(sigset_t *set)
+{
+	sigdelsetmask(set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = *set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+}
+
+static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
+				  int has_handler)
+{
+	unsigned long ret = regs->gpr[3];
+	int restart = 1;
+
+	/* syscall ? */
+	if (TRAP(regs) != 0x0C00)
+		return;
+
+	/* error signalled ? */
+	if (!(regs->ccr & 0x10000000))
+		return;
+
+	switch (ret) {
+	case ERESTART_RESTARTBLOCK:
+	case ERESTARTNOHAND:
+		/* ERESTARTNOHAND means that the syscall should only be
+		 * restarted if there was no handler for the signal, and since
+		 * we only get here if there is a handler, we dont restart.
+		 */
+		restart = !has_handler;
+		break;
+	case ERESTARTSYS:
+		/* ERESTARTSYS means to restart the syscall if there is no
+		 * handler or the handler was registered with SA_RESTART
+		 */
+		restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
+		break;
+	case ERESTARTNOINTR:
+		/* ERESTARTNOINTR means that the syscall should be
+		 * called again after the signal handler returns.
+		 */
+		break;
+	default:
+		return;
+	}
+	if (restart) {
+		if (ret == ERESTART_RESTARTBLOCK)
+			regs->gpr[0] = __NR_restart_syscall;
+		else
+			regs->gpr[3] = regs->orig_gpr3;
+		regs->nip -= 4;
+		regs->result = 0;
+	} else {
+		regs->result = -EINTR;
+		regs->gpr[3] = EINTR;
+		regs->ccr |= 0x10000000;
+	}
+}
+
+int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+	siginfo_t info;
+	int signr;
+	struct k_sigaction ka;
+	int ret;
+	int is32 = is_32bit_task();
+
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else if (!oldset)
+		oldset = &current->blocked;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+	/* Is there any syscall restart business here ? */
+	check_syscall_restart(regs, &ka, signr > 0);
+
+	if (signr <= 0) {
+		/* No signal to deliver -- put the saved sigmask back */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		}
+		return 0;               /* no signals delivered */
+	}
+
+        /*
+	 * Reenable the DABR before delivering the signal to
+	 * user space. The DABR will have been cleared if it
+	 * triggered inside the kernel.
+	 */
+	if (current->thread.dabr)
+		set_dabr(current->thread.dabr);
+
+	if (is32) {
+        	if (ka.sa.sa_flags & SA_SIGINFO)
+			ret = handle_rt_signal32(signr, &ka, &info, oldset,
+					regs);
+		else
+			ret = handle_signal32(signr, &ka, &info, oldset,
+					regs);
+	} else {
+		ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
+	}
+
+	if (ret) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked, &current->blocked,
+			  &ka.sa.sa_mask);
+		if (!(ka.sa.sa_flags & SA_NODEFER))
+			sigaddset(&current->blocked, signr);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+
+		/*
+		 * A signal was successfully delivered; the saved sigmask is in
+		 * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+	}
+
+	return ret;
+}
+
+long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+		unsigned long r5, unsigned long r6, unsigned long r7,
+		unsigned long r8, struct pt_regs *regs)
+{
+	return do_sigaltstack(uss, uoss, regs->gpr[1]);
+}
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
new file mode 100644
index 0000000..77efb3d
--- /dev/null
+++ b/arch/powerpc/kernel/signal.h
@@ -0,0 +1,55 @@
+/*
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Extracted from signal_32.c and signal_64.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#ifndef _POWERPC_ARCH_SIGNAL_H
+#define _POWERPC_ARCH_SIGNAL_H
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+				  size_t frame_size);
+extern void restore_sigmask(sigset_t *set);
+
+extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+			   siginfo_t *info, sigset_t *oldset,
+			   struct pt_regs *regs);
+
+extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
+			      siginfo_t *info, sigset_t *oldset,
+			      struct pt_regs *regs);
+
+
+#ifdef CONFIG_PPC64
+
+static inline int is_32bit_task(void)
+{
+	return test_thread_flag(TIF_32BIT);
+}
+
+extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
+			      siginfo_t *info, sigset_t *set,
+			      struct pt_regs *regs);
+
+#else /* CONFIG_PPC64 */
+
+static inline int is_32bit_task(void)
+{
+	return 1;
+}
+
+static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
+				     siginfo_t *info, sigset_t *set,
+				     struct pt_regs *regs)
+{
+	return -EFAULT;
+}
+
+#endif /* !defined(CONFIG_PPC64) */
+
+#endif  /* _POWERPC_ARCH_SIGNAL_H */
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index dd1dca5..590057e 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -51,12 +51,11 @@
 #include <asm/pgtable.h>
 #endif
 
+#include "signal.h"
+
 #undef DEBUG_SIG
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 #ifdef CONFIG_PPC64
-#define do_signal	do_signal32
 #define sys_sigsuspend	compat_sys_sigsuspend
 #define sys_rt_sigsuspend	compat_sys_rt_sigsuspend
 #define sys_rt_sigreturn	compat_sys_rt_sigreturn
@@ -231,8 +230,6 @@
 
 #endif /* CONFIG_PPC64 */
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -251,14 +248,6 @@
  	return -ERESTARTNOHAND;
 }
 
-#ifdef CONFIG_PPC32
-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
-		int r6, int r7, int r8, struct pt_regs *regs)
-{
-	return do_sigaltstack(uss, uoss, regs->gpr[1]);
-}
-#endif
-
 long sys_sigaction(int sig, struct old_sigaction __user *act,
 		struct old_sigaction __user *oact)
 {
@@ -293,14 +282,17 @@
 /*
  * When we have signals to deliver, we set up on the
  * user stack, going down from the original stack pointer:
- *	a sigregs struct
+ *	an ABI gap of 56 words
+ *	an mcontext struct
  *	a sigcontext struct
  *	a gap of __SIGNAL_FRAMESIZE bytes
  *
- * Each of these things must be a multiple of 16 bytes in size.
+ * Each of these things must be a multiple of 16 bytes in size. The following
+ * structure represent all of this except the __SIGNAL_FRAMESIZE gap
  *
  */
-struct sigregs {
+struct sigframe {
+	struct sigcontext sctx;		/* the sigcontext */
 	struct mcontext	mctx;		/* all the register values */
 	/*
 	 * Programs using the rs6000/xcoff abi can save up to 19 gp
@@ -703,44 +695,22 @@
 }
 #endif /* CONFIG_PPC64 */
 
-
-/*
- * Restore the user process's signal mask
- */
-#ifdef CONFIG_PPC64
-extern void restore_sigmask(sigset_t *set);
-#else /* CONFIG_PPC64 */
-static void restore_sigmask(sigset_t *set)
-{
-	sigdelsetmask(set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = *set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-}
-#endif
-
 /*
  * Set up a signal frame for a "real-time" signal handler
  * (one which gets siginfo).
  */
-static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
+int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
 		siginfo_t *info, sigset_t *oldset,
-		struct pt_regs *regs, unsigned long newsp)
+		struct pt_regs *regs)
 {
 	struct rt_sigframe __user *rt_sf;
 	struct mcontext __user *frame;
-	unsigned long origsp = newsp;
+	unsigned long newsp = 0;
 
 	/* Set up Signal Frame */
 	/* Put a Real Time Context onto stack */
-	newsp -= sizeof(*rt_sf);
-	rt_sf = (struct rt_sigframe __user *)newsp;
-
-	/* create a stack frame for the caller of the handler */
-	newsp -= __SIGNAL_FRAMESIZE + 16;
-
-	if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
+	rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
+	if (unlikely(rt_sf == NULL))
 		goto badframe;
 
 	/* Put the siginfo & fill in most of the ucontext */
@@ -770,8 +740,12 @@
 
 	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */
 
+	/* create a stack frame for the caller of the handler */
+	newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
 	if (put_user(regs->gpr[1], (u32 __user *)newsp))
 		goto badframe;
+
+	/* Fill registers for signal handler */
 	regs->gpr[1] = newsp;
 	regs->gpr[3] = sig;
 	regs->gpr[4] = (unsigned long) &rt_sf->info;
@@ -1015,27 +989,18 @@
 /*
  * OK, we're invoking a handler
  */
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
-		siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
-		unsigned long newsp)
+int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
 	struct sigcontext __user *sc;
-	struct sigregs __user *frame;
-	unsigned long origsp = newsp;
+	struct sigframe __user *frame;
+	unsigned long newsp = 0;
 
 	/* Set up Signal Frame */
-	newsp -= sizeof(struct sigregs);
-	frame = (struct sigregs __user *) newsp;
-
-	/* Put a sigcontext on the stack */
-	newsp -= sizeof(*sc);
-	sc = (struct sigcontext __user *) newsp;
-
-	/* create a stack frame for the caller of the handler */
-	newsp -= __SIGNAL_FRAMESIZE;
-
-	if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+	if (unlikely(frame == NULL))
 		goto badframe;
+	sc = (struct sigcontext __user *) &frame->sctx;
 
 #if _NSIG != 64
 #error "Please adjust handle_signal()"
@@ -1047,7 +1012,7 @@
 #else
 	    || __put_user(oldset->sig[1], &sc->_unused[3])
 #endif
-	    || __put_user(to_user_ptr(frame), &sc->regs)
+	    || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
 	    || __put_user(sig, &sc->signal))
 		goto badframe;
 
@@ -1063,8 +1028,11 @@
 
 	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */
 
+	/* create a stack frame for the caller of the handler */
+	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
 	if (put_user(regs->gpr[1], (u32 __user *)newsp))
 		goto badframe;
+
 	regs->gpr[1] = newsp;
 	regs->gpr[3] = sig;
 	regs->gpr[4] = (unsigned long) sc;
@@ -1126,106 +1094,3 @@
 	force_sig(SIGSEGV, current);
 	return 0;
 }
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
-{
-	siginfo_t info;
-	struct k_sigaction ka;
-	unsigned int newsp;
-	int signr, ret;
-
-#ifdef CONFIG_PPC32
-	if (try_to_freeze()) {
-		signr = 0;
-		if (!signal_pending(current))
-			goto no_signal;
-	}
-#endif
-
-	if (test_thread_flag(TIF_RESTORE_SIGMASK))
-		oldset = &current->saved_sigmask;
-	else if (!oldset)
-		oldset = &current->blocked;
-
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-#ifdef CONFIG_PPC32
-no_signal:
-#endif
-	if (TRAP(regs) == 0x0C00		/* System Call! */
-	    && regs->ccr & 0x10000000		/* error signalled */
-	    && ((ret = regs->gpr[3]) == ERESTARTSYS
-		|| ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
-		|| ret == ERESTART_RESTARTBLOCK)) {
-
-		if (signr > 0
-		    && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
-			|| (ret == ERESTARTSYS
-			    && !(ka.sa.sa_flags & SA_RESTART)))) {
-			/* make the system call return an EINTR error */
-			regs->result = -EINTR;
-			regs->gpr[3] = EINTR;
-			/* note that the cr0.SO bit is already set */
-		} else {
-			regs->nip -= 4;	/* Back up & retry system call */
-			regs->result = 0;
-			regs->trap = 0;
-			if (ret == ERESTART_RESTARTBLOCK)
-				regs->gpr[0] = __NR_restart_syscall;
-			else
-				regs->gpr[3] = regs->orig_gpr3;
-		}
-	}
-
-	if (signr == 0) {
-		/* No signal to deliver -- put the saved sigmask back */
-		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-			clear_thread_flag(TIF_RESTORE_SIGMASK);
-			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-		}
-		return 0;		/* no signals delivered */
-	}
-
-	if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
-	    && !on_sig_stack(regs->gpr[1]))
-		newsp = current->sas_ss_sp + current->sas_ss_size;
-	else
-		newsp = regs->gpr[1];
-	newsp &= ~0xfUL;
-
-#ifdef CONFIG_PPC64
-	/*
-	 * Reenable the DABR before delivering the signal to
-	 * user space. The DABR will have been cleared if it
-	 * triggered inside the kernel.
-	 */
-	if (current->thread.dabr)
-		set_dabr(current->thread.dabr);
-#endif
-
-	/* Whee!  Actually deliver the signal.  */
-	if (ka.sa.sa_flags & SA_SIGINFO)
-		ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
-	else
-		ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
-
-	if (ret) {
-		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked, &current->blocked,
-			  &ka.sa.sa_mask);
-		if (!(ka.sa.sa_flags & SA_NODEFER))
-			sigaddset(&current->blocked, signr);
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-		/* A signal was successfully delivered; the saved sigmask is in
-		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
-		if (test_thread_flag(TIF_RESTORE_SIGMASK))
-			clear_thread_flag(TIF_RESTORE_SIGMASK);
-	}
-
-	return ret;
-}
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 1ce0ae3..de895e6 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -34,9 +34,9 @@
 #include <asm/syscalls.h>
 #include <asm/vdso.h>
 
-#define DEBUG_SIG 0
+#include "signal.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#define DEBUG_SIG 0
 
 #define GP_REGS_SIZE	min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
 #define FP_REGS_SIZE	sizeof(elf_fpregset_t)
@@ -64,14 +64,6 @@
 	char abigap[288];
 } __attribute__ ((aligned (16)));
 
-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
-		     unsigned long r6, unsigned long r7, unsigned long r8,
-		     struct pt_regs *regs)
-{
-	return do_sigaltstack(uss, uoss, regs->gpr[1]);
-}
-
-
 /*
  * Set up the sigcontext for the signal frame.
  */
@@ -176,6 +168,13 @@
 	 */
 	discard_lazy_cpu_state();
 
+	/*
+	 * Force reload of FP/VEC.
+	 * This has to be done before copying stuff into current->thread.fpr/vr
+	 * for the reasons explained in the previous comment.
+	 */
+	regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
+
 	err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
 
 #ifdef CONFIG_ALTIVEC
@@ -197,32 +196,10 @@
 		current->thread.vrsave = 0;
 #endif /* CONFIG_ALTIVEC */
 
-	/* Force reload of FP/VEC */
-	regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
-
 	return err;
 }
 
 /*
- * Allocate space for the signal frame
- */
-static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-				  size_t frame_size)
-{
-        unsigned long newsp;
-
-        /* Default to using normal stack */
-        newsp = regs->gpr[1];
-
-	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
-		if (! on_sig_stack(regs->gpr[1]))
-			newsp = (current->sas_ss_sp + current->sas_ss_size);
-	}
-
-        return (void __user *)((newsp - frame_size) & -16ul);
-}
-
-/*
  * Setup the trampoline code on the stack
  */
 static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
@@ -249,19 +226,6 @@
 }
 
 /*
- * Restore the user process's signal mask (also used by signal32.c)
- */
-void restore_sigmask(sigset_t *set)
-{
-	sigdelsetmask(set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = *set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-}
-
-
-/*
  * Handle {get,set,swap}_context operations
  */
 int sys_swapcontext(struct ucontext __user *old_ctx,
@@ -355,7 +319,7 @@
 	return 0;
 }
 
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
 		sigset_t *set, struct pt_regs *regs)
 {
 	/* Handler is *really* a pointer to the function descriptor for
@@ -369,8 +333,7 @@
 	long err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+	if (unlikely(frame == NULL))
 		goto badframe;
 
 	err |= __put_user(&frame->info, &frame->pinfo);
@@ -407,7 +370,7 @@
 	funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
 
 	/* Allocate a dummy caller frame for the signal handler. */
-	newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
+	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
 	err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
 
 	/* Set up "regs" so we "return" to the signal handler. */
@@ -438,134 +401,3 @@
 	force_sigsegv(signr, current);
 	return 0;
 }
-
-
-/*
- * OK, we're invoking a handler
- */
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
-			 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
-{
-	int ret;
-
-	/* Set up Signal Frame */
-	ret = setup_rt_frame(sig, ka, info, oldset, regs);
-
-	if (ret) {
-		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
-		if (!(ka->sa.sa_flags & SA_NODEFER))
-			sigaddset(&current->blocked,sig);
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-	}
-
-	return ret;
-}
-
-static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
-{
-	switch ((int)regs->result) {
-	case -ERESTART_RESTARTBLOCK:
-	case -ERESTARTNOHAND:
-		/* ERESTARTNOHAND means that the syscall should only be
-		 * restarted if there was no handler for the signal, and since
-		 * we only get here if there is a handler, we dont restart.
-		 */
-		regs->result = -EINTR;
-		regs->gpr[3] = EINTR;
-		regs->ccr |= 0x10000000;
-		break;
-	case -ERESTARTSYS:
-		/* ERESTARTSYS means to restart the syscall if there is no
-		 * handler or the handler was registered with SA_RESTART
-		 */
-		if (!(ka->sa.sa_flags & SA_RESTART)) {
-			regs->result = -EINTR;
-			regs->gpr[3] = EINTR;
-			regs->ccr |= 0x10000000;
-			break;
-		}
-		/* fallthrough */
-	case -ERESTARTNOINTR:
-		/* ERESTARTNOINTR means that the syscall should be
-		 * called again after the signal handler returns.
-		 */
-		regs->gpr[3] = regs->orig_gpr3;
-		regs->nip -= 4;
-		regs->result = 0;
-		break;
-	}
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
-{
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
-
-	/*
-	 * If the current thread is 32 bit - invoke the
-	 * 32 bit signal handling code
-	 */
-	if (test_thread_flag(TIF_32BIT))
-		return do_signal32(oldset, regs);
-
-	if (test_thread_flag(TIF_RESTORE_SIGMASK))
-		oldset = &current->saved_sigmask;
-	else if (!oldset)
-		oldset = &current->blocked;
-
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		int ret;
-
-		/* Whee!  Actually deliver the signal.  */
-		if (TRAP(regs) == 0x0C00)
-			syscall_restart(regs, &ka);
-
-		/*
-		 * Reenable the DABR before delivering the signal to
-		 * user space. The DABR will have been cleared if it
-		 * triggered inside the kernel.
-		 */
-		if (current->thread.dabr)
-			set_dabr(current->thread.dabr);
-
-		ret = handle_signal(signr, &ka, &info, oldset, regs);
-
-		/* If a signal was successfully delivered, the saved sigmask is in
-		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
-		if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
-			clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-		return ret;
-	}
-
-	if (TRAP(regs) == 0x0C00) {	/* System Call! */
-		if ((int)regs->result == -ERESTARTNOHAND ||
-		    (int)regs->result == -ERESTARTSYS ||
-		    (int)regs->result == -ERESTARTNOINTR) {
-			regs->gpr[3] = regs->orig_gpr3;
-			regs->nip -= 4; /* Back up & retry system call */
-			regs->result = 0;
-		} else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
-			regs->gpr[0] = __NR_restart_syscall;
-			regs->nip -= 4;
-			regs->result = 0;
-		}
-	}
-	/* No signal to deliver -- put the saved sigmask back */
-	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-		clear_thread_flag(TIF_RESTORE_SIGMASK);
-		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(do_signal);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 22f1ef1..d577b71 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -201,13 +201,6 @@
 	/* Can deadlock when called with interrupts disabled */
 	WARN_ON(irqs_disabled());
 
-	/* remove 'self' from the map */
-	if (cpu_isset(smp_processor_id(), map))
-		cpu_clear(smp_processor_id(), map);
-
-	/* sanity check the map, remove any non-online processors. */
-	cpus_and(map, map, cpu_online_map);
-
 	if (unlikely(smp_ops == NULL))
 		return ret;
 
@@ -222,10 +215,17 @@
 	/* Must grab online cpu count with preempt disabled, otherwise
 	 * it can change. */
 	num_cpus = num_online_cpus() - 1;
-	if (!num_cpus || cpus_empty(map)) {
-		ret = 0;
-		goto out;
-	}
+	if (!num_cpus)
+		goto done;
+
+	/* remove 'self' from the map */
+	if (cpu_isset(smp_processor_id(), map))
+		cpu_clear(smp_processor_id(), map);
+
+	/* sanity check the map, remove any non-online processors. */
+	cpus_and(map, map, cpu_online_map);
+	if (cpus_empty(map))
+		goto done;
 
 	call_data = &data;
 	smp_wmb();
@@ -263,6 +263,7 @@
 		}
 	}
 
+ done:
 	ret = 0;
 
  out:
@@ -282,16 +283,17 @@
 int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic,
 			int wait)
 {
-	cpumask_t map=CPU_MASK_NONE;
+	cpumask_t map = CPU_MASK_NONE;
+	int ret = -EBUSY;
 
 	if (!cpu_online(cpu))
 		return -EINVAL;
 
-	if (cpu == smp_processor_id())
-		return -EBUSY;
-
 	cpu_set(cpu, map);
-	return smp_call_function_map(func,info,nonatomic,wait,map);
+	if (cpu != get_cpu())
+		ret = smp_call_function_map(func,info,nonatomic,wait,map);
+	put_cpu();
+	return ret;
 }
 EXPORT_SYMBOL(smp_call_function_single);
 
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 047246a..b42cbf1 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -810,3 +810,12 @@
 	return sys_request_key(_type, _description, _callout_info, destringid);
 }
 
+asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
+				   unsigned offset_hi, unsigned offset_lo,
+				   unsigned nbytes_hi, unsigned nbytes_lo)
+{
+	loff_t offset = ((loff_t)offset_hi << 32) | offset_lo;
+	loff_t nbytes = ((loff_t)nbytes_hi << 32) | nbytes_lo;
+
+	return sys_sync_file_range(fd, offset, nbytes, flags);
+}
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 68991c2..55d29ed 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -442,12 +442,14 @@
 	return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
 			kobject_name(&dev->kobj));
 }
+EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
 
 void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
 {
 	struct node *node = &node_devices[nid];
 	sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
 }
+EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
 
 #else
 static void register_nodes(void)
@@ -457,9 +459,6 @@
 
 #endif
 
-EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
-EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
-
 /* Only valid if CPU is present. */
 static ssize_t show_physical_id(struct sys_device *dev, char *buf)
 {
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 2c8564d..e5df167 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -77,9 +77,8 @@
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
 #ifdef CONFIG_PPC_ISERIES
-unsigned long iSeries_recal_titan = 0;
-unsigned long iSeries_recal_tb = 0; 
-static unsigned long first_settimeofday = 1;
+static unsigned long __initdata iSeries_recal_titan;
+static signed long __initdata iSeries_recal_tb;
 #endif
 
 /* The decrementer counts down by 128 every 128ns on a 601. */
@@ -113,8 +112,9 @@
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL_GPL(rtc_lock);
 
-u64 tb_to_ns_scale;
-unsigned tb_to_ns_shift;
+static u64 tb_to_ns_scale __read_mostly;
+static unsigned tb_to_ns_shift __read_mostly;
+static unsigned long boot_tb __read_mostly;
 
 struct gettimeofday_struct do_gtod;
 
@@ -214,7 +214,6 @@
  	run_posix_cpu_timers(current);
 }
 
-#ifdef CONFIG_PPC_SPLPAR
 /*
  * Stuff for accounting stolen time.
  */
@@ -222,19 +221,28 @@
 	int	initialized;			/* thread is running */
 	u64	tb;			/* last TB value read */
 	u64	purr;			/* last PURR value read */
-	spinlock_t lock;
 };
 
+/*
+ * Each entry in the cpu_purr_data array is manipulated only by its
+ * "owner" cpu -- usually in the timer interrupt but also occasionally
+ * in process context for cpu online.  As long as cpus do not touch
+ * each others' cpu_purr_data, disabling local interrupts is
+ * sufficient to serialize accesses.
+ */
 static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
 
 static void snapshot_tb_and_purr(void *data)
 {
+	unsigned long flags;
 	struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
 
+	local_irq_save(flags);
 	p->tb = mftb();
 	p->purr = mfspr(SPRN_PURR);
 	wmb();
 	p->initialized = 1;
+	local_irq_restore(flags);
 }
 
 /*
@@ -242,15 +250,14 @@
  */
 void snapshot_timebases(void)
 {
-	int cpu;
-
 	if (!cpu_has_feature(CPU_FTR_PURR))
 		return;
-	for_each_possible_cpu(cpu)
-		spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock);
 	on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
 }
 
+/*
+ * Must be called with interrupts disabled.
+ */
 void calculate_steal_time(void)
 {
 	u64 tb, purr;
@@ -262,7 +269,6 @@
 	pme = &per_cpu(cpu_purr_data, smp_processor_id());
 	if (!pme->initialized)
 		return;		/* this can happen in early boot */
-	spin_lock(&pme->lock);
 	tb = mftb();
 	purr = mfspr(SPRN_PURR);
 	stolen = (tb - pme->tb) - (purr - pme->purr);
@@ -270,9 +276,9 @@
 		account_steal_time(current, stolen);
 	pme->tb = tb;
 	pme->purr = purr;
-	spin_unlock(&pme->lock);
 }
 
+#ifdef CONFIG_PPC_SPLPAR
 /*
  * Must be called before the cpu is added to the online map when
  * a cpu is being brought up at runtime.
@@ -284,12 +290,12 @@
 
 	if (!cpu_has_feature(CPU_FTR_PURR))
 		return;
+	local_irq_save(flags);
 	pme = &per_cpu(cpu_purr_data, smp_processor_id());
-	spin_lock_irqsave(&pme->lock, flags);
 	pme->tb = mftb();
 	pme->purr = mfspr(SPRN_PURR);
 	pme->initialized = 1;
-	spin_unlock_irqrestore(&pme->lock, flags);
+	local_irq_restore(flags);
 }
 
 #endif /* CONFIG_PPC_SPLPAR */
@@ -550,10 +556,15 @@
  * returned by the service processor for the timebase frequency.  
  */
 
-static void iSeries_tb_recal(void)
+static int __init iSeries_tb_recal(void)
 {
 	struct div_result divres;
 	unsigned long titan, tb;
+
+	/* Make sure we only run on iSeries */
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		return -ENODEV;
+
 	tb = get_tb();
 	titan = HvCallXm_loadTod();
 	if ( iSeries_recal_titan ) {
@@ -594,8 +605,18 @@
 	}
 	iSeries_recal_titan = titan;
 	iSeries_recal_tb = tb;
+
+	return 0;
 }
-#endif
+late_initcall(iSeries_tb_recal);
+
+/* Called from platform early init */
+void __init iSeries_time_init_early(void)
+{
+	iSeries_recal_tb = get_tb();
+	iSeries_recal_titan = HvCallXm_loadTod();
+}
+#endif /* CONFIG_PPC_ISERIES */
 
 /*
  * For iSeries shared processors, we have to let the hypervisor
@@ -735,7 +756,7 @@
 {
 	if (__USE_RTC())
 		return get_rtc();
-	return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
+	return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
 }
 
 int do_settimeofday(struct timespec *tv)
@@ -759,12 +780,6 @@
 	 * to the RTC again, or write to the RTC but then they don't call
 	 * settimeofday to perform this operation.
 	 */
-#ifdef CONFIG_PPC_ISERIES
-	if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
-		iSeries_tb_recal();
-		first_settimeofday = 0;
-	}
-#endif
 
 	/* Make userspace gettimeofday spin until we're done. */
 	++vdso_data->tb_update_count;
@@ -960,6 +975,8 @@
 	}
 	tb_to_ns_scale = scale;
 	tb_to_ns_shift = shift;
+	/* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
+	boot_tb = get_tb();
 
 	tm = get_boot_time();
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index bf6445a..2bb1cb9 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -149,6 +149,7 @@
 
 	bust_spinlocks(0);
 	die.lock_owner = -1;
+	add_taint(TAINT_DIE);
 	spin_unlock_irqrestore(&die.lock, flags);
 
 	if (kexec_should_crash(current) ||
@@ -777,7 +778,7 @@
 			return;
 
 		if (!(regs->msr & MSR_PR) &&  /* not user-mode */
-		    report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
+		    report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
 			regs->nip += 4;
 			return;
 		}
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 87703df..cbca1df 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -151,12 +151,18 @@
 
 static int early_console_initialized;
 
-/* called by setup_system */
+/*
+ * Called by setup_system after ppc_md->probe and ppc_md->early_init.
+ * Call it again after setting udbg_putc in ppc_md->setup_arch.
+ */
 void register_early_udbg_console(void)
 {
 	if (early_console_initialized)
 		return;
 
+	if (!udbg_putc)
+		return;
+
 	if (strstr(boot_command_line, "udbg-immortal")) {
 		printk(KERN_INFO "early console immortal !\n");
 		udbg_console.flags &= ~CON_BOOT;
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 4245579..cef01e4 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -670,7 +670,7 @@
 	/*
 	 * Fill up the "systemcfg" stuff for backward compatiblity
 	 */
-	strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
+	strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
 	vdso_data->version.major = SYSTEMCFG_MAJOR;
 	vdso_data->version.minor = SYSTEMCFG_MINOR;
 	vdso_data->processor = mfspr(SPRN_PVR);
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
index 05909f7..72ca26d 100644
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -32,6 +32,8 @@
 	mr	r11,r4			/* r11 saves tz */
 	bl	__get_datapage@local	/* get data page */
 	mr	r9, r3			/* datapage ptr in r9 */
+	cmplwi	r10,0			/* check if tv is NULL */
+	beq	3f
 	bl	__do_get_xsec@local	/* get xsec from tb & kernel */
 	bne-	2f			/* out of line -> do syscall */
 
@@ -50,7 +52,7 @@
 	mulhwu	r5,r5,r6
 	stw	r5,TVAL32_TV_USEC(r10)
 
-	cmpli	cr0,r11,0		/* check if tz is NULL */
+3:	cmplwi	r11,0			/* check if tz is NULL */
 	beq	1f
 	lwz	r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */
 	lwz	r5,CFG_TZ_DSTTIME(r9)
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
index 40ffd9b..c6401f9 100644
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -1,5 +1,4 @@
-
-	/*
+/*
  * Userland implementation of gettimeofday() for 64 bits processes in a
  * ppc64 kernel for use in the vDSO
  *
@@ -32,6 +31,8 @@
 	mr	r11,r3			/* r11 holds tv */
 	mr	r10,r4			/* r10 holds tz */
 	bl	V_LOCAL_FUNC(__get_datapage)	/* get data page */
+	cmpldi	r11,0			/* check if tv is NULL */
+	beq	2f
 	bl	V_LOCAL_FUNC(__do_get_xsec)	/* get xsec from tb & kernel */
 	lis     r7,15			/* r7 = 1000000 = USEC_PER_SEC */
 	ori     r7,r7,16960
@@ -43,8 +44,8 @@
 					 * XSEC_PER_SEC
 					 */
 	rldicl  r0,r0,44,20
-	cmpldi	cr0,r10,0		/* check if tz is NULL */
 	std	r0,TVAL64_TV_USEC(r11)	/* store usec in tv */
+2:	cmpldi	r10,0			/* check if tz is NULL */
 	beq	1f
 	lwz	r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
 	lwz	r5,CFG_TZ_DSTTIME(r3)
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 1320673..ae4acd8 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -7,6 +7,7 @@
 #define PROVIDE32(x)	PROVIDE(x)
 #endif
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
 
 ENTRY(_stext)
 
@@ -34,7 +35,7 @@
 	/* Text and gots */
 	.text : {
 		_text = .;
-		*(.text .text.*)
+		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
@@ -167,7 +168,7 @@
 #ifdef CONFIG_PPC32
 	.data    :
 	{
-		*(.data)
+		DATA_DATA
 		*(.sdata)
 		*(.got.plt) *(.got)
 	}
@@ -211,6 +212,11 @@
 		*(.data.cacheline_aligned)
 	}
 
+	. = ALIGN(L1_CACHE_BYTES);
+	.data.read_mostly : {
+		*(.data.read_mostly)
+	}
+
 	. = ALIGN(PAGE_SIZE);
 	__data_nosave : {
 		__nosave_begin = .;
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index 180ee29..2f24ea0 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -437,27 +437,26 @@
 	struct list_head *l;
 	rh_block_t *blk;
 	rh_block_t *newblk;
-	unsigned long start;
+	unsigned long start, sp_size;
 
 	/* Validate size, and alignment must be power of two */
 	if (size <= 0 || (alignment & (alignment - 1)) != 0)
 		return (unsigned long) -EINVAL;
 
-	/* given alignment larger that default rheap alignment */
-	if (alignment > info->alignment)
-		size += alignment - 1;
-
 	/* Align to configured alignment */
 	size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
 
-	if (assure_empty(info, 1) < 0)
+	if (assure_empty(info, 2) < 0)
 		return (unsigned long) -ENOMEM;
 
 	blk = NULL;
 	list_for_each(l, &info->free_list) {
 		blk = list_entry(l, rh_block_t, list);
-		if (size <= blk->size)
-			break;
+		if (size <= blk->size) {
+			start = (blk->start + alignment - 1) & ~(alignment - 1);
+			if (start + size <= blk->start + blk->size)
+				break;
+		}
 		blk = NULL;
 	}
 
@@ -470,25 +469,36 @@
 		list_del(&blk->list);
 		newblk = blk;
 	} else {
+		/* Fragment caused, split if needed */
+		/* Create block for fragment in the beginning */
+		sp_size = start - blk->start;
+		if (sp_size) {
+			rh_block_t *spblk;
+
+			spblk = get_slot(info);
+			spblk->start = blk->start;
+			spblk->size = sp_size;
+			/* add before the blk */
+			list_add(&spblk->list, blk->list.prev);
+		}
 		newblk = get_slot(info);
-		newblk->start = blk->start;
+		newblk->start = start;
 		newblk->size = size;
 
-		/* blk still in free list, with updated start, size */
-		blk->start += size;
-		blk->size -= size;
+		/* blk still in free list, with updated start and size
+		 * for fragment in the end */
+		blk->start = start + size;
+		blk->size -= sp_size + size;
+		/* No fragment in the end, remove blk */
+		if (blk->size == 0) {
+			list_del(&blk->list);
+			release_slot(info, blk);
+		}
 	}
 
 	newblk->owner = owner;
-	start = newblk->start;
 	attach_taken_block(info, newblk);
 
-	/* for larger alignment return fixed up pointer  */
-	/* this is no problem with the deallocator since */
-	/* we scan for pointers that lie in the blocks   */
-	if (alignment > info->alignment)
-		start = (start + alignment - 1) & ~(alignment - 1);
-
 	return start;
 }
 
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index ca4dcb0..c3df504 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -12,7 +12,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/4xx_mmu.c b/arch/powerpc/mm/4xx_mmu.c
index 838e09d..7ff2609 100644
--- a/arch/powerpc/mm/4xx_mmu.c
+++ b/arch/powerpc/mm/4xx_mmu.c
@@ -9,7 +9,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 4f839c6..7e4d27a 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -11,8 +11,7 @@
 hash-$(CONFIG_PPC_NATIVE)	:= hash_native_64.o
 obj-$(CONFIG_PPC64)		+= init_64.o pgtable_64.o mmu_context_64.o \
 				   hash_utils_64.o hash_low_64.o tlb_64.o \
-				   slb_low.o slb.o stab.o mmap.o imalloc.o \
-				   $(hash-y)
+				   slb_low.o slb.o stab.o mmap.o $(hash-y)
 obj-$(CONFIG_PPC_STD_MMU_32)	+= ppc_mmu_32.o hash_low_32.o tlb_32.o
 obj-$(CONFIG_40x)		+= 4xx_mmu.o
 obj-$(CONFIG_44x)		+= 44x_mmu.o
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index bfe9013..0ece513 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -279,14 +279,13 @@
 #endif /* CONFIG_8xx */
 
 	if (is_exec) {
-#ifdef CONFIG_PPC64
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
 		/* protection fault */
 		if (error_code & DSISR_PROTFAULT)
 			goto bad_area;
 		if (!(vma->vm_flags & VM_EXEC))
 			goto bad_area;
-#endif
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#else
 		pte_t *ptep;
 		pmd_t *pmdp;
 
@@ -381,7 +380,7 @@
 	}
 	printk("VM: killing process %s\n", current->comm);
 	if (user_mode(regs))
-		do_exit(SIGKILL);
+		do_group_exit(SIGKILL);
 	return SIGKILL;
 
 do_sigbus:
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 123da03..afab247 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -14,7 +14,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 4a20d89..6ba9b47 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -104,7 +104,7 @@
 		spin_unlock(&native_tlbie_lock);
 }
 
-static inline void native_lock_hpte(hpte_t *hptep)
+static inline void native_lock_hpte(struct hash_pte *hptep)
 {
 	unsigned long *word = &hptep->v;
 
@@ -116,7 +116,7 @@
 	}
 }
 
-static inline void native_unlock_hpte(hpte_t *hptep)
+static inline void native_unlock_hpte(struct hash_pte *hptep)
 {
 	unsigned long *word = &hptep->v;
 
@@ -128,7 +128,7 @@
 			unsigned long pa, unsigned long rflags,
 			unsigned long vflags, int psize)
 {
-	hpte_t *hptep = htab_address + hpte_group;
+	struct hash_pte *hptep = htab_address + hpte_group;
 	unsigned long hpte_v, hpte_r;
 	int i;
 
@@ -163,7 +163,7 @@
 
 	hptep->r = hpte_r;
 	/* Guarantee the second dword is visible before the valid bit */
-	__asm__ __volatile__ ("eieio" : : : "memory");
+	eieio();
 	/*
 	 * Now set the first dword including the valid bit
 	 * NOTE: this also unlocks the hpte
@@ -177,7 +177,7 @@
 
 static long native_hpte_remove(unsigned long hpte_group)
 {
-	hpte_t *hptep;
+	struct hash_pte *hptep;
 	int i;
 	int slot_offset;
 	unsigned long hpte_v;
@@ -217,7 +217,7 @@
 static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
 				 unsigned long va, int psize, int local)
 {
-	hpte_t *hptep = htab_address + slot;
+	struct hash_pte *hptep = htab_address + slot;
 	unsigned long hpte_v, want_v;
 	int ret = 0;
 
@@ -233,15 +233,14 @@
 	/* Even if we miss, we need to invalidate the TLB */
 	if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
 		DBG_LOW(" -> miss\n");
-		native_unlock_hpte(hptep);
 		ret = -1;
 	} else {
 		DBG_LOW(" -> hit\n");
 		/* Update the HPTE */
 		hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
 			(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
-		native_unlock_hpte(hptep);
 	}
+	native_unlock_hpte(hptep);
 
 	/* Ensure it is out of the tlb too. */
 	tlbie(va, psize, local);
@@ -251,7 +250,7 @@
 
 static long native_hpte_find(unsigned long va, int psize)
 {
-	hpte_t *hptep;
+	struct hash_pte *hptep;
 	unsigned long hash;
 	unsigned long i, j;
 	long slot;
@@ -294,7 +293,7 @@
 {
 	unsigned long vsid, va;
 	long slot;
-	hpte_t *hptep;
+	struct hash_pte *hptep;
 
 	vsid = get_kernel_vsid(ea);
 	va = (vsid << 28) | (ea & 0x0fffffff);
@@ -315,7 +314,7 @@
 static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 				   int psize, int local)
 {
-	hpte_t *hptep = htab_address + slot;
+	struct hash_pte *hptep = htab_address + slot;
 	unsigned long hpte_v;
 	unsigned long want_v;
 	unsigned long flags;
@@ -345,7 +344,7 @@
 #define LP_BITS		8
 #define LP_MASK(i)	((0xFF >> (i)) << LP_SHIFT)
 
-static void hpte_decode(hpte_t *hpte, unsigned long slot,
+static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 			int *psize, unsigned long *va)
 {
 	unsigned long hpte_r = hpte->r;
@@ -415,7 +414,7 @@
 static void native_hpte_clear(void)
 {
 	unsigned long slot, slots, flags;
-	hpte_t *hptep = htab_address;
+	struct hash_pte *hptep = htab_address;
 	unsigned long hpte_v, va;
 	unsigned long pteg_count;
 	int psize;
@@ -462,7 +461,7 @@
 static void native_flush_hash_range(unsigned long number, int local)
 {
 	unsigned long va, hash, index, hidx, shift, slot;
-	hpte_t *hptep;
+	struct hash_pte *hptep;
 	unsigned long hpte_v;
 	unsigned long want_v;
 	unsigned long flags;
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 4f2f453..2ce9491 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -87,7 +87,7 @@
 static unsigned long _SDR1;
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
 
-hpte_t *htab_address;
+struct hash_pte *htab_address;
 unsigned long htab_size_bytes;
 unsigned long htab_hash_mask;
 int mmu_linear_psize = MMU_PAGE_4K;
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
deleted file mode 100644
index c831815..0000000
--- a/arch/powerpc/mm/imalloc.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * c 2001 PPC 64 Team, IBM Corp
- * 
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- */
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <linux/mutex.h>
-#include <asm/cacheflush.h>
-
-#include "mmu_decl.h"
-
-static DEFINE_MUTEX(imlist_mutex);
-struct vm_struct * imlist = NULL;
-
-static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
-{
-	unsigned long addr;
-	struct vm_struct **p, *tmp;
-
-	addr = ioremap_bot;
-	for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
-		if (size + addr < (unsigned long) tmp->addr)
-			break;
-		if ((unsigned long)tmp->addr >= ioremap_bot)
-			addr = tmp->size + (unsigned long) tmp->addr;
-		if (addr >= IMALLOC_END-size)
-			return 1;
-	}
-	*im_addr = addr;
-
-	return 0;
-}
-
-/* Return whether the region described by v_addr and size is a subset
- * of the region described by parent
- */
-static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
-			struct vm_struct *parent)
-{
-	return (int) (v_addr >= (unsigned long) parent->addr &&
-	              v_addr < (unsigned long) parent->addr + parent->size &&
-	    	      size < parent->size);
-}
-
-/* Return whether the region described by v_addr and size is a superset
- * of the region described by child
- */
-static int im_region_is_superset(unsigned long v_addr, unsigned long size,
-		struct vm_struct *child)
-{
-	struct vm_struct parent;
-
-	parent.addr = (void *) v_addr;
-	parent.size = size;
-
-	return im_region_is_subset((unsigned long) child->addr, child->size,
-			&parent);
-}
-
-/* Return whether the region described by v_addr and size overlaps
- * the region described by vm.  Overlapping regions meet the
- * following conditions:
- * 1) The regions share some part of the address space
- * 2) The regions aren't identical
- * 3) Neither region is a subset of the other
- */
-static int im_region_overlaps(unsigned long v_addr, unsigned long size,
-		     struct vm_struct *vm)
-{
-	if (im_region_is_superset(v_addr, size, vm))
-		return 0;
-
-	return (v_addr + size > (unsigned long) vm->addr + vm->size &&
-		v_addr < (unsigned long) vm->addr + vm->size) ||
-	       (v_addr < (unsigned long) vm->addr &&
-		v_addr + size > (unsigned long) vm->addr);
-}
-
-/* Determine imalloc status of region described by v_addr and size.
- * Can return one of the following:
- * IM_REGION_UNUSED   -  Entire region is unallocated in imalloc space.
- * IM_REGION_SUBSET -    Region is a subset of a region that is already
- * 			 allocated in imalloc space.
- * 		         vm will be assigned to a ptr to the parent region.
- * IM_REGION_EXISTS -    Exact region already allocated in imalloc space.
- *                       vm will be assigned to a ptr to the existing imlist
- *                       member.
- * IM_REGION_OVERLAPS -  Region overlaps an allocated region in imalloc space.
- * IM_REGION_SUPERSET -  Region is a superset of a region that is already
- *                       allocated in imalloc space.
- */
-static int im_region_status(unsigned long v_addr, unsigned long size,
-		    struct vm_struct **vm)
-{
-	struct vm_struct *tmp;
-
-	for (tmp = imlist; tmp; tmp = tmp->next)
-		if (v_addr < (unsigned long) tmp->addr + tmp->size)
-			break;
-
-	*vm = NULL;
-	if (tmp) {
-		if (im_region_overlaps(v_addr, size, tmp))
-			return IM_REGION_OVERLAP;
-
-		*vm = tmp;
-		if (im_region_is_subset(v_addr, size, tmp)) {
-			/* Return with tmp pointing to superset */
-			return IM_REGION_SUBSET;
-		}
-		if (im_region_is_superset(v_addr, size, tmp)) {
-			/* Return with tmp pointing to first subset */
-			return IM_REGION_SUPERSET;
-		}
-		else if (v_addr == (unsigned long) tmp->addr &&
-		 	 size == tmp->size) {
-			/* Return with tmp pointing to exact region */
-			return IM_REGION_EXISTS;
-		}
-	}
-
-	return IM_REGION_UNUSED;
-}
-
-static struct vm_struct * split_im_region(unsigned long v_addr, 
-		unsigned long size, struct vm_struct *parent)
-{
-	struct vm_struct *vm1 = NULL;
-	struct vm_struct *vm2 = NULL;
-	struct vm_struct *new_vm = NULL;
-	
-	vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
-	if (vm1	== NULL) {
-		printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
-		return NULL;
-	}
-
-	if (v_addr == (unsigned long) parent->addr) {
-	        /* Use existing parent vm_struct to represent child, allocate
-		 * new one for the remainder of parent range
-		 */
-		vm1->size = parent->size - size;
-		vm1->addr = (void *) (v_addr + size);
-		vm1->next = parent->next;
-
-		parent->size = size;
-		parent->next = vm1;
-		new_vm = parent;
-	} else if (v_addr + size == (unsigned long) parent->addr + 
-			parent->size) {
-		/* Allocate new vm_struct to represent child, use existing
-		 * parent one for remainder of parent range
-		 */
-		vm1->size = size;
-		vm1->addr = (void *) v_addr;
-		vm1->next = parent->next;
-		new_vm = vm1;
-
-		parent->size -= size;
-		parent->next = vm1;
-	} else {
-	        /* Allocate two new vm_structs for the new child and 
-		 * uppermost remainder, and use existing parent one for the
-		 * lower remainder of parent range
-		 */
-		vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
-		if (vm2 == NULL) {
-			printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
-			kfree(vm1);
-			return NULL;
-		}
-
-		vm1->size = size;
-		vm1->addr = (void *) v_addr;
-		vm1->next = vm2;
-		new_vm = vm1;
-
-		vm2->size = ((unsigned long) parent->addr + parent->size) - 
-				(v_addr + size);
-		vm2->addr = (void *) v_addr + size;
-		vm2->next = parent->next;
-
-		parent->size = v_addr - (unsigned long) parent->addr;
-		parent->next = vm1;
-	}
-
-	return new_vm;
-}
-
-static struct vm_struct * __add_new_im_area(unsigned long req_addr, 
-					    unsigned long size)
-{
-	struct vm_struct **p, *tmp, *area;
-		
-	for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
-		if (req_addr + size <= (unsigned long)tmp->addr)
-			break;
-	}
-	
-	area = kmalloc(sizeof(*area), GFP_KERNEL);
-	if (!area)
-		return NULL;
-	area->flags = 0;
-	area->addr = (void *)req_addr;
-	area->size = size;
-	area->next = *p;
-	*p = area;
-
-	return area;
-}
-
-static struct vm_struct * __im_get_area(unsigned long req_addr, 
-					unsigned long size,
-					int criteria)
-{
-	struct vm_struct *tmp;
-	int status;
-
-	status = im_region_status(req_addr, size, &tmp);
-	if ((criteria & status) == 0) {
-		return NULL;
-	}
-	
-	switch (status) {
-	case IM_REGION_UNUSED:
-		tmp = __add_new_im_area(req_addr, size);
-		break;
-	case IM_REGION_SUBSET:
-		tmp = split_im_region(req_addr, size, tmp);
-		break;
-	case IM_REGION_EXISTS:
-		/* Return requested region */
-		break;
-	case IM_REGION_SUPERSET:
-		/* Return first existing subset of requested region */
-		break;
-	default:
-		printk(KERN_ERR "%s() unexpected imalloc region status\n",
-				__FUNCTION__);
-		tmp = NULL;
-	}
-
-	return tmp;
-}
-
-struct vm_struct * im_get_free_area(unsigned long size)
-{
-	struct vm_struct *area;
-	unsigned long addr;
-	
-	mutex_lock(&imlist_mutex);
-	if (get_free_im_addr(size, &addr)) {
-		printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
-				__FUNCTION__, size);
-		area = NULL;
-		goto next_im_done;
-	}
-
-	area = __im_get_area(addr, size, IM_REGION_UNUSED);
-	if (area == NULL) {
-		printk(KERN_ERR 
-		       "%s() cannot obtain area for addr 0x%lx size 0x%lx\n",
-			__FUNCTION__, addr, size);
-	}
-next_im_done:
-	mutex_unlock(&imlist_mutex);
-	return area;
-}
-
-struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-		int criteria)
-{
-	struct vm_struct *area;
-
-	mutex_lock(&imlist_mutex);
-	area = __im_get_area(v_addr, size, criteria);
-	mutex_unlock(&imlist_mutex);
-	return area;
-}
-
-void im_free(void * addr)
-{
-	struct vm_struct **p, *tmp;
-  
-	if (!addr)
-		return;
-	if ((unsigned long) addr & ~PAGE_MASK) {
-		printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__,			addr);
-		return;
-	}
-	mutex_lock(&imlist_mutex);
-	for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
-		if (tmp->addr == addr) {
-			*p = tmp->next;
-			unmap_vm_area(tmp);
-			kfree(tmp);
-			mutex_unlock(&imlist_mutex);
-			return;
-		}
-	}
-	mutex_unlock(&imlist_mutex);
-	printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
-			addr);
-}
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 5fce6cc..e1f5ded 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
  *
  *  Derived from "arch/i386/mm/init.c"
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 7312a26..1d6edf7 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 246eeea..f0e7eed 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
  *
  *  Derived from "arch/i386/mm/init.c"
@@ -129,8 +128,6 @@
 	zone = pgdata->node_zones;
 
 	return __add_pages(zone, start_pfn, nr_pages);
-
-	return 0;
 }
 
 /*
@@ -310,11 +307,12 @@
 
 #ifdef CONFIG_HIGHMEM
 	map_page(PKMAP_BASE, 0, 0);	/* XXX gross */
-	pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
-			(PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
+	pkmap_page_table = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
+			(PKMAP_BASE), PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
 	map_page(KMAP_FIX_BEGIN, 0, 0);	/* XXX gross */
-	kmap_pte = pte_offset_kernel(pmd_offset(pgd_offset_k
-			(KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
+	kmap_pte = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
+			(KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN),
+			 KMAP_FIX_BEGIN);
 	kmap_prot = PAGE_KERNEL;
 #endif /* CONFIG_HIGHMEM */
 
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
index 972a8e8..86010fc 100644
--- a/arch/powerpc/mm/mmap.c
+++ b/arch/powerpc/mm/mmap.c
@@ -24,6 +24,7 @@
 
 #include <linux/personality.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 
 /*
  * Top of mmap area (just below the process stack).
diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c
index 792086b..cc32ba4 100644
--- a/arch/powerpc/mm/mmu_context_32.c
+++ b/arch/powerpc/mm/mmu_context_32.c
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 2558c34..c94a64f 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -40,8 +39,8 @@
 extern unsigned long ioremap_base;
 extern unsigned int rtas_data, rtas_size;
 
-struct _PTE;
-extern struct _PTE *Hash, *Hash_end;
+struct hash_pte;
+extern struct hash_pte *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 
 extern unsigned int num_tlbcam_entries;
@@ -90,16 +89,4 @@
 	else
 		_tlbie(va);
 }
-#else /* CONFIG_PPC64 */
-/* imalloc region types */
-#define IM_REGION_UNUSED	0x1
-#define IM_REGION_SUBSET	0x2
-#define IM_REGION_EXISTS	0x4
-#define IM_REGION_OVERLAP	0x8
-#define IM_REGION_SUPERSET	0x10
-
-extern struct vm_struct * im_get_free_area(unsigned long size);
-extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-				      int region_type);
-extern void im_free(void *addr);
 #endif
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index d8232b7..6448872 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -37,7 +36,6 @@
 unsigned long ioremap_base;
 unsigned long ioremap_bot;
 EXPORT_SYMBOL(ioremap_bot);	/* aka VMALLOC_END */
-int io_bat_index;
 
 #if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
 #define HAVE_BATS	1
@@ -93,7 +91,7 @@
 	free_pages((unsigned long)pgd, PGDIR_ORDER);
 }
 
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
 	pte_t *pte;
 	extern int mem_init_done;
@@ -300,51 +298,6 @@
 	}
 }
 
-/* is x a power of 4? */
-#define is_power_of_4(x)	is_power_of_2(x) && (ffs(x) & 1)
-
-/*
- * Set up a mapping for a block of I/O.
- * virt, phys, size must all be page-aligned.
- * This should only be called before ioremap is called.
- */
-void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
-			     unsigned int size, int flags)
-{
-	int i;
-
-	if (virt > KERNELBASE && virt < ioremap_bot)
-		ioremap_bot = ioremap_base = virt;
-
-#ifdef HAVE_BATS
-	/*
-	 * Use a BAT for this if possible...
-	 */
-	if (io_bat_index < 2 && is_power_of_2(size)
-	    && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
-		setbat(io_bat_index, virt, phys, size, flags);
-		++io_bat_index;
-		return;
-	}
-#endif /* HAVE_BATS */
-
-#ifdef HAVE_TLBCAM
-	/*
-	 * Use a CAM for this if possible...
-	 */
-	if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
-	    && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
-		settlbcam(tlbcam_index, virt, phys, size, flags, 0);
-		++tlbcam_index;
-		return;
-	}
-#endif /* HAVE_TLBCAM */
-
-	/* No BATs available, put it in the page tables. */
-	for (i = 0; i < size; i += PAGE_SIZE)
-		map_page(virt + i, phys + i, flags);
-}
-
 /* Scan the real Linux page tables and return a PTE pointer for
  * a virtual address in a context.
  * Returns true (1) if PTE was found, zero otherwise.  The pointer to
@@ -379,82 +332,6 @@
         return(retval);
 }
 
-/* Find physical address for this virtual address.  Normally used by
- * I/O functions, but anyone can call it.
- */
-unsigned long iopa(unsigned long addr)
-{
-	unsigned long pa;
-
-	/* I don't know why this won't work on PMacs or CHRP.  It
-	 * appears there is some bug, or there is some implicit
-	 * mapping done not properly represented by BATs or in page
-	 * tables.......I am actively working on resolving this, but
-	 * can't hold up other stuff.  -- Dan
-	 */
-	pte_t *pte;
-	struct mm_struct *mm;
-
-	/* Check the BATs */
-	pa = v_mapped_by_bats(addr);
-	if (pa)
-		return pa;
-
-	/* Allow mapping of user addresses (within the thread)
-	 * for DMA if necessary.
-	 */
-	if (addr < TASK_SIZE)
-		mm = current->mm;
-	else
-		mm = &init_mm;
-
-	pa = 0;
-	if (get_pteptr(mm, addr, &pte, NULL)) {
-		pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
-		pte_unmap(pte);
-	}
-
-	return(pa);
-}
-
-/* This is will find the virtual address for a physical one....
- * Swiped from APUS, could be dangerous :-).
- * This is only a placeholder until I really find a way to make this
- * work.  -- Dan
- */
-unsigned long
-mm_ptov (unsigned long paddr)
-{
-	unsigned long ret;
-#if 0
-	if (paddr < 16*1024*1024)
-		ret = ZTWO_VADDR(paddr);
-	else {
-		int i;
-
-		for (i = 0; i < kmap_chunk_count;){
-			unsigned long phys = kmap_chunks[i++];
-			unsigned long size = kmap_chunks[i++];
-			unsigned long virt = kmap_chunks[i++];
-			if (paddr >= phys
-			    && paddr < (phys + size)){
-				ret = virt + paddr - phys;
-				goto exit;
-			}
-		}
-	
-		ret = (unsigned long) __va(paddr);
-	}
-exit:
-#ifdef DEBUGPV
-	printk ("PTOV(%lx)=%lx\n", paddr, ret);
-#endif
-#else
-	ret = (unsigned long)paddr + KERNELBASE;
-#endif
-	return ret;
-}
-
 #ifdef CONFIG_DEBUG_PAGEALLOC
 
 static int __change_page_attr(struct page *page, pgprot_t prot)
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index ad6e135..3dfd10d 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -7,7 +7,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@samba.org)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -34,41 +33,27 @@
 #include <linux/stddef.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
-#include <linux/idr.h>
-#include <linux/nodemask.h>
-#include <linux/module.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
 #include <asm/prom.h>
-#include <asm/lmb.h>
-#include <asm/rtas.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/uaccess.h>
 #include <asm/smp.h>
 #include <asm/machdep.h>
 #include <asm/tlb.h>
-#include <asm/eeh.h>
 #include <asm/processor.h>
-#include <asm/mmzone.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
 #include <asm/system.h>
-#include <asm/iommu.h>
 #include <asm/abs_addr.h>
-#include <asm/vdso.h>
 #include <asm/firmware.h>
 
 #include "mmu_decl.h"
 
-unsigned long ioremap_bot = IMALLOC_BASE;
-static unsigned long phbs_io_bot = PHBS_IO_BASE;
+unsigned long ioremap_bot = IOREMAP_BASE;
 
 /*
  * map_io_page currently only called by __ioremap
@@ -102,8 +87,8 @@
 		 * entry in the hardware page table.
 		 *
 		 */
-		if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
-				      mmu_io_psize)) {
+		if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE,
+				      pa, flags, mmu_io_psize)) {
 			printk(KERN_ERR "Failed to do bolted mapping IO "
 			       "memory at %016lx !\n", pa);
 			return -ENOMEM;
@@ -113,8 +98,11 @@
 }
 
 
-static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
-			    unsigned long ea, unsigned long size,
+/**
+ * __ioremap_at - Low level function to establish the page tables
+ *                for an IO mapping
+ */
+void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
 			    unsigned long flags)
 {
 	unsigned long i;
@@ -122,17 +110,35 @@
 	if ((flags & _PAGE_PRESENT) == 0)
 		flags |= pgprot_val(PAGE_KERNEL);
 
+	WARN_ON(pa & ~PAGE_MASK);
+	WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+	WARN_ON(size & ~PAGE_MASK);
+
 	for (i = 0; i < size; i += PAGE_SIZE)
-		if (map_io_page(ea+i, pa+i, flags))
+		if (map_io_page((unsigned long)ea+i, pa+i, flags))
 			return NULL;
 
-	return (void __iomem *) (ea + (addr & ~PAGE_MASK));
+	return (void __iomem *)ea;
+}
+
+/**
+ * __iounmap_from - Low level function to tear down the page tables
+ *                  for an IO mapping. This is used for mappings that
+ *                  are manipulated manually, like partial unmapping of
+ *                  PCI IOs or ISA space.
+ */
+void __iounmap_at(void *ea, unsigned long size)
+{
+	WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+	WARN_ON(size & ~PAGE_MASK);
+
+	unmap_kernel_range((unsigned long)ea, size);
 }
 
 void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
 			 unsigned long flags)
 {
-	unsigned long pa, ea;
+	phys_addr_t paligned;
 	void __iomem *ret;
 
 	/*
@@ -144,27 +150,30 @@
 	 * IMALLOC_END
 	 * 
 	 */
-	pa = addr & PAGE_MASK;
-	size = PAGE_ALIGN(addr + size) - pa;
+	paligned = addr & PAGE_MASK;
+	size = PAGE_ALIGN(addr + size) - paligned;
 
-	if ((size == 0) || (pa == 0))
+	if ((size == 0) || (paligned == 0))
 		return NULL;
 
 	if (mem_init_done) {
 		struct vm_struct *area;
-		area = im_get_free_area(size);
+
+		area = __get_vm_area(size, VM_IOREMAP,
+				     ioremap_bot, IOREMAP_END);
 		if (area == NULL)
 			return NULL;
-		ea = (unsigned long)(area->addr);
-		ret = __ioremap_com(addr, pa, ea, size, flags);
+		ret = __ioremap_at(paligned, area->addr, size, flags);
 		if (!ret)
-			im_free(area->addr);
+			vunmap(area->addr);
 	} else {
-		ea = ioremap_bot;
-		ret = __ioremap_com(addr, pa, ea, size, flags);
+		ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags);
 		if (ret)
 			ioremap_bot += size;
 	}
+
+	if (ret)
+		ret += addr & ~PAGE_MASK;
 	return ret;
 }
 
@@ -187,62 +196,9 @@
 }
 
 
-#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
-
-int __ioremap_explicit(phys_addr_t pa, unsigned long ea,
-		       unsigned long size, unsigned long flags)
-{
-	struct vm_struct *area;
-	void __iomem *ret;
-	
-	/* For now, require page-aligned values for pa, ea, and size */
-	if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
-	    !IS_PAGE_ALIGNED(size)) {
-		printk(KERN_ERR	"unaligned value in %s\n", __FUNCTION__);
-		return 1;
-	}
-	
-	if (!mem_init_done) {
-		/* Two things to consider in this case:
-		 * 1) No records will be kept (imalloc, etc) that the region
-		 *    has been remapped
-		 * 2) It won't be easy to iounmap() the region later (because
-		 *    of 1)
-		 */
-		;
-	} else {
-		area = im_get_area(ea, size,
-			IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
-		if (area == NULL) {
-			/* Expected when PHB-dlpar is in play */
-			return 1;
-		}
-		if (ea != (unsigned long) area->addr) {
-			printk(KERN_ERR "unexpected addr return from "
-			       "im_get_area\n");
-			return 1;
-		}
-	}
-	
-	ret = __ioremap_com(pa, pa, ea, size, flags);
-	if (ret == NULL) {
-		printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
-		return 1;
-	}
-	if (ret != (void *) ea) {
-		printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
-		return 1;
-	}
-
-	return 0;
-}
-
 /*  
  * Unmap an IO region and remove it from imalloc'd list.
  * Access to IO memory should be serialized by driver.
- * This code is modeled after vmalloc code - unmap_vm_area()
- *
- * XXX	what about calls before mem_init_done (ie python_countermeasures())
  */
 void __iounmap(volatile void __iomem *token)
 {
@@ -251,9 +207,14 @@
 	if (!mem_init_done)
 		return;
 	
-	addr = (void *) ((unsigned long __force) token & PAGE_MASK);
-
-	im_free(addr);
+	addr = (void *) ((unsigned long __force)
+			 PCI_FIX_ADDR(token) & PAGE_MASK);
+	if ((unsigned long)addr < ioremap_bot) {
+		printk(KERN_WARNING "Attempt to iounmap early bolted mapping"
+		       " at 0x%p\n", addr);
+		return;
+	}
+	vunmap(addr);
 }
 
 void iounmap(volatile void __iomem *token)
@@ -264,77 +225,8 @@
 		__iounmap(token);
 }
 
-static int iounmap_subset_regions(unsigned long addr, unsigned long size)
-{
-	struct vm_struct *area;
-
-	/* Check whether subsets of this region exist */
-	area = im_get_area(addr, size, IM_REGION_SUPERSET);
-	if (area == NULL)
-		return 1;
-
-	while (area) {
-		iounmap((void __iomem *) area->addr);
-		area = im_get_area(addr, size,
-				IM_REGION_SUPERSET);
-	}
-
-	return 0;
-}
-
-int __iounmap_explicit(volatile void __iomem *start, unsigned long size)
-{
-	struct vm_struct *area;
-	unsigned long addr;
-	int rc;
-	
-	addr = (unsigned long __force) start & PAGE_MASK;
-
-	/* Verify that the region either exists or is a subset of an existing
-	 * region.  In the latter case, split the parent region to create 
-	 * the exact region 
-	 */
-	area = im_get_area(addr, size, 
-			    IM_REGION_EXISTS | IM_REGION_SUBSET);
-	if (area == NULL) {
-		/* Determine whether subset regions exist.  If so, unmap */
-		rc = iounmap_subset_regions(addr, size);
-		if (rc) {
-			printk(KERN_ERR
-			       "%s() cannot unmap nonexistent range 0x%lx\n",
- 				__FUNCTION__, addr);
-			return 1;
-		}
-	} else {
-		iounmap((void __iomem *) area->addr);
-	}
-	/*
-	 * FIXME! This can't be right:
-	iounmap(area->addr);
-	 * Maybe it should be "iounmap(area);"
-	 */
-	return 0;
-}
-
 EXPORT_SYMBOL(ioremap);
 EXPORT_SYMBOL(ioremap_flags);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(__iounmap);
-
-static DEFINE_SPINLOCK(phb_io_lock);
-
-void __iomem * reserve_phb_iospace(unsigned long size)
-{
-	void __iomem *virt_addr;
-		
-	if (phbs_io_bot >= IMALLOC_BASE) 
-		panic("reserve_phb_iospace(): phb io space overflow\n");
-			
-	spin_lock(&phb_io_lock);
-	virt_addr = (void __iomem *) phbs_io_bot;
-	phbs_io_bot += size;
-	spin_unlock(&phb_io_lock);
-
-	return virt_addr;
-}
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index ec1421a..5c45d47 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -35,12 +34,12 @@
 
 #include "mmu_decl.h"
 
-PTE *Hash, *Hash_end;
+struct hash_pte *Hash, *Hash_end;
 unsigned long Hash_size, Hash_mask;
 unsigned long _SDR1;
 
 union ubat {			/* BAT register values to be loaded */
-	BAT	bat;
+	struct ppc_bat bat;
 	u32	word[2];
 } BATS[8][2];			/* 8 pairs of IBAT, DBAT */
 
@@ -245,7 +244,7 @@
 	cacheable_memzero(Hash, Hash_size);
 	_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
 
-	Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
+	Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);
 
 	printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
 	       total_memory >> 20, Hash_size >> 10, Hash);
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 132c6bc..28492bb 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -55,7 +55,7 @@
 		for (entry = 0; entry < 8; entry++, ste++) {
 			if (!(ste->esid_data & STE_ESID_V)) {
 				ste->vsid_data = vsid_data;
-				asm volatile("eieio":::"memory");
+				eieio();
 				ste->esid_data = esid_data;
 				return (global_entry | entry);
 			}
@@ -101,7 +101,7 @@
 	asm volatile("sync" : : : "memory");    /* Order update */
 
 	castout_ste->vsid_data = vsid_data;
-	asm volatile("eieio" : : : "memory");   /* Order update */
+	eieio();				/* Order update */
 	castout_ste->esid_data = esid_data;
 
 	asm volatile("slbie  %0" : : "r" (old_esid << SID_SHIFT));
diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c
index 6a69417..06c7e77 100644
--- a/arch/powerpc/mm/tlb_32.c
+++ b/arch/powerpc/mm/tlb_32.c
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index 2bfc4d7..cbd34fc 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -239,3 +238,59 @@
 	pte_free_submit(*batchp);
 	*batchp = NULL;
 }
+
+/**
+ * __flush_hash_table_range - Flush all HPTEs for a given address range
+ *                            from the hash table (and the TLB). But keeps
+ *                            the linux PTEs intact.
+ *
+ * @mm		: mm_struct of the target address space (generally init_mm)
+ * @start	: starting address
+ * @end         : ending address (not included in the flush)
+ *
+ * This function is mostly to be used by some IO hotplug code in order
+ * to remove all hash entries from a given address range used to map IO
+ * space on a removed PCI-PCI bidge without tearing down the full mapping
+ * since 64K pages may overlap with other bridges when using 64K pages
+ * with 4K HW pages on IO space.
+ *
+ * Because of that usage pattern, it's only available with CONFIG_HOTPLUG
+ * and is implemented for small size rather than speed.
+ */
+#ifdef CONFIG_HOTPLUG
+
+void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+			      unsigned long end)
+{
+	unsigned long flags;
+
+	start = _ALIGN_DOWN(start, PAGE_SIZE);
+	end = _ALIGN_UP(end, PAGE_SIZE);
+
+	BUG_ON(!mm->pgd);
+
+	/* Note: Normally, we should only ever use a batch within a
+	 * PTE locked section. This violates the rule, but will work
+	 * since we don't actually modify the PTEs, we just flush the
+	 * hash while leaving the PTEs intact (including their reference
+	 * to being hashed). This is not the most performance oriented
+	 * way to do things but is fine for our needs here.
+	 */
+	local_irq_save(flags);
+	arch_enter_lazy_mmu_mode();
+	for (; start < end; start += PAGE_SIZE) {
+		pte_t *ptep = find_linux_pte(mm->pgd, start);
+		unsigned long pte;
+
+		if (ptep == NULL)
+			continue;
+		pte = pte_val(*ptep);
+		if (!(pte & _PAGE_HASHPTE))
+			continue;
+		hpte_need_flush(mm, start, ptep, pte, 0);
+	}
+	arch_leave_lazy_mmu_mode();
+	local_irq_restore(flags);
+}
+
+#endif /* CONFIG_HOTPLUG */
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index fe597a1..a7c206b 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Added mmcra[slot] support:
+ * Copyright (C) 2006-2007 Will Schmidt <willschm@us.ibm.com>, IBM
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -181,11 +183,17 @@
  * On GQ and newer the MMCRA stores the HV and PR bits at the time
  * the SIAR was sampled. We use that to work out if the SIAR was sampled in
  * the hypervisor, our exception vectors or RTAS.
+ * If the MMCRA_SAMPLE_ENABLE bit is set, we can use the MMCRA[slot] bits
+ * to more accurately identify the address of the sampled instruction. The
+ * mmcra[slot] bits represent the slot number of a sampled instruction
+ * within an instruction group.  The slot will contain a value between 1
+ * and 5 if MMCRA_SAMPLE_ENABLE is set, otherwise 0.
  */
 static unsigned long get_pc(struct pt_regs *regs)
 {
 	unsigned long pc = mfspr(SPRN_SIAR);
 	unsigned long mmcra;
+	unsigned long slot;
 
 	/* Cant do much about it */
 	if (!cur_cpu_spec->oprofile_mmcra_sihv)
@@ -193,6 +201,12 @@
 
 	mmcra = mfspr(SPRN_MMCRA);
 
+	if (mmcra & MMCRA_SAMPLE_ENABLE) {
+		slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT);
+		if (slot > 1)
+			pc += 4 * (slot - 1);
+	}
+
 	/* Were we in the hypervisor? */
 	if (firmware_has_feature(FW_FEATURE_LPAR) &&
 	    (mmcra & cur_cpu_spec->oprofile_mmcra_sihv))
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index f591a9f..4be6e7a 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -54,7 +54,7 @@
 	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 	    | (((bus->number - hose->first_busno) & 0xff) << 16)
-	    | (hose->index << 24);
+	    | (hose->global_number << 24);
 	int ret = -1;
 	int rval;
 
@@ -69,7 +69,7 @@
 	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 	    | (((bus->number - hose->first_busno) & 0xff) << 16)
-	    | (hose->index << 24);
+	    | (hose->global_number << 24);
 	int rval;
 
 	rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
@@ -83,7 +83,7 @@
 };
 
 
-void __init efika_pcisetup(void)
+static void __init efika_pcisetup(void)
 {
 	const int *bus_range;
 	int len;
@@ -128,7 +128,7 @@
 	printk(" controlled by %s\n", pcictrl->full_name);
 	printk("\n");
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(of_node_get(pcictrl));
 	if (!hose) {
 		printk(KERN_WARNING EFIKA_PLATFORM_NAME
 		       ": Can't allocate PCI controller structure for %s\n",
@@ -136,7 +136,6 @@
 		return;
 	}
 
-	hose->arch_data = of_node_get(pcictrl);
 	hose->first_busno = bus_range[0];
 	hose->last_busno = bus_range[1];
 	hose->ops = &rtas_pci_ops;
@@ -145,7 +144,7 @@
 }
 
 #else
-void __init efika_pcisetup(void)
+static void __init efika_pcisetup(void)
 {}
 #endif
 
@@ -252,6 +251,8 @@
 	.progress		= rtas_progress,
 	.get_boot_time		= rtas_get_boot_time,
 	.calibrate_decr		= generic_calibrate_decr,
+#ifdef CONFIG_PCI
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
+#endif
 };
 
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 1cfc00d..5c46e89 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -156,7 +156,7 @@
 
 }
 
-void lite5200_show_cpuinfo(struct seq_file *m)
+static void lite5200_show_cpuinfo(struct seq_file *m)
 {
 	struct device_node* np = of_find_all_nodes(NULL);
 	const char *model = NULL;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index 34d34a2..4c6c82a 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -112,18 +112,18 @@
 	u32 value;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
 	out_be32(hose->cfg_addr,
 		(1 << 31) |
-		((bus->number - hose->bus_offset) << 16) |
+		(bus->number << 16) |
 		(devfn << 8) |
 		(offset & 0xfc));
 	mb();
 
 #if defined(CONFIG_PPC_MPC5200_BUGFIX)
-	if (bus->number != hose->bus_offset) {
+	if (bus->number) {
 		/* workaround for the bug 435 of the MPC5200 (L25R);
 		 * Don't do 32 bits config access during type-1 cycles */
 		switch (len) {
@@ -169,18 +169,18 @@
 	u32 value, mask;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
 	out_be32(hose->cfg_addr,
 		(1 << 31) |
-		((bus->number - hose->bus_offset) << 16) |
+		(bus->number << 16) |
 		(devfn << 8) |
 		(offset & 0xfc));
 	mb();
 
 #if defined(CONFIG_PPC_MPC5200_BUGFIX)
-	if (bus->number != hose->bus_offset) {
+	if (bus->number) {
 		/* workaround for the bug 435 of the MPC5200 (L25R);
 		 * Don't do 32 bits config access during type-1 cycles */
 		switch (len) {
@@ -385,17 +385,13 @@
 	 * tree are needed to configure the 52xx PCI controller.  Rather
 	 * than parse the tree here, let pci_process_bridge_OF_ranges()
 	 * do it for us and extract the values after the fact */
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(node);
 	if (!hose)
 		return -ENOMEM;
 
-	hose->arch_data = node;
-	hose->set_cfg_type = 1;
-
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-	hose->bus_offset = 0;
 	hose->ops = &mpc52xx_pci_ops;
 
 	pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
index fd40044..ee2e763 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -9,8 +9,8 @@
 
 
 /* these are defined in mpc52xx_sleep.S, and only used here */
-extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs,
-		struct mpc52xx_cdm *, struct mpc52xx_intr *);
+extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs,
+		struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*);
 extern void mpc52xx_ds_sram(void);
 extern const long mpc52xx_ds_sram_size;
 extern void mpc52xx_ds_cached(void);
@@ -21,7 +21,7 @@
 static struct mpc52xx_cdm __iomem *cdm;
 static struct mpc52xx_intr __iomem *intr;
 static struct mpc52xx_gpio_wkup __iomem *gpiow;
-static void *sram;
+static void __iomem *sram;
 static int sram_size;
 
 struct mpc52xx_suspend mpc52xx_suspend;
@@ -100,7 +100,7 @@
 	u32 clk_enables;
 	u32 msr, hid0;
 	u32 intr_main_mask;
-	void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
+	void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500;
 	unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
 	char saved_0x500[mpc52xx_ds_cached_size];
 
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index de7fce9..89fde43 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -1,5 +1,5 @@
 choice
-	prompt "Machine Type"
+	prompt "82xx Board Type"
 	depends on PPC_82xx
 	default MPC82xx_ADS
 
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
index 47cb09f..da20832 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -49,7 +49,7 @@
 #include <linux/fs_enet_pd.h>
 
 #include <sysdev/fsl_soc.h>
-#include <../sysdev/cpm2_pic.h>
+#include <sysdev/cpm2_pic.h>
 
 #include "pq2ads.h"
 
@@ -507,7 +507,8 @@
 	return;
 }
 
-static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
+static int m82xx_pci_exclude_device(struct pci_controller *hose,
+				    u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -515,7 +516,7 @@
 		return PCIBIOS_SUCCESSFUL;
 }
 
-void __init add_bridge(struct device_node *np)
+static void __init mpc82xx_add_bridge(struct device_node *np)
 {
 	int len;
 	struct pci_controller *hose;
@@ -542,19 +543,13 @@
 
 	pci_assign_all_buses = 1;
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(np);
 
 	if (!hose)
 		return;
 
-	hose->arch_data = np;
-	hose->set_cfg_type = 1;
-
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
-	hose->bus_offset = 0;
-
-	hose->set_cfg_type = 1;
 
 	setup_indirect_pci(hose,
 			   r.start + offsetof(pci_cpm2_t, pci_cfg_addr),
@@ -584,7 +579,7 @@
 #ifdef CONFIG_PCI
 	ppc_md.pci_exclude_device = m82xx_pci_exclude_device;
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc82xx_add_bridge(np);
 
 	of_node_put(np);
 #endif
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 19cafdf..ec305f1 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -1,5 +1,5 @@
 choice
-	prompt "Machine Type"
+	prompt "83xx Board Type"
 	depends on PPC_83xx
 	default MPC834x_MDS
 
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 31a91b5..5a98f88 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for the PowerPC 83xx linux kernel.
 #
-obj-y				:= misc.o
+obj-y				:= misc.o usb.o
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_MPC8313_RDB)	+= mpc8313_rdb.o
 obj-$(CONFIG_MPC832x_RDB)	+= mpc832x_rdb.o
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 96970ac..3edfe17 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -28,11 +28,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -49,10 +44,11 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
+	mpc831x_usb_cfg();
 }
 
 void __init mpc8313_rdb_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 94843ed..b39cb52 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -49,11 +49,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static u8 *bcsr_regs = NULL;
 
 /* ************************************************************************
@@ -80,7 +75,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index 3db68b7..b2b28a4 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -32,11 +32,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -53,7 +48,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 40a0194..47ba544 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -38,11 +38,6 @@
 
 #include "mpc83xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -59,10 +54,12 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
+
+	mpc834x_usb_cfg();
 }
 
 static void __init mpc834x_itx_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 10394b2..4c9ff9c 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -38,61 +38,17 @@
 
 #include "mpc83xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 #define BCSR5_INT_USB		0x02
-/* Note: This is only for PB, not for PB+PIB
- * On PB only port0 is connected using ULPI */
-static int mpc834x_usb_cfg(void)
+static int mpc834xemds_usb_cfg(void)
 {
-	unsigned long sccr, sicrl;
-	void __iomem *immap;
+	struct device_node *np;
 	void __iomem *bcsr_regs = NULL;
 	u8 bcsr5;
-	struct device_node *np = NULL;
-	int port0_is_dr = 0;
 
-	if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL)
-		port0_is_dr = 1;
-	if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){
-		if (port0_is_dr) {
-			printk(KERN_WARNING
-				"There is only one USB port on PB board! \n");
-			return -1;
-		} else if (!port0_is_dr)
-			/* No usb port enabled */
-			return -1;
-	}
-
-	immap = ioremap(get_immrbase(), 0x1000);
-	if (!immap)
-		return -1;
-
-	/* Configure clock */
-	sccr = in_be32(immap + MPC83XX_SCCR_OFFS);
-	if (port0_is_dr)
-		sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
-	else
-		sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
-	out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
-
-	/* Configure Pin */
-	sicrl = in_be32(immap + MPC83XX_SICRL_OFFS);
-	/* set port0 only */
-	if (port0_is_dr)
-		sicrl |= MPC83XX_SICRL_USB0;
-	else
-		sicrl &= ~(MPC83XX_SICRL_USB0);
-	out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
-
-	iounmap(immap);
-
+	mpc834x_usb_cfg();
 	/* Map BCSR area */
 	np = of_find_node_by_name(NULL, "bcsr");
-	if (np != 0) {
+	if (np) {
 		struct resource res;
 
 		of_address_to_resource(np, 0, &res);
@@ -129,12 +85,12 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
-	mpc834x_usb_cfg();
+	mpc834xemds_usb_cfg();
 }
 
 static void __init mpc834x_mds_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index bceeff8..0e615fd 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -55,11 +55,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static u8 *bcsr_regs = NULL;
 
 /* ************************************************************************
@@ -86,7 +81,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc83xx_add_bridge(np);
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 9cd03b5..589ee55 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -3,9 +3,11 @@
 
 #include <linux/init.h>
 #include <linux/device.h>
+#include <asm/pci-bridge.h>
 
 /* System Clock Control Register */
 #define MPC83XX_SCCR_OFFS          0xA08
+#define MPC83XX_SCCR_USB_MASK      0x00f00000
 #define MPC83XX_SCCR_USB_MPHCM_11  0x00c00000
 #define MPC83XX_SCCR_USB_MPHCM_01  0x00400000
 #define MPC83XX_SCCR_USB_MPHCM_10  0x00800000
@@ -15,21 +17,43 @@
 
 /* system i/o configuration register low */
 #define MPC83XX_SICRL_OFFS         0x114
-#define MPC83XX_SICRL_USB0         0x40000000
-#define MPC83XX_SICRL_USB1         0x20000000
+#define MPC834X_SICRL_USB_MASK     0x60000000
+#define MPC834X_SICRL_USB0         0x40000000
+#define MPC834X_SICRL_USB1         0x20000000
+#define MPC831X_SICRL_USB_MASK     0x00000c00
+#define MPC831X_SICRL_USB_ULPI     0x00000800
 
 /* system i/o configuration register high */
 #define MPC83XX_SICRH_OFFS         0x118
-#define MPC83XX_SICRH_USB_UTMI     0x00020000
+#define MPC834X_SICRH_USB_UTMI     0x00020000
+#define MPC831X_SICRH_USB_MASK     0x000000e0
+#define MPC831X_SICRH_USB_ULPI     0x000000a0
+
+/* USB Control Register */
+#define FSL_USB2_CONTROL_OFFS      0x500
+#define CONTROL_UTMI_PHY_EN        0x00000200
+#define CONTROL_REFSEL_48MHZ       0x00000080
+#define CONTROL_PHY_CLK_SEL_ULPI   0x00000400
+#define CONTROL_OTG_PORT           0x00000020
+
+/* USB PORTSC Registers */
+#define FSL_USB2_PORTSC1_OFFS      0x184
+#define FSL_USB2_PORTSC2_OFFS      0x188
+#define PORTSCX_PTW_16BIT          0x10000000
+#define PORTSCX_PTS_UTMI           0x00000000
+#define PORTSCX_PTS_ULPI           0x80000000
 
 /*
  * Declaration for the various functions exported by the
  * mpc83xx_* files. Mostly for use by mpc83xx_setup
  */
 
-extern int add_bridge(struct device_node *dev);
-extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern int mpc83xx_add_bridge(struct device_node *dev);
+extern int mpc83xx_exclude_device(struct pci_controller *hose,
+				  u_char bus, u_char devfn);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
+extern int mpc834x_usb_cfg(void);
+extern int mpc831x_usb_cfg(void);
 
 #endif				/* __MPC83XX_H__ */
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 774457d0..c0e2b89 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -33,19 +33,14 @@
 #define DBG(x...)
 #endif
 
-int mpc83xx_pci2_busno;
-
-int mpc83xx_exclude_device(u_char bus, u_char devfn)
+int mpc83xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
 {
-	if (bus == 0 && PCI_SLOT(devfn) == 0)
+	if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (mpc83xx_pci2_busno)
-		if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0)
-			return PCIBIOS_DEVICE_NOT_FOUND;
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int __init add_bridge(struct device_node *dev)
+int __init mpc83xx_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -66,11 +61,10 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	hose = pcibios_alloc_controller();
+	pci_assign_all_buses = 1;
+	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
 
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -86,8 +80,6 @@
 	if ((rsrc.start & 0xfffff) == 0x8600) {
 		setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384);
 		primary = 0;
-		hose->bus_offset = hose->first_busno;
-		mpc83xx_pci2_busno = hose->first_busno;
 	}
 
 	printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
new file mode 100644
index 0000000..e7fdf01
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -0,0 +1,181 @@
+/*
+ * Freescale 83xx USB SOC setup code
+ *
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
+ * Author: Li Yang
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc83xx.h"
+
+
+#ifdef CONFIG_MPC834x
+int mpc834x_usb_cfg(void)
+{
+	unsigned long sccr, sicrl, sicrh;
+	void __iomem *immap;
+	struct device_node *np = NULL;
+	int port0_is_dr = 0, port1_is_dr = 0;
+	const void *prop, *dr_mode;
+
+	immap = ioremap(get_immrbase(), 0x1000);
+	if (!immap)
+		return -ENOMEM;
+
+	/* Read registers */
+	/* Note: DR and MPH must use the same clock setting in SCCR */
+	sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK;
+	sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;
+	sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;
+
+	np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+	if (np) {
+		sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
+
+		prop = of_get_property(np, "phy_type", NULL);
+		if (prop && (!strcmp(prop, "utmi") ||
+					!strcmp(prop, "utmi_wide"))) {
+			sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
+			sicrh |= MPC834X_SICRH_USB_UTMI;
+			port1_is_dr = 1;
+		} else if (prop && !strcmp(prop, "serial")) {
+			dr_mode = of_get_property(np, "dr_mode", NULL);
+			if (dr_mode && !strcmp(dr_mode, "otg")) {
+				sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
+				port1_is_dr = 1;
+			} else {
+				sicrl |= MPC834X_SICRL_USB0;
+			}
+		} else if (prop && !strcmp(prop, "ulpi")) {
+			sicrl |= MPC834X_SICRL_USB0;
+		} else {
+			printk(KERN_WARNING "834x USB PHY type not supported\n");
+		}
+		port0_is_dr = 1;
+		of_node_put(np);
+	}
+	np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph");
+	if (np) {
+		sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
+
+		prop = of_get_property(np, "port0", NULL);
+		if (prop) {
+			if (port0_is_dr)
+				printk(KERN_WARNING
+					"834x USB port0 can't be used by both DR and MPH!\n");
+			sicrl |= MPC834X_SICRL_USB0;
+		}
+		prop = of_get_property(np, "port1", NULL);
+		if (prop) {
+			if (port1_is_dr)
+				printk(KERN_WARNING
+					"834x USB port1 can't be used by both DR and MPH!\n");
+			sicrl |= MPC834X_SICRL_USB1;
+		}
+		of_node_put(np);
+	}
+
+	/* Write back */
+	out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
+	out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
+	out_be32(immap + MPC83XX_SICRH_OFFS, sicrh);
+
+	iounmap(immap);
+	return 0;
+}
+#endif /* CONFIG_MPC834x */
+
+#ifdef CONFIG_PPC_MPC831x
+int mpc831x_usb_cfg(void)
+{
+	u32 temp;
+	void __iomem *immap, *usb_regs;
+	struct device_node *np = NULL;
+	const void *prop;
+	struct resource res;
+	int ret = 0;
+#ifdef CONFIG_USB_OTG
+	const void *dr_mode;
+#endif
+
+	np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+	if (!np)
+		return -ENODEV;
+	prop = of_get_property(np, "phy_type", NULL);
+
+	/* Map IMMR space for pin and clock settings */
+	immap = ioremap(get_immrbase(), 0x1000);
+	if (!immap) {
+		of_node_put(np);
+		return -ENOMEM;
+	}
+
+	/* Configure clock */
+	temp = in_be32(immap + MPC83XX_SCCR_OFFS);
+	temp &= ~MPC83XX_SCCR_USB_MASK;
+	temp |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
+	out_be32(immap + MPC83XX_SCCR_OFFS, temp);
+
+	/* Configure pin mux for ULPI.  There is no pin mux for UTMI */
+	if (!strcmp(prop, "ulpi")) {
+		temp = in_be32(immap + MPC83XX_SICRL_OFFS);
+		temp &= ~MPC831X_SICRL_USB_MASK;
+		temp |= MPC831X_SICRL_USB_ULPI;
+		out_be32(immap + MPC83XX_SICRL_OFFS, temp);
+
+		temp = in_be32(immap + MPC83XX_SICRH_OFFS);
+		temp &= ~MPC831X_SICRH_USB_MASK;
+		temp |= MPC831X_SICRH_USB_ULPI;
+		out_be32(immap + MPC83XX_SICRH_OFFS, temp);
+	}
+
+	iounmap(immap);
+
+	/* Map USB SOC space */
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret) {
+		of_node_put(np);
+		return ret;
+	}
+	usb_regs = ioremap(res.start, res.end - res.start + 1);
+
+	/* Using on-chip PHY */
+	if (!strcmp(prop, "utmi_wide") ||
+			!strcmp(prop, "utmi")) {
+		/* Set UTMI_PHY_EN, REFSEL to 48MHZ */
+		out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
+				CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ);
+	/* Using external UPLI PHY */
+	} else if (!strcmp(prop, "ulpi")) {
+		/* Set PHY_CLK_SEL to ULPI */
+		temp = CONTROL_PHY_CLK_SEL_ULPI;
+#ifdef CONFIG_USB_OTG
+		/* Set OTG_PORT */
+		dr_mode = of_get_property(np, "dr_mode", NULL);
+		if (dr_mode && !strcmp(dr_mode, "otg"))
+			temp |= CONTROL_OTG_PORT;
+#endif /* CONFIG_USB_OTG */
+		out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);
+	} else {
+		printk(KERN_WARNING "831x USB PHY type not supported\n");
+		ret = -EINVAL;
+	}
+
+	iounmap(usb_regs);
+	of_node_put(np);
+	return ret;
+}
+#endif /* CONFIG_PPC_MPC831x */
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c
index 3e62fcb..4fe376e 100644
--- a/arch/powerpc/platforms/85xx/misc.c
+++ b/arch/powerpc/platforms/85xx/misc.c
@@ -13,11 +13,43 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+static __be32 __iomem *rstcr;
 
 extern void abort(void);
 
+static int __init mpc85xx_rstcr(void)
+{
+	struct device_node *np;
+	np = of_find_node_by_name(NULL, "global-utilities");
+	if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
+		const u32 *prop = of_get_property(np, "reg", NULL);
+		if (prop) {
+			/* map reset control register
+			 * 0xE00B0 is offset of reset control register
+			 */
+			rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
+			if (!rstcr)
+				printk (KERN_EMERG "Error: reset control "
+						"register not mapped!\n");
+		}
+	} else
+		printk (KERN_INFO "rstcr compatible register does not exist!\n");
+	if (np)
+		of_node_put(np);
+	return 0;
+}
+
+arch_initcall(mpc85xx_rstcr);
+
 void mpc85xx_restart(char *cmd)
 {
 	local_irq_disable();
+	if (rstcr)
+		/* set reset control register */
+		out_be32(rstcr, 0x2);	/* HRESET_REQ */
 	abort();
 }
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c
index bec84ff..6fb90aa 100644
--- a/arch/powerpc/platforms/85xx/mpc8544_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c
@@ -61,24 +61,11 @@
 		return;
 	}
 
-	/* Alloc mpic structure and per isu has 16 INT entries. */
 	mpic = mpic_alloc(np, r.start,
 			  MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			  16, 64, " OPENPIC     ");
+			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 
-	/*
-	 * 48 Internal Interrupts
-	 */
-	mpic_assign_isu(mpic, 0, r.start + 0x10200);
-	mpic_assign_isu(mpic, 1, r.start + 0x10400);
-	mpic_assign_isu(mpic, 2, r.start + 0x10600);
-
-	/*
-	 * 16 External interrupts
-	 */
-	mpic_assign_isu(mpic, 3, r.start + 0x10000);
-
 	mpic_init(mpic);
 
 #ifdef CONFIG_PPC_I8259
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h
index 83415db..7286ffa 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx.h
+++ b/arch/powerpc/platforms/85xx/mpc85xx.h
@@ -15,4 +15,4 @@
  */
 
 extern void mpc85xx_restart(char *);
-extern int add_bridge(struct device_node *dev);
+extern int mpc85xx_add_bridge(struct device_node *dev);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 5d27621..7235f70 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -38,13 +38,9 @@
 #include <asm/fs_pd.h>
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 #ifdef CONFIG_PCI
-static int mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(struct pci_controller *hose,
+				   u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -91,30 +87,10 @@
 
 	mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			4, 0, " OpenPIC  ");
+			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 	of_node_put(np);
 
-	mpic_assign_isu(mpic, 0, r.start + 0x10200);
-	mpic_assign_isu(mpic, 1, r.start + 0x10280);
-	mpic_assign_isu(mpic, 2, r.start + 0x10300);
-	mpic_assign_isu(mpic, 3, r.start + 0x10380);
-	mpic_assign_isu(mpic, 4, r.start + 0x10400);
-	mpic_assign_isu(mpic, 5, r.start + 0x10480);
-	mpic_assign_isu(mpic, 6, r.start + 0x10500);
-	mpic_assign_isu(mpic, 7, r.start + 0x10580);
-
-	/* Unused on this platform (leave room for 8548) */
-	mpic_assign_isu(mpic, 8, r.start + 0x10600);
-	mpic_assign_isu(mpic, 9, r.start + 0x10680);
-	mpic_assign_isu(mpic, 10, r.start + 0x10700);
-	mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-	/* External Interrupts */
-	mpic_assign_isu(mpic, 12, r.start + 0x10000);
-	mpic_assign_isu(mpic, 13, r.start + 0x10080);
-	mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
 	mpic_init(mpic);
 
 #ifdef CONFIG_CPM2
@@ -241,7 +217,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc85xx_add_bridge(np);
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 }
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 1490eb3..50c8d64 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -47,11 +47,6 @@
 #include <sysdev/fsl_soc.h>
 #include "mpc85xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static int cds_pci_slot = 2;
 static volatile u8 *cadmus;
 
@@ -60,15 +55,11 @@
 #define ARCADIA_HOST_BRIDGE_IDSEL	17
 #define ARCADIA_2ND_BRIDGE_IDSEL	3
 
-extern int mpc85xx_pci2_busno;
-
-static int mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(struct pci_controller *hose,
+				  u_char bus, u_char devfn)
 {
-	if (bus == 0 && PCI_SLOT(devfn) == 0)
+	if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (mpc85xx_pci2_busno)
-		if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0)
-			return PCIBIOS_DEVICE_NOT_FOUND;
 	/* We explicitly do not go past the Tundra 320 Bridge */
 	if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -78,52 +69,44 @@
 		return PCIBIOS_SUCCESSFUL;
 }
 
-static void __init mpc85xx_cds_pcibios_fixup(void)
+static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev)
 {
-	struct pci_dev *dev;
-	u_char		c;
+	u_char c;
+	if (dev->vendor == PCI_VENDOR_ID_VIA) {
+		switch (dev->device) {
+		case PCI_DEVICE_ID_VIA_82C586_1:
+			/*
+			 * U-Boot does not set the enable bits
+			 * for the IDE device. Force them on here.
+			 */
+			pci_read_config_byte(dev, 0x40, &c);
+			c |= 0x03; /* IDE: Chip Enable Bits */
+			pci_write_config_byte(dev, 0x40, c);
 
-	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-					PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+			/*
+			 * Since only primary interface works, force the
+			 * IDE function to standard primary IDE interrupt
+			 * w/ 8259 offset
+			 */
+			dev->irq = 14;
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+			break;
 		/*
-		 * U-Boot does not set the enable bits
-		 * for the IDE device. Force them on here.
+		 * Force legacy USB interrupt routing
 		 */
-		pci_read_config_byte(dev, 0x40, &c);
-		c |= 0x03; /* IDE: Chip Enable Bits */
-		pci_write_config_byte(dev, 0x40, c);
-
-		/*
-		 * Since only primary interface works, force the
-		 * IDE function to standard primary IDE interrupt
-		 * w/ 8259 offset
+		case PCI_DEVICE_ID_VIA_82C586_2:
+		/* There are two USB controllers.
+		 * Identify them by functon number
 		 */
-		dev->irq = 14;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-		pci_dev_put(dev);
+			if (PCI_FUNC(dev->devfn))
+				dev->irq = 11;
+			else
+				dev->irq = 10;
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+		default:
+			break;
+		}
 	}
-
-	/*
-	 * Force legacy USB interrupt routing
-	 */
-	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-					PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
-		dev->irq = 10;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
-		pci_dev_put(dev);
-	}
-
-	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-					PCI_DEVICE_ID_VIA_82C586_2, dev))) {
-		dev->irq = 11;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
-		pci_dev_put(dev);
-	}
-
-	/* Now map all the PCI irqs */
-	dev = NULL;
-	for_each_pci_dev(dev)
-		pci_read_irq_line(dev);
 }
 
 #ifdef CONFIG_PPC_I8259
@@ -165,33 +148,12 @@
 
 	mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			4, 0, " OpenPIC  ");
+			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 
 	/* Return the mpic node */
 	of_node_put(np);
 
-	mpic_assign_isu(mpic, 0, r.start + 0x10200);
-	mpic_assign_isu(mpic, 1, r.start + 0x10280);
-	mpic_assign_isu(mpic, 2, r.start + 0x10300);
-	mpic_assign_isu(mpic, 3, r.start + 0x10380);
-	mpic_assign_isu(mpic, 4, r.start + 0x10400);
-	mpic_assign_isu(mpic, 5, r.start + 0x10480);
-	mpic_assign_isu(mpic, 6, r.start + 0x10500);
-	mpic_assign_isu(mpic, 7, r.start + 0x10580);
-
-	/* Used only for 8548 so far, but no harm in
-	 * allocating them for everyone */
-	mpic_assign_isu(mpic, 8, r.start + 0x10600);
-	mpic_assign_isu(mpic, 9, r.start + 0x10680);
-	mpic_assign_isu(mpic, 10, r.start + 0x10700);
-	mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-	/* External Interrupts */
-	mpic_assign_isu(mpic, 12, r.start + 0x10000);
-	mpic_assign_isu(mpic, 13, r.start + 0x10080);
-	mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
 	mpic_init(mpic);
 
 #ifdef CONFIG_PPC_I8259
@@ -257,9 +219,9 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		mpc85xx_add_bridge(np);
 
-	ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+	ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 }
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index e3dddbf..004b80b 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -59,11 +59,6 @@
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -100,7 +95,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) {
-		add_bridge(np);
+		mpc85xx_add_bridge(np);
 	}
 	of_node_put(np);
 #endif
@@ -181,29 +176,10 @@
 
 	mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			4, 0, " OpenPIC  ");
+			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 	of_node_put(np);
 
-	/* Internal Interrupts */
-	mpic_assign_isu(mpic, 0, r.start + 0x10200);
-	mpic_assign_isu(mpic, 1, r.start + 0x10280);
-	mpic_assign_isu(mpic, 2, r.start + 0x10300);
-	mpic_assign_isu(mpic, 3, r.start + 0x10380);
-	mpic_assign_isu(mpic, 4, r.start + 0x10400);
-	mpic_assign_isu(mpic, 5, r.start + 0x10480);
-	mpic_assign_isu(mpic, 6, r.start + 0x10500);
-	mpic_assign_isu(mpic, 7, r.start + 0x10580);
-	mpic_assign_isu(mpic, 8, r.start + 0x10600);
-	mpic_assign_isu(mpic, 9, r.start + 0x10680);
-	mpic_assign_isu(mpic, 10, r.start + 0x10700);
-	mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-	/* External Interrupts */
-	mpic_assign_isu(mpic, 12, r.start + 0x10000);
-	mpic_assign_isu(mpic, 13, r.start + 0x10080);
-	mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
 	mpic_init(mpic);
 
 #ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c
index 48f17e2..8118417 100644
--- a/arch/powerpc/platforms/85xx/pci.c
+++ b/arch/powerpc/platforms/85xx/pci.c
@@ -33,10 +33,8 @@
 #define DBG(x...)
 #endif
 
-int mpc85xx_pci2_busno = 0;
-
 #ifdef CONFIG_PCI
-int __init add_bridge(struct device_node *dev)
+int __init mpc85xx_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -57,11 +55,10 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	hose = pcibios_alloc_controller();
+	pci_assign_all_buses = 1;
+	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
 
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -74,8 +71,6 @@
 	if ((rsrc.start & 0xfffff) == 0x9000) {
 		setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004);
 		primary = 0;
-		hose->bus_offset = hose->first_busno;
-		mpc85xx_pci2_busno = hose->first_busno;
 	}
 
 	printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index d1bcff5..0faebfd 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -1,5 +1,5 @@
 choice
-	prompt "Machine Type"
+	prompt "86xx Board Type"
 	depends on PPC_86xx
 	default MPC8641_HPCN
 
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
index 2834462..23f7ed2 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx.h
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -15,15 +15,10 @@
  * mpc86xx_* files. Mostly for use by mpc86xx_setup().
  */
 
-extern int add_bridge(struct device_node *dev);
+extern int mpc86xx_add_bridge(struct device_node *dev);
 
-extern int mpc86xx_exclude_device(u_char bus, u_char devfn);
-
-extern void setup_indirect_pcie(struct pci_controller *hose,
-				       u32 cfg_addr, u32 cfg_data);
-extern void setup_indirect_pcie_nomap(struct pci_controller *hose,
-					     void __iomem *cfg_addr,
-					     void __iomem *cfg_data);
+extern int mpc86xx_exclude_device(struct pci_controller *hose,
+				  u_char bus, u_char devfn);
 
 extern void __init mpc86xx_smp_init(void);
 
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 1051702..5b01ec7 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -44,13 +44,6 @@
 #define DBG(fmt...) do { } while(0)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-unsigned long pci_dram_offset = 0;
-#endif
-
-
 #ifdef CONFIG_PCI
 static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
@@ -81,22 +74,9 @@
 	/* Alloc mpic structure and per isu has 16 INT entries. */
 	mpic1 = mpic_alloc(np, res.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			16, NR_IRQS - 4,
-			" MPIC     ");
+			0, 256, " MPIC     ");
 	BUG_ON(mpic1 == NULL);
 
-	mpic_assign_isu(mpic1, 0, res.start + 0x10000);
-
-	/* 48 Internal Interrupts */
-	mpic_assign_isu(mpic1, 1, res.start + 0x10200);
-	mpic_assign_isu(mpic1, 2, res.start + 0x10400);
-	mpic_assign_isu(mpic1, 3, res.start + 0x10600);
-
-	/* 16 External interrupts
-	 * Moving them from [0 - 15] to [64 - 79]
-	 */
-	mpic_assign_isu(mpic1, 4, res.start + 0x10000);
-
 	mpic_init(mpic1);
 
 #ifdef CONFIG_PCI
@@ -319,6 +299,7 @@
 {
 	unsigned short temp;
 	pci_write_config_word(dev, 0x04, 0x0405);
+	dev->class &= ~0x5;
 	pci_read_config_word(dev, 0x4a, &temp);
 	temp |= 0x1000;
 	pci_write_config_word(dev, 0x4a, temp);
@@ -364,9 +345,7 @@
 
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
-
-	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
+		mpc86xx_add_bridge(np);
 #endif
 
 	printk("MPC86xx HPCN board from Freescale Semiconductor\n");
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index 8235c56..73cd5b05 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -122,7 +122,6 @@
 mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
 {
 	u16 cmd;
-	unsigned int temps;
 
 	DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
 			pcie_offset, pcie_size);
@@ -133,22 +132,49 @@
 	early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
 
 	early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
-
-	/* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
-	early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
-	temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
-	early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
 }
 
-int mpc86xx_exclude_device(u_char bus, u_char devfn)
+static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev)
 {
-	if (bus == 0 && PCI_SLOT(devfn) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	struct resource *res;
+	int i, res_idx = PCI_BRIDGE_RESOURCES;
+	struct pci_controller *hose;
 
-	return PCIBIOS_SUCCESSFUL;
+	/*
+	 * Make the bridge be transparent.
+	 */
+	dev->transparent = 1;
+
+	hose = pci_bus_to_host(dev->bus);
+	if (!hose) {
+		printk(KERN_ERR "Can't find hose for bus %d\n",
+		       dev->bus->number);
+		return;
+	}
+
+	if (hose->io_resource.flags) {
+		res = &dev->resource[res_idx++];
+		res->start = hose->io_resource.start;
+		res->end = hose->io_resource.end;
+		res->flags = hose->io_resource.flags;
+	}
+
+	for (i = 0; i < 3; i++) {
+		res = &dev->resource[res_idx + i];
+		res->start = hose->mem_resources[i].start;
+		res->end = hose->mem_resources[i].end;
+		res->flags = hose->mem_resources[i].flags;
+	}
 }
 
-int __init add_bridge(struct device_node *dev)
+
+DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent);
+DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent);
+
+#define PCIE_LTSSM	0x404	/* PCIe Link Training and Status */
+#define PCIE_LTSSM_L0	0x16	/* L0 state */
+
+int __init mpc86xx_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -156,6 +182,7 @@
 	const int *bus_range;
 	int has_address = 0;
 	int primary = 0;
+	u16 val;
 
 	DBG("Adding PCIE host bridge %s\n", dev->full_name);
 
@@ -168,17 +195,23 @@
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 		       " bus 0\n", dev->full_name);
 
-	hose = pcibios_alloc_controller();
+	pci_assign_all_buses = 1;
+	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
 
-	/* last_busno = 0xfe cause by MPC8641 PCIE bug */
+	hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG |
+				PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
+
 	hose->first_busno = bus_range ? bus_range[0] : 0x0;
-	hose->last_busno = bus_range ? bus_range[1] : 0xfe;
+	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-	setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4);
+	setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4);
+
+	/* Probe the hose link training status */
+	early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val);
+	if (val < PCIE_LTSSM_L0)
+		return -ENXIO;
 
 	/* Setup the PCIE host controller. */
 	mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1);
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 0901dba..f169355 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -32,6 +32,7 @@
 #include <linux/root_dev.h>
 #include <linux/time.h>
 #include <linux/rtc.h>
+#include <linux/fsl_devices.h>
 
 #include <asm/mmu.h>
 #include <asm/reg.h>
@@ -49,6 +50,10 @@
 
 #include "sysdev/mpc8xx_pic.h"
 
+#ifdef CONFIG_PCMCIA_M8XX
+struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
+#endif
+
 void m8xx_calibrate_decr(void);
 extern void m8xx_wdt_handler_install(bd_t *bp);
 extern int cpm_pic_init(void);
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index c36e475..5a808d6 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -22,6 +22,7 @@
 
 #include <linux/fs_enet_pd.h>
 #include <linux/fs_uart_pd.h>
+#include <linux/fsl_devices.h>
 #include <linux/mii.h>
 
 #include <asm/delay.h>
@@ -39,7 +40,7 @@
 #include <asm/prom.h>
 
 extern void cpm_reset(void);
-extern void mpc8xx_show_cpuinfo(struct seq_file*);
+extern void mpc8xx_show_cpuinfo(struct seq_file *);
 extern void mpc8xx_restart(char *cmd);
 extern void mpc8xx_calibrate_decr(void);
 extern int mpc8xx_set_rtc_time(struct rtc_time *tm);
@@ -47,9 +48,73 @@
 extern void m8xx_pic_init(void);
 extern unsigned int mpc8xx_get_irq(void);
 
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_scc3_ioports(struct fs_platform_info* ptr);
+static void init_smc1_uart_ioports(struct fs_uart_platform_info *fpi);
+static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi);
+static void init_scc3_ioports(struct fs_platform_info *ptr);
+
+#ifdef CONFIG_PCMCIA_M8XX
+static void pcmcia_hw_setup(int slot, int enable)
+{
+	unsigned *bcsr_io;
+
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+	if (enable)
+		clrbits32(bcsr_io, BCSR1_PCCEN);
+	else
+		setbits32(bcsr_io, BCSR1_PCCEN);
+
+	iounmap(bcsr_io);
+}
+
+static int pcmcia_set_voltage(int slot, int vcc, int vpp)
+{
+	u32 reg = 0;
+	unsigned *bcsr_io;
+
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+	switch (vcc) {
+	case 0:
+		break;
+	case 33:
+		reg |= BCSR1_PCCVCC0;
+		break;
+	case 50:
+		reg |= BCSR1_PCCVCC1;
+		break;
+	default:
+		return 1;
+	}
+
+	switch (vpp) {
+	case 0:
+		break;
+	case 33:
+	case 50:
+		if (vcc == vpp)
+			reg |= BCSR1_PCCVPP1;
+		else
+			return 1;
+		break;
+	case 120:
+		if ((vcc == 33) || (vcc == 50))
+			reg |= BCSR1_PCCVPP0;
+		else
+			return 1;
+	default:
+		return 1;
+	}
+
+	/* first, turn off all power */
+	clrbits32(bcsr_io, 0x00610000);
+
+	/* enable new powersettings */
+	setbits32(bcsr_io, reg);
+
+	iounmap(bcsr_io);
+	return 0;
+}
+#endif
 
 void __init mpc885ads_board_setup(void)
 {
@@ -62,7 +127,7 @@
 #endif
 
 	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-	cp = (cpm8xx_t *)immr_map(im_cpm);
+	cp = (cpm8xx_t *) immr_map(im_cpm);
 
 	if (bcsr_io == NULL) {
 		printk(KERN_CRIT "Could not remap BCSR\n");
@@ -75,13 +140,13 @@
 	out_8(&(cp->cp_smc[0].smc_smcm), tmpval8);
 	clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN);	/* brg1 */
 #else
-	setbits32(bcsr_io,BCSR1_RS232EN_1);
+	setbits32(bcsr_io, BCSR1_RS232EN_1);
 	out_be16(&cp->cp_smc[0].smc_smcmr, 0);
 	out_8(&cp->cp_smc[0].smc_smce, 0);
 #endif
 
 #ifdef CONFIG_SERIAL_CPM_SMC2
-	clrbits32(bcsr_io,BCSR1_RS232EN_2);
+	clrbits32(bcsr_io, BCSR1_RS232EN_2);
 	clrbits32(&cp->cp_simode, 0xe0000000 >> 1);
 	setbits32(&cp->cp_simode, 0x20000000 >> 1);	/* brg2 */
 	tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX);
@@ -90,7 +155,7 @@
 
 	init_smc2_uart_ioports(0);
 #else
-	setbits32(bcsr_io,BCSR1_RS232EN_2);
+	setbits32(bcsr_io, BCSR1_RS232EN_2);
 	out_be16(&cp->cp_smc[1].smc_smcmr, 0);
 	out_8(&cp->cp_smc[1].smc_smce, 0);
 #endif
@@ -99,29 +164,34 @@
 
 #ifdef CONFIG_FS_ENET
 	/* use MDC for MII (common) */
-	io_port = (iop8xx_t*)immr_map(im_ioport);
+	io_port = (iop8xx_t *) immr_map(im_ioport);
 	setbits16(&io_port->iop_pdpar, 0x0080);
 	clrbits16(&io_port->iop_pddir, 0x0080);
 
 	bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
-	clrbits32(bcsr_io,BCSR5_MII1_EN);
-	clrbits32(bcsr_io,BCSR5_MII1_RST);
+	clrbits32(bcsr_io, BCSR5_MII1_EN);
+	clrbits32(bcsr_io, BCSR5_MII1_RST);
 #ifndef CONFIG_FC_ENET_HAS_SCC
-	clrbits32(bcsr_io,BCSR5_MII2_EN);
-	clrbits32(bcsr_io,BCSR5_MII2_RST);
+	clrbits32(bcsr_io, BCSR5_MII2_EN);
+	clrbits32(bcsr_io, BCSR5_MII2_RST);
 
 #endif
 	iounmap(bcsr_io);
 	immr_unmap(io_port);
 
 #endif
+
+#ifdef CONFIG_PCMCIA_M8XX
+	/*Set up board specific hook-ups */
+	m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup;
+	m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage;
+#endif
 }
 
-
-static void init_fec1_ioports(struct fs_platform_info* ptr)
+static void init_fec1_ioports(struct fs_platform_info *ptr)
 {
-	cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
-	iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+	cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm);
+	iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport);
 
 	/* configure FEC1 pins  */
 	setbits16(&io_port->iop_papar, 0xf830);
@@ -143,11 +213,10 @@
 	immr_unmap(cp);
 }
 
-
-static void init_fec2_ioports(struct fs_platform_info* ptr)
+static void init_fec2_ioports(struct fs_platform_info *ptr)
 {
-	cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
-	iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+	cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm);
+	iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport);
 
 	/* configure FEC2 pins */
 	setbits32(&cp->cp_pepar, 0x0003fffc);
@@ -177,15 +246,15 @@
 	}
 }
 
-static void init_scc3_ioports(struct fs_platform_info* fpi)
+static void init_scc3_ioports(struct fs_platform_info *fpi)
 {
 	unsigned *bcsr_io;
 	iop8xx_t *io_port;
 	cpm8xx_t *cp;
 
 	bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
-	io_port = (iop8xx_t *)immr_map(im_ioport);
-	cp = (cpm8xx_t *)immr_map(im_cpm);
+	io_port = (iop8xx_t *) immr_map(im_ioport);
+	cp = (cpm8xx_t *) immr_map(im_cpm);
 
 	if (bcsr_io == NULL) {
 		printk(KERN_CRIT "Could not remap BCSR\n");
@@ -194,9 +263,9 @@
 
 	/* Enable the PHY.
 	 */
-	clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+	clrbits32(bcsr_io + 4, BCSR4_ETH10_RST);
 	udelay(1000);
-	setbits32(bcsr_io+4, BCSR4_ETH10_RST);
+	setbits32(bcsr_io + 4, BCSR4_ETH10_RST);
 	/* Configure port A pins for Txd and Rxd.
 	 */
 	setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD);
@@ -212,8 +281,7 @@
 	 */
 	setbits32(&cp->cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
 	clrbits32(&cp->cp_pepar, PE_ENET_TENA);
-	clrbits32(&cp->cp_pedir,
-		  PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
+	clrbits32(&cp->cp_pedir, PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
 	clrbits32(&cp->cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
 	setbits32(&cp->cp_peso, PE_ENET_TENA);
 
@@ -237,7 +305,7 @@
 	clrbits32(&cp->cp_pedir, PE_ENET_TENA);
 	setbits32(&cp->cp_peso, PE_ENET_TENA);
 
-	setbits32(bcsr_io+4, BCSR1_ETHEN);
+	setbits32(bcsr_io + 4, BCSR1_ETHEN);
 	iounmap(bcsr_io);
 	immr_unmap(io_port);
 	immr_unmap(cp);
@@ -257,50 +325,48 @@
 	}
 }
 
-
-
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr)
+static void init_smc1_uart_ioports(struct fs_uart_platform_info *ptr)
 {
-        unsigned *bcsr_io;
+	unsigned *bcsr_io;
 	cpm8xx_t *cp;
 
-	cp = (cpm8xx_t *)immr_map(im_cpm);
+	cp = (cpm8xx_t *) immr_map(im_cpm);
 	setbits32(&cp->cp_pepar, 0x000000c0);
 	clrbits32(&cp->cp_pedir, 0x000000c0);
 	clrbits32(&cp->cp_peso, 0x00000040);
 	setbits32(&cp->cp_peso, 0x00000080);
 	immr_unmap(cp);
 
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
 
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_1);
-        iounmap(bcsr_io);
+	if (bcsr_io == NULL) {
+		printk(KERN_CRIT "Could not remap BCSR1\n");
+		return;
+	}
+	clrbits32(bcsr_io, BCSR1_RS232EN_1);
+	iounmap(bcsr_io);
 }
 
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi)
+static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi)
 {
-        unsigned *bcsr_io;
+	unsigned *bcsr_io;
 	cpm8xx_t *cp;
 
-	cp = (cpm8xx_t *)immr_map(im_cpm);
+	cp = (cpm8xx_t *) immr_map(im_cpm);
 	setbits32(&cp->cp_pepar, 0x00000c00);
 	clrbits32(&cp->cp_pedir, 0x00000c00);
 	clrbits32(&cp->cp_peso, 0x00000400);
 	setbits32(&cp->cp_peso, 0x00000800);
 	immr_unmap(cp);
 
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
 
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_2);
-        iounmap(bcsr_io);
+	if (bcsr_io == NULL) {
+		printk(KERN_CRIT "Could not remap BCSR1\n");
+		return;
+	}
+	clrbits32(bcsr_io, BCSR1_RS232EN_2);
+	iounmap(bcsr_io);
 }
 
 void init_smc_ioports(struct fs_uart_platform_info *data)
@@ -373,15 +439,11 @@
 	return 1;
 }
 
-define_machine(mpc885_ads) {
-	.name			= "MPC885 ADS",
-	.probe			= mpc885ads_probe,
-	.setup_arch		= mpc885ads_setup_arch,
-	.init_IRQ		= m8xx_pic_init,
-	.show_cpuinfo		= mpc8xx_show_cpuinfo,
-	.get_irq		= mpc8xx_get_irq,
-	.restart		= mpc8xx_restart,
-	.calibrate_decr		= mpc8xx_calibrate_decr,
-	.set_rtc_time		= mpc8xx_set_rtc_time,
-	.get_rtc_time		= mpc8xx_get_rtc_time,
-};
+define_machine(mpc885_ads)
+{
+.name = "MPC885 ADS",.probe = mpc885ads_probe,.setup_arch =
+	    mpc885ads_setup_arch,.init_IRQ =
+	    m8xx_pic_init,.show_cpuinfo = mpc8xx_show_cpuinfo,.get_irq =
+	    mpc8xx_get_irq,.restart = mpc8xx_restart,.calibrate_decr =
+	    mpc8xx_calibrate_decr,.set_rtc_time =
+	    mpc8xx_set_rtc_time,.get_rtc_time = mpc8xx_get_rtc_time,};
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 361acfa..33545d3 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -2,7 +2,7 @@
 
 choice
 	prompt "Machine type"
-	depends on PPC64 || CLASSIC32
+	depends on PPC64 || 6xx
 	default PPC_MULTIPLATFORM
 
 config PPC_MULTIPLATFORM
@@ -16,15 +16,30 @@
 	bool "Embedded 6xx/7xx/7xxx-based board"
 	depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
 
-config APUS
-	bool "Amiga-APUS"
-	depends on PPC32 && BROKEN
+config PPC_82xx
+	bool "Freescale 82xx"
+	depends on 6xx
+
+config PPC_83xx
+	bool "Freescale 83xx"
+	depends on 6xx
+	select FSL_SOC
+	select 83xx
+	select WANT_DEVICE_TREE
+
+config PPC_86xx
+	bool "Freescale 86xx"
+	depends on 6xx
+	select FSL_SOC
+	select ALTIVEC
 	help
-	  Select APUS if configuring for a PowerUP Amiga.
-	  More information is available at:
-	  <http://linux-apus.sourceforge.net/>.
+	  The Freescale E600 SoCs have 74xx cores.
 endchoice
 
+config CLASSIC32
+	def_bool y
+	depends on 6xx && PPC_MULTIPLATFORM
+
 source "arch/powerpc/platforms/pseries/Kconfig"
 source "arch/powerpc/platforms/iseries/Kconfig"
 source "arch/powerpc/platforms/chrp/Kconfig"
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
new file mode 100644
index 0000000..b8b5fde94
--- /dev/null
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -0,0 +1,221 @@
+config PPC64
+	bool "64-bit kernel"
+	default n
+	help
+	  This option selects whether a 32-bit or a 64-bit kernel
+	  will be built.
+
+menu "Processor support"
+choice
+	prompt "Processor Type"
+	depends on PPC32
+	default 6xx
+	help
+	  There are five families of 32 bit PowerPC chips supported.
+	  The most common ones are the desktop and server CPUs (601, 603,
+	  604, 740, 750, 74xx) CPUs from Freescale and IBM, with their
+	  embedded 52xx/82xx/83xx/86xx counterparts.
+	  The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500
+	  (85xx) each form a family of their own that is not compatible
+	  with the others.
+
+	  If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx.
+
+config 6xx
+	bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx"
+	select PPC_FPU
+
+config PPC_85xx
+	bool "Freescale 85xx"
+	select E500
+	select FSL_SOC
+	select 85xx
+	select WANT_DEVICE_TREE
+
+config PPC_8xx
+	bool "Freescale 8xx"
+	select FSL_SOC
+	select 8xx
+
+config 40x
+	bool "AMCC 40x"
+	select PPC_DCR_NATIVE
+
+config 44x
+	bool "AMCC 44x"
+	select PPC_DCR_NATIVE
+	select WANT_DEVICE_TREE
+
+config E200
+	bool "Freescale e200"
+
+endchoice
+
+config POWER4_ONLY
+	bool "Optimize for POWER4"
+	depends on PPC64
+	default n
+	---help---
+	  Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
+	  The resulting binary will not work on POWER3 or RS64 processors
+	  when compiled with binutils 2.15 or later.
+
+config POWER3
+	bool
+	depends on PPC64
+	default y if !POWER4_ONLY
+
+config POWER4
+	depends on PPC64
+	def_bool y
+
+config 6xx
+	bool
+
+# this is temp to handle compat with arch=ppc
+config 8xx
+	bool
+
+# this is temp to handle compat with arch=ppc
+config 83xx
+	bool
+
+# this is temp to handle compat with arch=ppc
+config 85xx
+	bool
+
+config E500
+	bool
+
+config PPC_FPU
+	bool
+	default y if PPC64
+
+config 4xx
+	bool
+	depends on 40x || 44x
+	default y
+
+config BOOKE
+	bool
+	depends on E200 || E500 || 44x
+	default y
+
+config FSL_BOOKE
+	bool
+	depends on E200 || E500
+	default y
+
+config PTE_64BIT
+	bool
+	depends on 44x || E500
+	default y if 44x
+	default y if E500 && PHYS_64BIT
+
+config PHYS_64BIT
+	bool 'Large physical address support' if E500
+	depends on 44x || E500
+	select RESOURCES_64BIT
+	default y if 44x
+	---help---
+	  This option enables kernel support for larger than 32-bit physical
+	  addresses.  This features is not be available on all e500 cores.
+
+	  If in doubt, say N here.
+
+config ALTIVEC
+	bool "AltiVec Support"
+	depends on CLASSIC32 || POWER4
+	---help---
+	  This option enables kernel support for the Altivec extensions to the
+	  PowerPC processor. The kernel currently supports saving and restoring
+	  altivec registers, and turning on the 'altivec enable' bit so user
+	  processes can execute altivec instructions.
+
+	  This option is only usefully if you have a processor that supports
+	  altivec (G4, otherwise known as 74xx series), but does not have
+	  any affect on a non-altivec cpu (it does, however add code to the
+	  kernel).
+
+	  If in doubt, say Y here.
+
+config SPE
+	bool "SPE Support"
+	depends on E200 || E500
+	default y
+	---help---
+	  This option enables kernel support for the Signal Processing
+	  Extensions (SPE) to the PowerPC processor. The kernel currently
+	  supports saving and restoring SPE registers, and turning on the
+	  'spe enable' bit so user processes can execute SPE instructions.
+
+	  This option is only useful if you have a processor that supports
+	  SPE (e500, otherwise known as 85xx series), but does not have any
+	  effect on a non-spe cpu (it does, however add code to the kernel).
+
+	  If in doubt, say Y here.
+
+config PPC_STD_MMU
+	bool
+	depends on 6xx || POWER3 || POWER4 || PPC64
+	default y
+
+config PPC_STD_MMU_32
+	def_bool y
+	depends on PPC_STD_MMU && PPC32
+
+config PPC_MM_SLICES
+	bool
+	default y if HUGETLB_PAGE
+	default n
+
+config VIRT_CPU_ACCOUNTING
+	bool "Deterministic task and CPU time accounting"
+	depends on PPC64
+	default y
+	help
+	  Select this option to enable more accurate task and CPU time
+	  accounting.  This is done by reading a CPU counter on each
+	  kernel entry and exit and on transitions within the kernel
+	  between system, softirq and hardirq state, so there is a
+	  small performance impact.  This also enables accounting of
+	  stolen time on logically-partitioned systems running on
+	  IBM POWER5-based machines.
+
+	  If in doubt, say Y here.
+
+config SMP
+	depends on PPC_STD_MMU
+	bool "Symmetric multi-processing support"
+	---help---
+	  This enables support for systems with more than one CPU. If you have
+	  a system with only one CPU, say N. If you have a system with more
+	  than one CPU, say Y.  Note that the kernel does not currently
+	  support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
+	  since they have inadequate hardware support for multiprocessor
+	  operation.
+
+	  If you say N here, the kernel will run on single and multiprocessor
+	  machines, but will use only one CPU of a multiprocessor machine. If
+	  you say Y here, the kernel will run on single-processor machines.
+	  On a single-processor machine, the kernel will run faster if you say
+	  N here.
+
+	  If you don't know what to do here, say N.
+
+config NR_CPUS
+	int "Maximum number of CPUs (2-128)"
+	range 2 128
+	depends on SMP
+	default "32" if PPC64
+	default "4"
+
+config NOT_COHERENT_CACHE
+	bool
+	depends on 4xx || 8xx || E200
+	default y
+
+config CONFIG_CHECK_CACHE_COHERENCY
+	bool
+
+endmenu
diff --git a/arch/powerpc/platforms/apus/Kconfig b/arch/powerpc/platforms/apus/Kconfig
deleted file mode 100644
index 6bde3bf..0000000
--- a/arch/powerpc/platforms/apus/Kconfig
+++ /dev/null
@@ -1,130 +0,0 @@
-
-config AMIGA
-	bool
-	depends on APUS
-	default y
-	help
-	  This option enables support for the Amiga series of computers.
-
-config ZORRO
-	bool
-	depends on APUS
-	default y
-	help
-	  This enables support for the Zorro bus in the Amiga. If you have
-	  expansion cards in your Amiga that conform to the Amiga
-	  AutoConfig(tm) specification, say Y, otherwise N. Note that even
-	  expansion cards that do not fit in the Zorro slots but fit in e.g.
-	  the CPU slot may fall in this category, so you have to say Y to let
-	  Linux use these.
-
-config ABSTRACT_CONSOLE
-	bool
-	depends on APUS
-	default y
-
-config APUS_FAST_EXCEPT
-	bool
-	depends on APUS
-	default y
-
-config AMIGA_PCMCIA
-	bool "Amiga 1200/600 PCMCIA support"
-	depends on APUS && EXPERIMENTAL
-	help
-	  Include support in the kernel for pcmcia on Amiga 1200 and Amiga
-	  600. If you intend to use pcmcia cards say Y; otherwise say N.
-
-config AMIGA_BUILTIN_SERIAL
-	tristate "Amiga builtin serial support"
-	depends on APUS
-	help
-	  If you want to use your Amiga's built-in serial port in Linux,
-	  answer Y.
-
-	  To compile this driver as a module, choose M here.
-
-config GVPIOEXT
-	tristate "GVP IO-Extender support"
-	depends on APUS
-	help
-	  If you want to use a GVP IO-Extender serial card in Linux, say Y.
-	  Otherwise, say N.
-
-config GVPIOEXT_LP
-	tristate "GVP IO-Extender parallel printer support"
-	depends on GVPIOEXT
-	help
-	  Say Y to enable driving a printer from the parallel port on your
-	  GVP IO-Extender card, N otherwise.
-
-config GVPIOEXT_PLIP
-	tristate "GVP IO-Extender PLIP support"
-	depends on GVPIOEXT
-	help
-	  Say Y to enable doing IP over the parallel port on your GVP
-	  IO-Extender card, N otherwise.
-
-config MULTIFACE_III_TTY
-	tristate "Multiface Card III serial support"
-	depends on APUS
-	help
-	  If you want to use a Multiface III card's serial port in Linux,
-	  answer Y.
-
-	  To compile this driver as a module, choose M here.
-
-config A2232
-	tristate "Commodore A2232 serial support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && APUS
-	---help---
-	  This option supports the 2232 7-port serial card shipped with the
-	  Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
-	  a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
-	  each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
-	  ports were connected with 8 pin DIN connectors on the card bracket,
-	  for which 8 pin to DB25 adapters were supplied. The card also had
-	  jumpers internally to toggle various pinning configurations.
-
-	  This driver can be built as a module; but then "generic_serial"
-	  will also be built as a module. This has to be loaded before
-	  "ser_a2232". If you want to do this, answer M here.
-
-config WHIPPET_SERIAL
-	tristate "Hisoft Whippet PCMCIA serial support"
-	depends on AMIGA_PCMCIA
-	help
-	  HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
-	  is no listing for the Whippet in their Amiga section.
-
-config APNE
-	tristate "PCMCIA NE2000 support"
-	depends on AMIGA_PCMCIA
-	help
-	  If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
-	  say N.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called apne.
-
-config SERIAL_CONSOLE
-	bool "Support for serial port console"
-	depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y)
-
-config HEARTBEAT
-	bool "Use power LED as a heartbeat"
-	depends on APUS
-	help
-	  Use the power-on LED on your machine as a load meter.  The exact
-	  behavior is platform-dependent, but normally the flash frequency is
-	  a hyperbolic function of the 5-minute load average.
-
-config PROC_HARDWARE
-	bool "/proc/hardware support"
-	depends on APUS
-
-source "drivers/zorro/Kconfig"
-
-config PCI_PERMEDIA
-	bool "PCI for Permedia2"
-	depends on !4xx && !8xx && APUS
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index f9ac3fe..ab511d5 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -67,12 +67,14 @@
 	0x00003FC000000000ull,
 };
 
+static unsigned int pmi_frequency_limit = 0;
 /*
  * hardware specific functions
  */
 
 static struct of_device *pmi_dev;
 
+#ifdef CONFIG_PPC_PMI
 static int set_pmode_pmi(int cpu, unsigned int pmode)
 {
 	int ret;
@@ -101,7 +103,7 @@
 #endif
 	return ret;
 }
-
+#endif
 
 static int get_pmode(int cpu)
 {
@@ -156,15 +158,16 @@
 }
 
 static int set_pmode(int cpu, unsigned int slow_mode) {
+#ifdef CONFIG_PPC_PMI
 	if (pmi_dev)
 		return set_pmode_pmi(cpu, slow_mode);
 	else
+#endif
 		return set_pmode_reg(cpu, slow_mode);
 }
 
 static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
 {
-	struct cpufreq_policy policy;
 	u8 cpu;
 	u8 cbe_pmode_new;
 
@@ -173,15 +176,27 @@
 	cpu = cbe_node_to_cpu(pmi_msg.data1);
 	cbe_pmode_new = pmi_msg.data2;
 
-	cpufreq_get_policy(&policy, cpu);
+	pmi_frequency_limit = cbe_freqs[cbe_pmode_new].frequency;
 
-	policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency);
-	policy.min = min(policy.min, policy.max);
-
-	pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max);
-	cpufreq_set_policy(&policy);
+	pr_debug("cbe_handle_pmi: max freq=%d\n", pmi_frequency_limit);
 }
 
+static int pmi_notifier(struct notifier_block *nb,
+				       unsigned long event, void *data)
+{
+	struct cpufreq_policy *policy = data;
+
+	if (event != CPUFREQ_INCOMPATIBLE)
+		return 0;
+
+	cpufreq_verify_within_limits(policy, 0, pmi_frequency_limit);
+	return 0;
+}
+
+static struct notifier_block pmi_notifier_block = {
+	.notifier_call = pmi_notifier,
+};
+
 static struct pmi_handler cbe_pmi_handler = {
 	.type			= PMI_TYPE_FREQ_CHANGE,
 	.handle_pmi_message	= cbe_cpufreq_handle_pmi,
@@ -238,12 +253,21 @@
 
 	cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
 
+	if (pmi_dev) {
+		/* frequency might get limited later, initialize limit with max_freq */
+		pmi_frequency_limit = max_freq;
+		cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+	}
+
 	/* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
 	return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
 }
 
 static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
+	if (pmi_dev)
+		cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+
 	cpufreq_frequency_table_put_attr(policy->cpu);
 	return 0;
 }
@@ -302,26 +326,28 @@
 
 static int __init cbe_cpufreq_init(void)
 {
+#ifdef CONFIG_PPC_PMI
 	struct device_node *np;
-
+#endif
 	if (!machine_is(cell))
 		return -ENODEV;
-
+#ifdef CONFIG_PPC_PMI
 	np = of_find_node_by_type(NULL, "ibm,pmi");
 
 	pmi_dev = of_find_device_by_node(np);
 
 	if (pmi_dev)
 		pmi_register_handler(pmi_dev, &cbe_pmi_handler);
-
+#endif
 	return cpufreq_register_driver(&cbe_cpufreq_driver);
 }
 
 static void __exit cbe_cpufreq_exit(void)
 {
+#ifdef CONFIG_PPC_PMI
 	if (pmi_dev)
 		pmi_unregister_handler(pmi_dev, &cbe_pmi_handler);
-
+#endif
 	cpufreq_unregister_driver(&cbe_cpufreq_driver);
 }
 
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 7fb92f2..9d7c2ef 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -102,7 +102,7 @@
 		vaddr = (unsigned long)PCI_FIX_ADDR(addr);
 
 		/* Check if it's in allowed range for  PIO */
-		if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE)
+		if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
 			return;
 
 		/* Try to find a PTE. If not, clear the paddr, we'll do
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index a7f5a76..96a8f60 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -31,6 +31,7 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 #include <linux/mutex.h>
+#include <linux/linux_logo.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
 #include <asm/xmon.h>
@@ -183,7 +184,7 @@
 		spu->slb_replace = 0;
 
 	spu_restart_dma(spu);
-
+	spu->stats.slb_flt++;
 	return 0;
 }
 
@@ -332,6 +333,7 @@
 	if (stat & 0x10) /* SPU mailbox threshold */
 		spu->wbox_callback(spu);
 
+	spu->stats.class2_intr++;
 	return stat ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -462,8 +464,18 @@
 }
 EXPORT_SYMBOL_GPL(spu_free);
 
+static int spu_shutdown(struct sys_device *sysdev)
+{
+	struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+	spu_free_irqs(spu);
+	spu_destroy_spu(spu);
+	return 0;
+}
+
 struct sysdev_class spu_sysdev_class = {
-	set_kset_name("spu")
+	set_kset_name("spu"),
+	.shutdown = spu_shutdown,
 };
 
 int spu_add_sysdev_attr(struct sysdev_attribute *attr)
@@ -574,6 +586,9 @@
 	spin_unlock_irqrestore(&spu_list_lock, flags);
 	mutex_unlock(&spu_mutex);
 
+	spu->stats.utilization_state = SPU_UTIL_IDLE;
+	spu->stats.tstamp = jiffies;
+
 	goto out;
 
 out_free_irqs:
@@ -586,6 +601,45 @@
 	return ret;
 }
 
+static const char *spu_state_names[] = {
+	"user", "system", "iowait", "idle"
+};
+
+static unsigned long long spu_acct_time(struct spu *spu,
+		enum spu_utilization_state state)
+{
+	unsigned long long time = spu->stats.times[state];
+
+	if (spu->stats.utilization_state == state)
+		time += jiffies - spu->stats.tstamp;
+
+	return jiffies_to_msecs(time);
+}
+
+
+static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
+{
+	struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+	return sprintf(buf, "%s %llu %llu %llu %llu "
+		      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+		spu_state_names[spu->stats.utilization_state],
+		spu_acct_time(spu, SPU_UTIL_USER),
+		spu_acct_time(spu, SPU_UTIL_SYSTEM),
+		spu_acct_time(spu, SPU_UTIL_IOWAIT),
+		spu_acct_time(spu, SPU_UTIL_IDLE),
+		spu->stats.vol_ctx_switch,
+		spu->stats.invol_ctx_switch,
+		spu->stats.slb_flt,
+		spu->stats.hash_flt,
+		spu->stats.min_flt,
+		spu->stats.maj_flt,
+		spu->stats.class2_intr,
+		spu->stats.libassist);
+}
+
+static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);
+
 static int __init init_spu_base(void)
 {
 	int i, ret = 0;
@@ -603,14 +657,28 @@
 
 	ret = spu_enumerate_spus(create_spu);
 
-	if (ret) {
+	if (ret < 0) {
 		printk(KERN_WARNING "%s: Error initializing spus\n",
 			__FUNCTION__);
 		goto out_unregister_sysdev_class;
 	}
 
+	if (ret > 0) {
+		/*
+		 * We cannot put the forward declaration in
+		 * <linux/linux_logo.h> because of conflicting session type
+		 * conflicts for const and __initdata with different compiler
+		 * versions
+		 */
+		extern const struct linux_logo logo_spe_clut224;
+
+		fb_append_extra_logo(&logo_spe_clut224, ret);
+	}
+
 	xmon_register_spus(&spu_full_list);
 
+	spu_add_sysdev_attr(&attr_stat);
+
 	return 0;
 
  out_unregister_sysdev_class:
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index 1d4562a..75ed50f 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -279,6 +279,7 @@
 {
 	int ret;
 	struct device_node *node;
+	unsigned int n = 0;
 
 	ret = -ENODEV;
 	for (node = of_find_node_by_type(NULL, "spe");
@@ -289,8 +290,9 @@
 				__FUNCTION__, node->name);
 			break;
 		}
+		n++;
 	}
-	return ret;
+	return ret ? ret : n;
 }
 
 static int __init of_create_spu(struct spu *spu, void *data)
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index d32db9f..07a0e81 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -320,6 +320,12 @@
 	/* FIXME: what are the side-effects of this? */
 	prob->dma_querymask_RW = mask;
 	prob->dma_querytype_RW = mode;
+	/* In the current implementation, the SPU context is always
+	 * acquired in runnable state when new bits are added to the
+	 * mask (tagwait), so it's sufficient just to mask
+	 * dma_tagstatus_R with the 'mask' parameter here.
+	 */
+	ctx->csa.prob.dma_tagstatus_R &= mask;
 out:
 	spin_unlock(&ctx->csa.register_lock);
 
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 8654749..6d7bd60 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -23,10 +23,14 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <asm/atomic.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
 #include "spufs.h"
 
+
+atomic_t nr_spu_contexts = ATOMIC_INIT(0);
+
 struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
 	struct spu_context *ctx;
@@ -39,7 +43,7 @@
 	if (spu_init_csa(&ctx->csa))
 		goto out_free;
 	spin_lock_init(&ctx->mmio_lock);
-	spin_lock_init(&ctx->mapping_lock);
+	mutex_init(&ctx->mapping_lock);
 	kref_init(&ctx->kref);
 	mutex_init(&ctx->state_mutex);
 	mutex_init(&ctx->run_mutex);
@@ -53,10 +57,12 @@
 	INIT_LIST_HEAD(&ctx->rq);
 	if (gang)
 		spu_gang_add_ctx(gang, ctx);
-	ctx->rt_priority = current->rt_priority;
-	ctx->policy = current->policy;
-	ctx->prio = current->prio;
-	INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick);
+	ctx->cpus_allowed = current->cpus_allowed;
+	spu_set_timeslice(ctx);
+	ctx->stats.execution_state = SPUCTX_UTIL_USER;
+	ctx->stats.tstamp = jiffies;
+
+	atomic_inc(&nr_spu_contexts);
 	goto out;
 out_free:
 	kfree(ctx);
@@ -76,6 +82,7 @@
 	if (ctx->gang)
 		spu_gang_remove_ctx(ctx->gang, ctx);
 	BUG_ON(!list_empty(&ctx->rq));
+	atomic_dec(&nr_spu_contexts);
 	kfree(ctx);
 }
 
@@ -103,6 +110,7 @@
 
 void spu_unmap_mappings(struct spu_context *ctx)
 {
+	mutex_lock(&ctx->mapping_lock);
 	if (ctx->local_store)
 		unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
 	if (ctx->mfc)
@@ -117,6 +125,7 @@
 		unmap_mapping_range(ctx->mss, 0, 0x1000, 1);
 	if (ctx->psmap)
 		unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
+	mutex_unlock(&ctx->mapping_lock);
 }
 
 /**
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index 0f75c07..e064d0c 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -33,7 +33,8 @@
  * function. Currently, there are a few corner cases that we haven't had
  * to handle fortunately.
  */
-static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr)
+static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+		unsigned long dsisr, unsigned *flt)
 {
 	struct vm_area_struct *vma;
 	unsigned long is_write;
@@ -73,7 +74,8 @@
 			goto bad_area;
 	}
 	ret = 0;
-	switch (handle_mm_fault(mm, vma, ea, is_write)) {
+	*flt = handle_mm_fault(mm, vma, ea, is_write);
+	switch (*flt) {
 	case VM_FAULT_MINOR:
 		current->min_flt++;
 		break;
@@ -153,6 +155,7 @@
 {
 	u64 ea, dsisr, access;
 	unsigned long flags;
+	unsigned flt = 0;
 	int ret;
 
 	/*
@@ -178,9 +181,17 @@
 	if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
 		return 0;
 
+	spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT);
+
 	pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
 		dsisr, ctx->state);
 
+	ctx->stats.hash_flt++;
+	if (ctx->state == SPU_STATE_RUNNABLE) {
+		ctx->spu->stats.hash_flt++;
+		spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT);
+	}
+
 	/* we must not hold the lock when entering spu_handle_mm_fault */
 	spu_release(ctx);
 
@@ -192,7 +203,7 @@
 
 	/* hashing failed, so try the actual fault handler */
 	if (ret)
-		ret = spu_handle_mm_fault(current->mm, ea, dsisr);
+		ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
 
 	spu_acquire(ctx);
 	/*
@@ -201,11 +212,23 @@
 	 * In case of unhandled error report the problem to user space.
 	 */
 	if (!ret) {
+		if (flt == VM_FAULT_MINOR)
+			ctx->stats.min_flt++;
+		else
+			ctx->stats.maj_flt++;
+		if (ctx->state == SPU_STATE_RUNNABLE) {
+			if (flt == VM_FAULT_MINOR)
+				ctx->spu->stats.min_flt++;
+			else
+				ctx->spu->stats.maj_flt++;
+		}
+
 		if (ctx->spu)
 			ctx->ops->restart_dma(ctx);
 	} else
 		spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
 
+	spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(spufs_handle_class1);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 45614c73..c2814ea 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -28,6 +28,7 @@
 #include <linux/pagemap.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
+#include <linux/seq_file.h>
 
 #include <asm/io.h>
 #include <asm/semaphore.h>
@@ -39,17 +40,18 @@
 
 #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
 
+
 static int
 spufs_mem_open(struct inode *inode, struct file *file)
 {
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->local_store = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -59,10 +61,10 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->local_store = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -216,11 +218,12 @@
 #endif /* CONFIG_SPU_FS_64K_LS */
 
 static const struct file_operations spufs_mem_fops = {
-	.open	 		= spufs_mem_open,
-	.read   		= spufs_mem_read,
-	.write   		= spufs_mem_write,
-	.llseek  		= generic_file_llseek,
-	.mmap    		= spufs_mem_mmap,
+	.open			= spufs_mem_open,
+	.release		= spufs_mem_release,
+	.read			= spufs_mem_read,
+	.write			= spufs_mem_write,
+	.llseek			= generic_file_llseek,
+	.mmap			= spufs_mem_mmap,
 #ifdef CONFIG_SPU_FS_64K_LS
 	.get_unmapped_area	= spufs_get_unmapped_area,
 #endif
@@ -309,11 +312,11 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->cntl = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return simple_attr_open(inode, file, spufs_cntl_get,
 					spufs_cntl_set, "0x%08lx");
 }
@@ -326,10 +329,10 @@
 
 	simple_attr_close(inode, file);
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->cntl = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -812,11 +815,11 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->signal1 = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -826,10 +829,10 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->signal1 = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -936,11 +939,11 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->signal2 = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -950,10 +953,10 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->signal2 = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -1154,10 +1157,10 @@
 
 	file->private_data = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!i->i_openers++)
 		ctx->mss = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -1167,10 +1170,10 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->mss = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -1211,11 +1214,11 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = i->i_ctx;
 	if (!i->i_openers++)
 		ctx->psmap = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -1225,10 +1228,10 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->psmap = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -1281,11 +1284,11 @@
 	if (atomic_read(&inode->i_count) != 1)
 		return -EBUSY;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->mfc = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -1295,10 +1298,10 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->mfc = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -1496,14 +1499,15 @@
 		if (status)
 			ret = status;
 	}
-	spu_release(ctx);
 
 	if (ret)
-		goto out;
+		goto out_unlock;
 
 	ctx->tagwait |= 1 << cmd.tag;
 	ret = size;
 
+out_unlock:
+	spu_release(ctx);
 out:
 	return ret;
 }
@@ -1514,14 +1518,14 @@
 	u32 free_elements, tagstatus;
 	unsigned int mask;
 
+	poll_wait(file, &ctx->mfc_wq, wait);
+
 	spu_acquire(ctx);
 	ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
 	free_elements = ctx->ops->get_mfc_free_elements(ctx);
 	tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
 	spu_release(ctx);
 
-	poll_wait(file, &ctx->mfc_wq, wait);
-
 	mask = 0;
 	if (free_elements & 0xffff)
 		mask |= POLLOUT | POLLWRNORM;
@@ -1796,6 +1800,29 @@
 	return 0;
 }
 
+static int spufs_caps_show(struct seq_file *s, void *private)
+{
+	struct spu_context *ctx = s->private;
+
+	if (!(ctx->flags & SPU_CREATE_NOSCHED))
+		seq_puts(s, "sched\n");
+	if (!(ctx->flags & SPU_CREATE_ISOLATE))
+		seq_puts(s, "step\n");
+	return 0;
+}
+
+static int spufs_caps_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_caps_fops = {
+	.open		= spufs_caps_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
 			char __user *buf, size_t len, loff_t *pos)
 {
@@ -2013,7 +2040,105 @@
 	.read = spufs_proxydma_info_read,
 };
 
+static int spufs_show_tid(struct seq_file *s, void *private)
+{
+	struct spu_context *ctx = s->private;
+
+	seq_printf(s, "%d\n", ctx->tid);
+	return 0;
+}
+
+static int spufs_tid_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, spufs_show_tid, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_tid_fops = {
+	.open		= spufs_tid_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const char *ctx_state_names[] = {
+	"user", "system", "iowait", "loaded"
+};
+
+static unsigned long long spufs_acct_time(struct spu_context *ctx,
+		enum spuctx_execution_state state)
+{
+	unsigned long time = ctx->stats.times[state];
+
+	if (ctx->stats.execution_state == state)
+		time += jiffies - ctx->stats.tstamp;
+
+	return jiffies_to_msecs(time);
+}
+
+static unsigned long long spufs_slb_flts(struct spu_context *ctx)
+{
+	unsigned long long slb_flts = ctx->stats.slb_flt;
+
+	if (ctx->state == SPU_STATE_RUNNABLE) {
+		slb_flts += (ctx->spu->stats.slb_flt -
+			     ctx->stats.slb_flt_base);
+	}
+
+	return slb_flts;
+}
+
+static unsigned long long spufs_class2_intrs(struct spu_context *ctx)
+{
+	unsigned long long class2_intrs = ctx->stats.class2_intr;
+
+	if (ctx->state == SPU_STATE_RUNNABLE) {
+		class2_intrs += (ctx->spu->stats.class2_intr -
+				 ctx->stats.class2_intr_base);
+	}
+
+	return class2_intrs;
+}
+
+
+static int spufs_show_stat(struct seq_file *s, void *private)
+{
+	struct spu_context *ctx = s->private;
+
+	spu_acquire(ctx);
+	seq_printf(s, "%s %llu %llu %llu %llu "
+		      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+		ctx_state_names[ctx->stats.execution_state],
+		spufs_acct_time(ctx, SPUCTX_UTIL_USER),
+		spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM),
+		spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT),
+		spufs_acct_time(ctx, SPUCTX_UTIL_LOADED),
+		ctx->stats.vol_ctx_switch,
+		ctx->stats.invol_ctx_switch,
+		spufs_slb_flts(ctx),
+		ctx->stats.hash_flt,
+		ctx->stats.min_flt,
+		ctx->stats.maj_flt,
+		spufs_class2_intrs(ctx),
+		ctx->stats.libassist);
+	spu_release(ctx);
+	return 0;
+}
+
+static int spufs_stat_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, spufs_show_stat, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_stat_fops = {
+	.open		= spufs_stat_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+
 struct tree_descr spufs_dir_contents[] = {
+	{ "capabilities", &spufs_caps_fops, 0444, },
 	{ "mem",  &spufs_mem_fops,  0666, },
 	{ "regs", &spufs_regs_fops,  0666, },
 	{ "mbox", &spufs_mbox_fops, 0444, },
@@ -2045,10 +2170,13 @@
 	{ "wbox_info", &spufs_wbox_info_fops, 0444, },
 	{ "dma_info", &spufs_dma_info_fops, 0444, },
 	{ "proxydma_info", &spufs_proxydma_info_fops, 0444, },
+	{ "tid", &spufs_tid_fops, 0444, },
+	{ "stat", &spufs_stat_fops, 0444, },
 	{},
 };
 
 struct tree_descr spufs_dir_nosched_contents[] = {
+	{ "capabilities", &spufs_caps_fops, 0444, },
 	{ "mem",  &spufs_mem_fops,  0666, },
 	{ "mbox", &spufs_mbox_fops, 0444, },
 	{ "ibox", &spufs_ibox_fops, 0444, },
@@ -2067,6 +2195,8 @@
 	{ "psmap", &spufs_psmap_fops, 0666, },
 	{ "phys-id", &spufs_id_ops, 0666, },
 	{ "object-id", &spufs_object_id_ops, 0666, },
+	{ "tid", &spufs_tid_fops, 0444, },
+	{ "stat", &spufs_stat_fops, 0444, },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 7150730..f37460e 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -177,7 +177,7 @@
 static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
 			  int mode, struct spu_context *ctx)
 {
-	struct dentry *dentry;
+	struct dentry *dentry, *tmp;
 	int ret;
 
 	while (files->name && files->name[0]) {
@@ -193,7 +193,20 @@
 	}
 	return 0;
 out:
-	spufs_prune_dir(dir);
+	/*
+	 * remove all children from dir. dir->inode is not set so don't
+	 * just simply use spufs_prune_dir() and panic afterwards :)
+	 * dput() looks like it will do the right thing:
+	 * - dec parent's ref counter
+	 * - remove child from parent's child list
+	 * - free child's inode if possible
+	 * - free child
+	 */
+	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+		dput(dentry);
+	}
+
+	shrink_dcache_parent(dir);
 	return ret;
 }
 
@@ -219,10 +232,6 @@
 	return dcache_dir_close(inode, file);
 }
 
-const struct inode_operations spufs_dir_inode_operations = {
-	.lookup = simple_lookup,
-};
-
 const struct file_operations spufs_context_fops = {
 	.open		= dcache_dir_open,
 	.release	= spufs_dir_close,
@@ -256,7 +265,7 @@
 		goto out_iput;
 
 	ctx->flags = flags;
-	inode->i_op = &spufs_dir_inode_operations;
+	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	if (flags & SPU_CREATE_NOSCHED)
 		ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
@@ -274,6 +283,7 @@
 	goto out;
 
 out_free_ctx:
+	spu_forget(ctx);
 	put_spu_context(ctx);
 out_iput:
 	iput(inode);
@@ -349,37 +359,6 @@
 	return ret;
 }
 
-static int spufs_rmgang(struct inode *root, struct dentry *dir)
-{
-	/* FIXME: this fails if the dir is not empty,
-	          which causes a leak of gangs. */
-	return simple_rmdir(root, dir);
-}
-
-static int spufs_gang_close(struct inode *inode, struct file *file)
-{
-	struct inode *parent;
-	struct dentry *dir;
-	int ret;
-
-	dir = file->f_path.dentry;
-	parent = dir->d_parent->d_inode;
-
-	ret = spufs_rmgang(parent, dir);
-	WARN_ON(ret);
-
-	return dcache_dir_close(inode, file);
-}
-
-const struct file_operations spufs_gang_fops = {
-	.open		= dcache_dir_open,
-	.release	= spufs_gang_close,
-	.llseek		= dcache_dir_lseek,
-	.read		= generic_read_dir,
-	.readdir	= dcache_readdir,
-	.fsync		= simple_sync_file,
-};
-
 static int
 spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
 {
@@ -403,11 +382,10 @@
 	if (!gang)
 		goto out_iput;
 
-	inode->i_op = &spufs_dir_inode_operations;
+	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 
 	d_instantiate(dentry, inode);
-	dget(dentry);
 	dir->i_nlink++;
 	dentry->d_inode->i_nlink++;
 	return ret;
@@ -437,7 +415,7 @@
 		goto out;
 	}
 
-	filp->f_op = &spufs_gang_fops;
+	filp->f_op = &simple_dir_operations;
 	fd_install(ret, filp);
 out:
 	return ret;
@@ -458,8 +436,10 @@
 	 * in error path of *_open().
 	 */
 	ret = spufs_gang_open(dget(dentry), mntget(mnt));
-	if (ret < 0)
-		WARN_ON(spufs_rmgang(inode, dentry));
+	if (ret < 0) {
+		int err = simple_rmdir(inode, dentry);
+		WARN_ON(err);
+	}
 
 out:
 	mutex_unlock(&inode->i_mutex);
@@ -600,12 +580,16 @@
 	struct inode *inode;
 	int ret;
 
+	ret = -ENODEV;
+	if (!spu_management_ops)
+		goto out;
+
 	ret = -ENOMEM;
 	inode = spufs_new_inode(sb, S_IFDIR | 0775);
 	if (!inode)
 		goto out;
 
-	inode->i_op = &spufs_dir_inode_operations;
+	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	SPUFS_I(inode)->i_ctx = NULL;
 
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 5762660..58ae13b 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -29,7 +29,8 @@
 	spu = ctx->spu;
 	pte_fault = spu->dsisr &
 	    (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
-	return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
+	return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ?
+		1 : 0;
 }
 
 static int spu_setup_isolated(struct spu_context *ctx)
@@ -142,8 +143,11 @@
 			runcntl = SPU_RUNCNTL_RUNNABLE;
 		ctx->ops->runcntl_write(ctx, runcntl);
 	} else {
-		spu_start_tick(ctx);
+		unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL;
 		ctx->ops->npc_write(ctx, *npc);
+		if (test_thread_flag(TIF_SINGLESTEP))
+			mode = SPU_PRIVCNTL_MODE_SINGLE_STEP;
+		out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode);
 		ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
 	}
 
@@ -155,7 +159,6 @@
 {
 	int ret = 0;
 
-	spu_stop_tick(ctx);
 	*status = ctx->ops->status_read(ctx);
 	*npc = ctx->ops->npc_read(ctx);
 	spu_release(ctx);
@@ -298,9 +301,22 @@
 	ctx->ops->master_start(ctx);
 	ctx->event_return = 0;
 
-	ret = spu_acquire_runnable(ctx, 0);
-	if (ret)
-		return ret;
+	spu_acquire(ctx);
+	if (ctx->state == SPU_STATE_SAVED) {
+		__spu_update_sched_info(ctx);
+
+		ret = spu_activate(ctx, 0);
+		if (ret) {
+			spu_release(ctx);
+			goto out;
+		}
+	} else {
+		/*
+		 * We have to update the scheduling priority under active_mutex
+		 * to protect against find_victim().
+		 */
+		spu_update_sched_info(ctx);
+	}
 
 	ret = spu_run_init(ctx, npc);
 	if (ret) {
@@ -325,16 +341,20 @@
 
 		if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
 			ret = spu_reacquire_runnable(ctx, npc, &status);
-			if (ret) {
-				spu_stop_tick(ctx);
+			if (ret)
 				goto out2;
-			}
 			continue;
 		}
 		ret = spu_process_events(ctx);
 
 	} while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
-				      SPU_STATUS_STOPPED_BY_HALT)));
+				      SPU_STATUS_STOPPED_BY_HALT |
+				       SPU_STATUS_SINGLE_STEP)));
+
+	if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+	    (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) &&
+	    (ctx->state == SPU_STATE_RUNNABLE))
+		ctx->stats.libassist++;
 
 	ctx->ops->master_stop(ctx);
 	ret = spu_run_fini(ctx, npc, &status);
@@ -344,10 +364,15 @@
 	if ((ret == 0) ||
 	    ((ret == -ERESTARTSYS) &&
 	     ((status & SPU_STATUS_STOPPED_BY_HALT) ||
+	      (status & SPU_STATUS_SINGLE_STEP) ||
 	      ((status & SPU_STATUS_STOPPED_BY_STOP) &&
 	       (status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
 		ret = status;
 
+	/* Note: we don't need to force_sig SIGTRAP on single-step
+	 * since we have TIF_SINGLESTEP set, thus the kernel will do
+	 * it upon return from the syscall anyawy
+	 */
 	if ((status & SPU_STATUS_STOPPED_BY_STOP)
 	    && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
 		force_sig(SIGTRAP, current);
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index b6ecb30..e5b4dd1 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -35,6 +35,10 @@
 #include <linux/numa.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
+#include <linux/kthread.h>
+#include <linux/pid_namespace.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/io.h>
 #include <asm/mmu_context.h>
@@ -43,91 +47,126 @@
 #include <asm/spu_priv1.h>
 #include "spufs.h"
 
-#define SPU_TIMESLICE	(HZ)
-
 struct spu_prio_array {
 	DECLARE_BITMAP(bitmap, MAX_PRIO);
 	struct list_head runq[MAX_PRIO];
 	spinlock_t runq_lock;
 	struct list_head active_list[MAX_NUMNODES];
 	struct mutex active_mutex[MAX_NUMNODES];
+	int nr_active[MAX_NUMNODES];
+	int nr_waiting;
 };
 
+static unsigned long spu_avenrun[3];
 static struct spu_prio_array *spu_prio;
-static struct workqueue_struct *spu_sched_wq;
+static struct task_struct *spusched_task;
+static struct timer_list spusched_timer;
 
-static inline int node_allowed(int node)
+/*
+ * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
+ */
+#define NORMAL_PRIO		120
+
+/*
+ * Frequency of the spu scheduler tick.  By default we do one SPU scheduler
+ * tick for every 10 CPU scheduler ticks.
+ */
+#define SPUSCHED_TICK		(10)
+
+/*
+ * These are the 'tuning knobs' of the scheduler:
+ *
+ * Minimum timeslice is 5 msecs (or 1 spu scheduler tick, whichever is
+ * larger), default timeslice is 100 msecs, maximum timeslice is 800 msecs.
+ */
+#define MIN_SPU_TIMESLICE	max(5 * HZ / (1000 * SPUSCHED_TICK), 1)
+#define DEF_SPU_TIMESLICE	(100 * HZ / (1000 * SPUSCHED_TICK))
+
+#define MAX_USER_PRIO		(MAX_PRIO - MAX_RT_PRIO)
+#define SCALE_PRIO(x, prio) \
+	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE)
+
+/*
+ * scale user-nice values [ -20 ... 0 ... 19 ] to time slice values:
+ * [800ms ... 100ms ... 5ms]
+ *
+ * The higher a thread's priority, the bigger timeslices
+ * it gets during one round of execution. But even the lowest
+ * priority thread gets MIN_TIMESLICE worth of execution time.
+ */
+void spu_set_timeslice(struct spu_context *ctx)
 {
-	cpumask_t mask;
-
-	if (!nr_cpus_node(node))
-		return 0;
-	mask = node_to_cpumask(node);
-	if (!cpus_intersects(mask, current->cpus_allowed))
-		return 0;
-	return 1;
+	if (ctx->prio < NORMAL_PRIO)
+		ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio);
+	else
+		ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio);
 }
 
-void spu_start_tick(struct spu_context *ctx)
+/*
+ * Update scheduling information from the owning thread.
+ */
+void __spu_update_sched_info(struct spu_context *ctx)
 {
-	if (ctx->policy == SCHED_RR) {
-		/*
-		 * Make sure the exiting bit is cleared.
-		 */
-		clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
-		mb();
-		queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE);
-	}
-}
-
-void spu_stop_tick(struct spu_context *ctx)
-{
-	if (ctx->policy == SCHED_RR) {
-		/*
-		 * While the work can be rearming normally setting this flag
-		 * makes sure it does not rearm itself anymore.
-		 */
-		set_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
-		mb();
-		cancel_delayed_work(&ctx->sched_work);
-	}
-}
-
-void spu_sched_tick(struct work_struct *work)
-{
-	struct spu_context *ctx =
-		container_of(work, struct spu_context, sched_work.work);
-	struct spu *spu;
-	int preempted = 0;
+	/*
+	 * 32-Bit assignment are atomic on powerpc, and we don't care about
+	 * memory ordering here because retriving the controlling thread is
+	 * per defintion racy.
+	 */
+	ctx->tid = current->pid;
 
 	/*
-	 * If this context is being stopped avoid rescheduling from the
-	 * scheduler tick because we would block on the state_mutex.
-	 * The caller will yield the spu later on anyway.
+	 * We do our own priority calculations, so we normally want
+	 * ->static_prio to start with. Unfortunately thies field
+	 * contains junk for threads with a realtime scheduling
+	 * policy so we have to look at ->prio in this case.
 	 */
-	if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
-		return;
+	if (rt_prio(current->prio))
+		ctx->prio = current->prio;
+	else
+		ctx->prio = current->static_prio;
+	ctx->policy = current->policy;
 
-	mutex_lock(&ctx->state_mutex);
-	spu = ctx->spu;
-	if (spu) {
-		int best = sched_find_first_bit(spu_prio->bitmap);
-		if (best <= ctx->prio) {
-			spu_deactivate(ctx);
-			preempted = 1;
-		}
+	/*
+	 * A lot of places that don't hold active_mutex poke into
+	 * cpus_allowed, including grab_runnable_context which
+	 * already holds the runq_lock.  So abuse runq_lock
+	 * to protect this field aswell.
+	 */
+	spin_lock(&spu_prio->runq_lock);
+	ctx->cpus_allowed = current->cpus_allowed;
+	spin_unlock(&spu_prio->runq_lock);
+}
+
+void spu_update_sched_info(struct spu_context *ctx)
+{
+	int node = ctx->spu->node;
+
+	mutex_lock(&spu_prio->active_mutex[node]);
+	__spu_update_sched_info(ctx);
+	mutex_unlock(&spu_prio->active_mutex[node]);
+}
+
+static int __node_allowed(struct spu_context *ctx, int node)
+{
+	if (nr_cpus_node(node)) {
+		cpumask_t mask = node_to_cpumask(node);
+
+		if (cpus_intersects(mask, ctx->cpus_allowed))
+			return 1;
 	}
-	mutex_unlock(&ctx->state_mutex);
 
-	if (preempted) {
-		/*
-		 * We need to break out of the wait loop in spu_run manually
-		 * to ensure this context gets put on the runqueue again
-		 * ASAP.
-		 */
-		wake_up(&ctx->stop_wq);
-	} else
-		spu_start_tick(ctx);
+	return 0;
+}
+
+static int node_allowed(struct spu_context *ctx, int node)
+{
+	int rval;
+
+	spin_lock(&spu_prio->runq_lock);
+	rval = __node_allowed(ctx, node);
+	spin_unlock(&spu_prio->runq_lock);
+
+	return rval;
 }
 
 /**
@@ -136,9 +175,18 @@
  */
 static void spu_add_to_active_list(struct spu *spu)
 {
-	mutex_lock(&spu_prio->active_mutex[spu->node]);
-	list_add_tail(&spu->list, &spu_prio->active_list[spu->node]);
-	mutex_unlock(&spu_prio->active_mutex[spu->node]);
+	int node = spu->node;
+
+	mutex_lock(&spu_prio->active_mutex[node]);
+	spu_prio->nr_active[node]++;
+	list_add_tail(&spu->list, &spu_prio->active_list[node]);
+	mutex_unlock(&spu_prio->active_mutex[node]);
+}
+
+static void __spu_remove_from_active_list(struct spu *spu)
+{
+	list_del_init(&spu->list);
+	spu_prio->nr_active[spu->node]--;
 }
 
 /**
@@ -150,7 +198,7 @@
 	int node = spu->node;
 
 	mutex_lock(&spu_prio->active_mutex[node]);
-	list_del_init(&spu->list);
+	__spu_remove_from_active_list(spu);
 	mutex_unlock(&spu_prio->active_mutex[node]);
 }
 
@@ -181,6 +229,10 @@
 {
 	pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
 		 spu->number, spu->node);
+
+	ctx->stats.slb_flt_base = spu->stats.slb_flt;
+	ctx->stats.class2_intr_base = spu->stats.class2_intr;
+
 	spu->ctx = ctx;
 	spu->flags = 0;
 	ctx->spu = spu;
@@ -198,8 +250,8 @@
 	spu->timestamp = jiffies;
 	spu_cpu_affinity_set(spu, raw_smp_processor_id());
 	spu_switch_notify(spu, ctx);
-	spu_add_to_active_list(spu);
 	ctx->state = SPU_STATE_RUNNABLE;
+	spu_switch_state(spu, SPU_UTIL_SYSTEM);
 }
 
 /**
@@ -212,7 +264,8 @@
 	pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
 		 spu->pid, spu->number, spu->node);
 
-	spu_remove_from_active_list(spu);
+	spu_switch_state(spu, SPU_UTIL_IDLE);
+
 	spu_switch_notify(spu, NULL);
 	spu_unmap_mappings(ctx);
 	spu_save(&ctx->csa, spu);
@@ -229,6 +282,11 @@
 	ctx->spu = NULL;
 	spu->flags = 0;
 	spu->ctx = NULL;
+
+	ctx->stats.slb_flt +=
+		(spu->stats.slb_flt - ctx->stats.slb_flt_base);
+	ctx->stats.class2_intr +=
+		(spu->stats.class2_intr - ctx->stats.class2_intr_base);
 }
 
 /**
@@ -237,20 +295,39 @@
  */
 static void __spu_add_to_rq(struct spu_context *ctx)
 {
-	int prio = ctx->prio;
-
-	list_add_tail(&ctx->rq, &spu_prio->runq[prio]);
-	set_bit(prio, spu_prio->bitmap);
+	/*
+	 * Unfortunately this code path can be called from multiple threads
+	 * on behalf of a single context due to the way the problem state
+	 * mmap support works.
+	 *
+	 * Fortunately we need to wake up all these threads at the same time
+	 * and can simply skip the runqueue addition for every but the first
+	 * thread getting into this codepath.
+	 *
+	 * It's still quite hacky, and long-term we should proxy all other
+	 * threads through the owner thread so that spu_run is in control
+	 * of all the scheduling activity for a given context.
+	 */
+	if (list_empty(&ctx->rq)) {
+		list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
+		set_bit(ctx->prio, spu_prio->bitmap);
+		if (!spu_prio->nr_waiting++)
+			__mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+	}
 }
 
 static void __spu_del_from_rq(struct spu_context *ctx)
 {
 	int prio = ctx->prio;
 
-	if (!list_empty(&ctx->rq))
+	if (!list_empty(&ctx->rq)) {
+		if (!--spu_prio->nr_waiting)
+			del_timer(&spusched_timer);
 		list_del_init(&ctx->rq);
-	if (list_empty(&spu_prio->runq[prio]))
-		clear_bit(prio, spu_prio->bitmap);
+
+		if (list_empty(&spu_prio->runq[prio]))
+			clear_bit(prio, spu_prio->bitmap);
+	}
 }
 
 static void spu_prio_wait(struct spu_context *ctx)
@@ -273,34 +350,6 @@
 	remove_wait_queue(&ctx->stop_wq, &wait);
 }
 
-/**
- * spu_reschedule - try to find a runnable context for a spu
- * @spu:       spu available
- *
- * This function is called whenever a spu becomes idle.  It looks for the
- * most suitable runnable spu context and schedules it for execution.
- */
-static void spu_reschedule(struct spu *spu)
-{
-	int best;
-
-	spu_free(spu);
-
-	spin_lock(&spu_prio->runq_lock);
-	best = sched_find_first_bit(spu_prio->bitmap);
-	if (best < MAX_PRIO) {
-		struct list_head *rq = &spu_prio->runq[best];
-		struct spu_context *ctx;
-
-		BUG_ON(list_empty(rq));
-
-		ctx = list_entry(rq->next, struct spu_context, rq);
-		__spu_del_from_rq(ctx);
-		wake_up(&ctx->stop_wq);
-	}
-	spin_unlock(&spu_prio->runq_lock);
-}
-
 static struct spu *spu_get_idle(struct spu_context *ctx)
 {
 	struct spu *spu = NULL;
@@ -309,7 +358,7 @@
 
 	for (n = 0; n < MAX_NUMNODES; n++, node++) {
 		node = (node < MAX_NUMNODES) ? node : 0;
-		if (!node_allowed(node))
+		if (!node_allowed(ctx, node))
 			continue;
 		spu = spu_alloc_node(node);
 		if (spu)
@@ -341,15 +390,15 @@
 	node = cpu_to_node(raw_smp_processor_id());
 	for (n = 0; n < MAX_NUMNODES; n++, node++) {
 		node = (node < MAX_NUMNODES) ? node : 0;
-		if (!node_allowed(node))
+		if (!node_allowed(ctx, node))
 			continue;
 
 		mutex_lock(&spu_prio->active_mutex[node]);
 		list_for_each_entry(spu, &spu_prio->active_list[node], list) {
 			struct spu_context *tmp = spu->ctx;
 
-			if (tmp->rt_priority < ctx->rt_priority &&
-			    (!victim || tmp->rt_priority < victim->rt_priority))
+			if (tmp->prio > ctx->prio &&
+			    (!victim || tmp->prio > victim->prio))
 				victim = spu->ctx;
 		}
 		mutex_unlock(&spu_prio->active_mutex[node]);
@@ -377,7 +426,10 @@
 				victim = NULL;
 				goto restart;
 			}
+			spu_remove_from_active_list(spu);
 			spu_unbind_context(spu, victim);
+			victim->stats.invol_ctx_switch++;
+			spu->stats.invol_ctx_switch++;
 			mutex_unlock(&victim->state_mutex);
 			/*
 			 * We need to break out of the wait loop in spu_run
@@ -403,22 +455,30 @@
  */
 int spu_activate(struct spu_context *ctx, unsigned long flags)
 {
-
-	if (ctx->spu)
-		return 0;
+	spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
 
 	do {
 		struct spu *spu;
 
+		/*
+		 * If there are multiple threads waiting for a single context
+		 * only one actually binds the context while the others will
+		 * only be able to acquire the state_mutex once the context
+		 * already is in runnable state.
+		 */
+		if (ctx->spu)
+			return 0;
+
 		spu = spu_get_idle(ctx);
 		/*
 		 * If this is a realtime thread we try to get it running by
 		 * preempting a lower priority thread.
 		 */
-		if (!spu && ctx->rt_priority)
+		if (!spu && rt_prio(ctx->prio))
 			spu = find_victim(ctx);
 		if (spu) {
 			spu_bind_context(spu, ctx);
+			spu_add_to_active_list(spu);
 			return 0;
 		}
 
@@ -429,6 +489,59 @@
 }
 
 /**
+ * grab_runnable_context - try to find a runnable context
+ *
+ * Remove the highest priority context on the runqueue and return it
+ * to the caller.  Returns %NULL if no runnable context was found.
+ */
+static struct spu_context *grab_runnable_context(int prio, int node)
+{
+	struct spu_context *ctx;
+	int best;
+
+	spin_lock(&spu_prio->runq_lock);
+	best = sched_find_first_bit(spu_prio->bitmap);
+	while (best < prio) {
+		struct list_head *rq = &spu_prio->runq[best];
+
+		list_for_each_entry(ctx, rq, rq) {
+			/* XXX(hch): check for affinity here aswell */
+			if (__node_allowed(ctx, node)) {
+				__spu_del_from_rq(ctx);
+				goto found;
+			}
+		}
+		best++;
+	}
+	ctx = NULL;
+ found:
+	spin_unlock(&spu_prio->runq_lock);
+	return ctx;
+}
+
+static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
+{
+	struct spu *spu = ctx->spu;
+	struct spu_context *new = NULL;
+
+	if (spu) {
+		new = grab_runnable_context(max_prio, spu->node);
+		if (new || force) {
+			spu_remove_from_active_list(spu);
+			spu_unbind_context(spu, ctx);
+			ctx->stats.vol_ctx_switch++;
+			spu->stats.vol_ctx_switch++;
+			spu_free(spu);
+			if (new)
+				wake_up(&new->stop_wq);
+		}
+
+	}
+
+	return new != NULL;
+}
+
+/**
  * spu_deactivate - unbind a context from it's physical spu
  * @ctx:	spu context to unbind
  *
@@ -437,12 +550,17 @@
  */
 void spu_deactivate(struct spu_context *ctx)
 {
-	struct spu *spu = ctx->spu;
-
-	if (spu) {
-		spu_unbind_context(spu, ctx);
-		spu_reschedule(spu);
+	/*
+	 * We must never reach this for a nosched context,
+	 * but handle the case gracefull instead of panicing.
+	 */
+	if (ctx->flags & SPU_CREATE_NOSCHED) {
+		WARN_ON(1);
+		return;
 	}
+
+	__spu_deactivate(ctx, 1, MAX_PRIO);
+	spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
 }
 
 /**
@@ -455,36 +573,180 @@
  */
 void spu_yield(struct spu_context *ctx)
 {
-	struct spu *spu;
-
-	if (mutex_trylock(&ctx->state_mutex)) {
-		if ((spu = ctx->spu) != NULL) {
-			int best = sched_find_first_bit(spu_prio->bitmap);
-			if (best < MAX_PRIO) {
-				pr_debug("%s: yielding SPU %d NODE %d\n",
-					 __FUNCTION__, spu->number, spu->node);
-				spu_deactivate(ctx);
-			}
+	if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
+		mutex_lock(&ctx->state_mutex);
+		if (__spu_deactivate(ctx, 0, MAX_PRIO))
+			spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
+		else {
+			spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED);
+			spu_switch_state(ctx->spu, SPU_UTIL_USER);
 		}
 		mutex_unlock(&ctx->state_mutex);
 	}
 }
 
+static void spusched_tick(struct spu_context *ctx)
+{
+	if (ctx->flags & SPU_CREATE_NOSCHED)
+		return;
+	if (ctx->policy == SCHED_FIFO)
+		return;
+
+	if (--ctx->time_slice)
+		return;
+
+	/*
+	 * Unfortunately active_mutex ranks outside of state_mutex, so
+	 * we have to trylock here.  If we fail give the context another
+	 * tick and try again.
+	 */
+	if (mutex_trylock(&ctx->state_mutex)) {
+		struct spu *spu = ctx->spu;
+		struct spu_context *new;
+
+		new = grab_runnable_context(ctx->prio + 1, spu->node);
+		if (new) {
+
+			__spu_remove_from_active_list(spu);
+			spu_unbind_context(spu, ctx);
+			ctx->stats.invol_ctx_switch++;
+			spu->stats.invol_ctx_switch++;
+			spu_free(spu);
+			wake_up(&new->stop_wq);
+			/*
+			 * We need to break out of the wait loop in
+			 * spu_run manually to ensure this context
+			 * gets put on the runqueue again ASAP.
+			 */
+			wake_up(&ctx->stop_wq);
+		}
+		spu_set_timeslice(ctx);
+		mutex_unlock(&ctx->state_mutex);
+	} else {
+		ctx->time_slice++;
+	}
+}
+
+/**
+ * count_active_contexts - count nr of active tasks
+ *
+ * Return the number of tasks currently running or waiting to run.
+ *
+ * Note that we don't take runq_lock / active_mutex here.  Reading
+ * a single 32bit value is atomic on powerpc, and we don't care
+ * about memory ordering issues here.
+ */
+static unsigned long count_active_contexts(void)
+{
+	int nr_active = 0, node;
+
+	for (node = 0; node < MAX_NUMNODES; node++)
+		nr_active += spu_prio->nr_active[node];
+	nr_active += spu_prio->nr_waiting;
+
+	return nr_active;
+}
+
+/**
+ * spu_calc_load - given tick count, update the avenrun load estimates.
+ * @tick:	tick count
+ *
+ * No locking against reading these values from userspace, as for
+ * the CPU loadavg code.
+ */
+static void spu_calc_load(unsigned long ticks)
+{
+	unsigned long active_tasks; /* fixed-point */
+	static int count = LOAD_FREQ;
+
+	count -= ticks;
+
+	if (unlikely(count < 0)) {
+		active_tasks = count_active_contexts() * FIXED_1;
+		do {
+			CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
+			CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
+			CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
+			count += LOAD_FREQ;
+		} while (count < 0);
+	}
+}
+
+static void spusched_wake(unsigned long data)
+{
+	mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+	wake_up_process(spusched_task);
+	spu_calc_load(SPUSCHED_TICK);
+}
+
+static int spusched_thread(void *unused)
+{
+	struct spu *spu, *next;
+	int node;
+
+	while (!kthread_should_stop()) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		for (node = 0; node < MAX_NUMNODES; node++) {
+			mutex_lock(&spu_prio->active_mutex[node]);
+			list_for_each_entry_safe(spu, next,
+						 &spu_prio->active_list[node],
+						 list)
+				spusched_tick(spu->ctx);
+			mutex_unlock(&spu_prio->active_mutex[node]);
+		}
+	}
+
+	return 0;
+}
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+static int show_spu_loadavg(struct seq_file *s, void *private)
+{
+	int a, b, c;
+
+	a = spu_avenrun[0] + (FIXED_1/200);
+	b = spu_avenrun[1] + (FIXED_1/200);
+	c = spu_avenrun[2] + (FIXED_1/200);
+
+	/*
+	 * Note that last_pid doesn't really make much sense for the
+	 * SPU loadavg (it even seems very odd on the CPU side..),
+	 * but we include it here to have a 100% compatible interface.
+	 */
+	seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
+		LOAD_INT(a), LOAD_FRAC(a),
+		LOAD_INT(b), LOAD_FRAC(b),
+		LOAD_INT(c), LOAD_FRAC(c),
+		count_active_contexts(),
+		atomic_read(&nr_spu_contexts),
+		current->nsproxy->pid_ns->last_pid);
+	return 0;
+}
+
+static int spu_loadavg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, show_spu_loadavg, NULL);
+}
+
+static const struct file_operations spu_loadavg_fops = {
+	.open		= spu_loadavg_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 int __init spu_sched_init(void)
 {
-	int i;
-
-	spu_sched_wq = create_singlethread_workqueue("spusched");
-	if (!spu_sched_wq)
-		return 1;
+	struct proc_dir_entry *entry;
+	int err = -ENOMEM, i;
 
 	spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
-	if (!spu_prio) {
-		printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
-		       __FUNCTION__);
-		       destroy_workqueue(spu_sched_wq);
-		return 1;
-	}
+	if (!spu_prio)
+		goto out;
+
 	for (i = 0; i < MAX_PRIO; i++) {
 		INIT_LIST_HEAD(&spu_prio->runq[i]);
 		__clear_bit(i, spu_prio->bitmap);
@@ -495,7 +757,30 @@
 		INIT_LIST_HEAD(&spu_prio->active_list[i]);
 	}
 	spin_lock_init(&spu_prio->runq_lock);
+
+	setup_timer(&spusched_timer, spusched_wake, 0);
+
+	spusched_task = kthread_run(spusched_thread, NULL, "spusched");
+	if (IS_ERR(spusched_task)) {
+		err = PTR_ERR(spusched_task);
+		goto out_free_spu_prio;
+	}
+
+	entry = create_proc_entry("spu_loadavg", 0, NULL);
+	if (!entry)
+		goto out_stop_kthread;
+	entry->proc_fops = &spu_loadavg_fops;
+
+	pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n",
+			SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE);
 	return 0;
+
+ out_stop_kthread:
+	kthread_stop(spusched_task);
+ out_free_spu_prio:
+	kfree(spu_prio);
+ out:
+	return err;
 }
 
 void __exit spu_sched_exit(void)
@@ -503,6 +788,11 @@
 	struct spu *spu, *tmp;
 	int node;
 
+	remove_proc_entry("spu_loadavg", NULL);
+
+	del_timer_sync(&spusched_timer);
+	kthread_stop(spusched_task);
+
 	for (node = 0; node < MAX_NUMNODES; node++) {
 		mutex_lock(&spu_prio->active_mutex[node]);
 		list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node],
@@ -513,5 +803,4 @@
 		mutex_unlock(&spu_prio->active_mutex[node]);
 	}
 	kfree(spu_prio);
-	destroy_workqueue(spu_sched_wq);
 }
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore.c b/arch/powerpc/platforms/cell/spufs/spu_restore.c
index 0bf723d..4e19ed7 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_restore.c
+++ b/arch/powerpc/platforms/cell/spufs/spu_restore.c
@@ -296,7 +296,7 @@
  * This code deviates from the documented sequence in the
  * following aspects:
  *
- * 	1. The EA for LSCSA is passed from PPE in the
+ *	1. The EA for LSCSA is passed from PPE in the
  *	   signal notification channels.
  *	2. The register spill area is pulled by SPU
  *	   into LS, rather than pushed by PPE.
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save.c b/arch/powerpc/platforms/cell/spufs/spu_save.c
index 196033b..ae95cc1 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_save.c
+++ b/arch/powerpc/platforms/cell/spufs/spu_save.c
@@ -44,7 +44,7 @@
 	 *    Read the SPU_RdEventMsk channel and save to the LSCSA.
 	 */
 	offset = LSCSA_QW_OFFSET(event_mask);
-	regs_spill[offset].slot[0] = spu_readch(SPU_RdEventStatMask);
+	regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask);
 }
 
 static inline void save_tag_mask(void)
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 0a947fd..08b3530 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/fs.h>
+#include <linux/cpumask.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
@@ -39,9 +40,17 @@
 struct spu_context_ops;
 struct spu_gang;
 
-/* ctx->sched_flags */
-enum {
-	SPU_SCHED_EXITING = 0,
+/*
+ * This is the state for spu utilization reporting to userspace.
+ * Because this state is visible to userspace it must never change and needs
+ * to be kept strictly separate from any internal state kept by the kernel.
+ */
+enum spuctx_execution_state {
+	SPUCTX_UTIL_USER = 0,
+	SPUCTX_UTIL_SYSTEM,
+	SPUCTX_UTIL_IOWAIT,
+	SPUCTX_UTIL_LOADED,
+	SPUCTX_UTIL_MAX
 };
 
 struct spu_context {
@@ -55,7 +64,7 @@
 	struct address_space *signal2;	   /* 'signal2' area mappings. */
 	struct address_space *mss;	   /* 'mss' area mappings. */
 	struct address_space *psmap;	   /* 'psmap' area mappings. */
-	spinlock_t mapping_lock;
+	struct mutex mapping_lock;
 	u64 object_id;		   /* user space pointer for oprofile */
 
 	enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
@@ -81,13 +90,34 @@
 	struct list_head gang_list;
 	struct spu_gang *gang;
 
+	/* owner thread */
+	pid_t tid;
+
 	/* scheduler fields */
- 	struct list_head rq;
-	struct delayed_work sched_work;
+	struct list_head rq;
+	unsigned int time_slice;
 	unsigned long sched_flags;
-	unsigned long rt_priority;
+	cpumask_t cpus_allowed;
 	int policy;
 	int prio;
+
+	/* statistics */
+	struct {
+		/* updates protected by ctx->state_mutex */
+		enum spuctx_execution_state execution_state;
+		unsigned long tstamp;		/* time of last ctx switch */
+		unsigned long times[SPUCTX_UTIL_MAX];
+		unsigned long long vol_ctx_switch;
+		unsigned long long invol_ctx_switch;
+		unsigned long long min_flt;
+		unsigned long long maj_flt;
+		unsigned long long hash_flt;
+		unsigned long long slb_flt;
+		unsigned long long slb_flt_base; /* # at last ctx switch */
+		unsigned long long class2_intr;
+		unsigned long long class2_intr_base; /* # at last ctx switch */
+		unsigned long long libassist;
+	} stats;
 };
 
 struct spu_gang {
@@ -177,6 +207,7 @@
 int spufs_handle_class1(struct spu_context *ctx);
 
 /* context management */
+extern atomic_t nr_spu_contexts;
 static inline void spu_acquire(struct spu_context *ctx)
 {
 	mutex_lock(&ctx->state_mutex);
@@ -200,9 +231,9 @@
 int spu_activate(struct spu_context *ctx, unsigned long flags);
 void spu_deactivate(struct spu_context *ctx);
 void spu_yield(struct spu_context *ctx);
-void spu_start_tick(struct spu_context *ctx);
-void spu_stop_tick(struct spu_context *ctx);
-void spu_sched_tick(struct work_struct *work);
+void spu_set_timeslice(struct spu_context *ctx);
+void spu_update_sched_info(struct spu_context *ctx);
+void __spu_update_sched_info(struct spu_context *ctx);
 int __init spu_sched_init(void);
 void __exit spu_sched_exit(void);
 
@@ -210,7 +241,7 @@
 
 /*
  * spufs_wait
- * 	Same as wait_event_interruptible(), except that here
+ *	Same as wait_event_interruptible(), except that here
  *	we need to call spu_release(ctx) before sleeping, and
  *	then spu_acquire(ctx) when awoken.
  */
@@ -256,4 +287,37 @@
 extern struct spufs_coredump_reader spufs_coredump_read[];
 extern int spufs_coredump_num_notes;
 
+/*
+ * This function is a little bit too large for an inline, but
+ * as fault.c is built into the kernel we can't move it out of
+ * line.
+ */
+static inline void spuctx_switch_state(struct spu_context *ctx,
+		enum spuctx_execution_state new_state)
+{
+	WARN_ON(!mutex_is_locked(&ctx->state_mutex));
+
+	if (ctx->stats.execution_state != new_state) {
+		unsigned long curtime = jiffies;
+
+		ctx->stats.times[ctx->stats.execution_state] +=
+				 curtime - ctx->stats.tstamp;
+		ctx->stats.tstamp = curtime;
+		ctx->stats.execution_state = new_state;
+	}
+}
+
+static inline void spu_switch_state(struct spu *spu,
+		enum spuctx_execution_state new_state)
+{
+	if (spu->stats.utilization_state != new_state) {
+		unsigned long curtime = jiffies;
+
+		spu->stats.times[spu->stats.utilization_state] +=
+				 curtime - spu->stats.tstamp;
+		spu->stats.tstamp = curtime;
+		spu->stats.utilization_state = new_state;
+	}
+}
+
 #endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 71a0b41..9c506ba 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -70,7 +70,7 @@
   }
 #endif				/* debug */
 
-#define POLL_WHILE_FALSE(_c) 	POLL_WHILE_TRUE(!(_c))
+#define POLL_WHILE_FALSE(_c)	POLL_WHILE_TRUE(!(_c))
 
 static inline void acquire_spu_lock(struct spu *spu)
 {
@@ -387,6 +387,19 @@
 	csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW);
 }
 
+static inline void save_ppu_tagstatus(struct spu_state *csa, struct spu *spu)
+{
+	struct spu_problem __iomem *prob = spu->problem;
+
+	/* Save the Prxy_TagStatus register in the CSA.
+	 *
+	 * It is unnecessary to restore dma_tagstatus_R, however,
+	 * dma_tagstatus_R in the CSA is accessed via backing_ops, so
+	 * we must save it.
+	 */
+	csa->prob.dma_tagstatus_R = in_be32(&prob->dma_tagstatus_R);
+}
+
 static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -1812,6 +1825,7 @@
 	save_mfc_queues(prev, spu);	/* Step 19. */
 	save_ppu_querymask(prev, spu);	/* Step 20. */
 	save_ppu_querytype(prev, spu);	/* Step 21. */
+	save_ppu_tagstatus(prev, spu);  /* NEW.     */
 	save_mfc_csr_tsq(prev, spu);	/* Step 22. */
 	save_mfc_csr_cmd(prev, spu);	/* Step 23. */
 	save_mfc_csr_ato(prev, spu);	/* Step 24. */
@@ -1930,7 +1944,7 @@
 	reset_spu_privcntl(prev, spu);	        /* Step 16. */
 	reset_spu_lslr(prev, spu);              /* Step 17. */
 	setup_mfc_sr1(prev, spu);	        /* Step 18. */
-	spu_invalidate_slbs(spu);        	/* Step 19. */
+	spu_invalidate_slbs(spu);		/* Step 19. */
 	reset_ch_part1(prev, spu);	        /* Step 20. */
 	reset_ch_part2(prev, spu);	        /* Step 21. */
 	enable_interrupts(prev, spu);	        /* Step 22. */
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile
index f4f8252..5240046 100644
--- a/arch/powerpc/platforms/celleb/Makefile
+++ b/arch/powerpc/platforms/celleb/Makefile
@@ -4,5 +4,5 @@
 
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_PPC_UDBG_BEAT)	+= udbg_beat.o
-obj-$(CONFIG_HAS_TXX9_SERIAL)	+= scc_sio.o
+obj-$(CONFIG_SERIAL_TXX9)	+= scc_sio.o
 obj-$(CONFIG_SPU_BASE)		+= spu_priv1.o
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig
index d2c6905..22b4b4e 100644
--- a/arch/powerpc/platforms/chrp/Kconfig
+++ b/arch/powerpc/platforms/chrp/Kconfig
@@ -8,4 +8,5 @@
 	select PPC_MPC106
 	select PPC_UDBG_16550
 	select PPC_NATIVE
+	select PCI
 	default y
diff --git a/arch/powerpc/platforms/chrp/Makefile b/arch/powerpc/platforms/chrp/Makefile
index 902feb1..4b3bfad 100644
--- a/arch/powerpc/platforms/chrp/Makefile
+++ b/arch/powerpc/platforms/chrp/Makefile
@@ -1,4 +1,3 @@
-obj-y				+= setup.o time.o pegasos_eth.o
-obj-$(CONFIG_PCI)		+= pci.o
+obj-y				+= setup.o time.o pegasos_eth.o pci.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_NVRAM)		+= nvram.o
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index d32fedc..3690624 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -99,7 +99,7 @@
 	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 		| (((bus->number - hose->first_busno) & 0xff) << 16)
-		| (hose->index << 24);
+		| (hose->global_number << 24);
         int ret = -1;
 	int rval;
 
@@ -114,7 +114,7 @@
 	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 		| (((bus->number - hose->first_busno) & 0xff) << 16)
-		| (hose->index << 24);
+		| (hose->global_number << 24);
 	int rval;
 
 	rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
@@ -254,13 +254,12 @@
 			printk(" at %llx", (unsigned long long)r.start);
 		printk("\n");
 
-		hose = pcibios_alloc_controller();
+		hose = pcibios_alloc_controller(dev);
 		if (!hose) {
 			printk("Can't allocate PCI controller structure for %s\n",
 				dev->full_name);
 			continue;
 		}
-		hose->arch_data = dev;
 		hose->first_busno = bus_range[0];
 		hose->last_busno = bus_range[1];
 
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
index 7104567..5bcc58d 100644
--- a/arch/powerpc/platforms/chrp/pegasos_eth.c
+++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
@@ -169,7 +169,7 @@
 
 /***********/
 /***********/
-int mv643xx_eth_add_pds(void)
+static int __init mv643xx_eth_add_pds(void)
 {
 	int ret = 0;
 	static struct pci_device_id pci_marvell_mv64360[] = {
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index f2d2626..bec7726 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -28,6 +28,7 @@
 	bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)"
 	select TSI108_BRIDGE
 	select PPC_UDBG_16550
+	select WANT_DEVICE_TREE
 	help
 	  Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
 	  Board with TSI108/9 bridge (Hickory/Holly)
@@ -44,6 +45,7 @@
 config TSI108_BRIDGE
 	bool
 	depends on MPC7448HPC2 || PPC_HOLLY
+	select PCI
 	select MPIC
 	select MPIC_WEIRD
 	default y
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index 3a0b4a0..6292e36 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -45,7 +45,7 @@
 
 #define HOLLY_PCI_CFG_PHYS 0x7c000000
 
-int holly_exclude_device(u_char bus, u_char devfn)
+int holly_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index b412f00..f4d0a7a 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -54,8 +54,9 @@
 	},
 };
 
-static int __init add_bridge(struct device_node *dev)
+static int __init linkstation_add_bridge(struct device_node *dev)
 {
+#ifdef CONFIG_PCI
 	int len;
 	struct pci_controller *hose;
 	const int *bus_range;
@@ -67,18 +68,17 @@
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 				" bus 0\n", dev->full_name);
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(dev);
 	if (hose == NULL)
 		return -ENOMEM;
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
-	hose->arch_data = dev;
 	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
 
 	/* Interpret the "ranges" property */
 	/* This also maps the I/O region and sets isa_io/mem_base */
 	pci_process_bridge_OF_ranges(hose, dev, 1);
-
+#endif
 	return 0;
 }
 
@@ -92,7 +92,7 @@
 
 	/* Lookup PCI host bridges */
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
+		linkstation_add_bridge(np);
 
 	printk(KERN_INFO "BUFFALO Network Attached Storage Series\n");
 	printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n");
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index 4542e0c8..1e3cc69 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -54,15 +54,10 @@
 
 #define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000
 
-#ifndef CONFIG_PCI
-isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
-isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
-pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
-#endif
-
 extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
 
-int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
+int mpc7448_hpc2_exclude_device(struct pci_controller *hose,
+				u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
index a543a52..f7e0e0c 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
@@ -18,9 +18,4 @@
 
 #include <asm/ppcboot.h>
 
-/* Base Addresses for the PCI bus
- */
-#define MPC7448_HPC2_PCI_MEM_OFFSET	(0x00000000)
-#define MPC7448_HPC2_ISA_IO_BASE	(0x00000000)
-#define MPC7448_HPC2_ISA_MEM_BASE	(0x00000000)
 #endif				/* __PPC_PLATFORMS_MPC7448_HPC2_H */
diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h
index a843b0f..8d95fe4b 100644
--- a/arch/powerpc/platforms/iseries/call_hpt.h
+++ b/arch/powerpc/platforms/iseries/call_hpt.h
@@ -76,24 +76,25 @@
 	return compressedStatus;
 }
 
-static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn)
+static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn)
 {
 	return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
 }
 
-static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex,
+static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex,
 		u8 bitson, u8 bitsoff)
 {
 	return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
 			bitson, bitsoff);
 }
 
-static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex)
+static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex)
 {
 	HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
 }
 
-static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte)
+static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit,
+					 struct hash_pte *hpte)
 {
 	HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
 }
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c
index ed44dfc..b4e2c7a 100644
--- a/arch/powerpc/platforms/iseries/htab.c
+++ b/arch/powerpc/platforms/iseries/htab.c
@@ -44,7 +44,7 @@
 			 unsigned long vflags, int psize)
 {
 	long slot;
-	hpte_t lhpte;
+	struct hash_pte lhpte;
 	int secondary = 0;
 
 	BUG_ON(psize != MMU_PAGE_4K);
@@ -99,7 +99,7 @@
 
 static unsigned long iSeries_hpte_getword0(unsigned long slot)
 {
-	hpte_t hpte;
+	struct hash_pte hpte;
 
 	HvCallHpt_get(&hpte, slot);
 	return hpte.v;
@@ -144,7 +144,7 @@
 static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
 				  unsigned long va, int psize, int local)
 {
-	hpte_t hpte;
+	struct hash_pte hpte;
 	unsigned long want_v;
 
 	iSeries_hlock(slot);
@@ -176,7 +176,7 @@
  */
 static long iSeries_hpte_find(unsigned long vpn)
 {
-	hpte_t hpte;
+	struct hash_pte hpte;
 	long slot;
 
 	/*
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 9c97422..da87162 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -742,6 +742,11 @@
 	/* Install IO hooks */
 	ppc_pci_io = iseries_pci_io;
 
+	/* iSeries has no IO space in the common sense, it needs to set
+	 * the IO base to 0
+	 */
+	pci_io_base = 0;
+
 	if (root == NULL) {
 		printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
 				"of device tree\n");
@@ -763,7 +768,7 @@
 		if (phb == NULL)
 			continue;
 
-		phb->pci_mem_offset = phb->local_number = bus;
+		phb->pci_mem_offset = bus;
 		phb->first_busno = bus;
 		phb->last_busno = bus;
 		phb->ops = &iSeries_pci_ops;
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 7f5dcee..13a8b19 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -79,8 +79,6 @@
 static void iSeries_pci_final_fixup(void) { }
 #endif
 
-extern unsigned long iSeries_recal_tb;
-extern unsigned long iSeries_recal_titan;
 
 struct MemoryBlock {
 	unsigned long absStart;
@@ -292,8 +290,8 @@
 {
 	DBG(" -> iSeries_init_early()\n");
 
-	iSeries_recal_tb = get_tb();
-	iSeries_recal_titan = HvCallXm_loadTod();
+	/* Snapshot the timebase, for use in later recalibration */
+	iSeries_time_init_early();
 
 	/*
 	 * Initialize the DMA/TCE management
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 7aaa5bb..fceaae4 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -444,7 +444,7 @@
 	u3_ht = hose;
 }
 
-static int __init add_bridge(struct device_node *dev)
+static int __init maple_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -519,23 +519,6 @@
 	DBG(" <- maple_pci_irq_fixup\n");
 }
 
-static void __init maple_fixup_phb_resources(void)
-{
-	struct pci_controller *hose, *tmp;
-	
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
-		hose->io_resource.start += offset;
-		hose->io_resource.end += offset;
-
-		printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n",
-		       hose->global_number,
-		       (unsigned long long)hose->io_resource.start,
-		       (unsigned long long)hose->io_resource.end);
-	}
-}
-
 void __init maple_pci_init(void)
 {
 	struct device_node *np, *root;
@@ -558,7 +541,7 @@
 			continue;
 		if ((of_device_is_compatible(np, "u4-pcie") ||
 		     of_device_is_compatible(np, "u3-agp")) &&
-		    add_bridge(np) == 0)
+		    maple_add_bridge(np) == 0)
 			of_node_get(np);
 
 		if (of_device_is_compatible(np, "u3-ht")) {
@@ -570,27 +553,9 @@
 
 	/* Now setup the HyperTransport host if we found any
 	 */
-	if (ht && add_bridge(ht) != 0)
+	if (ht && maple_add_bridge(ht) != 0)
 		of_node_put(ht);
 
-        /*
-         * We need to call pci_setup_phb_io for the HT bridge first
-         * so it gets the I/O port numbers starting at 0, and we
-         * need to call it for the AGP bridge after that so it gets
-         * small positive I/O port numbers.
-         */
-        if (u3_ht)
-                pci_setup_phb_io(u3_ht, 1);
-        if (u3_agp)
-                pci_setup_phb_io(u3_agp, 0);
-        if (u4_pcie)
-                pci_setup_phb_io(u4_pcie, 0);
-
-	/* Fixup the IO resources on our host bridges as the common code
-	 * does it only for childs of the host bridges
-	 */
-	maple_fixup_phb_resources();
-
 	/* Setup the linkage between OF nodes and PHBs */ 
 	pci_devs_phb_init();
 
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 7c5076e..95cd90f 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -25,4 +25,13 @@
 	help
 	  Driver for MDIO via GPIO on PWRficient platforms
 
+config ELECTRA_IDE
+      tristate "Electra IDE driver"
+      default y
+      depends on PPC_PASEMI && ATA
+      select PATA_PLATFORM
+      help
+	This includes driver support for the Electra on-board IDE
+	interface.
+
 endmenu
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile
index 2cd2a4f..f47fcac 100644
--- a/arch/powerpc/platforms/pasemi/Makefile
+++ b/arch/powerpc/platforms/pasemi/Makefile
@@ -1,3 +1,4 @@
 obj-y	+= setup.o pci.o time.o idle.o powersave.o iommu.o
 obj-$(CONFIG_PPC_PASEMI_MDIO)	+= gpio_mdio.o
+obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
 obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c
new file mode 100644
index 0000000..12fb0c9
--- /dev/null
+++ b/arch/powerpc/platforms/pasemi/electra_ide.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/platform_device.h>
+
+#include <asm/prom.h>
+#include <asm/system.h>
+
+/* The electra IDE interface is incredibly simple: Just a device on the localbus
+ * with interrupts hooked up to one of the GPIOs. The device tree contains the
+ * address window and interrupt mappings already, and the pata_platform driver handles
+ * the rest. We just need to hook the two up.
+ */
+
+#define MAX_IFS	4	/* really, we have only one */
+
+static struct platform_device *pdevs[MAX_IFS];
+
+static int __devinit electra_ide_init(void)
+{
+	struct device_node *np;
+	struct resource r[3];
+	int ret = 0;
+	int i;
+
+	np = of_find_compatible_node(NULL, "ide", "electra-ide");
+	i = 0;
+
+	while (np && i < MAX_IFS) {
+		memset(r, 0, sizeof(r));
+
+		/* pata_platform wants two address ranges: one for the base registers,
+		 * another for the control (altstatus). It's located at offset 0x3f6 in
+		 * the window, but the device tree only has one large register window
+		 * that covers both ranges. So we need to split it up by hand here:
+		 */
+
+		ret = of_address_to_resource(np, 0, &r[0]);
+		if (ret)
+			goto out;
+		ret = of_address_to_resource(np, 0, &r[1]);
+		if (ret)
+			goto out;
+
+		r[1].start += 0x3f6;
+		r[0].end = r[1].start-1;
+
+		r[2].start = irq_of_parse_and_map(np, 0);
+		r[2].end = irq_of_parse_and_map(np, 0);
+		r[2].flags = IORESOURCE_IRQ;
+
+		pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n",
+			 r[0].start, r[1].start, r[2].start);
+		pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3);
+		if (IS_ERR(pdevs[i])) {
+			ret = PTR_ERR(pdevs[i]);
+			pdevs[i] = NULL;
+			goto out;
+		}
+		np = of_find_compatible_node(np, "ide", "electra-ide");
+	}
+out:
+	return ret;
+}
+module_init(electra_ide_init);
+
+static void __devexit electra_ide_exit(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_IFS; i++)
+		if (pdevs[i])
+			platform_device_unregister(pdevs[i]);
+}
+module_exit(electra_ide_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi Electra IDE driver");
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c
index 03cd45d8..3c962d5 100644
--- a/arch/powerpc/platforms/pasemi/idle.c
+++ b/arch/powerpc/platforms/pasemi/idle.c
@@ -26,6 +26,7 @@
 
 #include <asm/machdep.h>
 #include <asm/reg.h>
+#include <asm/smp.h>
 
 #include "pasemi.h"
 
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 95fa6a7..f33b21b 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -31,8 +31,6 @@
 #define IOBMAP_PAGE_SIZE	(1 << IOBMAP_PAGE_SHIFT)
 #define IOBMAP_PAGE_MASK	(IOBMAP_PAGE_SIZE - 1)
 
-#define IOBMAP_PAGE_FACTOR	(PAGE_SHIFT - IOBMAP_PAGE_SHIFT)
-
 #define IOB_BASE		0xe0000000
 #define IOB_SIZE		0x3000
 /* Configuration registers */
@@ -97,9 +95,6 @@
 
 	bus_addr = (tbl->it_offset + index) << PAGE_SHIFT;
 
-	npages <<= IOBMAP_PAGE_FACTOR;
-	index <<= IOBMAP_PAGE_FACTOR;
-
 	ip = ((u32 *)tbl->it_base) + index;
 
 	while (npages--) {
@@ -125,9 +120,6 @@
 
 	bus_addr = (tbl->it_offset + index) << PAGE_SHIFT;
 
-	npages <<= IOBMAP_PAGE_FACTOR;
-	index <<= IOBMAP_PAGE_FACTOR;
-
 	ip = ((u32 *)tbl->it_base) + index;
 
 	while (npages--) {
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index bbc6dfc..ab1f5f6 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -132,7 +132,7 @@
 	hose->cfg_data = ioremap(0xe0000000, 0x10000000);
 }
 
-static int __init add_bridge(struct device_node *dev)
+static int __init pas_add_bridge(struct device_node *dev)
 {
 	struct pci_controller *hose;
 
@@ -150,29 +150,11 @@
 	printk(KERN_INFO "Found PA-PXP PCI host bridge.\n");
 
 	/* Interpret the "ranges" property */
-	/* This also maps the I/O region and sets isa_io/mem_base */
 	pci_process_bridge_OF_ranges(hose, dev, 1);
-	pci_setup_phb_io(hose, 1);
 
 	return 0;
 }
 
-
-static void __init pas_fixup_phb_resources(void)
-{
-	struct pci_controller *hose, *tmp;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
-		hose->io_resource.start += offset;
-		hose->io_resource.end += offset;
-		printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
-		       hose->global_number,
-		       hose->io_resource.start, hose->io_resource.end);
-	}
-}
-
-
 void __init pas_pci_init(void)
 {
 	struct device_node *np, *root;
@@ -185,13 +167,11 @@
 	}
 
 	for (np = NULL; (np = of_get_next_child(root, np)) != NULL;)
-		if (np->name && !strcmp(np->name, "pxp") && !add_bridge(np))
+		if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np))
 			of_node_get(np);
 
 	of_node_put(root);
 
-	pas_fixup_phb_resources();
-
 	/* Setup the linkage between OF nodes and PHBs */
 	pci_devs_phb_init();
 
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index c5a3f61..ffe6528 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -239,7 +239,7 @@
 	return 1;
 }
 
-define_machine(pas) {
+define_machine(pasemi) {
 	.name			= "PA Semi PA6T-1682M",
 	.probe			= pas_probe,
 	.setup_arch		= pas_setup_arch,
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
index 5b7afe5..055990c 100644
--- a/arch/powerpc/platforms/powermac/Kconfig
+++ b/arch/powerpc/platforms/powermac/Kconfig
@@ -2,6 +2,7 @@
 	bool "Apple PowerMac based machines"
 	depends on PPC_MULTIPLATFORM
 	select MPIC
+	select PCI
 	select PPC_INDIRECT_PCI if PPC32
 	select PPC_MPC106 if PPC32
 	select PPC_NATIVE
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 3f507ab..efdf5eb 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -42,6 +42,7 @@
 #include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <linux/timer.h>
+#include <linux/mutex.h>
 #include <asm/keylargo.h>
 #include <asm/uninorth.h>
 #include <asm/io.h>
@@ -84,7 +85,7 @@
 	void			*hostdata;
 	int			channel;	/* some hosts have multiple */
 	int			mode;		/* current mode */
-	struct semaphore	sem;
+	struct mutex		mutex;
 	int			opened;
 	int			polled;		/* open mode */
 	struct platform_device	*platform_dev;
@@ -104,7 +105,7 @@
 
 struct pmac_i2c_host_kw
 {
-	struct semaphore	mutex;		/* Access mutex for use by
+	struct mutex		mutex;		/* Access mutex for use by
 						 * i2c-keywest */
 	void __iomem		*base;		/* register base address */
 	int			bsteps;		/* register stepping */
@@ -375,14 +376,14 @@
 static int kw_i2c_open(struct pmac_i2c_bus *bus)
 {
 	struct pmac_i2c_host_kw *host = bus->hostdata;
-	down(&host->mutex);
+	mutex_lock(&host->mutex);
 	return 0;
 }
 
 static void kw_i2c_close(struct pmac_i2c_bus *bus)
 {
 	struct pmac_i2c_host_kw *host = bus->hostdata;
-	up(&host->mutex);
+	mutex_unlock(&host->mutex);
 }
 
 static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
@@ -498,7 +499,7 @@
 		kfree(host);
 		return NULL;
 	}
-	init_MUTEX(&host->mutex);
+	mutex_init(&host->mutex);
 	init_completion(&host->complete);
 	spin_lock_init(&host->lock);
 	init_timer(&host->timeout_timer);
@@ -571,7 +572,7 @@
 	bus->open = kw_i2c_open;
 	bus->close = kw_i2c_close;
 	bus->xfer = kw_i2c_xfer;
-	init_MUTEX(&bus->sem);
+	mutex_init(&bus->mutex);
 	if (controller == busnode)
 		bus->flags = pmac_i2c_multibus;
 	list_add(&bus->link, &pmac_i2c_busses);
@@ -798,7 +799,7 @@
 		bus->mode = pmac_i2c_mode_std;
 		bus->hostdata = bus + 1;
 		bus->xfer = pmu_i2c_xfer;
-		init_MUTEX(&bus->sem);
+		mutex_init(&bus->mutex);
 		bus->flags = pmac_i2c_multibus;
 		list_add(&bus->link, &pmac_i2c_busses);
 
@@ -921,7 +922,7 @@
 		bus->mode = pmac_i2c_mode_std;
 		bus->hostdata = bus + 1;
 		bus->xfer = smu_i2c_xfer;
-		init_MUTEX(&bus->sem);
+		mutex_init(&bus->mutex);
 		bus->flags = 0;
 		list_add(&bus->link, &pmac_i2c_busses);
 
@@ -1093,13 +1094,13 @@
 {
 	int rc;
 
-	down(&bus->sem);
+	mutex_lock(&bus->mutex);
 	bus->polled = polled || pmac_i2c_force_poll;
 	bus->opened = 1;
 	bus->mode = pmac_i2c_mode_std;
 	if (bus->open && (rc = bus->open(bus)) != 0) {
 		bus->opened = 0;
-		up(&bus->sem);
+		mutex_unlock(&bus->mutex);
 		return rc;
 	}
 	return 0;
@@ -1112,7 +1113,7 @@
 	if (bus->close)
 		bus->close(bus);
 	bus->opened = 0;
-	up(&bus->sem);
+	mutex_unlock(&bus->mutex);
 }
 EXPORT_SYMBOL_GPL(pmac_i2c_close);
 
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index c4af9e2..92586db 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -35,8 +35,6 @@
 #define DBG(x...)
 #endif
 
-static int add_bridge(struct device_node *dev);
-
 /* XXX Could be per-controller, but I don't think we risk anything by
  * assuming we won't have both UniNorth and Bandit */
 static int has_uninorth;
@@ -897,7 +895,7 @@
  * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
  * if we have one or more bandit or chaos bridges, we don't have a MPC106.
  */
-static int __init add_bridge(struct device_node *dev)
+static int __init pmac_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -918,15 +916,9 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	/* XXX Different prototypes, to be merged */
-#ifdef CONFIG_PPC64
 	hose = pcibios_alloc_controller(dev);
-#else
-	hose = pcibios_alloc_controller();
-#endif
 	if (!hose)
 		return -ENOMEM;
-	hose->arch_data = dev;
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
@@ -1006,19 +998,6 @@
 #endif /* CONFIG_PPC32 */
 }
 
-#ifdef CONFIG_PPC64
-static void __init pmac_fixup_phb_resources(void)
-{
-	struct pci_controller *hose, *tmp;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
-		       hose->global_number,
-		       hose->io_resource.start, hose->io_resource.end);
-	}
-}
-#endif
-
 void __init pmac_pci_init(void)
 {
 	struct device_node *np, *root;
@@ -1036,7 +1015,7 @@
 		if (strcmp(np->name, "bandit") == 0
 		    || strcmp(np->name, "chaos") == 0
 		    || strcmp(np->name, "pci") == 0) {
-			if (add_bridge(np) == 0)
+			if (pmac_add_bridge(np) == 0)
 				of_node_get(np);
 		}
 		if (strcmp(np->name, "ht") == 0) {
@@ -1050,28 +1029,9 @@
 	/* Probe HT last as it relies on the agp resources to be already
 	 * setup
 	 */
-	if (ht && add_bridge(ht) != 0)
+	if (ht && pmac_add_bridge(ht) != 0)
 		of_node_put(ht);
 
-	/*
-	 * We need to call pci_setup_phb_io for the HT bridge first
-	 * so it gets the I/O port numbers starting at 0, and we
-	 * need to call it for the AGP bridge after that so it gets
-	 * small positive I/O port numbers.
-	 */
-	if (u3_ht)
-		pci_setup_phb_io(u3_ht, 1);
-	if (u3_agp)
-		pci_setup_phb_io(u3_agp, 0);
-	if (u4_pcie)
-		pci_setup_phb_io(u4_pcie, 0);
-
-	/*
-	 * On ppc64, fixup the IO resources on our host bridges as
-	 * the common code does it only for children of the host bridges
-	 */
-	pmac_fixup_phb_resources();
-
 	/* Setup the linkage between OF nodes and PHBs */
 	pci_devs_phb_init();
 
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index a410bc76..7ccb923 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -363,8 +363,19 @@
 		smp_ops = &core99_smp_ops;
 	}
 #ifdef CONFIG_PPC32
-	else
+	else {
+		/*
+		 * We have to set bits in cpu_possible_map here since the
+		 * secondary CPU(s) aren't in the device tree, and
+		 * setup_per_cpu_areas only allocates per-cpu data for
+		 * CPUs in the cpu_possible_map.
+		 */
+		int cpu;
+
+		for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu)
+			cpu_set(cpu, cpu_possible_map);
 		smp_ops = &psurge_smp_ops;
+	}
 #endif
 #endif /* CONFIG_SMP */
 
@@ -384,7 +395,7 @@
 static dev_t boot_dev;
 
 #ifdef CONFIG_SCSI
-void __init note_scsi_host(struct device_node *node, void *host)
+void note_scsi_host(struct device_node *node, void *host)
 {
 	int l;
 	char *p;
@@ -443,6 +454,9 @@
 
 static int pmac_late_init(void)
 {
+	if (!machine_is(powermac))
+		return -ENODEV;
+
 	initializing = 0;
 	/* this is udbg (which is __init) and we can later use it during
 	 * cpu hotplug (in smp_core99_kick_cpu) */
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 686ed82..cb2d8945 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -317,7 +317,6 @@
 		ncpus = NR_CPUS;
 	for (i = 1; i < ncpus ; ++i) {
 		cpu_set(i, cpu_present_map);
-		cpu_set(i, cpu_possible_map);
 		set_hard_smp_processor_id(i, i);
 	}
 
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 40f0008..a05079b 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -7,6 +7,7 @@
 	select USB_OHCI_BIG_ENDIAN_MMIO
 	select USB_ARCH_HAS_EHCI
 	select USB_EHCI_BIG_ENDIAN_MMIO
+	select MEMORY_HOTPLUG
 	help
 	  This option enables support for the Sony PS3 game console
 	  and other platforms using the PS3 hypervisor.
@@ -73,18 +74,12 @@
 
 config PS3_VUART
 	depends on PPC_PS3
-	bool "PS3 Virtual UART support" if PS3_ADVANCED
-	default y
-	help
-	  Include support for the PS3 Virtual UART.
-
-	  This support is required for several system services
-	  including the System Manager and AV Settings.  In
-	  general, all users will say Y.
+	tristate
 
 config PS3_PS3AV
+	depends on PPC_PS3
 	tristate "PS3 AV settings driver" if PS3_ADVANCED
-	depends on PS3_VUART
+	select PS3_VUART
 	default y
 	help
 	  Include support for the PS3 AV Settings driver.
@@ -93,13 +88,18 @@
 	  general, all users will say Y or M.
 
 config PS3_SYS_MANAGER
-	bool "PS3 System Manager driver" if PS3_ADVANCED
-	depends on PS3_VUART
-	default y
+	depends on PPC_PS3
+	tristate "PS3 System Manager driver" if PS3_ADVANCED
+	select PS3_VUART
+	default m
 	help
 	  Include support for the PS3 System Manager.
 
 	  This support is required for system control.  In
-	  general, all users will say Y.
+	  general, all users will say Y or M.
+
+config PS3_STORAGE
+	depends on PPC_PS3
+	tristate
 
 endmenu
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile
index a0048fc..ac1bdf8 100644
--- a/arch/powerpc/platforms/ps3/Makefile
+++ b/arch/powerpc/platforms/ps3/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
+obj-y += device-init.o
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
new file mode 100644
index 0000000..825ebb2
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -0,0 +1,785 @@
+/*
+ *  PS3 device registration routines.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+
+#include <asm/firmware.h>
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+#include "platform.h"
+
+/**
+ * ps3_setup_gelic_device - Setup and register a gelic device instance.
+ *
+ * Allocates memory for a struct ps3_system_bus_device instance, initialises the
+ * structure members, and registers the device instance with the system bus.
+ */
+
+static int __init ps3_setup_gelic_device(
+	const struct ps3_repository_device *repo)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+	BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p) {
+		result = -ENOMEM;
+		goto fail_malloc;
+	}
+
+	p->dev.match_id = PS3_MATCH_ID_GELIC;
+	p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+	p->dev.bus_id = repo->bus_id;
+	p->dev.dev_id = repo->dev_id;
+	p->dev.d_region = &p->d_region;
+
+	result = ps3_repository_find_interrupt(repo,
+		PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+			__func__, __LINE__);
+		goto fail_find_interrupt;
+	}
+
+	BUG_ON(p->dev.interrupt_id != 0);
+
+	result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+		PS3_DMA_OTHER, NULL, 0);
+
+	if (result) {
+		pr_debug("%s:%d ps3_dma_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_dma_init;
+	}
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result) {
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+		goto fail_device_register;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+
+fail_device_register:
+fail_dma_init:
+fail_find_interrupt:
+	kfree(p);
+fail_malloc:
+	pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init_refok ps3_setup_uhc_device(
+	const struct ps3_repository_device *repo, enum ps3_match_id match_id,
+	enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+		struct ps3_mmio_region m_region;
+	} *p;
+	u64 bus_addr;
+	u64 len;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+	BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p) {
+		result = -ENOMEM;
+		goto fail_malloc;
+	}
+
+	p->dev.match_id = match_id;
+	p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+	p->dev.bus_id = repo->bus_id;
+	p->dev.dev_id = repo->dev_id;
+	p->dev.d_region = &p->d_region;
+	p->dev.m_region = &p->m_region;
+
+	result = ps3_repository_find_interrupt(repo,
+		interrupt_type, &p->dev.interrupt_id);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+			__func__, __LINE__);
+		goto fail_find_interrupt;
+	}
+
+	result = ps3_repository_find_reg(repo, reg_type,
+		&bus_addr, &len);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_reg failed\n",
+			__func__, __LINE__);
+		goto fail_find_reg;
+	}
+
+	result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+		PS3_DMA_INTERNAL, NULL, 0);
+
+	if (result) {
+		pr_debug("%s:%d ps3_dma_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_dma_init;
+	}
+
+	result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,
+		PS3_MMIO_4K);
+
+	if (result) {
+		pr_debug("%s:%d ps3_mmio_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_mmio_init;
+	}
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result) {
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+		goto fail_device_register;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+
+fail_device_register:
+fail_mmio_init:
+fail_dma_init:
+fail_find_reg:
+fail_find_interrupt:
+	kfree(p);
+fail_malloc:
+	pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_setup_ehci_device(
+	const struct ps3_repository_device *repo)
+{
+	return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,
+		PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);
+}
+
+static int __init ps3_setup_ohci_device(
+	const struct ps3_repository_device *repo)
+{
+	return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,
+		PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);
+}
+
+static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
+	unsigned int port_number)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+	} *p;
+
+	pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,
+		match_id, port_number);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = match_id;
+	p->dev.dev_type = PS3_DEVICE_TYPE_VUART;
+	p->dev.port_number = port_number;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int ps3stor_wait_for_completion(u64 dev_id, u64 tag,
+				       unsigned int timeout)
+{
+	int result = -1;
+	unsigned int retries = 0;
+	u64 status;
+
+	for (retries = 0; retries < timeout; retries++) {
+		result = lv1_storage_check_async_status(dev_id, tag, &status);
+		if (!result)
+			break;
+
+		msleep(1);
+	}
+
+	if (result)
+		pr_debug("%s:%u: check_async_status: %s, status %lx\n",
+			 __func__, __LINE__, ps3_result(result), status);
+
+	return result;
+}
+
+/**
+ * ps3_storage_wait_for_device - Wait for a storage device to become ready.
+ * @repo: The repository device to wait for.
+ *
+ * Uses the hypervisor's storage device notification mechanism to wait until
+ * a storage device is ready.  The device notification mechanism uses a
+ * psuedo device (id = -1) to asynchronously notify the guest when storage
+ * devices become ready.  The notification device has a block size of 512
+ * bytes.
+ */
+
+static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
+{
+	int result;
+	const u64 notification_dev_id = (u64)-1LL;
+	const unsigned int timeout = HZ;
+	u64 lpar;
+	u64 tag;
+	struct {
+		u64 operation_code;	/* must be zero */
+		u64 event_mask;		/* 1 = device ready */
+	} *notify_cmd;
+	struct {
+		u64 event_type;		/* notify_device_ready */
+		u64 bus_id;
+		u64 dev_id;
+		u64 dev_type;
+		u64 dev_port;
+	} *notify_event;
+	enum {
+		notify_device_ready = 1
+	};
+
+	pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__,
+		 __LINE__, repo->bus_id, repo->dev_id, repo->dev_type);
+
+	notify_cmd = kzalloc(512, GFP_KERNEL);
+	notify_event = (void *)notify_cmd;
+	if (!notify_cmd)
+		return -ENOMEM;
+
+	lpar = ps3_mm_phys_to_lpar(__pa(notify_cmd));
+
+	result = lv1_open_device(repo->bus_id, notification_dev_id, 0);
+	if (result) {
+		printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__,
+		       __LINE__, ps3_result(result));
+		result = -ENODEV;
+		goto fail_free;
+	}
+
+	/* Setup and write the request for device notification. */
+
+	notify_cmd->operation_code = 0;	/* must be zero */
+	notify_cmd->event_mask = 0x01;	/* device ready */
+
+	result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar,
+				   &tag);
+	if (result) {
+		printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__,
+		       ps3_result(result));
+		result = -ENODEV;
+		goto fail_close;
+	}
+
+	/* Wait for the write completion */
+
+	result = ps3stor_wait_for_completion(notification_dev_id, tag,
+					     timeout);
+	if (result) {
+		printk(KERN_ERR "%s:%u: write not completed %s\n", __func__,
+		       __LINE__, ps3_result(result));
+		result = -ENODEV;
+		goto fail_close;
+	}
+
+	/* Loop here processing the requested notification events. */
+
+	result = -ENODEV;
+	while (1) {
+		memset(notify_event, 0, sizeof(*notify_event));
+
+		result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0,
+					  lpar, &tag);
+		if (result) {
+			printk(KERN_ERR "%s:%u: write failed %s\n", __func__,
+			       __LINE__, ps3_result(result));
+			break;
+		}
+
+		result = ps3stor_wait_for_completion(notification_dev_id, tag,
+						     timeout);
+		if (result) {
+			printk(KERN_ERR "%s:%u: read not completed %s\n",
+			       __func__, __LINE__, ps3_result(result));
+			break;
+		}
+
+		if (notify_event->event_type != notify_device_ready ||
+		    notify_event->bus_id != repo->bus_id) {
+			pr_debug("%s:%u: bad notify_event: event %lu, "
+				 "dev_id %lu, dev_type %lu\n",
+				 __func__, __LINE__, notify_event->event_type,
+				 notify_event->dev_id, notify_event->dev_type);
+			break;
+		}
+
+		if (notify_event->dev_id == repo->dev_id &&
+		    notify_event->dev_type == repo->dev_type) {
+			pr_debug("%s:%u: device ready: dev_id %u\n", __func__,
+				 __LINE__, repo->dev_id);
+			result = 0;
+			break;
+		}
+
+		if (notify_event->dev_id == repo->dev_id &&
+		    notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) {
+			pr_debug("%s:%u: no access: dev_id %u\n", __func__,
+				 __LINE__, repo->dev_id);
+			break;
+		}
+	}
+
+fail_close:
+	lv1_close_device(repo->bus_id, notification_dev_id);
+fail_free:
+	kfree(notify_cmd);
+	pr_debug(" <- %s:%u\n", __func__, __LINE__);
+	return result;
+}
+
+static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
+				 enum ps3_match_id match_id)
+{
+	int result;
+	struct ps3_storage_device *p;
+	u64 port, blk_size, num_blocks;
+	unsigned int num_regions, i;
+
+	pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id);
+
+	result = ps3_repository_read_stor_dev_info(repo->bus_index,
+						   repo->dev_index, &port,
+						   &blk_size, &num_blocks,
+						   &num_regions);
+	if (result) {
+		printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n",
+		       __func__, __LINE__, result);
+		return -ENODEV;
+	}
+
+	pr_debug("%s:%u: index %u:%u: port %lu blk_size %lu num_blocks %lu "
+		 "num_regions %u\n", __func__, __LINE__, repo->bus_index,
+		 repo->dev_index, port, blk_size, num_blocks, num_regions);
+
+	p = kzalloc(sizeof(struct ps3_storage_device) +
+		    num_regions * sizeof(struct ps3_storage_region),
+		    GFP_KERNEL);
+	if (!p) {
+		result = -ENOMEM;
+		goto fail_malloc;
+	}
+
+	p->sbd.match_id = match_id;
+	p->sbd.dev_type = PS3_DEVICE_TYPE_SB;
+	p->sbd.bus_id = repo->bus_id;
+	p->sbd.dev_id = repo->dev_id;
+	p->sbd.d_region = &p->dma_region;
+	p->blk_size = blk_size;
+	p->num_regions = num_regions;
+
+	result = ps3_repository_find_interrupt(repo,
+					       PS3_INTERRUPT_TYPE_EVENT_PORT,
+					       &p->sbd.interrupt_id);
+	if (result) {
+		printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__,
+		       __LINE__, result);
+		result = -ENODEV;
+		goto fail_find_interrupt;
+	}
+
+	/* FIXME: Arrange to only do this on a 'cold' boot */
+
+	result = ps3_storage_wait_for_device(repo);
+	if (result) {
+		printk(KERN_ERR "%s:%u: storage_notification failed %d\n",
+		       __func__, __LINE__, result);
+		result = -ENODEV;
+		goto fail_probe_notification;
+	}
+
+	for (i = 0; i < num_regions; i++) {
+		unsigned int id;
+		u64 start, size;
+
+		result = ps3_repository_read_stor_dev_region(repo->bus_index,
+							     repo->dev_index,
+							     i, &id, &start,
+							     &size);
+		if (result) {
+			printk(KERN_ERR
+			       "%s:%u: read_stor_dev_region failed %d\n",
+			       __func__, __LINE__, result);
+			result = -ENODEV;
+			goto fail_read_region;
+		}
+		pr_debug("%s:%u: region %u: id %u start %lu size %lu\n",
+			 __func__, __LINE__, i, id, start, size);
+
+		p->regions[i].id = id;
+		p->regions[i].start = start;
+		p->regions[i].size = size;
+	}
+
+	result = ps3_system_bus_device_register(&p->sbd);
+	if (result) {
+		pr_debug("%s:%u ps3_system_bus_device_register failed\n",
+			 __func__, __LINE__);
+		goto fail_device_register;
+	}
+
+	pr_debug(" <- %s:%u\n", __func__, __LINE__);
+	return 0;
+
+fail_device_register:
+fail_read_region:
+fail_probe_notification:
+fail_find_interrupt:
+	kfree(p);
+fail_malloc:
+	pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_vuart_devices(void)
+{
+	int result;
+	unsigned int port_number;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	result = ps3_repository_read_vuart_av_port(&port_number);
+	if (result)
+		port_number = 0; /* av default */
+
+	result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);
+	WARN_ON(result);
+
+	result = ps3_repository_read_vuart_sysmgr_port(&port_number);
+	if (result)
+		port_number = 2; /* sysmgr default */
+
+	result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER,
+		port_number);
+	WARN_ON(result);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_sound_devices(void)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+		struct ps3_mmio_region m_region;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = PS3_MATCH_ID_SOUND;
+	p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+	p->dev.d_region = &p->d_region;
+	p->dev.m_region = &p->m_region;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_graphics_devices(void)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
+	p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+/**
+ * ps3_register_repository_device - Register a device from the repositiory info.
+ *
+ */
+
+static int ps3_register_repository_device(
+	const struct ps3_repository_device *repo)
+{
+	int result;
+
+	switch (repo->dev_type) {
+	case PS3_DEV_TYPE_SB_GELIC:
+		result = ps3_setup_gelic_device(repo);
+		if (result) {
+			pr_debug("%s:%d ps3_setup_gelic_device failed\n",
+				__func__, __LINE__);
+		}
+		break;
+	case PS3_DEV_TYPE_SB_USB:
+
+		/* Each USB device has both an EHCI and an OHCI HC */
+
+		result = ps3_setup_ehci_device(repo);
+
+		if (result) {
+			pr_debug("%s:%d ps3_setup_ehci_device failed\n",
+				__func__, __LINE__);
+		}
+
+		result = ps3_setup_ohci_device(repo);
+
+		if (result) {
+			pr_debug("%s:%d ps3_setup_ohci_device failed\n",
+				__func__, __LINE__);
+		}
+		break;
+	case PS3_DEV_TYPE_STOR_DISK:
+		result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);
+
+		/* Some devices are not accessable from the Other OS lpar. */
+		if (result == -ENODEV) {
+			result = 0;
+			pr_debug("%s:%u: not accessable\n", __func__,
+				 __LINE__);
+		}
+
+		if (result)
+			pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+				 __func__, __LINE__);
+		break;
+
+	case PS3_DEV_TYPE_STOR_ROM:
+		result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM);
+		if (result)
+			pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+				 __func__, __LINE__);
+		break;
+
+	case PS3_DEV_TYPE_STOR_FLASH:
+		result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH);
+		if (result)
+			pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+				 __func__, __LINE__);
+		break;
+
+	default:
+		result = 0;
+		pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
+			repo->dev_type);
+	}
+
+	return result;
+}
+
+/**
+ * ps3_probe_thread - Background repository probing at system startup.
+ *
+ * This implementation only supports background probing on a single bus.
+ */
+
+static int ps3_probe_thread(void *data)
+{
+	struct ps3_repository_device *repo = data;
+	int result;
+	unsigned int ms = 250;
+
+	pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
+
+	do {
+		try_to_freeze();
+
+		pr_debug("%s:%u: probing...\n", __func__, __LINE__);
+
+		do {
+			result = ps3_repository_find_device(repo);
+
+			if (result == -ENODEV)
+				pr_debug("%s:%u: nothing new\n", __func__,
+					__LINE__);
+			else if (result)
+				pr_debug("%s:%u: find device error.\n",
+					__func__, __LINE__);
+			else {
+				pr_debug("%s:%u: found device\n", __func__,
+					__LINE__);
+				ps3_register_repository_device(repo);
+				ps3_repository_bump_device(repo);
+				ms = 250;
+			}
+		} while (!result);
+
+		pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms);
+
+		if ( ms > 60000)
+			break;
+
+		msleep_interruptible(ms);
+
+		/* An exponential backoff. */
+		ms <<= 1;
+
+	} while (!kthread_should_stop());
+
+	pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
+
+	return 0;
+}
+
+/**
+ * ps3_start_probe_thread - Starts the background probe thread.
+ *
+ */
+
+static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
+{
+	int result;
+	struct task_struct *task;
+	static struct ps3_repository_device repo; /* must be static */
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	memset(&repo, 0, sizeof(repo));
+
+	repo.bus_type = bus_type;
+
+	result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
+
+	if (result) {
+		printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result);
+		return -ENODEV;
+	}
+
+	result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
+
+	if (result) {
+		printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__,
+			result);
+		return -ENODEV;
+	}
+
+	task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type);
+
+	if (IS_ERR(task)) {
+		result = PTR_ERR(task);
+		printk(KERN_ERR "%s: kthread_run failed %d\n", __func__,
+		       result);
+		return result;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+/**
+ * ps3_register_devices - Probe the system and register devices found.
+ *
+ * A device_initcall() routine.
+ */
+
+static int __init ps3_register_devices(void)
+{
+	int result;
+
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	/* ps3_repository_dump_bus_info(); */
+
+	result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
+
+	ps3_register_vuart_devices();
+
+	ps3_register_graphics_devices();
+
+	ps3_repository_find_devices(PS3_BUS_TYPE_SB,
+		ps3_register_repository_device);
+
+	ps3_register_sound_devices();
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+device_initcall(ps3_register_devices);
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index a1409e4..5d2e176 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -29,12 +29,12 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
-static hpte_t *htab;
+static struct hash_pte *htab;
 static unsigned long htab_addr;
 static unsigned char *bolttab;
 static unsigned char *inusetab;
@@ -44,8 +44,8 @@
 #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
 	_debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
 static void _debug_dump_hpte(unsigned long pa, unsigned long va,
-	unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize,
-	unsigned long slot, const char* func, int line)
+	unsigned long group, unsigned long bitmap, struct hash_pte lhpte,
+	int psize, unsigned long slot, const char* func, int line)
 {
 	DBG("%s:%d: pa     = %lxh\n", func, line, pa);
 	DBG("%s:%d: lpar   = %lxh\n", func, line,
@@ -63,7 +63,7 @@
 	unsigned long pa, unsigned long rflags, unsigned long vflags, int psize)
 {
 	unsigned long slot;
-	hpte_t lhpte;
+	struct hash_pte lhpte;
 	int secondary = 0;
 	unsigned long result;
 	unsigned long bitmap;
@@ -234,10 +234,17 @@
 
 static void ps3_hpte_clear(void)
 {
-	/* Make sure to clean up the frame buffer device first */
-	ps3fb_cleanup();
+	int result;
 
-	lv1_unmap_htab(htab_addr);
+	DBG(" -> %s:%d\n", __func__, __LINE__);
+
+	result = lv1_unmap_htab(htab_addr);
+	BUG_ON(result);
+
+	ps3_mm_shutdown();
+	ps3_mm_vas_destroy();
+
+	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
 void __init ps3_hpte_init(unsigned long htab_size)
@@ -255,7 +262,7 @@
 
 	ppc64_pft_size = __ilog2(htab_size);
 
-	bitmap_size = htab_size / sizeof(hpte_t) / 8;
+	bitmap_size = htab_size / sizeof(struct hash_pte) / 8;
 
 	bolttab = __va(lmb_alloc(bitmap_size, 1));
 	inusetab = __va(lmb_alloc(bitmap_size, 1));
@@ -273,8 +280,8 @@
 
 	result = lv1_map_htab(0, &htab_addr);
 
-	htab = (hpte_t *)__ioremap(htab_addr, htab_size,
-				   pgprot_val(PAGE_READONLY_X));
+	htab = (__force struct hash_pte *)ioremap_flags(htab_addr, htab_size,
+					    pgprot_val(PAGE_READONLY_X));
 
 	DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
 		htab_addr, (unsigned long)htab);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 9da82c2..67e32ec 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -25,13 +25,14 @@
 #include <asm/machdep.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
+#include <asm/smp.h>
 
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 /**
@@ -77,19 +78,85 @@
 /**
  * struct ps3_private - a per cpu data structure
  * @bmp: ps3_bmp structure
- * @node: HV logical_ppe_id
- * @cpu: HV thread_id
+ * @ppe_id: HV logical_ppe_id
+ * @thread_id: HV thread_id
  */
 
 struct ps3_private {
 	struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
-	u64 node;
-	unsigned int cpu;
+	u64 ppe_id;
+	u64 thread_id;
 };
 
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
 
 /**
+ * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_mask(unsigned int virq)
+{
+	struct ps3_private *pd = get_irq_chip_data(virq);
+	unsigned long flags;
+
+	pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+		pd->thread_id, virq);
+
+	local_irq_save(flags);
+	clear_bit(63 - virq, &pd->bmp.mask);
+	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
+	local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_unmask(unsigned int virq)
+{
+	struct ps3_private *pd = get_irq_chip_data(virq);
+	unsigned long flags;
+
+	pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+		pd->thread_id, virq);
+
+	local_irq_save(flags);
+	set_bit(63 - virq, &pd->bmp.mask);
+	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
+	local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_eoi - HV end-of-interrupt.
+ * @virq: The assigned Linux virq.
+ *
+ * Calls lv1_end_of_interrupt_ext().
+ */
+
+static void ps3_chip_eoi(unsigned int virq)
+{
+	const struct ps3_private *pd = get_irq_chip_data(virq);
+	lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq);
+}
+
+/**
+ * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip.
+ */
+
+static struct irq_chip ps3_irq_chip = {
+	.typename = "ps3",
+	.mask = ps3_chip_mask,
+	.unmask = ps3_chip_unmask,
+	.eoi = ps3_chip_eoi,
+};
+
+/**
  * ps3_virq_setup - virq related setup.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
@@ -133,6 +200,8 @@
 		goto fail_set;
 	}
 
+	ps3_chip_mask(*virq);
+
 	return result;
 
 fail_set:
@@ -152,8 +221,8 @@
 {
 	const struct ps3_private *pd = get_irq_chip_data(virq);
 
-	pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
-		pd->node, pd->cpu, virq);
+	pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+		__LINE__, pd->ppe_id, pd->thread_id, virq);
 
 	set_irq_chip_data(virq, NULL);
 	irq_dispose_mapping(virq);
@@ -189,7 +258,8 @@
 
 	/* Binds outlet to cpu + virq. */
 
-	result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
+	result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq,
+		outlet, 0);
 
 	if (result) {
 		pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
@@ -221,10 +291,12 @@
 	int result;
 	const struct ps3_private *pd = get_irq_chip_data(virq);
 
-	pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
-		pd->node, pd->cpu, virq);
+	pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+		__LINE__, pd->ppe_id, pd->thread_id, virq);
 
-	result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
+	ps3_chip_mask(virq);
+
+	result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
 
 	if (result)
 		pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
@@ -281,7 +353,9 @@
 {
 	int result;
 
-	pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq);
+	pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
+
+	ps3_chip_mask(virq);
 
 	result = lv1_destruct_event_receive_port(virq_to_hw(virq));
 
@@ -289,17 +363,14 @@
 		pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	/* lv1_destruct_event_receive_port() destroys the IRQ plug,
-	 * so don't call ps3_irq_plug_destroy() here.
+	/*
+	 * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
+	 * calls from interrupt context (smp_call_function) when kexecing.
 	 */
 
-	result = ps3_virq_destroy(virq);
-	BUG_ON(result);
-
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
-EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
 
 int ps3_send_event_locally(unsigned int virq)
 {
@@ -310,17 +381,15 @@
  * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
- * @did: The HV device identifier read from the system repository.
- * @interrupt_id: The device interrupt id read from the system repository.
+ * @dev: The system bus device instance.
  * @virq: The assigned Linux virq.
  *
  * An event irq represents a virtual device interrupt.  The interrupt_id
  * coresponds to the software interrupt number.
  */
 
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
-	const struct ps3_device_id *did, unsigned int interrupt_id,
-	unsigned int *virq)
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+	enum ps3_cpu_binding cpu, unsigned int *virq)
 {
 	/* this should go in system-bus.c */
 
@@ -331,8 +400,8 @@
 	if (result)
 		return result;
 
-	result = lv1_connect_interrupt_event_receive_port(did->bus_id,
-		did->dev_id, virq_to_hw(*virq), interrupt_id);
+	result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
+		dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);
 
 	if (result) {
 		pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
@@ -344,24 +413,24 @@
 	}
 
 	pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
-		interrupt_id, *virq);
+		dev->interrupt_id, *virq);
 
 	return 0;
 }
 EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
 
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
-	unsigned int interrupt_id, unsigned int virq)
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+	unsigned int virq)
 {
 	/* this should go in system-bus.c */
 
 	int result;
 
 	pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
-		interrupt_id, virq);
+		dev->interrupt_id, virq);
 
-	result = lv1_disconnect_interrupt_event_receive_port(did->bus_id,
-		did->dev_id, virq_to_hw(virq), interrupt_id);
+	result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
+		dev->dev_id, virq_to_hw(virq), dev->interrupt_id);
 
 	if (result)
 		pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
@@ -371,6 +440,14 @@
 	result = ps3_event_receive_port_destroy(virq);
 	BUG_ON(result);
 
+	/*
+	 * ps3_event_receive_port_destroy() destroys the IRQ plug,
+	 * so don't call ps3_irq_plug_destroy() here.
+	 */
+
+	result = ps3_virq_destroy(virq);
+	BUG_ON(result);
+
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
@@ -411,16 +488,24 @@
 int ps3_io_irq_destroy(unsigned int virq)
 {
 	int result;
+	unsigned long outlet = virq_to_hw(virq);
 
-	result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+	ps3_chip_mask(virq);
+
+	/*
+	 * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
+	 * so call ps3_irq_plug_destroy() first.
+	 */
+
+	result = ps3_irq_plug_destroy(virq);
+	BUG_ON(result);
+
+	result = lv1_destruct_io_irq_outlet(outlet);
 
 	if (result)
 		pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	result = ps3_irq_plug_destroy(virq);
-	BUG_ON(result);
-
 	return result;
 }
 EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
@@ -460,11 +545,13 @@
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
 
 int ps3_vuart_irq_destroy(unsigned int virq)
 {
 	int result;
 
+	ps3_chip_mask(virq);
 	result = lv1_deconfigure_virtual_uart_irq();
 
 	if (result) {
@@ -478,6 +565,7 @@
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy);
 
 /**
  * ps3_spe_irq_setup - Setup an spe virq.
@@ -513,9 +601,14 @@
 
 int ps3_spe_irq_destroy(unsigned int virq)
 {
-	int result = ps3_irq_plug_destroy(virq);
+	int result;
+
+	ps3_chip_mask(virq);
+
+	result = ps3_irq_plug_destroy(virq);
 	BUG_ON(result);
-	return 0;
+
+	return result;
 }
 
 
@@ -532,7 +625,7 @@
 		*p & 0xffff);
 }
 
-static void __attribute__ ((unused)) _dump_256_bmp(const char *header,
+static void __maybe_unused _dump_256_bmp(const char *header,
 	const u64 *p, unsigned cpu, const char* func, int line)
 {
 	pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
@@ -545,86 +638,25 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&pd->bmp.lock, flags);
-	_dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line);
-	_dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
+	_dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line);
+	_dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
 	spin_unlock_irqrestore(&pd->bmp.lock, flags);
 }
 
 #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd,
+static void __maybe_unused _dump_mask(struct ps3_private *pd,
 	const char* func, int line)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&pd->bmp.lock, flags);
-	_dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
+	_dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
 	spin_unlock_irqrestore(&pd->bmp.lock, flags);
 }
 #else
 static void dump_bmp(struct ps3_private* pd) {};
 #endif /* defined(DEBUG) */
 
-static void ps3_chip_mask(unsigned int virq)
-{
-	struct ps3_private *pd = get_irq_chip_data(virq);
-	u64 bit = 0x8000000000000000UL >> virq;
-	u64 *p = &pd->bmp.mask;
-	u64 old;
-	unsigned long flags;
-
-	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
-	local_irq_save(flags);
-	asm volatile(
-		     "1:	ldarx %0,0,%3\n"
-		     "andc	%0,%0,%2\n"
-		     "stdcx.	%0,0,%3\n"
-		     "bne-	1b"
-		     : "=&r" (old), "+m" (*p)
-		     : "r" (bit), "r" (p)
-		     : "cc" );
-
-	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
-	local_irq_restore(flags);
-}
-
-static void ps3_chip_unmask(unsigned int virq)
-{
-	struct ps3_private *pd = get_irq_chip_data(virq);
-	u64 bit = 0x8000000000000000UL >> virq;
-	u64 *p = &pd->bmp.mask;
-	u64 old;
-	unsigned long flags;
-
-	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
-	local_irq_save(flags);
-	asm volatile(
-		     "1:	ldarx %0,0,%3\n"
-		     "or	%0,%0,%2\n"
-		     "stdcx.	%0,0,%3\n"
-		     "bne-	1b"
-		     : "=&r" (old), "+m" (*p)
-		     : "r" (bit), "r" (p)
-		     : "cc" );
-
-	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
-	local_irq_restore(flags);
-}
-
-static void ps3_chip_eoi(unsigned int virq)
-{
-	const struct ps3_private *pd = get_irq_chip_data(virq);
-	lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
-}
-
-static struct irq_chip irq_chip = {
-	.typename = "ps3",
-	.mask = ps3_chip_mask,
-	.unmask = ps3_chip_unmask,
-	.eoi = ps3_chip_eoi,
-};
-
 static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
 {
 	set_irq_chip_data(virq, NULL);
@@ -636,7 +668,7 @@
 	pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
 		virq);
 
-	set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
+	set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
 
 	return 0;
 }
@@ -656,7 +688,7 @@
 		cpu, virq, pd->bmp.ipi_debug_brk_mask);
 }
 
-unsigned int ps3_get_irq(void)
+static unsigned int ps3_get_irq(void)
 {
 	struct ps3_private *pd = &__get_cpu_var(ps3_private);
 	u64 x = (pd->bmp.status & pd->bmp.mask);
@@ -671,8 +703,8 @@
 	plug &= 0x3f;
 
 	if (unlikely(plug) == NO_IRQ) {
-		pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__,
-			pd->cpu);
+		pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__,
+			__LINE__, pd->thread_id);
 		dump_bmp(&per_cpu(ps3_private, 0));
 		dump_bmp(&per_cpu(ps3_private, 1));
 		return NO_IRQ;
@@ -702,16 +734,16 @@
 	for_each_possible_cpu(cpu) {
 		struct ps3_private *pd = &per_cpu(ps3_private, cpu);
 
-		lv1_get_logical_ppe_id(&pd->node);
-		pd->cpu = get_hard_smp_processor_id(cpu);
+		lv1_get_logical_ppe_id(&pd->ppe_id);
+		pd->thread_id = get_hard_smp_processor_id(cpu);
 		spin_lock_init(&pd->bmp.lock);
 
-		pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__,
-			__LINE__, pd->node, pd->cpu,
+		pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n",
+			__func__, __LINE__, pd->ppe_id, pd->thread_id,
 			ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
 
-		result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu,
-			ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
+		result = lv1_configure_irq_state_bitmap(pd->ppe_id,
+			pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
 
 		if (result)
 			pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
@@ -721,3 +753,16 @@
 
 	ppc_md.get_irq = ps3_get_irq;
 }
+
+void ps3_shutdown_IRQ(int cpu)
+{
+	int result;
+	u64 ppe_id;
+	u64 thread_id = get_hard_smp_processor_id(cpu);
+
+	lv1_get_logical_ppe_id(&ppe_id);
+	result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
+
+	DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__,
+		__LINE__, ppe_id, thread_id, cpu, ps3_result(result));
+}
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index f8a3e20..7bb3e16 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -30,9 +30,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 enum {
@@ -115,7 +115,8 @@
 };
 
 #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__)
-static void _debug_dump_map(const struct map* m, const char* func, int line)
+static void __maybe_unused _debug_dump_map(const struct map *m,
+	const char *func, int line)
 {
 	DBG("%s:%d: map.total     = %lxh\n", func, line, m->total);
 	DBG("%s:%d: map.rm.size   = %lxh\n", func, line, m->rm.size);
@@ -212,9 +213,15 @@
 
 void ps3_mm_vas_destroy(void)
 {
+	int result;
+
+	DBG("%s:%d: map.vas_id    = %lu\n", __func__, __LINE__, map.vas_id);
+
 	if (map.vas_id) {
-		lv1_select_virtual_address_space(0);
-		lv1_destruct_virtual_address_space(map.vas_id);
+		result = lv1_select_virtual_address_space(0);
+		BUG_ON(result);
+		result = lv1_destruct_virtual_address_space(map.vas_id);
+		BUG_ON(result);
 		map.vas_id = 0;
 	}
 }
@@ -232,7 +239,7 @@
  * @size is rounded down to a multiple of the vas large page size.
  */
 
-int ps3_mm_region_create(struct mem_region *r, unsigned long size)
+static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
 {
 	int result;
 	unsigned long muid;
@@ -273,10 +280,14 @@
  * @r: pointer to struct mem_region
  */
 
-void ps3_mm_region_destroy(struct mem_region *r)
+static void ps3_mm_region_destroy(struct mem_region *r)
 {
+	int result;
+
+	DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base);
 	if (r->base) {
-		lv1_release_memory(r->base);
+		result = lv1_release_memory(r->base);
+		BUG_ON(result);
 		r->size = r->base = r->offset = 0;
 		map.total = map.rm.size;
 	}
@@ -329,31 +340,34 @@
 /*============================================================================*/
 
 /**
- * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
+ * dma_sb_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
  * @r: pointer to dma region structure
  * @lpar_addr: HV lpar address
  */
 
-static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r,
+static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r,
 	unsigned long lpar_addr)
 {
-	BUG_ON(lpar_addr >= map.r1.base + map.r1.size);
-	return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr
-		: lpar_addr - map.r1.offset);
+	if (lpar_addr >= map.rm.size)
+		lpar_addr -= map.r1.offset;
+	BUG_ON(lpar_addr < r->offset);
+	BUG_ON(lpar_addr >= r->offset + r->len);
+	return r->bus_addr + lpar_addr - r->offset;
 }
 
 #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__)
-static void _dma_dump_region(const struct ps3_dma_region *r, const char* func,
-	int line)
+static void  __maybe_unused _dma_dump_region(const struct ps3_dma_region *r,
+	const char *func, int line)
 {
-	DBG("%s:%d: dev        %u:%u\n", func, line, r->did.bus_id,
-		r->did.dev_id);
+	DBG("%s:%d: dev        %u:%u\n", func, line, r->dev->bus_id,
+		r->dev->dev_id);
 	DBG("%s:%d: page_size  %u\n", func, line, r->page_size);
 	DBG("%s:%d: bus_addr   %lxh\n", func, line, r->bus_addr);
 	DBG("%s:%d: len        %lxh\n", func, line, r->len);
+	DBG("%s:%d: offset     %lxh\n", func, line, r->offset);
 }
 
-/**
+  /**
  * dma_chunk - A chunk of dma pages mapped by the io controller.
  * @region - The dma region that owns this chunk.
  * @lpar_addr: Starting lpar address of the area to map.
@@ -381,10 +395,11 @@
 	int line)
 {
 	DBG("%s:%d: r.dev        %u:%u\n", func, line,
-		c->region->did.bus_id, c->region->did.dev_id);
+		c->region->dev->bus_id, c->region->dev->dev_id);
 	DBG("%s:%d: r.bus_addr   %lxh\n", func, line, c->region->bus_addr);
 	DBG("%s:%d: r.page_size  %u\n", func, line, c->region->page_size);
 	DBG("%s:%d: r.len        %lxh\n", func, line, c->region->len);
+	DBG("%s:%d: r.offset     %lxh\n", func, line, c->region->offset);
 	DBG("%s:%d: c.lpar_addr  %lxh\n", func, line, c->lpar_addr);
 	DBG("%s:%d: c.bus_addr   %lxh\n", func, line, c->bus_addr);
 	DBG("%s:%d: c.len        %lxh\n", func, line, c->len);
@@ -395,39 +410,68 @@
 {
 	struct dma_chunk *c;
 	unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size);
-	unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
+	unsigned long aligned_len = _ALIGN_UP(len+bus_addr-aligned_bus,
+					      1 << r->page_size);
 
 	list_for_each_entry(c, &r->chunk_list.head, link) {
 		/* intersection */
-		if (aligned_bus >= c->bus_addr
-			&& aligned_bus < c->bus_addr + c->len
-			&& aligned_bus + aligned_len <= c->bus_addr + c->len) {
+		if (aligned_bus >= c->bus_addr &&
+		    aligned_bus + aligned_len <= c->bus_addr + c->len)
 			return c;
-		}
+
 		/* below */
-		if (aligned_bus + aligned_len <= c->bus_addr) {
+		if (aligned_bus + aligned_len <= c->bus_addr)
 			continue;
-		}
+
 		/* above */
-		if (aligned_bus >= c->bus_addr + c->len) {
+		if (aligned_bus >= c->bus_addr + c->len)
 			continue;
-		}
 
 		/* we don't handle the multi-chunk case for now */
-
 		dma_dump_chunk(c);
 		BUG();
 	}
 	return NULL;
 }
 
-static int dma_free_chunk(struct dma_chunk *c)
+static struct dma_chunk *dma_find_chunk_lpar(struct ps3_dma_region *r,
+	unsigned long lpar_addr, unsigned long len)
+{
+	struct dma_chunk *c;
+	unsigned long aligned_lpar = _ALIGN_DOWN(lpar_addr, 1 << r->page_size);
+	unsigned long aligned_len = _ALIGN_UP(len + lpar_addr - aligned_lpar,
+					      1 << r->page_size);
+
+	list_for_each_entry(c, &r->chunk_list.head, link) {
+		/* intersection */
+		if (c->lpar_addr <= aligned_lpar &&
+		    aligned_lpar < c->lpar_addr + c->len) {
+			if (aligned_lpar + aligned_len <= c->lpar_addr + c->len)
+				return c;
+			else {
+				dma_dump_chunk(c);
+				BUG();
+			}
+		}
+		/* below */
+		if (aligned_lpar + aligned_len <= c->lpar_addr) {
+			continue;
+		}
+		/* above */
+		if (c->lpar_addr + c->len <= aligned_lpar) {
+			continue;
+		}
+	}
+	return NULL;
+}
+
+static int dma_sb_free_chunk(struct dma_chunk *c)
 {
 	int result = 0;
 
 	if (c->bus_addr) {
-		result = lv1_unmap_device_dma_region(c->region->did.bus_id,
-			c->region->did.dev_id, c->bus_addr, c->len);
+		result = lv1_unmap_device_dma_region(c->region->dev->bus_id,
+			c->region->dev->dev_id, c->bus_addr, c->len);
 		BUG_ON(result);
 	}
 
@@ -435,8 +479,39 @@
 	return result;
 }
 
+static int dma_ioc0_free_chunk(struct dma_chunk *c)
+{
+	int result = 0;
+	int iopage;
+	unsigned long offset;
+	struct ps3_dma_region *r = c->region;
+
+	DBG("%s:start\n", __func__);
+	for (iopage = 0; iopage < (c->len >> r->page_size); iopage++) {
+		offset = (1 << r->page_size) * iopage;
+		/* put INVALID entry */
+		result = lv1_put_iopte(0,
+				       c->bus_addr + offset,
+				       c->lpar_addr + offset,
+				       r->ioid,
+				       0);
+		DBG("%s: bus=%#lx, lpar=%#lx, ioid=%d\n", __func__,
+		    c->bus_addr + offset,
+		    c->lpar_addr + offset,
+		    r->ioid);
+
+		if (result) {
+			DBG("%s:%d: lv1_put_iopte failed: %s\n", __func__,
+			    __LINE__, ps3_result(result));
+		}
+	}
+	kfree(c);
+	DBG("%s:end\n", __func__);
+	return result;
+}
+
 /**
- * dma_map_pages - Maps dma pages into the io controller bus address space.
+ * dma_sb_map_pages - Maps dma pages into the io controller bus address space.
  * @r: Pointer to a struct ps3_dma_region.
  * @phys_addr: Starting physical address of the area to map.
  * @len: Length in bytes of the area to map.
@@ -446,8 +521,8 @@
  * make the HV call to add the pages into the io controller address space.
  */
 
-static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
-	unsigned long len, struct dma_chunk **c_out)
+static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
+	    unsigned long len, struct dma_chunk **c_out, u64 iopte_flag)
 {
 	int result;
 	struct dma_chunk *c;
@@ -461,13 +536,13 @@
 
 	c->region = r;
 	c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
-	c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr);
+	c->bus_addr = dma_sb_lpar_to_bus(r, c->lpar_addr);
 	c->len = len;
 
-	result = lv1_map_device_dma_region(c->region->did.bus_id,
-		c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len,
-		0xf800000000000000UL);
-
+	BUG_ON(iopte_flag != 0xf800000000000000UL);
+	result = lv1_map_device_dma_region(c->region->dev->bus_id,
+					   c->region->dev->dev_id, c->lpar_addr,
+					   c->bus_addr, c->len, iopte_flag);
 	if (result) {
 		DBG("%s:%d: lv1_map_device_dma_region failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
@@ -487,26 +562,120 @@
 	return result;
 }
 
+static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
+			      unsigned long len, struct dma_chunk **c_out,
+			      u64 iopte_flag)
+{
+	int result;
+	struct dma_chunk *c, *last;
+	int iopage, pages;
+	unsigned long offset;
+
+	DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__,
+	    phys_addr, ps3_mm_phys_to_lpar(phys_addr), len);
+	c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC);
+
+	if (!c) {
+		result = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	c->region = r;
+	c->len = len;
+	c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
+	/* allocate IO address */
+	if (list_empty(&r->chunk_list.head)) {
+		/* first one */
+		c->bus_addr = r->bus_addr;
+	} else {
+		/* derive from last bus addr*/
+		last  = list_entry(r->chunk_list.head.next,
+				   struct dma_chunk, link);
+		c->bus_addr = last->bus_addr + last->len;
+		DBG("%s: last bus=%#lx, len=%#lx\n", __func__,
+		    last->bus_addr, last->len);
+	}
+
+	/* FIXME: check whether length exceeds region size */
+
+	/* build ioptes for the area */
+	pages = len >> r->page_size;
+	DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__,
+	    r->page_size, r->len, pages, iopte_flag);
+	for (iopage = 0; iopage < pages; iopage++) {
+		offset = (1 << r->page_size) * iopage;
+		result = lv1_put_iopte(0,
+				       c->bus_addr + offset,
+				       c->lpar_addr + offset,
+				       r->ioid,
+				       iopte_flag);
+		if (result) {
+			printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region "
+				"failed: %s\n", __func__, __LINE__,
+				ps3_result(result));
+			goto fail_map;
+		}
+		DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__,
+		    iopage, c->bus_addr + offset, c->lpar_addr + offset,
+		    r->ioid);
+	}
+
+	/* be sure that last allocated one is inserted at head */
+	list_add(&c->link, &r->chunk_list.head);
+
+	*c_out = c;
+	DBG("%s: end\n", __func__);
+	return 0;
+
+fail_map:
+	for (iopage--; 0 <= iopage; iopage--) {
+		lv1_put_iopte(0,
+			      c->bus_addr + offset,
+			      c->lpar_addr + offset,
+			      r->ioid,
+			      0);
+	}
+	kfree(c);
+fail_alloc:
+	*c_out = NULL;
+	return result;
+}
+
 /**
- * dma_region_create - Create a device dma region.
+ * dma_sb_region_create - Create a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This is the lowest level dma region create routine, and is the one that
  * will make the HV call to create the region.
  */
 
-static int dma_region_create(struct ps3_dma_region* r)
+static int dma_sb_region_create(struct ps3_dma_region *r)
 {
 	int result;
 
-	r->len = _ALIGN_UP(map.total, 1 << r->page_size);
+	pr_info(" -> %s:%d:\n", __func__, __LINE__);
+
+	BUG_ON(!r);
+
+	if (!r->dev->bus_id) {
+		pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+			r->dev->bus_id, r->dev->dev_id);
+		return 0;
+	}
+
+	DBG("%s:%u: len = 0x%lx, page_size = %u, offset = 0x%lx\n", __func__,
+	    __LINE__, r->len, r->page_size, r->offset);
+
+	BUG_ON(!r->len);
+	BUG_ON(!r->page_size);
+	BUG_ON(!r->region_ops);
+
 	INIT_LIST_HEAD(&r->chunk_list.head);
 	spin_lock_init(&r->chunk_list.lock);
 
-	result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id,
-		r->len, r->page_size, r->region_type, &r->bus_addr);
-
-	dma_dump_region(r);
+	result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id,
+		roundup_pow_of_two(r->len), r->page_size, r->region_type,
+		&r->bus_addr);
 
 	if (result) {
 		DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n",
@@ -517,6 +686,27 @@
 	return result;
 }
 
+static int dma_ioc0_region_create(struct ps3_dma_region *r)
+{
+	int result;
+
+	INIT_LIST_HEAD(&r->chunk_list.head);
+	spin_lock_init(&r->chunk_list.lock);
+
+	result = lv1_allocate_io_segment(0,
+					 r->len,
+					 r->page_size,
+					 &r->bus_addr);
+	if (result) {
+		DBG("%s:%d: lv1_allocate_io_segment failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		r->len = r->bus_addr = 0;
+	}
+	DBG("%s: len=%#lx, pg=%d, bus=%#lx\n", __func__,
+	    r->len, r->page_size, r->bus_addr);
+	return result;
+}
+
 /**
  * dma_region_free - Free a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
@@ -525,31 +715,62 @@
  * will make the HV call to free the region.
  */
 
-static int dma_region_free(struct ps3_dma_region* r)
+static int dma_sb_region_free(struct ps3_dma_region *r)
 {
 	int result;
 	struct dma_chunk *c;
 	struct dma_chunk *tmp;
 
-	list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) {
-		list_del(&c->link);
-		dma_free_chunk(c);
+	BUG_ON(!r);
+
+	if (!r->dev->bus_id) {
+		pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+			r->dev->bus_id, r->dev->dev_id);
+		return 0;
 	}
 
-	result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id,
+	list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) {
+		list_del(&c->link);
+		dma_sb_free_chunk(c);
+	}
+
+	result = lv1_free_device_dma_region(r->dev->bus_id, r->dev->dev_id,
 		r->bus_addr);
 
 	if (result)
 		DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	r->len = r->bus_addr = 0;
+	r->bus_addr = 0;
+
+	return result;
+}
+
+static int dma_ioc0_region_free(struct ps3_dma_region *r)
+{
+	int result;
+	struct dma_chunk *c, *n;
+
+	DBG("%s: start\n", __func__);
+	list_for_each_entry_safe(c, n, &r->chunk_list.head, link) {
+		list_del(&c->link);
+		dma_ioc0_free_chunk(c);
+	}
+
+	result = lv1_release_io_segment(0, r->bus_addr);
+
+	if (result)
+		DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+
+	r->bus_addr = 0;
+	DBG("%s: end\n", __func__);
 
 	return result;
 }
 
 /**
- * dma_map_area - Map an area of memory into a device dma region.
+ * dma_sb_map_area - Map an area of memory into a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @virt_addr: Starting virtual address of the area to map.
  * @len: Length in bytes of the area to map.
@@ -559,16 +780,19 @@
  * This is the common dma mapping routine.
  */
 
-static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
-	unsigned long len, unsigned long *bus_addr)
+static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
+	   unsigned long len, unsigned long *bus_addr,
+	   u64 iopte_flag)
 {
 	int result;
 	unsigned long flags;
 	struct dma_chunk *c;
 	unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
 		: virt_addr;
-
-	*bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
+	unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
+	unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
+					      1 << r->page_size);
+	*bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
 
 	if (!USE_DYNAMIC_DMA) {
 		unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
@@ -588,17 +812,18 @@
 	c = dma_find_chunk(r, *bus_addr, len);
 
 	if (c) {
+		DBG("%s:%d: reusing mapped chunk", __func__, __LINE__);
+		dma_dump_chunk(c);
 		c->usage_count++;
 		spin_unlock_irqrestore(&r->chunk_list.lock, flags);
 		return 0;
 	}
 
-	result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size),
-		_ALIGN_UP(len, 1 << r->page_size), &c);
+	result = dma_sb_map_pages(r, aligned_phys, aligned_len, &c, iopte_flag);
 
 	if (result) {
 		*bus_addr = 0;
-		DBG("%s:%d: dma_map_pages failed (%d)\n",
+		DBG("%s:%d: dma_sb_map_pages failed (%d)\n",
 			__func__, __LINE__, result);
 		spin_unlock_irqrestore(&r->chunk_list.lock, flags);
 		return result;
@@ -610,8 +835,57 @@
 	return result;
 }
 
+static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
+	     unsigned long len, unsigned long *bus_addr,
+	     u64 iopte_flag)
+{
+	int result;
+	unsigned long flags;
+	struct dma_chunk *c;
+	unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
+		: virt_addr;
+	unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
+	unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
+					      1 << r->page_size);
+
+	DBG(KERN_ERR "%s: vaddr=%#lx, len=%#lx\n", __func__,
+	    virt_addr, len);
+	DBG(KERN_ERR "%s: ph=%#lx a_ph=%#lx a_l=%#lx\n", __func__,
+	    phys_addr, aligned_phys, aligned_len);
+
+	spin_lock_irqsave(&r->chunk_list.lock, flags);
+	c = dma_find_chunk_lpar(r, ps3_mm_phys_to_lpar(phys_addr), len);
+
+	if (c) {
+		/* FIXME */
+		BUG();
+		*bus_addr = c->bus_addr + phys_addr - aligned_phys;
+		c->usage_count++;
+		spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+		return 0;
+	}
+
+	result = dma_ioc0_map_pages(r, aligned_phys, aligned_len, &c,
+				    iopte_flag);
+
+	if (result) {
+		*bus_addr = 0;
+		DBG("%s:%d: dma_ioc0_map_pages failed (%d)\n",
+			__func__, __LINE__, result);
+		spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+		return result;
+	}
+	*bus_addr = c->bus_addr + phys_addr - aligned_phys;
+	DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__,
+	    virt_addr, phys_addr, aligned_phys, *bus_addr);
+	c->usage_count = 1;
+
+	spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+	return result;
+}
+
 /**
- * dma_unmap_area - Unmap an area of memory from a device dma region.
+ * dma_sb_unmap_area - Unmap an area of memory from a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @bus_addr: The starting ioc bus address of the area to unmap.
  * @len: Length in bytes of the area to unmap.
@@ -619,7 +893,7 @@
  * This is the common dma unmap routine.
  */
 
-int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
+static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
 	unsigned long len)
 {
 	unsigned long flags;
@@ -631,7 +905,8 @@
 	if (!c) {
 		unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
 			1 << r->page_size);
-		unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
+		unsigned long aligned_len = _ALIGN_UP(len + bus_addr
+			- aligned_bus, 1 << r->page_size);
 		DBG("%s:%d: not found: bus_addr %lxh\n",
 			__func__, __LINE__, bus_addr);
 		DBG("%s:%d: not found: len %lxh\n",
@@ -647,94 +922,166 @@
 
 	if (!c->usage_count) {
 		list_del(&c->link);
-		dma_free_chunk(c);
+		dma_sb_free_chunk(c);
 	}
 
 	spin_unlock_irqrestore(&r->chunk_list.lock, flags);
 	return 0;
 }
 
+static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
+			unsigned long bus_addr, unsigned long len)
+{
+	unsigned long flags;
+	struct dma_chunk *c;
+
+	DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len);
+	spin_lock_irqsave(&r->chunk_list.lock, flags);
+	c = dma_find_chunk(r, bus_addr, len);
+
+	if (!c) {
+		unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
+							1 << r->page_size);
+		unsigned long aligned_len = _ALIGN_UP(len + bus_addr
+						      - aligned_bus,
+						      1 << r->page_size);
+		DBG("%s:%d: not found: bus_addr %lxh\n",
+		    __func__, __LINE__, bus_addr);
+		DBG("%s:%d: not found: len %lxh\n",
+		    __func__, __LINE__, len);
+		DBG("%s:%d: not found: aligned_bus %lxh\n",
+		    __func__, __LINE__, aligned_bus);
+		DBG("%s:%d: not found: aligned_len %lxh\n",
+		    __func__, __LINE__, aligned_len);
+		BUG();
+	}
+
+	c->usage_count--;
+
+	if (!c->usage_count) {
+		list_del(&c->link);
+		dma_ioc0_free_chunk(c);
+	}
+
+	spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+	DBG("%s: end\n", __func__);
+	return 0;
+}
+
 /**
- * dma_region_create_linear - Setup a linear dma maping for a device.
+ * dma_sb_region_create_linear - Setup a linear dma mapping for a device.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This routine creates an HV dma region for the device and maps all available
  * ram into the io controller bus address space.
  */
 
-static int dma_region_create_linear(struct ps3_dma_region *r)
+static int dma_sb_region_create_linear(struct ps3_dma_region *r)
 {
 	int result;
-	unsigned long tmp;
+	unsigned long virt_addr, len, tmp;
 
-	/* force 16M dma pages for linear mapping */
-
-	if (r->page_size != PS3_DMA_16M) {
-		pr_info("%s:%d: forcing 16M pages for linear map\n",
-			__func__, __LINE__);
-		r->page_size = PS3_DMA_16M;
+	if (r->len > 16*1024*1024) {	/* FIXME: need proper fix */
+		/* force 16M dma pages for linear mapping */
+		if (r->page_size != PS3_DMA_16M) {
+			pr_info("%s:%d: forcing 16M pages for linear map\n",
+				__func__, __LINE__);
+			r->page_size = PS3_DMA_16M;
+			r->len = _ALIGN_UP(r->len, 1 << r->page_size);
+		}
 	}
 
-	result = dma_region_create(r);
+	result = dma_sb_region_create(r);
 	BUG_ON(result);
 
-	result = dma_map_area(r, map.rm.base, map.rm.size, &tmp);
-	BUG_ON(result);
+	if (r->offset < map.rm.size) {
+		/* Map (part of) 1st RAM chunk */
+		virt_addr = map.rm.base + r->offset;
+		len = map.rm.size - r->offset;
+		if (len > r->len)
+			len = r->len;
+		result = dma_sb_map_area(r, virt_addr, len, &tmp,
+			IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+		BUG_ON(result);
+	}
 
-	if (USE_LPAR_ADDR)
-		result = dma_map_area(r, map.r1.base, map.r1.size,
-			&tmp);
-	else
-		result = dma_map_area(r, map.rm.size, map.r1.size,
-			&tmp);
-
-	BUG_ON(result);
+	if (r->offset + r->len > map.rm.size) {
+		/* Map (part of) 2nd RAM chunk */
+		virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size;
+		len = r->len;
+		if (r->offset >= map.rm.size)
+			virt_addr += r->offset - map.rm.size;
+		else
+			len -= map.rm.size - r->offset;
+		result = dma_sb_map_area(r, virt_addr, len, &tmp,
+			IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+		BUG_ON(result);
+	}
 
 	return result;
 }
 
 /**
- * dma_region_free_linear - Free a linear dma mapping for a device.
+ * dma_sb_region_free_linear - Free a linear dma mapping for a device.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This routine will unmap all mapped areas and free the HV dma region.
  */
 
-static int dma_region_free_linear(struct ps3_dma_region *r)
+static int dma_sb_region_free_linear(struct ps3_dma_region *r)
 {
 	int result;
+	unsigned long bus_addr, len, lpar_addr;
 
-	result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size);
-	BUG_ON(result);
+	if (r->offset < map.rm.size) {
+		/* Unmap (part of) 1st RAM chunk */
+		lpar_addr = map.rm.base + r->offset;
+		len = map.rm.size - r->offset;
+		if (len > r->len)
+			len = r->len;
+		bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
+		result = dma_sb_unmap_area(r, bus_addr, len);
+		BUG_ON(result);
+	}
 
-	result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base),
-		map.r1.size);
-	BUG_ON(result);
+	if (r->offset + r->len > map.rm.size) {
+		/* Unmap (part of) 2nd RAM chunk */
+		lpar_addr = map.r1.base;
+		len = r->len;
+		if (r->offset >= map.rm.size)
+			lpar_addr += r->offset - map.rm.size;
+		else
+			len -= map.rm.size - r->offset;
+		bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
+		result = dma_sb_unmap_area(r, bus_addr, len);
+		BUG_ON(result);
+	}
 
-	result = dma_region_free(r);
+	result = dma_sb_region_free(r);
 	BUG_ON(result);
 
 	return result;
 }
 
 /**
- * dma_map_area_linear - Map an area of memory into a device dma region.
+ * dma_sb_map_area_linear - Map an area of memory into a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @virt_addr: Starting virtual address of the area to map.
  * @len: Length in bytes of the area to map.
  * @bus_addr: A pointer to return the starting ioc bus address of the area to
  * map.
  *
- * This routine just returns the coresponding bus address.  Actual mapping
+ * This routine just returns the corresponding bus address.  Actual mapping
  * occurs in dma_region_create_linear().
  */
 
-static int dma_map_area_linear(struct ps3_dma_region *r,
-	unsigned long virt_addr, unsigned long len, unsigned long *bus_addr)
+static int dma_sb_map_area_linear(struct ps3_dma_region *r,
+	unsigned long virt_addr, unsigned long len, unsigned long *bus_addr,
+	u64 iopte_flag)
 {
 	unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
 		: virt_addr;
-	*bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
+	*bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
 	return 0;
 }
 
@@ -744,42 +1091,98 @@
  * @bus_addr: The starting ioc bus address of the area to unmap.
  * @len: Length in bytes of the area to unmap.
  *
- * This routine does nothing.  Unmapping occurs in dma_region_free_linear().
+ * This routine does nothing.  Unmapping occurs in dma_sb_region_free_linear().
  */
 
-static int dma_unmap_area_linear(struct ps3_dma_region *r,
+static int dma_sb_unmap_area_linear(struct ps3_dma_region *r,
 	unsigned long bus_addr, unsigned long len)
 {
 	return 0;
+};
+
+static const struct ps3_dma_region_ops ps3_dma_sb_region_ops =  {
+	.create = dma_sb_region_create,
+	.free = dma_sb_region_free,
+	.map = dma_sb_map_area,
+	.unmap = dma_sb_unmap_area
+};
+
+static const struct ps3_dma_region_ops ps3_dma_sb_region_linear_ops = {
+	.create = dma_sb_region_create_linear,
+	.free = dma_sb_region_free_linear,
+	.map = dma_sb_map_area_linear,
+	.unmap = dma_sb_unmap_area_linear
+};
+
+static const struct ps3_dma_region_ops ps3_dma_ioc0_region_ops = {
+	.create = dma_ioc0_region_create,
+	.free = dma_ioc0_region_free,
+	.map = dma_ioc0_map_area,
+	.unmap = dma_ioc0_unmap_area
+};
+
+int ps3_dma_region_init(struct ps3_system_bus_device *dev,
+	struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
+	enum ps3_dma_region_type region_type, void *addr, unsigned long len)
+{
+	unsigned long lpar_addr;
+
+	lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0;
+
+	r->dev = dev;
+	r->page_size = page_size;
+	r->region_type = region_type;
+	r->offset = lpar_addr;
+	if (r->offset >= map.rm.size)
+		r->offset -= map.r1.offset;
+	r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size);
+
+	switch (dev->dev_type) {
+	case PS3_DEVICE_TYPE_SB:
+		r->region_ops =  (USE_DYNAMIC_DMA)
+			? &ps3_dma_sb_region_ops
+			: &ps3_dma_sb_region_linear_ops;
+		break;
+	case PS3_DEVICE_TYPE_IOC0:
+		r->region_ops = &ps3_dma_ioc0_region_ops;
+		break;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+	return 0;
 }
+EXPORT_SYMBOL(ps3_dma_region_init);
 
 int ps3_dma_region_create(struct ps3_dma_region *r)
 {
-	return (USE_DYNAMIC_DMA)
-		? dma_region_create(r)
-		: dma_region_create_linear(r);
+	BUG_ON(!r);
+	BUG_ON(!r->region_ops);
+	BUG_ON(!r->region_ops->create);
+	return r->region_ops->create(r);
 }
+EXPORT_SYMBOL(ps3_dma_region_create);
 
 int ps3_dma_region_free(struct ps3_dma_region *r)
 {
-	return (USE_DYNAMIC_DMA)
-		? dma_region_free(r)
-		: dma_region_free_linear(r);
+	BUG_ON(!r);
+	BUG_ON(!r->region_ops);
+	BUG_ON(!r->region_ops->free);
+	return r->region_ops->free(r);
 }
+EXPORT_SYMBOL(ps3_dma_region_free);
 
 int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
-	unsigned long len, unsigned long *bus_addr)
+	unsigned long len, unsigned long *bus_addr,
+	u64 iopte_flag)
 {
-	return (USE_DYNAMIC_DMA)
-		? dma_map_area(r, virt_addr, len, bus_addr)
-		: dma_map_area_linear(r, virt_addr, len, bus_addr);
+	return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag);
 }
 
 int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
 	unsigned long len)
 {
-	return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len)
-		: dma_unmap_area_linear(r, bus_addr, len);
+	return r->region_ops->unmap(r, bus_addr, len);
 }
 
 /*============================================================================*/
@@ -810,12 +1213,13 @@
 	BUG_ON(map.rm.base);
 	BUG_ON(!map.rm.size);
 
-	lmb_add(map.rm.base, map.rm.size);
-	lmb_analyze();
 
 	/* arrange to do this in ps3_mm_add_memory */
 	ps3_mm_region_create(&map.r1, map.total - map.rm.size);
 
+	/* correct map.total for the real total amount of memory we use */
+	map.total = map.rm.size + map.r1.size;
+
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 5c3da08..b70e474 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -133,7 +133,7 @@
 } static saved_params;
 
 #define dump_header(_a) _dump_header(_a, __func__, __LINE__)
-static void _dump_header(const struct os_area_header __iomem *h, const char* func,
+static void _dump_header(const struct os_area_header *h, const char *func,
 	int line)
 {
 	pr_debug("%s:%d: h.magic_num:         '%s'\n", func, line,
@@ -151,7 +151,7 @@
 }
 
 #define dump_params(_a) _dump_params(_a, __func__, __LINE__)
-static void _dump_params(const struct os_area_params __iomem *p, const char* func,
+static void _dump_params(const struct os_area_params *p, const char *func,
 	int line)
 {
 	pr_debug("%s:%d: p.boot_flag:       %u\n", func, line, p->boot_flag);
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index ca04f03..87d5206 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -41,6 +41,7 @@
 /* irq */
 
 void ps3_init_IRQ(void);
+void ps3_shutdown_IRQ(int cpu);
 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
 
 /* smp */
@@ -82,6 +83,7 @@
 	PS3_DEV_TYPE_STOR_ROM = TYPE_ROM,	/* 5 */
 	PS3_DEV_TYPE_SB_GPIO = 6,
 	PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC,	/* 14 */
+	PS3_DEV_TYPE_NOACCESS = 255,
 };
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -129,24 +131,28 @@
 /* repository bus enumerators */
 
 struct ps3_repository_device {
+	enum ps3_bus_type bus_type;
 	unsigned int bus_index;
+	unsigned int bus_id;
+	enum ps3_dev_type dev_type;
 	unsigned int dev_index;
-	struct ps3_device_id did;
+	unsigned int dev_id;
 };
 
-int ps3_repository_find_device(enum ps3_bus_type bus_type,
-	enum ps3_dev_type dev_type,
-	const struct ps3_repository_device *start_dev,
-	struct ps3_repository_device *dev);
-static inline int ps3_repository_find_first_device(
-	enum ps3_bus_type bus_type, enum ps3_dev_type dev_type,
-	struct ps3_repository_device *dev)
+static inline struct ps3_repository_device *ps3_repository_bump_device(
+	struct ps3_repository_device *repo)
 {
-	return ps3_repository_find_device(bus_type, dev_type, NULL, dev);
+	repo->dev_index++;
+	return repo;
 }
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_device(struct ps3_repository_device *repo);
+int ps3_repository_find_devices(enum ps3_bus_type bus_type,
+	int (*callback)(const struct ps3_repository_device *repo));
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+	unsigned int *bus_index);
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id);
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len);
 
 /* repository block device info */
@@ -216,4 +222,19 @@
 int ps3_repository_read_spu_resource_id(unsigned int res_index,
 	enum ps3_spu_resource_type* resource_type, unsigned int *resource_id);
 
+/* repository vuart info */
+
+int ps3_repository_read_vuart_av_port(unsigned int *port);
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port);
+
+/* Page table entries */
+#define IOPTE_PP_W		0x8000000000000000ul /* protection: write */
+#define IOPTE_PP_R		0x4000000000000000ul /* protection: read */
+#define IOPTE_M			0x2000000000000000ul /* coherency required */
+#define IOPTE_SO_R		0x1000000000000000ul /* ordering: writes */
+#define IOPTE_SO_RW             0x1800000000000000ul /* ordering: r & w */
+#define IOPTE_RPN_Mask		0x07fffffffffff000ul /* RPN */
+#define IOPTE_H			0x0000000000000800ul /* cache hint */
+#define IOPTE_IOID_Mask		0x00000000000007fful /* ioid */
+
 #endif
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index ae586a0..8cc37cfe 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -138,7 +138,7 @@
 		pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 		dump_node_name(lpar_id, n1, n2, n3, n4);
-		return result;
+		return -ENOENT;
 	}
 
 	dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
@@ -155,7 +155,7 @@
 		pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
 			__func__, __LINE__, v2);
 
-	return result;
+	return 0;
 }
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -314,324 +314,140 @@
 		reg_index, bus_addr, len);
 }
 
-#if defined(DEBUG)
-int ps3_repository_dump_resource_info(unsigned int bus_index,
-	unsigned int dev_index)
+
+
+int ps3_repository_find_device(struct ps3_repository_device *repo)
 {
-	int result = 0;
-	unsigned int res_index;
+	int result;
+	struct ps3_repository_device tmp = *repo;
+	unsigned int num_dev;
 
-	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
-		bus_index, dev_index);
+	BUG_ON(repo->bus_index > 10);
+	BUG_ON(repo->dev_index > 10);
 
-	for (res_index = 0; res_index < 10; res_index++) {
-		enum ps3_interrupt_type intr_type;
-		unsigned int interrupt_id;
+	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
 
-		result = ps3_repository_read_dev_intr(bus_index, dev_index,
-			res_index, &intr_type, &interrupt_id);
-
-		if (result) {
-			if (result !=  LV1_NO_ENTRY)
-				pr_debug("%s:%d ps3_repository_read_dev_intr"
-					" (%u:%u) failed\n", __func__, __LINE__,
-					bus_index, dev_index);
-			break;
-		}
-
-		pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
-			__func__, __LINE__, bus_index, dev_index, intr_type,
-			interrupt_id);
-	}
-
-	for (res_index = 0; res_index < 10; res_index++) {
-		enum ps3_reg_type reg_type;
-		u64 bus_addr;
-		u64 len;
-
-		result = ps3_repository_read_dev_reg(bus_index, dev_index,
-			res_index, &reg_type, &bus_addr, &len);
-
-		if (result) {
-			if (result !=  LV1_NO_ENTRY)
-				pr_debug("%s:%d ps3_repository_read_dev_reg"
-					" (%u:%u) failed\n", __func__, __LINE__,
-					bus_index, dev_index);
-			break;
-		}
-
-		pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
-			__func__, __LINE__, bus_index, dev_index, reg_type,
-			bus_addr, len);
-	}
-
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
-}
-
-static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index)
-{
-	int result = 0;
-	unsigned int num_regions, region_index;
-	u64 port, blk_size, num_blocks;
-
-	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
-		bus_index, dev_index);
-
-	result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port,
-		&blk_size, &num_blocks, &num_regions);
 	if (result) {
-		pr_debug("%s:%d ps3_repository_read_stor_dev_info"
-			" (%u:%u) failed\n", __func__, __LINE__,
-			bus_index, dev_index);
-		goto out;
+		pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
+		return result;
 	}
 
-	pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
-		 "%lu, num_regions %u\n",
-		 __func__, __LINE__, bus_index, dev_index, port,
-		 blk_size, num_blocks, num_regions);
+	pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n",
+		__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
+		num_dev);
 
-	for (region_index = 0; region_index < num_regions; region_index++) {
-		unsigned int region_id;
-		u64 region_start, region_size;
-
-		result = ps3_repository_read_stor_dev_region(bus_index,
-			dev_index, region_index, &region_id, &region_start,
-			&region_size);
-		if (result) {
-			 pr_debug("%s:%d ps3_repository_read_stor_dev_region"
-				  " (%u:%u) failed\n", __func__, __LINE__,
-				  bus_index, dev_index);
-			break;
-		}
-
-		pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
-			 __func__, __LINE__, bus_index, dev_index, region_id,
-			 region_start, region_size);
+	if (tmp.dev_index >= num_dev) {
+		pr_debug("%s:%d: no device found\n", __func__, __LINE__);
+		return -ENODEV;
 	}
 
-out:
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
+	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
+		&tmp.dev_type);
+
+	if (result) {
+		pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__);
+		return result;
+	}
+
+	result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
+		&tmp.dev_id);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__,
+		__LINE__);
+		return result;
+	}
+
+	pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n",
+		__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
+
+	*repo = tmp;
+	return 0;
 }
 
-static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type,
-			    unsigned int num_dev)
+int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
+	int (*callback)(const struct ps3_repository_device *repo))
 {
 	int result = 0;
-	unsigned int dev_index;
+	struct ps3_repository_device repo;
 
-	pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index);
+	pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
 
-	for (dev_index = 0; dev_index < num_dev; dev_index++) {
-		enum ps3_dev_type dev_type;
-		unsigned int dev_id;
+	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
 
-		result = ps3_repository_read_dev_type(bus_index, dev_index,
-			&dev_type);
-
-		if (result) {
-			pr_debug("%s:%d ps3_repository_read_dev_type"
-				" (%u:%u) failed\n", __func__, __LINE__,
-				bus_index, dev_index);
-			break;
-		}
-
-		result = ps3_repository_read_dev_id(bus_index, dev_index,
-			&dev_id);
-
-		if (result) {
-			pr_debug("%s:%d ps3_repository_read_dev_id"
-				" (%u:%u) failed\n", __func__, __LINE__,
-				bus_index, dev_index);
-			continue;
-		}
-
-		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
-			__LINE__, bus_index, dev_index, dev_type, dev_id);
-
-		ps3_repository_dump_resource_info(bus_index, dev_index);
-
-		if (bus_type == PS3_BUS_TYPE_STORAGE)
-			dump_stor_dev_info(bus_index, dev_index);
-	}
-
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
-}
-
-int ps3_repository_dump_bus_info(void)
-{
-	int result = 0;
-	unsigned int bus_index;
-
-	pr_debug(" -> %s:%d\n", __func__, __LINE__);
-
-	for (bus_index = 0; bus_index < 10; bus_index++) {
-		enum ps3_bus_type bus_type;
-		unsigned int bus_id;
-		unsigned int num_dev;
-
-		result = ps3_repository_read_bus_type(bus_index, &bus_type);
+		result = ps3_repository_read_bus_type(repo.bus_index,
+			&repo.bus_type);
 
 		if (result) {
 			pr_debug("%s:%d read_bus_type(%u) failed\n",
-				__func__, __LINE__, bus_index);
+				__func__, __LINE__, repo.bus_index);
 			break;
 		}
 
-		result = ps3_repository_read_bus_id(bus_index, &bus_id);
+		if (repo.bus_type != bus_type) {
+			pr_debug("%s:%d: skip, bus_type %u\n", __func__,
+				__LINE__, repo.bus_type);
+			continue;
+		}
+
+		result = ps3_repository_read_bus_id(repo.bus_index,
+			&repo.bus_id);
 
 		if (result) {
 			pr_debug("%s:%d read_bus_id(%u) failed\n",
-				__func__, __LINE__, bus_index);
+				__func__, __LINE__, repo.bus_index);
 			continue;
 		}
 
-		if (bus_index != bus_id)
-			pr_debug("%s:%d bus_index != bus_id\n",
-				__func__, __LINE__);
+		for (repo.dev_index = 0; ; repo.dev_index++) {
+			result = ps3_repository_find_device(&repo);
 
-		result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
+			if (result == -ENODEV) {
+				result = 0;
+				break;
+			} else if (result)
+				break;
 
-		if (result) {
-			pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
-				__func__, __LINE__, bus_index);
-			continue;
+			result = callback(&repo);
+
+			if (result) {
+				pr_debug("%s:%d: abort at callback\n", __func__,
+					__LINE__);
+				break;
+			}
 		}
-
-		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
-			__func__, __LINE__, bus_index, bus_type, bus_id,
-			num_dev);
-
-		dump_device_info(bus_index, bus_type, num_dev);
+		break;
 	}
 
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
-#endif /* defined(DEBUG) */
 
-static int find_device(unsigned int bus_index, unsigned int num_dev,
-	unsigned int start_dev_index, enum ps3_dev_type dev_type,
-	struct ps3_repository_device *dev)
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+	unsigned int *bus_index)
 {
-	int result = 0;
-	unsigned int dev_index;
+	unsigned int i;
+	enum ps3_bus_type type;
+	int error;
 
-	pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type);
-
-	dev->dev_index = UINT_MAX;
-
-	for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) {
-		enum ps3_dev_type x;
-
-		result = ps3_repository_read_dev_type(bus_index, dev_index,
-			&x);
-
-		if (result) {
-			pr_debug("%s:%d read_dev_type failed\n",
-				__func__, __LINE__);
-			return result;
-		}
-
-		if (x == dev_type)
-			break;
-	}
-
-	if (dev_index == num_dev)
-		return -1;
-
-	pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
-		__func__, __LINE__, dev_type, dev_index);
-
-	result = ps3_repository_read_dev_id(bus_index, dev_index,
-		&dev->did.dev_id);
-
-	if (result) {
-		pr_debug("%s:%d read_dev_id failed\n",
-			__func__, __LINE__);
-		return result;
-	}
-
-	dev->dev_index = dev_index;
-
-	pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__,
-		dev->did.dev_id);
-
-	return result;
-}
-
-int ps3_repository_find_device (enum ps3_bus_type bus_type,
-	enum ps3_dev_type dev_type,
-	const struct ps3_repository_device *start_dev,
-	struct ps3_repository_device *dev)
-{
-	int result = 0;
-	unsigned int bus_index;
-	unsigned int num_dev;
-
-	pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
-		bus_type, dev_type);
-
-	BUG_ON(start_dev && start_dev->bus_index > 10);
-
-	for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
-		bus_index++) {
-		enum ps3_bus_type x;
-
-		result = ps3_repository_read_bus_type(bus_index, &x);
-
-		if (result) {
+	for (i = from; i < 10; i++) {
+		error = ps3_repository_read_bus_type(i, &type);
+		if (error) {
 			pr_debug("%s:%d read_bus_type failed\n",
 				__func__, __LINE__);
-			dev->bus_index = UINT_MAX;
-			return result;
+			*bus_index = UINT_MAX;
+			return error;
 		}
-		if (x == bus_type)
-			break;
+		if (type == bus_type) {
+			*bus_index = i;
+			return 0;
+		}
 	}
-
-	if (bus_index >= 10)
-		return -ENODEV;
-
-	pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
-		__func__, __LINE__, bus_type, bus_index);
-
-	result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
-
-	if (result) {
-		pr_debug("%s:%d read_bus_num_dev failed\n",
-			__func__, __LINE__);
-		return result;
-	}
-
-	result = find_device(bus_index, num_dev, start_dev
-		? start_dev->dev_index + 1 : 0, dev_type, dev);
-
-	if (result) {
-		pr_debug("%s:%d get_did failed\n", __func__, __LINE__);
-		return result;
-	}
-
-	result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id);
-
-	if (result) {
-		pr_debug("%s:%d read_bus_id failed\n",
-			__func__, __LINE__);
-		return result;
-	}
-
-	dev->bus_index = bus_index;
-
-	pr_debug("%s:%d found: bus_id %u, dev_id %u\n",
-		__func__, __LINE__, dev->did.bus_id, dev->did.dev_id);
-
-	return result;
+	*bus_index = UINT_MAX;
+	return -ENODEV;
 }
 
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
 {
 	int result = 0;
@@ -645,8 +461,8 @@
 		enum ps3_interrupt_type t;
 		unsigned int id;
 
-		result = ps3_repository_read_dev_intr(dev->bus_index,
-			dev->dev_index, res_index, &t, &id);
+		result = ps3_repository_read_dev_intr(repo->bus_index,
+			repo->dev_index, res_index, &t, &id);
 
 		if (result) {
 			pr_debug("%s:%d read_dev_intr failed\n",
@@ -669,7 +485,7 @@
 	return result;
 }
 
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
 {
 	int result = 0;
@@ -684,8 +500,8 @@
 		u64 a;
 		u64 l;
 
-		result = ps3_repository_read_dev_reg(dev->bus_index,
-			dev->dev_index, res_index, &t, &a, &l);
+		result = ps3_repository_read_dev_reg(repo->bus_index,
+			repo->dev_index, res_index, &t, &a, &l);
 
 		if (result) {
 			pr_debug("%s:%d read_dev_reg failed\n",
@@ -965,6 +781,36 @@
 	return result;
 }
 
+int ps3_repository_read_vuart_av_port(unsigned int *port)
+{
+	int result;
+	u64 v1;
+
+	result = read_node(PS3_LPAR_ID_CURRENT,
+		make_first_field("bi", 0),
+		make_field("vir_uart", 0),
+		make_field("port", 0),
+		make_field("avset", 0),
+		&v1, 0);
+	*port = v1;
+	return result;
+}
+
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
+{
+	int result;
+	u64 v1;
+
+	result = read_node(PS3_LPAR_ID_CURRENT,
+		make_first_field("bi", 0),
+		make_field("vir_uart", 0),
+		make_field("port", 0),
+		make_field("sysmgr", 0),
+		&v1, 0);
+	*port = v1;
+	return result;
+}
+
 /**
   * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
   * address: lpar address of cell_ext_os_area
@@ -1026,3 +872,205 @@
 	return result ? result
 		: ps3_repository_read_tb_freq(node_id, tb_freq);
 }
+
+#if defined(DEBUG)
+
+int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
+{
+	int result = 0;
+	unsigned int res_index;
+
+	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+		repo->bus_index, repo->dev_index);
+
+	for (res_index = 0; res_index < 10; res_index++) {
+		enum ps3_interrupt_type intr_type;
+		unsigned int interrupt_id;
+
+		result = ps3_repository_read_dev_intr(repo->bus_index,
+			repo->dev_index, res_index, &intr_type, &interrupt_id);
+
+		if (result) {
+			if (result !=  LV1_NO_ENTRY)
+				pr_debug("%s:%d ps3_repository_read_dev_intr"
+					" (%u:%u) failed\n", __func__, __LINE__,
+					repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			intr_type, interrupt_id);
+	}
+
+	for (res_index = 0; res_index < 10; res_index++) {
+		enum ps3_reg_type reg_type;
+		u64 bus_addr;
+		u64 len;
+
+		result = ps3_repository_read_dev_reg(repo->bus_index,
+			repo->dev_index, res_index, &reg_type, &bus_addr, &len);
+
+		if (result) {
+			if (result !=  LV1_NO_ENTRY)
+				pr_debug("%s:%d ps3_repository_read_dev_reg"
+					" (%u:%u) failed\n", __func__, __LINE__,
+					repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			reg_type, bus_addr, len);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int dump_stor_dev_info(struct ps3_repository_device *repo)
+{
+	int result = 0;
+	unsigned int num_regions, region_index;
+	u64 port, blk_size, num_blocks;
+
+	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+		repo->bus_index, repo->dev_index);
+
+	result = ps3_repository_read_stor_dev_info(repo->bus_index,
+		repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
+	if (result) {
+		pr_debug("%s:%d ps3_repository_read_stor_dev_info"
+			" (%u:%u) failed\n", __func__, __LINE__,
+			repo->bus_index, repo->dev_index);
+		goto out;
+	}
+
+	pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
+		 "%lu, num_regions %u\n",
+		 __func__, __LINE__, repo->bus_index, repo->dev_index, port,
+		 blk_size, num_blocks, num_regions);
+
+	for (region_index = 0; region_index < num_regions; region_index++) {
+		unsigned int region_id;
+		u64 region_start, region_size;
+
+		result = ps3_repository_read_stor_dev_region(repo->bus_index,
+			repo->dev_index, region_index, &region_id,
+			&region_start, &region_size);
+		if (result) {
+			 pr_debug("%s:%d ps3_repository_read_stor_dev_region"
+				  " (%u:%u) failed\n", __func__, __LINE__,
+				  repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			region_id, region_start, region_size);
+	}
+
+out:
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int dump_device_info(struct ps3_repository_device *repo,
+	unsigned int num_dev)
+{
+	int result = 0;
+
+	pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
+
+	for (repo->dev_index = 0; repo->dev_index < num_dev;
+		repo->dev_index++) {
+
+		result = ps3_repository_read_dev_type(repo->bus_index,
+			repo->dev_index, &repo->dev_type);
+
+		if (result) {
+			pr_debug("%s:%d ps3_repository_read_dev_type"
+				" (%u:%u) failed\n", __func__, __LINE__,
+				repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		result = ps3_repository_read_dev_id(repo->bus_index,
+			repo->dev_index, &repo->dev_id);
+
+		if (result) {
+			pr_debug("%s:%d ps3_repository_read_dev_id"
+				" (%u:%u) failed\n", __func__, __LINE__,
+				repo->bus_index, repo->dev_index);
+			continue;
+		}
+
+		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
+			__LINE__, repo->bus_index, repo->dev_index,
+			repo->dev_type, repo->dev_id);
+
+		ps3_repository_dump_resource_info(repo);
+
+		if (repo->bus_type == PS3_BUS_TYPE_STORAGE)
+			dump_stor_dev_info(repo);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+int ps3_repository_dump_bus_info(void)
+{
+	int result = 0;
+	struct ps3_repository_device repo;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	memset(&repo, 0, sizeof(repo));
+
+	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
+		unsigned int num_dev;
+
+		result = ps3_repository_read_bus_type(repo.bus_index,
+			&repo.bus_type);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_type(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			break;
+		}
+
+		result = ps3_repository_read_bus_id(repo.bus_index,
+			&repo.bus_id);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_id(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			continue;
+		}
+
+		if (repo.bus_index != repo.bus_id)
+			pr_debug("%s:%d bus_index != bus_id\n",
+				__func__, __LINE__);
+
+		result = ps3_repository_read_bus_num_dev(repo.bus_index,
+			&num_dev);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			continue;
+		}
+
+		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
+			__func__, __LINE__, repo.bus_index, repo.bus_type,
+			repo.bus_id, num_dev);
+
+		dump_device_info(&repo, num_dev);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+#endif /* defined(DEBUG) */
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 9353967..aa05288 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -37,28 +37,36 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 #if !defined(CONFIG_SMP)
 static void smp_send_stop(void) {}
 #endif
 
-int ps3_get_firmware_version(union ps3_firmware_version *v)
+static union ps3_firmware_version ps3_firmware_version;
+
+void ps3_get_firmware_version(union ps3_firmware_version *v)
 {
-	int result = lv1_get_version_info(&v->raw);
-
-	if (result) {
-		v->raw = 0;
-		return -1;
-	}
-
-	return result;
+	*v = ps3_firmware_version;
 }
 EXPORT_SYMBOL_GPL(ps3_get_firmware_version);
 
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev)
+{
+	union ps3_firmware_version x;
+
+	x.pad = 0;
+	x.major = major;
+	x.minor = minor;
+	x.rev = rev;
+
+	return (ps3_firmware_version.raw - x.raw);
+}
+EXPORT_SYMBOL_GPL(ps3_compare_firmware_version);
+
 static void ps3_power_save(void)
 {
 	/*
@@ -99,7 +107,8 @@
 	while(1);
 }
 
-#ifdef CONFIG_FB_PS3
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \
+    defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
 static void prealloc(struct ps3_prealloc *p)
 {
 	if (!p->size)
@@ -115,12 +124,15 @@
 	printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
 	       p->address);
 }
+#endif
 
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE)
 struct ps3_prealloc ps3fb_videomemory = {
-    .name = "ps3fb videomemory",
-    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
-    .align = 1024*1024			/* the GPU requires 1 MiB alignment */
+	.name = "ps3fb videomemory",
+	.size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+	.align = 1024*1024		/* the GPU requires 1 MiB alignment */
 };
+EXPORT_SYMBOL_GPL(ps3fb_videomemory);
 #define prealloc_ps3fb_videomemory()	prealloc(&ps3fb_videomemory)
 
 static int __init early_parse_ps3fb(char *p)
@@ -137,6 +149,30 @@
 #define prealloc_ps3fb_videomemory()	do { } while (0)
 #endif
 
+#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
+struct ps3_prealloc ps3flash_bounce_buffer = {
+	.name = "ps3flash bounce buffer",
+	.size = 256*1024,
+	.align = 256*1024
+};
+EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer);
+#define prealloc_ps3flash_bounce_buffer()	prealloc(&ps3flash_bounce_buffer)
+
+static int __init early_parse_ps3flash(char *p)
+{
+	if (!p)
+		return 1;
+
+	if (!strcmp(p, "off"))
+		ps3flash_bounce_buffer.size = 0;
+
+	return 0;
+}
+early_param("ps3flash", early_parse_ps3flash);
+#else
+#define prealloc_ps3flash_bounce_buffer()	do { } while (0)
+#endif
+
 static int ps3_set_dabr(u64 dabr)
 {
 	enum {DABR_USER = 1, DABR_KERNEL = 2,};
@@ -146,13 +182,13 @@
 
 static void __init ps3_setup_arch(void)
 {
-	union ps3_firmware_version v;
 
 	DBG(" -> %s:%d\n", __func__, __LINE__);
 
-	ps3_get_firmware_version(&v);
-	printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", v.major, v.minor,
-		v.rev);
+	lv1_get_version_info(&ps3_firmware_version.raw);
+	printk(KERN_INFO "PS3 firmware version %u.%u.%u\n",
+	       ps3_firmware_version.major, ps3_firmware_version.minor,
+	       ps3_firmware_version.rev);
 
 	ps3_spu_set_platform();
 	ps3_map_htab();
@@ -166,6 +202,8 @@
 #endif
 
 	prealloc_ps3fb_videomemory();
+	prealloc_ps3flash_bounce_buffer();
+
 	ppc_md.power_save = ps3_power_save;
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
@@ -184,7 +222,7 @@
 	DBG(" -> %s:%d\n", __func__, __LINE__);
 
 	dt_root = of_get_flat_dt_root();
-	if (!of_flat_dt_is_compatible(dt_root, "PS3"))
+	if (!of_flat_dt_is_compatible(dt_root, "sony,ps3"))
 		return 0;
 
 	powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
@@ -201,31 +239,12 @@
 #if defined(CONFIG_KEXEC)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-	DBG(" -> %s:%d\n", __func__, __LINE__);
+	int cpu = smp_processor_id();
 
-	if (secondary) {
-		int cpu;
-		for_each_online_cpu(cpu)
-			if (cpu)
-				ps3_smp_cleanup_cpu(cpu);
-	} else
-		ps3_smp_cleanup_cpu(0);
+	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
-	DBG(" <- %s:%d\n", __func__, __LINE__);
-}
-
-static void ps3_machine_kexec(struct kimage *image)
-{
-	unsigned long ppe_id;
-
-	DBG(" -> %s:%d\n", __func__, __LINE__);
-
-	lv1_get_logical_ppe_id(&ppe_id);
-	lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
-	ps3_mm_shutdown();
-	ps3_mm_vas_destroy();
-
-	default_machine_kexec(image);
+	ps3_smp_cleanup_cpu(cpu);
+	ps3_shutdown_IRQ(cpu);
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
@@ -247,7 +266,7 @@
 	.power_off			= ps3_power_off,
 #if defined(CONFIG_KEXEC)
 	.kexec_cpu_down			= ps3_kexec_cpu_down,
-	.machine_kexec			= ps3_machine_kexec,
+	.machine_kexec			= default_machine_kexec,
 	.machine_kexec_prepare		= default_machine_kexec_prepare,
 	.machine_crash_shutdown		= default_machine_crash_shutdown,
 #endif
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c
index 53416ec..f0b12f2 100644
--- a/arch/powerpc/platforms/ps3/smp.c
+++ b/arch/powerpc/platforms/ps3/smp.c
@@ -27,9 +27,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 static irqreturn_t ipi_function_handler(int irq, void *msg)
@@ -39,11 +39,11 @@
 }
 
 /**
-  * virqs - a per cpu array of virqs for ipi use
+  * ps3_ipi_virqs - a per cpu array of virqs for ipi use
   */
 
 #define MSG_COUNT 4
-static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]);
+static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]);
 
 static const char *names[MSG_COUNT] = {
 	"ipi call",
@@ -62,7 +62,7 @@
 		return;
 	}
 
-	virq = per_cpu(virqs, target)[msg];
+	virq = per_cpu(ps3_ipi_virqs, target)[msg];
 	result = ps3_send_event_locally(virq);
 
 	if (result)
@@ -94,13 +94,13 @@
 static void __init ps3_smp_setup_cpu(int cpu)
 {
 	int result;
-	unsigned int *virqs = per_cpu(virqs, cpu);
+	unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
 	int i;
 
 	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
 	/*
-	 * Check assumptions on virqs[] indexing. If this
+	 * Check assumptions on ps3_ipi_virqs[] indexing. If this
 	 * check fails, then a different mapping of PPC_MSG_
 	 * to index needs to be setup.
 	 */
@@ -132,13 +132,13 @@
 
 void ps3_smp_cleanup_cpu(int cpu)
 {
-	unsigned int *virqs = per_cpu(virqs, cpu);
+	unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
 	int i;
 
 	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
 	for (i = 0; i < MSG_COUNT; i++) {
-		free_irq(virqs[i], (void*)(long)i);
+		/* Can't call free_irq from interrupt context. */
 		ps3_event_receive_port_destroy(virqs[i]);
 		virqs[i] = NO_IRQ;
 	}
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index 651437c..502d80e 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -182,15 +182,18 @@
 {
 	struct table {char* name; unsigned long addr; unsigned long size;};
 
-	spu_pdata(spu)->shadow = __ioremap(
-		spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow),
-		pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED);
+	spu_pdata(spu)->shadow = ioremap_flags(spu_pdata(spu)->shadow_addr,
+					       sizeof(struct spe_shadow),
+					       pgprot_val(PAGE_READONLY) |
+					       _PAGE_NO_CACHE);
 	if (!spu_pdata(spu)->shadow) {
 		pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
 		goto fail_ioremap;
 	}
 
-	spu->local_store = ioremap(spu->local_store_phys, LS_SIZE);
+	spu->local_store = (__force void *)ioremap_flags(spu->local_store_phys,
+		LS_SIZE, _PAGE_NO_CACHE);
+
 	if (!spu->local_store) {
 		pr_debug("%s:%d: ioremap local_store failed\n",
 			__func__, __LINE__);
@@ -199,6 +202,7 @@
 
 	spu->problem = ioremap(spu->problem_phys,
 		sizeof(struct spu_problem));
+
 	if (!spu->problem) {
 		pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__);
 		goto fail_ioremap;
@@ -206,6 +210,7 @@
 
 	spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr,
 		sizeof(struct spu_priv2));
+
 	if (!spu->priv2) {
 		pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__);
 		goto fail_ioremap;
@@ -400,11 +405,13 @@
 		}
 	}
 
-	if (result)
+	if (result) {
 		printk(KERN_WARNING "%s:%d: Error initializing spus\n",
 			__func__, __LINE__);
+		return result;
+	}
 
-	return result;
+	return num_resource_id;
 }
 
 const struct spu_management_ops spu_management_ps3_ops = {
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 6bda510..4bb634a 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -30,22 +30,228 @@
 
 #include "platform.h"
 
+static struct device ps3_system_bus = {
+	.bus_id = "ps3_system",
+};
+
+/* FIXME: need device usage counters! */
+struct {
+	struct mutex mutex;
+	int sb_11; /* usb 0 */
+	int sb_12; /* usb 0 */
+	int gpu;
+} static usage_hack;
+
+static int ps3_is_device(struct ps3_system_bus_device *dev,
+			 unsigned int bus_id, unsigned int dev_id)
+{
+	return dev->bus_id == bus_id && dev->dev_id == dev_id;
+}
+
+static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev)
+{
+	int result;
+
+	BUG_ON(!dev->bus_id);
+	mutex_lock(&usage_hack.mutex);
+
+	if (ps3_is_device(dev, 1, 1)) {
+		usage_hack.sb_11++;
+		if (usage_hack.sb_11 > 1) {
+			result = 0;
+			goto done;
+		}
+	}
+
+	if (ps3_is_device(dev, 1, 2)) {
+		usage_hack.sb_12++;
+		if (usage_hack.sb_12 > 1) {
+			result = 0;
+			goto done;
+		}
+	}
+
+	result = lv1_open_device(dev->bus_id, dev->dev_id, 0);
+
+	if (result) {
+		pr_debug("%s:%d: lv1_open_device failed: %s\n", __func__,
+			__LINE__, ps3_result(result));
+			result = -EPERM;
+	}
+
+done:
+	mutex_unlock(&usage_hack.mutex);
+	return result;
+}
+
+static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev)
+{
+	int result;
+
+	BUG_ON(!dev->bus_id);
+	mutex_lock(&usage_hack.mutex);
+
+	if (ps3_is_device(dev, 1, 1)) {
+		usage_hack.sb_11--;
+		if (usage_hack.sb_11) {
+			result = 0;
+			goto done;
+		}
+	}
+
+	if (ps3_is_device(dev, 1, 2)) {
+		usage_hack.sb_12--;
+		if (usage_hack.sb_12) {
+			result = 0;
+			goto done;
+		}
+	}
+
+	result = lv1_close_device(dev->bus_id, dev->dev_id);
+	BUG_ON(result);
+
+done:
+	mutex_unlock(&usage_hack.mutex);
+	return result;
+}
+
+static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev)
+{
+	int result;
+
+	mutex_lock(&usage_hack.mutex);
+
+	usage_hack.gpu++;
+	if (usage_hack.gpu > 1) {
+		result = 0;
+		goto done;
+	}
+
+	result = lv1_gpu_open(0);
+
+	if (result) {
+		pr_debug("%s:%d: lv1_gpu_open failed: %s\n", __func__,
+			__LINE__, ps3_result(result));
+			result = -EPERM;
+	}
+
+done:
+	mutex_unlock(&usage_hack.mutex);
+	return result;
+}
+
+static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev)
+{
+	int result;
+
+	mutex_lock(&usage_hack.mutex);
+
+	usage_hack.gpu--;
+	if (usage_hack.gpu) {
+		result = 0;
+		goto done;
+	}
+
+	result = lv1_gpu_close();
+	BUG_ON(result);
+
+done:
+	mutex_unlock(&usage_hack.mutex);
+	return result;
+}
+
+int ps3_open_hv_device(struct ps3_system_bus_device *dev)
+{
+	BUG_ON(!dev);
+	pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id);
+
+	switch (dev->match_id) {
+	case PS3_MATCH_ID_EHCI:
+	case PS3_MATCH_ID_OHCI:
+	case PS3_MATCH_ID_GELIC:
+	case PS3_MATCH_ID_STOR_DISK:
+	case PS3_MATCH_ID_STOR_ROM:
+	case PS3_MATCH_ID_STOR_FLASH:
+		return ps3_open_hv_device_sb(dev);
+
+	case PS3_MATCH_ID_SOUND:
+	case PS3_MATCH_ID_GRAPHICS:
+		return ps3_open_hv_device_gpu(dev);
+
+	case PS3_MATCH_ID_AV_SETTINGS:
+	case PS3_MATCH_ID_SYSTEM_MANAGER:
+		pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
+			__LINE__, dev->match_id);
+		pr_debug("%s:%d: bus_id: %u\n", __func__,
+			__LINE__, dev->bus_id);
+		BUG();
+		return -EINVAL;
+
+	default:
+		break;
+	}
+
+	pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__,
+		dev->match_id);
+	BUG();
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ps3_open_hv_device);
+
+int ps3_close_hv_device(struct ps3_system_bus_device *dev)
+{
+	BUG_ON(!dev);
+	pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id);
+
+	switch (dev->match_id) {
+	case PS3_MATCH_ID_EHCI:
+	case PS3_MATCH_ID_OHCI:
+	case PS3_MATCH_ID_GELIC:
+	case PS3_MATCH_ID_STOR_DISK:
+	case PS3_MATCH_ID_STOR_ROM:
+	case PS3_MATCH_ID_STOR_FLASH:
+		return ps3_close_hv_device_sb(dev);
+
+	case PS3_MATCH_ID_SOUND:
+	case PS3_MATCH_ID_GRAPHICS:
+		return ps3_close_hv_device_gpu(dev);
+
+	case PS3_MATCH_ID_AV_SETTINGS:
+	case PS3_MATCH_ID_SYSTEM_MANAGER:
+		pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
+			__LINE__, dev->match_id);
+		pr_debug("%s:%d: bus_id: %u\n", __func__,
+			__LINE__, dev->bus_id);
+		BUG();
+		return -EINVAL;
+
+	default:
+		break;
+	}
+
+	pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__,
+		dev->match_id);
+	BUG();
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ps3_close_hv_device);
+
 #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__)
 static void _dump_mmio_region(const struct ps3_mmio_region* r,
 	const char* func, int line)
 {
-	pr_debug("%s:%d: dev       %u:%u\n", func, line, r->did.bus_id,
-		r->did.dev_id);
+	pr_debug("%s:%d: dev       %u:%u\n", func, line, r->dev->bus_id,
+		r->dev->dev_id);
 	pr_debug("%s:%d: bus_addr  %lxh\n", func, line, r->bus_addr);
 	pr_debug("%s:%d: len       %lxh\n", func, line, r->len);
 	pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr);
 }
 
-int ps3_mmio_region_create(struct ps3_mmio_region *r)
+static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r)
 {
 	int result;
 
-	result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id,
+	result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
 		r->bus_addr, r->len, r->page_size, &r->lpar_addr);
 
 	if (result) {
@@ -57,13 +263,26 @@
 	dump_mmio_region(r);
 	return result;
 }
+
+static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r)
+{
+	/* device specific; do nothing currently */
+	return 0;
+}
+
+int ps3_mmio_region_create(struct ps3_mmio_region *r)
+{
+	return r->mmio_ops->create(r);
+}
 EXPORT_SYMBOL_GPL(ps3_mmio_region_create);
 
-int ps3_free_mmio_region(struct ps3_mmio_region *r)
+static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r)
 {
 	int result;
 
-	result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id,
+	dump_mmio_region(r);
+;
+	result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
 		r->lpar_addr);
 
 	if (result)
@@ -73,14 +292,60 @@
 	r->lpar_addr = 0;
 	return result;
 }
+
+static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r)
+{
+	/* device specific; do nothing currently */
+	return 0;
+}
+
+
+int ps3_free_mmio_region(struct ps3_mmio_region *r)
+{
+	return r->mmio_ops->free(r);
+}
+
 EXPORT_SYMBOL_GPL(ps3_free_mmio_region);
 
+static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = {
+	.create = ps3_sb_mmio_region_create,
+	.free = ps3_sb_free_mmio_region
+};
+
+static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = {
+	.create = ps3_ioc0_mmio_region_create,
+	.free = ps3_ioc0_free_mmio_region
+};
+
+int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
+	struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len,
+	enum ps3_mmio_page_size page_size)
+{
+	r->dev = dev;
+	r->bus_addr = bus_addr;
+	r->len = len;
+	r->page_size = page_size;
+	switch (dev->dev_type) {
+	case PS3_DEVICE_TYPE_SB:
+		r->mmio_ops = &ps3_mmio_sb_region_ops;
+		break;
+	case PS3_DEVICE_TYPE_IOC0:
+		r->mmio_ops = &ps3_mmio_ioc0_region_ops;
+		break;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ps3_mmio_region_init);
+
 static int ps3_system_bus_match(struct device *_dev,
 	struct device_driver *_drv)
 {
 	int result;
-	struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv);
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
 	result = dev->match_id == drv->match_id;
 
@@ -92,32 +357,14 @@
 
 static int ps3_system_bus_probe(struct device *_dev)
 {
-	int result;
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
-	struct ps3_system_bus_driver *drv =
-		to_ps3_system_bus_driver(_dev->driver);
+	int result = 0;
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	struct ps3_system_bus_driver *drv;
 
-	result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0);
+	BUG_ON(!dev);
+	pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
 
-	if (result) {
-		pr_debug("%s:%d: lv1_open_device failed (%d)\n",
-			__func__, __LINE__, result);
-		result = -EACCES;
-		goto clean_none;
-	}
-
-	if (dev->d_region->did.bus_id) {
-		result = ps3_dma_region_create(dev->d_region);
-
-		if (result) {
-			pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n",
-				__func__, __LINE__, result);
-			BUG_ON("check region type");
-			result = -EINVAL;
-			goto clean_device;
-		}
-	}
-
+	drv = ps3_system_bus_dev_to_system_bus_drv(dev);
 	BUG_ON(!drv);
 
 	if (drv->probe)
@@ -126,56 +373,127 @@
 		pr_info("%s:%d: %s no probe method\n", __func__, __LINE__,
 			dev->core.bus_id);
 
-	if (result) {
-		pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__);
-		goto clean_dma;
-	}
-
-	return result;
-
-clean_dma:
-	ps3_dma_region_free(dev->d_region);
-clean_device:
-	lv1_close_device(dev->did.bus_id, dev->did.dev_id);
-clean_none:
+	pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
 	return result;
 }
 
 static int ps3_system_bus_remove(struct device *_dev)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
-	struct ps3_system_bus_driver *drv =
-		to_ps3_system_bus_driver(_dev->driver);
+	int result = 0;
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	struct ps3_system_bus_driver *drv;
+
+	BUG_ON(!dev);
+	pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
+
+	drv = ps3_system_bus_dev_to_system_bus_drv(dev);
+	BUG_ON(!drv);
 
 	if (drv->remove)
-		drv->remove(dev);
+		result = drv->remove(dev);
 	else
-		pr_info("%s:%d: %s no remove method\n", __func__, __LINE__,
-			dev->core.bus_id);
+		dev_dbg(&dev->core, "%s:%d %s: no remove method\n",
+			__func__, __LINE__, drv->core.name);
 
-	ps3_dma_region_free(dev->d_region);
-	ps3_free_mmio_region(dev->m_region);
-	lv1_close_device(dev->did.bus_id, dev->did.dev_id);
+	pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
+	return result;
+}
 
+static void ps3_system_bus_shutdown(struct device *_dev)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	struct ps3_system_bus_driver *drv;
+
+	BUG_ON(!dev);
+
+	dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+		dev->match_id);
+
+	if (!dev->core.driver) {
+		dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+			__LINE__);
+		return;
+	}
+
+	drv = ps3_system_bus_dev_to_system_bus_drv(dev);
+
+	BUG_ON(!drv);
+
+	dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__,
+		dev->core.bus_id, drv->core.name);
+
+	if (drv->shutdown)
+		drv->shutdown(dev);
+	else if (drv->remove) {
+		dev_dbg(&dev->core, "%s:%d %s: no shutdown, calling remove\n",
+			__func__, __LINE__, drv->core.name);
+		drv->remove(dev);
+	} else {
+		dev_dbg(&dev->core, "%s:%d %s: no shutdown method\n",
+			__func__, __LINE__, drv->core.name);
+		BUG();
+	}
+
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+}
+
+static int ps3_system_bus_uevent(struct device *_dev, char **envp,
+				 int num_envp, char *buffer, int buffer_size)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	int i = 0, length = 0;
+
+	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+			   &length, "MODALIAS=ps3:%d",
+			   dev->match_id))
+		return -ENOMEM;
+
+	envp[i] = NULL;
 	return 0;
 }
 
+static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
+	char *buf)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id);
+
+	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute ps3_system_bus_dev_attrs[] = {
+	__ATTR_RO(modalias),
+	__ATTR_NULL,
+};
+
 struct bus_type ps3_system_bus_type = {
 	.name = "ps3_system_bus",
 	.match = ps3_system_bus_match,
+	.uevent = ps3_system_bus_uevent,
 	.probe = ps3_system_bus_probe,
 	.remove = ps3_system_bus_remove,
+	.shutdown = ps3_system_bus_shutdown,
+	.dev_attrs = ps3_system_bus_dev_attrs,
 };
 
-int __init ps3_system_bus_init(void)
+static int __init ps3_system_bus_init(void)
 {
 	int result;
 
 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 		return -ENODEV;
 
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	mutex_init(&usage_hack.mutex);
+
+	result = device_register(&ps3_system_bus);
+	BUG_ON(result);
+
 	result = bus_register(&ps3_system_bus_type);
 	BUG_ON(result);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
 
@@ -185,16 +503,13 @@
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
  */
-
 static void * ps3_alloc_coherent(struct device *_dev, size_t size,
-	dma_addr_t *dma_handle, gfp_t flag)
+				      dma_addr_t *dma_handle, gfp_t flag)
 {
 	int result;
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	unsigned long virt_addr;
 
-	BUG_ON(!dev->d_region->bus_addr);
-
 	flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
 	flag |= __GFP_ZERO;
 
@@ -205,7 +520,8 @@
 		goto clean_none;
 	}
 
-	result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle);
+	result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle,
+			     IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
 
 	if (result) {
 		pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -226,7 +542,7 @@
 static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
 	dma_addr_t dma_handle)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
 	ps3_dma_unmap(dev->d_region, dma_handle, size);
 	free_pages((unsigned long)vaddr, get_order(size));
@@ -239,15 +555,16 @@
  * byte within the page as vaddr.
  */
 
-static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size,
+static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size,
 	enum dma_data_direction direction)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	int result;
 	unsigned long bus_addr;
 
 	result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
-		&bus_addr);
+			     &bus_addr,
+			     IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW | IOPTE_M);
 
 	if (result) {
 		pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -257,10 +574,44 @@
 	return bus_addr;
 }
 
+static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr,
+				      size_t size,
+				      enum dma_data_direction direction)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	int result;
+	unsigned long bus_addr;
+	u64 iopte_flag;
+
+	iopte_flag = IOPTE_M;
+	switch (direction) {
+	case DMA_BIDIRECTIONAL:
+		iopte_flag |= IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW;
+		break;
+	case DMA_TO_DEVICE:
+		iopte_flag |= IOPTE_PP_R | IOPTE_SO_R;
+		break;
+	case DMA_FROM_DEVICE:
+		iopte_flag |= IOPTE_PP_W | IOPTE_SO_RW;
+		break;
+	default:
+		/* not happned */
+		BUG();
+	};
+	result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
+			     &bus_addr, iopte_flag);
+
+	if (result) {
+		pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
+			__func__, __LINE__, result);
+	}
+	return bus_addr;
+}
+
 static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
 	size_t size, enum dma_data_direction direction)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	int result;
 
 	result = ps3_dma_unmap(dev->d_region, dma_addr, size);
@@ -271,20 +622,20 @@
 	}
 }
 
-static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
+static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
 	enum dma_data_direction direction)
 {
 #if defined(CONFIG_PS3_DYNAMIC_DMA)
 	BUG_ON("do");
 	return -EPERM;
 #else
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	int i;
 
 	for (i = 0; i < nents; i++, sg++) {
 		int result = ps3_dma_map(dev->d_region,
 			page_to_phys(sg->page) + sg->offset, sg->length,
-			&sg->dma_address);
+					 &sg->dma_address, 0);
 
 		if (result) {
 			pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -299,7 +650,15 @@
 #endif
 }
 
-static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg,
+static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
+			   int nents,
+			   enum dma_data_direction direction)
+{
+	BUG();
+	return 0;
+}
+
+static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
 	int nents, enum dma_data_direction direction)
 {
 #if defined(CONFIG_PS3_DYNAMIC_DMA)
@@ -307,18 +666,34 @@
 #endif
 }
 
+static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg,
+			    int nents, enum dma_data_direction direction)
+{
+	BUG();
+}
+
 static int ps3_dma_supported(struct device *_dev, u64 mask)
 {
 	return mask >= DMA_32BIT_MASK;
 }
 
-static struct dma_mapping_ops ps3_dma_ops = {
+static struct dma_mapping_ops ps3_sb_dma_ops = {
 	.alloc_coherent = ps3_alloc_coherent,
 	.free_coherent = ps3_free_coherent,
-	.map_single = ps3_map_single,
+	.map_single = ps3_sb_map_single,
 	.unmap_single = ps3_unmap_single,
-	.map_sg = ps3_map_sg,
-	.unmap_sg = ps3_unmap_sg,
+	.map_sg = ps3_sb_map_sg,
+	.unmap_sg = ps3_sb_unmap_sg,
+	.dma_supported = ps3_dma_supported
+};
+
+static struct dma_mapping_ops ps3_ioc0_dma_ops = {
+	.alloc_coherent = ps3_alloc_coherent,
+	.free_coherent = ps3_free_coherent,
+	.map_single = ps3_ioc0_map_single,
+	.unmap_single = ps3_unmap_single,
+	.map_sg = ps3_ioc0_map_sg,
+	.unmap_sg = ps3_ioc0_unmap_sg,
 	.dma_supported = ps3_dma_supported
 };
 
@@ -328,7 +703,7 @@
 
 static void ps3_system_bus_release_device(struct device *_dev)
 {
-	struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 	kfree(dev);
 }
 
@@ -343,18 +718,37 @@
 int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
 {
 	int result;
-	static unsigned int dev_count = 1;
+	static unsigned int dev_ioc0_count;
+	static unsigned int dev_sb_count;
+	static unsigned int dev_vuart_count;
 
-	dev->core.parent = NULL;
+	if (!dev->core.parent)
+		dev->core.parent = &ps3_system_bus;
 	dev->core.bus = &ps3_system_bus_type;
 	dev->core.release = ps3_system_bus_release_device;
 
-	dev->core.archdata.of_node = NULL;
-	dev->core.archdata.dma_ops = &ps3_dma_ops;
-	dev->core.archdata.numa_node = 0;
+	switch (dev->dev_type) {
+	case PS3_DEVICE_TYPE_IOC0:
+		dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops;
+		snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+			"ioc0_%02x", ++dev_ioc0_count);
+		break;
+	case PS3_DEVICE_TYPE_SB:
+		dev->core.archdata.dma_ops = &ps3_sb_dma_ops;
+		snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+			"sb_%02x", ++dev_sb_count);
 
-	snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x",
-		dev_count++);
+		break;
+	case PS3_DEVICE_TYPE_VUART:
+		snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+			"vuart_%02x", ++dev_vuart_count);
+		break;
+	default:
+		BUG();
+	};
+
+	dev->core.archdata.of_node = NULL;
+	dev->core.archdata.numa_node = 0;
 
 	pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id);
 
@@ -368,9 +762,15 @@
 {
 	int result;
 
+	pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
+
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
+
 	drv->core.bus = &ps3_system_bus_type;
 
 	result = driver_register(&drv->core);
+	pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 	return result;
 }
 
@@ -378,7 +778,9 @@
 
 void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv)
 {
+	pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 	driver_unregister(&drv->core);
+	pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 }
 
 EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister);
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index 1bae8b1..802a9cc 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -39,7 +39,7 @@
 }
 
 #define dump_time(_a) _dump_time(_a, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_time(int time, const char* func,
+static void __maybe_unused _dump_time(int time, const char *func,
 	int line)
 {
 	struct rtc_time tm;
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index ae1fc92..992ba67 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -8,7 +8,7 @@
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
-obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o
+obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
 obj-$(CONFIG_KEXEC)	+= kexec.o
 obj-$(CONFIG_PCI)	+= pci.o pci_dlpar.o
 obj-$(CONFIG_PCI_MSI)	+= msi.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 5f3e6d8..b8770395 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1,6 +1,8 @@
 /*
  * eeh.c
- * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation
+ * Copyright IBM Corporation 2001, 2005, 2006
+ * Copyright Dave Engebretsen & Todd Inglett 2001
+ * Copyright Linas Vepstas 2005, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -15,6 +17,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 
 #include <linux/delay.h>
@@ -117,7 +121,6 @@
 static unsigned long ignored_check;
 static unsigned long total_mmio_ffs;
 static unsigned long false_positives;
-static unsigned long ignored_failures;
 static unsigned long slot_resets;
 
 #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
@@ -505,6 +508,7 @@
 		printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
 		       ret, dn->full_name);
 		false_positives++;
+		pdn->eeh_false_positives ++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -513,6 +517,7 @@
 	 * they are empty when they don't have children. */
 	if ((rets[0] == 5) && (dn->child == NULL)) {
 		false_positives++;
+		pdn->eeh_false_positives ++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -522,6 +527,7 @@
 		printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
 		       ret, dn->full_name);
 		false_positives++;
+		pdn->eeh_false_positives ++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -529,6 +535,7 @@
 	/* If not the kind of error we know about, punt. */
 	if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
 		false_positives++;
+		pdn->eeh_false_positives ++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -921,6 +928,7 @@
 	pdn->eeh_mode = 0;
 	pdn->eeh_check_count = 0;
 	pdn->eeh_freeze_count = 0;
+	pdn->eeh_false_positives = 0;
 
 	if (status && strcmp(status, "ok") != 0)
 		return NULL;	/* ignore devices with bad status */
@@ -1139,7 +1147,8 @@
 	pdn = PCI_DN(dn);
 	pdn->pcidev = dev;
 
-	pci_addr_cache_insert_device (dev);
+	pci_addr_cache_insert_device(dev);
+	eeh_sysfs_add_device(dev);
 }
 
 void eeh_add_device_tree_late(struct pci_bus *bus)
@@ -1178,6 +1187,7 @@
 	printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
 #endif
 	pci_addr_cache_remove_device(dev);
+	eeh_sysfs_remove_device(dev);
 
 	dn = pci_device_to_OF_node(dev);
 	if (PCI_DN(dn)->pcidev) {
@@ -1214,11 +1224,10 @@
 				"check not wanted=%ld\n"
 				"eeh_total_mmio_ffs=%ld\n"
 				"eeh_false_positives=%ld\n"
-				"eeh_ignored_failures=%ld\n"
 				"eeh_slot_resets=%ld\n",
 				no_device, no_dn, no_cfg_addr, 
 				ignored_check, total_mmio_ffs, 
-				false_positives, ignored_failures, 
+				false_positives,
 				slot_resets);
 	}
 
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index f2bae04..e49c815 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -2,7 +2,8 @@
  * eeh_cache.c
  * PCI address cache; allows the lookup of PCI devices based on I/O address
  *
- * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation
+ * Copyright IBM Corporation 2004
+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2004
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -295,6 +296,8 @@
 			continue;
 		pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
 		PCI_DN(dn)->pcidev = dev;
+
+		eeh_sysfs_add_device(dev);
 	}
 
 #ifdef DEBUG
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 161a584..15e015e 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -1,6 +1,7 @@
 /*
  * PCI Error Recovery Driver for RPA-compliant PPC64 platform.
- * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org>
+ * Copyright IBM Corp. 2004 2005
+ * Copyright Linas Vepstas <linas@linas.org> 2004, 2005
  *
  * All rights reserved.
  *
@@ -19,8 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <linas@us.ibm.com>
- *
+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c
new file mode 100644
index 0000000..15e13b5
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_sysfs.c
@@ -0,0 +1,87 @@
+/*
+ * Sysfs entries for PCI Error Recovery for PAPR-compliant platform.
+ * Copyright IBM Corporation 2007
+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2007
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
+ */
+#include <linux/pci.h>
+#include <asm/ppc-pci.h>
+#include <asm/pci-bridge.h>
+#include <linux/kobject.h>
+
+/**
+ * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic
+ * @_name: name of file in sysfs directory
+ * @_memb: name of member in struct pci_dn to access
+ * @_format: printf format for display
+ *
+ * All of the attributes look very similar, so just
+ * auto-gen a cut-n-paste routine to display them.
+ */
+#define EEH_SHOW_ATTR(_name,_memb,_format)               \
+static ssize_t eeh_show_##_name(struct device *dev,      \
+		struct device_attribute *attr, char *buf)          \
+{                                                        \
+	struct pci_dev *pdev = to_pci_dev(dev);               \
+	struct device_node *dn = pci_device_to_OF_node(pdev); \
+	struct pci_dn *pdn;                                   \
+	                                                      \
+	if (!dn || PCI_DN(dn) == NULL)                        \
+		return 0;                                          \
+	                                                      \
+	pdn = PCI_DN(dn);                                     \
+	return sprintf(buf, _format "\n", pdn->_memb);        \
+}                                                        \
+static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
+
+
+EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x");
+EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x");
+EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x");
+EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d");
+EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d");
+EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d");
+
+void eeh_sysfs_add_device(struct pci_dev *pdev)
+{
+	int rc=0;
+
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives);
+	rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+
+	if (rc)
+		printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
+}
+
+void eeh_sysfs_remove_device(struct pci_dev *pdev)
+{
+	device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_check_count);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives);
+	device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+}
+
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 362dfbc..8cc6eee 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -373,12 +373,23 @@
 {
 	unsigned long size_bytes = 1UL << ppc64_pft_size;
 	unsigned long hpte_count = size_bytes >> 4;
-	unsigned long dummy1, dummy2;
+	unsigned long dummy1, dummy2, dword0;
+	long lpar_rc;
 	int i;
 
 	/* TODO: Use bulk call */
-	for (i = 0; i < hpte_count; i++)
-		plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+	for (i = 0; i < hpte_count; i++) {
+		/* dont remove HPTEs with VRMA mappings */
+		lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG,
+						&dummy1, &dummy2);
+		if (lpar_rc == H_NOT_FOUND) {
+			lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1);
+			if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK)
+				!= HPTE_V_VRMA_MASK))
+				/* Can be hpte for 1TB Seg. So remove it */
+				plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+		}
+	}
 }
 
 /*
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index ffaf6c5..47f0e08 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -110,8 +110,6 @@
 			}
 		}
 	}
-
-	eeh_add_device_tree_late(bus);
 }
 EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
 
@@ -139,6 +137,8 @@
 
 	/* Make the discovered devices available */
 	pci_bus_add_devices(child_bus);
+
+	eeh_add_device_tree_late(child_bus);
 	return 0;
 }
 
@@ -171,6 +171,7 @@
 		if (!list_empty(&bus->devices)) {
 			pcibios_fixup_new_pci_devices(bus, 0);
 			pci_bus_add_devices(bus);
+			eeh_add_device_tree_late(bus);
 		}
 	} else if (mode == PCI_PROBE_NORMAL) {
 		/* use legacy probe */
@@ -179,6 +180,7 @@
 		if (num) {
 			pcibios_fixup_new_pci_devices(bus, 1);
 			pci_bus_add_devices(bus);
+			eeh_add_device_tree_late(bus);
 		}
 
 		list_for_each_entry(dev, &bus->devices, bus_list)
@@ -200,8 +202,6 @@
 	rtas_setup_phb(phb);
 	pci_process_bridge_OF_ranges(phb, dn, 0);
 
-	pci_setup_phb_io_dynamic(phb, primary);
-
 	pci_devs_phb_init_dynamic(phb);
 
 	if (dn->child)
@@ -210,6 +210,7 @@
 	scan_phb(phb);
 	pcibios_fixup_new_pci_devices(phb->bus, 0);
 	pci_bus_add_devices(phb->bus);
+	eeh_add_device_tree_late(phb->bus);
 
 	return phb;
 }
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 2e4d10c..d003c80 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -108,6 +108,21 @@
 	return rc;
 }
 
+/* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */
+static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex,
+		unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
+{
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall_raw(H_READ, retbuf, flags, ptex);
+
+	*old_pteh_ret = retbuf[0];
+	*old_ptel_ret = retbuf[1];
+
+	return rc;
+}
+
 static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
 		unsigned long avpn)
 {
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 2729d55..61e19f7 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -33,6 +33,8 @@
 static inline void setup_kexec_cpu_down_mpic(void) { }
 #endif
 
+extern void pSeries_final_fixup(void);
+
 /* Poweron flag used for enabling auto ups restart */
 extern unsigned long rtas_poweron_auto;
 
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 5aa97af..c02f874 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -123,7 +123,7 @@
 	strcpy(np->full_name, path);
 
 	np->properties = proplist;
-	OF_MARK_DYNAMIC(np);
+	of_node_set_flag(np, OF_DYNAMIC);
 	kref_init(&np->kref);
 
 	np->parent = derive_parent(path);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 470db6e..59e69f0 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -176,7 +176,7 @@
 		return;
 
 	cascade_irq = irq_of_parse_and_map(cascade, 0);
-	if (cascade == NO_IRQ) {
+	if (cascade_irq == NO_IRQ) {
 		printk(KERN_ERR "mpic: failed to map cascade interrupt");
 		return;
 	}
@@ -399,6 +399,7 @@
 	 * a good time to find other work to dispatch.
 	 */
 	get_lppaca()->idle = 1;
+	get_lppaca()->donate_dedicated_cpu = 1;
 
 	/*
 	 * We come in with interrupts disabled, and need_resched()
@@ -431,6 +432,7 @@
 
 out:
 	HMT_medium();
+	get_lppaca()->donate_dedicated_cpu = 0;
 	get_lppaca()->idle = 0;
 }
 
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index b854e7f..5bd90a7 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -156,9 +156,9 @@
 
 
 #ifdef CONFIG_SMP
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
-	unsigned int server;
+	int server;
 	/* For the moment only implement delivery to all cpus or one cpu */
 	cpumask_t cpumask = irq_desc[virq].affinity;
 	cpumask_t tmp = CPU_MASK_NONE;
@@ -166,22 +166,25 @@
 	if (!distribute_irqs)
 		return default_server;
 
-	if (cpus_equal(cpumask, CPU_MASK_ALL)) {
-		server = default_distrib_server;
-	} else {
+	if (!cpus_equal(cpumask, CPU_MASK_ALL)) {
 		cpus_and(tmp, cpu_online_map, cpumask);
 
-		if (cpus_empty(tmp))
-			server = default_distrib_server;
-		else
-			server = get_hard_smp_processor_id(first_cpu(tmp));
+		server = first_cpu(tmp);
+
+		if (server < NR_CPUS)
+			return get_hard_smp_processor_id(server);
+
+		if (strict_check)
+			return -1;
 	}
 
-	return server;
+	if (cpus_equal(cpu_online_map, cpu_present_map))
+		return default_distrib_server;
 
+	return default_server;
 }
 #else
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
 	return default_server;
 }
@@ -192,7 +195,7 @@
 {
 	unsigned int irq;
 	int call_status;
-	unsigned int server;
+	int server;
 
 	pr_debug("xics: unmask virq %d\n", virq);
 
@@ -201,7 +204,7 @@
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return;
 
-	server = get_irq_server(virq);
+	server = get_irq_server(virq, 0);
 
 	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
 				DEFAULT_PRIORITY);
@@ -398,8 +401,7 @@
 	unsigned int irq;
 	int status;
 	int xics_status[2];
-	unsigned long newmask;
-	cpumask_t tmp = CPU_MASK_NONE;
+	int irq_server;
 
 	irq = (unsigned int)irq_map[virq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
@@ -413,18 +415,21 @@
 		return;
 	}
 
-	/* For the moment only implement delivery to all cpus or one cpu */
-	if (cpus_equal(cpumask, CPU_MASK_ALL)) {
-		newmask = default_distrib_server;
-	} else {
-		cpus_and(tmp, cpu_online_map, cpumask);
-		if (cpus_empty(tmp))
-			return;
-		newmask = get_hard_smp_processor_id(first_cpu(tmp));
+	/*
+	 * For the moment only implement delivery to all cpus or one cpu.
+	 * Get current irq_server for the given irq
+	 */
+	irq_server = get_irq_server(irq, 1);
+	if (irq_server == -1) {
+		char cpulist[128];
+		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+		printk(KERN_WARNING "xics_set_affinity: No online cpus in "
+				"the mask %s for irq %d\n", cpulist, virq);
+		return;
 	}
 
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,
-				irq, newmask, xics_status[1]);
+				irq, irq_server, xics_status[1]);
 
 	if (status) {
 		printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
@@ -752,6 +757,7 @@
 void xics_request_IPIs(void)
 {
 	unsigned int ipi;
+	int rc;
 
 	ipi = irq_create_mapping(xics_host, XICS_IPI);
 	BUG_ON(ipi == NO_IRQ);
@@ -762,11 +768,12 @@
 	 */
 	set_irq_handler(ipi, handle_percpu_irq);
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
-			    "IPI", NULL);
+		rc = request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
+				"IPI", NULL);
 	else
-		request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
-			    "IPI", NULL);
+		rc = request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
+				"IPI", NULL);
+	BUG_ON(rc);
 }
 #endif /* CONFIG_SMP */
 
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index c3ce0bd..f65078c 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -5,7 +5,6 @@
 mpic-msi-obj-$(CONFIG_PCI_MSI)	+= mpic_msi.o mpic_u3msi.o
 obj-$(CONFIG_MPIC)		+= mpic.o $(mpic-msi-obj-y)
 
-obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_MPC106)	+= grackle.o
 obj-$(CONFIG_PPC_DCR)		+= dcr.o
 obj-$(CONFIG_PPC_DCR_NATIVE)	+= dcr-low.o
@@ -13,16 +12,19 @@
 obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
-obj-$(CONFIG_FSL_PCIE)		+= fsl_pcie.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
 mv64x60-$(CONFIG_PCI)		+= mv64x60_pci.o
 obj-$(CONFIG_MV64X60)		+= $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o
+obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc_cmos_setup.o
 
 # contains only the suspend handler for time
+ifeq ($(CONFIG_RTC_CLASS),)
 obj-$(CONFIG_PM)		+= timer.o
+endif
 
 ifeq ($(CONFIG_PPC_MERGE),y)
+obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
 obj-$(CONFIG_PPC_83xx)		+= ipic.o
 obj-$(CONFIG_4xx)		+= uic.o
diff --git a/arch/powerpc/sysdev/fsl_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c
deleted file mode 100644
index 041c07e..0000000
--- a/arch/powerpc/sysdev/fsl_pcie.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Support for indirect PCI bridges.
- *
- * Copyright (C) 1998 Gabriel Paubert.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * "Temporary" MPC8548 Errata file -
- * The standard indirect_pci code should work with future silicon versions.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-
-#define PCI_CFG_OUT out_be32
-
-/* ERRATA PCI-Ex 14 PCIE Controller timeout */
-#define PCIE_FIX		out_be32(hose->cfg_addr+0x4, 0x0400ffff)
-
-
-static int
-indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
-		     int len, u32 *val)
-{
-	struct pci_controller *hose = bus->sysdata;
-	volatile void __iomem *cfg_data;
-	u32 temp;
-
-	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* Possible artifact of CDCpp50937 needs further investigation */
-	if (devfn != 0x0 && bus->number == 0xff)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	PCIE_FIX;
-	if (bus->number == 0xff) {
-		PCI_CFG_OUT(hose->cfg_addr,
-			    (0x80000000 | ((offset & 0xf00) << 16) |
-			     ((bus->number - hose->bus_offset) << 16)
-			     | (devfn << 8) | ((offset & 0xfc) )));
-	} else {
-		PCI_CFG_OUT(hose->cfg_addr,
-			    (0x80000001 | ((offset & 0xf00) << 16) |
-			     ((bus->number - hose->bus_offset) << 16)
-			     | (devfn << 8) | ((offset & 0xfc) )));
-	}
-
-	/*
-	 * Note: the caller has already checked that offset is
-	 * suitably aligned and that len is 1, 2 or 4.
-	 */
-	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
-	cfg_data = hose->cfg_data;
-	PCIE_FIX;
-	temp = in_le32(cfg_data);
-	switch (len) {
-	case 1:
-		*val = (temp >> (((offset & 3))*8)) & 0xff;
-		break;
-	case 2:
-		*val = (temp >> (((offset & 3))*8)) & 0xffff;
-		break;
-	default:
-		*val = temp;
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
-		      int len, u32 val)
-{
-	struct pci_controller *hose = bus->sysdata;
-	volatile void __iomem *cfg_data;
-	u32 temp;
-
-	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/* Possible artifact of CDCpp50937 needs further investigation */
-	if (devfn != 0x0 && bus->number == 0xff)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	PCIE_FIX;
-	if (bus->number == 0xff) {
-		PCI_CFG_OUT(hose->cfg_addr,
-			    (0x80000000 | ((offset & 0xf00) << 16) |
-			     ((bus->number - hose->bus_offset) << 16)
-			     | (devfn << 8) | ((offset & 0xfc) )));
-	} else {
-		PCI_CFG_OUT(hose->cfg_addr,
-			    (0x80000001 | ((offset & 0xf00) << 16) |
-			     ((bus->number - hose->bus_offset) << 16)
-			     | (devfn << 8) | ((offset & 0xfc) )));
-        }
-
-	/*
-	 * Note: the caller has already checked that offset is
-	 * suitably aligned and that len is 1, 2 or 4.
-	 */
-	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
-	cfg_data = hose->cfg_data;
-	switch (len) {
-	case 1:
-		PCIE_FIX;
-		temp = in_le32(cfg_data);
-		temp = (temp & ~(0xff << ((offset & 3) * 8))) |
-			(val << ((offset & 3) * 8));
-		PCIE_FIX;
-		out_le32(cfg_data, temp);
-		break;
-	case 2:
-		PCIE_FIX;
-		temp = in_le32(cfg_data);
-		temp = (temp & ~(0xffff << ((offset & 3) * 8)));
-		temp |= (val << ((offset & 3) * 8)) ;
-		PCIE_FIX;
-		out_le32(cfg_data, temp);
-		break;
-	default:
-		PCIE_FIX;
-		out_le32(cfg_data, val);
-		break;
-	}
-	PCIE_FIX;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops indirect_pcie_ops = {
-	indirect_read_config_pcie,
-	indirect_write_config_pcie
-};
-
-void __init
-setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
-	void __iomem * cfg_data)
-{
-	hose->cfg_addr = cfg_addr;
-	hose->cfg_data = cfg_data;
-	hose->ops = &indirect_pcie_ops;
-}
-
-void __init
-setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
-{
-	unsigned long base = cfg_addr & PAGE_MASK;
-	void __iomem *mbase, *addr, *data;
-
-	mbase = ioremap(base, PAGE_SIZE);
-	addr = mbase + (cfg_addr & ~PAGE_MASK);
-	if ((cfg_data & PAGE_MASK) != base)
-		mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
-	data = mbase + (cfg_data & ~PAGE_MASK);
-	setup_indirect_pcie_nomap(hose, addr, data);
-}
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index cad1757..c0ddc80 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -1028,6 +1028,19 @@
 
 arch_initcall(fs_enet_of_init);
 
+static int __init fsl_pcmcia_of_init(void)
+{
+	struct device_node *np = NULL;
+	/*
+	 * Register all the devices which type is "pcmcia"
+	 */
+	while ((np = of_find_compatible_node(np,
+			"pcmcia", "fsl,pq-pcmcia")) != NULL)
+			    of_platform_device_create(np, "m8xx-pcmcia", NULL);
+	return 0;
+}
+
+arch_initcall(fsl_pcmcia_of_init);
 
 static const char *smc_regs = "regs";
 static const char *smc_pram = "pram";
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index e714884..c7e6e85 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -33,18 +33,27 @@
 	struct pci_controller *hose = bus->sysdata;
 	volatile void __iomem *cfg_data;
 	u8 cfg_type = 0;
+	u32 bus_no, reg;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 	
-	if (hose->set_cfg_type)
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
 		if (bus->number != hose->first_busno)
 			cfg_type = 1;
 
-	PCI_CFG_OUT(hose->cfg_addr, 					 
-		 (0x80000000 | ((bus->number - hose->bus_offset) << 16)
-		  | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+	bus_no = (bus->number == hose->first_busno) ?
+			hose->self_busno : bus->number;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
+		reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+	else
+		reg = offset & 0xfc;
+
+	PCI_CFG_OUT(hose->cfg_addr,
+		 (0x80000000 | (bus_no << 16)
+		  | (devfn << 8) | reg | cfg_type));
 
 	/*
 	 * Note: the caller has already checked that offset is
@@ -72,18 +81,33 @@
 	struct pci_controller *hose = bus->sysdata;
 	volatile void __iomem *cfg_data;
 	u8 cfg_type = 0;
+	u32 bus_no, reg;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
-	if (hose->set_cfg_type)
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
 		if (bus->number != hose->first_busno)
 			cfg_type = 1;
 
-	PCI_CFG_OUT(hose->cfg_addr, 					 
-		 (0x80000000 | ((bus->number - hose->bus_offset) << 16)
-		  | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+	bus_no = (bus->number == hose->first_busno) ?
+			hose->self_busno : bus->number;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
+		reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+	else
+		reg = offset & 0xfc;
+
+	PCI_CFG_OUT(hose->cfg_addr,
+		 (0x80000000 | (bus_no << 16)
+		  | (devfn << 8) | reg | cfg_type));
+
+	/* surpress setting of PCI_PRIMARY_BUS */
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
+		if ((offset == PCI_PRIMARY_BUS) &&
+			(bus->number == hose->first_busno))
+		val &= 0xffffff00;
 
 	/*
 	 * Note: the caller has already checked that offset is
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h
index afa2ee6..9fe00ee 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.h
+++ b/arch/powerpc/sysdev/mpc8xx_pic.h
@@ -4,9 +4,16 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-extern struct hw_interrupt_type mpc8xx_pic;
-
 int mpc8xx_pic_init(void);
 unsigned int mpc8xx_get_irq(void);
 
+/*
+ * Some internal interrupt registers use an 8-bit mask for the interrupt
+ * level instead of a number.
+ */
+static inline uint mk_int_int_mask(uint mask)
+{
+	return (1 << (7 - (mask/2)));
+}
+
 #endif /* _PPC_KERNEL_PPC8xx_H */
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 4b0a9c8..b618fa6 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -12,6 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/console.h>
 #include <linux/mv643xx.h>
 #include <linux/platform_device.h>
 
@@ -420,3 +421,30 @@
 	return err;
 }
 arch_initcall(mv64x60_device_setup);
+
+static int __init mv64x60_add_mpsc_console(void)
+{
+	struct device_node *np = NULL;
+	const char *prop;
+
+	prop = of_get_property(of_chosen, "linux,stdout-path", NULL);
+	if (prop == NULL)
+		goto not_mpsc;
+
+	np = of_find_node_by_path(prop);
+	if (!np)
+		goto not_mpsc;
+
+	if (!of_device_is_compatible(np, "marvell,mpsc"))
+		goto not_mpsc;
+
+	prop = of_get_property(np, "block-index", NULL);
+	if (!prop)
+		goto not_mpsc;
+
+	add_preferred_console("ttyMM", *(int *)prop, NULL);
+
+not_mpsc:
+	return 0;
+}
+console_initcall(mv64x60_add_mpsc_console);
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c
index b5aef4c..45db86c 100644
--- a/arch/powerpc/sysdev/mv64x60_pci.c
+++ b/arch/powerpc/sysdev/mv64x60_pci.c
@@ -137,18 +137,15 @@
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 		       " bus 0\n", dev->full_name);
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
 
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
-
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
 	setup_indirect_pci(hose, rsrc.start, rsrc.start + 4);
-	hose->bus_offset = hose->first_busno;
+	hose->self_busno = hose->first_busno;
 
 	printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. "
 	       "Firmware bus number: %d->%d\n",
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index 887739f..f611d34 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -5,15 +5,13 @@
 config UCC_SLOW
 	bool
 	default n
-	select UCC
 	help
 	  This option provides qe_lib support to UCC slow
 	  protocols: UART, BISYNC, QMC
 
 config UCC_FAST
 	bool
-	default n
-	select UCC
+	default y if UCC_GETH
 	help
 	  This option provides qe_lib support to UCC fast
 	  protocols: HDLC, Ethernet, ATM, transparent
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index ac12a44..f970e54 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -18,6 +18,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/stddef.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -40,6 +41,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
 
 int ucc_set_type(int ucc_num, struct ucc_common *regs,
 		 enum ucc_speed_type speed)
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index 9143236..3df202e 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -19,6 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
@@ -70,6 +71,7 @@
 	printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x",
 		  (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
 }
+EXPORT_SYMBOL(ucc_fast_dump_regs);
 
 u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
 {
@@ -85,11 +87,13 @@
 	default: return QE_CR_SUBBLOCK_INVALID;
 	}
 }
+EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock);
 
 void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
 {
 	out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
 }
+EXPORT_SYMBOL(ucc_fast_transmit_on_demand);
 
 void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
 {
@@ -110,6 +114,7 @@
 	}
 	out_be32(&uf_regs->gumr, gumr);
 }
+EXPORT_SYMBOL(ucc_fast_enable);
 
 void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
 {
@@ -130,6 +135,7 @@
 	}
 	out_be32(&uf_regs->gumr, gumr);
 }
+EXPORT_SYMBOL(ucc_fast_disable);
 
 int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
 {
@@ -341,6 +347,7 @@
 	*uccf_ret = uccf;
 	return 0;
 }
+EXPORT_SYMBOL(ucc_fast_init);
 
 void ucc_fast_free(struct ucc_fast_private * uccf)
 {
@@ -355,3 +362,4 @@
 
 	kfree(uccf);
 }
+EXPORT_SYMBOL(ucc_fast_free);
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
new file mode 100644
index 0000000..e276048
--- /dev/null
+++ b/arch/powerpc/sysdev/rtc_cmos_setup.c
@@ -0,0 +1,49 @@
+/*
+ * Setup code for PC-style Real-Time Clock.
+ *
+ * Author: Wade Farnsworth <wfarnsworth@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/prom.h>
+
+static int  __init add_rtc(void)
+{
+	struct device_node *np;
+	struct platform_device *pd;
+	struct resource res;
+	int ret;
+
+	np = of_find_compatible_node(NULL, NULL, "pnpPNP,b00");
+	if (!np)
+		return -ENODEV;
+
+	ret = of_address_to_resource(np, 0, &res);
+	of_node_put(np);
+	if (ret)
+		return ret;
+
+	/*
+	 * RTC_PORT(x) is hardcoded in asm/mc146818rtc.h.  Verify that the
+	 * address provided by the device node matches.
+	 */
+	if (res.start != RTC_PORT(0))
+		return -EINVAL;
+
+	pd = platform_device_register_simple("rtc_cmos", -1,
+					     &res, 1);
+	if (IS_ERR(pd))
+		return PTR_ERR(pd);
+
+	return 0;
+}
+fs_initcall(add_rtc);
diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c
index 4a01748..e81e7ec 100644
--- a/arch/powerpc/sysdev/timer.c
+++ b/arch/powerpc/sysdev/timer.c
@@ -24,7 +24,12 @@
 
 	/* get current RTC time and convert to seconds */
 	get_rtc_time(&cur_rtc_tm);
-	rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time);
+	cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900,
+			      cur_rtc_tm.tm_mon + 1,
+			      cur_rtc_tm.tm_mday,
+			      cur_rtc_tm.tm_hour,
+			      cur_rtc_tm.tm_min,
+			      cur_rtc_tm.tm_sec);
 
 	diff = cur_rtc_time - suspend_rtc_time;
 
@@ -44,7 +49,12 @@
 	WARN_ON(!ppc_md.get_rtc_time);
 
 	get_rtc_time(&suspend_rtc_tm);
-	rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time);
+	suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900,
+				  suspend_rtc_tm.tm_mon + 1,
+				  suspend_rtc_tm.tm_mday,
+				  suspend_rtc_tm.tm_hour,
+				  suspend_rtc_tm.tm_min,
+				  suspend_rtc_tm.tm_sec);
 
 	return 0;
 }
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index 7d3b09b..a113d80 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -72,12 +72,11 @@
 	int ret;
 
 	for (np = NULL, i = 0;
-	     (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL;
+	     (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL;
 	     i++) {
 		struct resource r[2];
-		struct device_node *phy;
+		struct device_node *phy, *mdio;
 		hw_info tsi_eth_data;
-		const unsigned int *id;
 		const unsigned int *phy_id;
 		const void *mac_addr;
 		const phandle *ph;
@@ -111,6 +110,13 @@
 		if (mac_addr)
 			memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
 
+		ph = of_get_property(np, "mdio-handle", NULL);
+		mdio = of_find_node_by_phandle(*ph);
+		ret = of_address_to_resource(mdio, 0, &res);
+		of_node_put(mdio);
+		if (ret)
+			goto unreg;
+
 		ph = of_get_property(np, "phy-handle", NULL);
 		phy = of_find_node_by_phandle(*ph);
 
@@ -119,20 +125,25 @@
 			goto unreg;
 		}
 
-		id = of_get_property(phy, "reg", NULL);
-		phy_id = of_get_property(phy, "phy-id", NULL);
-		ret = of_address_to_resource(phy, 0, &res);
-		if (ret) {
-			of_node_put(phy);
-			goto unreg;
-		}
+		phy_id = of_get_property(phy, "reg", NULL);
+
 		tsi_eth_data.regs = r[0].start;
 		tsi_eth_data.phyregs = res.start;
 		tsi_eth_data.phy = *phy_id;
 		tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
-		if (of_device_is_compatible(phy, "bcm54xx"))
+
+		/* Some boards with the TSI108 bridge (e.g. Holly)
+		 * have a miswiring of the ethernet PHYs which
+		 * requires a workaround.  The special
+		 * "txc-rxc-delay-disable" property enables this
+		 * workaround.  FIXME: Need to port the tsi108_eth
+		 * driver itself to phylib and use a non-misleading
+		 * name for the workaround flag - it's not actually to
+		 * do with the model of PHY in use */
+		if (of_get_property(phy, "txc-rxc-delay-disable", NULL))
 			tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
 		of_node_put(phy);
+
 		ret =
 		    platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
 					     sizeof(hw_info));
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 2153163..90db8a7 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -64,9 +64,10 @@
 			   int offset, int len, u32 val)
 {
 	volatile unsigned char *cfg_addr;
+	struct pci_controller *hose = bus->sysdata;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfunc))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfunc))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
 	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
@@ -149,10 +150,11 @@
 			  int len, u32 * val)
 {
 	volatile unsigned char *cfg_addr;
+	struct pci_controller *hose = bus->sysdata;
 	u32 temp;
 
 	if (ppc_md.pci_exclude_device)
-		if (ppc_md.pci_exclude_device(bus->number, devfn))
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
 	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
@@ -219,14 +221,12 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	hose = pcibios_alloc_controller();
+	hose = pcibios_alloc_controller(dev);
 
 	if (!hose) {
 		printk("PCI Host bridge init failed\n");
 		return -ENOMEM;
 	}
-	hose->arch_data = dev;
-	hose->set_cfg_type = 1;
 
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 28fdf4f..669e656 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2634,7 +2634,7 @@
 __initcall(setup_xmon_sysrq);
 #endif /* CONFIG_MAGIC_SYSRQ */
 
-int __initdata xmon_early, xmon_off;
+static int __initdata xmon_early, xmon_off;
 
 static int __init early_parse_xmon(char *p)
 {
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index 4c0a7d7..615b658 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -477,9 +477,9 @@
 		}
 		else {
 			skb_put(skb,pkt_len-4);	/* Make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len-4, 0);
+				pkt_len-4);
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
 		}
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index cab395d..6f3ed6a 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -734,9 +734,9 @@
 		}
 		else {
 			skb_put(skb,pkt_len);	/* Make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len, 0);
+				pkt_len);
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
 		}
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index e58288e..703d47e 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -506,9 +506,9 @@
 		}
 		else {
 			skb_put(skb,pkt_len-4);	/* Make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 				cep->rx_vaddr[bdp - cep->rx_bd_base],
-				pkt_len-4, 0);
+				pkt_len-4);
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
 		}
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
index d38335d..0288279 100644
--- a/arch/ppc/8xx_io/fec.c
+++ b/arch/ppc/8xx_io/fec.c
@@ -725,7 +725,7 @@
 		fep->stats.rx_dropped++;
 	} else {
 		skb_put(skb,pkt_len-4);	/* Make room */
-		eth_copy_and_sum(skb, data, pkt_len-4, 0);
+		skb_copy_to_linear_data(skb, data, pkt_len-4);
 		skb->protocol=eth_type_trans(skb,dev);
 		netif_rx(skb);
 	}
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index ccce2a4..6bdeeb7 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -1237,8 +1237,10 @@
 	  infrastructure code to support PCI bus devices.
 
 config PCI_DOMAINS
-	bool
-	default PCI
+	def_bool PCI
+
+config PCI_SYSCALL
+	def_bool PCI
 
 config MPC83xx_PCI2
 	bool "Support for 2nd PCI host controller"
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index ab64256..fba7ca1 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -596,7 +596,11 @@
 	mr	r12,r4		/* restart at exc_exit_restart */
 	b	2b
 
-	.comm	fee_restarts,4
+	.section .bss
+	.align	2
+fee_restarts:
+	.space	4
+	.previous
 
 /* aargh, a nonrecoverable interrupt, panic */
 /* aargh, we don't know which trap this is */
@@ -851,7 +855,11 @@
 	mtspr	SPRN_DBSR,r11	/* clear all pending debug events */
 	blr
 
-	.comm	global_dbcr0,8
+	.section .bss
+	.align	4
+global_dbcr0:
+	.space	8
+	.previous
 #endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
 
 do_work:			/* r10 contains MSR_KERNEL here */
@@ -926,4 +934,8 @@
 	/* shouldn't return */
 	b	4b
 
-	.comm	ee_restarts,4
+	.section .bss
+	.align	2
+ee_restarts:
+	.space	4
+	.previous
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index d319f9b..0da55368 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -328,7 +328,7 @@
 	mtspr   SPRN_L1CSR0,r3
 	isync
 	blr
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
 	mfspr	r3,SPRN_L1CSR1
 	ori	r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
 	mtspr	SPRN_L1CSR1,r3
@@ -355,7 +355,7 @@
 _GLOBAL(__flush_icache_range)
 BEGIN_FTR_SECTION
 	blr				/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	li	r5,L1_CACHE_BYTES-1
 	andc	r3,r3,r5
 	subf	r4,r3,r4
@@ -472,7 +472,7 @@
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
 	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	rlwinm	r3,r3,0,0,19			/* Get page base address */
 	li	r4,4096/L1_CACHE_BYTES	/* Number of lines in a page */
 	mtctr	r4
@@ -500,7 +500,7 @@
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
 	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 	mfmsr	r10
 	rlwinm	r0,r10,0,28,26			/* clear DR */
 	mtmsr	r0
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 5e723c4..c2ec13b 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -633,12 +633,6 @@
 {
 }
 
-/* Add sysfs properties */
-void pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-}
-
-
 static int __init
 pcibios_init(void)
 {
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 4ad4996..63f0a98 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -40,7 +40,6 @@
 #include <asm/time.h>
 #include <asm/cputable.h>
 #include <asm/btext.h>
-#include <asm/div64.h>
 #include <asm/xmon.h>
 #include <asm/signal.h>
 #include <asm/dcr.h>
@@ -65,7 +64,6 @@
 
 EXPORT_SYMBOL(clear_pages);
 EXPORT_SYMBOL(clear_user_page);
-EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(transfer_to_handler);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(machine_check_exception);
@@ -93,7 +91,6 @@
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(__div64_32);
 
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index c79704f..967c1ef 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -526,7 +526,7 @@
 	 * Systems with OF can look in the properties on the cpu node(s)
 	 * for a possibly more accurate value.
 	 */
-	if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
+	if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) {
 		dcache_bsize = cur_cpu_spec->dcache_bsize;
 		icache_bsize = cur_cpu_spec->icache_bsize;
 		ucache_bsize = 0;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index aea100b..3f3b292 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -92,6 +92,7 @@
 	if (nl)
 		printk("\n");
 	show_regs(fp);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 	/* do_exit() should take care of panic'ing from an interrupt
 	 * context so we don't handle it here
@@ -619,7 +620,7 @@
 			return;
 
 		if (!(regs->msr & MSR_PR) &&  /* not user-mode */
-		    report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
+		    report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
 			regs->nip += 4;
 			return;
 		}
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 44cd128..19db874 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -32,7 +32,7 @@
   .text      :
   {
     _text = .;
-    *(.text)
+    TEXT_TEXT
     SCHED_TEXT
     LOCK_TEXT
     *(.fixup)
@@ -67,7 +67,7 @@
   . = ALIGN(4096);
   .data    :
   {
-    *(.data)
+    DATA_DATA
     *(.data1)
     *(.sdata)
     *(.sdata2)
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
index e756942..5f364dc 100644
--- a/arch/ppc/mm/hashtable.S
+++ b/arch/ppc/mm/hashtable.S
@@ -30,7 +30,11 @@
 #include <asm/asm-offsets.h>
 
 #ifdef CONFIG_SMP
-	.comm	mmu_hash_lock,4
+	.section .bss
+	.align	2
+	.globl mmu_hash_lock
+mmu_hash_lock:
+	.space	4
 #endif /* CONFIG_SMP */
 
 /*
@@ -461,9 +465,17 @@
 	sync		/* make sure pte updates get to memory */
 	blr
 
-	.comm	next_slot,4
-	.comm	primary_pteg_full,4
-	.comm	htab_hash_searches,4
+	.section .bss
+	.align	2
+next_slot:
+	.space	4
+	.globl primary_pteg_full
+primary_pteg_full:
+	.space	4
+	.globl htab_hash_searches
+htab_hash_searches:
+	.space	4
+	.previous
 
 /*
  * Flush the entry for a particular page from the hash table.
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index c023b72..35ebb63 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -92,7 +92,7 @@
 	free_pages((unsigned long)pgd, PGDIR_ORDER);
 }
 
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
 	pte_t *pte;
 	extern int mem_init_done;
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
index fa29740..4ff260b 100644
--- a/arch/ppc/mm/tlb.c
+++ b/arch/ppc/mm/tlb.c
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/pagemap.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 6f21110..3c56654 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -69,9 +69,6 @@
 
 TODC_ALLOC();
 
-unsigned char ucBoardRev;
-unsigned char ucBoardRevMaj, ucBoardRevMin;
-
 extern unsigned char prep_nvram_read_val(int addr);
 extern void prep_nvram_write_val(int addr,
 				 unsigned char val);
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 95694159..543795b 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -7,6 +7,7 @@
 
 wdt-mpc8xx-$(CONFIG_8xx_WDT)	+= m8xx_wdt.o
 
+obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPCBUG_NVRAM)	+= prep_nvram.o
 obj-$(CONFIG_PPC_OCP)		+= ocp.o
 obj-$(CONFIG_IBM_OCP)		+= ibm_ocp.o
diff --git a/arch/ppc/syslib/ibm_ocp.c b/arch/ppc/syslib/ibm_ocp.c
index 3f6e55c..2ee1766 100644
--- a/arch/ppc/syslib/ibm_ocp.c
+++ b/arch/ppc/syslib/ibm_ocp.c
@@ -1,4 +1,5 @@
 #include <linux/module.h>
+#include <asm/ibm4xx.h>
 #include <asm/ocp.h>
 
 struct ocp_sys_info_data ocp_sys_info = {
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
new file mode 100644
index 0000000..83b323a
--- /dev/null
+++ b/arch/ppc/syslib/indirect_pci.c
@@ -0,0 +1,134 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#ifdef CONFIG_PPC_INDIRECT_PCI_BE
+#define PCI_CFG_OUT out_be32
+#else
+#define PCI_CFG_OUT out_le32
+#endif
+
+static int
+indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		     int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile void __iomem *cfg_data;
+	u8 cfg_type = 0;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (hose->set_cfg_type)
+		if (bus->number != hose->first_busno)
+			cfg_type = 1;
+
+	PCI_CFG_OUT(hose->cfg_addr,
+		 (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+		  | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + (offset & 3);
+	switch (len) {
+	case 1:
+		*val = in_8(cfg_data);
+		break;
+	case 2:
+		*val = in_le16(cfg_data);
+		break;
+	default:
+		*val = in_le32(cfg_data);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		      int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile void __iomem *cfg_data;
+	u8 cfg_type = 0;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (hose->set_cfg_type)
+		if (bus->number != hose->first_busno)
+			cfg_type = 1;
+
+	PCI_CFG_OUT(hose->cfg_addr,
+		 (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+		  | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + (offset & 3);
+	switch (len) {
+	case 1:
+		out_8(cfg_data, val);
+		break;
+	case 2:
+		out_le16(cfg_data, val);
+		break;
+	default:
+		out_le32(cfg_data, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pci_ops =
+{
+	indirect_read_config,
+	indirect_write_config
+};
+
+void __init
+setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+	void __iomem * cfg_data)
+{
+	hose->cfg_addr = cfg_addr;
+	hose->cfg_data = cfg_data;
+	hose->ops = &indirect_pci_ops;
+}
+
+void __init
+setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+	unsigned long base = cfg_addr & PAGE_MASK;
+	void __iomem *mbase, *addr, *data;
+
+	mbase = ioremap(base, PAGE_SIZE);
+	addr = mbase + (cfg_addr & ~PAGE_MASK);
+	if ((cfg_data & PAGE_MASK) != base)
+		mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+	data = mbase + (cfg_data & ~PAGE_MASK);
+	setup_indirect_pci_nomap(hose, addr, data);
+}
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
index 8485a68..032f4b7 100644
--- a/arch/ppc/syslib/mv64x60.c
+++ b/arch/ppc/syslib/mv64x60.c
@@ -2415,7 +2415,6 @@
 	.attr = {
 		.name = "hs_reg",
 		.mode = S_IRUGO | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size  = VAL_LEN_MAX,
 	.read  = mv64xxx_hs_reg_read,
diff --git a/arch/ppc/syslib/qspan_pci.c b/arch/ppc/syslib/qspan_pci.c
index 85053b2..7a97c74 100644
--- a/arch/ppc/syslib/qspan_pci.c
+++ b/arch/ppc/syslib/qspan_pci.c
@@ -365,13 +365,13 @@
 }
 
 void __init
-m8xx_pcibios_fixup(void))
+m8xx_pcibios_fixup(void)
 {
    /* Lots to do here, all board and configuration specific. */
 }
 
 void __init
-m8xx_setup_pci_ptrs(void))
+m8xx_setup_pci_ptrs(void)
 {
 	set_config_access_method(qspan);
 
diff --git a/arch/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c
index 1654678..ace4ec0 100644
--- a/arch/ppc/syslib/virtex_devices.c
+++ b/arch/ppc/syslib/virtex_devices.c
@@ -71,6 +71,21 @@
 	}, \
 }
 
+/*
+ * ML300/ML403 Video Device: shortcut macro for single instance
+ */
+#define XPAR_TFT(num) { \
+	.name = "xilinxfb", \
+	.id = num, \
+	.num_resources = 1, \
+	.resource = (struct resource[]) { \
+		{ \
+			.start = XPAR_TFT_##num##_BASEADDR, \
+			.end = XPAR_TFT_##num##_BASEADDR+7, \
+			.flags = IORESOURCE_IO, \
+		}, \
+	}, \
+}
 
 /* UART 8250 driver platform data table */
 struct plat_serial8250_port virtex_serial_platform_data[] = {
@@ -146,20 +161,17 @@
 	XPAR_SYSACE(1),
 #endif
 
-	/* ML300/403 reference design framebuffer */
 #if defined(XPAR_TFT_0_BASEADDR)
-	{
-		.name		= "xilinxfb",
-		.id		= 0,
-		.num_resources	= 1,
-		.resource = (struct resource[]) {
-			{
-				.start	= XPAR_TFT_0_BASEADDR,
-				.end	= XPAR_TFT_0_BASEADDR+7,
-				.flags	= IORESOURCE_IO,
-			},
-		},
-	},
+	XPAR_TFT(0),
+#endif
+#if defined(XPAR_TFT_1_BASEADDR)
+	XPAR_TFT(1),
+#endif
+#if defined(XPAR_TFT_2_BASEADDR)
+	XPAR_TFT(2),
+#endif
+#if defined(XPAR_TFT_3_BASEADDR)
+	XPAR_TFT(3),
 #endif
 };
 
diff --git a/arch/ppc/syslib/virtex_devices.h b/arch/ppc/syslib/virtex_devices.h
index 3d4be14..9f38d92 100644
--- a/arch/ppc/syslib/virtex_devices.h
+++ b/arch/ppc/syslib/virtex_devices.h
@@ -31,4 +31,11 @@
  */
 int virtex_device_fixup(struct platform_device *dev);
 
+/* SPI Controller IP */
+struct xspi_platform_data {
+	s16 bus_num;
+	u16 num_chipselect;
+	u32 speed_hz;
+};
+
 #endif  /* __ASM_VIRTEX_DEVICES_H__ */
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 68441e0..143ed8e 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -19,7 +19,7 @@
 AFLAGS		+= -m31
 UTS_MACHINE	:= s390
 STACK_SIZE	:= 8192
-CHECKFLAGS	+= -D__s390__
+CHECKFLAGS	+= -D__s390__ -msize-long
 else
 LDFLAGS		:= -m elf64_s390
 MODFLAGS	+= -fpic -D__PIC__
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 81a2b92..6ffbab7 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -535,8 +535,7 @@
 
 /******************************* init / exit *********************************/
 
-static void
-appldata_online_cpu(int cpu)
+static void __cpuinit appldata_online_cpu(int cpu)
 {
 	init_virt_timer(&per_cpu(appldata_timer, cpu));
 	per_cpu(appldata_timer, cpu).function = appldata_timer_function;
@@ -580,7 +579,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block appldata_nb = {
+static struct notifier_block __cpuinitdata appldata_nb = {
 	.notifier_call = appldata_cpu_notify,
 };
 
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index 2775d261..95f5160 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -24,7 +24,7 @@
 #define CRYPT_S390_PRIORITY 300
 #define CRYPT_S390_COMPOSITE_PRIORITY 400
 
-/* s930 cryptographic operations */
+/* s390 cryptographic operations */
 enum crypt_s390_operations {
 	CRYPT_S390_KM   = 0x0100,
 	CRYPT_S390_KMC  = 0x0200,
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 2782cf9..b9a1ce1 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -481,9 +481,17 @@
 
 /* Diagnose 224 functions */
 
-static void diag224(void *ptr)
+static int diag224(void *ptr)
 {
-	asm volatile("diag %0,%1,0x224" : :"d" (0), "d"(ptr) : "memory");
+	int rc = -ENOTSUPP;
+
+	asm volatile(
+		"	diag	%1,%2,0x224\n"
+		"0:	lhi	%0,0x0\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "+d" (rc) :"d" (0), "d" (ptr) : "memory");
+	return rc;
 }
 
 static int diag224_get_name_table(void)
@@ -492,7 +500,10 @@
 	diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
 	if (!diag224_cpu_names)
 		return -ENOMEM;
-	diag224(diag224_cpu_names);
+	if (diag224(diag224_cpu_names)) {
+		kfree(diag224_cpu_names);
+		return -ENOTSUPP;
+	}
 	EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
 	return 0;
 }
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 32a69a1..acc4154 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1682,3 +1682,31 @@
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct compat_timeval *
 	jg	compat_sys_utimes
+
+	.globl	compat_sys_utimensat_wrapper
+compat_sys_utimensat_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# char *
+	llgtr	%r4,%r4			# struct compat_timespec *
+	lgfr	%r5,%r5			# int
+	jg	compat_sys_utimensat
+
+	.globl	compat_sys_signalfd_wrapper
+compat_sys_signalfd_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# compat_sigset_t *
+	llgfr	%r4,%r4			# compat_size_t
+	jg	compat_sys_signalfd
+
+	.globl	compat_sys_timerfd_wrapper
+compat_sys_timerfd_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	lgfr	%r4,%r4			# int
+	llgtr	%r5,%r5			# struct compat_itimerspec *
+	jg	compat_sys_timerfd
+
+	.globl	sys_eventfd_wrapper
+sys_eventfd_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	jg	sys_eventfd
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index dca6eaf..1b2f5ce 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -163,7 +163,7 @@
 
 static debug_info_t *debug_area_first = NULL;
 static debug_info_t *debug_area_last = NULL;
-static DECLARE_MUTEX(debug_lock);
+static DEFINE_MUTEX(debug_mutex);
 
 static int initialized;
 
@@ -576,7 +576,7 @@
 	int rc = 0;
 	file_private_info_t *p_info;
 
-	down(&debug_lock);
+	mutex_lock(&debug_mutex);
 	p_info = ((file_private_info_t *) file->private_data);
 	if (p_info->view->input_proc)
 		rc = p_info->view->input_proc(p_info->debug_info_org,
@@ -584,7 +584,7 @@
 					      length, offset);
 	else
 		rc = -EPERM;
-	up(&debug_lock);
+	mutex_unlock(&debug_mutex);
 	return rc;		/* number of input characters */
 }
 
@@ -602,7 +602,7 @@
 	file_private_info_t *p_info;
 	debug_info_t *debug_info, *debug_info_snapshot;
 
-	down(&debug_lock);
+	mutex_lock(&debug_mutex);
 	debug_info = file->f_path.dentry->d_inode->i_private;
 	/* find debug view */
 	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
@@ -653,7 +653,7 @@
 	file->private_data = p_info;
 	debug_info_get(debug_info);
 out:
-	up(&debug_lock);
+	mutex_unlock(&debug_mutex);
 	return rc;
 }
 
@@ -688,7 +688,7 @@
 
 	if (!initialized)
 		BUG();
-	down(&debug_lock);
+	mutex_lock(&debug_mutex);
 
         /* create new debug_info */
 
@@ -702,7 +702,7 @@
         if (!rc){
 		printk(KERN_ERR "debug: debug_register failed for %s\n",name);
         }
-	up(&debug_lock);
+	mutex_unlock(&debug_mutex);
 	return rc;
 }
 
@@ -716,9 +716,9 @@
 {
 	if (!id)
 		goto out;
-	down(&debug_lock);
+	mutex_lock(&debug_mutex);
 	debug_info_put(id);
-	up(&debug_lock);
+	mutex_unlock(&debug_mutex);
 
 out:
 	return;
@@ -1054,11 +1054,11 @@
 	int rc = 0;
 
 	s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
-	down(&debug_lock);
+	mutex_lock(&debug_mutex);
 	debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
 	printk(KERN_INFO "debug: Initialization complete\n");
 	initialized = 1;
-	up(&debug_lock);
+	mutex_unlock(&debug_mutex);
 
 	return rc;
 }
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 50538e5..e6289ee 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -171,37 +171,6 @@
 }
 #endif
 
-#define ADDR2G	(1UL << 31)
-
-static noinline __init unsigned long sclp_memory_detect(void)
-{
-	struct sclp_readinfo_sccb *sccb;
-	unsigned long long memsize;
-
-	sccb = &s390_readinfo_sccb;
-
-	if (sccb->header.response_code != 0x10)
-		return 0;
-
-	if (sccb->rnsize)
-		memsize = sccb->rnsize << 20;
-	else
-		memsize = sccb->rnsize2 << 20;
-	if (sccb->rnmax)
-		memsize *= sccb->rnmax;
-	else
-		memsize *= sccb->rnmax2;
-#ifndef CONFIG_64BIT
-	/*
-	 * Can't deal with more than 2G in 31 bit addressing mode, so
-	 * limit the value in order to avoid strange side effects.
-	 */
-	if (memsize > ADDR2G)
-		memsize = ADDR2G;
-#endif
-	return (unsigned long) memsize;
-}
-
 static inline __init unsigned long __tprot(unsigned long addr)
 {
 	int cc = -1;
@@ -218,6 +187,7 @@
 
 /* Checking memory in 128KB increments. */
 #define CHUNK_INCR	(1UL << 17)
+#define ADDR2G		(1UL << 31)
 
 static noinline __init void find_memory_chunks(unsigned long memsize)
 {
@@ -293,7 +263,7 @@
  */
 void __init startup_init(void)
 {
-	unsigned long memsize;
+	unsigned long long memsize;
 
 	ipl_save_parameters();
 	clear_bss_section();
@@ -305,8 +275,17 @@
 	sort_main_extable();
 	setup_lowcore_early();
 	sclp_readinfo_early();
+	sclp_facilities_detect();
 	memsize = sclp_memory_detect();
+#ifndef CONFIG_64BIT
+	/*
+	 * Can't deal with more than 2G in 31 bit addressing mode, so
+	 * limit the value in order to avoid strange side effects.
+	 */
+	if (memsize > ADDR2G)
+		memsize = ADDR2G;
+#endif
 	if (memory_fast_detect() < 0)
-		find_memory_chunks(memsize);
+		find_memory_chunks((unsigned long) memsize);
 	lockdep_on();
 }
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index c8a2212..bc7ff36 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -107,6 +107,11 @@
 	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
 	.endm
 
+	.macro	SAVE_ALL_SVC psworg,savearea
+	la	%r12,\psworg
+	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
+	.endm
+
 	.macro	SAVE_ALL_SYNC psworg,savearea
 	la	%r12,\psworg
 	tm	\psworg+1,0x01		# test problem state bit
@@ -218,7 +223,7 @@
 	STORE_TIMER __LC_SYNC_ENTER_TIMER
 sysc_saveall:
 	SAVE_ALL_BASE __LC_SAVE_AREA
-	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	lh	%r7,0x8a	  # get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -769,10 +774,13 @@
 
 	RESTORE_ALL __LC_RETURN_MCCK_PSW,0
 
-#ifdef CONFIG_SMP
 /*
  * Restart interruption handler, kick starter for additional CPUs
  */
+#ifdef CONFIG_SMP
+#ifndef CONFIG_HOTPLUG_CPU
+	.section .init.text,"ax"
+#endif
 	.globl restart_int_handler
 restart_int_handler:
 	l	%r15,__LC_SAVE_AREA+60	# load ksp
@@ -785,6 +793,9 @@
 	br	%r14			# branch to start_secondary
 restart_addr:
 	.long	start_secondary
+#ifndef CONFIG_HOTPLUG_CPU
+	.previous
+#endif
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 93745fd..2a7b130 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -99,6 +99,11 @@
 	larl	%r13,system_call
 	.endm
 
+	.macro	SAVE_ALL_SVC psworg,savearea
+	la	%r12,\psworg
+	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
+	.endm
+
 	.macro	SAVE_ALL_SYNC psworg,savearea
 	la	%r12,\psworg
 	tm	\psworg+1,0x01		# test problem state bit
@@ -207,7 +212,7 @@
 	STORE_TIMER __LC_SYNC_ENTER_TIMER
 sysc_saveall:
 	SAVE_ALL_BASE __LC_SAVE_AREA
-	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	llgh	%r7,__LC_SVC_INT_CODE	# get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -745,10 +750,13 @@
 #endif
 	lpswe	__LC_RETURN_MCCK_PSW	# back to caller
 
-#ifdef CONFIG_SMP
 /*
  * Restart interruption handler, kick starter for additional CPUs
  */
+#ifdef CONFIG_SMP
+#ifndef CONFIG_HOTPLUG_CPU
+	.section .init.text,"ax"
+#endif
 	.globl restart_int_handler
 restart_int_handler:
 	lg	%r15,__LC_SAVE_AREA+120 # load ksp
@@ -759,6 +767,9 @@
 	lmg	%r6,%r15,__SF_GPRS(%r15) # load registers from clone
 	stosm	__SF_EMPTY(%r15),0x04	# now we can turn dat on
 	jg	start_secondary
+#ifndef CONFIG_HOTPLUG_CPU
+	.previous
+#endif
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 367caf9..8b8f136 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -25,10 +25,6 @@
 
 #define IPL_PARM_BLOCK_VERSION 0
 
-#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
-#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
-#define SCCB_FLAG (s390_readinfo_sccb.flags)
-
 #define IPL_UNKNOWN_STR		"unknown"
 #define IPL_CCW_STR		"ccw"
 #define IPL_FCP_STR		"fcp"
@@ -146,6 +142,8 @@
 
 static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
 
+static struct sclp_ipl_info sclp_ipl_info;
+
 int diag308(unsigned long subcode, void *addr)
 {
 	register unsigned long _addr asm("0") = (unsigned long) addr;
@@ -297,8 +295,8 @@
 static struct subsys_attribute sys_ipl_device_attr =
 	__ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
 
-static ssize_t ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off,
-				  size_t count)
+static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr,
+				  char *buf, loff_t off, size_t count)
 {
 	unsigned int size = IPL_PARMBLOCK_SIZE;
 
@@ -314,14 +312,13 @@
 	.attr = {
 		.name = "binary_parameter",
 		.mode = S_IRUGO,
-		.owner = THIS_MODULE,
 	},
 	.size = PAGE_SIZE,
 	.read = &ipl_parameter_read,
 };
 
-static ssize_t ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off,
-	size_t count)
+static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *attr,
+				 char *buf, loff_t off, size_t count)
 {
 	unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
 	void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
@@ -338,10 +335,9 @@
 	.attr = {
 		.name = "scp_data",
 		.mode = S_IRUGO,
-		.owner = THIS_MODULE,
 	},
 	.size = PAGE_SIZE,
-	.read = &ipl_scp_data_read,
+	.read = ipl_scp_data_read,
 };
 
 /* FCP ipl device attributes */
@@ -375,9 +371,9 @@
 {
 	char loadparm[LOADPARM_LEN + 1] = {};
 
-	if (!SCCB_VALID)
+	if (!sclp_ipl_info.is_valid)
 		return sprintf(page, "#unknown#\n");
-	memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
+	memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
 	EBCASC(loadparm, LOADPARM_LEN);
 	strstrip(loadparm);
 	return sprintf(page, "%s\n", loadparm);
@@ -910,9 +906,9 @@
 	reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
 	reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
 	/* check if read scp info worked and set loadparm */
-	if (SCCB_VALID)
+	if (sclp_ipl_info.is_valid)
 		memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
-		       SCCB_LOADPARM, LOADPARM_LEN);
+		       &sclp_ipl_info.loadparm, LOADPARM_LEN);
 	else
 		/* read scp info failed: set empty loadparm (EBCDIC blanks) */
 		memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
@@ -1007,7 +1003,7 @@
 {
 	int rc;
 
-	if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
+	if (!sclp_ipl_info.has_dump)
 		return 0; /* LDIPL DUMP is not installed */
 	if (!diag308_set_works)
 		return 0;
@@ -1088,6 +1084,7 @@
 {
 	int rc;
 
+	sclp_get_ipl_info(&sclp_ipl_info);
 	reipl_probe();
 	rc = ipl_init();
 	if (rc)
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index e39333a..358d2bb 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -413,7 +413,7 @@
 			break;
 		}
 	}
-	BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
+	kretprobe_assert(ri, orig_ret_address, trampoline_address);
 	regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE;
 
 	reset_current_kprobe();
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index eb43c3b..441975b 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -93,8 +93,8 @@
 	/* disable monitor call class 0 */
 	__ctl_clear_bit(8, 15);
 
-	atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
-			    (void *)(long) smp_processor_id());
+	atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+				   (void *)(long) smp_processor_id());
 }
 
 extern void s390_handle_mcck(void);
@@ -115,7 +115,7 @@
 	}
 
 	rc = atomic_notifier_call_chain(&idle_chain,
-			CPU_IDLE, (void *)(long) cpu);
+					S390_CPU_IDLE, (void *)(long) cpu);
 	if (rc != NOTIFY_OK && rc != NOTIFY_DONE)
 		BUG();
 	if (rc != NOTIFY_OK) {
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 2a8f087..f4503ca 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -294,7 +294,6 @@
 static int
 do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long tmp;
 	ptrace_area parea; 
 	int copied, ret;
 
@@ -304,10 +303,7 @@
 		/* Remove high order bit from address (only for 31 bit). */
 		addr &= PSW_ADDR_INSN;
 		/* read word at location addr. */
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (copied != sizeof(tmp))
-			return -EIO;
-		return put_user(tmp, (unsigned long __force __user *) data);
+		return generic_ptrace_peekdata(child, addr, data);
 
 	case PTRACE_PEEKUSR:
 		/* read the word at location addr in the USER area. */
@@ -318,10 +314,7 @@
 		/* Remove high order bit from address (only for 31 bit). */
 		addr &= PSW_ADDR_INSN;
 		/* write the word at location addr. */
-		copied = access_process_vm(child, addr, &data, sizeof(data),1);
-		if (copied != sizeof(data))
-			return -EIO;
-		return 0;
+		return generic_ptrace_pokedata(child, addr, data);
 
 	case PTRACE_POKEUSR:
 		/* write the word at location addr in the USER area */
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 6bfb088..7e1bfb9 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -102,7 +102,7 @@
 /*
  * cpu_init() initializes state that is per-CPU.
  */
-void __devinit cpu_init (void)
+void __cpuinit cpu_init(void)
 {
         int addr = hard_smp_processor_id();
 
@@ -300,6 +300,7 @@
 	else
 		sprintf(str, "cio_ignore=all,!0.0.%04x",
 			ipl_info.data.fcp.dev_id.devno);
+	strcat(COMMAND_LINE, " ");
 	strcat(COMMAND_LINE, str);
 	console_loglevel = 2;
 }
@@ -915,7 +916,7 @@
 	setup_zfcpdump(console_devno);
 }
 
-void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
 {
    printk("cpu %d "
 #ifdef CONFIG_SMP
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 09f028a..182c085a 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -410,58 +410,40 @@
 unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \
 	__attribute__((__section__(".data")));
 
-static void __init smp_get_save_areas(void)
+static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
 {
-	unsigned int cpu, cpu_num, rc;
-	__u16 boot_cpu_addr;
-
 	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
 		return;
-	boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
-	cpu_num = 1;
-	for (cpu = 0; cpu <= 65535; cpu++) {
-		if ((u16) cpu == boot_cpu_addr)
-			continue;
-		__cpu_logical_map[1] = (__u16) cpu;
-		if (signal_processor(1, sigp_sense) == sigp_not_operational)
-			continue;
-		if (cpu_num >= NR_CPUS) {
-			printk("WARNING: Registers for cpu %i are not "
-			       "saved, since dump kernel was compiled with"
-			       "NR_CPUS=%i!\n", cpu_num, NR_CPUS);
-			continue;
-		}
-		zfcpdump_save_areas[cpu_num] =
-			alloc_bootmem(sizeof(union save_area));
-		while (1) {
-			rc = signal_processor(1, sigp_stop_and_store_status);
-			if (rc != sigp_busy)
-				break;
-			cpu_relax();
-		}
-		memcpy(zfcpdump_save_areas[cpu_num],
-		       (void *)(unsigned long) store_prefix() +
-		       SAVE_AREA_BASE, SAVE_AREA_SIZE);
-#ifdef __s390x__
-		/* copy original prefix register */
-		zfcpdump_save_areas[cpu_num]->s390x.pref_reg =
-			zfcpdump_prefix_array[cpu_num];
-#endif
-		cpu_num++;
+	if (cpu >= NR_CPUS) {
+		printk(KERN_WARNING "Registers for cpu %i not saved since dump "
+		       "kernel was compiled with NR_CPUS=%i\n", cpu, NR_CPUS);
+		return;
 	}
+	zfcpdump_save_areas[cpu] = alloc_bootmem(sizeof(union save_area));
+	__cpu_logical_map[1] = (__u16) phy_cpu;
+	while (signal_processor(1, sigp_stop_and_store_status) == sigp_busy)
+		cpu_relax();
+	memcpy(zfcpdump_save_areas[cpu],
+	       (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
+	       SAVE_AREA_SIZE);
+#ifdef CONFIG_64BIT
+	/* copy original prefix register */
+	zfcpdump_save_areas[cpu]->s390x.pref_reg = zfcpdump_prefix_array[cpu];
+#endif
 }
 
 union save_area *zfcpdump_save_areas[NR_CPUS + 1];
 EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
 
 #else
-#define smp_get_save_areas() do { } while (0)
-#endif
+
+static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
+
+#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */
 
 /*
  * Lets check how many CPUs we have.
  */
-
 static unsigned int __init smp_count_cpus(void)
 {
 	unsigned int cpu, num_cpus;
@@ -470,7 +452,6 @@
 	/*
 	 * cpu 0 is the boot cpu. See smp_prepare_boot_cpu.
 	 */
-
 	boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
 	current_thread_info()->cpu = 0;
 	num_cpus = 1;
@@ -480,19 +461,18 @@
 		__cpu_logical_map[1] = (__u16) cpu;
 		if (signal_processor(1, sigp_sense) == sigp_not_operational)
 			continue;
+		smp_get_save_area(num_cpus, cpu);
 		num_cpus++;
 	}
-
 	printk("Detected %d CPU's\n", (int) num_cpus);
 	printk("Boot cpu address %2X\n", boot_cpu_addr);
-
 	return num_cpus;
 }
 
 /*
  *	Activate a secondary processor.
  */
-int __devinit start_secondary(void *cpuvoid)
+int __cpuinit start_secondary(void *cpuvoid)
 {
 	/* Setup the cpu */
 	cpu_init();
@@ -606,7 +586,6 @@
 {
 	unsigned int phy_cpus, pos_cpus, cpu;
 
-	smp_get_save_areas();
 	phy_cpus = smp_count_cpus();
 	pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS);
 
@@ -741,7 +720,7 @@
 			smp_create_idle(cpu);
 }
 
-void __devinit smp_prepare_boot_cpu(void)
+void __init smp_prepare_boot_cpu(void)
 {
 	BUG_ON(smp_processor_id() != 0);
 
@@ -750,7 +729,7 @@
 	current_set[0] = current;
 }
 
-void smp_cpus_done(unsigned int max_cpus)
+void __init smp_cpus_done(unsigned int max_cpus)
 {
 	cpu_present_map = cpu_possible_map;
 }
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index cd8d321..738feb4 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -322,3 +322,8 @@
 SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
 SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait_wrapper)
 SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
+NI_SYSCALL							/* 314 sys_fallocate */
+SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper)	/* 315 */
+SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
+SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper)
+SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9c2872a..48dae49 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -226,10 +226,10 @@
 			    unsigned long action, void *hcpu)
 {
 	switch (action) {
-	case CPU_IDLE:
+	case S390_CPU_IDLE:
 		stop_hz_timer();
 		break;
-	case CPU_NOT_IDLE:
+	case S390_CPU_NOT_IDLE:
 		start_hz_timer();
 		break;
 	}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index cbfe730..8ec9def 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -253,19 +253,23 @@
 {
 	static int die_counter;
 
+	oops_enter();
 	debug_stop_all();
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
-        show_regs(regs);
+	print_modules();
+	show_regs(regs);
 	bust_spinlocks(0);
-        spin_unlock_irq(&die_lock);
+	add_taint(TAINT_DIE);
+	spin_unlock_irq(&die_lock);
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 	if (panic_on_oops)
 		panic("Fatal exception: panic_on_oops");
-        do_exit(SIGSEGV);
+	oops_exit();
+	do_exit(SIGSEGV);
 }
 
 static void inline
@@ -316,7 +320,7 @@
 		else {
 			enum bug_trap_type btt;
 
-			btt = report_bug(regs->psw.addr & PSW_ADDR_INSN);
+			btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs);
 			if (btt == BUG_TRAP_TYPE_WARN)
 				return;
 			die(str, regs, interruption_code);
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index e9d3432..7158a80 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -21,7 +21,7 @@
   . = 0x00000000;
   _text = .;			/* Text and read-only data */
   .text : {
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	KPROBES_TEXT
@@ -48,7 +48,7 @@
   BUG_TABLE
 
   .data : {			/* Data */
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
 	}
 
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 1e1a6ee..b6ed143 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -545,10 +545,10 @@
 			      unsigned long action, void *hcpu)
 {
 	switch (action) {
-	case CPU_IDLE:
+	case S390_CPU_IDLE:
 		stop_cpu_timer();
 		break;
-	case CPU_NOT_IDLE:
+	case S390_CPU_NOT_IDLE:
 		start_cpu_timer();
 		break;
 	}
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 59aea65..5208443 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,7 +4,7 @@
 
 EXTRA_AFLAGS := -traditional
 
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o
-obj-$(CONFIG_32BIT) += div64.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+obj-$(CONFIG_32BIT) += div64.o qrnnd.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 916b72a..9098531 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -61,30 +61,38 @@
 
 void show_mem(void)
 {
-        int i, total = 0, reserved = 0;
-        int shared = 0, cached = 0;
+	int i, total = 0, reserved = 0;
+	int shared = 0, cached = 0;
 	struct page *page;
 
-        printk("Mem-info:\n");
-        show_free_areas();
-        printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-        i = max_mapnr;
-        while (i-- > 0) {
+	printk("Mem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10));
+	i = max_mapnr;
+	while (i-- > 0) {
 		if (!pfn_valid(i))
 			continue;
 		page = pfn_to_page(i);
-                total++;
+		total++;
 		if (PageReserved(page))
-                        reserved++;
+			reserved++;
 		else if (PageSwapCache(page))
-                        cached++;
+			cached++;
 		else if (page_count(page))
 			shared += page_count(page) - 1;
-        }
-        printk("%d pages of RAM\n",total);
-        printk("%d reserved pages\n",reserved);
-        printk("%d pages shared\n",shared);
-        printk("%d pages swap cached\n",cached);
+	}
+	printk("%d pages of RAM\n", total);
+	printk("%d reserved pages\n", reserved);
+	printk("%d pages shared\n", shared);
+	printk("%d pages swap cached\n", cached);
+
+	printk("%lu pages dirty\n", global_page_state(NR_FILE_DIRTY));
+	printk("%lu pages writeback\n", global_page_state(NR_WRITEBACK));
+	printk("%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
+	printk("%lu pages slab\n",
+	       global_page_state(NR_SLAB_RECLAIMABLE) +
+	       global_page_state(NR_SLAB_UNRECLAIMABLE));
+	printk("%lu pages pagetables\n", global_page_state(NR_PAGETABLE));
 }
 
 static void __init setup_ro_region(void)
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 038179e..d8ed667 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -55,8 +55,21 @@
 config GENERIC_CLOCKEVENTS
 	def_bool n
 
+config SYS_SUPPORTS_PM
+	bool
+
 config SYS_SUPPORTS_APM_EMULATION
 	bool
+	select SYS_SUPPORTS_PM
+
+config SYS_SUPPORTS_SMP
+	bool
+
+config SYS_SUPPORTS_NUMA
+	bool
+
+config SYS_SUPPORTS_PCI
+	bool
 
 config ARCH_MAY_HAVE_PC_FDC
 	bool
@@ -81,257 +94,8 @@
 
 menu "System type"
 
-config SOLUTION_ENGINE
-	bool
-
-choice
-	prompt "SuperH system type"
-	default SH_UNKNOWN
-
-config SH_SOLUTION_ENGINE
-	bool "SolutionEngine"
-	select SOLUTION_ENGINE
-	help
-	  Select SolutionEngine if configuring for a Hitachi SH7709
-	  or SH7750 evaluation board.
-
-config SH_7722_SOLUTION_ENGINE
-	bool "SolutionEngine7722"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7722
-	help
-	  Select 7722 SolutionEngine if configuring for a Hitachi SH772
-	  evaluation board.
-
-config SH_7751_SOLUTION_ENGINE
-	bool "SolutionEngine7751"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7751
-	help
-	  Select 7751 SolutionEngine if configuring for a Hitachi SH7751
-	  evaluation board.
-	  
-config SH_7780_SOLUTION_ENGINE
-	bool "SolutionEngine7780"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7780
-	help
-	  Select 7780 SolutionEngine if configuring for a Renesas SH7780
-	  evaluation board.
-
-config SH_7300_SOLUTION_ENGINE
-	bool "SolutionEngine7300"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7300
-	help
-	  Select 7300 SolutionEngine if configuring for a Hitachi
-	  SH7300(SH-Mobile V) evaluation board.
-
-config SH_7343_SOLUTION_ENGINE
-	bool "SolutionEngine7343"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH7343
-	help
-	  Select 7343 SolutionEngine if configuring for a Hitachi
-	  SH7343 (SH-Mobile 3AS) evaluation board.
-
-config SH_73180_SOLUTION_ENGINE
-       bool "SolutionEngine73180"
-	select SOLUTION_ENGINE
-	select CPU_SUBTYPE_SH73180
-	help
-	  Select 73180 SolutionEngine if configuring for a Hitachi
-	  SH73180(SH-Mobile 3) evaluation board.
-
-config SH_7751_SYSTEMH
-	bool "SystemH7751R"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select SystemH if you are configuring for a Renesas SystemH
-	  7751R evaluation board.
-
-config SH_HP6XX
-	bool "HP6XX"
-	select SYS_SUPPORTS_APM_EMULATION
-	help
-	  Select HP6XX if configuring for a HP jornada HP6xx.
-	  More information (hardware only) at
-	  <http://www.hp.com/jornada/>.
-
-config SH_SATURN
-	bool "Saturn"
-	select CPU_SUBTYPE_SH7604
-	help
-	  Select Saturn if configuring for a SEGA Saturn.
-
-config SH_DREAMCAST
-	bool "Dreamcast"
-	select CPU_SUBTYPE_SH7091
-	help
-	  Select Dreamcast if configuring for a SEGA Dreamcast.
-	  More information at
-	  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
-	  Dreamcast project is at <http://linuxdc.sourceforge.net/>.
-
-config SH_MPC1211
-	bool "Interface MPC1211"
-	help
-	  CTP/PCI-SH02 is a CPU module computer that is produced
-	  by Interface Corporation.
-	  More information at <http://www.interface.co.jp>
-
-config SH_SH03
-	bool "Interface CTP/PCI-SH03"
-	help
-	  CTP/PCI-SH03 is a CPU module computer that is produced
-	  by Interface Corporation.
-	  More information at <http://www.interface.co.jp>
-
-config SH_SECUREEDGE5410
-	bool "SecureEdge5410"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select SecureEdge5410 if configuring for a SnapGear SH board.
-	  This includes both the OEM SecureEdge products as well as the
-	  SME product line.
-
-config SH_HS7751RVOIP
-	bool "HS7751RVOIP"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select HS7751RVOIP if configuring for a Renesas Technology
-	  Sales VoIP board.
-
-config SH_7710VOIPGW
-	bool "SH7710-VOIP-GW"
-	select CPU_SUBTYPE_SH7710
-	help
-	  Select this option to build a kernel for the SH7710 based
-	  VOIP GW.
-
-config SH_RTS7751R2D
-	bool "RTS7751R2D"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select RTS7751R2D if configuring for a Renesas Technology
-	  Sales SH-Graphics board.
-
-config SH_HIGHLANDER
-	bool "Highlander"
-
-config SH_EDOSK7705
-	bool "EDOSK7705"
-	select CPU_SUBTYPE_SH7705
-
-config SH_SH4202_MICRODEV
-	bool "SH4-202 MicroDev"
-	select CPU_SUBTYPE_SH4_202
-	help
-	  Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
-	  with an SH4-202 CPU.
-
-config SH_LANDISK
-	bool "LANDISK"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  I-O DATA DEVICE, INC. "LANDISK Series" support.
-
-config SH_TITAN
-	bool "TITAN"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select Titan if you are configuring for a Nimble Microsystems
-	  NetEngine NP51R.
-
-config SH_SHMIN
-	bool "SHMIN"
-	select CPU_SUBTYPE_SH7706
-	help
-	  Select SHMIN if configuring for the SHMIN board.
-
-config SH_7206_SOLUTION_ENGINE
-	bool "SolutionEngine7206"
-	select CPU_SUBTYPE_SH7206
-	help
-	  Select 7206 SolutionEngine if configuring for a Hitachi SH7206
-	  evaluation board.
-
-config SH_7619_SOLUTION_ENGINE
-	bool "SolutionEngine7619"
-	select CPU_SUBTYPE_SH7619
-	help
-	  Select 7619 SolutionEngine if configuring for a Hitachi SH7619
-	  evaluation board.
-	
-config SH_LBOX_RE2
-	bool "L-BOX RE2"
-	select CPU_SUBTYPE_SH7751R
-	help
-	  Select L-BOX RE2 if configuring for the NTT COMWARE L-BOX RE2.
-
-config SH_UNKNOWN
-	bool "BareCPU"
-	help
-	  "Bare CPU" aka "unknown" means an SH-based system which is not one
-	  of the specific ones mentioned above, which means you need to enter
-	  all sorts of stuff like CONFIG_MEMORY_START because the config
-	  system doesn't already know what it is.  You get a machine vector
-	  without any platform-specific code in it, so things like the RTC may
-	  not work.
-
-	  This option is for the early stages of porting to a new machine.
-
-endchoice
-
-source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
-source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
-source "arch/sh/boards/renesas/r7780rp/Kconfig"
-
 source "arch/sh/mm/Kconfig"
 
-config CF_ENABLER
-	bool "Compact Flash Enabler support"
-	depends on SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_SH03
-	---help---
-	  Compact Flash is a small, removable mass storage device introduced
-	  in 1994 originally as a PCMCIA device.  If you say `Y' here, you
-	  compile in support for Compact Flash devices directly connected to
-	  a SuperH processor.  A Compact Flash FAQ is available at
-	  <http://www.compactflash.org/faqs/faq.htm>.
-
-	  If your board has "Directly Connected" CompactFlash at area 5 or 6,
-	  you may want to enable this option.  Then, you can use CF as
-	  primary IDE drive (only tested for SanDisk).
-
-	  If in doubt, select 'N'.
-
-choice
-	prompt "Compact Flash Connection Area"
-	depends on CF_ENABLER
-	default CF_AREA6
-
-config CF_AREA5
-	bool "Area5"
-	help
-	  If your board has "Directly Connected" CompactFlash, You should
-	  select the area where your CF is connected to.
-
-	  - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
-	  - "Area6" if it is connected to Area 6 (0x18000000)
-
-	  "Area6" will work for most boards.
-
-config CF_AREA6
-	bool "Area6"
-
-endchoice
-
-config CF_BASE_ADDR
-	hex
-	depends on CF_ENABLER
-	default "0xb8000000" if CF_AREA6
-	default "0xb4000000" if CF_AREA5
-
 menu "Processor features"
 
 choice
@@ -351,7 +115,7 @@
 
 config SH_FPU
 	bool "FPU support"
-	depends on !CPU_SH3
+	depends on CPU_SH4
 	default y
 	help
 	  Selecting this option will enable support for SH processors that
@@ -437,6 +201,209 @@
 
 endmenu
 
+menu "Board support"
+
+config SOLUTION_ENGINE
+	bool
+
+config SH_SOLUTION_ENGINE
+	bool "SolutionEngine"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7750
+	help
+	  Select SolutionEngine if configuring for a Hitachi SH7709
+	  or SH7750 evaluation board.
+
+config SH_7206_SOLUTION_ENGINE
+	bool "SolutionEngine7206"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7206
+	help
+	  Select 7206 SolutionEngine if configuring for a Hitachi SH7206
+	  evaluation board.
+
+config SH_7619_SOLUTION_ENGINE
+	bool "SolutionEngine7619"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7619
+	help
+	  Select 7619 SolutionEngine if configuring for a Hitachi SH7619
+	  evaluation board.
+	
+config SH_7722_SOLUTION_ENGINE
+	bool "SolutionEngine7722"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7722
+	help
+	  Select 7722 SolutionEngine if configuring for a Hitachi SH772
+	  evaluation board.
+
+config SH_7751_SOLUTION_ENGINE
+	bool "SolutionEngine7751"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7751
+	help
+	  Select 7751 SolutionEngine if configuring for a Hitachi SH7751
+	  evaluation board.
+	  
+config SH_7780_SOLUTION_ENGINE
+	bool "SolutionEngine7780"
+	select SOLUTION_ENGINE
+	select SYS_SUPPORTS_PCI
+	depends on CPU_SUBTYPE_SH7780
+	help
+	  Select 7780 SolutionEngine if configuring for a Renesas SH7780
+	  evaluation board.
+
+config SH_7300_SOLUTION_ENGINE
+	bool "SolutionEngine7300"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7300
+	help
+	  Select 7300 SolutionEngine if configuring for a Hitachi
+	  SH7300(SH-Mobile V) evaluation board.
+
+config SH_7343_SOLUTION_ENGINE
+	bool "SolutionEngine7343"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7343
+	help
+	  Select 7343 SolutionEngine if configuring for a Hitachi
+	  SH7343 (SH-Mobile 3AS) evaluation board.
+
+config SH_73180_SOLUTION_ENGINE
+	bool "SolutionEngine73180"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH73180
+	help
+	  Select 73180 SolutionEngine if configuring for a Hitachi
+	  SH73180(SH-Mobile 3) evaluation board.
+
+config SH_7751_SYSTEMH
+	bool "SystemH7751R"
+	depends on CPU_SUBTYPE_SH7751R
+	help
+	  Select SystemH if you are configuring for a Renesas SystemH
+	  7751R evaluation board.
+
+config SH_HP6XX
+	bool "HP6XX"
+	select SYS_SUPPORTS_APM_EMULATION
+	select HD6446X_SERIES
+	depends on CPU_SUBTYPE_SH7709
+	help
+	  Select HP6XX if configuring for a HP jornada HP6xx.
+	  More information (hardware only) at
+	  <http://www.hp.com/jornada/>.
+
+config SH_DREAMCAST
+	bool "Dreamcast"
+	select SYS_SUPPORTS_PCI
+	depends on CPU_SUBTYPE_SH7091
+	help
+	  Select Dreamcast if configuring for a SEGA Dreamcast.
+	  More information at
+	  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
+	  Dreamcast project is at <http://linuxdc.sourceforge.net/>.
+
+config SH_MPC1211
+	bool "Interface MPC1211"
+	depends on CPU_SUBTYPE_SH7751 && BROKEN
+	help
+	  CTP/PCI-SH02 is a CPU module computer that is produced
+	  by Interface Corporation.
+	  More information at <http://www.interface.co.jp>
+
+config SH_SH03
+	bool "Interface CTP/PCI-SH03"
+	depends on CPU_SUBTYPE_SH7751 && BROKEN
+	select SYS_SUPPORTS_PCI
+	help
+	  CTP/PCI-SH03 is a CPU module computer that is produced
+	  by Interface Corporation.
+	  More information at <http://www.interface.co.jp>
+
+config SH_SECUREEDGE5410
+	bool "SecureEdge5410"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  Select SecureEdge5410 if configuring for a SnapGear SH board.
+	  This includes both the OEM SecureEdge products as well as the
+	  SME product line.
+
+config SH_HS7751RVOIP
+	bool "HS7751RVOIP"
+	depends on CPU_SUBTYPE_SH7751R
+	help
+	  Select HS7751RVOIP if configuring for a Renesas Technology
+	  Sales VoIP board.
+
+config SH_7710VOIPGW
+	bool "SH7710-VOIP-GW"
+	depends on CPU_SUBTYPE_SH7710
+	help
+	  Select this option to build a kernel for the SH7710 based
+	  VOIP GW.
+
+config SH_RTS7751R2D
+	bool "RTS7751R2D"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  Select RTS7751R2D if configuring for a Renesas Technology
+	  Sales SH-Graphics board.
+
+config SH_HIGHLANDER
+	bool "Highlander"
+	depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
+	select SYS_SUPPORTS_PCI
+
+config SH_EDOSK7705
+	bool "EDOSK7705"
+	depends on CPU_SUBTYPE_SH7705
+
+config SH_SH4202_MICRODEV
+	bool "SH4-202 MicroDev"
+	depends on CPU_SUBTYPE_SH4_202
+	help
+	  Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
+	  with an SH4-202 CPU.
+
+config SH_LANDISK
+	bool "LANDISK"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  I-O DATA DEVICE, INC. "LANDISK Series" support.
+
+config SH_TITAN
+	bool "TITAN"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  Select Titan if you are configuring for a Nimble Microsystems
+	  NetEngine NP51R.
+
+config SH_SHMIN
+	bool "SHMIN"
+	depends on CPU_SUBTYPE_SH7706
+	help
+	  Select SHMIN if configuring for the SHMIN board.
+
+config SH_LBOX_RE2
+	bool "L-BOX RE2"
+	depends on CPU_SUBTYPE_SH7751R
+	select SYS_SUPPORTS_PCI
+	help
+	  Select L-BOX RE2 if configuring for the NTT COMWARE L-BOX RE2.
+
+endmenu
+
+source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
+source "arch/sh/boards/renesas/r7780rp/Kconfig"
+
 menu "Timer and clock configuration"
 
 config SH_TMU
@@ -473,13 +440,13 @@
 	int "Peripheral clock frequency (in Hz)"
 	default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
 	default "31250000" if CPU_SUBTYPE_SH7619
+	default "32000000" if CPU_SUBTYPE_SH7722
 	default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
 			      CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
 			      CPU_SUBTYPE_SH7206
-	default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 || \
-			      CPU_SUBTYPE_SH7785
-	default "60000000" if CPU_SUBTYPE_SH7751
+	default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
 	default "66000000" if CPU_SUBTYPE_SH4_202
+	default "50000000"
 	help
 	  This option is used to specify the peripheral clock frequency.
 	  This is necessary for determining the reference clock value on
@@ -487,8 +454,10 @@
 
 config SH_CLK_MD
 	int "CPU Mode Pin Setting"
-	default 0
 	depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
+	default 6 if CPU_SUBTYPE_SH7206
+	default 5 if CPU_SUBTYPE_SH7619
+	default 0
 	help
 	  MD2 - MD0 pin setting.
 
@@ -560,6 +529,7 @@
 
 config SMP
 	bool "Symmetric multi-processing support"
+	depends on SYS_SUPPORTS_SMP
 	---help---
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -584,6 +554,7 @@
 	int "Maximum number of CPUs (2-32)"
 	range 2 32
 	depends on SMP
+	default "4" if CPU_SHX3
 	default "2"
 	help
 	  This allows you to specify the maximum number of CPUs which this
@@ -623,6 +594,7 @@
 
 config UBC_WAKEUP
 	bool "Wakeup UBC on startup"
+	depends on CPU_SH4
 	help
 	  Selecting this option will wakeup the User Break Controller (UBC) on
 	  startup. Although the UBC is left in an awake state when the processor
@@ -651,8 +623,8 @@
 # we're not using PCMCIA, so we make it dependent on
 # PCMCIA outright. -- PFM.
 config ISA
-	bool
-	default y if PCMCIA
+	def_bool y
+	depends on PCMCIA && HD6446X_SERIES
 	help
 	  Find out whether you have ISA slots on your motherboard.  ISA is the
 	  name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -690,6 +662,49 @@
 	tristate "SuperHyway Bus support"
 	depends on CPU_SUBTYPE_SH4_202
 
+config CF_ENABLER
+	bool "Compact Flash Enabler support"
+	depends on SOLUTION_ENGINE || SH_SH03
+	---help---
+	  Compact Flash is a small, removable mass storage device introduced
+	  in 1994 originally as a PCMCIA device.  If you say `Y' here, you
+	  compile in support for Compact Flash devices directly connected to
+	  a SuperH processor.  A Compact Flash FAQ is available at
+	  <http://www.compactflash.org/faqs/faq.htm>.
+
+	  If your board has "Directly Connected" CompactFlash at area 5 or 6,
+	  you may want to enable this option.  Then, you can use CF as
+	  primary IDE drive (only tested for SanDisk).
+
+	  If in doubt, select 'N'.
+
+choice
+	prompt "Compact Flash Connection Area"
+	depends on CF_ENABLER
+	default CF_AREA6
+
+config CF_AREA5
+	bool "Area5"
+	help
+	  If your board has "Directly Connected" CompactFlash, You should
+	  select the area where your CF is connected to.
+
+	  - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
+	  - "Area6" if it is connected to Area 6 (0x18000000)
+
+	  "Area6" will work for most boards.
+
+config CF_AREA6
+	bool "Area6"
+
+endchoice
+
+config CF_BASE_ADDR
+	hex
+	depends on CF_ENABLER
+	default "0xb8000000" if CF_AREA6
+	default "0xb4000000" if CF_AREA5
+
 source "arch/sh/drivers/pci/Kconfig"
 
 source "drivers/pci/Kconfig"
@@ -707,7 +722,7 @@
 endmenu
 
 menu "Power management options (EXPERIMENTAL)"
-depends on EXPERIMENTAL
+depends on EXPERIMENTAL && SYS_SUPPORTS_PM
 
 source kernel/power/Kconfig
 
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index b563072..52f6a99 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -52,6 +52,10 @@
 	  select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
 	  the kernel command line option to toggle back and forth.
 
+config DEBUG_BOOTMEM
+	depends on DEBUG_KERNEL
+	bool "Debug BOOTMEM initialization"
+
 config DEBUG_STACKOVERFLOW
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL
@@ -82,6 +86,7 @@
 	bool "Include KGDB kernel debugger"
 	select FRAME_POINTER
 	select DEBUG_INFO
+	depends on CPU_SH3 || CPU_SH4
 	help
 	  Include in-kernel hooks for kgdb, the Linux kernel source level
 	  debugger.  See <http://kgdb.sourceforge.net/> for more information.
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 7b11224..77fecc6 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -34,20 +34,20 @@
 endif
 endif
 
-cflags-$(CONFIG_CPU_SH2)		:= -m2
-cflags-$(CONFIG_CPU_SH2A)		:= -m2a $(call cc-option,-m2a-nofpu,)
-cflags-$(CONFIG_CPU_SH3)		:= -m3
-cflags-$(CONFIG_CPU_SH4)		:= -m4 \
+cflags-$(CONFIG_CPU_SH2)		:= $(call cc-option,-m2,)
+cflags-$(CONFIG_CPU_SH2A)		+= $(call cc-option,-m2a,) \
+					   $(call cc-option,-m2a-nofpu,)
+cflags-$(CONFIG_CPU_SH3)		:= $(call cc-option,-m3,)
+cflags-$(CONFIG_CPU_SH4)		:= $(call cc-option,-m4,) \
 	$(call cc-option,-mno-implicit-fp,-m4-nofpu)
-cflags-$(CONFIG_CPU_SH4A)		:= -m4a $(call cc-option,-m4a-nofpu,)
+cflags-$(CONFIG_CPU_SH4A)		+= $(call cc-option,-m4a,) \
+					   $(call cc-option,-m4a-nofpu,)
 
 cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= -mb
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= -ml
 
 cflags-y	+= $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding
 
-cflags-$(CONFIG_SH_DSP)			+= -Wa,-dsp
-
 cflags-$(CONFIG_MORE_COMPILE_OPTIONS)	+= \
 	$(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
 
@@ -87,39 +87,37 @@
 core-$(CONFIG_SH_FPU_EMU)	+= arch/sh/math-emu/
 
 # Boards
-machdir-$(CONFIG_SH_SOLUTION_ENGINE)		:= se/770x
-machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE)	:= se/7722
-machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)	:= se/7751
-machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE)	:= se/7780
-machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)	:= se/7300
-machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)	:= se/7343
-machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)	:= se/73180
-machdir-$(CONFIG_SH_HP6XX)			:= hp6xx
-machdir-$(CONFIG_SH_SATURN)			:= saturn
-machdir-$(CONFIG_SH_DREAMCAST)			:= dreamcast
-machdir-$(CONFIG_SH_MPC1211)			:= mpc1211
-machdir-$(CONFIG_SH_SH03)			:= sh03
-machdir-$(CONFIG_SH_SECUREEDGE5410)		:= snapgear
-machdir-$(CONFIG_SH_HS7751RVOIP)		:= renesas/hs7751rvoip
-machdir-$(CONFIG_SH_RTS7751R2D)			:= renesas/rts7751r2d
-machdir-$(CONFIG_SH_7751_SYSTEMH)		:= renesas/systemh
-machdir-$(CONFIG_SH_EDOSK7705)			:= renesas/edosk7705
-machdir-$(CONFIG_SH_HIGHLANDER)			:= renesas/r7780rp
-machdir-$(CONFIG_SH_7710VOIPGW)			:= renesas/sh7710voipgw
-machdir-$(CONFIG_SH_SH4202_MICRODEV)		:= superh/microdev
-machdir-$(CONFIG_SH_LANDISK)			:= landisk
-machdir-$(CONFIG_SH_TITAN)			:= titan
-machdir-$(CONFIG_SH_SHMIN)			:= shmin
-machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE)	:= se/7206
-machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE)	:= se/7619
-machdir-$(CONFIG_SH_LBOX_RE2)			:= lboxre2
-machdir-$(CONFIG_SH_UNKNOWN)			:= unknown
+machdir-$(CONFIG_SH_SOLUTION_ENGINE)		+= se/770x
+machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE)	+= se/7722
+machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)	+= se/7751
+machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE)	+= se/7780
+machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)	+= se/7300
+machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)	+= se/7343
+machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)	+= se/73180
+machdir-$(CONFIG_SH_HP6XX)			+= hp6xx
+machdir-$(CONFIG_SH_DREAMCAST)			+= dreamcast
+machdir-$(CONFIG_SH_MPC1211)			+= mpc1211
+machdir-$(CONFIG_SH_SH03)			+= sh03
+machdir-$(CONFIG_SH_SECUREEDGE5410)		+= snapgear
+machdir-$(CONFIG_SH_HS7751RVOIP)		+= renesas/hs7751rvoip
+machdir-$(CONFIG_SH_RTS7751R2D)			+= renesas/rts7751r2d
+machdir-$(CONFIG_SH_7751_SYSTEMH)		+= renesas/systemh
+machdir-$(CONFIG_SH_EDOSK7705)			+= renesas/edosk7705
+machdir-$(CONFIG_SH_HIGHLANDER)			+= renesas/r7780rp
+machdir-$(CONFIG_SH_7710VOIPGW)			+= renesas/sh7710voipgw
+machdir-$(CONFIG_SH_SH4202_MICRODEV)		+= superh/microdev
+machdir-$(CONFIG_SH_LANDISK)			+= landisk
+machdir-$(CONFIG_SH_TITAN)			+= titan
+machdir-$(CONFIG_SH_SHMIN)			+= shmin
+machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE)	+= se/7206
+machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE)	+= se/7619
+machdir-$(CONFIG_SH_LBOX_RE2)			+= lboxre2
 
-incdir-y			:= $(notdir $(machdir-y))
-incdir-$(CONFIG_SH_HP6XX)			:= hp6xx
+incdir-y	:= $(notdir $(machdir-y))
 
 ifneq ($(machdir-y),)
-core-y				+= arch/sh/boards/$(machdir-y)/
+core-y	+= $(addprefix arch/sh/boards/, \
+	     $(filter-out ., $(patsubst %,%/,$(machdir-y))))
 endif
 
 # Companion chips
@@ -157,19 +155,31 @@
 #	Most boards have their own mach directories.  For the ones that
 #	don't, just reference the parent directory so the semantics are
 #	kept roughly the same.
+#
+#	When multiple boards are compiled in at the same time, preference
+#	for the mach link is given to whichever has a directory for its
+#	headers. However, this is only a workaround until platforms that
+#	can live in the same kernel image back away from relying on the
+#	mach link.
 
 include/asm-sh/.mach: $(wildcard include/config/sh/*.h) \
 		      include/config/auto.conf FORCE
-	@echo -n '  SYMLINK include/asm-sh/mach -> '
 	$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
-	$(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
-		echo -e 'include/asm-sh/$(incdir-y)'; \
-		ln -fsn $(incdir-prefix)$(incdir-y) \
+	$(Q)rm -f include/asm-sh/mach
+	$(Q)for i in $(incdir-y); do \
+	if [ -d $(incdir-prefix)$$i ]; then \
+		echo -n '  SYMLINK include/asm-sh/mach -> '; \
+		echo -e "include/asm-sh/$$i"; \
+		ln -fsn $(incdir-prefix)$$i \
 			include/asm-sh/mach; \
 	else \
-		echo -e 'include/asm-sh'; \
-		ln -fsn $(incdir-prefix) include/asm-sh/mach; \
-	fi
+		if [ ! -d include/asm-sh/mach ]; then \
+			echo -n '  SYMLINK include/asm-sh/mach -> '; \
+			echo -e 'include/asm-sh'; \
+			ln -fsn $(incdir-prefix) include/asm-sh/mach; \
+		fi; \
+	fi; \
+	done
 	@touch $@
 
 archprepare: include/asm-sh/.cpu include/asm-sh/.mach maketools
@@ -188,7 +198,9 @@
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
-CLEAN_FILES += include/asm-sh/machtypes.h
+CLEAN_FILES += include/asm-sh/machtypes.h \
+	       include/asm-sh/cpu include/asm-sh/.cpu \
+	       include/asm-sh/mach include/asm-sh/.mach
 
 define archhelp
 	@echo '* zImage 	           - Compressed kernel image'
diff --git a/arch/sh/boards/dreamcast/setup.c b/arch/sh/boards/dreamcast/setup.c
index f13017e..8799df6 100644
--- a/arch/sh/boards/dreamcast/setup.c
+++ b/arch/sh/boards/dreamcast/setup.c
@@ -60,7 +60,7 @@
 #endif
 }
 
-struct sh_machine_vector mv_dreamcast __initmv = {
+static struct sh_machine_vector mv_dreamcast __initmv = {
 	.mv_name		= "Sega Dreamcast",
 	.mv_setup		= dreamcast_setup,
 	.mv_irq_demux		= systemasic_irq_demux,
@@ -70,4 +70,3 @@
 	.mv_consistent_free	= dreamcast_consistent_free,
 #endif
 };
-ALIAS_MV(dreamcast)
diff --git a/arch/sh/boards/hp6xx/mach.c b/arch/sh/boards/hp6xx/mach.c
deleted file mode 100644
index 08dbba9..0000000
--- a/arch/sh/boards/hp6xx/mach.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/arch/sh/boards/hp6xx/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the HP680
- */
-#include <asm/machvec.h>
-#include <asm/hd64461.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-struct sh_machine_vector mv_hp6xx __initmv = {
-	.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
-
-	.mv_inb = hd64461_inb,
-	.mv_inw = hd64461_inw,
-	.mv_inl = hd64461_inl,
-	.mv_outb = hd64461_outb,
-	.mv_outw = hd64461_outw,
-	.mv_outl = hd64461_outl,
-
-	.mv_inb_p = hd64461_inb_p,
-	.mv_inw_p = hd64461_inw,
-	.mv_inl_p = hd64461_inl,
-	.mv_outb_p = hd64461_outb_p,
-	.mv_outw_p = hd64461_outw,
-	.mv_outl_p = hd64461_outl,
-
-	.mv_insb = hd64461_insb,
-	.mv_insw = hd64461_insw,
-	.mv_insl = hd64461_insl,
-	.mv_outsb = hd64461_outsb,
-	.mv_outsw = hd64461_outsw,
-	.mv_outsl = hd64461_outsl,
-
-	.mv_readw = hd64461_readw,
-	.mv_writew = hd64461_writew,
-
-	.mv_irq_demux = hd64461_irq_demux,
-};
-
-ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/hp6xx/setup.c b/arch/sh/boards/hp6xx/setup.c
index 6aeee85..7ae7089 100644
--- a/arch/sh/boards/hp6xx/setup.c
+++ b/arch/sh/boards/hp6xx/setup.c
@@ -98,10 +98,9 @@
 }
 device_initcall(hp6xx_devices_setup);
 
-struct sh_machine_vector mv_hp6xx __initmv = {
+static struct sh_machine_vector mv_hp6xx __initmv = {
 	.mv_name = "hp6xx",
 	.mv_setup = hp6xx_setup,
 	.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
 	.mv_irq_demux = hd64461_irq_demux,
 };
-ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/landisk/gio.c b/arch/sh/boards/landisk/gio.c
index 50d38be..a37643d 100644
--- a/arch/sh/boards/landisk/gio.c
+++ b/arch/sh/boards/landisk/gio.c
@@ -69,7 +69,7 @@
 	}
 
 	switch (cmd) {
-	case GIODRV_IOCSGIOSETADDR:	/* addres set */
+	case GIODRV_IOCSGIOSETADDR:	/* address set */
 		addr = data;
 		break;
 
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index 4058b4f..eda7176 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/arch/sh/boards/landisk/setup.c
@@ -44,8 +44,14 @@
 	},
 };
 
+static struct platform_device rtc_device = {
+	.name		= "rs5c313",
+	.id		= -1,
+};
+
 static struct platform_device *landisk_devices[] __initdata = {
 	&cf_ide_device,
+	&rtc_device,
 };
 
 static int __init landisk_devices_setup(void)
@@ -91,10 +97,9 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_landisk __initmv = {
+static struct sh_machine_vector mv_landisk __initmv = {
 	.mv_name = "LANDISK",
 	.mv_nr_irqs = 72,
 	.mv_setup = landisk_setup,
 	.mv_init_irq = init_landisk_IRQ,
 };
-ALIAS_MV(landisk)
diff --git a/arch/sh/boards/lboxre2/setup.c b/arch/sh/boards/lboxre2/setup.c
index 4e20f7c..9c830fd 100644
--- a/arch/sh/boards/lboxre2/setup.c
+++ b/arch/sh/boards/lboxre2/setup.c
@@ -77,9 +77,8 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_lboxre2 __initmv = {
+static struct sh_machine_vector mv_lboxre2 __initmv = {
 	.mv_name		= "L-BOX RE2",
 	.mv_nr_irqs		= 72,
 	.mv_init_irq		= init_lboxre2_IRQ,
 };
-ALIAS_MV(lboxre2)
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
index 1a0604b..8ce03e0 100644
--- a/arch/sh/boards/mpc1211/setup.c
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -338,11 +338,10 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_mpc1211 __initmv = {
+static struct sh_machine_vector mv_mpc1211 __initmv = {
 	.mv_name		= "Interface MPC-1211(CTP/PCI/MPC-SH02)",
 	.mv_setup		= mpc1211_setup,
 	.mv_nr_irqs		= 48,
 	.mv_irq_demux		= mpc1211_irq_demux,
 	.mv_init_irq		= init_mpc1211_IRQ,
 };
-ALIAS_MV(mpc1211)
diff --git a/arch/sh/boards/renesas/edosk7705/setup.c b/arch/sh/boards/renesas/edosk7705/setup.c
index ec5be01..f076c45 100644
--- a/arch/sh/boards/renesas/edosk7705/setup.c
+++ b/arch/sh/boards/renesas/edosk7705/setup.c
@@ -21,7 +21,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_edosk7705 __initmv = {
+static struct sh_machine_vector mv_edosk7705 __initmv = {
 	.mv_name		= "EDOSK7705",
 	.mv_nr_irqs		= 80,
 
@@ -41,4 +41,3 @@
 	.mv_isa_port2addr	= sh_edosk7705_isa_port2addr,
 	.mv_init_irq		= sh_edosk7705_init_irq,
 };
-ALIAS_MV(edosk7705)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c
index f7d0e30..fa5fa39 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/setup.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c
@@ -89,7 +89,7 @@
 	printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
 }
 
-struct sh_machine_vector mv_hs7751rvoip __initmv = {
+static struct sh_machine_vector mv_hs7751rvoip __initmv = {
 	.mv_name		= "HS7751RVoIP",
 	.mv_setup		= hs7751rvoip_setup,
 	.mv_nr_irqs		= 72,
@@ -118,4 +118,3 @@
 	.mv_init_irq		= hs7751rvoip_init_irq,
 	.mv_ioport_map		= hs7751rvoip_ioport_map,
 };
-ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/r7780rp/Kconfig b/arch/sh/boards/renesas/r7780rp/Kconfig
index 9fb1164..fc8f28e 100644
--- a/arch/sh/boards/renesas/r7780rp/Kconfig
+++ b/arch/sh/boards/renesas/r7780rp/Kconfig
@@ -6,18 +6,18 @@
 
 config SH_R7780RP
 	bool "R7780RP-1 board support"
-	select CPU_SUBTYPE_SH7780
+	depends on CPU_SUBTYPE_SH7780
 
 config SH_R7780MP
 	bool "R7780MP board support"
-	select CPU_SUBTYPE_SH7780
+	depends on CPU_SUBTYPE_SH7780
 	help
 	  Selecting this option will enable support for the mass-production
 	  version of the R7780RP. If in doubt, say Y.
 
 config SH_R7785RP
 	bool "R7785RP board support"
-	select CPU_SUBTYPE_SH7785
+	depends on CPU_SUBTYPE_SH7785
 
 endchoice
 
diff --git a/arch/sh/boards/renesas/r7780rp/Makefile b/arch/sh/boards/renesas/r7780rp/Makefile
index 609e5d5..b1d20af 100644
--- a/arch/sh/boards/renesas/r7780rp/Makefile
+++ b/arch/sh/boards/renesas/r7780rp/Makefile
@@ -3,5 +3,8 @@
 #
 irqinit-y			:= irq-r7780rp.o
 irqinit-$(CONFIG_SH_R7785RP)	:= irq-r7785rp.o
+obj-y				:= setup.o irq.o $(irqinit-y)
+
+ifneq ($(CONFIG_SH_R7785RP),y)
 obj-$(CONFIG_PUSH_SWITCH)	+= psw.o
-obj-y	 			:= setup.o irq.o $(irqinit-y)
+endif
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index 0727ef9..5afb864 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -166,10 +166,9 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_highlander __initmv = {
+static struct sh_machine_vector mv_highlander __initmv = {
 	.mv_name		= "Highlander",
 	.mv_nr_irqs		= 109,
 	.mv_setup		= highlander_setup,
 	.mv_init_irq		= highlander_init_irq,
 };
-ALIAS_MV(highlander)
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 593f26a..656fda3 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -176,7 +176,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_rts7751r2d __initmv = {
+static struct sh_machine_vector mv_rts7751r2d __initmv = {
 	.mv_name		= "RTS7751R2D",
 	.mv_setup		= rts7751r2d_setup,
 	.mv_nr_irqs		= 72,
@@ -189,4 +189,3 @@
 	.mv_consistent_free	= voyagergx_consistent_free,
 #endif
 };
-ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c
index 180810b..2dce8bd 100644
--- a/arch/sh/boards/renesas/sh7710voipgw/setup.c
+++ b/arch/sh/boards/renesas/sh7710voipgw/setup.c
@@ -88,9 +88,8 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_sh7710voipgw __initmv = {
+static struct sh_machine_vector mv_sh7710voipgw __initmv = {
 	.mv_name		= "SH7710 VoIP Gateway",
 	.mv_nr_irqs		= 104,
 	.mv_init_irq		= sh7710voipgw_init_irq,
 };
-ALIAS_MV(sh7710voipgw)
diff --git a/arch/sh/boards/renesas/systemh/setup.c b/arch/sh/boards/renesas/systemh/setup.c
index 9361176..ee78af8 100644
--- a/arch/sh/boards/renesas/systemh/setup.c
+++ b/arch/sh/boards/renesas/systemh/setup.c
@@ -28,7 +28,7 @@
 	make_systemh_irq(0xb);	/* Ethernet interrupt */
 }
 
-struct sh_machine_vector mv_7751systemh __initmv = {
+static struct sh_machine_vector mv_7751systemh __initmv = {
 	.mv_name		= "7751 SystemH",
 	.mv_nr_irqs		= 72,
 
@@ -55,4 +55,3 @@
 
 	.mv_init_irq		= sh7751systemh_init_irq,
 };
-ALIAS_MV(7751systemh)
diff --git a/arch/sh/boards/saturn/Makefile b/arch/sh/boards/saturn/Makefile
deleted file mode 100644
index 75a3042..0000000
--- a/arch/sh/boards/saturn/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the Sega Saturn specific parts of the kernel
-#
-
-obj-y	 := setup.o io.o irq.o
-
-obj-$(CONFIG_SMP) += smp.o
-
diff --git a/arch/sh/boards/saturn/io.c b/arch/sh/boards/saturn/io.c
deleted file mode 100644
index c6e4f7f..0000000
--- a/arch/sh/boards/saturn/io.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/sh/boards/saturn/io.c
- *
- * I/O routines for the Sega Saturn.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <asm/saturn/io.h>
-#include <asm/machvec.h>
-
-unsigned long saturn_isa_port2addr(unsigned long offset)
-{
-	return offset;
-}
-
-void *saturn_ioremap(unsigned long offset, unsigned long size)
-{
-	return (void *)offset;
-}
-
-void saturn_iounmap(void *addr)
-{
-}
-
diff --git a/arch/sh/boards/saturn/irq.c b/arch/sh/boards/saturn/irq.c
deleted file mode 100644
index 15d1d3f..0000000
--- a/arch/sh/boards/saturn/irq.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * arch/sh/boards/saturn/irq.c
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-/*
- * Interrupts map out as follows:
- *
- *  Vector	Name		Mask
- *
- * 	64	VBLANKIN	0x0001
- * 	65	VBLANKOUT	0x0002
- *	66	HBLANKIN	0x0004
- *	67	TIMER0		0x0008
- *	68	TIMER1		0x0010
- *	69	DSPEND		0x0020
- *	70	SOUNDREQUEST	0x0040
- *	71	SYSTEMMANAGER	0x0080
- *	72	PAD		0x0100
- *	73	LEVEL2DMAEND	0x0200
- *	74	LEVEL1DMAEND	0x0400
- *	75	LEVEL0DMAEND	0x0800
- *	76	DMAILLEGAL	0x1000
- *	77	SRITEDRAWEND	0x2000
- *	78	ABUS		0x8000
- *
- */
-#define SATURN_IRQ_MIN		64	/* VBLANKIN */
-#define SATURN_IRQ_MAX		78	/* ABUS */
-
-#define SATURN_IRQ_MASK		0xbfff
-
-static inline u32 saturn_irq_mask(unsigned int irq_nr)
-{
-	u32 mask;
-
-	mask = (1 << (irq_nr - SATURN_IRQ_MIN));
-	mask <<= (irq_nr == SATURN_IRQ_MAX);
-	mask &= SATURN_IRQ_MASK;
-
-	return mask;
-}
-
-static inline void mask_saturn_irq(unsigned int irq_nr)
-{
-	u32 mask;
-
-	mask = ctrl_inl(SATURN_IMR);
-	mask |= saturn_irq_mask(irq_nr);
-	ctrl_outl(mask, SATURN_IMR);
-}
-
-static inline void unmask_saturn_irq(unsigned int irq_nr)
-{
-	u32 mask;
-
-	mask = ctrl_inl(SATURN_IMR);
-	mask &= ~saturn_irq_mask(irq_nr);
-	ctrl_outl(mask, SATURN_IMR);
-}
-
-static void disable_saturn_irq(unsigned int irq_nr)
-{
-	mask_saturn_irq(irq_nr);
-}
-
-static void enable_saturn_irq(unsigned int irq_nr)
-{
-	unmask_saturn_irq(irq_nr);
-}
-
-static void mask_and_ack_saturn_irq(unsigned int irq_nr)
-{
-	mask_saturn_irq(irq_nr);
-}
-
-static void end_saturn_irq(unsigned int irq_nr)
-{
-	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		unmask_saturn_irq(irq_nr);
-}
-
-static unsigned int startup_saturn_irq(unsigned int irq_nr)
-{
-	unmask_saturn_irq(irq_nr);
-
-	return 0;
-}
-
-static void shutdown_saturn_irq(unsigned int irq_nr)
-{
-	mask_saturn_irq(irq_nr);
-}
-
-static struct hw_interrupt_type saturn_int = {
-	.typename	= "Saturn",
-	.enable		= enable_saturn_irq,
-	.disable	= disable_saturn_irq,
-	.ack		= mask_and_ack_saturn_irq,
-	.end		= end_saturn_irq,
-	.startup	= startup_saturn_irq,
-	.shutdown	= shutdown_saturn_irq,
-};
-
-int saturn_irq_demux(int irq_nr)
-{
-	/* FIXME */
-	return irq_nr;
-}
-
diff --git a/arch/sh/boards/saturn/setup.c b/arch/sh/boards/saturn/setup.c
deleted file mode 100644
index a3a37c9..0000000
--- a/arch/sh/boards/saturn/setup.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 
- * arch/sh/boards/saturn/setup.c
- *
- * Hardware support for the Sega Saturn.
- *
- * Copyright (c) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/io.h>
-
-extern int saturn_irq_demux(int irq_nr);
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_saturn __initmv = {
-	.mv_name		= "Sega Saturn",
-	.mv_nr_irqs		= 80,	/* Fix this later */
-
-	.mv_isa_port2addr	= saturn_isa_port2addr,
-	.mv_irq_demux		= saturn_irq_demux,
-
-	.mv_ioremap		= saturn_ioremap,
-	.mv_iounmap		= saturn_iounmap,
-};
-ALIAS_MV(saturn)
diff --git a/arch/sh/boards/saturn/smp.c b/arch/sh/boards/saturn/smp.c
deleted file mode 100644
index 7646091..0000000
--- a/arch/sh/boards/saturn/smp.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* 
- * arch/sh/boards/saturn/smp.c
- *
- * SMP support for the Sega Saturn.
- *
- * Copyright (c) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-
-#include <asm/saturn/smpc.h>
-
-extern void start_secondary(void);
-
-void __smp_send_ipi(unsigned int cpu, unsigned int action)
-{
-	/* Nothing here yet .. */
-}
-
-unsigned int __smp_probe_cpus(void)
-{
-	/*
-	 * This is just a straightforward master/slave configuration,
-	 * and probing isn't really supported..
-	 */
-	return 2;
-}
-
-/*
- * We're only allowed to do byte-access to SMPC registers. In
- * addition to which, we treat them as write-only, since
- * reading from them will return undefined data.
- */
-static inline void smpc_slave_stop(unsigned int cpu)
-{
-	smpc_barrier();
-	ctrl_outb(1, SMPC_STATUS);
-
-	ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND);
-	smpc_barrier();
-}
-
-static inline void smpc_slave_start(unsigned int cpu)
-{
-	ctrl_outb(1, SMPC_STATUS);
-	ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND);
-
-	smpc_barrier();
-}
-
-void __smp_slave_init(unsigned int cpu)
-{
-	register unsigned long vbr;
-	void **entry;
-
-	__asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr));
-	entry = (void **)(vbr + 0x310 + 0x94);
-
-	smpc_slave_stop(cpu);
-
-	*(void **)entry = (void *)start_secondary;
-
-	smpc_slave_start(cpu);
-}
-
diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c
index ca71487..a074b62 100644
--- a/arch/sh/boards/se/7206/setup.c
+++ b/arch/sh/boards/se/7206/setup.c
@@ -70,7 +70,7 @@
  * The Machine Vector
  */
 
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 256,
 	.mv_inb			= se7206_inb,
@@ -96,4 +96,3 @@
 
 	.mv_init_irq		= init_se7206_IRQ,
 };
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7300/setup.c b/arch/sh/boards/se/7300/setup.c
index f196095..eb469f5 100644
--- a/arch/sh/boards/se/7300/setup.c
+++ b/arch/sh/boards/se/7300/setup.c
@@ -46,7 +46,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_7300se __initmv = {
+static struct sh_machine_vector mv_7300se __initmv = {
 	.mv_name = "SolutionEngine 7300",
 	.mv_nr_irqs = 109,
 	.mv_inb = sh7300se_inb,
@@ -72,4 +72,3 @@
 
 	.mv_init_irq = init_7300se_IRQ,
 };
-ALIAS_MV(7300se)
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
index 911ce1c..1deee85 100644
--- a/arch/sh/boards/se/73180/setup.c
+++ b/arch/sh/boards/se/73180/setup.c
@@ -38,15 +38,15 @@
 
 static int __init se73180_devices_setup(void)
 {
-	return platform_add_devices(sh7343se_platform_devices,
-				    ARRAY_SIZE(sh7343se_platform_devices));
+	return platform_add_devices(se73180_devices,
+				    ARRAY_SIZE(se73180_devices));
 }
 __initcall(se73180_devices_setup);
 
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_73180se __initmv = {
+static struct sh_machine_vector mv_73180se __initmv = {
 	.mv_name = "SolutionEngine 73180",
 	.mv_nr_irqs = 108,
 	.mv_inb = sh73180se_inb,
@@ -73,4 +73,3 @@
 	.mv_init_irq = init_73180se_IRQ,
 	.mv_irq_demux = shmse_irq_demux,
 };
-ALIAS_MV(73180se)
diff --git a/arch/sh/boards/se/7343/setup.c b/arch/sh/boards/se/7343/setup.c
index 3fdb16f..8fec155 100644
--- a/arch/sh/boards/se/7343/setup.c
+++ b/arch/sh/boards/se/7343/setup.c
@@ -64,7 +64,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_7343se __initmv = {
+static struct sh_machine_vector mv_7343se __initmv = {
 	.mv_name = "SolutionEngine 7343",
 	.mv_setup = sh7343se_setup,
 	.mv_nr_irqs = 108,
@@ -92,4 +92,3 @@
 	.mv_init_irq = init_7343se_IRQ,
 	.mv_irq_demux = shmse_irq_demux,
 };
-ALIAS_MV(7343se)
diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c
index 52d2c4d..1d0ef7f 100644
--- a/arch/sh/boards/se/7619/setup.c
+++ b/arch/sh/boards/se/7619/setup.c
@@ -15,8 +15,7 @@
  * The Machine Vector
  */
 
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 108,
 };
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c
index c8eccff..cdb0807 100644
--- a/arch/sh/boards/se/770x/irq.c
+++ b/arch/sh/boards/se/770x/irq.c
@@ -15,46 +15,7 @@
 #include <asm/io.h>
 #include <asm/se.h>
 
-/* 
- * If the problem of make_ipr_irq is solved, 
- * this code will become unnecessary. :-) 
- */
-static void se770x_disable_ipr_irq(unsigned int irq)
-{
-	struct ipr_data *p = get_irq_chip_data(irq);
-
-	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
-}
-
-static void se770x_enable_ipr_irq(unsigned int irq)
-{
-	struct ipr_data *p = get_irq_chip_data(irq);
-
-	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
-}
-
-static struct irq_chip se770x_irq_chip = {
-	.name           = "MS770xSE-FPGA",
-	.mask           = se770x_disable_ipr_irq,
-	.unmask         = se770x_enable_ipr_irq,
-	.mask_ack       = se770x_disable_ipr_irq,
-};
-
-void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs)
-{
-	int i;
-
-	for (i = 0; i < nr_irqs; i++) {
-		unsigned int irq = table[i].irq;
-		disable_irq_nosync(irq);
-		set_irq_chip_and_handler_name(irq, &se770x_irq_chip,
-			handle_level_irq, "level");
-		set_irq_chip_data(irq, &table[i]);
-		se770x_enable_ipr_irq(irq);
-	}
-}
-
-static struct ipr_data se770x_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/*
 	* Super I/O (Just mimic PC):
 	*  1: keyboard
@@ -68,46 +29,67 @@
 	*/
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
 	/* This is default value */
-	{ 13, 0, 8,  0x0f-13 ,BCR_ILCRA},
-	{ 5 , 0, 4,  0x0f- 5 ,BCR_ILCRA},
-	{ 10, 0, 0,  0x0f-10, BCR_ILCRB},
-	{ 7 , 0, 4,  0x0f- 7, BCR_ILCRC},
-	{ 3 , 0, 0,  0x0f- 3, BCR_ILCRC},
-	{ 1 , 0, 12, 0x0f- 1, BCR_ILCRD},
-	{ 12, 0, 4,  0x0f-12, BCR_ILCRD}, /* LAN */
-	{ 2 , 0, 8,  0x0f- 2, BCR_ILCRE}, /* PCIRQ2 */
-	{ 6 , 0, 4,  0x0f- 6, BCR_ILCRE}, /* PCIRQ1 */
-	{ 14, 0, 0,  0x0f-14, BCR_ILCRE}, /* PCIRQ0 */
-	{ 0 , 0, 12, 0x0f   , BCR_ILCRF}, 
-	{ 4 , 0, 4,  0x0f- 4, BCR_ILCRF},
-	{ 8 , 0, 12, 0x0f- 8, BCR_ILCRG},
-	{ 9 , 0, 8,  0x0f- 9, BCR_ILCRG},
-	{ 11, 0, 4,  0x0f-11, BCR_ILCRG},
+	{ 13, 0, 8,  0x0f-13, },
+	{ 5 , 0, 4,  0x0f- 5, },
+	{ 10, 1, 0,  0x0f-10, },
+	{ 7 , 2, 4,  0x0f- 7, },
+	{ 3 , 2, 0,  0x0f- 3, },
+	{ 1 , 3, 12, 0x0f- 1, },
+	{ 12, 3, 4,  0x0f-12, }, /* LAN */
+	{ 2 , 4, 8,  0x0f- 2, }, /* PCIRQ2 */
+	{ 6 , 4, 4,  0x0f- 6, }, /* PCIRQ1 */
+	{ 14, 4, 0,  0x0f-14, }, /* PCIRQ0 */
+	{ 0 , 5, 12, 0x0f   , }, 
+	{ 4 , 5, 4,  0x0f- 4, },
+	{ 8 , 6, 12, 0x0f- 8, },
+	{ 9 , 6, 8,  0x0f- 9, },
+	{ 11, 6, 4,  0x0f-11, },
 #else
-	{ 14, 0,  8, 0x0f-14 ,BCR_ILCRA},
-	{ 12, 0,  4, 0x0f-12 ,BCR_ILCRA},
-	{  8, 0,  4, 0x0f- 8 ,BCR_ILCRB},
-	{  6, 0, 12, 0x0f- 6 ,BCR_ILCRC},
-	{  5, 0,  8, 0x0f- 5 ,BCR_ILCRC},
-	{  4, 0,  4, 0x0f- 4 ,BCR_ILCRC},
-	{  3, 0,  0, 0x0f- 3 ,BCR_ILCRC},
-	{  1, 0, 12, 0x0f- 1 ,BCR_ILCRD},
+	{ 14, 0,  8, 0x0f-14, },
+	{ 12, 0,  4, 0x0f-12, },
+	{  8, 1,  4, 0x0f- 8, },
+	{  6, 2, 12, 0x0f- 6, },
+	{  5, 2,  8, 0x0f- 5, },
+	{  4, 2,  4, 0x0f- 4, },
+	{  3, 2,  0, 0x0f- 3, },
+	{  1, 3, 12, 0x0f- 1, },
 #if defined(CONFIG_STNIC)
 	/* ST NIC */
-	{ 10, 0,  4, 0x0f-10 ,BCR_ILCRD}, 	/* LAN */
+	{ 10, 3,  4, 0x0f-10, }, 	/* LAN */
 #endif
 	/* MRSHPC IRQs setting */
-	{  0, 0, 12, 0x0f- 0 ,BCR_ILCRE},	/* PCIRQ3 */
-	{ 11, 0,  8, 0x0f-11 ,BCR_ILCRE}, 	/* PCIRQ2 */
-	{  9, 0,  4, 0x0f- 9 ,BCR_ILCRE}, 	/* PCIRQ1 */
-	{  7, 0,  0, 0x0f- 7 ,BCR_ILCRE}, 	/* PCIRQ0 */
+	{  0, 4, 12, 0x0f- 0, },	/* PCIRQ3 */
+	{ 11, 4,  8, 0x0f-11, }, 	/* PCIRQ2 */
+	{  9, 4,  4, 0x0f- 9, }, 	/* PCIRQ1 */
+	{  7, 4,  0, 0x0f- 7, }, 	/* PCIRQ0 */
 	/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
 	/* NOTE: #2 and #13 are not used on PC */
-	{ 13, 0,  4, 0x0f-13 ,BCR_ILCRG}, 	/* SLOTIRQ2 */
-	{  2, 0,  0, 0x0f- 2 ,BCR_ILCRG}, 	/* SLOTIRQ1 */
+	{ 13, 6,  4, 0x0f-13, }, 	/* SLOTIRQ2 */
+	{  2, 6,  0, 0x0f- 2, }, 	/* SLOTIRQ1 */
 #endif
 };
 
+static unsigned long ipr_offsets[] = {
+	BCR_ILCRA,
+	BCR_ILCRB,
+	BCR_ILCRC,
+	BCR_ILCRD,
+	BCR_ILCRE,
+	BCR_ILCRF,
+	BCR_ILCRG,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+	.chip = {
+		.name	= "IPR-se770x",
+	},
+};
+
 /*
  * Initialize IRQ setting
  */
@@ -122,5 +104,5 @@
 	ctrl_outw(0, BCR_ILCRF);
 	ctrl_outw(0, BCR_ILCRG);
 
-	make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
index 17a2631..2962da1 100644
--- a/arch/sh/boards/se/770x/setup.c
+++ b/arch/sh/boards/se/770x/setup.c
@@ -122,7 +122,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_setup		= smsc_setup,
 #if defined(CONFIG_CPU_SH4)
@@ -160,4 +160,3 @@
 
 	.mv_init_irq		= init_se_IRQ,
 };
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7722/irq.c b/arch/sh/boards/se/7722/irq.c
index 099e5de..26cff0e 100644
--- a/arch/sh/boards/se/7722/irq.c
+++ b/arch/sh/boards/se/7722/irq.c
@@ -19,15 +19,24 @@
 #define INTC_INTMSK0             0xFFD00044
 #define INTC_INTMSKCLR0          0xFFD00064
 
+struct se7722_data {
+	unsigned char irq;
+	unsigned char ipr_idx;
+	unsigned char shift;
+	unsigned short priority;
+	unsigned long addr;
+};
+
+
 static void disable_se7722_irq(unsigned int irq)
 {
-	struct ipr_data *p = get_irq_chip_data(irq);
+	struct se7722_data *p = get_irq_chip_data(irq);
 	ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr );
 }
 
 static void enable_se7722_irq(unsigned int irq)
 {
-	struct ipr_data *p = get_irq_chip_data(irq);
+	struct se7722_data *p = get_irq_chip_data(irq);
 	ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr );
 }
 
@@ -38,7 +47,7 @@
 	.mask_ack       = disable_se7722_irq,
 };
 
-static struct ipr_data ipr_irq_table[] = {
+static struct se7722_data ipr_irq_table[] = {
 	/* irq        ,idx,sft, priority     , addr   */
 	{ MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } ,
 	{ MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } ,
diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
index 636ca6c..6cca6cb 100644
--- a/arch/sh/boards/se/7722/setup.c
+++ b/arch/sh/boards/se/7722/setup.c
@@ -137,7 +137,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_se7722 __initmv = {
+static struct sh_machine_vector mv_se7722 __initmv = {
 	.mv_name                = "Solution Engine 7722" ,
 	.mv_setup               = se7722_setup ,
 	.mv_nr_irqs		= 109 ,
@@ -145,4 +145,3 @@
 	.mv_irq_demux           = se7722_irq_demux,
 
 };
-ALIAS_MV(se7722)
diff --git a/arch/sh/boards/se/7751/irq.c b/arch/sh/boards/se/7751/irq.c
index e4c63a4..c3d1259 100644
--- a/arch/sh/boards/se/7751/irq.c
+++ b/arch/sh/boards/se/7751/irq.c
@@ -14,44 +14,31 @@
 #include <asm/irq.h>
 #include <asm/se7751.h>
 
-static struct ipr_data se7751_ipr_map[] = {
-  /* Leave old Solution Engine code in for reference. */
-#if defined(CONFIG_SH_SOLUTION_ENGINE)
-	/*
-	 * Super I/O (Just mimic PC):
-	 *  1: keyboard
-	 *  3: serial 0
-	 *  4: serial 1
-	 *  5: printer
-	 *  6: floppy
-	 *  8: rtc
-	 * 12: mouse
-	 * 14: ide0
-	 */
-	{ 14, BCR_ILCRA, 2, 0x0f-14 },
-	{ 12, BCR_ILCRA, 1, 0x0f-12 },
-	{  8, BCR_ILCRB, 1, 0x0f- 8 },
-	{  6, BCR_ILCRC, 3, 0x0f- 6 },
-	{  5, BCR_ILCRC, 2, 0x0f- 5 },
-	{  4, BCR_ILCRC, 1, 0x0f- 4 },
-	{  3, BCR_ILCRC, 0, 0x0f- 3 },
-	{  1, BCR_ILCRD, 3, 0x0f- 1 },
-
-	{ 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */
-
-	{  0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */
-	{ 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */
-	{  9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */
-	{  7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */
-
-	/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
-	/* NOTE: #2 and #13 are not used on PC */
-	{ 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */
-	{  2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */
-#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
-	{ 13, BCR_ILCRD, 3, 2 },
+static struct ipr_data ipr_irq_table[] = {
+	{ 13, 3, 3, 2 },
 	/* Add additional entries here as drivers are added and tested. */
-#endif
+};
+
+static unsigned long ipr_offsets[] = {
+	BCR_ILCRA,
+	BCR_ILCRB,
+	BCR_ILCRC,
+	BCR_ILCRD,
+	BCR_ILCRE,
+	BCR_ILCRF,
+	BCR_ILCRG,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-se7751",
+	},
 };
 
 /*
@@ -59,5 +46,5 @@
  */
 void __init init_7751se_IRQ(void)
 {
-	make_ipr_irq(se7751_ipr_map, ARRAY_SIZE(se7751_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
index 52c7bfa..7873d07 100644
--- a/arch/sh/boards/se/7751/setup.c
+++ b/arch/sh/boards/se/7751/setup.c
@@ -48,7 +48,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_7751se __initmv = {
+static struct sh_machine_vector mv_7751se __initmv = {
 	.mv_name		= "7751 SolutionEngine",
 	.mv_nr_irqs		= 72,
 
@@ -71,4 +71,3 @@
 
 	.mv_init_irq		= init_7751se_IRQ,
 };
-ALIAS_MV(7751se)
diff --git a/arch/sh/boards/se/7780/irq.c b/arch/sh/boards/se/7780/irq.c
index 3d0625c..8749147 100644
--- a/arch/sh/boards/se/7780/irq.c
+++ b/arch/sh/boards/se/7780/irq.c
@@ -16,28 +16,6 @@
 #include <asm/io.h>
 #include <asm/se7780.h>
 
-#define INTC_INTMSK0             0xFFD00044
-#define INTC_INTMSKCLR0          0xFFD00064
-
-static void disable_se7780_irq(unsigned int irq)
-{
-	struct intc2_data *p = get_irq_chip_data(irq);
-	ctrl_outl(1 << p->msk_shift, INTC_INTMSK0 + p->msk_offset);
-}
-
-static void enable_se7780_irq(unsigned int irq)
-{
-	struct intc2_data *p = get_irq_chip_data(irq);
-	ctrl_outl(1 << p->msk_shift, INTC_INTMSKCLR0 + p->msk_offset);
-}
-
-static struct irq_chip se7780_irq_chip __read_mostly = {
-	.name           = "SE7780",
-	.mask           = disable_se7780_irq,
-	.unmask         = enable_se7780_irq,
-	.mask_ack       = disable_se7780_irq,
-};
-
 static struct intc2_data intc2_irq_table[] = {
 	{ 2,  0, 31, 0, 31, 3 }, /* daughter board EXTINT1 */
 	{ 4,  0, 30, 0, 30, 3 }, /* daughter board EXTINT2 */
@@ -51,13 +29,24 @@
 	{ 0 , 0, 24, 0, 24, 3 }, /* SM501 */
 };
 
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0, /* N/A */
+	.msk_base	= 0xffd00044,
+	.mskclr_base	= 0xffd00064,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-se7780",
+	},
+};
+
 /*
  * Initialize IRQ setting
  */
 void __init init_se7780_IRQ(void)
 {
-	int i ;
-
 	/* enable all interrupt at FPGA */
 	ctrl_outw(0, FPGA_INTMSK1);
 	/* mask SM501 interrupt */
@@ -79,11 +68,5 @@
 	/* FPGA + 0x0A */
 	ctrl_outw((IRQPIN_PCCPW << IRQPOS_PCCPW), FPGA_INTSEL3);
 
-	for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) {
-		disable_irq_nosync(intc2_irq_table[i].irq);
-		set_irq_chip_and_handler_name( intc2_irq_table[i].irq, &se7780_irq_chip,
-			handle_level_irq, "level");
-		set_irq_chip_data( intc2_irq_table[i].irq, &intc2_irq_table[i] );
-		disable_se7780_irq(intc2_irq_table[i].irq);
-	}
+	register_intc2_controller(&intc2_irq_desc);
 }
diff --git a/arch/sh/boards/se/7780/setup.c b/arch/sh/boards/se/7780/setup.c
index df7d08a..723f2fd 100644
--- a/arch/sh/boards/se/7780/setup.c
+++ b/arch/sh/boards/se/7780/setup.c
@@ -113,10 +113,9 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_se7780 __initmv = {
+static struct sh_machine_vector mv_se7780 __initmv = {
 	.mv_name                = "Solution Engine 7780" ,
 	.mv_setup               = se7780_setup ,
 	.mv_nr_irqs		= 111 ,
 	.mv_init_irq		= init_se7780_IRQ,
 };
-ALIAS_MV(se7780)
diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c
index c069c44..9c031a8 100644
--- a/arch/sh/boards/sh03/setup.c
+++ b/arch/sh/boards/sh03/setup.c
@@ -15,17 +15,33 @@
 #include <asm/sh03/sh03.h>
 #include <asm/addrspace.h>
 
-static struct ipr_data sh03_ipr_map[] = {
-	{ IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY },
-	{ IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY },
-	{ IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY },
-	{ IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY },
+static struct ipr_data ipr_irq_table[] = {
+	{ IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
+	{ IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
+	{ IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
+	{ IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
+};
+
+static unsigned long ipr_offsets[] = {
+	INTC_IPRD,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh03",
+	},
 };
 
 static void __init init_sh03_IRQ(void)
 {
 	ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
-	make_ipr_irq(sh03_ipr_map, ARRAY_SIZE(sh03_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
 
 extern void *cf_io_base;
@@ -74,11 +90,10 @@
 }
 __initcall(sh03_devices_setup);
 
-struct sh_machine_vector mv_sh03 __initmv = {
+static struct sh_machine_vector mv_sh03 __initmv = {
 	.mv_name		= "Interface (CTP/PCI-SH03)",
 	.mv_setup		= sh03_setup,
 	.mv_nr_irqs		= 48,
 	.mv_ioport_map		= sh03_ioport_map,
 	.mv_init_irq		= init_sh03_IRQ,
 };
-ALIAS_MV(sh03)
diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c
index 4a9df4a..dfd1245 100644
--- a/arch/sh/boards/shmin/setup.c
+++ b/arch/sh/boards/shmin/setup.c
@@ -6,28 +6,44 @@
  * SHMIN Support.
  */
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <asm/machvec.h>
 #include <asm/shmin.h>
 #include <asm/clock.h>
-#include <asm/irq.h>
 #include <asm/io.h>
 
 #define PFC_PHCR	0xa400010eUL
 #define INTC_ICR1	0xa4000010UL
 #define INTC_IPRC	0xa4000016UL
 
-static struct ipr_data shmin_ipr_map[] = {
-	{ .irq=32, .addr=INTC_IPRC, .shift= 0, .priority=0 },
-	{ .irq=33, .addr=INTC_IPRC, .shift= 4, .priority=0 },
-	{ .irq=34, .addr=INTC_IPRC, .shift= 8, .priority=8 },
-	{ .irq=35, .addr=INTC_IPRC, .shift=12, .priority=0 },
+static struct ipr_data ipr_irq_table[] = {
+	{ 32, 0, 0, 0 },
+	{ 33, 0, 4, 0 },
+	{ 34, 0, 8, 8 },
+	{ 35, 0, 12, 0 },
+};
+
+static unsigned long ipr_offsets[] = {
+	INTC_IPRC,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-shmin",
+	},
 };
 
 static void __init init_shmin_irq(void)
 {
 	ctrl_outw(0x2a00, PFC_PHCR);	// IRQ0-3=IRQ
 	ctrl_outw(0x0aaa, INTC_ICR1);	// IRQ0-3=IRQ-mode,Low-active.
-	make_ipr_irq(shmin_ipr_map, ARRAY_SIZE(shmin_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
 
 static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
@@ -43,9 +59,8 @@
 
 }
 
-struct sh_machine_vector mv_shmin __initmv = {
+static struct sh_machine_vector mv_shmin __initmv = {
 	.mv_name	= "SHMIN",
 	.mv_init_irq	= init_shmin_irq,
 	.mv_ioport_map	= shmin_ioport_map,
 };
-ALIAS_MV(shmin)
diff --git a/arch/sh/boards/snapgear/rtc.c b/arch/sh/boards/snapgear/rtc.c
index 1659fdd..edb3dd9 100644
--- a/arch/sh/boards/snapgear/rtc.c
+++ b/arch/sh/boards/snapgear/rtc.c
@@ -108,7 +108,7 @@
 static void ds1302_reset(void)
 {
 	unsigned long	flags;
-	/* Hardware dependant reset/init */
+	/* Hardware dependent reset/init */
 	local_irq_save(flags);
 	set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
 	set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
index 650fb36..84271d8 100644
--- a/arch/sh/boards/snapgear/setup.c
+++ b/arch/sh/boards/snapgear/setup.c
@@ -68,11 +68,27 @@
  * IRL3 = crypto
  */
 
-static struct ipr_data snapgear_ipr_map[] = {
-	make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY);
-	make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY);
-	make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY);
-	make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
+static struct ipr_data ipr_irq_table[] = {
+	{ IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
+	{ IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
+	{ IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
+	{ IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
+};
+
+static unsigned long ipr_offsets[] = {
+	INTC_IPRD,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-snapgear",
+	},
 };
 
 static void __init init_snapgear_IRQ(void)
@@ -82,7 +98,7 @@
 
 	printk("Setup SnapGear IRQ/IPR ...\n");
 
-	make_ipr_irq(snapgear_ipr_map, ARRAY_SIZE(snapgear_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
 
 /*
@@ -96,7 +112,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_snapgear __initmv = {
+static struct sh_machine_vector mv_snapgear __initmv = {
 	.mv_name		= "SnapGear SecureEdge5410",
 	.mv_setup		= snapgear_setup,
 	.mv_nr_irqs		= 72,
@@ -117,4 +133,3 @@
 
 	.mv_init_irq		= init_snapgear_IRQ,
 };
-ALIAS_MV(snapgear)
diff --git a/arch/sh/boards/superh/microdev/io.c b/arch/sh/boards/superh/microdev/io.c
index 83419bf..b704e20 100644
--- a/arch/sh/boards/superh/microdev/io.c
+++ b/arch/sh/boards/superh/microdev/io.c
@@ -198,12 +198,12 @@
 	/*
 	 *	There is a board feature with the current SH4-202 MicroDev in
 	 *	that the 2 byte enables (nBE0 and nBE1) are tied together (and
-	 *	to the Chip Select Line (Ethernet_CS)). Due to this conectivity,
+	 *	to the Chip Select Line (Ethernet_CS)). Due to this connectivity,
 	 *	it is not possible to safely perform 8-bit writes to the
 	 *	Ethernet registers, as 16-bits will be consumed from the Data
 	 *	lines (corrupting the other byte).  Hence, this function is
-	 *	written to impliment 16-bit read/modify/write for all byte-wide
-	 *	acceses.
+	 *	written to implement 16-bit read/modify/write for all byte-wide
+	 *	accesses.
 	 *
 	 *	Note: there is no problem with byte READS (even or odd).
 	 *
diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c
index 8c64baa..4d33507 100644
--- a/arch/sh/boards/superh/microdev/irq.c
+++ b/arch/sh/boards/superh/microdev/irq.c
@@ -11,6 +11,7 @@
 
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/microdev.h>
@@ -100,7 +101,7 @@
 
 	fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
 
-	/* disable interupts on the FPGA INTC register */
+	/* disable interrupts on the FPGA INTC register */
 	ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
 }
 
@@ -125,7 +126,7 @@
 	priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri);
 	ctrl_outl(priorities, priorityReg);
 
-	/* enable interupts on the FPGA INTC register */
+	/* enable interrupts on the FPGA INTC register */
 	ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
 }
 
@@ -152,7 +153,7 @@
 {
 	int i;
 
-		/* disable interupts on the FPGA INTC register */
+		/* disable interrupts on the FPGA INTC register */
 	ctrl_outl(~0ul, MICRODEV_FPGA_INTDSB_REG);
 
 	for (i = 0; i < NUM_EXTERNAL_IRQS; i++)
diff --git a/arch/sh/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c
index 031c814..fc8cd06 100644
--- a/arch/sh/boards/superh/microdev/setup.c
+++ b/arch/sh/boards/superh/microdev/setup.c
@@ -349,7 +349,7 @@
 	SMSC_WRITE_INDEXED(0x00, 0xc7);	/* GP47 = nIOWOP */
 	SMSC_WRITE_INDEXED(0x08, 0xe8);	/* GP20 = nIDE2_OE */
 
-		/* Exit the configuraton state */
+		/* Exit the configuration state */
 	outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
 
 	return 0;
@@ -371,7 +371,7 @@
 /*
  * The Machine Vector
  */
-struct sh_machine_vector mv_sh4202_microdev __initmv = {
+static struct sh_machine_vector mv_sh4202_microdev __initmv = {
 	.mv_name		= "SH4-202 MicroDev",
 	.mv_setup		= microdev_setup,
 	.mv_nr_irqs		= 72,		/* QQQ need to check this - use the MACRO */
@@ -403,4 +403,3 @@
 	.mv_heartbeat		= microdev_heartbeat,
 #endif
 };
-ALIAS_MV(sh4202_microdev)
diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c
index 6bcd939..606d25a 100644
--- a/arch/sh/boards/titan/setup.c
+++ b/arch/sh/boards/titan/setup.c
@@ -12,7 +12,7 @@
 #include <asm/titan.h>
 #include <asm/io.h>
 
-static struct ipr_data titan_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR idx, shift, prio */
 	{ TITAN_IRQ_WAN,   3, 12, 8 },	/* eth0 (WAN) */
 	{ TITAN_IRQ_LAN,   3,  8, 8 },	/* eth1 (LAN) */
@@ -20,15 +20,33 @@
 	{ TITAN_IRQ_USB,   3,  0, 8 },	/* mPCI B (bottom), USB */
 };
 
+static unsigned long ipr_offsets[] = { /* stolen from setup-sh7750.c */
+	0xffd00004UL,	/* 0: IPRA */
+	0xffd00008UL,	/* 1: IPRB */
+	0xffd0000cUL,	/* 2: IPRC */
+	0xffd00010UL,	/* 3: IPRD */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-titan",
+	},
+};
 static void __init init_titan_irq(void)
 {
 	/* enable individual interrupt mode for externals */
 	ipr_irq_enable_irlm();
 	/* register ipr irqs */
-	make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
 
-struct sh_machine_vector mv_titan __initmv = {
+static struct sh_machine_vector mv_titan __initmv = {
 	.mv_name =	"Titan",
 
 	.mv_inb =	titan_inb,
@@ -52,4 +70,3 @@
 
 	.mv_init_irq =	init_titan_irq,
 };
-ALIAS_MV(titan)
diff --git a/arch/sh/boards/unknown/Makefile b/arch/sh/boards/unknown/Makefile
deleted file mode 100644
index 7d18f40..0000000
--- a/arch/sh/boards/unknown/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for unknown SH boards 
-#
-
-obj-y	 := setup.o
-
diff --git a/arch/sh/boards/unknown/setup.c b/arch/sh/boards/unknown/setup.c
deleted file mode 100644
index 1c94137..0000000
--- a/arch/sh/boards/unknown/setup.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/arch/sh/boards/unknown/setup.c
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Setup code for an unknown machine (internal peripherials only)
- *
- * This is the simplest of all boards, and serves only as a quick and dirty
- * method to start debugging a new board during bring-up until proper board
- * setup code is written.
- */
-#include <linux/init.h>
-#include <asm/machvec.h>
-
-struct sh_machine_vector mv_unknown __initmv = {
-	.mv_name		= "Unknown",
-};
-ALIAS_MV(unknown)
diff --git a/arch/sh/cchips/Kconfig b/arch/sh/cchips/Kconfig
index 0582ca8..2e516e9 100644
--- a/arch/sh/cchips/Kconfig
+++ b/arch/sh/cchips/Kconfig
@@ -13,10 +13,8 @@
 	  are additional GPIO bits that can be used to interface to
 	  external as well.
 
-# A board must have defined HD6446X_SERIES in order to see these
 config HD6446X_SERIES
-	bool "HD6446x support"
-	default n
+	bool
 
 choice
 	prompt "HD6446x options"
@@ -25,7 +23,6 @@
 
 config HD64461
 	bool "Hitachi HD64461 companion chip support"
-	depends on CPU_SUBTYPE_SH7709
 	---help---
 	  The Hitachi HD64461 provides an interface for
 	  the SH7709 CPU, supporting a LCD controller,
@@ -40,7 +37,6 @@
 
 config HD64465
 	bool "Hitachi HD64465 companion chip support"
-	depends on CPU_SUBTYPE_SH7750
 	---help---
 	  The Hitachi HD64465 provides an interface for
 	  the SH7750 CPU, supporting a LCD controller,
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index 70f1290..d70e5c8 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -28,7 +28,7 @@
 	unsigned long val;
 	unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
-	pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+	pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
 	val = readl((void __iomem *)VOYAGER_INT_MASK);
 	val &= ~mask;
 	writel(val, (void __iomem *)VOYAGER_INT_MASK);
@@ -39,7 +39,7 @@
 	unsigned long val;
 	unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
-	pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+	pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
 	val = readl((void __iomem *)VOYAGER_INT_MASK);
 	val |= mask;
 	writel(val, (void __iomem *)VOYAGER_INT_MASK);
@@ -125,11 +125,12 @@
 			i = 17;
 		else
 			printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
-		pr_debug("voyagergx_irq_demux %d \n", i);
-    	    	if (i < VOYAGER_IRQ_NUM) {
+		pr_debug("voyagergx_irq_demux %ld \n", i);
+		if (i < VOYAGER_IRQ_NUM) {
 			irq = VOYAGER_IRQ_BASE + i;
-    	    		if (voyagergx_demux[i].func != 0)
-				irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev);
+			if (voyagergx_demux[i].func != 0)
+				irq = voyagergx_demux[i].func(irq,
+						voyagergx_demux[i].dev);
 		}
 	}
 	return irq;
diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig
index 8b6b5a7..3fdd270 100644
--- a/arch/sh/configs/dreamcast_defconfig
+++ b/arch/sh/configs/dreamcast_defconfig
@@ -1,15 +1,23 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 10:51:55 2006
+# Linux kernel version: 2.6.22-rc4
+# Sat Jul  7 03:47:45 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -28,6 +36,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
@@ -35,8 +44,10 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -50,14 +61,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -93,44 +109,9 @@
 #
 # System type
 #
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-CONFIG_SH_DREAMCAST=y
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH4=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
-
-#
-# SH-3 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -138,79 +119,93 @@
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
-CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
 CONFIG_CPU_SUBTYPE_SH7091=y
-CONFIG_CPU_SUBTYPE_SH7750R=y
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
 # CONFIG_CPU_SUBTYPE_SH7750S is not set
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
 
 #
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_SH_FPU=y
 # CONFIG_SH_DSP is not set
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
 
 #
-# Timer support
+# Board support
+#
+CONFIG_SH_DREAMCAST=y
+
+#
+# Timer and clock configuration
 #
 CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=49876504
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
 
 #
 # CPU Frequency scaling
@@ -232,6 +227,7 @@
 #
 # DMA support
 #
+CONFIG_SH_DMA_API=y
 CONFIG_SH_DMA=y
 CONFIG_NR_ONCHIP_DMA_CHANNELS=4
 CONFIG_NR_DMA_CHANNELS_BOOL=y
@@ -240,17 +236,23 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
 
 #
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
@@ -269,33 +271,23 @@
 # Bus options
 #
 CONFIG_PCI=y
-# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 CONFIG_NET=y
@@ -303,13 +295,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -327,30 +319,20 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -376,7 +358,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -394,10 +385,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -408,6 +395,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -421,13 +409,16 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
-# ATA/ATAPI/MFM/RLL support
+# Misc devices
 #
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -436,10 +427,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -455,6 +442,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -470,15 +458,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -521,47 +501,16 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_SC92031 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -604,17 +553,19 @@
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -660,10 +611,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -680,14 +627,8 @@
 # CONFIG_PCIPCWATCHDOG is not set
 # CONFIG_WDTPCI is not set
 CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -695,11 +636,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -711,44 +648,51 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -763,13 +707,17 @@
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -789,10 +737,6 @@
 # CONFIG_FONT_SUN8x16 is not set
 # CONFIG_FONT_SUN12x22 is not set
 # CONFIG_FONT_10x18 is not set
-
-#
-# Logo configuration
-#
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
@@ -800,7 +744,6 @@
 # CONFIG_LOGO_SUPERH_MONO is not set
 # CONFIG_LOGO_SUPERH_VGA16 is not set
 CONFIG_LOGO_SUPERH_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -808,6 +751,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -823,10 +772,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -874,10 +819,12 @@
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -957,6 +904,11 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Profiling support
 #
 CONFIG_PROFILING=y
@@ -965,17 +917,18 @@
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
+# CONFIG_SH_KGDB is not set
 
 #
 # Security options
@@ -991,8 +944,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig
new file mode 100644
index 0000000..17f7402
--- /dev/null
+++ b/arch/sh/configs/r7780mp_defconfig
@@ -0,0 +1,1223 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Mon Jun 11 10:24:57 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+# CONFIG_32BIT is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_DSP is not set
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_SPECULATIVE_EXECUTION=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Board support
+#
+# CONFIG_SH_7780_SOLUTION_ENGINE is not set
+CONFIG_SH_HIGHLANDER=y
+# CONFIG_SH_R7780RP is not set
+CONFIG_SH_R7780MP=y
+# CONFIG_SH_R7785RP is not set
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_PCLK_FREQ=32000000
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+CONFIG_PUSH_SWITCH=y
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+# CONFIG_PCNET32_NAPI is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+# CONFIG_VIA_RHINE_NAPI is not set
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OSS_OBSOLETE is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_FRAME_POINTER is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_4KSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig
index 0f5ec64..5c29338 100644
--- a/arch/sh/configs/r7785rp_defconfig
+++ b/arch/sh/configs/r7785rp_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc3
-# Mon Mar 12 14:26:33 2007
+# Linux kernel version: 2.6.22-rc4
+# Thu Jul 12 12:33:15 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,7 +11,9 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_PCI=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -43,6 +45,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_RELAY is not set
 # CONFIG_BLK_DEV_INITRD is not set
@@ -60,13 +63,18 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -102,55 +110,11 @@
 #
 # System type
 #
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-CONFIG_SH_HIGHLANDER=y
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_UNKNOWN is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_R7780MP is not set
-CONFIG_SH_R7785RP=y
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH4=y
 CONFIG_CPU_SH4A=y
 CONFIG_CPU_SHX2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -158,10 +122,7 @@
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -170,23 +131,12 @@
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 CONFIG_CPU_SUBTYPE_SH7785=y
-
-#
-# SH4AL-DSP Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
@@ -194,6 +144,7 @@
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x08000000
@@ -201,6 +152,12 @@
 CONFIG_32BIT=y
 # CONFIG_X2TLB is not set
 CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -215,17 +172,17 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
 
 #
 # Processor features
@@ -241,12 +198,22 @@
 CONFIG_CPU_HAS_PTEA=y
 
 #
+# Board support
+#
+CONFIG_SH_HIGHLANDER=y
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_R7780MP is not set
+CONFIG_SH_R7785RP=y
+
+#
 # Timer and clock configuration
 #
 CONFIG_SH_TMU=y
 CONFIG_SH_TIMER_IRQ=28
-CONFIG_NO_IDLE_HZ=y
 CONFIG_SH_PCLK_FREQ=50000000
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
 
 #
 # CPU Frequency scaling
@@ -261,7 +228,6 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
@@ -278,7 +244,7 @@
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_KEXEC=y
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
@@ -300,31 +266,22 @@
 CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
 CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 CONFIG_NET=y
@@ -332,7 +289,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -377,20 +333,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 CONFIG_BRIDGE=m
@@ -417,8 +361,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
 CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -438,10 +390,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -475,12 +423,10 @@
 #
 # Misc devices
 #
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -509,6 +455,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -554,10 +501,6 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
@@ -580,6 +523,7 @@
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
 # CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
 # CONFIG_PATA_CS5520 is not set
 # CONFIG_PATA_CS5530 is not set
@@ -629,6 +573,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -644,15 +589,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -673,10 +610,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
@@ -689,55 +623,26 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -789,6 +694,7 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -831,14 +737,8 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_DRM is not set
@@ -848,10 +748,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -864,16 +761,15 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -885,22 +781,30 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -908,7 +812,7 @@
 # CONFIG_FB_TILEBLITTING is not set
 
 #
-# Frambuffer hardware drivers
+# Frame buffer hardware drivers
 #
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
@@ -930,12 +834,11 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
 # CONFIG_FB_VIRTUAL is not set
-
-#
-# Logo configuration
-#
 # CONFIG_LOGO is not set
 
 #
@@ -952,13 +855,10 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=m
-# CONFIG_OBSOLETE_OSS is not set
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_ICH is not set
+# CONFIG_OSS_OBSOLETE is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 
 #
 # HID Devices
@@ -982,10 +882,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1026,18 +922,30 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
 #
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_SH=y
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
 # DMA Engine support
 #
 # CONFIG_DMA_ENGINE is not set
@@ -1051,14 +959,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1157,6 +1057,7 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1239,7 +1140,6 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1266,6 +1166,7 @@
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_4KSTACKS is not set
@@ -1300,6 +1201,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
@@ -1328,7 +1230,9 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
index 87ab908..f2f2a3c 100644
--- a/arch/sh/configs/se7206_defconfig
+++ b/arch/sh/configs/se7206_defconfig
@@ -1,18 +1,22 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Wed Dec  6 14:40:15 2006
+# Linux kernel version: 2.6.22-rc4
+# Fri Jun 15 19:37:46 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 # CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -34,8 +38,10 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -48,12 +54,17 @@
 # CONFIG_ELF_CORE is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
-CONFIG_SLAB=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 # CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -83,53 +94,10 @@
 #
 # System type
 #
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-CONFIG_SH_7206_SOLUTION_ENGINE=y
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH2=y
 CONFIG_CPU_SH2A=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
 CONFIG_CPU_SUBTYPE_SH7206=y
-
-#
-# SH-3 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -137,10 +105,7 @@
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -149,32 +114,28 @@
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 # CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_PAGE_OFFSET=0x00000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -184,35 +145,42 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
 
 #
 # Processor features
 #
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_SH_FPU is not set
 # CONFIG_SH_FPU_EMU is not set
 # CONFIG_SH_DSP is not set
+CONFIG_CPU_HAS_IPR_IRQ=y
 
 #
-# Timer support
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7206_SOLUTION_ENGINE=y
+
+#
+# Timer and clock configuration
 #
 CONFIG_SH_CMT=y
 # CONFIG_SH_MTU2 is not set
 CONFIG_SH_TIMER_IRQ=140
-# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=33333333
 CONFIG_SH_CLK_MD=6
+# CONFIG_TICK_ONESHOT is not set
 
 #
 # CPU Frequency scaling
@@ -227,11 +195,11 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
 #
+# CONFIG_HEARTBEAT is not set
 # CONFIG_PUSH_SWITCH is not set
 
 #
@@ -239,10 +207,11 @@
 #
 CONFIG_HZ_100=y
 # CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=100
 # CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -252,23 +221,18 @@
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
-# CONFIG_UBC_WAKEUP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
 #
 # Bus options
 #
-# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Executable file formats
 #
 CONFIG_BINFMT_FLAT=y
@@ -277,11 +241,6 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 CONFIG_NET=y
@@ -289,7 +248,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 # CONFIG_UNIX is not set
 # CONFIG_NET_KEY is not set
@@ -314,25 +272,14 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -358,7 +305,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -375,10 +331,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
@@ -393,6 +345,7 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -424,7 +377,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -452,16 +404,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -471,6 +420,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -479,18 +429,13 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -499,10 +444,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -511,19 +452,6 @@
 # CONFIG_MD is not set
 
 #
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -531,10 +459,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -544,27 +468,14 @@
 CONFIG_MII=y
 # CONFIG_STNIC is not set
 CONFIG_SMC91X=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -604,6 +515,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -639,29 +551,15 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -674,27 +572,30 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -703,6 +604,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -717,10 +624,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -802,7 +705,6 @@
 CONFIG_PROC_SYSCTL=y
 # CONFIG_SYSFS is not set
 # CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -816,7 +718,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
@@ -849,6 +750,11 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -861,14 +767,11 @@
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_UNWIND_INFO is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
 
 #
 # Security options
@@ -883,8 +786,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig
index 20ac7f4..3a3c3c1 100644
--- a/arch/sh/configs/se7619_defconfig
+++ b/arch/sh/configs/se7619_defconfig
@@ -1,18 +1,22 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Wed Dec  6 16:35:36 2006
+# Linux kernel version: 2.6.22-rc4
+# Fri Jun 15 19:43:06 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 # CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -31,8 +35,10 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -45,12 +51,17 @@
 # CONFIG_ELF_CORE is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
-CONFIG_SLAB=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 # CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -80,52 +91,9 @@
 #
 # System type
 #
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-CONFIG_SH_7619_SOLUTION_ENGINE=y
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
 CONFIG_CPU_SUBTYPE_SH7619=y
-
-#
-# SH-2A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -133,10 +101,7 @@
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -145,32 +110,28 @@
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 # CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_PAGE_OFFSET=0x00000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -180,34 +141,41 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 CONFIG_SH_WRITETHROUGH=y
-# CONFIG_SH_OCRAM is not set
 
 #
 # Processor features
 #
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_SH_FPU is not set
 # CONFIG_SH_FPU_EMU is not set
 # CONFIG_SH_DSP is not set
+CONFIG_CPU_HAS_IPR_IRQ=y
 
 #
-# Timer support
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7619_SOLUTION_ENGINE=y
+
+#
+# Timer and clock configuration
 #
 CONFIG_SH_CMT=y
 CONFIG_SH_TIMER_IRQ=86
-# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=31250000
 CONFIG_SH_CLK_MD=5
+# CONFIG_TICK_ONESHOT is not set
 
 #
 # CPU Frequency scaling
@@ -222,11 +190,11 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
 #
+# CONFIG_HEARTBEAT is not set
 # CONFIG_PUSH_SWITCH is not set
 
 #
@@ -234,10 +202,11 @@
 #
 CONFIG_HZ_100=y
 # CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=100
 # CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -247,23 +216,18 @@
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
-# CONFIG_UBC_WAKEUP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
 #
 # Bus options
 #
-# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Executable file formats
 #
 CONFIG_BINFMT_FLAT=y
@@ -272,11 +236,6 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 # CONFIG_NET is not set
@@ -295,10 +254,6 @@
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
@@ -313,6 +268,7 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -344,7 +300,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -372,16 +327,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -391,6 +343,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -398,17 +351,12 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
 # Misc devices
 #
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -417,10 +365,6 @@
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -429,19 +373,6 @@
 # CONFIG_MD is not set
 
 #
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
 # ISDN subsystem
 #
 
@@ -471,6 +402,7 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -506,29 +438,15 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -541,26 +459,29 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -569,6 +490,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -583,10 +510,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -668,7 +591,6 @@
 CONFIG_PROC_SYSCTL=y
 # CONFIG_SYSFS is not set
 # CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -682,7 +604,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
@@ -715,14 +636,11 @@
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_UNWIND_INFO is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
 
 #
 # Security options
@@ -737,8 +655,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7722_defconfig b/arch/sh/configs/se7722_defconfig
index ca4c663..764b813 100644
--- a/arch/sh/configs/se7722_defconfig
+++ b/arch/sh/configs/se7722_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc7
-# Fri Apr 27 16:30:30 2007
+# Linux kernel version: 2.6.22-rc4
+# Wed Jun 20 18:08:04 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,7 +11,9 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_NUMA=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -43,6 +45,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
@@ -60,14 +63,20 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -103,57 +112,12 @@
 #
 # System type
 #
-CONFIG_SOLUTION_ENGINE=y
-# CONFIG_SH_SOLUTION_ENGINE is not set
-CONFIG_SH_7722_SOLUTION_ENGINE=y
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7780_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_HIGHLANDER is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_LBOX_RE2 is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
 CONFIG_CPU_SH4=y
 CONFIG_CPU_SH4A=y
 CONFIG_CPU_SH4AL_DSP=y
 CONFIG_CPU_SHX2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -162,10 +126,6 @@
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7710 is not set
 # CONFIG_CPU_SUBTYPE_SH7712 is not set
-
-#
-# SH-4 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7091 is not set
 # CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -174,23 +134,11 @@
 # CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
 # CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 CONFIG_CPU_SUBTYPE_SH7722=y
@@ -198,15 +146,21 @@
 #
 # Memory management options
 #
+CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
-# CONFIG_32BIT is not set
 # CONFIG_X2TLB is not set
 CONFIG_VSYSCALL=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=1
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=2
 CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
@@ -216,26 +170,25 @@
 # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_MEMORY_HOTPLUG is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
 
 #
 # Cache configuration
 #
 # CONFIG_SH_DIRECT_MAPPED is not set
 # CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
 
 #
 # Processor features
@@ -252,12 +205,20 @@
 CONFIG_CPU_HAS_PTEA=y
 
 #
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7722_SOLUTION_ENGINE=y
+
+#
 # Timer and clock configuration
 #
 CONFIG_SH_TMU=y
 CONFIG_SH_TIMER_IRQ=16
-CONFIG_NO_IDLE_HZ=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 
 #
 # CPU Frequency scaling
@@ -272,7 +233,6 @@
 #
 # Companion Chips
 #
-# CONFIG_HD6446X_SERIES is not set
 
 #
 # Additional SuperH Device Drivers
@@ -290,7 +250,6 @@
 CONFIG_HZ=250
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
-# CONFIG_SMP is not set
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
@@ -307,7 +266,11 @@
 #
 # Bus options
 #
-# CONFIG_PCI is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -315,22 +278,12 @@
 # CONFIG_PCCARD is not set
 
 #
-# PCI Hotplug Support
-#
-
-#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
 # Networking
 #
 CONFIG_NET=y
@@ -338,7 +291,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -375,20 +327,8 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -414,7 +354,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -432,10 +381,6 @@
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -464,10 +409,7 @@
 #
 # Misc devices
 #
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 # CONFIG_IDE is not set
 
 #
@@ -496,6 +438,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -511,10 +454,6 @@
 #
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 CONFIG_PATA_PLATFORM=y
@@ -525,19 +464,6 @@
 # CONFIG_MD is not set
 
 #
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -545,10 +471,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -558,27 +480,14 @@
 CONFIG_MII=y
 # CONFIG_STNIC is not set
 CONFIG_SMC91X=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -627,6 +536,7 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -667,14 +577,8 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -682,10 +586,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
 # CONFIG_I2C is not set
 
 #
@@ -698,16 +598,15 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -719,16 +618,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -757,10 +659,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -800,18 +698,30 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
 #
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_SH=y
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
 # DMA Engine support
 #
 # CONFIG_DMA_ENGINE is not set
@@ -825,14 +735,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -937,23 +839,24 @@
 #
 # Profiling support
 #
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
 
 #
 # Kernel hacking
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
 # CONFIG_SH_KGDB is not set
 
 #
@@ -973,8 +876,10 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/shx3_defconfig b/arch/sh/configs/shx3_defconfig
new file mode 100644
index 0000000..219bad5
--- /dev/null
+++ b/arch/sh/configs/shx3_defconfig
@@ -0,0 +1,756 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Wed Jun 20 14:09:27 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_UTS_NS is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX3=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+CONFIG_CPU_SUBTYPE_SHX3=y
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Board support
+#
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 ip=192.168.1.2:::255.255.255.0 root=/dev/nfs nfsroot=192.168.1.1:/exports/devel/rfs/mobiler noaliencache earlyprintk=bios ignore_loglevel"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# Misc devices
+#
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SLAB_LEAK=y
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_LOCKDEP=y
+CONFIG_DEBUG_LOCKDEP=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_VM=y
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_4KSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 99935f9..3338980 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -36,23 +36,6 @@
 	  support. Setting this to a higher value allows for cascading DMACs
 	  with additional channels.
 
-config DMA_PAGE_OPS
-	bool "Use DMAC for page copy/clear"
-	depends on SH_DMA && BROKEN
-	help
-	  Selecting this option will use a dual-address mode configured channel
-	  in the SH DMAC for copy_page()/clear_page(). Primarily a performance
-	  hack.
-
-config DMA_PAGE_OPS_CHANNEL
-	depends on DMA_PAGE_OPS
-	int "DMA channel for sh memory-manager page copy/clear"
-	default "3"
-	help
-	  This allows the specification of the dual address dma channel,
-	  in case channel 3 is unavailable. On the SH4, channels 1,2, and 3
-	  are dual-address capable.
-
 config SH_DMABRG
 	bool "SH7760 DMABRG support"
 	depends on CPU_SUBTYPE_SH7760
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
index e062067..cf8e119 100644
--- a/arch/sh/drivers/dma/dma-api.c
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <asm/dma.h>
 
 DEFINE_SPINLOCK(dma_spin_lock);
@@ -115,7 +116,7 @@
 /**
  * request_dma_bycap - Allocate a DMA channel based on its capabilities
  * @dmac: List of DMA controllers to search
- * @caps: List of capabilites
+ * @caps: List of capabilities
  *
  * Search all channels of all DMA controllers to find a channel which
  * matches the requested capabilities. The result is the channel
diff --git a/arch/sh/drivers/dma/dma-isa.c b/arch/sh/drivers/dma/dma-isa.c
index 05a74ff..5fb044b 100644
--- a/arch/sh/drivers/dma/dma-isa.c
+++ b/arch/sh/drivers/dma/dma-isa.c
@@ -28,7 +28,7 @@
  * NOTE: ops->xfer() is the preferred way of doing things. However, there
  * are some users of the ISA DMA API that exist in common code that we
  * don't necessarily want to go out of our way to break, so we still
- * allow for some compatability at that level. Any new code is strongly
+ * allow for some compatibility at that level. Any new code is strongly
  * advised to run far away from the ISA DMA API and use the SH DMA API
  * directly.
  */
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c
index 9d0a293..5e22689 100644
--- a/arch/sh/drivers/dma/dmabrg.c
+++ b/arch/sh/drivers/dma/dmabrg.c
@@ -33,7 +33,7 @@
  *     9      | HAC1/SSI1 | rec | half done    | DMABRGI2
  *
  * all can be enabled/disabled in the DMABRGCR register,
- * as well as checked if they occured.
+ * as well as checked if they occurred.
  *
  * DMABRGI0 services  USB  DMA  Address  errors,  but it still must be
  * enabled/acked in the DMABRGCR register.  USB-DMA complete indicator
diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig
index 6d1cbbe..fbc6f2c 100644
--- a/arch/sh/drivers/pci/Kconfig
+++ b/arch/sh/drivers/pci/Kconfig
@@ -1,5 +1,6 @@
 config PCI
 	bool "PCI support"
+	depends on SYS_SUPPORTS_PCI
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/sh/drivers/pci/ops-dreamcast.c b/arch/sh/drivers/pci/ops-dreamcast.c
index 381306c..e1284fc 100644
--- a/arch/sh/drivers/pci/ops-dreamcast.c
+++ b/arch/sh/drivers/pci/ops-dreamcast.c
@@ -57,7 +57,7 @@
  *
  * Also, we could very easily support both Type 0 and Type 1 configurations
  * here, but since it doesn't seem that there is any such implementation in
- * existance, we don't bother.
+ * existence, we don't bother.
  *
  * I suppose if someone actually gets around to ripping the chip out of
  * the BBA and hanging some more devices off of it, then this might be
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
index d67656a..543417f 100644
--- a/arch/sh/drivers/pci/pci-st40.c
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -292,7 +292,7 @@
 			    PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
 			    PCI_COMMAND_IO);
 
-	/* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000
+	/* Access to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000
 	 * on the PCI bus. This allows a nice 1-1 bus to phys mapping.
 	 */
 
@@ -315,7 +315,7 @@
 	ST40PCI_WRITE(CSR_MBAR0, 0);
 	ST40PCI_WRITE(LSR0, 0x0fff0001);
 
-	/* ... and set up the initial incomming window to expose all of RAM */
+	/* ... and set up the initial incoming window to expose all of RAM */
 	pci_set_rbar_region(7, memStart, memStart, memSize);
 
 	/* Maximise timeout values */
@@ -473,7 +473,7 @@
 
 	mask = r2p2(regionSize) - 0x10000;
 
-	/* Diable the region (in case currently in use, should never happen) */
+	/* Disable the region (in case currently in use, should never happen) */
 	ST40PCI_WRITE_INDEXED(RSR, region, 0);
 
 	/* Start of local address space to publish */
diff --git a/arch/sh/drivers/pci/pci-st40.h b/arch/sh/drivers/pci/pci-st40.h
index d729e0c..cf0d35b 100644
--- a/arch/sh/drivers/pci/pci-st40.h
+++ b/arch/sh/drivers/pci/pci-st40.h
@@ -4,7 +4,7 @@
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.                            
  *
- * Defintions for the ST40 PCI hardware.
+ * Definitions for the ST40 PCI hardware.
  */
 
 #ifndef __PCI_ST40_H__
diff --git a/arch/sh/drivers/superhyway/ops-sh4-202.c b/arch/sh/drivers/superhyway/ops-sh4-202.c
index a55c98a..3b14bf8 100644
--- a/arch/sh/drivers/superhyway/ops-sh4-202.c
+++ b/arch/sh/drivers/superhyway/ops-sh4-202.c
@@ -130,7 +130,7 @@
 	 * Some modules (PBR and ePBR for instance) also appear to have
 	 * VCRL/VCRH flipped in the documentation, but on the SH4-202
 	 * itself it appears that these are all consistently mapped with
-	 * VCRH preceeding VCRL.
+	 * VCRH preceding VCRL.
 	 *
 	 * Do not trust the documentation, for it is evil.
 	 */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 9104b62..1f141a8 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -4,10 +4,9 @@
 
 extra-y	:= head.o init_task.o vmlinux.lds
 
-obj-y	:= process.o signal.o traps.o irq.o \
-	ptrace.o setup.o time.o sys_sh.o semaphore.o \
-	io.o io_generic.o sh_ksyms.o syscalls.o \
-	debugtraps.o
+obj-y	:= debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \
+	   semaphore.o setup.o signal.o sys_sh.o syscalls.o \
+	   time.o topology.o traps.o
 
 obj-y				+= cpu/ timers/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
@@ -17,7 +16,7 @@
 obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
 obj-$(CONFIG_SH_KGDB)		+= kgdb_stub.o kgdb_jmp.o
 obj-$(CONFIG_SH_CPU_FREQ)	+= cpufreq.o
-obj-$(CONFIG_MODULES)		+= module.o
+obj-$(CONFIG_MODULES)		+= sh_ksyms.o module.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
index 0758d48..1c3b996 100644
--- a/arch/sh/kernel/cf-enabler.c
+++ b/arch/sh/kernel/cf-enabler.c
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -31,7 +32,7 @@
  */
 #if defined(CONFIG_CPU_SH4)
 /* SH4 can't access PCMCIA interface through P2 area.
- * we must remap it with appropreate attribute bit of the page set.
+ * we must remap it with appropriate attribute bit of the page set.
  * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */
 
 #if defined(CONFIG_CF_AREA6)
@@ -74,11 +75,7 @@
 #if defined(CONFIG_CPU_SH4)
 	allocate_cf_area();
 #endif
-#if defined(CONFIG_SH_UNKNOWN)
-	/* This should be done in each board's init_xxx_irq. */
-	make_imask_irq(14);
-	disable_irq(14);
-#endif
+
 	return 0;
 }
 
@@ -149,6 +146,11 @@
 	ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
 	return 0;
 }
+#else
+static int __init cf_init_se(void)
+{
+	return -1;
+}
 #endif
 
 int __init cf_init(void)
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 014f318..6325154 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -278,6 +278,11 @@
 {
 }
 
+void __init __attribute__ ((weak))
+arch_clk_init(void)
+{
+}
+
 static int show_clocks(char *buf, char **start, off_t off,
 		       int len, int *eof, void *data)
 {
@@ -314,6 +319,8 @@
 		ret |= clk_register(clk);
 	}
 
+	arch_clk_init();
+
 	/* Kick the child clocks.. */
 	propagate_rate(&master_clk);
 	propagate_rate(&bus_clk);
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 6451ad6..9172e97 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -21,8 +21,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
 #include <asm/io.h>
-
-extern void detect_cpu_and_cache_system(void);
+#include <asm/ubc.h>
 
 /*
  * Generic wrapper for command line arguments to disable on-chip
@@ -152,15 +151,6 @@
 	flags |= CCR_CACHE_CB;
 #endif
 
-#ifdef CONFIG_SH_OCRAM
-	/* Turn on OCRAM -- halve the OC */
-	flags |= CCR_CACHE_ORA;
-	current_cpu_data.dcache.sets >>= 1;
-
-	current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
-				    current_cpu_data.dcache.linesz;
-#endif
-
 	ctrl_outl(flags, CCR);
 	back_to_P1();
 }
@@ -269,7 +259,6 @@
 	}
 #endif
 
-#ifdef CONFIG_UBC_WAKEUP
 	/*
 	 * Some brain-damaged loaders decided it would be a good idea to put
 	 * the UBC to sleep. This causes some issues when it comes to things
@@ -277,7 +266,5 @@
 	 * we wake it up and hope that all is well.
 	 */
 	ubc_wakeup();
-#endif
-
 	speculative_execution_init();
 }
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index d8e22f4..cc52213 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -13,36 +13,31 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <asm/smp.h>
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define INTC2_BASE	0xfe080000
-#define INTC2_INTMSK	(INTC2_BASE + 0x40)
-#define INTC2_INTMSKCLR	(INTC2_BASE + 0x60)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7785)
-#define INTC2_BASE	0xffd40000
-#define INTC2_INTMSK	(INTC2_BASE + 0x38)
-#define INTC2_INTMSKCLR	(INTC2_BASE + 0x3c)
-#endif
+static inline struct intc2_desc *get_intc2_desc(unsigned int irq)
+{
+	struct irq_chip *chip = get_irq_chip(irq);
+	return (void *)((char *)chip - offsetof(struct intc2_desc, chip));
+}
 
 static void disable_intc2_irq(unsigned int irq)
 {
 	struct intc2_data *p = get_irq_chip_data(irq);
-	ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
+	struct intc2_desc *d = get_intc2_desc(irq);
+
+	ctrl_outl(1 << p->msk_shift, d->msk_base + p->msk_offset +
+				     (hard_smp_processor_id() * 4));
 }
 
 static void enable_intc2_irq(unsigned int irq)
 {
 	struct intc2_data *p = get_irq_chip_data(irq);
-	ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
-}
+	struct intc2_desc *d = get_intc2_desc(irq);
 
-static struct irq_chip intc2_irq_chip = {
-	.name		= "INTC2",
-	.mask		= disable_intc2_irq,
-	.unmask		= enable_intc2_irq,
-	.mask_ack	= disable_intc2_irq,
-};
+	ctrl_outl(1 << p->msk_shift, d->mskclr_base + p->msk_offset +
+				     (hard_smp_processor_id() * 4));
+}
 
 /*
  * Setup an INTC2 style interrupt.
@@ -56,30 +51,36 @@
  *
  * in the intc2_data table.
  */
-void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
+void register_intc2_controller(struct intc2_desc *desc)
 {
 	int i;
 
-	for (i = 0; i < nr_irqs; i++) {
+	desc->chip.mask = disable_intc2_irq;
+	desc->chip.unmask = enable_intc2_irq;
+	desc->chip.mask_ack = disable_intc2_irq;
+
+	for (i = 0; i < desc->nr_irqs; i++) {
 		unsigned long ipr, flags;
-		struct intc2_data *p = table + i;
+		struct intc2_data *p = desc->intc2_data + i;
 
 		disable_irq_nosync(p->irq);
 
-		/* Set the priority level */
-		local_irq_save(flags);
+		if (desc->prio_base) {
+			/* Set the priority level */
+			local_irq_save(flags);
 
-		ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
-		ipr &= ~(0xf << p->ipr_shift);
-		ipr |= p->priority << p->ipr_shift;
-		ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
+			ipr = ctrl_inl(desc->prio_base + p->ipr_offset);
+			ipr &= ~(0xf << p->ipr_shift);
+			ipr |= p->priority << p->ipr_shift;
+			ctrl_outl(ipr, desc->prio_base + p->ipr_offset);
 
-		local_irq_restore(flags);
+			local_irq_restore(flags);
+		}
 
-		set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
+		set_irq_chip_and_handler_name(p->irq, &desc->chip,
 					      handle_level_irq, "level");
 		set_irq_chip_data(p->irq, p);
 
-		enable_intc2_irq(p->irq);
+		disable_intc2_irq(p->irq);
 	}
 }
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 210280b..98e84f4 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -22,58 +22,57 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 
+static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
+{
+	struct irq_chip *chip = get_irq_chip(irq);
+	return (void *)((char *)chip - offsetof(struct ipr_desc, chip));
+}
+
 static void disable_ipr_irq(unsigned int irq)
 {
 	struct ipr_data *p = get_irq_chip_data(irq);
+	unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
 	/* Set the priority in IPR to 0 */
-	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
+	ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr);
 }
 
 static void enable_ipr_irq(unsigned int irq)
 {
 	struct ipr_data *p = get_irq_chip_data(irq);
+	unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
 	/* Set priority in IPR back to original value */
-	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
+	ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr);
 }
 
-static struct irq_chip ipr_irq_chip = {
-	.name		= "IPR",
-	.mask		= disable_ipr_irq,
-	.unmask		= enable_ipr_irq,
-	.mask_ack	= disable_ipr_irq,
-};
+/*
+ * The shift value is now the number of bits to shift, not the number of
+ * bits/4. This is to make it easier to read the value directly from the
+ * datasheets. The IPR address is calculated using the ipr_offset table.
+ */
 
-unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak));
-unsigned int map_ipridx_to_addr(int idx)
-{
-	return 0;
-}
-
-void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
+void register_ipr_controller(struct ipr_desc *desc)
 {
 	int i;
 
-	for (i = 0; i < nr_irqs; i++) {
-		unsigned int irq = table[i].irq;
+	desc->chip.mask = disable_ipr_irq;
+	desc->chip.unmask = enable_ipr_irq;
+	desc->chip.mask_ack = disable_ipr_irq;
 
-		if (!irq)
-			irq = table[i].irq = i;
+	for (i = 0; i < desc->nr_irqs; i++) {
+		struct ipr_data *p = desc->ipr_data + i;
 
-		/* could the IPR index be mapped, if not we ignore this */
-		if (!table[i].addr) {
-			table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
-			if (!table[i].addr)
-				continue;
-		}
+		BUG_ON(p->ipr_idx >= desc->nr_offsets);
+		BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
 
-		disable_irq_nosync(irq);
-		set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
+		disable_irq_nosync(p->irq);
+		set_irq_chip_and_handler_name(p->irq, &desc->chip,
 				      handle_level_irq, "level");
-		set_irq_chip_data(irq, &table[i]);
-		enable_ipr_irq(irq);
+		set_irq_chip_data(p->irq, p);
+		disable_ipr_irq(p->irq);
 	}
 }
-EXPORT_SYMBOL(make_ipr_irq);
+
+EXPORT_SYMBOL(register_ipr_controller);
 
 #if !defined(CONFIG_CPU_HAS_PINT_IRQ)
 int ipr_irq_demux(int irq)
diff --git a/arch/sh/kernel/cpu/irq/maskreg.c b/arch/sh/kernel/cpu/irq/maskreg.c
index 492db31..978992e 100644
--- a/arch/sh/kernel/cpu/irq/maskreg.c
+++ b/arch/sh/kernel/cpu/irq/maskreg.c
@@ -38,7 +38,7 @@
 	.end = end_maskreg_irq
 };
 
-/* actual implementatin */
+/* actual implementation */
 static unsigned int startup_maskreg_irq(unsigned int irq)
 {
 	enable_maskreg_irq(irq);
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index c16dc8f..ee8f1fe 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -311,6 +311,7 @@
 	rte
 	 nop
 
+	.align 2
 #ifdef CONFIG_TRACE_IRQFLAGS
 1:     .long   trace_hardirqs_off
 #endif
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index 108e81b..abbf174 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -9,23 +9,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
-
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 
 int __init detect_cpu_and_cache_system(void)
 {
-#if defined(CONFIG_CPU_SUBTYPE_SH7604)
-	current_cpu_data.type			= CPU_SH7604;
-	current_cpu_data.dcache.ways		= 4;
-	current_cpu_data.dcache.way_incr	= (1<<10);
-	current_cpu_data.dcache.sets		= 64;
-	current_cpu_data.dcache.entry_shift	= 4;
-	current_cpu_data.dcache.linesz		= L1_CACHE_BYTES;
-	current_cpu_data.dcache.flags		= 0;
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+#if defined(CONFIG_CPU_SUBTYPE_SH7619)
 	current_cpu_data.type			= CPU_SH7619;
 	current_cpu_data.dcache.ways		= 4;
 	current_cpu_data.dcache.way_incr	= (1<<12);
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index f83ff8a..1a107fe 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -52,7 +52,7 @@
 }
 __initcall(sh7619_devices_setup);
 
-static struct ipr_data sh7619_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	{ 86, 0,  4, 2 },	/* CMI0 */
 	{ 88, 1, 12, 3 },	/* SCIF0_ERI */
 	{ 89, 1, 12, 3 },	/* SCIF0_RXI */
@@ -68,7 +68,7 @@
 	{ 99, 1,  4, 3 },	/* SCIF2_TXI */
 };
 
-static unsigned int ipr_offsets[] = {
+static unsigned long ipr_offsets[] = {
 	0xf8080000,	/* IPRC */
 	0xf8080002,	/* IPRD */
 	0xf8080004,	/* IPRE */
@@ -76,15 +76,19 @@
 	0xf8080008,	/* IPRG */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7619",
+	},
+};
 
 void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index 4ed9110..b6e3a63 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -57,7 +57,7 @@
 }
 __initcall(sh7206_devices_setup);
 
-static struct ipr_data sh7206_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	{ 140,  7, 12, 2 },	/* CMI0 */
 	{ 164,  8,  4, 2 },	/* MTU2_TGI1A */
 	{ 240, 13, 12, 3 },	/* SCIF0_BRI */
@@ -78,7 +78,7 @@
 	{ 255, 13,  0, 3 },	/* SCIF3_TXI */
 };
 
-static unsigned int ipr_offsets[] = {
+static unsigned long ipr_offsets[] = {
 	0xfffe0818,	/* IPR01 */
 	0xfffe081a,	/* IPR02 */
 	0,		/* unused */
@@ -95,15 +95,19 @@
 	0xfffe0c10,	/* IPR14 */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7206",
+	},
+};
 
 void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 832c0b4..d8e1229 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -320,6 +320,9 @@
 
 	.align	2
 5:	.long	0x00001000	! DSP
+#ifdef CONFIG_KGDB_NMI
+6:	.long	in_nmi
+#endif
 7:	.long	0x30000000
 
 ! common exception handler
@@ -337,8 +340,27 @@
 general_exception:
 	mov.l	1f, k2
 	mov.l	2f, k3
+#ifdef CONFIG_CPU_SUBTYPE_SHX3
+	mov.l	@k2, k2
+
+	! Is EXPEVT larger than 0x800?
+	mov	#0x8, k0
+	shll8	k0
+	cmp/hs	k0, k2
+	bf	0f
+
+	! then add 0x580 (k2 is 0xd80 or 0xda0)
+	mov	#0x58, k0
+	shll2	k0
+	shll2	k0
+	add	k0, k2
+0:
+	bra	handle_exception
+	 nop
+#else
 	bra	handle_exception
 	 mov.l	@k2, k2
+#endif
 	.align	2
 1:	.long	EXPEVT
 2:	.long	ret_from_exception
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index 1983fb7..a55b8ce 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -48,7 +48,7 @@
 }
 __initcall(sh7705_devices_setup);
 
-static struct ipr_data sh7705_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
 	{ 17, 0,  8, 2 }, /* TMU1 TUNI */
@@ -70,25 +70,29 @@
 };
 
 static unsigned long ipr_offsets[] = {
-	0xFFFFFEE2	/* 0: IPRA */
-,	0xFFFFFEE4	/* 1: IPRB */
-,	0xA4000016	/* 2: IPRC */
-,	0xA4000018	/* 3: IPRD */
-,	0xA400001A	/* 4: IPRE */
-,	0xA4080000	/* 5: IPRF */
-,	0xA4080002	/* 6: IPRG */
-,	0xA4080004	/* 7: IPRH */
+	0xFFFFFEE2,	/* 0: IPRA */
+	0xFFFFFEE4,	/* 1: IPRB */
+	0xA4000016,	/* 2: IPRC */
+	0xA4000018,	/* 3: IPRD */
+	0xA400001A,	/* 4: IPRE */
+	0xA4080000,	/* 5: IPRF */
+	0xA4080002,	/* 6: IPRG */
+	0xA4080004,	/* 7: IPRH */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (idx >= ARRAY_SIZE(ipr_offsets))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
 
-void __init init_IRQ_ipr()
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7705",
+	},
+};
+
+void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7705_ipr_map, ARRAY_SIZE(sh7705_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
index c7d7c35..d79ec0c 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
@@ -12,6 +12,26 @@
 #include <linux/serial.h>
 #include <asm/sci.h>
 
+static struct resource rtc_resources[] = {
+	[0] =	{
+		.start	= 0xfffffec0,
+		.end	= 0xfffffec0 + 0x1e,
+		.flags  = IORESOURCE_IO,
+	},
+	[1] =	{
+		.start  = 20,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] =	{
+		.start	= 21,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] =	{
+		.start	= 22,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xfffffe80,
@@ -41,8 +61,16 @@
 	},
 };
 
+static struct platform_device rtc_device = {
+	.name		= "sh-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rtc_resources),
+	.resource	= rtc_resources,
+};
+
 static struct platform_device *sh7709_devices[] __initdata = {
 	&sci_device,
+	&rtc_device,
 };
 
 static int __init sh7709_devices_setup(void)
@@ -52,32 +80,66 @@
 }
 __initcall(sh7709_devices_setup);
 
-#define IPRx(A,N)	.addr=A, .shift=N
-#define IPRA(N)	IPRx(0xfffffee2UL,N)
-#define IPRB(N)	IPRx(0xfffffee4UL,N)
-#define IPRC(N)	IPRx(0xa4000016UL,N)
-#define IPRD(N)	IPRx(0xa4000018UL,N)
-#define IPRE(N)	IPRx(0xa400001aUL,N)
+static struct ipr_data ipr_irq_table[] = {
+	{ 16, 0, 12, 2 }, /* TMU TUNI0 */
+	{ 17, 0, 8,  4 }, /* TMU TUNI1 */
+	{ 18, 0, 4,  1 }, /* TMU TUNI1 */
+	{ 19, 0, 4,  1 }, /* TMU TUNI1 */
+	{ 20, 0, 0,  2 }, /* RTC CUI */
+	{ 21, 0, 0,  2 }, /* RTC CUI */
+	{ 22, 0, 0,  2 }, /* RTC CUI */
 
-static struct ipr_data sh7709_ipr_map[] = {
-	[16]		= { IPRA(12), 2 }, /* TMU TUNI0 */
-	[17]		= { IPRA(8),  4 }, /* TMU TUNI1 */
-	[18 ... 19]	= { IPRA(4),  1 }, /* TMU TUNI1 */
-	[20 ... 22]	= { IPRA(0),  2 }, /* RTC CUI */
-	[23 ... 26]	= { IPRB(4),  3 }, /* SCI */
-	[27]		= { IPRB(12), 2 }, /* WDT ITI */
-	[32]		= { IPRC(0),  1 }, /* IRQ 0 */
-	[33]		= { IPRC(4),  1 }, /* IRQ 1 */
-	[34]		= { IPRC(8),  1 }, /* IRQ 2 APM */
-	[35]		= { IPRC(12), 1 }, /* IRQ 3 TOUCHSCREEN */
-	[36]		= { IPRD(0),  1 }, /* IRQ 4 */
-	[37]		= { IPRD(4),  1 }, /* IRQ 5 */
-	[48 ... 51]	= { IPRE(12), 7 }, /* DMA */
-	[52 ... 55]	= { IPRE(8),  3 }, /* IRDA */
-	[56 ... 59]	= { IPRE(4),  3 }, /* SCIF */
+	{ 23, 1, 4,  3 }, /* SCI */
+	{ 24, 1, 4,  3 }, /* SCI */
+	{ 25, 1, 4,  3 }, /* SCI */
+	{ 26, 1, 4,  3 }, /* SCI */
+	{ 27, 1, 12, 3 }, /* WDT ITI */
+
+	{ 32, 2, 0,  1 }, /* IRQ 0 */
+	{ 33, 2, 4,  1 }, /* IRQ 1 */
+	{ 34, 2, 8,  1 }, /* IRQ 2 APM */
+	{ 35, 2, 12, 1 }, /* IRQ 3 TOUCHSCREEN */
+
+	{ 36, 3, 0,  1 }, /* IRQ 4 */
+	{ 37, 3, 4,  1 }, /* IRQ 5 */
+
+	{ 48, 4, 12, 7 }, /* DMA */
+	{ 49, 4, 12, 7 }, /* DMA */
+	{ 50, 4, 12, 7 }, /* DMA */
+	{ 51, 4, 12, 7 }, /* DMA */
+
+	{ 52, 4, 8,  3 }, /* IRDA */
+	{ 53, 4, 8,  3 }, /* IRDA */
+	{ 54, 4, 8,  3 }, /* IRDA */
+	{ 55, 4, 8,  3 }, /* IRDA */
+
+	{ 56, 4, 4,  3 }, /* SCIF */
+	{ 57, 4, 4,  3 }, /* SCIF */
+	{ 58, 4, 4,  3 }, /* SCIF */
+	{ 59, 4, 4,  3 }, /* SCIF */
 };
 
-void __init init_IRQ_ipr()
+static unsigned long ipr_offsets[] = {
+	0xfffffee2,	/* 0: IPRA */
+	0xfffffee4,	/* 1: IPRB */
+	0xa4000016,	/* 2: IPRC */
+	0xa4000018,	/* 3: IPRD */
+	0xa400001a,	/* 4: IPRE */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7709",
+	},
+};
+
+void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 51760a7..f40e6da 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -49,7 +49,7 @@
 }
 __initcall(sh7710_devices_setup);
 
-static struct ipr_data sh7710_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
 	{ 17, 0,  8, 2 }, /* TMU1 TUNI */
@@ -78,26 +78,30 @@
 };
 
 static unsigned long ipr_offsets[] = {
-	0xA414FEE2	/* 0: IPRA */
-,	0xA414FEE4	/* 1: IPRB */
-,	0xA4140016	/* 2: IPRC */
-,	0xA4140018	/* 3: IPRD */
-,	0xA414001A	/* 4: IPRE */
-,	0xA4080000	/* 5: IPRF */
-,	0xA4080002	/* 6: IPRG */
-,	0xA4080004	/* 7: IPRH */
-,	0xA4080006	/* 8: IPRI */
+	0xA414FEE2,	/* 0: IPRA */
+	0xA414FEE4,	/* 1: IPRB */
+	0xA4140016,	/* 2: IPRC */
+	0xA4140018,	/* 3: IPRD */
+	0xA414001A,	/* 4: IPRE */
+	0xA4080000,	/* 5: IPRF */
+	0xA4080002,	/* 6: IPRG */
+	0xA4080004,	/* 7: IPRH */
+	0xA4080006,	/* 8: IPRI */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (idx >= ARRAY_SIZE(ipr_offsets))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
 
-void __init init_IRQ_ipr()
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7710",
+	},
+};
+
+void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7710_ipr_map, ARRAY_SIZE(sh7710_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 8add10b..dadd6bf 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -10,7 +10,11 @@
 
 # CPU subtype setup
 obj-$(CONFIG_CPU_SUBTYPE_SH7750)	+= setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7750R)	+= setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7750S)	+= setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7091)	+= setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751R)	+= setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7760)	+= setup-sh7760.o
 obj-$(CONFIG_CPU_SUBTYPE_SH4_202)	+= setup-sh4-202.o
 
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index fcb2c41b..a334294 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -111,7 +111,7 @@
 	return 0;
 }
 
-static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
+static int shoc_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id)
 {
 	unsigned long frqcr3;
 	unsigned int tmp;
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index d61dd59..c5a4fc7 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -138,7 +138,7 @@
 /*
  * Load the FPU with signalling NANS.  This bit pattern we're using
  * has the property that no matter wether considered as single or as
- * double precission represents signaling NANS.  
+ * double precision represents signaling NANS.  
  */
 
 static void
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 8cd0490..66c3f75 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -12,6 +12,7 @@
  */
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/smp.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 
@@ -140,6 +141,14 @@
 			current_cpu_data.flags |= CPU_HAS_LLSC;
 		}
 		break;
+	case 0x4000:	/* 1st cut */
+	case 0x4001:	/* 2nd cut */
+		current_cpu_data.type = CPU_SHX3;
+		current_cpu_data.icache.ways = 4;
+		current_cpu_data.dcache.ways = 4;
+		current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+					  CPU_HAS_LLSC;
+		break;
 	case 0x8000:
 		current_cpu_data.type = CPU_ST40RA;
 		current_cpu_data.flags |= CPU_HAS_FPU;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index 6f8f458..da153bc 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -82,7 +82,7 @@
 }
 __initcall(sh7750_devices_setup);
 
-static struct ipr_data sh7750_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
 	{ 17, 0, 12, 2 }, /* TMU1 TUNI */
@@ -106,7 +106,27 @@
 	{ 38, 2,  8, 7 }, /* DMAC DMAE */
 };
 
-static struct ipr_data sh7751_ipr_map[] = {
+static unsigned long ipr_offsets[] = {
+	0xffd00004UL,	/* 0: IPRA */
+	0xffd00008UL,	/* 1: IPRB */
+	0xffd0000cUL,	/* 2: IPRC */
+	0xffd00010UL,	/* 3: IPRD */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7750",
+	},
+};
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7751
+static struct ipr_data ipr_irq_table_sh7751[] = {
 	{ 44, 2,  8, 7 }, /* DMAC DMTE4 */
 	{ 45, 2,  8, 7 }, /* DMAC DMTE5 */
 	{ 46, 2,  8, 7 }, /* DMAC DMTE6 */
@@ -118,19 +138,25 @@
 	/*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
 };
 
-static unsigned long ipr_offsets[] = {
-	0xffd00004UL,	/* 0: IPRA */
-	0xffd00008UL,	/* 1: IPRB */
-	0xffd0000cUL,	/* 2: IPRC */
-	0xffd00010UL,	/* 3: IPRD */
-};
+static struct ipr_desc ipr_irq_desc_sh7751 = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
+	.ipr_data	= ipr_irq_table_sh7751,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table_sh7751),
+
+	.chip = {
+		.name	= "IPR-sh7751",
+	},
+};
+#endif
+
+void __init init_IRQ_ipr(void)
 {
-	if (idx >= ARRAY_SIZE(ipr_offsets))
-		return 0;
-	return ipr_offsets[idx];
+	register_ipr_controller(&ipr_irq_desc);
+#ifdef CONFIG_CPU_SUBTYPE_SH7751
+	register_ipr_controller(&ipr_irq_desc_sh7751);
+#endif
 }
 
 #define INTC_ICR	0xffd00000UL
@@ -141,11 +167,3 @@
 {
 	ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
 }
-
-void __init init_IRQ_ipr()
-{
-	make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
-#ifdef CONFIG_CPU_SUBTYPE_SH7751
-	make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
-#endif
-}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index b7c7028..3df1697 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -96,7 +96,25 @@
 	{109,12,  0, 4,  0,  3},	/* CMTI */
 };
 
-static struct ipr_data sh7760_ipr_map[] = {
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0xfe080000,
+	.msk_base	= 0xfe080040,
+	.mskclr_base	= 0xfe080060,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-sh7760",
+	},
+};
+
+void __init init_IRQ_intc2(void)
+{
+	register_intc2_controller(&intc2_irq_desc);
+}
+
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
 	{ 17, 0,  8, 2 }, /* TMU1 TUNI */
@@ -133,20 +151,19 @@
 	0xffd00010UL,	/* 3: IPRD */
 };
 
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (idx >= ARRAY_SIZE(ipr_offsets))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
 
-void __init init_IRQ_intc2(void)
-{
-	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
-}
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
 
-void __init  init_IRQ_ipr(void)
+	.chip = {
+		.name	= "IPR-sh7760",
+	},
+};
+
+void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index ab7422f..4006232 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_CPU_SUBTYPE_SH73180)	+= setup-sh73180.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7343)	+= setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7722)	+= setup-sh7722.o
+obj-$(CONFIG_CPU_SUBTYPE_SHX3)		+= setup-shx3.o
 
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SUBTYPE_SH73180)	:= clock-sh73180.o
@@ -17,5 +18,6 @@
 clock-$(CONFIG_CPU_SUBTYPE_SH7785)	:= clock-sh7785.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7343.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SHX3)	:= clock-shx3.o
 
 obj-y	+= $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 2909003..51b386d 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -17,7 +17,6 @@
 #include <asm/clock.h>
 #include <asm/freq.h>
 
-#define SH7722_PLL_FREQ (32000000/8)
 #define N  (-1)
 #define NM (-2)
 #define ROUND_NEAREST 0
@@ -141,28 +140,36 @@
 */
 static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 };
 
-static void master_clk_init(struct clk *clk)
+static void master_clk_recalc(struct clk *clk)
 {
-	clk_set_rate(clk, clk_get_rate(clk));
+	unsigned frqcr = ctrl_inl(FRQCR);
+
+	clk->rate = CONFIG_SH_PCLK_FREQ * (((frqcr >> 24) & 0x1f) + 1);
 }
 
-static void master_clk_recalc(struct clk *clk)
+static void master_clk_init(struct clk *clk)
+{
+	clk->parent = NULL;
+	clk->flags |= CLK_RATE_PROPAGATES;
+	clk->rate = CONFIG_SH_PCLK_FREQ;
+	master_clk_recalc(clk);
+}
+
+
+static void module_clk_recalc(struct clk *clk)
 {
 	unsigned long frqcr = ctrl_inl(FRQCR);
 
-	clk->rate = CONFIG_SH_PCLK_FREQ * (1 + (frqcr >> 24 & 0xF));
+	clk->rate = clk->parent->rate / (((frqcr >> 24) & 0x1f) + 1);
 }
 
 static int master_clk_setrate(struct clk *clk, unsigned long rate, int id)
 {
-	int div = rate / SH7722_PLL_FREQ;
+	int div = rate / clk->rate;
 	int master_divs[] = { 2, 3, 4, 6, 8, 16 };
 	int index;
 	unsigned long frqcr;
 
-	if (rate < SH7722_PLL_FREQ * 2)
-		return -EINVAL;
-
 	for (index = 1; index < ARRAY_SIZE(master_divs); index++)
 		if (div >= master_divs[index - 1] && div < master_divs[index])
 			break;
@@ -185,6 +192,10 @@
 	.set_rate = master_clk_setrate,
 };
 
+static struct clk_ops sh7722_module_clk_ops = {
+       .recalc = module_clk_recalc,
+};
+
 struct frqcr_context {
 	unsigned mask;
 	unsigned shift;
@@ -489,7 +500,7 @@
 
 	if (siu < 0)
 		return /* siu */ ;
-	BUG_ON(siu > 1);
+	BUG_ON(siu > 2);
 	r = ctrl_inl(sh7722_siu_regs[siu]);
 	clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
 }
@@ -571,7 +582,7 @@
  */
 struct clk_ops *onchip_ops[] = {
 	&sh7722_master_clk_ops,
-	&sh7722_frqcr_clk_ops,
+	&sh7722_module_clk_ops,
 	&sh7722_frqcr_clk_ops,
 	&sh7722_frqcr_clk_ops,
 };
@@ -583,7 +594,7 @@
 	*ops = onchip_ops[type];
 }
 
-int __init sh7722_clock_init(void)
+int __init arch_clk_init(void)
 {
 	struct clk *master;
 	int i;
@@ -597,4 +608,3 @@
 	clk_put(master);
 	return 0;
 }
-arch_initcall(sh7722_clock_init);
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
new file mode 100644
index 0000000..c630b29
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
@@ -0,0 +1,135 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-shx3.c
+ *
+ * SH-X3 support for the clock framework
+ *
+ *  Copyright (C) 2006-2007  Renesas Technology Corp.
+ *  Copyright (C) 2006-2007  Renesas Solutions Corp.
+ *  Copyright (C) 2006-2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int ifc_divisors[] = { 1, 2, 4 ,6 };
+static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
+static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 };
+static int cfc_divisors[] = { 1, 1, 4, 6 };
+
+#define IFC_POS		28
+#define IFC_MSK		0x0003
+#define BFC_MSK		0x000f
+#define PFC_MSK		0x000f
+#define CFC_MSK		0x0003
+#define BFC_POS		16
+#define PFC_POS		0
+#define CFC_POS		20
+
+static void master_clk_init(struct clk *clk)
+{
+	clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK];
+}
+
+static struct clk_ops shx3_master_clk_ops = {
+	.init		= master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK);
+	clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops shx3_module_clk_ops = {
+	.recalc		= module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK);
+	clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops shx3_bus_clk_ops = {
+	.recalc		= bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK);
+	clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops shx3_cpu_clk_ops = {
+	.recalc		= cpu_clk_recalc,
+};
+
+static struct clk_ops *shx3_clk_ops[] = {
+	&shx3_master_clk_ops,
+	&shx3_module_clk_ops,
+	&shx3_bus_clk_ops,
+	&shx3_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+	if (idx < ARRAY_SIZE(shx3_clk_ops))
+		*ops = shx3_clk_ops[idx];
+}
+
+static void shyway_clk_recalc(struct clk *clk)
+{
+	int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK);
+	clk->rate = clk->parent->rate / cfc_divisors[idx];
+}
+
+static struct clk_ops shx3_shyway_clk_ops = {
+	.recalc		= shyway_clk_recalc,
+};
+
+static struct clk shx3_shyway_clk = {
+	.name		= "shyway_clk",
+	.flags		= CLK_ALWAYS_ENABLED,
+	.ops		= &shx3_shyway_clk_ops,
+};
+
+/*
+ * Additional SHx3-specific on-chip clocks that aren't already part of the
+ * clock framework
+ */
+static struct clk *shx3_onchip_clocks[] = {
+	&shx3_shyway_clk,
+};
+
+static int __init shx3_clk_init(void)
+{
+	struct clk *clk = clk_get(NULL, "master_clk");
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
+		struct clk *clkp = shx3_onchip_clocks[i];
+
+		clkp->parent = clk;
+		clk_register(clkp);
+		clk_enable(clkp);
+	}
+
+	/*
+	 * Now that we have the rest of the clocks registered, we need to
+	 * force the parent clock to propagate so that these clocks will
+	 * automatically figure out their rate. We cheat by handing the
+	 * parent clock its current rate and forcing child propagation.
+	 */
+	clk_set_rate(clk, clk_get_rate(clk));
+
+	clk_put(clk);
+
+	return 0;
+}
+arch_initcall(shx3_clk_init);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 1143fbf..a3e159e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -1,7 +1,7 @@
 /*
  * SH7722 Setup
  *
- *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2006 - 2007  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -10,6 +10,8 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/serial.h>
+#include <linux/mm.h>
+#include <asm/mmzone.h>
 #include <asm/sci.h>
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -42,7 +44,7 @@
 }
 __initcall(sh7722_devices_setup);
 
-static struct ipr_data sh7722_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, prio */
 	{ 16, 0, 12, 2 }, /* TMU0 */
 	{ 17, 0,  8, 2 }, /* TMU1 */
@@ -67,14 +69,25 @@
 	0xa408002c, /* 11: IPRL */
 };
 
-unsigned int map_ipridx_to_addr(int idx)
-{
-	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
-		return 0;
-	return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+	.ipr_offsets	= ipr_offsets,
+	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
+
+	.ipr_data	= ipr_irq_table,
+	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
+
+	.chip = {
+		.name	= "IPR-sh7722",
+	},
+};
 
 void __init init_IRQ_ipr(void)
 {
-	make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
+	register_ipr_controller(&ipr_irq_desc);
+}
+
+void __init plat_mem_setup(void)
+{
+	/* Register the URAM space as Node 1 */
+	setup_bootmem_node(1, 0x055f0000, 0x05610000);
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 9aeaa2d..b57c760 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -102,7 +102,20 @@
 	{ 68, 0x14,  8, 0, 18, 2 },	/* PCIC4 */
 };
 
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0xffd40000,
+	.msk_base	= 0xffd40038,
+	.mskclr_base	= 0xffd4003c,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-sh7780",
+	},
+};
+
 void __init init_IRQ_intc2(void)
 {
-	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+	register_intc2_controller(&intc2_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 07b0de8..ce10ec5 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -97,7 +97,21 @@
 	{ 60, 12, 16, 0, 7, 3 },	/* SCIF5 ERI, RXI, BRI, TXI */
 };
 
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0xffd40000,
+	.msk_base	= 0xffd40038,
+	.mskclr_base	= 0xffd4003c,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-sh7785",
+	},
+};
+
 void __init init_IRQ_intc2(void)
 {
-	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+	register_intc2_controller(&intc2_irq_desc);
 }
+
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
new file mode 100644
index 0000000..70683ea
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -0,0 +1,85 @@
+/*
+ * SH-X3 Setup
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/io.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+	{
+		.mapbase	= 0xffc30000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 40, 41, 43, 42 },
+	}, {
+		.mapbase	= 0xffc40000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 44, 45, 47, 46 },
+	}, {
+		.mapbase	= 0xffc50000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 48, 49, 51, 50 },
+	}, {
+		.mapbase	= 0xffc60000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 52, 53, 55, 54 },
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct platform_device sci_device = {
+	.name		= "sh-sci",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= sci_platform_data,
+	},
+};
+
+static struct platform_device *shx3_devices[] __initdata = {
+	&sci_device,
+};
+
+static int __init shx3_devices_setup(void)
+{
+	return platform_add_devices(shx3_devices,
+				    ARRAY_SIZE(shx3_devices));
+}
+__initcall(shx3_devices_setup);
+
+static struct intc2_data intc2_irq_table[] = {
+	{ 16, 0, 0, 0, 1, 2 },		/* TMU0 */
+	{ 40, 4, 0, 0x20, 0, 3 },	/* SCIF0 ERI */
+	{ 41, 4, 0, 0x20, 1, 3 },	/* SCIF0 RXI */
+	{ 42, 4, 0, 0x20, 2, 3 },	/* SCIF0 BRI */
+	{ 43, 4, 0, 0x20, 3, 3 },	/* SCIF0 TXI */
+};
+
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+	.prio_base	= 0xfe410000,
+	.msk_base	= 0xfe410820,
+	.mskclr_base	= 0xfe410850,
+
+	.intc2_data	= intc2_irq_table,
+	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
+
+	.chip = {
+		.name	= "INTC2-SHX3",
+	},
+};
+
+void __init init_IRQ_intc2(void)
+{
+	register_intc2_controller(&intc2_irq_desc);
+}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 27b923c..2789779 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -158,15 +158,11 @@
 }
 
 #ifdef CONFIG_4KSTACKS
-/*
- * These should really be __section__(".bss.page_aligned") as well, but
- * gcc's 3.0 and earlier don't handle that correctly.
- */
 static char softirq_stack[NR_CPUS * THREAD_SIZE]
-		__attribute__((__aligned__(THREAD_SIZE)));
+		__attribute__((__section__(".bss.page_aligned")));
 
 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
-		__attribute__((__aligned__(THREAD_SIZE)));
+		__attribute__((__section__(".bss.page_aligned")));
 
 /*
  * allocate per-cpu stacks for hardirq and for softirq processing
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c
index a532336..edd1ec2 100644
--- a/arch/sh/kernel/kgdb_stub.c
+++ b/arch/sh/kernel/kgdb_stub.c
@@ -2,7 +2,7 @@
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
  *
- * Containes extracts from code by Glenn Engel, Jim Kingdon,
+ * Contains extracts from code by Glenn Engel, Jim Kingdon,
  * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
  * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
  * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
@@ -85,7 +85,7 @@
  *
  * Responses can be run-length encoded to save space.  A '*' means that
  * the next character is an ASCII encoding giving a repeat count which
- * stands for that many repititions of the character preceding the '*'.
+ * stands for that many repetitions of the character preceding the '*'.
  * The encoding is n+29, yielding a printable character where n >=3
  * (which is where RLE starts to win).  Don't use an n > 126.
  *
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c
new file mode 100644
index 0000000..23c5948
--- /dev/null
+++ b/arch/sh/kernel/machvec.c
@@ -0,0 +1,130 @@
+/*
+ * arch/sh/kernel/machvec.c
+ *
+ * The SuperH machine vector setup handlers, yanked from setup.c
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *  Copyright (C) 2002 - 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/machvec.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define MV_NAME_SIZE 32
+
+#define for_each_mv(mv) \
+	for ((mv) = (struct sh_machine_vector *)&__machvec_start; \
+	     (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \
+	     (mv)++)
+
+static struct sh_machine_vector * __init get_mv_byname(const char *name)
+{
+	struct sh_machine_vector *mv;
+
+	for_each_mv(mv)
+		if (strcasecmp(name, mv->mv_name) == 0)
+			return mv;
+
+	return NULL;
+}
+
+static unsigned int __initdata machvec_selected;
+
+static int __init early_parse_mv(char *from)
+{
+	char mv_name[MV_NAME_SIZE] = "";
+	char *mv_end;
+	char *mv_comma;
+	int mv_len;
+	struct sh_machine_vector *mvp;
+
+	mv_end = strchr(from, ' ');
+	if (mv_end == NULL)
+		mv_end = from + strlen(from);
+
+	mv_comma = strchr(from, ',');
+	mv_len = mv_end - from;
+	if (mv_len > (MV_NAME_SIZE-1))
+		mv_len = MV_NAME_SIZE-1;
+	memcpy(mv_name, from, mv_len);
+	mv_name[mv_len] = '\0';
+	from = mv_end;
+
+	machvec_selected = 1;
+
+	/* Boot with the generic vector */
+	if (strcmp(mv_name, "generic") == 0)
+		return 0;
+
+	mvp = get_mv_byname(mv_name);
+	if (unlikely(!mvp)) {
+		printk("Available vectors:\n\n\t'%s', ", sh_mv.mv_name);
+		for_each_mv(mvp)
+			printk("'%s', ", mvp->mv_name);
+		printk("\n\n");
+		panic("Failed to select machvec '%s' -- halting.\n",
+		      mv_name);
+	} else
+		sh_mv = *mvp;
+
+	return 0;
+}
+early_param("sh_mv", early_parse_mv);
+
+void __init sh_mv_setup(void)
+{
+	/*
+	 * Only overload the machvec if one hasn't been selected on
+	 * the command line with sh_mv=
+	 */
+	if (!machvec_selected) {
+		unsigned long machvec_size;
+
+		machvec_size = ((unsigned long)&__machvec_end -
+				(unsigned long)&__machvec_start);
+
+		/*
+		 * If the machvec hasn't been preselected, use the first
+		 * vector (usually the only one) from .machvec.init.
+		 */
+		if (machvec_size >= sizeof(struct sh_machine_vector))
+			sh_mv = *(struct sh_machine_vector *)&__machvec_start;
+	}
+
+	printk(KERN_NOTICE "Booting machvec: %s\n", get_system_type());
+
+	/*
+	 * Manually walk the vec, fill in anything that the board hasn't yet
+	 * by hand, wrapping to the generic implementation.
+	 */
+#define mv_set(elem) do { \
+	if (!sh_mv.mv_##elem) \
+		sh_mv.mv_##elem = generic_##elem; \
+} while (0)
+
+	mv_set(inb);	mv_set(inw);	mv_set(inl);
+	mv_set(outb);	mv_set(outw);	mv_set(outl);
+
+	mv_set(inb_p);	mv_set(inw_p);	mv_set(inl_p);
+	mv_set(outb_p);	mv_set(outw_p);	mv_set(outl_p);
+
+	mv_set(insb);	mv_set(insw);	mv_set(insl);
+	mv_set(outsb);	mv_set(outsw);	mv_set(outsl);
+
+	mv_set(readb);	mv_set(readw);	mv_set(readl);
+	mv_set(writeb);	mv_set(writew);	mv_set(writel);
+
+	mv_set(ioport_map);
+	mv_set(ioport_unmap);
+	mv_set(irq_demux);
+
+	if (!sh_mv.mv_nr_irqs)
+		sh_mv.mv_nr_irqs = NR_IRQS;
+}
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 6b4f574..6334a4c 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -17,6 +17,7 @@
 #include <linux/kexec.h>
 #include <linux/kdebug.h>
 #include <linux/tick.h>
+#include <linux/reboot.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
@@ -26,8 +27,6 @@
 static int hlt_counter;
 int ubc_usercnt = 0;
 
-#define HARD_IDLE_TIMEOUT (HZ / 3)
-
 void (*pm_idle)(void);
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
@@ -44,16 +43,39 @@
 }
 EXPORT_SYMBOL(enable_hlt);
 
+static int __init nohlt_setup(char *__unused)
+{
+	hlt_counter = 1;
+	return 1;
+}
+__setup("nohlt", nohlt_setup);
+
+static int __init hlt_setup(char *__unused)
+{
+	hlt_counter = 0;
+	return 1;
+}
+__setup("hlt", hlt_setup);
+
 void default_idle(void)
 {
-	if (!hlt_counter)
-		cpu_sleep();
-	else
-		cpu_relax();
+	if (!hlt_counter) {
+		clear_thread_flag(TIF_POLLING_NRFLAG);
+		smp_mb__after_clear_bit();
+		set_bl_bit();
+		while (!need_resched())
+			cpu_sleep();
+		clear_bl_bit();
+		set_thread_flag(TIF_POLLING_NRFLAG);
+	} else
+		while (!need_resched())
+			cpu_relax();
 }
 
 void cpu_idle(void)
 {
+	set_thread_flag(TIF_POLLING_NRFLAG);
+
 	/* endless idle loop with no priority at all */
 	while (1) {
 		void (*idle)(void) = pm_idle;
@@ -298,9 +320,7 @@
 	ctrl_outl(pc, UBC_BARA);
 
 #ifdef CONFIG_MMU
-	/* We don't have any ASID settings for the SH-2! */
-	if (current_cpu_data.type != CPU_SH7604)
-		ctrl_outb(asid, UBC_BASRA);
+	ctrl_outb(asid, UBC_BASRA);
 #endif
 
 	ctrl_outl(0, UBC_BAMRA);
@@ -384,8 +404,8 @@
 			unsigned long r6, unsigned long r7,
 			struct pt_regs __regs)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 #ifdef CONFIG_MMU
+	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
 #else
 	/* fork almost works, enough to trick you into looking elsewhere :-( */
@@ -428,23 +448,20 @@
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *ufilename, char **uargv,
-			  char **uenvp, unsigned long r7,
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
+			  char __user * __user *uenvp, unsigned long r7,
 			  struct pt_regs __regs)
 {
 	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	int error;
 	char *filename;
 
-	filename = getname((char __user *)ufilename);
+	filename = getname(ufilename);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
 
-	error = do_execve(filename,
-			  (char __user * __user *)uargv,
-			  (char __user * __user *)uenvp,
-			  regs);
+	error = do_execve(filename, uargv, uenvp, regs);
 	if (error == 0) {
 		task_lock(current);
 		current->ptrace &= ~PT_DTRACE;
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 3fb5fc0..891d1d4 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -91,17 +91,8 @@
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
-	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp,(unsigned long *) data);
-		break;
-	}
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -128,17 +119,14 @@
 			tmp = !!tsk_used_math(child);
 		else
 			tmp = 0;
-		ret = put_user(tmp, (unsigned long *)data);
+		ret = put_user(tmp, (unsigned long __user *)data);
 		break;
 	}
 
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-			break;
-		ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
@@ -196,7 +184,7 @@
 
 	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
 		long pc;
-		struct pt_regs *dummy = NULL;
+		struct pt_regs *regs = NULL;
 
 		ret = -EIO;
 		if (!valid_signal(data))
@@ -207,7 +195,7 @@
 			child->ptrace |= PT_DTRACE;
 		}
 
-		pc = get_stack_long(child, (long)&dummy->pc);
+		pc = get_stack_long(child, (long)&regs->pc);
 
 		/* Next scheduling will set up UBC */
 		if (child->thread.ubc_pc == 0)
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index c277291..de8e6e2 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -23,6 +23,7 @@
 #include <linux/kexec.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/page.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
@@ -41,20 +42,19 @@
  * The bigger value means no problem.
  */
 struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
+
+/*
+ * The machine vector. First entry in .machvec.init, or clobbered by
+ * sh_mv= on the command line, prior to .machvec.init teardown.
+ */
+struct sh_machine_vector sh_mv = { .mv_name = "generic", };
+
 #ifdef CONFIG_VT
 struct screen_info screen_info;
 #endif
 
-#if defined(CONFIG_SH_UNKNOWN)
-struct sh_machine_vector sh_mv;
-#endif
-
 extern int root_mountflags;
 
-#define MV_NAME_SIZE 32
-
-static struct sh_machine_vector* __init get_mv_byname(const char* name);
-
 /*
  * This is set up by the setup-routine at boot-time
  */
@@ -80,131 +80,17 @@
 
 unsigned long memory_start, memory_end;
 
-static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
-				  struct sh_machine_vector** mvp,
-				  unsigned long *mv_io_base)
+static int __init early_parse_mem(char *p)
 {
-	char c = ' ', *to = command_line, *from = COMMAND_LINE;
-	int len = 0;
-
-	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	unsigned long size;
 
 	memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
-	memory_end = memory_start + __MEMORY_SIZE;
-
-	for (;;) {
-		/*
-		 * "mem=XXX[kKmM]" defines a size of memory.
-		 */
-		if (c == ' ' && !memcmp(from, "mem=", 4)) {
-			if (to != command_line)
-				to--;
-			{
-				unsigned long mem_size;
-
-				mem_size = memparse(from+4, &from);
-				memory_end = memory_start + mem_size;
-			}
-		}
-
-		if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
-			char* mv_end;
-			char* mv_comma;
-			int mv_len;
-			if (to != command_line)
-				to--;
-			from += 6;
-			mv_end = strchr(from, ' ');
-			if (mv_end == NULL)
-				mv_end = from + strlen(from);
-
-			mv_comma = strchr(from, ',');
-			if ((mv_comma != NULL) && (mv_comma < mv_end)) {
-				int ints[3];
-				get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
-				*mv_io_base = ints[1];
-				mv_len = mv_comma - from;
-			} else {
-				mv_len = mv_end - from;
-			}
-			if (mv_len > (MV_NAME_SIZE-1))
-				mv_len = MV_NAME_SIZE-1;
-			memcpy(mv_name, from, mv_len);
-			mv_name[mv_len] = '\0';
-			from = mv_end;
-
-			*mvp = get_mv_byname(mv_name);
-		}
-
-		c = *(from++);
-		if (!c)
-			break;
-		if (COMMAND_LINE_SIZE <= ++len)
-			break;
-		*(to++) = c;
-	}
-	*to = '\0';
-	*cmdline_p = command_line;
-}
-
-static int __init sh_mv_setup(char **cmdline_p)
-{
-#ifdef CONFIG_SH_UNKNOWN
-	extern struct sh_machine_vector mv_unknown;
-#endif
-	struct sh_machine_vector *mv = NULL;
-	char mv_name[MV_NAME_SIZE] = "";
-	unsigned long mv_io_base = 0;
-
-	parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
-
-#ifdef CONFIG_SH_UNKNOWN
-	if (mv == NULL) {
-		mv = &mv_unknown;
-		if (*mv_name != '\0') {
-			printk("Warning: Unsupported machine %s, using unknown\n",
-			       mv_name);
-		}
-	}
-	sh_mv = *mv;
-#endif
-
-	/*
-	 * Manually walk the vec, fill in anything that the board hasn't yet
-	 * by hand, wrapping to the generic implementation.
-	 */
-#define mv_set(elem) do { \
-	if (!sh_mv.mv_##elem) \
-		sh_mv.mv_##elem = generic_##elem; \
-} while (0)
-
-	mv_set(inb);	mv_set(inw);	mv_set(inl);
-	mv_set(outb);	mv_set(outw);	mv_set(outl);
-
-	mv_set(inb_p);	mv_set(inw_p);	mv_set(inl_p);
-	mv_set(outb_p);	mv_set(outw_p);	mv_set(outl_p);
-
-	mv_set(insb);	mv_set(insw);	mv_set(insl);
-	mv_set(outsb);	mv_set(outsw);	mv_set(outsl);
-
-	mv_set(readb);	mv_set(readw);	mv_set(readl);
-	mv_set(writeb);	mv_set(writew);	mv_set(writel);
-
-	mv_set(ioport_map);
-	mv_set(ioport_unmap);
-	mv_set(irq_demux);
-
-#ifdef CONFIG_SH_UNKNOWN
-	__set_io_port_base(mv_io_base);
-#endif
-
-	if (!sh_mv.mv_nr_irqs)
-		sh_mv.mv_nr_irqs = NR_IRQS;
+	size = memparse(p, &p);
+	memory_end = memory_start + size;
 
 	return 0;
 }
+early_param("mem", early_parse_mem);
 
 /*
  * Register fully available low RAM pages with the bootmem allocator.
@@ -230,7 +116,7 @@
 	free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
 }
 
-void __init setup_bootmem_allocator(unsigned long start_pfn)
+void __init setup_bootmem_allocator(unsigned long free_pfn)
 {
 	unsigned long bootmap_size;
 
@@ -239,9 +125,10 @@
 	 * bootstrap step all allocations (until the page allocator
 	 * is intact) must be done via bootmem_alloc().
 	 */
-	bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
+	bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
 					 min_low_pfn, max_low_pfn);
 
+	add_active_range(0, min_low_pfn, max_low_pfn);
 	register_bootmem_low_pages();
 
 	node_set_online(0);
@@ -254,7 +141,7 @@
 	 * an invalid RAM area.
 	 */
 	reserve_bootmem(__MEMORY_START+PAGE_SIZE,
-		(PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
+		(PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
 
 	/*
 	 * reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -262,6 +149,8 @@
 	 */
 	reserve_bootmem(__MEMORY_START, PAGE_SIZE);
 
+	sparse_memory_present_with_active_regions(0);
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
 	if (&__rd_start != &__rd_end) {
@@ -315,10 +204,6 @@
 {
 	enable_mmu();
 
-#ifdef CONFIG_CMDLINE_BOOL
-	strcpy(COMMAND_LINE, CONFIG_CMDLINE);
-#endif
-
 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
 
 #ifdef CONFIG_BLK_DEV_RAM
@@ -339,9 +224,22 @@
 	data_resource.start = virt_to_phys(_etext);
 	data_resource.end = virt_to_phys(_edata)-1;
 
+	memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
+	memory_end = memory_start + __MEMORY_SIZE;
+
+#ifdef CONFIG_CMDLINE_BOOL
+	strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line));
+#else
+	strlcpy(command_line, COMMAND_LINE, sizeof(command_line));
+#endif
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = command_line;
+
 	parse_early_param();
 
-	sh_mv_setup(cmdline_p);
+	sh_mv_setup();
 
 	/*
 	 * Find the highest page frame number we have available
@@ -355,8 +253,9 @@
 	min_low_pfn = __MEMORY_START >> PAGE_SHIFT;
 
 	nodes_clear(node_online_map);
+
+	/* Setup bootmem with available RAM */
 	setup_memory();
-	paging_init();
 	sparse_init();
 
 #ifdef CONFIG_DUMMY_CONSOLE
@@ -366,46 +265,13 @@
 	/* Perform the machine specific initialisation */
 	if (likely(sh_mv.mv_setup))
 		sh_mv.mv_setup(cmdline_p);
+
+	paging_init();
 }
 
-struct sh_machine_vector* __init get_mv_byname(const char* name)
-{
-	extern long __machvec_start, __machvec_end;
-	struct sh_machine_vector *all_vecs =
-		(struct sh_machine_vector *)&__machvec_start;
-
-	int i, n = ((unsigned long)&__machvec_end
-		    - (unsigned long)&__machvec_start)/
-		sizeof(struct sh_machine_vector);
-
-	for (i = 0; i < n; ++i) {
-		struct sh_machine_vector *mv = &all_vecs[i];
-		if (mv == NULL)
-			continue;
-		if (strcasecmp(name, get_system_type()) == 0) {
-			return mv;
-		}
-	}
-	return NULL;
-}
-
-static struct cpu cpu[NR_CPUS];
-
-static int __init topology_init(void)
-{
-	int cpu_id;
-
-	for_each_possible_cpu(cpu_id)
-		register_cpu(&cpu[cpu_id], cpu_id);
-
-	return 0;
-}
-
-subsys_initcall(topology_init);
-
 static const char *cpu_name[] = {
 	[CPU_SH7206]	= "SH7206",	[CPU_SH7619]	= "SH7619",
-	[CPU_SH7604]	= "SH7604",	[CPU_SH7300]	= "SH7300",
+	[CPU_SH7300]	= "SH7300",
 	[CPU_SH7705]	= "SH7705",	[CPU_SH7706]	= "SH7706",
 	[CPU_SH7707]	= "SH7707",	[CPU_SH7708]	= "SH7708",
 	[CPU_SH7709]	= "SH7709",	[CPU_SH7710]	= "SH7710",
@@ -419,7 +285,7 @@
 	[CPU_SH7770]	= "SH7770",	[CPU_SH7780]	= "SH7780",
 	[CPU_SH7781]	= "SH7781",	[CPU_SH7343]	= "SH7343",
 	[CPU_SH7785]	= "SH7785",	[CPU_SH7722]	= "SH7722",
-	[CPU_SH_NONE]	= "Unknown"
+	[CPU_SHX3]	= "SH-X3",	[CPU_SH_NONE]	= "Unknown"
 };
 
 const char *get_cpu_subtype(struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index c1cfcb9..c968dcf 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -78,6 +78,16 @@
 DECLARE_EXPORT(__movmem_i4_even);
 DECLARE_EXPORT(__movmem_i4_odd);
 DECLARE_EXPORT(__movmemSI12_i4);
+
+#if (__GNUC_MINOR__ == 2 || defined(__GNUC_STM_RELEASE__))
+/*
+ * GCC 4.2 emits these for division, as do GCC 4.1.x versions of the ST
+ * compiler which include backported patches.
+ */
+DECLARE_EXPORT(__sdivsi3_i4i);
+DECLARE_EXPORT(__udiv_qrnnd_16);
+DECLARE_EXPORT(__udivsi3_i4i);
+#endif
 #else /* GCC 3.x */
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index b32c35a..706d81c 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -23,6 +23,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/freezer.h>
+#include <linux/io.h>
 #include <asm/system.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -261,14 +262,14 @@
 		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, regs->regs[15]);
+	do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame);
 
 	return r0;
 
 badframe:
 	force_sig(SIGSEGV, current);
 	return 0;
-}	
+}
 
 /*
  * Set up a signal frame.
@@ -481,7 +482,7 @@
 
 static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-	      sigset_t *oldset, struct pt_regs *regs)
+	      sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
 {
 	int ret;
 
@@ -489,6 +490,7 @@
 	if (regs->tra >= 0) {
 		/* If so, check system call restarting.. */
 		switch (regs->regs[0]) {
+			case -ERESTART_RESTARTBLOCK:
 			case -ERESTARTNOHAND:
 				regs->regs[0] = -EINTR;
 				break;
@@ -500,6 +502,7 @@
 				}
 			/* fallthrough */
 			case -ERESTARTNOINTR:
+				regs->regs[0] = save_r0;
 				regs->pc -= instruction_size(
 						ctrl_inw(regs->pc - 4));
 				break;
@@ -583,7 +586,8 @@
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+		if (handle_signal(signr, &ka, &info, oldset,
+				  regs, save_r0) == 0) {
 			/* a signal was successfully delivered; the saved
 			 * sigmask will have been stored in the signal frame,
 			 * and will be restored by sigreturn, so we can simply
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index dbebadd..283e142 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -10,6 +10,8 @@
  * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
+
+#include <linux/err.h>
 #include <linux/cache.h>
 #include <linux/cpumask.h>
 #include <linux/delay.h>
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index 4357d1a..ff5656e 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/arch/sh/kernel/syscalls.S
@@ -308,9 +308,9 @@
 	.long sys_utimes
  	.long sys_fadvise64_64_wrapper
 	.long sys_ni_syscall	/* Reserved for vserver */
-	.long sys_ni_syscall	/* Reserved for mbind */
-	.long sys_ni_syscall	/* 275 - get_mempolicy */
-	.long sys_ni_syscall	/* set_mempolicy */
+	.long sys_mbind
+	.long sys_get_mempolicy		/* 275 */
+	.long sys_set_mempolicy
 	.long sys_mq_open
 	.long sys_mq_unlink
 	.long sys_mq_timedsend
@@ -355,3 +355,6 @@
 	.long sys_getcpu
 	.long sys_epoll_pwait
 	.long sys_utimensat		/* 320 */
+	.long sys_signalfd
+	.long sys_timerfd
+	.long sys_eventfd
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 2d997e2..097ebd4 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -30,7 +30,7 @@
 
 static int tmu_timer_start(void)
 {
-	ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
+	ctrl_outb(ctrl_inb(TMU_012_TSTR) | 0x3, TMU_012_TSTR);
 	return 0;
 }
 
@@ -52,7 +52,7 @@
 
 static int tmu_timer_stop(void)
 {
-	ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
+	ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~0x3, TMU_012_TSTR);
 	return 0;
 }
 
@@ -174,7 +174,8 @@
 
 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7785)
+    !defined(CONFIG_CPU_SUBTYPE_SH7785) && \
+    !defined(CONFIG_CPU_SUBTYPE_SHX3)
 	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
 #endif
 
diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c
index a6bcc91..4e7e747 100644
--- a/arch/sh/kernel/timers/timer.c
+++ b/arch/sh/kernel/timers/timer.c
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <asm/timer.h>
 
-static struct sys_timer *sys_timers[] __initdata = {
+static struct sys_timer *sys_timers[] = {
 #ifdef CONFIG_SH_TMU
 	&tmu_timer,
 #endif
@@ -26,7 +26,7 @@
 	NULL,
 };
 
-static char timer_override[10] __initdata;
+static char timer_override[10];
 static int __init timer_setup(char *str)
 {
 	if (str)
@@ -53,4 +53,3 @@
 
 	return NULL;
 }
-
diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c
new file mode 100644
index 0000000..9b5844a
--- /dev/null
+++ b/arch/sh/kernel/topology.c
@@ -0,0 +1,49 @@
+/*
+ * arch/sh/kernel/topology.c
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+	int i, ret;
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+	for_each_online_node(i)
+		register_one_node(i);
+#endif
+
+	for_each_present_cpu(i) {
+		ret = register_cpu(&per_cpu(cpu_devices, i), i);
+		if (unlikely(ret))
+			printk(KERN_WARNING "%s: register_cpu %d failed (%d)\n",
+			       __FUNCTION__, i, ret);
+	}
+
+#if defined(CONFIG_NUMA) && !defined(CONFIG_SMP)
+	/*
+	 * In the UP case, make sure the CPU association is still
+	 * registered under each node. Without this, sysfs fails
+	 * to make the connection between nodes other than node0
+	 * and cpu0.
+	 */
+	for_each_online_node(i)
+		if (i != numa_node_id())
+			register_cpu_under_node(raw_smp_processor_id(), i);
+#endif
+
+	return 0;
+}
+subsys_initcall(topology_init);
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 3a19764..502d43e 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -21,6 +21,7 @@
 #include <linux/bug.h>
 #include <linux/debug_locks.h>
 #include <linux/kdebug.h>
+#include <linux/kexec.h>
 #include <linux/limits.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -82,6 +83,8 @@
 {
 	static int die_counter;
 
+	oops_enter();
+
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
@@ -100,7 +103,19 @@
 			 (unsigned long)task_stack_page(current));
 
 	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
+
+	if (kexec_should_crash(current))
+		crash_kexec(regs);
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops)
+		panic("Fatal exception");
+
+	oops_exit();
 	do_exit(SIGSEGV);
 }
 
@@ -513,7 +528,7 @@
  *       misaligned data access
  *       access to >= 0x80000000 is user mode
  * Unfortuntaly we can't distinguish between instruction address error
- * and data address errors caused by read acceses.
+ * and data address errors caused by read accesses.
  */
 asmlinkage void do_address_error(struct pt_regs *regs,
 				 unsigned long writeaccess,
@@ -570,7 +585,7 @@
 		info.si_signo = SIGBUS;
 		info.si_errno = 0;
 		info.si_code = si_code;
-		info.si_addr = (void *) address;
+		info.si_addr = (void __user *)address;
 		force_sig_info(SIGBUS, &info, current);
 	} else {
 		if (regs->pc & 1)
@@ -603,7 +618,7 @@
  */
 int is_dsp_inst(struct pt_regs *regs)
 {
-	unsigned short inst;
+	unsigned short inst = 0;
 
 	/*
 	 * Safe guard if DSP mode is already enabled or we're lacking
@@ -631,7 +646,6 @@
 				unsigned long r6, unsigned long r7,
 				struct pt_regs __regs)
 {
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	siginfo_t info;
 
 	switch (r4) {
@@ -860,7 +874,7 @@
 void handle_BUG(struct pt_regs *regs)
 {
 	enum bug_trap_type tt;
-	tt = report_bug(regs->pc);
+	tt = report_bug(regs->pc, regs);
 	if (tt == BUG_TRAP_TYPE_WARN) {
 		regs->pc += 2;
 		return;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index d83143c..0696402 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -22,7 +22,7 @@
 	*(.empty_zero_page)
 	} = 0
   .text : {
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	*(.fixup)
@@ -41,7 +41,7 @@
   BUG_TABLE
 
   .data : {			/* Data */
-	*(.data)
+	DATA_DATA
 
  	 /* Align the initial ramdisk image (INITRD) on page boundaries. */
  	 . = ALIGN(PAGE_SIZE);
@@ -97,18 +97,20 @@
   __initramfs_end = .;
 #endif
 
+ . = ALIGN(4);
   __machvec_start = .;
-  .init.machvec : { *(.init.machvec) }
+  .machvec.init : { *(.machvec.init) }
   __machvec_end = .;
+
   . = ALIGN(PAGE_SIZE);
-  __init_end = .;
-
-  . = ALIGN(4);
-  __bss_start = .;		/* BSS */
-  .bss : { *(.bss) }
-
-  . = ALIGN(4);
-  _end = . ;
+  .bss : {
+	__init_end = .;
+	__bss_start = .;		/* BSS */
+  	*(.bss.page_aligned)
+  	*(.bss)
+	. = ALIGN(4);
+	_end = . ;
+  }
 
   /* When something in the kernel is NOT compiled as a module, the
    * module cleanup code and data are put into these segments.  Both
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
index e146baf..2aa9438 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.c
+++ b/arch/sh/kernel/vsyscall/vsyscall.c
@@ -17,6 +17,7 @@
 #include <linux/gfp.h>
 #include <linux/module.h>
 #include <linux/elf.h>
+#include <linux/sched.h>
 
 /*
  * Should the kernel map a VDSO page into processes and pass its
diff --git a/arch/sh/lib/div64-generic.c b/arch/sh/lib/div64-generic.c
index c02473a..4bef3b5 100644
--- a/arch/sh/lib/div64-generic.c
+++ b/arch/sh/lib/div64-generic.c
@@ -4,16 +4,15 @@
 
 #include <linux/types.h>
 
-extern u64 __xdiv64_32(u64 n, u32 d);
+extern uint64_t __xdiv64_32(u64 n, u32 d);
 
-u64 __div64_32(u64 *xp, u32 y)
+uint32_t __div64_32(u64 *xp, u32 y)
 {
-	u64 rem;
-	u64 q = __xdiv64_32(*xp, y);
+	uint32_t rem;
+	uint64_t q = __xdiv64_32(*xp, y);
 
 	rem = *xp - q * y;
 	*xp = q;
 
 	return rem;
 }
-
diff --git a/arch/sh/lib/div64.S b/arch/sh/lib/div64.S
index eefc275..5ee7334 100644
--- a/arch/sh/lib/div64.S
+++ b/arch/sh/lib/div64.S
@@ -1,12 +1,12 @@
 /*	
- * unsigned long long __xdiv64_32(unsigned long long n, unsigned long d); 
+ * unsigned long __xdiv64_32(unsigned long long n, unsigned long d); 
  */
 
 #include <linux/linkage.h>
 
 .text
 ENTRY(__xdiv64_32)
-#ifdef  __LITTLE_ENDIAN__
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
 	mov	r4, r0
 	mov	r5, r1
 #else
@@ -34,7 +34,7 @@
 	rotcl	r0
 	div1	r6, r1
 	.endr
-#ifdef  __LITTLE_ENDIAN__
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
 	mov	r2, r1
 	rts
 	 rotcl	r0
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
index 1efbac1..ac2d7ab 100644
--- a/arch/sh/math-emu/math.c
+++ b/arch/sh/math-emu/math.c
@@ -148,7 +148,7 @@
 	return 0;
 }
 
-// to process fmov's extention (odd n for DR access XD).
+// to process fmov's extension (odd n for DR access XD).
 #define FMOV_EXT(x) if(x&1) x+=16-1
 
 static int
@@ -507,6 +507,7 @@
 	unsigned short insn = *(unsigned short *)regs->pc;
 	unsigned short finsn;
 	unsigned long nextpc;
+	siginfo_t info;
 	int nib[4] = {
 		(insn >> 12) & 0xf,
 		(insn >> 8) & 0xf,
@@ -559,9 +560,11 @@
 				~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
 			set_tsk_thread_flag(tsk, TIF_USEDFPU);
 		} else {
-			tsk->thread.trap_no = 11;
-			tsk->thread.error_code = 0;
-			force_sig(SIGFPE, tsk);
+			info.si_signo = SIGFPE;
+			info.si_errno = 0;
+			info.si_code = FPE_FLTINV;
+			info.si_addr = (void __user *)regs->pc;
+			force_sig_info(SIGFPE, &info, tsk);
 		}
 
 		regs->pc = nextpc;
@@ -576,14 +579,17 @@
 			     struct pt_regs regs)
 {
 	struct task_struct *tsk = current;
+	siginfo_t info;
 
 	if (ieee_fpe_handler (&regs))
 		return;
 
 	regs.pc += 2;
-	tsk->thread.trap_no = 11;
-	tsk->thread.error_code = 0;
-	force_sig(SIGFPE, tsk);
+	info.si_signo = SIGFPE;
+	info.si_errno = 0;
+	info.si_code = FPE_FLTINV;
+	info.si_addr = (void __user *)regs.pc;
+	force_sig_info(SIGFPE, &info, tsk);
 }
 
 /**
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 253346d..28d79a4 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -1,5 +1,3 @@
-menu "Processor selection"
-
 #
 # Processor families
 #
@@ -38,27 +36,31 @@
 config CPU_SHX2
 	bool
 
+config CPU_SHX3
+	bool
+
+choice
+	prompt "Processor sub-type selection"
+
 #
 # Processor subtypes
 #
 
-comment "SH-2 Processor Support"
-
-config CPU_SUBTYPE_SH7604
-	bool "Support SH7604 processor"
-	select CPU_SH2
+# SH-2 Processor Support
 
 config CPU_SUBTYPE_SH7619
 	bool "Support SH7619 processor"
 	select CPU_SH2
+	select CPU_HAS_IPR_IRQ
 
-comment "SH-2A Processor Support"
+# SH-2A Processor Support
 
 config CPU_SUBTYPE_SH7206
 	bool "Support SH7206 processor"
 	select CPU_SH2A
+	select CPU_HAS_IPR_IRQ
 
-comment "SH-3 Processor Support"
+# SH-3 Processor Support
 
 config CPU_SUBTYPE_SH7300
 	bool "Support SH7300 processor"
@@ -113,7 +115,7 @@
 	help
 	  Select SH7712 if you have a SH3-DSP SH7712 CPU.
 
-comment "SH-4 Processor Support"
+# SH-4 Processor Support
 
 config CPU_SUBTYPE_SH7750
 	bool "Support SH7750 processor"
@@ -125,7 +127,7 @@
 config CPU_SUBTYPE_SH7091
 	bool "Support SH7091 processor"
 	select CPU_SH4
-	select CPU_SUBTYPE_SH7750
+	select CPU_HAS_IPR_IRQ
 	help
 	  Select SH7091 if you have an SH-4 based Sega device (such as
 	  the Dreamcast, Naomi, and Naomi 2).
@@ -133,13 +135,11 @@
 config CPU_SUBTYPE_SH7750R
 	bool "Support SH7750R processor"
 	select CPU_SH4
-	select CPU_SUBTYPE_SH7750
 	select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7750S
 	bool "Support SH7750S processor"
 	select CPU_SH4
-	select CPU_SUBTYPE_SH7750
 	select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7751
@@ -153,7 +153,6 @@
 config CPU_SUBTYPE_SH7751R
 	bool "Support SH7751R processor"
 	select CPU_SH4
-	select CPU_SUBTYPE_SH7751
 	select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7760
@@ -166,7 +165,7 @@
 	bool "Support SH4-202 processor"
 	select CPU_SH4
 
-comment "ST40 Processor Support"
+# ST40 Processor Support
 
 config CPU_SUBTYPE_ST40STB1
 	bool "Support ST40STB1/ST40RA processors"
@@ -181,7 +180,7 @@
 	help
 	  Select ST40GX1 if you have a ST40GX1 CPU.
 
-comment "SH-4A Processor Support"
+# SH-4A Processor Support
 
 config CPU_SUBTYPE_SH7770
 	bool "Support SH7770 processor"
@@ -198,7 +197,13 @@
 	select CPU_SHX2
 	select CPU_HAS_INTC2_IRQ
 
-comment "SH4AL-DSP Processor Support"
+config CPU_SUBTYPE_SHX3
+	bool "Support SH-X3 processor"
+	select CPU_SH4A
+	select CPU_SHX3
+	select CPU_HAS_INTC2_IRQ
+
+# SH4AL-DSP Processor Support
 
 config CPU_SUBTYPE_SH73180
 	bool "Support SH73180 processor"
@@ -213,8 +218,10 @@
 	select CPU_SH4AL_DSP
 	select CPU_SHX2
 	select CPU_HAS_IPR_IRQ
+	select ARCH_SPARSEMEM_ENABLE
+	select SYS_SUPPORTS_NUMA
 
-endmenu
+endchoice
 
 menu "Memory management options"
 
@@ -266,7 +273,7 @@
 
 config 32BIT
 	bool "Support 32-bit physical addressing through PMB"
-	depends on CPU_SH4A && MMU && (!X2TLB || BROKEN)
+	depends on MMU && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
 	default y
 	help
 	  If you say Y here, physical addressing will be extended to
@@ -295,6 +302,17 @@
 	  For systems with an MMU that can afford to give up a page,
 	  (the default value) say Y.
 
+config NUMA
+	bool "Non Uniform Memory Access (NUMA) Support"
+	depends on MMU && SYS_SUPPORTS_NUMA && EXPERIMENTAL
+	default n
+	help
+	  Some SH systems have many various memories scattered around
+	  the address space, each with varying latencies. This enables
+	  support for these blocks by binding them to nodes and allowing
+	  memory policies to be used for prioritizing and controlling
+	  allocation behaviour.
+
 config NODES_SHIFT
 	int
 	default "1"
@@ -302,14 +320,34 @@
 
 config ARCH_FLATMEM_ENABLE
 	def_bool y
+	depends on !NUMA
+
+config ARCH_SPARSEMEM_ENABLE
+	def_bool y
+	select SPARSEMEM_STATIC
+
+config ARCH_SPARSEMEM_DEFAULT
+	def_bool y
 
 config MAX_ACTIVE_REGIONS
 	int
+	default "2" if (CPU_SUBTYPE_SH7722 && SPARSEMEM)
 	default "1"
 
 config ARCH_POPULATES_NODE_MAP
 	def_bool y
 
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool y
+
+config ARCH_ENABLE_MEMORY_HOTPLUG
+	def_bool y
+	depends on SPARSEMEM
+
+config ARCH_MEMORY_PROBE
+	def_bool y
+	depends on MEMORY_HOTPLUG
+
 choice
 	prompt "Kernel page size"
 	default PAGE_SIZE_4KB
@@ -394,15 +432,4 @@
 
 	  If unsure, say N.
 
-config SH_OCRAM
-	bool "Operand Cache RAM (OCRAM) support"
-	help
-	  Selecting this option will automatically tear down the number of
-	  sets in the dcache by half, which in turn exposes a memory range.
-
-	  The addresses for the OC RAM base will vary according to the
-	  processor version. Consult vendor documentation for specifics.
-
-	  If unsure, say N.
-
 endmenu
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 3ffd7f6..d677d7f 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -8,9 +8,6 @@
 obj-$(CONFIG_CPU_SH3)	+= cache-sh3.o
 obj-$(CONFIG_CPU_SH4)	+= cache-sh4.o
 
-obj-$(CONFIG_DMA_PAGE_OPS)	+= pg-dma.o
-obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
-
 mmu-y			:= fault-nommu.o tlb-nommu.o pg-nommu.o
 mmu-$(CONFIG_MMU)	:= fault.o clear_page.o copy_page.o tlb-flush.o	\
 			   ioremap.o
@@ -27,5 +24,7 @@
 obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
 endif
 
+obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 obj-$(CONFIG_SH7705_CACHE_32KB)	+= cache-sh7705.o
 obj-$(CONFIG_32BIT)		+= pmb.o
+obj-$(CONFIG_NUMA)		+= numa.o
diff --git a/arch/sh/mm/copy_page.S b/arch/sh/mm/copy_page.S
index 397c94c..ae039f2 100644
--- a/arch/sh/mm/copy_page.S
+++ b/arch/sh/mm/copy_page.S
@@ -129,6 +129,7 @@
 	rts
 	 nop
 #endif
+	.align 2
 .Lpsz:	.long	PAGE_SIZE
 /*
  * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 9207da6..0b3eaf6 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -15,43 +15,11 @@
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
-#include <linux/kdebug.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 #include <asm/kgdb.h>
 
-#ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-
-/* Hook to register for page fault notifications */
-int register_page_fault_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
-
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
-}
-
-static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
-				    int trap, int sig)
-{
-	struct die_args args = {
-		.regs = regs,
-		.trapnr = trap,
-	};
-	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
-}
-#else
-static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
-				    int trap, int sig)
-{
-	return NOTIFY_DONE;
-}
-#endif
-
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -64,16 +32,10 @@
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	struct vm_area_struct * vma;
-	unsigned long page;
 	int si_code;
 	siginfo_t info;
 
 	trace_hardirqs_on();
-
-	if (notify_page_fault(DIE_PAGE_FAULT, regs,
-			      writeaccess, SIGSEGV) == NOTIFY_STOP)
-		return;
-
 	local_irq_enable();
 
 #ifdef CONFIG_SH_KGDB
@@ -207,24 +169,38 @@
  * terminate things with extreme prejudice.
  *
  */
-	if (address < PAGE_SIZE)
-		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-	else
-		printk(KERN_ALERT "Unable to handle kernel paging request");
-	printk(" at virtual address %08lx\n", address);
-	printk(KERN_ALERT "pc = %08lx\n", regs->pc);
-	page = (unsigned long)get_TTB();
-	if (page) {
-		page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
-		printk(KERN_ALERT "*pde = %08lx\n", page);
-		if (page & _PAGE_PRESENT) {
-			page &= PAGE_MASK;
-			address &= 0x003ff000;
-			page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
-			printk(KERN_ALERT "*pte = %08lx\n", page);
+
+	bust_spinlocks(1);
+
+	if (oops_may_print()) {
+		__typeof__(pte_val(__pte(0))) page;
+
+		if (address < PAGE_SIZE)
+			printk(KERN_ALERT "Unable to handle kernel NULL "
+					  "pointer dereference");
+		else
+			printk(KERN_ALERT "Unable to handle kernel paging "
+					  "request");
+		printk(" at virtual address %08lx\n", address);
+		printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+		page = (unsigned long)get_TTB();
+		if (page) {
+			page = ((__typeof__(page) *) __va(page))[address >>
+								 PGDIR_SHIFT];
+			printk(KERN_ALERT "*pde = %08lx\n", page);
+			if (page & _PAGE_PRESENT) {
+				page &= PAGE_MASK;
+				address &= 0x003ff000;
+				page = ((__typeof__(page) *)
+						__va(page))[address >>
+							    PAGE_SHIFT];
+				printk(KERN_ALERT "*pte = %08lx\n", page);
+			}
 		}
 	}
+
 	die("Oops", regs, writeaccess);
+	bust_spinlocks(0);
 	do_exit(SIGKILL);
 
 /*
@@ -285,7 +261,7 @@
 	pte_t *pte;
 	pte_t entry;
 	struct mm_struct *mm = current->mm;
-	spinlock_t *ptl;
+	spinlock_t *ptl = NULL;
 	int ret = 1;
 
 #ifdef CONFIG_SH_KGDB
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 8fe223a..82b68c7 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -12,11 +12,13 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/proc_fs.h>
+#include <linux/pagemap.h>
 #include <linux/percpu.h>
 #include <linux/io.h>
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
+#include <asm/sections.h>
 #include <asm/cache.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -35,14 +37,11 @@
 	show_free_areas();
 
 	for_each_online_pgdat(pgdat) {
-		struct page *page, *end;
-		unsigned long flags;
+		unsigned long flags, i;
 
 		pgdat_resize_lock(pgdat, &flags);
-		page = pgdat->node_mem_map;
-		end = page + pgdat->node_spanned_pages;
-
-		do {
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
+			struct page *page = pgdat_page_nr(pgdat, i);
 			total++;
 			if (PageReserved(page))
 				reserved++;
@@ -54,9 +53,7 @@
 				free++;
 			else
 				shared += page_count(page) - 1;
-			page++;
-		} while (page < end);
-
+		}
 		pgdat_resize_unlock(pgdat, &flags);
 	}
 
@@ -112,7 +109,7 @@
  * As a performance optimization, other platforms preserve the fixmap mapping
  * across a context switch, we don't presently do this, but this could be done
  * in a similar fashion as to the wired TLB interface that sh64 uses (by way
- * of the memorry mapped UTLB configuration) -- this unfortunately forces us to
+ * of the memory mapped UTLB configuration) -- this unfortunately forces us to
  * give up a TLB entry for each mapping we want to preserve. While this may be
  * viable for a small number of fixmaps, it's not particularly useful for
  * everything and needs to be carefully evaluated. (ie, we may want this for
@@ -136,16 +133,12 @@
 }
 #endif	/* CONFIG_MMU */
 
-/* References to section boundaries */
-
-extern char _text, _etext, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
-
 /*
  * paging_init() sets up the page tables
  */
 void __init paging_init(void)
 {
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
 	int nid;
 
 	/* We don't need to map the kernel through the TLB, as
@@ -157,43 +150,39 @@
 	 * check for a null value. */
 	set_TTB(swapper_pg_dir);
 
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+
 	for_each_online_node(nid) {
 		pg_data_t *pgdat = NODE_DATA(nid);
-		unsigned long max_zone_pfns[MAX_NR_ZONES];
 		unsigned long low, start_pfn;
 
-		memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
-
 		start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT;
 		low = pgdat->bdata->node_low_pfn;
 
-		max_zone_pfns[ZONE_NORMAL] = low;
-		add_active_range(nid, start_pfn, low);
+		if (max_zone_pfns[ZONE_NORMAL] < low)
+			max_zone_pfns[ZONE_NORMAL] = low;
 
 		printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
 		       nid, start_pfn, low);
-
-		free_area_init_nodes(max_zone_pfns);
-
-		printk("Node %u: mem_map starts at %p\n",
-		       pgdat->node_id, pgdat->node_mem_map);
 	}
+
+	free_area_init_nodes(max_zone_pfns);
 }
 
 static struct kcore_list kcore_mem, kcore_vmalloc;
 
 void __init mem_init(void)
 {
-	int codesize, reservedpages, datasize, initsize;
+	int codesize, datasize, initsize;
 	int nid;
 
-	reservedpages = 0;
+	num_physpages = 0;
+	high_memory = NULL;
 
 	for_each_online_node(nid) {
 		pg_data_t *pgdat = NODE_DATA(nid);
 		unsigned long node_pages = 0;
 		void *node_high_memory;
-		int i;
 
 		num_physpages += pgdat->node_present_pages;
 
@@ -202,13 +191,9 @@
 
 		totalram_pages += node_pages;
 
-		for (i = 0; i < node_pages; i++)
-			if (PageReserved(pgdat->node_mem_map + i))
-				reservedpages++;
-
-		node_high_memory = (void *)((pgdat->node_start_pfn +
-					     pgdat->node_spanned_pages) <<
-						PAGE_SHIFT);
+		node_high_memory = (void *)__va((pgdat->node_start_pfn +
+						 pgdat->node_spanned_pages) <<
+						 PAGE_SHIFT);
 		if (node_high_memory > high_memory)
 			high_memory = node_high_memory;
 	}
@@ -238,11 +223,10 @@
 		   VMALLOC_END - VMALLOC_START);
 
 	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
-	       "%dk reserved, %dk data, %dk init)\n",
+	       "%dk data, %dk init)\n",
 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
-		totalram_pages << (PAGE_SHIFT-10),
+		num_physpages << (PAGE_SHIFT-10),
 		codesize >> 10,
-		reservedpages << (PAGE_SHIFT-10),
 		datasize >> 10,
 		initsize >> 10);
 
@@ -263,7 +247,9 @@
 		free_page(addr);
 		totalram_pages++;
 	}
-	printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+	printk("Freeing unused kernel memory: %ldk freed\n",
+	       ((unsigned long)&__init_end -
+	        (unsigned long)&__init_begin) >> 10);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -276,6 +262,50 @@
 		free_page(p);
 		totalram_pages++;
 	}
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+	printk("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 }
 #endif
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+void online_page(struct page *page)
+{
+	ClearPageReserved(page);
+	init_page_count(page);
+	__free_page(page);
+	totalram_pages++;
+	num_physpages++;
+}
+
+int arch_add_memory(int nid, u64 start, u64 size)
+{
+	pg_data_t *pgdat;
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+	unsigned long nr_pages = size >> PAGE_SHIFT;
+	int ret;
+
+	pgdat = NODE_DATA(nid);
+
+	/* We only have ZONE_NORMAL, so this is easy.. */
+	ret = __add_pages(pgdat->node_zones + ZONE_NORMAL, start_pfn, nr_pages);
+	if (unlikely(ret))
+		printk("%s: Failed, __add_pages() == %d\n", __FUNCTION__, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(arch_add_memory);
+
+int remove_memory(u64 start, u64 size)
+{
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(remove_memory);
+
+#ifdef CONFIG_NUMA
+int memory_add_physaddr_to_nid(u64 addr)
+{
+	/* Node 0 for now.. */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
+#endif
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index be03d74..0c7b7e3 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -22,6 +22,7 @@
 #include <asm/addrspace.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu.h>
 
 /*
  * Remap an arbitrary physical address space into the kernel virtual
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
new file mode 100644
index 0000000..8aff065
--- /dev/null
+++ b/arch/sh/mm/numa.c
@@ -0,0 +1,92 @@
+/*
+ * arch/sh/mm/numa.c - Multiple node support for SH machines
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/numa.h>
+#include <linux/pfn.h>
+#include <asm/sections.h>
+
+static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL_GPL(node_data);
+
+/*
+ * On SH machines the conventional approach is to stash system RAM
+ * in node 0, and other memory blocks in to node 1 and up, ordered by
+ * latency. Each node's pgdat is node-local at the beginning of the node,
+ * immediately followed by the node mem map.
+ */
+void __init setup_memory(void)
+{
+	unsigned long free_pfn = PFN_UP(__pa(_end));
+
+	/*
+	 * Node 0 sets up its pgdat at the first available pfn,
+	 * and bumps it up before setting up the bootmem allocator.
+	 */
+	NODE_DATA(0) = pfn_to_kaddr(free_pfn);
+	memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
+	free_pfn += PFN_UP(sizeof(struct pglist_data));
+	NODE_DATA(0)->bdata = &plat_node_bdata[0];
+
+	/* Set up node 0 */
+	setup_bootmem_allocator(free_pfn);
+
+	/* Give the platforms a chance to hook up their nodes */
+	plat_mem_setup();
+}
+
+void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
+{
+	unsigned long bootmap_pages, bootmap_start, bootmap_size;
+	unsigned long start_pfn, free_pfn, end_pfn;
+
+	/* Don't allow bogus node assignment */
+	BUG_ON(nid > MAX_NUMNODES || nid == 0);
+
+	/*
+	 * The free pfn starts at the beginning of the range, and is
+	 * advanced as necessary for pgdat and node map allocations.
+	 */
+	free_pfn = start_pfn = start >> PAGE_SHIFT;
+	end_pfn = end >> PAGE_SHIFT;
+
+	add_active_range(nid, start_pfn, end_pfn);
+
+	/* Node-local pgdat */
+	NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
+	free_pfn += PFN_UP(sizeof(struct pglist_data));
+	memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+
+	NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+	NODE_DATA(nid)->node_start_pfn = start_pfn;
+	NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
+
+	/* Node-local bootmap */
+	bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+	bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
+	bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
+				    end_pfn);
+
+	free_bootmem_with_active_regions(nid, end_pfn);
+
+	/* Reserve the pgdat and bootmap space with the bootmem allocator */
+	reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
+			     sizeof(struct pglist_data));
+	reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
+			     bootmap_pages << PAGE_SHIFT);
+
+	/* It's up */
+	node_set_online(nid);
+
+	/* Kick sparsemem */
+	sparse_memory_present_with_active_regions(nid);
+}
diff --git a/arch/sh/mm/pg-dma.c b/arch/sh/mm/pg-dma.c
deleted file mode 100644
index bb23679..0000000
--- a/arch/sh/mm/pg-dma.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * arch/sh/mm/pg-dma.c
- *
- * Fast clear_page()/copy_page() implementation using the SH DMAC
- *
- * Copyright (C) 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/semaphore.h>
-#include <asm/mmu_context.h>
-#include <asm/addrspace.h>
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-
-/* Channel to use for page ops, must be dual-address mode capable. */
-static int dma_channel = CONFIG_DMA_PAGE_OPS_CHANNEL;
-
-static void copy_page_dma(void *to, void *from)
-{
-	/* 
-	 * This doesn't seem to get triggered until further along in the
-	 * boot process, at which point the DMAC is already initialized.
-	 * Fix this in the same fashion as clear_page_dma() in the event
-	 * that this crashes due to the DMAC not being initialized.
-	 */
-
-	flush_icache_range((unsigned long)from, PAGE_SIZE);
-	dma_write_page(dma_channel, (unsigned long)from, (unsigned long)to);
-	dma_wait_for_completion(dma_channel);
-}
-
-static void clear_page_dma(void *to)
-{
-	/*
-	 * We get invoked quite early on, if the DMAC hasn't been initialized
-	 * yet, fall back on the slow manual implementation.
-	 */
-	if (dma_info[dma_channel].chan != dma_channel) {
-		clear_page_slow(to);
-		return;
-	}
-
-	dma_write_page(dma_channel, (unsigned long)empty_zero_page,
-				    (unsigned long)to);
-
-	/*
-	 * FIXME: Something is a bit racy here, if we poll the counter right
-	 * away, we seem to lock. flushing the page from the dcache doesn't
-	 * seem to make a difference one way or the other, though either a full
-	 * icache or dcache flush does.
-	 *
-	 * The location of this is important as well, and must happen prior to
-	 * the completion loop but after the transfer was initiated.
-	 *
-	 * Oddly enough, this doesn't appear to be an issue for copy_page()..
-	 */
-	flush_icache_range((unsigned long)to, PAGE_SIZE);
-
-	dma_wait_for_completion(dma_channel);
-}
-
-static int __init pg_dma_init(void)
-{
-	int ret;
-	
-	ret = request_dma(dma_channel, "page ops");
-	if (ret != 0)
-		return ret;
-
-	copy_page = copy_page_dma;
-	clear_page = clear_page_dma;
-
-	return ret;
-}
-
-static void __exit pg_dma_exit(void)
-{
-	free_dma(dma_channel);
-}
-
-module_init(pg_dma_init);
-module_exit(pg_dma_exit);
-
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
-MODULE_DESCRIPTION("Optimized page copy/clear routines using a dual-address mode capable DMAC channel");
-MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 02aae06..b6a5a33 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -3,7 +3,7 @@
  *
  * Privileged Space Mapping Buffer (PMB) Support.
  *
- * Copyright (C) 2005, 2006 Paul Mundt
+ * Copyright (C) 2005, 2006, 2007 Paul Mundt
  *
  * P1/P2 Section mapping definitions from map32.h, which was:
  *
@@ -68,6 +68,32 @@
 	return mk_pmb_entry(entry) | PMB_DATA;
 }
 
+static DEFINE_SPINLOCK(pmb_list_lock);
+static struct pmb_entry *pmb_list;
+
+static inline void pmb_list_add(struct pmb_entry *pmbe)
+{
+	struct pmb_entry **p, *tmp;
+
+	p = &pmb_list;
+	while ((tmp = *p) != NULL)
+		p = &tmp->next;
+
+	pmbe->next = tmp;
+	*p = pmbe;
+}
+
+static inline void pmb_list_del(struct pmb_entry *pmbe)
+{
+	struct pmb_entry **p, *tmp;
+
+	for (p = &pmb_list; (tmp = *p); p = &tmp->next)
+		if (tmp == pmbe) {
+			*p = tmp->next;
+			return;
+		}
+}
+
 struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
 			    unsigned long flags)
 {
@@ -81,11 +107,19 @@
 	pmbe->ppn	= ppn;
 	pmbe->flags	= flags;
 
+	spin_lock_irq(&pmb_list_lock);
+	pmb_list_add(pmbe);
+	spin_unlock_irq(&pmb_list_lock);
+
 	return pmbe;
 }
 
 void pmb_free(struct pmb_entry *pmbe)
 {
+	spin_lock_irq(&pmb_list_lock);
+	pmb_list_del(pmbe);
+	spin_unlock_irq(&pmb_list_lock);
+
 	kmem_cache_free(pmb_cache, pmbe);
 }
 
@@ -167,31 +201,6 @@
 	clear_bit(entry, &pmb_map);
 }
 
-static DEFINE_SPINLOCK(pmb_list_lock);
-static struct pmb_entry *pmb_list;
-
-static inline void pmb_list_add(struct pmb_entry *pmbe)
-{
-	struct pmb_entry **p, *tmp;
-
-	p = &pmb_list;
-	while ((tmp = *p) != NULL)
-		p = &tmp->next;
-
-	pmbe->next = tmp;
-	*p = pmbe;
-}
-
-static inline void pmb_list_del(struct pmb_entry *pmbe)
-{
-	struct pmb_entry **p, *tmp;
-
-	for (p = &pmb_list; (tmp = *p); p = &tmp->next)
-		if (tmp == pmbe) {
-			*p = tmp->next;
-			return;
-		}
-}
 
 static struct {
 	unsigned long size;
@@ -283,25 +292,14 @@
 	} while (pmbe);
 }
 
-static void pmb_cache_ctor(void *pmb, struct kmem_cache *cachep, unsigned long flags)
+static void pmb_cache_ctor(void *pmb, struct kmem_cache *cachep,
+			   unsigned long flags)
 {
 	struct pmb_entry *pmbe = pmb;
 
 	memset(pmb, 0, sizeof(struct pmb_entry));
 
-	spin_lock_irq(&pmb_list_lock);
-
 	pmbe->entry = PMB_NO_ENTRY;
-	pmb_list_add(pmbe);
-
-	spin_unlock_irq(&pmb_list_lock);
-}
-
-static void pmb_cache_dtor(void *pmb, struct kmem_cache *cachep, unsigned long flags)
-{
-	spin_lock_irq(&pmb_list_lock);
-	pmb_list_del(pmb);
-	spin_unlock_irq(&pmb_list_lock);
 }
 
 static int __init pmb_init(void)
@@ -312,8 +310,7 @@
 	BUG_ON(unlikely(nr_entries >= NR_PMB_ENTRIES));
 
 	pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry), 0,
-				      SLAB_PANIC, pmb_cache_ctor,
-				      pmb_cache_dtor);
+				      SLAB_PANIC, pmb_cache_ctor, NULL);
 
 	jump_to_P2();
 
diff --git a/arch/sh/tools/Makefile b/arch/sh/tools/Makefile
index 3c370a1..567516b 100644
--- a/arch/sh/tools/Makefile
+++ b/arch/sh/tools/Makefile
@@ -12,4 +12,5 @@
 
 include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
 	@echo '  Generating $@'
+	$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
 	$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 554f801..4b5e930 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -7,15 +7,17 @@
 #
 SE			SH_SOLUTION_ENGINE
 7751SE			SH_7751_SOLUTION_ENGINE		
+7722SE			SH_7722_SOLUTION_ENGINE		
 7300SE			SH_7300_SOLUTION_ENGINE
 7343SE			SH_7343_SOLUTION_ENGINE
+7206SE			SH_7206_SOLUTION_ENGINE
+7619SE			SH_7619_SOLUTION_ENGINE
 7780SE			SH_7780_SOLUTION_ENGINE
 73180SE			SH_73180_SOLUTION_ENGINE
 7751SYSTEMH		SH_7751_SYSTEMH
 HP6XX			SH_HP6XX
 HD64461			HD64461
 HD64465			HD64465
-SATURN			SH_SATURN
 DREAMCAST		SH_DREAMCAST
 MPC1211			SH_MPC1211
 SNAPGEAR		SH_SECUREEDGE5410
@@ -31,5 +33,4 @@
 TITAN			SH_TITAN
 SHMIN			SH_SHMIN
 7710VOIPGW		SH_7710VOIPGW
-7206SE			SH_7206_SOLUTION_ENGINE
-7619SE			SH_7619_SOLUTION_ENGINE
+LBOXRE2			SH_LBOX_RE2
diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
index fb51660..3334f99 100644
--- a/arch/sh64/kernel/pci_sh5.c
+++ b/arch/sh64/kernel/pci_sh5.c
@@ -521,10 +521,10 @@
 		bus->resource[0]->start = PCIBIOS_MIN_IO;
 		bus->resource[1]->start = PCIBIOS_MIN_MEM;
 #else
-		bus->resource[0]->end = 0
-		bus->resource[1]->end = 0
-		bus->resource[0]->start =0
-		  bus->resource[1]->start = 0;
+		bus->resource[0]->end = 0;
+		bus->resource[1]->end = 0;
+		bus->resource[0]->start =0;
+		bus->resource[1]->start = 0;
 #endif
 		/* Turn off downstream PF memory address range by default */
 		bus->resource[2]->start = 1024*1024;
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index 4e95e18..df06c64 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -129,17 +129,9 @@
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
-	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp,(unsigned long *) data);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -166,10 +158,7 @@
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-			break;
-		ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR:
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
index c8525ad..0bb4a8f 100644
--- a/arch/sh64/kernel/signal.c
+++ b/arch/sh64/kernel/signal.c
@@ -640,6 +640,7 @@
 	if (regs->syscall_nr >= 0) {
 		/* If so, check system call restarting.. */
 		switch (regs->regs[REG_RET]) {
+			case -ERESTART_RESTARTBLOCK:
 			case -ERESTARTNOHAND:
 				regs->regs[REG_RET] = -EINTR;
 				break;
diff --git a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S
index 4f9616f..02aea86 100644
--- a/arch/sh64/kernel/vmlinux.lds.S
+++ b/arch/sh64/kernel/vmlinux.lds.S
@@ -54,7 +54,7 @@
 	} = 0
 
   .text : C_PHYS(.text) {
-	*(.text)
+	TEXT_TEXT
 	*(.text64)
         *(.text..SHmedia32)
 	SCHED_TEXT
@@ -78,7 +78,7 @@
   _etext = .;			/* End of text section */
 
   .data : C_PHYS(.data) {			/* Data */
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
 	}
 
diff --git a/arch/sh64/lib/c-checksum.c b/arch/sh64/lib/c-checksum.c
index 4b26763..bd55017 100644
--- a/arch/sh64/lib/c-checksum.c
+++ b/arch/sh64/lib/c-checksum.c
@@ -213,3 +213,4 @@
 
 	return (__wsum)result;
 }
+EXPORT_SYMBOL(csum_tcpudp_nofold);
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index bd992c0..73df711 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -178,6 +178,13 @@
 	bool
 	default n
 
+config EMULATED_CMPXCHG
+	bool
+	default y
+	help
+	  Sparc32 does not have a CAS instruction like sparc64. cmpxchg()
+	  is emulated, and therefore it is not completely atomic.
+
 config SUN_PM
 	bool
 	default y
@@ -203,10 +210,16 @@
 	  CP-1200, JavaEngine-1, Corona, Red October, and Serengeti SGSC.
 	  All of these platforms are extremely obscure, so say N if unsure.
 
+config PCI_SYSCALL
+	def_bool PCI
+
 source "drivers/pci/Kconfig"
 
 endif
 
+config NO_DMA
+	def_bool !PCI
+
 config SUN_OPENPROMFS
 	tristate "Openprom tree appears in /proc/openprom"
 	help
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 4d9ad590..4fea3ac 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -68,16 +68,6 @@
 	cpu_data(id).prom_node = cpu_node;
 	cpu_data(id).mid = cpu_get_hwmid(cpu_node);
 
-	/* this is required to tune the scheduler correctly */
-	/* is it possible to have CPUs with different cache sizes? */
-	if (id == boot_cpu_id) {
-		int cache_line,cache_nlines;
-		cache_line = 0x20;
-		cache_line = prom_getintdefault(cpu_node, "ecache-line-size", cache_line);
-		cache_nlines = 0x8000;
-		cache_nlines = prom_getintdefault(cpu_node, "ecache-nlines", cache_nlines);
-		max_cache_size = cache_line * cache_nlines;
-	}
 	if (cpu_data(id).mid < 0)
 		panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
 }
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index f1401b5..7b4612d 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -148,7 +148,7 @@
 }
 
 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
-static void __init kick_start_clock(void)
+static void __devinit kick_start_clock(void)
 {
 	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
 	unsigned char sec;
@@ -223,7 +223,7 @@
 	return (data1 == data2);	/* Was the write blocked? */
 }
 
-static void __init mostek_set_system_time(void)
+static void __devinit mostek_set_system_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
 	struct mostek48t02 *mregs;
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c
index dc9ffea..3bc3bff 100644
--- a/arch/sparc/kernel/traps.c
+++ b/arch/sparc/kernel/traps.c
@@ -101,6 +101,7 @@
 
 	printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
 	show_regs(regs);
+	add_taint(TAINT_DIE);
 
 	__SAVE; __SAVE; __SAVE; __SAVE;
 	__SAVE; __SAVE; __SAVE; __SAVE;
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index f0bb6e6..f75a1b8 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -12,7 +12,7 @@
   .text 0xf0004000 :
   {
     _text = .;
-    *(.text)
+    TEXT_TEXT
     SCHED_TEXT
     LOCK_TEXT
     *(.gnu.warning)
@@ -22,7 +22,7 @@
   RODATA
   .data    :
   {
-    *(.data)
+    DATA_DATA
     CONSTRUCTORS
   }
   .data1   : { *(.data1) }
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index 559335f..cbddeb3 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -2,6 +2,7 @@
  * atomic32.c: 32-bit atomic_t implementation
  *
  * Copyright (C) 2004 Keith M Wesolowski
+ * Copyright (C) 2007 Kyle McMartin
  * 
  * Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
  */
@@ -117,3 +118,17 @@
 	return old & mask;
 }
 EXPORT_SYMBOL(___change_bit);
+
+unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new)
+{
+	unsigned long flags;
+	u32 prev;
+
+	spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
+	if ((prev = *ptr) == old)
+		*ptr = new;
+	spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
+
+	return (unsigned long)prev;
+}
+EXPORT_SYMBOL(__cmpxchg_u32);
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index e5eaa80..ca26232 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -160,9 +160,6 @@
 static inline int srmmu_pte_present(pte_t pte)
 { return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE); }
 
-static inline int srmmu_pte_read(pte_t pte)
-{ return !(pte_val(pte) & SRMMU_NOREAD); }
-
 static inline void srmmu_pte_clear(pte_t *ptep)
 { srmmu_set_pte(ptep, __pte(0)); }
 
@@ -2181,7 +2178,6 @@
 
 	BTFIXUPSET_CALL(pte_present, srmmu_pte_present, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_SWAPO0G0);
-	BTFIXUPSET_CALL(pte_read, srmmu_pte_read, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(pmd_bad, srmmu_pmd_bad, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pmd_present, srmmu_pmd_present, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 436021c..bdd835fb 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1748,11 +1748,6 @@
 }
 static void sun4c_pte_clear(pte_t *ptep)	{ *ptep = __pte(0); }
 
-static int sun4c_pte_read(pte_t pte)
-{
-	return (pte_val(pte) & _SUN4C_PAGE_READ);
-}
-
 static int sun4c_pmd_bad(pmd_t pmd)
 {
 	return (((pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE) ||
@@ -2212,7 +2207,6 @@
 
 	BTFIXUPSET_CALL(pte_present, sun4c_pte_present, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pte_clear, sun4c_pte_clear, BTFIXUPCALL_STG0O0);
-	BTFIXUPSET_CALL(pte_read, sun4c_pte_read, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(pmd_bad, sun4c_pmd_bad, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pmd_present, sun4c_pmd_present, BTFIXUPCALL_NORM);
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 831781c..b84b6af 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -108,6 +108,15 @@
 
 source kernel/Kconfig.hz
 
+config HOTPLUG_CPU
+	bool "Support for hot-pluggable CPUs"
+	depends on SMP
+	select HOTPLUG
+	---help---
+	  Say Y here to experiment with turning CPUs off and on.  CPUs
+	  can be controlled through /sys/devices/system/cpu/cpu#.
+	  Say N if you want to disable CPU hotplug.
+
 source "init/Kconfig"
 
 config SYSVIPC_COMPAT
@@ -147,10 +156,10 @@
 	  If you don't know what to do here, say N.
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-64)"
-	range 2 64
+	int "Maximum number of CPUs (2-1024)"
+	range 2 1024
 	depends on SMP
-	default "32"
+	default "64"
 
 source "drivers/cpufreq/Kconfig"
 
@@ -305,6 +314,12 @@
 	bool
 	default y
 
+config SUN_LDOMS
+	bool "Sun Logical Domains support"
+	help
+	  Say Y here is you want to support virtual devices via
+	  Logical Domains.
+
 config PCI
 	bool "PCI support"
 	select ARCH_SUPPORTS_MSI
@@ -320,8 +335,10 @@
 	  doesn't.
 
 config PCI_DOMAINS
-	bool
-	default PCI
+	def_bool PCI
+
+config PCI_SYSCALL
+	def_bool PCI
 
 source "drivers/pci/Kconfig"
 
@@ -396,6 +413,15 @@
 	  when dealing with UltraSPARC cpus at a cost of slightly increased
 	  overhead in some places. If unsure say N here.
 
+config SCHED_MC
+	bool "Multi-core scheduler support"
+	depends on SMP
+	default y
+	help
+	  Multi-core scheduler support improves the CPU scheduler's decision
+	  making when dealing with multi-core CPU chips at a cost of slightly
+	  increased overhead in some places. If unsure say N here.
+
 source "kernel/Kconfig.preempt"
 
 config CMDLINE_BOOL
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 65840a6..45ebf91 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22-rc1
-# Mon May 14 04:17:48 2007
+# Linux kernel version: 2.6.22
+# Tue Jul 17 01:19:52 2007
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -42,12 +42,11 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=18
@@ -82,22 +81,15 @@
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
-
-#
-# Block layer
-#
 CONFIG_BLOCK=y
 CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_BLK_DEV_BSG=y
 
 #
 # IO Schedulers
@@ -156,12 +148,15 @@
 CONFIG_RESOURCES_64BIT=y
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=1
+CONFIG_VIRT_TO_BUS=y
 CONFIG_SBUS=y
 CONFIG_SBUSCHAR=y
 CONFIG_SUN_AUXIO=y
 CONFIG_SUN_IO=y
+# CONFIG_SUN_LDOMS is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
 CONFIG_ARCH_SUPPORTS_MSI=y
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
@@ -246,10 +241,6 @@
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 CONFIG_IP_DCCP=m
 CONFIG_INET_DCCP_DIAG=m
 CONFIG_IP_DCCP_ACKVEC=y
@@ -269,15 +260,7 @@
 #
 # CONFIG_IP_DCCP_DEBUG is not set
 # CONFIG_NET_DCCPPROBE is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -314,6 +297,7 @@
 # CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -328,26 +312,10 @@
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
 CONFIG_CONNECTOR=m
 # CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
@@ -364,18 +332,11 @@
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 CONFIG_CDROM_PKTCDVD_WCACHE=y
 CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
+CONFIG_MISC_DEVICES=y
 # CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-# CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -440,6 +401,7 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
 # CONFIG_SCSI_TGT is not set
 CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
@@ -505,7 +467,6 @@
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SUNESP is not set
 # CONFIG_SCSI_SRP is not set
 # CONFIG_ATA is not set
@@ -545,30 +506,16 @@
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
 # CONFIG_I2O is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
 # CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
 # CONFIG_SUNLANCE is not set
@@ -578,10 +525,6 @@
 # CONFIG_SUNGEM is not set
 CONFIG_CASSINI=m
 # CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
@@ -617,7 +560,6 @@
 # CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=m
 CONFIG_BNX2=m
@@ -631,11 +573,6 @@
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_MLX4_CORE is not set
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
 # CONFIG_TR is not set
 
 #
@@ -665,6 +602,7 @@
 CONFIG_PPP_BSDCOMP=m
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
 # CONFIG_SLIP is not set
 CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
@@ -677,10 +615,6 @@
 # ISDN subsystem
 #
 # CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
 # CONFIG_PHONE is not set
 
 #
@@ -688,6 +622,7 @@
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -733,7 +668,6 @@
 # CONFIG_INPUT_POWERMATE is not set
 # CONFIG_INPUT_YEALINK is not set
 # CONFIG_INPUT_UINPUT is not set
-# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Hardware I/O ports
@@ -773,10 +707,6 @@
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
@@ -785,10 +715,6 @@
 # CONFIG_APPLICOM is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
 CONFIG_DEVPORT=y
 CONFIG_I2C=y
@@ -822,6 +748,7 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_TAOS_EVM is not set
 # CONFIG_I2C_STUB is not set
 # CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
@@ -833,11 +760,13 @@
 #
 # CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -848,11 +777,8 @@
 #
 # CONFIG_SPI is not set
 # CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
@@ -949,6 +875,8 @@
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_SBUS is not set
+# CONFIG_FB_XVR500 is not set
+# CONFIG_FB_XVR2500 is not set
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
@@ -970,9 +898,6 @@
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_ARK is not set
 # CONFIG_FB_PM3 is not set
-# CONFIG_FB_XVR500 is not set
-# CONFIG_FB_XVR2500 is not set
-# CONFIG_FB_PCI is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -1118,10 +1043,7 @@
 #
 # CONFIG_SOUND_PRIME is not set
 CONFIG_AC97_BUS=m
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
 
@@ -1132,10 +1054,7 @@
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
-
-#
-# USB support
-#
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB_ARCH_HAS_EHCI=y
@@ -1157,7 +1076,6 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
-# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
@@ -1165,6 +1083,7 @@
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=m
 # CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
 
 #
 # USB Device Class drivers
@@ -1256,17 +1175,9 @@
 #
 # LED Triggers
 #
-
-#
-# InfiniBand support
-#
 # CONFIG_INFINIBAND is not set
 
 #
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
 # Real Time Clock
 #
 # CONFIG_RTC_CLASS is not set
@@ -1387,7 +1298,6 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -1465,8 +1375,10 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHEDSTATS=y
 # CONFIG_TIMER_STATS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1496,10 +1408,10 @@
 CONFIG_KEYS=y
 # CONFIG_KEYS_DEBUG_PROC_KEYS is not set
 # CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=y
@@ -1539,10 +1451,7 @@
 CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_TEST=m
-
-#
-# Hardware crypto devices
-#
+CONFIG_CRYPTO_HW=y
 
 #
 # Library routines
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index c749dcc..b66876b 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.70 2002/02/09 19:49:30 davem Exp $
+#
 # Makefile for the linux kernel.
 #
 
@@ -8,17 +8,17 @@
 extra-y		:= head.o init_task.o vmlinux.lds
 
 obj-y		:= process.o setup.o cpu.o idprom.o \
-		   traps.o devices.o auxio.o una_asm.o \
+		   traps.o auxio.o una_asm.o sysfs.o \
 		   irq.o ptrace.o time.o sys_sparc.o signal.o \
 		   unaligned.o central.o pci.o starfire.o semaphore.o \
 		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
-		   visemul.o prom.o of_device.o hvapi.o
+		   visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
 			    pci_psycho.o pci_sabre.o pci_schizo.o \
 			    pci_sun4v.o pci_sun4v_asm.o pci_fire.o
-obj-$(CONFIG_SMP)	 += smp.o trampoline.o
+obj-$(CONFIG_SMP)	 += smp.o trampoline.o hvtramp.o
 obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
 obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
 obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
@@ -26,6 +26,7 @@
 obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
 obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
 obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o
 obj-$(CONFIG_AUDIT) += audit.o
 obj-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o
 obj-y += $(obj-yy)
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
deleted file mode 100644
index 0e03c8e..0000000
--- a/arch/sparc64/kernel/devices.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* devices.c: Initial scan of the prom device tree for important
- *            Sparc device nodes which we need to find.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/threads.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/bootmem.h>
-
-#include <asm/page.h>
-#include <asm/oplib.h>
-#include <asm/system.h>
-#include <asm/smp.h>
-#include <asm/spitfire.h>
-#include <asm/timer.h>
-#include <asm/cpudata.h>
-
-/* Used to synchronize accesses to NatSemi SUPER I/O chip configure
- * operations in asm/ns87303.h
- */
-DEFINE_SPINLOCK(ns87303_lock);
-
-extern void cpu_probe(void);
-extern void central_probe(void);
-
-static const char *cpu_mid_prop(void)
-{
-	if (tlb_type == spitfire)
-		return "upa-portid";
-	return "portid";
-}
-
-static int get_cpu_mid(struct device_node *dp)
-{
-	struct property *prop;
-
-	if (tlb_type == hypervisor) {
-		struct linux_prom64_registers *reg;
-		int len;
-
-		prop = of_find_property(dp, "cpuid", &len);
-		if (prop && len == 4)
-			return *(int *) prop->value;
-
-		prop = of_find_property(dp, "reg", NULL);
-		reg = prop->value;
-		return (reg[0].phys_addr >> 32) & 0x0fffffffUL;
-	} else {
-		const char *prop_name = cpu_mid_prop();
-
-		prop = of_find_property(dp, prop_name, NULL);
-		if (prop)
-			return *(int *) prop->value;
-		return 0;
-	}
-}
-
-static int check_cpu_node(struct device_node *dp, int *cur_inst,
-			  int (*compare)(struct device_node *, int, void *),
-			  void *compare_arg,
-			  struct device_node **dev_node, int *mid)
-{
-	if (!compare(dp, *cur_inst, compare_arg)) {
-		if (dev_node)
-			*dev_node = dp;
-		if (mid)
-			*mid = get_cpu_mid(dp);
-		return 0;
-	}
-
-	(*cur_inst)++;
-
-	return -ENODEV;
-}
-
-static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
-			 void *compare_arg,
-			 struct device_node **dev_node, int *mid)
-{
-	struct device_node *dp;
-	int cur_inst;
-
-	cur_inst = 0;
-	for_each_node_by_type(dp, "cpu") {
-		int err = check_cpu_node(dp, &cur_inst,
-					 compare, compare_arg,
-					 dev_node, mid);
-		if (err == 0)
-			return 0;
-	}
-
-	return -ENODEV;
-}
-
-static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
-{
-	int desired_instance = (int) (long) _arg;
-
-	if (instance == desired_instance)
-		return 0;
-	return -ENODEV;
-}
-
-int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
-{
-	return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
-			     dev_node, mid);
-}
-
-static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
-{
-	int desired_mid = (int) (long) _arg;
-	int this_mid;
-
-	this_mid = get_cpu_mid(dp);
-	if (this_mid == desired_mid)
-		return 0;
-	return -ENODEV;
-}
-
-int cpu_find_by_mid(int mid, struct device_node **dev_node)
-{
-	return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
-			     dev_node, NULL);
-}
-
-void __init device_scan(void)
-{
-	/* FIX ME FAST... -DaveM */
-	ioport_resource.end = 0xffffffffffffffffUL;
-
-	prom_printf("Booting Linux...\n");
-
-#ifndef CONFIG_SMP
-	{
-		struct device_node *dp;
-		int err, def;
-
-		err = cpu_find_by_instance(0, &dp, NULL);
-		if (err) {
-			prom_printf("No cpu nodes, cannot continue\n");
-			prom_halt();
-		}
-		cpu_data(0).clock_tick =
-			of_getintprop_default(dp, "clock-frequency", 0);
-
-		def = ((tlb_type == hypervisor) ?
-		       (8 * 1024) :
-		       (16 * 1024));
-		cpu_data(0).dcache_size = of_getintprop_default(dp,
-								"dcache-size",
-								def);
-
-		def = 32;
-		cpu_data(0).dcache_line_size =
-			of_getintprop_default(dp, "dcache-line-size", def);
-
-		def = 16 * 1024;
-		cpu_data(0).icache_size = of_getintprop_default(dp,
-								"icache-size",
-								def);
-
-		def = 32;
-		cpu_data(0).icache_line_size =
-			of_getintprop_default(dp, "icache-line-size", def);
-
-		def = ((tlb_type == hypervisor) ?
-		       (3 * 1024 * 1024) :
-		       (4 * 1024 * 1024));
-		cpu_data(0).ecache_size = of_getintprop_default(dp,
-								"ecache-size",
-								def);
-
-		def = 64;
-		cpu_data(0).ecache_line_size =
-			of_getintprop_default(dp, "ecache-line-size", def);
-		printk("CPU[0]: Caches "
-		       "D[sz(%d):line_sz(%d)] "
-		       "I[sz(%d):line_sz(%d)] "
-		       "E[sz(%d):line_sz(%d)]\n",
-		       cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
-		       cpu_data(0).icache_size, cpu_data(0).icache_line_size,
-		       cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
-	}
-#endif
-
-	central_probe();
-
-	cpu_probe();
-}
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c
new file mode 100644
index 0000000..ba01533
--- /dev/null
+++ b/arch/sparc64/kernel/ds.c
@@ -0,0 +1,1168 @@
+/* ds.c: Domain Services driver for Logical Domains
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/cpu.h>
+
+#include <asm/ldc.h>
+#include <asm/vio.h>
+#include <asm/power.h>
+#include <asm/mdesc.h>
+#include <asm/head.h>
+#include <asm/irq.h>
+
+#define DRV_MODULE_NAME		"ds"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"Jul 11, 2007"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM domain services driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+struct ds_msg_tag {
+	__u32			type;
+#define DS_INIT_REQ		0x00
+#define DS_INIT_ACK		0x01
+#define DS_INIT_NACK		0x02
+#define DS_REG_REQ		0x03
+#define DS_REG_ACK		0x04
+#define DS_REG_NACK		0x05
+#define DS_UNREG_REQ		0x06
+#define DS_UNREG_ACK		0x07
+#define DS_UNREG_NACK		0x08
+#define DS_DATA			0x09
+#define DS_NACK			0x0a
+
+	__u32			len;
+};
+
+/* Result codes */
+#define DS_OK			0x00
+#define DS_REG_VER_NACK		0x01
+#define DS_REG_DUP		0x02
+#define DS_INV_HDL		0x03
+#define DS_TYPE_UNKNOWN		0x04
+
+struct ds_version {
+	__u16			major;
+	__u16			minor;
+};
+
+struct ds_ver_req {
+	struct ds_msg_tag	tag;
+	struct ds_version	ver;
+};
+
+struct ds_ver_ack {
+	struct ds_msg_tag	tag;
+	__u16			minor;
+};
+
+struct ds_ver_nack {
+	struct ds_msg_tag	tag;
+	__u16			major;
+};
+
+struct ds_reg_req {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+	__u16			major;
+	__u16			minor;
+	char			svc_id[0];
+};
+
+struct ds_reg_ack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+	__u16			minor;
+};
+
+struct ds_reg_nack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+	__u16			major;
+};
+
+struct ds_unreg_req {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+};
+
+struct ds_unreg_ack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+};
+
+struct ds_unreg_nack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+};
+
+struct ds_data {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+};
+
+struct ds_data_nack {
+	struct ds_msg_tag	tag;
+	__u64			handle;
+	__u64			result;
+};
+
+struct ds_cap_state {
+	__u64			handle;
+
+	void			(*data)(struct ldc_channel *lp,
+					struct ds_cap_state *cp,
+					void *buf, int len);
+
+	const char		*service_id;
+
+	u8			state;
+#define CAP_STATE_UNKNOWN	0x00
+#define CAP_STATE_REG_SENT	0x01
+#define CAP_STATE_REGISTERED	0x02
+};
+
+static void md_update_data(struct ldc_channel *lp, struct ds_cap_state *cp,
+			   void *buf, int len);
+static void domain_shutdown_data(struct ldc_channel *lp,
+				 struct ds_cap_state *cp,
+				 void *buf, int len);
+static void domain_panic_data(struct ldc_channel *lp,
+			      struct ds_cap_state *cp,
+			      void *buf, int len);
+#ifdef CONFIG_HOTPLUG_CPU
+static void dr_cpu_data(struct ldc_channel *lp,
+			struct ds_cap_state *cp,
+			void *buf, int len);
+#endif
+static void ds_pri_data(struct ldc_channel *lp,
+			struct ds_cap_state *cp,
+			void *buf, int len);
+static void ds_var_data(struct ldc_channel *lp,
+			struct ds_cap_state *cp,
+			void *buf, int len);
+
+struct ds_cap_state ds_states[] = {
+	{
+		.service_id	= "md-update",
+		.data		= md_update_data,
+	},
+	{
+		.service_id	= "domain-shutdown",
+		.data		= domain_shutdown_data,
+	},
+	{
+		.service_id	= "domain-panic",
+		.data		= domain_panic_data,
+	},
+#ifdef CONFIG_HOTPLUG_CPU
+	{
+		.service_id	= "dr-cpu",
+		.data		= dr_cpu_data,
+	},
+#endif
+	{
+		.service_id	= "pri",
+		.data		= ds_pri_data,
+	},
+	{
+		.service_id	= "var-config",
+		.data		= ds_var_data,
+	},
+	{
+		.service_id	= "var-config-backup",
+		.data		= ds_var_data,
+	},
+};
+
+static DEFINE_SPINLOCK(ds_lock);
+
+struct ds_info {
+	struct ldc_channel	*lp;
+	u8			hs_state;
+#define DS_HS_START		0x01
+#define DS_HS_DONE		0x02
+
+	void			*rcv_buf;
+	int			rcv_buf_len;
+};
+
+static struct ds_info *ds_info;
+
+static struct ds_cap_state *find_cap(u64 handle)
+{
+	unsigned int index = handle >> 32;
+
+	if (index >= ARRAY_SIZE(ds_states))
+		return NULL;
+	return &ds_states[index];
+}
+
+static struct ds_cap_state *find_cap_by_string(const char *name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
+		if (strcmp(ds_states[i].service_id, name))
+			continue;
+
+		return &ds_states[i];
+	}
+	return NULL;
+}
+
+static int __ds_send(struct ldc_channel *lp, void *data, int len)
+{
+	int err, limit = 1000;
+
+	err = -EINVAL;
+	while (limit-- > 0) {
+		err = ldc_write(lp, data, len);
+		if (!err || (err != -EAGAIN))
+			break;
+		udelay(1);
+	}
+
+	return err;
+}
+
+static int ds_send(struct ldc_channel *lp, void *data, int len)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&ds_lock, flags);
+	err = __ds_send(lp, data, len);
+	spin_unlock_irqrestore(&ds_lock, flags);
+
+	return err;
+}
+
+struct ds_md_update_req {
+	__u64				req_num;
+};
+
+struct ds_md_update_res {
+	__u64				req_num;
+	__u32				result;
+};
+
+static void md_update_data(struct ldc_channel *lp,
+			   struct ds_cap_state *dp,
+			   void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_md_update_req *rp;
+	struct {
+		struct ds_data		data;
+		struct ds_md_update_res	res;
+	} pkt;
+
+	rp = (struct ds_md_update_req *) (dpkt + 1);
+
+	printk(KERN_INFO PFX "Machine description update.\n");
+
+	mdesc_update();
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.data.tag.type = DS_DATA;
+	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+	pkt.data.handle = dp->handle;
+	pkt.res.req_num = rp->req_num;
+	pkt.res.result = DS_OK;
+
+	ds_send(lp, &pkt, sizeof(pkt));
+}
+
+struct ds_shutdown_req {
+	__u64				req_num;
+	__u32				ms_delay;
+};
+
+struct ds_shutdown_res {
+	__u64				req_num;
+	__u32				result;
+	char				reason[1];
+};
+
+static void domain_shutdown_data(struct ldc_channel *lp,
+				 struct ds_cap_state *dp,
+				 void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_shutdown_req *rp;
+	struct {
+		struct ds_data		data;
+		struct ds_shutdown_res	res;
+	} pkt;
+
+	rp = (struct ds_shutdown_req *) (dpkt + 1);
+
+	printk(KERN_ALERT PFX "Shutdown request from "
+	       "LDOM manager received.\n");
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.data.tag.type = DS_DATA;
+	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+	pkt.data.handle = dp->handle;
+	pkt.res.req_num = rp->req_num;
+	pkt.res.result = DS_OK;
+	pkt.res.reason[0] = 0;
+
+	ds_send(lp, &pkt, sizeof(pkt));
+
+	wake_up_powerd();
+}
+
+struct ds_panic_req {
+	__u64				req_num;
+};
+
+struct ds_panic_res {
+	__u64				req_num;
+	__u32				result;
+	char				reason[1];
+};
+
+static void domain_panic_data(struct ldc_channel *lp,
+			      struct ds_cap_state *dp,
+			      void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_panic_req *rp;
+	struct {
+		struct ds_data		data;
+		struct ds_panic_res	res;
+	} pkt;
+
+	rp = (struct ds_panic_req *) (dpkt + 1);
+
+	printk(KERN_ALERT PFX "Panic request from "
+	       "LDOM manager received.\n");
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.data.tag.type = DS_DATA;
+	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+	pkt.data.handle = dp->handle;
+	pkt.res.req_num = rp->req_num;
+	pkt.res.result = DS_OK;
+	pkt.res.reason[0] = 0;
+
+	ds_send(lp, &pkt, sizeof(pkt));
+
+	panic("PANIC requested by LDOM manager.");
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+struct dr_cpu_tag {
+	__u64				req_num;
+	__u32				type;
+#define DR_CPU_CONFIGURE		0x43
+#define DR_CPU_UNCONFIGURE		0x55
+#define DR_CPU_FORCE_UNCONFIGURE	0x46
+#define DR_CPU_STATUS			0x53
+
+/* Responses */
+#define DR_CPU_OK			0x6f
+#define DR_CPU_ERROR			0x65
+
+	__u32				num_records;
+};
+
+struct dr_cpu_resp_entry {
+	__u32				cpu;
+	__u32				result;
+#define DR_CPU_RES_OK			0x00
+#define DR_CPU_RES_FAILURE		0x01
+#define DR_CPU_RES_BLOCKED		0x02
+#define DR_CPU_RES_CPU_NOT_RESPONDING	0x03
+#define DR_CPU_RES_NOT_IN_MD		0x04
+
+	__u32				stat;
+#define DR_CPU_STAT_NOT_PRESENT		0x00
+#define DR_CPU_STAT_UNCONFIGURED	0x01
+#define DR_CPU_STAT_CONFIGURED		0x02
+
+	__u32				str_off;
+};
+
+static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data)
+{
+	struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
+	struct ds_info *dp = ds_info;
+	struct {
+		struct ds_data		data;
+		struct dr_cpu_tag	tag;
+	} pkt;
+	int msg_len;
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.data.tag.type = DS_DATA;
+	pkt.data.handle = cp->handle;
+	pkt.tag.req_num = tag->req_num;
+	pkt.tag.type = DR_CPU_ERROR;
+	pkt.tag.num_records = 0;
+
+	msg_len = (sizeof(struct ds_data) +
+		   sizeof(struct dr_cpu_tag));
+
+	pkt.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
+
+	__ds_send(dp->lp, &pkt, msg_len);
+}
+
+static void dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ds_lock, flags);
+	__dr_cpu_send_error(cp, data);
+	spin_unlock_irqrestore(&ds_lock, flags);
+}
+
+#define CPU_SENTINEL	0xffffffff
+
+static void purge_dups(u32 *list, u32 num_ents)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_ents; i++) {
+		u32 cpu = list[i];
+		unsigned int j;
+
+		if (cpu == CPU_SENTINEL)
+			continue;
+
+		for (j = i + 1; j < num_ents; j++) {
+			if (list[j] == cpu)
+				list[j] = CPU_SENTINEL;
+		}
+	}
+}
+
+static int dr_cpu_size_response(int ncpus)
+{
+	return (sizeof(struct ds_data) +
+		sizeof(struct dr_cpu_tag) +
+		(sizeof(struct dr_cpu_resp_entry) * ncpus));
+}
+
+static void dr_cpu_init_response(struct ds_data *resp, u64 req_num,
+				 u64 handle, int resp_len, int ncpus,
+				 cpumask_t *mask, u32 default_stat)
+{
+	struct dr_cpu_resp_entry *ent;
+	struct dr_cpu_tag *tag;
+	int i, cpu;
+
+	tag = (struct dr_cpu_tag *) (resp + 1);
+	ent = (struct dr_cpu_resp_entry *) (tag + 1);
+
+	resp->tag.type = DS_DATA;
+	resp->tag.len = resp_len - sizeof(struct ds_msg_tag);
+	resp->handle = handle;
+	tag->req_num = req_num;
+	tag->type = DR_CPU_OK;
+	tag->num_records = ncpus;
+
+	i = 0;
+	for_each_cpu_mask(cpu, *mask) {
+		ent[i].cpu = cpu;
+		ent[i].result = DR_CPU_RES_OK;
+		ent[i].stat = default_stat;
+		i++;
+	}
+	BUG_ON(i != ncpus);
+}
+
+static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus,
+			u32 res, u32 stat)
+{
+	struct dr_cpu_resp_entry *ent;
+	struct dr_cpu_tag *tag;
+	int i;
+
+	tag = (struct dr_cpu_tag *) (resp + 1);
+	ent = (struct dr_cpu_resp_entry *) (tag + 1);
+
+	for (i = 0; i < ncpus; i++) {
+		if (ent[i].cpu != cpu)
+			continue;
+		ent[i].result = res;
+		ent[i].stat = stat;
+		break;
+	}
+}
+
+static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num,
+			    cpumask_t *mask)
+{
+	struct ds_data *resp;
+	int resp_len, ncpus, cpu;
+	unsigned long flags;
+
+	ncpus = cpus_weight(*mask);
+	resp_len = dr_cpu_size_response(ncpus);
+	resp = kzalloc(resp_len, GFP_KERNEL);
+	if (!resp)
+		return -ENOMEM;
+
+	dr_cpu_init_response(resp, req_num, cp->handle,
+			     resp_len, ncpus, mask,
+			     DR_CPU_STAT_CONFIGURED);
+
+	mdesc_fill_in_cpu_data(*mask);
+
+	for_each_cpu_mask(cpu, *mask) {
+		int err;
+
+		printk(KERN_INFO PFX "Starting cpu %d...\n", cpu);
+		err = cpu_up(cpu);
+		if (err) {
+			__u32 res = DR_CPU_RES_FAILURE;
+			__u32 stat = DR_CPU_STAT_UNCONFIGURED;
+
+			if (!cpu_present(cpu)) {
+				/* CPU not present in MD */
+				res = DR_CPU_RES_NOT_IN_MD;
+				stat = DR_CPU_STAT_NOT_PRESENT;
+			} else if (err == -ENODEV) {
+				/* CPU did not call in successfully */
+				res = DR_CPU_RES_CPU_NOT_RESPONDING;
+			}
+
+			printk(KERN_INFO PFX "CPU startup failed err=%d\n",
+			       err);
+			dr_cpu_mark(resp, cpu, ncpus, res, stat);
+		}
+	}
+
+	spin_lock_irqsave(&ds_lock, flags);
+	__ds_send(ds_info->lp, resp, resp_len);
+	spin_unlock_irqrestore(&ds_lock, flags);
+
+	kfree(resp);
+
+	/* Redistribute IRQs, taking into account the new cpus.  */
+	fixup_irqs();
+
+	return 0;
+}
+
+static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num,
+			      cpumask_t *mask)
+{
+	struct ds_data *resp;
+	int resp_len, ncpus, cpu;
+	unsigned long flags;
+
+	ncpus = cpus_weight(*mask);
+	resp_len = dr_cpu_size_response(ncpus);
+	resp = kzalloc(resp_len, GFP_KERNEL);
+	if (!resp)
+		return -ENOMEM;
+
+	dr_cpu_init_response(resp, req_num, cp->handle,
+			     resp_len, ncpus, mask,
+			     DR_CPU_STAT_UNCONFIGURED);
+
+	for_each_cpu_mask(cpu, *mask) {
+		int err;
+
+		printk(KERN_INFO PFX "CPU[%d]: Shutting down cpu %d...\n",
+		       smp_processor_id(), cpu);
+		err = cpu_down(cpu);
+		if (err)
+			dr_cpu_mark(resp, cpu, ncpus,
+				    DR_CPU_RES_FAILURE,
+				    DR_CPU_STAT_CONFIGURED);
+	}
+
+	spin_lock_irqsave(&ds_lock, flags);
+	__ds_send(ds_info->lp, resp, resp_len);
+	spin_unlock_irqrestore(&ds_lock, flags);
+
+	kfree(resp);
+
+	return 0;
+}
+
+static void dr_cpu_data(struct ldc_channel *lp,
+			struct ds_cap_state *cp,
+			void *buf, int len)
+{
+	struct ds_data *data = buf;
+	struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
+	u32 *cpu_list = (u32 *) (tag + 1);
+	u64 req_num = tag->req_num;
+	cpumask_t mask;
+	unsigned int i;
+	int err;
+
+	switch (tag->type) {
+	case DR_CPU_CONFIGURE:
+	case DR_CPU_UNCONFIGURE:
+	case DR_CPU_FORCE_UNCONFIGURE:
+		break;
+
+	default:
+		dr_cpu_send_error(cp, data);
+		return;
+	}
+
+	purge_dups(cpu_list, tag->num_records);
+
+	cpus_clear(mask);
+	for (i = 0; i < tag->num_records; i++) {
+		if (cpu_list[i] == CPU_SENTINEL)
+			continue;
+
+		if (cpu_list[i] < NR_CPUS)
+			cpu_set(cpu_list[i], mask);
+	}
+
+	if (tag->type == DR_CPU_CONFIGURE)
+		err = dr_cpu_configure(cp, req_num, &mask);
+	else
+		err = dr_cpu_unconfigure(cp, req_num, &mask);
+
+	if (err)
+		dr_cpu_send_error(cp, data);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+struct ds_pri_msg {
+	__u64				req_num;
+	__u64				type;
+#define DS_PRI_REQUEST			0x00
+#define DS_PRI_DATA			0x01
+#define DS_PRI_UPDATE			0x02
+};
+
+static void ds_pri_data(struct ldc_channel *lp,
+			struct ds_cap_state *dp,
+			void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_pri_msg *rp;
+
+	rp = (struct ds_pri_msg *) (dpkt + 1);
+
+	printk(KERN_INFO PFX "PRI REQ [%lx:%lx], len=%d\n",
+	       rp->req_num, rp->type, len);
+}
+
+struct ds_var_hdr {
+	__u32				type;
+#define DS_VAR_SET_REQ			0x00
+#define DS_VAR_DELETE_REQ		0x01
+#define DS_VAR_SET_RESP			0x02
+#define DS_VAR_DELETE_RESP		0x03
+};
+
+struct ds_var_set_msg {
+	struct ds_var_hdr		hdr;
+	char				name_and_value[0];
+};
+
+struct ds_var_delete_msg {
+	struct ds_var_hdr		hdr;
+	char				name[0];
+};
+
+struct ds_var_resp {
+	struct ds_var_hdr		hdr;
+	__u32				result;
+#define DS_VAR_SUCCESS			0x00
+#define DS_VAR_NO_SPACE			0x01
+#define DS_VAR_INVALID_VAR		0x02
+#define DS_VAR_INVALID_VAL		0x03
+#define DS_VAR_NOT_PRESENT		0x04
+};
+
+static DEFINE_MUTEX(ds_var_mutex);
+static int ds_var_doorbell;
+static int ds_var_response;
+
+static void ds_var_data(struct ldc_channel *lp,
+			struct ds_cap_state *dp,
+			void *buf, int len)
+{
+	struct ds_data *dpkt = buf;
+	struct ds_var_resp *rp;
+
+	rp = (struct ds_var_resp *) (dpkt + 1);
+
+	if (rp->hdr.type != DS_VAR_SET_RESP &&
+	    rp->hdr.type != DS_VAR_DELETE_RESP)
+		return;
+
+	ds_var_response = rp->result;
+	wmb();
+	ds_var_doorbell = 1;
+}
+
+void ldom_set_var(const char *var, const char *value)
+{
+	struct ds_info *dp = ds_info;
+	struct ds_cap_state *cp;
+
+	cp = find_cap_by_string("var-config");
+	if (cp->state != CAP_STATE_REGISTERED)
+		cp = find_cap_by_string("var-config-backup");
+
+	if (cp->state == CAP_STATE_REGISTERED) {
+		union {
+			struct {
+				struct ds_data		data;
+				struct ds_var_set_msg	msg;
+			} header;
+			char			all[512];
+		} pkt;
+		unsigned long flags;
+		char  *base, *p;
+		int msg_len, loops;
+
+		memset(&pkt, 0, sizeof(pkt));
+		pkt.header.data.tag.type = DS_DATA;
+		pkt.header.data.handle = cp->handle;
+		pkt.header.msg.hdr.type = DS_VAR_SET_REQ;
+		base = p = &pkt.header.msg.name_and_value[0];
+		strcpy(p, var);
+		p += strlen(var) + 1;
+		strcpy(p, value);
+		p += strlen(value) + 1;
+
+		msg_len = (sizeof(struct ds_data) +
+			   sizeof(struct ds_var_set_msg) +
+			   (p - base));
+		msg_len = (msg_len + 3) & ~3;
+		pkt.header.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
+
+		mutex_lock(&ds_var_mutex);
+
+		spin_lock_irqsave(&ds_lock, flags);
+		ds_var_doorbell = 0;
+		ds_var_response = -1;
+
+		__ds_send(dp->lp, &pkt, msg_len);
+		spin_unlock_irqrestore(&ds_lock, flags);
+
+		loops = 1000;
+		while (ds_var_doorbell == 0) {
+			if (loops-- < 0)
+				break;
+			barrier();
+			udelay(100);
+		}
+
+		mutex_unlock(&ds_var_mutex);
+
+		if (ds_var_doorbell == 0 ||
+		    ds_var_response != DS_VAR_SUCCESS)
+			printk(KERN_ERR PFX "var-config [%s:%s] "
+			       "failed, response(%d).\n",
+			       var, value,
+			       ds_var_response);
+	} else {
+		printk(KERN_ERR PFX "var-config not registered so "
+		       "could not set (%s) variable to (%s).\n",
+		       var, value);
+	}
+}
+
+void ldom_reboot(const char *boot_command)
+{
+	/* Don't bother with any of this if the boot_command
+	 * is empty.
+	 */
+	if (boot_command && strlen(boot_command)) {
+		char full_boot_str[256];
+
+		strcpy(full_boot_str, "boot ");
+		strcpy(full_boot_str + strlen("boot "), boot_command);
+
+		ldom_set_var("reboot-command", full_boot_str);
+	}
+	sun4v_mach_sir();
+}
+
+void ldom_power_off(void)
+{
+	sun4v_mach_exit(0);
+}
+
+static void ds_conn_reset(struct ds_info *dp)
+{
+	printk(KERN_ERR PFX "ds_conn_reset() from %p\n",
+	       __builtin_return_address(0));
+}
+
+static int register_services(struct ds_info *dp)
+{
+	struct ldc_channel *lp = dp->lp;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
+		struct {
+			struct ds_reg_req req;
+			u8 id_buf[256];
+		} pbuf;
+		struct ds_cap_state *cp = &ds_states[i];
+		int err, msg_len;
+		u64 new_count;
+
+		if (cp->state == CAP_STATE_REGISTERED)
+			continue;
+
+		new_count = sched_clock() & 0xffffffff;
+		cp->handle = ((u64) i << 32) | new_count;
+
+		msg_len = (sizeof(struct ds_reg_req) +
+			   strlen(cp->service_id));
+
+		memset(&pbuf, 0, sizeof(pbuf));
+		pbuf.req.tag.type = DS_REG_REQ;
+		pbuf.req.tag.len = (msg_len - sizeof(struct ds_msg_tag));
+		pbuf.req.handle = cp->handle;
+		pbuf.req.major = 1;
+		pbuf.req.minor = 0;
+		strcpy(pbuf.req.svc_id, cp->service_id);
+
+		err = __ds_send(lp, &pbuf, msg_len);
+		if (err > 0)
+			cp->state = CAP_STATE_REG_SENT;
+	}
+	return 0;
+}
+
+static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
+{
+
+	if (dp->hs_state == DS_HS_START) {
+		if (pkt->type != DS_INIT_ACK)
+			goto conn_reset;
+
+		dp->hs_state = DS_HS_DONE;
+
+		return register_services(dp);
+	}
+
+	if (dp->hs_state != DS_HS_DONE)
+		goto conn_reset;
+
+	if (pkt->type == DS_REG_ACK) {
+		struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt;
+		struct ds_cap_state *cp = find_cap(ap->handle);
+
+		if (!cp) {
+			printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n",
+			       ap->handle);
+			return 0;
+		}
+		printk(KERN_INFO PFX "Registered %s service.\n",
+		       cp->service_id);
+		cp->state = CAP_STATE_REGISTERED;
+	} else if (pkt->type == DS_REG_NACK) {
+		struct ds_reg_nack *np = (struct ds_reg_nack *) pkt;
+		struct ds_cap_state *cp = find_cap(np->handle);
+
+		if (!cp) {
+			printk(KERN_ERR PFX "REG NACK for "
+			       "unknown handle %lx\n",
+			       np->handle);
+			return 0;
+		}
+		printk(KERN_INFO PFX "Could not register %s service\n",
+		       cp->service_id);
+		cp->state = CAP_STATE_UNKNOWN;
+	}
+
+	return 0;
+
+conn_reset:
+	ds_conn_reset(dp);
+	return -ECONNRESET;
+}
+
+static void __send_ds_nack(struct ds_info *dp, u64 handle)
+{
+	struct ds_data_nack nack = {
+		.tag = {
+			.type = DS_NACK,
+			.len = (sizeof(struct ds_data_nack) -
+				sizeof(struct ds_msg_tag)),
+		},
+		.handle = handle,
+		.result = DS_INV_HDL,
+	};
+
+	__ds_send(dp->lp, &nack, sizeof(nack));
+}
+
+static LIST_HEAD(ds_work_list);
+static DECLARE_WAIT_QUEUE_HEAD(ds_wait);
+
+struct ds_queue_entry {
+	struct list_head		list;
+	int				req_len;
+	int				__pad;
+	u64				req[0];
+};
+
+static void process_ds_work(void)
+{
+	struct ds_queue_entry *qp, *tmp;
+	static struct ds_info *dp;
+	unsigned long flags;
+	LIST_HEAD(todo);
+
+	spin_lock_irqsave(&ds_lock, flags);
+	list_splice(&ds_work_list, &todo);
+	INIT_LIST_HEAD(&ds_work_list);
+	spin_unlock_irqrestore(&ds_lock, flags);
+
+	dp = ds_info;
+
+	list_for_each_entry_safe(qp, tmp, &todo, list) {
+		struct ds_data *dpkt = (struct ds_data *) qp->req;
+		struct ds_cap_state *cp = find_cap(dpkt->handle);
+		int req_len = qp->req_len;
+
+		if (!cp) {
+			printk(KERN_ERR PFX "Data for unknown handle %lu\n",
+			       dpkt->handle);
+
+			spin_lock_irqsave(&ds_lock, flags);
+			__send_ds_nack(dp, dpkt->handle);
+			spin_unlock_irqrestore(&ds_lock, flags);
+		} else {
+			cp->data(dp->lp, cp, dpkt, req_len);
+		}
+
+		list_del(&qp->list);
+		kfree(qp);
+	}
+}
+
+static int ds_thread(void *__unused)
+{
+	DEFINE_WAIT(wait);
+
+	while (1) {
+		prepare_to_wait(&ds_wait, &wait, TASK_INTERRUPTIBLE);
+		if (list_empty(&ds_work_list))
+			schedule();
+		finish_wait(&ds_wait, &wait);
+
+		if (kthread_should_stop())
+			break;
+
+		process_ds_work();
+	}
+
+	return 0;
+}
+
+static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
+{
+	struct ds_data *dpkt = (struct ds_data *) pkt;
+	struct ds_queue_entry *qp;
+
+	qp = kmalloc(sizeof(struct ds_queue_entry) + len, GFP_ATOMIC);
+	if (!qp) {
+		__send_ds_nack(dp, dpkt->handle);
+	} else {
+		memcpy(&qp->req, pkt, len);
+		list_add_tail(&qp->list, &ds_work_list);
+		wake_up(&ds_wait);
+	}
+	return 0;
+}
+
+static void ds_up(struct ds_info *dp)
+{
+	struct ldc_channel *lp = dp->lp;
+	struct ds_ver_req req;
+	int err;
+
+	req.tag.type = DS_INIT_REQ;
+	req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
+	req.ver.major = 1;
+	req.ver.minor = 0;
+
+	err = __ds_send(lp, &req, sizeof(req));
+	if (err > 0)
+		dp->hs_state = DS_HS_START;
+}
+
+static void ds_event(void *arg, int event)
+{
+	struct ds_info *dp = arg;
+	struct ldc_channel *lp = dp->lp;
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&ds_lock, flags);
+
+	if (event == LDC_EVENT_UP) {
+		ds_up(dp);
+		spin_unlock_irqrestore(&ds_lock, flags);
+		return;
+	}
+
+	if (event != LDC_EVENT_DATA_READY) {
+		printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+		spin_unlock_irqrestore(&ds_lock, flags);
+		return;
+	}
+
+	err = 0;
+	while (1) {
+		struct ds_msg_tag *tag;
+
+		err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));
+
+		if (unlikely(err < 0)) {
+			if (err == -ECONNRESET)
+				ds_conn_reset(dp);
+			break;
+		}
+		if (err == 0)
+			break;
+
+		tag = dp->rcv_buf;
+		err = ldc_read(lp, tag + 1, tag->len);
+
+		if (unlikely(err < 0)) {
+			if (err == -ECONNRESET)
+				ds_conn_reset(dp);
+			break;
+		}
+		if (err < tag->len)
+			break;
+
+		if (tag->type < DS_DATA)
+			err = ds_handshake(dp, dp->rcv_buf);
+		else
+			err = ds_data(dp, dp->rcv_buf,
+				      sizeof(*tag) + err);
+		if (err == -ECONNRESET)
+			break;
+	}
+
+	spin_unlock_irqrestore(&ds_lock, flags);
+}
+
+static int __devinit ds_probe(struct vio_dev *vdev,
+			      const struct vio_device_id *id)
+{
+	static int ds_version_printed;
+	struct ldc_channel_config ds_cfg = {
+		.event		= ds_event,
+		.mtu		= 4096,
+		.mode		= LDC_MODE_STREAM,
+	};
+	struct ldc_channel *lp;
+	struct ds_info *dp;
+	int err;
+
+	if (ds_version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	dp = kzalloc(sizeof(*dp), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!dp)
+		goto out_err;
+
+	dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
+	if (!dp->rcv_buf)
+		goto out_free_dp;
+
+	dp->rcv_buf_len = 4096;
+
+	ds_cfg.tx_irq = vdev->tx_irq;
+	ds_cfg.rx_irq = vdev->rx_irq;
+
+	lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp);
+	if (IS_ERR(lp)) {
+		err = PTR_ERR(lp);
+		goto out_free_rcv_buf;
+	}
+	dp->lp = lp;
+
+	err = ldc_bind(lp, "DS");
+	if (err)
+		goto out_free_ldc;
+
+	ds_info = dp;
+
+	start_powerd();
+
+	return err;
+
+out_free_ldc:
+	ldc_free(dp->lp);
+
+out_free_rcv_buf:
+	kfree(dp->rcv_buf);
+
+out_free_dp:
+	kfree(dp);
+
+out_err:
+	return err;
+}
+
+static int ds_remove(struct vio_dev *vdev)
+{
+	return 0;
+}
+
+static struct vio_device_id ds_match[] = {
+	{
+		.type = "domain-services-port",
+	},
+	{},
+};
+
+static struct vio_driver ds_driver = {
+	.id_table	= ds_match,
+	.probe		= ds_probe,
+	.remove		= ds_remove,
+	.driver		= {
+		.name	= "ds",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init ds_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ds_states); i++)
+		ds_states[i].handle = ((u64)i << 32);
+
+	kthread_run(ds_thread, NULL, "kldomd");
+
+	return vio_register_driver(&ds_driver);
+}
+
+subsys_initcall(ds_init);
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 732b77c..8059531 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1725,74 +1725,127 @@
 	 * returns %o0: sysino
 	 */
 	.globl	sun4v_devino_to_sysino
+	.type	sun4v_devino_to_sysino,#function
 sun4v_devino_to_sysino:
 	mov	HV_FAST_INTR_DEVINO2SYSINO, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 mov	%o1, %o0
+	.size	sun4v_devino_to_sysino, .-sun4v_devino_to_sysino
 
 	/* %o0: sysino
 	 *
 	 * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED})
 	 */
 	.globl	sun4v_intr_getenabled
+	.type	sun4v_intr_getenabled,#function
 sun4v_intr_getenabled:
 	mov	HV_FAST_INTR_GETENABLED, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 mov	%o1, %o0
+	.size	sun4v_intr_getenabled, .-sun4v_intr_getenabled
 
 	/* %o0: sysino
 	 * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
 	 */
 	.globl	sun4v_intr_setenabled
+	.type	sun4v_intr_setenabled,#function
 sun4v_intr_setenabled:
 	mov	HV_FAST_INTR_SETENABLED, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 nop
+	.size	sun4v_intr_setenabled, .-sun4v_intr_setenabled
 
 	/* %o0: sysino
 	 *
 	 * returns %o0: intr_state (HV_INTR_STATE_*)
 	 */
 	.globl	sun4v_intr_getstate
+	.type	sun4v_intr_getstate,#function
 sun4v_intr_getstate:
 	mov	HV_FAST_INTR_GETSTATE, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 mov	%o1, %o0
+	.size	sun4v_intr_getstate, .-sun4v_intr_getstate
 
 	/* %o0: sysino
 	 * %o1: intr_state (HV_INTR_STATE_*)
 	 */
 	.globl	sun4v_intr_setstate
+	.type	sun4v_intr_setstate,#function
 sun4v_intr_setstate:
 	mov	HV_FAST_INTR_SETSTATE, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 nop
+	.size	sun4v_intr_setstate, .-sun4v_intr_setstate
 
 	/* %o0: sysino
 	 *
 	 * returns %o0: cpuid
 	 */
 	.globl	sun4v_intr_gettarget
+	.type	sun4v_intr_gettarget,#function
 sun4v_intr_gettarget:
 	mov	HV_FAST_INTR_GETTARGET, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 mov	%o1, %o0
+	.size	sun4v_intr_gettarget, .-sun4v_intr_gettarget
 
 	/* %o0: sysino
 	 * %o1: cpuid
 	 */
 	.globl	sun4v_intr_settarget
+	.type	sun4v_intr_settarget,#function
 sun4v_intr_settarget:
 	mov	HV_FAST_INTR_SETTARGET, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 nop
+	.size	sun4v_intr_settarget, .-sun4v_intr_settarget
+
+	/* %o0:	cpuid
+	 * %o1: pc
+	 * %o2:	rtba
+	 * %o3:	arg0
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_cpu_start
+	.type	sun4v_cpu_start,#function
+sun4v_cpu_start:
+	mov	HV_FAST_CPU_START, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_cpu_start, .-sun4v_cpu_start
+
+	/* %o0:	cpuid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_cpu_stop
+	.type	sun4v_cpu_stop,#function
+sun4v_cpu_stop:
+	mov	HV_FAST_CPU_STOP, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_cpu_stop, .-sun4v_cpu_stop
+
+	/* returns %o0:	status  */
+	.globl	sun4v_cpu_yield
+	.type	sun4v_cpu_yield, #function
+sun4v_cpu_yield:
+	mov	HV_FAST_CPU_YIELD, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_cpu_yield, .-sun4v_cpu_yield
 
 	/* %o0:	type
 	 * %o1:	queue paddr
@@ -1801,20 +1854,13 @@
 	 * returns %o0:	status
 	 */
 	.globl	sun4v_cpu_qconf
+	.type	sun4v_cpu_qconf,#function
 sun4v_cpu_qconf:
 	mov	HV_FAST_CPU_QCONF, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 nop
-
-	/* returns %o0:	status
-	 */
-	.globl	sun4v_cpu_yield
-sun4v_cpu_yield:
-	mov	HV_FAST_CPU_YIELD, %o5
-	ta	HV_FAST_TRAP
-	retl
-	 nop
+	.size	sun4v_cpu_qconf, .-sun4v_cpu_qconf
 
 	/* %o0:	num cpus in cpu list
 	 * %o1:	cpu list paddr
@@ -1823,11 +1869,13 @@
 	 * returns %o0: status
 	 */
 	.globl	sun4v_cpu_mondo_send
+	.type	sun4v_cpu_mondo_send,#function
 sun4v_cpu_mondo_send:
 	mov	HV_FAST_CPU_MONDO_SEND, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 nop
+	.size	sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send
 
 	/* %o0:	CPU ID
 	 *
@@ -1835,6 +1883,7 @@
 	 *         %o0:	cpu state as HV_CPU_STATE_*
 	 */
 	.globl	sun4v_cpu_state
+	.type	sun4v_cpu_state,#function
 sun4v_cpu_state:
 	mov	HV_FAST_CPU_STATE, %o5
 	ta	HV_FAST_TRAP
@@ -1843,6 +1892,37 @@
 	mov	%o1, %o0
 1:	retl
 	 nop
+	.size	sun4v_cpu_state, .-sun4v_cpu_state
+
+	/* %o0: virtual address
+	 * %o1: must be zero
+	 * %o2: TTE
+	 * %o3: HV_MMU_* flags
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_mmu_map_perm_addr
+	.type	sun4v_mmu_map_perm_addr,#function
+sun4v_mmu_map_perm_addr:
+	mov	HV_FAST_MMU_MAP_PERM_ADDR, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr
+
+	/* %o0: number of TSB descriptions
+	 * %o1: TSB descriptions real address
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_mmu_tsb_ctx0
+	.type	sun4v_mmu_tsb_ctx0,#function
+sun4v_mmu_tsb_ctx0:
+	mov	HV_FAST_MMU_TSB_CTX0, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0
 
 	/* %o0:	API group number
 	 * %o1: pointer to unsigned long major number storage
@@ -1851,6 +1931,7 @@
 	 * returns %o0: status
 	 */
 	.globl	sun4v_get_version
+	.type	sun4v_get_version,#function
 sun4v_get_version:
 	mov	HV_CORE_GET_VER, %o5
 	mov	%o1, %o3
@@ -1859,6 +1940,7 @@
 	stx	%o1, [%o3]
 	retl
 	 stx	%o2, [%o4]
+	.size	sun4v_get_version, .-sun4v_get_version
 
 	/* %o0: API group number
 	 * %o1: desired major number
@@ -1868,18 +1950,49 @@
 	 * returns %o0: status
 	 */
 	.globl	sun4v_set_version
+	.type	sun4v_set_version,#function
 sun4v_set_version:
 	mov	HV_CORE_SET_VER, %o5
 	mov	%o3, %o4
 	ta	HV_CORE_TRAP
 	retl
 	 stx	%o1, [%o4]
+	.size	sun4v_set_version, .-sun4v_set_version
+
+	/* %o0: pointer to unsigned long time
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_tod_get
+	.type	sun4v_tod_get,#function
+sun4v_tod_get:
+	mov	%o0, %o4
+	mov	HV_FAST_TOD_GET, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	retl
+	 nop
+	.size	sun4v_tod_get, .-sun4v_tod_get
+
+	/* %o0: time
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_tod_set
+	.type	sun4v_tod_set,#function
+sun4v_tod_set:
+	mov	HV_FAST_TOD_SET, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_tod_set, .-sun4v_tod_set
 
 	/* %o0: pointer to unsigned long status
 	 *
 	 * returns %o0: signed character
 	 */
 	.globl	sun4v_con_getchar
+	.type	sun4v_con_getchar,#function
 sun4v_con_getchar:
 	mov	%o0, %o4
 	mov	HV_FAST_CONS_GETCHAR, %o5
@@ -1889,17 +2002,20 @@
 	stx	%o0, [%o4]
 	retl
 	 sra	%o1, 0, %o0
+	.size	sun4v_con_getchar, .-sun4v_con_getchar
 
 	/* %o0: signed long character
 	 *
 	 * returns %o0: status
 	 */
 	.globl	sun4v_con_putchar
+	.type	sun4v_con_putchar,#function
 sun4v_con_putchar:
 	mov	HV_FAST_CONS_PUTCHAR, %o5
 	ta	HV_FAST_TRAP
 	retl
 	 sra	%o0, 0, %o0
+	.size	sun4v_con_putchar, .-sun4v_con_putchar
 
 	/* %o0: buffer real address
 	 * %o1: buffer size
@@ -1908,6 +2024,7 @@
 	 * returns %o0: status
 	 */
 	.globl	sun4v_con_read
+	.type	sun4v_con_read,#function
 sun4v_con_read:
 	mov	%o2, %o4
 	mov	HV_FAST_CONS_READ, %o5
@@ -1922,6 +2039,7 @@
 	stx	%o1, [%o4]
 1:	retl
 	 nop
+	.size	sun4v_con_read, .-sun4v_con_read
 
 	/* %o0: buffer real address
 	 * %o1: buffer size
@@ -1930,6 +2048,7 @@
 	 * returns %o0: status
 	 */
 	.globl	sun4v_con_write
+	.type	sun4v_con_write,#function
 sun4v_con_write:
 	mov	%o2, %o4
 	mov	HV_FAST_CONS_WRITE, %o5
@@ -1937,3 +2056,540 @@
 	stx	%o1, [%o4]
 	retl
 	 nop
+	.size	sun4v_con_write, .-sun4v_con_write
+
+	/* %o0:	soft state
+	 * %o1:	address of description string
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_mach_set_soft_state
+	.type	sun4v_mach_set_soft_state,#function
+sun4v_mach_set_soft_state:
+	mov	HV_FAST_MACH_SET_SOFT_STATE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state
+
+	/* %o0: exit code
+	 *
+	 * Does not return.
+	 */
+	.globl	sun4v_mach_exit
+	.type	sun4v_mach_exit,#function
+sun4v_mach_exit:
+	mov	HV_FAST_MACH_EXIT, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_mach_exit, .-sun4v_mach_exit
+
+	/* %o0: buffer real address
+	 * %o1: buffer length
+	 * %o2: pointer to unsigned long real_buf_len
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_mach_desc
+	.type	sun4v_mach_desc,#function
+sun4v_mach_desc:
+	mov	%o2, %o4
+	mov	HV_FAST_MACH_DESC, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	retl
+	 nop
+	.size	sun4v_mach_desc, .-sun4v_mach_desc
+
+	/* %o0: new timeout in milliseconds
+	 * %o1: pointer to unsigned long orig_timeout
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_mach_set_watchdog
+	.type	sun4v_mach_set_watchdog,#function
+sun4v_mach_set_watchdog:
+	mov	%o1, %o4
+	mov	HV_FAST_MACH_SET_WATCHDOG, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	retl
+	 nop
+	.size	sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog
+
+	/* No inputs and does not return.  */
+	.globl	sun4v_mach_sir
+	.type	sun4v_mach_sir,#function
+sun4v_mach_sir:
+	mov	%o1, %o4
+	mov	HV_FAST_MACH_SIR, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	retl
+	 nop
+	.size	sun4v_mach_sir, .-sun4v_mach_sir
+
+	/* %o0: channel
+	 * %o1:	ra
+	 * %o2:	num_entries
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_tx_qconf
+	.type	sun4v_ldc_tx_qconf,#function
+sun4v_ldc_tx_qconf:
+	mov	HV_FAST_LDC_TX_QCONF, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf
+
+	/* %o0: channel
+	 * %o1:	pointer to unsigned long ra
+	 * %o2:	pointer to unsigned long num_entries
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_tx_qinfo
+	.type	sun4v_ldc_tx_qinfo,#function
+sun4v_ldc_tx_qinfo:
+	mov	%o1, %g1
+	mov	%o2, %g2
+	mov	HV_FAST_LDC_TX_QINFO, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	stx	%o2, [%g2]
+	retl
+	 nop
+	.size	sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo
+
+	/* %o0: channel
+	 * %o1:	pointer to unsigned long head_off
+	 * %o2:	pointer to unsigned long tail_off
+	 * %o2:	pointer to unsigned long chan_state
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_tx_get_state
+	.type	sun4v_ldc_tx_get_state,#function
+sun4v_ldc_tx_get_state:
+	mov	%o1, %g1
+	mov	%o2, %g2
+	mov	%o3, %g3
+	mov	HV_FAST_LDC_TX_GET_STATE, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	stx	%o2, [%g2]
+	stx	%o3, [%g3]
+	retl
+	 nop
+	.size	sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state
+
+	/* %o0: channel
+	 * %o1:	tail_off
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_tx_set_qtail
+	.type	sun4v_ldc_tx_set_qtail,#function
+sun4v_ldc_tx_set_qtail:
+	mov	HV_FAST_LDC_TX_SET_QTAIL, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail
+
+	/* %o0: channel
+	 * %o1:	ra
+	 * %o2:	num_entries
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_rx_qconf
+	.type	sun4v_ldc_rx_qconf,#function
+sun4v_ldc_rx_qconf:
+	mov	HV_FAST_LDC_RX_QCONF, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf
+
+	/* %o0: channel
+	 * %o1:	pointer to unsigned long ra
+	 * %o2:	pointer to unsigned long num_entries
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_rx_qinfo
+	.type	sun4v_ldc_rx_qinfo,#function
+sun4v_ldc_rx_qinfo:
+	mov	%o1, %g1
+	mov	%o2, %g2
+	mov	HV_FAST_LDC_RX_QINFO, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	stx	%o2, [%g2]
+	retl
+	 nop
+	.size	sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo
+
+	/* %o0: channel
+	 * %o1:	pointer to unsigned long head_off
+	 * %o2:	pointer to unsigned long tail_off
+	 * %o2:	pointer to unsigned long chan_state
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_rx_get_state
+	.type	sun4v_ldc_rx_get_state,#function
+sun4v_ldc_rx_get_state:
+	mov	%o1, %g1
+	mov	%o2, %g2
+	mov	%o3, %g3
+	mov	HV_FAST_LDC_RX_GET_STATE, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	stx	%o2, [%g2]
+	stx	%o3, [%g3]
+	retl
+	 nop
+	.size	sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state
+
+	/* %o0: channel
+	 * %o1:	head_off
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_rx_set_qhead
+	.type	sun4v_ldc_rx_set_qhead,#function
+sun4v_ldc_rx_set_qhead:
+	mov	HV_FAST_LDC_RX_SET_QHEAD, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead
+
+	/* %o0: channel
+	 * %o1:	ra
+	 * %o2:	num_entries
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_ldc_set_map_table
+	.type	sun4v_ldc_set_map_table,#function
+sun4v_ldc_set_map_table:
+	mov	HV_FAST_LDC_SET_MAP_TABLE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table
+
+	/* %o0: channel
+	 * %o1:	pointer to unsigned long ra
+	 * %o2:	pointer to unsigned long num_entries
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_ldc_get_map_table
+	.type	sun4v_ldc_get_map_table,#function
+sun4v_ldc_get_map_table:
+	mov	%o1, %g1
+	mov	%o2, %g2
+	mov	HV_FAST_LDC_GET_MAP_TABLE, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	stx	%o2, [%g2]
+	retl
+	 nop
+	.size	sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table
+
+	/* %o0:	channel
+	 * %o1:	dir_code
+	 * %o2:	tgt_raddr
+	 * %o3:	lcl_raddr
+	 * %o4:	len
+	 * %o5:	pointer to unsigned long actual_len
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_copy
+	.type	sun4v_ldc_copy,#function
+sun4v_ldc_copy:
+	mov	%o5, %g1
+	mov	HV_FAST_LDC_COPY, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	retl
+	 nop
+	.size	sun4v_ldc_copy, .-sun4v_ldc_copy
+
+	/* %o0:	channel
+	 * %o1:	cookie
+	 * %o2:	pointer to unsigned long ra
+	 * %o3:	pointer to unsigned long perm
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_mapin
+	.type	sun4v_ldc_mapin,#function
+sun4v_ldc_mapin:
+	mov	%o2, %g1
+	mov	%o3, %g2
+	mov	HV_FAST_LDC_MAPIN, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	stx	%o2, [%g2]
+	retl
+	 nop
+	.size	sun4v_ldc_mapin, .-sun4v_ldc_mapin
+
+	/* %o0:	ra
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_unmap
+	.type	sun4v_ldc_unmap,#function
+sun4v_ldc_unmap:
+	mov	HV_FAST_LDC_UNMAP, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_ldc_unmap, .-sun4v_ldc_unmap
+
+	/* %o0: channel
+	 * %o1:	cookie
+	 * %o2:	mte_cookie
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ldc_revoke
+	.type	sun4v_ldc_revoke,#function
+sun4v_ldc_revoke:
+	mov	HV_FAST_LDC_REVOKE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_ldc_revoke, .-sun4v_ldc_revoke
+
+	/* %o0: device handle
+	 * %o1:	device INO
+	 * %o2:	pointer to unsigned long cookie
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_vintr_get_cookie
+	.type	sun4v_vintr_get_cookie,#function
+sun4v_vintr_get_cookie:
+	mov	%o2, %g1
+	mov	HV_FAST_VINTR_GET_COOKIE, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	retl
+	 nop
+	.size	sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie
+
+	/* %o0: device handle
+	 * %o1:	device INO
+	 * %o2:	cookie
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_vintr_set_cookie
+	.type	sun4v_vintr_set_cookie,#function
+sun4v_vintr_set_cookie:
+	mov	HV_FAST_VINTR_SET_COOKIE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie
+
+	/* %o0: device handle
+	 * %o1:	device INO
+	 * %o2:	pointer to unsigned long valid_state
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_vintr_get_valid
+	.type	sun4v_vintr_get_valid,#function
+sun4v_vintr_get_valid:
+	mov	%o2, %g1
+	mov	HV_FAST_VINTR_GET_VALID, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	retl
+	 nop
+	.size	sun4v_vintr_get_valid, .-sun4v_vintr_get_valid
+
+	/* %o0: device handle
+	 * %o1:	device INO
+	 * %o2:	valid_state
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_vintr_set_valid
+	.type	sun4v_vintr_set_valid,#function
+sun4v_vintr_set_valid:
+	mov	HV_FAST_VINTR_SET_VALID, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_vintr_set_valid, .-sun4v_vintr_set_valid
+
+	/* %o0: device handle
+	 * %o1:	device INO
+	 * %o2:	pointer to unsigned long state
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_vintr_get_state
+	.type	sun4v_vintr_get_state,#function
+sun4v_vintr_get_state:
+	mov	%o2, %g1
+	mov	HV_FAST_VINTR_GET_STATE, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	retl
+	 nop
+	.size	sun4v_vintr_get_state, .-sun4v_vintr_get_state
+
+	/* %o0: device handle
+	 * %o1:	device INO
+	 * %o2:	state
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_vintr_set_state
+	.type	sun4v_vintr_set_state,#function
+sun4v_vintr_set_state:
+	mov	HV_FAST_VINTR_SET_STATE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_vintr_set_state, .-sun4v_vintr_set_state
+
+	/* %o0: device handle
+	 * %o1:	device INO
+	 * %o2:	pointer to unsigned long cpuid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_vintr_get_target
+	.type	sun4v_vintr_get_target,#function
+sun4v_vintr_get_target:
+	mov	%o2, %g1
+	mov	HV_FAST_VINTR_GET_TARGET, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%g1]
+	retl
+	 nop
+	.size	sun4v_vintr_get_target, .-sun4v_vintr_get_target
+
+	/* %o0: device handle
+	 * %o1:	device INO
+	 * %o2:	cpuid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	sun4v_vintr_set_target
+	.type	sun4v_vintr_set_target,#function
+sun4v_vintr_set_target:
+	mov	HV_FAST_VINTR_SET_TARGET, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_vintr_set_target, .-sun4v_vintr_set_target
+
+	/* %o0: NCS sub-function
+	 * %o1:	sub-function arg real-address
+	 * %o2:	sub-function arg size
+	 *
+	 * returns %o0:	status
+	 */
+	.globl	sun4v_ncs_request
+	.type	sun4v_ncs_request,#function
+sun4v_ncs_request:
+	mov	HV_FAST_NCS_REQUEST, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_ncs_request, .-sun4v_ncs_request
+
+	.globl	sun4v_svc_send
+	.type	sun4v_svc_send,#function
+sun4v_svc_send:
+	save	%sp, -192, %sp
+	mov	%i0, %o0
+	mov	%i1, %o1
+	mov	%i2, %o2
+	mov	HV_FAST_SVC_SEND, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%i3]
+	ret
+	restore
+	.size	sun4v_svc_send, .-sun4v_svc_send
+
+	.globl	sun4v_svc_recv
+	.type	sun4v_svc_recv,#function
+sun4v_svc_recv:
+	save	%sp, -192, %sp
+	mov	%i0, %o0
+	mov	%i1, %o1
+	mov	%i2, %o2
+	mov	HV_FAST_SVC_RECV, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%i3]
+	ret
+	restore
+	.size	sun4v_svc_recv, .-sun4v_svc_recv
+
+	.globl	sun4v_svc_getstatus
+	.type	sun4v_svc_getstatus,#function
+sun4v_svc_getstatus:
+	mov	HV_FAST_SVC_GETSTATUS, %o5
+	mov	%o1, %o4
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	retl
+	 nop
+	.size	sun4v_svc_getstatus, .-sun4v_svc_getstatus
+
+	.globl	sun4v_svc_setstatus
+	.type	sun4v_svc_setstatus,#function
+sun4v_svc_setstatus:
+	mov	HV_FAST_SVC_SETSTATUS, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_svc_setstatus, .-sun4v_svc_setstatus
+
+	.globl	sun4v_svc_clrstatus
+	.type	sun4v_svc_clrstatus,#function
+sun4v_svc_clrstatus:
+	mov	HV_FAST_SVC_CLRSTATUS, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+	.size	sun4v_svc_clrstatus, .-sun4v_svc_clrstatus
+
+	.globl	sun4v_mmustat_conf
+	.type	sun4v_mmustat_conf,#function
+sun4v_mmustat_conf:
+	mov	%o1, %o4
+	mov	HV_FAST_MMUSTAT_CONF, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	retl
+	 nop
+	.size	sun4v_mmustat_conf, .-sun4v_mmustat_conf
+
+	.globl	sun4v_mmustat_info
+	.type	sun4v_mmustat_info,#function
+sun4v_mmustat_info:
+	mov	%o0, %o4
+	mov	HV_FAST_MMUSTAT_INFO, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	retl
+	 nop
+	.size	sun4v_mmustat_info, .-sun4v_mmustat_info
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index baea10a..7725952 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -523,7 +523,7 @@
 #else
 	mov	0, %o0
 #endif
-	stb	%o0, [%g6 + TI_CPU]
+	sth	%o0, [%g6 + TI_CPU]
 
 	/* Off we go.... */
 	call	start_kernel
@@ -653,33 +653,54 @@
 	 restore
 sparc64_boot_end:
 
-#include "ktlb.S"
-#include "tsb.S"
 #include "etrap.S"
 #include "rtrap.S"
 #include "winfixup.S"
 #include "entry.S"
 #include "sun4v_tlb_miss.S"
 #include "sun4v_ivec.S"
+#include "ktlb.S"
+#include "tsb.S"
 
 /*
  * The following skip makes sure the trap table in ttable.S is aligned
  * on a 32K boundary as required by the v9 specs for TBA register.
  *
  * We align to a 32K boundary, then we have the 32K kernel TSB,
- * then the 32K aligned trap table.
+ * the 64K kernel 4MB TSB, and then the 32K aligned trap table.
  */
 1:
 	.skip	0x4000 + _start - 1b
 
+! 0x0000000000408000
+
 	.globl	swapper_tsb
 swapper_tsb:
 	.skip	(32 * 1024)
 
-! 0x0000000000408000
+	.globl	swapper_4m_tsb
+swapper_4m_tsb:
+	.skip	(64 * 1024)
 
+! 0x0000000000420000
+
+	/* Some care needs to be exercised if you try to move the
+	 * location of the trap table relative to other things.  For
+	 * one thing there are br* instructions in some of the
+	 * trap table entires which branch back to code in ktlb.S
+	 * Those instructions can only handle a signed 16-bit
+	 * displacement.
+	 *
+	 * There is a binutils bug (bugzilla #4558) which causes
+	 * the relocation overflow checks for such instructions to
+	 * not be done correctly.  So bintuils will not notice the
+	 * error and will instead write junk into the relocation and
+	 * you'll have an unbootable kernel.
+	 */
 #include "ttable.S"
 
+! 0x0000000000428000
+
 #include "systbls.S"
 
 	.data
diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc64/kernel/hvapi.c
index f03ffc8..f34f5d6 100644
--- a/arch/sparc64/kernel/hvapi.c
+++ b/arch/sparc64/kernel/hvapi.c
@@ -9,6 +9,7 @@
 
 #include <asm/hypervisor.h>
 #include <asm/oplib.h>
+#include <asm/sstate.h>
 
 /* If the hypervisor indicates that the API setting
  * calls are unsupported, by returning HV_EBADTRAP or
@@ -107,7 +108,7 @@
 				p->minor = actual_minor;
 				ret = 0;
 			} else if (hv_ret == HV_EBADTRAP ||
-				   HV_ENOTSUPPORTED) {
+				   hv_ret == HV_ENOTSUPPORTED) {
 				if (p->flags & FLAG_PRE_API) {
 					if (major == 1) {
 						p->major = 1;
@@ -179,6 +180,8 @@
 	if (sun4v_hvapi_register(group, major, &minor))
 		goto bad;
 
+	sun4v_sstate_init();
+
 	return;
 
 bad:
diff --git a/arch/sparc64/kernel/hvtramp.S b/arch/sparc64/kernel/hvtramp.S
new file mode 100644
index 0000000..a55c252
--- /dev/null
+++ b/arch/sparc64/kernel/hvtramp.S
@@ -0,0 +1,140 @@
+/* hvtramp.S: Hypervisor start-cpu trampoline code.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <asm/thread_info.h>
+#include <asm/hypervisor.h>
+#include <asm/scratchpad.h>
+#include <asm/spitfire.h>
+#include <asm/hvtramp.h>
+#include <asm/pstate.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+#include <asm/asi.h>
+
+	.text
+	.align		8
+	.globl		hv_cpu_startup, hv_cpu_startup_end
+
+	/* This code executes directly out of the hypervisor
+	 * with physical addressing (va==pa).  %o0 contains
+	 * our client argument which for Linux points to
+	 * a descriptor data structure which defines the
+	 * MMU entries we need to load up.
+	 *
+	 * After we set things up we enable the MMU and call
+	 * into the kernel.
+	 *
+	 * First setup basic privileged cpu state.
+	 */
+hv_cpu_startup:
+	SET_GL(0)
+	wrpr		%g0, 15, %pil
+	wrpr		%g0, 0, %canrestore
+	wrpr		%g0, 0, %otherwin
+	wrpr		%g0, 6, %cansave
+	wrpr		%g0, 6, %cleanwin
+	wrpr		%g0, 0, %cwp
+	wrpr		%g0, 0, %wstate
+	wrpr		%g0, 0, %tl
+
+	sethi		%hi(sparc64_ttable_tl0), %g1
+	wrpr		%g1, %tba
+
+	mov		%o0, %l0
+
+	lduw		[%l0 + HVTRAMP_DESCR_CPU], %g1
+	mov		SCRATCHPAD_CPUID, %g2
+	stxa		%g1, [%g2] ASI_SCRATCHPAD
+
+	ldx		[%l0 + HVTRAMP_DESCR_FAULT_INFO_VA], %g2
+	stxa		%g2, [%g0] ASI_SCRATCHPAD
+
+	mov		0, %l1
+	lduw		[%l0 + HVTRAMP_DESCR_NUM_MAPPINGS], %l2
+	add		%l0, HVTRAMP_DESCR_MAPS, %l3
+
+1:	ldx		[%l3 + HVTRAMP_MAPPING_VADDR], %o0
+	clr		%o1
+	ldx		[%l3 + HVTRAMP_MAPPING_TTE], %o2
+	mov		HV_MMU_IMMU | HV_MMU_DMMU, %o3
+	mov		HV_FAST_MMU_MAP_PERM_ADDR, %o5
+	ta		HV_FAST_TRAP
+
+	brnz,pn		%o0, 80f
+	 nop
+
+	add		%l1, 1, %l1
+	cmp		%l1, %l2
+	blt,a,pt	%xcc, 1b
+	 add		%l3, HVTRAMP_MAPPING_SIZE, %l3
+
+	ldx		[%l0 + HVTRAMP_DESCR_FAULT_INFO_PA], %o0
+	mov		HV_FAST_MMU_FAULT_AREA_CONF, %o5
+	ta		HV_FAST_TRAP
+
+	brnz,pn		%o0, 80f
+	 nop
+
+	wrpr		%g0, (PSTATE_PRIV | PSTATE_PEF), %pstate
+
+	ldx		[%l0 + HVTRAMP_DESCR_THREAD_REG], %l6
+
+	mov		1, %o0
+	set		1f, %o1
+	mov		HV_FAST_MMU_ENABLE, %o5
+	ta		HV_FAST_TRAP
+
+	ba,pt		%xcc, 80f
+	 nop
+
+1:
+	wr		%g0, 0, %fprs
+	wr		%g0, ASI_P, %asi
+
+	mov		PRIMARY_CONTEXT, %g7
+	stxa		%g0, [%g7] ASI_MMU
+	membar		#Sync
+
+	mov		SECONDARY_CONTEXT, %g7
+	stxa		%g0, [%g7] ASI_MMU
+	membar		#Sync
+
+	mov		%l6, %g6
+	ldx		[%g6 + TI_TASK], %g4
+
+	mov		1, %g5
+	sllx		%g5, THREAD_SHIFT, %g5
+	sub		%g5, (STACKFRAME_SZ + STACK_BIAS), %g5
+	add		%g6, %g5, %sp
+	mov		0, %fp
+
+	call		init_irqwork_curcpu
+	 nop
+	call		hard_smp_processor_id
+	 nop
+
+	mov		%o0, %o1
+	mov		0, %o0
+	mov		0, %o2
+	call		sun4v_init_mondo_queues
+	 mov		1, %o3
+
+	call		init_cur_cpu_trap
+	 mov		%g6, %o0
+
+	wrpr		%g0, (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE), %pstate
+
+	call		smp_callin
+	 nop
+	call		cpu_idle
+	 mov		0, %o0
+	call		cpu_panic
+	 nop
+
+80:	ba,pt		%xcc, 80b
+	 nop
+
+	.align		8
+hv_cpu_startup_end:
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 3edc18e..8cb3358 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,7 +1,6 @@
-/* $Id: irq.c,v 1.114 2002/01/11 08:45:38 davem Exp $
- * irq.c: UltraSparc IRQ handling/init/registry.
+/* irq.c: UltraSparc IRQ handling/init/registry.
  *
- * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 2007  David S. Miller  (davem@davemloft.net)
  * Copyright (C) 1998  Eddie C. Dost    (ecd@skynet.be)
  * Copyright (C) 1998  Jakub Jelinek    (jj@ultra.linux.cz)
  */
@@ -43,6 +42,7 @@
 #include <asm/cpudata.h>
 #include <asm/auxio.h>
 #include <asm/head.h>
+#include <asm/hypervisor.h>
 
 /* UPA nodes send interrupt packet to UltraSparc with first data reg
  * value low 5 (7 on Starfire) bits holding the IRQ identifier being
@@ -171,8 +171,6 @@
 	return 0;
 }
 
-extern unsigned long real_hard_smp_processor_id(void);
-
 static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid)
 {
 	unsigned int tid;
@@ -295,6 +293,11 @@
 	}
 }
 
+static void sun4u_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+	sun4u_irq_enable(virt_irq);
+}
+
 static void sun4u_irq_disable(unsigned int virt_irq)
 {
 	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
@@ -311,6 +314,10 @@
 static void sun4u_irq_end(unsigned int virt_irq)
 {
 	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+	struct irq_desc *desc = irq_desc + virt_irq;
+
+	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		return;
 
 	if (likely(data))
 		upa_writeq(ICLR_IDLE, data->iclr);
@@ -331,6 +338,10 @@
 		if (err != HV_EOK)
 			printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
 			       ino, cpuid, err);
+		err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
+		if (err != HV_EOK)
+			printk("sun4v_intr_setstate(%x): "
+			       "err(%d)\n", ino, err);
 		err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
 		if (err != HV_EOK)
 			printk("sun4v_intr_setenabled(%x): err(%d)\n",
@@ -338,6 +349,24 @@
 	}
 }
 
+static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+
+	if (likely(bucket)) {
+		unsigned long cpuid;
+		int err;
+
+		cpuid = irq_choose_cpu(virt_irq);
+
+		err = sun4v_intr_settarget(ino, cpuid);
+		if (err != HV_EOK)
+			printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
+			       ino, cpuid, err);
+	}
+}
+
 static void sun4v_irq_disable(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -371,6 +400,10 @@
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
 	unsigned int ino = bucket - &ivector_table[0];
+	struct irq_desc *desc = irq_desc + virt_irq;
+
+	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		return;
 
 	if (likely(bucket)) {
 		int err;
@@ -382,6 +415,108 @@
 	}
 }
 
+static void sun4v_virq_enable(unsigned int virt_irq)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+
+	if (likely(bucket)) {
+		unsigned long cpuid, dev_handle, dev_ino;
+		int err;
+
+		cpuid = irq_choose_cpu(virt_irq);
+
+		dev_handle = ino & IMAP_IGN;
+		dev_ino = ino & IMAP_INO;
+
+		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
+		if (err != HV_EOK)
+			printk("sun4v_vintr_set_target(%lx,%lx,%lu): "
+			       "err(%d)\n",
+			       dev_handle, dev_ino, cpuid, err);
+		err = sun4v_vintr_set_state(dev_handle, dev_ino,
+					    HV_INTR_STATE_IDLE);
+		if (err != HV_EOK)
+			printk("sun4v_vintr_set_state(%lx,%lx,"
+				"HV_INTR_STATE_IDLE): err(%d)\n",
+			       dev_handle, dev_ino, err);
+		err = sun4v_vintr_set_valid(dev_handle, dev_ino,
+					    HV_INTR_ENABLED);
+		if (err != HV_EOK)
+			printk("sun4v_vintr_set_state(%lx,%lx,"
+			       "HV_INTR_ENABLED): err(%d)\n",
+			       dev_handle, dev_ino, err);
+	}
+}
+
+static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+
+	if (likely(bucket)) {
+		unsigned long cpuid, dev_handle, dev_ino;
+		int err;
+
+		cpuid = irq_choose_cpu(virt_irq);
+
+		dev_handle = ino & IMAP_IGN;
+		dev_ino = ino & IMAP_INO;
+
+		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
+		if (err != HV_EOK)
+			printk("sun4v_vintr_set_target(%lx,%lx,%lu): "
+			       "err(%d)\n",
+			       dev_handle, dev_ino, cpuid, err);
+	}
+}
+
+static void sun4v_virq_disable(unsigned int virt_irq)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+
+	if (likely(bucket)) {
+		unsigned long dev_handle, dev_ino;
+		int err;
+
+		dev_handle = ino & IMAP_IGN;
+		dev_ino = ino & IMAP_INO;
+
+		err = sun4v_vintr_set_valid(dev_handle, dev_ino,
+					    HV_INTR_DISABLED);
+		if (err != HV_EOK)
+			printk("sun4v_vintr_set_state(%lx,%lx,"
+			       "HV_INTR_DISABLED): err(%d)\n",
+			       dev_handle, dev_ino, err);
+	}
+}
+
+static void sun4v_virq_end(unsigned int virt_irq)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+	struct irq_desc *desc = irq_desc + virt_irq;
+
+	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		return;
+
+	if (likely(bucket)) {
+		unsigned long dev_handle, dev_ino;
+		int err;
+
+		dev_handle = ino & IMAP_IGN;
+		dev_ino = ino & IMAP_INO;
+
+		err = sun4v_vintr_set_state(dev_handle, dev_ino,
+					    HV_INTR_STATE_IDLE);
+		if (err != HV_EOK)
+			printk("sun4v_vintr_set_state(%lx,%lx,"
+				"HV_INTR_STATE_IDLE): err(%d)\n",
+			       dev_handle, dev_ino, err);
+	}
+}
+
 static void run_pre_handler(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -399,6 +534,7 @@
 	.enable		= sun4u_irq_enable,
 	.disable	= sun4u_irq_disable,
 	.end		= sun4u_irq_end,
+	.set_affinity	= sun4u_set_affinity,
 };
 
 static struct irq_chip sun4u_irq_ack = {
@@ -407,6 +543,7 @@
 	.disable	= sun4u_irq_disable,
 	.ack		= run_pre_handler,
 	.end		= sun4u_irq_end,
+	.set_affinity	= sun4u_set_affinity,
 };
 
 static struct irq_chip sun4v_irq = {
@@ -414,6 +551,7 @@
 	.enable		= sun4v_irq_enable,
 	.disable	= sun4v_irq_disable,
 	.end		= sun4v_irq_end,
+	.set_affinity	= sun4v_set_affinity,
 };
 
 static struct irq_chip sun4v_irq_ack = {
@@ -422,6 +560,7 @@
 	.disable	= sun4v_irq_disable,
 	.ack		= run_pre_handler,
 	.end		= sun4v_irq_end,
+	.set_affinity	= sun4v_set_affinity,
 };
 
 #ifdef CONFIG_PCI_MSI
@@ -433,9 +572,27 @@
 	.disable	= sun4v_msi_disable,
 	.ack		= run_pre_handler,
 	.end		= sun4v_irq_end,
+	.set_affinity	= sun4v_set_affinity,
 };
 #endif
 
+static struct irq_chip sun4v_virq = {
+	.typename	= "vsun4v",
+	.enable		= sun4v_virq_enable,
+	.disable	= sun4v_virq_disable,
+	.end		= sun4v_virq_end,
+	.set_affinity	= sun4v_virt_set_affinity,
+};
+
+static struct irq_chip sun4v_virq_ack = {
+	.typename	= "vsun4v+ack",
+	.enable		= sun4v_virq_enable,
+	.disable	= sun4v_virq_disable,
+	.ack		= run_pre_handler,
+	.end		= sun4v_virq_end,
+	.set_affinity	= sun4v_virt_set_affinity,
+};
+
 void irq_install_pre_handler(int virt_irq,
 			     void (*func)(unsigned int, void *, void *),
 			     void *arg1, void *arg2)
@@ -449,7 +606,8 @@
 
 	chip = get_irq_chip(virt_irq);
 	if (chip == &sun4u_irq_ack ||
-	    chip == &sun4v_irq_ack
+	    chip == &sun4v_irq_ack ||
+	    chip == &sun4v_virq_ack
 #ifdef CONFIG_PCI_MSI
 	    || chip == &sun4v_msi
 #endif
@@ -457,7 +615,9 @@
 		return;
 
 	chip = (chip == &sun4u_irq ?
-		&sun4u_irq_ack : &sun4v_irq_ack);
+		&sun4u_irq_ack :
+		(chip == &sun4v_irq ?
+		 &sun4v_irq_ack : &sun4v_virq_ack));
 	set_irq_chip(virt_irq, chip);
 }
 
@@ -494,19 +654,18 @@
 	return bucket->virt_irq;
 }
 
-unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
+static unsigned int sun4v_build_common(unsigned long sysino,
+				       struct irq_chip *chip)
 {
 	struct ino_bucket *bucket;
 	struct irq_handler_data *data;
-	unsigned long sysino;
 
 	BUG_ON(tlb_type != hypervisor);
 
-	sysino = sun4v_devino_to_sysino(devhandle, devino);
 	bucket = &ivector_table[sysino];
 	if (!bucket->virt_irq) {
 		bucket->virt_irq = virt_irq_alloc(__irq(bucket));
-		set_irq_chip(bucket->virt_irq, &sun4v_irq);
+		set_irq_chip(bucket->virt_irq, chip);
 	}
 
 	data = get_irq_chip_data(bucket->virt_irq);
@@ -531,6 +690,32 @@
 	return bucket->virt_irq;
 }
 
+unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
+{
+	unsigned long sysino = sun4v_devino_to_sysino(devhandle, devino);
+
+	return sun4v_build_common(sysino, &sun4v_irq);
+}
+
+unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
+{
+	unsigned long sysino, hv_err;
+
+	BUG_ON(devhandle & ~IMAP_IGN);
+	BUG_ON(devino & ~IMAP_INO);
+
+	sysino = devhandle | devino;
+
+	hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino);
+	if (hv_err) {
+		prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] "
+			    "err=%lu\n", devhandle, devino, hv_err);
+		prom_halt();
+	}
+
+	return sun4v_build_common(sysino, &sun4v_virq);
+}
+
 #ifdef CONFIG_PCI_MSI
 unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
 			     unsigned int msi_start, unsigned int msi_end)
@@ -618,6 +803,26 @@
 	set_irq_regs(old_regs);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+void fixup_irqs(void)
+{
+	unsigned int irq;
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&irq_desc[irq].lock, flags);
+		if (irq_desc[irq].action &&
+		    !(irq_desc[irq].status & IRQ_PER_CPU)) {
+			if (irq_desc[irq].chip->set_affinity)
+				irq_desc[irq].chip->set_affinity(irq,
+					irq_desc[irq].affinity);
+		}
+		spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+	}
+}
+#endif
+
 struct sun5_timer {
 	u64	count0;
 	u64	limit0;
@@ -694,9 +899,20 @@
 	trap_block[cpu].irq_worklist = 0;
 }
 
-static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type)
+/* Please be very careful with register_one_mondo() and
+ * sun4v_register_mondo_queues().
+ *
+ * On SMP this gets invoked from the CPU trampoline before
+ * the cpu has fully taken over the trap table from OBP,
+ * and it's kernel stack + %g6 thread register state is
+ * not fully cooked yet.
+ *
+ * Therefore you cannot make any OBP calls, not even prom_printf,
+ * from these two routines.
+ */
+static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask)
 {
-	unsigned long num_entries = 128;
+	unsigned long num_entries = (qmask + 1) / 64;
 	unsigned long status;
 
 	status = sun4v_cpu_qconf(type, paddr, num_entries);
@@ -711,44 +927,58 @@
 {
 	struct trap_per_cpu *tb = &trap_block[this_cpu];
 
-	register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO);
-	register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO);
-	register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR);
-	register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR);
+	register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO,
+			   tb->cpu_mondo_qmask);
+	register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO,
+			   tb->dev_mondo_qmask);
+	register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR,
+			   tb->resum_qmask);
+	register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR,
+			   tb->nonresum_qmask);
 }
 
-static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, int use_bootmem)
+static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem)
 {
-	void *page;
+	unsigned long size = PAGE_ALIGN(qmask + 1);
+	unsigned long order = get_order(size);
+	void *p = NULL;
 
-	if (use_bootmem)
-		page = alloc_bootmem_low_pages(PAGE_SIZE);
-	else
-		page = (void *) get_zeroed_page(GFP_ATOMIC);
+	if (use_bootmem) {
+		p = __alloc_bootmem_low(size, size, 0);
+	} else {
+		struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order);
+		if (page)
+			p = page_address(page);
+	}
 
-	if (!page) {
+	if (!p) {
 		prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
 		prom_halt();
 	}
 
-	*pa_ptr = __pa(page);
+	*pa_ptr = __pa(p);
 }
 
-static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, int use_bootmem)
+static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem)
 {
-	void *page;
+	unsigned long size = PAGE_ALIGN(qmask + 1);
+	unsigned long order = get_order(size);
+	void *p = NULL;
 
-	if (use_bootmem)
-		page = alloc_bootmem_low_pages(PAGE_SIZE);
-	else
-		page = (void *) get_zeroed_page(GFP_ATOMIC);
+	if (use_bootmem) {
+		p = __alloc_bootmem_low(size, size, 0);
+	} else {
+		struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order);
+		if (page)
+			p = page_address(page);
+	}
 
-	if (!page) {
+	if (!p) {
 		prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
 		prom_halt();
 	}
 
-	*pa_ptr = __pa(page);
+	*pa_ptr = __pa(p);
 }
 
 static void __cpuinit init_cpu_send_mondo_info(struct trap_per_cpu *tb, int use_bootmem)
@@ -779,12 +1009,12 @@
 	struct trap_per_cpu *tb = &trap_block[cpu];
 
 	if (alloc) {
-		alloc_one_mondo(&tb->cpu_mondo_pa, use_bootmem);
-		alloc_one_mondo(&tb->dev_mondo_pa, use_bootmem);
-		alloc_one_mondo(&tb->resum_mondo_pa, use_bootmem);
-		alloc_one_kbuf(&tb->resum_kernel_buf_pa, use_bootmem);
-		alloc_one_mondo(&tb->nonresum_mondo_pa, use_bootmem);
-		alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, use_bootmem);
+		alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask, use_bootmem);
+		alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask, use_bootmem);
+		alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask, use_bootmem);
+		alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask, use_bootmem);
+		alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask, use_bootmem);
+		alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, tb->nonresum_qmask, use_bootmem);
 
 		init_cpu_send_mondo_info(tb, use_bootmem);
 	}
diff --git a/arch/sparc64/kernel/itlb_miss.S b/arch/sparc64/kernel/itlb_miss.S
index ad46e20..5a8377b 100644
--- a/arch/sparc64/kernel/itlb_miss.S
+++ b/arch/sparc64/kernel/itlb_miss.S
@@ -11,12 +11,12 @@
 /* ITLB ** ICACHE line 2: TSB compare and TLB load	*/
 	bne,pn	%xcc, tsb_miss_itlb		! Miss
 	 mov	FAULT_CODE_ITLB, %g3
-	andcc	%g5, _PAGE_EXEC_4U, %g0		! Executable?
+	sethi	%hi(_PAGE_EXEC_4U), %g4
+	andcc	%g5, %g4, %g0			! Executable?
 	be,pn	%xcc, tsb_do_fault
 	 nop					! Delay slot, fill me
 	stxa	%g5, [%g0] ASI_ITLB_DATA_IN	! Load TLB
 	retry					! Trap done
-	nop
 
 /* ITLB ** ICACHE line 3: 				*/
 	nop
diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c
new file mode 100644
index 0000000..85a2be0
--- /dev/null
+++ b/arch/sparc64/kernel/ldc.c
@@ -0,0 +1,2373 @@
+/* ldc.c: Logical Domain Channel link-layer protocol driver.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+
+#include <asm/hypervisor.h>
+#include <asm/iommu.h>
+#include <asm/page.h>
+#include <asm/ldc.h>
+#include <asm/mdesc.h>
+
+#define DRV_MODULE_NAME		"ldc"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"June 25, 2007"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+#define LDC_PACKET_SIZE		64
+
+/* Packet header layout for unreliable and reliable mode frames.
+ * When in RAW mode, packets are simply straight 64-byte payloads
+ * with no headers.
+ */
+struct ldc_packet {
+	u8			type;
+#define LDC_CTRL		0x01
+#define LDC_DATA		0x02
+#define LDC_ERR			0x10
+
+	u8			stype;
+#define LDC_INFO		0x01
+#define LDC_ACK			0x02
+#define LDC_NACK		0x04
+
+	u8			ctrl;
+#define LDC_VERS		0x01 /* Link Version		*/
+#define LDC_RTS			0x02 /* Request To Send		*/
+#define LDC_RTR			0x03 /* Ready To Receive	*/
+#define LDC_RDX			0x04 /* Ready for Data eXchange	*/
+#define LDC_CTRL_MSK		0x0f
+
+	u8			env;
+#define LDC_LEN			0x3f
+#define LDC_FRAG_MASK		0xc0
+#define LDC_START		0x40
+#define LDC_STOP		0x80
+
+	u32			seqid;
+
+	union {
+		u8		u_data[LDC_PACKET_SIZE - 8];
+		struct {
+			u32	pad;
+			u32	ackid;
+			u8	r_data[LDC_PACKET_SIZE - 8 - 8];
+		} r;
+	} u;
+};
+
+struct ldc_version {
+	u16 major;
+	u16 minor;
+};
+
+/* Ordered from largest major to lowest.  */
+static struct ldc_version ver_arr[] = {
+	{ .major = 1, .minor = 0 },
+};
+
+#define LDC_DEFAULT_MTU			(4 * LDC_PACKET_SIZE)
+#define LDC_DEFAULT_NUM_ENTRIES		(PAGE_SIZE / LDC_PACKET_SIZE)
+
+struct ldc_channel;
+
+struct ldc_mode_ops {
+	int (*write)(struct ldc_channel *, const void *, unsigned int);
+	int (*read)(struct ldc_channel *, void *, unsigned int);
+};
+
+static const struct ldc_mode_ops raw_ops;
+static const struct ldc_mode_ops nonraw_ops;
+static const struct ldc_mode_ops stream_ops;
+
+int ldom_domaining_enabled;
+
+struct ldc_iommu {
+	/* Protects arena alloc/free.  */
+	spinlock_t			lock;
+	struct iommu_arena		arena;
+	struct ldc_mtable_entry		*page_table;
+};
+
+struct ldc_channel {
+	/* Protects all operations that depend upon channel state.  */
+	spinlock_t			lock;
+
+	unsigned long			id;
+
+	u8				*mssbuf;
+	u32				mssbuf_len;
+	u32				mssbuf_off;
+
+	struct ldc_packet		*tx_base;
+	unsigned long			tx_head;
+	unsigned long			tx_tail;
+	unsigned long			tx_num_entries;
+	unsigned long			tx_ra;
+
+	unsigned long			tx_acked;
+
+	struct ldc_packet		*rx_base;
+	unsigned long			rx_head;
+	unsigned long			rx_tail;
+	unsigned long			rx_num_entries;
+	unsigned long			rx_ra;
+
+	u32				rcv_nxt;
+	u32				snd_nxt;
+
+	unsigned long			chan_state;
+
+	struct ldc_channel_config	cfg;
+	void				*event_arg;
+
+	const struct ldc_mode_ops	*mops;
+
+	struct ldc_iommu		iommu;
+
+	struct ldc_version		ver;
+
+	u8				hs_state;
+#define LDC_HS_CLOSED			0x00
+#define LDC_HS_OPEN			0x01
+#define LDC_HS_GOTVERS			0x02
+#define LDC_HS_SENTRTR			0x03
+#define LDC_HS_GOTRTR			0x04
+#define LDC_HS_COMPLETE			0x10
+
+	u8				flags;
+#define LDC_FLAG_ALLOCED_QUEUES		0x01
+#define LDC_FLAG_REGISTERED_QUEUES	0x02
+#define LDC_FLAG_REGISTERED_IRQS	0x04
+#define LDC_FLAG_RESET			0x10
+
+	u8				mss;
+	u8				state;
+
+#define LDC_IRQ_NAME_MAX		32
+	char				rx_irq_name[LDC_IRQ_NAME_MAX];
+	char				tx_irq_name[LDC_IRQ_NAME_MAX];
+
+	struct hlist_head		mh_list;
+
+	struct hlist_node		list;
+};
+
+#define ldcdbg(TYPE, f, a...) \
+do {	if (lp->cfg.debug & LDC_DEBUG_##TYPE) \
+		printk(KERN_INFO PFX "ID[%lu] " f, lp->id, ## a); \
+} while (0)
+
+static const char *state_to_str(u8 state)
+{
+	switch (state) {
+	case LDC_STATE_INVALID:
+		return "INVALID";
+	case LDC_STATE_INIT:
+		return "INIT";
+	case LDC_STATE_BOUND:
+		return "BOUND";
+	case LDC_STATE_READY:
+		return "READY";
+	case LDC_STATE_CONNECTED:
+		return "CONNECTED";
+	default:
+		return "<UNKNOWN>";
+	}
+}
+
+static void ldc_set_state(struct ldc_channel *lp, u8 state)
+{
+	ldcdbg(STATE, "STATE (%s) --> (%s)\n",
+	       state_to_str(lp->state),
+	       state_to_str(state));
+
+	lp->state = state;
+}
+
+static unsigned long __advance(unsigned long off, unsigned long num_entries)
+{
+	off += LDC_PACKET_SIZE;
+	if (off == (num_entries * LDC_PACKET_SIZE))
+		off = 0;
+
+	return off;
+}
+
+static unsigned long rx_advance(struct ldc_channel *lp, unsigned long off)
+{
+	return __advance(off, lp->rx_num_entries);
+}
+
+static unsigned long tx_advance(struct ldc_channel *lp, unsigned long off)
+{
+	return __advance(off, lp->tx_num_entries);
+}
+
+static struct ldc_packet *handshake_get_tx_packet(struct ldc_channel *lp,
+						  unsigned long *new_tail)
+{
+	struct ldc_packet *p;
+	unsigned long t;
+
+	t = tx_advance(lp, lp->tx_tail);
+	if (t == lp->tx_head)
+		return NULL;
+
+	*new_tail = t;
+
+	p = lp->tx_base;
+	return p + (lp->tx_tail / LDC_PACKET_SIZE);
+}
+
+/* When we are in reliable or stream mode, have to track the next packet
+ * we haven't gotten an ACK for in the TX queue using tx_acked.  We have
+ * to be careful not to stomp over the queue past that point.  During
+ * the handshake, we don't have TX data packets pending in the queue
+ * and that's why handshake_get_tx_packet() need not be mindful of
+ * lp->tx_acked.
+ */
+static unsigned long head_for_data(struct ldc_channel *lp)
+{
+	if (lp->cfg.mode == LDC_MODE_STREAM)
+		return lp->tx_acked;
+	return lp->tx_head;
+}
+
+static int tx_has_space_for(struct ldc_channel *lp, unsigned int size)
+{
+	unsigned long limit, tail, new_tail, diff;
+	unsigned int mss;
+
+	limit = head_for_data(lp);
+	tail = lp->tx_tail;
+	new_tail = tx_advance(lp, tail);
+	if (new_tail == limit)
+		return 0;
+
+	if (limit > new_tail)
+		diff = limit - new_tail;
+	else
+		diff = (limit +
+			((lp->tx_num_entries * LDC_PACKET_SIZE) - new_tail));
+	diff /= LDC_PACKET_SIZE;
+	mss = lp->mss;
+
+	if (diff * mss < size)
+		return 0;
+
+	return 1;
+}
+
+static struct ldc_packet *data_get_tx_packet(struct ldc_channel *lp,
+					     unsigned long *new_tail)
+{
+	struct ldc_packet *p;
+	unsigned long h, t;
+
+	h = head_for_data(lp);
+	t = tx_advance(lp, lp->tx_tail);
+	if (t == h)
+		return NULL;
+
+	*new_tail = t;
+
+	p = lp->tx_base;
+	return p + (lp->tx_tail / LDC_PACKET_SIZE);
+}
+
+static int set_tx_tail(struct ldc_channel *lp, unsigned long tail)
+{
+	unsigned long orig_tail = lp->tx_tail;
+	int limit = 1000;
+
+	lp->tx_tail = tail;
+	while (limit-- > 0) {
+		unsigned long err;
+
+		err = sun4v_ldc_tx_set_qtail(lp->id, tail);
+		if (!err)
+			return 0;
+
+		if (err != HV_EWOULDBLOCK) {
+			lp->tx_tail = orig_tail;
+			return -EINVAL;
+		}
+		udelay(1);
+	}
+
+	lp->tx_tail = orig_tail;
+	return -EBUSY;
+}
+
+/* This just updates the head value in the hypervisor using
+ * a polling loop with a timeout.  The caller takes care of
+ * upating software state representing the head change, if any.
+ */
+static int __set_rx_head(struct ldc_channel *lp, unsigned long head)
+{
+	int limit = 1000;
+
+	while (limit-- > 0) {
+		unsigned long err;
+
+		err = sun4v_ldc_rx_set_qhead(lp->id, head);
+		if (!err)
+			return 0;
+
+		if (err != HV_EWOULDBLOCK)
+			return -EINVAL;
+
+		udelay(1);
+	}
+
+	return -EBUSY;
+}
+
+static int send_tx_packet(struct ldc_channel *lp,
+			  struct ldc_packet *p,
+			  unsigned long new_tail)
+{
+	BUG_ON(p != (lp->tx_base + (lp->tx_tail / LDC_PACKET_SIZE)));
+
+	return set_tx_tail(lp, new_tail);
+}
+
+static struct ldc_packet *handshake_compose_ctrl(struct ldc_channel *lp,
+						 u8 stype, u8 ctrl,
+						 void *data, int dlen,
+						 unsigned long *new_tail)
+{
+	struct ldc_packet *p = handshake_get_tx_packet(lp, new_tail);
+
+	if (p) {
+		memset(p, 0, sizeof(*p));
+		p->type = LDC_CTRL;
+		p->stype = stype;
+		p->ctrl = ctrl;
+		if (data)
+			memcpy(p->u.u_data, data, dlen);
+	}
+	return p;
+}
+
+static int start_handshake(struct ldc_channel *lp)
+{
+	struct ldc_packet *p;
+	struct ldc_version *ver;
+	unsigned long new_tail;
+
+	ver = &ver_arr[0];
+
+	ldcdbg(HS, "SEND VER INFO maj[%u] min[%u]\n",
+	       ver->major, ver->minor);
+
+	p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS,
+				   ver, sizeof(*ver), &new_tail);
+	if (p) {
+		int err = send_tx_packet(lp, p, new_tail);
+		if (!err)
+			lp->flags &= ~LDC_FLAG_RESET;
+		return err;
+	}
+	return -EBUSY;
+}
+
+static int send_version_nack(struct ldc_channel *lp,
+			     u16 major, u16 minor)
+{
+	struct ldc_packet *p;
+	struct ldc_version ver;
+	unsigned long new_tail;
+
+	ver.major = major;
+	ver.minor = minor;
+
+	p = handshake_compose_ctrl(lp, LDC_NACK, LDC_VERS,
+				   &ver, sizeof(ver), &new_tail);
+	if (p) {
+		ldcdbg(HS, "SEND VER NACK maj[%u] min[%u]\n",
+		       ver.major, ver.minor);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_version_ack(struct ldc_channel *lp,
+			    struct ldc_version *vp)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+
+	p = handshake_compose_ctrl(lp, LDC_ACK, LDC_VERS,
+				   vp, sizeof(*vp), &new_tail);
+	if (p) {
+		ldcdbg(HS, "SEND VER ACK maj[%u] min[%u]\n",
+		       vp->major, vp->minor);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_rts(struct ldc_channel *lp)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+
+	p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RTS, NULL, 0,
+				   &new_tail);
+	if (p) {
+		p->env = lp->cfg.mode;
+		p->seqid = 0;
+		lp->rcv_nxt = 0;
+
+		ldcdbg(HS, "SEND RTS env[0x%x] seqid[0x%x]\n",
+		       p->env, p->seqid);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_rtr(struct ldc_channel *lp)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+
+	p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RTR, NULL, 0,
+				   &new_tail);
+	if (p) {
+		p->env = lp->cfg.mode;
+		p->seqid = 0;
+
+		ldcdbg(HS, "SEND RTR env[0x%x] seqid[0x%x]\n",
+		       p->env, p->seqid);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_rdx(struct ldc_channel *lp)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+
+	p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RDX, NULL, 0,
+				   &new_tail);
+	if (p) {
+		p->env = 0;
+		p->seqid = ++lp->snd_nxt;
+		p->u.r.ackid = lp->rcv_nxt;
+
+		ldcdbg(HS, "SEND RDX env[0x%x] seqid[0x%x] ackid[0x%x]\n",
+		       p->env, p->seqid, p->u.r.ackid);
+
+		return send_tx_packet(lp, p, new_tail);
+	}
+	return -EBUSY;
+}
+
+static int send_data_nack(struct ldc_channel *lp, struct ldc_packet *data_pkt)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+	int err;
+
+	p = data_get_tx_packet(lp, &new_tail);
+	if (!p)
+		return -EBUSY;
+	memset(p, 0, sizeof(*p));
+	p->type = data_pkt->type;
+	p->stype = LDC_NACK;
+	p->ctrl = data_pkt->ctrl & LDC_CTRL_MSK;
+	p->seqid = lp->snd_nxt + 1;
+	p->u.r.ackid = lp->rcv_nxt;
+
+	ldcdbg(HS, "SEND DATA NACK type[0x%x] ctl[0x%x] seq[0x%x] ack[0x%x]\n",
+	       p->type, p->ctrl, p->seqid, p->u.r.ackid);
+
+	err = send_tx_packet(lp, p, new_tail);
+	if (!err)
+		lp->snd_nxt++;
+
+	return err;
+}
+
+static int ldc_abort(struct ldc_channel *lp)
+{
+	unsigned long hv_err;
+
+	ldcdbg(STATE, "ABORT\n");
+
+	/* We report but do not act upon the hypervisor errors because
+	 * there really isn't much we can do if they fail at this point.
+	 */
+	hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+	if (hv_err)
+		printk(KERN_ERR PFX "ldc_abort: "
+		       "sun4v_ldc_tx_qconf(%lx,%lx,%lx) failed, err=%lu\n",
+		       lp->id, lp->tx_ra, lp->tx_num_entries, hv_err);
+
+	hv_err = sun4v_ldc_tx_get_state(lp->id,
+					&lp->tx_head,
+					&lp->tx_tail,
+					&lp->chan_state);
+	if (hv_err)
+		printk(KERN_ERR PFX "ldc_abort: "
+		       "sun4v_ldc_tx_get_state(%lx,...) failed, err=%lu\n",
+		       lp->id, hv_err);
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+	if (hv_err)
+		printk(KERN_ERR PFX "ldc_abort: "
+		       "sun4v_ldc_rx_qconf(%lx,%lx,%lx) failed, err=%lu\n",
+		       lp->id, lp->rx_ra, lp->rx_num_entries, hv_err);
+
+	/* Refetch the RX queue state as well, because we could be invoked
+	 * here in the queue processing context.
+	 */
+	hv_err = sun4v_ldc_rx_get_state(lp->id,
+					&lp->rx_head,
+					&lp->rx_tail,
+					&lp->chan_state);
+	if (hv_err)
+		printk(KERN_ERR PFX "ldc_abort: "
+		       "sun4v_ldc_rx_get_state(%lx,...) failed, err=%lu\n",
+		       lp->id, hv_err);
+
+	return -ECONNRESET;
+}
+
+static struct ldc_version *find_by_major(u16 major)
+{
+	struct ldc_version *ret = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ver_arr); i++) {
+		struct ldc_version *v = &ver_arr[i];
+		if (v->major <= major) {
+			ret = v;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int process_ver_info(struct ldc_channel *lp, struct ldc_version *vp)
+{
+	struct ldc_version *vap;
+	int err;
+
+	ldcdbg(HS, "GOT VERSION INFO major[%x] minor[%x]\n",
+	       vp->major, vp->minor);
+
+	if (lp->hs_state == LDC_HS_GOTVERS) {
+		lp->hs_state = LDC_HS_OPEN;
+		memset(&lp->ver, 0, sizeof(lp->ver));
+	}
+
+	vap = find_by_major(vp->major);
+	if (!vap) {
+		err = send_version_nack(lp, 0, 0);
+	} else if (vap->major != vp->major) {
+		err = send_version_nack(lp, vap->major, vap->minor);
+	} else {
+		struct ldc_version ver = *vp;
+		if (ver.minor > vap->minor)
+			ver.minor = vap->minor;
+		err = send_version_ack(lp, &ver);
+		if (!err) {
+			lp->ver = ver;
+			lp->hs_state = LDC_HS_GOTVERS;
+		}
+	}
+	if (err)
+		return ldc_abort(lp);
+
+	return 0;
+}
+
+static int process_ver_ack(struct ldc_channel *lp, struct ldc_version *vp)
+{
+	ldcdbg(HS, "GOT VERSION ACK major[%x] minor[%x]\n",
+	       vp->major, vp->minor);
+
+	if (lp->hs_state == LDC_HS_GOTVERS) {
+		if (lp->ver.major != vp->major ||
+		    lp->ver.minor != vp->minor)
+			return ldc_abort(lp);
+	} else {
+		lp->ver = *vp;
+		lp->hs_state = LDC_HS_GOTVERS;
+	}
+	if (send_rts(lp))
+		return ldc_abort(lp);
+	return 0;
+}
+
+static int process_ver_nack(struct ldc_channel *lp, struct ldc_version *vp)
+{
+	struct ldc_version *vap;
+
+	if ((vp->major == 0 && vp->minor == 0) ||
+	    !(vap = find_by_major(vp->major))) {
+		return ldc_abort(lp);
+	} else {
+		struct ldc_packet *p;
+		unsigned long new_tail;
+
+		p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS,
+					   vap, sizeof(*vap),
+					   &new_tail);
+		if (p)
+			return send_tx_packet(lp, p, new_tail);
+		else
+			return ldc_abort(lp);
+	}
+}
+
+static int process_version(struct ldc_channel *lp,
+			   struct ldc_packet *p)
+{
+	struct ldc_version *vp;
+
+	vp = (struct ldc_version *) p->u.u_data;
+
+	switch (p->stype) {
+	case LDC_INFO:
+		return process_ver_info(lp, vp);
+
+	case LDC_ACK:
+		return process_ver_ack(lp, vp);
+
+	case LDC_NACK:
+		return process_ver_nack(lp, vp);
+
+	default:
+		return ldc_abort(lp);
+	}
+}
+
+static int process_rts(struct ldc_channel *lp,
+		       struct ldc_packet *p)
+{
+	ldcdbg(HS, "GOT RTS stype[%x] seqid[%x] env[%x]\n",
+	       p->stype, p->seqid, p->env);
+
+	if (p->stype     != LDC_INFO	   ||
+	    lp->hs_state != LDC_HS_GOTVERS ||
+	    p->env       != lp->cfg.mode)
+		return ldc_abort(lp);
+
+	lp->snd_nxt = p->seqid;
+	lp->rcv_nxt = p->seqid;
+	lp->hs_state = LDC_HS_SENTRTR;
+	if (send_rtr(lp))
+		return ldc_abort(lp);
+
+	return 0;
+}
+
+static int process_rtr(struct ldc_channel *lp,
+		       struct ldc_packet *p)
+{
+	ldcdbg(HS, "GOT RTR stype[%x] seqid[%x] env[%x]\n",
+	       p->stype, p->seqid, p->env);
+
+	if (p->stype     != LDC_INFO ||
+	    p->env       != lp->cfg.mode)
+		return ldc_abort(lp);
+
+	lp->snd_nxt = p->seqid;
+	lp->hs_state = LDC_HS_COMPLETE;
+	ldc_set_state(lp, LDC_STATE_CONNECTED);
+	send_rdx(lp);
+
+	return LDC_EVENT_UP;
+}
+
+static int rx_seq_ok(struct ldc_channel *lp, u32 seqid)
+{
+	return lp->rcv_nxt + 1 == seqid;
+}
+
+static int process_rdx(struct ldc_channel *lp,
+		       struct ldc_packet *p)
+{
+	ldcdbg(HS, "GOT RDX stype[%x] seqid[%x] env[%x] ackid[%x]\n",
+	       p->stype, p->seqid, p->env, p->u.r.ackid);
+
+	if (p->stype != LDC_INFO ||
+	    !(rx_seq_ok(lp, p->seqid)))
+		return ldc_abort(lp);
+
+	lp->rcv_nxt = p->seqid;
+
+	lp->hs_state = LDC_HS_COMPLETE;
+	ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+	return LDC_EVENT_UP;
+}
+
+static int process_control_frame(struct ldc_channel *lp,
+				 struct ldc_packet *p)
+{
+	switch (p->ctrl) {
+	case LDC_VERS:
+		return process_version(lp, p);
+
+	case LDC_RTS:
+		return process_rts(lp, p);
+
+	case LDC_RTR:
+		return process_rtr(lp, p);
+
+	case LDC_RDX:
+		return process_rdx(lp, p);
+
+	default:
+		return ldc_abort(lp);
+	}
+}
+
+static int process_error_frame(struct ldc_channel *lp,
+			       struct ldc_packet *p)
+{
+	return ldc_abort(lp);
+}
+
+static int process_data_ack(struct ldc_channel *lp,
+			    struct ldc_packet *ack)
+{
+	unsigned long head = lp->tx_acked;
+	u32 ackid = ack->u.r.ackid;
+
+	while (1) {
+		struct ldc_packet *p = lp->tx_base + (head / LDC_PACKET_SIZE);
+
+		head = tx_advance(lp, head);
+
+		if (p->seqid == ackid) {
+			lp->tx_acked = head;
+			return 0;
+		}
+		if (head == lp->tx_tail)
+			return ldc_abort(lp);
+	}
+
+	return 0;
+}
+
+static void send_events(struct ldc_channel *lp, unsigned int event_mask)
+{
+	if (event_mask & LDC_EVENT_RESET)
+		lp->cfg.event(lp->event_arg, LDC_EVENT_RESET);
+	if (event_mask & LDC_EVENT_UP)
+		lp->cfg.event(lp->event_arg, LDC_EVENT_UP);
+	if (event_mask & LDC_EVENT_DATA_READY)
+		lp->cfg.event(lp->event_arg, LDC_EVENT_DATA_READY);
+}
+
+static irqreturn_t ldc_rx(int irq, void *dev_id)
+{
+	struct ldc_channel *lp = dev_id;
+	unsigned long orig_state, hv_err, flags;
+	unsigned int event_mask;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	orig_state = lp->chan_state;
+	hv_err = sun4v_ldc_rx_get_state(lp->id,
+					&lp->rx_head,
+					&lp->rx_tail,
+					&lp->chan_state);
+
+	ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
+	       orig_state, lp->chan_state, lp->rx_head, lp->rx_tail);
+
+	event_mask = 0;
+
+	if (lp->cfg.mode == LDC_MODE_RAW &&
+	    lp->chan_state == LDC_CHANNEL_UP) {
+		lp->hs_state = LDC_HS_COMPLETE;
+		ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+		event_mask |= LDC_EVENT_UP;
+
+		orig_state = lp->chan_state;
+	}
+
+	/* If we are in reset state, flush the RX queue and ignore
+	 * everything.
+	 */
+	if (lp->flags & LDC_FLAG_RESET) {
+		(void) __set_rx_head(lp, lp->rx_tail);
+		goto out;
+	}
+
+	/* Once we finish the handshake, we let the ldc_read()
+	 * paths do all of the control frame and state management.
+	 * Just trigger the callback.
+	 */
+	if (lp->hs_state == LDC_HS_COMPLETE) {
+handshake_complete:
+		if (lp->chan_state != orig_state) {
+			unsigned int event = LDC_EVENT_RESET;
+
+			if (lp->chan_state == LDC_CHANNEL_UP)
+				event = LDC_EVENT_UP;
+
+			event_mask |= event;
+		}
+		if (lp->rx_head != lp->rx_tail)
+			event_mask |= LDC_EVENT_DATA_READY;
+
+		goto out;
+	}
+
+	if (lp->chan_state != orig_state)
+		goto out;
+
+	while (lp->rx_head != lp->rx_tail) {
+		struct ldc_packet *p;
+		unsigned long new;
+		int err;
+
+		p = lp->rx_base + (lp->rx_head / LDC_PACKET_SIZE);
+
+		switch (p->type) {
+		case LDC_CTRL:
+			err = process_control_frame(lp, p);
+			if (err > 0)
+				event_mask |= err;
+			break;
+
+		case LDC_DATA:
+			event_mask |= LDC_EVENT_DATA_READY;
+			err = 0;
+			break;
+
+		case LDC_ERR:
+			err = process_error_frame(lp, p);
+			break;
+
+		default:
+			err = ldc_abort(lp);
+			break;
+		}
+
+		if (err < 0)
+			break;
+
+		new = lp->rx_head;
+		new += LDC_PACKET_SIZE;
+		if (new == (lp->rx_num_entries * LDC_PACKET_SIZE))
+			new = 0;
+		lp->rx_head = new;
+
+		err = __set_rx_head(lp, new);
+		if (err < 0) {
+			(void) ldc_abort(lp);
+			break;
+		}
+		if (lp->hs_state == LDC_HS_COMPLETE)
+			goto handshake_complete;
+	}
+
+out:
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	send_events(lp, event_mask);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ldc_tx(int irq, void *dev_id)
+{
+	struct ldc_channel *lp = dev_id;
+	unsigned long flags, hv_err, orig_state;
+	unsigned int event_mask = 0;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	orig_state = lp->chan_state;
+	hv_err = sun4v_ldc_tx_get_state(lp->id,
+					&lp->tx_head,
+					&lp->tx_tail,
+					&lp->chan_state);
+
+	ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
+	       orig_state, lp->chan_state, lp->tx_head, lp->tx_tail);
+
+	if (lp->cfg.mode == LDC_MODE_RAW &&
+	    lp->chan_state == LDC_CHANNEL_UP) {
+		lp->hs_state = LDC_HS_COMPLETE;
+		ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+		event_mask |= LDC_EVENT_UP;
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	send_events(lp, event_mask);
+
+	return IRQ_HANDLED;
+}
+
+/* XXX ldc_alloc() and ldc_free() needs to run under a mutex so
+ * XXX that addition and removal from the ldc_channel_list has
+ * XXX atomicity, otherwise the __ldc_channel_exists() check is
+ * XXX totally pointless as another thread can slip into ldc_alloc()
+ * XXX and add a channel with the same ID.  There also needs to be
+ * XXX a spinlock for ldc_channel_list.
+ */
+static HLIST_HEAD(ldc_channel_list);
+
+static int __ldc_channel_exists(unsigned long id)
+{
+	struct ldc_channel *lp;
+	struct hlist_node *n;
+
+	hlist_for_each_entry(lp, n, &ldc_channel_list, list) {
+		if (lp->id == id)
+			return 1;
+	}
+	return 0;
+}
+
+static int alloc_queue(const char *name, unsigned long num_entries,
+		       struct ldc_packet **base, unsigned long *ra)
+{
+	unsigned long size, order;
+	void *q;
+
+	size = num_entries * LDC_PACKET_SIZE;
+	order = get_order(size);
+
+	q = (void *) __get_free_pages(GFP_KERNEL, order);
+	if (!q) {
+		printk(KERN_ERR PFX "Alloc of %s queue failed with "
+		       "size=%lu order=%lu\n", name, size, order);
+		return -ENOMEM;
+	}
+
+	memset(q, 0, PAGE_SIZE << order);
+
+	*base = q;
+	*ra = __pa(q);
+
+	return 0;
+}
+
+static void free_queue(unsigned long num_entries, struct ldc_packet *q)
+{
+	unsigned long size, order;
+
+	if (!q)
+		return;
+
+	size = num_entries * LDC_PACKET_SIZE;
+	order = get_order(size);
+
+	free_pages((unsigned long)q, order);
+}
+
+/* XXX Make this configurable... XXX */
+#define LDC_IOTABLE_SIZE	(8 * 1024)
+
+static int ldc_iommu_init(struct ldc_channel *lp)
+{
+	unsigned long sz, num_tsb_entries, tsbsize, order;
+	struct ldc_iommu *iommu = &lp->iommu;
+	struct ldc_mtable_entry *table;
+	unsigned long hv_err;
+	int err;
+
+	num_tsb_entries = LDC_IOTABLE_SIZE;
+	tsbsize = num_tsb_entries * sizeof(struct ldc_mtable_entry);
+
+	spin_lock_init(&iommu->lock);
+
+	sz = num_tsb_entries / 8;
+	sz = (sz + 7UL) & ~7UL;
+	iommu->arena.map = kzalloc(sz, GFP_KERNEL);
+	if (!iommu->arena.map) {
+		printk(KERN_ERR PFX "Alloc of arena map failed, sz=%lu\n", sz);
+		return -ENOMEM;
+	}
+
+	iommu->arena.limit = num_tsb_entries;
+
+	order = get_order(tsbsize);
+
+	table = (struct ldc_mtable_entry *)
+		__get_free_pages(GFP_KERNEL, order);
+	err = -ENOMEM;
+	if (!table) {
+		printk(KERN_ERR PFX "Alloc of MTE table failed, "
+		       "size=%lu order=%lu\n", tsbsize, order);
+		goto out_free_map;
+	}
+
+	memset(table, 0, PAGE_SIZE << order);
+
+	iommu->page_table = table;
+
+	hv_err = sun4v_ldc_set_map_table(lp->id, __pa(table),
+					 num_tsb_entries);
+	err = -EINVAL;
+	if (hv_err)
+		goto out_free_table;
+
+	return 0;
+
+out_free_table:
+	free_pages((unsigned long) table, order);
+	iommu->page_table = NULL;
+
+out_free_map:
+	kfree(iommu->arena.map);
+	iommu->arena.map = NULL;
+
+	return err;
+}
+
+static void ldc_iommu_release(struct ldc_channel *lp)
+{
+	struct ldc_iommu *iommu = &lp->iommu;
+	unsigned long num_tsb_entries, tsbsize, order;
+
+	(void) sun4v_ldc_set_map_table(lp->id, 0, 0);
+
+	num_tsb_entries = iommu->arena.limit;
+	tsbsize = num_tsb_entries * sizeof(struct ldc_mtable_entry);
+	order = get_order(tsbsize);
+
+	free_pages((unsigned long) iommu->page_table, order);
+	iommu->page_table = NULL;
+
+	kfree(iommu->arena.map);
+	iommu->arena.map = NULL;
+}
+
+struct ldc_channel *ldc_alloc(unsigned long id,
+			      const struct ldc_channel_config *cfgp,
+			      void *event_arg)
+{
+	struct ldc_channel *lp;
+	const struct ldc_mode_ops *mops;
+	unsigned long dummy1, dummy2, hv_err;
+	u8 mss, *mssbuf;
+	int err;
+
+	err = -ENODEV;
+	if (!ldom_domaining_enabled)
+		goto out_err;
+
+	err = -EINVAL;
+	if (!cfgp)
+		goto out_err;
+
+	switch (cfgp->mode) {
+	case LDC_MODE_RAW:
+		mops = &raw_ops;
+		mss = LDC_PACKET_SIZE;
+		break;
+
+	case LDC_MODE_UNRELIABLE:
+		mops = &nonraw_ops;
+		mss = LDC_PACKET_SIZE - 8;
+		break;
+
+	case LDC_MODE_STREAM:
+		mops = &stream_ops;
+		mss = LDC_PACKET_SIZE - 8 - 8;
+		break;
+
+	default:
+		goto out_err;
+	}
+
+	if (!cfgp->event || !event_arg || !cfgp->rx_irq || !cfgp->tx_irq)
+		goto out_err;
+
+	hv_err = sun4v_ldc_tx_qinfo(id, &dummy1, &dummy2);
+	err = -ENODEV;
+	if (hv_err == HV_ECHANNEL)
+		goto out_err;
+
+	err = -EEXIST;
+	if (__ldc_channel_exists(id))
+		goto out_err;
+
+	mssbuf = NULL;
+
+	lp = kzalloc(sizeof(*lp), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!lp)
+		goto out_err;
+
+	spin_lock_init(&lp->lock);
+
+	lp->id = id;
+
+	err = ldc_iommu_init(lp);
+	if (err)
+		goto out_free_ldc;
+
+	lp->mops = mops;
+	lp->mss = mss;
+
+	lp->cfg = *cfgp;
+	if (!lp->cfg.mtu)
+		lp->cfg.mtu = LDC_DEFAULT_MTU;
+
+	if (lp->cfg.mode == LDC_MODE_STREAM) {
+		mssbuf = kzalloc(lp->cfg.mtu, GFP_KERNEL);
+		if (!mssbuf) {
+			err = -ENOMEM;
+			goto out_free_iommu;
+		}
+		lp->mssbuf = mssbuf;
+	}
+
+	lp->event_arg = event_arg;
+
+	/* XXX allow setting via ldc_channel_config to override defaults
+	 * XXX or use some formula based upon mtu
+	 */
+	lp->tx_num_entries = LDC_DEFAULT_NUM_ENTRIES;
+	lp->rx_num_entries = LDC_DEFAULT_NUM_ENTRIES;
+
+	err = alloc_queue("TX", lp->tx_num_entries,
+			  &lp->tx_base, &lp->tx_ra);
+	if (err)
+		goto out_free_mssbuf;
+
+	err = alloc_queue("RX", lp->rx_num_entries,
+			  &lp->rx_base, &lp->rx_ra);
+	if (err)
+		goto out_free_txq;
+
+	lp->flags |= LDC_FLAG_ALLOCED_QUEUES;
+
+	lp->hs_state = LDC_HS_CLOSED;
+	ldc_set_state(lp, LDC_STATE_INIT);
+
+	INIT_HLIST_NODE(&lp->list);
+	hlist_add_head(&lp->list, &ldc_channel_list);
+
+	INIT_HLIST_HEAD(&lp->mh_list);
+
+	return lp;
+
+out_free_txq:
+	free_queue(lp->tx_num_entries, lp->tx_base);
+
+out_free_mssbuf:
+	if (mssbuf)
+		kfree(mssbuf);
+
+out_free_iommu:
+	ldc_iommu_release(lp);
+
+out_free_ldc:
+	kfree(lp);
+
+out_err:
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(ldc_alloc);
+
+void ldc_free(struct ldc_channel *lp)
+{
+	if (lp->flags & LDC_FLAG_REGISTERED_IRQS) {
+		free_irq(lp->cfg.rx_irq, lp);
+		free_irq(lp->cfg.tx_irq, lp);
+	}
+
+	if (lp->flags & LDC_FLAG_REGISTERED_QUEUES) {
+		sun4v_ldc_tx_qconf(lp->id, 0, 0);
+		sun4v_ldc_rx_qconf(lp->id, 0, 0);
+		lp->flags &= ~LDC_FLAG_REGISTERED_QUEUES;
+	}
+	if (lp->flags & LDC_FLAG_ALLOCED_QUEUES) {
+		free_queue(lp->tx_num_entries, lp->tx_base);
+		free_queue(lp->rx_num_entries, lp->rx_base);
+		lp->flags &= ~LDC_FLAG_ALLOCED_QUEUES;
+	}
+
+	hlist_del(&lp->list);
+
+	if (lp->mssbuf)
+		kfree(lp->mssbuf);
+
+	ldc_iommu_release(lp);
+
+	kfree(lp);
+}
+EXPORT_SYMBOL(ldc_free);
+
+/* Bind the channel.  This registers the LDC queues with
+ * the hypervisor and puts the channel into a pseudo-listening
+ * state.  This does not initiate a handshake, ldc_connect() does
+ * that.
+ */
+int ldc_bind(struct ldc_channel *lp, const char *name)
+{
+	unsigned long hv_err, flags;
+	int err = -EINVAL;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (!name)
+		goto out_err;
+
+	if (lp->state != LDC_STATE_INIT)
+		goto out_err;
+
+	snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
+	snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
+
+	err = request_irq(lp->cfg.rx_irq, ldc_rx,
+			  IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+			  lp->rx_irq_name, lp);
+	if (err)
+		goto out_err;
+
+	err = request_irq(lp->cfg.tx_irq, ldc_tx,
+			  IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+			  lp->tx_irq_name, lp);
+	if (err)
+		goto out_free_rx_irq;
+
+
+	lp->flags |= LDC_FLAG_REGISTERED_IRQS;
+
+	err = -ENODEV;
+	hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
+	if (hv_err)
+		goto out_free_tx_irq;
+
+	hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+	if (hv_err)
+		goto out_free_tx_irq;
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
+	if (hv_err)
+		goto out_unmap_tx;
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+	if (hv_err)
+		goto out_unmap_tx;
+
+	lp->flags |= LDC_FLAG_REGISTERED_QUEUES;
+
+	hv_err = sun4v_ldc_tx_get_state(lp->id,
+					&lp->tx_head,
+					&lp->tx_tail,
+					&lp->chan_state);
+	err = -EBUSY;
+	if (hv_err)
+		goto out_unmap_rx;
+
+	lp->tx_acked = lp->tx_head;
+
+	lp->hs_state = LDC_HS_OPEN;
+	ldc_set_state(lp, LDC_STATE_BOUND);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return 0;
+
+out_unmap_rx:
+	lp->flags &= ~LDC_FLAG_REGISTERED_QUEUES;
+	sun4v_ldc_rx_qconf(lp->id, 0, 0);
+
+out_unmap_tx:
+	sun4v_ldc_tx_qconf(lp->id, 0, 0);
+
+out_free_tx_irq:
+	lp->flags &= ~LDC_FLAG_REGISTERED_IRQS;
+	free_irq(lp->cfg.tx_irq, lp);
+
+out_free_rx_irq:
+	free_irq(lp->cfg.rx_irq, lp);
+
+out_err:
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_bind);
+
+int ldc_connect(struct ldc_channel *lp)
+{
+	unsigned long flags;
+	int err;
+
+	if (lp->cfg.mode == LDC_MODE_RAW)
+		return -EINVAL;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
+	    !(lp->flags & LDC_FLAG_REGISTERED_QUEUES) ||
+	    lp->hs_state != LDC_HS_OPEN)
+		err = -EINVAL;
+	else
+		err = start_handshake(lp);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_connect);
+
+int ldc_disconnect(struct ldc_channel *lp)
+{
+	unsigned long hv_err, flags;
+	int err;
+
+	if (lp->cfg.mode == LDC_MODE_RAW)
+		return -EINVAL;
+
+	if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
+	    !(lp->flags & LDC_FLAG_REGISTERED_QUEUES))
+		return -EINVAL;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	err = -ENODEV;
+	hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
+	if (hv_err)
+		goto out_err;
+
+	hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+	if (hv_err)
+		goto out_err;
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
+	if (hv_err)
+		goto out_err;
+
+	hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+	if (hv_err)
+		goto out_err;
+
+	ldc_set_state(lp, LDC_STATE_BOUND);
+	lp->hs_state = LDC_HS_OPEN;
+	lp->flags |= LDC_FLAG_RESET;
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return 0;
+
+out_err:
+	sun4v_ldc_tx_qconf(lp->id, 0, 0);
+	sun4v_ldc_rx_qconf(lp->id, 0, 0);
+	free_irq(lp->cfg.tx_irq, lp);
+	free_irq(lp->cfg.rx_irq, lp);
+	lp->flags &= ~(LDC_FLAG_REGISTERED_IRQS |
+		       LDC_FLAG_REGISTERED_QUEUES);
+	ldc_set_state(lp, LDC_STATE_INIT);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_disconnect);
+
+int ldc_state(struct ldc_channel *lp)
+{
+	return lp->state;
+}
+EXPORT_SYMBOL(ldc_state);
+
+static int write_raw(struct ldc_channel *lp, const void *buf, unsigned int size)
+{
+	struct ldc_packet *p;
+	unsigned long new_tail;
+	int err;
+
+	if (size > LDC_PACKET_SIZE)
+		return -EMSGSIZE;
+
+	p = data_get_tx_packet(lp, &new_tail);
+	if (!p)
+		return -EAGAIN;
+
+	memcpy(p, buf, size);
+
+	err = send_tx_packet(lp, p, new_tail);
+	if (!err)
+		err = size;
+
+	return err;
+}
+
+static int read_raw(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+	struct ldc_packet *p;
+	unsigned long hv_err, new;
+	int err;
+
+	if (size < LDC_PACKET_SIZE)
+		return -EINVAL;
+
+	hv_err = sun4v_ldc_rx_get_state(lp->id,
+					&lp->rx_head,
+					&lp->rx_tail,
+					&lp->chan_state);
+	if (hv_err)
+		return ldc_abort(lp);
+
+	if (lp->chan_state == LDC_CHANNEL_DOWN ||
+	    lp->chan_state == LDC_CHANNEL_RESETTING)
+		return -ECONNRESET;
+
+	if (lp->rx_head == lp->rx_tail)
+		return 0;
+
+	p = lp->rx_base + (lp->rx_head / LDC_PACKET_SIZE);
+	memcpy(buf, p, LDC_PACKET_SIZE);
+
+	new = rx_advance(lp, lp->rx_head);
+	lp->rx_head = new;
+
+	err = __set_rx_head(lp, new);
+	if (err < 0)
+		err = -ECONNRESET;
+	else
+		err = LDC_PACKET_SIZE;
+
+	return err;
+}
+
+static const struct ldc_mode_ops raw_ops = {
+	.write		=	write_raw,
+	.read		=	read_raw,
+};
+
+static int write_nonraw(struct ldc_channel *lp, const void *buf,
+			unsigned int size)
+{
+	unsigned long hv_err, tail;
+	unsigned int copied;
+	u32 seq;
+	int err;
+
+	hv_err = sun4v_ldc_tx_get_state(lp->id, &lp->tx_head, &lp->tx_tail,
+					&lp->chan_state);
+	if (unlikely(hv_err))
+		return -EBUSY;
+
+	if (unlikely(lp->chan_state != LDC_CHANNEL_UP))
+		return ldc_abort(lp);
+
+	if (!tx_has_space_for(lp, size))
+		return -EAGAIN;
+
+	seq = lp->snd_nxt;
+	copied = 0;
+	tail = lp->tx_tail;
+	while (copied < size) {
+		struct ldc_packet *p = lp->tx_base + (tail / LDC_PACKET_SIZE);
+		u8 *data = ((lp->cfg.mode == LDC_MODE_UNRELIABLE) ?
+			    p->u.u_data :
+			    p->u.r.r_data);
+		int data_len;
+
+		p->type = LDC_DATA;
+		p->stype = LDC_INFO;
+		p->ctrl = 0;
+
+		data_len = size - copied;
+		if (data_len > lp->mss)
+			data_len = lp->mss;
+
+		BUG_ON(data_len > LDC_LEN);
+
+		p->env = (data_len |
+			  (copied == 0 ? LDC_START : 0) |
+			  (data_len == size - copied ? LDC_STOP : 0));
+
+		p->seqid = ++seq;
+
+		ldcdbg(DATA, "SENT DATA [%02x:%02x:%02x:%02x:%08x]\n",
+		       p->type,
+		       p->stype,
+		       p->ctrl,
+		       p->env,
+		       p->seqid);
+
+		memcpy(data, buf, data_len);
+		buf += data_len;
+		copied += data_len;
+
+		tail = tx_advance(lp, tail);
+	}
+
+	err = set_tx_tail(lp, tail);
+	if (!err) {
+		lp->snd_nxt = seq;
+		err = size;
+	}
+
+	return err;
+}
+
+static int rx_bad_seq(struct ldc_channel *lp, struct ldc_packet *p,
+		      struct ldc_packet *first_frag)
+{
+	int err;
+
+	if (first_frag)
+		lp->rcv_nxt = first_frag->seqid - 1;
+
+	err = send_data_nack(lp, p);
+	if (err)
+		return err;
+
+	err = __set_rx_head(lp, lp->rx_tail);
+	if (err < 0)
+		return ldc_abort(lp);
+
+	return 0;
+}
+
+static int data_ack_nack(struct ldc_channel *lp, struct ldc_packet *p)
+{
+	if (p->stype & LDC_ACK) {
+		int err = process_data_ack(lp, p);
+		if (err)
+			return err;
+	}
+	if (p->stype & LDC_NACK)
+		return ldc_abort(lp);
+
+	return 0;
+}
+
+static int rx_data_wait(struct ldc_channel *lp, unsigned long cur_head)
+{
+	unsigned long dummy;
+	int limit = 1000;
+
+	ldcdbg(DATA, "DATA WAIT cur_head[%lx] rx_head[%lx] rx_tail[%lx]\n",
+	       cur_head, lp->rx_head, lp->rx_tail);
+	while (limit-- > 0) {
+		unsigned long hv_err;
+
+		hv_err = sun4v_ldc_rx_get_state(lp->id,
+						&dummy,
+						&lp->rx_tail,
+						&lp->chan_state);
+		if (hv_err)
+			return ldc_abort(lp);
+
+		if (lp->chan_state == LDC_CHANNEL_DOWN ||
+		    lp->chan_state == LDC_CHANNEL_RESETTING)
+			return -ECONNRESET;
+
+		if (cur_head != lp->rx_tail) {
+			ldcdbg(DATA, "DATA WAIT DONE "
+			       "head[%lx] tail[%lx] chan_state[%lx]\n",
+			       dummy, lp->rx_tail, lp->chan_state);
+			return 0;
+		}
+
+		udelay(1);
+	}
+	return -EAGAIN;
+}
+
+static int rx_set_head(struct ldc_channel *lp, unsigned long head)
+{
+	int err = __set_rx_head(lp, head);
+
+	if (err < 0)
+		return ldc_abort(lp);
+
+	lp->rx_head = head;
+	return 0;
+}
+
+static void send_data_ack(struct ldc_channel *lp)
+{
+	unsigned long new_tail;
+	struct ldc_packet *p;
+
+	p = data_get_tx_packet(lp, &new_tail);
+	if (likely(p)) {
+		int err;
+
+		memset(p, 0, sizeof(*p));
+		p->type = LDC_DATA;
+		p->stype = LDC_ACK;
+		p->ctrl = 0;
+		p->seqid = lp->snd_nxt + 1;
+		p->u.r.ackid = lp->rcv_nxt;
+
+		err = send_tx_packet(lp, p, new_tail);
+		if (!err)
+			lp->snd_nxt++;
+	}
+}
+
+static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+	struct ldc_packet *first_frag;
+	unsigned long hv_err, new;
+	int err, copied;
+
+	hv_err = sun4v_ldc_rx_get_state(lp->id,
+					&lp->rx_head,
+					&lp->rx_tail,
+					&lp->chan_state);
+	if (hv_err)
+		return ldc_abort(lp);
+
+	if (lp->chan_state == LDC_CHANNEL_DOWN ||
+	    lp->chan_state == LDC_CHANNEL_RESETTING)
+		return -ECONNRESET;
+
+	if (lp->rx_head == lp->rx_tail)
+		return 0;
+
+	first_frag = NULL;
+	copied = err = 0;
+	new = lp->rx_head;
+	while (1) {
+		struct ldc_packet *p;
+		int pkt_len;
+
+		BUG_ON(new == lp->rx_tail);
+		p = lp->rx_base + (new / LDC_PACKET_SIZE);
+
+		ldcdbg(RX, "RX read pkt[%02x:%02x:%02x:%02x:%08x:%08x] "
+		       "rcv_nxt[%08x]\n",
+		       p->type,
+		       p->stype,
+		       p->ctrl,
+		       p->env,
+		       p->seqid,
+		       p->u.r.ackid,
+		       lp->rcv_nxt);
+
+		if (unlikely(!rx_seq_ok(lp, p->seqid))) {
+			err = rx_bad_seq(lp, p, first_frag);
+			copied = 0;
+			break;
+		}
+
+		if (p->type & LDC_CTRL) {
+			err = process_control_frame(lp, p);
+			if (err < 0)
+				break;
+			err = 0;
+		}
+
+		lp->rcv_nxt = p->seqid;
+
+		if (!(p->type & LDC_DATA)) {
+			new = rx_advance(lp, new);
+			goto no_data;
+		}
+		if (p->stype & (LDC_ACK | LDC_NACK)) {
+			err = data_ack_nack(lp, p);
+			if (err)
+				break;
+		}
+		if (!(p->stype & LDC_INFO)) {
+			new = rx_advance(lp, new);
+			err = rx_set_head(lp, new);
+			if (err)
+				break;
+			goto no_data;
+		}
+
+		pkt_len = p->env & LDC_LEN;
+
+		/* Every initial packet starts with the START bit set.
+		 *
+		 * Singleton packets will have both START+STOP set.
+		 *
+		 * Fragments will have START set in the first frame, STOP
+		 * set in the last frame, and neither bit set in middle
+		 * frames of the packet.
+		 *
+		 * Therefore if we are at the beginning of a packet and
+		 * we don't see START, or we are in the middle of a fragmented
+		 * packet and do see START, we are unsynchronized and should
+		 * flush the RX queue.
+		 */
+		if ((first_frag == NULL && !(p->env & LDC_START)) ||
+		    (first_frag != NULL &&  (p->env & LDC_START))) {
+			if (!first_frag)
+				new = rx_advance(lp, new);
+
+			err = rx_set_head(lp, new);
+			if (err)
+				break;
+
+			if (!first_frag)
+				goto no_data;
+		}
+		if (!first_frag)
+			first_frag = p;
+
+		if (pkt_len > size - copied) {
+			/* User didn't give us a big enough buffer,
+			 * what to do?  This is a pretty serious error.
+			 *
+			 * Since we haven't updated the RX ring head to
+			 * consume any of the packets, signal the error
+			 * to the user and just leave the RX ring alone.
+			 *
+			 * This seems the best behavior because this allows
+			 * a user of the LDC layer to start with a small
+			 * RX buffer for ldc_read() calls and use -EMSGSIZE
+			 * as a cue to enlarge it's read buffer.
+			 */
+			err = -EMSGSIZE;
+			break;
+		}
+
+		/* Ok, we are gonna eat this one.  */
+		new = rx_advance(lp, new);
+
+		memcpy(buf,
+		       (lp->cfg.mode == LDC_MODE_UNRELIABLE ?
+			p->u.u_data : p->u.r.r_data), pkt_len);
+		buf += pkt_len;
+		copied += pkt_len;
+
+		if (p->env & LDC_STOP)
+			break;
+
+no_data:
+		if (new == lp->rx_tail) {
+			err = rx_data_wait(lp, new);
+			if (err)
+				break;
+		}
+	}
+
+	if (!err)
+		err = rx_set_head(lp, new);
+
+	if (err && first_frag)
+		lp->rcv_nxt = first_frag->seqid - 1;
+
+	if (!err) {
+		err = copied;
+		if (err > 0 && lp->cfg.mode != LDC_MODE_UNRELIABLE)
+			send_data_ack(lp);
+	}
+
+	return err;
+}
+
+static const struct ldc_mode_ops nonraw_ops = {
+	.write		=	write_nonraw,
+	.read		=	read_nonraw,
+};
+
+static int write_stream(struct ldc_channel *lp, const void *buf,
+			unsigned int size)
+{
+	if (size > lp->cfg.mtu)
+		size = lp->cfg.mtu;
+	return write_nonraw(lp, buf, size);
+}
+
+static int read_stream(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+	if (!lp->mssbuf_len) {
+		int err = read_nonraw(lp, lp->mssbuf, lp->cfg.mtu);
+		if (err < 0)
+			return err;
+
+		lp->mssbuf_len = err;
+		lp->mssbuf_off = 0;
+	}
+
+	if (size > lp->mssbuf_len)
+		size = lp->mssbuf_len;
+	memcpy(buf, lp->mssbuf + lp->mssbuf_off, size);
+
+	lp->mssbuf_off += size;
+	lp->mssbuf_len -= size;
+
+	return size;
+}
+
+static const struct ldc_mode_ops stream_ops = {
+	.write		=	write_stream,
+	.read		=	read_stream,
+};
+
+int ldc_write(struct ldc_channel *lp, const void *buf, unsigned int size)
+{
+	unsigned long flags;
+	int err;
+
+	if (!buf)
+		return -EINVAL;
+
+	if (!size)
+		return 0;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (lp->hs_state != LDC_HS_COMPLETE)
+		err = -ENOTCONN;
+	else
+		err = lp->mops->write(lp, buf, size);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_write);
+
+int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+	unsigned long flags;
+	int err;
+
+	if (!buf)
+		return -EINVAL;
+
+	if (!size)
+		return 0;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (lp->hs_state != LDC_HS_COMPLETE)
+		err = -ENOTCONN;
+	else
+		err = lp->mops->read(lp, buf, size);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(ldc_read);
+
+static long arena_alloc(struct ldc_iommu *iommu, unsigned long npages)
+{
+	struct iommu_arena *arena = &iommu->arena;
+	unsigned long n, i, start, end, limit;
+	int pass;
+
+	limit = arena->limit;
+	start = arena->hint;
+	pass = 0;
+
+again:
+	n = find_next_zero_bit(arena->map, limit, start);
+	end = n + npages;
+	if (unlikely(end >= limit)) {
+		if (likely(pass < 1)) {
+			limit = start;
+			start = 0;
+			pass++;
+			goto again;
+		} else {
+			/* Scanned the whole thing, give up. */
+			return -1;
+		}
+	}
+
+	for (i = n; i < end; i++) {
+		if (test_bit(i, arena->map)) {
+			start = i + 1;
+			goto again;
+		}
+	}
+
+	for (i = n; i < end; i++)
+		__set_bit(i, arena->map);
+
+	arena->hint = end;
+
+	return n;
+}
+
+#define COOKIE_PGSZ_CODE	0xf000000000000000ULL
+#define COOKIE_PGSZ_CODE_SHIFT	60ULL
+
+static u64 pagesize_code(void)
+{
+	switch (PAGE_SIZE) {
+	default:
+	case (8ULL * 1024ULL):
+		return 0;
+	case (64ULL * 1024ULL):
+		return 1;
+	case (512ULL * 1024ULL):
+		return 2;
+	case (4ULL * 1024ULL * 1024ULL):
+		return 3;
+	case (32ULL * 1024ULL * 1024ULL):
+		return 4;
+	case (256ULL * 1024ULL * 1024ULL):
+		return 5;
+	}
+}
+
+static u64 make_cookie(u64 index, u64 pgsz_code, u64 page_offset)
+{
+	return ((pgsz_code << COOKIE_PGSZ_CODE_SHIFT) |
+		(index << PAGE_SHIFT) |
+		page_offset);
+}
+
+static u64 cookie_to_index(u64 cookie, unsigned long *shift)
+{
+	u64 szcode = cookie >> COOKIE_PGSZ_CODE_SHIFT;
+
+	cookie &= ~COOKIE_PGSZ_CODE;
+
+	*shift = szcode * 3;
+
+	return (cookie >> (13ULL + (szcode * 3ULL)));
+}
+
+static struct ldc_mtable_entry *alloc_npages(struct ldc_iommu *iommu,
+					     unsigned long npages)
+{
+	long entry;
+
+	entry = arena_alloc(iommu, npages);
+	if (unlikely(entry < 0))
+		return NULL;
+
+	return iommu->page_table + entry;
+}
+
+static u64 perm_to_mte(unsigned int map_perm)
+{
+	u64 mte_base;
+
+	mte_base = pagesize_code();
+
+	if (map_perm & LDC_MAP_SHADOW) {
+		if (map_perm & LDC_MAP_R)
+			mte_base |= LDC_MTE_COPY_R;
+		if (map_perm & LDC_MAP_W)
+			mte_base |= LDC_MTE_COPY_W;
+	}
+	if (map_perm & LDC_MAP_DIRECT) {
+		if (map_perm & LDC_MAP_R)
+			mte_base |= LDC_MTE_READ;
+		if (map_perm & LDC_MAP_W)
+			mte_base |= LDC_MTE_WRITE;
+		if (map_perm & LDC_MAP_X)
+			mte_base |= LDC_MTE_EXEC;
+	}
+	if (map_perm & LDC_MAP_IO) {
+		if (map_perm & LDC_MAP_R)
+			mte_base |= LDC_MTE_IOMMU_R;
+		if (map_perm & LDC_MAP_W)
+			mte_base |= LDC_MTE_IOMMU_W;
+	}
+
+	return mte_base;
+}
+
+static int pages_in_region(unsigned long base, long len)
+{
+	int count = 0;
+
+	do {
+		unsigned long new = (base + PAGE_SIZE) & PAGE_MASK;
+
+		len -= (new - base);
+		base = new;
+		count++;
+	} while (len > 0);
+
+	return count;
+}
+
+struct cookie_state {
+	struct ldc_mtable_entry		*page_table;
+	struct ldc_trans_cookie		*cookies;
+	u64				mte_base;
+	u64				prev_cookie;
+	u32				pte_idx;
+	u32				nc;
+};
+
+static void fill_cookies(struct cookie_state *sp, unsigned long pa,
+			 unsigned long off, unsigned long len)
+{
+	do {
+		unsigned long tlen, new = pa + PAGE_SIZE;
+		u64 this_cookie;
+
+		sp->page_table[sp->pte_idx].mte = sp->mte_base | pa;
+
+		tlen = PAGE_SIZE;
+		if (off)
+			tlen = PAGE_SIZE - off;
+		if (tlen > len)
+			tlen = len;
+
+		this_cookie = make_cookie(sp->pte_idx,
+					  pagesize_code(), off);
+
+		off = 0;
+
+		if (this_cookie == sp->prev_cookie) {
+			sp->cookies[sp->nc - 1].cookie_size += tlen;
+		} else {
+			sp->cookies[sp->nc].cookie_addr = this_cookie;
+			sp->cookies[sp->nc].cookie_size = tlen;
+			sp->nc++;
+		}
+		sp->prev_cookie = this_cookie + tlen;
+
+		sp->pte_idx++;
+
+		len -= tlen;
+		pa = new;
+	} while (len > 0);
+}
+
+static int sg_count_one(struct scatterlist *sg)
+{
+	unsigned long base = page_to_pfn(sg->page) << PAGE_SHIFT;
+	long len = sg->length;
+
+	if ((sg->offset | len) & (8UL - 1))
+		return -EFAULT;
+
+	return pages_in_region(base + sg->offset, len);
+}
+
+static int sg_count_pages(struct scatterlist *sg, int num_sg)
+{
+	int count;
+	int i;
+
+	count = 0;
+	for (i = 0; i < num_sg; i++) {
+		int err = sg_count_one(sg + i);
+		if (err < 0)
+			return err;
+		count += err;
+	}
+
+	return count;
+}
+
+int ldc_map_sg(struct ldc_channel *lp,
+	       struct scatterlist *sg, int num_sg,
+	       struct ldc_trans_cookie *cookies, int ncookies,
+	       unsigned int map_perm)
+{
+	unsigned long i, npages, flags;
+	struct ldc_mtable_entry *base;
+	struct cookie_state state;
+	struct ldc_iommu *iommu;
+	int err;
+
+	if (map_perm & ~LDC_MAP_ALL)
+		return -EINVAL;
+
+	err = sg_count_pages(sg, num_sg);
+	if (err < 0)
+		return err;
+
+	npages = err;
+	if (err > ncookies)
+		return -EMSGSIZE;
+
+	iommu = &lp->iommu;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	base = alloc_npages(iommu, npages);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	if (!base)
+		return -ENOMEM;
+
+	state.page_table = iommu->page_table;
+	state.cookies = cookies;
+	state.mte_base = perm_to_mte(map_perm);
+	state.prev_cookie = ~(u64)0;
+	state.pte_idx = (base - iommu->page_table);
+	state.nc = 0;
+
+	for (i = 0; i < num_sg; i++)
+		fill_cookies(&state, page_to_pfn(sg[i].page) << PAGE_SHIFT,
+			     sg[i].offset, sg[i].length);
+
+	return state.nc;
+}
+EXPORT_SYMBOL(ldc_map_sg);
+
+int ldc_map_single(struct ldc_channel *lp,
+		   void *buf, unsigned int len,
+		   struct ldc_trans_cookie *cookies, int ncookies,
+		   unsigned int map_perm)
+{
+	unsigned long npages, pa, flags;
+	struct ldc_mtable_entry *base;
+	struct cookie_state state;
+	struct ldc_iommu *iommu;
+
+	if ((map_perm & ~LDC_MAP_ALL) || (ncookies < 1))
+		return -EINVAL;
+
+	pa = __pa(buf);
+	if ((pa | len) & (8UL - 1))
+		return -EFAULT;
+
+	npages = pages_in_region(pa, len);
+
+	iommu = &lp->iommu;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	base = alloc_npages(iommu, npages);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	if (!base)
+		return -ENOMEM;
+
+	state.page_table = iommu->page_table;
+	state.cookies = cookies;
+	state.mte_base = perm_to_mte(map_perm);
+	state.prev_cookie = ~(u64)0;
+	state.pte_idx = (base - iommu->page_table);
+	state.nc = 0;
+	fill_cookies(&state, (pa & PAGE_MASK), (pa & ~PAGE_MASK), len);
+	BUG_ON(state.nc != 1);
+
+	return state.nc;
+}
+EXPORT_SYMBOL(ldc_map_single);
+
+static void free_npages(unsigned long id, struct ldc_iommu *iommu,
+			u64 cookie, u64 size)
+{
+	struct iommu_arena *arena = &iommu->arena;
+	unsigned long i, shift, index, npages;
+	struct ldc_mtable_entry *base;
+
+	npages = PAGE_ALIGN(((cookie & ~PAGE_MASK) + size)) >> PAGE_SHIFT;
+	index = cookie_to_index(cookie, &shift);
+	base = iommu->page_table + index;
+
+	BUG_ON(index > arena->limit ||
+	       (index + npages) > arena->limit);
+
+	for (i = 0; i < npages; i++) {
+		if (base->cookie)
+			sun4v_ldc_revoke(id, cookie + (i << shift),
+					 base->cookie);
+		base->mte = 0;
+		__clear_bit(index + i, arena->map);
+	}
+}
+
+void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+	       int ncookies)
+{
+	struct ldc_iommu *iommu = &lp->iommu;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	for (i = 0; i < ncookies; i++) {
+		u64 addr = cookies[i].cookie_addr;
+		u64 size = cookies[i].cookie_size;
+
+		free_npages(lp->id, iommu, addr, size);
+	}
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+EXPORT_SYMBOL(ldc_unmap);
+
+int ldc_copy(struct ldc_channel *lp, int copy_dir,
+	     void *buf, unsigned int len, unsigned long offset,
+	     struct ldc_trans_cookie *cookies, int ncookies)
+{
+	unsigned int orig_len;
+	unsigned long ra;
+	int i;
+
+	if (copy_dir != LDC_COPY_IN && copy_dir != LDC_COPY_OUT) {
+		printk(KERN_ERR PFX "ldc_copy: ID[%lu] Bad copy_dir[%d]\n",
+		       lp->id, copy_dir);
+		return -EINVAL;
+	}
+
+	ra = __pa(buf);
+	if ((ra | len | offset) & (8UL - 1)) {
+		printk(KERN_ERR PFX "ldc_copy: ID[%lu] Unaligned buffer "
+		       "ra[%lx] len[%x] offset[%lx]\n",
+		       lp->id, ra, len, offset);
+		return -EFAULT;
+	}
+
+	if (lp->hs_state != LDC_HS_COMPLETE ||
+	    (lp->flags & LDC_FLAG_RESET)) {
+		printk(KERN_ERR PFX "ldc_copy: ID[%lu] Link down hs_state[%x] "
+		       "flags[%x]\n", lp->id, lp->hs_state, lp->flags);
+		return -ECONNRESET;
+	}
+
+	orig_len = len;
+	for (i = 0; i < ncookies; i++) {
+		unsigned long cookie_raddr = cookies[i].cookie_addr;
+		unsigned long this_len = cookies[i].cookie_size;
+		unsigned long actual_len;
+
+		if (unlikely(offset)) {
+			unsigned long this_off = offset;
+
+			if (this_off > this_len)
+				this_off = this_len;
+
+			offset -= this_off;
+			this_len -= this_off;
+			if (!this_len)
+				continue;
+			cookie_raddr += this_off;
+		}
+
+		if (this_len > len)
+			this_len = len;
+
+		while (1) {
+			unsigned long hv_err;
+
+			hv_err = sun4v_ldc_copy(lp->id, copy_dir,
+						cookie_raddr, ra,
+						this_len, &actual_len);
+			if (unlikely(hv_err)) {
+				printk(KERN_ERR PFX "ldc_copy: ID[%lu] "
+				       "HV error %lu\n",
+				       lp->id, hv_err);
+				if (lp->hs_state != LDC_HS_COMPLETE ||
+				    (lp->flags & LDC_FLAG_RESET))
+					return -ECONNRESET;
+				else
+					return -EFAULT;
+			}
+
+			cookie_raddr += actual_len;
+			ra += actual_len;
+			len -= actual_len;
+			if (actual_len == this_len)
+				break;
+
+			this_len -= actual_len;
+		}
+
+		if (!len)
+			break;
+	}
+
+	/* It is caller policy what to do about short copies.
+	 * For example, a networking driver can declare the
+	 * packet a runt and drop it.
+	 */
+
+	return orig_len - len;
+}
+EXPORT_SYMBOL(ldc_copy);
+
+void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+			  struct ldc_trans_cookie *cookies, int *ncookies,
+			  unsigned int map_perm)
+{
+	void *buf;
+	int err;
+
+	if (len & (8UL - 1))
+		return ERR_PTR(-EINVAL);
+
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	err = ldc_map_single(lp, buf, len, cookies, *ncookies, map_perm);
+	if (err < 0) {
+		kfree(buf);
+		return ERR_PTR(err);
+	}
+	*ncookies = err;
+
+	return buf;
+}
+EXPORT_SYMBOL(ldc_alloc_exp_dring);
+
+void ldc_free_exp_dring(struct ldc_channel *lp, void *buf, unsigned int len,
+			struct ldc_trans_cookie *cookies, int ncookies)
+{
+	ldc_unmap(lp, cookies, ncookies);
+	kfree(buf);
+}
+EXPORT_SYMBOL(ldc_free_exp_dring);
+
+static int __init ldc_init(void)
+{
+	unsigned long major, minor;
+	struct mdesc_handle *hp;
+	const u64 *v;
+	u64 mp;
+
+	hp = mdesc_grab();
+	if (!hp)
+		return -ENODEV;
+
+	mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
+	if (mp == MDESC_NODE_NULL)
+		return -ENODEV;
+
+	v = mdesc_get_property(hp, mp, "domaining-enabled", NULL);
+	if (!v)
+		return -ENODEV;
+
+	major = 1;
+	minor = 0;
+	if (sun4v_hvapi_register(HV_GRP_LDOM, major, &minor)) {
+		printk(KERN_INFO PFX "Could not register LDOM hvapi.\n");
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "%s", version);
+
+	if (!*v) {
+		printk(KERN_INFO PFX "Domaining disabled.\n");
+		return -ENODEV;
+	}
+	ldom_domaining_enabled = 1;
+
+	return 0;
+}
+
+core_initcall(ldc_init);
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
new file mode 100644
index 0000000..de5310f
--- /dev/null
+++ b/arch/sparc64/kernel/mdesc.c
@@ -0,0 +1,764 @@
+/* mdesc.c: Sun4V machine description handling.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/bootmem.h>
+#include <linux/log2.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+
+#include <asm/hypervisor.h>
+#include <asm/mdesc.h>
+#include <asm/prom.h>
+#include <asm/oplib.h>
+#include <asm/smp.h>
+
+/* Unlike the OBP device tree, the machine description is a full-on
+ * DAG.  An arbitrary number of ARCs are possible from one
+ * node to other nodes and thus we can't use the OBP device_node
+ * data structure to represent these nodes inside of the kernel.
+ *
+ * Actually, it isn't even a DAG, because there are back pointers
+ * which create cycles in the graph.
+ *
+ * mdesc_hdr and mdesc_elem describe the layout of the data structure
+ * we get from the Hypervisor.
+ */
+struct mdesc_hdr {
+	u32	version; /* Transport version */
+	u32	node_sz; /* node block size */
+	u32	name_sz; /* name block size */
+	u32	data_sz; /* data block size */
+} __attribute__((aligned(16)));
+
+struct mdesc_elem {
+	u8	tag;
+#define MD_LIST_END	0x00
+#define MD_NODE		0x4e
+#define MD_NODE_END	0x45
+#define MD_NOOP		0x20
+#define MD_PROP_ARC	0x61
+#define MD_PROP_VAL	0x76
+#define MD_PROP_STR	0x73
+#define MD_PROP_DATA	0x64
+	u8	name_len;
+	u16	resv;
+	u32	name_offset;
+	union {
+		struct {
+			u32	data_len;
+			u32	data_offset;
+		} data;
+		u64	val;
+	} d;
+};
+
+struct mdesc_mem_ops {
+	struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
+	void (*free)(struct mdesc_handle *handle);
+};
+
+struct mdesc_handle {
+	struct list_head	list;
+	struct mdesc_mem_ops	*mops;
+	void			*self_base;
+	atomic_t		refcnt;
+	unsigned int		handle_size;
+	struct mdesc_hdr	mdesc;
+};
+
+static void mdesc_handle_init(struct mdesc_handle *hp,
+			      unsigned int handle_size,
+			      void *base)
+{
+	BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
+
+	memset(hp, 0, handle_size);
+	INIT_LIST_HEAD(&hp->list);
+	hp->self_base = base;
+	atomic_set(&hp->refcnt, 1);
+	hp->handle_size = handle_size;
+}
+
+static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size)
+{
+	struct mdesc_handle *hp;
+	unsigned int handle_size, alloc_size;
+
+	handle_size = (sizeof(struct mdesc_handle) -
+		       sizeof(struct mdesc_hdr) +
+		       mdesc_size);
+	alloc_size = PAGE_ALIGN(handle_size);
+
+	hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
+	if (hp)
+		mdesc_handle_init(hp, handle_size, hp);
+
+	return hp;
+}
+
+static void mdesc_bootmem_free(struct mdesc_handle *hp)
+{
+	unsigned int alloc_size, handle_size = hp->handle_size;
+	unsigned long start, end;
+
+	BUG_ON(atomic_read(&hp->refcnt) != 0);
+	BUG_ON(!list_empty(&hp->list));
+
+	alloc_size = PAGE_ALIGN(handle_size);
+
+	start = (unsigned long) hp;
+	end = start + alloc_size;
+
+	while (start < end) {
+		struct page *p;
+
+		p = virt_to_page(start);
+		ClearPageReserved(p);
+		__free_page(p);
+		start += PAGE_SIZE;
+	}
+}
+
+static struct mdesc_mem_ops bootmem_mdesc_memops = {
+	.alloc = mdesc_bootmem_alloc,
+	.free  = mdesc_bootmem_free,
+};
+
+static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
+{
+	unsigned int handle_size;
+	void *base;
+
+	handle_size = (sizeof(struct mdesc_handle) -
+		       sizeof(struct mdesc_hdr) +
+		       mdesc_size);
+
+	base = kmalloc(handle_size + 15, GFP_KERNEL);
+	if (base) {
+		struct mdesc_handle *hp;
+		unsigned long addr;
+
+		addr = (unsigned long)base;
+		addr = (addr + 15UL) & ~15UL;
+		hp = (struct mdesc_handle *) addr;
+
+		mdesc_handle_init(hp, handle_size, base);
+		return hp;
+	}
+
+	return NULL;
+}
+
+static void mdesc_kfree(struct mdesc_handle *hp)
+{
+	BUG_ON(atomic_read(&hp->refcnt) != 0);
+	BUG_ON(!list_empty(&hp->list));
+
+	kfree(hp->self_base);
+}
+
+static struct mdesc_mem_ops kmalloc_mdesc_memops = {
+	.alloc = mdesc_kmalloc,
+	.free  = mdesc_kfree,
+};
+
+static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
+					struct mdesc_mem_ops *mops)
+{
+	struct mdesc_handle *hp = mops->alloc(mdesc_size);
+
+	if (hp)
+		hp->mops = mops;
+
+	return hp;
+}
+
+static void mdesc_free(struct mdesc_handle *hp)
+{
+	hp->mops->free(hp);
+}
+
+static struct mdesc_handle *cur_mdesc;
+static LIST_HEAD(mdesc_zombie_list);
+static DEFINE_SPINLOCK(mdesc_lock);
+
+struct mdesc_handle *mdesc_grab(void)
+{
+	struct mdesc_handle *hp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdesc_lock, flags);
+	hp = cur_mdesc;
+	if (hp)
+		atomic_inc(&hp->refcnt);
+	spin_unlock_irqrestore(&mdesc_lock, flags);
+
+	return hp;
+}
+EXPORT_SYMBOL(mdesc_grab);
+
+void mdesc_release(struct mdesc_handle *hp)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdesc_lock, flags);
+	if (atomic_dec_and_test(&hp->refcnt)) {
+		list_del_init(&hp->list);
+		hp->mops->free(hp);
+	}
+	spin_unlock_irqrestore(&mdesc_lock, flags);
+}
+EXPORT_SYMBOL(mdesc_release);
+
+void mdesc_update(void)
+{
+	unsigned long len, real_len, status;
+	struct mdesc_handle *hp, *orig_hp;
+	unsigned long flags;
+
+	(void) sun4v_mach_desc(0UL, 0UL, &len);
+
+	hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
+	if (!hp) {
+		printk(KERN_ERR "MD: mdesc alloc fails\n");
+		return;
+	}
+
+	status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
+	if (status != HV_EOK || real_len > len) {
+		printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
+		       status);
+		atomic_dec(&hp->refcnt);
+		mdesc_free(hp);
+		return;
+	}
+
+	spin_lock_irqsave(&mdesc_lock, flags);
+	orig_hp = cur_mdesc;
+	cur_mdesc = hp;
+
+	if (atomic_dec_and_test(&orig_hp->refcnt))
+		mdesc_free(orig_hp);
+	else
+		list_add(&orig_hp->list, &mdesc_zombie_list);
+	spin_unlock_irqrestore(&mdesc_lock, flags);
+}
+
+static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
+{
+	return (struct mdesc_elem *) (mdesc + 1);
+}
+
+static void *name_block(struct mdesc_hdr *mdesc)
+{
+	return ((void *) node_block(mdesc)) + mdesc->node_sz;
+}
+
+static void *data_block(struct mdesc_hdr *mdesc)
+{
+	return ((void *) name_block(mdesc)) + mdesc->name_sz;
+}
+
+u64 mdesc_node_by_name(struct mdesc_handle *hp,
+		       u64 from_node, const char *name)
+{
+	struct mdesc_elem *ep = node_block(&hp->mdesc);
+	const char *names = name_block(&hp->mdesc);
+	u64 last_node = hp->mdesc.node_sz / 16;
+	u64 ret;
+
+	if (from_node == MDESC_NODE_NULL) {
+		ret = from_node = 0;
+	} else if (from_node >= last_node) {
+		return MDESC_NODE_NULL;
+	} else {
+		ret = ep[from_node].d.val;
+	}
+
+	while (ret < last_node) {
+		if (ep[ret].tag != MD_NODE)
+			return MDESC_NODE_NULL;
+		if (!strcmp(names + ep[ret].name_offset, name))
+			break;
+		ret = ep[ret].d.val;
+	}
+	if (ret >= last_node)
+		ret = MDESC_NODE_NULL;
+	return ret;
+}
+EXPORT_SYMBOL(mdesc_node_by_name);
+
+const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
+			       const char *name, int *lenp)
+{
+	const char *names = name_block(&hp->mdesc);
+	u64 last_node = hp->mdesc.node_sz / 16;
+	void *data = data_block(&hp->mdesc);
+	struct mdesc_elem *ep;
+
+	if (node == MDESC_NODE_NULL || node >= last_node)
+		return NULL;
+
+	ep = node_block(&hp->mdesc) + node;
+	ep++;
+	for (; ep->tag != MD_NODE_END; ep++) {
+		void *val = NULL;
+		int len = 0;
+
+		switch (ep->tag) {
+		case MD_PROP_VAL:
+			val = &ep->d.val;
+			len = 8;
+			break;
+
+		case MD_PROP_STR:
+		case MD_PROP_DATA:
+			val = data + ep->d.data.data_offset;
+			len = ep->d.data.data_len;
+			break;
+
+		default:
+			break;
+		}
+		if (!val)
+			continue;
+
+		if (!strcmp(names + ep->name_offset, name)) {
+			if (lenp)
+				*lenp = len;
+			return val;
+		}
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(mdesc_get_property);
+
+u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
+{
+	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+	const char *names = name_block(&hp->mdesc);
+	u64 last_node = hp->mdesc.node_sz / 16;
+
+	if (from == MDESC_NODE_NULL || from >= last_node)
+		return MDESC_NODE_NULL;
+
+	ep = base + from;
+
+	ep++;
+	for (; ep->tag != MD_NODE_END; ep++) {
+		if (ep->tag != MD_PROP_ARC)
+			continue;
+
+		if (strcmp(names + ep->name_offset, arc_type))
+			continue;
+
+		return ep - base;
+	}
+
+	return MDESC_NODE_NULL;
+}
+EXPORT_SYMBOL(mdesc_next_arc);
+
+u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
+{
+	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+
+	ep = base + arc;
+
+	return ep->d.val;
+}
+EXPORT_SYMBOL(mdesc_arc_target);
+
+const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
+{
+	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+	const char *names = name_block(&hp->mdesc);
+	u64 last_node = hp->mdesc.node_sz / 16;
+
+	if (node == MDESC_NODE_NULL || node >= last_node)
+		return NULL;
+
+	ep = base + node;
+	if (ep->tag != MD_NODE)
+		return NULL;
+
+	return names + ep->name_offset;
+}
+EXPORT_SYMBOL(mdesc_node_name);
+
+static void __init report_platform_properties(void)
+{
+	struct mdesc_handle *hp = mdesc_grab();
+	u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
+	const char *s;
+	const u64 *v;
+
+	if (pn == MDESC_NODE_NULL) {
+		prom_printf("No platform node in machine-description.\n");
+		prom_halt();
+	}
+
+	s = mdesc_get_property(hp, pn, "banner-name", NULL);
+	printk("PLATFORM: banner-name [%s]\n", s);
+	s = mdesc_get_property(hp, pn, "name", NULL);
+	printk("PLATFORM: name [%s]\n", s);
+
+	v = mdesc_get_property(hp, pn, "hostid", NULL);
+	if (v)
+		printk("PLATFORM: hostid [%08lx]\n", *v);
+	v = mdesc_get_property(hp, pn, "serial#", NULL);
+	if (v)
+		printk("PLATFORM: serial# [%08lx]\n", *v);
+	v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
+	printk("PLATFORM: stick-frequency [%08lx]\n", *v);
+	v = mdesc_get_property(hp, pn, "mac-address", NULL);
+	if (v)
+		printk("PLATFORM: mac-address [%lx]\n", *v);
+	v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
+	if (v)
+		printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);
+	v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
+	if (v)
+		printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);
+	v = mdesc_get_property(hp, pn, "max-cpus", NULL);
+	if (v)
+		printk("PLATFORM: max-cpus [%lu]\n", *v);
+
+#ifdef CONFIG_SMP
+	{
+		int max_cpu, i;
+
+		if (v) {
+			max_cpu = *v;
+			if (max_cpu > NR_CPUS)
+				max_cpu = NR_CPUS;
+		} else {
+			max_cpu = NR_CPUS;
+		}
+		for (i = 0; i < max_cpu; i++)
+			cpu_set(i, cpu_possible_map);
+	}
+#endif
+
+	mdesc_release(hp);
+}
+
+static int inline find_in_proplist(const char *list, const char *match, int len)
+{
+	while (len > 0) {
+		int l;
+
+		if (!strcmp(list, match))
+			return 1;
+		l = strlen(list) + 1;
+		list += l;
+		len -= l;
+	}
+	return 0;
+}
+
+static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
+					struct mdesc_handle *hp,
+					u64 mp)
+{
+	const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
+	const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
+	const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
+	const char *type;
+	int type_len;
+
+	type = mdesc_get_property(hp, mp, "type", &type_len);
+
+	switch (*level) {
+	case 1:
+		if (find_in_proplist(type, "instn", type_len)) {
+			c->icache_size = *size;
+			c->icache_line_size = *line_size;
+		} else if (find_in_proplist(type, "data", type_len)) {
+			c->dcache_size = *size;
+			c->dcache_line_size = *line_size;
+		}
+		break;
+
+	case 2:
+		c->ecache_size = *size;
+		c->ecache_line_size = *line_size;
+		break;
+
+	default:
+		break;
+	}
+
+	if (*level == 1) {
+		u64 a;
+
+		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+			u64 target = mdesc_arc_target(hp, a);
+			const char *name = mdesc_node_name(hp, target);
+
+			if (!strcmp(name, "cache"))
+				fill_in_one_cache(c, hp, target);
+		}
+	}
+}
+
+static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
+				    int core_id)
+{
+	u64 a;
+
+	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
+		u64 t = mdesc_arc_target(hp, a);
+		const char *name;
+		const u64 *id;
+
+		name = mdesc_node_name(hp, t);
+		if (!strcmp(name, "cpu")) {
+			id = mdesc_get_property(hp, t, "id", NULL);
+			if (*id < NR_CPUS)
+				cpu_data(*id).core_id = core_id;
+		} else {
+			u64 j;
+
+			mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
+				u64 n = mdesc_arc_target(hp, j);
+				const char *n_name;
+
+				n_name = mdesc_node_name(hp, n);
+				if (strcmp(n_name, "cpu"))
+					continue;
+
+				id = mdesc_get_property(hp, n, "id", NULL);
+				if (*id < NR_CPUS)
+					cpu_data(*id).core_id = core_id;
+			}
+		}
+	}
+}
+
+static void __devinit set_core_ids(struct mdesc_handle *hp)
+{
+	int idx;
+	u64 mp;
+
+	idx = 1;
+	mdesc_for_each_node_by_name(hp, mp, "cache") {
+		const u64 *level;
+		const char *type;
+		int len;
+
+		level = mdesc_get_property(hp, mp, "level", NULL);
+		if (*level != 1)
+			continue;
+
+		type = mdesc_get_property(hp, mp, "type", &len);
+		if (!find_in_proplist(type, "instn", len))
+			continue;
+
+		mark_core_ids(hp, mp, idx);
+
+		idx++;
+	}
+}
+
+static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
+				    int proc_id)
+{
+	u64 a;
+
+	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
+		u64 t = mdesc_arc_target(hp, a);
+		const char *name;
+		const u64 *id;
+
+		name = mdesc_node_name(hp, t);
+		if (strcmp(name, "cpu"))
+			continue;
+
+		id = mdesc_get_property(hp, t, "id", NULL);
+		if (*id < NR_CPUS)
+			cpu_data(*id).proc_id = proc_id;
+	}
+}
+
+static void __devinit __set_proc_ids(struct mdesc_handle *hp,
+				     const char *exec_unit_name)
+{
+	int idx;
+	u64 mp;
+
+	idx = 0;
+	mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
+		const char *type;
+		int len;
+
+		type = mdesc_get_property(hp, mp, "type", &len);
+		if (!find_in_proplist(type, "int", len) &&
+		    !find_in_proplist(type, "integer", len))
+			continue;
+
+		mark_proc_ids(hp, mp, idx);
+
+		idx++;
+	}
+}
+
+static void __devinit set_proc_ids(struct mdesc_handle *hp)
+{
+	__set_proc_ids(hp, "exec_unit");
+	__set_proc_ids(hp, "exec-unit");
+}
+
+static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
+					 unsigned char def)
+{
+	u64 val;
+
+	if (!p)
+		goto use_default;
+	val = *p;
+
+	if (!val || val >= 64)
+		goto use_default;
+
+	*mask = ((1U << val) * 64U) - 1U;
+	return;
+
+use_default:
+	*mask = ((1U << def) * 64U) - 1U;
+}
+
+static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
+				     struct trap_per_cpu *tb)
+{
+	const u64 *val;
+
+	val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
+	get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
+
+	val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
+	get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
+
+	val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
+	get_one_mondo_bits(val, &tb->resum_qmask, 6);
+
+	val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
+	get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
+}
+
+void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
+{
+	struct mdesc_handle *hp = mdesc_grab();
+	u64 mp;
+
+	ncpus_probed = 0;
+	mdesc_for_each_node_by_name(hp, mp, "cpu") {
+		const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
+		const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
+		struct trap_per_cpu *tb;
+		cpuinfo_sparc *c;
+		int cpuid;
+		u64 a;
+
+		ncpus_probed++;
+
+		cpuid = *id;
+
+#ifdef CONFIG_SMP
+		if (cpuid >= NR_CPUS)
+			continue;
+		if (!cpu_isset(cpuid, mask))
+			continue;
+#else
+		/* On uniprocessor we only want the values for the
+		 * real physical cpu the kernel booted onto, however
+		 * cpu_data() only has one entry at index 0.
+		 */
+		if (cpuid != real_hard_smp_processor_id())
+			continue;
+		cpuid = 0;
+#endif
+
+		c = &cpu_data(cpuid);
+		c->clock_tick = *cfreq;
+
+		tb = &trap_block[cpuid];
+		get_mondo_data(hp, mp, tb);
+
+		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+			u64 j, t = mdesc_arc_target(hp, a);
+			const char *t_name;
+
+			t_name = mdesc_node_name(hp, t);
+			if (!strcmp(t_name, "cache")) {
+				fill_in_one_cache(c, hp, t);
+				continue;
+			}
+
+			mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
+				u64 n = mdesc_arc_target(hp, j);
+				const char *n_name;
+
+				n_name = mdesc_node_name(hp, n);
+				if (!strcmp(n_name, "cache"))
+					fill_in_one_cache(c, hp, n);
+			}
+		}
+
+#ifdef CONFIG_SMP
+		cpu_set(cpuid, cpu_present_map);
+#endif
+
+		c->core_id = 0;
+		c->proc_id = -1;
+	}
+
+#ifdef CONFIG_SMP
+	sparc64_multi_core = 1;
+#endif
+
+	set_core_ids(hp);
+	set_proc_ids(hp);
+
+	smp_fill_in_sib_core_maps();
+
+	mdesc_release(hp);
+}
+
+void __init sun4v_mdesc_init(void)
+{
+	struct mdesc_handle *hp;
+	unsigned long len, real_len, status;
+	cpumask_t mask;
+
+	(void) sun4v_mach_desc(0UL, 0UL, &len);
+
+	printk("MDESC: Size is %lu bytes.\n", len);
+
+	hp = mdesc_alloc(len, &bootmem_mdesc_memops);
+	if (hp == NULL) {
+		prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
+		prom_halt();
+	}
+
+	status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
+	if (status != HV_EOK || real_len > len) {
+		prom_printf("sun4v_mach_desc fails, err(%lu), "
+			    "len(%lu), real_len(%lu)\n",
+			    status, len, real_len);
+		mdesc_free(hp);
+		prom_halt();
+	}
+
+	cur_mdesc = hp;
+
+	report_platform_properties();
+
+	cpus_setall(mask);
+	mdesc_fill_in_cpu_data(mask);
+}
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 16cc46a..6676b93 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -343,6 +343,15 @@
 
 	if (model && !strcmp(model, "SUNW,simba"))
 		return 1;
+
+	/* Treat PCI busses lacking ranges property just like
+	 * simba.
+	 */
+	if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
+		if (!of_find_property(np, "ranges", NULL))
+			return 1;
+	}
+
 	return 0;
 }
 
@@ -549,8 +558,6 @@
 
 static int __init use_1to1_mapping(struct device_node *pp)
 {
-	const char *model;
-
 	/* If this is on the PMU bus, don't try to translate it even
 	 * if a ranges property exists.
 	 */
@@ -567,9 +574,11 @@
 	if (!strcmp(pp->name, "dma"))
 		return 0;
 
-	/* Similarly for Simba PCI bridges.  */
-	model = of_get_property(pp, "model", NULL);
-	if (model && !strcmp(model, "SUNW,simba"))
+	/* Similarly for all PCI bridges, if we get this far
+	 * it lacks a ranges property, and this will include
+	 * cases like Simba.
+	 */
+	if (!strcmp(pp->type, "pci") || !strcmp(pp->type, "pciex"))
 		return 0;
 
 	return 1;
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index d4c077d..55ad1b8 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -306,6 +306,20 @@
 	pci_controller_scan(pci_controller_init);
 }
 
+static int ofpci_verbose;
+
+static int __init ofpci_debug(char *str)
+{
+	int val = 0;
+
+	get_option(&str, &val);
+	if (val)
+		ofpci_verbose = 1;
+	return 1;
+}
+
+__setup("ofpci_debug=", ofpci_debug);
+
 static unsigned long pci_parse_of_flags(u32 addr0)
 {
 	unsigned long flags = 0;
@@ -337,7 +351,9 @@
 	addrs = of_get_property(node, "assigned-addresses", &proplen);
 	if (!addrs)
 		return;
-	printk("    parse addresses (%d bytes) @ %p\n", proplen, addrs);
+	if (ofpci_verbose)
+		printk("    parse addresses (%d bytes) @ %p\n",
+		       proplen, addrs);
 	op_res = &op->resource[0];
 	for (; proplen >= 20; proplen -= 20, addrs += 5, op_res++) {
 		struct resource *res;
@@ -348,8 +364,9 @@
 		if (!flags)
 			continue;
 		i = addrs[0] & 0xff;
-		printk("  start: %lx, end: %lx, i: %x\n",
-		       op_res->start, op_res->end, i);
+		if (ofpci_verbose)
+			printk("  start: %lx, end: %lx, i: %x\n",
+			       op_res->start, op_res->end, i);
 
 		if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
 			res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
@@ -393,8 +410,9 @@
 	if (type == NULL)
 		type = "";
 
-	printk("    create device, devfn: %x, type: %s hostcontroller(%d)\n",
-	       devfn, type, host_controller);
+	if (ofpci_verbose)
+		printk("    create device, devfn: %x, type: %s\n",
+		       devfn, type);
 
 	dev->bus = bus;
 	dev->sysdata = node;
@@ -430,12 +448,14 @@
 		 */
 		pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
 		dev->class = class >> 8;
+		dev->revision = class & 0xff;
 
 		sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
 			dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
 	}
-	printk("    class: 0x%x device name: %s\n",
-	       dev->class, pci_name(dev));
+	if (ofpci_verbose)
+		printk("    class: 0x%x device name: %s\n",
+		       dev->class, pci_name(dev));
 
 	/* I have seen IDE devices which will not respond to
 	 * the bmdma simplex check reads if bus mastering is
@@ -469,7 +489,8 @@
 	}
 	pci_parse_of_addrs(sd->op, node, dev);
 
-	printk("    adding to system ...\n");
+	if (ofpci_verbose)
+		printk("    adding to system ...\n");
 
 	pci_device_add(dev, bus);
 
@@ -502,6 +523,89 @@
 	res->end += root->start;
 }
 
+/* For PCI bus devices which lack a 'ranges' property we interrogate
+ * the config space values to set the resources, just like the generic
+ * Linux PCI probing code does.
+ */
+static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
+					  struct pci_bus *bus,
+					  struct pci_pbm_info *pbm)
+{
+	struct resource *res;
+	u8 io_base_lo, io_limit_lo;
+	u16 mem_base_lo, mem_limit_lo;
+	unsigned long base, limit;
+
+	pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
+	pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
+	base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
+	limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
+
+	if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+		u16 io_base_hi, io_limit_hi;
+
+		pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
+		pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
+		base |= (io_base_hi << 16);
+		limit |= (io_limit_hi << 16);
+	}
+
+	res = bus->resource[0];
+	if (base <= limit) {
+		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
+		if (!res->start)
+			res->start = base;
+		if (!res->end)
+			res->end = limit + 0xfff;
+		pci_resource_adjust(res, &pbm->io_space);
+	}
+
+	pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
+	pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
+	base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
+	limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+
+	res = bus->resource[1];
+	if (base <= limit) {
+		res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
+			      IORESOURCE_MEM);
+		res->start = base;
+		res->end = limit + 0xfffff;
+		pci_resource_adjust(res, &pbm->mem_space);
+	}
+
+	pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
+	pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
+	base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
+	limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
+
+	if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+		u32 mem_base_hi, mem_limit_hi;
+
+		pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
+		pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
+
+		/*
+		 * Some bridges set the base > limit by default, and some
+		 * (broken) BIOSes do not initialize them.  If we find
+		 * this, just assume they are not being used.
+		 */
+		if (mem_base_hi <= mem_limit_hi) {
+			base |= ((long) mem_base_hi) << 32;
+			limit |= ((long) mem_limit_hi) << 32;
+		}
+	}
+
+	res = bus->resource[2];
+	if (base <= limit) {
+		res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
+			      IORESOURCE_MEM | IORESOURCE_PREFETCH);
+		res->start = base;
+		res->end = limit + 0xfffff;
+		pci_resource_adjust(res, &pbm->mem_space);
+	}
+}
+
 /* Cook up fake bus resources for SUNW,simba PCI bridges which lack
  * a proper 'ranges' property.
  */
@@ -547,7 +651,8 @@
 	unsigned int flags;
 	u64 size;
 
-	printk("of_scan_pci_bridge(%s)\n", node->full_name);
+	if (ofpci_verbose)
+		printk("of_scan_pci_bridge(%s)\n", node->full_name);
 
 	/* parse bus-range property */
 	busrange = of_get_property(node, "bus-range", &len);
@@ -560,13 +665,8 @@
 	simba = 0;
 	if (ranges == NULL) {
 		const char *model = of_get_property(node, "model", NULL);
-		if (model && !strcmp(model, "SUNW,simba")) {
+		if (model && !strcmp(model, "SUNW,simba"))
 			simba = 1;
-		} else {
-			printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
-			       node->full_name);
-			return;
-		}
 	}
 
 	bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
@@ -590,7 +690,10 @@
 	}
 	if (simba) {
 		apb_fake_ranges(dev, bus, pbm);
-		goto simba_cont;
+		goto after_ranges;
+	} else if (ranges == NULL) {
+		pci_cfg_fake_ranges(dev, bus, pbm);
+		goto after_ranges;
 	}
 	i = 1;
 	for (; len >= 32; len -= 32, ranges += 8) {
@@ -629,10 +732,11 @@
 		 */
 		pci_resource_adjust(res, root);
 	}
-simba_cont:
+after_ranges:
 	sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
 		bus->number);
-	printk("    bus name: %s\n", bus->name);
+	if (ofpci_verbose)
+		printk("    bus name: %s\n", bus->name);
 
 	pci_of_scan_bus(pbm, node, bus);
 }
@@ -646,12 +750,14 @@
 	int reglen, devfn;
 	struct pci_dev *dev;
 
-	printk("PCI: scan_bus[%s] bus no %d\n",
-	       node->full_name, bus->number);
+	if (ofpci_verbose)
+		printk("PCI: scan_bus[%s] bus no %d\n",
+		       node->full_name, bus->number);
 
 	child = NULL;
 	while ((child = of_get_next_child(node, child)) != NULL) {
-		printk("  * %s\n", child->full_name);
+		if (ofpci_verbose)
+			printk("  * %s\n", child->full_name);
 		reg = of_get_property(child, "reg", &reglen);
 		if (reg == NULL || reglen < 20)
 			continue;
@@ -661,7 +767,9 @@
 		dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
 		if (!dev)
 			continue;
-		printk("PCI: dev header type: %x\n", dev->hdr_type);
+		if (ofpci_verbose)
+			printk("PCI: dev header type: %x\n",
+			       dev->hdr_type);
 
 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index f974fef..4249214 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -291,8 +291,9 @@
 
 	for (i = 0; i < num_pbm_ranges; i++) {
 		const struct linux_prom_pci_ranges *pr = &pbm_ranges[i];
-		unsigned long a;
+		unsigned long a, size;
 		u32 parent_phys_hi, parent_phys_lo;
+		u32 size_hi, size_lo;
 		int type;
 
 		parent_phys_hi = pr->parent_phys_hi;
@@ -300,9 +301,14 @@
 		if (tlb_type == hypervisor)
 			parent_phys_hi &= 0x0fffffff;
 
+		size_hi = pr->size_hi;
+		size_lo = pr->size_lo;
+
 		type = (pr->child_phys_hi >> 24) & 0x3;
 		a = (((unsigned long)parent_phys_hi << 32UL) |
 		     ((unsigned long)parent_phys_lo  <<  0UL));
+		size = (((unsigned long)size_hi << 32UL) |
+			((unsigned long)size_lo  <<  0UL));
 
 		switch (type) {
 		case 0:
@@ -313,7 +319,7 @@
 		case 1:
 			/* 16-bit IO space, 16MB */
 			pbm->io_space.start = a;
-			pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL);
+			pbm->io_space.end = a + size - 1UL;
 			pbm->io_space.flags = IORESOURCE_IO;
 			saw_io = 1;
 			break;
@@ -321,7 +327,7 @@
 		case 2:
 			/* 32-bit MEM space, 2GB */
 			pbm->mem_space.start = a;
-			pbm->mem_space.end = a + (0x80000000UL - 1UL);
+			pbm->mem_space.end = a + size - 1UL;
 			pbm->mem_space.flags = IORESOURCE_MEM;
 			saw_mem = 1;
 			break;
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index e237779..22e1be5 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -636,13 +636,18 @@
 static void sabre_scan_bus(struct pci_pbm_info *pbm)
 {
 	static int once;
-	struct pci_bus *pbus;
 
 	/* The APB bridge speaks to the Sabre host PCI bridge
 	 * at 66Mhz, but the front side of APB runs at 33Mhz
 	 * for both segments.
+	 *
+	 * Hummingbird systems do not use APB, so they run
+	 * at 66MHZ.
 	 */
-	pbm->is_66mhz_capable = 0;
+	if (hummingbird_p)
+		pbm->is_66mhz_capable = 1;
+	else
+		pbm->is_66mhz_capable = 0;
 
 	/* This driver has not been verified to handle
 	 * multiple SABREs yet, so trap this.
@@ -656,13 +661,13 @@
 	}
 	once++;
 
-	pbus = pci_scan_one_pbm(pbm);
-	if (!pbus)
+	pbm->pci_bus = pci_scan_one_pbm(pbm);
+	if (!pbm->pci_bus)
 		return;
 
-	sabre_root_bus = pbus;
+	sabre_root_bus = pbm->pci_bus;
 
-	apb_init(pbus);
+	apb_init(pbm->pci_bus);
 
 	sabre_register_error_handlers(pbm);
 }
@@ -762,9 +767,10 @@
 			/* Of course, Sun has to encode things a thousand
 			 * different ways, inconsistently.
 			 */
-			cpu_find_by_instance(0, &dp, NULL);
-			if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
-				hummingbird_p = 1;
+			for_each_node_by_type(dp, "cpu") {
+				if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
+					hummingbird_p = 1;
+			}
 		}
 	}
 
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 044e8ec..6b3fe2c 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -12,6 +12,7 @@
 #include <linux/percpu.h>
 #include <linux/irq.h>
 #include <linux/msi.h>
+#include <linux/log2.h>
 
 #include <asm/iommu.h>
 #include <asm/irq.h>
@@ -26,6 +27,9 @@
 
 #include "pci_sun4v.h"
 
+static unsigned long vpci_major = 1;
+static unsigned long vpci_minor = 1;
+
 #define PGLIST_NENTS	(PAGE_SIZE / sizeof(u64))
 
 struct iommu_batch {
@@ -638,9 +642,8 @@
 {
 	struct iommu *iommu = pbm->iommu;
 	struct property *prop;
-	unsigned long num_tsb_entries, sz;
+	unsigned long num_tsb_entries, sz, tsbsize;
 	u32 vdma[2], dma_mask, dma_offset;
-	int tsbsize;
 
 	prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
 	if (prop) {
@@ -654,31 +657,15 @@
 		vdma[1] = 0x80000000;
 	}
 
-	dma_mask = vdma[0];
-	switch (vdma[1]) {
-		case 0x20000000:
-			dma_mask |= 0x1fffffff;
-			tsbsize = 64;
-			break;
-
-		case 0x40000000:
-			dma_mask |= 0x3fffffff;
-			tsbsize = 128;
-			break;
-
-		case 0x80000000:
-			dma_mask |= 0x7fffffff;
-			tsbsize = 256;
-			break;
-
-		default:
-			prom_printf("PCI-SUN4V: strange virtual-dma size.\n");
-			prom_halt();
+	if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) {
+		prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n",
+			    vdma[0], vdma[1]);
+		prom_halt();
 	};
 
-	tsbsize *= (8 * 1024);
-
-	num_tsb_entries = tsbsize / sizeof(iopte_t);
+	dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
+	num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
+	tsbsize = num_tsb_entries * sizeof(iopte_t);
 
 	dma_offset = vdma[0];
 
@@ -689,7 +676,7 @@
 	iommu->dma_addr_mask = dma_mask;
 
 	/* Allocate and initialize the free area map.  */
-	sz = num_tsb_entries / 8;
+	sz = (num_tsb_entries + 7) / 8;
 	sz = (sz + 7UL) & ~7UL;
 	iommu->arena.map = kzalloc(sz, GFP_KERNEL);
 	if (!iommu->arena.map) {
@@ -1178,6 +1165,7 @@
 
 void sun4v_pci_init(struct device_node *dp, char *model_name)
 {
+	static int hvapi_negotiated = 0;
 	struct pci_controller_info *p;
 	struct pci_pbm_info *pbm;
 	struct iommu *iommu;
@@ -1186,6 +1174,20 @@
 	u32 devhandle;
 	int i;
 
+	if (!hvapi_negotiated++) {
+		int err = sun4v_hvapi_register(HV_GRP_PCI,
+					       vpci_major,
+					       &vpci_minor);
+
+		if (err) {
+			prom_printf("SUN4V_PCI: Could not register hvapi, "
+				    "err=%d\n", err);
+			prom_halt();
+		}
+		printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n",
+		       vpci_major, vpci_minor);
+	}
+
 	prop = of_find_property(dp, "reg", NULL);
 	regs = prop->value;
 
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 699b24b..8dd4294 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -1,7 +1,6 @@
-/* $Id: power.c,v 1.10 2001/12/11 01:57:16 davem Exp $
- * power.c: Power management driver.
+/* power.c: Power management driver.
  *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/kernel.h>
@@ -19,6 +18,8 @@
 #include <asm/prom.h>
 #include <asm/of_device.h>
 #include <asm/io.h>
+#include <asm/power.h>
+#include <asm/sstate.h>
 
 #include <linux/unistd.h>
 
@@ -28,24 +29,26 @@
  */
 int scons_pwroff = 1; 
 
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
 static void __iomem *power_reg;
 
 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
 static int button_pressed;
 
-static irqreturn_t power_handler(int irq, void *dev_id)
+void wake_up_powerd(void)
 {
 	if (button_pressed == 0) {
 		button_pressed = 1;
 		wake_up(&powerd_wait);
 	}
+}
+
+static irqreturn_t power_handler(int irq, void *dev_id)
+{
+	wake_up_powerd();
 
 	/* FIXME: Check registers for status... */
 	return IRQ_HANDLED;
 }
-#endif /* CONFIG_PCI */
 
 extern void machine_halt(void);
 extern void machine_alt_power_off(void);
@@ -53,20 +56,20 @@
 
 void machine_power_off(void)
 {
+	sstate_poweroff();
 	if (!serial_console || scons_pwroff) {
-#ifdef CONFIG_PCI
 		if (power_reg) {
 			/* Both register bits seem to have the
 			 * same effect, so until I figure out
 			 * what the difference is...
 			 */
 			writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg);
-		} else
-#endif /* CONFIG_PCI */
+		} else {
 			if (poweroff_method != NULL) {
 				poweroff_method();
 				/* not reached */
 			}
+		}
 	}
 	machine_halt();
 }
@@ -74,7 +77,6 @@
 void (*pm_power_off)(void) = machine_power_off;
 EXPORT_SYMBOL(pm_power_off);
 
-#ifdef CONFIG_PCI
 static int powerd(void *__unused)
 {
 	static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
@@ -84,7 +86,7 @@
 	daemonize("powerd");
 
 	add_wait_queue(&powerd_wait, &wait);
-again:
+
 	for (;;) {
 		set_task_state(current, TASK_INTERRUPTIBLE);
 		if (button_pressed)
@@ -98,16 +100,28 @@
 	/* Ok, down we go... */
 	button_pressed = 0;
 	if (kernel_execve("/sbin/shutdown", argv, envp) < 0) {
-		printk("powerd: shutdown execution failed\n");
-		add_wait_queue(&powerd_wait, &wait);
-		goto again;
+		printk(KERN_ERR "powerd: shutdown execution failed\n");
+		machine_power_off();
 	}
 	return 0;
 }
 
+int start_powerd(void)
+{
+	int err;
+
+	err = kernel_thread(powerd, NULL, CLONE_FS);
+	if (err < 0)
+		printk(KERN_ERR "power: Failed to start power daemon.\n");
+	else
+		printk(KERN_INFO "power: powerd running.\n");
+
+	return err;
+}
+
 static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
 {
-	if (irq == PCI_IRQ_NONE)
+	if (irq == 0xffffffff)
 		return 0;
 	if (!of_find_property(dp, "button", NULL))
 		return 0;
@@ -128,17 +142,14 @@
 	poweroff_method = machine_halt;  /* able to use the standard halt */
 
 	if (has_button_interrupt(irq, op->node)) {
-		if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
-			printk("Failed to start power daemon.\n");
+		if (start_powerd() < 0)
 			return 0;
-		}
-		printk("powerd running.\n");
 
 		if (request_irq(irq,
 				power_handler, 0, "power", NULL) < 0)
-			printk("power: Error, cannot register IRQ handler.\n");
+			printk(KERN_ERR "power: Cannot setup IRQ handler.\n");
 	} else {
-		printk("not using powerd.\n");
+		printk(KERN_INFO "power: Not using powerd.\n");
 	}
 
 	return 0;
@@ -162,4 +173,3 @@
 	of_register_driver(&power_driver, &of_bus_type);
 	return;
 }
-#endif /* CONFIG_PCI */
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 952762b..9355750 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -29,6 +29,7 @@
 #include <linux/compat.h>
 #include <linux/tick.h>
 #include <linux/init.h>
+#include <linux/cpu.h>
 
 #include <asm/oplib.h>
 #include <asm/uaccess.h>
@@ -45,10 +46,11 @@
 #include <asm/mmu_context.h>
 #include <asm/unistd.h>
 #include <asm/hypervisor.h>
+#include <asm/sstate.h>
 
 /* #define VERBOSE_SHOWREGS */
 
-static void sparc64_yield(void)
+static void sparc64_yield(int cpu)
 {
 	if (tlb_type != hypervisor)
 		return;
@@ -56,7 +58,7 @@
 	clear_thread_flag(TIF_POLLING_NRFLAG);
 	smp_mb__after_clear_bit();
 
-	while (!need_resched()) {
+	while (!need_resched() && !cpu_is_offline(cpu)) {
 		unsigned long pstate;
 
 		/* Disable interrupts. */
@@ -67,7 +69,7 @@
 			: "=&r" (pstate)
 			: "i" (PSTATE_IE));
 
-		if (!need_resched())
+		if (!need_resched() && !cpu_is_offline(cpu))
 			sun4v_cpu_yield();
 
 		/* Re-enable interrupts. */
@@ -85,15 +87,25 @@
 /* The idle loop on sparc64. */
 void cpu_idle(void)
 {
+	int cpu = smp_processor_id();
+
 	set_thread_flag(TIF_POLLING_NRFLAG);
 
 	while(1) {
 		tick_nohz_stop_sched_tick();
-		while (!need_resched())
-			sparc64_yield();
+
+		while (!need_resched() && !cpu_is_offline(cpu))
+			sparc64_yield(cpu);
+
 		tick_nohz_restart_sched_tick();
 
 		preempt_enable_no_resched();
+
+#ifdef CONFIG_HOTPLUG_CPU
+		if (cpu_is_offline(cpu))
+			cpu_play_dead();
+#endif
+
 		schedule();
 		preempt_disable();
 	}
@@ -106,6 +118,7 @@
 
 void machine_halt(void)
 {
+	sstate_halt();
 	if (!serial_console && prom_palette)
 		prom_palette (1);
 	if (prom_keyboard)
@@ -116,6 +129,7 @@
 
 void machine_alt_power_off(void)
 {
+	sstate_poweroff();
 	if (!serial_console && prom_palette)
 		prom_palette(1);
 	if (prom_keyboard)
@@ -128,6 +142,7 @@
 {
 	char *p;
 	
+	sstate_reboot();
 	p = strchr (reboot_command, '\n');
 	if (p) *p = 0;
 	if (!serial_console && prom_palette)
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 02830e4..5d22030 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -28,6 +28,7 @@
 #include <asm/irq.h>
 #include <asm/asi.h>
 #include <asm/upa.h>
+#include <asm/smp.h>
 
 static struct device_node *allnodes;
 
@@ -932,29 +933,29 @@
  * This should conform to both Sunfire/Wildfire server and Fusion
  * desktop designs.
  */
-#define SYSIO_IMAP_SLOT0	0x2c04UL
-#define SYSIO_IMAP_SLOT1	0x2c0cUL
-#define SYSIO_IMAP_SLOT2	0x2c14UL
-#define SYSIO_IMAP_SLOT3	0x2c1cUL
-#define SYSIO_IMAP_SCSI		0x3004UL
-#define SYSIO_IMAP_ETH		0x300cUL
-#define SYSIO_IMAP_BPP		0x3014UL
-#define SYSIO_IMAP_AUDIO	0x301cUL
-#define SYSIO_IMAP_PFAIL	0x3024UL
-#define SYSIO_IMAP_KMS		0x302cUL
-#define SYSIO_IMAP_FLPY		0x3034UL
-#define SYSIO_IMAP_SHW		0x303cUL
-#define SYSIO_IMAP_KBD		0x3044UL
-#define SYSIO_IMAP_MS		0x304cUL
-#define SYSIO_IMAP_SER		0x3054UL
-#define SYSIO_IMAP_TIM0		0x3064UL
-#define SYSIO_IMAP_TIM1		0x306cUL
-#define SYSIO_IMAP_UE		0x3074UL
-#define SYSIO_IMAP_CE		0x307cUL
-#define SYSIO_IMAP_SBERR	0x3084UL
-#define SYSIO_IMAP_PMGMT	0x308cUL
-#define SYSIO_IMAP_GFX		0x3094UL
-#define SYSIO_IMAP_EUPA		0x309cUL
+#define SYSIO_IMAP_SLOT0	0x2c00UL
+#define SYSIO_IMAP_SLOT1	0x2c08UL
+#define SYSIO_IMAP_SLOT2	0x2c10UL
+#define SYSIO_IMAP_SLOT3	0x2c18UL
+#define SYSIO_IMAP_SCSI		0x3000UL
+#define SYSIO_IMAP_ETH		0x3008UL
+#define SYSIO_IMAP_BPP		0x3010UL
+#define SYSIO_IMAP_AUDIO	0x3018UL
+#define SYSIO_IMAP_PFAIL	0x3020UL
+#define SYSIO_IMAP_KMS		0x3028UL
+#define SYSIO_IMAP_FLPY		0x3030UL
+#define SYSIO_IMAP_SHW		0x3038UL
+#define SYSIO_IMAP_KBD		0x3040UL
+#define SYSIO_IMAP_MS		0x3048UL
+#define SYSIO_IMAP_SER		0x3050UL
+#define SYSIO_IMAP_TIM0		0x3060UL
+#define SYSIO_IMAP_TIM1		0x3068UL
+#define SYSIO_IMAP_UE		0x3070UL
+#define SYSIO_IMAP_CE		0x3078UL
+#define SYSIO_IMAP_SBERR	0x3080UL
+#define SYSIO_IMAP_PMGMT	0x3088UL
+#define SYSIO_IMAP_GFX		0x3090UL
+#define SYSIO_IMAP_EUPA		0x3098UL
 
 #define bogon     ((unsigned long) -1)
 static unsigned long sysio_irq_offsets[] = {
@@ -1005,10 +1006,10 @@
  * Interrupt Clear register pointer, SYSIO specific version.
  */
 #define SYSIO_ICLR_UNUSED0	0x3400UL
-#define SYSIO_ICLR_SLOT0	0x340cUL
-#define SYSIO_ICLR_SLOT1	0x344cUL
-#define SYSIO_ICLR_SLOT2	0x348cUL
-#define SYSIO_ICLR_SLOT3	0x34ccUL
+#define SYSIO_ICLR_SLOT0	0x3408UL
+#define SYSIO_ICLR_SLOT1	0x3448UL
+#define SYSIO_ICLR_SLOT2	0x3488UL
+#define SYSIO_ICLR_SLOT3	0x34c8UL
 static unsigned long sysio_imap_to_iclr(unsigned long imap)
 {
 	unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
@@ -1665,6 +1666,155 @@
 	return ret;
 }
 
+static const char *get_mid_prop(void)
+{
+	return (tlb_type == spitfire ? "upa-portid" : "portid");
+}
+
+struct device_node *of_find_node_by_cpuid(int cpuid)
+{
+	struct device_node *dp;
+	const char *mid_prop = get_mid_prop();
+
+	for_each_node_by_type(dp, "cpu") {
+		int id = of_getintprop_default(dp, mid_prop, -1);
+		const char *this_mid_prop = mid_prop;
+
+		if (id < 0) {
+			this_mid_prop = "cpuid";
+			id = of_getintprop_default(dp, this_mid_prop, -1);
+		}
+
+		if (id < 0) {
+			prom_printf("OF: Serious problem, cpu lacks "
+				    "%s property", this_mid_prop);
+			prom_halt();
+		}
+		if (cpuid == id)
+			return dp;
+	}
+	return NULL;
+}
+
+static void __init of_fill_in_cpu_data(void)
+{
+	struct device_node *dp;
+	const char *mid_prop = get_mid_prop();
+
+	ncpus_probed = 0;
+	for_each_node_by_type(dp, "cpu") {
+		int cpuid = of_getintprop_default(dp, mid_prop, -1);
+		const char *this_mid_prop = mid_prop;
+		struct device_node *portid_parent;
+		int portid = -1;
+
+		portid_parent = NULL;
+		if (cpuid < 0) {
+			this_mid_prop = "cpuid";
+			cpuid = of_getintprop_default(dp, this_mid_prop, -1);
+			if (cpuid >= 0) {
+				int limit = 2;
+
+				portid_parent = dp;
+				while (limit--) {
+					portid_parent = portid_parent->parent;
+					if (!portid_parent)
+						break;
+					portid = of_getintprop_default(portid_parent,
+								       "portid", -1);
+					if (portid >= 0)
+						break;
+				}
+			}
+		}
+
+		if (cpuid < 0) {
+			prom_printf("OF: Serious problem, cpu lacks "
+				    "%s property", this_mid_prop);
+			prom_halt();
+		}
+
+		ncpus_probed++;
+
+#ifdef CONFIG_SMP
+		if (cpuid >= NR_CPUS)
+			continue;
+#else
+		/* On uniprocessor we only want the values for the
+		 * real physical cpu the kernel booted onto, however
+		 * cpu_data() only has one entry at index 0.
+		 */
+		if (cpuid != real_hard_smp_processor_id())
+			continue;
+		cpuid = 0;
+#endif
+
+		cpu_data(cpuid).clock_tick =
+			of_getintprop_default(dp, "clock-frequency", 0);
+
+		if (portid_parent) {
+			cpu_data(cpuid).dcache_size =
+				of_getintprop_default(dp, "l1-dcache-size",
+						      16 * 1024);
+			cpu_data(cpuid).dcache_line_size =
+				of_getintprop_default(dp, "l1-dcache-line-size",
+						      32);
+			cpu_data(cpuid).icache_size =
+				of_getintprop_default(dp, "l1-icache-size",
+						      8 * 1024);
+			cpu_data(cpuid).icache_line_size =
+				of_getintprop_default(dp, "l1-icache-line-size",
+						      32);
+			cpu_data(cpuid).ecache_size =
+				of_getintprop_default(dp, "l2-cache-size", 0);
+			cpu_data(cpuid).ecache_line_size =
+				of_getintprop_default(dp, "l2-cache-line-size", 0);
+			if (!cpu_data(cpuid).ecache_size ||
+			    !cpu_data(cpuid).ecache_line_size) {
+				cpu_data(cpuid).ecache_size =
+					of_getintprop_default(portid_parent,
+							      "l2-cache-size",
+							      (4 * 1024 * 1024));
+				cpu_data(cpuid).ecache_line_size =
+					of_getintprop_default(portid_parent,
+							      "l2-cache-line-size", 64);
+			}
+
+			cpu_data(cpuid).core_id = portid + 1;
+			cpu_data(cpuid).proc_id = portid;
+#ifdef CONFIG_SMP
+			sparc64_multi_core = 1;
+#endif
+		} else {
+			cpu_data(cpuid).dcache_size =
+				of_getintprop_default(dp, "dcache-size", 16 * 1024);
+			cpu_data(cpuid).dcache_line_size =
+				of_getintprop_default(dp, "dcache-line-size", 32);
+
+			cpu_data(cpuid).icache_size =
+				of_getintprop_default(dp, "icache-size", 16 * 1024);
+			cpu_data(cpuid).icache_line_size =
+				of_getintprop_default(dp, "icache-line-size", 32);
+
+			cpu_data(cpuid).ecache_size =
+				of_getintprop_default(dp, "ecache-size",
+						      (4 * 1024 * 1024));
+			cpu_data(cpuid).ecache_line_size =
+				of_getintprop_default(dp, "ecache-line-size", 64);
+
+			cpu_data(cpuid).core_id = 0;
+			cpu_data(cpuid).proc_id = -1;
+		}
+
+#ifdef CONFIG_SMP
+		cpu_set(cpuid, cpu_present_map);
+		cpu_set(cpuid, cpu_possible_map);
+#endif
+	}
+
+	smp_fill_in_sib_core_maps();
+}
+
 void __init prom_build_devicetree(void)
 {
 	struct device_node **nextp;
@@ -1679,4 +1829,7 @@
 				     &nextp);
 	printk("PROM: Built device tree with %u bytes of memory.\n",
 	       prom_early_allocated);
+
+	if (tlb_type != hypervisor)
+		of_fill_in_cpu_data();
 }
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 91f6e2a..a1fd9bc 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -629,29 +629,29 @@
  * This should conform to both Sunfire/Wildfire server and Fusion
  * desktop designs.
  */
-#define SYSIO_IMAP_SLOT0	0x2c04UL
-#define SYSIO_IMAP_SLOT1	0x2c0cUL
-#define SYSIO_IMAP_SLOT2	0x2c14UL
-#define SYSIO_IMAP_SLOT3	0x2c1cUL
-#define SYSIO_IMAP_SCSI		0x3004UL
-#define SYSIO_IMAP_ETH		0x300cUL
-#define SYSIO_IMAP_BPP		0x3014UL
-#define SYSIO_IMAP_AUDIO	0x301cUL
-#define SYSIO_IMAP_PFAIL	0x3024UL
-#define SYSIO_IMAP_KMS		0x302cUL
-#define SYSIO_IMAP_FLPY		0x3034UL
-#define SYSIO_IMAP_SHW		0x303cUL
-#define SYSIO_IMAP_KBD		0x3044UL
-#define SYSIO_IMAP_MS		0x304cUL
-#define SYSIO_IMAP_SER		0x3054UL
-#define SYSIO_IMAP_TIM0		0x3064UL
-#define SYSIO_IMAP_TIM1		0x306cUL
-#define SYSIO_IMAP_UE		0x3074UL
-#define SYSIO_IMAP_CE		0x307cUL
-#define SYSIO_IMAP_SBERR	0x3084UL
-#define SYSIO_IMAP_PMGMT	0x308cUL
-#define SYSIO_IMAP_GFX		0x3094UL
-#define SYSIO_IMAP_EUPA		0x309cUL
+#define SYSIO_IMAP_SLOT0	0x2c00UL
+#define SYSIO_IMAP_SLOT1	0x2c08UL
+#define SYSIO_IMAP_SLOT2	0x2c10UL
+#define SYSIO_IMAP_SLOT3	0x2c18UL
+#define SYSIO_IMAP_SCSI		0x3000UL
+#define SYSIO_IMAP_ETH		0x3008UL
+#define SYSIO_IMAP_BPP		0x3010UL
+#define SYSIO_IMAP_AUDIO	0x3018UL
+#define SYSIO_IMAP_PFAIL	0x3020UL
+#define SYSIO_IMAP_KMS		0x3028UL
+#define SYSIO_IMAP_FLPY		0x3030UL
+#define SYSIO_IMAP_SHW		0x3038UL
+#define SYSIO_IMAP_KBD		0x3040UL
+#define SYSIO_IMAP_MS		0x3048UL
+#define SYSIO_IMAP_SER		0x3050UL
+#define SYSIO_IMAP_TIM0		0x3060UL
+#define SYSIO_IMAP_TIM1		0x3068UL
+#define SYSIO_IMAP_UE		0x3070UL
+#define SYSIO_IMAP_CE		0x3078UL
+#define SYSIO_IMAP_SBERR	0x3080UL
+#define SYSIO_IMAP_PMGMT	0x3088UL
+#define SYSIO_IMAP_GFX		0x3090UL
+#define SYSIO_IMAP_EUPA		0x3098UL
 
 #define bogon     ((unsigned long) -1)
 static unsigned long sysio_irq_offsets[] = {
@@ -700,10 +700,10 @@
  * Interrupt Clear register pointer, SYSIO specific version.
  */
 #define SYSIO_ICLR_UNUSED0	0x3400UL
-#define SYSIO_ICLR_SLOT0	0x340cUL
-#define SYSIO_ICLR_SLOT1	0x344cUL
-#define SYSIO_ICLR_SLOT2	0x348cUL
-#define SYSIO_ICLR_SLOT3	0x34ccUL
+#define SYSIO_ICLR_SLOT0	0x3408UL
+#define SYSIO_ICLR_SLOT1	0x3448UL
+#define SYSIO_ICLR_SLOT2	0x3488UL
+#define SYSIO_ICLR_SLOT3	0x34c8UL
 static unsigned long sysio_imap_to_iclr(unsigned long imap)
 {
 	unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index dea9c3c..aafde3d 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -46,11 +46,17 @@
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/mmu.h>
+#include <asm/ns87303.h>
 
 #ifdef CONFIG_IP_PNP
 #include <net/ipconfig.h>
 #endif
 
+/* Used to synchronize accesses to NatSemi SUPER I/O chip configure
+ * operations in asm/ns87303.h
+ */
+DEFINE_SPINLOCK(ns87303_lock);
+
 struct screen_info screen_info = {
 	0, 0,			/* orig-x, orig-y */
 	0,			/* unused */
@@ -370,8 +376,6 @@
 	init_cur_cpu_trap(current_thread_info());
 
 	paging_init();
-
-	smp_setup_cpu_possible_map();
 }
 
 static int __init set_preferred_console(void)
@@ -424,7 +428,7 @@
 unsigned int dcache_parity_tl1_occurred;
 unsigned int icache_parity_tl1_occurred;
 
-static int ncpus_probed;
+int ncpus_probed;
 
 static int show_cpuinfo(struct seq_file *m, void *__unused)
 {
@@ -438,7 +442,6 @@
 		   "D$ parity tl1\t: %u\n"
 		   "I$ parity tl1\t: %u\n"
 #ifndef CONFIG_SMP
-		   "Cpu0Bogo\t: %lu.%02lu\n"
 		   "Cpu0ClkTck\t: %016lx\n"
 #endif
 		   ,
@@ -453,9 +456,7 @@
 		   dcache_parity_tl1_occurred,
 		   icache_parity_tl1_occurred
 #ifndef CONFIG_SMP
-		   , cpu_data(0).udelay_val/(500000/HZ),
-		   (cpu_data(0).udelay_val/(5000/HZ)) % 100,
-		   cpu_data(0).clock_tick
+		   , cpu_data(0).clock_tick
 #endif
 		);
 #ifdef CONFIG_SMP
@@ -509,30 +510,3 @@
 
 int serial_console = -1;
 int stop_a_enabled = 1;
-
-static int __init topology_init(void)
-{
-	int i, err;
-
-	err = -ENOMEM;
-
-	/* Count the number of physically present processors in
-	 * the machine, even on uniprocessor, so that /proc/cpuinfo
-	 * output is consistent with 2.4.x
-	 */
-	ncpus_probed = 0;
-	while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
-		ncpus_probed++;
-
-	for_each_possible_cpu(i) {
-		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
-		if (p) {
-			register_cpu(p, i);
-			err = 0;
-		}
-	}
-
-	return err;
-}
-
-subsys_initcall(topology_init);
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 203e873..fb13775 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -289,9 +289,7 @@
 	struct rt_signal_frame __user *sf;
 	unsigned long tpc, tnpc, tstate;
 	__siginfo_fpu_t __user *fpu_save;
-	mm_segment_t old_fs;
 	sigset_t set;
-	stack_t st;
 	int err;
 
 	/* Always make any pending restarted system calls return -EINTR */
@@ -327,20 +325,13 @@
 		err |= restore_fpu_state(regs, &sf->fpu_state);
 
 	err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
-	err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t));
-	
+	err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
+
 	if (err)
 		goto segv;
-		
+
 	regs->tpc = tpc;
 	regs->tnpc = tnpc;
-	
-	/* It is more difficult to avoid calling this function than to
-	   call it and ignore errors.  */
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf);
-	set_fs(old_fs);
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	spin_lock_irq(&current->sighand->siglock);
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 24fdf1d..b448d33 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1,6 +1,6 @@
 /* smp.c: Sparc64 SMP support.
  *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/module.h>
@@ -28,6 +28,8 @@
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 #include <asm/cpudata.h>
+#include <asm/hvtramp.h>
+#include <asm/io.h>
 
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
@@ -40,18 +42,27 @@
 #include <asm/tlb.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
+#include <asm/mdesc.h>
+#include <asm/ldc.h>
+#include <asm/hypervisor.h>
 
 extern void calibrate_delay(void);
 
-/* Please don't make this stuff initdata!!!  --DaveM */
-unsigned char boot_cpu_id;
+int sparc64_multi_core __read_mostly;
 
+cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE;
 cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
-cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE;
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly =
 	{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
+	{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+
+EXPORT_SYMBOL(cpu_possible_map);
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_sibling_map);
+EXPORT_SYMBOL(cpu_core_map);
+
 static cpumask_t smp_commenced_mask;
-static cpumask_t cpu_callout_map;
 
 void smp_info(struct seq_file *m)
 {
@@ -68,65 +79,17 @@
 	
 	for_each_online_cpu(i)
 		seq_printf(m,
-			   "Cpu%dBogo\t: %lu.%02lu\n"
 			   "Cpu%dClkTck\t: %016lx\n",
-			   i, cpu_data(i).udelay_val / (500000/HZ),
-			   (cpu_data(i).udelay_val / (5000/HZ)) % 100,
 			   i, cpu_data(i).clock_tick);
 }
 
-void __init smp_store_cpu_info(int id)
-{
-	struct device_node *dp;
-	int def;
-
-	cpu_data(id).udelay_val			= loops_per_jiffy;
-
-	cpu_find_by_mid(id, &dp);
-	cpu_data(id).clock_tick =
-		of_getintprop_default(dp, "clock-frequency", 0);
-
-	def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024));
-	cpu_data(id).dcache_size =
-		of_getintprop_default(dp, "dcache-size", def);
-
-	def = 32;
-	cpu_data(id).dcache_line_size =
-		of_getintprop_default(dp, "dcache-line-size", def);
-
-	def = 16 * 1024;
-	cpu_data(id).icache_size =
-		of_getintprop_default(dp, "icache-size", def);
-
-	def = 32;
-	cpu_data(id).icache_line_size =
-		of_getintprop_default(dp, "icache-line-size", def);
-
-	def = ((tlb_type == hypervisor) ?
-	       (3 * 1024 * 1024) :
-	       (4 * 1024 * 1024));
-	cpu_data(id).ecache_size =
-		of_getintprop_default(dp, "ecache-size", def);
-
-	def = 64;
-	cpu_data(id).ecache_line_size =
-		of_getintprop_default(dp, "ecache-line-size", def);
-
-	printk("CPU[%d]: Caches "
-	       "D[sz(%d):line_sz(%d)] "
-	       "I[sz(%d):line_sz(%d)] "
-	       "E[sz(%d):line_sz(%d)]\n",
-	       id,
-	       cpu_data(id).dcache_size, cpu_data(id).dcache_line_size,
-	       cpu_data(id).icache_size, cpu_data(id).icache_line_size,
-	       cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
-}
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
 
 extern void setup_sparc64_timer(void);
 
 static volatile unsigned long callin_flag = 0;
 
-void __init smp_callin(void)
+void __devinit smp_callin(void)
 {
 	int cpuid = hard_smp_processor_id();
 
@@ -144,8 +107,6 @@
 
 	local_irq_enable();
 
-	calibrate_delay();
-	smp_store_cpu_info(cpuid);
 	callin_flag = 1;
 	__asm__ __volatile__("membar #Sync\n\t"
 			     "flush  %%g6" : : : "memory");
@@ -162,7 +123,9 @@
 	while (!cpu_isset(cpuid, smp_commenced_mask))
 		rmb();
 
+	spin_lock(&call_lock);
 	cpu_set(cpuid, cpu_online_map);
+	spin_unlock(&call_lock);
 
 	/* idle thread is expected to have preempt disabled */
 	preempt_disable();
@@ -310,6 +273,67 @@
 	spin_unlock_irqrestore(&itc_sync_lock, flags);
 }
 
+#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
+/* XXX Put this in some common place. XXX */
+static unsigned long kimage_addr_to_ra(void *p)
+{
+	unsigned long val = (unsigned long) p;
+
+	return kern_base + (val - KERNBASE);
+}
+
+static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
+{
+	extern unsigned long sparc64_ttable_tl0;
+	extern unsigned long kern_locked_tte_data;
+	extern int bigkernel;
+	struct hvtramp_descr *hdesc;
+	unsigned long trampoline_ra;
+	struct trap_per_cpu *tb;
+	u64 tte_vaddr, tte_data;
+	unsigned long hv_err;
+
+	hdesc = kzalloc(sizeof(*hdesc), GFP_KERNEL);
+	if (!hdesc) {
+		printk(KERN_ERR "ldom_startcpu_cpuid: Cannot allocate "
+		       "hvtramp_descr.\n");
+		return;
+	}
+
+	hdesc->cpu = cpu;
+	hdesc->num_mappings = (bigkernel ? 2 : 1);
+
+	tb = &trap_block[cpu];
+	tb->hdesc = hdesc;
+
+	hdesc->fault_info_va = (unsigned long) &tb->fault_info;
+	hdesc->fault_info_pa = kimage_addr_to_ra(&tb->fault_info);
+
+	hdesc->thread_reg = thread_reg;
+
+	tte_vaddr = (unsigned long) KERNBASE;
+	tte_data = kern_locked_tte_data;
+
+	hdesc->maps[0].vaddr = tte_vaddr;
+	hdesc->maps[0].tte   = tte_data;
+	if (bigkernel) {
+		tte_vaddr += 0x400000;
+		tte_data  += 0x400000;
+		hdesc->maps[1].vaddr = tte_vaddr;
+		hdesc->maps[1].tte   = tte_data;
+	}
+
+	trampoline_ra = kimage_addr_to_ra(hv_cpu_startup);
+
+	hv_err = sun4v_cpu_start(cpu, trampoline_ra,
+				 kimage_addr_to_ra(&sparc64_ttable_tl0),
+				 __pa(hdesc));
+	if (hv_err)
+		printk(KERN_ERR "ldom_startcpu_cpuid: sun4v_cpu_start() "
+		       "gives error %lu\n", hv_err);
+}
+#endif
+
 extern void sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int load);
 
 extern unsigned long sparc64_cpu_startup;
@@ -322,6 +346,7 @@
 
 static int __devinit smp_boot_one_cpu(unsigned int cpu)
 {
+	struct trap_per_cpu *tb = &trap_block[cpu];
 	unsigned long entry =
 		(unsigned long)(&sparc64_cpu_startup);
 	unsigned long cookie =
@@ -332,21 +357,25 @@
 	p = fork_idle(cpu);
 	callin_flag = 0;
 	cpu_new_thread = task_thread_info(p);
-	cpu_set(cpu, cpu_callout_map);
 
 	if (tlb_type == hypervisor) {
 		/* Alloc the mondo queues, cpu will load them.  */
 		sun4v_init_mondo_queues(0, cpu, 1, 0);
 
-		prom_startcpu_cpuid(cpu, entry, cookie);
+#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
+		if (ldom_domaining_enabled)
+			ldom_startcpu_cpuid(cpu,
+					    (unsigned long) cpu_new_thread);
+		else
+#endif
+			prom_startcpu_cpuid(cpu, entry, cookie);
 	} else {
-		struct device_node *dp;
+		struct device_node *dp = of_find_node_by_cpuid(cpu);
 
-		cpu_find_by_mid(cpu, &dp);
 		prom_startcpu(dp->node, entry, cookie);
 	}
 
-	for (timeout = 0; timeout < 5000000; timeout++) {
+	for (timeout = 0; timeout < 50000; timeout++) {
 		if (callin_flag)
 			break;
 		udelay(100);
@@ -356,11 +385,15 @@
 		ret = 0;
 	} else {
 		printk("Processor %d is stuck.\n", cpu);
-		cpu_clear(cpu, cpu_callout_map);
 		ret = -ENODEV;
 	}
 	cpu_new_thread = NULL;
 
+	if (tb->hdesc) {
+		kfree(tb->hdesc);
+		tb->hdesc = NULL;
+	}
+
 	return ret;
 }
 
@@ -447,7 +480,7 @@
 static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
 {
 	u64 pstate, ver;
-	int nack_busy_id, is_jbus;
+	int nack_busy_id, is_jbus, need_more;
 
 	if (cpus_empty(mask))
 		return;
@@ -463,6 +496,7 @@
 	__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
 
 retry:
+	need_more = 0;
 	__asm__ __volatile__("wrpr %0, %1, %%pstate\n\t"
 			     : : "r" (pstate), "i" (PSTATE_IE));
 
@@ -491,6 +525,10 @@
 				: /* no outputs */
 				: "r" (target), "i" (ASI_INTR_W));
 			nack_busy_id++;
+			if (nack_busy_id == 32) {
+				need_more = 1;
+				break;
+			}
 		}
 	}
 
@@ -507,6 +545,16 @@
 			if (dispatch_stat == 0UL) {
 				__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
 						     : : "r" (pstate));
+				if (unlikely(need_more)) {
+					int i, cnt = 0;
+					for_each_cpu_mask(i, mask) {
+						cpu_clear(i, mask);
+						cnt++;
+						if (cnt == 32)
+							break;
+					}
+					goto retry;
+				}
 				return;
 			}
 			if (!--stuck)
@@ -544,6 +592,8 @@
 				if ((dispatch_stat & check_mask) == 0)
 					cpu_clear(i, mask);
 				this_busy_nack += 2;
+				if (this_busy_nack == 64)
+					break;
 			}
 
 			goto retry;
@@ -746,7 +796,6 @@
 	int wait;
 };
 
-static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
 static struct call_data_struct *call_data;
 
 extern unsigned long xcall_call_function;
@@ -1178,112 +1227,57 @@
 	preempt_enable();
 }
 
-void __init smp_tick_init(void)
-{
-	boot_cpu_id = hard_smp_processor_id();
-}
-
 /* /proc/profile writes can call this, don't __init it please. */
 int setup_profiling_timer(unsigned int multiplier)
 {
 	return -EINVAL;
 }
 
-static void __init smp_tune_scheduling(void)
-{
-	struct device_node *dp;
-	int instance;
-	unsigned int def, smallest = ~0U;
-
-	def = ((tlb_type == hypervisor) ?
-	       (3 * 1024 * 1024) :
-	       (4 * 1024 * 1024));
-
-	instance = 0;
-	while (!cpu_find_by_instance(instance, &dp, NULL)) {
-		unsigned int val;
-
-		val = of_getintprop_default(dp, "ecache-size", def);
-		if (val < smallest)
-			smallest = val;
-
-		instance++;
-	}
-
-	/* Any value less than 256K is nonsense.  */
-	if (smallest < (256U * 1024U))
-		smallest = 256 * 1024;
-
-	max_cache_size = smallest;
-
-	if (smallest < 1U * 1024U * 1024U)
-		printk(KERN_INFO "Using max_cache_size of %uKB\n",
-		       smallest / 1024U);
-	else
-		printk(KERN_INFO "Using max_cache_size of %uMB\n",
-		       smallest / 1024U / 1024U);
-}
-
-/* Constrain the number of cpus to max_cpus.  */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	if (num_possible_cpus() > max_cpus) {
-		int instance, mid;
-
-		instance = 0;
-		while (!cpu_find_by_instance(instance, NULL, &mid)) {
-			if (mid != boot_cpu_id) {
-				cpu_clear(mid, phys_cpu_present_map);
-				cpu_clear(mid, cpu_present_map);
-				if (num_possible_cpus() <= max_cpus)
-					break;
-			}
-			instance++;
-		}
-	}
-
-	for_each_possible_cpu(i) {
-		if (tlb_type == hypervisor) {
-			int j;
-
-			/* XXX get this mapping from machine description */
-			for_each_possible_cpu(j) {
-				if ((j >> 2) == (i >> 2))
-					cpu_set(j, cpu_sibling_map[i]);
-			}
-		} else {
-			cpu_set(i, cpu_sibling_map[i]);
-		}
-	}
-
-	smp_store_cpu_info(boot_cpu_id);
-	smp_tune_scheduling();
-}
-
-/* Set this up early so that things like the scheduler can init
- * properly.  We use the same cpu mask for both the present and
- * possible cpu map.
- */
-void __init smp_setup_cpu_possible_map(void)
-{
-	int instance, mid;
-
-	instance = 0;
-	while (!cpu_find_by_instance(instance, NULL, &mid)) {
-		if (mid < NR_CPUS) {
-			cpu_set(mid, phys_cpu_present_map);
-			cpu_set(mid, cpu_present_map);
-		}
-		instance++;
-	}
 }
 
 void __devinit smp_prepare_boot_cpu(void)
 {
 }
 
+void __devinit smp_fill_in_sib_core_maps(void)
+{
+	unsigned int i;
+
+	for_each_present_cpu(i) {
+		unsigned int j;
+
+		cpus_clear(cpu_core_map[i]);
+		if (cpu_data(i).core_id == 0) {
+			cpu_set(i, cpu_core_map[i]);
+			continue;
+		}
+
+		for_each_present_cpu(j) {
+			if (cpu_data(i).core_id ==
+			    cpu_data(j).core_id)
+				cpu_set(j, cpu_core_map[i]);
+		}
+	}
+
+	for_each_present_cpu(i) {
+		unsigned int j;
+
+		cpus_clear(cpu_sibling_map[i]);
+		if (cpu_data(i).proc_id == -1) {
+			cpu_set(i, cpu_sibling_map[i]);
+			continue;
+		}
+
+		for_each_present_cpu(j) {
+			if (cpu_data(i).proc_id ==
+			    cpu_data(j).proc_id)
+				cpu_set(j, cpu_sibling_map[i]);
+		}
+	}
+}
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
 	int ret = smp_boot_one_cpu(cpu);
@@ -1305,18 +1299,112 @@
 	return ret;
 }
 
-void __init smp_cpus_done(unsigned int max_cpus)
+#ifdef CONFIG_HOTPLUG_CPU
+void cpu_play_dead(void)
 {
-	unsigned long bogosum = 0;
+	int cpu = smp_processor_id();
+	unsigned long pstate;
+
+	idle_task_exit();
+
+	if (tlb_type == hypervisor) {
+		struct trap_per_cpu *tb = &trap_block[cpu];
+
+		sun4v_cpu_qconf(HV_CPU_QUEUE_CPU_MONDO,
+				tb->cpu_mondo_pa, 0);
+		sun4v_cpu_qconf(HV_CPU_QUEUE_DEVICE_MONDO,
+				tb->dev_mondo_pa, 0);
+		sun4v_cpu_qconf(HV_CPU_QUEUE_RES_ERROR,
+				tb->resum_mondo_pa, 0);
+		sun4v_cpu_qconf(HV_CPU_QUEUE_NONRES_ERROR,
+				tb->nonresum_mondo_pa, 0);
+	}
+
+	cpu_clear(cpu, smp_commenced_mask);
+	membar_safe("#Sync");
+
+	local_irq_disable();
+
+	__asm__ __volatile__(
+		"rdpr	%%pstate, %0\n\t"
+		"wrpr	%0, %1, %%pstate"
+		: "=r" (pstate)
+		: "i" (PSTATE_IE));
+
+	while (1)
+		barrier();
+}
+
+int __cpu_disable(void)
+{
+	int cpu = smp_processor_id();
+	cpuinfo_sparc *c;
 	int i;
 
-	for_each_online_cpu(i)
-		bogosum += cpu_data(i).udelay_val;
-	printk("Total of %ld processors activated "
-	       "(%lu.%02lu BogoMIPS).\n",
-	       (long) num_online_cpus(),
-	       bogosum/(500000/HZ),
-	       (bogosum/(5000/HZ))%100);
+	for_each_cpu_mask(i, cpu_core_map[cpu])
+		cpu_clear(cpu, cpu_core_map[i]);
+	cpus_clear(cpu_core_map[cpu]);
+
+	for_each_cpu_mask(i, cpu_sibling_map[cpu])
+		cpu_clear(cpu, cpu_sibling_map[i]);
+	cpus_clear(cpu_sibling_map[cpu]);
+
+	c = &cpu_data(cpu);
+
+	c->core_id = 0;
+	c->proc_id = -1;
+
+	spin_lock(&call_lock);
+	cpu_clear(cpu, cpu_online_map);
+	spin_unlock(&call_lock);
+
+	smp_wmb();
+
+	/* Make sure no interrupts point to this cpu.  */
+	fixup_irqs();
+
+	local_irq_enable();
+	mdelay(1);
+	local_irq_disable();
+
+	return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	int i;
+
+	for (i = 0; i < 100; i++) {
+		smp_rmb();
+		if (!cpu_isset(cpu, smp_commenced_mask))
+			break;
+		msleep(100);
+	}
+	if (cpu_isset(cpu, smp_commenced_mask)) {
+		printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+	} else {
+#if defined(CONFIG_SUN_LDOMS)
+		unsigned long hv_err;
+		int limit = 100;
+
+		do {
+			hv_err = sun4v_cpu_stop(cpu);
+			if (hv_err == HV_EOK) {
+				cpu_clear(cpu, cpu_present_map);
+				break;
+			}
+		} while (--limit > 0);
+		if (limit <= 0) {
+			printk(KERN_ERR "sun4v_cpu_stop() fails err=%lu\n",
+			       hv_err);
+		}
+#endif
+	}
+}
+#endif
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
 }
 
 void smp_send_reschedule(int cpu)
@@ -1337,7 +1425,7 @@
 EXPORT_SYMBOL(__per_cpu_base);
 EXPORT_SYMBOL(__per_cpu_shift);
 
-void __init setup_per_cpu_areas(void)
+void __init real_setup_per_cpu_areas(void)
 {
 	unsigned long goal, size, i;
 	char *ptr;
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index d00f51a..719d676 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,7 +1,6 @@
-/* $Id: sparc64_ksyms.c,v 1.121 2002/02/09 19:49:31 davem Exp $
- * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
+/* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
  * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
  */
@@ -24,10 +23,10 @@
 #include <linux/syscalls.h>
 #include <linux/percpu.h>
 #include <linux/init.h>
+#include <linux/rwsem.h>
 #include <net/compat.h>
 
 #include <asm/oplib.h>
-#include <asm/delay.h>
 #include <asm/system.h>
 #include <asm/auxio.h>
 #include <asm/pgtable.h>
@@ -58,7 +57,6 @@
 #include <asm/ns87303.h>
 #include <asm/timer.h>
 #include <asm/cpudata.h>
-#include <asm/rwsem.h>
 
 struct poll {
 	int fd;
@@ -124,10 +122,6 @@
 EXPORT_SYMBOL(__write_unlock);
 EXPORT_SYMBOL(__write_trylock);
 
-/* CPU online map and active count.  */
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(phys_cpu_present_map);
-
 EXPORT_SYMBOL(smp_call_function);
 #endif /* CONFIG_SMP */
 
@@ -330,12 +324,6 @@
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(strncmp);
 
-/* Delay routines. */
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__delay);
-
 void VISenter(void);
 /* RAID code needs this */
 EXPORT_SYMBOL(VISenter);
diff --git a/arch/sparc64/kernel/sstate.c b/arch/sparc64/kernel/sstate.c
new file mode 100644
index 0000000..5b6e75b
--- /dev/null
+++ b/arch/sparc64/kernel/sstate.c
@@ -0,0 +1,104 @@
+/* sstate.c: System soft state support.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
+
+#include <asm/hypervisor.h>
+#include <asm/sstate.h>
+#include <asm/oplib.h>
+#include <asm/head.h>
+#include <asm/io.h>
+
+static int hv_supports_soft_state;
+
+static unsigned long kimage_addr_to_ra(const char *p)
+{
+	unsigned long val = (unsigned long) p;
+
+	return kern_base + (val - KERNBASE);
+}
+
+static void do_set_sstate(unsigned long state, const char *msg)
+{
+	unsigned long err;
+
+	if (!hv_supports_soft_state)
+		return;
+
+	err = sun4v_mach_set_soft_state(state, kimage_addr_to_ra(msg));
+	if (err) {
+		printk(KERN_WARNING "SSTATE: Failed to set soft-state to "
+		       "state[%lx] msg[%s], err=%lu\n",
+		       state, msg, err);
+	}
+}
+
+static const char booting_msg[32] __attribute__((aligned(32))) =
+	"Linux booting";
+static const char running_msg[32] __attribute__((aligned(32))) =
+	"Linux running";
+static const char halting_msg[32] __attribute__((aligned(32))) =
+	"Linux halting";
+static const char poweroff_msg[32] __attribute__((aligned(32))) =
+	"Linux powering off";
+static const char rebooting_msg[32] __attribute__((aligned(32))) =
+	"Linux rebooting";
+static const char panicing_msg[32] __attribute__((aligned(32))) =
+	"Linux panicing";
+
+void sstate_booting(void)
+{
+	do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg);
+}
+
+void sstate_running(void)
+{
+	do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg);
+}
+
+void sstate_halt(void)
+{
+	do_set_sstate(HV_SOFT_STATE_TRANSITION, halting_msg);
+}
+
+void sstate_poweroff(void)
+{
+	do_set_sstate(HV_SOFT_STATE_TRANSITION, poweroff_msg);
+}
+
+void sstate_reboot(void)
+{
+	do_set_sstate(HV_SOFT_STATE_TRANSITION, rebooting_msg);
+}
+
+static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr)
+{
+	do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block sstate_panic_block = {
+	.notifier_call	=	sstate_panic_event,
+	.priority	=	INT_MAX,
+};
+
+void __init sun4v_sstate_init(void)
+{
+	unsigned long major, minor;
+
+	major = 1;
+	minor = 0;
+	if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor))
+		return;
+
+	hv_supports_soft_state = 1;
+
+	prom_sun4v_guest_soft_state();
+	atomic_notifier_chain_register(&panic_notifier_list,
+				       &sstate_panic_block);
+}
diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S
index 405855d..574bc24 100644
--- a/arch/sparc64/kernel/sun4v_ivec.S
+++ b/arch/sparc64/kernel/sun4v_ivec.S
@@ -22,12 +22,12 @@
 	be,pn	%xcc, sun4v_cpu_mondo_queue_empty
 	 nop
 
-	/* Get &trap_block[smp_processor_id()] into %g3.  */
-	ldxa	[%g0] ASI_SCRATCHPAD, %g3
-	sub	%g3, TRAP_PER_CPU_FAULT_INFO, %g3
+	/* Get &trap_block[smp_processor_id()] into %g4.  */
+	ldxa	[%g0] ASI_SCRATCHPAD, %g4
+	sub	%g4, TRAP_PER_CPU_FAULT_INFO, %g4
 
 	/* Get CPU mondo queue base phys address into %g7.  */
-	ldx	[%g3 + TRAP_PER_CPU_CPU_MONDO_PA], %g7
+	ldx	[%g4 + TRAP_PER_CPU_CPU_MONDO_PA], %g7
 
 	/* Now get the cross-call arguments and handler PC, same
 	 * layout as sun4u:
@@ -47,8 +47,7 @@
 	add	%g2, 0x40 - 0x8 - 0x8, %g2
 
 	/* Update queue head pointer.  */
-	sethi	%hi(8192 - 1), %g4
-	or	%g4, %lo(8192 - 1), %g4
+	lduw	[%g4 + TRAP_PER_CPU_CPU_MONDO_QMASK], %g4
 	and	%g2, %g4, %g2
 
 	mov	INTRQ_CPU_MONDO_HEAD, %g4
@@ -71,12 +70,12 @@
 	be,pn	%xcc, sun4v_dev_mondo_queue_empty
 	 nop
 
-	/* Get &trap_block[smp_processor_id()] into %g3.  */
-	ldxa	[%g0] ASI_SCRATCHPAD, %g3
-	sub	%g3, TRAP_PER_CPU_FAULT_INFO, %g3
+	/* Get &trap_block[smp_processor_id()] into %g4.  */
+	ldxa	[%g0] ASI_SCRATCHPAD, %g4
+	sub	%g4, TRAP_PER_CPU_FAULT_INFO, %g4
 
 	/* Get DEV mondo queue base phys address into %g5.  */
-	ldx	[%g3 + TRAP_PER_CPU_DEV_MONDO_PA], %g5
+	ldx	[%g4 + TRAP_PER_CPU_DEV_MONDO_PA], %g5
 
 	/* Load IVEC into %g3.  */
 	ldxa	[%g5 + %g2] ASI_PHYS_USE_EC, %g3
@@ -90,8 +89,7 @@
 	 */
 
 	/* Update queue head pointer, this frees up some registers.  */
-	sethi	%hi(8192 - 1), %g4
-	or	%g4, %lo(8192 - 1), %g4
+	lduw	[%g4 + TRAP_PER_CPU_DEV_MONDO_QMASK], %g4
 	and	%g2, %g4, %g2
 
 	mov	INTRQ_DEVICE_MONDO_HEAD, %g4
@@ -143,6 +141,8 @@
 	brnz,pn	%g1, sun4v_res_mondo_queue_full
 	 nop
 
+	lduw	[%g3 + TRAP_PER_CPU_RESUM_QMASK], %g4
+
 	/* Remember this entry's offset in %g1.  */
 	mov	%g2, %g1
 
@@ -173,8 +173,6 @@
 	add	%g2, 0x08, %g2
 
 	/* Update queue head pointer.  */
-	sethi	%hi(8192 - 1), %g4
-	or	%g4, %lo(8192 - 1), %g4
 	and	%g2, %g4, %g2
 
 	mov	INTRQ_RESUM_MONDO_HEAD, %g4
@@ -254,6 +252,8 @@
 	brnz,pn	%g1, sun4v_nonres_mondo_queue_full
 	 nop
 
+	lduw	[%g3 + TRAP_PER_CPU_NONRESUM_QMASK], %g4
+
 	/* Remember this entry's offset in %g1.  */
 	mov	%g2, %g1
 
@@ -284,8 +284,6 @@
 	add	%g2, 0x08, %g2
 
 	/* Update queue head pointer.  */
-	sethi	%hi(8192 - 1), %g4
-	or	%g4, %lo(8192 - 1), %g4
 	and	%g2, %g4, %g2
 
 	mov	INTRQ_NONRESUM_MONDO_HEAD, %g4
diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
new file mode 100644
index 0000000..52816c7
--- /dev/null
+++ b/arch/sparc64/kernel/sysfs.c
@@ -0,0 +1,295 @@
+/* sysfs.c: Toplogy sysfs support code for sparc64.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
+
+#include <asm/hypervisor.h>
+#include <asm/spitfire.h>
+
+static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64)));
+
+#define SHOW_MMUSTAT_ULONG(NAME) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+	struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \
+	return sprintf(buf, "%lu\n", p->NAME); \
+} \
+static SYSDEV_ATTR(NAME, 0444, show_##NAME, NULL)
+
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte);
+
+static struct attribute *mmu_stat_attrs[] = {
+	&attr_immu_tsb_hits_ctx0_8k_tte.attr,
+	&attr_immu_tsb_ticks_ctx0_8k_tte.attr,
+	&attr_immu_tsb_hits_ctx0_64k_tte.attr,
+	&attr_immu_tsb_ticks_ctx0_64k_tte.attr,
+	&attr_immu_tsb_hits_ctx0_4mb_tte.attr,
+	&attr_immu_tsb_ticks_ctx0_4mb_tte.attr,
+	&attr_immu_tsb_hits_ctx0_256mb_tte.attr,
+	&attr_immu_tsb_ticks_ctx0_256mb_tte.attr,
+	&attr_immu_tsb_hits_ctxnon0_8k_tte.attr,
+	&attr_immu_tsb_ticks_ctxnon0_8k_tte.attr,
+	&attr_immu_tsb_hits_ctxnon0_64k_tte.attr,
+	&attr_immu_tsb_ticks_ctxnon0_64k_tte.attr,
+	&attr_immu_tsb_hits_ctxnon0_4mb_tte.attr,
+	&attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr,
+	&attr_immu_tsb_hits_ctxnon0_256mb_tte.attr,
+	&attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr,
+	&attr_dmmu_tsb_hits_ctx0_8k_tte.attr,
+	&attr_dmmu_tsb_ticks_ctx0_8k_tte.attr,
+	&attr_dmmu_tsb_hits_ctx0_64k_tte.attr,
+	&attr_dmmu_tsb_ticks_ctx0_64k_tte.attr,
+	&attr_dmmu_tsb_hits_ctx0_4mb_tte.attr,
+	&attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr,
+	&attr_dmmu_tsb_hits_ctx0_256mb_tte.attr,
+	&attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr,
+	&attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr,
+	&attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr,
+	&attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr,
+	&attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr,
+	&attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr,
+	&attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr,
+	&attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr,
+	&attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr,
+	NULL,
+};
+
+static struct attribute_group mmu_stat_group = {
+	.attrs = mmu_stat_attrs,
+	.name = "mmu_stats",
+};
+
+/* XXX convert to rusty's on_one_cpu */
+static unsigned long run_on_cpu(unsigned long cpu,
+			        unsigned long (*func)(unsigned long),
+				unsigned long arg)
+{
+	cpumask_t old_affinity = current->cpus_allowed;
+	unsigned long ret;
+
+	/* should return -EINVAL to userspace */
+	if (set_cpus_allowed(current, cpumask_of_cpu(cpu)))
+		return 0;
+
+	ret = func(arg);
+
+	set_cpus_allowed(current, old_affinity);
+
+	return ret;
+}
+
+static unsigned long read_mmustat_enable(unsigned long junk)
+{
+	unsigned long ra = 0;
+
+	sun4v_mmustat_info(&ra);
+
+	return ra != 0;
+}
+
+static unsigned long write_mmustat_enable(unsigned long val)
+{
+	unsigned long ra, orig_ra;
+
+	if (val)
+		ra = __pa(&per_cpu(mmu_stats, smp_processor_id()));
+	else
+		ra = 0UL;
+
+	return sun4v_mmustat_conf(ra, &orig_ra);
+}
+
+static ssize_t show_mmustat_enable(struct sys_device *s, char *buf)
+{
+	unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0);
+	return sprintf(buf, "%lx\n", val);
+}
+
+static ssize_t store_mmustat_enable(struct sys_device *s, const char *buf, size_t count)
+{
+	unsigned long val, err;
+	int ret = sscanf(buf, "%ld", &val);
+
+	if (ret != 1)
+		return -EINVAL;
+
+	err = run_on_cpu(s->id, write_mmustat_enable, val);
+	if (err)
+		return -EIO;
+
+	return count;
+}
+
+static SYSDEV_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable);
+
+static int mmu_stats_supported;
+
+static int register_mmu_stats(struct sys_device *s)
+{
+	if (!mmu_stats_supported)
+		return 0;
+	sysdev_create_file(s, &attr_mmustat_enable);
+	return sysfs_create_group(&s->kobj, &mmu_stat_group);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void unregister_mmu_stats(struct sys_device *s)
+{
+	if (!mmu_stats_supported)
+		return;
+	sysfs_remove_group(&s->kobj, &mmu_stat_group);
+	sysdev_remove_file(s, &attr_mmustat_enable);
+}
+#endif
+
+#define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+	cpuinfo_sparc *c = &cpu_data(dev->id); \
+	return sprintf(buf, "%lu\n", c->MEMBER); \
+}
+
+#define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+	cpuinfo_sparc *c = &cpu_data(dev->id); \
+	return sprintf(buf, "%u\n", c->MEMBER); \
+}
+
+SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick);
+SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size);
+SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size);
+SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size);
+SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size);
+SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size);
+SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size);
+
+static struct sysdev_attribute cpu_core_attrs[] = {
+	_SYSDEV_ATTR(clock_tick,          0444, show_clock_tick, NULL),
+	_SYSDEV_ATTR(l1_dcache_size,      0444, show_l1_dcache_size, NULL),
+	_SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
+	_SYSDEV_ATTR(l1_icache_size,      0444, show_l1_icache_size, NULL),
+	_SYSDEV_ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL),
+	_SYSDEV_ATTR(l2_cache_size,       0444, show_l2_cache_size, NULL),
+	_SYSDEV_ATTR(l2_cache_line_size,  0444, show_l2_cache_line_size, NULL),
+};
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static void register_cpu_online(unsigned int cpu)
+{
+	struct cpu *c = &per_cpu(cpu_devices, cpu);
+	struct sys_device *s = &c->sysdev;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
+		sysdev_create_file(s, &cpu_core_attrs[i]);
+
+	register_mmu_stats(s);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void unregister_cpu_online(unsigned int cpu)
+{
+	struct cpu *c = &per_cpu(cpu_devices, cpu);
+	struct sys_device *s = &c->sysdev;
+	int i;
+
+	unregister_mmu_stats(s);
+	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
+		sysdev_remove_file(s, &cpu_core_attrs[i]);
+}
+#endif
+
+static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
+				      unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned int)(long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		register_cpu_online(cpu);
+		break;
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_DEAD:
+	case CPU_DEAD_FROZEN:
+		unregister_cpu_online(cpu);
+		break;
+#endif
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
+	.notifier_call	= sysfs_cpu_notify,
+};
+
+static void __init check_mmu_stats(void)
+{
+	unsigned long dummy1, err;
+
+	if (tlb_type != hypervisor)
+		return;
+
+	err = sun4v_mmustat_info(&dummy1);
+	if (!err)
+		mmu_stats_supported = 1;
+}
+
+static int __init topology_init(void)
+{
+	int cpu;
+
+	check_mmu_stats();
+
+	register_cpu_notifier(&sysfs_cpu_nb);
+
+	for_each_possible_cpu(cpu) {
+		struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+		register_cpu(c, cpu);
+		if (cpu_online(cpu))
+			register_cpu_online(cpu);
+	}
+
+	return 0;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 2d63d76..62e316a 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -680,22 +680,14 @@
 
 static u32 hypervisor_get_time(void)
 {
-	register unsigned long func asm("%o5");
-	register unsigned long arg0 asm("%o0");
-	register unsigned long arg1 asm("%o1");
+	unsigned long ret, time;
 	int retries = 10000;
 
 retry:
-	func = HV_FAST_TOD_GET;
-	arg0 = 0;
-	arg1 = 0;
-	__asm__ __volatile__("ta	%6"
-			     : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
-			     : "0" (func), "1" (arg0), "2" (arg1),
-			       "i" (HV_FAST_TRAP));
-	if (arg0 == HV_EOK)
-		return arg1;
-	if (arg0 == HV_EWOULDBLOCK) {
+	ret = sun4v_tod_get(&time);
+	if (ret == HV_EOK)
+		return time;
+	if (ret == HV_EWOULDBLOCK) {
 		if (--retries > 0) {
 			udelay(100);
 			goto retry;
@@ -709,20 +701,14 @@
 
 static int hypervisor_set_time(u32 secs)
 {
-	register unsigned long func asm("%o5");
-	register unsigned long arg0 asm("%o0");
+	unsigned long ret;
 	int retries = 10000;
 
 retry:
-	func = HV_FAST_TOD_SET;
-	arg0 = secs;
-	__asm__ __volatile__("ta	%4"
-			     : "=&r" (func), "=&r" (arg0)
-			     : "0" (func), "1" (arg0),
-			       "i" (HV_FAST_TRAP));
-	if (arg0 == HV_EOK)
+	ret = sun4v_tod_set(secs);
+	if (ret == HV_EOK)
 		return 0;
-	if (arg0 == HV_EWOULDBLOCK) {
+	if (ret == HV_EWOULDBLOCK) {
 		if (--retries > 0) {
 			udelay(100);
 			goto retry;
@@ -862,11 +848,7 @@
 static unsigned long sparc64_init_timers(void)
 {
 	struct device_node *dp;
-	struct property *prop;
 	unsigned long clock;
-#ifdef CONFIG_SMP
-	extern void smp_tick_init(void);
-#endif
 
 	dp = of_find_node_by_path("/");
 	if (tlb_type == spitfire) {
@@ -879,21 +861,15 @@
 		if (manuf == 0x17 && impl == 0x13) {
 			/* Hummingbird, aka Ultra-IIe */
 			tick_ops = &hbtick_operations;
-			prop = of_find_property(dp, "stick-frequency", NULL);
+			clock = of_getintprop_default(dp, "stick-frequency", 0);
 		} else {
 			tick_ops = &tick_operations;
-			cpu_find_by_instance(0, &dp, NULL);
-			prop = of_find_property(dp, "clock-frequency", NULL);
+			clock = local_cpu_data().clock_tick;
 		}
 	} else {
 		tick_ops = &stick_operations;
-		prop = of_find_property(dp, "stick-frequency", NULL);
+		clock = of_getintprop_default(dp, "stick-frequency", 0);
 	}
-	clock = *(unsigned int *) prop->value;
-
-#ifdef CONFIG_SMP
-	smp_tick_init();
-#endif
 
 	return clock;
 }
@@ -1055,10 +1031,31 @@
 	sparc64_clockevent.mult = mult;
 }
 
+static unsigned long tb_ticks_per_usec __read_mostly;
+
+void __delay(unsigned long loops)
+{
+	unsigned long bclock, now;
+
+	bclock = tick_ops->get_tick();
+	do {
+		now = tick_ops->get_tick();
+	} while ((now-bclock) < loops);
+}
+EXPORT_SYMBOL(__delay);
+
+void udelay(unsigned long usecs)
+{
+	__delay(tb_ticks_per_usec * usecs);
+}
+EXPORT_SYMBOL(udelay);
+
 void __init time_init(void)
 {
 	unsigned long clock = sparc64_init_timers();
 
+	tb_ticks_per_usec = clock / USEC_PER_SEC;
+
 	timer_ticks_per_nsec_quotient =
 		clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT);
 
@@ -1365,6 +1362,7 @@
 	return hypervisor_set_time(seconds);
 }
 
+#ifdef CONFIG_PCI
 static void bq4802_get_rtc_time(struct rtc_time *time)
 {
 	unsigned char val = readb(bq4802_regs + 0x0e);
@@ -1436,6 +1434,7 @@
 
 	return 0;
 }
+#endif /* CONFIG_PCI */
 
 struct mini_rtc_ops {
 	void (*get_rtc_time)(struct rtc_time *);
@@ -1452,10 +1451,12 @@
 	.set_rtc_time = hypervisor_set_rtc_time,
 };
 
+#ifdef CONFIG_PCI
 static struct mini_rtc_ops bq4802_rtc_ops = {
 	.get_rtc_time = bq4802_get_rtc_time,
 	.set_rtc_time = bq4802_set_rtc_time,
 };
+#endif /* CONFIG_PCI */
 
 static struct mini_rtc_ops *mini_rtc_ops;
 
@@ -1579,8 +1580,10 @@
 		mini_rtc_ops = &hypervisor_rtc_ops;
 	else if (this_is_starfire)
 		mini_rtc_ops = &starfire_rtc_ops;
+#ifdef CONFIG_PCI
 	else if (bq4802_regs)
 		mini_rtc_ops = &bq4802_rtc_ops;
+#endif /* CONFIG_PCI */
 	else
 		return -ENODEV;
 
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index d0fde36..6ef2d29 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -795,8 +795,7 @@
 void __init cheetah_ecache_flush_init(void)
 {
 	unsigned long largest_size, smallest_linesize, order, ver;
-	struct device_node *dp;
-	int i, instance, sz;
+	int i, sz;
 
 	/* Scan all cpu device tree nodes, note two values:
 	 * 1) largest E-cache size
@@ -805,18 +804,20 @@
 	largest_size = 0UL;
 	smallest_linesize = ~0UL;
 
-	instance = 0;
-	while (!cpu_find_by_instance(instance, &dp, NULL)) {
+	for (i = 0; i < NR_CPUS; i++) {
 		unsigned long val;
 
-		val = of_getintprop_default(dp, "ecache-size",
-					    (2 * 1024 * 1024));
+		val = cpu_data(i).ecache_size;
+		if (!val)
+			continue;
+
 		if (val > largest_size)
 			largest_size = val;
-		val = of_getintprop_default(dp, "ecache-line-size", 64);
+
+		val = cpu_data(i).ecache_line_size;
 		if (val < smallest_linesize)
 			smallest_linesize = val;
-		instance++;
+
 	}
 
 	if (largest_size == 0UL || smallest_linesize == ~0UL) {
@@ -2224,6 +2225,7 @@
 	notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
 	__asm__ __volatile__("flushw");
 	__show_regs(regs);
+	add_taint(TAINT_DIE);
 	if (regs->tstate & TSTATE_PRIV) {
 		struct reg_window *rw = (struct reg_window *)
 			(regs->u_regs[UREG_FP] + STACK_BIAS);
@@ -2564,7 +2566,15 @@
 	    (TRAP_PER_CPU_TSB_HUGE_TEMP !=
 	     offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
 	    (TRAP_PER_CPU_IRQ_WORKLIST !=
-	     offsetof(struct trap_per_cpu, irq_worklist)))
+	     offsetof(struct trap_per_cpu, irq_worklist)) ||
+	    (TRAP_PER_CPU_CPU_MONDO_QMASK !=
+	     offsetof(struct trap_per_cpu, cpu_mondo_qmask)) ||
+	    (TRAP_PER_CPU_DEV_MONDO_QMASK !=
+	     offsetof(struct trap_per_cpu, dev_mondo_qmask)) ||
+	    (TRAP_PER_CPU_RESUM_QMASK !=
+	     offsetof(struct trap_per_cpu, resum_qmask)) ||
+	    (TRAP_PER_CPU_NONRESUM_QMASK !=
+	     offsetof(struct trap_per_cpu, nonresum_qmask)))
 		trap_per_cpu_offsets_are_bolixed_dave();
 
 	if ((TSB_CONFIG_TSB !=
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
new file mode 100644
index 0000000..49569b4
--- /dev/null
+++ b/arch/sparc64/kernel/vio.c
@@ -0,0 +1,395 @@
+/* vio.c: Virtual I/O channel devices probing infrastructure.
+ *
+ *    Copyright (c) 2003-2005 IBM Corp.
+ *     Dave Engebretsen engebret@us.ibm.com
+ *     Santiago Leon santil@us.ibm.com
+ *     Hollis Blanchard <hollisb@us.ibm.com>
+ *     Stephen Rothwell
+ *
+ * Adapted to sparc64 by David S. Miller davem@davemloft.net
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+
+#include <asm/mdesc.h>
+#include <asm/vio.h>
+
+static inline int find_in_proplist(const char *list, const char *match,
+				   int len)
+{
+	while (len > 0) {
+		int l;
+
+		if (!strcmp(list, match))
+			return 1;
+		l = strlen(list) + 1;
+		list += l;
+		len -= l;
+	}
+	return 0;
+}
+
+static const struct vio_device_id *vio_match_device(
+	const struct vio_device_id *matches,
+	const struct vio_dev *dev)
+{
+	const char *type, *compat;
+	int len;
+
+	type = dev->type;
+	compat = dev->compat;
+	len = dev->compat_len;
+
+	while (matches->type[0] || matches->compat[0]) {
+		int match = 1;
+		if (matches->type[0])
+			match &= !strcmp(matches->type, type);
+
+		if (matches->compat[0]) {
+			match &= len &&
+				find_in_proplist(compat, matches->compat, len);
+		}
+		if (match)
+			return matches;
+		matches++;
+	}
+	return NULL;
+}
+
+static int vio_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct vio_dev *vio_dev = to_vio_dev(dev);
+	struct vio_driver *vio_drv = to_vio_driver(drv);
+	const struct vio_device_id *matches = vio_drv->id_table;
+
+	if (!matches)
+		return 0;
+
+	return vio_match_device(matches, vio_dev) != NULL;
+}
+
+static int vio_device_probe(struct device *dev)
+{
+	struct vio_dev *vdev = to_vio_dev(dev);
+	struct vio_driver *drv = to_vio_driver(dev->driver);
+	const struct vio_device_id *id;
+	int error = -ENODEV;
+
+	if (drv->probe) {
+		id = vio_match_device(drv->id_table, vdev);
+		if (id)
+			error = drv->probe(vdev, id);
+	}
+
+	return error;
+}
+
+static int vio_device_remove(struct device *dev)
+{
+	struct vio_dev *vdev = to_vio_dev(dev);
+	struct vio_driver *drv = to_vio_driver(dev->driver);
+
+	if (drv->remove)
+		return drv->remove(vdev);
+
+	return 1;
+}
+
+static ssize_t devspec_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct vio_dev *vdev = to_vio_dev(dev);
+	const char *str = "none";
+
+	if (!strcmp(vdev->type, "network"))
+		str = "vnet";
+	else if (!strcmp(vdev->type, "block"))
+		str = "vdisk";
+
+	return sprintf(buf, "%s\n", str);
+}
+
+static ssize_t type_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct vio_dev *vdev = to_vio_dev(dev);
+	return sprintf(buf, "%s\n", vdev->type);
+}
+
+static struct device_attribute vio_dev_attrs[] = {
+	__ATTR_RO(devspec),
+	__ATTR_RO(type),
+	__ATTR_NULL
+};
+
+static struct bus_type vio_bus_type = {
+	.name		= "vio",
+	.dev_attrs	= vio_dev_attrs,
+	.match		= vio_bus_match,
+	.probe		= vio_device_probe,
+	.remove		= vio_device_remove,
+};
+
+int vio_register_driver(struct vio_driver *viodrv)
+{
+	viodrv->driver.bus = &vio_bus_type;
+
+	return driver_register(&viodrv->driver);
+}
+EXPORT_SYMBOL(vio_register_driver);
+
+void vio_unregister_driver(struct vio_driver *viodrv)
+{
+	driver_unregister(&viodrv->driver);
+}
+EXPORT_SYMBOL(vio_unregister_driver);
+
+static void __devinit vio_dev_release(struct device *dev)
+{
+	kfree(to_vio_dev(dev));
+}
+
+static ssize_t
+show_pciobppath_attr(struct device *dev, struct device_attribute *attr,
+		     char *buf)
+{
+	struct vio_dev *vdev;
+	struct device_node *dp;
+
+	vdev = to_vio_dev(dev);
+	dp = vdev->dp;
+
+	return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name);
+}
+
+static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH,
+		   show_pciobppath_attr, NULL);
+
+struct device_node *cdev_node;
+
+static struct vio_dev *root_vdev;
+static u64 cdev_cfg_handle;
+
+static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
+				  struct vio_dev *vdev)
+{
+	u64 a;
+
+	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+		const u64 *chan_id;
+		const u64 *irq;
+		u64 target;
+
+		target = mdesc_arc_target(hp, a);
+
+		irq = mdesc_get_property(hp, target, "tx-ino", NULL);
+		if (irq)
+			vdev->tx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
+
+		irq = mdesc_get_property(hp, target, "rx-ino", NULL);
+		if (irq)
+			vdev->rx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
+
+		chan_id = mdesc_get_property(hp, target, "id", NULL);
+		if (chan_id)
+			vdev->channel_id = *chan_id;
+	}
+}
+
+static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
+				      struct device *parent)
+{
+	const char *type, *compat;
+	struct device_node *dp;
+	struct vio_dev *vdev;
+	int err, tlen, clen;
+
+	type = mdesc_get_property(hp, mp, "device-type", &tlen);
+	if (!type) {
+		type = mdesc_get_property(hp, mp, "name", &tlen);
+		if (!type) {
+			type = mdesc_node_name(hp, mp);
+			tlen = strlen(type) + 1;
+		}
+	}
+	if (tlen > VIO_MAX_TYPE_LEN) {
+		printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
+		       type);
+		return NULL;
+	}
+
+	compat = mdesc_get_property(hp, mp, "device-type", &clen);
+	if (!compat) {
+		clen = 0;
+	} else if (clen > VIO_MAX_COMPAT_LEN) {
+		printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n",
+		       clen, type);
+		return NULL;
+	}
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev) {
+		printk(KERN_ERR "VIO: Could not allocate vio_dev\n");
+		return NULL;
+	}
+
+	vdev->mp = mp;
+	memcpy(vdev->type, type, tlen);
+	if (compat)
+		memcpy(vdev->compat, compat, clen);
+	else
+		memset(vdev->compat, 0, sizeof(vdev->compat));
+	vdev->compat_len = clen;
+
+	vdev->channel_id = ~0UL;
+	vdev->tx_irq = ~0;
+	vdev->rx_irq = ~0;
+
+	vio_fill_channel_info(hp, mp, vdev);
+
+	snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp);
+	vdev->dev.parent = parent;
+	vdev->dev.bus = &vio_bus_type;
+	vdev->dev.release = vio_dev_release;
+
+	if (parent == NULL) {
+		dp = cdev_node;
+	} else if (to_vio_dev(parent) == root_vdev) {
+		dp = of_get_next_child(cdev_node, NULL);
+		while (dp) {
+			if (!strcmp(dp->type, type))
+				break;
+
+			dp = of_get_next_child(cdev_node, dp);
+		}
+	} else {
+		dp = to_vio_dev(parent)->dp;
+	}
+	vdev->dp = dp;
+
+	err = device_register(&vdev->dev);
+	if (err) {
+		printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
+		       vdev->dev.bus_id, err);
+		kfree(vdev);
+		return NULL;
+	}
+	if (vdev->dp)
+		err = sysfs_create_file(&vdev->dev.kobj,
+					&dev_attr_obppath.attr);
+
+	return vdev;
+}
+
+static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent)
+{
+	u64 a;
+
+	mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) {
+		struct vio_dev *vdev;
+		u64 target;
+
+		target = mdesc_arc_target(hp, a);
+		vdev = vio_create_one(hp, target, &parent->dev);
+		if (vdev)
+			walk_tree(hp, target, vdev);
+	}
+}
+
+static void create_devices(struct mdesc_handle *hp, u64 root)
+{
+	u64 mp;
+
+	root_vdev = vio_create_one(hp, root, NULL);
+	if (!root_vdev) {
+		printk(KERN_ERR "VIO: Coult not create root device.\n");
+		return;
+	}
+
+	walk_tree(hp, root, root_vdev);
+
+	/* Domain services is odd as it doesn't sit underneath the
+	 * channel-devices node, so we plug it in manually.
+	 */
+	mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services");
+	if (mp != MDESC_NODE_NULL) {
+		struct vio_dev *parent = vio_create_one(hp, mp,
+							&root_vdev->dev);
+
+		if (parent)
+			walk_tree(hp, mp, parent);
+	}
+}
+
+const char *channel_devices_node = "channel-devices";
+const char *channel_devices_compat = "SUNW,sun4v-channel-devices";
+const char *cfg_handle_prop = "cfg-handle";
+
+static int __init vio_init(void)
+{
+	struct mdesc_handle *hp;
+	const char *compat;
+	const u64 *cfg_handle;
+	int err, len;
+	u64 root;
+
+	err = bus_register(&vio_bus_type);
+	if (err) {
+		printk(KERN_ERR "VIO: Could not register bus type err=%d\n",
+		       err);
+		return err;
+	}
+
+	hp = mdesc_grab();
+	if (!hp)
+		return 0;
+
+	root = mdesc_node_by_name(hp, MDESC_NODE_NULL, channel_devices_node);
+	if (root == MDESC_NODE_NULL) {
+		printk(KERN_INFO "VIO: No channel-devices MDESC node.\n");
+		mdesc_release(hp);
+		return 0;
+	}
+
+	cdev_node = of_find_node_by_name(NULL, "channel-devices");
+	err = -ENODEV;
+	if (!cdev_node) {
+		printk(KERN_INFO "VIO: No channel-devices OBP node.\n");
+		goto out_release;
+	}
+
+	compat = mdesc_get_property(hp, root, "compatible", &len);
+	if (!compat) {
+		printk(KERN_ERR "VIO: Channel devices lacks compatible "
+		       "property\n");
+		goto out_release;
+	}
+	if (!find_in_proplist(compat, channel_devices_compat, len)) {
+		printk(KERN_ERR "VIO: Channel devices node lacks (%s) "
+		       "compat entry.\n", channel_devices_compat);
+		goto out_release;
+	}
+
+	cfg_handle = mdesc_get_property(hp, root, cfg_handle_prop, NULL);
+	if (!cfg_handle) {
+		printk(KERN_ERR "VIO: Channel devices lacks %s property\n",
+		       cfg_handle_prop);
+		goto out_release;
+	}
+
+	cdev_cfg_handle = *cfg_handle;
+
+	create_devices(hp, root);
+
+	mdesc_release(hp);
+
+	return 0;
+
+out_release:
+	mdesc_release(hp);
+	return err;
+}
+
+postcore_initcall(vio_init);
diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c
new file mode 100644
index 0000000..15613ad
--- /dev/null
+++ b/arch/sparc64/kernel/viohs.c
@@ -0,0 +1,792 @@
+/* viohs.c: LDOM Virtual I/O handshake helper layer.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/ldc.h>
+#include <asm/vio.h>
+
+int vio_ldc_send(struct vio_driver_state *vio, void *data, int len)
+{
+	int err, limit = 1000;
+
+	err = -EINVAL;
+	while (limit-- > 0) {
+		err = ldc_write(vio->lp, data, len);
+		if (!err || (err != -EAGAIN))
+			break;
+		udelay(1);
+	}
+
+	return err;
+}
+EXPORT_SYMBOL(vio_ldc_send);
+
+static int send_ctrl(struct vio_driver_state *vio,
+		     struct vio_msg_tag *tag, int len)
+{
+	tag->sid = vio_send_sid(vio);
+	return vio_ldc_send(vio, tag, len);
+}
+
+static void init_tag(struct vio_msg_tag *tag, u8 type, u8 stype, u16 stype_env)
+{
+	tag->type = type;
+	tag->stype = stype;
+	tag->stype_env = stype_env;
+}
+
+static int send_version(struct vio_driver_state *vio, u16 major, u16 minor)
+{
+	struct vio_ver_info pkt;
+
+	vio->_local_sid = (u32) sched_clock();
+
+	memset(&pkt, 0, sizeof(pkt));
+	init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_VER_INFO);
+	pkt.major = major;
+	pkt.minor = minor;
+	pkt.dev_class = vio->dev_class;
+
+	viodbg(HS, "SEND VERSION INFO maj[%u] min[%u] devclass[%u]\n",
+	       major, minor, vio->dev_class);
+
+	return send_ctrl(vio, &pkt.tag, sizeof(pkt));
+}
+
+static int start_handshake(struct vio_driver_state *vio)
+{
+	int err;
+
+	viodbg(HS, "START HANDSHAKE\n");
+
+	vio->hs_state = VIO_HS_INVALID;
+
+	err = send_version(vio,
+			   vio->ver_table[0].major,
+			   vio->ver_table[0].minor);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+void vio_link_state_change(struct vio_driver_state *vio, int event)
+{
+	if (event == LDC_EVENT_UP) {
+		vio->hs_state = VIO_HS_INVALID;
+
+		switch (vio->dev_class) {
+		case VDEV_NETWORK:
+		case VDEV_NETWORK_SWITCH:
+			vio->dr_state = (VIO_DR_STATE_TXREQ |
+					 VIO_DR_STATE_RXREQ);
+			break;
+
+		case VDEV_DISK:
+			vio->dr_state = VIO_DR_STATE_TXREQ;
+			break;
+		case VDEV_DISK_SERVER:
+			vio->dr_state = VIO_DR_STATE_RXREQ;
+			break;
+		}
+		start_handshake(vio);
+	}
+}
+EXPORT_SYMBOL(vio_link_state_change);
+
+static int handshake_failure(struct vio_driver_state *vio)
+{
+	struct vio_dring_state *dr;
+
+	/* XXX Put policy here...  Perhaps start a timer to fire
+	 * XXX in 100 ms, which will bring the link up and retry
+	 * XXX the handshake.
+	 */
+
+	viodbg(HS, "HANDSHAKE FAILURE\n");
+
+	vio->dr_state &= ~(VIO_DR_STATE_TXREG |
+			   VIO_DR_STATE_RXREG);
+
+	dr = &vio->drings[VIO_DRIVER_RX_RING];
+	memset(dr, 0, sizeof(*dr));
+
+	kfree(vio->desc_buf);
+	vio->desc_buf = NULL;
+	vio->desc_buf_len = 0;
+
+	vio->hs_state = VIO_HS_INVALID;
+
+	return -ECONNRESET;
+}
+
+static int process_unknown(struct vio_driver_state *vio, void *arg)
+{
+	struct vio_msg_tag *pkt = arg;
+
+	viodbg(HS, "UNKNOWN CONTROL [%02x:%02x:%04x:%08x]\n",
+	       pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+
+	printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n",
+	       vio->vdev->channel_id);
+
+	ldc_disconnect(vio->lp);
+
+	return -ECONNRESET;
+}
+
+static int send_dreg(struct vio_driver_state *vio)
+{
+	struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_TX_RING];
+	union {
+		struct vio_dring_register pkt;
+		char all[sizeof(struct vio_dring_register) +
+			 (sizeof(struct ldc_trans_cookie) *
+			  dr->ncookies)];
+	} u;
+	int i;
+
+	memset(&u, 0, sizeof(u));
+	init_tag(&u.pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_DRING_REG);
+	u.pkt.dring_ident = 0;
+	u.pkt.num_descr = dr->num_entries;
+	u.pkt.descr_size = dr->entry_size;
+	u.pkt.options = VIO_TX_DRING;
+	u.pkt.num_cookies = dr->ncookies;
+
+	viodbg(HS, "SEND DRING_REG INFO ndesc[%u] dsz[%u] opt[0x%x] "
+	       "ncookies[%u]\n",
+	       u.pkt.num_descr, u.pkt.descr_size, u.pkt.options,
+	       u.pkt.num_cookies);
+
+	for (i = 0; i < dr->ncookies; i++) {
+		u.pkt.cookies[i] = dr->cookies[i];
+
+		viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n",
+		       i,
+		       (unsigned long long) u.pkt.cookies[i].cookie_addr,
+		       (unsigned long long) u.pkt.cookies[i].cookie_size);
+	}
+
+	return send_ctrl(vio, &u.pkt.tag, sizeof(u));
+}
+
+static int send_rdx(struct vio_driver_state *vio)
+{
+	struct vio_rdx pkt;
+
+	memset(&pkt, 0, sizeof(pkt));
+
+	init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_RDX);
+
+	viodbg(HS, "SEND RDX INFO\n");
+
+	return send_ctrl(vio, &pkt.tag, sizeof(pkt));
+}
+
+static int send_attr(struct vio_driver_state *vio)
+{
+	return vio->ops->send_attr(vio);
+}
+
+static struct vio_version *find_by_major(struct vio_driver_state *vio,
+					 u16 major)
+{
+	struct vio_version *ret = NULL;
+	int i;
+
+	for (i = 0; i < vio->ver_table_entries; i++) {
+		struct vio_version *v = &vio->ver_table[i];
+		if (v->major <= major) {
+			ret = v;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int process_ver_info(struct vio_driver_state *vio,
+			    struct vio_ver_info *pkt)
+{
+	struct vio_version *vap;
+	int err;
+
+	viodbg(HS, "GOT VERSION INFO maj[%u] min[%u] devclass[%u]\n",
+	       pkt->major, pkt->minor, pkt->dev_class);
+
+	if (vio->hs_state != VIO_HS_INVALID) {
+		/* XXX Perhaps invoke start_handshake? XXX */
+		memset(&vio->ver, 0, sizeof(vio->ver));
+		vio->hs_state = VIO_HS_INVALID;
+	}
+
+	vap = find_by_major(vio, pkt->major);
+
+	vio->_peer_sid = pkt->tag.sid;
+
+	if (!vap) {
+		pkt->tag.stype = VIO_SUBTYPE_NACK;
+		pkt->major = 0;
+		pkt->minor = 0;
+		viodbg(HS, "SEND VERSION NACK maj[0] min[0]\n");
+		err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+	} else if (vap->major != pkt->major) {
+		pkt->tag.stype = VIO_SUBTYPE_NACK;
+		pkt->major = vap->major;
+		pkt->minor = vap->minor;
+		viodbg(HS, "SEND VERSION NACK maj[%u] min[%u]\n",
+		       pkt->major, pkt->minor);
+		err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+	} else {
+		struct vio_version ver = {
+			.major = pkt->major,
+			.minor = pkt->minor,
+		};
+		if (ver.minor > vap->minor)
+			ver.minor = vap->minor;
+		pkt->minor = ver.minor;
+		pkt->tag.stype = VIO_SUBTYPE_ACK;
+		viodbg(HS, "SEND VERSION ACK maj[%u] min[%u]\n",
+		       pkt->major, pkt->minor);
+		err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+		if (err > 0) {
+			vio->ver = ver;
+			vio->hs_state = VIO_HS_GOTVERS;
+		}
+	}
+	if (err < 0)
+		return handshake_failure(vio);
+
+	return 0;
+}
+
+static int process_ver_ack(struct vio_driver_state *vio,
+			   struct vio_ver_info *pkt)
+{
+	viodbg(HS, "GOT VERSION ACK maj[%u] min[%u] devclass[%u]\n",
+	       pkt->major, pkt->minor, pkt->dev_class);
+
+	if (vio->hs_state & VIO_HS_GOTVERS) {
+		if (vio->ver.major != pkt->major ||
+		    vio->ver.minor != pkt->minor) {
+			pkt->tag.stype = VIO_SUBTYPE_NACK;
+			(void) send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+			return handshake_failure(vio);
+		}
+	} else {
+		vio->ver.major = pkt->major;
+		vio->ver.minor = pkt->minor;
+		vio->hs_state = VIO_HS_GOTVERS;
+	}
+
+	switch (vio->dev_class) {
+	case VDEV_NETWORK:
+	case VDEV_DISK:
+		if (send_attr(vio) < 0)
+			return handshake_failure(vio);
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int process_ver_nack(struct vio_driver_state *vio,
+			    struct vio_ver_info *pkt)
+{
+	struct vio_version *nver;
+
+	viodbg(HS, "GOT VERSION NACK maj[%u] min[%u] devclass[%u]\n",
+	       pkt->major, pkt->minor, pkt->dev_class);
+
+	if ((pkt->major == 0 && pkt->minor == 0) ||
+	    !(nver = find_by_major(vio, pkt->major)))
+		return handshake_failure(vio);
+
+	if (send_version(vio, nver->major, nver->minor) < 0)
+		return handshake_failure(vio);
+
+	return 0;
+}
+
+static int process_ver(struct vio_driver_state *vio, struct vio_ver_info *pkt)
+{
+	switch (pkt->tag.stype) {
+	case VIO_SUBTYPE_INFO:
+		return process_ver_info(vio, pkt);
+
+	case VIO_SUBTYPE_ACK:
+		return process_ver_ack(vio, pkt);
+
+	case VIO_SUBTYPE_NACK:
+		return process_ver_nack(vio, pkt);
+
+	default:
+		return handshake_failure(vio);
+	};
+}
+
+static int process_attr(struct vio_driver_state *vio, void *pkt)
+{
+	int err;
+
+	if (!(vio->hs_state & VIO_HS_GOTVERS))
+		return handshake_failure(vio);
+
+	err = vio->ops->handle_attr(vio, pkt);
+	if (err < 0) {
+		return handshake_failure(vio);
+	} else {
+		vio->hs_state |= VIO_HS_GOT_ATTR;
+
+		if ((vio->dr_state & VIO_DR_STATE_TXREQ) &&
+		    !(vio->hs_state & VIO_HS_SENT_DREG)) {
+			if (send_dreg(vio) < 0)
+				return handshake_failure(vio);
+
+			vio->hs_state |= VIO_HS_SENT_DREG;
+		}
+	}
+	return 0;
+}
+
+static int all_drings_registered(struct vio_driver_state *vio)
+{
+	int need_rx, need_tx;
+
+	need_rx = (vio->dr_state & VIO_DR_STATE_RXREQ);
+	need_tx = (vio->dr_state & VIO_DR_STATE_TXREQ);
+
+	if (need_rx &&
+	    !(vio->dr_state & VIO_DR_STATE_RXREG))
+		return 0;
+
+	if (need_tx &&
+	    !(vio->dr_state & VIO_DR_STATE_TXREG))
+		return 0;
+
+	return 1;
+}
+
+static int process_dreg_info(struct vio_driver_state *vio,
+			     struct vio_dring_register *pkt)
+{
+	struct vio_dring_state *dr;
+	int i, len;
+
+	viodbg(HS, "GOT DRING_REG INFO ident[%llx] "
+	       "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+	       (unsigned long long) pkt->dring_ident,
+	       pkt->num_descr, pkt->descr_size, pkt->options,
+	       pkt->num_cookies);
+
+	if (!(vio->dr_state & VIO_DR_STATE_RXREQ))
+		goto send_nack;
+
+	if (vio->dr_state & VIO_DR_STATE_RXREG)
+		goto send_nack;
+
+	vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC);
+	if (!vio->desc_buf)
+		goto send_nack;
+
+	vio->desc_buf_len = pkt->descr_size;
+
+	dr = &vio->drings[VIO_DRIVER_RX_RING];
+
+	dr->num_entries = pkt->num_descr;
+	dr->entry_size = pkt->descr_size;
+	dr->ncookies = pkt->num_cookies;
+	for (i = 0; i < dr->ncookies; i++) {
+		dr->cookies[i] = pkt->cookies[i];
+
+		viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n",
+		       i,
+		       (unsigned long long)
+		       pkt->cookies[i].cookie_addr,
+		       (unsigned long long)
+		       pkt->cookies[i].cookie_size);
+	}
+
+	pkt->tag.stype = VIO_SUBTYPE_ACK;
+	pkt->dring_ident = ++dr->ident;
+
+	viodbg(HS, "SEND DRING_REG ACK ident[%llx]\n",
+	       (unsigned long long) pkt->dring_ident);
+
+	len = (sizeof(*pkt) +
+	       (dr->ncookies * sizeof(struct ldc_trans_cookie)));
+	if (send_ctrl(vio, &pkt->tag, len) < 0)
+		goto send_nack;
+
+	vio->dr_state |= VIO_DR_STATE_RXREG;
+
+	return 0;
+
+send_nack:
+	pkt->tag.stype = VIO_SUBTYPE_NACK;
+	viodbg(HS, "SEND DRING_REG NACK\n");
+	(void) send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+
+	return handshake_failure(vio);
+}
+
+static int process_dreg_ack(struct vio_driver_state *vio,
+			    struct vio_dring_register *pkt)
+{
+	struct vio_dring_state *dr;
+
+	viodbg(HS, "GOT DRING_REG ACK ident[%llx] "
+	       "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+	       (unsigned long long) pkt->dring_ident,
+	       pkt->num_descr, pkt->descr_size, pkt->options,
+	       pkt->num_cookies);
+
+	dr = &vio->drings[VIO_DRIVER_TX_RING];
+
+	if (!(vio->dr_state & VIO_DR_STATE_TXREQ))
+		return handshake_failure(vio);
+
+	dr->ident = pkt->dring_ident;
+	vio->dr_state |= VIO_DR_STATE_TXREG;
+
+	if (all_drings_registered(vio)) {
+		if (send_rdx(vio) < 0)
+			return handshake_failure(vio);
+		vio->hs_state = VIO_HS_SENT_RDX;
+	}
+	return 0;
+}
+
+static int process_dreg_nack(struct vio_driver_state *vio,
+			     struct vio_dring_register *pkt)
+{
+	viodbg(HS, "GOT DRING_REG NACK ident[%llx] "
+	       "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+	       (unsigned long long) pkt->dring_ident,
+	       pkt->num_descr, pkt->descr_size, pkt->options,
+	       pkt->num_cookies);
+
+	return handshake_failure(vio);
+}
+
+static int process_dreg(struct vio_driver_state *vio,
+			struct vio_dring_register *pkt)
+{
+	if (!(vio->hs_state & VIO_HS_GOTVERS))
+		return handshake_failure(vio);
+
+	switch (pkt->tag.stype) {
+	case VIO_SUBTYPE_INFO:
+		return process_dreg_info(vio, pkt);
+
+	case VIO_SUBTYPE_ACK:
+		return process_dreg_ack(vio, pkt);
+
+	case VIO_SUBTYPE_NACK:
+		return process_dreg_nack(vio, pkt);
+
+	default:
+		return handshake_failure(vio);
+	}
+}
+
+static int process_dunreg(struct vio_driver_state *vio,
+			  struct vio_dring_unregister *pkt)
+{
+	struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_RX_RING];
+
+	viodbg(HS, "GOT DRING_UNREG\n");
+
+	if (pkt->dring_ident != dr->ident)
+		return 0;
+
+	vio->dr_state &= ~VIO_DR_STATE_RXREG;
+
+	memset(dr, 0, sizeof(*dr));
+
+	kfree(vio->desc_buf);
+	vio->desc_buf = NULL;
+	vio->desc_buf_len = 0;
+
+	return 0;
+}
+
+static int process_rdx_info(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+	viodbg(HS, "GOT RDX INFO\n");
+
+	pkt->tag.stype = VIO_SUBTYPE_ACK;
+	viodbg(HS, "SEND RDX ACK\n");
+	if (send_ctrl(vio, &pkt->tag, sizeof(*pkt)) < 0)
+		return handshake_failure(vio);
+
+	vio->hs_state |= VIO_HS_SENT_RDX_ACK;
+	return 0;
+}
+
+static int process_rdx_ack(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+	viodbg(HS, "GOT RDX ACK\n");
+
+	if (!(vio->hs_state & VIO_HS_SENT_RDX))
+		return handshake_failure(vio);
+
+	vio->hs_state |= VIO_HS_GOT_RDX_ACK;
+	return 0;
+}
+
+static int process_rdx_nack(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+	viodbg(HS, "GOT RDX NACK\n");
+
+	return handshake_failure(vio);
+}
+
+static int process_rdx(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+	if (!all_drings_registered(vio))
+		handshake_failure(vio);
+
+	switch (pkt->tag.stype) {
+	case VIO_SUBTYPE_INFO:
+		return process_rdx_info(vio, pkt);
+
+	case VIO_SUBTYPE_ACK:
+		return process_rdx_ack(vio, pkt);
+
+	case VIO_SUBTYPE_NACK:
+		return process_rdx_nack(vio, pkt);
+
+	default:
+		return handshake_failure(vio);
+	}
+}
+
+int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt)
+{
+	struct vio_msg_tag *tag = pkt;
+	u8 prev_state = vio->hs_state;
+	int err;
+
+	switch (tag->stype_env) {
+	case VIO_VER_INFO:
+		err = process_ver(vio, pkt);
+		break;
+
+	case VIO_ATTR_INFO:
+		err = process_attr(vio, pkt);
+		break;
+
+	case VIO_DRING_REG:
+		err = process_dreg(vio, pkt);
+		break;
+
+	case VIO_DRING_UNREG:
+		err = process_dunreg(vio, pkt);
+		break;
+
+	case VIO_RDX:
+		err = process_rdx(vio, pkt);
+		break;
+
+	default:
+		err = process_unknown(vio, pkt);
+		break;
+	}
+	if (!err &&
+	    vio->hs_state != prev_state &&
+	    (vio->hs_state & VIO_HS_COMPLETE))
+		vio->ops->handshake_complete(vio);
+
+	return err;
+}
+EXPORT_SYMBOL(vio_control_pkt_engine);
+
+void vio_conn_reset(struct vio_driver_state *vio)
+{
+}
+EXPORT_SYMBOL(vio_conn_reset);
+
+/* The issue is that the Solaris virtual disk server just mirrors the
+ * SID values it gets from the client peer.  So we work around that
+ * here in vio_{validate,send}_sid() so that the drivers don't need
+ * to be aware of this crap.
+ */
+int vio_validate_sid(struct vio_driver_state *vio, struct vio_msg_tag *tp)
+{
+	u32 sid;
+
+	/* Always let VERSION+INFO packets through unchecked, they
+	 * define the new SID.
+	 */
+	if (tp->type == VIO_TYPE_CTRL &&
+	    tp->stype == VIO_SUBTYPE_INFO &&
+	    tp->stype_env == VIO_VER_INFO)
+		return 0;
+
+	/* Ok, now figure out which SID to use.  */
+	switch (vio->dev_class) {
+	case VDEV_NETWORK:
+	case VDEV_NETWORK_SWITCH:
+	case VDEV_DISK_SERVER:
+	default:
+		sid = vio->_peer_sid;
+		break;
+
+	case VDEV_DISK:
+		sid = vio->_local_sid;
+		break;
+	}
+
+	if (sid == tp->sid)
+		return 0;
+	viodbg(DATA, "BAD SID tag->sid[%08x] peer_sid[%08x] local_sid[%08x]\n",
+	       tp->sid, vio->_peer_sid, vio->_local_sid);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(vio_validate_sid);
+
+u32 vio_send_sid(struct vio_driver_state *vio)
+{
+	switch (vio->dev_class) {
+	case VDEV_NETWORK:
+	case VDEV_NETWORK_SWITCH:
+	case VDEV_DISK:
+	default:
+		return vio->_local_sid;
+
+	case VDEV_DISK_SERVER:
+		return vio->_peer_sid;
+	}
+}
+EXPORT_SYMBOL(vio_send_sid);
+
+extern int vio_ldc_alloc(struct vio_driver_state *vio,
+			 struct ldc_channel_config *base_cfg,
+			 void *event_arg)
+{
+	struct ldc_channel_config cfg = *base_cfg;
+	struct ldc_channel *lp;
+
+	cfg.tx_irq = vio->vdev->tx_irq;
+	cfg.rx_irq = vio->vdev->rx_irq;
+
+	lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg);
+	if (IS_ERR(lp))
+		return PTR_ERR(lp);
+
+	vio->lp = lp;
+
+	return 0;
+}
+EXPORT_SYMBOL(vio_ldc_alloc);
+
+void vio_ldc_free(struct vio_driver_state *vio)
+{
+	ldc_free(vio->lp);
+	vio->lp = NULL;
+
+	kfree(vio->desc_buf);
+	vio->desc_buf = NULL;
+	vio->desc_buf_len = 0;
+}
+EXPORT_SYMBOL(vio_ldc_free);
+
+void vio_port_up(struct vio_driver_state *vio)
+{
+	unsigned long flags;
+	int err, state;
+
+	spin_lock_irqsave(&vio->lock, flags);
+
+	state = ldc_state(vio->lp);
+
+	err = 0;
+	if (state == LDC_STATE_INIT) {
+		err = ldc_bind(vio->lp, vio->name);
+		if (err)
+			printk(KERN_WARNING "%s: Port %lu bind failed, "
+			       "err=%d\n",
+			       vio->name, vio->vdev->channel_id, err);
+	}
+
+	if (!err) {
+		err = ldc_connect(vio->lp);
+		if (err)
+			printk(KERN_WARNING "%s: Port %lu connect failed, "
+			       "err=%d\n",
+			       vio->name, vio->vdev->channel_id, err);
+	}
+	if (err) {
+		unsigned long expires = jiffies + HZ;
+
+		expires = round_jiffies(expires);
+		mod_timer(&vio->timer, expires);
+	}
+
+	spin_unlock_irqrestore(&vio->lock, flags);
+}
+EXPORT_SYMBOL(vio_port_up);
+
+static void vio_port_timer(unsigned long _arg)
+{
+	struct vio_driver_state *vio = (struct vio_driver_state *) _arg;
+
+	vio_port_up(vio);
+}
+
+int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
+		    u8 dev_class, struct vio_version *ver_table,
+		    int ver_table_size, struct vio_driver_ops *ops,
+		    char *name)
+{
+	switch (dev_class) {
+	case VDEV_NETWORK:
+	case VDEV_NETWORK_SWITCH:
+	case VDEV_DISK:
+	case VDEV_DISK_SERVER:
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (!ops->send_attr ||
+	    !ops->handle_attr ||
+	    !ops->handshake_complete)
+		return -EINVAL;
+
+	if (!ver_table || ver_table_size < 0)
+		return -EINVAL;
+
+	if (!name)
+		return -EINVAL;
+
+	spin_lock_init(&vio->lock);
+
+	vio->name = name;
+
+	vio->dev_class = dev_class;
+	vio->vdev = vdev;
+
+	vio->ver_table = ver_table;
+	vio->ver_table_entries = ver_table_size;
+
+	vio->ops = ops;
+
+	setup_timer(&vio->timer, vio_port_timer, (unsigned long) vio);
+
+	return 0;
+}
+EXPORT_SYMBOL(vio_driver_init);
diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
index 13fa2a2..3ad10f3 100644
--- a/arch/sparc64/kernel/vmlinux.lds.S
+++ b/arch/sparc64/kernel/vmlinux.lds.S
@@ -1,5 +1,6 @@
 /* ld script to make UltraLinux kernel */
 
+#include <asm/page.h>
 #include <asm-generic/vmlinux.lds.h>
 
 OUTPUT_FORMAT("elf64-sparc", "elf64-sparc", "elf64-sparc")
@@ -14,7 +15,7 @@
   .text 0x0000000000404000 :
   {
     _text = .;
-    *(.text)
+    TEXT_TEXT
     SCHED_TEXT
     LOCK_TEXT
     KPROBES_TEXT
@@ -23,11 +24,11 @@
   _etext = .;
   PROVIDE (etext = .);
 
-  RODATA
+  RO_DATA(PAGE_SIZE)
 
   .data    :
   {
-    *(.data)
+    DATA_DATA
     CONSTRUCTORS
   }
   .data1   : { *(.data1) }
@@ -44,7 +45,7 @@
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
 
-  . = ALIGN(8192);
+  . = ALIGN(PAGE_SIZE);
   __init_begin = .;
   .init.text : { 
 	_sinittext = .;
@@ -83,17 +84,17 @@
   __sun4v_2insn_patch_end = .;
 
 #ifdef CONFIG_BLK_DEV_INITRD
-  . = ALIGN(8192); 
+  . = ALIGN(PAGE_SIZE);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
 #endif
 
-  . = ALIGN(8192);
+  . = ALIGN(PAGE_SIZE);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
-  . = ALIGN(8192);
+  . = ALIGN(PAGE_SIZE);
   __init_end = .;
   __bss_start = .;
   .sbss      : { *(.sbss) *(.scommon) }
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 4a725d8..c4a6d6e 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -14,6 +14,6 @@
 	 NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \
 	 NGpage.o NGbzero.o \
 	 copy_in_user.o user_fixup.o memmove.o \
-	 mcount.o ipcsum.o rwsem.o xor.o delay.o
+	 mcount.o ipcsum.o rwsem.o xor.o
 
 obj-y += iomap.o
diff --git a/arch/sparc64/lib/delay.c b/arch/sparc64/lib/delay.c
deleted file mode 100644
index fb27e54..0000000
--- a/arch/sparc64/lib/delay.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* delay.c: Delay loops for sparc64
- *
- * Copyright (C) 2004, 2006 David S. Miller <davem@davemloft.net>
- *
- * Based heavily upon x86 variant which is:
- *	Copyright (C) 1993 Linus Torvalds
- *	Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- */
-
-#include <linux/delay.h>
-#include <asm/timer.h>
-
-void __delay(unsigned long loops)
-{
-	unsigned long bclock, now;
-	
-	bclock = tick_ops->get_tick();
-	do {
-		now = tick_ops->get_tick();
-	} while ((now-bclock) < loops);
-}
-
-/* We used to multiply by HZ after shifting down by 32 bits
- * but that runs into problems for higher values of HZ and
- * slow cpus.
- */
-void __const_udelay(unsigned long n)
-{
-	n *= 4;
-
-	n *= (cpu_data(raw_smp_processor_id()).udelay_val * (HZ/4));
-	n >>= 32;
-
-	__delay(n + 1);
-}
-
-void __udelay(unsigned long n)
-{
-	__const_udelay(n * 0x10c7UL);
-}
-
-
-void __ndelay(unsigned long n)
-{
-	__const_udelay(n * 0x5UL);
-}
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 6e5b01d..3010227 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -23,6 +23,7 @@
 #include <linux/kprobes.h>
 #include <linux/cache.h>
 #include <linux/sort.h>
+#include <linux/percpu.h>
 
 #include <asm/head.h>
 #include <asm/system.h>
@@ -43,8 +44,8 @@
 #include <asm/tsb.h>
 #include <asm/hypervisor.h>
 #include <asm/prom.h>
-
-extern void device_scan(void);
+#include <asm/sstate.h>
+#include <asm/mdesc.h>
 
 #define MAX_PHYS_ADDRESS	(1UL << 42UL)
 #define KPTE_BITMAP_CHUNK_SZ	(256UL * 1024UL * 1024UL)
@@ -60,8 +61,11 @@
 unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
-/* A special kernel TSB for 4MB and 256MB linear mappings.  */
-struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
+/* A special kernel TSB for 4MB and 256MB linear mappings.
+ * Space is allocated for this right after the trap table
+ * in arch/sparc64/kernel/head.S
+ */
+extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
 #endif
 
 #define MAX_BANKS	32
@@ -190,12 +194,9 @@
 }
 
 #define PG_dcache_dirty		PG_arch_1
-#define PG_dcache_cpu_shift	24UL
-#define PG_dcache_cpu_mask	(256UL - 1UL)
-
-#if NR_CPUS > 256
-#error D-cache dirty tracking and thread_info->cpu need fixing for > 256 cpus
-#endif
+#define PG_dcache_cpu_shift	32UL
+#define PG_dcache_cpu_mask	\
+	((1UL<<ilog2(roundup_pow_of_two(NR_CPUS)))-1UL)
 
 #define dcache_dirty_cpu(page) \
 	(((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
@@ -557,26 +558,11 @@
 				       unsigned long pte,
 				       unsigned long mmu)
 {
-	register unsigned long func asm("%o5");
-	register unsigned long arg0 asm("%o0");
-	register unsigned long arg1 asm("%o1");
-	register unsigned long arg2 asm("%o2");
-	register unsigned long arg3 asm("%o3");
+	unsigned long ret = sun4v_mmu_map_perm_addr(vaddr, 0, pte, mmu);
 
-	func = HV_FAST_MMU_MAP_PERM_ADDR;
-	arg0 = vaddr;
-	arg1 = 0;
-	arg2 = pte;
-	arg3 = mmu;
-	__asm__ __volatile__("ta	0x80"
-			     : "=&r" (func), "=&r" (arg0),
-			       "=&r" (arg1), "=&r" (arg2),
-			       "=&r" (arg3)
-			     : "0" (func), "1" (arg0), "2" (arg1),
-			       "3" (arg2), "4" (arg3));
-	if (arg0 != 0) {
+	if (ret != 0) {
 		prom_printf("hypervisor_tlb_lock[%lx:%lx:%lx:%lx]: "
-			    "errors with %lx\n", vaddr, 0, pte, mmu, arg0);
+			    "errors with %lx\n", vaddr, 0, pte, mmu, ret);
 		prom_halt();
 	}
 }
@@ -1313,20 +1299,16 @@
 
 void __cpuinit sun4v_ktsb_register(void)
 {
-	register unsigned long func asm("%o5");
-	register unsigned long arg0 asm("%o0");
-	register unsigned long arg1 asm("%o1");
-	unsigned long pa;
+	unsigned long pa, ret;
 
 	pa = kern_base + ((unsigned long)&ktsb_descr[0] - KERNBASE);
 
-	func = HV_FAST_MMU_TSB_CTX0;
-	arg0 = NUM_KTSB_DESCR;
-	arg1 = pa;
-	__asm__ __volatile__("ta	%6"
-			     : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
-			     : "0" (func), "1" (arg0), "2" (arg1),
-			       "i" (HV_FAST_TRAP));
+	ret = sun4v_mmu_tsb_ctx0(NUM_KTSB_DESCR, pa);
+	if (ret != 0) {
+		prom_printf("hypervisor_mmu_tsb_ctx0[%lx]: "
+			    "errors with %lx\n", pa, ret);
+		prom_halt();
+	}
 }
 
 /* paging_init() sets up the page tables */
@@ -1334,6 +1316,9 @@
 extern void cheetah_ecache_flush_init(void);
 extern void sun4v_patch_tlb_handlers(void);
 
+extern void cpu_probe(void);
+extern void central_probe(void);
+
 static unsigned long last_valid_pfn;
 pgd_t swapper_pg_dir[2048];
 
@@ -1345,9 +1330,24 @@
 	unsigned long end_pfn, pages_avail, shift, phys_base;
 	unsigned long real_end, i;
 
+	/* These build time checkes make sure that the dcache_dirty_cpu()
+	 * page->flags usage will work.
+	 *
+	 * When a page gets marked as dcache-dirty, we store the
+	 * cpu number starting at bit 32 in the page->flags.  Also,
+	 * functions like clear_dcache_dirty_cpu use the cpu mask
+	 * in 13-bit signed-immediate instruction fields.
+	 */
+	BUILD_BUG_ON(FLAGS_RESERVED != 32);
+	BUILD_BUG_ON(SECTIONS_WIDTH + NODES_WIDTH + ZONES_WIDTH +
+		     ilog2(roundup_pow_of_two(NR_CPUS)) > FLAGS_RESERVED);
+	BUILD_BUG_ON(NR_CPUS > 4096);
+
 	kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
 	kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
 
+	sstate_booting();
+
 	/* Invalidate both kernel TSBs.  */
 	memset(swapper_tsb, 0x40, sizeof(swapper_tsb));
 #ifndef CONFIG_DEBUG_PAGEALLOC
@@ -1416,8 +1416,13 @@
 
 	kernel_physical_mapping_init();
 
+	real_setup_per_cpu_areas();
+
 	prom_build_devicetree();
 
+	if (tlb_type == hypervisor)
+		sun4v_mdesc_init();
+
 	{
 		unsigned long zones_size[MAX_NR_ZONES];
 		unsigned long zholes_size[MAX_NR_ZONES];
@@ -1434,7 +1439,10 @@
 				    zholes_size);
 	}
 
-	device_scan();
+	prom_printf("Booting Linux...\n");
+
+	central_probe();
+	cpu_probe();
 }
 
 static void __init taint_real_pages(void)
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index 0b42137..33c5b7d 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -14,10 +14,34 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/system.h>
+#include <asm/ldc.h>
+
+int prom_service_exists(const char *service_name)
+{
+	int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
+			    P1275_INOUT(1, 1), service_name);
+
+	if (err)
+		return 0;
+	return 1;
+}
+
+void prom_sun4v_guest_soft_state(void)
+{
+	const char *svc = "SUNW,soft-state-supported";
+
+	if (!prom_service_exists(svc))
+		return;
+	p1275_cmd(svc, P1275_INOUT(0, 0));
+}
 
 /* Reset and reboot the machine with the command 'bcommand'. */
 void prom_reboot(const char *bcommand)
 {
+#ifdef CONFIG_SUN_LDOMS
+	if (ldom_domaining_enabled)
+		ldom_reboot(bcommand);
+#endif
 	p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
 		  P1275_INOUT(1, 0), bcommand);
 }
@@ -72,6 +96,10 @@
  */
 void prom_halt(void)
 {
+#ifdef CONFIG_SUN_LDOMS
+	if (ldom_domaining_enabled)
+		ldom_power_off();
+#endif
 again:
 	p1275_cmd("exit", P1275_INOUT(0, 0));
 	goto again; /* PROM is out to get me -DaveM */
@@ -79,6 +107,10 @@
 
 void prom_halt_power_off(void)
 {
+#ifdef CONFIG_SUN_LDOMS
+	if (ldom_domaining_enabled)
+		ldom_power_off();
+#endif
 	p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
 
 	/* if nothing else helps, we just halt */
diff --git a/arch/sparc64/prom/p1275.c b/arch/sparc64/prom/p1275.c
index 2b32c48..7fcccc0 100644
--- a/arch/sparc64/prom/p1275.c
+++ b/arch/sparc64/prom/p1275.c
@@ -16,6 +16,7 @@
 #include <asm/system.h>
 #include <asm/spitfire.h>
 #include <asm/pstate.h>
+#include <asm/ldc.h>
 
 struct {
 	long prom_callback;			/* 0x00 */
diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c
index 500f05e..17b7ecf 100644
--- a/arch/sparc64/prom/tree.c
+++ b/arch/sparc64/prom/tree.c
@@ -13,6 +13,7 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
+#include <asm/ldc.h>
 
 /* Return the child of node 'node' or zero if no this node has no
  * direct descendent.
@@ -261,9 +262,17 @@
 int
 prom_setprop(int node, const char *pname, char *value, int size)
 {
-	if(size == 0) return 0;
-	if((pname == 0) || (value == 0)) return 0;
+	if (size == 0)
+		return 0;
+	if ((pname == 0) || (value == 0))
+		return 0;
 	
+#ifdef CONFIG_SUN_LDOMS
+	if (ldom_domaining_enabled) {
+		ldom_set_var(pname, value);
+		return 0;
+	}
+#endif
 	return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
 					  P1275_ARG(2,P1275_ARG_IN_BUF)|
 					  P1275_INOUT(4, 1), 
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c504312..e6ff302 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -278,6 +278,7 @@
 config KERNEL_STACK_ORDER
 	int "Kernel stack size order"
 	default 1 if 64BIT
+	range 1 10 if 64BIT
 	default 0 if !64BIT
 	help
 	This option determines the size of UML kernel stacks.  They will
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 09c1aca..c86f5eb2 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -47,4 +47,13 @@
         If you're involved in UML kernel development and want to use gcov,
         say Y.  If you're unsure, say N.
 
+config DEBUG_STACK_USAGE
+	bool "Stack utilization instrumentation"
+	default N
+	help
+	  Track the maximum kernel stack usage - this will look at each
+	  kernel stack at process exit and log it if it's the deepest
+	  stack seen so far.
+
+	  This option will slow down process creation and destruction somewhat.
 endmenu
diff --git a/arch/um/config.release b/arch/um/config.release
deleted file mode 100644
index fc68bcb..0000000
--- a/arch/um/config.release
+++ /dev/null
@@ -1,333 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_USERMODE=y
-# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCI is not set
-CONFIG_UID16=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General Setup
-#
-CONFIG_STDIO_CONSOLE=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_SSL=y
-CONFIG_HOSTFS=y
-CONFIG_MCONSOLE=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_HOST_2G_2G is not set
-# CONFIG_UML_SMP is not set
-# CONFIG_SMP is not set
-CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
-CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
-CONFIG_NEST_LEVEL=0
-CONFIG_KERNEL_HALF_GIGS=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_KMOD=y
-
-#
-# Devices
-#
-CONFIG_BLK_DEV_UBD=y
-# CONFIG_BLK_DEV_UBD_SYNC is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_MMAPPER is not set
-CONFIG_UML_SOUND=y
-CONFIG_SOUND=y
-CONFIG_HOSTAUDIO=y
-# CONFIG_UML_WATCHDOG is not set
-# CONFIG_TTY_LOG is not set
-CONFIG_FD_CHAN=y
-# CONFIG_NULL_CHAN is not set
-CONFIG_PORT_CHAN=y
-CONFIG_PTY_CHAN=y
-CONFIG_TTY_CHAN=y
-CONFIG_XTERM_CHAN=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#  
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network device support
-#
-CONFIG_UML_NET=y
-CONFIG_UML_NET_ETHERTAP=y
-CONFIG_UML_NET_TUNTAP=y
-CONFIG_UML_NET_SLIP=y
-CONFIG_UML_NET_DAEMON=y
-CONFIG_UML_NET_MCAST=y
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=y
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PLIP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-# CONFIG_SLIP_MODE_SLIP6 is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-CONFIG_SHAPER=m
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-CONFIG_ADFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_BFS_FS=m
-CONFIG_EXT3_FS=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_UMSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_EFS_FS=m
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=m
-CONFIG_TMPFS=y
-CONFIG_RAMFS=m
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-CONFIG_MINIX_FS=m
-CONFIG_VXFS_FS=m
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-CONFIG_HPFS_FS=m
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_QNX4FS_FS=m
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-CONFIG_SYSV_FS=m
-CONFIG_UDF_FS=m
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-CONFIG_ZLIB_FS_INFLATE=m
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_PT_PROXY is not set
-# CONFIG_GPROF is not set
-# CONFIG_GCOV is not set
diff --git a/arch/um/defconfig b/arch/um/defconfig
index a54d0ef..a25cd25 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -189,7 +189,7 @@
 # CONFIG_NOCONFIG_CHAN is not set
 CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
 CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
+CONFIG_SSL_CHAN="pts"
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -527,3 +527,4 @@
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_GPROF is not set
 # CONFIG_GCOV is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 3aa3516..368d3e9 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -203,22 +203,37 @@
 	}
 }
 
-void enable_chan(struct line *line)
+int enable_chan(struct line *line)
 {
 	struct list_head *ele;
 	struct chan *chan;
+	int err;
 
 	list_for_each(ele, &line->chan_list){
 		chan = list_entry(ele, struct chan, list);
-		if(open_one_chan(chan))
+		err = open_one_chan(chan);
+		if (err) {
+			if (chan->primary)
+				goto out_close;
+
 			continue;
+		}
 
 		if(chan->enabled)
 			continue;
-		line_setup_irq(chan->fd, chan->input, chan->output, line,
-			       chan);
+		err = line_setup_irq(chan->fd, chan->input, chan->output, line,
+				     chan);
+		if (err)
+			goto out_close;
+
 		chan->enabled = 1;
 	}
+
+	return 0;
+
+ out_close:
+	close_chan(&line->chan_list, 0);
+	return err;
 }
 
 /* Items are added in IRQ context, when free_irq can't be called, and
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 13f0bf8..4d438f3 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -51,19 +51,21 @@
 /*
  * UML SIGWINCH handling
  *
- * The point of this is to handle SIGWINCH on consoles which have host ttys and
- * relay them inside UML to whatever might be running on the console and cares
- * about the window size (since SIGWINCH notifies about terminal size changes).
+ * The point of this is to handle SIGWINCH on consoles which have host
+ * ttys and relay them inside UML to whatever might be running on the
+ * console and cares about the window size (since SIGWINCH notifies
+ * about terminal size changes).
  *
- * So, we have a separate thread for each host tty attached to a UML device
- * (side-issue - I'm annoyed that one thread can't have multiple controlling
- * ttys for purposed of handling SIGWINCH, but I imagine there are other reasons
- * that doesn't make any sense).
+ * So, we have a separate thread for each host tty attached to a UML
+ * device (side-issue - I'm annoyed that one thread can't have
+ * multiple controlling ttys for the purpose of handling SIGWINCH, but
+ * I imagine there are other reasons that doesn't make any sense).
  *
- * SIGWINCH can't be received synchronously, so you have to set up to receive it
- * as a signal.  That being the case, if you are going to wait for it, it is
- * convenient to sit in sigsuspend() and wait for the signal to bounce you out of
- * it (see below for how we make sure to exit only on SIGWINCH).
+ * SIGWINCH can't be received synchronously, so you have to set up to
+ * receive it as a signal.  That being the case, if you are going to
+ * wait for it, it is convenient to sit in sigsuspend() and wait for
+ * the signal to bounce you out of it (see below for how we make sure
+ * to exit only on SIGWINCH).
  */
 
 static void winch_handler(int sig)
@@ -112,7 +114,8 @@
 
 	err = os_new_tty_pgrp(pty_fd, os_getpid());
 	if(err < 0){
-		printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
+		printk("winch_thread : new_tty_pgrp failed on fd %d, "
+		       "err = %d\n", pty_fd, -err);
 		exit(1);
 	}
 
@@ -126,8 +129,9 @@
 		       "err = %d\n", -count);
 
 	while(1){
-		/* This will be interrupted by SIGWINCH only, since other signals
-		 * are blocked.*/
+		/* This will be interrupted by SIGWINCH only, since
+		 * other signals are blocked.
+		 */
 		sigsuspend(&sigs);
 
 		count = os_write_file(pipe_fd, &c, sizeof(c));
@@ -137,10 +141,10 @@
 	}
 }
 
-static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
+static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
+		       unsigned long *stack_out)
 {
 	struct winch_data data;
-	unsigned long stack;
 	int fds[2], n, err;
 	char c;
 
@@ -153,9 +157,11 @@
 	data = ((struct winch_data) { .pty_fd 		= fd,
 				      .pipe_fd 		= fds[1] } );
 	/* CLONE_FILES so this thread doesn't hold open files which are open
-	 * now, but later closed.  This is a problem with /dev/net/tun.
+	 * now, but later closed in a different thread.  This is a
+	 * problem with /dev/net/tun, which if held open by this
+	 * thread, prevents the TUN/TAP device from being reused.
 	 */
-	err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0);
+	err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out);
 	if(err < 0){
 		printk("fork of winch_thread failed - errno = %d\n", -err);
 		goto out_close;
@@ -170,7 +176,13 @@
                 err = -EINVAL;
 		goto out_close;
 	}
-	return err ;
+
+	if (os_set_fd_block(*fd_out, 0)) {
+		printk("winch_tramp: failed to set thread_fd non-blocking.\n");
+		goto out_close;
+	}
+
+	return err;
 
  out_close:
 	os_close_file(fds[1]);
@@ -181,25 +193,25 @@
 
 void register_winch(int fd, struct tty_struct *tty)
 {
-	int pid, thread, thread_fd = -1;
-	int count;
+	unsigned long stack;
+	int pid, thread, count, thread_fd = -1;
 	char c = 1;
 
 	if(!isatty(fd))
 		return;
 
 	pid = tcgetpgrp(fd);
-	if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
-			     tty) && (pid == -1)){
-		thread = winch_tramp(fd, tty, &thread_fd);
-		if(thread > 0){
-			register_winch_irq(thread_fd, fd, thread, tty);
+	if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) &&
+	    (pid == -1)) {
+		thread = winch_tramp(fd, tty, &thread_fd, &stack);
+		if (thread < 0)
+			return;
 
-			count = os_write_file(thread_fd, &c, sizeof(c));
-			if(count != sizeof(c))
-				printk("register_winch : failed to write "
-				       "synchronization byte, err = %d\n",
-					-count);
-		}
+		register_winch_irq(thread_fd, fd, thread, tty, stack);
+
+		count = os_write_file(thread_fd, &c, sizeof(c));
+		if(count != sizeof(c))
+			printk("register_winch : failed to write "
+			       "synchronization byte, err = %d\n", -count);
 	}
 }
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index 1545384..ca8c9e1 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -8,7 +8,7 @@
 
 static inline void *cow_malloc(int size)
 {
-	return um_kmalloc(size);
+	return kmalloc(size, UM_GFP_KERNEL);
 }
 
 static inline void cow_free(void *ptr)
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index b869e38..8d2008f 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -35,7 +35,7 @@
 {
 	struct sockaddr_un *sun;
 
-	sun = um_kmalloc(sizeof(struct sockaddr_un));
+	sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
 	if(sun == NULL){
 		printk("new_addr: allocation of sockaddr_un failed\n");
 		return NULL;
@@ -83,7 +83,7 @@
 		goto out_close;
 	}
 
-	sun = um_kmalloc(sizeof(struct sockaddr_un));
+	sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
 	if(sun == NULL){
 		printk("new_addr: allocation of sockaddr_un failed\n");
 		err = -ENOMEM;
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 7f083ec..39c01ff 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -37,7 +37,7 @@
 		printk("fd_init : couldn't parse file descriptor '%s'\n", str);
 		return(NULL);
 	}
-	data = um_kmalloc(sizeof(*data));
+	data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
 	if(data == NULL) return(NULL);
 	*data = ((struct fd_chan) { .fd  	= n,
 				    .raw  	= opts->raw });
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index 5eeecf89..1171790 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -68,7 +68,7 @@
 		args = pid_args;
 	}
 
-	pid = run_helper(pre_exec, &data, args, NULL);
+	pid = run_helper(pre_exec, &data, args);
 
 	os_close_file(out_fds[0]);
 	os_close_file(in_fds[1]);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index ced9910..3e0b68e 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -3,6 +3,7 @@
  * Licensed under the GPL
  */
 
+#include "linux/kernel.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/list.h"
@@ -453,7 +454,10 @@
 	tty->driver_data = line;
 	line->tty = tty;
 
-	enable_chan(line);
+	err = enable_chan(line);
+	if (err)
+		return err;
+
 	INIT_DELAYED_WORK(&line->task, line_timer_cb);
 
 	if(!line->sigio){
@@ -745,8 +749,24 @@
 	int tty_fd;
 	int pid;
 	struct tty_struct *tty;
+	unsigned long stack;
 };
 
+static void free_winch(struct winch *winch, int free_irq_ok)
+{
+	list_del(&winch->list);
+
+	if (winch->pid != -1)
+		os_kill_process(winch->pid, 1);
+	if (winch->fd != -1)
+		os_close_file(winch->fd);
+	if (winch->stack != 0)
+		free_stack(winch->stack, 0);
+	if (free_irq_ok)
+		free_irq(WINCH_IRQ, winch);
+	kfree(winch);
+}
+
 static irqreturn_t winch_interrupt(int irq, void *data)
 {
 	struct winch *winch = data;
@@ -763,12 +783,13 @@
 				       "errno = %d\n", -err);
 				printk("fd %d is losing SIGWINCH support\n",
 				       winch->tty_fd);
+				free_winch(winch, 0);
 				return IRQ_HANDLED;
 			}
 			goto out;
 		}
 	}
-	tty  = winch->tty;
+	tty = winch->tty;
 	if (tty != NULL) {
 		line = tty->driver_data;
 		chan_window_size(&line->chan_list, &tty->winsize.ws_row,
@@ -781,43 +802,44 @@
 	return IRQ_HANDLED;
 }
 
-void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
+void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
+			unsigned long stack)
 {
 	struct winch *winch;
 
 	winch = kmalloc(sizeof(*winch), GFP_KERNEL);
 	if (winch == NULL) {
 		printk("register_winch_irq - kmalloc failed\n");
-		return;
+		goto cleanup;
 	}
 
 	*winch = ((struct winch) { .list  	= LIST_HEAD_INIT(winch->list),
 				   .fd  	= fd,
 				   .tty_fd 	= tty_fd,
 				   .pid  	= pid,
-				   .tty 	= tty });
+				   .tty 	= tty,
+				   .stack	= stack });
+
+	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
+			   IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			   "winch", winch) < 0) {
+		printk("register_winch_irq - failed to register IRQ\n");
+		goto out_free;
+	}
 
 	spin_lock(&winch_handler_lock);
 	list_add(&winch->list, &winch_handlers);
 	spin_unlock(&winch_handler_lock);
 
-	if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-			  "winch", winch) < 0)
-		printk("register_winch_irq - failed to register IRQ\n");
-}
+	return;
 
-static void free_winch(struct winch *winch)
-{
-	list_del(&winch->list);
-
-	if(winch->pid != -1)
-		os_kill_process(winch->pid, 1);
-	if(winch->fd != -1)
-		os_close_file(winch->fd);
-
-	free_irq(WINCH_IRQ, winch);
+ out_free:
 	kfree(winch);
+ cleanup:
+	os_kill_process(pid, 1);
+	os_close_file(fd);
+	if (stack != 0)
+		free_stack(stack, 0);
 }
 
 static void unregister_winch(struct tty_struct *tty)
@@ -830,7 +852,7 @@
 	list_for_each(ele, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
                 if(winch->tty == tty){
-			free_winch(winch);
+			free_winch(winch, 1);
 			break;
                 }
         }
@@ -846,7 +868,7 @@
 
 	list_for_each_safe(ele, next, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
-		free_winch(winch);
+		free_winch(winch, 1);
 	}
 
 	spin_unlock(&winch_handler_lock);
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index d319db1..236a3df 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -30,7 +30,7 @@
 {
 	struct sockaddr_in *sin;
 
-	sin = um_kmalloc(sizeof(struct sockaddr_in));
+	sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
 	if(sin == NULL){
 		printk("new_addr: allocation of sockaddr_in failed\n");
 		return NULL;
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 62e5ad6..f31e715 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -86,8 +86,9 @@
 	int len;
 
 	req->originlen = sizeof(req->origin);
-	req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
-			    (struct sockaddr *) req->origin, &req->originlen);
+	req->len = recvfrom(fd, &req->request, sizeof(req->request),
+			    MSG_DONTWAIT, (struct sockaddr *) req->origin,
+			    &req->originlen);
 	if (req->len < 0)
 		return 0;
 
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 3503cff..da946e3 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -187,7 +187,7 @@
 	}
 	pe_data.close_me = fds[0];
 	pe_data.stdout = fds[1];
-	pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
+	pid = run_helper(change_pre_exec, &pe_data, argv);
 
 	if (pid > 0)	/* Avoid hang as we won't get data in failure case. */
 		read_output(fds[0], output, output_len);
@@ -217,7 +217,7 @@
 		netmask[2], netmask[3]);
 
 	output_len = UM_KERN_PAGE_SIZE;
-	output = um_kmalloc(output_len);
+	output = kmalloc(output_len, UM_GFP_KERNEL);
 	if(output == NULL)
 		printk("change : failed to allocate output buffer\n");
 
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index 483aa15..1316456 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -53,7 +53,7 @@
 			return -EIO;
 		}
 
-		pri->compiled = um_kmalloc(sizeof(struct bpf_program));
+		pri->compiled = kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL);
 		if(pri->compiled == NULL){
 			printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
 			return -ENOMEM;
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 3f6357d..c799b00 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -50,7 +50,7 @@
 	if(kern_data == NULL)
 		return NULL;
 
-	data = um_kmalloc(sizeof(*data));
+	data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
 	if(data == NULL)
 		goto err;
 
@@ -188,7 +188,7 @@
 		{ .sock_fd  		= new,
 		  .pipe_fd 		= socket[1] });
 
-	err = run_helper(port_pre_exec, &data, argv, NULL);
+	err = run_helper(port_pre_exec, &data, argv);
 	if(err < 0)
 		goto out_shutdown;
 
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index df4976c..1e3fd61 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
@@ -7,12 +7,14 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <fcntl.h>
 #include <errno.h>
 #include <termios.h>
+#include <sys/stat.h>
 #include "chan_user.h"
-#include "user.h"
-#include "kern_util.h"
 #include "os.h"
+#include "user.h"
+#include "kern_constants.h"
 #include "um_malloc.h"
 
 struct pty_chan {
@@ -27,12 +29,14 @@
 {
 	struct pty_chan *data;
 
-	data = um_kmalloc(sizeof(*data));
-	if(data == NULL) return(NULL);
+	data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+	if (data == NULL)
+		return NULL;
+
 	*data = ((struct pty_chan) { .announce  	= opts->announce, 
 				     .dev  		= device,
 				     .raw  		= opts->raw });
-	return(data);
+	return data;
 }
 
 static int pts_open(int input, int output, int primary, void *d,
@@ -43,31 +47,35 @@
 	int fd, err;
 
 	fd = get_pty();
-	if(fd < 0){
+	if (fd < 0) {
 		err = -errno;
-		printk("open_pts : Failed to open pts\n");
+		printk(UM_KERN_ERR "open_pts : Failed to open pts\n");
 		return err;
 	}
-	if(data->raw){
+
+	if (data->raw) {
 		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
-		if(err)
-			return(err);
+		if (err)
+			return err;
 
 		err = raw(fd);
-		if(err)
-			return(err);
+		if (err)
+			return err;
 	}
 
 	dev = ptsname(fd);
 	sprintf(data->dev_name, "%s", dev);
 	*dev_out = data->dev_name;
+
 	if (data->announce)
 		(*data->announce)(dev, data->dev);
-	return(fd);
+
+	return fd;
 }
 
 static int getmaster(char *line)
 {
+	struct stat buf;
 	char *pty, *bank, *cp;
 	int master, err;
 
@@ -75,24 +83,29 @@
 	for (bank = "pqrs"; *bank; bank++) {
 		line[strlen("/dev/pty")] = *bank;
 		*pty = '0';
-		if (os_stat_file(line, NULL) < 0)
+		/* Did we hit the end ? */
+		if ((stat(line, &buf) < 0) && (errno == ENOENT))
 			break;
+
 		for (cp = "0123456789abcdef"; *cp; cp++) {
 			*pty = *cp;
-			master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
+			master = open(line, O_RDWR);
 			if (master >= 0) {
 				char *tp = &line[strlen("/dev/")];
 
 				/* verify slave side is usable */
 				*tp = 't';
-				err = os_access(line, OS_ACC_RW_OK);
+				err = access(line, R_OK | W_OK);
 				*tp = 'p';
-				if(err == 0) return(master);
-				(void) os_close_file(master);
+				if(!err)
+					return master;
+				close(master);
 			}
 		}
 	}
-	return(-1);
+
+	printk(UM_KERN_ERR "getmaster - no usable host pty devices\n");
+	return -ENOENT;
 }
 
 static int pty_open(int input, int output, int primary, void *d,
@@ -103,20 +116,22 @@
 	char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
 
 	fd = getmaster(dev);
-	if(fd < 0)
-		return(-errno);
+	if (fd < 0)
+		return fd;
 
 	if(data->raw){
 		err = raw(fd);
-		if(err)
-			return(err);
+		if (err)
+			return err;
 	}
 	
-	if(data->announce) (*data->announce)(dev, data->dev);
+	if (data->announce)
+		(*data->announce)(dev, data->dev);
 
 	sprintf(data->dev_name, "%s", dev);
 	*dev_out = data->dev_name;
-	return(fd);
+
+	return fd;
 }
 
 const struct chan_ops pty_ops = {
@@ -144,14 +159,3 @@
 	.free		= generic_free,
 	.winch		= 0,
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 78f0e51..c0b73c2 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -85,13 +85,13 @@
 	pe_data.stdin = fd;
 	pe_data.stdout = fds[1];
 	pe_data.close_me = fds[0];
-	err = run_helper(slip_pre_exec, &pe_data, argv, NULL);
+	err = run_helper(slip_pre_exec, &pe_data, argv);
 	if(err < 0)
 		goto out_close;
 	pid = err;
 
 	output_len = UM_KERN_PAGE_SIZE;
-	output = um_kmalloc(output_len);
+	output = kmalloc(output_len, UM_GFP_KERNEL);
 	if(output == NULL){
 		printk("slip_tramp : failed to allocate output buffer\n");
 		os_kill_process(pid, 1);
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 39f889f..0e462f6 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -42,7 +42,7 @@
 
 	pe_data.stdin = fd;
 	pe_data.stdout = fd;
-	pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL);
+	pid = run_helper(slirp_pre_exec, &pe_data, argv);
 
 	return(pid);
 }
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index fd09ad9..875d60d 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -42,8 +42,6 @@
 	.announce 	= ssl_announce,
 	.xterm_title	= "Serial Line #%d",
 	.raw		= 1,
-	.tramp_stack 	= 0,
-	.in_kernel 	= 1,
 };
 
 static int ssl_config(char *str, char **error_out);
@@ -99,7 +97,13 @@
 
 static int ssl_open(struct tty_struct *tty, struct file *filp)
 {
-	return line_open(serial_lines, tty);
+	int err = line_open(serial_lines, tty);
+
+	if (err)
+		printk(KERN_ERR "Failed to open serial line %d, err = %d\n",
+		       tty->index, err);
+
+	return err;
 }
 
 #if 0
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 9115392..4739dd5 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -1,3 +1,4 @@
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/console.h>
 
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 2bb4193..656036e 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -46,8 +46,6 @@
 	.announce 	= stdio_announce,
 	.xterm_title	= "Virtual Console #%d",
 	.raw		= 1,
-	.tramp_stack 	= 0,
-	.in_kernel 	= 1,
 };
 
 static int con_config(char *str, char **error_out);
@@ -101,7 +99,12 @@
 
 static int con_open(struct tty_struct *tty, struct file *filp)
 {
-	return line_open(vts, tty);
+	int err = line_open(vts, tty);
+	if (err)
+		printk(KERN_ERR "Failed to open console %d, err = %d\n",
+		       tty->index, err);
+
+	return err;
 }
 
 /* Set in an initcall, checked in an exitcall */
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index c07d0d5..a9f87e19 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -29,7 +29,7 @@
 	}
 	str++;
 
-	data = um_kmalloc(sizeof(*data));
+	data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
 	if(data == NULL)
 		return NULL;
 	*data = ((struct tty_chan) { .dev 	= str,
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 70509dd..fc27f6c 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -20,6 +20,7 @@
 #define MAJOR_NR UBD_MAJOR
 #define UBD_SHIFT 4
 
+#include "linux/kernel.h"
 #include "linux/module.h"
 #include "linux/blkdev.h"
 #include "linux/hdreg.h"
@@ -711,6 +712,8 @@
 	ubd_dev->queue->queuedata = ubd_dev;
 
 	blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG);
+	if(ubd_dev->cow.file != NULL)
+		blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long));
 	err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
 	if(err){
 		*error_out = "Failed to register device";
@@ -1082,7 +1085,7 @@
 {
 	struct io_thread_req *io_req;
 	struct request *req;
-	int n;
+	int n, last_sectors;
 
 	while(1){
 		struct ubd *dev = q->queuedata;
@@ -1098,9 +1101,11 @@
 		}
 
 		req = dev->request;
+		last_sectors = 0;
 		while(dev->start_sg < dev->end_sg){
 			struct scatterlist *sg = &dev->sg[dev->start_sg];
 
+			req->sector += last_sectors;
 			io_req = kmalloc(sizeof(struct io_thread_req),
 					 GFP_ATOMIC);
 			if(io_req == NULL){
@@ -1112,6 +1117,7 @@
 					(unsigned long long) req->sector << 9,
 					sg->offset, sg->length, sg->page);
 
+			last_sectors = sg->length >> 9;
 			n = os_write_file(thread_fd, &io_req,
 					  sizeof(struct io_thread_req *));
 			if(n != sizeof(struct io_thread_req *)){
@@ -1123,7 +1129,6 @@
 				return;
 			}
 
-			req->sector += sg->length >> 9;
 			dev->start_sg++;
 		}
 		dev->end_sg = 0;
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 4707b3f..41d254b 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -43,6 +43,12 @@
 	kernel_fd = fds[0];
 	*fd_out = fds[1];
 
+	err = os_set_fd_block(*fd_out, 0);
+	if (err) {
+		printk("start_io_thread - failed to set nonblocking I/O.\n");
+		goto out_close;
+	}
+
 	pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
 		    NULL);
 	if(pid < 0){
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 571c2b3..fd817e5 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -1,22 +1,20 @@
 /* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
-#include <stdio.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
 #include <termios.h>
-#include <signal.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include "kern_util.h"
 #include "chan_user.h"
-#include "user.h"
 #include "os.h"
+#include "init.h"
+#include "user.h"
 #include "xterm.h"
+#include "kern_constants.h"
 
 struct xterm_chan {
 	int pid;
@@ -25,25 +23,21 @@
 	int device;
 	int raw;
 	struct termios tt;
-	unsigned long stack;
-	int direct_rcv;
 };
 
-/* Not static because it's called directly by the tt mode gdb code */
-void *xterm_init(char *str, int device, const struct chan_opts *opts)
+static void *xterm_init(char *str, int device, const struct chan_opts *opts)
 {
 	struct xterm_chan *data;
 
 	data = malloc(sizeof(*data));
-	if(data == NULL) return(NULL);
-	*data = ((struct xterm_chan) { .pid 		= -1, 
+	if (data == NULL)
+		return NULL;
+	*data = ((struct xterm_chan) { .pid 		= -1,
 				       .helper_pid 	= -1,
-				       .device 		= device, 
+				       .device 		= device,
 				       .title 		= opts->xterm_title,
-				       .raw  		= opts->raw,
-				       .stack 		= opts->tramp_stack,
-				       .direct_rcv 	= !opts->in_kernel } );
-	return(data);
+				       .raw  		= opts->raw } );
+	return data;
 }
 
 /* Only changed by xterm_setup, which is a setup */
@@ -57,16 +51,22 @@
 	terminal_emulator = line;
 
 	line = strchr(line, ',');
-	if(line == NULL) return(0);
+	if (line == NULL)
+		return 0;
+
 	*line++ = '\0';
-	if(*line) title_switch = line;
+	if (*line)
+		title_switch = line;
 
 	line = strchr(line, ',');
-	if(line == NULL) return(0);
-	*line++ = '\0';
-	if(*line) exec_switch = line;
+	if (line == NULL)
+		return 0;
 
-	return(0);
+	*line++ = '\0';
+	if (*line)
+		exec_switch = line;
+
+	return 0;
 }
 
 __uml_setup("xterm=", xterm_setup,
@@ -82,107 +82,128 @@
 "    are 'xterm=gnome-terminal,-t,-x'.\n\n"
 );
 
-/* XXX This badly needs some cleaning up in the error paths
- * Not static because it's called directly by the tt mode gdb code
- */
-int xterm_open(int input, int output, int primary, void *d,
+static int xterm_open(int input, int output, int primary, void *d,
 		      char **dev_out)
 {
 	struct xterm_chan *data = d;
-	unsigned long stack;
 	int pid, fd, new, err;
 	char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
-	char *argv[] = { terminal_emulator, title_switch, title, exec_switch, 
+	char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
 			 "/usr/lib/uml/port-helper", "-uml-socket",
 			 file, NULL };
 
-	if(os_access(argv[4], OS_ACC_X_OK) < 0)
+	if (access(argv[4], X_OK) < 0)
 		argv[4] = "port-helper";
 
 	/* Check that DISPLAY is set, this doesn't guarantee the xterm
 	 * will work but w/o it we can be pretty sure it won't. */
-	if (!getenv("DISPLAY")) {
-		printk("xterm_open: $DISPLAY not set.\n");
+	if (getenv("DISPLAY") == NULL) {
+		printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n");
 		return -ENODEV;
 	}
 
+	/*
+	 * This business of getting a descriptor to a temp file,
+	 * deleting the file and closing the descriptor is just to get
+	 * a known-unused name for the Unix socket that we really
+	 * want.
+	 */
 	fd = mkstemp(file);
-	if(fd < 0){
+	if (fd < 0) {
 		err = -errno;
-		printk("xterm_open : mkstemp failed, errno = %d\n", errno);
+		printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n",
+		       errno);
 		return err;
 	}
 
-	if(unlink(file)){
+	if (unlink(file)) {
 		err = -errno;
-		printk("xterm_open : unlink failed, errno = %d\n", errno);
+		printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n",
+		       errno);
 		return err;
 	}
-	os_close_file(fd);
+	close(fd);
 
 	fd = os_create_unix_socket(file, sizeof(file), 1);
-	if(fd < 0){
-		printk("xterm_open : create_unix_socket failed, errno = %d\n", 
-		       -fd);
-		return(fd);
+	if (fd < 0) {
+		printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, "
+		       "errno = %d\n", -fd);
+		return fd;
 	}
 
 	sprintf(title, data->title, data->device);
-	stack = data->stack;
-	pid = run_helper(NULL, NULL, argv, &stack);
-	if(pid < 0){
-		printk("xterm_open : run_helper failed, errno = %d\n", -pid);
-		return(pid);
+	pid = run_helper(NULL, NULL, argv);
+	if (pid < 0) {
+		err = pid;
+		printk(UM_KERN_ERR "xterm_open : run_helper failed, "
+		       "errno = %d\n", -err);
+		goto out_close1;
 	}
 
-	if (data->direct_rcv) {
-		new = os_rcv_fd(fd, &data->helper_pid);
-	} else {
-		err = os_set_fd_block(fd, 0);
-		if(err < 0){
-			printk("xterm_open : failed to set descriptor "
-			       "non-blocking, err = %d\n", -err);
-			return(err);
-		}
-		new = xterm_fd(fd, &data->helper_pid);
+	err = os_set_fd_block(fd, 0);
+	if (err < 0) {
+		printk(UM_KERN_ERR "xterm_open : failed to set descriptor "
+		       "non-blocking, err = %d\n", -err);
+		goto out_kill;
 	}
-	if(new < 0){
-		printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
-		goto out;
+
+	new = xterm_fd(fd, &data->helper_pid);
+	if (new < 0) {
+		err = new;
+		printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
+		       -err);
+		goto out_kill;
+	}
+
+	err = os_set_fd_block(new, 0);
+	if (err) {
+		printk(UM_KERN_ERR "xterm_open : failed to set xterm "
+		       "descriptor non-blocking, err = %d\n", -err);
+		goto out_close2;
 	}
 
 	CATCH_EINTR(err = tcgetattr(new, &data->tt));
-	if(err){
+	if (err) {
 		new = err;
-		goto out;
+		goto out_close2;
 	}
 
-	if(data->raw){
+	if (data->raw) {
 		err = raw(new);
-		if(err){
+		if (err) {
 			new = err;
-			goto out;
+			goto out_close2;
 		}
 	}
 
+	unlink(file);
 	data->pid = pid;
 	*dev_out = NULL;
- out:
-	unlink(file);
-	return(new);
+
+	return new;
+
+ out_close2:
+	close(new);
+ out_kill:
+	os_kill_process(pid, 1);
+ out_close1:
+	close(fd);
+
+	return err;
 }
 
-/* Not static because it's called directly by the tt mode gdb code */
-void xterm_close(int fd, void *d)
+static void xterm_close(int fd, void *d)
 {
 	struct xterm_chan *data = d;
 	
-	if(data->pid != -1) 
+	if (data->pid != -1)
 		os_kill_process(data->pid, 1);
 	data->pid = -1;
-	if(data->helper_pid != -1) 
+
+	if (data->helper_pid != -1)
 		os_kill_process(data->helper_pid, 0);
 	data->helper_pid = -1;
+
 	os_close_file(fd);
 }
 
@@ -203,14 +224,3 @@
 	.free		= xterm_free,
 	.winch		= 1,
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index a4ce705..b646bcc 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -1,18 +1,14 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
-#include "linux/errno.h"
-#include "linux/slab.h"
-#include "linux/signal.h"
-#include "linux/interrupt.h"
-#include "asm/irq.h"
-#include "irq_user.h"
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <linux/irqreturn.h>
+#include <asm/irq.h>
 #include "irq_kern.h"
-#include "kern_util.h"
 #include "os.h"
-#include "xterm.h"
 
 struct xterm_wait {
 	struct completion ready;
@@ -27,12 +23,13 @@
 	int fd;
 
 	fd = os_rcv_fd(xterm->fd, &xterm->pid);
-	if(fd == -EAGAIN)
-		return(IRQ_NONE);
+	if (fd == -EAGAIN)
+		return IRQ_NONE;
 
 	xterm->new_fd = fd;
 	complete(&xterm->ready);
-	return(IRQ_HANDLED);
+
+	return IRQ_HANDLED;
 }
 
 int xterm_fd(int socket, int *pid_out)
@@ -41,22 +38,21 @@
 	int err, ret;
 
 	data = kmalloc(sizeof(*data), GFP_KERNEL);
-	if(data == NULL){
+	if (data == NULL) {
 		printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n");
-		return(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	/* This is a locked semaphore... */
-	*data = ((struct xterm_wait) 
-		{ .fd 		= socket,
-		  .pid 		= -1,
-		  .new_fd 	= -1 });
+	*data = ((struct xterm_wait) { .fd 		= socket,
+				       .pid 		= -1,
+				       .new_fd	 	= -1 });
 	init_completion(&data->ready);
 
-	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, 
+	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
 			     IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			     "xterm", data);
-	if (err){
+	if (err) {
 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
 		       "err = %d\n",  err);
 		ret = err;
@@ -76,16 +72,5 @@
  out:
 	kfree(data);
 
-	return(ret);
+	return ret;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index c4b41bb..624b510 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -40,7 +40,7 @@
 extern void deactivate_chan(struct list_head *chans, int irq);
 extern void reactivate_chan(struct list_head *chans, int irq);
 extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
-extern void enable_chan(struct line *line);
+extern int enable_chan(struct line *line);
 extern void close_chan(struct list_head *chans, int delay_free_irq);
 extern int chan_window_size(struct list_head *chans, 
 			     unsigned short *rows_out, 
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 38f16d8..5a2263e 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -12,8 +12,6 @@
 	void (*const announce)(char *dev_name, int dev);
 	char *xterm_title;
 	const int raw;
-	const unsigned long tramp_stack;
-	const int in_kernel;
 };
 
 enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
@@ -44,7 +42,8 @@
 
 struct tty_struct;
 extern void register_winch(int fd,  struct tty_struct *tty);
-extern void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty);
+extern void register_winch_irq(int fd, int tty_fd, int pid,
+			       struct tty_struct *tty, unsigned long stack);
 
 #define __channel_help(fn, prefix) \
 __uml_help(fn, prefix "[0-9]*=<channel description>\n" \
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 541f4a8..6eee343 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -9,6 +9,7 @@
 OFFSET(HOST_TASK_PID, task_struct, pid);
 
 DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
+DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
 DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
 
 DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
@@ -26,6 +27,9 @@
 
 DEFINE(UM_NR_CPUS, NR_CPUS);
 
+DEFINE(UM_GFP_KERNEL, GFP_KERNEL);
+DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC);
+
 /* For crypto assembler code. */
 DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
 
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 4d9fb263..930b261 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -239,11 +239,9 @@
 /* execvp.c */
 extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
 /* helper.c */
-extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-		      unsigned long *stack_out);
+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
 extern int run_helper_thread(int (*proc)(void *), void *arg,
-			     unsigned int flags, unsigned long *stack_out,
-			     int stack_order);
+			     unsigned int flags, unsigned long *stack_out);
 extern int helper_wait(int pid);
 
 
diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h
index e6d7c5a..0ad17cb 100644
--- a/arch/um/include/um_malloc.h
+++ b/arch/um/include/um_malloc.h
@@ -6,11 +6,17 @@
 #ifndef __UM_MALLOC_H__
 #define __UM_MALLOC_H__
 
-extern void *um_kmalloc(int size);
-extern void *um_kmalloc_atomic(int size);
+#include "kern_constants.h"
+
+extern void *__kmalloc(int size, int flags);
+static inline void *kmalloc(int size, int flags)
+{
+	return __kmalloc(size, flags);
+}
+
 extern void kfree(const void *ptr);
 
-extern void *um_vmalloc(int size);
+extern void *vmalloc(unsigned long size);
 extern void vfree(void *ptr);
 
 #endif /* __UM_MALLOC_H__ */
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 87a4e44..2454774 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -62,7 +62,7 @@
   } =0x90909090
   .plt            : { *(.plt) }
   .text           : {
-    *(.text)
+    TEXT_TEXT
     SCHED_TEXT
     LOCK_TEXT
     *(.fixup)
@@ -99,7 +99,8 @@
     *(.data.init_task)
     . = ALIGN(KERNEL_STACK_SIZE);
     *(.data.init_irqstack)
-    *(.data .data.* .gnu.linkonce.d.*)
+    DATA_DATA
+    *(.data.* .gnu.linkonce.d.*)
     SORT(CONSTRUCTORS)
   }
   .data1          : { *(.data1) }
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index 8b7f2cd..c716b5a 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -1,8 +1,9 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 
+#include "linux/kernel.h"
 #include "linux/init.h"
 #include "linux/ctype.h"
 #include "linux/proc_fs.h"
@@ -24,11 +25,14 @@
 	val = uml_exitcode;
 	len = sprintf(page, "%d\n", val);
 	len -= off;
-	if(len <= off+count) *eof = 1;
+	if(len <= off+count)
+		*eof = 1;
 	*start = page + off;
-	if(len > count) len = count;
-	if(len < 0) len = 0;
-	return(len);
+	if(len > count)
+		len = count;
+	if(len < 0)
+		len = 0;
+	return len;
 }
 
 static int write_proc_exitcode(struct file *file, const char __user *buffer,
@@ -38,12 +42,14 @@
 	int tmp;
 
 	if(copy_from_user(buf, buffer, count))
-		return(-EFAULT);
+		return -EFAULT;
+
 	tmp = simple_strtol(buf, &end, 0);
 	if((*end != '\0') && !isspace(*end))
-		return(-EINVAL);
+		return -EINVAL;
+
 	uml_exitcode = tmp;
-	return(count);
+	return count;
 }
 
 static int make_proc_exitcode(void)
@@ -54,24 +60,13 @@
 	if(ent == NULL){
 		printk(KERN_WARNING "make_proc_exitcode : Failed to register "
 		       "/proc/exitcode\n");
-		return(0);
+		return 0;
 	}
 
 	ent->read_proc = read_proc_exitcode;
 	ent->write_proc = write_proc_exitcode;
-	
-	return(0);
+
+	return 0;
 }
 
 __initcall(make_proc_exitcode);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index dba04d8..9870feb 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -30,7 +30,6 @@
 #include "irq_kern.h"
 #include "os.h"
 #include "sigio.h"
-#include "um_malloc.h"
 #include "misc_constants.h"
 #include "as-layout.h"
 
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 8d2c549..bfa52f2 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -46,7 +46,6 @@
 #include "mode.h"
 #include "mode_kern.h"
 #include "choose-mode.h"
-#include "um_malloc.h"
 
 /* This is a per-cpu array.  A processor only modifies its entry and it only
  * cares about its entry, so it's OK if another processor is modifying its
@@ -262,21 +261,6 @@
 {
 }
 
-void *um_kmalloc(int size)
-{
-	return kmalloc(size, GFP_KERNEL);
-}
-
-void *um_kmalloc_atomic(int size)
-{
-	return kmalloc(size, GFP_ATOMIC);
-}
-
-void *um_vmalloc(int size)
-{
-	return vmalloc(size);
-}
-
 int __cant_sleep(void) {
 	return in_atomic() || irqs_disabled() || in_interrupt();
 	/* Is in_interrupt() really needed? */
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 627742d..6916c88 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -52,17 +52,9 @@
 	switch (request) {
 		/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
-		int copied;
-
-		ret = -EIO;
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp, p);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
         case PTRACE_PEEKUSR:
@@ -72,11 +64,7 @@
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		ret = -EIO;
-		if (access_process_vm(child, addr, &data, sizeof(data), 
-				      1) != sizeof(data))
-			break;
-		ret = 0;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index bc59f97..307b937 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -37,7 +37,7 @@
 
   .text      :
   {
-    *(.text)
+    TEXT_TEXT
     SCHED_TEXT
     LOCK_TEXT
     *(.fixup)
@@ -61,7 +61,7 @@
     *(.data.init_task)
     . = ALIGN(KERNEL_STACK_SIZE);
     *(.data.init_irqstack)
-    *(.data)
+    DATA_DATA
     *(.gnu.linkonce.d*)
     CONSTRUCTORS
   }
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 9bf944f..b126df4 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -177,6 +177,7 @@
 static int aio_req_fd_r = -1;
 static int aio_req_fd_w = -1;
 static int aio_pid = -1;
+static unsigned long aio_stack;
 
 static int not_aio_thread(void *arg)
 {
@@ -212,7 +213,6 @@
 
 static int init_aio_24(void)
 {
-	unsigned long stack;
 	int fds[2], err;
 
 	err = os_pipe(fds, 1, 1);
@@ -227,7 +227,7 @@
 		goto out_close_pipe;
 
 	err = run_helper_thread(not_aio_thread, NULL,
-				CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+				CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
 	if(err < 0)
 		goto out_close_pipe;
 
@@ -252,7 +252,6 @@
 #define DEFAULT_24_AIO 0
 static int init_aio_26(void)
 {
-	unsigned long stack;
 	int err;
 
 	if(io_setup(256, &ctx)){
@@ -263,7 +262,7 @@
 	}
 
 	err = run_helper_thread(aio_thread, NULL,
-				CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+				CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
 	if(err < 0)
 		return err;
 
@@ -365,8 +364,10 @@
 
 static void exit_aio(void)
 {
-	if(aio_pid != -1)
+	if (aio_pid != -1) {
 		os_kill_process(aio_pid, 1);
+		free_stack(aio_stack, 0);
+	}
 }
 
 __uml_exitcall(exit_aio);
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index acba301..61d3953 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -54,7 +54,7 @@
 		return;
 	}
 
-	output = um_kmalloc(UM_KERN_PAGE_SIZE);
+	output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL);
 	if(output == NULL)
 		printk("etap_change : Failed to allocate output buffer\n");
 	read_output(fd, output, UM_KERN_PAGE_SIZE);
@@ -117,7 +117,7 @@
 	pe_data.control_remote = control_remote;
 	pe_data.control_me = control_me;
 	pe_data.data_me = data_me;
-	pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
+	pid = run_helper(etap_pre_exec, &pe_data, args);
 
 	if(pid < 0)
 		err = pid;
@@ -166,7 +166,7 @@
 	err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], 
 			 control_fds[1], data_fds[0], data_fds[1]);
 	output_len = UM_KERN_PAGE_SIZE;
-	output = um_kmalloc(output_len);
+	output = kmalloc(output_len, UM_GFP_KERNEL);
 	read_output(control_fds[0], output, output_len);
 
 	if(output == NULL)
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 11a9779..f848b4e 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -83,7 +83,7 @@
 	data.stdout = remote;
 	data.close_me = me;
 
-	pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
+	pid = run_helper(tuntap_pre_exec, &data, argv);
 
 	if(pid < 0)
 		return -pid;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 97bed16..d81af7b 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -44,17 +44,13 @@
 /* Returns either the pid of the child process we run or -E* on failure.
  * XXX The alloc_stack here breaks if this is called in the tracing thread, so
  * we need to receive a preallocated stack (a local buffer is ok). */
-int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-	       unsigned long *stack_out)
+int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
 {
 	struct helper_data data;
 	unsigned long stack, sp;
 	int pid, fds[2], ret, n;
 
-	if ((stack_out != NULL) && (*stack_out != 0))
-		stack = *stack_out;
-	else
-		stack = alloc_stack(0, __cant_sleep());
+	stack = alloc_stack(0, __cant_sleep());
 	if (stack == 0)
 		return -ENOMEM;
 
@@ -76,8 +72,8 @@
 	data.pre_data = pre_data;
 	data.argv = argv;
 	data.fd = fds[1];
-	data.buf = __cant_sleep() ? um_kmalloc_atomic(PATH_MAX) :
-					um_kmalloc(PATH_MAX);
+	data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
+					kmalloc(PATH_MAX, UM_GFP_KERNEL);
 	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
 	if (pid < 0) {
 		ret = -errno;
@@ -113,22 +109,21 @@
 		close(fds[1]);
 	close(fds[0]);
 out_free:
-	if ((stack_out == NULL) || (*stack_out == 0))
-		free_stack(stack, 0);
+	free_stack(stack, 0);
 	return ret;
 }
 
 int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
-		      unsigned long *stack_out, int stack_order)
+		      unsigned long *stack_out)
 {
 	unsigned long stack, sp;
 	int pid, status, err;
 
-	stack = alloc_stack(stack_order, __cant_sleep());
+	stack = alloc_stack(0, __cant_sleep());
 	if (stack == 0)
 		return -ENOMEM;
 
-	sp = stack + (UM_KERN_PAGE_SIZE << stack_order) - sizeof(void *);
+	sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *);
 	pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
 	if (pid < 0) {
 		err = -errno;
@@ -147,7 +142,7 @@
 		if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
 			printk("run_helper_thread - thread returned status "
 			       "0x%x\n", status);
-		free_stack(stack, stack_order);
+		free_stack(stack, 0);
 	} else
 		*stack_out = stack;
 	return pid;
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index ea9a236..e85f499 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -24,6 +24,7 @@
 #include "uml-config.h"
 #include "os.h"
 #include "um_malloc.h"
+#include "kern_constants.h"
 
 /* Set in main, unchanged thereafter */
 char *linux_prog;
@@ -232,9 +233,10 @@
 
 	if(!CAN_KMALLOC())
 		return __real_malloc(size);
-	else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
-		ret = um_kmalloc(size);
-	else ret = um_vmalloc(size);
+	else if(size <= UM_KERN_PAGE_SIZE)
+		/* finding contiguous pages can be hard*/
+		ret = kmalloc(size, UM_GFP_KERNEL);
+	else ret = vmalloc(size);
 
 	/* glibc people insist that if malloc fails, errno should be
 	 * set by malloc as well. So we do.
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 8d4e0c6..dc03e9c 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -26,6 +26,7 @@
  * exitcall.
  */
 static int write_sigio_pid = -1;
+static unsigned long write_sigio_stack;
 
 /* These arrays are initialized before the sigio thread is started, and
  * the descriptors closed after it is killed.  So, it can't see them change.
@@ -104,7 +105,7 @@
 	if(n <= polls->size)
 		return 0;
 
-	new = um_kmalloc_atomic(n * sizeof(struct pollfd));
+	new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
 	if(new == NULL){
 		printk("need_poll : failed to allocate new pollfds\n");
 		return -ENOMEM;
@@ -144,8 +145,10 @@
 	return;
  fail:
 	/* Critical section start */
-	if(write_sigio_pid != -1)
+	if (write_sigio_pid != -1) {
 		os_kill_process(write_sigio_pid, 1);
+		free_stack(write_sigio_stack, 0);
+	}
 	write_sigio_pid = -1;
 	close(sigio_private[0]);
 	close(sigio_private[1]);
@@ -230,7 +233,7 @@
 {
 	struct pollfd *p;
 
-	p = um_kmalloc(sizeof(struct pollfd));
+	p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
 	if (p == NULL) {
 		printk("setup_initial_poll : failed to allocate poll\n");
 		return NULL;
@@ -243,7 +246,6 @@
 
 static void write_sigio_workaround(void)
 {
-	unsigned long stack;
 	struct pollfd *p;
 	int err;
 	int l_write_sigio_fds[2];
@@ -293,7 +295,8 @@
 	memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
 
 	write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
-					    CLONE_FILES | CLONE_VM, &stack, 0);
+					    CLONE_FILES | CLONE_VM,
+					    &write_sigio_stack);
 
 	if (write_sigio_pid < 0)
 		goto out_clear;
@@ -356,10 +359,12 @@
 
 static void sigio_cleanup(void)
 {
-	if(write_sigio_pid != -1){
-		os_kill_process(write_sigio_pid, 1);
-		write_sigio_pid = -1;
-	}
+	if (write_sigio_pid == -1)
+		return;
+
+	os_kill_process(write_sigio_pid, 1);
+	free_stack(write_sigio_stack, 0);
+	write_sigio_pid = -1;
 }
 
 __uml_exitcall(sigio_cleanup);
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 5c894632..0f7df4e 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -25,6 +25,7 @@
 #include "sysdep/ptrace.h"
 #include "sysdep/stub.h"
 #include "init.h"
+#include "kern_constants.h"
 
 extern unsigned long batch_syscall_stub, __syscall_stub_start;
 
@@ -149,8 +150,8 @@
 	*stack = 0;
 	multi_op_count++;
 
-	if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
-		     PAGE_SIZE - 10 * sizeof(long))){
+	if(!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) <
+		     UM_KERN_PAGE_SIZE - 10 * sizeof(long))){
 		*addr = stack;
 		return 0;
 	}
@@ -168,8 +169,8 @@
 	/* If *addr still is uninitialized, it *must* contain NULL.
 	 * Thus in this case do_syscall_stub correctly won't be called.
 	 */
-	if((((unsigned long) *addr) & ~PAGE_MASK) >=
-	   PAGE_SIZE - (10 + data_count) * sizeof(long)) {
+	if((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >=
+	   UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) {
 		ret = do_syscall_stub(mm_idp, addr);
 		/* in case of error, don't overwrite data on stack */
 		if(ret)
@@ -183,8 +184,8 @@
 
 	memcpy(stack + 1, data, data_count * sizeof(long));
 
-	*stub_addr = (void *)(((unsigned long)(stack + 1) & ~PAGE_MASK) +
-			      UML_CONFIG_STUB_DATA);
+	*stub_addr = (void *)(((unsigned long)(stack + 1) &
+			       ~UM_KERN_PAGE_MASK) + UML_CONFIG_STUB_DATA);
 
 	return 0;
 }
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index f9d2f85..ba9af8d 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -41,7 +41,7 @@
 	if(pid != os_getpgrp())
 		return(0);
 
-	register_winch_irq(-1, fd, -1, data);
+	register_winch_irq(-1, fd, -1, data, 0);
 	return(1);
 }
 
@@ -252,11 +252,12 @@
 	unsigned long sp;
 	int pid, status, n, flags;
 
-	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+	stack = mmap(NULL, UM_KERN_PAGE_SIZE,
+		     PROT_READ | PROT_WRITE | PROT_EXEC,
 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	if(stack == MAP_FAILED)
 		panic("start_userspace : mmap failed, errno = %d", errno);
-	sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
+	sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
 
 	flags = CLONE_FILES | SIGCHLD;
 	if(proc_mm) flags |= CLONE_VM;
@@ -279,7 +280,7 @@
 		panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
 		      errno);
 
-	if(munmap(stack, PAGE_SIZE) < 0)
+	if(munmap(stack, UM_KERN_PAGE_SIZE) < 0)
 		panic("start_userspace : munmap failed, errno = %d\n", errno);
 
 	return(pid);
@@ -365,7 +366,7 @@
 	thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
 				(unsigned long) stub_clone_handler -
 				(unsigned long) &__syscall_stub_start;
-	thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
+	thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE -
 		sizeof(void *);
 #ifdef __SIGNAL_FRAMESIZE
 	thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
@@ -453,7 +454,7 @@
 				      .u         =
 				      { .mmap    =
 					{ .addr    = code,
-					  .len     = PAGE_SIZE,
+					  .len     = UM_KERN_PAGE_SIZE,
 					  .prot    = PROT_EXEC,
 					  .flags   = MAP_FIXED | MAP_PRIVATE,
 					  .fd      = code_fd,
@@ -476,7 +477,7 @@
 				  .u         =
 				  { .mmap    =
 				    { .addr    = data,
-				      .len     = PAGE_SIZE,
+				      .len     = UM_KERN_PAGE_SIZE,
 				      .prot    = PROT_READ | PROT_WRITE,
 				      .flags   = MAP_FIXED | MAP_SHARED,
 				      .fd      = map_fd,
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 79471f8..46f6139 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -107,11 +107,12 @@
 	unsigned long sp;
 	int pid, n, status;
 
-	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+	stack = mmap(NULL, UM_KERN_PAGE_SIZE,
+		     PROT_READ | PROT_WRITE | PROT_EXEC,
 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	if(stack == MAP_FAILED)
 		fatal_perror("check_ptrace : mmap failed");
-	sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
+	sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
 	pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
 	if(pid < 0)
 		fatal_perror("start_ptraced_child : clone failed");
@@ -144,9 +145,7 @@
 		int exit_with = WEXITSTATUS(status);
 		if (exit_with == 2)
 			non_fatal("check_ptrace : child exited with status 2. "
-				  "Serious trouble happening! Try updating "
-				  "your host skas patch!\nDisabling SYSEMU "
-				  "support.");
+				  "\nDisabling SYSEMU support.\n");
 		non_fatal("check_ptrace : child exited with exitcode %d, while "
 			  "expecting %d; status 0x%x\n", exit_with,
 			  exitcode, status);
@@ -155,7 +154,7 @@
 		ret = -1;
 	}
 
-	if(munmap(stack, PAGE_SIZE) < 0)
+	if(munmap(stack, UM_KERN_PAGE_SIZE) < 0)
 		fatal_perror("check_ptrace : munmap failed");
 	return ret;
 }
@@ -209,6 +208,7 @@
 static void __init check_sysemu(void)
 {
 	void *stack;
+	unsigned long regs[MAX_REG_NR];
 	int pid, n, status, count=0;
 
 	non_fatal("Checking syscall emulation patch for ptrace...");
@@ -225,11 +225,20 @@
 		fatal("check_sysemu : expected SIGTRAP, got status = %d",
 		      status);
 
-	n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
-		   os_getpid());
-	if(n < 0)
-		fatal_perror("check_sysemu : failed to modify system call "
-			     "return");
+	if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+		fatal_perror("check_sysemu : PTRACE_GETREGS failed");
+	if(PT_SYSCALL_NR(regs) != __NR_getpid){
+		non_fatal("check_sysemu got system call number %d, "
+			  "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid);
+		goto fail;
+	}
+
+	n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
+	if(n < 0){
+		non_fatal("check_sysemu : failed to modify system call "
+			  "return");
+		goto fail;
+	}
 
 	if (stop_ptraced_child(pid, stack, 0, 0) < 0)
 		goto fail_stopped;
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 3f33165..419b2d5 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -5,7 +5,8 @@
  * so I *must* declare good prototypes for them and then EXPORT them.
  * The kernel code uses the macro defined by include/linux/string.h,
  * so I undef macros; the userspace code does not include that and I
- * add an EXPORT for the glibc one.*/
+ * add an EXPORT for the glibc one.
+ */
 
 #undef strlen
 #undef strstr
@@ -61,12 +62,18 @@
 EXPORT_SYMBOL_PROTO(__xstat);
 EXPORT_SYMBOL_PROTO(__lxstat);
 EXPORT_SYMBOL_PROTO(__lxstat64);
+EXPORT_SYMBOL_PROTO(__fxstat64);
 EXPORT_SYMBOL_PROTO(lseek);
 EXPORT_SYMBOL_PROTO(lseek64);
 EXPORT_SYMBOL_PROTO(chown);
+EXPORT_SYMBOL_PROTO(fchown);
 EXPORT_SYMBOL_PROTO(truncate);
+EXPORT_SYMBOL_PROTO(ftruncate64);
 EXPORT_SYMBOL_PROTO(utime);
+EXPORT_SYMBOL_PROTO(utimes);
+EXPORT_SYMBOL_PROTO(futimes);
 EXPORT_SYMBOL_PROTO(chmod);
+EXPORT_SYMBOL_PROTO(fchmod);
 EXPORT_SYMBOL_PROTO(rename);
 EXPORT_SYMBOL_PROTO(__xmknod);
 
@@ -102,14 +109,3 @@
 
 extern long __guard __attribute__((weak));
 EXPORT_SYMBOL(__guard);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index a9b0934..a458ac9 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -117,24 +117,16 @@
 	int rval;
 
 	switch (request) {
-		unsigned long val, copied;
+		unsigned long val;
 
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
 	case PTRACE_PEEKDATA:
-		copied = access_process_vm(child, addr, &val, sizeof(val), 0);
-		rval = -EIO;
-		if (copied != sizeof(val))
-			break;
-		rval = put_user(val, (unsigned long *)data);
+		rval = generic_ptrace_peekdata(child, addr, data);
 		goto out;
 
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		rval = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1)
-		    == sizeof(data))
-			break;
-		rval = -EIO;
+		rval = generic_ptrace_pokedata(child, addr, data);
 		goto out;
 
 	/* Read/write the word at location ADDR in the registers.  */
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
index 3563082..6172599 100644
--- a/arch/v850/kernel/vmlinux.lds.S
+++ b/arch/v850/kernel/vmlinux.lds.S
@@ -92,7 +92,7 @@
 #define TEXT_CONTENTS							      \
 		_text = .;						      \
 		__stext = . ;						      \
-        	*(.text)						      \
+		TEXT_TEXT						      \
 		SCHED_TEXT						      \
 			*(.exit.text)	/* 2.5 convention */		      \
 			*(.text.exit)	/* 2.4 convention */		      \
@@ -113,7 +113,7 @@
 /* Kernel data segment.  */
 #define DATA_CONTENTS							      \
 		__sdata = . ;						      \
-        	*(.data)						      \
+		DATA_DATA						      \
 			*(.exit.data)	/* 2.5 convention */		      \
 			*(.data.exit)	/* 2.4 convention */		      \
 		. = ALIGN (16) ;					      \
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 145bb82..14bf8ce 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -427,13 +427,20 @@
 	  This is purely to save memory - each supported CPU requires
 	  memory in the static kernel configuration.
 
+config PHYSICAL_ALIGN
+	hex
+	default "0x200000"
+
 config HOTPLUG_CPU
-	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+	bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)"
 	depends on SMP && HOTPLUG && EXPERIMENTAL
 	help
 		Say Y here to experiment with turning CPUs off and on.  CPUs
 		can be controlled through /sys/devices/system/cpu/cpu#.
-		Say N if you want to disable CPU hotplug.
+		This is also required for suspend/hibernation on SMP systems.
+
+		Say N if you want to disable CPU hotplug and don't need to
+		suspend.
 
 config ARCH_ENABLE_MEMORY_HOTPLUG
 	def_bool y
@@ -767,8 +774,8 @@
 source "arch/x86_64/oprofile/Kconfig"
 
 config KPROBES
-	bool "Kprobes (EXPERIMENTAL)"
-	depends on KALLSYMS && EXPERIMENTAL && MODULES
+	bool "Kprobes"
+	depends on KALLSYMS && MODULES
 	help
 	  Kprobes allows you to trap at almost any kernel address and
 	  execute a callback function.  register_kprobe() establishes
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index ee6f650..6709638 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -1,135 +1,9 @@
 #
 # arch/x86_64/boot/Makefile
 #
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1994 by Linus Torvalds
-#
+# The actual boot code is shared with i386 including the Makefile.
+# So tell kbuild that we fetch the code from i386 and include the
+# Makefile from i386 too.
 
-# ROOT_DEV specifies the default root-device when making the image.
-# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
-# the default of FLOPPY is used by 'build'.
-
-ROOT_DEV := CURRENT
-
-# If you want to preset the SVGA mode, uncomment the next line and
-# set SVGA_MODE to whatever number you want.
-# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
-# The number is the same as you would ordinarily press at bootup.
-
-SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
-
-# If you want the RAM disk device, define this to be the size in blocks.
-
-#RAMDISK := -DRAMDISK=512
-
-targets		:= vmlinux.bin bootsect bootsect.o \
-		   setup setup.o bzImage mtools.conf
-
-EXTRA_CFLAGS := -m32
-
-hostprogs-y	:= tools/build
-HOST_EXTRACFLAGS += $(LINUXINCLUDE)
-subdir-		:= compressed/	#Let make clean descend in compressed/
-# ---------------------------------------------------------------------------
-
-$(obj)/bzImage: IMAGE_OFFSET := 0x100000
-$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
-$(obj)/bzImage: BUILDFLAGS   := -b
-
-quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
-	    $(obj)/vmlinux.bin $(ROOT_DEV) > $@
-
-$(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
-			      $(obj)/vmlinux.bin $(obj)/tools/build FORCE
-	$(call if_changed,image)
-	@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
-
-$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
-	$(call if_changed,objcopy)
-
-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
-LDFLAGS_setup	 := -Ttext 0x0 -s --oformat binary -e begtext
-
-$(obj)/setup $(obj)/bootsect: %: %.o FORCE
-	$(call if_changed,ld)
-
-$(obj)/compressed/vmlinux: FORCE
-	$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
-
-# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel
-FDARGS = 
-# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel
-FDINITRD =
-
-image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,)
-
-$(obj)/mtools.conf: $(src)/mtools.conf.in
-	sed -e 's|@OBJ@|$(obj)|g' < $< > $@
-
-# This requires write access to /dev/fd0
-zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
-	MTOOLSRC=$(obj)/mtools.conf mformat a:			; sync
-	syslinux /dev/fd0					; sync
-	echo '$(image_cmdline)' | \
-		MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg
-	if [ -f '$(FDINITRD)' ] ; then \
-		MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \
-	fi
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
-
-# These require being root or having syslinux 2.02 or higher installed
-fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
-	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
-	MTOOLSRC=$(obj)/mtools.conf mformat v:			; sync
-	syslinux $(obj)/fdimage					; sync
-	echo '$(image_cmdline)' | \
-		MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
-	if [ -f '$(FDINITRD)' ] ; then \
-		MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \
-	fi
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
-
-fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
-	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
-	MTOOLSRC=$(obj)/mtools.conf mformat w:			; sync
-	syslinux $(obj)/fdimage					; sync
-	echo '$(image_cmdline)' | \
-		MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
-	if [ -f '$(FDINITRD)' ] ; then \
-		MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \
-	fi
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
-
-isoimage: $(BOOTIMAGE)
-	-rm -rf $(obj)/isoimage
-	mkdir $(obj)/isoimage
-	for i in lib lib64 share end ; do \
-		if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
-			cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
-			break ; \
-		fi ; \
-		if [ $$i = end ] ; then exit 1 ; fi ; \
-	done
-	cp $(BOOTIMAGE) $(obj)/isoimage/linux
-	echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
-	if [ -f '$(FDINITRD)' ] ; then \
-		cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \
-	fi
-	mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \
-		-no-emul-boot -boot-load-size 4 -boot-info-table \
-		$(obj)/isoimage
-	rm -rf $(obj)/isoimage
-
-zlilo: $(BOOTIMAGE)
-	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
-	if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
-	cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
-	cp System.map $(INSTALL_PATH)/
-	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-
-install:
-	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
+src := arch/i386/boot
+include $(src)/Makefile
diff --git a/arch/x86_64/boot/bootsect.S b/arch/x86_64/boot/bootsect.S
deleted file mode 100644
index 011b7a4..0000000
--- a/arch/x86_64/boot/bootsect.S
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *	bootsect.S		Copyright (C) 1991, 1992 Linus Torvalds
- *
- *	modified by Drew Eckhardt
- *	modified by Bruce Evans (bde)
- *	modified by Chris Noe (May 1999) (as86 -> gas)
- *	gutted by H. Peter Anvin (Jan 2003)
- *
- * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
- * addresses must be multiplied by 16 to obtain their respective linear
- * addresses. To avoid confusion, linear addresses are written using leading
- * hex while segment addresses are written as segment:offset.
- *
- */
-
-#include <asm/boot.h>
-
-SETUPSECTS	= 4			/* default nr of setup-sectors */
-BOOTSEG		= 0x07C0		/* original address of boot-sector */
-INITSEG		= DEF_INITSEG		/* we move boot here - out of the way */
-SETUPSEG	= DEF_SETUPSEG		/* setup starts here */
-SYSSEG		= DEF_SYSSEG		/* system loaded at 0x10000 (65536) */
-SYSSIZE		= DEF_SYSSIZE		/* system size: # of 16-byte clicks */
-					/* to be loaded */
-ROOT_DEV	= 0 			/* ROOT_DEV is now written by "build" */
-SWAP_DEV	= 0			/* SWAP_DEV is now written by "build" */
-
-#ifndef SVGA_MODE
-#define SVGA_MODE ASK_VGA
-#endif
-
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif
-
-#ifndef ROOT_RDONLY
-#define ROOT_RDONLY 1
-#endif
-
-.code16
-.text
-
-.global _start
-_start:
-
-	# Normalize the start address
-	jmpl	$BOOTSEG, $start2
-
-start2:
-	movw	%cs, %ax
-	movw	%ax, %ds
-	movw	%ax, %es
-	movw	%ax, %ss
-	movw	$0x7c00, %sp
-	sti
-	cld
-
-	movw	$bugger_off_msg, %si
-
-msg_loop:
-	lodsb
-	andb	%al, %al
-	jz	die
-	movb	$0xe, %ah
-	movw	$7, %bx
-	int	$0x10
-	jmp	msg_loop
-
-die:
-	# Allow the user to press a key, then reboot
-	xorw	%ax, %ax
-	int	$0x16
-	int	$0x19
-
-	# int 0x19 should never return.  In case it does anyway,
-	# invoke the BIOS reset code...
-	ljmp	$0xf000,$0xfff0
-
-
-bugger_off_msg:
-	.ascii	"Direct booting from floppy is no longer supported.\r\n"
-	.ascii	"Please use a boot loader program instead.\r\n"
-	.ascii	"\n"
-	.ascii	"Remove disk and press any key to reboot . . .\r\n"
-	.byte	0
-
-
-	# Kernel attributes; used by setup
-
-	.org 497
-setup_sects:	.byte SETUPSECTS
-root_flags:	.word ROOT_RDONLY
-syssize:	.word SYSSIZE
-swap_dev:	.word SWAP_DEV
-ram_size:	.word RAMDISK
-vid_mode:	.word SVGA_MODE
-root_dev:	.word ROOT_DEV
-boot_flag:	.word 0xAA55
diff --git a/arch/x86_64/boot/compressed/Makefile b/arch/x86_64/boot/compressed/Makefile
index 705a3e3..c9f2da7 100644
--- a/arch/x86_64/boot/compressed/Makefile
+++ b/arch/x86_64/boot/compressed/Makefile
@@ -7,11 +7,12 @@
 #
 
 targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-EXTRA_AFLAGS	:= -traditional
 
-# cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with
-# -m32
-CFLAGS := -m64 -D__KERNEL__ -Iinclude -O2  -fno-strict-aliasing -fPIC -mcmodel=small -fno-builtin
+CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2  \
+	  -fno-strict-aliasing -fPIC -mcmodel=small \
+	   $(call cc-option, -ffreestanding) \
+	   $(call cc-option, -fno-stack-protector)
+AFLAGS  := $(CFLAGS) -D__ASSEMBLY__
 LDFLAGS := -m elf_x86_64
 
 LDFLAGS_vmlinux := -T
diff --git a/arch/x86_64/boot/compressed/head.S b/arch/x86_64/boot/compressed/head.S
index f9d5692..1312bfa 100644
--- a/arch/x86_64/boot/compressed/head.S
+++ b/arch/x86_64/boot/compressed/head.S
@@ -46,10 +46,10 @@
  * at and where we were actually loaded at.  This can only be done
  * with a short local call on x86.  Nothing  else will tell us what
  * address we are running at.  The reserved chunk of the real-mode
- * data at 0x34-0x3f are used as the stack for this calculation.
- * Only 4 bytes are needed.
+ * data at 0x1e4 (defined as a scratch field) are used as the stack
+ * for this calculation. Only 4 bytes are needed.
  */
-	leal	0x40(%esi), %esp
+	leal	(0x1e4+4)(%esi), %esp
 	call	1f
 1:	popl	%ebp
 	subl	$1b, %ebp
diff --git a/arch/x86_64/boot/install.sh b/arch/x86_64/boot/install.sh
deleted file mode 100644
index baaa236..0000000
--- a/arch/x86_64/boot/install.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-. $srctree/arch/i386/boot/install.sh
diff --git a/arch/x86_64/boot/mtools.conf.in b/arch/x86_64/boot/mtools.conf.in
deleted file mode 100644
index efd6d24..0000000
--- a/arch/x86_64/boot/mtools.conf.in
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# mtools configuration file for "make (b)zdisk"
-#
-
-# Actual floppy drive
-drive a:
-  file="/dev/fd0"
-
-# 1.44 MB floppy disk image
-drive v:
-  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
-
-# 2.88 MB floppy disk image (mostly for virtual uses)
-drive w:
-  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
-
-
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
deleted file mode 100644
index e9e33f9..0000000
--- a/arch/x86_64/boot/setup.S
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
- *	setup.S		Copyright (C) 1991, 1992 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- * Move PS/2 aux init code to psaux.c
- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *
- * some changes and additional features by Christoph Niemann,
- * March 1993/June 1994 (Christoph.Niemann@linux.org)
- *
- * add APM BIOS checking by Stephen Rothwell, May 1994
- * (sfr@canb.auug.org.au)
- *
- * High load stuff, initrd support and position independency
- * by Hans Lermen & Werner Almesberger, February 1996
- * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
- *
- * Video handling moved to video.S by Martin Mares, March 1996
- * <mj@k332.feld.cvut.cz>
- *
- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
- * parsons) to avoid loadlin confusion, July 1997
- *
- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
- * <stiker@northlink.com>
- *
- * Fix to work around buggy BIOSes which don't use carry bit correctly
- * and/or report extended memory in CX/DX for e801h memory size detection 
- * call.  As a result the kernel got wrong figures.  The int15/e801h docs
- * from Ralf Brown interrupt list seem to indicate AX/BX should be used
- * anyway.  So to avoid breaking many machines (presumably there was a reason
- * to orginally use CX/DX instead of AX/BX), we do a kludge to see
- * if CX/DX have been changed in the e801 call and if so use AX/BX .
- * Michael Miller, April 2001 <michaelm@mjmm.org>
- *
- * Added long mode checking and SSE force. March 2003, Andi Kleen.		
- */
-
-#include <asm/segment.h>
-#include <linux/utsrelease.h>
-#include <linux/compile.h>
-#include <asm/boot.h>
-#include <asm/e820.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-
-/* Signature words to ensure LILO loaded us right */
-#define SIG1	0xAA55
-#define SIG2	0x5A5A
-
-INITSEG  = DEF_INITSEG		# 0x9000, we move boot here, out of the way
-SYSSEG   = DEF_SYSSEG		# 0x1000, system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG		# 0x9020, this is the current segment
-				# ... and the former contents of CS
-
-DELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020
-
-.code16
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-start:
-	jmp	trampoline
-
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
-		.ascii	"HdrS"		# header signature
-		.word	0x0206		# header version number (>= 0x0105)
-					# or else old loadlin-1.5 will fail)
-realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
-start_sys_seg:	.word	SYSSEG
-		.word	kernel_version	# pointing to kernel version string
-					# above section of header is compatible
-					# with loadlin-1.5 (header v1.5). Don't
-					# change it.
-
-type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
-					#      Bootlin, SYSLX, bootsect...)
-					# See Documentation/i386/boot.txt for
-					# assigned ids
-	
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH	= 1			# If set, the kernel is loaded high
-CAN_USE_HEAP	= 0x80			# If set, the loader also has set
-					# heap_end_ptr to tell how much
-					# space behind setup.S can be used for
-					# heap purposes.
-					# Only the loader knows what is free
-#ifndef __BIG_KERNEL__
-		.byte	0
-#else
-		.byte	LOADED_HIGH
-#endif
-
-setup_move_size: .word  0x8000		# size to move, when setup is not
-					# loaded at 0x90000. We will move setup 
-					# to 0x90000 then just before jumping
-					# into the kernel. However, only the
-					# loader knows how much data behind
-					# us also needs to be loaded.
-
-code32_start:				# here loaders can put a different
-					# start address for 32-bit code.
-#ifndef __BIG_KERNEL__
-		.long	0x1000		#   0x1000 = default for zImage
-#else
-		.long	0x100000	# 0x100000 = default for big kernel
-#endif
-
-ramdisk_image:	.long	0		# address of loaded ramdisk image
-					# Here the loader puts the 32-bit
-					# address where it loaded the image.
-					# This only will be read by the kernel.
-
-ramdisk_size:	.long	0		# its size in bytes
-
-bootsect_kludge:
-		.long	0		# obsolete
-
-heap_end_ptr:	.word	modelist+1024	# (Header version 0x0201 or later)
-					# space from here (exclusive) down to
-					# end of setup code can be used by setup
-					# for local heap purposes.
-
-pad1:		.word	0
-cmd_line_ptr:	.long 0			# (Header version 0x0202 or later)
-					# If nonzero, a 32-bit pointer
-					# to the kernel command line.
-					# The command line should be
-					# located between the start of
-					# setup and the end of low
-					# memory (0xa0000), or it may
-					# get overwritten before it
-					# gets read.  If this field is
-					# used, there is no longer
-					# anything magical about the
-					# 0x90000 segment; the setup
-					# can be located anywhere in
-					# low memory 0x10000 or higher.
-
-ramdisk_max:	.long 0xffffffff
-kernel_alignment:  .long 0x200000       # physical addr alignment required for
-					# protected mode relocatable kernel
-#ifdef CONFIG_RELOCATABLE
-relocatable_kernel:    .byte 1
-#else
-relocatable_kernel:    .byte 0
-#endif
-pad2:                  .byte 0
-pad3:                  .word 0
-
-cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
-                                                #added with boot protocol
-                                                #version 2.06
-
-trampoline:	call	start_of_setup
-		.align 16
-					# The offset at this point is 0x240
-		.space  (0xeff-0x240+1)	# E820 & EDD space (ending at 0xeff)
-# End of setup header #####################################################
-
-start_of_setup:
-# Bootlin depends on this being done early
-	movw	$0x01500, %ax
-	movb	$0x81, %dl
-	int	$0x13
-
-#ifdef SAFE_RESET_DISK_CONTROLLER
-# Reset the disk controller.
-	movw	$0x0000, %ax
-	movb	$0x80, %dl
-	int	$0x13
-#endif
-
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
-	movw	%cs, %ax		# aka SETUPSEG
-	movw	%ax, %ds
-# Check signature at end of setup
-	cmpw	$SIG1, setup_sig1
-	jne	bad_sig
-
-	cmpw	$SIG2, setup_sig2
-	jne	bad_sig
-
-	jmp	good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
-	lodsb
-	andb	%al, %al
-	jz	fin
-
-	call	prtchr
-	jmp	prtstr
-
-fin:	ret
-
-# Space printing
-prtsp2:	call	prtspc		# Print double space
-prtspc:	movb	$0x20, %al	# Print single space (note: fall-thru)
-
-prtchr:	
-	pushw	%ax
-	pushw	%cx
-	movw	$0007,%bx
-	movw	$0x01, %cx
-	movb	$0x0e, %ah
-	int	$0x10
-	popw	%cx
-	popw	%ax
-	ret
-
-beep:	movb	$0x07, %al
-	jmp	prtchr
-	
-no_sig_mess: .string	"No setup signature found ..."
-
-good_sig1:
-	jmp	good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
-	movw	%cs, %ax			# SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# INITSEG
-	movw	%ax, %ds
-	xorb	%bh, %bh
-	movb	(497), %bl			# get setup sect from bootsect
-	subw	$4, %bx				# LILO loads 4 sectors of setup
-	shlw	$8, %bx				# convert to words (1sect=2^8 words)
-	movw	%bx, %cx
-	shrw	$3, %bx				# convert to segment
-	addw	$SYSSEG, %bx
-	movw	%bx, %cs:start_sys_seg
-# Move rest of setup code/data to here
-	movw	$2048, %di			# four sectors loaded by LILO
-	subw	%si, %si
-	movw	%cs, %ax			# aka SETUPSEG
-	movw	%ax, %es
-	movw	$SYSSEG, %ax
-	movw	%ax, %ds
-	rep
-	movsw
-	movw	%cs, %ax			# aka SETUPSEG
-	movw	%ax, %ds
-	cmpw	$SIG1, setup_sig1
-	jne	no_sig
-
-	cmpw	$SIG2, setup_sig2
-	jne	no_sig
-
-	jmp	good_sig
-
-no_sig:
-	lea	no_sig_mess, %si
-	call	prtstr
-
-no_sig_loop:
-	jmp	no_sig_loop
-
-good_sig:
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
-	movw	%ax, %ds
-# Check if an old loader tries to load a big-kernel
-	testb	$LOADED_HIGH, %cs:loadflags	# Do we have a big kernel?
-	jz	loader_ok			# No, no danger for old loaders.
-
-	cmpb	$0, %cs:type_of_loader 		# Do we have a loader that
-						# can deal with us?
-	jnz	loader_ok			# Yes, continue.
-
-	pushw	%cs				# No, we have an old loader,
-	popw	%ds				# die. 
-	lea	loader_panic_mess, %si
-	call	prtstr
-
-	jmp	no_sig_loop
-
-loader_panic_mess: .string "Wrong loader, giving up..."
-
-loader_ok:
-	/* check for long mode. */
-	/* we have to do this before the VESA setup, otherwise the user
-	   can't see the error message. */
-	
-	pushw	%ds
-	movw	%cs,%ax
-	movw	%ax,%ds
-	
-	call verify_cpu
-	testl %eax,%eax
-	jz sse_ok
-
-no_longmode:
-	call	beep
-	lea	long_mode_panic,%si
-	call	prtstr
-no_longmode_loop:		
-	jmp	no_longmode_loop
-long_mode_panic:
-	.string "Your CPU does not support long mode. Use a 32bit distribution."
-	.byte 0
-
-#include "../kernel/verify_cpu.S"
-sse_ok:
-	popw	%ds
-	
-# tell BIOS we want to go to long mode
-	movl  $0xec00,%eax	# declare target operating mode
-	movl  $2,%ebx		# long mode
-	int $0x15			
-	
-# Get memory size (extended mem, kB)
-
-	xorl	%eax, %eax
-	movl	%eax, (0x1e0)
-#ifndef STANDARD_MEMORY_BIOS_CALL
-	movb	%al, (E820NR)
-# Try three different memory detection schemes.  First, try
-# e820h, which lets us assemble a memory map, then try e801h,
-# which returns a 32-bit memory size, and finally 88h, which
-# returns 0-64m
-
-# method E820H:
-# the memory map from hell.  e820h returns memory classified into
-# a whole bunch of different types, and allows memory holes and
-# everything.  We scan through this memory map and build a list
-# of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
-
-#define SMAP  0x534d4150
-
-meme820:
-	xorl	%ebx, %ebx			# continuation counter
-	movw	$E820MAP, %di			# point into the whitelist
-						# so we can have the bios
-						# directly write into it.
-
-jmpe820:
-	movl	$0x0000e820, %eax		# e820, upper word zeroed
-	movl	$SMAP, %edx			# ascii 'SMAP'
-	movl	$20, %ecx			# size of the e820rec
-	pushw	%ds				# data record.
-	popw	%es
-	int	$0x15				# make the call
-	jc	bail820				# fall to e801 if it fails
-
-	cmpl	$SMAP, %eax			# check the return is `SMAP'
-	jne	bail820				# fall to e801 if it fails
-
-#	cmpl	$1, 16(%di)			# is this usable memory?
-#	jne	again820
-
-	# If this is usable memory, we save it by simply advancing %di by
-	# sizeof(e820rec).
-	#
-good820:
-	movb	(E820NR), %al			# up to 128 entries
-	cmpb	$E820MAX, %al
-	jae	bail820
-
-	incb	(E820NR)
-	movw	%di, %ax
-	addw	$20, %ax
-	movw	%ax, %di
-again820:
-	cmpl	$0, %ebx			# check to see if
-	jne	jmpe820				# %ebx is set to EOF
-bail820:
-
-
-# method E801H:
-# memory size is in 1k chunksizes, to avoid confusing loadlin.
-# we store the 0xe801 memory size in a completely different place,
-# because it will most likely be longer than 16 bits.
-# (use 1e0 because that's what Larry Augustine uses in his
-# alternative new memory detection scheme, and it's sensible
-# to write everything into the same place.)
-
-meme801:
-	stc					# fix to work around buggy
-	xorw	%cx,%cx				# BIOSes which don't clear/set
-	xorw	%dx,%dx				# carry on pass/error of
-						# e801h memory size call
-						# or merely pass cx,dx though
-						# without changing them.
-	movw	$0xe801, %ax
-	int	$0x15
-	jc	mem88
-
-	cmpw	$0x0, %cx			# Kludge to handle BIOSes
-	jne	e801usecxdx			# which report their extended
-	cmpw	$0x0, %dx			# memory in AX/BX rather than
-	jne	e801usecxdx			# CX/DX.  The spec I have read
-	movw	%ax, %cx			# seems to indicate AX/BX 
-	movw	%bx, %dx			# are more reasonable anyway...
-
-e801usecxdx:
-	andl	$0xffff, %edx			# clear sign extend
-	shll	$6, %edx			# and go from 64k to 1k chunks
-	movl	%edx, (0x1e0)			# store extended memory size
-	andl	$0xffff, %ecx			# clear sign extend
- 	addl	%ecx, (0x1e0)			# and add lower memory into
-						# total size.
-
-# Ye Olde Traditional Methode.  Returns the memory size (up to 16mb or
-# 64mb, depending on the bios) in ax.
-mem88:
-
-#endif
-	movb	$0x88, %ah
-	int	$0x15
-	movw	%ax, (2)
-
-# Set the keyboard repeat rate to the max
-	movw	$0x0305, %ax
-	xorw	%bx, %bx
-	int	$0x16
-
-# Check for video adapter and its parameters and allow the
-# user to browse video modes.
-	call	video				# NOTE: we need %ds pointing
-						# to bootsector
-
-# Get hd0 data...
-	xorw	%ax, %ax
-	movw	%ax, %ds
-	ldsw	(4 * 0x41), %si
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	pushw	%ax
-	movw	%ax, %es
-	movw	$0x0080, %di
-	movw	$0x10, %cx
-	pushw	%cx
-	cld
-	rep
- 	movsb
-# Get hd1 data...
-	xorw	%ax, %ax
-	movw	%ax, %ds
-	ldsw	(4 * 0x46), %si
-	popw	%cx
-	popw	%es
-	movw	$0x0090, %di
-	rep
-	movsb
-# Check that there IS a hd1 :-)
-	movw	$0x01500, %ax
-	movb	$0x81, %dl
-	int	$0x13
-	jc	no_disk1
-	
-	cmpb	$3, %ah
-	je	is_disk1
-
-no_disk1:
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
-	movw	%ax, %es
-	movw	$0x0090, %di
-	movw	$0x10, %cx
-	xorw	%ax, %ax
-	cld
-	rep
-	stosb
-is_disk1:
-
-# Check for PS/2 pointing device
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	movw	%ax, %ds
-	movb	$0, (0x1ff)			# default is no pointing device
-	int	$0x11				# int 0x11: equipment list
-	testb	$0x04, %al			# check if mouse installed
-	jz	no_psmouse
-
-	movb	$0xAA, (0x1ff)			# device present
-no_psmouse:
-
-#include "../../i386/boot/edd.S"
-
-# Now we want to move to protected mode ...
-	cmpw	$0, %cs:realmode_swtch
-	jz	rmodeswtch_normal
-
-	lcall	*%cs:realmode_swtch
-
-	jmp	rmodeswtch_end
-
-rmodeswtch_normal:
-        pushw	%cs
-	call	default_switch
-
-rmodeswtch_end:
-# we get the code32 start address and modify the below 'jmpi'
-# (loader may have changed it)
-	movl	%cs:code32_start, %eax
-	movl	%eax, %cs:code32
-
-# Now we move the system to its rightful place ... but we check if we have a
-# big-kernel. In that case we *must* not move it ...
-	testb	$LOADED_HIGH, %cs:loadflags
-	jz	do_move0			# .. then we have a normal low
-						# loaded zImage
-						# .. or else we have a high
-						# loaded bzImage
-	jmp	end_move			# ... and we skip moving
-
-do_move0:
-	movw	$0x100, %ax			# start of destination segment
-	movw	%cs, %bp			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %bp		# aka INITSEG
-	movw	%cs:start_sys_seg, %bx		# start of source segment
-	cld
-do_move:
-	movw	%ax, %es			# destination segment
-	incb	%ah				# instead of add ax,#0x100
-	movw	%bx, %ds			# source segment
-	addw	$0x100, %bx
-	subw	%di, %di
-	subw	%si, %si
-	movw 	$0x800, %cx
-	rep
-	movsw
-	cmpw	%bp, %bx			# assume start_sys_seg > 0x200,
-						# so we will perhaps read one
-						# page more than needed, but
-						# never overwrite INITSEG
-						# because destination is a
-						# minimum one page below source
-	jb	do_move
-
-end_move:
-# then we load the segment descriptors
-	movw	%cs, %ax			# aka SETUPSEG
-	movw	%ax, %ds
-		
-# Check whether we need to be downward compatible with version <=201
-	cmpl	$0, cmd_line_ptr
-	jne	end_move_self		# loader uses version >=202 features
-	cmpb	$0x20, type_of_loader
-	je	end_move_self		# bootsect loader, we know of it
-
-# Boot loader doesnt support boot protocol version 2.02.
-# If we have our code not at 0x90000, we need to move it there now.
-# We also then need to move the params behind it (commandline)
-# Because we would overwrite the code on the current IP, we move
-# it in two steps, jumping high after the first one.
-	movw	%cs, %ax
-	cmpw	$SETUPSEG, %ax
-	je	end_move_self
-
-	cli					# make sure we really have
-						# interrupts disabled !
-						# because after this the stack
-						# should not be used
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	movw	%ss, %dx
-	cmpw	%ax, %dx
-	jb	move_self_1
-
-	addw	$INITSEG, %dx
-	subw	%ax, %dx			# this will go into %ss after
-						# the move
-move_self_1:
-	movw	%ax, %ds
-	movw	$INITSEG, %ax			# real INITSEG
-	movw	%ax, %es
-	movw	%cs:setup_move_size, %cx
-	std					# we have to move up, so we use
-						# direction down because the
-						# areas may overlap
-	movw	%cx, %di
-	decw	%di
-	movw	%di, %si
-	subw	$move_self_here+0x200, %cx
-	rep
-	movsb
-	ljmp	$SETUPSEG, $move_self_here
-
-move_self_here:
-	movw	$move_self_here+0x200, %cx
-	rep
-	movsb
-	movw	$SETUPSEG, %ax
-	movw	%ax, %ds
-	movw	%dx, %ss
-end_move_self:					# now we are at the right place
-	lidt	idt_48				# load idt with 0,0
-	xorl	%eax, %eax			# Compute gdt_base
-	movw	%ds, %ax			# (Convert %ds:gdt to a linear ptr)
-	shll	$4, %eax
-	addl	$gdt, %eax
-	movl	%eax, (gdt_48+2)
-	lgdt	gdt_48				# load gdt with whatever is
-						# appropriate
-
-# that was painless, now we enable a20
-	call	empty_8042
-
-	movb	$0xD1, %al			# command write
-	outb	%al, $0x64
-	call	empty_8042
-
-	movb	$0xDF, %al			# A20 on
-	outb	%al, $0x60
-	call	empty_8042
-
-#
-#	You must preserve the other bits here. Otherwise embarrasing things
-#	like laptops powering off on boot happen. Corrected version by Kira
-#	Brown from Linux 2.2
-#
-	inb	$0x92, %al			# 
-	orb	$02, %al			# "fast A20" version
-	outb	%al, $0x92			# some chips have only this
-
-# wait until a20 really *is* enabled; it can take a fair amount of
-# time on certain systems; Toshiba Tecras are known to have this
-# problem.  The memory location used here (0x200) is the int 0x80
-# vector, which should be safe to use.
-
-	xorw	%ax, %ax			# segment 0x0000
-	movw	%ax, %fs
-	decw	%ax				# segment 0xffff (HMA)
-	movw	%ax, %gs
-a20_wait:
-	incw	%ax				# unused memory location <0xfff0
-	movw	%ax, %fs:(0x200)		# we use the "int 0x80" vector
-	cmpw	%gs:(0x210), %ax		# and its corresponding HMA addr
-	je	a20_wait			# loop until no longer aliased
-
-# make sure any possible coprocessor is properly reset..
-	xorw	%ax, %ax
-	outb	%al, $0xf0
-	call	delay
-
-	outb	%al, $0xf1
-	call	delay
-
-# well, that went ok, I hope. Now we mask all interrupts - the rest
-# is done in init_IRQ().
-	movb	$0xFF, %al			# mask all interrupts for now
-	outb	%al, $0xA1
-	call	delay
-	
-	movb	$0xFB, %al			# mask all irq's but irq2 which
-	outb	%al, $0x21			# is cascaded
-
-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-# need no steenking BIOS anyway (except for the initial loading :-).
-# The BIOS-routine wants lots of unnecessary data, and it's less
-# "interesting" anyway. This is how REAL programmers do it.
-#
-# Well, now's the time to actually move into protected mode. To make
-# things as simple as possible, we do no register set-up or anything,
-# we let the gnu-compiled 32-bit programs do that. We just jump to
-# absolute address 0x1000 (or the loader supplied one),
-# in 32-bit protected mode.
-#
-# Note that the short jump isn't strictly needed, although there are
-# reasons why it might be a good idea. It won't hurt in any case.
-	movw	$1, %ax				# protected mode (PE) bit
-	lmsw	%ax				# This is it!
-	jmp	flush_instr
-
-flush_instr:
-	xorw	%bx, %bx			# Flag to indicate a boot
-	xorl	%esi, %esi			# Pointer to real-mode code
-	movw	%cs, %si
-	subw	$DELTA_INITSEG, %si
-	shll	$4, %esi			# Convert to 32-bit pointer
-# NOTE: For high loaded big kernels we need a
-#	jmpi    0x100000,__KERNEL_CS
-#
-#	but we yet haven't reloaded the CS register, so the default size 
-#	of the target offset still is 16 bit.
-#	However, using an operand prefix (0x66), the CPU will properly
-#	take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
-#	Manual, Mixing 16-bit and 32-bit code, page 16-6)
-
-	.byte 0x66, 0xea			# prefix + jmpi-opcode
-code32:	.long	0x1000				# will be set to 0x100000
-						# for big kernels
-	.word	__KERNEL_CS
-
-# Here's a bunch of information about your current kernel..
-kernel_version:	.ascii	UTS_RELEASE
-		.ascii	" ("
-		.ascii	LINUX_COMPILE_BY
-		.ascii	"@"
-		.ascii	LINUX_COMPILE_HOST
-		.ascii	") "
-		.ascii	UTS_VERSION
-		.byte	0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
-	cli					# no interrupts allowed !
-	movb	$0x80, %al			# disable NMI for bootup
-						# sequence
-	outb	%al, $0x70
-	lret
-
-
-# This routine checks that the keyboard command queue is empty
-# (after emptying the output buffers)
-#
-# Some machines have delusions that the keyboard buffer is always full
-# with no keyboard attached...
-#
-# If there is no keyboard controller, we will usually get 0xff
-# to all the reads.  With each IO taking a microsecond and
-# a timeout of 100,000 iterations, this can take about half a
-# second ("delay" == outb to port 0x80). That should be ok,
-# and should also be plenty of time for a real keyboard controller
-# to empty.
-#
-
-empty_8042:
-	pushl	%ecx
-	movl	$100000, %ecx
-
-empty_8042_loop:
-	decl	%ecx
-	jz	empty_8042_end_loop
-
-	call	delay
-
-	inb	$0x64, %al			# 8042 status port
-	testb	$1, %al				# output buffer?
-	jz	no_output
-
-	call	delay
-	inb	$0x60, %al			# read it
-	jmp	empty_8042_loop
-
-no_output:
-	testb	$2, %al				# is input buffer full?
-	jnz	empty_8042_loop			# yes - loop
-empty_8042_end_loop:
-	popl	%ecx
-	ret
-
-# Read the cmos clock. Return the seconds in al
-gettime:
-	pushw	%cx
-	movb	$0x02, %ah
-	int	$0x1a
-	movb	%dh, %al			# %dh contains the seconds
-	andb	$0x0f, %al
-	movb	%dh, %ah
-	movb	$0x04, %cl
-	shrb	%cl, %ah
-	aad
-	popw	%cx
-	ret
-
-# Delay is needed after doing I/O
-delay:
-	outb	%al,$0x80
-	ret
-
-# Descriptor tables
-gdt:
-	.word	0, 0, 0, 0			# dummy
-
-	.word	0, 0, 0, 0			# unused
-
-	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
-	.word	0				# base address = 0
-	.word	0x9A00				# code read/exec
-	.word	0x00CF				# granularity = 4096, 386
-						#  (+5th nibble of limit)
-
-	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
-	.word	0				# base address = 0
-	.word	0x9200				# data read/write
-	.word	0x00CF				# granularity = 4096, 386
-						#  (+5th nibble of limit)
-gdt_end:
-idt_48:
-	.word	0				# idt limit = 0
-	.word	0, 0				# idt base = 0L
-gdt_48:
-	.word	gdt_end-gdt-1			# gdt limit
-	.word	0, 0				# gdt base (filled in later)
-
-# Include video setup & detection code
-
-#include "../../i386/boot/video.S"
-
-# Setup signature -- must be last
-setup_sig1:	.word	SIG1
-setup_sig2:	.word	SIG2
-
-# After this point, there is some free space which is used by the video mode
-# handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/arch/x86_64/boot/tools/build.c b/arch/x86_64/boot/tools/build.c
deleted file mode 100644
index eae8669..0000000
--- a/arch/x86_64/boot/tools/build.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 1997 Martin Mares
- */
-
-/*
- * This file builds a disk-image from three different files:
- *
- * - bootsect: compatibility mbr which prints an error message if
- *             someone tries to boot the kernel directly.
- * - setup: 8086 machine code, sets up system parm
- * - system: 80386 code for actual system
- *
- * It does some checking that all files are of the correct type, and
- * just writes the result to stdout, removing headers and padding to
- * the right amount. It also writes some system data to stderr.
- */
-
-/*
- * Changes by tytso to allow root device specification
- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
- * Cross compiling fixes by Gertjan van Wingerde, July 1996
- * Rewritten by Martin Mares, April 1997
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <asm/boot.h>
-
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long u32;
-
-#define DEFAULT_MAJOR_ROOT 0
-#define DEFAULT_MINOR_ROOT 0
-
-/* Minimal number of setup sectors (see also bootsect.S) */
-#define SETUP_SECTS 4
-
-byte buf[1024];
-int fd;
-int is_big_kernel;
-
-void die(const char * str, ...)
-{
-	va_list args;
-	va_start(args, str);
-	vfprintf(stderr, str, args);
-	fputc('\n', stderr);
-	exit(1);
-}
-
-void file_open(const char *name)
-{
-	if ((fd = open(name, O_RDONLY, 0)) < 0)
-		die("Unable to open `%s': %m", name);
-}
-
-void usage(void)
-{
-	die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
-}
-
-int main(int argc, char ** argv)
-{
-	unsigned int i, c, sz, setup_sectors;
-	u32 sys_size;
-	byte major_root, minor_root;
-	struct stat sb;
-
-	if (argc > 2 && !strcmp(argv[1], "-b"))
-	  {
-	    is_big_kernel = 1;
-	    argc--, argv++;
-	  }
-	if ((argc < 4) || (argc > 5))
-		usage();
-	if (argc > 4) {
-		if (!strcmp(argv[4], "CURRENT")) {
-			if (stat("/", &sb)) {
-				perror("/");
-				die("Couldn't stat /");
-			}
-			major_root = major(sb.st_dev);
-			minor_root = minor(sb.st_dev);
-		} else if (strcmp(argv[4], "FLOPPY")) {
-			if (stat(argv[4], &sb)) {
-				perror(argv[4]);
-				die("Couldn't stat root device.");
-			}
-			major_root = major(sb.st_rdev);
-			minor_root = minor(sb.st_rdev);
-		} else {
-			major_root = 0;
-			minor_root = 0;
-		}
-	} else {
-		major_root = DEFAULT_MAJOR_ROOT;
-		minor_root = DEFAULT_MINOR_ROOT;
-	}
-	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
-
-	file_open(argv[1]);
-	i = read(fd, buf, sizeof(buf));
-	fprintf(stderr,"Boot sector %d bytes.\n",i);
-	if (i != 512)
-		die("Boot block must be exactly 512 bytes");
-	if (buf[510] != 0x55 || buf[511] != 0xaa)
-		die("Boot block hasn't got boot flag (0xAA55)");
-	buf[508] = minor_root;
-	buf[509] = major_root;
-	if (write(1, buf, 512) != 512)
-		die("Write call failed");
-	close (fd);
-
-	file_open(argv[2]);				    /* Copy the setup code */
-	for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
-		if (write(1, buf, c) != c)
-			die("Write call failed");
-	if (c != 0)
-		die("read-error on `setup'");
-	close (fd);
-
-	setup_sectors = (i + 511) / 512;	/* Pad unused space with zeros */
-	/* for compatibility with ancient versions of LILO. */
-	if (setup_sectors < SETUP_SECTS)
-		setup_sectors = SETUP_SECTS;
-	fprintf(stderr, "Setup is %d bytes.\n", i);
-	memset(buf, 0, sizeof(buf));
-	while (i < setup_sectors * 512) {
-		c = setup_sectors * 512 - i;
-		if (c > sizeof(buf))
-			c = sizeof(buf);
-		if (write(1, buf, c) != c)
-			die("Write call failed");
-		i += c;
-	}
-
-	file_open(argv[3]);
-	if (fstat (fd, &sb))
-		die("Unable to stat `%s': %m", argv[3]);
-	sz = sb.st_size;
-	fprintf (stderr, "System is %d kB\n", sz/1024);
-	sys_size = (sz + 15) / 16;
-	if (!is_big_kernel && sys_size > DEF_SYSSIZE)
-		die("System is too big. Try using bzImage or modules.");
-	while (sz > 0) {
-		int l, n;
-
-		l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
-		if ((n=read(fd, buf, l)) != l) {
-			if (n < 0)
-				die("Error reading %s: %m", argv[3]);
-			else
-				die("%s: Unexpected EOF", argv[3]);
-		}
-		if (write(1, buf, l) != l)
-			die("Write failed");
-		sz -= l;
-	}
-	close(fd);
-
-	if (lseek(1, 497, SEEK_SET) != 497)		    /* Write sizes to the bootsector */
-		die("Output: seek failed");
-	buf[0] = setup_sectors;
-	if (write(1, buf, 1) != 1)
-		die("Write of setup sector count failed");
-	if (lseek(1, 500, SEEK_SET) != 500)
-		die("Output: seek failed");
-	buf[0] = (sys_size & 0xff);
-	buf[1] = ((sys_size >> 8) & 0xff);
-	buf[2] = ((sys_size >> 16) & 0xff);
-	buf[3] = ((sys_size >> 24) & 0xff);
-	if (write(1, buf, 4) != 4)
-		die("Write of image length failed");
-
-	return 0;					    /* Everything is OK */
-}
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 941a7e3..40178e5 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-git3
-# Tue May  1 07:30:48 2007
+# Linux kernel version: 2.6.22-rc2
+# Mon May 21 13:23:40 2007
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -53,6 +53,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
@@ -72,14 +73,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -118,11 +124,11 @@
 # CONFIG_X86_VSMP is not set
 # CONFIG_MK8 is not set
 # CONFIG_MPSC is not set
-CONFIG_MCORE2=y
-# CONFIG_GENERIC_CPU is not set
-CONFIG_X86_L1_CACHE_BYTES=64
-CONFIG_X86_L1_CACHE_SHIFT=6
-CONFIG_X86_INTERNODE_CACHE_BYTES=64
+# CONFIG_MCORE2 is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
 CONFIG_X86_TSC=y
 CONFIG_X86_GOOD_APIC=y
 # CONFIG_MICROCODE is not set
@@ -174,7 +180,7 @@
 CONFIG_X86_MCE_AMD=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
-# CONFIG_RELOCATABLE is not set
+CONFIG_RELOCATABLE=y
 CONFIG_PHYSICAL_START=0x200000
 CONFIG_SECCOMP=y
 # CONFIG_CC_STACKPROTECTOR is not set
@@ -242,7 +248,7 @@
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
 
 #
 # CPUFreq processor drivers
@@ -266,6 +272,7 @@
 CONFIG_PCI_MMCONFIG=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+CONFIG_ARCH_SUPPORTS_MSI=y
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_HT_IRQ is not set
@@ -274,10 +281,6 @@
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -395,7 +398,9 @@
 #
 # CONFIG_CFG80211 is not set
 # CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -458,14 +463,12 @@
 # Misc devices
 #
 # CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_SONY_LAPTOP is not set
 # CONFIG_THINKPAD_ACPI is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
 
@@ -482,6 +485,7 @@
 # CONFIG_BLK_DEV_IDESCSI is not set
 CONFIG_BLK_DEV_IDEACPI=y
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
@@ -491,6 +495,7 @@
 # CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
@@ -556,6 +561,7 @@
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -579,15 +585,16 @@
 CONFIG_SCSI_AIC79XX=y
 CONFIG_AIC79XX_CMDS_PER_DEVICE=32
 CONFIG_AIC79XX_RESET_DELAY_MS=4000
-# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
 # CONFIG_AIC79XX_DEBUG_ENABLE is not set
 CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
 # CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=y
+CONFIG_MEGARAID_MAILBOX=y
 # CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
+CONFIG_MEGARAID_SAS=y
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -609,12 +616,9 @@
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_ACPI=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_SVW=y
 CONFIG_ATA_PIIX=y
@@ -631,7 +635,6 @@
 CONFIG_SATA_VIA=y
 # CONFIG_SATA_VITESSE is not set
 # CONFIG_SATA_INIC162X is not set
-CONFIG_SATA_ACPI=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
@@ -681,6 +684,7 @@
 # CONFIG_DM_MIRROR is not set
 # CONFIG_DM_ZERO is not set
 # CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
 
 #
 # Fusion MPT device support
@@ -688,13 +692,14 @@
 CONFIG_FUSION=y
 CONFIG_FUSION_SPI=y
 # CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_SAS=y
 CONFIG_FUSION_MAX_SGE=128
 # CONFIG_FUSION_CTL is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 CONFIG_IEEE1394=y
 
 #
@@ -705,10 +710,7 @@
 #
 # Controllers
 #
-
-#
-# Texas Instruments PCILynx requires I2C
-#
+# CONFIG_IEEE1394_PCILYNX is not set
 CONFIG_IEEE1394_OHCI1394=y
 
 #
@@ -725,11 +727,7 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -745,10 +743,6 @@
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
 # CONFIG_PHYLIB is not set
 
 #
@@ -779,8 +773,7 @@
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
-CONFIG_AMD8111_ETH=y
-# CONFIG_AMD8111E_NAPI is not set
+# CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 CONFIG_B44=y
 CONFIG_FORCEDETH=y
@@ -802,10 +795,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
@@ -824,10 +814,7 @@
 CONFIG_BNX2=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
@@ -835,6 +822,7 @@
 # CONFIG_S2IO_NAPI is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
 
 #
 # Token Ring devices
@@ -848,8 +836,14 @@
 # CONFIG_WLAN_80211 is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -902,9 +896,17 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -954,10 +956,6 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_INTEL=y
@@ -965,7 +963,6 @@
 # CONFIG_HW_RANDOM_GEODE is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 CONFIG_AGP=y
@@ -988,11 +985,58 @@
 #
 # CONFIG_TCG_TPM is not set
 # CONFIG_TELCLOCK is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
 
 #
-# I2C support
+# I2C Algorithms
 #
-# CONFIG_I2C is not set
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
 
 #
 # SPI support
@@ -1004,12 +1048,58 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+CONFIG_SENSORS_CORETEMP=y
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+CONFIG_SENSORS_SMSC47B397=m
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multifunction device drivers
@@ -1020,17 +1110,20 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
 # CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -1056,14 +1149,10 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
-CONFIG_OBSOLETE_OSS=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_ES1371 is not set
-CONFIG_SOUND_ICH=y
+# CONFIG_OSS_OBSOLETE is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 
 #
@@ -1142,37 +1231,10 @@
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
 #
@@ -1216,10 +1278,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1264,10 +1322,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
 # Virtualization
 #
 # CONFIG_KVM is not set
@@ -1385,6 +1439,7 @@
 CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1468,10 +1523,9 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
-CONFIG_TIMER_STATS=y
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1487,6 +1541,8 @@
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
@@ -1513,9 +1569,11 @@
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 21868f9..782dea8 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -526,7 +526,7 @@
 	.quad sys_init_module
 	.quad sys_delete_module
 	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
-	.quad sys_quotactl
+	.quad sys32_quotactl
 	.quad sys_getpgid
 	.quad sys_fchdir
 	.quad quiet_ni_syscall	/* bdflush */
@@ -620,7 +620,7 @@
 	.quad quiet_ni_syscall		/* tux */
 	.quad quiet_ni_syscall    	/* security */
 	.quad sys_gettid	
-	.quad sys_readahead	/* 225 */
+	.quad sys32_readahead	/* 225 */
 	.quad sys_setxattr
 	.quad sys_lsetxattr
 	.quad sys_fsetxattr
@@ -645,7 +645,7 @@
 	.quad compat_sys_io_getevents
 	.quad compat_sys_io_submit
 	.quad sys_io_cancel
-	.quad sys_fadvise64		/* 250 */
+	.quad sys32_fadvise64		/* 250 */
 	.quad quiet_ni_syscall 	/* free_huge_pages */
 	.quad sys_exit_group
 	.quad sys32_lookup_dcookie
@@ -709,7 +709,7 @@
 	.quad compat_sys_set_robust_list
 	.quad compat_sys_get_robust_list
 	.quad sys_splice
-	.quad sys_sync_file_range
+	.quad sys32_sync_file_range
 	.quad sys_tee			/* 315 */
 	.quad compat_sys_vmsplice
 	.quad compat_sys_move_pages
diff --git a/arch/x86_64/ia32/mmap32.c b/arch/x86_64/ia32/mmap32.c
index 079f413..e4b84b4 100644
--- a/arch/x86_64/ia32/mmap32.c
+++ b/arch/x86_64/ia32/mmap32.c
@@ -29,6 +29,7 @@
 #include <linux/personality.h>
 #include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 
 /*
  * Top of mmap area (just below the process stack).
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 200fdde..99a78a3 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -860,3 +860,22 @@
 	return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
 }
 
+asmlinkage ssize_t sys32_readahead(int fd, unsigned off_lo, unsigned off_hi, size_t count)
+{
+	return sys_readahead(fd, ((u64)off_hi << 32) | off_lo, count);
+}
+
+asmlinkage long sys32_sync_file_range(int fd, unsigned off_low, unsigned off_hi,
+			   unsigned n_low, unsigned n_hi,  int flags)
+{
+	return sys_sync_file_range(fd,
+				   ((u64)off_hi << 32) | off_low,
+				   ((u64)n_hi << 32) | n_low, flags);
+}
+
+asmlinkage long sys32_fadvise64(int fd, unsigned offset_lo, unsigned offset_hi, size_t len,
+		     int advice)
+{
+	return sys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo,
+				len, advice);
+}
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index de1de8a..47f1dc3 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -44,6 +44,7 @@
 
 obj-y				+= topology.o
 obj-y				+= intel_cacheinfo.o
+obj-y				+= addon_cpuid_features.o
 obj-y				+= pcspeaker.o
 
 CFLAGS_vsyscall.o		:= $(PROFILING) -g0
@@ -55,6 +56,7 @@
 topology-y                     += ../../i386/kernel/topology.o
 microcode-$(subst m,y,$(CONFIG_MICROCODE))  += ../../i386/kernel/microcode.o
 intel_cacheinfo-y		+= ../../i386/kernel/cpu/intel_cacheinfo.o
+addon_cpuid_features-y		+= ../../i386/kernel/cpu/addon_cpuid_features.o
 quirks-y			+= ../../i386/kernel/quirks.o
 i8237-y				+= ../../i386/kernel/i8237.o
 msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
diff --git a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig
index c0749d2..a3fd519 100644
--- a/arch/x86_64/kernel/cpufreq/Kconfig
+++ b/arch/x86_64/kernel/cpufreq/Kconfig
@@ -48,10 +48,6 @@
 
 	  If in doubt, say N.
 
-config X86_SPEEDSTEP_CENTRINO_ACPI
-	bool
-	depends on X86_SPEEDSTEP_CENTRINO
-
 config X86_ACPI_CPUFREQ
 	tristate "ACPI Processor P-States driver"
 	select CPU_FREQ_TABLE
@@ -73,7 +69,7 @@
 config X86_ACPI_CPUFREQ_PROC_INTF
 	bool "/proc/acpi/processor/../performance interface (deprecated)"
 	depends on PROC_FS
-	depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K8_ACPI
+	depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K8_ACPI
 	help
 	  This enables the deprecated /proc/acpi/processor/../performance
 	  interface. While it is helpful for debugging, the generic,
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 56eaa25..296d2b0 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -91,9 +91,9 @@
 static void early_serial_write(struct console *con, const char *s, unsigned n)
 {
 	while (*s && n-- > 0) {
-		early_serial_putc(*s);
 		if (*s == '\n')
 			early_serial_putc('\r');
+		early_serial_putc(*s);
 		s++;
 	}
 }
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index fa984b5..a67f87b 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -1163,3 +1163,10 @@
 	ret
 	CFI_ENDPROC
 ENDPROC(call_softirq)
+
+KPROBE_ENTRY(ignore_sysret)
+	CFI_STARTPROC
+	mov $-ENOSYS,%eax
+	sysret
+	CFI_ENDPROC
+ENDPROC(ignore_sysret)
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 1fab487..941c84ba 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -73,7 +73,11 @@
 	addq	%rbp, init_level4_pgt + (511*8)(%rip)
 
 	addq	%rbp, level3_ident_pgt + 0(%rip)
+
 	addq	%rbp, level3_kernel_pgt + (510*8)(%rip)
+	addq	%rbp, level3_kernel_pgt + (511*8)(%rip)
+
+	addq	%rbp, level2_fixmap_pgt + (506*8)(%rip)
 
 	/* Add an Identity mapping if I am above 1G */
 	leaq	_text(%rip), %rdi
@@ -314,7 +318,16 @@
 	.fill	510,8,0
 	/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
 	.quad	level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
-	.fill	1,8,0
+	.quad	level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+
+NEXT_PAGE(level2_fixmap_pgt)
+	.fill	506,8,0
+	.quad	level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
+	.fill	5,8,0
+
+NEXT_PAGE(level1_fixmap_pgt)
+	.fill	512,8,0
 
 NEXT_PAGE(level2_ident_pgt)
 	/* Since I easily can, map the first 1G.
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index d8bfe31..1c6c6f7 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1492,6 +1492,7 @@
 static void end_lapic_irq (unsigned int i) { /* nothing */ }
 
 static struct hw_interrupt_type lapic_irq_type __read_mostly = {
+	.name = "local-APIC",
 	.typename = "local-APIC-edge",
 	.startup = NULL, /* startup_irq() not used for IRQ0 */
 	.shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 3eaceac..39cb3fa 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -144,17 +144,43 @@
 
 	for (irq = 0; irq < NR_IRQS; irq++) {
 		cpumask_t mask;
+		int break_affinity = 0;
+		int set_affinity = 1;
+
 		if (irq == 2)
 			continue;
 
+		/* interrupt's are disabled at this point */
+		spin_lock(&irq_desc[irq].lock);
+
+		if (!irq_has_action(irq) ||
+		    cpus_equal(irq_desc[irq].affinity, map)) {
+			spin_unlock(&irq_desc[irq].lock);
+			continue;
+		}
+
 		cpus_and(mask, irq_desc[irq].affinity, map);
-		if (any_online_cpu(mask) == NR_CPUS) {
-			printk("Breaking affinity for irq %i\n", irq);
+		if (cpus_empty(mask)) {
+			break_affinity = 1;
 			mask = map;
 		}
+
+		if (irq_desc[irq].chip->mask)
+			irq_desc[irq].chip->mask(irq);
+
 		if (irq_desc[irq].chip->set_affinity)
 			irq_desc[irq].chip->set_affinity(irq, mask);
-		else if (irq_desc[irq].action && !(warned++))
+		else if (!(warned++))
+			set_affinity = 0;
+
+		if (irq_desc[irq].chip->unmask)
+			irq_desc[irq].chip->unmask(irq);
+
+		spin_unlock(&irq_desc[irq].lock);
+
+		if (break_affinity && set_affinity)
+			printk("Broke affinity for irq %i\n", irq);
+		else if (!set_affinity)
 			printk("Cannot set affinity for irq %i\n", irq);
 	}
 
diff --git a/arch/x86_64/kernel/k8.c b/arch/x86_64/kernel/k8.c
index bc11b32..7377ccb 100644
--- a/arch/x86_64/kernel/k8.c
+++ b/arch/x86_64/kernel/k8.c
@@ -39,10 +39,10 @@
 {
 	int i;
 	struct pci_dev *dev;
+
 	if (num_k8_northbridges)
 		return 0;
 
-	num_k8_northbridges = 0;
 	dev = NULL;
 	while ((dev = next_k8_northbridge(dev)) != NULL)
 		num_k8_northbridges++;
@@ -52,6 +52,11 @@
 	if (!k8_northbridges)
 		return -ENOMEM;
 
+	if (!num_k8_northbridges) {
+		k8_northbridges[0] = NULL;
+		return 0;
+	}
+
 	flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL);
 	if (!flush_words) {
 		kfree(k8_northbridges);
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index a14375d..aa1d159 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -497,15 +497,17 @@
 	for (i = 0; i < next; i++) {		
 		unsigned long start = jiffies;
 		while (!mcelog.entry[i].finished) {
-			if (!time_before(jiffies, start + 2)) {
+			if (time_after_eq(jiffies, start + 2)) {
 				memset(mcelog.entry + i,0, sizeof(struct mce));
-				continue;
+				goto timeout;
 			}
 			cpu_relax();
 		}
 		smp_rmb();
 		err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
 		buf += sizeof(struct mce); 
+ timeout:
+		;
 	} 
 
 	memset(mcelog.entry, 0, next * sizeof(struct mce));
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 931c64b..edbbc59 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -296,7 +296,7 @@
 static DEFINE_PER_CPU(local_t, alert_counter);
 static DEFINE_PER_CPU(int, nmi_touch);
 
-void touch_nmi_watchdog (void)
+void touch_nmi_watchdog(void)
 {
 	if (nmi_watchdog > 0) {
 		unsigned cpu;
@@ -306,8 +306,10 @@
 		 * do it ourselves because the alert count increase is not
 		 * atomic.
 		 */
-		for_each_present_cpu (cpu)
-			per_cpu(nmi_touch, cpu) = 1;
+		for_each_present_cpu(cpu) {
+			if (per_cpu(nmi_touch, cpu) != 1)
+				per_cpu(nmi_touch, cpu) = 1;
+		}
 	}
 
  	touch_softlockup_watchdog();
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 651ccfb..90f6315 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -22,8 +22,7 @@
 int iommu_bio_merge __read_mostly = 0;
 EXPORT_SYMBOL(iommu_bio_merge);
 
-int iommu_sac_force __read_mostly = 0;
-EXPORT_SYMBOL(iommu_sac_force);
+static int iommu_sac_force __read_mostly = 0;
 
 int no_iommu __read_mostly;
 #ifdef CONFIG_IOMMU_DEBUG
@@ -322,5 +321,17 @@
 	return 0;
 }
 
+#ifdef CONFIG_PCI
+/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+
+static __devinit void via_no_dac(struct pci_dev *dev)
+{
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+		printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+		forbid_dac = 1;
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+#endif
 /* Must execute after PCI subsystem */
 fs_initcall(pci_iommu_init);
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 9409117..fa6775e 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -313,17 +313,9 @@
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp,(unsigned long __user *) data);
+	case PTRACE_PEEKDATA:
+		ret = generic_ptrace_peekdata(child, addr, data);
 		break;
-	}
 
 	/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
@@ -367,10 +359,7 @@
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-			break;
-		ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c
index c116b54..7503068 100644
--- a/arch/x86_64/kernel/reboot.c
+++ b/arch/x86_64/kernel/reboot.c
@@ -8,6 +8,7 @@
 #include <linux/string.h>
 #include <linux/pm.h>
 #include <linux/kdebug.h>
+#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/delay.h>
 #include <asm/hw_irq.h>
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index eb6524f..33ef718 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -846,6 +846,8 @@
 			c->x86_capability[2] = cpuid_edx(0x80860001);
 	}
 
+	init_scattered_cpuid_features(c);
+
 	c->apicid = phys_pkg_id(0);
 
 	/*
@@ -931,7 +933,7 @@
 	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
 	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
 	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
-	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
+	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
 
 		/* AMD-defined */
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -947,10 +949,11 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Other (Linux-defined) */
-		"cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
-		"constant_tsc", NULL, NULL,
-		"up", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+		NULL, NULL, NULL, NULL,
+		"constant_tsc", "up", NULL, "arch_perfmon",
+		"pebs", "bts", NULL, "sync_rdtsc",
+		"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Intel-defined (#2) */
@@ -961,7 +964,7 @@
 
 		/* VIA/Cyrix/Centaur-defined */
 		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
@@ -972,6 +975,12 @@
 		"osvw", "ibs", NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+		/* Auxiliary (Linux-defined) */
+		"ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
 	static char *x86_power_flags[] = { 
 		"ts",	/* temperature sensor */
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 64379a8..1200aaa 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -150,6 +150,8 @@
 char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]
 __attribute__((section(".bss.page_aligned")));
 
+extern asmlinkage void ignore_sysret(void);
+
 /* May not be marked __init: used by software suspend */
 void syscall_init(void)
 {
@@ -160,6 +162,7 @@
 	 */ 
 	wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32); 
 	wrmsrl(MSR_LSTAR, system_call); 
+	wrmsrl(MSR_CSTAR, ignore_sysret);
 
 #ifdef CONFIG_IA32_EMULATION   		
 	syscall32_cpu_init ();
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 2ff4685..0694940 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -357,7 +357,7 @@
 }
 
 /*
- * smp_call_function_single - Run a function on another CPU
+ * smp_call_function_single - Run a function on a specific CPU
  * @func: The function to run. This must be fast and non-blocking.
  * @info: An arbitrary pointer to pass to the function.
  * @nonatomic: Currently unused.
@@ -374,14 +374,18 @@
 {
 	/* prevent preemption and reschedule on another processor */
 	int me = get_cpu();
-	if (cpu == me) {
-		put_cpu();
-		return 0;
-	}
 
 	/* Can deadlock when called with interrupts disabled */
 	WARN_ON(irqs_disabled());
 
+	if (cpu == me) {
+		local_irq_disable();
+		func(info);
+		local_irq_enable();
+		put_cpu();
+		return 0;
+	}
+
 	spin_lock_bh(&call_lock);
 	__smp_call_function_single(cpu, func, info, nonatomic, wait);
 	spin_unlock_bh(&call_lock);
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index cb29fb9..74cbeb2 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -330,6 +330,7 @@
 
 static void print_trace_address(void *data, unsigned long addr)
 {
+	touch_nmi_watchdog();
 	printk_address(addr);
 }
 
@@ -465,13 +466,14 @@
 
 unsigned __kprobes long oops_begin(void)
 {
-	int cpu = smp_processor_id();
+	int cpu;
 	unsigned long flags;
 
 	oops_enter();
 
 	/* racy, but better than risking deadlock. */
 	local_irq_save(flags);
+	cpu = smp_processor_id();
 	if (!spin_trylock(&die_lock)) { 
 		if (cpu == die_owner) 
 			/* nested oops. should stop eventually */;
@@ -517,6 +519,7 @@
 	printk("\n");
 	notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
 	show_registers(regs);
+	add_taint(TAINT_DIE);
 	/* Executive summary in case the oops scrolled away */
 	printk(KERN_ALERT "RIP ");
 	printk_address(regs->rip); 
@@ -530,7 +533,7 @@
 	unsigned long flags = oops_begin();
 
 	if (!user_mode(regs))
-		report_bug(regs->rip);
+		report_bug(regs->rip, regs);
 
 	__die(str, regs, err);
 	oops_end(flags);
diff --git a/arch/x86_64/kernel/verify_cpu.S b/arch/x86_64/kernel/verify_cpu.S
index e035f59..45b6f8a 100644
--- a/arch/x86_64/kernel/verify_cpu.S
+++ b/arch/x86_64/kernel/verify_cpu.S
@@ -37,20 +37,6 @@
 	pushl	$0			# Kill any dangerous flags
 	popfl
 
-	/* minimum CPUID flags for x86-64 as defined by AMD */
-#define M(x) (1<<(x))
-#define M2(a,b) M(a)|M(b)
-#define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d)
-
-#define SSE_MASK \
-	(M2(X86_FEATURE_XMM,X86_FEATURE_XMM2))
-#define REQUIRED_MASK1 \
-	(M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\
-	 M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\
-	 M(X86_FEATURE_FXSR))
-#define REQUIRED_MASK2 \
-	(M(X86_FEATURE_LM - 32))
-
 	pushfl				# standard way to check for cpuid
 	popl	%eax
 	movl	%eax,%ebx
@@ -79,8 +65,8 @@
 verify_cpu_noamd:
 	movl    $0x1,%eax		# Does the cpu have what it takes
 	cpuid
-	andl	$REQUIRED_MASK1,%edx
-	xorl	$REQUIRED_MASK1,%edx
+	andl	$REQUIRED_MASK0,%edx
+	xorl	$REQUIRED_MASK0,%edx
 	jnz	verify_cpu_no_longmode
 
 	movl    $0x80000000,%eax	# See if extended cpuid is implemented
@@ -90,8 +76,8 @@
 
 	movl    $0x80000001,%eax	# Does the cpu have what it takes
 	cpuid
-	andl    $REQUIRED_MASK2,%edx
-	xorl    $REQUIRED_MASK2,%edx
+	andl    $REQUIRED_MASK1,%edx
+	xorl    $REQUIRED_MASK1,%edx
 	jnz     verify_cpu_no_longmode
 
 verify_cpu_sse_test:
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 88cfa50..dbccfda 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -31,7 +31,7 @@
 	*(.bootstrap.text)
 	_stext = .;
 	/* Then the rest */
-	*(.text)
+	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
 	KPROBES_TEXT
@@ -55,7 +55,7 @@
   . = ALIGN(PAGE_SIZE);        /* Align data segment to page size boundary */
 				/* Data */
   .data : AT(ADDR(.data) - LOAD_OFFSET) {
-	*(.data)
+	DATA_DATA
 	CONSTRUCTORS
 	} :data
 
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index 51d4c6f..57660d5 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -175,10 +175,13 @@
  * unlikely */
 time_t __vsyscall(1) vtime(time_t *t)
 {
+	struct timeval tv;
 	time_t result;
 	if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
 		return time_syscall(t);
-	result = __vsyscall_gtod_data.wall_time_sec;
+
+	vgettimeofday(&tv, 0);
+	result = tv.tv_sec;
 	if (t)
 		*t = result;
 	return result;
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index bfb62a1..635e58d 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -476,6 +476,12 @@
 bad_area_nosemaphore:
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & PF_USER) {
+
+		/*
+		 * It's possible to have interrupts off here.
+		 */
+		local_irq_enable();
+
 		if (is_prefetch(regs, address, error_code))
 			return;
 
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 1336da8..9a0e98a 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -79,6 +79,8 @@
 			if (unlikely(i % MAX_ORDER_NR_PAGES == 0)) {
 				touch_nmi_watchdog();
 			}
+			if (!pfn_valid(pgdat->node_start_pfn + i))
+				continue;
 			page = pfn_to_page(pgdat->node_start_pfn + i);
 			total++;
 			if (PageReserved(page))
@@ -603,6 +605,11 @@
 	if (num_possible_cpus() > 1)
 		start = (unsigned long)_etext;
 #endif
+
+#ifdef CONFIG_KPROBES
+	start = (unsigned long)__start_rodata;
+#endif
+	
 	end = (unsigned long)__end_rodata;
 	start = (start + PAGE_SIZE - 1) & PAGE_MASK;
 	end &= PAGE_MASK;
@@ -761,3 +768,9 @@
 {
 	return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
 }
+
+void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+{
+	return __alloc_bootmem_core(pgdat->bdata, size,
+			SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
+}
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
index d653d0b..9148f4a 100644
--- a/arch/x86_64/mm/pageattr.c
+++ b/arch/x86_64/mm/pageattr.c
@@ -74,10 +74,11 @@
 	struct page *pg;
 
 	/* When clflush is available always use it because it is
-	   much cheaper than WBINVD */
-	if (!cpu_has_clflush)
+	   much cheaper than WBINVD. Disable clflush for now because
+	   the high level code is not ready yet */
+	if (1 || !cpu_has_clflush)
 		asm volatile("wbinvd" ::: "memory");
-	list_for_each_entry(pg, l, lru) {
+	else list_for_each_entry(pg, l, lru) {
 		void *adr = page_address(pg);
 		if (cpu_has_clflush)
 			cache_flush_page(adr);
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index 698079b..d0323cd 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -39,6 +39,7 @@
 	DEFINE(PT_LEND, offsetof (struct pt_regs, lend));
 	DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount));
 	DEFINE(PT_SAR, offsetof (struct pt_regs, sar));
+	DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel));
 	DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall));
 	DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0]));
 	DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 9e271ba..8dc7a2c 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -125,8 +125,9 @@
 
 	movi	a2, 0
 	rsr	a3, SAR
-	wsr	a2, ICOUNTLEVEL
+	xsr	a2, ICOUNTLEVEL
 	s32i	a3, a1, PT_SAR
+	s32i	a2, a1, PT_ICOUNTLEVEL
 
 	/* Rotate ws so that the current windowbase is at bit0. */
 	/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
@@ -276,8 +277,9 @@
 
 	movi	a2, 0
 	rsr	a3, SAR
-	wsr	a2, ICOUNTLEVEL
+	xsr	a2, ICOUNTLEVEL
 	s32i	a3, a1, PT_SAR
+	s32i	a2, a1, PT_ICOUNTLEVEL
 
 	/* Rotate ws so that the current windowbase is at bit0. */
 	/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
@@ -330,14 +332,16 @@
 
 common_exception:
 
-	/* Save EXCVADDR, DEBUGCAUSE, and PC, and clear LCOUNT */
+	/* Save some registers, disable loops and clear the syscall flag. */
 
 	rsr	a2, DEBUGCAUSE
 	rsr	a3, EPC_1
 	s32i	a2, a1, PT_DEBUGCAUSE
 	s32i	a3, a1, PT_PC
 
+	movi	a2, -1
 	rsr	a3, EXCVADDR
+	s32i	a2, a1, PT_SYSCALL
 	movi	a2, 0
 	s32i	a3, a1, PT_EXCVADDR
 	xsr	a2, LCOUNT
@@ -450,27 +454,8 @@
 
 	/* Restore the state of the task and return from the exception. */
 
-
-	/* If we are returning from a user exception, and the process
-	 * to run next has PT_SINGLESTEP set, we want to setup
-	 * ICOUNT and ICOUNTLEVEL to step one instruction.
-	 * PT_SINGLESTEP is set by sys_ptrace (ptrace.c)
-	 */
-
 4:	/* a2 holds GET_CURRENT(a2,a1)  */
 
-	l32i	a3, a2, TI_TASK
-	l32i	a3, a3, TASK_PTRACE
-	bbci.l	a3, PT_SINGLESTEP_BIT, 1f # jump if single-step flag is not set
-
-	movi	a3, -2			# PT_SINGLESTEP flag is set,
-	movi	a4, 1			# icountlevel of 1 means it won't
-	wsr	a3, ICOUNT		# start counting until after rfe
-	wsr	a4, ICOUNTLEVEL		# so setup icount & icountlevel.
-	isync
-
-1:
-
 #if XCHAL_EXTRA_SA_SIZE
 
 	/* For user exceptions, restore the extra state from the user's TCB. */
@@ -665,6 +650,13 @@
 	wsr	a3, LEND
 	wsr	a2, LCOUNT
 
+	/* We control single stepping through the ICOUNTLEVEL register. */
+
+	l32i	a2, a1, PT_ICOUNTLEVEL
+	movi	a3, -2
+	wsr	a2, ICOUNTLEVEL
+	wsr	a3, ICOUNT
+
 	/* Check if it was double exception. */
 
 	l32i	a0, a1, PT_DEPC
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index ea89910..67e6913 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -19,6 +19,8 @@
 #include <asm/page.h>
 #include <asm/cacheasm.h>
 
+#include <linux/linkage.h>
+
 /*
  * This module contains the entry code for kernel images. It performs the
  * minimal setup needed to call the generic C routines.
@@ -227,13 +229,14 @@
 should_never_return:
 	j	should_never_return
 
-	/* Define some common data structures here.  We define them
-	 * here in this assembly file due to their unusual alignment
-	 * requirements.
-	 */
 
-	.comm   swapper_pg_dir,PAGE_SIZE,PAGE_SIZE
-	.comm	empty_bad_page_table,PAGE_SIZE,PAGE_SIZE
-	.comm	empty_bad_page,PAGE_SIZE,PAGE_SIZE
-	.comm	empty_zero_page,PAGE_SIZE,PAGE_SIZE
+/*
+ * BSS section
+ */
+	
+.section ".bss.page_aligned", "w"
+ENTRY(swapper_pg_dir)
+	.fill	PAGE_SIZE, 1, 0
+ENTRY(empty_zero_page)
+	.fill	PAGE_SIZE, 1, 0
 
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 45571cc..77deae5 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -401,7 +401,7 @@
  * Also, think for a moment about likes of floppy.c that
  * include architecture specific parts. They may want to redefine ins/outs.
  *
- * We do not use horroble macroses here because we want to
+ * We do not use horrible macros here because we want to
  * advance pointer by sizeof(size).
  */
 void outsb(unsigned long addr, const void *src, unsigned long count) {
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 14104ff..06a13d9 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -50,18 +50,8 @@
 	switch (request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
 	case PTRACE_PEEKDATA:
-	{
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp,(unsigned long *) data);
-
+		ret = generic_ptrace_peekdata(child, addr, data);
 		goto out;
-	}
 
 	/* Read the word at location addr in the USER area.  */
 
@@ -138,10 +128,7 @@
 
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		if (access_process_vm(child, addr, &data, sizeof(data), 1)
-		    == sizeof(data))
-			break;
-		ret = -EIO;
+		ret = generic_ptrace_pokedata(child, addr, data);
 		goto out;
 
 	case PTRACE_POKEUSR:
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 1ecf671..2e8d398 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -41,6 +41,7 @@
 #include <asm/platform.h>
 #include <asm/page.h>
 #include <asm/setup.h>
+#include <asm/param.h>
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 5810767..033aae0 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -1,397 +1,239 @@
-// TODO coprocessor stuff
 /*
- *  linux/arch/xtensa/kernel/signal.c
+ * arch/xtensa/kernel/signal.c
  *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ * Default platform functions.
  *
- *  Joe Taylor <joe@tensilica.com>
- *  Chris Zankel <chris@zankel.net>
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  *
+ * Copyright (C) 2005, 2006 Tensilica Inc.
+ * Copyright (C) 1991, 1992  Linus Torvalds
+ * 1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  *
- *
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com>
  */
 
-#include <asm/variant/core.h>
-#include <asm/coprocessor.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
-#include <linux/wait.h>
 #include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
 #include <linux/personality.h>
+#include <linux/freezer.h>
+
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
-#include <asm/pgtable.h>
 #include <asm/cacheflush.h>
+#include <asm/coprocessor.h>
+#include <asm/unistd.h>
 
 #define DEBUG_SIG  0
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options,
-			  struct rusage * ru);
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
 
 extern struct task_struct *coproc_owners[];
 
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-
-int xtensa_sigsuspend(struct pt_regs *regs)
-{
-	old_sigset_t mask = (old_sigset_t) regs->areg[3];
-	sigset_t saveset;
-
-	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	siginitset(&current->blocked, mask);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->areg[2] = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(regs, &saveset))
-			return -EINTR;
-	}
-}
-
-asmlinkage int
-xtensa_rt_sigsuspend(struct pt_regs *regs)
-{
-	sigset_t *unewset = (sigset_t *) regs->areg[4];
-	size_t sigsetsize = (size_t) regs->areg[3];
-	sigset_t saveset, newset;
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->areg[2] = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(regs, &saveset))
-			return -EINTR;
-	}
-}
-
-asmlinkage int
-xtensa_sigaction(int sig, const struct old_sigaction *act,
-	      struct old_sigaction *oact)
-{
-	struct k_sigaction new_ka, old_ka;
-	int ret;
-
-	if (act) {
-		old_sigset_t mask;
-		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
-
-asmlinkage int
-xtensa_sigaltstack(struct pt_regs *regs)
-{
-	const stack_t *uss = (stack_t *) regs->areg[4];
-	stack_t *uoss = (stack_t *) regs->areg[3];
-
-	if (regs->depc > 64)
-		panic ("Double exception sys_sigreturn\n");
-
-
-	return do_sigaltstack(uss, uoss, regs->areg[1]);
-}
-
-
-/*
- * Do a signal return; undo the signal stack.
- */
-
-struct sigframe
-{
-	struct sigcontext sc;
-	struct _cpstate cpstate;
-	unsigned long extramask[_NSIG_WORDS-1];
-	unsigned char retcode[6];
-	unsigned int reserved[4]; /* Reserved area for chaining */
-	unsigned int window[4]; /* Window of 4 registers for initial context */
-};
+extern void release_all_cp (struct task_struct *);
 
 struct rt_sigframe
 {
 	struct siginfo info;
 	struct ucontext uc;
-	struct _cpstate cpstate;
+	cp_state_t cpstate;
 	unsigned char retcode[6];
-	unsigned int reserved[4]; /* Reserved area for chaining */
-	unsigned int window[4]; /* Window of 4 registers for initial context */
+	unsigned int window[4];
 };
 
-extern void release_all_cp (struct task_struct *);
-
-
-// FIXME restore_cpextra
-static inline int
-restore_cpextra (struct _cpstate *buf)
-{
-#if 0
-	/* The signal handler may have used coprocessors in which
-	 * case they are still enabled.  We disable them to force a
-	 * reloading of the original task's CP state by the lazy
-	 * context-switching mechanisms of CP exception handling.
-	 * Also, we essentially discard any coprocessor state that the
-	 * signal handler created. */
-
-	struct task_struct *tsk = current;
-	release_all_cp(tsk);
-	return __copy_from_user(tsk->thread.cpextra, buf, XTENSA_CP_EXTRA_SIZE);
-#endif
-	return 0;
-}
-
-/* Note: We don't copy double exception 'tregs', we have to finish double exc. first before we return to signal handler! This dbl.exc.handler might cause another double exception, but I think we are fine as the situation is the same as if we had returned to the signal handerl and got an interrupt immediately...
+/* 
+ * Flush register windows stored in pt_regs to stack.
+ * Returns 1 for errors.
+ *
+ * Note that windowbase, windowstart, and wmask are not updated!
  */
 
-
-static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+int
+flush_window_regs_user(struct pt_regs *regs)
 {
-	struct thread_struct *thread;
-	unsigned int err = 0;
-	unsigned long ps;
-	struct _cpstate *buf;
+	const unsigned long ws = regs->windowstart;
+	const unsigned long wb = regs->windowbase;
+	unsigned long sp = 0;
+	unsigned long wm;
+	int err = 1;
+	int base;
 
-#define COPY(x)	err |= __get_user(regs->x, &sc->sc_##x)
-	COPY(pc);
-	COPY(depc);
-	COPY(wmask);
-	COPY(lbeg);
-	COPY(lend);
-	COPY(lcount);
-	COPY(sar);
-	COPY(windowbase);
-	COPY(windowstart);
-#undef COPY
+	/* Return if no other frames. */
 
-	/* For PS, restore only PS.CALLINC.
-	 * Assume that all other bits are either the same as for the signal
-	 * handler, or the user mode value doesn't matter (e.g. PS.OWB).
-	 */
-	err |= __get_user(ps, &sc->sc_ps);
-	regs->ps = (regs->ps & ~PS_CALLINC_MASK)
-		| (ps & PS_CALLINC_MASK);
+	if (regs->wmask == 1)
+		return 0;
 
-	/* Additional corruption checks */
+	/* Rotate windowmask and skip empty frames. */
 
-	if ((regs->windowbase >= (XCHAL_NUM_AREGS/4))
-	|| ((regs->windowstart & ~((1<<(XCHAL_NUM_AREGS/4)) - 1)) != 0) )
-		err = 1;
-	if ((regs->lcount > 0)
-	&& ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
-		err = 1;
+	wm = (ws >> wb) | (ws << (XCHAL_NUM_AREGS / 4 - wb));
+	base = (XCHAL_NUM_AREGS / 4) - (regs->wmask >> 4);
+		
+	/* For call8 or call12 frames, we need the previous stack pointer. */
 
-	/* Restore extended register state.
-	 * See struct thread_struct in processor.h.
-	 */
-	thread = &current->thread;
+	if ((regs->wmask & 2) == 0)
+		if (__get_user(sp, (int*)(regs->areg[base * 4 + 1] - 12)))
+			goto errout;
 
-	err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4);
-	err |= __get_user(buf, &sc->sc_cpstate);
-	if (buf) {
-		if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
-			goto badframe;
-		err |= restore_cpextra(buf);
-	}
+	/* Spill frames to stack. */
 
-	regs->syscall = -1;		/* disable syscall checks */
-	return err;
+	while (base < XCHAL_NUM_AREGS / 4) {
 
-badframe:
-	return 1;
-}
+		int m = (wm >> base);
+		int inc = 0;
 
-static inline void
-flush_my_cpstate(struct task_struct *tsk)
-{
-	unsigned long flags;
-	local_irq_save(flags);
+		/* Save registers a4..a7 (call8) or a4...a11 (call12) */
 
-#if 0	// FIXME
-	for (i = 0; i < XCHAL_CP_NUM; i++) {
-		if (tsk == coproc_owners[i]) {
-			xthal_validate_cp(i);
-			xthal_save_cpregs(tsk->thread.cpregs_ptr[i], i);
+		if (m & 2) {			/* call4 */
+			inc = 1;
 
-			/* Invalidate and "disown" the cp to allow
-			 * callers the chance to reset cp state in the
-			 * task_struct. */
+		} else if (m & 4) {		/* call8 */
+			if (copy_to_user((void*)(sp - 32),
+					   &regs->areg[(base + 1) * 4], 16))
+				goto errout;
+			inc = 2;
 
-			xthal_invalidate_cp(i);
-			coproc_owners[i] = 0;
+		} else if (m & 8) {	/* call12 */
+			if (copy_to_user((void*)(sp - 48),
+					   &regs->areg[(base + 1) * 4], 32))
+				goto errout;
+			inc = 3;
 		}
+
+		/* Save current frame a0..a3 under next SP */
+
+		sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS];
+		if (copy_to_user((void*)(sp - 16), &regs->areg[base * 4], 16))
+			goto errout;
+
+		/* Get current stack pointer for next loop iteration. */
+
+		sp = regs->areg[base * 4 + 1];
+		base += inc;
 	}
-#endif
-	local_irq_restore(flags);
-}
 
-/* Return codes:
-	0:  nothing saved
-	1:  stuff to save, successful
-       -1:  stuff to save, error happened
-*/
-static int
-save_cpextra (struct _cpstate *buf)
-{
-#if XCHAL_CP_NUM == 0
 	return 0;
-#else
 
-	/* FIXME: If a task has never used a coprocessor, there is
-	 * no need to save and restore anything.  Tracking this
-	 * information would allow us to optimize this section.
-	 * Perhaps we can use current->used_math or (current->flags &
-	 * PF_USEDFPU) or define a new field in the thread
-	 * structure. */
-
-	/* We flush any live, task-owned cp state to the task_struct,
-	 * then copy it all to the sigframe.  Then we clear all
-	 * cp/extra state in the task_struct, effectively
-	 * clearing/resetting all cp/extra state for the signal
-	 * handler (cp-exception handling will load these new values
-	 * into the cp/extra registers.)  This step is important for
-	 * things like a floating-point cp, where the OS must reset
-	 * the FCR to the default rounding mode. */
-
-	int err = 0;
-	struct task_struct *tsk = current;
-
-	flush_my_cpstate(tsk);
-	/* Note that we just copy everything: 'extra' and 'cp' state together.*/
-	err |= __copy_to_user(buf, tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
-	memset(tsk->thread.cp_save, 0, XTENSA_CP_EXTRA_SIZE);
-
-#if (XTENSA_CP_EXTRA_SIZE == 0)
-#error Sanity check on memset above, cpextra_size should not be zero.
-#endif
-
-	return err ? -1 : 1;
-#endif
+errout:
+	return err;
 }
 
+/*
+ * Note: We don't copy double exception 'regs', we have to finish double exc. 
+ * first before we return to signal handler! This dbl.exc.handler might cause 
+ * another double exception, but I think we are fine as the situation is the 
+ * same as if we had returned to the signal handerl and got an interrupt 
+ * immediately...
+ */
+
 static int
-setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
+setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate,
 		 struct pt_regs *regs, unsigned long mask)
 {
-	struct thread_struct *thread;
 	int err = 0;
 
-//printk("setup_sigcontext\n");
 #define COPY(x)	err |= __put_user(regs->x, &sc->sc_##x)
 	COPY(pc);
 	COPY(ps);
-	COPY(depc);
-	COPY(wmask);
 	COPY(lbeg);
 	COPY(lend);
 	COPY(lcount);
 	COPY(sar);
-	COPY(windowbase);
-	COPY(windowstart);
 #undef COPY
 
-	/* Save extended register state.
-	 * See struct thread_struct in processor.h.
-	 */
-	thread = &current->thread;
-	err |= __copy_to_user (sc->sc_areg, regs->areg, XCHAL_NUM_AREGS * 4);
+	err |= flush_window_regs_user(regs);
+	err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4);
+
+	// err |= __copy_to_user (sc->sc_a, regs->areg, XCHAL_NUM_AREGS * 4)
+
+#if XCHAL_HAVE_CP
+# error Coprocessors unsupported
 	err |= save_cpextra(cpstate);
 	err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate);
+#endif
 	/* non-iBCS2 extensions.. */
 	err |= __put_user(mask, &sc->oldmask);
 
 	return err;
 }
 
-asmlinkage int xtensa_sigreturn(struct pt_regs *regs)
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
-	struct sigframe *frame = (struct sigframe *)regs->areg[1];
-	sigset_t set;
-	if (regs->depc > 64)
-		panic ("Double exception sys_sigreturn\n");
+	unsigned int err = 0;
+	unsigned long ps;
 
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto badframe;
+#define COPY(x)	err |= __get_user(regs->x, &sc->sc_##x)
+	COPY(pc);
+	COPY(lbeg);
+	COPY(lend);
+	COPY(lcount);
+	COPY(sar);
+#undef COPY
 
-	if (__get_user(set.sig[0], &frame->sc.oldmask)
-	    || (_NSIG_WORDS > 1
-		&& __copy_from_user(&set.sig[1], &frame->extramask,
-				    sizeof(frame->extramask))))
-		goto badframe;
+	/* All registers were flushed to stack. Start with a prestine frame. */
 
-	sigdelsetmask(&set, ~_BLOCKABLE);
+	regs->wmask = 1;
+	regs->windowbase = 0;
+	regs->windowstart = 1;
 
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	/* For PS, restore only PS.CALLINC.
+	 * Assume that all other bits are either the same as for the signal
+	 * handler, or the user mode value doesn't matter (e.g. PS.OWB).
+	 */
+	err |= __get_user(ps, &sc->sc_ps);
+	regs->ps = (regs->ps & ~PS_CALLINC_MASK) | (ps & PS_CALLINC_MASK);
 
-	if (restore_sigcontext(regs, &frame->sc))
-		goto badframe;
-	return regs->areg[2];
+	/* Additional corruption checks */
 
-badframe:
-	force_sig(SIGSEGV, current);
-	return 0;
+	if ((regs->lcount > 0)
+	    && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
+		err = 1;
+
+	err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4);
+
+#if XCHAL_HAVE_CP
+# error Coprocessors unsupported
+ 	/* The signal handler may have used coprocessors in which
+	 * case they are still enabled.  We disable them to force a
+	 * reloading of the original task's CP state by the lazy
+	 * context-switching mechanisms of CP exception handling.
+	 * Also, we essentially discard any coprocessor state that the
+	 * signal handler created. */
+
+	if (!err) {
+	  struct task_struct *tsk = current;
+	  release_all_cp(tsk);
+	  err |= __copy_from_user(tsk->thread.cpextra, sc->sc_cpstate, 
+	      			  XTENSA_CP_EXTRA_SIZE);
+	}
+#endif
+
+	regs->syscall = -1;		/* disable syscall checks */
+	return err;
 }
 
-asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs)
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
+				    long a4, long a5, struct pt_regs *regs)
 {
-	struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
+	struct rt_sigframe __user *frame;
 	sigset_t set;
-	stack_t st;
 	int ret;
+
 	if (regs->depc > 64)
-	{
-		printk("!!!!!!! DEPC !!!!!!!\n");
-		return 0;
-	}
+		panic("rt_sigreturn in double exception!\n");
+
+	frame = (struct rt_sigframe __user *) regs->areg[1];
 
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -407,13 +249,11 @@
 
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 		goto badframe;
+
 	ret = regs->areg[2];
 
-	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->areg[1]) == -EFAULT)
 		goto badframe;
-	/* It is more difficult to avoid calling this function than to
-	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, regs->areg[1]);
 
 	return ret;
 
@@ -422,77 +262,50 @@
 	return 0;
 }
 
+
+
 /*
  * Set up a signal frame.
  */
 
-/*
- * Determine which stack to use..
- */
-static inline void *
-get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
-{
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
-
-	return (void *)((sp - frame_size) & -16ul);
-}
-
-#define USE_SIGRETURN		0
-#define USE_RT_SIGRETURN	1
-
 static int
-gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
+gen_return_code(unsigned char *codemem)
 {
-	unsigned int retcall;
 	int err = 0;
 
-#if 0
-	/* Ignoring SA_RESTORER for now; it's supposed to be obsolete,
-	 * and the xtensa glibc doesn't use it.
+	/*
+	 * The 12-bit immediate is really split up within the 24-bit MOVI
+	 * instruction.  As long as the above system call numbers fit within
+	 * 8-bits, the following code works fine. See the Xtensa ISA for
+	 * details.
 	 */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->pr = (unsigned long) ka->sa.sa_restorer;
-	} else
-#endif /* 0 */
-	{
 
-#if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255)
-
-/* The 12-bit immediate is really split up within the 24-bit MOVI
- * instruction.  As long as the above system call numbers fit within
- * 8-bits, the following code works fine. See the Xtensa ISA for
- * details.
- */
-
-#error Generating the MOVI instruction below breaks!
+#if __NR_rt_sigreturn > 255
+# error Generating the MOVI instruction below breaks!
 #endif
 
-		retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn;
-
 #ifdef __XTENSA_EB__   /* Big Endian version */
-		/* Generate instruction:  MOVI a2, retcall */
-		err |= __put_user(0x22, &codemem[0]);
-		err |= __put_user(0x0a, &codemem[1]);
-		err |= __put_user(retcall, &codemem[2]);
-		/* Generate instruction:  SYSCALL */
-		err |= __put_user(0x00, &codemem[3]);
-		err |= __put_user(0x05, &codemem[4]);
-		err |= __put_user(0x00, &codemem[5]);
+	/* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
+	err |= __put_user(0x22, &codemem[0]);
+	err |= __put_user(0x0a, &codemem[1]);
+	err |= __put_user(__NR_rt_sigreturn, &codemem[2]);
+	/* Generate instruction:  SYSCALL */
+	err |= __put_user(0x00, &codemem[3]);
+	err |= __put_user(0x05, &codemem[4]);
+	err |= __put_user(0x00, &codemem[5]);
 
 #elif defined __XTENSA_EL__   /* Little Endian version */
-		/* Generate instruction:  MOVI a2, retcall */
-		err |= __put_user(0x22, &codemem[0]);
-		err |= __put_user(0xa0, &codemem[1]);
-		err |= __put_user(retcall, &codemem[2]);
-		/* Generate instruction:  SYSCALL */
-		err |= __put_user(0x00, &codemem[3]);
-		err |= __put_user(0x50, &codemem[4]);
-		err |= __put_user(0x00, &codemem[5]);
+	/* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
+	err |= __put_user(0x22, &codemem[0]);
+	err |= __put_user(0xa0, &codemem[1]);
+	err |= __put_user(__NR_rt_sigreturn, &codemem[2]);
+	/* Generate instruction:  SYSCALL */
+	err |= __put_user(0x00, &codemem[3]);
+	err |= __put_user(0x50, &codemem[4]);
+	err |= __put_user(0x00, &codemem[5]);
 #else
-#error Must use compiler for Xtensa processors.
+# error Must use compiler for Xtensa processors.
 #endif
-	}
 
 	/* Flush generated code out of the data cache */
 
@@ -504,97 +317,29 @@
 	return err;
 }
 
-static void
-set_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr,
-	void *handler, unsigned long arg1, void *arg2, void *arg3)
-{
-	/* Set up registers for signal handler */
-	start_thread(regs, (unsigned long) handler, (unsigned long) stack);
 
-	/* Set up a stack frame for a call4
-	 * Note: PS.CALLINC is set to one by start_thread
-	 */
-	regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000;
-	regs->areg[6] = arg1;
-	regs->areg[7] = (unsigned long) arg2;
-	regs->areg[8] = (unsigned long) arg3;
-}
-
-static void setup_frame(int sig, struct k_sigaction *ka,
+static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			sigset_t *set, struct pt_regs *regs)
 {
-	struct sigframe *frame;
-	int err = 0;
-	int signal;
-
-	frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
-	if (regs->depc > 64)
-	{
-		printk("!!!!!!! DEPC !!!!!!!\n");
-		return;
-	}
-
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
-
-	signal = current_thread_info()->exec_domain
-		&& current_thread_info()->exec_domain->signal_invmap
-		&& sig < 32
-		? current_thread_info()->exec_domain->signal_invmap[sig]
-		: sig;
-
-	err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]);
-
-	if (_NSIG_WORDS > 1) {
-		err |= __copy_to_user(frame->extramask, &set->sig[1],
-				      sizeof(frame->extramask));
-	}
-
-	/* Create sys_sigreturn syscall in stack frame */
-	err |= gen_return_code(frame->retcode, USE_SIGRETURN);
-
-	if (err)
-		goto give_sigsegv;
-
-	/* Create signal handler execution context.
-	 * Return context not modified until this point.
-	 */
-	set_thread_state(regs, frame, frame->retcode,
-		ka->sa.sa_handler, signal, &frame->sc, NULL);
-
-	/* Set access mode to USER_DS.  Nomenclature is outdated, but
-	 * functionality is used in uaccess.h
-	 */
-	set_fs(USER_DS);
-
-
-#if DEBUG_SIG
-	printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
-		current->comm, current->pid, signal, frame, regs->pc);
-#endif
-
-	return;
-
-give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
-}
-
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			   sigset_t *set, struct pt_regs *regs)
-{
 	struct rt_sigframe *frame;
 	int err = 0;
 	int signal;
+	unsigned long sp, ra;
 
-	frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
+	sp = regs->areg[1];
+
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) {
+		sp = current->sas_ss_sp + current->sas_ss_size;
+	}
+
+	frame = (void *)((sp - sizeof(*frame)) & -16ul);
+
 	if (regs->depc > 64)
 		panic ("Double exception sys_sigreturn\n");
 
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
 		goto give_sigsegv;
+	}
 
 	signal = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -602,9 +347,12 @@
 		? current_thread_info()->exec_domain->signal_invmap[sig]
 		: sig;
 
-	err |= copy_siginfo_to_user(&frame->info, info);
+	if (ka->sa.sa_flags & SA_SIGINFO) {
+		err |= copy_siginfo_to_user(&frame->info, info);
+	}
 
-	/* Create the ucontext.  */
+	/* Create the user context.  */
+
 	err |= __put_user(0, &frame->uc.uc_flags);
 	err |= __put_user(0, &frame->uc.uc_link);
 	err |= __put_user((void *)current->sas_ss_sp,
@@ -617,16 +365,31 @@
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
 	/* Create sys_rt_sigreturn syscall in stack frame */
-	err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN);
 
-	if (err)
+	err |= gen_return_code(frame->retcode);
+
+	if (err) {
 		goto give_sigsegv;
+	}
+		
 
-	/* Create signal handler execution context.
+	/* 
+	 * Create signal handler execution context.
 	 * Return context not modified until this point.
 	 */
-	set_thread_state(regs, frame, frame->retcode,
-		ka->sa.sa_handler, signal, &frame->info, &frame->uc);
+
+	/* Set up registers for signal handler */
+	start_thread(regs, (unsigned long) ka->sa.sa_handler, 
+		     (unsigned long) frame);
+
+	/* Set up a stack frame for a call4
+	 * Note: PS.CALLINC is set to one by start_thread
+	 */
+	ra = (unsigned long) frame->retcode;
+	regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000;
+	regs->areg[6] = (unsigned long) signal;
+	regs->areg[7] = (unsigned long) &frame->info;
+	regs->areg[8] = (unsigned long) &frame->uc;
 
 	/* Set access mode to USER_DS.  Nomenclature is outdated, but
 	 * functionality is used in uaccess.h
@@ -646,6 +409,48 @@
 	force_sig(SIGSEGV, current);
 }
 
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+
+asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, 
+    				     size_t sigsetsize,
+    				     long a2, long a3, long a4, long a5, 
+				     struct pt_regs *regs)
+{
+	sigset_t saveset, newset;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+
+	sigdelsetmask(&newset, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	regs->areg[2] = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(regs, &saveset))
+			return -EINTR;
+	}
+}
+
+asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, 
+				   stack_t __user *uoss,
+    				   long a2, long a3, long a4, long a5,
+				   struct pt_regs *regs)
+{
+	return do_sigaltstack(uss, uoss, regs->areg[1]);
+}
+
 
 
 /*
@@ -663,51 +468,89 @@
 	int signr;
 	struct k_sigaction ka;
 
+	if (!user_mode(regs))
+		return 0;
+
+	if (try_to_freeze())
+		goto no_signal;
+
 	if (!oldset)
 		oldset = &current->blocked;
 
+	task_pt_regs(current)->icountlevel = 0;
+
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	/* Are we from a system call? */
-	if (regs->syscall >= 0) {
-		/* If so, check system call restarting.. */
-		switch (regs->areg[2]) {
-			case ERESTARTNOHAND:
-			case ERESTART_RESTARTBLOCK:
-				regs->areg[2] = -EINTR;
-				break;
+	if (signr > 0) {
 
-			case ERESTARTSYS:
-				if (!(ka.sa.sa_flags & SA_RESTART)) {
+		/* Are we from a system call? */
+
+		if ((signed)regs->syscall >= 0) {
+
+			/* If so, check system call restarting.. */
+
+			switch (regs->areg[2]) {
+				case -ERESTARTNOHAND:
+				case -ERESTART_RESTARTBLOCK:
 					regs->areg[2] = -EINTR;
 					break;
-				}
-			/* fallthrough */
-			case ERESTARTNOINTR:
-				regs->areg[2] = regs->syscall;
-				regs->pc -= 3;
+
+				case -ERESTARTSYS:
+					if (!(ka.sa.sa_flags & SA_RESTART)) {
+						regs->areg[2] = -EINTR;
+						break;
+					}
+					/* fallthrough */
+				case -ERESTARTNOINTR:
+					regs->areg[2] = regs->syscall;
+					regs->pc -= 3;
+					break;
+
+				default:
+					/* nothing to do */
+					if (regs->areg[2] != 0)
+					break;
+			}
 		}
+
+		/* Whee!  Actually deliver the signal.  */
+		/* Set up the stack frame */
+		setup_frame(signr, &ka, &info, oldset, regs);
+
+		if (ka.sa.sa_flags & SA_ONESHOT)
+			ka.sa.sa_handler = SIG_DFL;
+
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+		if (!(ka.sa.sa_flags & SA_NODEFER))
+			sigaddset(&current->blocked, signr);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+		if (current->ptrace & PT_SINGLESTEP)
+			task_pt_regs(current)->icountlevel = 1;
+
+		return 1;
 	}
 
-	if (signr == 0)
-		return 0;		/* no signals delivered */
-
-	/* Whee!  Actually deliver the signal.  */
-
-	/* Set up the stack frame */
-	if (ka.sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame(signr, &ka, &info, oldset, regs);
-	else
-		setup_frame(signr, &ka, oldset, regs);
-
-	if (ka.sa.sa_flags & SA_ONESHOT)
-		ka.sa.sa_handler = SIG_DFL;
-
-	spin_lock_irq(&current->sighand->siglock);
-	sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
-	if (!(ka.sa.sa_flags & SA_NODEFER))
-		sigaddset(&current->blocked, signr);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	return 1;
+no_signal:
+	/* Did we come from a system call? */
+	if ((signed) regs->syscall >= 0) {
+		/* Restart the system call - no handlers present */
+		switch (regs->areg[2]) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->areg[2] = regs->syscall;
+			regs->pc -= 3;
+			break;
+		case -ERESTART_RESTARTBLOCK:
+			regs->areg[2] = __NR_restart_syscall;
+			regs->pc -= 3;
+			break;
+		}
+	}
+	if (current->ptrace & PT_SINGLESTEP)
+		task_pt_regs(current)->icountlevel = 1;
+	return 0;
 }
+
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 693ab26..c5e62f9 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -482,6 +482,7 @@
 	if (!user_mode(regs))
 		show_stack(NULL, (unsigned long*)regs->areg[1]);
 
+	add_taint(TAINT_DIE);
 	spin_unlock_irq(&die_lock);
 
 	if (in_interrupt())
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 4fbd66a..b0582c3 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -85,7 +85,6 @@
     /* The .head.text section must be the first section! */
     *(.head.text)
     *(.literal .text)
-    *(.srom.text)
     VMLINUX_SYMBOL(__sched_text_start) = .;
     *(.sched.literal .sched.text)
     VMLINUX_SYMBOL(__sched_text_end) = .;
@@ -95,6 +94,7 @@
 
   }
   _etext = .;
+  PROVIDE (etext = .);
 
   . = ALIGN(16);
 
@@ -102,32 +102,6 @@
 
   /*  Relocation table */
 
-  . = ALIGN(16);
-  __boot_reloc_table_start = ABSOLUTE(.);
-
-  __relocate : {
-
-    RELOCATE_ENTRY(_WindowVectors_text,
-		   .WindowVectors.text);
-#if 0
-    RELOCATE_ENTRY(_KernelExceptionVector_literal,
-		   .KernelExceptionVector.literal);
-#endif
-    RELOCATE_ENTRY(_KernelExceptionVector_text,
-		   .KernelExceptionVector.text);
-#if 0
-    RELOCATE_ENTRY(_UserExceptionVector_literal,
-		   .UserExceptionVector.literal);
-#endif
-    RELOCATE_ENTRY(_UserExceptionVector_text,
-		   .UserExceptionVector.text);
-    RELOCATE_ENTRY(_DoubleExceptionVector_literal,
-		   .DoubleExceptionVector.literal);
-    RELOCATE_ENTRY(_DoubleExceptionVector_text,
-		   .DoubleExceptionVector.text);
-  }
-  __boot_reloc_table_end = ABSOLUTE(.) ;
-
   .fixup   : { *(.fixup) }
 
   . = ALIGN(16);
@@ -172,6 +146,22 @@
     __tagtable_begin = .;
     *(.taglist)
     __tagtable_end = .;
+
+    . = ALIGN(16);
+    __boot_reloc_table_start = ABSOLUTE(.);
+
+    RELOCATE_ENTRY(_WindowVectors_text,
+		   .WindowVectors.text);
+    RELOCATE_ENTRY(_KernelExceptionVector_text,
+		   .KernelExceptionVector.text);
+    RELOCATE_ENTRY(_UserExceptionVector_text,
+		   .UserExceptionVector.text);
+    RELOCATE_ENTRY(_DoubleExceptionVector_literal,
+		   .DoubleExceptionVector.literal);
+    RELOCATE_ENTRY(_DoubleExceptionVector_text,
+		   .DoubleExceptionVector.text);
+  
+    __boot_reloc_table_end = ABSOLUTE(.) ;
   }
 
   . = ALIGN(XCHAL_ICACHE_LINESIZE);
@@ -192,16 +182,6 @@
 
   SECURITY_INIT
 
-  . = ALIGN(4);
-
-  __start___ftr_fixup = .;
-  __ftr_fixup : { *(__ftr_fixup) }
-  __stop___ftr_fixup = .;
-
-  . = ALIGN(4096);
-  __per_cpu_start = .;
-  .data.percpu  : { *(.data.percpu) }
-  __per_cpu_end = .;
 
 #ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(4096);
@@ -210,6 +190,12 @@
   __initramfs_end = .;
 #endif
 
+  . = ALIGN(4096);
+  __per_cpu_start = .;
+  .data.percpu  : { *(.data.percpu) }
+  __per_cpu_end = .;
+
+
   /* We need this dummy segment here */
 
   . = ALIGN(4);
@@ -271,9 +257,9 @@
 
   /* BSS section */
   _bss_start = .;
-  .sbss : { *(.sbss) *(.scommon) }
-  .bss : { *(COMMON) *(.bss) }
+  .bss : { *(.bss.page_aligned) *(.bss) }
   _bss_end = .;
+
   _end = .;
 
   /* only used by the boot loader  */
@@ -291,16 +277,16 @@
     *(.ResetVector.text)
   }
 
-
   /* Sections to be discarded */
   /DISCARD/ :
   {
-        *(.text.exit)
-	*(.text.exit.literal)
-        *(.data.exit)
+  	*(.exit.literal .exit.text)
+  	*(.exit.data)
         *(.exitcall.exit)
   }
 
+  .xt.lit : { *(.xt.lit) }
+  .xt.prop : { *(.xt.prop) }
 
   .debug  0 :  { *(.debug) }
   .line  0 :  { *(.line) }
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index cd7e6a0..60dbdb4 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -38,21 +38,10 @@
 /*
  * String functions
  */
-EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
 
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(kernel_thread);
 
 /*
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S
index a834057..b2655d9 100644
--- a/arch/xtensa/lib/strncpy_user.S
+++ b/arch/xtensa/lib/strncpy_user.S
@@ -25,18 +25,18 @@
 /*
  * char *__strncpy_user(char *dst, const char *src, size_t len)
  */
-.text
-.begin literal
-.align	4
-.Lmask0:
-	.byte	0xff, 0x00, 0x00, 0x00
-.Lmask1:
-	.byte	0x00, 0xff, 0x00, 0x00
-.Lmask2:
-	.byte	0x00, 0x00, 0xff, 0x00
-.Lmask3:
-	.byte	0x00, 0x00, 0x00, 0xff
-.end literal
+
+#ifdef __XTENSA_EB__
+# define MASK0 0xff000000
+# define MASK1 0x00ff0000
+# define MASK2 0x0000ff00
+# define MASK3 0x000000ff
+#else
+# define MASK0 0x000000ff
+# define MASK1 0x0000ff00
+# define MASK2 0x00ff0000
+# define MASK3 0xff000000
+#endif
 
 # Register use
 #   a0/ return address
@@ -53,6 +53,7 @@
 #   a11/ dst
 #   a12/ tmp
 
+.text
 .align	4
 .global	__strncpy_user
 .type	__strncpy_user,@function
@@ -61,10 +62,10 @@
 	# a2/ dst, a3/ src, a4/ len
 	mov	a11, a2		# leave dst in return value register
 	beqz	a4, .Lret	# if len is zero
-	l32r	a5, .Lmask0	# mask for byte 0
-	l32r	a6, .Lmask1	# mask for byte 1
-	l32r	a7, .Lmask2	# mask for byte 2
-	l32r	a8, .Lmask3	# mask for byte 3
+	movi	a5, MASK0	# mask for byte 0
+	movi	a6, MASK1	# mask for byte 1
+	movi	a7, MASK2	# mask for byte 2
+	movi	a8, MASK3	# mask for byte 3
 	bbsi.l	a3, 0, .Lsrc1mod2 # if only  8-bit aligned
 	bbsi.l	a3, 1, .Lsrc2mod4 # if only 16-bit aligned
 .Lsrcaligned:	# return here when src is word-aligned
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S
index 5e9c1e7..ad3f616 100644
--- a/arch/xtensa/lib/strnlen_user.S
+++ b/arch/xtensa/lib/strnlen_user.S
@@ -24,18 +24,18 @@
 /*
  * size_t __strnlen_user(const char *s, size_t len)
  */
-.text
-.begin literal
-.align	4
-.Lmask0:
-	.byte	0xff, 0x00, 0x00, 0x00
-.Lmask1:
-	.byte	0x00, 0xff, 0x00, 0x00
-.Lmask2:
-	.byte	0x00, 0x00, 0xff, 0x00
-.Lmask3:
-	.byte	0x00, 0x00, 0x00, 0xff
-.end literal
+
+#ifdef __XTENSA_EB__
+# define MASK0 0xff000000
+# define MASK1 0x00ff0000
+# define MASK2 0x0000ff00
+# define MASK3 0x000000ff
+#else
+# define MASK0 0x000000ff
+# define MASK1 0x0000ff00
+# define MASK2 0x00ff0000
+# define MASK3 0xff000000
+#endif
 
 # Register use:
 #   a2/ src
@@ -48,6 +48,7 @@
 #   a9/ tmp
 #   a10/ tmp
 
+.text
 .align	4
 .global	__strnlen_user
 .type	__strnlen_user,@function
@@ -56,10 +57,10 @@
 	# a2/ s, a3/ len
 	addi	a4, a2, -4	# because we overincrement at the end;
 				# we compensate with load offsets of 4
-	l32r	a5, .Lmask0	# mask for byte 0
-	l32r	a6, .Lmask1	# mask for byte 1
-	l32r	a7, .Lmask2	# mask for byte 2
-	l32r	a8, .Lmask3	# mask for byte 3
+	movi	a5, MASK0	# mask for byte 0
+	movi	a6, MASK1	# mask for byte 1
+	movi	a7, MASK2	# mask for byte 2
+	movi	a8, MASK3	# mask for byte 3
 	bbsi.l	a2, 0, .L1mod2	# if only  8-bit aligned
 	bbsi.l	a2, 1, .L2mod4	# if only 16-bit aligned
 
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index e1ec2d1..8415c76 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -205,7 +205,7 @@
 	/* Writing zeros to the <t>TLBCFG special registers ensure
 	 * that valid values exist in the register.  For existing
 	 * PGSZID<w> fields, zero selects the first element of the
-	 * page-size array.  For nonexistant PGSZID<w> fields, zero is
+	 * page-size array.  For nonexistent PGSZID<w> fields, zero is
 	 * the best value to write.  Also, when changing PGSZID<w>
 	 * fields, the corresponding TLB must be flushed.
 	 */
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
index 4bfe333..f09962f 100644
--- a/arch/xtensa/platform-iss/network.c
+++ b/arch/xtensa/platform-iss/network.c
@@ -473,7 +473,7 @@
 	netif_start_queue(dev);
 
 	/* clear buffer - it can happen that the host side of the interface
-	 * is full when we gethere. In this case, new data is never queued,
+	 * is full when we get here. In this case, new data is never queued,
 	 * SIGIOs never arrive, and the net never works.
 	 */
 	while ((err = iss_net_rx(dev)) > 0)
diff --git a/block/Kconfig b/block/Kconfig
index a50f481..0768741 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -1,7 +1,7 @@
 #
 # Block layer core configuration
 #
-config BLOCK
+menuconfig BLOCK
        bool "Enable the block layer" if EMBEDDED
        default y
        help
@@ -49,6 +49,19 @@
 
 	  If unsure, say Y.
 
-endif
+endif # BLOCK
+
+config BLK_DEV_BSG
+	bool "Block layer SG support v4 (EXPERIMENTAL)"
+	depends on (SCSI=y) && EXPERIMENTAL
+	---help---
+	Saying Y here will enable generic SG (SCSI generic) v4 support
+	for any block device.
+
+	Unlike SG v3 (aka block/scsi_ioctl.c drivers/scsi/sg.c), SG v4
+	can handle complicated SCSI commands: tagged variable length cdbs
+	with bidirectional data transfers and generic request/response
+	protocols (e.g. Task Management Functions and SMP in Serial
+	Attached SCSI).
 
 source block/Kconfig.iosched
diff --git a/block/Makefile b/block/Makefile
index 4b84d0d..959feeb 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
 
+obj-$(CONFIG_BLK_DEV_BSG)	+= bsg.o
 obj-$(CONFIG_IOSCHED_NOOP)	+= noop-iosched.o
 obj-$(CONFIG_IOSCHED_AS)	+= as-iosched.o
 obj-$(CONFIG_IOSCHED_DEADLINE)	+= deadline-iosched.o
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 109e91b..3e316dd 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1322,10 +1322,9 @@
 {
 	struct as_data *ad;
 
-	ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
+	ad = kmalloc_node(sizeof(*ad), GFP_KERNEL | __GFP_ZERO, q->node);
 	if (!ad)
 		return NULL;
-	memset(ad, 0, sizeof(*ad));
 
 	ad->q = q; /* Identify what queue the data belongs to */
 
diff --git a/block/bsg.c b/block/bsg.c
new file mode 100644
index 0000000..baa04e7
--- /dev/null
+++ b/block/bsg.c
@@ -0,0 +1,1095 @@
+/*
+ * bsg.c - block layer implementation of the sg v3 interface
+ *
+ * Copyright (C) 2004 Jens Axboe <axboe@suse.de> SUSE Labs
+ * Copyright (C) 2004 Peter M. Jones <pjones@redhat.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License version 2.  See the file "COPYING" in the main directory of this
+ *  archive for more details.
+ *
+ */
+/*
+ * TODO
+ *	- Should this get merged, block/scsi_ioctl.c will be migrated into
+ *	  this file. To keep maintenance down, it's easier to have them
+ *	  seperated right now.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/blkdev.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/percpu.h>
+#include <linux/uio.h>
+#include <linux/bsg.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/sg.h>
+
+#define BSG_DESCRIPTION	"Block layer SCSI generic (bsg) driver"
+#define BSG_VERSION	"0.4"
+
+struct bsg_device {
+	request_queue_t *queue;
+	spinlock_t lock;
+	struct list_head busy_list;
+	struct list_head done_list;
+	struct hlist_node dev_list;
+	atomic_t ref_count;
+	int minor;
+	int queued_cmds;
+	int done_cmds;
+	wait_queue_head_t wq_done;
+	wait_queue_head_t wq_free;
+	char name[BUS_ID_SIZE];
+	int max_queue;
+	unsigned long flags;
+};
+
+enum {
+	BSG_F_BLOCK		= 1,
+	BSG_F_WRITE_PERM	= 2,
+};
+
+#define BSG_DEFAULT_CMDS	64
+#define BSG_MAX_DEVS		32768
+
+#undef BSG_DEBUG
+
+#ifdef BSG_DEBUG
+#define dprintk(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ##args)
+#else
+#define dprintk(fmt, args...)
+#endif
+
+static DEFINE_MUTEX(bsg_mutex);
+static int bsg_device_nr, bsg_minor_idx;
+
+#define BSG_LIST_ARRAY_SIZE	8
+static struct hlist_head bsg_device_list[BSG_LIST_ARRAY_SIZE];
+
+static struct class *bsg_class;
+static LIST_HEAD(bsg_class_list);
+static int bsg_major;
+
+static struct kmem_cache *bsg_cmd_cachep;
+
+/*
+ * our internal command type
+ */
+struct bsg_command {
+	struct bsg_device *bd;
+	struct list_head list;
+	struct request *rq;
+	struct bio *bio;
+	struct bio *bidi_bio;
+	int err;
+	struct sg_io_v4 hdr;
+	struct sg_io_v4 __user *uhdr;
+	char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static void bsg_free_command(struct bsg_command *bc)
+{
+	struct bsg_device *bd = bc->bd;
+	unsigned long flags;
+
+	kmem_cache_free(bsg_cmd_cachep, bc);
+
+	spin_lock_irqsave(&bd->lock, flags);
+	bd->queued_cmds--;
+	spin_unlock_irqrestore(&bd->lock, flags);
+
+	wake_up(&bd->wq_free);
+}
+
+static struct bsg_command *bsg_alloc_command(struct bsg_device *bd)
+{
+	struct bsg_command *bc = ERR_PTR(-EINVAL);
+
+	spin_lock_irq(&bd->lock);
+
+	if (bd->queued_cmds >= bd->max_queue)
+		goto out;
+
+	bd->queued_cmds++;
+	spin_unlock_irq(&bd->lock);
+
+	bc = kmem_cache_zalloc(bsg_cmd_cachep, GFP_KERNEL);
+	if (unlikely(!bc)) {
+		spin_lock_irq(&bd->lock);
+		bd->queued_cmds--;
+		bc = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	bc->bd = bd;
+	INIT_LIST_HEAD(&bc->list);
+	dprintk("%s: returning free cmd %p\n", bd->name, bc);
+	return bc;
+out:
+	spin_unlock_irq(&bd->lock);
+	return bc;
+}
+
+static inline struct hlist_head *bsg_dev_idx_hash(int index)
+{
+	return &bsg_device_list[index & (BSG_LIST_ARRAY_SIZE - 1)];
+}
+
+static int bsg_io_schedule(struct bsg_device *bd)
+{
+	DEFINE_WAIT(wait);
+	int ret = 0;
+
+	spin_lock_irq(&bd->lock);
+
+	BUG_ON(bd->done_cmds > bd->queued_cmds);
+
+	/*
+	 * -ENOSPC or -ENODATA?  I'm going for -ENODATA, meaning "I have no
+	 * work to do", even though we return -ENOSPC after this same test
+	 * during bsg_write() -- there, it means our buffer can't have more
+	 * bsg_commands added to it, thus has no space left.
+	 */
+	if (bd->done_cmds == bd->queued_cmds) {
+		ret = -ENODATA;
+		goto unlock;
+	}
+
+	if (!test_bit(BSG_F_BLOCK, &bd->flags)) {
+		ret = -EAGAIN;
+		goto unlock;
+	}
+
+	prepare_to_wait(&bd->wq_done, &wait, TASK_UNINTERRUPTIBLE);
+	spin_unlock_irq(&bd->lock);
+	io_schedule();
+	finish_wait(&bd->wq_done, &wait);
+
+	return ret;
+unlock:
+	spin_unlock_irq(&bd->lock);
+	return ret;
+}
+
+static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq,
+				struct sg_io_v4 *hdr, int has_write_perm)
+{
+	memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
+
+	if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request,
+			   hdr->request_len))
+		return -EFAULT;
+
+	if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
+		if (blk_verify_command(rq->cmd, has_write_perm))
+			return -EPERM;
+	} else if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	/*
+	 * fill in request structure
+	 */
+	rq->cmd_len = hdr->request_len;
+	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+
+	rq->timeout = (hdr->timeout * HZ) / 1000;
+	if (!rq->timeout)
+		rq->timeout = q->sg_timeout;
+	if (!rq->timeout)
+		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+
+	return 0;
+}
+
+/*
+ * Check if sg_io_v4 from user is allowed and valid
+ */
+static int
+bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw)
+{
+	int ret = 0;
+
+	if (hdr->guard != 'Q')
+		return -EINVAL;
+	if (hdr->request_len > BLK_MAX_CDB)
+		return -EINVAL;
+	if (hdr->dout_xfer_len > (q->max_sectors << 9) ||
+	    hdr->din_xfer_len > (q->max_sectors << 9))
+		return -EIO;
+
+	switch (hdr->protocol) {
+	case BSG_PROTOCOL_SCSI:
+		switch (hdr->subprotocol) {
+		case BSG_SUB_PROTOCOL_SCSI_CMD:
+		case BSG_SUB_PROTOCOL_SCSI_TRANSPORT:
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	*rw = hdr->dout_xfer_len ? WRITE : READ;
+	return ret;
+}
+
+/*
+ * map sg_io_v4 to a request.
+ */
+static struct request *
+bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr)
+{
+	request_queue_t *q = bd->queue;
+	struct request *rq, *next_rq = NULL;
+	int ret, rw;
+	unsigned int dxfer_len;
+	void *dxferp = NULL;
+
+	dprintk("map hdr %llx/%u %llx/%u\n", (unsigned long long) hdr->dout_xferp,
+		hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
+		hdr->din_xfer_len);
+
+	ret = bsg_validate_sgv4_hdr(q, hdr, &rw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	/*
+	 * map scatter-gather elements seperately and string them to request
+	 */
+	rq = blk_get_request(q, rw, GFP_KERNEL);
+	if (!rq)
+		return ERR_PTR(-ENOMEM);
+	ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, test_bit(BSG_F_WRITE_PERM,
+						       &bd->flags));
+	if (ret)
+		goto out;
+
+	if (rw == WRITE && hdr->din_xfer_len) {
+		if (!test_bit(QUEUE_FLAG_BIDI, &q->queue_flags)) {
+			ret = -EOPNOTSUPP;
+			goto out;
+		}
+
+		next_rq = blk_get_request(q, READ, GFP_KERNEL);
+		if (!next_rq) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		rq->next_rq = next_rq;
+
+		dxferp = (void*)(unsigned long)hdr->din_xferp;
+		ret =  blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len);
+		if (ret)
+			goto out;
+	}
+
+	if (hdr->dout_xfer_len) {
+		dxfer_len = hdr->dout_xfer_len;
+		dxferp = (void*)(unsigned long)hdr->dout_xferp;
+	} else if (hdr->din_xfer_len) {
+		dxfer_len = hdr->din_xfer_len;
+		dxferp = (void*)(unsigned long)hdr->din_xferp;
+	} else
+		dxfer_len = 0;
+
+	if (dxfer_len) {
+		ret = blk_rq_map_user(q, rq, dxferp, dxfer_len);
+		if (ret)
+			goto out;
+	}
+	return rq;
+out:
+	blk_put_request(rq);
+	if (next_rq) {
+		blk_rq_unmap_user(next_rq->bio);
+		blk_put_request(next_rq);
+	}
+	return ERR_PTR(ret);
+}
+
+/*
+ * async completion call-back from the block layer, when scsi/ide/whatever
+ * calls end_that_request_last() on a request
+ */
+static void bsg_rq_end_io(struct request *rq, int uptodate)
+{
+	struct bsg_command *bc = rq->end_io_data;
+	struct bsg_device *bd = bc->bd;
+	unsigned long flags;
+
+	dprintk("%s: finished rq %p bc %p, bio %p stat %d\n",
+		bd->name, rq, bc, bc->bio, uptodate);
+
+	bc->hdr.duration = jiffies_to_msecs(jiffies - bc->hdr.duration);
+
+	spin_lock_irqsave(&bd->lock, flags);
+	list_move_tail(&bc->list, &bd->done_list);
+	bd->done_cmds++;
+	spin_unlock_irqrestore(&bd->lock, flags);
+
+	wake_up(&bd->wq_done);
+}
+
+/*
+ * do final setup of a 'bc' and submit the matching 'rq' to the block
+ * layer for io
+ */
+static void bsg_add_command(struct bsg_device *bd, request_queue_t *q,
+			    struct bsg_command *bc, struct request *rq)
+{
+	rq->sense = bc->sense;
+	rq->sense_len = 0;
+
+	/*
+	 * add bc command to busy queue and submit rq for io
+	 */
+	bc->rq = rq;
+	bc->bio = rq->bio;
+	if (rq->next_rq)
+		bc->bidi_bio = rq->next_rq->bio;
+	bc->hdr.duration = jiffies;
+	spin_lock_irq(&bd->lock);
+	list_add_tail(&bc->list, &bd->busy_list);
+	spin_unlock_irq(&bd->lock);
+
+	dprintk("%s: queueing rq %p, bc %p\n", bd->name, rq, bc);
+
+	rq->end_io_data = bc;
+	blk_execute_rq_nowait(q, NULL, rq, 1, bsg_rq_end_io);
+}
+
+static struct bsg_command *bsg_next_done_cmd(struct bsg_device *bd)
+{
+	struct bsg_command *bc = NULL;
+
+	spin_lock_irq(&bd->lock);
+	if (bd->done_cmds) {
+		bc = list_entry(bd->done_list.next, struct bsg_command, list);
+		list_del(&bc->list);
+		bd->done_cmds--;
+	}
+	spin_unlock_irq(&bd->lock);
+
+	return bc;
+}
+
+/*
+ * Get a finished command from the done list
+ */
+static struct bsg_command *bsg_get_done_cmd(struct bsg_device *bd)
+{
+	struct bsg_command *bc;
+	int ret;
+
+	do {
+		bc = bsg_next_done_cmd(bd);
+		if (bc)
+			break;
+
+		if (!test_bit(BSG_F_BLOCK, &bd->flags)) {
+			bc = ERR_PTR(-EAGAIN);
+			break;
+		}
+
+		ret = wait_event_interruptible(bd->wq_done, bd->done_cmds);
+		if (ret) {
+			bc = ERR_PTR(-ERESTARTSYS);
+			break;
+		}
+	} while (1);
+
+	dprintk("%s: returning done %p\n", bd->name, bc);
+
+	return bc;
+}
+
+static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
+				    struct bio *bio, struct bio *bidi_bio)
+{
+	int ret = 0;
+
+	dprintk("rq %p bio %p %u\n", rq, bio, rq->errors);
+	/*
+	 * fill in all the output members
+	 */
+	hdr->device_status = status_byte(rq->errors);
+	hdr->transport_status = host_byte(rq->errors);
+	hdr->driver_status = driver_byte(rq->errors);
+	hdr->info = 0;
+	if (hdr->device_status || hdr->transport_status || hdr->driver_status)
+		hdr->info |= SG_INFO_CHECK;
+	hdr->din_resid = rq->data_len;
+	hdr->response_len = 0;
+
+	if (rq->sense_len && hdr->response) {
+		int len = min_t(unsigned int, hdr->max_response_len,
+					rq->sense_len);
+
+		ret = copy_to_user((void*)(unsigned long)hdr->response,
+				   rq->sense, len);
+		if (!ret)
+			hdr->response_len = len;
+		else
+			ret = -EFAULT;
+	}
+
+	if (rq->next_rq) {
+		blk_rq_unmap_user(bidi_bio);
+		blk_put_request(rq->next_rq);
+	}
+
+	blk_rq_unmap_user(bio);
+	blk_put_request(rq);
+
+	return ret;
+}
+
+static int bsg_complete_all_commands(struct bsg_device *bd)
+{
+	struct bsg_command *bc;
+	int ret, tret;
+
+	dprintk("%s: entered\n", bd->name);
+
+	set_bit(BSG_F_BLOCK, &bd->flags);
+
+	/*
+	 * wait for all commands to complete
+	 */
+	ret = 0;
+	do {
+		ret = bsg_io_schedule(bd);
+		/*
+		 * look for -ENODATA specifically -- we'll sometimes get
+		 * -ERESTARTSYS when we've taken a signal, but we can't
+		 * return until we're done freeing the queue, so ignore
+		 * it.  The signal will get handled when we're done freeing
+		 * the bsg_device.
+		 */
+	} while (ret != -ENODATA);
+
+	/*
+	 * discard done commands
+	 */
+	ret = 0;
+	do {
+		spin_lock_irq(&bd->lock);
+		if (!bd->queued_cmds) {
+			spin_unlock_irq(&bd->lock);
+			break;
+		}
+		spin_unlock_irq(&bd->lock);
+
+		bc = bsg_get_done_cmd(bd);
+		if (IS_ERR(bc))
+			break;
+
+		tret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio,
+						bc->bidi_bio);
+		if (!ret)
+			ret = tret;
+
+		bsg_free_command(bc);
+	} while (1);
+
+	return ret;
+}
+
+static int
+__bsg_read(char __user *buf, size_t count, struct bsg_device *bd,
+	   const struct iovec *iov, ssize_t *bytes_read)
+{
+	struct bsg_command *bc;
+	int nr_commands, ret;
+
+	if (count % sizeof(struct sg_io_v4))
+		return -EINVAL;
+
+	ret = 0;
+	nr_commands = count / sizeof(struct sg_io_v4);
+	while (nr_commands) {
+		bc = bsg_get_done_cmd(bd);
+		if (IS_ERR(bc)) {
+			ret = PTR_ERR(bc);
+			break;
+		}
+
+		/*
+		 * this is the only case where we need to copy data back
+		 * after completing the request. so do that here,
+		 * bsg_complete_work() cannot do that for us
+		 */
+		ret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio,
+					       bc->bidi_bio);
+
+		if (copy_to_user(buf, &bc->hdr, sizeof(bc->hdr)))
+			ret = -EFAULT;
+
+		bsg_free_command(bc);
+
+		if (ret)
+			break;
+
+		buf += sizeof(struct sg_io_v4);
+		*bytes_read += sizeof(struct sg_io_v4);
+		nr_commands--;
+	}
+
+	return ret;
+}
+
+static inline void bsg_set_block(struct bsg_device *bd, struct file *file)
+{
+	if (file->f_flags & O_NONBLOCK)
+		clear_bit(BSG_F_BLOCK, &bd->flags);
+	else
+		set_bit(BSG_F_BLOCK, &bd->flags);
+}
+
+static inline void bsg_set_write_perm(struct bsg_device *bd, struct file *file)
+{
+	if (file->f_mode & FMODE_WRITE)
+		set_bit(BSG_F_WRITE_PERM, &bd->flags);
+	else
+		clear_bit(BSG_F_WRITE_PERM, &bd->flags);
+}
+
+/*
+ * Check if the error is a "real" error that we should return.
+ */
+static inline int err_block_err(int ret)
+{
+	if (ret && ret != -ENOSPC && ret != -ENODATA && ret != -EAGAIN)
+		return 1;
+
+	return 0;
+}
+
+static ssize_t
+bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct bsg_device *bd = file->private_data;
+	int ret;
+	ssize_t bytes_read;
+
+	dprintk("%s: read %Zd bytes\n", bd->name, count);
+
+	bsg_set_block(bd, file);
+	bytes_read = 0;
+	ret = __bsg_read(buf, count, bd, NULL, &bytes_read);
+	*ppos = bytes_read;
+
+	if (!bytes_read || (bytes_read && err_block_err(ret)))
+		bytes_read = ret;
+
+	return bytes_read;
+}
+
+static int __bsg_write(struct bsg_device *bd, const char __user *buf,
+		       size_t count, ssize_t *bytes_written)
+{
+	struct bsg_command *bc;
+	struct request *rq;
+	int ret, nr_commands;
+
+	if (count % sizeof(struct sg_io_v4))
+		return -EINVAL;
+
+	nr_commands = count / sizeof(struct sg_io_v4);
+	rq = NULL;
+	bc = NULL;
+	ret = 0;
+	while (nr_commands) {
+		request_queue_t *q = bd->queue;
+
+		bc = bsg_alloc_command(bd);
+		if (IS_ERR(bc)) {
+			ret = PTR_ERR(bc);
+			bc = NULL;
+			break;
+		}
+
+		bc->uhdr = (struct sg_io_v4 __user *) buf;
+		if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		/*
+		 * get a request, fill in the blanks, and add to request queue
+		 */
+		rq = bsg_map_hdr(bd, &bc->hdr);
+		if (IS_ERR(rq)) {
+			ret = PTR_ERR(rq);
+			rq = NULL;
+			break;
+		}
+
+		bsg_add_command(bd, q, bc, rq);
+		bc = NULL;
+		rq = NULL;
+		nr_commands--;
+		buf += sizeof(struct sg_io_v4);
+		*bytes_written += sizeof(struct sg_io_v4);
+	}
+
+	if (bc)
+		bsg_free_command(bc);
+
+	return ret;
+}
+
+static ssize_t
+bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct bsg_device *bd = file->private_data;
+	ssize_t bytes_written;
+	int ret;
+
+	dprintk("%s: write %Zd bytes\n", bd->name, count);
+
+	bsg_set_block(bd, file);
+	bsg_set_write_perm(bd, file);
+
+	bytes_written = 0;
+	ret = __bsg_write(bd, buf, count, &bytes_written);
+	*ppos = bytes_written;
+
+	/*
+	 * return bytes written on non-fatal errors
+	 */
+	if (!bytes_written || (bytes_written && err_block_err(ret)))
+		bytes_written = ret;
+
+	dprintk("%s: returning %Zd\n", bd->name, bytes_written);
+	return bytes_written;
+}
+
+static struct bsg_device *bsg_alloc_device(void)
+{
+	struct bsg_device *bd;
+
+	bd = kzalloc(sizeof(struct bsg_device), GFP_KERNEL);
+	if (unlikely(!bd))
+		return NULL;
+
+	spin_lock_init(&bd->lock);
+
+	bd->max_queue = BSG_DEFAULT_CMDS;
+
+	INIT_LIST_HEAD(&bd->busy_list);
+	INIT_LIST_HEAD(&bd->done_list);
+	INIT_HLIST_NODE(&bd->dev_list);
+
+	init_waitqueue_head(&bd->wq_free);
+	init_waitqueue_head(&bd->wq_done);
+	return bd;
+}
+
+static int bsg_put_device(struct bsg_device *bd)
+{
+	int ret = 0;
+
+	mutex_lock(&bsg_mutex);
+
+	if (!atomic_dec_and_test(&bd->ref_count))
+		goto out;
+
+	dprintk("%s: tearing down\n", bd->name);
+
+	/*
+	 * close can always block
+	 */
+	set_bit(BSG_F_BLOCK, &bd->flags);
+
+	/*
+	 * correct error detection baddies here again. it's the responsibility
+	 * of the app to properly reap commands before close() if it wants
+	 * fool-proof error detection
+	 */
+	ret = bsg_complete_all_commands(bd);
+
+	blk_put_queue(bd->queue);
+	hlist_del(&bd->dev_list);
+	kfree(bd);
+out:
+	mutex_unlock(&bsg_mutex);
+	return ret;
+}
+
+static struct bsg_device *bsg_add_device(struct inode *inode,
+					 struct request_queue *rq,
+					 struct file *file)
+{
+	struct bsg_device *bd;
+#ifdef BSG_DEBUG
+	unsigned char buf[32];
+#endif
+
+	bd = bsg_alloc_device();
+	if (!bd)
+		return ERR_PTR(-ENOMEM);
+
+	bd->queue = rq;
+	kobject_get(&rq->kobj);
+	bsg_set_block(bd, file);
+
+	atomic_set(&bd->ref_count, 1);
+	bd->minor = iminor(inode);
+	mutex_lock(&bsg_mutex);
+	hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(bd->minor));
+
+	strncpy(bd->name, rq->bsg_dev.class_dev->class_id, sizeof(bd->name) - 1);
+	dprintk("bound to <%s>, max queue %d\n",
+		format_dev_t(buf, inode->i_rdev), bd->max_queue);
+
+	mutex_unlock(&bsg_mutex);
+	return bd;
+}
+
+static struct bsg_device *__bsg_get_device(int minor)
+{
+	struct bsg_device *bd = NULL;
+	struct hlist_node *entry;
+
+	mutex_lock(&bsg_mutex);
+
+	hlist_for_each(entry, bsg_dev_idx_hash(minor)) {
+		bd = hlist_entry(entry, struct bsg_device, dev_list);
+		if (bd->minor == minor) {
+			atomic_inc(&bd->ref_count);
+			break;
+		}
+
+		bd = NULL;
+	}
+
+	mutex_unlock(&bsg_mutex);
+	return bd;
+}
+
+static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
+{
+	struct bsg_device *bd = __bsg_get_device(iminor(inode));
+	struct bsg_class_device *bcd, *__bcd;
+
+	if (bd)
+		return bd;
+
+	/*
+	 * find the class device
+	 */
+	bcd = NULL;
+	mutex_lock(&bsg_mutex);
+	list_for_each_entry(__bcd, &bsg_class_list, list) {
+		if (__bcd->minor == iminor(inode)) {
+			bcd = __bcd;
+			break;
+		}
+	}
+	mutex_unlock(&bsg_mutex);
+
+	if (!bcd)
+		return ERR_PTR(-ENODEV);
+
+	return bsg_add_device(inode, bcd->queue, file);
+}
+
+static int bsg_open(struct inode *inode, struct file *file)
+{
+	struct bsg_device *bd = bsg_get_device(inode, file);
+
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
+
+	file->private_data = bd;
+	return 0;
+}
+
+static int bsg_release(struct inode *inode, struct file *file)
+{
+	struct bsg_device *bd = file->private_data;
+
+	file->private_data = NULL;
+	return bsg_put_device(bd);
+}
+
+static unsigned int bsg_poll(struct file *file, poll_table *wait)
+{
+	struct bsg_device *bd = file->private_data;
+	unsigned int mask = 0;
+
+	poll_wait(file, &bd->wq_done, wait);
+	poll_wait(file, &bd->wq_free, wait);
+
+	spin_lock_irq(&bd->lock);
+	if (!list_empty(&bd->done_list))
+		mask |= POLLIN | POLLRDNORM;
+	if (bd->queued_cmds >= bd->max_queue)
+		mask |= POLLOUT;
+	spin_unlock_irq(&bd->lock);
+
+	return mask;
+}
+
+static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct bsg_device *bd = file->private_data;
+	int __user *uarg = (int __user *) arg;
+
+	switch (cmd) {
+		/*
+		 * our own ioctls
+		 */
+	case SG_GET_COMMAND_Q:
+		return put_user(bd->max_queue, uarg);
+	case SG_SET_COMMAND_Q: {
+		int queue;
+
+		if (get_user(queue, uarg))
+			return -EFAULT;
+		if (queue < 1)
+			return -EINVAL;
+
+		spin_lock_irq(&bd->lock);
+		bd->max_queue = queue;
+		spin_unlock_irq(&bd->lock);
+		return 0;
+	}
+
+	/*
+	 * SCSI/sg ioctls
+	 */
+	case SG_GET_VERSION_NUM:
+	case SCSI_IOCTL_GET_IDLUN:
+	case SCSI_IOCTL_GET_BUS_NUMBER:
+	case SG_SET_TIMEOUT:
+	case SG_GET_TIMEOUT:
+	case SG_GET_RESERVED_SIZE:
+	case SG_SET_RESERVED_SIZE:
+	case SG_EMULATED_HOST:
+	case SCSI_IOCTL_SEND_COMMAND: {
+		void __user *uarg = (void __user *) arg;
+		return scsi_cmd_ioctl(file, bd->queue, NULL, cmd, uarg);
+	}
+	case SG_IO: {
+		struct request *rq;
+		struct bio *bio, *bidi_bio = NULL;
+		struct sg_io_v4 hdr;
+
+		if (copy_from_user(&hdr, uarg, sizeof(hdr)))
+			return -EFAULT;
+
+		rq = bsg_map_hdr(bd, &hdr);
+		if (IS_ERR(rq))
+			return PTR_ERR(rq);
+
+		bio = rq->bio;
+		if (rq->next_rq)
+			bidi_bio = rq->next_rq->bio;
+		blk_execute_rq(bd->queue, NULL, rq, 0);
+		blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio);
+
+		if (copy_to_user(uarg, &hdr, sizeof(hdr)))
+			return -EFAULT;
+
+		return 0;
+	}
+	/*
+	 * block device ioctls
+	 */
+	default:
+#if 0
+		return ioctl_by_bdev(bd->bdev, cmd, arg);
+#else
+		return -ENOTTY;
+#endif
+	}
+}
+
+static struct file_operations bsg_fops = {
+	.read		=	bsg_read,
+	.write		=	bsg_write,
+	.poll		=	bsg_poll,
+	.open		=	bsg_open,
+	.release	=	bsg_release,
+	.unlocked_ioctl	=	bsg_ioctl,
+	.owner		=	THIS_MODULE,
+};
+
+void bsg_unregister_queue(struct request_queue *q)
+{
+	struct bsg_class_device *bcd = &q->bsg_dev;
+
+	WARN_ON(!bcd->class_dev);
+
+	mutex_lock(&bsg_mutex);
+	sysfs_remove_link(&q->kobj, "bsg");
+	class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor));
+	bcd->class_dev = NULL;
+	list_del_init(&bcd->list);
+	bsg_device_nr--;
+	mutex_unlock(&bsg_mutex);
+}
+EXPORT_SYMBOL_GPL(bsg_unregister_queue);
+
+int bsg_register_queue(struct request_queue *q, const char *name)
+{
+	struct bsg_class_device *bcd, *__bcd;
+	dev_t dev;
+	int ret = -EMFILE;
+	struct class_device *class_dev = NULL;
+
+	/*
+	 * we need a proper transport to send commands, not a stacked device
+	 */
+	if (!q->request_fn)
+		return 0;
+
+	bcd = &q->bsg_dev;
+	memset(bcd, 0, sizeof(*bcd));
+	INIT_LIST_HEAD(&bcd->list);
+
+	mutex_lock(&bsg_mutex);
+	if (bsg_device_nr == BSG_MAX_DEVS) {
+		printk(KERN_ERR "bsg: too many bsg devices\n");
+		goto err;
+	}
+
+retry:
+	list_for_each_entry(__bcd, &bsg_class_list, list) {
+		if (__bcd->minor == bsg_minor_idx) {
+			bsg_minor_idx++;
+			if (bsg_minor_idx == BSG_MAX_DEVS)
+				bsg_minor_idx = 0;
+			goto retry;
+		}
+	}
+
+	bcd->minor = bsg_minor_idx++;
+	if (bsg_minor_idx == BSG_MAX_DEVS)
+		bsg_minor_idx = 0;
+
+	bcd->queue = q;
+	dev = MKDEV(bsg_major, bcd->minor);
+	class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name);
+	if (IS_ERR(class_dev)) {
+		ret = PTR_ERR(class_dev);
+		goto err;
+	}
+	bcd->class_dev = class_dev;
+
+	if (q->kobj.sd) {
+		ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg");
+		if (ret)
+			goto err;
+	}
+
+	list_add_tail(&bcd->list, &bsg_class_list);
+	bsg_device_nr++;
+
+	mutex_unlock(&bsg_mutex);
+	return 0;
+err:
+	if (class_dev)
+		class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor));
+	mutex_unlock(&bsg_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(bsg_register_queue);
+
+static int bsg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
+{
+	int ret;
+	struct scsi_device *sdp = to_scsi_device(cl_dev->dev);
+	struct request_queue *rq = sdp->request_queue;
+
+	if (rq->kobj.parent)
+		ret = bsg_register_queue(rq, kobject_name(rq->kobj.parent));
+	else
+		ret = bsg_register_queue(rq, kobject_name(&sdp->sdev_gendev.kobj));
+	return ret;
+}
+
+static void bsg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
+{
+	bsg_unregister_queue(to_scsi_device(cl_dev->dev)->request_queue);
+}
+
+static struct class_interface bsg_intf = {
+	.add	= bsg_add,
+	.remove	= bsg_remove,
+};
+
+static struct cdev bsg_cdev = {
+	.kobj   = {.name = "bsg", },
+	.owner  = THIS_MODULE,
+};
+
+static int __init bsg_init(void)
+{
+	int ret, i;
+	dev_t devid;
+
+	bsg_cmd_cachep = kmem_cache_create("bsg_cmd",
+				sizeof(struct bsg_command), 0, 0, NULL, NULL);
+	if (!bsg_cmd_cachep) {
+		printk(KERN_ERR "bsg: failed creating slab cache\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < BSG_LIST_ARRAY_SIZE; i++)
+		INIT_HLIST_HEAD(&bsg_device_list[i]);
+
+	bsg_class = class_create(THIS_MODULE, "bsg");
+	if (IS_ERR(bsg_class)) {
+		ret = PTR_ERR(bsg_class);
+		goto destroy_kmemcache;
+	}
+
+	ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
+	if (ret)
+		goto destroy_bsg_class;
+
+	bsg_major = MAJOR(devid);
+
+	cdev_init(&bsg_cdev, &bsg_fops);
+	ret = cdev_add(&bsg_cdev, MKDEV(bsg_major, 0), BSG_MAX_DEVS);
+	if (ret)
+		goto unregister_chrdev;
+
+	ret = scsi_register_interface(&bsg_intf);
+	if (ret)
+		goto remove_cdev;
+
+	printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
+	       " loaded (major %d)\n", bsg_major);
+	return 0;
+remove_cdev:
+	printk(KERN_ERR "bsg: failed register scsi interface %d\n", ret);
+	cdev_del(&bsg_cdev);
+unregister_chrdev:
+	unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS);
+destroy_bsg_class:
+	class_destroy(bsg_class);
+destroy_kmemcache:
+	kmem_cache_destroy(bsg_cmd_cachep);
+	return ret;
+}
+
+MODULE_AUTHOR("Jens Axboe");
+MODULE_DESCRIPTION(BSG_DESCRIPTION);
+MODULE_LICENSE("GPL");
+
+device_initcall(bsg_init);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index baef5fc..9755a3c 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -92,6 +92,8 @@
 	struct cfq_queue *active_queue;
 	struct cfq_io_context *active_cic;
 
+	struct cfq_queue *async_cfqq[IOPRIO_BE_NR];
+
 	struct timer_list idle_class_timer;
 
 	sector_t last_position;
@@ -1249,9 +1251,9 @@
 {
 	struct cfq_io_context *cic;
 
-	cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask, cfqd->queue->node);
+	cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask | __GFP_ZERO,
+							cfqd->queue->node);
 	if (cic) {
-		memset(cic, 0, sizeof(*cic));
 		cic->last_end_request = jiffies;
 		INIT_LIST_HEAD(&cic->queue_list);
 		cic->dtor = cfq_free_io_context;
@@ -1351,8 +1353,8 @@
 }
 
 static struct cfq_queue *
-cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
-	      gfp_t gfp_mask)
+cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
+		     struct task_struct *tsk, gfp_t gfp_mask)
 {
 	struct cfq_queue *cfqq, *new_cfqq = NULL;
 	struct cfq_io_context *cic;
@@ -1374,17 +1376,19 @@
 			 * free memory.
 			 */
 			spin_unlock_irq(cfqd->queue->queue_lock);
-			new_cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask|__GFP_NOFAIL, cfqd->queue->node);
+			new_cfqq = kmem_cache_alloc_node(cfq_pool,
+					gfp_mask | __GFP_NOFAIL | __GFP_ZERO,
+					cfqd->queue->node);
 			spin_lock_irq(cfqd->queue->queue_lock);
 			goto retry;
 		} else {
-			cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask, cfqd->queue->node);
+			cfqq = kmem_cache_alloc_node(cfq_pool,
+					gfp_mask | __GFP_ZERO,
+					cfqd->queue->node);
 			if (!cfqq)
 				goto out;
 		}
 
-		memset(cfqq, 0, sizeof(*cfqq));
-
 		RB_CLEAR_NODE(&cfqq->rb_node);
 		INIT_LIST_HEAD(&cfqq->fifo);
 
@@ -1405,12 +1409,35 @@
 	if (new_cfqq)
 		kmem_cache_free(cfq_pool, new_cfqq);
 
-	atomic_inc(&cfqq->ref);
 out:
 	WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
 	return cfqq;
 }
 
+static struct cfq_queue *
+cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
+	      gfp_t gfp_mask)
+{
+	const int ioprio = task_ioprio(tsk);
+	struct cfq_queue *cfqq = NULL;
+
+	if (!is_sync)
+		cfqq = cfqd->async_cfqq[ioprio];
+	if (!cfqq)
+		cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask);
+
+	/*
+	 * pin the queue now that it's allocated, scheduler exit will prune it
+	 */
+	if (!is_sync && !cfqd->async_cfqq[ioprio]) {
+		atomic_inc(&cfqq->ref);
+		cfqd->async_cfqq[ioprio] = cfqq;
+	}
+
+	atomic_inc(&cfqq->ref);
+	return cfqq;
+}
+
 /*
  * We drop cfq io contexts lazily, so we may find a dead one.
  */
@@ -2019,6 +2046,7 @@
 {
 	struct cfq_data *cfqd = e->elevator_data;
 	request_queue_t *q = cfqd->queue;
+	int i;
 
 	cfq_shutdown_timer_wq(cfqd);
 
@@ -2035,6 +2063,13 @@
 		__cfq_exit_single_io_context(cfqd, cic);
 	}
 
+	/*
+	 * Put the async queues
+	 */
+	for (i = 0; i < IOPRIO_BE_NR; i++)
+		if (cfqd->async_cfqq[i])	
+			cfq_put_queue(cfqd->async_cfqq[i]);
+
 	spin_unlock_irq(q->queue_lock);
 
 	cfq_shutdown_timer_wq(cfqd);
@@ -2046,12 +2081,10 @@
 {
 	struct cfq_data *cfqd;
 
-	cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL, q->node);
+	cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
 	if (!cfqd)
 		return NULL;
 
-	memset(cfqd, 0, sizeof(*cfqd));
-
 	cfqd->service_tree = CFQ_RB_ROOT;
 	INIT_LIST_HEAD(&cfqd->cic_list);
 
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 6d673e9..87ca02a 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -360,10 +360,9 @@
 {
 	struct deadline_data *dd;
 
-	dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
+	dd = kmalloc_node(sizeof(*dd), GFP_KERNEL | __GFP_ZERO, q->node);
 	if (!dd)
 		return NULL;
-	memset(dd, 0, sizeof(*dd));
 
 	INIT_LIST_HEAD(&dd->fifo_list[READ]);
 	INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
diff --git a/block/elevator.c b/block/elevator.c
index ce866eb..d265963 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -112,12 +112,8 @@
 static struct elevator_type *elevator_find(const char *name)
 {
 	struct elevator_type *e;
-	struct list_head *entry;
 
-	list_for_each(entry, &elv_list) {
-
-		e = list_entry(entry, struct elevator_type, list);
-
+	list_for_each_entry(e, &elv_list, list) {
 		if (!strcmp(e->elevator_name, name))
 			return e;
 	}
@@ -181,11 +177,10 @@
 	elevator_t *eq;
 	int i;
 
-	eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL, q->node);
+	eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL | __GFP_ZERO, q->node);
 	if (unlikely(!eq))
 		goto err;
 
-	memset(eq, 0, sizeof(*eq));
 	eq->ops = &e->ops;
 	eq->elevator_type = e;
 	kobject_init(&eq->kobj);
@@ -1116,14 +1111,11 @@
 {
 	elevator_t *e = q->elevator;
 	struct elevator_type *elv = e->elevator_type;
-	struct list_head *entry;
+	struct elevator_type *__e;
 	int len = 0;
 
 	spin_lock(&elv_list_lock);
-	list_for_each(entry, &elv_list) {
-		struct elevator_type *__e;
-
-		__e = list_entry(entry, struct elevator_type, list);
+	list_for_each_entry(__e, &elv_list, list) {
 		if (!strcmp(elv->elevator_name, __e->elevator_name))
 			len += sprintf(name+len, "[%s] ", elv->elevator_name);
 		else
diff --git a/block/genhd.c b/block/genhd.c
index 93a2cf6..3af1e7a 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -108,28 +108,24 @@
 
 EXPORT_SYMBOL(register_blkdev);
 
-/* todo: make void - error printk here */
-int unregister_blkdev(unsigned int major, const char *name)
+void unregister_blkdev(unsigned int major, const char *name)
 {
 	struct blk_major_name **n;
 	struct blk_major_name *p = NULL;
 	int index = major_to_index(major);
-	int ret = 0;
 
 	mutex_lock(&block_subsys_lock);
 	for (n = &major_names[index]; *n; n = &(*n)->next)
 		if ((*n)->major == major)
 			break;
-	if (!*n || strcmp((*n)->name, name))
-		ret = -EINVAL;
-	else {
+	if (!*n || strcmp((*n)->name, name)) {
+		WARN_ON(1);
+	} else {
 		p = *n;
 		*n = p->next;
 	}
 	mutex_unlock(&block_subsys_lock);
 	kfree(p);
-
-	return ret;
 }
 
 EXPORT_SYMBOL(unregister_blkdev);
@@ -423,7 +419,10 @@
 {
 	return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
 }
-
+static ssize_t disk_capability_read(struct gendisk *disk, char *page)
+{
+	return sprintf(page, "%x\n", disk->flags);
+}
 static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
 	preempt_disable();
@@ -466,6 +465,10 @@
 	.attr = {.name = "size", .mode = S_IRUGO },
 	.show	= disk_size_read
 };
+static struct disk_attribute disk_attr_capability = {
+	.attr = {.name = "capability", .mode = S_IRUGO },
+	.show	= disk_capability_read
+};
 static struct disk_attribute disk_attr_stat = {
 	.attr = {.name = "stat", .mode = S_IRUGO },
 	.show	= disk_stats_read
@@ -506,6 +509,7 @@
 	&disk_attr_removable.attr,
 	&disk_attr_size.attr,
 	&disk_attr_stat.attr,
+	&disk_attr_capability.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 	&disk_attr_fail.attr,
 #endif
@@ -688,6 +692,27 @@
 	.show	= diskstats_show
 };
 
+static void media_change_notify_thread(struct work_struct *work)
+{
+	struct gendisk *gd = container_of(work, struct gendisk, async_notify);
+	char event[] = "MEDIA_CHANGE=1";
+	char *envp[] = { event, NULL };
+
+	/*
+	 * set enviroment vars to indicate which event this is for
+	 * so that user space will know to go check the media status.
+	 */
+	kobject_uevent_env(&gd->kobj, KOBJ_CHANGE, envp);
+	put_device(gd->driverfs_dev);
+}
+
+void genhd_media_change_notify(struct gendisk *disk)
+{
+	get_device(disk->driverfs_dev);
+	schedule_work(&disk->async_notify);
+}
+EXPORT_SYMBOL_GPL(genhd_media_change_notify);
+
 struct gendisk *alloc_disk(int minors)
 {
 	return alloc_disk_node(minors, -1);
@@ -697,26 +722,28 @@
 {
 	struct gendisk *disk;
 
-	disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
+	disk = kmalloc_node(sizeof(struct gendisk),
+				GFP_KERNEL | __GFP_ZERO, node_id);
 	if (disk) {
-		memset(disk, 0, sizeof(struct gendisk));
 		if (!init_disk_stats(disk)) {
 			kfree(disk);
 			return NULL;
 		}
 		if (minors > 1) {
 			int size = (minors - 1) * sizeof(struct hd_struct *);
-			disk->part = kmalloc_node(size, GFP_KERNEL, node_id);
+			disk->part = kmalloc_node(size,
+				GFP_KERNEL | __GFP_ZERO, node_id);
 			if (!disk->part) {
 				kfree(disk);
 				return NULL;
 			}
-			memset(disk->part, 0, size);
 		}
 		disk->minors = minors;
 		kobj_set_kset_s(disk,block_subsys);
 		kobject_init(&disk->kobj);
 		rand_initialize_disk(disk);
+		INIT_WORK(&disk->async_notify,
+			media_change_notify_thread);
 	}
 	return disk;
 }
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 6b5173a..d7cadf3 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -256,6 +256,7 @@
 	rq->end_io = NULL;
 	rq->end_io_data = NULL;
 	rq->completion_data = NULL;
+	rq->next_rq = NULL;
 }
 
 /**
@@ -340,6 +341,15 @@
 	if (rq == &q->post_flush_rq)
 		return QUEUE_ORDSEQ_POSTFLUSH;
 
+	/*
+	 * !fs requests don't need to follow barrier ordering.  Always
+	 * put them at the front.  This fixes the following deadlock.
+	 *
+	 * http://thread.gmane.org/gmane.linux.kernel/537473
+	 */
+	if (!blk_fs_request(rq))
+		return QUEUE_ORDSEQ_DRAIN;
+
 	if ((rq->cmd_flags & REQ_ORDERED_COLOR) ==
 	    (q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR))
 		return QUEUE_ORDSEQ_DRAIN;
@@ -518,8 +528,6 @@
 static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
 {
 	request_queue_t *q = bio->bi_private;
-	struct bio_vec *bvec;
-	int i;
 
 	/*
 	 * This is dry run, restore bio_sector and size.  We'll finish
@@ -531,13 +539,6 @@
 	if (bio->bi_size)
 		return 1;
 
-	/* Rewind bvec's */
-	bio->bi_idx = 0;
-	bio_for_each_segment(bvec, bio, i) {
-		bvec->bv_len += bvec->bv_offset;
-		bvec->bv_offset = 0;
-	}
-
 	/* Reset bio */
 	set_bit(BIO_UPTODATE, &bio->bi_flags);
 	bio->bi_size = q->bi_size;
@@ -1295,9 +1296,9 @@
 	if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID)))
 		blk_recount_segments(q, nxt);
 	if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) ||
-	    BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size))
+	    BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size))
 		return 0;
-	if (bio->bi_size + nxt->bi_size > q->max_segment_size)
+	if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size)
 		return 0;
 
 	return 1;
@@ -1828,11 +1829,11 @@
 {
 	request_queue_t *q;
 
-	q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id);
+	q = kmem_cache_alloc_node(requestq_cachep,
+				gfp_mask | __GFP_ZERO, node_id);
 	if (!q)
 		return NULL;
 
-	memset(q, 0, sizeof(*q));
 	init_timer(&q->unplug_timer);
 
 	snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue");
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index e83f1db..a26ba07 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -41,8 +41,6 @@
 
 EXPORT_SYMBOL(scsi_command_size);
 
-#define BLK_DEFAULT_TIMEOUT	(60 * HZ)
-
 #include <scsi/sg.h>
 
 static int sg_get_version(int __user *p)
@@ -114,7 +112,7 @@
 #define safe_for_read(cmd)	[cmd] = CMD_READ_SAFE
 #define safe_for_write(cmd)	[cmd] = CMD_WRITE_SAFE
 
-static int verify_command(struct file *file, unsigned char *cmd)
+int blk_verify_command(unsigned char *cmd, int has_write_perm)
 {
 	static unsigned char cmd_type[256] = {
 
@@ -193,18 +191,11 @@
 		safe_for_write(GPCMD_SET_STREAMING),
 	};
 	unsigned char type = cmd_type[cmd[0]];
-	int has_write_perm = 0;
 
 	/* Anybody who can open the device can do a read-safe command */
 	if (type & CMD_READ_SAFE)
 		return 0;
 
-	/*
-	 * file can be NULL from ioctl_by_bdev()...
-	 */
-	if (file)
-		has_write_perm = file->f_mode & FMODE_WRITE;
-
 	/* Write-safe commands just require a writable open.. */
 	if ((type & CMD_WRITE_SAFE) && has_write_perm)
 		return 0;
@@ -221,25 +212,96 @@
 	/* Otherwise fail it with an "Operation not permitted" */
 	return -EPERM;
 }
+EXPORT_SYMBOL_GPL(blk_verify_command);
+
+int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq,
+		      struct sg_io_hdr *hdr, int has_write_perm)
+{
+	memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
+
+	if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
+		return -EFAULT;
+	if (blk_verify_command(rq->cmd, has_write_perm))
+		return -EPERM;
+
+	/*
+	 * fill in request structure
+	 */
+	rq->cmd_len = hdr->cmd_len;
+	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+
+	rq->timeout = (hdr->timeout * HZ) / 1000;
+	if (!rq->timeout)
+		rq->timeout = q->sg_timeout;
+	if (!rq->timeout)
+		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blk_fill_sghdr_rq);
+
+/*
+ * unmap a request that was previously mapped to this sg_io_hdr. handles
+ * both sg and non-sg sg_io_hdr.
+ */
+int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr)
+{
+	blk_rq_unmap_user(rq->bio);
+	blk_put_request(rq);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blk_unmap_sghdr_rq);
+
+int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
+			  struct bio *bio)
+{
+	int r, ret = 0;
+
+	/*
+	 * fill in all the output members
+	 */
+	hdr->status = rq->errors & 0xff;
+	hdr->masked_status = status_byte(rq->errors);
+	hdr->msg_status = msg_byte(rq->errors);
+	hdr->host_status = host_byte(rq->errors);
+	hdr->driver_status = driver_byte(rq->errors);
+	hdr->info = 0;
+	if (hdr->masked_status || hdr->host_status || hdr->driver_status)
+		hdr->info |= SG_INFO_CHECK;
+	hdr->resid = rq->data_len;
+	hdr->sb_len_wr = 0;
+
+	if (rq->sense_len && hdr->sbp) {
+		int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
+
+		if (!copy_to_user(hdr->sbp, rq->sense, len))
+			hdr->sb_len_wr = len;
+		else
+			ret = -EFAULT;
+	}
+
+	rq->bio = bio;
+	r = blk_unmap_sghdr_rq(rq, hdr);
+	if (ret)
+		r = ret;
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(blk_complete_sghdr_rq);
 
 static int sg_io(struct file *file, request_queue_t *q,
 		struct gendisk *bd_disk, struct sg_io_hdr *hdr)
 {
-	unsigned long start_time, timeout;
-	int writing = 0, ret = 0;
+	unsigned long start_time;
+	int writing = 0, ret = 0, has_write_perm = 0;
 	struct request *rq;
 	char sense[SCSI_SENSE_BUFFERSIZE];
-	unsigned char cmd[BLK_MAX_CDB];
 	struct bio *bio;
 
 	if (hdr->interface_id != 'S')
 		return -EINVAL;
 	if (hdr->cmd_len > BLK_MAX_CDB)
 		return -EINVAL;
-	if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len))
-		return -EFAULT;
-	if (verify_command(file, cmd))
-		return -EPERM;
 
 	if (hdr->dxfer_len > (q->max_hw_sectors << 9))
 		return -EIO;
@@ -260,25 +322,13 @@
 	if (!rq)
 		return -ENOMEM;
 
-	/*
-	 * fill in request structure
-	 */
-	rq->cmd_len = hdr->cmd_len;
-	memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
-	memcpy(rq->cmd, cmd, hdr->cmd_len);
+	if (file)
+		has_write_perm = file->f_mode & FMODE_WRITE;
 
-	memset(sense, 0, sizeof(sense));
-	rq->sense = sense;
-	rq->sense_len = 0;
-
-	rq->cmd_type = REQ_TYPE_BLOCK_PC;
-
-	timeout = msecs_to_jiffies(hdr->timeout);
-	rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX;
-	if (!rq->timeout)
-		rq->timeout = q->sg_timeout;
-	if (!rq->timeout)
-		rq->timeout = BLK_DEFAULT_TIMEOUT;
+	if (blk_fill_sghdr_rq(q, rq, hdr, has_write_perm)) {
+		blk_put_request(rq);
+		return -EFAULT;
+	}
 
 	if (hdr->iovec_count) {
 		const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
@@ -306,6 +356,9 @@
 		goto out;
 
 	bio = rq->bio;
+	memset(sense, 0, sizeof(sense));
+	rq->sense = sense;
+	rq->sense_len = 0;
 	rq->retries = 0;
 
 	start_time = jiffies;
@@ -316,31 +369,9 @@
 	 */
 	blk_execute_rq(q, bd_disk, rq, 0);
 
-	/* write to all output members */
-	hdr->status = 0xff & rq->errors;
-	hdr->masked_status = status_byte(rq->errors);
-	hdr->msg_status = msg_byte(rq->errors);
-	hdr->host_status = host_byte(rq->errors);
-	hdr->driver_status = driver_byte(rq->errors);
-	hdr->info = 0;
-	if (hdr->masked_status || hdr->host_status || hdr->driver_status)
-		hdr->info |= SG_INFO_CHECK;
-	hdr->resid = rq->data_len;
 	hdr->duration = ((jiffies - start_time) * 1000) / HZ;
-	hdr->sb_len_wr = 0;
 
-	if (rq->sense_len && hdr->sbp) {
-		int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
-
-		if (!copy_to_user(hdr->sbp, rq->sense, len))
-			hdr->sb_len_wr = len;
-	}
-
-	if (blk_rq_unmap_user(bio))
-		ret = -EFAULT;
-
-	/* may not have succeeded, but output values written to control
-	 * structure (struct sg_io_hdr).  */
+	return blk_complete_sghdr_rq(rq, hdr, bio);
 out:
 	blk_put_request(rq);
 	return ret;
@@ -427,7 +458,7 @@
 	if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
 		goto error;
 
-	err = verify_command(file, rq->cmd);
+	err = blk_verify_command(rq->cmd, file->f_mode & FMODE_WRITE);
 	if (err)
 		goto error;
 
@@ -454,7 +485,7 @@
 		rq->retries = 1;
 		break;
 	default:
-		rq->timeout = BLK_DEFAULT_TIMEOUT;
+		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
 		break;
 	}
 
@@ -501,7 +532,7 @@
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->data = NULL;
 	rq->data_len = 0;
-	rq->timeout = BLK_DEFAULT_TIMEOUT;
+	rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
 	memset(rq->cmd, 0, sizeof(rq->cmd));
 	rq->cmd[0] = cmd;
 	rq->cmd[4] = data;
@@ -517,16 +548,12 @@
 	return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
 }
 
-int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
+int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
+		   struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
 {
-	request_queue_t *q;
 	int err;
 
-	q = bd_disk->queue;
-	if (!q)
-		return -ENXIO;
-
-	if (blk_get_queue(q))
+	if (!q || blk_get_queue(q))
 		return -ENXIO;
 
 	switch (cmd) {
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 4ca0ab3..3d1a1e2 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1,10 +1,18 @@
 #
+# Generic algorithms support
+#
+config XOR_BLOCKS
+	tristate
+
+#
+# async_tx api: hardware offloaded memory transfer/transform support
+#
+source "crypto/async_tx/Kconfig"
+
+#
 # Cryptographic API Configuration
 #
-
-menu "Cryptographic options"
-
-config CRYPTO
+menuconfig CRYPTO
 	bool "Cryptographic API"
 	help
 	  This option provides the core Cryptographic API.
@@ -463,5 +471,3 @@
 source "drivers/crypto/Kconfig"
 
 endif	# if CRYPTO
-
-endmenu
diff --git a/crypto/Makefile b/crypto/Makefile
index cce46a1..0cf17f1 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -50,3 +50,9 @@
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
 
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+
+#
+# generic algorithms and the async_tx api
+#
+obj-$(CONFIG_XOR_BLOCKS) += xor.o
+obj-$(CONFIG_ASYNC_CORE) += async_tx/
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index 9348ddd..1c166b4 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -19,16 +19,41 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 
+static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen)
+{
+	struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm);
+	unsigned long alignmask = crypto_ablkcipher_alignmask(tfm);
+	int ret;
+	u8 *buffer, *alignbuffer;
+	unsigned long absize;
+
+	absize = keylen + alignmask;
+	buffer = kmalloc(absize, GFP_ATOMIC);
+	if (!buffer)
+		return -ENOMEM;
+
+	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+	memcpy(alignbuffer, key, keylen);
+	ret = cipher->setkey(tfm, alignbuffer, keylen);
+	memset(alignbuffer, 0, absize);
+	kfree(buffer);
+	return ret;
+}
+
 static int setkey(struct crypto_ablkcipher *tfm, const u8 *key,
 		  unsigned int keylen)
 {
 	struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm);
+	unsigned long alignmask = crypto_ablkcipher_alignmask(tfm);
 
 	if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
 		crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
 
+	if ((unsigned long)key & alignmask)
+		return setkey_unaligned(tfm, key, keylen);
+
 	return cipher->setkey(tfm, key, keylen);
 }
 
@@ -66,8 +91,10 @@
 	seq_printf(m, "min keysize  : %u\n", ablkcipher->min_keysize);
 	seq_printf(m, "max keysize  : %u\n", ablkcipher->max_keysize);
 	seq_printf(m, "ivsize       : %u\n", ablkcipher->ivsize);
-	seq_printf(m, "qlen         : %u\n", ablkcipher->queue->qlen);
-	seq_printf(m, "max qlen     : %u\n", ablkcipher->queue->max_qlen);
+	if (ablkcipher->queue) {
+		seq_printf(m, "qlen         : %u\n", ablkcipher->queue->qlen);
+		seq_printf(m, "max qlen     : %u\n", ablkcipher->queue->max_qlen);
+	}
 }
 
 const struct crypto_type crypto_ablkcipher_type = {
diff --git a/crypto/algapi.c b/crypto/algapi.c
index f137a432..38aa9e99 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -34,7 +34,7 @@
 	if (alg) {
 		if (crypto_is_larval(alg)) {
 			struct crypto_larval *larval = (void *)alg;
-			complete(&larval->completion);
+			complete_all(&larval->completion);
 		}
 		crypto_mod_put(alg);
 	}
@@ -164,7 +164,7 @@
 				continue;
 
 			larval->adult = alg;
-			complete(&larval->completion);
+			complete_all(&larval->completion);
 			continue;
 		}
 
diff --git a/crypto/api.c b/crypto/api.c
index 55af8bb..4ccc5af 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -48,8 +48,10 @@
 
 void crypto_mod_put(struct crypto_alg *alg)
 {
+	struct module *module = alg->cra_module;
+
 	crypto_alg_put(alg);
-	module_put(alg->cra_module);
+	module_put(module);
 }
 EXPORT_SYMBOL_GPL(crypto_mod_put);
 
@@ -142,7 +144,7 @@
 	down_write(&crypto_alg_sem);
 	list_del(&alg->cra_list);
 	up_write(&crypto_alg_sem);
-	complete(&larval->completion);
+	complete_all(&larval->completion);
 	crypto_alg_put(alg);
 }
 
diff --git a/crypto/async_tx/Kconfig b/crypto/async_tx/Kconfig
new file mode 100644
index 0000000..d8fb3914
--- /dev/null
+++ b/crypto/async_tx/Kconfig
@@ -0,0 +1,16 @@
+config ASYNC_CORE
+	tristate
+
+config ASYNC_MEMCPY
+	tristate
+	select ASYNC_CORE
+
+config ASYNC_XOR
+	tristate
+	select ASYNC_CORE
+	select XOR_BLOCKS
+
+config ASYNC_MEMSET
+	tristate
+	select ASYNC_CORE
+
diff --git a/crypto/async_tx/Makefile b/crypto/async_tx/Makefile
new file mode 100644
index 0000000..27baa7d
--- /dev/null
+++ b/crypto/async_tx/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_ASYNC_CORE) += async_tx.o
+obj-$(CONFIG_ASYNC_MEMCPY) += async_memcpy.o
+obj-$(CONFIG_ASYNC_MEMSET) += async_memset.o
+obj-$(CONFIG_ASYNC_XOR) += async_xor.o
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
new file mode 100644
index 0000000..a973f4e
--- /dev/null
+++ b/crypto/async_tx/async_memcpy.c
@@ -0,0 +1,131 @@
+/*
+ * copy offload engine support
+ *
+ * Copyright © 2006, Intel Corporation.
+ *
+ *      Dan Williams <dan.j.williams@intel.com>
+ *
+ *      with architecture considerations by:
+ *      Neil Brown <neilb@suse.de>
+ *      Jeff Garzik <jeff@garzik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/async_tx.h>
+
+/**
+ * async_memcpy - attempt to copy memory with a dma engine.
+ * @dest: destination page
+ * @src: src page
+ * @offset: offset in pages to start transaction
+ * @len: length in bytes
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
+ *	ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST
+ * @depend_tx: memcpy depends on the result of this transaction
+ * @cb_fn: function to call when the memcpy completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+	unsigned int src_offset, size_t len, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_param)
+{
+	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY);
+	struct dma_device *device = chan ? chan->device : NULL;
+	int int_en = cb_fn ? 1 : 0;
+	struct dma_async_tx_descriptor *tx = device ?
+		device->device_prep_dma_memcpy(chan, len,
+		int_en) : NULL;
+
+	if (tx) { /* run the memcpy asynchronously */
+		dma_addr_t addr;
+		enum dma_data_direction dir;
+
+		pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+
+		dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+			DMA_NONE : DMA_FROM_DEVICE;
+
+		addr = dma_map_page(device->dev, dest, dest_offset, len, dir);
+		tx->tx_set_dest(addr, tx, 0);
+
+		dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+			DMA_NONE : DMA_TO_DEVICE;
+
+		addr = dma_map_page(device->dev, src, src_offset, len, dir);
+		tx->tx_set_src(addr, tx, 0);
+
+		async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+	} else { /* run the memcpy synchronously */
+		void *dest_buf, *src_buf;
+		pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+		/* wait for any prerequisite operations */
+		if (depend_tx) {
+			/* if ack is already set then we cannot be sure
+			 * we are referring to the correct operation
+			 */
+			BUG_ON(depend_tx->ack);
+			if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+				panic("%s: DMA_ERROR waiting for depend_tx\n",
+					__FUNCTION__);
+		}
+
+		if (flags & ASYNC_TX_KMAP_DST)
+			dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
+		else
+			dest_buf = page_address(dest) + dest_offset;
+
+		if (flags & ASYNC_TX_KMAP_SRC)
+			src_buf = kmap_atomic(src, KM_USER0) + src_offset;
+		else
+			src_buf = page_address(src) + src_offset;
+
+		memcpy(dest_buf, src_buf, len);
+
+		if (flags & ASYNC_TX_KMAP_DST)
+			kunmap_atomic(dest_buf, KM_USER0);
+
+		if (flags & ASYNC_TX_KMAP_SRC)
+			kunmap_atomic(src_buf, KM_USER0);
+
+		async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+	}
+
+	return tx;
+}
+EXPORT_SYMBOL_GPL(async_memcpy);
+
+static int __init async_memcpy_init(void)
+{
+	return 0;
+}
+
+static void __exit async_memcpy_exit(void)
+{
+	do { } while (0);
+}
+
+module_init(async_memcpy_init);
+module_exit(async_memcpy_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous memcpy api");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c
new file mode 100644
index 0000000..66ef635
--- /dev/null
+++ b/crypto/async_tx/async_memset.c
@@ -0,0 +1,109 @@
+/*
+ * memory fill offload engine support
+ *
+ * Copyright © 2006, Intel Corporation.
+ *
+ *      Dan Williams <dan.j.williams@intel.com>
+ *
+ *      with architecture considerations by:
+ *      Neil Brown <neilb@suse.de>
+ *      Jeff Garzik <jeff@garzik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/async_tx.h>
+
+/**
+ * async_memset - attempt to fill memory with a dma engine.
+ * @dest: destination page
+ * @val: fill value
+ * @offset: offset in pages to start transaction
+ * @len: length in bytes
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: memset depends on the result of this transaction
+ * @cb_fn: function to call when the memcpy completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_memset(struct page *dest, int val, unsigned int offset,
+	size_t len, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_param)
+{
+	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET);
+	struct dma_device *device = chan ? chan->device : NULL;
+	int int_en = cb_fn ? 1 : 0;
+	struct dma_async_tx_descriptor *tx = device ?
+		device->device_prep_dma_memset(chan, val, len,
+			int_en) : NULL;
+
+	if (tx) { /* run the memset asynchronously */
+		dma_addr_t dma_addr;
+		enum dma_data_direction dir;
+
+		pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+		dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+			DMA_NONE : DMA_FROM_DEVICE;
+
+		dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
+		tx->tx_set_dest(dma_addr, tx, 0);
+
+		async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+	} else { /* run the memset synchronously */
+		void *dest_buf;
+		pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+		dest_buf = (void *) (((char *) page_address(dest)) + offset);
+
+		/* wait for any prerequisite operations */
+		if (depend_tx) {
+			/* if ack is already set then we cannot be sure
+			 * we are referring to the correct operation
+			 */
+			BUG_ON(depend_tx->ack);
+			if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+				panic("%s: DMA_ERROR waiting for depend_tx\n",
+					__FUNCTION__);
+		}
+
+		memset(dest_buf, val, len);
+
+		async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+	}
+
+	return tx;
+}
+EXPORT_SYMBOL_GPL(async_memset);
+
+static int __init async_memset_init(void)
+{
+	return 0;
+}
+
+static void __exit async_memset_exit(void)
+{
+	do { } while (0);
+}
+
+module_init(async_memset_init);
+module_exit(async_memset_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous memset api");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
new file mode 100644
index 0000000..0350071
--- /dev/null
+++ b/crypto/async_tx/async_tx.c
@@ -0,0 +1,497 @@
+/*
+ * core routines for the asynchronous memory transfer/transform api
+ *
+ * Copyright © 2006, Intel Corporation.
+ *
+ *	Dan Williams <dan.j.williams@intel.com>
+ *
+ *	with architecture considerations by:
+ *	Neil Brown <neilb@suse.de>
+ *	Jeff Garzik <jeff@garzik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/async_tx.h>
+
+#ifdef CONFIG_DMA_ENGINE
+static enum dma_state_client
+dma_channel_add_remove(struct dma_client *client,
+	struct dma_chan *chan, enum dma_state state);
+
+static struct dma_client async_tx_dma = {
+	.event_callback = dma_channel_add_remove,
+	/* .cap_mask == 0 defaults to all channels */
+};
+
+/**
+ * dma_cap_mask_all - enable iteration over all operation types
+ */
+static dma_cap_mask_t dma_cap_mask_all;
+
+/**
+ * chan_ref_percpu - tracks channel allocations per core/opertion
+ */
+struct chan_ref_percpu {
+	struct dma_chan_ref *ref;
+};
+
+static int channel_table_initialized;
+static struct chan_ref_percpu *channel_table[DMA_TX_TYPE_END];
+
+/**
+ * async_tx_lock - protect modification of async_tx_master_list and serialize
+ *	rebalance operations
+ */
+static spinlock_t async_tx_lock;
+
+static struct list_head
+async_tx_master_list = LIST_HEAD_INIT(async_tx_master_list);
+
+/* async_tx_issue_pending_all - start all transactions on all channels */
+void async_tx_issue_pending_all(void)
+{
+	struct dma_chan_ref *ref;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+		ref->chan->device->device_issue_pending(ref->chan);
+	rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(async_tx_issue_pending_all);
+
+/* dma_wait_for_async_tx - spin wait for a transcation to complete
+ * @tx: transaction to wait on
+ */
+enum dma_status
+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+{
+	enum dma_status status;
+	struct dma_async_tx_descriptor *iter;
+
+	if (!tx)
+		return DMA_SUCCESS;
+
+	/* poll through the dependency chain, return when tx is complete */
+	do {
+		iter = tx;
+		while (iter->cookie == -EBUSY)
+			iter = iter->parent;
+
+		status = dma_sync_wait(iter->chan, iter->cookie);
+	} while (status == DMA_IN_PROGRESS || (iter != tx));
+
+	return status;
+}
+EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
+
+/* async_tx_run_dependencies - helper routine for dma drivers to process
+ *	(start) dependent operations on their target channel
+ * @tx: transaction with dependencies
+ */
+void
+async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
+{
+	struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
+	struct dma_device *dev;
+	struct dma_chan *chan;
+
+	list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
+		depend_node) {
+		chan = dep_tx->chan;
+		dev = chan->device;
+		/* we can't depend on ourselves */
+		BUG_ON(chan == tx->chan);
+		list_del(&dep_tx->depend_node);
+		tx->tx_submit(dep_tx);
+
+		/* we need to poke the engine as client code does not
+		 * know about dependency submission events
+		 */
+		dev->device_issue_pending(chan);
+	}
+}
+EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
+
+static void
+free_dma_chan_ref(struct rcu_head *rcu)
+{
+	struct dma_chan_ref *ref;
+	ref = container_of(rcu, struct dma_chan_ref, rcu);
+	kfree(ref);
+}
+
+static void
+init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan)
+{
+	INIT_LIST_HEAD(&ref->node);
+	INIT_RCU_HEAD(&ref->rcu);
+	ref->chan = chan;
+	atomic_set(&ref->count, 0);
+}
+
+/**
+ * get_chan_ref_by_cap - returns the nth channel of the given capability
+ * 	defaults to returning the channel with the desired capability and the
+ * 	lowest reference count if the index can not be satisfied
+ * @cap: capability to match
+ * @index: nth channel desired, passing -1 has the effect of forcing the
+ *  default return value
+ */
+static struct dma_chan_ref *
+get_chan_ref_by_cap(enum dma_transaction_type cap, int index)
+{
+	struct dma_chan_ref *ret_ref = NULL, *min_ref = NULL, *ref;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+		if (dma_has_cap(cap, ref->chan->device->cap_mask)) {
+			if (!min_ref)
+				min_ref = ref;
+			else if (atomic_read(&ref->count) <
+				atomic_read(&min_ref->count))
+				min_ref = ref;
+
+			if (index-- == 0) {
+				ret_ref = ref;
+				break;
+			}
+		}
+	rcu_read_unlock();
+
+	if (!ret_ref)
+		ret_ref = min_ref;
+
+	if (ret_ref)
+		atomic_inc(&ret_ref->count);
+
+	return ret_ref;
+}
+
+/**
+ * async_tx_rebalance - redistribute the available channels, optimize
+ * for cpu isolation in the SMP case, and opertaion isolation in the
+ * uniprocessor case
+ */
+static void async_tx_rebalance(void)
+{
+	int cpu, cap, cpu_idx = 0;
+	unsigned long flags;
+
+	if (!channel_table_initialized)
+		return;
+
+	spin_lock_irqsave(&async_tx_lock, flags);
+
+	/* undo the last distribution */
+	for_each_dma_cap_mask(cap, dma_cap_mask_all)
+		for_each_possible_cpu(cpu) {
+			struct dma_chan_ref *ref =
+				per_cpu_ptr(channel_table[cap], cpu)->ref;
+			if (ref) {
+				atomic_set(&ref->count, 0);
+				per_cpu_ptr(channel_table[cap], cpu)->ref =
+									NULL;
+			}
+		}
+
+	for_each_dma_cap_mask(cap, dma_cap_mask_all)
+		for_each_online_cpu(cpu) {
+			struct dma_chan_ref *new;
+			if (NR_CPUS > 1)
+				new = get_chan_ref_by_cap(cap, cpu_idx++);
+			else
+				new = get_chan_ref_by_cap(cap, -1);
+
+			per_cpu_ptr(channel_table[cap], cpu)->ref = new;
+		}
+
+	spin_unlock_irqrestore(&async_tx_lock, flags);
+}
+
+static enum dma_state_client
+dma_channel_add_remove(struct dma_client *client,
+	struct dma_chan *chan, enum dma_state state)
+{
+	unsigned long found, flags;
+	struct dma_chan_ref *master_ref, *ref;
+	enum dma_state_client ack = DMA_DUP; /* default: take no action */
+
+	switch (state) {
+	case DMA_RESOURCE_AVAILABLE:
+		found = 0;
+		rcu_read_lock();
+		list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+			if (ref->chan == chan) {
+				found = 1;
+				break;
+			}
+		rcu_read_unlock();
+
+		pr_debug("async_tx: dma resource available [%s]\n",
+			found ? "old" : "new");
+
+		if (!found)
+			ack = DMA_ACK;
+		else
+			break;
+
+		/* add the channel to the generic management list */
+		master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL);
+		if (master_ref) {
+			/* keep a reference until async_tx is unloaded */
+			dma_chan_get(chan);
+			init_dma_chan_ref(master_ref, chan);
+			spin_lock_irqsave(&async_tx_lock, flags);
+			list_add_tail_rcu(&master_ref->node,
+				&async_tx_master_list);
+			spin_unlock_irqrestore(&async_tx_lock,
+				flags);
+		} else {
+			printk(KERN_WARNING "async_tx: unable to create"
+				" new master entry in response to"
+				" a DMA_RESOURCE_ADDED event"
+				" (-ENOMEM)\n");
+			return 0;
+		}
+
+		async_tx_rebalance();
+		break;
+	case DMA_RESOURCE_REMOVED:
+		found = 0;
+		spin_lock_irqsave(&async_tx_lock, flags);
+		list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+			if (ref->chan == chan) {
+				/* permit backing devices to go away */
+				dma_chan_put(ref->chan);
+				list_del_rcu(&ref->node);
+				call_rcu(&ref->rcu, free_dma_chan_ref);
+				found = 1;
+				break;
+			}
+		spin_unlock_irqrestore(&async_tx_lock, flags);
+
+		pr_debug("async_tx: dma resource removed [%s]\n",
+			found ? "ours" : "not ours");
+
+		if (found)
+			ack = DMA_ACK;
+		else
+			break;
+
+		async_tx_rebalance();
+		break;
+	case DMA_RESOURCE_SUSPEND:
+	case DMA_RESOURCE_RESUME:
+		printk(KERN_WARNING "async_tx: does not support dma channel"
+			" suspend/resume\n");
+		break;
+	default:
+		BUG();
+	}
+
+	return ack;
+}
+
+static int __init
+async_tx_init(void)
+{
+	enum dma_transaction_type cap;
+
+	spin_lock_init(&async_tx_lock);
+	bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END);
+
+	/* an interrupt will never be an explicit operation type.
+	 * clearing this bit prevents allocation to a slot in 'channel_table'
+	 */
+	clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits);
+
+	for_each_dma_cap_mask(cap, dma_cap_mask_all) {
+		channel_table[cap] = alloc_percpu(struct chan_ref_percpu);
+		if (!channel_table[cap])
+			goto err;
+	}
+
+	channel_table_initialized = 1;
+	dma_async_client_register(&async_tx_dma);
+	dma_async_client_chan_request(&async_tx_dma);
+
+	printk(KERN_INFO "async_tx: api initialized (async)\n");
+
+	return 0;
+err:
+	printk(KERN_ERR "async_tx: initialization failure\n");
+
+	while (--cap >= 0)
+		free_percpu(channel_table[cap]);
+
+	return 1;
+}
+
+static void __exit async_tx_exit(void)
+{
+	enum dma_transaction_type cap;
+
+	channel_table_initialized = 0;
+
+	for_each_dma_cap_mask(cap, dma_cap_mask_all)
+		if (channel_table[cap])
+			free_percpu(channel_table[cap]);
+
+	dma_async_client_unregister(&async_tx_dma);
+}
+
+/**
+ * async_tx_find_channel - find a channel to carry out the operation or let
+ *	the transaction execute synchronously
+ * @depend_tx: transaction dependency
+ * @tx_type: transaction type
+ */
+struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+	enum dma_transaction_type tx_type)
+{
+	/* see if we can keep the chain on one channel */
+	if (depend_tx &&
+		dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
+		return depend_tx->chan;
+	else if (likely(channel_table_initialized)) {
+		struct dma_chan_ref *ref;
+		int cpu = get_cpu();
+		ref = per_cpu_ptr(channel_table[tx_type], cpu)->ref;
+		put_cpu();
+		return ref ? ref->chan : NULL;
+	} else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(async_tx_find_channel);
+#else
+static int __init async_tx_init(void)
+{
+	printk(KERN_INFO "async_tx: api initialized (sync-only)\n");
+	return 0;
+}
+
+static void __exit async_tx_exit(void)
+{
+	do { } while (0);
+}
+#endif
+
+void
+async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+	enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_param)
+{
+	tx->callback = cb_fn;
+	tx->callback_param = cb_param;
+
+	/* set this new tx to run after depend_tx if:
+	 * 1/ a dependency exists (depend_tx is !NULL)
+	 * 2/ the tx can not be submitted to the current channel
+	 */
+	if (depend_tx && depend_tx->chan != chan) {
+		/* if ack is already set then we cannot be sure
+		 * we are referring to the correct operation
+		 */
+		BUG_ON(depend_tx->ack);
+
+		tx->parent = depend_tx;
+		spin_lock_bh(&depend_tx->lock);
+		list_add_tail(&tx->depend_node, &depend_tx->depend_list);
+		if (depend_tx->cookie == 0) {
+			struct dma_chan *dep_chan = depend_tx->chan;
+			struct dma_device *dep_dev = dep_chan->device;
+			dep_dev->device_dependency_added(dep_chan);
+		}
+		spin_unlock_bh(&depend_tx->lock);
+
+		/* schedule an interrupt to trigger the channel switch */
+		async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
+	} else {
+		tx->parent = NULL;
+		tx->tx_submit(tx);
+	}
+
+	if (flags & ASYNC_TX_ACK)
+		async_tx_ack(tx);
+
+	if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
+		async_tx_ack(depend_tx);
+}
+EXPORT_SYMBOL_GPL(async_tx_submit);
+
+/**
+ * async_trigger_callback - schedules the callback function to be run after
+ * any dependent operations have been completed.
+ * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: 'callback' requires the completion of this transaction
+ * @cb_fn: function to call after depend_tx completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_trigger_callback(enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_param)
+{
+	struct dma_chan *chan;
+	struct dma_device *device;
+	struct dma_async_tx_descriptor *tx;
+
+	if (depend_tx) {
+		chan = depend_tx->chan;
+		device = chan->device;
+
+		/* see if we can schedule an interrupt
+		 * otherwise poll for completion
+		 */
+		if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
+			device = NULL;
+
+		tx = device ? device->device_prep_dma_interrupt(chan) : NULL;
+	} else
+		tx = NULL;
+
+	if (tx) {
+		pr_debug("%s: (async)\n", __FUNCTION__);
+
+		async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+	} else {
+		pr_debug("%s: (sync)\n", __FUNCTION__);
+
+		/* wait for any prerequisite operations */
+		if (depend_tx) {
+			/* if ack is already set then we cannot be sure
+			 * we are referring to the correct operation
+			 */
+			BUG_ON(depend_tx->ack);
+			if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+				panic("%s: DMA_ERROR waiting for depend_tx\n",
+					__FUNCTION__);
+		}
+
+		async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+	}
+
+	return tx;
+}
+EXPORT_SYMBOL_GPL(async_trigger_callback);
+
+module_init(async_tx_init);
+module_exit(async_tx_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
new file mode 100644
index 0000000..2575f67
--- /dev/null
+++ b/crypto/async_tx/async_xor.c
@@ -0,0 +1,327 @@
+/*
+ * xor offload engine api
+ *
+ * Copyright © 2006, Intel Corporation.
+ *
+ *      Dan Williams <dan.j.williams@intel.com>
+ *
+ *      with architecture considerations by:
+ *      Neil Brown <neilb@suse.de>
+ *      Jeff Garzik <jeff@garzik.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/raid/xor.h>
+#include <linux/async_tx.h>
+
+static void
+do_async_xor(struct dma_async_tx_descriptor *tx, struct dma_device *device,
+	struct dma_chan *chan, struct page *dest, struct page **src_list,
+	unsigned int offset, unsigned int src_cnt, size_t len,
+	enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_param)
+{
+	dma_addr_t dma_addr;
+	enum dma_data_direction dir;
+	int i;
+
+	pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+
+	dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+		DMA_NONE : DMA_FROM_DEVICE;
+
+	dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
+	tx->tx_set_dest(dma_addr, tx, 0);
+
+	dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+		DMA_NONE : DMA_TO_DEVICE;
+
+	for (i = 0; i < src_cnt; i++) {
+		dma_addr = dma_map_page(device->dev, src_list[i],
+			offset, len, dir);
+		tx->tx_set_src(dma_addr, tx, i);
+	}
+
+	async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+}
+
+static void
+do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
+	unsigned int src_cnt, size_t len, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_param)
+{
+	void *_dest;
+	int i;
+
+	pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+
+	/* reuse the 'src_list' array to convert to buffer pointers */
+	for (i = 0; i < src_cnt; i++)
+		src_list[i] = (struct page *)
+			(page_address(src_list[i]) + offset);
+
+	/* set destination address */
+	_dest = page_address(dest) + offset;
+
+	if (flags & ASYNC_TX_XOR_ZERO_DST)
+		memset(_dest, 0, len);
+
+	xor_blocks(src_cnt, len, _dest,
+		(void **) src_list);
+
+	async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+}
+
+/**
+ * async_xor - attempt to xor a set of blocks with a dma engine.
+ *	xor_blocks always uses the dest as a source so the ASYNC_TX_XOR_ZERO_DST
+ *	flag must be set to not include dest data in the calculation.  The
+ *	assumption with dma eninges is that they only use the destination
+ *	buffer as a source when it is explicity specified in the source list.
+ * @dest: destination page
+ * @src_list: array of source pages (if the dest is also a source it must be
+ *	at index zero).  The contents of this array may be overwritten.
+ * @offset: offset in pages to start transaction
+ * @src_cnt: number of source pages
+ * @len: length in bytes
+ * @flags: ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DEST,
+ *	ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: xor depends on the result of this transaction.
+ * @cb_fn: function to call when the xor completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+	int src_cnt, size_t len, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_param)
+{
+	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR);
+	struct dma_device *device = chan ? chan->device : NULL;
+	struct dma_async_tx_descriptor *tx = NULL;
+	dma_async_tx_callback _cb_fn;
+	void *_cb_param;
+	unsigned long local_flags;
+	int xor_src_cnt;
+	int i = 0, src_off = 0, int_en;
+
+	BUG_ON(src_cnt <= 1);
+
+	while (src_cnt) {
+		local_flags = flags;
+		if (device) { /* run the xor asynchronously */
+			xor_src_cnt = min(src_cnt, device->max_xor);
+			/* if we are submitting additional xors
+			 * only set the callback on the last transaction
+			 */
+			if (src_cnt > xor_src_cnt) {
+				local_flags &= ~ASYNC_TX_ACK;
+				_cb_fn = NULL;
+				_cb_param = NULL;
+			} else {
+				_cb_fn = cb_fn;
+				_cb_param = cb_param;
+			}
+
+			int_en = _cb_fn ? 1 : 0;
+
+			tx = device->device_prep_dma_xor(
+				chan, xor_src_cnt, len, int_en);
+
+			if (tx) {
+				do_async_xor(tx, device, chan, dest,
+				&src_list[src_off], offset, xor_src_cnt, len,
+				local_flags, depend_tx, _cb_fn,
+				_cb_param);
+			} else /* fall through */
+				goto xor_sync;
+		} else { /* run the xor synchronously */
+xor_sync:
+			/* in the sync case the dest is an implied source
+			 * (assumes the dest is at the src_off index)
+			 */
+			if (flags & ASYNC_TX_XOR_DROP_DST) {
+				src_cnt--;
+				src_off++;
+			}
+
+			/* process up to 'MAX_XOR_BLOCKS' sources */
+			xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
+
+			/* if we are submitting additional xors
+			 * only set the callback on the last transaction
+			 */
+			if (src_cnt > xor_src_cnt) {
+				local_flags &= ~ASYNC_TX_ACK;
+				_cb_fn = NULL;
+				_cb_param = NULL;
+			} else {
+				_cb_fn = cb_fn;
+				_cb_param = cb_param;
+			}
+
+			/* wait for any prerequisite operations */
+			if (depend_tx) {
+				/* if ack is already set then we cannot be sure
+				 * we are referring to the correct operation
+				 */
+				BUG_ON(depend_tx->ack);
+				if (dma_wait_for_async_tx(depend_tx) ==
+					DMA_ERROR)
+					panic("%s: DMA_ERROR waiting for "
+						"depend_tx\n",
+						__FUNCTION__);
+			}
+
+			do_sync_xor(dest, &src_list[src_off], offset,
+				xor_src_cnt, len, local_flags, depend_tx,
+				_cb_fn, _cb_param);
+		}
+
+		/* the previous tx is hidden from the client,
+		 * so ack it
+		 */
+		if (i && depend_tx)
+			async_tx_ack(depend_tx);
+
+		depend_tx = tx;
+
+		if (src_cnt > xor_src_cnt) {
+			/* drop completed sources */
+			src_cnt -= xor_src_cnt;
+			src_off += xor_src_cnt;
+
+			/* unconditionally preserve the destination */
+			flags &= ~ASYNC_TX_XOR_ZERO_DST;
+
+			/* use the intermediate result a source, but remember
+			 * it's dropped, because it's implied, in the sync case
+			 */
+			src_list[--src_off] = dest;
+			src_cnt++;
+			flags |= ASYNC_TX_XOR_DROP_DST;
+		} else
+			src_cnt = 0;
+		i++;
+	}
+
+	return tx;
+}
+EXPORT_SYMBOL_GPL(async_xor);
+
+static int page_is_zero(struct page *p, unsigned int offset, size_t len)
+{
+	char *a = page_address(p) + offset;
+	return ((*(u32 *) a) == 0 &&
+		memcmp(a, a + 4, len - 4) == 0);
+}
+
+/**
+ * async_xor_zero_sum - attempt a xor parity check with a dma engine.
+ * @dest: destination page used if the xor is performed synchronously
+ * @src_list: array of source pages.  The dest page must be listed as a source
+ * 	at index zero.  The contents of this array may be overwritten.
+ * @offset: offset in pages to start transaction
+ * @src_cnt: number of source pages
+ * @len: length in bytes
+ * @result: 0 if sum == 0 else non-zero
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: xor depends on the result of this transaction.
+ * @cb_fn: function to call when the xor completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_xor_zero_sum(struct page *dest, struct page **src_list,
+	unsigned int offset, int src_cnt, size_t len,
+	u32 *result, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_param)
+{
+	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM);
+	struct dma_device *device = chan ? chan->device : NULL;
+	int int_en = cb_fn ? 1 : 0;
+	struct dma_async_tx_descriptor *tx = device ?
+		device->device_prep_dma_zero_sum(chan, src_cnt, len, result,
+			int_en) : NULL;
+	int i;
+
+	BUG_ON(src_cnt <= 1);
+
+	if (tx) {
+		dma_addr_t dma_addr;
+		enum dma_data_direction dir;
+
+		pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+
+		dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+			DMA_NONE : DMA_TO_DEVICE;
+
+		for (i = 0; i < src_cnt; i++) {
+			dma_addr = dma_map_page(device->dev, src_list[i],
+				offset, len, dir);
+			tx->tx_set_src(dma_addr, tx, i);
+		}
+
+		async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+	} else {
+		unsigned long xor_flags = flags;
+
+		pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+		xor_flags |= ASYNC_TX_XOR_DROP_DST;
+		xor_flags &= ~ASYNC_TX_ACK;
+
+		tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,
+			depend_tx, NULL, NULL);
+
+		if (tx) {
+			if (dma_wait_for_async_tx(tx) == DMA_ERROR)
+				panic("%s: DMA_ERROR waiting for tx\n",
+					__FUNCTION__);
+			async_tx_ack(tx);
+		}
+
+		*result = page_is_zero(dest, offset, len) ? 0 : 1;
+
+		tx = NULL;
+
+		async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+	}
+
+	return tx;
+}
+EXPORT_SYMBOL_GPL(async_xor_zero_sum);
+
+static int __init async_xor_init(void)
+{
+	return 0;
+}
+
+static void __exit async_xor_exit(void)
+{
+	do { } while (0);
+}
+
+module_init(async_xor_init);
+module_exit(async_xor_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous xor/xor-zero-sum api");
+MODULE_LICENSE("GPL");
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 8edf40c..40a3dcf 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -336,16 +336,41 @@
 	return blkcipher_walk_next(desc, walk);
 }
 
+static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher;
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+	int ret;
+	u8 *buffer, *alignbuffer;
+	unsigned long absize;
+
+	absize = keylen + alignmask;
+	buffer = kmalloc(absize, GFP_ATOMIC);
+	if (!buffer)
+		return -ENOMEM;
+
+	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+	memcpy(alignbuffer, key, keylen);
+	ret = cipher->setkey(tfm, alignbuffer, keylen);
+	memset(alignbuffer, 0, absize);
+	kfree(buffer);
+	return ret;
+}
+
 static int setkey(struct crypto_tfm *tfm, const u8 *key,
 		  unsigned int keylen)
 {
 	struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher;
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
 
 	if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 		return -EINVAL;
 	}
 
+	if ((unsigned long)key & alignmask)
+		return setkey_unaligned(tfm, key, keylen);
+
 	return cipher->setkey(tfm, key, keylen);
 }
 
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 333aab2f..0b2650c 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -20,16 +20,43 @@
 #include <linux/string.h>
 #include "internal.h"
 
+static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+	int ret;
+	u8 *buffer, *alignbuffer;
+	unsigned long absize;
+
+	absize = keylen + alignmask;
+	buffer = kmalloc(absize, GFP_ATOMIC);
+	if (!buffer)
+		return -ENOMEM;
+
+	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+	memcpy(alignbuffer, key, keylen);
+	ret = cia->cia_setkey(tfm, alignbuffer, keylen);
+	memset(alignbuffer, 0, absize);
+	kfree(buffer);
+	return ret;
+
+}
+
 static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
 {
 	struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
-	
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+
 	tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
 	if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 		return -EINVAL;
-	} else
-		return cia->cia_setkey(tfm, key, keylen);
+	}
+
+	if ((unsigned long)key & alignmask)
+		return setkey_unaligned(tfm, key, keylen);
+
+	return cia->cia_setkey(tfm, key, keylen);
 }
 
 static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 3ff4e1f..ac6dce2 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -298,7 +298,7 @@
 	mutex_init(&state->mutex);
 	crypto_init_queue(&state->queue, CRYPTD_MAX_QLEN);
 
-	state->task = kthread_create(fn, state, name);
+	state->task = kthread_run(fn, state, name);
 	if (IS_ERR(state->task))
 		return PTR_ERR(state->task);
 
@@ -316,6 +316,8 @@
 	struct cryptd_state *state = data;
 	int stop;
 
+	current->flags |= PF_NOFREEZE;
+
 	do {
 		struct crypto_async_request *req, *backlog;
 
diff --git a/crypto/hash.c b/crypto/hash.c
index 4ccd22d..4d75ca7 100644
--- a/crypto/hash.c
+++ b/crypto/hash.c
@@ -22,6 +22,42 @@
 	return alg->cra_ctxsize;
 }
 
+static int hash_setkey_unaligned(struct crypto_hash *crt, const u8 *key,
+		                 unsigned int keylen)
+{
+	struct crypto_tfm *tfm = crypto_hash_tfm(crt);
+	struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+	unsigned long alignmask = crypto_hash_alignmask(crt);
+	int ret;
+	u8 *buffer, *alignbuffer;
+	unsigned long absize;
+
+	absize = keylen + alignmask;
+	buffer = kmalloc(absize, GFP_ATOMIC);
+	if (!buffer)
+		return -ENOMEM;
+
+	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+	memcpy(alignbuffer, key, keylen);
+	ret = alg->setkey(crt, alignbuffer, keylen);
+	memset(alignbuffer, 0, absize);
+	kfree(buffer);
+	return ret;
+}
+
+static int hash_setkey(struct crypto_hash *crt, const u8 *key,
+		unsigned int keylen)
+{
+	struct crypto_tfm *tfm = crypto_hash_tfm(crt);
+	struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+	unsigned long alignmask = crypto_hash_alignmask(crt);
+
+	if ((unsigned long)key & alignmask)
+		return hash_setkey_unaligned(crt, key, keylen);
+
+	return alg->setkey(crt, key, keylen);
+}
+
 static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 {
 	struct hash_tfm *crt = &tfm->crt_hash;
@@ -34,7 +70,7 @@
 	crt->update = alg->update;
 	crt->final = alg->final;
 	crt->digest = alg->digest;
-	crt->setkey = alg->setkey;
+	crt->setkey = hash_setkey;
 	crt->digestsize = alg->digestsize;
 
 	return 0;
diff --git a/crypto/proc.c b/crypto/proc.c
index 102c751..3d73323 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -23,24 +23,13 @@
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	struct list_head *v;
-	loff_t n = *pos;
-
 	down_read(&crypto_alg_sem);
-	list_for_each(v, &crypto_alg_list)
-		if (!n--)
-			return list_entry(v, struct crypto_alg, cra_list);
-	return NULL;
+	return seq_list_start(&crypto_alg_list, *pos);
 }
 
 static void *c_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	struct list_head *v = p;
-	
-	(*pos)++;
-	v = v->next;
-	return (v == &crypto_alg_list) ?
-		NULL : list_entry(v, struct crypto_alg, cra_list);
+	return seq_list_next(p, &crypto_alg_list, pos);
 }
 
 static void c_stop(struct seq_file *m, void *p)
@@ -50,7 +39,7 @@
 
 static int c_show(struct seq_file *m, void *p)
 {
-	struct crypto_alg *alg = (struct crypto_alg *)p;
+	struct crypto_alg *alg = list_entry(p, struct crypto_alg, cra_list);
 	
 	seq_printf(m, "name         : %s\n", alg->cra_name);
 	seq_printf(m, "driver       : %s\n", alg->cra_driver_name);
diff --git a/crypto/xor.c b/crypto/xor.c
new file mode 100644
index 0000000..b2e6db0
--- /dev/null
+++ b/crypto/xor.c
@@ -0,0 +1,155 @@
+/*
+ * xor.c : Multiple Devices driver for Linux
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000,
+ * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson.
+ *
+ * Dispatch optimized RAID-5 checksumming functions.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define BH_TRACE 0
+#include <linux/module.h>
+#include <linux/raid/md.h>
+#include <linux/raid/xor.h>
+#include <asm/xor.h>
+
+/* The xor routines to use.  */
+static struct xor_block_template *active_template;
+
+void
+xor_blocks(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
+{
+	unsigned long *p1, *p2, *p3, *p4;
+
+	p1 = (unsigned long *) srcs[0];
+	if (src_count == 1) {
+		active_template->do_2(bytes, dest, p1);
+		return;
+	}
+
+	p2 = (unsigned long *) srcs[1];
+	if (src_count == 2) {
+		active_template->do_3(bytes, dest, p1, p2);
+		return;
+	}
+
+	p3 = (unsigned long *) srcs[2];
+	if (src_count == 3) {
+		active_template->do_4(bytes, dest, p1, p2, p3);
+		return;
+	}
+
+	p4 = (unsigned long *) srcs[3];
+	active_template->do_5(bytes, dest, p1, p2, p3, p4);
+}
+EXPORT_SYMBOL(xor_blocks);
+
+/* Set of all registered templates.  */
+static struct xor_block_template *template_list;
+
+#define BENCH_SIZE (PAGE_SIZE)
+
+static void
+do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
+{
+	int speed;
+	unsigned long now;
+	int i, count, max;
+
+	tmpl->next = template_list;
+	template_list = tmpl;
+
+	/*
+	 * Count the number of XORs done during a whole jiffy, and use
+	 * this to calculate the speed of checksumming.  We use a 2-page
+	 * allocation to have guaranteed color L1-cache layout.
+	 */
+	max = 0;
+	for (i = 0; i < 5; i++) {
+		now = jiffies;
+		count = 0;
+		while (jiffies == now) {
+			mb(); /* prevent loop optimzation */
+			tmpl->do_2(BENCH_SIZE, b1, b2);
+			mb();
+			count++;
+			mb();
+		}
+		if (count > max)
+			max = count;
+	}
+
+	speed = max * (HZ * BENCH_SIZE / 1024);
+	tmpl->speed = speed;
+
+	printk(KERN_INFO "   %-10s: %5d.%03d MB/sec\n", tmpl->name,
+	       speed / 1000, speed % 1000);
+}
+
+static int __init
+calibrate_xor_blocks(void)
+{
+	void *b1, *b2;
+	struct xor_block_template *f, *fastest;
+
+	b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
+	if (!b1) {
+		printk(KERN_WARNING "xor: Yikes!  No memory available.\n");
+		return -ENOMEM;
+	}
+	b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
+
+	/*
+	 * If this arch/cpu has a short-circuited selection, don't loop through
+	 * all the possible functions, just test the best one
+	 */
+
+	fastest = NULL;
+
+#ifdef XOR_SELECT_TEMPLATE
+		fastest = XOR_SELECT_TEMPLATE(fastest);
+#endif
+
+#define xor_speed(templ)	do_xor_speed((templ), b1, b2)
+
+	if (fastest) {
+		printk(KERN_INFO "xor: automatically using best "
+			"checksumming function: %s\n",
+			fastest->name);
+		xor_speed(fastest);
+	} else {
+		printk(KERN_INFO "xor: measuring software checksum speed\n");
+		XOR_TRY_TEMPLATES;
+		fastest = template_list;
+		for (f = fastest; f; f = f->next)
+			if (f->speed > fastest->speed)
+				fastest = f;
+	}
+
+	printk(KERN_INFO "xor: using function: %s (%d.%03d MB/sec)\n",
+	       fastest->name, fastest->speed / 1000, fastest->speed % 1000);
+
+#undef xor_speed
+
+	free_pages((unsigned long)b1, 2);
+
+	active_template = fastest;
+	return 0;
+}
+
+static __exit void xor_exit(void) { }
+
+MODULE_LICENSE("GPL");
+
+/* when built-in xor.o must initialize before drivers/md/md.o */
+core_initcall(calibrate_xor_blocks);
+module_exit(xor_exit);
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 050323f..7916f4b 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -24,8 +24,6 @@
 
 source "drivers/ata/Kconfig"
 
-source "drivers/cdrom/Kconfig"
-
 source "drivers/md/Kconfig"
 
 source "drivers/message/fusion/Kconfig"
@@ -54,6 +52,8 @@
 
 source "drivers/w1/Kconfig"
 
+source "drivers/power/Kconfig"
+
 source "drivers/hwmon/Kconfig"
 
 source "drivers/mfd/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index adad2f3..503d825 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,7 @@
 obj-$(CONFIG_RTC_LIB)		+= rtc/
 obj-y				+= i2c/
 obj-$(CONFIG_W1)		+= w1/
+obj-$(CONFIG_POWER_SUPPLY)	+= power/
 obj-$(CONFIG_HWMON)		+= hwmon/
 obj-$(CONFIG_PHONE)		+= telephony/
 obj-$(CONFIG_MD)		+= md/
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 674bf81..423ed08 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1246,7 +1246,7 @@
 	del_timer(&motor_off_timer);
 
 	ReqCnt = 0;
-	ReqCmd = CURRENT->cmd;
+	ReqCmd = rq_data_dir(CURRENT);
 	ReqBlock = CURRENT->sector;
 	ReqBuffer = CURRENT->buffer;
 	setup_req_params(drive);
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 689a4c3..d85520f 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -439,7 +439,7 @@
 	   a choice of command end or some data which is ready to be collected */
 	/* I think we have to transfer data while the interrupt line is on and its
 	   not any other type of interrupt */
-	if (CURRENT->cmd == WRITE) {
+	if (rq_data_dir(CURRENT) == WRITE) {
 		extern void hdc63463_writedma(void);
 		if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
 			printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
@@ -799,7 +799,7 @@
 	raw_cmd.head = start_head;
 	raw_cmd.cylinder = track / p->heads;
 	raw_cmd.cmdtype = CURRENT->cmd;
-	raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
+	raw_cmd.cmdcode = rq_data_dir(CURRENT) == WRITE ? CMD_WD : CMD_RD;
 	raw_cmd.cmddata[0] = dev + 1;	/* DAG: +1 to get US */
 	raw_cmd.cmddata[1] = raw_cmd.head;
 	raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
@@ -830,7 +830,7 @@
 	hdc63463_dataleft = nsect * 256;	/* Better way? */
 
 	DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
-	     raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",
+	     raw_cmd.dev + 'a', rq_data_dir(CURRENT) == READ ? "read" : "writ",
 		       raw_cmd.cylinder,
 		       raw_cmd.head,
 	    raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
@@ -917,13 +917,6 @@
 
 		DBG("mfm_request: block after offset=%d\n", block);
 
-		if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {
-			printk("unknown mfm-command %d\n", CURRENT->cmd);
-			end_request(CURRENT, 0);
-			Busy = 0;
-			printk("mfm: continue 4\n");
-			continue;
-		}
 		issue_request(block, nsect, CURRENT);
 
 		break;
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index b770dea..3cd79ca 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -1357,7 +1357,7 @@
         .update_status  = set_brightness_status,
 };
 
-static void __exit asus_acpi_exit(void)
+static void asus_acpi_exit(void)
 {
 	if (asus_backlight_device)
 		backlight_device_unregister(asus_backlight_device);
@@ -1398,7 +1398,7 @@
 	if (!asus_hotk_found) {
 		acpi_bus_unregister_driver(&asus_hotk_driver);
 		remove_proc_entry(PROC_ASUS, acpi_root_dir);
-		return result;
+		return -ENODEV;
 	}
 
 	asus_backlight_device = backlight_device_register("asus",NULL,NULL,
@@ -1407,6 +1407,7 @@
 		printk(KERN_ERR "Could not register asus backlight device\n");
 		asus_backlight_device = NULL;
 		asus_acpi_exit();
+		return -ENODEV;
 	}
         asus_backlight_device->props.max_brightness = 15;
 
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index a2efae8..0c9f15c 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -59,7 +59,7 @@
 	return node_to_pxm_map[node];
 }
 
-int __cpuinit acpi_map_pxm_to_node(int pxm)
+int acpi_map_pxm_to_node(int pxm)
 {
 	int node = pxm_to_node_map[pxm];
 
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index b998340..2e7ba61 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -33,6 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/kmod.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/workqueue.h>
 #include <linux/nmi.h>
 #include <linux/acpi.h>
@@ -73,6 +74,21 @@
 static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
 
+#define	OSI_STRING_LENGTH_MAX 64	/* arbitrary */
+static char osi_additional_string[OSI_STRING_LENGTH_MAX];
+
+#define OSI_LINUX_ENABLED
+#ifdef	OSI_LINUX_ENABLED
+int osi_linux = 1;	/* enable _OSI(Linux) by default */
+#else
+int osi_linux;		/* disable _OSI(Linux) by default */
+#endif
+
+
+#ifdef CONFIG_DMI
+static struct __initdata dmi_system_id acpi_osl_dmi_table[];
+#endif
+
 static void __init acpi_request_region (struct acpi_generic_address *addr,
 	unsigned int length, char *desc)
 {
@@ -121,8 +137,9 @@
 }
 device_initcall(acpi_reserve_resources);
 
-acpi_status acpi_os_initialize(void)
+acpi_status __init acpi_os_initialize(void)
 {
+	dmi_check_system(acpi_osl_dmi_table);
 	return AE_OK;
 }
 
@@ -960,20 +977,38 @@
 
 __setup("acpi_os_name=", acpi_os_name_setup);
 
+static void enable_osi_linux(int enable) {
+
+	if (osi_linux != enable)
+		printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n",
+			enable ? "En": "Dis");
+
+	osi_linux = enable;
+	return;
+}
+
 /*
- * _OSI control
+ * Modify the list of "OS Interfaces" reported to BIOS via _OSI
+ *
  * empty string disables _OSI
- * TBD additional string adds to _OSI
+ * string starting with '!' disables that string
+ * otherwise string is added to list, augmenting built-in strings
  */
 static int __init acpi_osi_setup(char *str)
 {
 	if (str == NULL || *str == '\0') {
 		printk(KERN_INFO PREFIX "_OSI method disabled\n");
 		acpi_gbl_create_osi_method = FALSE;
-	} else {
-		/* TBD */
-		printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n",
-		       str);
+	} else if (!strcmp("!Linux", str)) {
+		enable_osi_linux(0);
+	} else if (*str == '!') {
+		if (acpi_osi_invalidate(++str) == AE_OK)
+			printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
+	} else if (!strcmp("Linux", str)) {
+		enable_osi_linux(1);
+	} else if (*osi_additional_string == '\0') {
+		strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
+		printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
 	}
 
 	return 1;
@@ -1143,11 +1178,28 @@
 acpi_status
 acpi_os_validate_interface (char *interface)
 {
-
-    return AE_SUPPORT;
+	if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
+		return AE_OK;
+	if (!strcmp("Linux", interface)) {
+		printk(KERN_WARNING PREFIX
+			"System BIOS is requesting _OSI(Linux)\n");
+#ifdef	OSI_LINUX_ENABLED
+		printk(KERN_WARNING PREFIX
+			"Please test with \"acpi_osi=!Linux\"\n"
+			"Please send dmidecode "
+			"to linux-acpi@vger.kernel.org\n");
+#else
+		printk(KERN_WARNING PREFIX
+			"If \"acpi_osi=Linux\" works better,\n"
+			"Please send dmidecode "
+			"to linux-acpi@vger.kernel.org\n");
+#endif
+		if(osi_linux)
+			return AE_OK;
+	}
+	return AE_SUPPORT;
 }
 
-
 /******************************************************************************
  *
  * FUNCTION:    acpi_os_validate_address
@@ -1174,5 +1226,51 @@
     return AE_OK;
 }
 
+#ifdef CONFIG_DMI
+#ifdef	OSI_LINUX_ENABLED
+static int dmi_osi_not_linux(struct dmi_system_id *d)
+{
+	printk(KERN_NOTICE "%s detected: requires not _OSI(Linux)\n", d->ident);
+	enable_osi_linux(0);
+	return 0;
+}
+#else
+static int dmi_osi_linux(struct dmi_system_id *d)
+{
+	printk(KERN_NOTICE "%s detected: requires _OSI(Linux)\n", d->ident);
+	enable_osi_linux(1);
+	return 0;
+}
+#endif
+
+static struct dmi_system_id acpi_osl_dmi_table[] __initdata = {
+#ifdef	OSI_LINUX_ENABLED
+	/*
+	 * Boxes that need NOT _OSI(Linux)
+	 */
+	{
+	 .callback = dmi_osi_not_linux,
+	 .ident = "Toshiba Satellite P100",
+	 .matches = {
+		     DMI_MATCH(DMI_BOARD_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_BOARD_NAME, "Satellite P100"),
+		     },
+	 },
+#else
+	/*
+	 * Boxes that need _OSI(Linux)
+	 */
+	{
+	 .callback = dmi_osi_linux,
+	 .ident = "Intel Napa CRB",
+	 .matches = {
+		     DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+		     DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"),
+		     },
+	 },
+#endif
+	{}
+};
+#endif /* CONFIG_DMI */
 
 #endif
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index f7de02a..e1ca86d 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -115,7 +115,6 @@
 
 static int acpi_processor_errata_piix4(struct pci_dev *dev)
 {
-	u8 rev = 0;
 	u8 value1 = 0;
 	u8 value2 = 0;
 
@@ -127,9 +126,7 @@
 	 * Note that 'dev' references the PIIX4 ACPI Controller.
 	 */
 
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-	switch (rev) {
+	switch (dev->revision) {
 	case 0:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
 		break;
@@ -147,7 +144,7 @@
 		break;
 	}
 
-	switch (rev) {
+	switch (dev->revision) {
 
 	case 0:		/* PIIX4 A-step */
 	case 1:		/* PIIX4 B-step */
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index ee5759b..80ffc78 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -332,16 +332,18 @@
 	int sleep_ticks = 0;
 	u32 t1, t2 = 0;
 
-	pr = processors[smp_processor_id()];
-	if (!pr)
-		return;
-
 	/*
 	 * Interrupts must be disabled during bus mastering calculations and
 	 * for C2/C3 transitions.
 	 */
 	local_irq_disable();
 
+	pr = processors[smp_processor_id()];
+	if (!pr) {
+		local_irq_enable();
+		return;
+	}
+
 	/*
 	 * Check whether we truly need to go idle, or should
 	 * reschedule:
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 0e7b121..3bc0c67 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -123,14 +123,14 @@
 		}
 	}
 
-	/* The table must be either an SSDT or a PSDT */
+	/* The table must be either an SSDT or a PSDT or an OEMx */
 
 	if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT))
 	    &&
-	    (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)))
-	{
+	    (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
+	    && (strncmp(table_desc->pointer->signature, "OEM", 3))) {
 		ACPI_ERROR((AE_INFO,
-			    "Table has invalid signature [%4.4s], must be SSDT or PSDT",
+			    "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx",
 			    table_desc->pointer->signature));
 		return_ACPI_STATUS(AE_BAD_SIGNATURE);
 	}
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 1ada017..88a6fc7 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -827,6 +827,9 @@
 static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
 {
 	struct acpi_thermal *tz = seq->private;
+	struct acpi_device *device;
+	acpi_status status;
+
 	int i = 0;
 	int j = 0;
 
@@ -849,9 +852,10 @@
 			   tz->trips.passive.tc1, tz->trips.passive.tc2,
 			   tz->trips.passive.tsp);
 		for (j = 0; j < tz->trips.passive.devices.count; j++) {
-
-			seq_printf(seq, "0x%p ",
-				   tz->trips.passive.devices.handles[j]);
+			status = acpi_bus_get_device(tz->trips.passive.devices.
+						     handles[j], &device);
+			seq_printf(seq, "%4.4s ", status ? "" :
+				   acpi_device_bid(device));
 		}
 		seq_puts(seq, "\n");
 	}
@@ -862,9 +866,13 @@
 		seq_printf(seq, "active[%d]:               %ld C: devices=",
 			   i,
 			   KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
-		for (j = 0; j < tz->trips.active[i].devices.count; j++)
-			seq_printf(seq, "0x%p ",
-				   tz->trips.active[i].devices.handles[j]);
+		for (j = 0; j < tz->trips.active[i].devices.count; j++){
+			status = acpi_bus_get_device(tz->trips.active[i].
+						     devices.handles[j],
+						     &device);
+			seq_printf(seq, "%4.4s ", status ? "" :
+				   acpi_device_bid(device));
+		}
 		seq_puts(seq, "\n");
 	}
 
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 3906d47..13369b4 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -524,7 +524,7 @@
 	return AE_OK;
 }
 
-static acpi_status __exit remove_device(void)
+static acpi_status remove_device(void)
 {
 	ProcItem *item;
 
@@ -538,7 +538,7 @@
         .update_status  = set_lcd_status,
 };
 
-static void __exit toshiba_acpi_exit(void)
+static void toshiba_acpi_exit(void)
 {
 	if (toshiba_backlight_device)
 		backlight_device_unregister(toshiba_backlight_device);
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 4c1e008..879eaa1 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -68,6 +68,10 @@
 				union acpi_operand_object **return_obj);
 
 static acpi_status
+acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
+				  union acpi_operand_object **internal_object);
+
+static acpi_status
 acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
 			   union acpi_operand_object *dest_desc);
 
@@ -518,77 +522,73 @@
 	return_ACPI_STATUS(AE_NO_MEMORY);
 }
 
-#ifdef ACPI_FUTURE_IMPLEMENTATION
-/* Code to convert packages that are parameters to control methods */
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_copy_epackage_to_ipackage
  *
- * PARAMETERS:  *internal_object   - Pointer to the object we are returning
- *              *Buffer            - Where the object is returned
- *              *space_used        - Where the length of the object is returned
+ * PARAMETERS:  external_object     - The external object to be converted
+ *              internal_object     - Where the internal object is returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: This function is called to place a package object in a user
- *              buffer.  A package object by definition contains other objects.
- *
- *              The buffer is assumed to have sufficient space for the object.
- *              The caller must have verified the buffer length needed using the
- *              acpi_ut_get_object_size function before calling this function.
+ * DESCRIPTION: Copy an external package object to an internal package.
+ *              Handles nested packages.
  *
  ******************************************************************************/
 
 static acpi_status
-acpi_ut_copy_epackage_to_ipackage(union acpi_operand_object *internal_object,
-				  u8 * buffer, u32 * space_used)
+acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
+				  union acpi_operand_object **internal_object)
 {
-	u8 *free_space;
-	union acpi_object *external_object;
-	u32 length = 0;
-	u32 this_index;
-	u32 object_space = 0;
-	union acpi_operand_object *this_internal_obj;
-	union acpi_object *this_external_obj;
+	acpi_status status = AE_OK;
+	union acpi_operand_object *package_object;
+	union acpi_operand_object **package_elements;
+	acpi_native_uint i;
 
 	ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
 
-	/*
-	 * First package at head of the buffer
-	 */
-	external_object = (union acpi_object *)buffer;
+	/* Create the package object */
+
+	package_object =
+	    acpi_ut_create_package_object(external_object->package.count);
+	if (!package_object) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	package_elements = package_object->package.elements;
 
 	/*
-	 * Free space begins right after the first package
+	 * Recursive implementation. Probably ok, since nested external packages
+	 * as parameters should be very rare.
 	 */
-	free_space = buffer + sizeof(union acpi_object);
+	for (i = 0; i < external_object->package.count; i++) {
+		status =
+		    acpi_ut_copy_eobject_to_iobject(&external_object->package.
+						    elements[i],
+						    &package_elements[i]);
+		if (ACPI_FAILURE(status)) {
 
-	external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
-	external_object->package.count = internal_object->package.count;
-	external_object->package.elements = (union acpi_object *)free_space;
+			/* Truncate package and delete it */
 
-	/*
-	 * Build an array of ACPI_OBJECTS in the buffer
-	 * and move the free space past it
-	 */
-	free_space +=
-	    external_object->package.count * sizeof(union acpi_object);
+			package_object->package.count = i;
+			package_elements[i] = NULL;
+			acpi_ut_remove_reference(package_object);
+			return_ACPI_STATUS(status);
+		}
+	}
 
-	/* Call walk_package */
-
+	*internal_object = package_object;
+	return_ACPI_STATUS(status);
 }
 
-#endif				/* Future implementation */
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_copy_eobject_to_iobject
  *
- * PARAMETERS:  *internal_object   - The external object to be converted
- *              *buffer_ptr     - Where the internal object is returned
+ * PARAMETERS:  external_object     - The external object to be converted
+ *              internal_object     - Where the internal object is returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status              - the status of the call
  *
  * DESCRIPTION: Converts an external object to an internal object.
  *
@@ -603,16 +603,10 @@
 	ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
 
 	if (external_object->type == ACPI_TYPE_PACKAGE) {
-		/*
-		 * Packages as external input to control methods are not supported,
-		 */
-		ACPI_ERROR((AE_INFO,
-			    "Packages as parameters not implemented!"));
-
-		return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
-	}
-
-	else {
+		status =
+		    acpi_ut_copy_epackage_to_ipackage(external_object,
+						      internal_object);
+	} else {
 		/*
 		 * Build a simple object (no nested objects)
 		 */
@@ -803,33 +797,19 @@
 		 * Create and build the package object
 		 */
 		target_object =
-		    acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
+		    acpi_ut_create_package_object(source_object->package.count);
 		if (!target_object) {
 			return (AE_NO_MEMORY);
 		}
 
-		target_object->package.count = source_object->package.count;
 		target_object->common.flags = source_object->common.flags;
 
-		/*
-		 * Create the object array
-		 */
-		target_object->package.elements =
-		    ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.
-					  count + 1) * sizeof(void *));
-		if (!target_object->package.elements) {
-			status = AE_NO_MEMORY;
-			goto error_exit;
-		}
+		/* Pass the new package object back to the package walk routine */
 
-		/*
-		 * Pass the new package object back to the package walk routine
-		 */
 		state->pkg.this_target_obj = target_object;
 
-		/*
-		 * Store the object pointer in the parent package object
-		 */
+		/* Store the object pointer in the parent package object */
+
 		*this_target_ptr = target_object;
 		break;
 
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 13d5879..8ec6f8e 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -59,10 +59,9 @@
 /*
  * Strings supported by the _OSI predefined (internal) method.
  */
-static const char *acpi_interfaces_supported[] = {
+static char *acpi_interfaces_supported[] = {
 	/* Operating System Vendor Strings */
 
-	"Linux",
 	"Windows 2000",
 	"Windows 2001",
 	"Windows 2001 SP0",
@@ -158,6 +157,31 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_osi_invalidate
+ *
+ * PARAMETERS:  interface_string
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: invalidate string in pre-defiend _OSI string list
+ *
+ ******************************************************************************/
+
+acpi_status acpi_osi_invalidate(char *interface)
+{
+	int i;
+
+	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
+		if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) {
+			*acpi_interfaces_supported[i] = '\0';
+			return AE_OK;
+		}
+	}
+	return AE_NOT_FOUND;
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_evaluate_object
  *
  * PARAMETERS:  prefix_node         - Starting node
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index 4696124..76ee766 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -146,6 +146,48 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_create_package_object
+ *
+ * PARAMETERS:  Count               - Number of package elements
+ *
+ * RETURN:      Pointer to a new Package object, null on failure
+ *
+ * DESCRIPTION: Create a fully initialized package object
+ *
+ ******************************************************************************/
+
+union acpi_operand_object *acpi_ut_create_package_object(u32 count)
+{
+	union acpi_operand_object *package_desc;
+	union acpi_operand_object **package_elements;
+
+	ACPI_FUNCTION_TRACE_U32(ut_create_package_object, count);
+
+	/* Create a new Package object */
+
+	package_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
+	if (!package_desc) {
+		return_PTR(NULL);
+	}
+
+	/*
+	 * Create the element array. Count+1 allows the array to be null
+	 * terminated.
+	 */
+	package_elements = ACPI_ALLOCATE_ZEROED((acpi_size)
+						(count + 1) * sizeof(void *));
+	if (!package_elements) {
+		acpi_ut_remove_reference(package_desc);
+		return_PTR(NULL);
+	}
+
+	package_desc->package.count = count;
+	package_desc->package.elements = package_elements;
+	return_PTR(package_desc);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_create_buffer_object
  *
  * PARAMETERS:  buffer_size            - Size of buffer to be created
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index e9a5780..2d49691 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -61,7 +61,7 @@
  *              called, so any early initialization belongs here.
  *
  ******************************************************************************/
-acpi_status acpi_initialize_subsystem(void)
+acpi_status __init acpi_initialize_subsystem(void)
 {
 	acpi_status status;
 
@@ -108,8 +108,6 @@
 	return_ACPI_STATUS(status);
 }
 
-ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem)
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enable_subsystem
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ad1f59c..d8046a1 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -16,6 +16,11 @@
 	  that "speaks" the ATA protocol, also called ATA controller),
 	  because you will be asked for it.
 
+	  NOTE: ATA enables basic SCSI support; *however*,
+	  'SCSI disk support', 'SCSI tape support', or
+	  'SCSI CDROM support' may also be needed,
+	  depending on your hardware configuration.
+
 if ATA
 
 config ATA_NONSTANDARD
@@ -132,7 +137,7 @@
 	depends on PCI
 	select PATA_SIS
 	help
-	  This option enables support for SiS Serial ATA on 
+	  This option enables support for SiS Serial ATA on
 	  SiS 964/965/966/180 and Parallel ATA on SiS 180.
 	  The PATA support for SiS 180 requires additionally to
 	  enable the PATA_SIS driver in the config.
@@ -304,7 +309,7 @@
 	  If unsure, say N.
 
 config PATA_HPT3X3
-	tristate "HPT 343/363 PATA support (Experimental)"
+	tristate "HPT 343/363 PATA support"
 	depends on PCI
 	help
 	  This option enables support for the HPT 343/363
@@ -312,6 +317,14 @@
 
 	  If unsure, say N.
 
+config PATA_HPT3X3_DMA
+	bool "HPT 343/363 DMA support (Experimental)"
+	depends on PATA_HPT3X3
+	help
+	  This option enables DMA support for the HPT343/363
+	  controllers. Enable with care as there are still some
+	  problems with DMA on this chipset.
+
 config PATA_ISAPNP
 	tristate "ISA Plug and Play PATA support (Experimental)"
 	depends on EXPERIMENTAL && ISAPNP
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index e00e1b9..11e4eb9 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"ahci"
-#define DRV_VERSION	"2.1"
+#define DRV_VERSION	"2.3"
 
 
 enum {
@@ -54,7 +54,7 @@
 	AHCI_MAX_PORTS		= 32,
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
-	AHCI_USE_CLUSTERING	= 0,
+	AHCI_USE_CLUSTERING	= 1,
 	AHCI_MAX_CMDS		= 32,
 	AHCI_CMD_SZ		= 32,
 	AHCI_CMD_SLOT_SZ	= AHCI_MAX_CMDS * AHCI_CMD_SZ,
@@ -81,6 +81,7 @@
 	board_ahci_vt8251	= 2,
 	board_ahci_ign_iferr	= 3,
 	board_ahci_sb600	= 4,
+	board_ahci_mv		= 5,
 
 	/* global controller registers */
 	HOST_CAP		= 0x00, /* host capabilities */
@@ -170,6 +171,9 @@
 	AHCI_FLAG_IGN_IRQ_IF_ERR	= (1 << 25), /* ignore IRQ_IF_ERR */
 	AHCI_FLAG_HONOR_PI		= (1 << 26), /* honor PORTS_IMPL */
 	AHCI_FLAG_IGN_SERR_INTERNAL	= (1 << 27), /* ignore SERR_INTERNAL */
+	AHCI_FLAG_32BIT_ONLY		= (1 << 28), /* force 32bit */
+	AHCI_FLAG_MV_PATA		= (1 << 29), /* PATA port */
+	AHCI_FLAG_NO_MSI		= (1 << 30), /* no PCI MSI */
 
 	AHCI_FLAG_COMMON		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
@@ -227,9 +231,12 @@
 static void ahci_error_handler(struct ata_port *ap);
 static void ahci_vt8251_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+static int ahci_port_resume(struct ata_port *ap);
+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+			       u32 opts);
 #ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
-static int ahci_port_resume(struct ata_port *ap);
 static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int ahci_pci_device_resume(struct pci_dev *pdev);
 #endif
@@ -326,14 +333,14 @@
 	{
 		.flags		= AHCI_FLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 	/* board_ahci_pi */
 	{
 		.flags		= AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 	/* board_ahci_vt8251 */
@@ -341,22 +348,35 @@
 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_HRST_TO_RESUME |
 				  AHCI_FLAG_NO_NCQ,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_vt8251_ops,
 	},
 	/* board_ahci_ign_iferr */
 	{
 		.flags		= AHCI_FLAG_COMMON | AHCI_FLAG_IGN_IRQ_IF_ERR,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 	/* board_ahci_sb600 */
 	{
 		.flags		= AHCI_FLAG_COMMON |
-				  AHCI_FLAG_IGN_SERR_INTERNAL,
+				  AHCI_FLAG_IGN_SERR_INTERNAL |
+				  AHCI_FLAG_32BIT_ONLY,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
+	/* board_ahci_mv */
+	{
+		.sht		= &ahci_sht,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+				  ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI |
+				  AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI |
+				  AHCI_FLAG_MV_PATA,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 };
@@ -424,12 +444,39 @@
 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci },		/* MCP67 */
 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci },		/* MCP67 */
 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci },		/* MCP67 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci },		/* MCP73 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci },		/* MCP77 */
+	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci },		/* MCP77 */
 
 	/* SiS */
 	{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
 	{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */
 	{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
 
+	/* Marvell */
+	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
+
 	/* Generic, PCI class code for AHCI */
 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -455,11 +502,17 @@
 	return (cap & 0x1f) + 1;
 }
 
+static inline void __iomem *__ahci_port_base(struct ata_host *host,
+					     unsigned int port_no)
+{
+	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+
+	return mmio + 0x100 + (port_no * 0x80);
+}
+
 static inline void __iomem *ahci_port_base(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-
-	return mmio + 0x100 + (ap->port_no * 0x80);
+	return __ahci_port_base(ap->host, ap->port_no);
 }
 
 /**
@@ -492,9 +545,16 @@
 	hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
 	hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
 
+	/* some chips lie about 64bit support */
+	if ((cap & HOST_CAP_64) && (pi->flags & AHCI_FLAG_32BIT_ONLY)) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "controller can't do 64bit DMA, forcing 32bit\n");
+		cap &= ~HOST_CAP_64;
+	}
+
 	/* fixup zero port_map */
 	if (!port_map) {
-		port_map = (1 << ahci_nr_ports(hpriv->cap)) - 1;
+		port_map = (1 << ahci_nr_ports(cap)) - 1;
 		dev_printk(KERN_WARNING, &pdev->dev,
 			   "PORTS_IMPL is zero, forcing 0x%x\n", port_map);
 
@@ -502,6 +562,20 @@
 		hpriv->saved_port_map = port_map;
 	}
 
+	/*
+	 * Temporary Marvell 6145 hack: PATA port presence
+	 * is asserted through the standard AHCI port
+	 * presence register, as bit 4 (counting from 0)
+	 */
+	if (pi->flags & AHCI_FLAG_MV_PATA) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "MV_AHCI HACK: port_map %x -> %x\n",
+			   hpriv->port_map,
+			   hpriv->port_map & 0xf);
+
+		port_map &= 0xf;
+	}
+
 	/* cross check port_map and cap.n_ports */
 	if (pi->flags & AHCI_FLAG_HONOR_PI) {
 		u32 tmp_port_map = port_map;
@@ -707,7 +781,7 @@
 }
 #endif
 
-static void ahci_init_port(struct ata_port *ap)
+static void ahci_start_port(struct ata_port *ap)
 {
 	/* enable FIS reception */
 	ahci_start_fis_rx(ap);
@@ -781,39 +855,62 @@
 	return 0;
 }
 
+static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
+			   int port_no, void __iomem *mmio,
+			   void __iomem *port_mmio)
+{
+	const char *emsg = NULL;
+	int rc;
+	u32 tmp;
+
+	/* make sure port is not active */
+	rc = ahci_deinit_port(ap, &emsg);
+	if (rc)
+		dev_printk(KERN_WARNING, &pdev->dev,
+			   "%s (%d)\n", emsg, rc);
+
+	/* clear SError */
+	tmp = readl(port_mmio + PORT_SCR_ERR);
+	VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
+	writel(tmp, port_mmio + PORT_SCR_ERR);
+
+	/* clear port IRQ */
+	tmp = readl(port_mmio + PORT_IRQ_STAT);
+	VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
+	if (tmp)
+		writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+	writel(1 << port_no, mmio + HOST_IRQ_STAT);
+}
+
 static void ahci_init_controller(struct ata_host *host)
 {
 	struct pci_dev *pdev = to_pci_dev(host->dev);
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-	int i, rc;
+	int i;
+	void __iomem *port_mmio;
 	u32 tmp;
 
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-		void __iomem *port_mmio = ahci_port_base(ap);
-		const char *emsg = NULL;
+	if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) {
+		port_mmio = __ahci_port_base(host, 4);
 
-		if (ata_port_is_dummy(ap))
-			continue;
-
-		/* make sure port is not active */
-		rc = ahci_deinit_port(ap, &emsg);
-		if (rc)
-			dev_printk(KERN_WARNING, &pdev->dev,
-				   "%s (%d)\n", emsg, rc);
-
-		/* clear SError */
-		tmp = readl(port_mmio + PORT_SCR_ERR);
-		VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
-		writel(tmp, port_mmio + PORT_SCR_ERR);
+		writel(0, port_mmio + PORT_IRQ_MASK);
 
 		/* clear port IRQ */
 		tmp = readl(port_mmio + PORT_IRQ_STAT);
 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
 		if (tmp)
 			writel(tmp, port_mmio + PORT_IRQ_STAT);
+	}
 
-		writel(1 << i, mmio + HOST_IRQ_STAT);
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		port_mmio = ahci_port_base(ap);
+		if (ata_port_is_dummy(ap))
+			continue;
+
+		ahci_port_init(pdev, ap, i, mmio, port_mmio);
 	}
 
 	tmp = readl(mmio + HOST_CTL);
@@ -1199,7 +1296,7 @@
 		ata_port_abort(ap);
 }
 
-static void ahci_host_intr(struct ata_port *ap)
+static void ahci_port_intr(struct ata_port *ap)
 {
 	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
 	struct ata_eh_info *ehi = &ap->eh_info;
@@ -1325,7 +1422,7 @@
 
 		ap = host->ports[i];
 		if (ap) {
-			ahci_host_intr(ap);
+			ahci_port_intr(ap);
 			VPRINTK("port %u\n", i);
 		} else {
 			VPRINTK("port %u (no irq)\n", i);
@@ -1433,7 +1530,7 @@
 		ahci_power_down(ap);
 	else {
 		ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
-		ahci_init_port(ap);
+		ahci_start_port(ap);
 	}
 
 	return rc;
@@ -1442,7 +1539,7 @@
 static int ahci_port_resume(struct ata_port *ap)
 {
 	ahci_power_up(ap);
-	ahci_init_port(ap);
+	ahci_start_port(ap);
 
 	return 0;
 }
@@ -1540,13 +1637,8 @@
 
 	ap->private_data = pp;
 
-	/* power up port */
-	ahci_power_up(ap);
-
-	/* initialize port */
-	ahci_init_port(ap);
-
-	return 0;
+	/* engage engines, captain */
+	return ahci_port_resume(ap);
 }
 
 static void ahci_port_stop(struct ata_port *ap)
@@ -1691,7 +1783,7 @@
 	if (rc)
 		return rc;
 
-	if (pci_enable_msi(pdev))
+	if ((pi.flags & AHCI_FLAG_NO_MSI) || pci_enable_msi(pdev))
 		pci_intx(pdev, 1);
 
 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
@@ -1712,14 +1804,18 @@
 	host->private_data = hpriv;
 
 	for (i = 0; i < host->n_ports; i++) {
-		if (hpriv->port_map & (1 << i)) {
-			struct ata_port *ap = host->ports[i];
-			void __iomem *port_mmio = ahci_port_base(ap);
+		struct ata_port *ap = host->ports[i];
+		void __iomem *port_mmio = ahci_port_base(ap);
 
+		/* standard SATA port setup */
+		if (hpriv->port_map & (1 << i)) {
 			ap->ioaddr.cmd_addr = port_mmio;
 			ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
-		} else
-			host->ports[i]->ops = &ata_dummy_port_ops;
+		}
+
+		/* disabled/not-implemented port */
+		else
+			ap->ops = &ata_dummy_port_ops;
 	}
 
 	/* initialize adapter */
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index c3d7532..430fcf4 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -26,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "ata_generic"
-#define DRV_VERSION "0.2.11"
+#define DRV_VERSION "0.2.12"
 
 /*
  *	A generic parallel ATA driver using libata
@@ -50,7 +50,7 @@
 
 	/* Bits 5 and 6 indicate if DMA is active on master/slave */
 	if (ap->ioaddr.bmdma_addr)
-		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
@@ -143,10 +143,10 @@
 	u16 command;
 	static const struct ata_port_info info = {
 		.sht = &generic_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &generic_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 13b6b1d..d9fa329 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -155,7 +155,6 @@
 static int piix_init_one (struct pci_dev *pdev,
 				    const struct pci_device_id *ent);
 static void piix_pata_error_handler(struct ata_port *ap);
-static void piix_sata_error_handler(struct ata_port *ap);
 static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
 static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
 static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev);
@@ -201,6 +200,8 @@
 	/* ICH7/7-R (i945, i975) UDMA 100*/
 	{ 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 },
 	{ 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+	/* ICH8 Mobile PATA Controller */
+	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
 
 	/* NOTE: The following PCI ids must be kept in sync with the
 	 * list in drivers/pci/quirks.c.
@@ -364,7 +365,7 @@
 
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
-	.error_handler		= piix_sata_error_handler,
+	.error_handler		= ata_bmdma_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 
 	.irq_handler		= ata_interrupt,
@@ -413,7 +414,7 @@
 	 */
 	.map = {
 		/* PM   PS   SM   SS       MAP */
-		{  P0,  P2,  RV,  RV }, /* 00b */
+		{  P0,  P2,  NA,  NA }, /* 00b */
 		{ IDE, IDE,  P1,  P3 }, /* 01b */
 		{  P0,  P2, IDE, IDE }, /* 10b */
 		{  RV,  RV,  RV,  RV },
@@ -496,7 +497,7 @@
 		.flags		= PIIX_SATA_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -506,7 +507,7 @@
 		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -517,7 +518,7 @@
 				  PIIX_FLAG_AHCI,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -528,7 +529,7 @@
 				  PIIX_FLAG_AHCI,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -539,7 +540,7 @@
 				  PIIX_FLAG_AHCI,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -579,6 +580,7 @@
 	{ 0x27DF, 0x0005, 0x0280 },	/* ICH7 on Acer 5602WLMi */
 	{ 0x27DF, 0x1025, 0x0110 },	/* ICH7 on Acer 3682WLMi */
 	{ 0x27DF, 0x1043, 0x1267 },	/* ICH7 on Asus W5F */
+	{ 0x24CA, 0x1025, 0x0061 },	/* ICH4 on ACER Aspire 2023WLMi */
 	/* end marker */
 	{ 0, }
 };
@@ -641,12 +643,6 @@
 			   ata_std_postreset);
 }
 
-static void piix_sata_error_handler(struct ata_port *ap)
-{
-	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
-			   ata_std_postreset);
-}
-
 /**
  *	piix_set_piomode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
@@ -691,8 +687,14 @@
 	if (adev->class == ATA_DEV_ATA)
 		control |= 4;	/* PPE enable */
 
+	/* PIO configuration clears DTE unconditionally.  It will be
+	 * programmed in set_dmamode which is guaranteed to be called
+	 * after set_piomode if any DMA mode is available.
+	 */
 	pci_read_config_word(dev, master_port, &master_data);
 	if (is_slave) {
+		/* clear TIME1|IE1|PPE1|DTE1 */
+		master_data &= 0xff0f;
 		/* Enable SITRE (seperate slave timing register) */
 		master_data |= 0x4000;
 		/* enable PPE1, IE1 and TIME1 as needed */
@@ -700,12 +702,14 @@
 		pci_read_config_byte(dev, slave_port, &slave_data);
 		slave_data &= (ap->port_no ? 0x0f : 0xf0);
 		/* Load the timing nibble for this slave */
-		slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
+		slave_data |= ((timings[pio][0] << 2) | timings[pio][1])
+						<< (ap->port_no ? 4 : 0);
 	} else {
-		/* Master keeps the bits in a different format */
-		master_data &= 0xccf8;
+		/* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */
+		master_data &= 0xccf0;
 		/* Enable PPE, IE and TIME as appropriate */
 		master_data |= control;
+		/* load ISP and RCT */
 		master_data |=
 			(timings[pio][0] << 12) |
 			(timings[pio][1] << 8);
@@ -822,7 +826,7 @@
 			master_data &= 0xFF4F;  /* Mask out IORDY|TIME1|DMAONLY */
 			master_data |= control << 4;
 			pci_read_config_byte(dev, 0x44, &slave_data);
-			slave_data &= (0x0F + 0xE1 * ap->port_no);
+			slave_data &= (ap->port_no ? 0x0f : 0xf0);
 			/* Load the matching timing */
 			slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
 			pci_write_config_byte(dev, 0x44, slave_data);
@@ -834,8 +838,11 @@
 				(timings[pio][0] << 12) |
 				(timings[pio][1] << 8);
 		}
-		udma_enable &= ~(1 << devid);
-		pci_write_config_word(dev, master_port, master_data);
+
+		if (ap->udma_mask) {
+			udma_enable &= ~(1 << devid);
+			pci_write_config_word(dev, master_port, master_data);
+		}
 	}
 	/* Don't scribble on 0x48 if the controller does not support UDMA */
 	if (ap->udma_mask)
@@ -921,20 +928,18 @@
 {
 	struct pci_dev *pdev = NULL;
 	u16 cfg;
-	u8 rev;
 	int no_piix_dma = 0;
 
 	while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
 	{
 		/* Look for 450NX PXB. Check for problem configurations
 		   A PCI quirk checks bit 6 already */
-		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
 		pci_read_config_word(pdev, 0x41, &cfg);
 		/* Only on the original revision: IDE DMA can hang */
-		if (rev == 0x00)
+		if (pdev->revision == 0x00)
 			no_piix_dma = 1;
 		/* On all revisions below 5 PXB bus lock must be disabled for IDE */
-		else if (cfg & (1<<14) && rev < 5)
+		else if (cfg & (1<<14) && pdev->revision < 5)
 			no_piix_dma = 2;
 	}
 	if (no_piix_dma)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 0223673..c059f78 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -24,15 +24,13 @@
 #include <acpi/acmacros.h>
 #include <acpi/actypes.h>
 
-#define SATA_ROOT_PORT(x)	(((x) >> 16) & 0xffff)
-#define SATA_PORT_NUMBER(x)	((x) & 0xffff)	/* or NO_PORT_MULT */
 #define NO_PORT_MULT		0xffff
-#define SATA_ADR_RSVD		0xffffffff
+#define SATA_ADR(root,pmp)	(((root) << 16) | (pmp))
 
 #define REGS_PER_GTF		7
-struct taskfile_array {
-	u8	tfa[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
-};
+struct ata_acpi_gtf {
+	u8	tf[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
+} __packed;
 
 /*
  *	Helper - belongs in the PCI layer somewhere eventually
@@ -42,237 +40,173 @@
 	return (dev->bus == &pci_bus_type);
 }
 
-/**
- * sata_get_dev_handle - finds acpi_handle and PCI device.function
- * @dev: device to locate
- * @handle: returned acpi_handle for @dev
- * @pcidevfn: return PCI device.func for @dev
- *
- * This function is somewhat SATA-specific.  Or at least the
- * PATA & SATA versions of this function are different,
- * so it's not entirely generic code.
- *
- * Returns 0 on success, <0 on error.
- */
-static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
-					acpi_integer *pcidevfn)
+static void ata_acpi_associate_sata_port(struct ata_port *ap)
 {
-	struct pci_dev	*pci_dev;
-	acpi_integer	addr;
+	acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
 
-	if (!is_pci_dev(dev))
-		return -ENODEV;
+	ap->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr);
+}
 
-	pci_dev = to_pci_dev(dev);	/* NOTE: PCI-specific */
-	/* Please refer to the ACPI spec for the syntax of _ADR. */
-	addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
-	*pcidevfn = addr;
-	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
-	if (!*handle)
-		return -ENODEV;
+static void ata_acpi_associate_ide_port(struct ata_port *ap)
+{
+	int max_devices, i;
+
+	ap->acpi_handle = acpi_get_child(ap->host->acpi_handle, ap->port_no);
+	if (!ap->acpi_handle)
+		return;
+
+	max_devices = 1;
+	if (ap->flags & ATA_FLAG_SLAVE_POSS)
+		max_devices++;
+
+	for (i = 0; i < max_devices; i++) {
+		struct ata_device *dev = &ap->device[i];
+
+		dev->acpi_handle = acpi_get_child(ap->acpi_handle, i);
+	}
+}
+
+/**
+ * ata_acpi_associate - associate ATA host with ACPI objects
+ * @host: target ATA host
+ *
+ * Look up ACPI objects associated with @host and initialize
+ * acpi_handle fields of @host, its ports and devices accordingly.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+void ata_acpi_associate(struct ata_host *host)
+{
+	int i;
+
+	if (!is_pci_dev(host->dev) || libata_noacpi)
+		return;
+
+	host->acpi_handle = DEVICE_ACPI_HANDLE(host->dev);
+	if (!host->acpi_handle)
+		return;
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		if (host->ports[0]->flags & ATA_FLAG_ACPI_SATA)
+			ata_acpi_associate_sata_port(ap);
+		else
+			ata_acpi_associate_ide_port(ap);
+	}
+}
+
+/**
+ * ata_acpi_gtm - execute _GTM
+ * @ap: target ATA port
+ * @gtm: out parameter for _GTM result
+ *
+ * Evaluate _GTM and store the result in @gtm.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
+ */
+static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
+{
+	struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
+	union acpi_object *out_obj;
+	acpi_status status;
+	int rc = 0;
+
+	status = acpi_evaluate_object(ap->acpi_handle, "_GTM", NULL, &output);
+
+	rc = -ENOENT;
+	if (status == AE_NOT_FOUND)
+		goto out_free;
+
+	rc = -EINVAL;
+	if (ACPI_FAILURE(status)) {
+		ata_port_printk(ap, KERN_ERR,
+				"ACPI get timing mode failed (AE 0x%x)\n",
+				status);
+		goto out_free;
+	}
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		ata_port_printk(ap, KERN_WARNING,
+				"_GTM returned unexpected object type 0x%x\n",
+				out_obj->type);
+
+		goto out_free;
+	}
+
+	if (out_obj->buffer.length != sizeof(struct ata_acpi_gtm)) {
+		ata_port_printk(ap, KERN_ERR,
+				"_GTM returned invalid length %d\n",
+				out_obj->buffer.length);
+		goto out_free;
+	}
+
+	memcpy(gtm, out_obj->buffer.pointer, sizeof(struct ata_acpi_gtm));
+	rc = 0;
+ out_free:
+	kfree(output.pointer);
+	return rc;
+}
+
+/**
+ * ata_acpi_stm - execute _STM
+ * @ap: target ATA port
+ * @stm: timing parameter to _STM
+ *
+ * Evaluate _STM with timing parameter @stm.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure.
+ */
+static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
+{
+	acpi_status status;
+	struct acpi_object_list         input;
+	union acpi_object               in_params[3];
+
+	in_params[0].type = ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length = sizeof(struct ata_acpi_gtm);
+	in_params[0].buffer.pointer = (u8 *)stm;
+	/* Buffers for id may need byteswapping ? */
+	in_params[1].type = ACPI_TYPE_BUFFER;
+	in_params[1].buffer.length = 512;
+	in_params[1].buffer.pointer = (u8 *)ap->device[0].id;
+	in_params[2].type = ACPI_TYPE_BUFFER;
+	in_params[2].buffer.length = 512;
+	in_params[2].buffer.pointer = (u8 *)ap->device[1].id;
+
+	input.count = 3;
+	input.pointer = in_params;
+
+	status = acpi_evaluate_object(ap->acpi_handle, "_STM", &input, NULL);
+
+	if (status == AE_NOT_FOUND)
+		return -ENOENT;
+	if (ACPI_FAILURE(status)) {
+		ata_port_printk(ap, KERN_ERR,
+			"ACPI set timing mode failed (status=0x%x)\n", status);
+		return -EINVAL;
+	}
 	return 0;
 }
 
 /**
- * pata_get_dev_handle - finds acpi_handle and PCI device.function
- * @dev: device to locate
- * @handle: returned acpi_handle for @dev
- * @pcidevfn: return PCI device.func for @dev
- *
- * The PATA and SATA versions of this function are different.
- *
- * Returns 0 on success, <0 on error.
- */
-static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
-				acpi_integer *pcidevfn)
-{
-	unsigned int bus, devnum, func;
-	acpi_integer addr;
-	acpi_handle dev_handle, parent_handle;
-	struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
-					.pointer = NULL};
-	acpi_status status;
-	struct acpi_device_info	*dinfo = NULL;
-	int ret = -ENODEV;
-	struct pci_dev *pdev;
-
-	if (!is_pci_dev(dev))
-		return -ENODEV;
-
-	pdev = to_pci_dev(dev);
-
-	bus = pdev->bus->number;
-	devnum = PCI_SLOT(pdev->devfn);
-	func = PCI_FUNC(pdev->devfn);
-
-	dev_handle = DEVICE_ACPI_HANDLE(dev);
-	parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
-
-	status = acpi_get_object_info(parent_handle, &buffer);
-	if (ACPI_FAILURE(status))
-		goto err;
-
-	dinfo = buffer.pointer;
-	if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
-	    dinfo->address == bus) {
-		/* ACPI spec for _ADR for PCI bus: */
-		addr = (acpi_integer)(devnum << 16 | func);
-		*pcidevfn = addr;
-		*handle = dev_handle;
-	} else {
-		goto err;
-	}
-
-	if (!*handle)
-		goto err;
-	ret = 0;
-err:
-	kfree(dinfo);
-	return ret;
-}
-
-struct walk_info {		/* can be trimmed some */
-	struct device	*dev;
-	struct acpi_device *adev;
-	acpi_handle	handle;
-	acpi_integer	pcidevfn;
-	unsigned int	drivenum;
-	acpi_handle	obj_handle;
-	struct ata_port *ataport;
-	struct ata_device *atadev;
-	u32		sata_adr;
-	int		status;
-	char		basepath[ACPI_PATHNAME_MAX];
-	int		basepath_len;
-};
-
-static acpi_status get_devices(acpi_handle handle,
-				u32 level, void *context, void **return_value)
-{
-	acpi_status		status;
-	struct walk_info	*winfo = context;
-	struct acpi_buffer	namebuf = {ACPI_ALLOCATE_BUFFER, NULL};
-	char			*pathname;
-	struct acpi_buffer	buffer;
-	struct acpi_device_info	*dinfo;
-
-	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf);
-	if (status)
-		goto ret;
-	pathname = namebuf.pointer;
-
-	buffer.length = ACPI_ALLOCATE_BUFFER;
-	buffer.pointer = NULL;
-	status = acpi_get_object_info(handle, &buffer);
-	if (ACPI_FAILURE(status))
-		goto out2;
-
-	dinfo = buffer.pointer;
-
-	/* find full device path name for pcidevfn */
-	if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
-	    dinfo->address == winfo->pcidevfn) {
-		if (ata_msg_probe(winfo->ataport))
-			ata_dev_printk(winfo->atadev, KERN_DEBUG,
-				":%s: matches pcidevfn (0x%llx)\n",
-				pathname, winfo->pcidevfn);
-		strlcpy(winfo->basepath, pathname,
-			sizeof(winfo->basepath));
-		winfo->basepath_len = strlen(pathname);
-		goto out;
-	}
-
-	/* if basepath is not yet known, ignore this object */
-	if (!winfo->basepath_len)
-		goto out;
-
-	/* if this object is in scope of basepath, maybe use it */
-	if (strncmp(pathname, winfo->basepath,
-	    winfo->basepath_len) == 0) {
-		if (!(dinfo->valid & ACPI_VALID_ADR))
-			goto out;
-		if (ata_msg_probe(winfo->ataport))
-			ata_dev_printk(winfo->atadev, KERN_DEBUG,
-				"GOT ONE: (%s) root_port = 0x%llx,"
-				" port_num = 0x%llx\n", pathname,
-				SATA_ROOT_PORT(dinfo->address),
-				SATA_PORT_NUMBER(dinfo->address));
-		/* heuristics: */
-		if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
-			if (ata_msg_probe(winfo->ataport))
-				ata_dev_printk(winfo->atadev,
-					KERN_DEBUG, "warning: don't"
-					" know how to handle SATA port"
-					" multiplier\n");
-		if (SATA_ROOT_PORT(dinfo->address) ==
-			winfo->ataport->port_no &&
-		    SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
-			if (ata_msg_probe(winfo->ataport))
-				ata_dev_printk(winfo->atadev,
-					KERN_DEBUG,
-					"THIS ^^^^^ is the requested"
-					" SATA drive (handle = 0x%p)\n",
-					handle);
-			winfo->sata_adr = dinfo->address;
-			winfo->obj_handle = handle;
-		}
-	}
-out:
-	kfree(dinfo);
-out2:
-	kfree(pathname);
-
-ret:
-	return status;
-}
-
-/* Get the SATA drive _ADR object. */
-static int get_sata_adr(struct device *dev, acpi_handle handle,
-			acpi_integer pcidevfn, unsigned int drive,
-			struct ata_port *ap,
-			struct ata_device *atadev, u32 *dev_adr)
-{
-	acpi_status	status;
-	struct walk_info *winfo;
-	int		err = -ENOMEM;
-
-	winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
-	if (!winfo)
-		goto out;
-
-	winfo->dev = dev;
-	winfo->atadev = atadev;
-	winfo->ataport = ap;
-	if (acpi_bus_get_device(handle, &winfo->adev) < 0)
-		if (ata_msg_probe(ap))
-			ata_dev_printk(winfo->atadev, KERN_DEBUG,
-				"acpi_bus_get_device failed\n");
-	winfo->handle = handle;
-	winfo->pcidevfn = pcidevfn;
-	winfo->drivenum = drive;
-
-	status = acpi_get_devices(NULL, get_devices, winfo, NULL);
-	if (ACPI_FAILURE(status)) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(winfo->atadev, KERN_DEBUG,
-				"%s: acpi_get_devices failed\n",
-				__FUNCTION__);
-		err = -ENODEV;
-	} else {
-		*dev_adr = winfo->sata_adr;
-		atadev->obj_handle = winfo->obj_handle;
-		err = 0;
-	}
-	kfree(winfo);
-out:
-	return err;
-}
-
-/**
- * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * ata_dev_get_GTF - get the drive bootup default taskfile settings
  * @dev: target ATA device
- * @gtf_length: number of bytes of _GTF data returned at @gtf_address
- * @gtf_address: buffer containing _GTF taskfile arrays
+ * @gtf: output parameter for buffer containing _GTF taskfile arrays
+ * @ptr_to_free: pointer which should be freed
  *
  * This applies to both PATA and SATA drives.
  *
@@ -282,121 +216,41 @@
  * The <variable number> is not known in advance, so have ACPI-CA
  * allocate the buffer as needed and return it, then free it later.
  *
- * The returned @gtf_length and @gtf_address are only valid if the
- * function return value is 0.
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't
+ * contain valid data.  -errno on other errors.
  */
-static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
-			    unsigned long *gtf_address, unsigned long *obj_loc)
+static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
+			   void **ptr_to_free)
 {
 	struct ata_port *ap = dev->ap;
 	acpi_status status;
-	acpi_handle dev_handle = NULL;
-	acpi_handle chan_handle, drive_handle;
-	acpi_integer pcidevfn = 0;
-	u32 dev_adr;
 	struct acpi_buffer output;
 	union acpi_object *out_obj;
-	struct device *gdev = ap->host->dev;
-	int err = -ENODEV;
+	int rc = 0;
 
-	*gtf_length = 0;
-	*gtf_address = 0UL;
-	*obj_loc = 0UL;
-
-	if (libata_noacpi)
-		return 0;
+	/* set up output buffer */
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
 
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
 			       __FUNCTION__, ap->port_no);
 
-	if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED)) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG, "%s: ERR: "
-				"ata_dev_present: %d, PORT_DISABLED: %lu\n",
-				__FUNCTION__, ata_dev_enabled(dev),
-				ap->flags & ATA_FLAG_DISABLED);
-		goto out;
-	}
-
-	/* Don't continue if device has no _ADR method.
-	 * _GTF is intended for known motherboard devices. */
-	if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
-		err = pata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
-		if (err < 0) {
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: pata_get_dev_handle failed (%d)\n",
-					__FUNCTION__, err);
-			goto out;
-		}
-	} else {
-		err = sata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
-		if (err < 0) {
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: sata_get_dev_handle failed (%d\n",
-					__FUNCTION__, err);
-			goto out;
-		}
-	}
-
-	/* Get this drive's _ADR info. if not already known. */
-	if (!dev->obj_handle) {
-		if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
-			/* get child objects of dev_handle == channel objects,
-	 		 * + _their_ children == drive objects */
-			/* channel is ap->port_no */
-			chan_handle = acpi_get_child(dev_handle,
-						ap->port_no);
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: chan adr=%d: chan_handle=0x%p\n",
-					__FUNCTION__, ap->port_no,
-					chan_handle);
-			if (!chan_handle) {
-				err = -ENODEV;
-				goto out;
-			}
-			/* TBD: could also check ACPI object VALID bits */
-			drive_handle = acpi_get_child(chan_handle, dev->devno);
-			if (!drive_handle) {
-				err = -ENODEV;
-				goto out;
-			}
-			dev_adr = dev->devno;
-			dev->obj_handle = drive_handle;
-		} else {	/* for SATA mode */
-			dev_adr = SATA_ADR_RSVD;
-			err = get_sata_adr(gdev, dev_handle, pcidevfn, 0,
-					ap, dev, &dev_adr);
-		}
-		if (err < 0 || dev_adr == SATA_ADR_RSVD ||
-		    !dev->obj_handle) {
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: get_sata/pata_adr failed: "
-					"err=%d, dev_adr=%u, obj_handle=0x%p\n",
-					__FUNCTION__, err, dev_adr,
-					dev->obj_handle);
-			goto out;
-		}
-	}
-
-	/* Setting up output buffer */
-	output.length = ACPI_ALLOCATE_BUFFER;
-	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
-
 	/* _GTF has no input parameters */
-	err = -EIO;
-	status = acpi_evaluate_object(dev->obj_handle, "_GTF",
-					NULL, &output);
+	status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
+
 	if (ACPI_FAILURE(status)) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				"%s: Run _GTF error: status = 0x%x\n",
-				__FUNCTION__, status);
-		goto out;
+		if (status != AE_NOT_FOUND) {
+			ata_dev_printk(dev, KERN_WARNING,
+				       "_GTF evaluation failed (AE 0x%x)\n",
+				       status);
+			rc = -EIO;
+		}
+		goto out_free;
 	}
 
 	if (!output.length || !output.pointer) {
@@ -406,43 +260,39 @@
 				__FUNCTION__,
 				(unsigned long long)output.length,
 				output.pointer);
-		kfree(output.pointer);
-		goto out;
+		goto out_free;
 	}
 
 	out_obj = output.pointer;
 	if (out_obj->type != ACPI_TYPE_BUFFER) {
-		kfree(output.pointer);
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
-				"error: expected object type of "
-				" ACPI_TYPE_BUFFER, got 0x%x\n",
-				__FUNCTION__, out_obj->type);
-		err = -ENOENT;
-		goto out;
+		ata_dev_printk(dev, KERN_WARNING,
+			       "_GTF unexpected object type 0x%x\n",
+			       out_obj->type);
+		rc = -EINVAL;
+		goto out_free;
 	}
 
-	if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
-	    out_obj->buffer.length % REGS_PER_GTF) {
-		if (ata_msg_drv(ap))
-			ata_dev_printk(dev, KERN_ERR,
-				"%s: unexpected GTF length (%d) or addr (0x%p)\n",
-				__FUNCTION__, out_obj->buffer.length,
-				out_obj->buffer.pointer);
-		err = -ENOENT;
-		goto out;
+	if (out_obj->buffer.length % REGS_PER_GTF) {
+		ata_dev_printk(dev, KERN_WARNING,
+			       "unexpected _GTF length (%d)\n",
+			       out_obj->buffer.length);
+		rc = -EINVAL;
+		goto out_free;
 	}
 
-	*gtf_length = out_obj->buffer.length;
-	*gtf_address = (unsigned long)out_obj->buffer.pointer;
-	*obj_loc = (unsigned long)out_obj;
+	*ptr_to_free = out_obj;
+	*gtf = (void *)out_obj->buffer.pointer;
+	rc = out_obj->buffer.length / REGS_PER_GTF;
+
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: returning "
-			"gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
-			__FUNCTION__, *gtf_length, *gtf_address, *obj_loc);
-	err = 0;
-out:
-	return err;
+			"gtf=%p, gtf_count=%d, ptr_to_free=%p\n",
+			__FUNCTION__, *gtf, rc, *ptr_to_free);
+	return rc;
+
+ out_free:
+	kfree(output.pointer);
+	return rc;
 }
 
 /**
@@ -461,154 +311,99 @@
  * function also waits for idle after writing control and before
  * writing the remaining registers.
  *
- * LOCKING: TBD:
- * Inherited from caller.
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
-static void taskfile_load_raw(struct ata_device *dev,
-			      const struct taskfile_array *gtf)
+static int taskfile_load_raw(struct ata_device *dev,
+			      const struct ata_acpi_gtf *gtf)
 {
 	struct ata_port *ap = dev->ap;
-	struct ata_taskfile tf;
-	unsigned int err;
+	struct ata_taskfile tf, rtf;
+	unsigned int err_mask;
 
-	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: "
-			"%02x %02x %02x %02x %02x %02x %02x\n",
-			__FUNCTION__,
-			gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
-			gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
-
-	if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0)
-	    && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0)
-	    && (gtf->tfa[6] == 0))
-		return;
+	if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0)
+	    && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0)
+	    && (gtf->tf[6] == 0))
+		return 0;
 
 	ata_tf_init(dev, &tf);
 
 	/* convert gtf to tf */
 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
 	tf.protocol = ATA_PROT_NODATA;
-	tf.feature = gtf->tfa[0];	/* 0x1f1 */
-	tf.nsect   = gtf->tfa[1];	/* 0x1f2 */
-	tf.lbal    = gtf->tfa[2];	/* 0x1f3 */
-	tf.lbam    = gtf->tfa[3];	/* 0x1f4 */
-	tf.lbah    = gtf->tfa[4];	/* 0x1f5 */
-	tf.device  = gtf->tfa[5];	/* 0x1f6 */
-	tf.command = gtf->tfa[6];	/* 0x1f7 */
-
-	err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
-	if (err && ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_ERR,
-			"%s: ata_exec_internal failed: %u\n",
-			__FUNCTION__, err);
-}
-
-/**
- * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
- * @dev: target ATA device
- * @gtf_length: total number of bytes of _GTF taskfiles
- * @gtf_address: location of _GTF taskfile arrays
- *
- * This applies to both PATA and SATA drives.
- *
- * Write {gtf_address, length gtf_length} in groups of
- * REGS_PER_GTF bytes.
- */
-static int do_drive_set_taskfiles(struct ata_device *dev,
-				  unsigned int gtf_length,
-				  unsigned long gtf_address)
-{
-	struct ata_port *ap = dev->ap;
-	int err = -ENODEV;
-	int gtf_count = gtf_length / REGS_PER_GTF;
-	int ix;
-	struct taskfile_array	*gtf;
+	tf.feature = gtf->tf[0];	/* 0x1f1 */
+	tf.nsect   = gtf->tf[1];	/* 0x1f2 */
+	tf.lbal    = gtf->tf[2];	/* 0x1f3 */
+	tf.lbam    = gtf->tf[3];	/* 0x1f4 */
+	tf.lbah    = gtf->tf[4];	/* 0x1f5 */
+	tf.device  = gtf->tf[5];	/* 0x1f6 */
+	tf.command = gtf->tf[6];	/* 0x1f7 */
 
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
-			       __FUNCTION__, ap->port_no);
+		ata_dev_printk(dev, KERN_DEBUG, "executing ACPI cmd "
+			       "%02x/%02x:%02x:%02x:%02x:%02x:%02x\n",
+			       tf.command, tf.feature, tf.nsect,
+			       tf.lbal, tf.lbam, tf.lbah, tf.device);
 
-	if (libata_noacpi || !(ap->flags & ATA_FLAG_ACPI_SATA))
-		return 0;
-
-	if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED))
-		goto out;
-	if (!gtf_count)		/* shouldn't be here */
-		goto out;
-
-	if (gtf_length % REGS_PER_GTF) {
-		if (ata_msg_drv(ap))
-			ata_dev_printk(dev, KERN_ERR,
-				"%s: unexpected GTF length (%d)\n",
-				__FUNCTION__, gtf_length);
-		goto out;
+	rtf = tf;
+	err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0);
+	if (err_mask) {
+		ata_dev_printk(dev, KERN_ERR,
+			"ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed "
+			"(Emask=0x%x Stat=0x%02x Err=0x%02x)\n",
+			tf.command, tf.feature, tf.nsect, tf.lbal, tf.lbam,
+			tf.lbah, tf.device, err_mask, rtf.command, rtf.feature);
+		return -EIO;
 	}
 
-	for (ix = 0; ix < gtf_count; ix++) {
-		gtf = (struct taskfile_array *)
-			(gtf_address + ix * REGS_PER_GTF);
-
-		/* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
-		taskfile_load_raw(dev, gtf);
-	}
-
-	err = 0;
-out:
-	return err;
+	return 0;
 }
 
 /**
  * ata_acpi_exec_tfs - get then write drive taskfile settings
- * @ap: the ata_port for the drive
+ * @dev: target ATA device
  *
- * This applies to both PATA and SATA drives.
+ * Evaluate _GTF and excute returned taskfiles.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Number of executed taskfiles on success, 0 if _GTF doesn't exist or
+ * doesn't contain valid data.  -errno on other errors.
  */
-int ata_acpi_exec_tfs(struct ata_port *ap)
+static int ata_acpi_exec_tfs(struct ata_device *dev)
 {
-	int ix;
-	int ret = 0;
-	unsigned int gtf_length;
-	unsigned long gtf_address;
-	unsigned long obj_loc;
+	struct ata_acpi_gtf *gtf = NULL;
+	void *ptr_to_free = NULL;
+	int gtf_count, i, rc;
 
-	if (libata_noacpi)
-		return 0;
-	/*
-	 * TBD - implement PATA support.  For now,
-	 * we should not run GTF on PATA devices since some
-	 * PATA require execution of GTM/STM before GTF.
-	 */
-	if (!(ap->flags & ATA_FLAG_ACPI_SATA))
-		return 0;
+	/* get taskfiles */
+	rc = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
+	if (rc < 0)
+		return rc;
+	gtf_count = rc;
 
-	for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
-		struct ata_device *dev = &ap->device[ix];
+	/* execute them */
+	for (i = 0, rc = 0; i < gtf_count; i++) {
+		int tmp;
 
-		if (!ata_dev_enabled(dev))
-			continue;
-
-		ret = do_drive_get_GTF(dev, &gtf_length, &gtf_address,
-				       &obj_loc);
-		if (ret < 0) {
-			if (ata_msg_probe(ap))
-				ata_port_printk(ap, KERN_DEBUG,
-					"%s: get_GTF error (%d)\n",
-					__FUNCTION__, ret);
-			break;
-		}
-
-		ret = do_drive_set_taskfiles(dev, gtf_length, gtf_address);
-		kfree((void *)obj_loc);
-		if (ret < 0) {
-			if (ata_msg_probe(ap))
-				ata_port_printk(ap, KERN_DEBUG,
-					"%s: set_taskfiles error (%d)\n",
-					__FUNCTION__, ret);
-			break;
-		}
+		/* ACPI errors are eventually ignored.  Run till the
+		 * end even after errors.
+		 */
+		tmp = taskfile_load_raw(dev, gtf++);
+		if (!rc)
+			rc = tmp;
 	}
 
-	return ret;
+	kfree(ptr_to_free);
+
+	if (rc == 0)
+		return gtf_count;
+	return rc;
 }
 
 /**
@@ -620,62 +415,25 @@
  * ATM this function never returns a failure.  It is an optional
  * method and if it fails for whatever reason, we should still
  * just keep going.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
-int ata_acpi_push_id(struct ata_device *dev)
+static int ata_acpi_push_id(struct ata_device *dev)
 {
 	struct ata_port *ap = dev->ap;
-	acpi_handle handle;
-	acpi_integer pcidevfn;
 	int err;
-	struct device *gdev = ap->host->dev;
-	u32 dev_adr;
 	acpi_status status;
 	struct acpi_object_list input;
 	union acpi_object in_params[1];
 
-	if (libata_noacpi)
-		return 0;
-
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
 			       __FUNCTION__, dev->devno, ap->port_no);
 
-	/* Don't continue if not a SATA device. */
-	if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				"%s: Not a SATA device\n", __FUNCTION__);
-		goto out;
-	}
-
-	/* Don't continue if device has no _ADR method.
-	 * _SDD is intended for known motherboard devices. */
-	err = sata_get_dev_handle(gdev, &handle, &pcidevfn);
-	if (err < 0) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				"%s: sata_get_dev_handle failed (%d\n",
-				__FUNCTION__, err);
-		goto out;
-	}
-
-	/* Get this drive's _ADR info, if not already known */
-	if (!dev->obj_handle) {
-		dev_adr = SATA_ADR_RSVD;
-		err = get_sata_adr(gdev, handle, pcidevfn, dev->devno, ap, dev,
-					&dev_adr);
-		if (err < 0 || dev_adr == SATA_ADR_RSVD ||
-			!dev->obj_handle) {
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: get_sata_adr failed: "
-					"err=%d, dev_adr=%u, obj_handle=0x%p\n",
-					__FUNCTION__, err, dev_adr,
-					dev->obj_handle);
-			goto out;
-		}
-	}
-
 	/* Give the drive Identify data to the drive via the _SDD method */
 	/* _SDD: set up input parameters */
 	input.count = 1;
@@ -687,20 +445,150 @@
 
 	/* It's OK for _SDD to be missing too. */
 	swap_buf_le16(dev->id, ATA_ID_WORDS);
-	status = acpi_evaluate_object(dev->obj_handle, "_SDD", &input, NULL);
+	status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL);
 	swap_buf_le16(dev->id, ATA_ID_WORDS);
 
 	err = ACPI_FAILURE(status) ? -EIO : 0;
-	if (err < 0) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				       "%s _SDD error: status = 0x%x\n",
-				       __FUNCTION__, status);
-	}
+	if (err < 0)
+		ata_dev_printk(dev, KERN_WARNING,
+			       "ACPI _SDD failed (AE 0x%x)\n", status);
 
-	/* always return success */
-out:
-	return 0;
+	return err;
 }
 
+/**
+ * ata_acpi_on_suspend - ATA ACPI hook called on suspend
+ * @ap: target ATA port
+ *
+ * This function is called when @ap is about to be suspended.  All
+ * devices are already put to sleep but the port_suspend() callback
+ * hasn't been executed yet.  Error return from this function aborts
+ * suspend.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int ata_acpi_on_suspend(struct ata_port *ap)
+{
+	unsigned long flags;
+	int rc;
 
+	/* proceed iff per-port acpi_handle is valid */
+	if (!ap->acpi_handle)
+		return 0;
+	BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
+
+	/* store timing parameters */
+	rc = ata_acpi_gtm(ap, &ap->acpi_gtm);
+
+	spin_lock_irqsave(ap->lock, flags);
+	if (rc == 0)
+		ap->pflags |= ATA_PFLAG_GTM_VALID;
+	else
+		ap->pflags &= ~ATA_PFLAG_GTM_VALID;
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	if (rc == -ENOENT)
+		rc = 0;
+	return rc;
+}
+
+/**
+ * ata_acpi_on_resume - ATA ACPI hook called on resume
+ * @ap: target ATA port
+ *
+ * This function is called when @ap is resumed - right after port
+ * itself is resumed but before any EH action is taken.
+ *
+ * LOCKING:
+ * EH context.
+ */
+void ata_acpi_on_resume(struct ata_port *ap)
+{
+	int i;
+
+	if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) {
+		BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
+
+		/* restore timing parameters */
+		ata_acpi_stm(ap, &ap->acpi_gtm);
+	}
+
+	/* schedule _GTF */
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		ap->device[i].flags |= ATA_DFLAG_ACPI_PENDING;
+}
+
+/**
+ * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
+ * @dev: target ATA device
+ *
+ * This function is called when @dev is about to be configured.
+ * IDENTIFY data might have been modified after this hook is run.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Positive number if IDENTIFY data needs to be refreshed, 0 if not,
+ * -errno on failure.
+ */
+int ata_acpi_on_devcfg(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->ap;
+	struct ata_eh_context *ehc = &ap->eh_context;
+	int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA;
+	int rc;
+
+	if (!dev->acpi_handle)
+		return 0;
+
+	/* do we need to do _GTF? */
+	if (!(dev->flags & ATA_DFLAG_ACPI_PENDING) &&
+	    !(acpi_sata && (ehc->i.flags & ATA_EHI_DID_HARDRESET)))
+		return 0;
+
+	/* do _SDD if SATA */
+	if (acpi_sata) {
+		rc = ata_acpi_push_id(dev);
+		if (rc)
+			goto acpi_err;
+	}
+
+	/* do _GTF */
+	rc = ata_acpi_exec_tfs(dev);
+	if (rc < 0)
+		goto acpi_err;
+
+	dev->flags &= ~ATA_DFLAG_ACPI_PENDING;
+
+	/* refresh IDENTIFY page if any _GTF command has been executed */
+	if (rc > 0) {
+		rc = ata_dev_reread_id(dev, 0);
+		if (rc < 0) {
+			ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY "
+				       "after ACPI commands\n");
+			return rc;
+		}
+	}
+
+	return 0;
+
+ acpi_err:
+	/* let EH retry on the first failure, disable ACPI on the second */
+	if (dev->flags & ATA_DFLAG_ACPI_FAILED) {
+		ata_dev_printk(dev, KERN_WARNING, "ACPI on devcfg failed the "
+			       "second time, disabling (errno=%d)\n", rc);
+
+		dev->acpi_handle = NULL;
+
+		/* if port is working, request IDENTIFY reload and continue */
+		if (!(ap->pflags & ATA_PFLAG_FROZEN))
+			rc = 1;
+	}
+	dev->flags |= ATA_DFLAG_ACPI_FAILED;
+	return rc;
+}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index d3ea7f5..88e2dd0 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -59,7 +59,7 @@
 
 #include "libata.h"
 
-#define DRV_VERSION	"2.20"	/* must be exactly four chars */
+#define DRV_VERSION	"2.21"	/* must be exactly four chars */
 
 
 /* debounce timing parameters in msecs { interval, duration, timeout } */
@@ -71,6 +71,7 @@
 					u16 heads, u16 sectors);
 static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
 static void ata_dev_xfermask(struct ata_device *dev);
+static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
 
 unsigned int ata_print_id = 1;
 static struct workqueue_struct *ata_wq;
@@ -600,8 +601,9 @@
 
 void ata_dev_disable(struct ata_device *dev)
 {
-	if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) {
-		ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+	if (ata_dev_enabled(dev)) {
+		if (ata_msg_drv(dev->ap))
+			ata_dev_printk(dev, KERN_WARNING, "disabled\n");
 		ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 |
 					     ATA_DNXFER_QUIET);
 		dev->class++;
@@ -977,17 +979,12 @@
 {
 	u64 sectors = dev->n_sectors;
 	u64 hpa_sectors;
-	
+
 	if (ata_id_has_lba48(dev->id))
 		hpa_sectors = ata_read_native_max_address_ext(dev);
 	else
 		hpa_sectors = ata_read_native_max_address(dev);
 
-	/* if no hpa, both should be equal */
-	ata_dev_printk(dev, KERN_INFO, "%s 1: sectors = %lld, "
-				"hpa_sectors = %lld\n",
-		__FUNCTION__, (long long)sectors, (long long)hpa_sectors);
-
 	if (hpa_sectors > sectors) {
 		ata_dev_printk(dev, KERN_INFO,
 			"Host Protected Area detected:\n"
@@ -1009,7 +1006,11 @@
 				return hpa_sectors;
 			}
 		}
-	}
+	} else if (hpa_sectors < sectors)
+		ata_dev_printk(dev, KERN_WARNING, "%s 1: hpa sectors (%lld) "
+			       "is smaller than sectors (%lld)\n", __FUNCTION__,
+			       (long long)hpa_sectors, (long long)sectors);
+
 	return sectors;
 }
 
@@ -1283,18 +1284,11 @@
 void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
 			 unsigned long delay)
 {
-	int rc;
-
-	if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
-		return;
-
 	PREPARE_DELAYED_WORK(&ap->port_task, fn);
 	ap->port_task_data = data;
 
-	rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
-
-	/* rc == 0 means that another user is using port task */
-	WARN_ON(rc == 0);
+	/* may fail if ata_port_flush_task() in progress */
+	queue_delayed_work(ata_wq, &ap->port_task, delay);
 }
 
 /**
@@ -1309,32 +1303,9 @@
  */
 void ata_port_flush_task(struct ata_port *ap)
 {
-	unsigned long flags;
-
 	DPRINTK("ENTER\n");
 
-	spin_lock_irqsave(ap->lock, flags);
-	ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
-	spin_unlock_irqrestore(ap->lock, flags);
-
-	DPRINTK("flush #1\n");
-	cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */
-
-	/*
-	 * At this point, if a task is running, it's guaranteed to see
-	 * the FLUSH flag; thus, it will never queue pio tasks again.
-	 * Cancel and flush.
-	 */
-	if (!cancel_delayed_work(&ap->port_task)) {
-		if (ata_msg_ctl(ap))
-			ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
-					__FUNCTION__);
-		cancel_work_sync(&ap->port_task.work);
-	}
-
-	spin_lock_irqsave(ap->lock, flags);
-	ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
-	spin_unlock_irqrestore(ap->lock, flags);
+	cancel_rearming_delayed_work(&ap->port_task);
 
 	if (ata_msg_ctl(ap))
 		ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
@@ -1588,7 +1559,7 @@
  *	Check if the current speed of the device requires IORDY. Used
  *	by various controllers for chip configuration.
  */
- 
+
 unsigned int ata_pio_need_iordy(const struct ata_device *adev)
 {
 	/* Controller doesn't support  IORDY. Probably a pointless check
@@ -1611,7 +1582,7 @@
  *	Compute the highest mode possible if we are not using iordy. Return
  *	-1 if no iordy mode is available.
  */
- 
+
 static u32 ata_pio_mask_no_iordy(const struct ata_device *adev)
 {
 	/* If we have no drive specific rule, then PIO 2 is non IORDY */
@@ -1727,7 +1698,7 @@
 
 	/* sanity check */
 	rc = -EINVAL;
-	reason = "device reports illegal type";
+	reason = "device reports invalid type";
 
 	if (class == ATA_DEV_ATA) {
 		if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
@@ -1814,7 +1785,7 @@
 		desc[0] = '\0';
 		return;
 	}
-	if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) {
+	if (dev->horkage & ATA_HORKAGE_NONCQ) {
 		snprintf(desc, desc_sz, "NCQ (not used)");
 		return;
 	}
@@ -1845,7 +1816,8 @@
 int ata_dev_configure(struct ata_device *dev)
 {
 	struct ata_port *ap = dev->ap;
-	int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
+	struct ata_eh_context *ehc = &ap->eh_context;
+	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
 	const u16 *id = dev->id;
 	unsigned int xfer_mask;
 	char revbuf[7];		/* XYZ-99\0 */
@@ -1862,15 +1834,13 @@
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
 
-	/* set _SDD */
-	rc = ata_acpi_push_id(dev);
-	if (rc) {
-		ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n",
-			rc);
-	}
+	/* set horkage */
+	dev->horkage |= ata_dev_blacklisted(dev);
 
-	/* retrieve and execute the ATA task file of _GTF */
-	ata_acpi_exec_tfs(ap);
+	/* let ACPI work its magic */
+	rc = ata_acpi_on_devcfg(dev);
+	if (rc)
+		return rc;
 
 	/* print device capabilities */
 	if (ata_msg_probe(ap))
@@ -1900,6 +1870,13 @@
 	if (ata_msg_probe(ap))
 		ata_dump_id(id);
 
+	/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
+	ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
+			sizeof(fwrevbuf));
+
+	ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
+			sizeof(modelbuf));
+
 	/* ATA-specific feature tests */
 	if (dev->class == ATA_DEV_ATA) {
 		if (ata_id_is_cfa(id)) {
@@ -1914,13 +1891,6 @@
 
 		dev->n_sectors = ata_id_n_sectors(id);
 
-		/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
-		ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
-				sizeof(fwrevbuf));
-
-		ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
-				sizeof(modelbuf));
-
 		if (dev->id[59] & 0x100)
 			dev->multi_count = dev->id[59] & 0xff;
 
@@ -2009,7 +1979,9 @@
 
 		/* print device info to dmesg */
 		if (ata_msg_drv(ap) && print_info)
-			ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
+			ata_dev_printk(dev, KERN_INFO,
+				       "ATAPI: %s, %s, max %s%s\n",
+				       modelbuf, fwrevbuf,
 				       ata_mode_string(xfer_mask),
 				       cdb_intr_string);
 	}
@@ -2040,14 +2012,10 @@
 		dev->max_sectors = ATA_MAX_SECTORS;
 	}
 
-	if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128)
+	if (dev->horkage & ATA_HORKAGE_MAX_SEC_128)
 		dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
 					 dev->max_sectors);
 
-	/* limit ATAPI DMA to R/W commands only */
-	if (ata_device_blacklisted(dev) & ATA_HORKAGE_DMA_RW_ONLY)
-		dev->horkage |= ATA_HORKAGE_DMA_RW_ONLY;
-
 	if (ap->ops->dev_config)
 		ap->ops->dev_config(dev);
 
@@ -2663,7 +2631,7 @@
 		t->active += (t->cycle - (t->active + t->recover)) / 2;
 		t->recover = t->cycle - t->active;
 	}
-	
+
 	/* In a few cases quantisation may produce enough errors to
 	   leave t->cycle too low for the sum of active and recovery
 	   if so we must correct this */
@@ -2893,9 +2861,6 @@
 	if (used_dma && (ap->host->flags & ATA_HOST_SIMPLEX))
 		ap->host->simplex_claimed = ap;
 
-	/* step5: chip specific finalisation */
-	if (ap->ops->post_set_mode)
-		ap->ops->post_set_mode(ap);
  out:
 	if (rc)
 		*r_failed_dev = dev;
@@ -3025,7 +2990,7 @@
 
 		if (!(status & ATA_BUSY))
 			return 0;
-		if (status == 0xff)
+		if (!ata_port_online(ap) && status == 0xff)
 			return -ENODEV;
 		if (time_after(now, deadline))
 			return -EBUSY;
@@ -3062,22 +3027,28 @@
 		}
 	}
 
-	/* if device 1 was found in ata_devchk, wait for
-	 * register access, then wait for BSY to clear
+	/* if device 1 was found in ata_devchk, wait for register
+	 * access briefly, then wait for BSY to clear.
 	 */
-	while (dev1) {
-		u8 nsect, lbal;
+	if (dev1) {
+		int i;
 
 		ap->ops->dev_select(ap, 1);
-		nsect = ioread8(ioaddr->nsect_addr);
-		lbal = ioread8(ioaddr->lbal_addr);
-		if ((nsect == 1) && (lbal == 1))
-			break;
-		if (time_after(jiffies, deadline))
-			return -EBUSY;
-		msleep(50);	/* give drive a breather */
-	}
-	if (dev1) {
+
+		/* Wait for register access.  Some ATAPI devices fail
+		 * to set nsect/lbal after reset, so don't waste too
+		 * much time on it.  We're gonna wait for !BSY anyway.
+		 */
+		for (i = 0; i < 2; i++) {
+			u8 nsect, lbal;
+
+			nsect = ioread8(ioaddr->nsect_addr);
+			lbal = ioread8(ioaddr->lbal_addr);
+			if ((nsect == 1) && (lbal == 1))
+				break;
+			msleep(50);	/* give drive a breather */
+		}
+
 		rc = ata_wait_ready(ap, deadline);
 		if (rc) {
 			if (rc != -ENODEV)
@@ -3193,9 +3164,6 @@
 	if ((slave_possible) && (err != 0x81))
 		ap->device[1].class = ata_dev_try_classify(ap, 1, &err);
 
-	/* re-enable interrupts */
-	ap->ops->irq_on(ap);
-
 	/* is double-select really necessary? */
 	if (ap->device[1].class != ATA_DEV_NONE)
 		ap->ops->dev_select(ap, 1);
@@ -3358,7 +3326,7 @@
 		return 0;
 
 	/* if SATA, resume phy */
-	if (ap->cbl == ATA_CBL_SATA) {
+	if (ap->flags & ATA_FLAG_SATA) {
 		rc = sata_phy_resume(ap, timing, deadline);
 		/* whine about phy resume failure but proceed */
 		if (rc && rc != -EOPNOTSUPP)
@@ -3371,7 +3339,7 @@
 	 */
 	if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap)) {
 		rc = ata_wait_ready(ap, deadline);
-		if (rc) {
+		if (rc && rc != -ENODEV) {
 			ata_port_printk(ap, KERN_WARNING, "device not ready "
 					"(errno=%d), forcing hardreset\n", rc);
 			ehc->i.action |= ATA_EH_HARDRESET;
@@ -3580,10 +3548,6 @@
 	if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
 		sata_scr_write(ap, SCR_ERROR, serror);
 
-	/* re-enable interrupts */
-	if (!ap->ops->error_handler)
-		ap->ops->irq_on(ap);
-
 	/* is double-select really necessary? */
 	if (classes[0] != ATA_DEV_NONE)
 		ap->ops->dev_select(ap, 1);
@@ -3654,7 +3618,7 @@
 
 /**
  *	ata_dev_reread_id - Re-read IDENTIFY data
- *	@adev: target ATA device
+ *	@dev: target ATA device
  *	@readid_flags: read ID flags
  *
  *	Re-read IDENTIFY page and make sure @dev is still attached to
@@ -3771,10 +3735,13 @@
 	{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA },
 	{ "_NEC DV5800A", 	NULL,		ATA_HORKAGE_NODMA },
 	{ "SAMSUNG CD-ROM SN-124","N001",	ATA_HORKAGE_NODMA },
+	{ "Seagate STT20000A", NULL,		ATA_HORKAGE_NODMA },
+	{ "IOMEGA  ZIP 250       ATAPI", NULL,	ATA_HORKAGE_NODMA }, /* temporary fix */
+	{ "IOMEGA  ZIP 250       ATAPI       Floppy",
+				NULL,		ATA_HORKAGE_NODMA },
 
 	/* Weird ATAPI devices */
-	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 |
-						ATA_HORKAGE_DMA_RW_ONLY },
+	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },
 
 	/* Devices we expect to fail diagnostics */
 
@@ -3785,6 +3752,10 @@
 	{ "FUJITSU MHT2060BH",	NULL,		ATA_HORKAGE_NONCQ },
 	/* NCQ is broken */
 	{ "Maxtor 6L250S0",     "BANC1G10",     ATA_HORKAGE_NONCQ },
+	{ "Maxtor 6B200M0",	"BANC1BM0",	ATA_HORKAGE_NONCQ },
+	{ "Maxtor 6B200M0",	"BANC1B10",	ATA_HORKAGE_NONCQ },
+	{ "HITACHI HDS7250SASUN500G 0621KTAWSD", "K2AOAJ0AHITACHI",
+	 ATA_HORKAGE_NONCQ },
 	/* NCQ hard hangs device under heavier load, needs hard power cycle */
 	{ "Maxtor 6B250S0",	"BANC1B70",	ATA_HORKAGE_NONCQ },
 	/* Blacklist entries taken from Silicon Image 3124/3132
@@ -3792,6 +3763,12 @@
 	{ "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
 	{ "HTS541080G9SA00",    "MB4OC60D",     ATA_HORKAGE_NONCQ, },
 	{ "HTS541010G9SA00",    "MBZOC60D",     ATA_HORKAGE_NONCQ, },
+	/* Drives which do spurious command completion */
+	{ "HTS541680J9SA00",	"SB2IC7EP",	ATA_HORKAGE_NONCQ, },
+	{ "HTS541612J9SA00",	"SBDIC7JP",	ATA_HORKAGE_NONCQ, },
+	{ "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, },
+	{ "WDC WD740ADFD-00NLR1", NULL,		ATA_HORKAGE_NONCQ, },
+	{ "FUJITSU MHV2080BH",	"00840028",	ATA_HORKAGE_NONCQ, },
 
 	/* Devices with NCQ limits */
 
@@ -3799,7 +3776,7 @@
 	{ }
 };
 
-unsigned long ata_device_blacklisted(const struct ata_device *dev)
+static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
 {
 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
 	unsigned char model_rev[ATA_ID_FW_REV_LEN + 1];
@@ -3829,7 +3806,7 @@
 	if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
 	    (dev->flags & ATA_DFLAG_CDB_INTR))
 		return 1;
-	return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0;
+	return (dev->horkage & ATA_HORKAGE_NODMA) ? 1 : 0;
 }
 
 /**
@@ -3934,10 +3911,13 @@
 	/* set up set-features taskfile */
 	DPRINTK("set features - xfer mode\n");
 
+	/* Some controllers and ATAPI devices show flaky interrupt
+	 * behavior after setting xfer mode.  Use polling instead.
+	 */
 	ata_tf_init(dev, &tf);
 	tf.command = ATA_CMD_SET_FEATURES;
 	tf.feature = SETFEATURES_XFER;
-	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_POLLING;
 	tf.protocol = ATA_PROT_NODATA;
 	tf.nsect = dev->xfer_mode;
 
@@ -4094,6 +4074,69 @@
 	if (idx)
 		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
 }
+
+/**
+ *	ata_fill_sg_dumb - Fill PCI IDE PRD table
+ *	@qc: Metadata associated with taskfile to be transferred
+ *
+ *	Fill PCI IDE PRD (scatter-gather) table with segments
+ *	associated with the current disk command. Perform the fill
+ *	so that we avoid writing any length 64K records for
+ *	controllers that don't follow the spec.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host lock)
+ *
+ */
+static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct scatterlist *sg;
+	unsigned int idx;
+
+	WARN_ON(qc->__sg == NULL);
+	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+	idx = 0;
+	ata_for_each_sg(sg, qc) {
+		u32 addr, offset;
+		u32 sg_len, len, blen;
+
+ 		/* determine if physical DMA addr spans 64K boundary.
+		 * Note h/w doesn't support 64-bit, so we unconditionally
+		 * truncate dma_addr_t to u32.
+		 */
+		addr = (u32) sg_dma_address(sg);
+		sg_len = sg_dma_len(sg);
+
+		while (sg_len) {
+			offset = addr & 0xffff;
+			len = sg_len;
+			if ((offset + sg_len) > 0x10000)
+				len = 0x10000 - offset;
+
+			blen = len & 0xffff;
+			ap->prd[idx].addr = cpu_to_le32(addr);
+			if (blen == 0) {
+			   /* Some PATA chipsets like the CS5530 can't
+			      cope with 0x0000 meaning 64K as the spec says */
+				ap->prd[idx].flags_len = cpu_to_le32(0x8000);
+				blen = 0x8000;
+				ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
+			}
+			ap->prd[idx].flags_len = cpu_to_le32(blen);
+			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+
+			idx++;
+			sg_len -= len;
+			addr += len;
+		}
+	}
+
+	if (idx)
+		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+
 /**
  *	ata_check_atapi_dma - Check whether ATAPI DMA can be supported
  *	@qc: Metadata associated with taskfile to check
@@ -4111,33 +4154,19 @@
 int ata_check_atapi_dma(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	int rc = 0; /* Assume ATAPI DMA is OK by default */
 
-	/* some drives can only do ATAPI DMA on read/write */
-	if (unlikely(qc->dev->horkage & ATA_HORKAGE_DMA_RW_ONLY)) {
-		struct scsi_cmnd *cmd = qc->scsicmd;
-		u8 *scsicmd = cmd->cmnd;
-
-		switch (scsicmd[0]) {
-		case READ_10:
-		case WRITE_10:
-		case READ_12:
-		case WRITE_12:
-		case READ_6:
-		case WRITE_6:
-			/* atapi dma maybe ok */
-			break;
-		default:
-			/* turn off atapi dma */
-			return 1;
-		}
-	}
+	/* Don't allow DMA if it isn't multiple of 16 bytes.  Quite a
+	 * few ATAPI devices choke on such DMA requests.
+	 */
+	if (unlikely(qc->nbytes & 15))
+		return 1;
 
 	if (ap->ops->check_atapi_dma)
-		rc = ap->ops->check_atapi_dma(qc);
+		return ap->ops->check_atapi_dma(qc);
 
-	return rc;
+	return 0;
 }
+
 /**
  *	ata_qc_prep - Prepare taskfile for submission
  *	@qc: Metadata associated with taskfile to be prepared
@@ -4155,6 +4184,23 @@
 	ata_fill_sg(qc);
 }
 
+/**
+ *	ata_dumb_qc_prep - Prepare taskfile for submission
+ *	@qc: Metadata associated with taskfile to be prepared
+ *
+ *	Prepare ATA taskfile for submission.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host lock)
+ */
+void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
+{
+	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+		return;
+
+	ata_fill_sg_dumb(qc);
+}
+
 void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
 
 /**
@@ -4784,8 +4830,6 @@
 		} else
 			ata_qc_complete(qc);
 	}
-
-	ata_altstatus(ap); /* flush */
 }
 
 /**
@@ -5415,14 +5459,6 @@
 		}
 	}
 
-	/* Some controllers show flaky interrupt behavior after
-	 * setting xfer mode.  Use polling instead.
-	 */
-	if (unlikely(qc->tf.command == ATA_CMD_SET_FEATURES &&
-		     qc->tf.feature == SETFEATURES_XFER) &&
-	    (ap->flags & ATA_FLAG_SETXFER_POLLING))
-		qc->tf.flags |= ATA_TFLAG_POLLING;
-
 	/* select the device */
 	ata_dev_select(ap, qc->dev->devno, 1, 0);
 
@@ -5672,7 +5708,7 @@
  */
 int sata_scr_valid(struct ata_port *ap)
 {
-	return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
+	return (ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read;
 }
 
 /**
@@ -6305,6 +6341,9 @@
 	if (rc)
 		return rc;
 
+	/* associate with ACPI nodes */
+	ata_acpi_associate(host);
+
 	/* set cable, sata_spd_limit and report */
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
@@ -6319,7 +6358,8 @@
 		/* init sata_spd_limit to the current value */
 		if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
 			int spd = (scontrol >> 4) & 0xf;
-			ap->hw_sata_spd_limit &= (1 << spd) - 1;
+			if (spd)
+				ap->hw_sata_spd_limit &= (1 << spd) - 1;
 		}
 		ap->sata_spd_limit = ap->hw_sata_spd_limit;
 
@@ -6335,7 +6375,7 @@
 		if (!ata_port_is_dummy(ap))
 			ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p "
 					"ctl 0x%p bmdma 0x%p irq %d\n",
-					ap->cbl == ATA_CBL_SATA ? 'S' : 'P',
+					(ap->flags & ATA_FLAG_SATA) ? 'S' : 'P',
 					ata_mode_string(xfer_mask),
 					ap->ioaddr.cmd_addr,
 					ap->ioaddr.ctl_addr,
@@ -6434,6 +6474,9 @@
 	if (rc)
 		return rc;
 
+	/* Used to print device info at probe */
+	host->irq = irq;
+
 	rc = ata_host_register(host, sht);
 	/* if failed, just free the IRQ and leave ports alone */
 	if (rc)
@@ -6487,13 +6530,7 @@
 	spin_unlock_irqrestore(ap->lock, flags);
 
 	ata_port_wait_eh(ap);
-
-	/* Flush hotplug task.  The sequence is similar to
-	 * ata_port_flush_task().
-	 */
-	cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */
-	cancel_delayed_work(&ap->hotplug_task);
-	cancel_work_sync(&ap->hotplug_task.work);
+	cancel_rearming_delayed_work(&ap->hotplug_task);
 
  skip_eh:
 	/* remove the associated SCSI host */
@@ -6824,11 +6861,13 @@
 EXPORT_SYMBOL_GPL(ata_altstatus);
 EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
+EXPORT_SYMBOL_GPL(ata_sff_port_start);
 EXPORT_SYMBOL_GPL(ata_interrupt);
 EXPORT_SYMBOL_GPL(ata_do_set_mode);
 EXPORT_SYMBOL_GPL(ata_data_xfer);
 EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
+EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
 EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup);
 EXPORT_SYMBOL_GPL(ata_bmdma_start);
@@ -6880,7 +6919,6 @@
 EXPORT_SYMBOL_GPL(ata_id_string);
 EXPORT_SYMBOL_GPL(ata_id_c_string);
 EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
-EXPORT_SYMBOL_GPL(ata_device_blacklisted);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
 EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
@@ -6889,9 +6927,9 @@
 
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
-EXPORT_SYMBOL_GPL(ata_pci_init_native_host);
+EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
 EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
-EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host);
+EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
 #ifdef CONFIG_PM
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 5309c31..9aa62a0 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -336,6 +336,7 @@
 			}
 			ata_port_printk(ap, KERN_ERR, "EH pending after %d "
 					"tries, giving up\n", ATA_EH_MAX_REPEAT);
+			ap->pflags &= ~ATA_PFLAG_EH_PENDING;
 		}
 
 		/* this run is complete, make sure EH info is clear */
@@ -1009,7 +1010,7 @@
 	sense_buf[0] = 0x70;
 	sense_buf[2] = qc->result_tf.feature >> 4;
 
-	/* some devices time out if garbage left in tf */ 
+	/* some devices time out if garbage left in tf */
 	ata_tf_init(dev, &tf);
 
 	memset(cdb, 0, ATAPI_CDB_LEN);
@@ -1616,7 +1617,7 @@
 	unsigned long deadline;
 	unsigned int action;
 	ata_reset_fn_t reset;
-	int i, did_followup_srst, rc;
+	int i, rc;
 
 	/* about to reset */
 	ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
@@ -1665,8 +1666,6 @@
 
 	/* did prereset() screw up?  if so, fix up to avoid oopsing */
 	if (!reset) {
-		ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested "
-				"invalid reset type\n");
 		if (softreset)
 			reset = softreset;
 		else
@@ -1689,11 +1688,9 @@
 
 	rc = ata_do_reset(ap, reset, classes, deadline);
 
-	did_followup_srst = 0;
 	if (reset == hardreset &&
 	    ata_eh_followup_srst_needed(rc, classify, classes)) {
 		/* okay, let's do follow-up softreset */
-		did_followup_srst = 1;
 		reset = softreset;
 
 		if (!reset) {
@@ -1900,6 +1897,57 @@
 	return 1;
 }
 
+static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+{
+	struct ata_port *ap = dev->ap;
+	struct ata_eh_context *ehc = &ap->eh_context;
+
+	ehc->tries[dev->devno]--;
+
+	switch (err) {
+	case -ENODEV:
+		/* device missing or wrong IDENTIFY data, schedule probing */
+		ehc->i.probe_mask |= (1 << dev->devno);
+	case -EINVAL:
+		/* give it just one more chance */
+		ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
+	case -EIO:
+		if (ehc->tries[dev->devno] == 1) {
+			/* This is the last chance, better to slow
+			 * down than lose it.
+			 */
+			sata_down_spd_limit(ap);
+			ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+		}
+	}
+
+	if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
+		/* disable device if it has used up all its chances */
+		ata_dev_disable(dev);
+
+		/* detach if offline */
+		if (ata_port_offline(ap))
+			ata_eh_detach_dev(dev);
+
+		/* probe if requested */
+		if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+		    !(ehc->did_probe_mask & (1 << dev->devno))) {
+			ata_eh_detach_dev(dev);
+			ata_dev_init(dev);
+
+			ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+			ehc->did_probe_mask |= (1 << dev->devno);
+			ehc->i.action |= ATA_EH_SOFTRESET;
+		}
+	} else {
+		/* soft didn't work?  be haaaaard */
+		if (ehc->i.flags & ATA_EHI_DID_RESET)
+			ehc->i.action |= ATA_EH_HARDRESET;
+		else
+			ehc->i.action |= ATA_EH_SOFTRESET;
+	}
+}
+
 /**
  *	ata_eh_recover - recover host port after error
  *	@ap: host port to recover
@@ -2000,50 +2048,7 @@
 	goto out;
 
  dev_fail:
-	ehc->tries[dev->devno]--;
-
-	switch (rc) {
-	case -ENODEV:
-		/* device missing or wrong IDENTIFY data, schedule probing */
-		ehc->i.probe_mask |= (1 << dev->devno);
-	case -EINVAL:
-		/* give it just one more chance */
-		ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
-	case -EIO:
-		if (ehc->tries[dev->devno] == 1) {
-			/* This is the last chance, better to slow
-			 * down than lose it.
-			 */
-			sata_down_spd_limit(ap);
-			ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
-		}
-	}
-
-	if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
-		/* disable device if it has used up all its chances */
-		ata_dev_disable(dev);
-
-		/* detach if offline */
-		if (ata_port_offline(ap))
-			ata_eh_detach_dev(dev);
-
-		/* probe if requested */
-		if ((ehc->i.probe_mask & (1 << dev->devno)) &&
-		    !(ehc->did_probe_mask & (1 << dev->devno))) {
-			ata_eh_detach_dev(dev);
-			ata_dev_init(dev);
-
-			ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
-			ehc->did_probe_mask |= (1 << dev->devno);
-			ehc->i.action |= ATA_EH_SOFTRESET;
-		}
-	} else {
-		/* soft didn't work?  be haaaaard */
-		if (ehc->i.flags & ATA_EHI_DID_RESET)
-			ehc->i.action |= ATA_EH_HARDRESET;
-		else
-			ehc->i.action |= ATA_EH_SOFTRESET;
-	}
+	ata_eh_handle_dev_fail(dev, rc);
 
 	if (ata_port_nr_enabled(ap)) {
 		ata_port_printk(ap, KERN_WARNING, "failed to recover some "
@@ -2157,19 +2162,25 @@
 
 	WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
 
+	/* tell ACPI we're suspending */
+	rc = ata_acpi_on_suspend(ap);
+	if (rc)
+		goto out;
+
 	/* suspend */
 	ata_eh_freeze_port(ap);
 
 	if (ap->ops->port_suspend)
 		rc = ap->ops->port_suspend(ap, ap->pm_mesg);
 
+ out:
 	/* report result */
 	spin_lock_irqsave(ap->lock, flags);
 
 	ap->pflags &= ~ATA_PFLAG_PM_PENDING;
 	if (rc == 0)
 		ap->pflags |= ATA_PFLAG_SUSPENDED;
-	else
+	else if (ap->pflags & ATA_PFLAG_FROZEN)
 		ata_port_schedule_eh(ap);
 
 	if (ap->pm_result) {
@@ -2210,6 +2221,9 @@
 	if (ap->ops->port_resume)
 		rc = ap->ops->port_resume(ap);
 
+	/* tell ACPI that we're resuming */
+	ata_acpi_on_resume(ap);
+
 	/* report result */
 	spin_lock_irqsave(ap->lock, flags);
 	ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 242c43e..cfde22d 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1050,14 +1050,15 @@
 static void scsi_6_lba_len(const u8 *cdb, u64 *plba, u32 *plen)
 {
 	u64 lba = 0;
-	u32 len = 0;
+	u32 len;
 
 	VPRINTK("six-byte command\n");
 
+	lba |= ((u64)(cdb[1] & 0x1f)) << 16;
 	lba |= ((u64)cdb[2]) << 8;
 	lba |= ((u64)cdb[3]);
 
-	len |= ((u32)cdb[4]);
+	len = cdb[4];
 
 	*plba = lba;
 	*plen = len;
@@ -1362,12 +1363,22 @@
 	 * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
 	 * cache
 	 */
-	if (ap->ops->error_handler &&
-	    !need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
-	    ((qc->tf.feature == SETFEATURES_WC_ON) ||
-	     (qc->tf.feature == SETFEATURES_WC_OFF))) {
-		ap->eh_info.action |= ATA_EH_REVALIDATE;
-		ata_port_schedule_eh(ap);
+	if (ap->ops->error_handler && !need_sense) {
+		switch (qc->tf.command) {
+		case ATA_CMD_SET_FEATURES:
+			if ((qc->tf.feature == SETFEATURES_WC_ON) ||
+			    (qc->tf.feature == SETFEATURES_WC_OFF)) {
+				ap->eh_info.action |= ATA_EH_REVALIDATE;
+				ata_port_schedule_eh(ap);
+			}
+			break;
+
+		case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+		case ATA_CMD_SET_MULTI: /* multi_count changed */
+			ap->eh_info.action |= ATA_EH_REVALIDATE;
+			ata_port_schedule_eh(ap);
+			break;
+		}
 	}
 
 	/* For ATA pass thru (SAT) commands, generate a sense block if
@@ -2373,11 +2384,6 @@
 	int using_pio = (dev->flags & ATA_DFLAG_PIO);
 	int nodata = (scmd->sc_data_direction == DMA_NONE);
 
-	if (!using_pio)
-		/* Check whether ATAPI DMA is safe */
-		if (ata_check_atapi_dma(qc))
-			using_pio = 1;
-
 	memset(qc->cdb, 0, dev->cdb_len);
 	memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
 
@@ -2390,19 +2396,22 @@
 	}
 
 	qc->tf.command = ATA_CMD_PACKET;
+	qc->nbytes = scmd->request_bufflen;
 
-	/* no data, or PIO data xfer */
+	/* check whether ATAPI DMA is safe */
+	if (!using_pio && ata_check_atapi_dma(qc))
+		using_pio = 1;
+
 	if (using_pio || nodata) {
+		/* no data, or PIO data xfer */
 		if (nodata)
 			qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
 		else
 			qc->tf.protocol = ATA_PROT_ATAPI;
 		qc->tf.lbam = (8 * 1024) & 0xff;
 		qc->tf.lbah = (8 * 1024) >> 8;
-	}
-
-	/* DMA data xfer */
-	else {
+	} else {
+		/* DMA data xfer */
 		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
 		qc->tf.feature |= ATAPI_PKT_DMA;
 
@@ -2411,8 +2420,6 @@
 			qc->tf.feature |= ATAPI_DMADIR;
 	}
 
-	qc->nbytes = scmd->request_bufflen;
-
 	return 0;
 }
 
@@ -2505,22 +2512,21 @@
 			return ATA_PROT_NODATA;
 
 		case 6:		/* DMA */
+		case 10:	/* UDMA Data-in */
+		case 11:	/* UDMA Data-Out */
 			return ATA_PROT_DMA;
 
 		case 4:		/* PIO Data-in */
 		case 5:		/* PIO Data-out */
 			return ATA_PROT_PIO;
 
-		case 10:	/* Device Reset */
 		case 0:		/* Hard Reset */
 		case 1:		/* SRST */
-		case 2:		/* Bus Idle */
-		case 7:		/* Packet */
-		case 8:		/* DMA Queued */
-		case 9:		/* Device Diagnostic */
-		case 11:	/* UDMA Data-in */
-		case 12:	/* UDMA Data-Out */
-		case 13:	/* FPDMA */
+		case 8:		/* Device Diagnostic */
+		case 9:		/* Device Reset */
+		case 7:		/* DMA Queued */
+		case 12:	/* FPDMA */
+		case 15:	/* Return Response Info */
 		default:	/* Reserved */
 			break;
 	}
@@ -2551,10 +2557,6 @@
 	if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
 		goto invalid_fld;
 
-	if (cdb[1] & 0xe0)
-		/* PIO multi not supported yet */
-		goto invalid_fld;
-
 	/*
 	 * 12 and 16 byte CDBs use different offsets to
 	 * provide the various register values.
@@ -2599,12 +2601,26 @@
 		tf->device = cdb[8];
 		tf->command = cdb[9];
 	}
-	/*
-	 * If slave is possible, enforce correct master/slave bit
-	*/
-	if (qc->ap->flags & ATA_FLAG_SLAVE_POSS)
-		tf->device = qc->dev->devno ?
-			tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
+
+	/* enforce correct master/slave bit */
+	tf->device = dev->devno ?
+		tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
+
+	/* sanity check for pio multi commands */
+	if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf))
+		goto invalid_fld;
+
+	if (is_multi_taskfile(tf)) {
+		unsigned int multi_count = 1 << (cdb[1] >> 5);
+
+		/* compare the passed through multi_count
+		 * with the cached multi_count of libata
+		 */
+		if (multi_count != dev->multi_count)
+			ata_dev_printk(dev, KERN_WARNING,
+				       "invalid multi_count %u ignored\n",
+				       multi_count);
+	}
 
 	/* READ/WRITE LONG use a non-standard sect_size */
 	qc->sect_size = ATA_SECT_SIZE;
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index e35d134..ca7d224 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -80,25 +80,25 @@
 u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
 {
 	unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
-	u8 host_stat, post_stat, status;
+	u8 host_stat = 0, post_stat = 0, status;
 
 	status = ata_busy_wait(ap, bits, 1000);
 	if (status & bits)
 		if (ata_msg_err(ap))
 			printk(KERN_ERR "abnormal status 0x%X\n", status);
 
-	/* get controller status; clear intr, err bits */
-	host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-	iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-		 ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	if (ap->ioaddr.bmdma_addr) {
+		/* get controller status; clear intr, err bits */
+		host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+		iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
+			 ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 
-	post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-
+		post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	}
 	if (ata_msg_intr(ap))
 		printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
 			__FUNCTION__,
 			host_stat, post_stat, status);
-
 	return status;
 }
 
@@ -516,6 +516,27 @@
 		ata_bmdma_stop(qc);
 }
 
+/**
+ *	ata_sff_port_start - Set port up for dma.
+ *	@ap: Port to initialize
+ *
+ *	Called just after data structures for each port are
+ *	initialized.  Allocates space for PRD table if the device
+ *	is DMA capable SFF.
+ *
+ *	May be used as the port_start() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
+int ata_sff_port_start(struct ata_port *ap)
+{
+	if (ap->ioaddr.bmdma_addr)
+		return ata_port_start(ap);
+	return 0;
+}
+
 #ifdef CONFIG_PCI
 
 static int ata_resources_present(struct pci_dev *pdev, int port)
@@ -583,13 +604,17 @@
 }
 
 /**
- *	ata_pci_init_native_host - acquire native ATA resources and init host
+ *	ata_pci_init_sff_host - acquire native PCI ATA resources and init host
  *	@host: target ATA host
  *
  *	Acquire native PCI ATA resources for @host and initialize the
  *	first two ports of @host accordingly.  Ports marked dummy are
  *	skipped and allocation failure makes the port dummy.
  *
+ *	Note that native PCI resources are valid even for legacy hosts
+ *	as we fix up pdev resources array early in boot, so this
+ *	function can be used for both native and legacy SFF hosts.
+ *
  *	LOCKING:
  *	Inherited from calling layer (may sleep).
  *
@@ -597,7 +622,7 @@
  *	0 if at least one port is initialized, -ENODEV if no port is
  *	available.
  */
-int ata_pci_init_native_host(struct ata_host *host)
+int ata_pci_init_sff_host(struct ata_host *host)
 {
 	struct device *gdev = host->dev;
 	struct pci_dev *pdev = to_pci_dev(gdev);
@@ -652,7 +677,7 @@
 }
 
 /**
- *	ata_pci_prepare_native_host - helper to prepare native PCI ATA host
+ *	ata_pci_prepare_sff_host - helper to prepare native PCI ATA host
  *	@pdev: target PCI device
  *	@ppi: array of port_info, must be enough for two ports
  *	@r_host: out argument for the initialized ATA host
@@ -666,9 +691,9 @@
  *	RETURNS:
  *	0 on success, -errno otherwise.
  */
-int ata_pci_prepare_native_host(struct pci_dev *pdev,
-				const struct ata_port_info * const * ppi,
-				struct ata_host **r_host)
+int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+			     const struct ata_port_info * const * ppi,
+			     struct ata_host **r_host)
 {
 	struct ata_host *host;
 	int rc;
@@ -684,7 +709,7 @@
 		goto err_out;
 	}
 
-	rc = ata_pci_init_native_host(host);
+	rc = ata_pci_init_sff_host(host);
 	if (rc)
 		goto err_out;
 
@@ -709,221 +734,6 @@
 	return rc;
 }
 
-struct ata_legacy_devres {
-	unsigned int	mask;
-	unsigned long	cmd_port[2];
-	void __iomem *	cmd_addr[2];
-	void __iomem *	ctl_addr[2];
-	unsigned int	irq[2];
-	void *		irq_dev_id[2];
-};
-
-static void ata_legacy_free_irqs(struct ata_legacy_devres *legacy_dr)
-{
-	int i;
-
-	for (i = 0; i < 2; i++) {
-		if (!legacy_dr->irq[i])
-			continue;
-
-		free_irq(legacy_dr->irq[i], legacy_dr->irq_dev_id[i]);
-		legacy_dr->irq[i] = 0;
-		legacy_dr->irq_dev_id[i] = NULL;
-	}
-}
-
-static void ata_legacy_release(struct device *gdev, void *res)
-{
-	struct ata_legacy_devres *this = res;
-	int i;
-
-	ata_legacy_free_irqs(this);
-
-	for (i = 0; i < 2; i++) {
-		if (this->cmd_addr[i])
-			ioport_unmap(this->cmd_addr[i]);
-		if (this->ctl_addr[i])
-			ioport_unmap(this->ctl_addr[i]);
-		if (this->cmd_port[i])
-			release_region(this->cmd_port[i], 8);
-	}
-}
-
-static int ata_init_legacy_port(struct ata_port *ap,
-				struct ata_legacy_devres *legacy_dr)
-{
-	struct ata_host *host = ap->host;
-	int port_no = ap->port_no;
-	unsigned long cmd_port, ctl_port;
-
-	if (port_no == 0) {
-		cmd_port = ATA_PRIMARY_CMD;
-		ctl_port = ATA_PRIMARY_CTL;
-	} else {
-		cmd_port = ATA_SECONDARY_CMD;
-		ctl_port = ATA_SECONDARY_CTL;
-	}
-
-	/* request cmd_port */
-	if (request_region(cmd_port, 8, "libata"))
-		legacy_dr->cmd_port[port_no] = cmd_port;
-	else {
-		dev_printk(KERN_WARNING, host->dev,
-			   "0x%0lX IDE port busy\n", cmd_port);
-		return -EBUSY;
-	}
-
-	/* iomap cmd and ctl ports */
-	legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8);
-	legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1);
-	if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) {
-		dev_printk(KERN_WARNING, host->dev,
-			   "failed to map cmd/ctl ports\n");
-		return -ENOMEM;
-	}
-
-	/* init IO addresses */
-	ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no];
-	ap->ioaddr.altstatus_addr = legacy_dr->ctl_addr[port_no];
-	ap->ioaddr.ctl_addr = legacy_dr->ctl_addr[port_no];
-	ata_std_ports(&ap->ioaddr);
-
-	return 0;
-}
-
-/**
- *	ata_init_legacy_host - acquire legacy ATA resources and init ATA host
- *	@host: target ATA host
- *	@was_busy: out parameter, indicates whether any port was busy
- *
- *	Acquire legacy ATA resources for the first two ports of @host
- *	and initialize it accordingly.  Ports marked dummy are skipped
- *	and resource acquistion failure makes the port dummy.
- *
- *	LOCKING:
- *	Inherited from calling layer (may sleep).
- *
- *	RETURNS:
- *	0 if at least one port is initialized, -ENODEV if no port is
- *	available.
- */
-static int ata_init_legacy_host(struct ata_host *host, int *was_busy)
-{
-	struct device *gdev = host->dev;
-	struct ata_legacy_devres *legacy_dr;
-	int i, rc;
-
-	if (!devres_open_group(gdev, NULL, GFP_KERNEL))
-		return -ENOMEM;
-
-	rc = -ENOMEM;
-	legacy_dr = devres_alloc(ata_legacy_release, sizeof(*legacy_dr),
-				 GFP_KERNEL);
-	if (!legacy_dr)
-		goto err_out;
-	devres_add(gdev, legacy_dr);
-
-	for (i = 0; i < 2; i++) {
-		if (ata_port_is_dummy(host->ports[i]))
-			continue;
-
-		rc = ata_init_legacy_port(host->ports[i], legacy_dr);
-		if (rc == 0)
-			legacy_dr->mask |= 1 << i;
-		else {
-			if (rc == -EBUSY)
-				(*was_busy)++;
-			host->ports[i]->ops = &ata_dummy_port_ops;
-		}
-	}
-
-	if (!legacy_dr->mask) {
-		dev_printk(KERN_ERR, gdev, "no available legacy port\n");
-		return -ENODEV;
-	}
-
-	devres_remove_group(gdev, NULL);
-	return 0;
-
- err_out:
-	devres_release_group(gdev, NULL);
-	return rc;
-}
-
-/**
- *	ata_request_legacy_irqs - request legacy ATA IRQs
- *	@host: target ATA host
- *	@handler: array of IRQ handlers
- *	@irq_flags: array of IRQ flags
- *	@dev_id: array of IRQ dev_ids
- *
- *	Request legacy IRQs for non-dummy legacy ports in @host.  All
- *	IRQ parameters are passed as array to allow ports to have
- *	separate IRQ handlers.
- *
- *	LOCKING:
- *	Inherited from calling layer (may sleep).
- *
- *	RETURNS:
- *	0 on success, -errno otherwise.
- */
-static int ata_request_legacy_irqs(struct ata_host *host,
-				   irq_handler_t const *handler,
-				   const unsigned int *irq_flags,
-				   void * const *dev_id)
-{
-	struct device *gdev = host->dev;
-	struct ata_legacy_devres *legacy_dr;
-	int i, rc;
-
-	legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL);
-	BUG_ON(!legacy_dr);
-
-	for (i = 0; i < 2; i++) {
-		unsigned int irq;
-
-		/* FIXME: ATA_*_IRQ() should take generic device not pci_dev */
-		if (i == 0)
-			irq = ATA_PRIMARY_IRQ(to_pci_dev(gdev));
-		else
-			irq = ATA_SECONDARY_IRQ(to_pci_dev(gdev));
-
-		if (!(legacy_dr->mask & (1 << i)))
-			continue;
-
-		if (!handler[i]) {
-			dev_printk(KERN_ERR, gdev,
-				   "NULL handler specified for port %d\n", i);
-			rc = -EINVAL;
-			goto err_out;
-		}
-
-		rc = request_irq(irq, handler[i], irq_flags[i], DRV_NAME,
-				 dev_id[i]);
-		if (rc) {
-			dev_printk(KERN_ERR, gdev,
-				"irq %u request failed (errno=%d)\n", irq, rc);
-			goto err_out;
-		}
-
-		/* record irq allocation in legacy_dr */
-		legacy_dr->irq[i] = irq;
-		legacy_dr->irq_dev_id[i] = dev_id[i];
-
-		/* only used to print info */
-		if (i == 0)
-			host->irq = irq;
-		else
-			host->irq2 = irq;
-	}
-
-	return 0;
-
- err_out:
-	ata_legacy_free_irqs(legacy_dr);
-	return rc;
-}
-
 /**
  *	ata_pci_init_one - Initialize/register PCI IDE host controller
  *	@pdev: Controller to be initialized
@@ -1008,35 +818,11 @@
 #endif
 	}
 
-	/* alloc and init host */
-	host = ata_host_alloc_pinfo(dev, ppi, 2);
-	if (!host) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "failed to allocate ATA host\n");
-		rc = -ENOMEM;
+	/* prepare host */
+	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
+	if (rc)
 		goto err_out;
-	}
 
-	if (!legacy_mode) {
-		rc = ata_pci_init_native_host(host);
-		if (rc)
-			goto err_out;
-	} else {
-		int was_busy = 0;
-
-		rc = ata_init_legacy_host(host, &was_busy);
-		if (was_busy)
-			pcim_pin_device(pdev);
-		if (rc)
-			goto err_out;
-
-		/* request respective PCI regions, may fail */
-		rc = pci_request_region(pdev, 1, DRV_NAME);
-		rc = pci_request_region(pdev, 3, DRV_NAME);
-	}
-
-	/* init BMDMA, may fail */
-	ata_pci_init_bmdma(host);
 	pci_set_master(pdev);
 
 	/* start host and request IRQ */
@@ -1044,19 +830,31 @@
 	if (rc)
 		goto err_out;
 
-	if (!legacy_mode)
+	if (!legacy_mode) {
 		rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
 				      IRQF_SHARED, DRV_NAME, host);
-	else {
-		irq_handler_t handler[2] = { host->ops->irq_handler,
-					     host->ops->irq_handler };
-		unsigned int irq_flags[2] = { IRQF_SHARED, IRQF_SHARED };
-		void *dev_id[2] = { host, host };
+		if (rc)
+			goto err_out;
+		host->irq = pdev->irq;
+	} else {
+		if (!ata_port_is_dummy(host->ports[0])) {
+			host->irq = ATA_PRIMARY_IRQ(pdev);
+			rc = devm_request_irq(dev, host->irq,
+					      pi->port_ops->irq_handler,
+					      IRQF_SHARED, DRV_NAME, host);
+			if (rc)
+				goto err_out;
+		}
 
-		rc = ata_request_legacy_irqs(host, handler, irq_flags, dev_id);
+		if (!ata_port_is_dummy(host->ports[1])) {
+			host->irq2 = ATA_SECONDARY_IRQ(pdev);
+			rc = devm_request_irq(dev, host->irq2,
+					      pi->port_ops->irq_handler,
+					      IRQF_SHARED, DRV_NAME, host);
+			if (rc)
+				goto err_out;
+		}
 	}
-	if (rc)
-		goto err_out;
 
 	/* register */
 	rc = ata_host_register(host, pi->sht);
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 5e24666..ba17fc5 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -98,17 +98,15 @@
 
 /* libata-acpi.c */
 #ifdef CONFIG_ATA_ACPI
-extern int ata_acpi_exec_tfs(struct ata_port *ap);
-extern int ata_acpi_push_id(struct ata_device *dev);
+extern void ata_acpi_associate(struct ata_host *host);
+extern int ata_acpi_on_suspend(struct ata_port *ap);
+extern void ata_acpi_on_resume(struct ata_port *ap);
+extern int ata_acpi_on_devcfg(struct ata_device *adev);
 #else
-static inline int ata_acpi_exec_tfs(struct ata_port *ap)
-{
-	return 0;
-}
-static inline int ata_acpi_push_id(struct ata_device *dev)
-{
-	return 0;
-}
+static inline void ata_acpi_associate(struct ata_host *host) { }
+static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
+static inline void ata_acpi_on_resume(struct ata_port *ap) { }
+static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; }
 #endif
 
 /* libata-scsi.c */
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 3c55a5f..0104367 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -455,23 +455,21 @@
 
 static void ali_init_chipset(struct pci_dev *pdev)
 {
-	u8 rev, tmp;
+	u8 tmp;
 	struct pci_dev *north, *isa_bridge;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
 	/*
 	 * The chipset revision selects the driver operations and
 	 * mode data.
 	 */
 
-	if (rev >= 0x20 && rev < 0xC2) {
+	if (pdev->revision >= 0x20 && pdev->revision < 0xC2) {
 		/* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
 		pci_read_config_byte(pdev, 0x4B, &tmp);
 		/* Clear CD-ROM DMA write bit */
 		tmp &= 0x7F;
 		pci_write_config_byte(pdev, 0x4B, tmp);
-	} else if (rev >= 0xC2) {
+	} else if (pdev->revision >= 0xC2) {
 		/* Enable cable detection logic */
 		pci_read_config_byte(pdev, 0x4B, &tmp);
 		pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
@@ -483,21 +481,21 @@
 		/* Configure the ALi bridge logic. For non ALi rely on BIOS.
 		   Set the south bridge enable bit */
 		pci_read_config_byte(isa_bridge, 0x79, &tmp);
-		if (rev == 0xC2)
+		if (pdev->revision == 0xC2)
 			pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
-		else if (rev > 0xC2 && rev < 0xC5)
+		else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
 			pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
 	}
-	if (rev >= 0x20) {
+	if (pdev->revision >= 0x20) {
 		/*
 		 * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
 		 * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
 		 * via 0x54/55.
 		 */
 		pci_read_config_byte(pdev, 0x53, &tmp);
-		if (rev <= 0x20)
+		if (pdev->revision <= 0x20)
 			tmp &= ~0x02;
-		if (rev >= 0xc7)
+		if (pdev->revision >= 0xc7)
 			tmp |= 0x03;
 		else
 			tmp |= 0x01;	/* CD_ROM enable for DMA */
@@ -520,14 +518,14 @@
 {
 	static const struct ata_port_info info_early = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &ali_early_port_ops
 	};
 	/* Revision 0x20 added DMA */
 	static const struct ata_port_info info_20 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &ali_20_port_ops
@@ -535,7 +533,7 @@
 	/* Revision 0x20 with support logic added UDMA */
 	static const struct ata_port_info info_20_udma = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,	/* UDMA33 */
@@ -544,60 +542,58 @@
 	/* Revision 0xC2 adds UDMA66 */
 	static const struct ata_port_info info_c2 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &ali_c2_port_ops
 	};
-	/* Revision 0xC3 is UDMA100 */
+	/* Revision 0xC3 is UDMA66 for now */
 	static const struct ata_port_info info_c3 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &ali_c2_port_ops
 	};
-	/* Revision 0xC4 is UDMA133 */
+	/* Revision 0xC4 is UDMA100 */
 	static const struct ata_port_info info_c4 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &ali_c2_port_ops
 	};
 	/* Revision 0xC5 is UDMA133 with LBA48 DMA */
 	static const struct ata_port_info info_c5 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &ali_c5_port_ops
 	};
 
 	const struct ata_port_info *ppi[] = { NULL, NULL };
-	u8 rev, tmp;
+	u8 tmp;
 	struct pci_dev *isa_bridge;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
 	/*
 	 * The chipset revision selects the driver operations and
 	 * mode data.
 	 */
 
-	if (rev < 0x20) {
+	if (pdev->revision < 0x20) {
 		ppi[0] = &info_early;
-	} else if (rev < 0xC2) {
+	} else if (pdev->revision < 0xC2) {
         	ppi[0] = &info_20;
-	} else if (rev == 0xC2) {
+	} else if (pdev->revision == 0xC2) {
         	ppi[0] = &info_c2;
-	} else if (rev == 0xC3) {
+	} else if (pdev->revision == 0xC3) {
         	ppi[0] = &info_c3;
-	} else if (rev == 0xC4) {
+	} else if (pdev->revision == 0xC4) {
         	ppi[0] = &info_c4;
 	} else
         	ppi[0] = &info_c5;
@@ -605,7 +601,7 @@
 	ali_init_chipset(pdev);
 
 	isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
-	if (isa_bridge && rev >= 0x20 && rev < 0xC2) {
+	if (isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
 		/* Are we paired with a UDMA capable chip */
 		pci_read_config_byte(isa_bridge, 0x5E, &tmp);
 		if ((tmp & 0x1E) == 0x12)
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index b439351..b09faca 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -541,7 +541,7 @@
 	static const struct ata_port_info info[10] = {
 		{	/* 0: AMD 7401 */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,	/* No SWDMA */
 			.udma_mask = 0x07,	/* UDMA 33 */
@@ -549,91 +549,89 @@
 		},
 		{	/* 1: Early AMD7409 - no swdma */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x1f,	/* UDMA 66 */
+			.udma_mask = ATA_UDMA4,	/* UDMA 66 */
 			.port_ops = &amd66_port_ops
 		},
 		{	/* 2: AMD 7409, no swdma errata */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x1f,	/* UDMA 66 */
+			.udma_mask = ATA_UDMA4,	/* UDMA 66 */
 			.port_ops = &amd66_port_ops
 		},
 		{	/* 3: AMD 7411 */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100 */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
 			.port_ops = &amd100_port_ops
 		},
 		{	/* 4: AMD 7441 */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100 */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
 			.port_ops = &amd100_port_ops
 		},
 		{	/* 5: AMD 8111*/
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x7f,	/* UDMA 133, no swdma */
+			.udma_mask = ATA_UDMA6,	/* UDMA 133, no swdma */
 			.port_ops = &amd133_port_ops
 		},
 		{	/* 6: AMD 8111 UDMA 100 (Serenade) */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100, no swdma */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100, no swdma */
 			.port_ops = &amd133_port_ops
 		},
 		{	/* 7: Nvidia Nforce */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100 */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
 			.port_ops = &nv100_port_ops
 		},
 		{	/* 8: Nvidia Nforce2 and later */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x7f,	/* UDMA 133, no swdma */
+			.udma_mask = ATA_UDMA6,	/* UDMA 133, no swdma */
 			.port_ops = &nv133_port_ops
 		},
 		{	/* 9: AMD CS5536 (Geode companion) */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100 */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
 			.port_ops = &amd100_port_ops
 		}
 	};
 	const struct ata_port_info *ppi[] = { NULL, NULL };
 	static int printed_version;
 	int type = id->driver_data;
-	u8 rev;
 	u8 fifo;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
 	pci_read_config_byte(pdev, 0x41, &fifo);
 
 	/* Check for AMD7409 without swdma errata and if found adjust type */
-	if (type == 1 && rev > 0x7)
+	if (type == 1 && pdev->revision > 0x7)
 		type = 2;
 
 	/* Check for AMD7411 */
@@ -693,6 +691,8 @@
 	{ PCI_VDEVICE(NVIDIA,	PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE),	8 },
 	{ PCI_VDEVICE(NVIDIA,	PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE),	8 },
 	{ PCI_VDEVICE(NVIDIA,	PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE),	8 },
+	{ PCI_VDEVICE(NVIDIA,	PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE),	8 },
+	{ PCI_VDEVICE(NVIDIA,	PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE),	8 },
 	{ PCI_VDEVICE(AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE),		9 },
 
 	{ },
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 9861059..ce589d9 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -28,7 +28,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_artop"
-#define DRV_VERSION	"0.4.2"
+#define DRV_VERSION	"0.4.3"
 
 /*
  *	The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -97,9 +97,9 @@
  *	artop6260_cable_detect	-	identify cable type
  *	@ap: Port
  *
- *	Identify the cable type for the ARTOp interface in question
+ *	Identify the cable type for the ARTOP interface in question
  */
- 
+
 static int artop6260_cable_detect(struct ata_port *ap)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
@@ -416,7 +416,7 @@
 	static int printed_version;
 	static const struct ata_port_info info_6210 = {
 		.sht		= &artop_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask 	= ATA_UDMA2,
@@ -424,7 +424,7 @@
 	};
 	static const struct ata_port_info info_626x = {
 		.sht		= &artop_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask 	= ATA_UDMA4,
@@ -432,7 +432,7 @@
 	};
 	static const struct ata_port_info info_626x_fast = {
 		.sht		= &artop_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask 	= ATA_UDMA5,
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 8449146..80509be 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -270,7 +270,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &atiixp_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x06,	/* No MWDMA0 support */
 		.udma_mask = 0x3F,
@@ -285,6 +285,7 @@
 	{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), },
 	{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), },
 	{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), },
+	{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), },
 
 	{ },
 };
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index ed00fa9..0feb5ae 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -107,7 +107,7 @@
 		pci_write_config_byte(pdev, arttim + 1, (t.active << 4) | t.recover);
 	} else {
 		/* Save the shared timings for channel, they will be loaded
-		   by qc_issue_prot. Reloading the setup time is expensive 
+		   by qc_issue_prot. Reloading the setup time is expensive
 		   so we keep a merged one loaded */
 		pci_read_config_byte(pdev, ARTIM23, &reg);
 		reg &= 0x3F;
@@ -231,7 +231,7 @@
 	pci_write_config_byte(pdev, CMDTIM, 0);
 	/* 512 byte bursts (sector) */
 	pci_write_config_byte(pdev, BRST, 0x40);
-	/* 
+	/*
 	 * A reporter a long time ago
 	 * Had problems with the data fifo
 	 * So don't run the risk
@@ -251,7 +251,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &cmd640_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &cmd640_port_ops
 	};
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 2a79b33..dc443e7 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -31,7 +31,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_cmd64x"
-#define DRV_VERSION "0.2.2"
+#define DRV_VERSION "0.2.3"
 
 /*
  * CMD64x specific registers definition.
@@ -380,21 +380,21 @@
 	static const struct ata_port_info cmd_info[6] = {
 		{	/* CMD 643 - no UDMA */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.port_ops = &cmd64x_port_ops
 		},
 		{	/* CMD 646 with broken UDMA */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.port_ops = &cmd64x_port_ops
 		},
 		{	/* CMD 646 with working UDMA */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA1,
@@ -402,14 +402,14 @@
 		},
 		{	/* CMD 646 rev 1  */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.port_ops = &cmd646r1_port_ops
 		},
 		{	/* CMD 648 */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA2,
@@ -417,7 +417,7 @@
 		},
 		{	/* CMD 649 */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA3,
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 83bcc5b..6bf037d 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -41,7 +41,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_cs5520"
-#define DRV_VERSION	"0.6.4"
+#define DRV_VERSION	"0.6.5"
 
 struct pio_clocks
 {
@@ -146,7 +146,7 @@
 	.queuecommand		= ata_scsi_queuecmd,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= LIBATA_MAX_PRD,
+	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
 	.use_clustering		= ATA_SHT_USE_CLUSTERING,
@@ -178,7 +178,7 @@
 	.bmdma_start		= ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
-	.qc_prep		= ata_qc_prep,
+	.qc_prep		= ata_dumb_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_data_xfer,
 
@@ -284,6 +284,11 @@
 				      ata_interrupt, 0, DRV_NAME, host);
 		if (rc)
 			return rc;
+
+		if (i == 0)
+			host->irq = irq[0];
+		else
+			host->irq2 = irq[1];
 	}
 
 	return ata_host_register(host, &cs5520_sht);
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 1b67923..68f150a 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -35,7 +35,7 @@
 #include <linux/dmi.h>
 
 #define DRV_NAME	"pata_cs5530"
-#define DRV_VERSION	"0.7.2"
+#define DRV_VERSION	"0.7.3"
 
 static void __iomem *cs5530_port_base(struct ata_port *ap)
 {
@@ -167,7 +167,7 @@
 	.queuecommand		= ata_scsi_queuecmd,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= LIBATA_MAX_PRD,
+	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
 	.use_clustering		= ATA_SHT_USE_CLUSTERING,
@@ -201,7 +201,7 @@
 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
 	.cable_detect	= ata_cable_40wire,
 
-	.qc_prep 	= ata_qc_prep,
+	.qc_prep 	= ata_dumb_qc_prep,
 	.qc_issue	= cs5530_qc_issue_prot,
 
 	.data_xfer	= ata_data_xfer,
@@ -266,7 +266,7 @@
 	}
 
 	pci_set_master(cs5530_0);
-	pci_set_mwi(cs5530_0);
+	pci_try_set_mwi(cs5530_0);
 
 	/*
 	 * Set PCI CacheLineSize to 16-bytes:
@@ -337,7 +337,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &cs5530_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,
@@ -346,7 +346,7 @@
 	/* The docking connector doesn't do UDMA, and it seems not MWDMA */
 	static const struct ata_port_info info_palmax_secondary = {
 		.sht = &cs5530_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &cs5530_port_ops
 	};
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index f37d4cd..360b6f3 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -39,7 +39,7 @@
 #include <asm/msr.h>
 
 #define DRV_NAME	"cs5535"
-#define DRV_VERSION	"0.2.11"
+#define DRV_VERSION	"0.2.12"
 
 /*
  *	The Geode (Aka Athlon GX now) uses an internal MSR based
@@ -225,10 +225,10 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &cs5535_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &cs5535_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index 27b9f29..6cbc877 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -18,7 +18,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_cypress"
-#define DRV_VERSION "0.1.4"
+#define DRV_VERSION "0.1.5"
 
 /* here are the offset definitions for the registers */
 
@@ -167,7 +167,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &cy82c693_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &cy82c693_port_ops
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 079248a..c8ba59c 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -303,7 +303,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &efar_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma1-2 */
 		.udma_mask 	= 0x0f, /* UDMA 66 */
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index c6c8a8b..6f7d34a 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -220,32 +220,6 @@
 	return ATA_CBL_PATA80;
 }
 
-static int hpt36x_pre_reset(struct ata_port *ap, unsigned long deadline)
-{
-	static const struct pci_bits hpt36x_enable_bits[] = {
-		{ 0x50, 1, 0x04, 0x04 },
-		{ 0x54, 1, 0x04, 0x04 }
-	};
-	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
-	if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no]))
-		return -ENOENT;
-
-	return ata_std_prereset(ap, deadline);
-}
-
-/**
- *	hpt36x_error_handler	-	reset the hpt36x bus
- *	@ap: ATA port to reset
- *
- *	Perform the reset handling for the 366/368
- */
-
-static void hpt36x_error_handler(struct ata_port *ap)
-{
-	ata_bmdma_drive_eh(ap, hpt36x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *	hpt366_set_piomode		-	PIO setup
  *	@ap: ATA interface
@@ -351,7 +325,7 @@
 
 	.freeze		= ata_bmdma_freeze,
 	.thaw		= ata_bmdma_thaw,
-	.error_handler	= hpt36x_error_handler,
+	.error_handler	= ata_bmdma_error_handler,
 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
 	.cable_detect	= hpt36x_cable_detect,
 
@@ -419,10 +393,10 @@
 {
 	static const struct ata_port_info info_hpt366 = {
 		.sht = &hpt36x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &hpt366_port_ops
 	};
 	struct ata_port_info info = info_hpt366;
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 5a0a410..b0af65a 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -26,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt37x"
-#define DRV_VERSION	"0.6.5"
+#define DRV_VERSION	"0.6.6"
 
 struct hpt_clock {
 	u8	xfer_speed;
@@ -889,25 +889,25 @@
 	/* HPT370 - UDMA100 */
 	static const struct ata_port_info info_hpt370 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370_port_ops
 	};
 	/* HPT370A - UDMA100 */
 	static const struct ata_port_info info_hpt370a = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370a_port_ops
 	};
 	/* HPT370 - UDMA100 */
 	static const struct ata_port_info info_hpt370_33 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x0f,
@@ -916,7 +916,7 @@
 	/* HPT370A - UDMA100 */
 	static const struct ata_port_info info_hpt370a_33 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x0f,
@@ -925,28 +925,19 @@
 	/* HPT371, 372 and friends - UDMA133 */
 	static const struct ata_port_info info_hpt372 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &hpt372_port_ops
 	};
-	/* HPT371, 372 and friends - UDMA100 at 50MHz clock */
-	static const struct ata_port_info info_hpt372_50 = {
-		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
-		.pio_mask = 0x1f,
-		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
-		.port_ops = &hpt372_port_ops
-	};
-	/* HPT374 - UDMA133 */
+	/* HPT374 - UDMA100 */
 	static const struct ata_port_info info_hpt374 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt374_port_ops
 	};
 
@@ -961,7 +952,7 @@
 	u8 mcr1;
 	u32 freq;
 	int prefer_dpll = 1;
-	
+
 	unsigned long iobase = pci_resource_start(dev, 4);
 
 	const struct hpt_chip *chip_table;
@@ -1055,7 +1046,7 @@
 	 */
 
 	pci_write_config_byte(dev, 0x5b, 0x23);
-	
+
 	/*
 	 * HighPoint does this for HPT372A.
 	 * NOTE: This register is only writeable via I/O space.
@@ -1088,7 +1079,7 @@
 	 *	Turn the frequency check into a band and then find a timing
 	 *	table to match it.
 	 */
-	 
+
 	clock_slot = hpt37x_clock_slot(freq, chip_table->base);
 	if (chip_table->clocks[clock_slot] == NULL || prefer_dpll) {
 		/*
@@ -1098,17 +1089,21 @@
 		 *	use a 50MHz DPLL by choice
 		 */
 		unsigned int f_low, f_high;
-		int adjust;
-		
-		clock_slot = 2;
+		int dpll, adjust;
+
+		/* Compute DPLL */
+		dpll = 2;
 		if (port->udma_mask & 0xE0)
-			clock_slot = 3;
-		
-		f_low = (MHz[clock_slot] * chip_table->base) / 192;
+			dpll = 3;
+
+		f_low = (MHz[clock_slot] * 48) / MHz[dpll];
 		f_high = f_low + 2;
+		if (clock_slot > 1)
+			f_high += 2;
 
 		/* Select the DPLL clock. */
 		pci_write_config_byte(dev, 0x5b, 0x21);
+		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
 
 		for(adjust = 0; adjust < 8; adjust++) {
 			if (hpt37x_calibrate_dpll(dev))
@@ -1124,12 +1119,12 @@
 			printk(KERN_WARNING "hpt37x: DPLL did not stabilize.\n");
 			return -ENODEV;
 		}
-		if (clock_slot == 3)
+		if (dpll == 3)
 			private_data = (void *)hpt37x_timings_66;
 		else
 			private_data = (void *)hpt37x_timings_50;
 
-		printk(KERN_INFO "hpt37x: Bus clock %dMHz, using DPLL.\n", MHz[clock_slot]);
+		printk(KERN_INFO "hpt37x: Bus clock %dMHz, using DPLL.\n", MHz[dpll]);
 	} else {
 		private_data = (void *)chip_table->clocks[clock_slot];
 		/*
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index f25154a..aa29cde 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -490,10 +490,10 @@
 	/* HPT372N and friends - UDMA133 */
 	static const struct ata_port_info info = {
 		.sht = &hpt3x2n_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &hpt3x2n_port_ops
 	};
 	struct ata_port_info port = info;
@@ -521,8 +521,8 @@
 			/* 371N if rev > 1 */
 			break;
 		case PCI_DEVICE_ID_TTI_HPT372:
-			/* 372N if rev >= 1*/
-			if (class_rev == 0)
+			/* 372N if rev >= 2*/
+			if (class_rev < 2)
 				return -ENODEV;
 			break;
 		case PCI_DEVICE_ID_TTI_HPT302:
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index bbabe79..be0f05e 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -23,7 +23,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt3x3"
-#define DRV_VERSION	"0.4.2"
+#define DRV_VERSION	"0.5.3"
 
 /**
  *	hpt3x3_set_piomode		-	PIO setup
@@ -52,6 +52,7 @@
 	pci_write_config_dword(pdev, 0x48, r2);
 }
 
+#if defined(CONFIG_PATA_HPT3X3_DMA)
 /**
  *	hpt3x3_set_dmamode		-	DMA timing setup
  *	@ap: ATA interface
@@ -59,6 +60,9 @@
  *
  *	Set up the channel for MWDMA or UDMA modes. Much the same as with
  *	PIO, load the mode number and then set MWDMA or UDMA flag.
+ *
+ *	0x44 : bit 0-2 master mode, 3-5 slave mode, etc
+ *	0x48 : bit 4/0 DMA/UDMA bit 5/1 for slave etc
  */
 
 static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
@@ -76,13 +80,26 @@
 	r2 &= ~(0x11 << dn);	/* Clear MWDMA and UDMA bits */
 
 	if (adev->dma_mode >= XFER_UDMA_0)
-		r2 |= 0x01 << dn;	/* Ultra mode */
+		r2 |= (0x10 << dn);	/* Ultra mode */
 	else
-		r2 |= 0x10 << dn;	/* MWDMA */
+		r2 |= (0x01 << dn);	/* MWDMA */
 
 	pci_write_config_dword(pdev, 0x44, r1);
 	pci_write_config_dword(pdev, 0x48, r2);
 }
+#endif /* CONFIG_PATA_HPT3X3_DMA */
+
+/**
+ *	hpt3x3_atapi_dma	-	ATAPI DMA check
+ *	@qc: Queued command
+ *
+ *	Just say no - we don't do ATAPI DMA
+ */
+
+static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
+{
+	return 1;
+}
 
 static struct scsi_host_template hpt3x3_sht = {
 	.module			= THIS_MODULE,
@@ -105,7 +122,9 @@
 static struct ata_port_operations hpt3x3_port_ops = {
 	.port_disable	= ata_port_disable,
 	.set_piomode	= hpt3x3_set_piomode,
+#if defined(CONFIG_PATA_HPT3X3_DMA)
 	.set_dmamode	= hpt3x3_set_dmamode,
+#endif
 	.mode_filter	= ata_pci_default_filter,
 
 	.tf_load	= ata_tf_load,
@@ -124,6 +143,7 @@
 	.bmdma_start 	= ata_bmdma_start,
 	.bmdma_stop	= ata_bmdma_stop,
 	.bmdma_status 	= ata_bmdma_status,
+	.check_atapi_dma= hpt3x3_atapi_dma,
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
@@ -158,32 +178,79 @@
 		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
 }
 
-
 /**
  *	hpt3x3_init_one		-	Initialise an HPT343/363
- *	@dev: PCI device
+ *	@pdev: PCI device
  *	@id: Entry in match table
  *
- *	Perform basic initialisation. The chip has a quirk that it won't
- *	function unless it is at XX00. The old ATA driver touched this up
- *	but we leave it for pci quirks to do properly.
+ *	Perform basic initialisation. We set the device up so we access all
+ *	ports via BAR4. This is neccessary to work around errata.
  */
 
-static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht = &hpt3x3_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
+#if defined(CONFIG_PATA_HPT3X3_DMA)
+		/* Further debug needed */
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,
+#endif
 		.port_ops = &hpt3x3_port_ops
 	};
+	/* Register offsets of taskfiles in BAR4 area */
+	static const u8 offset_cmd[2] = { 0x20, 0x28 };
+	static const u8 offset_ctl[2] = { 0x36, 0x3E };
 	const struct ata_port_info *ppi[] = { &info, NULL };
+	struct ata_host *host;
+	int i, rc;
+	void __iomem *base;
 
-	hpt3x3_init_chipset(dev);
-	/* Now kick off ATA set up */
-	return ata_pci_init_one(dev, ppi);
+	hpt3x3_init_chipset(pdev);
+
+	if (!printed_version++)
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
+	if (!host)
+		return -ENOMEM;
+	/* acquire resources and fill host */
+	rc = pcim_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	/* Everything is relative to BAR4 if we set up this way */
+	rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
+	host->iomap = pcim_iomap_table(pdev);
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		return rc;
+	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		return rc;
+
+	base = host->iomap[4];	/* Bus mastering base */
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_ioports *ioaddr = &host->ports[i]->ioaddr;
+
+		ioaddr->cmd_addr = base + offset_cmd[i];
+		ioaddr->altstatus_addr =
+		ioaddr->ctl_addr = base + offset_ctl[i];
+		ioaddr->scr_addr = NULL;
+		ata_std_ports(ioaddr);
+		ioaddr->bmdma_addr = base + 8 * i;
+	}
+	pci_set_master(pdev);
+	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+				 &hpt3x3_sht);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index c791a46..321d98b 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -530,7 +530,7 @@
 
 		ap->pio_mask = 0x1f;
 		ap->mwdma_mask = info->mwdma_mask;
-		ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+		ap->flags |= ATA_FLAG_SLAVE_POSS;
 		ap->ops = &pata_icside_port_ops;
 
 		pata_icside_setup_ioaddr(&ap->ioaddr, info->base, info->port[i]);
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index d042efd..5525518 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -17,7 +17,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_isapnp"
-#define DRV_VERSION "0.2.0"
+#define DRV_VERSION "0.2.1"
 
 static struct scsi_host_template isapnp_sht = {
 	.module			= THIS_MODULE,
@@ -77,7 +77,6 @@
 	struct ata_host *host;
 	struct ata_port *ap;
 	void __iomem *cmd_addr, *ctl_addr;
-	int rc;
 
 	if (pnp_port_valid(idev, 0) == 0)
 		return -ENODEV;
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index a769952..b8af55e 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -19,7 +19,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_it8213"
-#define DRV_VERSION	"0.0.2"
+#define DRV_VERSION	"0.0.3"
 
 /**
  *	it8213_pre_reset	-	check for 40/80 pin
@@ -313,10 +313,10 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &it8213_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask 	= 0x1f, /* UDMA 100 */
+		.udma_mask 	= ATA_UDMA4, /* FIXME: want UDMA 100? */
 		.port_ops	= &it8213_ops,
 	};
 	/* Current IT8213 stuff is single port */
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index ff9a6fd..430673b 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -1,7 +1,8 @@
 /*
- * ata-it821x.c 	- IT821x PATA for new ATA layer
+ * pata_it821x.c 	- IT821x PATA for new ATA layer
  *			  (C) 2005 Red Hat Inc
  *			  Alan Cox <alan@redhat.com>
+ *			  (C) 2007 Bartlomiej Zolnierkiewicz
  *
  * based upon
  *
@@ -65,7 +66,6 @@
  *
  *  TODO
  *	-	ATAPI and other speed filtering
- *	-	Command filter in smart mode
  *	-	RAID configuration ioctls
  */
 
@@ -80,7 +80,7 @@
 
 
 #define DRV_NAME "pata_it821x"
-#define DRV_VERSION "0.3.6"
+#define DRV_VERSION "0.3.7"
 
 struct it821x_dev
 {
@@ -461,14 +461,8 @@
 
 static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused)
 {
-	int dma_enabled = 0;
 	int i;
 
-	/* Bits 5 and 6 indicate if DMA is active on master/slave */
-	/* It is possible that BMDMA isn't allocated */
-	if (ap->ioaddr.bmdma_addr)
-		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
 		if (ata_dev_enabled(dev)) {
@@ -477,7 +471,7 @@
 			dev->dma_mode = XFER_MW_DMA_0;
 			/* We do need the right mode information for DMA or PIO
 			   and this comes from the current configuration flags */
-			if (dma_enabled & (1 << (5 + i))) {
+			if (ata_id_has_dma(dev->id)) {
 				ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
 				dev->xfer_mode = XFER_MW_DMA_0;
 				dev->xfer_shift = ATA_SHIFT_MWDMA;
@@ -593,8 +587,7 @@
 	itdev->want[1][1] = ATA_ANY;
 	itdev->last_device = -1;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &conf);
-	if (conf == 0x10) {
+	if (pdev->revision == 0x11) {
 		itdev->timing10 = 1;
 		/* Need to disable ATAPI DMA for this case */
 		if (!itdev->smart)
@@ -696,7 +689,7 @@
 	.port_start	= it821x_port_start,
 };
 
-static void __devinit it821x_disable_raid(struct pci_dev *pdev)
+static void it821x_disable_raid(struct pci_dev *pdev)
 {
 	/* Reset local CPU, and set BIOS not ready */
 	pci_write_config_byte(pdev, 0x5E, 0x01);
@@ -720,17 +713,17 @@
 
 	static const struct ata_port_info info_smart = {
 		.sht = &it821x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &it821x_smart_port_ops
 	};
 	static const struct ata_port_info info_passthru = {
 		.sht = &it821x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &it821x_passthru_port_ops
 	};
 
@@ -800,7 +793,7 @@
 
 
 module_param_named(noraid, it8212_noraid, int, S_IRUGO);
-MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode");
+MODULE_PARM_DESC(noraid, "Force card into bypass mode");
 
 module_init(it821x_init);
 module_exit(it821x_exit);
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index b994351..4ca7fd6 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -1,13 +1,14 @@
 /*
  * ixp4xx PATA/Compact Flash driver
- * Copyright (c) 2006 Tower Technologies
+ * Copyright (C) 2006-07 Tower Technologies
  * Author: Alessandro Zummo <a.zummo@towertech.it>
  *
  * An ATA driver to handle a Compact Flash connected
  * to the ixp4xx expansion bus in TrueIDE mode. The CF
  * must have it chip selects connected to two CS lines
- * on the ixp4xx. The interrupt line is optional, if not
- * specified the driver will run in polling mode.
+ * on the ixp4xx. In the irq is not available, you might
+ * want to modify both this driver and libata to run in
+ * polling mode.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -23,7 +24,7 @@
 #include <scsi/scsi_host.h>
 
 #define DRV_NAME	"pata_ixp4xx_cf"
-#define DRV_VERSION	"0.1.2"
+#define DRV_VERSION	"0.2"
 
 static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error)
 {
@@ -42,13 +43,6 @@
 	return 0;
 }
 
-static void ixp4xx_phy_reset(struct ata_port *ap)
-{
-	ap->cbl = ATA_CBL_PATA40;
-	ata_port_probe(ap);
-	ata_bus_reset(ap);
-}
-
 static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
 				unsigned int buflen, int write_data)
 {
@@ -56,7 +50,7 @@
 	unsigned int words = buflen >> 1;
 	u16 *buf16 = (u16 *) buf;
 	struct ata_port *ap = adev->ap;
-	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+	void __iomem *mmio = ap->ioaddr.data_addr;
 	struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
 
 	/* set the expansion bus in 16bit mode and restore
@@ -92,10 +86,6 @@
 	*data->cs0_cfg |= 0x01;
 }
 
-static void ixp4xx_irq_clear(struct ata_port *ap)
-{
-}
-
 static struct scsi_host_template ixp4xx_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
@@ -115,29 +105,32 @@
 };
 
 static struct ata_port_operations ixp4xx_port_ops = {
-	.set_mode	= ixp4xx_set_mode,
-	.mode_filter	= ata_pci_default_filter,
+	.set_mode		= ixp4xx_set_mode,
+	.mode_filter		= ata_pci_default_filter,
 
-	.port_disable	= ata_port_disable,
-	.tf_load	= ata_tf_load,
-	.tf_read	= ata_tf_read,
-	.check_status 	= ata_check_status,
-	.exec_command	= ata_exec_command,
-	.dev_select 	= ata_std_dev_select,
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.exec_command		= ata_exec_command,
+	.check_status 		= ata_check_status,
+	.dev_select 		= ata_std_dev_select,
 
-	.qc_prep 	= ata_qc_prep,
-	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
-	.data_xfer	= ixp4xx_mmio_data_xfer,
-	.cable_detect	= ata_cable_40wire,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 
-	.irq_clear	= ixp4xx_irq_clear,
-	.irq_on		= ata_irq_on,
-	.irq_ack	= ata_irq_ack,
+	.qc_prep 		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ixp4xx_mmio_data_xfer,
+	.cable_detect		= ata_cable_40wire,
 
-	.port_start	= ata_port_start,
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_dummy_irq_ack,
 
-	.phy_reset	= ixp4xx_phy_reset,
+	.port_start		= ata_port_start,
 };
 
 static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
@@ -178,7 +171,6 @@
 	struct ata_host *host;
 	struct ata_port *ap;
 	struct ixp4xx_pata_data *data = pdev->dev.platform_data;
-	int rc;
 
 	cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -211,10 +203,6 @@
 	ap->pio_mask = 0x1f; /* PIO4 */
 	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
 
-	/* run in polling mode if no irq has been assigned */
-	if (!irq)
-		ap->flags |= ATA_FLAG_PIO_POLLING;
-
 	ixp4xx_setup_port(&ap->ioaddr, data);
 
 	dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 8d799e8..4d67f23 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -19,7 +19,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_jmicron"
-#define DRV_VERSION	"0.1.4"
+#define DRV_VERSION	"0.1.5"
 
 typedef enum {
 	PORT_PATA0 = 0,
@@ -193,11 +193,11 @@
 {
 	static const struct ata_port_info info = {
 		.sht		= &jmicron_sht,
-		.flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags	= ATA_FLAG_SLAVE_POSS,
 
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask 	= 0x3f,
+		.udma_mask 	= ATA_UDMA5,
 
 		.port_ops	= &jmicron_ops,
 	};
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 7070992..edffc25 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -64,7 +64,7 @@
 #include <linux/platform_device.h>
 
 #define DRV_NAME "pata_legacy"
-#define DRV_VERSION "0.5.4"
+#define DRV_VERSION "0.5.5"
 
 #define NR_HOST 6
 
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index edbfe0d..87594c0 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -163,22 +163,22 @@
 {
 	static const struct ata_port_info info = {
 		.sht		= &marvell_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask 	= 0x3f,
+		.udma_mask 	= ATA_UDMA5,
 
 		.port_ops	= &marvell_ops,
 	};
 	static const struct ata_port_info info_sata = {
 		.sht		= &marvell_sht,
 		/* Slave possible as its magically mapped not real */
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask 	= 0x7f,
+		.udma_mask 	= ATA_UDMA6,
 
 		.port_ops	= &marvell_ops,
 	};
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 368fac7..182e83c 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -467,13 +467,27 @@
 static int
 mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
 {
-	return 0;	/* FIXME : What to do here ? */
+	struct ata_host *host = dev_get_drvdata(&op->dev);
+
+	return ata_host_suspend(host, state);
 }
 
 static int
 mpc52xx_ata_resume(struct of_device *op)
 {
-	return 0;	/* FIXME : What to do here ? */
+	struct ata_host *host = dev_get_drvdata(&op->dev);
+	struct mpc52xx_ata_priv *priv = host->private_data;
+	int rv;
+
+	rv = mpc52xx_ata_hw_init(priv);
+	if (rv) {
+		printk(KERN_ERR DRV_NAME ": Error during HW init\n");
+		return rv;
+	}
+
+	ata_host_resume(host);
+
+	return 0;
 }
 
 #endif
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 81f5634..40eb574 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -94,12 +94,12 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &netcell_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		/* Actually we don't really care about these as the
 		   firmware deals with it */
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask 	= 0x3f, /* UDMA 133 */
+		.udma_mask 	= ATA_UDMA5, /* UDMA 133 */
 		.port_ops	= &netcell_ops,
 	};
 	const struct ata_port_info *port_info[] = { &info, NULL };
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index ea70ec7..2f5d714 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -193,7 +193,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &ns87410_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x0F,
 		.port_ops = &ns87410_port_ops
 	};
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 29c23dd..091a70a 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -291,7 +291,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &oldpiix_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma1-2 */
 		.port_ops	= &oldpiix_pata_ops,
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 1c44653..458bf67 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -218,7 +218,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &opti_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &opti_port_ops
 	};
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 3093b02..f89bdfd 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -484,14 +484,14 @@
 {
 	static const struct ata_port_info info_82c700 = {
 		.sht = &optidma_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &optidma_port_ops
 	};
 	static const struct ata_port_info info_82c700_udma = {
 		.sht = &optidma_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 4d44c75..a56257c9 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -129,7 +129,7 @@
 	.irq_on		= ata_irq_on,
 	.irq_ack	= ata_irq_ack,
 
-	.port_start	= ata_port_start,
+	.port_start	= ata_sff_port_start,
 };
 
 #define CS_CHECK(fn, ret) \
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 0d2cc49..69a5aa4 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -689,10 +689,12 @@
 	void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR];
 	u32 scr;
 	long start_count, end_count;
-	long pll_clock;
+	struct timeval start_time, end_time;
+	long pll_clock, usec_elapsed;
 
 	/* Read current counter value */
 	start_count = pdc_read_counter(host);
+	do_gettimeofday(&start_time);
 
 	/* Start the test mode */
 	scr = readl(mmio_base + PDC_SYS_CTL);
@@ -705,6 +707,7 @@
 
 	/* Read the counter values again */
 	end_count = pdc_read_counter(host);
+	do_gettimeofday(&end_time);
 
 	/* Stop the test mode */
 	scr = readl(mmio_base + PDC_SYS_CTL);
@@ -713,7 +716,11 @@
 	readl(mmio_base + PDC_SYS_CTL); /* flush */
 
 	/* calculate the input clock in Hz */
-	pll_clock = (start_count - end_count) * 10;
+	usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
+		(end_time.tv_usec - start_time.tv_usec);
+
+	pll_clock = (start_count - end_count) / 100 *
+		(100000000 / usec_elapsed);
 
 	PDPRINTK("start[%ld] end[%ld] \n", start_count, end_count);
 	PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock);
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index edbaf9d..92447bed 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -31,8 +31,8 @@
 
 	pci_read_config_word(pdev, 0x50, &cis);
 	if (cis & (1 << (10 + ap->port_no)))
-		return ATA_CBL_PATA80;
-	return ATA_CBL_PATA40;
+		return ATA_CBL_PATA40;
+	return ATA_CBL_PATA80;
 }
 
 /**
@@ -320,7 +320,7 @@
 	static const struct ata_port_info info[3] = {
 		{
 			.sht = &pdc202xx_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA2,
@@ -328,7 +328,7 @@
 		},
 		{
 			.sht = &pdc202xx_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA4,
@@ -336,7 +336,7 @@
 		},
 		{
 			.sht = &pdc202xx_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA5,
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 1f63848..79f841b 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -22,7 +22,7 @@
 #include <linux/pata_platform.h>
 
 #define DRV_NAME "pata_platform"
-#define DRV_VERSION "0.1.2"
+#define DRV_VERSION "1.0"
 
 static int pio_mask = 1;
 
@@ -139,6 +139,7 @@
 	struct resource *io_res, *ctl_res;
 	struct ata_host *host;
 	struct ata_port *ap;
+	struct pata_platform_info *pp_info;
 	unsigned int mmio;
 
 	/*
@@ -208,11 +209,12 @@
 
 	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
 
-	pata_platform_setup_port(&ap->ioaddr, pdev->dev.platform_data);
+	pp_info = (struct pata_platform_info *)(pdev->dev.platform_data);
+	pata_platform_setup_port(&ap->ioaddr, pp_info);
 
 	/* activate */
 	return ata_host_activate(host, platform_get_irq(pdev, 0), ata_interrupt,
-				 0, &pata_platform_sht);
+				 pp_info->irq_flags, &pata_platform_sht);
 }
 
 /**
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index fb8c9e1..1998c19 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -26,7 +26,7 @@
 #include <linux/platform_device.h>
 
 #define DRV_NAME "pata_qdi"
-#define DRV_VERSION "0.3.0"
+#define DRV_VERSION "0.3.1"
 
 #define NR_HOST 4	/* Two 6580s */
 
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index ba96b54..7d1aabe 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -257,7 +257,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &radisys_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma1-2 */
 		.udma_mask	= 0x14, /* UDMA33/66 only */
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 2bfd7ef..7632fcb 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -21,7 +21,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_rz1000"
-#define DRV_VERSION	"0.2.3"
+#define DRV_VERSION	"0.2.4"
 
 
 /**
@@ -133,7 +133,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht = &rz1000_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &rz1000_port_ops
 	};
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 225013e..b8b2d11 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -40,7 +40,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sc1200"
-#define DRV_VERSION	"0.2.4"
+#define DRV_VERSION	"0.2.5"
 
 #define SC1200_REV_A	0x00
 #define SC1200_REV_B1	0x01
@@ -185,7 +185,7 @@
 	.queuecommand		= ata_scsi_queuecmd,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= LIBATA_MAX_PRD,
+	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
 	.use_clustering		= ATA_SHT_USE_CLUSTERING,
@@ -219,7 +219,7 @@
 	.bmdma_stop	= ata_bmdma_stop,
 	.bmdma_status 	= ata_bmdma_status,
 
-	.qc_prep 	= ata_qc_prep,
+	.qc_prep 	= ata_dumb_qc_prep,
 	.qc_issue	= sc1200_qc_issue_prot,
 
 	.data_xfer	= ata_data_xfer,
@@ -245,7 +245,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &sc1200_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 844e53b..c55667e 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -43,7 +43,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME		"pata_scc"
-#define DRV_VERSION		"0.1"
+#define DRV_VERSION		"0.2"
 
 #define PCI_DEVICE_ID_TOSHIBA_SCC_ATA		0x01b4
 
@@ -238,6 +238,12 @@
 	else
 		offset = 0;	/* 100MHz */
 
+	/* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */
+	if (adev->class == ATA_DEV_ATAPI && speed > XFER_UDMA_4) {
+		printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
+		speed = XFER_UDMA_4;
+	}
+
 	if (speed >= XFER_UDMA_0)
 		idx = speed - XFER_UDMA_0;
 	else
@@ -489,23 +495,26 @@
  *	Note: Original code is ata_bus_post_reset().
  */
 
-static void scc_bus_post_reset (struct ata_port *ap, unsigned int devmask)
+static int scc_bus_post_reset(struct ata_port *ap, unsigned int devmask,
+                              unsigned long deadline)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int dev0 = devmask & (1 << 0);
 	unsigned int dev1 = devmask & (1 << 1);
-	unsigned long timeout;
+	int rc;
 
 	/* if device 0 was found in ata_devchk, wait for its
 	 * BSY bit to clear
 	 */
-	if (dev0)
-		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+	if (dev0) {
+		rc = ata_wait_ready(ap, deadline);
+		if (rc && rc != -ENODEV)
+			return rc;
+	}
 
 	/* if device 1 was found in ata_devchk, wait for
 	 * register access, then wait for BSY to clear
 	 */
-	timeout = jiffies + ATA_TMOUT_BOOT;
 	while (dev1) {
 		u8 nsect, lbal;
 
@@ -514,14 +523,15 @@
 		lbal = in_be32(ioaddr->lbal_addr);
 		if ((nsect == 1) && (lbal == 1))
 			break;
-		if (time_after(jiffies, timeout)) {
-			dev1 = 0;
-			break;
-		}
+		if (time_after(jiffies, deadline))
+			return -EBUSY;
 		msleep(50);	/* give drive a breather */
 	}
-	if (dev1)
-		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+	if (dev1) {
+		rc = ata_wait_ready(ap, deadline);
+		if (rc && rc != -ENODEV)
+			return rc;
+	}
 
 	/* is all this really necessary? */
 	ap->ops->dev_select(ap, 0);
@@ -529,6 +539,8 @@
 		ap->ops->dev_select(ap, 1);
 	if (dev0)
 		ap->ops->dev_select(ap, 0);
+
+	return 0;
 }
 
 /**
@@ -537,8 +549,8 @@
  *	Note: Original code is ata_bus_softreset().
  */
 
-static unsigned int scc_bus_softreset (struct ata_port *ap,
-				       unsigned int devmask)
+static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
+                                      unsigned long deadline)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
@@ -570,7 +582,7 @@
 	if (scc_check_status(ap) == 0xFF)
 		return 0;
 
-	scc_bus_post_reset(ap, devmask);
+	scc_bus_post_reset(ap, devmask, deadline);
 
 	return 0;
 }
@@ -579,11 +591,13 @@
  *	scc_std_softreset - reset host port via ATA SRST
  *	@ap: port to reset
  *	@classes: resulting classes of attached devices
+ *	@deadline: deadline jiffies for the operation
  *
  *	Note: Original code is ata_std_softreset().
  */
 
-static int scc_std_softreset (struct ata_port *ap, unsigned int *classes)
+static int scc_std_softreset (struct ata_port *ap, unsigned int *classes,
+                              unsigned long deadline)
 {
 	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
 	unsigned int devmask = 0, err_mask;
@@ -607,7 +621,7 @@
 
 	/* issue bus reset */
 	DPRINTK("about to softreset, devmask=%x\n", devmask);
-	err_mask = scc_bus_softreset(ap, devmask);
+	err_mask = scc_bus_softreset(ap, devmask, deadline);
 	if (err_mask) {
 		ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
 				err_mask);
@@ -676,10 +690,11 @@
 
 		if (reg & INTSTS_BMSINT) {
 			unsigned int classes;
+			unsigned long deadline = jiffies + ATA_TMOUT_BOOT;
 			printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME);
 			out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT);
 			/* TBD: SW reset */
-			scc_std_softreset(ap, &classes);
+			scc_std_softreset(ap, &classes, deadline);
 			continue;
 		}
 
@@ -715,22 +730,36 @@
 
 static u8 scc_bmdma_status (struct ata_port *ap)
 {
-	u8 host_stat;
 	void __iomem *mmio = ap->ioaddr.bmdma_addr;
+	u8 host_stat = in_be32(mmio + SCC_DMA_STATUS);
+	u32 int_status = in_be32(mmio + SCC_DMA_INTST);
+	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+	static int retry = 0;
 
-	host_stat = in_be32(mmio + SCC_DMA_STATUS);
+	/* return if IOS_SS is cleared */
+	if (!(in_be32(mmio + SCC_DMA_CMD) & ATA_DMA_START))
+		return host_stat;
 
-	/* Workaround for PTERADD: emulate DMA_INTR when
-	 * - IDE_STATUS[ERR] = 1
-	 * - INT_STATUS[INTRQ] = 1
-	 * - DMA_STATUS[IORACTA] = 1
-	 */
-	if (!(host_stat & ATA_DMA_INTR)) {
-		u32 int_status = in_be32(mmio + SCC_DMA_INTST);
-		if (ata_altstatus(ap) & ATA_ERR &&
-		    int_status & INTSTS_INTRQ &&
-		    host_stat & ATA_DMA_ACTIVE)
-			host_stat |= ATA_DMA_INTR;
+	/* errata A252,A308 workaround: Step4 */
+	if (ata_altstatus(ap) & ATA_ERR && int_status & INTSTS_INTRQ)
+		return (host_stat | ATA_DMA_INTR);
+
+	/* errata A308 workaround Step5 */
+	if (int_status & INTSTS_IOIRQS) {
+		host_stat |= ATA_DMA_INTR;
+
+		/* We don't check ATAPI DMA because it is limited to UDMA4 */
+		if ((qc->tf.protocol == ATA_PROT_DMA &&
+		     qc->dev->xfer_mode > XFER_UDMA_4)) {
+			if (!(int_status & INTSTS_ACTEINT)) {
+				printk(KERN_WARNING "ata%u: data lost occurred. (ACTEINT==0, retry:%d)\n",
+				       ap->print_id, retry);
+				host_stat |= ATA_DMA_ERR;
+				if (retry++)
+					ap->udma_mask >>= 1;
+			} else
+				retry = 0;
+		}
 	}
 
 	return host_stat;
@@ -862,9 +891,10 @@
 /**
  *	scc_pata_prereset - prepare for reset
  *	@ap: ATA port to be reset
+ *	@deadline: deadline jiffies for the operation
  */
 
-static int scc_pata_prereset (struct ata_port *ap, unsigned long deadline)
+static int scc_pata_prereset(struct ata_port *ap, unsigned long deadline)
 {
 	ap->cbl = ATA_CBL_PATA80;
 	return ata_std_prereset(ap, deadline);
@@ -882,10 +912,6 @@
 {
 	DPRINTK("ENTER\n");
 
-	/* re-enable interrupts */
-	if (!ap->ops->error_handler)
-		ap->ops->irq_on(ap);
-
 	/* is double-select really necessary? */
 	if (classes[0] != ATA_DEV_NONE)
 		ap->ops->dev_select(ap, 1);
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index dee6e21..8969154 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -41,7 +41,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_serverworks"
-#define DRV_VERSION "0.4.0"
+#define DRV_VERSION "0.4.1"
 
 #define SVWKS_CSB5_REVISION_NEW	0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
 #define SVWKS_CSB6_REVISION	0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
@@ -410,11 +410,8 @@
 
 static int serverworks_fixup_csb(struct pci_dev *pdev)
 {
-	u8 rev;
 	u8 btr;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
 	/* Third Channel Test */
 	if (!(PCI_FUNC(pdev->devfn) & 1)) {
 		struct pci_dev * findev = NULL;
@@ -456,7 +453,7 @@
 	if (!(PCI_FUNC(pdev->devfn) & 1))
 		btr |= 0x2;
 	else
-		btr |= (rev >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
+		btr |= (pdev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
 	pci_write_config_byte(pdev, 0x5A, btr);
 
 	return btr;
@@ -478,31 +475,31 @@
 	static const struct ata_port_info info[4] = {
 		{ /* OSB4 */
 			.sht = &serverworks_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = 0x07,
 			.port_ops = &serverworks_osb4_port_ops
 		}, { /* OSB4 no UDMA */
 			.sht = &serverworks_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = 0x00,
 			.port_ops = &serverworks_osb4_port_ops
 		}, { /* CSB5 */
 			.sht = &serverworks_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x1f,
+			.udma_mask = ATA_UDMA4,
 			.port_ops = &serverworks_csb_port_ops
 		}, { /* CSB5 - later revisions*/
 			.sht = &serverworks_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,
+			.udma_mask = ATA_UDMA5,
 			.port_ops = &serverworks_csb_port_ops
 		}
 	};
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 440e2cb..b0cd52d 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -35,6 +35,8 @@
 #define DRV_NAME "pata_sil680"
 #define DRV_VERSION "0.4.6"
 
+#define SIL680_MMIO_BAR		5
+
 /**
  *	sil680_selreg		-	return register base
  *	@hwif: interface
@@ -293,8 +295,8 @@
 
 	pci_read_config_byte(pdev, 0x8A, &tmpbyte);
 
-	printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
-			tmpbyte & 1, tmpbyte & 0x30);
+	dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
+		tmpbyte & 1, tmpbyte & 0x30);
 
 	switch(tmpbyte & 0x30) {
 		case 0x00:
@@ -315,8 +317,8 @@
 	}
 
 	pci_read_config_byte(pdev,   0x8A, &tmpbyte);
-	printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
-			tmpbyte & 1, tmpbyte & 0x30);
+	dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
+		tmpbyte & 1, tmpbyte & 0x30);
 
 	pci_write_config_byte(pdev,  0xA1, 0x72);
 	pci_write_config_word(pdev,  0xA2, 0x328A);
@@ -339,22 +341,23 @@
 	return tmpbyte & 0x30;
 }
 
-static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit sil680_init_one(struct pci_dev *pdev,
+				     const struct pci_device_id *id)
 {
 	static const struct ata_port_info info = {
 		.sht = &sil680_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &sil680_port_ops
 	};
 	static const struct ata_port_info info_slow = {
 		.sht = &sil680_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &sil680_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index f223126..9a829a7 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -73,14 +73,14 @@
 }
 
 /**
- *	sis_port_base		-	return PCI configuration base for dev
+ *	sis_old_port_base		-	return PCI configuration base for dev
  *	@adev: device
  *
  *	Returns the base of the PCI configuration registers for this port
  *	number.
  */
 
-static int sis_port_base(struct ata_device *adev)
+static int sis_old_port_base(struct ata_device *adev)
 {
 	return  0x40 + (4 * adev->ap->port_no) +  (2 * adev->devno);
 }
@@ -149,6 +149,9 @@
 	if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
 		return -ENOENT;
 
+	/* Clear the FIFO settings. We can't enable the FIFO until
+	   we know we are poking at a disk */
+	pci_write_config_byte(pdev, 0x4B, 0);
 	return ata_std_prereset(ap, deadline);
 }
 
@@ -211,7 +214,7 @@
 static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
 	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
-	int port = sis_port_base(adev);
+	int port = sis_old_port_base(adev);
 	u8 t1, t2;
 	int speed = adev->pio_mode - XFER_PIO_0;
 
@@ -248,7 +251,7 @@
 static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
 	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
-	int port = sis_port_base(adev);
+	int port = sis_old_port_base(adev);
 	int speed = adev->pio_mode - XFER_PIO_0;
 
 	const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
@@ -328,7 +331,7 @@
 {
 	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
-	int drive_pci = sis_port_base(adev);
+	int drive_pci = sis_old_port_base(adev);
 	u16 timing;
 
 	const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 };
@@ -367,7 +370,7 @@
 {
 	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
-	int drive_pci = sis_port_base(adev);
+	int drive_pci = sis_old_port_base(adev);
 	u16 timing;
 
 	const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 };
@@ -378,12 +381,12 @@
 	if (adev->dma_mode < XFER_UDMA_0) {
 		/* bits 3-0 hold recovery timing bits 8-10 active timing and
 		   the higer bits are dependant on the device, bit 15 udma */
-		timing &= ~ 0x870F;
+		timing &= ~0x870F;
 		timing |= mwdma_bits[speed];
 	} else {
 		/* Bit 15 is UDMA on/off, bit 12-14 are cycle time */
 		speed = adev->dma_mode - XFER_UDMA_0;
-		timing &= ~0x6000;
+		timing &= ~0xF000;
 		timing |= udma_bits[speed];
 	}
 	pci_write_config_word(pdev, drive_pci, timing);
@@ -405,22 +408,22 @@
 {
 	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
-	int drive_pci = sis_port_base(adev);
-	u16 timing;
+	int drive_pci = sis_old_port_base(adev);
+	u8 timing;
 
-	const u16 udma_bits[]  = { 0x8B00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100};
+	const u8 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
 
-	pci_read_config_word(pdev, drive_pci, &timing);
+	pci_read_config_byte(pdev, drive_pci + 1, &timing);
 
 	if (adev->dma_mode < XFER_UDMA_0) {
 		/* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
 	} else {
-		/* Bit 15 is UDMA on/off, bit 12-14 are cycle time */
+		/* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
 		speed = adev->dma_mode - XFER_UDMA_0;
-		timing &= ~0x0F00;
+		timing &= ~0x8F;
 		timing |= udma_bits[speed];
 	}
-	pci_write_config_word(pdev, drive_pci, timing);
+	pci_write_config_byte(pdev, drive_pci + 1, timing);
 }
 
 /**
@@ -440,22 +443,22 @@
 {
 	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
-	int drive_pci = sis_port_base(adev);
-	u16 timing;
+	int drive_pci = sis_old_port_base(adev);
+	u8 timing;
+	/* Low 4 bits are timing */
+	static const u8 udma_bits[]  = { 0x8F, 0x8A, 0x87, 0x85, 0x83, 0x82, 0x81};
 
-	static const u16 udma_bits[]  = { 0x8F00, 0x8A00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100};
-
-	pci_read_config_word(pdev, drive_pci, &timing);
+	pci_read_config_byte(pdev, drive_pci + 1, &timing);
 
 	if (adev->dma_mode < XFER_UDMA_0) {
 		/* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
 	} else {
-		/* Bit 15 is UDMA on/off, bit 12-14 are cycle time */
+		/* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
 		speed = adev->dma_mode - XFER_UDMA_0;
-		timing &= ~0x0F00;
+		timing &= ~0x8F;
 		timing |= udma_bits[speed];
 	}
-	pci_write_config_word(pdev, drive_pci, timing);
+	pci_write_config_byte(pdev, drive_pci + 1, timing);
 }
 
 /**
@@ -560,6 +563,40 @@
 	.port_start		= ata_port_start,
 };
 
+static const struct ata_port_operations sis_133_for_sata_ops = {
+	.port_disable		= ata_port_disable,
+	.set_piomode		= sis_133_set_piomode,
+	.set_dmamode		= sis_133_set_dmamode,
+	.mode_filter		= ata_pci_default_filter,
+
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
+
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+	.cable_detect		= sis_133_cable_detect,
+
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
+	.bmdma_stop		= ata_bmdma_stop,
+	.bmdma_status		= ata_bmdma_status,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_data_xfer,
+
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
+
+	.port_start		= ata_port_start,
+};
+
 static const struct ata_port_operations sis_133_early_ops = {
 	.port_disable		= ata_port_disable,
 	.set_piomode		= sis_100_set_piomode,
@@ -698,7 +735,7 @@
 
 static const struct ata_port_info sis_info = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.mwdma_mask	= 0x07,
 	.udma_mask	= 0,
@@ -706,7 +743,7 @@
 };
 static const struct ata_port_info sis_info33 = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.mwdma_mask	= 0x07,
 	.udma_mask	= ATA_UDMA2,	/* UDMA 33 */
@@ -714,42 +751,49 @@
 };
 static const struct ata_port_info sis_info66 = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.udma_mask	= ATA_UDMA4,	/* UDMA 66 */
 	.port_ops	= &sis_66_ops,
 };
 static const struct ata_port_info sis_info100 = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.udma_mask	= ATA_UDMA5,
 	.port_ops	= &sis_100_ops,
 };
 static const struct ata_port_info sis_info100_early = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.udma_mask	= ATA_UDMA5,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.port_ops	= &sis_66_ops,
 };
-const struct ata_port_info sis_info133 = {
+static const struct ata_port_info sis_info133 = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_ops,
 };
-static const struct ata_port_info sis_info133_early = {
+const struct ata_port_info sis_info133_for_sata = {
 	.sht		= &sis_sht,
 	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.udma_mask	= ATA_UDMA6,
+	.port_ops	= &sis_133_for_sata_ops,
+};
+static const struct ata_port_info sis_info133_early = {
+	.sht		= &sis_sht,
+	.flags		= ATA_FLAG_SLAVE_POSS,
+	.pio_mask	= 0x1f,	/* pio0-4 */
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_early_ops,
 };
 
 /* Privately shared with the SiS180 SATA driver, not for use elsewhere */
-EXPORT_SYMBOL_GPL(sis_info133);
+EXPORT_SYMBOL_GPL(sis_info133_for_sata);
 
 static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
 {
@@ -887,9 +931,7 @@
 		if (host != NULL) {
 			chipset = sets;			/* Match found */
 			if (sets->device == 0x630) {	/* SIS630 */
-				u8 host_rev;
-				pci_read_config_byte(host, PCI_REVISION_ID, &host_rev);
-				if (host_rev >= 0x30)	/* 630 ET */
+				if (host->revision >= 0x30)	/* 630 ET */
 					chipset = &sis100_early;
 			}
 			break;
@@ -933,7 +975,6 @@
 		u16 trueid;
 		u8 prefctl;
 		u8 idecfg;
-		u8 sbrev;
 
 		/* Try the second unmasking technique */
 		pci_read_config_byte(pdev, 0x4a, &idecfg);
@@ -946,11 +987,10 @@
 			lpc_bridge = pci_get_slot(pdev->bus, 0x10); /* Bus 0 Dev 2 Fn 0 */
 			if (lpc_bridge == NULL)
 				break;
-			pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
 			pci_read_config_byte(pdev, 0x49, &prefctl);
 			pci_dev_put(lpc_bridge);
 
-			if (sbrev == 0x10 && (prefctl & 0x80)) {
+			if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
 				chipset = &sis133_early;
 				break;
 			}
@@ -975,6 +1015,7 @@
 static const struct pci_device_id sis_pci_tbl[] = {
 	{ PCI_VDEVICE(SI, 0x5513), },	/* SiS 5513 */
 	{ PCI_VDEVICE(SI, 0x5518), },	/* SiS 5518 */
+	{ PCI_VDEVICE(SI, 0x1180), },	/* SiS 1180 */
 
 	{ }
 };
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index f48491a..8c2813a 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -26,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_sl82c105"
-#define DRV_VERSION "0.3.0"
+#define DRV_VERSION "0.3.1"
 
 enum {
 	/*
@@ -270,7 +270,6 @@
 static int sl82c105_bridge_revision(struct pci_dev *pdev)
 {
 	struct pci_dev *bridge;
-	u8 rev;
 
 	/*
 	 * The bridge should be part of the same device, but function 0.
@@ -292,10 +291,8 @@
 	/*
 	 * We need to find function 0's revision, not function 1
 	 */
-	pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
-
 	pci_dev_put(bridge);
-	return rev;
+	return bridge->revision;
 }
 
 
@@ -303,14 +300,14 @@
 {
 	static const struct ata_port_info info_dma = {
 		.sht = &sl82c105_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &sl82c105_port_ops
 	};
 	static const struct ata_port_info info_early = {
 		.sht = &sl82c105_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &sl82c105_port_ops
 	};
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index b1d3076..af21f44 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -235,7 +235,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &triflex_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &triflex_port_ops
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index e4c71f7..f645fe2 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -60,6 +60,7 @@
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
+#include <linux/dmi.h>
 
 #define DRV_NAME "pata_via"
 #define DRV_VERSION "0.3.1"
@@ -122,6 +123,31 @@
 	{ NULL }
 };
 
+
+/*
+ *	Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+	{
+		.ident = "Acer Ferrari 3400",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),
+			DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),
+		},
+	},
+	{ }
+};
+
+static int via_cable_override(struct pci_dev *pdev)
+{
+	/* Systems by DMI */
+	if (dmi_check_system(cable_dmi_table))
+		return 1;
+	return 0;
+}
+
+
 /**
  *	via_cable_detect	-	cable detection
  *	@ap: ATA port
@@ -139,6 +165,9 @@
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u32 ata66;
 
+	if (via_cable_override(pdev))
+		return ATA_CBL_PATA40_SHORT;
+
 	/* Early chips are 40 wire */
 	if ((config->flags & VIA_UDMA) < VIA_UDMA_66)
 		return ATA_CBL_PATA40;
@@ -423,7 +452,7 @@
 	/* Early VIA without UDMA support */
 	static const struct ata_port_info via_mwdma_info = {
 		.sht = &via_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &via_port_ops
@@ -431,7 +460,7 @@
 	/* Ditto with IRQ masking required */
 	static const struct ata_port_info via_mwdma_info_borked = {
 		.sht = &via_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &via_port_ops_noirq,
@@ -439,37 +468,37 @@
 	/* VIA UDMA 33 devices (and borked 66) */
 	static const struct ata_port_info via_udma33_info = {
 		.sht = &via_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7,
+		.udma_mask = ATA_UDMA2,
 		.port_ops = &via_port_ops
 	};
 	/* VIA UDMA 66 devices */
 	static const struct ata_port_info via_udma66_info = {
 		.sht = &via_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &via_port_ops
 	};
 	/* VIA UDMA 100 devices */
 	static const struct ata_port_info via_udma100_info = {
 		.sht = &via_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &via_port_ops
 	};
 	/* UDMA133 with bad AST (All current 133) */
 	static const struct ata_port_info via_udma133_info = {
 		.sht = &via_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,	/* FIXME: should check north bridge */
+		.udma_mask = ATA_UDMA6,	/* FIXME: should check north bridge */
 		.port_ops = &via_port_ops
 	};
 	struct ata_port_info type;
@@ -477,7 +506,6 @@
 	struct pci_dev *isa = NULL;
 	const struct via_isa_bridge *config;
 	static int printed_version;
-	u8 t;
 	u8 enable;
 	u32 timing;
 
@@ -491,9 +519,8 @@
 			!!(config->flags & VIA_BAD_ID),
 			config->id, NULL))) {
 
-			pci_read_config_byte(isa, PCI_REVISION_ID, &t);
-			if (t >= config->rev_min &&
-			    t <= config->rev_max)
+			if (isa->revision >= config->rev_min &&
+			    isa->revision <= config->rev_max)
 				break;
 			pci_dev_put(isa);
 		}
@@ -592,10 +619,11 @@
 #endif
 
 static const struct pci_device_id via[] = {
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), },
+	{ PCI_VDEVICE(VIA, 0x0571), },
+	{ PCI_VDEVICE(VIA, 0x0581), },
+	{ PCI_VDEVICE(VIA, 0x1571), },
+	{ PCI_VDEVICE(VIA, 0x3164), },
+	{ PCI_VDEVICE(VIA, 0x5324), },
 
 	{ },
 };
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index cc4ad27..83abfec 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 
 #define DRV_NAME "pata_winbond"
-#define DRV_VERSION "0.0.2"
+#define DRV_VERSION "0.0.3"
 
 #define NR_HOST 4	/* Two winbond controllers, two channels each */
 
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 52b6953..bec1de5 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -44,7 +44,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pdc_adma"
-#define DRV_VERSION	"0.05"
+#define DRV_VERSION	"0.06"
 
 /* macro to calculate base address for ATA regs */
 #define ADMA_ATA_REGS(base,port_no)	((base) + ((port_no) * 0x40))
@@ -145,32 +145,32 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.can_queue		= ATA_DEF_QUEUE,
-	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= LIBATA_MAX_PRD,
-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
-	.emulated		= ATA_SHT_EMULATED,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.proc_name		= DRV_NAME,
-	.dma_boundary		= ADMA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.proc_name		= DRV_NAME,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.dma_boundary		= ADMA_DMA_BOUNDARY,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.emulated		= ATA_SHT_EMULATED,
 };
 
 static const struct ata_port_operations adma_ata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
-	.check_status		= ata_check_status,
-	.check_atapi_dma	= adma_check_atapi_dma,
 	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
 	.dev_select		= ata_std_dev_select,
 	.phy_reset		= adma_phy_reset,
+	.check_atapi_dma	= adma_check_atapi_dma,
+	.data_xfer		= ata_data_xfer,
 	.qc_prep		= adma_qc_prep,
 	.qc_issue		= adma_qc_issue,
 	.eng_timeout		= adma_eng_timeout,
-	.data_xfer		= ata_data_xfer,
 	.irq_clear		= adma_irq_clear,
 	.irq_on			= ata_irq_on,
 	.irq_ack		= ata_irq_ack,
@@ -188,7 +188,7 @@
 				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
 				  ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x10, /* pio4 */
-		.udma_mask	= 0x1f, /* udma0-4 */
+		.udma_mask	= ATA_UDMA4,
 		.port_ops	= &adma_ata_ops,
 	},
 };
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index bda5e77..3de1834 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -28,7 +28,7 @@
 #include <scsi/scsi_device.h>
 
 #define DRV_NAME	"sata_inic162x"
-#define DRV_VERSION	"0.1"
+#define DRV_VERSION	"0.2"
 
 enum {
 	MMIO_BAR		= 5,
@@ -192,7 +192,7 @@
 
 static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg)
 {
-	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	void __iomem *scr_addr = ap->ioaddr.scr_addr;
 	void __iomem *addr;
 	u32 val;
 
@@ -210,7 +210,7 @@
 
 static void inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
 {
-	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	void __iomem *scr_addr = ap->ioaddr.scr_addr;
 	void __iomem *addr;
 
 	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
@@ -496,6 +496,13 @@
 	/* inic can only handle upto LBA28 max sectors */
 	if (dev->max_sectors > ATA_MAX_SECTORS)
 		dev->max_sectors = ATA_MAX_SECTORS;
+
+	if (dev->n_sectors >= 1 << 28) {
+		ata_dev_printk(dev, KERN_ERR,
+	"ERROR: This driver doesn't support LBA48 yet and may cause\n"
+	"                data corruption on such devices.  Disabling.\n");
+		ata_dev_disable(dev);
+	}
 }
 
 static void init_port(struct ata_port *ap)
@@ -587,7 +594,7 @@
 	.flags			= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
 	.pio_mask		= 0x1f,	/* pio0-4 */
 	.mwdma_mask		= 0x07, /* mwdma0-2 */
-	.udma_mask		= 0x7f,	/* udma0-6 */
+	.udma_mask		= ATA_UDMA6,
 	.port_ops		= &inic_port_ops
 };
 
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index cb9b9ac..fb8a749 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -21,6 +21,45 @@
  *
  */
 
+/*
+  sata_mv TODO list:
+
+  1) Needs a full errata audit for all chipsets.  I implemented most
+  of the errata workarounds found in the Marvell vendor driver, but
+  I distinctly remember a couple workarounds (one related to PCI-X)
+  are still needed.
+
+  4) Add NCQ support (easy to intermediate, once new-EH support appears)
+
+  5) Investigate problems with PCI Message Signalled Interrupts (MSI).
+
+  6) Add port multiplier support (intermediate)
+
+  7) Test and verify 3.0 Gbps support
+
+  8) Develop a low-power-consumption strategy, and implement it.
+
+  9) [Experiment, low priority] See if ATAPI can be supported using
+  "unknown FIS" or "vendor-specific FIS" support, or something creative
+  like that.
+
+  10) [Experiment, low priority] Investigate interrupt coalescing.
+  Quite often, especially with PCI Message Signalled Interrupts (MSI),
+  the overhead reduced by interrupt mitigation is quite often not
+  worth the latency cost.
+
+  11) [Experiment, Marvell value added] Is it possible to use target
+  mode to cross-connect two Linux boxes with Marvell cards?  If so,
+  creating LibATA target mode support would be very interesting.
+
+  Target mode, for those without docs, is the ability to directly
+  connect two SATA controllers.
+
+  13) Verify that 7042 is fully supported.  I only have a 6042.
+
+*/
+
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -35,7 +74,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_mv"
-#define DRV_VERSION	"0.8"
+#define DRV_VERSION	"0.81"
 
 enum {
 	/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -64,8 +103,6 @@
 	MV_SATAHC_ARBTR_REG_SZ	= MV_MINOR_REG_AREA_SZ,		/* arbiter */
 	MV_PORT_REG_SZ		= MV_MINOR_REG_AREA_SZ,
 
-	MV_USE_Q_DEPTH		= ATA_DEF_QUEUE,
-
 	MV_MAX_Q_DEPTH		= 32,
 	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
 
@@ -89,18 +126,22 @@
 	/* Host Flags */
 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
 	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
-	MV_COMMON_FLAGS		= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-				   ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
+	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+				  ATA_FLAG_PIO_POLLING,
 	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
 
 	CRQB_FLAG_READ		= (1 << 0),
 	CRQB_TAG_SHIFT		= 1,
+	CRQB_IOID_SHIFT		= 6,	/* CRQB Gen-II/IIE IO Id shift */
+	CRQB_HOSTQ_SHIFT	= 17,	/* CRQB Gen-II/IIE HostQueTag shift */
 	CRQB_CMD_ADDR_SHIFT	= 8,
 	CRQB_CMD_CS		= (0x2 << 11),
 	CRQB_CMD_LAST		= (1 << 15),
 
 	CRPB_FLAG_STATUS_SHIFT	= 8,
+	CRPB_IOID_SHIFT_6	= 5,	/* CRPB Gen-II IO Id shift */
+	CRPB_IOID_SHIFT_7	= 7,	/* CRPB Gen-IIE IO Id shift */
 
 	EPRD_FLAG_END_OF_TBL	= (1 << 31),
 
@@ -192,8 +233,10 @@
 	EDMA_ERR_DEV_DCON	= (1 << 3),
 	EDMA_ERR_DEV_CON	= (1 << 4),
 	EDMA_ERR_SERR		= (1 << 5),
-	EDMA_ERR_SELF_DIS	= (1 << 7),
+	EDMA_ERR_SELF_DIS	= (1 << 7),	/* Gen II/IIE self-disable */
+	EDMA_ERR_SELF_DIS_5	= (1 << 8),	/* Gen I self-disable */
 	EDMA_ERR_BIST_ASYNC	= (1 << 8),
+	EDMA_ERR_TRANS_IRQ_7	= (1 << 8),	/* Gen IIE transprt layer irq */
 	EDMA_ERR_CRBQ_PAR	= (1 << 9),
 	EDMA_ERR_CRPB_PAR	= (1 << 10),
 	EDMA_ERR_INTRL_PAR	= (1 << 11),
@@ -204,13 +247,33 @@
 	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),
 	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),
 	EDMA_ERR_TRANS_PROTO	= (1 << 31),
-	EDMA_ERR_FATAL		= (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
-				   EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
-				   EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
-				   EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
-				   EDMA_ERR_LNK_DATA_RX |
-				   EDMA_ERR_LNK_DATA_TX |
-				   EDMA_ERR_TRANS_PROTO),
+	EDMA_ERR_OVERRUN_5	= (1 << 5),
+	EDMA_ERR_UNDERRUN_5	= (1 << 6),
+	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
+				  EDMA_ERR_PRD_PAR |
+				  EDMA_ERR_DEV_DCON |
+				  EDMA_ERR_DEV_CON |
+				  EDMA_ERR_SERR |
+				  EDMA_ERR_SELF_DIS |
+				  EDMA_ERR_CRBQ_PAR |
+				  EDMA_ERR_CRPB_PAR |
+				  EDMA_ERR_INTRL_PAR |
+				  EDMA_ERR_IORDY |
+				  EDMA_ERR_LNK_CTRL_RX_2 |
+				  EDMA_ERR_LNK_DATA_RX |
+				  EDMA_ERR_LNK_DATA_TX |
+				  EDMA_ERR_TRANS_PROTO,
+	EDMA_EH_FREEZE_5	= EDMA_ERR_D_PAR |
+				  EDMA_ERR_PRD_PAR |
+				  EDMA_ERR_DEV_DCON |
+				  EDMA_ERR_DEV_CON |
+				  EDMA_ERR_OVERRUN_5 |
+				  EDMA_ERR_UNDERRUN_5 |
+				  EDMA_ERR_SELF_DIS_5 |
+				  EDMA_ERR_CRBQ_PAR |
+				  EDMA_ERR_CRPB_PAR |
+				  EDMA_ERR_INTRL_PAR |
+				  EDMA_ERR_IORDY,
 
 	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
 	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
@@ -238,18 +301,18 @@
 	MV_HP_ERRATA_60X1B2	= (1 << 3),
 	MV_HP_ERRATA_60X1C0	= (1 << 4),
 	MV_HP_ERRATA_XX42A0	= (1 << 5),
-	MV_HP_50XX		= (1 << 6),
-	MV_HP_GEN_IIE		= (1 << 7),
+	MV_HP_GEN_I		= (1 << 6),
+	MV_HP_GEN_II		= (1 << 7),
+	MV_HP_GEN_IIE		= (1 << 8),
 
 	/* Port private flags (pp_flags) */
 	MV_PP_FLAG_EDMA_EN	= (1 << 0),
 	MV_PP_FLAG_EDMA_DS_ACT	= (1 << 1),
+	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),
 };
 
-#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
-#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
-#define IS_GEN_I(hpriv) IS_50XX(hpriv)
-#define IS_GEN_II(hpriv) IS_60XX(hpriv)
+#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
+#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
 #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
 
 enum {
@@ -308,6 +371,10 @@
 	dma_addr_t		crpb_dma;
 	struct mv_sg		*sg_tbl;
 	dma_addr_t		sg_tbl_dma;
+
+	unsigned int		req_idx;
+	unsigned int		resp_idx;
+
 	u32			pp_flags;
 };
 
@@ -340,14 +407,15 @@
 static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
 static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
 static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
-static void mv_phy_reset(struct ata_port *ap);
-static void __mv_phy_reset(struct ata_port *ap, int can_sleep);
 static int mv_port_start(struct ata_port *ap);
 static void mv_port_stop(struct ata_port *ap);
 static void mv_qc_prep(struct ata_queued_cmd *qc);
 static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
-static void mv_eng_timeout(struct ata_port *ap);
+static void mv_error_handler(struct ata_port *ap);
+static void mv_post_int_cmd(struct ata_queued_cmd *qc);
+static void mv_eh_freeze(struct ata_port *ap);
+static void mv_eh_thaw(struct ata_port *ap);
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 
 static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
@@ -371,14 +439,31 @@
 static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
 static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
 			     unsigned int port_no);
-static void mv_stop_and_reset(struct ata_port *ap);
 
-static struct scsi_host_template mv_sht = {
+static struct scsi_host_template mv5_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.can_queue		= MV_USE_Q_DEPTH,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= MV_MAX_SG_CT,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= 1,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= MV_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct scsi_host_template mv6_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= MV_MAX_SG_CT,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
@@ -400,19 +485,21 @@
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
 
-	.phy_reset		= mv_phy_reset,
 	.cable_detect		= ata_cable_sata,
 
 	.qc_prep		= mv_qc_prep,
 	.qc_issue		= mv_qc_issue,
 	.data_xfer		= ata_data_xfer,
 
-	.eng_timeout		= mv_eng_timeout,
-
 	.irq_clear		= mv_irq_clear,
 	.irq_on			= ata_irq_on,
 	.irq_ack		= ata_irq_ack,
 
+	.error_handler		= mv_error_handler,
+	.post_internal_cmd	= mv_post_int_cmd,
+	.freeze			= mv_eh_freeze,
+	.thaw			= mv_eh_thaw,
+
 	.scr_read		= mv5_scr_read,
 	.scr_write		= mv5_scr_write,
 
@@ -429,19 +516,21 @@
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
 
-	.phy_reset		= mv_phy_reset,
 	.cable_detect		= ata_cable_sata,
 
 	.qc_prep		= mv_qc_prep,
 	.qc_issue		= mv_qc_issue,
 	.data_xfer		= ata_data_xfer,
 
-	.eng_timeout		= mv_eng_timeout,
-
 	.irq_clear		= mv_irq_clear,
 	.irq_on			= ata_irq_on,
 	.irq_ack		= ata_irq_ack,
 
+	.error_handler		= mv_error_handler,
+	.post_internal_cmd	= mv_post_int_cmd,
+	.freeze			= mv_eh_freeze,
+	.thaw			= mv_eh_thaw,
+
 	.scr_read		= mv_scr_read,
 	.scr_write		= mv_scr_write,
 
@@ -458,19 +547,21 @@
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
 
-	.phy_reset		= mv_phy_reset,
 	.cable_detect		= ata_cable_sata,
 
 	.qc_prep		= mv_qc_prep_iie,
 	.qc_issue		= mv_qc_issue,
 	.data_xfer		= ata_data_xfer,
 
-	.eng_timeout		= mv_eng_timeout,
-
 	.irq_clear		= mv_irq_clear,
 	.irq_on			= ata_irq_on,
 	.irq_ack		= ata_irq_ack,
 
+	.error_handler		= mv_error_handler,
+	.post_internal_cmd	= mv_post_int_cmd,
+	.freeze			= mv_eh_freeze,
+	.thaw			= mv_eh_thaw,
+
 	.scr_read		= mv_scr_read,
 	.scr_write		= mv_scr_write,
 
@@ -482,44 +573,44 @@
 	{  /* chip_504x */
 		.flags		= MV_COMMON_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_508x */
-		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_5080 */
-		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_604x */
-		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv6_ops,
 	},
 	{  /* chip_608x */
-		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-				   MV_FLAG_DUAL_HC),
+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+				  MV_FLAG_DUAL_HC,
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv6_ops,
 	},
 	{  /* chip_6042 */
-		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
 	},
 	{  /* chip_7042 */
-		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
 	},
 };
@@ -538,6 +629,9 @@
 
 	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
 
+	/* Adaptec 1430SA */
+	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
+
 	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
 
 	/* add Marvell 7042 support */
@@ -662,6 +756,46 @@
 {
 }
 
+static void mv_set_edma_ptrs(void __iomem *port_mmio,
+			     struct mv_host_priv *hpriv,
+			     struct mv_port_priv *pp)
+{
+	u32 index;
+
+	/*
+	 * initialize request queue
+	 */
+	index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
+
+	WARN_ON(pp->crqb_dma & 0x3ff);
+	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
+		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
+		writelfl((pp->crqb_dma & 0xffffffff) | index,
+			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+	else
+		writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+
+	/*
+	 * initialize response queue
+	 */
+	index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
+
+	WARN_ON(pp->crpb_dma & 0xff);
+	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+
+	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
+		writelfl((pp->crpb_dma & 0xffffffff) | index,
+			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+	else
+		writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+
+	writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
+		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+}
+
 /**
  *      mv_start_dma - Enable eDMA engine
  *      @base: port base address
@@ -673,9 +807,15 @@
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
+static void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv,
+			 struct mv_port_priv *pp)
 {
-	if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
+	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
+		/* clear EDMA event indicators, if any */
+		writelfl(0, base + EDMA_ERR_IRQ_CAUSE_OFS);
+
+		mv_set_edma_ptrs(base, hpriv, pp);
+
 		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
 		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
 	}
@@ -692,14 +832,14 @@
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_stop_dma(struct ata_port *ap)
+static int mv_stop_dma(struct ata_port *ap)
 {
 	void __iomem *port_mmio = mv_ap_base(ap);
 	struct mv_port_priv *pp	= ap->private_data;
 	u32 reg;
-	int i;
+	int i, err = 0;
 
-	if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
+	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
 		/* Disable EDMA if active.   The disable bit auto clears.
 		 */
 		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
@@ -711,16 +851,18 @@
 	/* now properly wait for the eDMA to stop */
 	for (i = 1000; i > 0; i--) {
 		reg = readl(port_mmio + EDMA_CMD_OFS);
-		if (!(EDMA_EN & reg)) {
+		if (!(reg & EDMA_EN))
 			break;
-		}
+
 		udelay(100);
 	}
 
-	if (EDMA_EN & reg) {
+	if (reg & EDMA_EN) {
 		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
-		/* FIXME: Consider doing a reset here to recover */
+		err = -EIO;
 	}
+
+	return err;
 }
 
 #ifdef ATA_DEBUG
@@ -837,12 +979,13 @@
 		writelfl(val, mv_ap_base(ap) + ofs);
 }
 
-static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
+static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
+			void __iomem *port_mmio)
 {
 	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
 
 	/* set up non-NCQ EDMA configuration */
-	cfg &= ~(1 << 9);	/* disable equeue */
+	cfg &= ~(1 << 9);	/* disable eQue */
 
 	if (IS_GEN_I(hpriv)) {
 		cfg &= ~0x1f;		/* clear queue depth */
@@ -862,7 +1005,7 @@
 		cfg |= (1 << 18);	/* enab early completion */
 		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
 		cfg &= ~(1 << 16);	/* dis FIS-based switching (for now) */
-		cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
+		cfg &= ~(EDMA_CFG_NCQ);	/* clear NCQ */
 	}
 
 	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
@@ -924,28 +1067,9 @@
 	pp->sg_tbl = mem;
 	pp->sg_tbl_dma = mem_dma;
 
-	mv_edma_cfg(hpriv, port_mmio);
+	mv_edma_cfg(ap, hpriv, port_mmio);
 
-	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
-	writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
-		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-
-	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
-		writelfl(pp->crqb_dma & 0xffffffff,
-			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
-	else
-		writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
-
-	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
-
-	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
-		writelfl(pp->crpb_dma & 0xffffffff,
-			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
-	else
-		writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
-
-	writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
-		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+	mv_set_edma_ptrs(port_mmio, hpriv, pp);
 
 	/* Don't turn on EDMA here...do it before DMA commands only.  Else
 	 * we'll be unable to send non-data, PIO, etc due to restricted access
@@ -1008,11 +1132,6 @@
 	return n_sg;
 }
 
-static inline unsigned mv_inc_q_index(unsigned index)
-{
-	return (index + 1) & MV_MAX_Q_DEPTH_MASK;
-}
-
 static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
 {
 	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
@@ -1041,7 +1160,7 @@
 	u16 flags = 0;
 	unsigned in_index;
 
- 	if (ATA_PROT_DMA != qc->tf.protocol)
+ 	if (qc->tf.protocol != ATA_PROT_DMA)
 		return;
 
 	/* Fill in command request block
@@ -1050,10 +1169,10 @@
 		flags |= CRQB_FLAG_READ;
 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
 	flags |= qc->tag << CRQB_TAG_SHIFT;
+	flags |= qc->tag << CRQB_IOID_SHIFT;	/* 50xx appears to ignore this*/
 
-	/* get current queue index from hardware */
-	in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
-			>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+	/* get current queue index from software */
+	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
 
 	pp->crqb[in_index].sg_addr =
 		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
@@ -1133,7 +1252,7 @@
 	unsigned in_index;
 	u32 flags = 0;
 
- 	if (ATA_PROT_DMA != qc->tf.protocol)
+ 	if (qc->tf.protocol != ATA_PROT_DMA)
 		return;
 
 	/* Fill in Gen IIE command request block
@@ -1143,10 +1262,11 @@
 
 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
 	flags |= qc->tag << CRQB_TAG_SHIFT;
+	flags |= qc->tag << CRQB_IOID_SHIFT;	/* "I/O Id" is -really-
+						   what we use as our tag */
 
-	/* get current queue index from hardware */
-	in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
-			>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+	/* get current queue index from software */
+	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
 
 	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
 	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
@@ -1194,83 +1314,41 @@
  */
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 {
-	void __iomem *port_mmio = mv_ap_base(qc->ap);
-	struct mv_port_priv *pp = qc->ap->private_data;
-	unsigned in_index;
-	u32 in_ptr;
+	struct ata_port *ap = qc->ap;
+	void __iomem *port_mmio = mv_ap_base(ap);
+	struct mv_port_priv *pp = ap->private_data;
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	u32 in_index;
 
-	if (ATA_PROT_DMA != qc->tf.protocol) {
+	if (qc->tf.protocol != ATA_PROT_DMA) {
 		/* We're about to send a non-EDMA capable command to the
 		 * port.  Turn off EDMA so there won't be problems accessing
 		 * shadow block, etc registers.
 		 */
-		mv_stop_dma(qc->ap);
+		mv_stop_dma(ap);
 		return ata_qc_issue_prot(qc);
 	}
 
-	in_ptr   = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-	in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+	mv_start_dma(port_mmio, hpriv, pp);
+
+	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
 
 	/* until we do queuing, the queue should be empty at this point */
 	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
 		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
 
-	in_index = mv_inc_q_index(in_index);	/* now incr producer index */
+	pp->req_idx++;
 
-	mv_start_dma(port_mmio, pp);
+	in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
 
 	/* and write the request in pointer to kick the EDMA to life */
-	in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
-	in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
-	writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
+		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
 
 	return 0;
 }
 
 /**
- *      mv_get_crpb_status - get status from most recently completed cmd
- *      @ap: ATA channel to manipulate
- *
- *      This routine is for use when the port is in DMA mode, when it
- *      will be using the CRPB (command response block) method of
- *      returning command completion information.  We check indices
- *      are good, grab status, and bump the response consumer index to
- *      prove that we're up to date.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static u8 mv_get_crpb_status(struct ata_port *ap)
-{
-	void __iomem *port_mmio = mv_ap_base(ap);
-	struct mv_port_priv *pp = ap->private_data;
-	unsigned out_index;
-	u32 out_ptr;
-	u8 ata_status;
-
-	out_ptr   = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
-	out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
-
-	ata_status = le16_to_cpu(pp->crpb[out_index].flags)
-					>> CRPB_FLAG_STATUS_SHIFT;
-
-	/* increment our consumer index... */
-	out_index = mv_inc_q_index(out_index);
-
-	/* and, until we do NCQ, there should only be 1 CRPB waiting */
-	WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
-		>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
-
-	/* write out our inc'd consumer index so EDMA knows we're caught up */
-	out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
-	out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
-	writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
-
-	/* Return ATA status register for completed CRPB */
-	return ata_status;
-}
-
-/**
  *      mv_err_intr - Handle error interrupts on the port
  *      @ap: ATA channel to manipulate
  *      @reset_allowed: bool: 0 == don't trigger from reset here
@@ -1284,30 +1362,191 @@
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_err_intr(struct ata_port *ap, int reset_allowed)
+static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
 {
 	void __iomem *port_mmio = mv_ap_base(ap);
-	u32 edma_err_cause, serr = 0;
+	u32 edma_err_cause, eh_freeze_mask, serr = 0;
+	struct mv_port_priv *pp = ap->private_data;
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
+	unsigned int action = 0, err_mask = 0;
+	struct ata_eh_info *ehi = &ap->eh_info;
 
-	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+	ata_ehi_clear_desc(ehi);
 
-	if (EDMA_ERR_SERR & edma_err_cause) {
+	if (!edma_enabled) {
+		/* just a guess: do we need to do this? should we
+		 * expand this, and do it in all cases?
+		 */
 		sata_scr_read(ap, SCR_ERROR, &serr);
 		sata_scr_write_flush(ap, SCR_ERROR, serr);
 	}
-	if (EDMA_ERR_SELF_DIS & edma_err_cause) {
-		struct mv_port_priv *pp	= ap->private_data;
-		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+
+	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+	ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
+
+	/*
+	 * all generations share these EDMA error cause bits
+	 */
+
+	if (edma_err_cause & EDMA_ERR_DEV)
+		err_mask |= AC_ERR_DEV;
+	if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
+			EDMA_ERR_CRBQ_PAR | EDMA_ERR_CRPB_PAR |
+			EDMA_ERR_INTRL_PAR)) {
+		err_mask |= AC_ERR_ATA_BUS;
+		action |= ATA_EH_HARDRESET;
+		ata_ehi_push_desc(ehi, ", parity error");
 	}
-	DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
-		"SERR: 0x%08x\n", ap->print_id, edma_err_cause, serr);
+	if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
+		ata_ehi_hotplugged(ehi);
+		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
+			", dev disconnect" : ", dev connect");
+	}
+
+	if (IS_GEN_I(hpriv)) {
+		eh_freeze_mask = EDMA_EH_FREEZE_5;
+
+		if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
+			struct mv_port_priv *pp	= ap->private_data;
+			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+			ata_ehi_push_desc(ehi, ", EDMA self-disable");
+		}
+	} else {
+		eh_freeze_mask = EDMA_EH_FREEZE;
+
+		if (edma_err_cause & EDMA_ERR_SELF_DIS) {
+			struct mv_port_priv *pp	= ap->private_data;
+			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+			ata_ehi_push_desc(ehi, ", EDMA self-disable");
+		}
+
+		if (edma_err_cause & EDMA_ERR_SERR) {
+			sata_scr_read(ap, SCR_ERROR, &serr);
+			sata_scr_write_flush(ap, SCR_ERROR, serr);
+			err_mask = AC_ERR_ATA_BUS;
+			action |= ATA_EH_HARDRESET;
+		}
+	}
 
 	/* Clear EDMA now that SERR cleanup done */
 	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
-	/* check for fatal here and recover if needed */
-	if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
-		mv_stop_and_reset(ap);
+	if (!err_mask) {
+		err_mask = AC_ERR_OTHER;
+		action |= ATA_EH_HARDRESET;
+	}
+
+	ehi->serror |= serr;
+	ehi->action |= action;
+
+	if (qc)
+		qc->err_mask |= err_mask;
+	else
+		ehi->err_mask |= err_mask;
+
+	if (edma_err_cause & eh_freeze_mask)
+		ata_port_freeze(ap);
+	else
+		ata_port_abort(ap);
+}
+
+static void mv_intr_pio(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+	u8 ata_status;
+
+	/* ignore spurious intr if drive still BUSY */
+	ata_status = readb(ap->ioaddr.status_addr);
+	if (unlikely(ata_status & ATA_BUSY))
+		return;
+
+	/* get active ATA command */
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (unlikely(!qc))			/* no active tag */
+		return;
+	if (qc->tf.flags & ATA_TFLAG_POLLING)	/* polling; we don't own qc */
+		return;
+
+	/* and finally, complete the ATA command */
+	qc->err_mask |= ac_err_mask(ata_status);
+	ata_qc_complete(qc);
+}
+
+static void mv_intr_edma(struct ata_port *ap)
+{
+	void __iomem *port_mmio = mv_ap_base(ap);
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	struct mv_port_priv *pp = ap->private_data;
+	struct ata_queued_cmd *qc;
+	u32 out_index, in_index;
+	bool work_done = false;
+
+	/* get h/w response queue pointer */
+	in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+			>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+	while (1) {
+		u16 status;
+
+		/* get s/w response queue last-read pointer, and compare */
+		out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
+		if (in_index == out_index)
+			break;
+
+		 
+		/* 50xx: get active ATA command */
+		if (IS_GEN_I(hpriv)) 
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+
+		/* 60xx: get active ATA command via tag, to enable support
+		 * for queueing.  this works transparently for queued and
+		 * non-queued modes.
+		 */
+		else {
+			unsigned int tag;
+
+			if (IS_GEN_II(hpriv))
+				tag = (le16_to_cpu(pp->crpb[out_index].id)
+					>> CRPB_IOID_SHIFT_6) & 0x3f;
+			else
+				tag = (le16_to_cpu(pp->crpb[out_index].id)
+					>> CRPB_IOID_SHIFT_7) & 0x3f;
+
+			qc = ata_qc_from_tag(ap, tag);
+		}
+
+		/* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
+		 * bits (WARNING: might not necessarily be associated
+		 * with this command), which -should- be clear
+		 * if all is well
+		 */
+		status = le16_to_cpu(pp->crpb[out_index].flags);
+		if (unlikely(status & 0xff)) {
+			mv_err_intr(ap, qc);
+			return;
+		}
+
+		/* and finally, complete the ATA command */
+		if (qc) {
+			qc->err_mask |=
+				ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
+			ata_qc_complete(qc);
+		}
+
+		/* advance software response queue pointer, to 
+		 * indicate (after the loop completes) to hardware
+		 * that we have consumed a response queue entry.
+		 */
+		work_done = true;
+		pp->resp_idx++;
+	}
+
+	if (work_done)
+		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
+			 (out_index << EDMA_RSP_Q_PTR_SHIFT),
+			 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 }
 
 /**
@@ -1330,10 +1569,8 @@
 {
 	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
 	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
-	struct ata_queued_cmd *qc;
 	u32 hc_irq_cause;
-	int shift, port, port0, hard_port, handled;
-	unsigned int err_mask;
+	int port, port0;
 
 	if (hc == 0)
 		port0 = 0;
@@ -1342,79 +1579,95 @@
 
 	/* we'll need the HC success int register in most cases */
 	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
-	if (hc_irq_cause)
-		writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+	if (!hc_irq_cause)
+		return;
+
+	writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
 
 	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
 		hc,relevant,hc_irq_cause);
 
 	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
-		u8 ata_status = 0;
 		struct ata_port *ap = host->ports[port];
 		struct mv_port_priv *pp = ap->private_data;
+		int have_err_bits, hard_port, shift;
 
-		hard_port = mv_hardport_from_port(port); /* range 0..3 */
-		handled = 0;	/* ensure ata_status is set if handled++ */
-
-		/* Note that DEV_IRQ might happen spuriously during EDMA,
-		 * and should be ignored in such cases.
-		 * The cause of this is still under investigation.
-		 */
-		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
-			/* EDMA: check for response queue interrupt */
-			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
-				ata_status = mv_get_crpb_status(ap);
-				handled = 1;
-			}
-		} else {
-			/* PIO: check for device (drive) interrupt */
-			if ((DEV_IRQ << hard_port) & hc_irq_cause) {
-				ata_status = readb(ap->ioaddr.status_addr);
-				handled = 1;
-				/* ignore spurious intr if drive still BUSY */
-				if (ata_status & ATA_BUSY) {
-					ata_status = 0;
-					handled = 0;
-				}
-			}
-		}
-
-		if (ap && (ap->flags & ATA_FLAG_DISABLED))
+		if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
 			continue;
 
-		err_mask = ac_err_mask(ata_status);
-
 		shift = port << 1;		/* (port * 2) */
 		if (port >= MV_PORTS_PER_HC) {
 			shift++;	/* skip bit 8 in the HC Main IRQ reg */
 		}
-		if ((PORT0_ERR << shift) & relevant) {
-			mv_err_intr(ap, 1);
-			err_mask |= AC_ERR_OTHER;
-			handled = 1;
+		have_err_bits = ((PORT0_ERR << shift) & relevant);
+
+		if (unlikely(have_err_bits)) {
+			struct ata_queued_cmd *qc;
+
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
+				continue;
+
+			mv_err_intr(ap, qc);
+			continue;
 		}
 
-		if (handled) {
-			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
-				VPRINTK("port %u IRQ found for qc, "
-					"ata_status 0x%x\n", port,ata_status);
-				/* mark qc status appropriately */
-				if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
-					qc->err_mask |= err_mask;
-					ata_qc_complete(qc);
-				}
-			}
+		hard_port = mv_hardport_from_port(port); /* range 0..3 */
+
+		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
+				mv_intr_edma(ap);
+		} else {
+			if ((DEV_IRQ << hard_port) & hc_irq_cause)
+				mv_intr_pio(ap);
 		}
 	}
 	VPRINTK("EXIT\n");
 }
 
+static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+{
+	struct ata_port *ap;
+	struct ata_queued_cmd *qc;
+	struct ata_eh_info *ehi;
+	unsigned int i, err_mask, printed = 0;
+	u32 err_cause;
+
+	err_cause = readl(mmio + PCI_IRQ_CAUSE_OFS);
+
+	dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
+		   err_cause);
+
+	DPRINTK("All regs @ PCI error\n");
+	mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
+
+	writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+
+	for (i = 0; i < host->n_ports; i++) {
+		ap = host->ports[i];
+		if (!ata_port_offline(ap)) {
+			ehi = &ap->eh_info;
+			ata_ehi_clear_desc(ehi);
+			if (!printed++)
+				ata_ehi_push_desc(ehi,
+					"PCI err cause 0x%08x", err_cause);
+			err_mask = AC_ERR_HOST_BUS;
+			ehi->action = ATA_EH_HARDRESET;
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc)
+				qc->err_mask |= err_mask;
+			else
+				ehi->err_mask |= err_mask;
+
+			ata_port_freeze(ap);
+		}
+	}
+}
+
 /**
- *      mv_interrupt -
+ *      mv_interrupt - Main interrupt event handler
  *      @irq: unused
  *      @dev_instance: private data; in this case the host structure
- *      @regs: unused
  *
  *      Read the read only register to determine if any host
  *      controllers have pending interrupts.  If so, call lower level
@@ -1430,7 +1683,6 @@
 	struct ata_host *host = dev_instance;
 	unsigned int hc, handled = 0, n_hcs;
 	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
-	struct mv_host_priv *hpriv;
 	u32 irq_stat;
 
 	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
@@ -1444,34 +1696,21 @@
 	n_hcs = mv_get_hc_count(host->ports[0]->flags);
 	spin_lock(&host->lock);
 
+	if (unlikely(irq_stat & PCI_ERR)) {
+		mv_pci_error(host, mmio);
+		handled = 1;
+		goto out_unlock;	/* skip all other HC irq handling */
+	}
+
 	for (hc = 0; hc < n_hcs; hc++) {
 		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
 		if (relevant) {
 			mv_host_intr(host, relevant, hc);
-			handled++;
+			handled = 1;
 		}
 	}
 
-	hpriv = host->private_data;
-	if (IS_60XX(hpriv)) {
-		/* deal with the interrupt coalescing bits */
-		if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
-			writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
-			writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
-			writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
-		}
-	}
-
-	if (PCI_ERR & irq_stat) {
-		printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
-		       readl(mmio + PCI_IRQ_CAUSE_OFS));
-
-		DPRINTK("All regs @ PCI error\n");
-		mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
-
-		writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
-		handled++;
-	}
+out_unlock:
 	spin_unlock(&host->lock);
 
 	return IRQ_RETVAL(handled);
@@ -1526,12 +1765,9 @@
 
 static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
 {
-	u8 rev_id;
 	int early_5080;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
-	early_5080 = (pdev->device == 0x5080) && (rev_id == 0);
+	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
 
 	if (!early_5080) {
 		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
@@ -1860,7 +2096,7 @@
 
 	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
 
-	if (IS_60XX(hpriv)) {
+	if (IS_GEN_II(hpriv)) {
 		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
 		ifctl |= (1 << 7);		/* enable gen2i speed */
 		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
@@ -1876,32 +2112,12 @@
 
 	hpriv->ops->phy_errata(hpriv, mmio, port_no);
 
-	if (IS_50XX(hpriv))
+	if (IS_GEN_I(hpriv))
 		mdelay(1);
 }
 
-static void mv_stop_and_reset(struct ata_port *ap)
-{
-	struct mv_host_priv *hpriv = ap->host->private_data;
-	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
-
-	mv_stop_dma(ap);
-
-	mv_channel_reset(hpriv, mmio, ap->port_no);
-
-	__mv_phy_reset(ap, 0);
-}
-
-static inline void __msleep(unsigned int msec, int can_sleep)
-{
-	if (can_sleep)
-		msleep(msec);
-	else
-		mdelay(msec);
-}
-
 /**
- *      __mv_phy_reset - Perform eDMA reset followed by COMRESET
+ *      mv_phy_reset - Perform eDMA reset followed by COMRESET
  *      @ap: ATA channel to manipulate
  *
  *      Part of this is taken from __sata_phy_reset and modified to
@@ -1911,14 +2127,12 @@
  *      Inherited from caller.  This is coded to safe to call at
  *      interrupt level, i.e. it does not sleep.
  */
-static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
+static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
+			 unsigned long deadline)
 {
 	struct mv_port_priv *pp	= ap->private_data;
 	struct mv_host_priv *hpriv = ap->host->private_data;
 	void __iomem *port_mmio = mv_ap_base(ap);
-	struct ata_taskfile tf;
-	struct ata_device *dev = &ap->device[0];
-	unsigned long timeout;
 	int retry = 5;
 	u32 sstatus;
 
@@ -1931,22 +2145,21 @@
 	/* Issue COMRESET via SControl */
 comreset_retry:
 	sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
-	__msleep(1, can_sleep);
+	msleep(1);
 
 	sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
-	__msleep(20, can_sleep);
+	msleep(20);
 
-	timeout = jiffies + msecs_to_jiffies(200);
 	do {
 		sata_scr_read(ap, SCR_STATUS, &sstatus);
 		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
 			break;
 
-		__msleep(1, can_sleep);
-	} while (time_before(jiffies, timeout));
+		msleep(1);
+	} while (time_before(jiffies, deadline));
 
 	/* work around errata */
-	if (IS_60XX(hpriv) &&
+	if (IS_GEN_II(hpriv) &&
 	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
 	    (retry-- > 0))
 		goto comreset_retry;
@@ -1955,13 +2168,8 @@
 		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
 		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
 
-	if (ata_port_online(ap)) {
-		ata_port_probe(ap);
-	} else {
-		sata_scr_read(ap, SCR_STATUS, &sstatus);
-		ata_port_printk(ap, KERN_INFO,
-				"no device found (phy stat %08x)\n", sstatus);
-		ata_port_disable(ap);
+	if (ata_port_offline(ap)) {
+		*class = ATA_DEV_NONE;
 		return;
 	}
 
@@ -1975,68 +2183,152 @@
 		u8 drv_stat = ata_check_status(ap);
 		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
 			break;
-		__msleep(500, can_sleep);
+		msleep(500);
 		if (retry-- <= 0)
 			break;
+		if (time_after(jiffies, deadline))
+			break;
 	}
 
-	tf.lbah = readb(ap->ioaddr.lbah_addr);
-	tf.lbam = readb(ap->ioaddr.lbam_addr);
-	tf.lbal = readb(ap->ioaddr.lbal_addr);
-	tf.nsect = readb(ap->ioaddr.nsect_addr);
+	/* FIXME: if we passed the deadline, the following
+	 * code probably produces an invalid result
+	 */
 
-	dev->class = ata_dev_classify(&tf);
-	if (!ata_dev_enabled(dev)) {
-		VPRINTK("Port disabled post-sig: No device present.\n");
-		ata_port_disable(ap);
-	}
+	/* finally, read device signature from TF registers */
+	*class = ata_dev_try_classify(ap, 0, NULL);
 
 	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
-	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+	WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
 
 	VPRINTK("EXIT\n");
 }
 
-static void mv_phy_reset(struct ata_port *ap)
+static int mv_prereset(struct ata_port *ap, unsigned long deadline)
 {
-	__mv_phy_reset(ap, 1);
+	struct mv_port_priv *pp	= ap->private_data;
+	struct ata_eh_context *ehc = &ap->eh_context;
+	int rc;
+	
+	rc = mv_stop_dma(ap);
+	if (rc)
+		ehc->i.action |= ATA_EH_HARDRESET;
+
+	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
+		pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
+		ehc->i.action |= ATA_EH_HARDRESET;
+	}
+
+	/* if we're about to do hardreset, nothing more to do */
+	if (ehc->i.action & ATA_EH_HARDRESET)
+		return 0;
+
+	if (ata_port_online(ap))
+		rc = ata_wait_ready(ap, deadline);
+	else
+		rc = -ENODEV;
+
+	return rc;
 }
 
-/**
- *      mv_eng_timeout - Routine called by libata when SCSI times out I/O
- *      @ap: ATA channel to manipulate
- *
- *      Intent is to clear all pending error conditions, reset the
- *      chip/bus, fail the command, and move on.
- *
- *      LOCKING:
- *      This routine holds the host lock while failing the command.
- */
-static void mv_eng_timeout(struct ata_port *ap)
+static int mv_hardreset(struct ata_port *ap, unsigned int *class,
+			unsigned long deadline)
+{
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+
+	mv_stop_dma(ap);
+
+	mv_channel_reset(hpriv, mmio, ap->port_no);
+
+	mv_phy_reset(ap, class, deadline);
+
+	return 0;
+}
+
+static void mv_postreset(struct ata_port *ap, unsigned int *classes)
+{
+	u32 serr;
+
+	/* print link status */
+	sata_print_link_status(ap);
+
+	/* clear SError */
+	sata_scr_read(ap, SCR_ERROR, &serr);
+	sata_scr_write_flush(ap, SCR_ERROR, serr);
+
+	/* bail out if no device is present */
+	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+		DPRINTK("EXIT, no device\n");
+		return;
+	}
+
+	/* set up device control */
+	iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+}
+
+static void mv_error_handler(struct ata_port *ap)
+{
+	ata_do_eh(ap, mv_prereset, ata_std_softreset,
+		  mv_hardreset, mv_postreset);
+}
+
+static void mv_post_int_cmd(struct ata_queued_cmd *qc)
+{
+	mv_stop_dma(qc->ap);
+}
+
+static void mv_eh_freeze(struct ata_port *ap)
 {
 	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
-	struct ata_queued_cmd *qc;
-	unsigned long flags;
+	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+	u32 tmp, mask;
+	unsigned int shift;
 
-	ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
-	DPRINTK("All regs @ start of eng_timeout\n");
-	mv_dump_all_regs(mmio, ap->port_no, to_pci_dev(ap->host->dev));
+	/* FIXME: handle coalescing completion events properly */
 
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
-	       mmio, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
+	shift = ap->port_no * 2;
+	if (hc > 0)
+		shift++;
 
-	spin_lock_irqsave(&ap->host->lock, flags);
-	mv_err_intr(ap, 0);
-	mv_stop_and_reset(ap);
-	spin_unlock_irqrestore(&ap->host->lock, flags);
+	mask = 0x3 << shift;
 
-	WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
-	if (qc->flags & ATA_QCFLAG_ACTIVE) {
-		qc->err_mask |= AC_ERR_TIMEOUT;
-		ata_eh_qc_complete(qc);
+	/* disable assertion of portN err, done events */
+	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
+	writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
+}
+
+static void mv_eh_thaw(struct ata_port *ap)
+{
+	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+	void __iomem *port_mmio = mv_ap_base(ap);
+	u32 tmp, mask, hc_irq_cause;
+	unsigned int shift, hc_port_no = ap->port_no;
+
+	/* FIXME: handle coalescing completion events properly */
+
+	shift = ap->port_no * 2;
+	if (hc > 0) {
+		shift++;
+		hc_port_no -= 4;
 	}
+
+	mask = 0x3 << shift;
+
+	/* clear EDMA errors on this port */
+	writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+	/* clear pending irq events */
+	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+	hc_irq_cause &= ~(1 << hc_port_no);	/* clear CRPB-done */
+	hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
+	writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+
+	/* enable assertion of portN err, done events */
+	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
+	writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
 }
 
 /**
@@ -2092,17 +2384,14 @@
 {
 	struct pci_dev *pdev = to_pci_dev(host->dev);
 	struct mv_host_priv *hpriv = host->private_data;
-	u8 rev_id;
 	u32 hp_flags = hpriv->hp_flags;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
 	switch(board_idx) {
 	case chip_5080:
 		hpriv->ops = &mv5xxx_ops;
-		hp_flags |= MV_HP_50XX;
+		hp_flags |= MV_HP_GEN_I;
 
-		switch (rev_id) {
+		switch (pdev->revision) {
 		case 0x1:
 			hp_flags |= MV_HP_ERRATA_50XXB0;
 			break;
@@ -2120,9 +2409,9 @@
 	case chip_504x:
 	case chip_508x:
 		hpriv->ops = &mv5xxx_ops;
-		hp_flags |= MV_HP_50XX;
+		hp_flags |= MV_HP_GEN_I;
 
-		switch (rev_id) {
+		switch (pdev->revision) {
 		case 0x0:
 			hp_flags |= MV_HP_ERRATA_50XXB0;
 			break;
@@ -2140,8 +2429,9 @@
 	case chip_604x:
 	case chip_608x:
 		hpriv->ops = &mv6xxx_ops;
+		hp_flags |= MV_HP_GEN_II;
 
-		switch (rev_id) {
+		switch (pdev->revision) {
 		case 0x7:
 			hp_flags |= MV_HP_ERRATA_60X1B2;
 			break;
@@ -2159,10 +2449,9 @@
 	case chip_7042:
 	case chip_6042:
 		hpriv->ops = &mv6xxx_ops;
-
 		hp_flags |= MV_HP_GEN_IIE;
 
-		switch (rev_id) {
+		switch (pdev->revision) {
 		case 0x0:
 			hp_flags |= MV_HP_ERRATA_XX42A0;
 			break;
@@ -2226,7 +2515,7 @@
 	hpriv->ops->enable_leds(hpriv, mmio);
 
 	for (port = 0; port < host->n_ports; port++) {
-		if (IS_60XX(hpriv)) {
+		if (IS_GEN_II(hpriv)) {
 			void __iomem *port_mmio = mv_port_base(mmio, port);
 
 			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
@@ -2261,7 +2550,7 @@
 	/* and unmask interrupt generation for host regs */
 	writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
 
-	if (IS_50XX(hpriv))
+	if (IS_GEN_I(hpriv))
 		writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
 	else
 		writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
@@ -2290,25 +2579,32 @@
 {
 	struct pci_dev *pdev = to_pci_dev(host->dev);
 	struct mv_host_priv *hpriv = host->private_data;
-	u8 rev_id, scc;
-	const char *scc_s;
+	u8 scc;
+	const char *scc_s, *gen;
 
 	/* Use this to determine the HW stepping of the chip so we know
 	 * what errata to workaround
 	 */
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
 	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
 	if (scc == 0)
 		scc_s = "SCSI";
 	else if (scc == 0x01)
 		scc_s = "RAID";
 	else
-		scc_s = "unknown";
+		scc_s = "?";
+
+	if (IS_GEN_I(hpriv))
+		gen = "I";
+	else if (IS_GEN_II(hpriv))
+		gen = "II";
+	else if (IS_GEN_IIE(hpriv))
+		gen = "IIE";
+	else
+		gen = "?";
 
 	dev_printk(KERN_INFO, &pdev->dev,
-	       "%u slots %u ports %s mode IRQ via %s\n",
-	       (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
+	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
+	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
 	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
 }
 
@@ -2370,8 +2666,9 @@
 	mv_print_info(host);
 
 	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
 	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
-				 &mv_sht);
+				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
 }
 
 static int __init mv_init(void)
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 1a49c777f..db81e3e 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -49,7 +49,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME			"sata_nv"
-#define DRV_VERSION			"3.3"
+#define DRV_VERSION			"3.4"
 
 #define NV_ADMA_DMA_BOUNDARY		0xffffffffUL
 
@@ -325,6 +325,7 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
+	.change_queue_depth	= ata_scsi_change_queue_depth,
 	.can_queue		= NV_ADMA_MAX_CPBS,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= NV_ADMA_SGTBL_TOTAL_LEN,
@@ -802,7 +803,7 @@
 			u16 status;
 			u32 gen_ctl;
 			u32 notifier, notifier_error;
-			
+
 			/* if ADMA is disabled, use standard ata interrupt handler */
 			if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
 				u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
@@ -963,7 +964,7 @@
 
 	/* clear ADMA status */
 	writew(0xffff, mmio + NV_ADMA_STAT);
-	
+
 	/* clear notifiers - note both ports need to be written with
 	   something even though we are only clearing on one */
 	if (ap->port_no == 0) {
@@ -1559,7 +1560,7 @@
 	}
 
 	ppi[0] = &nv_port_info[type];
-	rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
 	if (rc)
 		return rc;
 
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 3a7d9b5..d2fcb9a 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -45,8 +45,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME	"sata_promise"
-#define DRV_VERSION	"2.07"
-
+#define DRV_VERSION	"2.09"
 
 enum {
 	PDC_MAX_PORTS		= 4,
@@ -94,7 +93,7 @@
 	board_20319		= 2,	/* FastTrak S150 TX4 */
 	board_20619		= 3,	/* FastTrak TX4000 */
 	board_2057x		= 4,	/* SATAII150 Tx2plus */
-	board_2057x_pata	= 5,	/* SATAII150 Tx2plus */
+	board_2057x_pata	= 5,	/* SATAII150 Tx2plus PATA port */
 	board_40518		= 6,	/* SATAII150 Tx4 */
 
 	PDC_HAS_PATA		= (1 << 1), /* PDC20375/20575 has PATA */
@@ -124,7 +123,6 @@
 	PDC_FLAG_4_PORTS	= (1 << 26), /* 4 ports */
 };
 
-
 struct pdc_port_priv {
 	u8			*pkt;
 	dma_addr_t		pkt_dma;
@@ -252,7 +250,7 @@
 				  PDC_FLAG_SATA_PATA,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_old_sata_ops,
 	},
 
@@ -261,7 +259,7 @@
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
 
@@ -271,7 +269,7 @@
 				  PDC_FLAG_4_PORTS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_old_sata_ops,
 	},
 
@@ -281,7 +279,7 @@
 				  PDC_FLAG_4_PORTS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
 
@@ -291,17 +289,17 @@
 				  PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_sata_ops,
 	},
 
 	/* board_2057x_pata */
 	{
-		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
+		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
 				  PDC_FLAG_GEN_II,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
 
@@ -311,7 +309,7 @@
 				  PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_sata_ops,
 	},
 };
@@ -340,7 +338,6 @@
 	{ }	/* terminate list */
 };
 
-
 static struct pci_driver pdc_ata_pci_driver = {
 	.name			= DRV_NAME,
 	.id_table		= pdc_ata_pci_tbl,
@@ -348,7 +345,6 @@
 	.remove			= ata_pci_remove_one,
 };
 
-
 static int pdc_common_port_start(struct ata_port *ap)
 {
 	struct device *dev = ap->host->dev;
@@ -382,7 +378,7 @@
 
 	/* fix up PHYMODE4 align timing */
 	if (ap->flags & PDC_FLAG_GEN_II) {
-		void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr;
+		void __iomem *mmio = ap->ioaddr.scr_addr;
 		unsigned int tmp;
 
 		tmp = readl(mmio + 0x014);
@@ -418,7 +414,7 @@
 static int pdc_pata_cable_detect(struct ata_port *ap)
 {
 	u8 tmp;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+	void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
 
 	tmp = readb(mmio);
 	if (tmp & 0x01)
@@ -438,7 +434,6 @@
 	return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
 			       u32 val)
 {
@@ -573,7 +568,7 @@
 
 static void pdc_freeze(struct ata_port *ap)
 {
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *mmio = ap->ioaddr.cmd_addr;
 	u32 tmp;
 
 	tmp = readl(mmio + PDC_CTLSTAT);
@@ -585,7 +580,7 @@
 
 static void pdc_thaw(struct ata_port *ap)
 {
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *mmio = ap->ioaddr.cmd_addr;
 	u32 tmp;
 
 	/* clear IRQ */
@@ -657,8 +652,8 @@
 	ata_port_abort(ap);
 }
 
-static inline unsigned int pdc_host_intr( struct ata_port *ap,
-                                          struct ata_queued_cmd *qc)
+static inline unsigned int pdc_host_intr(struct ata_port *ap,
+					 struct ata_queued_cmd *qc)
 {
 	unsigned int handled = 0;
 	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
@@ -685,10 +680,10 @@
 		handled = 1;
 		break;
 
-        default:
+	default:
 		ap->stats.idle_irq++;
 		break;
-        }
+	}
 
 	return handled;
 }
@@ -701,6 +696,18 @@
 	readl(mmio + PDC_INT_SEQMASK);
 }
 
+static inline int pdc_is_sataii_tx4(unsigned long flags)
+{
+	const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
+	return (flags & mask) == mask;
+}
+
+static inline unsigned int pdc_port_no_to_ata_no(unsigned int port_no, int is_sataii_tx4)
+{
+	static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+	return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
+}
+
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
@@ -709,6 +716,9 @@
 	unsigned int i, tmp;
 	unsigned int handled = 0;
 	void __iomem *mmio_base;
+	unsigned int hotplug_offset, ata_no;
+	u32 hotplug_status;
+	int is_sataii_tx4;
 
 	VPRINTK("ENTER\n");
 
@@ -719,10 +729,20 @@
 
 	mmio_base = host->iomap[PDC_MMIO_BAR];
 
+	/* read and clear hotplug flags for all ports */
+	if (host->ports[0]->flags & PDC_FLAG_GEN_II)
+		hotplug_offset = PDC2_SATA_PLUG_CSR;
+	else
+		hotplug_offset = PDC_SATA_PLUG_CSR;
+	hotplug_status = readl(mmio_base + hotplug_offset);
+	if (hotplug_status & 0xff)
+		writel(hotplug_status | 0xff, mmio_base + hotplug_offset);
+	hotplug_status &= 0xff;	/* clear uninteresting bits */
+
 	/* reading should also clear interrupts */
 	mask = readl(mmio_base + PDC_INT_SEQMASK);
 
-	if (mask == 0xffffffff) {
+	if (mask == 0xffffffff && hotplug_status == 0) {
 		VPRINTK("QUICK EXIT 2\n");
 		return IRQ_NONE;
 	}
@@ -730,16 +750,34 @@
 	spin_lock(&host->lock);
 
 	mask &= 0xffff;		/* only 16 tags possible */
-	if (!mask) {
+	if (mask == 0 && hotplug_status == 0) {
 		VPRINTK("QUICK EXIT 3\n");
 		goto done_irq;
 	}
 
 	writel(mask, mmio_base + PDC_INT_SEQMASK);
 
+	is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags);
+
 	for (i = 0; i < host->n_ports; i++) {
 		VPRINTK("port %u\n", i);
 		ap = host->ports[i];
+
+		/* check for a plug or unplug event */
+		ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
+		tmp = hotplug_status & (0x11 << ata_no);
+		if (tmp && ap &&
+		    !(ap->flags & ATA_FLAG_DISABLED)) {
+			struct ata_eh_info *ehi = &ap->eh_info;
+			ata_ehi_clear_desc(ehi);
+			ata_ehi_hotplugged(ehi);
+			ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp);
+			ata_port_freeze(ap);
+			++handled;
+			continue;
+		}
+
+		/* check for a packet interrupt */
 		tmp = mask & (1 << (i + 1));
 		if (tmp && ap &&
 		    !(ap->flags & ATA_FLAG_DISABLED)) {
@@ -784,9 +822,12 @@
 		if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
 			break;
 		/*FALLTHROUGH*/
+	case ATA_PROT_NODATA:
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			break;
+		/*FALLTHROUGH*/
 	case ATA_PROT_ATAPI_DMA:
 	case ATA_PROT_DMA:
-	case ATA_PROT_NODATA:
 		pdc_packet_start(qc);
 		return 0;
 
@@ -800,15 +841,14 @@
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
-		 tf->protocol == ATA_PROT_NODATA);
+		 tf->protocol == ATA_PROT_ATAPI_DMA);
 	ata_tf_load(ap, tf);
 }
 
-
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
-		 tf->protocol == ATA_PROT_NODATA);
+		 tf->protocol == ATA_PROT_ATAPI_DMA);
 	ata_exec_command(ap, tf);
 }
 
@@ -864,7 +904,6 @@
 	ap->ioaddr.scr_addr		= scr_addr;
 }
 
-
 static void pdc_host_init(struct ata_host *host)
 {
 	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
@@ -894,9 +933,9 @@
 	tmp = readl(mmio + hotplug_offset);
 	writel(tmp | 0xff, mmio + hotplug_offset);
 
-	/* mask plug/unplug ints */
+	/* unmask plug/unplug ints */
 	tmp = readl(mmio + hotplug_offset);
-	writel(tmp | 0xff0000, mmio + hotplug_offset);
+	writel(tmp & ~0xff0000, mmio + hotplug_offset);
 
 	/* don't initialise TBG or SLEW on 2nd generation chips */
 	if (is_gen2)
@@ -952,10 +991,8 @@
 
 	if (pi->flags & PDC_FLAG_SATA_PATA) {
 		u8 tmp = readb(base + PDC_FLASH_CTL+1);
-		if (!(tmp & 0x80)) {
+		if (!(tmp & 0x80))
 			ppi[n_ports++] = pi + 1;
-			dev_printk(KERN_INFO, &pdev->dev, "PATA port found\n");
-		}
 	}
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
@@ -965,22 +1002,12 @@
 	}
 	host->iomap = pcim_iomap_table(pdev);
 
-	is_sataii_tx4 = 0;
-	if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) {
-		is_sataii_tx4 = 1;
-		dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n");
-	}
+	is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);
 	for (i = 0; i < host->n_ports; i++) {
-		static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
-		int ata_nr;
-
-		ata_nr = i;
-		if (is_sataii_tx4)
-			ata_nr = sataii_tx4_port_remap[i];
-
+		unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
 		pdc_ata_setup_port(host->ports[i],
-				   base + 0x200 + ata_nr * 0x80,
-				   base + 0x400 + ata_nr * 0x100);
+				   base + 0x200 + ata_no * 0x80,
+				   base + 0x400 + ata_no * 0x100);
 	}
 
 	/* initialize adapter */
@@ -999,19 +1026,16 @@
 				 &pdc_ata_sht);
 }
 
-
 static int __init pdc_ata_init(void)
 {
 	return pci_register_driver(&pdc_ata_pci_driver);
 }
 
-
 static void __exit pdc_ata_exit(void)
 {
 	pci_unregister_driver(&pdc_ata_pci_driver);
 }
 
-
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index f5a05de..9ab554d 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -39,7 +39,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_qstor"
-#define DRV_VERSION	"0.07"
+#define DRV_VERSION	"0.08"
 
 enum {
 	QS_MMIO_BAR		= 4,
@@ -176,7 +176,7 @@
 				  //FIXME ATA_FLAG_SRST |
 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x10, /* pio4 */
-		.udma_mask	= 0x7f, /* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &qs_ata_ops,
 	},
 };
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index e8483aa..2a86dc4 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -218,7 +218,7 @@
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 	/* sil_3112_no_sata_irq */
@@ -227,7 +227,7 @@
 				  SIL_FLAG_NO_SATA_IRQ,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 	/* sil_3512 */
@@ -235,7 +235,7 @@
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 	/* sil_3114 */
@@ -243,7 +243,7 @@
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 };
@@ -262,8 +262,9 @@
 	unsigned long sfis_cfg;	/* SATA FIS reception config register */
 } sil_port[] = {
 	/* port 0 ... */
-	{ 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
-	{ 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
+	/*   tf    ctl  bmdma  bmdma2  fifo    scr   sien   mode   sfis */
+	{  0x80,  0x8A,   0x0,  0x10,  0x40, 0x100, 0x148,  0xb4, 0x14c },
+	{  0xC0,  0xCA,   0x8,  0x18,  0x44, 0x180, 0x1c8,  0xf4, 0x1cc },
 	{ 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
 	{ 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
 	/* ... port 3 */
@@ -305,7 +306,7 @@
 	u32 tmp, dev_mode[2];
 	unsigned int i;
 	int rc;
-	
+
 	rc = ata_do_set_mode(ap, r_failed);
 	if (rc)
 		return rc;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 0cb6618..ac43a30 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -30,7 +30,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_sil24"
-#define DRV_VERSION	"0.8"
+#define DRV_VERSION	"0.9"
 
 /*
  * Port request block (PRB) 32 bytes
@@ -426,7 +426,7 @@
 				  SIL24_FLAG_PCIX_IRQ_WOC,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
 		.port_ops	= &sil24_ops,
 	},
 	/* sil_3132 */
@@ -434,7 +434,7 @@
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
 		.port_ops	= &sil24_ops,
 	},
 	/* sil_3131/sil_3531 */
@@ -442,7 +442,7 @@
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
 		.port_ops	= &sil24_ops,
 	},
 };
@@ -888,7 +888,7 @@
 		if (status & (1 << i)) {
 			struct ata_port *ap = host->ports[i];
 			if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
-				sil24_host_intr(host->ports[i]);
+				sil24_host_intr(ap);
 				handled++;
 			} else
 				printk(KERN_ERR DRV_NAME
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index ee66c5f..33716b0 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -43,7 +43,7 @@
 #include "sis.h"
 
 #define DRV_NAME	"sata_sis"
-#define DRV_VERSION	"0.7"
+#define DRV_VERSION	"0.8"
 
 enum {
 	sis_180			= 0,
@@ -72,8 +72,8 @@
 	{ PCI_VDEVICE(SI, 0x0181), sis_180 },		/* SiS 964/180 */
 	{ PCI_VDEVICE(SI, 0x0182), sis_180 },		/* SiS 965/965L */
 	{ PCI_VDEVICE(SI, 0x0183), sis_180 },		/* SiS 965/965L */
-	{ PCI_VDEVICE(SI, 0x1182), sis_180 },		/* SiS 966/966L */
-	{ PCI_VDEVICE(SI, 0x1183), sis_180 },		/* SiS 966/966L */
+	{ PCI_VDEVICE(SI, 0x1182), sis_180 },		/* SiS 966/680 */
+	{ PCI_VDEVICE(SI, 0x1183), sis_180 },		/* SiS 966/966L/968/680 */
 
 	{ }	/* terminate list */
 };
@@ -133,7 +133,7 @@
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x7,
-	.udma_mask	= 0x7f,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_ops,
 };
 
@@ -161,7 +161,6 @@
 			case 0x0182:
 			case 0x0183:
 			case 0x1182:
-			case 0x1183:
 				addr += SIS182_SATA1_OFS;
 				break;
 		}
@@ -183,8 +182,8 @@
 
 	pci_read_config_dword(pdev, cfg_addr, &val);
 
-	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
-	    (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+	    (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
 		pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
 
 	return (val|val2) &  0xfffffffb; /* avoid problems with powerdowned ports */
@@ -203,8 +202,8 @@
 
 	pci_write_config_dword(pdev, cfg_addr, val);
 
-	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
-	    (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+	    (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
 		pci_write_config_dword(pdev, cfg_addr+0x10, val);
 }
 
@@ -224,8 +223,8 @@
 
 	val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
 
-	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
-	    (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+	    (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
 		val2 = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
 
 	return (val | val2) &  0xfffffffb;
@@ -245,8 +244,8 @@
 		sis_scr_cfg_write(ap, sc_reg, val);
 	else {
 		iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
-		if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
-		    (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+		if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+		    (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
 			iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
 	}
 }
@@ -255,7 +254,7 @@
 {
 	static int printed_version;
 	struct ata_port_info pi = sis_port_info;
-	const struct ata_port_info *ppi[] = { &pi, NULL };
+	const struct ata_port_info *ppi[] = { &pi, &pi };
 	struct ata_host *host;
 	u32 genctl, val;
 	u8 pmr;
@@ -293,11 +292,11 @@
 		/* The PATA-handling is provided by pata_sis */
 		switch (pmr & 0x30) {
 		case 0x10:
-			ppi[1] = &sis_info133;
+			ppi[1] = &sis_info133_for_sata;
 			break;
 
 		case 0x30:
-			ppi[0] = &sis_info133;
+			ppi[0] = &sis_info133_for_sata;
 			break;
 		}
 		if ((pmr & SIS_PMR_COMBINED) == 0) {
@@ -324,18 +323,18 @@
 		break;
 
 	case 0x1182:
+		dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/966/680 SATA controller\n");
+		pi.flags |= ATA_FLAG_SLAVE_POSS;
+		break;
+
 	case 0x1183:
-		pci_read_config_dword(pdev, 0x64, &val);
-		if (val & 0x10000000) {
-			dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/1183/966L SATA controller\n");
-		} else {
-			dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/1183/966 SATA controller\n");
-			pi.flags |= ATA_FLAG_SLAVE_POSS;
-		}
+		dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
+		ppi[0] = &sis_info133_for_sata;
+		ppi[1] = &sis_info133_for_sata;
 		break;
 	}
 
-	rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
 	if (rc)
 		return rc;
 
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 1724673..63fe99af 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -53,7 +53,7 @@
 #endif /* CONFIG_PPC_OF */
 
 #define DRV_NAME	"sata_svw"
-#define DRV_VERSION	"2.1"
+#define DRV_VERSION	"2.2"
 
 enum {
 	/* ap->flags bits */
@@ -107,7 +107,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -116,7 +116,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -197,7 +197,8 @@
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 dmactl;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
 	/* load PRD table addr. */
 	mb();	/* make sure PRD table writes are visible to controller */
 	writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
@@ -225,7 +226,7 @@
 static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = ap->ioaddr.bmdma_addr;
 	u8 dmactl;
 
 	/* start host DMA transaction */
@@ -253,7 +254,7 @@
 
 static u8 k2_stat_check_status(struct ata_port *ap)
 {
-       	return readl((void __iomem *) ap->ioaddr.status_addr);
+       	return readl(ap->ioaddr.status_addr);
 }
 
 #ifdef CONFIG_PPC_OF
@@ -360,7 +361,7 @@
 				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask	= 0x7f,
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &k2_sata_ops,
 	},
 	/* board_svw8 */
@@ -370,7 +371,7 @@
 				  K2_FLAG_SATA_8_PORTS,
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask	= 0x7f,
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &k2_sata_ops,
 	},
 };
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 3a4f445..5193bd8 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -30,6 +30,54 @@
  *
  */
 
+/*
+	Theory of operation
+	-------------------
+
+	The SX4 (PDC20621) chip features a single Host DMA (HDMA) copy
+	engine, DIMM memory, and four ATA engines (one per SATA port).
+	Data is copied to/from DIMM memory by the HDMA engine, before
+	handing off to one (or more) of the ATA engines.  The ATA
+	engines operate solely on DIMM memory.
+
+	The SX4 behaves like a PATA chip, with no SATA controls or
+	knowledge whatsoever, leading to the presumption that
+	PATA<->SATA bridges exist on SX4 boards, external to the
+	PDC20621 chip itself.
+
+	The chip is quite capable, supporting an XOR engine and linked
+	hardware commands (permits a string to transactions to be
+	submitted and waited-on as a single unit), and an optional
+	microprocessor.
+
+	The limiting factor is largely software.  This Linux driver was
+	written to multiplex the single HDMA engine to copy disk
+	transactions into a fixed DIMM memory space, from where an ATA
+	engine takes over.  As a result, each WRITE looks like this:
+
+		submit HDMA packet to hardware
+		hardware copies data from system memory to DIMM
+		hardware raises interrupt
+
+		submit ATA packet to hardware
+		hardware executes ATA WRITE command, w/ data in DIMM
+		hardware raises interrupt
+	
+	and each READ looks like this:
+
+		submit ATA packet to hardware
+		hardware executes ATA READ command, w/ data in DIMM
+		hardware raises interrupt
+	
+		submit HDMA packet to hardware
+		hardware copies data from DIMM to system memory
+		hardware raises interrupt
+
+	This is a very slow, lock-step way of doing things that can
+	certainly be improved by motivated kernel hackers.
+
+ */
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -44,7 +92,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME	"sata_sx4"
-#define DRV_VERSION	"0.10"
+#define DRV_VERSION	"0.11"
 
 
 enum {
@@ -58,6 +106,8 @@
 	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */
 	PDC_HDMA_CTLSTAT	= 0x12C, /* Host DMA control / status */
 
+	PDC_CTLSTAT		= 0x60,	/* IDEn control / status */
+
 	PDC_20621_SEQCTL	= 0x400,
 	PDC_20621_SEQMASK	= 0x480,
 	PDC_20621_GENERAL_CTL	= 0x484,
@@ -87,48 +137,60 @@
 
 	board_20621		= 0,	/* FastTrak S150 SX4 */
 
-	PDC_RESET		= (1 << 11), /* HDMA reset */
+	PDC_MASK_INT		= (1 << 10), /* HDMA/ATA mask int */
+	PDC_RESET		= (1 << 11), /* HDMA/ATA reset */
+	PDC_DMA_ENABLE		= (1 << 7),  /* DMA start/stop */
 
 	PDC_MAX_HDMA		= 32,
 	PDC_HDMA_Q_MASK		= (PDC_MAX_HDMA - 1),
 
-	PDC_DIMM0_SPD_DEV_ADDRESS     = 0x50,
-	PDC_DIMM1_SPD_DEV_ADDRESS     = 0x51,
-	PDC_MAX_DIMM_MODULE           = 0x02,
-	PDC_I2C_CONTROL_OFFSET        = 0x48,
-	PDC_I2C_ADDR_DATA_OFFSET      = 0x4C,
-	PDC_DIMM0_CONTROL_OFFSET      = 0x80,
-	PDC_DIMM1_CONTROL_OFFSET      = 0x84,
-	PDC_SDRAM_CONTROL_OFFSET      = 0x88,
-	PDC_I2C_WRITE                 = 0x00000000,
-	PDC_I2C_READ                  = 0x00000040,
-	PDC_I2C_START                 = 0x00000080,
-	PDC_I2C_MASK_INT              = 0x00000020,
-	PDC_I2C_COMPLETE              = 0x00010000,
-	PDC_I2C_NO_ACK                = 0x00100000,
-	PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
-	PDC_DIMM_SPD_SUBADDRESS_END   = 0x7F,
-	PDC_DIMM_SPD_ROW_NUM          = 3,
-	PDC_DIMM_SPD_COLUMN_NUM       = 4,
-	PDC_DIMM_SPD_MODULE_ROW       = 5,
-	PDC_DIMM_SPD_TYPE             = 11,
-	PDC_DIMM_SPD_FRESH_RATE       = 12,
-	PDC_DIMM_SPD_BANK_NUM         = 17,
-	PDC_DIMM_SPD_CAS_LATENCY      = 18,
-	PDC_DIMM_SPD_ATTRIBUTE        = 21,
-	PDC_DIMM_SPD_ROW_PRE_CHARGE   = 27,
-	PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
-	PDC_DIMM_SPD_RAS_CAS_DELAY    = 29,
-	PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
-	PDC_DIMM_SPD_SYSTEM_FREQ      = 126,
-	PDC_CTL_STATUS		      = 0x08,
-	PDC_DIMM_WINDOW_CTLR	      = 0x0C,
-	PDC_TIME_CONTROL              = 0x3C,
-	PDC_TIME_PERIOD               = 0x40,
-	PDC_TIME_COUNTER              = 0x44,
-	PDC_GENERAL_CTLR	      = 0x484,
-	PCI_PLL_INIT                  = 0x8A531824,
-	PCI_X_TCOUNT                  = 0xEE1E5CFF
+	PDC_DIMM0_SPD_DEV_ADDRESS	= 0x50,
+	PDC_DIMM1_SPD_DEV_ADDRESS	= 0x51,
+	PDC_I2C_CONTROL			= 0x48,
+	PDC_I2C_ADDR_DATA		= 0x4C,
+	PDC_DIMM0_CONTROL		= 0x80,
+	PDC_DIMM1_CONTROL		= 0x84,
+	PDC_SDRAM_CONTROL		= 0x88,
+	PDC_I2C_WRITE			= 0,		/* master -> slave */
+	PDC_I2C_READ			= (1 << 6),	/* master <- slave */
+	PDC_I2C_START			= (1 << 7),	/* start I2C proto */
+	PDC_I2C_MASK_INT		= (1 << 5),	/* mask I2C interrupt */
+	PDC_I2C_COMPLETE		= (1 << 16),	/* I2C normal compl. */
+	PDC_I2C_NO_ACK			= (1 << 20),	/* slave no-ack addr */
+	PDC_DIMM_SPD_SUBADDRESS_START	= 0x00,
+	PDC_DIMM_SPD_SUBADDRESS_END	= 0x7F,
+	PDC_DIMM_SPD_ROW_NUM		= 3,
+	PDC_DIMM_SPD_COLUMN_NUM		= 4,
+	PDC_DIMM_SPD_MODULE_ROW		= 5,
+	PDC_DIMM_SPD_TYPE		= 11,
+	PDC_DIMM_SPD_FRESH_RATE		= 12,
+	PDC_DIMM_SPD_BANK_NUM		= 17,
+	PDC_DIMM_SPD_CAS_LATENCY	= 18,
+	PDC_DIMM_SPD_ATTRIBUTE		= 21,
+	PDC_DIMM_SPD_ROW_PRE_CHARGE	= 27,
+	PDC_DIMM_SPD_ROW_ACTIVE_DELAY	= 28,
+	PDC_DIMM_SPD_RAS_CAS_DELAY	= 29,
+	PDC_DIMM_SPD_ACTIVE_PRECHARGE	= 30,
+	PDC_DIMM_SPD_SYSTEM_FREQ	= 126,
+	PDC_CTL_STATUS			= 0x08,
+	PDC_DIMM_WINDOW_CTLR		= 0x0C,
+	PDC_TIME_CONTROL		= 0x3C,
+	PDC_TIME_PERIOD			= 0x40,
+	PDC_TIME_COUNTER		= 0x44,
+	PDC_GENERAL_CTLR		= 0x484,
+	PCI_PLL_INIT			= 0x8A531824,
+	PCI_X_TCOUNT			= 0xEE1E5CFF,
+
+	/* PDC_TIME_CONTROL bits */
+	PDC_TIMER_BUZZER		= (1 << 10),
+	PDC_TIMER_MODE_PERIODIC		= 0,		/* bits 9:8 == 00 */
+	PDC_TIMER_MODE_ONCE		= (1 << 8),	/* bits 9:8 == 01 */
+	PDC_TIMER_ENABLE		= (1 << 7),
+	PDC_TIMER_MASK_INT		= (1 << 5),
+	PDC_TIMER_SEQ_MASK		= 0x1f,		/* SEQ ID for timer */
+	PDC_TIMER_DEFAULT		= PDC_TIMER_MODE_ONCE |
+					  PDC_TIMER_ENABLE |
+					  PDC_TIMER_MASK_INT,
 };
 
 
@@ -217,7 +279,7 @@
 				  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_20621_ops,
 	},
 
@@ -999,17 +1061,17 @@
 	i2creg |= subaddr << 16;
 
 	/* Set the device and subaddress */
-	writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
-	readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+	writel(i2creg, mmio + PDC_I2C_ADDR_DATA);
+	readl(mmio + PDC_I2C_ADDR_DATA);
 
 	/* Write Control to perform read operation, mask int */
 	writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
-	       mmio + PDC_I2C_CONTROL_OFFSET);
+	       mmio + PDC_I2C_CONTROL);
 
 	for (count = 0; count <= 1000; count ++) {
-		status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
+		status = readl(mmio + PDC_I2C_CONTROL);
 		if (status & PDC_I2C_COMPLETE) {
-			status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+			status = readl(mmio + PDC_I2C_ADDR_DATA);
 			break;
 		} else if (count == 1000)
 			return 0;
@@ -1099,8 +1161,8 @@
    	data |= (((size / 16) - 1) << 16);
    	data |= (0 << 23);
 	data |= 8;
-   	writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
-	readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
+   	writel(data, mmio + PDC_DIMM0_CONTROL);
+	readl(mmio + PDC_DIMM0_CONTROL);
    	return size;
 }
 
@@ -1122,27 +1184,27 @@
 	*/
 
 	data = 0x022259F1;
-	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
-	readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+	writel(data, mmio + PDC_SDRAM_CONTROL);
+	readl(mmio + PDC_SDRAM_CONTROL);
 
 	/* Turn on for ECC */
 	pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
 			  PDC_DIMM_SPD_TYPE, &spd0);
 	if (spd0 == 0x02) {
 		data |= (0x01 << 16);
-		writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
-		readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+		writel(data, mmio + PDC_SDRAM_CONTROL);
+		readl(mmio + PDC_SDRAM_CONTROL);
 		printk(KERN_ERR "Local DIMM ECC Enabled\n");
    	}
 
    	/* DIMM Initialization Select/Enable (bit 18/19) */
    	data &= (~(1<<18));
    	data |= (1<<19);
-   	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+   	writel(data, mmio + PDC_SDRAM_CONTROL);
 
    	error = 1;
    	for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
-		data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+		data = readl(mmio + PDC_SDRAM_CONTROL);
 		if (!(data & (1<<19))) {
 	   		error = 0;
 	   		break;
@@ -1176,7 +1238,7 @@
 	VPRINTK("Time Period Register (0x40): 0x%x\n", time_period);
 
 	/* Enable timer */
-	writel(0x00001a0, mmio + PDC_TIME_CONTROL);
+	writel(PDC_TIMER_DEFAULT, mmio + PDC_TIME_CONTROL);
 	readl(mmio + PDC_TIME_CONTROL);
 
 	/* Wait 3 seconds */
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 006f5e3..b52f83a 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -36,7 +36,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_uli"
-#define DRV_VERSION	"1.1"
+#define DRV_VERSION	"1.2"
 
 enum {
 	uli_5289		= 0,
@@ -129,7 +129,7 @@
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 			  ATA_FLAG_IGN_SIMPLEX,
 	.pio_mask       = 0x1f,		/* pio0-4 */
-	.udma_mask      = 0x7f,		/* udma0-6 */
+	.udma_mask      = ATA_UDMA6,
 	.port_ops       = &uli_ops,
 };
 
@@ -213,7 +213,7 @@
 	host->private_data = hpriv;
 
 	/* the first two ports are standard SFF */
-	rc = ata_pci_init_native_host(host);
+	rc = ata_pci_init_sff_host(host);
 	if (rc)
 		return rc;
 
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index ac4f43c..c412447 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_via"
-#define DRV_VERSION	"2.1"
+#define DRV_VERSION	"2.2"
 
 enum board_ids_enum {
 	vt6420,
@@ -85,6 +85,9 @@
 	{ PCI_VDEVICE(VIA, 0x0591), vt6420 },
 	{ PCI_VDEVICE(VIA, 0x3149), vt6420 },
 	{ PCI_VDEVICE(VIA, 0x3249), vt6421 },
+	{ PCI_VDEVICE(VIA, 0x5287), vt6420 },
+	{ PCI_VDEVICE(VIA, 0x5372), vt6420 },
+	{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
 
 	{ }	/* terminate list */
 };
@@ -220,7 +223,7 @@
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x07,
-	.udma_mask	= 0x7f,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6420_sata_ops,
 };
 
@@ -228,7 +231,7 @@
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x07,
-	.udma_mask	= 0x7f,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6421_sata_ops,
 };
 
@@ -236,7 +239,7 @@
 	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0,
-	.udma_mask	= 0x7f,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6421_pata_ops,
 };
 
@@ -300,9 +303,7 @@
 	if (!(ap->pflags & ATA_PFLAG_LOADING))
 		goto skip_scr;
 
-	/* Resume phy.  This is the old resume sequence from
-	 * __sata_phy_reset().
-	 */
+	/* Resume phy.  This is the old SATA resume sequence */
 	svia_scr_write(ap, SCR_CONTROL, 0x300);
 	svia_scr_read(ap, SCR_CONTROL); /* flush */
 
@@ -411,7 +412,7 @@
 	struct ata_host *host;
 	int rc;
 
-	rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
 	if (rc)
 		return rc;
 	*r_host = host;
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 80126f8..1b5d81f 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -47,7 +47,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_vsc"
-#define DRV_VERSION	"2.1"
+#define DRV_VERSION	"2.2"
 
 enum {
 	VSC_MMIO_BAR			= 0,
@@ -371,7 +371,7 @@
 				  ATA_FLAG_MMIO,
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask	= 0x7f,
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &vsc_sata_ops,
 	};
 	const struct ata_port_info *ppi[] = { &pi, NULL };
diff --git a/drivers/ata/sis.h b/drivers/ata/sis.h
index 0f2208d..f7f3eeb 100644
--- a/drivers/ata/sis.h
+++ b/drivers/ata/sis.h
@@ -2,4 +2,4 @@
 struct ata_port_info;
 
 /* pata_sis.c */
-extern const struct ata_port_info sis_info133;
+extern const struct ata_port_info sis_info133_for_sata;
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index f5a47a4..bb4ae628 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -7,7 +7,7 @@
 	depends on NETDEVICES && ATM
 	default y
 
-if ATM_DRIVERS
+if ATM_DRIVERS && NETDEVICES && ATM
 
 config ATM_DUMMY
 	tristate "Dummy ATM driver"
@@ -142,7 +142,7 @@
 
 config ATM_FIRESTREAM
 	tristate "Fujitsu FireStream (FS50/FS155) "
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	help
 	  Driver for the Fujitsu FireStream 155 (MB86697) and
 	  FireStream 50 (MB86695) ATM PCI chips.
@@ -152,7 +152,7 @@
 
 config ATM_ZATM
 	tristate "ZeitNet ZN1221/ZN1225"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	help
 	  Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM
 	  adapters.
@@ -240,7 +240,7 @@
 
 config ATM_AMBASSADOR
 	tristate "Madge Ambassador (Collage PCI 155 Server)"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	select BITREVERSE
 	help
 	  This is a driver for ATMizer based ATM card produced by Madge
@@ -265,7 +265,7 @@
 
 config ATM_HORIZON
 	tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	help
 	  This is a driver for the Horizon chipset ATM adapter cards once
 	  produced by Madge Networks Ltd. Say Y (or M to compile as a module
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 59651ab..b34b382 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -1040,7 +1040,7 @@
   struct atm_qos * qos;
   struct atm_trafprm * txtp;
   struct atm_trafprm * rxtp;
-  u16 tx_rate_bits;
+  u16 tx_rate_bits = -1; // hush gcc
   u16 tx_vc_bits = -1; // hush gcc
   u16 tx_frame_bits = -1; // hush gcc
   
@@ -1096,6 +1096,8 @@
 	    r = round_up;
 	  }
 	  error = make_rate (pcr, r, &tx_rate_bits, NULL);
+	  if (error)
+	    return error;
 	  tx_vc_bits = TX_UBR_CAPPED;
 	  tx_frame_bits = TX_FRAME_CAPPED;
 	}
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 0d3a38b..77637e7 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1704,7 +1704,6 @@
 	struct pci_dev *pci_dev;
 	unsigned long real_base;
 	void __iomem *base;
-	unsigned char revision;
 	int error,i,last;
 
 	DPRINTK(">eni_init\n");
@@ -1715,12 +1714,6 @@
 	pci_dev = eni_dev->pci_dev;
 	real_base = pci_resource_start(pci_dev, 0);
 	eni_dev->irq = pci_dev->irq;
-	error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision);
-	if (error) {
-		printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",
-		    dev->number,error);
-		return -EINVAL;
-	}
 	if ((error = pci_write_config_word(pci_dev,PCI_COMMAND,
 	    PCI_COMMAND_MEMORY |
 	    (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
@@ -1729,7 +1722,7 @@
 		return -EIO;
 	}
 	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
-	    dev->number,revision,real_base,eni_dev->irq);
+	    dev->number,pci_dev->revision,real_base,eni_dev->irq);
 	if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) {
 		printk("\n");
 		printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 9c67df5..38b688f 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1475,6 +1475,7 @@
 	struct FS_BPENTRY *qe, *ne;
 	struct sk_buff *skb;
 	int n = 0;
+	u32 qe_tmp;
 
 	fs_dprintk (FS_DEBUG_QUEUE, "Topping off queue at %x (%d-%d/%d)\n", 
 		    fp->offset, read_fs (dev, FP_CNT (fp->offset)), fp->n, 
@@ -1502,10 +1503,16 @@
 		ne->skb = skb;
 		ne->fp = fp;
 
-		qe = (struct FS_BPENTRY *) (read_fs (dev, FP_EA(fp->offset)));
-		fs_dprintk (FS_DEBUG_QUEUE, "link at %p\n", qe);
-		if (qe) {
-			qe = bus_to_virt ((long) qe);
+		/*
+		 * FIXME: following code encodes and decodes
+		 * machine pointers (could be 64-bit) into a
+		 * 32-bit register.
+		 */
+
+		qe_tmp = read_fs (dev, FP_EA(fp->offset));
+		fs_dprintk (FS_DEBUG_QUEUE, "link at %x\n", qe_tmp);
+		if (qe_tmp) {
+			qe = bus_to_virt ((long) qe_tmp);
 			qe->next = virt_to_bus(ne);
 			qe->flags &= ~FP_FLAGS_EPI;
 		} else
@@ -1647,7 +1654,7 @@
 {
 	struct fs_dev *dev = (struct fs_dev *) data;
   
-	fs_irq (0, dev, NULL);
+	fs_irq (0, dev);
 	dev->timer.expires = jiffies + FS_POLL_FREQ;
 	add_timer (&dev->timer);
 }
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 057efbc..8f995ce 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -47,7 +47,8 @@
 #include <linux/bitops.h>
 #include <linux/wait.h>
 #include <linux/jiffies.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
+
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
@@ -2435,7 +2436,7 @@
 
 	set_bit(ATM_VF_ADDR, &vcc->flags);
 
-	down(&card->mutex);
+	mutex_lock(&card->mutex);
 
 	OPRINTK("%s: opening vpi.vci: %d.%d\n", card->name, vpi, vci);
 
@@ -2446,7 +2447,7 @@
 		break;
 	default:
 		printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
-		up(&card->mutex);
+		mutex_unlock(&card->mutex);
 		return -EPROTONOSUPPORT;
 	}
 
@@ -2455,7 +2456,7 @@
 		card->vcs[index] = kzalloc(sizeof(struct vc_map), GFP_KERNEL);
 		if (!card->vcs[index]) {
 			printk("%s: can't alloc vc in open()\n", card->name);
-			up(&card->mutex);
+			mutex_unlock(&card->mutex);
 			return -ENOMEM;
 		}
 		card->vcs[index]->card = card;
@@ -2484,14 +2485,14 @@
 	if (inuse) {
 		printk("%s: %s vci already in use.\n", card->name,
 		       inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx");
-		up(&card->mutex);
+		mutex_unlock(&card->mutex);
 		return -EADDRINUSE;
 	}
 
 	if (vcc->qos.txtp.traffic_class != ATM_NONE) {
 		error = idt77252_init_tx(card, vc, vcc, &vcc->qos);
 		if (error) {
-			up(&card->mutex);
+			mutex_unlock(&card->mutex);
 			return error;
 		}
 	}
@@ -2499,14 +2500,14 @@
 	if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
 		error = idt77252_init_rx(card, vc, vcc, &vcc->qos);
 		if (error) {
-			up(&card->mutex);
+			mutex_unlock(&card->mutex);
 			return error;
 		}
 	}
 
 	set_bit(ATM_VF_READY, &vcc->flags);
 
-	up(&card->mutex);
+	mutex_unlock(&card->mutex);
 	return 0;
 }
 
@@ -2520,7 +2521,7 @@
 	unsigned long addr;
 	unsigned long timeout;
 
-	down(&card->mutex);
+	mutex_lock(&card->mutex);
 
 	IPRINTK("%s: idt77252_close: vc = %d (%d.%d)\n",
 		card->name, vc->index, vcc->vpi, vcc->vci);
@@ -2591,7 +2592,7 @@
 		free_scq(card, vc->scq);
 	}
 
-	up(&card->mutex);
+	mutex_unlock(&card->mutex);
 }
 
 static int
@@ -2602,7 +2603,7 @@
 	struct vc_map *vc = vcc->dev_data;
 	int error = 0;
 
-	down(&card->mutex);
+	mutex_lock(&card->mutex);
 
 	if (qos->txtp.traffic_class != ATM_NONE) {
 	    	if (!test_bit(VCF_TX, &vc->flags)) {
@@ -2648,7 +2649,7 @@
 	set_bit(ATM_VF_HASQOS, &vcc->flags);
 
 out:
-	up(&card->mutex);
+	mutex_unlock(&card->mutex);
 	return error;
 }
 
@@ -3678,7 +3679,6 @@
 	unsigned long membase, srambase;
 	struct idt77252_dev *card;
 	struct atm_dev *dev;
-	ushort revision = 0;
 	int i, err;
 
 
@@ -3687,19 +3687,13 @@
 		return err;
 	}
 
-	if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) {
-		printk("idt77252-%d: can't read PCI_REVISION_ID\n", index);
-		err = -ENODEV;
-		goto err_out_disable_pdev;
-	}
-
 	card = kzalloc(sizeof(struct idt77252_dev), GFP_KERNEL);
 	if (!card) {
 		printk("idt77252-%d: can't allocate private data\n", index);
 		err = -ENOMEM;
 		goto err_out_disable_pdev;
 	}
-	card->revision = revision;
+	card->revision = pcidev->revision;
 	card->index = index;
 	card->pcidev = pcidev;
 	sprintf(card->name, "idt77252-%d", card->index);
@@ -3709,7 +3703,7 @@
 	membase = pci_resource_start(pcidev, 1);
 	srambase = pci_resource_start(pcidev, 2);
 
-	init_MUTEX(&card->mutex);
+	mutex_init(&card->mutex);
 	spin_lock_init(&card->cmd_lock);
 	spin_lock_init(&card->tst_lock);
 
@@ -3761,8 +3755,8 @@
 	}
 
 	printk("%s: ABR SAR (Rev %c): MEM %08lx SRAM %08lx [%u KB]\n",
-	       card->name, ((revision > 1) && (revision < 25)) ?
-	       'A' + revision - 1 : '?', membase, srambase,
+	       card->name, ((card->revision > 1) && (card->revision < 25)) ?
+	       'A' + card->revision - 1 : '?', membase, srambase,
 	       card->sramsize / 1024);
 
 	if (init_card(dev)) {
diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h
index 544b397..6f2b4a5 100644
--- a/drivers/atm/idt77252.h
+++ b/drivers/atm/idt77252.h
@@ -37,7 +37,7 @@
 #include <linux/ptrace.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
-
+#include <linux/mutex.h>
 
 /*****************************************************************************/
 /*                                                                           */
@@ -359,7 +359,7 @@
 	unsigned long		srambase;	/* SAR's sram  base address */
 	void __iomem		*fbq[4];	/* FBQ fill addresses */
 
-	struct semaphore	mutex;
+	struct mutex		mutex;
 	spinlock_t		cmd_lock;	/* for r/w utility/sram */
 
 	unsigned long		softstat;
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index bb7ef57..a3b605a 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -2290,7 +2290,6 @@
 	unsigned long real_base;
 	void __iomem *base;
 	unsigned short command;  
-	unsigned char revision;  
 	int error, i; 
 	  
 	/* The device has been identified and registered. Now we read   
@@ -2305,16 +2304,14 @@
 	real_base = pci_resource_start (iadev->pci, 0);
 	iadev->irq = iadev->pci->irq;
 		  
-	if ((error = pci_read_config_word(iadev->pci, PCI_COMMAND,&command))   
-		    || (error = pci_read_config_byte(iadev->pci,   
-				PCI_REVISION_ID,&revision)))   
-	{  
+	error = pci_read_config_word(iadev->pci, PCI_COMMAND, &command);
+	if (error) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%x\n",  
 				dev->number,error);  
 		return -EINVAL;  
 	}  
 	IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%lx,irq=%d\n",  
-			dev->number, revision, real_base, iadev->irq);)  
+			dev->number, iadev->pci->revision, real_base, iadev->irq);)
 	  
 	/* find mapping size of board */  
 	  
@@ -2353,7 +2350,7 @@
 		return error;  
 	}  
 	IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n",  
-			dev->number, revision, base, iadev->irq);)  
+			dev->number, iadev->pci->revision, base, iadev->irq);)
 	  
 	/* filling the iphase dev structure */  
 	iadev->mem = iadev->pci_map_size /2;  
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 09f477d..0e2c1ae 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -246,8 +246,8 @@
 };
 
 enum lanai_type {
-	lanai2	= PCI_VENDOR_ID_EF_ATM_LANAI2,
-	lanaihb	= PCI_VENDOR_ID_EF_ATM_LANAIHB
+	lanai2	= PCI_DEVICE_ID_EF_ATM_LANAI2,
+	lanaihb	= PCI_DEVICE_ID_EF_ATM_LANAIHB
 };
 
 struct lanai_dev_stats {
@@ -293,7 +293,6 @@
 	struct atm_vcc *cbrvcc;
 	int number;
 	int board_rev;
-	u8 pci_revision;
 /* TODO - look at race conditions with maintence of conf1/conf2 */
 /* TODO - transmit locking: should we use _irq not _irqsave? */
 /* TODO - organize above in some rational fashion (see <asm/cache.h>) */
@@ -1969,14 +1968,6 @@
 		    "(itf %d): No suitable DMA available.\n", lanai->number);
 		return -EBUSY;
 	}
-	/* Get the pci revision byte */
-	result = pci_read_config_byte(pci, PCI_REVISION_ID,
-	    &lanai->pci_revision);
-	if (result != PCIBIOS_SUCCESSFUL) {
-		printk(KERN_ERR DEV_LABEL "(itf %d): can't read "
-		    "PCI_REVISION_ID: %d\n", lanai->number, result);
-		return -EINVAL;
-	}
 	result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w);
 	if (result != PCIBIOS_SUCCESSFUL) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): can't read "
@@ -2254,7 +2245,7 @@
 	lanai_timed_poll_start(lanai);
 	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d, base=0x%lx, irq=%u "
 	    "(%02X-%02X-%02X-%02X-%02X-%02X)\n", lanai->number,
-	    (int) lanai->pci_revision, (unsigned long) lanai->base,
+	    (int) lanai->pci->revision, (unsigned long) lanai->base,
 	    lanai->pci->irq,
 	    atmdev->esi[0], atmdev->esi[1], atmdev->esi[2],
 	    atmdev->esi[3], atmdev->esi[4], atmdev->esi[5]);
@@ -2491,7 +2482,7 @@
 		    (unsigned int) lanai->magicno, lanai->num_vci);
 	if (left-- == 0)
 		return sprintf(page, "revision: board=%d, pci_if=%d\n",
-		    lanai->board_rev, (int) lanai->pci_revision);
+		    lanai->board_rev, (int) lanai->pci->revision);
 	if (left-- == 0)
 		return sprintf(page, "EEPROM ESI: "
 		    "%02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -2631,14 +2622,8 @@
 }
 
 static struct pci_device_id lanai_pci_tbl[] = {
-	{
-		PCI_VENDOR_ID_EF, PCI_VENDOR_ID_EF_ATM_LANAI2,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
-	},
-	{
-		PCI_VENDOR_ID_EF, PCI_VENDOR_ID_EF_ATM_LANAIHB,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
-	},
+	{ PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAI2) },
+	{ PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAIHB) },
 	{ 0, }	/* terminal entry */
 };
 MODULE_DEVICE_TABLE(pci, lanai_pci_tbl);
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 2ad2527..58583c6 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -915,7 +915,7 @@
 	unsigned long flags;
 	u32 *loop;
 	unsigned short chan;
-	int pcr,unlimited;
+	int unlimited;
 
 	DPRINTK("open_tx_first\n");
 	zatm_dev = ZATM_DEV(vcc->dev);
@@ -936,6 +936,8 @@
 	    vcc->qos.txtp.max_pcr >= ATM_OC3_PCR);
 	if (unlimited && zatm_dev->ubr != -1) zatm_vcc->shaper = zatm_dev->ubr;
 	else {
+		int uninitialized_var(pcr);
+
 		if (unlimited) vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU;
 		if ((zatm_vcc->shaper = alloc_shaper(vcc->dev,&pcr,
 		    vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,unlimited))
@@ -1182,7 +1184,6 @@
 	struct zatm_dev *zatm_dev;
 	struct pci_dev *pci_dev;
 	unsigned short command;
-	unsigned char revision;
 	int error,i,last;
 	unsigned long t0,t1,t2;
 
@@ -1192,8 +1193,7 @@
 	pci_dev = zatm_dev->pci_dev;
 	zatm_dev->base = pci_resource_start(pci_dev, 0);
 	zatm_dev->irq = pci_dev->irq;
-	if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command)) ||
-	    (error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision))) {
+	if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command))) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",
 		    dev->number,error);
 		return -EINVAL;
@@ -1206,7 +1206,7 @@
 	}
 	eprom_get_esi(dev);
 	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%x,irq=%d,",
-	    dev->number,revision,zatm_dev->base,zatm_dev->irq);
+	    dev->number,pci_dev->revision,zatm_dev->base,zatm_dev->irq);
 	/* reset uPD98401 */
 	zout(0,SWR);
 	while (!(zin(GSR) & uPD98401_INT_IND));
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index 2e18a63e..de2fcce 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -5,8 +5,11 @@
 # Auxiliary display drivers configuration.
 #
 
-menu "Auxiliary Display support"
+menuconfig AUXDISPLAY
 	depends on PARPORT
+	bool "Auxiliary Display support"
+
+if AUXDISPLAY && PARPORT
 
 config KS0108
 	tristate "KS0108 LCD Controller"
@@ -68,6 +71,10 @@
 	depends on X86
 	depends on FB
 	depends on KS0108
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
 	default n
 	---help---
 	  If you have a Crystalfontz 128x64 2-color LCD, cfag12864b Series,
@@ -107,4 +114,5 @@
 
 	  If you compile this as a module, you can still override this
 	  value using the module parameters.
-endmenu
+
+endif # AUXDISPLAY
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c
index 66fafbb..307c190 100644
--- a/drivers/auxdisplay/cfag12864bfb.c
+++ b/drivers/auxdisplay/cfag12864bfb.c
@@ -73,9 +73,11 @@
 
 static struct fb_ops cfag12864bfb_ops = {
 	.owner = THIS_MODULE,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
+	.fb_read = fb_sys_read,
+	.fb_write = fb_sys_write,
+	.fb_fillrect = sys_fillrect,
+	.fb_copyarea = sys_copyarea,
+	.fb_imageblit = sys_imageblit,
 	.fb_mmap = cfag12864bfb_mmap,
 };
 
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 1ec0654..7370d7c 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 
 #include "base.h"
 
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 5512d84..47eb02d 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -44,6 +44,6 @@
 
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
-extern void devres_release_all(struct device *dev);
+extern int devres_release_all(struct device *dev);
 
 extern struct kset devices_subsys;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index dca7348..61c6752 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -138,12 +138,24 @@
 	}
 }
 
-static struct kobj_type ktype_bus = {
+static struct kobj_type bus_ktype = {
 	.sysfs_ops	= &bus_sysfs_ops,
-
 };
 
-static decl_subsys(bus, &ktype_bus, NULL);
+static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
+{
+	struct kobj_type *ktype = get_ktype(kobj);
+
+	if (ktype == &bus_ktype)
+		return 1;
+	return 0;
+}
+
+static struct kset_uevent_ops bus_uevent_ops = {
+	.filter = bus_uevent_filter,
+};
+
+static decl_subsys(bus, &bus_ktype, &bus_uevent_ops);
 
 
 #ifdef CONFIG_HOTPLUG
@@ -562,7 +574,6 @@
 
 	bus->drivers_probe_attr.attr.name = "drivers_probe";
 	bus->drivers_probe_attr.attr.mode = S_IWUSR;
-	bus->drivers_probe_attr.attr.owner = bus->owner;
 	bus->drivers_probe_attr.store = store_drivers_probe;
 	retval = bus_create_file(bus, &bus->drivers_probe_attr);
 	if (retval)
@@ -570,7 +581,6 @@
 
 	bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
 	bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
-	bus->drivers_autoprobe_attr.attr.owner = bus->owner;
 	bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
 	bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
 	retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
@@ -610,7 +620,8 @@
 	if (error)
 		goto out_put_bus;
 	drv->kobj.kset = &bus->drivers;
-	if ((error = kobject_register(&drv->kobj)))
+	error = kobject_register(&drv->kobj);
+	if (error)
 		goto out_put_bus;
 
 	if (drv->bus->drivers_autoprobe) {
@@ -760,7 +771,8 @@
 
 	if (bus->bus_attrs) {
 		for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
-			if ((error = bus_create_file(bus,&bus->bus_attrs[i])))
+			error = bus_create_file(bus,&bus->bus_attrs[i]);
+			if (error)
 				goto Err;
 		}
 	}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 20c4ea6..4d22226 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -312,9 +312,6 @@
 
 	pr_debug("device class '%s': release.\n", cd->class_id);
 
-	kfree(cd->devt_attr);
-	cd->devt_attr = NULL;
-
 	if (cd->release)
 		cd->release(cd);
 	else if (cls->release)
@@ -369,36 +366,6 @@
 	return class_name;
 }
 
-static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index,
-				   char *buffer, int buffer_size,
-				   int *cur_len,
-				   struct class_device *class_dev)
-{
-	struct device *dev = class_dev->dev;
-	char *path;
-
-	if (!dev)
-		return 0;
-
-	/* add device, backing this class device (deprecated) */
-	path = kobject_get_path(&dev->kobj, GFP_KERNEL);
-
-	add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size,
-		       cur_len, "PHYSDEVPATH=%s", path);
-	kfree(path);
-
-	if (dev->bus)
-		add_uevent_var(envp, num_envp, cur_index,
-			       buffer, buffer_size, cur_len,
-			       "PHYSDEVBUS=%s", dev->bus->name);
-
-	if (dev->driver)
-		add_uevent_var(envp, num_envp, cur_index,
-			       buffer, buffer_size, cur_len,
-			       "PHYSDEVDRIVER=%s", dev->driver->name);
-	return 0;
-}
-
 static int make_deprecated_class_device_links(struct class_device *class_dev)
 {
 	char *class_name;
@@ -430,11 +397,6 @@
 	kfree(class_name);
 }
 #else
-static inline int deprecated_class_uevent(char **envp, int num_envp,
-					  int *cur_index, char *buffer,
-					  int buffer_size, int *cur_len,
-					  struct class_device *class_dev)
-{ return 0; }
 static inline int make_deprecated_class_device_links(struct class_device *cd)
 { return 0; }
 static void remove_deprecated_class_device_links(struct class_device *cd)
@@ -445,15 +407,13 @@
 			 int num_envp, char *buffer, int buffer_size)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
+	struct device *dev = class_dev->dev;
 	int i = 0;
 	int length = 0;
 	int retval = 0;
 
 	pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
 
-	deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
-				&length, class_dev);
-
 	if (MAJOR(class_dev->devt)) {
 		add_uevent_var(envp, num_envp, &i,
 			       buffer, buffer_size, &length,
@@ -464,6 +424,26 @@
 			       "MINOR=%u", MINOR(class_dev->devt));
 	}
 
+	if (dev) {
+		const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+		if (path) {
+			add_uevent_var(envp, num_envp, &i,
+				       buffer, buffer_size, &length,
+				       "PHYSDEVPATH=%s", path);
+			kfree(path);
+		}
+
+		if (dev->bus)
+			add_uevent_var(envp, num_envp, &i,
+				       buffer, buffer_size, &length,
+				       "PHYSDEVBUS=%s", dev->bus->name);
+
+		if (dev->driver)
+			add_uevent_var(envp, num_envp, &i,
+				       buffer, buffer_size, &length,
+				       "PHYSDEVDRIVER=%s", dev->driver->name);
+	}
+
 	/* terminate, set to next free slot, shrink available space */
 	envp[i] = NULL;
 	envp = &envp[i];
@@ -564,6 +544,9 @@
 	return print_dev_t(buf, class_dev->devt);
 }
 
+static struct class_device_attribute class_devt_attr =
+	__ATTR(dev, S_IRUGO, show_dev, NULL);
+
 static ssize_t store_uevent(struct class_device *class_dev,
 			    const char *buf, size_t count)
 {
@@ -571,6 +554,9 @@
 	return count;
 }
 
+static struct class_device_attribute class_uevent_attr =
+	__ATTR(uevent, S_IWUSR, NULL, store_uevent);
+
 void class_device_initialize(struct class_device *class_dev)
 {
 	kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -620,32 +606,15 @@
 				  &parent_class->subsys.kobj, "subsystem");
 	if (error)
 		goto out3;
-	class_dev->uevent_attr.attr.name = "uevent";
-	class_dev->uevent_attr.attr.mode = S_IWUSR;
-	class_dev->uevent_attr.attr.owner = parent_class->owner;
-	class_dev->uevent_attr.store = store_uevent;
-	error = class_device_create_file(class_dev, &class_dev->uevent_attr);
+
+	error = class_device_create_file(class_dev, &class_uevent_attr);
 	if (error)
 		goto out3;
 
 	if (MAJOR(class_dev->devt)) {
-		struct class_device_attribute *attr;
-		attr = kzalloc(sizeof(*attr), GFP_KERNEL);
-		if (!attr) {
-			error = -ENOMEM;
+		error = class_device_create_file(class_dev, &class_devt_attr);
+		if (error)
 			goto out4;
-		}
-		attr->attr.name = "dev";
-		attr->attr.mode = S_IRUGO;
-		attr->attr.owner = parent_class->owner;
-		attr->show = show_dev;
-		error = class_device_create_file(class_dev, attr);
-		if (error) {
-			kfree(attr);
-			goto out4;
-		}
-
-		class_dev->devt_attr = attr;
 	}
 
 	error = class_device_add_attrs(class_dev);
@@ -688,10 +657,10 @@
  out6:
 	class_device_remove_attrs(class_dev);
  out5:
-	if (class_dev->devt_attr)
-		class_device_remove_file(class_dev, class_dev->devt_attr);
+	if (MAJOR(class_dev->devt))
+		class_device_remove_file(class_dev, &class_devt_attr);
  out4:
-	class_device_remove_file(class_dev, &class_dev->uevent_attr);
+	class_device_remove_file(class_dev, &class_uevent_attr);
  out3:
 	kobject_del(&class_dev->kobj);
  out2:
@@ -791,9 +760,9 @@
 		sysfs_remove_link(&class_dev->kobj, "device");
 	}
 	sysfs_remove_link(&class_dev->kobj, "subsystem");
-	class_device_remove_file(class_dev, &class_dev->uevent_attr);
-	if (class_dev->devt_attr)
-		class_device_remove_file(class_dev, class_dev->devt_attr);
+	class_device_remove_file(class_dev, &class_uevent_attr);
+	if (MAJOR(class_dev->devt))
+		class_device_remove_file(class_dev, &class_devt_attr);
 	class_device_remove_attrs(class_dev);
 	class_device_remove_groups(class_dev);
 
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b78fc1e..0455aa7 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -180,10 +180,12 @@
 			const char *path;
 
 			path = kobject_get_path(&parent->kobj, GFP_KERNEL);
-			add_uevent_var(envp, num_envp, &i,
-				       buffer, buffer_size, &length,
-				       "PHYSDEVPATH=%s", path);
-			kfree(path);
+			if (path) {
+				add_uevent_var(envp, num_envp, &i,
+					       buffer, buffer_size, &length,
+					       "PHYSDEVPATH=%s", path);
+				kfree(path);
+			}
 
 			add_uevent_var(envp, num_envp, &i,
 				       buffer, buffer_size, &length,
@@ -308,6 +310,9 @@
 	return count;
 }
 
+static struct device_attribute uevent_attr =
+	__ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
+
 static int device_add_attributes(struct device *dev,
 				 struct device_attribute *attrs)
 {
@@ -421,6 +426,9 @@
 	return print_dev_t(buf, dev->devt);
 }
 
+static struct device_attribute devt_attr =
+	__ATTR(dev, S_IRUGO, show_dev, NULL);
+
 /*
  *	devices_subsys - structure to be registered with kobject core.
  */
@@ -679,35 +687,14 @@
 		blocking_notifier_call_chain(&dev->bus->bus_notifier,
 					     BUS_NOTIFY_ADD_DEVICE, dev);
 
-	dev->uevent_attr.attr.name = "uevent";
-	dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
-	if (dev->driver)
-		dev->uevent_attr.attr.owner = dev->driver->owner;
-	dev->uevent_attr.store = store_uevent;
-	dev->uevent_attr.show = show_uevent;
-	error = device_create_file(dev, &dev->uevent_attr);
+	error = device_create_file(dev, &uevent_attr);
 	if (error)
 		goto attrError;
 
 	if (MAJOR(dev->devt)) {
-		struct device_attribute *attr;
-		attr = kzalloc(sizeof(*attr), GFP_KERNEL);
-		if (!attr) {
-			error = -ENOMEM;
+		error = device_create_file(dev, &devt_attr);
+		if (error)
 			goto ueventattrError;
-		}
-		attr->attr.name = "dev";
-		attr->attr.mode = S_IRUGO;
-		if (dev->driver)
-			attr->attr.owner = dev->driver->owner;
-		attr->show = show_dev;
-		error = device_create_file(dev, attr);
-		if (error) {
-			kfree(attr);
-			goto ueventattrError;
-		}
-
-		dev->devt_attr = attr;
 	}
 
 	if (dev->class) {
@@ -731,11 +718,14 @@
 		}
 	}
 
-	if ((error = device_add_attrs(dev)))
+	error = device_add_attrs(dev);
+	if (error)
 		goto AttrsError;
-	if ((error = device_pm_add(dev)))
+	error = device_pm_add(dev);
+	if (error)
 		goto PMError;
-	if ((error = bus_add_device(dev)))
+	error = bus_add_device(dev);
+	if (error)
 		goto BusError;
 	kobject_uevent(&dev->kobj, KOBJ_ADD);
 	bus_attach_device(dev);
@@ -765,10 +755,8 @@
 					     BUS_NOTIFY_DEL_DEVICE, dev);
 	device_remove_attrs(dev);
  AttrsError:
-	if (dev->devt_attr) {
-		device_remove_file(dev, dev->devt_attr);
-		kfree(dev->devt_attr);
-	}
+	if (MAJOR(dev->devt))
+		device_remove_file(dev, &devt_attr);
 
 	if (dev->class) {
 		sysfs_remove_link(&dev->kobj, "subsystem");
@@ -790,7 +778,7 @@
 		}
 	}
  ueventattrError:
-	device_remove_file(dev, &dev->uevent_attr);
+	device_remove_file(dev, &uevent_attr);
  attrError:
 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
 	kobject_del(&dev->kobj);
@@ -867,10 +855,8 @@
 
 	if (parent)
 		klist_del(&dev->knode_parent);
-	if (dev->devt_attr) {
-		device_remove_file(dev, dev->devt_attr);
-		kfree(dev->devt_attr);
-	}
+	if (MAJOR(dev->devt))
+		device_remove_file(dev, &devt_attr);
 	if (dev->class) {
 		sysfs_remove_link(&dev->kobj, "subsystem");
 		/* If this is not a "fake" compatible device, remove the
@@ -924,7 +910,7 @@
 			up(&dev->class->sem);
 		}
 	}
-	device_remove_file(dev, &dev->uevent_attr);
+	device_remove_file(dev, &uevent_attr);
 	device_remove_attrs(dev);
 	bus_remove_device(dev);
 
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 92428e5..7ac474d 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -207,19 +207,6 @@
 	return driver_probe_device(drv, dev);
 }
 
-static int device_probe_drivers(void *data)
-{
-	struct device *dev = data;
-	int ret = 0;
-
-	if (dev->bus) {
-		down(&dev->sem);
-		ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
-		up(&dev->sem);
-	}
-	return ret;
-}
-
 /**
  *	device_attach - try to attach device to a driver.
  *	@dev:	device.
@@ -294,24 +281,16 @@
 	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
 }
 
-/**
- *	device_release_driver - manually detach device from driver.
- *	@dev:	device.
- *
- *	Manually detach device from driver.
- *
+/*
  *	__device_release_driver() must be called with @dev->sem held.
- *	When called for a USB interface, @dev->parent->sem must be held
- *	as well.
+ *	When called for a USB interface, @dev->parent->sem must be held as well.
  */
-
 static void __device_release_driver(struct device * dev)
 {
 	struct device_driver * drv;
 
-	drv = dev->driver;
+	drv = get_driver(dev->driver);
 	if (drv) {
-		get_driver(drv);
 		driver_sysfs_remove(dev);
 		sysfs_remove_link(&dev->kobj, "driver");
 		klist_remove(&dev->knode_driver);
@@ -331,6 +310,13 @@
 	}
 }
 
+/**
+ *	device_release_driver - manually detach device from driver.
+ *	@dev:	device.
+ *
+ *	Manually detach device from driver.
+ *	When called for a USB interface, @dev->parent->sem must be held.
+ */
 void device_release_driver(struct device * dev)
 {
 	/*
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index e1c0730..e8beb8e 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -10,6 +10,8 @@
 #include <linux/device.h>
 #include <linux/module.h>
 
+#include "base.h"
+
 struct devres_node {
 	struct list_head		entry;
 	dr_release_t			release;
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index 9406259..7647abf 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -8,6 +8,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/poison.h>
+#include <linux/sched.h>
 
 /*
  * Pool allocator ... wraps the dma_alloc_coherent page allocator, so
@@ -126,7 +127,7 @@
 	} else if (allocation < size)
 		return NULL;
 
-	if (!(retval = kmalloc (sizeof *retval, GFP_KERNEL)))
+	if (!(retval = kmalloc_node (sizeof *retval, GFP_KERNEL, dev_to_node(dev))))
 		return retval;
 
 	strlcpy (retval->name, name, sizeof retval->name);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 97ab5bd..53f0ee6 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1,7 +1,7 @@
 /*
  * firmware_class.c - Multi purpose firmware loading support
  *
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
  *
  * Please see Documentation/firmware_class/ for more information.
  *
@@ -23,7 +23,7 @@
 
 #define to_dev(obj) container_of(obj, struct device, kobj)
 
-MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
+MODULE_AUTHOR("Manuel Estrada Sainz");
 MODULE_DESCRIPTION("Multi purpose firmware loading support");
 MODULE_LICENSE("GPL");
 
@@ -175,7 +175,7 @@
 static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
 
 static ssize_t
-firmware_data_read(struct kobject *kobj,
+firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
 		   char *buffer, loff_t offset, size_t count)
 {
 	struct device *dev = to_dev(kobj);
@@ -240,7 +240,7 @@
  *	the driver as a firmware image.
  **/
 static ssize_t
-firmware_data_write(struct kobject *kobj,
+firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
 		    char *buffer, loff_t offset, size_t count)
 {
 	struct device *dev = to_dev(kobj);
@@ -271,7 +271,7 @@
 }
 
 static struct bin_attribute firmware_attr_data_tmpl = {
-	.attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
+	.attr = {.name = "data", .mode = 0644},
 	.size = 0,
 	.read = firmware_data_read,
 	.write = firmware_data_write,
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 05dc876..eb9f38d 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -20,64 +20,44 @@
  */
 
 #include <linux/device.h>
+#include <linux/mutex.h>
+
 #include "power.h"
 
 LIST_HEAD(dpm_active);
 LIST_HEAD(dpm_off);
 LIST_HEAD(dpm_off_irq);
 
-DECLARE_MUTEX(dpm_sem);
-DECLARE_MUTEX(dpm_list_sem);
+DEFINE_MUTEX(dpm_mtx);
+DEFINE_MUTEX(dpm_list_mtx);
 
 int (*platform_enable_wakeup)(struct device *dev, int is_on);
 
-
-/**
- *	device_pm_set_parent - Specify power dependency.
- *	@dev:		Device who needs power.
- *	@parent:	Device that supplies power.
- *
- *	This function is used to manually describe a power-dependency
- *	relationship. It may be used to specify a transversal relationship
- *	(where the power supplier is not the physical (or electrical)
- *	ancestor of a specific device.
- *	The effect of this is that the supplier will not be powered down
- *	before the power dependent.
- */
-
-void device_pm_set_parent(struct device * dev, struct device * parent)
-{
-	put_device(dev->power.pm_parent);
-	dev->power.pm_parent = get_device(parent);
-}
-EXPORT_SYMBOL_GPL(device_pm_set_parent);
-
-int device_pm_add(struct device * dev)
+int device_pm_add(struct device *dev)
 {
 	int error;
 
 	pr_debug("PM: Adding info for %s:%s\n",
 		 dev->bus ? dev->bus->name : "No Bus",
 		 kobject_name(&dev->kobj));
-	down(&dpm_list_sem);
+	mutex_lock(&dpm_list_mtx);
 	list_add_tail(&dev->power.entry, &dpm_active);
-	device_pm_set_parent(dev, dev->parent);
-	if ((error = dpm_sysfs_add(dev)))
+	error = dpm_sysfs_add(dev);
+	if (error)
 		list_del(&dev->power.entry);
-	up(&dpm_list_sem);
+	mutex_unlock(&dpm_list_mtx);
 	return error;
 }
 
-void device_pm_remove(struct device * dev)
+void device_pm_remove(struct device *dev)
 {
 	pr_debug("PM: Removing info for %s:%s\n",
 		 dev->bus ? dev->bus->name : "No Bus",
 		 kobject_name(&dev->kobj));
-	down(&dpm_list_sem);
+	mutex_lock(&dpm_list_mtx);
 	dpm_sysfs_remove(dev);
-	put_device(dev->power.pm_parent);
 	list_del_init(&dev->power.entry);
-	up(&dpm_list_sem);
+	mutex_unlock(&dpm_list_mtx);
 }
 
 
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index fb3d35a..2760f25 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -14,12 +14,12 @@
 /*
  * Used to synchronize global power management operations.
  */
-extern struct semaphore dpm_sem;
+extern struct mutex dpm_mtx;
 
 /*
  * Used to serialize changes to the dpm_* lists.
  */
-extern struct semaphore dpm_list_sem;
+extern struct mutex dpm_list_mtx;
 
 /*
  * The PM lists.
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index a2c6418..00fd84a 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -29,14 +29,6 @@
 
 	down(&dev->sem);
 
-	if (dev->power.pm_parent
-			&& dev->power.pm_parent->power.power_state.event) {
-		dev_err(dev, "PM: resume from %d, parent %s still %d\n",
-			dev->power.power_state.event,
-			dev->power.pm_parent->bus_id,
-			dev->power.pm_parent->power.power_state.event);
-	}
-
 	if (dev->bus && dev->bus->resume) {
 		dev_dbg(dev,"resuming\n");
 		error = dev->bus->resume(dev);
@@ -80,7 +72,7 @@
  */
 void dpm_resume(void)
 {
-	down(&dpm_list_sem);
+	mutex_lock(&dpm_list_mtx);
 	while(!list_empty(&dpm_off)) {
 		struct list_head * entry = dpm_off.next;
 		struct device * dev = to_device(entry);
@@ -88,13 +80,12 @@
 		get_device(dev);
 		list_move_tail(entry, &dpm_active);
 
-		up(&dpm_list_sem);
-		if (!dev->power.prev_state.event)
-			resume_device(dev);
-		down(&dpm_list_sem);
+		mutex_unlock(&dpm_list_mtx);
+		resume_device(dev);
+		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
 	}
-	up(&dpm_list_sem);
+	mutex_unlock(&dpm_list_mtx);
 }
 
 
@@ -108,9 +99,9 @@
 void device_resume(void)
 {
 	might_sleep();
-	down(&dpm_sem);
+	mutex_lock(&dpm_mtx);
 	dpm_resume();
-	up(&dpm_sem);
+	mutex_unlock(&dpm_mtx);
 }
 
 EXPORT_SYMBOL_GPL(device_resume);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 96370ec..df6174d 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -32,9 +32,9 @@
 
 void dpm_runtime_resume(struct device * dev)
 {
-	down(&dpm_sem);
+	mutex_lock(&dpm_mtx);
 	runtime_resume(dev);
-	up(&dpm_sem);
+	mutex_unlock(&dpm_mtx);
 }
 EXPORT_SYMBOL(dpm_runtime_resume);
 
@@ -49,7 +49,7 @@
 {
 	int error = 0;
 
-	down(&dpm_sem);
+	mutex_lock(&dpm_mtx);
 	if (dev->power.power_state.event == state.event)
 		goto Done;
 
@@ -59,7 +59,7 @@
 	if (!(error = suspend_device(dev, state)))
 		dev->power.power_state = state;
  Done:
-	up(&dpm_sem);
+	mutex_unlock(&dpm_mtx);
 	return error;
 }
 EXPORT_SYMBOL(dpm_runtime_suspend);
@@ -78,8 +78,8 @@
  */
 void dpm_set_power_state(struct device * dev, pm_message_t state)
 {
-	down(&dpm_sem);
+	mutex_lock(&dpm_mtx);
 	dev->power.power_state = state;
-	up(&dpm_sem);
+	mutex_unlock(&dpm_mtx);
 }
 #endif  /*  0  */
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 42d2b86..26df9b2 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -40,6 +40,14 @@
 }
 
 
+static void
+suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
+{
+	dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
+		((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
+		", may wakeup" : "");
+}
+
 /**
  *	suspend_device - Save state of one device.
  *	@dev:	Device.
@@ -55,49 +63,21 @@
 		dev_dbg(dev, "PM: suspend %d-->%d\n",
 			dev->power.power_state.event, state.event);
 	}
-	if (dev->power.pm_parent
-			&& dev->power.pm_parent->power.power_state.event) {
-		dev_err(dev,
-			"PM: suspend %d->%d, parent %s already %d\n",
-			dev->power.power_state.event, state.event,
-			dev->power.pm_parent->bus_id,
-			dev->power.pm_parent->power.power_state.event);
-	}
 
-	dev->power.prev_state = dev->power.power_state;
-
-	if (dev->class && dev->class->suspend && !dev->power.power_state.event) {
-		dev_dbg(dev, "class %s%s\n",
-			suspend_verb(state.event),
-			((state.event == PM_EVENT_SUSPEND)
-					&& device_may_wakeup(dev))
-				? ", may wakeup"
-				: ""
-			);
+	if (dev->class && dev->class->suspend) {
+		suspend_device_dbg(dev, state, "class ");
 		error = dev->class->suspend(dev, state);
 		suspend_report_result(dev->class->suspend, error);
 	}
 
-	if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) {
-		dev_dbg(dev, "%s%s\n",
-			suspend_verb(state.event),
-			((state.event == PM_EVENT_SUSPEND)
-					&& device_may_wakeup(dev))
-				? ", may wakeup"
-				: ""
-			);
+	if (!error && dev->type && dev->type->suspend) {
+		suspend_device_dbg(dev, state, "type ");
 		error = dev->type->suspend(dev, state);
 		suspend_report_result(dev->type->suspend, error);
 	}
 
-	if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
-		dev_dbg(dev, "%s%s\n",
-			suspend_verb(state.event),
-			((state.event == PM_EVENT_SUSPEND)
-					&& device_may_wakeup(dev))
-				? ", may wakeup"
-				: ""
-			);
+	if (!error && dev->bus && dev->bus->suspend) {
+		suspend_device_dbg(dev, state, "");
 		error = dev->bus->suspend(dev, state);
 		suspend_report_result(dev->bus->suspend, error);
 	}
@@ -108,21 +88,15 @@
 
 /*
  * This is called with interrupts off, only a single CPU
- * running. We can't do down() on a semaphore (and we don't
+ * running. We can't acquire a mutex or semaphore (and we don't
  * need the protection)
  */
 static int suspend_device_late(struct device *dev, pm_message_t state)
 {
 	int error = 0;
 
-	if (dev->bus && dev->bus->suspend_late && !dev->power.power_state.event) {
-		dev_dbg(dev, "LATE %s%s\n",
-			suspend_verb(state.event),
-			((state.event == PM_EVENT_SUSPEND)
-					&& device_may_wakeup(dev))
-				? ", may wakeup"
-				: ""
-			);
+	if (dev->bus && dev->bus->suspend_late) {
+		suspend_device_dbg(dev, state, "LATE ");
 		error = dev->bus->suspend_late(dev, state);
 		suspend_report_result(dev->bus->suspend_late, error);
 	}
@@ -153,18 +127,18 @@
 	int error = 0;
 
 	might_sleep();
-	down(&dpm_sem);
-	down(&dpm_list_sem);
+	mutex_lock(&dpm_mtx);
+	mutex_lock(&dpm_list_mtx);
 	while (!list_empty(&dpm_active) && error == 0) {
 		struct list_head * entry = dpm_active.prev;
 		struct device * dev = to_device(entry);
 
 		get_device(dev);
-		up(&dpm_list_sem);
+		mutex_unlock(&dpm_list_mtx);
 
 		error = suspend_device(dev, state);
 
-		down(&dpm_list_sem);
+		mutex_lock(&dpm_list_mtx);
 
 		/* Check if the device got removed */
 		if (!list_empty(&dev->power.entry)) {
@@ -179,11 +153,11 @@
 				error == -EAGAIN ? " (please convert to suspend_late)" : "");
 		put_device(dev);
 	}
-	up(&dpm_list_sem);
+	mutex_unlock(&dpm_list_mtx);
 	if (error)
 		dpm_resume();
 
-	up(&dpm_sem);
+	mutex_unlock(&dpm_mtx);
 	return error;
 }
 
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 29f1291..18febe2 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,7 +21,7 @@
 #include <linux/string.h>
 #include <linux/pm.h>
 #include <linux/device.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 #include "base.h"
 
@@ -155,7 +155,7 @@
 
 
 static LIST_HEAD(sysdev_drivers);
-static DECLARE_MUTEX(sysdev_drivers_lock);
+static DEFINE_MUTEX(sysdev_drivers_lock);
 
 /**
  *	sysdev_driver_register - Register auxillary driver
@@ -172,7 +172,7 @@
 int sysdev_driver_register(struct sysdev_class * cls,
 			   struct sysdev_driver * drv)
 {
-	down(&sysdev_drivers_lock);
+	mutex_lock(&sysdev_drivers_lock);
 	if (cls && kset_get(&cls->kset)) {
 		list_add_tail(&drv->entry, &cls->drivers);
 
@@ -184,7 +184,7 @@
 		}
 	} else
 		list_add_tail(&drv->entry, &sysdev_drivers);
-	up(&sysdev_drivers_lock);
+	mutex_unlock(&sysdev_drivers_lock);
 	return 0;
 }
 
@@ -197,7 +197,7 @@
 void sysdev_driver_unregister(struct sysdev_class * cls,
 			      struct sysdev_driver * drv)
 {
-	down(&sysdev_drivers_lock);
+	mutex_lock(&sysdev_drivers_lock);
 	list_del_init(&drv->entry);
 	if (cls) {
 		if (drv->remove) {
@@ -207,7 +207,7 @@
 		}
 		kset_put(&cls->kset);
 	}
-	up(&sysdev_drivers_lock);
+	mutex_unlock(&sysdev_drivers_lock);
 }
 
 EXPORT_SYMBOL_GPL(sysdev_driver_register);
@@ -246,7 +246,7 @@
 	if (!error) {
 		struct sysdev_driver * drv;
 
-		down(&sysdev_drivers_lock);
+		mutex_lock(&sysdev_drivers_lock);
 		/* Generic notification is implicit, because it's that
 		 * code that should have called us.
 		 */
@@ -262,7 +262,7 @@
 			if (drv->add)
 				drv->add(sysdev);
 		}
-		up(&sysdev_drivers_lock);
+		mutex_unlock(&sysdev_drivers_lock);
 	}
 	return error;
 }
@@ -271,7 +271,7 @@
 {
 	struct sysdev_driver * drv;
 
-	down(&sysdev_drivers_lock);
+	mutex_lock(&sysdev_drivers_lock);
 	list_for_each_entry(drv, &sysdev_drivers, entry) {
 		if (drv->remove)
 			drv->remove(sysdev);
@@ -281,7 +281,7 @@
 		if (drv->remove)
 			drv->remove(sysdev);
 	}
-	up(&sysdev_drivers_lock);
+	mutex_unlock(&sysdev_drivers_lock);
 
 	kobject_unregister(&sysdev->kobj);
 }
@@ -308,7 +308,7 @@
 
 	pr_debug("Shutting Down System Devices\n");
 
-	down(&sysdev_drivers_lock);
+	mutex_lock(&sysdev_drivers_lock);
 	list_for_each_entry_reverse(cls, &system_subsys.list,
 				    kset.kobj.entry) {
 		struct sys_device * sysdev;
@@ -337,7 +337,7 @@
 				cls->shutdown(sysdev);
 		}
 	}
-	up(&sysdev_drivers_lock);
+	mutex_unlock(&sysdev_drivers_lock);
 }
 
 static void __sysdev_resume(struct sys_device *dev)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b4c8319..8f65b88 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -2,9 +2,12 @@
 # Block device driver configuration
 #
 
-if BLOCK
+menuconfig BLK_DEV
+	bool "Block devices"
+	depends on BLOCK
+	default y
 
-menu "Block devices"
+if BLK_DEV
 
 config BLK_DEV_FD
 	tristate "Normal floppy disk support"
@@ -56,48 +59,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called z2ram.
 
-config ATARI_ACSI
-	tristate "Atari ACSI support"
-	depends on ATARI && BROKEN
-	---help---
-	  This enables support for the Atari ACSI interface. The driver
-	  supports hard disks and CD-ROMs, which have 512-byte sectors, or can
-	  be switched to that mode. Due to the ACSI command format, only disks
-	  up to 1 GB are supported. Special support for certain ACSI to SCSI
-	  adapters, which could relax that, isn't included yet. The ACSI
-	  driver is also the basis for certain other drivers for devices
-	  attached to the ACSI bus: Atari SLM laser printer, BioNet-100
-	  Ethernet, and PAMsNet Ethernet. If you want to use one of these
-	  devices, you need ACSI support, too.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called acsi.
-
-comment "Some devices (e.g. CD jukebox) support multiple LUNs"
-	depends on ATARI && ATARI_ACSI
-
-config ACSI_MULTI_LUN
-	bool "Probe all LUNs on each ACSI device"
-	depends on ATARI_ACSI
-	help
-	  If you have a ACSI device that supports more than one LUN (Logical
-	  Unit Number), e.g. a CD jukebox, you should say Y here so that all
-	  will be found by the ACSI driver. An ACSI device with multiple LUNs
-	  acts logically like multiple ACSI devices. The vast majority of ACSI
-	  devices have only one LUN, and so most people can say N here and
-	  should in fact do so, because it is safer.
-
-config ATARI_SLM
-	tristate "Atari SLM laser printer support"
-	depends on ATARI && ATARI_ACSI!=n
-	help
-	  If you have an Atari SLM laser printer, say Y to include support for
-	  it in the kernel. Otherwise, say N. This driver is also available as
-	  a module ( = code which can be inserted in and removed from the
-	  running kernel whenever you want). The module will be called
-	  acsi_slm. Be warned: the driver needs much ST-RAM and can cause
-	  problems due to that fact!
-
 config BLK_DEV_XD
 	tristate "XT hard disk support"
 	depends on ISA && ISA_DMA_API
@@ -141,7 +102,7 @@
 
 config BLK_CPQ_DA
 	tristate "Compaq SMART2 support"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	help
 	  This is the driver for Compaq Smart Array controllers.  Everyone
 	  using these boards should say Y here.  See the file
@@ -451,8 +412,19 @@
 	This driver provides Support for ATA over Ethernet block
 	devices like the Coraid EtherDrive (R) Storage Blade.
 
+config SUNVDC
+	tristate "Sun Virtual Disk Client support"
+	depends on SUN_LDOMS
+	help
+	  Support for virtual disk devices as a client under Sun
+	  Logical Domains.
+
 source "drivers/s390/block/Kconfig"
 
-endmenu
+config XILINX_SYSACE
+	tristate "Xilinx SystemACE support"
+	depends on 4xx
+	help
+	  Include support for the Xilinx SystemACE CompactFlash interface
 
-endif
+endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index dd88e33..9ee08ab 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,8 +9,6 @@
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy.o
 obj-$(CONFIG_AMIGA_FLOPPY)	+= amiflop.o
 obj-$(CONFIG_ATARI_FLOPPY)	+= ataflop.o
-obj-$(CONFIG_ATARI_ACSI)	+= acsi.o
-obj-$(CONFIG_ATARI_SLM)		+= acsi_slm.o
 obj-$(CONFIG_AMIGA_Z2RAM)	+= z2ram.o
 obj-$(CONFIG_BLK_DEV_RAM)	+= rd.o
 obj-$(CONFIG_BLK_DEV_LOOP)	+= loop.o
@@ -19,7 +17,9 @@
 obj-$(CONFIG_BLK_CPQ_DA)	+= cpqarray.o
 obj-$(CONFIG_BLK_CPQ_CISS_DA)  += cciss.o
 obj-$(CONFIG_BLK_DEV_DAC960)	+= DAC960.o
+obj-$(CONFIG_XILINX_SYSACE)	+= xsysace.o
 obj-$(CONFIG_CDROM_PKTCDVD)	+= pktcdvd.o
+obj-$(CONFIG_SUNVDC)		+= sunvdc.o
 
 obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
 obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
deleted file mode 100644
index e3d9152..0000000
--- a/drivers/block/acsi.c
+++ /dev/null
@@ -1,1825 +0,0 @@
-/*
- * acsi.c -- Device driver for Atari ACSI hard disks
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * Some parts are based on hd.c by Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- */
-
-/*
- * Still to in this file:
- *  - If a command ends with an error status (!= 0), the following
- *    REQUEST SENSE commands (4 to fill the ST-DMA FIFO) are done by
- *    polling the _IRQ signal (not interrupt-driven). This should be
- *    avoided in future because it takes up a non-neglectible time in
- *    the interrupt service routine while interrupts are disabled.
- *    Maybe a timer interrupt will get lost :-(
- */
-
-/*
- * General notes:
- *
- *  - All ACSI devices (disks, CD-ROMs, ...) use major number 28.
- *    Minors are organized like it is with SCSI: The upper 4 bits
- *    identify the device, the lower 4 bits the partition.
- *    The device numbers (the upper 4 bits) are given in the same
- *    order as the devices are found on the bus.
- *  - Up to 8 LUNs are supported for each target (if CONFIG_ACSI_MULTI_LUN
- *    is defined), but only a total of 16 devices (due to minor
- *    numbers...). Note that Atari allows only a maximum of 4 targets
- *    (i.e. controllers, not devices) on the ACSI bus!
- *  - A optimizing scheme similar to SCSI scatter-gather is implemented.
- *  - Removable media are supported. After a medium change to device
- *    is reinitialized (partition check etc.). Also, if the device
- *    knows the PREVENT/ALLOW MEDIUM REMOVAL command, the door should
- *    be locked and unlocked when mounting the first or unmounting the
- *    last filesystem on the device. The code is untested, because I
- *    don't have a removable hard disk.
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/genhd.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */
-#include <scsi/scsi_ioctl.h>
-#include <linux/hdreg.h> /* for HDIO_GETGEO */
-#include <linux/blkpg.h>
-#include <linux/buffer_head.h>
-#include <linux/blkdev.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-static void (*do_acsi)(void) = NULL;
-static struct request_queue *acsi_queue;
-#define QUEUE (acsi_queue)
-#define CURRENT elv_next_request(acsi_queue)
-
-#define DEBUG
-#undef DEBUG_DETECT
-#undef NO_WRITE
-
-#define MAX_ERRORS     		8	/* Max read/write errors/sector */
-#define MAX_LUN				8	/* Max LUNs per target */
-#define MAX_DEV		   		16
-
-#define ACSI_BUFFER_SIZE			(16*1024) /* "normal" ACSI buffer size */
-#define ACSI_BUFFER_MINSIZE			(2048) 	  /* min. buf size if ext. DMA */
-#define ACSI_BUFFER_SIZE_ORDER	 	2		  /* order size for above */
-#define ACSI_BUFFER_MINSIZE_ORDER	0 	  	  /* order size for above */
-#define ACSI_BUFFER_SECTORS	(ACSI_BUFFER_SIZE/512)
-
-#define ACSI_BUFFER_ORDER \
-	(ATARIHW_PRESENT(EXTD_DMA) ? \
-	 ACSI_BUFFER_MINSIZE_ORDER : \
-	 ACSI_BUFFER_SIZE_ORDER)
-
-#define ACSI_TIMEOUT		(4*HZ)
-
-/* minimum delay between two commands */
-
-#define COMMAND_DELAY 500
-
-typedef enum {
-	NONE, HARDDISK, CDROM
-} ACSI_TYPE;
-
-struct acsi_info_struct {
-	ACSI_TYPE		type;			/* type of device */
-	unsigned		target;			/* target number */
-	unsigned		lun;			/* LUN in target controller */
-	unsigned		removable : 1;	/* Flag for removable media */
-	unsigned		read_only : 1;	/* Flag for read only devices */
-	unsigned		old_atari_disk : 1; /* Is an old Atari disk       */
-	unsigned		changed : 1;	/* Medium has been changed */
-	unsigned long 	size;			/* #blocks */
-	int access_count;
-} acsi_info[MAX_DEV];
-
-/*
- *	SENSE KEYS
- */
-
-#define NO_SENSE		0x00
-#define RECOVERED_ERROR 	0x01
-#define NOT_READY		0x02
-#define MEDIUM_ERROR		0x03
-#define HARDWARE_ERROR		0x04
-#define ILLEGAL_REQUEST 	0x05
-#define UNIT_ATTENTION		0x06
-#define DATA_PROTECT		0x07
-#define BLANK_CHECK		0x08
-#define COPY_ABORTED		0x0a
-#define ABORTED_COMMAND 	0x0b
-#define VOLUME_OVERFLOW 	0x0d
-#define MISCOMPARE		0x0e
-
-
-/*
- *	DEVICE TYPES
- */
-
-#define TYPE_DISK	0x00
-#define TYPE_TAPE	0x01
-#define TYPE_WORM	0x04
-#define TYPE_ROM	0x05
-#define TYPE_MOD	0x07
-#define TYPE_NO_LUN	0x7f
-
-/* The data returned by MODE SENSE differ between the old Atari
- * hard disks and SCSI disks connected to ACSI. In the following, both
- * formats are defined and some macros to operate on them potably.
- */
-
-typedef struct {
-	unsigned long	dummy[2];
-	unsigned long	sector_size;
-	unsigned char	format_code;
-#define ATARI_SENSE_FORMAT_FIX	1	
-#define ATARI_SENSE_FORMAT_CHNG	2
-	unsigned char	cylinders_h;
-	unsigned char	cylinders_l;
-	unsigned char	heads;
-	unsigned char	reduced_h;
-	unsigned char	reduced_l;
-	unsigned char	precomp_h;
-	unsigned char	precomp_l;
-	unsigned char	landing_zone;
-	unsigned char	steprate;
-	unsigned char	type;
-#define ATARI_SENSE_TYPE_FIXCHNG_MASK		4
-#define ATARI_SENSE_TYPE_SOFTHARD_MASK		8
-#define ATARI_SENSE_TYPE_FIX				4
-#define ATARI_SENSE_TYPE_CHNG				0
-#define ATARI_SENSE_TYPE_SOFT				0
-#define ATARI_SENSE_TYPE_HARD				8
-	unsigned char	sectors;
-} ATARI_SENSE_DATA;
-
-#define ATARI_CAPACITY(sd) \
-	(((int)((sd).cylinders_h<<8)|(sd).cylinders_l) * \
-	 (sd).heads * (sd).sectors)
-
-
-typedef struct {
-	unsigned char   dummy1;
-	unsigned char   medium_type;
-	unsigned char   dummy2;
-	unsigned char   descriptor_size;
-	unsigned long   block_count;
-	unsigned long   sector_size;
-	/* Page 0 data */
-	unsigned char	page_code;
-	unsigned char	page_size;
-	unsigned char	page_flags;
-	unsigned char	qualifier;
-} SCSI_SENSE_DATA;
-
-#define SCSI_CAPACITY(sd) 	((sd).block_count & 0xffffff)
-
-
-typedef union {
-	ATARI_SENSE_DATA	atari;
-	SCSI_SENSE_DATA		scsi;
-} SENSE_DATA;
-
-#define SENSE_TYPE_UNKNOWN	0
-#define SENSE_TYPE_ATARI	1
-#define SENSE_TYPE_SCSI		2
-
-#define SENSE_TYPE(sd)										\
-	(((sd).atari.dummy[0] == 8 &&							\
-	  ((sd).atari.format_code == 1 ||						\
-	   (sd).atari.format_code == 2)) ? SENSE_TYPE_ATARI :	\
-	 ((sd).scsi.dummy1 >= 11) ? SENSE_TYPE_SCSI :			\
-	 SENSE_TYPE_UNKNOWN)
-	 
-#define CAPACITY(sd)							\
-	(SENSE_TYPE(sd) == SENSE_TYPE_ATARI ?		\
-	 ATARI_CAPACITY((sd).atari) :				\
-	 SCSI_CAPACITY((sd).scsi))
-
-#define SECTOR_SIZE(sd)							\
-	(SENSE_TYPE(sd) == SENSE_TYPE_ATARI ?		\
-	 (sd).atari.sector_size :					\
-	 (sd).scsi.sector_size & 0xffffff)
-
-/* Default size if capacity cannot be determined (1 GByte) */
-#define	DEFAULT_SIZE	0x1fffff
-
-#define CARTRCH_STAT(aip,buf)						\
-	(aip->old_atari_disk ?						\
-	 (((buf)[0] & 0x7f) == 0x28) :					\
-	 ((((buf)[0] & 0x70) == 0x70) ?					\
-	  (((buf)[2] & 0x0f) == 0x06) :					\
-	  (((buf)[0] & 0x0f) == 0x06)))					\
-
-/* These two are also exported to other drivers that work on the ACSI bus and
- * need an ST-RAM buffer. */
-char 			*acsi_buffer;
-unsigned long 	phys_acsi_buffer;
-
-static int NDevices;
-
-static int				CurrentNReq;
-static int				CurrentNSect;
-static char				*CurrentBuffer;
-
-static DEFINE_SPINLOCK(acsi_lock);
-
-
-#define SET_TIMER()	mod_timer(&acsi_timer, jiffies + ACSI_TIMEOUT)
-#define CLEAR_TIMER()	del_timer(&acsi_timer)
-
-static unsigned long	STramMask;
-#define STRAM_ADDR(a)	(((a) & STramMask) == 0)
-
-
-
-/* ACSI commands */
-
-static char tur_cmd[6]        = { 0x00, 0, 0, 0, 0, 0 };
-static char modesense_cmd[6]  = { 0x1a, 0, 0, 0, 24, 0 };
-static char modeselect_cmd[6] = { 0x15, 0, 0, 0, 12, 0 };
-static char inquiry_cmd[6]    = { 0x12, 0, 0, 0,255, 0 };
-static char reqsense_cmd[6]   = { 0x03, 0, 0, 0, 4, 0 };
-static char read_cmd[6]       = { 0x08, 0, 0, 0, 0, 0 };
-static char write_cmd[6]      = { 0x0a, 0, 0, 0, 0, 0 };
-static char pa_med_rem_cmd[6] = { 0x1e, 0, 0, 0, 0, 0 };
-
-#define CMDSET_TARG_LUN(cmd,targ,lun)			\
-    do {						\
-		cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5;	\
-		cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5;	\
-	} while(0)
-
-#define CMDSET_BLOCK(cmd,blk)						\
-    do {											\
-		unsigned long __blk = (blk);				\
-		cmd[3] = __blk; __blk >>= 8;				\
-		cmd[2] = __blk; __blk >>= 8;				\
-		cmd[1] = (cmd[1] & 0xe0) | (__blk & 0x1f);	\
-	} while(0)
-
-#define CMDSET_LEN(cmd,len)						\
-	do {										\
-		cmd[4] = (len);							\
-	} while(0)
-
-/* ACSI errors (from REQUEST SENSE); There are two tables, one for the
- * old Atari disks and one for SCSI on ACSI disks.
- */
-
-struct acsi_error {
-	unsigned char	code;
-	const char		*text;
-} atari_acsi_errors[] = {
-	{ 0x00, "No error (??)" },
-	{ 0x01, "No index pulses" },
-	{ 0x02, "Seek not complete" },
-	{ 0x03, "Write fault" },
-	{ 0x04, "Drive not ready" },
-	{ 0x06, "No Track 00 signal" },
-	{ 0x10, "ECC error in ID field" },
-	{ 0x11, "Uncorrectable data error" },
-	{ 0x12, "ID field address mark not found" },
-	{ 0x13, "Data field address mark not found" },
-	{ 0x14, "Record not found" },
-	{ 0x15, "Seek error" },
-	{ 0x18, "Data check in no retry mode" },
-	{ 0x19, "ECC error during verify" },
-	{ 0x1a, "Access to bad block" },
-	{ 0x1c, "Unformatted or bad format" },
-	{ 0x20, "Invalid command" },
-	{ 0x21, "Invalid block address" },
-	{ 0x23, "Volume overflow" },
-	{ 0x24, "Invalid argument" },
-	{ 0x25, "Invalid drive number" },
-	{ 0x26, "Byte zero parity check" },
-	{ 0x28, "Cartride changed" },
-	{ 0x2c, "Error count overflow" },
-	{ 0x30, "Controller selftest failed" }
-},
-
-	scsi_acsi_errors[] = {
-	{ 0x00, "No error (??)" },
-	{ 0x01, "Recovered error" },
-	{ 0x02, "Drive not ready" },
-	{ 0x03, "Uncorrectable medium error" },
-	{ 0x04, "Hardware error" },
-	{ 0x05, "Illegal request" },
-	{ 0x06, "Unit attention (Reset or cartridge changed)" },
-	{ 0x07, "Data protection" },
-	{ 0x08, "Blank check" },
-	{ 0x0b, "Aborted Command" },
-	{ 0x0d, "Volume overflow" }
-};
-
-
-
-/***************************** Prototypes *****************************/
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
-                        rwflag, int enable);
-static int acsi_reqsense( char *buffer, int targ, int lun);
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip);
-static irqreturn_t acsi_interrupt (int irq, void *data);
-static void unexpected_acsi_interrupt( void );
-static void bad_rw_intr( void );
-static void read_intr( void );
-static void write_intr( void);
-static void acsi_times_out( unsigned long dummy );
-static void copy_to_acsibuffer( void );
-static void copy_from_acsibuffer( void );
-static void do_end_requests( void );
-static void do_acsi_request( request_queue_t * );
-static void redo_acsi_request( void );
-static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int
-                       cmd, unsigned long arg );
-static int acsi_open( struct inode * inode, struct file * filp );
-static int acsi_release( struct inode * inode, struct file * file );
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag );
-static int acsi_change_blk_size( int target, int lun);
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
-static int acsi_revalidate (struct gendisk *disk);
-
-/************************* End of Prototypes **************************/
-
-
-DEFINE_TIMER(acsi_timer, acsi_times_out, 0, 0);
-
-
-#ifdef CONFIG_ATARI_SLM
-
-extern int attach_slm( int target, int lun );
-extern int slm_init( void );
-
-#endif
-
-
-
-/***********************************************************************
- *
- *   ACSI primitives
- *
- **********************************************************************/
-
-
-/*
- * The following two functions wait for _IRQ to become Low or High,
- * resp., with a timeout. The 'timeout' parameter is in jiffies
- * (10ms).
- * If the functions are called with timer interrupts on (int level <
- * 6), the timeout is based on the 'jiffies' variable to provide exact
- * timeouts for device probing etc.
- * If interrupts are disabled, the number of tries is based on the
- * 'loops_per_jiffy' variable. A rough estimation is sufficient here...
- */
-
-#define INT_LEVEL													\
-	({	unsigned __sr;												\
-		__asm__ __volatile__ ( "movew	%/sr,%0" : "=dm" (__sr) );	\
-		(__sr >> 8) & 7;											\
-	})
-
-int acsi_wait_for_IRQ( unsigned timeout )
-
-{
-	if (INT_LEVEL < 6) {
-		unsigned long maxjif = jiffies + timeout;
-		while (time_before(jiffies, maxjif))
-			if (!(mfp.par_dt_reg & 0x20)) return( 1 );
-	}
-	else {
-		long tries = loops_per_jiffy / 8 * timeout;
-		while( --tries >= 0 )
-			if (!(mfp.par_dt_reg & 0x20)) return( 1 );
-	}		
-	return( 0 ); /* timeout! */
-}
-
-
-int acsi_wait_for_noIRQ( unsigned timeout )
-
-{
-	if (INT_LEVEL < 6) {
-		unsigned long maxjif = jiffies + timeout;
-		while (time_before(jiffies, maxjif))
-			if (mfp.par_dt_reg & 0x20) return( 1 );
-	}
-	else {
-		long tries = loops_per_jiffy * timeout / 8;
-		while( tries-- >= 0 )
-			if (mfp.par_dt_reg & 0x20) return( 1 );
-	}		
-	return( 0 ); /* timeout! */
-}
-
-static struct timeval start_time;
-
-void
-acsi_delay_start(void)
-{
-	do_gettimeofday(&start_time);
-}
-
-/* wait from acsi_delay_start to now usec (<1E6) usec */
-
-void
-acsi_delay_end(long usec)
-{
-	struct timeval end_time;
-	long deltau,deltas;
-	do_gettimeofday(&end_time);
-	deltau=end_time.tv_usec - start_time.tv_usec;
-	deltas=end_time.tv_sec - start_time.tv_sec;
-	if (deltas > 1 || deltas < 0)
-		return;
-	if (deltas > 0)
-		deltau += 1000*1000;
-	if (deltau >= usec)
-		return;
-	udelay(usec-deltau);
-}
-
-/* acsicmd_dma() sends an ACSI command and sets up the DMA to transfer
- * 'blocks' blocks of 512 bytes from/to 'buffer'.
- * Because the _IRQ signal is used for handshaking the command bytes,
- * the ACSI interrupt has to be disabled in this function. If the end
- * of the operation should be signalled by a real interrupt, it has to be
- * reenabled afterwards.
- */
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, int enable)
-
-{	unsigned long	flags, paddr;
-	int				i;
-
-#ifdef NO_WRITE
-	if (rwflag || *cmd == 0x0a) {
-		printk( "ACSI: Write commands disabled!\n" );
-		return( 0 );
-	}
-#endif
-	
-	rwflag = rwflag ? 0x100 : 0;
-	paddr = virt_to_phys( buffer );
-
-	acsi_delay_end(COMMAND_DELAY);
-	DISABLE_IRQ();
-
-	local_irq_save(flags);
-	/* Low on A1 */
-	dma_wd.dma_mode_status = 0x88 | rwflag;
-	MFPDELAY();
-
-	/* set DMA address */
-	dma_wd.dma_lo = (unsigned char)paddr;
-	paddr >>= 8;
-	MFPDELAY();
-	dma_wd.dma_md = (unsigned char)paddr;
-	paddr >>= 8;
-	MFPDELAY();
-	if (ATARIHW_PRESENT(EXTD_DMA))
-		st_dma_ext_dmahi = (unsigned short)paddr;
-	else
-		dma_wd.dma_hi = (unsigned char)paddr;
-	MFPDELAY();
-	local_irq_restore(flags);
-
-	/* send the command bytes except the last */
-	for( i = 0; i < 5; ++i ) {
-		DMA_LONG_WRITE( *cmd++, 0x8a | rwflag );
-		udelay(20);
-		if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-	}
-
-	/* Clear FIFO and switch DMA to correct direction */  
-	dma_wd.dma_mode_status = 0x92 | (rwflag ^ 0x100);  
-	MFPDELAY();
-	dma_wd.dma_mode_status = 0x92 | rwflag;
-	MFPDELAY();
-
-	/* How many sectors for DMA */
-	dma_wd.fdc_acces_seccount = blocks;
-	MFPDELAY();
-	
-	/* send last command byte */
-	dma_wd.dma_mode_status = 0x8a | rwflag;
-	MFPDELAY();
-	DMA_LONG_WRITE( *cmd++, 0x0a | rwflag );
-	if (enable)
-		ENABLE_IRQ();
-	udelay(80);
-
-	return( 1 );
-}
-
-
-/*
- * acsicmd_nodma() sends an ACSI command that requires no DMA.
- */
-
-int acsicmd_nodma( const char *cmd, int enable)
-
-{	int	i;
-
-	acsi_delay_end(COMMAND_DELAY);
-	DISABLE_IRQ();
-
-	/* send first command byte */
-	dma_wd.dma_mode_status = 0x88;
-	MFPDELAY();
-	DMA_LONG_WRITE( *cmd++, 0x8a );
-	udelay(20);
-	if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-
-	/* send the intermediate command bytes */
-	for( i = 0; i < 4; ++i ) {
-		DMA_LONG_WRITE( *cmd++, 0x8a );
-		udelay(20);
-		if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-	}
-
-	/* send last command byte */
-	DMA_LONG_WRITE( *cmd++, 0x0a );
-	if (enable)
-		ENABLE_IRQ();
-	udelay(80);
-	
-	return( 1 );
-	/* Note that the ACSI interrupt is still disabled after this
-	 * function. If you want to get the IRQ delivered, enable it manually!
-	 */
-}
-
-
-static int acsi_reqsense( char *buffer, int targ, int lun)
-
-{
-	CMDSET_TARG_LUN( reqsense_cmd, targ, lun);
-	if (!acsicmd_dma( reqsense_cmd, buffer, 1, 0, 0 )) return( 0 );
-	if (!acsi_wait_for_IRQ( 10 )) return( 0 );
-	acsi_getstatus();
-	if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
-	if (!acsi_wait_for_IRQ( 10 )) return( 0 );
-	acsi_getstatus();
-	if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
-	if (!acsi_wait_for_IRQ( 10 )) return( 0 );
-	acsi_getstatus();
-	if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
-	if (!acsi_wait_for_IRQ( 10 )) return( 0 );
-	acsi_getstatus();
-	dma_cache_maintenance( virt_to_phys(buffer), 16, 0 );
-	
-	return( 1 );
-}	
-
-
-/*
- * ACSI status phase: get the status byte from the bus
- *
- * I've seen several times that a 0xff status is read, propably due to
- * a timing error. In this case, the procedure is repeated after the
- * next _IRQ edge.
- */
-
-int acsi_getstatus( void )
-
-{	int	status;
-
-	DISABLE_IRQ();
-	for(;;) {
-		if (!acsi_wait_for_IRQ( 100 )) {
-			acsi_delay_start();
-			return( -1 );
-		}
-		dma_wd.dma_mode_status = 0x8a;
-		MFPDELAY();
-		status = dma_wd.fdc_acces_seccount;
-		if (status != 0xff) break;
-#ifdef DEBUG
-		printk("ACSI: skipping 0xff status byte\n" );
-#endif
-		udelay(40);
-		acsi_wait_for_noIRQ( 20 );
-	}
-	dma_wd.dma_mode_status = 0x80;
-	udelay(40);
-	acsi_wait_for_noIRQ( 20 );
-
-	acsi_delay_start();
-	return( status & 0x1f ); /* mask of the device# */
-}
-
-
-#if (defined(CONFIG_ATARI_SLM) || defined(CONFIG_ATARI_SLM_MODULE))
-
-/* Receive data in an extended status phase. Needed by SLM printer. */
-
-int acsi_extstatus( char *buffer, int cnt )
-
-{	int	status;
-
-	DISABLE_IRQ();
-	udelay(80);
-	while( cnt-- > 0 ) {
-		if (!acsi_wait_for_IRQ( 40 )) return( 0 );
-		dma_wd.dma_mode_status = 0x8a;
-		MFPDELAY();
-		status = dma_wd.fdc_acces_seccount;
-		MFPDELAY();
-		*buffer++ = status & 0xff;
-		udelay(40);
-	}
-	return( 1 );
-}
-
-
-/* Finish an extended status phase */
-
-void acsi_end_extstatus( void )
-
-{
-	dma_wd.dma_mode_status = 0x80;
-	udelay(40);
-	acsi_wait_for_noIRQ( 20 );
-	acsi_delay_start();
-}
-
-
-/* Send data in an extended command phase */
-
-int acsi_extcmd( unsigned char *buffer, int cnt )
-
-{
-	while( cnt-- > 0 ) {
-		DMA_LONG_WRITE( *buffer++, 0x8a );
-		udelay(20);
-		if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-	}
-	return( 1 );
-}
-
-#endif
-
-
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip)
-
-{	int atari_err, i, errcode;
-	struct acsi_error *arr;
-
-	atari_err = aip->old_atari_disk;
-	if (atari_err)
-		errcode = errblk[0] & 0x7f;
-	else
-		if ((errblk[0] & 0x70) == 0x70)
-			errcode = errblk[2] & 0x0f;
-		else
-			errcode = errblk[0] & 0x0f;
-	
-	printk( KERN_ERR "ACSI error 0x%02x", errcode );
-
-	if (errblk[0] & 0x80)
-		printk( " for sector %d",
-				((errblk[1] & 0x1f) << 16) |
-				(errblk[2] << 8) | errblk[0] );
-
-	arr = atari_err ? atari_acsi_errors : scsi_acsi_errors;
-	i = atari_err ? sizeof(atari_acsi_errors)/sizeof(*atari_acsi_errors) :
-		            sizeof(scsi_acsi_errors)/sizeof(*scsi_acsi_errors);
-	
-	for( --i; i >= 0; --i )
-		if (arr[i].code == errcode) break;
-	if (i >= 0)
-		printk( ": %s\n", arr[i].text );
-}
-
-/*******************************************************************
- *
- * ACSI interrupt routine
- *   Test, if this is a ACSI interrupt and call the irq handler
- *   Otherwise ignore this interrupt.
- *
- *******************************************************************/
-
-static irqreturn_t acsi_interrupt(int irq, void *data )
-
-{	void (*acsi_irq_handler)(void) = do_acsi;
-
-	do_acsi = NULL;
-	CLEAR_TIMER();
-
-	if (!acsi_irq_handler)
-		acsi_irq_handler = unexpected_acsi_interrupt;
-	acsi_irq_handler();
-	return IRQ_HANDLED;
-}
-
-
-/******************************************************************
- *
- * The Interrupt handlers
- *
- *******************************************************************/
-
-
-static void unexpected_acsi_interrupt( void )
-
-{
-	printk( KERN_WARNING "Unexpected ACSI interrupt\n" );
-}
-
-
-/* This function is called in case of errors. Because we cannot reset
- * the ACSI bus or a single device, there is no other choice than
- * retrying several times :-(
- */
-
-static void bad_rw_intr( void )
-
-{
-	if (!CURRENT)
-		return;
-
-	if (++CURRENT->errors >= MAX_ERRORS)
-		end_request(CURRENT, 0);
-	/* Otherwise just retry */
-}
-
-
-static void read_intr( void )
-
-{	int		status;
-	
-	status = acsi_getstatus();
-	if (status != 0) {
-		struct gendisk *disk = CURRENT->rq_disk;
-		struct acsi_info_struct *aip = disk->private_data;
-		printk(KERN_ERR "%s: ", disk->disk_name);
-		if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun))
-			printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
-		else {
-			acsi_print_error(acsi_buffer, aip);
-			if (CARTRCH_STAT(aip, acsi_buffer))
-				aip->changed = 1;
-		}
-		ENABLE_IRQ();
-		bad_rw_intr();
-		redo_acsi_request();
-		return;
-	}
-
-	dma_cache_maintenance( virt_to_phys(CurrentBuffer), CurrentNSect*512, 0 );
-	if (CurrentBuffer == acsi_buffer)
-		copy_from_acsibuffer();
-
-	do_end_requests();
-	redo_acsi_request();
-}
-
-
-static void write_intr(void)
-
-{	int	status;
-
-	status = acsi_getstatus();
-	if (status != 0) {
-		struct gendisk *disk = CURRENT->rq_disk;
-		struct acsi_info_struct *aip = disk->private_data;
-		printk( KERN_ERR "%s: ", disk->disk_name);
-		if (!acsi_reqsense( acsi_buffer, aip->target, aip->lun))
-			printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
-		else {
-			acsi_print_error(acsi_buffer, aip);
-			if (CARTRCH_STAT(aip, acsi_buffer))
-				aip->changed = 1;
-		}
-		bad_rw_intr();
-		redo_acsi_request();
-		return;
-	}
-
-	do_end_requests();
-	redo_acsi_request();
-}
-
-
-static void acsi_times_out( unsigned long dummy )
-
-{
-	DISABLE_IRQ();
-	if (!do_acsi) return;
-
-	do_acsi = NULL;
-	printk( KERN_ERR "ACSI timeout\n" );
-	if (!CURRENT)
-	    return;
-	if (++CURRENT->errors >= MAX_ERRORS) {
-#ifdef DEBUG
-		printk( KERN_ERR "ACSI: too many errors.\n" );
-#endif
-		end_request(CURRENT, 0);
-	}
-
-	redo_acsi_request();
-}
-
-
-
-/***********************************************************************
- *
- *  Scatter-gather utility functions
- *
- ***********************************************************************/
-
-
-static void copy_to_acsibuffer( void )
-
-{	int					i;
-	char				*src, *dst;
-	struct buffer_head	*bh;
-	
-	src = CURRENT->buffer;
-	dst = acsi_buffer;
-	bh = CURRENT->bh;
-
-	if (!bh)
-		memcpy( dst, src, CurrentNSect*512 );
-	else
-		for( i = 0; i < CurrentNReq; ++i ) {
-			memcpy( dst, src, bh->b_size );
-			dst += bh->b_size;
-			if ((bh = bh->b_reqnext))
-				src = bh->b_data;
-		}
-}
-
-
-static void copy_from_acsibuffer( void )
-
-{	int					i;
-	char				*src, *dst;
-	struct buffer_head	*bh;
-	
-	dst = CURRENT->buffer;
-	src = acsi_buffer;
-	bh = CURRENT->bh;
-
-	if (!bh)
-		memcpy( dst, src, CurrentNSect*512 );
-	else
-		for( i = 0; i < CurrentNReq; ++i ) {
-			memcpy( dst, src, bh->b_size );
-			src += bh->b_size;
-			if ((bh = bh->b_reqnext))
-				dst = bh->b_data;
-		}
-}
-
-
-static void do_end_requests( void )
-
-{	int		i, n;
-
-	if (!CURRENT->bh) {
-		CURRENT->nr_sectors -= CurrentNSect;
-		CURRENT->current_nr_sectors -= CurrentNSect;
-		CURRENT->sector += CurrentNSect;
-		if (CURRENT->nr_sectors == 0)
-			end_request(CURRENT, 1);
-	}
-	else {
-		for( i = 0; i < CurrentNReq; ++i ) {
-			n = CURRENT->bh->b_size >> 9;
-			CURRENT->nr_sectors -= n;
-			CURRENT->current_nr_sectors -= n;
-			CURRENT->sector += n;
-			end_request(CURRENT, 1);
-		}
-	}
-}
-
-
-
-
-/***********************************************************************
- *
- *  do_acsi_request and friends
- *
- ***********************************************************************/
-
-static void do_acsi_request( request_queue_t * q )
-
-{
-	stdma_lock( acsi_interrupt, NULL );
-	redo_acsi_request();
-}
-
-
-static void redo_acsi_request( void )
-{
-	unsigned			block, target, lun, nsect;
-	char 				*buffer;
-	unsigned long		pbuffer;
-	struct buffer_head	*bh;
-	struct gendisk *disk;
-	struct acsi_info_struct *aip;
-
-  repeat:
-	CLEAR_TIMER();
-
-	if (do_acsi)
-		return;
-
-	if (!CURRENT) {
-		do_acsi = NULL;
-		ENABLE_IRQ();
-		stdma_release();
-		return;
-	}
-
-	disk = CURRENT->rq_disk;
-	aip = disk->private_data;
-	if (CURRENT->bh) {
-		if (!CURRENT->bh && !buffer_locked(CURRENT->bh))
-			panic("ACSI: block not locked");
-	}
-
-	block = CURRENT->sector;
-	if (block+CURRENT->nr_sectors >= get_capacity(disk)) {
-#ifdef DEBUG
-		printk( "%s: attempted access for blocks %d...%ld past end of device at block %ld.\n",
-		       disk->disk_name,
-		       block, block + CURRENT->nr_sectors - 1,
-		       get_capacity(disk));
-#endif
-		end_request(CURRENT, 0);
-		goto repeat;
-	}
-	if (aip->changed) {
-		printk( KERN_NOTICE "%s: request denied because cartridge has "
-				"been changed.\n", disk->disk_name);
-		end_request(CURRENT, 0);
-		goto repeat;
-	}
-	
-	target = aip->target;
-	lun    = aip->lun;
-
-	/* Find out how many sectors should be transferred from/to
-	 * consecutive buffers and thus can be done with a single command.
-	 */
-	buffer      = CURRENT->buffer;
-	pbuffer     = virt_to_phys(buffer);
-	nsect       = CURRENT->current_nr_sectors;
-	CurrentNReq = 1;
-
-	if ((bh = CURRENT->bh) && bh != CURRENT->bhtail) {
-		if (!STRAM_ADDR(pbuffer)) {
-			/* If transfer is done via the ACSI buffer anyway, we can
-			 * assemble as much bh's as fit in the buffer.
-			 */
-			while( (bh = bh->b_reqnext) ) {
-				if (nsect + (bh->b_size>>9) > ACSI_BUFFER_SECTORS) break;
-				nsect += bh->b_size >> 9;
-				++CurrentNReq;
-				if (bh == CURRENT->bhtail) break;
-			}
-			buffer = acsi_buffer;
-			pbuffer = phys_acsi_buffer;
-		}
-		else {
-			unsigned long pendadr, pnewadr;
-			pendadr = pbuffer + nsect*512;
-			while( (bh = bh->b_reqnext) ) {
-				pnewadr = virt_to_phys(bh->b_data);
-				if (!STRAM_ADDR(pnewadr) || pendadr != pnewadr) break;
-				nsect += bh->b_size >> 9;
-				pendadr = pnewadr + bh->b_size;
-				++CurrentNReq;
-				if (bh == CURRENT->bhtail) break;
-			}
-		}
-	}
-	else {
-		if (!STRAM_ADDR(pbuffer)) {
-			buffer = acsi_buffer;
-			pbuffer = phys_acsi_buffer;
-			if (nsect > ACSI_BUFFER_SECTORS)
-				nsect = ACSI_BUFFER_SECTORS;
-		}
-	}
-	CurrentBuffer = buffer;
-	CurrentNSect  = nsect;
-
-	if (rq_data_dir(CURRENT) == WRITE) {
-		CMDSET_TARG_LUN( write_cmd, target, lun );
-		CMDSET_BLOCK( write_cmd, block );
-		CMDSET_LEN( write_cmd, nsect );
-		if (buffer == acsi_buffer)
-			copy_to_acsibuffer();
-		dma_cache_maintenance( pbuffer, nsect*512, 1 );
-		do_acsi = write_intr;
-		if (!acsicmd_dma( write_cmd, buffer, nsect, 1, 1)) {
-			do_acsi = NULL;
-			printk( KERN_ERR "ACSI (write): Timeout in command block\n" );
-			bad_rw_intr();
-			goto repeat;
-		}
-		SET_TIMER();
-		return;
-	}
-	if (rq_data_dir(CURRENT) == READ) {
-		CMDSET_TARG_LUN( read_cmd, target, lun );
-		CMDSET_BLOCK( read_cmd, block );
-		CMDSET_LEN( read_cmd, nsect );
-		do_acsi = read_intr;
-		if (!acsicmd_dma( read_cmd, buffer, nsect, 0, 1)) {
-			do_acsi = NULL;
-			printk( KERN_ERR "ACSI (read): Timeout in command block\n" );
-			bad_rw_intr();
-			goto repeat;
-		}
-		SET_TIMER();
-		return;
-	}
-	panic("unknown ACSI command");
-}
-
-
-
-/***********************************************************************
- *
- *  Misc functions: ioctl, open, release, check_change, ...
- *
- ***********************************************************************/
-
-static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
-	struct acsi_info_struct *aip = bdev->bd_disk->private_data;
-
-	/*
-	 * Just fake some geometry here, it's nonsense anyway
-	 * To make it easy, use Adaptec's usual 64/32 mapping
-	 */
-	geo->heads = 64;
-	geo->sectors = 32;
-	geo->cylinders = aip->size >> 11;
-	return 0;
-}
-
-static int acsi_ioctl( struct inode *inode, struct file *file,
-					   unsigned int cmd, unsigned long arg )
-{
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct acsi_info_struct *aip = disk->private_data;
-	switch (cmd) {
-	  case SCSI_IOCTL_GET_IDLUN:
-		/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
-		put_user( aip->target | (aip->lun << 8),
-				  &((Scsi_Idlun *) arg)->dev_id );
-		put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
-		return 0;
-	  default:
-		return -EINVAL;
-	}
-}
-
-
-/*
- * Open a device, check for read-only and lock the medium if it is
- * removable.
- *
- * Changes by Martin Rogge, 9th Aug 1995:
- * Check whether check_disk_change (and therefore revalidate_acsidisk)
- * was successful. They fail when there is no medium in the drive.
- *
- * The problem of media being changed during an operation can be 
- * ignored because of the prevent_removal code.
- *
- * Added check for the validity of the device number.
- *
- */
-
-static int acsi_open( struct inode * inode, struct file * filp )
-{
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct acsi_info_struct *aip = disk->private_data;
-
-	if (aip->access_count == 0 && aip->removable) {
-#if 0
-		aip->changed = 1;	/* safety first */
-#endif
-		check_disk_change( inode->i_bdev );
-		if (aip->changed)	/* revalidate was not successful (no medium) */
-			return -ENXIO;
-		acsi_prevent_removal(aip, 1);
-	}
-	aip->access_count++;
-
-	if (filp && filp->f_mode) {
-		check_disk_change( inode->i_bdev );
-		if (filp->f_mode & 2) {
-			if (aip->read_only) {
-				acsi_release( inode, filp );
-				return -EROFS;
-			}
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-
-static int acsi_release( struct inode * inode, struct file * file )
-{
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct acsi_info_struct *aip = disk->private_data;
-	if (--aip->access_count == 0 && aip->removable)
-		acsi_prevent_removal(aip, 0);
-	return( 0 );
-}
-
-/*
- * Prevent or allow a media change for removable devices.
- */
-
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag)
-{
-	stdma_lock( NULL, NULL );
-	
-	CMDSET_TARG_LUN(pa_med_rem_cmd, aip->target, aip->lun);
-	CMDSET_LEN( pa_med_rem_cmd, flag );
-	
-	if (acsicmd_nodma(pa_med_rem_cmd, 0) && acsi_wait_for_IRQ(3*HZ))
-		acsi_getstatus();
-	/* Do not report errors -- some devices may not know this command. */
-
-	ENABLE_IRQ();
-	stdma_release();
-}
-
-static int acsi_media_change(struct gendisk *disk)
-{
-	struct acsi_info_struct *aip = disk->private_data;
-
-	if (!aip->removable) 
-		return 0;
-
-	if (aip->changed)
-		/* We can be sure that the medium has been changed -- REQUEST
-		 * SENSE has reported this earlier.
-		 */
-		return 1;
-
-	/* If the flag isn't set, make a test by reading block 0.
-	 * If errors happen, it seems to be better to say "changed"...
-	 */
-	stdma_lock( NULL, NULL );
-	CMDSET_TARG_LUN(read_cmd, aip->target, aip->lun);
-	CMDSET_BLOCK( read_cmd, 0 );
-	CMDSET_LEN( read_cmd, 1 );
-	if (acsicmd_dma(read_cmd, acsi_buffer, 1, 0, 0) &&
-	    acsi_wait_for_IRQ(3*HZ)) {
-		if (acsi_getstatus()) {
-			if (acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
-				if (CARTRCH_STAT(aip, acsi_buffer))
-					aip->changed = 1;
-			}
-			else {
-				printk( KERN_ERR "%s: REQUEST SENSE failed in test for "
-				       "medium change; assuming a change\n", disk->disk_name );
-				aip->changed = 1;
-			}
-		}
-	}
-	else {
-		printk( KERN_ERR "%s: Test for medium changed timed out; "
-				"assuming a change\n", disk->disk_name);
-		aip->changed = 1;
-	}
-	ENABLE_IRQ();
-	stdma_release();
-
-	/* Now, after reading a block, the changed status is surely valid. */
-	return aip->changed;
-}
-
-
-static int acsi_change_blk_size( int target, int lun)
-
-{	int i;
-
-	for (i=0; i<12; i++)
-		acsi_buffer[i] = 0;
-
-	acsi_buffer[3] = 8;
-	acsi_buffer[10] = 2;
-	CMDSET_TARG_LUN( modeselect_cmd, target, lun);
-
-	if (!acsicmd_dma( modeselect_cmd, acsi_buffer, 1,1,0) ||
-		!acsi_wait_for_IRQ( 3*HZ ) ||
-		acsi_getstatus() != 0 ) {
-		return(0);
-	}
-	return(1);
-}
-
-
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd )
-
-{
-	int page;
-
-	CMDSET_TARG_LUN( modesense_cmd, target, lun );
-	for (page=0; page<4; page++) {
-		modesense_cmd[2] = page;
-		if (!acsicmd_dma( modesense_cmd, acsi_buffer, 1, 0, 0 ) ||
-		    !acsi_wait_for_IRQ( 3*HZ ) ||
-		    acsi_getstatus())
-			continue;
-
-		/* read twice to jump over the second 16-byte border! */
-		udelay(300);
-		if (acsi_wait_for_noIRQ( 20 ) &&
-		    acsicmd_nodma( modesense_cmd, 0 ) &&
-		    acsi_wait_for_IRQ( 3*HZ ) &&
-		    acsi_getstatus() == 0)
-			break;
-	}
-	if (page == 4) {
-		return(0);
-	}
-
-	dma_cache_maintenance( phys_acsi_buffer, sizeof(SENSE_DATA), 0 );
-	*sd = *(SENSE_DATA *)acsi_buffer;
-
-	/* Validity check, depending on type of data */
-	
-	switch( SENSE_TYPE(*sd) ) {
-
-	  case SENSE_TYPE_ATARI:
-		if (CAPACITY(*sd) == 0)
-			goto invalid_sense;
-		break;
-
-	  case SENSE_TYPE_SCSI:
-		if (sd->scsi.descriptor_size != 8)
-			goto invalid_sense;
-		break;
-
-	  case SENSE_TYPE_UNKNOWN:
-
-		printk( KERN_ERR "ACSI target %d, lun %d: Cannot interpret "
-				"sense data\n", target, lun ); 
-		
-	  invalid_sense:
-
-#ifdef DEBUG
-		{	int i;
-		printk( "Mode sense data for ACSI target %d, lun %d seem not valid:",
-				target, lun );
-		for( i = 0; i < sizeof(SENSE_DATA); ++i )
-			printk( "%02x ", (unsigned char)acsi_buffer[i] );
-		printk( "\n" );
-		}
-#endif
-		return( 0 );
-	}
-		
-	return( 1 );
-}
-
-
-
-/*******************************************************************
- *
- *  Initialization
- *
- ********************************************************************/
-
-
-extern struct block_device_operations acsi_fops;
-
-static struct gendisk *acsi_gendisk[MAX_DEV];
-
-#define MAX_SCSI_DEVICE_CODE 10
-
-static const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
-{
- "Direct-Access    ",
- "Sequential-Access",
- "Printer          ",
- "Processor        ",
- "WORM             ",
- "CD-ROM           ",
- "Scanner          ",
- "Optical Device   ",
- "Medium Changer   ",
- "Communications   "
-};
-
-static void print_inquiry(unsigned char *data)
-{
-	int i;
-
-	printk(KERN_INFO "  Vendor: ");
-	for (i = 8; i < 16; i++)
-		{
-	        if (data[i] >= 0x20 && i < data[4] + 5)
-			printk("%c", data[i]);
-		else
-			printk(" ");
-		}
-
-	printk("  Model: ");
-	for (i = 16; i < 32; i++)
-		{
-	        if (data[i] >= 0x20 && i < data[4] + 5)
-			printk("%c", data[i]);
-		else
-			printk(" ");
-		}
-
-	printk("  Rev: ");
-	for (i = 32; i < 36; i++)
-		{
-	        if (data[i] >= 0x20 && i < data[4] + 5)
-			printk("%c", data[i]);
-		else
-			printk(" ");
-		}
-
-	printk("\n");
-
-	i = data[0] & 0x1f;
-
-	printk(KERN_INFO "  Type:   %s ", (i < MAX_SCSI_DEVICE_CODE
-									   ? scsi_device_types[i]
-									   : "Unknown          "));
-	printk("                 ANSI SCSI revision: %02x", data[2] & 0x07);
-	if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
-	  printk(" CCS\n");
-	else
-	  printk("\n");
-}
-
-
-/* 
- * Changes by Martin Rogge, 9th Aug 1995: 
- * acsi_devinit has been taken out of acsi_geninit, because it needs 
- * to be called from revalidate_acsidisk. The result of request sense 
- * is now checked for DRIVE NOT READY.
- *
- * The structure *aip is only valid when acsi_devinit returns 
- * DEV_SUPPORTED. 
- *
- */
-	
-#define DEV_NONE	0
-#define DEV_UNKNOWN	1
-#define DEV_SUPPORTED	2
-#define DEV_SLM		3
-
-static int acsi_devinit(struct acsi_info_struct *aip)
-{
-	int status, got_inquiry;
-	SENSE_DATA sense;
-	unsigned char reqsense, extsense;
-
-	/*****************************************************************/
-	/* Do a TEST UNIT READY command to test the presence of a device */
-	/*****************************************************************/
-
-	CMDSET_TARG_LUN(tur_cmd, aip->target, aip->lun);
-	if (!acsicmd_nodma(tur_cmd, 0)) {
-		/* timed out -> no device here */
-#ifdef DEBUG_DETECT
-		printk("target %d lun %d: timeout\n", aip->target, aip->lun);
-#endif
-		return DEV_NONE;
-	}
-		
-	/*************************/
-	/* Read the ACSI status. */
-	/*************************/
-
-	status = acsi_getstatus();
-	if (status) {
-		if (status == 0x12) {
-			/* The SLM printer should be the only device that
-			 * responds with the error code in the status byte. In
-			 * correct status bytes, bit 4 is never set.
-			 */
-			printk( KERN_INFO "Detected SLM printer at id %d lun %d\n",
-			       aip->target, aip->lun);
-			return DEV_SLM;
-		}
-		/* ignore CHECK CONDITION, since some devices send a
-		   UNIT ATTENTION */
-		if ((status & 0x1e) != 0x2) {
-#ifdef DEBUG_DETECT
-			printk("target %d lun %d: status %d\n",
-			       aip->target, aip->lun, status);
-#endif
-			return DEV_UNKNOWN;
-		}
-	}
-
-	/*******************************/
-	/* Do a REQUEST SENSE command. */
-	/*******************************/
-
-	if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
-		printk( KERN_WARNING "acsi_reqsense failed\n");
-		acsi_buffer[0] = 0;
-		acsi_buffer[2] = UNIT_ATTENTION;
-	}
-	reqsense = acsi_buffer[0];
-	extsense = acsi_buffer[2] & 0xf;
-	if (status) {
-		if ((reqsense & 0x70) == 0x70) {	/* extended sense */
-			if (extsense != UNIT_ATTENTION &&
-			    extsense != NOT_READY) {
-#ifdef DEBUG_DETECT
-				printk("target %d lun %d: extended sense %d\n",
-				       aip->target, aip->lun, extsense);
-#endif
-				return DEV_UNKNOWN;
-			}
-		}
-		else {
-			if (reqsense & 0x7f) {
-#ifdef DEBUG_DETECT
-				printk("target %d lun %d: sense %d\n",
-				       aip->target, aip->lun, reqsense);
-#endif
-				return DEV_UNKNOWN;
-			}
-		}
-	}
-	else 
-		if (reqsense == 0x4) {	/* SH204 Bug workaround */
-#ifdef DEBUG_DETECT
-			printk("target %d lun %d status=0 sense=4\n",
-			       aip->target, aip->lun);
-#endif
-			return DEV_UNKNOWN;
-		}
-
-	/***********************************************************/
-	/* Do an INQUIRY command to get more infos on this device. */
-	/***********************************************************/
-
-	/* Assume default values */
-	aip->removable = 1;
-	aip->read_only = 0;
-	aip->old_atari_disk = 0;
-	aip->changed = (extsense == NOT_READY);	/* medium inserted? */
-	aip->size = DEFAULT_SIZE;
-	got_inquiry = 0;
-	/* Fake inquiry result for old atari disks */
-	memcpy(acsi_buffer, "\000\000\001\000    Adaptec 40xx"
-	       "                    ", 40);
-	CMDSET_TARG_LUN(inquiry_cmd, aip->target, aip->lun);
-	if (acsicmd_dma(inquiry_cmd, acsi_buffer, 1, 0, 0) &&
-	    acsi_getstatus() == 0) {
-		acsicmd_nodma(inquiry_cmd, 0);
-		acsi_getstatus();
-		dma_cache_maintenance( phys_acsi_buffer, 256, 0 );
-		got_inquiry = 1;
-		aip->removable = !!(acsi_buffer[1] & 0x80);
-	}
-	if (aip->type == NONE)	/* only at boot time */
-		print_inquiry(acsi_buffer);
-	switch(acsi_buffer[0]) {
-	  case TYPE_DISK:
-		aip->type = HARDDISK;
-		break;
-	  case TYPE_ROM:
-		aip->type = CDROM;
-		aip->read_only = 1;
-		break;
-	  default:
-		return DEV_UNKNOWN;
-	}
-	/****************************/
-	/* Do a MODE SENSE command. */
-	/****************************/
-
-	if (!acsi_mode_sense(aip->target, aip->lun, &sense)) {
-		printk( KERN_WARNING "No mode sense data.\n" );
-		return DEV_UNKNOWN;
-	}
-	if ((SECTOR_SIZE(sense) != 512) &&
-	    ((aip->type != CDROM) ||
-	     !acsi_change_blk_size(aip->target, aip->lun) ||
-	     !acsi_mode_sense(aip->target, aip->lun, &sense) ||
-	     (SECTOR_SIZE(sense) != 512))) {
-		printk( KERN_WARNING "Sector size != 512 not supported.\n" );
-		return DEV_UNKNOWN;
-	}
-	/* There are disks out there that claim to have 0 sectors... */
-	if (CAPACITY(sense))
-		aip->size = CAPACITY(sense);	/* else keep DEFAULT_SIZE */
-	if (!got_inquiry && SENSE_TYPE(sense) == SENSE_TYPE_ATARI) {
-		/* If INQUIRY failed and the sense data suggest an old
-		 * Atari disk (SH20x, Megafile), the disk is not removable
-		 */
-		aip->removable = 0;
-		aip->old_atari_disk = 1;
-	}
-	
-	/******************/
-	/* We've done it. */
-	/******************/
-	
-	return DEV_SUPPORTED;
-}
-
-EXPORT_SYMBOL(acsi_delay_start);
-EXPORT_SYMBOL(acsi_delay_end);
-EXPORT_SYMBOL(acsi_wait_for_IRQ);
-EXPORT_SYMBOL(acsi_wait_for_noIRQ);
-EXPORT_SYMBOL(acsicmd_nodma);
-EXPORT_SYMBOL(acsi_getstatus);
-EXPORT_SYMBOL(acsi_buffer);
-EXPORT_SYMBOL(phys_acsi_buffer);
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-
-EXPORT_SYMBOL(acsi_extstatus);
-EXPORT_SYMBOL(acsi_end_extstatus);
-EXPORT_SYMBOL(acsi_extcmd);
-EXPORT_SYMBOL(acsi_attach_SLMs);
-
-/* to remember IDs of SLM devices, SLM module is loaded later
- * (index is target#, contents is lun#, -1 means "no SLM") */
-int SLM_devices[8];
-#endif
-
-static struct block_device_operations acsi_fops = {
-	.owner		= THIS_MODULE,
-	.open		= acsi_open,
-	.release	= acsi_release,
-	.ioctl		= acsi_ioctl,
-	.getgeo		= acsi_getgeo,
-	.media_changed	= acsi_media_change,
-	.revalidate_disk= acsi_revalidate,
-};
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-/* call attach_slm() for each device that is a printer; needed for init of SLM
- * driver as a module, since it's not yet present if acsi.c is inited and thus
- * the bus gets scanned. */
-void acsi_attach_SLMs( int (*attach_func)( int, int ) )
-{
-	int i, n = 0;
-
-	for( i = 0; i < 8; ++i )
-		if (SLM_devices[i] >= 0)
-			n += (*attach_func)( i, SLM_devices[i] );
-	printk( KERN_INFO "Found %d SLM printer(s) total.\n", n );
-}
-#endif /* CONFIG_ATARI_SLM_MODULE */
-
-
-int acsi_init( void )
-{
-	int err = 0;
-	int i, target, lun;
-	struct acsi_info_struct *aip;
-#ifdef CONFIG_ATARI_SLM
-	int n_slm = 0;
-#endif
-	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
-		return 0;
-	if (register_blkdev(ACSI_MAJOR, "ad")) {
-		err = -EBUSY;
-		goto out1;
-	}
-	if (!(acsi_buffer =
-		  (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) {
-		err = -ENOMEM;
-		printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );
-		goto out2;
-	}
-	phys_acsi_buffer = virt_to_phys( acsi_buffer );
-	STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
-	
-	acsi_queue = blk_init_queue(do_acsi_request, &acsi_lock);
-	if (!acsi_queue) {
-		err = -ENOMEM;
-		goto out2a;
-	}
-#ifdef CONFIG_ATARI_SLM
-	err = slm_init();
-#endif
-	if (err)
-		goto out3;
-
-	printk( KERN_INFO "Probing ACSI devices:\n" );
-	NDevices = 0;
-#ifdef CONFIG_ATARI_SLM_MODULE
-	for( i = 0; i < 8; ++i )
-		SLM_devices[i] = -1;
-#endif
-	stdma_lock(NULL, NULL);
-
-	for (target = 0; target < 8 && NDevices < MAX_DEV; ++target) {
-		lun = 0;
-		do {
-			aip = &acsi_info[NDevices];
-			aip->type = NONE;
-			aip->target = target;
-			aip->lun = lun;
-			i = acsi_devinit(aip);
-			switch (i) {
-			  case DEV_SUPPORTED:
-				printk( KERN_INFO "Detected ");
-				switch (aip->type) {
-				  case HARDDISK:
-					printk("disk");
-					break;
-				  case CDROM:
-					printk("cdrom");
-					break;
-				  default:
-				}
-				printk(" ad%c at id %d lun %d ",
-				       'a' + NDevices, target, lun);
-				if (aip->removable) 
-					printk("(removable) ");
-				if (aip->read_only) 
-					printk("(read-only) ");
-				if (aip->size == DEFAULT_SIZE)
-					printk(" unkown size, using default ");
-				printk("%ld MByte\n",
-				       (aip->size*512+1024*1024/2)/(1024*1024));
-				NDevices++;
-				break;
-			  case DEV_SLM:
-#ifdef CONFIG_ATARI_SLM
-				n_slm += attach_slm( target, lun );
-				break;
-#endif
-#ifdef CONFIG_ATARI_SLM_MODULE
-				SLM_devices[target] = lun;
-				break;
-#endif
-				/* neither of the above: fall through to unknown device */
-			  case DEV_UNKNOWN:
-				printk( KERN_INFO "Detected unsupported device at "
-						"id %d lun %d\n", target, lun);
-				break;
-			}
-		}
-#ifdef CONFIG_ACSI_MULTI_LUN
-		while (i != DEV_NONE && ++lun < MAX_LUN);
-#else
-		while (0);
-#endif
-	}
-
-	/* reenable interrupt */
-	ENABLE_IRQ();
-	stdma_release();
-
-#ifndef CONFIG_ATARI_SLM
-	printk( KERN_INFO "Found %d ACSI device(s) total.\n", NDevices );
-#else
-	printk( KERN_INFO "Found %d ACSI device(s) and %d SLM printer(s) total.\n",
-			NDevices, n_slm );
-#endif
-	err = -ENOMEM;
-	for( i = 0; i < NDevices; ++i ) {
-		acsi_gendisk[i] = alloc_disk(16);
-		if (!acsi_gendisk[i])
-			goto out4;
-	}
-
-	for( i = 0; i < NDevices; ++i ) {
-		struct gendisk *disk = acsi_gendisk[i];
-		sprintf(disk->disk_name, "ad%c", 'a'+i);
-		aip = &acsi_info[NDevices];
-		disk->major = ACSI_MAJOR;
-		disk->first_minor = i << 4;
-		if (acsi_info[i].type != HARDDISK)
-			disk->minors = 1;
-		disk->fops = &acsi_fops;
-		disk->private_data = &acsi_info[i];
-		set_capacity(disk, acsi_info[i].size);
-		disk->queue = acsi_queue;
-		add_disk(disk);
-	}
-	return 0;
-out4:
-	while (i--)
-		put_disk(acsi_gendisk[i]);
-out3:
-	blk_cleanup_queue(acsi_queue);
-out2a:
-	atari_stram_free( acsi_buffer );
-out2:
-	unregister_blkdev( ACSI_MAJOR, "ad" );
-out1:
-	return err;
-}
-
-
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	int err;
-
-	if ((err = acsi_init()))
-		return( err );
-	printk( KERN_INFO "ACSI driver loaded as module.\n");
-	return( 0 );
-}
-
-void cleanup_module(void)
-{
-	int i;
-	del_timer( &acsi_timer );
-	blk_cleanup_queue(acsi_queue);
-	atari_stram_free( acsi_buffer );
-
-	if (unregister_blkdev( ACSI_MAJOR, "ad" ) != 0)
-		printk( KERN_ERR "acsi: cleanup_module failed\n");
-
-	for (i = 0; i < NDevices; i++) {
-		del_gendisk(acsi_gendisk[i]);
-		put_disk(acsi_gendisk[i]);
-	}
-}
-#endif
-
-/*
- * This routine is called to flush all partitions and partition tables
- * for a changed scsi disk, and then re-read the new partition table.
- * If we are revalidating a disk because of a media change, then we
- * enter with usage == 0.  If we are using an ioctl, we automatically have
- * usage == 1 (we need an open channel to use an ioctl :-), so this
- * is our limit.
- *
- * Changes by Martin Rogge, 9th Aug 1995: 
- * got cd-roms to work by calling acsi_devinit. There are only two problems:
- * First, if there is no medium inserted, the status will remain "changed".
- * That is no problem at all, but our design of three-valued logic (medium
- * changed, medium not changed, no medium inserted).
- * Secondly the check could fail completely and the drive could deliver
- * nonsensical data, which could mess up the acsi_info[] structure. In
- * that case we try to make the entry safe.
- *
- */
-
-static int acsi_revalidate(struct gendisk *disk)
-{
-	struct acsi_info_struct *aip = disk->private_data;
-	stdma_lock( NULL, NULL );
-	if (acsi_devinit(aip) != DEV_SUPPORTED) {
-		printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",
-		       aip->target, aip->lun);
-		aip->size = 0;
-		aip->read_only = 1;
-		aip->removable = 1;
-		aip->changed = 1; /* next acsi_open will try again... */
-	}
-
-	ENABLE_IRQ();
-	stdma_release();
-	set_capacity(disk, aip->size);
-	return 0;
-}
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
deleted file mode 100644
index 1d9d9b4..0000000
--- a/drivers/block/acsi_slm.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * acsi_slm.c -- Device driver for the Atari SLM laser printer
- *
- * Copyright 1995 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- * 
- */
-
-/*
-
-Notes:
-
-The major number for SLM printers is 28 (like ACSI), but as a character
-device, not block device. The minor number is the number of the printer (if
-you have more than one SLM; currently max. 2 (#define-constant) SLMs are
-supported). The device can be opened for reading and writing. If reading it,
-you get some status infos (MODE SENSE data). Writing mode is used for the data
-to be printed. Some ioctls allow to get the printer status and to tune printer
-modes and some internal variables.
-
-A special problem of the SLM driver is the timing and thus the buffering of
-the print data. The problem is that all the data for one page must be present
-in memory when printing starts, else --when swapping occurs-- the timing could
-not be guaranteed. There are several ways to assure this:
-
- 1) Reserve a buffer of 1196k (maximum page size) statically by
-    atari_stram_alloc(). The data are collected there until they're complete,
-	and then printing starts. Since the buffer is reserved, no further
-	considerations about memory and swapping are needed. So this is the
-	simplest method, but it needs a lot of memory for just the SLM.
-
-    An striking advantage of this method is (supposed the SLM_CONT_CNT_REPROG
-	method works, see there), that there are no timing problems with the DMA
-	anymore.
-	
- 2) The other method would be to reserve the buffer dynamically each time
-    printing is required. I could think of looking at mem_map where the
-	largest unallocted ST-RAM area is, taking the area, and then extending it
-	by swapping out the neighbored pages, until the needed size is reached.
-	This requires some mm hacking, but seems possible. The only obstacle could
-	be pages that cannot be swapped out (reserved pages)...
-
- 3) Another possibility would be to leave the real data in user space and to
-    work with two dribble buffers of about 32k in the driver: While the one
-	buffer is DMAed to the SLM, the other can be filled with new data. But
-	to keep the timing, that requires that the user data remain in memory and
-	are not swapped out. Requires mm hacking, too, but maybe not so bad as
-	method 2).
-
-*/
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-#include <asm/atari_SLM.h>
-
-
-#undef	DEBUG
-
-/* Define this if the page data are continuous in physical memory. That
- * requires less reprogramming of the ST-DMA */
-#define	SLM_CONTINUOUS_DMA
-
-/* Use continuous reprogramming of the ST-DMA counter register. This is
- * --strictly speaking-- not allowed, Atari recommends not to look at the
- * counter register while a DMA is going on. But I don't know if that applies
- * only for reading the register, or also writing to it. Writing only works
- * fine for me... The advantage is that the timing becomes absolutely
- * uncritical: Just update each, say 200ms, the counter reg to its maximum,
- * and the DMA will work until the status byte interrupt occurs.
- */
-#define	SLM_CONT_CNT_REPROG
-
-#define CMDSET_TARG_LUN(cmd,targ,lun)			\
-    do {										\
-		cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5;	\
-		cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5;	\
-	} while(0)
-
-#define	START_TIMER(to)	mod_timer(&slm_timer, jiffies + (to))
-#define	STOP_TIMER()	del_timer(&slm_timer)
-
-
-static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 };
-static char slmprint_cmd[6]    = { 0x0a, 0, 0, 0, 0, 0 };
-static char slminquiry_cmd[6]  = { 0x12, 0, 0, 0, 0, 0x80 };
-static char slmmsense_cmd[6]   = { 0x1a, 0, 0, 0, 255, 0 };
-#if 0
-static char slmmselect_cmd[6]  = { 0x15, 0, 0, 0, 0, 0 };
-#endif
-
-
-#define	MAX_SLM		2
-
-static struct slm {
-	unsigned	target;			/* target number */
-	unsigned	lun;			/* LUN in target controller */
-	atomic_t	wr_ok; 			/* set to 0 if output part busy */
-	atomic_t	rd_ok;			/* set to 0 if status part busy */
-} slm_info[MAX_SLM];
-
-int N_SLM_Printers = 0;
-
-/* printer buffer */
-static unsigned char	*SLMBuffer;	/* start of buffer */
-static unsigned char	*BufferP;	/* current position in buffer */
-static int				BufferSize;	/* length of buffer for page size */
-
-typedef enum { IDLE, FILLING, PRINTING } SLMSTATE;
-static SLMSTATE			SLMState;
-static int				SLMBufOwner;	/* SLM# currently using the buffer */
-
-/* DMA variables */
-#ifndef SLM_CONT_CNT_REPROG
-static unsigned long	SLMCurAddr;		/* current base addr of DMA chunk */
-static unsigned long	SLMEndAddr;		/* expected end addr */
-static unsigned long	SLMSliceSize;	/* size of one DMA chunk */
-#endif
-static int				SLMError;
-
-/* wait queues */
-static DECLARE_WAIT_QUEUE_HEAD(slm_wait);	/* waiting for buffer */
-static DECLARE_WAIT_QUEUE_HEAD(print_wait);	/* waiting for printing finished */
-
-/* status codes */
-#define	SLMSTAT_OK		0x00
-#define	SLMSTAT_ORNERY	0x02
-#define	SLMSTAT_TONER	0x03
-#define	SLMSTAT_WARMUP	0x04
-#define	SLMSTAT_PAPER	0x05
-#define	SLMSTAT_DRUM	0x06
-#define	SLMSTAT_INJAM	0x07
-#define	SLMSTAT_THRJAM	0x08
-#define	SLMSTAT_OUTJAM	0x09
-#define	SLMSTAT_COVER	0x0a
-#define	SLMSTAT_FUSER	0x0b
-#define	SLMSTAT_IMAGER	0x0c
-#define	SLMSTAT_MOTOR	0x0d
-#define	SLMSTAT_VIDEO	0x0e
-#define	SLMSTAT_SYSTO	0x10
-#define	SLMSTAT_OPCODE	0x12
-#define	SLMSTAT_DEVNUM	0x15
-#define	SLMSTAT_PARAM	0x1a
-#define	SLMSTAT_ACSITO	0x1b	/* driver defined */
-#define	SLMSTAT_NOTALL	0x1c	/* driver defined */
-
-static char *SLMErrors[] = {
-	/* 0x00 */	"OK and ready",
-	/* 0x01 */	NULL,
-	/* 0x02 */	"ornery printer",
-	/* 0x03 */	"toner empty",
-	/* 0x04 */	"warming up",
-	/* 0x05 */	"paper empty",
-	/* 0x06 */	"drum empty",
-	/* 0x07 */	"input jam",
-	/* 0x08 */	"through jam",
-	/* 0x09 */	"output jam",
-	/* 0x0a */	"cover open",
-	/* 0x0b */	"fuser malfunction",
-	/* 0x0c */	"imager malfunction",
-	/* 0x0d */	"motor malfunction",
-	/* 0x0e */	"video malfunction",
-	/* 0x0f */	NULL,
-	/* 0x10 */	"printer system timeout",
-	/* 0x11 */	NULL,
-	/* 0x12 */	"invalid operation code",
-	/* 0x13 */	NULL,
-	/* 0x14 */	NULL,
-	/* 0x15 */	"invalid device number",
-	/* 0x16 */	NULL,
-	/* 0x17 */	NULL,
-	/* 0x18 */	NULL,
-	/* 0x19 */	NULL,
-	/* 0x1a */	"invalid parameter list",
-	/* 0x1b */	"ACSI timeout",
-	/* 0x1c */	"not all printed"
-};
-
-#define	N_ERRORS	(sizeof(SLMErrors)/sizeof(*SLMErrors))
-
-/* real (driver caused) error? */
-#define	IS_REAL_ERROR(x)	(x > 0x10)
-
-
-static struct {
-	char	*name;
-	int 	w, h;
-} StdPageSize[] = {
-	{ "Letter", 2400, 3180 },
-	{ "Legal",  2400, 4080 },
-	{ "A4",     2336, 3386 },
-	{ "B5",     2016, 2914 }
-};
-
-#define	N_STD_SIZES		(sizeof(StdPageSize)/sizeof(*StdPageSize))
-
-#define	SLM_BUFFER_SIZE	(2336*3386/8)	/* A4 for now */
-#define	SLM_DMA_AMOUNT	255				/* #sectors to program the DMA for */
-
-#ifdef	SLM_CONTINUOUS_DMA
-# define	SLM_DMA_INT_OFFSET	0		/* DMA goes until seccnt 0, no offs */
-# define	SLM_DMA_END_OFFSET	32		/* 32 Byte ST-DMA FIFO */
-# define	SLM_SLICE_SIZE(w) 	(255*512)
-#else
-# define	SLM_DMA_INT_OFFSET	32		/* 32 Byte ST-DMA FIFO */
-# define	SLM_DMA_END_OFFSET	32		/* 32 Byte ST-DMA FIFO */
-# define	SLM_SLICE_SIZE(w)	((254*512)/(w/8)*(w/8))
-#endif
-
-/* calculate the number of jiffies to wait for 'n' bytes */
-#ifdef SLM_CONT_CNT_REPROG
-#define	DMA_TIME_FOR(n)		50
-#define	DMA_STARTUP_TIME	0
-#else
-#define	DMA_TIME_FOR(n)		(n/1400-1)
-#define	DMA_STARTUP_TIME	650
-#endif
-
-/***************************** Prototypes *****************************/
-
-static char *slm_errstr( int stat );
-static int slm_getstats( char *buffer, int device );
-static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
-                         *ppos );
-static void start_print( int device );
-static irqreturn_t slm_interrupt(int irc, void *data);
-static void slm_test_ready( unsigned long dummy );
-static void set_dma_addr( unsigned long paddr );
-static unsigned long get_dma_addr( void );
-static ssize_t slm_write( struct file *file, const char *buf, size_t count,
-                          loff_t *ppos );
-static int slm_ioctl( struct inode *inode, struct file *file, unsigned int
-                      cmd, unsigned long arg );
-static int slm_open( struct inode *inode, struct file *file );
-static int slm_release( struct inode *inode, struct file *file );
-static int slm_req_sense( int device );
-static int slm_mode_sense( int device, char *buffer, int abs_flag );
-#if 0
-static int slm_mode_select( int device, char *buffer, int len, int
-                            default_flag );
-#endif
-static int slm_get_pagesize( int device, int *w, int *h );
-
-/************************* End of Prototypes **************************/
-
-
-static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
-
-static const struct file_operations slm_fops = {
-	.owner =	THIS_MODULE,
-	.read =		slm_read,
-	.write =	slm_write,
-	.ioctl =	slm_ioctl,
-	.open =		slm_open,
-	.release =	slm_release,
-};
-
-
-/* ---------------------------------------------------------------------- */
-/*							   Status Functions							  */
-
-
-static char *slm_errstr( int stat )
-
-{	char *p;
-	static char	str[22];
-
-	stat &= 0x1f;
-	if (stat >= 0 && stat < N_ERRORS && (p = SLMErrors[stat]))
-		return( p );
-	sprintf( str, "unknown status 0x%02x", stat );
-	return( str );
-}
-
-
-static int slm_getstats( char *buffer, int device )
-
-{	int 			len = 0, stat, i, w, h;
-	unsigned char	buf[256];
-	
-	stat = slm_mode_sense( device, buf, 0 );
-	if (IS_REAL_ERROR(stat))
-		return( -EIO );
-	
-#define SHORTDATA(i)		((buf[i] << 8) | buf[i+1])
-#define	BOOLDATA(i,mask)	((buf[i] & mask) ? "on" : "off")
-
-	w = SHORTDATA( 3 );
-	h = SHORTDATA( 1 );
-		
-	len += sprintf( buffer+len, "Status\t\t%s\n",
-					slm_errstr( stat ) );
-	len += sprintf( buffer+len, "Page Size\t%dx%d",
-					w, h );
-
-	for( i = 0; i < N_STD_SIZES; ++i ) {
-		if (w == StdPageSize[i].w && h == StdPageSize[i].h)
-			break;
-	}
-	if (i < N_STD_SIZES)
-		len += sprintf( buffer+len, " (%s)", StdPageSize[i].name );
-	buffer[len++] = '\n';
-
-	len += sprintf( buffer+len, "Top/Left Margin\t%d/%d\n",
-					SHORTDATA( 5 ), SHORTDATA( 7 ) );
-	len += sprintf( buffer+len, "Manual Feed\t%s\n",
-					BOOLDATA( 9, 0x01 ) );
-	len += sprintf( buffer+len, "Input Select\t%d\n",
-					(buf[9] >> 1) & 7 );
-	len += sprintf( buffer+len, "Auto Select\t%s\n",
-					BOOLDATA( 9, 0x10 ) );
-	len += sprintf( buffer+len, "Prefeed Paper\t%s\n",
-					BOOLDATA( 9, 0x20 ) );
-	len += sprintf( buffer+len, "Thick Pixels\t%s\n",
-					BOOLDATA( 9, 0x40 ) );
-	len += sprintf( buffer+len, "H/V Resol.\t%d/%d dpi\n",
-					SHORTDATA( 12 ), SHORTDATA( 10 ) );
-	len += sprintf( buffer+len, "System Timeout\t%d\n",
-					buf[14] );
-	len += sprintf( buffer+len, "Scan Time\t%d\n",
-					SHORTDATA( 15 ) );
-	len += sprintf( buffer+len, "Page Count\t%d\n",
-					SHORTDATA( 17 ) );
-	len += sprintf( buffer+len, "In/Out Cap.\t%d/%d\n",
-					SHORTDATA( 19 ), SHORTDATA( 21 ) );
-	len += sprintf( buffer+len, "Stagger Output\t%s\n",
-					BOOLDATA( 23, 0x01 ) );
-	len += sprintf( buffer+len, "Output Select\t%d\n",
-					(buf[23] >> 1) & 7 );
-	len += sprintf( buffer+len, "Duplex Print\t%s\n",
-					BOOLDATA( 23, 0x10 ) );
-	len += sprintf( buffer+len, "Color Sep.\t%s\n",
-					BOOLDATA( 23, 0x20 ) );
-
-	return( len );
-}
-
-
-static ssize_t slm_read( struct file *file, char *buf, size_t count,
-						 loff_t *ppos )
-
-{
-	struct inode *node = file->f_path.dentry->d_inode;
-	unsigned long page;
-	int length;
-	int end;
-
-	if (!(page = __get_free_page( GFP_KERNEL )))
-		return( -ENOMEM );
-	
-	length = slm_getstats( (char *)page, iminor(node) );
-	if (length < 0) {
-		count = length;
-		goto out;
-	}
-	if (file->f_pos >= length) {
-		count = 0;
-		goto out;
-	}
-	if (count + file->f_pos > length)
-		count = length - file->f_pos;
-	end = count + file->f_pos;
-	if (copy_to_user(buf, (char *)page + file->f_pos, count)) {
-		count = -EFAULT;
-		goto out;
-	}
-	file->f_pos = end;
-out:	free_page( page );
-	return( count );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*								   Printing								  */
-
-
-static void start_print( int device )
-
-{	struct slm *sip = &slm_info[device];
-	unsigned char	*cmd;
-	unsigned long	paddr;
-	int				i;
-	
-	stdma_lock( slm_interrupt, NULL );
-
-	CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun );
-	cmd = slmprint_cmd;
-	paddr = virt_to_phys( SLMBuffer );
-	dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 );
-	DISABLE_IRQ();
-
-	/* Low on A1 */
-	dma_wd.dma_mode_status = 0x88;
-	MFPDELAY();
-
-	/* send the command bytes except the last */
-	for( i = 0; i < 5; ++i ) {
-		DMA_LONG_WRITE( *cmd++, 0x8a );
-		udelay(20);
-		if (!acsi_wait_for_IRQ( HZ/2 )) {
-			SLMError = 1;
-			return; /* timeout */
-		}
-	}
-	/* last command byte */
-	DMA_LONG_WRITE( *cmd++, 0x82 );
-	MFPDELAY();
-	/* set DMA address */
-	set_dma_addr( paddr );
-	/* program DMA for write and select sector counter reg */
-	dma_wd.dma_mode_status = 0x192;
-	MFPDELAY();
-	/* program for 255*512 bytes and start DMA */
-	DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
-
-#ifndef SLM_CONT_CNT_REPROG
-	SLMCurAddr = paddr;
-	SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
-#endif
-	START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize ));
-#if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG)
-	printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
-			SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
-#endif
-	
-	ENABLE_IRQ();
-}
-
-
-/* Only called when an error happened or at the end of a page */
-
-static irqreturn_t slm_interrupt(int irc, void *data)
-
-{	unsigned long	addr;
-	int				stat;
-	
-	STOP_TIMER();
-	addr = get_dma_addr();
-	stat = acsi_getstatus();
-	SLMError = (stat < 0)             ? SLMSTAT_ACSITO :
-		       (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL :
-									    stat;
-
-	dma_wd.dma_mode_status = 0x80;
-	MFPDELAY();
-#ifdef DEBUG
-	printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError );
-#endif
-
-	wake_up( &print_wait );
-	stdma_release();
-	ENABLE_IRQ();
-	return IRQ_HANDLED;
-}
-
-
-static void slm_test_ready( unsigned long dummy )
-
-{
-#ifdef SLM_CONT_CNT_REPROG
-	/* program for 255*512 bytes again */
-	dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
-	START_TIMER( DMA_TIME_FOR(0) );
-#ifdef DEBUG
-	printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n",
-			DMA_TIME_FOR(0), get_dma_addr() );
-#endif
-	
-#else /* !SLM_CONT_CNT_REPROG */
-
-	unsigned long	flags, addr;
-	int				d, ti;
-#ifdef DEBUG
-	struct timeval start_tm, end_tm;
-	int			   did_wait = 0;
-#endif
-
-	local_irq_save(flags);
-
-	addr = get_dma_addr();
-	if ((d = SLMEndAddr - addr) > 0) {
-		local_irq_restore(flags);
-		
-		/* slice not yet finished, decide whether to start another timer or to
-		 * busy-wait */
-		ti = DMA_TIME_FOR( d );
-		if (ti > 0) {
-#ifdef DEBUG
-			printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n",
-					ti, d );
-#endif
-			START_TIMER( ti );
-			return;
-		}
-		/* wait for desired end address to be reached */
-#ifdef DEBUG
-		do_gettimeofday( &start_tm );
-		did_wait = 1;
-#endif
-		local_irq_disable();
-		while( get_dma_addr() < SLMEndAddr )
-			barrier();
-	}
-
-	/* slice finished, start next one */
-	SLMCurAddr += SLMSliceSize;
-
-#ifdef SLM_CONTINUOUS_DMA
-	/* program for 255*512 bytes again */
-	dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
-#else
-	/* set DMA address;
-	 * add 2 bytes for the ones in the SLM controller FIFO! */
-	set_dma_addr( SLMCurAddr + 2 );
-	/* toggle DMA to write and select sector counter reg */
-	dma_wd.dma_mode_status = 0x92;
-	MFPDELAY();
-	dma_wd.dma_mode_status = 0x192;
-	MFPDELAY();
-	/* program for 255*512 bytes and start DMA */
-	DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
-#endif
-	
-	local_irq_restore(flags);
-
-#ifdef DEBUG
-	if (did_wait) {
-		int ms;
-		do_gettimeofday( &end_tm );
-		ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) -
-			 (start_tm.tv_sec*1000000+start_tm.tv_usec); 
-		printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n",
-				ms/1000, ms%1000, d );
-	}
-	else
-		printk( "SLM: didn't wait (!)\n" );
-#endif
-
-	if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) {
-		/* will be last slice, no timer necessary */
-#ifdef DEBUG
-		printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n",
-				SLMCurAddr, SLMEndAddr );
-#endif
-	}
-	else {
-		/* not last slice */
-		SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
-		START_TIMER( DMA_TIME_FOR( SLMSliceSize ));
-#ifdef DEBUG
-		printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
-				SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
-#endif
-	}
-#endif /* SLM_CONT_CNT_REPROG */
-}
-
-
-static void set_dma_addr( unsigned long paddr )
-
-{	unsigned long flags;
-
-	local_irq_save(flags);
-	dma_wd.dma_lo = (unsigned char)paddr;
-	paddr >>= 8;
-	MFPDELAY();
-	dma_wd.dma_md = (unsigned char)paddr;
-	paddr >>= 8;
-	MFPDELAY();
-	if (ATARIHW_PRESENT( EXTD_DMA ))
-		st_dma_ext_dmahi = (unsigned short)paddr;
-	else
-		dma_wd.dma_hi = (unsigned char)paddr;
-	MFPDELAY();
-	local_irq_restore(flags);
-}
-
-
-static unsigned long get_dma_addr( void )
-
-{	unsigned long	addr;
-	
-	addr = dma_wd.dma_lo & 0xff;
-	MFPDELAY();
-	addr |= (dma_wd.dma_md & 0xff) << 8;
-	MFPDELAY();
-	addr |= (dma_wd.dma_hi & 0xff) << 16;
-	MFPDELAY();
-
-	return( addr );
-}
-
-
-static ssize_t slm_write( struct file *file, const char *buf, size_t count,
-						  loff_t *ppos )
-
-{
-	struct inode *node = file->f_path.dentry->d_inode;
-	int		device = iminor(node);
-	int		n, filled, w, h;
-
-	while( SLMState == PRINTING ||
-		   (SLMState == FILLING && SLMBufOwner != device) ) {
-		interruptible_sleep_on( &slm_wait );
-		if (signal_pending(current))
-			return( -ERESTARTSYS );
-	}
-	if (SLMState == IDLE) {
-		/* first data of page: get current page size  */
-		if (slm_get_pagesize( device, &w, &h ))
-			return( -EIO );
-		BufferSize = w*h/8;
-		if (BufferSize > SLM_BUFFER_SIZE)
-			return( -ENOMEM );
-
-		SLMState = FILLING;
-		SLMBufOwner = device;
-	}
-
-	n = count;
-	filled = BufferP - SLMBuffer;
-	if (filled + n > BufferSize)
-		n = BufferSize - filled;
-
-	if (copy_from_user(BufferP, buf, n))
-		return -EFAULT;
-	BufferP += n;
-	filled += n;
-
-	if (filled == BufferSize) {
-		/* Check the paper size again! The user may have switched it in the
-		 * time between starting the data and finishing them. Would end up in
-		 * a trashy page... */
-		if (slm_get_pagesize( device, &w, &h ))
-			return( -EIO );
-		if (BufferSize != w*h/8) {
-			printk( KERN_NOTICE "slm%d: page size changed while printing\n",
-					device );
-			return( -EAGAIN );
-		}
-
-		SLMState = PRINTING;
-		/* choose a slice size that is a multiple of the line size */
-#ifndef SLM_CONT_CNT_REPROG
-		SLMSliceSize = SLM_SLICE_SIZE(w);
-#endif
-		
-		start_print( device );
-		sleep_on( &print_wait );
-		if (SLMError && IS_REAL_ERROR(SLMError)) {
-			printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) );
-			n = -EIO;
-		}
-
-		SLMState = IDLE;
-		BufferP = SLMBuffer;
-		wake_up_interruptible( &slm_wait );
-	}
-	
-	return( n );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*							   ioctl Functions							  */
-
-
-static int slm_ioctl( struct inode *inode, struct file *file,
-					  unsigned int cmd, unsigned long arg )
-
-{	int		device = iminor(inode), err;
-	
-	/* I can think of setting:
-	 *  - manual feed
-	 *  - paper format
-	 *  - copy count
-	 *  - ...
-	 * but haven't implemented that yet :-)
-	 * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data?
-	 */
-	switch( cmd ) {
-
-	  case SLMIORESET:		/* reset buffer, i.e. empty the buffer */
-		if (!(file->f_mode & 2))
-			return( -EINVAL );
-		if (SLMState == PRINTING)
-			return( -EBUSY );
-		SLMState = IDLE;
-		BufferP = SLMBuffer;
-		wake_up_interruptible( &slm_wait );
-		return( 0 );
-		
-	  case SLMIOGSTAT: {	/* get status */
-		int stat;
-		char *str;
-
-		stat = slm_req_sense( device );
-		if (arg) {
-			str = slm_errstr( stat );
-			if (put_user(stat,
-    	    	    	    	     (long *)&((struct SLM_status *)arg)->stat))
-    	    	    	    	return -EFAULT;
-			if (copy_to_user( ((struct SLM_status *)arg)->str, str,
-						 strlen(str) + 1))
-				return -EFAULT;
-		}
-		return( stat );
-	  }
-		
-	  case SLMIOGPSIZE: {	/* get paper size */
-		int w, h;
-		
-		if ((err = slm_get_pagesize( device, &w, &h ))) return( err );
-		
-    	    	if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width))
-			return -EFAULT;
-		if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height))
-			return -EFAULT;
-		return( 0 );
-	  }
-		
-	  case SLMIOGMFEED:	/* get manual feed */
-		return( -EINVAL );
-
-	  case SLMIOSPSIZE:	/* set paper size */
-		return( -EINVAL );
-
-	  case SLMIOSMFEED:	/* set manual feed */
-		return( -EINVAL );
-
-	}
-	return( -EINVAL );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*							 Opening and Closing						  */
-
-
-static int slm_open( struct inode *inode, struct file *file )
-
-{	int device;
-	struct slm *sip;
-	
-	device = iminor(inode);
-	if (device >= N_SLM_Printers)
-		return( -ENXIO );
-	sip = &slm_info[device];
-
-	if (file->f_mode & 2) {
-		/* open for writing is exclusive */
-		if ( !atomic_dec_and_test(&sip->wr_ok) ) {
-			atomic_inc(&sip->wr_ok);	
-			return( -EBUSY );
-		}
-	}
-	if (file->f_mode & 1) {
-		/* open for reading is exclusive */
-                if ( !atomic_dec_and_test(&sip->rd_ok) ) {
-                        atomic_inc(&sip->rd_ok);
-                        return( -EBUSY );
-                }
-	}
-
-	return( 0 );
-}
-
-
-static int slm_release( struct inode *inode, struct file *file )
-
-{	int device;
-	struct slm *sip;
-	
-	device = iminor(inode);
-	sip = &slm_info[device];
-
-	if (file->f_mode & 2)
-		atomic_inc( &sip->wr_ok );
-	if (file->f_mode & 1)
-		atomic_inc( &sip->rd_ok );
-	
-	return( 0 );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*						 ACSI Primitives for the SLM					  */
-
-
-static int slm_req_sense( int device )
-
-{	int			stat, rv;
-	struct slm *sip = &slm_info[device];
-	
-	stdma_lock( NULL, NULL );
-
-	CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun );
-	if (!acsicmd_nodma( slmreqsense_cmd, 0 ) ||
-		(stat = acsi_getstatus()) < 0)
-		rv = SLMSTAT_ACSITO;
-	else
-		rv = stat & 0x1f;
-
-	ENABLE_IRQ();
-	stdma_release();
-	return( rv );
-}
-
-
-static int slm_mode_sense( int device, char *buffer, int abs_flag )
-
-{	unsigned char	stat, len;
-	int				rv = 0;
-	struct slm		*sip = &slm_info[device];
-	
-	stdma_lock( NULL, NULL );
-
-	CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun );
-	slmmsense_cmd[5] = abs_flag ? 0x80 : 0;
-	if (!acsicmd_nodma( slmmsense_cmd, 0 )) {
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-
-	if (!acsi_extstatus( &stat, 1 )) {
-		acsi_end_extstatus();
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-	
-	if (!acsi_extstatus( &len, 1 )) {
-		acsi_end_extstatus();
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-	buffer[0] = len;
-	if (!acsi_extstatus( buffer+1, len )) {
-		acsi_end_extstatus();
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-	
-	acsi_end_extstatus();
-	rv = stat & 0x1f;
-
-  the_end:
-	ENABLE_IRQ();
-	stdma_release();
-	return( rv );
-}
-
-
-#if 0
-/* currently unused */
-static int slm_mode_select( int device, char *buffer, int len,
-							int default_flag )
-
-{	int			stat, rv;
-	struct slm	*sip = &slm_info[device];
-	
-	stdma_lock( NULL, NULL );
-
-	CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun );
-	slmmselect_cmd[5] = default_flag ? 0x80 : 0;
-	if (!acsicmd_nodma( slmmselect_cmd, 0 )) {
-		rv = SLMSTAT_ACSITO;
-		goto the_end;
-	}
-
-	if (!default_flag) {
-		unsigned char c = len;
-		if (!acsi_extcmd( &c, 1 )) {
-			rv = SLMSTAT_ACSITO;
-			goto the_end;
-		}
-		if (!acsi_extcmd( buffer, len )) {
-			rv = SLMSTAT_ACSITO;
-			goto the_end;
-		}
-	}
-	
-	stat = acsi_getstatus();
-	rv = (stat < 0 ? SLMSTAT_ACSITO : stat);
-
-  the_end:
-	ENABLE_IRQ();
-	stdma_release();
-	return( rv );
-}
-#endif
-
-
-static int slm_get_pagesize( int device, int *w, int *h )
-
-{	char	buf[256];
-	int		stat;
-	
-	stat = slm_mode_sense( device, buf, 0 );
-	ENABLE_IRQ();
-	stdma_release();
-
-	if (stat != SLMSTAT_OK)
-		return( -EIO );
-
-	*w = (buf[3] << 8) | buf[4];
-	*h = (buf[1] << 8) | buf[2];
-	return( 0 );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*								Initialization							  */
-
-
-int attach_slm( int target, int lun )
-
-{	static int	did_register;
-	int			len;
-
-	if (N_SLM_Printers >= MAX_SLM) {
-		printk( KERN_WARNING "Too much SLMs\n" );
-		return( 0 );
-	}
-	
-	/* do an INQUIRY */
-	udelay(100);
-	CMDSET_TARG_LUN( slminquiry_cmd, target, lun );
-	if (!acsicmd_nodma( slminquiry_cmd, 0 )) {
-	  inq_timeout:
-		printk( KERN_ERR "SLM inquiry command timed out.\n" );
-	  inq_fail:
-		acsi_end_extstatus();
-		return( 0 );
-	}
-	/* read status and header of return data */
-	if (!acsi_extstatus( SLMBuffer, 6 ))
-		goto inq_timeout;
-
-	if (SLMBuffer[1] != 2) { /* device type == printer? */
-		printk( KERN_ERR "SLM inquiry returned device type != printer\n" );
-		goto inq_fail;
-	}
-	len = SLMBuffer[5];
-	
-	/* read id string */
-	if (!acsi_extstatus( SLMBuffer, len ))
-		goto inq_timeout;
-	acsi_end_extstatus();
-	SLMBuffer[len] = 0;
-
-	if (!did_register) {
-		did_register = 1;
-	}
-
-	slm_info[N_SLM_Printers].target = target;
-	slm_info[N_SLM_Printers].lun    = lun;
-	atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 ); 
-	atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 );
-	
-	printk( KERN_INFO "  Printer: %s\n", SLMBuffer );
-	printk( KERN_INFO "Detected slm%d at id %d lun %d\n",
-			N_SLM_Printers, target, lun );
-	N_SLM_Printers++;
-	return( 1 );
-}
-
-int slm_init( void )
-
-{
-	int i;
-	if (register_chrdev( ACSI_MAJOR, "slm", &slm_fops )) {
-		printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", ACSI_MAJOR );
-		return -EBUSY;
-	}
-	
-	if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) {
-		printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" );
-		unregister_chrdev( ACSI_MAJOR, "slm" );
-		return -ENOMEM;
-	}
-	BufferP = SLMBuffer;
-	SLMState = IDLE;
-	
-	return 0;
-}
-
-#ifdef MODULE
-
-/* from acsi.c */
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-
-int init_module(void)
-{
-	int err;
-
-	if ((err = slm_init()))
-		return( err );
-	/* This calls attach_slm() for every target/lun where acsi.c detected a
-	 * printer */
-	acsi_attach_SLMs( attach_slm );
-	return( 0 );
-}
-
-void cleanup_module(void)
-{
-	if (unregister_chrdev( ACSI_MAJOR, "slm" ) != 0)
-		printk( KERN_ERR "acsi_slm: cleanup_module failed\n");
-	atari_stram_free( SLMBuffer );
-}
-#endif
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 27a1390..6ce8b89 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1363,7 +1363,7 @@
 #ifdef DEBUG
 		printk("fd: sector %ld + %d requested for %s\n",
 		       CURRENT->sector,cnt,
-		       (CURRENT->cmd==READ)?"read":"write");
+		       (rq_data_dir(CURRENT) == READ) ? "read" : "write");
 #endif
 		block = CURRENT->sector + cnt;
 		if ((int)block > floppy->blocks) {
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5acc6c4..a2d6612 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -87,6 +87,7 @@
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3214},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3215},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3237},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x323D},
 	{PCI_VENDOR_ID_HP,     PCI_ANY_ID,	PCI_ANY_ID, PCI_ANY_ID,
 		PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
 	{0,}
@@ -119,6 +120,7 @@
 	{0x3214103C, "Smart Array E200i", &SA5_access, 120},
 	{0x3215103C, "Smart Array E200i", &SA5_access, 120},
 	{0x3237103C, "Smart Array E500", &SA5_access, 512},
+	{0x323D103C, "Smart Array P700m", &SA5_access, 512},
 	{0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
 };
 
@@ -1168,7 +1170,7 @@
 	case SG_EMULATED_HOST:
 	case SG_IO:
 	case SCSI_IOCTL_SEND_COMMAND:
-		return scsi_cmd_ioctl(filep, disk, cmd, argp);
+		return scsi_cmd_ioctl(filep, disk->queue, disk, cmd, argp);
 
 	/* scsi_cmd_ioctl would normally handle these, below, but */
 	/* they aren't a good fit for cciss, as CD-ROMs are */
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 90961a8..4aca7dd 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -555,7 +555,6 @@
 {
 	struct scsi_cmnd *cmd;
 	ctlr_info_t *ctlr;
-	u64bit addr64;
 	ErrorInfo_struct *ei;
 
 	ei = cp->err_info;
@@ -569,20 +568,7 @@
 	cmd = (struct scsi_cmnd *) cp->scsi_cmd;	
 	ctlr = hba[cp->ctlr];
 
-	/* undo the DMA mappings */
-
-	if (cmd->use_sg) {
-		pci_unmap_sg(ctlr->pdev,
-			cmd->request_buffer, cmd->use_sg,
-				cmd->sc_data_direction); 
-	}
-	else if (cmd->request_bufflen) {
-		addr64.val32.lower = cp->SG[0].Addr.lower;
-                addr64.val32.upper = cp->SG[0].Addr.upper;
-                pci_unmap_single(ctlr->pdev, (dma_addr_t) addr64.val,
-                	cmd->request_bufflen, 
-				cmd->sc_data_direction);
-	}
+	scsi_dma_unmap(cmd);
 
 	cmd->result = (DID_OK << 16); 		/* host byte */
 	cmd->result |= (COMMAND_COMPLETE << 8);	/* msg byte */
@@ -597,7 +583,7 @@
 		ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
 			SCSI_SENSE_BUFFERSIZE : 
 			ei->SenseLen);
-	cmd->resid = ei->ResidualCnt;
+	scsi_set_resid(cmd, ei->ResidualCnt);
 
 	if(ei->CommandStatus != 0) 
 	{ /* an error has occurred */ 
@@ -1204,46 +1190,29 @@
 		CommandList_struct *cp,	
 		struct scsi_cmnd *cmd)
 {
-	unsigned int use_sg, nsegs=0, len;
-	struct scatterlist *scatter = (struct scatterlist *) cmd->request_buffer;
+	unsigned int len;
+	struct scatterlist *sg;
 	__u64 addr64;
+	int use_sg, i;
 
-	/* is it just one virtual address? */	
-	if (!cmd->use_sg) {
-		if (cmd->request_bufflen) {	/* anything to xfer? */
+	BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
 
-			addr64 = (__u64) pci_map_single(pdev, 
-				cmd->request_buffer, 
-				cmd->request_bufflen, 
-				cmd->sc_data_direction); 
-	
-			cp->SG[0].Addr.lower = 
-			  (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
-			cp->SG[0].Addr.upper =
-			  (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
-			cp->SG[0].Len = cmd->request_bufflen;
-			nsegs=1;
+	use_sg = scsi_dma_map(cmd);
+	if (use_sg) {	/* not too many addrs? */
+		scsi_for_each_sg(cmd, sg, use_sg, i) {
+			addr64 = (__u64) sg_dma_address(sg);
+			len  = sg_dma_len(sg);
+			cp->SG[i].Addr.lower =
+				(__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+			cp->SG[i].Addr.upper =
+				(__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+			cp->SG[i].Len = len;
+			cp->SG[i].Ext = 0;  // we are not chaining
 		}
-	} /* else, must be a list of virtual addresses.... */
-	else if (cmd->use_sg <= MAXSGENTRIES) {	/* not too many addrs? */
+	}
 
-		use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg,
-			cmd->sc_data_direction);
-
-		for (nsegs=0; nsegs < use_sg; nsegs++) {
-			addr64 = (__u64) sg_dma_address(&scatter[nsegs]);
-			len  = sg_dma_len(&scatter[nsegs]);
-			cp->SG[nsegs].Addr.lower =
-			  (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
-			cp->SG[nsegs].Addr.upper =
-			  (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
-			cp->SG[nsegs].Len = len;
-			cp->SG[nsegs].Ext = 0;  // we are not chaining
-		}
-	} else BUG();
-
-	cp->Header.SGList = (__u8) nsegs;   /* no. SGs contig in this cmd */
-	cp->Header.SGTotal = (__u16) nsegs; /* total sgs in this cmd list */
+	cp->Header.SGList = (__u8) use_sg;   /* no. SGs contig in this cmd */
+	cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
 	return;
 }
 
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 3587cb4..fe08804 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -670,7 +670,7 @@
 	if (drive == current_reqD)
 		drive = current_drive;
 	del_timer(&fd_timeout);
-	if (drive < 0 || drive > N_DRIVE) {
+	if (drive < 0 || drive >= N_DRIVE) {
 		fd_timeout.expires = jiffies + 20UL * HZ;
 		drive = 0;
 	} else
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 5526ead..e425daa 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -68,12 +68,14 @@
 #include <linux/loop.h>
 #include <linux/compat.h>
 #include <linux/suspend.h>
+#include <linux/freezer.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>		/* for invalidate_bdev() */
 #include <linux/completion.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
 #include <linux/kthread.h>
+#include <linux/splice.h>
 
 #include <asm/uaccess.h>
 
@@ -401,50 +403,73 @@
 };
 
 static int
-lo_read_actor(read_descriptor_t *desc, struct page *page,
-	      unsigned long offset, unsigned long size)
+lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+		struct splice_desc *sd)
 {
-	unsigned long count = desc->count;
-	struct lo_read_data *p = desc->arg.data;
+	struct lo_read_data *p = sd->u.data;
 	struct loop_device *lo = p->lo;
+	struct page *page = buf->page;
 	sector_t IV;
+	size_t size;
+	int ret;
 
-	IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
+	ret = buf->ops->confirm(pipe, buf);
+	if (unlikely(ret))
+		return ret;
 
-	if (size > count)
-		size = count;
+	IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
+							(buf->offset >> 9);
+	size = sd->len;
+	if (size > p->bsize)
+		size = p->bsize;
 
-	if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) {
-		size = 0;
+	if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) {
 		printk(KERN_ERR "loop: transfer error block %ld\n",
 		       page->index);
-		desc->error = -EINVAL;
+		size = -EINVAL;
 	}
 
 	flush_dcache_page(p->page);
 
-	desc->count = count - size;
-	desc->written += size;
-	p->offset += size;
+	if (size > 0)
+		p->offset += size;
+
 	return size;
 }
 
 static int
+lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+	return __splice_from_pipe(pipe, sd, lo_splice_actor);
+}
+
+static int
 do_lo_receive(struct loop_device *lo,
 	      struct bio_vec *bvec, int bsize, loff_t pos)
 {
 	struct lo_read_data cookie;
+	struct splice_desc sd;
 	struct file *file;
-	int retval;
+	long retval;
 
 	cookie.lo = lo;
 	cookie.page = bvec->bv_page;
 	cookie.offset = bvec->bv_offset;
 	cookie.bsize = bsize;
+
+	sd.len = 0;
+	sd.total_len = bvec->bv_len;
+	sd.flags = 0;
+	sd.pos = pos;
+	sd.u.data = &cookie;
+
 	file = lo->lo_backing_file;
-	retval = file->f_op->sendfile(file, &pos, bvec->bv_len,
-			lo_read_actor, &cookie);
-	return (retval < 0)? retval: 0;
+	retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
+
+	if (retval < 0)
+		return retval;
+
+	return 0;
 }
 
 static int
@@ -576,13 +601,6 @@
 	struct loop_device *lo = data;
 	struct bio *bio;
 
-	/*
-	 * loop can be used in an encrypted device,
-	 * hence, it mustn't be stopped at all
-	 * because it could be indirectly used during suspension
-	 */
-	current->flags |= PF_NOFREEZE;
-
 	set_user_nice(current, -20);
 
 	while (!kthread_should_stop() || lo->lo_bio) {
@@ -679,8 +697,8 @@
 	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
 		goto out_putf;
 
-	/* new backing store needs to support loop (eg sendfile) */
-	if (!inode->i_fop->sendfile)
+	/* new backing store needs to support loop (eg splice_read) */
+	if (!inode->i_fop->splice_read)
 		goto out_putf;
 
 	/* size of the new backing store needs to be the same */
@@ -760,7 +778,7 @@
 		 * If we can't read - sorry. If we only can't write - well,
 		 * it's going to be read-only.
 		 */
-		if (!file->f_op->sendfile)
+		if (!file->f_op->splice_read)
 			goto out_putf;
 		if (aops->prepare_write && aops->commit_write)
 			lo_flags |= LO_FLAGS_USE_AOPS;
@@ -1354,7 +1372,7 @@
  */
 static int max_loop;
 module_param(max_loop, int, 0);
-MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand");
+MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
 
@@ -1394,16 +1412,11 @@
 EXPORT_SYMBOL(loop_register_transfer);
 EXPORT_SYMBOL(loop_unregister_transfer);
 
-static struct loop_device *loop_init_one(int i)
+static struct loop_device *loop_alloc(int i)
 {
 	struct loop_device *lo;
 	struct gendisk *disk;
 
-	list_for_each_entry(lo, &loop_devices, lo_list) {
-		if (lo->lo_number == i)
-			return lo;
-	}
-
 	lo = kzalloc(sizeof(*lo), GFP_KERNEL);
 	if (!lo)
 		goto out;
@@ -1427,8 +1440,6 @@
 	disk->private_data	= lo;
 	disk->queue		= lo->lo_queue;
 	sprintf(disk->disk_name, "loop%d", i);
-	add_disk(disk);
-	list_add_tail(&lo->lo_list, &loop_devices);
 	return lo;
 
 out_free_queue:
@@ -1439,15 +1450,37 @@
 	return NULL;
 }
 
-static void loop_del_one(struct loop_device *lo)
+static void loop_free(struct loop_device *lo)
 {
-	del_gendisk(lo->lo_disk);
 	blk_cleanup_queue(lo->lo_queue);
 	put_disk(lo->lo_disk);
 	list_del(&lo->lo_list);
 	kfree(lo);
 }
 
+static struct loop_device *loop_init_one(int i)
+{
+	struct loop_device *lo;
+
+	list_for_each_entry(lo, &loop_devices, lo_list) {
+		if (lo->lo_number == i)
+			return lo;
+	}
+
+	lo = loop_alloc(i);
+	if (lo) {
+		add_disk(lo->lo_disk);
+		list_add_tail(&lo->lo_list, &loop_devices);
+	}
+	return lo;
+}
+
+static void loop_del_one(struct loop_device *lo)
+{
+	del_gendisk(lo->lo_disk);
+	loop_free(lo);
+}
+
 static struct kobject *loop_probe(dev_t dev, int *part, void *data)
 {
 	struct loop_device *lo;
@@ -1464,30 +1497,78 @@
 
 static int __init loop_init(void)
 {
-	if (register_blkdev(LOOP_MAJOR, "loop"))
-		return -EIO;
-	blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS,
-				  THIS_MODULE, loop_probe, NULL, NULL);
+	int i, nr;
+	unsigned long range;
+	struct loop_device *lo, *next;
+
+	/*
+	 * loop module now has a feature to instantiate underlying device
+	 * structure on-demand, provided that there is an access dev node.
+	 * However, this will not work well with user space tool that doesn't
+	 * know about such "feature".  In order to not break any existing
+	 * tool, we do the following:
+	 *
+	 * (1) if max_loop is specified, create that many upfront, and this
+	 *     also becomes a hard limit.
+	 * (2) if max_loop is not specified, create 8 loop device on module
+	 *     load, user can further extend loop device by create dev node
+	 *     themselves and have kernel automatically instantiate actual
+	 *     device on-demand.
+	 */
+	if (max_loop > 1UL << MINORBITS)
+		return -EINVAL;
 
 	if (max_loop) {
-		printk(KERN_INFO "loop: the max_loop option is obsolete "
-				 "and will be removed in March 2008\n");
-
+		nr = max_loop;
+		range = max_loop;
+	} else {
+		nr = 8;
+		range = 1UL << MINORBITS;
 	}
+
+	if (register_blkdev(LOOP_MAJOR, "loop"))
+		return -EIO;
+
+	for (i = 0; i < nr; i++) {
+		lo = loop_alloc(i);
+		if (!lo)
+			goto Enomem;
+		list_add_tail(&lo->lo_list, &loop_devices);
+	}
+
+	/* point of no return */
+
+	list_for_each_entry(lo, &loop_devices, lo_list)
+		add_disk(lo->lo_disk);
+
+	blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
+				  THIS_MODULE, loop_probe, NULL, NULL);
+
 	printk(KERN_INFO "loop: module loaded\n");
 	return 0;
+
+Enomem:
+	printk(KERN_INFO "loop: out of memory\n");
+
+	list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
+		loop_free(lo);
+
+	unregister_blkdev(LOOP_MAJOR, "loop");
+	return -ENOMEM;
 }
 
 static void __exit loop_exit(void)
 {
+	unsigned long range;
 	struct loop_device *lo, *next;
 
+	range = max_loop ? max_loop :  1UL << MINORBITS;
+
 	list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
 		loop_del_one(lo);
 
-	blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS);
-	if (unregister_blkdev(LOOP_MAJOR, "loop"))
-		printk(KERN_WARNING "loop: cannot unregister blkdev\n");
+	blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
+	unregister_blkdev(LOOP_MAJOR, "loop");
 }
 
 module_init(loop_init);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 069ae39..c129510 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -122,17 +122,12 @@
 	int result;
 	struct msghdr msg;
 	struct kvec iov;
-	unsigned long flags;
-	sigset_t oldset;
+	sigset_t blocked, oldset;
 
 	/* Allow interception of SIGKILL only
 	 * Don't allow other signals to interrupt the transmission */
-	spin_lock_irqsave(&current->sighand->siglock, flags);
-	oldset = current->blocked;
-	sigfillset(&current->blocked);
-	sigdelsetmask(&current->blocked, sigmask(SIGKILL));
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	siginitsetinv(&blocked, sigmask(SIGKILL));
+	sigprocmask(SIG_SETMASK, &blocked, &oldset);
 
 	do {
 		sock->sk->sk_allocation = GFP_NOIO;
@@ -151,11 +146,9 @@
 
 		if (signal_pending(current)) {
 			siginfo_t info;
-			spin_lock_irqsave(&current->sighand->siglock, flags);
 			printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
-				current->pid, current->comm, 
-				dequeue_signal(current, &current->blocked, &info));
-			spin_unlock_irqrestore(&current->sighand->siglock, flags);
+				current->pid, current->comm,
+				dequeue_signal_lock(current, &current->blocked, &info));
 			result = -EINTR;
 			break;
 		}
@@ -169,10 +162,7 @@
 		buf += result;
 	} while (size > 0);
 
-	spin_lock_irqsave(&current->sighand->siglock, flags);
-	current->blocked = oldset;
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	sigprocmask(SIG_SETMASK, &oldset, NULL);
 
 	return result;
 }
@@ -416,7 +406,7 @@
 /*
  * We always wait for result of write, for now. It would be nice to make it optional
  * in future
- * if ((req->cmd == WRITE) && (lo->flags & NBD_WRITE_NOCHK)) 
+ * if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
  *   { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
  */
 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index f1b9dd7..31be33e 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -146,8 +146,7 @@
  **********************************************************/
 
 #define DEF_ATTR(_obj,_name,_mode) \
-	static struct attribute _obj = { \
-		.name = _name, .owner = THIS_MODULE, .mode = _mode }
+	static struct attribute _obj = { .name = _name, .mode = _mode }
 
 /**********************************************************
   /sys/class/pktcdvd/pktcdvd[0-7]/
@@ -1594,6 +1593,7 @@
 	long min_sleep_time, residue;
 
 	set_user_nice(current, -20);
+	set_freezable();
 
 	for (;;) {
 		DECLARE_WAITQUEUE(wait, current);
@@ -1653,9 +1653,6 @@
 				}
 			}
 
-			if (signal_pending(current)) {
-				flush_signals(current);
-			}
 			if (kthread_should_stop())
 				break;
 		}
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
new file mode 100644
index 0000000..0f5e3ca
--- /dev/null
+++ b/drivers/block/sunvdc.c
@@ -0,0 +1,972 @@
+/* sunvdc.c: Sun LDOM Virtual Disk Client.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/list.h>
+
+#include <asm/vio.h>
+#include <asm/ldc.h>
+
+#define DRV_MODULE_NAME		"sunvdc"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"June 25, 2007"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM virtual disk client driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+#define VDC_TX_RING_SIZE	256
+
+#define WAITING_FOR_LINK_UP	0x01
+#define WAITING_FOR_TX_SPACE	0x02
+#define WAITING_FOR_GEN_CMD	0x04
+#define WAITING_FOR_ANY		-1
+
+struct vdc_req_entry {
+	struct request		*req;
+};
+
+struct vdc_port {
+	struct vio_driver_state	vio;
+
+	struct vdc		*vp;
+
+	struct gendisk		*disk;
+
+	struct vdc_completion	*cmp;
+
+	u64			req_id;
+	u64			seq;
+	struct vdc_req_entry	rq_arr[VDC_TX_RING_SIZE];
+
+	unsigned long		ring_cookies;
+
+	u64			max_xfer_size;
+	u32			vdisk_block_size;
+
+	/* The server fills these in for us in the disk attribute
+	 * ACK packet.
+	 */
+	u64			operations;
+	u32			vdisk_size;
+	u8			vdisk_type;
+	u8			dev_no;
+
+	char			disk_name[32];
+
+	struct vio_disk_geom	geom;
+	struct vio_disk_vtoc	label;
+
+	struct list_head	list;
+};
+
+static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
+{
+	return container_of(vio, struct vdc_port, vio);
+}
+
+struct vdc {
+	/* Protects prot_list.  */
+	spinlock_t		lock;
+
+	struct vio_dev		*dev;
+
+	struct list_head	port_list;
+};
+
+/* Ordered from largest major to lowest */
+static struct vio_version vdc_versions[] = {
+	{ .major = 1, .minor = 0 },
+};
+
+#define VDCBLK_NAME	"vdisk"
+static int vdc_major;
+#define PARTITION_SHIFT	3
+
+static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr)
+{
+	return vio_dring_avail(dr, VDC_TX_RING_SIZE);
+}
+
+static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+	struct gendisk *disk = bdev->bd_disk;
+	struct vdc_port *port = disk->private_data;
+
+	geo->heads = (u8) port->geom.num_hd;
+	geo->sectors = (u8) port->geom.num_sec;
+	geo->cylinders = port->geom.num_cyl;
+
+	return 0;
+}
+
+static struct block_device_operations vdc_fops = {
+	.owner		= THIS_MODULE,
+	.getgeo		= vdc_getgeo,
+};
+
+static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for)
+{
+	if (vio->cmp &&
+	    (waiting_for == -1 ||
+	     vio->cmp->waiting_for == waiting_for)) {
+		vio->cmp->err = err;
+		complete(&vio->cmp->com);
+		vio->cmp = NULL;
+	}
+}
+
+static void vdc_handshake_complete(struct vio_driver_state *vio)
+{
+	vdc_finish(vio, 0, WAITING_FOR_LINK_UP);
+}
+
+static int vdc_handle_unknown(struct vdc_port *port, void *arg)
+{
+	struct vio_msg_tag *pkt = arg;
+
+	printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+	       pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+	printk(KERN_ERR PFX "Resetting connection.\n");
+
+	ldc_disconnect(port->vio.lp);
+
+	return -ECONNRESET;
+}
+
+static int vdc_send_attr(struct vio_driver_state *vio)
+{
+	struct vdc_port *port = to_vdc_port(vio);
+	struct vio_disk_attr_info pkt;
+
+	memset(&pkt, 0, sizeof(pkt));
+
+	pkt.tag.type = VIO_TYPE_CTRL;
+	pkt.tag.stype = VIO_SUBTYPE_INFO;
+	pkt.tag.stype_env = VIO_ATTR_INFO;
+	pkt.tag.sid = vio_send_sid(vio);
+
+	pkt.xfer_mode = VIO_DRING_MODE;
+	pkt.vdisk_block_size = port->vdisk_block_size;
+	pkt.max_xfer_size = port->max_xfer_size;
+
+	viodbg(HS, "SEND ATTR xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+	       pkt.xfer_mode, pkt.vdisk_block_size, pkt.max_xfer_size);
+
+	return vio_ldc_send(&port->vio, &pkt, sizeof(pkt));
+}
+
+static int vdc_handle_attr(struct vio_driver_state *vio, void *arg)
+{
+	struct vdc_port *port = to_vdc_port(vio);
+	struct vio_disk_attr_info *pkt = arg;
+
+	viodbg(HS, "GOT ATTR stype[0x%x] ops[%lx] disk_size[%lu] disk_type[%x] "
+	       "xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+	       pkt->tag.stype, pkt->operations,
+	       pkt->vdisk_size, pkt->vdisk_type,
+	       pkt->xfer_mode, pkt->vdisk_block_size,
+	       pkt->max_xfer_size);
+
+	if (pkt->tag.stype == VIO_SUBTYPE_ACK) {
+		switch (pkt->vdisk_type) {
+		case VD_DISK_TYPE_DISK:
+		case VD_DISK_TYPE_SLICE:
+			break;
+
+		default:
+			printk(KERN_ERR PFX "%s: Bogus vdisk_type 0x%x\n",
+			       vio->name, pkt->vdisk_type);
+			return -ECONNRESET;
+		}
+
+		if (pkt->vdisk_block_size > port->vdisk_block_size) {
+			printk(KERN_ERR PFX "%s: BLOCK size increased "
+			       "%u --> %u\n",
+			       vio->name,
+			       port->vdisk_block_size, pkt->vdisk_block_size);
+			return -ECONNRESET;
+		}
+
+		port->operations = pkt->operations;
+		port->vdisk_size = pkt->vdisk_size;
+		port->vdisk_type = pkt->vdisk_type;
+		if (pkt->max_xfer_size < port->max_xfer_size)
+			port->max_xfer_size = pkt->max_xfer_size;
+		port->vdisk_block_size = pkt->vdisk_block_size;
+		return 0;
+	} else {
+		printk(KERN_ERR PFX "%s: Attribute NACK\n", vio->name);
+
+		return -ECONNRESET;
+	}
+}
+
+static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc)
+{
+	int err = desc->status;
+
+	vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
+}
+
+static void vdc_end_request(struct request *req, int uptodate, int num_sectors)
+{
+	if (end_that_request_first(req, uptodate, num_sectors))
+		return;
+	add_disk_randomness(req->rq_disk);
+	end_that_request_last(req, uptodate);
+}
+
+static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
+			unsigned int index)
+{
+	struct vio_disk_desc *desc = vio_dring_entry(dr, index);
+	struct vdc_req_entry *rqe = &port->rq_arr[index];
+	struct request *req;
+
+	if (unlikely(desc->hdr.state != VIO_DESC_DONE))
+		return;
+
+	ldc_unmap(port->vio.lp, desc->cookies, desc->ncookies);
+	desc->hdr.state = VIO_DESC_FREE;
+	dr->cons = (index + 1) & (VDC_TX_RING_SIZE - 1);
+
+	req = rqe->req;
+	if (req == NULL) {
+		vdc_end_special(port, desc);
+		return;
+	}
+
+	rqe->req = NULL;
+
+	vdc_end_request(req, !desc->status, desc->size >> 9);
+
+	if (blk_queue_stopped(port->disk->queue))
+		blk_start_queue(port->disk->queue);
+}
+
+static int vdc_ack(struct vdc_port *port, void *msgbuf)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct vio_dring_data *pkt = msgbuf;
+
+	if (unlikely(pkt->dring_ident != dr->ident ||
+		     pkt->start_idx != pkt->end_idx ||
+		     pkt->start_idx >= VDC_TX_RING_SIZE))
+		return 0;
+
+	vdc_end_one(port, dr, pkt->start_idx);
+
+	return 0;
+}
+
+static int vdc_nack(struct vdc_port *port, void *msgbuf)
+{
+	/* XXX Implement me XXX */
+	return 0;
+}
+
+static void vdc_event(void *arg, int event)
+{
+	struct vdc_port *port = arg;
+	struct vio_driver_state *vio = &port->vio;
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&vio->lock, flags);
+
+	if (unlikely(event == LDC_EVENT_RESET ||
+		     event == LDC_EVENT_UP)) {
+		vio_link_state_change(vio, event);
+		spin_unlock_irqrestore(&vio->lock, flags);
+		return;
+	}
+
+	if (unlikely(event != LDC_EVENT_DATA_READY)) {
+		printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+		spin_unlock_irqrestore(&vio->lock, flags);
+		return;
+	}
+
+	err = 0;
+	while (1) {
+		union {
+			struct vio_msg_tag tag;
+			u64 raw[8];
+		} msgbuf;
+
+		err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
+		if (unlikely(err < 0)) {
+			if (err == -ECONNRESET)
+				vio_conn_reset(vio);
+			break;
+		}
+		if (err == 0)
+			break;
+		viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
+		       msgbuf.tag.type,
+		       msgbuf.tag.stype,
+		       msgbuf.tag.stype_env,
+		       msgbuf.tag.sid);
+		err = vio_validate_sid(vio, &msgbuf.tag);
+		if (err < 0)
+			break;
+
+		if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
+			if (msgbuf.tag.stype == VIO_SUBTYPE_ACK)
+				err = vdc_ack(port, &msgbuf);
+			else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK)
+				err = vdc_nack(port, &msgbuf);
+			else
+				err = vdc_handle_unknown(port, &msgbuf);
+		} else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
+			err = vio_control_pkt_engine(vio, &msgbuf);
+		} else {
+			err = vdc_handle_unknown(port, &msgbuf);
+		}
+		if (err < 0)
+			break;
+	}
+	if (err < 0)
+		vdc_finish(&port->vio, err, WAITING_FOR_ANY);
+	spin_unlock_irqrestore(&vio->lock, flags);
+}
+
+static int __vdc_tx_trigger(struct vdc_port *port)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct vio_dring_data hdr = {
+		.tag = {
+			.type		= VIO_TYPE_DATA,
+			.stype		= VIO_SUBTYPE_INFO,
+			.stype_env	= VIO_DRING_DATA,
+			.sid		= vio_send_sid(&port->vio),
+		},
+		.dring_ident		= dr->ident,
+		.start_idx		= dr->prod,
+		.end_idx		= dr->prod,
+	};
+	int err, delay;
+
+	hdr.seq = dr->snd_nxt;
+	delay = 1;
+	do {
+		err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+		if (err > 0) {
+			dr->snd_nxt++;
+			break;
+		}
+		udelay(delay);
+		if ((delay <<= 1) > 128)
+			delay = 128;
+	} while (err == -EAGAIN);
+
+	return err;
+}
+
+static int __send_request(struct request *req)
+{
+	struct vdc_port *port = req->rq_disk->private_data;
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct scatterlist sg[port->ring_cookies];
+	struct vdc_req_entry *rqe;
+	struct vio_disk_desc *desc;
+	unsigned int map_perm;
+	int nsg, err, i;
+	u64 len;
+	u8 op;
+
+	map_perm = LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO;
+
+	if (rq_data_dir(req) == READ) {
+		map_perm |= LDC_MAP_W;
+		op = VD_OP_BREAD;
+	} else {
+		map_perm |= LDC_MAP_R;
+		op = VD_OP_BWRITE;
+	}
+
+	nsg = blk_rq_map_sg(req->q, req, sg);
+
+	len = 0;
+	for (i = 0; i < nsg; i++)
+		len += sg[i].length;
+
+	if (unlikely(vdc_tx_dring_avail(dr) < 1)) {
+		blk_stop_queue(port->disk->queue);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	desc = vio_dring_cur(dr);
+
+	err = ldc_map_sg(port->vio.lp, sg, nsg,
+			 desc->cookies, port->ring_cookies,
+			 map_perm);
+	if (err < 0) {
+		printk(KERN_ERR PFX "ldc_map_sg() failure, err=%d.\n", err);
+		return err;
+	}
+
+	rqe = &port->rq_arr[dr->prod];
+	rqe->req = req;
+
+	desc->hdr.ack = VIO_ACK_ENABLE;
+	desc->req_id = port->req_id;
+	desc->operation = op;
+	if (port->vdisk_type == VD_DISK_TYPE_DISK) {
+		desc->slice = 2;
+	} else {
+		desc->slice = 0;
+	}
+	desc->status = ~0;
+	desc->offset = (req->sector << 9) / port->vdisk_block_size;
+	desc->size = len;
+	desc->ncookies = err;
+
+	/* This has to be a non-SMP write barrier because we are writing
+	 * to memory which is shared with the peer LDOM.
+	 */
+	wmb();
+	desc->hdr.state = VIO_DESC_READY;
+
+	err = __vdc_tx_trigger(port);
+	if (err < 0) {
+		printk(KERN_ERR PFX "vdc_tx_trigger() failure, err=%d\n", err);
+	} else {
+		port->req_id++;
+		dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+	}
+out:
+
+	return err;
+}
+
+static void do_vdc_request(request_queue_t *q)
+{
+	while (1) {
+		struct request *req = elv_next_request(q);
+
+		if (!req)
+			break;
+
+		blkdev_dequeue_request(req);
+		if (__send_request(req) < 0)
+			vdc_end_request(req, 0, req->hard_nr_sectors);
+	}
+}
+
+static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
+{
+	struct vio_dring_state *dr;
+	struct vio_completion comp;
+	struct vio_disk_desc *desc;
+	unsigned int map_perm;
+	unsigned long flags;
+	int op_len, err;
+	void *req_buf;
+
+	if (!(((u64)1 << ((u64)op - 1)) & port->operations))
+		return -EOPNOTSUPP;
+
+	switch (op) {
+	case VD_OP_BREAD:
+	case VD_OP_BWRITE:
+	default:
+		return -EINVAL;
+
+	case VD_OP_FLUSH:
+		op_len = 0;
+		map_perm = 0;
+		break;
+
+	case VD_OP_GET_WCE:
+		op_len = sizeof(u32);
+		map_perm = LDC_MAP_W;
+		break;
+
+	case VD_OP_SET_WCE:
+		op_len = sizeof(u32);
+		map_perm = LDC_MAP_R;
+		break;
+
+	case VD_OP_GET_VTOC:
+		op_len = sizeof(struct vio_disk_vtoc);
+		map_perm = LDC_MAP_W;
+		break;
+
+	case VD_OP_SET_VTOC:
+		op_len = sizeof(struct vio_disk_vtoc);
+		map_perm = LDC_MAP_R;
+		break;
+
+	case VD_OP_GET_DISKGEOM:
+		op_len = sizeof(struct vio_disk_geom);
+		map_perm = LDC_MAP_W;
+		break;
+
+	case VD_OP_SET_DISKGEOM:
+		op_len = sizeof(struct vio_disk_geom);
+		map_perm = LDC_MAP_R;
+		break;
+
+	case VD_OP_SCSICMD:
+		op_len = 16;
+		map_perm = LDC_MAP_RW;
+		break;
+
+	case VD_OP_GET_DEVID:
+		op_len = sizeof(struct vio_disk_devid);
+		map_perm = LDC_MAP_W;
+		break;
+
+	case VD_OP_GET_EFI:
+	case VD_OP_SET_EFI:
+		return -EOPNOTSUPP;
+		break;
+	};
+
+	map_perm |= LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO;
+
+	op_len = (op_len + 7) & ~7;
+	req_buf = kzalloc(op_len, GFP_KERNEL);
+	if (!req_buf)
+		return -ENOMEM;
+
+	if (len > op_len)
+		len = op_len;
+
+	if (map_perm & LDC_MAP_R)
+		memcpy(req_buf, buf, len);
+
+	spin_lock_irqsave(&port->vio.lock, flags);
+
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+	/* XXX If we want to use this code generically we have to
+	 * XXX handle TX ring exhaustion etc.
+	 */
+	desc = vio_dring_cur(dr);
+
+	err = ldc_map_single(port->vio.lp, req_buf, op_len,
+			     desc->cookies, port->ring_cookies,
+			     map_perm);
+	if (err < 0) {
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+		kfree(req_buf);
+		return err;
+	}
+
+	init_completion(&comp.com);
+	comp.waiting_for = WAITING_FOR_GEN_CMD;
+	port->vio.cmp = &comp;
+
+	desc->hdr.ack = VIO_ACK_ENABLE;
+	desc->req_id = port->req_id;
+	desc->operation = op;
+	desc->slice = 0;
+	desc->status = ~0;
+	desc->offset = 0;
+	desc->size = op_len;
+	desc->ncookies = err;
+
+	/* This has to be a non-SMP write barrier because we are writing
+	 * to memory which is shared with the peer LDOM.
+	 */
+	wmb();
+	desc->hdr.state = VIO_DESC_READY;
+
+	err = __vdc_tx_trigger(port);
+	if (err >= 0) {
+		port->req_id++;
+		dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+
+		wait_for_completion(&comp.com);
+		err = comp.err;
+	} else {
+		port->vio.cmp = NULL;
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+	}
+
+	if (map_perm & LDC_MAP_W)
+		memcpy(buf, req_buf, len);
+
+	kfree(req_buf);
+
+	return err;
+}
+
+static int __devinit vdc_alloc_tx_ring(struct vdc_port *port)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	unsigned long len, entry_size;
+	int ncookies;
+	void *dring;
+
+	entry_size = sizeof(struct vio_disk_desc) +
+		(sizeof(struct ldc_trans_cookie) * port->ring_cookies);
+	len = (VDC_TX_RING_SIZE * entry_size);
+
+	ncookies = VIO_MAX_RING_COOKIES;
+	dring = ldc_alloc_exp_dring(port->vio.lp, len,
+				    dr->cookies, &ncookies,
+				    (LDC_MAP_SHADOW |
+				     LDC_MAP_DIRECT |
+				     LDC_MAP_RW));
+	if (IS_ERR(dring))
+		return PTR_ERR(dring);
+
+	dr->base = dring;
+	dr->entry_size = entry_size;
+	dr->num_entries = VDC_TX_RING_SIZE;
+	dr->prod = dr->cons = 0;
+	dr->pending = VDC_TX_RING_SIZE;
+	dr->ncookies = ncookies;
+
+	return 0;
+}
+
+static void vdc_free_tx_ring(struct vdc_port *port)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+	if (dr->base) {
+		ldc_free_exp_dring(port->vio.lp, dr->base,
+				   (dr->entry_size * dr->num_entries),
+				   dr->cookies, dr->ncookies);
+		dr->base = NULL;
+		dr->entry_size = 0;
+		dr->num_entries = 0;
+		dr->pending = 0;
+		dr->ncookies = 0;
+	}
+}
+
+static int probe_disk(struct vdc_port *port)
+{
+	struct vio_completion comp;
+	struct request_queue *q;
+	struct gendisk *g;
+	int err;
+
+	init_completion(&comp.com);
+	comp.err = 0;
+	comp.waiting_for = WAITING_FOR_LINK_UP;
+	port->vio.cmp = &comp;
+
+	vio_port_up(&port->vio);
+
+	wait_for_completion(&comp.com);
+	if (comp.err)
+		return comp.err;
+
+	err = generic_request(port, VD_OP_GET_VTOC,
+			      &port->label, sizeof(port->label));
+	if (err < 0) {
+		printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err);
+		return err;
+	}
+
+	err = generic_request(port, VD_OP_GET_DISKGEOM,
+			      &port->geom, sizeof(port->geom));
+	if (err < 0) {
+		printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
+		       "error %d\n", err);
+		return err;
+	}
+
+	port->vdisk_size = ((u64)port->geom.num_cyl *
+			    (u64)port->geom.num_hd *
+			    (u64)port->geom.num_sec);
+
+	q = blk_init_queue(do_vdc_request, &port->vio.lock);
+	if (!q) {
+		printk(KERN_ERR PFX "%s: Could not allocate queue.\n",
+		       port->vio.name);
+		return -ENOMEM;
+	}
+	g = alloc_disk(1 << PARTITION_SHIFT);
+	if (!g) {
+		printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n",
+		       port->vio.name);
+		blk_cleanup_queue(q);
+		return -ENOMEM;
+	}
+
+	port->disk = g;
+
+	blk_queue_max_hw_segments(q, port->ring_cookies);
+	blk_queue_max_phys_segments(q, port->ring_cookies);
+	blk_queue_max_sectors(q, port->max_xfer_size);
+	g->major = vdc_major;
+	g->first_minor = port->dev_no << PARTITION_SHIFT;
+	strcpy(g->disk_name, port->disk_name);
+
+	g->fops = &vdc_fops;
+	g->queue = q;
+	g->private_data = port;
+	g->driverfs_dev = &port->vio.vdev->dev;
+
+	set_capacity(g, port->vdisk_size);
+
+	printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n",
+	       g->disk_name,
+	       port->vdisk_size, (port->vdisk_size >> (20 - 9)));
+
+	add_disk(g);
+
+	return 0;
+}
+
+static struct ldc_channel_config vdc_ldc_cfg = {
+	.event		= vdc_event,
+	.mtu		= 64,
+	.mode		= LDC_MODE_UNRELIABLE,
+};
+
+static struct vio_driver_ops vdc_vio_ops = {
+	.send_attr		= vdc_send_attr,
+	.handle_attr		= vdc_handle_attr,
+	.handshake_complete	= vdc_handshake_complete,
+};
+
+static int __devinit vdc_port_probe(struct vio_dev *vdev,
+				    const struct vio_device_id *id)
+{
+	struct mdesc_handle *hp;
+	struct vdc_port *port;
+	unsigned long flags;
+	struct vdc *vp;
+	const u64 *port_id;
+	int err;
+
+	vp = dev_get_drvdata(vdev->dev.parent);
+	if (!vp) {
+		printk(KERN_ERR PFX "Cannot find port parent vdc.\n");
+		return -ENODEV;
+	}
+
+	hp = mdesc_grab();
+
+	port_id = mdesc_get_property(hp, vdev->mp, "id", NULL);
+	err = -ENODEV;
+	if (!port_id) {
+		printk(KERN_ERR PFX "Port lacks id property.\n");
+		goto err_out_release_mdesc;
+	}
+	if ((*port_id << PARTITION_SHIFT) & ~(u64)MINORMASK) {
+		printk(KERN_ERR PFX "Port id [%lu] too large.\n", *port_id);
+		goto err_out_release_mdesc;
+	}
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!port) {
+		printk(KERN_ERR PFX "Cannot allocate vdc_port.\n");
+		goto err_out_release_mdesc;
+	}
+
+	port->vp = vp;
+	port->dev_no = *port_id;
+
+	if (port->dev_no >= 26)
+		snprintf(port->disk_name, sizeof(port->disk_name),
+			 VDCBLK_NAME "%c%c",
+			 'a' + (port->dev_no / 26) - 1,
+			 'a' + (port->dev_no % 26));
+	else
+		snprintf(port->disk_name, sizeof(port->disk_name),
+			 VDCBLK_NAME "%c", 'a' + (port->dev_no % 26));
+
+	err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
+			      vdc_versions, ARRAY_SIZE(vdc_versions),
+			      &vdc_vio_ops, port->disk_name);
+	if (err)
+		goto err_out_free_port;
+
+	port->vdisk_block_size = 512;
+	port->max_xfer_size = ((128 * 1024) / port->vdisk_block_size);
+	port->ring_cookies = ((port->max_xfer_size *
+			       port->vdisk_block_size) / PAGE_SIZE) + 2;
+
+	err = vio_ldc_alloc(&port->vio, &vdc_ldc_cfg, port);
+	if (err)
+		goto err_out_free_port;
+
+	err = vdc_alloc_tx_ring(port);
+	if (err)
+		goto err_out_free_ldc;
+
+	err = probe_disk(port);
+	if (err)
+		goto err_out_free_tx_ring;
+
+	INIT_LIST_HEAD(&port->list);
+
+	spin_lock_irqsave(&vp->lock, flags);
+	list_add(&port->list, &vp->port_list);
+	spin_unlock_irqrestore(&vp->lock, flags);
+
+	dev_set_drvdata(&vdev->dev, port);
+
+	mdesc_release(hp);
+
+	return 0;
+
+err_out_free_tx_ring:
+	vdc_free_tx_ring(port);
+
+err_out_free_ldc:
+	vio_ldc_free(&port->vio);
+
+err_out_free_port:
+	kfree(port);
+
+err_out_release_mdesc:
+	mdesc_release(hp);
+	return err;
+}
+
+static int vdc_port_remove(struct vio_dev *vdev)
+{
+	struct vdc_port *port = dev_get_drvdata(&vdev->dev);
+
+	if (port) {
+		del_timer_sync(&port->vio.timer);
+
+		vdc_free_tx_ring(port);
+		vio_ldc_free(&port->vio);
+
+		dev_set_drvdata(&vdev->dev, NULL);
+
+		kfree(port);
+	}
+	return 0;
+}
+
+static struct vio_device_id vdc_port_match[] = {
+	{
+		.type = "vdc-port",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(vio, vdc_match);
+
+static struct vio_driver vdc_port_driver = {
+	.id_table	= vdc_port_match,
+	.probe		= vdc_port_probe,
+	.remove		= vdc_port_remove,
+	.driver		= {
+		.name	= "vdc_port",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __devinit vdc_probe(struct vio_dev *vdev,
+			       const struct vio_device_id *id)
+{
+	static int vdc_version_printed;
+	struct vdc *vp;
+
+	if (vdc_version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	vp = kzalloc(sizeof(struct vdc), GFP_KERNEL);
+	if (!vp)
+		return -ENOMEM;
+
+	spin_lock_init(&vp->lock);
+	vp->dev = vdev;
+	INIT_LIST_HEAD(&vp->port_list);
+
+	dev_set_drvdata(&vdev->dev, vp);
+
+	return 0;
+}
+
+static int vdc_remove(struct vio_dev *vdev)
+{
+
+	struct vdc *vp = dev_get_drvdata(&vdev->dev);
+
+	if (vp) {
+		kfree(vp);
+		dev_set_drvdata(&vdev->dev, NULL);
+	}
+	return 0;
+}
+
+static struct vio_device_id vdc_match[] = {
+	{
+		.type = "block",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(vio, vdc_match);
+
+static struct vio_driver vdc_driver = {
+	.id_table	= vdc_match,
+	.probe		= vdc_probe,
+	.remove		= vdc_remove,
+	.driver		= {
+		.name	= "vdc",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init vdc_init(void)
+{
+	int err;
+
+	err = register_blkdev(0, VDCBLK_NAME);
+	if (err < 0)
+		goto out_err;
+
+	vdc_major = err;
+	err = vio_register_driver(&vdc_driver);
+	if (err)
+		goto out_unregister_blkdev;
+
+	err = vio_register_driver(&vdc_port_driver);
+	if (err)
+		goto out_unregister_vdc;
+
+	return 0;
+
+out_unregister_vdc:
+	vio_unregister_driver(&vdc_driver);
+
+out_unregister_blkdev:
+	unregister_blkdev(vdc_major, VDCBLK_NAME);
+	vdc_major = 0;
+
+out_err:
+	return err;
+}
+
+static void __exit vdc_exit(void)
+{
+	vio_unregister_driver(&vdc_port_driver);
+	vio_unregister_driver(&vdc_driver);
+	unregister_blkdev(vdc_major, VDCBLK_NAME);
+}
+
+module_init(vdc_init);
+module_exit(vdc_exit);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 746a118..8b13d7d 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1547,10 +1547,8 @@
 #endif
 
 #if 0 /* We let them stop themselves. */
-	struct list_head *p;
 	struct ub_lun *lun;
-	list_for_each(p, &sc->luns) {
-		lun = list_entry(p, struct ub_lun, link);
+	list_for_each_entry(lun, &sc->luns, link) {
 		blk_stop_queue(lun->disk->queue);
 	}
 #endif
@@ -1562,7 +1560,6 @@
 {
 	struct ub_dev *sc = container_of(work, struct ub_dev, reset_work);
 	unsigned long flags;
-	struct list_head *p;
 	struct ub_lun *lun;
 	int lkr, rc;
 
@@ -1608,8 +1605,7 @@
 	spin_lock_irqsave(sc->lock, flags);
 	sc->reset = 0;
 	tasklet_schedule(&sc->tasklet);
-	list_for_each(p, &sc->luns) {
-		lun = list_entry(p, struct ub_lun, link);
+	list_for_each_entry(lun, &sc->luns, link) {
 		blk_start_queue(lun->disk->queue);
 	}
 	wake_up(&sc->reset_wait);
@@ -1713,7 +1709,7 @@
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	void __user *usermem = (void __user *) arg;
 
-	return scsi_cmd_ioctl(filp, disk, cmd, usermem);
+	return scsi_cmd_ioctl(filp, disk->queue, disk, cmd, usermem);
 }
 
 /*
@@ -2348,7 +2344,6 @@
 static void ub_disconnect(struct usb_interface *intf)
 {
 	struct ub_dev *sc = usb_get_intfdata(intf);
-	struct list_head *p;
 	struct ub_lun *lun;
 	unsigned long flags;
 
@@ -2403,8 +2398,7 @@
 	/*
 	 * Unregister the upper layer.
 	 */
-	list_for_each (p, &sc->luns) {
-		lun = list_entry(p, struct ub_lun, link);
+	list_for_each_entry(lun, &sc->luns, link) {
 		del_gendisk(lun->disk);
 		/*
 		 * I wish I could do:
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 6f5d620..dec74bd 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -105,12 +105,6 @@
 	unsigned long	csr_base;
 	unsigned char	__iomem *csr_remap;
 	unsigned long	csr_len;
-#ifdef CONFIG_MM_MAP_MEMORY
-	unsigned long	mem_base;
-	unsigned char	__iomem *mem_remap;
-	unsigned long	mem_len;
-#endif
-
 	unsigned int	win_size; /* PCI window size */
 	unsigned int	mm_size;  /* size in kbytes */
 
@@ -872,10 +866,6 @@
 
 	card->csr_base = pci_resource_start(dev, 0);
 	card->csr_len  = pci_resource_len(dev, 0);
-#ifdef CONFIG_MM_MAP_MEMORY
-	card->mem_base = pci_resource_start(dev, 1);
-	card->mem_len  = pci_resource_len(dev, 1);
-#endif
 
 	printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n",
 	       card->card_number, dev->bus->number, dev->devfn);
@@ -903,27 +893,6 @@
 	printk(KERN_INFO "MM%d: CSR 0x%08lx -> 0x%p (0x%lx)\n", card->card_number,
 	       card->csr_base, card->csr_remap, card->csr_len);
 
-#ifdef CONFIG_MM_MAP_MEMORY
-	if (!request_mem_region(card->mem_base, card->mem_len, "Micro Memory")) {
-		printk(KERN_ERR "MM%d: Unable to request memory region\n", card->card_number);
-		ret = -ENOMEM;
-
-		goto failed_req_mem;
-	}
-
-	if (!(card->mem_remap = ioremap(card->mem_base, cards->mem_len))) {
-		printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number);
-		ret = -ENOMEM;
-
-		goto failed_remap_mem;
-	}
-
-	printk(KERN_INFO "MM%d: MEM 0x%8lx -> 0x%8lx (0x%lx)\n", card->card_number,
-	       card->mem_base, card->mem_remap, card->mem_len);
-#else
-	printk(KERN_INFO "MM%d: MEM area not remapped (CONFIG_MM_MAP_MEMORY not set)\n",
-	       card->card_number);
-#endif
 	switch(card->dev->device) {
 	case 0x5415:
 		card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG;
@@ -1091,12 +1060,6 @@
 				    card->mm_pages[1].desc,
 				    card->mm_pages[1].page_dma);
  failed_magic:
-#ifdef CONFIG_MM_MAP_MEMORY
-	iounmap(card->mem_remap);
- failed_remap_mem:
-	release_mem_region(card->mem_base, card->mem_len);
- failed_req_mem:
-#endif
 	iounmap(card->csr_remap);
  failed_remap_csr:
 	release_mem_region(card->csr_base, card->csr_len);
@@ -1116,10 +1079,6 @@
 	tasklet_kill(&card->tasklet);
 	iounmap(card->csr_remap);
 	release_mem_region(card->csr_base, card->csr_len);
-#ifdef CONFIG_MM_MAP_MEMORY
-	iounmap(card->mem_remap);
-	release_mem_region(card->mem_base, card->mem_len);
-#endif
 	free_irq(card->irq, card);
 
 	if (card->mm_pages[0].desc)
@@ -1133,23 +1092,18 @@
 	blk_cleanup_queue(card->queue);
 }
 
-static const struct pci_device_id mm_pci_ids[] = { {
-	.vendor =	PCI_VENDOR_ID_MICRO_MEMORY,
-	.device =	PCI_DEVICE_ID_MICRO_MEMORY_5415CN,
-	}, {
-	.vendor =	PCI_VENDOR_ID_MICRO_MEMORY,
-	.device =	PCI_DEVICE_ID_MICRO_MEMORY_5425CN,
-	}, {
-	.vendor =	PCI_VENDOR_ID_MICRO_MEMORY,
-	.device =	PCI_DEVICE_ID_MICRO_MEMORY_6155,
-	}, {
+static const struct pci_device_id mm_pci_ids[] = {
+    {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5415CN)},
+    {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5425CN)},
+    {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_6155)},
+    {
 	.vendor	=	0x8086,
 	.device	=	0xB555,
 	.subvendor=	0x1332,
 	.subdevice=	0x5460,
 	.class	=	0x050000,
 	.class_mask=	0,
-	}, { /* end: all zeroes */ }
+    }, { /* end: all zeroes */ }
 };
 
 MODULE_DEVICE_TABLE(pci, mm_pci_ids);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 68592c3..dae3991 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -252,10 +252,10 @@
 	struct gendisk *disk = bdev->bd_disk;
 	struct viodasd_device *d = disk->private_data;
 
-	geo->sectors = d->sectors ? d->sectors : 0;
+	geo->sectors = d->sectors ? d->sectors : 32;
 	geo->heads = d->tracks ? d->tracks  : 64;
 	geo->cylinders = d->cylinders ? d->cylinders :
-		get_capacity(disk) / (geo->cylinders * geo->heads);
+		get_capacity(disk) / (geo->sectors * geo->heads);
 
 	return 0;
 }
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
new file mode 100644
index 0000000..732ec63
--- /dev/null
+++ b/drivers/block/xsysace.c
@@ -0,0 +1,1164 @@
+/*
+ * Xilinx SystemACE device driver
+ *
+ * Copyright 2007 Secret Lab Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+/*
+ * The SystemACE chip is designed to configure FPGAs by loading an FPGA
+ * bitstream from a file on a CF card and squirting it into FPGAs connected
+ * to the SystemACE JTAG chain.  It also has the advantage of providing an
+ * MPU interface which can be used to control the FPGA configuration process
+ * and to use the attached CF card for general purpose storage.
+ *
+ * This driver is a block device driver for the SystemACE.
+ *
+ * Initialization:
+ *    The driver registers itself as a platform_device driver at module
+ *    load time.  The platform bus will take care of calling the
+ *    ace_probe() method for all SystemACE instances in the system.  Any
+ *    number of SystemACE instances are supported.  ace_probe() calls
+ *    ace_setup() which initialized all data structures, reads the CF
+ *    id structure and registers the device.
+ *
+ * Processing:
+ *    Just about all of the heavy lifting in this driver is performed by
+ *    a Finite State Machine (FSM).  The driver needs to wait on a number
+ *    of events; some raised by interrupts, some which need to be polled
+ *    for.  Describing all of the behaviour in a FSM seems to be the
+ *    easiest way to keep the complexity low and make it easy to
+ *    understand what the driver is doing.  If the block ops or the
+ *    request function need to interact with the hardware, then they
+ *    simply need to flag the request and kick of FSM processing.
+ *
+ *    The FSM itself is atomic-safe code which can be run from any
+ *    context.  The general process flow is:
+ *    1. obtain the ace->lock spinlock.
+ *    2. loop on ace_fsm_dostate() until the ace->fsm_continue flag is
+ *       cleared.
+ *    3. release the lock.
+ *
+ *    Individual states do not sleep in any way.  If a condition needs to
+ *    be waited for then the state much clear the fsm_continue flag and
+ *    either schedule the FSM to be run again at a later time, or expect
+ *    an interrupt to call the FSM when the desired condition is met.
+ *
+ *    In normal operation, the FSM is processed at interrupt context
+ *    either when the driver's tasklet is scheduled, or when an irq is
+ *    raised by the hardware.  The tasklet can be scheduled at any time.
+ *    The request method in particular schedules the tasklet when a new
+ *    request has been indicated by the block layer.  Once started, the
+ *    FSM proceeds as far as it can processing the request until it
+ *    needs on a hardware event.  At this point, it must yield execution.
+ *
+ *    A state has two options when yielding execution:
+ *    1. ace_fsm_yield()
+ *       - Call if need to poll for event.
+ *       - clears the fsm_continue flag to exit the processing loop
+ *       - reschedules the tasklet to run again as soon as possible
+ *    2. ace_fsm_yieldirq()
+ *       - Call if an irq is expected from the HW
+ *       - clears the fsm_continue flag to exit the processing loop
+ *       - does not reschedule the tasklet so the FSM will not be processed
+ *         again until an irq is received.
+ *    After calling a yield function, the state must return control back
+ *    to the FSM main loop.
+ *
+ *    Additionally, the driver maintains a kernel timer which can process
+ *    the FSM.  If the FSM gets stalled, typically due to a missed
+ *    interrupt, then the kernel timer will expire and the driver can
+ *    continue where it left off.
+ *
+ * To Do:
+ *    - Add FPGA configuration control interface.
+ *    - Request major number from lanana
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/platform_device.h>
+
+MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
+MODULE_DESCRIPTION("Xilinx SystemACE device driver");
+MODULE_LICENSE("GPL");
+
+/* SystemACE register definitions */
+#define ACE_BUSMODE (0x00)
+
+#define ACE_STATUS (0x04)
+#define ACE_STATUS_CFGLOCK      (0x00000001)
+#define ACE_STATUS_MPULOCK      (0x00000002)
+#define ACE_STATUS_CFGERROR     (0x00000004)	/* config controller error */
+#define ACE_STATUS_CFCERROR     (0x00000008)	/* CF controller error */
+#define ACE_STATUS_CFDETECT     (0x00000010)
+#define ACE_STATUS_DATABUFRDY   (0x00000020)
+#define ACE_STATUS_DATABUFMODE  (0x00000040)
+#define ACE_STATUS_CFGDONE      (0x00000080)
+#define ACE_STATUS_RDYFORCFCMD  (0x00000100)
+#define ACE_STATUS_CFGMODEPIN   (0x00000200)
+#define ACE_STATUS_CFGADDR_MASK (0x0000e000)
+#define ACE_STATUS_CFBSY        (0x00020000)
+#define ACE_STATUS_CFRDY        (0x00040000)
+#define ACE_STATUS_CFDWF        (0x00080000)
+#define ACE_STATUS_CFDSC        (0x00100000)
+#define ACE_STATUS_CFDRQ        (0x00200000)
+#define ACE_STATUS_CFCORR       (0x00400000)
+#define ACE_STATUS_CFERR        (0x00800000)
+
+#define ACE_ERROR (0x08)
+#define ACE_CFGLBA (0x0c)
+#define ACE_MPULBA (0x10)
+
+#define ACE_SECCNTCMD (0x14)
+#define ACE_SECCNTCMD_RESET      (0x0100)
+#define ACE_SECCNTCMD_IDENTIFY   (0x0200)
+#define ACE_SECCNTCMD_READ_DATA  (0x0300)
+#define ACE_SECCNTCMD_WRITE_DATA (0x0400)
+#define ACE_SECCNTCMD_ABORT      (0x0600)
+
+#define ACE_VERSION (0x16)
+#define ACE_VERSION_REVISION_MASK (0x00FF)
+#define ACE_VERSION_MINOR_MASK    (0x0F00)
+#define ACE_VERSION_MAJOR_MASK    (0xF000)
+
+#define ACE_CTRL (0x18)
+#define ACE_CTRL_FORCELOCKREQ   (0x0001)
+#define ACE_CTRL_LOCKREQ        (0x0002)
+#define ACE_CTRL_FORCECFGADDR   (0x0004)
+#define ACE_CTRL_FORCECFGMODE   (0x0008)
+#define ACE_CTRL_CFGMODE        (0x0010)
+#define ACE_CTRL_CFGSTART       (0x0020)
+#define ACE_CTRL_CFGSEL         (0x0040)
+#define ACE_CTRL_CFGRESET       (0x0080)
+#define ACE_CTRL_DATABUFRDYIRQ  (0x0100)
+#define ACE_CTRL_ERRORIRQ       (0x0200)
+#define ACE_CTRL_CFGDONEIRQ     (0x0400)
+#define ACE_CTRL_RESETIRQ       (0x0800)
+#define ACE_CTRL_CFGPROG        (0x1000)
+#define ACE_CTRL_CFGADDR_MASK   (0xe000)
+
+#define ACE_FATSTAT (0x1c)
+
+#define ACE_NUM_MINORS 16
+#define ACE_SECTOR_SIZE (512)
+#define ACE_FIFO_SIZE (32)
+#define ACE_BUF_PER_SECTOR (ACE_SECTOR_SIZE / ACE_FIFO_SIZE)
+
+struct ace_reg_ops;
+
+struct ace_device {
+	/* driver state data */
+	int id;
+	int media_change;
+	int users;
+	struct list_head list;
+
+	/* finite state machine data */
+	struct tasklet_struct fsm_tasklet;
+	uint fsm_task;		/* Current activity (ACE_TASK_*) */
+	uint fsm_state;		/* Current state (ACE_FSM_STATE_*) */
+	uint fsm_continue_flag;	/* cleared to exit FSM mainloop */
+	uint fsm_iter_num;
+	struct timer_list stall_timer;
+
+	/* Transfer state/result, use for both id and block request */
+	struct request *req;	/* request being processed */
+	void *data_ptr;		/* pointer to I/O buffer */
+	int data_count;		/* number of buffers remaining */
+	int data_result;	/* Result of transfer; 0 := success */
+
+	int id_req_count;	/* count of id requests */
+	int id_result;
+	struct completion id_completion;	/* used when id req finishes */
+	int in_irq;
+
+	/* Details of hardware device */
+	unsigned long physaddr;
+	void *baseaddr;
+	int irq;
+	int bus_width;		/* 0 := 8 bit; 1 := 16 bit */
+	struct ace_reg_ops *reg_ops;
+	int lock_count;
+
+	/* Block device data structures */
+	spinlock_t lock;
+	struct device *dev;
+	struct request_queue *queue;
+	struct gendisk *gd;
+
+	/* Inserted CF card parameters */
+	struct hd_driveid cf_id;
+};
+
+static int ace_major;
+
+/* ---------------------------------------------------------------------
+ * Low level register access
+ */
+
+struct ace_reg_ops {
+	u16(*in) (struct ace_device * ace, int reg);
+	void (*out) (struct ace_device * ace, int reg, u16 val);
+	void (*datain) (struct ace_device * ace);
+	void (*dataout) (struct ace_device * ace);
+};
+
+/* 8 Bit bus width */
+static u16 ace_in_8(struct ace_device *ace, int reg)
+{
+	void *r = ace->baseaddr + reg;
+	return in_8(r) | (in_8(r + 1) << 8);
+}
+
+static void ace_out_8(struct ace_device *ace, int reg, u16 val)
+{
+	void *r = ace->baseaddr + reg;
+	out_8(r, val);
+	out_8(r + 1, val >> 8);
+}
+
+static void ace_datain_8(struct ace_device *ace)
+{
+	void *r = ace->baseaddr + 0x40;
+	u8 *dst = ace->data_ptr;
+	int i = ACE_FIFO_SIZE;
+	while (i--)
+		*dst++ = in_8(r++);
+	ace->data_ptr = dst;
+}
+
+static void ace_dataout_8(struct ace_device *ace)
+{
+	void *r = ace->baseaddr + 0x40;
+	u8 *src = ace->data_ptr;
+	int i = ACE_FIFO_SIZE;
+	while (i--)
+		out_8(r++, *src++);
+	ace->data_ptr = src;
+}
+
+static struct ace_reg_ops ace_reg_8_ops = {
+	.in = ace_in_8,
+	.out = ace_out_8,
+	.datain = ace_datain_8,
+	.dataout = ace_dataout_8,
+};
+
+/* 16 bit big endian bus attachment */
+static u16 ace_in_be16(struct ace_device *ace, int reg)
+{
+	return in_be16(ace->baseaddr + reg);
+}
+
+static void ace_out_be16(struct ace_device *ace, int reg, u16 val)
+{
+	out_be16(ace->baseaddr + reg, val);
+}
+
+static void ace_datain_be16(struct ace_device *ace)
+{
+	int i = ACE_FIFO_SIZE / 2;
+	u16 *dst = ace->data_ptr;
+	while (i--)
+		*dst++ = in_le16(ace->baseaddr + 0x40);
+	ace->data_ptr = dst;
+}
+
+static void ace_dataout_be16(struct ace_device *ace)
+{
+	int i = ACE_FIFO_SIZE / 2;
+	u16 *src = ace->data_ptr;
+	while (i--)
+		out_le16(ace->baseaddr + 0x40, *src++);
+	ace->data_ptr = src;
+}
+
+/* 16 bit little endian bus attachment */
+static u16 ace_in_le16(struct ace_device *ace, int reg)
+{
+	return in_le16(ace->baseaddr + reg);
+}
+
+static void ace_out_le16(struct ace_device *ace, int reg, u16 val)
+{
+	out_le16(ace->baseaddr + reg, val);
+}
+
+static void ace_datain_le16(struct ace_device *ace)
+{
+	int i = ACE_FIFO_SIZE / 2;
+	u16 *dst = ace->data_ptr;
+	while (i--)
+		*dst++ = in_be16(ace->baseaddr + 0x40);
+	ace->data_ptr = dst;
+}
+
+static void ace_dataout_le16(struct ace_device *ace)
+{
+	int i = ACE_FIFO_SIZE / 2;
+	u16 *src = ace->data_ptr;
+	while (i--)
+		out_be16(ace->baseaddr + 0x40, *src++);
+	ace->data_ptr = src;
+}
+
+static struct ace_reg_ops ace_reg_be16_ops = {
+	.in = ace_in_be16,
+	.out = ace_out_be16,
+	.datain = ace_datain_be16,
+	.dataout = ace_dataout_be16,
+};
+
+static struct ace_reg_ops ace_reg_le16_ops = {
+	.in = ace_in_le16,
+	.out = ace_out_le16,
+	.datain = ace_datain_le16,
+	.dataout = ace_dataout_le16,
+};
+
+static inline u16 ace_in(struct ace_device *ace, int reg)
+{
+	return ace->reg_ops->in(ace, reg);
+}
+
+static inline u32 ace_in32(struct ace_device *ace, int reg)
+{
+	return ace_in(ace, reg) | (ace_in(ace, reg + 2) << 16);
+}
+
+static inline void ace_out(struct ace_device *ace, int reg, u16 val)
+{
+	ace->reg_ops->out(ace, reg, val);
+}
+
+static inline void ace_out32(struct ace_device *ace, int reg, u32 val)
+{
+	ace_out(ace, reg, val);
+	ace_out(ace, reg + 2, val >> 16);
+}
+
+/* ---------------------------------------------------------------------
+ * Debug support functions
+ */
+
+#if defined(DEBUG)
+static void ace_dump_mem(void *base, int len)
+{
+	const char *ptr = base;
+	int i, j;
+
+	for (i = 0; i < len; i += 16) {
+		printk(KERN_INFO "%.8x:", i);
+		for (j = 0; j < 16; j++) {
+			if (!(j % 4))
+				printk(" ");
+			printk("%.2x", ptr[i + j]);
+		}
+		printk(" ");
+		for (j = 0; j < 16; j++)
+			printk("%c", isprint(ptr[i + j]) ? ptr[i + j] : '.');
+		printk("\n");
+	}
+}
+#else
+static inline void ace_dump_mem(void *base, int len)
+{
+}
+#endif
+
+static void ace_dump_regs(struct ace_device *ace)
+{
+	dev_info(ace->dev, "    ctrl:  %.8x  seccnt/cmd: %.4x      ver:%.4x\n"
+		 "    status:%.8x  mpu_lba:%.8x  busmode:%4x\n"
+		 "    error: %.8x  cfg_lba:%.8x  fatstat:%.4x\n",
+		 ace_in32(ace, ACE_CTRL),
+		 ace_in(ace, ACE_SECCNTCMD),
+		 ace_in(ace, ACE_VERSION),
+		 ace_in32(ace, ACE_STATUS),
+		 ace_in32(ace, ACE_MPULBA),
+		 ace_in(ace, ACE_BUSMODE),
+		 ace_in32(ace, ACE_ERROR),
+		 ace_in32(ace, ACE_CFGLBA), ace_in(ace, ACE_FATSTAT));
+}
+
+void ace_fix_driveid(struct hd_driveid *id)
+{
+#if defined(__BIG_ENDIAN)
+	u16 *buf = (void *)id;
+	int i;
+
+	/* All half words have wrong byte order; swap the bytes */
+	for (i = 0; i < sizeof(struct hd_driveid); i += 2, buf++)
+		*buf = le16_to_cpu(*buf);
+
+	/* Some of the data values are 32bit; swap the half words  */
+	id->lba_capacity = ((id->lba_capacity >> 16) & 0x0000FFFF) |
+	    ((id->lba_capacity << 16) & 0xFFFF0000);
+	id->spg = ((id->spg >> 16) & 0x0000FFFF) |
+	    ((id->spg << 16) & 0xFFFF0000);
+#endif
+}
+
+/* ---------------------------------------------------------------------
+ * Finite State Machine (FSM) implementation
+ */
+
+/* FSM tasks; used to direct state transitions */
+#define ACE_TASK_IDLE      0
+#define ACE_TASK_IDENTIFY  1
+#define ACE_TASK_READ      2
+#define ACE_TASK_WRITE     3
+#define ACE_FSM_NUM_TASKS  4
+
+/* FSM state definitions */
+#define ACE_FSM_STATE_IDLE               0
+#define ACE_FSM_STATE_REQ_LOCK           1
+#define ACE_FSM_STATE_WAIT_LOCK          2
+#define ACE_FSM_STATE_WAIT_CFREADY       3
+#define ACE_FSM_STATE_IDENTIFY_PREPARE   4
+#define ACE_FSM_STATE_IDENTIFY_TRANSFER  5
+#define ACE_FSM_STATE_IDENTIFY_COMPLETE  6
+#define ACE_FSM_STATE_REQ_PREPARE        7
+#define ACE_FSM_STATE_REQ_TRANSFER       8
+#define ACE_FSM_STATE_REQ_COMPLETE       9
+#define ACE_FSM_STATE_ERROR             10
+#define ACE_FSM_NUM_STATES              11
+
+/* Set flag to exit FSM loop and reschedule tasklet */
+static inline void ace_fsm_yield(struct ace_device *ace)
+{
+	dev_dbg(ace->dev, "ace_fsm_yield()\n");
+	tasklet_schedule(&ace->fsm_tasklet);
+	ace->fsm_continue_flag = 0;
+}
+
+/* Set flag to exit FSM loop and wait for IRQ to reschedule tasklet */
+static inline void ace_fsm_yieldirq(struct ace_device *ace)
+{
+	dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
+
+	if (ace->irq == NO_IRQ)
+		/* No IRQ assigned, so need to poll */
+		tasklet_schedule(&ace->fsm_tasklet);
+	ace->fsm_continue_flag = 0;
+}
+
+/* Get the next read/write request; ending requests that we don't handle */
+struct request *ace_get_next_request(request_queue_t * q)
+{
+	struct request *req;
+
+	while ((req = elv_next_request(q)) != NULL) {
+		if (blk_fs_request(req))
+			break;
+		end_request(req, 0);
+	}
+	return req;
+}
+
+static void ace_fsm_dostate(struct ace_device *ace)
+{
+	struct request *req;
+	u32 status;
+	u16 val;
+	int count;
+	int i;
+
+#if defined(DEBUG)
+	dev_dbg(ace->dev, "fsm_state=%i, id_req_count=%i\n",
+		ace->fsm_state, ace->id_req_count);
+#endif
+
+	switch (ace->fsm_state) {
+	case ACE_FSM_STATE_IDLE:
+		/* See if there is anything to do */
+		if (ace->id_req_count || ace_get_next_request(ace->queue)) {
+			ace->fsm_iter_num++;
+			ace->fsm_state = ACE_FSM_STATE_REQ_LOCK;
+			mod_timer(&ace->stall_timer, jiffies + HZ);
+			if (!timer_pending(&ace->stall_timer))
+				add_timer(&ace->stall_timer);
+			break;
+		}
+		del_timer(&ace->stall_timer);
+		ace->fsm_continue_flag = 0;
+		break;
+
+	case ACE_FSM_STATE_REQ_LOCK:
+		if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
+			/* Already have the lock, jump to next state */
+			ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
+			break;
+		}
+
+		/* Request the lock */
+		val = ace_in(ace, ACE_CTRL);
+		ace_out(ace, ACE_CTRL, val | ACE_CTRL_LOCKREQ);
+		ace->fsm_state = ACE_FSM_STATE_WAIT_LOCK;
+		break;
+
+	case ACE_FSM_STATE_WAIT_LOCK:
+		if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
+			/* got the lock; move to next state */
+			ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
+			break;
+		}
+
+		/* wait a bit for the lock */
+		ace_fsm_yield(ace);
+		break;
+
+	case ACE_FSM_STATE_WAIT_CFREADY:
+		status = ace_in32(ace, ACE_STATUS);
+		if (!(status & ACE_STATUS_RDYFORCFCMD) ||
+		    (status & ACE_STATUS_CFBSY)) {
+			/* CF card isn't ready; it needs to be polled */
+			ace_fsm_yield(ace);
+			break;
+		}
+
+		/* Device is ready for command; determine what to do next */
+		if (ace->id_req_count)
+			ace->fsm_state = ACE_FSM_STATE_IDENTIFY_PREPARE;
+		else
+			ace->fsm_state = ACE_FSM_STATE_REQ_PREPARE;
+		break;
+
+	case ACE_FSM_STATE_IDENTIFY_PREPARE:
+		/* Send identify command */
+		ace->fsm_task = ACE_TASK_IDENTIFY;
+		ace->data_ptr = &ace->cf_id;
+		ace->data_count = ACE_BUF_PER_SECTOR;
+		ace_out(ace, ACE_SECCNTCMD, ACE_SECCNTCMD_IDENTIFY);
+
+		/* As per datasheet, put config controller in reset */
+		val = ace_in(ace, ACE_CTRL);
+		ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
+
+		/* irq handler takes over from this point; wait for the
+		 * transfer to complete */
+		ace->fsm_state = ACE_FSM_STATE_IDENTIFY_TRANSFER;
+		ace_fsm_yieldirq(ace);
+		break;
+
+	case ACE_FSM_STATE_IDENTIFY_TRANSFER:
+		/* Check that the sysace is ready to receive data */
+		status = ace_in32(ace, ACE_STATUS);
+		if (status & ACE_STATUS_CFBSY) {
+			dev_dbg(ace->dev, "CFBSY set; t=%i iter=%i dc=%i\n",
+				ace->fsm_task, ace->fsm_iter_num,
+				ace->data_count);
+			ace_fsm_yield(ace);
+			break;
+		}
+		if (!(status & ACE_STATUS_DATABUFRDY)) {
+			ace_fsm_yield(ace);
+			break;
+		}
+
+		/* Transfer the next buffer */
+		ace->reg_ops->datain(ace);
+		ace->data_count--;
+
+		/* If there are still buffers to be transfers; jump out here */
+		if (ace->data_count != 0) {
+			ace_fsm_yieldirq(ace);
+			break;
+		}
+
+		/* transfer finished; kick state machine */
+		dev_dbg(ace->dev, "identify finished\n");
+		ace->fsm_state = ACE_FSM_STATE_IDENTIFY_COMPLETE;
+		break;
+
+	case ACE_FSM_STATE_IDENTIFY_COMPLETE:
+		ace_fix_driveid(&ace->cf_id);
+		ace_dump_mem(&ace->cf_id, 512);	/* Debug: Dump out disk ID */
+
+		if (ace->data_result) {
+			/* Error occured, disable the disk */
+			ace->media_change = 1;
+			set_capacity(ace->gd, 0);
+			dev_err(ace->dev, "error fetching CF id (%i)\n",
+				ace->data_result);
+		} else {
+			ace->media_change = 0;
+
+			/* Record disk parameters */
+			set_capacity(ace->gd, ace->cf_id.lba_capacity);
+			dev_info(ace->dev, "capacity: %i sectors\n",
+				 ace->cf_id.lba_capacity);
+		}
+
+		/* We're done, drop to IDLE state and notify waiters */
+		ace->fsm_state = ACE_FSM_STATE_IDLE;
+		ace->id_result = ace->data_result;
+		while (ace->id_req_count) {
+			complete(&ace->id_completion);
+			ace->id_req_count--;
+		}
+		break;
+
+	case ACE_FSM_STATE_REQ_PREPARE:
+		req = ace_get_next_request(ace->queue);
+		if (!req) {
+			ace->fsm_state = ACE_FSM_STATE_IDLE;
+			break;
+		}
+
+		/* Okay, it's a data request, set it up for transfer */
+		dev_dbg(ace->dev,
+			"request: sec=%lx hcnt=%lx, ccnt=%x, dir=%i\n",
+			req->sector, req->hard_nr_sectors,
+			req->current_nr_sectors, rq_data_dir(req));
+
+		ace->req = req;
+		ace->data_ptr = req->buffer;
+		ace->data_count = req->current_nr_sectors * ACE_BUF_PER_SECTOR;
+		ace_out32(ace, ACE_MPULBA, req->sector & 0x0FFFFFFF);
+
+		count = req->hard_nr_sectors;
+		if (rq_data_dir(req)) {
+			/* Kick off write request */
+			dev_dbg(ace->dev, "write data\n");
+			ace->fsm_task = ACE_TASK_WRITE;
+			ace_out(ace, ACE_SECCNTCMD,
+				count | ACE_SECCNTCMD_WRITE_DATA);
+		} else {
+			/* Kick off read request */
+			dev_dbg(ace->dev, "read data\n");
+			ace->fsm_task = ACE_TASK_READ;
+			ace_out(ace, ACE_SECCNTCMD,
+				count | ACE_SECCNTCMD_READ_DATA);
+		}
+
+		/* As per datasheet, put config controller in reset */
+		val = ace_in(ace, ACE_CTRL);
+		ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
+
+		/* Move to the transfer state.  The systemace will raise
+		 * an interrupt once there is something to do
+		 */
+		ace->fsm_state = ACE_FSM_STATE_REQ_TRANSFER;
+		if (ace->fsm_task == ACE_TASK_READ)
+			ace_fsm_yieldirq(ace);	/* wait for data ready */
+		break;
+
+	case ACE_FSM_STATE_REQ_TRANSFER:
+		/* Check that the sysace is ready to receive data */
+		status = ace_in32(ace, ACE_STATUS);
+		if (status & ACE_STATUS_CFBSY) {
+			dev_dbg(ace->dev,
+				"CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n",
+				ace->fsm_task, ace->fsm_iter_num,
+				ace->req->current_nr_sectors * 16,
+				ace->data_count, ace->in_irq);
+			ace_fsm_yield(ace);	/* need to poll CFBSY bit */
+			break;
+		}
+		if (!(status & ACE_STATUS_DATABUFRDY)) {
+			dev_dbg(ace->dev,
+				"DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n",
+				ace->fsm_task, ace->fsm_iter_num,
+				ace->req->current_nr_sectors * 16,
+				ace->data_count, ace->in_irq);
+			ace_fsm_yieldirq(ace);
+			break;
+		}
+
+		/* Transfer the next buffer */
+		i = 16;
+		if (ace->fsm_task == ACE_TASK_WRITE)
+			ace->reg_ops->dataout(ace);
+		else
+			ace->reg_ops->datain(ace);
+		ace->data_count--;
+
+		/* If there are still buffers to be transfers; jump out here */
+		if (ace->data_count != 0) {
+			ace_fsm_yieldirq(ace);
+			break;
+		}
+
+		/* bio finished; is there another one? */
+		i = ace->req->current_nr_sectors;
+		if (end_that_request_first(ace->req, 1, i)) {
+			/* dev_dbg(ace->dev, "next block; h=%li c=%i\n",
+			 *      ace->req->hard_nr_sectors,
+			 *      ace->req->current_nr_sectors);
+			 */
+			ace->data_ptr = ace->req->buffer;
+			ace->data_count = ace->req->current_nr_sectors * 16;
+			ace_fsm_yieldirq(ace);
+			break;
+		}
+
+		ace->fsm_state = ACE_FSM_STATE_REQ_COMPLETE;
+		break;
+
+	case ACE_FSM_STATE_REQ_COMPLETE:
+		/* Complete the block request */
+		blkdev_dequeue_request(ace->req);
+		end_that_request_last(ace->req, 1);
+		ace->req = NULL;
+
+		/* Finished request; go to idle state */
+		ace->fsm_state = ACE_FSM_STATE_IDLE;
+		break;
+
+	default:
+		ace->fsm_state = ACE_FSM_STATE_IDLE;
+		break;
+	}
+}
+
+static void ace_fsm_tasklet(unsigned long data)
+{
+	struct ace_device *ace = (void *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ace->lock, flags);
+
+	/* Loop over state machine until told to stop */
+	ace->fsm_continue_flag = 1;
+	while (ace->fsm_continue_flag)
+		ace_fsm_dostate(ace);
+
+	spin_unlock_irqrestore(&ace->lock, flags);
+}
+
+static void ace_stall_timer(unsigned long data)
+{
+	struct ace_device *ace = (void *)data;
+	unsigned long flags;
+
+	dev_warn(ace->dev,
+		 "kicking stalled fsm; state=%i task=%i iter=%i dc=%i\n",
+		 ace->fsm_state, ace->fsm_task, ace->fsm_iter_num,
+		 ace->data_count);
+	spin_lock_irqsave(&ace->lock, flags);
+
+	/* Rearm the stall timer *before* entering FSM (which may then
+	 * delete the timer) */
+	mod_timer(&ace->stall_timer, jiffies + HZ);
+
+	/* Loop over state machine until told to stop */
+	ace->fsm_continue_flag = 1;
+	while (ace->fsm_continue_flag)
+		ace_fsm_dostate(ace);
+
+	spin_unlock_irqrestore(&ace->lock, flags);
+}
+
+/* ---------------------------------------------------------------------
+ * Interrupt handling routines
+ */
+static int ace_interrupt_checkstate(struct ace_device *ace)
+{
+	u32 sreg = ace_in32(ace, ACE_STATUS);
+	u16 creg = ace_in(ace, ACE_CTRL);
+
+	/* Check for error occurance */
+	if ((sreg & (ACE_STATUS_CFGERROR | ACE_STATUS_CFCERROR)) &&
+	    (creg & ACE_CTRL_ERRORIRQ)) {
+		dev_err(ace->dev, "transfer failure\n");
+		ace_dump_regs(ace);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static irqreturn_t ace_interrupt(int irq, void *dev_id)
+{
+	u16 creg;
+	struct ace_device *ace = dev_id;
+
+	/* be safe and get the lock */
+	spin_lock(&ace->lock);
+	ace->in_irq = 1;
+
+	/* clear the interrupt */
+	creg = ace_in(ace, ACE_CTRL);
+	ace_out(ace, ACE_CTRL, creg | ACE_CTRL_RESETIRQ);
+	ace_out(ace, ACE_CTRL, creg);
+
+	/* check for IO failures */
+	if (ace_interrupt_checkstate(ace))
+		ace->data_result = -EIO;
+
+	if (ace->fsm_task == 0) {
+		dev_err(ace->dev,
+			"spurious irq; stat=%.8x ctrl=%.8x cmd=%.4x\n",
+			ace_in32(ace, ACE_STATUS), ace_in32(ace, ACE_CTRL),
+			ace_in(ace, ACE_SECCNTCMD));
+		dev_err(ace->dev, "fsm_task=%i fsm_state=%i data_count=%i\n",
+			ace->fsm_task, ace->fsm_state, ace->data_count);
+	}
+
+	/* Loop over state machine until told to stop */
+	ace->fsm_continue_flag = 1;
+	while (ace->fsm_continue_flag)
+		ace_fsm_dostate(ace);
+
+	/* done with interrupt; drop the lock */
+	ace->in_irq = 0;
+	spin_unlock(&ace->lock);
+
+	return IRQ_HANDLED;
+}
+
+/* ---------------------------------------------------------------------
+ * Block ops
+ */
+static void ace_request(request_queue_t * q)
+{
+	struct request *req;
+	struct ace_device *ace;
+
+	req = ace_get_next_request(q);
+
+	if (req) {
+		ace = req->rq_disk->private_data;
+		tasklet_schedule(&ace->fsm_tasklet);
+	}
+}
+
+static int ace_media_changed(struct gendisk *gd)
+{
+	struct ace_device *ace = gd->private_data;
+	dev_dbg(ace->dev, "ace_media_changed(): %i\n", ace->media_change);
+
+	return ace->media_change;
+}
+
+static int ace_revalidate_disk(struct gendisk *gd)
+{
+	struct ace_device *ace = gd->private_data;
+	unsigned long flags;
+
+	dev_dbg(ace->dev, "ace_revalidate_disk()\n");
+
+	if (ace->media_change) {
+		dev_dbg(ace->dev, "requesting cf id and scheduling tasklet\n");
+
+		spin_lock_irqsave(&ace->lock, flags);
+		ace->id_req_count++;
+		spin_unlock_irqrestore(&ace->lock, flags);
+
+		tasklet_schedule(&ace->fsm_tasklet);
+		wait_for_completion(&ace->id_completion);
+	}
+
+	dev_dbg(ace->dev, "revalidate complete\n");
+	return ace->id_result;
+}
+
+static int ace_open(struct inode *inode, struct file *filp)
+{
+	struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+	unsigned long flags;
+
+	dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
+
+	filp->private_data = ace;
+	spin_lock_irqsave(&ace->lock, flags);
+	ace->users++;
+	spin_unlock_irqrestore(&ace->lock, flags);
+
+	check_disk_change(inode->i_bdev);
+	return 0;
+}
+
+static int ace_release(struct inode *inode, struct file *filp)
+{
+	struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+	unsigned long flags;
+	u16 val;
+
+	dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
+
+	spin_lock_irqsave(&ace->lock, flags);
+	ace->users--;
+	if (ace->users == 0) {
+		val = ace_in(ace, ACE_CTRL);
+		ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
+	}
+	spin_unlock_irqrestore(&ace->lock, flags);
+	return 0;
+}
+
+static int ace_ioctl(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+{
+	struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+	struct hd_geometry __user *geo = (struct hd_geometry __user *)arg;
+	struct hd_geometry g;
+	dev_dbg(ace->dev, "ace_ioctl()\n");
+
+	switch (cmd) {
+	case HDIO_GETGEO:
+		g.heads = ace->cf_id.heads;
+		g.sectors = ace->cf_id.sectors;
+		g.cylinders = ace->cf_id.cyls;
+		g.start = 0;
+		return copy_to_user(geo, &g, sizeof(g)) ? -EFAULT : 0;
+
+	default:
+		return -ENOTTY;
+	}
+	return -ENOTTY;
+}
+
+static struct block_device_operations ace_fops = {
+	.owner = THIS_MODULE,
+	.open = ace_open,
+	.release = ace_release,
+	.media_changed = ace_media_changed,
+	.revalidate_disk = ace_revalidate_disk,
+	.ioctl = ace_ioctl,
+};
+
+/* --------------------------------------------------------------------
+ * SystemACE device setup/teardown code
+ */
+static int __devinit ace_setup(struct ace_device *ace)
+{
+	u16 version;
+	u16 val;
+
+	int rc;
+
+	spin_lock_init(&ace->lock);
+	init_completion(&ace->id_completion);
+
+	/*
+	 * Map the device
+	 */
+	ace->baseaddr = ioremap(ace->physaddr, 0x80);
+	if (!ace->baseaddr)
+		goto err_ioremap;
+
+	if (ace->irq != NO_IRQ) {
+		rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
+		if (rc) {
+			/* Failure - fall back to polled mode */
+			dev_err(ace->dev, "request_irq failed\n");
+			ace->irq = NO_IRQ;
+		}
+	}
+
+	/*
+	 * Initialize the state machine tasklet and stall timer
+	 */
+	tasklet_init(&ace->fsm_tasklet, ace_fsm_tasklet, (unsigned long)ace);
+	setup_timer(&ace->stall_timer, ace_stall_timer, (unsigned long)ace);
+
+	/*
+	 * Initialize the request queue
+	 */
+	ace->queue = blk_init_queue(ace_request, &ace->lock);
+	if (ace->queue == NULL)
+		goto err_blk_initq;
+	blk_queue_hardsect_size(ace->queue, 512);
+
+	/*
+	 * Allocate and initialize GD structure
+	 */
+	ace->gd = alloc_disk(ACE_NUM_MINORS);
+	if (!ace->gd)
+		goto err_alloc_disk;
+
+	ace->gd->major = ace_major;
+	ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
+	ace->gd->fops = &ace_fops;
+	ace->gd->queue = ace->queue;
+	ace->gd->private_data = ace;
+	snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
+
+	/* set bus width */
+	if (ace->bus_width == 1) {
+		/* 0x0101 should work regardless of endianess */
+		ace_out_le16(ace, ACE_BUSMODE, 0x0101);
+
+		/* read it back to determine endianess */
+		if (ace_in_le16(ace, ACE_BUSMODE) == 0x0001)
+			ace->reg_ops = &ace_reg_le16_ops;
+		else
+			ace->reg_ops = &ace_reg_be16_ops;
+	} else {
+		ace_out_8(ace, ACE_BUSMODE, 0x00);
+		ace->reg_ops = &ace_reg_8_ops;
+	}
+
+	/* Make sure version register is sane */
+	version = ace_in(ace, ACE_VERSION);
+	if ((version == 0) || (version == 0xFFFF))
+		goto err_read;
+
+	/* Put sysace in a sane state by clearing most control reg bits */
+	ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE |
+		ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
+
+	/* Enable interrupts */
+	val = ace_in(ace, ACE_CTRL);
+	val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ;
+	ace_out(ace, ACE_CTRL, val);
+
+	/* Print the identification */
+	dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n",
+		 (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff);
+	dev_dbg(ace->dev, "physaddr 0x%lx, mapped to 0x%p, irq=%i\n",
+		ace->physaddr, ace->baseaddr, ace->irq);
+
+	ace->media_change = 1;
+	ace_revalidate_disk(ace->gd);
+
+	/* Make the sysace device 'live' */
+	add_disk(ace->gd);
+
+	return 0;
+
+      err_read:
+	put_disk(ace->gd);
+      err_alloc_disk:
+	blk_cleanup_queue(ace->queue);
+      err_blk_initq:
+	iounmap(ace->baseaddr);
+	if (ace->irq != NO_IRQ)
+		free_irq(ace->irq, ace);
+      err_ioremap:
+	printk(KERN_INFO "xsysace: error initializing device at 0x%lx\n",
+	       ace->physaddr);
+	return -ENOMEM;
+}
+
+static void __devexit ace_teardown(struct ace_device *ace)
+{
+	if (ace->gd) {
+		del_gendisk(ace->gd);
+		put_disk(ace->gd);
+	}
+
+	if (ace->queue)
+		blk_cleanup_queue(ace->queue);
+
+	tasklet_kill(&ace->fsm_tasklet);
+
+	if (ace->irq != NO_IRQ)
+		free_irq(ace->irq, ace);
+
+	iounmap(ace->baseaddr);
+}
+
+/* ---------------------------------------------------------------------
+ * Platform Bus Support
+ */
+
+static int __devinit ace_probe(struct device *device)
+{
+	struct platform_device *dev = to_platform_device(device);
+	struct ace_device *ace;
+	int i;
+
+	dev_dbg(device, "ace_probe(%p)\n", device);
+
+	/*
+	 * Allocate the ace device structure
+	 */
+	ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL);
+	if (!ace)
+		goto err_alloc;
+
+	ace->dev = device;
+	ace->id = dev->id;
+	ace->irq = NO_IRQ;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		if (dev->resource[i].flags & IORESOURCE_MEM)
+			ace->physaddr = dev->resource[i].start;
+		if (dev->resource[i].flags & IORESOURCE_IRQ)
+			ace->irq = dev->resource[i].start;
+	}
+
+	/* FIXME: Should get bus_width from the platform_device struct */
+	ace->bus_width = 1;
+
+	dev_set_drvdata(&dev->dev, ace);
+
+	/* Call the bus-independant setup code */
+	if (ace_setup(ace) != 0)
+		goto err_setup;
+
+	return 0;
+
+      err_setup:
+	dev_set_drvdata(&dev->dev, NULL);
+	kfree(ace);
+      err_alloc:
+	printk(KERN_ERR "xsysace: could not initialize device\n");
+	return -ENOMEM;
+}
+
+/*
+ * Platform bus remove() method
+ */
+static int __devexit ace_remove(struct device *device)
+{
+	struct ace_device *ace = dev_get_drvdata(device);
+
+	dev_dbg(device, "ace_remove(%p)\n", device);
+
+	if (ace) {
+		ace_teardown(ace);
+		kfree(ace);
+	}
+
+	return 0;
+}
+
+static struct device_driver ace_driver = {
+	.name = "xsysace",
+	.bus = &platform_bus_type,
+	.probe = ace_probe,
+	.remove = __devexit_p(ace_remove),
+};
+
+/* ---------------------------------------------------------------------
+ * Module init/exit routines
+ */
+static int __init ace_init(void)
+{
+	ace_major = register_blkdev(ace_major, "xsysace");
+	if (ace_major <= 0) {
+		printk(KERN_WARNING "xsysace: register_blkdev() failed\n");
+		return ace_major;
+	}
+
+	pr_debug("Registering Xilinx SystemACE driver, major=%i\n", ace_major);
+	return driver_register(&ace_driver);
+}
+
+static void __exit ace_exit(void)
+{
+	pr_debug("Unregistering Xilinx SystemACE driver\n");
+	driver_unregister(&ace_driver);
+	unregister_blkdev(ace_major, "xsysace");
+}
+
+module_init(ace_init);
+module_exit(ace_exit);
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 7cc2685..e40fa98 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -44,9 +44,6 @@
 extern int m68k_realnum_memory;
 extern struct mem_info m68k_memory[NUM_MEMINFO];
 
-#define TRUE                  (1)
-#define FALSE                 (0)
-
 #define Z2MINOR_COMBINED      (0)
 #define Z2MINOR_Z2ONLY        (1)
 #define Z2MINOR_CHIPONLY      (2)
@@ -374,9 +371,7 @@
 {
     int i, j;
     blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256);
-    if ( unregister_blkdev( Z2RAM_MAJOR, DEVICE_NAME ) != 0 )
-	printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
-
+    unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
     del_gendisk(z2ram_gendisk);
     put_disk(z2ram_gendisk);
     blk_cleanup_queue(z2_queue);
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index b0238b4..59b0548 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -115,11 +115,11 @@
 	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 },
 
 	/* Broadcom BCM2045 */
-	{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
 
 	/* IBM/Lenovo ThinkPad with Broadcom chip */
-	{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
-	{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
 
 	/* Targus ACB10US */
 	{ USB_DEVICE(0x0a5c, 0x2100), .driver_info = HCI_RESET },
@@ -128,17 +128,17 @@
 	{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
 
 	/* HP laptop with Broadcom chip */
-	{ USB_DEVICE(0x03f0, 0x171d), .driver_info = HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x03f0, 0x171d), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
 
 	/* Dell laptop with Broadcom chip */
-	{ USB_DEVICE(0x413c, 0x8126), .driver_info = HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x413c, 0x8126), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
 
 	/* Microsoft Wireless Transceiver for Bluetooth 2.0 */
 	{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
 
 	/* Kensington Bluetooth USB adapter */
 	{ USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
-	{ USB_DEVICE(0x047d, 0x105e), .driver_info = HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x047d, 0x105e), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
 
 	/* ISSC Bluetooth Adapter v3.1 */
 	{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
@@ -148,8 +148,8 @@
 	{ USB_DEVICE(0x0400, 0x080a), .driver_info = HCI_BROKEN_ISOC },
 
 	/* Belkin F8T012 and F8T013 devices */
-	{ USB_DEVICE(0x050d, 0x0012), .driver_info = HCI_WRONG_SCO_MTU },
-	{ USB_DEVICE(0x050d, 0x0013), .driver_info = HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x050d, 0x0012), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x050d, 0x0013), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
 
 	/* Digianswer devices */
 	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
@@ -199,7 +199,6 @@
 #define __pending_q(husb, type)   (&husb->pending_q[type-1])
 #define __completed_q(husb, type) (&husb->completed_q[type-1])
 #define __transmit_q(husb, type)  (&husb->transmit_q[type-1])
-#define __reassembly(husb, type)  (husb->reassembly[type-1])
 
 static inline struct _urb *__get_completed(struct hci_usb *husb, int type)
 {
@@ -429,12 +428,6 @@
 			kfree(urb->transfer_buffer);
 			_urb_free(_urb);
 		}
-
-		/* Release reassembly buffers */
-		if (husb->reassembly[i]) {
-			kfree_skb(husb->reassembly[i]);
-			husb->reassembly[i] = NULL;
-		}
 	}
 }
 
@@ -671,83 +664,6 @@
 	return 0;
 }
 
-static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int count)
-{
-	BT_DBG("%s type %d data %p count %d", husb->hdev->name, type, data, count);
-
-	husb->hdev->stat.byte_rx += count;
-
-	while (count) {
-		struct sk_buff *skb = __reassembly(husb, type);
-		struct { int expect; } *scb;
-		int len = 0;
-	
-		if (!skb) {
-			/* Start of the frame */
-
-			switch (type) {
-			case HCI_EVENT_PKT:
-				if (count >= HCI_EVENT_HDR_SIZE) {
-					struct hci_event_hdr *h = data;
-					len = HCI_EVENT_HDR_SIZE + h->plen;
-				} else
-					return -EILSEQ;
-				break;
-
-			case HCI_ACLDATA_PKT:
-				if (count >= HCI_ACL_HDR_SIZE) {
-					struct hci_acl_hdr *h = data;
-					len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
-				} else
-					return -EILSEQ;
-				break;
-#ifdef CONFIG_BT_HCIUSB_SCO
-			case HCI_SCODATA_PKT:
-				if (count >= HCI_SCO_HDR_SIZE) {
-					struct hci_sco_hdr *h = data;
-					len = HCI_SCO_HDR_SIZE + h->dlen;
-				} else
-					return -EILSEQ;
-				break;
-#endif
-			}
-			BT_DBG("new packet len %d", len);
-
-			skb = bt_skb_alloc(len, GFP_ATOMIC);
-			if (!skb) {
-				BT_ERR("%s no memory for the packet", husb->hdev->name);
-				return -ENOMEM;
-			}
-			skb->dev = (void *) husb->hdev;
-			bt_cb(skb)->pkt_type = type;
-	
-			__reassembly(husb, type) = skb;
-
-			scb = (void *) skb->cb;
-			scb->expect = len;
-		} else {
-			/* Continuation */
-			scb = (void *) skb->cb;
-			len = scb->expect;
-		}
-
-		len = min(len, count);
-		
-		memcpy(skb_put(skb, len), data, len);
-
-		scb->expect -= len;
-		if (!scb->expect) {
-			/* Complete frame */
-			__reassembly(husb, type) = NULL;
-			bt_cb(skb)->pkt_type = type;
-			hci_recv_frame(skb);
-		}
-
-		count -= len; data += len;
-	}
-	return 0;
-}
-
 static void hci_usb_rx_complete(struct urb *urb)
 {
 	struct _urb *_urb = container_of(urb, struct _urb, urb);
@@ -776,7 +692,7 @@
 					urb->iso_frame_desc[i].actual_length);
 	
 			if (!urb->iso_frame_desc[i].status)
-				__recv_frame(husb, _urb->type, 
+				hci_recv_fragment(husb->hdev, _urb->type, 
 					urb->transfer_buffer + urb->iso_frame_desc[i].offset,
 					urb->iso_frame_desc[i].actual_length);
 		}
@@ -784,7 +700,7 @@
 		;
 #endif
 	} else {
-		err = __recv_frame(husb, _urb->type, urb->transfer_buffer, count);
+		err = hci_recv_fragment(husb->hdev, _urb->type, urb->transfer_buffer, count);
 		if (err < 0) { 
 			BT_ERR("%s corrupted packet: type %d count %d",
 					husb->hdev->name, _urb->type, count);
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
index 963fc55..56cd3a9 100644
--- a/drivers/bluetooth/hci_usb.h
+++ b/drivers/bluetooth/hci_usb.h
@@ -102,9 +102,9 @@
 	struct hci_dev		*hdev;
 
 	unsigned long		state;
-	
+
 	struct usb_device	*udev;
-	
+
 	struct usb_host_endpoint	*bulk_in_ep;
 	struct usb_host_endpoint	*bulk_out_ep;
 	struct usb_host_endpoint	*intr_in_ep;
@@ -116,7 +116,6 @@
 	__u8			ctrl_req;
 
 	struct sk_buff_head	transmit_q[4];
-	struct sk_buff		*reassembly[4];		/* Reassembly buffers */
 
 	rwlock_t		completion_lock;
 
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index b71a5cc..0638730 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -180,11 +180,6 @@
 	return total;
 }
 
-static loff_t vhci_llseek(struct file *file, loff_t offset, int origin)
-{
-	return -ESPIPE;
-}
-
 static ssize_t vhci_read(struct file *file,
 				char __user *buf, size_t count, loff_t *pos)
 {
@@ -334,7 +329,6 @@
 
 static const struct file_operations vhci_fops = {
 	.owner		= THIS_MODULE,
-	.llseek		= vhci_llseek,
 	.read		= vhci_read,
 	.write		= vhci_write,
 	.poll		= vhci_poll,
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig
deleted file mode 100644
index 4b12e90..0000000
--- a/drivers/cdrom/Kconfig
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# CDROM driver configuration
-#
-
-menu "Old CD-ROM drivers (not SCSI, not IDE)"
-	depends on ISA && BLOCK
-
-config CD_NO_IDESCSI
-	bool "Support non-SCSI/IDE/ATAPI CDROM drives"
-	---help---
-	  If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
-	  here, otherwise N. Read the CD-ROM-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  Note that the answer to this question doesn't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions about these CD-ROM drives. If you are unsure what you
-	  have, say Y and find out whether you have one of the following
-	  drives.
-
-	  For each of these drivers, a <file:Documentation/cdrom/{driver_name}>
-	  exists. Especially in cases where you do not know exactly which kind
-	  of drive you have you should read there. Most of these drivers use a
-	  file drivers/cdrom/{driver_name}.h where you can define your
-	  interface parameters and switch some internal goodies.
-
-	  To compile these CD-ROM drivers as a module, choose M instead of Y.
-
-	  If you want to use any of these CD-ROM drivers, you also have to
-	  answer Y or M to "ISO 9660 CD-ROM file system support" below (this
-	  answer will get "defaulted" for you if you enable any of the Linux
-	  CD-ROM drivers).
-
-config AZTCD
-	tristate "Aztech/Orchid/Okano/Wearnes/TXC/CyDROM  CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  This is your driver if you have an Aztech CDA268-01A, Orchid
-	  CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or
-	  CR540 CD-ROM drive.  This driver -- just like all these CD-ROM
-	  drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such
-	  as Aztech CDA269-031SE. Please read the file
-	  <file:Documentation/cdrom/aztcd>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aztcd.
-
-config GSCD
-	tristate "Goldstar R420 CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  If this is your CD-ROM drive, say Y here.  As described in the file
-	  <file:Documentation/cdrom/gscd>, you might have to change a setting
-	  in the file <file:drivers/cdrom/gscd.h> before compiling the
-	  kernel.  Please read the file <file:Documentation/cdrom/gscd>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called gscd.
-
-config SBPCD
-	tristate "Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support"
-	depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-	---help---
-	  This driver supports most of the drives which use the Panasonic or
-	  Sound Blaster interface.  Please read the file
-	  <file:Documentation/cdrom/sbpcd>.
-
-	  The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives
-	  (sometimes labeled "Creative"), the Creative Labs CD200, the
-	  Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x
-	  model), the TEAC CD-55A fall under this category.  Some other
-	  "electrically compatible" drives (Vertos, Genoa, some Funai models)
-	  are currently not supported; for the Sanyo H94A drive currently a
-	  separate driver (asked later) is responsible.  Most drives have a
-	  uniquely shaped faceplate, with a caddyless motorized drawer, but
-	  without external brand markings.  The older CR-52x drives have a
-	  caddy and manual loading/eject, but still no external markings.  The
-	  driver is able to do an extended auto-probing for interface
-	  addresses and drive types; this can help to find facts in cases you
-	  are not sure, but can consume some time during the boot process if
-	  none of the supported drives gets found.  Once your drive got found,
-	  you should enter the reported parameters into
-	  <file:drivers/cdrom/sbpcd.h> and set "DISTRIBUTION 0" there.
-
-	  This driver can support up to four CD-ROM controller cards, and each
-	  card can support up to four CD-ROM drives; if you say Y here, you
-	  will be asked how many controller cards you have.  If compiled as a
-	  module, only one controller card (but with up to four drives) is
-	  usable.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sbpcd.
-
-config MCDX
-	tristate "Mitsumi CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  Use this driver if you want to be able to use your Mitsumi LU-005,
-	  FX-001 or FX-001D CD-ROM drive.
-
-	  Please read the file <file:Documentation/cdrom/mcdx>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called mcdx.
-
-config OPTCD
-	tristate "Optics Storage DOLPHIN 8000AT CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  This is the driver for the 'DOLPHIN' drive with a 34-pin Sony
-	  compatible interface. It also works with the Lasermate CR328A. If
-	  you have one of those, say Y. This driver does not work for the
-	  Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that
-	  one. Please read the file <file:Documentation/cdrom/optcd>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called optcd.
-
-config CM206
-	tristate "Philips/LMS CM206 CDROM support"
-	depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-	---help---
-	  If you have a Philips/LMS CD-ROM drive cm206 in combination with a
-	  cm260 host adapter card, say Y here. Please also read the file
-	  <file:Documentation/cdrom/cm206>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called cm206.
-
-config SJCD
-	tristate "Sanyo CDR-H94A CDROM support"
-	depends on CD_NO_IDESCSI
-	help
-	  If this is your CD-ROM drive, say Y here and read the file
-	  <file:Documentation/cdrom/sjcd>. You should then also say Y or M to
-	  "ISO 9660 CD-ROM file system support" below, because that's the
-	  file system used on CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sjcd.
-
-config ISP16_CDI
-	tristate "ISP16/MAD16/Mozart soft configurable cdrom interface support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  These are sound cards with built-in cdrom interfaces using the OPTi
-	  82C928 or 82C929 chips. Say Y here to have them detected and
-	  possibly configured at boot time. In addition, You'll have to say Y
-	  to a driver for the particular cdrom drive you have attached to the
-	  card. Read <file:Documentation/cdrom/isp16> for details.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called isp16.
-
-config CDU31A
-	tristate "Sony CDU31A/CDU33A CDROM support"
-	depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-	---help---
-	  These CD-ROM drives have a spring-pop-out caddyless drawer, and a
-	  rectangular green LED centered beneath it.  NOTE: these CD-ROM
-	  drives will not be auto detected by the kernel at boot time; you
-	  have to provide the interface address as an option to the kernel at
-	  boot time as described in <file:Documentation/cdrom/cdu31a> or fill
-	  in your parameters into <file:drivers/cdrom/cdu31a.c>.  Try "man
-	  bootparam" or see the documentation of your boot loader (lilo or
-	  loadlin) about how to pass options to the kernel.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called cdu31a.
-
-config CDU535
-	tristate "Sony CDU535 CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM
-	  drives. Please read the file <file:Documentation/cdrom/sonycd535>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sonycd535.
-
-endmenu
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
index d1d1e5a..774c180 100644
--- a/drivers/cdrom/Makefile
+++ b/drivers/cdrom/Makefile
@@ -10,14 +10,4 @@
 obj-$(CONFIG_PARIDE_PCD)	+=		cdrom.o
 obj-$(CONFIG_CDROM_PKTCDVD)	+=		cdrom.o
 
-obj-$(CONFIG_AZTCD)		+= aztcd.o
-obj-$(CONFIG_CDU31A)		+= cdu31a.o     cdrom.o
-obj-$(CONFIG_CM206)		+= cm206.o      cdrom.o
-obj-$(CONFIG_GSCD)		+= gscd.o
-obj-$(CONFIG_ISP16_CDI)		+= isp16.o
-obj-$(CONFIG_MCDX)		+= mcdx.o       cdrom.o
-obj-$(CONFIG_OPTCD)		+= optcd.o
-obj-$(CONFIG_SBPCD)		+= sbpcd.o      cdrom.o
-obj-$(CONFIG_SJCD)		+= sjcd.o
-obj-$(CONFIG_CDU535)		+= sonycd535.o
 obj-$(CONFIG_VIOCD)		+= viocd.o      cdrom.o
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
deleted file mode 100644
index 1f9fb7a..0000000
--- a/drivers/cdrom/aztcd.c
+++ /dev/null
@@ -1,2492 +0,0 @@
-#define AZT_VERSION "2.60"
-
-/*      $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $
-	linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver
-
-	Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
-
-	based on Mitsumi CDROM driver by  Martin Hariss and preworks by
-	Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby 
-	Schirmer.
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2, or (at your option)
-	any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-	HISTORY
-	V0.0    Adaption to Aztech CD268-01A Version 1.3
-		Version is PRE_ALPHA, unresolved points:
-		1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW
-		   thus driver causes CPU overhead and is very slow 
-		2. could not find a way to stop the drive, when it is
-		   in data read mode, therefore I had to set
-		   msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one
-		   frame can be read in sequence, this is also the reason for
-		3. getting 'timeout in state 4' messages, but nevertheless
-		   it works
-		W.Zimmermann, Oct. 31, 1994
-	V0.1    Version is ALPHA, problems #2 and #3 resolved.  
-		W.Zimmermann, Nov. 3, 1994
-	V0.2    Modification to some comments, debugging aids for partial test
-		with Borland C under DOS eliminated. Timer interrupt wait 
-		STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented; 
-		use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_
-		SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy 
-		waiting seems better to me than interrupt rescheduling.
-		Besides that, when used in the wrong place, STEN_LOW_WAIT causes
-		kernel panic.
-		In function aztPlay command ACMD_PLAY_AUDIO added, should make
-		audio functions work. The Aztech drive needs different commands
-		to read data tracks and play audio tracks.
-		W.Zimmermann, Nov. 8, 1994
-	V0.3    Recognition of missing drive during boot up improved (speeded up).
-		W.Zimmermann, Nov. 13, 1994
-	V0.35   Rewrote the control mechanism in azt_poll (formerly mcd_poll) 
-		including removal of all 'goto' commands. :-); 
-		J. Nardone, Nov. 14, 1994
-	V0.4    Renamed variables and constants to 'azt' instead of 'mcd'; had
-		to make some "compatibility" defines in azt.h; please note,
-		that the source file was renamed to azt.c, the include file to
-		azt.h                
-		Speeded up drive recognition during init (will be a little bit 
-		slower than before if no drive is installed!); suggested by
-		Robby Schirmer.
-		read_count declared volatile and set to AZT_BUF_SIZ to make
-		drive faster (now 300kB/sec, was 60kB/sec before, measured
-		by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096';
-		different AZT_BUF_SIZes were test, above 16 no further im-
-		provement seems to be possible; suggested by E.Moenkeberg.
-		W.Zimmermann, Nov. 18, 1994
-	V0.42   Included getAztStatus command in GetQChannelInfo() to allow
-		reading Q-channel info on audio disks, if drive is stopped, 
-		and some other bug fixes in the audio stuff, suggested by 
-		Robby Schirmer.
-		Added more ioctls (reading data in mode 1 and mode 2).
-		Completely removed the old azt_poll() routine.
-		Detection of ORCHID CDS-3110 in aztcd_init implemented.
-		Additional debugging aids (see the readme file).
-		W.Zimmermann, Dec. 9, 1994  
-	V0.50   Autodetection of drives implemented.
-		W.Zimmermann, Dec. 12, 1994
-	V0.52   Prepared for including in the standard kernel, renamed most
-		variables to contain 'azt', included autoconf.h
-		W.Zimmermann, Dec. 16, 1994        
-	V0.6    Version for being included in the standard Linux kernel.
-		Renamed source and header file to aztcd.c and aztcd.h
-		W.Zimmermann, Dec. 24, 1994
-	V0.7    Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case
-		CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl,
-		which causes kernel crashes when playing audio, changed 
-		include-files (config.h instead of autoconf.h, removed
-		delay.h)
-		W.Zimmermann, Jan. 8, 1995
-	V0.72   Some more modifications for adaption to the standard kernel.
-		W.Zimmermann, Jan. 16, 1995
-        V0.80   aztcd is now part of the standard kernel since version 1.1.83.
-                Modified the SET_TIMER and CLEAR_TIMER macros to comply with
-                the new timer scheme.
-                W.Zimmermann, Jan. 21, 1995
-        V0.90   Included CDROMVOLCTRL, but with my Aztech drive I can only turn
-                the channels on and off. If it works better with your drive, 
-                please mail me. Also implemented ACMD_CLOSE for CDROMSTART.
-                W.Zimmermann, Jan. 24, 1995
-        V1.00   Implemented close and lock tray commands. Patches supplied by
-		Frank Racis        
-                Added support for loadable MODULEs, so aztcd can now also be
-                loaded by insmod and removed by rmmod during run time
-                Werner Zimmermann, Mar. 24, 95
-        V1.10   Implemented soundcard configuration for Orchid CDS-3110 drives
-                connected to Soundwave32 cards. Release for LST 2.1.
-                (still experimental)
-                Werner Zimmermann, May 8, 95
-        V1.20   Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but
-                sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver-
-                sion needs an update of Dosemu0.60's cdrom.c, which will come with the 
-                next revision of Dosemu.
-                Also Soundwave32 support now works.
-                Werner Zimmermann, May 22, 95
-	V1.30   Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
-	        Werner Zimmermann, July 4, 95
-	V1.40   Started multisession support. Implementation copied from mcdx.c
-	        by Heiko Schlittermann. Not tested yet.
-	        Werner Zimmermann, July 15, 95
-        V1.50   Implementation of ioctl CDROMRESET, continued multisession, began
-                XA, but still untested. Heavy modifications to drive status de-
-                tection.
-                Werner Zimmermann, July 25, 95
-        V1.60   XA support now should work. Speeded up drive recognition in cases, 
-                where no drive is installed.
-                Werner Zimmermann, August 8, 1995
-        V1.70   Multisession support now is completed, but there is still not 
-                enough testing done. If you can test it, please contact me. For
-                details please read Documentation/cdrom/aztcd
-                Werner Zimmermann, August 19, 1995
-        V1.80   Modification to suit the new kernel boot procedure introduced
-                with kernel 1.3.33. Will definitely not work with older kernels.
-                Programming done by Linus himself.
-                Werner Zimmermann, October 11, 1995
-	V1.90   Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza.
-	        Werner Zimmermann, October 21, 1995
-        V2.00   Changed #include "blk.h" to <linux/blk.h> as the directory
-                structure was changed. README.aztcd is now /usr/src/docu-
-                mentation/cdrom/aztcd
-                Werner Zimmermann, November 10, 95
-        V2.10   Started to modify azt_poll to prevent reading beyond end of
-                tracks.
-                Werner Zimmermann, December 3, 95
-        V2.20   Changed some comments
-                Werner Zimmermann, April 1, 96
-        V2.30   Implemented support for CyCDROM CR520, CR940, Code for CR520 
-        	delivered by H.Berger with preworks by E.Moenkeberg.
-                Werner Zimmermann, April 29, 96
-        V2.40   Reorganized the placement of functions in the source code file
-                to reflect the layered approach; did not actually change code
-                Werner Zimmermann, May 1, 96
-        V2.50   Heiko Eissfeldt suggested to remove some VERIFY_READs in 
-                aztcd_ioctl; check_aztcd_media_change modified 
-                Werner Zimmermann, May 16, 96       
-	V2.60   Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
-                Adaption to linux kernel > 2.1.0
-		Werner Zimmermann, Nov 29, 97
-		
-        November 1999 -- Make kernel-parameter implementation work with 2.3.x 
-	                 Removed init_module & cleanup_module in favor of 
-			 module_init & module_exit.
-			 Torben Mathiasen <tmm@image.dk>
-*/
-
-#include <linux/blkdev.h>
-#include "aztcd.h"
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/uaccess.h>
-
-/*###########################################################################
-  Defines
-  ###########################################################################
-*/
-
-#define MAJOR_NR AZTECH_CDROM_MAJOR
-#define QUEUE (azt_queue)
-#define CURRENT elv_next_request(azt_queue)
-#define SET_TIMER(func, jifs)   delay_timer.expires = jiffies + (jifs); \
-                                delay_timer.function = (void *) (func); \
-                                add_timer(&delay_timer);
-
-#define CLEAR_TIMER             del_timer(&delay_timer);
-
-#define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
-                                return value;}
-#define RETURN(message)        {printk("aztcd: Warning: %s failed\n",message);\
-                                return;}
-
-/* Macros to switch the IDE-interface to the slave device and back to the master*/
-#define SWITCH_IDE_SLAVE  outb_p(0xa0,azt_port+6); \
-	                  outb_p(0x10,azt_port+6); \
-	                  outb_p(0x00,azt_port+7); \
-	                  outb_p(0x10,azt_port+6);
-#define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
-
-
-#if 0
-#define AZT_TEST
-#define AZT_TEST1		/* <int-..> */
-#define AZT_TEST2		/* do_aztcd_request */
-#define AZT_TEST3		/* AZT_S_state */
-#define AZT_TEST4		/* QUICK_LOOP-counter */
-#define AZT_TEST5		/* port(1) state */
-#define AZT_DEBUG
-#define AZT_DEBUG_MULTISESSION
-#endif
-
-static struct request_queue *azt_queue;
-
-static int current_valid(void)
-{
-        return CURRENT &&
-		CURRENT->cmd == READ &&
-		CURRENT->sector != -1;
-}
-
-#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
-#define AZT_BUF_SIZ 16
-
-#define READ_TIMEOUT 3000
-
-#define azt_port aztcd		/*needed for the modutils */
-
-/*##########################################################################
-  Type Definitions
-  ##########################################################################
-*/
-enum azt_state_e { AZT_S_IDLE,	/* 0 */
-	AZT_S_START,		/* 1 */
-	AZT_S_MODE,		/* 2 */
-	AZT_S_READ,		/* 3 */
-	AZT_S_DATA,		/* 4 */
-	AZT_S_STOP,		/* 5 */
-	AZT_S_STOPPING		/* 6 */
-};
-enum azt_read_modes { AZT_MODE_0,	/*read mode for audio disks, not supported by Aztech firmware */
-	AZT_MODE_1,		/*read mode for normal CD-ROMs */
-	AZT_MODE_2		/*read mode for XA CD-ROMs */
-};
-
-/*##########################################################################
-  Global Variables
-  ##########################################################################
-*/
-static int aztPresent = 0;
-
-static volatile int azt_transfer_is_active = 0;
-
-static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ];	/*buffer for block size conversion */
-#if AZT_PRIVATE_IOCTLS
-static char buf[CD_FRAMESIZE_RAW];	/*separate buffer for the ioctls */
-#endif
-
-static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
-static volatile int azt_buf_in, azt_buf_out = -1;
-static volatile int azt_error = 0;
-static int azt_open_count = 0;
-static volatile enum azt_state_e azt_state = AZT_S_IDLE;
-#ifdef AZT_TEST3
-static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
-static volatile int azt_st_old = 0;
-#endif
-static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
-
-static int azt_mode = -1;
-static volatile int azt_read_count = 1;
-
-static int azt_port = AZT_BASE_ADDR;
-
-module_param(azt_port, int, 0);
-
-static int azt_port_auto[16] = AZT_BASE_AUTO;
-
-static char azt_cont = 0;
-static char azt_init_end = 0;
-static char azt_auto_eject = AZT_AUTO_EJECT;
-
-static int AztTimeout, AztTries;
-static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static DEFINE_TIMER(delay_timer, NULL, 0, 0);
-
-static struct azt_DiskInfo DiskInfo;
-static struct azt_Toc Toc[MAX_TRACKS];
-static struct azt_Play_msf azt_Play;
-
-static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-static char aztDiskChanged = 1;
-static char aztTocUpToDate = 0;
-
-static unsigned char aztIndatum;
-static unsigned long aztTimeOutCount;
-static int aztCmd = 0;
-
-static DEFINE_SPINLOCK(aztSpin);
-
-/*###########################################################################
-   Function Prototypes
-  ###########################################################################
-*/
-/* CDROM Drive Low Level I/O Functions */
-static void aztStatTimer(void);
-
-/* CDROM Drive Command Functions */
-static int aztGetDiskInfo(void);
-#if AZT_MULTISESSION
-static int aztGetMultiDiskInfo(void);
-#endif
-static int aztGetToc(int multi);
-
-/* Kernel Interface Functions */
-static int check_aztcd_media_change(struct gendisk *disk);
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-		       unsigned long arg);
-static int aztcd_open(struct inode *ip, struct file *fp);
-static int aztcd_release(struct inode *inode, struct file *file);
-
-static struct block_device_operations azt_fops = {
-	.owner		= THIS_MODULE,
-	.open		= aztcd_open,
-	.release	= aztcd_release,
-	.ioctl		= aztcd_ioctl,
-	.media_changed	= check_aztcd_media_change,
-};
-
-/* Aztcd State Machine: Controls Drive Operating State */
-static void azt_poll(void);
-
-/* Miscellaneous support functions */
-static void azt_hsg2msf(long hsg, struct msf *msf);
-static long azt_msf2hsg(struct msf *mp);
-static void azt_bin2bcd(unsigned char *p);
-static int azt_bcd2bin(unsigned char bcd);
-
-/*##########################################################################
-  CDROM Drive Low Level I/O Functions
-  ##########################################################################
-*/
-/* Macros for the drive hardware interface handshake, these macros use
-   busy waiting */
-/* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
-# define OP_OK op_ok()
-static void op_ok(void)
-{
-	aztTimeOutCount = 0;
-	do {
-		aztIndatum = inb(DATA_PORT);
-		aztTimeOutCount++;
-		if (aztTimeOutCount >= AZT_TIMEOUT) {
-			printk("aztcd: Error Wait OP_OK\n");
-			break;
-		}
-	} while (aztIndatum != AFL_OP_OK);
-}
-
-/* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
-#if 0
-# define PA_OK pa_ok()
-static void pa_ok(void)
-{
-	aztTimeOutCount = 0;
-	do {
-		aztIndatum = inb(DATA_PORT);
-		aztTimeOutCount++;
-		if (aztTimeOutCount >= AZT_TIMEOUT) {
-			printk("aztcd: Error Wait PA_OK\n");
-			break;
-		}
-	} while (aztIndatum != AFL_PA_OK);
-}
-#endif
-
-/* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
-# define STEN_LOW  sten_low()
-static void sten_low(void)
-{
-	aztTimeOutCount = 0;
-	do {
-		aztIndatum = inb(STATUS_PORT);
-		aztTimeOutCount++;
-		if (aztTimeOutCount >= AZT_TIMEOUT) {
-			if (azt_init_end)
-				printk
-				    ("aztcd: Error Wait STEN_LOW commands:%x\n",
-				     aztCmd);
-			break;
-		}
-	} while (aztIndatum & AFL_STATUS);
-}
-
-/* Wait for DTEN=Low = handshake signal 'Data available'*/
-# define DTEN_LOW dten_low()
-static void dten_low(void)
-{
-	aztTimeOutCount = 0;
-	do {
-		aztIndatum = inb(STATUS_PORT);
-		aztTimeOutCount++;
-		if (aztTimeOutCount >= AZT_TIMEOUT) {
-			printk("aztcd: Error Wait DTEN_OK\n");
-			break;
-		}
-	} while (aztIndatum & AFL_DATA);
-}
-
-/* 
- * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
- * may cause kernel panic when used in the wrong place
-*/
-#define STEN_LOW_WAIT   statusAzt()
-static void statusAzt(void)
-{
-	AztTimeout = AZT_STATUS_DELAY;
-	SET_TIMER(aztStatTimer, HZ / 100);
-	sleep_on(&azt_waitq);
-	if (AztTimeout <= 0)
-		printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",
-		       aztCmd);
-	return;
-}
-
-static void aztStatTimer(void)
-{
-	if (!(inb(STATUS_PORT) & AFL_STATUS)) {
-		wake_up(&azt_waitq);
-		return;
-	}
-	AztTimeout--;
-	if (AztTimeout <= 0) {
-		wake_up(&azt_waitq);
-		printk("aztcd: Error aztStatTimer: Timeout\n");
-		return;
-	}
-	SET_TIMER(aztStatTimer, HZ / 100);
-}
-
-/*##########################################################################
-  CDROM Drive Command Functions
-  ##########################################################################
-*/
-/* 
- * Send a single command, return -1 on error, else 0
-*/
-static int aztSendCmd(int cmd)
-{
-	unsigned char data;
-	int retry;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: Executing command %x\n", cmd);
-#endif
-
-	if ((azt_port == 0x1f0) || (azt_port == 0x170))
-		SWITCH_IDE_SLAVE;	/*switch IDE interface to slave configuration */
-
-	aztCmd = cmd;
-	outb(POLLED, MODE_PORT);
-	do {
-		if (inb(STATUS_PORT) & AFL_STATUS)
-			break;
-		inb(DATA_PORT);	/* if status left from last command, read and */
-	} while (1);		/* discard it */
-	do {
-		if (inb(STATUS_PORT) & AFL_DATA)
-			break;
-		inb(DATA_PORT);	/* if data left from last command, read and */
-	} while (1);		/* discard it */
-	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-		outb((unsigned char) cmd, CMD_PORT);
-		STEN_LOW;
-		data = inb(DATA_PORT);
-		if (data == AFL_OP_OK) {
-			return 0;
-		}		/*OP_OK? */
-		if (data == AFL_OP_ERR) {
-			STEN_LOW;
-			data = inb(DATA_PORT);
-			printk
-			    ("### Error 1 aztcd: aztSendCmd %x  Error Code %x\n",
-			     cmd, data);
-		}
-	}
-	if (retry >= AZT_RETRY_ATTEMPTS) {
-		printk("### Error 2 aztcd: aztSendCmd %x \n", cmd);
-		azt_error = 0xA5;
-	}
-	RETURNM("aztSendCmd", -1);
-}
-
-/*
- * Send a play or read command to the drive, return -1 on error, else 0
-*/
-static int sendAztCmd(int cmd, struct azt_Play_msf *params)
-{
-	unsigned char data;
-	int retry;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: play start=%02x:%02x:%02x  end=%02x:%02x:%02x\n",
-	       params->start.min, params->start.sec, params->start.frame,
-	       params->end.min, params->end.sec, params->end.frame);
-#endif
-	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-		aztSendCmd(cmd);
-		outb(params->start.min, CMD_PORT);
-		outb(params->start.sec, CMD_PORT);
-		outb(params->start.frame, CMD_PORT);
-		outb(params->end.min, CMD_PORT);
-		outb(params->end.sec, CMD_PORT);
-		outb(params->end.frame, CMD_PORT);
-		STEN_LOW;
-		data = inb(DATA_PORT);
-		if (data == AFL_PA_OK) {
-			return 0;
-		}		/*PA_OK ? */
-		if (data == AFL_PA_ERR) {
-			STEN_LOW;
-			data = inb(DATA_PORT);
-			printk
-			    ("### Error 1 aztcd: sendAztCmd %x  Error Code %x\n",
-			     cmd, data);
-		}
-	}
-	if (retry >= AZT_RETRY_ATTEMPTS) {
-		printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd);
-		azt_error = 0xA5;
-	}
-	RETURNM("sendAztCmd", -1);
-}
-
-/*
- * Send a seek command to the drive, return -1 on error, else 0
-*/
-static int aztSeek(struct azt_Play_msf *params)
-{
-	unsigned char data;
-	int retry;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: aztSeek %02x:%02x:%02x\n",
-	       params->start.min, params->start.sec, params->start.frame);
-#endif
-	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-		aztSendCmd(ACMD_SEEK);
-		outb(params->start.min, CMD_PORT);
-		outb(params->start.sec, CMD_PORT);
-		outb(params->start.frame, CMD_PORT);
-		STEN_LOW;
-		data = inb(DATA_PORT);
-		if (data == AFL_PA_OK) {
-			return 0;
-		}		/*PA_OK ? */
-		if (data == AFL_PA_ERR) {
-			STEN_LOW;
-			data = inb(DATA_PORT);
-			printk("### Error 1 aztcd: aztSeek\n");
-		}
-	}
-	if (retry >= AZT_RETRY_ATTEMPTS) {
-		printk("### Error 2 aztcd: aztSeek\n ");
-		azt_error = 0xA5;
-	}
-	RETURNM("aztSeek", -1);
-}
-
-/* Send a Set Disk Type command
-   does not seem to work with Aztech drives, behavior is completely indepen-
-   dent on which mode is set ???
-*/
-static int aztSetDiskType(int type)
-{
-	unsigned char data;
-	int retry;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: set disk type command: type= %i\n", type);
-#endif
-	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-		aztSendCmd(ACMD_SET_DISK_TYPE);
-		outb(type, CMD_PORT);
-		STEN_LOW;
-		data = inb(DATA_PORT);
-		if (data == AFL_PA_OK) {	/*PA_OK ? */
-			azt_read_mode = type;
-			return 0;
-		}
-		if (data == AFL_PA_ERR) {
-			STEN_LOW;
-			data = inb(DATA_PORT);
-			printk
-			    ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",
-			     type, data);
-		}
-	}
-	if (retry >= AZT_RETRY_ATTEMPTS) {
-		printk("### Error 2 aztcd: aztSetDiskType %x\n ", type);
-		azt_error = 0xA5;
-	}
-	RETURNM("aztSetDiskType", -1);
-}
-
-
-/* used in azt_poll to poll the status, expects another program to issue a 
- * ACMD_GET_STATUS directly before 
- */
-static int aztStatus(void)
-{
-	int st;
-/*	int i;
-
-	i = inb(STATUS_PORT) & AFL_STATUS;    is STEN=0?    ???
-	if (!i)
-*/ STEN_LOW;
-	if (aztTimeOutCount < AZT_TIMEOUT) {
-		st = inb(DATA_PORT) & 0xFF;
-		return st;
-	} else
-		RETURNM("aztStatus", -1);
-}
-
-/*
- * Get the drive status
- */
-static int getAztStatus(void)
-{
-	int st;
-
-	if (aztSendCmd(ACMD_GET_STATUS))
-		RETURNM("getAztStatus 1", -1);
-	STEN_LOW;
-	st = inb(DATA_PORT) & 0xFF;
-#ifdef AZT_DEBUG
-	printk("aztcd: Status = %x\n", st);
-#endif
-	if ((st == 0xFF) || (st & AST_CMD_CHECK)) {
-		printk
-		    ("aztcd: AST_CMD_CHECK error or no status available\n");
-		return -1;
-	}
-
-	if (((st & AST_MODE_BITS) != AST_BUSY)
-	    && (aztAudioStatus == CDROM_AUDIO_PLAY))
-		/* XXX might be an error? look at q-channel? */
-		aztAudioStatus = CDROM_AUDIO_COMPLETED;
-
-	if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) {
-		aztDiskChanged = 1;
-		aztTocUpToDate = 0;
-		aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-	}
-	return st;
-}
-
-
-/*
- * Send a 'Play' command and get the status.  Use only from the top half.
- */
-static int aztPlay(struct azt_Play_msf *arg)
-{
-	if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0)
-		RETURNM("aztPlay", -1);
-	return 0;
-}
-
-/*
- * Subroutines to automatically close the door (tray) and 
- * lock it closed when the cd is mounted.  Leave the tray
- * locking as an option
- */
-static void aztCloseDoor(void)
-{
-	aztSendCmd(ACMD_CLOSE);
-	STEN_LOW;
-	return;
-}
-
-static void aztLockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
-	aztSendCmd(ACMD_LOCK);
-	STEN_LOW;
-#endif
-	return;
-}
-
-static void aztUnlockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
-	aztSendCmd(ACMD_UNLOCK);
-	STEN_LOW;
-#endif
-	return;
-}
-
-/*
- * Read a value from the drive.  Should return quickly, so a busy wait
- * is used to avoid excessive rescheduling. The read command itself must
- * be issued with aztSendCmd() directly before
- */
-static int aztGetValue(unsigned char *result)
-{
-	int s;
-
-	STEN_LOW;
-	if (aztTimeOutCount >= AZT_TIMEOUT) {
-		printk("aztcd: aztGetValue timeout\n");
-		return -1;
-	}
-	s = inb(DATA_PORT) & 0xFF;
-	*result = (unsigned char) s;
-	return 0;
-}
-
-/*
- * Read the current Q-channel info.  Also used for reading the
- * table of contents.
- */
-static int aztGetQChannelInfo(struct azt_Toc *qp)
-{
-	unsigned char notUsed;
-	int st;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetQChannelInfo  Time:%li\n", jiffies);
-#endif
-	if ((st = getAztStatus()) == -1)
-		RETURNM("aztGetQChannelInfo 1", -1);
-	if (aztSendCmd(ACMD_GET_Q_CHANNEL))
-		RETURNM("aztGetQChannelInfo 2", -1);
-	/*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */
-	if (aztGetValue(&notUsed))
-		RETURNM("aztGetQChannelInfo 3", -1);	/*??? Nullbyte einlesen */
-	if ((st & AST_MODE_BITS) == AST_INITIAL) {
-		qp->ctrl_addr = 0;	/* when audio stop ACMD_GET_Q_CHANNEL returns */
-		qp->track = 0;	/* only one byte with Aztech drives */
-		qp->pointIndex = 0;
-		qp->trackTime.min = 0;
-		qp->trackTime.sec = 0;
-		qp->trackTime.frame = 0;
-		qp->diskTime.min = 0;
-		qp->diskTime.sec = 0;
-		qp->diskTime.frame = 0;
-		return 0;
-	} else {
-		if (aztGetValue(&qp->ctrl_addr) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->track) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->pointIndex) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->trackTime.min) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->trackTime.sec) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->trackTime.frame) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&notUsed) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->diskTime.min) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->diskTime.sec) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->diskTime.frame) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-	}
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztGetQChannelInfo  Time:%li\n", jiffies);
-#endif
-	return 0;
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary
- */
-static int aztUpdateToc(void)
-{
-	int st;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztUpdateToc  Time:%li\n", jiffies);
-#endif
-	if (aztTocUpToDate)
-		return 0;
-
-	if (aztGetDiskInfo() < 0)
-		return -EIO;
-
-	if (aztGetToc(0) < 0)
-		return -EIO;
-
-	/*audio disk detection
-	   with my Aztech drive there is no audio status bit, so I use the copy
-	   protection bit of the first track. If this track is copy protected 
-	   (copy bit = 0), I assume, it's an audio  disk. Strange, but works ??? */
-	if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
-		DiskInfo.audio = 1;
-	else
-		DiskInfo.audio = 0;
-
-	/* XA detection */
-	if (!DiskInfo.audio) {
-		azt_Play.start.min = 0;	/*XA detection only seems to work */
-		azt_Play.start.sec = 2;	/*when we play a track */
-		azt_Play.start.frame = 0;
-		azt_Play.end.min = 0;
-		azt_Play.end.sec = 0;
-		azt_Play.end.frame = 1;
-		if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
-			return -1;
-		DTEN_LOW;
-		for (st = 0; st < CD_FRAMESIZE; st++)
-			inb(DATA_PORT);
-	}
-	DiskInfo.xa = getAztStatus() & AST_MODE;
-	if (DiskInfo.xa) {
-		printk
-		    ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
-	}
-
-	/*multisession detection
-	   support for multisession CDs is done automatically with Aztech drives,
-	   we don't have to take care about TOC redirection; if we want the isofs
-	   to take care about redirection, we have to set AZT_MULTISESSION to 1 */
-	DiskInfo.multi = 0;
-#if AZT_MULTISESSION
-	if (DiskInfo.xa) {
-		aztGetMultiDiskInfo();	/*here Disk.Info.multi is set */
-	}
-#endif
-	if (DiskInfo.multi) {
-		DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
-		DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
-		DiskInfo.lastSession.frame =
-		    Toc[DiskInfo.next].diskTime.frame;
-		printk("aztcd: Multisession support experimental\n");
-	} else {
-		DiskInfo.lastSession.min =
-		    Toc[DiskInfo.first].diskTime.min;
-		DiskInfo.lastSession.sec =
-		    Toc[DiskInfo.first].diskTime.sec;
-		DiskInfo.lastSession.frame =
-		    Toc[DiskInfo.first].diskTime.frame;
-	}
-
-	aztTocUpToDate = 1;
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztUpdateToc  Time:%li\n", jiffies);
-#endif
-	return 0;
-}
-
-
-/* Read the table of contents header, i.e. no. of tracks and start of first 
- * track
- */
-static int aztGetDiskInfo(void)
-{
-	int limit;
-	unsigned char test;
-	struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetDiskInfo  Time:%li\n", jiffies);
-#endif
-	if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
-		RETURNM("aztGetDiskInfo 1", -1);
-	STEN_LOW_WAIT;
-	test = 0;
-	for (limit = 300; limit > 0; limit--) {
-		if (aztGetQChannelInfo(&qInfo) < 0)
-			RETURNM("aztGetDiskInfo 2", -1);
-		if (qInfo.pointIndex == 0xA0) {	/*Number of FirstTrack */
-			DiskInfo.first = qInfo.diskTime.min;
-			DiskInfo.first = azt_bcd2bin(DiskInfo.first);
-			test = test | 0x01;
-		}
-		if (qInfo.pointIndex == 0xA1) {	/*Number of LastTrack */
-			DiskInfo.last = qInfo.diskTime.min;
-			DiskInfo.last = azt_bcd2bin(DiskInfo.last);
-			test = test | 0x02;
-		}
-		if (qInfo.pointIndex == 0xA2) {	/*DiskLength */
-			DiskInfo.diskLength.min = qInfo.diskTime.min;
-			DiskInfo.diskLength.sec = qInfo.diskTime.sec;
-			DiskInfo.diskLength.frame = qInfo.diskTime.frame;
-			test = test | 0x04;
-		}
-		if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) {	/*StartTime of First Track */
-			DiskInfo.firstTrack.min = qInfo.diskTime.min;
-			DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
-			DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
-			test = test | 0x08;
-		}
-		if (test == 0x0F)
-			break;
-	}
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztGetDiskInfo  Time:%li\n", jiffies);
-	printk
-	    ("Disk Info: first %d last %d length %02X:%02X.%02X dez  first %02X:%02X.%02X dez\n",
-	     DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
-	     DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
-	     DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
-	     DiskInfo.firstTrack.frame);
-#endif
-	if (test != 0x0F)
-		return -1;
-	return 0;
-}
-
-#if AZT_MULTISESSION
-/*
- * Get Multisession Disk Info
- */
-static int aztGetMultiDiskInfo(void)
-{
-	int limit, k = 5;
-	unsigned char test;
-	struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetMultiDiskInfo\n");
-#endif
-
-	do {
-		azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min;
-		azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec;
-		azt_Play.start.frame =
-		    Toc[DiskInfo.last + 1].diskTime.frame;
-		test = 0;
-
-		for (limit = 30; limit > 0; limit--) {	/*Seek for LeadIn of next session */
-			if (aztSeek(&azt_Play))
-				RETURNM("aztGetMultiDiskInfo 1", -1);
-			if (aztGetQChannelInfo(&qInfo) < 0)
-				RETURNM("aztGetMultiDiskInfo 2", -1);
-			if ((qInfo.track == 0) && (qInfo.pointIndex))
-				break;	/*LeadIn found */
-			if ((azt_Play.start.sec += 10) > 59) {
-				azt_Play.start.sec = 0;
-				azt_Play.start.min++;
-			}
-		}
-		if (!limit)
-			break;	/*Check, if a leadin track was found, if not we're
-				   at the end of the disk */
-#ifdef AZT_DEBUG_MULTISESSION
-		printk("leadin found track %d  pointIndex %x  limit %d\n",
-		       qInfo.track, qInfo.pointIndex, limit);
-#endif
-		for (limit = 300; limit > 0; limit--) {
-			if (++azt_Play.start.frame > 74) {
-				azt_Play.start.frame = 0;
-				if (azt_Play.start.sec > 59) {
-					azt_Play.start.sec = 0;
-					azt_Play.start.min++;
-				}
-			}
-			if (aztSeek(&azt_Play))
-				RETURNM("aztGetMultiDiskInfo 3", -1);
-			if (aztGetQChannelInfo(&qInfo) < 0)
-				RETURNM("aztGetMultiDiskInfo 4", -1);
-			if (qInfo.pointIndex == 0xA0) {	/*Number of NextTrack */
-				DiskInfo.next = qInfo.diskTime.min;
-				DiskInfo.next = azt_bcd2bin(DiskInfo.next);
-				test = test | 0x01;
-			}
-			if (qInfo.pointIndex == 0xA1) {	/*Number of LastTrack */
-				DiskInfo.last = qInfo.diskTime.min;
-				DiskInfo.last = azt_bcd2bin(DiskInfo.last);
-				test = test | 0x02;
-			}
-			if (qInfo.pointIndex == 0xA2) {	/*DiskLength */
-				DiskInfo.diskLength.min =
-				    qInfo.diskTime.min;
-				DiskInfo.diskLength.sec =
-				    qInfo.diskTime.sec;
-				DiskInfo.diskLength.frame =
-				    qInfo.diskTime.frame;
-				test = test | 0x04;
-			}
-			if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) {	/*StartTime of Next Track */
-				DiskInfo.nextSession.min =
-				    qInfo.diskTime.min;
-				DiskInfo.nextSession.sec =
-				    qInfo.diskTime.sec;
-				DiskInfo.nextSession.frame =
-				    qInfo.diskTime.frame;
-				test = test | 0x08;
-			}
-			if (test == 0x0F)
-				break;
-		}
-#ifdef AZT_DEBUG_MULTISESSION
-		printk
-		    ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez  first %02x:%02x.%02x dez  next %02x:%02x.%02x dez\n",
-		     DiskInfo.first, DiskInfo.next, DiskInfo.last,
-		     DiskInfo.diskLength.min, DiskInfo.diskLength.sec,
-		     DiskInfo.diskLength.frame, DiskInfo.firstTrack.min,
-		     DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame,
-		     DiskInfo.nextSession.min, DiskInfo.nextSession.sec,
-		     DiskInfo.nextSession.frame);
-#endif
-		if (test != 0x0F)
-			break;
-		else
-			DiskInfo.multi = 1;	/*found TOC of more than one session */
-		aztGetToc(1);
-	} while (--k);
-
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztGetMultiDiskInfo  Time:%li\n", jiffies);
-#endif
-	return 0;
-}
-#endif
-
-/*
- * Read the table of contents (TOC)
- */
-static int aztGetToc(int multi)
-{
-	int i, px;
-	int limit;
-	struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetToc  Time:%li\n", jiffies);
-#endif
-	if (!multi) {
-		for (i = 0; i < MAX_TRACKS; i++)
-			Toc[i].pointIndex = 0;
-		i = DiskInfo.last + 3;
-	} else {
-		for (i = DiskInfo.next; i < MAX_TRACKS; i++)
-			Toc[i].pointIndex = 0;
-		i = DiskInfo.last + 4 - DiskInfo.next;
-	}
-
-/*Is there a good reason to stop motor before TOC read?
-  if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
-      STEN_LOW_WAIT;
-*/
-
-	if (!multi) {
-		azt_mode = 0x05;
-		if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
-			RETURNM("aztGetToc 2", -1);
-		STEN_LOW_WAIT;
-	}
-	for (limit = 300; limit > 0; limit--) {
-		if (multi) {
-			if (++azt_Play.start.sec > 59) {
-				azt_Play.start.sec = 0;
-				azt_Play.start.min++;
-			}
-			if (aztSeek(&azt_Play))
-				RETURNM("aztGetToc 3", -1);
-		}
-		if (aztGetQChannelInfo(&qInfo) < 0)
-			break;
-
-		px = azt_bcd2bin(qInfo.pointIndex);
-
-		if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
-			if (Toc[px].pointIndex == 0) {
-				Toc[px] = qInfo;
-				i--;
-			}
-
-		if (i <= 0)
-			break;
-	}
-
-	Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
-	Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
-
-#ifdef AZT_DEBUG_MULTISESSION
-	printk("aztcd: exiting aztGetToc\n");
-	for (i = 1; i <= DiskInfo.last + 1; i++)
-		printk
-		    ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez  %02X:%02X.%02X dez\n",
-		     i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
-		     Toc[i].trackTime.min, Toc[i].trackTime.sec,
-		     Toc[i].trackTime.frame, Toc[i].diskTime.min,
-		     Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-	for (i = 100; i < 103; i++)
-		printk
-		    ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez  %02X:%02X.%02X dez\n",
-		     i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
-		     Toc[i].trackTime.min, Toc[i].trackTime.sec,
-		     Toc[i].trackTime.frame, Toc[i].diskTime.min,
-		     Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-#endif
-
-	return limit > 0 ? 0 : -1;
-}
-
-
-/*##########################################################################
-  Kernel Interface Functions
-  ##########################################################################
-*/
-
-#ifndef MODULE
-static int __init aztcd_setup(char *str)
-{
-	int ints[4];
-
-	(void) get_options(str, ARRAY_SIZE(ints), ints);
-
-	if (ints[0] > 0)
-		azt_port = ints[1];
-	if (ints[1] > 1)
-		azt_cont = ints[2];
-	return 1;
-}
-
-__setup("aztcd=", aztcd_setup);
-
-#endif				/* !MODULE */
-
-/* 
- * Checking if the media has been changed
-*/
-static int check_aztcd_media_change(struct gendisk *disk)
-{
-	if (aztDiskChanged) {	/* disk changed */
-		aztDiskChanged = 0;
-		return 1;
-	} else
-		return 0;	/* no change */
-}
-
-/*
- * Kernel IO-controls
-*/
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-		       unsigned long arg)
-{
-	int i;
-	struct azt_Toc qInfo;
-	struct cdrom_ti ti;
-	struct cdrom_tochdr tocHdr;
-	struct cdrom_msf msf;
-	struct cdrom_tocentry entry;
-	struct azt_Toc *tocPtr;
-	struct cdrom_subchnl subchnl;
-	struct cdrom_volctrl volctrl;
-	void __user *argp = (void __user *)arg;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztcd_ioctl - Command:%x   Time: %li\n",
-	       cmd, jiffies);
-	printk("aztcd Status %x\n", getAztStatus());
-#endif
-	if (!ip)
-		RETURNM("aztcd_ioctl 1", -EINVAL);
-	if (getAztStatus() < 0)
-		RETURNM("aztcd_ioctl 2", -EIO);
-	if ((!aztTocUpToDate) || (aztDiskChanged)) {
-		if ((i = aztUpdateToc()) < 0)
-			RETURNM("aztcd_ioctl 3", i);	/* error reading TOC */
-	}
-
-	switch (cmd) {
-	case CDROMSTART:	/* Spin up the drive. Don't know, what to do,
-				   at least close the tray */
-#if AZT_PRIVATE_IOCTLS
-		if (aztSendCmd(ACMD_CLOSE))
-			RETURNM("aztcd_ioctl 4", -1);
-		STEN_LOW_WAIT;
-#endif
-		break;
-	case CDROMSTOP:	/* Spin down the drive */
-		if (aztSendCmd(ACMD_STOP))
-			RETURNM("aztcd_ioctl 5", -1);
-		STEN_LOW_WAIT;
-		/* should we do anything if it fails? */
-		aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-		break;
-	case CDROMPAUSE:	/* Pause the drive */
-		if (aztAudioStatus != CDROM_AUDIO_PLAY)
-			return -EINVAL;
-
-		if (aztGetQChannelInfo(&qInfo) < 0) {	/* didn't get q channel info */
-			aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-			RETURNM("aztcd_ioctl 7", 0);
-		}
-		azt_Play.start = qInfo.diskTime;	/* remember restart point */
-
-		if (aztSendCmd(ACMD_PAUSE))
-			RETURNM("aztcd_ioctl 8", -1);
-		STEN_LOW_WAIT;
-		aztAudioStatus = CDROM_AUDIO_PAUSED;
-		break;
-	case CDROMRESUME:	/* Play it again, Sam */
-		if (aztAudioStatus != CDROM_AUDIO_PAUSED)
-			return -EINVAL;
-		/* restart the drive at the saved position. */
-		i = aztPlay(&azt_Play);
-		if (i < 0) {
-			aztAudioStatus = CDROM_AUDIO_ERROR;
-			return -EIO;
-		}
-		aztAudioStatus = CDROM_AUDIO_PLAY;
-		break;
-	case CDROMMULTISESSION:	/*multisession support -- experimental */
-		{
-			struct cdrom_multisession ms;
-#ifdef AZT_DEBUG
-			printk("aztcd ioctl MULTISESSION\n");
-#endif
-			if (copy_from_user(&ms, argp,
-			     sizeof(struct cdrom_multisession)))
-				return -EFAULT;
-			if (ms.addr_format == CDROM_MSF) {
-				ms.addr.msf.minute =
-				    azt_bcd2bin(DiskInfo.lastSession.min);
-				ms.addr.msf.second =
-				    azt_bcd2bin(DiskInfo.lastSession.sec);
-				ms.addr.msf.frame =
-				    azt_bcd2bin(DiskInfo.lastSession.
-						frame);
-			} else if (ms.addr_format == CDROM_LBA)
-				ms.addr.lba =
-				    azt_msf2hsg(&DiskInfo.lastSession);
-			else
-				return -EINVAL;
-			ms.xa_flag = DiskInfo.xa;
-			if (copy_to_user(argp, &ms,
-			     sizeof(struct cdrom_multisession)))
-				return -EFAULT;
-#ifdef AZT_DEBUG
-			if (ms.addr_format == CDROM_MSF)
-				printk
-				    ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
-				     ms.xa_flag, ms.addr.msf.minute,
-				     ms.addr.msf.second, ms.addr.msf.frame,
-				     DiskInfo.lastSession.min,
-				     DiskInfo.lastSession.sec,
-				     DiskInfo.lastSession.frame);
-			else
-				printk
-				    ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
-				     ms.xa_flag, ms.addr.lba,
-				     DiskInfo.lastSession.min,
-				     DiskInfo.lastSession.sec,
-				     DiskInfo.lastSession.frame);
-#endif
-			return 0;
-		}
-	case CDROMPLAYTRKIND:	/* Play a track.  This currently ignores index. */
-		if (copy_from_user(&ti, argp, sizeof ti))
-			return -EFAULT;
-		if (ti.cdti_trk0 < DiskInfo.first
-		    || ti.cdti_trk0 > DiskInfo.last
-		    || ti.cdti_trk1 < ti.cdti_trk0) {
-			return -EINVAL;
-		}
-		if (ti.cdti_trk1 > DiskInfo.last)
-			ti.cdti_trk1 = DiskInfo.last;
-		azt_Play.start = Toc[ti.cdti_trk0].diskTime;
-		azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
-#ifdef AZT_DEBUG
-		printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
-		       azt_Play.start.min, azt_Play.start.sec,
-		       azt_Play.start.frame, azt_Play.end.min,
-		       azt_Play.end.sec, azt_Play.end.frame);
-#endif
-		i = aztPlay(&azt_Play);
-		if (i < 0) {
-			aztAudioStatus = CDROM_AUDIO_ERROR;
-			return -EIO;
-		}
-		aztAudioStatus = CDROM_AUDIO_PLAY;
-		break;
-	case CDROMPLAYMSF:	/* Play starting at the given MSF address. */
-/*              if (aztAudioStatus == CDROM_AUDIO_PLAY) 
-		{ if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
-		  STEN_LOW;
-		  aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-		}
-*/
-		if (copy_from_user(&msf, argp, sizeof msf))
-			return -EFAULT;
-		/* convert to bcd */
-		azt_bin2bcd(&msf.cdmsf_min0);
-		azt_bin2bcd(&msf.cdmsf_sec0);
-		azt_bin2bcd(&msf.cdmsf_frame0);
-		azt_bin2bcd(&msf.cdmsf_min1);
-		azt_bin2bcd(&msf.cdmsf_sec1);
-		azt_bin2bcd(&msf.cdmsf_frame1);
-		azt_Play.start.min = msf.cdmsf_min0;
-		azt_Play.start.sec = msf.cdmsf_sec0;
-		azt_Play.start.frame = msf.cdmsf_frame0;
-		azt_Play.end.min = msf.cdmsf_min1;
-		azt_Play.end.sec = msf.cdmsf_sec1;
-		azt_Play.end.frame = msf.cdmsf_frame1;
-#ifdef AZT_DEBUG
-		printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
-		       azt_Play.start.min, azt_Play.start.sec,
-		       azt_Play.start.frame, azt_Play.end.min,
-		       azt_Play.end.sec, azt_Play.end.frame);
-#endif
-		i = aztPlay(&azt_Play);
-		if (i < 0) {
-			aztAudioStatus = CDROM_AUDIO_ERROR;
-			return -EIO;
-		}
-		aztAudioStatus = CDROM_AUDIO_PLAY;
-		break;
-
-	case CDROMREADTOCHDR:	/* Read the table of contents header */
-		tocHdr.cdth_trk0 = DiskInfo.first;
-		tocHdr.cdth_trk1 = DiskInfo.last;
-		if (copy_to_user(argp, &tocHdr, sizeof tocHdr))
-			return -EFAULT;
-		break;
-	case CDROMREADTOCENTRY:	/* Read an entry in the table of contents */
-		if (copy_from_user(&entry, argp, sizeof entry))
-			return -EFAULT;
-		if ((!aztTocUpToDate) || aztDiskChanged)
-			aztUpdateToc();
-		if (entry.cdte_track == CDROM_LEADOUT)
-			tocPtr = &Toc[DiskInfo.last + 1];
-		else if (entry.cdte_track > DiskInfo.last
-			 || entry.cdte_track < DiskInfo.first) {
-			return -EINVAL;
-		} else
-			tocPtr = &Toc[entry.cdte_track];
-		entry.cdte_adr = tocPtr->ctrl_addr;
-		entry.cdte_ctrl = tocPtr->ctrl_addr >> 4;
-		if (entry.cdte_format == CDROM_LBA)
-			entry.cdte_addr.lba =
-			    azt_msf2hsg(&tocPtr->diskTime);
-		else if (entry.cdte_format == CDROM_MSF) {
-			entry.cdte_addr.msf.minute =
-			    azt_bcd2bin(tocPtr->diskTime.min);
-			entry.cdte_addr.msf.second =
-			    azt_bcd2bin(tocPtr->diskTime.sec);
-			entry.cdte_addr.msf.frame =
-			    azt_bcd2bin(tocPtr->diskTime.frame);
-		} else {
-			return -EINVAL;
-		}
-		if (copy_to_user(argp, &entry, sizeof entry))
-			return -EFAULT;
-		break;
-	case CDROMSUBCHNL:	/* Get subchannel info */
-		if (copy_from_user
-		    (&subchnl, argp, sizeof(struct cdrom_subchnl)))
-			return -EFAULT;
-		if (aztGetQChannelInfo(&qInfo) < 0) {
-#ifdef AZT_DEBUG
-			printk
-			    ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",
-			     cmd);
-#endif
-			return -EIO;
-		}
-		subchnl.cdsc_audiostatus = aztAudioStatus;
-		subchnl.cdsc_adr = qInfo.ctrl_addr;
-		subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
-		subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
-		subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
-		if (subchnl.cdsc_format == CDROM_LBA) {
-			subchnl.cdsc_absaddr.lba =
-			    azt_msf2hsg(&qInfo.diskTime);
-			subchnl.cdsc_reladdr.lba =
-			    azt_msf2hsg(&qInfo.trackTime);
-		} else {	/*default */
-			subchnl.cdsc_format = CDROM_MSF;
-			subchnl.cdsc_absaddr.msf.minute =
-			    azt_bcd2bin(qInfo.diskTime.min);
-			subchnl.cdsc_absaddr.msf.second =
-			    azt_bcd2bin(qInfo.diskTime.sec);
-			subchnl.cdsc_absaddr.msf.frame =
-			    azt_bcd2bin(qInfo.diskTime.frame);
-			subchnl.cdsc_reladdr.msf.minute =
-			    azt_bcd2bin(qInfo.trackTime.min);
-			subchnl.cdsc_reladdr.msf.second =
-			    azt_bcd2bin(qInfo.trackTime.sec);
-			subchnl.cdsc_reladdr.msf.frame =
-			    azt_bcd2bin(qInfo.trackTime.frame);
-		}
-		if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl)))
-			return -EFAULT;
-		break;
-	case CDROMVOLCTRL:	/* Volume control 
-				   * With my Aztech CD268-01A volume control does not work, I can only
-				   turn the channels on (any value !=0) or off (value==0). Maybe it
-				   works better with your drive */
-		if (copy_from_user(&volctrl, argp, sizeof(volctrl)))
-			return -EFAULT;
-		azt_Play.start.min = 0x21;
-		azt_Play.start.sec = 0x84;
-		azt_Play.start.frame = volctrl.channel0;
-		azt_Play.end.min = volctrl.channel1;
-		azt_Play.end.sec = volctrl.channel2;
-		azt_Play.end.frame = volctrl.channel3;
-		sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
-		STEN_LOW_WAIT;
-		break;
-	case CDROMEJECT:
-		aztUnlockDoor();	/* Assume user knows what they're doing */
-		/* all drives can at least stop! */
-		if (aztAudioStatus == CDROM_AUDIO_PLAY) {
-			if (aztSendCmd(ACMD_STOP))
-				RETURNM("azt_ioctl 10", -1);
-			STEN_LOW_WAIT;
-		}
-		if (aztSendCmd(ACMD_EJECT))
-			RETURNM("azt_ioctl 11", -1);
-		STEN_LOW_WAIT;
-		aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-		break;
-	case CDROMEJECT_SW:
-		azt_auto_eject = (char) arg;
-		break;
-	case CDROMRESET:
-		outb(ACMD_SOFT_RESET, CMD_PORT);	/*send reset */
-		STEN_LOW;
-		if (inb(DATA_PORT) != AFL_OP_OK) {	/*OP_OK? */
-			printk
-			    ("aztcd: AZTECH CD-ROM drive does not respond\n");
-		}
-		break;
-/*Take care, the following code is not compatible with other CD-ROM drivers,
-  use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
-  if you do not want to use it!
-*/
-#if AZT_PRIVATE_IOCTLS
-	case CDROMREADCOOKED:	/*read data in mode 1 (2048 Bytes) */
-	case CDROMREADRAW:	/*read data in mode 2 (2336 Bytes) */
-		{
-			if (copy_from_user(&msf, argp, sizeof msf))
-				return -EFAULT;
-			/* convert to bcd */
-			azt_bin2bcd(&msf.cdmsf_min0);
-			azt_bin2bcd(&msf.cdmsf_sec0);
-			azt_bin2bcd(&msf.cdmsf_frame0);
-			msf.cdmsf_min1 = 0;
-			msf.cdmsf_sec1 = 0;
-			msf.cdmsf_frame1 = 1;	/*read only one frame */
-			azt_Play.start.min = msf.cdmsf_min0;
-			azt_Play.start.sec = msf.cdmsf_sec0;
-			azt_Play.start.frame = msf.cdmsf_frame0;
-			azt_Play.end.min = msf.cdmsf_min1;
-			azt_Play.end.sec = msf.cdmsf_sec1;
-			azt_Play.end.frame = msf.cdmsf_frame1;
-			if (cmd == CDROMREADRAW) {
-				if (DiskInfo.xa) {
-					return -1;	/*XA Disks can't be read raw */
-				} else {
-					if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play))
-						return -1;
-					DTEN_LOW;
-					insb(DATA_PORT, buf, CD_FRAMESIZE_RAW);
-					if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW))
-						return -EFAULT;
-				}
-			} else
-				/*CDROMREADCOOKED*/ {
-				if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
-					return -1;
-				DTEN_LOW;
-				insb(DATA_PORT, buf, CD_FRAMESIZE);
-				if (copy_to_user(argp, &buf, CD_FRAMESIZE))
-					return -EFAULT;
-				}
-		}
-		break;
-	case CDROMSEEK:	/*seek msf address */
-		if (copy_from_user(&msf, argp, sizeof msf))
-			return -EFAULT;
-		/* convert to bcd */
-		azt_bin2bcd(&msf.cdmsf_min0);
-		azt_bin2bcd(&msf.cdmsf_sec0);
-		azt_bin2bcd(&msf.cdmsf_frame0);
-		azt_Play.start.min = msf.cdmsf_min0;
-		azt_Play.start.sec = msf.cdmsf_sec0;
-		azt_Play.start.frame = msf.cdmsf_frame0;
-		if (aztSeek(&azt_Play))
-			return -1;
-		break;
-#endif				/*end of incompatible code */
-	case CDROMREADMODE1:	/*set read data in mode 1 */
-		return aztSetDiskType(AZT_MODE_1);
-	case CDROMREADMODE2:	/*set read data in mode 2 */
-		return aztSetDiskType(AZT_MODE_2);
-	default:
-		return -EINVAL;
-	}
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztcd_ioctl Command:%x  Time:%li\n", cmd,
-	       jiffies);
-#endif
-	return 0;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-static void azt_transfer(void)
-{
-#ifdef AZT_TEST
-	printk("aztcd: executing azt_transfer Time:%li\n", jiffies);
-#endif
-	if (!current_valid())
-	        return;
-
-	while (CURRENT->nr_sectors) {
-		int bn = CURRENT->sector / 4;
-		int i;
-		for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i);
-		if (i < AZT_BUF_SIZ) {
-			int offs = (i * 4 + (CURRENT->sector & 3)) * 512;
-			int nr_sectors = 4 - (CURRENT->sector & 3);
-			if (azt_buf_out != i) {
-				azt_buf_out = i;
-				if (azt_buf_bn[i] != bn) {
-					azt_buf_out = -1;
-					continue;
-				}
-			}
-			if (nr_sectors > CURRENT->nr_sectors)
-			    nr_sectors = CURRENT->nr_sectors;
-			memcpy(CURRENT->buffer, azt_buf + offs,
-				nr_sectors * 512);
-			CURRENT->nr_sectors -= nr_sectors;
-			CURRENT->sector += nr_sectors;
-			CURRENT->buffer += nr_sectors * 512;
-		} else {
-			azt_buf_out = -1;
-			break;
-		}
-	}
-}
-
-static void do_aztcd_request(request_queue_t * q)
-{
-#ifdef AZT_TEST
-	printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector,
-	       CURRENT->nr_sectors, jiffies);
-#endif
-	if (DiskInfo.audio) {
-		printk("aztcd: Error, tried to mount an Audio CD\n");
-		end_request(CURRENT, 0);
-		return;
-	}
-	azt_transfer_is_active = 1;
-	while (current_valid()) {
-		azt_transfer();
-		if (CURRENT->nr_sectors == 0) {
-			end_request(CURRENT, 1);
-		} else {
-			azt_buf_out = -1;	/* Want to read a block not in buffer */
-			if (azt_state == AZT_S_IDLE) {
-				if ((!aztTocUpToDate) || aztDiskChanged) {
-					if (aztUpdateToc() < 0) {
-						while (current_valid())
-							end_request(CURRENT, 0);
-						break;
-					}
-				}
-				azt_state = AZT_S_START;
-				AztTries = 5;
-				SET_TIMER(azt_poll, HZ / 100);
-			}
-			break;
-		}
-	}
-	azt_transfer_is_active = 0;
-#ifdef AZT_TEST2
-	printk
-	    ("azt_next_bn:%x  azt_buf_in:%x azt_buf_out:%x  azt_buf_bn:%x\n",
-	     azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
-	printk(" do_aztcd_request ends  Time:%li\n", jiffies);
-#endif
-}
-
-
-static void azt_invalidate_buffers(void)
-{
-	int i;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: executing azt_invalidate_buffers\n");
-#endif
-	for (i = 0; i < AZT_BUF_SIZ; ++i)
-		azt_buf_bn[i] = -1;
-	azt_buf_out = -1;
-}
-
-/*
- * Open the device special file.  Check that a disk is in.
- */
-static int aztcd_open(struct inode *ip, struct file *fp)
-{
-	int st;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztcd_open\n");
-#endif
-
-	if (aztPresent == 0)
-		return -ENXIO;	/* no hardware */
-
-	if (!azt_open_count && azt_state == AZT_S_IDLE) {
-		azt_invalidate_buffers();
-
-		st = getAztStatus();	/* check drive status */
-		if (st == -1)
-			goto err_out;	/* drive doesn't respond */
-
-		if (st & AST_DOOR_OPEN) {	/* close door, then get the status again. */
-			printk("aztcd: Door Open?\n");
-			aztCloseDoor();
-			st = getAztStatus();
-		}
-
-		if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) {	/*no disk in drive or changed */
-			printk
-			    ("aztcd: Disk Changed or No Disk in Drive?\n");
-			aztTocUpToDate = 0;
-		}
-		if (aztUpdateToc())
-			goto err_out;
-
-	}
-	++azt_open_count;
-	aztLockDoor();
-
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztcd_open\n");
-#endif
-	return 0;
-
-      err_out:
-	return -EIO;
-}
-
-
-/*
- * On close, we flush all azt blocks from the buffer cache.
- */
-static int aztcd_release(struct inode *inode, struct file *file)
-{
-#ifdef AZT_DEBUG
-	printk("aztcd: executing aztcd_release\n");
-	printk("inode: %p, device: %s    file: %p\n", inode,
-	       inode->i_bdev->bd_disk->disk_name, file);
-#endif
-	if (!--azt_open_count) {
-		azt_invalidate_buffers();
-		aztUnlockDoor();
-		if (azt_auto_eject)
-			aztSendCmd(ACMD_EJECT);
-		CLEAR_TIMER;
-	}
-	return 0;
-}
-
-static struct gendisk *azt_disk;
-
-/*
- * Test for presence of drive and initialize it.  Called at boot time.
- */
-
-static int __init aztcd_init(void)
-{
-	long int count, max_count;
-	unsigned char result[50];
-	int st;
-	void* status = NULL;
-	int i = 0;
-	int ret = 0;
-
-	if (azt_port == 0) {
-		printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization");
-		return -EIO;
-	}
-
-	printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM "
-	       "CD-ROM Driver\n");
-	printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n");
-	if (azt_port == -1) {
-		printk
-		    ("aztcd: DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",
-		     AZT_VERSION);
-	} else
-		printk
-		    ("aztcd: DriverVersion=%s BaseAddress=0x%x  For IDE/ATAPI-drives use ide-cd.c\n",
-		     AZT_VERSION, azt_port);
-	printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/"
-	       "Documentation/cdrom/aztcd\n");
-
-
-#ifdef AZT_SW32			/*CDROM connected to Soundwave32 card */
-	if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) {
-		printk
-		    ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
-		     AZT_SW32_BASE_ADDR, AZT_SW32_INIT,
-		     AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG);
-		return -EIO;
-	} else {
-		printk(KERN_INFO
-		       "aztcd: Soundwave32 card detected at %x  Version %x\n",
-		       AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
-		outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG);
-		for (count = 0; count < 10000; count++);	/*delay a bit */
-	}
-#endif
-
-	/* check for presence of drive */
-
-	if (azt_port == -1) {	/* autoprobing for proprietary interface  */
-		for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) {
-			azt_port = azt_port_auto[i];
-			printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x"
-			       "\n", azt_port);
-			 /*proprietary interfaces need 4 bytes */
-			if (!request_region(azt_port, 4, "aztcd")) {
-				continue;
-			}
-			outb(POLLED, MODE_PORT);
-			inb(CMD_PORT);
-			inb(CMD_PORT);
-			outb(ACMD_GET_VERSION, CMD_PORT);	/*Try to get version info */
-
-			aztTimeOutCount = 0;
-			do {
-				aztIndatum = inb(STATUS_PORT);
-				aztTimeOutCount++;
-				if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-					break;
-			} while (aztIndatum & AFL_STATUS);
-			if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */
-				break;
-			}
-			else {  /* Drive not found on this port - try next one */
-				release_region(azt_port, 4);
-			}
-		}
-		if ((i == 16) || (azt_port_auto[i] == 0)) {
-			printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
-			return -EIO;
-		}
-	} else {		/* no autoprobing */
-		if ((azt_port == 0x1f0) || (azt_port == 0x170))
-			status = request_region(azt_port, 8, "aztcd");	/*IDE-interfaces need 8 bytes */
-		else
-			status = request_region(azt_port, 4, "aztcd");	/*proprietary interfaces need 4 bytes */
-		if (!status) {
-			printk(KERN_WARNING "aztcd: conflict, I/O port (%X) "
-			       "already used\n", azt_port);
-			return -EIO;
-		}
-
-		if ((azt_port == 0x1f0) || (azt_port == 0x170))
-			SWITCH_IDE_SLAVE;	/*switch IDE interface to slave configuration */
-
-		outb(POLLED, MODE_PORT);
-		inb(CMD_PORT);
-		inb(CMD_PORT);
-		outb(ACMD_GET_VERSION, CMD_PORT);	/*Try to get version info */
-
-		aztTimeOutCount = 0;
-		do {
-			aztIndatum = inb(STATUS_PORT);
-			aztTimeOutCount++;
-			if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-				break;
-		} while (aztIndatum & AFL_STATUS);
-
-		if (inb(DATA_PORT) != AFL_OP_OK) {	/*OP_OK? If not, reset and try again */
-#ifndef MODULE
-			if (azt_cont != 0x79) {
-				printk(KERN_WARNING "aztcd: no AZTECH CD-ROM "
-				       "drive found-Try boot parameter aztcd="
-				       "<BaseAddress>,0x79\n");
-				ret = -EIO;
-				goto err_out;
-			}
-#else
-			if (0) {
-			}
-#endif
-			else {
-				printk(KERN_INFO "aztcd: drive reset - "
-				       "please wait\n");
-				for (count = 0; count < 50; count++) {
-					inb(STATUS_PORT);	/*removing all data from earlier tries */
-					inb(DATA_PORT);
-				}
-				outb(POLLED, MODE_PORT);
-				inb(CMD_PORT);
-				inb(CMD_PORT);
-				getAztStatus();	/*trap errors */
-				outb(ACMD_SOFT_RESET, CMD_PORT);	/*send reset */
-				STEN_LOW;
-				if (inb(DATA_PORT) != AFL_OP_OK) {	/*OP_OK? */
-					printk(KERN_WARNING "aztcd: no AZTECH "
-					       "CD-ROM drive found\n");
-					ret = -EIO;
-					goto err_out;
-				}
-
-				for (count = 0; count < AZT_TIMEOUT;
-				     count++)
-					barrier();	/* Stop gcc 2.96 being smart */
-				/* use udelay(), damnit -- AV */
-
-				if ((st = getAztStatus()) == -1) {
-					printk(KERN_WARNING "aztcd: Drive Status"
-					       " Error Status=%x\n", st);
-					ret = -EIO;
-					goto err_out;
-				}
-#ifdef AZT_DEBUG
-				printk(KERN_DEBUG "aztcd: Status = %x\n", st);
-#endif
-				outb(POLLED, MODE_PORT);
-				inb(CMD_PORT);
-				inb(CMD_PORT);
-				outb(ACMD_GET_VERSION, CMD_PORT);	/*GetVersion */
-				STEN_LOW;
-				OP_OK;
-			}
-		}
-	}
-
-	azt_init_end = 1;
-	STEN_LOW;
-	result[0] = inb(DATA_PORT);	/*reading in a null byte??? */
-	for (count = 1; count < 50; count++) {	/*Reading version string */
-		aztTimeOutCount = 0;	/*here we must implement STEN_LOW differently */
-		do {
-			aztIndatum = inb(STATUS_PORT);	/*because we want to exit by timeout */
-			aztTimeOutCount++;
-			if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-				break;
-		} while (aztIndatum & AFL_STATUS);
-		if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-			break;	/*all chars read? */
-		result[count] = inb(DATA_PORT);
-	}
-	if (count > 30)
-		max_count = 30;	/*print max.30 chars of the version string */
-	else
-		max_count = count;
-	printk(KERN_INFO "aztcd: FirmwareVersion=");
-	for (count = 1; count < max_count; count++)
-		printk("%c", result[count]);
-	printk("<<>> ");
-
-	if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) {
-		printk("AZTECH drive detected\n");
-	/*AZTECH*/}
-		else if ((result[2] == 'C') && (result[3] == 'D')
-			 && (result[4] == 'D')) {
-		printk("ORCHID or WEARNES drive detected\n");	/*ORCHID or WEARNES */
-	} else if ((result[1] == 0x03) && (result[2] == '5')) {
-		printk("TXC or CyCDROM drive detected\n");	/*Conrad TXC, CyCDROM */
-	} else {		/*OTHERS or none */
-		printk("\nunknown drive or firmware version detected\n");
-		printk
-		    ("aztcd may not run stable, if you want to try anyhow,\n");
-		printk("boot with: aztcd=<BaseAddress>,0x79\n");
-		if ((azt_cont != 0x79)) {
-			printk("aztcd: FirmwareVersion=");
-			for (count = 1; count < 5; count++)
-				printk("%c", result[count]);
-			printk("<<>> ");
-			printk("Aborted\n");
-			ret = -EIO;
-			goto err_out;
-		}
-	}
-	azt_disk = alloc_disk(1);
-	if (!azt_disk)
-		goto err_out;
-
-	if (register_blkdev(MAJOR_NR, "aztcd")) {
-		ret = -EIO;
-		goto err_out2;
-	}
-
-	azt_queue = blk_init_queue(do_aztcd_request, &aztSpin);
-	if (!azt_queue) {
-		ret = -ENOMEM;
-		goto err_out3;
-	}
-
-	blk_queue_hardsect_size(azt_queue, 2048);
-	azt_disk->major = MAJOR_NR;
-	azt_disk->first_minor = 0;
-	azt_disk->fops = &azt_fops;
-	sprintf(azt_disk->disk_name, "aztcd");
-	azt_disk->queue = azt_queue;
-	add_disk(azt_disk);
-	azt_invalidate_buffers();
-	aztPresent = 1;
-	aztCloseDoor();
-	return 0;
-err_out3:
-	unregister_blkdev(MAJOR_NR, "aztcd");
-err_out2:
-	put_disk(azt_disk);
-err_out:
-	if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
-		SWITCH_IDE_MASTER;
-		release_region(azt_port, 8);	/*IDE-interface */
-	} else
-		release_region(azt_port, 4);	/*proprietary interface */
-	return ret;
-
-}
-
-static void __exit aztcd_exit(void)
-{
-	del_gendisk(azt_disk);
-	put_disk(azt_disk);
-	if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
-		printk("What's that: can't unregister aztcd\n");
-		return;
-	}
-	blk_cleanup_queue(azt_queue);
-	if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
-		SWITCH_IDE_MASTER;
-		release_region(azt_port, 8);	/*IDE-interface */
-	} else
-		release_region(azt_port, 4);	/*proprietary interface */
-	printk(KERN_INFO "aztcd module released.\n");
-}
-
-module_init(aztcd_init);
-module_exit(aztcd_exit);
-
-/*##########################################################################
-  Aztcd State Machine: Controls Drive Operating State
-  ##########################################################################
-*/
-static void azt_poll(void)
-{
-	int st = 0;
-	int loop_ctl = 1;
-	int skip = 0;
-
-	if (azt_error) {
-		if (aztSendCmd(ACMD_GET_ERROR))
-			RETURN("azt_poll 1");
-		STEN_LOW;
-		azt_error = inb(DATA_PORT) & 0xFF;
-		printk("aztcd: I/O error 0x%02x\n", azt_error);
-		azt_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
-		if (AztTries == 5)
-			printk
-			    ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n",
-			     azt_next_bn);
-#endif
-		if (!AztTries--) {
-			printk
-			    ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n",
-			     azt_next_bn);
-			if (azt_transfer_is_active) {
-				AztTries = 0;
-				loop_ctl = 0;
-			}
-			if (current_valid())
-				end_request(CURRENT, 0);
-			AztTries = 5;
-		}
-		azt_error = 0;
-		azt_state = AZT_S_STOP;
-	}
-
-	while (loop_ctl) {
-		loop_ctl = 0;	/* each case must flip this back to 1 if we want
-				   to come back up here */
-		switch (azt_state) {
-
-		case AZT_S_IDLE:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_IDLE\n");
-			}
-#endif
-			return;
-
-		case AZT_S_START:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_START\n");
-			}
-#endif
-			if (aztSendCmd(ACMD_GET_STATUS))
-				RETURN("azt_poll 2");	/*result will be checked by aztStatus() */
-			azt_state =
-			    azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
-			AztTimeout = 3000;
-			break;
-
-		case AZT_S_MODE:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_MODE\n");
-			}
-#endif
-			if (!skip) {
-				if ((st = aztStatus()) != -1) {
-					if ((st & AST_DSK_CHG)
-					    || (st & AST_NOT_READY)) {
-						aztDiskChanged = 1;
-						aztTocUpToDate = 0;
-						azt_invalidate_buffers();
-						end_request(CURRENT, 0);
-						printk
-						    ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
-					}
-				} else
-					break;
-			}
-			skip = 0;
-
-			if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
-				aztDiskChanged = 1;
-				aztTocUpToDate = 0;
-				printk
-				    ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
-				end_request(CURRENT, 0);
-				printk((st & AST_DOOR_OPEN) ?
-				       "aztcd: door open\n" :
-				       "aztcd: disk removed\n");
-				if (azt_transfer_is_active) {
-					azt_state = AZT_S_START;
-					loop_ctl = 1;	/* goto immediately */
-					break;
-				}
-				azt_state = AZT_S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-
-/*	  if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
-	  outb(0x01, DATA_PORT);
-	  PA_OK;
-	  STEN_LOW;
-*/
-			if (aztSendCmd(ACMD_GET_STATUS))
-				RETURN("azt_poll 4");
-			STEN_LOW;
-			azt_mode = 1;
-			azt_state = AZT_S_READ;
-			AztTimeout = 3000;
-
-			break;
-
-
-		case AZT_S_READ:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_READ\n");
-			}
-#endif
-			if (!skip) {
-				if ((st = aztStatus()) != -1) {
-					if ((st & AST_DSK_CHG)
-					    || (st & AST_NOT_READY)) {
-						aztDiskChanged = 1;
-						aztTocUpToDate = 0;
-						azt_invalidate_buffers();
-						printk
-						    ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
-						end_request(CURRENT, 0);
-					}
-				} else
-					break;
-			}
-
-			skip = 0;
-			if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
-				aztDiskChanged = 1;
-				aztTocUpToDate = 0;
-				printk((st & AST_DOOR_OPEN) ?
-				       "aztcd: door open\n" :
-				       "aztcd: disk removed\n");
-				if (azt_transfer_is_active) {
-					azt_state = AZT_S_START;
-					loop_ctl = 1;
-					break;
-				}
-				azt_state = AZT_S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-
-			if (current_valid()) {
-				struct azt_Play_msf msf;
-				int i;
-				azt_next_bn = CURRENT->sector / 4;
-				azt_hsg2msf(azt_next_bn, &msf.start);
-				i = 0;
-				/* find out in which track we are */
-				while (azt_msf2hsg(&msf.start) >
-				       azt_msf2hsg(&Toc[++i].trackTime)) {
-				};
-				if (azt_msf2hsg(&msf.start) <
-				    azt_msf2hsg(&Toc[i].trackTime) -
-				    AZT_BUF_SIZ) {
-					azt_read_count = AZT_BUF_SIZ;	/*fast, because we read ahead */
-					/*azt_read_count=CURRENT->nr_sectors;    slow, no read ahead */
-				} else	/* don't read beyond end of track */
-#if AZT_MULTISESSION
-				{
-					azt_read_count =
-					    (azt_msf2hsg(&Toc[i].trackTime)
-					     / 4) * 4 -
-					    azt_msf2hsg(&msf.start);
-					if (azt_read_count < 0)
-						azt_read_count = 0;
-					if (azt_read_count > AZT_BUF_SIZ)
-						azt_read_count =
-						    AZT_BUF_SIZ;
-					printk
-					    ("aztcd: warning - trying to read beyond end of track\n");
-/*               printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
-*/ }
-#else
-				{
-					azt_read_count = AZT_BUF_SIZ;
-				}
-#endif
-				msf.end.min = 0;
-				msf.end.sec = 0;
-				msf.end.frame = azt_read_count;	/*Mitsumi here reads 0xffffff sectors */
-#ifdef AZT_TEST3
-				printk
-				    ("---reading msf-address %x:%x:%x  %x:%x:%x\n",
-				     msf.start.min, msf.start.sec,
-				     msf.start.frame, msf.end.min,
-				     msf.end.sec, msf.end.frame);
-				printk
-				    ("azt_next_bn:%x  azt_buf_in:%x azt_buf_out:%x  azt_buf_bn:%x\n",
-				     azt_next_bn, azt_buf_in, azt_buf_out,
-				     azt_buf_bn[azt_buf_in]);
-#endif
-				if (azt_read_mode == AZT_MODE_2) {
-					sendAztCmd(ACMD_PLAY_READ_RAW, &msf);	/*XA disks in raw mode */
-				} else {
-					sendAztCmd(ACMD_PLAY_READ, &msf);	/*others in cooked mode */
-				}
-				azt_state = AZT_S_DATA;
-				AztTimeout = READ_TIMEOUT;
-			} else {
-				azt_state = AZT_S_STOP;
-				loop_ctl = 1;
-				break;
-			}
-
-			break;
-
-
-		case AZT_S_DATA:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_DATA\n");
-			}
-#endif
-
-			st = inb(STATUS_PORT) & AFL_STATUSorDATA;
-
-			switch (st) {
-
-			case AFL_DATA:
-#ifdef AZT_TEST3
-				if (st != azt_st_old) {
-					azt_st_old = st;
-					printk("---AFL_DATA st:%x\n", st);
-				}
-#endif
-				if (!AztTries--) {
-					printk
-					    ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n",
-					     azt_next_bn);
-					if (azt_transfer_is_active) {
-						AztTries = 0;
-						break;
-					}
-					if (current_valid())
-						end_request(CURRENT, 0);
-					AztTries = 5;
-				}
-				azt_state = AZT_S_START;
-				AztTimeout = READ_TIMEOUT;
-				loop_ctl = 1;
-				break;
-
-			case AFL_STATUSorDATA:
-#ifdef AZT_TEST3
-				if (st != azt_st_old) {
-					azt_st_old = st;
-					printk
-					    ("---AFL_STATUSorDATA st:%x\n",
-					     st);
-				}
-#endif
-				break;
-
-			default:
-#ifdef AZT_TEST3
-				if (st != azt_st_old) {
-					azt_st_old = st;
-					printk("---default: st:%x\n", st);
-				}
-#endif
-				AztTries = 5;
-				if (!current_valid() && azt_buf_in == azt_buf_out) {
-					azt_state = AZT_S_STOP;
-					loop_ctl = 1;
-					break;
-				}
-				if (azt_read_count <= 0)
-					printk
-					    ("aztcd: warning - try to read 0 frames\n");
-				while (azt_read_count) {	/*??? fast read ahead loop */
-					azt_buf_bn[azt_buf_in] = -1;
-					DTEN_LOW;	/*??? unsolved problem, very
-							   seldom we get timeouts
-							   here, don't now the real
-							   reason. With my drive this
-							   sometimes also happens with
-							   Aztech's original driver under
-							   DOS. Is it a hardware bug? 
-							   I tried to recover from such
-							   situations here. Zimmermann */
-					if (aztTimeOutCount >= AZT_TIMEOUT) {
-						printk
-						    ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n",
-						     azt_read_count,
-						     CURRENT->nr_sectors,
-						     azt_buf_in);
-						printk
-						    ("azt_transfer_is_active:%x\n",
-						     azt_transfer_is_active);
-						azt_read_count = 0;
-						azt_state = AZT_S_STOP;
-						loop_ctl = 1;
-						end_request(CURRENT, 1);	/*should we have here (1) or (0)? */
-					} else {
-						if (azt_read_mode ==
-						    AZT_MODE_2) {
-							insb(DATA_PORT,
-							     azt_buf +
-							     CD_FRAMESIZE_RAW
-							     * azt_buf_in,
-							     CD_FRAMESIZE_RAW);
-						} else {
-							insb(DATA_PORT,
-							     azt_buf +
-							     CD_FRAMESIZE *
-							     azt_buf_in,
-							     CD_FRAMESIZE);
-						}
-						azt_read_count--;
-#ifdef AZT_TEST3
-						printk
-						    ("AZT_S_DATA; ---I've read data- read_count: %d\n",
-						     azt_read_count);
-						printk
-						    ("azt_next_bn:%d  azt_buf_in:%d azt_buf_out:%d  azt_buf_bn:%d\n",
-						     azt_next_bn,
-						     azt_buf_in,
-						     azt_buf_out,
-						     azt_buf_bn
-						     [azt_buf_in]);
-#endif
-						azt_buf_bn[azt_buf_in] =
-						    azt_next_bn++;
-						if (azt_buf_out == -1)
-							azt_buf_out =
-							    azt_buf_in;
-						azt_buf_in =
-						    azt_buf_in + 1 ==
-						    AZT_BUF_SIZ ? 0 :
-						    azt_buf_in + 1;
-					}
-				}
-				if (!azt_transfer_is_active) {
-					while (current_valid()) {
-						azt_transfer();
-						if (CURRENT->nr_sectors ==
-						    0)
-							end_request(CURRENT, 1);
-						else
-							break;
-					}
-				}
-
-				if (current_valid()
-				    && (CURRENT->sector / 4 < azt_next_bn
-					|| CURRENT->sector / 4 >
-					azt_next_bn + AZT_BUF_SIZ)) {
-					azt_state = AZT_S_STOP;
-					loop_ctl = 1;
-					break;
-				}
-				AztTimeout = READ_TIMEOUT;
-				if (azt_read_count == 0) {
-					azt_state = AZT_S_STOP;
-					loop_ctl = 1;
-					break;
-				}
-				break;
-			}
-			break;
-
-
-		case AZT_S_STOP:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_STOP\n");
-			}
-#endif
-			if (azt_read_count != 0)
-				printk("aztcd: discard data=%x frames\n",
-				       azt_read_count);
-			while (azt_read_count != 0) {
-				int i;
-				if (!(inb(STATUS_PORT) & AFL_DATA)) {
-					if (azt_read_mode == AZT_MODE_2)
-						for (i = 0;
-						     i < CD_FRAMESIZE_RAW;
-						     i++)
-							inb(DATA_PORT);
-					else
-						for (i = 0;
-						     i < CD_FRAMESIZE; i++)
-							inb(DATA_PORT);
-				}
-				azt_read_count--;
-			}
-			if (aztSendCmd(ACMD_GET_STATUS))
-				RETURN("azt_poll 5");
-			azt_state = AZT_S_STOPPING;
-			AztTimeout = 1000;
-			break;
-
-		case AZT_S_STOPPING:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_STOPPING\n");
-			}
-#endif
-
-			if ((st = aztStatus()) == -1 && AztTimeout)
-				break;
-
-			if ((st != -1)
-			    && ((st & AST_DSK_CHG)
-				|| (st & AST_NOT_READY))) {
-				aztDiskChanged = 1;
-				aztTocUpToDate = 0;
-				azt_invalidate_buffers();
-				printk
-				    ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
-				end_request(CURRENT, 0);
-			}
-
-#ifdef AZT_TEST3
-			printk("CURRENT_VALID %d azt_mode %d\n",
-			       current_valid(), azt_mode);
-#endif
-
-			if (current_valid()) {
-				if (st != -1) {
-					if (azt_mode == 1) {
-						azt_state = AZT_S_READ;
-						loop_ctl = 1;
-						skip = 1;
-						break;
-					} else {
-						azt_state = AZT_S_MODE;
-						loop_ctl = 1;
-						skip = 1;
-						break;
-					}
-				} else {
-					azt_state = AZT_S_START;
-					AztTimeout = 1;
-				}
-			} else {
-				azt_state = AZT_S_IDLE;
-				return;
-			}
-			break;
-
-		default:
-			printk("aztcd: invalid state %d\n", azt_state);
-			return;
-		}		/* case */
-	}			/* while */
-
-
-	if (!AztTimeout--) {
-		printk("aztcd: timeout in state %d\n", azt_state);
-		azt_state = AZT_S_STOP;
-		if (aztSendCmd(ACMD_STOP))
-			RETURN("azt_poll 6");
-		STEN_LOW_WAIT;
-	};
-
-	SET_TIMER(azt_poll, HZ / 100);
-}
-
-
-/*###########################################################################
- * Miscellaneous support functions
-  ###########################################################################
-*/
-static void azt_hsg2msf(long hsg, struct msf *msf)
-{
-	hsg += 150;
-	msf->min = hsg / 4500;
-	hsg %= 4500;
-	msf->sec = hsg / 75;
-	msf->frame = hsg % 75;
-#ifdef AZT_DEBUG
-	if (msf->min >= 70)
-		printk("aztcd: Error hsg2msf address Minutes\n");
-	if (msf->sec >= 60)
-		printk("aztcd: Error hsg2msf address Seconds\n");
-	if (msf->frame >= 75)
-		printk("aztcd: Error hsg2msf address Frames\n");
-#endif
-	azt_bin2bcd(&msf->min);	/* convert to BCD */
-	azt_bin2bcd(&msf->sec);
-	azt_bin2bcd(&msf->frame);
-}
-
-static long azt_msf2hsg(struct msf *mp)
-{
-	return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75
-	    + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET;
-}
-
-static void azt_bin2bcd(unsigned char *p)
-{
-	int u, t;
-
-	u = *p % 10;
-	t = *p / 10;
-	*p = u | (t << 4);
-}
-
-static int azt_bcd2bin(unsigned char bcd)
-{
-	return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR);
diff --git a/drivers/cdrom/aztcd.h b/drivers/cdrom/aztcd.h
deleted file mode 100644
index 057501e..0000000
--- a/drivers/cdrom/aztcd.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id: aztcd.h,v 2.60 1997/11/29 09:51:22 root Exp root $
- *
- * Definitions for a AztechCD268 CD-ROM interface
- *	Copyright (C) 1994-98  Werner Zimmermann
- *
- *	based on Mitsumi CDROM driver by Martin Harriss
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History:	W.Zimmermann adaption to Aztech CD268-01A Version 1.3
- *		October 1994 Email: Werner.Zimmermann@fht-esslingen.de
- */
-
-/* *** change this to set the I/O port address of your CD-ROM drive,
-       set to '-1', if you want autoprobing */
-#define AZT_BASE_ADDR		-1
-
-/* list of autoprobing addresses (not more than 15), last value must be 0x000
-   Note: Autoprobing is only enabled, if AZT_BASE_ADDR is set to '-1' ! */
-#define AZT_BASE_AUTO 		{ 0x320, 0x300, 0x310, 0x330, 0x000 }
-
-/* Uncomment this, if your CDROM is connected to a Soundwave32-soundcard
-   and configure AZT_BASE_ADDR and AZT_SW32_BASE_ADDR */
-/*#define AZT_SW32 1
-*/
-
-#ifdef AZT_SW32 
-#define AZT_SW32_BASE_ADDR      0x220  /*I/O port base address of your soundcard*/
-#endif
-
-/* Set this to 1, if you want your tray to be locked, set to 0 to prevent tray 
-   from locking */
-#define AZT_ALLOW_TRAY_LOCK	1
-
-/*Set this to 1 to allow auto-eject when unmounting a disk, set to 0, if you 
-  don't want the auto-eject feature*/
-#define AZT_AUTO_EJECT          0
-
-/*Set this to 1, if you want to use incompatible ioctls for reading in raw and
-  cooked mode */
-#define AZT_PRIVATE_IOCTLS      1
-
-/*Set this to 1, if you want multisession support by the ISO fs. Even if you set 
-  this value to '0' you can use multisession CDs. In that case the drive's firm-
-  ware will do the appropriate redirection automatically. The CD will then look
-  like a single session CD (but nevertheless all data may be read). Please read 
-  chapter '5.1 Multisession support' in README.aztcd for details. Normally it's 
-  uncritical to leave this setting untouched */
-#define AZT_MULTISESSION        1
-
-/*Uncomment this, if you are using a linux kernel version prior to 2.1.0 */
-/*#define AZT_KERNEL_PRIOR_2_1 */
-
-/*---------------------------------------------------------------------------*/
-/*-----nothing to be configured for normal applications below this line------*/
-
-
-/* Increase this if you get lots of timeouts; if you get kernel panic, replace
-   STEN_LOW_WAIT by STEN_LOW in the source code */
-#define AZT_STATUS_DELAY	400       /*for timer wait, STEN_LOW_WAIT*/
-#define AZT_TIMEOUT		8000000   /*for busy wait STEN_LOW, DTEN_LOW*/
-#define AZT_FAST_TIMEOUT	10000     /*for reading the version string*/
-
-/* number of times to retry a command before giving up */
-#define AZT_RETRY_ATTEMPTS	3
-
-/* port access macros */
-#define CMD_PORT		azt_port
-#define DATA_PORT		azt_port
-#define STATUS_PORT		azt_port+1
-#define MODE_PORT		azt_port+2
-#ifdef  AZT_SW32                
- #define AZT_SW32_INIT          (unsigned int) (0xFF00 & (AZT_BASE_ADDR*16))
- #define AZT_SW32_CONFIG_REG    AZT_SW32_BASE_ADDR+0x16  /*Soundwave32 Config. Register*/
- #define AZT_SW32_ID_REG        AZT_SW32_BASE_ADDR+0x04  /*Soundwave32 ID Version Register*/
-#endif
-
-/* status bits */
-#define AST_CMD_CHECK		0x80		/* 1 = command error */
-#define AST_DOOR_OPEN		0x40		/* 1 = door is open */
-#define AST_NOT_READY		0x20		/* 1 = no disk in the drive */
-#define AST_DSK_CHG		0x02		/* 1 = disk removed or changed */
-#define AST_MODE                0x01            /* 0=MODE1, 1=MODE2 */
-#define AST_MODE_BITS		0x1C		/* Mode Bits */
-#define AST_INITIAL		0x0C		/* initial, only valid ... */
-#define AST_BUSY		0x04		/* now playing, only valid
-						   in combination with mode
-						   bits */
-/* flag bits */
-#define AFL_DATA		0x02		/* data available if low */
-#define AFL_STATUS		0x04		/* status available if low */
-#define AFL_OP_OK		0x01		/* OP_OK command correct*/
-#define AFL_PA_OK		0x02		/* PA_OK parameter correct*/
-#define AFL_OP_ERR		0x05		/* error in command*/
-#define AFL_PA_ERR		0x06		/* error in parameters*/
-#define POLLED			0x04		/* polled mode */
-
-/* commands */
-#define ACMD_SOFT_RESET		0x10		/* reset drive */
-#define ACMD_PLAY_READ		0x20		/* read data track in cooked mode */
-#define ACMD_PLAY_READ_RAW      0x21		/* reading in raw mode*/
-#define ACMD_SEEK               0x30            /* seek msf address*/
-#define ACMD_SEEK_TO_LEADIN     0x31		/* seek to leadin track*/
-#define ACMD_GET_ERROR		0x40		/* get error code */
-#define ACMD_GET_STATUS		0x41		/* get status */
-#define ACMD_GET_Q_CHANNEL      0x50		/* read info from q channel */
-#define ACMD_EJECT		0x60		/* eject/open tray */
-#define ACMD_CLOSE              0x61            /* close tray */
-#define ACMD_LOCK		0x71		/* lock tray closed */
-#define ACMD_UNLOCK		0x72		/* unlock tray */
-#define ACMD_PAUSE		0x80		/* pause */
-#define ACMD_STOP		0x81		/* stop play */
-#define ACMD_PLAY_AUDIO		0x90		/* play audio track */
-#define ACMD_SET_VOLUME		0x93		/* set audio level */
-#define ACMD_GET_VERSION	0xA0		/* get firmware version */
-#define ACMD_SET_DISK_TYPE	0xA1		/* set disk data mode */
-
-#define MAX_TRACKS		104
-
-struct msf {
-	unsigned char	min;
-	unsigned char	sec;
-	unsigned char	frame;
-};
-
-struct azt_Play_msf {
-	struct msf	start;
-	struct msf	end;
-};
-
-struct azt_DiskInfo {
-	unsigned char	first;
-        unsigned char   next;
-	unsigned char	last;
-	struct msf	diskLength;
-	struct msf	firstTrack;
-        unsigned char   multi;
-        struct msf      nextSession;
-        struct msf      lastSession;
-        unsigned char   xa;
-        unsigned char   audio;
-};
-
-struct azt_Toc {
-	unsigned char	ctrl_addr;
-	unsigned char	track;
-	unsigned char	pointIndex;
-	struct msf	trackTime;
-	struct msf	diskTime;
-};
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 3625a05..499019b 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -302,7 +302,7 @@
 module_param(check_media_type, bool, 0);
 module_param(mrw_format_restart, bool, 0);
 
-static DEFINE_SPINLOCK(cdrom_lock);
+static DEFINE_MUTEX(cdrom_mutex);
 
 static const char *mrw_format_status[] = {
 	"not mrw",
@@ -438,10 +438,10 @@
 		cdo->generic_packet = cdrom_dummy_generic_packet;
 
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
-	spin_lock(&cdrom_lock);
+	mutex_lock(&cdrom_mutex);
 	cdi->next = topCdromPtr; 	
 	topCdromPtr = cdi;
-	spin_unlock(&cdrom_lock);
+	mutex_unlock(&cdrom_mutex);
 	return 0;
 }
 #undef ENSURE
@@ -452,7 +452,7 @@
 	cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 
 
 	prev = NULL;
-	spin_lock(&cdrom_lock);
+	mutex_lock(&cdrom_mutex);
 	cdi = topCdromPtr;
 	while (cdi && cdi != unreg) {
 		prev = cdi;
@@ -460,7 +460,7 @@
 	}
 
 	if (cdi == NULL) {
-		spin_unlock(&cdrom_lock);
+		mutex_unlock(&cdrom_mutex);
 		return -2;
 	}
 	if (prev)
@@ -468,7 +468,7 @@
 	else
 		topCdromPtr = cdi->next;
 
-	spin_unlock(&cdrom_lock);
+	mutex_unlock(&cdrom_mutex);
 
 	if (cdi->exit)
 		cdi->exit(cdi);
@@ -2695,11 +2695,12 @@
 {
 	void __user *argp = (void __user *)arg;
 	int ret;
+	struct gendisk *disk = ip->i_bdev->bd_disk;
 
 	/*
 	 * Try the generic SCSI command ioctl's first.
 	 */
-	ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, argp);
+	ret = scsi_cmd_ioctl(file, disk->queue, disk, cmd, argp);
 	if (ret != -ENOTTY)
 		return ret;
 
@@ -3289,103 +3290,137 @@
 	int	check;			/* check media type */
 } cdrom_sysctl_settings;
 
+enum cdrom_print_option {
+	CTL_NAME,
+	CTL_SPEED,
+	CTL_SLOTS,
+	CTL_CAPABILITY
+};
+
+static int cdrom_print_info(const char *header, int val, char *info,
+				int *pos, enum cdrom_print_option option)
+{
+	const int max_size = sizeof(cdrom_sysctl_settings.info);
+	struct cdrom_device_info *cdi;
+	int ret;
+
+	ret = scnprintf(info + *pos, max_size - *pos, header);
+	if (!ret)
+		return 1;
+
+	*pos += ret;
+
+	for (cdi = topCdromPtr; cdi; cdi = cdi->next) {
+		switch (option) {
+		case CTL_NAME:
+			ret = scnprintf(info + *pos, max_size - *pos,
+					"\t%s", cdi->name);
+			break;
+		case CTL_SPEED:
+			ret = scnprintf(info + *pos, max_size - *pos,
+					"\t%d", cdi->speed);
+			break;
+		case CTL_SLOTS:
+			ret = scnprintf(info + *pos, max_size - *pos,
+					"\t%d", cdi->capacity);
+			break;
+		case CTL_CAPABILITY:
+			ret = scnprintf(info + *pos, max_size - *pos,
+					"\t%d", CDROM_CAN(val) != 0);
+			break;
+		default:
+			printk(KERN_INFO "cdrom: invalid option%d\n", option);
+			return 1;
+		}
+		if (!ret)
+			return 1;
+		*pos += ret;
+	}
+
+	return 0;
+}
+
 static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
                            void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-        int pos;
-	struct cdrom_device_info *cdi;
+	int pos;
 	char *info = cdrom_sysctl_settings.info;
+	const int max_size = sizeof(cdrom_sysctl_settings.info);
 	
 	if (!*lenp || (*ppos && !write)) {
 		*lenp = 0;
 		return 0;
 	}
 
+	mutex_lock(&cdrom_mutex);
+
 	pos = sprintf(info, "CD-ROM information, " VERSION "\n");
 	
-	pos += sprintf(info+pos, "\ndrive name:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%s", cdi->name);
-
-	pos += sprintf(info+pos, "\ndrive speed:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", cdi->speed);
-
-	pos += sprintf(info+pos, "\ndrive # of slots:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", cdi->capacity);
-
-	pos += sprintf(info+pos, "\nCan close tray:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0);
-
-	pos += sprintf(info+pos, "\nCan open tray:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0);
-
-	pos += sprintf(info+pos, "\nCan lock tray:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0);
-
-	pos += sprintf(info+pos, "\nCan change speed:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0);
-
-	pos += sprintf(info+pos, "\nCan select disk:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0);
-
-	pos += sprintf(info+pos, "\nCan read multisession:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0);
-
-	pos += sprintf(info+pos, "\nCan read MCN:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0);
-
-	pos += sprintf(info+pos, "\nReports media changed:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0);
-
-	pos += sprintf(info+pos, "\nCan play audio:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0);
-
-	pos += sprintf(info+pos, "\nCan write CD-R:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0);
-
-	pos += sprintf(info+pos, "\nCan write CD-RW:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0);
-
-	pos += sprintf(info+pos, "\nCan read DVD:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0);
-
-	pos += sprintf(info+pos, "\nCan write DVD-R:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0);
-
-	pos += sprintf(info+pos, "\nCan write DVD-RAM:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
-
-	pos += sprintf(info+pos, "\nCan read MRW:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0);
-
-	pos += sprintf(info+pos, "\nCan write MRW:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
-
-	pos += sprintf(info+pos, "\nCan write RAM:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
-
-	strcpy(info+pos,"\n\n");
-		
-        return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+	if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
+		goto done;
+	if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
+		goto done;
+	if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
+		goto done;
+	if (cdrom_print_info("\nCan close tray:\t",
+				CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan open tray:\t",
+				CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan lock tray:\t",
+				CDC_LOCK, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan change speed:",
+				CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan select disk:",
+				CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan read multisession:",
+				CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan read MCN:\t",
+				CDC_MCN, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nReports media changed:",
+				CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan play audio:\t",
+				CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write CD-R:\t",
+				CDC_CD_R, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write CD-RW:",
+				CDC_CD_RW, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan read DVD:\t",
+				CDC_DVD, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write DVD-R:",
+				CDC_DVD_R, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write DVD-RAM:",
+				CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan read MRW:\t",
+				CDC_MRW, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write MRW:\t",
+				CDC_MRW_W, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write RAM:\t",
+				CDC_RAM, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (!scnprintf(info + pos, max_size - pos, "\n\n"))
+		goto done;
+doit:
+	mutex_unlock(&cdrom_mutex);
+	return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+done:
+	printk(KERN_INFO "cdrom: info buffer too small\n");
+	goto doit;
 }
 
 /* Unfortunately, per device settings are not implemented through
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
deleted file mode 100644
index 2157c58..0000000
--- a/drivers/cdrom/cdu31a.c
+++ /dev/null
@@ -1,3251 +0,0 @@
-/*
-* Sony CDU-31A CDROM interface device driver.
-*
-* Corey Minyard (minyard@wf-rch.cirr.com)
-*
-* Colossians 3:17
-*
-*  See Documentation/cdrom/cdu31a for additional details about this driver.
-* 
-* The Sony interface device driver handles Sony interface CDROM
-* drives and provides a complete block-level interface as well as an
-* ioctl() interface compatible with the Sun (as specified in
-* include/linux/cdrom.h).  With this interface, CDROMs can be
-* accessed and standard audio CDs can be played back normally.
-*
-* WARNING - 	All autoprobes have been removed from the driver.
-*		You MUST configure the CDU31A via a LILO config
-*		at boot time or in lilo.conf.  I have the
-*		following in my lilo.conf:
-*
-*                append="cdu31a=0x1f88,0,PAS"
-*
-*		The first number is the I/O base address of the
-*		card.  The second is the interrupt (0 means none).
- *		The third should be "PAS" if on a Pro-Audio
- *		spectrum, or nothing if on something else.
- *
- * This interface is (unfortunately) a polled interface.  This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables.  Some (like mine) do not even have the capability to
- * handle interrupts or DMA.  For this reason you will see a lot of
- * the following:
- *
- *   retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
- *   while (time_before(jiffies, retry_count) && (! <some condition to wait for))
- *   {
- *      while (handle_sony_cd_attention())
- *         ;
- *
- *      sony_sleep();
- *   }
- *   if (the condition not met)
- *   {
- *      return an error;
- *   }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try.  it also handles attentions, which are
- * asynchronous events from the drive informing the driver that a disk
- * has been inserted, removed, etc.
- *
- * NEWS FLASH - The driver now supports interrupts but they are
- * turned off by default.  Use of interrupts is highly encouraged, it
- * cuts CPU usage down to a reasonable level.  I had DMA in for a while
- * but PC DMA is just too slow.  Better to just insb() it.
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk.  The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal.  A lot of conversion goes on.
- *
- * DRIVER SPECIAL FEATURES
- * -----------------------
- *
- * This section describes features beyond the normal audio and CD-ROM
- * functions of the drive.
- *
- * XA compatibility
- *
- * The driver should support XA disks for both the CDU31A and CDU33A.
- * It does this transparently, the using program doesn't need to set it.
- *
- * Multi-Session
- *
- * A multi-session disk looks just like a normal disk to the user.
- * Just mount one normally, and all the data should be there.
- * A special thanks to Koen for help with this!
- * 
- * Raw sector I/O
- *
- * Using the CDROMREADAUDIO it is possible to read raw audio and data
- * tracks.  Both operations return 2352 bytes per sector.  On the data
- * tracks, the first 12 bytes is not returned by the drive and the value
- * of that data is indeterminate.
- *
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * TODO: 
- *       CDs with form1 and form2 sectors cause problems
- *       with current read-ahead strategy.
- *
- * Credits:
- *    Heiko Eissfeldt <heiko@colossus.escape.de>
- *         For finding abug in the return of the track numbers.
- *         TOC processing redone for proper multisession support.
- *
- *
- *  It probably a little late to be adding a history, but I guess I
- *  will start.
- *
- *  10/24/95 - Added support for disabling the eject button when the
- *             drive is open.  Note that there is a small problem
- *             still here, if the eject button is pushed while the
- *             drive light is flashing, the drive will return a bad
- *             status and be reset.  It recovers, though.
- *
- *  03/07/97 - Fixed a problem with timers.
- *
- *
- *  18 Spetember 1997 -- Ported to Uniform CD-ROM driver by 
- *                 Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- *                 changes by Erik Andersen <andersee@debian.org>
- *
- *  24 January 1998 -- Removed the scd_disc_status() function, which was now
- *                     just dead code left over from the port.
- *                          Erik Andersen <andersee@debian.org>
- *
- *  16 July 1998 -- Drive donated to Erik Andersen by John Kodis
- *                   <kodis@jagunet.com>.  Work begun on fixing driver to
- *                   work under 2.1.X.  Added temporary extra printks
- *                   which seem to slow it down enough to work.
- *
- *  9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	               Removed init_module & cleanup_module in favor of 
- *		       module_init & module_exit.
- *		       Torben Mathiasen <tmm@image.dk>
- *
- * 22 October 2004 -- Make the driver work in 2.6.X
- *		      Added workaround to fix hard lockups on eject
- *		      Fixed door locking problem after mounting empty drive
- *		      Set double-speed drives to double speed by default
- *		      Removed all readahead things - not needed anymore
- *			Ondrej Zary <rainbow@rainbow-software.org>
-*/
-
-#define DEBUG 1
-
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/cdrom.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/dma.h>
-
-#include "cdu31a.h"
-
-#define MAJOR_NR CDU31A_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
-
-#define PFX "CDU31A: "
-
-/*
-** Edit the following data to change interrupts, DMA channels, etc.
-** Default is polled and no DMA.  DMA is not recommended for double-speed
-** drives.
-*/
-static struct {
-	unsigned short base;	/* I/O Base Address */
-	short int_num;		/* Interrupt Number (-1 means scan for it,
-				   0 means don't use) */
-} cdu31a_addresses[] __initdata = {
-	{0}
-};
-
-static int handle_sony_cd_attention(void);
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int scd_spinup(void);
-/*static int scd_open(struct inode *inode, struct file *filp);*/
-static int scd_open(struct cdrom_device_info *, int);
-static void do_sony_cd_cmd(unsigned char cmd,
-			   unsigned char *params,
-			   unsigned int num_params,
-			   unsigned char *result_buffer,
-			   unsigned int *result_size);
-static void size_to_buf(unsigned int size, unsigned char *buf);
-
-/* Parameters for the read-ahead. */
-static unsigned int sony_next_block;	/* Next 512 byte block offset */
-static unsigned int sony_blocks_left = 0;	/* Number of 512 byte blocks left
-						   in the current read command. */
-
-
-/* The base I/O address of the Sony Interface.  This is a variable (not a
-   #define) so it can be easily changed via some future ioctl() */
-static unsigned int cdu31a_port = 0;
-module_param(cdu31a_port, uint, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive.  The
- * comment for the base address also applies here.
- */
-static volatile unsigned short sony_cd_cmd_reg;
-static volatile unsigned short sony_cd_param_reg;
-static volatile unsigned short sony_cd_write_reg;
-static volatile unsigned short sony_cd_control_reg;
-static volatile unsigned short sony_cd_status_reg;
-static volatile unsigned short sony_cd_result_reg;
-static volatile unsigned short sony_cd_read_reg;
-static volatile unsigned short sony_cd_fifost_reg;
-
-static struct request_queue *cdu31a_queue;
-static DEFINE_SPINLOCK(cdu31a_lock); /* queue lock */
-
-static int sony_spun_up = 0;	/* Has the drive been spun up? */
-
-static int sony_speed = 0;	/* Last wanted speed */
-
-static int sony_xa_mode = 0;	/* Is an XA disk in the drive
-				   and the drive a CDU31A? */
-
-static int sony_raw_data_mode = 1;	/* 1 if data tracks, 0 if audio.
-					   For raw data reads. */
-
-static unsigned int sony_usage = 0;	/* How many processes have the
-					   drive open. */
-
-static int sony_pas_init = 0;	/* Initialize the Pro-Audio
-				   Spectrum card? */
-
-static struct s_sony_session_toc single_toc;	/* Holds the
-						   table of
-						   contents. */
-
-static struct s_all_sessions_toc sony_toc;	/* entries gathered from all
-						   sessions */
-
-static int sony_toc_read = 0;	/* Has the TOC been read for
-				   the drive? */
-
-static struct s_sony_subcode last_sony_subcode;	/* Points to the last
-						   subcode address read */
-
-static DECLARE_MUTEX(sony_sem);		/* Semaphore for drive hardware access */
-
-static int is_double_speed = 0;	/* does the drive support double speed ? */
-
-static int is_auto_eject = 1;	/* Door has been locked? 1=No/0=Yes */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play.  The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over.  This holds the
- * position during a pause so a resume can restart it.  It uses the
- * audio status variable above to tell if it is paused.
- */
-static unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 };
-static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
-
-/* What IRQ is the drive using?  0 if none. */
-static int cdu31a_irq = 0;
-module_param(cdu31a_irq, int, 0);
-
-/* The interrupt handler will wake this queue up when it gets an
-   interrupts. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
-static int irq_flag = 0;
-
-static int curr_control_reg = 0;	/* Current value of the control register */
-
-/* A disk changed variable.  When a disk change is detected, it will
-   all be set to TRUE.  As the upper layers ask for disk_changed status
-   it will be cleared. */
-static char disk_changed;
-
-/* This was readahead_buffer once... Now it's used only for audio reads */
-static char audio_buffer[CD_FRAMESIZE_RAW];
-
-/* Used to time a short period to abort an operation after the
-   drive has been idle for a while.  This keeps the light on
-   the drive from flashing for very long. */
-static struct timer_list cdu31a_abort_timer;
-
-/* Marks if the timeout has started an abort read.  This is used
-   on entry to the drive to tell the code to read out the status
-   from the abort read. */
-static int abort_read_started = 0;
-
-/*
- * Uniform cdrom interface function
- * report back, if disc has changed from time of last request.
- */
-static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-	int retval;
-
-	retval = disk_changed;
-	disk_changed = 0;
-
-	return retval;
-}
-
-/*
- * Uniform cdrom interface function
- * report back, if drive is ready
- */
-static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-	if (CDSL_CURRENT != slot_nr)
-		/* we have no changer support */
-		return -EINVAL;
-	if (sony_spun_up)
-		return CDS_DISC_OK;
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	if (scd_spinup() == 0)
-		sony_spun_up = 1;
-	up(&sony_sem);
-	return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
-}
-
-static inline void enable_interrupts(void)
-{
-	curr_control_reg |= (SONY_ATTN_INT_EN_BIT
-			     | SONY_RES_RDY_INT_EN_BIT
-			     | SONY_DATA_RDY_INT_EN_BIT);
-	outb(curr_control_reg, sony_cd_control_reg);
-}
-
-static inline void disable_interrupts(void)
-{
-	curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
-			      | SONY_RES_RDY_INT_EN_BIT
-			      | SONY_DATA_RDY_INT_EN_BIT);
-	outb(curr_control_reg, sony_cd_control_reg);
-}
-
-/*
- * Wait a little while (used for polling the drive).  If in initialization,
- * setting a timeout doesn't work, so just loop for a while.
- */
-static inline void sony_sleep(void)
-{
-	if (cdu31a_irq <= 0) {
-		yield();
-	} else {		/* Interrupt driven */
-		DEFINE_WAIT(w);
-		int first = 1;
-
-		while (1) {
-			prepare_to_wait(&cdu31a_irq_wait, &w,
-					TASK_INTERRUPTIBLE);
-			if (first) {
-				enable_interrupts();
-				first = 0;
-			}
-
-			if (irq_flag != 0)
-				break;
-			if (!signal_pending(current)) {
-				schedule();
-				continue;
-			} else
-				disable_interrupts();
-			break;
-		}
-		finish_wait(&cdu31a_irq_wait, &w);
-		irq_flag = 0;
-	}
-}
-
-
-/*
- * The following are convenience routine to read various status and set
- * various conditions in the drive.
- */
-static inline int is_attention(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0;
-}
-
-static inline int is_busy(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0;
-}
-
-static inline int is_data_ready(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0;
-}
-
-static inline int is_data_requested(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0;
-}
-
-static inline int is_result_ready(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0;
-}
-
-static inline int is_param_write_rdy(void)
-{
-	return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0;
-}
-
-static inline int is_result_reg_not_empty(void)
-{
-	return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0;
-}
-
-static inline void reset_drive(void)
-{
-	curr_control_reg = 0;
-	sony_toc_read = 0;
-	outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
-}
-
-/*
- * Uniform cdrom interface function
- * reset drive and return when it is ready
- */
-static int scd_reset(struct cdrom_device_info *cdi)
-{
-	unsigned long retry_count;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	reset_drive();
-
-	retry_count = jiffies + SONY_RESET_TIMEOUT;
-	while (time_before(jiffies, retry_count) && (!is_attention())) {
-		sony_sleep();
-	}
-
-	up(&sony_sem);
-	return 0;
-}
-
-static inline void clear_attention(void)
-{
-	outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_result_ready(void)
-{
-	outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_data_ready(void)
-{
-	outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT,
-	     sony_cd_control_reg);
-}
-
-static inline void clear_param_reg(void)
-{
-	outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline unsigned char read_status_register(void)
-{
-	return inb(sony_cd_status_reg);
-}
-
-static inline unsigned char read_result_register(void)
-{
-	return inb(sony_cd_result_reg);
-}
-
-static inline unsigned char read_data_register(void)
-{
-	return inb(sony_cd_read_reg);
-}
-
-static inline void write_param(unsigned char param)
-{
-	outb(param, sony_cd_param_reg);
-}
-
-static inline void write_cmd(unsigned char cmd)
-{
-	outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT,
-	     sony_cd_control_reg);
-	outb(cmd, sony_cd_cmd_reg);
-}
-
-static irqreturn_t cdu31a_interrupt(int irq, void *dev_id)
-{
-	unsigned char val;
-
-	if (abort_read_started) {
-		/* We might be waiting for an abort to finish.  Don't
-		   disable interrupts yet, though, because we handle
-		   this one here. */
-		/* Clear out the result registers. */
-		while (is_result_reg_not_empty()) {
-			val = read_result_register();
-		}
-		clear_data_ready();
-		clear_result_ready();
-
-		/* Clear out the data */
-		while (is_data_requested()) {
-			val = read_data_register();
-		}
-		abort_read_started = 0;
-
-		/* If something was waiting, wake it up now. */
-		if (waitqueue_active(&cdu31a_irq_wait)) {
-			disable_interrupts();
-			irq_flag = 1;
-			wake_up_interruptible(&cdu31a_irq_wait);
-		}
-	} else if (waitqueue_active(&cdu31a_irq_wait)) {
-		disable_interrupts();
-		irq_flag = 1;
-		wake_up_interruptible(&cdu31a_irq_wait);
-	} else {
-		disable_interrupts();
-		printk(KERN_NOTICE PFX
-				"Got an interrupt but nothing was waiting\n");
-	}
-	return IRQ_HANDLED;
-}
-
-/*
- * give more verbose error messages
- */
-static unsigned char *translate_error(unsigned char err_code)
-{
-	static unsigned char errbuf[80];
-
-	switch (err_code) {
-		case 0x10: return "illegal command ";
-		case 0x11: return "illegal parameter ";
-
-		case 0x20: return "not loaded ";
-		case 0x21: return "no disc ";
-		case 0x22: return "not spinning ";
-		case 0x23: return "spinning ";
-		case 0x25: return "spindle servo ";
-		case 0x26: return "focus servo ";
-		case 0x29: return "eject mechanism ";
-		case 0x2a: return "audio playing ";
-		case 0x2c: return "emergency eject ";
-
-		case 0x30: return "focus ";
-		case 0x31: return "frame sync ";
-		case 0x32: return "subcode address ";
-		case 0x33: return "block sync ";
-		case 0x34: return "header address ";
-
-		case 0x40: return "illegal track read ";
-		case 0x41: return "mode 0 read ";
-		case 0x42: return "illegal mode read ";
-		case 0x43: return "illegal block size read ";
-		case 0x44: return "mode read ";
-		case 0x45: return "form read ";
-		case 0x46: return "leadout read ";
-		case 0x47: return "buffer overrun ";
-
-		case 0x53: return "unrecoverable CIRC ";
-		case 0x57: return "unrecoverable LECC ";
-
-		case 0x60: return "no TOC ";
-		case 0x61: return "invalid subcode data ";
-		case 0x63: return "focus on TOC read ";
-		case 0x64: return "frame sync on TOC read ";
-		case 0x65: return "TOC data ";
-
-		case 0x70: return "hardware failure ";
-		case 0x91: return "leadin ";
-		case 0x92: return "leadout ";
-		case 0x93: return "data track ";
-	}
-	sprintf(errbuf, "unknown 0x%02x ", err_code);
-	return errbuf;
-}
-
-/*
- * Set the drive parameters so the drive will auto-spin-up when a
- * disk is inserted.
- */
-static void set_drive_params(int want_doublespeed)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned char params[3];
-
-
-	params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME;
-	params[1] = 0x00;	/* Never spin down the drive. */
-	do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-		       params, 2, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_NOTICE PFX
-			"Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
-	}
-
-	params[0] = SONY_SD_MECH_CONTROL;
-	params[1] = SONY_AUTO_SPIN_UP_BIT;	/* Set auto spin up */
-
-	if (is_auto_eject)
-		params[1] |= SONY_AUTO_EJECT_BIT;
-
-	if (is_double_speed && want_doublespeed) {
-		params[1] |= SONY_DOUBLE_SPEED_BIT;	/* Set the drive to double speed if 
-							   possible */
-	}
-	do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-		       params, 2, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_NOTICE PFX "Unable to set mechanical "
-				"parameters: 0x%2.2x\n", res_reg[1]);
-	}
-}
-
-/*
- * Uniform cdrom interface function
- * select reading speed for data access
- */
-static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-	if (speed == 0)
-		sony_speed = 1;
-	else
-		sony_speed = speed - 1;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	set_drive_params(sony_speed);
-	up(&sony_sem);
-	return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * lock or unlock eject button
- */
-static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-	if (lock == 0) {
-		is_auto_eject = 1;
-	} else {
-		is_auto_eject = 0;
-	}
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	set_drive_params(sony_speed);
-	up(&sony_sem);
-	return 0;
-}
-
-/*
- * This code will reset the drive and attempt to restore sane parameters.
- */
-static void restart_on_error(void)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned long retry_count;
-
-
-	printk(KERN_NOTICE PFX "Resetting drive on error\n");
-	reset_drive();
-	retry_count = jiffies + SONY_RESET_TIMEOUT;
-	while (time_before(jiffies, retry_count) && (!is_attention())) {
-		sony_sleep();
-	}
-	set_drive_params(sony_speed);
-	do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n",
-		       res_reg[1]);
-	}
-
-	msleep(2000);
-
-	sony_get_toc();
-}
-
-/*
- * This routine writes data to the parameter register.  Since this should
- * happen fairly fast, it is polled with no OS waits between.
- */
-static int write_params(unsigned char *params, int num_params)
-{
-	unsigned int retry_count;
-
-
-	retry_count = SONY_READY_RETRIES;
-	while ((retry_count > 0) && (!is_param_write_rdy())) {
-		retry_count--;
-	}
-	if (!is_param_write_rdy()) {
-		return -EIO;
-	}
-
-	while (num_params > 0) {
-		write_param(*params);
-		params++;
-		num_params--;
-	}
-
-	return 0;
-}
-
-
-/*
- * The following reads data from the command result register.  It is a
- * fairly complex routine, all status info flows back through this
- * interface.  The algorithm is stolen directly from the flowcharts in
- * the drive manual.
- */
-static void
-get_result(unsigned char *result_buffer, unsigned int *result_size)
-{
-	unsigned char a, b;
-	int i;
-	unsigned long retry_count;
-
-
-	while (handle_sony_cd_attention());
-	/* Wait for the result data to be ready */
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-	while (time_before(jiffies, retry_count)
-	       && (is_busy() || (!(is_result_ready())))) {
-		sony_sleep();
-
-		while (handle_sony_cd_attention());
-	}
-	if (is_busy() || (!(is_result_ready()))) {
-		pr_debug(PFX "timeout out %d\n", __LINE__);
-		result_buffer[0] = 0x20;
-		result_buffer[1] = SONY_TIMEOUT_OP_ERR;
-		*result_size = 2;
-		return;
-	}
-
-	/*
-	 * Get the first two bytes.  This determines what else needs
-	 * to be done.
-	 */
-	clear_result_ready();
-	a = read_result_register();
-	*result_buffer = a;
-	result_buffer++;
-
-	/* Check for block error status result. */
-	if ((a & 0xf0) == 0x50) {
-		*result_size = 1;
-		return;
-	}
-
-	b = read_result_register();
-	*result_buffer = b;
-	result_buffer++;
-	*result_size = 2;
-
-	/*
-	 * 0x20 means an error occurred.  Byte 2 will have the error code.
-	 * Otherwise, the command succeeded, byte 2 will have the count of
-	 * how many more status bytes are coming.
-	 *
-	 * The result register can be read 10 bytes at a time, a wait for
-	 * result ready to be asserted must be done between every 10 bytes.
-	 */
-	if ((a & 0xf0) != 0x20) {
-		if (b > 8) {
-			for (i = 0; i < 8; i++) {
-				*result_buffer = read_result_register();
-				result_buffer++;
-				(*result_size)++;
-			}
-			b = b - 8;
-
-			while (b > 10) {
-				retry_count = SONY_READY_RETRIES;
-				while ((retry_count > 0)
-				       && (!is_result_ready())) {
-					retry_count--;
-				}
-				if (!is_result_ready()) {
-					pr_debug(PFX "timeout out %d\n",
-					       __LINE__);
-					result_buffer[0] = 0x20;
-					result_buffer[1] =
-					    SONY_TIMEOUT_OP_ERR;
-					*result_size = 2;
-					return;
-				}
-
-				clear_result_ready();
-
-				for (i = 0; i < 10; i++) {
-					*result_buffer =
-					    read_result_register();
-					result_buffer++;
-					(*result_size)++;
-				}
-				b = b - 10;
-			}
-
-			if (b > 0) {
-				retry_count = SONY_READY_RETRIES;
-				while ((retry_count > 0)
-				       && (!is_result_ready())) {
-					retry_count--;
-				}
-				if (!is_result_ready()) {
-					pr_debug(PFX "timeout out %d\n",
-					       __LINE__);
-					result_buffer[0] = 0x20;
-					result_buffer[1] =
-					    SONY_TIMEOUT_OP_ERR;
-					*result_size = 2;
-					return;
-				}
-			}
-		}
-
-		while (b > 0) {
-			*result_buffer = read_result_register();
-			result_buffer++;
-			(*result_size)++;
-			b--;
-		}
-	}
-}
-
-/*
- * Do a command that does not involve data transfer.  This routine must
- * be re-entrant from the same task to support being called from the
- * data operation code when an error occurs.
- */
-static void
-do_sony_cd_cmd(unsigned char cmd,
-	       unsigned char *params,
-	       unsigned int num_params,
-	       unsigned char *result_buffer, unsigned int *result_size)
-{
-	unsigned long retry_count;
-	int num_retries = 0;
-
-retry_cd_operation:
-
-	while (handle_sony_cd_attention());
-
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-	while (time_before(jiffies, retry_count) && (is_busy())) {
-		sony_sleep();
-
-		while (handle_sony_cd_attention());
-	}
-	if (is_busy()) {
-		pr_debug(PFX "timeout out %d\n", __LINE__);
-		result_buffer[0] = 0x20;
-		result_buffer[1] = SONY_TIMEOUT_OP_ERR;
-		*result_size = 2;
-	} else {
-		clear_result_ready();
-		clear_param_reg();
-
-		write_params(params, num_params);
-		write_cmd(cmd);
-
-		get_result(result_buffer, result_size);
-	}
-
-	if (((result_buffer[0] & 0xf0) == 0x20)
-	    && (num_retries < MAX_CDU31A_RETRIES)) {
-		num_retries++;
-		msleep(100);
-		goto retry_cd_operation;
-	}
-}
-
-
-/*
- * Handle an attention from the drive.  This will return 1 if it found one
- * or 0 if not (if one is found, the caller might want to call again).
- *
- * This routine counts the number of consecutive times it is called
- * (since this is always called from a while loop until it returns
- * a 0), and returns a 0 if it happens too many times.  This will help
- * prevent a lockup.
- */
-static int handle_sony_cd_attention(void)
-{
-	unsigned char atten_code;
-	static int num_consecutive_attentions = 0;
-	volatile int val;
-
-
-#if 0
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#endif
-	if (is_attention()) {
-		if (num_consecutive_attentions >
-		    CDU31A_MAX_CONSECUTIVE_ATTENTIONS) {
-			printk(KERN_NOTICE PFX "Too many consecutive "
-				"attentions: %d\n", num_consecutive_attentions);
-			num_consecutive_attentions = 0;
-			pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__,
-			       __LINE__);
-			return 0;
-		}
-
-		clear_attention();
-		atten_code = read_result_register();
-
-		switch (atten_code) {
-			/* Someone changed the CD.  Mark it as changed */
-		case SONY_MECH_LOADED_ATTN:
-			disk_changed = 1;
-			sony_toc_read = 0;
-			sony_audio_status = CDROM_AUDIO_NO_STATUS;
-			sony_blocks_left = 0;
-			break;
-
-		case SONY_SPIN_DOWN_COMPLETE_ATTN:
-			/* Mark the disk as spun down. */
-			sony_spun_up = 0;
-			break;
-
-		case SONY_AUDIO_PLAY_DONE_ATTN:
-			sony_audio_status = CDROM_AUDIO_COMPLETED;
-			read_subcode();
-			break;
-
-		case SONY_EJECT_PUSHED_ATTN:
-			if (is_auto_eject) {
-				sony_audio_status = CDROM_AUDIO_INVALID;
-			}
-			break;
-
-		case SONY_LEAD_IN_ERR_ATTN:
-		case SONY_LEAD_OUT_ERR_ATTN:
-		case SONY_DATA_TRACK_ERR_ATTN:
-		case SONY_AUDIO_PLAYBACK_ERR_ATTN:
-			sony_audio_status = CDROM_AUDIO_ERROR;
-			break;
-		}
-
-		num_consecutive_attentions++;
-		pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-		return 1;
-	} else if (abort_read_started) {
-		while (is_result_reg_not_empty()) {
-			val = read_result_register();
-		}
-		clear_data_ready();
-		clear_result_ready();
-		/* Clear out the data */
-		while (is_data_requested()) {
-			val = read_data_register();
-		}
-		abort_read_started = 0;
-		pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-		return 1;
-	}
-
-	num_consecutive_attentions = 0;
-#if 0
-	pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-#endif
-	return 0;
-}
-
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int int_to_bcd(unsigned int val)
-{
-	int retval;
-
-
-	retval = (val / 10) << 4;
-	retval = retval | val % 10;
-	return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int bcd_to_int(unsigned int bcd)
-{
-	return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void log_to_msf(unsigned int log, unsigned char *msf)
-{
-	log = log + LOG_START_OFFSET;
-	msf[0] = int_to_bcd(log / 4500);
-	log = log % 4500;
-	msf[1] = int_to_bcd(log / 75);
-	msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int msf_to_log(unsigned char *msf)
-{
-	unsigned int log;
-
-
-	log = msf[2];
-	log += msf[1] * 75;
-	log += msf[0] * 4500;
-	log = log - LOG_START_OFFSET;
-
-	return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void size_to_buf(unsigned int size, unsigned char *buf)
-{
-	buf[0] = size / 65536;
-	size = size % 65536;
-	buf[1] = size / 256;
-	buf[2] = size % 256;
-}
-
-/* Starts a read operation. Returns 0 on success and 1 on failure. 
-   The read operation used here allows multiple sequential sectors 
-   to be read and status returned for each sector.  The driver will
-   read the output one at a time as the requests come and abort the
-   operation if the requested sector is not the next one from the
-   drive. */
-static int
-start_request(unsigned int sector, unsigned int nsect)
-{
-	unsigned char params[6];
-	unsigned long retry_count;
-
-
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-	log_to_msf(sector, params);
-	size_to_buf(nsect, &params[3]);
-
-	/*
-	 * Clear any outstanding attentions and wait for the drive to
-	 * complete any pending operations.
-	 */
-	while (handle_sony_cd_attention());
-
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-	while (time_before(jiffies, retry_count) && (is_busy())) {
-		sony_sleep();
-
-		while (handle_sony_cd_attention());
-	}
-
-	if (is_busy()) {
-		printk(KERN_NOTICE PFX "Timeout while waiting "
-				"to issue command\n");
-		pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-		return 1;
-	} else {
-		/* Issue the command */
-		clear_result_ready();
-		clear_param_reg();
-
-		write_params(params, 6);
-		write_cmd(SONY_READ_BLKERR_STAT_CMD);
-
-		sony_blocks_left = nsect * 4;
-		sony_next_block = sector * 4;
-		pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-		return 0;
-	}
-	pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-/* Abort a pending read operation.  Clear all the drive status variables. */
-static void abort_read(void)
-{
-	unsigned char result_reg[2];
-	int result_size;
-	volatile int val;
-
-
-	do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
-	if ((result_reg[0] & 0xf0) == 0x20) {
-		printk(KERN_ERR PFX "Aborting read, %s error\n",
-		       translate_error(result_reg[1]));
-	}
-
-	while (is_result_reg_not_empty()) {
-		val = read_result_register();
-	}
-	clear_data_ready();
-	clear_result_ready();
-	/* Clear out the data */
-	while (is_data_requested()) {
-		val = read_data_register();
-	}
-
-	sony_blocks_left = 0;
-}
-
-/* Called when the timer times out.  This will abort the
-   pending read operation. */
-static void handle_abort_timeout(unsigned long data)
-{
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-	/* If it is in use, ignore it. */
-	if (down_trylock(&sony_sem) == 0) {
-		/* We can't use abort_read(), because it will sleep
-		   or schedule in the timer interrupt.  Just start
-		   the operation, finish it on the next access to
-		   the drive. */
-		clear_result_ready();
-		clear_param_reg();
-		write_cmd(SONY_ABORT_CMD);
-
-		sony_blocks_left = 0;
-		abort_read_started = 1;
-		up(&sony_sem);
-	}
-	pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* Actually get one sector of data from the drive. */
-static void
-input_data_sector(char *buffer)
-{
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-	/* If an XA disk on a CDU31A, skip the first 12 bytes of data from
-	   the disk.  The real data is after that. We can use audio_buffer. */
-	if (sony_xa_mode)
-		insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD);
-
-	clear_data_ready();
-
-	insb(sony_cd_read_reg, buffer, 2048);
-
-	/* If an XA disk, we have to clear out the rest of the unused
-	   error correction data. We can use audio_buffer for that. */
-	if (sony_xa_mode)
-		insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL);
-
-	pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* read data from the drive.  Note the nsect must be <= 4. */
-static void
-read_data_block(char *buffer,
-		unsigned int block,
-		unsigned int nblocks,
-		unsigned char res_reg[], int *res_size)
-{
-	unsigned long retry_count;
-
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-	res_reg[0] = 0;
-	res_reg[1] = 0;
-	*res_size = 0;
-
-	/* Wait for the drive to tell us we have something */
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-	while (time_before(jiffies, retry_count) && !(is_data_ready())) {
-		while (handle_sony_cd_attention());
-
-		sony_sleep();
-	}
-	if (!(is_data_ready())) {
-		if (is_result_ready()) {
-			get_result(res_reg, res_size);
-			if ((res_reg[0] & 0xf0) != 0x20) {
-				printk(KERN_NOTICE PFX "Got result that should"
-					" have been error: %d\n", res_reg[0]);
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_BAD_DATA_ERR;
-				*res_size = 2;
-			}
-			abort_read();
-		} else {
-			pr_debug(PFX "timeout out %d\n", __LINE__);
-			res_reg[0] = 0x20;
-			res_reg[1] = SONY_TIMEOUT_OP_ERR;
-			*res_size = 2;
-			abort_read();
-		}
-	} else {
-		input_data_sector(buffer);
-		sony_blocks_left -= nblocks;
-		sony_next_block += nblocks;
-
-		/* Wait for the status from the drive. */
-		retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-		while (time_before(jiffies, retry_count)
-		       && !(is_result_ready())) {
-			while (handle_sony_cd_attention());
-
-			sony_sleep();
-		}
-
-		if (!is_result_ready()) {
-			pr_debug(PFX "timeout out %d\n", __LINE__);
-			res_reg[0] = 0x20;
-			res_reg[1] = SONY_TIMEOUT_OP_ERR;
-			*res_size = 2;
-			abort_read();
-		} else {
-			get_result(res_reg, res_size);
-
-			/* If we got a buffer status, handle that. */
-			if ((res_reg[0] & 0xf0) == 0x50) {
-
-				if ((res_reg[0] ==
-				     SONY_NO_CIRC_ERR_BLK_STAT)
-				    || (res_reg[0] ==
-					SONY_NO_LECC_ERR_BLK_STAT)
-				    || (res_reg[0] ==
-					SONY_RECOV_LECC_ERR_BLK_STAT)) {
-					/* nothing here */
-				} else {
-					printk(KERN_ERR PFX "Data block "
-						"error: 0x%x\n", res_reg[0]);
-					res_reg[0] = 0x20;
-					res_reg[1] = SONY_BAD_DATA_ERR;
-					*res_size = 2;
-				}
-
-				/* Final transfer is done for read command, get final result. */
-				if (sony_blocks_left == 0) {
-					get_result(res_reg, res_size);
-				}
-			} else if ((res_reg[0] & 0xf0) != 0x20) {
-				/* The drive gave me bad status, I don't know what to do.
-				   Reset the driver and return an error. */
-				printk(KERN_ERR PFX "Invalid block "
-					"status: 0x%x\n", res_reg[0]);
-				restart_on_error();
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_BAD_DATA_ERR;
-				*res_size = 2;
-			}
-		}
-	}
-	pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail.  Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations.  This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void do_cdu31a_request(request_queue_t * q)
-{
-	struct request *req;
-	int block, nblock, num_retries;
-	unsigned char res_reg[12];
-	unsigned int res_size;
-
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-	spin_unlock_irq(q->queue_lock);
-	if (down_interruptible(&sony_sem)) {
-		spin_lock_irq(q->queue_lock);
-		return;
-	}
-
-	/* Get drive status before doing anything. */
-	while (handle_sony_cd_attention());
-
-	/* Make sure we have a valid TOC. */
-	sony_get_toc();
-
-
-	/* Make sure the timer is cancelled. */
-	del_timer(&cdu31a_abort_timer);
-
-	while (1) {
-		/*
-		 * The beginning here is stolen from the hard disk driver.  I hope
-		 * it's right.
-		 */
-		req = elv_next_request(q);
-		if (!req)
-			goto end_do_cdu31a_request;
-
-		if (!sony_spun_up)
-			scd_spinup();
-
-		block = req->sector;
-		nblock = req->nr_sectors;
-		pr_debug(PFX "request at block %d, length %d blocks\n",
-			block, nblock);
-		if (!sony_toc_read) {
-			printk(KERN_NOTICE PFX "TOC not read\n");
-			end_request(req, 0);
-			continue;
-		}
-
-		/* WTF??? */
-		if (!blk_fs_request(req)) {
-			end_request(req, 0);
-			continue;
-		}
-		if (rq_data_dir(req) == WRITE) {
-			end_request(req, 0);
-			continue;
-		}
-
-		/*
-		 * If the block address is invalid or the request goes beyond the end of
-		 * the media, return an error.
-		 */
-		if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
-			printk(KERN_NOTICE PFX "Request past end of media\n");
-			end_request(req, 0);
-			continue;
-		}
-
-		if (nblock > 4)
-			nblock = 4;
-		num_retries = 0;
-
-	try_read_again:
-		while (handle_sony_cd_attention());
-
-		if (!sony_toc_read) {
-			printk(KERN_NOTICE PFX "TOC not read\n");
-			end_request(req, 0);
-			continue;
-		}
-
-		/* If no data is left to be read from the drive, start the
-		   next request. */
-		if (sony_blocks_left == 0) {
-			if (start_request(block / 4, nblock / 4)) {
-				end_request(req, 0);
-				continue;
-			}
-		}
-		/* If the requested block is not the next one waiting in
-		   the driver, abort the current operation and start a
-		   new one. */
-		else if (block != sony_next_block) {
-			pr_debug(PFX "Read for block %d, expected %d\n",
-				 block, sony_next_block);
-			abort_read();
-			if (!sony_toc_read) {
-				printk(KERN_NOTICE PFX "TOC not read\n");
-				end_request(req, 0);
-				continue;
-			}
-			if (start_request(block / 4, nblock / 4)) {
-				printk(KERN_NOTICE PFX "start request failed\n");
-				end_request(req, 0);
-				continue;
-			}
-		}
-
-		read_data_block(req->buffer, block, nblock, res_reg, &res_size);
-
-		if (res_reg[0] != 0x20) {
-			if (!end_that_request_first(req, 1, nblock)) {
-				spin_lock_irq(q->queue_lock);
-				blkdev_dequeue_request(req);
-				end_that_request_last(req, 1);
-				spin_unlock_irq(q->queue_lock);
-			}
-			continue;
-		}
-
-		if (num_retries > MAX_CDU31A_RETRIES) {
-			end_request(req, 0);
-			continue;
-		}
-
-		num_retries++;
-		if (res_reg[1] == SONY_NOT_SPIN_ERR) {
-			do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-					&res_size);
-		} else {
-			printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n",
-				 translate_error(res_reg[1]), block, nblock);
-		}
-		goto try_read_again;
-	}
-      end_do_cdu31a_request:
-#if 0
-	/* After finished, cancel any pending operations. */
-	abort_read();
-#else
-	/* Start a timer to time out after a while to disable
-	   the read. */
-	cdu31a_abort_timer.expires = jiffies + 2 * HZ;	/* Wait 2 seconds */
-	add_timer(&cdu31a_abort_timer);
-#endif
-
-	up(&sony_sem);
-	spin_lock_irq(q->queue_lock);
-	pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * Read the table of contents from the drive and set up TOC if
- * successful.
- */
-static void sony_get_toc(void)
-{
-	unsigned char res_reg[2];
-	unsigned int res_size;
-	unsigned char parms[1];
-	int session;
-	int num_spin_ups;
-	int totaltracks = 0;
-	int mint = 99;
-	int maxt = 0;
-
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-	num_spin_ups = 0;
-	if (!sony_toc_read) {
-	      respinup_on_gettoc:
-		/* Ignore the result, since it might error if spinning already. */
-		do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		/* The drive sometimes returns error 0.  I don't know why, but ignore
-		   it.  It seems to mean the drive has already done the operation. */
-		if ((res_size < 2)
-		    || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-			/* If the drive is already playing, it's ok.  */
-			if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
-			    || (res_reg[1] == 0)) {
-				goto gettoc_drive_spinning;
-			}
-
-			/* If the drive says it is not spun up (even though we just did it!)
-			   then retry the operation at least a few times. */
-			if ((res_reg[1] == SONY_NOT_SPIN_ERR)
-			    && (num_spin_ups < MAX_CDU31A_RETRIES)) {
-				num_spin_ups++;
-				goto respinup_on_gettoc;
-			}
-
-			printk("cdu31a: Error reading TOC: %x %s\n",
-			       res_reg[0], translate_error(res_reg[1]));
-			return;
-		}
-
-	      gettoc_drive_spinning:
-
-		/* The idea here is we keep asking for sessions until the command
-		   fails.  Then we know what the last valid session on the disk is.
-		   No need to check session 0, since session 0 is the same as session
-		   1; the command returns different information if you give it 0. 
-		 */
-#if DEBUG
-		memset(&sony_toc, 0x0e, sizeof(sony_toc));
-		memset(&single_toc, 0x0f, sizeof(single_toc));
-#endif
-		session = 1;
-		while (1) {
-/* This seems to slow things down enough to make it work.  This
- * appears to be a problem in do_sony_cd_cmd.  This printk seems 
- * to address the symptoms...  -Erik */
-			pr_debug(PFX "Trying session %d\n", session);
-			parms[0] = session;
-			do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,
-				       parms, 1, res_reg, &res_size);
-
-			pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]);
-
-			if ((res_size < 2)
-			    || ((res_reg[0] & 0xf0) == 0x20)) {
-				/* An error reading the TOC, this must be past the last session. */
-				if (session == 1)
-					printk
-					    ("Yikes! Couldn't read any sessions!");
-				break;
-			}
-			pr_debug(PFX "Reading session %d\n", session);
-
-			parms[0] = session;
-			do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
-				       parms,
-				       1,
-				       (unsigned char *) &single_toc,
-				       &res_size);
-			if ((res_size < 2)
-			    || ((single_toc.exec_status[0] & 0xf0) ==
-				0x20)) {
-				printk(KERN_ERR PFX "Error reading "
-						"session %d: %x %s\n",
-				     session, single_toc.exec_status[0],
-				     translate_error(single_toc.
-						     exec_status[1]));
-				/* An error reading the TOC.  Return without sony_toc_read
-				   set. */
-				return;
-			}
-			pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, "
-					"1st trk %d, dsktyp %x, dum0 %x\n",
-			     single_toc.address0, single_toc.control0,
-			     single_toc.point0,
-			     bcd_to_int(single_toc.first_track_num),
-			     single_toc.disk_type, single_toc.dummy0);
-			pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, "
-					"lst trk %d, dummy1 %x, dum2 %x\n",
-			     single_toc.address1, single_toc.control1,
-			     single_toc.point1,
-			     bcd_to_int(single_toc.last_track_num),
-			     single_toc.dummy1, single_toc.dummy2);
-			pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x "
-				"leadout start min %d, sec %d, frame %d\n",
-			     single_toc.address2, single_toc.control2,
-			     single_toc.point2,
-			     bcd_to_int(single_toc.lead_out_start_msf[0]),
-			     bcd_to_int(single_toc.lead_out_start_msf[1]),
-			     bcd_to_int(single_toc.lead_out_start_msf[2]));
-			if (res_size > 18 && single_toc.pointb0 > 0xaf)
-				pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
-				     "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
-				     single_toc.addressb0,
-				     single_toc.controlb0,
-				     single_toc.pointb0,
-				     bcd_to_int(single_toc.
-						next_poss_prog_area_msf
-						[0]),
-				     bcd_to_int(single_toc.
-						next_poss_prog_area_msf
-						[1]),
-				     bcd_to_int(single_toc.
-						next_poss_prog_area_msf
-						[2]),
-				     single_toc.num_mode_5_pointers,
-				     bcd_to_int(single_toc.
-						max_start_outer_leadout_msf
-						[0]),
-				     bcd_to_int(single_toc.
-						max_start_outer_leadout_msf
-						[1]),
-				     bcd_to_int(single_toc.
-						max_start_outer_leadout_msf
-						[2]));
-			if (res_size > 27 && single_toc.pointb1 > 0xaf)
-				pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
-				     single_toc.addressb1,
-				     single_toc.controlb1,
-				     single_toc.pointb1,
-				     single_toc.dummyb0_1[0],
-				     single_toc.dummyb0_1[1],
-				     single_toc.dummyb0_1[2],
-				     single_toc.dummyb0_1[3],
-				     single_toc.num_skip_interval_pointers,
-				     single_toc.num_skip_track_assignments,
-				     single_toc.dummyb0_2);
-			if (res_size > 36 && single_toc.pointb2 > 0xaf)
-				pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-				     single_toc.addressb2,
-				     single_toc.controlb2,
-				     single_toc.pointb2,
-				     single_toc.tracksb2[0],
-				     single_toc.tracksb2[1],
-				     single_toc.tracksb2[2],
-				     single_toc.tracksb2[3],
-				     single_toc.tracksb2[4],
-				     single_toc.tracksb2[5],
-				     single_toc.tracksb2[6]);
-			if (res_size > 45 && single_toc.pointb3 > 0xaf)
-				pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-				     single_toc.addressb3,
-				     single_toc.controlb3,
-				     single_toc.pointb3,
-				     single_toc.tracksb3[0],
-				     single_toc.tracksb3[1],
-				     single_toc.tracksb3[2],
-				     single_toc.tracksb3[3],
-				     single_toc.tracksb3[4],
-				     single_toc.tracksb3[5],
-				     single_toc.tracksb3[6]);
-			if (res_size > 54 && single_toc.pointb4 > 0xaf)
-				pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-				     single_toc.addressb4,
-				     single_toc.controlb4,
-				     single_toc.pointb4,
-				     single_toc.tracksb4[0],
-				     single_toc.tracksb4[1],
-				     single_toc.tracksb4[2],
-				     single_toc.tracksb4[3],
-				     single_toc.tracksb4[4],
-				     single_toc.tracksb4[5],
-				     single_toc.tracksb4[6]);
-			if (res_size > 63 && single_toc.pointc0 > 0xaf)
-				pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-				     single_toc.addressc0,
-				     single_toc.controlc0,
-				     single_toc.pointc0,
-				     single_toc.dummyc0[0],
-				     single_toc.dummyc0[1],
-				     single_toc.dummyc0[2],
-				     single_toc.dummyc0[3],
-				     single_toc.dummyc0[4],
-				     single_toc.dummyc0[5],
-				     single_toc.dummyc0[6]);
-#undef DEBUG
-#define DEBUG 0
-
-			sony_toc.lead_out_start_msf[0] =
-			    bcd_to_int(single_toc.lead_out_start_msf[0]);
-			sony_toc.lead_out_start_msf[1] =
-			    bcd_to_int(single_toc.lead_out_start_msf[1]);
-			sony_toc.lead_out_start_msf[2] =
-			    bcd_to_int(single_toc.lead_out_start_msf[2]);
-			sony_toc.lead_out_start_lba =
-			    single_toc.lead_out_start_lba =
-			    msf_to_log(sony_toc.lead_out_start_msf);
-
-			/* For points that do not exist, move the data over them
-			   to the right location. */
-			if (single_toc.pointb0 != 0xb0) {
-				memmove(((char *) &single_toc) + 27,
-					((char *) &single_toc) + 18,
-					res_size - 18);
-				res_size += 9;
-			} else if (res_size > 18) {
-				sony_toc.lead_out_start_msf[0] =
-				    bcd_to_int(single_toc.
-					       max_start_outer_leadout_msf
-					       [0]);
-				sony_toc.lead_out_start_msf[1] =
-				    bcd_to_int(single_toc.
-					       max_start_outer_leadout_msf
-					       [1]);
-				sony_toc.lead_out_start_msf[2] =
-				    bcd_to_int(single_toc.
-					       max_start_outer_leadout_msf
-					       [2]);
-				sony_toc.lead_out_start_lba =
-				    msf_to_log(sony_toc.
-					       lead_out_start_msf);
-			}
-			if (single_toc.pointb1 != 0xb1) {
-				memmove(((char *) &single_toc) + 36,
-					((char *) &single_toc) + 27,
-					res_size - 27);
-				res_size += 9;
-			}
-			if (single_toc.pointb2 != 0xb2) {
-				memmove(((char *) &single_toc) + 45,
-					((char *) &single_toc) + 36,
-					res_size - 36);
-				res_size += 9;
-			}
-			if (single_toc.pointb3 != 0xb3) {
-				memmove(((char *) &single_toc) + 54,
-					((char *) &single_toc) + 45,
-					res_size - 45);
-				res_size += 9;
-			}
-			if (single_toc.pointb4 != 0xb4) {
-				memmove(((char *) &single_toc) + 63,
-					((char *) &single_toc) + 54,
-					res_size - 54);
-				res_size += 9;
-			}
-			if (single_toc.pointc0 != 0xc0) {
-				memmove(((char *) &single_toc) + 72,
-					((char *) &single_toc) + 63,
-					res_size - 63);
-				res_size += 9;
-			}
-#if DEBUG
-			printk(PRINT_INFO PFX "start track lba %u,  "
-					"leadout start lba %u\n",
-			     single_toc.start_track_lba,
-			     single_toc.lead_out_start_lba);
-			{
-				int i;
-				for (i = 0;
-				     i <
-				     1 +
-				     bcd_to_int(single_toc.last_track_num)
-				     -
-				     bcd_to_int(single_toc.
-						first_track_num); i++) {
-					printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x,  track %02d, start min %02d, sec %02d, frame %02d\n",
-					     i,
-					     single_toc.tracks[i].address,
-					     single_toc.tracks[i].control,
-					     bcd_to_int(single_toc.
-							tracks[i].track),
-					     bcd_to_int(single_toc.
-							tracks[i].
-							track_start_msf
-							[0]),
-					     bcd_to_int(single_toc.
-							tracks[i].
-							track_start_msf
-							[1]),
-					     bcd_to_int(single_toc.
-							tracks[i].
-							track_start_msf
-							[2]));
-					if (mint >
-					    bcd_to_int(single_toc.
-						       tracks[i].track))
-						mint =
-						    bcd_to_int(single_toc.
-							       tracks[i].
-							       track);
-					if (maxt <
-					    bcd_to_int(single_toc.
-						       tracks[i].track))
-						maxt =
-						    bcd_to_int(single_toc.
-							       tracks[i].
-							       track);
-				}
-				printk(KERN_INFO PFX "min track number %d,  "
-						"max track number %d\n",
-				     mint, maxt);
-			}
-#endif
-
-			/* prepare a special table of contents for a CD-I disc. They don't have one. */
-			if (single_toc.disk_type == 0x10 &&
-			    single_toc.first_track_num == 2 &&
-			    single_toc.last_track_num == 2 /* CD-I */ ) {
-				sony_toc.tracks[totaltracks].address = 1;
-				sony_toc.tracks[totaltracks].control = 4;	/* force data tracks */
-				sony_toc.tracks[totaltracks].track = 1;
-				sony_toc.tracks[totaltracks].
-				    track_start_msf[0] = 0;
-				sony_toc.tracks[totaltracks].
-				    track_start_msf[1] = 2;
-				sony_toc.tracks[totaltracks].
-				    track_start_msf[2] = 0;
-				mint = maxt = 1;
-				totaltracks++;
-			} else
-				/* gather track entries from this session */
-			{
-				int i;
-				for (i = 0;
-				     i <
-				     1 +
-				     bcd_to_int(single_toc.last_track_num)
-				     -
-				     bcd_to_int(single_toc.
-						first_track_num);
-				     i++, totaltracks++) {
-					sony_toc.tracks[totaltracks].
-					    address =
-					    single_toc.tracks[i].address;
-					sony_toc.tracks[totaltracks].
-					    control =
-					    single_toc.tracks[i].control;
-					sony_toc.tracks[totaltracks].
-					    track =
-					    bcd_to_int(single_toc.
-						       tracks[i].track);
-					sony_toc.tracks[totaltracks].
-					    track_start_msf[0] =
-					    bcd_to_int(single_toc.
-						       tracks[i].
-						       track_start_msf[0]);
-					sony_toc.tracks[totaltracks].
-					    track_start_msf[1] =
-					    bcd_to_int(single_toc.
-						       tracks[i].
-						       track_start_msf[1]);
-					sony_toc.tracks[totaltracks].
-					    track_start_msf[2] =
-					    bcd_to_int(single_toc.
-						       tracks[i].
-						       track_start_msf[2]);
-					if (i == 0)
-						single_toc.
-						    start_track_lba =
-						    msf_to_log(sony_toc.
-							       tracks
-							       [totaltracks].
-							       track_start_msf);
-					if (mint >
-					    sony_toc.tracks[totaltracks].
-					    track)
-						mint =
-						    sony_toc.
-						    tracks[totaltracks].
-						    track;
-					if (maxt <
-					    sony_toc.tracks[totaltracks].
-					    track)
-						maxt =
-						    sony_toc.
-						    tracks[totaltracks].
-						    track;
-				}
-			}
-			sony_toc.first_track_num = mint;
-			sony_toc.last_track_num = maxt;
-			/* Disk type of last session wins. For example:
-			   CD-Extra has disk type 0 for the first session, so
-			   a dumb HiFi CD player thinks it is a plain audio CD.
-			   We are interested in the disk type of the last session,
-			   which is 0x20 (XA) for CD-Extra, so we can access the
-			   data track ... */
-			sony_toc.disk_type = single_toc.disk_type;
-			sony_toc.sessions = session;
-
-			/* don't believe everything :-) */
-			if (session == 1)
-				single_toc.start_track_lba = 0;
-			sony_toc.start_track_lba =
-			    single_toc.start_track_lba;
-
-			if (session > 1 && single_toc.pointb0 == 0xb0 &&
-			    sony_toc.lead_out_start_lba ==
-			    single_toc.lead_out_start_lba) {
-				break;
-			}
-
-			/* Let's not get carried away... */
-			if (session > 40) {
-				printk(KERN_NOTICE PFX "too many sessions: "
-						"%d\n", session);
-				break;
-			}
-			session++;
-		}
-		sony_toc.track_entries = totaltracks;
-		/* add one entry for the LAST track with track number CDROM_LEADOUT */
-		sony_toc.tracks[totaltracks].address = single_toc.address2;
-		sony_toc.tracks[totaltracks].control = single_toc.control2;
-		sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;
-		sony_toc.tracks[totaltracks].track_start_msf[0] =
-		    sony_toc.lead_out_start_msf[0];
-		sony_toc.tracks[totaltracks].track_start_msf[1] =
-		    sony_toc.lead_out_start_msf[1];
-		sony_toc.tracks[totaltracks].track_start_msf[2] =
-		    sony_toc.lead_out_start_msf[2];
-
-		sony_toc_read = 1;
-
-		pr_debug(PFX "Disk session %d, start track: %d, "
-				"stop track: %d\n",
-		     session, single_toc.start_track_lba,
-		     single_toc.lead_out_start_lba);
-	}
-	pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-
-/*
- * Uniform cdrom interface function
- * return multisession offset and sector information
- */
-static int scd_get_last_session(struct cdrom_device_info *cdi,
-				struct cdrom_multisession *ms_info)
-{
-	if (ms_info == NULL)
-		return 1;
-
-	if (!sony_toc_read) {
-		if (down_interruptible(&sony_sem))
-			return -ERESTARTSYS;
-		sony_get_toc();
-		up(&sony_sem);
-	}
-
-	ms_info->addr_format = CDROM_LBA;
-	ms_info->addr.lba = sony_toc.start_track_lba;
-	ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE ||
-	    sony_toc.disk_type == 0x10 /* CDI */ ;
-
-	return 0;
-}
-
-/*
- * Search for a specific track in the table of contents.
- */
-static int find_track(int track)
-{
-	int i;
-
-	for (i = 0; i <= sony_toc.track_entries; i++) {
-		if (sony_toc.tracks[i].track == track) {
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-
-/*
- * Read the subcode and put it in last_sony_subcode for future use.
- */
-static int read_subcode(void)
-{
-	unsigned int res_size;
-
-
-	do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
-		       NULL,
-		       0, (unsigned char *) &last_sony_subcode, &res_size);
-	if ((res_size < 2)
-	    || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
-		printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n",
-		       translate_error(last_sony_subcode.exec_status[1]));
-		return -EIO;
-	}
-
-	last_sony_subcode.track_num =
-	    bcd_to_int(last_sony_subcode.track_num);
-	last_sony_subcode.index_num =
-	    bcd_to_int(last_sony_subcode.index_num);
-	last_sony_subcode.abs_msf[0] =
-	    bcd_to_int(last_sony_subcode.abs_msf[0]);
-	last_sony_subcode.abs_msf[1] =
-	    bcd_to_int(last_sony_subcode.abs_msf[1]);
-	last_sony_subcode.abs_msf[2] =
-	    bcd_to_int(last_sony_subcode.abs_msf[2]);
-
-	last_sony_subcode.rel_msf[0] =
-	    bcd_to_int(last_sony_subcode.rel_msf[0]);
-	last_sony_subcode.rel_msf[1] =
-	    bcd_to_int(last_sony_subcode.rel_msf[1]);
-	last_sony_subcode.rel_msf[2] =
-	    bcd_to_int(last_sony_subcode.rel_msf[2]);
-	return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * return the media catalog number found on some older audio cds
- */
-static int
-scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-	unsigned char resbuffer[2 + 14];
-	unsigned char *mcnp = mcn->medium_catalog_number;
-	unsigned char *resp = resbuffer + 3;
-	unsigned int res_size;
-
-	memset(mcn->medium_catalog_number, 0, 14);
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
-		       NULL, 0, resbuffer, &res_size);
-	up(&sony_sem);
-	if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
-	else {
-		/* packed bcd to single ASCII digits */
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-	}
-	*mcnp = '\0';
-	return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it.  If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing).  If the drive is paused or completed, the subcode information has
- * already been stored, just use that.  The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int sony_get_subchnl_info(struct cdrom_subchnl *schi)
-{
-	/* Get attention stuff */
-	while (handle_sony_cd_attention());
-
-	sony_get_toc();
-	if (!sony_toc_read) {
-		return -EIO;
-	}
-
-	switch (sony_audio_status) {
-	case CDROM_AUDIO_NO_STATUS:
-	case CDROM_AUDIO_PLAY:
-		if (read_subcode() < 0) {
-			return -EIO;
-		}
-		break;
-
-	case CDROM_AUDIO_PAUSED:
-	case CDROM_AUDIO_COMPLETED:
-		break;
-
-#if 0
-	case CDROM_AUDIO_NO_STATUS:
-		schi->cdsc_audiostatus = sony_audio_status;
-		return 0;
-		break;
-#endif
-	case CDROM_AUDIO_INVALID:
-	case CDROM_AUDIO_ERROR:
-	default:
-		return -EIO;
-	}
-
-	schi->cdsc_audiostatus = sony_audio_status;
-	schi->cdsc_adr = last_sony_subcode.address;
-	schi->cdsc_ctrl = last_sony_subcode.control;
-	schi->cdsc_trk = last_sony_subcode.track_num;
-	schi->cdsc_ind = last_sony_subcode.index_num;
-	if (schi->cdsc_format == CDROM_MSF) {
-		schi->cdsc_absaddr.msf.minute =
-		    last_sony_subcode.abs_msf[0];
-		schi->cdsc_absaddr.msf.second =
-		    last_sony_subcode.abs_msf[1];
-		schi->cdsc_absaddr.msf.frame =
-		    last_sony_subcode.abs_msf[2];
-
-		schi->cdsc_reladdr.msf.minute =
-		    last_sony_subcode.rel_msf[0];
-		schi->cdsc_reladdr.msf.second =
-		    last_sony_subcode.rel_msf[1];
-		schi->cdsc_reladdr.msf.frame =
-		    last_sony_subcode.rel_msf[2];
-	} else if (schi->cdsc_format == CDROM_LBA) {
-		schi->cdsc_absaddr.lba =
-		    msf_to_log(last_sony_subcode.abs_msf);
-		schi->cdsc_reladdr.lba =
-		    msf_to_log(last_sony_subcode.rel_msf);
-	}
-
-	return 0;
-}
-
-/* Get audio data from the drive.  This is fairly complex because I
-   am looking for status and data at the same time, but if I get status
-   then I just look for data.  I need to get the status immediately so
-   the switch from audio to data tracks will happen quickly. */
-static void
-read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
-{
-	unsigned long retry_count;
-	int result_read;
-
-
-	res_reg[0] = 0;
-	res_reg[1] = 0;
-	*res_size = 0;
-	result_read = 0;
-
-	/* Wait for the drive to tell us we have something */
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-      continue_read_audio_wait:
-	while (time_before(jiffies, retry_count) && !(is_data_ready())
-	       && !(is_result_ready() || result_read)) {
-		while (handle_sony_cd_attention());
-
-		sony_sleep();
-	}
-	if (!(is_data_ready())) {
-		if (is_result_ready() && !result_read) {
-			get_result(res_reg, res_size);
-
-			/* Read block status and continue waiting for data. */
-			if ((res_reg[0] & 0xf0) == 0x50) {
-				result_read = 1;
-				goto continue_read_audio_wait;
-			}
-			/* Invalid data from the drive.  Shut down the operation. */
-			else if ((res_reg[0] & 0xf0) != 0x20) {
-				printk(KERN_WARNING PFX "Got result that "
-						"should have been error: %d\n",
-				     res_reg[0]);
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_BAD_DATA_ERR;
-				*res_size = 2;
-			}
-			abort_read();
-		} else {
-			pr_debug(PFX "timeout out %d\n", __LINE__);
-			res_reg[0] = 0x20;
-			res_reg[1] = SONY_TIMEOUT_OP_ERR;
-			*res_size = 2;
-			abort_read();
-		}
-	} else {
-		clear_data_ready();
-
-		/* If data block, then get 2340 bytes offset by 12. */
-		if (sony_raw_data_mode) {
-			insb(sony_cd_read_reg, buffer + CD_XA_HEAD,
-			     CD_FRAMESIZE_RAW1);
-		} else {
-			/* Audio gets the whole 2352 bytes. */
-			insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW);
-		}
-
-		/* If I haven't already gotten the result, get it now. */
-		if (!result_read) {
-			/* Wait for the drive to tell us we have something */
-			retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-			while (time_before(jiffies, retry_count)
-			       && !(is_result_ready())) {
-				while (handle_sony_cd_attention());
-
-				sony_sleep();
-			}
-
-			if (!is_result_ready()) {
-				pr_debug(PFX "timeout out %d\n", __LINE__);
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_TIMEOUT_OP_ERR;
-				*res_size = 2;
-				abort_read();
-				return;
-			} else {
-				get_result(res_reg, res_size);
-			}
-		}
-
-		if ((res_reg[0] & 0xf0) == 0x50) {
-			if ((res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT)
-			    || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT)
-			    || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT)
-			    || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) {
-				/* Ok, nothing to do. */
-			} else {
-				printk(KERN_ERR PFX "Data block error: 0x%x\n",
-				       res_reg[0]);
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_BAD_DATA_ERR;
-				*res_size = 2;
-			}
-		} else if ((res_reg[0] & 0xf0) != 0x20) {
-			/* The drive gave me bad status, I don't know what to do.
-			   Reset the driver and return an error. */
-			printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n",
-			       res_reg[0]);
-			restart_on_error();
-			res_reg[0] = 0x20;
-			res_reg[1] = SONY_BAD_DATA_ERR;
-			*res_size = 2;
-		}
-	}
-}
-
-/* Perform a raw data read.  This will automatically detect the
-   track type and read the proper data (audio or data). */
-static int read_audio(struct cdrom_read_audio *ra)
-{
-	int retval;
-	unsigned char params[2];
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned int cframe;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	if (!sony_spun_up)
-		scd_spinup();
-
-	/* Set the drive to do raw operations. */
-	params[0] = SONY_SD_DECODE_PARAM;
-	params[1] = 0x06 | sony_raw_data_mode;
-	do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-		       params, 2, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n",
-		       res_reg[1]);
-		retval = -EIO;
-		goto out_up;
-	}
-
-	/* From here down, we have to goto exit_read_audio instead of returning
-	   because the drive parameters have to be set back to data before
-	   return. */
-
-	retval = 0;
-	if (start_request(ra->addr.lba, ra->nframes)) {
-		retval = -EIO;
-		goto exit_read_audio;
-	}
-
-	/* For every requested frame. */
-	cframe = 0;
-	while (cframe < ra->nframes) {
-		read_audio_data(audio_buffer, res_reg, &res_size);
-		if ((res_reg[0] & 0xf0) == 0x20) {
-			if (res_reg[1] == SONY_BAD_DATA_ERR) {
-				printk(KERN_ERR PFX "Data error on audio "
-						"sector %d\n",
-				     ra->addr.lba + cframe);
-			} else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) {
-				/* Illegal track type, change track types and start over. */
-				sony_raw_data_mode =
-				    (sony_raw_data_mode) ? 0 : 1;
-
-				/* Set the drive mode. */
-				params[0] = SONY_SD_DECODE_PARAM;
-				params[1] = 0x06 | sony_raw_data_mode;
-				do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-					       params,
-					       2, res_reg, &res_size);
-				if ((res_size < 2)
-				    || ((res_reg[0] & 0xf0) == 0x20)) {
-					printk(KERN_ERR PFX "Unable to set "
-						"decode params: 0x%2.2x\n",
-					     res_reg[1]);
-					retval = -EIO;
-					goto exit_read_audio;
-				}
-
-				/* Restart the request on the current frame. */
-				if (start_request
-				    (ra->addr.lba + cframe,
-				     ra->nframes - cframe)) {
-					retval = -EIO;
-					goto exit_read_audio;
-				}
-
-				/* Don't go back to the top because don't want to get into
-				   and infinite loop.  A lot of code gets duplicated, but
-				   that's no big deal, I don't guess. */
-				read_audio_data(audio_buffer, res_reg,
-						&res_size);
-				if ((res_reg[0] & 0xf0) == 0x20) {
-					if (res_reg[1] ==
-					    SONY_BAD_DATA_ERR) {
-						printk(KERN_ERR PFX "Data error"
-							" on audio sector %d\n",
-						     ra->addr.lba +
-						     cframe);
-					} else {
-						printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n",
-						     ra->addr.lba + cframe,
-						     translate_error
-						     (res_reg[1]));
-						retval = -EIO;
-						goto exit_read_audio;
-					}
-				} else if (copy_to_user(ra->buf +
-							       (CD_FRAMESIZE_RAW
-								* cframe),
-						        audio_buffer,
-							CD_FRAMESIZE_RAW)) {
-					retval = -EFAULT;
-					goto exit_read_audio;
-				}
-			} else {
-				printk(KERN_ERR PFX "Error reading audio "
-						"data on sector %d: %s\n",
-				     ra->addr.lba + cframe,
-				     translate_error(res_reg[1]));
-				retval = -EIO;
-				goto exit_read_audio;
-			}
-		} else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe),
-					(char *)audio_buffer,
-					CD_FRAMESIZE_RAW)) {
-			retval = -EFAULT;
-			goto exit_read_audio;
-		}
-
-		cframe++;
-	}
-
-	get_result(res_reg, &res_size);
-	if ((res_reg[0] & 0xf0) == 0x20) {
-		printk(KERN_ERR PFX "Error return from audio read: %s\n",
-		       translate_error(res_reg[1]));
-		retval = -EIO;
-		goto exit_read_audio;
-	}
-
-      exit_read_audio:
-
-	/* Set the drive mode back to the proper one for the disk. */
-	params[0] = SONY_SD_DECODE_PARAM;
-	if (!sony_xa_mode) {
-		params[1] = 0x0f;
-	} else {
-		params[1] = 0x07;
-	}
-	do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-		       params, 2, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n",
-		       res_reg[1]);
-		retval = -EIO;
-	}
-
- out_up:
-	up(&sony_sem);
-
-	return retval;
-}
-
-static int
-do_sony_cd_cmd_chk(const char *name,
-		   unsigned char cmd,
-		   unsigned char *params,
-		   unsigned int num_params,
-		   unsigned char *result_buffer, unsigned int *result_size)
-{
-	do_sony_cd_cmd(cmd, params, num_params, result_buffer,
-		       result_size);
-	if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) {
-		printk(KERN_ERR PFX "Error %s (CDROM%s)\n",
-		       translate_error(result_buffer[1]), name);
-		return -EIO;
-	}
-	return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * open the tray
- */
-static int scd_tray_move(struct cdrom_device_info *cdi, int position)
-{
-	int retval;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	if (position == 1 /* open tray */ ) {
-		unsigned char res_reg[12];
-		unsigned int res_size;
-
-		do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-			       &res_size);
-		do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		sony_audio_status = CDROM_AUDIO_INVALID;
-		retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
-					  res_reg, &res_size);
-	} else {
-		if (0 == scd_spinup())
-			sony_spun_up = 1;
-		retval = 0;
-	}
-	up(&sony_sem);
-	return retval;
-}
-
-/*
- * The big ugly ioctl handler.
- */
-static int scd_audio_ioctl(struct cdrom_device_info *cdi,
-			   unsigned int cmd, void *arg)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned char params[7];
-	int i, retval;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	switch (cmd) {
-	case CDROMSTART:	/* Spin up the drive */
-		retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
-					  0, res_reg, &res_size);
-		break;
-
-	case CDROMSTOP:	/* Spin down the drive */
-		do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		/*
-		 * Spin the drive down, ignoring the error if the disk was
-		 * already not spinning.
-		 */
-		sony_audio_status = CDROM_AUDIO_NO_STATUS;
-		retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
-					  0, res_reg, &res_size);
-		break;
-
-	case CDROMPAUSE:	/* Pause the drive */
-		if (do_sony_cd_cmd_chk
-		    ("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-		     &res_size)) {
-			retval = -EIO;
-			break;
-		}
-		/* Get the current position and save it for resuming */
-		if (read_subcode() < 0) {
-			retval = -EIO;
-			break;
-		}
-		cur_pos_msf[0] = last_sony_subcode.abs_msf[0];
-		cur_pos_msf[1] = last_sony_subcode.abs_msf[1];
-		cur_pos_msf[2] = last_sony_subcode.abs_msf[2];
-		sony_audio_status = CDROM_AUDIO_PAUSED;
-		retval = 0;
-		break;
-
-	case CDROMRESUME:	/* Start the drive after being paused */
-		if (sony_audio_status != CDROM_AUDIO_PAUSED) {
-			retval = -EINVAL;
-			break;
-		}
-
-		do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		/* Start the drive at the saved position. */
-		params[1] = int_to_bcd(cur_pos_msf[0]);
-		params[2] = int_to_bcd(cur_pos_msf[1]);
-		params[3] = int_to_bcd(cur_pos_msf[2]);
-		params[4] = int_to_bcd(final_pos_msf[0]);
-		params[5] = int_to_bcd(final_pos_msf[1]);
-		params[6] = int_to_bcd(final_pos_msf[2]);
-		params[0] = 0x03;
-		if (do_sony_cd_cmd_chk
-		    ("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg,
-		     &res_size) < 0) {
-			retval = -EIO;
-			break;
-		}
-		sony_audio_status = CDROM_AUDIO_PLAY;
-		retval = 0;
-		break;
-
-	case CDROMPLAYMSF:	/* Play starting at the given MSF address. */
-		do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		/* The parameters are given in int, must be converted */
-		for (i = 1; i < 7; i++) {
-			params[i] =
-			    int_to_bcd(((unsigned char *) arg)[i - 1]);
-		}
-		params[0] = 0x03;
-		if (do_sony_cd_cmd_chk
-		    ("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7,
-		     res_reg, &res_size) < 0) {
-			retval = -EIO;
-			break;
-		}
-
-		/* Save the final position for pauses and resumes */
-		final_pos_msf[0] = bcd_to_int(params[4]);
-		final_pos_msf[1] = bcd_to_int(params[5]);
-		final_pos_msf[2] = bcd_to_int(params[6]);
-		sony_audio_status = CDROM_AUDIO_PLAY;
-		retval = 0;
-		break;
-
-	case CDROMREADTOCHDR:	/* Read the table of contents header */
-		{
-			struct cdrom_tochdr *hdr;
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				retval = -EIO;
-				break;
-			}
-
-			hdr = (struct cdrom_tochdr *) arg;
-			hdr->cdth_trk0 = sony_toc.first_track_num;
-			hdr->cdth_trk1 = sony_toc.last_track_num;
-		}
-		retval = 0;
-		break;
-
-	case CDROMREADTOCENTRY:	/* Read a given table of contents entry */
-		{
-			struct cdrom_tocentry *entry;
-			int track_idx;
-			unsigned char *msf_val = NULL;
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				retval = -EIO;
-				break;
-			}
-
-			entry = (struct cdrom_tocentry *) arg;
-
-			track_idx = find_track(entry->cdte_track);
-			if (track_idx < 0) {
-				retval = -EINVAL;
-				break;
-			}
-
-			entry->cdte_adr =
-			    sony_toc.tracks[track_idx].address;
-			entry->cdte_ctrl =
-			    sony_toc.tracks[track_idx].control;
-			msf_val =
-			    sony_toc.tracks[track_idx].track_start_msf;
-
-			/* Logical buffer address or MSF format requested? */
-			if (entry->cdte_format == CDROM_LBA) {
-				entry->cdte_addr.lba = msf_to_log(msf_val);
-			} else if (entry->cdte_format == CDROM_MSF) {
-				entry->cdte_addr.msf.minute = *msf_val;
-				entry->cdte_addr.msf.second =
-				    *(msf_val + 1);
-				entry->cdte_addr.msf.frame =
-				    *(msf_val + 2);
-			}
-		}
-		retval = 0;
-		break;
-
-	case CDROMPLAYTRKIND:	/* Play a track.  This currently ignores index. */
-		{
-			struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-			int track_idx;
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				retval = -EIO;
-				break;
-			}
-
-			if ((ti->cdti_trk0 < sony_toc.first_track_num)
-			    || (ti->cdti_trk0 > sony_toc.last_track_num)
-			    || (ti->cdti_trk1 < ti->cdti_trk0)) {
-				retval = -EINVAL;
-				break;
-			}
-
-			track_idx = find_track(ti->cdti_trk0);
-			if (track_idx < 0) {
-				retval = -EINVAL;
-				break;
-			}
-			params[1] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[0]);
-			params[2] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[1]);
-			params[3] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[2]);
-
-			/*
-			 * If we want to stop after the last track, use the lead-out
-			 * MSF to do that.
-			 */
-			if (ti->cdti_trk1 >= sony_toc.last_track_num) {
-				track_idx = find_track(CDROM_LEADOUT);
-			} else {
-				track_idx = find_track(ti->cdti_trk1 + 1);
-			}
-			if (track_idx < 0) {
-				retval = -EINVAL;
-				break;
-			}
-			params[4] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[0]);
-			params[5] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[1]);
-			params[6] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[2]);
-			params[0] = 0x03;
-
-			do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-				       &res_size);
-
-			do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7,
-				       res_reg, &res_size);
-
-			if ((res_size < 2)
-			    || ((res_reg[0] & 0xf0) == 0x20)) {
-				printk(KERN_ERR PFX
-					"Params: %x %x %x %x %x %x %x\n",
-				       params[0], params[1], params[2],
-				       params[3], params[4], params[5],
-				       params[6]);
-				printk(KERN_ERR PFX
-					"Error %s (CDROMPLAYTRKIND)\n",
-				     translate_error(res_reg[1]));
-				retval = -EIO;
-				break;
-			}
-
-			/* Save the final position for pauses and resumes */
-			final_pos_msf[0] = bcd_to_int(params[4]);
-			final_pos_msf[1] = bcd_to_int(params[5]);
-			final_pos_msf[2] = bcd_to_int(params[6]);
-			sony_audio_status = CDROM_AUDIO_PLAY;
-			retval = 0;
-			break;
-		}
-
-	case CDROMVOLCTRL:	/* Volume control.  What volume does this change, anyway? */
-		{
-			struct cdrom_volctrl *volctrl =
-			    (struct cdrom_volctrl *) arg;
-
-			params[0] = SONY_SD_AUDIO_VOLUME;
-			params[1] = volctrl->channel0;
-			params[2] = volctrl->channel1;
-			retval = do_sony_cd_cmd_chk("VOLCTRL",
-						  SONY_SET_DRIVE_PARAM_CMD,
-						  params, 3, res_reg,
-						  &res_size);
-			break;
-		}
-	case CDROMSUBCHNL:	/* Get subchannel info */
-		retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg);
-		break;
-
-	default:
-		retval = -EINVAL;
-		break;
-	}
-	up(&sony_sem);
-	return retval;
-}
-
-static int scd_read_audio(struct cdrom_device_info *cdi,
-			 unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	int retval;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	switch (cmd) {
-	case CDROMREADAUDIO:	/* Read 2352 byte audio tracks and 2340 byte
-				   raw data tracks. */
-		{
-			struct cdrom_read_audio ra;
-
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				retval = -EIO;
-				break;
-			}
-
-			if (copy_from_user(&ra, argp, sizeof(ra))) {
-				retval = -EFAULT;
-				break;
-			}
-
-			if (ra.nframes == 0) {
-				retval = 0;
-				break;
-			}
-
-			if (!access_ok(VERIFY_WRITE, ra.buf,
-					CD_FRAMESIZE_RAW * ra.nframes))
-				return -EFAULT;
-
-			if (ra.addr_format == CDROM_LBA) {
-				if ((ra.addr.lba >=
-				     sony_toc.lead_out_start_lba)
-				    || (ra.addr.lba + ra.nframes >=
-					sony_toc.lead_out_start_lba)) {
-					retval = -EINVAL;
-					break;
-				}
-			} else if (ra.addr_format == CDROM_MSF) {
-				if ((ra.addr.msf.minute >= 75)
-				    || (ra.addr.msf.second >= 60)
-				    || (ra.addr.msf.frame >= 75)) {
-					retval = -EINVAL;
-					break;
-				}
-
-				ra.addr.lba = ((ra.addr.msf.minute * 4500)
-					       + (ra.addr.msf.second * 75)
-					       + ra.addr.msf.frame);
-				if ((ra.addr.lba >=
-				     sony_toc.lead_out_start_lba)
-				    || (ra.addr.lba + ra.nframes >=
-					sony_toc.lead_out_start_lba)) {
-					retval = -EINVAL;
-					break;
-				}
-
-				/* I know, this can go negative on an unsigned.  However,
-				   the first thing done to the data is to add this value,
-				   so this should compensate and allow direct msf access. */
-				ra.addr.lba -= LOG_START_OFFSET;
-			} else {
-				retval = -EINVAL;
-				break;
-			}
-
-			retval = read_audio(&ra);
-			break;
-		}
-		retval = 0;
-		break;
-
-	default:
-		retval = -EINVAL;
-	}
-	up(&sony_sem);
-	return retval;
-}
-
-static int scd_spinup(void)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	int num_spin_ups;
-
-	num_spin_ups = 0;
-
-      respinup_on_open:
-	do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-
-	/* The drive sometimes returns error 0.  I don't know why, but ignore
-	   it.  It seems to mean the drive has already done the operation. */
-	if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-		printk(KERN_ERR PFX "%s error (scd_open, spin up)\n",
-		       translate_error(res_reg[1]));
-		return 1;
-	}
-
-	do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
-
-	/* The drive sometimes returns error 0.  I don't know why, but ignore
-	   it.  It seems to mean the drive has already done the operation. */
-	if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-		/* If the drive is already playing, it's ok.  */
-		if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
-		    || (res_reg[1] == 0)) {
-			return 0;
-		}
-
-		/* If the drive says it is not spun up (even though we just did it!)
-		   then retry the operation at least a few times. */
-		if ((res_reg[1] == SONY_NOT_SPIN_ERR)
-		    && (num_spin_ups < MAX_CDU31A_RETRIES)) {
-			num_spin_ups++;
-			goto respinup_on_open;
-		}
-
-		printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n",
-		       translate_error(res_reg[1]));
-		do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-			       &res_size);
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Open the drive for operations.  Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int scd_open(struct cdrom_device_info *cdi, int purpose)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned char params[2];
-
-	if (purpose == 1) {
-		/* Open for IOCTLs only - no media check */
-		sony_usage++;
-		return 0;
-	}
-
-	if (sony_usage == 0) {
-		if (scd_spinup() != 0)
-			return -EIO;
-		sony_get_toc();
-		if (!sony_toc_read) {
-			do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0,
-				       res_reg, &res_size);
-			return -EIO;
-		}
-
-		/* For XA on the CDU31A only, we have to do special reads.
-		   The CDU33A handles XA automagically. */
-		/* if (   (sony_toc.disk_type == SONY_XA_DISK_TYPE) */
-		if ((sony_toc.disk_type != 0x00)
-		    && (!is_double_speed)) {
-			params[0] = SONY_SD_DECODE_PARAM;
-			params[1] = 0x07;
-			do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-				       params, 2, res_reg, &res_size);
-			if ((res_size < 2)
-			    || ((res_reg[0] & 0xf0) == 0x20)) {
-				printk(KERN_WARNING PFX "Unable to set "
-					"XA params: 0x%2.2x\n", res_reg[1]);
-			}
-			sony_xa_mode = 1;
-		}
-		/* A non-XA disk.  Set the parms back if necessary. */
-		else if (sony_xa_mode) {
-			params[0] = SONY_SD_DECODE_PARAM;
-			params[1] = 0x0f;
-			do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-				       params, 2, res_reg, &res_size);
-			if ((res_size < 2)
-			    || ((res_reg[0] & 0xf0) == 0x20)) {
-				printk(KERN_WARNING PFX "Unable to reset "
-					"XA params: 0x%2.2x\n", res_reg[1]);
-			}
-			sony_xa_mode = 0;
-		}
-
-		sony_spun_up = 1;
-	}
-
-	sony_usage++;
-
-	return 0;
-}
-
-
-/*
- * Close the drive.  Spin it down if no task is using it.  The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static void scd_release(struct cdrom_device_info *cdi)
-{
-	if (sony_usage == 1) {
-		unsigned char res_reg[12];
-		unsigned int res_size;
-
-		do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		sony_spun_up = 0;
-	}
-	sony_usage--;
-}
-
-static struct cdrom_device_ops scd_dops = {
-	.open			= scd_open,
-	.release		= scd_release,
-	.drive_status		= scd_drive_status,
-	.media_changed		= scd_media_changed,
-	.tray_move		= scd_tray_move,
-	.lock_door		= scd_lock_door,
-	.select_speed		= scd_select_speed,
-	.get_last_session	= scd_get_last_session,
-	.get_mcn		= scd_get_mcn,
-	.reset			= scd_reset,
-	.audio_ioctl		= scd_audio_ioctl,
-	.capability		= CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
-				  CDC_SELECT_SPEED | CDC_MULTI_SESSION |
-				  CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
-				  CDC_RESET | CDC_DRIVE_STATUS,
-	.n_minors		= 1,
-};
-
-static struct cdrom_device_info scd_info = {
-	.ops		= &scd_dops,
-	.speed		= 2,
-	.capacity	= 1,
-	.name		= "cdu31a"
-};
-
-static int scd_block_open(struct inode *inode, struct file *file)
-{
-	return cdrom_open(&scd_info, inode, file);
-}
-
-static int scd_block_release(struct inode *inode, struct file *file)
-{
-	return cdrom_release(&scd_info, file);
-}
-
-static int scd_block_ioctl(struct inode *inode, struct file *file,
-				unsigned cmd, unsigned long arg)
-{
-	int retval;
-
-	/* The eject and close commands should be handled by Uniform CD-ROM
-	 * driver - but I always got hard lockup instead of eject
-	 * until I put this here.
-	 */
-	switch (cmd) {
-		case CDROMEJECT:
-			scd_lock_door(&scd_info, 0);
-			retval = scd_tray_move(&scd_info, 1);
-			break;
-		case CDROMCLOSETRAY:
-			retval = scd_tray_move(&scd_info, 0);
-			break;
-		case CDROMREADAUDIO:
-			retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg);
-			break;
-		default:
-			retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
-	}
-	return retval;
-}
-
-static int scd_block_media_changed(struct gendisk *disk)
-{
-	return cdrom_media_changed(&scd_info);
-}
-
-static struct block_device_operations scd_bdops =
-{
-	.owner		= THIS_MODULE,
-	.open		= scd_block_open,
-	.release	= scd_block_release,
-	.ioctl		= scd_block_ioctl,
-	.media_changed	= scd_block_media_changed,
-};
-
-static struct gendisk *scd_gendisk;
-
-/* The different types of disc loading mechanisms supported */
-static char *load_mech[] __initdata =
-    { "caddy", "tray", "pop-up", "unknown" };
-
-static int __init
-get_drive_configuration(unsigned short base_io,
-			unsigned char res_reg[], unsigned int *res_size)
-{
-	unsigned long retry_count;
-
-
-	if (!request_region(base_io, 4, "cdu31a"))
-		return 0;
-
-	/* Set the base address */
-	cdu31a_port = base_io;
-
-	/* Set up all the register locations */
-	sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET;
-	sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET;
-	sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET;
-	sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET;
-	sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET;
-	sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET;
-	sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET;
-	sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET;
-
-	/*
-	 * Check to see if anything exists at the status register location.
-	 * I don't know if this is a good way to check, but it seems to work
-	 * ok for me.
-	 */
-	if (read_status_register() != 0xff) {
-		/*
-		 * Reset the drive and wait for attention from it (to say it's reset).
-		 * If you don't wait, the next operation will probably fail.
-		 */
-		reset_drive();
-		retry_count = jiffies + SONY_RESET_TIMEOUT;
-		while (time_before(jiffies, retry_count)
-		       && (!is_attention())) {
-			sony_sleep();
-		}
-
-#if 0
-		/* If attention is never seen probably not a CDU31a present */
-		if (!is_attention()) {
-			res_reg[0] = 0x20;
-			goto out_err;
-		}
-#endif
-
-		/*
-		 * Get the drive configuration.
-		 */
-		do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
-			       NULL,
-			       0, (unsigned char *) res_reg, res_size);
-		if (*res_size <= 2 || (res_reg[0] & 0xf0) != 0)
-			goto out_err;
-		return 1;
-	}
-
-	/* Return an error */
-	res_reg[0] = 0x20;
-out_err:
-	release_region(cdu31a_port, 4);
-	cdu31a_port = 0;
-	return 0;
-}
-
-#ifndef MODULE
-/*
- * Set up base I/O and interrupts, called from main.c.
- */
-
-static int __init cdu31a_setup(char *strings)
-{
-	int ints[4];
-
-	(void) get_options(strings, ARRAY_SIZE(ints), ints);
-
-	if (ints[0] > 0) {
-		cdu31a_port = ints[1];
-	}
-	if (ints[0] > 1) {
-		cdu31a_irq = ints[2];
-	}
-	if ((strings != NULL) && (*strings != '\0')) {
-		if (strcmp(strings, "PAS") == 0) {
-			sony_pas_init = 1;
-		} else {
-			printk(KERN_NOTICE PFX "Unknown interface type: %s\n",
-			       strings);
-		}
-	}
-
-	return 1;
-}
-
-__setup("cdu31a=", cdu31a_setup);
-
-#endif
-
-/*
- * Initialize the driver.
- */
-int __init cdu31a_init(void)
-{
-	struct s_sony_drive_config drive_config;
-	struct gendisk *disk;
-	int deficiency = 0;
-	unsigned int res_size;
-	char msg[255];
-	char buf[40];
-	int i;
-	int tmp_irq;
-
-	/*
-	 * According to Alex Freed (freed@europa.orion.adobe.com), this is
-	 * required for the Fusion CD-16 package.  If the sound driver is
-	 * loaded, it should work fine, but just in case...
-	 *
-	 * The following turn on the CD-ROM interface for a Fusion CD-16.
-	 */
-	if (sony_pas_init) {
-		outb(0xbc, 0x9a01);
-		outb(0xe2, 0x9a01);
-	}
-
-	/* Setting the base I/O address to 0xffff will disable it. */
-	if (cdu31a_port == 0xffff)
-		goto errout3;
-
-	if (cdu31a_port != 0) {
-		/* Need IRQ 0 because we can't sleep here. */
-		tmp_irq = cdu31a_irq;
-		cdu31a_irq = 0;
-		if (!get_drive_configuration(cdu31a_port,
-					    drive_config.exec_status,
-					    &res_size))
-			goto errout3;
-		cdu31a_irq = tmp_irq;
-	} else {
-		cdu31a_irq = 0;
-		for (i = 0; cdu31a_addresses[i].base; i++) {
-			if (get_drive_configuration(cdu31a_addresses[i].base,
-						     drive_config.exec_status,
-						     &res_size)) {
-				cdu31a_irq = cdu31a_addresses[i].int_num;
-				break;
-			}
-		}
-		if (!cdu31a_port)
-			goto errout3;
-	}
-
-	if (register_blkdev(MAJOR_NR, "cdu31a"))
-		goto errout2;
-
-	disk = alloc_disk(1);
-	if (!disk)
-		goto errout1;
-	disk->major = MAJOR_NR;
-	disk->first_minor = 0;
-	sprintf(disk->disk_name, "cdu31a");
-	disk->fops = &scd_bdops;
-	disk->flags = GENHD_FL_CD;
-
-	if (SONY_HWC_DOUBLE_SPEED(drive_config))
-		is_double_speed = 1;
-
-	tmp_irq = cdu31a_irq;	/* Need IRQ 0 because we can't sleep here. */
-	cdu31a_irq = 0;
-
-	sony_speed = is_double_speed; /* Set 2X drives to 2X by default */
-	set_drive_params(sony_speed);
-
-	cdu31a_irq = tmp_irq;
-
-	if (cdu31a_irq > 0) {
-		if (request_irq
-		    (cdu31a_irq, cdu31a_interrupt, IRQF_DISABLED,
-		     "cdu31a", NULL)) {
-			printk(KERN_WARNING PFX "Unable to grab IRQ%d for "
-					"the CDU31A driver\n", cdu31a_irq);
-			cdu31a_irq = 0;
-		}
-	}
-
-	sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
-		drive_config.vendor_id,
-		drive_config.product_id,
-		drive_config.product_rev_level);
-	sprintf(buf, "  Capabilities: %s",
-		load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
-	strcat(msg, buf);
-	if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
-		strcat(msg, ", audio");
-	else
-		deficiency |= CDC_PLAY_AUDIO;
-	if (SONY_HWC_EJECT(drive_config))
-		strcat(msg, ", eject");
-	else
-		deficiency |= CDC_OPEN_TRAY;
-	if (SONY_HWC_LED_SUPPORT(drive_config))
-		strcat(msg, ", LED");
-	if (SONY_HWC_ELECTRIC_VOLUME(drive_config))
-		strcat(msg, ", elec. Vol");
-	if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config))
-		strcat(msg, ", sep. Vol");
-	if (is_double_speed)
-		strcat(msg, ", double speed");
-	else
-		deficiency |= CDC_SELECT_SPEED;
-	if (cdu31a_irq > 0) {
-		sprintf(buf, ", irq %d", cdu31a_irq);
-		strcat(msg, buf);
-	}
-	strcat(msg, "\n");
-	printk(KERN_INFO PFX "%s",msg);
-
-	cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock);
-	if (!cdu31a_queue)
-		goto errout0;
-	blk_queue_hardsect_size(cdu31a_queue, 2048);
-
-	init_timer(&cdu31a_abort_timer);
-	cdu31a_abort_timer.function = handle_abort_timeout;
-
-	scd_info.mask = deficiency;
-	scd_gendisk = disk;
-	if (register_cdrom(&scd_info))
-		goto err;
-	disk->queue = cdu31a_queue;
-	add_disk(disk);
-
-	disk_changed = 1;
-	return 0;
-
-err:
-	blk_cleanup_queue(cdu31a_queue);
-errout0:
-	if (cdu31a_irq)
-		free_irq(cdu31a_irq, NULL);
-	printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n");
-	put_disk(disk);
-errout1:
-	if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
-		printk(KERN_WARNING PFX "Can't unregister block device\n");
-	}
-errout2:
-	release_region(cdu31a_port, 4);
-errout3:
-	return -EIO;
-}
-
-
-static void __exit cdu31a_exit(void)
-{
-	del_gendisk(scd_gendisk);
-	put_disk(scd_gendisk);
-	if (unregister_cdrom(&scd_info)) {
-		printk(KERN_WARNING PFX "Can't unregister from Uniform "
-				"cdrom driver\n");
-		return;
-	}
-	if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
-		printk(KERN_WARNING PFX "Can't unregister\n");
-		return;
-	}
-
-	blk_cleanup_queue(cdu31a_queue);
-
-	if (cdu31a_irq > 0)
-		free_irq(cdu31a_irq, NULL);
-
-	release_region(cdu31a_port, 4);
-	printk(KERN_INFO PFX "module released.\n");
-}
-
-#ifdef MODULE
-module_init(cdu31a_init);
-#endif
-module_exit(cdu31a_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU31A_CDROM_MAJOR);
diff --git a/drivers/cdrom/cdu31a.h b/drivers/cdrom/cdu31a.h
deleted file mode 100644
index 61d4768..0000000
--- a/drivers/cdrom/cdu31a.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Definitions for a Sony interface CDROM drive.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com)
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/*
- * General defines.
- */
-#define SONY_XA_DISK_TYPE 0x20
-
-/*
- * Offsets (from the base address) and bits for the various write registers
- * of the drive.
- */
-#define SONY_CMD_REG_OFFSET     0
-#define SONY_PARAM_REG_OFFSET   1
-#define SONY_WRITE_REG_OFFSET   2
-#define SONY_CONTROL_REG_OFFSET 3
-#       define SONY_ATTN_CLR_BIT        0x01
-#       define SONY_RES_RDY_CLR_BIT     0x02
-#       define SONY_DATA_RDY_CLR_BIT    0x04
-#       define SONY_ATTN_INT_EN_BIT     0x08
-#       define SONY_RES_RDY_INT_EN_BIT  0x10
-#       define SONY_DATA_RDY_INT_EN_BIT 0x20
-#       define SONY_PARAM_CLR_BIT       0x40
-#       define SONY_DRIVE_RESET_BIT     0x80
-
-/*
- * Offsets (from the base address) and bits for the various read registers
- * of the drive.
- */
-#define SONY_STATUS_REG_OFFSET  0
-#       define SONY_ATTN_BIT            0x01
-#       define SONY_RES_RDY_BIT         0x02
-#       define SONY_DATA_RDY_BIT        0x04
-#       define SONY_ATTN_INT_ST_BIT     0x08
-#       define SONY_RES_RDY_INT_ST_BIT  0x10
-#       define SONY_DATA_RDY_INT_ST_BIT 0x20
-#       define SONY_DATA_REQUEST_BIT    0x40
-#       define SONY_BUSY_BIT            0x80
-#define SONY_RESULT_REG_OFFSET  1
-#define SONY_READ_REG_OFFSET    2
-#define SONY_FIFOST_REG_OFFSET  3
-#       define SONY_PARAM_WRITE_RDY_BIT 0x01
-#       define SONY_PARAM_REG_EMPTY_BIT 0x02
-#       define SONY_RES_REG_NOT_EMP_BIT 0x04
-#       define SONY_RES_REG_FULL_BIT    0x08
-
-#define LOG_START_OFFSET        150     /* Offset of first logical sector */
-
-#define SONY_DETECT_TIMEOUT	(8*HZ/10) /* Maximum amount of time
-                                           that drive detection code
-                                           will wait for response
-                                           from drive (in 1/100th's
-                                           of seconds). */
- 
-#define SONY_JIFFIES_TIMEOUT    (10*HZ)	/* Maximum number of times the
-                                           drive will wait/try for an
-                                           operation */
-#define SONY_RESET_TIMEOUT      HZ	/* Maximum number of times the
-                                           drive will wait/try a reset
-                                           operation */
-#define SONY_READY_RETRIES      20000   /* How many times to retry a
-                                           spin waiting for a register
-                                           to come ready */
-
-#define MAX_CDU31A_RETRIES      3       /* How many times to retry an
-                                           operation */
-
-/* Commands to request or set drive control parameters and disc information */
-#define SONY_REQ_DRIVE_CONFIG_CMD       0x00    /* Returns s_sony_drive_config */
-#define SONY_REQ_DRIVE_MODE_CMD         0x01
-#define SONY_REQ_DRIVE_PARAM_CMD        0x02
-#define SONY_REQ_MECH_STATUS_CMD        0x03
-#define SONY_REQ_AUDIO_STATUS_CMD       0x04
-#define SONY_SET_DRIVE_PARAM_CMD        0x10
-#define SONY_REQ_TOC_DATA_CMD           0x20    /* Returns s_sony_toc */
-#define SONY_REQ_SUBCODE_ADDRESS_CMD    0x21    /* Returns s_sony_subcode */
-#define SONY_REQ_UPC_EAN_CMD            0x22
-#define SONY_REQ_ISRC_CMD               0x23
-#define SONY_REQ_TOC_DATA_SPEC_CMD      0x24    /* Returns s_sony_session_toc */
-
-/* Commands to request information from the drive */
-#define SONY_READ_TOC_CMD               0x30    /* let the drive firmware grab the TOC */
-#define SONY_SEEK_CMD                   0x31
-#define SONY_READ_CMD                   0x32
-#define SONY_READ_BLKERR_STAT_CMD       0x34
-#define SONY_ABORT_CMD                  0x35
-#define SONY_READ_TOC_SPEC_CMD          0x36
-
-/* Commands to control audio */
-#define SONY_AUDIO_PLAYBACK_CMD         0x40
-#define SONY_AUDIO_STOP_CMD             0x41
-#define SONY_AUDIO_SCAN_CMD             0x42
-
-/* Miscellaneous control commands */
-#define SONY_EJECT_CMD                  0x50
-#define SONY_SPIN_UP_CMD                0x51
-#define SONY_SPIN_DOWN_CMD              0x52
-
-/* Diagnostic commands */
-#define SONY_WRITE_BUFFER_CMD           0x60
-#define SONY_READ_BUFFER_CMD            0x61
-#define SONY_DIAGNOSTICS_CMD            0x62
-
-
-/*
- * The following are command parameters for the set drive parameter command
- */
-#define SONY_SD_DECODE_PARAM            0x00
-#define SONY_SD_INTERFACE_PARAM         0x01
-#define SONY_SD_BUFFERING_PARAM         0x02
-#define SONY_SD_AUDIO_PARAM             0x03
-#define SONY_SD_AUDIO_VOLUME            0x04
-#define SONY_SD_MECH_CONTROL            0x05
-#define SONY_SD_AUTO_SPIN_DOWN_TIME     0x06
-
-/*
- * The following are parameter bits for the mechanical control command
- */
-#define SONY_AUTO_SPIN_UP_BIT           0x01
-#define SONY_AUTO_EJECT_BIT             0x02
-#define SONY_DOUBLE_SPEED_BIT           0x04
-
-/*
- * The following extract information from the drive configuration about
- * the drive itself.
- */
-#define SONY_HWC_GET_LOAD_MECH(c)       (c.hw_config[0] & 0x03)
-#define SONY_HWC_EJECT(c)               (c.hw_config[0] & 0x04)
-#define SONY_HWC_LED_SUPPORT(c)         (c.hw_config[0] & 0x08)
-#define SONY_HWC_DOUBLE_SPEED(c)        (c.hw_config[0] & 0x10)
-#define SONY_HWC_GET_BUF_MEM_SIZE(c)    ((c.hw_config[0] & 0xc0) >> 6)
-#define SONY_HWC_AUDIO_PLAYBACK(c)      (c.hw_config[1] & 0x01)
-#define SONY_HWC_ELECTRIC_VOLUME(c)     (c.hw_config[1] & 0x02)
-#define SONY_HWC_ELECTRIC_VOLUME_CTL(c) (c.hw_config[1] & 0x04)
-
-#define SONY_HWC_CADDY_LOAD_MECH        0x00
-#define SONY_HWC_TRAY_LOAD_MECH         0x01
-#define SONY_HWC_POPUP_LOAD_MECH        0x02
-#define SONY_HWC_UNKWN_LOAD_MECH        0x03
-
-#define SONY_HWC_8KB_BUFFER             0x00
-#define SONY_HWC_32KB_BUFFER            0x01
-#define SONY_HWC_64KB_BUFFER            0x02
-#define SONY_HWC_UNKWN_BUFFER           0x03
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s_sony_drive_config
-{
-   unsigned char exec_status[2];
-   char vendor_id[8];
-   char product_id[16];
-   char product_rev_level[8];
-   unsigned char hw_config[2];
-};
-
-/* The following is returned from the request subcode address command */
-struct s_sony_subcode
-{
-   unsigned char exec_status[2];
-   unsigned char address        :4;
-   unsigned char control        :4;
-   unsigned char track_num;
-   unsigned char index_num;
-   unsigned char rel_msf[3];
-   unsigned char reserved1;
-   unsigned char abs_msf[3];
-};
-
-#define MAX_TRACKS 100	/* The maximum tracks a disk may have. */
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s_sony_toc
-{
-   unsigned char exec_status[2];
-   unsigned char address0       :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char disk_type;
-   unsigned char dummy0;
-   unsigned char address1       :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char address2       :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int lead_out_start_lba;
-};
-
-struct s_sony_session_toc
-{
-   unsigned char exec_status[2];
-   unsigned char session_number;
-   unsigned char address0       :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char disk_type;
-   unsigned char dummy0;
-   unsigned char address1       :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char address2       :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   unsigned char addressb0      :4;
-   unsigned char controlb0      :4;
-   unsigned char pointb0;
-   unsigned char next_poss_prog_area_msf[3];
-   unsigned char num_mode_5_pointers;
-   unsigned char max_start_outer_leadout_msf[3];
-   unsigned char addressb1      :4;
-   unsigned char controlb1      :4;
-   unsigned char pointb1;
-   unsigned char dummyb0_1[4];
-   unsigned char num_skip_interval_pointers;
-   unsigned char num_skip_track_assignments;
-   unsigned char dummyb0_2;
-   unsigned char addressb2      :4;
-   unsigned char controlb2      :4;
-   unsigned char pointb2;
-   unsigned char tracksb2[7];
-   unsigned char addressb3      :4;
-   unsigned char controlb3      :4;
-   unsigned char pointb3;
-   unsigned char tracksb3[7];
-   unsigned char addressb4      :4;
-   unsigned char controlb4      :4;
-   unsigned char pointb4;
-   unsigned char tracksb4[7];
-   unsigned char addressc0      :4;
-   unsigned char controlc0      :4;
-   unsigned char pointc0;
-   unsigned char dummyc0[7];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int start_track_lba;
-   unsigned int lead_out_start_lba;
-   unsigned int mint;
-   unsigned int maxt;
-};
-
-struct s_all_sessions_toc
-{
-   unsigned char sessions;
-   unsigned int track_entries;
-   unsigned char first_track_num;
-   unsigned char last_track_num;
-   unsigned char disk_type;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int start_track_lba;
-   unsigned int lead_out_start_lba;
-};
-
-
-/*
- * The following are errors returned from the drive.
- */
-
-/* Command error group */
-#define SONY_ILL_CMD_ERR                0x10
-#define SONY_ILL_PARAM_ERR              0x11
-
-/* Mechanism group */
-#define SONY_NOT_LOAD_ERR               0x20
-#define SONY_NO_DISK_ERR                0x21
-#define SONY_NOT_SPIN_ERR               0x22
-#define SONY_SPIN_ERR                   0x23
-#define SONY_SPINDLE_SERVO_ERR          0x25
-#define SONY_FOCUS_SERVO_ERR            0x26
-#define SONY_EJECT_MECH_ERR             0x29
-#define SONY_AUDIO_PLAYING_ERR          0x2a
-#define SONY_EMERGENCY_EJECT_ERR        0x2c
-
-/* Seek error group */
-#define SONY_FOCUS_ERR                  0x30
-#define SONY_FRAME_SYNC_ERR             0x31
-#define SONY_SUBCODE_ADDR_ERR           0x32
-#define SONY_BLOCK_SYNC_ERR             0x33
-#define SONY_HEADER_ADDR_ERR            0x34
-
-/* Read error group */
-#define SONY_ILL_TRACK_R_ERR            0x40
-#define SONY_MODE_0_R_ERR               0x41
-#define SONY_ILL_MODE_R_ERR             0x42
-#define SONY_ILL_BLOCK_SIZE_R_ERR       0x43
-#define SONY_MODE_R_ERR                 0x44
-#define SONY_FORM_R_ERR                 0x45
-#define SONY_LEAD_OUT_R_ERR             0x46
-#define SONY_BUFFER_OVERRUN_R_ERR       0x47
-
-/* Data error group */
-#define SONY_UNREC_CIRC_ERR             0x53
-#define SONY_UNREC_LECC_ERR             0x57
-
-/* Subcode error group */
-#define SONY_NO_TOC_ERR                 0x60
-#define SONY_SUBCODE_DATA_NVAL_ERR      0x61
-#define SONY_FOCUS_ON_TOC_READ_ERR      0x63
-#define SONY_FRAME_SYNC_ON_TOC_READ_ERR 0x64
-#define SONY_TOC_DATA_ERR               0x65
-
-/* Hardware failure group */
-#define SONY_HW_FAILURE_ERR             0x70
-#define SONY_LEAD_IN_A_ERR              0x91
-#define SONY_LEAD_OUT_A_ERR             0x92
-#define SONY_DATA_TRACK_A_ERR           0x93
-
-/*
- * The following are returned from the Read With Block Error Status command.
- * They are not errors but information (Errors from the 0x5x group above may
- * also be returned
- */
-#define SONY_NO_CIRC_ERR_BLK_STAT       0x50
-#define SONY_NO_LECC_ERR_BLK_STAT       0x54
-#define SONY_RECOV_LECC_ERR_BLK_STAT    0x55
-#define SONY_NO_ERR_DETECTION_STAT      0x59
-
-/* 
- * The following is not an error returned by the drive, but by the code
- * that talks to the drive.  It is returned because of a timeout.
- */
-#define SONY_TIMEOUT_OP_ERR             0x01
-#define SONY_SIGNAL_OP_ERR              0x02
-#define SONY_BAD_DATA_ERR               0x03
-
-
-/*
- * The following are attention code for asynchronous events from the drive.
- */
-
-/* Standard attention group */
-#define SONY_EMER_EJECT_ATTN            0x2c
-#define SONY_HW_FAILURE_ATTN            0x70
-#define SONY_MECH_LOADED_ATTN           0x80
-#define SONY_EJECT_PUSHED_ATTN          0x81
-
-/* Audio attention group */
-#define SONY_AUDIO_PLAY_DONE_ATTN       0x90
-#define SONY_LEAD_IN_ERR_ATTN           0x91
-#define SONY_LEAD_OUT_ERR_ATTN          0x92
-#define SONY_DATA_TRACK_ERR_ATTN        0x93
-#define SONY_AUDIO_PLAYBACK_ERR_ATTN    0x94
-
-/* Auto spin up group */
-#define SONY_SPIN_UP_COMPLETE_ATTN      0x24
-#define SONY_SPINDLE_SERVO_ERR_ATTN     0x25
-#define SONY_FOCUS_SERVO_ERR_ATTN       0x26
-#define SONY_TOC_READ_DONE_ATTN         0x62
-#define SONY_FOCUS_ON_TOC_READ_ERR_ATTN 0x63
-#define SONY_SYNC_ON_TOC_READ_ERR_ATTN  0x65
-
-/* Auto eject group */
-#define SONY_SPIN_DOWN_COMPLETE_ATTN    0x27
-#define SONY_EJECT_COMPLETE_ATTN        0x28
-#define SONY_EJECT_MECH_ERR_ATTN        0x29
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
deleted file mode 100644
index 2301311..0000000
--- a/drivers/cdrom/cm206.c
+++ /dev/null
@@ -1,1594 +0,0 @@
-/* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
-   Copyright (c) 1995--1997 David A. van Leeuwen.
-   $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $
-   
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published by
-     the Free Software Foundation; either version 2 of the License, or
-     (at your option) any later version.
-     
-     This program is distributed in the hope that it will be useful,
-     but WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-     GNU General Public License for more details.
-     
-     You should have received a copy of the GNU General Public License
-     along with this program; if not, write to the Free Software
-     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-History:
- Started 25 jan 1994. Waiting for documentation...
- 22 feb 1995: 0.1a first reasonably safe polling driver.
-	      Two major bugs, one in read_sector and one in 
-	      do_cm206_request, happened to cancel!
- 25 feb 1995: 0.2a first reasonable interrupt driven version of above.
-              uart writes are still done in polling mode. 
- 25 feb 1995: 0.21a writes also in interrupt mode, still some
-	      small bugs to be found... Larger buffer. 
-  2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in
-              initialization), read_ahead of 16. Timeouts implemented.
-	      unclear if they do something...
-  7 mrt 1995: 0.23 Start of background read-ahead.
- 18 mrt 1995: 0.24 Working background read-ahead. (still problems)
- 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
-              Statistics implemented, though separate stats206.h.
-	      Accessible through ioctl 0x1000 (just a number).
-	      Hard to choose between v1.2 development and 1.1.75.
-	      Bottom-half doesn't work with 1.2...
-	      0.25a: fixed... typo. Still problems...
-  1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n.
-  5 apr 1995: 0.27 Auto-probe for the adapter card base address.
-              Auto-probe for the adaptor card irq line.
-  7 apr 1995: 0.28 Added lilo setup support for base address and irq.
-              Use major number 32 (not in this source), officially
-	      assigned to this driver.
-  9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause,
-              resume, eject. Play_track ignores track info, because we can't 
-	      read a table-of-contents entry. Toc_entry is implemented
-	      as a `placebo' function: always returns start of disc. 
-  3 may 1995: 0.30 Audio support completed. The get_toc_entry function
-              is implemented as a binary search. 
- 15 may 1995: 0.31 More work on audio stuff. Workman is not easy to 
-              satisfy; changed binary search into linear search.
-	      Auto-probe for base address somewhat relaxed.
-  1 jun 1995: 0.32 Removed probe_irq_on/off for module version.
- 10 jun 1995: 0.33 Workman still behaves funny, but you should be
-              able to eject and substitute another disc.
-
- An adaptation of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg
-
- 18 jul 1995: 0.34 Patch by Heiko Eissfeldt included, mainly considering 
-              verify_area's in the ioctls. Some bugs introduced by 
-	      EM considering the base port and irq fixed. 
-
- 18 dec 1995: 0.35 Add some code for error checking... no luck...
-
- We jump to reach our goal: version 1.0 in the next stable linux kernel.
-
- 19 mar 1996: 0.95 Different implementation of CDROM_GET_UPC, on
-	      request of Thomas Quinot. 
- 25 mar 1996: 0.96 Interpretation of opening with O_WRONLY or O_RDWR:
-	      open only for ioctl operation, e.g., for operation of
-	      tray etc.
- 4 apr 1996:  0.97 First implementation of layer between VFS and cdrom
-              driver, a generic interface. Much of the functionality
-	      of cm206_open() and cm206_ioctl() is transferred to a
-	      new file cdrom.c and its header ucdrom.h. 
-
-	      Upgrade to Linux kernel 1.3.78. 
-
- 11 apr 1996  0.98 Upgrade to Linux kernel 1.3.85
-              More code moved to cdrom.c
- 
- 	      0.99 Some more small changes to decrease number
- 	      of oopses at module load; 
- 
- 27 jul 1996  0.100 Many hours of debugging, kernel change from 1.2.13
-	      to 2.0.7 seems to have introduced some weird behavior
-	      in (interruptible_)sleep_on(&cd->data): the process
-	      seems to be woken without any explicit wake_up in my own
-	      code. Patch to try 100x in case such untriggered wake_up's 
-	      occur. 
-
- 28 jul 1996  0.101 Rewriting of the code that receives the command echo,
-	      using a fifo to store echoed bytes. 
-
- 	      Branch from 0.99:
- 
- 	      0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
- 	      (emoenke) various typos found by others.  extra
- 	      module-load oops protection.
- 
- 	      0.99.1.1 Initialization constant cdrom_dops.speed
- 	      changed from float (2.0) to int (2); Cli()-sti() pair
- 	      around cm260_reset() in module initialization code.
- 
- 	      0.99.1.2 Changes literally as proposed by Scott Snyder
- 	      <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which
- 	      have to do mainly with the poor minor support i had. The
- 	      major new concept is to change a cdrom driver's
- 	      operations struct from the capabilities struct. This
- 	      reflects the fact that there is one major for a driver,
- 	      whilst there can be many minors whith completely
- 	      different capabilities.
-
-	      0.99.1.3 More changes for operations/info separation.
-
-	      0.99.1.4 Added speed selection (someone had to do this
-	      first).
-
-  23 jan 1997 0.99.1.5 MODULE_PARMS call added.
-
-  23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as 
-  	      0.99.1.1--0.99.1.5. I get too many complaints about the
-	      drive making read errors. What't wrong with the 2.0+
-	      kernel line? Why get i (and othe cm206 owners) weird
-	      results? Why were things good in the good old 1.1--1.2 
-	      era? Why don't i throw away the drive?
-
- 2 feb 1997   0.102 Added `volatile' to values in cm206_struct. Seems to 
- 	      reduce many of the problems. Rewrote polling routines
-	      to use fixed delays between polls. 
-	      0.103 Changed printk behavior. 
-	      0.104 Added a 0.100 -> 0.100.1.1 change
-
-11 feb 1997   0.105 Allow auto_probe during module load, disable
-              with module option "auto_probe=0". Moved some debugging
-	      statements to lower priority. Implemented select_speed()
-	      function. 
-
-13 feb 1997   1.0 Final version for 2.0 kernel line. 
-
-	      All following changes will be for the 2.1 kernel line. 
-
-15 feb 1997   1.1 Keep up with kernel 2.1.26, merge in changes from 
-              cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS. 
-
-14 sep 1997   1.2 Upgrade to Linux 2.1.55.  Added blksize_size[], patch
-              sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>.
-
-21 dec 1997   1.4 Upgrade to Linux 2.1.72.  
-
-24 jan 1998   Removed the cm206_disc_status() function, as it was now dead
-              code.  The Uniform CDROM driver now provides this functionality.
-	      
-9 Nov. 1999   Make kernel-parameter implementation work with 2.3.x 
-	      Removed init_module & cleanup_module in favor of 
-	      module_init & module_exit.
-	      Torben Mathiasen <tmm@image.dk>
- * 
- * Parts of the code are based upon lmscd.c written by Kai Petzke,
- * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
- * Harriss, but any off-the-shelf dynamic programming algorithm won't
- * be able to find them.
- *
- * The cm206 drive interface and the cm260 adapter card seem to be 
- * sufficiently different from their cm205/cm250 counterparts
- * in order to write a complete new driver.
- * 
- * I call all routines connected to the Linux kernel something
- * with `cm206' in it, as this stuff is too series-dependent. 
- * 
- * Currently, my limited knowledge is based on:
- * - The Linux Kernel Hacker's guide, v. 0.5, by Michael K. Johnson
- * - Linux Kernel Programmierung, by Michael Beck and others
- * - Philips/LMS cm206 and cm226 product specification
- * - Philips/LMS cm260 product specification
- *
- * David van Leeuwen, david@tm.tno.nl.  */
-#define REVISION "$Revision: 1.5 $"
-
-#include <linux/module.h>
-
-#include <linux/errno.h>	/* These include what we really need */
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-/* #include <linux/ucdrom.h> */
-
-#include <asm/io.h>
-
-#define MAJOR_NR CM206_CDROM_MAJOR
-
-#include <linux/blkdev.h>
-
-#undef DEBUG
-#define STATISTICS		/* record times and frequencies of events */
-#define AUTO_PROBE_MODULE
-#define USE_INSW
-
-#include "cm206.h"
-
-/* This variable defines whether or not to probe for adapter base port 
-   address and interrupt request. It can be overridden by the boot 
-   parameter `auto'.
-*/
-static int auto_probe = 1;	/* Yes, why not? */
-
-static int cm206_base = CM206_BASE;
-static int cm206_irq = CM206_IRQ;
-#ifdef MODULE
-static int cm206[2] = { 0, 0 };	/* for compatible `insmod' parameter passing */
-module_param_array(cm206, int, NULL, 0);	/* base,irq or irq,base */
-#endif
-
-module_param(cm206_base, int, 0);	/* base */
-module_param(cm206_irq, int, 0);	/* irq */
-module_param(auto_probe, bool, 0);	/* auto probe base and irq */
-MODULE_LICENSE("GPL");
-
-#define POLLOOP 100		/* milliseconds */
-#define READ_AHEAD 1		/* defines private buffer, waste! */
-#define BACK_AHEAD 1		/* defines adapter-read ahead */
-#define DATA_TIMEOUT (3*HZ)	/* measured in jiffies (10 ms) */
-#define UART_TIMEOUT (5*HZ/100)
-#define DSB_TIMEOUT (7*HZ)	/* time for the slowest command to finish */
-#define UR_SIZE 4		/* uart receive buffer fifo size */
-
-#define LINUX_BLOCK_SIZE 512	/* WHERE is this defined? */
-#define RAW_SECTOR_SIZE 2352	/* ok, is also defined in cdrom.h */
-#define ISO_SECTOR_SIZE 2048
-#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE)	/* 4 */
-#define CD_SYNC_HEAD 16		/* CD_SYNC + CD_HEAD */
-
-#ifdef STATISTICS		/* keep track of errors in counters */
-#define stats(i) { ++cd->stats[st_ ## i]; \
-		     cd->last_stat[st_ ## i] = cd->stat_counter++; \
-		 }
-#else
-#define stats(i) (void) 0;
-#endif
-
-#define Debug(a) {printk (KERN_DEBUG); printk a;}
-#ifdef DEBUG
-#define debug(a) Debug(a)
-#else
-#define debug(a) (void) 0;
-#endif
-
-typedef unsigned char uch;	/* 8-bits */
-typedef unsigned short ush;	/* 16-bits */
-
-struct toc_struct {		/* private copy of Table of Contents */
-	uch track, fsm[3], q0;
-};
-
-struct cm206_struct {
-	volatile ush intr_ds;	/* data status read on last interrupt */
-	volatile ush intr_ls;	/* uart line status read on last interrupt */
-	volatile uch ur[UR_SIZE];	/* uart receive buffer fifo */
-	volatile uch ur_w, ur_r;	/* write/read buffer index */
-	volatile uch dsb, cc;	/* drive status byte and condition (error) code */
-	int command;		/* command to be written to the uart */
-	int openfiles;
-	ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2];	/* buffered cd-sector */
-	int sector_first, sector_last;	/* range of these sectors */
-	wait_queue_head_t uart;	/* wait queues for interrupt */
-	wait_queue_head_t data;
-	struct timer_list timer;	/* time-out */
-	char timed_out;
-	signed char max_sectors;	/* number of sectors that fit in adapter mem */
-	char wait_back;		/* we're waiting for a background-read */
-	char background;	/* is a read going on in the background? */
-	int adapter_first;	/* if so, that's the starting sector */
-	int adapter_last;
-	char fifo_overflowed;
-	uch disc_status[7];	/* result of get_disc_status command */
-#ifdef STATISTICS
-	int stats[NR_STATS];
-	int last_stat[NR_STATS];	/* `time' at which stat was stat */
-	int stat_counter;
-#endif
-	struct toc_struct toc[101];	/* The whole table of contents + lead-out */
-	uch q[10];		/* Last read q-channel info */
-	uch audio_status[5];	/* last read position on pause */
-	uch media_changed;	/* record if media changed */
-};
-
-#define DISC_STATUS cd->disc_status[0]
-#define FIRST_TRACK cd->disc_status[1]
-#define LAST_TRACK cd->disc_status[2]
-#define PAUSED cd->audio_status[0]	/* misuse this memory byte! */
-#define PLAY_TO cd->toc[0]	/* toc[0] records end-time in play */
-
-static struct cm206_struct *cd;	/* the main memory structure */
-static struct request_queue *cm206_queue;
-static DEFINE_SPINLOCK(cm206_lock);
-
-/* First, we define some polling functions. These are actually
-   only being used in the initialization. */
-
-static void send_command_polled(int command)
-{
-	int loop = POLLOOP;
-	while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
-	       && loop > 0) {
-		mdelay(1);	/* one millisec delay */
-		--loop;
-	}
-	outw(command, r_uart_transmit);
-}
-
-static uch receive_echo_polled(void)
-{
-	int loop = POLLOOP;
-	while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
-		mdelay(1);
-		--loop;
-	}
-	return ((uch) inw(r_uart_receive));
-}
-
-static uch send_receive_polled(int command)
-{
-	send_command_polled(command);
-	return receive_echo_polled();
-}
-
-static inline void clear_ur(void)
-{
-	if (cd->ur_r != cd->ur_w) {
-		debug(("Deleting bytes from fifo:"));
-		for (; cd->ur_r != cd->ur_w;
-		     cd->ur_r++, cd->ur_r %= UR_SIZE)
-			debug((" 0x%x", cd->ur[cd->ur_r]));
-		debug(("\n"));
-	}
-}
-
-static struct tasklet_struct cm206_tasklet;
-
-/* The interrupt handler. When the cm260 generates an interrupt, very
-   much care has to be taken in reading out the registers in the right
-   order; in case of a receive_buffer_full interrupt, first the
-   uart_receive must be read, and then the line status again to
-   de-assert the interrupt line. It took me a couple of hours to find
-   this out:-( 
-
-   The function reset_cm206 appears to cause an interrupt, because
-   pulling up the INIT line clears both the uart-write-buffer /and/
-   the uart-write-buffer-empty mask. We call this a `lost interrupt,'
-   as there seems so reason for this to happen.
-*/
-
-static irqreturn_t cm206_interrupt(int sig, void *dev_id)
-{
-	volatile ush fool;
-	cd->intr_ds = inw(r_data_status);	/* resets data_ready, data_error,
-						   crc_error, sync_error, toc_ready 
-						   interrupts */
-	cd->intr_ls = inw(r_line_status);	/* resets overrun bit */
-	debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
-	       cd->background));
-	if (cd->intr_ls & ls_attention)
-		stats(attention);
-	/* receive buffer full? */
-	if (cd->intr_ls & ls_receive_buffer_full) {
-		cd->ur[cd->ur_w] = inb(r_uart_receive);	/* get order right! */
-		cd->intr_ls = inw(r_line_status);	/* resets rbf interrupt */
-		debug(("receiving #%d: 0x%x\n", cd->ur_w,
-		       cd->ur[cd->ur_w]));
-		cd->ur_w++;
-		cd->ur_w %= UR_SIZE;
-		if (cd->ur_w == cd->ur_r)
-			debug(("cd->ur overflow!\n"));
-		if (waitqueue_active(&cd->uart) && cd->background < 2) {
-			del_timer(&cd->timer);
-			wake_up_interruptible(&cd->uart);
-		}
-	}
-	/* data ready in fifo? */
-	else if (cd->intr_ds & ds_data_ready) {
-		if (cd->background)
-			++cd->adapter_last;
-		if (waitqueue_active(&cd->data)
-		    && (cd->wait_back || !cd->background)) {
-			del_timer(&cd->timer);
-			wake_up_interruptible(&cd->data);
-		}
-		stats(data_ready);
-	}
-	/* ready to issue a write command? */
-	else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
-		outw(dc_normal | (inw(r_data_status) & 0x7f),
-		     r_data_control);
-		outw(cd->command, r_uart_transmit);
-		cd->command = 0;
-		if (!cd->background)
-			wake_up_interruptible(&cd->uart);
-	}
-	/* now treat errors (at least, identify them for debugging) */
-	else if (cd->intr_ds & ds_fifo_overflow) {
-		debug(("Fifo overflow at sectors 0x%x\n",
-		       cd->sector_first));
-		fool = inw(r_fifo_output_buffer);	/* de-assert the interrupt */
-		cd->fifo_overflowed = 1;	/* signal one word less should be read */
-		stats(fifo_overflow);
-	} else if (cd->intr_ds & ds_data_error) {
-		debug(("Data error at sector 0x%x\n", cd->sector_first));
-		stats(data_error);
-	} else if (cd->intr_ds & ds_crc_error) {
-		debug(("CRC error at sector 0x%x\n", cd->sector_first));
-		stats(crc_error);
-	} else if (cd->intr_ds & ds_sync_error) {
-		debug(("Sync at sector 0x%x\n", cd->sector_first));
-		stats(sync_error);
-	} else if (cd->intr_ds & ds_toc_ready) {
-		/* do something appropriate */
-	}
-	/* couldn't see why this interrupt, maybe due to init */
-	else {
-		outw(dc_normal | READ_AHEAD, r_data_control);
-		stats(lost_intr);
-	}
-	if (cd->background
-	    && (cd->adapter_last - cd->adapter_first == cd->max_sectors
-		|| cd->fifo_overflowed))
-		tasklet_schedule(&cm206_tasklet);	/* issue a stop read command */
-	stats(interrupt);
-	return IRQ_HANDLED;
-}
-
-/* we have put the address of the wait queue in who */
-static void cm206_timeout(unsigned long who)
-{
-	cd->timed_out = 1;
-	debug(("Timing out\n"));
-	wake_up_interruptible((wait_queue_head_t *) who);
-}
-
-/* This function returns 1 if a timeout occurred, 0 if an interrupt
-   happened */
-static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
-{
-	cd->timed_out = 0;
-	init_timer(&cd->timer);
-	cd->timer.data = (unsigned long) wait;
-	cd->timer.expires = jiffies + timeout;
-	add_timer(&cd->timer);
-	debug(("going to sleep\n"));
-	interruptible_sleep_on(wait);
-	del_timer(&cd->timer);
-	if (cd->timed_out) {
-		cd->timed_out = 0;
-		return 1;
-	} else
-		return 0;
-}
-
-static void send_command(int command)
-{
-	debug(("Sending 0x%x\n", command));
-	if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
-		cd->command = command;
-		cli();		/* don't interrupt before sleep */
-		outw(dc_mask_sync_error | dc_no_stop_on_error |
-		     (inw(r_data_status) & 0x7f), r_data_control);
-		/* interrupt routine sends command */
-		if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
-			debug(("Time out on write-buffer\n"));
-			stats(write_timeout);
-			outw(command, r_uart_transmit);
-		}
-		debug(("Write commmand delayed\n"));
-	} else
-		outw(command, r_uart_transmit);
-}
-
-static uch receive_byte(int timeout)
-{
-	uch ret;
-	cli();
-	debug(("cli\n"));
-	ret = cd->ur[cd->ur_r];
-	if (cd->ur_r != cd->ur_w) {
-		sti();
-		debug(("returning #%d: 0x%x\n", cd->ur_r,
-		       cd->ur[cd->ur_r]));
-		cd->ur_r++;
-		cd->ur_r %= UR_SIZE;
-		return ret;
-	} else if (sleep_or_timeout(&cd->uart, timeout)) {	/* does sti() */
-		debug(("Time out on receive-buffer\n"));
-#ifdef STATISTICS
-		if (timeout == UART_TIMEOUT)
-			stats(receive_timeout)	/* no `;'! */
-			    else
-			stats(dsb_timeout);
-#endif
-		return 0xda;
-	}
-	ret = cd->ur[cd->ur_r];
-	debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
-	       cd->ur[cd->ur_r]));
-	cd->ur_r++;
-	cd->ur_r %= UR_SIZE;
-	return ret;
-}
-
-static inline uch receive_echo(void)
-{
-	return receive_byte(UART_TIMEOUT);
-}
-
-static inline uch send_receive(int command)
-{
-	send_command(command);
-	return receive_echo();
-}
-
-static inline uch wait_dsb(void)
-{
-	return receive_byte(DSB_TIMEOUT);
-}
-
-static int type_0_command(int command, int expect_dsb)
-{
-	int e;
-	clear_ur();
-	if (command != (e = send_receive(command))) {
-		debug(("command 0x%x echoed as 0x%x\n", command, e));
-		stats(echo);
-		return -1;
-	}
-	if (expect_dsb) {
-		cd->dsb = wait_dsb();	/* wait for command to finish */
-	}
-	return 0;
-}
-
-static int type_1_command(int command, int bytes, uch * status)
-{				/* returns info */
-	int i;
-	if (type_0_command(command, 0))
-		return -1;
-	for (i = 0; i < bytes; i++)
-		status[i] = send_receive(c_gimme);
-	return 0;
-}
-
-/* This function resets the adapter card. We'd better not do this too
- * often, because it tends to generate `lost interrupts.' */
-static void reset_cm260(void)
-{
-	outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
-	udelay(10);		/* 3.3 mu sec minimum */
-	outw(dc_normal | READ_AHEAD, r_data_control);
-}
-
-/* fsm: frame-sec-min from linear address; one of many */
-static void fsm(int lba, uch * fsm)
-{
-	fsm[0] = lba % 75;
-	lba /= 75;
-	lba += 2;
-	fsm[1] = lba % 60;
-	fsm[2] = lba / 60;
-}
-
-static inline int fsm2lba(uch * fsm)
-{
-	return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
-}
-
-static inline int f_s_m2lba(uch f, uch s, uch m)
-{
-	return f + 75 * (s - 2 + 60 * m);
-}
-
-static int start_read(int start)
-{
-	uch read_sector[4] = { c_read_data, };
-	int i, e;
-
-	fsm(start, &read_sector[1]);
-	clear_ur();
-	for (i = 0; i < 4; i++)
-		if (read_sector[i] != (e = send_receive(read_sector[i]))) {
-			debug(("read_sector: %x echoes %x\n",
-			       read_sector[i], e));
-			stats(echo);
-			if (e == 0xff) {	/* this seems to happen often */
-				e = receive_echo();
-				debug(("Second try %x\n", e));
-				if (e != read_sector[i])
-					return -1;
-			}
-		}
-	return 0;
-}
-
-static int stop_read(void)
-{
-	int e;
-	type_0_command(c_stop, 0);
-	if ((e = receive_echo()) != 0xff) {
-		debug(("c_stop didn't send 0xff, but 0x%x\n", e));
-		stats(stop_0xff);
-		return -1;
-	}
-	return 0;
-}
-
-/* This function starts to read sectors in adapter memory, the
-   interrupt routine should stop the read. In fact, the bottom_half
-   routine takes care of this. Set a flag `background' in the cd
-   struct to indicate the process. */
-
-static int read_background(int start, int reading)
-{
-	if (cd->background)
-		return -1;	/* can't do twice */
-	outw(dc_normal | BACK_AHEAD, r_data_control);
-	if (!reading && start_read(start))
-		return -2;
-	cd->adapter_first = cd->adapter_last = start;
-	cd->background = 1;	/* flag a read is going on */
-	return 0;
-}
-
-#ifdef USE_INSW
-#define transport_data insw
-#else
-/* this routine implements insw(,,). There was a time i had the
-   impression that there would be any difference in error-behaviour. */
-void transport_data(int port, ush * dest, int count)
-{
-	int i;
-	ush *d;
-	for (i = 0, d = dest; i < count; i++, d++)
-		*d = inw(port);
-}
-#endif
-
-
-#define MAX_TRIES 100
-static int read_sector(int start)
-{
-	int tries = 0;
-	if (cd->background) {
-		cd->background = 0;
-		cd->adapter_last = -1;	/* invalidate adapter memory */
-		stop_read();
-	}
-	cd->fifo_overflowed = 0;
-	reset_cm260();		/* empty fifo etc. */
-	if (start_read(start))
-		return -1;
-	do {
-		if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
-			debug(("Read timed out sector 0x%x\n", start));
-			stats(read_timeout);
-			stop_read();
-			return -3;
-		}
-		tries++;
-	} while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
-	if (tries > 1)
-		debug(("Took me some tries\n"))
-		    else
-	if (tries == MAX_TRIES)
-		debug(("MAX_TRIES tries for read sector\n"));
-	transport_data(r_fifo_output_buffer, cd->sector,
-		       READ_AHEAD * RAW_SECTOR_SIZE / 2);
-	if (read_background(start + READ_AHEAD, 1))
-		stats(read_background);
-	cd->sector_first = start;
-	cd->sector_last = start + READ_AHEAD;
-	stats(read_restarted);
-	return 0;
-}
-
-/* The function of bottom-half is to send a stop command to the drive
-   This isn't easy because the routine is not `owned' by any process;
-   we can't go to sleep! The variable cd->background gives the status:
-   0 no read pending
-   1 a read is pending
-   2 c_stop waits for write_buffer_empty
-   3 c_stop waits for receive_buffer_full: echo
-   4 c_stop waits for receive_buffer_full: 0xff
-*/
-
-static void cm206_tasklet_func(unsigned long ignore)
-{
-	debug(("bh: %d\n", cd->background));
-	switch (cd->background) {
-	case 1:
-		stats(bh);
-		if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
-			cd->command = c_stop;
-			outw(dc_mask_sync_error | dc_no_stop_on_error |
-			     (inw(r_data_status) & 0x7f), r_data_control);
-			cd->background = 2;
-			break;	/* we'd better not time-out here! */
-		} else
-			outw(c_stop, r_uart_transmit);
-		/* fall into case 2: */
-	case 2:
-		/* the write has been satisfied by interrupt routine */
-		cd->background = 3;
-		break;
-	case 3:
-		if (cd->ur_r != cd->ur_w) {
-			if (cd->ur[cd->ur_r] != c_stop) {
-				debug(("cm206_bh: c_stop echoed 0x%x\n",
-				       cd->ur[cd->ur_r]));
-				stats(echo);
-			}
-			cd->ur_r++;
-			cd->ur_r %= UR_SIZE;
-		}
-		cd->background++;
-		break;
-	case 4:
-		if (cd->ur_r != cd->ur_w) {
-			if (cd->ur[cd->ur_r] != 0xff) {
-				debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
-				stats(stop_0xff);
-			}
-			cd->ur_r++;
-			cd->ur_r %= UR_SIZE;
-		}
-		cd->background = 0;
-	}
-}
-
-static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
-
-/* This command clears the dsb_possible_media_change flag, so we must 
- * retain it.
- */
-static void get_drive_status(void)
-{
-	uch status[2];
-	type_1_command(c_drive_status, 2, status);	/* this might be done faster */
-	cd->dsb = status[0];
-	cd->cc = status[1];
-	cd->media_changed |=
-	    !!(cd->dsb & (dsb_possible_media_change |
-			  dsb_drive_not_ready | dsb_tray_not_closed));
-}
-
-static void get_disc_status(void)
-{
-	if (type_1_command(c_disc_status, 7, cd->disc_status)) {
-		debug(("get_disc_status: error\n"));
-	}
-}
-
-/* The new open. The real opening strategy is defined in cdrom.c. */
-
-static int cm206_open(struct cdrom_device_info *cdi, int purpose)
-{
-	if (!cd->openfiles) {	/* reset only first time */
-		cd->background = 0;
-		reset_cm260();
-		cd->adapter_last = -1;	/* invalidate adapter memory */
-		cd->sector_last = -1;
-	}
-	++cd->openfiles;
-	stats(open);
-	return 0;
-}
-
-static void cm206_release(struct cdrom_device_info *cdi)
-{
-	if (cd->openfiles == 1) {
-		if (cd->background) {
-			cd->background = 0;
-			stop_read();
-		}
-		cd->sector_last = -1;	/* Make our internal buffer invalid */
-		FIRST_TRACK = 0;	/* No valid disc status */
-	}
-	--cd->openfiles;
-}
-
-/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
- * and then reads a sector in kernel memory.  */
-static void empty_buffer(int sectors)
-{
-	while (sectors >= 0) {
-		transport_data(r_fifo_output_buffer,
-			       cd->sector + cd->fifo_overflowed,
-			       RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
-		--sectors;
-		++cd->adapter_first;	/* update the current adapter sector */
-		cd->fifo_overflowed = 0;	/* reset overflow bit */
-		stats(sector_transferred);
-	}
-	cd->sector_first = cd->adapter_first - 1;
-	cd->sector_last = cd->adapter_first;	/* update the buffer sector */
-}
-
-/* try_adapter. This function determines if the requested sector is
-   in adapter memory, or will appear there soon. Returns 0 upon
-   success */
-static int try_adapter(int sector)
-{
-	if (cd->adapter_first <= sector && sector < cd->adapter_last) {
-		/* sector is in adapter memory */
-		empty_buffer(sector - cd->adapter_first);
-		return 0;
-	} else if (cd->background == 1 && cd->adapter_first <= sector
-		   && sector < cd->adapter_first + cd->max_sectors) {
-		/* a read is going on, we can wait for it */
-		cd->wait_back = 1;
-		while (sector >= cd->adapter_last) {
-			if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
-				debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
-				stats(back_read_timeout);
-				cd->wait_back = 0;
-				return -1;
-			}
-		}
-		cd->wait_back = 0;
-		empty_buffer(sector - cd->adapter_first);
-		return 0;
-	} else
-		return -2;
-}
-
-/* This is not a very smart implementation. We could optimize for 
-   consecutive block numbers. I'm not convinced this would really
-   bring down the processor load. */
-static void do_cm206_request(request_queue_t * q)
-{
-	long int i, cd_sec_no;
-	int quarter, error;
-	uch *source, *dest;
-	struct request *req;
-
-	while (1) {	/* repeat until all requests have been satisfied */
-		req = elv_next_request(q);
-		if (!req)
-			return;
-
-		if (req->cmd != READ) {
-			debug(("Non-read command %d on cdrom\n", req->cmd));
-			end_request(req, 0);
-			continue;
-		}
-		spin_unlock_irq(q->queue_lock);
-		error = 0;
-		for (i = 0; i < req->nr_sectors; i++) {
-			int e1, e2;
-			cd_sec_no = (req->sector + i) / BLOCKS_ISO;	/* 4 times 512 bytes */
-			quarter = (req->sector + i) % BLOCKS_ISO;
-			dest = req->buffer + i * LINUX_BLOCK_SIZE;
-			/* is already in buffer memory? */
-			if (cd->sector_first <= cd_sec_no
-			    && cd_sec_no < cd->sector_last) {
-				source =
-				    ((uch *) cd->sector) + 16 +
-				    quarter * LINUX_BLOCK_SIZE +
-				    (cd_sec_no -
-				     cd->sector_first) * RAW_SECTOR_SIZE;
-				memcpy(dest, source, LINUX_BLOCK_SIZE);
-			} else if (!(e1 = try_adapter(cd_sec_no)) ||
-				   !(e2 = read_sector(cd_sec_no))) {
-				source =
-				    ((uch *) cd->sector) + 16 +
-				    quarter * LINUX_BLOCK_SIZE;
-				memcpy(dest, source, LINUX_BLOCK_SIZE);
-			} else {
-				error = 1;
-				debug(("cm206_request: %d %d\n", e1, e2));
-			}
-		}
-		spin_lock_irq(q->queue_lock);
-		end_request(req, !error);
-	}
-}
-
-/* Audio support. I've tried very hard, but the cm206 drive doesn't 
-   seem to have a get_toc (table-of-contents) function, while i'm
-   pretty sure it must read the toc upon disc insertion. Therefore
-   this function has been implemented through a binary search 
-   strategy. All track starts that happen to be found are stored in
-   cd->toc[], for future use. 
-
-   I've spent a whole day on a bug that only shows under Workman---
-   I don't get it. Tried everything, nothing works. If workman asks
-   for track# 0xaa, it'll get the wrong time back. Any other program
-   receives the correct value. I'm stymied.
-*/
-
-/* seek seeks to address lba. It does wait to arrive there. */
-static void seek(int lba)
-{
-	int i;
-	uch seek_command[4] = { c_seek, };
-
-	fsm(lba, &seek_command[1]);
-	for (i = 0; i < 4; i++)
-		type_0_command(seek_command[i], 0);
-	cd->dsb = wait_dsb();
-}
-
-static uch bcdbin(unsigned char bcd)
-{				/* stolen from mcd.c! */
-	return (bcd >> 4) * 10 + (bcd & 0xf);
-}
-
-static inline uch normalize_track(uch track)
-{
-	if (track < 1)
-		return 1;
-	if (track > LAST_TRACK)
-		return LAST_TRACK + 1;
-	return track;
-}
-
-/* This function does a binary search for track start. It records all
- * tracks seen in the process. Input $track$ must be between 1 and
- * #-of-tracks+1.  Note that the start of the disc must be in toc[1].fsm. 
- */
-static int get_toc_lba(uch track)
-{
-	int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
-	int i, lba, l, old_lba = 0;
-	uch *q = cd->q;
-	uch ct;			/* current track */
-	int binary = 0;
-	const int skip = 3 * 60 * 75;	/* 3 minutes */
-
-	for (i = track; i > 0; i--)
-		if (cd->toc[i].track) {
-			min = fsm2lba(cd->toc[i].fsm);
-			break;
-		}
-	lba = min + skip;
-	do {
-		seek(lba);
-		type_1_command(c_read_current_q, 10, q);
-		ct = normalize_track(q[1]);
-		if (!cd->toc[ct].track) {
-			l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
-							bcdbin(q[4]) - 2 +
-							60 * (q[7] -
-							      bcdbin(q
-								     [3])));
-			cd->toc[ct].track = q[1];	/* lead out still 0xaa */
-			fsm(l, cd->toc[ct].fsm);
-			cd->toc[ct].q0 = q[0];	/* contains adr and ctrl info */
-			if (ct == track)
-				return l;
-		}
-		old_lba = lba;
-		if (binary) {
-			if (ct < track)
-				min = lba;
-			else
-				max = lba;
-			lba = (min + max) / 2;
-		} else {
-			if (ct < track)
-				lba += skip;
-			else {
-				binary = 1;
-				max = lba;
-				min = lba - skip;
-				lba = (min + max) / 2;
-			}
-		}
-	} while (lba != old_lba);
-	return lba;
-}
-
-static void update_toc_entry(uch track)
-{
-	track = normalize_track(track);
-	if (!cd->toc[track].track)
-		get_toc_lba(track);
-}
-
-/* return 0 upon success */
-static int read_toc_header(struct cdrom_tochdr *hp)
-{
-	if (!FIRST_TRACK)
-		get_disc_status();
-	if (hp) {
-		int i;
-		hp->cdth_trk0 = FIRST_TRACK;
-		hp->cdth_trk1 = LAST_TRACK;
-		/* fill in first track position */
-		for (i = 0; i < 3; i++)
-			cd->toc[1].fsm[i] = cd->disc_status[3 + i];
-		update_toc_entry(LAST_TRACK + 1);	/* find most entries */
-		return 0;
-	}
-	return -1;
-}
-
-static void play_from_to_msf(struct cdrom_msf *msfp)
-{
-	uch play_command[] = { c_play,
-		msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
-		msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
-		    2
-	};
-	int i;
-	for (i = 0; i < 9; i++)
-		type_0_command(play_command[i], 0);
-	for (i = 0; i < 3; i++)
-		PLAY_TO.fsm[i] = play_command[i + 4];
-	PLAY_TO.track = 0;	/* say no track end */
-	cd->dsb = wait_dsb();
-}
-
-static void play_from_to_track(int from, int to)
-{
-	uch play_command[8] = { c_play, };
-	int i;
-
-	if (from == 0) {	/* continue paused play */
-		for (i = 0; i < 3; i++) {
-			play_command[i + 1] = cd->audio_status[i + 2];
-			play_command[i + 4] = PLAY_TO.fsm[i];
-		}
-	} else {
-		update_toc_entry(from);
-		update_toc_entry(to + 1);
-		for (i = 0; i < 3; i++) {
-			play_command[i + 1] = cd->toc[from].fsm[i];
-			PLAY_TO.fsm[i] = play_command[i + 4] =
-			    cd->toc[to + 1].fsm[i];
-		}
-		PLAY_TO.track = to;
-	}
-	for (i = 0; i < 7; i++)
-		type_0_command(play_command[i], 0);
-	for (i = 0; i < 2; i++)
-		type_0_command(0x2, 0);	/* volume */
-	cd->dsb = wait_dsb();
-}
-
-static int get_current_q(struct cdrom_subchnl *qp)
-{
-	int i;
-	uch *q = cd->q;
-	if (type_1_command(c_read_current_q, 10, q))
-		return 0;
-/*  q[0] = bcdbin(q[0]); Don't think so! */
-	for (i = 2; i < 6; i++)
-		q[i] = bcdbin(q[i]);
-	qp->cdsc_adr = q[0] & 0xf;
-	qp->cdsc_ctrl = q[0] >> 4;	/* from mcd.c */
-	qp->cdsc_trk = q[1];
-	qp->cdsc_ind = q[2];
-	if (qp->cdsc_format == CDROM_MSF) {
-		qp->cdsc_reladdr.msf.minute = q[3];
-		qp->cdsc_reladdr.msf.second = q[4];
-		qp->cdsc_reladdr.msf.frame = q[5];
-		qp->cdsc_absaddr.msf.minute = q[7];
-		qp->cdsc_absaddr.msf.second = q[8];
-		qp->cdsc_absaddr.msf.frame = q[9];
-	} else {
-		qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
-		qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
-	}
-	get_drive_status();
-	if (cd->dsb & dsb_play_in_progress)
-		qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
-	else if (PAUSED)
-		qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
-	else
-		qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
-	return 0;
-}
-
-static void invalidate_toc(void)
-{
-	memset(cd->toc, 0, sizeof(cd->toc));
-	memset(cd->disc_status, 0, sizeof(cd->disc_status));
-}
-
-/* cdrom.c guarantees that cdte_format == CDROM_MSF */
-static void get_toc_entry(struct cdrom_tocentry *ep)
-{
-	uch track = normalize_track(ep->cdte_track);
-	update_toc_entry(track);
-	ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
-	ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
-	ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
-	ep->cdte_adr = cd->toc[track].q0 & 0xf;
-	ep->cdte_ctrl = cd->toc[track].q0 >> 4;
-	ep->cdte_datamode = 0;
-}
-
-/* Audio ioctl.  Ioctl commands connected to audio are in such an
- * idiosyncratic i/o format, that we leave these untouched. Return 0
- * upon success. Memory checking has been done by cdrom_ioctl(), the
- * calling function, as well as LBA/MSF sanitization.
-*/
-static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
-			     void *arg)
-{
-	switch (cmd) {
-	case CDROMREADTOCHDR:
-		return read_toc_header((struct cdrom_tochdr *) arg);
-	case CDROMREADTOCENTRY:
-		get_toc_entry((struct cdrom_tocentry *) arg);
-		return 0;
-	case CDROMPLAYMSF:
-		play_from_to_msf((struct cdrom_msf *) arg);
-		return 0;
-	case CDROMPLAYTRKIND:	/* admittedly, not particularly beautiful */
-		play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
-				   ((struct cdrom_ti *) arg)->cdti_trk1);
-		return 0;
-	case CDROMSTOP:
-		PAUSED = 0;
-		if (cd->dsb & dsb_play_in_progress)
-			return type_0_command(c_stop, 1);
-		else
-			return 0;
-	case CDROMPAUSE:
-		get_drive_status();
-		if (cd->dsb & dsb_play_in_progress) {
-			type_0_command(c_stop, 1);
-			type_1_command(c_audio_status, 5,
-				       cd->audio_status);
-			PAUSED = 1;	/* say we're paused */
-		}
-		return 0;
-	case CDROMRESUME:
-		if (PAUSED)
-			play_from_to_track(0, 0);
-		PAUSED = 0;
-		return 0;
-	case CDROMSTART:
-	case CDROMVOLCTRL:
-		return 0;
-	case CDROMSUBCHNL:
-		return get_current_q((struct cdrom_subchnl *) arg);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-	if (cd != NULL) {
-		int r;
-		get_drive_status();	/* ensure cd->media_changed OK */
-		r = cd->media_changed;
-		cd->media_changed = 0;	/* clear bit */
-		return r;
-	} else
-		return -EIO;
-}
-
-/* The new generic cdrom support. Routines should be concise, most of
-   the logic should be in cdrom.c */
-
-
-/* controls tray movement */
-static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
-{
-	if (position) {		/* 1: eject */
-		type_0_command(c_open_tray, 1);
-		invalidate_toc();
-	} else
-		type_0_command(c_close_tray, 1);	/* 0: close */
-	return 0;
-}
-
-/* gives current state of the drive */
-static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-	get_drive_status();
-	if (cd->dsb & dsb_tray_not_closed)
-		return CDS_TRAY_OPEN;
-	if (!(cd->dsb & dsb_disc_present))
-		return CDS_NO_DISC;
-	if (cd->dsb & dsb_drive_not_ready)
-		return CDS_DRIVE_NOT_READY;
-	return CDS_DISC_OK;
-}
-
-/* locks or unlocks door lock==1: lock; return 0 upon success */
-static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-	uch command = (lock) ? c_lock_tray : c_unlock_tray;
-	type_0_command(command, 1);	/* wait and get dsb */
-	/* the logic calculates the success, 0 means successful */
-	return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
-}
-
-/* Although a session start should be in LBA format, we return it in 
-   MSF format because it is slightly easier, and the new generic ioctl
-   will take care of the necessary conversion. */
-static int cm206_get_last_session(struct cdrom_device_info *cdi,
-				  struct cdrom_multisession *mssp)
-{
-	if (!FIRST_TRACK)
-		get_disc_status();
-	if (mssp != NULL) {
-		if (DISC_STATUS & cds_multi_session) {	/* multi-session */
-			mssp->addr.msf.frame = cd->disc_status[3];
-			mssp->addr.msf.second = cd->disc_status[4];
-			mssp->addr.msf.minute = cd->disc_status[5];
-			mssp->addr_format = CDROM_MSF;
-			mssp->xa_flag = 1;
-		} else {
-			mssp->xa_flag = 0;
-		}
-		return 1;
-	}
-	return 0;
-}
-
-static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-	uch upc[10];
-	char *ret = mcn->medium_catalog_number;
-	int i;
-
-	if (type_1_command(c_read_upc, 10, upc))
-		return -EIO;
-	for (i = 0; i < 13; i++) {
-		int w = i / 2 + 1, r = i % 2;
-		if (r)
-			ret[i] = 0x30 | (upc[w] & 0x0f);
-		else
-			ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
-	}
-	ret[13] = '\0';
-	return 0;
-}
-
-static int cm206_reset(struct cdrom_device_info *cdi)
-{
-	stop_read();
-	reset_cm260();
-	outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
-	mdelay(1);		/* 750 musec minimum */
-	outw(dc_normal | READ_AHEAD, r_data_control);
-	cd->sector_last = -1;	/* flag no data buffered */
-	cd->adapter_last = -1;
-	invalidate_toc();
-	return 0;
-}
-
-static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-	int r;
-	switch (speed) {
-	case 0:
-		r = type_0_command(c_auto_mode, 1);
-		break;
-	case 1:
-		r = type_0_command(c_force_1x, 1);
-		break;
-	case 2:
-		r = type_0_command(c_force_2x, 1);
-		break;
-	default:
-		return -1;
-	}
-	if (r < 0)
-		return r;
-	else
-		return 1;
-}
-
-static struct cdrom_device_ops cm206_dops = {
-	.open			= cm206_open,
-	.release		= cm206_release,
-	.drive_status		= cm206_drive_status,
-	.media_changed		= cm206_media_changed,
-	.tray_move		= cm206_tray_move,
-	.lock_door		= cm206_lock_door,
-	.select_speed		= cm206_select_speed,
-	.get_last_session	= cm206_get_last_session,
-	.get_mcn		= cm206_get_upc,
-	.reset			= cm206_reset,
-	.audio_ioctl		= cm206_audio_ioctl,
-	.capability		= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
-				  CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
-				  CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
-				  CDC_DRIVE_STATUS,
-	.n_minors		= 1,
-};
-
-
-static struct cdrom_device_info cm206_info = {
-	.ops		= &cm206_dops,
-	.speed		= 2,
-	.capacity	= 1,
-	.name		= "cm206",
-};
-
-static int cm206_block_open(struct inode *inode, struct file *file)
-{
-	return cdrom_open(&cm206_info, inode, file);
-}
-
-static int cm206_block_release(struct inode *inode, struct file *file)
-{
-	return cdrom_release(&cm206_info, file);
-}
-
-static int cm206_block_ioctl(struct inode *inode, struct file *file,
-				unsigned cmd, unsigned long arg)
-{
-	switch (cmd) {
-#ifdef STATISTICS
-	case CM206CTL_GET_STAT:
-		if (arg >= NR_STATS)
-			return -EINVAL;
-		return cd->stats[arg];
-	case CM206CTL_GET_LAST_STAT:
-		if (arg >= NR_STATS)
-			return -EINVAL;
-		return cd->last_stat[arg];
-#endif
-	default:
-		break;
-	}
-
-	return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
-}
-
-static int cm206_block_media_changed(struct gendisk *disk)
-{
-	return cdrom_media_changed(&cm206_info);
-}
-
-static struct block_device_operations cm206_bdops =
-{
-	.owner		= THIS_MODULE,
-	.open		= cm206_block_open,
-	.release	= cm206_block_release,
-	.ioctl		= cm206_block_ioctl,
-	.media_changed	= cm206_block_media_changed,
-};
-
-static struct gendisk *cm206_gendisk;
-
-/* This function probes for the adapter card. It returns the base
-   address if it has found the adapter card. One can specify a base 
-   port to probe specifically, or 0 which means span all possible
-   bases. 
-
-   Linus says it is too dangerous to use writes for probing, so we
-   stick with pure reads for a while. Hope that 8 possible ranges,
-   request_region, 15 bits of one port and 6 of another make things
-   likely enough to accept the region on the first hit...
- */
-static int __init probe_base_port(int base)
-{
-	int b = 0x300, e = 0x370;	/* this is the range of start addresses */
-	volatile int fool, i;
-
-	if (base)
-		b = e = base;
-	for (base = b; base <= e; base += 0x10) {
-		if (!request_region(base, 0x10,"cm206"))
-			continue;
-		for (i = 0; i < 3; i++)
-			fool = inw(base + 2);	/* empty possibly uart_receive_buffer */
-		if ((inw(base + 6) & 0xffef) != 0x0001 ||	/* line_status */
-		    (inw(base) & 0xad00) != 0)	{ /* data status */
-		    	release_region(base,0x10);
-			continue;
-		}
-		return (base);
-	}
-	return 0;
-}
-
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-static int __init probe_irq(int nr)
-{
-	int irqs, irq;
-	outw(dc_normal | READ_AHEAD, r_data_control);	/* disable irq-generation */
-	sti();
-	irqs = probe_irq_on();
-	reset_cm260();		/* causes interrupt */
-	udelay(100);		/* wait for it */
-	irq = probe_irq_off(irqs);
-	outw(dc_normal | READ_AHEAD, r_data_control);	/* services interrupt */
-	if (nr && irq != nr && irq > 0)
-		return 0;	/* wrong interrupt happened */
-	else
-		return irq;
-}
-#endif
-
-int __init cm206_init(void)
-{
-	uch e = 0;
-	long int size = sizeof(struct cm206_struct);
-	struct gendisk *disk;
-
-	printk(KERN_INFO "cm206 cdrom driver " REVISION);
-	cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
-	if (!cm206_base) {
-		printk(" can't find adapter!\n");
-		return -EIO;
-	}
-	printk(" adapter at 0x%x", cm206_base);
-	cd = kmalloc(size, GFP_KERNEL);
-	if (!cd)
-               goto out_base;
-	/* Now we have found the adaptor card, try to reset it. As we have
-	 * found out earlier, this process generates an interrupt as well,
-	 * so we might just exploit that fact for irq probing! */
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-	cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
-	if (cm206_irq <= 0) {
-		printk("can't find IRQ!\n");
-		goto out_probe;
-	} else
-		printk(" IRQ %d found\n", cm206_irq);
-#else
-	cli();
-	reset_cm260();
-	/* Now, the problem here is that reset_cm260 can generate an
-	   interrupt. It seems that this can cause a kernel oops some time
-	   later. So we wait a while and `service' this interrupt. */
-	mdelay(1);
-	outw(dc_normal | READ_AHEAD, r_data_control);
-	sti();
-	printk(" using IRQ %d\n", cm206_irq);
-#endif
-	if (send_receive_polled(c_drive_configuration) !=
-	    c_drive_configuration) {
-		printk(KERN_INFO " drive not there\n");
-		goto out_probe;
-	}
-	e = send_receive_polled(c_gimme);
-	printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
-	if (e & dcf_transfer_rate)
-		printk(" double");
-	else
-		printk(" single");
-	printk(" speed drive");
-	if (e & dcf_motorized_tray)
-		printk(", motorized tray");
-	if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
-		printk("\nUnable to reserve IRQ---aborted\n");
-		goto out_probe;
-	}
-	printk(".\n");
-
-	if (register_blkdev(MAJOR_NR, "cm206"))
-		goto out_blkdev;
-
-	disk = alloc_disk(1);
-	if (!disk)
-		goto out_disk;
-	disk->major = MAJOR_NR;
-	disk->first_minor = 0;
-	sprintf(disk->disk_name, "cm206cd");
-	disk->fops = &cm206_bdops;
-	disk->flags = GENHD_FL_CD;
-	cm206_gendisk = disk;
-	if (register_cdrom(&cm206_info) != 0) {
-		printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
-		goto out_cdrom;
-	}
-	cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock);
-	if (!cm206_queue)
-		goto out_queue;
-		
-	blk_queue_hardsect_size(cm206_queue, 2048);
-	disk->queue = cm206_queue;
-	add_disk(disk);
-
-	memset(cd, 0, sizeof(*cd));	/* give'm some reasonable value */
-	cd->sector_last = -1;	/* flag no data buffered */
-	cd->adapter_last = -1;
-	init_timer(&cd->timer);
-	cd->timer.function = cm206_timeout;
-	cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
-	printk(KERN_INFO "%d kB adapter memory available, "
-	       " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
-	       size);
-	return 0;
-
-out_queue:
-	unregister_cdrom(&cm206_info);
-out_cdrom:
-	put_disk(disk);
-out_disk:
-	unregister_blkdev(MAJOR_NR, "cm206");
-out_blkdev:
-	free_irq(cm206_irq, NULL);
-out_probe:
-	kfree(cd);
-out_base:
-	release_region(cm206_base, 16);
-	return -EIO;
-}
-
-#ifdef MODULE
-
-
-static void __init parse_options(void)
-{
-	int i;
-	for (i = 0; i < 2; i++) {
-		if (0x300 <= cm206[i] && i <= 0x370
-		    && cm206[i] % 0x10 == 0) {
-			cm206_base = cm206[i];
-			auto_probe = 0;
-		} else if (3 <= cm206[i] && cm206[i] <= 15) {
-			cm206_irq = cm206[i];
-			auto_probe = 0;
-		}
-	}
-}
-
-static int __init __cm206_init(void)
-{
-	parse_options();
-#if !defined(AUTO_PROBE_MODULE)
-	auto_probe = 0;
-#endif
-	return cm206_init();
-}
-
-static void __exit cm206_exit(void)
-{
-	del_gendisk(cm206_gendisk);
-	put_disk(cm206_gendisk);
-	if (unregister_cdrom(&cm206_info)) {
-		printk("Can't unregister cdrom cm206\n");
-		return;
-	}
-	if (unregister_blkdev(MAJOR_NR, "cm206")) {
-		printk("Can't unregister major cm206\n");
-		return;
-	}
-	blk_cleanup_queue(cm206_queue);
-	free_irq(cm206_irq, NULL);
-	kfree(cd);
-	release_region(cm206_base, 16);
-	printk(KERN_INFO "cm206 removed\n");
-}
-
-module_init(__cm206_init);
-module_exit(cm206_exit);
-
-#else				/* !MODULE */
-
-/* This setup function accepts either `auto' or numbers in the range
- * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
-
-static int __init cm206_setup(char *s)
-{
-	int i, p[4];
-
-	(void) get_options(s, ARRAY_SIZE(p), p);
-
-	if (!strcmp(s, "auto"))
-		auto_probe = 1;
-	for (i = 1; i <= p[0]; i++) {
-		if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
-			cm206_base = p[i];
-			auto_probe = 0;
-		} else if (3 <= p[i] && p[i] <= 15) {
-			cm206_irq = p[i];
-			auto_probe = 0;
-		}
-	}
-	return 1;
-}
-
-__setup("cm206=", cm206_setup);
-
-#endif				/* !MODULE */
-MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR);
-
diff --git a/drivers/cdrom/cm206.h b/drivers/cdrom/cm206.h
deleted file mode 100644
index 0ae51c1..0000000
--- a/drivers/cdrom/cm206.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* cm206.h Header file for cm206.c.
-   Copyright (c) 1995 David van Leeuwen 
-*/
-
-#ifndef LINUX_CM206_H
-#define LINUX_CM206_H
-
-#include <linux/ioctl.h>
-
-/* First, the cm260 stuff */
-/* The ports and irq used. Although CM206_BASE and CM206_IRQ are defined
-   below, the values are not used unless autoprobing is turned off and 
-   no LILO boot options or module command line options are given. Change
-   these values to your own as last resort if autoprobing and options
-   don't work. */
-
-#define CM206_BASE 0x340
-#define CM206_IRQ 11
-
-#define r_data_status (cm206_base)
-#define r_uart_receive (cm206_base+0x2)
-#define r_fifo_output_buffer (cm206_base+0x4)
-#define r_line_status (cm206_base+0x6)
-#define r_data_control (cm206_base+0x8)
-#define r_uart_transmit (cm206_base+0xa)
-#define r_test_clock (cm206_base+0xc)
-#define r_test_control (cm206_base+0xe)
-
-/* the data_status flags */
-#define ds_ram_size 0x4000
-#define ds_toc_ready 0x2000
-#define ds_fifo_empty 0x1000
-#define ds_sync_error 0x800
-#define ds_crc_error 0x400
-#define ds_data_error 0x200
-#define ds_fifo_overflow 0x100
-#define ds_data_ready 0x80
-
-/* the line_status flags */
-#define ls_attention 0x10
-#define ls_parity_error 0x8
-#define ls_overrun 0x4
-#define ls_receive_buffer_full 0x2
-#define ls_transmitter_buffer_empty 0x1
-
-/* the data control register flags */
-#define dc_read_q_channel 0x4000
-#define dc_mask_sync_error 0x2000
-#define dc_toc_enable 0x1000
-#define dc_no_stop_on_error 0x800
-#define dc_break 0x400
-#define dc_initialize 0x200
-#define dc_mask_transmit_ready 0x100
-#define dc_flag_enable 0x80
-
-/* Define the default data control register flags here */
-#define dc_normal (dc_mask_sync_error | dc_no_stop_on_error | \
-		   dc_mask_transmit_ready)
-
-/* now some constants related to the cm206 */
-/* another drive status byte, echoed by the cm206 on most commands */
-
-#define dsb_error_condition 0x1
-#define dsb_play_in_progress 0x4
-#define dsb_possible_media_change 0x8
-#define dsb_disc_present 0x10
-#define dsb_drive_not_ready 0x20
-#define dsb_tray_locked 0x40
-#define dsb_tray_not_closed 0x80
-
-#define dsb_not_useful (dsb_drive_not_ready | dsb_tray_not_closed)
-
-/* the cm206 command set */
-
-#define c_close_tray 0
-#define c_lock_tray 0x01
-#define c_unlock_tray 0x04
-#define c_open_tray 0x05
-#define c_seek 0x10
-#define c_read_data 0x20
-#define c_force_1x 0x21
-#define c_force_2x 0x22
-#define c_auto_mode 0x23
-#define c_play 0x30
-#define c_set_audio_mode 0x31
-#define c_read_current_q 0x41
-#define c_stream_q 0x42
-#define c_drive_status 0x50
-#define c_disc_status 0x51
-#define c_audio_status 0x52
-#define c_drive_configuration 0x53
-#define c_read_upc 0x60
-#define c_stop 0x70
-#define c_calc_checksum 0xe5
-
-#define c_gimme 0xf8
-
-/* finally, the (error) condition that the drive can be in      *
- * OK, this is not always an error, but let's prefix it with e_ */
-
-#define e_none 0
-#define e_illegal_command 0x01
-#define e_sync 0x02
-#define e_seek 0x03
-#define e_parity 0x04
-#define e_focus 0x05
-#define e_header_sync 0x06
-#define e_code_incompatibility 0x07
-#define e_reset_done 0x08
-#define e_bad_parameter 0x09
-#define e_radial 0x0a
-#define e_sub_code 0x0b
-#define e_no_data_track 0x0c
-#define e_scan 0x0d
-#define e_tray_open 0x0f
-#define e_no_disc 0x10
-#define e_tray stalled 0x11
-
-/* drive configuration masks */
-
-#define dcf_revision_code 0x7
-#define dcf_transfer_rate 0x60
-#define dcf_motorized_tray 0x80
-
-/* disc status byte */
-
-#define cds_multi_session 0x2
-#define cds_all_audio 0x8
-#define cds_xa_mode 0xf0
-
-/* finally some ioctls for the driver */
-
-#define CM206CTL_GET_STAT _IO( 0x20, 0 )
-#define CM206CTL_GET_LAST_STAT _IO( 0x20, 1 )
-
-#ifdef STATISTICS
-
-/* This is an ugly way to guarantee that the names of the statistics
- * are the same in the code and in the diagnostics program.  */
-
-#ifdef __KERNEL__
-#define x(a) st_ ## a
-#define y enum
-#else
-#define x(a) #a
-#define y char * stats_name[] = 
-#endif
-
-y {x(interrupt), x(data_ready), x(fifo_overflow), x(data_error),
-     x(crc_error), x(sync_error), x(lost_intr), x(echo),
-     x(write_timeout), x(receive_timeout), x(read_timeout),
-     x(dsb_timeout), x(stop_0xff), x(back_read_timeout),
-     x(sector_transferred), x(read_restarted), x(read_background),
-     x(bh), x(open), x(ioctl_multisession), x(attention)
-#ifdef __KERNEL__
-     , x(last_entry)
-#endif
- };
-
-#ifdef __KERNEL__
-#define NR_STATS st_last_entry
-#else
-#define NR_STATS (sizeof(stats_name)/sizeof(char*))
-#endif
-
-#undef y
-#undef x
-
-#endif /* STATISTICS */
-
-#endif /* LINUX_CM206_H */
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
deleted file mode 100644
index b3ab6e9..0000000
--- a/drivers/cdrom/gscd.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-#define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
-
-/*
-	linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
-
-        Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
-        based upon pre-works by   Eberhard Moenkeberg <emoenke@gwdg.de>
-        
-
-        For all kind of other information about the GoldStar CDROM
-        and this Linux device driver I installed a WWW-URL:
-        http://linux.rz.fh-hannover.de/~raupach        
-
-
-             If you are the editor of a Linux CD, you should
-             enable gscd.c within your boot floppy kernel and
-             send me one of your CDs for free.
-
-
-        --------------------------------------------------------------------
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2, or (at your option)
-	any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-	
-	--------------------------------------------------------------------
-	
-	9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
-	                   Removed init_module & cleanup_module in favor of 
-		   	   module_init & module_exit.
-			   Torben Mathiasen <tmm@image.dk>
-
-*/
-
-/* These settings are for various debug-level. Leave they untouched ... */
-#define  NO_GSCD_DEBUG
-#define  NO_IOCTL_DEBUG
-#define  NO_MODULE_DEBUG
-#define  NO_FUTURE_WORK
-/*------------------------*/
-
-#include <linux/module.h>
-
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#include <linux/blkdev.h>
-#include "gscd.h"
-
-static int gscdPresent = 0;
-
-static unsigned char gscd_buf[2048];	/* buffer for block size conversion */
-static int gscd_bn = -1;
-static short gscd_port = GSCD_BASE_ADDR;
-module_param_named(gscd, gscd_port, short, 0);
-
-/* Kommt spaeter vielleicht noch mal dran ...
- *    static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
- */
-
-static void gscd_read_cmd(struct request *req);
-static void gscd_hsg2msf(long hsg, struct msf *msf);
-static void gscd_bin2bcd(unsigned char *p);
-
-/* Schnittstellen zum Kern/FS */
-
-static void __do_gscd_request(unsigned long dummy);
-static int gscd_ioctl(struct inode *, struct file *, unsigned int,
-		      unsigned long);
-static int gscd_open(struct inode *, struct file *);
-static int gscd_release(struct inode *, struct file *);
-static int check_gscd_med_chg(struct gendisk *disk);
-
-/*      GoldStar Funktionen    */
-
-static void cmd_out(int, char *, char *, int);
-static void cmd_status(void);
-static void init_cd_drive(int);
-
-static int get_status(void);
-static void clear_Audio(void);
-static void cc_invalidate(void);
-
-/* some things for the next version */
-#ifdef FUTURE_WORK
-static void update_state(void);
-static long gscd_msf2hsg(struct msf *mp);
-static int gscd_bcd2bin(unsigned char bcd);
-#endif
-
-
-/*      lo-level cmd-Funktionen    */
-
-static void cmd_info_in(char *, int);
-static void cmd_end(void);
-static void cmd_read_b(char *, int, int);
-static void cmd_read_w(char *, int, int);
-static int cmd_unit_alive(void);
-static void cmd_write_cmd(char *);
-
-
-/*      GoldStar Variablen     */
-
-static int curr_drv_state;
-static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-static int drv_mode;
-static int disk_state;
-static int speed;
-static int ndrives;
-
-static unsigned char drv_num_read;
-static unsigned char f_dsk_valid;
-static unsigned char current_drive;
-static unsigned char f_drv_ok;
-
-
-static char f_AudioPlay;
-static char f_AudioPause;
-static int AudioStart_m;
-static int AudioStart_f;
-static int AudioEnd_m;
-static int AudioEnd_f;
-
-static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
-static DEFINE_SPINLOCK(gscd_lock);
-static struct request_queue *gscd_queue;
-
-static struct block_device_operations gscd_fops = {
-	.owner		= THIS_MODULE,
-	.open		= gscd_open,
-	.release	= gscd_release,
-	.ioctl		= gscd_ioctl,
-	.media_changed	= check_gscd_med_chg,
-};
-
-/* 
- * Checking if the media has been changed
- * (not yet implemented)
- */
-static int check_gscd_med_chg(struct gendisk *disk)
-{
-#ifdef GSCD_DEBUG
-	printk("gscd: check_med_change\n");
-#endif
-	return 0;
-}
-
-
-#ifndef MODULE
-/* Using new interface for kernel-parameters */
-
-static int __init gscd_setup(char *str)
-{
-	int ints[2];
-	(void) get_options(str, ARRAY_SIZE(ints), ints);
-
-	if (ints[0] > 0) {
-		gscd_port = ints[1];
-	}
-	return 1;
-}
-
-__setup("gscd=", gscd_setup);
-
-#endif
-
-static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-		      unsigned long arg)
-{
-	unsigned char to_do[10];
-	unsigned char dummy;
-
-
-	switch (cmd) {
-	case CDROMSTART:	/* Spin up the drive */
-		/* Don't think we can do this.  Even if we could,
-		 * I think the drive times out and stops after a while
-		 * anyway.  For now, ignore it.
-		 */
-		return 0;
-
-	case CDROMRESUME:	/* keine Ahnung was das ist */
-		return 0;
-
-
-	case CDROMEJECT:
-		cmd_status();
-		to_do[0] = CMD_TRAY_CTL;
-		cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-		return 0;
-
-	default:
-		return -EINVAL;
-	}
-
-}
-
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static void gscd_transfer(struct request *req)
-{
-	while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) {
-		long offs = (req->sector & 3) * 512;
-		memcpy(req->buffer, gscd_buf + offs, 512);
-		req->nr_sectors--;
-		req->sector++;
-		req->buffer += 512;
-	}
-}
-
-
-/*
- * I/O request routine called from Linux kernel.
- */
-
-static void do_gscd_request(request_queue_t * q)
-{
-	__do_gscd_request(0);
-}
-
-static void __do_gscd_request(unsigned long dummy)
-{
-	struct request *req;
-	unsigned int block;
-	unsigned int nsect;
-
-repeat:
-	req = elv_next_request(gscd_queue);
-	if (!req)
-		return;
-
-	block = req->sector;
-	nsect = req->nr_sectors;
-
-	if (req->sector == -1)
-		goto out;
-
-	if (req->cmd != READ) {
-		printk("GSCD: bad cmd %u\n", rq_data_dir(req));
-		end_request(req, 0);
-		goto repeat;
-	}
-
-	gscd_transfer(req);
-
-	/* if we satisfied the request from the buffer, we're done. */
-
-	if (req->nr_sectors == 0) {
-		end_request(req, 1);
-		goto repeat;
-	}
-#ifdef GSCD_DEBUG
-	printk("GSCD: block %d, nsect %d\n", block, nsect);
-#endif
-	gscd_read_cmd(req);
-out:
-	return;
-}
-
-
-
-/*
- * Check the result of the set-mode command.  On success, send the
- * read-data command.
- */
-
-static void gscd_read_cmd(struct request *req)
-{
-	long block;
-	struct gscd_Play_msf gscdcmd;
-	char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 };	/* cmd mode M-S-F secth sectl */
-
-	cmd_status();
-	if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
-		printk("GSCD: no disk or door open\n");
-		end_request(req, 0);
-	} else {
-		if (disk_state & ST_INVALID) {
-			printk("GSCD: disk invalid\n");
-			end_request(req, 0);
-		} else {
-			gscd_bn = -1;	/* purge our buffer */
-			block = req->sector / 4;
-			gscd_hsg2msf(block, &gscdcmd.start);	/* cvt to msf format */
-
-			cmd[2] = gscdcmd.start.min;
-			cmd[3] = gscdcmd.start.sec;
-			cmd[4] = gscdcmd.start.frame;
-
-#ifdef GSCD_DEBUG
-			printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3],
-			       cmd[4]);
-#endif
-			cmd_out(TYPE_DATA, (char *) &cmd,
-				(char *) &gscd_buf[0], 1);
-
-			gscd_bn = req->sector / 4;
-			gscd_transfer(req);
-			end_request(req, 1);
-		}
-	}
-	SET_TIMER(__do_gscd_request, 1);
-}
-
-
-/*
- * Open the device special file.  Check that a disk is in.
- */
-
-static int gscd_open(struct inode *ip, struct file *fp)
-{
-	int st;
-
-#ifdef GSCD_DEBUG
-	printk("GSCD: open\n");
-#endif
-
-	if (gscdPresent == 0)
-		return -ENXIO;	/* no hardware */
-
-	get_status();
-	st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
-	if (st) {
-		printk("GSCD: no disk or door open\n");
-		return -ENXIO;
-	}
-
-/*	if (updateToc() < 0)
-		return -EIO;
-*/
-
-	return 0;
-}
-
-
-/*
- * On close, we flush all gscd blocks from the buffer cache.
- */
-
-static int gscd_release(struct inode *inode, struct file *file)
-{
-
-#ifdef GSCD_DEBUG
-	printk("GSCD: release\n");
-#endif
-
-	gscd_bn = -1;
-
-	return 0;
-}
-
-
-static int get_status(void)
-{
-	int status;
-
-	cmd_status();
-	status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
-
-	if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) {
-		cc_invalidate();
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-
-static void cc_invalidate(void)
-{
-	drv_num_read = 0xFF;
-	f_dsk_valid = 0xFF;
-	current_drive = 0xFF;
-	f_drv_ok = 0xFF;
-
-	clear_Audio();
-
-}
-
-static void clear_Audio(void)
-{
-
-	f_AudioPlay = 0;
-	f_AudioPause = 0;
-	AudioStart_m = 0;
-	AudioStart_f = 0;
-	AudioEnd_m = 0;
-	AudioEnd_f = 0;
-
-}
-
-/*
- *   waiting ?  
- */
-
-static int wait_drv_ready(void)
-{
-	int found, read;
-
-	do {
-		found = inb(GSCDPORT(0));
-		found &= 0x0f;
-		read = inb(GSCDPORT(0));
-		read &= 0x0f;
-	} while (read != found);
-
-#ifdef GSCD_DEBUG
-	printk("Wait for: %d\n", read);
-#endif
-
-	return read;
-}
-
-static void cc_Ident(char *respons)
-{
-	char to_do[] = { CMD_IDENT, 0, 0 };
-
-	cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E);
-
-}
-
-static void cc_SetSpeed(void)
-{
-	char to_do[] = { CMD_SETSPEED, 0, 0 };
-	char dummy;
-
-	if (speed > 0) {
-		to_do[1] = speed & 0x0F;
-		cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-	}
-}
-
-static void cc_Reset(void)
-{
-	char to_do[] = { CMD_RESET, 0 };
-	char dummy;
-
-	cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-}
-
-static void cmd_status(void)
-{
-	char to_do[] = { CMD_STATUS, 0 };
-	char dummy;
-
-	cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-#ifdef GSCD_DEBUG
-	printk("GSCD: Status: %d\n", disk_state);
-#endif
-
-}
-
-static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
-{
-	int result;
-
-
-	result = wait_drv_ready();
-	if (result != drv_mode) {
-		unsigned long test_loops = 0xFFFF;
-		int i, dummy;
-
-		outb(curr_drv_state, GSCDPORT(0));
-
-		/* LOCLOOP_170 */
-		do {
-			result = wait_drv_ready();
-			test_loops--;
-		} while ((result != drv_mode) && (test_loops > 0));
-
-		if (result != drv_mode) {
-			disk_state = ST_x08 | ST_x04 | ST_INVALID;
-			return;
-		}
-
-		/* ...and waiting */
-		for (i = 1, dummy = 1; i < 0xFFFF; i++) {
-			dummy *= i;
-		}
-	}
-
-	/* LOC_172 */
-	/* check the unit */
-	/* and wake it up */
-	if (cmd_unit_alive() != 0x08) {
-		/* LOC_174 */
-		/* game over for this unit */
-		disk_state = ST_x08 | ST_x04 | ST_INVALID;
-		return;
-	}
-
-	/* LOC_176 */
-#ifdef GSCD_DEBUG
-	printk("LOC_176 ");
-#endif
-	if (drv_mode == 0x09) {
-		/* magic... */
-		printk("GSCD: magic ...\n");
-		outb(result, GSCDPORT(2));
-	}
-
-	/* write the command to the drive */
-	cmd_write_cmd(cmd);
-
-	/* LOC_178 */
-	for (;;) {
-		result = wait_drv_ready();
-		if (result != drv_mode) {
-			/* LOC_179 */
-			if (result == 0x04) {	/* Mode 4 */
-				/* LOC_205 */
-#ifdef GSCD_DEBUG
-				printk("LOC_205 ");
-#endif
-				disk_state = inb(GSCDPORT(2));
-
-				do {
-					result = wait_drv_ready();
-				} while (result != drv_mode);
-				return;
-
-			} else {
-				if (result == 0x06) {	/* Mode 6 */
-					/* LOC_181 */
-#ifdef GSCD_DEBUG
-					printk("LOC_181 ");
-#endif
-
-					if (cmd_type == TYPE_DATA) {
-						/* read data */
-						/* LOC_184 */
-						if (drv_mode == 9) {
-							/* read the data to the buffer (word) */
-
-							/* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
-							cmd_read_w
-							    (respo_buf,
-							     respo_count,
-							     CD_FRAMESIZE /
-							     2);
-							return;
-						} else {
-							/* read the data to the buffer (byte) */
-
-							/* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW)    */
-							cmd_read_b
-							    (respo_buf,
-							     respo_count,
-							     CD_FRAMESIZE);
-							return;
-						}
-					} else {
-						/* read the info to the buffer */
-						cmd_info_in(respo_buf,
-							    respo_count);
-						return;
-					}
-
-					return;
-				}
-			}
-
-		} else {
-			disk_state = ST_x08 | ST_x04 | ST_INVALID;
-			return;
-		}
-	}			/* for (;;) */
-
-
-#ifdef GSCD_DEBUG
-	printk("\n");
-#endif
-}
-
-
-static void cmd_write_cmd(char *pstr)
-{
-	int i, j;
-
-	/* LOC_177 */
-#ifdef GSCD_DEBUG
-	printk("LOC_177 ");
-#endif
-
-	/* calculate the number of parameter */
-	j = *pstr & 0x0F;
-
-	/* shift it out */
-	for (i = 0; i < j; i++) {
-		outb(*pstr, GSCDPORT(2));
-		pstr++;
-	}
-}
-
-
-static int cmd_unit_alive(void)
-{
-	int result;
-	unsigned long max_test_loops;
-
-
-	/* LOC_172 */
-#ifdef GSCD_DEBUG
-	printk("LOC_172 ");
-#endif
-
-	outb(curr_drv_state, GSCDPORT(0));
-	max_test_loops = 0xFFFF;
-
-	do {
-		result = wait_drv_ready();
-		max_test_loops--;
-	} while ((result != 0x08) && (max_test_loops > 0));
-
-	return result;
-}
-
-
-static void cmd_info_in(char *pb, int count)
-{
-	int result;
-	char read;
-
-
-	/* read info */
-	/* LOC_182 */
-#ifdef GSCD_DEBUG
-	printk("LOC_182 ");
-#endif
-
-	do {
-		read = inb(GSCDPORT(2));
-		if (count > 0) {
-			*pb = read;
-			pb++;
-			count--;
-		}
-
-		/* LOC_183 */
-		do {
-			result = wait_drv_ready();
-		} while (result == 0x0E);
-	} while (result == 6);
-
-	cmd_end();
-	return;
-}
-
-
-static void cmd_read_b(char *pb, int count, int size)
-{
-	int result;
-	int i;
-
-
-	/* LOC_188 */
-	/* LOC_189 */
-#ifdef GSCD_DEBUG
-	printk("LOC_189 ");
-#endif
-
-	do {
-		do {
-			result = wait_drv_ready();
-		} while (result != 6 || result == 0x0E);
-
-		if (result != 6) {
-			cmd_end();
-			return;
-		}
-#ifdef GSCD_DEBUG
-		printk("LOC_191 ");
-#endif
-
-		for (i = 0; i < size; i++) {
-			*pb = inb(GSCDPORT(2));
-			pb++;
-		}
-		count--;
-	} while (count > 0);
-
-	cmd_end();
-	return;
-}
-
-
-static void cmd_end(void)
-{
-	int result;
-
-
-	/* LOC_204 */
-#ifdef GSCD_DEBUG
-	printk("LOC_204 ");
-#endif
-
-	do {
-		result = wait_drv_ready();
-		if (result == drv_mode) {
-			return;
-		}
-	} while (result != 4);
-
-	/* LOC_205 */
-#ifdef GSCD_DEBUG
-	printk("LOC_205 ");
-#endif
-
-	disk_state = inb(GSCDPORT(2));
-
-	do {
-		result = wait_drv_ready();
-	} while (result != drv_mode);
-	return;
-
-}
-
-
-static void cmd_read_w(char *pb, int count, int size)
-{
-	int result;
-	int i;
-
-
-#ifdef GSCD_DEBUG
-	printk("LOC_185 ");
-#endif
-
-	do {
-		/* LOC_185 */
-		do {
-			result = wait_drv_ready();
-		} while (result != 6 || result == 0x0E);
-
-		if (result != 6) {
-			cmd_end();
-			return;
-		}
-
-		for (i = 0; i < size; i++) {
-			/* na, hier muss ich noch mal drueber nachdenken */
-			*pb = inw(GSCDPORT(2));
-			pb++;
-		}
-		count--;
-	} while (count > 0);
-
-	cmd_end();
-	return;
-}
-
-static int __init find_drives(void)
-{
-	int *pdrv;
-	int drvnum;
-	int subdrv;
-	int i;
-
-	speed = 0;
-	pdrv = (int *) &drv_states;
-	curr_drv_state = 0xFE;
-	subdrv = 0;
-	drvnum = 0;
-
-	for (i = 0; i < 8; i++) {
-		subdrv++;
-		cmd_status();
-		disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
-		if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
-			/* LOC_240 */
-			*pdrv = curr_drv_state;
-			init_cd_drive(drvnum);
-			pdrv++;
-			drvnum++;
-		} else {
-			if (subdrv < 2) {
-				continue;
-			} else {
-				subdrv = 0;
-			}
-		}
-
-/*       curr_drv_state<<1;         <-- das geht irgendwie nicht */
-/* muss heissen:    curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
-		curr_drv_state *= 2;
-		curr_drv_state |= 1;
-#ifdef GSCD_DEBUG
-		printk("DriveState: %d\n", curr_drv_state);
-#endif
-	}
-
-	ndrives = drvnum;
-	return drvnum;
-}
-
-static void __init init_cd_drive(int num)
-{
-	char resp[50];
-	int i;
-
-	printk("GSCD: init unit %d\n", num);
-	cc_Ident((char *) &resp);
-
-	printk("GSCD: identification: ");
-	for (i = 0; i < 0x1E; i++) {
-		printk("%c", resp[i]);
-	}
-	printk("\n");
-
-	cc_SetSpeed();
-
-}
-
-#ifdef FUTURE_WORK
-/* return_done */
-static void update_state(void)
-{
-	unsigned int AX;
-
-
-	if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
-		if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
-			AX = ST_INVALID;
-		}
-
-		if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
-		    == 0) {
-			invalidate();
-			f_drv_ok = 0;
-		}
-
-		AX |= 0x8000;
-	}
-
-	if (disk_state & ST_PLAYING) {
-		AX |= 0x200;
-	}
-
-	AX |= 0x100;
-	/* pkt_esbx = AX; */
-
-	disk_state = 0;
-
-}
-#endif
-
-static struct gendisk *gscd_disk;
-
-static void __exit gscd_exit(void)
-{
-	CLEAR_TIMER;
-
-	del_gendisk(gscd_disk);
-	put_disk(gscd_disk);
-	if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
-		printk("What's that: can't unregister GoldStar-module\n");
-		return;
-	}
-	blk_cleanup_queue(gscd_queue);
-	release_region(gscd_port, GSCD_IO_EXTENT);
-	printk(KERN_INFO "GoldStar-module released.\n");
-}
-
-/* This is the common initialisation for the GoldStar drive. */
-/* It is called at boot time AND for module init.           */
-static int __init gscd_init(void)
-{
-	int i;
-	int result;
-	int ret=0;
-
-	printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
-	printk(KERN_INFO
-	       "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n",
-	       gscd_port);
-
-	if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) {
-		printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already"
-		       " in use.\n", gscd_port);
-		return -EIO;
-	}
-
-
-	/* check for card */
-	result = wait_drv_ready();
-	if (result == 0x09) {
-		printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n");
-		ret = -EIO;
-		goto err_out1;
-	}
-
-	if (result == 0x0b) {
-		drv_mode = result;
-		i = find_drives();
-		if (i == 0) {
-			printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is"
-			       " not found.\n");
-			ret = -EIO;
-			goto err_out1;
-		}
-	}
-
-	if ((result != 0x0b) && (result != 0x09)) {
-		printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not "
-		       "exist or H/W error\n");
-		ret = -EIO;
-		goto err_out1;
-	}
-
-	/* reset all drives */
-	i = 0;
-	while (drv_states[i] != 0) {
-		curr_drv_state = drv_states[i];
-		printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
-		cc_Reset();
-		printk("done\n");
-		i++;
-	}
-
-	gscd_disk = alloc_disk(1);
-	if (!gscd_disk)
-		goto err_out1;
-	gscd_disk->major = MAJOR_NR;
-	gscd_disk->first_minor = 0;
-	gscd_disk->fops = &gscd_fops;
-	sprintf(gscd_disk->disk_name, "gscd");
-
-	if (register_blkdev(MAJOR_NR, "gscd")) {
-		ret = -EIO;
-		goto err_out2;
-	}
-
-	gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock);
-	if (!gscd_queue) {
-		ret = -ENOMEM;
-		goto err_out3;
-	}
-
-	disk_state = 0;
-	gscdPresent = 1;
-
-	gscd_disk->queue = gscd_queue;
-	add_disk(gscd_disk);
-
-	printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
-	return 0;
-
-err_out3:
-	unregister_blkdev(MAJOR_NR, "gscd");
-err_out2:
-	put_disk(gscd_disk);
-err_out1:
-	release_region(gscd_port, GSCD_IO_EXTENT);
-	return ret;
-}
-
-static void gscd_hsg2msf(long hsg, struct msf *msf)
-{
-	hsg += CD_MSF_OFFSET;
-	msf->min = hsg / (CD_FRAMES * CD_SECS);
-	hsg %= CD_FRAMES * CD_SECS;
-	msf->sec = hsg / CD_FRAMES;
-	msf->frame = hsg % CD_FRAMES;
-
-	gscd_bin2bcd(&msf->min);	/* convert to BCD */
-	gscd_bin2bcd(&msf->sec);
-	gscd_bin2bcd(&msf->frame);
-}
-
-
-static void gscd_bin2bcd(unsigned char *p)
-{
-	int u, t;
-
-	u = *p % 10;
-	t = *p / 10;
-	*p = u | (t << 4);
-}
-
-
-#ifdef FUTURE_WORK
-static long gscd_msf2hsg(struct msf *mp)
-{
-	return gscd_bcd2bin(mp->frame)
-	    + gscd_bcd2bin(mp->sec) * CD_FRAMES
-	    + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
-}
-
-static int gscd_bcd2bin(unsigned char bcd)
-{
-	return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-#endif
-
-MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
-MODULE_LICENSE("GPL");
-module_init(gscd_init);
-module_exit(gscd_exit);
-MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR);
diff --git a/drivers/cdrom/gscd.h b/drivers/cdrom/gscd.h
deleted file mode 100644
index a41e64b..0000000
--- a/drivers/cdrom/gscd.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Definitions for a GoldStar R420 CD-ROM interface
- *
- *   Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- *                       Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- *  Published under the GPL.
- *
- */
-
-
-/* The Interface Card default address is 0x340. This will work for most
-   applications. Address selection is accomplished by jumpers PN801-1 to
-   PN801-4 on the GoldStar Interface Card.
-   Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
-   0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0             */
-
-/* insert here the I/O port address and extent */
-#define GSCD_BASE_ADDR	        0x340
-#define GSCD_IO_EXTENT          4
-
-
-/************** nothing to set up below here *********************/
-
-/* port access macro */
-#define GSCDPORT(x)		(gscd_port + (x))
-
-/*
- * commands
- * the lower nibble holds the command length
- */
-#define CMD_STATUS     0x01
-#define CMD_READSUBQ   0x02 /* 1: ?, 2: UPC, 5: ? */
-#define CMD_SEEK       0x05 /* read_mode M-S-F */
-#define CMD_READ       0x07 /* read_mode M-S-F nsec_h nsec_l */
-#define CMD_RESET      0x11
-#define CMD_SETMODE    0x15
-#define CMD_PLAY       0x17 /* M-S-F M-S-F */
-#define CMD_LOCK_CTL   0x22 /* 0: unlock, 1: lock */
-#define CMD_IDENT      0x31
-#define CMD_SETSPEED   0x32 /* 0: auto */ /* ??? */
-#define CMD_GETMODE    0x41
-#define CMD_PAUSE      0x51
-#define CMD_READTOC    0x61
-#define CMD_DISKINFO   0x71
-#define CMD_TRAY_CTL   0x81
-
-/*
- * disk_state:
- */
-#define ST_PLAYING	0x80
-#define ST_UNLOCKED	0x40
-#define ST_NO_DISK	0x20
-#define ST_DOOR_OPEN	0x10
-#define ST_x08  0x08
-#define ST_x04	0x04
-#define ST_INVALID	0x02
-#define ST_x01	0x01
-
-/*
- * cmd_type:
- */
-#define TYPE_INFO	0x01
-#define TYPE_DATA	0x02
-
-/*
- * read_mode:
- */
-#define MOD_POLLED	0x80
-#define MOD_x08	0x08
-#define MOD_RAW	0x04
-
-#define READ_DATA(port, buf, nr) insb(port, buf, nr)
-
-#define SET_TIMER(func, jifs) \
-	((mod_timer(&gscd_timer, jiffies + jifs)), \
-	(gscd_timer.function = func))
-
-#define CLEAR_TIMER		del_timer_sync(&gscd_timer)
-
-#define MAX_TRACKS		104
-
-struct msf {
-	unsigned char	min;
-	unsigned char	sec;
-	unsigned char	frame;
-};
-
-struct gscd_Play_msf {
-	struct msf	start;
-	struct msf	end;
-};
-
-struct gscd_DiskInfo {
-	unsigned char	first;
-	unsigned char	last;
-	struct msf	diskLength;
-	struct msf	firstTrack;
-};
-
-struct gscd_Toc {
-	unsigned char	ctrl_addr;
-	unsigned char	track;
-	unsigned char	pointIndex;
-	struct msf	trackTime;
-	struct msf	diskTime;
-};
-
diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c
deleted file mode 100644
index db0fd9a..0000000
--- a/drivers/cdrom/isp16.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* -- ISP16 cdrom detection and configuration
- *
- *    Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
- *
- *    Version 0.6
- *
- *    History:
- *    0.5 First release.
- *        Was included in the sjcd and optcd cdrom drivers.
- *    0.6 First "stand-alone" version.
- *        Removed sound configuration.
- *        Added "module" support.
- *
- *      9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	                   Removed init_module & cleanup_module in favor of 
- *			   module_init & module_exit.
- *			   Torben Mathiasen <tmm@image.dk>
- *
- *     19 June 2004     -- check_region() converted to request_region()
- *                         and return statement cleanups.
- *                          - Jesper Juhl
- *
- *    Detect cdrom interface on ISP16 sound card.
- *    Configure cdrom interface.
- *
- *    Algorithm for the card with OPTi 82C928 taken
- *    from the CDSETUP.SYS driver for MSDOS,
- *    by OPTi Computers, version 2.03.
- *    Algorithm for the card with OPTi 82C929 as communicated
- *    to me by Vadim Model and Leo Spiekman.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define ISP16_VERSION_MAJOR 0
-#define ISP16_VERSION_MINOR 6
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include "isp16.h"
-
-static short isp16_detect(void);
-static short isp16_c928__detect(void);
-static short isp16_c929__detect(void);
-static short isp16_cdi_config(int base, u_char drive_type, int irq,
-			      int dma);
-static short isp16_type;	/* dependent on type of interface card */
-static u_char isp16_ctrl;
-static u_short isp16_enable_port;
-
-static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
-static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
-static int isp16_cdrom_dma = ISP16_CDROM_DMA;
-static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
-
-module_param(isp16_cdrom_base, int, 0);
-module_param(isp16_cdrom_irq, int, 0);
-module_param(isp16_cdrom_dma, int, 0);
-module_param(isp16_cdrom_type, charp, 0);
-
-#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
-#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
-
-#ifndef MODULE
-
-static int
-__init isp16_setup(char *str)
-{
-	int ints[4];
-
-	(void) get_options(str, ARRAY_SIZE(ints), ints);
-	if (ints[0] > 0)
-		isp16_cdrom_base = ints[1];
-	if (ints[0] > 1)
-		isp16_cdrom_irq = ints[2];
-	if (ints[0] > 2)
-		isp16_cdrom_dma = ints[3];
-	if (str)
-		isp16_cdrom_type = str;
-
-	return 1;
-}
-
-__setup("isp16=", isp16_setup);
-
-#endif				/* MODULE */
-
-/*
- *  ISP16 initialisation.
- *
- */
-static int __init isp16_init(void)
-{
-	u_char expected_drive;
-
-	printk(KERN_INFO
-	       "ISP16: configuration cdrom interface, version %d.%d.\n",
-	       ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR);
-
-	if (!strcmp(isp16_cdrom_type, "noisp16")) {
-		printk("ISP16: no cdrom interface configured.\n");
-		return 0;
-	}
-
-	if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) {
-		printk("ISP16: i/o ports already in use.\n");
-		goto out;
-	}
-
-	if ((isp16_type = isp16_detect()) < 0) {
-		printk("ISP16: no cdrom interface found.\n");
-		goto cleanup_out;
-	}
-
-	printk(KERN_INFO
-	       "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n",
-	       (isp16_type == 2) ? 9 : 8);
-
-	if (!strcmp(isp16_cdrom_type, "Sanyo"))
-		expected_drive =
-		    (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
-	else if (!strcmp(isp16_cdrom_type, "Sony"))
-		expected_drive = ISP16_SONY;
-	else if (!strcmp(isp16_cdrom_type, "Panasonic"))
-		expected_drive =
-		    (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
-	else if (!strcmp(isp16_cdrom_type, "Mitsumi"))
-		expected_drive = ISP16_MITSUMI;
-	else {
-		printk("ISP16: %s not supported by cdrom interface.\n",
-		       isp16_cdrom_type);
-		goto cleanup_out;
-	}
-
-	if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
-			     isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
-		printk
-		    ("ISP16: cdrom interface has not been properly configured.\n");
-		goto cleanup_out;
-	}
-	printk(KERN_INFO
-	       "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
-	       " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq,
-	       isp16_cdrom_dma, isp16_cdrom_type);
-	return 0;
-
-cleanup_out:
-	release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-out:
-	return -EIO;
-}
-
-static short __init isp16_detect(void)
-{
-
-	if (isp16_c929__detect() >= 0)
-		return 2;
-	else
-		return (isp16_c928__detect());
-}
-
-static short __init isp16_c928__detect(void)
-{
-	u_char ctrl;
-	u_char enable_cdrom;
-	u_char io;
-	short i = -1;
-
-	isp16_ctrl = ISP16_C928__CTRL;
-	isp16_enable_port = ISP16_C928__ENABLE_PORT;
-
-	/* read' and write' are a special read and write, respectively */
-
-	/* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
-	ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC;
-	ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-	/* read' 3,4 and 5-bit from the cdrom enable port */
-	enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38;
-
-	if (!(enable_cdrom & 0x20)) {	/* 5-bit not set */
-		/* read' last 2 bits of ISP16_IO_SET_PORT */
-		io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03;
-		if (((io & 0x01) << 1) == (io & 0x02)) {	/* bits are the same */
-			if (io == 0) {	/* ...the same and 0 */
-				i = 0;
-				enable_cdrom |= 0x20;
-			} else {	/* ...the same and 1 *//* my card, first time 'round */
-				i = 1;
-				enable_cdrom |= 0x28;
-			}
-			ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
-		} else {	/* bits are not the same */
-			ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-			return i;	/* -> not detected: possibly incorrect conclusion */
-		}
-	} else if (enable_cdrom == 0x20)
-		i = 0;
-	else if (enable_cdrom == 0x28)	/* my card, already initialised */
-		i = 1;
-
-	ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-	return i;
-}
-
-static short __init isp16_c929__detect(void)
-{
-	u_char ctrl;
-	u_char tmp;
-
-	isp16_ctrl = ISP16_C929__CTRL;
-	isp16_enable_port = ISP16_C929__ENABLE_PORT;
-
-	/* read' and write' are a special read and write, respectively */
-
-	/* read' ISP16_CTRL_PORT and save */
-	ctrl = ISP16_IN(ISP16_CTRL_PORT);
-
-	/* write' zero to the ctrl port and get response */
-	ISP16_OUT(ISP16_CTRL_PORT, 0);
-	tmp = ISP16_IN(ISP16_CTRL_PORT);
-
-	if (tmp != 2)		/* isp16 with 82C929 not detected */
-		return -1;
-
-	/* restore ctrl port value */
-	ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-	return 2;
-}
-
-static short __init
-isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
-{
-	u_char base_code;
-	u_char irq_code;
-	u_char dma_code;
-	u_char i;
-
-	if ((drive_type == ISP16_MITSUMI) && (dma != 0))
-		printk("ISP16: Mitsumi cdrom drive has no dma support.\n");
-
-	switch (base) {
-	case 0x340:
-		base_code = ISP16_BASE_340;
-		break;
-	case 0x330:
-		base_code = ISP16_BASE_330;
-		break;
-	case 0x360:
-		base_code = ISP16_BASE_360;
-		break;
-	case 0x320:
-		base_code = ISP16_BASE_320;
-		break;
-	default:
-		printk
-		    ("ISP16: base address 0x%03X not supported by cdrom interface.\n",
-		     base);
-		return -1;
-	}
-	switch (irq) {
-	case 0:
-		irq_code = ISP16_IRQ_X;
-		break;		/* disable irq */
-	case 5:
-		irq_code = ISP16_IRQ_5;
-		printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
-		       " due to possible conflicts with the sound card.\n");
-		break;
-	case 7:
-		irq_code = ISP16_IRQ_7;
-		printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
-		       " due to possible conflicts with the sound card.\n");
-		break;
-	case 3:
-		irq_code = ISP16_IRQ_3;
-		break;
-	case 9:
-		irq_code = ISP16_IRQ_9;
-		break;
-	case 10:
-		irq_code = ISP16_IRQ_10;
-		break;
-	case 11:
-		irq_code = ISP16_IRQ_11;
-		break;
-	default:
-		printk("ISP16: irq %d not supported by cdrom interface.\n",
-		       irq);
-		return -1;
-	}
-	switch (dma) {
-	case 0:
-		dma_code = ISP16_DMA_X;
-		break;		/* disable dma */
-	case 1:
-		printk("ISP16: dma 1 cannot be used by cdrom interface,"
-		       " due to conflict with the sound card.\n");
-		return -1;
-		break;
-	case 3:
-		dma_code = ISP16_DMA_3;
-		break;
-	case 5:
-		dma_code = ISP16_DMA_5;
-		break;
-	case 6:
-		dma_code = ISP16_DMA_6;
-		break;
-	case 7:
-		dma_code = ISP16_DMA_7;
-		break;
-	default:
-		printk("ISP16: dma %d not supported by cdrom interface.\n",
-		       dma);
-		return -1;
-	}
-
-	if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
-	    drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
-	    drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
-	    drive_type != ISP16_DRIVE_X) {
-		printk
-		    ("ISP16: drive type (code 0x%02X) not supported by cdrom"
-		     " interface.\n", drive_type);
-		return -1;
-	}
-
-	/* set type of interface */
-	i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;	/* clear some bits */
-	ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type);
-
-	/* enable cdrom on interface with 82C929 chip */
-	if (isp16_type > 1)
-		ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM);
-
-	/* set base address, irq and dma */
-	i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;	/* keep some bits */
-	ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
-
-	return 0;
-}
-
-static void __exit isp16_exit(void)
-{
-	release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-	printk(KERN_INFO "ISP16: module released.\n");
-}
-
-module_init(isp16_init);
-module_exit(isp16_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/cdrom/isp16.h b/drivers/cdrom/isp16.h
deleted file mode 100644
index 5bd22c8..0000000
--- a/drivers/cdrom/isp16.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -- isp16.h
- *
- *  Header for detection and initialisation of cdrom interface (only) on
- *  ISP16 (MAD16, Mozart) sound card.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/* These are the default values */
-#define ISP16_CDROM_TYPE "Sanyo"
-#define ISP16_CDROM_IO_BASE 0x340
-#define ISP16_CDROM_IRQ 0
-#define ISP16_CDROM_DMA 0
-
-/* Some (Media)Magic */
-/* define types of drive the interface on an ISP16 card may be looking at */
-#define ISP16_DRIVE_X 0x00
-#define ISP16_SONY  0x02
-#define ISP16_PANASONIC0 0x02
-#define ISP16_SANYO0 0x02
-#define ISP16_MITSUMI  0x04
-#define ISP16_PANASONIC1 0x06
-#define ISP16_SANYO1 0x06
-#define ISP16_DRIVE_NOT_USED 0x08  /* not used */
-#define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
-/* ...for port */
-#define ISP16_DRIVE_SET_PORT 0xF8D
-/* set io parameters */
-#define ISP16_BASE_340  0x00
-#define ISP16_BASE_330  0x40
-#define ISP16_BASE_360  0x80
-#define ISP16_BASE_320  0xC0
-#define ISP16_IRQ_X  0x00
-#define ISP16_IRQ_5  0x04  /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_7  0x08  /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_3  0x0C
-#define ISP16_IRQ_9  0x10
-#define ISP16_IRQ_10  0x14
-#define ISP16_IRQ_11  0x18
-#define ISP16_DMA_X  0x03
-#define ISP16_DMA_3  0x00
-#define ISP16_DMA_5  0x00
-#define ISP16_DMA_6  0x01
-#define ISP16_DMA_7  0x02
-#define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
-/* ...for port */
-#define ISP16_IO_SET_PORT  0xF8E
-/* enable the card */
-#define ISP16_C928__ENABLE_PORT  0xF90  /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__ENABLE_PORT  0xF91  /* ISP16 with OPTi 82C929 chip */
-#define ISP16_ENABLE_CDROM  0x80  /* seven bit */
-
-/* the magic stuff */
-#define ISP16_CTRL_PORT  0xF8F
-#define ISP16_C928__CTRL  0xE2  /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__CTRL  0xE3  /* ISP16 with OPTi 82C929 chip */
-
-#define ISP16_IO_BASE 0xF8D
-#define ISP16_IO_SIZE 5  /* ports used from 0xF8D up to 0xF91 */
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
deleted file mode 100644
index f574962..0000000
--- a/drivers/cdrom/mcdx.c
+++ /dev/null
@@ -1,1943 +0,0 @@
-/*
- * The Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.14(hs)
- *
- * ... anyway, I'm back again, thanks to Marcin, he adopted
- * large portions of my code (at least the parts containing
- * my main thoughts ...)
- *
- ****************** H E L P *********************************
- * If you ever plan to update your CD ROM drive and perhaps
- * want to sell or simply give away your Mitsumi FX-001[DS]
- * -- Please --
- * mail me (heiko@lotte.sax.de).  When my last drive goes
- * ballistic no more driver support will be available from me!
- *************************************************************
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- *  The Linux Community at all and ...
- *  Martin Harriss (he wrote the first Mitsumi Driver)
- *  Eberhard Moenkeberg (he gave me much support and the initial kick)
- *  Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
- *      improved the original driver)
- *  Jon Tombs, Bjorn Ekwall (module support)
- *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- *  Gerd Knorr (he lent me his PhotoCD)
- *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- *  Andreas Kies (testing the mysterious hang-ups)
- *  Heiko Eissfeldt (VERIFY_READ/WRITE)
- *  Marcin Dalecki (improved performance, shortened code)
- *  ... somebody forgotten?
- *
- *  9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	               Removed init_module & cleanup_module in favor of 
- *		       module_init & module_exit.
- *		       Torben Mathiasen <tmm@image.dk>
- */
-
-
-#ifdef RCS
-static const char *mcdx_c_version
-    = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $";
-#endif
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-
-#include <linux/major.h>
-#define MAJOR_NR MITSUMI_X_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#include "mcdx.h"
-
-#ifndef HZ
-#error HZ not defined
-#endif
-
-#define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args)
-
-#if !MCDX_QUIET
-#define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args)
-#else
-#define xinfo(fmt, args...) { ; }
-#endif
-
-#if MCDX_DEBUG
-#define xtrace(lvl, fmt, args...) \
-		{ if (lvl > 0) \
-			{ printk(KERN_DEBUG MCDX ":: " fmt, ## args); } }
-#define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args)
-#else
-#define xtrace(lvl, fmt, args...) { ; }
-#define xdebug(fmt, args...) { ; }
-#endif
-
-/* CONSTANTS *******************************************************/
-
-/* Following are the number of sectors we _request_ from the drive
-   every time an access outside the already requested range is done.
-   The _direct_ size is the number of sectors we're allowed to skip
-   directly (performing a read instead of requesting the new sector
-   needed */
-static const int REQUEST_SIZE = 800;	/* should be less then 255 * 4 */
-static const int DIRECT_SIZE = 400;	/* should be less then REQUEST_SIZE */
-
-enum drivemodes { TOC, DATA, RAW, COOKED };
-enum datamodes { MODE0, MODE1, MODE2 };
-enum resetmodes { SOFT, HARD };
-
-static const int SINGLE = 0x01;		/* single speed drive (FX001S, LU) */
-static const int DOUBLE = 0x02;		/* double speed drive (FX001D, ..? */
-static const int DOOR = 0x04;		/* door locking capability */
-static const int MULTI = 0x08;		/* multi session capability */
-
-static const unsigned char READ1X = 0xc0;
-static const unsigned char READ2X = 0xc1;
-
-
-/* DECLARATIONS ****************************************************/
-struct s_subqcode {
-	unsigned char control;
-	unsigned char tno;
-	unsigned char index;
-	struct cdrom_msf0 tt;
-	struct cdrom_msf0 dt;
-};
-
-struct s_diskinfo {
-	unsigned int n_first;
-	unsigned int n_last;
-	struct cdrom_msf0 msf_leadout;
-	struct cdrom_msf0 msf_first;
-};
-
-struct s_multi {
-	unsigned char multi;
-	struct cdrom_msf0 msf_last;
-};
-
-struct s_version {
-	unsigned char code;
-	unsigned char ver;
-};
-
-/* Per drive/controller stuff **************************************/
-
-struct s_drive_stuff {
-	/* waitqueues */
-	wait_queue_head_t busyq;
-	wait_queue_head_t lockq;
-	wait_queue_head_t sleepq;
-
-	/* flags */
-	volatile int introk;	/* status of last irq operation */
-	volatile int busy;	/* drive performs an operation */
-	volatile int lock;	/* exclusive usage */
-
-	/* cd infos */
-	struct s_diskinfo di;
-	struct s_multi multi;
-	struct s_subqcode *toc;	/* first entry of the toc array */
-	struct s_subqcode start;
-	struct s_subqcode stop;
-	int xa;			/* 1 if xa disk */
-	int audio;		/* 1 if audio disk */
-	int audiostatus;
-
-	/* `buffer' control */
-	volatile int valid;	/* pending, ..., values are valid */
-	volatile int pending;	/* next sector to be read */
-	volatile int low_border;	/* first sector not to be skipped direct */
-	volatile int high_border;	/* first sector `out of area' */
-#ifdef AK2
-	volatile int int_err;
-#endif				/* AK2 */
-
-	/* adds and odds */
-	unsigned wreg_data;	/* w data */
-	unsigned wreg_reset;	/* w hardware reset */
-	unsigned wreg_hcon;	/* w hardware conf */
-	unsigned wreg_chn;	/* w channel */
-	unsigned rreg_data;	/* r data */
-	unsigned rreg_status;	/* r status */
-
-	int irq;		/* irq used by this drive */
-	int present;		/* drive present and its capabilities */
-	unsigned char readcmd;	/* read cmd depends on single/double speed */
-	unsigned char playcmd;	/* play should always be single speed */
-	unsigned int xxx;	/* set if changed, reset while open */
-	unsigned int yyy;	/* set if changed, reset by media_changed */
-	int users;		/* keeps track of open/close */
-	int lastsector;		/* last block accessible */
-	int status;		/* last operation's error / status */
-	int readerrs;		/* # of blocks read w/o error */
-	struct cdrom_device_info info;
-	struct gendisk *disk;
-};
-
-
-/* Prototypes ******************************************************/
-
-/*	The following prototypes are already declared elsewhere.  They are
- 	repeated here to show what's going on.  And to sense, if they're
-	changed elsewhere. */
-
-static int mcdx_init(void);
-
-static int mcdx_block_open(struct inode *inode, struct file *file)
-{
-	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_open(&p->info, inode, file);
-}
-
-static int mcdx_block_release(struct inode *inode, struct file *file)
-{
-	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_release(&p->info, file);
-}
-
-static int mcdx_block_ioctl(struct inode *inode, struct file *file,
-				unsigned cmd, unsigned long arg)
-{
-	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_ioctl(file, &p->info, inode, cmd, arg);
-}
-
-static int mcdx_block_media_changed(struct gendisk *disk)
-{
-	struct s_drive_stuff *p = disk->private_data;
-	return cdrom_media_changed(&p->info);
-}
-
-static struct block_device_operations mcdx_bdops =
-{
-	.owner		= THIS_MODULE,
-	.open		= mcdx_block_open,
-	.release	= mcdx_block_release,
-	.ioctl		= mcdx_block_ioctl,
-	.media_changed	= mcdx_block_media_changed,
-};
-
-
-/*	Indirect exported functions. These functions are exported by their
-	addresses, such as mcdx_open and mcdx_close in the
-	structure mcdx_dops. */
-
-/* exported by file_ops */
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose);
-static void mcdx_close(struct cdrom_device_info *cdi);
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr);
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position);
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock);
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
-			    unsigned int cmd, void *arg);
-
-/* misc internal support functions */
-static void log2msf(unsigned int, struct cdrom_msf0 *);
-static unsigned int msf2log(const struct cdrom_msf0 *);
-static unsigned int uint2bcd(unsigned int);
-static unsigned int bcd2uint(unsigned char);
-static unsigned port(int *);
-static int irq(int *);
-static void mcdx_delay(struct s_drive_stuff *, long jifs);
-static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
-			 int nr_sectors);
-static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector,
-		     int nr_sectors);
-
-static int mcdx_config(struct s_drive_stuff *, int);
-static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *,
-			       int);
-static int mcdx_stop(struct s_drive_stuff *, int);
-static int mcdx_hold(struct s_drive_stuff *, int);
-static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int);
-static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int);
-static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int);
-static int mcdx_requestsubqcode(struct s_drive_stuff *,
-				struct s_subqcode *, int);
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *,
-				     struct s_multi *, int);
-static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *,
-			       int);
-static int mcdx_getstatus(struct s_drive_stuff *, int);
-static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *);
-static int mcdx_talk(struct s_drive_stuff *,
-		     const unsigned char *cmd, size_t,
-		     void *buffer, size_t size, unsigned int timeout, int);
-static int mcdx_readtoc(struct s_drive_stuff *);
-static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *);
-static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *);
-static int mcdx_setattentuator(struct s_drive_stuff *,
-			       struct cdrom_volctrl *, int);
-
-/* static variables ************************************************/
-
-static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
-static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
-static DEFINE_SPINLOCK(mcdx_lock);
-static struct request_queue *mcdx_queue;
-
-/* You can only set the first two pairs, from old MODULE_PARM code.  */
-static int mcdx_set(const char *val, struct kernel_param *kp)
-{
-	get_options((char *)val, 4, (int *)mcdx_drive_map);
-	return 0;
-}
-module_param_call(mcdx, mcdx_set, NULL, NULL, 0);
-
-static struct cdrom_device_ops mcdx_dops = {
-	.open		= mcdx_open,
-	.release	= mcdx_close,
-	.media_changed	= mcdx_media_changed,
-	.tray_move	= mcdx_tray_move,
-	.lock_door	= mcdx_lockdoor,
-	.audio_ioctl	= mcdx_audio_ioctl,
-	.capability	= CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED |
-			  CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
-};
-
-/* KERNEL INTERFACE FUNCTIONS **************************************/
-
-
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
-			    unsigned int cmd, void *arg)
-{
-	struct s_drive_stuff *stuffp = cdi->handle;
-
-	if (!stuffp->present)
-		return -ENXIO;
-
-	if (stuffp->xxx) {
-		if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-			stuffp->lastsector = -1;
-		} else {
-			stuffp->lastsector = (CD_FRAMESIZE / 512)
-			    * msf2log(&stuffp->di.msf_leadout) - 1;
-		}
-
-		if (stuffp->toc) {
-			kfree(stuffp->toc);
-			stuffp->toc = NULL;
-			if (-1 == mcdx_readtoc(stuffp))
-				return -1;
-		}
-
-		stuffp->xxx = 0;
-	}
-
-	switch (cmd) {
-	case CDROMSTART:{
-			xtrace(IOCTL, "ioctl() START\n");
-			/* Spin up the drive.  Don't think we can do this.
-			   * For now, ignore it.
-			 */
-			return 0;
-		}
-
-	case CDROMSTOP:{
-			xtrace(IOCTL, "ioctl() STOP\n");
-			stuffp->audiostatus = CDROM_AUDIO_INVALID;
-			if (-1 == mcdx_stop(stuffp, 1))
-				return -EIO;
-			return 0;
-		}
-
-	case CDROMPLAYTRKIND:{
-			struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-
-			xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
-			if ((ti->cdti_trk0 < stuffp->di.n_first)
-			    || (ti->cdti_trk0 > stuffp->di.n_last)
-			    || (ti->cdti_trk1 < stuffp->di.n_first))
-				return -EINVAL;
-			if (ti->cdti_trk1 > stuffp->di.n_last)
-				ti->cdti_trk1 = stuffp->di.n_last;
-			xtrace(PLAYTRK, "ioctl() track %d to %d\n",
-			       ti->cdti_trk0, ti->cdti_trk1);
-			return mcdx_playtrk(stuffp, ti);
-		}
-
-	case CDROMPLAYMSF:{
-			struct cdrom_msf *msf = (struct cdrom_msf *) arg;
-
-			xtrace(IOCTL, "ioctl() PLAYMSF\n");
-
-			if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
-			    && (-1 == mcdx_hold(stuffp, 1)))
-				return -EIO;
-
-			msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
-			msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
-			msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
-
-			msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
-			msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
-			msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
-
-			stuffp->stop.dt.minute = msf->cdmsf_min1;
-			stuffp->stop.dt.second = msf->cdmsf_sec1;
-			stuffp->stop.dt.frame = msf->cdmsf_frame1;
-
-			return mcdx_playmsf(stuffp, msf);
-		}
-
-	case CDROMRESUME:{
-			xtrace(IOCTL, "ioctl() RESUME\n");
-			return mcdx_playtrk(stuffp, NULL);
-		}
-
-	case CDROMREADTOCENTRY:{
-			struct cdrom_tocentry *entry =
-			    (struct cdrom_tocentry *) arg;
-			struct s_subqcode *tp = NULL;
-			xtrace(IOCTL, "ioctl() READTOCENTRY\n");
-
-			if (-1 == mcdx_readtoc(stuffp))
-				return -1;
-			if (entry->cdte_track == CDROM_LEADOUT)
-				tp = &stuffp->toc[stuffp->di.n_last -
-						  stuffp->di.n_first + 1];
-			else if (entry->cdte_track > stuffp->di.n_last
-				 || entry->cdte_track < stuffp->di.n_first)
-				return -EINVAL;
-			else
-				tp = &stuffp->toc[entry->cdte_track -
-						  stuffp->di.n_first];
-
-			if (NULL == tp)
-				return -EIO;
-			entry->cdte_adr = tp->control;
-			entry->cdte_ctrl = tp->control >> 4;
-			/* Always return stuff in MSF, and let the Uniform cdrom driver
-			   worry about what the user actually wants */
-			entry->cdte_addr.msf.minute =
-			    bcd2uint(tp->dt.minute);
-			entry->cdte_addr.msf.second =
-			    bcd2uint(tp->dt.second);
-			entry->cdte_addr.msf.frame =
-			    bcd2uint(tp->dt.frame);
-			return 0;
-		}
-
-	case CDROMSUBCHNL:{
-			struct cdrom_subchnl *sub =
-			    (struct cdrom_subchnl *) arg;
-			struct s_subqcode q;
-
-			xtrace(IOCTL, "ioctl() SUBCHNL\n");
-
-			if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
-				return -EIO;
-
-			xtrace(SUBCHNL, "audiostatus: %x\n",
-			       stuffp->audiostatus);
-			sub->cdsc_audiostatus = stuffp->audiostatus;
-			sub->cdsc_adr = q.control;
-			sub->cdsc_ctrl = q.control >> 4;
-			sub->cdsc_trk = bcd2uint(q.tno);
-			sub->cdsc_ind = bcd2uint(q.index);
-
-			xtrace(SUBCHNL, "trk %d, ind %d\n",
-			       sub->cdsc_trk, sub->cdsc_ind);
-			/* Always return stuff in MSF, and let the Uniform cdrom driver
-			   worry about what the user actually wants */
-			sub->cdsc_absaddr.msf.minute =
-			    bcd2uint(q.dt.minute);
-			sub->cdsc_absaddr.msf.second =
-			    bcd2uint(q.dt.second);
-			sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
-			sub->cdsc_reladdr.msf.minute =
-			    bcd2uint(q.tt.minute);
-			sub->cdsc_reladdr.msf.second =
-			    bcd2uint(q.tt.second);
-			sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
-			xtrace(SUBCHNL,
-			       "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
-			       sub->cdsc_absaddr.msf.minute,
-			       sub->cdsc_absaddr.msf.second,
-			       sub->cdsc_absaddr.msf.frame,
-			       sub->cdsc_reladdr.msf.minute,
-			       sub->cdsc_reladdr.msf.second,
-			       sub->cdsc_reladdr.msf.frame);
-
-			return 0;
-		}
-
-	case CDROMREADTOCHDR:{
-			struct cdrom_tochdr *toc =
-			    (struct cdrom_tochdr *) arg;
-
-			xtrace(IOCTL, "ioctl() READTOCHDR\n");
-			toc->cdth_trk0 = stuffp->di.n_first;
-			toc->cdth_trk1 = stuffp->di.n_last;
-			xtrace(TOCHDR,
-			       "ioctl() track0 = %d, track1 = %d\n",
-			       stuffp->di.n_first, stuffp->di.n_last);
-			return 0;
-		}
-
-	case CDROMPAUSE:{
-			xtrace(IOCTL, "ioctl() PAUSE\n");
-			if (stuffp->audiostatus != CDROM_AUDIO_PLAY)
-				return -EINVAL;
-			if (-1 == mcdx_stop(stuffp, 1))
-				return -EIO;
-			stuffp->audiostatus = CDROM_AUDIO_PAUSED;
-			if (-1 ==
-			    mcdx_requestsubqcode(stuffp, &stuffp->start,
-						 1))
-				return -EIO;
-			return 0;
-		}
-
-	case CDROMMULTISESSION:{
-			struct cdrom_multisession *ms =
-			    (struct cdrom_multisession *) arg;
-			xtrace(IOCTL, "ioctl() MULTISESSION\n");
-			/* Always return stuff in LBA, and let the Uniform cdrom driver
-			   worry about what the user actually wants */
-			ms->addr.lba = msf2log(&stuffp->multi.msf_last);
-			ms->xa_flag = !!stuffp->multi.multi;
-			xtrace(MS,
-			       "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
-			       ms->xa_flag, ms->addr.lba,
-			       stuffp->multi.msf_last.minute,
-			       stuffp->multi.msf_last.second,
-			       stuffp->multi.msf_last.frame);
-
-			return 0;
-		}
-
-	case CDROMEJECT:{
-			xtrace(IOCTL, "ioctl() EJECT\n");
-			if (stuffp->users > 1)
-				return -EBUSY;
-			return (mcdx_tray_move(cdi, 1));
-		}
-
-	case CDROMCLOSETRAY:{
-			xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
-			return (mcdx_tray_move(cdi, 0));
-		}
-
-	case CDROMVOLCTRL:{
-			struct cdrom_volctrl *volctrl =
-			    (struct cdrom_volctrl *) arg;
-			xtrace(IOCTL, "ioctl() VOLCTRL\n");
-
-#if 0				/* not tested! */
-			/* adjust for the weirdness of workman (md) */
-			/* can't test it (hs) */
-			volctrl.channel2 = volctrl.channel1;
-			volctrl.channel1 = volctrl.channel3 = 0x00;
-#endif
-			return mcdx_setattentuator(stuffp, volctrl, 2);
-		}
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static void do_mcdx_request(request_queue_t * q)
-{
-	struct s_drive_stuff *stuffp;
-	struct request *req;
-
-      again:
-
-	req = elv_next_request(q);
-	if (!req)
-		return;
-
-	stuffp = req->rq_disk->private_data;
-
-	if (!stuffp->present) {
-		xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
-		xtrace(REQUEST, "end_request(0): bad device\n");
-		end_request(req, 0);
-		return;
-	}
-
-	if (stuffp->audio) {
-		xwarn("do_request() attempt to read from audio cd\n");
-		xtrace(REQUEST, "end_request(0): read from audio\n");
-		end_request(req, 0);
-		return;
-	}
-
-	xtrace(REQUEST, "do_request() (%lu + %lu)\n",
-	       req->sector, req->nr_sectors);
-
-	if (req->cmd != READ) {
-		xwarn("do_request(): non-read command to cd!!\n");
-		xtrace(REQUEST, "end_request(0): write\n");
-		end_request(req, 0);
-		return;
-	}
-	else {
-		stuffp->status = 0;
-		while (req->nr_sectors) {
-			int i;
-
-			i = mcdx_transfer(stuffp,
-					  req->buffer,
-					  req->sector,
-					  req->nr_sectors);
-
-			if (i == -1) {
-				end_request(req, 0);
-				goto again;
-			}
-			req->sector += i;
-			req->nr_sectors -= i;
-			req->buffer += (i * 512);
-		}
-		end_request(req, 1);
-		goto again;
-
-		xtrace(REQUEST, "end_request(1)\n");
-		end_request(req, 1);
-	}
-
-	goto again;
-}
-
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
-{
-	struct s_drive_stuff *stuffp;
-	xtrace(OPENCLOSE, "open()\n");
-	stuffp = cdi->handle;
-	if (!stuffp->present)
-		return -ENXIO;
-
-	/* Make the modules looking used ... (thanx bjorn).
-	 * But we shouldn't forget to decrement the module counter
-	 * on error return */
-
-	/* this is only done to test if the drive talks with us */
-	if (-1 == mcdx_getstatus(stuffp, 1))
-		return -EIO;
-
-	if (stuffp->xxx) {
-
-		xtrace(OPENCLOSE, "open() media changed\n");
-		stuffp->audiostatus = CDROM_AUDIO_INVALID;
-		stuffp->readcmd = 0;
-		xtrace(OPENCLOSE, "open() Request multisession info\n");
-		if (-1 ==
-		    mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6))
-			xinfo("No multidiskinfo\n");
-	} else {
-		/* multisession ? */
-		if (!stuffp->multi.multi)
-			stuffp->multi.msf_last.second = 2;
-
-		xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
-		       stuffp->multi.multi,
-		       stuffp->multi.msf_last.minute,
-		       stuffp->multi.msf_last.second,
-		       stuffp->multi.msf_last.frame);
-
-		{;
-		}		/* got multisession information */
-		/* request the disks table of contents (aka diskinfo) */
-		if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-
-			stuffp->lastsector = -1;
-
-		} else {
-
-			stuffp->lastsector = (CD_FRAMESIZE / 512)
-			    * msf2log(&stuffp->di.msf_leadout) - 1;
-
-			xtrace(OPENCLOSE,
-			       "open() start %d (%02x:%02x.%02x) %d\n",
-			       stuffp->di.n_first,
-			       stuffp->di.msf_first.minute,
-			       stuffp->di.msf_first.second,
-			       stuffp->di.msf_first.frame,
-			       msf2log(&stuffp->di.msf_first));
-			xtrace(OPENCLOSE,
-			       "open() last %d (%02x:%02x.%02x) %d\n",
-			       stuffp->di.n_last,
-			       stuffp->di.msf_leadout.minute,
-			       stuffp->di.msf_leadout.second,
-			       stuffp->di.msf_leadout.frame,
-			       msf2log(&stuffp->di.msf_leadout));
-		}
-
-		if (stuffp->toc) {
-			xtrace(MALLOC, "open() free old toc @ %p\n",
-			       stuffp->toc);
-			kfree(stuffp->toc);
-
-			stuffp->toc = NULL;
-		}
-
-		xtrace(OPENCLOSE, "open() init irq generation\n");
-		if (-1 == mcdx_config(stuffp, 1))
-			return -EIO;
-#ifdef FALLBACK
-		/* Set the read speed */
-		xwarn("AAA %x AAA\n", stuffp->readcmd);
-		if (stuffp->readerrs)
-			stuffp->readcmd = READ1X;
-		else
-			stuffp->readcmd =
-			    stuffp->present | SINGLE ? READ1X : READ2X;
-		xwarn("XXX %x XXX\n", stuffp->readcmd);
-#else
-		stuffp->readcmd =
-		    stuffp->present | SINGLE ? READ1X : READ2X;
-#endif
-
-		/* try to get the first sector, iff any ... */
-		if (stuffp->lastsector >= 0) {
-			char buf[512];
-			int ans;
-			int tries;
-
-			stuffp->xa = 0;
-			stuffp->audio = 0;
-
-			for (tries = 6; tries; tries--) {
-
-				stuffp->introk = 1;
-
-				xtrace(OPENCLOSE, "open() try as %s\n",
-				       stuffp->xa ? "XA" : "normal");
-				/* set data mode */
-				if (-1 == (ans = mcdx_setdatamode(stuffp,
-								  stuffp->
-								  xa ?
-								  MODE2 :
-								  MODE1,
-								  1))) {
-					/* return -EIO; */
-					stuffp->xa = 0;
-					break;
-				}
-
-				if ((stuffp->audio = e_audio(ans)))
-					break;
-
-				while (0 ==
-				       (ans =
-					mcdx_transfer(stuffp, buf, 0, 1)));
-
-				if (ans == 1)
-					break;
-				stuffp->xa = !stuffp->xa;
-			}
-		}
-		/* xa disks will be read in raw mode, others not */
-		if (-1 == mcdx_setdrivemode(stuffp,
-					    stuffp->xa ? RAW : COOKED,
-					    1))
-			return -EIO;
-		if (stuffp->audio) {
-			xinfo("open() audio disk found\n");
-		} else if (stuffp->lastsector >= 0) {
-			xinfo("open() %s%s disk found\n",
-			      stuffp->xa ? "XA / " : "",
-			      stuffp->multi.
-			      multi ? "Multi Session" : "Single Session");
-		}
-	}
-	stuffp->xxx = 0;
-	stuffp->users++;
-	return 0;
-}
-
-static void mcdx_close(struct cdrom_device_info *cdi)
-{
-	struct s_drive_stuff *stuffp;
-
-	xtrace(OPENCLOSE, "close()\n");
-
-	stuffp = cdi->handle;
-
-	--stuffp->users;
-}
-
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-/*	Return: 1 if media changed since last call to this function
-			0 otherwise */
-{
-	struct s_drive_stuff *stuffp;
-
-	xinfo("mcdx_media_changed called for device %s\n", cdi->name);
-
-	stuffp = cdi->handle;
-	mcdx_getstatus(stuffp, 1);
-
-	if (stuffp->yyy == 0)
-		return 0;
-
-	stuffp->yyy = 0;
-	return 1;
-}
-
-#ifndef MODULE
-static int __init mcdx_setup(char *str)
-{
-	int pi[4];
-	(void) get_options(str, ARRAY_SIZE(pi), pi);
-
-	if (pi[0] > 0)
-		mcdx_drive_map[0][0] = pi[1];
-	if (pi[0] > 1)
-		mcdx_drive_map[0][1] = pi[2];
-	return 1;
-}
-
-__setup("mcdx=", mcdx_setup);
-
-#endif
-
-/* DIRTY PART ******************************************************/
-
-static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
-/* This routine is used for sleeping.
- * A jifs value <0 means NO sleeping,
- *              =0 means minimal sleeping (let the kernel
- *                 run for other processes)
- *              >0 means at least sleep for that amount.
- *	May be we could use a simple count loop w/ jumps to itself, but
- *	I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
-{
-	if (jifs < 0)
-		return;
-
-	xtrace(SLEEP, "*** delay: sleepq\n");
-	interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
-	xtrace(SLEEP, "delay awoken\n");
-	if (signal_pending(current)) {
-		xtrace(SLEEP, "got signal\n");
-	}
-}
-
-static irqreturn_t mcdx_intr(int irq, void *dev_id)
-{
-	struct s_drive_stuff *stuffp = dev_id;
-	unsigned char b;
-
-#ifdef AK2
-	if (!stuffp->busy && stuffp->pending)
-		stuffp->int_err = 1;
-
-#endif				/* AK2 */
-	/* get the interrupt status */
-	b = inb(stuffp->rreg_status);
-	stuffp->introk = ~b & MCDX_RBIT_DTEN;
-
-	/* NOTE: We only should get interrupts if the data we
-	 * requested are ready to transfer.
-	 * But the drive seems to generate ``asynchronous'' interrupts
-	 * on several error conditions too.  (Despite the err int enable
-	 * setting during initialisation) */
-
-	/* if not ok, read the next byte as the drives status */
-	if (!stuffp->introk) {
-		xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
-		if (~b & MCDX_RBIT_STEN) {
-			xinfo("intr() irq %d    status 0x%02x\n",
-			      irq, inb(stuffp->rreg_data));
-		} else {
-			xinfo("intr() irq %d ambiguous hw status\n", irq);
-		}
-	} else {
-		xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);
-	}
-
-	stuffp->busy = 0;
-	wake_up_interruptible(&stuffp->busyq);
-	return IRQ_HANDLED;
-}
-
-
-static int mcdx_talk(struct s_drive_stuff *stuffp,
-	  const unsigned char *cmd, size_t cmdlen,
-	  void *buffer, size_t size, unsigned int timeout, int tries)
-/* Send a command to the drive, wait for the result.
- * returns -1 on timeout, drive status otherwise
- * If buffer is not zero, the result (length size) is stored there.
- * If buffer is zero the size should be the number of bytes to read
- * from the drive.  These bytes are discarded.
- */
-{
-	int st;
-	char c;
-	int discard;
-
-	/* Somebody wants the data read? */
-	if ((discard = (buffer == NULL)))
-		buffer = &c;
-
-	while (stuffp->lock) {
-		xtrace(SLEEP, "*** talk: lockq\n");
-		interruptible_sleep_on(&stuffp->lockq);
-		xtrace(SLEEP, "talk: awoken\n");
-	}
-
-	stuffp->lock = 1;
-
-	/* An operation other then reading data destroys the
-	   * data already requested and remembered in stuffp->request, ... */
-	stuffp->valid = 0;
-
-#if MCDX_DEBUG & TALK
-	{
-		unsigned char i;
-		xtrace(TALK,
-		       "talk() %d / %d tries, res.size %d, command 0x%02x",
-		       tries, timeout, size, (unsigned char) cmd[0]);
-		for (i = 1; i < cmdlen; i++)
-			xtrace(TALK, " 0x%02x", cmd[i]);
-		xtrace(TALK, "\n");
-	}
-#endif
-
-	/*  give up if all tries are done (bad) or if the status
-	 *  st != -1 (good) */
-	for (st = -1; st == -1 && tries; tries--) {
-
-		char *bp = (char *) buffer;
-		size_t sz = size;
-
-		outsb(stuffp->wreg_data, cmd, cmdlen);
-		xtrace(TALK, "talk() command sent\n");
-
-		/* get the status byte */
-		if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
-			xinfo("talk() %02x timed out (status), %d tr%s left\n",
-			     cmd[0], tries - 1, tries == 2 ? "y" : "ies");
-			continue;
-		}
-		st = *bp;
-		sz--;
-		if (!discard)
-			bp++;
-
-		xtrace(TALK, "talk() got status 0x%02x\n", st);
-
-		/* command error? */
-		if (e_cmderr(st)) {
-			xwarn("command error cmd = %02x %s \n",
-			      cmd[0], cmdlen > 1 ? "..." : "");
-			st = -1;
-			continue;
-		}
-
-		/* audio status? */
-		if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
-			stuffp->audiostatus =
-			    e_audiobusy(st) ? CDROM_AUDIO_PLAY :
-			    CDROM_AUDIO_NO_STATUS;
-		else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
-			 && e_audiobusy(st) == 0)
-			stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
-
-		/* media change? */
-		if (e_changed(st)) {
-			xinfo("talk() media changed\n");
-			stuffp->xxx = stuffp->yyy = 1;
-		}
-
-		/* now actually get the data */
-		while (sz--) {
-			if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
-				xinfo("talk() %02x timed out (data), %d tr%s left\n",
-				     cmd[0], tries - 1,
-				     tries == 2 ? "y" : "ies");
-				st = -1;
-				break;
-			}
-			if (!discard)
-				bp++;
-			xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));
-		}
-	}
-
-#if !MCDX_QUIET
-	if (!tries && st == -1)
-		xinfo("talk() giving up\n");
-#endif
-
-	stuffp->lock = 0;
-	wake_up_interruptible(&stuffp->lockq);
-
-	xtrace(TALK, "talk() done with 0x%02x\n", st);
-	return st;
-}
-
-/* MODULE STUFF ***********************************************************/
-
-static int __init __mcdx_init(void)
-{
-	int i;
-	int drives = 0;
-
-	mcdx_init();
-	for (i = 0; i < MCDX_NDRIVES; i++) {
-		if (mcdx_stuffp[i]) {
-			xtrace(INIT, "init_module() drive %d stuff @ %p\n",
-			       i, mcdx_stuffp[i]);
-			drives++;
-		}
-	}
-
-	if (!drives)
-		return -EIO;
-
-	return 0;
-}
-
-static void __exit mcdx_exit(void)
-{
-	int i;
-
-	xinfo("cleanup_module called\n");
-
-	for (i = 0; i < MCDX_NDRIVES; i++) {
-		struct s_drive_stuff *stuffp = mcdx_stuffp[i];
-		if (!stuffp)
-			continue;
-		del_gendisk(stuffp->disk);
-		if (unregister_cdrom(&stuffp->info)) {
-			printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
-			continue;
-		}
-		put_disk(stuffp->disk);
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		free_irq(stuffp->irq, NULL);
-		if (stuffp->toc) {
-			xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
-			       stuffp->toc);
-			kfree(stuffp->toc);
-		}
-		xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",
-		       stuffp);
-		mcdx_stuffp[i] = NULL;
-		kfree(stuffp);
-	}
-
-	if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
-		xwarn("cleanup() unregister_blkdev() failed\n");
-	}
-	blk_cleanup_queue(mcdx_queue);
-#if !MCDX_QUIET
-	else
-	xinfo("cleanup() succeeded\n");
-#endif
-}
-
-#ifdef MODULE
-module_init(__mcdx_init);
-#endif
-module_exit(mcdx_exit);
-
-
-/* Support functions ************************************************/
-
-static int __init mcdx_init_drive(int drive)
-{
-	struct s_version version;
-	struct gendisk *disk;
-	struct s_drive_stuff *stuffp;
-	int size = sizeof(*stuffp);
-	char msg[80];
-
-	xtrace(INIT, "init() try drive %d\n", drive);
-
-	xtrace(INIT, "kmalloc space for stuffpt's\n");
-	xtrace(MALLOC, "init() malloc %d bytes\n", size);
-	if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
-		xwarn("init() malloc failed\n");
-		return 1;
-	}
-
-	disk = alloc_disk(1);
-	if (!disk) {
-		xwarn("init() malloc failed\n");
-		kfree(stuffp);
-		return 1;
-	}
-
-	xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
-	       sizeof(*stuffp), stuffp);
-
-	/* set default values */
-	stuffp->present = 0;	/* this should be 0 already */
-	stuffp->toc = NULL;	/* this should be NULL already */
-
-	/* setup our irq and i/o addresses */
-	stuffp->irq = irq(mcdx_drive_map[drive]);
-	stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
-	stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
-	stuffp->wreg_hcon = stuffp->wreg_reset + 1;
-	stuffp->wreg_chn = stuffp->wreg_hcon + 1;
-
-	init_waitqueue_head(&stuffp->busyq);
-	init_waitqueue_head(&stuffp->lockq);
-	init_waitqueue_head(&stuffp->sleepq);
-
-	/* check if i/o addresses are available */
-	if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
-		xwarn("0x%03x,%d: Init failed. "
-		      "I/O ports (0x%03x..0x%03x) already in use.\n",
-		      stuffp->wreg_data, stuffp->irq,
-		      stuffp->wreg_data,
-		      stuffp->wreg_data + MCDX_IO_SIZE - 1);
-		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
-		kfree(stuffp);
-		put_disk(disk);
-		xtrace(INIT, "init() continue at next drive\n");
-		return 0;	/* next drive */
-	}
-
-	xtrace(INIT, "init() i/o port is available at 0x%03x\n"
-	       stuffp->wreg_data);
-	xtrace(INIT, "init() hardware reset\n");
-	mcdx_reset(stuffp, HARD, 1);
-
-	xtrace(INIT, "init() get version\n");
-	if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
-		/* failed, next drive */
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq);
-		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
-		kfree(stuffp);
-		put_disk(disk);
-		xtrace(INIT, "init() continue at next drive\n");
-		return 0;
-	}
-
-	switch (version.code) {
-	case 'D':
-		stuffp->readcmd = READ2X;
-		stuffp->present = DOUBLE | DOOR | MULTI;
-		break;
-	case 'F':
-		stuffp->readcmd = READ1X;
-		stuffp->present = SINGLE | DOOR | MULTI;
-		break;
-	case 'M':
-		stuffp->readcmd = READ1X;
-		stuffp->present = SINGLE;
-		break;
-	default:
-		stuffp->present = 0;
-		break;
-	}
-
-	stuffp->playcmd = READ1X;
-
-	if (!stuffp->present) {
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq);
-		kfree(stuffp);
-		put_disk(disk);
-		return 0;	/* next drive */
-	}
-
-	xtrace(INIT, "init() register blkdev\n");
-	if (register_blkdev(MAJOR_NR, "mcdx")) {
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		kfree(stuffp);
-		put_disk(disk);
-		return 1;
-	}
-
-	mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
-	if (!mcdx_queue) {
-		unregister_blkdev(MAJOR_NR, "mcdx");
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		kfree(stuffp);
-		put_disk(disk);
-		return 1;
-	}
-
-	xtrace(INIT, "init() subscribe irq and i/o\n");
-	if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) {
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
-		stuffp->irq = 0;
-		blk_cleanup_queue(mcdx_queue);
-		kfree(stuffp);
-		put_disk(disk);
-		return 0;
-	}
-
-	xtrace(INIT, "init() get garbage\n");
-	{
-		int i;
-		mcdx_delay(stuffp, HZ / 2);
-		for (i = 100; i; i--)
-			(void) inb(stuffp->rreg_status);
-	}
-
-
-#ifdef WE_KNOW_WHY
-	/* irq 11 -> channel register */
-	outb(0x50, stuffp->wreg_chn);
-#endif
-
-	xtrace(INIT, "init() set non dma but irq mode\n");
-	mcdx_config(stuffp, 1);
-
-	stuffp->info.ops = &mcdx_dops;
-	stuffp->info.speed = 2;
-	stuffp->info.capacity = 1;
-	stuffp->info.handle = stuffp;
-	sprintf(stuffp->info.name, "mcdx%d", drive);
-	disk->major = MAJOR_NR;
-	disk->first_minor = drive;
-	strcpy(disk->disk_name, stuffp->info.name);
-	disk->fops = &mcdx_bdops;
-	disk->flags = GENHD_FL_CD;
-	stuffp->disk = disk;
-
-	sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
-		" (Firmware version %c %x)\n",
-		stuffp->wreg_data, stuffp->irq, version.code, version.ver);
-	mcdx_stuffp[drive] = stuffp;
-	xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
-	if (register_cdrom(&stuffp->info) != 0) {
-		printk("Cannot register Mitsumi CD-ROM!\n");
-		free_irq(stuffp->irq, NULL);
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		kfree(stuffp);
-		put_disk(disk);
-		if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
-			xwarn("cleanup() unregister_blkdev() failed\n");
-		blk_cleanup_queue(mcdx_queue);
-		return 2;
-	}
-	disk->private_data = stuffp;
-	disk->queue = mcdx_queue;
-	add_disk(disk);
-	printk(msg);
-	return 0;
-}
-
-static int __init mcdx_init(void)
-{
-	int drive;
-	xwarn("Version 2.14(hs) \n");
-
-	xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
-
-	/* zero the pointer array */
-	for (drive = 0; drive < MCDX_NDRIVES; drive++)
-		mcdx_stuffp[drive] = NULL;
-
-	/* do the initialisation */
-	for (drive = 0; drive < MCDX_NDRIVES; drive++) {
-		switch (mcdx_init_drive(drive)) {
-		case 2:
-			return -EIO;
-		case 1:
-			break;
-		}
-	}
-	return 0;
-}
-
-static int mcdx_transfer(struct s_drive_stuff *stuffp,
-	      char *p, int sector, int nr_sectors)
-/*	This seems to do the actually transfer.  But it does more.  It
-	keeps track of errors occurred and will (if possible) fall back
-	to single speed on error.
-	Return:	-1 on timeout or other error
-			else status byte (as in stuff->st) */
-{
-	int ans;
-
-	ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
-	return ans;
-#ifdef FALLBACK
-	if (-1 == ans)
-		stuffp->readerrs++;
-	else
-		return ans;
-
-	if (stuffp->readerrs && stuffp->readcmd == READ1X) {
-		xwarn("XXX Already reading 1x -- no chance\n");
-		return -1;
-	}
-
-	xwarn("XXX Fallback to 1x\n");
-
-	stuffp->readcmd = READ1X;
-	return mcdx_transfer(stuffp, p, sector, nr_sectors);
-#endif
-
-}
-
-
-static int mcdx_xfer(struct s_drive_stuff *stuffp,
-		     char *p, int sector, int nr_sectors)
-/*	This does actually the transfer from the drive.
-	Return:	-1 on timeout or other error
-			else status byte (as in stuff->st) */
-{
-	int border;
-	int done = 0;
-	long timeout;
-
-	if (stuffp->audio) {
-		xwarn("Attempt to read from audio CD.\n");
-		return -1;
-	}
-
-	if (!stuffp->readcmd) {
-		xinfo("Can't transfer from missing disk.\n");
-		return -1;
-	}
-
-	while (stuffp->lock) {
-		interruptible_sleep_on(&stuffp->lockq);
-	}
-
-	if (stuffp->valid && (sector >= stuffp->pending)
-	    && (sector < stuffp->low_border)) {
-
-		/* All (or at least a part of the sectors requested) seems
-		   * to be already requested, so we don't need to bother the
-		   * drive with new requests ...
-		   * Wait for the drive become idle, but first
-		   * check for possible occurred errors --- the drive
-		   * seems to report them asynchronously */
-
-
-		border = stuffp->high_border < (border =
-						sector + nr_sectors)
-		    ? stuffp->high_border : border;
-
-		stuffp->lock = current->pid;
-
-		do {
-
-			while (stuffp->busy) {
-
-				timeout =
-				    interruptible_sleep_on_timeout
-				    (&stuffp->busyq, 5 * HZ);
-
-				if (!stuffp->introk) {
-					xtrace(XFER,
-					       "error via interrupt\n");
-				} else if (!timeout) {
-					xtrace(XFER, "timeout\n");
-				} else if (signal_pending(current)) {
-					xtrace(XFER, "signal\n");
-				} else
-					continue;
-
-				stuffp->lock = 0;
-				stuffp->busy = 0;
-				stuffp->valid = 0;
-
-				wake_up_interruptible(&stuffp->lockq);
-				xtrace(XFER, "transfer() done (-1)\n");
-				return -1;
-			}
-
-			/* check if we need to set the busy flag (as we
-			 * expect an interrupt */
-			stuffp->busy = (3 == (stuffp->pending & 3));
-
-			/* Test if it's the first sector of a block,
-			 * there we have to skip some bytes as we read raw data */
-			if (stuffp->xa && (0 == (stuffp->pending & 3))) {
-				const int HEAD =
-				    CD_FRAMESIZE_RAW - CD_XA_TAIL -
-				    CD_FRAMESIZE;
-				insb(stuffp->rreg_data, p, HEAD);
-			}
-
-			/* now actually read the data */
-			insb(stuffp->rreg_data, p, 512);
-
-			/* test if it's the last sector of a block,
-			 * if so, we have to handle XA special */
-			if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
-				char dummy[CD_XA_TAIL];
-				insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL);
-			}
-
-			if (stuffp->pending == sector) {
-				p += 512;
-				done++;
-				sector++;
-			}
-		} while (++(stuffp->pending) < border);
-
-		stuffp->lock = 0;
-		wake_up_interruptible(&stuffp->lockq);
-
-	} else {
-
-		/* The requested sector(s) is/are out of the
-		 * already requested range, so we have to bother the drive
-		 * with a new request. */
-
-		static unsigned char cmd[] = {
-			0,
-			0, 0, 0,
-			0, 0, 0
-		};
-
-		cmd[0] = stuffp->readcmd;
-
-		/* The numbers held in ->pending, ..., should be valid */
-		stuffp->valid = 1;
-		stuffp->pending = sector & ~3;
-
-		/* do some sanity checks */
-		if (stuffp->pending > stuffp->lastsector) {
-			xwarn
-			    ("transfer() sector %d from nirvana requested.\n",
-			     stuffp->pending);
-			stuffp->status = MCDX_ST_EOM;
-			stuffp->valid = 0;
-			xtrace(XFER, "transfer() done (-1)\n");
-			return -1;
-		}
-
-		if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
-		    > stuffp->lastsector + 1) {
-			xtrace(XFER, "cut low_border\n");
-			stuffp->low_border = stuffp->lastsector + 1;
-		}
-		if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
-		    > stuffp->lastsector + 1) {
-			xtrace(XFER, "cut high_border\n");
-			stuffp->high_border = stuffp->lastsector + 1;
-		}
-
-		{		/* Convert the sector to be requested to MSF format */
-			struct cdrom_msf0 pending;
-			log2msf(stuffp->pending / 4, &pending);
-			cmd[1] = pending.minute;
-			cmd[2] = pending.second;
-			cmd[3] = pending.frame;
-		}
-
-		cmd[6] =
-		    (unsigned
-		     char) ((stuffp->high_border - stuffp->pending) / 4);
-		xtrace(XFER, "[%2d]\n", cmd[6]);
-
-		stuffp->busy = 1;
-		/* Now really issue the request command */
-		outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
-	}
-#ifdef AK2
-	if (stuffp->int_err) {
-		stuffp->valid = 0;
-		stuffp->int_err = 0;
-		return -1;
-	}
-#endif				/* AK2 */
-
-	stuffp->low_border = (stuffp->low_border +=
-			      done) <
-	    stuffp->high_border ? stuffp->low_border : stuffp->high_border;
-
-	return done;
-}
-
-
-/*	Access to elements of the mcdx_drive_map members */
-
-static unsigned port(int *ip)
-{
-	return ip[0];
-}
-static int irq(int *ip)
-{
-	return ip[1];
-}
-
-/*	Misc number converters */
-
-static unsigned int bcd2uint(unsigned char c)
-{
-	return (c >> 4) * 10 + (c & 0x0f);
-}
-
-static unsigned int uint2bcd(unsigned int ival)
-{
-	return ((ival / 10) << 4) | (ival % 10);
-}
-
-static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
-{
-	l += CD_MSF_OFFSET;
-	pmsf->minute = uint2bcd(l / 4500), l %= 4500;
-	pmsf->second = uint2bcd(l / 75);
-	pmsf->frame = uint2bcd(l % 75);
-}
-
-static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
-{
-	return bcd2uint(pmsf->frame)
-	    + bcd2uint(pmsf->second) * 75
-	    + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
-}
-
-int mcdx_readtoc(struct s_drive_stuff *stuffp)
-/*  Read the toc entries from the CD,
- *  Return: -1 on failure, else 0 */
-{
-
-	if (stuffp->toc) {
-		xtrace(READTOC, "ioctl() toc already read\n");
-		return 0;
-	}
-
-	xtrace(READTOC, "ioctl() readtoc for %d tracks\n",
-	       stuffp->di.n_last - stuffp->di.n_first + 1);
-
-	if (-1 == mcdx_hold(stuffp, 1))
-		return -1;
-
-	xtrace(READTOC, "ioctl() tocmode\n");
-	if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
-		return -EIO;
-
-	/* all seems to be ok so far ... malloc */
-	{
-		int size;
-		size =
-		    sizeof(struct s_subqcode) * (stuffp->di.n_last -
-						 stuffp->di.n_first + 2);
-
-		xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);
-		stuffp->toc = kmalloc(size, GFP_KERNEL);
-		if (!stuffp->toc) {
-			xwarn("Cannot malloc %d bytes for toc\n", size);
-			mcdx_setdrivemode(stuffp, DATA, 1);
-			return -EIO;
-		}
-	}
-
-	/* now read actually the index */
-	{
-		int trk;
-		int retries;
-
-		for (trk = 0;
-		     trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
-		     trk++)
-			stuffp->toc[trk].index = 0;
-
-		for (retries = 300; retries; retries--) {	/* why 300? */
-			struct s_subqcode q;
-			unsigned int idx;
-
-			if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
-				mcdx_setdrivemode(stuffp, DATA, 1);
-				return -EIO;
-			}
-
-			idx = bcd2uint(q.index);
-
-			if ((idx > 0)
-			    && (idx <= stuffp->di.n_last)
-			    && (q.tno == 0)
-			    && (stuffp->toc[idx - stuffp->di.n_first].
-				index == 0)) {
-				stuffp->toc[idx - stuffp->di.n_first] = q;
-				xtrace(READTOC,
-				       "ioctl() toc idx %d (trk %d)\n",
-				       idx, trk);
-				trk--;
-			}
-			if (trk == 0)
-				break;
-		}
-		memset(&stuffp->
-		       toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
-		       sizeof(stuffp->toc[0]));
-		stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
-			    1].dt = stuffp->di.msf_leadout;
-	}
-
-	/* unset toc mode */
-	xtrace(READTOC, "ioctl() undo toc mode\n");
-	if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
-		return -EIO;
-
-#if MCDX_DEBUG && READTOC
-	{
-		int trk;
-		for (trk = 0;
-		     trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
-		     trk++)
-			xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
-			       "  %02x:%02x.%02x  %02x:%02x.%02x\n",
-			       trk + stuffp->di.n_first,
-			       stuffp->toc[trk].control,
-			       stuffp->toc[trk].tno,
-			       stuffp->toc[trk].index,
-			       stuffp->toc[trk].tt.minute,
-			       stuffp->toc[trk].tt.second,
-			       stuffp->toc[trk].tt.frame,
-			       stuffp->toc[trk].dt.minute,
-			       stuffp->toc[trk].dt.second,
-			       stuffp->toc[trk].dt.frame);
-	}
-#endif
-
-	return 0;
-}
-
-static int
-mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
-{
-	unsigned char cmd[7] = {
-		0, 0, 0, 0, 0, 0, 0
-	};
-
-	if (!stuffp->readcmd) {
-		xinfo("Can't play from missing disk.\n");
-		return -1;
-	}
-
-	cmd[0] = stuffp->playcmd;
-
-	cmd[1] = msf->cdmsf_min0;
-	cmd[2] = msf->cdmsf_sec0;
-	cmd[3] = msf->cdmsf_frame0;
-	cmd[4] = msf->cdmsf_min1;
-	cmd[5] = msf->cdmsf_sec1;
-	cmd[6] = msf->cdmsf_frame1;
-
-	xtrace(PLAYMSF, "ioctl(): play %x "
-	       "%02x:%02x:%02x -- %02x:%02x:%02x\n",
-	       cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
-
-	outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
-	if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
-		xwarn("playmsf() timeout\n");
-		return -1;
-	}
-
-	stuffp->audiostatus = CDROM_AUDIO_PLAY;
-	return 0;
-}
-
-static int
-mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
-{
-	struct s_subqcode *p;
-	struct cdrom_msf msf;
-
-	if (-1 == mcdx_readtoc(stuffp))
-		return -1;
-
-	if (ti)
-		p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
-	else
-		p = &stuffp->start;
-
-	msf.cdmsf_min0 = p->dt.minute;
-	msf.cdmsf_sec0 = p->dt.second;
-	msf.cdmsf_frame0 = p->dt.frame;
-
-	if (ti) {
-		p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
-		stuffp->stop = *p;
-	} else
-		p = &stuffp->stop;
-
-	msf.cdmsf_min1 = p->dt.minute;
-	msf.cdmsf_sec1 = p->dt.second;
-	msf.cdmsf_frame1 = p->dt.frame;
-
-	return mcdx_playmsf(stuffp, &msf);
-}
-
-
-/* Drive functions ************************************************/
-
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
-{
-	struct s_drive_stuff *stuffp = cdi->handle;
-
-	if (!stuffp->present)
-		return -ENXIO;
-	if (!(stuffp->present & DOOR))
-		return -ENOSYS;
-
-	if (position)		/* 1: eject */
-		return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
-	else			/* 0: close */
-		return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
-	return 1;
-}
-
-static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
-{
-	return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
-{
-	return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
-		     struct s_subqcode *sub, int tries)
-{
-	char buf[11];
-	int ans;
-
-	if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf),
-				   2 * HZ, tries)))
-		return -1;
-	sub->control = buf[1];
-	sub->tno = buf[2];
-	sub->index = buf[3];
-	sub->tt.minute = buf[4];
-	sub->tt.second = buf[5];
-	sub->tt.frame = buf[6];
-	sub->dt.minute = buf[8];
-	sub->dt.second = buf[9];
-	sub->dt.frame = buf[10];
-
-	return ans;
-}
-
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
-			  struct s_multi *multi, int tries)
-{
-	char buf[5];
-	int ans;
-
-	if (stuffp->present & MULTI) {
-		ans =
-		    mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ,
-			      tries);
-		multi->multi = buf[1];
-		multi->msf_last.minute = buf[2];
-		multi->msf_last.second = buf[3];
-		multi->msf_last.frame = buf[4];
-		return ans;
-	} else {
-		multi->multi = 0;
-		return 0;
-	}
-}
-
-static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
-		    int tries)
-{
-	char buf[9];
-	int ans;
-	ans =
-	    mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);
-	if (ans == -1) {
-		info->n_first = 0;
-		info->n_last = 0;
-	} else {
-		info->n_first = bcd2uint(buf[1]);
-		info->n_last = bcd2uint(buf[2]);
-		info->msf_leadout.minute = buf[3];
-		info->msf_leadout.second = buf[4];
-		info->msf_leadout.frame = buf[5];
-		info->msf_first.minute = buf[6];
-		info->msf_first.second = buf[7];
-		info->msf_first.frame = buf[8];
-	}
-	return ans;
-}
-
-static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
-		  int tries)
-{
-	char cmd[2];
-	int ans;
-
-	xtrace(HW, "setdrivemode() %d\n", mode);
-
-	if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
-		return -1;
-
-	switch (mode) {
-	case TOC:
-		cmd[1] |= 0x04;
-		break;
-	case DATA:
-		cmd[1] &= ~0x04;
-		break;
-	case RAW:
-		cmd[1] |= 0x40;
-		break;
-	case COOKED:
-		cmd[1] &= ~0x40;
-		break;
-	default:
-		break;
-	}
-	cmd[0] = 0x50;
-	return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
-		 int tries)
-{
-	unsigned char cmd[2] = { 0xa0 };
-	xtrace(HW, "setdatamode() %d\n", mode);
-	switch (mode) {
-	case MODE0:
-		cmd[1] = 0x00;
-		break;
-	case MODE1:
-		cmd[1] = 0x01;
-		break;
-	case MODE2:
-		cmd[1] = 0x02;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
-{
-	char cmd[4];
-
-	xtrace(HW, "config()\n");
-
-	cmd[0] = 0x90;
-
-	cmd[1] = 0x10;		/* irq enable */
-	cmd[2] = 0x05;		/* pre, err irq enable */
-
-	if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
-		return -1;
-
-	cmd[1] = 0x02;		/* dma select */
-	cmd[2] = 0x00;		/* no dma */
-
-	return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
-}
-
-static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
-		    int tries)
-{
-	char buf[3];
-	int ans;
-
-	if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
-				   1, buf, sizeof(buf), 2 * HZ, tries)))
-		return ans;
-
-	ver->code = buf[1];
-	ver->ver = buf[2];
-
-	return ans;
-}
-
-static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
-{
-	if (mode == HARD) {
-		outb(0, stuffp->wreg_chn);	/* no dma, no irq -> hardware */
-		outb(0, stuffp->wreg_reset);	/* hw reset */
-		return 0;
-	} else
-		return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
-{
-	struct s_drive_stuff *stuffp = cdi->handle;
-	char cmd[2] = { 0xfe };
-
-	if (!(stuffp->present & DOOR))
-		return -ENOSYS;
-	if (stuffp->present & DOOR) {
-		cmd[1] = lock ? 0x01 : 0x00;
-		return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
-	} else
-		return 0;
-}
-
-static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
-{
-	return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int
-mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
-{
-	unsigned long timeout = to + jiffies;
-	char c;
-
-	if (!buf)
-		buf = &c;
-
-	while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) {
-		if (time_after(jiffies, timeout))
-			return -1;
-		mcdx_delay(stuffp, delay);
-	}
-
-	*buf = (unsigned char) inb(stuffp->rreg_data) & 0xff;
-
-	return 0;
-}
-
-static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
-		    struct cdrom_volctrl *vol, int tries)
-{
-	char cmd[5];
-	cmd[0] = 0xae;
-	cmd[1] = vol->channel0;
-	cmd[2] = 0;
-	cmd[3] = vol->channel1;
-	cmd[4] = 0;
-
-	return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR);
diff --git a/drivers/cdrom/mcdx.h b/drivers/cdrom/mcdx.h
deleted file mode 100644
index 83c364a..0000000
--- a/drivers/cdrom/mcdx.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Definitions for the Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: @VERSION@
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- *  The Linux Community at all and ...
- *  Martin Harris (he wrote the first Mitsumi Driver)
- *  Eberhard Moenkeberg (he gave me much support and the initial kick)
- *  Bernd Huebner, Ruediger Helsch (Unifix-Software Gmbh, they
- *      improved the original driver)
- *  Jon Tombs, Bjorn Ekwall (module support)
- *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- *  Gerd Knorr (he lent me his PhotoCD)
- *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- *  Andreas Kies (testing the mysterious hang up's)
- *  ... somebody forgotten?
- *  Marcin Dalecki
- *  
- */
-
-/*
- *	The following lines are for user configuration
- *	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *	{0|1} -- 1 if you want the driver detect your drive, may crash and
- *	needs a long time to seek.  The higher the address the longer the
- *	seek.
- *
- *  WARNING: AUTOPROBE doesn't work.
- */
-#define MCDX_AUTOPROBE 0
-
-/*
- *	Drive specific settings according to the jumpers on the controller
- *	board(s).
- *	o	MCDX_NDRIVES  :  number of used entries of the following table
- *	o	MCDX_DRIVEMAP :  table of {i/o base, irq} per controller
- *
- *	NOTE: I didn't get a drive at irq 9(2) working.  Not even alone.
- */
-#if MCDX_AUTOPROBE == 0
-	#define MCDX_NDRIVES 1
-	#define MCDX_DRIVEMAP {		\
-			{0x300, 11},	\
-			{0x304, 05},  	\
-			{0x000, 00},  	\
-			{0x000, 00},  	\
-			{0x000, 00},  	\
-	  	}
-#else
-	#error Autoprobing is not implemented yet.
-#endif
-
-#ifndef MCDX_QUIET
-#define MCDX_QUIET   1
-#endif
-
-#ifndef MCDX_DEBUG
-#define MCDX_DEBUG   0
-#endif
-
-/* *** make the following line uncommented, if you're sure,
- * *** all configuration is done */
-/* #define I_WAS_HERE */
-
-/*	The name of the device */
-#define MCDX "mcdx"	
-
-/* Flags for DEBUGGING */
-#define INIT 		0
-#define MALLOC 		0
-#define IOCTL 		0
-#define PLAYTRK     0
-#define SUBCHNL     0
-#define TOCHDR      0
-#define MS          0
-#define PLAYMSF     0
-#define READTOC     0
-#define OPENCLOSE 	0
-#define HW		    0
-#define TALK		0
-#define IRQ 		0
-#define XFER 		0
-#define REQUEST	 	0
-#define SLEEP		0
-
-/*	The following addresses are taken from the Mitsumi Reference 
- *  and describe the possible i/o range for the controller.
- */
-#define MCDX_IO_BEGIN	((char*) 0x300)	/* first base of i/o addr */
-#define MCDX_IO_END		((char*) 0x3fc)	/* last base of i/o addr */
-
-/*	Per controller 4 bytes i/o are needed. */
-#define MCDX_IO_SIZE		4
-
-/*
- *	Bits
- */
-
-/* The status byte, returned from every command, set if
- * the description is true */
-#define MCDX_RBIT_OPEN       0x80	/* door is open */
-#define MCDX_RBIT_DISKSET    0x40	/* disk set (recognised) */
-#define MCDX_RBIT_CHANGED    0x20	/* disk was changed */
-#define MCDX_RBIT_CHECK      0x10	/* disk rotates, servo is on */
-#define MCDX_RBIT_AUDIOTR    0x08   /* current track is audio */
-#define MCDX_RBIT_RDERR      0x04	/* read error, refer SENSE KEY */
-#define MCDX_RBIT_AUDIOBS    0x02	/* currently playing audio */
-#define MCDX_RBIT_CMDERR     0x01	/* command, param or format error */
-
-/* The I/O Register holding the h/w status of the drive,
- * can be read at i/o base + 1 */
-#define MCDX_RBIT_DOOR       0x10	/* door is open */
-#define MCDX_RBIT_STEN       0x04	/* if 0, i/o base contains drive status */
-#define MCDX_RBIT_DTEN       0x02	/* if 0, i/o base contains data */
-
-/*
- *	The commands.
- */
-
-#define OPCODE	1		/* offset of opcode */
-#define MCDX_CMD_REQUEST_TOC		1, 0x10
-#define MCDX_CMD_REQUEST_STATUS		1, 0x40 
-#define MCDX_CMD_RESET				1, 0x60
-#define MCDX_CMD_REQUEST_DRIVE_MODE	1, 0xc2
-#define MCDX_CMD_SET_INTERLEAVE		2, 0xc8, 0
-#define MCDX_CMD_DATAMODE_SET		2, 0xa0, 0
-	#define MCDX_DATAMODE1		0x01
-	#define MCDX_DATAMODE2		0x02
-#define MCDX_CMD_LOCK_DOOR		2, 0xfe, 0
-
-#define READ_AHEAD			4	/* 8 Sectors (4K) */
-
-/*	Useful macros */
-#define e_door(x)		((x) & MCDX_RBIT_OPEN)
-#define e_check(x)		(~(x) & MCDX_RBIT_CHECK)
-#define e_notset(x)		(~(x) & MCDX_RBIT_DISKSET)
-#define e_changed(x)	((x) & MCDX_RBIT_CHANGED)
-#define e_audio(x)		((x) & MCDX_RBIT_AUDIOTR)
-#define e_audiobusy(x)	((x) & MCDX_RBIT_AUDIOBS)
-#define e_cmderr(x)		((x) & MCDX_RBIT_CMDERR)
-#define e_readerr(x)	((x) & MCDX_RBIT_RDERR)
-
-/**	no drive specific */
-#define MCDX_CDBLK	2048	/* 2048 cooked data each blk */
-
-#define MCDX_DATA_TIMEOUT	(HZ/10)	/* 0.1 second */
-
-/*
- * Access to the msf array
- */
-#define MSF_MIN		0			/* minute */
-#define MSF_SEC		1			/* second */
-#define MSF_FRM		2			/* frame  */
-
-/*
- * Errors
- */
-#define MCDX_E		1			/* unspec error */
-#define MCDX_ST_EOM 0x0100		/* end of media */
-#define MCDX_ST_DRV 0x00ff		/* mask to query the drive status */
-
-#ifndef I_WAS_HERE
-#ifndef MODULE
-#warning You have not edited mcdx.h
-#warning Perhaps irq and i/o settings are wrong.
-#endif
-#endif
-
-/* ex:set ts=4 sw=4: */
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
deleted file mode 100644
index 3541690..0000000
--- a/drivers/cdrom/optcd.c
+++ /dev/null
@@ -1,2105 +0,0 @@
-/*	linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver
-	$Id: optcd.c,v 1.11 1997/01/26 07:13:00 davem Exp $
-
-	Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
-	Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
-	by Eberhard Moenkeberg (emoenke@gwdg.de). 
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2, or (at your option)
-	any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/*	Revision history
-
-
-	14-5-95		v0.0	Plays sound tracks. No reading of data CDs yet.
-				Detection of disk change doesn't work.
-	21-5-95		v0.1	First ALPHA version. CD can be mounted. The
-				device major nr is borrowed from the Aztech
-				driver. Speed is around 240 kb/s, as measured
-				with "time dd if=/dev/cdrom of=/dev/null \
-				bs=2048 count=4096".
-	24-6-95		v0.2	Reworked the #defines for the command codes
-				and the like, as well as the structure of
-				the hardware communication protocol, to
-				reflect the "official" documentation, kindly
-				supplied by C.K. Tan, Optics Storage Pte. Ltd.
-				Also tidied up the state machine somewhat.
-	28-6-95		v0.3	Removed the ISP-16 interface code, as this
-				should go into its own driver. The driver now
-				has its own major nr.
-				Disk change detection now seems to work, too.
-				This version became part of the standard
-				kernel as of version 1.3.7
-	24-9-95		v0.4	Re-inserted ISP-16 interface code which I
-				copied from sjcd.c, with a few changes.
-				Updated README.optcd. Submitted for
-				inclusion in 1.3.21
-	29-9-95		v0.4a	Fixed bug that prevented compilation as module
-	25-10-95	v0.5	Started multisession code. Implementation
-				copied from Werner Zimmermann, who copied it
-				from Heiko Schlittermann's mcdx.
-	17-1-96		v0.6	Multisession works; some cleanup too.
-	18-4-96		v0.7	Increased some timing constants;
-				thanks to Luke McFarlane. Also tidied up some
-				printk behaviour. ISP16 initialization
-				is now handled by a separate driver.
-				
-	09-11-99 	  	Make kernel-parameter implementation work with 2.3.x 
-	                 	Removed init_module & cleanup_module in favor of 
-			 	module_init & module_exit.
-			 	Torben Mathiasen <tmm@image.dk>
-*/
-
-/* Includes */
-
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <linux/blkdev.h>
-
-#include <linux/cdrom.h>
-#include "optcd.h"
-
-#include <asm/uaccess.h>
-
-#define MAJOR_NR OPTICS_CDROM_MAJOR
-#define QUEUE (opt_queue)
-#define CURRENT elv_next_request(opt_queue)
-
-
-/* Debug support */
-
-
-/* Don't forget to add new debug flags here. */
-#if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
-    DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
-#define DEBUG(x) debug x
-static void debug(int debug_this, const char* fmt, ...)
-{
-	char s[1024];
-	va_list args;
-
-	if (!debug_this)
-		return;
-
-	va_start(args, fmt);
-	vsnprintf(s, sizeof(s), fmt, args);
-	printk(KERN_DEBUG "optcd: %s\n", s);
-	va_end(args);
-}
-#else
-#define DEBUG(x)
-#endif
-
-
-/* Drive hardware/firmware characteristics
-   Identifiers in accordance with Optics Storage documentation */
-
-
-#define optcd_port optcd			/* Needed for the modutils. */
-static short optcd_port = OPTCD_PORTBASE;	/* I/O base of drive. */
-module_param(optcd_port, short, 0);
-/* Drive registers, read */
-#define DATA_PORT	optcd_port	/* Read data/status */
-#define STATUS_PORT	optcd_port+1	/* Indicate data/status availability */
-
-/* Drive registers, write */
-#define COMIN_PORT	optcd_port	/* For passing command/parameter */
-#define RESET_PORT	optcd_port+1	/* Write anything and wait 0.5 sec */
-#define HCON_PORT	optcd_port+2	/* Host Xfer Configuration */
-
-
-/* Command completion/status read from DATA register */
-#define ST_DRVERR		0x80
-#define ST_DOOR_OPEN		0x40
-#define ST_MIXEDMODE_DISK	0x20
-#define ST_MODE_BITS		0x1c
-#define ST_M_STOP		0x00
-#define ST_M_READ		0x04
-#define ST_M_AUDIO		0x04
-#define ST_M_PAUSE		0x08
-#define ST_M_INITIAL		0x0c
-#define ST_M_ERROR		0x10
-#define ST_M_OTHERS		0x14
-#define	ST_MODE2TRACK		0x02
-#define	ST_DSK_CHG		0x01
-#define ST_L_LOCK		0x01
-#define ST_CMD_OK		0x00
-#define ST_OP_OK		0x01
-#define ST_PA_OK		0x02
-#define ST_OP_ERROR		0x05
-#define ST_PA_ERROR		0x06
-
-
-/* Error codes (appear as command completion code from DATA register) */
-/* Player related errors */
-#define ERR_ILLCMD	0x11	/* Illegal command to player module */
-#define ERR_ILLPARM	0x12	/* Illegal parameter to player module */
-#define ERR_SLEDGE	0x13
-#define ERR_FOCUS	0x14
-#define ERR_MOTOR	0x15
-#define ERR_RADIAL	0x16
-#define ERR_PLL		0x17	/* PLL lock error */
-#define ERR_SUB_TIM	0x18	/* Subcode timeout error */
-#define ERR_SUB_NF	0x19	/* Subcode not found error */
-#define ERR_TRAY	0x1a
-#define ERR_TOC		0x1b	/* Table of Contents read error */
-#define ERR_JUMP	0x1c
-/* Data errors */
-#define ERR_MODE	0x21
-#define ERR_FORM	0x22
-#define ERR_HEADADDR	0x23	/* Header Address not found */
-#define ERR_CRC		0x24
-#define ERR_ECC		0x25	/* Uncorrectable ECC error */
-#define ERR_CRC_UNC	0x26	/* CRC error and uncorrectable error */
-#define ERR_ILLBSYNC	0x27	/* Illegal block sync error */
-#define ERR_VDST	0x28	/* VDST not found */
-/* Timeout errors */
-#define ERR_READ_TIM	0x31	/* Read timeout error */
-#define ERR_DEC_STP	0x32	/* Decoder stopped */
-#define ERR_DEC_TIM	0x33	/* Decoder interrupt timeout error */
-/* Function abort codes */
-#define ERR_KEY		0x41	/* Key -Detected abort */
-#define ERR_READ_FINISH	0x42	/* Read Finish */
-/* Second Byte diagnostic codes */
-#define ERR_NOBSYNC	0x01	/* No block sync */
-#define ERR_SHORTB	0x02	/* Short block */
-#define ERR_LONGB	0x03	/* Long block */
-#define ERR_SHORTDSP	0x04	/* Short DSP word */
-#define ERR_LONGDSP	0x05	/* Long DSP word */
-
-
-/* Status availability flags read from STATUS register */
-#define FL_EJECT	0x20
-#define FL_WAIT		0x10	/* active low */
-#define FL_EOP		0x08	/* active low */
-#define FL_STEN		0x04	/* Status available when low */
-#define FL_DTEN		0x02	/* Data available when low */
-#define FL_DRQ		0x01	/* active low */
-#define FL_RESET	0xde	/* These bits are high after a reset */
-#define FL_STDT		(FL_STEN|FL_DTEN)
-
-
-/* Transfer mode, written to HCON register */
-#define HCON_DTS	0x08
-#define HCON_SDRQB	0x04
-#define HCON_LOHI	0x02
-#define HCON_DMA16	0x01
-
-
-/* Drive command set, written to COMIN register */
-/* Quick response commands */
-#define COMDRVST	0x20	/* Drive Status Read */
-#define COMERRST	0x21	/* Error Status Read */
-#define COMIOCTLISTAT	0x22	/* Status Read; reset disk changed bit */
-#define COMINITSINGLE	0x28	/* Initialize Single Speed */
-#define COMINITDOUBLE	0x29	/* Initialize Double Speed */
-#define COMUNLOCK	0x30	/* Unlock */
-#define COMLOCK		0x31	/* Lock */
-#define COMLOCKST	0x32	/* Lock/Unlock Status */
-#define COMVERSION	0x40	/* Get Firmware Revision */
-#define COMVOIDREADMODE	0x50	/* Void Data Read Mode */
-/* Read commands */
-#define COMFETCH	0x60	/* Prefetch Data */
-#define COMREAD		0x61	/* Read */
-#define COMREADRAW	0x62	/* Read Raw Data */
-#define COMREADALL	0x63	/* Read All 2646 Bytes */
-/* Player control commands */
-#define COMLEADIN	0x70	/* Seek To Lead-in */
-#define COMSEEK		0x71	/* Seek */
-#define COMPAUSEON	0x80	/* Pause On */
-#define COMPAUSEOFF	0x81	/* Pause Off */
-#define COMSTOP		0x82	/* Stop */
-#define COMOPEN		0x90	/* Open Tray Door */
-#define COMCLOSE	0x91	/* Close Tray Door */
-#define COMPLAY		0xa0	/* Audio Play */
-#define COMPLAY_TNO	0xa2	/* Audio Play By Track Number */
-#define COMSUBQ		0xb0	/* Read Sub-q Code */
-#define COMLOCATION	0xb1	/* Read Head Position */
-/* Audio control commands */
-#define COMCHCTRL	0xc0	/* Audio Channel Control */
-/* Miscellaneous (test) commands */
-#define COMDRVTEST	0xd0	/* Write Test Bytes */
-#define COMTEST		0xd1	/* Diagnostic Test */
-
-/* Low level drive interface. Only here we do actual I/O
-   Waiting for status / data available */
-
-
-/* Busy wait until FLAG goes low. Return 0 on timeout. */
-static inline int flag_low(int flag, unsigned long timeout)
-{
-	int flag_high;
-	unsigned long count = 0;
-
-	while ((flag_high = (inb(STATUS_PORT) & flag)))
-		if (++count >= timeout)
-			break;
-
-	DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
-		flag, count, flag_high ? " timeout" : ""));
-	return !flag_high;
-}
-
-
-/* Timed waiting for status or data */
-static int sleep_timeout;	/* max # of ticks to sleep */
-static DECLARE_WAIT_QUEUE_HEAD(waitq);
-static void sleep_timer(unsigned long data);
-static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
-static DEFINE_SPINLOCK(optcd_lock);
-static struct request_queue *opt_queue;
-
-/* Timer routine: wake up when desired flag goes low,
-   or when timeout expires. */
-static void sleep_timer(unsigned long data)
-{
-	int flags = inb(STATUS_PORT) & FL_STDT;
-
-	if (flags == FL_STDT && --sleep_timeout > 0) {
-		mod_timer(&delay_timer, jiffies + HZ/100); /* multi-statement macro */
-	} else
-		wake_up(&waitq);
-}
-
-
-/* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */
-static int sleep_flag_low(int flag, unsigned long timeout)
-{
-	int flag_high;
-
-	DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
-
-	sleep_timeout = timeout;
-	flag_high = inb(STATUS_PORT) & flag;
-	if (flag_high && sleep_timeout > 0) {
-		mod_timer(&delay_timer, jiffies + HZ/100);
-		sleep_on(&waitq);
-		flag_high = inb(STATUS_PORT) & flag;
-	}
-
-	DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
-		flag, timeout, flag_high ? " timeout" : ""));
-	return !flag_high;
-}
-
-/* Low level drive interface. Only here we do actual I/O
-   Sending commands and parameters */
-
-
-/* Errors in the command protocol */
-#define ERR_IF_CMD_TIMEOUT	0x100
-#define ERR_IF_ERR_TIMEOUT	0x101
-#define ERR_IF_RESP_TIMEOUT	0x102
-#define ERR_IF_DATA_TIMEOUT	0x103
-#define ERR_IF_NOSTAT		0x104
-
-
-/* Send command code. Return <0 indicates error */
-static int send_cmd(int cmd)
-{
-	unsigned char ack;
-
-	DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
-
-	outb(HCON_DTS, HCON_PORT);	/* Enable Suspend Data Transfer */
-	outb(cmd, COMIN_PORT);		/* Send command code */
-	if (!flag_low(FL_STEN, BUSY_TIMEOUT))	/* Wait for status */
-		return -ERR_IF_CMD_TIMEOUT;
-	ack = inb(DATA_PORT);		/* read command acknowledge */
-	outb(HCON_SDRQB, HCON_PORT);	/* Disable Suspend Data Transfer */
-	return ack==ST_OP_OK ? 0 : -ack;
-}
-
-
-/* Send command parameters. Return <0 indicates error */
-static int send_params(struct cdrom_msf *params)
-{
-	unsigned char ack;
-
-	DEBUG((DEBUG_DRIVE_IF, "sending parameters"
-		" %02x:%02x:%02x"
-		" %02x:%02x:%02x",
-		params->cdmsf_min0,
-		params->cdmsf_sec0,
-		params->cdmsf_frame0,
-		params->cdmsf_min1,
-		params->cdmsf_sec1,
-		params->cdmsf_frame1));
-
-	outb(params->cdmsf_min0, COMIN_PORT);
-	outb(params->cdmsf_sec0, COMIN_PORT);
-	outb(params->cdmsf_frame0, COMIN_PORT);
-	outb(params->cdmsf_min1, COMIN_PORT);
-	outb(params->cdmsf_sec1, COMIN_PORT);
-	outb(params->cdmsf_frame1, COMIN_PORT);
-	if (!flag_low(FL_STEN, BUSY_TIMEOUT))	/* Wait for status */
-		return -ERR_IF_CMD_TIMEOUT;
-	ack = inb(DATA_PORT);		/* read command acknowledge */
-	return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Send parameters for SEEK command. Return <0 indicates error */
-static int send_seek_params(struct cdrom_msf *params)
-{
-	unsigned char ack;
-
-	DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
-		" %02x:%02x:%02x",
-		params->cdmsf_min0,
-		params->cdmsf_sec0,
-		params->cdmsf_frame0));
-
-	outb(params->cdmsf_min0, COMIN_PORT);
-	outb(params->cdmsf_sec0, COMIN_PORT);
-	outb(params->cdmsf_frame0, COMIN_PORT);
-	if (!flag_low(FL_STEN, BUSY_TIMEOUT))	/* Wait for status */
-		return -ERR_IF_CMD_TIMEOUT;
-	ack = inb(DATA_PORT);		/* read command acknowledge */
-	return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Wait for command execution status. Choice between busy waiting
-   and sleeping. Return value <0 indicates timeout. */
-static inline int get_exec_status(int busy_waiting)
-{
-	unsigned char exec_status;
-
-	if (busy_waiting
-	    ? !flag_low(FL_STEN, BUSY_TIMEOUT)
-	    : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
-		return -ERR_IF_CMD_TIMEOUT;
-
-	exec_status = inb(DATA_PORT);
-	DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
-	return exec_status;
-}
-
-
-/* Wait busy for extra byte of data that a command returns.
-   Return value <0 indicates timeout. */
-static inline int get_data(int short_timeout)
-{
-	unsigned char data;
-
-	if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
-		return -ERR_IF_DATA_TIMEOUT;
-
-	data = inb(DATA_PORT);
-	DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
-	return data;
-}
-
-
-/* Returns 0 if failed */
-static int reset_drive(void)
-{
-	unsigned long count = 0;
-	int flags;
-
-	DEBUG((DEBUG_DRIVE_IF, "reset drive"));
-
-	outb(0, RESET_PORT);
-	while (++count < RESET_WAIT)
-		inb(DATA_PORT);
-
-	count = 0;
-	while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
-		if (++count >= BUSY_TIMEOUT)
-			break;
-
-	DEBUG((DEBUG_DRIVE_IF, "reset %s",
-		flags == FL_RESET ? "succeeded" : "failed"));
-
-	if (flags != FL_RESET)
-		return 0;		/* Reset failed */
-	outb(HCON_SDRQB, HCON_PORT);	/* Disable Suspend Data Transfer */
-	return 1;			/* Reset succeeded */
-}
-
-
-/* Facilities for asynchronous operation */
-
-/* Read status/data availability flags FL_STEN and FL_DTEN */
-static inline int stdt_flags(void)
-{
-	return inb(STATUS_PORT) & FL_STDT;
-}
-
-
-/* Fetch status that has previously been waited for. <0 means not available */
-static inline int fetch_status(void)
-{
-	unsigned char status;
-
-	if (inb(STATUS_PORT) & FL_STEN)
-		return -ERR_IF_NOSTAT;
-
-	status = inb(DATA_PORT);
-	DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
-	return status;
-}
-
-
-/* Fetch data that has previously been waited for. */
-static inline void fetch_data(char *buf, int n)
-{
-	insb(DATA_PORT, buf, n);
-	DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
-}
-
-
-/* Flush status and data fifos */
-static inline void flush_data(void)
-{
-	while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
-		inb(DATA_PORT);
-	DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
-}
-
-/* Command protocol */
-
-
-/* Send a simple command and wait for response. Command codes < COMFETCH
-   are quick response commands */
-static inline int exec_cmd(int cmd)
-{
-	int ack = send_cmd(cmd);
-	if (ack < 0)
-		return ack;
-	return get_exec_status(cmd < COMFETCH);
-}
-
-
-/* Send a command with parameters. Don't wait for the response,
- * which consists of data blocks read from the CD. */
-static inline int exec_read_cmd(int cmd, struct cdrom_msf *params)
-{
-	int ack = send_cmd(cmd);
-	if (ack < 0)
-		return ack;
-	return send_params(params);
-}
-
-
-/* Send a seek command with parameters and wait for response */
-static inline int exec_seek_cmd(int cmd, struct cdrom_msf *params)
-{
-	int ack = send_cmd(cmd);
-	if (ack < 0)
-		return ack;
-	ack = send_seek_params(params);
-	if (ack < 0)
-		return ack;
-	return 0;
-}
-
-
-/* Send a command with parameters and wait for response */
-static inline int exec_long_cmd(int cmd, struct cdrom_msf *params)
-{
-	int ack = exec_read_cmd(cmd, params);
-	if (ack < 0)
-		return ack;
-	return get_exec_status(0);
-}
-
-/* Address conversion routines */
-
-
-/* Binary to BCD (2 digits) */
-static inline void single_bin2bcd(u_char *p)
-{
-	DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
-	*p = (*p % 10) | ((*p / 10) << 4);
-}
-
-
-/* Convert entire msf struct */
-static void bin2bcd(struct cdrom_msf *msf)
-{
-	single_bin2bcd(&msf->cdmsf_min0);
-	single_bin2bcd(&msf->cdmsf_sec0);
-	single_bin2bcd(&msf->cdmsf_frame0);
-	single_bin2bcd(&msf->cdmsf_min1);
-	single_bin2bcd(&msf->cdmsf_sec1);
-	single_bin2bcd(&msf->cdmsf_frame1);
-}
-
-
-/* Linear block address to minute, second, frame form */
-#define CD_FPM	(CD_SECS * CD_FRAMES)	/* frames per minute */
-
-static void lba2msf(int lba, struct cdrom_msf *msf)
-{
-	DEBUG((DEBUG_CONV, "lba2msf %d", lba));
-	lba += CD_MSF_OFFSET;
-	msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM;
-	msf->cdmsf_sec0 = lba / CD_FRAMES;
-	msf->cdmsf_frame0 = lba % CD_FRAMES;
-	msf->cdmsf_min1 = 0;
-	msf->cdmsf_sec1 = 0;
-	msf->cdmsf_frame1 = 0;
-	bin2bcd(msf);
-}
-
-
-/* Two BCD digits to binary */
-static inline u_char bcd2bin(u_char bcd)
-{
-	DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
-	return (bcd >> 4) * 10 + (bcd & 0x0f);
-}
-
-
-static void msf2lba(union cdrom_addr *addr)
-{
-	addr->lba = addr->msf.minute * CD_FPM
-	            + addr->msf.second * CD_FRAMES
-	            + addr->msf.frame - CD_MSF_OFFSET;
-}
-
-
-/* Minute, second, frame address BCD to binary or to linear address,
-   depending on MODE */
-static void msf_bcd2bin(union cdrom_addr *addr)
-{
-	addr->msf.minute = bcd2bin(addr->msf.minute);
-	addr->msf.second = bcd2bin(addr->msf.second);
-	addr->msf.frame = bcd2bin(addr->msf.frame);
-}
-
-/* High level drive commands */
-
-
-static int audio_status = CDROM_AUDIO_NO_STATUS;
-static char toc_uptodate = 0;
-static char disk_changed = 1;
-
-/* Get drive status, flagging completion of audio play and disk changes. */
-static int drive_status(void)
-{
-	int status;
-
-	status = exec_cmd(COMIOCTLISTAT);
-	DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
-	if (status < 0)
-		return status;
-	if (status == 0xff)	/* No status available */
-		return -ERR_IF_NOSTAT;
-
-	if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
-		(audio_status == CDROM_AUDIO_PLAY)) {
-		audio_status = CDROM_AUDIO_COMPLETED;
-	}
-
-	if (status & ST_DSK_CHG) {
-		toc_uptodate = 0;
-		disk_changed = 1;
-		audio_status = CDROM_AUDIO_NO_STATUS;
-	}
-
-	return status;
-}
-
-
-/* Read the current Q-channel info. Also used for reading the
-   table of contents. qp->cdsc_format must be set on entry to
-   indicate the desired address format */
-static int get_q_channel(struct cdrom_subchnl *qp)
-{
-	int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
-
-	status = drive_status();
-	if (status < 0)
-		return status;
-	qp->cdsc_audiostatus = audio_status;
-
-	status = exec_cmd(COMSUBQ);
-	if (status < 0)
-		return status;
-
-	d1 = get_data(0);
-	if (d1 < 0)
-		return d1;
-	qp->cdsc_adr = d1;
-	qp->cdsc_ctrl = d1 >> 4;
-
-	d2 = get_data(0);
-	if (d2 < 0)
-		return d2;
-	qp->cdsc_trk = bcd2bin(d2);
-
-	d3 = get_data(0);
-	if (d3 < 0)
-		return d3;
-	qp->cdsc_ind = bcd2bin(d3);
-
-	d4 = get_data(0);
-	if (d4 < 0)
-		return d4;
-	qp->cdsc_reladdr.msf.minute = d4;
-
-	d5 = get_data(0);
-	if (d5 < 0)
-		return d5;
-	qp->cdsc_reladdr.msf.second = d5;
-
-	d6 = get_data(0);
-	if (d6 < 0)
-		return d6;
-	qp->cdsc_reladdr.msf.frame = d6;
-
-	d7 = get_data(0);
-	if (d7 < 0)
-		return d7;
-	/* byte not used */
-
-	d8 = get_data(0);
-	if (d8 < 0)
-		return d8;
-	qp->cdsc_absaddr.msf.minute = d8;
-
-	d9 = get_data(0);
-	if (d9 < 0)
-		return d9;
-	qp->cdsc_absaddr.msf.second = d9;
-
-	d10 = get_data(0);
-	if (d10 < 0)
-		return d10;
-	qp->cdsc_absaddr.msf.frame = d10;
-
-	DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
-		d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
-
-	msf_bcd2bin(&qp->cdsc_absaddr);
-	msf_bcd2bin(&qp->cdsc_reladdr);
-	if (qp->cdsc_format == CDROM_LBA) {
-		msf2lba(&qp->cdsc_absaddr);
-		msf2lba(&qp->cdsc_reladdr);
-	}
-
-	return 0;
-}
-
-/* Table of contents handling */
-
-
-/* Errors in table of contents */
-#define ERR_TOC_MISSINGINFO	0x120
-#define ERR_TOC_MISSINGENTRY	0x121
-
-
-struct cdrom_disk_info {
-	unsigned char		first;
-	unsigned char		last;
-	struct cdrom_msf0	disk_length;
-	struct cdrom_msf0	first_track;
-	/* Multisession info: */
-	unsigned char		next;
-	struct cdrom_msf0	next_session;
-	struct cdrom_msf0	last_session;
-	unsigned char		multi;
-	unsigned char		xa;
-	unsigned char		audio;
-};
-static struct cdrom_disk_info disk_info;
-
-#define MAX_TRACKS		111
-static struct cdrom_subchnl toc[MAX_TRACKS];
-
-#define QINFO_FIRSTTRACK	100 /* bcd2bin(0xa0) */
-#define QINFO_LASTTRACK		101 /* bcd2bin(0xa1) */
-#define QINFO_DISKLENGTH	102 /* bcd2bin(0xa2) */
-#define QINFO_NEXTSESSION	110 /* bcd2bin(0xb0) */
-
-#define I_FIRSTTRACK	0x01
-#define I_LASTTRACK	0x02
-#define I_DISKLENGTH	0x04
-#define I_NEXTSESSION	0x08
-#define I_ALL	(I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
-
-
-#if DEBUG_TOC
-static void toc_debug_info(int i)
-{
-	printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d"
-		"  %2d:%02d.%02d %2d:%02d.%02d\n",
-		i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
-		toc[i].cdsc_trk, toc[i].cdsc_ind,
-		toc[i].cdsc_reladdr.msf.minute,
-		toc[i].cdsc_reladdr.msf.second,
-		toc[i].cdsc_reladdr.msf.frame,
-		toc[i].cdsc_absaddr.msf.minute,
-		toc[i].cdsc_absaddr.msf.second,
-		toc[i].cdsc_absaddr.msf.frame);
-}
-#endif
-
-
-static int read_toc(void)
-{
-	int status, limit, count;
-	unsigned char got_info = 0;
-	struct cdrom_subchnl q_info;
-#if DEBUG_TOC
-	int i;
-#endif
-
-	DEBUG((DEBUG_TOC, "starting read_toc"));
-
-	count = 0;
-	for (limit = 60; limit > 0; limit--) {
-		int index;
-
-		q_info.cdsc_format = CDROM_MSF;
-		status = get_q_channel(&q_info);
-		if (status < 0)
-			return status;
-
-		index = q_info.cdsc_ind;
-		if (index > 0 && index < MAX_TRACKS
-		    && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
-			toc[index] = q_info;
-			DEBUG((DEBUG_TOC, "got %d", index));
-			if (index < 100)
-				count++;
-
-			switch (q_info.cdsc_ind) {
-			case QINFO_FIRSTTRACK:
-				got_info |= I_FIRSTTRACK;
-				break;
-			case QINFO_LASTTRACK:
-				got_info |= I_LASTTRACK;
-				break;
-			case QINFO_DISKLENGTH:
-				got_info |= I_DISKLENGTH;
-				break;
-			case QINFO_NEXTSESSION:
-				got_info |= I_NEXTSESSION;
-				break;
-			}
-		}
-
-		if ((got_info & I_ALL) == I_ALL
-		    && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
-		       >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
-			break;
-	}
-
-	/* Construct disk_info from TOC */
-	if (disk_info.first == 0) {
-		disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
-		disk_info.first_track.minute =
-			toc[disk_info.first].cdsc_absaddr.msf.minute;
-		disk_info.first_track.second =
-			toc[disk_info.first].cdsc_absaddr.msf.second;
-		disk_info.first_track.frame =
-			toc[disk_info.first].cdsc_absaddr.msf.frame;
-	}
-	disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
-	disk_info.disk_length.minute =
-			toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
-	disk_info.disk_length.second =
-			toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
-	disk_info.disk_length.frame =
-			toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
-	disk_info.next_session.minute =
-			toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
-	disk_info.next_session.second =
-			toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
-	disk_info.next_session.frame =
-			toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
-	disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
-	disk_info.last_session.minute =
-			toc[disk_info.next].cdsc_absaddr.msf.minute;
-	disk_info.last_session.second =
-			toc[disk_info.next].cdsc_absaddr.msf.second;
-	disk_info.last_session.frame =
-			toc[disk_info.next].cdsc_absaddr.msf.frame;
-	toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
-			disk_info.disk_length.minute;
-	toc[disk_info.last + 1].cdsc_absaddr.msf.second =
-			disk_info.disk_length.second;
-	toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
-			disk_info.disk_length.frame;
-#if DEBUG_TOC
-	for (i = 1; i <= disk_info.last + 1; i++)
-		toc_debug_info(i);
-	toc_debug_info(QINFO_FIRSTTRACK);
-	toc_debug_info(QINFO_LASTTRACK);
-	toc_debug_info(QINFO_DISKLENGTH);
-	toc_debug_info(QINFO_NEXTSESSION);
-#endif
-
-	DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
-		got_info, count));
-	if ((got_info & I_ALL) != I_ALL
-	    || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
-	       < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
-		return -ERR_TOC_MISSINGINFO;
-	return 0;
-}
-
-
-#ifdef MULTISESSION
-static int get_multi_disk_info(void)
-{
-	int sessions, status;
-	struct cdrom_msf multi_index;
-
-
-	for (sessions = 2; sessions < 10 /* %%for now */; sessions++) {
-		int count;
-
-		for (count = 100; count < MAX_TRACKS; count++) 
-			toc[count].cdsc_ind = 0;
-
-		multi_index.cdmsf_min0 = disk_info.next_session.minute;
-		multi_index.cdmsf_sec0 = disk_info.next_session.second;
-		multi_index.cdmsf_frame0 = disk_info.next_session.frame;
-		if (multi_index.cdmsf_sec0 >= 20)
-			multi_index.cdmsf_sec0 -= 20;
-		else {
-			multi_index.cdmsf_sec0 += 40;
-			multi_index.cdmsf_min0--;
-		}
-		DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
-			multi_index.cdmsf_min0,
-			multi_index.cdmsf_sec0,
-			multi_index.cdmsf_frame0));
-		bin2bcd(&multi_index);
-		multi_index.cdmsf_min1 = 0;
-		multi_index.cdmsf_sec1 = 0;
-		multi_index.cdmsf_frame1 = 1;
-
-		status = exec_read_cmd(COMREAD, &multi_index);
-		if (status < 0) {
-			DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
-				-status));
-			break;
-		}
-		status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
-				0 : -ERR_TOC_MISSINGINFO;
-		flush_data();
-		if (status < 0) {
-			DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
-			break;
-		}
-
-		status = read_toc();
-		if (status < 0) {
-			DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
-			break;
-		}
-
-		disk_info.multi = 1;
-	}
-
-	exec_cmd(COMSTOP);
-
-	if (status < 0)
-		return -EIO;
-	return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int update_toc(void)
-{
-	int status, count;
-
-	if (toc_uptodate)
-		return 0;
-
-	DEBUG((DEBUG_TOC, "starting update_toc"));
-
-	disk_info.first = 0;
-	for (count = 0; count < MAX_TRACKS; count++) 
-		toc[count].cdsc_ind = 0;
-
-	status = exec_cmd(COMLEADIN);
-	if (status < 0)
-		return -EIO;
-
-	status = read_toc();
-	if (status < 0) {
-		DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
-		return -EIO;
-	}
-
-        /* Audio disk detection. Look at first track. */
-	disk_info.audio =
-		(toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
-
-	/* XA detection */
-	disk_info.xa = drive_status() & ST_MODE2TRACK;
-
-	/* Multisession detection: if we want this, define MULTISESSION */
-	disk_info.multi = 0;
-#ifdef MULTISESSION
- 	if (disk_info.xa)
-		get_multi_disk_info();	/* Here disk_info.multi is set */
-#endif /* MULTISESSION */
-	if (disk_info.multi)
-		printk(KERN_WARNING "optcd: Multisession support experimental, "
-			"see Documentation/cdrom/optcd\n");
-
-	DEBUG((DEBUG_TOC, "exiting update_toc"));
-
-	toc_uptodate = 1;
-	return 0;
-}
-
-/* Request handling */
-
-static int current_valid(void)
-{
-        return CURRENT &&
-		CURRENT->cmd == READ &&
-		CURRENT->sector != -1;
-}
-
-/* Buffers for block size conversion. */
-#define NOBUF		-1
-
-static char buf[CD_FRAMESIZE * N_BUFS];
-static volatile int buf_bn[N_BUFS], next_bn;
-static volatile int buf_in = 0, buf_out = NOBUF;
-
-static inline void opt_invalidate_buffers(void)
-{
-	int i;
-
-	DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
-
-	for (i = 0; i < N_BUFS; i++)
-		buf_bn[i] = NOBUF;
-	buf_out = NOBUF;
-}
-
-
-/* Take care of the different block sizes between cdrom and Linux.
-   When Linux gets variable block sizes this will probably go away. */
-static void transfer(void)
-{
-#if DEBUG_BUFFERS | DEBUG_REQUEST
-	printk(KERN_DEBUG "optcd: executing transfer\n");
-#endif
-
-	if (!current_valid())
-		return;
-	while (CURRENT -> nr_sectors) {
-		int bn = CURRENT -> sector / 4;
-		int i, offs, nr_sectors;
-		for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
-
-		DEBUG((DEBUG_REQUEST, "found %d", i));
-
-		if (i >= N_BUFS) {
-			buf_out = NOBUF;
-			break;
-		}
-
-		offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
-		nr_sectors = 4 - (CURRENT -> sector & 3);
-
-		if (buf_out != i) {
-			buf_out = i;
-			if (buf_bn[i] != bn) {
-				buf_out = NOBUF;
-				continue;
-			}
-		}
-
-		if (nr_sectors > CURRENT -> nr_sectors)
-			nr_sectors = CURRENT -> nr_sectors;
-		memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
-		CURRENT -> nr_sectors -= nr_sectors;
-		CURRENT -> sector += nr_sectors;
-		CURRENT -> buffer += nr_sectors * 512;
-	}
-}
-
-
-/* State machine for reading disk blocks */
-
-enum state_e {
-	S_IDLE,		/* 0 */
-	S_START,	/* 1 */
-	S_READ,		/* 2 */
-	S_DATA,		/* 3 */
-	S_STOP,		/* 4 */
-	S_STOPPING	/* 5 */
-};
-
-static volatile enum state_e state = S_IDLE;
-#if DEBUG_STATE
-static volatile enum state_e state_old = S_STOP;
-static volatile int flags_old = 0;
-static volatile long state_n = 0;
-#endif
-
-
-/* Used as mutex to keep do_optcd_request (and other processes calling
-   ioctl) out while some process is inside a VFS call.
-   Reverse is accomplished by checking if state = S_IDLE upon entry
-   of opt_ioctl and opt_media_change. */
-static int in_vfs = 0;
-
-
-static volatile int transfer_is_active = 0;
-static volatile int error = 0;	/* %% do something with this?? */
-static int tries;		/* ibid?? */
-static int timeout = 0;
-
-static void poll(unsigned long data);
-static struct timer_list req_timer = {.function = poll};
-
-
-static void poll(unsigned long data)
-{
-	static volatile int read_count = 1;
-	int flags;
-	int loop_again = 1;
-	int status = 0;
-	int skip = 0;
-
-	if (error) {
-		printk(KERN_ERR "optcd: I/O error 0x%02x\n", error);
-		opt_invalidate_buffers();
-		if (!tries--) {
-			printk(KERN_ERR "optcd: read block %d failed;"
-				" Giving up\n", next_bn);
-			if (transfer_is_active)
-				loop_again = 0;
-			if (current_valid())
-				end_request(CURRENT, 0);
-			tries = 5;
-		}
-		error = 0;
-		state = S_STOP;
-	}
-
-	while (loop_again)
-	{
-		loop_again = 0; /* each case must flip this back to 1 if we want
-		                 to come back up here */
-
-#if DEBUG_STATE
-		if (state == state_old)
-			state_n++;
-		else {
-			state_old = state;
-			if (++state_n > 1)
-				printk(KERN_DEBUG "optcd: %ld times "
-					"in previous state\n", state_n);
-			printk(KERN_DEBUG "optcd: state %d\n", state);
-			state_n = 0;
-		}
-#endif
-
-		switch (state) {
-		case S_IDLE:
-			return;
-		case S_START:
-			if (in_vfs)
-				break;
-			if (send_cmd(COMDRVST)) {
-				state = S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-			state = S_READ;
-			timeout = READ_TIMEOUT;
-			break;
-		case S_READ: {
-			struct cdrom_msf msf;
-			if (!skip) {
-				status = fetch_status();
-				if (status < 0)
-					break;
-				if (status & ST_DSK_CHG) {
-					toc_uptodate = 0;
-					opt_invalidate_buffers();
-				}
-			}
-			skip = 0;
-			if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
-				toc_uptodate = 0;
-				opt_invalidate_buffers();
-				printk(KERN_WARNING "optcd: %s\n",
-					(status & ST_DOOR_OPEN)
-					? "door open"
-					: "disk removed");
-				state = S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-			if (!current_valid()) {
-				state = S_STOP;
-				loop_again = 1;
-				break;
-			}
-			next_bn = CURRENT -> sector / 4;
-			lba2msf(next_bn, &msf);
-			read_count = N_BUFS;
-			msf.cdmsf_frame1 = read_count; /* Not BCD! */
-
-			DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
-				msf.cdmsf_min0,
-				msf.cdmsf_sec0,
-				msf.cdmsf_frame0,
-				msf.cdmsf_min1,
-				msf.cdmsf_sec1,
-				msf.cdmsf_frame1));
-			DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
-				" buf_out:%d buf_bn:%d",
-				next_bn,
-				buf_in,
-				buf_out,
-				buf_bn[buf_in]));
-
-			exec_read_cmd(COMREAD, &msf);
-			state = S_DATA;
-			timeout = READ_TIMEOUT;
-			break;
-		}
-		case S_DATA:
-			flags = stdt_flags() & (FL_STEN|FL_DTEN);
-
-#if DEBUG_STATE
-			if (flags != flags_old) {
-				flags_old = flags;
-				printk(KERN_DEBUG "optcd: flags:%x\n", flags);
-			}
-			if (flags == FL_STEN)
-				printk(KERN_DEBUG "timeout cnt: %d\n", timeout);
-#endif
-
-			switch (flags) {
-			case FL_DTEN:		/* only STEN low */
-				if (!tries--) {
-					printk(KERN_ERR
-						"optcd: read block %d failed; "
-						"Giving up\n", next_bn);
-					if (transfer_is_active) {
-						tries = 0;
-						break;
-					}
-					if (current_valid())
-						end_request(CURRENT, 0);
-					tries = 5;
-				}
-				state = S_START;
-				timeout = READ_TIMEOUT;
-				loop_again = 1;
-			case (FL_STEN|FL_DTEN):	 /* both high */
-				break;
-			default:	/* DTEN low */
-				tries = 5;
-				if (!current_valid() && buf_in == buf_out) {
-					state = S_STOP;
-					loop_again = 1;
-					break;
-				}
-				if (read_count<=0)
-					printk(KERN_WARNING
-						"optcd: warning - try to read"
-						" 0 frames\n");
-				while (read_count) {
-					buf_bn[buf_in] = NOBUF;
-					if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
-					/* should be no waiting here!?? */
-						printk(KERN_ERR
-						   "read_count:%d "
-						   "CURRENT->nr_sectors:%ld "
-						   "buf_in:%d\n",
-							read_count,
-							CURRENT->nr_sectors,
-							buf_in);
-						printk(KERN_ERR
-							"transfer active: %x\n",
-							transfer_is_active);
-						read_count = 0;
-						state = S_STOP;
-						loop_again = 1;
-						end_request(CURRENT, 0);
-						break;
-					}
-					fetch_data(buf+
-					    CD_FRAMESIZE*buf_in,
-					    CD_FRAMESIZE);
-					read_count--;
-
-					DEBUG((DEBUG_REQUEST,
-						"S_DATA; ---I've read data- "
-						"read_count: %d",
-						read_count));
-					DEBUG((DEBUG_REQUEST,
-						"next_bn:%d  buf_in:%d "
-						"buf_out:%d  buf_bn:%d",
-						next_bn,
-						buf_in,
-						buf_out,
-						buf_bn[buf_in]));
-
-					buf_bn[buf_in] = next_bn++;
-					if (buf_out == NOBUF)
-						buf_out = buf_in;
-					buf_in = buf_in + 1 ==
-						N_BUFS ? 0 : buf_in + 1;
-				}
-				if (!transfer_is_active) {
-					while (current_valid()) {
-						transfer();
-						if (CURRENT -> nr_sectors == 0)
-							end_request(CURRENT, 1);
-						else
-							break;
-					}
-				}
-
-				if (current_valid()
-				    && (CURRENT -> sector / 4 < next_bn ||
-				    CURRENT -> sector / 4 >
-				     next_bn + N_BUFS)) {
-					state = S_STOP;
-					loop_again = 1;
-					break;
-				}
-				timeout = READ_TIMEOUT;
-				if (read_count == 0) {
-					state = S_STOP;
-					loop_again = 1;
-					break;
-				}
-			}
-			break;
-		case S_STOP:
-			if (read_count != 0)
-				printk(KERN_ERR
-					"optcd: discard data=%x frames\n",
-					read_count);
-			flush_data();
-			if (send_cmd(COMDRVST)) {
-				state = S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-			state = S_STOPPING;
-			timeout = STOP_TIMEOUT;
-			break;
-		case S_STOPPING:
-			status = fetch_status();
-			if (status < 0 && timeout)
-					break;
-			if ((status >= 0) && (status & ST_DSK_CHG)) {
-				toc_uptodate = 0;
-				opt_invalidate_buffers();
-			}
-			if (current_valid()) {
-				if (status >= 0) {
-					state = S_READ;
-					loop_again = 1;
-					skip = 1;
-					break;
-				} else {
-					state = S_START;
-					timeout = 1;
-				}
-			} else {
-				state = S_IDLE;
-				return;
-			}
-			break;
-		default:
-			printk(KERN_ERR "optcd: invalid state %d\n", state);
-			return;
-		} /* case */
-	} /* while */
-
-	if (!timeout--) {
-		printk(KERN_ERR "optcd: timeout in state %d\n", state);
-		state = S_STOP;
-		if (exec_cmd(COMSTOP) < 0) {
-			state = S_IDLE;
-			while (current_valid())
-				end_request(CURRENT, 0);
-			return;
-		}
-	}
-
-	mod_timer(&req_timer, jiffies + HZ/100);
-}
-
-
-static void do_optcd_request(request_queue_t * q)
-{
-	DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
-	       CURRENT -> sector, CURRENT -> nr_sectors));
-
-	if (disk_info.audio) {
-		printk(KERN_WARNING "optcd: tried to mount an Audio CD\n");
-		end_request(CURRENT, 0);
-		return;
-	}
-
-	transfer_is_active = 1;
-	while (current_valid()) {
-		transfer();	/* First try to transfer block from buffers */
-		if (CURRENT -> nr_sectors == 0) {
-			end_request(CURRENT, 1);
-		} else {	/* Want to read a block not in buffer */
-			buf_out = NOBUF;
-			if (state == S_IDLE) {
-				/* %% Should this block the request queue?? */
-				if (update_toc() < 0) {
-					while (current_valid())
-						end_request(CURRENT, 0);
-					break;
-				}
-				/* Start state machine */
-				state = S_START;
-				timeout = READ_TIMEOUT;
-				tries = 5;
-				/* %% why not start right away?? */
-				mod_timer(&req_timer, jiffies + HZ/100);
-			}
-			break;
-		}
-	}
-	transfer_is_active = 0;
-
-	DEBUG((DEBUG_REQUEST, "next_bn:%d  buf_in:%d buf_out:%d  buf_bn:%d",
-	       next_bn, buf_in, buf_out, buf_bn[buf_in]));
-	DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
-}
-
-/* IOCTLs */
-
-
-static char auto_eject = 0;
-
-static int cdrompause(void)
-{
-	int status;
-
-	if (audio_status != CDROM_AUDIO_PLAY)
-		return -EINVAL;
-
-	status = exec_cmd(COMPAUSEON);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
-		return -EIO;
-	}
-	audio_status = CDROM_AUDIO_PAUSED;
-	return 0;
-}
-
-
-static int cdromresume(void)
-{
-	int status;
-
-	if (audio_status != CDROM_AUDIO_PAUSED)
-		return -EINVAL;
-
-	status = exec_cmd(COMPAUSEOFF);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
-		audio_status = CDROM_AUDIO_ERROR;
-		return -EIO;
-	}
-	audio_status = CDROM_AUDIO_PLAY;
-	return 0;
-}
-
-
-static int cdromplaymsf(void __user *arg)
-{
-	int status;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&msf, arg, sizeof msf))
-		return -EFAULT;
-
-	bin2bcd(&msf);
-	status = exec_long_cmd(COMPLAY, &msf);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
-		audio_status = CDROM_AUDIO_ERROR;
-		return -EIO;
-	}
-
-	audio_status = CDROM_AUDIO_PLAY;
-	return 0;
-}
-
-
-static int cdromplaytrkind(void __user *arg)
-{
-	int status;
-	struct cdrom_ti ti;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&ti, arg, sizeof ti))
-		return -EFAULT;
-
-	if (ti.cdti_trk0 < disk_info.first
-	    || ti.cdti_trk0 > disk_info.last
-	    || ti.cdti_trk1 < ti.cdti_trk0)
-		return -EINVAL;
-	if (ti.cdti_trk1 > disk_info.last)
-		ti.cdti_trk1 = disk_info.last;
-
-	msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
-	msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
-	msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
-	msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
-	msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
-	msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
-
-	DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
-		msf.cdmsf_min0,
-		msf.cdmsf_sec0,
-		msf.cdmsf_frame0,
-		msf.cdmsf_min1,
-		msf.cdmsf_sec1,
-		msf.cdmsf_frame1));
-
-	bin2bcd(&msf);
-	status = exec_long_cmd(COMPLAY, &msf);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
-		audio_status = CDROM_AUDIO_ERROR;
-		return -EIO;
-	}
-
-	audio_status = CDROM_AUDIO_PLAY;
-	return 0;
-}
-
-
-static int cdromreadtochdr(void __user *arg)
-{
-	struct cdrom_tochdr tochdr;
-
-	tochdr.cdth_trk0 = disk_info.first;
-	tochdr.cdth_trk1 = disk_info.last;
-
-	return copy_to_user(arg, &tochdr, sizeof tochdr) ? -EFAULT : 0;
-}
-
-
-static int cdromreadtocentry(void __user *arg)
-{
-	struct cdrom_tocentry entry;
-	struct cdrom_subchnl *tocptr;
-
-	if (copy_from_user(&entry, arg, sizeof entry))
-		return -EFAULT;
-
-	if (entry.cdte_track == CDROM_LEADOUT)
-		tocptr = &toc[disk_info.last + 1];
-	else if (entry.cdte_track > disk_info.last
-		|| entry.cdte_track < disk_info.first)
-		return -EINVAL;
-	else
-		tocptr = &toc[entry.cdte_track];
-
-	entry.cdte_adr = tocptr->cdsc_adr;
-	entry.cdte_ctrl = tocptr->cdsc_ctrl;
-	entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
-	entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
-	entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
-	/* %% What should go into entry.cdte_datamode? */
-
-	if (entry.cdte_format == CDROM_LBA)
-		msf2lba(&entry.cdte_addr);
-	else if (entry.cdte_format != CDROM_MSF)
-		return -EINVAL;
-
-	return copy_to_user(arg, &entry, sizeof entry) ? -EFAULT : 0;
-}
-
-
-static int cdromvolctrl(void __user *arg)
-{
-	int status;
-	struct cdrom_volctrl volctrl;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&volctrl, arg, sizeof volctrl))
-		return -EFAULT;
-
-	msf.cdmsf_min0 = 0x10;
-	msf.cdmsf_sec0 = 0x32;
-	msf.cdmsf_frame0 = volctrl.channel0;
-	msf.cdmsf_min1 = volctrl.channel1;
-	msf.cdmsf_sec1 = volctrl.channel2;
-	msf.cdmsf_frame1 = volctrl.channel3;
-
-	status = exec_long_cmd(COMCHCTRL, &msf);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
-		return -EIO;
-	}
-	return 0;
-}
-
-
-static int cdromsubchnl(void __user *arg)
-{
-	int status;
-	struct cdrom_subchnl subchnl;
-
-	if (copy_from_user(&subchnl, arg, sizeof subchnl))
-		return -EFAULT;
-
-	if (subchnl.cdsc_format != CDROM_LBA
-	    && subchnl.cdsc_format != CDROM_MSF)
-		return -EINVAL;
-
-	status = get_q_channel(&subchnl);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
-		return -EIO;
-	}
-
-	if (copy_to_user(arg, &subchnl, sizeof subchnl))
-		return -EFAULT;
-	return 0;
-}
-
-
-static struct gendisk *optcd_disk;
-
-
-static int cdromread(void __user *arg, int blocksize, int cmd)
-{
-	int status;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&msf, arg, sizeof msf))
-		return -EFAULT;
-
-	bin2bcd(&msf);
-	msf.cdmsf_min1 = 0;
-	msf.cdmsf_sec1 = 0;
-	msf.cdmsf_frame1 = 1;	/* read only one frame */
-	status = exec_read_cmd(cmd, &msf);
-
-	DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
-
-	if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
-		return -EIO;
-
-	fetch_data(optcd_disk->private_data, blocksize);
-
-	if (copy_to_user(arg, optcd_disk->private_data, blocksize))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int cdromseek(void __user *arg)
-{
-	int status;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&msf, arg, sizeof msf))
-		return -EFAULT;
-
-	bin2bcd(&msf);
-	status = exec_seek_cmd(COMSEEK, &msf);
-
-	DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
-
-	if (status < 0)
-		return -EIO;
-	return 0;
-}
-
-
-#ifdef MULTISESSION
-static int cdrommultisession(void __user *arg)
-{
-	struct cdrom_multisession ms;
-
-	if (copy_from_user(&ms, arg, sizeof ms))
-		return -EFAULT;
-
-	ms.addr.msf.minute = disk_info.last_session.minute;
-	ms.addr.msf.second = disk_info.last_session.second;
-	ms.addr.msf.frame = disk_info.last_session.frame;
-
-	if (ms.addr_format != CDROM_LBA
-	   && ms.addr_format != CDROM_MSF)
-		return -EINVAL;
-	if (ms.addr_format == CDROM_LBA)
-		msf2lba(&ms.addr);
-
-	ms.xa_flag = disk_info.xa;
-
-  	if (copy_to_user(arg, &ms, sizeof(struct cdrom_multisession)))
-		return -EFAULT;
-
-#if DEBUG_MULTIS
- 	if (ms.addr_format == CDROM_MSF)
-               	printk(KERN_DEBUG
-			"optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
-			ms.xa_flag,
-			ms.addr.msf.minute,
-			ms.addr.msf.second,
-			ms.addr.msf.frame);
-	else
-		printk(KERN_DEBUG
-		    "optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
-			ms.xa_flag,
-			ms.addr.lba,
-			disk_info.last_session.minute,
-			disk_info.last_session.second,
-			disk_info.last_session.frame);
-#endif /* DEBUG_MULTIS */
-
-	return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int cdromreset(void)
-{
-	if (state != S_IDLE) {
-		error = 1;
-		tries = 0;
-	}
-
-	toc_uptodate = 0;
-	disk_changed = 1;
-	opt_invalidate_buffers();
-	audio_status = CDROM_AUDIO_NO_STATUS;
-
-	if (!reset_drive())
-		return -EIO;
-	return 0;
-}
-
-/* VFS calls */
-
-
-static int opt_ioctl(struct inode *ip, struct file *fp,
-                     unsigned int cmd, unsigned long arg)
-{
-	int status, err, retval = 0;
-	void __user *argp = (void __user *)arg;
-
-	DEBUG((DEBUG_VFS, "starting opt_ioctl"));
-
-	if (!ip)
-		return -EINVAL;
-
-	if (cmd == CDROMRESET)
-		return cdromreset();
-
-	/* is do_optcd_request or another ioctl busy? */
-	if (state != S_IDLE || in_vfs)
-		return -EBUSY;
-
-	in_vfs = 1;
-
-	status = drive_status();
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
-		in_vfs = 0;
-		return -EIO;
-	}
-
-	if (status & ST_DOOR_OPEN)
-		switch (cmd) {	/* Actions that can be taken with door open */
-		case CDROMCLOSETRAY:
-			/* We do this before trying to read the toc. */
-			err = exec_cmd(COMCLOSE);
-			if (err < 0) {
-				DEBUG((DEBUG_VFS,
-				       "exec_cmd COMCLOSE: %02x", -err));
-				in_vfs = 0;
-				return -EIO;
-			}
-			break;
-		default:	in_vfs = 0;
-				return -EBUSY;
-		}
-
-	err = update_toc();
-	if (err < 0) {
-		DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
-		in_vfs = 0;
-		return -EIO;
-	}
-
-	DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
-
-	switch (cmd) {
-	case CDROMPAUSE:	retval = cdrompause(); break;
-	case CDROMRESUME:	retval = cdromresume(); break;
-	case CDROMPLAYMSF:	retval = cdromplaymsf(argp); break;
-	case CDROMPLAYTRKIND:	retval = cdromplaytrkind(argp); break;
-	case CDROMREADTOCHDR:	retval = cdromreadtochdr(argp); break;
-	case CDROMREADTOCENTRY:	retval = cdromreadtocentry(argp); break;
-
-	case CDROMSTOP:		err = exec_cmd(COMSTOP);
-				if (err < 0) {
-					DEBUG((DEBUG_VFS,
-						"exec_cmd COMSTOP: %02x",
-						-err));
-					retval = -EIO;
-				} else
-					audio_status = CDROM_AUDIO_NO_STATUS;
-				break;
-	case CDROMSTART:	break;	/* This is a no-op */
-	case CDROMEJECT:	err = exec_cmd(COMUNLOCK);
-				if (err < 0) {
-					DEBUG((DEBUG_VFS,
-						"exec_cmd COMUNLOCK: %02x",
-						-err));
-					retval = -EIO;
-					break;
-				}
-				err = exec_cmd(COMOPEN);
-				if (err < 0) {
-					DEBUG((DEBUG_VFS,
-						"exec_cmd COMOPEN: %02x",
-						-err));
-					retval = -EIO;
-				}
-				break;
-
-	case CDROMVOLCTRL:	retval = cdromvolctrl(argp); break;
-	case CDROMSUBCHNL:	retval = cdromsubchnl(argp); break;
-
-	/* The drive detects the mode and automatically delivers the
-	   correct 2048 bytes, so we don't need these IOCTLs */
-	case CDROMREADMODE2:	retval = -EINVAL; break;
-	case CDROMREADMODE1:	retval = -EINVAL; break;
-
-	/* Drive doesn't support reading audio */
-	case CDROMREADAUDIO:	retval = -EINVAL; break;
-
-	case CDROMEJECT_SW:	auto_eject = (char) arg;
-				break;
-
-#ifdef MULTISESSION
-	case CDROMMULTISESSION:	retval = cdrommultisession(argp); break;
-#endif
-
-	case CDROM_GET_MCN:	retval = -EINVAL; break; /* not implemented */
-	case CDROMVOLREAD:	retval = -EINVAL; break; /* not implemented */
-
-	case CDROMREADRAW:
-			/* this drive delivers 2340 bytes in raw mode */
-			retval = cdromread(argp, CD_FRAMESIZE_RAW1, COMREADRAW);
-			break;
-	case CDROMREADCOOKED:
-			retval = cdromread(argp, CD_FRAMESIZE, COMREAD);
-			break;
-	case CDROMREADALL:
-			retval = cdromread(argp, CD_FRAMESIZE_RAWER, COMREADALL);
-			break;
-
-	case CDROMSEEK:		retval = cdromseek(argp); break;
-	case CDROMPLAYBLK:	retval = -EINVAL; break; /* not implemented */
-	case CDROMCLOSETRAY:	break;	/* The action was taken earlier */
-	default:		retval = -EINVAL;
-	}
-	in_vfs = 0;
-	return retval;
-}
-
-
-static int open_count = 0;
-
-/* Open device special file; check that a disk is in. */
-static int opt_open(struct inode *ip, struct file *fp)
-{
-	DEBUG((DEBUG_VFS, "starting opt_open"));
-
-	if (!open_count && state == S_IDLE) {
-		int status;
-		char *buf;
-
-		buf = kmalloc(CD_FRAMESIZE_RAWER, GFP_KERNEL);
-		if (!buf) {
-			printk(KERN_INFO "optcd: cannot allocate read buffer\n");
-			return -ENOMEM;
-		}
-		optcd_disk->private_data = buf;		/* save read buffer */
-
-		toc_uptodate = 0;
-		opt_invalidate_buffers();
-
-		status = exec_cmd(COMCLOSE);	/* close door */
-		if (status < 0) {
-			DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status));
-		}
-
-		status = drive_status();
-		if (status < 0) {
-			DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
-			goto err_out;
-		}
-		DEBUG((DEBUG_VFS, "status: %02x", status));
-		if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
-			printk(KERN_INFO "optcd: no disk or door open\n");
-			goto err_out;
-		}
-		status = exec_cmd(COMLOCK);		/* Lock door */
-		if (status < 0) {
-			DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
-		}
-		status = update_toc();	/* Read table of contents */
-		if (status < 0)	{
-			DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
-	 		status = exec_cmd(COMUNLOCK);	/* Unlock door */
-			if (status < 0) {
-				DEBUG((DEBUG_VFS,
-				       "exec_cmd COMUNLOCK: %02x", -status));
-			}
-			goto err_out;
-		}
-		open_count++;
-	}
-
-	DEBUG((DEBUG_VFS, "exiting opt_open"));
-
-	return 0;
-
-err_out:
-	return -EIO;
-}
-
-
-/* Release device special file; flush all blocks from the buffer cache */
-static int opt_release(struct inode *ip, struct file *fp)
-{
-	int status;
-
-	DEBUG((DEBUG_VFS, "executing opt_release"));
-	DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
-		ip, ip->i_bdev->bd_disk->disk_name, fp));
-
-	if (!--open_count) {
-		toc_uptodate = 0;
-		opt_invalidate_buffers();
-	 	status = exec_cmd(COMUNLOCK);	/* Unlock door */
-		if (status < 0) {
-			DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
-		}
-		if (auto_eject) {
-			status = exec_cmd(COMOPEN);
-			DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
-		}
-		kfree(optcd_disk->private_data);
-		del_timer(&delay_timer);
-		del_timer(&req_timer);
-	}
-	return 0;
-}
-
-
-/* Check if disk has been changed */
-static int opt_media_change(struct gendisk *disk)
-{
-	DEBUG((DEBUG_VFS, "executing opt_media_change"));
-	DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
-			disk->disk_name, disk_changed));
-
-	if (disk_changed) {
-		disk_changed = 0;
-		return 1;
-	}
-	return 0;
-}
-
-/* Driver initialisation */
-
-
-/* Returns 1 if a drive is detected with a version string
-   starting with "DOLPHIN". Otherwise 0. */
-static int __init version_ok(void)
-{
-	char devname[100];
-	int count, i, ch, status;
-
-	status = exec_cmd(COMVERSION);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
-		return 0;
-	}
-	if ((count = get_data(1)) < 0) {
-		DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
-		return 0;
-	}
-	for (i = 0, ch = -1; count > 0; count--) {
-		if ((ch = get_data(1)) < 0) {
-			DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
-			break;
-		}
-		if (i < 99)
-			devname[i++] = ch;
-	}
-	devname[i] = '\0';
-	if (ch < 0)
-		return 0;
-
-	printk(KERN_INFO "optcd: Device %s detected\n", devname);
-	return ((devname[0] == 'D')
-	     && (devname[1] == 'O')
-	     && (devname[2] == 'L')
-	     && (devname[3] == 'P')
-	     && (devname[4] == 'H')
-	     && (devname[5] == 'I')
-	     && (devname[6] == 'N'));
-}
-
-
-static struct block_device_operations opt_fops = {
-	.owner		= THIS_MODULE,
-	.open		= opt_open,
-	.release	= opt_release,
-	.ioctl		= opt_ioctl,
-	.media_changed	= opt_media_change,
-};
-
-#ifndef MODULE
-/* Get kernel parameter when used as a kernel driver */
-static int optcd_setup(char *str)
-{
-	int ints[4];
-	(void)get_options(str, ARRAY_SIZE(ints), ints);
-	
-	if (ints[0] > 0)
-		optcd_port = ints[1];
-
- 	return 1;
-}
-
-__setup("optcd=", optcd_setup);
-
-#endif /* MODULE */
-
-/* Test for presence of drive and initialize it. Called at boot time
-   or during module initialisation. */
-static int __init optcd_init(void)
-{
-	int status;
-
-	if (optcd_port <= 0) {
-		printk(KERN_INFO
-			"optcd: no Optics Storage CDROM Initialization\n");
-		return -EIO;
-	}
-	optcd_disk = alloc_disk(1);
-	if (!optcd_disk) {
-		printk(KERN_ERR "optcd: can't allocate disk\n");
-		return -ENOMEM;
-	}
-	optcd_disk->major = MAJOR_NR;
-	optcd_disk->first_minor = 0;
-	optcd_disk->fops = &opt_fops;
-	sprintf(optcd_disk->disk_name, "optcd");
-
-	if (!request_region(optcd_port, 4, "optcd")) {
-		printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n",
-			optcd_port);
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-
-	if (!reset_drive()) {
-		printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port);
-		release_region(optcd_port, 4);
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-	if (!version_ok()) {
-		printk(KERN_ERR "optcd: unknown drive detected; aborting\n");
-		release_region(optcd_port, 4);
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-	status = exec_cmd(COMINITDOUBLE);
-	if (status < 0) {
-		printk(KERN_ERR "optcd: cannot init double speed mode\n");
-		release_region(optcd_port, 4);
-		DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-	if (register_blkdev(MAJOR_NR, "optcd")) {
-		release_region(optcd_port, 4);
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-
-
-	opt_queue = blk_init_queue(do_optcd_request, &optcd_lock);
-	if (!opt_queue) {
-		unregister_blkdev(MAJOR_NR, "optcd");
-		release_region(optcd_port, 4);
-		put_disk(optcd_disk);
-		return -ENOMEM;
-	}
-
-	blk_queue_hardsect_size(opt_queue, 2048);
-	optcd_disk->queue = opt_queue;
-	add_disk(optcd_disk);
-
-	printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
-	return 0;
-}
-
-
-static void __exit optcd_exit(void)
-{
-	del_gendisk(optcd_disk);
-	put_disk(optcd_disk);
-	if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
-		printk(KERN_ERR "optcd: what's that: can't unregister\n");
-		return;
-	}
-	blk_cleanup_queue(opt_queue);
-	release_region(optcd_port, 4);
-	printk(KERN_INFO "optcd: module released.\n");
-}
-
-module_init(optcd_init);
-module_exit(optcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR);
diff --git a/drivers/cdrom/optcd.h b/drivers/cdrom/optcd.h
deleted file mode 100644
index 1911bb9..0000000
--- a/drivers/cdrom/optcd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*	linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver
-	$Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $
-
-	Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
-	Configuration file for linux/drivers/cdrom/optcd.c
-*/
-
-#ifndef _LINUX_OPTCD_H
-#define _LINUX_OPTCD_H
-
-
-/* I/O base of drive. Drive uses base to base+2.
-   This setting can be overridden with the kernel or insmod command
-   line option 'optcd=<portbase>'. Use address of 0 to disable driver. */
-#define OPTCD_PORTBASE	0x340
-
-
-/* enable / disable parts of driver by define / undef */
-#define	MULTISESSION		/* multisession support (ALPHA) */
-
-
-/* Change 0 to 1 to debug various parts of the driver */
-#define	DEBUG_DRIVE_IF	0	/* Low level drive interface */
-#define	DEBUG_CONV	0	/* Address conversions */
-#define	DEBUG_BUFFERS	0	/* Buffering and block size conversion */
-#define	DEBUG_REQUEST	0	/* Request mechanism */
-#define	DEBUG_STATE	0	/* State machine */
-#define	DEBUG_TOC	0	/* Q-channel and Table of Contents */
-#define	DEBUG_MULTIS	0	/* Multisession code */
-#define	DEBUG_VFS	0	/* VFS interface */
-
-
-/* Don't touch these unless you know what you're doing. */
-
-/* Various timeout loop repetition counts. */
-#define BUSY_TIMEOUT		10000000	/* for busy wait */
-#define FAST_TIMEOUT		100000		/* ibid. for probing */
-#define SLEEP_TIMEOUT		6000		/* for timer wait */
-#define MULTI_SEEK_TIMEOUT	1000		/* for timer wait */
-#define READ_TIMEOUT		6000		/* for poll wait */
-#define STOP_TIMEOUT		2000		/* for poll wait */
-#define RESET_WAIT		5000		/* busy wait at drive reset */
-
-/* # of buffers for block size conversion. 6 is optimal for my setup (P75),
-   giving 280 kb/s, with 0.4% CPU usage. Experiment to find your optimal
-   setting */
-#define N_BUFS		6
-
-
-#endif /* _LINUX_OPTCD_H */
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
deleted file mode 100644
index a1283b1..0000000
--- a/drivers/cdrom/sbpcd.c
+++ /dev/null
@@ -1,5966 +0,0 @@
-/*
- *  sbpcd.c   CD-ROM device driver for the whole family of traditional,
- *            non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives.
- *            Works with SoundBlaster compatible cards and with "no-sound"
- *            interface cards like Lasermate, Panasonic CI-101P, Teac, ...
- *            Also for the Longshine LCS-7260 drive.
- *            Also for the IBM "External ISA CD-Rom" drive.
- *            Also for the CreativeLabs CD200 drive.
- *            Also for the TEAC CD-55A drive.
- *            Also for the ECS-AT "Vertos 100" drive.
- *            Not for Sanyo drives (but for the H94A, sjcd is there...).
- *            Not for any other Funai drives than the CD200 types (sometimes
- *             labelled E2550UA or MK4015 or 2800F).
- */
-
-#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000"
-
-/*   Copyright (C) 1993, 1994, 1995  Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2, or (at your option)
- *   any later version.
- *
- *   You should have received a copy of the GNU General Public License
- *   (for example /usr/src/linux/COPYING); if not, write to the Free
- *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   If you change this software, you should mail a .diff file with some
- *   description lines to emoenke@gwdg.de. I want to know about it.
- *
- *   If you are the editor of a Linux CD, you should enable sbpcd.c within
- *   your boot floppy kernel and send me one of your CDs for free.
- *
- *   If you would like to port the driver to an other operating system (f.e.
- *   FreeBSD or NetBSD) or use it as an information source, you shall not be
- *   restricted by the GPL under the following conditions:
- *     a) the source code of your work is freely available
- *     b) my part of the work gets mentioned at all places where your 
- *        authorship gets mentioned
- *     c) I receive a copy of your code together with a full installation
- *        package of your operating system for free.
- *
- *
- *  VERSION HISTORY
- *
- *  0.1  initial release, April/May 93, after mcd.c (Martin Harriss)
- *
- *  0.2  thek "repeat:"-loop in do_sbpcd_request did not check for
- *       end-of-request_queue (resulting in kernel panic).
- *       Flow control seems stable, but throughput is not better.  
- *
- *  0.3  interrupt locking totally eliminated (maybe "inb" and "outb"
- *       are still locking) - 0.2 made keyboard-type-ahead losses.
- *       check_sbpcd_media_change added (to use by isofs/inode.c)
- *       - but it detects almost nothing.
- *
- *  0.4  use MAJOR 25 definitely.
- *       Almost total re-design to support double-speed drives and
- *       "naked" (no sound) interface cards ("LaserMate" interface type).
- *       Flow control should be exact now.
- *       Don't occupy the SbPro IRQ line (not needed either); will
- *       live together with Hannu Savolainen's sndkit now.
- *       Speeded up data transfer to 150 kB/sec, with help from Kai
- *       Makisara, the "provider" of the "mt" tape utility.
- *       Give "SpinUp" command if necessary.
- *       First steps to support up to 4 drives (but currently only one).
- *       Implemented audio capabilities - workman should work, xcdplayer
- *       gives some problems.
- *       This version is still consuming too much CPU time, and
- *       sleeping still has to be worked on.
- *       During "long" implied seeks, it seems possible that a 
- *       ReadStatus command gets ignored. That gives the message
- *       "ResponseStatus timed out" (happens about 6 times here during
- *       a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is
- *       handled without data error, but it should get done better.
- *
- *  0.5  Free CPU during waits (again with help from Kai Makisara).
- *       Made it work together with the LILO/kernel setup standard.
- *       Included auto-probing code, as suggested by YGGDRASIL.
- *       Formal redesign to add DDI debugging.
- *       There are still flaws in IOCTL (workman with double speed drive).
- *
- *  1.0  Added support for all drive IDs (0...3, no longer only 0)
- *       and up to 4 drives on one controller.
- *       Added "#define MANY_SESSION" for "old" multi session CDs.
- *
- *  1.1  Do SpinUp for new drives, too.
- *       Revised for clean compile under "old" kernels (0.99pl9).
- *
- *  1.2  Found the "workman with double-speed drive" bug: use the driver's
- *       audio_state, not what the drive is reporting with ReadSubQ.
- *
- *  1.3  Minor cleanups.
- *       Refinements regarding Workman.
- *
- *  1.4  Read XA disks (PhotoCDs) with "old" drives, too (but only the first
- *       session - no chance to fully access a "multi-session" CD).
- *       This currently still is too slow (50 kB/sec) - but possibly
- *       the old drives won't do it faster.
- *       Implemented "door (un)lock" for new drives (still does not work
- *       as wanted - no lock possible after an unlock).
- *       Added some debugging printout for the UPC/EAN code - but my drives 
- *       return only zeroes. Is there no UPC/EAN code written?
- *
- *  1.5  Laborate with UPC/EAN code (not better yet).
- *       Adapt to kernel 1.1.8 change (have to explicitly include
- *       <linux/string.h> now).
- *
- *  1.6  Trying to read audio frames as data. Impossible with the current
- *       drive firmware levels, as it seems. Awaiting any hint. ;-)
- *       Changed "door unlock": repeat it until success.
- *       Changed CDROMSTOP routine (stop somewhat "softer" so that Workman
- *       won't get confused).
- *       Added a third interface type: Sequoia S-1000, as used with the SPEA
- *       Media FX sound card. This interface (usable for Sony and Mitsumi 
- *       drives, too) needs a special configuration setup and behaves like a 
- *       LaserMate type after that. Still experimental - I do not have such
- *       an interface.
- *       Use the "variable BLOCK_SIZE" feature (2048). But it does only work
- *       if you give the mount option "block=2048".
- *       The media_check routine is currently disabled; now that it gets
- *       called as it should I fear it must get synchronized for not to
- *       disturb the normal driver's activity.
- *
- *  2.0  Version number bumped - two reasons:
- *       - reading audio tracks as data works now with CR-562 and CR-563. We
- *       currently do it by an IOCTL (yet has to get standardized), one frame
- *       at a time; that is pretty slow. But it works.
- *       - we are maintaining now up to 4 interfaces (each up to 4 drives):
- *       did it the easy way - a different MAJOR (25, 26, ...) and a different
- *       copy of the driver (sbpcd.c, sbpcd2.c, sbpcd3.c, sbpcd4.c - only
- *       distinguished by the value of SBPCD_ISSUE and the driver's name),
- *       and a common sbpcd.h file.
- *       Bettered the "ReadCapacity error" problem with old CR-52x drives (the
- *       drives sometimes need a manual "eject/insert" before work): just
- *       reset the drive and do again. Needs lots of resets here and sometimes
- *       that does not cure, so this can't be the solution.
- *
- *  2.1  Found bug with multisession CDs (accessing frame 16).
- *       "read audio" works now with address type CDROM_MSF, too.
- *       Bigger audio frame buffer: allows reading max. 4 frames at time; this
- *       gives a significant speedup, but reading more than one frame at once
- *       gives missing chunks at each single frame boundary.
- *
- *  2.2  Kernel interface cleanups: timers, init, setup, media check.
- *
- *  2.3  Let "door lock" and "eject" live together.
- *       Implemented "close tray" (done automatically during open).
- *
- *  2.4  Use different names for device registering.
- *
- *  2.5  Added "#if EJECT" code (default: enabled) to automatically eject
- *       the tray during last call to "sbpcd_release".
- *       Added "#if JUKEBOX" code (default: disabled) to automatically eject
- *       the tray during call to "sbpcd_open" if no disk is in.
- *       Turn on the CD volume of "compatible" sound cards, too; just define
- *       SOUND_BASE (in sbpcd.h) accordingly (default: disabled).
- *
- *  2.6  Nothing new.  
- *
- *  2.7  Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly:
- *       0 disables, 1 enables auto-ejecting. Useful to keep the tray in
- *       during shutdown.
- *
- *  2.8  Added first support (still BETA, I need feedback or a drive) for
- *       the Longshine LCS-7260 drives. They appear as double-speed drives
- *       using the "old" command scheme, extended by tray control and door
- *       lock functions.
- *       Found (and fixed preliminary) a flaw with some multisession CDs: we
- *       have to re-direct not only the accesses to frame 16 (the isofs
- *       routines drive it up to max. 100), but also those to the continuation
- *       (repetition) frames (as far as they exist - currently set fix as
- *       16..20).
- *       Changed default of the "JUKEBOX" define. If you use this default,
- *       your tray will eject if you try to mount without a disk in. Next
- *       mount command will insert the tray - so, just fill in a disk. ;-)
- *
- *  2.9  Fulfilled the Longshine LCS-7260 support; with great help and
- *       experiments by Serge Robyns.
- *       First attempts to support the TEAC CD-55A drives; but still not
- *       usable yet.
- *       Implemented the CDROMMULTISESSION ioctl; this is an attempt to handle
- *       multi session CDs more "transparent" (redirection handling has to be
- *       done within the isofs routines, and only for the special purpose of
- *       obtaining the "right" volume descriptor; accesses to the raw device
- *       should not get redirected).
- *
- *  3.0  Just a "normal" increment, with some provisions to do it better. ;-)
- *       Introduced "#define READ_AUDIO" to specify the maximum number of 
- *       audio frames to grab with one request. This defines a buffer size
- *       within kernel space; a value of 0 will reserve no such space and
- *       disable the CDROMREADAUDIO ioctl. A value of 75 enables the reading
- *       of a whole second with one command, but will use a buffer of more
- *       than 172 kB.
- *       Started CD200 support. Drive detection should work, but nothing
- *       more.
- *
- *  3.1  Working to support the CD200 and the Teac CD-55A drives.
- *       AT-BUS style device numbering no longer used: use SCSI style now.
- *       So, the first "found" device has MINOR 0, regardless of the
- *       jumpered drive ID. This implies modifications to the /dev/sbpcd*
- *       entries for some people, but will help the DAU (german TLA, english:
- *       "newbie", maybe ;-) to install his "first" system from a CD.
- *
- *  3.2  Still testing with CD200 and CD-55A drives.
- *
- *  3.3  Working with CD200 support.
- *
- *  3.4  Auto-probing stops if an address of 0 is seen (to be entered with
- *       the kernel command line).
- *       Made the driver "loadable". If used as a module, "audio copy" is
- *       disabled, and the internal read ahead data buffer has a reduced size
- *       of 4 kB; so, throughput may be reduced a little bit with slow CPUs.
- *
- *  3.5  Provisions to handle weird photoCDs which have an interrupted
- *       "formatting" immediately after the last frames of some files: simply
- *       never "read ahead" with MultiSession CDs. By this, CPU usage may be
- *       increased with those CDs, and there may be a loss in speed.
- *       Re-structured the messaging system.
- *       The "loadable" version no longer has a limited READ_AUDIO buffer
- *       size.
- *       Removed "MANY_SESSION" handling for "old" multi session CDs.
- *       Added "private" IOCTLs CDROMRESET and CDROMVOLREAD.
- *       Started again to support the TEAC CD-55A drives, now that I found
- *       the money for "my own" drive. ;-)
- *       The TEAC CD-55A support is fairly working now.
- *       I have measured that the drive "delivers" at 600 kB/sec (even with
- *       bigger requests than the drive's 64 kB buffer can satisfy), but
- *       the "real" rate does not exceed 520 kB/sec at the moment. 
- *       Caused by the various changes to build in TEAC support, the timed
- *       loops are de-optimized at the moment (less throughput with CR-52x
- *       drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64).
- *
- *  3.6  Fixed TEAC data read problems with SbPro interfaces.
- *       Initial size of the READ_AUDIO buffer is 0. Can get set to any size
- *       during runtime.
- *
- *  3.7  Introduced MAX_DRIVES for some poor interface cards (seen with TEAC
- *       drives) which allow only one drive (ID 0); this avoids repetitive
- *       detection under IDs 1..3. 
- *       Elongated cmd_out_T response waiting; necessary for photo CDs with
- *       a lot of sessions.
- *       Bettered the sbpcd_open() behavior with TEAC drives.
- *
- *  3.8  Elongated max_latency for CR-56x drives.
- *
- *  3.9  Finally fixed the long-known SoundScape/SPEA/Sequoia S-1000 interface
- *       configuration bug.
- *       Now Corey, Heiko, Ken, Leo, Vadim/Eric & Werner are invited to copy
- *       the config_spea() routine into their drivers. ;-)
- *
- *  4.0  No "big step" - normal version increment.
- *       Adapted the benefits from 1.3.33.
- *       Fiddled with CDROMREADAUDIO flaws.
- *       Avoid ReadCapacity command with CD200 drives (the MKE 1.01 version
- *       seems not to support it).
- *       Fulfilled "read audio" for CD200 drives, with help of Pete Heist
- *       (heistp@rpi.edu).
- *
- *  4.1  Use loglevel KERN_INFO with printk().
- *       Added support for "Vertos 100" drive ("ECS-AT") - it is very similar
- *       to the Longshine LCS-7260. Give feedback if you can - I never saw
- *       such a drive, and I have no specs.
- *
- *  4.2  Support for Teac 16-bit interface cards. Can't get auto-detected,
- *       so you have to jumper your card to 0x2C0. Still not 100% - come
- *       in contact if you can give qualified feedback.
- *       Use loglevel KERN_NOTICE with printk(). If you get annoyed by a
- *       flood of unwanted messages and the accompanied delay, try to read
- *       my documentation. Especially the Linux CDROM drivers have to do an
- *       important job for the newcomers, so the "distributed" version has
- *       to fit some special needs. Since generations, the flood of messages
- *       is user-configurable (even at runtime), but to get aware of this, one
- *       needs a special mental quality: the ability to read.
- *       
- *  4.3  CD200F does not like to receive a command while the drive is
- *       reading the ToC; still trying to solve it.
- *       Removed some redundant verify_area calls (yes, Heiko Eissfeldt
- *       is visiting all the Linux CDROM drivers ;-).
- *       
- *  4.4  Adapted one idea from tiensivu@pilot.msu.edu's "stripping-down"
- *       experiments: "KLOGD_PAUSE".
- *       Inhibited "play audio" attempts with data CDs. Provisions for a
- *       "data-safe" handling of "mixed" (data plus audio) Cds.
- *
- *  4.5  Meanwhile Gonzalo Tornaria <tornaria@cmat.edu.uy> (GTL) built a
- *       special end_request routine: we seem to have to take care for not
- *       to have two processes working at the request list. My understanding
- *       was and is that ll_rw_blk should not call do_sbpcd_request as long
- *       as there is still one call active (the first call will care for all
- *       outstanding I/Os, and if a second call happens, that is a bug in
- *       ll_rw_blk.c).
- *       "Check media change" without touching any drive.
- *
- *  4.6  Use a semaphore to synchronize multi-activity; elaborated by Rob
- *       Riggs <rriggs@tesser.com>. At the moment, we simply block "read"
- *       against "ioctl" and vice versa. This could be refined further, but
- *       I guess with almost no performance increase.
- *       Experiments to speed up the CD-55A; again with help of Rob Riggs
- *       (to be true, he gave both, idea & code. ;-)
- *
- *  4.61 Ported to Uniform CD-ROM driver by 
- *       Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- *       changes by Erik Andersen <andersee@debian.org>
- *
- *  4.62 Fix a bug where playing audio left the drive in an unusable state.
- *         Heiko Eissfeldt <heiko@colossus.escape.de>
- *
- *  November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	             Removed init_module & cleanup_module in favor of 
- *	             module_init & module_exit.
- *	             Torben Mathiasen <tmm@image.dk>
- *
- *  4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer.
- *		Annoying things fixed:
- *		TOC reread on automated disk changes
- *		TOC reread on manual cd changes
- *		Play IOCTL tries to play CD before it's actually ready... sometimes.
- *		CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play.
- *		Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000
- *
- *  4.64 Fix module parameters - were being completely ignored.
- *	 Can also specify max_drives=N as a setup int to get rid of
- *	 "ghost" drives on crap hardware (aren't they all?)   Paul Gortmaker
- *
- *  TODO
- *     implement "read all subchannel data" (96 bytes per frame)
- *     remove alot of the virtual status bits and deal with hardware status
- *     move the change of cd for audio to a better place
- *     add debug levels to insmod parameters (trivial)
- *
- *     special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
- *     elaborated speed-up experiments (and the fabulous results!), for
- *     the "push" towards load-free wait loops, and for the extensive mail
- *     thread which brought additional hints and bug fixes.
- *
- */
-
-/*
- * Trying to merge requests breaks this driver horribly (as in it goes
- * boom and apparently has done so since 2.3.41).  As it is a legacy
- * driver for a horribly slow double speed CD on a hideous interface
- * designed for polled operation, I won't lose any sleep in simply
- * disallowing merging.				Paul G.  02/2001
- *
- * Thu May 30 14:14:47 CEST 2002:
- *
- * I have presumably found the reson for the above - there was a bogous
- * end_request substitute, which was manipulating the request queues
- * incorrectly. If someone has access to the actual hardware, and it's
- * still operations - well  please free to test it.
- *
- * Marcin Dalecki
- */
-
-/*
- * Add bio/kdev_t changes for 2.5.x required to make it work again. 
- * Still room for improvement in the request handling here if anyone
- * actually cares.  Bring your own chainsaw.    Paul G.  02/2002
- */
-
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <stdarg.h>
-#include "sbpcd.h"
-
-#define MAJOR_NR MATSUSHITA_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-/*==========================================================================*/
-#if SBPCD_DIS_IRQ
-# define SBPCD_CLI cli()
-# define SBPCD_STI sti()
-#else
-# define SBPCD_CLI
-# define SBPCD_STI
-#endif
-
-/*==========================================================================*/
-/*
- * auto-probing address list
- * inspired by Adam J. Richter from Yggdrasil
- *
- * still not good enough - can cause a hang.
- *   example: a NE 2000 ethernet card at 300 will cause a hang probing 310.
- * if that happens, reboot and use the LILO (kernel) command line.
- * The possibly conflicting ethernet card addresses get NOT probed 
- * by default - to minimize the hang possibilities. 
- *
- * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to
- * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx.
- *
- * send mail to emoenke@gwdg.de if your interface card is not FULLY
- * represented here.
- */
-static int sbpcd[] =
-{
-	CDROM_PORT, SBPRO, /* probe with user's setup first */
-#if DISTRIBUTION
-	0x230, 1, /* Soundblaster Pro and 16 (default) */
-#if 0
-	0x300, 0, /* CI-101P (default), WDH-7001C (default),
-		     Galaxy (default), Reveal (one default) */
-	0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */
-	0x2C0, 3, /* Teac 16-bit cards */
-	0x260, 1, /* OmniCD */
-	0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default),
-		     Longshine LCS-6853 (default) */
-	0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */
-	0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */
-	0x360, 0, /* Lasermate, CI-101P */
-	0x270, 1, /* Soundblaster 16 */
-	0x670, 0, /* "sound card #9" */
-	0x690, 0, /* "sound card #9" */
-	0x338, 2, /* SPEA Media FX, Ensonic SoundScape (default) */
-	0x328, 2, /* SPEA Media FX */
-	0x348, 2, /* SPEA Media FX */
-	0x634, 0, /* some newer sound cards */
-	0x638, 0, /* some newer sound cards */
-	0x230, 1, /* some newer sound cards */
-	/* due to incomplete address decoding of the SbPro card, these must be last */
-	0x630, 0, /* "sound card #9" (default) */
-	0x650, 0, /* "sound card #9" */
-#ifdef MODULE
-	/*
-	 * some "hazardous" locations (no harm with the loadable version)
-	 * (will stop the bus if a NE2000 ethernet card resides at offset -0x10)
-	 */
-	0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
-	0x350, 0, /* Lasermate, CI-101P */
-	0x358, 2, /* SPEA Media FX */
-	0x370, 0, /* Lasermate, CI-101P */
-	0x290, 1, /* Soundblaster 16 */
-	0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
-#endif /* MODULE */
-#endif
-#endif /* DISTRIBUTION */
-};
-
-/*
- * Protects access to global structures etc.
- */
-static  __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock);
-static struct request_queue *sbpcd_queue;
-
-/* You can only set the first pair, from old MODULE_PARM code.  */
-static int sbpcd_set(const char *val, struct kernel_param *kp)
-{
-	get_options((char *)val, 2, (int *)sbpcd);
-	return 0;
-}
-module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0);
-
-#define NUM_PROBE  (sizeof(sbpcd) / sizeof(int))
-
-/*==========================================================================*/
-
-#define INLINE inline
-
-/*==========================================================================*/
-/*
- * the forward references:
- */
-static void sbp_sleep(u_int);
-static void mark_timeout_delay(u_long);
-static void mark_timeout_data(u_long);
-#if 0
-static void mark_timeout_audio(u_long);
-#endif
-static void sbp_read_cmd(struct request *req);
-static int sbp_data(struct request *req);
-static int cmd_out(void);
-static int DiskInfo(void);
-
-/*==========================================================================*/
-
-/*
- * pattern for printk selection:
- *
- * (1<<DBG_INF)  necessary information
- * (1<<DBG_BSZ)  BLOCK_SIZE trace
- * (1<<DBG_REA)  "read" status trace
- * (1<<DBG_CHK)  "media check" trace
- * (1<<DBG_TIM)  datarate timer test
- * (1<<DBG_INI)  initialization trace
- * (1<<DBG_TOC)  tell TocEntry values
- * (1<<DBG_IOC)  ioctl trace
- * (1<<DBG_STA)  "ResponseStatus" trace
- * (1<<DBG_ERR)  "cc_ReadError" trace
- * (1<<DBG_CMD)  "cmd_out" trace
- * (1<<DBG_WRN)  give explanation before auto-probing
- * (1<<DBG_MUL)  multi session code test
- * (1<<DBG_IDX)  "drive_id != 0" test code
- * (1<<DBG_IOX)  some special information
- * (1<<DBG_DID)  drive ID test
- * (1<<DBG_RES)  drive reset info
- * (1<<DBG_SPI)  SpinUp test info
- * (1<<DBG_IOS)  ioctl trace: "subchannel"
- * (1<<DBG_IO2)  ioctl trace: general
- * (1<<DBG_UPC)  show UPC info
- * (1<<DBG_XA1)  XA mode debugging
- * (1<<DBG_LCK)  door (un)lock info
- * (1<<DBG_SQ1)   dump SubQ frame
- * (1<<DBG_AUD)  "read audio" debugging
- * (1<<DBG_SEQ)  Sequoia interface configuration trace
- * (1<<DBG_LCS)  Longshine LCS-7260 debugging trace
- * (1<<DBG_CD2)  MKE/Funai CD200 debugging trace
- * (1<<DBG_TEA)  TEAC CD-55A debugging trace
- * (1<<DBG_ECS)  ECS-AT (Vertos-100) debugging trace
- * (1<<DBG_000)  unnecessary information
- */
-#if DISTRIBUTION
-static int sbpcd_debug = (1<<DBG_INF);
-#else
-static int sbpcd_debug = 0 & ((1<<DBG_INF) |
-			  (1<<DBG_TOC) |
-			  (1<<DBG_MUL) |
-			  (1<<DBG_UPC));
-#endif /* DISTRIBUTION */
-
-static int sbpcd_ioaddr = CDROM_PORT;	/* default I/O base address */
-static int sbpro_type = SBPRO;
-static unsigned char f_16bit;
-static unsigned char do_16bit;
-static int CDo_command, CDo_reset;
-static int CDo_sel_i_d, CDo_enable;
-static int CDi_info, CDi_status, CDi_data;
-static struct cdrom_msf msf;
-static struct cdrom_ti ti;
-static struct cdrom_tochdr tochdr;
-static struct cdrom_tocentry tocentry;
-static struct cdrom_subchnl SC;
-static struct cdrom_volctrl volctrl;
-static struct cdrom_read_audio read_audio;
-
-static unsigned char msgnum;
-static char msgbuf[80];
-
-static int max_drives = MAX_DRIVES;
-module_param(max_drives, int, 0);
-#ifndef MODULE
-static unsigned char setup_done;
-static const char *str_sb_l = "soundblaster";
-static const char *str_sp_l = "spea";
-static const char *str_ss_l = "soundscape";
-static const char *str_t16_l = "teac16bit";
-static const char *str_ss = "SoundScape";
-#endif
-static const char *str_sb = "SoundBlaster";
-static const char *str_lm = "LaserMate";
-static const char *str_sp = "SPEA";
-static const char *str_t16 = "Teac16bit";
-static const char *type;
-static const char *major_name="sbpcd";
-
-/*==========================================================================*/
-
-#ifdef FUTURE
-static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq);
-#endif /* FUTURE */
-
-static int teac=SBP_TEAC_SPEED;
-static int buffers=SBP_BUFFER_FRAMES;
-
-static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */
-static u_char family1[]="CR-56";    /* MKE CR-562, CR-563 */
-static u_char family2[]="CD200";    /* MKE CD200, Funai CD200F */
-static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */
-static u_char familyT[]="CD-55";    /* TEAC CD-55A */
-static u_char familyV[]="ECS-AT";   /* ECS Vertos 100 */
-
-static u_int recursion; /* internal testing only */
-static u_int fatal_err; /* internal testing only */
-static u_int response_count;
-static u_int flags_cmd_out;
-static u_char cmd_type;
-static u_char drvcmd[10];
-static u_char infobuf[20];
-static u_char xa_head_buf[CD_XA_HEAD];
-static u_char xa_tail_buf[CD_XA_TAIL];
-
-#if OLD_BUSY
-static volatile u_char busy_data;
-static volatile u_char busy_audio; /* true semaphores would be safer */
-#endif /* OLD_BUSY */ 
-static DECLARE_MUTEX(ioctl_read_sem);
-static u_long timeout;
-static volatile u_char timed_out_delay;
-static volatile u_char timed_out_data;
-#if 0
-static volatile u_char timed_out_audio;
-#endif
-static u_int datarate= 1000000;
-static u_int maxtim16=16000000;
-static u_int maxtim04= 4000000;
-static u_int maxtim02= 2000000;
-static u_int maxtim_8=   30000;
-#if LONG_TIMING
-static u_int maxtim_data= 9000;
-#else
-static u_int maxtim_data= 3000;
-#endif /* LONG_TIMING */ 
-#if DISTRIBUTION
-static int n_retries=6;
-#else
-static int n_retries=6;
-#endif
-/*==========================================================================*/
-
-static int ndrives;
-static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto};
-
-/*==========================================================================*/
-/*
- * drive space begins here (needed separate for each unit) 
- */
-static struct sbpcd_drive {
-	char drv_id;           /* "jumpered" drive ID or -1 */
-	char drv_sel;          /* drive select lines bits */
-	
-	char drive_model[9];
-	u_char firmware_version[4];
-	char f_eject;          /* auto-eject flag: 0 or 1 */
-	u_char *sbp_buf;       /* Pointer to internal data buffer,
-				  space allocated during sbpcd_init() */
-	u_int sbp_bufsiz;      /* size of sbp_buf (# of frames) */
-	int sbp_first_frame;   /* First frame in buffer */
-	int sbp_last_frame;    /* Last frame in buffer  */
-	int sbp_read_frames;   /* Number of frames being read to buffer */
-	int sbp_current;       /* Frame being currently read */
-	
-	u_char mode;           /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */
-	u_char *aud_buf;       /* Pointer to audio data buffer,
-				  space allocated during sbpcd_init() */
-	u_int sbp_audsiz;      /* size of aud_buf (# of raw frames) */
-	u_int drv_type;
-	u_char drv_options;
-	int status_bits;
-	u_char diskstate_flags;
-	u_char sense_byte;
-	
-	u_char CD_changed;
-	char open_count;
-	u_char error_byte;
-	
-	u_char f_multisession;
-	u_int lba_multi;
-	int first_session;
-	int last_session;
-	int track_of_last_session;
-	
-	u_char audio_state;
-	u_int pos_audio_start;
-	u_int pos_audio_end;
-	char vol_chan0;
-	u_char vol_ctrl0;
-	char vol_chan1;
-	u_char vol_ctrl1;
-#if 000 /* no supported drive has it */
-	char vol_chan2;
-	u_char vol_ctrl2;
-	char vol_chan3;
-	u_char vol_ctrl3;
-#endif /*000 */
-	u_char volume_control; /* TEAC on/off bits */
-	
-	u_char SubQ_ctl_adr;
-	u_char SubQ_trk;
-	u_char SubQ_pnt_idx;
-	u_int SubQ_run_tot;
-	u_int SubQ_run_trk;
-	u_char SubQ_whatisthis;
-	
-	u_char UPC_ctl_adr;
-	u_char UPC_buf[7];
-	
-	int frame_size;
-	int CDsize_frm;
-	
-	u_char xa_byte; /* 0x20: XA capabilities */
-	u_char n_first_track; /* binary */
-	u_char n_last_track; /* binary (not bcd), 0x01...0x63 */
-	u_int size_msf; /* time of whole CD, position of LeadOut track */
-	u_int size_blk;
-	
-	u_char TocEnt_nixbyte; /* em */
-	u_char TocEnt_ctl_adr;
-	u_char TocEnt_number;
-	u_char TocEnt_format; /* em */
-	u_int TocEnt_address;
-#ifdef SAFE_MIXED
-	char has_data;
-#endif /* SAFE_MIXED */ 
-	u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */
-	
-	struct {
-		u_char nixbyte; /* em */
-		u_char ctl_adr; /* 0x4x: data, 0x0x: audio */
-		u_char number;
-		u_char format; /* em */ /* 0x00: lba, 0x01: msf */
-		u_int address;
-	} TocBuffer[MAX_TRACKS+1]; /* last entry faked */ 
-	
-	int in_SpinUp; /* CR-52x test flag */
-	int n_bytes; /* TEAC awaited response count */
-	u_char error_state, b3, b4; /* TEAC command error state */
-	u_char f_drv_error; /* TEAC command error flag */
-	u_char speed_byte;
-	int frmsiz;
-	u_char f_XA; /* 1: XA */
-	u_char type_byte; /* 0, 1, 3 */
-	u_char mode_xb_6;
-	u_char mode_yb_7;
-	u_char mode_xb_8;
-	u_char delay;
-	struct cdrom_device_info *sbpcd_infop;
-	struct gendisk *disk;
-} D_S[NR_SBPCD];
-
-static struct sbpcd_drive *current_drive = D_S;
-
-/*
- * drive space ends here (needed separate for each unit)
- */
-/*==========================================================================*/
-#if 0
-unsigned long cli_sti; /* for saving the processor flags */
-#endif
-/*==========================================================================*/
-static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
-static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
-#if 0
-static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0);
-#endif
-/*==========================================================================*/
-/*
- * DDI interface
- */
-static void msg(int level, const char *fmt, ...)
-{
-#if DISTRIBUTION
-#define MSG_LEVEL KERN_NOTICE
-#else
-#define MSG_LEVEL KERN_INFO
-#endif /* DISTRIBUTION */
-
-	char buf[256];
-	va_list args;
-	
-	if (!(sbpcd_debug&(1<<level))) return;
-	
-	msgnum++;
-	if (msgnum>99) msgnum=0;
-	va_start(args, fmt);
-	vsnprintf(buf, sizeof(buf), fmt, args);
-	va_end(args);
-	printk(MSG_LEVEL "%s-%d [%02d]:  %s", major_name, current_drive - D_S, msgnum, buf);
-#if KLOGD_PAUSE
-	sbp_sleep(KLOGD_PAUSE); /* else messages get lost */
-#endif /* KLOGD_PAUSE */ 
-	return;
-}
-/*==========================================================================*/
-/*
- * DDI interface: runtime trace bit pattern maintenance
- */
-static int sbpcd_dbg_ioctl(unsigned long arg, int level)
-{
-	switch(arg)
-	{
-	case 0:	/* OFF */
-		sbpcd_debug = DBG_INF;
-		break;
-		
-	default:
-		if (arg>=128) sbpcd_debug &= ~(1<<(arg-128));
-		else sbpcd_debug |= (1<<arg);
-	}
-	return (arg);
-}
-/*==========================================================================*/
-static void mark_timeout_delay(u_long i)
-{
-	timed_out_delay=1;
-#if 0
-	msg(DBG_TIM,"delay timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-static void mark_timeout_data(u_long i)
-{
-	timed_out_data=1;
-#if 0
-	msg(DBG_TIM,"data timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-#if 0
-static void mark_timeout_audio(u_long i)
-{
-	timed_out_audio=1;
-#if 0
-	msg(DBG_TIM,"audio timer expired.\n");
-#endif
-}
-#endif
-/*==========================================================================*/
-/*
- * Wait a little while (used for polling the drive).
- */
-static void sbp_sleep(u_int time)
-{
-	sti();
-	schedule_timeout_interruptible(time);
-	sti();
-}
-/*==========================================================================*/
-#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);}
-/*==========================================================================*/
-/*
- *  convert logical_block_address to m-s-f_number (3 bytes only)
- */
-static INLINE void lba2msf(int lba, u_char *msf)
-{
-	lba += CD_MSF_OFFSET;
-	msf[0] = lba / (CD_SECS*CD_FRAMES);
-	lba %= CD_SECS*CD_FRAMES;
-	msf[1] = lba / CD_FRAMES;
-	msf[2] = lba % CD_FRAMES;
-}
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- *  convert msf-bin to msf-bcd
- */
-static INLINE void bin2bcdx(u_char *p)  /* must work only up to 75 or 99 */
-{
-	*p=((*p/10)<<4)|(*p%10);
-}
-/*==========================================================================*/
-static INLINE u_int blk2msf(u_int blk)
-{
-	MSF msf;
-	u_int mm;
-	
-	msf.c[3] = 0;
-	msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES);
-	mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES);
-	msf.c[1] = mm / CD_FRAMES;
-	msf.c[0] = mm % CD_FRAMES;
-	return (msf.n);
-}
-/*==========================================================================*/
-static INLINE u_int make16(u_char rh, u_char rl)
-{
-	return ((rh<<8)|rl);
-}
-/*==========================================================================*/
-static INLINE u_int make32(u_int rh, u_int rl)
-{
-	return ((rh<<16)|rl);
-}
-/*==========================================================================*/
-static INLINE u_char swap_nibbles(u_char i)
-{
-	return ((i<<4)|(i>>4));
-}
-/*==========================================================================*/
-static INLINE u_char byt2bcd(u_char i)
-{
-	return (((i/10)<<4)+i%10);
-}
-/*==========================================================================*/
-static INLINE u_char bcd2bin(u_char bcd)
-{
-	return ((bcd>>4)*10+(bcd&0x0F));
-}
-/*==========================================================================*/
-static INLINE int msf2blk(int msfx)
-{
-	MSF msf;
-	int i;
-	
-	msf.n=msfx;
-	i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET;
-	if (i<0) return (0);
-	return (i);
-}
-/*==========================================================================*/
-/*
- *  convert m-s-f_number (3 bytes only) to logical_block_address 
- */
-static INLINE int msf2lba(u_char *msf)
-{
-	int i;
-	
-	i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET;
-	if (i<0) return (0);
-	return (i);
-}
-/*==========================================================================*/
-/* evaluate cc_ReadError code */ 
-static int sta2err(int sta)
-{
-	if (famT_drive)
-	{
-		if (sta==0x00) return (0);
-		if (sta==0x01) return (-604); /* CRC error */
-		if (sta==0x02) return (-602); /* drive not ready */
-		if (sta==0x03) return (-607); /* unknown media */
-		if (sta==0x04) return (-612); /* general failure */
-		if (sta==0x05) return (0);
-		if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */
-		if (sta==0x0b) return (-612); /* general failure */
-		if (sta==0xff) return (-612); /* general failure */
-		return (0);
-	}
-	else
-	{
-		if (sta<=2) return (sta);
-		if (sta==0x05) return (-604); /* CRC error */
-		if (sta==0x06) return (-606); /* seek error */
-		if (sta==0x0d) return (-606); /* seek error */
-		if (sta==0x0e) return (-603); /* unknown command */
-		if (sta==0x14) return (-603); /* unknown command */
-		if (sta==0x0c) return (-611); /* read fault */
-		if (sta==0x0f) return (-611); /* read fault */
-		if (sta==0x10) return (-611); /* read fault */
-		if (sta>=0x16) return (-612); /* general failure */
-		if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */
-		if (famL_drive)
-			if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */
-		return (-602); /* drive not ready */
-	}
-}
-/*==========================================================================*/
-static INLINE void clr_cmdbuf(void)
-{
-	int i;
-	
-	for (i=0;i<10;i++) drvcmd[i]=0;
-	cmd_type=0;
-}
-/*==========================================================================*/
-static void flush_status(void)
-{
-	int i;
-	
-	sbp_sleep(15*HZ/10);
-	for (i=maxtim_data;i!=0;i--) inb(CDi_status);
-}
-/*====================================================================*/
-/*
- * CDi status loop for Teac CD-55A (Rob Riggs)
- *
- * This is needed because for some strange reason
- * the CD-55A can take a real long time to give a
- * status response. This seems to happen after we
- * issue a READ command where a long seek is involved.
- *
- * I tried to ensure that we get max throughput with
- * minimal busy waiting. We busy wait at first, then
- * "switch gears" and start sleeping. We sleep for
- * longer periods of time the longer we wait.
- *
- */
-static int CDi_stat_loop_T(void)
-{
-	int	i, gear=1;
-	u_long  timeout_1, timeout_2, timeout_3, timeout_4;
-
-	timeout_1 = jiffies + HZ / 50;  /* sbp_sleep(0) for a short period */
-	timeout_2 = jiffies + HZ / 5;	/* nap for no more than 200ms */
-	timeout_3 = jiffies + 5 * HZ;	/* sleep for up to 5s */
-	timeout_4 = jiffies + 45 * HZ;	/* long sleep for up to 45s. */
-	do
-          {
-            i = inb(CDi_status);
-            if (!(i&s_not_data_ready)) return (i);
-            if (!(i&s_not_result_ready)) return (i);
-            switch(gear)
-              {
-              case 4:
-                sbp_sleep(HZ);
-                if (time_after(jiffies, timeout_4)) gear++;
-                msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
-                break;
-              case 3:
-                sbp_sleep(HZ/10);
-                if (time_after(jiffies, timeout_3)) gear++;
-                break;
-              case 2:
-                sbp_sleep(HZ/100);
-                if (time_after(jiffies, timeout_2)) gear++;
-                break;
-              case 1:
-                sbp_sleep(0);
-                if (time_after(jiffies, timeout_1)) gear++;
-              }
-          } while (gear < 5);
-	return -1;
-}
-/*==========================================================================*/
-static int CDi_stat_loop(void)
-{
-	int i,j;
-	
-	for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
-	{
-		for ( ;i!=0;i--)
-		{
-			j=inb(CDi_status);
-			if (!(j&s_not_data_ready)) return (j);
-			if (!(j&s_not_result_ready)) return (j);
-			if (fam0L_drive) if (j&s_attention) return (j);
-		}
-		sbp_sleep(1);
-		i = 1;
-	}
-	msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
-	return (-1);
-}
-/*==========================================================================*/
-#if 00000
-/*==========================================================================*/
-static int tst_DataReady(void)
-{
-	int i;
-	
-	i=inb(CDi_status);
-	if (i&s_not_data_ready) return (0);
-	return (1);
-}
-/*==========================================================================*/
-static int tst_ResultReady(void)
-{
-	int i;
-	
-	i=inb(CDi_status);
-	if (i&s_not_result_ready) return (0);
-	return (1);
-}
-/*==========================================================================*/
-static int tst_Attention(void)
-{
-	int i;
-	
-	i=inb(CDi_status);
-	if (i&s_attention) return (1);
-	return (0);
-}
-/*==========================================================================*/
-#endif
-/*==========================================================================*/
-static int ResponseInfo(void)
-{
-	int i,j,st=0;
-	u_long timeout;
-	
-	for (i=0,timeout=jiffies+HZ;i<response_count;i++) 
-	{
-		for (j=maxtim_data; ; )
-		{
-			for ( ;j!=0;j-- )
-			{
-				st=inb(CDi_status);
-				if (!(st&s_not_result_ready)) break;
-			}
-			if ((j!=0)||time_after_eq(jiffies, timeout)) break;
-			sbp_sleep(1);
-			j = 1;
-		}
-		if (time_after_eq(jiffies, timeout)) break;
-		infobuf[i]=inb(CDi_info);
-	}
-#if 000
-	while (!(inb(CDi_status)&s_not_result_ready))
-	{
-		infobuf[i++]=inb(CDi_info);
-	}
-	j=i-response_count;
-	if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);
-#endif /* 000 */
-	for (j=0;j<i;j++)
-		sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-	msgbuf[j*3]=0;
-	msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i);
-	j=response_count-i;
-	if (j>0) return (-j);
-	else return (i);
-}
-/*==========================================================================*/
-static void EvaluateStatus(int st)
-{
-	current_drive->status_bits=0;
-	if (fam1_drive) current_drive->status_bits=st|p_success;
-	else if (fam0_drive)
-	{
-		if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in;
-		if (st&p_spinning) current_drive->status_bits |= p_spinning;
-		if (st&p_check) current_drive->status_bits |= p_check;
- 		if (st&p_success_old) current_drive->status_bits |= p_success;
- 		if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
-		if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok;
-	}
-	else if (famLV_drive)
-	{
- 		current_drive->status_bits |= p_success;
-		if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in;
-		if (st&p_spinning) current_drive->status_bits |= p_spinning;
-		if (st&p_check) current_drive->status_bits |= p_check;
-		if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
-		if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed;
-		if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked;
-	}
-	else if (fam2_drive)
-	{
- 		current_drive->status_bits |= p_success;
-		if (st&p2_check) current_drive->status_bits |= p1_check;
-		if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
-		if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
-		if (st&p2_busy1) current_drive->status_bits |= p1_busy;
-		if (st&p2_busy2) current_drive->status_bits |= p1_busy;
-		if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
-		if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
-		if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
-	}
-	else if (famT_drive)
-	{
-		return; /* still needs to get coded */
- 		current_drive->status_bits |= p_success;
-		if (st&p2_check) current_drive->status_bits |= p1_check;
-		if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
-		if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
-		if (st&p2_busy1) current_drive->status_bits |= p1_busy;
-		if (st&p2_busy2) current_drive->status_bits |= p1_busy;
-		if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
-		if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
-		if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
-	}
-	return;
-}
-/*==========================================================================*/
-static int cmd_out_T(void);
-
-static int get_state_T(void)
-{
-	int i;
-
-	clr_cmdbuf();
-	current_drive->n_bytes=1;
-	drvcmd[0]=CMDT_STATUS;
-	i=cmd_out_T();
-	if (i>=0) i=infobuf[0];
-	else
-	{
-		msg(DBG_TEA,"get_state_T error %d\n", i);
-		return (i);
-	}
-	if (i>=0)
-		/* 2: closed, disk in */
-		current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok;
-	else if (current_drive->error_state==6)
-	{
-		/* 3: closed, disk in, changed ("06 xx xx") */
-		current_drive->status_bits=p1_door_closed|p1_disk_in;
-		current_drive->CD_changed=0xFF;
-		current_drive->diskstate_flags &= ~toc_bit;
-	}
-	else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00))
-	{
-		/* 1: closed, no disk ("xx yy zz"or "02 3A 00") */
-		current_drive->status_bits=p1_door_closed;
-		current_drive->open_count=0;
-	}
-	else if (current_drive->b4==0x01)
-	{
-		/* 0: open ("02 3A 01") */
-		current_drive->status_bits=0;
-		current_drive->open_count=0;
-	}
-	else
-	{
-		/* 1: closed, no disk ("02 3A xx") */
-		current_drive->status_bits=p1_door_closed;
-		current_drive->open_count=0;
-	}
-	return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static int ResponseStatus(void)
-{
-	int i,j;
-	u_long timeout;
-	
-	msg(DBG_STA,"doing ResponseStatus...\n");
-	if (famT_drive) return (get_state_T());
-	if (flags_cmd_out & f_respo3) timeout = jiffies;
-	else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ;
-	else timeout = jiffies + 4*HZ;
-	j=maxtim_8;
-	do
-	{
-		for ( ;j!=0;j--)
-		{ 
-			i=inb(CDi_status);
-			if (!(i&s_not_result_ready)) break;
-		}
-		if ((j!=0)||time_after(jiffies, timeout)) break;
-		sbp_sleep(1);
-		j = 1;
-	}
-	while (1);
-	if (j==0) 
-	{
-		if ((flags_cmd_out & f_respo3) == 0)
-			msg(DBG_STA,"ResponseStatus: timeout.\n");
-		current_drive->status_bits=0;
-		return (-401);
-	}
-	i=inb(CDi_info);
-	msg(DBG_STA,"ResponseStatus: response %02X.\n", i);
-	EvaluateStatus(i);
-	msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i);
-	return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static void cc_ReadStatus(void)
-{
-	int i;
-	
-	msg(DBG_STA,"giving cc_ReadStatus command\n");
-	if (famT_drive) return;
-	SBPCD_CLI;
-	if (fam0LV_drive) OUT(CDo_command,CMD0_STATUS);
-	else if (fam1_drive) OUT(CDo_command,CMD1_STATUS);
-	else if (fam2_drive) OUT(CDo_command,CMD2_STATUS);
-	if (!fam0LV_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
-	SBPCD_STI;
-}
-/*==========================================================================*/
-static int cc_ReadError(void)
-{
-	int i;
-
-	clr_cmdbuf();
-	msg(DBG_ERR,"giving cc_ReadError command.\n");
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_READ_ERR;
-		response_count=8;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_READ_ERR;
-		response_count=6;
-		if (famLV_drive)
-			flags_cmd_out=f_putcmd;
-		else
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_READ_ERR;
-		response_count=6;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		response_count=5;
-		drvcmd[0]=CMDT_READ_ERR;
-	}
-	i=cmd_out();
-	current_drive->error_byte=0;
-	msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i);
-	if (i<0) return (i);
-	if (fam0V_drive) i=1;
-	else i=2;
-	current_drive->error_byte=infobuf[i];
-	msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte);
-	i=sta2err(infobuf[i]);
-        if (i==-ERR_DISKCHANGE)
-        {
-                current_drive->CD_changed=0xFF;
-                current_drive->diskstate_flags &= ~toc_bit;
-        }
-	return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void);
-
-static int cmd_out_T(void)
-{
-#undef CMDT_TRIES
-#define CMDT_TRIES 1000
-#define TEST_FALSE_FF 1
-
-	int i, j, l=0, m, ntries;
-	unsigned long flags;
-
-	current_drive->error_state=0;
-	current_drive->b3=0;
-	current_drive->b4=0;
-	current_drive->f_drv_error=0;
-	for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf);
-
-	OUT(CDo_sel_i_d,0);
-	OUT(CDo_enable,current_drive->drv_sel);
-	i=inb(CDi_status);
-	do_16bit=0;
-	if ((f_16bit)&&(!(i&0x80)))
-	{
-		do_16bit=1;
-		msg(DBG_TEA,"cmd_out_T: do_16bit set.\n");
-	}
-	if (!(i&s_not_result_ready))
-	do
-	{
-		j=inb(CDi_info);
-		i=inb(CDi_status);
-		sbp_sleep(0);
-		msg(DBG_TEA,"cmd_out_T: spurious !s_not_result_ready. (%02X)\n", j);
-	}
-	while (!(i&s_not_result_ready));
-	save_flags(flags); cli();
-	for (i=0;i<10;i++) OUT(CDo_command,drvcmd[i]);
-	restore_flags(flags);
-	for (ntries=CMDT_TRIES;ntries>0;ntries--)
-	{
-		if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */
-#if 01
-		OUT(CDo_sel_i_d,1);
-#endif /* 01 */
-		if (teac==2)
-                  {
-                    if ((i=CDi_stat_loop_T()) == -1) break;
-                  }
-		else
-                  {
-#if 0
-                    OUT(CDo_sel_i_d,1);
-#endif /* 0 */ 
-                    i=inb(CDi_status);
-                  }
-		if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */
-		{
-			OUT(CDo_sel_i_d,1);
-			if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
-			if (drvcmd[0]==CMDT_DISKINFO)
-			{
-				l=0;
-				do
-                                {
-                                        if (do_16bit)
-                                        {
-                                                i=inw(CDi_data);
-                                                infobuf[l++]=i&0x0ff;
-                                                infobuf[l++]=i>>8;
-#if TEST_FALSE_FF
-                                                if ((l==2)&&(infobuf[0]==0x0ff))
-                                                {
-                                                        infobuf[0]=infobuf[1];
-                                                        l=1;
-                                                        msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n");
-                                                }
-#endif /* TEST_FALSE_FF */ 
-                                        }
-                                        else infobuf[l++]=inb(CDi_data);
-                                        i=inb(CDi_status);
-                                }
-				while (!(i&s_not_data_ready));
-				for (j=0;j<l;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-				msgbuf[j*3]=0;
-				msg(DBG_CMD,"cmd_out_T data response:%s\n", msgbuf);
-			}
-			else
-			{
-				msg(DBG_TEA,"cmd_out_T: data response with cmd_%02X!\n",
-                                    drvcmd[0]);
-				j=0;
-				do
-				{
-                                        if (do_16bit) i=inw(CDi_data);
-                                        else i=inb(CDi_data);
-                                        j++;
-                                        i=inb(CDi_status);
-				}
-				while (!(i&s_not_data_ready));
-				msg(DBG_TEA,"cmd_out_T: data response: discarded %d bytes/words.\n", j);
-				fatal_err++;
-			}
-		}
-		i=inb(CDi_status);
-		if (!(i&s_not_result_ready))
-		{
-			OUT(CDo_sel_i_d,0);
-			if (drvcmd[0]==CMDT_DISKINFO) m=l;
-			else m=0;
-			do
-			{
-				infobuf[m++]=inb(CDi_info);
-				i=inb(CDi_status);
-			}
-			while (!(i&s_not_result_ready));
-			for (j=0;j<m;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-			msgbuf[j*3]=0;
-			msg(DBG_CMD,"cmd_out_T info response:%s\n", msgbuf);
-			if (drvcmd[0]==CMDT_DISKINFO)
-                        {
-                                infobuf[0]=infobuf[l];
-                                if (infobuf[0]!=0x02) return (l); /* data length */
-                        }
-			else if (infobuf[0]!=0x02) return (m); /* info length */
-			do
-			{
-				++recursion;
-				if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion);
-				clr_cmdbuf();
-				drvcmd[0]=CMDT_READ_ERR;
-				j=cmd_out_T(); /* !!! recursive here !!! */
-				--recursion;
-				sbp_sleep(1);
-			}
-			while (j<0);
-			current_drive->error_state=infobuf[2];
-			current_drive->b3=infobuf[3];
-			current_drive->b4=infobuf[4];
-			if (current_drive->f_drv_error)
-			{
-				current_drive->f_drv_error=0;
-				cc_DriveReset();
-				current_drive->error_state=2;
-			}
-			return (-current_drive->error_state-400);
-		}
-		if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
-		if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10);
-		else sbp_sleep(HZ/100);
-		if (ntries>(CMDT_TRIES-50)) continue;
-		msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
-	}
-	current_drive->f_drv_error=1;
-	cc_DriveReset();
-	current_drive->error_state=2;
-	return (-99);
-}
-/*==========================================================================*/
-static int cmd_out(void)
-{
-	int i=0;
-	
-	if (famT_drive) return(cmd_out_T());
-	
-	if (flags_cmd_out&f_putcmd)
-	{ 
-		unsigned long flags;
-		for (i=0;i<7;i++)
-			sprintf(&msgbuf[i*3], " %02X", drvcmd[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_CMD,"cmd_out:%s\n", msgbuf);
-		save_flags(flags); cli();
-		for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
-		restore_flags(flags);
-	}
-	if (response_count!=0)
-	{
-		if (cmd_type!=0)
-		{
-			if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-			msg(DBG_INF,"misleaded to try ResponseData.\n");
-			if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-			return (-22);
-		}
-		else i=ResponseInfo();
-		if (i<0) return (i);
-	}
-	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n");
-	if (flags_cmd_out&f_lopsta)
-	{
-		i=CDi_stat_loop();
-		if ((i<0)||!(i&s_attention)) return (-8);
-	}
-	if (!(flags_cmd_out&f_getsta)) goto LOC_229;
-	
- LOC_228:
-	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n");
-	cc_ReadStatus();
-	
- LOC_229:
-	if (flags_cmd_out&f_ResponseStatus) 
-	{
-		if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n");
-		i=ResponseStatus();
-		/* builds status_bits, returns orig. status or p_busy_new */
-		if (i<0) return (i);
-		if (flags_cmd_out&(f_bit1|f_wait_if_busy))
-		{
-			if (!st_check)
-			{
-				if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232;
-				if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228;
-			}
-		}
-	}
- LOC_232:
-	if (!(flags_cmd_out&f_obey_p_check)) return (0);
-	if (!st_check) return (0);
-	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n");
-	i=cc_ReadError();
-	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n");
-	msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i);
-	return (i);
-}
-/*==========================================================================*/
-static int cc_Seek(u_int pos, char f_blk_msf)
-{
-	int i;
-	
-  clr_cmdbuf();
-	if (f_blk_msf>1) return (-3);
-	if (fam0V_drive)
-	{
-		drvcmd[0]=CMD0_SEEK;
-		if (f_blk_msf==1) pos=msf2blk(pos);
-		drvcmd[2]=(pos>>16)&0x00FF;
-		drvcmd[3]=(pos>>8)&0x00FF;
-		drvcmd[4]=pos&0x00FF;
-		if (fam0_drive)
-		  flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-			f_ResponseStatus | f_obey_p_check | f_bit1;
-		else
-		  flags_cmd_out = f_putcmd;
-	}
-	else if (fam1L_drive)
-	{
-		drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */
-		if (f_blk_msf==0) pos=blk2msf(pos);
-		drvcmd[1]=(pos>>16)&0x00FF;
-		drvcmd[2]=(pos>>8)&0x00FF;
-		drvcmd[3]=pos&0x00FF;
-		if (famL_drive)
-			flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-		else
-			flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_SEEK;
-		if (f_blk_msf==0) pos=blk2msf(pos);
-		drvcmd[2]=(pos>>24)&0x00FF;
-		drvcmd[3]=(pos>>16)&0x00FF;
-		drvcmd[4]=(pos>>8)&0x00FF;
-		drvcmd[5]=pos&0x00FF;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_SEEK;
-		if (f_blk_msf==1) pos=msf2blk(pos);
-		drvcmd[2]=(pos>>24)&0x00FF;
-		drvcmd[3]=(pos>>16)&0x00FF;
-		drvcmd[4]=(pos>>8)&0x00FF;
-		drvcmd[5]=pos&0x00FF;
-		current_drive->n_bytes=1;
-	}
-	response_count=0;
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_SpinUp(void)
-{
-	int i;
-	
-	msg(DBG_SPI,"SpinUp.\n");
-	current_drive->in_SpinUp = 1;
-	clr_cmdbuf();
-	if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_SPINUP;
-		if (fam0L_drive)
-		  flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
-		    f_ResponseStatus|f_obey_p_check|f_bit1;
-		else
-		  flags_cmd_out=f_putcmd;
-	}
-	else if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_SPINUP;
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_TRAY_CTL;
-		drvcmd[4]=0x01; /* "spinup" */
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_TRAY_CTL;
-		drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */
-	}
-	response_count=0;
-	i=cmd_out();
-	current_drive->in_SpinUp = 0;
-	return (i);
-}
-/*==========================================================================*/
-static int cc_SpinDown(void)
-{
-	int i;
-	
-	if (fam0_drive) return (0);
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_SPINDOWN;
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_TRAY_CTL;
-		drvcmd[4]=0x02; /* "eject" */
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famL_drive)
-	{
-		drvcmd[0]=CMDL_SPINDOWN;
-		drvcmd[1]=1;
-		flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-	}
-	else if (famV_drive)
-	{
-		drvcmd[0]=CMDV_SPINDOWN;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_TRAY_CTL;
-		drvcmd[4]=0x02; /* "eject" */
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_get_mode_T(void)
-{
-	int i;
-	
-	clr_cmdbuf();
-	response_count=10;
-	drvcmd[0]=CMDT_GETMODE;
-	drvcmd[4]=response_count;
-	i=cmd_out_T();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_set_mode_T(void)
-{
-	int i;
-	
-	clr_cmdbuf();
-	response_count=1;
-	drvcmd[0]=CMDT_SETMODE;
-	drvcmd[1]=current_drive->speed_byte;
-	drvcmd[2]=current_drive->frmsiz>>8;
-	drvcmd[3]=current_drive->frmsiz&0x0FF;
-	drvcmd[4]=current_drive->f_XA; /* 1: XA */
-	drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */
-	drvcmd[6]=current_drive->mode_xb_6;
-	drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control;
-	drvcmd[8]=current_drive->mode_xb_8;
-	drvcmd[9]=current_drive->delay;
-	i=cmd_out_T();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_prep_mode_T(void)
-{
-	int i, j;
-	
-	i=cc_get_mode_T();
-	if (i<0) return (i);
-	for (i=0;i<10;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
-	current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */
-	current_drive->frmsiz=make16(infobuf[2],infobuf[3]);
-	current_drive->f_XA=infobuf[4];
-	if (current_drive->f_XA==0) current_drive->type_byte=0;
-	else current_drive->type_byte=1;
-	current_drive->mode_xb_6=infobuf[6];
-	current_drive->mode_yb_7=1;
-	current_drive->mode_xb_8=infobuf[8];
-	current_drive->delay=0; /* 0, 1, 2, 3 */
-	j=cc_set_mode_T();
-	i=cc_get_mode_T();
-	for (i=0;i<10;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
-	return (j);
-}
-/*==========================================================================*/
-static int cc_SetSpeed(u_char speed, u_char x1, u_char x2)
-{
-	int i;
-	
-	if (fam0LV_drive) return (0);
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_SETMODE;
-		drvcmd[1]=0x03;
-		drvcmd[2]=speed;
-		drvcmd[3]=x1;
-		drvcmd[4]=x2;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_SETSPEED;
-		if (speed&speed_auto)
-		{
-			drvcmd[2]=0xFF;
-			drvcmd[3]=0xFF;
-		}
-		else
-		{
-			drvcmd[2]=0;
-			drvcmd[3]=150;
-		}
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		return (0);
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_SetVolume(void)
-{
-	int i;
-	u_char channel0,channel1,volume0,volume1;
-	u_char control0,value0,control1,value1;
-	
-	current_drive->diskstate_flags &= ~volume_bit;
-	clr_cmdbuf();
-	channel0=current_drive->vol_chan0;
-	volume0=current_drive->vol_ctrl0;
-	channel1=control1=current_drive->vol_chan1;
-	volume1=value1=current_drive->vol_ctrl1;
-	control0=value0=0;
-	
-	if (famV_drive) return (0);
-
-	if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211))
-	{
-		if ((volume0!=0)&&(volume1==0))
-		{
-			volume1=volume0;
-			channel1=channel0;
-		}
-		else if ((volume0==0)&&(volume1!=0))
-		{
-			volume0=volume1;
-			channel0=channel1;
-		}
-	}
-	if (channel0>1)
-	{
-		channel0=0;
-		volume0=0;
-	}
-	if (channel1>1)
-	{
-		channel1=1;
-		volume1=0;
-	}
-	
-	if (fam1_drive)
-	{
-		control0=channel0+1;
-		control1=channel1+1;
-		value0=(volume0>volume1)?volume0:volume1;
-		value1=value0;
-		if (volume0==0) control0=0;
-		if (volume1==0) control1=0;
-		drvcmd[0]=CMD1_SETMODE;
-		drvcmd[1]=0x05;
-		drvcmd[3]=control0;
-		drvcmd[4]=value0;
-		drvcmd[5]=control1;
-		drvcmd[6]=value1;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		control0=channel0+1;
-		control1=channel1+1;
-		value0=(volume0>volume1)?volume0:volume1;
-		value1=value0;
-		if (volume0==0) control0=0;
-		if (volume1==0) control1=0;
-		drvcmd[0]=CMD2_SETMODE;
-		drvcmd[1]=0x0E;
-		drvcmd[3]=control0;
-		drvcmd[4]=value0;
-		drvcmd[5]=control1;
-		drvcmd[6]=value1;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famL_drive)
-	{
-		if ((volume0==0)||(channel0!=0)) control0 |= 0x80;
-		if ((volume1==0)||(channel1!=1)) control0 |= 0x40;
-		if (volume0|volume1) value0=0x80;
-		drvcmd[0]=CMDL_SETMODE;
-		drvcmd[1]=0x03;
-		drvcmd[4]=control0;
-		drvcmd[5]=value0;
-		flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-	}
-	else if (fam0_drive) /* different firmware levels */
-	{
-		if (current_drive->drv_type>=drv_300)
-		{
-			control0=volume0&0xFC;
-			value0=volume1&0xFC;
-			if ((volume0!=0)&&(volume0<4)) control0 |= 0x04;
-			if ((volume1!=0)&&(volume1<4)) value0 |= 0x04;
-			if (channel0!=0) control0 |= 0x01;
-			if (channel1==1) value0 |= 0x01;
-		}
-		else
-		{
-			value0=(volume0>volume1)?volume0:volume1;
-			if (current_drive->drv_type<drv_211)
-			{
-				if (channel0!=0)
-				{
-					i=channel1;
-					channel1=channel0;
-					channel0=i;
-					i=volume1;
-					volume1=volume0;
-					volume0=i;
-				}
-				if (channel0==channel1)
-				{
-					if (channel0==0)
-					{
-						channel1=1;
-						volume1=0;
-						volume0=value0;
-					}
-					else
-					{
-						channel0=0;
-						volume0=0;
-						volume1=value0;
-					}
-				}
-			}
-			
-			if ((volume0!=0)&&(volume1!=0))
-			{
-				if (volume0==0xFF) volume1=0xFF;
-				else if (volume1==0xFF) volume0=0xFF;
-			}
-			else if (current_drive->drv_type<drv_201) volume0=volume1=value0;
-			
-			if (current_drive->drv_type>=drv_201)
-			{
-				if (volume0==0) control0 |= 0x80;
-				if (volume1==0) control0 |= 0x40;
-			}
-			if (current_drive->drv_type>=drv_211)
-			{
-				if (channel0!=0) control0 |= 0x20;
-				if (channel1!=1) control0 |= 0x10;
-			}
-		}
-		drvcmd[0]=CMD0_SETMODE;
-		drvcmd[1]=0x83;
-		drvcmd[4]=control0;
-		drvcmd[5]=value0;
-		flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		current_drive->volume_control=0;
-		if (!volume0) current_drive->volume_control|=0x10;
-		if (!volume1) current_drive->volume_control|=0x20;
-		i=cc_prep_mode_T();
-		if (i<0) return (i);
-	}
-	if (!famT_drive)
-	{
-		response_count=0;
-		i=cmd_out();
-		if (i<0) return (i);
-	}
-	current_drive->diskstate_flags |= volume_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int GetStatus(void)
-{
-	int i;
-	
-	if (famT_drive) return (0);
-	flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check;
-	response_count=0;
-	cmd_type=0;
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void)
-{
-	int i;
-	
-	msg(DBG_RES,"cc_DriveReset called.\n");
-	clr_cmdbuf();
-	response_count=0;
-	if (fam0LV_drive) OUT(CDo_reset,0x00);
-	else if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_RESET;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_RESET;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		OUT(CDo_reset,0x00);
-	}
-	else if (famT_drive)
-	{
-		OUT(CDo_sel_i_d,0);
-		OUT(CDo_enable,current_drive->drv_sel);
-		OUT(CDo_command,CMDT_RESET);
-		for (i=1;i<10;i++) OUT(CDo_command,0);
-	}
-	if (fam0LV_drive) sbp_sleep(5*HZ); /* wait 5 seconds */
-	else sbp_sleep(1*HZ); /* wait a second */
-#if 1
-	if (famT_drive)
-	{
-		msg(DBG_TEA, "================CMDT_RESET given=================.\n");
-		sbp_sleep(3*HZ);
-	}
-#endif /* 1 */ 
-	flush_status();
-	i=GetStatus();
-	if (i<0) return i;
-	if (!famT_drive)
-		if (current_drive->error_byte!=aud_12) return -501;
-	return (0);
-}
-
-/*==========================================================================*/
-static int SetSpeed(void)
-{
-	int i, speed;
-	
-	if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0);
-	speed=speed_auto;
-	if (!(current_drive->drv_options&speed_auto))
-	{
-		speed |= speed_300;
-		if (!(current_drive->drv_options&speed_300)) speed=0;
-	}
-	i=cc_SetSpeed(speed,0,0);
-	return (i);
-}
-
-static void switch_drive(struct sbpcd_drive *);
-
-static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	if (p != current_drive)
-		switch_drive(p);
-
-	return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
-}
-
-/*==========================================================================*/
-static int DriveReset(void)
-{
-	int i;
-	
-	i=cc_DriveReset();
-	if (i<0) return (-22);
-	do
-	{
-		i=GetStatus();
-		if ((i<0)&&(i!=-ERR_DISKCHANGE)) {
-			return (-2); /* from sta2err */
-		}
-		if (!st_caddy_in) break;
-		sbp_sleep(1);
-	}
-	while (!st_diskok);
-#if 000
-	current_drive->CD_changed=1;
-#endif
-	if ((st_door_closed) && (st_caddy_in))
-	{
-		i=DiskInfo();
-		if (i<0) return (-23);
-	}
-	return (0);
-}
-
-static int sbpcd_reset(struct cdrom_device_info *cdi)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	if (p != current_drive)
-		switch_drive(p);
-	return DriveReset();
-}
-
-/*==========================================================================*/
-static int cc_PlayAudio(int pos_audio_start,int pos_audio_end)
-{
-	int i, j, n;
-	
-	if (current_drive->audio_state==audio_playing) return (-EINVAL);
-	clr_cmdbuf();
-	response_count=0;
-	if (famLV_drive)
-	{
-		drvcmd[0]=CMDL_PLAY;
-		i=msf2blk(pos_audio_start);
-		n=msf2blk(pos_audio_end)+1-i;
-		drvcmd[1]=(i>>16)&0x00FF;
-		drvcmd[2]=(i>>8)&0x00FF;
-		drvcmd[3]=i&0x00FF;
-		drvcmd[4]=(n>>16)&0x00FF;
-		drvcmd[5]=(n>>8)&0x00FF;
-		drvcmd[6]=n&0x00FF;
-		if (famL_drive)
-		flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-			f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
-		else
-		  flags_cmd_out = f_putcmd;
-	}
-	else
-	{
-		j=1;
-		if (fam1_drive)
-		{
-			drvcmd[0]=CMD1_PLAY_MSF;
-			flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
-				f_obey_p_check | f_wait_if_busy;
-		}
-		else if (fam2_drive)
-		{
-			drvcmd[0]=CMD2_PLAY_MSF;
-			flags_cmd_out = f_putcmd | f_ResponseStatus | f_obey_p_check;
-		}
-		else if (famT_drive)
-		{
-			drvcmd[0]=CMDT_PLAY_MSF;
-			j=3;
-			response_count=1;
-		}
-		else if (fam0_drive)
-		{
-			drvcmd[0]=CMD0_PLAY_MSF;
-			flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-				f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
-		}
-		drvcmd[j]=(pos_audio_start>>16)&0x00FF;
-		drvcmd[j+1]=(pos_audio_start>>8)&0x00FF;
-		drvcmd[j+2]=pos_audio_start&0x00FF;
-		drvcmd[j+3]=(pos_audio_end>>16)&0x00FF;
-		drvcmd[j+4]=(pos_audio_end>>8)&0x00FF;
-		drvcmd[j+5]=pos_audio_end&0x00FF;
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_Pause_Resume(int pau_res)
-{
-	int i;
-	
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_PAU_RES;
-		if (pau_res!=1) drvcmd[1]=0x80;
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_PAU_RES;
-		if (pau_res!=1) drvcmd[2]=0x01;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_PAU_RES;
-		if (pau_res!=1) drvcmd[1]=0x80;
-		if (famL_drive)
-			flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
-				f_obey_p_check|f_bit1;
-		else if (famV_drive)
-		  flags_cmd_out=f_putcmd;
-		else
-			flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
-				f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		if (pau_res==3)	return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end));
-		else if (pau_res==1) drvcmd[0]=CMDT_PAUSE;
-		else return (-56);
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_LockDoor(char lock)
-{
-	int i;
-	
-	if (fam0_drive) return (0);
-	msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S);
-	msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked);
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_LOCK_CTL;
-		if (lock==1) drvcmd[1]=0x01;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_LOCK_CTL;
-		if (lock==1) drvcmd[4]=0x01;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famLV_drive)
-	{
-		drvcmd[0]=CMDL_LOCK_CTL;
-		if (lock==1) drvcmd[1]=0x01;
-		if (famL_drive)
-		  flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-		else
-		  flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_LOCK_CTL;
-		if (lock==1) drvcmd[4]=0x01;
-	}
-	i=cmd_out();
-	msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked);
-	return (i);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int UnLockDoor(void)
-{
-	int i,j;
-	
-	j=20;
-	do
-	{
-		i=cc_LockDoor(0);
-		--j;
-		sbp_sleep(1);
-	}
-	while ((i<0)&&(j));
-	if (i<0)
-	{
-		cc_DriveReset();
-		return -84;
-	}
-	return (0);
-}
-/*==========================================================================*/
-static int LockDoor(void)
-{
-	int i,j;
-	
-	j=20;
-	do
-	{
-		i=cc_LockDoor(1);
-		--j;
-		sbp_sleep(1);
-	}
-	while ((i<0)&&(j));
-	if (j==0)
-	{		
-		cc_DriveReset();
-		j=20;
-		do
-		{
-			i=cc_LockDoor(1);
-			--j;
-			sbp_sleep(1);
-		}
-		while ((i<0)&&(j));
-	}
-	return (i);
-}
-
-static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-  return lock ? LockDoor() : UnLockDoor();
-}
-
-/*==========================================================================*/
-static int cc_CloseTray(void)
-{
-	int i;
-	
-	if (fam0_drive) return (0);
-	msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S);
-	msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed);
-	
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_TRAY_CTL;
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_TRAY_CTL;
-		drvcmd[1]=0x01;
-		drvcmd[4]=0x03; /* "insert" */
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famLV_drive)
-	{
-		drvcmd[0]=CMDL_TRAY_CTL;
-		if (famLV_drive)
-		  flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
-			f_ResponseStatus|f_obey_p_check|f_bit1;
-		else
-		  flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_TRAY_CTL;
-		drvcmd[4]=0x03; /* "insert" */
-	}
-	i=cmd_out();
-	msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed);
-
-	i=cc_ReadError();
-	flags_cmd_out |= f_respo2;
-	cc_ReadStatus(); /* command: give 1-byte status */
-	i=ResponseStatus();
-	if (famT_drive&&(i<0))
-	{
-		cc_DriveReset();
-		i=ResponseStatus();
-#if 0
-                sbp_sleep(HZ);
-#endif /* 0 */ 
-		i=ResponseStatus();
-	}
-	if (i<0)
-	{
-		msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i);
-	}
-	if (!(famT_drive))
-	{
-		if (!st_spinning)
-		{
-			cc_SpinUp();
-			if (st_check) i=cc_ReadError();
-			flags_cmd_out |= f_respo2;
-			cc_ReadStatus();
-			i=ResponseStatus();
-		} else {
-		}
-	}
-	i=DiskInfo();
-	return (i);
-}
-
-static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
-{
-	int retval=0;
-	switch_drive(cdi->handle);
-	/* DUH! --AJK */
-	if(current_drive->CD_changed != 0xFF) {
-		current_drive->CD_changed=0xFF;
-		current_drive->diskstate_flags &= ~cd_size_bit;
-	}
-	if (position == 1) {
-		cc_SpinDown();
-	} else {
-		retval=cc_CloseTray();
-	}
-  return retval;
-}
-
-/*==========================================================================*/
-static int cc_ReadSubQ(void)
-{
-	int i,j;
-
-	current_drive->diskstate_flags &= ~subq_bit;
-	for (j=255;j>0;j--)
-	{
-		clr_cmdbuf();
-		if (fam1_drive)
-		{
-			drvcmd[0]=CMD1_READSUBQ;
-			flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-			response_count=11;
-		}
-		else if (fam2_drive)
-		{
-			drvcmd[0]=CMD2_READSUBQ;
-			drvcmd[1]=0x02;
-			drvcmd[3]=0x01;
-			flags_cmd_out=f_putcmd;
-			response_count=10;
-		}
-		else if (fam0LV_drive)
-		{
-			drvcmd[0]=CMD0_READSUBQ;
-			drvcmd[1]=0x02;
-			if (famLV_drive)
-				flags_cmd_out=f_putcmd;
-			else
-				flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-			response_count=13;
-		}
-		else if (famT_drive)
-		{
-			response_count=12;
-			drvcmd[0]=CMDT_READSUBQ;
-			drvcmd[1]=0x02;
-			drvcmd[2]=0x40;
-			drvcmd[3]=0x01;
-			drvcmd[8]=response_count;
-		}
-		i=cmd_out();
-		if (i<0) return (i);
-		for (i=0;i<response_count;i++)
-		{
-			sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-			msgbuf[i*3]=0;
-			msg(DBG_SQ1,"cc_ReadSubQ:%s\n", msgbuf);
-		}
-		if (famT_drive) break;
-		if (infobuf[0]!=0) break;
-		if ((!st_spinning) || (j==1))
-		{
-			current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0;
-			current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0;
-			return (0);
-		}
-	}
-	if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1];
-	else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]);
-	current_drive->SubQ_trk=byt2bcd(infobuf[2]);
-	current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]);
-	if (fam0LV_drive) i=5;
-	else if (fam12_drive) i=4;
-	else if (famT_drive) i=8;
-	current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
-	i=7;
-	if (fam0LV_drive) i=9;
-	else if (fam12_drive) i=7;
-	else if (famT_drive) i=4;
-	current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
-	current_drive->SubQ_whatisthis=infobuf[i+3];
-	current_drive->diskstate_flags |= subq_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ModeSense(void)
-{
-	int i;
-	
-	if (fam2_drive) return (0);
-	if (famV_drive) return (0);
-	current_drive->diskstate_flags &= ~frame_size_bit;
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		response_count=5;
-		drvcmd[0]=CMD1_GETMODE;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam0L_drive)
-	{
-		response_count=2;
-		drvcmd[0]=CMD0_GETMODE;
-		if (famL_drive) flags_cmd_out=f_putcmd;
-		else flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		response_count=10;
-		drvcmd[0]=CMDT_GETMODE;
-		drvcmd[4]=response_count;
-	}
-	i=cmd_out();
-	if (i<0) return (i);
-	i=0;
-	current_drive->sense_byte=0;
-	if (fam1_drive) current_drive->sense_byte=infobuf[i++];
-	else if (famT_drive)
-	{
-		if (infobuf[4]==0x01) current_drive->xa_byte=0x20;
-		else current_drive->xa_byte=0;
-		i=2;
-	}
-	current_drive->frame_size=make16(infobuf[i],infobuf[i+1]);
-	for (i=0;i<response_count;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf);
-	
-	current_drive->diskstate_flags |= frame_size_bit;
-	return (0);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int cc_ModeSelect(int framesize)
-{
-	int i;
-	
-	if (fam2_drive) return (0);
-	if (famV_drive) return (0);
-	current_drive->diskstate_flags &= ~frame_size_bit;
-	clr_cmdbuf();
-	current_drive->frame_size=framesize;
-	if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82;
-	else current_drive->sense_byte=0x00;
-	
-	msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n",
-	    current_drive->sense_byte, current_drive->frame_size);
-	
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_SETMODE;
-		drvcmd[1]=0x00;
-		drvcmd[2]=current_drive->sense_byte;
-		drvcmd[3]=(current_drive->frame_size>>8)&0xFF;
-		drvcmd[4]=current_drive->frame_size&0xFF;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam0L_drive)
-	{
-		drvcmd[0]=CMD0_SETMODE;
-		drvcmd[1]=0x00;
-		drvcmd[2]=(current_drive->frame_size>>8)&0xFF;
-		drvcmd[3]=current_drive->frame_size&0xFF;
-		drvcmd[4]=0x00;
-		if(famL_drive)
-			flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check;
-		else
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		return (-1);
-	}
-	response_count=0;
-	i=cmd_out();
-	if (i<0) return (i);
-	current_drive->diskstate_flags |= frame_size_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int cc_GetVolume(void)
-{
-	int i;
-	u_char switches;
-	u_char chan0=0;
-	u_char vol0=0;
-	u_char chan1=1;
-	u_char vol1=0;
-	
-	if (famV_drive) return (0);
-	current_drive->diskstate_flags &= ~volume_bit;
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_GETMODE;
-		drvcmd[1]=0x05;
-		response_count=5;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_GETMODE;
-		drvcmd[1]=0x0E;
-		response_count=5;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (fam0L_drive)
-	{
-		drvcmd[0]=CMD0_GETMODE;
-		drvcmd[1]=0x03;
-		response_count=2;
-		if(famL_drive)
-			flags_cmd_out=f_putcmd;
-		else
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		i=cc_get_mode_T();
-		if (i<0) return (i);
-	}
-	if (!famT_drive)
-	{
-		i=cmd_out();
-		if (i<0) return (i);
-	}
-	if (fam1_drive)
-	{
-		chan0=infobuf[1]&0x0F;
-		vol0=infobuf[2];
-		chan1=infobuf[3]&0x0F;
-		vol1=infobuf[4];
-		if (chan0==0)
-		{
-			chan0=1;
-			vol0=0;
-		}
-		if (chan1==0)
-		{
-			chan1=2;
-			vol1=0;
-		}
-		chan0 >>= 1;
-		chan1 >>= 1;
-	}
-	else if (fam2_drive)
-	{
-		chan0=infobuf[1];
-		vol0=infobuf[2];
-		chan1=infobuf[3];
-		vol1=infobuf[4];
-	}
-	else if (famL_drive)
-	{
-		chan0=0;
-		chan1=1;
-		vol0=vol1=infobuf[1];
-		switches=infobuf[0];
-		if ((switches&0x80)!=0) chan0=1;
-		if ((switches&0x40)!=0) chan1=0;
-	}
-	else if (fam0_drive) /* different firmware levels */
-	{
-		chan0=0;
-		chan1=1;
-		vol0=vol1=infobuf[1];
-		if (current_drive->drv_type>=drv_201)
-		{
-			if (current_drive->drv_type<drv_300)
-			{
-				switches=infobuf[0];
-				if ((switches&0x80)!=0) vol0=0;
-				if ((switches&0x40)!=0) vol1=0;
-				if (current_drive->drv_type>=drv_211)
-				{
-					if ((switches&0x20)!=0) chan0=1;
-					if ((switches&0x10)!=0) chan1=0;
-				}
-			}
-			else
-			{
-				vol0=infobuf[0];
-				if ((vol0&0x01)!=0) chan0=1;
-				if ((vol1&0x01)==0) chan1=0;
-				vol0 &= 0xFC;
-				vol1 &= 0xFC;
-				if (vol0!=0) vol0 += 3;
-				if (vol1!=0) vol1 += 3;
-			}
-		}
-	}
-	else if (famT_drive)
-	{
-		current_drive->volume_control=infobuf[7];
-		chan0=0;
-		chan1=1;
-		if (current_drive->volume_control&0x10) vol0=0;
-		else vol0=0xff;
-		if (current_drive->volume_control&0x20) vol1=0;
-		else vol1=0xff;
-	}
-	current_drive->vol_chan0=chan0;
-	current_drive->vol_ctrl0=vol0;
-	current_drive->vol_chan1=chan1;
-	current_drive->vol_ctrl1=vol1;
-#if 000
-	current_drive->vol_chan2=2;
-	current_drive->vol_ctrl2=0xFF;
-	current_drive->vol_chan3=3;
-	current_drive->vol_ctrl3=0xFF;
-#endif /*  000 */
-	current_drive->diskstate_flags |= volume_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadCapacity(void)
-{
-	int i, j;
-	
-	if (fam2_drive) return (0); /* some firmware lacks this command */
-	if (famLV_drive) return (0); /* some firmware lacks this command */
-	if (famT_drive) return (0); /* done with cc_ReadTocDescr() */
-	current_drive->diskstate_flags &= ~cd_size_bit;
-	for (j=3;j>0;j--)
-	{
-		clr_cmdbuf();
-		if (fam1_drive)
-		{
-			drvcmd[0]=CMD1_CAPACITY;
-			response_count=5;
-			flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-		}
-#if 00
-		else if (fam2_drive)
-		{
-			drvcmd[0]=CMD2_CAPACITY;
-			response_count=8;
-			flags_cmd_out=f_putcmd;
-		}
-#endif
-		else if (fam0_drive)
-		{
-			drvcmd[0]=CMD0_CAPACITY;
-			response_count=5;
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-		}
-		i=cmd_out();
-		if (i>=0) break;
-		msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i);
-		cc_ReadError();
-	}
-	if (j==0) return (i);
-	if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET;
-	else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
-#if 00
-	else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
-#endif
-	current_drive->diskstate_flags |= cd_size_bit;
-	msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm);
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocDescr(void)
-{
-	int i;
-	
-	current_drive->diskstate_flags &= ~toc_bit;
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_DISKINFO;
-		response_count=6;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_DISKINFO;
-		response_count=6;
-		if(famLV_drive)
-			flags_cmd_out=f_putcmd;
-		else
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		/* possibly longer timeout periods necessary */
-		current_drive->f_multisession=0;
-		drvcmd[0]=CMD2_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[2]=0xAB;
-		drvcmd[3]=0xFF; /* session */
-		response_count=8;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		current_drive->f_multisession=0;
-		response_count=12;
-		drvcmd[0]=CMDT_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[6]=CDROM_LEADOUT;
-		drvcmd[8]=response_count;
-		drvcmd[9]=0x00;
-	}
-	i=cmd_out();
-	if (i<0) return (i);
-	if ((famT_drive)&&(i<response_count)) return (-100-i);
-	if ((fam1_drive)||(fam2_drive)||(fam0LV_drive))
-		current_drive->xa_byte=infobuf[0];
-	if (fam2_drive)
-	{
-		current_drive->first_session=infobuf[1];
-		current_drive->last_session=infobuf[2];
-		current_drive->n_first_track=infobuf[3];
-		current_drive->n_last_track=infobuf[4];
-		if (current_drive->first_session!=current_drive->last_session)
-		{
-			current_drive->f_multisession=1;
-			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
-		}
-#if 0
-		if (current_drive->first_session!=current_drive->last_session)
-		{
-			if (current_drive->last_session<=20)
-				zwanzig=current_drive->last_session+1;
-			else zwanzig=20;
-			for (count=current_drive->first_session;count<zwanzig;count++)
-			{
-				drvcmd[0]=CMD2_DISKINFO;
-				drvcmd[1]=0x02;
-				drvcmd[2]=0xAB;
-				drvcmd[3]=count;
-				response_count=8;
-				flags_cmd_out=f_putcmd;
-				i=cmd_out();
-				if (i<0) return (i);
-				current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
-			}
-			current_drive->diskstate_flags |= multisession_bit;
-		}
-#endif
-		drvcmd[0]=CMD2_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[2]=0xAA;
-		drvcmd[3]=0xFF;
-		response_count=5;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		if (i<0) return (i);
-		current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
-		current_drive->size_blk=msf2blk(current_drive->size_msf);
-		current_drive->CDsize_frm=current_drive->size_blk+1;
-	}
-	else if (famT_drive)
-	{
-		current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11]));
-		current_drive->size_blk=msf2blk(current_drive->size_msf);
-		current_drive->CDsize_frm=current_drive->size_blk+1;
-		current_drive->n_first_track=infobuf[2];
-		current_drive->n_last_track=infobuf[3];
-	}
-	else
-	{
-		current_drive->n_first_track=infobuf[1];
-		current_drive->n_last_track=infobuf[2];
-		current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
-		current_drive->size_blk=msf2blk(current_drive->size_msf);
-		if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1;
-	}
-	current_drive->diskstate_flags |= toc_bit;
-	msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n",
-	    current_drive->xa_byte,
-	    current_drive->n_first_track,
-	    current_drive->n_last_track,
-	    current_drive->size_msf,
-	    current_drive->first_session,
-	    current_drive->last_session);
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocEntry(int num)
-{
-	int i;
-	
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_READTOC;
-		drvcmd[2]=num;
-		response_count=8;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		/* possibly longer timeout periods necessary */
-		drvcmd[0]=CMD2_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[2]=num;
-		response_count=5;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_READTOC;
-		drvcmd[1]=0x02;
-		drvcmd[2]=num;
-		response_count=8;
-		if (famLV_drive)
-			flags_cmd_out=f_putcmd;
-		else
-		  flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		response_count=12;
-		drvcmd[0]=CMDT_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[6]=num;
-		drvcmd[8]=response_count;
-		drvcmd[9]=0x00;
-	}
-	i=cmd_out();
-	if (i<0) return (i);
-	if ((famT_drive)&&(i<response_count)) return (-100-i);
-	if ((fam1_drive)||(fam0LV_drive))
-	{
-		current_drive->TocEnt_nixbyte=infobuf[0];
-		i=1;
-	}
-	else if (fam2_drive) i=0;
-	else if (famT_drive) i=5;
-	current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
-	if ((fam1_drive)||(fam0L_drive))
-	{
-		current_drive->TocEnt_number=infobuf[i++];
-		current_drive->TocEnt_format=infobuf[i];
-	}
-	else
-	  {
-	    current_drive->TocEnt_number=num;
-	    current_drive->TocEnt_format=0;
-	  }
-	if (fam1_drive) i=4;
-	else if (fam0LV_drive) i=5;
-	else if (fam2_drive) i=2;
-	else if (famT_drive) i=9;
-	current_drive->TocEnt_address=make32(make16(0,infobuf[i]),
-				     make16(infobuf[i+1],infobuf[i+2]));
-	for (i=0;i<response_count;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_ECS,"TocEntry:%s\n", msgbuf);
-	msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n",
-	    current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr,
-	    current_drive->TocEnt_number, current_drive->TocEnt_format,
-	    current_drive->TocEnt_address);
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadPacket(void)
-{
-	int i;
-	
-	clr_cmdbuf();
-	drvcmd[0]=CMD0_PACKET;
-	drvcmd[1]=response_count;
-	if(famL_drive) flags_cmd_out=f_putcmd;
-	else if (fam01_drive)
-		flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	else if (fam2_drive) return (-1); /* not implemented yet */
-	else if (famT_drive)
-	{
-		return (-1);
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int convert_UPC(u_char *p)
-{
-	int i;
-	
-	p++;
-	if (fam0L_drive) p[13]=0;
-	for (i=0;i<7;i++)
-	{
-		if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++);
-		else if (fam0L_drive)
-		{
-			current_drive->UPC_buf[i]=((*p++)<<4)&0xFF;
-			current_drive->UPC_buf[i] |= *p++;
-		}
-		else if (famT_drive)
-		{
-			return (-1);
-		}
-		else /* CD200 */
-		{
-			return (-1);
-		}
-	}
-	current_drive->UPC_buf[6] &= 0xF0;
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadUPC(void)
-{
-	int i;
-#if TEST_UPC
-	int block, checksum;
-#endif /* TEST_UPC */ 
-	
-	if (fam2_drive) return (0); /* not implemented yet */
-	if (famT_drive)	return (0); /* not implemented yet */
-	if (famV_drive)	return (0); /* not implemented yet */
-#if 1
-	if (fam0_drive) return (0); /* but it should work */
-#endif
-	
-	current_drive->diskstate_flags &= ~upc_bit;
-#if TEST_UPC
-	for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++)
-	{
-#endif /* TEST_UPC */ 
-		clr_cmdbuf();
-		if (fam1_drive)
-		{
-			drvcmd[0]=CMD1_READ_UPC;
-#if TEST_UPC
-			drvcmd[1]=(block>>16)&0xFF;
-			drvcmd[2]=(block>>8)&0xFF;
-			drvcmd[3]=block&0xFF;
-#endif /* TEST_UPC */ 
-			response_count=8;
-			flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-		}
-		else if (fam0L_drive)
-		{
-			drvcmd[0]=CMD0_READ_UPC;
-#if TEST_UPC
-			drvcmd[2]=(block>>16)&0xFF;
-			drvcmd[3]=(block>>8)&0xFF;
-			drvcmd[4]=block&0xFF;
-#endif /* TEST_UPC */ 
-			response_count=0;
-			flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-		}
-		else if (fam2_drive)
-		{
-			return (-1);
-		}
-		else if (famT_drive)
-		{
-			return (-1);
-		}
-		i=cmd_out();
-		if (i<0)
-		{
-			msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
-			return (i);
-		}
-		if (fam0L_drive)
-		{
-			response_count=16;
-			if (famL_drive) flags_cmd_out=f_putcmd;
-			i=cc_ReadPacket();
-			if (i<0)
-			{
-				msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
-				return (i);
-			}
-		}
-#if TEST_UPC
-		checksum=0;
-#endif /* TEST_UPC */ 
-		for (i=0;i<(fam1_drive?8:16);i++)
-		{
-#if TEST_UPC
-			checksum |= infobuf[i];
-#endif /* TEST_UPC */ 
-			sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-		}
-		msgbuf[i*3]=0;
-		msg(DBG_UPC,"UPC info:%s\n", msgbuf);
-#if TEST_UPC
-		if ((checksum&0x7F)!=0) break;
-	}
-#endif /* TEST_UPC */ 
-	current_drive->UPC_ctl_adr=0;
-	if (fam1_drive) i=0;
-	else i=2;
-	if ((infobuf[i]&0x80)!=0)
-	{
-		convert_UPC(&infobuf[i]);
-		current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02;
-	}
-	for (i=0;i<7;i++)
-		sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]);
-	sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr);
-	msgbuf[i*3+5]=0;
-	msg(DBG_UPC,"UPC code:%s\n", msgbuf);
-	current_drive->diskstate_flags |= upc_bit;
-	return (0);
-}
-
-static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-	int i;
-	unsigned char *mcnp = mcn->medium_catalog_number;
-	unsigned char *resp;
-
-	current_drive->diskstate_flags &= ~upc_bit;
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_READ_UPC;
-		response_count=8;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam0L_drive)
-	{
-		drvcmd[0]=CMD0_READ_UPC;
-		response_count=0;
-		flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-	}
-	else if (fam2_drive)
-	{
-		return (-1);
-	}
-	else if (famT_drive)
-	{
-		return (-1);
-	}
-	i=cmd_out();
-	if (i<0)
-	{
-		msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
-		return (i);
-	}
-	if (fam0L_drive)
-	{
-		response_count=16;
-		if (famL_drive) flags_cmd_out=f_putcmd;
-		i=cc_ReadPacket();
-		if (i<0)
-		{
-			msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
-			return (i);
-		}
-	}
-	current_drive->UPC_ctl_adr=0;
-	if (fam1_drive) i=0;
-	else i=2;
-
-	resp = infobuf + i;
-	if (*resp++ == 0x80) {
-		/* packed bcd to single ASCII digits */
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-	}
-	*mcnp = '\0';
-
-	current_drive->diskstate_flags |= upc_bit;
-	return (0);
-}
-
-/*==========================================================================*/
-static int cc_CheckMultiSession(void)
-{
-	int i;
-	
-	if (fam2_drive) return (0);
-	current_drive->f_multisession=0;
-	current_drive->lba_multi=0;
-	if (fam0_drive) return (0);
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_MULTISESS;
-		response_count=6;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-		i=cmd_out();
-		if (i<0) return (i);
-		if ((infobuf[0]&0x80)!=0)
-		{
-			current_drive->f_multisession=1;
-			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]),
-							make16(infobuf[2],infobuf[3])));
-		}
-	}
-	else if (famLV_drive)
-	{
-		drvcmd[0]=CMDL_MULTISESS;
-		drvcmd[1]=3;
-		drvcmd[2]=1;
-		response_count=8;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		if (i<0) return (i);
-		current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),
-						make16(infobuf[6],infobuf[7])));
-	}
-	else if (famT_drive)
-	{
-		response_count=12;
-		drvcmd[0]=CMDT_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[6]=0;
-		drvcmd[8]=response_count;
-		drvcmd[9]=0x40;
-		i=cmd_out();
-		if (i<0) return (i);
-		if (i<response_count) return (-100-i);
-		current_drive->first_session=infobuf[2];
-		current_drive->last_session=infobuf[3];
-		current_drive->track_of_last_session=infobuf[6];
-		if (current_drive->first_session!=current_drive->last_session)
-		{
-			current_drive->f_multisession=1;
-			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
-		}
-	}
-	for (i=0;i<response_count;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi);
-	if (current_drive->lba_multi>200)
-	{
-		current_drive->f_multisession=1;
-		msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi);
-	}
-	return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-static int cc_SubChanInfo(int frame, int count, u_char *buffer)
-	/* "frame" is a RED BOOK (msf-bin) address */
-{
-	int i;
-	
-	if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */
-	if (famT_drive)
-	{
-		return (-1);
-	}
-#if 0
-	if (current_drive->audio_state!=audio_playing) return (-ENODATA);
-#endif
-	clr_cmdbuf();
-	drvcmd[0]=CMD1_SUBCHANINF;
-	drvcmd[1]=(frame>>16)&0xFF;
-	drvcmd[2]=(frame>>8)&0xFF;
-	drvcmd[3]=frame&0xFF;
-	drvcmd[5]=(count>>8)&0xFF;
-	drvcmd[6]=count&0xFF;
-	flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	cmd_type=READ_SC;
-	current_drive->frame_size=CD_FRAMESIZE_SUB;
-	i=cmd_out(); /* which buffer to use? */
-	return (i);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-static void __init check_datarate(void)
-{
-	int i=0;
-	
-	msg(DBG_IOX,"check_datarate entered.\n");
-	datarate=0;
-#if TEST_STI
-	for (i=0;i<=1000;i++) printk(".");
-#endif
-	/* set a timer to make (timed_out_delay!=0) after 1.1 seconds */
-#if 1
-	del_timer(&delay_timer);
-#endif
-	delay_timer.expires=jiffies+11*HZ/10;
-	timed_out_delay=0;
-	add_timer(&delay_timer);
-#if 0
-	msg(DBG_TIM,"delay timer started (11*HZ/10).\n");
-#endif
-	do
-	{
-		i=inb(CDi_status);
-		datarate++;
-#if 1
-		if (datarate>0x6FFFFFFF) break;
-#endif 
-	}
-	while (!timed_out_delay);
-	del_timer(&delay_timer);
-#if 0
-	msg(DBG_TIM,"datarate: %04X\n", datarate);
-#endif
-	if (datarate<65536) datarate=65536;
-	maxtim16=datarate*16;
-	maxtim04=datarate*4;
-	maxtim02=datarate*2;
-	maxtim_8=datarate/32;
-#if LONG_TIMING
-	maxtim_data=datarate/100;
-#else
-	maxtim_data=datarate/300;
-#endif /* LONG_TIMING */ 
-#if 0
-	msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data);
-#endif
-}
-/*==========================================================================*/
-#if 0
-static int c2_ReadError(int fam)
-{
-	int i;
-	
-	clr_cmdbuf();
-	response_count=9;
-	clr_respo_buf(9);
-	if (fam==1)
-	{
-		drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
-		i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus);
-	}
-	else if (fam==2)
-	{
-		drvcmd[0]=CMD2_READ_ERR;
-		i=do_cmd(f_putcmd);
-	}
-	else return (-1);
-	return (i);
-}
-#endif
-/*==========================================================================*/
-static void __init ask_mail(void)
-{
-	int i;
-	
-	msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de\n");
-	msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n");
-	msg(DBG_INF, "%s\n", VERSION);
-	msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n",
-	    CDo_command, type, current_drive->drive_model, current_drive->drv_id);
-	for (i=0;i<12;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_INF,"infobuf =%s\n", msgbuf);
-	for (i=0;i<12;i++)
-		sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_INF,"infobuf =%s\n", msgbuf);
-}
-/*==========================================================================*/
-static int __init check_version(void)
-{
-	int i, j, l;
-	int teac_possible=0;
-	
-	msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S);
-	current_drive->drv_type=0;
-
-	/* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */
-	/* clear any pending error state */
-	clr_cmdbuf();
-	drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
-	response_count=9;
-	flags_cmd_out=f_putcmd;
-	i=cmd_out();
-	if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).\n",i);
-	/* read drive version */
-	clr_cmdbuf();
-	for (i=0;i<12;i++) infobuf[i]=0;
-	drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */
-	response_count=12; /* fam1: only 11 */
-	flags_cmd_out=f_putcmd;
-	i=cmd_out();
-	if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i);
-	if (i==-11) teac_possible++;
-	j=0;
-	for (i=0;i<12;i++) j+=infobuf[i];
-	if (j)
-	{
-		for (i=0;i<12;i++)
-			sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_ECS,"infobuf =%s\n", msgbuf);
-		for (i=0;i<12;i++)
-			sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_ECS,"infobuf =%s\n", msgbuf);
-	}
-	for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break;
-	if (i==4)
-	{
-		current_drive->drive_model[0]='C';
-		current_drive->drive_model[1]='R';
-		current_drive->drive_model[2]='-';
-		current_drive->drive_model[3]='5';
-		current_drive->drive_model[4]=infobuf[i++];
-		current_drive->drive_model[5]=infobuf[i++];
-		current_drive->drive_model[6]=0;
-		current_drive->drv_type=drv_fam1;
-	}
-	if (!current_drive->drv_type)
-	{
-		for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break;
-		if (i==8)
-		{
-			current_drive->drive_model[0]='C';
-			current_drive->drive_model[1]='R';
-			current_drive->drive_model[2]='-';
-			current_drive->drive_model[3]='5';
-			current_drive->drive_model[4]='2';
-			current_drive->drive_model[5]='x';
-			current_drive->drive_model[6]=0;
-			current_drive->drv_type=drv_fam0;
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break;
-		if (i==8)
-		{
-			for (j=0;j<8;j++)
-				current_drive->drive_model[j]=infobuf[j];
-			current_drive->drive_model[8]=0;
-			current_drive->drv_type=drv_famL;
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break;
-		if (i==6)
-		{
-			for (j=0;j<6;j++)
-				current_drive->drive_model[j]=infobuf[j];
-			current_drive->drive_model[6]=0;
-			current_drive->drv_type=drv_famV;
-			i+=2; /* 2 blanks before version */
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		/* check for CD200 */
-		clr_cmdbuf();
-		drvcmd[0]=CMD2_READ_ERR;
-		response_count=9;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i);
-		if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i);
-		/* read drive version */
-		clr_cmdbuf();
-		for (i=0;i<12;i++) infobuf[i]=0;
-		if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-#if 0
-		OUT(CDo_reset,0);
-		sbp_sleep(6*HZ);
-		OUT(CDo_enable,current_drive->drv_sel);
-#endif
-		drvcmd[0]=CMD2_READ_VER;
-		response_count=12;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i);
-		if (i==-7) teac_possible++;
-		j=0;
-		for (i=0;i<12;i++) j+=infobuf[i];
-		if (j)
-		{
-			for (i=0;i<12;i++)
-				sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-			msgbuf[i*3]=0;
-			msg(DBG_IDX,"infobuf =%s\n", msgbuf);
-			for (i=0;i<12;i++)
-				sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-			msgbuf[i*3]=0;
-			msg(DBG_IDX,"infobuf =%s\n", msgbuf);
-		}
-		if (i>=0)
-		{
-			for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break;
-			if (i==5)
-			{
-				current_drive->drive_model[0]='C';
-				current_drive->drive_model[1]='D';
-				current_drive->drive_model[2]='2';
-				current_drive->drive_model[3]='0';
-				current_drive->drive_model[4]='0';
-				current_drive->drive_model[5]=infobuf[i++];
-				current_drive->drive_model[6]=infobuf[i++];
-				current_drive->drive_model[7]=0;
-				current_drive->drv_type=drv_fam2;
-			}
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		/* check for TEAC CD-55A */
-		msg(DBG_TEA,"teac_possible: %d\n",teac_possible);
-		for (j=1;j<=((current_drive->drv_id==0)?3:1);j++)
-		{
-			for (l=1;l<=((current_drive->drv_id==0)?10:1);l++)
-			{
-				msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l);
-				if (sbpro_type==1) OUT(CDo_reset,0);
-				else
-				{
-					OUT(CDo_enable,current_drive->drv_sel);
-					OUT(CDo_sel_i_d,0);
-					OUT(CDo_command,CMDT_RESET);
-					for (i=0;i<9;i++) OUT(CDo_command,0);
-				}
-				sbp_sleep(5*HZ/10);
-				OUT(CDo_enable,current_drive->drv_sel);
-				OUT(CDo_sel_i_d,0);
-				i=inb(CDi_status);
-				msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i);
-#if 0
-				if (i&s_not_result_ready) continue; /* drive not present or ready */
-#endif
-				i=inb(CDi_info);
-				msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i);
-				if (i==0x55) break; /* drive found */
-			}
-			if (i==0x55) break; /* drive found */
-		}
-		if (i==0x55) /* drive found */
-		{
-			msg(DBG_TEA,"TEAC drive found.\n");
-			clr_cmdbuf();
-			flags_cmd_out=f_putcmd;
-			response_count=12;
-			drvcmd[0]=CMDT_READ_VER;
-			drvcmd[4]=response_count;
-			for (i=0;i<12;i++) infobuf[i]=0;
-			i=cmd_out_T();
-			if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i);
-			for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break;
-			if (i==6)
-			{
-				current_drive->drive_model[0]='C';
-				current_drive->drive_model[1]='D';
-				current_drive->drive_model[2]='-';
-				current_drive->drive_model[3]='5';
-				current_drive->drive_model[4]='5';
-				current_drive->drive_model[5]=0;
-				current_drive->drv_type=drv_famT;
-			}
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id);
-		return (-522);
-	}
-	for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j];
-	if (famL_drive)
-	{
-	  u_char lcs_firm_e1[]="A E1";
-	  u_char lcs_firm_f4[]="A4F4";
-		
-	  for (j=0;j<4;j++)
-	    if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break;
-	  if (j==4) current_drive->drv_type=drv_e1;
-	  
-	  for (j=0;j<4;j++)
-	    if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break;
-	  if (j==4) current_drive->drv_type=drv_f4;
-
-	  if (current_drive->drv_type==drv_famL) ask_mail();
-	}
-	else if (famT_drive)
-	{
-		j=infobuf[4]; /* one-byte version??? - here: 0x15 */
-		if (j=='5')
-		{
-			current_drive->firmware_version[0]=infobuf[7];
-			current_drive->firmware_version[1]=infobuf[8];
-			current_drive->firmware_version[2]=infobuf[10];
-			current_drive->firmware_version[3]=infobuf[11];
-		}
-		else
-		{
-			if (j!=0x15) ask_mail();
-			current_drive->firmware_version[0]='0';
-			current_drive->firmware_version[1]='.';
-			current_drive->firmware_version[2]='0'+(j>>4);
-			current_drive->firmware_version[3]='0'+(j&0x0f);
-		}
-	}
-	else /* CR-52x, CR-56x, CD200, ECS-AT */
-	{
-		j = (current_drive->firmware_version[0] & 0x0F) * 100 +
-			(current_drive->firmware_version[2] & 0x0F) *10 +
-				(current_drive->firmware_version[3] & 0x0F);
-		if (fam0_drive)
-		{
-			if (j<200) current_drive->drv_type=drv_199;
-			else if (j<201) current_drive->drv_type=drv_200;
-			else if (j<210) current_drive->drv_type=drv_201;
-			else if (j<211) current_drive->drv_type=drv_210;
-			else if (j<300) current_drive->drv_type=drv_211;
-			else if (j>=300) current_drive->drv_type=drv_300;
-		}
-		else if (fam1_drive)
-		{
-			if (j<100) current_drive->drv_type=drv_099;
-			else
-			{
-				current_drive->drv_type=drv_100;
-				if ((j!=500)&&(j!=102)) ask_mail();
-			}
-		}
-		else if (fam2_drive)
-		{
-			if (current_drive->drive_model[5]=='F')
-			{
-				if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210))
-				  ask_mail(); /* unknown version at time */
-			}
-			else
-			{
-				msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.\n");
-				if ((j!=101)&&(j!=35))
-				  ask_mail(); /* unknown version at time */
-			}
-		}
-		else if (famV_drive)
-		  {
-		    if ((j==100)||(j==150)) current_drive->drv_type=drv_at;
-		    ask_mail(); /* hopefully we get some feedback by this */
-		  }
-	}
-	msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type);
-	msg(DBG_INI,"check_version done.\n");
-	return (0);
-}
-/*==========================================================================*/
-static void switch_drive(struct sbpcd_drive *p)
-{
-	current_drive = p;
-	OUT(CDo_enable,current_drive->drv_sel);
-	msg(DBG_DID,"drive %d (ID=%d) activated.\n",
-		current_drive - D_S, current_drive->drv_id);
-	return;
-}
-/*==========================================================================*/
-#ifdef PATH_CHECK
-/*
- * probe for the presence of an interface card
- */
-static int __init check_card(int port)
-{
-#undef N_RESPO
-#define N_RESPO 20
-	int i, j, k;
-	u_char response[N_RESPO];
-	u_char save_port0;
-	u_char save_port3;
-	
-	msg(DBG_INI,"check_card entered.\n");
-	save_port0=inb(port+0);
-	save_port3=inb(port+3);
-	
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		OUT(port+3,j) ; /* enable drive #j */
-		OUT(port+0,CMD0_PATH_CHECK);
-		for (i=10;i>0;i--) OUT(port+0,0);
-		for (k=0;k<N_RESPO;k++) response[k]=0;
-		for (k=0;k<N_RESPO;k++)
-		{
-			for (i=10000;i>0;i--)
-			{
-				if (inb(port+1)&s_not_result_ready) continue;
-				response[k]=inb(port+0);
-				break;
-			}
-		}
-		for (i=0;i<N_RESPO;i++)
-			sprintf(&msgbuf[i*3], " %02X", response[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-		OUT(port+0,CMD0_PATH_CHECK);
-		for (i=10;i>0;i--) OUT(port+0,0);
-		for (k=0;k<N_RESPO;k++) response[k]=0xFF;
-		for (k=0;k<N_RESPO;k++)
-		{
-			for (i=10000;i>0;i--)
-			{
-				if (inb(port+1)&s_not_result_ready) continue;
-				response[k]=inb(port+0);
-				break;
-			}
-		}
-		for (i=0;i<N_RESPO;i++)
-			sprintf(&msgbuf[i*3], " %02X", response[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-
-		if (response[0]==0xAA)
-			if (response[1]==0x55)
-				return (0);
-	}
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		OUT(port+3,j) ; /* enable drive #j */
-		OUT(port+0,CMD2_READ_VER);
-		for (i=10;i>0;i--) OUT(port+0,0);
-		for (k=0;k<N_RESPO;k++) response[k]=0;
-		for (k=0;k<N_RESPO;k++)
-		{
-			for (i=1000000;i>0;i--)
-			{
-				if (inb(port+1)&s_not_result_ready) continue;
-				response[k]=inb(port+0);
-				break;
-			}
-		}
-		for (i=0;i<N_RESPO;i++)
-			sprintf(&msgbuf[i*3], " %02X", response[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
-		OUT(port+0,CMD2_READ_VER);
-		for (i=10;i>0;i--) OUT(port+0,0);
-		for (k=0;k<N_RESPO;k++) response[k]=0xFF;
-		for (k=0;k<N_RESPO;k++)
-		{
-			for (i=1000000;i>0;i--)
-			{
-				if (inb(port+1)&s_not_result_ready) continue;
-				response[k]=inb(port+0);
-				break;
-			}
-		}
-		for (i=0;i<N_RESPO;i++)
-			sprintf(&msgbuf[i*3], " %02X", response[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
-		if (response[0]==0xAA)
-			if (response[1]==0x55)
-				return (0);
-	}
-	OUT(port+0,save_port0);
-	OUT(port+3,save_port3);
-	return (0); /* in any case - no real "function" at time */
-}
-#endif /* PATH_CHECK */ 
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * probe for the presence of drives on the selected controller
- */
-static int __init check_drives(void)
-{
-	int i, j;
-	
-	msg(DBG_INI,"check_drives entered.\n");
-	ndrives=0;
-	for (j=0;j<max_drives;j++)
-	{
-		struct sbpcd_drive *p = D_S + ndrives;
-		p->drv_id=j;
-		if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1;
-		else p->drv_sel=j;
-		switch_drive(p);
-		msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
-		msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
-		i=check_version();
-		if (i<0) msg(DBG_INI,"check_version returns %d.\n",i);
-		else
-		{
-			current_drive->drv_options=drv_pattern[j];
-			if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150);
-			msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n",
-			    current_drive - D_S,
-			    current_drive->drv_id,
-			    current_drive->drive_model,
-			    current_drive->firmware_version,
-			    CDo_command,
-			    sbpro_type);
-			ndrives++;
-		}
-	}
-	for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1;
-	if (ndrives==0) return (-1);
-	return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- *  obtain if requested service disturbs current audio state
- */            
-static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc)
-{
-	switch (audio_state)                   /* audio status from controller  */
-	{
-	case aud_11: /* "audio play in progress" */
-	case audx11:
-		switch (func)                      /* DOS command code */
-		{
-		case cmd_07: /* input flush  */
-		case cmd_0d: /* open device  */
-		case cmd_0e: /* close device */
-		case cmd_0c: /* ioctl output */
-			return (1);
-		case cmd_03: /* ioctl input  */
-			switch (subfunc)
-				/* DOS ioctl input subfunction */
-			{
-			case cxi_00:
-			case cxi_06:
-			case cxi_09:
-				return (1);
-			default:
-				return (ERROR15);
-			}
-			return (1);
-		default:
-			return (ERROR15);
-		}
-		return (1);
-	case aud_12:                  /* "audio play paused"      */
-	case audx12:
-		return (1);
-	default:
-		return (2);
-	}
-}
-/*==========================================================================*/
-/* allowed is only
- * ioctl_o, flush_input, open_device, close_device, 
- * tell_address, tell_volume, tell_capabiliti,
- * tell_framesize, tell_CD_changed, tell_audio_posi
- */
-static int check_allowed1(u_char func1, u_char func2)
-{
-#if 000
-	if (func1==ioctl_o) return (0);
-	if (func1==read_long) return (-1);
-	if (func1==read_long_prefetch) return (-1);
-	if (func1==seek) return (-1);
-	if (func1==audio_play) return (-1);
-	if (func1==audio_pause) return (-1);
-	if (func1==audio_resume) return (-1);
-	if (func1!=ioctl_i) return (0);
-	if (func2==tell_SubQ_run_tot) return (-1);
-	if (func2==tell_cdsize) return (-1);
-	if (func2==tell_TocDescrip) return (-1);
-	if (func2==tell_TocEntry) return (-1);
-	if (func2==tell_subQ_info) return (-1);
-	if (fam1_drive) if (func2==tell_SubChanInfo) return (-1);
-	if (func2==tell_UPC) return (-1);
-#else
-	return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed2(u_char func1, u_char func2)
-{
-#if 000
-	if (func1==read_long) return (-1);
-	if (func1==read_long_prefetch) return (-1);
-	if (func1==seek) return (-1);
-	if (func1==audio_play) return (-1);
-  if (func1!=ioctl_o) return (0);
-	if (fam1_drive)
-	{
-		if (func2==EjectDisk) return (-1);
-		if (func2==CloseTray) return (-1);
-	}
-#else
-	return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed3(u_char func1, u_char func2)
-{
-#if 000
-	if (func1==ioctl_i)
-	{
-		if (func2==tell_address) return (0);
-		if (func2==tell_capabiliti) return (0);
-		if (func2==tell_CD_changed) return (0);
-		if (fam0L_drive) if (func2==tell_SubChanInfo) return (0);
-		return (-1);
-	}
-	if (func1==ioctl_o)
-	{
-		if (func2==DriveReset) return (0);
-		if (fam0L_drive)
-		{
-			if (func2==EjectDisk) return (0);
-			if (func2==LockDoor) return (0);
-	  if (func2==CloseTray) return (0);
-		}
-		return (-1);
-    }
-	if (func1==flush_input) return (-1);
-	if (func1==read_long) return (-1);
-	if (func1==read_long_prefetch) return (-1);
-	if (func1==seek) return (-1);
-	if (func1==audio_play) return (-1);
-	if (func1==audio_pause) return (-1);
-	if (func1==audio_resume) return (-1);
-#else
-	return (0);
-#endif
-}
-/*==========================================================================*/
-static int seek_pos_audio_end(void)
-{
-	int i;
-
-	i=msf2blk(current_drive->pos_audio_end)-1;
-	if (i<0) return (-1);
-	i=cc_Seek(i,0);
-	return (i);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-static int ReadToC(void)
-{
-	int i, j;
-	current_drive->diskstate_flags &= ~toc_bit;
-	current_drive->ored_ctl_adr=0;
-	/* special handling of CD-I HE */
-	if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) ||
-             current_drive->xa_byte == 0x10)
-        {
-		current_drive->TocBuffer[1].nixbyte=0;
-		current_drive->TocBuffer[1].ctl_adr=0x40;
-		current_drive->TocBuffer[1].number=1;
-		current_drive->TocBuffer[1].format=0;
-		current_drive->TocBuffer[1].address=blk2msf(0);
-		current_drive->ored_ctl_adr |= 0x40;
-		current_drive->n_first_track = 1;
-		current_drive->n_last_track = 1;
-		current_drive->xa_byte = 0x10;
-                j = 2;
-        } else
-	for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++)
-	{
-		i=cc_ReadTocEntry(j);
-		if (i<0)
-		{
-			msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i);
-			return (i);
-		}
-		current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte;
-		current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr;
-		current_drive->TocBuffer[j].number=current_drive->TocEnt_number;
-		current_drive->TocBuffer[j].format=current_drive->TocEnt_format;
-		current_drive->TocBuffer[j].address=current_drive->TocEnt_address;
-		current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr;
-	}
-	/* fake entry for LeadOut Track */
-	current_drive->TocBuffer[j].nixbyte=0;
-	current_drive->TocBuffer[j].ctl_adr=0;
-	current_drive->TocBuffer[j].number=CDROM_LEADOUT;
-	current_drive->TocBuffer[j].format=0;
-	current_drive->TocBuffer[j].address=current_drive->size_msf;
-	
-	current_drive->diskstate_flags |= toc_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int DiskInfo(void)
-{
-	int i, j;
-	
-	current_drive->mode=READ_M1;
-	
-#undef LOOP_COUNT
-#define LOOP_COUNT 10 /* needed for some "old" drives */
-	
-	msg(DBG_000,"DiskInfo entered.\n");
-	for (j=1;j<LOOP_COUNT;j++)
-	{
-#if 0
-		i=SetSpeed();
-		if (i<0)
-		{
-			msg(DBG_INF,"DiskInfo: SetSpeed returns %d\n", i);
-			continue;
-		}
-		i=cc_ModeSense();
-		if (i<0)
-		{
-			msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i);
-			continue;
-		}
-#endif
-		i=cc_ReadCapacity();
-		if (i>=0) break;
-		msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i);
-#if 0
-		i=cc_DriveReset();
-#endif
-		if (!fam0_drive && j == 2) break;
-	}
-	if (j==LOOP_COUNT) return (-33); /* give up */
-	
-	i=cc_ReadTocDescr();
-	if (i<0)
-	{
-		msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i);
-		return (i);
-	}
-	i=ReadToC();
-	if (i<0)
-	{
-		msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i);
-		return (i);
-	}
-	i=cc_CheckMultiSession();
-	if (i<0)
-	{
-		msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i);
-		return (i);
-	}
-	if (current_drive->f_multisession) current_drive->sbp_bufsiz=1;  /* possibly a weird PhotoCD */
-	else current_drive->sbp_bufsiz=buffers;
-	i=cc_ReadTocEntry(current_drive->n_first_track);
-	if (i<0)
-	{
-		msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i);
-		return (i);
-	}
-	i=cc_ReadUPC();
-	if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i);
-	if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10))
-	{
-		/* XA disk with old drive */
-		cc_ModeSelect(CD_FRAMESIZE_RAW1);
-		cc_ModeSense();
-	}
-	if (famT_drive)	cc_prep_mode_T();
-	msg(DBG_000,"DiskInfo done.\n");
-	return (0);
-}
-
-static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	int st;
-
-	if (CDSL_CURRENT != slot_nr) {
-		 /* we have no changer support */
-		 return -EINVAL;
-	}
-
-        cc_ReadStatus();
-	st=ResponseStatus();
-	if (st<0)
-	{
-		msg(DBG_INF,"sbpcd_drive_status: timeout.\n");
-		return (0);
-	}
-	msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
-	msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
-	msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
-	msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
-	msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
-	msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-
-#if 0
-  if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN;
-  if (p->status_bits & p_disk_ok) return CDS_DISC_OK;
-  if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
-
-  return CDS_NO_DISC;
-#else
-  if (p->status_bits & p_spinning) return CDS_DISC_OK;
-/*  return CDS_TRAY_OPEN; */
-  return CDS_NO_DISC;
-  
-#endif
-
-}
-
-
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- *  called always if driver gets entered
- *  returns 0 or ERROR2 or ERROR15
- */
-static int prepare(u_char func, u_char subfunc)
-{
-	int i;
-	
-	if (fam0L_drive)
-	{
-		i=inb(CDi_status);
-		if (i&s_attention) GetStatus();
-	}
-	else if (fam1_drive) GetStatus();
-	else if (fam2_drive) GetStatus();
-	else if (famT_drive) GetStatus();
-	if (current_drive->CD_changed==0xFF)
-	{
-		current_drive->diskstate_flags=0;
-		current_drive->audio_state=0;
-		if (!st_diskok)
-		{
-			i=check_allowed1(func,subfunc);
-			if (i<0) return (-2);
-		}
-		else 
-		{
-			i=check_allowed3(func,subfunc);
-			if (i<0)
-			{
-				current_drive->CD_changed=1;
-				return (-15);
-			}
-		}
-	}
-	else
-	{
-		if (!st_diskok)
-		{
-			current_drive->diskstate_flags=0;
-			current_drive->audio_state=0;
-			i=check_allowed1(func,subfunc);
-			if (i<0) return (-2);
-		}
-		else
-		{ 
-			if (st_busy)
-			{
-				if (current_drive->audio_state!=audio_pausing)
-				{
-					i=check_allowed2(func,subfunc);
-					if (i<0) return (-2);
-				}
-			}
-			else
-			{
-				if (current_drive->audio_state==audio_playing) seek_pos_audio_end();
-				current_drive->audio_state=0;
-			}
-			if (!frame_size_valid)
-			{
-				i=DiskInfo();
-				if (i<0)
-				{
-					current_drive->diskstate_flags=0;
-					current_drive->audio_state=0;
-					i=check_allowed1(func,subfunc);
-					if (i<0) return (-2);
-				}
-			}
-		}
-    }
-	return (0);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * Check the results of the "get status" command.
- */
-static int sbp_status(void)
-{
-	int st;
-	
-	st=ResponseStatus();
-	if (st<0)
-	{
-		msg(DBG_INF,"sbp_status: timeout.\n");
-		return (0);
-	}
-	
-	if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n");
-	
-	if (st_check) 
-	{
-		msg(DBG_INF,"st_check detected - retrying.\n");
-		return (0);
-	}
-	if (!st_door_closed)
-	{
-		msg(DBG_INF,"door is open - retrying.\n");
-		return (0);
-	}
-	if (!st_caddy_in)
-	{
-		msg(DBG_INF,"disk removed - retrying.\n");
-		return (0);
-	}
-	if (!st_diskok) 
-	{
-		msg(DBG_INF,"!st_diskok detected - retrying.\n");
-		return (0);
-	}
-	if (st_busy) 
-	{
-		msg(DBG_INF,"st_busy detected - retrying.\n");
-		return (0);
-	}
-	return (1);
-}
-/*==========================================================================*/
-		
-static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	ms_infp->addr_format = CDROM_LBA;
-	ms_infp->addr.lba    = p->lba_multi;
-	if (p->f_multisession)
-		ms_infp->xa_flag=1; /* valid redirection address */
-	else
-		ms_infp->xa_flag=0; /* invalid redirection address */
-
-	return  0;
-}
-
-static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
-		       void * arg)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	int i, st, j;
-	
-	msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
-	if (p->drv_id==-1) {
-		msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
-		return (-ENXIO);             /* no such drive */
-	}
-	down(&ioctl_read_sem);
-	if (p != current_drive)
-		switch_drive(p);
-	
-	msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
-	switch (cmd) 		/* Sun-compatible */
-	{
-		
-	case CDROMPAUSE:     /* Pause the drive */
-		msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
-		/* pause the drive unit when it is currently in PLAY mode,         */
-		/* or reset the starting and ending locations when in PAUSED mode. */
-		/* If applicable, at the next stopping point it reaches            */
-		/* the drive will discontinue playing.                             */
-		switch (current_drive->audio_state)
-		{
-		case audio_playing:
-			if (famL_drive) i=cc_ReadSubQ();
-			else i=cc_Pause_Resume(1);
-			if (i<0) RETURN_UP(-EIO);
-			if (famL_drive) i=cc_Pause_Resume(1);
-			else i=cc_ReadSubQ();
-			if (i<0) RETURN_UP(-EIO);
-			current_drive->pos_audio_start=current_drive->SubQ_run_tot;
-			current_drive->audio_state=audio_pausing;
-			RETURN_UP(0);
-		case audio_pausing:
-			i=cc_Seek(current_drive->pos_audio_start,1);
-			if (i<0) RETURN_UP(-EIO);
-			RETURN_UP(0);
-		default:
-			RETURN_UP(-EINVAL);
-		}
-
-	case CDROMRESUME: /* resume paused audio play */
-		msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n");
-		/* resume playing audio tracks when a previous PLAY AUDIO call has  */
-		/* been paused with a PAUSE command.                                */
-		/* It will resume playing from the location saved in SubQ_run_tot.  */
-		if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
-		if (famL_drive)
-			i=cc_PlayAudio(current_drive->pos_audio_start,
-				       current_drive->pos_audio_end);
-		else i=cc_Pause_Resume(3);
-		if (i<0) RETURN_UP(-EIO);
-		current_drive->audio_state=audio_playing;
-		RETURN_UP(0);
-
-	case CDROMPLAYMSF:
-		msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		if (current_drive->audio_state==audio_playing)
-		{
-			i=cc_Pause_Resume(1);
-			if (i<0) RETURN_UP(-EIO);
-			i=cc_ReadSubQ();
-			if (i<0) RETURN_UP(-EIO);
-			current_drive->pos_audio_start=current_drive->SubQ_run_tot;
-			i=cc_Seek(current_drive->pos_audio_start,1);
-		}
-		memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
-		/* values come as msf-bin */
-		current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
-                        (msf.cdmsf_sec0<<8) |
-				msf.cdmsf_frame0;
-		current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
-			(msf.cdmsf_sec1<<8) |
-				msf.cdmsf_frame1;
-		msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
-		    current_drive->pos_audio_start,current_drive->pos_audio_end);
-		i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
-		if (i<0)
-		{
-			msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
-			DriveReset();
-			current_drive->audio_state=0;
-			RETURN_UP(-EIO);
-		}
-		current_drive->audio_state=audio_playing;
-		RETURN_UP(0);
-		
-	case CDROMPLAYTRKIND: /* Play a track.  This currently ignores index. */
-		msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		if (current_drive->audio_state==audio_playing)
-		{
-			msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
-#if 1
-			RETURN_UP(0); /* just let us play on */
-#else
-			RETURN_UP(-EINVAL); /* play on, but say "error" */
-#endif
-		}
-		memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
-		msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
-		    ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
-		if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL);
-		if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
-		if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
-		if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
-		current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
-		current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
-		i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
-		if (i<0)
-		{
-			msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
-			DriveReset();
-			current_drive->audio_state=0;
-			RETURN_UP(-EIO);
-		}
-		current_drive->audio_state=audio_playing;
-		RETURN_UP(0);
-		
-	case CDROMREADTOCHDR:        /* Read the table of contents header */
-		msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
-		tochdr.cdth_trk0=current_drive->n_first_track;
-		tochdr.cdth_trk1=current_drive->n_last_track;
-		memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
-		RETURN_UP(0);
-		
-	case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
-		msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
-		memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
-		i=tocentry.cdte_track;
-		if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
-		else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
-                  RETURN_UP(-EINVAL);
-		tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
-		tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
-		tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
-		if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
-		{
-			tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
-			tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
-			tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
-		}
-		else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
-			tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
-		else RETURN_UP(-EINVAL);
-		memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
-		RETURN_UP(0);
-		
-	case CDROMSTOP:      /* Spin down the drive */
-		msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */ 
-		i=cc_Pause_Resume(1);
-		current_drive->audio_state=0;
-#if 0
-		cc_DriveReset();
-#endif
-		RETURN_UP(i);
-
-	case CDROMSTART:  /* Spin up the drive */
-		msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
-		cc_SpinUp();
-		current_drive->audio_state=0;
-		RETURN_UP(0);
-
-	case CDROMVOLCTRL:   /* Volume control */
-		msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
-		memcpy(&volctrl,(char *) arg,sizeof(volctrl));
-		current_drive->vol_chan0=0;
-		current_drive->vol_ctrl0=volctrl.channel0;
-		current_drive->vol_chan1=1;
-		current_drive->vol_ctrl1=volctrl.channel1;
-		i=cc_SetVolume();
-		RETURN_UP(0);
-
-	case CDROMVOLREAD:   /* read Volume settings from drive */
-		msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
-		st=cc_GetVolume();
-		if (st<0) RETURN_UP(st);
-		volctrl.channel0=current_drive->vol_ctrl0;
-		volctrl.channel1=current_drive->vol_ctrl1;
-		volctrl.channel2=0;
-		volctrl.channel2=0;
-		memcpy((void *)arg,&volctrl,sizeof(volctrl));
-		RETURN_UP(0);
-
-	case CDROMSUBCHNL:   /* Get subchannel info */
-		msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
-		/* Bogus, I can do better than this! --AJK
-		if ((st_spinning)||(!subq_valid)) {
-			i=cc_ReadSubQ();
-			if (i<0) RETURN_UP(-EIO);
-		}
-		*/
-		i=cc_ReadSubQ();
-		if (i<0) {
-			j=cc_ReadError(); /* clear out error status from drive */
-			current_drive->audio_state=CDROM_AUDIO_NO_STATUS;
-			/* get and set the disk state here,
-			probably not the right place, but who cares!
-			It makes it work properly! --AJK */
-			if (current_drive->CD_changed==0xFF) {
-				msg(DBG_000,"Disk changed detect\n");
-				current_drive->diskstate_flags &= ~cd_size_bit;
-			}
-			RETURN_UP(-EIO);
-		}
-		if (current_drive->CD_changed==0xFF) {
-			/* reread the TOC because the disk has changed! --AJK */
-			msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
-			i=DiskInfo();
-			if(i==0) {
-				current_drive->CD_changed=0x00; /* cd has changed, procede, */
-				RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
-			} else {
-				RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
-			}
-		}
-		memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
-		/*
-			This virtual crap is very bogus!
-			It doesn't detect when the cd is done playing audio!
-			Lets do this right with proper hardware register reading!
-		*/
-		cc_ReadStatus();
-		i=ResponseStatus();
-		msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
-		msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
-		msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
-		msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
-		msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
-		msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-		/* st_busy indicates if it's _ACTUALLY_ playing audio */
-		switch (current_drive->audio_state)
-		{
-		case audio_playing:
-			if(st_busy==0) {
-				/* CD has stopped playing audio --AJK */
-				current_drive->audio_state=audio_completed;
-				SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
-			} else {
-				SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
-			}
-			break;
-		case audio_pausing:
-			SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
-			break;
-		case audio_completed:
-			SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
-			break;
-		default:
-			SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
-			break;
-		}
-		SC.cdsc_adr=current_drive->SubQ_ctl_adr;
-		SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4;
-		SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk);
-		SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx);
-		if (SC.cdsc_format==CDROM_LBA)
-		{
-			SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot);
-			SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk);
-		}
-		else /* not only if (SC.cdsc_format==CDROM_MSF) */
-		{
-			SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF;
-			SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF;
-			SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF;
-			SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF;
-			SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF;
-			SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF;
-		}
-		memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
-		msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
-		    SC.cdsc_format,SC.cdsc_audiostatus,
-		    SC.cdsc_adr,SC.cdsc_ctrl,
-		    SC.cdsc_trk,SC.cdsc_ind,
-		    SC.cdsc_absaddr,SC.cdsc_reladdr);
-		RETURN_UP(0);
-
-	default:
-		msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
-		RETURN_UP(-EINVAL);
-	} /* end switch(cmd) */
-}
-/*==========================================================================*/
-/*
- *  Take care of the different block sizes between cdrom and Linux.
- */
-static void sbp_transfer(struct request *req)
-{
-	long offs;
-
-	while ( (req->nr_sectors > 0) &&
-	       (req->sector/4 >= current_drive->sbp_first_frame) &&
-	       (req->sector/4 <= current_drive->sbp_last_frame) )
-	{
-		offs = (req->sector - current_drive->sbp_first_frame * 4) * 512;
-		memcpy(req->buffer, current_drive->sbp_buf + offs, 512);
-		req->nr_sectors--;
-		req->sector++;
-		req->buffer += 512;
-	}
-}
-/*==========================================================================*/
-/*
- *  special end_request for sbpcd to solve CURRENT==NULL bug. (GTL)
- *  GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy>
- *
- *  This is a kludge so we don't need to modify end_request.
- *  We put the req we take out after INIT_REQUEST in the requests list,
- *  so that end_request will discard it.
- *
- *  The bug could be present in other block devices, perhaps we
- *  should modify INIT_REQUEST and end_request instead, and
- *  change every block device..
- *
- *  Could be a race here?? Could e.g. a timer interrupt schedule() us?
- *  If so, we should copy end_request here, and do it right.. (or
- *  modify end_request and the block devices).
- *
- *  In any case, the race here would be much small than it was, and
- *  I couldn't reproduce..
- *
- *  The race could be: suppose CURRENT==NULL. We put our req in the list,
- *  and we are scheduled. Other process takes over, and gets into
- *  do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so
- *  proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in
- *  end_request, but now CURRENT==NULL... oops!
- *
- */
-#undef DEBUG_GTL
-
-/*==========================================================================*/
-/*
- *  I/O request routine, called from Linux kernel.
- */
-static void do_sbpcd_request(request_queue_t * q)
-{
-	u_int block;
-	u_int nsect;
-	int status_tries, data_tries;
-	struct request *req;
-	struct sbpcd_drive *p;
-#ifdef DEBUG_GTL
-	static int xx_nr=0;
-	int xnr;
-#endif
-
- request_loop:
-#ifdef DEBUG_GTL
-	xnr=++xx_nr;
-
-	req = elv_next_request(q);
-
-	if (!req)
-	{
-		printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
-			xnr, current->pid, jiffies);
-		printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n",
-			xnr, jiffies);
-		return;
-	}
-
-	printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
-		xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
-#endif
-
-	req = elv_next_request(q);	/* take out our request so no other */
-	if (!req)
-		return;
-
-	if (req -> sector == -1)
-		end_request(req, 0);
-	spin_unlock_irq(q->queue_lock);
-
-	down(&ioctl_read_sem);
-	if (rq_data_dir(elv_next_request(q)) != READ)
-	{
-		msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
-		goto err_done;
-	}
-	p = req->rq_disk->private_data;
-#if OLD_BUSY
-	while (busy_audio) sbp_sleep(HZ); /* wait a bit */
-	busy_data=1;
-#endif /* OLD_BUSY */
-
-	if (p->audio_state==audio_playing) goto err_done;
-	if (p != current_drive)
-		switch_drive(p);
-
-	block = req->sector; /* always numbered as 512-byte-pieces */
-	nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
-
-	msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect);
-#if 0
-	msg(DBG_MUL,"read LBA %d\n", block/4);
-#endif
-
-	sbp_transfer(req);
-	/* if we satisfied the request from the buffer, we're done. */
-	if (req->nr_sectors == 0)
-	{
-#ifdef DEBUG_GTL
-		printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n",
-			xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-		up(&ioctl_read_sem);
-		spin_lock_irq(q->queue_lock);
-		end_request(req, 1);
-		goto request_loop;
-	}
-
-#ifdef FUTURE
-	i=prepare(0,0); /* at moment not really a hassle check, but ... */
-	if (i!=0)
-		msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
-#endif /* FUTURE */
-
-	if (!st_spinning) cc_SpinUp();
-
-	for (data_tries=n_retries; data_tries > 0; data_tries--)
-	{
-		for (status_tries=3; status_tries > 0; status_tries--)
-		{
-			flags_cmd_out |= f_respo3;
-			cc_ReadStatus();
-			if (sbp_status() != 0) break;
-			if (st_check) cc_ReadError();
-			sbp_sleep(1);    /* wait a bit, try again */
-		}
-		if (status_tries == 0)
-		{
-			msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
-			break;
-		}
-		
-		sbp_read_cmd(req);
-		sbp_sleep(0);
-		if (sbp_data(req) != 0)
-		{
-#ifdef SAFE_MIXED
-			current_drive->has_data=2; /* is really a data disk */
-#endif /* SAFE_MIXED */
-#ifdef DEBUG_GTL
-			printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
-				xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-			up(&ioctl_read_sem);
-			spin_lock_irq(q->queue_lock);
-			end_request(req, 1);
-			goto request_loop;
-		}
-	}
-
- err_done:
-#if OLD_BUSY
-	busy_data=0;
-#endif /* OLD_BUSY */
-#ifdef DEBUG_GTL
-	printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
-		xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-	up(&ioctl_read_sem);
-	sbp_sleep(0);    /* wait a bit, try again */
-	spin_lock_irq(q->queue_lock);
-	end_request(req, 0);
-	goto request_loop;
-}
-/*==========================================================================*/
-/*
- *  build and send the READ command.
- */
-static void sbp_read_cmd(struct request *req)
-{
-#undef OLD
-
-	int i;
-	int block;
-
-	current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1;      /* purge buffer */
-	current_drive->sbp_current = 0;
-	block=req->sector/4;
-	if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
-		current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
-	else
-	{
-		current_drive->sbp_read_frames=current_drive->CDsize_frm-block;
-		/* avoid reading past end of data */
-		if (current_drive->sbp_read_frames < 1)
-		{
-			msg(DBG_INF,"requested frame %d, CD size %d ???\n",
-			    block, current_drive->CDsize_frm);
-			current_drive->sbp_read_frames=1;
-		}
-	}
-
-	flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
-	clr_cmdbuf();
-	if (famV_drive)
-	  {
-	    drvcmd[0]=CMDV_READ;
-	    lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
-	    bin2bcdx(&drvcmd[1]);
-	    bin2bcdx(&drvcmd[2]);
-	    bin2bcdx(&drvcmd[3]);
-	    drvcmd[4]=current_drive->sbp_read_frames>>8;
-	    drvcmd[5]=current_drive->sbp_read_frames&0xff;
-	    drvcmd[6]=0x02; /* flag "msf-bcd" */
-	}
-	else if (fam0L_drive)
-	{
-		flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
-		if (current_drive->xa_byte==0x20)
-		{
-			cmd_type=READ_M2;
-			drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
-			drvcmd[1]=(block>>16)&0x0ff;
-			drvcmd[2]=(block>>8)&0x0ff;
-			drvcmd[3]=block&0x0ff;
-			drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-			drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-		}
-		else
-		{
-			drvcmd[0]=CMD0_READ; /* "read frames", old drives */
-			if (current_drive->drv_type>=drv_201)
-			{
-				lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
-				bin2bcdx(&drvcmd[1]);
-				bin2bcdx(&drvcmd[2]);
-				bin2bcdx(&drvcmd[3]);
-			}
-			else
-			{
-				drvcmd[1]=(block>>16)&0x0ff;
-				drvcmd[2]=(block>>8)&0x0ff;
-				drvcmd[3]=block&0x0ff;
-			}
-			drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-			drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-			drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
-		}
-	}
-	else if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_READ;
-		lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-		drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
-		drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_READ;
-		lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-		drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-		drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-		drvcmd[6]=0x02;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_READ;
-		drvcmd[2]=(block>>24)&0x0ff;
-		drvcmd[3]=(block>>16)&0x0ff;
-		drvcmd[4]=(block>>8)&0x0ff;
-		drvcmd[5]=block&0x0ff;
-		drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
-		drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
-	}
-	flags_cmd_out=f_putcmd;
-	response_count=0;
-	i=cmd_out();
-	if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i);
-	return;
-}
-/*==========================================================================*/
-/*
- *  Check the completion of the read-data command.  On success, read
- *  the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
- */
-static int sbp_data(struct request *req)
-{
-	int i=0, j=0, l, frame;
-	u_int try=0;
-	u_long timeout;
-	u_char *p;
-	u_int data_tries = 0;
-	u_int data_waits = 0;
-	u_int data_retrying = 0;
-	int error_flag;
-	int xa_count;
-	int max_latency;
-	int success;
-	int wait;
-	int duration;
-
-	error_flag=0;
-	success=0;
-#if LONG_TIMING
-	max_latency=9*HZ;
-#else
-	if (current_drive->f_multisession) max_latency=15*HZ;
-	else max_latency=5*HZ;
-#endif
-	duration=jiffies;
-	for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
-	{
-		SBPCD_CLI;
-
-		del_timer(&data_timer);
-		data_timer.expires=jiffies+max_latency;
-		timed_out_data=0;
-		add_timer(&data_timer);
-		while (!timed_out_data)
-		{
-			if (current_drive->f_multisession) try=maxtim_data*4;
-			else try=maxtim_data;
-			msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
-			for ( ; try!=0;try--)
-			{
-				j=inb(CDi_status);
-				if (!(j&s_not_data_ready)) break;
-				if (!(j&s_not_result_ready)) break;
-				if (fam0LV_drive) if (j&s_attention) break;
-			}
-			if (!(j&s_not_data_ready)) goto data_ready;
-			if (try==0)
-			{
-				if (data_retrying == 0) data_waits++;
-				data_retrying = 1;
-				msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n");
-				sbp_sleep(1);
-				try = 1;
-			}
-		}
-		msg(DBG_INF,"sbp_data: CDi_status loop expired.\n");
-	data_ready:
-		del_timer(&data_timer);
-
-		if (timed_out_data)
-		{
-			msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j);
-			error_flag++;
-		}
-		if (try==0)
-		{
-			msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j);
-			error_flag++;
-		}
-		if (!(j&s_not_result_ready))
-		{
-			msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j);
-			response_count=20;
-			j=ResponseInfo();
-			j=inb(CDi_status);
-		}
-		if (j&s_not_data_ready)
-		{
-			if ((current_drive->ored_ctl_adr&0x40)==0)
-				msg(DBG_INF, "CD contains no data tracks.\n");
-			else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j);
-			error_flag++;
-		}
-		SBPCD_STI;
-		if (error_flag) break;
-
-		msg(DBG_000, "sbp_data: beginning to read.\n");
-		p = current_drive->sbp_buf + frame *  CD_FRAMESIZE;
-		if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-		if (cmd_type==READ_M2) {
-                        if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
-                        else insb(CDi_data, xa_head_buf, CD_XA_HEAD);
-		}
-		if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1);
-		else insb(CDi_data, p, CD_FRAMESIZE);
-		if (cmd_type==READ_M2) {
-                        if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
-                        else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
-		}
-		current_drive->sbp_current++;
-		if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-		if (cmd_type==READ_M2)
-		{
-			for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++)
-				sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]);
-			msgbuf[xa_count*3]=0;
-			msg(DBG_XA1,"xa head:%s\n", msgbuf);
-		}
-		data_retrying = 0;
-		data_tries++;
-		if (data_tries >= 1000)
-		{
-			msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries);
-			data_waits = data_tries = 0;
-		}
-	}
-	duration=jiffies-duration;
-	msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
-	if (famT_drive)
-	{
-		wait=8;
-		do
-		{
-			if (teac==2)
-                          {
-                            if ((i=CDi_stat_loop_T()) == -1) break;
-                          }
-                        else
-                          {
-                            sbp_sleep(1);
-                            OUT(CDo_sel_i_d,0);
-                            i=inb(CDi_status);
-                          }
-			if (!(i&s_not_data_ready))
-			{
-				OUT(CDo_sel_i_d,1);
-				j=0;
-				do
-				{
-					if (do_16bit) i=inw(CDi_data);
-					else i=inb(CDi_data);
-					j++;
-					i=inb(CDi_status);
-				}
-				while (!(i&s_not_data_ready));
-				msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j);
-			}
-			if (!(i&s_not_result_ready))
-			{
-				OUT(CDo_sel_i_d,0);
-				l=0;
-				do
-				{
-					infobuf[l++]=inb(CDi_info);
-					i=inb(CDi_status);
-				}
-				while (!(i&s_not_result_ready));
-				if (infobuf[0]==0x00) success=1;
-#if 1
-				for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
-				msgbuf[j*3]=0;
-				msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf);
-#endif
-				if (infobuf[0]==0x02)
-				{
-					error_flag++;
-					do
-					{
-						++recursion;
-						if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion);
-						else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n");
-						clr_cmdbuf();
-						drvcmd[0]=CMDT_READ_ERR;
-						j=cmd_out_T(); /* !!! recursive here !!! */
-						--recursion;
-						sbp_sleep(1);
-					}
-					while (j<0);
-					current_drive->error_state=infobuf[2];
-					current_drive->b3=infobuf[3];
-					current_drive->b4=infobuf[4];
-				}
-				break;
-			}
-			else
-			{
-#if 0
-				msg(DBG_TEA, "============= waiting for result=================.\n");
-				sbp_sleep(1);
-#endif
-			}
-		}
-		while (wait--);
-	}
-
-	if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
-	{
-		msg(DBG_TEA, "================error flag: %d=================.\n", error_flag);
-		msg(DBG_INF,"sbp_data: read aborted by drive.\n");
-#if 1
-		i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
-		i=cc_ReadError();
-#endif
-		return (0);
-	}
-	
-	if (fam0LV_drive)
-	{
-		SBPCD_CLI;
-		i=maxtim_data;
-		for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
-		{
-			for ( ;i!=0;i--)
-			{
-				j=inb(CDi_status);
-				if (!(j&s_not_data_ready)) break;
-				if (!(j&s_not_result_ready)) break;
-				if (j&s_attention) break;
-			}
-			if (i != 0 || time_after_eq(jiffies, timeout)) break;
-			sbp_sleep(0);
-			i = 1;
-		}
-		if (i==0) msg(DBG_INF,"status timeout after READ.\n");
-		if (!(j&s_attention))
-		{
-			msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
-			i=cc_DriveReset();  /* ugly fix to prevent a hang */
-			SBPCD_STI;
-			return (0);
-		}
-		SBPCD_STI;
-	}
-
-#if 0
-	if (!success)
-#endif
-		do
-		{
-			if (fam0LV_drive) cc_ReadStatus();
-#if 1
-			if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
-#endif
-			i=ResponseStatus();  /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-#if 1
-			if (famT_drive)	msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
-#endif
-			if (i<0)
-			{
-				msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
-				return (0);
-			}
-		}
-		while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
-	if (st_check)
-	{
-		i=cc_ReadError();
-		msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i);
-		return (0);
-	}
-	if (fatal_err)
-	{
-		fatal_err=0;
-		current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1;      /* purge buffer */
-		current_drive->sbp_current = 0;
-		msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
-		return (0);
-	}
-	
-	current_drive->sbp_first_frame = req -> sector / 4;
-	current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
-	sbp_transfer(req);
-	return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_block_open(struct inode *inode, struct file *file)
-{
-	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_open(p->sbpcd_infop, inode, file);
-}
-
-static int sbpcd_block_release(struct inode *inode, struct file *file)
-{
-	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_release(p->sbpcd_infop, file);
-}
-
-static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
-				unsigned cmd, unsigned long arg)
-{
-	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-	struct cdrom_device_info *cdi = p->sbpcd_infop;
-	int ret, i;
-
-	ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg);
-	if (ret != -ENOSYS)
-		return ret;
-
-	msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg);
-	if (p->drv_id==-1) {
-		msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
-		return (-ENXIO);             /* no such drive */
-	}
-	down(&ioctl_read_sem);
-	if (p != current_drive)
-		switch_drive(p);
-	
-	msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
-	switch (cmd) 		/* Sun-compatible */
-	{
-	case DDIOCSDBG:		/* DDI Debug */
-		if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
-		i=sbpcd_dbg_ioctl(arg,1);
-		RETURN_UP(i);
-	case CDROMRESET:      /* hard reset the drive */
-		msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
-		i=DriveReset();
-		current_drive->audio_state=0;
-		RETURN_UP(i);
-
-	case CDROMREADMODE1:
-		msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		cc_ModeSelect(CD_FRAMESIZE);
-		cc_ModeSense();
-		current_drive->mode=READ_M1;
-		RETURN_UP(0);
-
-	case CDROMREADMODE2: /* not usable at the moment */
-		msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		cc_ModeSelect(CD_FRAMESIZE_RAW1);
-		cc_ModeSense();
-		current_drive->mode=READ_M2;
-		RETURN_UP(0);
-
-	case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
-		msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
-		if (current_drive->sbp_audsiz>0)
-			vfree(current_drive->aud_buf);
-		current_drive->aud_buf=NULL;
-		current_drive->sbp_audsiz=arg;
-
-		if (current_drive->sbp_audsiz>16)
-		{
-			current_drive->sbp_audsiz = 0;
-			RETURN_UP(current_drive->sbp_audsiz);
-		}
-	
-		if (current_drive->sbp_audsiz>0)
-		{
-			current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
-			if (current_drive->aud_buf==NULL)
-			{
-				msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
-				current_drive->sbp_audsiz=0;
-			}
-			else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
-		}
-		RETURN_UP(current_drive->sbp_audsiz);
-
-	case CDROMREADAUDIO:
-	{ /* start of CDROMREADAUDIO */
-		int i=0, j=0, frame, block=0;
-		u_int try=0;
-		u_long timeout;
-		u_char *p;
-		u_int data_tries = 0;
-		u_int data_waits = 0;
-		u_int data_retrying = 0;
-		int status_tries;
-		int error_flag;
-
-		msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
-		if (fam0_drive) RETURN_UP(-EINVAL);
-		if (famL_drive) RETURN_UP(-EINVAL);
-		if (famV_drive) RETURN_UP(-EINVAL);
-		if (famT_drive) RETURN_UP(-EINVAL);
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL);
-		if (copy_from_user(&read_audio, (void __user *)arg,
-				   sizeof(struct cdrom_read_audio)))
-			RETURN_UP(-EFAULT);
-		if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
-		if (!access_ok(VERIFY_WRITE, read_audio.buf,
-			      read_audio.nframes*CD_FRAMESIZE_RAW))
-                	RETURN_UP(-EFAULT);
-
-		if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
-			block=msf2lba(&read_audio.addr.msf.minute);
-		else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
-			block=read_audio.addr.lba;
-		else RETURN_UP(-EINVAL);
-#if 000
-		i=cc_SetSpeed(speed_150,0,0);
-		if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
-#endif
-		msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
-		    block, blk2msf(block));
-		msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
-#if OLD_BUSY
-		while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
-		busy_audio=1;
-#endif /* OLD_BUSY */
-		error_flag=0;
-		for (data_tries=5; data_tries>0; data_tries--)
-		{
-			msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
-			current_drive->mode=READ_AU;
-			cc_ModeSelect(CD_FRAMESIZE_RAW);
-			cc_ModeSense();
-			for (status_tries=3; status_tries > 0; status_tries--)
-			{
-				flags_cmd_out |= f_respo3;
-				cc_ReadStatus();
-				if (sbp_status() != 0) break;
-				if (st_check) cc_ReadError();
-				sbp_sleep(1);    /* wait a bit, try again */
-			}
-			if (status_tries == 0)
-			{
-				msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
-				continue;
-			}
-			msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
-
-			flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
-			if (fam0L_drive)
-			{
-				flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
-				cmd_type=READ_M2;
-				drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
-				drvcmd[1]=(block>>16)&0x000000ff;
-				drvcmd[2]=(block>>8)&0x000000ff;
-				drvcmd[3]=block&0x000000ff;
-				drvcmd[4]=0;
-				drvcmd[5]=read_audio.nframes; /* # of frames */
-				drvcmd[6]=0;
-			}
-			else if (fam1_drive)
-			{
-				drvcmd[0]=CMD1_READ; /* "read frames", new drives */
-				lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-				drvcmd[4]=0;
-				drvcmd[5]=0;
-				drvcmd[6]=read_audio.nframes; /* # of frames */
-			}
-			else if (fam2_drive)
-			{
-				drvcmd[0]=CMD2_READ_XA2;
-				lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-				drvcmd[4]=0;
-				drvcmd[5]=read_audio.nframes; /* # of frames */
-				drvcmd[6]=0x11; /* raw mode */
-			}
-			else if (famT_drive) /* CD-55A: not tested yet */
-			{
-			}
-			msg(DBG_AUD,"read_audio: before giving \"read\" command.\n");
-			flags_cmd_out=f_putcmd;
-			response_count=0;
-			i=cmd_out();
-			if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i);
-			sbp_sleep(0);
-			msg(DBG_AUD,"read_audio: after giving \"read\" command.\n");
-			for (frame=1;frame<2 && !error_flag; frame++)
-			{
-				try=maxtim_data;
-				for (timeout=jiffies+9*HZ; ; )
-				{
-					for ( ; try!=0;try--)
-					{
-						j=inb(CDi_status);
-						if (!(j&s_not_data_ready)) break;
-						if (!(j&s_not_result_ready)) break;
-						if (fam0L_drive) if (j&s_attention) break;
-					}
-					if (try != 0 || time_after_eq(jiffies, timeout)) break;
-					if (data_retrying == 0) data_waits++;
-					data_retrying = 1;
-					sbp_sleep(1);
-					try = 1;
-				}
-				if (try==0)
-				{
-					msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n");
-					error_flag++;
-					break;
-				}
-				msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n");
-				if (j&s_not_data_ready)
-				{
-					msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n");
-					error_flag++;
-					break;
-				}
-				msg(DBG_AUD,"read_audio: before reading data.\n");
-				error_flag=0;
-				p = current_drive->aud_buf;
-				if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-				if (do_16bit)
-				{
-					u_short *p2 = (u_short *) p;
-
-					for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
-				  	{
-						if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
-						/* get one sample */
-						*p2++ = inw_p(CDi_data);
-						*p2++ = inw_p(CDi_data);
-					}
-				} else {
-					for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
-				  	{
-						if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
-						/* get one sample */
-						*p++ = inb_p(CDi_data);
-						*p++ = inb_p(CDi_data);
-						*p++ = inb_p(CDi_data);
-						*p++ = inb_p(CDi_data);
-					}
-				}
-				if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-				data_retrying = 0;
-			}
-			msg(DBG_AUD,"read_audio: after reading data.\n");
-			if (error_flag)    /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
-			{
-				msg(DBG_AUD,"read_audio: read aborted by drive\n");
-#if 0000
-				i=cc_DriveReset();                /* ugly fix to prevent a hang */
-#else
-				i=cc_ReadError();
-#endif
-				continue;
-			}
-			if (fam0L_drive)
-			{
-				i=maxtim_data;
-				for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
-				{
-					for ( ;i!=0;i--)
-					{
-						j=inb(CDi_status);
-						if (!(j&s_not_data_ready)) break;
-						if (!(j&s_not_result_ready)) break;
-						if (j&s_attention) break;
-					}
-					if (i != 0 || time_after_eq(jiffies, timeout)) break;
-					sbp_sleep(0);
-					i = 1;
-				}
-				if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
-				if (!(j&s_attention))
-				{
-					msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n");
-					i=cc_DriveReset();  /* ugly fix to prevent a hang */
-					continue;
-				}
-			}
-			do
-			{
-				if (fam0L_drive) cc_ReadStatus();
-				i=ResponseStatus();  /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-				if (i<0) { msg(DBG_AUD,
-					       "read_audio: cc_ReadStatus error after read: %02X\n",
-					       current_drive->status_bits);
-					   continue; /* FIXME */
-				   }
-			}
-			while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
-			if (st_check)
-			{
-				i=cc_ReadError();
-				msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
-				continue;
-			}
-			if (copy_to_user(read_audio.buf,
-					 current_drive->aud_buf,
-					 read_audio.nframes * CD_FRAMESIZE_RAW))
-				RETURN_UP(-EFAULT);
-			msg(DBG_AUD,"read_audio: copy_to_user done.\n");
-			break;
-		}
-		cc_ModeSelect(CD_FRAMESIZE);
-		cc_ModeSense();
-		current_drive->mode=READ_M1;
-#if OLD_BUSY
-		busy_audio=0;
-#endif /* OLD_BUSY */
-		if (data_tries == 0)
-		{
-			msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
-			RETURN_UP(-EIO);
-		}
-		msg(DBG_AUD,"read_audio: successful return.\n");
-		RETURN_UP(0);
-	} /* end of CDROMREADAUDIO */
-
-	default:
-		msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
-		RETURN_UP(-EINVAL);
-	} /* end switch(cmd) */
-}
-
-static int sbpcd_block_media_changed(struct gendisk *disk)
-{
-	struct sbpcd_drive *p = disk->private_data;
-	return cdrom_media_changed(p->sbpcd_infop);
-}
-
-static struct block_device_operations sbpcd_bdops =
-{
-	.owner		= THIS_MODULE,
-	.open		= sbpcd_block_open,
-	.release	= sbpcd_block_release,
-	.ioctl		= sbpcd_block_ioctl,
-	.media_changed	= sbpcd_block_media_changed,
-};
-/*==========================================================================*/
-/*
- *  Open the device special file.  Check that a disk is in. Read TOC.
- */
-static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
-{
-	struct sbpcd_drive *p = cdi->handle;
-
-	down(&ioctl_read_sem);
-	switch_drive(p);
-
-	/*
-	 * try to keep an "open" counter here and lock the door if 0->1.
-	 */
-	msg(DBG_LCK,"open_count: %d -> %d\n",
-	    current_drive->open_count,current_drive->open_count+1);
-	if (++current_drive->open_count<=1)
-	{
-		int i;
-		i=LockDoor();
-		current_drive->open_count=1;
-		if (famT_drive)	msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n");
-		i=DiskInfo();
-		if (famT_drive)	msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n");
-		if ((current_drive->ored_ctl_adr&0x40)==0)
-		{		
-			msg(DBG_INF,"CD contains no data tracks.\n");
-#ifdef SAFE_MIXED
-			current_drive->has_data=0;
-#endif /* SAFE_MIXED */
-		}
-#ifdef SAFE_MIXED
-		else if (current_drive->has_data<1) current_drive->has_data=1;
-#endif /* SAFE_MIXED */ 
-	}
-	if (!st_spinning) cc_SpinUp();
-	RETURN_UP(0);
-}
-/*==========================================================================*/
-/*
- *  On close, we flush all sbp blocks from the buffer cache.
- */
-static void sbpcd_release(struct cdrom_device_info * cdi)
-{
-	struct sbpcd_drive *p = cdi->handle;
-
-	if (p->drv_id==-1) {
-		msg(DBG_INF, "release: bad device: %s\n", cdi->name);
-		return;
-	}
-	down(&ioctl_read_sem);
-	switch_drive(p);
-	/*
-	 * try to keep an "open" counter here and unlock the door if 1->0.
-	 */
-	msg(DBG_LCK,"open_count: %d -> %d\n",
-	    p->open_count,p->open_count-1);
-	if (p->open_count>-2) /* CDROMEJECT may have been done */
-	{
-		if (--p->open_count<=0) 
-		{
-			p->sbp_first_frame=p->sbp_last_frame=-1;
-			if (p->audio_state!=audio_playing)
-				if (p->f_eject) cc_SpinDown();
-			p->diskstate_flags &= ~cd_size_bit;
-			p->open_count=0; 
-#ifdef SAFE_MIXED
-			p->has_data=0;
-#endif /* SAFE_MIXED */ 
-		}
-	}
-	up(&ioctl_read_sem);
-	return ;
-}
-/*==========================================================================*/
-/*
- *
- */
-static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
-static struct cdrom_device_ops sbpcd_dops = {
-	.open			= sbpcd_open,
-	.release		= sbpcd_release,
-	.drive_status		= sbpcd_drive_status,
-	.media_changed		= sbpcd_media_changed,
-	.tray_move		= sbpcd_tray_move,
-	.lock_door		= sbpcd_lock_door,
-	.select_speed		= sbpcd_select_speed,
-	.get_last_session	= sbpcd_get_last_session,
-	.get_mcn		= sbpcd_get_mcn,
-	.reset			= sbpcd_reset,
-	.audio_ioctl		= sbpcd_audio_ioctl,
-	.capability		= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
-				CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
-				CDC_MCN | CDC_PLAY_AUDIO,
-	.n_minors		= 1,
-};
-
-/*==========================================================================*/
-/*
- * accept "kernel command line" parameters 
- * (suggested by Peter MacDonald with SLS 1.03)
- *
- * This is only implemented for the first controller. Should be enough to
- * allow installing with a "strange" distribution kernel.
- *
- * use: tell LILO:
- *                 sbpcd=0x230,SoundBlaster
- *             or
- *                 sbpcd=0x300,LaserMate
- *             or
- *                 sbpcd=0x338,SoundScape
- *             or
- *                 sbpcd=0x2C0,Teac16bit
- *
- * (upper/lower case sensitive here - but all-lowercase is ok!!!).
- *
- * the address value has to be the CDROM PORT ADDRESS -
- * not the soundcard base address.
- * For the SPEA/SoundScape setup, DO NOT specify the "configuration port"
- * address, but the address which is really used for the CDROM (usually 8
- * bytes above).
- *
- */
-
-int sbpcd_setup(char *s)
-{
-#ifndef MODULE
-	int p[4];
-	(void)get_options(s, ARRAY_SIZE(p), p);
-	setup_done++;
-	msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
-	sbpro_type=0; /* default: "LaserMate" */
-	if (p[0]>1) sbpro_type=p[2];
-	else if (!strcmp(s,str_sb)) sbpro_type=1;
-	else if (!strcmp(s,str_sb_l)) sbpro_type=1;
-	else if (!strcmp(s,str_sp)) sbpro_type=2;
-	else if (!strcmp(s,str_sp_l)) sbpro_type=2;
-	else if (!strcmp(s,str_ss)) sbpro_type=2;
-	else if (!strcmp(s,str_ss_l)) sbpro_type=2;
-	else if (!strcmp(s,str_t16)) sbpro_type=3;
-	else if (!strcmp(s,str_t16_l)) sbpro_type=3;
-	if (p[0]>0) sbpcd_ioaddr=p[1];
-	if (p[0]>2) max_drives=p[3];
-#else
-	sbpcd_ioaddr = sbpcd[0];
-	sbpro_type = sbpcd[1];
-#endif
-	
-	CDo_command=sbpcd_ioaddr;
-	CDi_info=sbpcd_ioaddr;
-	CDi_status=sbpcd_ioaddr+1;
-	CDo_sel_i_d=sbpcd_ioaddr+1;
-	CDo_reset=sbpcd_ioaddr+2;
-	CDo_enable=sbpcd_ioaddr+3; 
-	f_16bit=0;
-	if ((sbpro_type==1)||(sbpro_type==3))
-	{
-		CDi_data=sbpcd_ioaddr;
-		if (sbpro_type==3)
-                {
-                        f_16bit=1;
-                        sbpro_type=1;
-                }
-	}
-	else CDi_data=sbpcd_ioaddr+2;
-
-	return 1;
-}
-
-__setup("sbpcd=", sbpcd_setup);
-
-
-/*==========================================================================*/
-/*
- * Sequoia S-1000 CD-ROM Interface Configuration
- * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards
- * The soundcard has to get jumpered for the interface type "Panasonic"
- * (not Sony or Mitsumi) and to get soft-configured for
- *     -> configuration port address
- *     -> CDROM port offset (num_ports): has to be 8 here. Possibly this
- *        offset value determines the interface type (none, Panasonic,
- *        Mitsumi, Sony).
- *        The interface uses a configuration port (0x320, 0x330, 0x340, 0x350)
- *        some bytes below the real CDROM address.
- *         
- *        For the Panasonic style (LaserMate) interface and the configuration
- *        port 0x330, we have to use an offset of 8; so, the real CDROM port
- *        address is 0x338.
- */
-static int __init config_spea(void)
-{
-	/*
-         * base address offset between configuration port and CDROM port,
-	 * this probably defines the interface type
-         *   2 (type=??): 0x00
-         *   8 (type=LaserMate):0x10
-         *  16 (type=??):0x20
-         *  32 (type=??):0x30
-         */
-	int n_ports=0x10;
-
-	int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */
-	int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */
-	int dack_polarity=0; /* L:0x00, H:0x80 */
-	int drq_polarity=0x40; /* L:0x00, H:0x40 */
-	int i;
-
-#define SPEA_REG_1 sbpcd_ioaddr-0x08+4
-#define SPEA_REG_2 sbpcd_ioaddr-0x08+5
-	
-	OUT(SPEA_REG_1,0xFF);
-	i=inb(SPEA_REG_1);
-	if (i!=0x0F)
-	{
-		msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr);
-		return (-1); /* no interface found */
-	}
-	OUT(SPEA_REG_1,0x04);
-	OUT(SPEA_REG_2,0xC0);
-	
-	OUT(SPEA_REG_1,0x05);
-	OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity);
-	
-#if 1
-#define SPEA_PATTERN 0x80
-#else
-#define SPEA_PATTERN 0x00
-#endif
-	OUT(SPEA_REG_1,0x06);
-	OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-	OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-	
-	OUT(SPEA_REG_1,0x09);
-	i=(inb(SPEA_REG_2)&0xCF)|n_ports;
-	OUT(SPEA_REG_2,i);
-	
-	sbpro_type = 0; /* acts like a LaserMate interface now */
-	msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr);
-	return (0);
-}
-
-/*==========================================================================*/
-/*
- *  Test for presence of drive and initialize it.
- *  Called once at boot or load time.
- */
-
-/* FIXME: cleanups after failed allocations are too ugly for words */
-#ifdef MODULE
-int __init __sbpcd_init(void)
-#else
-int __init sbpcd_init(void)
-#endif
-{
-	int i=0, j=0;
-	int addr[2]={1, CDROM_PORT};
-	int port_index;
-
-	sti();
-	
-	msg(DBG_INF,"sbpcd.c %s\n", VERSION);
-#ifndef MODULE
-#if DISTRIBUTION
-	if (!setup_done)
-	{
-		msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drives\n");
-		msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =\n");
-		msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).\n");
-		msg(DBG_INF,"If that happens, you have to reboot and use the\n");
-		msg(DBG_INF,"LILO (kernel) command line feature like:\n");
-		msg(DBG_INF,"   LILO boot: ... sbpcd=0x230,SoundBlaster\n");
-		msg(DBG_INF,"or like:\n");
-		msg(DBG_INF,"   LILO boot: ... sbpcd=0x300,LaserMate\n");
-		msg(DBG_INF,"or like:\n");
-		msg(DBG_INF,"   LILO boot: ... sbpcd=0x338,SoundScape\n");
-		msg(DBG_INF,"with your REAL address.\n");
-		msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n");
-	}
-#endif /* DISTRIBUTION */
-	sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
-	sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */
-#endif /* MODULE */
-	
-	for (port_index=0;port_index<NUM_PROBE;port_index+=2)
-	{
-		addr[1]=sbpcd[port_index];
-		if (addr[1]==0) break;
-		if (check_region(addr[1],4))
-		{
-			msg(DBG_INF,"check_region: %03X is not free.\n",addr[1]);
-			continue;
-		}
-		if (sbpcd[port_index+1]==2) type=str_sp;
-		else if (sbpcd[port_index+1]==1) type=str_sb;
-		else if (sbpcd[port_index+1]==3) type=str_t16;
-		else type=str_lm;
-		sbpcd_setup((char *)type);
-#if DISTRIBUTION
-		msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
-#endif /* DISTRIBUTION */
-		if (sbpcd[port_index+1]==2)
-		{
-			i=config_spea();
-			if (i<0) continue;
-		}
-#ifdef PATH_CHECK
-		if (check_card(addr[1])) continue;
-#endif /* PATH_CHECK */ 
-		i=check_drives();
-		msg(DBG_INI,"check_drives done.\n");
-		if (i>=0) break; /* drive found */
-	} /* end of cycling through the set of possible I/O port addresses */
-	
-	if (ndrives==0)
-	{
-		msg(DBG_INF, "No drive found.\n");
-#ifdef MODULE
-		return -EIO;
-#else
-		goto init_done;
-#endif /* MODULE */
-	}
-	
-	if (port_index>0)
-          {
-            msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n");
-            msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n");
-          }
-	check_datarate();
-	msg(DBG_INI,"check_datarate done.\n");
-	
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		struct sbpcd_drive *p = D_S + j;
-		if (p->drv_id==-1)
-			continue;
-		switch_drive(p);
-#if 1
-		if (!famL_drive) cc_DriveReset();
-#endif
-		if (!st_spinning) cc_SpinUp();
-		p->sbp_first_frame = -1;  /* First frame in buffer */
-		p->sbp_last_frame = -1;   /* Last frame in buffer  */
-		p->sbp_read_frames = 0;   /* Number of frames being read to buffer */
-		p->sbp_current = 0;       /* Frame being currently read */
-		p->CD_changed=1;
-		p->frame_size=CD_FRAMESIZE;
-		p->f_eject=0;
-#if EJECT
-		if (!fam0_drive) p->f_eject=1;
-#endif /* EJECT */ 
-		cc_ReadStatus();
-		i=ResponseStatus();  /* returns orig. status or p_busy_new */
-		if (famT_drive) i=ResponseStatus();  /* returns orig. status or p_busy_new */
-		if (i<0)
-		{
-			if (i!=-402)
-				msg(DBG_INF,"init: ResponseStatus returns %d.\n",i);
-		}
-		else
-		{
-			if (st_check)
-			{
-				i=cc_ReadError();
-				msg(DBG_INI,"init: cc_ReadError returns %d\n",i);
-			}
-		}
-		msg(DBG_INI,"init: first GetStatus: %d\n",i);
-		msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n",
-		    p->error_byte);
-		if (p->error_byte==aud_12)
-		{
-			timeout=jiffies+2*HZ;
-			do
-			{
-				i=GetStatus();
-				msg(DBG_INI,"init: second GetStatus: %02X\n",i);
-				msg(DBG_LCS,
-				    "init: second GetStatus: error_byte=%d\n",
-				    p->error_byte);
-				if (i<0) break;
-				if (!st_caddy_in) break;
-				}
-			while ((!st_diskok)||time_after(jiffies, timeout));
-		}
-		i=SetSpeed();
-		if (i>=0) p->CD_changed=1;
-	}
-
-	if (!request_region(CDo_command,4,major_name))
-	{
-		printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command);
-		return -EIO;
-	}
-
-	/*
-	 * Turn on the CD audio channels.
-	 * The addresses are obtained from SOUND_BASE (see sbpcd.h).
-	 */
-#if SOUND_BASE
-	OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
-	OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
-#endif /* SOUND_BASE */
-
-	if (register_blkdev(MAJOR_NR, major_name)) {
-#ifdef MODULE
-		return -EIO;
-#else
-		goto init_done;
-#endif /* MODULE */
-	}
-
-	/*
-	 * init error handling is broken beyond belief in this driver...
-	 */
-	sbpcd_queue = blk_init_queue(do_sbpcd_request, &sbpcd_lock);
-	if (!sbpcd_queue) {
-		release_region(CDo_command,4);
-		unregister_blkdev(MAJOR_NR, major_name);
-		return -ENOMEM;
-	}
-
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		struct cdrom_device_info * sbpcd_infop;
-		struct gendisk *disk;
-		struct sbpcd_drive *p = D_S + j;
-
-		if (p->drv_id==-1) continue;
-		switch_drive(p);
-#ifdef SAFE_MIXED
-		p->has_data=0;
-#endif /* SAFE_MIXED */ 
-		/*
-		 * allocate memory for the frame buffers
-		 */
-		p->aud_buf=NULL;
-		p->sbp_audsiz=0;
-		p->sbp_bufsiz=buffers;
-		if (p->drv_type&drv_fam1)
-			if (READ_AUDIO>0)
-				p->sbp_audsiz = READ_AUDIO;
-		p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE);
-		if (!p->sbp_buf) {
-			msg(DBG_INF,"data buffer (%d frames) not available.\n",
-				buffers);
-			if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
-			{
-				printk("Can't unregister %s\n", major_name);
-			}
-			release_region(CDo_command,4);
-			blk_cleanup_queue(sbpcd_queue);
-			return -EIO;
-		}
-#ifdef MODULE
-		msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
-#endif /* MODULE */
-		if (p->sbp_audsiz>0)
-		{
-			p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW);
-			if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz);
-			else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz);
-		}
-                sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
-		if (sbpcd_infop == NULL)
-		{
-                        release_region(CDo_command,4);
-			blk_cleanup_queue(sbpcd_queue);
-                        return -ENOMEM;
-		}
-		memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
-		sbpcd_infop->ops = &sbpcd_dops;
-		sbpcd_infop->speed = 2;
-		sbpcd_infop->capacity = 1;
-		sprintf(sbpcd_infop->name, "sbpcd%d", j);
-		sbpcd_infop->handle = p;
-		p->sbpcd_infop = sbpcd_infop;
-		disk = alloc_disk(1);
-		disk->major = MAJOR_NR;
-		disk->first_minor = j;
-		disk->fops = &sbpcd_bdops;
-		strcpy(disk->disk_name, sbpcd_infop->name);
-		disk->flags = GENHD_FL_CD;
-		p->disk = disk;
-		if (register_cdrom(sbpcd_infop))
-		{
-			printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
-		}
-		disk->private_data = p;
-		disk->queue = sbpcd_queue;
-		add_disk(disk);
-	}
-	blk_queue_hardsect_size(sbpcd_queue, CD_FRAMESIZE);
-
-#ifndef MODULE
- init_done:
-#endif
-	return 0;
-}
-/*==========================================================================*/
-#ifdef MODULE
-static void sbpcd_exit(void)
-{
-	int j;
-	
-	if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
-	{
-		msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
-		return;
-	}
-	release_region(CDo_command,4);
-	blk_cleanup_queue(sbpcd_queue);
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		if (D_S[j].drv_id==-1) continue;
-		del_gendisk(D_S[j].disk);
-		put_disk(D_S[j].disk);
-		vfree(D_S[j].sbp_buf);
-		if (D_S[j].sbp_audsiz>0)
-			vfree(D_S[j].aud_buf);
-		if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
-		{
-			msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
-			return;
-		}
-		vfree(D_S[j].sbpcd_infop);
-	}
-	msg(DBG_INF, "%s module released.\n", major_name);
-}
-
-
-module_init(__sbpcd_init) /*HACK!*/;
-module_exit(sbpcd_exit);
-
-
-#endif /* MODULE */
-static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	msg(DBG_CHK,"media_check (%s) called\n", cdi->name);
-	
-	if (p->CD_changed==0xFF)
-        {
-                p->CD_changed=0;
-                msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
-		current_drive->diskstate_flags &= ~toc_bit;
-		/* we *don't* need invalidate here, it's done by caller */
-		current_drive->diskstate_flags &= ~cd_size_bit;
-#ifdef SAFE_MIXED
-		current_drive->has_data=0;
-#endif /* SAFE_MIXED */ 
-
-                return (1);
-        }
-        else
-                return (0);
-}
-
-MODULE_LICENSE("GPL");
-/* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but
-   AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */
-MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR);
-
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file. 
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
-
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
deleted file mode 100644
index 2f2225f..0000000
--- a/drivers/cdrom/sbpcd.h
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * sbpcd.h   Specify interface address and interface type here.
- */
-
-/*
- * Attention! This file contains user-serviceable parts!
- * I recommend to make use of it...
- * If you feel helpless, look into Documentation/cdrom/sbpcd
- * (good idea anyway, at least before mailing me).
- *
- * The definitions for the first controller can get overridden by
- * the kernel command line ("lilo boot option").
- * Examples:
- *                                 sbpcd=0x300,LaserMate
- *                             or
- *                                 sbpcd=0x230,SoundBlaster
- *                             or
- *                                 sbpcd=0x338,SoundScape
- *                             or
- *                                 sbpcd=0x2C0,Teac16bit
- *
- * If sbpcd gets used as a module, you can load it with
- *     insmod sbpcd.o sbpcd=0x300,0
- * or
- *     insmod sbpcd.o sbpcd=0x230,1
- * or
- *     insmod sbpcd.o sbpcd=0x338,2
- * or
- *     insmod sbpcd.o sbpcd=0x2C0,3
- * respective to override the configured address and type.
- */
-
-/*
- * define your CDROM port base address as CDROM_PORT
- * and specify the type of your interface card as SBPRO.
- *
- * address:
- * ========
- * SBPRO type addresses typically are 0x0230 (=0x220+0x10), 0x0250, ...
- * LASERMATE type (CI-101P, WDH-7001C) addresses typically are 0x0300, ...
- * SOUNDSCAPE addresses are from the LASERMATE type and range. You have to
- * specify the REAL address here, not the configuration port address. Look
- * at the CDROM driver's invoking line within your DOS CONFIG.SYS, or let
- * sbpcd auto-probe, if you are not firm with the address.
- * There are some soundcards on the market with 0x0630, 0x0650, ...; their
- * type is not obvious (both types are possible).
- *
- * example: if your SBPRO audio address is 0x220, specify 0x230 and SBPRO 1.
- *          if your soundcard has its CDROM port above 0x300, specify
- *          that address and try SBPRO 0 first.
- *          if your SoundScape configuration port is at 0x330, specify
- *          0x338 and SBPRO 2.
- *
- * interface type:
- * ===============
- * set SBPRO to 1 for "true" SoundBlaster card
- * set SBPRO to 0 for "compatible" soundcards and
- *                for "poor" (no sound) interface cards.
- * set SBPRO to 2 for Ensonic SoundScape or SPEA Media FX cards
- * set SBPRO to 3 for Teac 16bit interface cards
- *
- * Almost all "compatible" sound boards need to set SBPRO to 0.
- * If SBPRO is set wrong, the drives will get found - but any
- * data access will give errors (audio access will work).
- * The "OmniCD" no-sound interface card from CreativeLabs and most Teac
- * interface cards need SBPRO 1.
- *
- * sound base:
- * ===========
- * The SOUND_BASE definition tells if we should try to turn the CD sound
- * channels on. It will only be of use regarding soundcards with a SbPro
- * compatible mixer.
- *
- * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels
- *          #define SOUND_BASE 0     leaves the soundcard untouched
- */
-#define CDROM_PORT 0x340 /* <-----------<< port address                      */
-#define SBPRO      0     /* <-----------<< interface type                    */
-#define MAX_DRIVES 4     /* set to 1 if the card does not use "drive select" */
-#define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0   */
-
-/*
- * some more or less user dependent definitions - service them!
- */
-
-/* Set this to 0 once you have configured your interface definitions right. */
-#define DISTRIBUTION 1
-
-/*
- * Time to wait after giving a message.
- * This gets important if you enable non-standard DBG_xxx flags.
- * You will see what happens if you omit the pause or make it
- * too short. Be warned!
- */
-#define KLOGD_PAUSE 1
-
-/* tray control: eject tray if no disk is in */
-#if DISTRIBUTION
-#define JUKEBOX 0
-#else
-#define JUKEBOX 1
-#endif /* DISTRIBUTION */
-
-/* tray control: eject tray after last use */
-#if DISTRIBUTION
-#define EJECT 0
-#else
-#define EJECT 1
-#endif /* DISTRIBUTION */
-
-/* max. number of audio frames to read with one     */
-/* request (allocates n* 2352 bytes kernel memory!) */
-/* may be freely adjusted, f.e. 75 (= 1 sec.), at   */
-/* runtime by use of the CDROMAUDIOBUFSIZ ioctl.    */
-#define READ_AUDIO 0
-
-/* Optimizations for the Teac CD-55A drive read performance.
- * SBP_TEAC_SPEED can be changed here, or one can set the 
- * variable "teac" when loading as a module.
- * Valid settings are:
- *   0 - very slow - the recommended "DISTRIBUTION 1" setup.
- *   1 - 2x performance with little overhead. No busy waiting.
- *   2 - 4x performance with 5ms overhead per read. Busy wait.
- *
- * Setting SBP_TEAC_SPEED or the variable 'teac' to anything
- * other than 0 may cause problems. If you run into them, first
- * change SBP_TEAC_SPEED back to 0 and see if your drive responds
- * normally. If yes, you are "allowed" to report your case - to help
- * me with the driver, not to solve your hassle. Don´t mail if you
- * simply are stuck into your own "tuning" experiments, you know?
- */
-#define SBP_TEAC_SPEED 1
-
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * nothing to change below here if you are not fully aware what you're doing
- */
-#ifndef _LINUX_SBPCD_H
-
-#define _LINUX_SBPCD_H
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * driver's own read_ahead, data mode
- */
-#define SBP_BUFFER_FRAMES 8 
-
-#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
-#undef  FUTURE
-#undef SAFE_MIXED
-
-#define TEST_UPC 0
-#define SPEA_TEST 0
-#define TEST_STI 0
-#define OLD_BUSY 0
-#undef PATH_CHECK
-#ifndef SOUND_BASE
-#define SOUND_BASE 0
-#endif
-#if DISTRIBUTION
-#undef SBP_TEAC_SPEED
-#define SBP_TEAC_SPEED 0
-#endif
-/*==========================================================================*/
-/*
- * DDI interface definitions
- * "invented" by Fred N. van Kempen..
- */
-#define DDIOCSDBG	0x9000
-
-/*==========================================================================*/
-/*
- * "private" IOCTL functions
- */
-#define CDROMAUDIOBUFSIZ	0x5382 /* set the audio buffer size */
-
-/*==========================================================================*/
-/*
- * Debug output levels
- */
-#define DBG_INF	1	/* necessary information */
-#define DBG_BSZ	2	/* BLOCK_SIZE trace */
-#define DBG_REA	3	/* READ status trace */
-#define DBG_CHK	4	/* MEDIA CHECK trace */
-#define DBG_TIM	5	/* datarate timer test */
-#define DBG_INI	6	/* initialization trace */
-#define DBG_TOC	7	/* tell TocEntry values */
-#define DBG_IOC	8	/* ioctl trace */
-#define DBG_STA	9	/* ResponseStatus() trace */
-#define DBG_ERR	10	/* cc_ReadError() trace */
-#define DBG_CMD	11	/* cmd_out() trace */
-#define DBG_WRN	12	/* give explanation before auto-probing */
-#define DBG_MUL	13	/* multi session code test */
-#define DBG_IDX	14	/* test code for drive_id !=0 */
-#define DBG_IOX	15	/* some special information */
-#define DBG_DID	16	/* drive ID test */
-#define DBG_RES	17	/* drive reset info */
-#define DBG_SPI	18	/* SpinUp test */
-#define DBG_IOS	19	/* ioctl trace: subchannel functions */
-#define DBG_IO2	20	/* ioctl trace: general */
-#define DBG_UPC	21	/* show UPC information */
-#define DBG_XA1	22	/* XA mode debugging */
-#define DBG_LCK	23	/* door (un)lock info */
-#define DBG_SQ1	24	/* dump SubQ frame */
-#define DBG_AUD	25	/* READ AUDIO debugging */
-#define DBG_SEQ	26	/* Sequoia interface configuration trace */
-#define DBG_LCS	27	/* Longshine LCS-7260 debugging trace */
-#define DBG_CD2	28	/* MKE/Funai CD200 debugging trace */
-#define DBG_TEA	29	/* TEAC CD-55A debugging trace */
-#define DBG_ECS	30	/* ECS-AT (Vertos 100) debugging trace */
-#define DBG_000	31	/* unnecessary information */
-
-/*==========================================================================*/
-/*==========================================================================*/
-
-/*
- * bits of flags_cmd_out:
- */
-#define f_respo3		0x100
-#define f_putcmd		0x80
-#define f_respo2		0x40
-#define f_lopsta		0x20
-#define f_getsta		0x10
-#define f_ResponseStatus	0x08
-#define f_obey_p_check		0x04
-#define f_bit1			0x02
-#define f_wait_if_busy		0x01
-
-/*
- * diskstate_flags:
- */
-#define x80_bit			0x80
-#define upc_bit			0x40
-#define volume_bit		0x20
-#define toc_bit			0x10
-#define multisession_bit	0x08
-#define cd_size_bit		0x04
-#define subq_bit		0x02
-#define frame_size_bit		0x01
-
-/*
- * disk states (bits of diskstate_flags):
- */
-#define upc_valid		(current_drive->diskstate_flags&upc_bit)
-#define volume_valid		(current_drive->diskstate_flags&volume_bit)
-#define toc_valid		(current_drive->diskstate_flags&toc_bit)
-#define cd_size_valid		(current_drive->diskstate_flags&cd_size_bit)
-#define subq_valid		(current_drive->diskstate_flags&subq_bit)
-#define frame_size_valid	(current_drive->diskstate_flags&frame_size_bit)
-
-/*
- * the status_bits variable
- */
-#define p_success	0x100
-#define p_door_closed	0x80
-#define p_caddy_in	0x40
-#define p_spinning	0x20
-#define p_check		0x10
-#define p_busy_new	0x08
-#define p_door_locked	0x04
-#define p_disk_ok	0x01
-
-/*
- * LCS-7260 special status result bits:
- */
-#define p_lcs_door_locked	0x02
-#define p_lcs_door_closed	0x01 /* probably disk_in */
-
-/*
- * CR-52x special status result bits:
- */
-#define p_caddin_old	0x40
-#define p_success_old	0x08
-#define p_busy_old	0x04
-#define p_bit_1		0x02	/* hopefully unused now */
-
-/*
- * "generation specific" defs of the status result bits:
- */
-#define p0_door_closed	0x80
-#define p0_caddy_in	0x40
-#define p0_spinning	0x20
-#define p0_check	0x10
-#define p0_success	0x08 /* unused */
-#define p0_busy		0x04
-#define p0_bit_1	0x02 /* unused */
-#define p0_disk_ok	0x01
-
-#define pL_disk_in	0x40
-#define pL_spinning	0x20
-#define pL_check	0x10
-#define pL_success	0x08 /* unused ?? */
-#define pL_busy		0x04
-#define pL_door_locked	0x02
-#define pL_door_closed	0x01
-
-#define pV_door_closed	0x40
-#define pV_spinning	0x20
-#define pV_check	0x10
-#define pV_success	0x08
-#define pV_busy		0x04
-#define pV_door_locked	0x02
-#define pV_disk_ok	0x01
-
-#define p1_door_closed	0x80
-#define p1_disk_in	0x40
-#define p1_spinning	0x20
-#define p1_check	0x10
-#define p1_busy		0x08
-#define p1_door_locked	0x04
-#define p1_bit_1	0x02 /* unused */
-#define p1_disk_ok	0x01
-
-#define p2_disk_ok	0x80
-#define p2_door_locked	0x40
-#define p2_spinning	0x20
-#define p2_busy2	0x10
-#define p2_busy1	0x08
-#define p2_door_closed	0x04
-#define p2_disk_in	0x02
-#define p2_check	0x01
-
-/*
- * used drive states:
- */
-#define st_door_closed	(current_drive->status_bits&p_door_closed)
-#define st_caddy_in	(current_drive->status_bits&p_caddy_in)
-#define st_spinning	(current_drive->status_bits&p_spinning)
-#define st_check	(current_drive->status_bits&p_check)
-#define st_busy		(current_drive->status_bits&p_busy_new)
-#define st_door_locked	(current_drive->status_bits&p_door_locked)
-#define st_diskok	(current_drive->status_bits&p_disk_ok)
-
-/*
- * bits of the CDi_status register:
- */
-#define s_not_result_ready	0x04 /* 0: "result ready" */
-#define s_not_data_ready	0x02 /* 0: "data ready"   */
-#define s_attention		0x01 /* 1: "attention required" */
-/*
- * usable as:
- */
-#define DRV_ATTN	((inb(CDi_status)&s_attention)!=0)
-#define DATA_READY	((inb(CDi_status)&s_not_data_ready)==0)
-#define RESULT_READY	((inb(CDi_status)&s_not_result_ready)==0)
-
-/*
- * drive families and types (firmware versions):
- */
-#define drv_fam0	0x0100		/* CR-52x family */
-#define drv_199		(drv_fam0+0x01)	/* <200 */
-#define drv_200		(drv_fam0+0x02)	/* <201 */
-#define drv_201		(drv_fam0+0x03)	/* <210 */
-#define drv_210		(drv_fam0+0x04)	/* <211 */
-#define drv_211		(drv_fam0+0x05)	/* <300 */
-#define drv_300		(drv_fam0+0x06)	/* >=300 */
-
-#define drv_fam1	0x0200		/* CR-56x family */
-#define drv_099		(drv_fam1+0x01)	/* <100 */
-#define drv_100		(drv_fam1+0x02)	/* >=100, only 1.02 and 5.00 known */
-
-#define drv_fam2	0x0400		/* CD200 family */
-
-#define drv_famT	0x0800		/* TEAC CD-55A */
-
-#define drv_famL	0x1000		/* Longshine family */
-#define drv_260		(drv_famL+0x01)	/* LCS-7260 */
-#define drv_e1		(drv_famL+0x01)	/* LCS-7260, firmware "A E1" */
-#define drv_f4		(drv_famL+0x02)	/* LCS-7260, firmware "A4F4" */
-
-#define drv_famV	0x2000		/* ECS-AT (vertos-100) family */
-#define drv_at		(drv_famV+0x01)	/* ECS-AT, firmware "1.00" */
-
-#define fam0_drive	(current_drive->drv_type&drv_fam0)
-#define famL_drive	(current_drive->drv_type&drv_famL)
-#define famV_drive	(current_drive->drv_type&drv_famV)
-#define fam1_drive	(current_drive->drv_type&drv_fam1)
-#define fam2_drive	(current_drive->drv_type&drv_fam2)
-#define famT_drive	(current_drive->drv_type&drv_famT)
-#define fam0L_drive	(current_drive->drv_type&(drv_fam0|drv_famL))
-#define fam0V_drive	(current_drive->drv_type&(drv_fam0|drv_famV))
-#define famLV_drive	(current_drive->drv_type&(drv_famL|drv_famV))
-#define fam0LV_drive	(current_drive->drv_type&(drv_fam0|drv_famL|drv_famV))
-#define fam1L_drive	(current_drive->drv_type&(drv_fam1|drv_famL))
-#define fam1V_drive	(current_drive->drv_type&(drv_fam1|drv_famV))
-#define fam1LV_drive	(current_drive->drv_type&(drv_fam1|drv_famL|drv_famV))
-#define fam01_drive	(current_drive->drv_type&(drv_fam0|drv_fam1))
-#define fam12_drive	(current_drive->drv_type&(drv_fam1|drv_fam2))
-#define fam2T_drive	(current_drive->drv_type&(drv_fam2|drv_famT))
-
-/*
- * audio states:
- */
-#define audio_completed	3 /* Forgot this one! --AJK */
-#define audio_playing	2
-#define audio_pausing	1
-
-/*
- * drv_pattern, drv_options:
- */
-#define speed_auto	0x80
-#define speed_300	0x40
-#define speed_150	0x20
-#define audio_mono	0x04
-
-/*
- * values of cmd_type (0 else):
- */
-#define READ_M1	0x01	/* "data mode 1": 2048 bytes per frame */
-#define READ_M2	0x02	/* "data mode 2": 12+2048+280 bytes per frame */
-#define READ_SC	0x04	/* "subchannel info": 96 bytes per frame */
-#define READ_AU	0x08	/* "audio frame": 2352 bytes per frame */
-
-/*
- * sense_byte:
- *
- *          values: 00
- *                  01
- *                  81
- *                  82 "raw audio" mode
- *                  xx from infobuf[0] after 85 00 00 00 00 00 00
- */
-
-/* audio status (bin) */
-#define aud_00 0x00 /* Audio status byte not supported or not valid */
-#define audx11 0x0b /* Audio play operation in progress             */
-#define audx12 0x0c /* Audio play operation paused                  */
-#define audx13 0x0d /* Audio play operation successfully completed  */
-#define audx14 0x0e /* Audio play operation stopped due to error    */
-#define audx15 0x0f /* No current audio status to return            */
-/* audio status (bcd) */
-#define aud_11 0x11 /* Audio play operation in progress             */
-#define aud_12 0x12 /* Audio play operation paused                  */
-#define aud_13 0x13 /* Audio play operation successfully completed  */
-#define aud_14 0x14 /* Audio play operation stopped due to error    */
-#define aud_15 0x15 /* No current audio status to return            */
-
-/*
- * highest allowed drive number (MINOR+1)
- */
-#define NR_SBPCD	4
-
-/*
- * we try to never disable interrupts - seems to work
- */
-#define SBPCD_DIS_IRQ	0
-
-/*
- * "write byte to port"
- */
-#define OUT(x,y)	outb(y,x)
-
-/*==========================================================================*/
-
-#define MIXER_addr SOUND_BASE+4 /* sound card's address register */
-#define MIXER_data SOUND_BASE+5 /* sound card's data register */
-#define MIXER_CD_Volume	0x28	/* internal SB Pro register address */
-
-/*==========================================================================*/
-
-#define MAX_TRACKS	99
-
-#define ERR_DISKCHANGE 615
-
-/*==========================================================================*/
-/*
- * To make conversions easier (machine dependent!)
- */
-typedef union _msf
-{
-	u_int n;
-	u_char c[4];
-} MSF;
-
-typedef union _blk
-{
-	u_int n;
-	u_char c[4];
-} BLK;
-
-/*==========================================================================*/
-
-/*============================================================================
-==============================================================================
-
-COMMAND SET of "old" drives like CR-521, CR-522
-               (the CR-562 family is different):
-
-No.	Command			       Code
---------------------------------------------
-
-Drive Commands:
- 1	Seek				01	
- 2	Read Data			02
- 3	Read XA-Data			03
- 4	Read Header			04
- 5	Spin Up				05
- 6	Spin Down			06
- 7	Diagnostic			07
- 8	Read UPC			08
- 9	Read ISRC			09
-10	Play Audio			0A
-11	Play Audio MSF			0B
-12	Play Audio Track/Index		0C
-
-Status Commands:
-13	Read Status			81	
-14	Read Error			82
-15	Read Drive Version		83
-16	Mode Select			84
-17	Mode Sense			85
-18	Set XA Parameter		86
-19	Read XA Parameter		87
-20	Read Capacity			88
-21	Read SUB_Q			89
-22	Read Disc Code			8A
-23	Read Disc Information		8B
-24	Read TOC			8C
-25	Pause/Resume			8D
-26	Read Packet			8E
-27	Read Path Check			00
- 
- 
-all numbers (lba, msf-bin, msf-bcd, counts) to transfer high byte first
-
-mnemo     7-byte command        #bytes response (r0...rn)
-________ ____________________  ____ 
-
-Read Status:
-status:  81.                    (1)  one-byte command, gives the main
-                                                          status byte
-Read Error:
-check1:  82 00 00 00 00 00 00.  (6)  r1: audio status
-
-Read Packet:
-check2:  8e xx 00 00 00 00 00. (xx)  gets xx bytes response, relating
-                                        to commands 01 04 05 07 08 09
-
-Play Audio:
-play:    0a ll-bb-aa nn-nn-nn.  (0)  play audio, ll-bb-aa: starting block (lba),
-                                                 nn-nn-nn: #blocks
-Play Audio MSF:
-         0b mm-ss-ff mm-ss-ff   (0)  play audio from/to
-
-Play Audio Track/Index:
-         0c ...
-
-Pause/Resume:
-pause:   8d pr 00 00 00 00 00.  (0)  pause (pr=00) 
-                                     resume (pr=80) audio playing
-
-Mode Select:
-         84 00 nn-nn ??.?? 00   (0)  nn-nn: 2048 or 2340
-                                     possibly defines transfer size
-
-set_vol: 84 83 00 00 sw le 00.  (0)  sw(itch): lrxxxxxx (off=1)
-                                     le(vel): min=0, max=FF, else half
-				     (firmware 2.11)
-
-Mode Sense:
-get_vol: 85 03 00 00 00 00 00.  (2)  tell current audio volume setting
-
-Read Disc Information:
-tocdesc: 8b 00 00 00 00 00 00.  (6)  read the toc descriptor ("msf-bin"-format)
-
-Read TOC:
-tocent:  8c fl nn 00 00 00 00.  (8)  read toc entry #nn
-                                       (fl=0:"lba"-, =2:"msf-bin"-format)
-
-Read Capacity:
-capacit: 88 00 00 00 00 00 00.  (5)  "read CD-ROM capacity"
-
-
-Read Path Check:
-ping:    00 00 00 00 00 00 00.  (2)  r0=AA, r1=55
-                                     ("ping" if the drive is connected)
-
-Read Drive Version:
-ident:   83 00 00 00 00 00 00. (12)  gives "MATSHITAn.nn" 
-                                     (n.nn = 2.01, 2.11., 3.00, ...)
-
-Seek:
-seek:    01 00 ll-bb-aa 00 00.  (0)  
-seek:    01 02 mm-ss-ff 00 00.  (0)  
-
-Read Data:
-read:    02 xx-xx-xx nn-nn fl.  (?)  read nn-nn blocks of 2048 bytes,
-                                     starting at block xx-xx-xx  
-                                     fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read XA-Data:
-read:    03 xx-xx-xx nn-nn fl.  (?)  read nn-nn blocks of 2340 bytes, 
-                                     starting at block xx-xx-xx
-                                     fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read SUB_Q:
-         89 fl 00 00 00 00 00. (13)  r0: audio status, r4-r7: lba/msf, 
-                                       fl=0: "lba", fl=2: "msf"
-
-Read Disc Code:
-         8a 00 00 00 00 00 00. (14)  possibly extended "check condition"-info
-
-Read Header:
-         04 00 ll-bb-aa 00 00.  (0)   4 bytes response with "check2"
-         04 02 mm-ss-ff 00 00.  (0)   4 bytes response with "check2"
-
-Spin Up:
-         05 00 ll-bb-aa 00 00.  (0)  possibly implies a "seek"
-
-Spin Down:
-         06 ...
-
-Diagnostic:
-         07 00 ll-bb-aa 00 00.  (2)   2 bytes response with "check2"
-         07 02 mm-ss-ff 00 00.  (2)   2 bytes response with "check2"
-
-Read UPC:
-         08 00 ll-bb-aa 00 00. (16)  
-         08 02 mm-ss-ff 00 00. (16)  
-
-Read ISRC:
-         09 00 ll-bb-aa 00 00. (15)  15 bytes response with "check2"
-         09 02 mm-ss-ff 00 00. (15)  15 bytes response with "check2"
-
-Set XA Parameter:
-         86 ...
-
-Read XA Parameter:
-         87 ...
-
-==============================================================================
-============================================================================*/
-
-/*
- * commands
- *
- * CR-52x:      CMD0_
- * CR-56x:      CMD1_
- * CD200:       CMD2_
- * LCS-7260:    CMDL_
- * TEAC CD-55A: CMDT_
- * ECS-AT:      CMDV_
- */
-#define CMD1_RESET	0x0a
-#define CMD2_RESET	0x01
-#define CMDT_RESET	0xc0
-
-#define CMD1_LOCK_CTL	0x0c
-#define CMD2_LOCK_CTL	0x1e
-#define CMDT_LOCK_CTL	CMD2_LOCK_CTL
-#define CMDL_LOCK_CTL	0x0e
-#define CMDV_LOCK_CTL	CMDL_LOCK_CTL
-
-#define CMD1_TRAY_CTL	0x07
-#define CMD2_TRAY_CTL	0x1b
-#define CMDT_TRAY_CTL	CMD2_TRAY_CTL
-#define CMDL_TRAY_CTL	0x0d
-#define CMDV_TRAY_CTL	CMDL_TRAY_CTL
-
-#define CMD1_MULTISESS	0x8d
-#define CMDL_MULTISESS	0x8c
-#define CMDV_MULTISESS	CMDL_MULTISESS
-
-#define CMD1_SUBCHANINF	0x11
-#define CMD2_SUBCHANINF	0x??
-
-#define CMD1_ABORT	0x08
-#define CMD2_ABORT	0x08
-#define CMDT_ABORT	0x08
-
-#define CMD2_x02	0x02
-
-#define CMD2_SETSPEED	0xda
-
-#define CMD0_PATH_CHECK	0x00
-#define CMD1_PATH_CHECK	0x???
-#define CMD2_PATH_CHECK	0x???
-#define CMDT_PATH_CHECK	0x???
-#define CMDL_PATH_CHECK	CMD0_PATH_CHECK
-#define CMDV_PATH_CHECK	CMD0_PATH_CHECK
-
-#define CMD0_SEEK	0x01
-#define CMD1_SEEK	CMD0_SEEK
-#define CMD2_SEEK	0x2b
-#define CMDT_SEEK	CMD2_SEEK
-#define CMDL_SEEK	CMD0_SEEK
-#define CMDV_SEEK	CMD0_SEEK
-
-#define CMD0_READ	0x02
-#define CMD1_READ	0x10
-#define CMD2_READ	0x28
-#define CMDT_READ	CMD2_READ
-#define CMDL_READ	CMD0_READ
-#define CMDV_READ	CMD0_READ
-
-#define CMD0_READ_XA	0x03
-#define CMD2_READ_XA	0xd4
-#define CMD2_READ_XA2	0xd5
-#define CMDL_READ_XA	CMD0_READ_XA /* really ?? */
-#define CMDV_READ_XA	CMD0_READ_XA
-
-#define CMD0_READ_HEAD	0x04
-
-#define CMD0_SPINUP	0x05
-#define CMD1_SPINUP	0x02
-#define CMD2_SPINUP	CMD2_TRAY_CTL
-#define CMDL_SPINUP	CMD0_SPINUP
-#define CMDV_SPINUP	CMD0_SPINUP
-
-#define CMD0_SPINDOWN	0x06 /* really??? */
-#define CMD1_SPINDOWN	0x06
-#define CMD2_SPINDOWN	CMD2_TRAY_CTL
-#define CMDL_SPINDOWN	0x0d
-#define CMDV_SPINDOWN	CMD0_SPINDOWN
-
-#define CMD0_DIAG	0x07
-
-#define CMD0_READ_UPC	0x08
-#define CMD1_READ_UPC	0x88
-#define CMD2_READ_UPC	0x???
-#define CMDL_READ_UPC	CMD0_READ_UPC
-#define CMDV_READ_UPC	0x8f
-
-#define CMD0_READ_ISRC	0x09
-
-#define CMD0_PLAY	0x0a
-#define CMD1_PLAY	0x???
-#define CMD2_PLAY	0x???
-#define CMDL_PLAY	CMD0_PLAY
-#define CMDV_PLAY	CMD0_PLAY
-
-#define CMD0_PLAY_MSF	0x0b
-#define CMD1_PLAY_MSF	0x0e
-#define CMD2_PLAY_MSF	0x47
-#define CMDT_PLAY_MSF	CMD2_PLAY_MSF
-#define CMDL_PLAY_MSF	0x???
-
-#define CMD0_PLAY_TI	0x0c
-#define CMD1_PLAY_TI	0x0f
-
-#define CMD0_STATUS	0x81
-#define CMD1_STATUS	0x05
-#define CMD2_STATUS	0x00
-#define CMDT_STATUS	CMD2_STATUS
-#define CMDL_STATUS	CMD0_STATUS
-#define CMDV_STATUS	CMD0_STATUS
-#define CMD2_SEEK_LEADIN 0x00
-
-#define CMD0_READ_ERR	0x82
-#define CMD1_READ_ERR	CMD0_READ_ERR
-#define CMD2_READ_ERR	0x03
-#define CMDT_READ_ERR	CMD2_READ_ERR /* get audio status */
-#define CMDL_READ_ERR	CMD0_READ_ERR
-#define CMDV_READ_ERR	CMD0_READ_ERR
-
-#define CMD0_READ_VER	0x83
-#define CMD1_READ_VER	CMD0_READ_VER
-#define CMD2_READ_VER	0x12
-#define CMDT_READ_VER	CMD2_READ_VER /* really ?? */
-#define CMDL_READ_VER	CMD0_READ_VER
-#define CMDV_READ_VER	CMD0_READ_VER
-
-#define CMD0_SETMODE	0x84
-#define CMD1_SETMODE	0x09
-#define CMD2_SETMODE	0x55
-#define CMDT_SETMODE	CMD2_SETMODE
-#define CMDL_SETMODE	CMD0_SETMODE
-
-#define CMD0_GETMODE	0x85
-#define CMD1_GETMODE	0x84
-#define CMD2_GETMODE	0x5a
-#define CMDT_GETMODE	CMD2_GETMODE
-#define CMDL_GETMODE	CMD0_GETMODE
-
-#define CMD0_SET_XA	0x86
-
-#define CMD0_GET_XA	0x87
-
-#define CMD0_CAPACITY	0x88
-#define CMD1_CAPACITY	0x85
-#define CMD2_CAPACITY	0x25
-#define CMDL_CAPACITY	CMD0_CAPACITY /* missing in some firmware versions */
-
-#define CMD0_READSUBQ	0x89
-#define CMD1_READSUBQ	0x87
-#define CMD2_READSUBQ	0x42
-#define CMDT_READSUBQ	CMD2_READSUBQ
-#define CMDL_READSUBQ	CMD0_READSUBQ
-#define CMDV_READSUBQ	CMD0_READSUBQ
-
-#define CMD0_DISKCODE	0x8a
-
-#define CMD0_DISKINFO	0x8b
-#define CMD1_DISKINFO	CMD0_DISKINFO
-#define CMD2_DISKINFO	0x43
-#define CMDT_DISKINFO	CMD2_DISKINFO
-#define CMDL_DISKINFO	CMD0_DISKINFO
-#define CMDV_DISKINFO	CMD0_DISKINFO
-
-#define CMD0_READTOC	0x8c
-#define CMD1_READTOC	CMD0_READTOC
-#define CMD2_READTOC	0x???
-#define CMDL_READTOC	CMD0_READTOC
-#define CMDV_READTOC	CMD0_READTOC
-
-#define CMD0_PAU_RES	0x8d
-#define CMD1_PAU_RES	0x0d
-#define CMD2_PAU_RES	0x4b
-#define CMDT_PAUSE	CMD2_PAU_RES
-#define CMDL_PAU_RES	CMD0_PAU_RES
-#define CMDV_PAUSE	CMD0_PAU_RES
-
-#define CMD0_PACKET	0x8e
-#define CMD1_PACKET	CMD0_PACKET
-#define CMD2_PACKET	0x???
-#define CMDL_PACKET	CMD0_PACKET
-#define CMDV_PACKET	0x???
-
-/*==========================================================================*/
-/*==========================================================================*/
-#endif /* _LINUX_SBPCD_H */
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file. 
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
deleted file mode 100644
index 5409fca..0000000
--- a/drivers/cdrom/sjcd.c
+++ /dev/null
@@ -1,1815 +0,0 @@
-/* -- sjcd.c
- *
- *   Sanyo CD-ROM device driver implementation, Version 1.6
- *   Copyright (C) 1995  Vadim V. Model
- *
- *   model@cecmow.enet.dec.com
- *   vadim@rbrf.ru
- *   vadim@ipsun.ras.ru
- *
- *
- *  This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
- *  it was developed under use of mcd.c from Martin Harriss, with help of
- *  Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl).
- *
- *  It is planned to include these routines into sbpcd.c later - to make
- *  a "mixed use" on one cable possible for all kinds of drives which use
- *  the SoundBlaster/Panasonic style CDROM interface. But today, the
- *  ability to install directly from CDROM is more important than flexibility.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History:
- *  1.1 First public release with kernel version 1.3.7.
- *      Written by Vadim Model.
- *  1.2 Added detection and configuration of cdrom interface
- *      on ISP16 soundcard.
- *      Allow for command line options: sjcd=<io_base>,<irq>,<dma>
- *  1.3 Some minor changes to README.sjcd.
- *  1.4 MSS Sound support!! Listen to a CD through the speakers.
- *  1.5 Module support and bugfixes.
- *      Tray locking.
- *  1.6 Removed ISP16 code from this driver.
- *      Allow only to set io base address on command line: sjcd=<io_base>
- *      Changes to Documentation/cdrom/sjcd
- *      Added cleanup after any error in the initialisation.
- *  1.7 Added code to set the sector size tables to prevent the bug present in 
- *      the previous version of this driver.  Coded added by Anthony Barbachan 
- *      from bugfix tip originally suggested by Alan Cox.
- *
- *  November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	             Removed init_module & cleanup_module in favor of 
- *	             module_init & module_exit.
- *	             Torben Mathiasen <tmm@image.dk>
- */
-
-#define SJCD_VERSION_MAJOR 1
-#define SJCD_VERSION_MINOR 7
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-#include "sjcd.h"
-
-static int sjcd_present = 0;
-static struct request_queue *sjcd_queue;
-
-#define MAJOR_NR SANYO_CDROM_MAJOR
-#define QUEUE (sjcd_queue)
-#define CURRENT elv_next_request(sjcd_queue)
-
-#define SJCD_BUF_SIZ 32		/* cdr-h94a has internal 64K buffer */
-
-/*
- * buffer for block size conversion
- */
-static char sjcd_buf[2048 * SJCD_BUF_SIZ];
-static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn;
-static volatile int sjcd_buf_in, sjcd_buf_out = -1;
-
-/*
- * Status.
- */
-static unsigned short sjcd_status_valid = 0;
-static unsigned short sjcd_door_closed;
-static unsigned short sjcd_door_was_open;
-static unsigned short sjcd_media_is_available;
-static unsigned short sjcd_media_is_changed;
-static unsigned short sjcd_toc_uptodate = 0;
-static unsigned short sjcd_command_failed;
-static volatile unsigned char sjcd_completion_status = 0;
-static volatile unsigned char sjcd_completion_error = 0;
-static unsigned short sjcd_command_is_in_progress = 0;
-static unsigned short sjcd_error_reported = 0;
-static DEFINE_SPINLOCK(sjcd_lock);
-
-static int sjcd_open_count;
-
-static int sjcd_audio_status;
-static struct sjcd_play_msf sjcd_playing;
-
-static int sjcd_base = SJCD_BASE_ADDR;
-
-module_param(sjcd_base, int, 0);
-
-static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
-
-/*
- * Data transfer.
- */
-static volatile unsigned short sjcd_transfer_is_active = 0;
-
-enum sjcd_transfer_state {
-	SJCD_S_IDLE = 0,
-	SJCD_S_START = 1,
-	SJCD_S_MODE = 2,
-	SJCD_S_READ = 3,
-	SJCD_S_DATA = 4,
-	SJCD_S_STOP = 5,
-	SJCD_S_STOPPING = 6
-};
-static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
-static long sjcd_transfer_timeout = 0;
-static int sjcd_read_count = 0;
-static unsigned char sjcd_mode = 0;
-
-#define SJCD_READ_TIMEOUT 5000
-
-#if defined( SJCD_GATHER_STAT )
-/*
- * Statistic.
- */
-static struct sjcd_stat statistic;
-#endif
-
-/*
- * Timer.
- */
-static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
-
-#define SJCD_SET_TIMER( func, tmout )           \
-    ( sjcd_delay_timer.expires = jiffies+tmout,         \
-      sjcd_delay_timer.function = ( void * )func, \
-      add_timer( &sjcd_delay_timer ) )
-
-#define CLEAR_TIMER del_timer( &sjcd_delay_timer )
-
-/*
- * Set up device, i.e., use command line data to set
- * base address.
- */
-#ifndef MODULE
-static int __init sjcd_setup(char *str)
-{
-	int ints[2];
-	(void) get_options(str, ARRAY_SIZE(ints), ints);
-	if (ints[0] > 0)
-		sjcd_base = ints[1];
-
-	return 1;
-}
-
-__setup("sjcd=", sjcd_setup);
-
-#endif
-
-/*
- * Special converters.
- */
-static unsigned char bin2bcd(int bin)
-{
-	int u, v;
-
-	u = bin % 10;
-	v = bin / 10;
-	return (u | (v << 4));
-}
-
-static int bcd2bin(unsigned char bcd)
-{
-	return ((bcd >> 4) * 10 + (bcd & 0x0F));
-}
-
-static long msf2hsg(struct msf *mp)
-{
-	return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75
-		+ bcd2bin(mp->min) * 4500 - 150);
-}
-
-static void hsg2msf(long hsg, struct msf *msf)
-{
-	hsg += 150;
-	msf->min = hsg / 4500;
-	hsg %= 4500;
-	msf->sec = hsg / 75;
-	msf->frame = hsg % 75;
-	msf->min = bin2bcd(msf->min);	/* convert to BCD */
-	msf->sec = bin2bcd(msf->sec);
-	msf->frame = bin2bcd(msf->frame);
-}
-
-/*
- * Send a command to cdrom. Invalidate status.
- */
-static void sjcd_send_cmd(unsigned char cmd)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: send_cmd( 0x%x )\n", cmd);
-#endif
-	outb(cmd, SJCDPORT(0));
-	sjcd_command_is_in_progress = 1;
-	sjcd_status_valid = 0;
-	sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with one arg to cdrom. Invalidate status.
- */
-static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a);
-#endif
-	outb(cmd, SJCDPORT(0));
-	outb(a, SJCDPORT(0));
-	sjcd_command_is_in_progress = 1;
-	sjcd_status_valid = 0;
-	sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with four args to cdrom. Invalidate status.
- */
-static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a,
-			    unsigned char b, unsigned char c,
-			    unsigned char d)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: send_4_cmd( 0x%x )\n", cmd);
-#endif
-	outb(cmd, SJCDPORT(0));
-	outb(a, SJCDPORT(0));
-	outb(b, SJCDPORT(0));
-	outb(c, SJCDPORT(0));
-	outb(d, SJCDPORT(0));
-	sjcd_command_is_in_progress = 1;
-	sjcd_status_valid = 0;
-	sjcd_command_failed = 0;
-}
-
-/*
- * Send a play or read command to cdrom. Invalidate Status.
- */
-static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: send_long_cmd( 0x%x )\n", cmd);
-#endif
-	outb(cmd, SJCDPORT(0));
-	outb(pms->start.min, SJCDPORT(0));
-	outb(pms->start.sec, SJCDPORT(0));
-	outb(pms->start.frame, SJCDPORT(0));
-	outb(pms->end.min, SJCDPORT(0));
-	outb(pms->end.sec, SJCDPORT(0));
-	outb(pms->end.frame, SJCDPORT(0));
-	sjcd_command_is_in_progress = 1;
-	sjcd_status_valid = 0;
-	sjcd_command_failed = 0;
-}
-
-/*
- * Get a value from the data port. Should not block, so we use a little
- * wait for a while. Returns 0 if OK.
- */
-static int sjcd_load_response(void *buf, int len)
-{
-	unsigned char *resp = (unsigned char *) buf;
-
-	for (; len; --len) {
-		int i;
-		for (i = 200;
-		     i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))););
-		if (i > 0)
-			*resp++ = (unsigned char) inb(SJCDPORT(0));
-		else
-			break;
-	}
-	return (len);
-}
-
-/*
- * Load and parse command completion status (drive info byte and maybe error).
- * Sorry, no error classification yet.
- */
-static void sjcd_load_status(void)
-{
-	sjcd_media_is_changed = 0;
-	sjcd_completion_error = 0;
-	sjcd_completion_status = inb(SJCDPORT(0));
-	if (sjcd_completion_status & SST_DOOR_OPENED) {
-		sjcd_door_closed = sjcd_media_is_available = 0;
-	} else {
-		sjcd_door_closed = 1;
-		if (sjcd_completion_status & SST_MEDIA_CHANGED)
-			sjcd_media_is_available = sjcd_media_is_changed =
-			    1;
-		else if (sjcd_completion_status & 0x0F) {
-			/*
-			 * OK, we seem to catch an error ...
-			 */
-			while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))));
-			sjcd_completion_error = inb(SJCDPORT(0));
-			if ((sjcd_completion_status & 0x08) &&
-			    (sjcd_completion_error & 0x40))
-				sjcd_media_is_available = 0;
-			else
-				sjcd_command_failed = 1;
-		} else
-			sjcd_media_is_available = 1;
-	}
-	/*
-	 * Ok, status loaded successfully.
-	 */
-	sjcd_status_valid = 1, sjcd_error_reported = 0;
-	sjcd_command_is_in_progress = 0;
-
-	/*
-	 * If the disk is changed, the TOC is not valid.
-	 */
-	if (sjcd_media_is_changed)
-		sjcd_toc_uptodate = 0;
-#if defined( SJCD_TRACE )
-	printk("SJCD: status %02x.%02x loaded.\n",
-	       (int) sjcd_completion_status, (int) sjcd_completion_error);
-#endif
-}
-
-/*
- * Read status from cdrom. Check to see if the status is available.
- */
-static int sjcd_check_status(void)
-{
-	/*
-	 * Try to load the response from cdrom into buffer.
-	 */
-	if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) {
-		sjcd_load_status();
-		return (1);
-	} else {
-		/*
-		 * No status is available.
-		 */
-		return (0);
-	}
-}
-
-/*
- * This is just timeout counter, and nothing more. Surprised ? :-)
- */
-static volatile long sjcd_status_timeout;
-
-/*
- * We need about 10 seconds to wait. The longest command takes about 5 seconds
- * to probe the disk (usually after tray closed or drive reset). Other values
- * should be thought of for other commands.
- */
-#define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
-
-static void sjcd_status_timer(void)
-{
-	if (sjcd_check_status()) {
-		/*
-		 * The command completed and status is loaded, stop waiting.
-		 */
-		wake_up(&sjcd_waitq);
-	} else if (--sjcd_status_timeout <= 0) {
-		/*
-		 * We are timed out. 
-		 */
-		wake_up(&sjcd_waitq);
-	} else {
-		/*
-		 * We have still some time to wait. Try again.
-		 */
-		SJCD_SET_TIMER(sjcd_status_timer, 1);
-	}
-}
-
-/*
- * Wait for status for 10 sec approx. Returns non-positive when timed out.
- * Should not be used while reading data CDs.
- */
-static int sjcd_wait_for_status(void)
-{
-	sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
-	SJCD_SET_TIMER(sjcd_status_timer, 1);
-	sleep_on(&sjcd_waitq);
-#if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
-	if (sjcd_status_timeout <= 0)
-		printk("SJCD: Error Wait For Status.\n");
-#endif
-	return (sjcd_status_timeout);
-}
-
-static int sjcd_receive_status(void)
-{
-	int i;
-#if defined( SJCD_TRACE )
-	printk("SJCD: receive_status\n");
-#endif
-	/*
-	 * Wait a bit for status available.
-	 */
-	for (i = 200; i-- && (sjcd_check_status() == 0););
-	if (i < 0) {
-#if defined( SJCD_TRACE )
-		printk("SJCD: long wait for status\n");
-#endif
-		if (sjcd_wait_for_status() <= 0)
-			printk("SJCD: Timeout when read status.\n");
-		else
-			i = 0;
-	}
-	return (i);
-}
-
-/*
- * Load the status. Issue get status command and wait for status available.
- */
-static void sjcd_get_status(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: get_status\n");
-#endif
-	sjcd_send_cmd(SCMD_GET_STATUS);
-	sjcd_receive_status();
-}
-
-/*
- * Check the drive if the disk is changed. Should be revised.
- */
-static int sjcd_disk_change(struct gendisk *disk)
-{
-#if 0
-	printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name);
-#endif
-	if (!sjcd_command_is_in_progress)
-		sjcd_get_status();
-	return (sjcd_status_valid ? sjcd_media_is_changed : 0);
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary.
- * We assume that the drive contains no more than 99 toc entries.
- */
-static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS];
-static unsigned char sjcd_first_track_no, sjcd_last_track_no;
-#define sjcd_disk_length  sjcd_table_of_contents[0].un.track_msf
-
-static int sjcd_update_toc(void)
-{
-	struct sjcd_hw_disk_info info;
-	int i;
-#if defined( SJCD_TRACE )
-	printk("SJCD: update toc:\n");
-#endif
-	/*
-	 * check to see if we need to do anything
-	 */
-	if (sjcd_toc_uptodate)
-		return (0);
-
-	/*
-	 * Get the TOC start information.
-	 */
-	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK);
-	sjcd_receive_status();
-
-	if (!sjcd_status_valid) {
-		printk("SJCD: cannot load status.\n");
-		return (-1);
-	}
-
-	if (!sjcd_media_is_available) {
-		printk("SJCD: no disk in drive\n");
-		return (-1);
-	}
-
-	if (!sjcd_command_failed) {
-		if (sjcd_load_response(&info, sizeof(info)) != 0) {
-			printk
-			    ("SJCD: cannot load response about TOC start.\n");
-			return (-1);
-		}
-		sjcd_first_track_no = bcd2bin(info.un.track_no);
-	} else {
-		printk("SJCD: get first failed\n");
-		return (-1);
-	}
-#if defined( SJCD_TRACE )
-	printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no);
-#endif
-	/*
-	 * Get the TOC finish information.
-	 */
-	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK);
-	sjcd_receive_status();
-
-	if (!sjcd_status_valid) {
-		printk("SJCD: cannot load status.\n");
-		return (-1);
-	}
-
-	if (!sjcd_media_is_available) {
-		printk("SJCD: no disk in drive\n");
-		return (-1);
-	}
-
-	if (!sjcd_command_failed) {
-		if (sjcd_load_response(&info, sizeof(info)) != 0) {
-			printk
-			    ("SJCD: cannot load response about TOC finish.\n");
-			return (-1);
-		}
-		sjcd_last_track_no = bcd2bin(info.un.track_no);
-	} else {
-		printk("SJCD: get last failed\n");
-		return (-1);
-	}
-#if defined( SJCD_TRACE )
-	printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no);
-#endif
-	for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) {
-		/*
-		 * Get the first track information.
-		 */
-		sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i));
-		sjcd_receive_status();
-
-		if (!sjcd_status_valid) {
-			printk("SJCD: cannot load status.\n");
-			return (-1);
-		}
-
-		if (!sjcd_media_is_available) {
-			printk("SJCD: no disk in drive\n");
-			return (-1);
-		}
-
-		if (!sjcd_command_failed) {
-			if (sjcd_load_response(&sjcd_table_of_contents[i],
-					       sizeof(struct
-						      sjcd_hw_disk_info))
-			    != 0) {
-				printk
-				    ("SJCD: cannot load info for %d track\n",
-				     i);
-				return (-1);
-			}
-		} else {
-			printk("SJCD: get info %d failed\n", i);
-			return (-1);
-		}
-	}
-
-	/*
-	 * Get the disk length info.
-	 */
-	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE);
-	sjcd_receive_status();
-
-	if (!sjcd_status_valid) {
-		printk("SJCD: cannot load status.\n");
-		return (-1);
-	}
-
-	if (!sjcd_media_is_available) {
-		printk("SJCD: no disk in drive\n");
-		return (-1);
-	}
-
-	if (!sjcd_command_failed) {
-		if (sjcd_load_response(&info, sizeof(info)) != 0) {
-			printk
-			    ("SJCD: cannot load response about disk size.\n");
-			return (-1);
-		}
-		sjcd_disk_length.min = info.un.track_msf.min;
-		sjcd_disk_length.sec = info.un.track_msf.sec;
-		sjcd_disk_length.frame = info.un.track_msf.frame;
-	} else {
-		printk("SJCD: get size failed\n");
-		return (1);
-	}
-#if defined( SJCD_TRACE )
-	printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,
-	       sjcd_disk_length.sec, sjcd_disk_length.frame);
-#endif
-	return (0);
-}
-
-/*
- * Load subchannel information.
- */
-static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp)
-{
-	int s;
-#if defined( SJCD_TRACE )
-	printk("SJCD: load sub q\n");
-#endif
-	sjcd_send_cmd(SCMD_GET_QINFO);
-	s = sjcd_receive_status();
-	if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {
-		sjcd_send_cmd(0xF2);
-		s = sjcd_receive_status();
-		if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
-			return (-1);
-		sjcd_send_cmd(SCMD_GET_QINFO);
-		s = sjcd_receive_status();
-		if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
-			return (-1);
-	}
-	if (sjcd_media_is_available)
-		if (sjcd_load_response(qp, sizeof(*qp)) == 0)
-			return (0);
-	return (-1);
-}
-
-/*
- * Start playing from the specified position.
- */
-static int sjcd_play(struct sjcd_play_msf *mp)
-{
-	struct sjcd_play_msf msf;
-
-	/*
-	 * Turn the device to play mode.
-	 */
-	sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);
-	if (sjcd_receive_status() < 0)
-		return (-1);
-
-	/*
-	 * Seek to the starting point.
-	 */
-	msf.start = mp->start;
-	msf.end.min = msf.end.sec = msf.end.frame = 0x00;
-	sjcd_send_6_cmd(SCMD_SEEK, &msf);
-	if (sjcd_receive_status() < 0)
-		return (-1);
-
-	/*
-	 * Start playing.
-	 */
-	sjcd_send_6_cmd(SCMD_PLAY, mp);
-	return (sjcd_receive_status());
-}
-
-/*
- * Tray control functions.
- */
-static int sjcd_tray_close(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: tray_close\n");
-#endif
-	sjcd_send_cmd(SCMD_CLOSE_TRAY);
-	return (sjcd_receive_status());
-}
-
-static int sjcd_tray_lock(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: tray_lock\n");
-#endif
-	sjcd_send_cmd(SCMD_LOCK_TRAY);
-	return (sjcd_receive_status());
-}
-
-static int sjcd_tray_unlock(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: tray_unlock\n");
-#endif
-	sjcd_send_cmd(SCMD_UNLOCK_TRAY);
-	return (sjcd_receive_status());
-}
-
-static int sjcd_tray_open(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: tray_open\n");
-#endif
-	sjcd_send_cmd(SCMD_EJECT_TRAY);
-	return (sjcd_receive_status());
-}
-
-/*
- * Do some user commands.
- */
-static int sjcd_ioctl(struct inode *ip, struct file *fp,
-		      unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-#if defined( SJCD_TRACE )
-	printk("SJCD:ioctl\n");
-#endif
-
-	sjcd_get_status();
-	if (!sjcd_status_valid)
-		return (-EIO);
-	if (sjcd_update_toc() < 0)
-		return (-EIO);
-
-	switch (cmd) {
-	case CDROMSTART:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: start\n");
-#endif
-			return (0);
-		}
-
-	case CDROMSTOP:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: stop\n");
-#endif
-			sjcd_send_cmd(SCMD_PAUSE);
-			(void) sjcd_receive_status();
-			sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-			return (0);
-		}
-
-	case CDROMPAUSE:{
-			struct sjcd_hw_qinfo q_info;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: pause\n");
-#endif
-			if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
-				sjcd_send_cmd(SCMD_PAUSE);
-				(void) sjcd_receive_status();
-				if (sjcd_get_q_info(&q_info) < 0) {
-					sjcd_audio_status =
-					    CDROM_AUDIO_NO_STATUS;
-				} else {
-					sjcd_audio_status =
-					    CDROM_AUDIO_PAUSED;
-					sjcd_playing.start = q_info.abs;
-				}
-				return (0);
-			} else
-				return (-EINVAL);
-		}
-
-	case CDROMRESUME:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: resume\n");
-#endif
-			if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {
-				/*
-				 * continue play starting at saved location
-				 */
-				if (sjcd_play(&sjcd_playing) < 0) {
-					sjcd_audio_status =
-					    CDROM_AUDIO_ERROR;
-					return (-EIO);
-				} else {
-					sjcd_audio_status =
-					    CDROM_AUDIO_PLAY;
-					return (0);
-				}
-			} else
-				return (-EINVAL);
-		}
-
-	case CDROMPLAYTRKIND:{
-			struct cdrom_ti ti;
-			int s = -EFAULT;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: playtrkind\n");
-#endif
-			if (!copy_from_user(&ti, argp, sizeof(ti))) {
-				s = 0;
-				if (ti.cdti_trk0 < sjcd_first_track_no)
-					return (-EINVAL);
-				if (ti.cdti_trk1 > sjcd_last_track_no)
-					ti.cdti_trk1 = sjcd_last_track_no;
-				if (ti.cdti_trk0 > ti.cdti_trk1)
-					return (-EINVAL);
-
-				sjcd_playing.start =
-				    sjcd_table_of_contents[ti.cdti_trk0].
-				    un.track_msf;
-				sjcd_playing.end =
-				    (ti.cdti_trk1 <
-				     sjcd_last_track_no) ?
-				    sjcd_table_of_contents[ti.cdti_trk1 +
-							   1].un.
-				    track_msf : sjcd_table_of_contents[0].
-				    un.track_msf;
-
-				if (sjcd_play(&sjcd_playing) < 0) {
-					sjcd_audio_status =
-					    CDROM_AUDIO_ERROR;
-					return (-EIO);
-				} else
-					sjcd_audio_status =
-					    CDROM_AUDIO_PLAY;
-			}
-			return (s);
-		}
-
-	case CDROMPLAYMSF:{
-			struct cdrom_msf sjcd_msf;
-			int s;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: playmsf\n");
-#endif
-			if ((s =
-			     access_ok(VERIFY_READ, argp, sizeof(sjcd_msf))
-			     		? 0 : -EFAULT) == 0) {
-				if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
-					sjcd_send_cmd(SCMD_PAUSE);
-					(void) sjcd_receive_status();
-					sjcd_audio_status =
-					    CDROM_AUDIO_NO_STATUS;
-				}
-
-				if (copy_from_user(&sjcd_msf, argp,
-					       sizeof(sjcd_msf)))
-					return (-EFAULT);
-
-				sjcd_playing.start.min =
-				    bin2bcd(sjcd_msf.cdmsf_min0);
-				sjcd_playing.start.sec =
-				    bin2bcd(sjcd_msf.cdmsf_sec0);
-				sjcd_playing.start.frame =
-				    bin2bcd(sjcd_msf.cdmsf_frame0);
-				sjcd_playing.end.min =
-				    bin2bcd(sjcd_msf.cdmsf_min1);
-				sjcd_playing.end.sec =
-				    bin2bcd(sjcd_msf.cdmsf_sec1);
-				sjcd_playing.end.frame =
-				    bin2bcd(sjcd_msf.cdmsf_frame1);
-
-				if (sjcd_play(&sjcd_playing) < 0) {
-					sjcd_audio_status =
-					    CDROM_AUDIO_ERROR;
-					return (-EIO);
-				} else
-					sjcd_audio_status =
-					    CDROM_AUDIO_PLAY;
-			}
-			return (s);
-		}
-
-	case CDROMREADTOCHDR:{
-			struct cdrom_tochdr toc_header;
-#if defined (SJCD_TRACE )
-			printk("SJCD: ioctl: readtocheader\n");
-#endif
-			toc_header.cdth_trk0 = sjcd_first_track_no;
-			toc_header.cdth_trk1 = sjcd_last_track_no;
-			if (copy_to_user(argp, &toc_header,
-					 sizeof(toc_header)))
-				return -EFAULT;
-			return 0;
-		}
-
-	case CDROMREADTOCENTRY:{
-			struct cdrom_tocentry toc_entry;
-			int s;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: readtocentry\n");
-#endif
-			if ((s =
-			     access_ok(VERIFY_WRITE, argp, sizeof(toc_entry))
-			     		? 0 : -EFAULT) == 0) {
-				struct sjcd_hw_disk_info *tp;
-
-				if (copy_from_user(&toc_entry, argp,
-					       sizeof(toc_entry)))
-					return (-EFAULT);
-				if (toc_entry.cdte_track == CDROM_LEADOUT)
-					tp = &sjcd_table_of_contents[0];
-				else if (toc_entry.cdte_track <
-					 sjcd_first_track_no)
-					return (-EINVAL);
-				else if (toc_entry.cdte_track >
-					 sjcd_last_track_no)
-					return (-EINVAL);
-				else
-					tp = &sjcd_table_of_contents
-					    [toc_entry.cdte_track];
-
-				toc_entry.cdte_adr =
-				    tp->track_control & 0x0F;
-				toc_entry.cdte_ctrl =
-				    tp->track_control >> 4;
-
-				switch (toc_entry.cdte_format) {
-				case CDROM_LBA:
-					toc_entry.cdte_addr.lba =
-					    msf2hsg(&(tp->un.track_msf));
-					break;
-				case CDROM_MSF:
-					toc_entry.cdte_addr.msf.minute =
-					    bcd2bin(tp->un.track_msf.min);
-					toc_entry.cdte_addr.msf.second =
-					    bcd2bin(tp->un.track_msf.sec);
-					toc_entry.cdte_addr.msf.frame =
-					    bcd2bin(tp->un.track_msf.
-						    frame);
-					break;
-				default:
-					return (-EINVAL);
-				}
-				if (copy_to_user(argp, &toc_entry,
-						 sizeof(toc_entry)))
-					s = -EFAULT;
-			}
-			return (s);
-		}
-
-	case CDROMSUBCHNL:{
-			struct cdrom_subchnl subchnl;
-			int s;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: subchnl\n");
-#endif
-			if ((s =
-			     access_ok(VERIFY_WRITE, argp, sizeof(subchnl))
-			     		? 0 : -EFAULT) == 0) {
-				struct sjcd_hw_qinfo q_info;
-
-				if (copy_from_user(&subchnl, argp,
-					       sizeof(subchnl)))
-					return (-EFAULT);
-
-				if (sjcd_get_q_info(&q_info) < 0)
-					return (-EIO);
-
-				subchnl.cdsc_audiostatus =
-				    sjcd_audio_status;
-				subchnl.cdsc_adr =
-				    q_info.track_control & 0x0F;
-				subchnl.cdsc_ctrl =
-				    q_info.track_control >> 4;
-				subchnl.cdsc_trk =
-				    bcd2bin(q_info.track_no);
-				subchnl.cdsc_ind = bcd2bin(q_info.x);
-
-				switch (subchnl.cdsc_format) {
-				case CDROM_LBA:
-					subchnl.cdsc_absaddr.lba =
-					    msf2hsg(&(q_info.abs));
-					subchnl.cdsc_reladdr.lba =
-					    msf2hsg(&(q_info.rel));
-					break;
-				case CDROM_MSF:
-					subchnl.cdsc_absaddr.msf.minute =
-					    bcd2bin(q_info.abs.min);
-					subchnl.cdsc_absaddr.msf.second =
-					    bcd2bin(q_info.abs.sec);
-					subchnl.cdsc_absaddr.msf.frame =
-					    bcd2bin(q_info.abs.frame);
-					subchnl.cdsc_reladdr.msf.minute =
-					    bcd2bin(q_info.rel.min);
-					subchnl.cdsc_reladdr.msf.second =
-					    bcd2bin(q_info.rel.sec);
-					subchnl.cdsc_reladdr.msf.frame =
-					    bcd2bin(q_info.rel.frame);
-					break;
-				default:
-					return (-EINVAL);
-				}
-				if (copy_to_user(argp, &subchnl,
-					         sizeof(subchnl)))
-					s = -EFAULT;
-			}
-			return (s);
-		}
-
-	case CDROMVOLCTRL:{
-			struct cdrom_volctrl vol_ctrl;
-			int s;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: volctrl\n");
-#endif
-			if ((s =
-			     access_ok(VERIFY_READ, argp, sizeof(vol_ctrl))
-			     		? 0 : -EFAULT) == 0) {
-				unsigned char dummy[4];
-
-				if (copy_from_user(&vol_ctrl, argp,
-					       sizeof(vol_ctrl)))
-					return (-EFAULT);
-				sjcd_send_4_cmd(SCMD_SET_VOLUME,
-						vol_ctrl.channel0, 0xFF,
-						vol_ctrl.channel1, 0xFF);
-				if (sjcd_receive_status() < 0)
-					return (-EIO);
-				(void) sjcd_load_response(dummy, 4);
-			}
-			return (s);
-		}
-
-	case CDROMEJECT:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: eject\n");
-#endif
-			if (!sjcd_command_is_in_progress) {
-				sjcd_tray_unlock();
-				sjcd_send_cmd(SCMD_EJECT_TRAY);
-				(void) sjcd_receive_status();
-			}
-			return (0);
-		}
-
-#if defined( SJCD_GATHER_STAT )
-	case 0xABCD:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: statistic\n");
-#endif
-			if (copy_to_user(argp, &statistic, sizeof(statistic)))
-				return -EFAULT;
-			return 0;
-		}
-#endif
-
-	default:
-		return (-EINVAL);
-	}
-}
-
-/*
- * Invalidate internal buffers of the driver.
- */
-static void sjcd_invalidate_buffers(void)
-{
-	int i;
-	for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);
-	sjcd_buf_out = -1;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static int current_valid(void)
-{
-        return CURRENT &&
-		CURRENT->cmd == READ &&
-		CURRENT->sector != -1;
-}
-
-static void sjcd_transfer(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: transfer:\n");
-#endif
-	if (current_valid()) {
-		while (CURRENT->nr_sectors) {
-			int i, bn = CURRENT->sector / 4;
-			for (i = 0;
-			     i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;
-			     i++);
-			if (i < SJCD_BUF_SIZ) {
-				int offs =
-				    (i * 4 + (CURRENT->sector & 3)) * 512;
-				int nr_sectors = 4 - (CURRENT->sector & 3);
-				if (sjcd_buf_out != i) {
-					sjcd_buf_out = i;
-					if (sjcd_buf_bn[i] != bn) {
-						sjcd_buf_out = -1;
-						continue;
-					}
-				}
-				if (nr_sectors > CURRENT->nr_sectors)
-					nr_sectors = CURRENT->nr_sectors;
-#if defined( SJCD_TRACE )
-				printk("SJCD: copy out\n");
-#endif
-				memcpy(CURRENT->buffer, sjcd_buf + offs,
-				       nr_sectors * 512);
-				CURRENT->nr_sectors -= nr_sectors;
-				CURRENT->sector += nr_sectors;
-				CURRENT->buffer += nr_sectors * 512;
-			} else {
-				sjcd_buf_out = -1;
-				break;
-			}
-		}
-	}
-#if defined( SJCD_TRACE )
-	printk("SJCD: transfer: done\n");
-#endif
-}
-
-static void sjcd_poll(void)
-{
-#if defined( SJCD_GATHER_STAT )
-	/*
-	 * Update total number of ticks.
-	 */
-	statistic.ticks++;
-	statistic.tticks[sjcd_transfer_state]++;
-#endif
-
-      ReSwitch:switch (sjcd_transfer_state) {
-
-	case SJCD_S_IDLE:{
-#if defined( SJCD_GATHER_STAT )
-			statistic.idle_ticks++;
-#endif
-#if defined( SJCD_TRACE )
-			printk("SJCD_S_IDLE\n");
-#endif
-			return;
-		}
-
-	case SJCD_S_START:{
-#if defined( SJCD_GATHER_STAT )
-			statistic.start_ticks++;
-#endif
-			sjcd_send_cmd(SCMD_GET_STATUS);
-			sjcd_transfer_state =
-			    sjcd_mode ==
-			    SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
-			sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
-			printk("SJCD_S_START: goto SJCD_S_%s mode\n",
-			       sjcd_transfer_state ==
-			       SJCD_S_READ ? "READ" : "MODE");
-#endif
-			break;
-		}
-
-	case SJCD_S_MODE:{
-			if (sjcd_check_status()) {
-				/*
-				 * Previous command is completed.
-				 */
-				if (!sjcd_status_valid
-				    || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-
-				sjcd_mode = 0;	/* unknown mode; should not be valid when failed */
-				sjcd_send_1_cmd(SCMD_SET_MODE,
-						SCMD_MODE_COOKED);
-				sjcd_transfer_state = SJCD_S_READ;
-				sjcd_transfer_timeout = 1000;
-#if defined( SJCD_TRACE )
-				printk
-				    ("SJCD_S_MODE: goto SJCD_S_READ mode\n");
-#endif
-			}
-#if defined( SJCD_GATHER_STAT )
-			else
-				statistic.mode_ticks++;
-#endif
-			break;
-		}
-
-	case SJCD_S_READ:{
-			if (sjcd_status_valid ? 1 : sjcd_check_status()) {
-				/*
-				 * Previous command is completed.
-				 */
-				if (!sjcd_status_valid
-				    || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-				if (!sjcd_media_is_available) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-				if (sjcd_mode != SCMD_MODE_COOKED) {
-					/*
-					 * We seem to come from set mode. So discard one byte of result.
-					 */
-					if (sjcd_load_response
-					    (&sjcd_mode, 1) != 0) {
-#if defined( SJCD_TRACE )
-						printk
-						    ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");
-#endif
-						sjcd_transfer_state =
-						    SJCD_S_STOP;
-						goto ReSwitch;
-					}
-					if (sjcd_mode != SCMD_MODE_COOKED) {
-#if defined( SJCD_TRACE )
-						printk
-						    ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");
-#endif
-						sjcd_transfer_state =
-						    SJCD_S_STOP;
-						goto ReSwitch;
-					}
-				}
-
-				if (current_valid()) {
-					struct sjcd_play_msf msf;
-
-					sjcd_next_bn = CURRENT->sector / 4;
-					hsg2msf(sjcd_next_bn, &msf.start);
-					msf.end.min = 0;
-					msf.end.sec = 0;
-					msf.end.frame = sjcd_read_count =
-					    SJCD_BUF_SIZ;
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD: ---reading msf-address %x:%x:%x  %x:%x:%x\n",
-					     msf.start.min, msf.start.sec,
-					     msf.start.frame, msf.end.min,
-					     msf.end.sec, msf.end.frame);
-					printk
-					    ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n",
-					     sjcd_next_bn, sjcd_buf_in,
-					     sjcd_buf_out,
-					     sjcd_buf_bn[sjcd_buf_in]);
-#endif
-					sjcd_send_6_cmd(SCMD_DATA_READ,
-							&msf);
-					sjcd_transfer_state = SJCD_S_DATA;
-					sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_READ: go to SJCD_S_DATA mode\n");
-#endif
-				} else {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-			}
-#if defined( SJCD_GATHER_STAT )
-			else
-				statistic.read_ticks++;
-#endif
-			break;
-		}
-
-	case SJCD_S_DATA:{
-			unsigned char stat;
-
-		      sjcd_s_data:stat =
-			    inb(SJCDPORT
-				(1));
-#if defined( SJCD_TRACE )
-			printk("SJCD_S_DATA: status = 0x%02x\n", stat);
-#endif
-			if (SJCD_STATUS_AVAILABLE(stat)) {
-				/*
-				 * No data is waiting for us in the drive buffer. Status of operation
-				 * completion is available. Read and parse it.
-				 */
-				sjcd_load_status();
-
-				if (!sjcd_status_valid
-				    || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD: read block %d failed, maybe audio disk? Giving up\n",
-					     sjcd_next_bn);
-#endif
-					if (current_valid())
-						end_request(CURRENT, 0);
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-
-				if (!sjcd_media_is_available) {
-					printk
-					    ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n");
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-
-				sjcd_transfer_state = SJCD_S_READ;
-				goto ReSwitch;
-			} else if (SJCD_DATA_AVAILABLE(stat)) {
-				/*
-				 * One frame is read into device buffer. We must copy it to our memory.
-				 * Otherwise cdrom hangs up. Check to see if we have something to copy
-				 * to.
-				 */
-				if (!current_valid()
-				    && sjcd_buf_in == sjcd_buf_out) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n");
-					printk
-					    (" ... all the date would be discarded\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-
-				/*
-				 * Everything seems to be OK. Just read the frame and recalculate
-				 * indices.
-				 */
-				sjcd_buf_bn[sjcd_buf_in] = -1;	/* ??? */
-				insb(SJCDPORT(2),
-				     sjcd_buf + 2048 * sjcd_buf_in, 2048);
-#if defined( SJCD_TRACE )
-				printk
-				    ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
-				     sjcd_next_bn, sjcd_buf_in,
-				     sjcd_buf_out,
-				     sjcd_buf_bn[sjcd_buf_in]);
-#endif
-				sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;
-				if (sjcd_buf_out == -1)
-					sjcd_buf_out = sjcd_buf_in;
-				if (++sjcd_buf_in == SJCD_BUF_SIZ)
-					sjcd_buf_in = 0;
-
-				/*
-				 * Only one frame is ready at time. So we should turn over to wait for
-				 * another frame. If we need that, of course.
-				 */
-				if (--sjcd_read_count == 0) {
-					/*
-					 * OK, request seems to be precessed. Continue transferring...
-					 */
-					if (!sjcd_transfer_is_active) {
-						while (current_valid()) {
-							/*
-							 * Continue transferring.
-							 */
-							sjcd_transfer();
-							if (CURRENT->
-							    nr_sectors ==
-							    0)
-								end_request
-								    (CURRENT, 1);
-							else
-								break;
-						}
-					}
-					if (current_valid() &&
-					    (CURRENT->sector / 4 <
-					     sjcd_next_bn
-					     || CURRENT->sector / 4 >
-					     sjcd_next_bn +
-					     SJCD_BUF_SIZ)) {
-#if defined( SJCD_TRACE )
-						printk
-						    ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");
-#endif
-						sjcd_transfer_state =
-						    SJCD_S_STOP;
-						goto ReSwitch;
-					}
-				}
-				/*
-				 * Now we should turn around rather than wait for while.
-				 */
-				goto sjcd_s_data;
-			}
-#if defined( SJCD_GATHER_STAT )
-			else
-				statistic.data_ticks++;
-#endif
-			break;
-		}
-
-	case SJCD_S_STOP:{
-			sjcd_read_count = 0;
-			sjcd_send_cmd(SCMD_STOP);
-			sjcd_transfer_state = SJCD_S_STOPPING;
-			sjcd_transfer_timeout = 500;
-#if defined( SJCD_GATHER_STAT )
-			statistic.stop_ticks++;
-#endif
-			break;
-		}
-
-	case SJCD_S_STOPPING:{
-			unsigned char stat;
-
-			stat = inb(SJCDPORT(1));
-#if defined( SJCD_TRACE )
-			printk("SJCD_S_STOP: status = 0x%02x\n", stat);
-#endif
-			if (SJCD_DATA_AVAILABLE(stat)) {
-				int i;
-#if defined( SJCD_TRACE )
-				printk("SJCD_S_STOP: discard data\n");
-#endif
-				/*
-				 * Discard all the data from the pipe. Foolish method.
-				 */
-				for (i = 2048; i--;
-				     (void) inb(SJCDPORT(2)));
-				sjcd_transfer_timeout = 500;
-			} else if (SJCD_STATUS_AVAILABLE(stat)) {
-				sjcd_load_status();
-				if (sjcd_status_valid
-				    && sjcd_media_is_changed) {
-					sjcd_toc_uptodate = 0;
-					sjcd_invalidate_buffers();
-				}
-				if (current_valid()) {
-					if (sjcd_status_valid)
-						sjcd_transfer_state =
-						    SJCD_S_READ;
-					else
-						sjcd_transfer_state =
-						    SJCD_S_START;
-				} else
-					sjcd_transfer_state = SJCD_S_IDLE;
-				goto ReSwitch;
-			}
-#if defined( SJCD_GATHER_STAT )
-			else
-				statistic.stopping_ticks++;
-#endif
-			break;
-		}
-
-	default:
-		printk("SJCD: poll: invalid state %d\n",
-		       sjcd_transfer_state);
-		return;
-	}
-
-	if (--sjcd_transfer_timeout == 0) {
-		printk("SJCD: timeout in state %d\n", sjcd_transfer_state);
-		while (current_valid())
-			end_request(CURRENT, 0);
-		sjcd_send_cmd(SCMD_STOP);
-		sjcd_transfer_state = SJCD_S_IDLE;
-		goto ReSwitch;
-	}
-
-	/*
-	 * Get back in some time. 1 should be replaced with count variable to
-	 * avoid unnecessary testings.
-	 */
-	SJCD_SET_TIMER(sjcd_poll, 1);
-}
-
-static void do_sjcd_request(request_queue_t * q)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: do_sjcd_request(%ld+%ld)\n",
-	       CURRENT->sector, CURRENT->nr_sectors);
-#endif
-	sjcd_transfer_is_active = 1;
-	while (current_valid()) {
-		sjcd_transfer();
-		if (CURRENT->nr_sectors == 0)
-			end_request(CURRENT, 1);
-		else {
-			sjcd_buf_out = -1;	/* Want to read a block not in buffer */
-			if (sjcd_transfer_state == SJCD_S_IDLE) {
-				if (!sjcd_toc_uptodate) {
-					if (sjcd_update_toc() < 0) {
-						printk
-						    ("SJCD: transfer: discard\n");
-						while (current_valid())
-							end_request(CURRENT, 0);
-						break;
-					}
-				}
-				sjcd_transfer_state = SJCD_S_START;
-				SJCD_SET_TIMER(sjcd_poll, HZ / 100);
-			}
-			break;
-		}
-	}
-	sjcd_transfer_is_active = 0;
-#if defined( SJCD_TRACE )
-	printk
-	    ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
-	     sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
-	     sjcd_buf_bn[sjcd_buf_in]);
-	printk("do_sjcd_request ends\n");
-#endif
-}
-
-/*
- * Open the device special file. Check disk is in.
- */
-static int sjcd_open(struct inode *ip, struct file *fp)
-{
-	/*
-	 * Check the presence of device.
-	 */
-	if (!sjcd_present)
-		return (-ENXIO);
-
-	/*
-	 * Only read operations are allowed. Really? (:-)
-	 */
-	if (fp->f_mode & 2)
-		return (-EROFS);
-
-	if (sjcd_open_count == 0) {
-		int s, sjcd_open_tries;
-/* We don't know that, do we? */
-/*
-    sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-*/
-		sjcd_mode = 0;
-		sjcd_door_was_open = 0;
-		sjcd_transfer_state = SJCD_S_IDLE;
-		sjcd_invalidate_buffers();
-		sjcd_status_valid = 0;
-
-		/*
-		 * Strict status checking.
-		 */
-		for (sjcd_open_tries = 4; --sjcd_open_tries;) {
-			if (!sjcd_status_valid)
-				sjcd_get_status();
-			if (!sjcd_status_valid) {
-#if defined( SJCD_DIAGNOSTIC )
-				printk
-				    ("SJCD: open: timed out when check status.\n");
-#endif
-				goto err_out;
-			} else if (!sjcd_media_is_available) {
-#if defined( SJCD_DIAGNOSTIC )
-				printk("SJCD: open: no disk in drive\n");
-#endif
-				if (!sjcd_door_closed) {
-					sjcd_door_was_open = 1;
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD: open: close the tray\n");
-#endif
-					s = sjcd_tray_close();
-					if (s < 0 || !sjcd_status_valid
-					    || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-						printk
-						    ("SJCD: open: tray close attempt failed\n");
-#endif
-						goto err_out;
-					}
-					continue;
-				} else
-					goto err_out;
-			}
-			break;
-		}
-		s = sjcd_tray_lock();
-		if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-			printk("SJCD: open: tray lock attempt failed\n");
-#endif
-			goto err_out;
-		}
-#if defined( SJCD_TRACE )
-		printk("SJCD: open: done\n");
-#endif
-	}
-
-	++sjcd_open_count;
-	return (0);
-
-      err_out:
-	return (-EIO);
-}
-
-/*
- * On close, we flush all sjcd blocks from the buffer cache.
- */
-static int sjcd_release(struct inode *inode, struct file *file)
-{
-	int s;
-
-#if defined( SJCD_TRACE )
-	printk("SJCD: release\n");
-#endif
-	if (--sjcd_open_count == 0) {
-		sjcd_invalidate_buffers();
-		s = sjcd_tray_unlock();
-		if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-			printk
-			    ("SJCD: release: tray unlock attempt failed.\n");
-#endif
-		}
-		if (sjcd_door_was_open) {
-			s = sjcd_tray_open();
-			if (s < 0 || !sjcd_status_valid
-			    || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-				printk
-				    ("SJCD: release: tray unload attempt failed.\n");
-#endif
-			}
-		}
-	}
-	return 0;
-}
-
-/*
- * A list of file operations allowed for this cdrom.
- */
-static struct block_device_operations sjcd_fops = {
-	.owner		= THIS_MODULE,
-	.open		= sjcd_open,
-	.release	= sjcd_release,
-	.ioctl		= sjcd_ioctl,
-	.media_changed	= sjcd_disk_change,
-};
-
-/*
- * Following stuff is intended for initialization of the cdrom. It
- * first looks for presence of device. If the device is present, it
- * will be reset. Then read the version of the drive and load status.
- * The version is two BCD-coded bytes.
- */
-static struct {
-	unsigned char major, minor;
-} sjcd_version;
-
-static struct gendisk *sjcd_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- * Probe cdrom, find out version and status.
- */
-static int __init sjcd_init(void)
-{
-	int i;
-
-	printk(KERN_INFO
-	       "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n",
-	       SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);
-
-#if defined( SJCD_TRACE )
-	printk("SJCD: sjcd=0x%x: ", sjcd_base);
-#endif
-
-	if (register_blkdev(MAJOR_NR, "sjcd"))
-		return -EIO;
-
-	sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock);
-	if (!sjcd_queue)
-		goto out0;
-
-	blk_queue_hardsect_size(sjcd_queue, 2048);
-
-	sjcd_disk = alloc_disk(1);
-	if (!sjcd_disk) {
-		printk(KERN_ERR "SJCD: can't allocate disk");
-		goto out1;
-	}
-	sjcd_disk->major = MAJOR_NR,
-	sjcd_disk->first_minor = 0,
-	sjcd_disk->fops = &sjcd_fops,
-	sprintf(sjcd_disk->disk_name, "sjcd");
-
-	if (!request_region(sjcd_base, 4,"sjcd")) {
-		printk
-		    ("SJCD: Init failed, I/O port (%X) is already in use\n",
-		     sjcd_base);
-		goto out2;
-	}
-
-	/*
-	 * Check for card. Since we are booting now, we can't use standard
-	 * wait algorithm.
-	 */
-	printk(KERN_INFO "SJCD: Resetting: ");
-	sjcd_send_cmd(SCMD_RESET);
-	for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-		unsigned long timer;
-
-		/*
-		 * Wait 10ms approx.
-		 */
-		for (timer = jiffies; time_before_eq(jiffies, timer););
-		if ((i % 100) == 0)
-			printk(".");
-		(void) sjcd_check_status();
-	}
-	if (i == 0 || sjcd_command_failed) {
-		printk(" reset failed, no drive found.\n");
-		goto out3;
-	} else
-		printk("\n");
-
-	/*
-	 * Get and print out cdrom version.
-	 */
-	printk(KERN_INFO "SJCD: Getting version: ");
-	sjcd_send_cmd(SCMD_GET_VERSION);
-	for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-		unsigned long timer;
-
-		/*
-		 * Wait 10ms approx.
-		 */
-		for (timer = jiffies; time_before_eq(jiffies, timer););
-		if ((i % 100) == 0)
-			printk(".");
-		(void) sjcd_check_status();
-	}
-	if (i == 0 || sjcd_command_failed) {
-		printk(" get version failed, no drive found.\n");
-		goto out3;
-	}
-
-	if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
-		printk(" %1x.%02x\n", (int) sjcd_version.major,
-		       (int) sjcd_version.minor);
-	} else {
-		printk(" read version failed, no drive found.\n");
-		goto out3;
-	}
-
-	/*
-	 * Check and print out the tray state. (if it is needed?).
-	 */
-	if (!sjcd_status_valid) {
-		printk(KERN_INFO "SJCD: Getting status: ");
-		sjcd_send_cmd(SCMD_GET_STATUS);
-		for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-			unsigned long timer;
-
-			/*
-			 * Wait 10ms approx.
-			 */
-			for (timer = jiffies;
-			     time_before_eq(jiffies, timer););
-			if ((i % 100) == 0)
-				printk(".");
-			(void) sjcd_check_status();
-		}
-		if (i == 0 || sjcd_command_failed) {
-			printk(" get status failed, no drive found.\n");
-			goto out3;
-		} else
-			printk("\n");
-	}
-
-	printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
-	sjcd_disk->queue = sjcd_queue;
-	add_disk(sjcd_disk);
-
-	sjcd_present++;
-	return (0);
-out3:
-	release_region(sjcd_base, 4);
-out2:
-	put_disk(sjcd_disk);
-out1:
-	blk_cleanup_queue(sjcd_queue);
-out0:
-	if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
-		printk("SJCD: cannot unregister device.\n");
-	return (-EIO);
-}
-
-static void __exit sjcd_exit(void)
-{
-	del_gendisk(sjcd_disk);
-	put_disk(sjcd_disk);
-	release_region(sjcd_base, 4);
-	blk_cleanup_queue(sjcd_queue);
-	if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
-		printk("SJCD: cannot unregister device.\n");
-	printk(KERN_INFO "SJCD: module: removed.\n");
-}
-
-module_init(sjcd_init);
-module_exit(sjcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR);
diff --git a/drivers/cdrom/sjcd.h b/drivers/cdrom/sjcd.h
deleted file mode 100644
index 0aa5e71..0000000
--- a/drivers/cdrom/sjcd.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Definitions for a Sanyo CD-ROM interface.
- *
- *   Copyright (C) 1995  Vadim V. Model
- *                                       model@cecmow.enet.dec.com
- *                                       vadim@rbrf.msk.su
- *                                       vadim@ipsun.ras.ru
- *                       Eric van der Maarel
- *                                       H.T.M.v.d.Maarel@marin.nl
- *
- *  This information is based on mcd.c from M. Harriss and sjcd102.lst from
- *  E. Moenkeberg.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __SJCD_H__
-#define __SJCD_H__
-
-/*
- * Change this to set the I/O port address as default. More flexibility
- * come with setup implementation.
- */
-#define SJCD_BASE_ADDR      0x340
-
-/*
- * Change this to set the irq as default. Really SANYO do not use interrupts
- * at all.
- */
-#define SJCD_INTR_NR        0
-
-/*
- * Change this to set the dma as default value. really SANYO does not use
- * direct memory access at all.
- */
-#define SJCD_DMA_NR         0
-
-/*
- * Macros which allow us to find out the status of the drive.
- */
-#define SJCD_STATUS_AVAILABLE( x ) (((x)&0x02)==0)
-#define SJCD_DATA_AVAILABLE( x )   (((x)&0x01)==0)
-
-/*
- * Port access macro. Three ports are available: S-data port (command port),
- * status port (read only) and D-data port (read only).
- */
-#define SJCDPORT( x )       ( sjcd_base + ( x ) )
-#define SJCD_STATUS_PORT    SJCDPORT( 1 )
-#define SJCD_S_DATA_PORT    SJCDPORT( 0 )
-#define SJCD_COMMAND_PORT   SJCDPORT( 0 )
-#define SJCD_D_DATA_PORT    SJCDPORT( 2 )
-
-/*
- * Drive info bits. Drive info available as first (mandatory) byte of
- * command completion status.
- */
-#define SST_NOT_READY       0x10        /* no disk in the drive (???) */
-#define SST_MEDIA_CHANGED   0x20        /* disk is changed */
-#define SST_DOOR_OPENED     0x40        /* door is open */
-
-/* commands */
-
-#define SCMD_EJECT_TRAY     0xD0        /* eject tray if not locked */
-#define SCMD_LOCK_TRAY      0xD2        /* lock tray when in */
-#define SCMD_UNLOCK_TRAY    0xD4        /* unlock tray when in */
-#define SCMD_CLOSE_TRAY     0xD6        /* load tray in */
-
-#define SCMD_RESET          0xFA        /* soft reset */
-#define SCMD_GET_STATUS     0x80
-#define SCMD_GET_VERSION    0xCC
-
-#define SCMD_DATA_READ      0xA0        /* are the same, depend on mode&args */
-#define SCMD_SEEK           0xA0
-#define SCMD_PLAY           0xA0
-
-#define SCMD_GET_QINFO      0xA8
-
-#define SCMD_SET_MODE       0xC4
-#define SCMD_MODE_PLAY      0xE0
-#define SCMD_MODE_COOKED    (0xF8 & ~0x20)
-#define SCMD_MODE_RAW       0xF9
-#define SCMD_MODE_x20_BIT   0x20        /* What is it for ? */
-
-#define SCMD_SET_VOLUME     0xAE
-#define SCMD_PAUSE          0xE0
-#define SCMD_STOP           0xE0
-
-#define SCMD_GET_DISK_INFO  0xAA
-
-/*
- * Some standard arguments for SCMD_GET_DISK_INFO.
- */
-#define SCMD_GET_1_TRACK    0xA0    /* get the first track information */
-#define SCMD_GET_L_TRACK    0xA1    /* get the last track information */
-#define SCMD_GET_D_SIZE     0xA2    /* get the whole disk information */
-
-/*
- * Borrowed from hd.c. Allows to optimize multiple port read commands.
- */
-#define S_READ_DATA( port, buf, nr )      insb( port, buf, nr )
-
-/*
- * We assume that there are no audio disks with TOC length more than this
- * number (I personally have never seen disks with more than 20 fragments).
- */
-#define SJCD_MAX_TRACKS		100
-
-struct msf {
-  unsigned char   min;
-  unsigned char   sec;
-  unsigned char   frame;
-};
-
-struct sjcd_hw_disk_info {
-  unsigned char track_control;
-  unsigned char track_no;
-  unsigned char x, y, z;
-  union {
-    unsigned char track_no;
-    struct msf track_msf;
-  } un;
-};
-
-struct sjcd_hw_qinfo {
-  unsigned char track_control;
-  unsigned char track_no;
-  unsigned char x;
-  struct msf rel;
-  struct msf abs;
-};
-
-struct sjcd_play_msf {
-  struct msf  start;
-  struct msf  end;
-};
-
-struct sjcd_disk_info {
-  unsigned char   first;
-  unsigned char   last;
-  struct msf      disk_length;
-  struct msf      first_track;
-};
-
-struct sjcd_toc {
-  unsigned char   ctrl_addr;
-  unsigned char   track;
-  unsigned char   point_index;
-  struct msf      track_time;
-  struct msf      disk_time;
-};
-
-#if defined( SJCD_GATHER_STAT )
-
-struct sjcd_stat {
-  int ticks;
-  int tticks[ 8 ];
-  int idle_ticks;
-  int start_ticks;
-  int mode_ticks;
-  int read_ticks;
-  int data_ticks;
-  int stop_ticks;
-  int stopping_ticks;
-};
-
-#endif
-
-#endif
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
deleted file mode 100644
index f77ada9..0000000
--- a/drivers/cdrom/sonycd535.c
+++ /dev/null
@@ -1,1689 +0,0 @@
-/*
- * Sony CDU-535 interface device driver
- *
- * This is a modified version of the CDU-31A device driver (see below).
- * Changes were made using documentation for the CDU-531 (which Sony
- * assures me is very similar to the 535) and partial disassembly of the
- * DOS driver.  I used Minyard's driver and replaced the CDU-31A
- * commands with the CDU-531 commands.  This was complicated by a different
- * interface protocol with the drive.  The driver is still polled.
- *
- * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec.
- * I tried polling without the sony_sleep during the data transfers but
- * it did not speed things up any.
- *
- * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict
- * with CDU-31A driver.  This is the also the number from the Linux
- * Device Driver Registry for the Sony Drive.  Hope nobody else is using it.
- *
- * 1993-08-29 (rgj) remove the configuring of the interface board address
- * from the top level configuration, you have to modify it in this file.
- *
- * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>)
- *
- * 1995-05-20
- *  Modified to support CDU-510/515 series
- *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *  Fixed to report verify_area() failures
- *      (Heiko Eissfeldt <heiko@colossus.escape.de>)
- *
- * 1995-06-01
- *  More changes to support CDU-510/515 series
- *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	            Removed init_module & cleanup_module in favor of 
- *	            module_init & module_exit.
- *                  Torben Mathiasen <tmm@image.dk>
- *
- * September 2003 - Fix SMP support by removing cli/sti calls.
- *                  Using spinlocks with a wait_queue instead.
- *                  Felipe Damasio <felipewd@terra.com.br>
- *
- * Things to do:
- *  - handle errors and status better, put everything into a single word
- *  - use interrupts (code mostly there, but a big hole still missing)
- *  - handle multi-session CDs?
- *  - use DMA?
- *
- *  Known Bugs:
- *  -
- *
- *   Ken Pizzini (ken@halcyon.com)
- *
- * Original by:
- *   Ron Jeppesen (ronj.an@site007.saic.com)
- *
- *
- *------------------------------------------------------------------------
- * Sony CDROM interface device driver.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above)
- *
- * Colossians 3:17
- *
- * The Sony interface device driver handles Sony interface CDROM
- * drives and provides a complete block-level interface as well as an
- * ioctl() interface compatible with the Sun (as specified in
- * include/linux/cdrom.h).  With this interface, CDROMs can be
- * accessed and standard audio CDs can be played back normally.
- *
- * This interface is (unfortunately) a polled interface.  This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables.  Some (like mine) do not even have the capability to
- * handle interrupts or DMA.  For this reason you will see a bit of
- * the following:
- *
- *   snap = jiffies;
- *   while (jiffies-snap < SONY_JIFFIES_TIMEOUT)
- *   {
- *		if (some_condition())
- *         break;
- *      sony_sleep();
- *   }
- *   if (some_condition not met)
- *   {
- *      return an_error;
- *   }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try.  (The conditional is written so that jiffies
- * wrap-around is handled properly.)
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk.  The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal.  A lot of conversion goes on.
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-# include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#define REALLY_SLOW_IO
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/cdrom.h>
-
-#define MAJOR_NR CDU535_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
-#include "sonycd535.h"
-
-/*
- * this is the base address of the interface card for the Sony CDU-535
- * CDROM drive.  If your jumpers are set for an address other than
- * this one (the default), change the following line to the
- * proper address.
- */
-#ifndef CDU535_ADDRESS
-# define CDU535_ADDRESS			0x340
-#endif
-#ifndef CDU535_INTERRUPT
-# define CDU535_INTERRUPT		0
-#endif
-#ifndef CDU535_HANDLE
-# define CDU535_HANDLE			"cdu535"
-#endif
-#ifndef CDU535_MESSAGE_NAME
-# define CDU535_MESSAGE_NAME	"Sony CDU-535"
-#endif
-
-#define CDU535_BLOCK_SIZE	2048 
- 
-#ifndef MAX_SPINUP_RETRY
-# define MAX_SPINUP_RETRY		3	/* 1 is sufficient for most drives... */
-#endif
-#ifndef RETRY_FOR_BAD_STATUS
-# define RETRY_FOR_BAD_STATUS	100	/* in 10th of second */
-#endif
-
-#ifndef DEBUG
-# define DEBUG	1
-#endif
-
-/*
- *  SONY535_BUFFER_SIZE determines the size of internal buffer used
- *  by the drive.  It must be at least 2K and the larger the buffer
- *  the better the transfer rate.  It does however take system memory.
- *  On my system I get the following transfer rates using dd to read
- *  10 Mb off /dev/cdrom.
- *
- *    8K buffer      43 Kb/sec
- *   16K buffer      66 Kb/sec
- *   32K buffer      91 Kb/sec
- *   64K buffer     111 Kb/sec
- *  128K buffer     123 Kb/sec
- *  512K buffer     123 Kb/sec
- */
-#define SONY535_BUFFER_SIZE	(64*1024)
-
-/*
- *  if LOCK_DOORS is defined then the eject button is disabled while
- * the device is open.
- */
-#ifndef NO_LOCK_DOORS
-# define LOCK_DOORS
-#endif
-
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int cdu_open(struct inode *inode, struct file *filp);
-static inline unsigned int int_to_bcd(unsigned int val);
-static unsigned int bcd_to_int(unsigned int bcd);
-static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
-					   Byte * response, int n_response, int ignoreStatusBit7);
-
-/* The base I/O address of the Sony Interface.  This is a variable (not a
-   #define) so it can be easily changed via some future ioctl() */
-static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
-module_param(sony535_cd_base_io, int, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive.  The
- * comment for the base address also applies here.
- */
-static unsigned short select_unit_reg;
-static unsigned short result_reg;
-static unsigned short command_reg;
-static unsigned short read_status_reg;
-static unsigned short data_reg;
-
-static DEFINE_SPINLOCK(sonycd535_lock); /* queue lock */
-static struct request_queue *sonycd535_queue;
-
-static int initialized;			/* Has the drive been initialized? */
-static int sony_disc_changed = 1;	/* Has the disk been changed
-					   since the last check? */
-static int sony_toc_read;		/* Has the table of contents been
-					   read? */
-static unsigned int sony_buffer_size;	/* Size in bytes of the read-ahead
-					   buffer. */
-static unsigned int sony_buffer_sectors;	/* Size (in 2048 byte records) of
-						   the read-ahead buffer. */
-static unsigned int sony_usage;		/* How many processes have the
-					   drive open. */
-
-static int sony_first_block = -1;	/* First OS block (512 byte) in
-					   the read-ahead buffer */
-static int sony_last_block = -1;	/* Last OS block (512 byte) in
-					   the read-ahead buffer */
-
-static struct s535_sony_toc *sony_toc;	/* Points to the table of
-					   contents. */
-
-static struct s535_sony_subcode *last_sony_subcode;		/* Points to the last
-								   subcode address read */
-static Byte **sony_buffer;		/* Points to the pointers
-					   to the sector buffers */
-
-static int sony_inuse;			/* is the drive in use? Only one
-					   open at a time allowed */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play.  The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over.  This holds the
- * position during a pause so a resume can restart it.  It uses the
- * audio status variable above to tell if it is paused.
- *   I just kept the CDU-31A driver behavior rather than using the PAUSE
- * command on the CDU-535.
- */
-static Byte cur_pos_msf[3];
-static Byte final_pos_msf[3];
-
-/* What IRQ is the drive using?  0 if none. */
-static int sony535_irq_used = CDU535_INTERRUPT;
-
-/* The interrupt handler will wake this queue up when it gets an interrupt. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
-
-
-/*
- * This routine returns 1 if the disk has been changed since the last
- * check or 0 if it hasn't.  Setting flag to 0 resets the changed flag.
- */
-static int
-cdu535_check_media_change(struct gendisk *disk)
-{
-	/* if driver is not initialized, always return 0 */
-	int retval = initialized ? sony_disc_changed : 0;
-	sony_disc_changed = 0;
-	return retval;
-}
-
-static inline void
-enable_interrupts(void)
-{
-#ifdef USE_IRQ
-	/*
-	 * This code was taken from cdu31a.c; it will not
-	 * directly work for the cdu535 as written...
-	 */
-	curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
-						| SONY_RES_RDY_INT_EN_BIT
-						| SONY_DATA_RDY_INT_EN_BIT);
-	outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static inline void
-disable_interrupts(void)
-{
-#ifdef USE_IRQ
-	/*
-	 * This code was taken from cdu31a.c; it will not
-	 * directly work for the cdu535 as written...
-	 */
-	curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
-						| SONY_RES_RDY_INT_EN_BIT
-						| SONY_DATA_RDY_INT_EN_BIT);
-	outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static irqreturn_t
-cdu535_interrupt(int irq, void *dev_id)
-{
-	disable_interrupts();
-	if (waitqueue_active(&cdu535_irq_wait)) {
-		wake_up(&cdu535_irq_wait);
-		return IRQ_HANDLED;
-	}
-	printk(CDU535_MESSAGE_NAME
-			": Got an interrupt but nothing was waiting\n");
-	return IRQ_NONE;
-}
-
-
-/*
- * Wait a little while.
- */
-static inline void
-sony_sleep(void)
-{
-	if (sony535_irq_used <= 0) {	/* poll */
-		yield();
-	} else {	/* Interrupt driven */
-		DEFINE_WAIT(wait);
-		
-		spin_lock_irq(&sonycd535_lock);
-		enable_interrupts();
-		prepare_to_wait(&cdu535_irq_wait, &wait, TASK_INTERRUPTIBLE);
-		spin_unlock_irq(&sonycd535_lock);
-		schedule();
-		finish_wait(&cdu535_irq_wait, &wait);
-	}
-}
-
-/*------------------start of SONY CDU535 very specific ---------------------*/
-
-/****************************************************************************
- * void select_unit( int unit_no )
- *
- *  Select the specified unit (0-3) so that subsequent commands reference it
- ****************************************************************************/
-static void
-select_unit(int unit_no)
-{
-	unsigned int select_mask = ~(1 << unit_no);
-	outb(select_mask, select_unit_reg);
-}
-
-/***************************************************************************
- * int read_result_reg( Byte *data_ptr )
- *
- *  Read a result byte from the Sony CDU controller, store in location pointed
- * to by data_ptr.  Return zero on success, TIME_OUT if we did not receive
- * data.
- ***************************************************************************/
-static int
-read_result_reg(Byte *data_ptr)
-{
-	unsigned long snap;
-	int read_status;
-
-	snap = jiffies;
-	while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-		read_status = inb(read_status_reg);
-		if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-#if DEBUG > 1
-			printk(CDU535_MESSAGE_NAME
-					": read_result_reg(): readStatReg = 0x%x\n", read_status);
-#endif
-			*data_ptr = inb(result_reg);
-			return 0;
-		} else {
-			sony_sleep();
-		}
-	}
-	printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
-	return TIME_OUT;
-}
-
-/****************************************************************************
- * int read_exec_status( Byte status[2] )
- *
- *  Read the execution status of the last command and put into status.
- * Handles reading second status word if available.  Returns 0 on success,
- * TIME_OUT on failure.
- ****************************************************************************/
-static int
-read_exec_status(Byte status[2])
-{
-	status[1] = 0;
-	if (read_result_reg(&(status[0])) != 0)
-		return TIME_OUT;
-	if ((status[0] & 0x80) != 0) {	/* byte two follows */
-		if (read_result_reg(&(status[1])) != 0)
-			return TIME_OUT;
-	}
-#if DEBUG > 1
-	printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
-			status[0], status[1]);
-#endif
-	return 0;
-}
-
-/****************************************************************************
- * int check_drive_status( void )
- *
- *  Check the current drive status.  Using this before executing a command
- * takes care of the problem of unsolicited drive status-2 messages.
- * Add a check of the audio status if we think the disk is playing.
- ****************************************************************************/
-static int
-check_drive_status(void)
-{
-	Byte status, e_status[2];
-	int  CDD, ATN;
-	Byte cmd;
-
-	select_unit(0);
-	if (sony_audio_status == CDROM_AUDIO_PLAY) {	/* check status */
-		outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
-		if (read_result_reg(&status) == 0) {
-			switch (status) {
-			case 0x0:
-				break;		/* play in progress */
-			case 0x1:
-				break;		/* paused */
-			case 0x3:		/* audio play completed */
-			case 0x5:		/* play not requested */
-				sony_audio_status = CDROM_AUDIO_COMPLETED;
-				read_subcode();
-				break;
-			case 0x4:		/* error during play */
-				sony_audio_status = CDROM_AUDIO_ERROR;
-				break;
-			}
-		}
-	}
-	/* now check drive status */
-	outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
-	if (read_result_reg(&status) != 0)
-		return TIME_OUT;
-
-#if DEBUG > 1
-	printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
-#endif
-
-	if (status == 0)
-		return 0;
-
-	ATN = status & 0xf;
-	CDD = (status >> 4) & 0xf;
-
-	switch (ATN) {
-	case 0x0:
-		break;					/* go on to CDD stuff */
-	case SONY535_ATN_BUSY:
-		if (initialized)
-			printk(CDU535_MESSAGE_NAME " error: drive busy\n");
-		return CD_BUSY;
-	case SONY535_ATN_EJECT_IN_PROGRESS:
-		printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
-		sony_audio_status = CDROM_AUDIO_INVALID;
-		return CD_BUSY;
-	case SONY535_ATN_RESET_OCCURRED:
-	case SONY535_ATN_DISC_CHANGED:
-	case SONY535_ATN_RESET_AND_DISC_CHANGED:
-#if DEBUG > 0
-		printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
-#endif
-		sony_disc_changed = 1;
-		sony_toc_read = 0;
-		sony_audio_status = CDROM_AUDIO_NO_STATUS;
-		sony_first_block = -1;
-		sony_last_block = -1;
-		if (initialized) {
-			cmd = SONY535_SPIN_UP;
-			do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
-			sony_get_toc();
-		}
-		return 0;
-	default:
-		printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
-		return CD_BUSY;
-	}
-	switch (CDD) {			/* the 531 docs are not helpful in decoding this */
-	case 0x0:				/* just use the values from the DOS driver */
-	case 0x2:
-	case 0xa:
-		break;				/* no error */
-	case 0xc:
-		printk(CDU535_MESSAGE_NAME
-				": check_drive_status(): CDD = 0xc! Not properly handled!\n");
-		return CD_BUSY;		/* ? */
-	default:
-		return CD_BUSY;
-	}
-	return 0;
-}	/* check_drive_status() */
-
-/*****************************************************************************
- * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
- *                Byte *response, int n_response, int ignore_status_bit7 )
- *
- *  Generic routine for executing commands.  The command and its parameters
- *  should be placed in the cmd[] array, number of bytes in the command is
- *  stored in nCmd.  The response from the command will be stored in the
- *  response array.  The number of bytes you expect back (excluding status)
- *  should be passed in n_response.  Finally, some
- *  commands set bit 7 of the return status even when there is no second
- *  status byte, on these commands set ignoreStatusBit7 TRUE.
- *    If the command was sent and data received back, then we return 0,
- *  else we return TIME_OUT.  You still have to check the status yourself.
- *    You should call check_drive_status() before calling this routine
- *  so that you do not lose notifications of disk changes, etc.
- ****************************************************************************/
-static int
-do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
-			Byte * response, int n_response, int ignore_status_bit7)
-{
-	int i;
-
-	/* write out the command */
-	for (i = 0; i < n_cmd; i++)
-		outb(cmd[i], command_reg);
-
-	/* read back the status */
-	if (read_result_reg(status) != 0)
-		return TIME_OUT;
-	if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
-		/* get second status byte */
-		if (read_result_reg(status + 1) != 0)
-			return TIME_OUT;
-	} else {
-		status[1] = 0;
-	}
-#if DEBUG > 2
-	printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
-			*cmd, status[0], status[1]);
-#endif
-
-	/* do not know about when I should read set of data and when not to */
-	if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
-		return 0;
-
-	/* else, read in rest of data */
-	for (i = 0; 0 < n_response; n_response--, i++)
-		if (read_result_reg(response + i) != 0)
-			return TIME_OUT;
-	return 0;
-}	/* do_sony_cmd() */
-
-/**************************************************************************
- * int set_drive_mode( int mode, Byte status[2] )
- *
- *  Set the drive mode to the specified value (mode=0 is audio, mode=e0
- * is mode-1 CDROM
- **************************************************************************/
-static int
-set_drive_mode(int mode, Byte status[2])
-{
-	Byte cmd_buff[2];
-	Byte ret_buff[1];
-
-	cmd_buff[0] = SONY535_SET_DRIVE_MODE;
-	cmd_buff[1] = mode;
-	return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
-}
-
-/***************************************************************************
- * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
- *                             Byte *data_buff, int buff_size )
- *
- *  Read n_blocks of data from the CDROM starting at position params[0:2],
- *  number of blocks in stored in params[3:5] -- both these are already
- *  int bcd format.
- *  Transfer the data into the buffer pointed at by data_buff.  buff_size
- *  gives the number of bytes available in the buffer.
- *    The routine returns number of bytes read in if successful, otherwise
- *  it returns one of the standard error returns.
- ***************************************************************************/
-static int
-seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
-					   Byte **buff, int buf_size)
-{
-	Byte cmd_buff[7];
-	int  i;
-	int  read_status;
-	unsigned long snap;
-	Byte *data_buff;
-	int  sector_count = 0;
-
-	if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
-		return NO_ROOM;
-
-	set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
-
-	/* send command to read the data */
-	cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
-	for (i = 0; i < 6; i++)
-		cmd_buff[i + 1] = params[i];
-	for (i = 0; i < 7; i++)
-		outb(cmd_buff[i], command_reg);
-
-	/* read back the data one block at a time */
-	while (0 < n_blocks--) {
-		/* wait for data to be ready */
-		int data_valid = 0;
-		snap = jiffies;
-		while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-			read_status = inb(read_status_reg);
-			if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-				read_exec_status(status);
-				return BAD_STATUS;
-			}
-			if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
-				/* data is ready, read it */
-				data_buff = buff[sector_count++];
-				for (i = 0; i < CDU535_BLOCK_SIZE; i++)
-					*data_buff++ = inb(data_reg);	/* unrolling this loop does not seem to help */
-				data_valid = 1;
-				break;			/* exit the timeout loop */
-			}
-			sony_sleep();		/* data not ready, sleep a while */
-		}
-		if (!data_valid)
-			return TIME_OUT;	/* if we reach this stage */
-	}
-
-	/* read all the data, now read the status */
-	if ((i = read_exec_status(status)) != 0)
-		return i;
-	return CDU535_BLOCK_SIZE * sector_count;
-}	/* seek_and_read_N_blocks() */
-
-/****************************************************************************
- * int request_toc_data( Byte status[2], struct s535_sony_toc *toc )
- *
- *  Read in the table of contents data.  Converts all the bcd data
- * into integers in the toc structure.
- ****************************************************************************/
-static int
-request_toc_data(Byte status[2], struct s535_sony_toc *toc)
-{
-	int  to_status;
-	int  i, j, n_tracks, track_no;
-	int  first_track_num, last_track_num;
-	Byte cmd_no = 0xb2;
-	Byte track_address_buffer[5];
-
-	/* read the fixed portion of the table of contents */
-	if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
-		return to_status;
-
-	/* convert the data into integers so we can use them */
-	first_track_num = bcd_to_int(toc->first_track_num);
-	last_track_num = bcd_to_int(toc->last_track_num);
-	n_tracks = last_track_num - first_track_num + 1;
-
-	/* read each of the track address descriptors */
-	for (i = 0; i < n_tracks; i++) {
-		/* read the descriptor into a temporary buffer */
-		for (j = 0; j < 5; j++) {
-			if (read_result_reg(track_address_buffer + j) != 0)
-				return TIME_OUT;
-			if (j == 1)		/* need to convert from bcd */
-				track_no = bcd_to_int(track_address_buffer[j]);
-		}
-		/* copy the descriptor to proper location - sonycd.c just fills */
-		memcpy(toc->tracks + i, track_address_buffer, 5);
-	}
-	return 0;
-}	/* request_toc_data() */
-
-/***************************************************************************
- * int spin_up_drive( Byte status[2] )
- *
- *  Spin up the drive (unless it is already spinning).
- ***************************************************************************/
-static int
-spin_up_drive(Byte status[2])
-{
-	Byte cmd;
-
-	/* first see if the drive is already spinning */
-	cmd = SONY535_REQUEST_DRIVE_STATUS_1;
-	if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
-		return TIME_OUT;
-	if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
-		return 0;	/* it's already spinning */
-
-	/* otherwise, give the spin-up command */
-	cmd = SONY535_SPIN_UP;
-	return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
-}
-
-/*--------------------end of SONY CDU535 very specific ---------------------*/
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int
-int_to_bcd(unsigned int val)
-{
-	int retval;
-
-	retval = (val / 10) << 4;
-	retval = retval | val % 10;
-	return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int
-bcd_to_int(unsigned int bcd)
-{
-	return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void
-log_to_msf(unsigned int log, Byte *msf)
-{
-	log = log + LOG_START_OFFSET;
-	msf[0] = int_to_bcd(log / 4500);
-	log = log % 4500;
-	msf[1] = int_to_bcd(log / 75);
-	msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int
-msf_to_log(Byte *msf)
-{
-	unsigned int log;
-
-
-	log = bcd_to_int(msf[2]);
-	log += bcd_to_int(msf[1]) * 75;
-	log += bcd_to_int(msf[0]) * 4500;
-	log = log - LOG_START_OFFSET;
-
-	return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void
-size_to_buf(unsigned int size, Byte *buf)
-{
-	buf[0] = size / 65536;
-	size = size % 65536;
-	buf[1] = size / 256;
-	buf[2] = size % 256;
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail.  Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations.  This especially helps since the OS
- * may use 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void
-do_cdu535_request(request_queue_t * q)
-{
-	struct request *req;
-	unsigned int read_size;
-	int  block;
-	int  nsect;
-	int  copyoff;
-	int  spin_up_retry;
-	Byte params[10];
-	Byte status[2];
-	Byte cmd[2];
-
-	while (1) {
-		req = elv_next_request(q);
-		if (!req)
-			return;
-
-		block = req->sector;
-		nsect = req->nr_sectors;
-		if (!blk_fs_request(req)) {
-			end_request(req, 0);
-			continue;
-		}
-		if (rq_data_dir(req) == WRITE) {
-			end_request(req, 0);
-			continue;
-		}
-		/*
-		 * If the block address is invalid or the request goes beyond
-		 * the end of the media, return an error.
-		 */
-		if (sony_toc->lead_out_start_lba <= (block/4)) {
-			end_request(req, 0);
-			return;
-		}
-		if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
-			end_request(req, 0);
-			return;
-		}
-		while (0 < nsect) {
-			/*
-			 * If the requested sector is not currently in
-			 * the read-ahead buffer, it must be read in.
-			 */
-			if ((block < sony_first_block) || (sony_last_block < block)) {
-				sony_first_block = (block / 4) * 4;
-				log_to_msf(block / 4, params);
-				
-				/*
-				 * If the full read-ahead would go beyond the end of the media, trim
-				 * it back to read just till the end of the media.
-				 */
-				if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
-					sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
-					read_size = sony_toc->lead_out_start_lba - (block / 4);
-				} else {
-					sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
-					read_size = sony_buffer_sectors;
-				}
-				size_to_buf(read_size, &params[3]);
-				
-				/*
-				 * Read the data.  If the drive was not spinning,
-				 * spin it up and try some more.
-				 */
-				for (spin_up_retry=0 ;; ++spin_up_retry) {
-					/* This loop has been modified to support the Sony
-					 * CDU-510/515 series, thanks to Claudio Porfiri 
-					 * <C.Porfiri@nisms.tei.ericsson.se>.
-					 */
-					/*
-					 * This part is to deal with very slow hardware.  We
-					 * try at most MAX_SPINUP_RETRY times to read the same
-					 * block.  A check for seek_and_read_N_blocks' result is
-					 * performed; if the result is wrong, the CDROM's engine
-					 * is restarted and the operation is tried again.
-					 */
-					/*
-					 * 1995-06-01: The system got problems when downloading
-					 * from Slackware CDROM, the problem seems to be:
-					 * seek_and_read_N_blocks returns BAD_STATUS and we
-					 * should wait for a while before retrying, so a new
-					 * part was added to discriminate the return value from
-					 * seek_and_read_N_blocks for the various cases.
-					 */
-					int readStatus = seek_and_read_N_blocks(params, read_size,
-										status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
-					if (0 <= readStatus)	/* Good data; common case, placed first */
-						break;
-					if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
-						/* give up */
-						if (readStatus == NO_ROOM)
-							printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
-						else
-							printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
-							       status[0]);
-						sony_first_block = -1;
-						sony_last_block = -1;
-						end_request(req, 0);
-						return;
-					}
-					if (readStatus == BAD_STATUS) {
-						/* Sleep for a while, then retry */
-						set_current_state(TASK_INTERRUPTIBLE);
-						spin_unlock_irq(&sonycd535_lock);
-						schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
-						spin_lock_irq(&sonycd535_lock);
-					}
-#if DEBUG > 0
-					printk(CDU535_MESSAGE_NAME
-					       " debug: calling spin up when reading data!\n");
-#endif
-					cmd[0] = SONY535_SPIN_UP;
-					do_sony_cmd(cmd, 1, status, NULL, 0, 0);
-				}
-			}
-			/*
-			 * The data is in memory now, copy it to the buffer and advance to the
-			 * next block to read.
-			 */
-			copyoff = block - sony_first_block;
-			memcpy(req->buffer,
-			       sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-			
-			block += 1;
-			nsect -= 1;
-			req->buffer += 512;
-		}
-
-		end_request(req, 1);
-	}
-}
-
-/*
- * Read the table of contents from the drive and set sony_toc_read if
- * successful.
- */
-static void
-sony_get_toc(void)
-{
-	Byte status[2];
-	if (!sony_toc_read) {
-		/* do not call check_drive_status() from here since it can call this routine */
-		if (request_toc_data(status, sony_toc) < 0)
-			return;
-		sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
-		sony_toc_read = 1;
-	}
-}
-
-
-/*
- * Search for a specific track in the table of contents.  track is
- * passed in bcd format
- */
-static int
-find_track(int track)
-{
-	int i;
-	int num_tracks;
-
-
-	num_tracks = bcd_to_int(sony_toc->last_track_num) -
-		bcd_to_int(sony_toc->first_track_num) + 1;
-	for (i = 0; i < num_tracks; i++) {
-		if (sony_toc->tracks[i].track == track) {
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-/*
- * Read the subcode and put it int last_sony_subcode for future use.
- */
-static int
-read_subcode(void)
-{
-	Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
-	Byte status[2];
-	int  dsc_status;
-
-	if (check_drive_status() != 0)
-		return -EIO;
-
-	if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
-							   sizeof(struct s535_sony_subcode), 1)) != 0) {
-		printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
-				status[0], dsc_status);
-		return -EIO;
-	}
-	return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it.  If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing).  If the drive is paused or completed, the subcode information has
- * already been stored, just use that.  The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int
-sony_get_subchnl_info(void __user *arg)
-{
-	struct cdrom_subchnl schi;
-
-	/* Get attention stuff */
-	if (check_drive_status() != 0)
-		return -EIO;
-
-	sony_get_toc();
-	if (!sony_toc_read) {
-		return -EIO;
-	}
-	if (copy_from_user(&schi, arg, sizeof schi))
-		return -EFAULT;
-
-	switch (sony_audio_status) {
-	case CDROM_AUDIO_PLAY:
-		if (read_subcode() < 0) {
-			return -EIO;
-		}
-		break;
-
-	case CDROM_AUDIO_PAUSED:
-	case CDROM_AUDIO_COMPLETED:
-		break;
-
-	case CDROM_AUDIO_NO_STATUS:
-		schi.cdsc_audiostatus = sony_audio_status;
-		if (copy_to_user(arg, &schi, sizeof schi))
-			return -EFAULT;
-		return 0;
-		break;
-
-	case CDROM_AUDIO_INVALID:
-	case CDROM_AUDIO_ERROR:
-	default:
-		return -EIO;
-	}
-
-	schi.cdsc_audiostatus = sony_audio_status;
-	schi.cdsc_adr = last_sony_subcode->address;
-	schi.cdsc_ctrl = last_sony_subcode->control;
-	schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
-	schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
-	if (schi.cdsc_format == CDROM_MSF) {
-		schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
-		schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
-		schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
-
-		schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
-		schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
-		schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
-	} else if (schi.cdsc_format == CDROM_LBA) {
-		schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
-		schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
-	}
-	return copy_to_user(arg, &schi, sizeof schi) ? -EFAULT : 0;
-}
-
-
-/*
- * The big ugly ioctl handler.
- */
-static int
-cdu_ioctl(struct inode *inode,
-		  struct file *file,
-		  unsigned int cmd,
-		  unsigned long arg)
-{
-	Byte status[2];
-	Byte cmd_buff[10], params[10];
-	int  i;
-	int  dsc_status;
-	void __user *argp = (void __user *)arg;
-
-	if (check_drive_status() != 0)
-		return -EIO;
-
-	switch (cmd) {
-	case CDROMSTART:			/* Spin up the drive */
-		if (spin_up_drive(status) < 0) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
-					status[0]);
-			return -EIO;
-		}
-		return 0;
-		break;
-
-	case CDROMSTOP:			/* Spin down the drive */
-		cmd_buff[0] = SONY535_HOLD;
-		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
-		/*
-		 * Spin the drive down, ignoring the error if the disk was
-		 * already not spinning.
-		 */
-		sony_audio_status = CDROM_AUDIO_NO_STATUS;
-		cmd_buff[0] = SONY535_SPIN_DOWN;
-		dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-		if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
-			((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
-					status[0]);
-			return -EIO;
-		}
-		return 0;
-		break;
-
-	case CDROMPAUSE:			/* Pause the drive */
-		cmd_buff[0] = SONY535_HOLD;		/* CDU-31 driver uses AUDIO_STOP, not pause */
-		if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
-					status[0]);
-			return -EIO;
-		}
-		/* Get the current position and save it for resuming */
-		if (read_subcode() < 0) {
-			return -EIO;
-		}
-		cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
-		cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
-		cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
-		sony_audio_status = CDROM_AUDIO_PAUSED;
-		return 0;
-		break;
-
-	case CDROMRESUME:			/* Start the drive after being paused */
-		set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-		if (sony_audio_status != CDROM_AUDIO_PAUSED) {
-			return -EINVAL;
-		}
-		spin_up_drive(status);
-
-		/* Start the drive at the saved position. */
-		cmd_buff[0] = SONY535_PLAY_AUDIO;
-		cmd_buff[1] = 0;		/* play back starting at this address */
-		cmd_buff[2] = cur_pos_msf[0];
-		cmd_buff[3] = cur_pos_msf[1];
-		cmd_buff[4] = cur_pos_msf[2];
-		cmd_buff[5] = SONY535_PLAY_AUDIO;
-		cmd_buff[6] = 2;		/* set ending address */
-		cmd_buff[7] = final_pos_msf[0];
-		cmd_buff[8] = final_pos_msf[1];
-		cmd_buff[9] = final_pos_msf[2];
-		if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-			(do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
-					status[0]);
-			return -EIO;
-		}
-		sony_audio_status = CDROM_AUDIO_PLAY;
-		return 0;
-		break;
-
-	case CDROMPLAYMSF:			/* Play starting at the given MSF address. */
-		if (copy_from_user(params, argp, 6))
-			return -EFAULT;
-		spin_up_drive(status);
-		set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-		/* The parameters are given in int, must be converted */
-		for (i = 0; i < 3; i++) {
-			cmd_buff[2 + i] = int_to_bcd(params[i]);
-			cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
-		}
-		cmd_buff[0] = SONY535_PLAY_AUDIO;
-		cmd_buff[1] = 0;		/* play back starting at this address */
-		/* cmd_buff[2-4] are filled in for loop above */
-		cmd_buff[5] = SONY535_PLAY_AUDIO;
-		cmd_buff[6] = 2;		/* set ending address */
-		/* cmd_buff[7-9] are filled in for loop above */
-		if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-			(do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
-					status[0]);
-			return -EIO;
-		}
-		/* Save the final position for pauses and resumes */
-		final_pos_msf[0] = cmd_buff[7];
-		final_pos_msf[1] = cmd_buff[8];
-		final_pos_msf[2] = cmd_buff[9];
-		sony_audio_status = CDROM_AUDIO_PLAY;
-		return 0;
-		break;
-
-	case CDROMREADTOCHDR:		/* Read the table of contents header */
-		{
-			struct cdrom_tochdr __user *hdr = argp;
-			struct cdrom_tochdr loc_hdr;
-
-			sony_get_toc();
-			if (!sony_toc_read)
-				return -EIO;
-			loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
-			loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
-			if (copy_to_user(hdr, &loc_hdr, sizeof *hdr))
-				return -EFAULT;
-		}
-		return 0;
-		break;
-
-	case CDROMREADTOCENTRY:	/* Read a given table of contents entry */
-		{
-			struct cdrom_tocentry __user *entry = argp;
-			struct cdrom_tocentry loc_entry;
-			int  track_idx;
-			Byte *msf_val = NULL;
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				return -EIO;
-			}
-
-			if (copy_from_user(&loc_entry, entry, sizeof loc_entry))
-				return -EFAULT;
-
-			/* Lead out is handled separately since it is special. */
-			if (loc_entry.cdte_track == CDROM_LEADOUT) {
-				loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;
-				loc_entry.cdte_ctrl = sony_toc->control2;
-				msf_val = sony_toc->lead_out_start_msf;
-			} else {
-				track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
-				if (track_idx < 0)
-					return -EINVAL;
-				loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;
-				loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
-				msf_val = sony_toc->tracks[track_idx].track_start_msf;
-			}
-
-			/* Logical buffer address or MSF format requested? */
-			if (loc_entry.cdte_format == CDROM_LBA) {
-				loc_entry.cdte_addr.lba = msf_to_log(msf_val);
-			} else if (loc_entry.cdte_format == CDROM_MSF) {
-				loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
-				loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
-				loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
-			}
-			if (copy_to_user(entry, &loc_entry, sizeof *entry))
-				return -EFAULT;
-		}
-		return 0;
-		break;
-
-	case CDROMPLAYTRKIND:		/* Play a track.  This currently ignores index. */
-		{
-			struct cdrom_ti ti;
-			int track_idx;
-
-			sony_get_toc();
-			if (!sony_toc_read)
-				return -EIO;
-
-			if (copy_from_user(&ti, argp, sizeof ti))
-				return -EFAULT;
-			if ((ti.cdti_trk0 < sony_toc->first_track_num)
-				|| (sony_toc->last_track_num < ti.cdti_trk0)
-				|| (ti.cdti_trk1 < ti.cdti_trk0)) {
-				return -EINVAL;
-			}
-			track_idx = find_track(int_to_bcd(ti.cdti_trk0));
-			if (track_idx < 0)
-				return -EINVAL;
-			params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
-			params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
-			params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
-			/*
-			 * If we want to stop after the last track, use the lead-out
-			 * MSF to do that.
-			 */
-			if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
-				log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
-						   &(params[4]));
-			} else {
-				track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
-				if (track_idx < 0)
-					return -EINVAL;
-				log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
-						   &(params[4]));
-			}
-			params[0] = 0x03;
-
-			spin_up_drive(status);
-
-			set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-			/* Start the drive at the saved position. */
-			cmd_buff[0] = SONY535_PLAY_AUDIO;
-			cmd_buff[1] = 0;	/* play back starting at this address */
-			cmd_buff[2] = params[1];
-			cmd_buff[3] = params[2];
-			cmd_buff[4] = params[3];
-			cmd_buff[5] = SONY535_PLAY_AUDIO;
-			cmd_buff[6] = 2;	/* set ending address */
-			cmd_buff[7] = params[4];
-			cmd_buff[8] = params[5];
-			cmd_buff[9] = params[6];
-			if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-				(do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-				printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
-						status[0]);
-				printk("... Params: %x %x %x %x %x %x %x\n",
-						params[0], params[1], params[2],
-						params[3], params[4], params[5], params[6]);
-				return -EIO;
-			}
-			/* Save the final position for pauses and resumes */
-			final_pos_msf[0] = params[4];
-			final_pos_msf[1] = params[5];
-			final_pos_msf[2] = params[6];
-			sony_audio_status = CDROM_AUDIO_PLAY;
-			return 0;
-		}
-
-	case CDROMSUBCHNL:			/* Get subchannel info */
-		return sony_get_subchnl_info(argp);
-
-	case CDROMVOLCTRL:			/* Volume control.  What volume does this change, anyway? */
-		{
-			struct cdrom_volctrl volctrl;
-
-			if (copy_from_user(&volctrl, argp, sizeof volctrl))
-				return -EFAULT;
-			cmd_buff[0] = SONY535_SET_VOLUME;
-			cmd_buff[1] = volctrl.channel0;
-			cmd_buff[2] = volctrl.channel1;
-			if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
-				printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
-						status[0]);
-				return -EIO;
-			}
-		}
-		return 0;
-
-	case CDROMEJECT:			/* Eject the drive */
-		cmd_buff[0] = SONY535_STOP;
-		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-		cmd_buff[0] = SONY535_SPIN_DOWN;
-		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
-		sony_audio_status = CDROM_AUDIO_INVALID;
-		cmd_buff[0] = SONY535_EJECT_CADDY;
-		if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
-					status[0]);
-			return -EIO;
-		}
-		return 0;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-}
-
-
-/*
- * Open the drive for operations.  Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int
-cdu_open(struct inode *inode,
-		 struct file *filp)
-{
-	Byte status[2], cmd_buff[2];
-
-	if (sony_inuse)
-		return -EBUSY;
-	if (check_drive_status() != 0)
-		return -EIO;
-	sony_inuse = 1;
-
-	if (spin_up_drive(status) != 0) {
-		printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
-				status[0]);
-		sony_inuse = 0;
-		return -EIO;
-	}
-	sony_get_toc();
-	if (!sony_toc_read) {
-		cmd_buff[0] = SONY535_SPIN_DOWN;
-		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-		sony_inuse = 0;
-		return -EIO;
-	}
-	check_disk_change(inode->i_bdev);
-	sony_usage++;
-
-#ifdef LOCK_DOORS
-	/* disable the eject button while mounted */
-	cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
-	do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-#endif
-
-	return 0;
-}
-
-
-/*
- * Close the drive.  Spin it down if no task is using it.  The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static int
-cdu_release(struct inode *inode,
-			struct file *filp)
-{
-	Byte status[2], cmd_no;
-
-	sony_inuse = 0;
-
-	if (0 < sony_usage) {
-		sony_usage--;
-	}
-	if (sony_usage == 0) {
-		check_drive_status();
-
-		if (sony_audio_status != CDROM_AUDIO_PLAY) {
-			cmd_no = SONY535_SPIN_DOWN;
-			do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-		}
-#ifdef LOCK_DOORS
-		/* enable the eject button after umount */
-		cmd_no = SONY535_ENABLE_EJECT_BUTTON;
-		do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-#endif
-	}
-	return 0;
-}
-
-static struct block_device_operations cdu_fops =
-{
-	.owner		= THIS_MODULE,
-	.open		= cdu_open,
-	.release	= cdu_release,
-	.ioctl		= cdu_ioctl,
-	.media_changed	= cdu535_check_media_change,
-};
-
-static struct gendisk *cdu_disk;
-
-/*
- * Initialize the driver.
- */
-static int __init sony535_init(void)
-{
-	struct s535_sony_drive_config drive_config;
-	Byte cmd_buff[3];
-	Byte ret_buff[2];
-	Byte status[2];
-	unsigned long snap;
-	int  got_result = 0;
-	int  tmp_irq;
-	int  i;
-	int err;
-
-	/* Setting the base I/O address to 0 will disable it. */
-	if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
-		return 0;
-
-	/* Set up all the register locations */
-	result_reg = sony535_cd_base_io;
-	command_reg = sony535_cd_base_io;
-	data_reg = sony535_cd_base_io + 1;
-	read_status_reg = sony535_cd_base_io + 2;
-	select_unit_reg = sony535_cd_base_io + 3;
-
-#ifndef USE_IRQ
-	sony535_irq_used = 0;	/* polling only until this is ready... */
-#endif
-	/* we need to poll until things get initialized */
-	tmp_irq = sony535_irq_used;
-	sony535_irq_used = 0;
-
-#if DEBUG > 0
-	printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n",
-			sony535_cd_base_io);
-#endif
-	/* look for the CD-ROM, follows the procedure in the DOS driver */
-	inb(select_unit_reg);
-	/* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
-	schedule_timeout_interruptible((HZ+17)*40/18);
-	inb(result_reg);
-
-	outb(0, read_status_reg);	/* does a reset? */
-	snap = jiffies;
-	while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-		select_unit(0);
-		if (inb(result_reg) != 0xff) {
-			got_result = 1;
-			break;
-		}
-		sony_sleep();
-	}
-
-	if (!got_result || check_drive_status() == TIME_OUT)
-		goto Enodev;
-
-	/* CD-ROM drive responded --  get the drive configuration */
-	cmd_buff[0] = SONY535_INQUIRY;
-	if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0)
-		goto Enodev;
-
-	/* was able to get the configuration,
-	 * set drive mode as rest of init
-	 */
-#if DEBUG > 0
-	/* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
-	if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
-		printk(CDU535_MESSAGE_NAME
-				"Inquiry command returned status = 0x%x\n", status[0]);
-#endif
-	/* now ready to use interrupts, if available */
-	sony535_irq_used = tmp_irq;
-
-	/* A negative sony535_irq_used will attempt an autoirq. */
-	if (sony535_irq_used < 0) {
-		unsigned long irq_mask, delay;
-
-		irq_mask = probe_irq_on();
-		enable_interrupts();
-		outb(0, read_status_reg);	/* does a reset? */
-		delay = jiffies + HZ/10;
-		while (time_before(jiffies, delay)) ;
-
-		sony535_irq_used = probe_irq_off(irq_mask);
-		disable_interrupts();
-	}
-	if (sony535_irq_used > 0) {
-	    if (request_irq(sony535_irq_used, cdu535_interrupt,
-						IRQF_DISABLED, CDU535_HANDLE, NULL)) {
-			printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
-					" driver; polling instead.\n", sony535_irq_used);
-			sony535_irq_used = 0;
-		}
-	}
-	cmd_buff[0] = SONY535_SET_DRIVE_MODE;
-	cmd_buff[1] = 0x0;	/* default audio */
-	if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0)
-		goto Enodev_irq;
-
-	/* set the drive mode successful, we are set! */
-	sony_buffer_size = SONY535_BUFFER_SIZE;
-	sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
-
-	printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
-		   drive_config.vendor_id,
-		   drive_config.product_id,
-		   drive_config.product_rev_level);
-	printk("  base address %03X, ", sony535_cd_base_io);
-	if (tmp_irq > 0)
-		printk("IRQ%d, ", tmp_irq);
-	printk("using %d byte buffer\n", sony_buffer_size);
-
-	if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
-		err = -EIO;
-		goto out1;
-	}
-	sonycd535_queue = blk_init_queue(do_cdu535_request, &sonycd535_lock);
-	if (!sonycd535_queue) {
-		err = -ENOMEM;
-		goto out1a;
-	}
-
-	blk_queue_hardsect_size(sonycd535_queue, CDU535_BLOCK_SIZE);
-	sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
-	err = -ENOMEM;
-	if (!sony_toc)
-		goto out2;
-	last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL);
-	if (!last_sony_subcode)
-		goto out3;
-	sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL);
-	if (!sony_buffer)
-		goto out4;
-	for (i = 0; i < sony_buffer_sectors; i++) {
-		sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
-		if (!sony_buffer[i]) {
-			while (--i>=0)
-				kfree(sony_buffer[i]);
-			goto out5;
-		}
-	}
-	initialized = 1;
-
-	cdu_disk = alloc_disk(1);
-	if (!cdu_disk)
-		goto out6;
-	cdu_disk->major = MAJOR_NR;
-	cdu_disk->first_minor = 0;
-	cdu_disk->fops = &cdu_fops;
-	sprintf(cdu_disk->disk_name, "cdu");
-
-	if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) {
-		printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n",
-			sony535_cd_base_io);
-		goto out7;
-	}
-	cdu_disk->queue = sonycd535_queue;
-	add_disk(cdu_disk);
-	return 0;
-
-out7:
-	put_disk(cdu_disk);
-out6:
-	for (i = 0; i < sony_buffer_sectors; i++)
-		kfree(sony_buffer[i]);
-out5:
-	kfree(sony_buffer);
-out4:
-	kfree(last_sony_subcode);
-out3:
-	kfree(sony_toc);
-out2:
-	blk_cleanup_queue(sonycd535_queue);
-out1a:
-	unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
-out1:
-	if (sony535_irq_used)
-		free_irq(sony535_irq_used, NULL);
-	return err;
-Enodev_irq:
-	if (sony535_irq_used)
-		free_irq(sony535_irq_used, NULL);
-Enodev:
-	printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
-	return -EIO;
-}
-
-#ifndef MODULE
-
-/*
- * accept "kernel command line" parameters
- * (added by emoenke@gwdg.de)
- *
- * use: tell LILO:
- *                 sonycd535=0x320
- *
- * the address value has to be the existing CDROM port address.
- */
-static int __init
-sonycd535_setup(char *strings)
-{
-	int ints[3];
-	(void)get_options(strings, ARRAY_SIZE(ints), ints);
-	/* if IRQ change and default io base desired,
-	 * then call with io base of 0
-	 */
-	if (ints[0] > 0)
-		if (ints[1] != 0)
-			sony535_cd_base_io = ints[1];
-	if (ints[0] > 1)
-		sony535_irq_used = ints[2];
-	if ((strings != NULL) && (*strings != '\0'))
-		printk(CDU535_MESSAGE_NAME
-				": Warning: Unknown interface type: %s\n", strings);
-				
-	return 1;
-}
-
-__setup("sonycd535=", sonycd535_setup);
-
-#endif /* MODULE */
-
-static void __exit
-sony535_exit(void)
-{
-	int i;
-
-	release_region(sony535_cd_base_io, 4);
-	for (i = 0; i < sony_buffer_sectors; i++)
-		kfree(sony_buffer[i]);
-	kfree(sony_buffer);
-	kfree(last_sony_subcode);
-	kfree(sony_toc);
-	del_gendisk(cdu_disk);
-	put_disk(cdu_disk);
-	blk_cleanup_queue(sonycd535_queue);
-	if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
-		printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
-	else
-		printk(KERN_INFO CDU535_HANDLE " module released\n");
-}
-
-module_init(sony535_init);
-module_exit(sony535_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU535_CDROM_MAJOR);
diff --git a/drivers/cdrom/sonycd535.h b/drivers/cdrom/sonycd535.h
deleted file mode 100644
index 5dea1ef..0000000
--- a/drivers/cdrom/sonycd535.h
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef SONYCD535_H
-#define SONYCD535_H
-
-/*
- * define all the commands recognized by the CDU-531/5
- */
-#define SONY535_REQUEST_DRIVE_STATUS_1		(0x80)
-#define SONY535_REQUEST_SENSE			(0x82)
-#define SONY535_REQUEST_DRIVE_STATUS_2		(0x84)
-#define SONY535_REQUEST_ERROR_STATUS		(0x86)
-#define SONY535_REQUEST_AUDIO_STATUS		(0x88)
-#define SONY535_INQUIRY				(0x8a)
-
-#define SONY535_SET_INACTIVITY_TIME		(0x90)
-
-#define SONY535_SEEK_AND_READ_N_BLOCKS_1	(0xa0)
-#define SONY535_SEEK_AND_READ_N_BLOCKS_2	(0xa4)
-#define SONY535_PLAY_AUDIO			(0xa6)
-
-#define SONY535_REQUEST_DISC_CAPACITY		(0xb0)
-#define SONY535_REQUEST_TOC_DATA		(0xb2)
-#define SONY535_REQUEST_SUB_Q_DATA		(0xb4)
-#define SONY535_REQUEST_ISRC			(0xb6)
-#define SONY535_REQUEST_UPC_EAN			(0xb8)
-
-#define SONY535_SET_DRIVE_MODE			(0xc0)
-#define SONY535_REQUEST_DRIVE_MODE		(0xc2)
-#define SONY535_SET_RETRY_COUNT			(0xc4)
-
-#define SONY535_DIAGNOSTIC_1			(0xc6)
-#define SONY535_DIAGNOSTIC_4			(0xcc)
-#define SONY535_DIAGNOSTIC_5			(0xce)
-
-#define SONY535_EJECT_CADDY			(0xd0)
-#define SONY535_DISABLE_EJECT_BUTTON		(0xd2)
-#define SONY535_ENABLE_EJECT_BUTTON		(0xd4)
-
-#define SONY535_HOLD				(0xe0)
-#define SONY535_AUDIO_PAUSE_ON_OFF		(0xe2)
-#define SONY535_SET_VOLUME			(0xe8)
-
-#define SONY535_STOP				(0xf0)
-#define SONY535_SPIN_UP				(0xf2)
-#define SONY535_SPIN_DOWN			(0xf4)
-
-#define SONY535_CLEAR_PARAMETERS		(0xf6)
-#define SONY535_CLEAR_ENDING_ADDRESS		(0xf8)
-
-/*
- * define some masks
- */
-#define SONY535_DATA_NOT_READY_BIT		(0x1)
-#define SONY535_RESULT_NOT_READY_BIT		(0x2)
-
-/*
- *  drive status 1
- */
-#define SONY535_STATUS1_COMMAND_ERROR		(0x1)
-#define SONY535_STATUS1_DATA_ERROR		(0x2)
-#define SONY535_STATUS1_SEEK_ERROR		(0x4)
-#define SONY535_STATUS1_DISC_TYPE_ERROR		(0x8)
-#define SONY535_STATUS1_NOT_SPINNING		(0x10)
-#define SONY535_STATUS1_EJECT_BUTTON_PRESSED	(0x20)
-#define SONY535_STATUS1_CADDY_NOT_INSERTED	(0x40)
-#define SONY535_STATUS1_BYTE_TWO_FOLLOWS	(0x80)
-
-/*
- * drive status 2
- */
-#define SONY535_CDD_LOADING_ERROR		(0x7)
-#define SONY535_CDD_NO_DISC			(0x8)
-#define SONY535_CDD_UNLOADING_ERROR		(0x9)
-#define SONY535_CDD_CADDY_NOT_INSERTED		(0xd)
-#define SONY535_ATN_RESET_OCCURRED		(0x2)
-#define SONY535_ATN_DISC_CHANGED		(0x4)
-#define SONY535_ATN_RESET_AND_DISC_CHANGED	(0x6)
-#define SONY535_ATN_EJECT_IN_PROGRESS		(0xe)
-#define SONY535_ATN_BUSY			(0xf)
-
-/*
- * define some parameters
- */
-#define SONY535_AUDIO_DRIVE_MODE		(0)
-#define SONY535_CDROM_DRIVE_MODE		(0xe0)
-
-#define SONY535_PLAY_OP_PLAYBACK		(0)
-#define SONY535_PLAY_OP_ENTER_HOLD		(1)
-#define SONY535_PLAY_OP_SET_AUDIO_ENDING_ADDR	(2)
-#define SONY535_PLAY_OP_SCAN_FORWARD		(3)
-#define SONY535_PLAY_OP_SCAN_BACKWARD		(4)
-
-/*
- *  convert from msf format to block number 
- */
-#define SONY_BLOCK_NUMBER(m,s,f) (((m)*60L+(s))*75L+(f))
-#define SONY_BLOCK_NUMBER_MSF(x) (((x)[0]*60L+(x)[1])*75L+(x)[2])
-
-/*
- *  error return values from the doSonyCmd() routines
- */
-#define TIME_OUT			(-1)
-#define NO_CDROM			(-2)
-#define BAD_STATUS			(-3)
-#define CD_BUSY				(-4)
-#define NOT_DATA_CD			(-5)
-#define NO_ROOM				(-6)
-
-#define LOG_START_OFFSET        150     /* Offset of first logical sector */
-
-#define SONY_JIFFIES_TIMEOUT	(5*HZ)	/* Maximum time
-					   the drive will wait/try for an
-					   operation */
-#define SONY_READY_RETRIES      (50000)  /* How many times to retry a
-                                                  spin waiting for a register
-                                                  to come ready */
-#define SONY535_FAST_POLLS	(10000)   /* how many times recheck 
-                                                  status waiting for a data
-                                                  to become ready */
-
-typedef unsigned char Byte;
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s535_sony_drive_config
-{
-   char vendor_id[8];
-   char product_id[16];
-   char product_rev_level[4];
-};
-
-/* The following is returned from the request sub-q data command */
-struct s535_sony_subcode
-{
-   unsigned char address        :4;
-   unsigned char control        :4;
-   unsigned char track_num;
-   unsigned char index_num;
-   unsigned char rel_msf[3];
-   unsigned char abs_msf[3];
-};
-
-struct s535_sony_disc_capacity
-{
-   Byte mFirstTrack, sFirstTrack, fFirstTrack;
-   Byte mLeadOut, sLeadOut, fLeadOut;
-};
-
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s535_sony_toc
-{
-   unsigned char reserved0      :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char reserved0a;
-   unsigned char reserved0b;
-   unsigned char reserved1      :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char reserved2      :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char reserved    :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[100];
-
-   unsigned int lead_out_start_lba;
-};
-
-#endif /* SONYCD535_H */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index abcafac..d8d7125 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -114,7 +114,7 @@
 
 config ROCKETPORT
 	tristate "Comtrol RocketPort support"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
 	help
 	  This driver supports Comtrol RocketPort and RocketModem PCI boards.   
           These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
@@ -157,7 +157,7 @@
 
 config DIGIEPCA
 	tristate "Digiboard Intelligent Async Support"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
 	---help---
 	  This is a driver for Digi International's Xx, Xeve, and Xem series
 	  of cards which provide multiple serial ports. You would need
@@ -213,8 +213,6 @@
 	  This is upgraded (1.9.1) driver from original Moxa drivers with
 	  changes finally resulting in PCI probing.
 
-	  Use at your own risk.
-
 	  This driver can also be built as a module. The module will be called
 	  mxser_new. If you want to do that, say M here.
 
@@ -354,7 +352,7 @@
 
 config STALLION
 	tristate "Stallion EasyIO or EC8/32 support"
-	depends on STALDRV && BROKEN_ON_SMP
+	depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
 	help
 	  If you have an EasyIO or EasyConnection 8/32 multiport Stallion
 	  card, then this is for you; say Y.  Make sure to read
@@ -365,7 +363,7 @@
 
 config ISTALLION
 	tristate "Stallion EC8/64, ONboard, Brumby support"
-	depends on STALDRV && BROKEN_ON_SMP
+	depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
 	help
 	  If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
 	  serial multiport card, say Y here. Make sure to read
@@ -374,20 +372,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called istallion.
 
-config AU1000_UART
-	bool "Enable Au1000 UART Support"
-	depends on SERIAL_NONSTANDARD && MIPS
-	help
-	  If you have an Alchemy AU1000 processor (MIPS based) and you want
-	  to use serial ports, say Y.  Otherwise, say N.
-
-config AU1000_SERIAL_CONSOLE
-	bool "Enable Au1000 serial console"
-	depends on AU1000_UART
-	help
-	  If you have an Alchemy AU1000 processor (MIPS based) and you want
-	  to use a console on a serial port, say Y.  Otherwise, say N.
-
 config SERIAL_DEC
 	bool "DECstation serial support"
 	depends on MACH_DECSTATION
@@ -815,7 +799,7 @@
 
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
-	depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390
+	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -993,15 +977,14 @@
 	depends on CPU_VR41XX
 
 config RAW_DRIVER
-	tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
+	tristate "RAW driver (/dev/raw/rawN)"
 	depends on BLOCK
 	help
-	  The raw driver permits block devices to be bound to /dev/raw/rawN. 
-	  Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. 
+	  The raw driver permits block devices to be bound to /dev/raw/rawN.
+	  Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
 	  See the raw(8) manpage for more details.
 
-          The raw driver is deprecated and will be removed soon.
-          Applications should simply open the device (eg /dev/hda1)
+          Applications should preferably open the device (eg /dev/hda1)
           with the O_DIRECT flag.
 
 config MAX_RAW_DEVS
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 2f56ecc..f2996a9 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_VT)		+= vt_ioctl.o vc_screen.o consolemap.o \
 				   consolemap_deftbl.o selection.o keyboard.o
 obj-$(CONFIG_HW_CONSOLE)	+= vt.o defkeymap.o
+obj-$(CONFIG_AUDIT)		+= tty_audit.o
 obj-$(CONFIG_MAGIC_SYSRQ)	+= sysrq.o
 obj-$(CONFIG_ESPSERIAL)		+= esp.o
 obj-$(CONFIG_MVME147_SCC)	+= generic_serial.o vme_scc.o
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index fdbca25..35ab1a9 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -176,7 +176,7 @@
 #define I830_GMCH_MEM_MASK		0x1
 #define I830_GMCH_MEM_64M		0x1
 #define I830_GMCH_MEM_128M		0
-#define I830_GMCH_GMS_MASK		0x70
+#define I830_GMCH_GMS_MASK		0xF0
 #define I830_GMCH_GMS_DISABLED		0x00
 #define I830_GMCH_GMS_LOCAL		0x10
 #define I830_GMCH_GMS_STOLEN_512	0x20
@@ -231,6 +231,10 @@
 #define I965_PGETBL_SIZE_512KB	(0 << 1)
 #define I965_PGETBL_SIZE_256KB	(1 << 1)
 #define I965_PGETBL_SIZE_128KB	(2 << 1)
+#define G33_PGETBL_SIZE_MASK    (3 << 8)
+#define G33_PGETBL_SIZE_1M      (1 << 8)
+#define G33_PGETBL_SIZE_2M      (2 << 8)
+
 #define I810_DRAM_CTL		0x3000
 #define I810_DRAM_ROW_0		0x00000001
 #define I810_DRAM_ROW_0_SDRAM	0x00000001
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index e6c534e..df0ddf1 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -462,9 +462,7 @@
 	 * erratum 46: Setup violation on AGP SBA pins - Disable side band addressing.
 	 * With this lot disabled, we should prevent lockups. */
 	if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) {
-		u8 revision=0;
-		pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
-		if (revision == 0x10 || revision == 0x11) {
+		if (pdev->revision == 0x10 || pdev->revision == 0x11) {
 			agp_bridge->flags = AGP_ERRATA_FASTWRITES;
 			agp_bridge->flags |= AGP_ERRATA_SBA;
 			agp_bridge->flags |= AGP_ERRATA_1X;
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 801abdd..d95662e 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -367,10 +367,8 @@
 static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
 {
 	char *revstring;
-	u8 rev_id;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-	switch (rev_id) {
+	switch (pdev->revision) {
 	case 0x01: revstring="A0"; break;
 	case 0x02: revstring="A1"; break;
 	case 0x11: revstring="B0"; break;
@@ -386,7 +384,7 @@
 	 * Work around errata.
 	 * Chips before B2 stepping incorrectly reporting v3.5
 	 */
-	if (rev_id < 0x13) {
+	if (pdev->revision < 0x13) {
 		printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n");
 		bridge->major_version = 3;
 		bridge->minor_version = 0;
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index ebdd6dd..1b47c89a 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -321,7 +321,7 @@
 static int __init agp_init(void)
 {
 	if (!agp_off)
-		printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
+		printk(KERN_INFO "Linux agpgart interface v%d.%d\n",
 			AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
 	return 0;
 }
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 679d7f9..c7ed617 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -37,6 +37,7 @@
 #include <linux/agpgart.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include "agp.h"
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 45aeb91..d535c40 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -37,6 +37,7 @@
 #include <linux/vmalloc.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 9c69f2e..a124060 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -20,6 +20,14 @@
 #define PCI_DEVICE_ID_INTEL_82965G_IG       0x29A2
 #define PCI_DEVICE_ID_INTEL_82965GM_HB      0x2A00
 #define PCI_DEVICE_ID_INTEL_82965GM_IG      0x2A02
+#define PCI_DEVICE_ID_INTEL_82965GME_IG     0x2A12
+#define PCI_DEVICE_ID_INTEL_82945GME_IG     0x27AE
+#define PCI_DEVICE_ID_INTEL_G33_HB          0x29C0
+#define PCI_DEVICE_ID_INTEL_G33_IG          0x29C2
+#define PCI_DEVICE_ID_INTEL_Q35_HB          0x29B0
+#define PCI_DEVICE_ID_INTEL_Q35_IG          0x29B2
+#define PCI_DEVICE_ID_INTEL_Q33_HB          0x29D0
+#define PCI_DEVICE_ID_INTEL_Q33_IG          0x29D2
 
 #define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
                  agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
@@ -27,6 +35,9 @@
                  agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
                  agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB)
 
+#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB)
 
 extern int agp_memory_reserved;
 
@@ -53,6 +64,8 @@
 #define I915_PTEADDR	0x1C
 #define I915_GMCH_GMS_STOLEN_48M	(0x6 << 4)
 #define I915_GMCH_GMS_STOLEN_64M	(0x7 << 4)
+#define G33_GMCH_GMS_STOLEN_128M       (0x8 << 4)
+#define G33_GMCH_GMS_STOLEN_256M       (0x9 << 4)
 
 /* Intel 965G registers */
 #define I965_MSAC 0x62
@@ -86,11 +99,18 @@
 	 .type = INTEL_AGP_CACHED_MEMORY}
 };
 
-static struct _intel_i810_private {
-	struct pci_dev *i810_dev;	/* device one */
-	volatile u8 __iomem *registers;
+static struct _intel_private {
+	struct pci_dev *pcidev;	/* device one */
+	u8 __iomem *registers;
+	u32 __iomem *gtt;		/* I915G */
 	int num_dcache_entries;
-} intel_i810_private;
+	/* gtt_entries is the number of gtt entries that are already mapped
+	 * to stolen memory.  Stolen memory is larger than the memory mapped
+	 * through gtt_entries, as it includes some reserved space for the BIOS
+	 * popup and for the GTT.
+	 */
+	int gtt_entries;			/* i830+ */
+} intel_private;
 
 static int intel_i810_fetch_size(void)
 {
@@ -127,32 +147,32 @@
 
 	current_size = A_SIZE_FIX(agp_bridge->current_size);
 
-	if (!intel_i810_private.registers) {
-		pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
+	if (!intel_private.registers) {
+		pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
 		temp &= 0xfff80000;
 
-		intel_i810_private.registers = ioremap(temp, 128 * 4096);
-		if (!intel_i810_private.registers) {
+		intel_private.registers = ioremap(temp, 128 * 4096);
+		if (!intel_private.registers) {
 			printk(KERN_ERR PFX "Unable to remap memory.\n");
 			return -ENOMEM;
 		}
 	}
 
-	if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
+	if ((readl(intel_private.registers+I810_DRAM_CTL)
 		& I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
 		/* This will need to be dynamically assigned */
 		printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");
-		intel_i810_private.num_dcache_entries = 1024;
+		intel_private.num_dcache_entries = 1024;
 	}
-	pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);
+	pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-	writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL);
-	readl(intel_i810_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
+	writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+	readl(intel_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
 
 	if (agp_bridge->driver->needs_scratch_page) {
 		for (i = 0; i < current_size->num_entries; i++) {
-			writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
-			readl(intel_i810_private.registers+I810_PTE_BASE+(i*4));	/* PCI posting. */
+			writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+			readl(intel_private.registers+I810_PTE_BASE+(i*4));	/* PCI posting. */
 		}
 	}
 	global_cache_flush();
@@ -161,9 +181,9 @@
 
 static void intel_i810_cleanup(void)
 {
-	writel(0, intel_i810_private.registers+I810_PGETBL_CTL);
-	readl(intel_i810_private.registers);	/* PCI Posting. */
-	iounmap(intel_i810_private.registers);
+	writel(0, intel_private.registers+I810_PGETBL_CTL);
+	readl(intel_private.registers);	/* PCI Posting. */
+	iounmap(intel_private.registers);
 }
 
 static void intel_i810_tlbflush(struct agp_memory *mem)
@@ -261,9 +281,9 @@
 			global_cache_flush();
 		for (i = pg_start; i < (pg_start + mem->page_count); i++) {
 			writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
-			       intel_i810_private.registers+I810_PTE_BASE+(i*4));
+			       intel_private.registers+I810_PTE_BASE+(i*4));
 		}
-		readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
+		readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
 		break;
 	case AGP_PHYS_MEMORY:
 	case AGP_NORMAL_MEMORY:
@@ -273,9 +293,9 @@
 			writel(agp_bridge->driver->mask_memory(agp_bridge,
 							       mem->memory[i],
 							       mask_type),
-			       intel_i810_private.registers+I810_PTE_BASE+(j*4));
+			       intel_private.registers+I810_PTE_BASE+(j*4));
 		}
-		readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
+		readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
 		break;
 	default:
 		goto out_err;
@@ -298,9 +318,9 @@
 		return 0;
 
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
+		writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
 	}
-	readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
+	readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -354,7 +374,7 @@
 	struct agp_memory *new;
 
 	if (type == AGP_DCACHE_MEMORY) {
-		if (pg_count != intel_i810_private.num_dcache_entries)
+		if (pg_count != intel_private.num_dcache_entries)
 			return NULL;
 
 		new = agp_create_memory(1);
@@ -404,18 +424,6 @@
 	{512, 131072, 7},
 };
 
-static struct _intel_i830_private {
-	struct pci_dev *i830_dev;		/* device one */
-	volatile u8 __iomem *registers;
-	volatile u32 __iomem *gtt;		/* I915G */
-	/* gtt_entries is the number of gtt entries that are already mapped
-	 * to stolen memory.  Stolen memory is larger than the memory mapped
-	 * through gtt_entries, as it includes some reserved space for the BIOS
-	 * popup and for the GTT.
-	 */
-	int gtt_entries;
-} intel_i830_private;
-
 static void intel_i830_init_gtt_entries(void)
 {
 	u16 gmch_ctrl;
@@ -429,7 +437,7 @@
 
 	if (IS_I965) {
 		u32 pgetbl_ctl;
-		pgetbl_ctl = readl(intel_i830_private.registers+I810_PGETBL_CTL);
+		pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
 
 		/* The 965 has a field telling us the size of the GTT,
 		 * which may be larger than what is necessary to map the
@@ -451,6 +459,22 @@
 			size = 512;
 		}
 		size += 4; /* add in BIOS popup space */
+	} else if (IS_G33) {
+	/* G33's GTT size defined in gmch_ctrl */
+		switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
+		case G33_PGETBL_SIZE_1M:
+			size = 1024;
+			break;
+		case G33_PGETBL_SIZE_2M:
+			size = 2048;
+			break;
+		default:
+			printk(KERN_INFO PFX "Unknown page table size 0x%x, "
+				"assuming 512KB\n",
+				(gmch_ctrl & G33_PGETBL_SIZE_MASK));
+			size = 512;
+		}
+		size += 4;
 	} else {
 		/* On previous hardware, the GTT size was just what was
 		 * required to map the aperture.
@@ -471,7 +495,7 @@
 			gtt_entries = MB(8) - KB(size);
 			break;
 		case I830_GMCH_GMS_LOCAL:
-			rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
+			rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
 			gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
 					MB(ddt[I830_RDRAM_DDT(rdct)]);
 			local = 1;
@@ -502,7 +526,8 @@
 			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
 			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
 			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 )
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
+			    IS_I965 || IS_G33)
 				gtt_entries = MB(48) - KB(size);
 			else
 				gtt_entries = 0;
@@ -512,10 +537,24 @@
 			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
 			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
 			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965)
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
+			    IS_I965 || IS_G33)
 				gtt_entries = MB(64) - KB(size);
 			else
 				gtt_entries = 0;
+			break;
+		case G33_GMCH_GMS_STOLEN_128M:
+			if (IS_G33)
+				gtt_entries = MB(128) - KB(size);
+			else
+				gtt_entries = 0;
+			break;
+		case G33_GMCH_GMS_STOLEN_256M:
+			if (IS_G33)
+				gtt_entries = MB(256) - KB(size);
+			else
+				gtt_entries = 0;
+			break;
 		default:
 			gtt_entries = 0;
 			break;
@@ -529,7 +568,7 @@
 		       "No pre-allocated video memory detected.\n");
 	gtt_entries /= KB(4);
 
-	intel_i830_private.gtt_entries = gtt_entries;
+	intel_private.gtt_entries = gtt_entries;
 }
 
 /* The intel i830 automatically initializes the agp aperture during POST.
@@ -547,14 +586,14 @@
 	num_entries = size->num_entries;
 	agp_bridge->gatt_table_real = NULL;
 
-	pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
+	pci_read_config_dword(intel_private.pcidev,I810_MMADDR,&temp);
 	temp &= 0xfff80000;
 
-	intel_i830_private.registers = ioremap(temp,128 * 4096);
-	if (!intel_i830_private.registers)
+	intel_private.registers = ioremap(temp,128 * 4096);
+	if (!intel_private.registers)
 		return -ENOMEM;
 
-	temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+	temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
 	global_cache_flush();	/* FIXME: ?? */
 
 	/* we have to call this as early as possible after the MMIO base address is known */
@@ -614,20 +653,20 @@
 
 	current_size = A_SIZE_FIX(agp_bridge->current_size);
 
-	pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
+	pci_read_config_dword(intel_private.pcidev,I810_GMADDR,&temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
 	gmch_ctrl |= I830_GMCH_ENABLED;
 	pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
 
-	writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
-	readl(intel_i830_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
+	writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+	readl(intel_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
 
 	if (agp_bridge->driver->needs_scratch_page) {
-		for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
-			writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
-			readl(intel_i830_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */
+		for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
+			writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+			readl(intel_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */
 		}
 	}
 
@@ -637,7 +676,7 @@
 
 static void intel_i830_cleanup(void)
 {
-	iounmap(intel_i830_private.registers);
+	iounmap(intel_private.registers);
 }
 
 static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type)
@@ -653,9 +692,9 @@
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
 
-	if (pg_start < intel_i830_private.gtt_entries) {
-		printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
-				pg_start,intel_i830_private.gtt_entries);
+	if (pg_start < intel_private.gtt_entries) {
+		printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
+				pg_start,intel_private.gtt_entries);
 
 		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
 		goto out_err;
@@ -683,9 +722,9 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
 						       mem->memory[i], mask_type),
-		       intel_i830_private.registers+I810_PTE_BASE+(j*4));
+		       intel_private.registers+I810_PTE_BASE+(j*4));
 	}
-	readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
+	readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
 	agp_bridge->driver->tlb_flush(mem);
 
 out:
@@ -703,15 +742,15 @@
 	if (mem->page_count == 0)
 		return 0;
 
-	if (pg_start < intel_i830_private.gtt_entries) {
+	if (pg_start < intel_private.gtt_entries) {
 		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
 		return -EINVAL;
 	}
 
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
+		writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
 	}
-	readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
+	readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -734,7 +773,7 @@
 
 	current_size = A_SIZE_FIX(agp_bridge->current_size);
 
-	pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
+	pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp);
 
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
@@ -742,13 +781,13 @@
 	gmch_ctrl |= I830_GMCH_ENABLED;
 	pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
 
-	writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
-	readl(intel_i830_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
+	writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+	readl(intel_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
 
 	if (agp_bridge->driver->needs_scratch_page) {
-		for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
-			writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
-			readl(intel_i830_private.gtt+i);	/* PCI Posting. */
+		for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
+			writel(agp_bridge->scratch_page, intel_private.gtt+i);
+			readl(intel_private.gtt+i);	/* PCI Posting. */
 		}
 	}
 
@@ -758,8 +797,8 @@
 
 static void intel_i915_cleanup(void)
 {
-	iounmap(intel_i830_private.gtt);
-	iounmap(intel_i830_private.registers);
+	iounmap(intel_private.gtt);
+	iounmap(intel_private.registers);
 }
 
 static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -776,9 +815,9 @@
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
 
-	if (pg_start < intel_i830_private.gtt_entries) {
-		printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
-				pg_start,intel_i830_private.gtt_entries);
+	if (pg_start < intel_private.gtt_entries) {
+		printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
+				pg_start,intel_private.gtt_entries);
 
 		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
 		goto out_err;
@@ -805,10 +844,10 @@
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mask_type), intel_i830_private.gtt+j);
+			mem->memory[i], mask_type), intel_private.gtt+j);
 	}
 
-	readl(intel_i830_private.gtt+j-1);
+	readl(intel_private.gtt+j-1);
 	agp_bridge->driver->tlb_flush(mem);
 
  out:
@@ -826,15 +865,15 @@
 	if (mem->page_count == 0)
 		return 0;
 
-	if (pg_start < intel_i830_private.gtt_entries) {
+	if (pg_start < intel_private.gtt_entries) {
 		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
 		return -EINVAL;
 	}
 
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
+		writel(agp_bridge->scratch_page, intel_private.gtt+i);
 	}
-	readl(intel_i830_private.gtt+i-1);
+	readl(intel_private.gtt+i-1);
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -850,7 +889,7 @@
 	int aper_size; /* size in megabytes */
 	int i;
 
-	aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
+	aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1);
 
 	for (i = 0; i < num_sizes; i++) {
 		if (aper_size == intel_i830_sizes[i].size) {
@@ -878,20 +917,20 @@
 	num_entries = size->num_entries;
 	agp_bridge->gatt_table_real = NULL;
 
-	pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
-	pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
+	pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
+	pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2);
 
-	intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
-	if (!intel_i830_private.gtt)
+	intel_private.gtt = ioremap(temp2, 256 * 1024);
+	if (!intel_private.gtt)
 		return -ENOMEM;
 
 	temp &= 0xfff80000;
 
-	intel_i830_private.registers = ioremap(temp,128 * 4096);
-	if (!intel_i830_private.registers)
+	intel_private.registers = ioremap(temp,128 * 4096);
+	if (!intel_private.registers)
 		return -ENOMEM;
 
-	temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+	temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
 	global_cache_flush();	/* FIXME: ? */
 
 	/* we have to call this as early as possible after the MMIO base address is known */
@@ -938,20 +977,20 @@
        num_entries = size->num_entries;
        agp_bridge->gatt_table_real = NULL;
 
-       pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
+       pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
 
        temp &= 0xfff00000;
-       intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
+       intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
 
-       if (!intel_i830_private.gtt)
+       if (!intel_private.gtt)
                return -ENOMEM;
 
 
-       intel_i830_private.registers = ioremap(temp,128 * 4096);
-       if (!intel_i830_private.registers)
+       intel_private.registers = ioremap(temp,128 * 4096);
+       if (!intel_private.registers)
                return -ENOMEM;
 
-       temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+       temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
        global_cache_flush();   /* FIXME: ? */
 
        /* we have to call this as early as possible after the MMIO base address is known */
@@ -1722,41 +1761,127 @@
 	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static int find_i810(u16 device)
+static const struct agp_bridge_driver intel_g33_driver = {
+	.owner                  = THIS_MODULE,
+	.aperture_sizes         = intel_i830_sizes,
+	.size_type              = FIXED_APER_SIZE,
+	.num_aperture_sizes     = 4,
+	.needs_scratch_page     = TRUE,
+	.configure              = intel_i915_configure,
+	.fetch_size             = intel_i9xx_fetch_size,
+	.cleanup                = intel_i915_cleanup,
+	.tlb_flush              = intel_i810_tlbflush,
+	.mask_memory            = intel_i965_mask_memory,
+	.masks                  = intel_i810_masks,
+	.agp_enable             = intel_i810_agp_enable,
+	.cache_flush            = global_cache_flush,
+	.create_gatt_table      = intel_i915_create_gatt_table,
+	.free_gatt_table        = intel_i830_free_gatt_table,
+	.insert_memory          = intel_i915_insert_entries,
+	.remove_memory          = intel_i915_remove_entries,
+	.alloc_by_type          = intel_i830_alloc_by_type,
+	.free_by_type           = intel_i810_free_by_type,
+	.agp_alloc_page         = agp_generic_alloc_page,
+	.agp_destroy_page       = agp_generic_destroy_page,
+	.agp_type_to_mask_type  = intel_i830_type_to_mask_type,
+};
+
+static int find_gmch(u16 device)
 {
-	struct pci_dev *i810_dev;
+	struct pci_dev *gmch_device;
 
-	i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
-	if (!i810_dev)
-		return 0;
-	intel_i810_private.i810_dev = i810_dev;
-	return 1;
-}
-
-static int find_i830(u16 device)
-{
-	struct pci_dev *i830_dev;
-
-	i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
-	if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
-		i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
-				device, i830_dev);
+	gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
+	if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
+		gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                device, gmch_device);
 	}
 
-	if (!i830_dev)
+	if (!gmch_device)
 		return 0;
 
-	intel_i830_private.i830_dev = i830_dev;
+	intel_private.pcidev = gmch_device;
 	return 1;
 }
 
+/* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of
+ * driver and gmch_driver must be non-null, and find_gmch will determine
+ * which one should be used if a gmch_chip_id is present.
+ */
+static const struct intel_driver_description {
+	unsigned int chip_id;
+	unsigned int gmch_chip_id;
+	unsigned int multi_gmch_chip; /* if we have more gfx chip type on this HB. */
+	char *name;
+	const struct agp_bridge_driver *driver;
+	const struct agp_bridge_driver *gmch_driver;
+} intel_agp_chipsets[] = {
+	{ PCI_DEVICE_ID_INTEL_82443LX_0, 0, 0, "440LX", &intel_generic_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82443BX_0, 0, 0, "440BX", &intel_generic_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82443GX_0, 0, 0, "440GX", &intel_generic_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, 0, "i810",
+		NULL, &intel_810_driver },
+	{ PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, 0, "i810",
+		NULL, &intel_810_driver },
+	{ PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, 0, "i810",
+		NULL, &intel_810_driver },
+	{ PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, 0, "i815",
+		&intel_815_driver, &intel_810_driver },
+	{ PCI_DEVICE_ID_INTEL_82820_HB, 0, 0, "i820", &intel_820_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, 0, "i820", &intel_820_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, 0, "830M",
+		&intel_830mp_driver, &intel_830_driver },
+	{ PCI_DEVICE_ID_INTEL_82840_HB, 0, 0, "i840", &intel_840_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82845_HB, 0, 0, "845G", &intel_845_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M",
+		&intel_845_driver, &intel_830_driver },
+	{ PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM",
+		&intel_845_driver, &intel_830_driver },
+	{ PCI_DEVICE_ID_INTEL_82860_HB, 0, 0, "i860", &intel_860_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, 0, "865",
+		&intel_845_driver, &intel_830_driver },
+	{ PCI_DEVICE_ID_INTEL_82875_HB, 0, 0, "i875", &intel_845_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, 0, "915G",
+		NULL, &intel_915_driver },
+	{ PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, 0, "915GM",
+		NULL, &intel_915_driver },
+	{ PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G",
+		NULL, &intel_915_driver },
+	{ PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 1, "945GM",
+		NULL, &intel_915_driver },
+	{ PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
+		NULL, &intel_915_driver },
+	{ PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
+		NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_82965G_1_HB, PCI_DEVICE_ID_INTEL_82965G_1_IG, 0, "965G",
+		NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, 0, "965Q",
+		NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G",
+		NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 1, "965GM",
+		NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
+		NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL },
+	{ PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, 0, "G33",
+		NULL, &intel_g33_driver },
+	{ PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, 0, "Q35",
+		NULL, &intel_g33_driver },
+	{ PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
+		NULL, &intel_g33_driver },
+	{ 0, 0, 0, NULL, NULL, NULL }
+};
+
 static int __devinit agp_intel_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
 	struct agp_bridge_data *bridge;
-	char *name = "(unknown)";
 	u8 cap_ptr = 0;
 	struct resource *r;
+	int i;
 
 	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 
@@ -1764,195 +1889,49 @@
 	if (!bridge)
 		return -ENOMEM;
 
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_INTEL_82443LX_0:
-		bridge->driver = &intel_generic_driver;
-		name = "440LX";
-		break;
-	case PCI_DEVICE_ID_INTEL_82443BX_0:
-		bridge->driver = &intel_generic_driver;
-		name = "440BX";
-		break;
-	case PCI_DEVICE_ID_INTEL_82443GX_0:
-		bridge->driver = &intel_generic_driver;
-		name = "440GX";
-		break;
-	case PCI_DEVICE_ID_INTEL_82810_MC1:
-		name = "i810";
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1))
-			goto fail;
-		bridge->driver = &intel_810_driver;
-		break;
-	case PCI_DEVICE_ID_INTEL_82810_MC3:
-		name = "i810 DC100";
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3))
-			goto fail;
-		bridge->driver = &intel_810_driver;
-		break;
-	case PCI_DEVICE_ID_INTEL_82810E_MC:
-		name = "i810 E";
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG))
-			goto fail;
-		bridge->driver = &intel_810_driver;
-		break;
-	 case PCI_DEVICE_ID_INTEL_82815_MC:
-		/*
-		 * The i815 can operate either as an i810 style
-		 * integrated device, or as an AGP4X motherboard.
-		 */
-		if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC))
-			bridge->driver = &intel_810_driver;
-		else
-			bridge->driver = &intel_815_driver;
-		name = "i815";
-		break;
-	case PCI_DEVICE_ID_INTEL_82820_HB:
-	case PCI_DEVICE_ID_INTEL_82820_UP_HB:
-		bridge->driver = &intel_820_driver;
-		name = "i820";
-		break;
-	case PCI_DEVICE_ID_INTEL_82830_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC))
-			bridge->driver = &intel_830_driver;
-		else
-			bridge->driver = &intel_830mp_driver;
-		name = "830M";
-		break;
-	case PCI_DEVICE_ID_INTEL_82840_HB:
-		bridge->driver = &intel_840_driver;
-		name = "i840";
-		break;
-	case PCI_DEVICE_ID_INTEL_82845_HB:
-		bridge->driver = &intel_845_driver;
-		name = "i845";
-		break;
-	case PCI_DEVICE_ID_INTEL_82845G_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG))
-			bridge->driver = &intel_830_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "845G";
-		break;
-	case PCI_DEVICE_ID_INTEL_82850_HB:
-		bridge->driver = &intel_850_driver;
-		name = "i850";
-		break;
-	case PCI_DEVICE_ID_INTEL_82855PM_HB:
-		bridge->driver = &intel_845_driver;
-		name = "855PM";
-		break;
-	case PCI_DEVICE_ID_INTEL_82855GM_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) {
-			bridge->driver = &intel_830_driver;
-			name = "855";
-		} else {
-			bridge->driver = &intel_845_driver;
-			name = "855GM";
+	for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
+		/* In case that multiple models of gfx chip may
+		   stand on same host bridge type, this can be
+		   sure we detect the right IGD. */
+		if (pdev->device == intel_agp_chipsets[i].chip_id) {
+			if ((intel_agp_chipsets[i].gmch_chip_id != 0) &&
+				find_gmch(intel_agp_chipsets[i].gmch_chip_id)) {
+				bridge->driver =
+					intel_agp_chipsets[i].gmch_driver;
+				break;
+			} else if (intel_agp_chipsets[i].multi_gmch_chip) {
+				continue;
+			} else {
+				bridge->driver = intel_agp_chipsets[i].driver;
+				break;
+			}
 		}
-		break;
-	case PCI_DEVICE_ID_INTEL_82860_HB:
-		bridge->driver = &intel_860_driver;
-		name = "i860";
-		break;
-	case PCI_DEVICE_ID_INTEL_82865_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG))
-			bridge->driver = &intel_830_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "865";
-		break;
-	case PCI_DEVICE_ID_INTEL_82875_HB:
-		bridge->driver = &intel_845_driver;
-		name = "i875";
-		break;
-	case PCI_DEVICE_ID_INTEL_82915G_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG))
-			bridge->driver = &intel_915_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "915G";
-		break;
-	case PCI_DEVICE_ID_INTEL_82915GM_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG))
-			bridge->driver = &intel_915_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "915GM";
-		break;
-	case PCI_DEVICE_ID_INTEL_82945G_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG))
-			bridge->driver = &intel_915_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "945G";
-		break;
-	case PCI_DEVICE_ID_INTEL_82945GM_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG))
-			bridge->driver = &intel_915_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "945GM";
-		break;
-	case PCI_DEVICE_ID_INTEL_82946GZ_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG))
-			bridge->driver = &intel_i965_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "946GZ";
-		break;
-	case PCI_DEVICE_ID_INTEL_82965G_1_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG))
-			bridge->driver = &intel_i965_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "965G";
-		break;
-	case PCI_DEVICE_ID_INTEL_82965Q_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG))
-			bridge->driver = &intel_i965_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "965Q";
-		break;
-	case PCI_DEVICE_ID_INTEL_82965G_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG))
-			bridge->driver = &intel_i965_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "965G";
-		break;
-	case PCI_DEVICE_ID_INTEL_82965GM_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82965GM_IG))
-			bridge->driver = &intel_i965_driver;
-		else
-			bridge->driver = &intel_845_driver;
-		name = "965GM";
-		break;
-	case PCI_DEVICE_ID_INTEL_7505_0:
-		bridge->driver = &intel_7505_driver;
-		name = "E7505";
-		break;
-	case PCI_DEVICE_ID_INTEL_7205_0:
-		bridge->driver = &intel_7505_driver;
-		name = "E7205";
-		break;
-	default:
+	}
+
+	if (intel_agp_chipsets[i].name == NULL) {
 		if (cap_ptr)
-			printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n",
-			    pdev->device);
+			printk(KERN_WARNING PFX "Unsupported Intel chipset"
+                               "(device id: %04x)\n", pdev->device);
 		agp_put_bridge(bridge);
 		return -ENODEV;
-	};
+	}
+
+	if (bridge->driver == NULL) {
+		/* bridge has no AGP and no IGD detected */
+		if (cap_ptr)
+			printk(KERN_WARNING PFX "Failed to find bridge device "
+				"(chip_id: %04x)\n",
+				intel_agp_chipsets[i].gmch_chip_id);
+		agp_put_bridge(bridge);
+		return -ENODEV;
+        }
 
 	bridge->dev = pdev;
 	bridge->capndx = cap_ptr;
+	bridge->dev_private_data = &intel_private;
 
-	if (bridge->driver == &intel_810_driver)
-		bridge->dev_private_data = &intel_i810_private;
-	else if (bridge->driver == &intel_830_driver)
-		bridge->dev_private_data = &intel_i830_private;
-
-	printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
+	printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n",
+		intel_agp_chipsets[i].name);
 
 	/*
 	* The following fixes the case where the BIOS has "forgotten" to
@@ -1988,12 +1967,6 @@
 
 	pci_set_drvdata(pdev, bridge);
 	return agp_add_bridge(bridge);
-
-fail:
-	printk(KERN_ERR PFX "Detected an Intel %s chipset, "
-		"but could not find the secondary device.\n", name);
-	agp_put_bridge(bridge);
-	return -ENODEV;
 }
 
 static void __devexit agp_intel_remove(struct pci_dev *pdev)
@@ -2002,10 +1975,8 @@
 
 	agp_remove_bridge(bridge);
 
-	if (intel_i810_private.i810_dev)
-		pci_dev_put(intel_i810_private.i810_dev);
-	if (intel_i830_private.i830_dev)
-		pci_dev_put(intel_i830_private.i830_dev);
+	if (intel_private.pcidev)
+		pci_dev_put(intel_private.pcidev);
 
 	agp_put_bridge(bridge);
 }
@@ -2021,10 +1992,8 @@
 	 * as host bridge (00:00) resumes before graphics device (02:00),
 	 * then our access to its pci space can work right.
 	 */
-	if (intel_i810_private.i810_dev)
-		pci_restore_state(intel_i810_private.i810_dev);
-	if (intel_i830_private.i830_dev)
-		pci_restore_state(intel_i830_private.i830_dev);
+	if (intel_private.pcidev)
+		pci_restore_state(intel_private.pcidev);
 
 	if (bridge->driver == &intel_generic_driver)
 		intel_configure();
@@ -2087,6 +2056,9 @@
 	ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
 	ID(PCI_DEVICE_ID_INTEL_82965G_HB),
 	ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
+	ID(PCI_DEVICE_ID_INTEL_G33_HB),
+	ID(PCI_DEVICE_ID_INTEL_Q35_HB),
+	ID(PCI_DEVICE_ID_INTEL_Q33_HB),
 	{ }
 };
 
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 4eaceab..7b02bf1 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -738,6 +738,7 @@
 	}
 	/* If the quotient is zero refuse the change */
 	if (!quot && old_termios) {
+		/* FIXME: Will need updating for new tty in the end */
 		info->tty->termios->c_cflag &= ~CBAUD;
 		info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
 		baud = tty_get_baud_rate(info->tty);
@@ -783,7 +784,6 @@
 	/*
 	 * Set up parity check flag
 	 */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 
 	info->read_status_mask = UART_LSR_OE | UART_LSR_DR;
 	if (I_INPCK(info->tty))
@@ -1367,11 +1367,6 @@
 	unsigned long flags;
 	unsigned int cflag = tty->termios->c_cflag;
 
-	if (   (cflag == old_termios->c_cflag)
-	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
 	change_speed(info, old_termios);
 
 	/* Handle transition to B0 status */
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 179c7a3..ec116df 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/pm.h>
 #include <linux/apm-emulation.h>
+#include <linux/freezer.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -329,13 +330,8 @@
 			/*
 			 * Wait for the suspend/resume to complete.  If there
 			 * are pending acknowledges, we wait here for them.
-			 *
-			 * Note: we need to ensure that the PM subsystem does
-			 * not kick us out of the wait when it suspends the
-			 * threads.
 			 */
 			flags = current->flags;
-			current->flags |= PF_NOFREEZE;
 
 			wait_event(apm_suspend_waitqueue,
 				   as->suspend_state == SUSPEND_DONE);
@@ -365,13 +361,8 @@
 			/*
 			 * Wait for the suspend/resume to complete.  If there
 			 * are pending acknowledges, we wait here for them.
-			 *
-			 * Note: we need to ensure that the PM subsystem does
-			 * not kick us out of the wait when it suspends the
-			 * threads.
 			 */
 			flags = current->flags;
-			current->flags |= PF_NOFREEZE;
 
 			wait_event_interruptible(apm_suspend_waitqueue,
 					 as->suspend_state == SUSPEND_DONE);
@@ -598,7 +589,6 @@
 		kapmd_tsk = NULL;
 		return ret;
 	}
-	kapmd_tsk->flags |= PF_NOFREEZE;
 	wake_up_process(kapmd_tsk);
 
 #ifdef CONFIG_PROC_FS
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index ed53f54..b6f2639 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -91,11 +91,6 @@
 	unsigned short c;
 	unsigned char cp;
 
-#if 0	/*  Can't seek (pread) on this device  */
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-#endif
-
 	if (!vfd_is_open)
 		return -ENODEV;
 
@@ -139,11 +134,6 @@
 	size_t indx = len;
 	int i, esc = 0;
 
-#if 0	/*  Can't seek (pwrite) on this device  */
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-#endif
-
 	if (!vfd_is_open)
 		return -EBUSY;
 
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index fd40b95..4b3916f 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -177,6 +177,7 @@
 	unsigned long	refcount;
 	unsigned long	sum;
 	unsigned char	*inverse_translations[4];
+	u16		*inverse_trans_unicode;
 	int		readonly;
 };
 
@@ -207,6 +208,41 @@
 	}
 }
 
+static void set_inverse_trans_unicode(struct vc_data *conp,
+				      struct uni_pagedir *p)
+{
+	int i, j, k, glyph;
+	u16 **p1, *p2;
+	u16 *q;
+
+	if (!p) return;
+	q = p->inverse_trans_unicode;
+	if (!q) {
+		q = p->inverse_trans_unicode =
+			kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
+		if (!q)
+			return;
+	}
+	memset(q, 0, MAX_GLYPH * sizeof(u16));
+
+	for (i = 0; i < 32; i++) {
+		p1 = p->uni_pgdir[i];
+		if (!p1)
+			continue;
+		for (j = 0; j < 32; j++) {
+			p2 = p1[j];
+			if (!p2)
+				continue;
+			for (k = 0; k < 64; k++) {
+				glyph = p2[k];
+				if (glyph >= 0 && glyph < MAX_GLYPH
+					       && q[glyph] < 32)
+		  			q[glyph] = (i << 11) + (j << 6) + k;
+			}
+		}
+	}
+}
+
 unsigned short *set_translate(int m, struct vc_data *vc)
 {
 	inv_translate[vc->vc_num] = m;
@@ -217,19 +253,29 @@
  * Inverse translation is impossible for several reasons:
  * 1. The font<->character maps are not 1-1.
  * 2. The text may have been written while a different translation map
- *    was active, or using Unicode.
+ *    was active.
  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
  */
-unsigned char inverse_translate(struct vc_data *conp, int glyph)
+u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
 {
 	struct uni_pagedir *p;
+	int m;
 	if (glyph < 0 || glyph >= MAX_GLYPH)
 		return 0;
-	else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
-		 !p->inverse_translations[inv_translate[conp->vc_num]])
+	else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
 		return glyph;
-	else
-		return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
+	else if (use_unicode) {
+		if (!p->inverse_trans_unicode)
+			return glyph;
+		else
+			return p->inverse_trans_unicode[glyph];
+	} else {
+		m = inv_translate[conp->vc_num];
+		if (!p->inverse_translations[m])
+			return glyph;
+		else
+			return p->inverse_translations[m][glyph];
+	}
 }
 
 static void update_user_maps(void)
@@ -243,6 +289,7 @@
 		p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
 		if (p && p != q) {
 			set_inverse_transl(vc_cons[i].d, p, USER_MAP);
+			set_inverse_trans_unicode(vc_cons[i].d, p);
 			q = p;
 		}
 	}
@@ -353,6 +400,10 @@
 		kfree(p->inverse_translations[i]);
 		p->inverse_translations[i] = NULL;
 	}
+	if (p->inverse_trans_unicode) {
+		kfree(p->inverse_trans_unicode);
+		p->inverse_trans_unicode = NULL;
+	}
 }
 
 void con_free_unimap(struct vc_data *vc)
@@ -511,6 +562,7 @@
 
 	for (i = 0; i <= 3; i++)
 		set_inverse_transl(vc, p, i); /* Update all inverse translations */
+	set_inverse_trans_unicode(vc, p);
   
 	return err;
 }
@@ -561,6 +613,7 @@
 
 	for (i = 0; i <= 3; i++)
 		set_inverse_transl(vc, p, i);	/* Update all inverse translations */
+	set_inverse_trans_unicode(vc, p);
 	dflt = p;
 	return err;
 }
@@ -617,6 +670,19 @@
 		p->readonly = rdonly;
 }
 
+/* may be called during an interrupt */
+u32 conv_8bit_to_uni(unsigned char c)
+{
+	/*
+	 * Always use USER_MAP. This function is used by the keyboard,
+	 * which shouldn't be affected by G0/G1 switching, etc.
+	 * If the user map still contains default values, i.e. the
+	 * direct-to-font mapping, then assume user is using Latin1.
+	 */
+	unsigned short uni = translations[USER_MAP][c];
+	return uni == (0xf000 | c) ? c : uni;
+}
+
 int
 conv_uni_to_pc(struct vc_data *conp, long ucs) 
 {
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index c72ee97d..9e0adfe 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -646,6 +646,7 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
+#include <linux/firmware.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -680,6 +681,44 @@
 
 #define STD_COM_FLAGS (0)
 
+/* firmware stuff */
+#define ZL_MAX_BLOCKS	16
+#define DRIVER_VERSION	0x02010203
+#define RAM_SIZE 0x80000
+
+#define Z_FPGA_LOADED(X)	((readl(&(X)->init_ctrl) & (1<<17)) != 0)
+
+enum zblock_type {
+	ZBLOCK_PRG = 0,
+	ZBLOCK_FPGA = 1
+};
+
+struct zfile_header {
+	char name[64];
+	char date[32];
+	char aux[32];
+	u32 n_config;
+	u32 config_offset;
+	u32 n_blocks;
+	u32 block_offset;
+	u32 reserved[9];
+} __attribute__ ((packed));
+
+struct zfile_config {
+	char name[64];
+	u32 mailbox;
+	u32 function;
+	u32 n_blocks;
+	u32 block_list[ZL_MAX_BLOCKS];
+} __attribute__ ((packed));
+
+struct zfile_block {
+	u32 type;
+	u32 file_offset;
+	u32 ram_offset;
+	u32 size;
+} __attribute__ ((packed));
+
 static struct tty_driver *cy_serial_driver;
 
 #ifdef CONFIG_ISA
@@ -1061,6 +1100,7 @@
 
 				if (data & info->ignore_status_mask) {
 					info->icount.rx++;
+					spin_unlock(&cinfo->card_lock);
 					return;
 				}
 				if (tty_buffer_request_room(tty, 1)) {
@@ -1850,11 +1890,11 @@
 	struct cyclades_card *cinfo;
 	struct cyclades_port *info;
 	struct tty_struct *tty;
-	static struct FIRM_ID *firm_id;
-	static struct ZFW_CTRL *zfw_ctrl;
-	static struct BOARD_CTRL *board_ctrl;
-	static struct CH_CTRL *ch_ctrl;
-	static struct BUF_CTRL *buf_ctrl;
+	struct FIRM_ID __iomem *firm_id;
+	struct ZFW_CTRL __iomem *zfw_ctrl;
+	struct BOARD_CTRL __iomem *board_ctrl;
+	struct CH_CTRL __iomem *ch_ctrl;
+	struct BUF_CTRL __iomem *buf_ctrl;
 	unsigned long expires = jiffies + HZ;
 	int card, port;
 
@@ -1998,7 +2038,6 @@
 		struct ZFW_CTRL __iomem *zfw_ctrl;
 		struct BOARD_CTRL __iomem *board_ctrl;
 		struct CH_CTRL __iomem *ch_ctrl;
-		int retval;
 
 		base_addr = card->base_addr;
 
@@ -2370,7 +2409,6 @@
 		struct ZFW_CTRL __iomem *zfw_ctrl;
 		struct BOARD_CTRL __iomem *board_ctrl;
 		struct CH_CTRL __iomem *ch_ctrl;
-		int retval;
 
 		base_addr = cinfo->base_addr;
 		firm_id = base_addr + ID_ADDRESS;
@@ -4126,10 +4164,6 @@
 	printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
 #endif
 
-	if (tty->termios->c_cflag == old_termios->c_cflag &&
-			(tty->termios->c_iflag & (IXON | IXANY)) ==
-			(old_termios->c_iflag & (IXON | IXANY)))
-		return;
 	set_line_char(info);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
@@ -4432,10 +4466,10 @@
 static int __devinit cy_init_card(struct cyclades_card *cinfo)
 {
 	struct cyclades_port *info;
-	u32 mailbox;
+	u32 uninitialized_var(mailbox);
 	unsigned int nports;
 	unsigned short chip_number;
-	int index, port;
+	int uninitialized_var(index), port;
 
 	spin_lock_init(&cinfo->card_lock);
 
@@ -4738,17 +4772,295 @@
 }				/* cy_detect_isa */
 
 #ifdef CONFIG_PCI
-static void __devinit plx_init(void __iomem * addr, __u32 initctl)
+static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
+{
+	unsigned int a;
+
+	for (a = 0; a < size && *str; a++, str++)
+		if (*str & 0x80)
+			return -EINVAL;
+
+	for (; a < size; a++, str++)
+		if (*str)
+			return -EINVAL;
+
+	return 0;
+}
+
+static inline void __devinit cyz_fpga_copy(void __iomem *fpga, u8 *data,
+		unsigned int size)
+{
+	for (; size > 0; size--) {
+		cy_writel(fpga, *data++);
+		udelay(10);
+	}
+}
+
+static void __devinit plx_init(struct pci_dev *pdev, int irq,
+		struct RUNTIME_9060 __iomem *addr)
 {
 	/* Reset PLX */
-	cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
 	udelay(100L);
-	cy_writel(addr + initctl, readl(addr + initctl) & ~0x40000000);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
 
 	/* Reload Config. Registers from EEPROM */
-	cy_writel(addr + initctl, readl(addr + initctl) | 0x20000000);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
 	udelay(100L);
-	cy_writel(addr + initctl, readl(addr + initctl) & ~0x20000000);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
+
+	/* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
+	 * the IRQ is lost and, thus, we have to re-write it to the PCI config.
+	 * registers. This will remain here until we find a permanent fix.
+	 */
+	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+}
+
+static int __devinit __cyz_load_fw(const struct firmware *fw,
+		const char *name, const u32 mailbox, void __iomem *base,
+		void __iomem *fpga)
+{
+	void *ptr = fw->data;
+	struct zfile_header *h = ptr;
+	struct zfile_config *c, *cs;
+	struct zfile_block *b, *bs;
+	unsigned int a, tmp, len = fw->size;
+#define BAD_FW KERN_ERR "Bad firmware: "
+	if (len < sizeof(*h)) {
+		printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
+		return -EINVAL;
+	}
+
+	cs = ptr + h->config_offset;
+	bs = ptr + h->block_offset;
+
+	if ((void *)(cs + h->n_config) > ptr + len ||
+			(void *)(bs + h->n_blocks) > ptr + len) {
+		printk(BAD_FW "too short");
+		return  -EINVAL;
+	}
+
+	if (cyc_isfwstr(h->name, sizeof(h->name)) ||
+			cyc_isfwstr(h->date, sizeof(h->date))) {
+		printk(BAD_FW "bad formatted header string\n");
+		return -EINVAL;
+	}
+
+	if (strncmp(name, h->name, sizeof(h->name))) {
+		printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
+		return -EINVAL;
+	}
+
+	tmp = 0;
+	for (c = cs; c < cs + h->n_config; c++) {
+		for (a = 0; a < c->n_blocks; a++)
+			if (c->block_list[a] > h->n_blocks) {
+				printk(BAD_FW "bad block ref number in cfgs\n");
+				return -EINVAL;
+			}
+		if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
+			tmp++;
+	}
+	if (!tmp) {
+		printk(BAD_FW "nothing appropriate\n");
+		return -EINVAL;
+	}
+
+	for (b = bs; b < bs + h->n_blocks; b++)
+		if (b->file_offset + b->size > len) {
+			printk(BAD_FW "bad block data offset\n");
+			return -EINVAL;
+		}
+
+	/* everything is OK, let's seek'n'load it */
+	for (c = cs; c < cs + h->n_config; c++)
+		if (c->mailbox == mailbox && c->function == 0)
+			break;
+
+	for (a = 0; a < c->n_blocks; a++) {
+		b = &bs[c->block_list[a]];
+		if (b->type == ZBLOCK_FPGA) {
+			if (fpga != NULL)
+				cyz_fpga_copy(fpga, ptr + b->file_offset,
+						b->size);
+		} else {
+			if (base != NULL)
+				memcpy_toio(base + b->ram_offset,
+					       ptr + b->file_offset, b->size);
+		}
+	}
+#undef BAD_FW
+	return 0;
+}
+
+static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
+		struct RUNTIME_9060 __iomem *ctl_addr, int irq)
+{
+	const struct firmware *fw;
+	struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
+	struct CUSTOM_REG __iomem *cust = base_addr;
+	struct ZFW_CTRL __iomem *pt_zfwctrl;
+	void __iomem *tmp;
+	u32 mailbox, status;
+	unsigned int i;
+	int retval;
+
+	retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
+	if (retval) {
+		dev_err(&pdev->dev, "can't get firmware\n");
+		goto err;
+	}
+
+	/* Check whether the firmware is already loaded and running. If
+	   positive, skip this board */
+	if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
+		u32 cntval = readl(base_addr + 0x190);
+
+		udelay(100);
+		if (cntval != readl(base_addr + 0x190)) {
+			/* FW counter is working, FW is running */
+			dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
+					"Skipping board.\n");
+			retval = 0;
+			goto err_rel;
+		}
+	}
+
+	/* start boot */
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
+			~0x00030800UL);
+
+	mailbox = readl(&ctl_addr->mail_box_0);
+
+	if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) {
+		/* stops CPU and set window to beginning of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+		cy_writel(&cust->cpu_stop, 0);
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+		udelay(100);
+	}
+
+	plx_init(pdev, irq, ctl_addr);
+
+	if (mailbox != 0) {
+		/* load FPGA */
+		retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
+				base_addr);
+		if (retval)
+			goto err_rel;
+		if (!Z_FPGA_LOADED(ctl_addr)) {
+			dev_err(&pdev->dev, "fw upload successful, but fw is "
+					"not loaded\n");
+			goto err_rel;
+		}
+	}
+
+	/* stops CPU and set window to beginning of RAM */
+	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+	cy_writel(&cust->cpu_stop, 0);
+	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+	udelay(100);
+
+	/* clear memory */
+	for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+		cy_writeb(tmp, 255);
+	if (mailbox != 0) {
+		/* set window to last 512K of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
+		//sleep(1);
+		for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+			cy_writeb(tmp, 255);
+		/* set window to beginning of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+		//sleep(1);
+	}
+
+	retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
+	release_firmware(fw);
+	if (retval)
+		goto err;
+
+	/* finish boot and start boards */
+	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+	cy_writel(&cust->cpu_start, 0);
+	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+	i = 0;
+	while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
+		msleep(100);
+	if (status != ZFIRM_ID) {
+		if (status == ZFIRM_HLT) {
+			dev_err(&pdev->dev, "you need an external power supply "
+				"for this number of ports. Firmware halted and "
+				"board reset.\n");
+			retval = -EIO;
+			goto err;
+		}
+		dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
+				"some more time\n", status);
+		while ((status = readl(&fid->signature)) != ZFIRM_ID &&
+				i++ < 200)
+			msleep(100);
+		if (status != ZFIRM_ID) {
+			dev_err(&pdev->dev, "Board not started in 20 seconds! "
+					"Giving up. (fid->signature = 0x%x)\n",
+					status);
+			dev_info(&pdev->dev, "*** Warning ***: if you are "
+				"upgrading the FW, please power cycle the "
+				"system before loading the new FW to the "
+				"Cyclades-Z.\n");
+
+			if (Z_FPGA_LOADED(ctl_addr))
+				plx_init(pdev, irq, ctl_addr);
+
+			retval = -EIO;
+			goto err;
+		}
+		dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
+				i / 10);
+	}
+	pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
+
+	dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
+			base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
+			base_addr + readl(&fid->zfwctrl_addr));
+
+	dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
+		readl(&pt_zfwctrl->board_ctrl.fw_version),
+		readl(&pt_zfwctrl->board_ctrl.n_channel));
+
+	if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) {
+		dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
+			"check the connection between the Z host card and the "
+			"serial expanders.\n");
+
+		if (Z_FPGA_LOADED(ctl_addr))
+			plx_init(pdev, irq, ctl_addr);
+
+		dev_info(&pdev->dev, "Null number of ports detected. Board "
+				"reset.\n");
+		retval = 0;
+		goto err;
+	}
+
+	cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
+	cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
+
+	/*
+	   Early firmware failed to start looking for commands.
+	   This enables firmware interrupts for those commands.
+	 */
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
+			(1 << 17));
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
+			0x00030800UL);
+
+	plx_init(pdev, irq, ctl_addr);
+
+	return 0;
+err_rel:
+	release_firmware(fw);
+err:
+	return retval;
 }
 
 static int __devinit cy_pci_probe(struct pci_dev *pdev,
@@ -4830,16 +5142,9 @@
 		}
 
 		/* Disable interrupts on the PLX before resetting it */
-		cy_writew(addr0 + 0x68,
-			readw(addr0 + 0x68) & ~0x0900);
+		cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900);
 
-		plx_init(addr0, 0x6c);
-		/* For some yet unknown reason, once the PLX9060 reloads
-		   the EEPROM, the IRQ is lost and, thus, we have to
-		   re-write it to the PCI config. registers.
-		   This will remain here until we find a permanent
-		   fix. */
-		pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+		plx_init(pdev, irq, addr0);
 
 		mailbox = (u32)readl(&ctl_addr->mail_box_0);
 
@@ -4880,6 +5185,9 @@
 			if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
 				cy_writel(addr2 + ID_ADDRESS, 0L);
 
+			retval = cyz_load_fw(pdev, addr2, addr0, irq);
+			if (retval)
+				goto err_unmap;
 			/* This must be a Cyclades-8Zo/PCI.  The extendable
 			   version will have a different device_id and will
 			   be allocated its maximum number of ports. */
@@ -4956,15 +5264,7 @@
 		case PLX_9060:
 		case PLX_9080:
 		default:	/* Old boards, use PLX_9060 */
-
-			plx_init(addr0, 0x6c);
-		/* For some yet unknown reason, once the PLX9060 reloads
-		   the EEPROM, the IRQ is lost and, thus, we have to
-		   re-write it to the PCI config. registers.
-		   This will remain here until we find a permanent
-		   fix. */
-			pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
-
+			plx_init(pdev, irq, addr0);
 			cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900);
 			break;
 		}
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index ef833a1..0b7ffa5 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -6,7 +6,7 @@
 #
 config DRM
 	tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
-	depends on (AGP || AGP=n) && PCI
+	depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG
 	help
 	  Kernel-level support for the Direct Rendering Infrastructure (DRI)
 	  introduced in XFree86 4.0. If you say Y here, you need to select
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index 5b91bc0..3345641 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -73,9 +73,9 @@
 	free_pages((unsigned long)address, order);
 }
 
-int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
+int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
 {
-	drm_sg_mem_t *entry = dev->sg;
+	struct drm_sg_mem *entry = dev->sg;
 	unsigned long pages;
 	int i;
 	int order;
@@ -122,9 +122,9 @@
 }
 EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
 
-int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
+int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
 {
-	drm_sg_mem_t *entry = dev->sg;
+	struct drm_sg_mem *entry = dev->sg;
 	void *address = NULL;
 	unsigned long pages;
 	u32 *pci_gart, page_base, bus_address = 0;
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 0891984..2d6f2d0 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -109,31 +109,31 @@
  * \note KW: Actually it's illegal to change either for
  * backwards-compatibility reasons.
  */
-typedef struct drm_clip_rect {
+struct drm_clip_rect {
 	unsigned short x1;
 	unsigned short y1;
 	unsigned short x2;
 	unsigned short y2;
-} drm_clip_rect_t;
+};
 
 /**
  * Drawable information.
  */
-typedef struct drm_drawable_info {
+struct drm_drawable_info {
 	unsigned int num_rects;
-	drm_clip_rect_t *rects;
-} drm_drawable_info_t;
+	struct drm_clip_rect *rects;
+};
 
 /**
  * Texture region,
  */
-typedef struct drm_tex_region {
+struct drm_tex_region {
 	unsigned char next;
 	unsigned char prev;
 	unsigned char in_use;
 	unsigned char padding;
 	unsigned int age;
-} drm_tex_region_t;
+};
 
 /**
  * Hardware lock.
@@ -142,17 +142,17 @@
  * processor bus contention on a multiprocessor system, there should not be any
  * other data stored in the same cache line.
  */
-typedef struct drm_hw_lock {
+struct drm_hw_lock {
 	__volatile__ unsigned int lock;		/**< lock variable */
 	char padding[60];			/**< Pad to cache line */
-} drm_hw_lock_t;
+};
 
 /**
  * DRM_IOCTL_VERSION ioctl argument type.
  *
  * \sa drmGetVersion().
  */
-typedef struct drm_version {
+struct drm_version {
 	int version_major;	  /**< Major version */
 	int version_minor;	  /**< Minor version */
 	int version_patchlevel;	  /**< Patch level */
@@ -162,33 +162,33 @@
 	char __user *date;	  /**< User-space buffer to hold date */
 	size_t desc_len;	  /**< Length of desc buffer */
 	char __user *desc;	  /**< User-space buffer to hold desc */
-} drm_version_t;
+};
 
 /**
  * DRM_IOCTL_GET_UNIQUE ioctl argument type.
  *
  * \sa drmGetBusid() and drmSetBusId().
  */
-typedef struct drm_unique {
+struct drm_unique {
 	size_t unique_len;	  /**< Length of unique */
 	char __user *unique;	  /**< Unique name for driver instantiation */
-} drm_unique_t;
+};
 
-typedef struct drm_list {
+struct drm_list {
 	int count;		  /**< Length of user-space structures */
-	drm_version_t __user *version;
-} drm_list_t;
+	struct drm_version __user *version;
+};
 
-typedef struct drm_block {
+struct drm_block {
 	int unused;
-} drm_block_t;
+};
 
 /**
  * DRM_IOCTL_CONTROL ioctl argument type.
  *
  * \sa drmCtlInstHandler() and drmCtlUninstHandler().
  */
-typedef struct drm_control {
+struct drm_control {
 	enum {
 		DRM_ADD_COMMAND,
 		DRM_RM_COMMAND,
@@ -196,24 +196,24 @@
 		DRM_UNINST_HANDLER
 	} func;
 	int irq;
-} drm_control_t;
+};
 
 /**
  * Type of memory to map.
  */
-typedef enum drm_map_type {
+enum drm_map_type {
 	_DRM_FRAME_BUFFER = 0,	  /**< WC (no caching), no core dump */
 	_DRM_REGISTERS = 1,	  /**< no caching, no core dump */
 	_DRM_SHM = 2,		  /**< shared, cached */
 	_DRM_AGP = 3,		  /**< AGP/GART */
 	_DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
 	_DRM_CONSISTENT = 5,	  /**< Consistent memory for PCI DMA */
-} drm_map_type_t;
+};
 
 /**
  * Memory mapping flags.
  */
-typedef enum drm_map_flags {
+enum drm_map_flags {
 	_DRM_RESTRICTED = 0x01,	     /**< Cannot be mapped to user-virtual */
 	_DRM_READ_ONLY = 0x02,
 	_DRM_LOCKED = 0x04,	     /**< shared, cached, locked */
@@ -221,12 +221,12 @@
 	_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
 	_DRM_CONTAINS_LOCK = 0x20,   /**< SHM page that contains lock */
 	_DRM_REMOVABLE = 0x40	     /**< Removable mapping */
-} drm_map_flags_t;
+};
 
-typedef struct drm_ctx_priv_map {
+struct drm_ctx_priv_map {
 	unsigned int ctx_id;	 /**< Context requesting private mapping */
 	void *handle;		 /**< Handle of map */
-} drm_ctx_priv_map_t;
+};
 
 /**
  * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
@@ -234,30 +234,30 @@
  *
  * \sa drmAddMap().
  */
-typedef struct drm_map {
+struct drm_map {
 	unsigned long offset;	 /**< Requested physical address (0 for SAREA)*/
 	unsigned long size;	 /**< Requested physical size (bytes) */
-	drm_map_type_t type;	 /**< Type of memory to map */
-	drm_map_flags_t flags;	 /**< Flags */
+	enum drm_map_type type;	 /**< Type of memory to map */
+	enum drm_map_flags flags;	 /**< Flags */
 	void *handle;		 /**< User-space: "Handle" to pass to mmap() */
 				 /**< Kernel-space: kernel-virtual address */
 	int mtrr;		 /**< MTRR slot used */
 	/*   Private data */
-} drm_map_t;
+};
 
 /**
  * DRM_IOCTL_GET_CLIENT ioctl argument type.
  */
-typedef struct drm_client {
+struct drm_client {
 	int idx;		/**< Which client desired? */
 	int auth;		/**< Is client authenticated? */
 	unsigned long pid;	/**< Process ID */
 	unsigned long uid;	/**< User ID */
 	unsigned long magic;	/**< Magic */
 	unsigned long iocs;	/**< Ioctl count */
-} drm_client_t;
+};
 
-typedef enum {
+enum drm_stat_type {
 	_DRM_STAT_LOCK,
 	_DRM_STAT_OPENS,
 	_DRM_STAT_CLOSES,
@@ -275,23 +275,23 @@
 	_DRM_STAT_SPECIAL,	/**< Special DMA (e.g., priority or polled) */
 	_DRM_STAT_MISSED	/**< Missed DMA opportunity */
 	    /* Add to the *END* of the list */
-} drm_stat_type_t;
+};
 
 /**
  * DRM_IOCTL_GET_STATS ioctl argument type.
  */
-typedef struct drm_stats {
+struct drm_stats {
 	unsigned long count;
 	struct {
 		unsigned long value;
-		drm_stat_type_t type;
+		enum drm_stat_type type;
 	} data[15];
-} drm_stats_t;
+};
 
 /**
  * Hardware locking flags.
  */
-typedef enum drm_lock_flags {
+enum drm_lock_flags {
 	_DRM_LOCK_READY = 0x01,	     /**< Wait until hardware is ready for DMA */
 	_DRM_LOCK_QUIESCENT = 0x02,  /**< Wait until hardware quiescent */
 	_DRM_LOCK_FLUSH = 0x04,	     /**< Flush this context's DMA queue first */
@@ -301,17 +301,17 @@
 	   full-screen DGA-like mode. */
 	_DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
 	_DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
-} drm_lock_flags_t;
+};
 
 /**
  * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
  *
  * \sa drmGetLock() and drmUnlock().
  */
-typedef struct drm_lock {
+struct drm_lock {
 	int context;
-	drm_lock_flags_t flags;
-} drm_lock_t;
+	enum drm_lock_flags flags;
+};
 
 /**
  * DMA flags
@@ -321,7 +321,7 @@
  *
  * \sa drm_dma.
  */
-typedef enum drm_dma_flags {
+enum drm_dma_flags {
 	/* Flags for DMA buffer dispatch */
 	_DRM_DMA_BLOCK = 0x01,	      /**<
 				       * Block until buffer dispatched.
@@ -340,14 +340,14 @@
 	_DRM_DMA_WAIT = 0x10,	      /**< Wait for free buffers */
 	_DRM_DMA_SMALLER_OK = 0x20,   /**< Smaller-than-requested buffers OK */
 	_DRM_DMA_LARGER_OK = 0x40     /**< Larger-than-requested buffers OK */
-} drm_dma_flags_t;
+};
 
 /**
  * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
  *
  * \sa drmAddBufs().
  */
-typedef struct drm_buf_desc {
+struct drm_buf_desc {
 	int count;		 /**< Number of buffers of this size */
 	int size;		 /**< Size in bytes */
 	int low_mark;		 /**< Low water mark */
@@ -363,44 +363,44 @@
 				  * Start address of where the AGP buffers are
 				  * in the AGP aperture
 				  */
-} drm_buf_desc_t;
+};
 
 /**
  * DRM_IOCTL_INFO_BUFS ioctl argument type.
  */
-typedef struct drm_buf_info {
+struct drm_buf_info {
 	int count;		/**< Entries in list */
-	drm_buf_desc_t __user *list;
-} drm_buf_info_t;
+	struct drm_buf_desc __user *list;
+};
 
 /**
  * DRM_IOCTL_FREE_BUFS ioctl argument type.
  */
-typedef struct drm_buf_free {
+struct drm_buf_free {
 	int count;
 	int __user *list;
-} drm_buf_free_t;
+};
 
 /**
  * Buffer information
  *
  * \sa drm_buf_map.
  */
-typedef struct drm_buf_pub {
+struct drm_buf_pub {
 	int idx;		       /**< Index into the master buffer list */
 	int total;		       /**< Buffer size */
 	int used;		       /**< Amount of buffer in use (for DMA) */
 	void __user *address;	       /**< Address of buffer */
-} drm_buf_pub_t;
+};
 
 /**
  * DRM_IOCTL_MAP_BUFS ioctl argument type.
  */
-typedef struct drm_buf_map {
+struct drm_buf_map {
 	int count;		/**< Length of the buffer list */
 	void __user *virtual;		/**< Mmap'd area in user-virtual */
-	drm_buf_pub_t __user *list;	/**< Buffer information */
-} drm_buf_map_t;
+	struct drm_buf_pub __user *list;	/**< Buffer information */
+};
 
 /**
  * DRM_IOCTL_DMA ioctl argument type.
@@ -409,48 +409,48 @@
  *
  * \sa drmDMA().
  */
-typedef struct drm_dma {
+struct drm_dma {
 	int context;			  /**< Context handle */
 	int send_count;			  /**< Number of buffers to send */
 	int __user *send_indices;	  /**< List of handles to buffers */
 	int __user *send_sizes;		  /**< Lengths of data to send */
-	drm_dma_flags_t flags;		  /**< Flags */
+	enum drm_dma_flags flags;	  /**< Flags */
 	int request_count;		  /**< Number of buffers requested */
 	int request_size;		  /**< Desired size for buffers */
 	int __user *request_indices;	  /**< Buffer information */
 	int __user *request_sizes;
 	int granted_count;		  /**< Number of buffers granted */
-} drm_dma_t;
+};
 
-typedef enum {
+enum drm_ctx_flags {
 	_DRM_CONTEXT_PRESERVED = 0x01,
 	_DRM_CONTEXT_2DONLY = 0x02
-} drm_ctx_flags_t;
+};
 
 /**
  * DRM_IOCTL_ADD_CTX ioctl argument type.
  *
  * \sa drmCreateContext() and drmDestroyContext().
  */
-typedef struct drm_ctx {
+struct drm_ctx {
 	drm_context_t handle;
-	drm_ctx_flags_t flags;
-} drm_ctx_t;
+	enum drm_ctx_flags flags;
+};
 
 /**
  * DRM_IOCTL_RES_CTX ioctl argument type.
  */
-typedef struct drm_ctx_res {
+struct drm_ctx_res {
 	int count;
-	drm_ctx_t __user *contexts;
-} drm_ctx_res_t;
+	struct drm_ctx __user *contexts;
+};
 
 /**
  * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
  */
-typedef struct drm_draw {
+struct drm_draw {
 	drm_drawable_t handle;
-} drm_draw_t;
+};
 
 /**
  * DRM_IOCTL_UPDATE_DRAW ioctl argument type.
@@ -459,52 +459,52 @@
 	DRM_DRAWABLE_CLIPRECTS,
 } drm_drawable_info_type_t;
 
-typedef struct drm_update_draw {
+struct drm_update_draw {
 	drm_drawable_t handle;
 	unsigned int type;
 	unsigned int num;
 	unsigned long long data;
-} drm_update_draw_t;
+};
 
 /**
  * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
  */
-typedef struct drm_auth {
+struct drm_auth {
 	drm_magic_t magic;
-} drm_auth_t;
+};
 
 /**
  * DRM_IOCTL_IRQ_BUSID ioctl argument type.
  *
  * \sa drmGetInterruptFromBusID().
  */
-typedef struct drm_irq_busid {
+struct drm_irq_busid {
 	int irq;	/**< IRQ number */
 	int busnum;	/**< bus number */
 	int devnum;	/**< device number */
 	int funcnum;	/**< function number */
-} drm_irq_busid_t;
+};
 
-typedef enum {
+enum drm_vblank_seq_type {
 	_DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
 	_DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
 	_DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
 	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
 	_DRM_VBLANK_SIGNAL = 0x40000000	/**< Send signal instead of blocking */
-} drm_vblank_seq_type_t;
+};
 
 #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
 #define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
 				_DRM_VBLANK_NEXTONMISS)
 
 struct drm_wait_vblank_request {
-	drm_vblank_seq_type_t type;
+	enum drm_vblank_seq_type type;
 	unsigned int sequence;
 	unsigned long signal;
 };
 
 struct drm_wait_vblank_reply {
-	drm_vblank_seq_type_t type;
+	enum drm_vblank_seq_type type;
 	unsigned int sequence;
 	long tval_sec;
 	long tval_usec;
@@ -515,41 +515,41 @@
  *
  * \sa drmWaitVBlank().
  */
-typedef union drm_wait_vblank {
+union drm_wait_vblank {
 	struct drm_wait_vblank_request request;
 	struct drm_wait_vblank_reply reply;
-} drm_wait_vblank_t;
+};
 
 /**
  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
  *
  * \sa drmAgpEnable().
  */
-typedef struct drm_agp_mode {
+struct drm_agp_mode {
 	unsigned long mode;	/**< AGP mode */
-} drm_agp_mode_t;
+};
 
 /**
  * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
  *
  * \sa drmAgpAlloc() and drmAgpFree().
  */
-typedef struct drm_agp_buffer {
+struct drm_agp_buffer {
 	unsigned long size;	/**< In bytes -- will round to page boundary */
 	unsigned long handle;	/**< Used for binding / unbinding */
 	unsigned long type;	/**< Type of memory to allocate */
 	unsigned long physical;	/**< Physical used by i810 */
-} drm_agp_buffer_t;
+};
 
 /**
  * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
  *
  * \sa drmAgpBind() and drmAgpUnbind().
  */
-typedef struct drm_agp_binding {
+struct drm_agp_binding {
 	unsigned long handle;	/**< From drm_agp_buffer */
 	unsigned long offset;	/**< In bytes -- will round to page boundary */
-} drm_agp_binding_t;
+};
 
 /**
  * DRM_IOCTL_AGP_INFO ioctl argument type.
@@ -558,7 +558,7 @@
  * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
  * drmAgpVendorId() and drmAgpDeviceId().
  */
-typedef struct drm_agp_info {
+struct drm_agp_info {
 	int agp_version_major;
 	int agp_version_minor;
 	unsigned long mode;
@@ -570,25 +570,25 @@
 	/* PCI information */
 	unsigned short id_vendor;
 	unsigned short id_device;
-} drm_agp_info_t;
+};
 
 /**
  * DRM_IOCTL_SG_ALLOC ioctl argument type.
  */
-typedef struct drm_scatter_gather {
+struct drm_scatter_gather {
 	unsigned long size;	/**< In bytes -- will round to page boundary */
 	unsigned long handle;	/**< Used for mapping / unmapping */
-} drm_scatter_gather_t;
+};
 
 /**
  * DRM_IOCTL_SET_VERSION ioctl argument type.
  */
-typedef struct drm_set_version {
+struct drm_set_version {
 	int drm_di_major;
 	int drm_di_minor;
 	int drm_dd_major;
 	int drm_dd_minor;
-} drm_set_version_t;
+};
 
 #define DRM_IOCTL_BASE			'd'
 #define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
@@ -596,61 +596,61 @@
 #define DRM_IOW(nr,type)		_IOW(DRM_IOCTL_BASE,nr,type)
 #define DRM_IOWR(nr,type)		_IOWR(DRM_IOCTL_BASE,nr,type)
 
-#define DRM_IOCTL_VERSION		DRM_IOWR(0x00, drm_version_t)
-#define DRM_IOCTL_GET_UNIQUE		DRM_IOWR(0x01, drm_unique_t)
-#define DRM_IOCTL_GET_MAGIC		DRM_IOR( 0x02, drm_auth_t)
-#define DRM_IOCTL_IRQ_BUSID		DRM_IOWR(0x03, drm_irq_busid_t)
-#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, drm_map_t)
-#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, drm_client_t)
-#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, drm_stats_t)
-#define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, drm_set_version_t)
+#define DRM_IOCTL_VERSION		DRM_IOWR(0x00, struct drm_version)
+#define DRM_IOCTL_GET_UNIQUE		DRM_IOWR(0x01, struct drm_unique)
+#define DRM_IOCTL_GET_MAGIC		DRM_IOR( 0x02, struct drm_auth)
+#define DRM_IOCTL_IRQ_BUSID		DRM_IOWR(0x03, struct drm_irq_busid)
+#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, struct drm_map)
+#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
+#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
+#define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, struct drm_set_version)
 
-#define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, drm_unique_t)
-#define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, drm_auth_t)
-#define DRM_IOCTL_BLOCK			DRM_IOWR(0x12, drm_block_t)
-#define DRM_IOCTL_UNBLOCK		DRM_IOWR(0x13, drm_block_t)
-#define DRM_IOCTL_CONTROL		DRM_IOW( 0x14, drm_control_t)
-#define DRM_IOCTL_ADD_MAP		DRM_IOWR(0x15, drm_map_t)
-#define DRM_IOCTL_ADD_BUFS		DRM_IOWR(0x16, drm_buf_desc_t)
-#define DRM_IOCTL_MARK_BUFS		DRM_IOW( 0x17, drm_buf_desc_t)
-#define DRM_IOCTL_INFO_BUFS		DRM_IOWR(0x18, drm_buf_info_t)
-#define DRM_IOCTL_MAP_BUFS		DRM_IOWR(0x19, drm_buf_map_t)
-#define DRM_IOCTL_FREE_BUFS		DRM_IOW( 0x1a, drm_buf_free_t)
+#define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, struct drm_unique)
+#define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, struct drm_auth)
+#define DRM_IOCTL_BLOCK			DRM_IOWR(0x12, struct drm_block)
+#define DRM_IOCTL_UNBLOCK		DRM_IOWR(0x13, struct drm_block)
+#define DRM_IOCTL_CONTROL		DRM_IOW( 0x14, struct drm_control)
+#define DRM_IOCTL_ADD_MAP		DRM_IOWR(0x15, struct drm_map)
+#define DRM_IOCTL_ADD_BUFS		DRM_IOWR(0x16, struct drm_buf_desc)
+#define DRM_IOCTL_MARK_BUFS		DRM_IOW( 0x17, struct drm_buf_desc)
+#define DRM_IOCTL_INFO_BUFS		DRM_IOWR(0x18, struct drm_buf_info)
+#define DRM_IOCTL_MAP_BUFS		DRM_IOWR(0x19, struct drm_buf_map)
+#define DRM_IOCTL_FREE_BUFS		DRM_IOW( 0x1a, struct drm_buf_free)
 
-#define DRM_IOCTL_RM_MAP		DRM_IOW( 0x1b, drm_map_t)
+#define DRM_IOCTL_RM_MAP		DRM_IOW( 0x1b, struct drm_map)
 
-#define DRM_IOCTL_SET_SAREA_CTX		DRM_IOW( 0x1c, drm_ctx_priv_map_t)
-#define DRM_IOCTL_GET_SAREA_CTX 	DRM_IOWR(0x1d, drm_ctx_priv_map_t)
+#define DRM_IOCTL_SET_SAREA_CTX		DRM_IOW( 0x1c, struct drm_ctx_priv_map)
+#define DRM_IOCTL_GET_SAREA_CTX 	DRM_IOWR(0x1d, struct drm_ctx_priv_map)
 
-#define DRM_IOCTL_ADD_CTX		DRM_IOWR(0x20, drm_ctx_t)
-#define DRM_IOCTL_RM_CTX		DRM_IOWR(0x21, drm_ctx_t)
-#define DRM_IOCTL_MOD_CTX		DRM_IOW( 0x22, drm_ctx_t)
-#define DRM_IOCTL_GET_CTX		DRM_IOWR(0x23, drm_ctx_t)
-#define DRM_IOCTL_SWITCH_CTX		DRM_IOW( 0x24, drm_ctx_t)
-#define DRM_IOCTL_NEW_CTX		DRM_IOW( 0x25, drm_ctx_t)
-#define DRM_IOCTL_RES_CTX		DRM_IOWR(0x26, drm_ctx_res_t)
-#define DRM_IOCTL_ADD_DRAW		DRM_IOWR(0x27, drm_draw_t)
-#define DRM_IOCTL_RM_DRAW		DRM_IOWR(0x28, drm_draw_t)
-#define DRM_IOCTL_DMA			DRM_IOWR(0x29, drm_dma_t)
-#define DRM_IOCTL_LOCK			DRM_IOW( 0x2a, drm_lock_t)
-#define DRM_IOCTL_UNLOCK		DRM_IOW( 0x2b, drm_lock_t)
-#define DRM_IOCTL_FINISH		DRM_IOW( 0x2c, drm_lock_t)
+#define DRM_IOCTL_ADD_CTX		DRM_IOWR(0x20, struct drm_ctx)
+#define DRM_IOCTL_RM_CTX		DRM_IOWR(0x21, struct drm_ctx)
+#define DRM_IOCTL_MOD_CTX		DRM_IOW( 0x22, struct drm_ctx)
+#define DRM_IOCTL_GET_CTX		DRM_IOWR(0x23, struct drm_ctx)
+#define DRM_IOCTL_SWITCH_CTX		DRM_IOW( 0x24, struct drm_ctx)
+#define DRM_IOCTL_NEW_CTX		DRM_IOW( 0x25, struct drm_ctx)
+#define DRM_IOCTL_RES_CTX		DRM_IOWR(0x26, struct drm_ctx_res)
+#define DRM_IOCTL_ADD_DRAW		DRM_IOWR(0x27, struct drm_draw)
+#define DRM_IOCTL_RM_DRAW		DRM_IOWR(0x28, struct drm_draw)
+#define DRM_IOCTL_DMA			DRM_IOWR(0x29, struct drm_dma)
+#define DRM_IOCTL_LOCK			DRM_IOW( 0x2a, struct drm_lock)
+#define DRM_IOCTL_UNLOCK		DRM_IOW( 0x2b, struct drm_lock)
+#define DRM_IOCTL_FINISH		DRM_IOW( 0x2c, struct drm_lock)
 
 #define DRM_IOCTL_AGP_ACQUIRE		DRM_IO(  0x30)
 #define DRM_IOCTL_AGP_RELEASE		DRM_IO(  0x31)
-#define DRM_IOCTL_AGP_ENABLE		DRM_IOW( 0x32, drm_agp_mode_t)
-#define DRM_IOCTL_AGP_INFO		DRM_IOR( 0x33, drm_agp_info_t)
-#define DRM_IOCTL_AGP_ALLOC		DRM_IOWR(0x34, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_FREE		DRM_IOW( 0x35, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_BIND		DRM_IOW( 0x36, drm_agp_binding_t)
-#define DRM_IOCTL_AGP_UNBIND		DRM_IOW( 0x37, drm_agp_binding_t)
+#define DRM_IOCTL_AGP_ENABLE		DRM_IOW( 0x32, struct drm_agp_mode)
+#define DRM_IOCTL_AGP_INFO		DRM_IOR( 0x33, struct drm_agp_info)
+#define DRM_IOCTL_AGP_ALLOC		DRM_IOWR(0x34, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_FREE		DRM_IOW( 0x35, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_BIND		DRM_IOW( 0x36, struct drm_agp_binding)
+#define DRM_IOCTL_AGP_UNBIND		DRM_IOW( 0x37, struct drm_agp_binding)
 
-#define DRM_IOCTL_SG_ALLOC		DRM_IOW( 0x38, drm_scatter_gather_t)
-#define DRM_IOCTL_SG_FREE		DRM_IOW( 0x39, drm_scatter_gather_t)
+#define DRM_IOCTL_SG_ALLOC		DRM_IOW( 0x38, struct drm_scatter_gather)
+#define DRM_IOCTL_SG_FREE		DRM_IOW( 0x39, struct drm_scatter_gather)
 
-#define DRM_IOCTL_WAIT_VBLANK		DRM_IOWR(0x3a, drm_wait_vblank_t)
+#define DRM_IOCTL_WAIT_VBLANK		DRM_IOWR(0x3a, union drm_wait_vblank)
 
-#define DRM_IOCTL_UPDATE_DRAW		DRM_IOW(0x3f, drm_update_draw_t)
+#define DRM_IOCTL_UPDATE_DRAW		DRM_IOW(0x3f, struct drm_update_draw)
 
 /**
  * Device specific ioctls should only be in their respective headers
@@ -663,4 +663,49 @@
 #define DRM_COMMAND_BASE                0x40
 #define DRM_COMMAND_END			0xA0
 
+/* typedef area */
+#ifndef __KERNEL__
+typedef struct drm_clip_rect drm_clip_rect_t;
+typedef struct drm_drawable_info drm_drawable_info_t;
+typedef struct drm_tex_region drm_tex_region_t;
+typedef struct drm_hw_lock drm_hw_lock_t;
+typedef struct drm_version drm_version_t;
+typedef struct drm_unique drm_unique_t;
+typedef struct drm_list drm_list_t;
+typedef struct drm_block drm_block_t;
+typedef struct drm_control drm_control_t;
+typedef enum drm_map_type drm_map_type_t;
+typedef enum drm_map_flags drm_map_flags_t;
+typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
+typedef struct drm_map drm_map_t;
+typedef struct drm_client drm_client_t;
+typedef enum drm_stat_type drm_stat_type_t;
+typedef struct drm_stats drm_stats_t;
+typedef enum drm_lock_flags drm_lock_flags_t;
+typedef struct drm_lock drm_lock_t;
+typedef enum drm_dma_flags drm_dma_flags_t;
+typedef struct drm_buf_desc drm_buf_desc_t;
+typedef struct drm_buf_info drm_buf_info_t;
+typedef struct drm_buf_free drm_buf_free_t;
+typedef struct drm_buf_pub drm_buf_pub_t;
+typedef struct drm_buf_map drm_buf_map_t;
+typedef struct drm_dma drm_dma_t;
+typedef union drm_wait_vblank drm_wait_vblank_t;
+typedef struct drm_agp_mode drm_agp_mode_t;
+typedef enum drm_ctx_flags drm_ctx_flags_t;
+typedef struct drm_ctx drm_ctx_t;
+typedef struct drm_ctx_res drm_ctx_res_t;
+typedef struct drm_draw drm_draw_t;
+typedef struct drm_update_draw drm_update_draw_t;
+typedef struct drm_auth drm_auth_t;
+typedef struct drm_irq_busid drm_irq_busid_t;
+typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
+
+typedef struct drm_agp_buffer drm_agp_buffer_t;
+typedef struct drm_agp_binding drm_agp_binding_t;
+typedef struct drm_agp_info drm_agp_info_t;
+typedef struct drm_scatter_gather drm_scatter_gather_t;
+typedef struct drm_set_version drm_set_version_t;
+#endif
+
 #endif
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index d494315..0df87fc 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -75,6 +75,8 @@
 #include <asm/pgalloc.h>
 #include "drm.h"
 
+#include <linux/idr.h>
+
 #define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
 #define __OS_HAS_MTRR (defined(CONFIG_MTRR))
 
@@ -274,32 +276,23 @@
 	int flags;
 } drm_ioctl_desc_t;
 
-typedef struct drm_devstate {
-	pid_t owner;			/**< X server pid holding x_lock */
-} drm_devstate_t;
-
-typedef struct drm_magic_entry {
-	drm_hash_item_t hash_item;
+struct drm_magic_entry {
 	struct list_head head;
+	struct drm_hash_item hash_item;
 	struct drm_file *priv;
 	struct drm_magic_entry *next;
-} drm_magic_entry_t;
+};
 
-typedef struct drm_magic_head {
-	struct drm_magic_entry *head;
-	struct drm_magic_entry *tail;
-} drm_magic_head_t;
-
-typedef struct drm_vma_entry {
+struct drm_vma_entry {
+	struct list_head head;
 	struct vm_area_struct *vma;
-	struct drm_vma_entry *next;
 	pid_t pid;
-} drm_vma_entry_t;
+};
 
 /**
  * DMA buffer.
  */
-typedef struct drm_buf {
+struct drm_buf {
 	int idx;		       /**< Index into master buflist */
 	int total;		       /**< Buffer size */
 	int order;		       /**< log-base-2(total) */
@@ -325,30 +318,30 @@
 
 	int dev_priv_size;		 /**< Size of buffer private storage */
 	void *dev_private;		 /**< Per-buffer private storage */
-} drm_buf_t;
+};
 
 /** bufs is one longer than it has to be */
-typedef struct drm_waitlist {
+struct drm_waitlist {
 	int count;			/**< Number of possible buffers */
-	drm_buf_t **bufs;		/**< List of pointers to buffers */
-	drm_buf_t **rp;			/**< Read pointer */
-	drm_buf_t **wp;			/**< Write pointer */
-	drm_buf_t **end;		/**< End pointer */
+	struct drm_buf **bufs;		/**< List of pointers to buffers */
+	struct drm_buf **rp;			/**< Read pointer */
+	struct drm_buf **wp;			/**< Write pointer */
+	struct drm_buf **end;		/**< End pointer */
 	spinlock_t read_lock;
 	spinlock_t write_lock;
-} drm_waitlist_t;
+};
 
-typedef struct drm_freelist {
+struct drm_freelist {
 	int initialized;	       /**< Freelist in use */
 	atomic_t count;		       /**< Number of free buffers */
-	drm_buf_t *next;	       /**< End pointer */
+	struct drm_buf *next;	       /**< End pointer */
 
 	wait_queue_head_t waiting;     /**< Processes waiting on free bufs */
 	int low_mark;		       /**< Low water mark */
 	int high_mark;		       /**< High water mark */
 	atomic_t wfh;		       /**< If waiting for high mark */
 	spinlock_t lock;
-} drm_freelist_t;
+};
 
 typedef struct drm_dma_handle {
 	dma_addr_t busaddr;
@@ -359,19 +352,19 @@
 /**
  * Buffer entry.  There is one of this for each buffer size order.
  */
-typedef struct drm_buf_entry {
+struct drm_buf_entry {
 	int buf_size;			/**< size */
 	int buf_count;			/**< number of buffers */
-	drm_buf_t *buflist;		/**< buffer list */
+	struct drm_buf *buflist;		/**< buffer list */
 	int seg_count;
 	int page_order;
-	drm_dma_handle_t **seglist;
+	struct drm_dma_handle **seglist;
 
-	drm_freelist_t freelist;
-} drm_buf_entry_t;
+	struct drm_freelist freelist;
+};
 
 /** File private data */
-typedef struct drm_file {
+struct drm_file {
 	int authenticated;
 	int master;
 	int minor;
@@ -379,16 +372,15 @@
 	uid_t uid;
 	drm_magic_t magic;
 	unsigned long ioctl_count;
-	struct drm_file *next;
-	struct drm_file *prev;
+	struct list_head lhead;
 	struct drm_head *head;
 	int remove_auth_on_close;
 	unsigned long lock_count;
 	void *driver_priv;
-} drm_file_t;
+};
 
 /** Wait queue */
-typedef struct drm_queue {
+struct drm_queue {
 	atomic_t use_count;		/**< Outstanding uses (+1) */
 	atomic_t finalization;		/**< Finalization in progress */
 	atomic_t block_count;		/**< Count of processes waiting */
@@ -401,16 +393,16 @@
 	atomic_t total_flushed;		/**< Total flushes statistic */
 	atomic_t total_locks;		/**< Total locks statistics */
 #endif
-	drm_ctx_flags_t flags;		/**< Context preserving and 2D-only */
-	drm_waitlist_t waitlist;	/**< Pending buffers */
+	enum drm_ctx_flags flags;	/**< Context preserving and 2D-only */
+	struct drm_waitlist waitlist;	/**< Pending buffers */
 	wait_queue_head_t flush_queue;	/**< Processes waiting until flush */
-} drm_queue_t;
+};
 
 /**
  * Lock data.
  */
-typedef struct drm_lock_data {
-	drm_hw_lock_t *hw_lock;		/**< Hardware lock */
+struct drm_lock_data {
+	struct drm_hw_lock *hw_lock;	/**< Hardware lock */
 	struct file *filp;		/**< File descr of lock holder (0=kernel) */
 	wait_queue_head_t lock_queue;	/**< Queue of blocked processes */
 	unsigned long lock_time;	/**< Time of last lock in jiffies */
@@ -418,16 +410,16 @@
 	uint32_t kernel_waiters;
 	uint32_t user_waiters;
 	int idle_has_lock;
-} drm_lock_data_t;
+};
 
 /**
  * DMA data.
  */
-typedef struct drm_device_dma {
+struct drm_device_dma {
 
-	drm_buf_entry_t bufs[DRM_MAX_ORDER + 1];	/**< buffers, grouped by their size order */
+	struct drm_buf_entry bufs[DRM_MAX_ORDER + 1];	/**< buffers, grouped by their size order */
 	int buf_count;			/**< total number of buffers */
-	drm_buf_t **buflist;		/**< Vector of pointers into drm_device_dma::bufs */
+	struct drm_buf **buflist;		/**< Vector of pointers into drm_device_dma::bufs */
 	int seg_count;
 	int page_count;			/**< number of pages */
 	unsigned long *pagelist;	/**< page list */
@@ -439,28 +431,27 @@
 		_DRM_DMA_USE_PCI_RO = 0x08
 	} flags;
 
-} drm_device_dma_t;
+};
 
 /**
  * AGP memory entry.  Stored as a doubly linked list.
  */
-typedef struct drm_agp_mem {
+struct drm_agp_mem {
 	unsigned long handle;		/**< handle */
 	DRM_AGP_MEM *memory;
 	unsigned long bound;		/**< address */
 	int pages;
-	struct drm_agp_mem *prev;	/**< previous entry */
-	struct drm_agp_mem *next;	/**< next entry */
-} drm_agp_mem_t;
+	struct list_head head;
+};
 
 /**
  * AGP data.
  *
  * \sa drm_agp_init() and drm_device::agp.
  */
-typedef struct drm_agp_head {
+struct drm_agp_head {
 	DRM_AGP_KERN agp_info;		/**< AGP device information */
-	drm_agp_mem_t *memory;		/**< memory entries */
+	struct list_head memory;
 	unsigned long mode;		/**< AGP mode */
 	struct agp_bridge_data *bridge;
 	int enabled;			/**< whether the AGP bus as been enabled */
@@ -469,51 +460,51 @@
 	int agp_mtrr;
 	int cant_use_aperture;
 	unsigned long page_mask;
-} drm_agp_head_t;
+};
 
 /**
  * Scatter-gather memory.
  */
-typedef struct drm_sg_mem {
+struct drm_sg_mem {
 	unsigned long handle;
 	void *virtual;
 	int pages;
 	struct page **pagelist;
 	dma_addr_t *busaddr;
-} drm_sg_mem_t;
+};
 
-typedef struct drm_sigdata {
+struct drm_sigdata {
 	int context;
-	drm_hw_lock_t *lock;
-} drm_sigdata_t;
+	struct drm_hw_lock *lock;
+};
 
 /**
  * Mappings list
  */
-typedef struct drm_map_list {
+struct drm_map_list {
 	struct list_head head;		/**< list head */
-	drm_hash_item_t hash;
-	drm_map_t *map;			/**< mapping */
+	struct drm_hash_item hash;
+	struct drm_map *map;			/**< mapping */
 	unsigned int user_token;
-} drm_map_list_t;
+};
 
-typedef drm_map_t drm_local_map_t;
+typedef struct drm_map drm_local_map_t;
 
 /**
  * Context handle list
  */
-typedef struct drm_ctx_list {
+struct drm_ctx_list {
 	struct list_head head;		/**< list head */
 	drm_context_t handle;		/**< context handle */
-	drm_file_t *tag;		/**< associated fd private data */
-} drm_ctx_list_t;
+	struct drm_file *tag;		/**< associated fd private data */
+};
 
-typedef struct drm_vbl_sig {
+struct drm_vbl_sig {
 	struct list_head head;
 	unsigned int sequence;
 	struct siginfo info;
 	struct task_struct *task;
-} drm_vbl_sig_t;
+};
 
 /* location of GART table */
 #define DRM_ATI_GART_MAIN 1
@@ -523,19 +514,19 @@
 #define DRM_ATI_GART_PCIE 2
 #define DRM_ATI_GART_IGP 3
 
-typedef struct ati_pcigart_info {
+struct drm_ati_pcigart_info {
 	int gart_table_location;
 	int gart_reg_if;
 	void *addr;
 	dma_addr_t bus_addr;
 	drm_local_map_t mapping;
 	int table_size;
-} drm_ati_pcigart_info;
+};
 
 /*
  * Generic memory manager structs
  */
-typedef struct drm_mm_node {
+struct drm_mm_node {
 	struct list_head fl_entry;
 	struct list_head ml_entry;
 	int free;
@@ -543,12 +534,12 @@
 	unsigned long size;
 	struct drm_mm *mm;
 	void *private;
-} drm_mm_node_t;
+};
 
-typedef struct drm_mm {
+struct drm_mm {
 	struct list_head fl_entry;
 	struct list_head ml_entry;
-} drm_mm_t;
+};
 
 /**
  * DRM driver structure. This structure represent the common code for
@@ -560,21 +551,21 @@
 struct drm_driver {
 	int (*load) (struct drm_device *, unsigned long flags);
 	int (*firstopen) (struct drm_device *);
-	int (*open) (struct drm_device *, drm_file_t *);
+	int (*open) (struct drm_device *, struct drm_file *);
 	void (*preclose) (struct drm_device *, struct file * filp);
-	void (*postclose) (struct drm_device *, drm_file_t *);
+	void (*postclose) (struct drm_device *, struct drm_file *);
 	void (*lastclose) (struct drm_device *);
 	int (*unload) (struct drm_device *);
 	int (*dma_ioctl) (DRM_IOCTL_ARGS);
 	void (*dma_ready) (struct drm_device *);
 	int (*dma_quiescent) (struct drm_device *);
-	int (*context_ctor) (struct drm_device * dev, int context);
-	int (*context_dtor) (struct drm_device * dev, int context);
-	int (*kernel_context_switch) (struct drm_device * dev, int old,
+	int (*context_ctor) (struct drm_device *dev, int context);
+	int (*context_dtor) (struct drm_device *dev, int context);
+	int (*kernel_context_switch) (struct drm_device *dev, int old,
 				      int new);
-	void (*kernel_context_switch_unlock) (struct drm_device * dev);
-	int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
-	int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence);
+	void (*kernel_context_switch_unlock) (struct drm_device *dev);
+	int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
+	int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
 	int (*dri_library_name) (struct drm_device *dev, char *buf);
 
 	/**
@@ -588,22 +579,23 @@
 	 * card is absolutely \b not AGP (return of 0), absolutely \b is AGP
 	 * (return of 1), or may or may not be AGP (return of 2).
 	 */
-	int (*device_is_agp) (struct drm_device * dev);
+	int (*device_is_agp) (struct drm_device *dev);
 
 	/* these have to be filled in */
 
 	irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
-	void (*irq_preinstall) (struct drm_device * dev);
-	void (*irq_postinstall) (struct drm_device * dev);
-	void (*irq_uninstall) (struct drm_device * dev);
-	void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);
+	void (*irq_preinstall) (struct drm_device *dev);
+	void (*irq_postinstall) (struct drm_device *dev);
+	void (*irq_uninstall) (struct drm_device *dev);
+	void (*reclaim_buffers) (struct drm_device *dev, struct file * filp);
 	void (*reclaim_buffers_locked) (struct drm_device *dev,
 					struct file *filp);
 	void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
 					struct file * filp);
-	unsigned long (*get_map_ofs) (drm_map_t * map);
-	unsigned long (*get_reg_ofs) (struct drm_device * dev);
-	void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
+	unsigned long (*get_map_ofs) (struct drm_map * map);
+	unsigned long (*get_reg_ofs) (struct drm_device *dev);
+	void (*set_version) (struct drm_device *dev,
+			     struct drm_set_version *sv);
 
 	int major;
 	int minor;
@@ -625,19 +617,19 @@
  * that may contain multiple heads. Embed one per head of these in the
  * private drm_device structure.
  */
-typedef struct drm_head {
+struct drm_head {
 	int minor;			/**< Minor device number */
 	struct drm_device *dev;
 	struct proc_dir_entry *dev_root;  /**< proc directory entry */
 	dev_t device;			/**< Device number for mknod */
 	struct class_device *dev_class;
-} drm_head_t;
+};
 
 /**
  * DRM device structure. This structure represent a complete card that
  * may contain multiple heads.
  */
-typedef struct drm_device {
+struct drm_device {
 	char *unique;			/**< Unique identifier: e.g., busid */
 	int unique_len;			/**< Length of unique field */
 	char *devname;			/**< For /proc/interrupts */
@@ -663,35 +655,33 @@
 	/** \name Performance counters */
 	/*@{ */
 	unsigned long counters;
-	drm_stat_type_t types[15];
+	enum drm_stat_type types[15];
 	atomic_t counts[15];
 	/*@} */
 
 	/** \name Authentication */
 	/*@{ */
-	drm_file_t *file_first;		/**< file list head */
-	drm_file_t *file_last;		/**< file list tail */
-	drm_open_hash_t magiclist;	/**< magic hash table */
+	struct list_head filelist;
+	struct drm_open_hash magiclist;	/**< magic hash table */
 	struct list_head magicfree;
 	/*@} */
 
 	/** \name Memory management */
 	/*@{ */
-	drm_map_list_t *maplist;	/**< Linked list of regions */
+	struct list_head maplist;	/**< Linked list of regions */
 	int map_count;			/**< Number of mappable regions */
-	drm_open_hash_t map_hash;	/**< User token hash table for maps */
+	struct drm_open_hash map_hash;	/**< User token hash table for maps */
 
 	/** \name Context handle management */
 	/*@{ */
-	drm_ctx_list_t *ctxlist;	/**< Linked list of context handles */
+	struct list_head ctxlist;	/**< Linked list of context handles */
 	int ctx_count;			/**< Number of context handles */
 	struct mutex ctxlist_mutex;	/**< For ctxlist */
 
-	drm_map_t **context_sareas;	    /**< per-context SAREA's */
-	int max_context;
+	struct idr ctx_idr;
 
-	drm_vma_entry_t *vmalist;	/**< List of vmas (for debugging) */
-	drm_lock_data_t lock;		/**< Information on hardware lock */
+	struct list_head vmalist;	/**< List of vmas (for debugging) */
+	struct drm_lock_data lock;	/**< Information on hardware lock */
 	/*@} */
 
 	/** \name DMA queues (contexts) */
@@ -699,8 +689,8 @@
 	int queue_count;		/**< Number of active DMA queues */
 	int queue_reserved;		  /**< Number of reserved DMA queues */
 	int queue_slots;		/**< Actual length of queuelist */
-	drm_queue_t **queuelist;	/**< Vector of pointers to DMA queues */
-	drm_device_dma_t *dma;		/**< Optional pointer for DMA support */
+	struct drm_queue **queuelist;	/**< Vector of pointers to DMA queues */
+	struct drm_device_dma *dma;		/**< Optional pointer for DMA support */
 	/*@} */
 
 	/** \name Context support */
@@ -725,8 +715,8 @@
 	atomic_t vbl_received;
 	atomic_t vbl_received2;		/**< number of secondary VBLANK interrupts */
 	spinlock_t vbl_lock;
-	drm_vbl_sig_t vbl_sigs;		/**< signal list to send on VBLANK */
-	drm_vbl_sig_t vbl_sigs2;	/**< signals to send on secondary VBLANK */
+	struct list_head vbl_sigs;		/**< signal list to send on VBLANK */
+	struct list_head vbl_sigs2;	/**< signals to send on secondary VBLANK */
 	unsigned int vbl_pending;
 	spinlock_t tasklet_lock;	/**< For drm_locked_tasklet */
 	void (*locked_tasklet_func)(struct drm_device *dev);
@@ -739,7 +729,7 @@
 	wait_queue_head_t buf_readers;	/**< Processes waiting to read */
 	wait_queue_head_t buf_writers;	/**< Processes waiting to ctx switch */
 
-	drm_agp_head_t *agp;	/**< AGP data */
+	struct drm_agp_head *agp;	/**< AGP data */
 
 	struct pci_dev *pdev;		/**< PCI device structure */
 	int pci_vendor;			/**< PCI vendor id */
@@ -747,26 +737,23 @@
 #ifdef __alpha__
 	struct pci_controller *hose;
 #endif
-	drm_sg_mem_t *sg;	/**< Scatter gather memory */
+	struct drm_sg_mem *sg;	/**< Scatter gather memory */
 	unsigned long *ctx_bitmap;	/**< context bitmap */
 	void *dev_private;		/**< device private data */
-	drm_sigdata_t sigdata;	   /**< For block_all_signals */
+	struct drm_sigdata sigdata;	   /**< For block_all_signals */
 	sigset_t sigmask;
 
 	struct drm_driver *driver;
 	drm_local_map_t *agp_buffer_map;
 	unsigned int agp_buffer_token;
-	drm_head_t primary;		/**< primary screen head */
+	struct drm_head primary;		/**< primary screen head */
 
 	/** \name Drawable information */
 	/*@{ */
 	spinlock_t drw_lock;
-	unsigned int drw_bitfield_length;
-	u32 *drw_bitfield;
-	unsigned int drw_info_length;
-	drm_drawable_info_t **drw_info;
+	struct idr drw_idr;
 	/*@} */
-} drm_device_t;
+};
 
 static __inline__ int drm_core_check_feature(struct drm_device *dev,
 					     int feature)
@@ -838,7 +825,7 @@
 		     unsigned int cmd, unsigned long arg);
 extern long drm_compat_ioctl(struct file *filp,
 			     unsigned int cmd, unsigned long arg);
-extern int drm_lastclose(drm_device_t *dev);
+extern int drm_lastclose(struct drm_device *dev);
 
 				/* Device support (drm_fops.h) */
 extern int drm_open(struct inode *inode, struct file *filp);
@@ -857,7 +844,7 @@
 			int request, int *eof, void *data);
 extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
 
-extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
+extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
 extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
 extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
 extern int drm_unbind_agp(DRM_AGP_MEM * handle);
@@ -896,9 +883,9 @@
 extern int drm_rmctx(struct inode *inode, struct file *filp,
 		     unsigned int cmd, unsigned long arg);
 
-extern int drm_ctxbitmap_init(drm_device_t * dev);
-extern void drm_ctxbitmap_cleanup(drm_device_t * dev);
-extern void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle);
+extern int drm_ctxbitmap_init(struct drm_device *dev);
+extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
+extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
 
 extern int drm_setsareactx(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg);
@@ -912,8 +899,9 @@
 		      unsigned int cmd, unsigned long arg);
 extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg);
-extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev,
+extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
 						  drm_drawable_t id);
+extern void drm_drawable_free_all(struct drm_device *dev);
 
 				/* Authentication IOCTL support (drm_auth.h) */
 extern int drm_getmagic(struct inode *inode, struct file *filp,
@@ -926,10 +914,10 @@
 		    unsigned int cmd, unsigned long arg);
 extern int drm_unlock(struct inode *inode, struct file *filp,
 		      unsigned int cmd, unsigned long arg);
-extern int drm_lock_take(drm_lock_data_t *lock_data, unsigned int context);
-extern int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context);
-extern void drm_idlelock_take(drm_lock_data_t *lock_data);
-extern void drm_idlelock_release(drm_lock_data_t *lock_data);
+extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
+extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context);
+extern void drm_idlelock_take(struct drm_lock_data *lock_data);
+extern void drm_idlelock_release(struct drm_lock_data *lock_data);
 
 /*
  * These are exported to drivers so that they can implement fencing using
@@ -940,15 +928,15 @@
 extern int drm_kernel_take_hw_lock(struct file *filp);
 
 				/* Buffer management support (drm_bufs.h) */
-extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addmap(drm_device_t * dev, unsigned int offset,
-		      unsigned int size, drm_map_type_t type,
-		      drm_map_flags_t flags, drm_local_map_t ** map_ptr);
+extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addmap(struct drm_device *dev, unsigned int offset,
+		      unsigned int size, enum drm_map_type type,
+		      enum drm_map_flags flags, drm_local_map_t ** map_ptr);
 extern int drm_addmap_ioctl(struct inode *inode, struct file *filp,
 			    unsigned int cmd, unsigned long arg);
-extern int drm_rmmap(drm_device_t * dev, drm_local_map_t * map);
-extern int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map);
+extern int drm_rmmap(struct drm_device *dev, drm_local_map_t * map);
+extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t * map);
 extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg);
 
@@ -963,56 +951,56 @@
 			unsigned int cmd, unsigned long arg);
 extern int drm_mapbufs(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg);
-extern unsigned long drm_get_resource_start(drm_device_t * dev,
+extern unsigned long drm_get_resource_start(struct drm_device *dev,
 					    unsigned int resource);
-extern unsigned long drm_get_resource_len(drm_device_t * dev,
+extern unsigned long drm_get_resource_len(struct drm_device *dev,
 					  unsigned int resource);
 
 				/* DMA support (drm_dma.h) */
-extern int drm_dma_setup(drm_device_t * dev);
-extern void drm_dma_takedown(drm_device_t * dev);
-extern void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf);
-extern void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp);
+extern int drm_dma_setup(struct drm_device *dev);
+extern void drm_dma_takedown(struct drm_device *dev);
+extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf);
+extern void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp);
 
 				/* IRQ support (drm_irq.h) */
 extern int drm_control(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg);
 extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-extern int drm_irq_uninstall(drm_device_t * dev);
-extern void drm_driver_irq_preinstall(drm_device_t * dev);
-extern void drm_driver_irq_postinstall(drm_device_t * dev);
-extern void drm_driver_irq_uninstall(drm_device_t * dev);
+extern int drm_irq_uninstall(struct drm_device *dev);
+extern void drm_driver_irq_preinstall(struct drm_device *dev);
+extern void drm_driver_irq_postinstall(struct drm_device *dev);
+extern void drm_driver_irq_uninstall(struct drm_device *dev);
 
 extern int drm_wait_vblank(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg);
-extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq);
-extern void drm_vbl_send_signals(drm_device_t * dev);
-extern void drm_locked_tasklet(drm_device_t *dev, void(*func)(drm_device_t*));
+extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
+extern void drm_vbl_send_signals(struct drm_device *dev);
+extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
 
 				/* AGP/GART support (drm_agpsupport.h) */
-extern drm_agp_head_t *drm_agp_init(drm_device_t * dev);
-extern int drm_agp_acquire(drm_device_t * dev);
+extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+extern int drm_agp_acquire(struct drm_device *dev);
 extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
 				 unsigned int cmd, unsigned long arg);
-extern int drm_agp_release(drm_device_t * dev);
+extern int drm_agp_release(struct drm_device *dev);
 extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
 				 unsigned int cmd, unsigned long arg);
-extern int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode);
+extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
 extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
 				unsigned int cmd, unsigned long arg);
-extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info);
+extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info * info);
 extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
 			      unsigned int cmd, unsigned long arg);
-extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
 extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg);
-extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
 extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
-extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
 extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg);
-extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
 extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
 extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge,
@@ -1024,16 +1012,18 @@
 				/* Stub support (drm_stub.h) */
 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
 		       struct drm_driver *driver);
-extern int drm_put_dev(drm_device_t * dev);
-extern int drm_put_head(drm_head_t * head);
+extern int drm_put_dev(struct drm_device *dev);
+extern int drm_put_head(struct drm_head *head);
 extern unsigned int drm_debug;
 extern unsigned int drm_cards_limit;
-extern drm_head_t **drm_heads;
+extern struct drm_head **drm_heads;
 extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 
+extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
+
 				/* Proc support (drm_proc.h) */
-extern int drm_proc_init(drm_device_t * dev,
+extern int drm_proc_init(struct drm_device *dev,
 			 int minor,
 			 struct proc_dir_entry *root,
 			 struct proc_dir_entry **dev_root);
@@ -1042,45 +1032,45 @@
 			    struct proc_dir_entry *dev_root);
 
 				/* Scatter Gather Support (drm_scatter.h) */
-extern void drm_sg_cleanup(drm_sg_mem_t * entry);
+extern void drm_sg_cleanup(struct drm_sg_mem * entry);
 extern int drm_sg_alloc(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
 extern int drm_sg_free(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg);
 
 			       /* ATI PCIGART support (ati_pcigart.h) */
-extern int drm_ati_pcigart_init(drm_device_t * dev,
-				drm_ati_pcigart_info * gart_info);
-extern int drm_ati_pcigart_cleanup(drm_device_t * dev,
-				   drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_init(struct drm_device *dev,
+				struct drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_cleanup(struct drm_device *dev,
+				   struct drm_ati_pcigart_info * gart_info);
 
-extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,
+extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
 				       size_t align, dma_addr_t maxaddr);
-extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
-extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
+extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
+extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
 
 			       /* sysfs support (drm_sysfs.c) */
 extern struct class *drm_sysfs_create(struct module *owner, char *name);
 extern void drm_sysfs_destroy(struct class *cs);
 extern struct class_device *drm_sysfs_device_add(struct class *cs,
-						 drm_head_t *head);
+						 struct drm_head *head);
 extern void drm_sysfs_device_remove(struct class_device *class_dev);
 
 /*
  * Basic memory manager support (drm_mm.c)
  */
-extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+extern struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
 				       unsigned long size,
 				       unsigned alignment);
-void drm_mm_put_block(drm_mm_node_t * cur);
-extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size,
+void drm_mm_put_block(struct drm_mm_node * cur);
+extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size,
 					 unsigned alignment, int best_match);
-extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size);
-extern void drm_mm_takedown(drm_mm_t *mm);
-extern int drm_mm_clean(drm_mm_t *mm);
-extern unsigned long drm_mm_tail_space(drm_mm_t *mm);
-extern int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size);
-extern int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size);
+extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size);
+extern void drm_mm_takedown(struct drm_mm *mm);
+extern int drm_mm_clean(struct drm_mm *mm);
+extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
+extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
+extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
 
 extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
 extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
@@ -1088,14 +1078,14 @@
 static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
 						   unsigned int token)
 {
-	drm_map_list_t *_entry;
-	list_for_each_entry(_entry, &dev->maplist->head, head)
+	struct drm_map_list *_entry;
+	list_for_each_entry(_entry, &dev->maplist, head)
 	    if (_entry->user_token == token)
 		return _entry->map;
 	return NULL;
 }
 
-static __inline__ int drm_device_is_agp(drm_device_t * dev)
+static __inline__ int drm_device_is_agp(struct drm_device *dev)
 {
 	if (dev->driver->device_is_agp != NULL) {
 		int err = (*dev->driver->device_is_agp) (dev);
@@ -1108,7 +1098,7 @@
 	return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
 
-static __inline__ int drm_device_is_pcie(drm_device_t * dev)
+static __inline__ int drm_device_is_pcie(struct drm_device *dev)
 {
 	return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
 }
@@ -1143,7 +1133,7 @@
 
 /*@}*/
 
-extern unsigned long drm_core_get_map_ofs(drm_map_t * map);
+extern unsigned long drm_core_get_map_ofs(struct drm_map * map);
 extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
 
 #endif				/* __KERNEL__ */
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index 40bfd9b..354f0e3 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -48,7 +48,7 @@
  * Verifies the AGP device has been initialized and acquired and fills in the
  * drm_agp_info structure with the information in drm_agp_head::agp_info.
  */
-int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info)
+int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
 {
 	DRM_AGP_KERN *kern;
 
@@ -74,16 +74,16 @@
 int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_agp_info_t info;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_info info;
 	int err;
 
 	err = drm_agp_info(dev, &info);
 	if (err)
 		return err;
 
-	if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
+	if (copy_to_user((struct drm_agp_info __user *) arg, &info, sizeof(info)))
 		return -EFAULT;
 	return 0;
 }
@@ -97,7 +97,7 @@
  * Verifies the AGP device hasn't been acquired before and calls
  * \c agp_backend_acquire.
  */
-int drm_agp_acquire(drm_device_t * dev)
+int drm_agp_acquire(struct drm_device * dev)
 {
 	if (!dev->agp)
 		return -ENODEV;
@@ -126,9 +126,9 @@
 int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
+	struct drm_file *priv = filp->private_data;
 
-	return drm_agp_acquire((drm_device_t *) priv->head->dev);
+	return drm_agp_acquire((struct drm_device *) priv->head->dev);
 }
 
 /**
@@ -139,7 +139,7 @@
  *
  * Verifies the AGP device has been acquired and calls \c agp_backend_release.
  */
-int drm_agp_release(drm_device_t * dev)
+int drm_agp_release(struct drm_device * dev)
 {
 	if (!dev->agp || !dev->agp->acquired)
 		return -EINVAL;
@@ -152,8 +152,8 @@
 int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	return drm_agp_release(dev);
 }
@@ -168,7 +168,7 @@
  * Verifies the AGP device has been acquired but not enabled, and calls
  * \c agp_enable.
  */
-int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode)
+int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
 {
 	if (!dev->agp || !dev->agp->acquired)
 		return -EINVAL;
@@ -185,11 +185,11 @@
 int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_agp_mode_t mode;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_mode mode;
 
-	if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
+	if (copy_from_user(&mode, (struct drm_agp_mode __user *) arg, sizeof(mode)))
 		return -EFAULT;
 
 	return drm_agp_enable(dev, mode);
@@ -207,9 +207,9 @@
  * Verifies the AGP device is present and has been acquired, allocates the
  * memory via alloc_agp() and creates a drm_agp_mem entry for it.
  */
-int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 	DRM_AGP_MEM *memory;
 	unsigned long pages;
 	u32 type;
@@ -232,11 +232,7 @@
 	entry->memory = memory;
 	entry->bound = 0;
 	entry->pages = pages;
-	entry->prev = NULL;
-	entry->next = dev->agp->memory;
-	if (dev->agp->memory)
-		dev->agp->memory->prev = entry;
-	dev->agp->memory = entry;
+	list_add(&entry->head, &dev->agp->memory);
 
 	request->handle = entry->handle;
 	request->physical = memory->physical;
@@ -248,10 +244,10 @@
 int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_agp_buffer_t request;
-	drm_agp_buffer_t __user *argp = (void __user *)arg;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_buffer request;
+	struct drm_agp_buffer __user *argp = (void __user *)arg;
 	int err;
 
 	if (copy_from_user(&request, argp, sizeof(request)))
@@ -262,10 +258,12 @@
 		return err;
 
 	if (copy_to_user(argp, &request, sizeof(request))) {
-		drm_agp_mem_t *entry = dev->agp->memory;
-
-		dev->agp->memory = entry->next;
-		dev->agp->memory->prev = NULL;
+		struct drm_agp_mem *entry;
+		list_for_each_entry(entry, &dev->agp->memory, head) {
+			if (entry->handle == request.handle)
+				break;
+		}
+		list_del(&entry->head);
 		drm_free_agp(entry->memory, entry->pages);
 		drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
 		return -EFAULT;
@@ -283,12 +281,12 @@
  *
  * Walks through drm_agp_head::memory until finding a matching handle.
  */
-static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
+static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
 					   unsigned long handle)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 
-	for (entry = dev->agp->memory; entry; entry = entry->next) {
+	list_for_each_entry(entry, &dev->agp->memory, head) {
 		if (entry->handle == handle)
 			return entry;
 	}
@@ -307,9 +305,9 @@
  * Verifies the AGP device is present and acquired, looks-up the AGP memory
  * entry and passes it to the unbind_agp() function.
  */
-int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 	int ret;
 
 	if (!dev->agp || !dev->agp->acquired)
@@ -328,12 +326,12 @@
 int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_agp_binding_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_binding request;
 
 	if (copy_from_user
-	    (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+	    (&request, (struct drm_agp_binding __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	return drm_agp_unbind(dev, &request);
@@ -352,9 +350,9 @@
  * is currently bound into the GATT. Looks-up the AGP memory entry and passes
  * it to bind_agp() function.
  */
-int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 	int retcode;
 	int page;
 
@@ -377,12 +375,12 @@
 int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_agp_binding_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_binding request;
 
 	if (copy_from_user
-	    (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+	    (&request, (struct drm_agp_binding __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	return drm_agp_bind(dev, &request);
@@ -402,9 +400,9 @@
  * unbind_agp(). Frees it via free_agp() as well as the entry itself
  * and unlinks from the doubly linked list it's inserted in.
  */
-int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
 {
-	drm_agp_mem_t *entry;
+	struct drm_agp_mem *entry;
 
 	if (!dev->agp || !dev->agp->acquired)
 		return -EINVAL;
@@ -413,13 +411,7 @@
 	if (entry->bound)
 		drm_unbind_agp(entry->memory);
 
-	if (entry->prev)
-		entry->prev->next = entry->next;
-	else
-		dev->agp->memory = entry->next;
-
-	if (entry->next)
-		entry->next->prev = entry->prev;
+	list_del(&entry->head);
 
 	drm_free_agp(entry->memory, entry->pages);
 	drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
@@ -430,12 +422,12 @@
 int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_agp_buffer_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_agp_buffer request;
 
 	if (copy_from_user
-	    (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
+	    (&request, (struct drm_agp_buffer __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	return drm_agp_free(dev, &request);
@@ -450,9 +442,9 @@
  * via the inter_module_* functions. Creates and initializes a drm_agp_head
  * structure.
  */
-drm_agp_head_t *drm_agp_init(drm_device_t * dev)
+struct drm_agp_head *drm_agp_init(struct drm_device *dev)
 {
-	drm_agp_head_t *head = NULL;
+	struct drm_agp_head *head = NULL;
 
 	if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
 		return NULL;
@@ -472,7 +464,7 @@
 		drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
 		return NULL;
 	}
-	head->memory = NULL;
+	INIT_LIST_HEAD(&head->memory);
 	head->cant_use_aperture = head->agp_info.cant_use_aperture;
 	head->page_mask = head->agp_info.page_mask;
 
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index c7b19d3..7f777da 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -45,15 +45,15 @@
  * the one with matching magic number, while holding the drm_device::struct_mutex
  * lock.
  */
-static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
+static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
 {
-	drm_file_t *retval = NULL;
-	drm_magic_entry_t *pt;
-	drm_hash_item_t *hash;
+	struct drm_file *retval = NULL;
+	struct drm_magic_entry *pt;
+	struct drm_hash_item *hash;
 
 	mutex_lock(&dev->struct_mutex);
 	if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
-		pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+		pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
 		retval = pt->priv;
 	}
 	mutex_unlock(&dev->struct_mutex);
@@ -71,10 +71,10 @@
  * associated the magic number hash key in drm_device::magiclist, while holding
  * the drm_device::struct_mutex lock.
  */
-static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
+static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
 			 drm_magic_t magic)
 {
-	drm_magic_entry_t *entry;
+	struct drm_magic_entry *entry;
 
 	DRM_DEBUG("%d\n", magic);
 
@@ -102,10 +102,10 @@
  * Searches and unlinks the entry in drm_device::magiclist with the magic
  * number hash key, while holding the drm_device::struct_mutex lock.
  */
-static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
+static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
 {
-	drm_magic_entry_t *pt;
-	drm_hash_item_t *hash;
+	struct drm_magic_entry *pt;
+	struct drm_hash_item *hash;
 
 	DRM_DEBUG("%d\n", magic);
 
@@ -114,7 +114,7 @@
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
-	pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+	pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
 	drm_ht_remove_item(&dev->magiclist, hash);
 	list_del(&pt->head);
 	mutex_unlock(&dev->struct_mutex);
@@ -142,9 +142,9 @@
 {
 	static drm_magic_t sequence = 0;
 	static DEFINE_SPINLOCK(lock);
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_auth_t auth;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_auth auth;
 
 	/* Find unique magic */
 	if (priv->magic) {
@@ -162,7 +162,7 @@
 	}
 
 	DRM_DEBUG("%u\n", auth.magic);
-	if (copy_to_user((drm_auth_t __user *) arg, &auth, sizeof(auth)))
+	if (copy_to_user((struct drm_auth __user *) arg, &auth, sizeof(auth)))
 		return -EFAULT;
 	return 0;
 }
@@ -181,12 +181,12 @@
 int drm_authmagic(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_auth_t auth;
-	drm_file_t *file;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_auth auth;
+	struct drm_file *file;
 
-	if (copy_from_user(&auth, (drm_auth_t __user *) arg, sizeof(auth)))
+	if (copy_from_user(&auth, (struct drm_auth __user *) arg, sizeof(auth)))
 		return -EFAULT;
 	DRM_DEBUG("%u\n", auth.magic);
 	if ((file = drm_find_file(dev, auth.magic))) {
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index c113458..923174c 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -36,26 +36,24 @@
 #include <linux/vmalloc.h>
 #include "drmP.h"
 
-unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource)
 {
 	return pci_resource_start(dev->pdev, resource);
 }
 EXPORT_SYMBOL(drm_get_resource_start);
 
-unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource)
 {
 	return pci_resource_len(dev->pdev, resource);
 }
 
 EXPORT_SYMBOL(drm_get_resource_len);
 
-static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
+static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
 					     drm_local_map_t *map)
 {
-	struct list_head *list;
-
-	list_for_each(list, &dev->maplist->head) {
-		drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
+	struct drm_map_list *entry;
+	list_for_each_entry(entry, &dev->maplist, head) {
 		if (entry->map && map->type == entry->map->type &&
 		    ((entry->map->offset == map->offset) ||
 		     (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
@@ -66,7 +64,7 @@
 	return NULL;
 }
 
-static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
+static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
 			  unsigned long user_token, int hashed_handle)
 {
 	int use_hashed_handle;
@@ -103,12 +101,13 @@
  * type.  Adds the map to the map list drm_device::maplist. Adds MTRR's where
  * applicable and if supported by the kernel.
  */
-static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
-			   unsigned int size, drm_map_type_t type,
-			   drm_map_flags_t flags, drm_map_list_t ** maplist)
+static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
+			   unsigned int size, enum drm_map_type type,
+			   enum drm_map_flags flags,
+			   struct drm_map_list ** maplist)
 {
-	drm_map_t *map;
-	drm_map_list_t *list;
+	struct drm_map *map;
+	struct drm_map_list *list;
 	drm_dma_handle_t *dmah;
 	unsigned long user_token;
 	int ret;
@@ -214,7 +213,7 @@
 		}
 		break;
 	case _DRM_AGP: {
-		drm_agp_mem_t *entry;
+		struct drm_agp_mem *entry;
 		int valid = 0;
 
 		if (!drm_core_has_AGP(dev)) {
@@ -237,14 +236,14 @@
 		 * skipped and we double check that dev->agp->memory is
 		 * actually set as well as being invalid before EPERM'ing
 		 */
-		for (entry = dev->agp->memory; entry; entry = entry->next) {
+		list_for_each_entry(entry, &dev->agp->memory, head) {
 			if ((map->offset >= entry->bound) &&
 			    (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
 				valid = 1;
 				break;
 			}
 		}
-		if (dev->agp->memory && !valid) {
+		if (!list_empty(&dev->agp->memory) && !valid) {
 			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 			return -EPERM;
 		}
@@ -289,7 +288,7 @@
 	list->map = map;
 
 	mutex_lock(&dev->struct_mutex);
-	list_add(&list->head, &dev->maplist->head);
+	list_add(&list->head, &dev->maplist);
 
 	/* Assign a 32-bit handle */
 	/* We do it here so that dev->struct_mutex protects the increment */
@@ -312,11 +311,11 @@
 	return 0;
 	}
 
-int drm_addmap(drm_device_t * dev, unsigned int offset,
-	       unsigned int size, drm_map_type_t type,
-	       drm_map_flags_t flags, drm_local_map_t ** map_ptr)
+int drm_addmap(struct drm_device * dev, unsigned int offset,
+	       unsigned int size, enum drm_map_type type,
+	       enum drm_map_flags flags, drm_local_map_t ** map_ptr)
 {
-	drm_map_list_t *list;
+	struct drm_map_list *list;
 	int rc;
 
 	rc = drm_addmap_core(dev, offset, size, type, flags, &list);
@@ -330,11 +329,11 @@
 int drm_addmap_ioctl(struct inode *inode, struct file *filp,
 		     unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_map_t map;
-	drm_map_list_t *maplist;
-	drm_map_t __user *argp = (void __user *)arg;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map map;
+	struct drm_map_list *maplist;
+	struct drm_map __user *argp = (void __user *)arg;
 	int err;
 
 	if (!(filp->f_mode & 3))
@@ -353,7 +352,7 @@
 	if (err)
 		return err;
 
-	if (copy_to_user(argp, maplist->map, sizeof(drm_map_t)))
+	if (copy_to_user(argp, maplist->map, sizeof(struct drm_map)))
 		return -EFAULT;
 
 	/* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
@@ -369,7 +368,7 @@
  * \param inode device inode.
  * \param filp file pointer.
  * \param cmd command.
- * \param arg pointer to a drm_map_t structure.
+ * \param arg pointer to a struct drm_map structure.
  * \return zero on success or a negative value on error.
  *
  * Searches the map on drm_device::maplist, removes it from the list, see if
@@ -378,31 +377,26 @@
  *
  * \sa drm_addmap
  */
-int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
+int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
 {
-	struct list_head *list;
-	drm_map_list_t *r_list = NULL;
+	struct drm_map_list *r_list = NULL, *list_t;
 	drm_dma_handle_t dmah;
+	int found = 0;
 
 	/* Find the list entry for the map and remove it */
-	list_for_each(list, &dev->maplist->head) {
-		r_list = list_entry(list, drm_map_list_t, head);
-
+	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
 		if (r_list->map == map) {
-			list_del(list);
+			list_del(&r_list->head);
 			drm_ht_remove_key(&dev->map_hash,
 					  r_list->user_token >> PAGE_SHIFT);
-			drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+			drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+			found = 1;
 			break;
 		}
 	}
 
-	/* List has wrapped around to the head pointer, or it's empty and we
-	 * didn't find anything.
-	 */
-	if (list == (&dev->maplist->head)) {
+	if (!found)
 		return -EINVAL;
-	}
 
 	switch (map->type) {
 	case _DRM_REGISTERS:
@@ -433,7 +427,7 @@
 	return 0;
 }
 
-int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
+int drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
 {
 	int ret;
 
@@ -456,21 +450,19 @@
 int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_map_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map request;
 	drm_local_map_t *map = NULL;
-	struct list_head *list;
+	struct drm_map_list *r_list;
 	int ret;
 
-	if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
+	if (copy_from_user(&request, (struct drm_map __user *) arg, sizeof(request))) {
 		return -EFAULT;
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	list_for_each(list, &dev->maplist->head) {
-		drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
-
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map &&
 		    r_list->user_token == (unsigned long)request.handle &&
 		    r_list->map->flags & _DRM_REMOVABLE) {
@@ -482,7 +474,7 @@
 	/* List has wrapped around to the head pointer, or its empty we didn't
 	 * find anything.
 	 */
-	if (list == (&dev->maplist->head)) {
+	if (list_empty(&dev->maplist) || !map) {
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
@@ -513,7 +505,8 @@
  *
  * Frees any pages and buffers associated with the given entry.
  */
-static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
+static void drm_cleanup_buf_error(struct drm_device * dev,
+				  struct drm_buf_entry * entry)
 {
 	int i;
 
@@ -550,20 +543,20 @@
 /**
  * Add AGP buffers for DMA transfers.
  *
- * \param dev drm_device_t to which the buffers are to be added.
- * \param request pointer to a drm_buf_desc_t describing the request.
+ * \param dev struct drm_device to which the buffers are to be added.
+ * \param request pointer to a struct drm_buf_desc describing the request.
  * \return zero on success or a negative number on failure.
  *
  * After some sanity checks creates a drm_buf structure for each buffer and
  * reallocates the buffer list of the same size order to accommodate the new
  * buffers.
  */
-int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_entry_t *entry;
-	drm_agp_mem_t *agp_entry;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_entry *entry;
+	struct drm_agp_mem *agp_entry;
+	struct drm_buf *buf;
 	unsigned long offset;
 	unsigned long agp_offset;
 	int count;
@@ -574,7 +567,7 @@
 	int total;
 	int byte_count;
 	int i, valid;
-	drm_buf_t **temp_buflist;
+	struct drm_buf **temp_buflist;
 
 	if (!dma)
 		return -EINVAL;
@@ -606,14 +599,14 @@
 
 	/* Make sure buffers are located in AGP memory that we own */
 	valid = 0;
-	for (agp_entry = dev->agp->memory; agp_entry; agp_entry = agp_entry->next) {
+	list_for_each_entry(agp_entry, &dev->agp->memory, head) {
 		if ((agp_offset >= agp_entry->bound) &&
 		    (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
 			valid = 1;
 			break;
 		}
 	}
-	if (dev->agp->memory && !valid) {
+	if (!list_empty(&dev->agp->memory) && !valid) {
 		DRM_DEBUG("zone invalid\n");
 		return -EINVAL;
 	}
@@ -728,24 +721,24 @@
 EXPORT_SYMBOL(drm_addbufs_agp);
 #endif				/* __OS_HAS_AGP */
 
-int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int count;
 	int order;
 	int size;
 	int total;
 	int page_order;
-	drm_buf_entry_t *entry;
+	struct drm_buf_entry *entry;
 	drm_dma_handle_t *dmah;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int alignment;
 	unsigned long offset;
 	int i;
 	int byte_count;
 	int page_count;
 	unsigned long *temp_pagelist;
-	drm_buf_t **temp_buflist;
+	struct drm_buf **temp_buflist;
 
 	if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
 		return -EINVAL;
@@ -954,11 +947,11 @@
 }
 EXPORT_SYMBOL(drm_addbufs_pci);
 
-static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_entry_t *entry;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_entry *entry;
+	struct drm_buf *buf;
 	unsigned long offset;
 	unsigned long agp_offset;
 	int count;
@@ -969,7 +962,7 @@
 	int total;
 	int byte_count;
 	int i;
-	drm_buf_t **temp_buflist;
+	struct drm_buf **temp_buflist;
 
 	if (!drm_core_check_feature(dev, DRIVER_SG))
 		return -EINVAL;
@@ -1116,11 +1109,11 @@
 	return 0;
 }
 
-static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_entry_t *entry;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_entry *entry;
+	struct drm_buf *buf;
 	unsigned long offset;
 	unsigned long agp_offset;
 	int count;
@@ -1131,7 +1124,7 @@
 	int total;
 	int byte_count;
 	int i;
-	drm_buf_t **temp_buflist;
+	struct drm_buf **temp_buflist;
 
 	if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
 		return -EINVAL;
@@ -1283,7 +1276,7 @@
  * \param inode device inode.
  * \param filp file pointer.
  * \param cmd command.
- * \param arg pointer to a drm_buf_desc_t request.
+ * \param arg pointer to a struct drm_buf_desc request.
  * \return zero on success or a negative number on failure.
  *
  * According with the memory type specified in drm_buf_desc::flags and the
@@ -1294,15 +1287,15 @@
 int drm_addbufs(struct inode *inode, struct file *filp,
 		unsigned int cmd, unsigned long arg)
 {
-	drm_buf_desc_t request;
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_buf_desc request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	int ret;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
 		return -EINVAL;
 
-	if (copy_from_user(&request, (drm_buf_desc_t __user *) arg,
+	if (copy_from_user(&request, (struct drm_buf_desc __user *) arg,
 			   sizeof(request)))
 		return -EFAULT;
 
@@ -1346,11 +1339,11 @@
 int drm_infobufs(struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_info_t request;
-	drm_buf_info_t __user *argp = (void __user *)arg;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_info request;
+	struct drm_buf_info __user *argp = (void __user *)arg;
 	int i;
 	int count;
 
@@ -1381,10 +1374,10 @@
 	if (request.count >= count) {
 		for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
 			if (dma->bufs[i].buf_count) {
-				drm_buf_desc_t __user *to =
+				struct drm_buf_desc __user *to =
 				    &request.list[count];
-				drm_buf_entry_t *from = &dma->bufs[i];
-				drm_freelist_t *list = &dma->bufs[i].freelist;
+				struct drm_buf_entry *from = &dma->bufs[i];
+				struct drm_freelist *list = &dma->bufs[i].freelist;
 				if (copy_to_user(&to->count,
 						 &from->buf_count,
 						 sizeof(from->buf_count)) ||
@@ -1434,12 +1427,12 @@
 int drm_markbufs(struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_desc_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_desc request;
 	int order;
-	drm_buf_entry_t *entry;
+	struct drm_buf_entry *entry;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
 		return -EINVAL;
@@ -1448,7 +1441,7 @@
 		return -EINVAL;
 
 	if (copy_from_user(&request,
-			   (drm_buf_desc_t __user *) arg, sizeof(request)))
+			   (struct drm_buf_desc __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d, %d, %d\n",
@@ -1484,13 +1477,13 @@
 int drm_freebufs(struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_free_t request;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_free request;
 	int i;
 	int idx;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
 		return -EINVAL;
@@ -1499,7 +1492,7 @@
 		return -EINVAL;
 
 	if (copy_from_user(&request,
-			   (drm_buf_free_t __user *) arg, sizeof(request)))
+			   (struct drm_buf_free __user *) arg, sizeof(request)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d\n", request.count);
@@ -1540,15 +1533,15 @@
 int drm_mapbufs(struct inode *inode, struct file *filp,
 		unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_map_t __user *argp = (void __user *)arg;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf_map __user *argp = (void __user *)arg;
 	int retcode = 0;
 	const int zero = 0;
 	unsigned long virtual;
 	unsigned long address;
-	drm_buf_map_t request;
+	struct drm_buf_map request;
 	int i;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
@@ -1574,7 +1567,7 @@
 			&& (dma->flags & _DRM_DMA_USE_SG))
 		    || (drm_core_check_feature(dev, DRIVER_FB_DMA)
 			&& (dma->flags & _DRM_DMA_USE_FB))) {
-			drm_map_t *map = dev->agp_buffer_map;
+			struct drm_map *map = dev->agp_buffer_map;
 			unsigned long token = dev->agp_buffer_token;
 
 			if (!map) {
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index 83094c7..61ad986 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -53,26 +53,14 @@
  * \param ctx_handle context handle.
  *
  * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::context_sareas, while holding the drm_device::struct_mutex
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
  * lock.
  */
-void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
+void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
 {
-	if (ctx_handle < 0)
-		goto failed;
-	if (!dev->ctx_bitmap)
-		goto failed;
-
-	if (ctx_handle < DRM_MAX_CTXBITMAP) {
-		mutex_lock(&dev->struct_mutex);
-		clear_bit(ctx_handle, dev->ctx_bitmap);
-		dev->context_sareas[ctx_handle] = NULL;
-		mutex_unlock(&dev->struct_mutex);
-		return;
-	}
-      failed:
-	DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
-	return;
+	mutex_lock(&dev->struct_mutex);
+	idr_remove(&dev->ctx_idr, ctx_handle);
+	mutex_unlock(&dev->struct_mutex);
 }
 
 /**
@@ -81,62 +69,28 @@
  * \param dev DRM device.
  * \return (non-negative) context handle on success or a negative number on failure.
  *
- * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
- * drm_device::context_sareas to accommodate the new entry while holding the
+ * Allocate a new idr from drm_device::ctx_idr while holding the
  * drm_device::struct_mutex lock.
  */
-static int drm_ctxbitmap_next(drm_device_t * dev)
+static int drm_ctxbitmap_next(struct drm_device * dev)
 {
-	int bit;
+	int new_id;
+	int ret;
 
-	if (!dev->ctx_bitmap)
-		return -1;
-
+again:
+	if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
+		DRM_ERROR("Out of memory expanding drawable idr\n");
+		return -ENOMEM;
+	}
 	mutex_lock(&dev->struct_mutex);
-	bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
-	if (bit < DRM_MAX_CTXBITMAP) {
-		set_bit(bit, dev->ctx_bitmap);
-		DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
-		if ((bit + 1) > dev->max_context) {
-			dev->max_context = (bit + 1);
-			if (dev->context_sareas) {
-				drm_map_t **ctx_sareas;
-
-				ctx_sareas = drm_realloc(dev->context_sareas,
-							 (dev->max_context -
-							  1) *
-							 sizeof(*dev->
-								context_sareas),
-							 dev->max_context *
-							 sizeof(*dev->
-								context_sareas),
-							 DRM_MEM_MAPS);
-				if (!ctx_sareas) {
-					clear_bit(bit, dev->ctx_bitmap);
-					mutex_unlock(&dev->struct_mutex);
-					return -1;
-				}
-				dev->context_sareas = ctx_sareas;
-				dev->context_sareas[bit] = NULL;
-			} else {
-				/* max_context == 1 at this point */
-				dev->context_sareas =
-				    drm_alloc(dev->max_context *
-					      sizeof(*dev->context_sareas),
-					      DRM_MEM_MAPS);
-				if (!dev->context_sareas) {
-					clear_bit(bit, dev->ctx_bitmap);
-					mutex_unlock(&dev->struct_mutex);
-					return -1;
-				}
-				dev->context_sareas[bit] = NULL;
-			}
-		}
+	ret = idr_get_new_above(&dev->ctx_idr, NULL,
+				DRM_RESERVED_CONTEXTS, &new_id);
+	if (ret == -EAGAIN) {
 		mutex_unlock(&dev->struct_mutex);
-		return bit;
+		goto again;
 	}
 	mutex_unlock(&dev->struct_mutex);
-	return -1;
+	return new_id;
 }
 
 /**
@@ -144,31 +98,11 @@
  *
  * \param dev DRM device.
  *
- * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Initialise the drm_device::ctx_idr
  */
-int drm_ctxbitmap_init(drm_device_t * dev)
+int drm_ctxbitmap_init(struct drm_device * dev)
 {
-	int i;
-	int temp;
-
-	mutex_lock(&dev->struct_mutex);
-	dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
-						     DRM_MEM_CTXBITMAP);
-	if (dev->ctx_bitmap == NULL) {
-		mutex_unlock(&dev->struct_mutex);
-		return -ENOMEM;
-	}
-	memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
-	dev->context_sareas = NULL;
-	dev->max_context = -1;
-	mutex_unlock(&dev->struct_mutex);
-
-	for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-		temp = drm_ctxbitmap_next(dev);
-		DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
-	}
-
+	idr_init(&dev->ctx_idr);
 	return 0;
 }
 
@@ -177,17 +111,13 @@
  *
  * \param dev DRM device.
  *
- * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
  */
-void drm_ctxbitmap_cleanup(drm_device_t * dev)
+void drm_ctxbitmap_cleanup(struct drm_device * dev)
 {
 	mutex_lock(&dev->struct_mutex);
-	if (dev->context_sareas)
-		drm_free(dev->context_sareas,
-			 sizeof(*dev->context_sareas) *
-			 dev->max_context, DRM_MEM_MAPS);
-	drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
+	idr_remove_all(&dev->ctx_idr);
 	mutex_unlock(&dev->struct_mutex);
 }
 
@@ -206,34 +136,34 @@
  * \param arg user argument pointing to a drm_ctx_priv_map structure.
  * \return zero on success or a negative number on failure.
  *
- * Gets the map from drm_device::context_sareas with the handle specified and
+ * Gets the map from drm_device::ctx_idr with the handle specified and
  * returns its handle.
  */
 int drm_getsareactx(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_ctx_priv_map_t __user *argp = (void __user *)arg;
-	drm_ctx_priv_map_t request;
-	drm_map_t *map;
-	drm_map_list_t *_entry;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx_priv_map __user *argp = (void __user *)arg;
+	struct drm_ctx_priv_map request;
+	struct drm_map *map;
+	struct drm_map_list *_entry;
 
 	if (copy_from_user(&request, argp, sizeof(request)))
 		return -EFAULT;
 
 	mutex_lock(&dev->struct_mutex);
-	if (dev->max_context < 0
-	    || request.ctx_id >= (unsigned)dev->max_context) {
+
+	map = idr_find(&dev->ctx_idr, request.ctx_id);
+	if (!map) {
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
-	map = dev->context_sareas[request.ctx_id];
 	mutex_unlock(&dev->struct_mutex);
 
 	request.handle = NULL;
-	list_for_each_entry(_entry, &dev->maplist->head, head) {
+	list_for_each_entry(_entry, &dev->maplist, head) {
 		if (_entry->map == map) {
 			request.handle =
 			    (void *)(unsigned long)_entry->user_token;
@@ -258,25 +188,24 @@
  * \return zero on success or a negative number on failure.
  *
  * Searches the mapping specified in \p arg and update the entry in
- * drm_device::context_sareas with it.
+ * drm_device::ctx_idr with it.
  */
 int drm_setsareactx(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_ctx_priv_map_t request;
-	drm_map_t *map = NULL;
-	drm_map_list_t *r_list = NULL;
-	struct list_head *list;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx_priv_map request;
+	struct drm_map *map = NULL;
+	struct drm_map_list *r_list = NULL;
 
 	if (copy_from_user(&request,
-			   (drm_ctx_priv_map_t __user *) arg, sizeof(request)))
+			   (struct drm_ctx_priv_map __user *) arg,
+			   sizeof(request)))
 		return -EFAULT;
 
 	mutex_lock(&dev->struct_mutex);
-	list_for_each(list, &dev->maplist->head) {
-		r_list = list_entry(list, drm_map_list_t, head);
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map
 		    && r_list->user_token == (unsigned long)request.handle)
 			goto found;
@@ -289,11 +218,10 @@
 	map = r_list->map;
 	if (!map)
 		goto bad;
-	if (dev->max_context < 0)
+
+	if (IS_ERR(idr_replace(&dev->ctx_idr, map, request.ctx_id)))
 		goto bad;
-	if (request.ctx_id >= (unsigned)dev->max_context)
-		goto bad;
-	dev->context_sareas[request.ctx_id] = map;
+
 	mutex_unlock(&dev->struct_mutex);
 	return 0;
 }
@@ -314,7 +242,7 @@
  *
  * Attempt to set drm_device::context_flag.
  */
-static int drm_context_switch(drm_device_t * dev, int old, int new)
+static int drm_context_switch(struct drm_device * dev, int old, int new)
 {
 	if (test_and_set_bit(0, &dev->context_flag)) {
 		DRM_ERROR("Reentering -- FIXME\n");
@@ -342,7 +270,7 @@
  * hardware lock is held, clears the drm_device::context_flag and wakes up
  * drm_device::context_wait.
  */
-static int drm_context_switch_complete(drm_device_t * dev, int new)
+static int drm_context_switch_complete(struct drm_device * dev, int new)
 {
 	dev->last_context = new;	/* PRE/POST: This is the _only_ writer. */
 	dev->last_switch = jiffies;
@@ -372,9 +300,9 @@
 int drm_resctx(struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg)
 {
-	drm_ctx_res_t res;
-	drm_ctx_t __user *argp = (void __user *)arg;
-	drm_ctx_t ctx;
+	struct drm_ctx_res res;
+	struct drm_ctx_res __user *argp = (void __user *)arg;
+	struct drm_ctx ctx;
 	int i;
 
 	if (copy_from_user(&res, argp, sizeof(res)))
@@ -409,11 +337,11 @@
 int drm_addctx(struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_ctx_list_t *ctx_entry;
-	drm_ctx_t __user *argp = (void __user *)arg;
-	drm_ctx_t ctx;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx_list *ctx_entry;
+	struct drm_ctx __user *argp = (void __user *)arg;
+	struct drm_ctx ctx;
 
 	if (copy_from_user(&ctx, argp, sizeof(ctx)))
 		return -EFAULT;
@@ -449,7 +377,7 @@
 	ctx_entry->tag = priv;
 
 	mutex_lock(&dev->ctxlist_mutex);
-	list_add(&ctx_entry->head, &dev->ctxlist->head);
+	list_add(&ctx_entry->head, &dev->ctxlist);
 	++dev->ctx_count;
 	mutex_unlock(&dev->ctxlist_mutex);
 
@@ -477,8 +405,8 @@
 int drm_getctx(struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg)
 {
-	drm_ctx_t __user *argp = (void __user *)arg;
-	drm_ctx_t ctx;
+	struct drm_ctx __user *argp = (void __user *)arg;
+	struct drm_ctx ctx;
 
 	if (copy_from_user(&ctx, argp, sizeof(ctx)))
 		return -EFAULT;
@@ -505,11 +433,11 @@
 int drm_switchctx(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_ctx_t ctx;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx ctx;
 
-	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+	if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d\n", ctx.handle);
@@ -530,11 +458,11 @@
 int drm_newctx(struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_ctx_t ctx;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx ctx;
 
-	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+	if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d\n", ctx.handle);
@@ -557,11 +485,11 @@
 int drm_rmctx(struct inode *inode, struct file *filp,
 	      unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_ctx_t ctx;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_ctx ctx;
 
-	if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+	if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
 		return -EFAULT;
 
 	DRM_DEBUG("%d\n", ctx.handle);
@@ -575,10 +503,10 @@
 	}
 
 	mutex_lock(&dev->ctxlist_mutex);
-	if (!list_empty(&dev->ctxlist->head)) {
-		drm_ctx_list_t *pos, *n;
+	if (!list_empty(&dev->ctxlist)) {
+		struct drm_ctx_list *pos, *n;
 
-		list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
 			if (pos->handle == ctx.handle) {
 				list_del(&pos->head);
 				drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
index 32ed19c..802fbdb 100644
--- a/drivers/char/drm/drm_dma.c
+++ b/drivers/char/drm/drm_dma.c
@@ -43,7 +43,7 @@
  *
  * Allocate and initialize a drm_device_dma structure.
  */
-int drm_dma_setup(drm_device_t * dev)
+int drm_dma_setup(struct drm_device *dev)
 {
 	int i;
 
@@ -67,9 +67,9 @@
  * Free all pages associated with DMA buffers, the buffers and pages lists, and
  * finally the drm_device::dma structure itself.
  */
-void drm_dma_takedown(drm_device_t * dev)
+void drm_dma_takedown(struct drm_device *dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i, j;
 
 	if (!dma)
@@ -129,7 +129,7 @@
  *
  * Resets the fields of \p buf.
  */
-void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
+void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf)
 {
 	if (!buf)
 		return;
@@ -152,9 +152,9 @@
  *
  * Frees each buffer associated with \p filp not already on the hardware.
  */
-void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp)
+void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	if (!dma)
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
index de37d5f..d6cdba5 100644
--- a/drivers/char/drm/drm_drawable.c
+++ b/drivers/char/drm/drm_drawable.c
@@ -44,83 +44,30 @@
 {
 	DRM_DEVICE;
 	unsigned long irqflags;
-	int i, j;
-	u32 *bitfield = dev->drw_bitfield;
-	unsigned int bitfield_length = dev->drw_bitfield_length;
-	drm_drawable_info_t **info = dev->drw_info;
-	unsigned int info_length = dev->drw_info_length;
-	drm_draw_t draw;
+	struct drm_draw draw;
+	int new_id = 0;
+	int ret;
 
-	for (i = 0, j = 0; i < bitfield_length; i++) {
-		if (bitfield[i] == ~0)
-			continue;
-
-		for (; j < 8 * sizeof(*bitfield); j++)
-			if (!(bitfield[i] & (1 << j)))
-				goto done;
+again:
+	if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
+		DRM_ERROR("Out of memory expanding drawable idr\n");
+		return -ENOMEM;
 	}
-done:
-
-	if (i == bitfield_length) {
-		bitfield_length++;
-
-		bitfield = drm_alloc(bitfield_length * sizeof(*bitfield),
-				     DRM_MEM_BUFS);
-
-		if (!bitfield) {
-			DRM_ERROR("Failed to allocate new drawable bitfield\n");
-			return DRM_ERR(ENOMEM);
-		}
-
-		if (8 * sizeof(*bitfield) * bitfield_length > info_length) {
-			info_length += 8 * sizeof(*bitfield);
-
-			info = drm_alloc(info_length * sizeof(*info),
-					 DRM_MEM_BUFS);
-
-			if (!info) {
-				DRM_ERROR("Failed to allocate new drawable info"
-					  " array\n");
-
-				drm_free(bitfield,
-					 bitfield_length * sizeof(*bitfield),
-					 DRM_MEM_BUFS);
-				return DRM_ERR(ENOMEM);
-			}
-		}
-
-		bitfield[i] = 0;
-	}
-
-	draw.handle = i * 8 * sizeof(*bitfield) + j + 1;
-	DRM_DEBUG("%d\n", draw.handle);
 
 	spin_lock_irqsave(&dev->drw_lock, irqflags);
-
-	bitfield[i] |= 1 << j;
-	info[draw.handle - 1] = NULL;
-
-	if (bitfield != dev->drw_bitfield) {
-		memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length *
-		       sizeof(*bitfield));
-		drm_free(dev->drw_bitfield, sizeof(*bitfield) *
-			 dev->drw_bitfield_length, DRM_MEM_BUFS);
-		dev->drw_bitfield = bitfield;
-		dev->drw_bitfield_length = bitfield_length;
-	}
-
-	if (info != dev->drw_info) {
-		memcpy(info, dev->drw_info, dev->drw_info_length *
-		       sizeof(*info));
-		drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length,
-			 DRM_MEM_BUFS);
-		dev->drw_info = info;
-		dev->drw_info_length = info_length;
+	ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id);
+	if (ret == -EAGAIN) {
+		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+		goto again;
 	}
 
 	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
-	DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
+	draw.handle = new_id;
+
+	DRM_DEBUG("%d\n", draw.handle);
+
+	DRM_COPY_TO_USER_IOCTL((struct drm_draw __user *)data, draw, sizeof(draw));
 
 	return 0;
 }
@@ -131,130 +78,52 @@
 int drm_rmdraw(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_draw_t draw;
- 	int id, idx;
- 	unsigned int shift;
+	struct drm_draw draw;
 	unsigned long irqflags;
-	u32 *bitfield = dev->drw_bitfield;
-	unsigned int bitfield_length = dev->drw_bitfield_length;
-	drm_drawable_info_t **info = dev->drw_info;
-	unsigned int info_length = dev->drw_info_length;
 
-	DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
+	DRM_COPY_FROM_USER_IOCTL(draw, (struct drm_draw __user *) data,
 				 sizeof(draw));
 
-	id = draw.handle - 1;
-	idx = id / (8 * sizeof(*bitfield));
-	shift = id % (8 * sizeof(*bitfield));
-
-	if (idx < 0 || idx >= bitfield_length ||
-	    !(bitfield[idx] & (1 << shift))) {
-		DRM_DEBUG("No such drawable %d\n", draw.handle);
-		return 0;
-	}
-
 	spin_lock_irqsave(&dev->drw_lock, irqflags);
 
-	bitfield[idx] &= ~(1 << shift);
+	drm_free(drm_get_drawable_info(dev, draw.handle),
+		 sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
+
+	idr_remove(&dev->drw_idr, draw.handle);
 
 	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-
-	if (info[id]) {
-		drm_free(info[id]->rects, info[id]->num_rects *
-			 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
-		drm_free(info[id], sizeof(**info), DRM_MEM_BUFS);
-	}
-
-	/* Can we shrink the arrays? */
-	if (idx == bitfield_length - 1) {
-		while (idx >= 0 && !bitfield[idx])
-			--idx;
-
-		bitfield_length = idx + 1;
-
-		if (idx != id / (8 * sizeof(*bitfield)))
-			bitfield = drm_alloc(bitfield_length *
-					     sizeof(*bitfield), DRM_MEM_BUFS);
-
-		if (!bitfield && bitfield_length) {
-			bitfield = dev->drw_bitfield;
-			bitfield_length = dev->drw_bitfield_length;
-		}
-	}
-
-	if (bitfield != dev->drw_bitfield) {
-		info_length = 8 * sizeof(*bitfield) * bitfield_length;
-
-		info = drm_alloc(info_length * sizeof(*info), DRM_MEM_BUFS);
-
-		if (!info && info_length) {
-			info = dev->drw_info;
-			info_length = dev->drw_info_length;
-		}
-
-		spin_lock_irqsave(&dev->drw_lock, irqflags);
-
-		memcpy(bitfield, dev->drw_bitfield, bitfield_length *
-		       sizeof(*bitfield));
-		drm_free(dev->drw_bitfield, sizeof(*bitfield) *
-			 dev->drw_bitfield_length, DRM_MEM_BUFS);
-		dev->drw_bitfield = bitfield;
-		dev->drw_bitfield_length = bitfield_length;
-
-		if (info != dev->drw_info) {
-			memcpy(info, dev->drw_info, info_length *
-			       sizeof(*info));
-			drm_free(dev->drw_info, sizeof(*info) *
-				 dev->drw_info_length, DRM_MEM_BUFS);
-			dev->drw_info = info;
-			dev->drw_info_length = info_length;
-		}
-
-		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-	}
-
 	DRM_DEBUG("%d\n", draw.handle);
 	return 0;
 }
 
-int drm_update_drawable_info(DRM_IOCTL_ARGS) {
+int drm_update_drawable_info(DRM_IOCTL_ARGS)
+{
 	DRM_DEVICE;
-	drm_update_draw_t update;
-	unsigned int id, idx, shift;
-	u32 *bitfield = dev->drw_bitfield;
-	unsigned long irqflags, bitfield_length = dev->drw_bitfield_length;
-	drm_drawable_info_t *info;
-	drm_clip_rect_t *rects;
+	struct drm_update_draw update;
+	unsigned long irqflags;
+	struct drm_clip_rect *rects;
+	struct drm_drawable_info *info;
 	int err;
 
-	DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
+	DRM_COPY_FROM_USER_IOCTL(update, (struct drm_update_draw __user *) data,
 				 sizeof(update));
 
-	id = update.handle - 1;
-	idx = id / (8 * sizeof(*bitfield));
-	shift = id % (8 * sizeof(*bitfield));
-
-	if (idx < 0 || idx >= bitfield_length ||
-	    !(bitfield[idx] & (1 << shift))) {
-		DRM_ERROR("No such drawable %d\n", update.handle);
-		return DRM_ERR(EINVAL);
-	}
-
-	info = dev->drw_info[id];
-
+	info = idr_find(&dev->drw_idr, update.handle);
 	if (!info) {
-		info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS);
-
-		if (!info) {
-			DRM_ERROR("Failed to allocate drawable info memory\n");
-			return DRM_ERR(ENOMEM);
+		info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
+		if (!info)
+			return -ENOMEM;
+		if (IS_ERR(idr_replace(&dev->drw_idr, info, update.handle))) {
+			DRM_ERROR("No such drawable %d\n", update.handle);
+			drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+			return -EINVAL;
 		}
 	}
 
 	switch (update.type) {
 	case DRM_DRAWABLE_CLIPRECTS:
 		if (update.num != info->num_rects) {
-			rects = drm_alloc(update.num * sizeof(drm_clip_rect_t),
+			rects = drm_alloc(update.num * sizeof(struct drm_clip_rect),
 					 DRM_MEM_BUFS);
 		} else
 			rects = info->rects;
@@ -266,7 +135,7 @@
 		}
 
 		if (update.num && DRM_COPY_FROM_USER(rects,
-						     (drm_clip_rect_t __user *)
+						     (struct drm_clip_rect __user *)
 						     (unsigned long)update.data,
 						     update.num *
 						     sizeof(*rects))) {
@@ -279,17 +148,16 @@
 
 		if (rects != info->rects) {
 			drm_free(info->rects, info->num_rects *
-				 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+				 sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
 		}
 
 		info->rects = rects;
 		info->num_rects = update.num;
-		dev->drw_info[id] = info;
 
 		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
 		DRM_DEBUG("Updated %d cliprects for drawable %d\n",
-			  info->num_rects, id);
+			  info->num_rects, update.handle);
 		break;
 	default:
 		DRM_ERROR("Invalid update type %d\n", update.type);
@@ -299,11 +167,9 @@
 	return 0;
 
 error:
-	if (!dev->drw_info[id])
-		drm_free(info, sizeof(*info), DRM_MEM_BUFS);
-	else if (rects != dev->drw_info[id]->rects)
-		drm_free(rects, update.num *
-			 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+	if (rects != info->rects)
+		drm_free(rects, update.num * sizeof(struct drm_clip_rect),
+			 DRM_MEM_BUFS);
 
 	return err;
 }
@@ -311,20 +177,27 @@
 /**
  * Caller must hold the drawable spinlock!
  */
-drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
-	u32 *bitfield = dev->drw_bitfield;
-	unsigned int idx, shift;
-
-	id--;
-	idx = id / (8 * sizeof(*bitfield));
-	shift = id % (8 * sizeof(*bitfield));
-
-	if (idx < 0 || idx >= dev->drw_bitfield_length ||
-	    !(bitfield[idx] & (1 << shift))) {
-		DRM_DEBUG("No such drawable %d\n", id);
-		return NULL;
-	}
-
-	return dev->drw_info[id];
+struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id)
+{
+	return idr_find(&dev->drw_idr, id);
 }
 EXPORT_SYMBOL(drm_get_drawable_info);
+
+static int drm_drawable_free(int idr, void *p, void *data)
+{
+	struct drm_drawable_info *info = p;
+
+	if (info) {
+		drm_free(info->rects, info->num_rects *
+			 sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
+		drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+	}
+
+	return 0;
+}
+
+void drm_drawable_free_all(struct drm_device *dev)
+{
+	idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
+	idr_remove_all(&dev->drw_idr);
+}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 8e77b7e..19994cd 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -129,11 +129,11 @@
  *
  * \sa drm_device
  */
-int drm_lastclose(drm_device_t * dev)
+int drm_lastclose(struct drm_device * dev)
 {
-	drm_magic_entry_t *pt, *next;
-	drm_map_list_t *r_list;
-	drm_vma_entry_t *vma, *vma_next;
+	struct drm_magic_entry *pt, *next;
+	struct drm_map_list *r_list, *list_t;
+	struct drm_vma_entry *vma, *vma_temp;
 	int i;
 
 	DRM_DEBUG("\n");
@@ -151,19 +151,10 @@
 	if (dev->irq_enabled)
 		drm_irq_uninstall(dev);
 
-	/* Free drawable information memory */
-	for (i = 0; i < dev->drw_bitfield_length / sizeof(*dev->drw_bitfield);
-	     i++) {
-		drm_drawable_info_t *info = drm_get_drawable_info(dev, i);
-
-		if (info) {
-			drm_free(info->rects, info->num_rects *
-				 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
-			drm_free(info, sizeof(*info), DRM_MEM_BUFS);
-		}
-	}
-
 	mutex_lock(&dev->struct_mutex);
+
+	/* Free drawable information memory */
+	drm_drawable_free_all(dev);
 	del_timer(&dev->timer);
 
 	/* Clear pid list */
@@ -178,19 +169,17 @@
 
 	/* Clear AGP information */
 	if (drm_core_has_AGP(dev) && dev->agp) {
-		drm_agp_mem_t *entry;
-		drm_agp_mem_t *nexte;
+		struct drm_agp_mem *entry, *tempe;
 
 		/* Remove AGP resources, but leave dev->agp
 		   intact until drv_cleanup is called. */
-		for (entry = dev->agp->memory; entry; entry = nexte) {
-			nexte = entry->next;
+		list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
 			if (entry->bound)
 				drm_unbind_agp(entry->memory);
 			drm_free_agp(entry->memory, entry->pages);
 			drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
 		}
-		dev->agp->memory = NULL;
+		INIT_LIST_HEAD(&dev->agp->memory);
 
 		if (dev->agp->acquired)
 			drm_agp_release(dev);
@@ -204,20 +193,14 @@
 	}
 
 	/* Clear vma list (only built for debugging) */
-	if (dev->vmalist) {
-		for (vma = dev->vmalist; vma; vma = vma_next) {
-			vma_next = vma->next;
-			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-		}
-		dev->vmalist = NULL;
+	list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
+		list_del(&vma->head);
+		drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
 	}
 
-	if (dev->maplist) {
-		while (!list_empty(&dev->maplist->head)) {
-			struct list_head *list = dev->maplist->head.next;
-			r_list = list_entry(list, drm_map_list_t, head);
-			drm_rmmap_locked(dev, r_list->map);
-		}
+	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
+		drm_rmmap_locked(dev, r_list->map);
+		r_list = NULL;
 	}
 
 	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
@@ -298,7 +281,7 @@
  *
  * \sa drm_init
  */
-static void drm_cleanup(drm_device_t * dev)
+static void drm_cleanup(struct drm_device * dev)
 {
 	DRM_DEBUG("\n");
 
@@ -309,11 +292,7 @@
 
 	drm_lastclose(dev);
 
-	if (dev->maplist) {
-		drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
-		dev->maplist = NULL;
-		drm_ht_remove(&dev->map_hash);
-	}
+	drm_ht_remove(&dev->map_hash);
 
 	drm_ctxbitmap_cleanup(dev);
 
@@ -342,8 +321,8 @@
 void drm_exit(struct drm_driver *driver)
 {
 	int i;
-	drm_device_t *dev = NULL;
-	drm_head_t *head;
+	struct drm_device *dev = NULL;
+	struct drm_head *head;
 
 	DRM_DEBUG("\n");
 
@@ -442,10 +421,10 @@
 static int drm_version(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_version_t __user *argp = (void __user *)arg;
-	drm_version_t version;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_version __user *argp = (void __user *)arg;
+	struct drm_version version;
 	int len;
 
 	if (copy_from_user(&version, argp, sizeof(version)))
@@ -478,8 +457,8 @@
 int drm_ioctl(struct inode *inode, struct file *filp,
 	      unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_ioctl_desc_t *ioctl;
 	drm_ioctl_t *func;
 	unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -529,3 +508,17 @@
 }
 
 EXPORT_SYMBOL(drm_ioctl);
+
+drm_local_map_t *drm_getsarea(struct drm_device *dev)
+{
+	struct drm_map_list *entry;
+
+	list_for_each_entry(entry, &dev->maplist, head) {
+		if (entry->map && entry->map->type == _DRM_SHM &&
+		    (entry->map->flags & _DRM_CONTAINS_LOCK)) {
+			return entry->map;
+		}
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(drm_getsarea);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 3b159ca..7bc51ba 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -39,9 +39,9 @@
 #include <linux/poll.h>
 
 static int drm_open_helper(struct inode *inode, struct file *filp,
-			   drm_device_t * dev);
+			   struct drm_device * dev);
 
-static int drm_setup(drm_device_t * dev)
+static int drm_setup(struct drm_device * dev)
 {
 	drm_local_map_t *map;
 	int i;
@@ -79,13 +79,6 @@
 	drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
 	INIT_LIST_HEAD(&dev->magicfree);
 
-	dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
-	if (dev->ctxlist == NULL)
-		return -ENOMEM;
-	memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
-	INIT_LIST_HEAD(&dev->ctxlist->head);
-
-	dev->vmalist = NULL;
 	dev->sigdata.lock = NULL;
 	init_waitqueue_head(&dev->lock.lock_queue);
 	dev->queue_count = 0;
@@ -135,7 +128,7 @@
  */
 int drm_open(struct inode *inode, struct file *filp)
 {
-	drm_device_t *dev = NULL;
+	struct drm_device *dev = NULL;
 	int minor = iminor(inode);
 	int retcode = 0;
 
@@ -174,7 +167,7 @@
  */
 int drm_stub_open(struct inode *inode, struct file *filp)
 {
-	drm_device_t *dev = NULL;
+	struct drm_device *dev = NULL;
 	int minor = iminor(inode);
 	int err = -ENODEV;
 	const struct file_operations *old_fops;
@@ -230,10 +223,10 @@
  * filp and add it into the double linked list in \p dev.
  */
 static int drm_open_helper(struct inode *inode, struct file *filp,
-			   drm_device_t * dev)
+			   struct drm_device * dev)
 {
 	int minor = iminor(inode);
-	drm_file_t *priv;
+	struct drm_file *priv;
 	int ret;
 
 	if (filp->f_flags & O_EXCL)
@@ -258,6 +251,8 @@
 	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count = 0;
 
+	INIT_LIST_HEAD(&priv->lhead);
+
 	if (dev->driver->open) {
 		ret = dev->driver->open(dev, priv);
 		if (ret < 0)
@@ -265,19 +260,10 @@
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	if (!dev->file_last) {
-		priv->next = NULL;
-		priv->prev = NULL;
-		dev->file_first = priv;
-		dev->file_last = priv;
-		/* first opener automatically becomes master */
+	if (list_empty(&dev->filelist))
 		priv->master = 1;
-	} else {
-		priv->next = NULL;
-		priv->prev = dev->file_last;
-		dev->file_last->next = priv;
-		dev->file_last = priv;
-	}
+
+	list_add(&priv->lhead, &dev->filelist);
 	mutex_unlock(&dev->struct_mutex);
 
 #ifdef __alpha__
@@ -309,8 +295,8 @@
 /** No-op. */
 int drm_fasync(int fd, struct file *filp, int on)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	int retcode;
 
 	DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
@@ -336,8 +322,8 @@
  */
 int drm_release(struct inode *inode, struct file *filp)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev;
 	int retcode = 0;
 
 	lock_kernel();
@@ -414,10 +400,10 @@
 	drm_fasync(-1, filp, 0);
 
 	mutex_lock(&dev->ctxlist_mutex);
-	if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
-		drm_ctx_list_t *pos, *n;
+	if (!list_empty(&dev->ctxlist)) {
+		struct drm_ctx_list *pos, *n;
 
-		list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
 			if (pos->tag == priv &&
 			    pos->handle != DRM_KERNEL_CONTEXT) {
 				if (dev->driver->context_dtor)
@@ -436,22 +422,12 @@
 
 	mutex_lock(&dev->struct_mutex);
 	if (priv->remove_auth_on_close == 1) {
-		drm_file_t *temp = dev->file_first;
-		while (temp) {
+		struct drm_file *temp;
+
+		list_for_each_entry(temp, &dev->filelist, lhead)
 			temp->authenticated = 0;
-			temp = temp->next;
-		}
 	}
-	if (priv->prev) {
-		priv->prev->next = priv->next;
-	} else {
-		dev->file_first = priv->next;
-	}
-	if (priv->next) {
-		priv->next->prev = priv->prev;
-	} else {
-		dev->file_last = priv->prev;
-	}
+	list_del(&priv->lhead);
 	mutex_unlock(&dev->struct_mutex);
 
 	if (dev->driver->postclose)
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c
index 31acb62..3ad3190 100644
--- a/drivers/char/drm/drm_hashtab.c
+++ b/drivers/char/drm/drm_hashtab.c
@@ -36,7 +36,7 @@
 #include "drm_hashtab.h"
 #include <linux/hash.h>
 
-int drm_ht_create(drm_open_hash_t *ht, unsigned int order)
+int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
 {
 	unsigned int i;
 
@@ -63,9 +63,9 @@
 	return 0;
 }
 
-void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key)
+void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
 {
-	drm_hash_item_t *entry;
+	struct drm_hash_item *entry;
 	struct hlist_head *h_list;
 	struct hlist_node *list;
 	unsigned int hashed_key;
@@ -75,15 +75,15 @@
 	DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
 	h_list = &ht->table[hashed_key];
 	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, drm_hash_item_t, head);
+		entry = hlist_entry(list, struct drm_hash_item, head);
 		DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
 	}
 }
 
-static struct hlist_node *drm_ht_find_key(drm_open_hash_t *ht, 
+static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, 
 					  unsigned long key)
 {
-	drm_hash_item_t *entry;
+	struct drm_hash_item *entry;
 	struct hlist_head *h_list;
 	struct hlist_node *list;
 	unsigned int hashed_key;
@@ -91,7 +91,7 @@
 	hashed_key = hash_long(key, ht->order);
 	h_list = &ht->table[hashed_key];
 	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, drm_hash_item_t, head);
+		entry = hlist_entry(list, struct drm_hash_item, head);
 		if (entry->key == key)
 			return list;
 		if (entry->key > key)
@@ -101,9 +101,9 @@
 }
 
 
-int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
+int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
-	drm_hash_item_t *entry;
+	struct drm_hash_item *entry;
 	struct hlist_head *h_list;
 	struct hlist_node *list, *parent;
 	unsigned int hashed_key;
@@ -113,7 +113,7 @@
 	h_list = &ht->table[hashed_key];
 	parent = NULL;
 	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, drm_hash_item_t, head);
+		entry = hlist_entry(list, struct drm_hash_item, head);
 		if (entry->key == key)
 			return -EINVAL;
 		if (entry->key > key)
@@ -132,7 +132,7 @@
  * Just insert an item and return any "bits" bit key that hasn't been 
  * used before.
  */
-int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
 			      unsigned long seed, int bits, int shift,
 			      unsigned long add)
 {
@@ -156,8 +156,8 @@
 	return 0;
 }
 
-int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key,
-		     drm_hash_item_t **item)
+int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
+		     struct drm_hash_item **item)
 {
 	struct hlist_node *list;
 
@@ -165,11 +165,11 @@
 	if (!list)
 		return -EINVAL;
 
-	*item = hlist_entry(list, drm_hash_item_t, head);
+	*item = hlist_entry(list, struct drm_hash_item, head);
 	return 0;
 }
 
-int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key)
+int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 {
 	struct hlist_node *list;
 
@@ -182,14 +182,14 @@
 	return -EINVAL;
 }
 
-int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item)
+int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
 	hlist_del_init(&item->head);
 	ht->fill--;
 	return 0;
 }
 
-void drm_ht_remove(drm_open_hash_t *ht)
+void drm_ht_remove(struct drm_open_hash *ht)
 {
 	if (ht->table) {
 		if (ht->use_vmalloc)
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h
index 613091c..0f13767 100644
--- a/drivers/char/drm/drm_hashtab.h
+++ b/drivers/char/drm/drm_hashtab.h
@@ -37,31 +37,31 @@
 
 #define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
 
-typedef struct drm_hash_item{
+struct drm_hash_item {
 	struct hlist_node head;
 	unsigned long key;
-} drm_hash_item_t;
+};
 
-typedef struct drm_open_hash{
+struct drm_open_hash {
 	unsigned int size;
 	unsigned int order;
 	unsigned int fill;
 	struct hlist_head *table;
 	int use_vmalloc;
-} drm_open_hash_t;
+};
 
 
-extern int drm_ht_create(drm_open_hash_t *ht, unsigned int order);
-extern int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item);
-extern int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
+extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
 				     unsigned long seed, int bits, int shift,
 				     unsigned long add);
-extern int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item);
+extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
 
-extern void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key);
-extern int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key);
-extern int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item);
-extern void drm_ht_remove(drm_open_hash_t *ht);
+extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern void drm_ht_remove(struct drm_open_hash *ht);
 
 
 #endif
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index fafeb34..462f46f 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -82,7 +82,7 @@
 			      unsigned long arg)
 {
 	drm_version32_t v32;
-	drm_version_t __user *version;
+	struct drm_version __user *version;
 	int err;
 
 	if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
@@ -129,7 +129,7 @@
 				unsigned long arg)
 {
 	drm_unique32_t uq32;
-	drm_unique_t __user *u;
+	struct drm_unique __user *u;
 	int err;
 
 	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
@@ -159,7 +159,7 @@
 				unsigned long arg)
 {
 	drm_unique32_t uq32;
-	drm_unique_t __user *u;
+	struct drm_unique __user *u;
 
 	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
 		return -EFAULT;
@@ -179,8 +179,8 @@
 typedef struct drm_map32 {
 	u32 offset;		/**< Requested physical address (0 for SAREA)*/
 	u32 size;		/**< Requested physical size (bytes) */
-	drm_map_type_t type;	/**< Type of memory to map */
-	drm_map_flags_t flags;	/**< Flags */
+	enum drm_map_type type;	/**< Type of memory to map */
+	enum drm_map_flags flags;	/**< Flags */
 	u32 handle;		/**< User-space: "Handle" to pass to mmap() */
 	int mtrr;		/**< MTRR slot used */
 } drm_map32_t;
@@ -190,7 +190,7 @@
 {
 	drm_map32_t __user *argp = (void __user *)arg;
 	drm_map32_t m32;
-	drm_map_t __user *map;
+	struct drm_map __user *map;
 	int idx, err;
 	void *handle;
 
@@ -228,7 +228,7 @@
 {
 	drm_map32_t __user *argp = (void __user *)arg;
 	drm_map32_t m32;
-	drm_map_t __user *map;
+	struct drm_map __user *map;
 	int err;
 	void *handle;
 
@@ -270,7 +270,7 @@
 			    unsigned long arg)
 {
 	drm_map32_t __user *argp = (void __user *)arg;
-	drm_map_t __user *map;
+	struct drm_map __user *map;
 	u32 handle;
 
 	if (get_user(handle, &argp->handle))
@@ -300,7 +300,7 @@
 {
 	drm_client32_t c32;
 	drm_client32_t __user *argp = (void __user *)arg;
-	drm_client_t __user *client;
+	struct drm_client __user *client;
 	int idx, err;
 
 	if (get_user(idx, &argp->idx))
@@ -333,7 +333,7 @@
 	u32 count;
 	struct {
 		u32 value;
-		drm_stat_type_t type;
+		enum drm_stat_type type;
 	} data[15];
 } drm_stats32_t;
 
@@ -342,7 +342,7 @@
 {
 	drm_stats32_t s32;
 	drm_stats32_t __user *argp = (void __user *)arg;
-	drm_stats_t __user *stats;
+	struct drm_stats __user *stats;
 	int i, err;
 
 	stats = compat_alloc_user_space(sizeof(*stats));
@@ -379,7 +379,7 @@
 			      unsigned long arg)
 {
 	drm_buf_desc32_t __user *argp = (void __user *)arg;
-	drm_buf_desc_t __user *buf;
+	struct drm_buf_desc __user *buf;
 	int err;
 	unsigned long agp_start;
 
@@ -411,7 +411,7 @@
 {
 	drm_buf_desc32_t b32;
 	drm_buf_desc32_t __user *argp = (void __user *)arg;
-	drm_buf_desc_t __user *buf;
+	struct drm_buf_desc __user *buf;
 
 	if (copy_from_user(&b32, argp, sizeof(b32)))
 		return -EFAULT;
@@ -440,8 +440,8 @@
 	drm_buf_info32_t req32;
 	drm_buf_info32_t __user *argp = (void __user *)arg;
 	drm_buf_desc32_t __user *to;
-	drm_buf_info_t __user *request;
-	drm_buf_desc_t __user *list;
+	struct drm_buf_info __user *request;
+	struct drm_buf_desc __user *list;
 	size_t nbytes;
 	int i, err;
 	int count, actual;
@@ -457,11 +457,11 @@
 	    && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
 		return -EFAULT;
 
-	nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t);
+	nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
 	request = compat_alloc_user_space(nbytes);
 	if (!access_ok(VERIFY_WRITE, request, nbytes))
 		return -EFAULT;
-	list = (drm_buf_desc_t *) (request + 1);
+	list = (struct drm_buf_desc *) (request + 1);
 
 	if (__put_user(count, &request->count)
 	    || __put_user(list, &request->list))
@@ -477,7 +477,7 @@
 	if (count >= actual)
 		for (i = 0; i < actual; ++i)
 			if (__copy_in_user(&to[i], &list[i],
-					   offsetof(drm_buf_desc_t, flags)))
+					   offsetof(struct drm_buf_desc, flags)))
 				return -EFAULT;
 
 	if (__put_user(actual, &argp->count))
@@ -505,8 +505,8 @@
 	drm_buf_map32_t __user *argp = (void __user *)arg;
 	drm_buf_map32_t req32;
 	drm_buf_pub32_t __user *list32;
-	drm_buf_map_t __user *request;
-	drm_buf_pub_t __user *list;
+	struct drm_buf_map __user *request;
+	struct drm_buf_pub __user *list;
 	int i, err;
 	int count, actual;
 	size_t nbytes;
@@ -519,11 +519,11 @@
 
 	if (count < 0)
 		return -EINVAL;
-	nbytes = sizeof(*request) + count * sizeof(drm_buf_pub_t);
+	nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
 	request = compat_alloc_user_space(nbytes);
 	if (!access_ok(VERIFY_WRITE, request, nbytes))
 		return -EFAULT;
-	list = (drm_buf_pub_t *) (request + 1);
+	list = (struct drm_buf_pub *) (request + 1);
 
 	if (__put_user(count, &request->count)
 	    || __put_user(list, &request->list))
@@ -539,7 +539,7 @@
 	if (count >= actual)
 		for (i = 0; i < actual; ++i)
 			if (__copy_in_user(&list32[i], &list[i],
-					   offsetof(drm_buf_pub_t, address))
+					   offsetof(struct drm_buf_pub, address))
 			    || __get_user(addr, &list[i].address)
 			    || __put_user((unsigned long)addr,
 					  &list32[i].address))
@@ -562,7 +562,7 @@
 			       unsigned long arg)
 {
 	drm_buf_free32_t req32;
-	drm_buf_free_t __user *request;
+	struct drm_buf_free __user *request;
 	drm_buf_free32_t __user *argp = (void __user *)arg;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -589,7 +589,7 @@
 				  unsigned long arg)
 {
 	drm_ctx_priv_map32_t req32;
-	drm_ctx_priv_map_t __user *request;
+	struct drm_ctx_priv_map __user *request;
 	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -610,7 +610,7 @@
 static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
 				  unsigned long arg)
 {
-	drm_ctx_priv_map_t __user *request;
+	struct drm_ctx_priv_map __user *request;
 	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
 	int err;
 	unsigned int ctx_id;
@@ -648,7 +648,7 @@
 {
 	drm_ctx_res32_t __user *argp = (void __user *)arg;
 	drm_ctx_res32_t res32;
-	drm_ctx_res_t __user *res;
+	struct drm_ctx_res __user *res;
 	int err;
 
 	if (copy_from_user(&res32, argp, sizeof(res32)))
@@ -658,7 +658,7 @@
 	if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
 		return -EFAULT;
 	if (__put_user(res32.count, &res->count)
-	    || __put_user((drm_ctx_t __user *) (unsigned long)res32.contexts,
+	    || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
 			  &res->contexts))
 		return -EFAULT;
 
@@ -679,7 +679,7 @@
 	int send_count;		  /**< Number of buffers to send */
 	u32 send_indices;	  /**< List of handles to buffers */
 	u32 send_sizes;		  /**< Lengths of data to send */
-	drm_dma_flags_t flags;		  /**< Flags */
+	enum drm_dma_flags flags;		  /**< Flags */
 	int request_count;	  /**< Number of buffers requested */
 	int request_size;	  /**< Desired size for buffers */
 	u32 request_indices;	  /**< Buffer information */
@@ -692,7 +692,7 @@
 {
 	drm_dma32_t d32;
 	drm_dma32_t __user *argp = (void __user *)arg;
-	drm_dma_t __user *d;
+	struct drm_dma __user *d;
 	int err;
 
 	if (copy_from_user(&d32, argp, sizeof(d32)))
@@ -740,7 +740,7 @@
 {
 	drm_agp_mode32_t __user *argp = (void __user *)arg;
 	drm_agp_mode32_t m32;
-	drm_agp_mode_t __user *mode;
+	struct drm_agp_mode __user *mode;
 
 	if (get_user(m32.mode, &argp->mode))
 		return -EFAULT;
@@ -772,7 +772,7 @@
 {
 	drm_agp_info32_t __user *argp = (void __user *)arg;
 	drm_agp_info32_t i32;
-	drm_agp_info_t __user *info;
+	struct drm_agp_info __user *info;
 	int err;
 
 	info = compat_alloc_user_space(sizeof(*info));
@@ -813,7 +813,7 @@
 {
 	drm_agp_buffer32_t __user *argp = (void __user *)arg;
 	drm_agp_buffer32_t req32;
-	drm_agp_buffer_t __user *request;
+	struct drm_agp_buffer __user *request;
 	int err;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -845,7 +845,7 @@
 			       unsigned long arg)
 {
 	drm_agp_buffer32_t __user *argp = (void __user *)arg;
-	drm_agp_buffer_t __user *request;
+	struct drm_agp_buffer __user *request;
 	u32 handle;
 
 	request = compat_alloc_user_space(sizeof(*request));
@@ -868,7 +868,7 @@
 {
 	drm_agp_binding32_t __user *argp = (void __user *)arg;
 	drm_agp_binding32_t req32;
-	drm_agp_binding_t __user *request;
+	struct drm_agp_binding __user *request;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
 		return -EFAULT;
@@ -887,7 +887,7 @@
 				 unsigned long arg)
 {
 	drm_agp_binding32_t __user *argp = (void __user *)arg;
-	drm_agp_binding_t __user *request;
+	struct drm_agp_binding __user *request;
 	u32 handle;
 
 	request = compat_alloc_user_space(sizeof(*request));
@@ -910,7 +910,7 @@
 			       unsigned long arg)
 {
 	drm_scatter_gather32_t __user *argp = (void __user *)arg;
-	drm_scatter_gather_t __user *request;
+	struct drm_scatter_gather __user *request;
 	int err;
 	unsigned long x;
 
@@ -938,7 +938,7 @@
 			      unsigned long arg)
 {
 	drm_scatter_gather32_t __user *argp = (void __user *)arg;
-	drm_scatter_gather_t __user *request;
+	struct drm_scatter_gather __user *request;
 	unsigned long x;
 
 	request = compat_alloc_user_space(sizeof(*request));
@@ -953,13 +953,13 @@
 }
 
 struct drm_wait_vblank_request32 {
-	drm_vblank_seq_type_t type;
+	enum drm_vblank_seq_type type;
 	unsigned int sequence;
 	u32 signal;
 };
 
 struct drm_wait_vblank_reply32 {
-	drm_vblank_seq_type_t type;
+	enum drm_vblank_seq_type type;
 	unsigned int sequence;
 	s32 tval_sec;
 	s32 tval_usec;
@@ -975,7 +975,7 @@
 {
 	drm_wait_vblank32_t __user *argp = (void __user *)arg;
 	drm_wait_vblank32_t req32;
-	drm_wait_vblank_t __user *request;
+	union drm_wait_vblank __user *request;
 	int err;
 
 	if (copy_from_user(&req32, argp, sizeof(req32)))
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 5658955..b195e10 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -52,10 +52,10 @@
 int drm_getunique(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_unique_t __user *argp = (void __user *)arg;
-	drm_unique_t u;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_unique __user *argp = (void __user *)arg;
+	struct drm_unique u;
 
 	if (copy_from_user(&u, argp, sizeof(u)))
 		return -EFAULT;
@@ -86,15 +86,15 @@
 int drm_setunique(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_unique_t u;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_unique u;
 	int domain, bus, slot, func, ret;
 
 	if (dev->unique_len || dev->unique)
 		return -EBUSY;
 
-	if (copy_from_user(&u, (drm_unique_t __user *) arg, sizeof(u)))
+	if (copy_from_user(&u, (struct drm_unique __user *) arg, sizeof(u)))
 		return -EFAULT;
 
 	if (!u.unique_len || u.unique_len > 1024)
@@ -136,7 +136,7 @@
 	return 0;
 }
 
-static int drm_set_busid(drm_device_t * dev)
+static int drm_set_busid(struct drm_device * dev)
 {
 	int len;
 
@@ -184,11 +184,11 @@
 int drm_getmap(struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_map_t __user *argp = (void __user *)arg;
-	drm_map_t map;
-	drm_map_list_t *r_list = NULL;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map __user *argp = (void __user *)arg;
+	struct drm_map map;
+	struct drm_map_list *r_list = NULL;
 	struct list_head *list;
 	int idx;
 	int i;
@@ -204,9 +204,9 @@
 	}
 
 	i = 0;
-	list_for_each(list, &dev->maplist->head) {
+	list_for_each(list, &dev->maplist) {
 		if (i == idx) {
-			r_list = list_entry(list, drm_map_list_t, head);
+			r_list = list_entry(list, struct drm_map_list, head);
 			break;
 		}
 		i++;
@@ -245,11 +245,11 @@
 int drm_getclient(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_client_t __user *argp = (drm_client_t __user *)arg;
-	drm_client_t client;
-	drm_file_t *pt;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_client __user *argp = (struct drm_client __user *)arg;
+	struct drm_client client;
+	struct drm_file *pt;
 	int idx;
 	int i;
 
@@ -257,12 +257,18 @@
 		return -EFAULT;
 	idx = client.idx;
 	mutex_lock(&dev->struct_mutex);
-	for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
-
-	if (!pt) {
+	
+	if (list_empty(&dev->filelist)) {
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
+
+	i = 0;
+	list_for_each_entry(pt, &dev->filelist, lhead) {
+		if (i++ >= idx)
+			break;
+	}
+
 	client.auth = pt->authenticated;
 	client.pid = pt->pid;
 	client.uid = pt->uid;
@@ -288,9 +294,9 @@
 int drm_getstats(struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_stats_t stats;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_stats stats;
 	int i;
 
 	memset(&stats, 0, sizeof(stats));
@@ -310,7 +316,7 @@
 
 	mutex_unlock(&dev->struct_mutex);
 
-	if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
+	if (copy_to_user((struct drm_stats __user *) arg, &stats, sizeof(stats)))
 		return -EFAULT;
 	return 0;
 }
@@ -329,10 +335,10 @@
 int drm_setversion(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_set_version_t sv;
-	drm_set_version_t retv;
+	struct drm_set_version sv;
+	struct drm_set_version retv;
 	int if_version;
-	drm_set_version_t __user *argp = (void __user *)data;
+	struct drm_set_version __user *argp = (void __user *)data;
 	int ret;
 
 	if (copy_from_user(&sv, argp, sizeof(sv)))
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 2e75331..871d2fd 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -53,10 +53,10 @@
 int drm_irq_by_busid(struct inode *inode, struct file *filp,
 		     unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_irq_busid_t __user *argp = (void __user *)arg;
-	drm_irq_busid_t p;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_irq_busid __user *argp = (void __user *)arg;
+	struct drm_irq_busid p;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
@@ -87,7 +87,7 @@
  * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
  * before and after the installation.
  */
-static int drm_irq_install(drm_device_t * dev)
+static int drm_irq_install(struct drm_device * dev)
 {
 	int ret;
 	unsigned long sh_flags = 0;
@@ -120,8 +120,8 @@
 
 		spin_lock_init(&dev->vbl_lock);
 
-		INIT_LIST_HEAD(&dev->vbl_sigs.head);
-		INIT_LIST_HEAD(&dev->vbl_sigs2.head);
+		INIT_LIST_HEAD(&dev->vbl_sigs);
+		INIT_LIST_HEAD(&dev->vbl_sigs2);
 
 		dev->vbl_pending = 0;
 	}
@@ -155,7 +155,7 @@
  *
  * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
  */
-int drm_irq_uninstall(drm_device_t * dev)
+int drm_irq_uninstall(struct drm_device * dev)
 {
 	int irq_enabled;
 
@@ -197,13 +197,13 @@
 int drm_control(struct inode *inode, struct file *filp,
 		unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_control_t ctl;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_control ctl;
 
 	/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
 
-	if (copy_from_user(&ctl, (drm_control_t __user *) arg, sizeof(ctl)))
+	if (copy_from_user(&ctl, (struct drm_control __user *) arg, sizeof(ctl)))
 		return -EFAULT;
 
 	switch (ctl.func) {
@@ -244,10 +244,10 @@
  */
 int drm_wait_vblank(DRM_IOCTL_ARGS)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_wait_vblank_t __user *argp = (void __user *)data;
-	drm_wait_vblank_t vblwait;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	union drm_wait_vblank __user *argp = (void __user *)data;
+	union drm_wait_vblank vblwait;
 	struct timeval now;
 	int ret = 0;
 	unsigned int flags, seq;
@@ -292,9 +292,9 @@
 
 	if (flags & _DRM_VBLANK_SIGNAL) {
 		unsigned long irqflags;
-		drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+		struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
 				      ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-		drm_vbl_sig_t *vbl_sig;
+		struct drm_vbl_sig *vbl_sig;
 
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
 
@@ -302,7 +302,7 @@
 		 * for the same vblank sequence number; nothing to be done in
 		 * that case
 		 */
-		list_for_each_entry(vbl_sig, &vbl_sigs->head, head) {
+		list_for_each_entry(vbl_sig, vbl_sigs, head) {
 			if (vbl_sig->sequence == vblwait.request.sequence
 			    && vbl_sig->info.si_signo == vblwait.request.signal
 			    && vbl_sig->task == current) {
@@ -324,7 +324,7 @@
 
 		if (!
 		    (vbl_sig =
-		     drm_alloc(sizeof(drm_vbl_sig_t), DRM_MEM_DRIVER))) {
+		     drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
 			return -ENOMEM;
 		}
 
@@ -336,7 +336,7 @@
 
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
 
-		list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head);
+		list_add_tail(&vbl_sig->head, vbl_sigs);
 
 		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
@@ -371,7 +371,7 @@
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-void drm_vbl_send_signals(drm_device_t * dev)
+void drm_vbl_send_signals(struct drm_device * dev)
 {
 	unsigned long flags;
 	int i;
@@ -379,20 +379,18 @@
 	spin_lock_irqsave(&dev->vbl_lock, flags);
 
 	for (i = 0; i < 2; i++) {
-		struct list_head *list, *tmp;
-		drm_vbl_sig_t *vbl_sig;
-		drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+		struct drm_vbl_sig *vbl_sig, *tmp;
+		struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
 		unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
 						   &dev->vbl_received);
 
-		list_for_each_safe(list, tmp, &vbl_sigs->head) {
-			vbl_sig = list_entry(list, drm_vbl_sig_t, head);
+		list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
 			if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
 				vbl_sig->info.si_code = vbl_seq;
 				send_sig_info(vbl_sig->info.si_signo,
 					      &vbl_sig->info, vbl_sig->task);
 
-				list_del(list);
+				list_del(&vbl_sig->head);
 
 				drm_free(vbl_sig, sizeof(*vbl_sig),
 					 DRM_MEM_DRIVER);
@@ -418,7 +416,7 @@
  */
 static void drm_locked_tasklet_func(unsigned long data)
 {
-	drm_device_t *dev = (drm_device_t*)data;
+	struct drm_device *dev = (struct drm_device *)data;
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev->tasklet_lock, irqflags);
@@ -455,7 +453,7 @@
  * context, it must not make any assumptions about this. Also, the HW lock will
  * be held with the kernel context or any client context.
  */
-void drm_locked_tasklet(drm_device_t *dev, void (*func)(drm_device_t*))
+void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device *))
 {
 	unsigned long irqflags;
 	static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index befd1af..c0534b5 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -51,15 +51,15 @@
 int drm_lock(struct inode *inode, struct file *filp,
 	     unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	DECLARE_WAITQUEUE(entry, current);
-	drm_lock_t lock;
+	struct drm_lock lock;
 	int ret = 0;
 
 	++priv->lock_count;
 
-	if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
+	if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock)))
 		return -EFAULT;
 
 	if (lock.context == DRM_KERNEL_CONTEXT) {
@@ -152,12 +152,12 @@
 int drm_unlock(struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_lock_t lock;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_lock lock;
 	unsigned long irqflags;
 
-	if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
+	if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock)))
 		return -EFAULT;
 
 	if (lock.context == DRM_KERNEL_CONTEXT) {
@@ -202,7 +202,7 @@
  *
  * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
  */
-int drm_lock_take(drm_lock_data_t *lock_data,
+int drm_lock_take(struct drm_lock_data *lock_data,
 		  unsigned int context)
 {
 	unsigned int old, new, prev;
@@ -251,7 +251,7 @@
  * Resets the lock file pointer.
  * Marks the lock as held by the given context, via the \p cmpxchg instruction.
  */
-static int drm_lock_transfer(drm_lock_data_t *lock_data,
+static int drm_lock_transfer(struct drm_lock_data *lock_data,
 			     unsigned int context)
 {
 	unsigned int old, new, prev;
@@ -277,7 +277,7 @@
  * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
  * waiting on the lock queue.
  */
-int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context)
+int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
 {
 	unsigned int old, new, prev;
 	volatile unsigned int *lock = &lock_data->hw_lock->lock;
@@ -319,7 +319,7 @@
  */
 static int drm_notifier(void *priv)
 {
-	drm_sigdata_t *s = (drm_sigdata_t *) priv;
+	struct drm_sigdata *s = (struct drm_sigdata *) priv;
 	unsigned int old, new, prev;
 
 	/* Allow signal delivery if lock isn't held */
@@ -350,7 +350,7 @@
  * having to worry about starvation.
  */
 
-void drm_idlelock_take(drm_lock_data_t *lock_data)
+void drm_idlelock_take(struct drm_lock_data *lock_data)
 {
 	int ret = 0;
 
@@ -369,7 +369,7 @@
 }
 EXPORT_SYMBOL(drm_idlelock_take);
 
-void drm_idlelock_release(drm_lock_data_t *lock_data)
+void drm_idlelock_release(struct drm_lock_data *lock_data)
 {
 	unsigned int old, prev;
 	volatile unsigned int *lock = &lock_data->hw_lock->lock;
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 92a8670..9301990 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -80,7 +80,7 @@
 
 #if __OS_HAS_AGP
 static void *agp_remap(unsigned long offset, unsigned long size,
-		       drm_device_t * dev)
+		       struct drm_device * dev)
 {
 	unsigned long *phys_addr_map, i, num_pages =
 	    PAGE_ALIGN(size) / PAGE_SIZE;
@@ -94,7 +94,7 @@
 	offset -= dev->hose->mem_space->start;
 #endif
 
-	for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+	list_for_each_entry(agpmem, &dev->agp->memory, head)
 		if (agpmem->bound <= offset
 		    && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
 		    (offset + size))
@@ -123,7 +123,7 @@
 }
 
 /** Wrapper around agp_allocate_memory() */
-DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(struct drm_device * dev, int pages, u32 type)
 {
 	return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
 }
@@ -148,7 +148,7 @@
 
 #else  /*  __OS_HAS_AGP  */
 static inline void *agp_remap(unsigned long offset, unsigned long size,
-			      drm_device_t * dev)
+			      struct drm_device * dev)
 {
 	return NULL;
 }
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c
index 2ec1d9f..3e6bc14 100644
--- a/drivers/char/drm/drm_mm.c
+++ b/drivers/char/drm/drm_mm.c
@@ -44,26 +44,26 @@
 #include "drmP.h"
 #include <linux/slab.h>
 
-unsigned long drm_mm_tail_space(drm_mm_t *mm)
+unsigned long drm_mm_tail_space(struct drm_mm *mm)
 {
 	struct list_head *tail_node;
-	drm_mm_node_t *entry;
+	struct drm_mm_node *entry;
 
 	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
 	if (!entry->free)
 		return 0;
 
 	return entry->size;
 }
 
-int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size)
+int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
 {
 	struct list_head *tail_node;
-	drm_mm_node_t *entry;
+	struct drm_mm_node *entry;
 
 	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
 	if (!entry->free)
 		return -ENOMEM;
 
@@ -75,13 +75,13 @@
 }
 
 
-static int drm_mm_create_tail_node(drm_mm_t *mm,
+static int drm_mm_create_tail_node(struct drm_mm *mm,
 			    unsigned long start,
 			    unsigned long size)
 {
-	drm_mm_node_t *child;
+	struct drm_mm_node *child;
 
-	child = (drm_mm_node_t *)
+	child = (struct drm_mm_node *)
 		drm_alloc(sizeof(*child), DRM_MEM_MM);
 	if (!child)
 		return -ENOMEM;
@@ -98,13 +98,13 @@
 }
 
 
-int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size)
+int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
 {
 	struct list_head *tail_node;
-	drm_mm_node_t *entry;
+	struct drm_mm_node *entry;
 
 	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
 	if (!entry->free) {
 		return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
 	}
@@ -112,12 +112,12 @@
 	return 0;
 }
 
-static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent,
+static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
 					    unsigned long size)
 {
-	drm_mm_node_t *child;
+	struct drm_mm_node *child;
 
-	child = (drm_mm_node_t *)
+	child = (struct drm_mm_node *)
 		drm_alloc(sizeof(*child), DRM_MEM_MM);
 	if (!child)
 		return NULL;
@@ -139,12 +139,12 @@
 
 
 
-drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
 				unsigned long size, unsigned alignment)
 {
 
-	drm_mm_node_t *align_splitoff = NULL;
-	drm_mm_node_t *child;
+	struct drm_mm_node *align_splitoff = NULL;
+	struct drm_mm_node *child;
 	unsigned tmp = 0;
 
 	if (alignment)
@@ -175,26 +175,26 @@
  * Otherwise add to the free stack.
  */
 
-void drm_mm_put_block(drm_mm_node_t * cur)
+void drm_mm_put_block(struct drm_mm_node * cur)
 {
 
-	drm_mm_t *mm = cur->mm;
+	struct drm_mm *mm = cur->mm;
 	struct list_head *cur_head = &cur->ml_entry;
 	struct list_head *root_head = &mm->ml_entry;
-	drm_mm_node_t *prev_node = NULL;
-	drm_mm_node_t *next_node;
+	struct drm_mm_node *prev_node = NULL;
+	struct drm_mm_node *next_node;
 
 	int merged = 0;
 
 	if (cur_head->prev != root_head) {
-		prev_node = list_entry(cur_head->prev, drm_mm_node_t, ml_entry);
+		prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
 		if (prev_node->free) {
 			prev_node->size += cur->size;
 			merged = 1;
 		}
 	}
 	if (cur_head->next != root_head) {
-		next_node = list_entry(cur_head->next, drm_mm_node_t, ml_entry);
+		next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry);
 		if (next_node->free) {
 			if (merged) {
 				prev_node->size += next_node->size;
@@ -218,14 +218,14 @@
 	}
 }
 
-drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
+struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
 				  unsigned long size,
 				  unsigned alignment, int best_match)
 {
 	struct list_head *list;
 	const struct list_head *free_stack = &mm->fl_entry;
-	drm_mm_node_t *entry;
-	drm_mm_node_t *best;
+	struct drm_mm_node *entry;
+	struct drm_mm_node *best;
 	unsigned long best_size;
 	unsigned wasted;
 
@@ -233,7 +233,7 @@
 	best_size = ~0UL;
 
 	list_for_each(list, free_stack) {
-		entry = list_entry(list, drm_mm_node_t, fl_entry);
+		entry = list_entry(list, struct drm_mm_node, fl_entry);
 		wasted = 0;
 
 		if (entry->size < size)
@@ -259,14 +259,14 @@
 	return best;
 }
 
-int drm_mm_clean(drm_mm_t * mm)
+int drm_mm_clean(struct drm_mm * mm)
 {
 	struct list_head *head = &mm->ml_entry;
 
 	return (head->next->next == head);
 }
 
-int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
+int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
 	INIT_LIST_HEAD(&mm->ml_entry);
 	INIT_LIST_HEAD(&mm->fl_entry);
@@ -275,12 +275,12 @@
 }
 
 
-void drm_mm_takedown(drm_mm_t * mm)
+void drm_mm_takedown(struct drm_mm * mm)
 {
 	struct list_head *bnode = mm->fl_entry.next;
-	drm_mm_node_t *entry;
+	struct drm_mm_node *entry;
 
-	entry = list_entry(bnode, drm_mm_node_t, fl_entry);
+	entry = list_entry(bnode, struct drm_mm_node, fl_entry);
 
 	if (entry->ml_entry.next != &mm->ml_entry ||
 	    entry->fl_entry.next != &mm->fl_entry) {
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 0fe7b44..0b8d343 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -34,8 +34,8 @@
 /** Read/write memory barrier */
 #define DRM_MEMORYBARRIER()		mb()
 /** DRM device local declaration */
-#define DRM_DEVICE	drm_file_t	*priv	= filp->private_data; \
-			drm_device_t	*dev	= priv->head->dev
+#define DRM_DEVICE	struct drm_file	*priv	= filp->private_data; \
+			struct drm_device *dev	= priv->head->dev
 
 /** IRQ handler arguments and return type and values */
 #define DRM_IRQ_ARGS		int irq, void *arg
@@ -96,24 +96,6 @@
 
 #define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
 
-/**
- * Get the pointer to the SAREA.
- *
- * Searches the SAREA on the mapping lists and points drm_device::sarea to it.
- */
-#define DRM_GETSAREA()							 \
-do { 									 \
-	drm_map_list_t *entry;						 \
-	list_for_each_entry( entry, &dev->maplist->head, head ) {	 \
-		if ( entry->map &&					 \
-		     entry->map->type == _DRM_SHM &&			 \
-		     (entry->map->flags & _DRM_CONTAINS_LOCK) ) {	 \
-			dev_priv->sarea = entry->map;			 \
- 			break;						 \
- 		}							 \
- 	}								 \
-} while (0)
-
 #define DRM_HZ HZ
 
 #define DRM_WAIT_ON( ret, queue, timeout, condition )		\
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 86a0f1c..e292bb0 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -47,7 +47,7 @@
 /**
  * \brief Allocate a PCI consistent memory block, for DMA.
  */
-drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
 				dma_addr_t maxaddr)
 {
 	drm_dma_handle_t *dmah;
@@ -126,7 +126,7 @@
  *
  * This function is for internal use in the Linux-specific DRM core code.
  */
-void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
+void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 {
 #if 1
 	unsigned long addr;
@@ -172,7 +172,7 @@
 /**
  * \brief Free a PCI consistent memory block
  */
-void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
+void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 {
 	__drm_pci_free(dev, dmah);
 	kfree(dmah);
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 31cdde8..30b200b 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -102,13 +102,20 @@
 	{0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
 	{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+	{0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
 	{0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5974, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
 	{0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+	{0x1002, 0x5a41, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5a42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5a61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5a62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
 	{0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
@@ -212,6 +219,8 @@
 	{0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
 	{0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x18CA, 0x0040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
+	{0x18CA, 0x0042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
 	{0, 0, 0}
 
 #define tdfx_PCI_IDS \
@@ -293,10 +302,15 @@
 	{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x27ae, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x29b2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x29c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x29d2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0, 0, 0}
 
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index b204498..12dfea8 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -87,7 +87,7 @@
  * "/proc/dri/%minor%/", and each entry in proc_list as
  * "/proc/dri/%minor%/%name%".
  */
-int drm_proc_init(drm_device_t * dev, int minor,
+int drm_proc_init(struct drm_device * dev, int minor,
 		  struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
 {
 	struct proc_dir_entry *ent;
@@ -163,7 +163,7 @@
 static int drm_name_info(char *buf, char **start, off_t offset, int request,
 			 int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
 
 	if (offset > DRM_PROC_LIMIT) {
@@ -205,11 +205,10 @@
 static int drm__vm_info(char *buf, char **start, off_t offset, int request,
 			int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
-	drm_map_t *map;
-	drm_map_list_t *r_list;
-	struct list_head *list;
+	struct drm_map *map;
+	struct drm_map_list *r_list;
 
 	/* Hardcoded from _DRM_FRAME_BUFFER,
 	   _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
@@ -229,9 +228,7 @@
 	DRM_PROC_PRINT("slot	 offset	      size type flags	 "
 		       "address mtrr\n\n");
 	i = 0;
-	if (dev->maplist != NULL)
-		list_for_each(list, &dev->maplist->head) {
-		r_list = list_entry(list, drm_map_list_t, head);
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		map = r_list->map;
 		if (!map)
 			continue;
@@ -242,14 +239,15 @@
 		DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08x ",
 			       i,
 			       map->offset,
-			       map->size, type, map->flags, r_list->user_token);
+			       map->size, type, map->flags,
+			       r_list->user_token);
 		if (map->mtrr < 0) {
 			DRM_PROC_PRINT("none\n");
 		} else {
 			DRM_PROC_PRINT("%4d\n", map->mtrr);
 		}
 		i++;
-		}
+	}
 
 	if (len > request + offset)
 		return request;
@@ -263,7 +261,7 @@
 static int drm_vm_info(char *buf, char **start, off_t offset, int request,
 		       int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
@@ -286,10 +284,10 @@
 static int drm__queues_info(char *buf, char **start, off_t offset,
 			    int request, int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
 	int i;
-	drm_queue_t *q;
+	struct drm_queue *q;
 
 	if (offset > DRM_PROC_LIMIT) {
 		*eof = 1;
@@ -336,7 +334,7 @@
 static int drm_queues_info(char *buf, char **start, off_t offset, int request,
 			   int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
@@ -359,9 +357,9 @@
 static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
 			  int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	if (!dma || offset > DRM_PROC_LIMIT) {
@@ -408,7 +406,7 @@
 static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
 			 int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
@@ -431,9 +429,9 @@
 static int drm__clients_info(char *buf, char **start, off_t offset,
 			     int request, int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
-	drm_file_t *priv;
+	struct drm_file *priv;
 
 	if (offset > DRM_PROC_LIMIT) {
 		*eof = 1;
@@ -444,7 +442,7 @@
 	*eof = 0;
 
 	DRM_PROC_PRINT("a dev	pid    uid	magic	  ioctls\n\n");
-	for (priv = dev->file_first; priv; priv = priv->next) {
+	list_for_each_entry(priv, &dev->filelist, lhead) {
 		DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
 			       priv->authenticated ? 'y' : 'n',
 			       priv->minor,
@@ -464,7 +462,7 @@
 static int drm_clients_info(char *buf, char **start, off_t offset,
 			    int request, int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
@@ -478,9 +476,9 @@
 static int drm__vma_info(char *buf, char **start, off_t offset, int request,
 			 int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int len = 0;
-	drm_vma_entry_t *pt;
+	struct drm_vma_entry *pt;
 	struct vm_area_struct *vma;
 #if defined(__i386__)
 	unsigned int pgprot;
@@ -497,7 +495,7 @@
 	DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
 		       atomic_read(&dev->vma_count),
 		       high_memory, virt_to_phys(high_memory));
-	for (pt = dev->vmalist; pt; pt = pt->next) {
+	list_for_each_entry(pt, &dev->vmalist, head) {
 		if (!(vma = pt->vma))
 			continue;
 		DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
@@ -537,7 +535,7 @@
 static int drm_vma_info(char *buf, char **start, off_t offset, int request,
 			int *eof, void *data)
 {
-	drm_device_t *dev = (drm_device_t *) data;
+	struct drm_device *dev = (struct drm_device *) data;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
diff --git a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
index e94297b..f546696 100644
--- a/drivers/char/drm/drm_sarea.h
+++ b/drivers/char/drm/drm_sarea.h
@@ -50,29 +50,35 @@
 #define SAREA_DRAWABLE_CLAIMED_ENTRY    0x80000000
 
 /** SAREA drawable */
-typedef struct drm_sarea_drawable {
+struct drm_sarea_drawable {
 	unsigned int stamp;
 	unsigned int flags;
-} drm_sarea_drawable_t;
+};
 
 /** SAREA frame */
-typedef struct drm_sarea_frame {
+struct drm_sarea_frame {
 	unsigned int x;
 	unsigned int y;
 	unsigned int width;
 	unsigned int height;
 	unsigned int fullscreen;
-} drm_sarea_frame_t;
+};
 
 /** SAREA */
-typedef struct drm_sarea {
+struct drm_sarea {
     /** first thing is always the DRM locking structure */
-	drm_hw_lock_t lock;
+	struct drm_hw_lock lock;
     /** \todo Use readers/writer lock for drm_sarea::drawable_lock */
-	drm_hw_lock_t drawable_lock;
-	drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES];	/**< drawables */
-	drm_sarea_frame_t frame;	/**< frame */
+	struct drm_hw_lock drawable_lock;
+	struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES];	/**< drawables */
+	struct drm_sarea_frame frame;	/**< frame */
 	drm_context_t dummy_context;
-} drm_sarea_t;
+};
+
+#ifndef __KERNEL__
+typedef struct drm_sarea_drawable drm_sarea_drawable_t;
+typedef struct drm_sarea_frame drm_sarea_frame_t;
+typedef struct drm_sarea drm_sarea_t;
+#endif
 
 #endif				/* _DRM_SAREA_H_ */
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
index 06ef7dd..067d25d 100644
--- a/drivers/char/drm/drm_scatter.c
+++ b/drivers/char/drm/drm_scatter.c
@@ -36,7 +36,7 @@
 
 #define DEBUG_SCATTER 0
 
-void drm_sg_cleanup(drm_sg_mem_t * entry)
+void drm_sg_cleanup(struct drm_sg_mem * entry)
 {
 	struct page *page;
 	int i;
@@ -65,11 +65,11 @@
 int drm_sg_alloc(struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_scatter_gather_t __user *argp = (void __user *)arg;
-	drm_scatter_gather_t request;
-	drm_sg_mem_t *entry;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_scatter_gather __user *argp = (void __user *)arg;
+	struct drm_scatter_gather request;
+	struct drm_sg_mem *entry;
 	unsigned long pages, i, j;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -201,16 +201,16 @@
 int drm_sg_free(struct inode *inode, struct file *filp,
 		unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_scatter_gather_t request;
-	drm_sg_mem_t *entry;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_scatter_gather request;
+	struct drm_sg_mem *entry;
 
 	if (!drm_core_check_feature(dev, DRIVER_SG))
 		return -EINVAL;
 
 	if (copy_from_user(&request,
-			   (drm_scatter_gather_t __user *) arg,
+			   (struct drm_scatter_gather __user *) arg,
 			   sizeof(request)))
 		return -EFAULT;
 
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c
index e15db6d..8421a93 100644
--- a/drivers/char/drm/drm_sman.c
+++ b/drivers/char/drm/drm_sman.c
@@ -38,13 +38,13 @@
 
 #include "drm_sman.h"
 
-typedef struct drm_owner_item {
-	drm_hash_item_t owner_hash;
+struct drm_owner_item {
+	struct drm_hash_item owner_hash;
 	struct list_head sman_list;
 	struct list_head mem_blocks;
-} drm_owner_item_t;
+};
 
-void drm_sman_takedown(drm_sman_t * sman)
+void drm_sman_takedown(struct drm_sman * sman)
 {
 	drm_ht_remove(&sman->user_hash_tab);
 	drm_ht_remove(&sman->owner_hash_tab);
@@ -56,12 +56,12 @@
 EXPORT_SYMBOL(drm_sman_takedown);
 
 int
-drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
 	      unsigned int user_order, unsigned int owner_order)
 {
 	int ret = 0;
 
-	sman->mm = (drm_sman_mm_t *) drm_calloc(num_managers, sizeof(*sman->mm),
+	sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers, sizeof(*sman->mm),
 						DRM_MEM_MM);
 	if (!sman->mm) {
 		ret = -ENOMEM;
@@ -88,8 +88,8 @@
 static void *drm_sman_mm_allocate(void *private, unsigned long size,
 				  unsigned alignment)
 {
-	drm_mm_t *mm = (drm_mm_t *) private;
-	drm_mm_node_t *tmp;
+	struct drm_mm *mm = (struct drm_mm *) private;
+	struct drm_mm_node *tmp;
 
 	tmp = drm_mm_search_free(mm, size, alignment, 1);
 	if (!tmp) {
@@ -101,30 +101,30 @@
 
 static void drm_sman_mm_free(void *private, void *ref)
 {
-	drm_mm_node_t *node = (drm_mm_node_t *) ref;
+	struct drm_mm_node *node = (struct drm_mm_node *) ref;
 
 	drm_mm_put_block(node);
 }
 
 static void drm_sman_mm_destroy(void *private)
 {
-	drm_mm_t *mm = (drm_mm_t *) private;
+	struct drm_mm *mm = (struct drm_mm *) private;
 	drm_mm_takedown(mm);
 	drm_free(mm, sizeof(*mm), DRM_MEM_MM);
 }
 
 static unsigned long drm_sman_mm_offset(void *private, void *ref)
 {
-	drm_mm_node_t *node = (drm_mm_node_t *) ref;
+	struct drm_mm_node *node = (struct drm_mm_node *) ref;
 	return node->start;
 }
 
 int
-drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
 		   unsigned long start, unsigned long size)
 {
-	drm_sman_mm_t *sman_mm;
-	drm_mm_t *mm;
+	struct drm_sman_mm *sman_mm;
+	struct drm_mm *mm;
 	int ret;
 
 	BUG_ON(manager >= sman->num_managers);
@@ -153,8 +153,8 @@
 EXPORT_SYMBOL(drm_sman_set_range);
 
 int
-drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
-		     drm_sman_mm_t * allocator)
+drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
+		     struct drm_sman_mm * allocator)
 {
 	BUG_ON(manager >= sman->num_managers);
 	sman->mm[manager] = *allocator;
@@ -163,16 +163,16 @@
 }
 EXPORT_SYMBOL(drm_sman_set_manager);
 
-static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman,
+static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
 						 unsigned long owner)
 {
 	int ret;
-	drm_hash_item_t *owner_hash_item;
-	drm_owner_item_t *owner_item;
+	struct drm_hash_item *owner_hash_item;
+	struct drm_owner_item *owner_item;
 
 	ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
 	if (!ret) {
-		return drm_hash_entry(owner_hash_item, drm_owner_item_t,
+		return drm_hash_entry(owner_hash_item, struct drm_owner_item,
 				      owner_hash);
 	}
 
@@ -194,14 +194,14 @@
 	return NULL;
 }
 
-drm_memblock_item_t *drm_sman_alloc(drm_sman_t *sman, unsigned int manager,
+struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
 				    unsigned long size, unsigned alignment,
 				    unsigned long owner)
 {
 	void *tmp;
-	drm_sman_mm_t *sman_mm;
-	drm_owner_item_t *owner_item;
-	drm_memblock_item_t *memblock;
+	struct drm_sman_mm *sman_mm;
+	struct drm_owner_item *owner_item;
+	struct drm_memblock_item *memblock;
 
 	BUG_ON(manager >= sman->num_managers);
 
@@ -246,9 +246,9 @@
 
 EXPORT_SYMBOL(drm_sman_alloc);
 
-static void drm_sman_free(drm_memblock_item_t *item)
+static void drm_sman_free(struct drm_memblock_item *item)
 {
-	drm_sman_t *sman = item->sman;
+	struct drm_sman *sman = item->sman;
 
 	list_del(&item->owner_list);
 	drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
@@ -256,40 +256,41 @@
 	drm_free(item, sizeof(*item), DRM_MEM_MM);
 }
 
-int drm_sman_free_key(drm_sman_t *sman, unsigned int key)
+int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
 {
-	drm_hash_item_t *hash_item;
-	drm_memblock_item_t *memblock_item;
+	struct drm_hash_item *hash_item;
+	struct drm_memblock_item *memblock_item;
 
 	if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
 		return -EINVAL;
 
-	memblock_item = drm_hash_entry(hash_item, drm_memblock_item_t, user_hash);
+	memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item,
+				       user_hash);
 	drm_sman_free(memblock_item);
 	return 0;
 }
 
 EXPORT_SYMBOL(drm_sman_free_key);
 
-static void drm_sman_remove_owner(drm_sman_t *sman,
-				  drm_owner_item_t *owner_item)
+static void drm_sman_remove_owner(struct drm_sman *sman,
+				  struct drm_owner_item *owner_item)
 {
 	list_del(&owner_item->sman_list);
 	drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
 	drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
 }
 
-int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner)
+int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
 {
 
-	drm_hash_item_t *hash_item;
-	drm_owner_item_t *owner_item;
+	struct drm_hash_item *hash_item;
+	struct drm_owner_item *owner_item;
 
 	if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
 		return -1;
 	}
 
-	owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+	owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
 	if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
 		drm_sman_remove_owner(sman, owner_item);
 		return -1;
@@ -300,10 +301,10 @@
 
 EXPORT_SYMBOL(drm_sman_owner_clean);
 
-static void drm_sman_do_owner_cleanup(drm_sman_t *sman,
-				      drm_owner_item_t *owner_item)
+static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
+				      struct drm_owner_item *owner_item)
 {
-	drm_memblock_item_t *entry, *next;
+	struct drm_memblock_item *entry, *next;
 
 	list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
 				 owner_list) {
@@ -312,28 +313,28 @@
 	drm_sman_remove_owner(sman, owner_item);
 }
 
-void drm_sman_owner_cleanup(drm_sman_t *sman, unsigned long owner)
+void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
 {
 
-	drm_hash_item_t *hash_item;
-	drm_owner_item_t *owner_item;
+	struct drm_hash_item *hash_item;
+	struct drm_owner_item *owner_item;
 
 	if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
 
 		return;
 	}
 
-	owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+	owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
 	drm_sman_do_owner_cleanup(sman, owner_item);
 }
 
 EXPORT_SYMBOL(drm_sman_owner_cleanup);
 
-void drm_sman_cleanup(drm_sman_t *sman)
+void drm_sman_cleanup(struct drm_sman *sman)
 {
-	drm_owner_item_t *entry, *next;
+	struct drm_owner_item *entry, *next;
 	unsigned int i;
-	drm_sman_mm_t *sman_mm;
+	struct drm_sman_mm *sman_mm;
 
 	list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
 		drm_sman_do_owner_cleanup(sman, entry);
diff --git a/drivers/char/drm/drm_sman.h b/drivers/char/drm/drm_sman.h
index ddc732a..39a39fe 100644
--- a/drivers/char/drm/drm_sman.h
+++ b/drivers/char/drm/drm_sman.h
@@ -50,7 +50,7 @@
  * for memory management.
  */
 
-typedef struct drm_sman_mm {
+struct drm_sman_mm {
 	/* private info. If allocated, needs to be destroyed by the destroy
 	   function */
 	void *private;
@@ -74,30 +74,30 @@
 	   "alloc" function */
 
 	unsigned long (*offset) (void *private, void *ref);
-} drm_sman_mm_t;
+};
 
-typedef struct drm_memblock_item {
+struct drm_memblock_item {
 	struct list_head owner_list;
-	drm_hash_item_t user_hash;
+	struct drm_hash_item user_hash;
 	void *mm_info;
-	drm_sman_mm_t *mm;
+	struct drm_sman_mm *mm;
 	struct drm_sman *sman;
-} drm_memblock_item_t;
+};
 
-typedef struct drm_sman {
-	drm_sman_mm_t *mm;
+struct drm_sman {
+	struct drm_sman_mm *mm;
 	int num_managers;
-	drm_open_hash_t owner_hash_tab;
-	drm_open_hash_t user_hash_tab;
+	struct drm_open_hash owner_hash_tab;
+	struct drm_open_hash user_hash_tab;
 	struct list_head owner_items;
-} drm_sman_t;
+};
 
 /*
  * Take down a memory manager. This function should only be called after a
  * successful init and after a call to drm_sman_cleanup.
  */
 
-extern void drm_sman_takedown(drm_sman_t * sman);
+extern void drm_sman_takedown(struct drm_sman * sman);
 
 /*
  * Allocate structures for a manager.
@@ -112,7 +112,7 @@
  *
  */
 
-extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+extern int drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
 			 unsigned int user_order, unsigned int owner_order);
 
 /*
@@ -120,7 +120,7 @@
  * manager unless a customized allogator is used.
  */
 
-extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+extern int drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
 			      unsigned long start, unsigned long size);
 
 /*
@@ -129,23 +129,23 @@
  * so it can be destroyed after this call.
  */
 
-extern int drm_sman_set_manager(drm_sman_t * sman, unsigned int mananger,
-				drm_sman_mm_t * allocator);
+extern int drm_sman_set_manager(struct drm_sman * sman, unsigned int mananger,
+				struct drm_sman_mm * allocator);
 
 /*
  * Allocate a memory block. Aligment is not implemented yet.
  */
 
-extern drm_memblock_item_t *drm_sman_alloc(drm_sman_t * sman,
-					   unsigned int manager,
-					   unsigned long size,
-					   unsigned alignment,
-					   unsigned long owner);
+extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman,
+						unsigned int manager,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long owner);
 /*
  * Free a memory block identified by its user hash key.
  */
 
-extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key);
+extern int drm_sman_free_key(struct drm_sman * sman, unsigned int key);
 
 /*
  * returns 1 iff there are no stale memory blocks associated with this owner.
@@ -154,7 +154,7 @@
  * resources associated with owner.
  */
 
-extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner);
+extern int drm_sman_owner_clean(struct drm_sman * sman, unsigned long owner);
 
 /*
  * Frees all stale memory blocks associated with this owner. Note that this
@@ -164,13 +164,13 @@
  * is not going to be referenced anymore.
  */
 
-extern void drm_sman_owner_cleanup(drm_sman_t * sman, unsigned long owner);
+extern void drm_sman_owner_cleanup(struct drm_sman * sman, unsigned long owner);
 
 /*
  * Frees all stale memory blocks associated with the memory manager.
  * See idling above.
  */
 
-extern void drm_sman_cleanup(drm_sman_t * sman);
+extern void drm_sman_cleanup(struct drm_sman * sman);
 
 #endif
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 19408ad..ee83ff9 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -49,16 +49,21 @@
 module_param_named(cards_limit, drm_cards_limit, int, 0444);
 module_param_named(debug, drm_debug, int, 0600);
 
-drm_head_t **drm_heads;
+struct drm_head **drm_heads;
 struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 
-static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
+static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
 			   const struct pci_device_id *ent,
 			   struct drm_driver *driver)
 {
 	int retcode;
 
+	INIT_LIST_HEAD(&dev->filelist);
+	INIT_LIST_HEAD(&dev->ctxlist);
+	INIT_LIST_HEAD(&dev->vmalist);
+	INIT_LIST_HEAD(&dev->maplist);
+
 	spin_lock_init(&dev->count_lock);
 	spin_lock_init(&dev->drw_lock);
 	spin_lock_init(&dev->tasklet_lock);
@@ -67,6 +72,8 @@
 	mutex_init(&dev->struct_mutex);
 	mutex_init(&dev->ctxlist_mutex);
 
+	idr_init(&dev->drw_idr);
+
 	dev->pdev = pdev;
 	dev->pci_device = pdev->device;
 	dev->pci_vendor = pdev->vendor;
@@ -76,12 +83,7 @@
 #endif
 	dev->irq = pdev->irq;
 
-	dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
-	if (dev->maplist == NULL)
-		return -ENOMEM;
-	INIT_LIST_HEAD(&dev->maplist->head);
 	if (drm_ht_create(&dev->map_hash, 12)) {
-		drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
 		return -ENOMEM;
 	}
 
@@ -143,9 +145,9 @@
  * create the proc init entry via proc_init(). This routines assigns
  * minor numbers to secondary heads of multi-headed cards
  */
-static int drm_get_head(drm_device_t * dev, drm_head_t * head)
+static int drm_get_head(struct drm_device * dev, struct drm_head * head)
 {
-	drm_head_t **heads = drm_heads;
+	struct drm_head **heads = drm_heads;
 	int ret;
 	int minor;
 
@@ -154,7 +156,7 @@
 	for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
 		if (!*heads) {
 
-			*head = (drm_head_t) {
+			*head = (struct drm_head) {
 			.dev = dev,.device =
 				    MKDEV(DRM_MAJOR, minor),.minor = minor,};
 
@@ -184,7 +186,7 @@
       err_g2:
 	drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
       err_g1:
-	*head = (drm_head_t) {
+	*head = (struct drm_head) {
 	.dev = NULL};
 	return ret;
 }
@@ -203,7 +205,7 @@
 int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
 		struct drm_driver *driver)
 {
-	drm_device_t *dev;
+	struct drm_device *dev;
 	int ret;
 
 	DRM_DEBUG("\n");
@@ -246,7 +248,7 @@
  * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
  * unregisters the character device.
  */
-int drm_put_dev(drm_device_t * dev)
+int drm_put_dev(struct drm_device * dev)
 {
 	DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
 
@@ -274,7 +276,7 @@
  * last minor released.
  *
  */
-int drm_put_head(drm_head_t * head)
+int drm_put_head(struct drm_head * head)
 {
 	int minor = head->minor;
 
@@ -283,7 +285,7 @@
 	drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
 	drm_sysfs_device_remove(head->dev_class);
 
-	*head = (drm_head_t) {.dev = NULL};
+	*head = (struct drm_head) {.dev = NULL};
 
 	drm_heads[minor] = NULL;
 
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index cc8e2eb..cf4349b 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -80,7 +80,7 @@
 
 static ssize_t show_dri(struct class_device *class_device, char *buf)
 {
-	drm_device_t * dev = ((drm_head_t *)class_get_devdata(class_device))->dev;
+	struct drm_device * dev = ((struct drm_head *)class_get_devdata(class_device))->dev;
 	if (dev->driver->dri_library_name)
 		return dev->driver->dri_library_name(dev, buf);
 	return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
@@ -104,7 +104,7 @@
  * Note: the struct class passed to this function must have previously been
  * created with a call to drm_sysfs_create().
  */
-struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
+struct class_device *drm_sysfs_device_add(struct class *cs, struct drm_head *head)
 {
 	struct class_device *class_dev;
 	int i, j, err;
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index b5c5b9f..68e36e5 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -79,11 +79,11 @@
 static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
 						unsigned long address)
 {
-	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_map_t *map = NULL;
-	drm_map_list_t *r_list;
-	drm_hash_item_t *hash;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map *map = NULL;
+	struct drm_map_list *r_list;
+	struct drm_hash_item *hash;
 
 	/*
 	 * Find the right map
@@ -97,7 +97,7 @@
 	if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
 		goto vm_nopage_error;
 
-	r_list = drm_hash_entry(hash, drm_map_list_t, hash);
+	r_list = drm_hash_entry(hash, struct drm_map_list, hash);
 	map = r_list->map;
 
 	if (map && map->type == _DRM_AGP) {
@@ -116,7 +116,7 @@
 		/*
 		 * It's AGP memory - find the real physical page to map
 		 */
-		for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
+		list_for_each_entry(agpmem, &dev->agp->memory, head) {
 			if (agpmem->bound <= baddr &&
 			    agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
 				break;
@@ -163,7 +163,7 @@
 static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
 						    unsigned long address)
 {
-	drm_map_t *map = (drm_map_t *) vma->vm_private_data;
+	struct drm_map *map = (struct drm_map *) vma->vm_private_data;
 	unsigned long offset;
 	unsigned long i;
 	struct page *page;
@@ -194,12 +194,11 @@
  */
 static void drm_vm_shm_close(struct vm_area_struct *vma)
 {
-	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_vma_entry_t *pt, *prev, *next;
-	drm_map_t *map;
-	drm_map_list_t *r_list;
-	struct list_head *list;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_vma_entry *pt, *temp;
+	struct drm_map *map;
+	struct drm_map_list *r_list;
 	int found_maps = 0;
 
 	DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -209,30 +208,22 @@
 	map = vma->vm_private_data;
 
 	mutex_lock(&dev->struct_mutex);
-	for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
-		next = pt->next;
+	list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
 		if (pt->vma->vm_private_data == map)
 			found_maps++;
 		if (pt->vma == vma) {
-			if (prev) {
-				prev->next = pt->next;
-			} else {
-				dev->vmalist = pt->next;
-			}
+			list_del(&pt->head);
 			drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
-		} else {
-			prev = pt;
 		}
 	}
+
 	/* We were the only map that was found */
 	if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
 		/* Check to see if we are in the maplist, if we are not, then
 		 * we delete this mappings information.
 		 */
 		found_maps = 0;
-		list = &dev->maplist->head;
-		list_for_each(list, &dev->maplist->head) {
-			r_list = list_entry(list, drm_map_list_t, head);
+		list_for_each_entry(r_list, &dev->maplist, head) {
 			if (r_list->map == map)
 				found_maps++;
 		}
@@ -283,9 +274,9 @@
 static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
 						    unsigned long address)
 {
-	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
 	unsigned long offset;
 	unsigned long page_nr;
 	struct page *page;
@@ -319,10 +310,10 @@
 static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
 						   unsigned long address)
 {
-	drm_map_t *map = (drm_map_t *) vma->vm_private_data;
-	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_sg_mem_t *entry = dev->sg;
+	struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_sg_mem *entry = dev->sg;
 	unsigned long offset;
 	unsigned long map_offset;
 	unsigned long page_offset;
@@ -414,9 +405,9 @@
  */
 static void drm_vm_open_locked(struct vm_area_struct *vma)
 {
-	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_vma_entry_t *vma_entry;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_vma_entry *vma_entry;
 
 	DRM_DEBUG("0x%08lx,0x%08lx\n",
 		  vma->vm_start, vma->vm_end - vma->vm_start);
@@ -425,16 +416,15 @@
 	vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
 	if (vma_entry) {
 		vma_entry->vma = vma;
-		vma_entry->next = dev->vmalist;
 		vma_entry->pid = current->pid;
-		dev->vmalist = vma_entry;
+		list_add(&vma_entry->head, &dev->vmalist);
 	}
 }
 
 static void drm_vm_open(struct vm_area_struct *vma)
 {
-	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	mutex_lock(&dev->struct_mutex);
 	drm_vm_open_locked(vma);
@@ -451,22 +441,18 @@
  */
 static void drm_vm_close(struct vm_area_struct *vma)
 {
-	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_vma_entry_t *pt, *prev;
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_vma_entry *pt, *temp;
 
 	DRM_DEBUG("0x%08lx,0x%08lx\n",
 		  vma->vm_start, vma->vm_end - vma->vm_start);
 	atomic_dec(&dev->vma_count);
 
 	mutex_lock(&dev->struct_mutex);
-	for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+	list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
 		if (pt->vma == vma) {
-			if (prev) {
-				prev->next = pt->next;
-			} else {
-				dev->vmalist = pt->next;
-			}
+			list_del(&pt->head);
 			drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
 			break;
 		}
@@ -486,9 +472,9 @@
  */
 static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev;
-	drm_device_dma_t *dma;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev;
+	struct drm_device_dma *dma;
 	unsigned long length = vma->vm_end - vma->vm_start;
 
 	dev = priv->head->dev;
@@ -526,7 +512,7 @@
 	return 0;
 }
 
-unsigned long drm_core_get_map_ofs(drm_map_t * map)
+unsigned long drm_core_get_map_ofs(struct drm_map * map)
 {
 	return map->offset;
 }
@@ -559,11 +545,11 @@
  */
 static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_map_t *map = NULL;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_map *map = NULL;
 	unsigned long offset = 0;
-	drm_hash_item_t *hash;
+	struct drm_hash_item *hash;
 
 	DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
 		  vma->vm_start, vma->vm_end, vma->vm_pgoff);
@@ -588,7 +574,7 @@
 		return -EINVAL;
 	}
 
-	map = drm_hash_entry(hash, drm_map_list_t, hash)->map;
+	map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
 	if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
 		return -EPERM;
 
@@ -677,8 +663,8 @@
 
 int drm_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 603d17f..cb44999 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -45,16 +45,16 @@
 #define I810_BUF_UNMAPPED 0
 #define I810_BUF_MAPPED   1
 
-static drm_buf_t *i810_freelist_get(drm_device_t * dev)
+static struct drm_buf *i810_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 	int used;
 
 	/* Linear search might not be the best solution */
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 		/* In use is already a pointer */
 		used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
@@ -70,7 +70,7 @@
  * yet, the hardware updates in use for us once its on the ring buffer.
  */
 
-static int i810_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+static int i810_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	int used;
@@ -87,10 +87,10 @@
 
 static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev;
 	drm_i810_private_t *dev_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_i810_buf_priv_t *buf_priv;
 
 	lock_kernel();
@@ -120,10 +120,10 @@
 	.fasync = drm_fasync,
 };
 
-static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
+static int i810_map_buffer(struct drm_buf * buf, struct file *filp)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	const struct file_operations *old_fops;
@@ -152,7 +152,7 @@
 	return retcode;
 }
 
-static int i810_unmap_buffer(drm_buf_t * buf)
+static int i810_unmap_buffer(struct drm_buf * buf)
 {
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	int retcode = 0;
@@ -172,10 +172,10 @@
 	return retcode;
 }
 
-static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
+static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
 			       struct file *filp)
 {
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_i810_buf_priv_t *buf_priv;
 	int retcode = 0;
 
@@ -202,9 +202,9 @@
 	return retcode;
 }
 
-static int i810_dma_cleanup(drm_device_t * dev)
+static int i810_dma_cleanup(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
@@ -233,7 +233,7 @@
 		dev->dev_private = NULL;
 
 		for (i = 0; i < dma->buf_count; i++) {
-			drm_buf_t *buf = dma->buflist[i];
+			struct drm_buf *buf = dma->buflist[i];
 			drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 			if (buf_priv->kernel_virtual && buf->total)
@@ -243,7 +243,7 @@
 	return 0;
 }
 
-static int i810_wait_ring(drm_device_t * dev, int n)
+static int i810_wait_ring(struct drm_device * dev, int n)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -276,7 +276,7 @@
 	return iters;
 }
 
-static void i810_kernel_lost_context(drm_device_t * dev)
+static void i810_kernel_lost_context(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -288,9 +288,9 @@
 		ring->space += ring->Size;
 }
 
-static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
+static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_priv)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int my_idx = 24;
 	u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
 	int i;
@@ -301,7 +301,7 @@
 	}
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 		buf_priv->in_use = hw_status++;
@@ -323,16 +323,14 @@
 	return 0;
 }
 
-static int i810_dma_initialize(drm_device_t * dev,
+static int i810_dma_initialize(struct drm_device * dev,
 			       drm_i810_private_t * dev_priv,
 			       drm_i810_init_t * init)
 {
-	struct list_head *list;
-
+	struct drm_map_list *r_list;
 	memset(dev_priv, 0, sizeof(drm_i810_private_t));
 
-	list_for_each(list, &dev->maplist->head) {
-		drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map &&
 		    r_list->map->type == _DRM_SHM &&
 		    r_list->map->flags & _DRM_CONTAINS_LOCK) {
@@ -478,8 +476,8 @@
 static int i810_dma_init(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv;
 	drm_i810_init_t init;
 	int retcode = 0;
@@ -536,7 +534,7 @@
  * Use 'volatile' & local var tmp to force the emitted values to be
  * identical to the verified ones.
  */
-static void i810EmitContextVerified(drm_device_t * dev,
+static void i810EmitContextVerified(struct drm_device * dev,
 				    volatile unsigned int *code)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -569,7 +567,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i810EmitTexVerified(drm_device_t * dev, volatile unsigned int *code)
+static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
@@ -602,7 +600,7 @@
 
 /* Need to do some additional checking when setting the dest buffer.
  */
-static void i810EmitDestVerified(drm_device_t * dev,
+static void i810EmitDestVerified(struct drm_device * dev,
 				 volatile unsigned int *code)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -637,7 +635,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i810EmitState(drm_device_t * dev)
+static void i810EmitState(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -668,14 +666,14 @@
 
 /* need to verify
  */
-static void i810_dma_dispatch_clear(drm_device_t * dev, int flags,
+static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
 				    unsigned int clear_color,
 				    unsigned int clear_zval)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = 2;
 	int i;
@@ -743,12 +741,12 @@
 	}
 }
 
-static void i810_dma_dispatch_swap(drm_device_t * dev)
+static void i810_dma_dispatch_swap(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = 2;
 	int i;
@@ -789,13 +787,13 @@
 	}
 }
 
-static void i810_dma_dispatch_vertex(drm_device_t * dev,
-				     drm_buf_t * buf, int discard, int used)
+static void i810_dma_dispatch_vertex(struct drm_device * dev,
+				     struct drm_buf * buf, int discard, int used)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_clip_rect_t *box = sarea_priv->boxes;
+	struct drm_clip_rect *box = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	unsigned long address = (unsigned long)buf->bus_address;
 	unsigned long start = address - dev->agp->base;
@@ -869,7 +867,7 @@
 	}
 }
 
-static void i810_dma_dispatch_flip(drm_device_t * dev)
+static void i810_dma_dispatch_flip(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	int pitch = dev_priv->pitch;
@@ -916,7 +914,7 @@
 
 }
 
-static void i810_dma_quiescent(drm_device_t * dev)
+static void i810_dma_quiescent(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -935,10 +933,10 @@
 	i810_wait_ring(dev, dev_priv->ring.Size - 8);
 }
 
-static int i810_flush_queue(drm_device_t * dev)
+static int i810_flush_queue(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i, ret = 0;
 	RING_LOCALS;
 
@@ -954,7 +952,7 @@
 	i810_wait_ring(dev, dev_priv->ring.Size - 8);
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 		int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
@@ -970,9 +968,9 @@
 }
 
 /* Must be called with the lock held */
-static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i810_reclaim_buffers(struct drm_device * dev, struct file *filp)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	if (!dma)
@@ -985,7 +983,7 @@
 	i810_flush_queue(dev);
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
 		if (buf->filp == filp && buf_priv) {
@@ -1003,8 +1001,8 @@
 static int i810_flush_ioctl(struct inode *inode, struct file *filp,
 			    unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
@@ -1015,9 +1013,9 @@
 static int i810_dma_vertex(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 	u32 *hw_status = dev_priv->hw_status_page;
 	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1051,8 +1049,8 @@
 static int i810_clear_bufs(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_clear_t clear;
 
 	if (copy_from_user
@@ -1074,8 +1072,8 @@
 static int i810_swap_bufs(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	DRM_DEBUG("i810_swap_bufs\n");
 
@@ -1088,8 +1086,8 @@
 static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
 		       unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 	u32 *hw_status = dev_priv->hw_status_page;
 	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1102,8 +1100,8 @@
 static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
 		       unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	int retcode = 0;
 	drm_i810_dma_t d;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
@@ -1123,7 +1121,7 @@
 	DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
 		  current->pid, retcode, d.granted);
 
-	if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
+	if (copy_to_user((void __user *) arg, &d, sizeof(d)))
 		return -EFAULT;
 	sarea_priv->last_dispatch = (int)hw_status[5];
 
@@ -1144,7 +1142,7 @@
 	return 0;
 }
 
-static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
+static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,
 				 unsigned int last_render)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1207,9 +1205,9 @@
 static int i810_dma_mc(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 	u32 *hw_status = dev_priv->hw_status_page;
 	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1238,8 +1236,8 @@
 static int i810_rstatus(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
 	return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
@@ -1248,8 +1246,8 @@
 static int i810_ov0_info(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 	drm_i810_overlay_t data;
 
@@ -1264,8 +1262,8 @@
 static int i810_fstatus(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1276,8 +1274,8 @@
 static int i810_ov0_flip(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1290,7 +1288,7 @@
 
 /* Not sure why this isn't set all the time:
  */
-static void i810_do_init_pageflip(drm_device_t * dev)
+static void i810_do_init_pageflip(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
@@ -1300,7 +1298,7 @@
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 
-static int i810_do_cleanup_pageflip(drm_device_t * dev)
+static int i810_do_cleanup_pageflip(struct drm_device * dev)
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
@@ -1315,8 +1313,8 @@
 static int i810_flip_bufs(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1330,7 +1328,7 @@
 	return 0;
 }
 
-int i810_driver_load(drm_device_t *dev, unsigned long flags)
+int i810_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	/* i810 has 4 more counters */
 	dev->counters += 4;
@@ -1342,12 +1340,12 @@
 	return 0;
 }
 
-void i810_driver_lastclose(drm_device_t * dev)
+void i810_driver_lastclose(struct drm_device * dev)
 {
 	i810_dma_cleanup(dev);
 }
 
-void i810_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i810_driver_preclose(struct drm_device * dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1357,12 +1355,12 @@
 	}
 }
 
-void i810_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void i810_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
 {
 	i810_reclaim_buffers(dev, filp);
 }
 
-int i810_driver_dma_quiescent(drm_device_t * dev)
+int i810_driver_dma_quiescent(struct drm_device * dev)
 {
 	i810_dma_quiescent(dev);
 	return 0;
@@ -1399,7 +1397,7 @@
  * \returns
  * A value of 1 is always retured to indictate every i810 is AGP.
  */
-int i810_driver_device_is_agp(drm_device_t * dev)
+int i810_driver_device_is_agp(struct drm_device * dev)
 {
 	return 1;
 }
diff --git a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
index 2deb925..614977d 100644
--- a/drivers/char/drm/i810_drm.h
+++ b/drivers/char/drm/i810_drm.h
@@ -158,7 +158,7 @@
 	unsigned int dirty;
 
 	unsigned int nbox;
-	drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[I810_NR_SAREA_CLIPRECTS];
 
 	/* Maintain an LRU of contiguous regions of texture space.  If
 	 * you think you own a region of texture memory, and it has an
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index e6df49f4..6488338 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -77,8 +77,8 @@
 } drm_i810_ring_buffer_t;
 
 typedef struct drm_i810_private {
-	drm_map_t *sarea_map;
-	drm_map_t *mmio_map;
+	struct drm_map *sarea_map;
+	struct drm_map *mmio_map;
 
 	drm_i810_sarea_t *sarea_priv;
 	drm_i810_ring_buffer_t ring;
@@ -88,7 +88,7 @@
 
 	dma_addr_t dma_status_page;
 
-	drm_buf_t *mmap_buffer;
+	struct drm_buf *mmap_buffer;
 
 	u32 front_di1, back_di1, zi1;
 
@@ -115,15 +115,15 @@
 } drm_i810_private_t;
 
 				/* i810_dma.c */
-extern int i810_driver_dma_quiescent(drm_device_t * dev);
-extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern int i810_driver_dma_quiescent(struct drm_device * dev);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
 					       struct file *filp);
 extern int i810_driver_load(struct drm_device *, unsigned long flags);
-extern void i810_driver_lastclose(drm_device_t * dev);
-extern void i810_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern void i810_driver_lastclose(struct drm_device * dev);
+extern void i810_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
 					       struct file *filp);
-extern int i810_driver_device_is_agp(drm_device_t * dev);
+extern int i810_driver_device_is_agp(struct drm_device * dev);
 
 extern drm_ioctl_desc_t i810_ioctls[];
 extern int i810_max_ioctl;
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 3314a9f..dc20c1a 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -47,16 +47,16 @@
 #define I830_BUF_UNMAPPED 0
 #define I830_BUF_MAPPED   1
 
-static drm_buf_t *i830_freelist_get(drm_device_t * dev)
+static struct drm_buf *i830_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 	int used;
 
 	/* Linear search might not be the best solution */
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 		/* In use is already a pointer */
 		used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
@@ -72,7 +72,7 @@
  * yet, the hardware updates in use for us once its on the ring buffer.
  */
 
-static int i830_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+static int i830_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	int used;
@@ -89,10 +89,10 @@
 
 static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev;
 	drm_i830_private_t *dev_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_i830_buf_priv_t *buf_priv;
 
 	lock_kernel();
@@ -122,10 +122,10 @@
 	.fasync = drm_fasync,
 };
 
-static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
+static int i830_map_buffer(struct drm_buf * buf, struct file *filp)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	const struct file_operations *old_fops;
@@ -156,7 +156,7 @@
 	return retcode;
 }
 
-static int i830_unmap_buffer(drm_buf_t * buf)
+static int i830_unmap_buffer(struct drm_buf * buf)
 {
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	int retcode = 0;
@@ -176,10 +176,10 @@
 	return retcode;
 }
 
-static int i830_dma_get_buffer(drm_device_t * dev, drm_i830_dma_t * d,
+static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
 			       struct file *filp)
 {
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_i830_buf_priv_t *buf_priv;
 	int retcode = 0;
 
@@ -206,9 +206,9 @@
 	return retcode;
 }
 
-static int i830_dma_cleanup(drm_device_t * dev)
+static int i830_dma_cleanup(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
@@ -238,7 +238,7 @@
 		dev->dev_private = NULL;
 
 		for (i = 0; i < dma->buf_count; i++) {
-			drm_buf_t *buf = dma->buflist[i];
+			struct drm_buf *buf = dma->buflist[i];
 			drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 			if (buf_priv->kernel_virtual && buf->total)
 				drm_core_ioremapfree(&buf_priv->map, dev);
@@ -247,7 +247,7 @@
 	return 0;
 }
 
-int i830_wait_ring(drm_device_t * dev, int n, const char *caller)
+int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -281,7 +281,7 @@
 	return iters;
 }
 
-static void i830_kernel_lost_context(drm_device_t * dev)
+static void i830_kernel_lost_context(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -296,9 +296,9 @@
 		dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
 }
 
-static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv)
+static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_priv)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int my_idx = 36;
 	u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
 	int i;
@@ -309,7 +309,7 @@
 	}
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 
 		buf_priv->in_use = hw_status++;
@@ -330,16 +330,15 @@
 	return 0;
 }
 
-static int i830_dma_initialize(drm_device_t * dev,
+static int i830_dma_initialize(struct drm_device * dev,
 			       drm_i830_private_t * dev_priv,
 			       drm_i830_init_t * init)
 {
-	struct list_head *list;
+	struct drm_map_list *r_list;
 
 	memset(dev_priv, 0, sizeof(drm_i830_private_t));
 
-	list_for_each(list, &dev->maplist->head) {
-		drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map &&
 		    r_list->map->type == _DRM_SHM &&
 		    r_list->map->flags & _DRM_CONTAINS_LOCK) {
@@ -455,8 +454,8 @@
 static int i830_dma_init(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv;
 	drm_i830_init_t init;
 	int retcode = 0;
@@ -490,7 +489,7 @@
 /* Most efficient way to verify state for the i830 is as it is
  * emitted.  Non-conformant state is silently dropped.
  */
-static void i830EmitContextVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
@@ -535,7 +534,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitTexVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
@@ -569,7 +568,7 @@
 		printk("rejected packet %x\n", code[0]);
 }
 
-static void i830EmitTexBlendVerified(drm_device_t * dev,
+static void i830EmitTexBlendVerified(struct drm_device * dev,
 				     unsigned int *code, unsigned int num)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -594,7 +593,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitTexPalette(drm_device_t * dev,
+static void i830EmitTexPalette(struct drm_device * dev,
 			       unsigned int *palette, int number, int is_shared)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -621,7 +620,7 @@
 
 /* Need to do some additional checking when setting the dest buffer.
  */
-static void i830EmitDestVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	unsigned int tmp;
@@ -682,7 +681,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitStippleVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -693,7 +692,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitState(drm_device_t * dev)
+static void i830EmitState(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -796,7 +795,7 @@
  * Performance monitoring functions
  */
 
-static void i830_fill_box(drm_device_t * dev,
+static void i830_fill_box(struct drm_device * dev,
 			  int x, int y, int w, int h, int r, int g, int b)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -834,7 +833,7 @@
 	ADVANCE_LP_RING();
 }
 
-static void i830_cp_performance_boxes(drm_device_t * dev)
+static void i830_cp_performance_boxes(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
@@ -879,7 +878,7 @@
 	dev_priv->sarea_priv->perf_boxes = 0;
 }
 
-static void i830_dma_dispatch_clear(drm_device_t * dev, int flags,
+static void i830_dma_dispatch_clear(struct drm_device * dev, int flags,
 				    unsigned int clear_color,
 				    unsigned int clear_zval,
 				    unsigned int clear_depthmask)
@@ -887,7 +886,7 @@
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = dev_priv->cpp;
 	int i;
@@ -974,12 +973,12 @@
 	}
 }
 
-static void i830_dma_dispatch_swap(drm_device_t * dev)
+static void i830_dma_dispatch_swap(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = dev_priv->cpp;
 	int i;
@@ -1044,7 +1043,7 @@
 	}
 }
 
-static void i830_dma_dispatch_flip(drm_device_t * dev)
+static void i830_dma_dispatch_flip(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -1087,13 +1086,13 @@
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 
-static void i830_dma_dispatch_vertex(drm_device_t * dev,
-				     drm_buf_t * buf, int discard, int used)
+static void i830_dma_dispatch_vertex(struct drm_device * dev,
+				     struct drm_buf * buf, int discard, int used)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_clip_rect_t *box = sarea_priv->boxes;
+	struct drm_clip_rect *box = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	unsigned long address = (unsigned long)buf->bus_address;
 	unsigned long start = address - dev->agp->base;
@@ -1199,7 +1198,7 @@
 	}
 }
 
-static void i830_dma_quiescent(drm_device_t * dev)
+static void i830_dma_quiescent(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -1216,10 +1215,10 @@
 	i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
 }
 
-static int i830_flush_queue(drm_device_t * dev)
+static int i830_flush_queue(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i, ret = 0;
 	RING_LOCALS;
 
@@ -1233,7 +1232,7 @@
 	i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 
 		int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
@@ -1249,9 +1248,9 @@
 }
 
 /* Must be called with the lock held */
-static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i830_reclaim_buffers(struct drm_device * dev, struct file *filp)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	if (!dma)
@@ -1264,7 +1263,7 @@
 	i830_flush_queue(dev);
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 
 		if (buf->filp == filp && buf_priv) {
@@ -1282,8 +1281,8 @@
 static int i830_flush_ioctl(struct inode *inode, struct file *filp,
 			    unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
@@ -1294,9 +1293,9 @@
 static int i830_dma_vertex(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
+	struct drm_device_dma *dma = dev->dma;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	u32 *hw_status = dev_priv->hw_status_page;
 	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
@@ -1328,8 +1327,8 @@
 static int i830_clear_bufs(struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_clear_t clear;
 
 	if (copy_from_user
@@ -1352,8 +1351,8 @@
 static int i830_swap_bufs(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 
 	DRM_DEBUG("i830_swap_bufs\n");
 
@@ -1365,7 +1364,7 @@
 
 /* Not sure why this isn't set all the time:
  */
-static void i830_do_init_pageflip(drm_device_t * dev)
+static void i830_do_init_pageflip(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
@@ -1375,7 +1374,7 @@
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 
-static int i830_do_cleanup_pageflip(drm_device_t * dev)
+static int i830_do_cleanup_pageflip(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
@@ -1390,8 +1389,8 @@
 static int i830_flip_bufs(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1408,8 +1407,8 @@
 static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
 		       unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	u32 *hw_status = dev_priv->hw_status_page;
 	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
@@ -1422,8 +1421,8 @@
 static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
 		       unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	int retcode = 0;
 	drm_i830_dma_t d;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
@@ -1444,7 +1443,7 @@
 	DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
 		  current->pid, retcode, d.granted);
 
-	if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
+	if (copy_to_user((void __user *) arg, &d, sizeof(d)))
 		return -EFAULT;
 	sarea_priv->last_dispatch = (int)hw_status[5];
 
@@ -1467,8 +1466,8 @@
 static int i830_getparam(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_getparam_t param;
 	int value;
@@ -1501,8 +1500,8 @@
 static int i830_setparam(struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_setparam_t param;
 
@@ -1526,7 +1525,7 @@
 	return 0;
 }
 
-int i830_driver_load(drm_device_t *dev, unsigned long flags)
+int i830_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	/* i830 has 4 more counters */
 	dev->counters += 4;
@@ -1538,12 +1537,12 @@
 	return 0;
 }
 
-void i830_driver_lastclose(drm_device_t * dev)
+void i830_driver_lastclose(struct drm_device * dev)
 {
 	i830_dma_cleanup(dev);
 }
 
-void i830_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i830_driver_preclose(struct drm_device * dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1553,12 +1552,12 @@
 	}
 }
 
-void i830_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
 {
 	i830_reclaim_buffers(dev, filp);
 }
 
-int i830_driver_dma_quiescent(drm_device_t * dev)
+int i830_driver_dma_quiescent(struct drm_device * dev)
 {
 	i830_dma_quiescent(dev);
 	return 0;
@@ -1594,7 +1593,7 @@
  * \returns
  * A value of 1 is always retured to indictate every i8xx is AGP.
  */
-int i830_driver_device_is_agp(drm_device_t * dev)
+int i830_driver_device_is_agp(struct drm_device * dev)
 {
 	return 1;
 }
diff --git a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h
index 66dd750..968a6d9 100644
--- a/drivers/char/drm/i830_drm.h
+++ b/drivers/char/drm/i830_drm.h
@@ -191,7 +191,7 @@
 	unsigned int dirty;
 
 	unsigned int nbox;
-	drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[I830_NR_SAREA_CLIPRECTS];
 
 	/* Maintain an LRU of contiguous regions of texture space.  If
 	 * you think you own a region of texture memory, and it has an
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index e91f94a..ddda679 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -84,8 +84,8 @@
 } drm_i830_ring_buffer_t;
 
 typedef struct drm_i830_private {
-	drm_map_t *sarea_map;
-	drm_map_t *mmio_map;
+	struct drm_map *sarea_map;
+	struct drm_map *mmio_map;
 
 	drm_i830_sarea_t *sarea_priv;
 	drm_i830_ring_buffer_t ring;
@@ -95,7 +95,7 @@
 
 	dma_addr_t dma_status_page;
 
-	drm_buf_t *mmap_buffer;
+	struct drm_buf *mmap_buffer;
 
 	u32 front_di1, back_di1, zi1;
 
@@ -132,16 +132,16 @@
 			 unsigned int cmd, unsigned long arg);
 
 extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i830_driver_irq_preinstall(drm_device_t * dev);
-extern void i830_driver_irq_postinstall(drm_device_t * dev);
-extern void i830_driver_irq_uninstall(drm_device_t * dev);
+extern void i830_driver_irq_preinstall(struct drm_device * dev);
+extern void i830_driver_irq_postinstall(struct drm_device * dev);
+extern void i830_driver_irq_uninstall(struct drm_device * dev);
 extern int i830_driver_load(struct drm_device *, unsigned long flags);
-extern void i830_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void i830_driver_lastclose(drm_device_t * dev);
-extern void i830_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern void i830_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void i830_driver_lastclose(struct drm_device * dev);
+extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev,
 					       struct file *filp);
-extern int i830_driver_dma_quiescent(drm_device_t * dev);
-extern int i830_driver_device_is_agp(drm_device_t * dev);
+extern int i830_driver_dma_quiescent(struct drm_device * dev);
+extern int i830_driver_device_is_agp(struct drm_device * dev);
 
 #define I830_READ(reg)          DRM_READ32(dev_priv->mmio_map, reg)
 #define I830_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, reg, val)
@@ -180,7 +180,7 @@
 	I830_WRITE(LP_RING + RING_TAIL, outring);			\
 } while(0)
 
-extern int i830_wait_ring(drm_device_t * dev, int n, const char *caller);
+extern int i830_wait_ring(struct drm_device * dev, int n, const char *caller);
 
 #define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
index 5841f76..a1b5c63 100644
--- a/drivers/char/drm/i830_irq.c
+++ b/drivers/char/drm/i830_irq.c
@@ -35,7 +35,7 @@
 
 irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	u16 temp;
 
@@ -53,7 +53,7 @@
 	return IRQ_HANDLED;
 }
 
-static int i830_emit_irq(drm_device_t * dev)
+static int i830_emit_irq(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -70,7 +70,7 @@
 	return atomic_read(&dev_priv->irq_emitted);
 }
 
-static int i830_wait_irq(drm_device_t * dev, int irq_nr)
+static int i830_wait_irq(struct drm_device * dev, int irq_nr)
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	DECLARE_WAITQUEUE(entry, current);
@@ -117,8 +117,8 @@
 int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd,
 		  unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_irq_emit_t emit;
 	int result;
@@ -149,8 +149,8 @@
 int i830_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd,
 		  unsigned long arg)
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->head->dev;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_irq_wait_t irqwait;
 
@@ -168,7 +168,7 @@
 
 /* drm_dma.h hooks
 */
-void i830_driver_irq_preinstall(drm_device_t * dev)
+void i830_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 
@@ -180,14 +180,14 @@
 	init_waitqueue_head(&dev_priv->irq_queue);
 }
 
-void i830_driver_irq_postinstall(drm_device_t * dev)
+void i830_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 
 	I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
 }
 
-void i830_driver_irq_uninstall(drm_device_t * dev)
+void i830_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	if (!dev_priv)
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 1ba15d9..3359cc2 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -35,14 +35,19 @@
 		       dev->pci_device == 0x2982 || \
 		       dev->pci_device == 0x2992 || \
 		       dev->pci_device == 0x29A2 || \
-		       dev->pci_device == 0x2A02)
+		       dev->pci_device == 0x2A02 || \
+		       dev->pci_device == 0x2A12)
+
+#define IS_G33(dev) (dev->pci_device == 0x29b2 || \
+		     dev->pci_device == 0x29c2 || \
+		     dev->pci_device == 0x29d2)
 
 /* Really want an OS-independent resettable timer.  Would like to have
  * this loop run for (eg) 3 sec, but have the timer reset every time
  * the head pointer changes, so that EBUSY only happens if the ring
  * actually stalls for (eg) 3 seconds.
  */
-int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
+int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
@@ -68,7 +73,7 @@
 	return DRM_ERR(EBUSY);
 }
 
-void i915_kernel_lost_context(drm_device_t * dev)
+void i915_kernel_lost_context(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
@@ -83,7 +88,7 @@
 		dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
 }
 
-static int i915_dma_cleanup(drm_device_t * dev)
+static int i915_dma_cleanup(struct drm_device * dev)
 {
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
@@ -106,6 +111,12 @@
 			I915_WRITE(0x02080, 0x1ffff000);
 		}
 
+		if (dev_priv->status_gfx_addr) {
+			dev_priv->status_gfx_addr = 0;
+			drm_core_ioremapfree(&dev_priv->hws_map, dev);
+			I915_WRITE(0x2080, 0x1ffff000);
+		}
+
 		drm_free(dev->dev_private, sizeof(drm_i915_private_t),
 			 DRM_MEM_DRIVER);
 
@@ -115,13 +126,13 @@
 	return 0;
 }
 
-static int i915_initialize(drm_device_t * dev,
+static int i915_initialize(struct drm_device * dev,
 			   drm_i915_private_t * dev_priv,
 			   drm_i915_init_t * init)
 {
 	memset(dev_priv, 0, sizeof(drm_i915_private_t));
 
-	DRM_GETSAREA();
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("can not find sarea!\n");
 		dev->dev_private = (void *)dev_priv;
@@ -179,30 +190,28 @@
 	dev_priv->allow_batchbuffer = 1;
 
 	/* Program Hardware Status Page */
-	dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
-						   0xffffffff);
+	if (!IS_G33(dev)) {
+		dev_priv->status_page_dmah =
+			drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
 
-	if (!dev_priv->status_page_dmah) {
-		dev->dev_private = (void *)dev_priv;
-		i915_dma_cleanup(dev);
-		DRM_ERROR("Can not allocate hardware status page\n");
-		return DRM_ERR(ENOMEM);
+		if (!dev_priv->status_page_dmah) {
+			dev->dev_private = (void *)dev_priv;
+			i915_dma_cleanup(dev);
+			DRM_ERROR("Can not allocate hardware status page\n");
+			return DRM_ERR(ENOMEM);
+		}
+		dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+		dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
+		memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+		I915_WRITE(0x02080, dev_priv->dma_status_page);
 	}
-	dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
-	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-
-	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
-	I915_WRITE(0x02080, dev_priv->dma_status_page);
 	DRM_DEBUG("Enabled hardware status page\n");
-
 	dev->dev_private = (void *)dev_priv;
-
 	return 0;
 }
 
-static int i915_dma_resume(drm_device_t * dev)
+static int i915_dma_resume(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -231,7 +240,10 @@
 	}
 	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
 
-	I915_WRITE(0x02080, dev_priv->dma_status_page);
+	if (dev_priv->status_gfx_addr != 0)
+		I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+	else
+		I915_WRITE(0x02080, dev_priv->dma_status_page);
 	DRM_DEBUG("Enabled hardware status page\n");
 
 	return 0;
@@ -345,7 +357,7 @@
 	return ret;
 }
 
-static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
+static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int i;
@@ -384,12 +396,12 @@
 	return 0;
 }
 
-static int i915_emit_box(drm_device_t * dev,
-			 drm_clip_rect_t __user * boxes,
+static int i915_emit_box(struct drm_device * dev,
+			 struct drm_clip_rect __user * boxes,
 			 int i, int DR1, int DR4)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	drm_clip_rect_t box;
+	struct drm_clip_rect box;
 	RING_LOCALS;
 
 	if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
@@ -427,7 +439,7 @@
  * emit. For now, do it in both places:
  */
 
-static void i915_emit_breadcrumb(drm_device_t *dev)
+static void i915_emit_breadcrumb(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -445,7 +457,7 @@
 	ADVANCE_LP_RING();
 }
 
-static int i915_dispatch_cmdbuffer(drm_device_t * dev,
+static int i915_dispatch_cmdbuffer(struct drm_device * dev,
 				   drm_i915_cmdbuffer_t * cmd)
 {
 	int nbox = cmd->num_cliprects;
@@ -477,11 +489,11 @@
 	return 0;
 }
 
-static int i915_dispatch_batchbuffer(drm_device_t * dev,
+static int i915_dispatch_batchbuffer(struct drm_device * dev,
 				     drm_i915_batchbuffer_t * batch)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	drm_clip_rect_t __user *boxes = batch->cliprects;
+	struct drm_clip_rect __user *boxes = batch->cliprects;
 	int nbox = batch->num_cliprects;
 	int i = 0, count;
 	RING_LOCALS;
@@ -523,7 +535,7 @@
 	return 0;
 }
 
-static int i915_dispatch_flip(drm_device_t * dev)
+static int i915_dispatch_flip(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -571,7 +583,7 @@
 	return 0;
 }
 
-static int i915_quiescent(drm_device_t * dev)
+static int i915_quiescent(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
@@ -613,7 +625,7 @@
 
 	if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
 						       batch.num_cliprects *
-						       sizeof(drm_clip_rect_t)))
+						       sizeof(struct drm_clip_rect)))
 		return DRM_ERR(EFAULT);
 
 	ret = i915_dispatch_batchbuffer(dev, &batch);
@@ -643,7 +655,7 @@
 	if (cmdbuf.num_cliprects &&
 	    DRM_VERIFYAREA_READ(cmdbuf.cliprects,
 				cmdbuf.num_cliprects *
-				sizeof(drm_clip_rect_t))) {
+				sizeof(struct drm_clip_rect))) {
 		DRM_ERROR("Fault accessing cliprects\n");
 		return DRM_ERR(EFAULT);
 	}
@@ -739,7 +751,48 @@
 	return 0;
 }
 
-int i915_driver_load(drm_device_t *dev, unsigned long flags)
+static int i915_set_status_page(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_hws_addr_t hws;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+	DRM_COPY_FROM_USER_IOCTL(hws, (drm_i915_hws_addr_t __user *) data,
+			sizeof(hws));
+	printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws.addr);
+
+	dev_priv->status_gfx_addr = hws.addr & (0x1ffff<<12);
+
+	dev_priv->hws_map.offset = dev->agp->agp_info.aper_base + hws.addr;
+	dev_priv->hws_map.size = 4*1024;
+	dev_priv->hws_map.type = 0;
+	dev_priv->hws_map.flags = 0;
+	dev_priv->hws_map.mtrr = 0;
+
+	drm_core_ioremap(&dev_priv->hws_map, dev);
+	if (dev_priv->hws_map.handle == NULL) {
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		dev_priv->status_gfx_addr = 0;
+		DRM_ERROR("can not ioremap virtual address for"
+				" G33 hw status page\n");
+		return DRM_ERR(ENOMEM);
+	}
+	dev_priv->hw_status_page = dev_priv->hws_map.handle;
+
+	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+	I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+	DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
+			dev_priv->status_gfx_addr);
+	DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
+	return 0;
+}
+
+int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	/* i915 has 4 more counters */
 	dev->counters += 4;
@@ -751,7 +804,7 @@
 	return 0;
 }
 
-void i915_driver_lastclose(drm_device_t * dev)
+void i915_driver_lastclose(struct drm_device * dev)
 {
 	if (dev->dev_private) {
 		drm_i915_private_t *dev_priv = dev->dev_private;
@@ -760,7 +813,7 @@
 	i915_dma_cleanup(dev);
 }
 
-void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i915_driver_preclose(struct drm_device * dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_i915_private_t *dev_priv = dev->dev_private;
@@ -785,6 +838,7 @@
 	[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
 	[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
 	[DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_HWS_ADDR)] = {i915_set_status_page, DRM_AUTH},
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
@@ -800,7 +854,7 @@
  * \returns
  * A value of 1 is always retured to indictate every i9x5 is AGP.
  */
-int i915_driver_device_is_agp(drm_device_t * dev)
+int i915_driver_device_is_agp(struct drm_device * dev)
 {
 	return 1;
 }
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 96a46888..05c66cf 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -64,7 +64,7 @@
 } drm_i915_init_t;
 
 typedef struct _drm_i915_sarea {
-	drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1];
+	struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
 	int last_upload;	/* last time texture was uploaded */
 	int last_enqueue;	/* last time a buffer was enqueued */
 	int last_dispatch;	/* age of the most recently dispatched buffer */
@@ -142,6 +142,7 @@
 #define DRM_I915_SET_VBLANK_PIPE	0x0d
 #define DRM_I915_GET_VBLANK_PIPE	0x0e
 #define DRM_I915_VBLANK_SWAP	0x0f
+#define DRM_I915_HWS_ADDR	0x11
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -169,7 +170,7 @@
 	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
 	int DR4;		/* window origin for GFX_OP_DRAWRECT_INFO */
 	int num_cliprects;	/* mulitpass with multiple cliprects? */
-	drm_clip_rect_t __user *cliprects;	/* pointer to userspace cliprects */
+	struct drm_clip_rect __user *cliprects;	/* pointer to userspace cliprects */
 } drm_i915_batchbuffer_t;
 
 /* As above, but pass a pointer to userspace buffer which can be
@@ -181,7 +182,7 @@
 	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
 	int DR4;		/* window origin for GFX_OP_DRAWRECT_INFO */
 	int num_cliprects;	/* mulitpass with multiple cliprects? */
-	drm_clip_rect_t __user *cliprects;	/* pointer to userspace cliprects */
+	struct drm_clip_rect __user *cliprects;	/* pointer to userspace cliprects */
 } drm_i915_cmdbuffer_t;
 
 /* Userspace can request & wait on irq's:
@@ -258,8 +259,12 @@
  */
 typedef struct drm_i915_vblank_swap {
 	drm_drawable_t drawable;
-	drm_vblank_seq_type_t seqtype;
+	enum drm_vblank_seq_type seqtype;
 	unsigned int sequence;
 } drm_i915_vblank_swap_t;
 
+typedef struct drm_i915_hws_addr {
+	uint64_t addr;
+} drm_i915_hws_addr_t;
+
 #endif				/* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 93cdcfe..fd91856 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -91,6 +91,8 @@
 	void *hw_status_page;
 	dma_addr_t dma_status_page;
 	unsigned long counter;
+	unsigned int status_gfx_addr;
+	drm_local_map_t hws_map;
 
 	unsigned int cpp;
 	int back_offset;
@@ -118,11 +120,11 @@
 extern int i915_max_ioctl;
 
 				/* i915_dma.c */
-extern void i915_kernel_lost_context(drm_device_t * dev);
+extern void i915_kernel_lost_context(struct drm_device * dev);
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
-extern void i915_driver_lastclose(drm_device_t * dev);
-extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern int i915_driver_device_is_agp(drm_device_t * dev);
+extern void i915_driver_lastclose(struct drm_device * dev);
+extern void i915_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern int i915_driver_device_is_agp(struct drm_device * dev);
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
 
@@ -130,12 +132,12 @@
 extern int i915_irq_emit(DRM_IOCTL_ARGS);
 extern int i915_irq_wait(DRM_IOCTL_ARGS);
 
-extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
-extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i915_driver_irq_preinstall(drm_device_t * dev);
-extern void i915_driver_irq_postinstall(drm_device_t * dev);
-extern void i915_driver_irq_uninstall(drm_device_t * dev);
+extern void i915_driver_irq_preinstall(struct drm_device * dev);
+extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern void i915_driver_irq_uninstall(struct drm_device * dev);
 extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
 extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
 extern int i915_vblank_swap(DRM_IOCTL_ARGS);
@@ -146,7 +148,7 @@
 extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
 extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
 extern void i915_mem_takedown(struct mem_block **heap);
-extern void i915_mem_release(drm_device_t * dev,
+extern void i915_mem_release(struct drm_device * dev,
 			     DRMFILE filp, struct mem_block *heap);
 
 #define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
@@ -186,7 +188,7 @@
 	I915_WRITE(LP_RING + RING_TAIL, outring);			\
 } while(0)
 
-extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
 #define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 78c1ae2..4b4b2ce 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -42,7 +42,7 @@
  *
  * This function will be called with the HW lock held.
  */
-static void i915_vblank_tasklet(drm_device_t *dev)
+static void i915_vblank_tasklet(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
@@ -50,7 +50,7 @@
 	int nhits, nrects, slice[2], upper[2], lower[2], i;
 	unsigned counter[2] = { atomic_read(&dev->vbl_received),
 				atomic_read(&dev->vbl_received2) };
-	drm_drawable_info_t *drw;
+	struct drm_drawable_info *drw;
 	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	u32 cpp = dev_priv->cpp;
 	u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
@@ -95,7 +95,7 @@
 		list_for_each(hit, &hits) {
 			drm_i915_vbl_swap_t *swap_cmp =
 				list_entry(hit, drm_i915_vbl_swap_t, head);
-			drm_drawable_info_t *drw_cmp =
+			struct drm_drawable_info *drw_cmp =
 				drm_get_drawable_info(dev, swap_cmp->drw_id);
 
 			if (drw_cmp &&
@@ -160,7 +160,7 @@
 		list_for_each(hit, &hits) {
 			drm_i915_vbl_swap_t *swap_hit =
 				list_entry(hit, drm_i915_vbl_swap_t, head);
-			drm_clip_rect_t *rect;
+			struct drm_clip_rect *rect;
 			int num_rects, pipe;
 			unsigned short top, bottom;
 
@@ -211,7 +211,7 @@
 
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u16 temp;
 
@@ -257,7 +257,7 @@
 	return IRQ_HANDLED;
 }
 
-static int i915_emit_irq(drm_device_t * dev)
+static int i915_emit_irq(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -283,7 +283,7 @@
 	return dev_priv->counter;
 }
 
-static int i915_wait_irq(drm_device_t * dev, int irq_nr)
+static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int ret = 0;
@@ -309,7 +309,7 @@
 	return ret;
 }
 
-static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
+static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
 				      atomic_t *counter)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -331,12 +331,12 @@
 }
 
 
-int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
 {
 	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
 }
 
-int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
 {
 	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
 }
@@ -389,7 +389,7 @@
 	return i915_wait_irq(dev, irqwait.irq_seq);
 }
 
-static void i915_enable_interrupt (drm_device_t *dev)
+static void i915_enable_interrupt (struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u16 flag;
@@ -569,7 +569,7 @@
 
 /* drm_dma.h hooks
 */
-void i915_driver_irq_preinstall(drm_device_t * dev)
+void i915_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -578,11 +578,11 @@
 	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 }
 
-void i915_driver_irq_postinstall(drm_device_t * dev)
+void i915_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&dev_priv->swaps_lock);
 	INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
 	dev_priv->swaps_pending = 0;
 
@@ -592,7 +592,7 @@
 	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 }
 
-void i915_driver_irq_uninstall(drm_device_t * dev)
+void i915_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u16 temp;
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index 52c6732..50b4bac 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -43,11 +43,11 @@
  * block to allocate, and the ring is drained prior to allocations --
  * in other words allocation is expensive.
  */
-static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
+static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_tex_region_t *list;
+	struct drm_tex_region *list;
 	unsigned shift, nr;
 	unsigned start;
 	unsigned end;
@@ -208,7 +208,7 @@
 
 /* Free all blocks associated with the releasing file.
  */
-void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
+void i915_mem_release(struct drm_device * dev, DRMFILE filp, struct mem_block *heap)
 {
 	struct mem_block *p;
 
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index c2a4bac..9c73a6e 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -46,7 +46,7 @@
 
 #define MINIMAL_CLEANUP 0
 #define FULL_CLEANUP 1
-static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup);
+static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup);
 
 /* ================================================================
  * Engine control
@@ -224,7 +224,7 @@
 #define MGA_BUFFER_FREE		0
 
 #if MGA_FREELIST_DEBUG
-static void mga_freelist_print(drm_device_t * dev)
+static void mga_freelist_print(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *entry;
@@ -245,10 +245,10 @@
 }
 #endif
 
-static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
+static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_priv)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_freelist_t *entry;
 	int i;
@@ -291,7 +291,7 @@
 	return 0;
 }
 
-static void mga_freelist_cleanup(drm_device_t * dev)
+static void mga_freelist_cleanup(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *entry;
@@ -311,10 +311,10 @@
 #if 0
 /* FIXME: Still needed?
  */
-static void mga_freelist_reset(drm_device_t * dev)
+static void mga_freelist_reset(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	int i;
 
@@ -326,7 +326,7 @@
 }
 #endif
 
-static drm_buf_t *mga_freelist_get(drm_device_t * dev)
+static struct drm_buf *mga_freelist_get(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *next;
@@ -359,7 +359,7 @@
 	return NULL;
 }
 
-int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -393,7 +393,7 @@
  * DMA initialization, cleanup
  */
 
-int mga_driver_load(drm_device_t * dev, unsigned long flags)
+int mga_driver_load(struct drm_device * dev, unsigned long flags)
 {
 	drm_mga_private_t *dev_priv;
 
@@ -434,7 +434,7 @@
  *
  * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
  */
-static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
 				    drm_mga_dma_bootstrap_t * dma_bs)
 {
 	drm_mga_private_t *const dev_priv =
@@ -445,11 +445,11 @@
 	const unsigned secondary_size = dma_bs->secondary_bin_count
 	    * dma_bs->secondary_bin_size;
 	const unsigned agp_size = (dma_bs->agp_size << 20);
-	drm_buf_desc_t req;
-	drm_agp_mode_t mode;
-	drm_agp_info_t info;
-	drm_agp_buffer_t agp_req;
-	drm_agp_binding_t bind_req;
+	struct drm_buf_desc req;
+	struct drm_agp_mode mode;
+	struct drm_agp_info info;
+	struct drm_agp_buffer agp_req;
+	struct drm_agp_binding bind_req;
 
 	/* Acquire AGP. */
 	err = drm_agp_acquire(dev);
@@ -548,10 +548,10 @@
 	}
 
 	{
-		drm_map_list_t *_entry;
+		struct drm_map_list *_entry;
 		unsigned long agp_token = 0;
 		
-		list_for_each_entry(_entry, &dev->maplist->head, head) {
+		list_for_each_entry(_entry, &dev->maplist, head) {
 			if (_entry->map == dev->agp_buffer_map)
 				agp_token = _entry->user_token;
 		}
@@ -588,7 +588,7 @@
 	return 0;
 }
 #else
-static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
 				    drm_mga_dma_bootstrap_t * dma_bs)
 {
 	return -EINVAL;
@@ -609,7 +609,7 @@
  *
  * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
  */
-static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
 				    drm_mga_dma_bootstrap_t * dma_bs)
 {
 	drm_mga_private_t *const dev_priv =
@@ -618,7 +618,7 @@
 	unsigned int primary_size;
 	unsigned int bin_count;
 	int err;
-	drm_buf_desc_t req;
+	struct drm_buf_desc req;
 
 	if (dev->dma == NULL) {
 		DRM_ERROR("dev->dma is NULL\n");
@@ -699,7 +699,7 @@
 	return 0;
 }
 
-static int mga_do_dma_bootstrap(drm_device_t * dev,
+static int mga_do_dma_bootstrap(struct drm_device * dev,
 				drm_mga_dma_bootstrap_t * dma_bs)
 {
 	const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
@@ -793,7 +793,7 @@
 	return err;
 }
 
-static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
+static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
 {
 	drm_mga_private_t *dev_priv;
 	int ret;
@@ -823,8 +823,7 @@
 	dev_priv->texture_offset = init->texture_offset[0];
 	dev_priv->texture_size = init->texture_size[0];
 
-	DRM_GETSAREA();
-
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("failed to find sarea!\n");
 		return DRM_ERR(EINVAL);
@@ -934,7 +933,7 @@
 	return 0;
 }
 
-static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup)
+static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
 {
 	int err = 0;
 	DRM_DEBUG("\n");
@@ -963,8 +962,8 @@
 		if (dev_priv->used_new_dma_init) {
 #if __OS_HAS_AGP
 			if (dev_priv->agp_handle != 0) {
-				drm_agp_binding_t unbind_req;
-				drm_agp_buffer_t free_req;
+				struct drm_agp_binding unbind_req;
+				struct drm_agp_buffer free_req;
 
 				unbind_req.handle = dev_priv->agp_handle;
 				drm_agp_unbind(dev, &unbind_req);
@@ -1041,11 +1040,11 @@
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-	drm_lock_t lock;
+	struct drm_lock lock;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
-	DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data,
+	DRM_COPY_FROM_USER_IOCTL(lock, (struct drm_lock __user *) data,
 				 sizeof(lock));
 
 	DRM_DEBUG("%s%s%s\n",
@@ -1087,9 +1086,9 @@
  * DMA buffer management
  */
 
-static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+static int mga_dma_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d)
 {
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i;
 
 	for (i = d->granted_count; i < d->request_count; i++) {
@@ -1114,10 +1113,10 @@
 int mga_dma_buffers(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-	drm_dma_t __user *argp = (void __user *)data;
-	drm_dma_t d;
+	struct drm_dma __user *argp = (void __user *)data;
+	struct drm_dma d;
 	int ret = 0;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1156,7 +1155,7 @@
 /**
  * Called just before the module is unloaded.
  */
-int mga_driver_unload(drm_device_t * dev)
+int mga_driver_unload(struct drm_device * dev)
 {
 	drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
 	dev->dev_private = NULL;
@@ -1167,12 +1166,12 @@
 /**
  * Called when the last opener of the device is closed.
  */
-void mga_driver_lastclose(drm_device_t * dev)
+void mga_driver_lastclose(struct drm_device * dev)
 {
 	mga_do_cleanup_dma(dev, FULL_CLEANUP);
 }
 
-int mga_driver_dma_quiescent(drm_device_t * dev)
+int mga_driver_dma_quiescent(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	return mga_do_wait_for_idle(dev_priv);
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
index 44d1293..944b50a 100644
--- a/drivers/char/drm/mga_drm.h
+++ b/drivers/char/drm/mga_drm.h
@@ -181,7 +181,7 @@
 
 	/* The current cliprects, or a subset thereof.
 	 */
-	drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS];
 	unsigned int nbox;
 
 	/* Information about the most recently used 3d drawable.  The
@@ -202,7 +202,7 @@
 	unsigned int exported_nback;
 	int exported_back_x, exported_front_x, exported_w;
 	int exported_back_y, exported_front_y, exported_h;
-	drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS];
 
 	/* Counters for aging textures and for client-side throttling.
 	 */
@@ -216,7 +216,7 @@
 
 	/* LRU lists for texture memory in agp space and on the card.
 	 */
-	drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
+	struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
 	unsigned int texAge[MGA_NR_TEX_HEAPS];
 
 	/* Mechanism to validate card state.
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index be49dbb..5572939 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -36,7 +36,7 @@
 
 #include "drm_pciids.h"
 
-static int mga_driver_device_is_agp(drm_device_t * dev);
+static int mga_driver_device_is_agp(struct drm_device * dev);
 
 static struct pci_device_id pciidlist[] = {
 	mga_PCI_IDS
@@ -118,7 +118,7 @@
  * \returns
  * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
  */
-static int mga_driver_device_is_agp(drm_device_t * dev)
+static int mga_driver_device_is_agp(struct drm_device * dev)
 {
 	const struct pci_dev *const pdev = dev->pdev;
 
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 6b0c531..49253af 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -65,7 +65,7 @@
 	struct drm_mga_freelist *next;
 	struct drm_mga_freelist *prev;
 	drm_mga_age_t age;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 } drm_mga_freelist_t;
 
 typedef struct {
@@ -157,10 +157,10 @@
 extern int mga_dma_flush(DRM_IOCTL_ARGS);
 extern int mga_dma_reset(DRM_IOCTL_ARGS);
 extern int mga_dma_buffers(DRM_IOCTL_ARGS);
-extern int mga_driver_load(drm_device_t *dev, unsigned long flags);
-extern int mga_driver_unload(drm_device_t * dev);
-extern void mga_driver_lastclose(drm_device_t * dev);
-extern int mga_driver_dma_quiescent(drm_device_t * dev);
+extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
+extern int mga_driver_unload(struct drm_device * dev);
+extern void mga_driver_lastclose(struct drm_device * dev);
+extern int mga_driver_dma_quiescent(struct drm_device * dev);
 
 extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
 
@@ -168,7 +168,7 @@
 extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
 extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
 
-extern int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf);
+extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
 
 				/* mga_warp.c */
 extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
@@ -176,12 +176,12 @@
 extern int mga_warp_init(drm_mga_private_t * dev_priv);
 
 				/* mga_irq.c */
-extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence);
-extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
-extern void mga_driver_irq_preinstall(drm_device_t * dev);
-extern void mga_driver_irq_postinstall(drm_device_t * dev);
-extern void mga_driver_irq_uninstall(drm_device_t * dev);
+extern void mga_driver_irq_preinstall(struct drm_device * dev);
+extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern void mga_driver_irq_uninstall(struct drm_device * dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
 			     unsigned long arg);
 
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
index eb96440..9302cb8 100644
--- a/drivers/char/drm/mga_irq.c
+++ b/drivers/char/drm/mga_irq.c
@@ -37,7 +37,7 @@
 
 irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	int status;
 	int handled = 0;
@@ -78,7 +78,7 @@
 	return IRQ_NONE;
 }
 
-int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	unsigned int cur_vblank;
 	int ret = 0;
@@ -96,7 +96,7 @@
 	return ret;
 }
 
-int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
+int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	unsigned int cur_fence;
@@ -115,7 +115,7 @@
 	return ret;
 }
 
-void mga_driver_irq_preinstall(drm_device_t * dev)
+void mga_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
@@ -125,7 +125,7 @@
 	MGA_WRITE(MGA_ICLEAR, ~0);
 }
 
-void mga_driver_irq_postinstall(drm_device_t * dev)
+void mga_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
@@ -135,7 +135,7 @@
 	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
 }
 
-void mga_driver_irq_uninstall(drm_device_t * dev)
+void mga_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	if (!dev_priv)
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
index 2837e66..d448b0a 100644
--- a/drivers/char/drm/mga_state.c
+++ b/drivers/char/drm/mga_state.c
@@ -42,7 +42,7 @@
  */
 
 static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
-			       drm_clip_rect_t * box)
+			       struct drm_clip_rect * box)
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -480,12 +480,12 @@
  *
  */
 
-static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
+static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * clear)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	int i;
 	DMA_LOCALS;
@@ -500,7 +500,7 @@
 	ADVANCE_DMA();
 
 	for (i = 0; i < nbox; i++) {
-		drm_clip_rect_t *box = &pbox[i];
+		struct drm_clip_rect *box = &pbox[i];
 		u32 height = box->y2 - box->y1;
 
 		DRM_DEBUG("   from=%d,%d to=%d,%d\n",
@@ -568,12 +568,12 @@
 	FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_swap(drm_device_t * dev)
+static void mga_dma_dispatch_swap(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	int i;
 	DMA_LOCALS;
@@ -598,7 +598,7 @@
 		  MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
 
 	for (i = 0; i < nbox; i++) {
-		drm_clip_rect_t *box = &pbox[i];
+		struct drm_clip_rect *box = &pbox[i];
 		u32 height = box->y2 - box->y1;
 		u32 start = box->y1 * dev_priv->front_pitch;
 
@@ -622,7 +622,7 @@
 	DRM_DEBUG("%s... done.\n", __FUNCTION__);
 }
 
-static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -669,7 +669,7 @@
 	FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
+static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf,
 				     unsigned int start, unsigned int end)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -718,7 +718,7 @@
 /* This copies a 64 byte aligned agp region to the frambuffer with a
  * standard blit, the ioctl needs to do checking.
  */
-static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf,
+static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf,
 				   unsigned int dstorg, unsigned int length)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -766,12 +766,12 @@
 	FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit)
+static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int nbox = sarea_priv->nbox;
 	u32 scandir = 0, i;
 	DMA_LOCALS;
@@ -880,8 +880,8 @@
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_vertex_t vertex;
 
@@ -920,8 +920,8 @@
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_indices_t indices;
 
@@ -959,9 +959,9 @@
 static int mga_dma_iload(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_mga_private_t *dev_priv = dev->dev_private;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_iload_t iload;
 	DRM_DEBUG("\n");
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index 1014602..b163ed0 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -81,7 +81,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
-static int R128_READ_PLL(drm_device_t * dev, int addr)
+static int R128_READ_PLL(struct drm_device * dev, int addr)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 
@@ -271,7 +271,7 @@
 
 /* Reset the engine.  This will stop the CCE if it is running.
  */
-static int r128_do_engine_reset(drm_device_t * dev)
+static int r128_do_engine_reset(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
@@ -308,7 +308,7 @@
 	return 0;
 }
 
-static void r128_cce_init_ring_buffer(drm_device_t * dev,
+static void r128_cce_init_ring_buffer(struct drm_device * dev,
 				      drm_r128_private_t * dev_priv)
 {
 	u32 ring_start;
@@ -347,7 +347,7 @@
 	R128_WRITE(R128_BUS_CNTL, tmp);
 }
 
-static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
+static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
 {
 	drm_r128_private_t *dev_priv;
 
@@ -456,8 +456,7 @@
 	dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
 					 (dev_priv->span_offset >> 5));
 
-	DRM_GETSAREA();
-
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		dev->dev_private = (void *)dev_priv;
@@ -585,7 +584,7 @@
 	return 0;
 }
 
-int r128_do_cleanup_cce(drm_device_t * dev)
+int r128_do_cleanup_cce(struct drm_device * dev)
 {
 
 	/* Make sure interrupts are disabled here because the uninstall ioctl
@@ -770,11 +769,11 @@
 #define R128_BUFFER_FREE	0
 
 #if 0
-static int r128_freelist_init(drm_device_t * dev)
+static int r128_freelist_init(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_freelist_t *entry;
 	int i;
@@ -816,12 +815,12 @@
 }
 #endif
 
-static drm_buf_t *r128_freelist_get(drm_device_t * dev)
+static struct drm_buf *r128_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_buf_priv_t *buf_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i, t;
 
 	/* FIXME: Optimize -- use freelist code */
@@ -854,13 +853,13 @@
 	return NULL;
 }
 
-void r128_freelist_reset(drm_device_t * dev)
+void r128_freelist_reset(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int i;
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_r128_buf_priv_t *buf_priv = buf->dev_private;
 		buf_priv->age = 0;
 	}
@@ -887,10 +886,10 @@
 	return DRM_ERR(EBUSY);
 }
 
-static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+static int r128_cce_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d)
 {
 	int i;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 
 	for (i = d->granted_count; i < d->request_count; i++) {
 		buf = r128_freelist_get(dev);
@@ -914,10 +913,10 @@
 int r128_cce_buffers(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int ret = 0;
-	drm_dma_t __user *argp = (void __user *)data;
-	drm_dma_t d;
+	struct drm_dma __user *argp = (void __user *)data;
+	struct drm_dma d;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 6e8af31..e94a39c 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -153,7 +153,7 @@
 
 	/* The current cliprects, or a subset thereof.
 	 */
-	drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS];
 	unsigned int nbox;
 
 	/* Counters for client-side throttling of rendering clients.
@@ -161,7 +161,7 @@
 	unsigned int last_frame;
 	unsigned int last_dispatch;
 
-	drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
+	struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
 	unsigned int tex_age[R128_NR_TEX_HEAPS];
 	int ctx_owner;
 	int pfAllowPageFlip;	/* number of 3d windows (0,1,2 or more) */
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 9086835..72249fb 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -57,7 +57,7 @@
 
 typedef struct drm_r128_freelist {
 	unsigned int age;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	struct drm_r128_freelist *next;
 	struct drm_r128_freelist *prev;
 } drm_r128_freelist_t;
@@ -118,7 +118,7 @@
 	drm_local_map_t *cce_ring;
 	drm_local_map_t *ring_rptr;
 	drm_local_map_t *agp_textures;
-	drm_ati_pcigart_info gart_info;
+	struct drm_ati_pcigart_info gart_info;
 } drm_r128_private_t;
 
 typedef struct drm_r128_buf_priv {
@@ -142,21 +142,21 @@
 extern int r128_fullscreen(DRM_IOCTL_ARGS);
 extern int r128_cce_buffers(DRM_IOCTL_ARGS);
 
-extern void r128_freelist_reset(drm_device_t * dev);
+extern void r128_freelist_reset(struct drm_device * dev);
 
 extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
 
 extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
-extern int r128_do_cleanup_cce(drm_device_t * dev);
+extern int r128_do_cleanup_cce(struct drm_device * dev);
 
-extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 
 extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
-extern void r128_driver_irq_preinstall(drm_device_t * dev);
-extern void r128_driver_irq_postinstall(drm_device_t * dev);
-extern void r128_driver_irq_uninstall(drm_device_t * dev);
-extern void r128_driver_lastclose(drm_device_t * dev);
-extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void r128_driver_irq_preinstall(struct drm_device * dev);
+extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern void r128_driver_irq_uninstall(struct drm_device * dev);
+extern void r128_driver_lastclose(struct drm_device * dev);
+extern void r128_driver_preclose(struct drm_device * dev, DRMFILE filp);
 
 extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
index 87f8ca2..c76fdca 100644
--- a/drivers/char/drm/r128_irq.c
+++ b/drivers/char/drm/r128_irq.c
@@ -37,7 +37,7 @@
 
 irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 	int status;
 
@@ -54,7 +54,7 @@
 	return IRQ_NONE;
 }
 
-int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	unsigned int cur_vblank;
 	int ret = 0;
@@ -72,7 +72,7 @@
 	return ret;
 }
 
-void r128_driver_irq_preinstall(drm_device_t * dev)
+void r128_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 
@@ -82,7 +82,7 @@
 	R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
 }
 
-void r128_driver_irq_postinstall(drm_device_t * dev)
+void r128_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 
@@ -90,7 +90,7 @@
 	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
 }
 
-void r128_driver_irq_uninstall(drm_device_t * dev)
+void r128_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 	if (!dev_priv)
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 17b11e7..7b334fb 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -38,7 +38,7 @@
  */
 
 static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
-				 drm_clip_rect_t * boxes, int count)
+				 struct drm_clip_rect * boxes, int count)
 {
 	u32 aux_sc_cntl = 0x00000000;
 	RING_LOCALS;
@@ -352,13 +352,13 @@
 		 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
 }
 
-static void r128_cce_dispatch_clear(drm_device_t * dev,
+static void r128_cce_dispatch_clear(struct drm_device * dev,
 				    drm_r128_clear_t * clear)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	unsigned int flags = clear->flags;
 	int i;
 	RING_LOCALS;
@@ -458,12 +458,12 @@
 	}
 }
 
-static void r128_cce_dispatch_swap(drm_device_t * dev)
+static void r128_cce_dispatch_swap(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -524,7 +524,7 @@
 	ADVANCE_RING();
 }
 
-static void r128_cce_dispatch_flip(drm_device_t * dev)
+static void r128_cce_dispatch_flip(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -567,7 +567,7 @@
 	ADVANCE_RING();
 }
 
-static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+static void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -637,8 +637,8 @@
 	sarea_priv->nbox = 0;
 }
 
-static void r128_cce_dispatch_indirect(drm_device_t * dev,
-				       drm_buf_t * buf, int start, int end)
+static void r128_cce_dispatch_indirect(struct drm_device * dev,
+				       struct drm_buf * buf, int start, int end)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -692,8 +692,8 @@
 	dev_priv->sarea_priv->last_dispatch++;
 }
 
-static void r128_cce_dispatch_indices(drm_device_t * dev,
-				      drm_buf_t * buf,
+static void r128_cce_dispatch_indices(struct drm_device * dev,
+				      struct drm_buf * buf,
 				      int start, int end, int count)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -777,11 +777,11 @@
 }
 
 static int r128_cce_dispatch_blit(DRMFILE filp,
-				  drm_device_t * dev, drm_r128_blit_t * blit)
+				  struct drm_device * dev, drm_r128_blit_t * blit)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	u32 *data;
 	int dword_shift, dwords;
@@ -887,7 +887,7 @@
  * have hardware stencil support.
  */
 
-static int r128_cce_dispatch_write_span(drm_device_t * dev,
+static int r128_cce_dispatch_write_span(struct drm_device * dev,
 					drm_r128_depth_t * depth)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -983,7 +983,7 @@
 	return 0;
 }
 
-static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
+static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
 					  drm_r128_depth_t * depth)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1105,7 +1105,7 @@
 	return 0;
 }
 
-static int r128_cce_dispatch_read_span(drm_device_t * dev,
+static int r128_cce_dispatch_read_span(struct drm_device * dev,
 				       drm_r128_depth_t * depth)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1148,7 +1148,7 @@
 	return 0;
 }
 
-static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
+static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
 					 drm_r128_depth_t * depth)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1220,7 +1220,7 @@
  * Polygon stipple
  */
 
-static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	int i;
@@ -1269,7 +1269,7 @@
 	return 0;
 }
 
-static int r128_do_init_pageflip(drm_device_t * dev)
+static int r128_do_init_pageflip(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG("\n");
@@ -1288,7 +1288,7 @@
 	return 0;
 }
 
-static int r128_do_cleanup_pageflip(drm_device_t * dev)
+static int r128_do_cleanup_pageflip(struct drm_device * dev)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG("\n");
@@ -1354,8 +1354,8 @@
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_vertex_t vertex;
 
@@ -1413,8 +1413,8 @@
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_indices_t elts;
 	int count;
@@ -1483,7 +1483,7 @@
 static int r128_cce_blit(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_blit_t blit;
 	int ret;
@@ -1571,8 +1571,8 @@
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_indirect_t indirect;
 #if 0
@@ -1675,7 +1675,7 @@
 	return 0;
 }
 
-void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void r128_driver_preclose(struct drm_device * dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1685,7 +1685,7 @@
 	}
 }
 
-void r128_driver_lastclose(drm_device_t * dev)
+void r128_driver_lastclose(struct drm_device * dev)
 {
 	r128_do_cleanup_cce(dev);
 }
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index 032a022..4e5aca6b 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -55,7 +55,7 @@
 static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
 			       drm_radeon_kcmd_buffer_t *cmdbuf, int n)
 {
-	drm_clip_rect_t box;
+	struct drm_clip_rect box;
 	int nr;
 	int i;
 	RING_LOCALS;
@@ -148,15 +148,16 @@
 
 	/* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
 	ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
-	ADD_RANGE(0x2080, 1);
+	ADD_RANGE(R300_VAP_CNTL, 1);
 	ADD_RANGE(R300_SE_VTE_CNTL, 2);
 	ADD_RANGE(0x2134, 2);
-	ADD_RANGE(0x2140, 1);
+	ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
 	ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
 	ADD_RANGE(0x21DC, 1);
-	ADD_RANGE(0x221C, 1);
-	ADD_RANGE(0x2220, 4);
-	ADD_RANGE(0x2288, 1);
+	ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
+	ADD_RANGE(R300_VAP_CLIP_X_0, 4);
+	ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
+	ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
 	ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
 	ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
 	ADD_RANGE(R300_GB_ENABLE, 1);
@@ -168,13 +169,13 @@
 	ADD_RANGE(R300_RE_POINTSIZE, 1);
 	ADD_RANGE(0x4230, 3);
 	ADD_RANGE(R300_RE_LINE_CNT, 1);
-	ADD_RANGE(0x4238, 1);
+	ADD_RANGE(R300_RE_UNK4238, 1);
 	ADD_RANGE(0x4260, 3);
-	ADD_RANGE(0x4274, 4);
-	ADD_RANGE(0x4288, 5);
-	ADD_RANGE(0x42A0, 1);
+	ADD_RANGE(R300_RE_SHADE, 4);
+	ADD_RANGE(R300_RE_POLYGON_MODE, 5);
+	ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
 	ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
-	ADD_RANGE(0x42B4, 1);
+	ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
 	ADD_RANGE(R300_RE_CULL_CNTL, 1);
 	ADD_RANGE(0x42C0, 2);
 	ADD_RANGE(R300_RS_CNTL_0, 2);
@@ -190,22 +191,22 @@
 	ADD_RANGE(R300_PFS_INSTR1_0, 64);
 	ADD_RANGE(R300_PFS_INSTR2_0, 64);
 	ADD_RANGE(R300_PFS_INSTR3_0, 64);
-	ADD_RANGE(0x4BC0, 1);
-	ADD_RANGE(0x4BC8, 3);
+	ADD_RANGE(R300_RE_FOG_STATE, 1);
+	ADD_RANGE(R300_FOG_COLOR_R, 3);
 	ADD_RANGE(R300_PP_ALPHA_TEST, 2);
 	ADD_RANGE(0x4BD8, 1);
 	ADD_RANGE(R300_PFS_PARAM_0_X, 64);
 	ADD_RANGE(0x4E00, 1);
 	ADD_RANGE(R300_RB3D_CBLEND, 2);
 	ADD_RANGE(R300_RB3D_COLORMASK, 1);
-	ADD_RANGE(0x4E10, 3);
+	ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
 	ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET);	/* check offset */
 	ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
 	ADD_RANGE(0x4E50, 9);
 	ADD_RANGE(0x4E88, 1);
 	ADD_RANGE(0x4EA0, 2);
 	ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
-	ADD_RANGE(0x4F10, 4);
+	ADD_RANGE(R300_RB3D_ZSTENCIL_FORMAT, 4);
 	ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);	/* check offset */
 	ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
 	ADD_RANGE(0x4F28, 1);
@@ -224,7 +225,7 @@
 	ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
 
 	/* Sporadic registers used as primitives are emitted */
-	ADD_RANGE(0x4f18, 1);
+	ADD_RANGE(R300_RB3D_ZCACHE_CTLSTAT, 1);
 	ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
 	ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
 	ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
@@ -692,9 +693,9 @@
 
 	BEGIN_RING(6);
 	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-	OUT_RING(0xa);
-	OUT_RING(CP_PACKET0(0x4f18, 0));
-	OUT_RING(0x3);
+	OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A);
+	OUT_RING(CP_PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
+	OUT_RING(R300_RB3D_ZCACHE_UNKNOWN_03);
 	OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
 	OUT_RING(0x0);
 	ADVANCE_RING();
@@ -705,7 +706,7 @@
  * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
  * be careful about how this function is called.
  */
-static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -766,8 +767,8 @@
 	}
 	
 	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0));
-	OUT_RING(dev_priv->scratch_ages[header.scratch.reg]);
+	OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
+	OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
 	ADVANCE_RING();
 	
 	return 0;
@@ -778,14 +779,14 @@
  * commands on the DMA ring buffer.
  * Called by the ioctl handler function radeon_cp_cmdbuf.
  */
-int r300_do_cp_cmdbuf(drm_device_t *dev,
+int r300_do_cp_cmdbuf(struct drm_device *dev,
 		      DRMFILE filp,
-		      drm_file_t *filp_priv,
+		      struct drm_file *filp_priv,
 		      drm_radeon_kcmd_buffer_t *cmdbuf)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf = NULL;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf = NULL;
 	int emit_dispatch_age = 0;
 	int ret = 0;
 
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
index ecda760..3ae57ec 100644
--- a/drivers/char/drm/r300_reg.h
+++ b/drivers/char/drm/r300_reg.h
@@ -47,12 +47,12 @@
 #	define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT	28
 
 /*
-This file contains registers and constants for the R300. They have been
-found mostly by examining command buffers captured using glxtest, as well
-as by extrapolating some known registers and constants from the R200.
-
-I am fairly certain that they are correct unless stated otherwise in comments.
-*/
+ * This file contains registers and constants for the R300. They have been
+ * found mostly by examining command buffers captured using glxtest, as well
+ * as by extrapolating some known registers and constants from the R200.
+ * I am fairly certain that they are correct unless stated otherwise
+ * in comments.
+ */
 
 #define R300_SE_VPORT_XSCALE                0x1D98
 #define R300_SE_VPORT_XOFFSET               0x1D9C
@@ -61,49 +61,60 @@
 #define R300_SE_VPORT_ZSCALE                0x1DA8
 #define R300_SE_VPORT_ZOFFSET               0x1DAC
 
-/* This register is written directly and also starts data section in many 3d CP_PACKET3's */
+
+/*
+ * Vertex Array Processing (VAP) Control
+ * Stolen from r200 code from Christoph Brill (It's a guess!)
+ */
+#define R300_VAP_CNTL	0x2080
+
+/* This register is written directly and also starts data section
+ * in many 3d CP_PACKET3's
+ */
 #define R300_VAP_VF_CNTL	0x2084
+#	define	R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT              0
+#	define  R300_VAP_VF_CNTL__PRIM_NONE                     (0<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_POINTS                   (1<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_LINES                    (2<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_LINE_STRIP               (3<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLES                (4<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN             (5<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP           (6<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_LINE_LOOP                (12<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_QUADS                    (13<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_QUAD_STRIP               (14<<0)
+#	define  R300_VAP_VF_CNTL__PRIM_POLYGON                  (15<<0)
 
-#	define	R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT                       0
-#	define  R300_VAP_VF_CNTL__PRIM_NONE				 (0<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_POINTS				 (1<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_LINES				 (2<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_LINE_STRIP			 (3<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLES			 (4<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN			 (5<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP			 (6<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_LINE_LOOP			 (12<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_QUADS			 	 (13<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_QUAD_STRIP			 (14<<0)
-#	define  R300_VAP_VF_CNTL__PRIM_POLYGON			 	 (15<<0)
+#	define	R300_VAP_VF_CNTL__PRIM_WALK__SHIFT              4
+	/* State based - direct writes to registers trigger vertex
+           generation */
+#	define	R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED         (0<<4)
+#	define	R300_VAP_VF_CNTL__PRIM_WALK_INDICES             (1<<4)
+#	define	R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST         (2<<4)
+#	define	R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED     (3<<4)
 
-#	define	R300_VAP_VF_CNTL__PRIM_WALK__SHIFT                       4
-	/* State based - direct writes to registers trigger vertex generation */
-#	define	R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED                      (0<<4)
-#	define	R300_VAP_VF_CNTL__PRIM_WALK_INDICES                          (1<<4)
-#	define	R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST                      (2<<4)
-#	define	R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED                  (3<<4)
+	/* I don't think I saw these three used.. */
+#	define	R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT            6
+#	define	R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT     9
+#	define	R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT        10
 
-		/* I don't think I saw these three used.. */
-#	define	R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT                     6
-#	define	R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT              9
-#	define	R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT                 10
-
-		/* index size - when not set the indices are assumed to be 16 bit */
-#	define	R300_VAP_VF_CNTL__INDEX_SIZE_32bit                      (1<<11)
-		/* number of vertices */
-#	define	R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT                    16
+	/* index size - when not set the indices are assumed to be 16 bit */
+#	define	R300_VAP_VF_CNTL__INDEX_SIZE_32bit              (1<<11)
+	/* number of vertices */
+#	define	R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT           16
 
 /* BEGIN: Wild guesses */
 #define R300_VAP_OUTPUT_VTX_FMT_0           0x2090
 #       define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT     (1<<0)
 #       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT   (1<<1)
-#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2)	/* GUESS */
-#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3)	/* GUESS */
-#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4)	/* GUESS */
-#       define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16)	/* GUESS */
+#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2)  /* GUESS */
+#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3)  /* GUESS */
+#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4)  /* GUESS */
+#       define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
 
 #define R300_VAP_OUTPUT_VTX_FMT_1           0x2094
+	/* each of the following is 3 bits wide, specifies number
+	   of components */
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
@@ -112,7 +123,7 @@
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
-/* END */
+/* END: Wild guesses */
 
 #define R300_SE_VTE_CNTL                  0x20b0
 #	define     R300_VPORT_X_SCALE_ENA                0x00000001
@@ -128,43 +139,54 @@
 #	define     R300_VTX_ST_DENORMALIZED              0x00001000
 
 /* BEGIN: Vertex data assembly - lots of uncertainties */
-/* gap */
-/* Where do we get our vertex data?
-//
-// Vertex data either comes either from immediate mode registers or from
-// vertex arrays.
-// There appears to be no mixed mode (though we can force the pitch of
-// vertex arrays to 0, effectively reusing the same element over and over
-// again).
-//
-// Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
-// if these registers influence vertex array processing.
-//
-// Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
-//
-// In both cases, vertex attributes are then passed through INPUT_ROUTE.
 
-// Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
-// into the vertex processor's input registers.
-// The first word routes the first input, the second word the second, etc.
-// The corresponding input is routed into the register with the given index.
-// The list is ended by a word with INPUT_ROUTE_END set.
-//
-// Always set COMPONENTS_4 in immediate mode. */
+/* gap */
+
+#define R300_VAP_CNTL_STATUS              0x2140
+#	define R300_VC_NO_SWAP                  (0 << 0)
+#	define R300_VC_16BIT_SWAP               (1 << 0)
+#	define R300_VC_32BIT_SWAP               (2 << 0)
+#	define R300_VAP_TCL_BYPASS		(1 << 8)
+
+/* gap */
+
+/* Where do we get our vertex data?
+ *
+ * Vertex data either comes either from immediate mode registers or from
+ * vertex arrays.
+ * There appears to be no mixed mode (though we can force the pitch of
+ * vertex arrays to 0, effectively reusing the same element over and over
+ * again).
+ *
+ * Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
+ * if these registers influence vertex array processing.
+ *
+ * Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
+ *
+ * In both cases, vertex attributes are then passed through INPUT_ROUTE.
+ *
+ * Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
+ * into the vertex processor's input registers.
+ * The first word routes the first input, the second word the second, etc.
+ * The corresponding input is routed into the register with the given index.
+ * The list is ended by a word with INPUT_ROUTE_END set.
+ *
+ * Always set COMPONENTS_4 in immediate mode.
+ */
 
 #define R300_VAP_INPUT_ROUTE_0_0            0x2150
 #       define R300_INPUT_ROUTE_COMPONENTS_1     (0 << 0)
 #       define R300_INPUT_ROUTE_COMPONENTS_2     (1 << 0)
 #       define R300_INPUT_ROUTE_COMPONENTS_3     (2 << 0)
 #       define R300_INPUT_ROUTE_COMPONENTS_4     (3 << 0)
-#       define R300_INPUT_ROUTE_COMPONENTS_RGBA  (4 << 0)	/* GUESS */
+#       define R300_INPUT_ROUTE_COMPONENTS_RGBA  (4 << 0) /* GUESS */
 #       define R300_VAP_INPUT_ROUTE_IDX_SHIFT    8
-#       define R300_VAP_INPUT_ROUTE_IDX_MASK     (31 << 8)	/* GUESS */
+#       define R300_VAP_INPUT_ROUTE_IDX_MASK     (31 << 8) /* GUESS */
 #       define R300_VAP_INPUT_ROUTE_END          (1 << 13)
-#       define R300_INPUT_ROUTE_IMMEDIATE_MODE   (0 << 14)	/* GUESS */
-#       define R300_INPUT_ROUTE_FLOAT            (1 << 14)	/* GUESS */
-#       define R300_INPUT_ROUTE_UNSIGNED_BYTE    (2 << 14)	/* GUESS */
-#       define R300_INPUT_ROUTE_FLOAT_COLOR      (3 << 14)	/* GUESS */
+#       define R300_INPUT_ROUTE_IMMEDIATE_MODE   (0 << 14) /* GUESS */
+#       define R300_INPUT_ROUTE_FLOAT            (1 << 14) /* GUESS */
+#       define R300_INPUT_ROUTE_UNSIGNED_BYTE    (2 << 14) /* GUESS */
+#       define R300_INPUT_ROUTE_FLOAT_COLOR      (3 << 14) /* GUESS */
 #define R300_VAP_INPUT_ROUTE_0_1            0x2154
 #define R300_VAP_INPUT_ROUTE_0_2            0x2158
 #define R300_VAP_INPUT_ROUTE_0_3            0x215C
@@ -174,10 +196,12 @@
 #define R300_VAP_INPUT_ROUTE_0_7            0x216C
 
 /* gap */
+
 /* Notes:
-//  - always set up to produce at least two attributes:
-//    if vertex program uses only position, fglrx will set normal, too
-//  - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal */
+ *  - always set up to produce at least two attributes:
+ *    if vertex program uses only position, fglrx will set normal, too
+ *  - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal.
+ */
 #define R300_VAP_INPUT_CNTL_0               0x2180
 #       define R300_INPUT_CNTL_0_COLOR           0x00000001
 #define R300_VAP_INPUT_CNTL_1               0x2184
@@ -186,20 +210,22 @@
 #       define R300_INPUT_CNTL_COLOR             0x00000004
 #       define R300_INPUT_CNTL_TC0               0x00000400
 #       define R300_INPUT_CNTL_TC1               0x00000800
-#       define R300_INPUT_CNTL_TC2               0x00001000	/* GUESS */
-#       define R300_INPUT_CNTL_TC3               0x00002000	/* GUESS */
-#       define R300_INPUT_CNTL_TC4               0x00004000	/* GUESS */
-#       define R300_INPUT_CNTL_TC5               0x00008000	/* GUESS */
-#       define R300_INPUT_CNTL_TC6               0x00010000	/* GUESS */
-#       define R300_INPUT_CNTL_TC7               0x00020000	/* GUESS */
+#       define R300_INPUT_CNTL_TC2               0x00001000 /* GUESS */
+#       define R300_INPUT_CNTL_TC3               0x00002000 /* GUESS */
+#       define R300_INPUT_CNTL_TC4               0x00004000 /* GUESS */
+#       define R300_INPUT_CNTL_TC5               0x00008000 /* GUESS */
+#       define R300_INPUT_CNTL_TC6               0x00010000 /* GUESS */
+#       define R300_INPUT_CNTL_TC7               0x00020000 /* GUESS */
 
 /* gap */
+
 /* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0
-// are set to a swizzling bit pattern, other words are 0.
-//
-// In immediate mode, the pattern is always set to xyzw. In vertex array
-// mode, the swizzling pattern is e.g. used to set zw components in texture
-// coordinates with only tweo components. */
+ * are set to a swizzling bit pattern, other words are 0.
+ *
+ * In immediate mode, the pattern is always set to xyzw. In vertex array
+ * mode, the swizzling pattern is e.g. used to set zw components in texture
+ * coordinates with only tweo components.
+ */
 #define R300_VAP_INPUT_ROUTE_1_0            0x21E0
 #       define R300_INPUT_ROUTE_SELECT_X    0
 #       define R300_INPUT_ROUTE_SELECT_Y    1
@@ -208,11 +234,11 @@
 #       define R300_INPUT_ROUTE_SELECT_ZERO 4
 #       define R300_INPUT_ROUTE_SELECT_ONE  5
 #       define R300_INPUT_ROUTE_SELECT_MASK 7
-#       define R300_INPUT_ROUTE_X_SHIFT          0
-#       define R300_INPUT_ROUTE_Y_SHIFT          3
-#       define R300_INPUT_ROUTE_Z_SHIFT          6
-#       define R300_INPUT_ROUTE_W_SHIFT          9
-#       define R300_INPUT_ROUTE_ENABLE           (15 << 12)
+#       define R300_INPUT_ROUTE_X_SHIFT     0
+#       define R300_INPUT_ROUTE_Y_SHIFT     3
+#       define R300_INPUT_ROUTE_Z_SHIFT     6
+#       define R300_INPUT_ROUTE_W_SHIFT     9
+#       define R300_INPUT_ROUTE_ENABLE      (15 << 12)
 #define R300_VAP_INPUT_ROUTE_1_1            0x21E4
 #define R300_VAP_INPUT_ROUTE_1_2            0x21E8
 #define R300_VAP_INPUT_ROUTE_1_3            0x21EC
@@ -221,79 +247,107 @@
 #define R300_VAP_INPUT_ROUTE_1_6            0x21F8
 #define R300_VAP_INPUT_ROUTE_1_7            0x21FC
 
-/* END */
+/* END: Vertex data assembly */
 
 /* gap */
-/* BEGIN: Upload vertex program and data
-// The programmable vertex shader unit has a memory bank of unknown size
-// that can be written to in 16 byte units by writing the address into
-// UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
-//
-// Pointers into the memory bank are always in multiples of 16 bytes.
-//
-// The memory bank is divided into areas with fixed meaning.
-//
-// Starting at address UPLOAD_PROGRAM: Vertex program instructions.
-// Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
-// whereas the difference between known addresses suggests size 512.
-//
-// Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
-// Native reported limits and the VPI layout suggest size 256, whereas
-// difference between known addresses suggests size 512.
-//
-// At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
-// floating point pointsize. The exact purpose of this state is uncertain,
-// as there is also the R300_RE_POINTSIZE register.
-//
-// Multiple vertex programs and parameter sets can be loaded at once,
-// which could explain the size discrepancy. */
+
+/* BEGIN: Upload vertex program and data */
+
+/*
+ * The programmable vertex shader unit has a memory bank of unknown size
+ * that can be written to in 16 byte units by writing the address into
+ * UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
+ *
+ * Pointers into the memory bank are always in multiples of 16 bytes.
+ *
+ * The memory bank is divided into areas with fixed meaning.
+ *
+ * Starting at address UPLOAD_PROGRAM: Vertex program instructions.
+ * Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
+ * whereas the difference between known addresses suggests size 512.
+ *
+ * Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
+ * Native reported limits and the VPI layout suggest size 256, whereas
+ * difference between known addresses suggests size 512.
+ *
+ * At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
+ * floating point pointsize. The exact purpose of this state is uncertain,
+ * as there is also the R300_RE_POINTSIZE register.
+ *
+ * Multiple vertex programs and parameter sets can be loaded at once,
+ * which could explain the size discrepancy.
+ */
 #define R300_VAP_PVS_UPLOAD_ADDRESS         0x2200
 #       define R300_PVS_UPLOAD_PROGRAM           0x00000000
 #       define R300_PVS_UPLOAD_PARAMETERS        0x00000200
 #       define R300_PVS_UPLOAD_POINTSIZE         0x00000406
-/* gap */
-#define R300_VAP_PVS_UPLOAD_DATA            0x2208
-/* END */
 
 /* gap */
+
+#define R300_VAP_PVS_UPLOAD_DATA            0x2208
+
+/* END: Upload vertex program and data */
+
+/* gap */
+
 /* I do not know the purpose of this register. However, I do know that
-// it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
-// for normal rendering. */
+ * it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
+ * for normal rendering.
+ */
 #define R300_VAP_UNKNOWN_221C               0x221C
 #       define R300_221C_NORMAL                  0x00000000
 #       define R300_221C_CLEAR                   0x0001C000
 
+/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first
+ * plane is per-pixel and the second plane is per-vertex.
+ *
+ * This was determined by experimentation alone but I believe it is correct.
+ *
+ * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest.
+ */
+#define R300_VAP_CLIP_X_0                   0x2220
+#define R300_VAP_CLIP_X_1                   0x2224
+#define R300_VAP_CLIP_Y_0                   0x2228
+#define R300_VAP_CLIP_Y_1                   0x2230
+
 /* gap */
+
 /* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
-// rendering commands and overwriting vertex program parameters.
-// Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
-// avoids bugs caused by still running shaders reading bad data from memory. */
-#define R300_VAP_PVS_WAITIDLE               0x2284	/* GUESS */
+ * rendering commands and overwriting vertex program parameters.
+ * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
+ * avoids bugs caused by still running shaders reading bad data from memory.
+ */
+#define R300_VAP_PVS_WAITIDLE               0x2284 /* GUESS */
 
 /* Absolutely no clue what this register is about. */
 #define R300_VAP_UNKNOWN_2288               0x2288
-#       define R300_2288_R300                    0x00750000	/* -- nh */
-#       define R300_2288_RV350                   0x0000FFFF	/* -- Vladimir */
+#       define R300_2288_R300                    0x00750000 /* -- nh */
+#       define R300_2288_RV350                   0x0000FFFF /* -- Vladimir */
 
 /* gap */
+
 /* Addresses are relative to the vertex program instruction area of the
-// memory bank. PROGRAM_END points to the last instruction of the active
-// program
-//
-// The meaning of the two UNKNOWN fields is obviously not known. However,
-// experiments so far have shown that both *must* point to an instruction
-// inside the vertex program, otherwise the GPU locks up.
-// fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
-// CNTL_1_UNKNOWN points to instruction where last write to position takes place.
-// Most likely this is used to ignore rest of the program in cases where group of verts arent visible.
-// For some reason this "section" is sometimes accepted other instruction that have
-// no relationship with position calculations.
-*/
+ * memory bank. PROGRAM_END points to the last instruction of the active
+ * program
+ *
+ * The meaning of the two UNKNOWN fields is obviously not known. However,
+ * experiments so far have shown that both *must* point to an instruction
+ * inside the vertex program, otherwise the GPU locks up.
+ *
+ * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
+ * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to
+ * position takes place.
+ *
+ * Most likely this is used to ignore rest of the program in cases
+ * where group of verts arent visible. For some reason this "section"
+ * is sometimes accepted other instruction that have no relationship with
+ * position calculations.
+ */
 #define R300_VAP_PVS_CNTL_1                 0x22D0
 #       define R300_PVS_CNTL_1_PROGRAM_START_SHIFT   0
 #       define R300_PVS_CNTL_1_POS_END_SHIFT         10
 #       define R300_PVS_CNTL_1_PROGRAM_END_SHIFT     20
-/* Addresses are relative to the vertex program parameters area. */
+/* Addresses are relative the the vertex program parameters area. */
 #define R300_VAP_PVS_CNTL_2                 0x22D4
 #       define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
 #       define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT  16
@@ -302,23 +356,26 @@
 #       define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0
 
 /* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
-// immediate vertices */
+ * immediate vertices
+ */
 #define R300_VAP_VTX_COLOR_R                0x2464
 #define R300_VAP_VTX_COLOR_G                0x2468
 #define R300_VAP_VTX_COLOR_B                0x246C
-#define R300_VAP_VTX_POS_0_X_1              0x2490	/* used for glVertex2*() */
+#define R300_VAP_VTX_POS_0_X_1              0x2490 /* used for glVertex2*() */
 #define R300_VAP_VTX_POS_0_Y_1              0x2494
-#define R300_VAP_VTX_COLOR_PKD              0x249C	/* RGBA */
-#define R300_VAP_VTX_POS_0_X_2              0x24A0	/* used for glVertex3*() */
+#define R300_VAP_VTX_COLOR_PKD              0x249C /* RGBA */
+#define R300_VAP_VTX_POS_0_X_2              0x24A0 /* used for glVertex3*() */
 #define R300_VAP_VTX_POS_0_Y_2              0x24A4
 #define R300_VAP_VTX_POS_0_Z_2              0x24A8
-#define R300_VAP_VTX_END_OF_PKT             0x24AC	/* write 0 to indicate end of packet? */
+/* write 0 to indicate end of packet? */
+#define R300_VAP_VTX_END_OF_PKT             0x24AC
 
 /* gap */
 
 /* These are values from r300_reg/r300_reg.h - they are known to be correct
-   and are here so we can use one register file instead of several
-   - Vladimir */
+ * and are here so we can use one register file instead of several
+ * - Vladimir
+ */
 #define R300_GB_VAP_RASTER_VTX_FMT_0	0x4000
 #	define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT	(1<<0)
 #	define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT	(1<<1)
@@ -341,14 +398,16 @@
 #	define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT	21
 
 /* UNK30 seems to enables point to quad transformation on textures
-   (or something closely related to that).
-   This bit is rather fatal at the time being due to lackings at pixel shader side */
+ * (or something closely related to that).
+ * This bit is rather fatal at the time being due to lackings at pixel
+ * shader side
+ */
 #define R300_GB_ENABLE	0x4008
 #	define R300_GB_POINT_STUFF_ENABLE	(1<<0)
 #	define R300_GB_LINE_STUFF_ENABLE	(1<<1)
 #	define R300_GB_TRIANGLE_STUFF_ENABLE	(1<<2)
 #	define R300_GB_STENCIL_AUTO_ENABLE	(1<<4)
-#	define R300_GB_UNK30			(1<<30)
+#	define R300_GB_UNK31			(1<<31)
 	/* each of the following is 2 bits wide */
 #define R300_GB_TEX_REPLICATE	0
 #define R300_GB_TEX_ST		1
@@ -383,11 +442,13 @@
 #	define R300_GB_MSPOS1__MS_Y5_SHIFT	20
 #	define R300_GB_MSPOS1__MSBD1		24
 
+
 #define R300_GB_TILE_CONFIG	0x4018
 #	define R300_GB_TILE_ENABLE	(1<<0)
 #	define R300_GB_TILE_PIPE_COUNT_RV300	0
 #	define R300_GB_TILE_PIPE_COUNT_R300	(3<<1)
 #	define R300_GB_TILE_PIPE_COUNT_R420	(7<<1)
+#	define R300_GB_TILE_PIPE_COUNT_RV410	(3<<1)
 #	define R300_GB_TILE_SIZE_8		0
 #	define R300_GB_TILE_SIZE_16		(1<<4)
 #	define R300_GB_TILE_SIZE_32		(2<<4)
@@ -442,17 +503,18 @@
 #	define R300_GB_W_SELECT_1		(1<<4)
 
 #define R300_GB_AA_CONFIG		0x4020
+#	define R300_AA_DISABLE			0x00
 #	define R300_AA_ENABLE			0x01
 #	define R300_AA_SUBSAMPLES_2		0
 #	define R300_AA_SUBSAMPLES_3		(1<<1)
 #	define R300_AA_SUBSAMPLES_4		(2<<1)
 #	define R300_AA_SUBSAMPLES_6		(3<<1)
 
-/* END */
-
 /* gap */
+
 /* Zero to flush caches. */
 #define R300_TX_CNTL                        0x4100
+#define R300_TX_FLUSH                       0x0
 
 /* The upper enable bits are guessed, based on fglrx reported limits. */
 #define R300_TX_ENABLE                      0x4104
@@ -474,24 +536,25 @@
 #       define R300_TX_ENABLE_15                 (1 << 15)
 
 /* The pointsize is given in multiples of 6. The pointsize can be
-// enormous: Clear() renders a single point that fills the entire
-// framebuffer. */
+ * enormous: Clear() renders a single point that fills the entire
+ * framebuffer.
+ */
 #define R300_RE_POINTSIZE                   0x421C
 #       define R300_POINTSIZE_Y_SHIFT            0
-#       define R300_POINTSIZE_Y_MASK             (0xFFFF << 0)	/* GUESS */
+#       define R300_POINTSIZE_Y_MASK             (0xFFFF << 0) /* GUESS */
 #       define R300_POINTSIZE_X_SHIFT            16
-#       define R300_POINTSIZE_X_MASK             (0xFFFF << 16)	/* GUESS */
+#       define R300_POINTSIZE_X_MASK             (0xFFFF << 16) /* GUESS */
 #       define R300_POINTSIZE_MAX             (R300_POINTSIZE_Y_MASK / 6)
 
 /* The line width is given in multiples of 6.
-   In default mode lines are classified as vertical lines.
-   HO: horizontal
-   VE: vertical or horizontal
-   HO & VE: no classification
-*/
+ * In default mode lines are classified as vertical lines.
+ * HO: horizontal
+ * VE: vertical or horizontal
+ * HO & VE: no classification
+ */
 #define R300_RE_LINE_CNT                      0x4234
 #       define R300_LINESIZE_SHIFT            0
-#       define R300_LINESIZE_MASK             (0xFFFF << 0)	/* GUESS */
+#       define R300_LINESIZE_MASK             (0xFFFF << 0) /* GUESS */
 #       define R300_LINESIZE_MAX             (R300_LINESIZE_MASK / 6)
 #       define R300_LINE_CNT_HO               (1 << 16)
 #       define R300_LINE_CNT_VE               (1 << 17)
@@ -499,6 +562,9 @@
 /* Some sort of scale or clamp value for texcoordless textures. */
 #define R300_RE_UNK4238                       0x4238
 
+/* Something shade related */
+#define R300_RE_SHADE                         0x4274
+
 #define R300_RE_SHADE_MODEL                   0x4278
 #	define R300_RE_SHADE_MODEL_SMOOTH     0x3aaaa
 #	define R300_RE_SHADE_MODEL_FLAT       0x39595
@@ -513,24 +579,31 @@
 #	define R300_PM_BACK_LINE              (1 << 7)
 #	define R300_PM_BACK_FILL              (1 << 8)
 
+/* Fog parameters */
+#define R300_RE_FOG_SCALE                     0x4294
+#define R300_RE_FOG_START                     0x4298
+
 /* Not sure why there are duplicate of factor and constant values.
-   My best guess so far is that there are seperate zbiases for test and write.
-   Ordering might be wrong.
-   Some of the tests indicate that fgl has a fallback implementation of zbias
-   via pixel shaders. */
+ * My best guess so far is that there are seperate zbiases for test and write.
+ * Ordering might be wrong.
+ * Some of the tests indicate that fgl has a fallback implementation of zbias
+ * via pixel shaders.
+ */
+#define R300_RE_ZBIAS_CNTL                    0x42A0 /* GUESS */
 #define R300_RE_ZBIAS_T_FACTOR                0x42A4
 #define R300_RE_ZBIAS_T_CONSTANT              0x42A8
 #define R300_RE_ZBIAS_W_FACTOR                0x42AC
 #define R300_RE_ZBIAS_W_CONSTANT              0x42B0
 
 /* This register needs to be set to (1<<1) for RV350 to correctly
-   perform depth test (see --vb-triangles in r300_demo)
-   Don't know about other chips. - Vladimir
-   This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
-   My guess is that there are two bits for each zbias primitive (FILL, LINE, POINT).
-   One to enable depth test and one for depth write.
-   Yet this doesnt explain why depth writes work ...
-    */
+ * perform depth test (see --vb-triangles in r300_demo)
+ * Don't know about other chips. - Vladimir
+ * This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
+ * My guess is that there are two bits for each zbias primitive
+ * (FILL, LINE, POINT).
+ *  One to enable depth test and one for depth write.
+ * Yet this doesnt explain why depth writes work ...
+ */
 #define R300_RE_OCCLUSION_CNTL		    0x42B4
 #	define R300_OCCLUSION_ON		(1<<1)
 
@@ -540,30 +613,38 @@
 #       define R300_FRONT_FACE_CCW               (0 << 2)
 #       define R300_FRONT_FACE_CW                (1 << 2)
 
-/* BEGIN: Rasterization / Interpolators - many guesses
-// 0_UNKNOWN_18 has always been set except for clear operations.
-// TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
-// on the vertex program, *not* the fragment program) */
+
+/* BEGIN: Rasterization / Interpolators - many guesses */
+
+/* 0_UNKNOWN_18 has always been set except for clear operations.
+ * TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
+ * on the vertex program, *not* the fragment program)
+ */
 #define R300_RS_CNTL_0                      0x4300
 #       define R300_RS_CNTL_TC_CNT_SHIFT         2
 #       define R300_RS_CNTL_TC_CNT_MASK          (7 << 2)
-#		define R300_RS_CNTL_CI_CNT_SHIFT         7	/* number of color interpolators used */
+	/* number of color interpolators used */
+#	define R300_RS_CNTL_CI_CNT_SHIFT         7
 #       define R300_RS_CNTL_0_UNKNOWN_18         (1 << 18)
-/* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n register. */
+	/* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n
+	   register. */
 #define R300_RS_CNTL_1                      0x4304
 
 /* gap */
+
 /* Only used for texture coordinates.
-// Use the source field to route texture coordinate input from the vertex program
-// to the desired interpolator. Note that the source field is relative to the
-// outputs the vertex program *actually* writes. If a vertex program only writes
-// texcoord[1], this will be source index 0.
-// Set INTERP_USED on all interpolators that produce data used by the
-// fragment program. INTERP_USED looks like a swizzling mask, but
-// I haven't seen it used that way.
-//
-// Note: The _UNKNOWN constants are always set in their respective register.
-// I don't know if this is necessary. */
+ * Use the source field to route texture coordinate input from the
+ * vertex program to the desired interpolator. Note that the source
+ * field is relative to the outputs the vertex program *actually*
+ * writes. If a vertex program only writes texcoord[1], this will
+ * be source index 0.
+ * Set INTERP_USED on all interpolators that produce data used by
+ * the fragment program. INTERP_USED looks like a swizzling mask,
+ * but I haven't seen it used that way.
+ *
+ * Note: The _UNKNOWN constants are always set in their respective
+ * register. I don't know if this is necessary.
+ */
 #define R300_RS_INTERP_0                    0x4310
 #define R300_RS_INTERP_1                    0x4314
 #       define R300_RS_INTERP_1_UNKNOWN          0x40
@@ -580,54 +661,63 @@
 #       define R300_RS_INTERP_USED               0x00D10000
 
 /* These DWORDs control how vertex data is routed into fragment program
-// registers, after interpolators. */
+ * registers, after interpolators.
+ */
 #define R300_RS_ROUTE_0                     0x4330
 #define R300_RS_ROUTE_1                     0x4334
 #define R300_RS_ROUTE_2                     0x4338
-#define R300_RS_ROUTE_3                     0x433C	/* GUESS */
-#define R300_RS_ROUTE_4                     0x4340	/* GUESS */
-#define R300_RS_ROUTE_5                     0x4344	/* GUESS */
-#define R300_RS_ROUTE_6                     0x4348	/* GUESS */
-#define R300_RS_ROUTE_7                     0x434C	/* GUESS */
+#define R300_RS_ROUTE_3                     0x433C /* GUESS */
+#define R300_RS_ROUTE_4                     0x4340 /* GUESS */
+#define R300_RS_ROUTE_5                     0x4344 /* GUESS */
+#define R300_RS_ROUTE_6                     0x4348 /* GUESS */
+#define R300_RS_ROUTE_7                     0x434C /* GUESS */
 #       define R300_RS_ROUTE_SOURCE_INTERP_0     0
 #       define R300_RS_ROUTE_SOURCE_INTERP_1     1
 #       define R300_RS_ROUTE_SOURCE_INTERP_2     2
 #       define R300_RS_ROUTE_SOURCE_INTERP_3     3
 #       define R300_RS_ROUTE_SOURCE_INTERP_4     4
-#       define R300_RS_ROUTE_SOURCE_INTERP_5     5	/* GUESS */
-#       define R300_RS_ROUTE_SOURCE_INTERP_6     6	/* GUESS */
-#       define R300_RS_ROUTE_SOURCE_INTERP_7     7	/* GUESS */
-#       define R300_RS_ROUTE_ENABLE              (1 << 3)	/* GUESS */
+#       define R300_RS_ROUTE_SOURCE_INTERP_5     5 /* GUESS */
+#       define R300_RS_ROUTE_SOURCE_INTERP_6     6 /* GUESS */
+#       define R300_RS_ROUTE_SOURCE_INTERP_7     7 /* GUESS */
+#       define R300_RS_ROUTE_ENABLE              (1 << 3) /* GUESS */
 #       define R300_RS_ROUTE_DEST_SHIFT          6
-#       define R300_RS_ROUTE_DEST_MASK           (31 << 6)	/* GUESS */
+#       define R300_RS_ROUTE_DEST_MASK           (31 << 6) /* GUESS */
 
 /* Special handling for color: When the fragment program uses color,
-// the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
-// color register index. */
+ * the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
+ * color register index.
+ *
+ * Apperently you may set the R300_RS_ROUTE_0_COLOR bit, but not provide any
+ * R300_RS_ROUTE_0_COLOR_DEST value; this setup is used for clearing the state.
+ * See r300_ioctl.c:r300EmitClearState. I'm not sure if this setup is strictly
+ * correct or not. - Oliver.
+ */
 #       define R300_RS_ROUTE_0_COLOR             (1 << 14)
 #       define R300_RS_ROUTE_0_COLOR_DEST_SHIFT  17
-#       define R300_RS_ROUTE_0_COLOR_DEST_MASK   (31 << 17)	/* GUESS */
+#       define R300_RS_ROUTE_0_COLOR_DEST_MASK   (31 << 17) /* GUESS */
 /* As above, but for secondary color */
 #		define R300_RS_ROUTE_1_COLOR1            (1 << 14)
 #		define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17
 #		define R300_RS_ROUTE_1_COLOR1_DEST_MASK  (31 << 17)
 #		define R300_RS_ROUTE_1_UNKNOWN11         (1 << 11)
-/* END */
+/* END: Rasterization / Interpolators - many guesses */
 
-/* BEGIN: Scissors and cliprects
-// There are four clipping rectangles. Their corner coordinates are inclusive.
-// Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
-// on whether the pixel is inside cliprects 0-3, respectively. For example,
-// if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
-// the number 3 (binary 0011).
-// Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
-// the pixel is rasterized.
-//
-// In addition to this, there is a scissors rectangle. Only pixels inside the
-// scissors rectangle are drawn. (coordinates are inclusive)
-//
-// For some reason, the top-left corner of the framebuffer is at (1440, 1440)
-// for the purpose of clipping and scissors. */
+/* BEGIN: Scissors and cliprects */
+
+/* There are four clipping rectangles. Their corner coordinates are inclusive.
+ * Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
+ * on whether the pixel is inside cliprects 0-3, respectively. For example,
+ * if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
+ * the number 3 (binary 0011).
+ * Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
+ * the pixel is rasterized.
+ *
+ * In addition to this, there is a scissors rectangle. Only pixels inside the
+ * scissors rectangle are drawn. (coordinates are inclusive)
+ *
+ * For some reason, the top-left corner of the framebuffer is at (1440, 1440)
+ * for the purpose of clipping and scissors.
+ */
 #define R300_RE_CLIPRECT_TL_0               0x43B0
 #define R300_RE_CLIPRECT_BR_0               0x43B4
 #define R300_RE_CLIPRECT_TL_1               0x43B8
@@ -661,6 +751,7 @@
 #       define R300_CLIP_3210                    (1 << 15)
 
 /* gap */
+
 #define R300_RE_SCISSORS_TL                 0x43E0
 #define R300_RE_SCISSORS_BR                 0x43E4
 #       define R300_SCISSORS_OFFSET              1440
@@ -668,12 +759,15 @@
 #       define R300_SCISSORS_X_MASK              (0x1FFF << 0)
 #       define R300_SCISSORS_Y_SHIFT             13
 #       define R300_SCISSORS_Y_MASK              (0x1FFF << 13)
-/* END */
+/* END: Scissors and cliprects */
 
-/* BEGIN: Texture specification
-// The texture specification dwords are grouped by meaning and not by texture unit.
-// This means that e.g. the offset for texture image unit N is found in register
-// TX_OFFSET_0 + (4*N) */
+/* BEGIN: Texture specification */
+
+/*
+ * The texture specification dwords are grouped by meaning and not by texture
+ * unit. This means that e.g. the offset for texture image unit N is found in
+ * register TX_OFFSET_0 + (4*N)
+ */
 #define R300_TX_FILTER_0                    0x4400
 #       define R300_TX_REPEAT                    0
 #       define R300_TX_MIRRORED                  1
@@ -697,13 +791,14 @@
 #	define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR         (10 <<  11)
 
 /* NOTE: NEAREST doesnt seem to exist.
-   Im not seting MAG_FILTER_MASK and (3 << 11) on for all
-   anisotropy modes because that would void selected mag filter */
-#	define R300_TX_MIN_FILTER_ANISO_NEAREST             ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-#	define R300_TX_MIN_FILTER_ANISO_LINEAR              ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-#	define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST ((1 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-#	define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR  ((2 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-#       define R300_TX_MIN_FILTER_MASK           ( (15 << 11) | (3 << 13) )
+ * Im not seting MAG_FILTER_MASK and (3 << 11) on for all
+ * anisotropy modes because that would void selected mag filter
+ */
+#	define R300_TX_MIN_FILTER_ANISO_NEAREST             (0 << 13)
+#	define R300_TX_MIN_FILTER_ANISO_LINEAR              (0 << 13)
+#	define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (1 << 13)
+#	define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR  (2 << 13)
+#       define R300_TX_MIN_FILTER_MASK   ( (15 << 11) | (3 << 13) )
 #	define R300_TX_MAX_ANISO_1_TO_1  (0 << 21)
 #	define R300_TX_MAX_ANISO_2_TO_1  (2 << 21)
 #	define R300_TX_MAX_ANISO_4_TO_1  (4 << 21)
@@ -734,10 +829,10 @@
 #       define R300_TX_HEIGHTMASK_SHIFT          11
 #       define R300_TX_HEIGHTMASK_MASK           (2047 << 11)
 #       define R300_TX_UNK23                     (1 << 23)
-#       define R300_TX_SIZE_SHIFT                26	/* largest of width, height */
-#       define R300_TX_SIZE_MASK                 (15 << 26)
-#       define R300_TX_SIZE_PROJECTED                     (1<<30)
-#       define R300_TX_SIZE_TXPITCH_EN                     (1<<31)
+#       define R300_TX_MAX_MIP_LEVEL_SHIFT       26
+#       define R300_TX_MAX_MIP_LEVEL_MASK        (0xf << 26)
+#       define R300_TX_SIZE_PROJECTED            (1<<30)
+#       define R300_TX_SIZE_TXPITCH_EN           (1<<31)
 #define R300_TX_FORMAT_0                    0x44C0
 	/* The interpretation of the format word by Wladimir van der Laan */
 	/* The X, Y, Z and W refer to the layout of the components.
@@ -761,11 +856,11 @@
 #	define R300_TX_FORMAT_DXT1	    	    0xF
 #	define R300_TX_FORMAT_DXT3	    	    0x10
 #	define R300_TX_FORMAT_DXT5	    	    0x11
-#	define R300_TX_FORMAT_D3DMFT_CxV8U8	    0x12	/* no swizzle */
-#	define R300_TX_FORMAT_A8R8G8B8	    	    0x13	/* no swizzle */
-#	define R300_TX_FORMAT_B8G8_B8G8	    	    0x14	/* no swizzle */
-#	define R300_TX_FORMAT_G8R8_G8B8	    	    0x15	/* no swizzle */
-						  /* 0x16 - some 16 bit green format.. ?? */
+#	define R300_TX_FORMAT_D3DMFT_CxV8U8	    0x12     /* no swizzle */
+#	define R300_TX_FORMAT_A8R8G8B8	    	    0x13     /* no swizzle */
+#	define R300_TX_FORMAT_B8G8_B8G8	    	    0x14     /* no swizzle */
+#	define R300_TX_FORMAT_G8R8_G8B8	    	    0x15     /* no swizzle */
+	/* 0x16 - some 16 bit green format.. ?? */
 #	define R300_TX_FORMAT_UNK25		   (1 << 25) /* no swizzle */
 #	define R300_TX_FORMAT_CUBIC_MAP		   (1 << 26)
 
@@ -793,23 +888,26 @@
 #	define R300_TX_FORMAT_W		3
 #	define R300_TX_FORMAT_ZERO	4
 #	define R300_TX_FORMAT_ONE	5
-#	define R300_TX_FORMAT_CUT_Z	6	/* 2.0*Z, everything above 1.0 is set to 0.0 */
-#	define R300_TX_FORMAT_CUT_W	7	/* 2.0*W, everything above 1.0 is set to 0.0 */
+	/* 2.0*Z, everything above 1.0 is set to 0.0 */
+#	define R300_TX_FORMAT_CUT_Z	6
+	/* 2.0*W, everything above 1.0 is set to 0.0 */
+#	define R300_TX_FORMAT_CUT_W	7
 
 #	define R300_TX_FORMAT_B_SHIFT	18
 #	define R300_TX_FORMAT_G_SHIFT	15
 #	define R300_TX_FORMAT_R_SHIFT	12
 #	define R300_TX_FORMAT_A_SHIFT	9
 	/* Convenience macro to take care of layout and swizzling */
-#	define R300_EASY_TX_FORMAT(B, G, R, A, FMT)	(\
-	  ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \
-	| ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \
-	| ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \
-	| ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \
-	| (R300_TX_FORMAT_##FMT) \
-	  )
-	/* These can be ORed with result of R300_EASY_TX_FORMAT() */
-	/* We don't really know what they do. Take values from a constant color ? */
+#	define R300_EASY_TX_FORMAT(B, G, R, A, FMT)	(		\
+		((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT)		\
+		| ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT)	\
+		| ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT)	\
+		| ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT)	\
+		| (R300_TX_FORMAT_##FMT)				\
+		)
+	/* These can be ORed with result of R300_EASY_TX_FORMAT()
+	   We don't really know what they do. Take values from a
+           constant color ? */
 #	define R300_TX_FORMAT_CONST_X		(1<<5)
 #	define R300_TX_FORMAT_CONST_Y		(2<<5)
 #	define R300_TX_FORMAT_CONST_Z		(4<<5)
@@ -819,7 +917,7 @@
 
 #define R300_TX_PITCH_0			    0x4500 /* obvious missing in gap */
 #define R300_TX_OFFSET_0                    0x4540
-/* BEGIN: Guess from R200 */
+	/* BEGIN: Guess from R200 */
 #       define R300_TXO_ENDIAN_NO_SWAP           (0 << 0)
 #       define R300_TXO_ENDIAN_BYTE_SWAP         (1 << 0)
 #       define R300_TXO_ENDIAN_WORD_SWAP         (2 << 0)
@@ -828,53 +926,61 @@
 #       define R300_TXO_MICRO_TILE               (1 << 3)
 #       define R300_TXO_OFFSET_MASK              0xffffffe0
 #       define R300_TXO_OFFSET_SHIFT             5
-/* END */
-#define R300_TX_CHROMA_KEY_0                      0x4580 /* 32 bit chroma key */
-#define R300_TX_BORDER_COLOR_0              0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 }
+	/* END: Guess from R200 */
 
-/* END */
+/* 32 bit chroma key */
+#define R300_TX_CHROMA_KEY_0                      0x4580
+/* ff00ff00 == { 0, 1.0, 0, 1.0 } */
+#define R300_TX_BORDER_COLOR_0              0x45C0
 
-/* BEGIN: Fragment program instruction set
-// Fragment programs are written directly into register space.
-// There are separate instruction streams for texture instructions and ALU
-// instructions.
-// In order to synchronize these streams, the program is divided into up
-// to 4 nodes. Each node begins with a number of TEX operations, followed
-// by a number of ALU operations.
-// The first node can have zero TEX ops, all subsequent nodes must have at least
-// one TEX ops.
-// All nodes must have at least one ALU op.
-//
-// The index of the last node is stored in PFS_CNTL_0: A value of 0 means
-// 1 node, a value of 3 means 4 nodes.
-// The total amount of instructions is defined in PFS_CNTL_2. The offsets are
-// offsets into the respective instruction streams, while *_END points to the
-// last instruction relative to this offset. */
+/* END: Texture specification */
+
+/* BEGIN: Fragment program instruction set */
+
+/* Fragment programs are written directly into register space.
+ * There are separate instruction streams for texture instructions and ALU
+ * instructions.
+ * In order to synchronize these streams, the program is divided into up
+ * to 4 nodes. Each node begins with a number of TEX operations, followed
+ * by a number of ALU operations.
+ * The first node can have zero TEX ops, all subsequent nodes must have at
+ * least
+ * one TEX ops.
+ * All nodes must have at least one ALU op.
+ *
+ * The index of the last node is stored in PFS_CNTL_0: A value of 0 means
+ * 1 node, a value of 3 means 4 nodes.
+ * The total amount of instructions is defined in PFS_CNTL_2. The offsets are
+ * offsets into the respective instruction streams, while *_END points to the
+ * last instruction relative to this offset.
+ */
 #define R300_PFS_CNTL_0                     0x4600
 #       define R300_PFS_CNTL_LAST_NODES_SHIFT    0
 #       define R300_PFS_CNTL_LAST_NODES_MASK     (3 << 0)
 #       define R300_PFS_CNTL_FIRST_NODE_HAS_TEX  (1 << 3)
 #define R300_PFS_CNTL_1                     0x4604
 /* There is an unshifted value here which has so far always been equal to the
-// index of the highest used temporary register. */
+ * index of the highest used temporary register.
+ */
 #define R300_PFS_CNTL_2                     0x4608
 #       define R300_PFS_CNTL_ALU_OFFSET_SHIFT    0
 #       define R300_PFS_CNTL_ALU_OFFSET_MASK     (63 << 0)
 #       define R300_PFS_CNTL_ALU_END_SHIFT       6
-#       define R300_PFS_CNTL_ALU_END_MASK        (63 << 0)
+#       define R300_PFS_CNTL_ALU_END_MASK        (63 << 6)
 #       define R300_PFS_CNTL_TEX_OFFSET_SHIFT    12
-#       define R300_PFS_CNTL_TEX_OFFSET_MASK     (31 << 12)	/* GUESS */
+#       define R300_PFS_CNTL_TEX_OFFSET_MASK     (31 << 12) /* GUESS */
 #       define R300_PFS_CNTL_TEX_END_SHIFT       18
-#       define R300_PFS_CNTL_TEX_END_MASK        (31 << 18)	/* GUESS */
+#       define R300_PFS_CNTL_TEX_END_MASK        (31 << 18) /* GUESS */
 
 /* gap */
+
 /* Nodes are stored backwards. The last active node is always stored in
-// PFS_NODE_3.
-// Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
-// first node is stored in NODE_2, the second node is stored in NODE_3.
-//
-// Offsets are relative to the master offset from PFS_CNTL_2.
-// LAST_NODE is set for the last node, and only for the last node. */
+ * PFS_NODE_3.
+ * Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
+ * first node is stored in NODE_2, the second node is stored in NODE_3.
+ *
+ * Offsets are relative to the master offset from PFS_CNTL_2.
+ */
 #define R300_PFS_NODE_0                     0x4610
 #define R300_PFS_NODE_1                     0x4614
 #define R300_PFS_NODE_2                     0x4618
@@ -887,91 +993,98 @@
 #       define R300_PFS_NODE_TEX_OFFSET_MASK     (31 << 12)
 #       define R300_PFS_NODE_TEX_END_SHIFT       17
 #       define R300_PFS_NODE_TEX_END_MASK        (31 << 17)
-/*#       define R300_PFS_NODE_LAST_NODE           (1 << 22) */
 #		define R300_PFS_NODE_OUTPUT_COLOR        (1 << 22)
 #		define R300_PFS_NODE_OUTPUT_DEPTH        (1 << 23)
 
 /* TEX
-// As far as I can tell, texture instructions cannot write into output
-// registers directly. A subsequent ALU instruction is always necessary,
-// even if it's just MAD o0, r0, 1, 0 */
+ * As far as I can tell, texture instructions cannot write into output
+ * registers directly. A subsequent ALU instruction is always necessary,
+ * even if it's just MAD o0, r0, 1, 0
+ */
 #define R300_PFS_TEXI_0                     0x4620
-#       define R300_FPITX_SRC_SHIFT              0
-#       define R300_FPITX_SRC_MASK               (31 << 0)
-#       define R300_FPITX_SRC_CONST              (1 << 5)	/* GUESS */
-#       define R300_FPITX_DST_SHIFT              6
-#       define R300_FPITX_DST_MASK               (31 << 6)
-#       define R300_FPITX_IMAGE_SHIFT            11
-#       define R300_FPITX_IMAGE_MASK             (15 << 11)	/* GUESS based on layout and native limits */
+#	define R300_FPITX_SRC_SHIFT              0
+#	define R300_FPITX_SRC_MASK               (31 << 0)
+	/* GUESS */
+#	define R300_FPITX_SRC_CONST              (1 << 5)
+#	define R300_FPITX_DST_SHIFT              6
+#	define R300_FPITX_DST_MASK               (31 << 6)
+#	define R300_FPITX_IMAGE_SHIFT            11
+	/* GUESS based on layout and native limits */
+#       define R300_FPITX_IMAGE_MASK             (15 << 11)
 /* Unsure if these are opcodes, or some kind of bitfield, but this is how
  * they were set when I checked
  */
-#		define R300_FPITX_OPCODE_SHIFT			15
-#			define R300_FPITX_OP_TEX			1
-#			define R300_FPITX_OP_KIL			2
-#			define R300_FPITX_OP_TXP			3
-#			define R300_FPITX_OP_TXB			4
+#	define R300_FPITX_OPCODE_SHIFT		15
+#		define R300_FPITX_OP_TEX	1
+#		define R300_FPITX_OP_KIL	2
+#		define R300_FPITX_OP_TXP	3
+#		define R300_FPITX_OP_TXB	4
+#	define R300_FPITX_OPCODE_MASK           (7 << 15)
 
 /* ALU
-// The ALU instructions register blocks are enumerated according to the order
-// in which fglrx. I assume there is space for 64 instructions, since
-// each block has space for a maximum of 64 DWORDs, and this matches reported
-// native limits.
-//
-// The basic functional block seems to be one MAD for each color and alpha,
-// and an adder that adds all components after the MUL.
-//  - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
-//  - DP4: Use OUTC_DP4, OUTA_DP4
-//  - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
-//  - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
-//  - CMP: If ARG2 < 0, return ARG1, else return ARG0
-//  - FLR: use FRC+MAD
-//  - XPD: use MAD+MAD
-//  - SGE, SLT: use MAD+CMP
-//  - RSQ: use ABS modifier for argument
-//  - Use OUTC_REPL_ALPHA to write results of an alpha-only operation (e.g. RCP)
-//    into color register
-//  - apparently, there's no quick DST operation
-//  - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
-//  - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
-//  - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
-//
-// Operand selection
-// First stage selects three sources from the available registers and
-// constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
-// fglrx sorts the three source fields: Registers before constants,
-// lower indices before higher indices; I do not know whether this is necessary.
-// fglrx fills unused sources with "read constant 0"
-// According to specs, you cannot select more than two different constants.
-//
-// Second stage selects the operands from the sources. This is defined in
-// INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
-// zero and one.
-// Swizzling and negation happens in this stage, as well.
-//
-// Important: Color and alpha seem to be mostly separate, i.e. their sources
-// selection appears to be fully independent (the register storage is probably
-// physically split into a color and an alpha section).
-// However (because of the apparent physical split), there is some interaction
-// WRT swizzling. If, for example, you want to load an R component into an
-// Alpha operand, this R component is taken from a *color* source, not from
-// an alpha source. The corresponding register doesn't even have to appear in
-// the alpha sources list. (I hope this alll makes sense to you)
-//
-// Destination selection
-// The destination register index is in FPI1 (color) and FPI3 (alpha) together
-// with enable bits.
-// There are separate enable bits for writing into temporary registers
-// (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_* /DSTA_OUTPUT).
-// You can write to both at once, or not write at all (the same index
-// must be used for both).
-//
-// Note: There is a special form for LRP
-//  - Argument order is the same as in ARB_fragment_program.
-//  - Operation is MAD
-//  - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
-//  - Set FPI0/FPI2_SPECIAL_LRP
-// Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD */
+ * The ALU instructions register blocks are enumerated according to the order
+ * in which fglrx. I assume there is space for 64 instructions, since
+ * each block has space for a maximum of 64 DWORDs, and this matches reported
+ * native limits.
+ *
+ * The basic functional block seems to be one MAD for each color and alpha,
+ * and an adder that adds all components after the MUL.
+ *  - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
+ *  - DP4: Use OUTC_DP4, OUTA_DP4
+ *  - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
+ *  - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
+ *  - CMPH: If ARG2 > 0.5, return ARG0, else return ARG1
+ *  - CMP: If ARG2 < 0, return ARG1, else return ARG0
+ *  - FLR: use FRC+MAD
+ *  - XPD: use MAD+MAD
+ *  - SGE, SLT: use MAD+CMP
+ *  - RSQ: use ABS modifier for argument
+ *  - Use OUTC_REPL_ALPHA to write results of an alpha-only operation
+ *    (e.g. RCP) into color register
+ *  - apparently, there's no quick DST operation
+ *  - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
+ *  - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
+ *  - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
+ *
+ * Operand selection
+ * First stage selects three sources from the available registers and
+ * constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
+ * fglrx sorts the three source fields: Registers before constants,
+ * lower indices before higher indices; I do not know whether this is
+ * necessary.
+ *
+ * fglrx fills unused sources with "read constant 0"
+ * According to specs, you cannot select more than two different constants.
+ *
+ * Second stage selects the operands from the sources. This is defined in
+ * INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
+ * zero and one.
+ * Swizzling and negation happens in this stage, as well.
+ *
+ * Important: Color and alpha seem to be mostly separate, i.e. their sources
+ * selection appears to be fully independent (the register storage is probably
+ * physically split into a color and an alpha section).
+ * However (because of the apparent physical split), there is some interaction
+ * WRT swizzling. If, for example, you want to load an R component into an
+ * Alpha operand, this R component is taken from a *color* source, not from
+ * an alpha source. The corresponding register doesn't even have to appear in
+ * the alpha sources list. (I hope this all makes sense to you)
+ *
+ * Destination selection
+ * The destination register index is in FPI1 (color) and FPI3 (alpha)
+ * together with enable bits.
+ * There are separate enable bits for writing into temporary registers
+ * (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_*
+ * /DSTA_OUTPUT). You can write to both at once, or not write at all (the
+ * same index must be used for both).
+ *
+ * Note: There is a special form for LRP
+ *  - Argument order is the same as in ARB_fragment_program.
+ *  - Operation is MAD
+ *  - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
+ *  - Set FPI0/FPI2_SPECIAL_LRP
+ * Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD
+ */
 #define R300_PFS_INSTR1_0                   0x46C0
 #       define R300_FPI1_SRC0C_SHIFT             0
 #       define R300_FPI1_SRC0C_MASK              (31 << 0)
@@ -982,6 +1095,7 @@
 #       define R300_FPI1_SRC2C_SHIFT             12
 #       define R300_FPI1_SRC2C_MASK              (31 << 12)
 #       define R300_FPI1_SRC2C_CONST             (1 << 17)
+#       define R300_FPI1_SRC_MASK                0x0003ffff
 #       define R300_FPI1_DSTC_SHIFT              18
 #       define R300_FPI1_DSTC_MASK               (31 << 18)
 #		define R300_FPI1_DSTC_REG_MASK_SHIFT     23
@@ -1003,6 +1117,7 @@
 #       define R300_FPI3_SRC2A_SHIFT             12
 #       define R300_FPI3_SRC2A_MASK              (31 << 12)
 #       define R300_FPI3_SRC2A_CONST             (1 << 17)
+#       define R300_FPI3_SRC_MASK                0x0003ffff
 #       define R300_FPI3_DSTA_SHIFT              18
 #       define R300_FPI3_DSTA_MASK               (31 << 18)
 #       define R300_FPI3_DSTA_REG                (1 << 23)
@@ -1028,7 +1143,8 @@
 #       define R300_FPI0_ARGC_SRC1C_LRP          15
 #       define R300_FPI0_ARGC_ZERO               20
 #       define R300_FPI0_ARGC_ONE                21
-#       define R300_FPI0_ARGC_HALF               22	/* GUESS */
+	/* GUESS */
+#       define R300_FPI0_ARGC_HALF               22
 #       define R300_FPI0_ARGC_SRC0C_YZX          23
 #       define R300_FPI0_ARGC_SRC1C_YZX          24
 #       define R300_FPI0_ARGC_SRC2C_YZX          25
@@ -1057,6 +1173,7 @@
 #       define R300_FPI0_OUTC_DP4                (2 << 23)
 #       define R300_FPI0_OUTC_MIN                (4 << 23)
 #       define R300_FPI0_OUTC_MAX                (5 << 23)
+#       define R300_FPI0_OUTC_CMPH               (7 << 23)
 #       define R300_FPI0_OUTC_CMP                (8 << 23)
 #       define R300_FPI0_OUTC_FRC                (9 << 23)
 #       define R300_FPI0_OUTC_REPL_ALPHA         (10 << 23)
@@ -1079,20 +1196,23 @@
 #       define R300_FPI2_ARGA_SRC1A_LRP          15
 #       define R300_FPI2_ARGA_ZERO               16
 #       define R300_FPI2_ARGA_ONE                17
-#       define R300_FPI2_ARGA_HALF               18	/* GUESS */
-
+	/* GUESS */
+#       define R300_FPI2_ARGA_HALF               18
 #       define R300_FPI2_ARG0A_SHIFT             0
 #       define R300_FPI2_ARG0A_MASK              (31 << 0)
 #       define R300_FPI2_ARG0A_NEG               (1 << 5)
-#		define R300_FPI2_ARG0A_ABS				 (1 << 6)	/* GUESS */
+	/* GUESS */
+#	define R300_FPI2_ARG0A_ABS		 (1 << 6)
 #       define R300_FPI2_ARG1A_SHIFT             7
 #       define R300_FPI2_ARG1A_MASK              (31 << 7)
 #       define R300_FPI2_ARG1A_NEG               (1 << 12)
-#		define R300_FPI2_ARG1A_ABS				 (1 << 13)	/* GUESS */
+	/* GUESS */
+#	define R300_FPI2_ARG1A_ABS		 (1 << 13)
 #       define R300_FPI2_ARG2A_SHIFT             14
 #       define R300_FPI2_ARG2A_MASK              (31 << 14)
 #       define R300_FPI2_ARG2A_NEG               (1 << 19)
-#		define R300_FPI2_ARG2A_ABS				 (1 << 20)	/* GUESS */
+	/* GUESS */
+#	define R300_FPI2_ARG2A_ABS		 (1 << 20)
 #       define R300_FPI2_SPECIAL_LRP             (1 << 21)
 #       define R300_FPI2_OUTA_MAD                (0 << 23)
 #       define R300_FPI2_OUTA_DP4                (1 << 23)
@@ -1106,9 +1226,19 @@
 #       define R300_FPI2_OUTA_RSQ                (11 << 23)
 #       define R300_FPI2_OUTA_SAT                (1 << 30)
 #       define R300_FPI2_UNKNOWN_31              (1 << 31)
-/* END */
+/* END: Fragment program instruction set */
 
-/* gap */
+/* Fog state and color */
+#define R300_RE_FOG_STATE                   0x4BC0
+#       define R300_FOG_ENABLE                   (1 << 0)
+#	define R300_FOG_MODE_LINEAR              (0 << 1)
+#	define R300_FOG_MODE_EXP                 (1 << 1)
+#	define R300_FOG_MODE_EXP2                (2 << 1)
+#	define R300_FOG_MODE_MASK                (3 << 1)
+#define R300_FOG_COLOR_R                    0x4BC8
+#define R300_FOG_COLOR_G                    0x4BCC
+#define R300_FOG_COLOR_B                    0x4BD0
+
 #define R300_PP_ALPHA_TEST                  0x4BD4
 #       define R300_REF_ALPHA_MASK               0x000000ff
 #       define R300_ALPHA_TEST_FAIL              (0 << 8)
@@ -1123,6 +1253,7 @@
 #       define R300_ALPHA_TEST_ENABLE            (1 << 11)
 
 /* gap */
+
 /* Fragment program parameters in 7.16 floating point */
 #define R300_PFS_PARAM_0_X                  0x4C00
 #define R300_PFS_PARAM_0_Y                  0x4C04
@@ -1135,45 +1266,48 @@
 #define R300_PFS_PARAM_31_W                 0x4DFC
 
 /* Notes:
-// - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in the application
-// - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND are set to the same
-//   function (both registers are always set up completely in any case)
-// - Most blend flags are simply copied from R200 and not tested yet */
+ * - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in
+ *   the application
+ * - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND
+ *    are set to the same
+ *   function (both registers are always set up completely in any case)
+ * - Most blend flags are simply copied from R200 and not tested yet
+ */
 #define R300_RB3D_CBLEND                    0x4E04
 #define R300_RB3D_ABLEND                    0x4E08
- /* the following only appear in CBLEND */
+/* the following only appear in CBLEND */
 #       define R300_BLEND_ENABLE                     (1 << 0)
 #       define R300_BLEND_UNKNOWN                    (3 << 1)
 #       define R300_BLEND_NO_SEPARATE                (1 << 3)
- /* the following are shared between CBLEND and ABLEND */
+/* the following are shared between CBLEND and ABLEND */
 #       define R300_FCN_MASK                         (3  << 12)
 #       define R300_COMB_FCN_ADD_CLAMP               (0  << 12)
 #       define R300_COMB_FCN_ADD_NOCLAMP             (1  << 12)
 #       define R300_COMB_FCN_SUB_CLAMP               (2  << 12)
 #       define R300_COMB_FCN_SUB_NOCLAMP             (3  << 12)
-#       define R300_SRC_BLEND_GL_ZERO                (32 << 16)
-#       define R300_SRC_BLEND_GL_ONE                 (33 << 16)
-#       define R300_SRC_BLEND_GL_SRC_COLOR           (34 << 16)
-#       define R300_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16)
-#       define R300_SRC_BLEND_GL_DST_COLOR           (36 << 16)
-#       define R300_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16)
-#       define R300_SRC_BLEND_GL_SRC_ALPHA           (38 << 16)
-#       define R300_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16)
-#       define R300_SRC_BLEND_GL_DST_ALPHA           (40 << 16)
-#       define R300_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16)
-#       define R300_SRC_BLEND_GL_SRC_ALPHA_SATURATE  (42 << 16)
-#       define R300_SRC_BLEND_MASK                   (63 << 16)
-#       define R300_DST_BLEND_GL_ZERO                (32 << 24)
-#       define R300_DST_BLEND_GL_ONE                 (33 << 24)
-#       define R300_DST_BLEND_GL_SRC_COLOR           (34 << 24)
-#       define R300_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24)
-#       define R300_DST_BLEND_GL_DST_COLOR           (36 << 24)
-#       define R300_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24)
-#       define R300_DST_BLEND_GL_SRC_ALPHA           (38 << 24)
-#       define R300_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24)
-#       define R300_DST_BLEND_GL_DST_ALPHA           (40 << 24)
-#       define R300_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24)
-#       define R300_DST_BLEND_MASK                   (63 << 24)
+#       define R300_COMB_FCN_MIN                     (4  << 12)
+#       define R300_COMB_FCN_MAX                     (5  << 12)
+#       define R300_COMB_FCN_RSUB_CLAMP              (6  << 12)
+#       define R300_COMB_FCN_RSUB_NOCLAMP            (7  << 12)
+#       define R300_BLEND_GL_ZERO                    (32)
+#       define R300_BLEND_GL_ONE                     (33)
+#       define R300_BLEND_GL_SRC_COLOR               (34)
+#       define R300_BLEND_GL_ONE_MINUS_SRC_COLOR     (35)
+#       define R300_BLEND_GL_DST_COLOR               (36)
+#       define R300_BLEND_GL_ONE_MINUS_DST_COLOR     (37)
+#       define R300_BLEND_GL_SRC_ALPHA               (38)
+#       define R300_BLEND_GL_ONE_MINUS_SRC_ALPHA     (39)
+#       define R300_BLEND_GL_DST_ALPHA               (40)
+#       define R300_BLEND_GL_ONE_MINUS_DST_ALPHA     (41)
+#       define R300_BLEND_GL_SRC_ALPHA_SATURATE      (42)
+#       define R300_BLEND_GL_CONST_COLOR             (43)
+#       define R300_BLEND_GL_ONE_MINUS_CONST_COLOR   (44)
+#       define R300_BLEND_GL_CONST_ALPHA             (45)
+#       define R300_BLEND_GL_ONE_MINUS_CONST_ALPHA   (46)
+#       define R300_BLEND_MASK                       (63)
+#       define R300_SRC_BLEND_SHIFT                  (16)
+#       define R300_DST_BLEND_SHIFT                  (24)
+#define R300_RB3D_BLEND_COLOR               0x4E10
 #define R300_RB3D_COLORMASK                 0x4E0C
 #       define R300_COLORMASK0_B                 (1<<0)
 #       define R300_COLORMASK0_G                 (1<<1)
@@ -1181,41 +1315,49 @@
 #       define R300_COLORMASK0_A                 (1<<3)
 
 /* gap */
+
 #define R300_RB3D_COLOROFFSET0              0x4E28
-#       define R300_COLOROFFSET_MASK             0xFFFFFFF0	/* GUESS */
-#define R300_RB3D_COLOROFFSET1              0x4E2C	/* GUESS */
-#define R300_RB3D_COLOROFFSET2              0x4E30	/* GUESS */
-#define R300_RB3D_COLOROFFSET3              0x4E34	/* GUESS */
+#       define R300_COLOROFFSET_MASK             0xFFFFFFF0 /* GUESS */
+#define R300_RB3D_COLOROFFSET1              0x4E2C /* GUESS */
+#define R300_RB3D_COLOROFFSET2              0x4E30 /* GUESS */
+#define R300_RB3D_COLOROFFSET3              0x4E34 /* GUESS */
+
 /* gap */
+
 /* Bit 16: Larger tiles
-// Bit 17: 4x2 tiles
-// Bit 18: Extremely weird tile like, but some pixels duplicated? */
+ * Bit 17: 4x2 tiles
+ * Bit 18: Extremely weird tile like, but some pixels duplicated?
+ */
 #define R300_RB3D_COLORPITCH0               0x4E38
-#       define R300_COLORPITCH_MASK              0x00001FF8	/* GUESS */
-#       define R300_COLOR_TILE_ENABLE            (1 << 16)	/* GUESS */
-#       define R300_COLOR_MICROTILE_ENABLE       (1 << 17)	/* GUESS */
-#       define R300_COLOR_ENDIAN_NO_SWAP         (0 << 18)	/* GUESS */
-#       define R300_COLOR_ENDIAN_WORD_SWAP       (1 << 18)	/* GUESS */
-#       define R300_COLOR_ENDIAN_DWORD_SWAP      (2 << 18)	/* GUESS */
+#       define R300_COLORPITCH_MASK              0x00001FF8 /* GUESS */
+#       define R300_COLOR_TILE_ENABLE            (1 << 16) /* GUESS */
+#       define R300_COLOR_MICROTILE_ENABLE       (1 << 17) /* GUESS */
+#       define R300_COLOR_ENDIAN_NO_SWAP         (0 << 18) /* GUESS */
+#       define R300_COLOR_ENDIAN_WORD_SWAP       (1 << 18) /* GUESS */
+#       define R300_COLOR_ENDIAN_DWORD_SWAP      (2 << 18) /* GUESS */
 #       define R300_COLOR_FORMAT_RGB565          (2 << 22)
 #       define R300_COLOR_FORMAT_ARGB8888        (3 << 22)
-#define R300_RB3D_COLORPITCH1               0x4E3C	/* GUESS */
-#define R300_RB3D_COLORPITCH2               0x4E40	/* GUESS */
-#define R300_RB3D_COLORPITCH3               0x4E44	/* GUESS */
+#define R300_RB3D_COLORPITCH1               0x4E3C /* GUESS */
+#define R300_RB3D_COLORPITCH2               0x4E40 /* GUESS */
+#define R300_RB3D_COLORPITCH3               0x4E44 /* GUESS */
 
 /* gap */
+
 /* Guess by Vladimir.
-// Set to 0A before 3D operations, set to 02 afterwards. */
+ * Set to 0A before 3D operations, set to 02 afterwards.
+ */
 #define R300_RB3D_DSTCACHE_CTLSTAT          0x4E4C
-#       define R300_RB3D_DSTCACHE_02             0x00000002
-#       define R300_RB3D_DSTCACHE_0A             0x0000000A
+#       define R300_RB3D_DSTCACHE_UNKNOWN_02             0x00000002
+#       define R300_RB3D_DSTCACHE_UNKNOWN_0A             0x0000000A
 
 /* gap */
-/* There seems to be no "write only" setting, so use Z-test = ALWAYS for this. */
-/* Bit (1<<8) is the "test" bit. so plain write is 6  - vd */
+/* There seems to be no "write only" setting, so use Z-test = ALWAYS
+ * for this.
+ * Bit (1<<8) is the "test" bit. so plain write is 6  - vd
+ */
 #define R300_RB3D_ZSTENCIL_CNTL_0                   0x4F00
-#       define R300_RB3D_Z_DISABLED_1            0x00000010	/* GUESS */
-#       define R300_RB3D_Z_DISABLED_2            0x00000014	/* GUESS */
+#       define R300_RB3D_Z_DISABLED_1            0x00000010
+#       define R300_RB3D_Z_DISABLED_2            0x00000014
 #       define R300_RB3D_Z_TEST                  0x00000012
 #       define R300_RB3D_Z_TEST_AND_WRITE        0x00000016
 #       define R300_RB3D_Z_WRITE_ONLY        	 0x00000006
@@ -1226,7 +1368,7 @@
 #	define R300_RB3D_STENCIL_ENABLE		 0x00000001
 
 #define R300_RB3D_ZSTENCIL_CNTL_1                   0x4F04
-		/* functions */
+	/* functions */
 #	define R300_ZS_NEVER			0
 #	define R300_ZS_LESS			1
 #	define R300_ZS_LEQUAL			2
@@ -1236,7 +1378,7 @@
 #	define R300_ZS_NOTEQUAL			6
 #	define R300_ZS_ALWAYS			7
 #       define R300_ZS_MASK                     7
-		/* operations */
+	/* operations */
 #	define R300_ZS_KEEP			0
 #	define R300_ZS_ZERO			1
 #	define R300_ZS_REPLACE			2
@@ -1245,9 +1387,8 @@
 #	define R300_ZS_INVERT			5
 #	define R300_ZS_INCR_WRAP		6
 #	define R300_ZS_DECR_WRAP		7
-
-       /* front and back refer to operations done for front
-          and back faces, i.e. separate stencil function support */
+	/* front and back refer to operations done for front
+	   and back faces, i.e. separate stencil function support */
 #	define R300_RB3D_ZS1_DEPTH_FUNC_SHIFT		0
 #	define R300_RB3D_ZS1_FRONT_FUNC_SHIFT		3
 #	define R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT	6
@@ -1269,45 +1410,64 @@
 #define R300_RB3D_ZSTENCIL_FORMAT                   0x4F10
 #	define R300_DEPTH_FORMAT_16BIT_INT_Z     (0 << 0)
 #	define R300_DEPTH_FORMAT_24BIT_INT_Z     (2 << 0)
+	/* 16 bit format or some aditional bit ? */
+#	define R300_DEPTH_FORMAT_UNK32          (32 << 0)
+
+#define R300_RB3D_EARLY_Z                           0x4F14
+#	define R300_EARLY_Z_DISABLE              (0 << 0)
+#	define R300_EARLY_Z_ENABLE               (1 << 0)
 
 /* gap */
+
+#define R300_RB3D_ZCACHE_CTLSTAT            0x4F18 /* GUESS */
+#       define R300_RB3D_ZCACHE_UNKNOWN_01  0x1
+#       define R300_RB3D_ZCACHE_UNKNOWN_03  0x3
+
+/* gap */
+
 #define R300_RB3D_DEPTHOFFSET               0x4F20
 #define R300_RB3D_DEPTHPITCH                0x4F24
-#       define R300_DEPTHPITCH_MASK              0x00001FF8	/* GUESS */
-#       define R300_DEPTH_TILE_ENABLE            (1 << 16)	/* GUESS */
-#       define R300_DEPTH_MICROTILE_ENABLE       (1 << 17)	/* GUESS */
-#       define R300_DEPTH_ENDIAN_NO_SWAP         (0 << 18)	/* GUESS */
-#       define R300_DEPTH_ENDIAN_WORD_SWAP       (1 << 18)	/* GUESS */
-#       define R300_DEPTH_ENDIAN_DWORD_SWAP      (2 << 18)	/* GUESS */
+#       define R300_DEPTHPITCH_MASK              0x00001FF8 /* GUESS */
+#       define R300_DEPTH_TILE_ENABLE            (1 << 16) /* GUESS */
+#       define R300_DEPTH_MICROTILE_ENABLE       (1 << 17) /* GUESS */
+#       define R300_DEPTH_ENDIAN_NO_SWAP         (0 << 18) /* GUESS */
+#       define R300_DEPTH_ENDIAN_WORD_SWAP       (1 << 18) /* GUESS */
+#       define R300_DEPTH_ENDIAN_DWORD_SWAP      (2 << 18) /* GUESS */
 
-/* BEGIN: Vertex program instruction set
-// Every instruction is four dwords long:
-//  DWORD 0: output and opcode
-//  DWORD 1: first argument
-//  DWORD 2: second argument
-//  DWORD 3: third argument
-//
-// Notes:
-//  - ABS r, a is implemented as MAX r, a, -a
-//  - MOV is implemented as ADD to zero
-//  - XPD is implemented as MUL + MAD
-//  - FLR is implemented as FRC + ADD
-//  - apparently, fglrx tries to schedule instructions so that there is at least
-//    one instruction between the write to a temporary and the first read
-//    from said temporary; however, violations of this scheduling are allowed
-//  - register indices seem to be unrelated with OpenGL aliasing to conventional state
-//  - only one attribute and one parameter can be loaded at a time; however, the
-//    same attribute/parameter can be used for more than one argument
-//  - the second software argument for POW is the third hardware argument (no idea why)
-//  - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
-//
-// There is some magic surrounding LIT:
-//  The single argument is replicated across all three inputs, but swizzled:
-//   First argument: xyzy
-//   Second argument: xyzx
-//   Third argument: xyzw
-//  Whenever the result is used later in the fragment program, fglrx forces x and w
-//  to be 1.0 in the input selection; I don't know whether this is strictly necessary */
+/* BEGIN: Vertex program instruction set */
+
+/* Every instruction is four dwords long:
+ *  DWORD 0: output and opcode
+ *  DWORD 1: first argument
+ *  DWORD 2: second argument
+ *  DWORD 3: third argument
+ *
+ * Notes:
+ *  - ABS r, a is implemented as MAX r, a, -a
+ *  - MOV is implemented as ADD to zero
+ *  - XPD is implemented as MUL + MAD
+ *  - FLR is implemented as FRC + ADD
+ *  - apparently, fglrx tries to schedule instructions so that there is at
+ *    least one instruction between the write to a temporary and the first
+ *    read from said temporary; however, violations of this scheduling are
+ *    allowed
+ *  - register indices seem to be unrelated with OpenGL aliasing to
+ *    conventional state
+ *  - only one attribute and one parameter can be loaded at a time; however,
+ *    the same attribute/parameter can be used for more than one argument
+ *  - the second software argument for POW is the third hardware argument
+ *    (no idea why)
+ *  - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
+ *
+ * There is some magic surrounding LIT:
+ *   The single argument is replicated across all three inputs, but swizzled:
+ *     First argument: xyzy
+ *     Second argument: xyzx
+ *     Third argument: xyzw
+ *   Whenever the result is used later in the fragment program, fglrx forces
+ *   x and w to be 1.0 in the input selection; I don't know whether this is
+ *   strictly necessary
+ */
 #define R300_VPI_OUT_OP_DOT                     (1 << 0)
 #define R300_VPI_OUT_OP_MUL                     (2 << 0)
 #define R300_VPI_OUT_OP_ADD                     (3 << 0)
@@ -1318,26 +1478,33 @@
 #define R300_VPI_OUT_OP_MIN                     (8 << 0)
 #define R300_VPI_OUT_OP_SGE                     (9 << 0)
 #define R300_VPI_OUT_OP_SLT                     (10 << 0)
-#define R300_VPI_OUT_OP_UNK12                   (12 << 0)	/* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+	/* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+#define R300_VPI_OUT_OP_UNK12                   (12 << 0)
+#define R300_VPI_OUT_OP_ARL                     (13 << 0)
 #define R300_VPI_OUT_OP_EXP                     (65 << 0)
 #define R300_VPI_OUT_OP_LOG                     (66 << 0)
-#define R300_VPI_OUT_OP_UNK67                   (67 << 0)	/* Used in fog computations, scalar(scalar) */
+	/* Used in fog computations, scalar(scalar) */
+#define R300_VPI_OUT_OP_UNK67                   (67 << 0)
 #define R300_VPI_OUT_OP_LIT                     (68 << 0)
 #define R300_VPI_OUT_OP_POW                     (69 << 0)
 #define R300_VPI_OUT_OP_RCP                     (70 << 0)
 #define R300_VPI_OUT_OP_RSQ                     (72 << 0)
-#define R300_VPI_OUT_OP_UNK73                   (73 << 0)	/* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+	/* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+#define R300_VPI_OUT_OP_UNK73                   (73 << 0)
 #define R300_VPI_OUT_OP_EX2                     (75 << 0)
 #define R300_VPI_OUT_OP_LG2                     (76 << 0)
 #define R300_VPI_OUT_OP_MAD_2                   (128 << 0)
-#define R300_VPI_OUT_OP_UNK129                  (129 << 0)	/* all temps, vector(scalar, vector, vector) */
+	/* all temps, vector(scalar, vector, vector) */
+#define R300_VPI_OUT_OP_UNK129                  (129 << 0)
 
 #define R300_VPI_OUT_REG_CLASS_TEMPORARY        (0 << 8)
+#define R300_VPI_OUT_REG_CLASS_ADDR             (1 << 8)
 #define R300_VPI_OUT_REG_CLASS_RESULT           (2 << 8)
 #define R300_VPI_OUT_REG_CLASS_MASK             (31 << 8)
 
 #define R300_VPI_OUT_REG_INDEX_SHIFT            13
-#define R300_VPI_OUT_REG_INDEX_MASK             (31 << 13)	/* GUESS based on fglrx native limits */
+	/* GUESS based on fglrx native limits */
+#define R300_VPI_OUT_REG_INDEX_MASK             (31 << 13)
 
 #define R300_VPI_OUT_WRITE_X                    (1 << 20)
 #define R300_VPI_OUT_WRITE_Y                    (1 << 21)
@@ -1348,14 +1515,16 @@
 #define R300_VPI_IN_REG_CLASS_ATTRIBUTE         (1 << 0)
 #define R300_VPI_IN_REG_CLASS_PARAMETER         (2 << 0)
 #define R300_VPI_IN_REG_CLASS_NONE              (9 << 0)
-#define R300_VPI_IN_REG_CLASS_MASK              (31 << 0)	/* GUESS */
+#define R300_VPI_IN_REG_CLASS_MASK              (31 << 0)
 
 #define R300_VPI_IN_REG_INDEX_SHIFT             5
-#define R300_VPI_IN_REG_INDEX_MASK              (255 << 5)	/* GUESS based on fglrx native limits */
+	/* GUESS based on fglrx native limits */
+#define R300_VPI_IN_REG_INDEX_MASK              (255 << 5)
 
 /* The R300 can select components from the input register arbitrarily.
-// Use the following constants, shifted by the component shift you
-// want to select */
+ * Use the following constants, shifted by the component shift you
+ * want to select
+ */
 #define R300_VPI_IN_SELECT_X    0
 #define R300_VPI_IN_SELECT_Y    1
 #define R300_VPI_IN_SELECT_Z    2
@@ -1373,11 +1542,11 @@
 #define R300_VPI_IN_NEG_Y                       (1 << 26)
 #define R300_VPI_IN_NEG_Z                       (1 << 27)
 #define R300_VPI_IN_NEG_W                       (1 << 28)
-/* END */
+/* END: Vertex program instruction set */
 
-//BEGIN: Packet 3 commands
+/* BEGIN: Packet 3 commands */
 
-// A primitive emission dword.
+/* A primitive emission dword. */
 #define R300_PRIM_TYPE_NONE                     (0 << 0)
 #define R300_PRIM_TYPE_POINT                    (1 << 0)
 #define R300_PRIM_TYPE_LINE                     (2 << 0)
@@ -1389,7 +1558,8 @@
 #define R300_PRIM_TYPE_RECT_LIST                (8 << 0)
 #define R300_PRIM_TYPE_3VRT_POINT_LIST          (9 << 0)
 #define R300_PRIM_TYPE_3VRT_LINE_LIST           (10 << 0)
-#define R300_PRIM_TYPE_POINT_SPRITES            (11 << 0)	// GUESS (based on r200)
+	/* GUESS (based on r200) */
+#define R300_PRIM_TYPE_POINT_SPRITES            (11 << 0)
 #define R300_PRIM_TYPE_LINE_LOOP                (12 << 0)
 #define R300_PRIM_TYPE_QUADS                    (13 << 0)
 #define R300_PRIM_TYPE_QUAD_STRIP               (14 << 0)
@@ -1399,37 +1569,58 @@
 #define R300_PRIM_WALK_LIST                     (2 << 4)
 #define R300_PRIM_WALK_RING                     (3 << 4)
 #define R300_PRIM_WALK_MASK                     (3 << 4)
-#define R300_PRIM_COLOR_ORDER_BGRA              (0 << 6)	// GUESS (based on r200)
-#define R300_PRIM_COLOR_ORDER_RGBA              (1 << 6)	// GUESS
+	/* GUESS (based on r200) */
+#define R300_PRIM_COLOR_ORDER_BGRA              (0 << 6)
+#define R300_PRIM_COLOR_ORDER_RGBA              (1 << 6)
 #define R300_PRIM_NUM_VERTICES_SHIFT            16
+#define R300_PRIM_NUM_VERTICES_MASK             0xffff
 
-// Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
-// Two parameter dwords:
-// 0. The first parameter appears to be always 0
-// 1. The second parameter is a standard primitive emission dword.
+/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
+ * Two parameter dwords:
+ * 0. The first parameter appears to be always 0
+ * 1. The second parameter is a standard primitive emission dword.
+ */
 #define R300_PACKET3_3D_DRAW_VBUF           0x00002800
 
-// Specify the full set of vertex arrays as (address, stride).
-// The first parameter is the number of vertex arrays specified.
-// The rest of the command is a variable length list of blocks, where
-// each block is three dwords long and specifies two arrays.
-// The first dword of a block is split into two words, the lower significant
-// word refers to the first array, the more significant word to the second
-// array in the block.
-// The low byte of each word contains the size of an array entry in dwords,
-// the high byte contains the stride of the array.
-// The second dword of a block contains the pointer to the first array,
-// the third dword of a block contains the pointer to the second array.
-// Note that if the total number of arrays is odd, the third dword of
-// the last block is omitted.
+/* Specify the full set of vertex arrays as (address, stride).
+ * The first parameter is the number of vertex arrays specified.
+ * The rest of the command is a variable length list of blocks, where
+ * each block is three dwords long and specifies two arrays.
+ * The first dword of a block is split into two words, the lower significant
+ * word refers to the first array, the more significant word to the second
+ * array in the block.
+ * The low byte of each word contains the size of an array entry in dwords,
+ * the high byte contains the stride of the array.
+ * The second dword of a block contains the pointer to the first array,
+ * the third dword of a block contains the pointer to the second array.
+ * Note that if the total number of arrays is odd, the third dword of
+ * the last block is omitted.
+ */
 #define R300_PACKET3_3D_LOAD_VBPNTR         0x00002F00
 
 #define R300_PACKET3_INDX_BUFFER            0x00003300
 #    define R300_EB_UNK1_SHIFT                      24
 #    define R300_EB_UNK1                    (0x80<<24)
 #    define R300_EB_UNK2                        0x0810
+#define R300_PACKET3_3D_DRAW_VBUF_2         0x00003400
 #define R300_PACKET3_3D_DRAW_INDX_2         0x00003600
 
-//END
+/* END: Packet 3 commands */
 
-#endif				/* _R300_REG_H */
+
+/* Color formats for 2d packets
+ */
+#define R300_CP_COLOR_FORMAT_CI8	2
+#define R300_CP_COLOR_FORMAT_ARGB1555	3
+#define R300_CP_COLOR_FORMAT_RGB565	4
+#define R300_CP_COLOR_FORMAT_ARGB8888	6
+#define R300_CP_COLOR_FORMAT_RGB332	7
+#define R300_CP_COLOR_FORMAT_RGB8	9
+#define R300_CP_COLOR_FORMAT_ARGB4444	15
+
+/*
+ * CP type-3 packets
+ */
+#define R300_CP_CMD_BITBLT_MULTI	0xC0009B00
+
+#endif /* _R300_REG_H */
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 68338389..af5790f 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -36,7 +36,7 @@
 
 #define RADEON_FIFO_DEBUG	0
 
-static int radeon_do_cleanup_cp(drm_device_t * dev);
+static int radeon_do_cleanup_cp(struct drm_device * dev);
 
 /* CP microcode (from ATI) */
 static const u32 R200_cp_microcode[][2] = {
@@ -816,7 +816,7 @@
 	{0000000000, 0000000000},
 };
 
-static int RADEON_READ_PLL(drm_device_t * dev, int addr)
+static int RADEON_READ_PLL(struct drm_device * dev, int addr)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1066,7 +1066,7 @@
 
 /* Reset the engine.  This will stop the CP if it is running.
  */
-static int radeon_do_engine_reset(drm_device_t * dev)
+static int radeon_do_engine_reset(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
@@ -1122,7 +1122,7 @@
 	return 0;
 }
 
-static void radeon_cp_init_ring_buffer(drm_device_t * dev,
+static void radeon_cp_init_ring_buffer(struct drm_device * dev,
 				       drm_radeon_private_t * dev_priv)
 {
 	u32 ring_start, cur_read_ptr;
@@ -1174,7 +1174,7 @@
 	} else
 #endif
 	{
-		drm_sg_mem_t *entry = dev->sg;
+		struct drm_sg_mem *entry = dev->sg;
 		unsigned long tmp_ofs, page_ofs;
 
 		tmp_ofs = dev_priv->ring_rptr->offset -
@@ -1384,7 +1384,7 @@
 	}
 }
 
-static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1420,6 +1420,10 @@
 		return DRM_ERR(EINVAL);
 	}
 
+	/* Enable vblank on CRTC1 for older X servers
+	 */
+	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
+
 	switch(init->func) {
 	case RADEON_INIT_R200_CP:
 		dev_priv->microcode_version = UCODE_R200;
@@ -1501,13 +1505,13 @@
 					 RADEON_ROUND_MODE_TRUNC |
 					 RADEON_ROUND_PREC_8TH_PIX);
 
-	DRM_GETSAREA();
 
 	dev_priv->ring_offset = init->ring_offset;
 	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
 	dev_priv->buffers_offset = init->buffers_offset;
 	dev_priv->gart_textures_offset = init->gart_textures_offset;
 
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		radeon_do_cleanup_cp(dev);
@@ -1731,7 +1735,7 @@
 	return 0;
 }
 
-static int radeon_do_cleanup_cp(drm_device_t * dev)
+static int radeon_do_cleanup_cp(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG("\n");
@@ -1787,7 +1791,7 @@
  *
  * Charl P. Botha <http://cpbotha.net>
  */
-static int radeon_do_resume_cp(drm_device_t * dev)
+static int radeon_do_resume_cp(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1914,7 +1918,7 @@
 	return 0;
 }
 
-void radeon_do_release(drm_device_t * dev)
+void radeon_do_release(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	int i, ret;
@@ -2042,12 +2046,12 @@
  * they can't get the lock.
  */
 
-drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i, t;
 	int start;
 
@@ -2082,12 +2086,12 @@
 }
 
 #if 0
-drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i, t;
 	int start;
 	u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
@@ -2116,15 +2120,15 @@
 }
 #endif
 
-void radeon_freelist_reset(drm_device_t * dev)
+void radeon_freelist_reset(struct drm_device * dev)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	int i;
 
 	dev_priv->last_buf = 0;
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
 		buf_priv->age = 0;
 	}
@@ -2166,11 +2170,11 @@
 	return DRM_ERR(EBUSY);
 }
 
-static int radeon_cp_get_buffers(DRMFILE filp, drm_device_t * dev,
-				 drm_dma_t * d)
+static int radeon_cp_get_buffers(DRMFILE filp, struct drm_device * dev,
+				 struct drm_dma * d)
 {
 	int i;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 
 	for (i = d->granted_count; i < d->request_count; i++) {
 		buf = radeon_freelist_get(dev);
@@ -2194,10 +2198,10 @@
 int radeon_cp_buffers(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	int ret = 0;
-	drm_dma_t __user *argp = (void __user *)data;
-	drm_dma_t d;
+	struct drm_dma __user *argp = (void __user *)data;
+	struct drm_dma d;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 66c4b6f..5a8e23f 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -417,7 +417,7 @@
 
 	/* The current cliprects, or a subset thereof.
 	 */
-	drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS];
 	unsigned int nbox;
 
 	/* Counters for client-side throttling of rendering clients.
@@ -426,7 +426,7 @@
 	unsigned int last_dispatch;
 	unsigned int last_clear;
 
-	drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
+	struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
 						       1];
 	unsigned int tex_age[RADEON_NR_TEX_HEAPS];
 	int ctx_owner;
@@ -604,7 +604,7 @@
 	int bufsz;
 	char __user *buf;
 	int nbox;
-	drm_clip_rect_t __user *boxes;
+	struct drm_clip_rect __user *boxes;
 } drm_radeon_cmd_buffer_t;
 
 typedef struct drm_radeon_tex_image {
@@ -655,6 +655,7 @@
 #define RADEON_PARAM_GART_TEX_HANDLE       10
 #define RADEON_PARAM_SCRATCH_OFFSET        11
 #define RADEON_PARAM_CARD_TYPE             12
+#define RADEON_PARAM_VBLANK_CRTC           13   /* VBLANK CRTC */
 
 typedef struct drm_radeon_getparam {
 	int param;
@@ -708,7 +709,7 @@
 #define RADEON_SETPARAM_PCIGART_LOCATION 3	/* PCI Gart Location */
 #define RADEON_SETPARAM_NEW_MEMMAP 4		/* Use new memory map */
 #define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5    /* PCI GART Table Size */
-
+#define RADEON_SETPARAM_VBLANK_CRTC 6           /* VBLANK CRTC */
 /* 1.14: Clients can allocate/free a surface
  */
 typedef struct drm_radeon_surface_alloc {
@@ -721,4 +722,7 @@
 	unsigned int address;
 } drm_radeon_surface_free_t;
 
+#define	DRM_RADEON_VBLANK_CRTC1 	1
+#define	DRM_RADEON_VBLANK_CRTC2 	2
+
 #endif
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 2eb652e..349ac3d 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -60,7 +60,7 @@
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
 	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
-	    DRIVER_IRQ_VBL,
+	    DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
 	.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
 	.load = radeon_driver_load,
 	.firstopen = radeon_driver_firstopen,
@@ -70,6 +70,7 @@
 	.lastclose = radeon_driver_lastclose,
 	.unload = radeon_driver_unload,
 	.vblank_wait = radeon_driver_vblank_wait,
+	.vblank_wait2 = radeon_driver_vblank_wait2,
 	.dri_library_name = dri_library_name,
 	.irq_preinstall = radeon_driver_irq_preinstall,
 	.irq_postinstall = radeon_driver_irq_postinstall,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 54f49ef..3b3d935 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -97,9 +97,10 @@
  *       new packet type)
  * 1.26- Add support for variable size PCI(E) gart aperture
  * 1.27- Add support for IGP GART
+ * 1.28- Add support for VBL on CRTC2
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		27
+#define DRIVER_MINOR		28
 #define DRIVER_PATCHLEVEL	0
 
 /*
@@ -154,7 +155,7 @@
 
 typedef struct drm_radeon_freelist {
 	unsigned int age;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	struct drm_radeon_freelist *next;
 	struct drm_radeon_freelist *prev;
 } drm_radeon_freelist_t;
@@ -277,13 +278,16 @@
 	/* SW interrupt */
 	wait_queue_head_t swi_queue;
 	atomic_t swi_emitted;
+	int vblank_crtc;
+	uint32_t irq_enable_reg;
+	int irq_enabled;
 
 	struct radeon_surface surfaces[RADEON_MAX_SURFACES];
 	struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
 
 	unsigned long pcigart_offset;
 	unsigned int pcigart_offset_set;
-	drm_ati_pcigart_info gart_info;
+	struct drm_ati_pcigart_info gart_info;
 
 	u32 scratch_ages[5];
 
@@ -299,7 +303,7 @@
 	int bufsz;
 	char *buf;
 	int nbox;
-	drm_clip_rect_t __user *boxes;
+	struct drm_clip_rect __user *boxes;
 } drm_radeon_kcmd_buffer_t;
 
 extern int radeon_no_wb;
@@ -332,8 +336,8 @@
 extern int radeon_fullscreen(DRM_IOCTL_ARGS);
 extern int radeon_cp_buffers(DRM_IOCTL_ARGS);
 
-extern void radeon_freelist_reset(drm_device_t * dev);
-extern drm_buf_t *radeon_freelist_get(drm_device_t * dev);
+extern void radeon_freelist_reset(struct drm_device * dev);
+extern struct drm_buf *radeon_freelist_get(struct drm_device * dev);
 
 extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
 
@@ -353,29 +357,33 @@
 extern int radeon_irq_emit(DRM_IOCTL_ARGS);
 extern int radeon_irq_wait(DRM_IOCTL_ARGS);
 
-extern void radeon_do_release(drm_device_t * dev);
-extern int radeon_driver_vblank_wait(drm_device_t * dev,
+extern void radeon_do_release(struct drm_device * dev);
+extern int radeon_driver_vblank_wait(struct drm_device * dev,
 				     unsigned int *sequence);
+extern int radeon_driver_vblank_wait2(struct drm_device * dev,
+				      unsigned int *sequence);
 extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
-extern void radeon_driver_irq_preinstall(drm_device_t * dev);
-extern void radeon_driver_irq_postinstall(drm_device_t * dev);
-extern void radeon_driver_irq_uninstall(drm_device_t * dev);
+extern void radeon_driver_irq_preinstall(struct drm_device * dev);
+extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern void radeon_driver_irq_uninstall(struct drm_device * dev);
+extern int radeon_vblank_crtc_get(struct drm_device *dev);
+extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
 
 extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
 extern int radeon_driver_unload(struct drm_device *dev);
 extern int radeon_driver_firstopen(struct drm_device *dev);
-extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp);
-extern void radeon_driver_lastclose(drm_device_t * dev);
-extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv);
+extern void radeon_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp);
+extern void radeon_driver_lastclose(struct drm_device * dev);
+extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv);
 extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
 				unsigned long arg);
 
 /* r300_cmdbuf.c */
 extern void r300_init_reg_flags(void);
 
-extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
-			     drm_file_t * filp_priv,
+extern int r300_do_cp_cmdbuf(struct drm_device * dev, DRMFILE filp,
+			     struct drm_file * filp_priv,
 			     drm_radeon_kcmd_buffer_t * cmdbuf);
 
 /* Flags for stats.boxes
@@ -496,12 +504,15 @@
 
 #define RADEON_GEN_INT_CNTL		0x0040
 #	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
+#	define RADEON_CRTC2_VBLANK_MASK		(1 << 9)
 #	define RADEON_GUI_IDLE_INT_ENABLE	(1 << 19)
 #	define RADEON_SW_INT_ENABLE		(1 << 25)
 
 #define RADEON_GEN_INT_STATUS		0x0044
 #	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
 #	define RADEON_CRTC_VBLANK_STAT_ACK   	(1 << 0)
+#	define RADEON_CRTC2_VBLANK_STAT		(1 << 9)
+#	define RADEON_CRTC2_VBLANK_STAT_ACK   	(1 << 9)
 #	define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
 #	define RADEON_SW_INT_TEST		(1 << 25)
 #	define RADEON_SW_INT_TEST_ACK   	(1 << 25)
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
index 1f1f9cc..56decda 100644
--- a/drivers/char/drm/radeon_ioc32.c
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -349,6 +349,36 @@
 			 DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
 }
 
+/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
+#if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
+typedef struct drm_radeon_setparam32 {
+	int param;
+	u64 value;
+} __attribute__((packed)) drm_radeon_setparam32_t;
+
+static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd,
+				     unsigned long arg)
+{
+	drm_radeon_setparam32_t req32;
+	drm_radeon_setparam_t __user *request;
+
+	if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user(req32.param, &request->param)
+	    || __put_user((void __user *)(unsigned long)req32.value,
+			  &request->value))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
+}
+#else
+#define compat_radeon_cp_setparam NULL
+#endif /* X86_64 || IA64 */
+
 drm_ioctl_compat_t *radeon_compat_ioctls[] = {
 	[DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
 	[DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
@@ -357,6 +387,7 @@
 	[DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
 	[DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
 	[DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
+	[DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam,
 	[DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
 	[DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
 };
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 3ff0baa..ad8a0ac 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -64,7 +64,7 @@
 
 irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
 	u32 stat;
@@ -73,18 +73,35 @@
 	 * outside the DRM
 	 */
 	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-						  RADEON_CRTC_VBLANK_STAT));
+						  RADEON_CRTC_VBLANK_STAT |
+						  RADEON_CRTC2_VBLANK_STAT));
 	if (!stat)
 		return IRQ_NONE;
 
+	stat &= dev_priv->irq_enable_reg;
+
 	/* SW interrupt */
 	if (stat & RADEON_SW_INT_TEST) {
 		DRM_WAKEUP(&dev_priv->swi_queue);
 	}
 
 	/* VBLANK interrupt */
-	if (stat & RADEON_CRTC_VBLANK_STAT) {
-		atomic_inc(&dev->vbl_received);
+	if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
+		int vblank_crtc = dev_priv->vblank_crtc;
+
+		if ((vblank_crtc &
+		     (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
+		    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+			if (stat & RADEON_CRTC_VBLANK_STAT)
+				atomic_inc(&dev->vbl_received);
+			if (stat & RADEON_CRTC2_VBLANK_STAT)
+				atomic_inc(&dev->vbl_received2);
+		} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
+			   (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
+			   ((stat & RADEON_CRTC2_VBLANK_STAT) &&
+			    (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
+			atomic_inc(&dev->vbl_received);
+
 		DRM_WAKEUP(&dev->vbl_queue);
 		drm_vbl_send_signals(dev);
 	}
@@ -92,7 +109,7 @@
 	return IRQ_HANDLED;
 }
 
-static int radeon_emit_irq(drm_device_t * dev)
+static int radeon_emit_irq(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	unsigned int ret;
@@ -110,7 +127,7 @@
 	return ret;
 }
 
-static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
+static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
@@ -127,19 +144,30 @@
 	return ret;
 }
 
-int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int radeon_driver_vblank_do_wait(struct drm_device * dev, unsigned int *sequence,
+				 int crtc)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
 	unsigned int cur_vblank;
 	int ret = 0;
-
+	int ack = 0;
+	atomic_t *counter;
 	if (!dev_priv) {
 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
 		return DRM_ERR(EINVAL);
 	}
 
-	radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
+	if (crtc == DRM_RADEON_VBLANK_CRTC1) {
+		counter = &dev->vbl_received;
+		ack |= RADEON_CRTC_VBLANK_STAT;
+	} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
+		counter = &dev->vbl_received2;
+		ack |= RADEON_CRTC2_VBLANK_STAT;
+	} else
+		return DRM_ERR(EINVAL);
+
+	radeon_acknowledge_irqs(dev_priv, ack);
 
 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
@@ -148,7 +176,7 @@
 	 * using vertical blanks...
 	 */
 	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(&dev->vbl_received))
+		    (((cur_vblank = atomic_read(counter))
 		      - *sequence) <= (1 << 23)));
 
 	*sequence = cur_vblank;
@@ -156,6 +184,16 @@
 	return ret;
 }
 
+int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+{
+	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
+}
+
+int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+{
+	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+}
+
 /* Needs the lock as it touches the ring.
  */
 int radeon_irq_emit(DRM_IOCTL_ARGS)
@@ -204,9 +242,24 @@
 	return radeon_wait_irq(dev, irqwait.irq_seq);
 }
 
+static void radeon_enable_interrupt(struct drm_device *dev)
+{
+	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+
+	dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
+	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
+		dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
+
+	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
+		dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
+
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+	dev_priv->irq_enabled = 1;
+}
+
 /* drm_dma.h hooks
 */
-void radeon_driver_irq_preinstall(drm_device_t * dev)
+void radeon_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
@@ -216,10 +269,11 @@
 
 	/* Clear bits if they're already high */
 	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-					   RADEON_CRTC_VBLANK_STAT));
+					   RADEON_CRTC_VBLANK_STAT |
+					   RADEON_CRTC2_VBLANK_STAT));
 }
 
-void radeon_driver_irq_postinstall(drm_device_t * dev)
+void radeon_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
@@ -227,18 +281,48 @@
 	atomic_set(&dev_priv->swi_emitted, 0);
 	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
 
-	/* Turn on SW and VBL ints */
-	RADEON_WRITE(RADEON_GEN_INT_CNTL,
-		     RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
+	radeon_enable_interrupt(dev);
 }
 
-void radeon_driver_irq_uninstall(drm_device_t * dev)
+void radeon_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
 	if (!dev_priv)
 		return;
 
+	dev_priv->irq_enabled = 0;
+
 	/* Disable *all* interrupts */
 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
 }
+
+
+int radeon_vblank_crtc_get(struct drm_device *dev)
+{
+	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+	u32 flag;
+	u32 value;
+
+	flag = RADEON_READ(RADEON_GEN_INT_CNTL);
+	value = 0;
+
+	if (flag & RADEON_CRTC_VBLANK_MASK)
+		value |= DRM_RADEON_VBLANK_CRTC1;
+
+	if (flag & RADEON_CRTC2_VBLANK_MASK)
+		value |= DRM_RADEON_VBLANK_CRTC2;
+	return value;
+}
+
+int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
+{
+	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+	if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+		DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
+		return DRM_ERR(EINVAL);
+	}
+	dev_priv->vblank_crtc = (unsigned int)value;
+	radeon_enable_interrupt(dev);
+	return 0;
+}
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 98c5f1d..3ddf86f 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -39,7 +39,7 @@
 
 static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
 						    dev_priv,
-						    drm_file_t * filp_priv,
+						    struct drm_file * filp_priv,
 						    u32 *offset)
 {
 	u64 off = *offset;
@@ -90,7 +90,7 @@
 
 static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 						     dev_priv,
-						     drm_file_t * filp_priv,
+						     struct drm_file * filp_priv,
 						     int id, u32 *data)
 {
 	switch (id) {
@@ -264,7 +264,7 @@
 
 static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
 						     dev_priv,
-						     drm_file_t *filp_priv,
+						     struct drm_file *filp_priv,
 						     drm_radeon_kcmd_buffer_t *
 						     cmdbuf,
 						     unsigned int *cmdsz)
@@ -421,7 +421,7 @@
  */
 
 static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
-					     drm_clip_rect_t * box)
+					     struct drm_clip_rect * box)
 {
 	RING_LOCALS;
 
@@ -439,7 +439,7 @@
 /* Emit 1.1 state
  */
 static int radeon_emit_state(drm_radeon_private_t * dev_priv,
-			     drm_file_t * filp_priv,
+			     struct drm_file * filp_priv,
 			     drm_radeon_context_regs_t * ctx,
 			     drm_radeon_texture_regs_t * tex,
 			     unsigned int dirty)
@@ -608,7 +608,7 @@
 /* Emit 1.2 state
  */
 static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
-			      drm_file_t * filp_priv,
+			      struct drm_file * filp_priv,
 			      drm_radeon_state_t * state)
 {
 	RING_LOCALS;
@@ -844,7 +844,7 @@
  * CP command dispatch functions
  */
 
-static void radeon_cp_dispatch_clear(drm_device_t * dev,
+static void radeon_cp_dispatch_clear(struct drm_device * dev,
 				     drm_radeon_clear_t * clear,
 				     drm_radeon_clear_rect_t * depth_boxes)
 {
@@ -852,7 +852,7 @@
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	unsigned int flags = clear->flags;
 	u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
 	int i;
@@ -1335,12 +1335,12 @@
 	ADVANCE_RING();
 }
 
-static void radeon_cp_dispatch_swap(drm_device_t * dev)
+static void radeon_cp_dispatch_swap(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG("\n");
@@ -1412,10 +1412,10 @@
 	ADVANCE_RING();
 }
 
-static void radeon_cp_dispatch_flip(drm_device_t * dev)
+static void radeon_cp_dispatch_flip(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
+	struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
 	int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
 	    ? dev_priv->front_offset : dev_priv->back_offset;
 	RING_LOCALS;
@@ -1491,8 +1491,8 @@
 	unsigned int vc_format;
 } drm_radeon_tcl_prim_t;
 
-static void radeon_cp_dispatch_vertex(drm_device_t * dev,
-				      drm_buf_t * buf,
+static void radeon_cp_dispatch_vertex(struct drm_device * dev,
+				      struct drm_buf * buf,
 				      drm_radeon_tcl_prim_t * prim)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1537,7 +1537,7 @@
 	} while (i < nbox);
 }
 
-static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -1554,8 +1554,8 @@
 	buf->used = 0;
 }
 
-static void radeon_cp_dispatch_indirect(drm_device_t * dev,
-					drm_buf_t * buf, int start, int end)
+static void radeon_cp_dispatch_indirect(struct drm_device * dev,
+					struct drm_buf * buf, int start, int end)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -1588,8 +1588,8 @@
 	}
 }
 
-static void radeon_cp_dispatch_indices(drm_device_t * dev,
-				       drm_buf_t * elt_buf,
+static void radeon_cp_dispatch_indices(struct drm_device * dev,
+				       struct drm_buf * elt_buf,
 				       drm_radeon_tcl_prim_t * prim)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1647,13 +1647,13 @@
 #define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
 
 static int radeon_cp_dispatch_texture(DRMFILE filp,
-				      drm_device_t * dev,
+				      struct drm_device * dev,
 				      drm_radeon_texture_t * tex,
 				      drm_radeon_tex_image_t * image)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
-	drm_buf_t *buf;
+	struct drm_file *filp_priv;
+	struct drm_buf *buf;
 	u32 format;
 	u32 *buffer;
 	const u8 __user *data;
@@ -1881,7 +1881,7 @@
 	return 0;
 }
 
-static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	int i;
@@ -2134,7 +2134,7 @@
 
 /* Not sure why this isn't set all the time:
  */
-static int radeon_do_init_pageflip(drm_device_t * dev)
+static int radeon_do_init_pageflip(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -2206,10 +2206,10 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
+	struct drm_file *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_radeon_vertex_t vertex;
 	drm_radeon_tcl_prim_t prim;
 
@@ -2289,10 +2289,10 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
+	struct drm_file *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_radeon_indices_t elts;
 	drm_radeon_tcl_prim_t prim;
 	int count;
@@ -2438,8 +2438,8 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_radeon_indirect_t indirect;
 	RING_LOCALS;
 
@@ -2507,10 +2507,10 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
+	struct drm_file *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_radeon_vertex2_t vertex;
 	int i;
 	unsigned char laststate;
@@ -2603,7 +2603,7 @@
 }
 
 static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
-			       drm_file_t * filp_priv,
+			       struct drm_file * filp_priv,
 			       drm_radeon_cmd_header_t header,
 			       drm_radeon_kcmd_buffer_t *cmdbuf)
 {
@@ -2728,8 +2728,8 @@
 	return 0;
 }
 
-static int radeon_emit_packet3(drm_device_t * dev,
-			       drm_file_t * filp_priv,
+static int radeon_emit_packet3(struct drm_device * dev,
+			       struct drm_file * filp_priv,
 			       drm_radeon_kcmd_buffer_t *cmdbuf)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2754,16 +2754,16 @@
 	return 0;
 }
 
-static int radeon_emit_packet3_cliprect(drm_device_t *dev,
-					drm_file_t *filp_priv,
+static int radeon_emit_packet3_cliprect(struct drm_device *dev,
+					struct drm_file *filp_priv,
 					drm_radeon_kcmd_buffer_t *cmdbuf,
 					int orig_nbox)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_clip_rect_t box;
+	struct drm_clip_rect box;
 	unsigned int cmdsz;
 	int ret;
-	drm_clip_rect_t __user *boxes = cmdbuf->boxes;
+	struct drm_clip_rect __user *boxes = cmdbuf->boxes;
 	int i = 0;
 	RING_LOCALS;
 
@@ -2816,7 +2816,7 @@
 	return 0;
 }
 
-static int radeon_emit_wait(drm_device_t * dev, int flags)
+static int radeon_emit_wait(struct drm_device * dev, int flags)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
@@ -2849,9 +2849,9 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf = NULL;
+	struct drm_file *filp_priv;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf = NULL;
 	int idx;
 	drm_radeon_kcmd_buffer_t cmdbuf;
 	drm_radeon_cmd_header_t header;
@@ -3085,6 +3085,9 @@
 		else
 			value = RADEON_CARD_PCI;
 		break;
+	case RADEON_PARAM_VBLANK_CRTC:
+		value = radeon_vblank_crtc_get(dev);
+		break;
 	default:
 		DRM_DEBUG("Invalid parameter %d\n", param.param);
 		return DRM_ERR(EINVAL);
@@ -3102,7 +3105,7 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_file_t *filp_priv;
+	struct drm_file *filp_priv;
 	drm_radeon_setparam_t sp;
 	struct drm_radeon_driver_file_fields *radeon_priv;
 
@@ -3141,6 +3144,9 @@
 		if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
 			dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
 		break;
+	case RADEON_SETPARAM_VBLANK_CRTC:
+		return radeon_vblank_crtc_set(dev, sp.value);
+		break;
 	default:
 		DRM_DEBUG("Invalid parameter %d\n", sp.param);
 		return DRM_ERR(EINVAL);
@@ -3156,7 +3162,7 @@
  *
  * DRM infrastructure takes care of reclaiming dma buffers.
  */
-void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void radeon_driver_preclose(struct drm_device *dev, DRMFILE filp)
 {
 	if (dev->dev_private) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3167,7 +3173,7 @@
 	}
 }
 
-void radeon_driver_lastclose(drm_device_t * dev)
+void radeon_driver_lastclose(struct drm_device *dev)
 {
 	if (dev->dev_private) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3180,7 +3186,7 @@
 	radeon_do_release(dev);
 }
 
-int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
+int radeon_driver_open(struct drm_device *dev, struct drm_file *filp_priv)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	struct drm_radeon_driver_file_fields *radeon_priv;
@@ -3202,7 +3208,7 @@
 	return 0;
 }
 
-void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
+void radeon_driver_postclose(struct drm_device *dev, struct drm_file *filp_priv)
 {
 	struct drm_radeon_driver_file_fields *radeon_priv =
 	    filp_priv->driver_priv;
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index b94fab5..18c7235 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -32,7 +32,7 @@
 #define SAVAGE_EVENT_USEC_TIMEOUT	5000000	/* 5s */
 #define SAVAGE_FREELIST_DEBUG		0
 
-static int savage_do_cleanup_bci(drm_device_t *dev);
+static int savage_do_cleanup_bci(struct drm_device *dev);
 
 static int
 savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
@@ -203,11 +203,11 @@
 /*
  * Freelist management
  */
-static int savage_freelist_init(drm_device_t * dev)
+static int savage_freelist_init(struct drm_device * dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *buf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *buf;
 	drm_savage_buf_priv_t *entry;
 	int i;
 	DRM_DEBUG("count=%d\n", dma->buf_count);
@@ -236,7 +236,7 @@
 	return 0;
 }
 
-static drm_buf_t *savage_freelist_get(drm_device_t * dev)
+static struct drm_buf *savage_freelist_get(struct drm_device * dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
@@ -269,7 +269,7 @@
 	return NULL;
 }
 
-void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
@@ -535,7 +535,7 @@
 	dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
 }
 
-int savage_driver_load(drm_device_t *dev, unsigned long chipset)
+int savage_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	drm_savage_private_t *dev_priv;
 
@@ -558,7 +558,7 @@
  * in drm_addmap. Therefore we add them manually before the maps are
  * initialized, and tear them down on last close.
  */
-int savage_driver_firstopen(drm_device_t *dev)
+int savage_driver_firstopen(struct drm_device *dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	unsigned long mmio_base, fb_base, fb_size, aperture_base;
@@ -655,7 +655,7 @@
 /*
  * Delete MTRRs and free device-private data.
  */
-void savage_driver_lastclose(drm_device_t *dev)
+void savage_driver_lastclose(struct drm_device *dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	int i;
@@ -667,7 +667,7 @@
 				 dev_priv->mtrr[i].size, DRM_MTRR_WC);
 }
 
-int savage_driver_unload(drm_device_t *dev)
+int savage_driver_unload(struct drm_device *dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
@@ -676,7 +676,7 @@
 	return 0;
 }
 
-static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init)
+static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
@@ -711,7 +711,7 @@
 	dev_priv->texture_offset = init->texture_offset;
 	dev_priv->texture_size = init->texture_size;
 
-	DRM_GETSAREA();
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		savage_do_cleanup_bci(dev);
@@ -898,7 +898,7 @@
 	return 0;
 }
 
-static int savage_do_cleanup_bci(drm_device_t * dev)
+static int savage_do_cleanup_bci(struct drm_device * dev)
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
@@ -1007,9 +1007,9 @@
  * DMA buffer management
  */
 
-static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
+static int savage_bci_get_buffers(DRMFILE filp, struct drm_device *dev, struct drm_dma *d)
 {
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 	int i;
 
 	for (i = d->granted_count; i < d->request_count; i++) {
@@ -1034,13 +1034,13 @@
 int savage_bci_buffers(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
-	drm_device_dma_t *dma = dev->dma;
-	drm_dma_t d;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_dma d;
 	int ret = 0;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
-	DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *) data, sizeof(d));
+	DRM_COPY_FROM_USER_IOCTL(d, (struct drm_dma __user *) data, sizeof(d));
 
 	/* Please don't send us buffers.
 	 */
@@ -1064,14 +1064,14 @@
 		ret = savage_bci_get_buffers(filp, dev, &d);
 	}
 
-	DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *) data, d, sizeof(d));
+	DRM_COPY_TO_USER_IOCTL((struct drm_dma __user *) data, d, sizeof(d));
 
 	return ret;
 }
 
-void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
+void savage_reclaim_buffers(struct drm_device *dev, DRMFILE filp)
 {
-	drm_device_dma_t *dma = dev->dma;
+	struct drm_device_dma *dma = dev->dma;
 	drm_savage_private_t *dev_priv = dev->dev_private;
 	int i;
 
@@ -1085,7 +1085,7 @@
 	/*i830_flush_queue(dev); */
 
 	for (i = 0; i < dma->buf_count; i++) {
-		drm_buf_t *buf = dma->buflist[i];
+		struct drm_buf *buf = dma->buflist[i];
 		drm_savage_buf_priv_t *buf_priv = buf->dev_private;
 
 		if (buf->filp == filp && buf_priv &&
diff --git a/drivers/char/drm/savage_drm.h b/drivers/char/drm/savage_drm.h
index e1148e8..8a576ef 100644
--- a/drivers/char/drm/savage_drm.h
+++ b/drivers/char/drm/savage_drm.h
@@ -47,7 +47,7 @@
 typedef struct _drm_savage_sarea {
 	/* LRU lists for texture memory in agp space and on the card.
 	 */
-	drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
+	struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
 						      1];
 	unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
 
@@ -113,7 +113,7 @@
 	unsigned int vb_size;	/* size of client vertex buffer in bytes */
 	unsigned int vb_stride;	/* stride of vertices in 32bit words */
 	/* boxes in client's address space */
-	drm_clip_rect_t __user *box_addr;
+	struct drm_clip_rect __user *box_addr;
 	unsigned int nbox;	/* number of clipping boxes */
 } drm_savage_cmdbuf_t;
 
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
index 8f04b3d..5fd54de 100644
--- a/drivers/char/drm/savage_drv.h
+++ b/drivers/char/drm/savage_drv.h
@@ -58,7 +58,7 @@
 	struct drm_savage_buf_priv *next;
 	struct drm_savage_buf_priv *prev;
 	drm_savage_age_t age;
-	drm_buf_t *buf;
+	struct drm_buf *buf;
 } drm_savage_buf_priv_t;
 
 typedef struct drm_savage_dma_page {
@@ -192,7 +192,7 @@
 	/* Err, there is a macro wait_event in include/linux/wait.h.
 	 * Avoid unwanted macro expansion. */
 	void (*emit_clip_rect) (struct drm_savage_private * dev_priv,
-				const drm_clip_rect_t * pbox);
+				const struct drm_clip_rect * pbox);
 	void (*dma_flush) (struct drm_savage_private * dev_priv);
 } drm_savage_private_t;
 
@@ -203,22 +203,22 @@
 /* BCI functions */
 extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
 				      unsigned int flags);
-extern void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf);
+extern void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf);
 extern void savage_dma_reset(drm_savage_private_t * dev_priv);
 extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page);
 extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv,
 				  unsigned int n);
-extern int savage_driver_load(drm_device_t *dev, unsigned long chipset);
-extern int savage_driver_firstopen(drm_device_t *dev);
-extern void savage_driver_lastclose(drm_device_t *dev);
-extern int savage_driver_unload(drm_device_t *dev);
-extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp);
+extern int savage_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int savage_driver_firstopen(struct drm_device *dev);
+extern void savage_driver_lastclose(struct drm_device *dev);
+extern int savage_driver_unload(struct drm_device *dev);
+extern void savage_reclaim_buffers(struct drm_device * dev, DRMFILE filp);
 
 /* state functions */
 extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
-				      const drm_clip_rect_t * pbox);
+				      const struct drm_clip_rect * pbox);
 extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
-				     const drm_clip_rect_t * pbox);
+				     const struct drm_clip_rect * pbox);
 
 #define SAVAGE_FB_SIZE_S3	0x01000000	/*  16MB */
 #define SAVAGE_FB_SIZE_S4	0x02000000	/*  32MB */
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
index 1ca1e9c..7749784 100644
--- a/drivers/char/drm/savage_state.c
+++ b/drivers/char/drm/savage_state.c
@@ -27,7 +27,7 @@
 #include "savage_drv.h"
 
 void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
-			       const drm_clip_rect_t * pbox)
+			       const struct drm_clip_rect * pbox)
 {
 	uint32_t scstart = dev_priv->state.s3d.new_scstart;
 	uint32_t scend = dev_priv->state.s3d.new_scend;
@@ -53,7 +53,7 @@
 }
 
 void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
-			      const drm_clip_rect_t * pbox)
+			      const struct drm_clip_rect * pbox)
 {
 	uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
 	uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
@@ -277,7 +277,7 @@
 
 static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv,
 				    const drm_savage_cmd_header_t * cmd_header,
-				    const drm_buf_t * dmabuf)
+				    const struct drm_buf * dmabuf)
 {
 	unsigned char reorder = 0;
 	unsigned int prim = cmd_header->prim.prim;
@@ -536,7 +536,7 @@
 static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
 				   const drm_savage_cmd_header_t * cmd_header,
 				   const uint16_t *idx,
-				   const drm_buf_t * dmabuf)
+				   const struct drm_buf * dmabuf)
 {
 	unsigned char reorder = 0;
 	unsigned int prim = cmd_header->idx.prim;
@@ -792,7 +792,7 @@
 				 const drm_savage_cmd_header_t * cmd_header,
 				 const drm_savage_cmd_header_t *data,
 				 unsigned int nbox,
-				 const drm_clip_rect_t *boxes)
+				 const struct drm_clip_rect *boxes)
 {
 	unsigned int flags = cmd_header->clear0.flags;
 	unsigned int clear_cmd;
@@ -861,7 +861,7 @@
 }
 
 static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
-				unsigned int nbox, const drm_clip_rect_t *boxes)
+				unsigned int nbox, const struct drm_clip_rect *boxes)
 {
 	unsigned int swap_cmd;
 	unsigned int i;
@@ -892,11 +892,11 @@
 static int savage_dispatch_draw(drm_savage_private_t * dev_priv,
 				const drm_savage_cmd_header_t *start,
 				const drm_savage_cmd_header_t *end,
-				const drm_buf_t * dmabuf,
+				const struct drm_buf * dmabuf,
 				const unsigned int *vtxbuf,
 				unsigned int vb_size, unsigned int vb_stride,
 				unsigned int nbox,
-				const drm_clip_rect_t *boxes)
+				const struct drm_clip_rect *boxes)
 {
 	unsigned int i, j;
 	int ret;
@@ -957,13 +957,13 @@
 {
 	DRM_DEVICE;
 	drm_savage_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_buf_t *dmabuf;
+	struct drm_device_dma *dma = dev->dma;
+	struct drm_buf *dmabuf;
 	drm_savage_cmdbuf_t cmdbuf;
 	drm_savage_cmd_header_t *kcmd_addr = NULL;
 	drm_savage_cmd_header_t *first_draw_cmd;
 	unsigned int *kvb_addr = NULL;
-	drm_clip_rect_t *kbox_addr = NULL;
+	struct drm_clip_rect *kbox_addr = NULL;
 	unsigned int i, j;
 	int ret = 0;
 
@@ -1019,7 +1019,7 @@
 		cmdbuf.vb_addr = kvb_addr;
 	}
 	if (cmdbuf.nbox) {
-		kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t),
+		kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(struct drm_clip_rect),
 				       DRM_MEM_DRIVER);
 		if (kbox_addr == NULL) {
 			ret = DRM_ERR(ENOMEM);
@@ -1027,7 +1027,7 @@
 		}
 
 		if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr,
-				       cmdbuf.nbox * sizeof(drm_clip_rect_t))) {
+				       cmdbuf.nbox * sizeof(struct drm_clip_rect))) {
 			ret = DRM_ERR(EFAULT);
 			goto done;
 		}
@@ -1158,7 +1158,7 @@
 	/* If we didn't need to allocate them, these'll be NULL */
 	drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
 	drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER);
-	drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t),
+	drm_free(kbox_addr, cmdbuf.nbox * sizeof(struct drm_clip_rect),
 		 DRM_MEM_DRIVER);
 
 	return ret;
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 690e0af..1912f58 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -35,7 +35,7 @@
 	sisdrv_PCI_IDS
 };
 
-static int sis_driver_load(drm_device_t *dev, unsigned long chipset)
+static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	drm_sis_private_t *dev_priv;
 	int ret;
@@ -54,7 +54,7 @@
 	return ret;
 }
 
-static int sis_driver_unload(drm_device_t *dev)
+static int sis_driver_unload(struct drm_device *dev)
 {
 	drm_sis_private_t *dev_priv = dev->dev_private;
 
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index 2b8d6f6..5630df8 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -33,11 +33,11 @@
 
 #define DRIVER_AUTHOR		"SIS, Tungsten Graphics"
 #define DRIVER_NAME		"sis"
-#define DRIVER_DESC		"SIS 300/630/540"
-#define DRIVER_DATE		"20060704"
+#define DRIVER_DESC		"SIS 300/630/540 and XGI V3XE/V5/V8"
+#define DRIVER_DATE		"20070626"
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		2
-#define DRIVER_PATCHLEVEL	1
+#define DRIVER_MINOR		3
+#define DRIVER_PATCHLEVEL	0
 
 enum sis_family {
 	SIS_OTHER = 0,
@@ -46,6 +46,7 @@
 
 #include "drm_sman.h"
 
+
 #define SIS_BASE (dev_priv->mmio)
 #define SIS_READ(reg)         DRM_READ32(SIS_BASE, reg);
 #define SIS_WRITE(reg, val)   DRM_WRITE32(SIS_BASE, reg, val);
@@ -53,7 +54,7 @@
 typedef struct drm_sis_private {
 	drm_local_map_t *mmio;
 	unsigned int idle_fault;
-	drm_sman_t sman;
+	struct drm_sman sman;
 	unsigned int chipset;
 	int vram_initialized;
 	int agp_initialized;
@@ -61,9 +62,9 @@
 	unsigned long agp_offset;
 } drm_sis_private_t;
 
-extern int sis_idle(drm_device_t *dev);
-extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
-extern void sis_lastclose(drm_device_t *dev);
+extern int sis_idle(struct drm_device *dev);
+extern void sis_reclaim_buffers_locked(struct drm_device *dev, struct file *filp);
+extern void sis_lastclose(struct drm_device *dev);
 
 extern drm_ioctl_desc_t sis_ioctls[];
 extern int sis_max_ioctl;
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index d26f5db..441bbdb 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -94,7 +94,7 @@
 	mutex_lock(&dev->struct_mutex);
 #if defined(CONFIG_FB_SIS)
 	{
-		drm_sman_mm_t sman_mm;
+		struct drm_sman_mm sman_mm;
 		sman_mm.private = (void *)0xFFFFFFFF;
 		sman_mm.allocate = sis_sman_mm_allocate;
 		sman_mm.free = sis_sman_mm_free;
@@ -123,14 +123,14 @@
 	return 0;
 }
 
-static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv,
+static int sis_drm_alloc(struct drm_device *dev, struct drm_file * priv,
 			 unsigned long data, int pool)
 {
 	drm_sis_private_t *dev_priv = dev->dev_private;
 	drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data;
 	drm_sis_mem_t mem;
 	int retval = 0;
-	drm_memblock_item_t *item;
+	struct drm_memblock_item *item;
 
 	DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem));
 
@@ -229,12 +229,12 @@
 	return sis_drm_alloc(dev, priv, data, AGP_TYPE);
 }
 
-static drm_local_map_t *sis_reg_init(drm_device_t *dev)
+static drm_local_map_t *sis_reg_init(struct drm_device *dev)
 {
-	drm_map_list_t *entry;
+	struct drm_map_list *entry;
 	drm_local_map_t *map;
 
-	list_for_each_entry(entry, &dev->maplist->head, head) {
+	list_for_each_entry(entry, &dev->maplist, head) {
 		map = entry->map;
 		if (!map)
 			continue;
@@ -245,7 +245,7 @@
 	return NULL;
 }
 
-int sis_idle(drm_device_t *dev)
+int sis_idle(struct drm_device *dev)
 {
 	drm_sis_private_t *dev_priv = dev->dev_private;
 	uint32_t idle_reg;
@@ -314,10 +314,10 @@
 	mutex_unlock(&dev->struct_mutex);
 }
 
-void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void sis_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
 {
 	drm_sis_private_t *dev_priv = dev->dev_private;
-	drm_file_t *priv = filp->private_data;
+	struct drm_file *priv = filp->private_data;
 
 	mutex_lock(&dev->struct_mutex);
 	if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index 13a9c5c..7ff2b62 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -151,7 +151,7 @@
 	return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
 }
 
-int via_dma_cleanup(drm_device_t * dev)
+int via_dma_cleanup(struct drm_device * dev)
 {
 	if (dev->dev_private) {
 		drm_via_private_t *dev_priv =
@@ -169,7 +169,7 @@
 	return 0;
 }
 
-static int via_initialize(drm_device_t * dev,
+static int via_initialize(struct drm_device * dev,
 			  drm_via_private_t * dev_priv,
 			  drm_via_dma_init_t * init)
 {
@@ -262,7 +262,7 @@
 	return retcode;
 }
 
-static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
+static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * cmd)
 {
 	drm_via_private_t *dev_priv;
 	uint32_t *vb;
@@ -316,7 +316,7 @@
 	return 0;
 }
 
-int via_driver_dma_quiescent(drm_device_t * dev)
+int via_driver_dma_quiescent(struct drm_device * dev)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
 
@@ -356,7 +356,7 @@
 	return 0;
 }
 
-static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
+static int via_dispatch_pci_cmdbuffer(struct drm_device * dev,
 				      drm_via_cmdbuffer_t * cmd)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 2881a06..fdb8609 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -207,7 +207,7 @@
  */
 
 static void
-via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)
+via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -289,7 +289,7 @@
 }
 			
 static void
-via_abort_dmablit(drm_device_t *dev, int engine)
+via_abort_dmablit(struct drm_device *dev, int engine)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -297,7 +297,7 @@
 }
 
 static void
-via_dmablit_engine_off(drm_device_t *dev, int engine)
+via_dmablit_engine_off(struct drm_device *dev, int engine)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -314,7 +314,7 @@
  */
 		
 void
-via_dmablit_handler(drm_device_t *dev, int engine, int from_irq)
+via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 	drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
@@ -433,7 +433,7 @@
  */
 
 static int
-via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine) 
+via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine) 
 {
 
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -466,7 +466,7 @@
 via_dmablit_timer(unsigned long data)
 {
 	drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
-	drm_device_t *dev = blitq->dev;
+	struct drm_device *dev = blitq->dev;
 	int engine = (int)
 		(blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
 		
@@ -502,7 +502,7 @@
 via_dmablit_workqueue(struct work_struct *work)
 {
 	drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
-	drm_device_t *dev = blitq->dev;
+	struct drm_device *dev = blitq->dev;
 	unsigned long irqsave;
 	drm_via_sg_info_t *cur_sg;
 	int cur_released;
@@ -545,7 +545,7 @@
 
 
 void
-via_init_dmablit(drm_device_t *dev)
+via_init_dmablit(struct drm_device *dev)
 {
 	int i,j;
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -582,7 +582,7 @@
 		
 
 static int
-via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
 {
 	int draw = xfer->to_fb;
 	int ret = 0;
@@ -730,7 +730,7 @@
 
 
 static int 
-via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)	 
+via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer)	 
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 	drm_via_sg_info_t *vsg;
diff --git a/drivers/char/drm/via_dmablit.h b/drivers/char/drm/via_dmablit.h
index f4036cd..6f6a513 100644
--- a/drivers/char/drm/via_dmablit.h
+++ b/drivers/char/drm/via_dmablit.h
@@ -59,7 +59,7 @@
 } drm_via_sg_info_t;
 
 typedef struct _drm_via_blitq {
-	drm_device_t *dev;
+	struct drm_device *dev;
 	uint32_t cur_blit_handle;
 	uint32_t done_blit_handle;
 	unsigned serviced;
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
index e4ee97d..8f53c76 100644
--- a/drivers/char/drm/via_drm.h
+++ b/drivers/char/drm/via_drm.h
@@ -40,7 +40,7 @@
 #define VIA_NR_XVMC_LOCKS               5
 #define VIA_MAX_CACHELINE_SIZE          64
 #define XVMCLOCKPTR(saPriv,lockNo)					\
-	((volatile drm_hw_lock_t *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
+	((volatile struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
 				      (VIA_MAX_CACHELINE_SIZE - 1)) &	\
 				     ~(VIA_MAX_CACHELINE_SIZE - 1)) +	\
 				    VIA_MAX_CACHELINE_SIZE*(lockNo)))
@@ -182,7 +182,7 @@
 typedef struct _drm_via_sarea {
 	unsigned int dirty;
 	unsigned int nbox;
-	drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS];
+	struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS];
 	drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1];
 	int texAge;		/* last time texture was uploaded */
 	int ctxOwner;		/* last context to upload state */
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index b46ca8e6..5767115 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -87,7 +87,7 @@
 	uint32_t irq_pending_mask;
 	int *irq_map;
 	unsigned int idle_fault;
-	drm_sman_t sman;
+	struct drm_sman sman;
 	int vram_initialized;
 	int agp_initialized;
 	unsigned long vram_offset;
@@ -123,31 +123,31 @@
 extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
 extern int via_dma_blit( DRM_IOCTL_ARGS );
 
-extern int via_driver_load(drm_device_t *dev, unsigned long chipset);
-extern int via_driver_unload(drm_device_t *dev);
+extern int via_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int via_driver_unload(struct drm_device *dev);
 
-extern int via_init_context(drm_device_t * dev, int context);
-extern int via_final_context(drm_device_t * dev, int context);
+extern int via_init_context(struct drm_device * dev, int context);
+extern int via_final_context(struct drm_device * dev, int context);
 
-extern int via_do_cleanup_map(drm_device_t * dev);
-extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int via_do_cleanup_map(struct drm_device * dev);
+extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 
 extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
-extern void via_driver_irq_preinstall(drm_device_t * dev);
-extern void via_driver_irq_postinstall(drm_device_t * dev);
-extern void via_driver_irq_uninstall(drm_device_t * dev);
+extern void via_driver_irq_preinstall(struct drm_device * dev);
+extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern void via_driver_irq_uninstall(struct drm_device * dev);
 
-extern int via_dma_cleanup(drm_device_t * dev);
+extern int via_dma_cleanup(struct drm_device * dev);
 extern void via_init_command_verifier(void);
-extern int via_driver_dma_quiescent(drm_device_t * dev);
+extern int via_driver_dma_quiescent(struct drm_device * dev);
 extern void via_init_futex(drm_via_private_t * dev_priv);
 extern void via_cleanup_futex(drm_via_private_t * dev_priv);
 extern void via_release_futex(drm_via_private_t * dev_priv, int context);
 
-extern void via_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
-extern void via_lastclose(drm_device_t *dev);
+extern void via_reclaim_buffers_locked(struct drm_device *dev, struct file *filp);
+extern void via_lastclose(struct drm_device *dev);
 
-extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
-extern void via_init_dmablit(drm_device_t *dev);
+extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
+extern void via_init_dmablit(struct drm_device *dev);
 
 #endif
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index 1ac5941..8dc99b5 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -98,7 +98,7 @@
 
 irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	drm_device_t *dev = (drm_device_t *) arg;
+	struct drm_device *dev = (struct drm_device *) arg;
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
 	int handled = 0;
@@ -163,7 +163,7 @@
 	}
 }
 
-int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	unsigned int cur_vblank;
@@ -191,7 +191,7 @@
 }
 
 static int
-via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
+via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequence,
 		    unsigned int *sequence)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -244,7 +244,7 @@
  * drm_dma.h hooks
  */
 
-void via_driver_irq_preinstall(drm_device_t * dev)
+void via_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
@@ -293,7 +293,7 @@
 	}
 }
 
-void via_driver_irq_postinstall(drm_device_t * dev)
+void via_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
@@ -312,7 +312,7 @@
 	}
 }
 
-void via_driver_irq_uninstall(drm_device_t * dev)
+void via_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index 4e3fc07..7fb9d2a 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -25,13 +25,13 @@
 #include "via_drm.h"
 #include "via_drv.h"
 
-static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
+static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
 
-	DRM_GETSAREA();
+	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		dev->dev_private = (void *)dev_priv;
@@ -68,7 +68,7 @@
 	return 0;
 }
 
-int via_do_cleanup_map(drm_device_t * dev)
+int via_do_cleanup_map(struct drm_device * dev)
 {
 	via_dma_cleanup(dev);
 
@@ -95,7 +95,7 @@
 	return -EINVAL;
 }
 
-int via_driver_load(drm_device_t *dev, unsigned long chipset)
+int via_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	drm_via_private_t *dev_priv;
 	int ret = 0;
@@ -115,7 +115,7 @@
 	return ret;
 }
 
-int via_driver_unload(drm_device_t *dev)
+int via_driver_unload(struct drm_device *dev)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
 
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index 2fcf057..85d56ac 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -127,7 +127,7 @@
 
 	drm_via_mem_t mem;
 	int retval = 0;
-	drm_memblock_item_t *item;
+	struct drm_memblock_item *item;
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	unsigned long tmpSize;
 
@@ -188,10 +188,10 @@
 }
 
 
-void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void via_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
-	drm_file_t *priv = filp->private_data;
+	struct drm_file *priv = filp->private_data;
 
 	mutex_lock(&dev->struct_mutex);
 	if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
index 2e7e080..832d483 100644
--- a/drivers/char/drm/via_verifier.c
+++ b/drivers/char/drm/via_verifier.c
@@ -252,10 +252,9 @@
 static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
 						    unsigned long offset,
 						    unsigned long size,
-						    drm_device_t * dev)
+						    struct drm_device * dev)
 {
-	struct list_head *list;
-	drm_map_list_t *r_list;
+	struct drm_map_list *r_list;
 	drm_local_map_t *map = seq->map_cache;
 
 	if (map && map->offset <= offset
@@ -263,8 +262,7 @@
 		return map;
 	}
 
-	list_for_each(list, &dev->maplist->head) {
-		r_list = (drm_map_list_t *) list;
+	list_for_each_entry(r_list, &dev->maplist, head) {
 		map = r_list->map;
 		if (!map)
 			continue;
@@ -964,7 +962,7 @@
 
 int
 via_verify_command_stream(const uint32_t * buf, unsigned int size,
-			  drm_device_t * dev, int agp)
+			  struct drm_device * dev, int agp)
 {
 
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -1039,7 +1037,7 @@
 }
 
 int
-via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+via_parse_command_stream(struct drm_device * dev, const uint32_t * buf,
 			 unsigned int size)
 {
 
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
index b77f59d..28b5029 100644
--- a/drivers/char/drm/via_verifier.h
+++ b/drivers/char/drm/via_verifier.h
@@ -47,7 +47,7 @@
 	drm_via_sequence_t unfinished;
 	int agp_texture;
 	int multitex;
-	drm_device_t *dev;
+	struct drm_device *dev;
 	drm_local_map_t *map_cache;
 	uint32_t vertex_count;
 	int agp;
@@ -55,8 +55,8 @@
 } drm_via_state_t;
 
 extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
-				     drm_device_t * dev, int agp);
-extern int via_parse_command_stream(drm_device_t *dev, const uint32_t *buf,
+				     struct drm_device * dev, int agp);
+extern int via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
 				    unsigned int size);
 
 #endif
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index d1bfbaa..74cd511 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1121,8 +1121,6 @@
 	/*
 	 * Set up parity check flag
 	 */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
 	if (I_INPCK(info->tty))
 		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
@@ -1920,11 +1918,6 @@
 	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
 	unsigned long flags;
 
-	if (   (tty->termios->c_cflag == old_termios->c_cflag)
-	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-		return;
-
 	change_speed(info);
 
 	spin_lock_irqsave(&info->lock, flags);
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 8ea0275..8facf3e 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -43,16 +43,6 @@
 
 #define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
 #define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __FUNCTION__)
-#define NEW_WRITE_LOCKING 1
-#if NEW_WRITE_LOCKING
-#define DECL      /* Nothing */
-#define LOCKIT    mutex_lock(& port->port_write_mutex);
-#define RELEASEIT mutex_unlock(&port->port_write_mutex);
-#else
-#define DECL      unsigned long flags;
-#define LOCKIT    save_flags (flags);cli ()
-#define RELEASEIT restore_flags (flags)
-#endif
 
 #define RS_EVENT_WRITE_WAKEUP	1
 
@@ -62,7 +52,6 @@
 void gs_put_char(struct tty_struct * tty, unsigned char ch)
 {
 	struct gs_port *port;
-	DECL
 
 	func_enter (); 
 
@@ -75,11 +64,11 @@
 	if (! (port->flags & ASYNC_INITIALIZED)) return;
 
 	/* Take a lock on the serial tranmit buffer! */
-	LOCKIT;
+	mutex_lock(& port->port_write_mutex);
 
 	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
 		/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
-		RELEASEIT;
+		mutex_unlock(&port->port_write_mutex);
 		return;
 	}
 
@@ -87,13 +76,11 @@
 	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
 	port->xmit_cnt++;  /* Characters in buffer */
 
-	RELEASEIT;
+	mutex_unlock(&port->port_write_mutex);
 	func_exit ();
 }
 
 
-#ifdef NEW_WRITE_LOCKING
-
 /*
 > Problems to take into account are:
 >       -1- Interrupts that empty part of the buffer.
@@ -166,90 +153,6 @@
 	func_exit ();
 	return total;
 }
-#else
-/*
-> Problems to take into account are:
->       -1- Interrupts that empty part of the buffer.
->       -2- page faults on the access to userspace. 
->       -3- Other processes that are also trying to do a "write". 
-*/
-
-int gs_write(struct tty_struct * tty,
-                    const unsigned char *buf, int count)
-{
-	struct gs_port *port;
-	int c, total = 0;
-	int t;
-	unsigned long flags;
-
-	func_enter ();
-
-	/* The standard serial driver returns 0 in this case. 
-	   That sounds to me as "No error, I just didn't get to writing any
-	   bytes. Feel free to try again." 
-	   The "official" way to write n bytes from buf is:
-
-		 for (nwritten = 0;nwritten < n;nwritten += rv) {
-			 rv = write (fd, buf+nwritten, n-nwritten);
-			 if (rv < 0) break; // Error: bail out. //
-		 } 
-
-	   which will loop endlessly in this case. The manual page for write
-	   agrees with me. In practise almost everybody writes 
-	   "write (fd, buf,n);" but some people might have had to deal with 
-	   incomplete writes in the past and correctly implemented it by now... 
-	 */
-
-	if (!tty) return -EIO;
-
-	port = tty->driver_data;
-	if (!port || !port->xmit_buf)
-		return -EIO;
-
-	local_save_flags(flags);
-	while (1) {
-		cli();
-		c = count;
-
-		/* This is safe because we "OWN" the "head". Noone else can 
-		   change the "head": we own the port_write_mutex. */
-		/* Don't overrun the end of the buffer */
-		t = SERIAL_XMIT_SIZE - port->xmit_head;
-		if (t < c) c = t;
-
-		/* This is safe because the xmit_cnt can only decrease. This 
-		   would increase "t", so we might copy too little chars. */
-		/* Don't copy past the "head" of the buffer */
-		t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
-		if (t < c) c = t;
-
-		/* Can't copy more? break out! */
-		if (c <= 0) {
-			local_restore_flags(flags);
-			break;
-		}
-		memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = ((port->xmit_head + c) &
-		                   (SERIAL_XMIT_SIZE-1));
-		port->xmit_cnt += c;
-		local_restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (port->xmit_cnt && 
-	    !tty->stopped && 
-	    !tty->hw_stopped &&
-	    !(port->flags & GS_TX_INTEN)) {
-		port->flags |= GS_TX_INTEN;
-		port->rd->enable_tx_interrupts (port);
-	}
-	func_exit ();
-	return total;
-}
-
-#endif
 
 
 
@@ -737,23 +640,6 @@
 		gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
 	}
 
-	/* This is an optimization that is only allowed for dumb cards */
-	/* Smart cards require knowledge of iflags and oflags too: that 
-	   might change hardware cooking mode.... */
-	if (old_termios) {
-		if(   (tiosp->c_iflag == old_termios->c_iflag)
-		   && (tiosp->c_oflag == old_termios->c_oflag)
-		   && (tiosp->c_cflag == old_termios->c_cflag)
-		   && (tiosp->c_lflag == old_termios->c_lflag)
-		   && (tiosp->c_line  == old_termios->c_line)
-		   && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) {
-			gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n");
-			return /* 0 */;
-		}
-	} else 
-		gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: "
-		           "no optimization\n");
-
 	if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) {
 		if(tiosp->c_iflag != old_termios->c_iflag)  printk("c_iflag changed\n");
 		if(tiosp->c_oflag != old_termios->c_oflag)  printk("c_oflag changed\n");
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index 9e1fc02..69f0a29 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -173,7 +173,6 @@
 static ssize_t gen_rtc_read(struct file *file, char __user *buf,
 			size_t count, loff_t *ppos)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	unsigned long data;
 	ssize_t retval;
 
@@ -183,18 +182,10 @@
 	if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
 		return -EAGAIN;
 
-	add_wait_queue(&gen_rtc_wait, &wait);
-	retval = -ERESTARTSYS;
-
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		data = xchg(&gen_rtc_irq_data, 0);
-		if (data)
-			break;
-		if (signal_pending(current))
-			goto out;
-		schedule();
-	}
+	retval = wait_event_interruptible(gen_rtc_wait,
+			(data = xchg(&gen_rtc_irq_data, 0)));
+	if (retval)
+		goto out;
 
 	/* first test allows optimizer to nuke this case for 32-bit machines */
 	if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
@@ -206,10 +197,7 @@
 		retval = put_user(data, (unsigned long __user *)buf) ?:
 			sizeof(unsigned long);
 	}
- out:
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&gen_rtc_wait, &wait);
-
+out:
 	return retval;
 }
 
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index f0e7263..0e8ceea 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -48,7 +48,7 @@
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <linux/sysrq.h>
-
+#include <linux/timer.h>
 
 #define VERSION_STR "0.9.0"
 
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 322bc5f..83c1151 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -674,11 +674,12 @@
  * calling hvc_poll() who determines whether a console adapter support
  * interrupts.
  */
-int khvcd(void *unused)
+static int khvcd(void *unused)
 {
 	int poll_mask;
 	struct hvc_struct *hp;
 
+	set_freezable();
 	__set_current_state(TASK_RUNNING);
 	do {
 		poll_mask = 0;
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 4ae9811..753f460 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -296,12 +296,10 @@
 	     (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
 	    == BIOS_CNTL_LOCK_ENABLE_MASK) {
 		static __initdata /*const*/ char warning[] =
-			KERN_WARNING PFX "Firmware space is locked read-only. "
-			KERN_WARNING PFX "If you can't or\n don't want to "
-			KERN_WARNING PFX "disable this in firmware setup, and "
-			KERN_WARNING PFX "if\n you are certain that your "
-			KERN_WARNING PFX "system has a functional\n RNG, try"
-			KERN_WARNING PFX "using the 'no_fwh_detect' option.\n";
+			KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
+			KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
+			KERN_WARNING PFX "you are certain that your system has a functional\n"
+			KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
 
 		if (no_fwh_detect)
 			return -ENODEV;
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c
index dd761a1..61ef013 100644
--- a/drivers/char/ip2/i2ellis.c
+++ b/drivers/char/ip2/i2ellis.c
@@ -43,8 +43,6 @@
 static void iiWriteMaskII(i2eBordStrPtr, unsigned char);
 static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char);
 
-static void ii2DelayTimer(unsigned int);
-static void ii2DelayWakeup(unsigned long id);
 static void ii2Nop(void);
 
 //***************
@@ -55,8 +53,6 @@
 
 static int iiDelayed;	// Set when the iiResetDelay function is
 							// called. Cleared when ANY board is reset.
-static struct timer_list * pDelayTimer;   // Used by iiDelayTimer
-static wait_queue_head_t pDelayWait;    // Used by iiDelayTimer
 static rwlock_t Dl_spinlock;
 
 //********
@@ -86,9 +82,6 @@
 static void
 iiEllisInit(void)
 {
-	pDelayTimer = kmalloc ( sizeof (struct timer_list), GFP_KERNEL );
-	init_timer(pDelayTimer);
-	init_waitqueue_head(&pDelayWait);
 	LOCK_INIT(&Dl_spinlock);
 }
 
@@ -106,7 +99,6 @@
 static void
 iiEllisCleanup(void)
 {
-	kfree(pDelayTimer);
 }
 
 //******************************************************************************
@@ -560,19 +552,6 @@
 	COMPLETE(pB, I2EE_GOOD);
 }
 
-//=======================================================
-// Delay Routines
-//
-// iiDelayIO
-// iiNop
-//=======================================================
-
-static void
-ii2DelayWakeup(unsigned long id)
-{
-	wake_up_interruptible ( &pDelayWait );
-}
-
 //******************************************************************************
 // Function:   ii2DelayTimer(mseconds)
 // Parameters: mseconds - number of milliseconds to delay
@@ -594,28 +573,7 @@
 static void
 ii2DelayTimer(unsigned int mseconds)
 {
-	wait_queue_t wait;
-
-	init_waitqueue_entry(&wait, current);
-
-	init_timer ( pDelayTimer );
-
-	add_wait_queue(&pDelayWait, &wait);
-
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	pDelayTimer->expires  = jiffies + ( mseconds + 9 ) / 10;
-	pDelayTimer->function = ii2DelayWakeup;
-	pDelayTimer->data     = 0;
-
-	add_timer ( pDelayTimer );
-
-	schedule();
-
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pDelayWait, &wait);
-
-	del_timer ( pDelayTimer );
+	msleep_interruptible(mseconds);
 }
 
 #if 0
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index b894f67..0baa8fa 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -2,11 +2,9 @@
 # IPMI device configuration
 #
 
-menu "IPMI"
-	depends on HAS_IOMEM
-
-config IPMI_HANDLER
+menuconfig IPMI_HANDLER
        tristate 'IPMI top-level message handler'
+       depends on HAS_IOMEM
        help
          This enables the central IPMI message handler, required for IPMI
 	 to work.
@@ -18,9 +16,10 @@
 
 	 If unsure, say N.
 
+if IPMI_HANDLER
+
 config IPMI_PANIC_EVENT
        bool 'Generate a panic event to all BMCs on a panic'
-       depends on IPMI_HANDLER
        help
          When a panic occurs, this will cause the IPMI message handler to
 	 generate an IPMI event describing the panic to each interface
@@ -40,14 +39,12 @@
 
 config IPMI_DEVICE_INTERFACE
        tristate 'Device interface for IPMI'
-       depends on IPMI_HANDLER
        help
          This provides an IOCTL interface to the IPMI message handler so
 	 userland processes may use IPMI.  It supports poll() and select().
 
 config IPMI_SI
        tristate 'IPMI System Interface handler'
-       depends on IPMI_HANDLER
        help
          Provides a driver for System Interfaces (KCS, SMIC, BT).
 	 Currently, only KCS and SMIC are supported.  If
@@ -55,15 +52,13 @@
 
 config IPMI_WATCHDOG
        tristate 'IPMI Watchdog Timer'
-       depends on IPMI_HANDLER
        help
          This enables the IPMI watchdog timer.
 
 config IPMI_POWEROFF
        tristate 'IPMI Poweroff'
-       depends on IPMI_HANDLER
        help
          This enables a function to power off the system with IPMI if
 	 the IPMI management controller is capable of this.
 
-endmenu
+endif # IPMI_HANDLER
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 8e222f2..b5df7e6 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2171,52 +2171,42 @@
 	int err;
 
 	bmc->device_id_attr.attr.name = "device_id";
-	bmc->device_id_attr.attr.owner = THIS_MODULE;
 	bmc->device_id_attr.attr.mode = S_IRUGO;
 	bmc->device_id_attr.show = device_id_show;
 
 	bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
-	bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
 	bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
 	bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
 
 	bmc->revision_attr.attr.name = "revision";
-	bmc->revision_attr.attr.owner = THIS_MODULE;
 	bmc->revision_attr.attr.mode = S_IRUGO;
 	bmc->revision_attr.show = revision_show;
 
 	bmc->firmware_rev_attr.attr.name = "firmware_revision";
-	bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
 	bmc->firmware_rev_attr.attr.mode = S_IRUGO;
 	bmc->firmware_rev_attr.show = firmware_rev_show;
 
 	bmc->version_attr.attr.name = "ipmi_version";
-	bmc->version_attr.attr.owner = THIS_MODULE;
 	bmc->version_attr.attr.mode = S_IRUGO;
 	bmc->version_attr.show = ipmi_version_show;
 
 	bmc->add_dev_support_attr.attr.name = "additional_device_support";
-	bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
 	bmc->add_dev_support_attr.attr.mode = S_IRUGO;
 	bmc->add_dev_support_attr.show = add_dev_support_show;
 
 	bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
-	bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
 	bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
 	bmc->manufacturer_id_attr.show = manufacturer_id_show;
 
 	bmc->product_id_attr.attr.name = "product_id";
-	bmc->product_id_attr.attr.owner = THIS_MODULE;
 	bmc->product_id_attr.attr.mode = S_IRUGO;
 	bmc->product_id_attr.show = product_id_show;
 
 	bmc->guid_attr.attr.name = "guid";
-	bmc->guid_attr.attr.owner = THIS_MODULE;
 	bmc->guid_attr.attr.mode = S_IRUGO;
 	bmc->guid_attr.show = guid_show;
 
 	bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
-	bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
 	bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
 	bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
 
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index e02893b..b86186d 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -679,7 +679,7 @@
 {
 	int rv;
 
-	printk ("Copyright (C) 2004 MontaVista Software -"
+	printk (KERN_INFO "Copyright (C) 2004 MontaVista Software -"
 		" IPMI Powerdown via sys_reboot.\n");
 
 	if (poweroff_powercycle)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 78e1b96..4edfdda 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2857,7 +2857,7 @@
 
 	mutex_unlock(&smi_infos_lock);
 
-	printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
+	printk(KERN_INFO "IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
 
 	return 0;
 
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 761f777..77a7a4a 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -171,9 +171,6 @@
 static int prev_card = 3;	/*	start servicing isi_card[0]	*/
 static struct tty_driver *isicom_normal;
 
-static DECLARE_COMPLETION(isi_timerdone);
-static char re_schedule = 1;
-
 static void isicom_tx(unsigned long _data);
 static void isicom_start(struct tty_struct *tty);
 
@@ -187,7 +184,7 @@
 
 struct	isi_board {
 	unsigned long		base;
-	unsigned char		irq;
+	int			irq;
 	unsigned char		port_count;
 	unsigned short		status;
 	unsigned short		port_status; /* each bit for each port */
@@ -227,7 +224,7 @@
  *	it wants to talk.
  */
 
-static inline int WaitTillCardIsFree(u16 base)
+static inline int WaitTillCardIsFree(unsigned long base)
 {
 	unsigned int count = 0;
 	unsigned int a = in_atomic(); /* do we run under spinlock? */
@@ -243,17 +240,18 @@
 
 static int lock_card(struct isi_board *card)
 {
-	char		retries;
 	unsigned long base = card->base;
+	unsigned int retries, a;
 
-	for (retries = 0; retries < 100; retries++) {
+	for (retries = 0; retries < 10; retries++) {
 		spin_lock_irqsave(&card->card_lock, card->flags);
-		if (inw(base + 0xe) & 0x1) {
-			return 1;
-		} else {
-			spin_unlock_irqrestore(&card->card_lock, card->flags);
-			udelay(1000);   /* 1ms */
+		for (a = 0; a < 10; a++) {
+			if (inw(base + 0xe) & 0x1)
+				return 1;
+			udelay(10);
 		}
+		spin_unlock_irqrestore(&card->card_lock, card->flags);
+		msleep(10);
 	}
 	printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
 		card->base);
@@ -261,23 +259,6 @@
 	return 0;	/* Failed to acquire the card! */
 }
 
-static int lock_card_at_interrupt(struct isi_board *card)
-{
-	unsigned char		retries;
-	unsigned long base = card->base;
-
-	for (retries = 0; retries < 200; retries++) {
-		spin_lock_irqsave(&card->card_lock, card->flags);
-
-		if (inw(base + 0xe) & 0x1)
-			return 1;
-		else
-			spin_unlock_irqrestore(&card->card_lock, card->flags);
-	}
-	/* Failing in interrupt is an acceptable event */
-	return 0;	/* Failed to acquire the card! */
-}
-
 static void unlock_card(struct isi_board *card)
 {
 	spin_unlock_irqrestore(&card->card_lock, card->flags);
@@ -415,7 +396,9 @@
 
 static void isicom_tx(unsigned long _data)
 {
-	short count = (BOARD_COUNT-1), card, base;
+	unsigned long flags, base;
+	unsigned int retries;
+	short count = (BOARD_COUNT-1), card;
 	short txcount, wrd, residue, word_count, cnt;
 	struct isi_port *port;
 	struct tty_struct *tty;
@@ -435,32 +418,34 @@
 	count = isi_card[card].port_count;
 	port = isi_card[card].ports;
 	base = isi_card[card].base;
+
+	spin_lock_irqsave(&isi_card[card].card_lock, flags);
+	for (retries = 0; retries < 100; retries++) {
+		if (inw(base + 0xe) & 0x1)
+			break;
+		udelay(2);
+	}
+	if (retries >= 100)
+		goto unlock;
+
 	for (;count > 0;count--, port++) {
-		if (!lock_card_at_interrupt(&isi_card[card]))
-			continue;
 		/* port not active or tx disabled to force flow control */
 		if (!(port->flags & ASYNC_INITIALIZED) ||
 				!(port->status & ISI_TXOK))
-			unlock_card(&isi_card[card]);
 			continue;
 
 		tty = port->tty;
 
-
-		if (tty == NULL) {
-			unlock_card(&isi_card[card]);
+		if (tty == NULL)
 			continue;
-		}
 
 		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
-		if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
-			unlock_card(&isi_card[card]);
+		if (txcount <= 0 || tty->stopped || tty->hw_stopped)
 			continue;
-		}
-		if (!(inw(base + 0x02) & (1 << port->channel))) {
-			unlock_card(&isi_card[card]);
+
+		if (!(inw(base + 0x02) & (1 << port->channel)))
 			continue;
-		}
+
 		pr_dbg("txing %d bytes, port%d.\n", txcount,
 			port->channel + 1);
 		outw((port->channel << isi_card[card].shift_count) | txcount,
@@ -508,16 +493,12 @@
 			port->status &= ~ISI_TXOK;
 		if (port->xmit_cnt <= WAKEUP_CHARS)
 			tty_wakeup(tty);
-		unlock_card(&isi_card[card]);
 	}
 
+unlock:
+	spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
 	/*	schedule another tx for hopefully in about 10ms	*/
 sched_again:
-	if (!re_schedule) {
-		complete(&isi_timerdone);
- 		return;
-	}
-
 	mod_timer(&tx, jiffies + msecs_to_jiffies(10));
 }
 
@@ -1749,17 +1730,13 @@
 static int __devinit isicom_probe(struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
-	unsigned int ioaddr, signature, index;
+	unsigned int signature, index;
 	int retval = -EPERM;
-	u8 pciirq;
 	struct isi_board *board = NULL;
 
 	if (card_count >= BOARD_COUNT)
 		goto err;
 
-	ioaddr = pci_resource_start(pdev, 3);
-	/* i.e at offset 0x1c in the PCI configuration register space. */
-	pciirq = pdev->irq;
 	dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
 
 	/* allot the first empty slot in the array */
@@ -1770,8 +1747,8 @@
 		}
 
 	board->index = index;
-	board->base = ioaddr;
-	board->irq = pciirq;
+	board->base = pci_resource_start(pdev, 3);
+	board->irq = pdev->irq;
 	card_count++;
 
 	pci_set_drvdata(pdev, board);
@@ -1901,9 +1878,7 @@
 
 static void __exit isicom_exit(void)
 {
-	re_schedule = 0;
-
-	wait_for_completion_timeout(&isi_timerdone, HZ);
+	del_timer_sync(&tx);
 
 	pci_unregister_driver(&isicom_driver);
 	tty_unregister_driver(isicom_normal);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 7b279d1..3c66f40 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -1753,9 +1753,6 @@
 		return;
 
 	tiosp = tty->termios;
-	if ((tiosp->c_cflag == old->c_cflag) &&
-	    (tiosp->c_iflag == old->c_iflag))
-		return;
 
 	stli_mkasyport(portp, &aport, tiosp);
 	stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
@@ -2166,14 +2163,10 @@
 	cdkhdr_t __iomem *hdrp;
 	cdkctrl_t __iomem *cp;
 	unsigned char __iomem *bits;
-	unsigned long flags;
-
-	spin_lock_irqsave(&brd_lock, flags);
 
 	if (test_bit(ST_CMDING, &portp->state)) {
 		printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n",
 				(int) cmd);
-		spin_unlock_irqrestore(&brd_lock, flags);
 		return;
 	}
 
@@ -2194,7 +2187,6 @@
 	writeb(readb(bits) | portp->portbit, bits);
 	set_bit(ST_CMDING, &portp->state);
 	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
@@ -3218,13 +3210,13 @@
 		goto err;
 	}
 
+	brdp->iosize = ECP_IOSIZE;
+
 	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
 		retval = -EIO;
 		goto err;
 	}
 
-	brdp->iosize = ECP_IOSIZE;
-
 /*
  *	Based on the specific board type setup the common vars to access
  *	and enable shared memory. Set all board specific information now
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 1b09450..2ce0af1 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -24,6 +24,7 @@
  * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
  */
 
+#include <linux/consolemap.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/tty.h>
@@ -308,10 +309,9 @@
  * Many other routines do put_queue, but I think either
  * they produce ASCII, or they produce some user-assigned
  * string, and in both cases we might assume that it is
- * in utf-8 already. UTF-8 is defined for words of up to 31 bits,
- * but we need only 16 bits here
+ * in utf-8 already.
  */
-static void to_utf8(struct vc_data *vc, ushort c)
+static void to_utf8(struct vc_data *vc, uint c)
 {
 	if (c < 0x80)
 		/*  0******* */
@@ -320,11 +320,21 @@
 		/* 110***** 10****** */
 		put_queue(vc, 0xc0 | (c >> 6));
 		put_queue(vc, 0x80 | (c & 0x3f));
-	} else {
+    	} else if (c < 0x10000) {
+	       	if (c >= 0xD800 && c < 0xE000)
+			return;
+		if (c == 0xFFFF)
+			return;
 		/* 1110**** 10****** 10****** */
 		put_queue(vc, 0xe0 | (c >> 12));
 		put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
 		put_queue(vc, 0x80 | (c & 0x3f));
+    	} else if (c < 0x110000) {
+		/* 11110*** 10****** 10****** 10****** */
+		put_queue(vc, 0xf0 | (c >> 18));
+		put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
+		put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
+		put_queue(vc, 0x80 | (c & 0x3f));
 	}
 }
 
@@ -393,7 +403,7 @@
 		return d;
 
 	if (kbd->kbdmode == VC_UNICODE)
-		to_utf8(vc, d);
+		to_utf8(vc, conv_8bit_to_uni(d));
 	else if (d < 0x100)
 		put_queue(vc, d);
 
@@ -407,7 +417,7 @@
 {
 	if (diacr) {
 		if (kbd->kbdmode == VC_UNICODE)
-			to_utf8(vc, diacr);
+			to_utf8(vc, conv_8bit_to_uni(diacr));
 		else if (diacr < 0x100)
 			put_queue(vc, diacr);
 		diacr = 0;
@@ -617,7 +627,7 @@
 		return;
 	}
 	if (kbd->kbdmode == VC_UNICODE)
-		to_utf8(vc, value);
+		to_utf8(vc, conv_8bit_to_uni(value));
 	else if (value < 0x100)
 		put_queue(vc, value);
 }
@@ -775,7 +785,7 @@
 	/* kludge */
 	if (up_flag && shift_state != old_state && npadch != -1) {
 		if (kbd->kbdmode == VC_UNICODE)
-			to_utf8(vc, npadch & 0xffff);
+			to_utf8(vc, npadch);
 		else
 			put_queue(vc, npadch & 0xff);
 		npadch = -1;
@@ -1005,8 +1015,8 @@
 	284,285,309,  0,312, 91,327,328,329,331,333,335,336,337,338,339,
 	367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
 	360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
-	103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
-	291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
+	103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
+	291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
 	264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
 	377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
 	308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index cc9a9d0..bbee97f 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -24,7 +24,7 @@
 #include <linux/crash_dump.h>
 #include <linux/backing-dev.h>
 #include <linux/bootmem.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
 #include <linux/pfn.h>
 
 #include <asm/uaccess.h>
@@ -75,6 +75,13 @@
 	 * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
 	 */
 	return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
+#elif defined(CONFIG_MIPS)
+	{
+		extern int __uncached_access(struct file *file,
+					     unsigned long addr);
+
+		return __uncached_access(file, addr);
+	}
 #else
 	/*
 	 * Accessing memory above the top the kernel knows about or through a file pointer
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 4e6fb96..71c8cd7 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -67,25 +67,13 @@
 #ifdef CONFIG_PROC_FS
 static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct miscdevice *p;
-	loff_t off = 0;
-
 	mutex_lock(&misc_mtx);
-	list_for_each_entry(p, &misc_list, list) {
-		if (*pos == off++) 
-			return p;
-	}
-	return NULL;
+	return seq_list_start(&misc_list, *pos);
 }
 
 static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct list_head *n = ((struct miscdevice *)v)->list.next;
-
-	++*pos;
-
-	return (n != &misc_list) ? list_entry(n, struct miscdevice, list)
-		 : NULL;
+	return seq_list_next(v, &misc_list, pos);
 }
 
 static void misc_seq_stop(struct seq_file *seq, void *v)
@@ -95,7 +83,7 @@
 
 static int misc_seq_show(struct seq_file *seq, void *v)
 {
-	const struct miscdevice *p = v;
+	const struct miscdevice *p = list_entry(v, struct miscdevice, list);
 
 	seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : "");
 	return 0;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index e0d35c2..ed76f0a 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -1405,7 +1405,6 @@
 static struct mon_str moxaLog;
 static int moxaFuncTout = HZ / 2;
 
-static void moxadelay(int);
 static void moxafunc(void __iomem *, int, ushort);
 static void wait_finish(void __iomem *);
 static void low_water_check(void __iomem *);
@@ -2404,10 +2403,10 @@
 	ofsAddr = moxa_ports[port].tableAddr;
 	if (ms100) {
 		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
-		moxadelay(ms100 * (HZ / 10));
+		msleep(ms100 * 10);
 	} else {
 		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
-		moxadelay(HZ / 4);	/* 250 ms */
+		msleep(250);
 	}
 	moxafunc(ofsAddr, FC_StopBreak, Magic_code);
 }
@@ -2476,18 +2475,6 @@
 /*****************************************************************************
  *	Static local functions: 					     *
  *****************************************************************************/
-/*
- * moxadelay - delays a specified number ticks
- */
-static void moxadelay(int tick)
-{
-	unsigned long st, et;
-
-	st = jiffies;
-	et = st + tick;
-	while (time_before(jiffies, et));
-}
-
 static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
 {
 
@@ -2535,7 +2522,7 @@
 		return -EFAULT;
 	baseAddr = moxa_boards[cardno].basemem;
 	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
-	moxadelay(1);		/* delay 10 ms */
+	msleep(10);
 	for (i = 0; i < 4096; i++)
 		writeb(0, baseAddr + i);	/* clear fix page */
 	for (i = 0; i < len; i++)
@@ -2713,7 +2700,7 @@
 			for (i = 0; i < 100; i++) {
 				if (readw(baseAddr + C218_key) == keycode)
 					break;
-				moxadelay(1);	/* delay 10 ms */
+				msleep(10);
 			}
 			if (readw(baseAddr + C218_key) != keycode) {
 				return (-1);
@@ -2725,7 +2712,7 @@
 		for (i = 0; i < 100; i++) {
 			if (readw(baseAddr + C218_key) == keycode)
 				break;
-			moxadelay(1);	/* delay 10 ms */
+			msleep(10);
 		}
 		retry++;
 	} while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
@@ -2736,7 +2723,7 @@
 	for (i = 0; i < 100; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);	/* delay 10 ms */
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code) {
 		return (-1);
@@ -2746,7 +2733,7 @@
 	for (i = 0; i < 100; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);	/* delay 10 ms */
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code) {
 		return (-1);
@@ -2788,7 +2775,7 @@
 			for (i = 0; i < 10; i++) {
 				if (readw(baseAddr + C320_key) == C320_KeyCode)
 					break;
-				moxadelay(1);
+				msleep(10);
 			}
 			if (readw(baseAddr + C320_key) != C320_KeyCode)
 				return (-1);
@@ -2799,7 +2786,7 @@
 		for (i = 0; i < 10; i++) {
 			if (readw(baseAddr + C320_key) == C320_KeyCode)
 				break;
-			moxadelay(1);
+			msleep(10);
 		}
 		retry++;
 	} while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
@@ -2809,7 +2796,7 @@
 	for (i = 0; i < 600; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code)
 		return (-100);
@@ -2828,7 +2815,7 @@
 	for (i = 0; i < 500; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code)
 		return (-102);
@@ -2842,7 +2829,7 @@
 	for (i = 0; i < 600; i++) {
 		if (readw(baseAddr + Magic_no) == Magic_code)
 			break;
-		moxadelay(1);
+		msleep(10);
 	}
 	if (readw(baseAddr + Magic_no) != Magic_code)
 		return (-102);
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 7ac3061..c716ef0 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -265,7 +265,7 @@
 	vdata->refcnt = ATOMIC_INIT(1);
 	vma->vm_private_data = vdata;
 
-	vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP);
+	vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP);
 	if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	vma->vm_ops = &mspec_vm_ops;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 5953a45..2aee3fe 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -90,8 +90,6 @@
 #define UART_MCR_AFE		0x20
 #define UART_LSR_SPECIAL	0x1E
 
-#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
-					  IXON|IXOFF))
 
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED)
 
@@ -1729,16 +1727,12 @@
 	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
-	if ((tty->termios->c_cflag != old_termios->c_cflag) ||
-			(RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+	mxser_change_speed(info, old_termios);
 
-		mxser_change_speed(info, old_termios);
-
-		if ((old_termios->c_cflag & CRTSCTS) &&
-				!(tty->termios->c_cflag & CRTSCTS)) {
-			tty->hw_stopped = 0;
-			mxser_start(tty);
-		}
+	if ((old_termios->c_cflag & CRTSCTS) &&
+			!(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		mxser_start(tty);
 	}
 
 /* Handle sw stopped */
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 6cde448..6a56393 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -72,8 +72,6 @@
 #define UART_MCR_AFE		0x20
 #define UART_LSR_SPECIAL	0x1E
 
-#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
-					  IXON|IXOFF))
 
 #define C168_ASIC_ID    1
 #define C104_ASIC_ID    2
@@ -1560,7 +1558,7 @@
 			return -EFAULT;
 		return 0;
 	case MOXA_ASPP_MON_EXT: {
-		int status, p, shiftbit;
+		int p, shiftbit;
 		unsigned long opmode;
 		unsigned cflag, iflag;
 
@@ -1990,18 +1988,14 @@
 	struct mxser_port *info = tty->driver_data;
 	unsigned long flags;
 
-	if ((tty->termios->c_cflag != old_termios->c_cflag) ||
-			(RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+	spin_lock_irqsave(&info->slock, flags);
+	mxser_change_speed(info, old_termios);
+	spin_unlock_irqrestore(&info->slock, flags);
 
-		spin_lock_irqsave(&info->slock, flags);
-		mxser_change_speed(info, old_termios);
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		if ((old_termios->c_cflag & CRTSCTS) &&
-				!(tty->termios->c_cflag & CRTSCTS)) {
-			tty->hw_stopped = 0;
-			mxser_start(tty);
-		}
+	if ((old_termios->c_cflag & CRTSCTS) &&
+			!(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		mxser_start(tty);
 	}
 
 	/* Handle sw stopped */
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 337a87f..e8332f3 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -400,7 +400,12 @@
 		/* Send the next block of data to device */
 		tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 		actual = tty->driver->write(tty, tbuf->buf, tbuf->count);
-		    
+
+		/* rollback was possible and has been done */
+		if (actual == -ERESTARTSYS) {
+			n_hdlc->tbuf = tbuf;
+			break;
+		}
 		/* if transmit error, throw frame away by */
 		/* pretending it was accepted by driver */
 		if (actual < 0)
@@ -780,13 +785,14 @@
 		poll_wait(filp, &tty->write_wait, wait);
 
 		/* set bits for operations that won't block */
-		if(n_hdlc->rx_buf_list.head)
+		if (n_hdlc->rx_buf_list.head)
 			mask |= POLLIN | POLLRDNORM;	/* readable */
 		if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
 			mask |= POLLHUP;
-		if(tty_hung_up_p(filp))
+		if (tty_hung_up_p(filp))
 			mask |= POLLHUP;
-		if(n_hdlc->tx_free_buf_list.head)
+		if (!tty_is_writelocked(tty) &&
+				n_hdlc->tx_free_buf_list.head)
 			mask |= POLLOUT | POLLWRNORM;	/* writable */
 	}
 	return mask;
@@ -861,7 +867,7 @@
 	spin_lock_irqsave(&list->spinlock,flags);
 	
 	buf->link=NULL;
-	if(list->tail)
+	if (list->tail)
 		list->tail->link = buf;
 	else
 		list->head = buf;
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 14557a4..6b918b8 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1071,8 +1071,6 @@
 	struct r3964_client_info *pClient;
 	struct r3964_message *pMsg;
 	struct r3964_client_message theMsg;
-	DECLARE_WAITQUEUE(wait, current);
-
 	int count;
 
 	TRACE_L("read()");
@@ -1086,16 +1084,8 @@
 				return -EAGAIN;
 			}
 			/* block until there is a message: */
-			add_wait_queue(&pInfo->read_wait, &wait);
-repeat:
-			__set_current_state(TASK_INTERRUPTIBLE);
-			pMsg = remove_msg(pInfo, pClient);
-			if (!pMsg && !signal_pending(current)) {
-				schedule();
-				goto repeat;
-			}
-			__set_current_state(TASK_RUNNING);
-			remove_wait_queue(&pInfo->read_wait, &wait);
+			wait_event_interruptible(pInfo->read_wait,
+					(pMsg = remove_msg(pInfo, pClient)));
 		}
 
 		/* If we still haven't got a message, we must have been signalled */
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index b3d4ccc..0380569 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -45,6 +45,8 @@
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/bitops.h>
+#include <linux/audit.h>
+#include <linux/file.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -78,6 +80,13 @@
 		free_page((unsigned long) buf);
 }
 
+static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
+			       unsigned char __user *ptr)
+{
+	tty_audit_add_data(tty, &x, 1);
+	return put_user(x, ptr);
+}
+
 /**
  *	n_tty_set__room	-	receive space
  *	@tty: terminal
@@ -1153,6 +1162,7 @@
 	if (n) {
 		retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
 		n -= retval;
+		tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
 		spin_lock_irqsave(&tty->read_lock, flags);
 		tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
 		tty->read_cnt -= n;
@@ -1191,6 +1201,7 @@
 			    is_current_pgrp_orphaned())
 				return -EIO;
 			kill_pgrp(task_pgrp(current), SIGTTIN, 1);
+			set_thread_flag(TIF_SIGPENDING);
 			return -ERESTARTSYS;
 		}
 	}
@@ -1278,7 +1289,7 @@
 				break;
 			cs = tty->link->ctrl_status;
 			tty->link->ctrl_status = 0;
-			if (put_user(cs, b++)) {
+			if (tty_put_user(tty, cs, b++)) {
 				retval = -EFAULT;
 				b--;
 				break;
@@ -1320,7 +1331,7 @@
 
 		/* Deal with packet mode. */
 		if (tty->packet && b == buf) {
-			if (put_user(TIOCPKT_DATA, b++)) {
+			if (tty_put_user(tty, TIOCPKT_DATA, b++)) {
 				retval = -EFAULT;
 				b--;
 				break;
@@ -1351,15 +1362,17 @@
 				spin_unlock_irqrestore(&tty->read_lock, flags);
 
 				if (!eol || (c != __DISABLED_CHAR)) {
-					if (put_user(c, b++)) {
+					if (tty_put_user(tty, c, b++)) {
 						retval = -EFAULT;
 						b--;
 						break;
 					}
 					nr--;
 				}
-				if (eol)
+				if (eol) {
+					tty_audit_push(tty);
 					break;
+				}
 			}
 			if (retval)
 				break;
@@ -1537,7 +1550,8 @@
 		else
 			tty->minimum_to_wake = 1;
 	}
-	if (tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
+	if (!tty_is_writelocked(tty) &&
+			tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
 			tty->driver->write_room(tty) > 0)
 		mask |= POLLOUT | POLLWRNORM;
 	return mask;
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 204deaa..98dec38 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -42,19 +42,12 @@
 
 #define PC		1
 #define ATARI		2
-#define COBALT		3
 
 /* select machine configuration */
 #if defined(CONFIG_ATARI)
 #  define MACH ATARI
 #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)  /* and others?? */
-#define MACH PC
-#  if defined(CONFIG_COBALT)
-#    include <linux/cobalt-nvram.h>
-#    define MACH COBALT
-#  else
-#    define MACH PC
-#  endif
+#  define MACH PC
 #else
 #  error Cannot build nvram driver for this machine configuration.
 #endif
@@ -76,18 +69,6 @@
 
 #endif
 
-#if MACH == COBALT
-
-#define CHECK_DRIVER_INIT()     1
-
-#define NVRAM_BYTES		(128-NVRAM_FIRST_BYTE)
-
-#define mach_check_checksum	cobalt_check_checksum
-#define mach_set_checksum	cobalt_set_checksum
-#define mach_proc_infos		cobalt_proc_infos
-
-#endif
-
 #if MACH == ATARI
 
 /* Special parameters for RTC in Atari machines */
@@ -604,177 +585,6 @@
 
 #endif /* MACH == PC */
 
-#if MACH == COBALT
-
-/* the cobalt CMOS has a wider range of its checksum */
-static int cobalt_check_checksum(void)
-{
-	int i;
-	unsigned short sum = 0;
-	unsigned short expect;
-
-	for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) {
-		if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1)))
-			continue;
-
-		sum += __nvram_read_byte(i);
-	}
-	expect = __nvram_read_byte(COBT_CMOS_CHECKSUM) << 8 |
-	    __nvram_read_byte(COBT_CMOS_CHECKSUM+1);
-	return ((sum & 0xffff) == expect);
-}
-
-static void cobalt_set_checksum(void)
-{
-	int i;
-	unsigned short sum = 0;
-
-	for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) {
-		if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1)))
-			continue;
-
-		sum += __nvram_read_byte(i);
-	}
-
-	__nvram_write_byte(sum >> 8, COBT_CMOS_CHECKSUM);
-	__nvram_write_byte(sum & 0xff, COBT_CMOS_CHECKSUM+1);
-}
-
-#ifdef CONFIG_PROC_FS
-
-static int cobalt_proc_infos(unsigned char *nvram, char *buffer, int *len,
-	off_t *begin, off_t offset, int size)
-{
-	int i;
-	unsigned int checksum;
-	unsigned int flags;
-	char sernum[14];
-	char *key = "cNoEbTaWlOtR!";
-	unsigned char bto_csum;
-
-	spin_lock_irq(&rtc_lock);
-	checksum = __nvram_check_checksum();
-	spin_unlock_irq(&rtc_lock);
-
-	PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not ");
-
-	flags = nvram[COBT_CMOS_FLAG_BYTE_0] << 8 
-	    | nvram[COBT_CMOS_FLAG_BYTE_1];
-
-	PRINT_PROC("Console: %s\n",
-		flags & COBT_CMOS_CONSOLE_FLAG ?  "on": "off");
-
-	PRINT_PROC("Firmware Debug Messages: %s\n",
-		flags & COBT_CMOS_DEBUG_FLAG ? "on": "off");
-
-	PRINT_PROC("Auto Prompt: %s\n",
-		flags & COBT_CMOS_AUTO_PROMPT_FLAG ? "on": "off");
-
-	PRINT_PROC("Shutdown Status: %s\n",
-		flags & COBT_CMOS_CLEAN_BOOT_FLAG ? "clean": "dirty");
-
-	PRINT_PROC("Hardware Probe: %s\n",
-		flags & COBT_CMOS_HW_NOPROBE_FLAG ? "partial": "full");
-
-	PRINT_PROC("System Fault: %sdetected\n",
-		flags & COBT_CMOS_SYSFAULT_FLAG ? "": "not ");
-
-	PRINT_PROC("Panic on OOPS: %s\n",
-		flags & COBT_CMOS_OOPSPANIC_FLAG ? "yes": "no");
-
-	PRINT_PROC("Delayed Cache Initialization: %s\n",
-		flags & COBT_CMOS_DELAY_CACHE_FLAG ? "yes": "no");
-
-	PRINT_PROC("Show Logo at Boot: %s\n",
-		flags & COBT_CMOS_NOLOGO_FLAG ? "no": "yes");
-
-	PRINT_PROC("Boot Method: ");
-	switch (nvram[COBT_CMOS_BOOT_METHOD]) {
-	case COBT_CMOS_BOOT_METHOD_DISK:
-		PRINT_PROC("disk\n");
-		break;
-
-	case COBT_CMOS_BOOT_METHOD_ROM:
-		PRINT_PROC("rom\n");
-		break;
-
-	case COBT_CMOS_BOOT_METHOD_NET:
-		PRINT_PROC("net\n");
-		break;
-
-	default:
-		PRINT_PROC("unknown\n");
-		break;
-	}
-
-	PRINT_PROC("Primary Boot Device: %d:%d\n",
-		nvram[COBT_CMOS_BOOT_DEV0_MAJ],
-		nvram[COBT_CMOS_BOOT_DEV0_MIN] );
-	PRINT_PROC("Secondary Boot Device: %d:%d\n",
-		nvram[COBT_CMOS_BOOT_DEV1_MAJ],
-		nvram[COBT_CMOS_BOOT_DEV1_MIN] );
-	PRINT_PROC("Tertiary Boot Device: %d:%d\n",
-		nvram[COBT_CMOS_BOOT_DEV2_MAJ],
-		nvram[COBT_CMOS_BOOT_DEV2_MIN] );
-
-	PRINT_PROC("Uptime: %d\n",
-		nvram[COBT_CMOS_UPTIME_0] << 24 |
-		nvram[COBT_CMOS_UPTIME_1] << 16 |
-		nvram[COBT_CMOS_UPTIME_2] << 8  |
-		nvram[COBT_CMOS_UPTIME_3]);
-
-	PRINT_PROC("Boot Count: %d\n",
-		nvram[COBT_CMOS_BOOTCOUNT_0] << 24 |
-		nvram[COBT_CMOS_BOOTCOUNT_1] << 16 |
-		nvram[COBT_CMOS_BOOTCOUNT_2] << 8  |
-		nvram[COBT_CMOS_BOOTCOUNT_3]);
-
-	/* 13 bytes of serial num */
-	for (i=0 ; i<13 ; i++) {
-		sernum[i] = nvram[COBT_CMOS_SYS_SERNUM_0 + i];
-	}
-	sernum[13] = '\0';
-
-	checksum = 0;
-	for (i=0 ; i<13 ; i++) {
-		checksum += sernum[i] ^ key[i];
-	}
-	checksum = ((checksum & 0x7f) ^ (0xd6)) & 0xff;
-
-	PRINT_PROC("Serial Number: %s", sernum);
-	if (checksum != nvram[COBT_CMOS_SYS_SERNUM_CSUM]) {
-		PRINT_PROC(" (invalid checksum)");
-	}
-	PRINT_PROC("\n");
-
-	PRINT_PROC("Rom Revison: %d.%d.%d\n", nvram[COBT_CMOS_ROM_REV_MAJ],
-		nvram[COBT_CMOS_ROM_REV_MIN], nvram[COBT_CMOS_ROM_REV_REV]);
-
-	PRINT_PROC("BTO Server: %d.%d.%d.%d", nvram[COBT_CMOS_BTO_IP_0],
-		nvram[COBT_CMOS_BTO_IP_1], nvram[COBT_CMOS_BTO_IP_2],
-		nvram[COBT_CMOS_BTO_IP_3]);
-	bto_csum = nvram[COBT_CMOS_BTO_IP_0] + nvram[COBT_CMOS_BTO_IP_1]
-		+ nvram[COBT_CMOS_BTO_IP_2] + nvram[COBT_CMOS_BTO_IP_3];
-	if (bto_csum != nvram[COBT_CMOS_BTO_IP_CSUM]) {
-		PRINT_PROC(" (invalid checksum)");
-	}
-	PRINT_PROC("\n");
-
-	if (flags & COBT_CMOS_VERSION_FLAG
-	 && nvram[COBT_CMOS_VERSION] >= COBT_CMOS_VER_BTOCODE) {
-		PRINT_PROC("BTO Code: 0x%x\n",
-			nvram[COBT_CMOS_BTO_CODE_0] << 24 |
-			nvram[COBT_CMOS_BTO_CODE_1] << 16 |
-			nvram[COBT_CMOS_BTO_CODE_2] << 8 |
-			nvram[COBT_CMOS_BTO_CODE_3]);
-	}
-
-	return 1;
-}
-#endif /* CONFIG_PROC_FS */
-
-#endif /* MACH == COBALT */
-
 #if MACH == ATARI
 
 static int
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 46c1b9774..7f52712 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -760,7 +760,7 @@
 
 static void extract_buf(struct entropy_store *r, __u8 *out)
 {
-	int i, x;
+	int i;
 	__u32 data[16], buf[5 + SHA_WORKSPACE_WORDS];
 
 	sha_init(buf);
@@ -772,9 +772,11 @@
 	 * attempts to find previous ouputs), unless the hash
 	 * function can be inverted.
 	 */
-	for (i = 0, x = 0; i < r->poolinfo->poolwords; i += 16, x+=2) {
-		sha_transform(buf, (__u8 *)r->pool+i, buf + 5);
-		add_entropy_words(r, &buf[x % 5], 1);
+	for (i = 0; i < r->poolinfo->poolwords; i += 16) {
+		/* hash blocks of 16 words = 512 bits */
+		sha_transform(buf, (__u8 *)(r->pool + i), buf + 5);
+		/* feed back portion of the resulting hash */
+		add_entropy_words(r, &buf[i % 5], 1);
 	}
 
 	/*
@@ -782,7 +784,7 @@
 	 * portion of the pool while mixing, and hash one
 	 * final time.
 	 */
-	__add_entropy_words(r, &buf[x % 5], 1, data);
+	__add_entropy_words(r, &buf[i % 5], 1, data);
 	sha_transform(buf, (__u8 *)data, buf + 5);
 
 	/*
@@ -792,7 +794,7 @@
 
 	buf[0] ^= buf[3];
 	buf[1] ^= buf[4];
-	buf[0] ^= rol32(buf[3], 16);
+	buf[2] ^= rol32(buf[2], 16);
 	memcpy(out, buf, EXTRACT_SIZE);
 	memset(buf, 0, sizeof(buf));
 }
@@ -1018,37 +1020,44 @@
 	return mask;
 }
 
+static int
+write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
+{
+	size_t bytes;
+	__u32 buf[16];
+	const char __user *p = buffer;
+
+	while (count > 0) {
+		bytes = min(count, sizeof(buf));
+		if (copy_from_user(&buf, p, bytes))
+			return -EFAULT;
+
+		count -= bytes;
+		p += bytes;
+
+		add_entropy_words(r, buf, (bytes + 3) / 4);
+	}
+
+	return 0;
+}
+
 static ssize_t
 random_write(struct file * file, const char __user * buffer,
 	     size_t count, loff_t *ppos)
 {
-	int ret = 0;
-	size_t bytes;
-	__u32 buf[16];
-	const char __user *p = buffer;
-	size_t c = count;
+	size_t ret;
+	struct inode *inode = file->f_path.dentry->d_inode;
 
-	while (c > 0) {
-		bytes = min(c, sizeof(buf));
+	ret = write_pool(&blocking_pool, buffer, count);
+	if (ret)
+		return ret;
+	ret = write_pool(&nonblocking_pool, buffer, count);
+	if (ret)
+		return ret;
 
-		bytes -= copy_from_user(&buf, p, bytes);
-		if (!bytes) {
-			ret = -EFAULT;
-			break;
-		}
-		c -= bytes;
-		p += bytes;
-
-		add_entropy_words(&input_pool, buf, (bytes + 3) / 4);
-	}
-	if (p == buffer) {
-		return (ssize_t)ret;
-	} else {
-		struct inode *inode = file->f_path.dentry->d_inode;
-	        inode->i_mtime = current_fs_time(inode->i_sb);
-		mark_inode_dirty(inode);
-		return (ssize_t)(p - buffer);
-	}
+	inode->i_mtime = current_fs_time(inode->i_sb);
+	mark_inode_dirty(inode);
+	return (ssize_t)count;
 }
 
 static int
@@ -1087,8 +1096,8 @@
 			return -EINVAL;
 		if (get_user(size, p++))
 			return -EFAULT;
-		retval = random_write(file, (const char __user *) p,
-				      size, &file->f_pos);
+		retval = write_pool(&input_pool, (const char __user *)p,
+				    size);
 		if (retval < 0)
 			return retval;
 		credit_entropy_store(&input_pool, ent_count);
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 3494e3f..b37e626 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -213,14 +213,6 @@
 		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
 }
 	
-/* Must be called with enabled interrupts */
-static inline void rc_long_delay(unsigned long delay)
-{
-	unsigned long i;
-	
-	for (i = jiffies + delay; time_after(i,jiffies); ) ;
-}
-
 /* Reset and setup CD180 chip */
 static void __init rc_init_CD180(struct riscom_board const * bp)
 {
@@ -231,7 +223,7 @@
 	rc_wait_CCR(bp);			   /* Wait for CCR ready        */
 	rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip          */
 	sti();
-	rc_long_delay(HZ/20);                      /* Delay 0.05 sec            */
+	msleep(50);				   /* Delay 0.05 sec            */
 	cli();
 	rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip      */
 	rc_out(bp, CD180_GICR, 0);                 /* Clear all bits            */
@@ -280,7 +272,7 @@
 		rc_wait_CCR(bp);
 		rc_out(bp, CD180_CCR, CCR_TXEN);        /* Enable transmitter     */
 		rc_out(bp, CD180_IER, IER_TXRDY);       /* Enable tx empty intr   */
-		rc_long_delay(HZ/20);	       		
+		msleep(50);
 		irqs = probe_irq_off(irqs);
 		val1 = rc_in(bp, RC_BSR);		/* Get Board Status reg   */
 		val2 = rc_in(bp, RC_ACK_TINT);          /* ACK interrupt          */
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index a3fd7e7..0270080 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1702,7 +1702,8 @@
 	if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
 		return 0;
 
-	mutex_lock_interruptible(&info->write_mtx);
+	if (mutex_lock_interruptible(&info->write_mtx))
+		return -ERESTARTSYS;
 
 #ifdef ROCKET_DEBUG_WRITE
 	printk(KERN_INFO "rp_write %d chars...", count);
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 20380a2..22cf7aa 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -1159,7 +1159,8 @@
 
 	spin_unlock_irq(&rtc_lock);
 
-	printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
+	if (printk_ratelimit())
+		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
 
 	/* Now we have new data */
 	wake_up_interruptible(&rtc_wait);
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index a69f094..d63f5cc 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -20,6 +20,7 @@
 
 #include <asm/uaccess.h>
 
+#include <linux/kbd_kern.h>
 #include <linux/vt_kern.h>
 #include <linux/consolemap.h>
 #include <linux/selection.h>
@@ -34,6 +35,7 @@
 /* Variables for selection control. */
 /* Use a dynamic buffer, instead of static (Dec 1994) */
 struct vc_data *sel_cons;		/* must not be deallocated */
+static int use_unicode;
 static volatile int sel_start = -1; 	/* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
@@ -54,10 +56,11 @@
 	complement_pos(sel_cons, where);
 }
 
-static unsigned char
+static u16
 sel_pos(int n)
 {
-	return inverse_translate(sel_cons, screen_glyph(sel_cons, n));
+	return inverse_translate(sel_cons, screen_glyph(sel_cons, n),
+				use_unicode);
 }
 
 /* remove the current selection highlight, if any,
@@ -86,8 +89,8 @@
   0xFF7FFFFF  /* latin-1 accented letters, not division sign */
 };
 
-static inline int inword(const unsigned char c) {
-	return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
+static inline int inword(const u16 c) {
+	return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
 }
 
 /* set inwordLut contents. Invoked by ioctl(). */
@@ -108,13 +111,36 @@
 	return (v > u) ? u : v;
 }
 
+/* stores the char in UTF8 and returns the number of bytes used (1-3) */
+static int store_utf8(u16 c, char *p)
+{
+	if (c < 0x80) {
+		/*  0******* */
+		p[0] = c;
+		return 1;
+	} else if (c < 0x800) {
+		/* 110***** 10****** */
+		p[0] = 0xc0 | (c >> 6);
+		p[1] = 0x80 | (c & 0x3f);
+		return 2;
+    	} else {
+		/* 1110**** 10****** 10****** */
+		p[0] = 0xe0 | (c >> 12);
+		p[1] = 0x80 | ((c >> 6) & 0x3f);
+		p[2] = 0x80 | (c & 0x3f);
+		return 3;
+    	}
+}
+
 /* set the current selection. Invoked by ioctl() or by kernel code. */
 int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
 	int sel_mode, new_sel_start, new_sel_end, spc;
 	char *bp, *obp;
-	int i, ps, pe;
+	int i, ps, pe, multiplier;
+	u16 c;
+	struct kbd_struct *kbd = kbd_table + fg_console;
 
 	poke_blanked_console();
 
@@ -158,6 +184,7 @@
 		clear_selection();
 		sel_cons = vc_cons[fg_console].d;
 	}
+	use_unicode = kbd && kbd->kbdmode == VC_UNICODE;
 
 	switch (sel_mode)
 	{
@@ -240,7 +267,8 @@
 	sel_end = new_sel_end;
 
 	/* Allocate a new buffer before freeing the old one ... */
-	bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
+	multiplier = use_unicode ? 3 : 1;  /* chars can take up to 3 bytes */
+	bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL);
 	if (!bp) {
 		printk(KERN_WARNING "selection: kmalloc() failed\n");
 		clear_selection();
@@ -251,8 +279,12 @@
 
 	obp = bp;
 	for (i = sel_start; i <= sel_end; i += 2) {
-		*bp = sel_pos(i);
-		if (!isspace(*bp++))
+		c = sel_pos(i);
+		if (use_unicode)
+			bp += store_utf8(c, bp);
+		else
+			*bp++ = c;
+		if (!isspace(c))
 			obp = bp;
 		if (! ((i + 2) % vc->vc_size_row)) {
 			/* strip trailing blanks from line and add newline,
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 3ef593a..73037a4 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -885,53 +885,6 @@
 	return IRQ_HANDLED;
 }
 
-/* External camera command (exported to the motion eye v4l driver) */
-int sonypi_camera_command(int command, u8 value)
-{
-	if (!camera)
-		return -EIO;
-
-	mutex_lock(&sonypi_device.lock);
-
-	switch (command) {
-	case SONYPI_COMMAND_SETCAMERA:
-		if (value)
-			sonypi_camera_on();
-		else
-			sonypi_camera_off();
-		break;
-	case SONYPI_COMMAND_SETCAMERABRIGHTNESS:
-		sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERACONTRAST:
-		sonypi_set(SONYPI_CAMERA_CONTRAST, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERAHUE:
-		sonypi_set(SONYPI_CAMERA_HUE, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERACOLOR:
-		sonypi_set(SONYPI_CAMERA_COLOR, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERASHARPNESS:
-		sonypi_set(SONYPI_CAMERA_SHARPNESS, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERAPICTURE:
-		sonypi_set(SONYPI_CAMERA_PICTURE, value);
-		break;
-	case SONYPI_COMMAND_SETCAMERAAGC:
-		sonypi_set(SONYPI_CAMERA_AGC, value);
-		break;
-	default:
-		printk(KERN_ERR "sonypi: sonypi_camera_command invalid: %d\n",
-		       command);
-		break;
-	}
-	mutex_unlock(&sonypi_device.lock);
-	return 0;
-}
-
-EXPORT_SYMBOL(sonypi_camera_command);
-
 static int sonypi_misc_fasync(int fd, struct file *filp, int on)
 {
 	int retval;
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index baf7234..4558556 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -345,18 +345,6 @@
 }
 
 
-/* Must be called with enabled interrupts */
-/* Ugly. Very ugly. Don't use this for anything else than initialization
-   code */
-static inline void sx_long_delay(unsigned long delay)
-{
-	unsigned long i;
-
-	for (i = jiffies + delay; time_after(i, jiffies); ) ;
-}
-
-
-
 /* Set the IRQ using the RTS lines that run to the PAL on the board.... */
 static int sx_set_irq ( struct specialix_board *bp)
 {
@@ -397,7 +385,7 @@
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out_off(bp, CD186x_CCR, CCR_HARDRESET);      /* Reset CD186x chip          */
 	spin_unlock_irqrestore(&bp->lock, flags);
-	sx_long_delay(HZ/20);                      /* Delay 0.05 sec            */
+	msleep(50);					/* Delay 0.05 sec            */
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out_off(bp, CD186x_GIVR, SX_ID);             /* Set ID for this chip      */
 	sx_out_off(bp, CD186x_GICR, 0);                 /* Clear all bits            */
@@ -533,7 +521,7 @@
 		sx_wait_CCR(bp);
 		sx_out(bp, CD186x_CCR, CCR_TXEN);        /* Enable transmitter     */
 		sx_out(bp, CD186x_IER, IER_TXRDY);       /* Enable tx empty intr   */
-		sx_long_delay(HZ/20);
+		msleep(50);
 		irqs = probe_irq_off(irqs);
 
 		dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index e45113a..93d0bb8 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1788,7 +1788,6 @@
 	if (tty == NULL)
 		return;
 
-	lock_kernel();
 	if (test_bit(ASYI_TXLOW, &portp->istate))
 		tty_wakeup(tty);
 
@@ -1802,7 +1801,6 @@
 			if (portp->flags & ASYNC_CHECK_CD)
 				tty_hangup(tty);	/* FIXME: module removal race here - AKPM */
 	}
-	unlock_kernel();
 }
 
 /*****************************************************************************/
@@ -2172,11 +2170,12 @@
 		}
 		status = inb(ioaddr + ECH_PNLSTATUS);
 		if ((status & ECH_PNLIDMASK) != nxtid)
-			goto err_fr;
+			break;
 		panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
 		if (!panelp) {
 			printk("STALLION: failed to allocate memory "
 				"(size=%Zd)\n", sizeof(struct stlpanel));
+			retval = -ENOMEM;
 			goto err_fr;
 		}
 		panelp->magic = STL_PANELMAGIC;
@@ -2223,8 +2222,10 @@
 		brdp->nrports += panelp->nrports;
 		brdp->panels[panelnr++] = panelp;
 		if ((brdp->brdtype != BRD_ECHPCI) &&
-		    (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
+		    (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
+			retval = -EINVAL;
 			goto err_fr;
+		}
 	}
 
 	brdp->nrpanels = panelnr;
@@ -2354,9 +2355,6 @@
 	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
 		goto err;
 
-	dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
-			pdev->vendor, pdev->device, pdev->class);
-
 	retval = pci_enable_device(pdev);
 	if (retval)
 		goto err;
@@ -2371,6 +2369,7 @@
 		dev_err(&pdev->dev, "too many boards found, "
 			"maximum supported %d\n", STL_MAXBRDS);
 		mutex_unlock(&stl_brdslock);
+		retval = -ENODEV;
 		goto err_fr;
 	}
 	brdp->brdnr = (unsigned int)brdnr;
@@ -4710,6 +4709,29 @@
 	spin_lock_init(&stallion_lock);
 	spin_lock_init(&brd_lock);
 
+	stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+	if (!stl_serial) {
+		retval = -ENOMEM;
+		goto err;
+	}
+
+	stl_serial->owner = THIS_MODULE;
+	stl_serial->driver_name = stl_drvname;
+	stl_serial->name = "ttyE";
+	stl_serial->major = STL_SERIALMAJOR;
+	stl_serial->minor_start = 0;
+	stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
+	stl_serial->subtype = SERIAL_TYPE_NORMAL;
+	stl_serial->init_termios = stl_deftermios;
+	stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(stl_serial, &stl_ops);
+
+	retval = tty_register_driver(stl_serial);
+	if (retval) {
+		printk("STALLION: failed to register serial driver\n");
+		goto err_frtty;
+	}
+
 /*
  *	Find any dynamically supported boards. That is via module load
  *	line options.
@@ -4726,26 +4748,23 @@
 		brdp->ioaddr2 = conf.ioaddr2;
 		brdp->irq = conf.irq;
 		brdp->irqtype = conf.irqtype;
-		if (stl_brdinit(brdp))
+		stl_brds[brdp->brdnr] = brdp;
+		if (stl_brdinit(brdp)) {
+			stl_brds[brdp->brdnr] = NULL;
 			kfree(brdp);
-		else {
+		} else {
 			for (j = 0; j < brdp->nrports; j++)
 				tty_register_device(stl_serial,
 					brdp->brdnr * STL_MAXPORTS + j, NULL);
-			stl_brds[brdp->brdnr] = brdp;
 			stl_nrbrds = i + 1;
 		}
 	}
 
 	/* this has to be _after_ isa finding because of locking */
 	retval = pci_register_driver(&stl_pcidriver);
-	if (retval && stl_nrbrds == 0)
-		goto err;
-
-	stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-	if (!stl_serial) {
-		retval = -ENOMEM;
-		goto err_pcidr;
+	if (retval && stl_nrbrds == 0) {
+		printk(KERN_ERR "STALLION: can't register pci driver\n");
+		goto err_unrtty;
 	}
 
 /*
@@ -4756,43 +4775,18 @@
 		printk("STALLION: failed to register serial board device\n");
 
 	stallion_class = class_create(THIS_MODULE, "staliomem");
-	if (IS_ERR(stallion_class)) {
-		retval = PTR_ERR(stallion_class);
-		goto err_reg;
-	}
+	if (IS_ERR(stallion_class))
+		printk("STALLION: failed to create class\n");
 	for (i = 0; i < 4; i++)
 		class_device_create(stallion_class, NULL,
 				    MKDEV(STL_SIOMEMMAJOR, i), NULL,
 				    "staliomem%d", i);
 
-	stl_serial->owner = THIS_MODULE;
-	stl_serial->driver_name = stl_drvname;
-	stl_serial->name = "ttyE";
-	stl_serial->major = STL_SERIALMAJOR;
-	stl_serial->minor_start = 0;
-	stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
-	stl_serial->subtype = SERIAL_TYPE_NORMAL;
-	stl_serial->init_termios = stl_deftermios;
-	stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(stl_serial, &stl_ops);
-
-	retval = tty_register_driver(stl_serial);
-	if (retval) {
-		printk("STALLION: failed to register serial driver\n");
-		goto err_clsdev;
-	}
-
 	return 0;
-err_clsdev:
-	for (i = 0; i < 4; i++)
-		class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
-	class_destroy(stallion_class);
-err_reg:
-	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+err_unrtty:
+	tty_unregister_driver(stl_serial);
+err_frtty:
 	put_tty_driver(stl_serial);
-err_pcidr:
-	pci_unregister_driver(&stl_pcidriver);
-	stl_free_isabrds();
 err:
 	return retval;
 }
@@ -4821,8 +4815,6 @@
 			tty_unregister_device(stl_serial,
 				brdp->brdnr * STL_MAXPORTS + j);
 	}
-	tty_unregister_driver(stl_serial);
-	put_tty_driver(stl_serial);
 
 	for (i = 0; i < 4; i++)
 		class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
@@ -4834,6 +4826,9 @@
 	pci_unregister_driver(&stl_pcidriver);
 
 	stl_free_isabrds();
+
+	tty_unregister_driver(stl_serial);
+	put_tty_driver(stl_serial);
 }
 
 module_init(stallion_module_init);
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 1da92a6..85a2328 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2721,9 +2721,9 @@
    its because the standard requires it. So check for SUBVENDOR_ID. */
 static struct pci_device_id sx_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = 0x0200,.subdevice = PCI_ANY_ID },
+		.subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
 	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = 0x0300,.subdevice = PCI_ANY_ID },
+		.subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
 	{ 0 }
 };
 
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index f02a079..f53e51d 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -160,8 +160,6 @@
 
 #define IO_PIN_SHUTDOWN_LIMIT 100
 
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 struct	_input_signal_events {
 	int	ri_up;	
 	int	ri_down;
@@ -3064,12 +3062,6 @@
 		printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__,
 			tty->driver->name );
 	
-	/* just return if nothing has changed */
-	if ((tty->termios->c_cflag == old_termios->c_cflag)
-	    && (RELEVANT_IFLAG(tty->termios->c_iflag) 
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
 	mgsl_change_params(info);
 
 	/* Handle transition to B0 status */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 02b49bc..428b514 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -144,8 +144,6 @@
 /*
  * tty support and callbacks
  */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 static struct tty_driver *serial_driver;
 
 static int  open(struct tty_struct *tty, struct file * filp);
@@ -823,12 +821,6 @@
 
 	DBGINFO(("%s set_termios\n", tty->driver->name));
 
-	/* just return if nothing has changed */
-	if ((tty->termios->c_cflag == old_termios->c_cflag)
-	    && (RELEVANT_IFLAG(tty->termios->c_iflag)
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-		return;
-
 	change_params(info);
 
 	/* Handle transition to B0 status */
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ef93d05..a65407b 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -135,8 +135,6 @@
 
 #define IO_PIN_SHUTDOWN_LIMIT 100
 
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 struct	_input_signal_events {
 	int	ri_up;
 	int	ri_down;
@@ -927,12 +925,6 @@
 		printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__,
 			tty->driver->name );
 
-	/* just return if nothing has changed */
-	if ((tty->termios->c_cflag == old_termios->c_cflag)
-	    && (RELEVANT_IFLAG(tty->termios->c_iflag)
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
 	change_params(info);
 
 	/* Handle transition to B0 status */
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index dc4e1ff..8f3f762 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -2,11 +2,9 @@
 # TPM device configuration
 #
 
-menu "TPM devices"
-	depends on HAS_IOMEM
-
-config TCG_TPM
+menuconfig TCG_TPM
 	tristate "TPM Hardware Support"
+	depends on HAS_IOMEM
 	depends on EXPERIMENTAL
 	---help---
 	  If you have a TPM security chip in your system, which
@@ -21,9 +19,11 @@
 	  Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
 	  and CONFIG_PNPACPI.
 
+if TCG_TPM
+
 config TCG_TIS
 	tristate "TPM Interface Specification 1.2 Interface"
-	depends on TCG_TPM && PNPACPI
+	depends on PNPACPI
 	---help---
 	  If you have a TPM security chip that is compliant with the
 	  TCG TIS 1.2 TPM specification say Yes and it will be accessible
@@ -32,7 +32,7 @@
 
 config TCG_NSC
 	tristate "National Semiconductor TPM Interface"
-	depends on TCG_TPM && PNPACPI
+	depends on PNPACPI
 	---help---
 	  If you have a TPM security chip from National Semiconductor 
 	  say Yes and it will be accessible from within Linux.  To 
@@ -41,7 +41,6 @@
 
 config TCG_ATMEL
 	tristate "Atmel TPM Interface"
-	depends on TCG_TPM
 	---help---
 	  If you have a TPM security chip from Atmel say Yes and it 
 	  will be accessible from within Linux.  To compile this driver 
@@ -49,7 +48,7 @@
 
 config TCG_INFINEON
 	tristate "Infineon Technologies TPM Interface"
-	depends on TCG_TPM && PNPACPI
+	depends on PNPACPI
 	---help---
 	  If you have a TPM security chip from Infineon Technologies
 	  (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
@@ -59,5 +58,4 @@
 	  Further information on this driver and the supported hardware
 	  can be found at http://www.prosec.rub.de/tpm
 
-endmenu
-
+endif # TCG_TPM
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
new file mode 100644
index 0000000..d222012
--- /dev/null
+++ b/drivers/char/tty_audit.c
@@ -0,0 +1,345 @@
+/*
+ * Creating audit events from TTY input.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.  All rights reserved.  This copyrighted
+ * material is made available to anyone wishing to use, modify, copy, or
+ * redistribute it subject to the terms and conditions of the GNU General
+ * Public License v.2.
+ *
+ * Authors: Miloslav Trmac <mitr@redhat.com>
+ */
+
+#include <linux/audit.h>
+#include <linux/file.h>
+#include <linux/tty.h>
+
+struct tty_audit_buf {
+	atomic_t count;
+	struct mutex mutex;	/* Protects all data below */
+	int major, minor;	/* The TTY which the data is from */
+	unsigned icanon:1;
+	size_t valid;
+	unsigned char *data;	/* Allocated size N_TTY_BUF_SIZE */
+};
+
+static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
+						 int icanon)
+{
+	struct tty_audit_buf *buf;
+
+	buf = kmalloc(sizeof (*buf), GFP_KERNEL);
+	if (!buf)
+		goto err;
+	if (PAGE_SIZE != N_TTY_BUF_SIZE)
+		buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+	else
+		buf->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+	if (!buf->data)
+		goto err_buf;
+	atomic_set(&buf->count, 1);
+	mutex_init(&buf->mutex);
+	buf->major = major;
+	buf->minor = minor;
+	buf->icanon = icanon;
+	buf->valid = 0;
+	return buf;
+
+err_buf:
+	kfree(buf);
+err:
+	return NULL;
+}
+
+static void tty_audit_buf_free(struct tty_audit_buf *buf)
+{
+	WARN_ON(buf->valid != 0);
+	if (PAGE_SIZE != N_TTY_BUF_SIZE)
+		kfree(buf->data);
+	else
+		free_page((unsigned long)buf->data);
+	kfree(buf);
+}
+
+static void tty_audit_buf_put(struct tty_audit_buf *buf)
+{
+	if (atomic_dec_and_test(&buf->count))
+		tty_audit_buf_free(buf);
+}
+
+/**
+ *	tty_audit_buf_push	-	Push buffered data out
+ *
+ *	Generate an audit message from the contents of @buf, which is owned by
+ *	@tsk with @loginuid.  @buf->mutex must be locked.
+ */
+static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
+			       struct tty_audit_buf *buf)
+{
+	struct audit_buffer *ab;
+
+	if (buf->valid == 0)
+		return;
+	if (audit_enabled == 0)
+		return;
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
+	if (ab) {
+		char name[sizeof(tsk->comm)];
+
+		audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
+				 "minor=%d comm=", tsk->pid, tsk->uid,
+				 loginuid, buf->major, buf->minor);
+		get_task_comm(name, tsk);
+		audit_log_untrustedstring(ab, name);
+		audit_log_format(ab, " data=");
+		audit_log_n_untrustedstring(ab, buf->valid, buf->data);
+		audit_log_end(ab);
+	}
+	buf->valid = 0;
+}
+
+/**
+ *	tty_audit_buf_push_current	-	Push buffered data out
+ *
+ *	Generate an audit message from the contents of @buf, which is owned by
+ *	the current task.  @buf->mutex must be locked.
+ */
+static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
+{
+	tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
+			   buf);
+}
+
+/**
+ *	tty_audit_exit	-	Handle a task exit
+ *
+ *	Make sure all buffered data is written out and deallocate the buffer.
+ *	Only needs to be called if current->signal->tty_audit_buf != %NULL.
+ */
+void tty_audit_exit(void)
+{
+	struct tty_audit_buf *buf;
+
+	spin_lock_irq(&current->sighand->siglock);
+	buf = current->signal->tty_audit_buf;
+	current->signal->tty_audit_buf = NULL;
+	spin_unlock_irq(&current->sighand->siglock);
+	if (!buf)
+		return;
+
+	mutex_lock(&buf->mutex);
+	tty_audit_buf_push_current(buf);
+	mutex_unlock(&buf->mutex);
+
+	tty_audit_buf_put(buf);
+}
+
+/**
+ *	tty_audit_fork	-	Copy TTY audit state for a new task
+ *
+ *	Set up TTY audit state in @sig from current.  @sig needs no locking.
+ */
+void tty_audit_fork(struct signal_struct *sig)
+{
+	spin_lock_irq(&current->sighand->siglock);
+	sig->audit_tty = current->signal->audit_tty;
+	spin_unlock_irq(&current->sighand->siglock);
+	sig->tty_audit_buf = NULL;
+}
+
+/**
+ *	tty_audit_push_task	-	Flush task's pending audit data
+ */
+void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+{
+	struct tty_audit_buf *buf;
+
+	spin_lock_irq(&tsk->sighand->siglock);
+	buf = tsk->signal->tty_audit_buf;
+	if (buf)
+		atomic_inc(&buf->count);
+	spin_unlock_irq(&tsk->sighand->siglock);
+	if (!buf)
+		return;
+
+	mutex_lock(&buf->mutex);
+	tty_audit_buf_push(tsk, loginuid, buf);
+	mutex_unlock(&buf->mutex);
+
+	tty_audit_buf_put(buf);
+}
+
+/**
+ *	tty_audit_buf_get	-	Get an audit buffer.
+ *
+ *	Get an audit buffer for @tty, allocate it if necessary.  Return %NULL
+ *	if TTY auditing is disabled or out of memory.  Otherwise, return a new
+ *	reference to the buffer.
+ */
+static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
+{
+	struct tty_audit_buf *buf, *buf2;
+
+	buf = NULL;
+	buf2 = NULL;
+	spin_lock_irq(&current->sighand->siglock);
+	if (likely(!current->signal->audit_tty))
+		goto out;
+	buf = current->signal->tty_audit_buf;
+	if (buf) {
+		atomic_inc(&buf->count);
+		goto out;
+	}
+	spin_unlock_irq(&current->sighand->siglock);
+
+	buf2 = tty_audit_buf_alloc(tty->driver->major,
+				   tty->driver->minor_start + tty->index,
+				   tty->icanon);
+	if (buf2 == NULL) {
+		audit_log_lost("out of memory in TTY auditing");
+		return NULL;
+	}
+
+	spin_lock_irq(&current->sighand->siglock);
+	if (!current->signal->audit_tty)
+		goto out;
+	buf = current->signal->tty_audit_buf;
+	if (!buf) {
+		current->signal->tty_audit_buf = buf2;
+		buf = buf2;
+		buf2 = NULL;
+	}
+	atomic_inc(&buf->count);
+	/* Fall through */
+ out:
+	spin_unlock_irq(&current->sighand->siglock);
+	if (buf2)
+		tty_audit_buf_free(buf2);
+	return buf;
+}
+
+/**
+ *	tty_audit_add_data	-	Add data for TTY auditing.
+ *
+ *	Audit @data of @size from @tty, if necessary.
+ */
+void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+			size_t size)
+{
+	struct tty_audit_buf *buf;
+	int major, minor;
+
+	if (unlikely(size == 0))
+		return;
+
+	buf = tty_audit_buf_get(tty);
+	if (!buf)
+		return;
+
+	mutex_lock(&buf->mutex);
+	major = tty->driver->major;
+	minor = tty->driver->minor_start + tty->index;
+	if (buf->major != major || buf->minor != minor
+	    || buf->icanon != tty->icanon) {
+		tty_audit_buf_push_current(buf);
+		buf->major = major;
+		buf->minor = minor;
+		buf->icanon = tty->icanon;
+	}
+	do {
+		size_t run;
+
+		run = N_TTY_BUF_SIZE - buf->valid;
+		if (run > size)
+			run = size;
+		memcpy(buf->data + buf->valid, data, run);
+		buf->valid += run;
+		data += run;
+		size -= run;
+		if (buf->valid == N_TTY_BUF_SIZE)
+			tty_audit_buf_push_current(buf);
+	} while (size != 0);
+	mutex_unlock(&buf->mutex);
+	tty_audit_buf_put(buf);
+}
+
+/**
+ *	tty_audit_push	-	Push buffered data out
+ *
+ *	Make sure no audit data is pending for @tty on the current process.
+ */
+void tty_audit_push(struct tty_struct *tty)
+{
+	struct tty_audit_buf *buf;
+
+	spin_lock_irq(&current->sighand->siglock);
+	if (likely(!current->signal->audit_tty)) {
+		spin_unlock_irq(&current->sighand->siglock);
+		return;
+	}
+	buf = current->signal->tty_audit_buf;
+	if (buf)
+		atomic_inc(&buf->count);
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (buf) {
+		int major, minor;
+
+		major = tty->driver->major;
+		minor = tty->driver->minor_start + tty->index;
+		mutex_lock(&buf->mutex);
+		if (buf->major == major && buf->minor == minor)
+			tty_audit_buf_push_current(buf);
+		mutex_unlock(&buf->mutex);
+		tty_audit_buf_put(buf);
+	}
+}
+
+/**
+ *	tty_audit_opening	-	A TTY is being opened.
+ *
+ *	As a special hack, tasks that close all their TTYs and open new ones
+ *	are assumed to be system daemons (e.g. getty) and auditing is
+ *	automatically disabled for them.
+ */
+void tty_audit_opening(void)
+{
+	int disable;
+
+	disable = 1;
+	spin_lock_irq(&current->sighand->siglock);
+	if (current->signal->audit_tty == 0)
+		disable = 0;
+	spin_unlock_irq(&current->sighand->siglock);
+	if (!disable)
+		return;
+
+	task_lock(current);
+	if (current->files) {
+		struct fdtable *fdt;
+		unsigned i;
+
+		/*
+		 * We don't take a ref to the file, so we must hold ->file_lock
+		 * instead.
+		 */
+		spin_lock(&current->files->file_lock);
+		fdt = files_fdtable(current->files);
+		for (i = 0; i < fdt->max_fds; i++) {
+			struct file *filp;
+
+			filp = fcheck_files(current->files, i);
+			if (filp && is_tty(filp)) {
+				disable = 0;
+				break;
+			}
+		}
+		spin_unlock(&current->files->file_lock);
+	}
+	task_unlock(current);
+	if (!disable)
+		return;
+
+	spin_lock_irq(&current->sighand->siglock);
+	current->signal->audit_tty = 0;
+	spin_unlock_irq(&current->sighand->siglock);
+}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 75d2a46..de37ebc 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1148,7 +1148,8 @@
 		return 0;
 	if (is_current_pgrp_orphaned())
 		return -EIO;
-	(void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+	kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+	set_thread_flag(TIF_SIGPENDING);
 	return -ERESTARTSYS;
 }
 
@@ -1172,8 +1173,14 @@
 	return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
 }
 
-static long hung_up_tty_ioctl(struct file * file,
-			      unsigned int cmd, unsigned long arg)
+static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
+			     unsigned int cmd, unsigned long arg)
+{
+	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
+}
+
+static long hung_up_tty_compat_ioctl(struct file * file,
+				     unsigned int cmd, unsigned long arg)
 {
 	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
 }
@@ -1221,8 +1228,8 @@
 	.read		= hung_up_tty_read,
 	.write		= hung_up_tty_write,
 	.poll		= hung_up_tty_poll,
-	.unlocked_ioctl = hung_up_tty_ioctl,
-	.compat_ioctl	= hung_up_tty_ioctl,
+	.ioctl		= hung_up_tty_ioctl,
+	.compat_ioctl	= hung_up_tty_compat_ioctl,
 	.release	= tty_release,
 };
 
@@ -1496,6 +1503,15 @@
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
+/**
+ * is_tty	-	checker whether file is a TTY
+ */
+int is_tty(struct file *filp)
+{
+	return filp->f_op->read == tty_read
+		|| filp->f_op->read == hung_up_tty_read;
+}
+
 static void session_clear_tty(struct pid *session)
 {
 	struct task_struct *p;
@@ -1719,6 +1735,23 @@
 	return i;
 }
 
+void tty_write_unlock(struct tty_struct *tty)
+{
+	mutex_unlock(&tty->atomic_write_lock);
+	wake_up_interruptible(&tty->write_wait);
+}
+
+int tty_write_lock(struct tty_struct *tty, int ndelay)
+{
+	if (!mutex_trylock(&tty->atomic_write_lock)) {
+		if (ndelay)
+			return -EAGAIN;
+		if (mutex_lock_interruptible(&tty->atomic_write_lock))
+			return -ERESTARTSYS;
+	}
+	return 0;
+}
+
 /*
  * Split writes up in sane blocksizes to avoid
  * denial-of-service type attacks
@@ -1730,13 +1763,12 @@
 	const char __user *buf,
 	size_t count)
 {
-	ssize_t ret = 0, written = 0;
+	ssize_t ret, written = 0;
 	unsigned int chunk;
 	
-	/* FIXME: O_NDELAY ... */
-	if (mutex_lock_interruptible(&tty->atomic_write_lock)) {
-		return -ERESTARTSYS;
-	}
+	ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
+	if (ret < 0)
+		return ret;
 
 	/*
 	 * We chunk up writes into a temporary buffer. This
@@ -1769,8 +1801,8 @@
 
 		buf = kmalloc(chunk, GFP_KERNEL);
 		if (!buf) {
-			mutex_unlock(&tty->atomic_write_lock);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto out;
 		}
 		kfree(tty->write_buf);
 		tty->write_cnt = chunk;
@@ -1805,7 +1837,8 @@
 		inode->i_mtime = current_fs_time(inode->i_sb);
 		ret = written;
 	}
-	mutex_unlock(&tty->atomic_write_lock);
+out:
+	tty_write_unlock(tty);
 	return ret;
 }
 
@@ -2009,11 +2042,9 @@
 	}
 
 	if (!*ltp_loc) {
-		ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
-						 GFP_KERNEL);
+		ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
 		if (!ltp)
 			goto free_mem_out;
-		memset(ltp, 0, sizeof(struct ktermios));
 	}
 
 	if (driver->type == TTY_DRIVER_TYPE_PTY) {
@@ -2042,11 +2073,9 @@
 		}
 
 		if (!*o_ltp_loc) {
-			o_ltp = (struct ktermios *)
-				kmalloc(sizeof(struct ktermios), GFP_KERNEL);
+			o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
 			if (!o_ltp)
 				goto free_mem_out;
-			memset(o_ltp, 0, sizeof(struct ktermios));
 		}
 
 		/*
@@ -2653,6 +2682,7 @@
 		__proc_set_tty(current, tty);
 	spin_unlock_irq(&current->sighand->siglock);
 	mutex_unlock(&tty_mutex);
+	tty_audit_opening();
 	return 0;
 }
 
@@ -2715,8 +2745,10 @@
 
 	check_tty_count(tty, "tty_open");
 	retval = ptm_driver->open(tty, filp);
-	if (!retval)
+	if (!retval) {
+		tty_audit_opening();
 		return 0;
+	}
 out1:
 	release_dev(filp);
 	return retval;
@@ -3156,14 +3188,13 @@
 
 static int send_break(struct tty_struct *tty, unsigned int duration)
 {
-	if (mutex_lock_interruptible(&tty->atomic_write_lock))
+	if (tty_write_lock(tty, 0) < 0)
 		return -EINTR;
 	tty->driver->break_ctl(tty, -1);
-	if (!signal_pending(current)) {
+	if (!signal_pending(current))
 		msleep_interruptible(duration);
-	}
 	tty->driver->break_ctl(tty, 0);
-	mutex_unlock(&tty->atomic_write_lock);
+	tty_write_unlock(tty);
 	if (signal_pending(current))
 		return -EINTR;
 	return 0;
@@ -3732,9 +3763,8 @@
 {
 	struct tty_driver *driver;
 
-	driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
+	driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
 	if (driver) {
-		memset(driver, 0, sizeof(struct tty_driver));
 		driver->magic = TTY_DRIVER_MAGIC;
 		driver->num = lines;
 		/* later we'll move allocation of tables here */
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index fd471cb..3423e9ee 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -52,8 +52,6 @@
 
 void tty_wait_until_sent(struct tty_struct * tty, long timeout)
 {
-	DECLARE_WAITQUEUE(wait, current);
-
 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
 	char buf[64];
 	
@@ -61,26 +59,13 @@
 #endif
 	if (!tty->driver->chars_in_buffer)
 		return;
-	add_wait_queue(&tty->write_wait, &wait);
 	if (!timeout)
 		timeout = MAX_SCHEDULE_TIMEOUT;
-	do {
-#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
-		printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
-		       tty->driver->chars_in_buffer(tty));
-#endif
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (signal_pending(current))
-			goto stop_waiting;
-		if (!tty->driver->chars_in_buffer(tty))
-			break;
-		timeout = schedule_timeout(timeout);
-	} while (timeout);
+	if (wait_event_interruptible_timeout(tty->write_wait,
+			!tty->driver->chars_in_buffer(tty), timeout))
+		return;
 	if (tty->driver->wait_until_sent)
 		tty->driver->wait_until_sent(tty, timeout);
-stop_waiting:
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&tty->write_wait, &wait);
 }
 
 EXPORT_SYMBOL(tty_wait_until_sent);
@@ -276,13 +261,12 @@
 				termios->c_cflag |= (baud_bits[i] << IBSHIFT);
 			ifound = i;
 		}
-	}
-	while(++i < n_baud_table);
+	} while (++i < n_baud_table);
 	if (ofound == -1)
 		termios->c_cflag |= BOTHER;
 	/* Set exact input bits only if the input and output differ or the
 	   user already did */
-	if (ifound == -1 && (ibaud != obaud  || ibinput))
+	if (ifound == -1 && (ibaud != obaud || ibinput))
 		termios->c_cflag |= (BOTHER << IBSHIFT);
 }
 
@@ -575,7 +559,7 @@
 		return -EFAULT;
 
 	mutex_lock(&tty->termios_mutex);
-	termios =  *tty->termios;
+	termios = *tty->termios;
 	termios.c_cc[VERASE] = tmp.sg_erase;
 	termios.c_cc[VKILL] = tmp.sg_kill;
 	set_sgflags(&termios, tmp.sg_flags);
@@ -667,7 +651,7 @@
 		return 0;
 	}
 
-	if (mutex_lock_interruptible(&tty->atomic_write_lock))
+	if (tty_write_lock(tty, 0) < 0)
 		return -ERESTARTSYS;
 
 	if (was_stopped)
@@ -675,7 +659,7 @@
 	tty->driver->write(tty, &ch, 1);
 	if (was_stopped)
 		stop_tty(tty);
-	mutex_unlock(&tty->atomic_write_lock);
+	tty_write_unlock(tty);
 	return 0;
 }
 
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 13faf8d..db57277 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -873,12 +873,12 @@
 }
 
 const struct file_operations viotap_fops = {
-	owner: THIS_MODULE,
-	read: viotap_read,
-	write: viotap_write,
-	ioctl: viotap_ioctl,
-	open: viotap_open,
-	release: viotap_release,
+	.owner =	THIS_MODULE,
+	.read =		viotap_read,
+	.write =	viotap_write,
+	.ioctl =	viotap_ioctl,
+	.open =		viotap_open,
+	.release =	viotap_release,
 };
 
 /* Handle interrupt events for tape */
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index 0cea8d4..e5ed091 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -19,18 +19,17 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/platform_device.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#include <asm/cpu.h>
 #include <asm/io.h>
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/irq.h>
@@ -44,18 +43,6 @@
 module_param(major, int, 0);
 MODULE_PARM_DESC(major, "Major device number");
 
-#define GIU_TYPE1_START		0x0b000100UL
-#define GIU_TYPE1_SIZE		0x20UL
-
-#define GIU_TYPE2_START		0x0f000140UL
-#define GIU_TYPE2_SIZE		0x20UL
-
-#define GIU_TYPE3_START		0x0f000140UL
-#define GIU_TYPE3_SIZE		0x28UL
-
-#define GIU_PULLUPDOWN_START	0x0b0002e0UL
-#define GIU_PULLUPDOWN_SIZE	0x04UL
-
 #define GIUIOSELL	0x00
 #define GIUIOSELH	0x02
 #define GIUPIODL	0x04
@@ -89,8 +76,6 @@
 #define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100
 
 static spinlock_t giu_lock;
-static struct resource *giu_resource1;
-static struct resource *giu_resource2;
 static unsigned long giu_flags;
 static unsigned int giu_nr_pins;
 
@@ -234,7 +219,7 @@
 				giu_set(GIUINTHTSELL, mask);
 			else
 				giu_clear(GIUINTHTSELL, mask);
-			if (current_cpu_data.cputype == CPU_VR4133) {
+			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
 				switch (trigger) {
 				case IRQ_TRIGGER_EDGE_FALLING:
 					giu_set(GIUFEDGEINHL, mask);
@@ -269,7 +254,7 @@
 				giu_set(GIUINTHTSELH, mask);
 			else
 				giu_clear(GIUINTHTSELH, mask);
-			if (current_cpu_data.cputype == CPU_VR4133) {
+			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
 				switch (trigger) {
 				case IRQ_TRIGGER_EDGE_FALLING:
 					giu_set(GIUFEDGEINHH, mask);
@@ -298,7 +283,6 @@
 		giu_write(GIUINTSTATH, mask);
 	}
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
 
 void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
@@ -321,7 +305,6 @@
 		giu_write(GIUINTSTATH, mask);
 	}
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
 
 gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
@@ -350,7 +333,6 @@
 
 	return GPIO_DATA_LOW;
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
 
 int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
@@ -388,7 +370,6 @@
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
 
 int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
@@ -438,7 +419,6 @@
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
 
 int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
@@ -477,7 +457,6 @@
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
 
 static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
@@ -596,61 +575,40 @@
 
 static int __devinit giu_probe(struct platform_device *dev)
 {
-	unsigned long start, size, flags = 0;
-	unsigned int nr_pins = 0, trigger, i, pin;
-	struct resource *res1, *res2 = NULL;
-	void *base;
+	struct resource *res;
+	unsigned int trigger, i, pin;
 	struct irq_chip *chip;
-	int retval;
+	int irq, retval;
 
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		start = GIU_TYPE1_START;
-		size = GIU_TYPE1_SIZE;
-		flags = GPIO_HAS_PULLUPDOWN_IO;
-		nr_pins = 50;
+	switch (dev->id) {
+	case GPIO_50PINS_PULLUPDOWN:
+		giu_flags = GPIO_HAS_PULLUPDOWN_IO;
+		giu_nr_pins = 50;
 		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-		start = GIU_TYPE2_START;
-		size = GIU_TYPE2_SIZE;
-		nr_pins = 36;
+	case GPIO_36PINS:
+		giu_nr_pins = 36;
 		break;
-	case CPU_VR4133:
-		start = GIU_TYPE3_START;
-		size = GIU_TYPE3_SIZE;
-		flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
-		nr_pins = 48;
+	case GPIO_48PINS_EDGE_SELECT:
+		giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+		giu_nr_pins = 48;
 		break;
 	default:
+		printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
 		return -ENODEV;
 	}
 
-	res1 = request_mem_region(start, size, "GIU");
-	if (res1 == NULL)
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
 		return -EBUSY;
 
-	base = ioremap(start, size);
-	if (base == NULL) {
-		release_resource(res1);
+	giu_base = ioremap(res->start, res->end - res->start + 1);
+	if (!giu_base)
 		return -ENOMEM;
-	}
-
-	if (flags & GPIO_HAS_PULLUPDOWN_IO) {
-		res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
-		if (res2 == NULL) {
-			iounmap(base);
-			release_resource(res1);
-			return -EBUSY;
-		}
-	}
 
 	retval = register_chrdev(major, "GIU", &gpio_fops);
 	if (retval < 0) {
-		iounmap(base);
-		release_resource(res1);
-		release_resource(res2);
+		iounmap(giu_base);
+		giu_base = NULL;
 		return retval;
 	}
 
@@ -660,11 +618,6 @@
 	}
 
 	spin_lock_init(&giu_lock);
-	giu_base = base;
-	giu_resource1 = res1;
-	giu_resource2 = res2;
-	giu_flags = flags;
-	giu_nr_pins = nr_pins;
 
 	giu_write(GIUINTENL, 0);
 	giu_write(GIUINTENH, 0);
@@ -685,22 +638,23 @@
 
 	}
 
-	return cascade_irq(GIUINT_IRQ, giu_get_irq);
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0 || irq >= NR_IRQS)
+		return -EBUSY;
+
+	return cascade_irq(irq, giu_get_irq);
 }
 
 static int __devexit giu_remove(struct platform_device *dev)
 {
-	iounmap(giu_base);
-
-	release_resource(giu_resource1);
-	if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
-		release_resource(giu_resource2);
+	if (giu_base) {
+		iounmap(giu_base);
+		giu_base = NULL;
+	}
 
 	return 0;
 }
 
-static struct platform_device *giu_platform_device;
-
 static struct platform_driver giu_device_driver = {
 	.probe		= giu_probe,
 	.remove		= __devexit_p(giu_remove),
@@ -712,30 +666,12 @@
 
 static int __init vr41xx_giu_init(void)
 {
-	int retval;
-
-	giu_platform_device = platform_device_alloc("GIU", -1);
-	if (!giu_platform_device)
-		return -ENOMEM;
-
-	retval = platform_device_add(giu_platform_device);
-	if (retval < 0) {
-		platform_device_put(giu_platform_device);
-		return retval;
-	}
-
-	retval = platform_driver_register(&giu_device_driver);
-	if (retval < 0)
-		platform_device_unregister(giu_platform_device);
-
-	return retval;
+	return platform_driver_register(&giu_device_driver);
 }
 
 static void __exit vr41xx_giu_exit(void)
 {
 	platform_driver_unregister(&giu_device_driver);
-
-	platform_device_unregister(giu_platform_device);
 }
 
 module_init(vr41xx_giu_init);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index bbd9fc4..edb7002 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -729,10 +729,9 @@
 	    /* although the numbers above are not valid since long ago, the
 	       point is still up-to-date and the comment still has its value
 	       even if only as a historical artifact.  --mj, July 1998 */
-	    vc = kmalloc(sizeof(struct vc_data), GFP_KERNEL);
+	    vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL);
 	    if (!vc)
 		return -ENOMEM;
-	    memset(vc, 0, sizeof(*vc));
 	    vc_cons[currcons].d = vc;
 	    INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
 	    visual_init(vc, currcons, 1);
@@ -1956,7 +1955,7 @@
 DEFINE_MUTEX(con_buf_mtx);
 
 /* is_double_width() is based on the wcwidth() implementation by
- * Markus Kuhn -- 2003-05-20 (Unicode 4.0)
+ * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
  * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
  */
 struct interval {
@@ -1988,11 +1987,10 @@
 	static const struct interval double_width[] = {
 		{ 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E },
 		{ 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF },
-		{ 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, { 0xFFE0, 0xFFE6 },
-		{ 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
+		{ 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 },
+		{ 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
 	};
-	return bisearch(ucs, double_width,
-		sizeof(double_width) / sizeof(*double_width) - 1);
+	return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1);
 }
 
 /* acquires console_sem */
@@ -2187,9 +2185,12 @@
 				    continue; /* nothing to display */
 				}
 				/* Glyph not found */
-				if (!(vc->vc_utf && !vc->vc_disp_ctrl) && !(c & ~charmask)) {
+				if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) {
 				    /* In legacy mode use the glyph we get by a 1:1 mapping.
-				       This would make absolutely no sense with Unicode in mind. */
+				       This would make absolutely no sense with Unicode in mind,
+				       but do this for ASCII characters since a font may lack
+				       Unicode mapping info and we don't want to end up with
+				       having question marks only. */
 				    tc = c;
 				} else {
 				    /* Display U+FFFD. If it's not found, display an inverse question mark. */
@@ -2213,6 +2214,7 @@
 				} else {
 					vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
 				}
+				FLUSH
 			}
 
 			while (1) {
@@ -2246,6 +2248,10 @@
 				if (tc < 0) tc = ' ';
 			}
 
+			if (inverse) {
+				FLUSH
+			}
+
 			if (rescan) {
 				rescan = 0;
 				inverse = 0;
@@ -2981,8 +2987,24 @@
 	return retval;
 }
 
-static int unbind_con_driver(const struct consw *csw, int first, int last,
-			     int deflt)
+/**
+ * unbind_con_driver - unbind a console driver
+ * @csw: pointer to console driver to unregister
+ * @first: first in range of consoles that @csw should be unbound from
+ * @last: last in range of consoles that @csw should be unbound from
+ * @deflt: should next bound console driver be default after @csw is unbound?
+ *
+ * To unbind a driver from all possible consoles, pass 0 as @first and
+ * %MAX_NR_CONSOLES as @last.
+ *
+ * @deflt controls whether the console that ends up replacing @csw should be
+ * the default console.
+ *
+ * RETURNS:
+ * -ENODEV if @csw isn't a registered console driver or can't be unregistered
+ * or 0 on success.
+ */
+int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
 {
 	struct module *owner = csw->owner;
 	const struct consw *defcsw = NULL;
@@ -3067,6 +3089,7 @@
 	return retval;
 
 }
+EXPORT_SYMBOL(unbind_con_driver);
 
 static int vt_bind(struct con_driver *con)
 {
@@ -3483,9 +3506,6 @@
 		}
 		return;
 	}
-	if (blank_state != blank_normal_wait)
-		return;
-	blank_state = blank_off;
 
 	/* entering graphics mode? */
 	if (entering_gfx) {
@@ -3493,10 +3513,15 @@
 		save_screen(vc);
 		vc->vc_sw->con_blank(vc, -1, 1);
 		console_blanked = fg_console + 1;
+		blank_state = blank_off;
 		set_origin(vc);
 		return;
 	}
 
+	if (blank_state != blank_normal_wait)
+		return;
+	blank_state = blank_off;
+
 	/* don't blank graphics */
 	if (vc->vc_mode != KD_TEXT) {
 		console_blanked = fg_console + 1;
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index fd955db..dc7548d 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -205,7 +205,7 @@
 module_init(ixp2000_wdt_init);
 module_exit(ixp2000_wdt_exit);
 
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net">);
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
 MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog");
 
 module_param(heartbeat, int, 0);
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 5cfcff5..e783dbf 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -105,14 +105,11 @@
  */
 static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev)
 {
-	u8 rev;
-
 	if (acpi_pm_good)
 		return;
 
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
 	/* the bug has been fixed in PIIX4M */
-	if (rev < 3) {
+	if (dev->revision < 3) {
 		printk(KERN_WARNING "* Found PM-Timer Bug on the chipset."
 		       " Due to workarounds for a bug,\n"
 		       "* this clock source is slow. Consider trying"
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig
index e0bdc0d..100bfd42 100644
--- a/drivers/connector/Kconfig
+++ b/drivers/connector/Kconfig
@@ -1,6 +1,5 @@
-menu "Connector - unified userspace <-> kernelspace linker"
 
-config CONNECTOR
+menuconfig CONNECTOR
 	tristate "Connector - unified userspace <-> kernelspace linker"
 	depends on NET
 	---help---
@@ -10,6 +9,8 @@
 	  Connector support can also be built as a module.  If so, the module
 	  will be called cn.ko.
 
+if CONNECTOR
+
 config PROC_EVENTS
 	boolean "Report process events to userspace"
 	depends on CONNECTOR=y
@@ -18,4 +19,4 @@
 	  Provide a connector that reports process events to userspace. Send
 	  events such as fork, exec, id change (uid, gid, suid, etc), and exit.
 
-endmenu
+endif # CONNECTOR
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index eb37fba..2f6a73c 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -39,6 +39,10 @@
  */
 static struct cpufreq_driver *cpufreq_driver;
 static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
+#ifdef CONFIG_HOTPLUG_CPU
+/* This one keeps track of the previously set governor of a removed CPU */
+static struct cpufreq_governor *cpufreq_cpu_governor[NR_CPUS];
+#endif
 static DEFINE_SPINLOCK(cpufreq_driver_lock);
 
 /*
@@ -770,9 +774,17 @@
 	}
 	policy->user_policy.min = policy->cpuinfo.min_freq;
 	policy->user_policy.max = policy->cpuinfo.max_freq;
-	policy->user_policy.governor = policy->governor;
 
 #ifdef CONFIG_SMP
+
+#ifdef CONFIG_HOTPLUG_CPU
+	if (cpufreq_cpu_governor[cpu]){
+		policy->governor = cpufreq_cpu_governor[cpu];
+		dprintk("Restoring governor %s for cpu %d\n",
+		       policy->governor->name, cpu);
+	}
+#endif
+
 	for_each_cpu_mask(j, policy->cpus) {
 		if (cpu == j)
 			continue;
@@ -826,13 +838,21 @@
 	/* set up files for this cpu device */
 	drv_attr = cpufreq_driver->attr;
 	while ((drv_attr) && (*drv_attr)) {
-		sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+		ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+		if (ret)
+			goto err_out_driver_exit;
 		drv_attr++;
 	}
-	if (cpufreq_driver->get)
-		sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
-	if (cpufreq_driver->target)
-		sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+	if (cpufreq_driver->get){
+		ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
+		if (ret)
+			goto err_out_driver_exit;
+	}
+	if (cpufreq_driver->target){
+		ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+		if (ret)
+			goto err_out_driver_exit;
+	}
 
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
 	for_each_cpu_mask(j, policy->cpus) {
@@ -865,6 +885,7 @@
 	/* set default policy */
 	ret = __cpufreq_set_policy(policy, &new_policy);
 	policy->user_policy.policy = policy->policy;
+	policy->user_policy.governor = policy->governor;
 
 	unlock_policy_rwsem_write(cpu);
 
@@ -961,6 +982,11 @@
 	}
 
 #ifdef CONFIG_SMP
+
+#ifdef CONFIG_HOTPLUG_CPU
+	cpufreq_cpu_governor[cpu] = data->governor;
+#endif
+
 	/* if we have other CPUs still registered, we need to unlink them,
 	 * or else wait_for_completion below will lock up. Clean the
 	 * cpufreq_cpu_data[] while holding the lock, and remove the sysfs
@@ -981,6 +1007,9 @@
 			if (j == cpu)
 				continue;
 			dprintk("removing link for cpu %u\n", j);
+#ifdef CONFIG_HOTPLUG_CPU
+			cpufreq_cpu_governor[j] = data->governor;
+#endif
 			cpu_sys_dev = get_cpu_sysdev(j);
 			sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
 			cpufreq_cpu_put(data);
@@ -1679,7 +1708,6 @@
 {
 	unsigned int cpu = (unsigned long)hcpu;
 	struct sys_device *sys_dev;
-	struct cpufreq_policy *policy;
 
 	sys_dev = get_cpu_sysdev(cpu);
 	if (sys_dev) {
@@ -1693,11 +1721,6 @@
 			if (unlikely(lock_policy_rwsem_write(cpu)))
 				BUG();
 
-			policy = cpufreq_cpu_data[cpu];
-			if (policy) {
-				__cpufreq_driver_target(policy, policy->min,
-						CPUFREQ_RELATION_H);
-			}
 			__cpufreq_remove_dev(sys_dev);
 			break;
 		case CPU_DOWN_FAILED:
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 8532bb7..e794527 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -96,15 +96,25 @@
 
 static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
 {
-	cputime64_t retval;
+	cputime64_t idle_time;
+	cputime64_t cur_jiffies;
+	cputime64_t busy_time;
 
-	retval = cputime64_add(kstat_cpu(cpu).cpustat.idle,
-			kstat_cpu(cpu).cpustat.iowait);
+	cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
+	busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user,
+			kstat_cpu(cpu).cpustat.system);
 
-	if (dbs_tuners_ins.ignore_nice)
-		retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice);
+	busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.irq);
+	busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.softirq);
+	busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.steal);
 
-	return retval;
+	if (!dbs_tuners_ins.ignore_nice) {
+		busy_time = cputime64_add(busy_time,
+				kstat_cpu(cpu).cpustat.nice);
+	}
+
+	idle_time = cputime64_sub(cur_jiffies, busy_time);
+	return idle_time;
 }
 
 /*
@@ -325,7 +335,7 @@
 static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 {
 	unsigned int idle_ticks, total_ticks;
-	unsigned int load;
+	unsigned int load = 0;
 	cputime64_t cur_jiffies;
 
 	struct cpufreq_policy *policy;
@@ -339,7 +349,8 @@
 	cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
 	total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
 			this_dbs_info->prev_cpu_wall);
-	this_dbs_info->prev_cpu_wall = cur_jiffies;
+	this_dbs_info->prev_cpu_wall = get_jiffies_64();
+
 	if (!total_ticks)
 		return;
 	/*
@@ -370,7 +381,8 @@
 		if (tmp_idle_ticks < idle_ticks)
 			idle_ticks = tmp_idle_ticks;
 	}
-	load = (100 * (total_ticks - idle_ticks)) / total_ticks;
+	if (likely(total_ticks > idle_ticks))
+		load = (100 * (total_ticks - idle_ticks)) / total_ticks;
 
 	/* Check for frequency increase */
 	if (load > dbs_tuners_ins.up_threshold) {
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index d2f0cbd..917b9ba 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -25,8 +25,7 @@
 
 #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
 static struct freq_attr _attr_##_name = {\
-	.attr = {.name = __stringify(_name), .owner = THIS_MODULE, \
-		.mode = _mode, }, \
+	.attr = {.name = __stringify(_name), .mode = _mode, }, \
 	.show = _show,\
 };
 
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 860345c..51bedab 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -37,6 +37,7 @@
 static unsigned int	cpu_is_managed[NR_CPUS];
 
 static DEFINE_MUTEX	(userspace_mutex);
+static int cpus_using_userspace_governor;
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
 
@@ -47,7 +48,11 @@
 {
         struct cpufreq_freqs *freq = data;
 
-	dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n", freq->cpu, freq->new);
+	if (!cpu_is_managed[freq->cpu])
+		return 0;
+
+	dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n",
+			freq->cpu, freq->new);
 	cpu_cur_freq[freq->cpu] = freq->new;
 
         return 0;
@@ -120,7 +125,7 @@
 
 static struct freq_attr freq_attr_scaling_setspeed =
 {
-	.attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE },
+	.attr = { .name = "scaling_setspeed", .mode = 0644 },
 	.show = show_speed,
 	.store = store_speed,
 };
@@ -142,6 +147,13 @@
 		if (rc)
 			goto start_out;
 
+		if (cpus_using_userspace_governor == 0) {
+			cpufreq_register_notifier(
+					&userspace_cpufreq_notifier_block,
+					CPUFREQ_TRANSITION_NOTIFIER);
+		}
+		cpus_using_userspace_governor++;
+
 		cpu_is_managed[cpu] = 1;
 		cpu_min_freq[cpu] = policy->min;
 		cpu_max_freq[cpu] = policy->max;
@@ -153,6 +165,13 @@
 		break;
 	case CPUFREQ_GOV_STOP:
 		mutex_lock(&userspace_mutex);
+		cpus_using_userspace_governor--;
+		if (cpus_using_userspace_governor == 0) {
+			cpufreq_unregister_notifier(
+					&userspace_cpufreq_notifier_block,
+					CPUFREQ_TRANSITION_NOTIFIER);
+		}
+
 		cpu_is_managed[cpu] = 0;
 		cpu_min_freq[cpu] = 0;
 		cpu_max_freq[cpu] = 0;
@@ -198,7 +217,6 @@
 
 static int __init cpufreq_gov_userspace_init(void)
 {
-	cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
 	return cpufreq_register_governor(&cpufreq_gov_userspace);
 }
 
@@ -206,7 +224,6 @@
 static void __exit cpufreq_gov_userspace_exit(void)
 {
 	cpufreq_unregister_governor(&cpufreq_gov_userspace);
-        cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
 }
 
 
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index e749092..5409f3a 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -199,7 +199,6 @@
 struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
 	.attr = { .name = "scaling_available_frequencies",
 		  .mode = 0444,
-		  .owner=THIS_MODULE
 		},
 	.show = show_available_freqs,
 };
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index bb90cbd..84ebfcc 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -1,4 +1,9 @@
-menu "Hardware crypto devices"
+
+menuconfig CRYPTO_HW
+	bool "Hardware crypto devices"
+	default y
+
+if CRYPTO_HW
 
 config CRYPTO_DEV_PADLOCK
 	tristate "Support for VIA PadLock ACE"
@@ -78,4 +83,4 @@
 	  that contains all parts of the crypto device driver (ap bus,
 	  request router and all the card drivers).
 
-endmenu
+endif # CRYPTO_HW
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index 6d3840e..6a86958 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -102,10 +102,15 @@
 	u32 flags = 0;
 	unsigned long iflags;
 
-	if (op->len == 0 || op->src == op->dst)
+	if (op->len == 0)
 		return 0;
 
-	if (op->flags & AES_FLAGS_COHERENT)
+	/* If the source and destination is the same, then
+	 * we need to turn on the coherent flags, otherwise
+	 * we don't need to worry
+	 */
+
+	if (op->src == op->dst)
 		flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
 
 	if (op->dir == AES_DIR_ENCRYPT)
@@ -120,7 +125,7 @@
 		_writefield(AES_WRITEIV0_REG, op->iv);
 	}
 
-	if (op->flags & AES_FLAGS_USRKEY) {
+	if (!(op->flags & AES_FLAGS_HIDDENKEY)) {
 		flags |= AES_CTRL_WRKEY;
 		_writefield(AES_WRITEKEY0_REG, op->key);
 	}
@@ -289,6 +294,7 @@
 			.setkey			=	geode_setkey,
 			.encrypt		=	geode_cbc_encrypt,
 			.decrypt		=	geode_cbc_decrypt,
+			.ivsize			=	AES_IV_LENGTH,
 		}
 	}
 };
diff --git a/drivers/crypto/geode-aes.h b/drivers/crypto/geode-aes.h
index 8003a36..f479686 100644
--- a/drivers/crypto/geode-aes.h
+++ b/drivers/crypto/geode-aes.h
@@ -20,8 +20,7 @@
 #define AES_DIR_DECRYPT 0
 #define AES_DIR_ENCRYPT 1
 
-#define AES_FLAGS_USRKEY   (1 << 0)
-#define AES_FLAGS_COHERENT (1 << 1)
+#define AES_FLAGS_HIDDENKEY (1 << 0)
 
 struct geode_aes_op {
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 72be6c6..8f670da 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -3,13 +3,13 @@
 #
 
 menu "DMA Engine support"
-	depends on !S390
+	depends on HAS_DMA
 
 config DMA_ENGINE
 	bool "Support for DMA engines"
 	---help---
-	  DMA engines offload copy operations from the CPU to dedicated
-	  hardware, allowing the copies to happen asynchronously.
+          DMA engines offload bulk memory operations from the CPU to dedicated
+          hardware, allowing the operations to happen asynchronously.
 
 comment "DMA Clients"
 
@@ -32,4 +32,12 @@
 	---help---
 	  Enable support for the Intel(R) I/OAT DMA engine.
 
+config INTEL_IOP_ADMA
+        tristate "Intel IOP ADMA support"
+        depends on DMA_ENGINE && (ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX)
+	select ASYNC_CORE
+        default m
+        ---help---
+          Enable support for the Intel(R) IOP Series RAID engines.
+
 endmenu
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index bdcfdbd..b3839b6 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
+obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 322ee29..8248992 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -37,11 +37,11 @@
  * Each device has a channels list, which runs unlocked but is never modified
  * once the device is registered, it's just setup by the driver.
  *
- * Each client has a channels list, it's only modified under the client->lock
- * and in an RCU callback, so it's safe to read under rcu_read_lock().
+ * Each client is responsible for keeping track of the channels it uses.  See
+ * the definition of dma_event_callback in dmaengine.h.
  *
  * Each device has a kref, which is initialized to 1 when the device is
- * registered. A kref_put is done for each class_device registered.  When the
+ * registered. A kref_get is done for each class_device registered.  When the
  * class_device is released, the coresponding kref_put is done in the release
  * method. Every time one of the device's channels is allocated to a client,
  * a kref_get occurs.  When the channel is freed, the coresponding kref_put
@@ -51,14 +51,17 @@
  * references to finish.
  *
  * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
- * with a kref and a per_cpu local_t.  A single reference is set when on an
- * ADDED event, and removed with a REMOVE event.  Net DMA client takes an
- * extra reference per outstanding transaction.  The relase function does a
- * kref_put on the device. -ChrisL
+ * with a kref and a per_cpu local_t.  A dma_chan_get is called when a client
+ * signals that it wants to use a channel, and dma_chan_put is called when
+ * a channel is removed or a client using it is unregesitered.  A client can
+ * take extra references per outstanding transaction, as is the case with
+ * the NET DMA client.  The release function does a kref_put on the device.
+ *	-ChrisL, DanW
  */
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/mm.h>
 #include <linux/device.h>
 #include <linux/dmaengine.h>
 #include <linux/hardirq.h>
@@ -66,6 +69,7 @@
 #include <linux/percpu.h>
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 static DEFINE_MUTEX(dma_list_mutex);
 static LIST_HEAD(dma_device_list);
@@ -100,8 +104,19 @@
 static ssize_t show_in_use(struct class_device *cd, char *buf)
 {
 	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+	int in_use = 0;
 
-	return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
+	if (unlikely(chan->slow_ref) &&
+		atomic_read(&chan->refcount.refcount) > 1)
+		in_use = 1;
+	else {
+		if (local_read(&(per_cpu_ptr(chan->local,
+			get_cpu())->refcount)) > 0)
+			in_use = 1;
+		put_cpu();
+	}
+
+	return sprintf(buf, "%d\n", in_use);
 }
 
 static struct class_device_attribute dma_class_attrs[] = {
@@ -127,44 +142,73 @@
 
 /* --- client and device registration --- */
 
+#define dma_chan_satisfies_mask(chan, mask) \
+	__dma_chan_satisfies_mask((chan), &(mask))
+static int
+__dma_chan_satisfies_mask(struct dma_chan *chan, dma_cap_mask_t *want)
+{
+	dma_cap_mask_t has;
+
+	bitmap_and(has.bits, want->bits, chan->device->cap_mask.bits,
+		DMA_TX_TYPE_END);
+	return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END);
+}
+
 /**
- * dma_client_chan_alloc - try to allocate a channel to a client
+ * dma_client_chan_alloc - try to allocate channels to a client
  * @client: &dma_client
  *
  * Called with dma_list_mutex held.
  */
-static struct dma_chan *dma_client_chan_alloc(struct dma_client *client)
+static void dma_client_chan_alloc(struct dma_client *client)
 {
 	struct dma_device *device;
 	struct dma_chan *chan;
-	unsigned long flags;
 	int desc;	/* allocated descriptor count */
+	enum dma_state_client ack;
 
-	/* Find a channel, any DMA engine will do */
-	list_for_each_entry(device, &dma_device_list, global_node) {
+	/* Find a channel */
+	list_for_each_entry(device, &dma_device_list, global_node)
 		list_for_each_entry(chan, &device->channels, device_node) {
-			if (chan->client)
+			if (!dma_chan_satisfies_mask(chan, client->cap_mask))
 				continue;
 
 			desc = chan->device->device_alloc_chan_resources(chan);
 			if (desc >= 0) {
-				kref_get(&device->refcount);
-				kref_init(&chan->refcount);
-				chan->slow_ref = 0;
-				INIT_RCU_HEAD(&chan->rcu);
-				chan->client = client;
-				spin_lock_irqsave(&client->lock, flags);
-				list_add_tail_rcu(&chan->client_node,
-				                  &client->channels);
-				spin_unlock_irqrestore(&client->lock, flags);
-				return chan;
+				ack = client->event_callback(client,
+						chan,
+						DMA_RESOURCE_AVAILABLE);
+
+				/* we are done once this client rejects
+				 * an available resource
+				 */
+				if (ack == DMA_ACK) {
+					dma_chan_get(chan);
+					kref_get(&device->refcount);
+				} else if (ack == DMA_NAK)
+					return;
 			}
 		}
-	}
-
-	return NULL;
 }
 
+enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
+{
+	enum dma_status status;
+	unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000);
+
+	dma_async_issue_pending(chan);
+	do {
+		status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+		if (time_after_eq(jiffies, dma_sync_wait_timeout)) {
+			printk(KERN_ERR "dma_sync_wait_timeout!\n");
+			return DMA_ERROR;
+		}
+	} while (status == DMA_IN_PROGRESS);
+
+	return status;
+}
+EXPORT_SYMBOL(dma_sync_wait);
+
 /**
  * dma_chan_cleanup - release a DMA channel's resources
  * @kref: kernel reference structure that contains the DMA channel device
@@ -173,7 +217,6 @@
 {
 	struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
 	chan->device->device_free_chan_resources(chan);
-	chan->client = NULL;
 	kref_put(&chan->device->refcount, dma_async_device_cleanup);
 }
 EXPORT_SYMBOL(dma_chan_cleanup);
@@ -189,7 +232,7 @@
 	kref_put(&chan->refcount, dma_chan_cleanup);
 }
 
-static void dma_client_chan_free(struct dma_chan *chan)
+static void dma_chan_release(struct dma_chan *chan)
 {
 	atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
 	chan->slow_ref = 1;
@@ -197,41 +240,42 @@
 }
 
 /**
- * dma_chans_rebalance - reallocate channels to clients
- *
- * When the number of DMA channel in the system changes,
- * channels need to be rebalanced among clients.
+ * dma_chans_notify_available - broadcast available channels to the clients
  */
-static void dma_chans_rebalance(void)
+static void dma_clients_notify_available(void)
 {
 	struct dma_client *client;
-	struct dma_chan *chan;
-	unsigned long flags;
+
+	mutex_lock(&dma_list_mutex);
+
+	list_for_each_entry(client, &dma_client_list, global_node)
+		dma_client_chan_alloc(client);
+
+	mutex_unlock(&dma_list_mutex);
+}
+
+/**
+ * dma_chans_notify_available - tell the clients that a channel is going away
+ * @chan: channel on its way out
+ */
+static void dma_clients_notify_removed(struct dma_chan *chan)
+{
+	struct dma_client *client;
+	enum dma_state_client ack;
 
 	mutex_lock(&dma_list_mutex);
 
 	list_for_each_entry(client, &dma_client_list, global_node) {
-		while (client->chans_desired > client->chan_count) {
-			chan = dma_client_chan_alloc(client);
-			if (!chan)
-				break;
-			client->chan_count++;
-			client->event_callback(client,
-	                                       chan,
-	                                       DMA_RESOURCE_ADDED);
-		}
-		while (client->chans_desired < client->chan_count) {
-			spin_lock_irqsave(&client->lock, flags);
-			chan = list_entry(client->channels.next,
-			                  struct dma_chan,
-			                  client_node);
-			list_del_rcu(&chan->client_node);
-			spin_unlock_irqrestore(&client->lock, flags);
-			client->chan_count--;
-			client->event_callback(client,
-			                       chan,
-			                       DMA_RESOURCE_REMOVED);
-			dma_client_chan_free(chan);
+		ack = client->event_callback(client, chan,
+				DMA_RESOURCE_REMOVED);
+
+		/* client was holding resources for this channel so
+		 * free it
+		 */
+		if (ack == DMA_ACK) {
+			dma_chan_put(chan);
+			kref_put(&chan->device->refcount,
+				dma_async_device_cleanup);
 		}
 	}
 
@@ -239,28 +283,14 @@
 }
 
 /**
- * dma_async_client_register - allocate and register a &dma_client
- * @event_callback: callback for notification of channel addition/removal
+ * dma_async_client_register - register a &dma_client
+ * @client: ptr to a client structure with valid 'event_callback' and 'cap_mask'
  */
-struct dma_client *dma_async_client_register(dma_event_callback event_callback)
+void dma_async_client_register(struct dma_client *client)
 {
-	struct dma_client *client;
-
-	client = kzalloc(sizeof(*client), GFP_KERNEL);
-	if (!client)
-		return NULL;
-
-	INIT_LIST_HEAD(&client->channels);
-	spin_lock_init(&client->lock);
-	client->chans_desired = 0;
-	client->chan_count = 0;
-	client->event_callback = event_callback;
-
 	mutex_lock(&dma_list_mutex);
 	list_add_tail(&client->global_node, &dma_client_list);
 	mutex_unlock(&dma_list_mutex);
-
-	return client;
 }
 EXPORT_SYMBOL(dma_async_client_register);
 
@@ -272,40 +302,42 @@
  */
 void dma_async_client_unregister(struct dma_client *client)
 {
+	struct dma_device *device;
 	struct dma_chan *chan;
+	enum dma_state_client ack;
 
 	if (!client)
 		return;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(chan, &client->channels, client_node)
-		dma_client_chan_free(chan);
-	rcu_read_unlock();
-
 	mutex_lock(&dma_list_mutex);
+	/* free all channels the client is holding */
+	list_for_each_entry(device, &dma_device_list, global_node)
+		list_for_each_entry(chan, &device->channels, device_node) {
+			ack = client->event_callback(client, chan,
+				DMA_RESOURCE_REMOVED);
+
+			if (ack == DMA_ACK) {
+				dma_chan_put(chan);
+				kref_put(&chan->device->refcount,
+					dma_async_device_cleanup);
+			}
+		}
+
 	list_del(&client->global_node);
 	mutex_unlock(&dma_list_mutex);
-
-	kfree(client);
-	dma_chans_rebalance();
 }
 EXPORT_SYMBOL(dma_async_client_unregister);
 
 /**
- * dma_async_client_chan_request - request DMA channels
- * @client: &dma_client
- * @number: count of DMA channels requested
- *
- * Clients call dma_async_client_chan_request() to specify how many
- * DMA channels they need, 0 to free all currently allocated.
- * The resulting allocations/frees are indicated to the client via the
- * event callback.
+ * dma_async_client_chan_request - send all available channels to the
+ * client that satisfy the capability mask
+ * @client - requester
  */
-void dma_async_client_chan_request(struct dma_client *client,
-			unsigned int number)
+void dma_async_client_chan_request(struct dma_client *client)
 {
-	client->chans_desired = number;
-	dma_chans_rebalance();
+	mutex_lock(&dma_list_mutex);
+	dma_client_chan_alloc(client);
+	mutex_unlock(&dma_list_mutex);
 }
 EXPORT_SYMBOL(dma_async_client_chan_request);
 
@@ -316,12 +348,31 @@
 int dma_async_device_register(struct dma_device *device)
 {
 	static int id;
-	int chancnt = 0;
+	int chancnt = 0, rc;
 	struct dma_chan* chan;
 
 	if (!device)
 		return -ENODEV;
 
+	/* validate device routines */
+	BUG_ON(dma_has_cap(DMA_MEMCPY, device->cap_mask) &&
+		!device->device_prep_dma_memcpy);
+	BUG_ON(dma_has_cap(DMA_XOR, device->cap_mask) &&
+		!device->device_prep_dma_xor);
+	BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
+		!device->device_prep_dma_zero_sum);
+	BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) &&
+		!device->device_prep_dma_memset);
+	BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
+		!device->device_prep_dma_interrupt);
+
+	BUG_ON(!device->device_alloc_chan_resources);
+	BUG_ON(!device->device_free_chan_resources);
+	BUG_ON(!device->device_dependency_added);
+	BUG_ON(!device->device_is_tx_complete);
+	BUG_ON(!device->device_issue_pending);
+	BUG_ON(!device->dev);
+
 	init_completion(&device->done);
 	kref_init(&device->refcount);
 	device->dev_id = id++;
@@ -338,17 +389,38 @@
 		snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d",
 		         device->dev_id, chan->chan_id);
 
+		rc = class_device_register(&chan->class_dev);
+		if (rc) {
+			chancnt--;
+			free_percpu(chan->local);
+			chan->local = NULL;
+			goto err_out;
+		}
+
 		kref_get(&device->refcount);
-		class_device_register(&chan->class_dev);
+		kref_init(&chan->refcount);
+		chan->slow_ref = 0;
+		INIT_RCU_HEAD(&chan->rcu);
 	}
 
 	mutex_lock(&dma_list_mutex);
 	list_add_tail(&device->global_node, &dma_device_list);
 	mutex_unlock(&dma_list_mutex);
 
-	dma_chans_rebalance();
+	dma_clients_notify_available();
 
 	return 0;
+
+err_out:
+	list_for_each_entry(chan, &device->channels, device_node) {
+		if (chan->local == NULL)
+			continue;
+		kref_put(&device->refcount, dma_async_device_cleanup);
+		class_device_unregister(&chan->class_dev);
+		chancnt--;
+		free_percpu(chan->local);
+	}
+	return rc;
 }
 EXPORT_SYMBOL(dma_async_device_register);
 
@@ -371,32 +443,165 @@
 void dma_async_device_unregister(struct dma_device *device)
 {
 	struct dma_chan *chan;
-	unsigned long flags;
 
 	mutex_lock(&dma_list_mutex);
 	list_del(&device->global_node);
 	mutex_unlock(&dma_list_mutex);
 
 	list_for_each_entry(chan, &device->channels, device_node) {
-		if (chan->client) {
-			spin_lock_irqsave(&chan->client->lock, flags);
-			list_del(&chan->client_node);
-			chan->client->chan_count--;
-			spin_unlock_irqrestore(&chan->client->lock, flags);
-			chan->client->event_callback(chan->client,
-			                             chan,
-			                             DMA_RESOURCE_REMOVED);
-			dma_client_chan_free(chan);
-		}
+		dma_clients_notify_removed(chan);
 		class_device_unregister(&chan->class_dev);
+		dma_chan_release(chan);
 	}
-	dma_chans_rebalance();
 
 	kref_put(&device->refcount, dma_async_device_cleanup);
 	wait_for_completion(&device->done);
 }
 EXPORT_SYMBOL(dma_async_device_unregister);
 
+/**
+ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
+ * @chan: DMA channel to offload copy to
+ * @dest: destination address (virtual)
+ * @src: source address (virtual)
+ * @len: length
+ *
+ * Both @dest and @src must be mappable to a bus address according to the
+ * DMA mapping API rules for streaming mappings.
+ * Both @dest and @src must stay memory resident (kernel memory or locked
+ * user space pages).
+ */
+dma_cookie_t
+dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+			void *src, size_t len)
+{
+	struct dma_device *dev = chan->device;
+	struct dma_async_tx_descriptor *tx;
+	dma_addr_t addr;
+	dma_cookie_t cookie;
+	int cpu;
+
+	tx = dev->device_prep_dma_memcpy(chan, len, 0);
+	if (!tx)
+		return -ENOMEM;
+
+	tx->ack = 1;
+	tx->callback = NULL;
+	addr = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
+	tx->tx_set_src(addr, tx, 0);
+	addr = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
+	tx->tx_set_dest(addr, tx, 0);
+	cookie = tx->tx_submit(tx);
+
+	cpu = get_cpu();
+	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+	put_cpu();
+
+	return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
+ * @chan: DMA channel to offload copy to
+ * @page: destination page
+ * @offset: offset in page to copy to
+ * @kdata: source address (virtual)
+ * @len: length
+ *
+ * Both @page/@offset and @kdata must be mappable to a bus address according
+ * to the DMA mapping API rules for streaming mappings.
+ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
+ * locked user space pages)
+ */
+dma_cookie_t
+dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+			unsigned int offset, void *kdata, size_t len)
+{
+	struct dma_device *dev = chan->device;
+	struct dma_async_tx_descriptor *tx;
+	dma_addr_t addr;
+	dma_cookie_t cookie;
+	int cpu;
+
+	tx = dev->device_prep_dma_memcpy(chan, len, 0);
+	if (!tx)
+		return -ENOMEM;
+
+	tx->ack = 1;
+	tx->callback = NULL;
+	addr = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
+	tx->tx_set_src(addr, tx, 0);
+	addr = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
+	tx->tx_set_dest(addr, tx, 0);
+	cookie = tx->tx_submit(tx);
+
+	cpu = get_cpu();
+	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+	put_cpu();
+
+	return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+
+/**
+ * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
+ * @chan: DMA channel to offload copy to
+ * @dest_pg: destination page
+ * @dest_off: offset in page to copy to
+ * @src_pg: source page
+ * @src_off: offset in page to copy from
+ * @len: length
+ *
+ * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
+ * address according to the DMA mapping API rules for streaming mappings.
+ * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
+ * (kernel memory or locked user space pages).
+ */
+dma_cookie_t
+dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+	unsigned int dest_off, struct page *src_pg, unsigned int src_off,
+	size_t len)
+{
+	struct dma_device *dev = chan->device;
+	struct dma_async_tx_descriptor *tx;
+	dma_addr_t addr;
+	dma_cookie_t cookie;
+	int cpu;
+
+	tx = dev->device_prep_dma_memcpy(chan, len, 0);
+	if (!tx)
+		return -ENOMEM;
+
+	tx->ack = 1;
+	tx->callback = NULL;
+	addr = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
+	tx->tx_set_src(addr, tx, 0);
+	addr = dma_map_page(dev->dev, dest_pg, dest_off, len, DMA_FROM_DEVICE);
+	tx->tx_set_dest(addr, tx, 0);
+	cookie = tx->tx_submit(tx);
+
+	cpu = get_cpu();
+	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+	put_cpu();
+
+	return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
+
+void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+	struct dma_chan *chan)
+{
+	tx->chan = chan;
+	spin_lock_init(&tx->lock);
+	INIT_LIST_HEAD(&tx->depend_node);
+	INIT_LIST_HEAD(&tx->depend_list);
+}
+EXPORT_SYMBOL(dma_async_tx_descriptor_init);
+
 static int __init dma_bus_init(void)
 {
 	mutex_init(&dma_list_mutex);
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c
index 8e87261..5fbe56b 100644
--- a/drivers/dma/ioatdma.c
+++ b/drivers/dma/ioatdma.c
@@ -32,16 +32,17 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include "ioatdma.h"
-#include "ioatdma_io.h"
 #include "ioatdma_registers.h"
 #include "ioatdma_hw.h"
 
 #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
 #define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
 #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
+#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
 
 /* internal functions */
 static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void ioat_shutdown(struct pci_dev *pdev);
 static void __devexit ioat_remove(struct pci_dev *pdev);
 
 static int enumerate_dma_channels(struct ioat_device *device)
@@ -51,8 +52,8 @@
 	int i;
 	struct ioat_dma_chan *ioat_chan;
 
-	device->common.chancnt = ioatdma_read8(device, IOAT_CHANCNT_OFFSET);
-	xfercap_scale = ioatdma_read8(device, IOAT_XFERCAP_OFFSET);
+	device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
+	xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
 	xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
 
 	for (i = 0; i < device->common.chancnt; i++) {
@@ -71,13 +72,79 @@
 		INIT_LIST_HEAD(&ioat_chan->used_desc);
 		/* This should be made common somewhere in dmaengine.c */
 		ioat_chan->common.device = &device->common;
-		ioat_chan->common.client = NULL;
 		list_add_tail(&ioat_chan->common.device_node,
 		              &device->common.channels);
 	}
 	return device->common.chancnt;
 }
 
+static void
+ioat_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
+{
+	struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+
+	pci_unmap_addr_set(desc, src, addr);
+
+	list_for_each_entry(iter, &desc->async_tx.tx_list, node) {
+		iter->hw->src_addr = addr;
+		addr += ioat_chan->xfercap;
+	}
+
+}
+
+static void
+ioat_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
+{
+	struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+
+	pci_unmap_addr_set(desc, dst, addr);
+
+	list_for_each_entry(iter, &desc->async_tx.tx_list, node) {
+		iter->hw->dst_addr = addr;
+		addr += ioat_chan->xfercap;
+	}
+}
+
+static dma_cookie_t
+ioat_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+	struct ioat_desc_sw *desc = tx_to_ioat_desc(tx);
+	int append = 0;
+	dma_cookie_t cookie;
+	struct ioat_desc_sw *group_start;
+
+	group_start = list_entry(desc->async_tx.tx_list.next,
+				 struct ioat_desc_sw, node);
+	spin_lock_bh(&ioat_chan->desc_lock);
+	/* cookie incr and addition to used_list must be atomic */
+	cookie = ioat_chan->common.cookie;
+	cookie++;
+	if (cookie < 0)
+		cookie = 1;
+	ioat_chan->common.cookie = desc->async_tx.cookie = cookie;
+
+	/* write address into NextDescriptor field of last desc in chain */
+	to_ioat_desc(ioat_chan->used_desc.prev)->hw->next =
+						group_start->async_tx.phys;
+	list_splice_init(&desc->async_tx.tx_list, ioat_chan->used_desc.prev);
+
+	ioat_chan->pending += desc->tx_cnt;
+	if (ioat_chan->pending >= 4) {
+		append = 1;
+		ioat_chan->pending = 0;
+	}
+	spin_unlock_bh(&ioat_chan->desc_lock);
+
+	if (append)
+		writeb(IOAT_CHANCMD_APPEND,
+			ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
+	
+	return cookie;
+}
+
 static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
 	struct ioat_dma_chan *ioat_chan,
 	gfp_t flags)
@@ -99,8 +166,13 @@
 	}
 
 	memset(desc, 0, sizeof(*desc));
+	dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
+	desc_sw->async_tx.tx_set_src = ioat_set_src;
+	desc_sw->async_tx.tx_set_dest = ioat_set_dest;
+	desc_sw->async_tx.tx_submit = ioat_tx_submit;
+	INIT_LIST_HEAD(&desc_sw->async_tx.tx_list);
 	desc_sw->hw = desc;
-	desc_sw->phys = phys;
+	desc_sw->async_tx.phys = phys;
 
 	return desc_sw;
 }
@@ -123,7 +195,7 @@
 	 * In-use bit automatically set by reading chanctrl
 	 * If 0, we got it, if 1, someone else did
 	 */
-	chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+	chanctrl = readw(ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
 	if (chanctrl & IOAT_CHANCTRL_CHANNEL_IN_USE)
 		return -EBUSY;
 
@@ -132,12 +204,12 @@
 		IOAT_CHANCTRL_ERR_INT_EN |
 		IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
 		IOAT_CHANCTRL_ERR_COMPLETION_EN;
-        ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+        writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
 
-	chanerr = ioatdma_chan_read32(ioat_chan, IOAT_CHANERR_OFFSET);
+	chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
 	if (chanerr) {
 		printk("IOAT: CHANERR = %x, clearing\n", chanerr);
-		ioatdma_chan_write32(ioat_chan, IOAT_CHANERR_OFFSET, chanerr);
+		writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
 	}
 
 	/* Allocate descriptors */
@@ -161,10 +233,10 @@
 		               &ioat_chan->completion_addr);
 	memset(ioat_chan->completion_virt, 0,
 	       sizeof(*ioat_chan->completion_virt));
-	ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_LOW,
-	               ((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF);
-	ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_HIGH,
-	               ((u64) ioat_chan->completion_addr) >> 32);
+	writel(((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF,
+	       ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);
+	writel(((u64) ioat_chan->completion_addr) >> 32,
+	       ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
 
 	ioat_start_null_desc(ioat_chan);
 	return i;
@@ -182,18 +254,20 @@
 
 	ioat_dma_memcpy_cleanup(ioat_chan);
 
-	ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
+	writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
 
 	spin_lock_bh(&ioat_chan->desc_lock);
 	list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
 		in_use_descs++;
 		list_del(&desc->node);
-		pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+		pci_pool_free(ioat_device->dma_pool, desc->hw,
+			      desc->async_tx.phys);
 		kfree(desc);
 	}
 	list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
 		list_del(&desc->node);
-		pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+		pci_pool_free(ioat_device->dma_pool, desc->hw,
+			      desc->async_tx.phys);
 		kfree(desc);
 	}
 	spin_unlock_bh(&ioat_chan->desc_lock);
@@ -210,50 +284,30 @@
 	ioat_chan->last_completion = ioat_chan->completion_addr = 0;
 
 	/* Tell hw the chan is free */
-	chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+	chanctrl = readw(ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
 	chanctrl &= ~IOAT_CHANCTRL_CHANNEL_IN_USE;
-	ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+	writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
-/**
- * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction
- * @ioat_chan: IOAT DMA channel handle
- * @dest: DMA destination address
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
-                                       dma_addr_t dest,
-                                       dma_addr_t src,
-                                       size_t len)
+static struct dma_async_tx_descriptor *
+ioat_dma_prep_memcpy(struct dma_chan *chan, size_t len, int int_en)
 {
-	struct ioat_desc_sw *first;
-	struct ioat_desc_sw *prev;
-	struct ioat_desc_sw *new;
-	dma_cookie_t cookie;
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+	struct ioat_desc_sw *first, *prev, *new;
 	LIST_HEAD(new_chain);
 	u32 copy;
 	size_t orig_len;
-	dma_addr_t orig_src, orig_dst;
-	unsigned int desc_count = 0;
-	unsigned int append = 0;
-
-	if (!ioat_chan || !dest || !src)
-		return -EFAULT;
+	int desc_count = 0;
 
 	if (!len)
-		return ioat_chan->common.cookie;
+		return NULL;
 
 	orig_len = len;
-	orig_src = src;
-	orig_dst = dest;
 
 	first = NULL;
 	prev = NULL;
 
 	spin_lock_bh(&ioat_chan->desc_lock);
-
 	while (len) {
 		if (!list_empty(&ioat_chan->free_desc)) {
 			new = to_ioat_desc(ioat_chan->free_desc.next);
@@ -270,141 +324,36 @@
 
 		new->hw->size = copy;
 		new->hw->ctl = 0;
-		new->hw->src_addr = src;
-		new->hw->dst_addr = dest;
-		new->cookie = 0;
+		new->async_tx.cookie = 0;
+		new->async_tx.ack = 1;
 
 		/* chain together the physical address list for the HW */
 		if (!first)
 			first = new;
 		else
-			prev->hw->next = (u64) new->phys;
+			prev->hw->next = (u64) new->async_tx.phys;
 
 		prev = new;
-
 		len  -= copy;
-		dest += copy;
-		src  += copy;
-
 		list_add_tail(&new->node, &new_chain);
 		desc_count++;
 	}
+
+	list_splice(&new_chain, &new->async_tx.tx_list);
+
 	new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
 	new->hw->next = 0;
+	new->tx_cnt = desc_count;
+	new->async_tx.ack = 0; /* client is in control of this ack */
+	new->async_tx.cookie = -EBUSY;
 
-	/* cookie incr and addition to used_list must be atomic */
-
-	cookie = ioat_chan->common.cookie;
-	cookie++;
-	if (cookie < 0)
-		cookie = 1;
-	ioat_chan->common.cookie = new->cookie = cookie;
-
-	pci_unmap_addr_set(new, src, orig_src);
-	pci_unmap_addr_set(new, dst, orig_dst);
 	pci_unmap_len_set(new, src_len, orig_len);
 	pci_unmap_len_set(new, dst_len, orig_len);
-
-	/* write address into NextDescriptor field of last desc in chain */
-	to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys;
-	list_splice_init(&new_chain, ioat_chan->used_desc.prev);
-
-	ioat_chan->pending += desc_count;
-	if (ioat_chan->pending >= 20) {
-		append = 1;
-		ioat_chan->pending = 0;
-	}
-
 	spin_unlock_bh(&ioat_chan->desc_lock);
 
-	if (append)
-		ioatdma_chan_write8(ioat_chan,
-		                    IOAT_CHANCMD_OFFSET,
-		                    IOAT_CHANCMD_APPEND);
-	return cookie;
+	return new ? &new->async_tx : NULL;
 }
 
-/**
- * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs
- * @chan: IOAT DMA channel handle
- * @dest: DMA destination address
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan,
-                                               void *dest,
-                                               void *src,
-                                               size_t len)
-{
-	dma_addr_t dest_addr;
-	dma_addr_t src_addr;
-	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
-	dest_addr = pci_map_single(ioat_chan->device->pdev,
-		dest, len, PCI_DMA_FROMDEVICE);
-	src_addr = pci_map_single(ioat_chan->device->pdev,
-		src, len, PCI_DMA_TODEVICE);
-
-	return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
-}
-
-/**
- * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page
- * @chan: IOAT DMA channel handle
- * @page: pointer to the page to copy to
- * @offset: offset into that page
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan,
-                                              struct page *page,
-                                              unsigned int offset,
-                                              void *src,
-                                              size_t len)
-{
-	dma_addr_t dest_addr;
-	dma_addr_t src_addr;
-	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
-	dest_addr = pci_map_page(ioat_chan->device->pdev,
-		page, offset, len, PCI_DMA_FROMDEVICE);
-	src_addr = pci_map_single(ioat_chan->device->pdev,
-		src, len, PCI_DMA_TODEVICE);
-
-	return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
-}
-
-/**
- * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages
- * @chan: IOAT DMA channel handle
- * @dest_pg: pointer to the page to copy to
- * @dest_off: offset into that page
- * @src_pg: pointer to the page to copy from
- * @src_off: offset into that page
- * @len: transaction length in bytes. This is guaranteed not to make a copy
- *	 across a page boundary.
- */
-
-static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan,
-                                             struct page *dest_pg,
-                                             unsigned int dest_off,
-                                             struct page *src_pg,
-                                             unsigned int src_off,
-                                             size_t len)
-{
-	dma_addr_t dest_addr;
-	dma_addr_t src_addr;
-	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
-	dest_addr = pci_map_page(ioat_chan->device->pdev,
-		dest_pg, dest_off, len, PCI_DMA_FROMDEVICE);
-	src_addr = pci_map_page(ioat_chan->device->pdev,
-		src_pg, src_off, len, PCI_DMA_TODEVICE);
-
-	return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
-}
 
 /**
  * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw
@@ -417,9 +366,8 @@
 
 	if (ioat_chan->pending != 0) {
 		ioat_chan->pending = 0;
-		ioatdma_chan_write8(ioat_chan,
-		                    IOAT_CHANCMD_OFFSET,
-		                    IOAT_CHANCMD_APPEND);
+		writeb(IOAT_CHANCMD_APPEND,
+		       ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
 	}
 }
 
@@ -449,7 +397,7 @@
 	if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==
 		IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {
 		printk("IOAT: Channel halted, chanerr = %x\n",
-			ioatdma_chan_read32(chan, IOAT_CHANERR_OFFSET));
+			readl(chan->reg_base + IOAT_CHANERR_OFFSET));
 
 		/* TODO do something to salvage the situation */
 	}
@@ -467,8 +415,8 @@
 		 * exceeding xfercap, perhaps. If so, only the last one will
 		 * have a cookie, and require unmapping.
 		 */
-		if (desc->cookie) {
-			cookie = desc->cookie;
+		if (desc->async_tx.cookie) {
+			cookie = desc->async_tx.cookie;
 
 			/* yes we are unmapping both _page and _single alloc'd
 			   regions with unmap_page. Is this *really* that bad?
@@ -483,14 +431,19 @@
 					PCI_DMA_TODEVICE);
 		}
 
-		if (desc->phys != phys_complete) {
-			/* a completed entry, but not the last, so cleanup */
-			list_del(&desc->node);
-			list_add_tail(&desc->node, &chan->free_desc);
+		if (desc->async_tx.phys != phys_complete) {
+			/* a completed entry, but not the last, so cleanup
+			 * if the client is done with the descriptor
+			 */
+			if (desc->async_tx.ack) {
+				list_del(&desc->node);
+				list_add_tail(&desc->node, &chan->free_desc);
+			} else
+				desc->async_tx.cookie = 0;
 		} else {
 			/* last used desc. Do not remove, so we can append from
 			   it, but don't look at it next time, either */
-			desc->cookie = 0;
+			desc->async_tx.cookie = 0;
 
 			/* TODO check status bits? */
 			break;
@@ -506,6 +459,17 @@
 	spin_unlock(&chan->cleanup_lock);
 }
 
+static void ioat_dma_dependency_added(struct dma_chan *chan)
+{
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+	spin_lock_bh(&ioat_chan->desc_lock);
+	if (ioat_chan->pending == 0) {
+		spin_unlock_bh(&ioat_chan->desc_lock);
+		ioat_dma_memcpy_cleanup(ioat_chan);
+	} else
+		spin_unlock_bh(&ioat_chan->desc_lock);
+}
+
 /**
  * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
  * @chan: IOAT DMA channel handle
@@ -553,13 +517,16 @@
 
 static struct pci_device_id ioat_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_UNISYS,
+		     PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
 	{ 0, }
 };
 
-static struct pci_driver ioat_pci_drv = {
+static struct pci_driver ioat_pci_driver = {
 	.name 	= "ioatdma",
 	.id_table = ioat_pci_tbl,
 	.probe	= ioat_probe,
+	.shutdown = ioat_shutdown,
 	.remove	= __devexit_p(ioat_remove),
 };
 
@@ -569,21 +536,21 @@
 	unsigned long attnstatus;
 	u8 intrctrl;
 
-	intrctrl = ioatdma_read8(instance, IOAT_INTRCTRL_OFFSET);
+	intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET);
 
 	if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))
 		return IRQ_NONE;
 
 	if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {
-		ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+		writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
 		return IRQ_NONE;
 	}
 
-	attnstatus = ioatdma_read32(instance, IOAT_ATTNSTATUS_OFFSET);
+	attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
 
 	printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus);
 
-	ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+	writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
 	return IRQ_HANDLED;
 }
 
@@ -607,19 +574,17 @@
 
 	desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
 	desc->hw->next = 0;
+	desc->async_tx.ack = 1;
 
 	list_add_tail(&desc->node, &ioat_chan->used_desc);
 	spin_unlock_bh(&ioat_chan->desc_lock);
 
-#if (BITS_PER_LONG == 64)
-	ioatdma_chan_write64(ioat_chan, IOAT_CHAINADDR_OFFSET, desc->phys);
-#else
-	ioatdma_chan_write32(ioat_chan,
-	                     IOAT_CHAINADDR_OFFSET_LOW,
-	                     (u32) desc->phys);
-	ioatdma_chan_write32(ioat_chan, IOAT_CHAINADDR_OFFSET_HIGH, 0);
-#endif
-	ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_START);
+	writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+	       ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW);
+	writel(((u64) desc->async_tx.phys) >> 32,
+	       ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH);
+
+	writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
 }
 
 /*
@@ -633,6 +598,8 @@
 	u8 *src;
 	u8 *dest;
 	struct dma_chan *dma_chan;
+	struct dma_async_tx_descriptor *tx;
+	dma_addr_t addr;
 	dma_cookie_t cookie;
 	int err = 0;
 
@@ -658,7 +625,15 @@
 		goto out;
 	}
 
-	cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE);
+	tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
+	async_tx_ack(tx);
+	addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
+			DMA_TO_DEVICE);
+	ioat_set_src(addr, tx, 0);
+	addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
+			DMA_FROM_DEVICE);
+	ioat_set_dest(addr, tx, 0);
+	cookie = ioat_tx_submit(tx);
 	ioat_dma_memcpy_issue_pending(dma_chan);
 	msleep(1);
 
@@ -699,7 +674,7 @@
 	if (err)
 		goto err_set_dma_mask;
 
-	err = pci_request_regions(pdev, ioat_pci_drv.name);
+	err = pci_request_regions(pdev, ioat_pci_driver.name);
 	if (err)
 		goto err_request_regions;
 
@@ -748,19 +723,20 @@
 
 	device->reg_base = reg_base;
 
-	ioatdma_write8(device, IOAT_INTRCTRL_OFFSET, IOAT_INTRCTRL_MASTER_INT_EN);
+	writeb(IOAT_INTRCTRL_MASTER_INT_EN, device->reg_base + IOAT_INTRCTRL_OFFSET);
 	pci_set_master(pdev);
 
 	INIT_LIST_HEAD(&device->common.channels);
 	enumerate_dma_channels(device);
 
+	dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
 	device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
 	device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
-	device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf;
-	device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg;
-	device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg;
-	device->common.device_memcpy_complete = ioat_dma_is_complete;
-	device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending;
+	device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy;
+	device->common.device_is_tx_complete = ioat_dma_is_complete;
+	device->common.device_issue_pending = ioat_dma_memcpy_issue_pending;
+	device->common.device_dependency_added = ioat_dma_dependency_added;
+	device->common.dev = &pdev->dev;
 	printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
 		device->common.chancnt);
 
@@ -787,9 +763,20 @@
 err_set_dma_mask:
 	pci_disable_device(pdev);
 err_enable_device:
+
+	printk(KERN_ERR "Intel(R) I/OAT DMA Engine initialization failed\n");
+
 	return err;
 }
 
+static void ioat_shutdown(struct pci_dev *pdev)
+{
+	struct ioat_device *device;
+	device = pci_get_drvdata(pdev);
+
+	dma_async_device_unregister(&device->common);
+}
+
 static void __devexit ioat_remove(struct pci_dev *pdev)
 {
 	struct ioat_device *device;
@@ -818,7 +805,7 @@
 }
 
 /* MODULE API */
-MODULE_VERSION("1.7");
+MODULE_VERSION("1.9");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Intel Corporation");
 
@@ -828,14 +815,14 @@
 	/* if forced, worst case is that rmmod hangs */
 	__unsafe(THIS_MODULE);
 
-	return pci_register_driver(&ioat_pci_drv);
+	return pci_register_driver(&ioat_pci_driver);
 }
 
 module_init(ioat_init_module);
 
 static void __exit ioat_exit_module(void)
 {
-	pci_unregister_driver(&ioat_pci_drv);
+	pci_unregister_driver(&ioat_pci_driver);
 }
 
 module_exit(ioat_exit_module);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index 62b26a9..d372647 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -30,9 +30,6 @@
 
 #define IOAT_LOW_COMPLETION_MASK	0xffffffc0
 
-extern struct list_head dma_device_list;
-extern struct list_head dma_client_list;
-
 /**
  * struct ioat_device - internal representation of a IOAT device
  * @pdev: PCI-Express device
@@ -105,21 +102,20 @@
 /**
  * struct ioat_desc_sw - wrapper around hardware descriptor
  * @hw: hardware DMA descriptor
- * @node:
- * @cookie:
- * @phys:
+ * @node: this descriptor will either be on the free list,
+ *     or attached to a transaction list (async_tx.tx_list)
+ * @tx_cnt: number of descriptors required to complete the transaction
+ * @async_tx: the generic software descriptor for all engines
  */
-
 struct ioat_desc_sw {
 	struct ioat_dma_descriptor *hw;
 	struct list_head node;
-	dma_cookie_t cookie;
-	dma_addr_t phys;
+	int tx_cnt;
 	DECLARE_PCI_UNMAP_ADDR(src)
 	DECLARE_PCI_UNMAP_LEN(src_len)
 	DECLARE_PCI_UNMAP_ADDR(dst)
 	DECLARE_PCI_UNMAP_LEN(dst_len)
+	struct dma_async_tx_descriptor async_tx;
 };
 
 #endif /* IOATDMA_H */
-
diff --git a/drivers/dma/ioatdma_io.h b/drivers/dma/ioatdma_io.h
deleted file mode 100644
index c0b4bf6..0000000
--- a/drivers/dma/ioatdma_io.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called COPYING.
- */
-#ifndef IOATDMA_IO_H
-#define IOATDMA_IO_H
-
-#include <asm/io.h>
-
-/*
- * device and per-channel MMIO register read and write functions
- * this is a lot of anoying inline functions, but it's typesafe
- */
-
-static inline u8 ioatdma_read8(struct ioat_device *device,
-                               unsigned int offset)
-{
-	return readb(device->reg_base + offset);
-}
-
-static inline u16 ioatdma_read16(struct ioat_device *device,
-                                 unsigned int offset)
-{
-	return readw(device->reg_base + offset);
-}
-
-static inline u32 ioatdma_read32(struct ioat_device *device,
-                                 unsigned int offset)
-{
-	return readl(device->reg_base + offset);
-}
-
-static inline void ioatdma_write8(struct ioat_device *device,
-                                  unsigned int offset, u8 value)
-{
-	writeb(value, device->reg_base + offset);
-}
-
-static inline void ioatdma_write16(struct ioat_device *device,
-                                   unsigned int offset, u16 value)
-{
-	writew(value, device->reg_base + offset);
-}
-
-static inline void ioatdma_write32(struct ioat_device *device,
-                                   unsigned int offset, u32 value)
-{
-	writel(value, device->reg_base + offset);
-}
-
-static inline u8 ioatdma_chan_read8(struct ioat_dma_chan *chan,
-                                    unsigned int offset)
-{
-	return readb(chan->reg_base + offset);
-}
-
-static inline u16 ioatdma_chan_read16(struct ioat_dma_chan *chan,
-                                      unsigned int offset)
-{
-	return readw(chan->reg_base + offset);
-}
-
-static inline u32 ioatdma_chan_read32(struct ioat_dma_chan *chan,
-                                      unsigned int offset)
-{
-	return readl(chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write8(struct ioat_dma_chan *chan,
-                                       unsigned int offset, u8 value)
-{
-	writeb(value, chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write16(struct ioat_dma_chan *chan,
-                                        unsigned int offset, u16 value)
-{
-	writew(value, chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write32(struct ioat_dma_chan *chan,
-                                        unsigned int offset, u32 value)
-{
-	writel(value, chan->reg_base + offset);
-}
-
-#if (BITS_PER_LONG == 64)
-static inline u64 ioatdma_chan_read64(struct ioat_dma_chan *chan,
-                                      unsigned int offset)
-{
-	return readq(chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write64(struct ioat_dma_chan *chan,
-                                        unsigned int offset, u64 value)
-{
-	writeq(value, chan->reg_base + offset);
-}
-#endif
-
-#endif /* IOATDMA_IO_H */
-
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
new file mode 100644
index 0000000..5a1d426
--- /dev/null
+++ b/drivers/dma/iop-adma.c
@@ -0,0 +1,1467 @@
+/*
+ * offload engine driver for the Intel Xscale series of i/o processors
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+/*
+ * This driver supports the asynchrounous DMA copy and RAID engines available
+ * on the Intel Xscale(R) family of I/O Processors (IOP 32x, 33x, 134x)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/async_tx.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/memory.h>
+#include <linux/ioport.h>
+
+#include <asm/arch/adma.h>
+
+#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
+#define to_iop_adma_device(dev) \
+	container_of(dev, struct iop_adma_device, common)
+#define tx_to_iop_adma_slot(tx) \
+	container_of(tx, struct iop_adma_desc_slot, async_tx)
+
+/**
+ * iop_adma_free_slots - flags descriptor slots for reuse
+ * @slot: Slot to free
+ * Caller must hold &iop_chan->lock while calling this function
+ */
+static void iop_adma_free_slots(struct iop_adma_desc_slot *slot)
+{
+	int stride = slot->slots_per_op;
+
+	while (stride--) {
+		slot->slots_per_op = 0;
+		slot = list_entry(slot->slot_node.next,
+				struct iop_adma_desc_slot,
+				slot_node);
+	}
+}
+
+static dma_cookie_t
+iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+	struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
+{
+	BUG_ON(desc->async_tx.cookie < 0);
+	spin_lock_bh(&desc->async_tx.lock);
+	if (desc->async_tx.cookie > 0) {
+		cookie = desc->async_tx.cookie;
+		desc->async_tx.cookie = 0;
+
+		/* call the callback (must not sleep or submit new
+		 * operations to this channel)
+		 */
+		if (desc->async_tx.callback)
+			desc->async_tx.callback(
+				desc->async_tx.callback_param);
+
+		/* unmap dma addresses
+		 * (unmap_single vs unmap_page?)
+		 */
+		if (desc->group_head && desc->unmap_len) {
+			struct iop_adma_desc_slot *unmap = desc->group_head;
+			struct device *dev =
+				&iop_chan->device->pdev->dev;
+			u32 len = unmap->unmap_len;
+			u32 src_cnt = unmap->unmap_src_cnt;
+			dma_addr_t addr = iop_desc_get_dest_addr(unmap,
+				iop_chan);
+
+			dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+			while (src_cnt--) {
+				addr = iop_desc_get_src_addr(unmap,
+							iop_chan,
+							src_cnt);
+				dma_unmap_page(dev, addr, len,
+					DMA_TO_DEVICE);
+			}
+			desc->group_head = NULL;
+		}
+	}
+
+	/* run dependent operations */
+	async_tx_run_dependencies(&desc->async_tx);
+	spin_unlock_bh(&desc->async_tx.lock);
+
+	return cookie;
+}
+
+static int
+iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
+	struct iop_adma_chan *iop_chan)
+{
+	/* the client is allowed to attach dependent operations
+	 * until 'ack' is set
+	 */
+	if (!desc->async_tx.ack)
+		return 0;
+
+	/* leave the last descriptor in the chain
+	 * so we can append to it
+	 */
+	if (desc->chain_node.next == &iop_chan->chain)
+		return 1;
+
+	dev_dbg(iop_chan->device->common.dev,
+		"\tfree slot: %d slots_per_op: %d\n",
+		desc->idx, desc->slots_per_op);
+
+	list_del(&desc->chain_node);
+	iop_adma_free_slots(desc);
+
+	return 0;
+}
+
+static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+{
+	struct iop_adma_desc_slot *iter, *_iter, *grp_start = NULL;
+	dma_cookie_t cookie = 0;
+	u32 current_desc = iop_chan_get_current_descriptor(iop_chan);
+	int busy = iop_chan_is_busy(iop_chan);
+	int seen_current = 0, slot_cnt = 0, slots_per_op = 0;
+
+	dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+	/* free completed slots from the chain starting with
+	 * the oldest descriptor
+	 */
+	list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
+					chain_node) {
+		pr_debug("\tcookie: %d slot: %d busy: %d "
+			"this_desc: %#x next_desc: %#x ack: %d\n",
+			iter->async_tx.cookie, iter->idx, busy,
+			iter->async_tx.phys, iop_desc_get_next_desc(iter),
+			iter->async_tx.ack);
+		prefetch(_iter);
+		prefetch(&_iter->async_tx);
+
+		/* do not advance past the current descriptor loaded into the
+		 * hardware channel, subsequent descriptors are either in
+		 * process or have not been submitted
+		 */
+		if (seen_current)
+			break;
+
+		/* stop the search if we reach the current descriptor and the
+		 * channel is busy, or if it appears that the current descriptor
+		 * needs to be re-read (i.e. has been appended to)
+		 */
+		if (iter->async_tx.phys == current_desc) {
+			BUG_ON(seen_current++);
+			if (busy || iop_desc_get_next_desc(iter))
+				break;
+		}
+
+		/* detect the start of a group transaction */
+		if (!slot_cnt && !slots_per_op) {
+			slot_cnt = iter->slot_cnt;
+			slots_per_op = iter->slots_per_op;
+			if (slot_cnt <= slots_per_op) {
+				slot_cnt = 0;
+				slots_per_op = 0;
+			}
+		}
+
+		if (slot_cnt) {
+			pr_debug("\tgroup++\n");
+			if (!grp_start)
+				grp_start = iter;
+			slot_cnt -= slots_per_op;
+		}
+
+		/* all the members of a group are complete */
+		if (slots_per_op != 0 && slot_cnt == 0) {
+			struct iop_adma_desc_slot *grp_iter, *_grp_iter;
+			int end_of_chain = 0;
+			pr_debug("\tgroup end\n");
+
+			/* collect the total results */
+			if (grp_start->xor_check_result) {
+				u32 zero_sum_result = 0;
+				slot_cnt = grp_start->slot_cnt;
+				grp_iter = grp_start;
+
+				list_for_each_entry_from(grp_iter,
+					&iop_chan->chain, chain_node) {
+					zero_sum_result |=
+					    iop_desc_get_zero_result(grp_iter);
+					    pr_debug("\titer%d result: %d\n",
+					    grp_iter->idx, zero_sum_result);
+					slot_cnt -= slots_per_op;
+					if (slot_cnt == 0)
+						break;
+				}
+				pr_debug("\tgrp_start->xor_check_result: %p\n",
+					grp_start->xor_check_result);
+				*grp_start->xor_check_result = zero_sum_result;
+			}
+
+			/* clean up the group */
+			slot_cnt = grp_start->slot_cnt;
+			grp_iter = grp_start;
+			list_for_each_entry_safe_from(grp_iter, _grp_iter,
+				&iop_chan->chain, chain_node) {
+				cookie = iop_adma_run_tx_complete_actions(
+					grp_iter, iop_chan, cookie);
+
+				slot_cnt -= slots_per_op;
+				end_of_chain = iop_adma_clean_slot(grp_iter,
+					iop_chan);
+
+				if (slot_cnt == 0 || end_of_chain)
+					break;
+			}
+
+			/* the group should be complete at this point */
+			BUG_ON(slot_cnt);
+
+			slots_per_op = 0;
+			grp_start = NULL;
+			if (end_of_chain)
+				break;
+			else
+				continue;
+		} else if (slots_per_op) /* wait for group completion */
+			continue;
+
+		/* write back zero sum results (single descriptor case) */
+		if (iter->xor_check_result && iter->async_tx.cookie)
+			*iter->xor_check_result =
+				iop_desc_get_zero_result(iter);
+
+		cookie = iop_adma_run_tx_complete_actions(
+					iter, iop_chan, cookie);
+
+		if (iop_adma_clean_slot(iter, iop_chan))
+			break;
+	}
+
+	BUG_ON(!seen_current);
+
+	iop_chan_idle(busy, iop_chan);
+
+	if (cookie > 0) {
+		iop_chan->completed_cookie = cookie;
+		pr_debug("\tcompleted cookie %d\n", cookie);
+	}
+}
+
+static void
+iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+{
+	spin_lock_bh(&iop_chan->lock);
+	__iop_adma_slot_cleanup(iop_chan);
+	spin_unlock_bh(&iop_chan->lock);
+}
+
+static void iop_adma_tasklet(unsigned long data)
+{
+	struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
+	__iop_adma_slot_cleanup(chan);
+}
+
+static struct iop_adma_desc_slot *
+iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots,
+			int slots_per_op)
+{
+	struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL;
+	struct list_head chain = LIST_HEAD_INIT(chain);
+	int slots_found, retry = 0;
+
+	/* start search from the last allocated descrtiptor
+	 * if a contiguous allocation can not be found start searching
+	 * from the beginning of the list
+	 */
+retry:
+	slots_found = 0;
+	if (retry == 0)
+		iter = iop_chan->last_used;
+	else
+		iter = list_entry(&iop_chan->all_slots,
+			struct iop_adma_desc_slot,
+			slot_node);
+
+	list_for_each_entry_safe_continue(
+		iter, _iter, &iop_chan->all_slots, slot_node) {
+		prefetch(_iter);
+		prefetch(&_iter->async_tx);
+		if (iter->slots_per_op) {
+			/* give up after finding the first busy slot
+			 * on the second pass through the list
+			 */
+			if (retry)
+				break;
+
+			slots_found = 0;
+			continue;
+		}
+
+		/* start the allocation if the slot is correctly aligned */
+		if (!slots_found++) {
+			if (iop_desc_is_aligned(iter, slots_per_op))
+				alloc_start = iter;
+			else {
+				slots_found = 0;
+				continue;
+			}
+		}
+
+		if (slots_found == num_slots) {
+			struct iop_adma_desc_slot *alloc_tail = NULL;
+			struct iop_adma_desc_slot *last_used = NULL;
+			iter = alloc_start;
+			while (num_slots) {
+				int i;
+				dev_dbg(iop_chan->device->common.dev,
+					"allocated slot: %d "
+					"(desc %p phys: %#x) slots_per_op %d\n",
+					iter->idx, iter->hw_desc,
+					iter->async_tx.phys, slots_per_op);
+
+				/* pre-ack all but the last descriptor */
+				if (num_slots != slots_per_op)
+					iter->async_tx.ack = 1;
+				else
+					iter->async_tx.ack = 0;
+
+				list_add_tail(&iter->chain_node, &chain);
+				alloc_tail = iter;
+				iter->async_tx.cookie = 0;
+				iter->slot_cnt = num_slots;
+				iter->xor_check_result = NULL;
+				for (i = 0; i < slots_per_op; i++) {
+					iter->slots_per_op = slots_per_op - i;
+					last_used = iter;
+					iter = list_entry(iter->slot_node.next,
+						struct iop_adma_desc_slot,
+						slot_node);
+				}
+				num_slots -= slots_per_op;
+			}
+			alloc_tail->group_head = alloc_start;
+			alloc_tail->async_tx.cookie = -EBUSY;
+			list_splice(&chain, &alloc_tail->async_tx.tx_list);
+			iop_chan->last_used = last_used;
+			iop_desc_clear_next_desc(alloc_start);
+			iop_desc_clear_next_desc(alloc_tail);
+			return alloc_tail;
+		}
+	}
+	if (!retry++)
+		goto retry;
+
+	/* try to free some slots if the allocation fails */
+	tasklet_schedule(&iop_chan->irq_tasklet);
+
+	return NULL;
+}
+
+static dma_cookie_t
+iop_desc_assign_cookie(struct iop_adma_chan *iop_chan,
+	struct iop_adma_desc_slot *desc)
+{
+	dma_cookie_t cookie = iop_chan->common.cookie;
+	cookie++;
+	if (cookie < 0)
+		cookie = 1;
+	iop_chan->common.cookie = desc->async_tx.cookie = cookie;
+	return cookie;
+}
+
+static void iop_adma_check_threshold(struct iop_adma_chan *iop_chan)
+{
+	dev_dbg(iop_chan->device->common.dev, "pending: %d\n",
+		iop_chan->pending);
+
+	if (iop_chan->pending >= IOP_ADMA_THRESHOLD) {
+		iop_chan->pending = 0;
+		iop_chan_append(iop_chan);
+	}
+}
+
+static dma_cookie_t
+iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
+	struct iop_adma_desc_slot *grp_start, *old_chain_tail;
+	int slot_cnt;
+	int slots_per_op;
+	dma_cookie_t cookie;
+
+	grp_start = sw_desc->group_head;
+	slot_cnt = grp_start->slot_cnt;
+	slots_per_op = grp_start->slots_per_op;
+
+	spin_lock_bh(&iop_chan->lock);
+	cookie = iop_desc_assign_cookie(iop_chan, sw_desc);
+
+	old_chain_tail = list_entry(iop_chan->chain.prev,
+		struct iop_adma_desc_slot, chain_node);
+	list_splice_init(&sw_desc->async_tx.tx_list,
+			 &old_chain_tail->chain_node);
+
+	/* fix up the hardware chain */
+	iop_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
+
+	/* 1/ don't add pre-chained descriptors
+	 * 2/ dummy read to flush next_desc write
+	 */
+	BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+	/* increment the pending count by the number of slots
+	 * memcpy operations have a 1:1 (slot:operation) relation
+	 * other operations are heavier and will pop the threshold
+	 * more often.
+	 */
+	iop_chan->pending += slot_cnt;
+	iop_adma_check_threshold(iop_chan);
+	spin_unlock_bh(&iop_chan->lock);
+
+	dev_dbg(iop_chan->device->common.dev, "%s cookie: %d slot: %d\n",
+		__FUNCTION__, sw_desc->async_tx.cookie, sw_desc->idx);
+
+	return cookie;
+}
+
+static void
+iop_adma_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+	int index)
+{
+	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
+
+	/* to do: support transfers lengths > IOP_ADMA_MAX_BYTE_COUNT */
+	iop_desc_set_dest_addr(sw_desc->group_head, iop_chan, addr);
+}
+
+static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
+static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
+
+/* returns the number of allocated descriptors */
+static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+{
+	char *hw_desc;
+	int idx;
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	struct iop_adma_desc_slot *slot = NULL;
+	int init = iop_chan->slots_allocated ? 0 : 1;
+	struct iop_adma_platform_data *plat_data =
+		iop_chan->device->pdev->dev.platform_data;
+	int num_descs_in_pool = plat_data->pool_size/IOP_ADMA_SLOT_SIZE;
+
+	/* Allocate descriptor slots */
+	do {
+		idx = iop_chan->slots_allocated;
+		if (idx == num_descs_in_pool)
+			break;
+
+		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+		if (!slot) {
+			printk(KERN_INFO "IOP ADMA Channel only initialized"
+				" %d descriptor slots", idx);
+			break;
+		}
+		hw_desc = (char *) iop_chan->device->dma_desc_pool_virt;
+		slot->hw_desc = (void *) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
+
+		dma_async_tx_descriptor_init(&slot->async_tx, chan);
+		slot->async_tx.tx_submit = iop_adma_tx_submit;
+		slot->async_tx.tx_set_dest = iop_adma_set_dest;
+		INIT_LIST_HEAD(&slot->chain_node);
+		INIT_LIST_HEAD(&slot->slot_node);
+		INIT_LIST_HEAD(&slot->async_tx.tx_list);
+		hw_desc = (char *) iop_chan->device->dma_desc_pool;
+		slot->async_tx.phys =
+			(dma_addr_t) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
+		slot->idx = idx;
+
+		spin_lock_bh(&iop_chan->lock);
+		iop_chan->slots_allocated++;
+		list_add_tail(&slot->slot_node, &iop_chan->all_slots);
+		spin_unlock_bh(&iop_chan->lock);
+	} while (iop_chan->slots_allocated < num_descs_in_pool);
+
+	if (idx && !iop_chan->last_used)
+		iop_chan->last_used = list_entry(iop_chan->all_slots.next,
+					struct iop_adma_desc_slot,
+					slot_node);
+
+	dev_dbg(iop_chan->device->common.dev,
+		"allocated %d descriptor slots last_used: %p\n",
+		iop_chan->slots_allocated, iop_chan->last_used);
+
+	/* initialize the channel and the chain with a null operation */
+	if (init) {
+		if (dma_has_cap(DMA_MEMCPY,
+			iop_chan->device->common.cap_mask))
+			iop_chan_start_null_memcpy(iop_chan);
+		else if (dma_has_cap(DMA_XOR,
+			iop_chan->device->common.cap_mask))
+			iop_chan_start_null_xor(iop_chan);
+		else
+			BUG();
+	}
+
+	return (idx > 0) ? idx : -ENOMEM;
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_interrupt(struct dma_chan *chan)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	struct iop_adma_desc_slot *sw_desc, *grp_start;
+	int slot_cnt, slots_per_op;
+
+	dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+	spin_lock_bh(&iop_chan->lock);
+	slot_cnt = iop_chan_interrupt_slot_count(&slots_per_op, iop_chan);
+	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+	if (sw_desc) {
+		grp_start = sw_desc->group_head;
+		iop_desc_init_interrupt(grp_start, iop_chan);
+		grp_start->unmap_len = 0;
+	}
+	spin_unlock_bh(&iop_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_memcpy_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+	int index)
+{
+	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+	struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+	iop_desc_set_memcpy_src_addr(grp_start, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	struct iop_adma_desc_slot *sw_desc, *grp_start;
+	int slot_cnt, slots_per_op;
+
+	if (unlikely(!len))
+		return NULL;
+	BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+
+	dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+		__FUNCTION__, len);
+
+	spin_lock_bh(&iop_chan->lock);
+	slot_cnt = iop_chan_memcpy_slot_count(len, &slots_per_op);
+	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+	if (sw_desc) {
+		grp_start = sw_desc->group_head;
+		iop_desc_init_memcpy(grp_start, int_en);
+		iop_desc_set_byte_count(grp_start, iop_chan, len);
+		sw_desc->unmap_src_cnt = 1;
+		sw_desc->unmap_len = len;
+		sw_desc->async_tx.tx_set_src = iop_adma_memcpy_set_src;
+	}
+	spin_unlock_bh(&iop_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len,
+	int int_en)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	struct iop_adma_desc_slot *sw_desc, *grp_start;
+	int slot_cnt, slots_per_op;
+
+	if (unlikely(!len))
+		return NULL;
+	BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+
+	dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+		__FUNCTION__, len);
+
+	spin_lock_bh(&iop_chan->lock);
+	slot_cnt = iop_chan_memset_slot_count(len, &slots_per_op);
+	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+	if (sw_desc) {
+		grp_start = sw_desc->group_head;
+		iop_desc_init_memset(grp_start, int_en);
+		iop_desc_set_byte_count(grp_start, iop_chan, len);
+		iop_desc_set_block_fill_val(grp_start, value);
+		sw_desc->unmap_src_cnt = 1;
+		sw_desc->unmap_len = len;
+	}
+	spin_unlock_bh(&iop_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_xor_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+	int index)
+{
+	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+	struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+	iop_desc_set_xor_src_addr(grp_start, index, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_xor(struct dma_chan *chan, unsigned int src_cnt, size_t len,
+	int int_en)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	struct iop_adma_desc_slot *sw_desc, *grp_start;
+	int slot_cnt, slots_per_op;
+
+	if (unlikely(!len))
+		return NULL;
+	BUG_ON(unlikely(len > IOP_ADMA_XOR_MAX_BYTE_COUNT));
+
+	dev_dbg(iop_chan->device->common.dev,
+		"%s src_cnt: %d len: %u int_en: %d\n",
+		__FUNCTION__, src_cnt, len, int_en);
+
+	spin_lock_bh(&iop_chan->lock);
+	slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op);
+	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+	if (sw_desc) {
+		grp_start = sw_desc->group_head;
+		iop_desc_init_xor(grp_start, src_cnt, int_en);
+		iop_desc_set_byte_count(grp_start, iop_chan, len);
+		sw_desc->unmap_src_cnt = src_cnt;
+		sw_desc->unmap_len = len;
+		sw_desc->async_tx.tx_set_src = iop_adma_xor_set_src;
+	}
+	spin_unlock_bh(&iop_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_xor_zero_sum_set_src(dma_addr_t addr,
+				struct dma_async_tx_descriptor *tx,
+				int index)
+{
+	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+	struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+	iop_desc_set_zero_sum_src_addr(grp_start, index, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_zero_sum(struct dma_chan *chan, unsigned int src_cnt,
+	size_t len, u32 *result, int int_en)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	struct iop_adma_desc_slot *sw_desc, *grp_start;
+	int slot_cnt, slots_per_op;
+
+	if (unlikely(!len))
+		return NULL;
+
+	dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+		__FUNCTION__, src_cnt, len);
+
+	spin_lock_bh(&iop_chan->lock);
+	slot_cnt = iop_chan_zero_sum_slot_count(len, src_cnt, &slots_per_op);
+	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+	if (sw_desc) {
+		grp_start = sw_desc->group_head;
+		iop_desc_init_zero_sum(grp_start, src_cnt, int_en);
+		iop_desc_set_zero_sum_byte_count(grp_start, len);
+		grp_start->xor_check_result = result;
+		pr_debug("\t%s: grp_start->xor_check_result: %p\n",
+			__FUNCTION__, grp_start->xor_check_result);
+		sw_desc->unmap_src_cnt = src_cnt;
+		sw_desc->unmap_len = len;
+		sw_desc->async_tx.tx_set_src = iop_adma_xor_zero_sum_set_src;
+	}
+	spin_unlock_bh(&iop_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void iop_adma_dependency_added(struct dma_chan *chan)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	tasklet_schedule(&iop_chan->irq_tasklet);
+}
+
+static void iop_adma_free_chan_resources(struct dma_chan *chan)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	struct iop_adma_desc_slot *iter, *_iter;
+	int in_use_descs = 0;
+
+	iop_adma_slot_cleanup(iop_chan);
+
+	spin_lock_bh(&iop_chan->lock);
+	list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
+					chain_node) {
+		in_use_descs++;
+		list_del(&iter->chain_node);
+	}
+	list_for_each_entry_safe_reverse(
+		iter, _iter, &iop_chan->all_slots, slot_node) {
+		list_del(&iter->slot_node);
+		kfree(iter);
+		iop_chan->slots_allocated--;
+	}
+	iop_chan->last_used = NULL;
+
+	dev_dbg(iop_chan->device->common.dev, "%s slots_allocated %d\n",
+		__FUNCTION__, iop_chan->slots_allocated);
+	spin_unlock_bh(&iop_chan->lock);
+
+	/* one is ok since we left it on there on purpose */
+	if (in_use_descs > 1)
+		printk(KERN_ERR "IOP: Freeing %d in use descriptors!\n",
+			in_use_descs - 1);
+}
+
+/**
+ * iop_adma_is_complete - poll the status of an ADMA transaction
+ * @chan: ADMA channel handle
+ * @cookie: ADMA transaction identifier
+ */
+static enum dma_status iop_adma_is_complete(struct dma_chan *chan,
+					dma_cookie_t cookie,
+					dma_cookie_t *done,
+					dma_cookie_t *used)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+	enum dma_status ret;
+
+	last_used = chan->cookie;
+	last_complete = iop_chan->completed_cookie;
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret == DMA_SUCCESS)
+		return ret;
+
+	iop_adma_slot_cleanup(iop_chan);
+
+	last_used = chan->cookie;
+	last_complete = iop_chan->completed_cookie;
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static irqreturn_t iop_adma_eot_handler(int irq, void *data)
+{
+	struct iop_adma_chan *chan = data;
+
+	dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
+
+	tasklet_schedule(&chan->irq_tasklet);
+
+	iop_adma_device_clear_eot_status(chan);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t iop_adma_eoc_handler(int irq, void *data)
+{
+	struct iop_adma_chan *chan = data;
+
+	dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
+
+	tasklet_schedule(&chan->irq_tasklet);
+
+	iop_adma_device_clear_eoc_status(chan);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t iop_adma_err_handler(int irq, void *data)
+{
+	struct iop_adma_chan *chan = data;
+	unsigned long status = iop_chan_get_status(chan);
+
+	dev_printk(KERN_ERR, chan->device->common.dev,
+		"error ( %s%s%s%s%s%s%s)\n",
+		iop_is_err_int_parity(status, chan) ? "int_parity " : "",
+		iop_is_err_mcu_abort(status, chan) ? "mcu_abort " : "",
+		iop_is_err_int_tabort(status, chan) ? "int_tabort " : "",
+		iop_is_err_int_mabort(status, chan) ? "int_mabort " : "",
+		iop_is_err_pci_tabort(status, chan) ? "pci_tabort " : "",
+		iop_is_err_pci_mabort(status, chan) ? "pci_mabort " : "",
+		iop_is_err_split_tx(status, chan) ? "split_tx " : "");
+
+	iop_adma_device_clear_err_status(chan);
+
+	BUG();
+
+	return IRQ_HANDLED;
+}
+
+static void iop_adma_issue_pending(struct dma_chan *chan)
+{
+	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+
+	if (iop_chan->pending) {
+		iop_chan->pending = 0;
+		iop_chan_append(iop_chan);
+	}
+}
+
+/*
+ * Perform a transaction to verify the HW works.
+ */
+#define IOP_ADMA_TEST_SIZE 2000
+
+static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+{
+	int i;
+	void *src, *dest;
+	dma_addr_t src_dma, dest_dma;
+	struct dma_chan *dma_chan;
+	dma_cookie_t cookie;
+	struct dma_async_tx_descriptor *tx;
+	int err = 0;
+	struct iop_adma_chan *iop_chan;
+
+	dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
+
+	src = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+	if (!src)
+		return -ENOMEM;
+	dest = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+	if (!dest) {
+		kfree(src);
+		return -ENOMEM;
+	}
+
+	/* Fill in src buffer */
+	for (i = 0; i < IOP_ADMA_TEST_SIZE; i++)
+		((u8 *) src)[i] = (u8)i;
+
+	memset(dest, 0, IOP_ADMA_TEST_SIZE);
+
+	/* Start copy, using first DMA channel */
+	dma_chan = container_of(device->common.channels.next,
+				struct dma_chan,
+				device_node);
+	if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	tx = iop_adma_prep_dma_memcpy(dma_chan, IOP_ADMA_TEST_SIZE, 1);
+	dest_dma = dma_map_single(dma_chan->device->dev, dest,
+				IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
+	iop_adma_set_dest(dest_dma, tx, 0);
+	src_dma = dma_map_single(dma_chan->device->dev, src,
+				IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
+	iop_adma_memcpy_set_src(src_dma, tx, 0);
+
+	cookie = iop_adma_tx_submit(tx);
+	iop_adma_issue_pending(dma_chan);
+	async_tx_ack(tx);
+	msleep(1);
+
+	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+			DMA_SUCCESS) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			"Self-test copy timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	iop_chan = to_iop_adma_chan(dma_chan);
+	dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
+		IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
+	if (memcmp(src, dest, IOP_ADMA_TEST_SIZE)) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			"Self-test copy failed compare, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+free_resources:
+	iop_adma_free_chan_resources(dma_chan);
+out:
+	kfree(src);
+	kfree(dest);
+	return err;
+}
+
+#define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
+static int __devinit
+iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+{
+	int i, src_idx;
+	struct page *dest;
+	struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST];
+	struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
+	dma_addr_t dma_addr, dest_dma;
+	struct dma_async_tx_descriptor *tx;
+	struct dma_chan *dma_chan;
+	dma_cookie_t cookie;
+	u8 cmp_byte = 0;
+	u32 cmp_word;
+	u32 zero_sum_result;
+	int err = 0;
+	struct iop_adma_chan *iop_chan;
+
+	dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
+
+	for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+		xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
+		if (!xor_srcs[src_idx])
+			while (src_idx--) {
+				__free_page(xor_srcs[src_idx]);
+				return -ENOMEM;
+			}
+	}
+
+	dest = alloc_page(GFP_KERNEL);
+	if (!dest)
+		while (src_idx--) {
+			__free_page(xor_srcs[src_idx]);
+			return -ENOMEM;
+		}
+
+	/* Fill in src buffers */
+	for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+		u8 *ptr = page_address(xor_srcs[src_idx]);
+		for (i = 0; i < PAGE_SIZE; i++)
+			ptr[i] = (1 << src_idx);
+	}
+
+	for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++)
+		cmp_byte ^= (u8) (1 << src_idx);
+
+	cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
+			(cmp_byte << 8) | cmp_byte;
+
+	memset(page_address(dest), 0, PAGE_SIZE);
+
+	dma_chan = container_of(device->common.channels.next,
+				struct dma_chan,
+				device_node);
+	if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	/* test xor */
+	tx = iop_adma_prep_dma_xor(dma_chan, IOP_ADMA_NUM_SRC_TEST,
+				PAGE_SIZE, 1);
+	dest_dma = dma_map_page(dma_chan->device->dev, dest, 0,
+				PAGE_SIZE, DMA_FROM_DEVICE);
+	iop_adma_set_dest(dest_dma, tx, 0);
+
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) {
+		dma_addr = dma_map_page(dma_chan->device->dev, xor_srcs[i], 0,
+			PAGE_SIZE, DMA_TO_DEVICE);
+		iop_adma_xor_set_src(dma_addr, tx, i);
+	}
+
+	cookie = iop_adma_tx_submit(tx);
+	iop_adma_issue_pending(dma_chan);
+	async_tx_ack(tx);
+	msleep(8);
+
+	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+		DMA_SUCCESS) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			"Self-test xor timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	iop_chan = to_iop_adma_chan(dma_chan);
+	dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
+		PAGE_SIZE, DMA_FROM_DEVICE);
+	for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
+		u32 *ptr = page_address(dest);
+		if (ptr[i] != cmp_word) {
+			dev_printk(KERN_ERR, dma_chan->device->dev,
+				"Self-test xor failed compare, disabling\n");
+			err = -ENODEV;
+			goto free_resources;
+		}
+	}
+	dma_sync_single_for_device(&iop_chan->device->pdev->dev, dest_dma,
+		PAGE_SIZE, DMA_TO_DEVICE);
+
+	/* skip zero sum if the capability is not present */
+	if (!dma_has_cap(DMA_ZERO_SUM, dma_chan->device->cap_mask))
+		goto free_resources;
+
+	/* zero sum the sources with the destintation page */
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
+		zero_sum_srcs[i] = xor_srcs[i];
+	zero_sum_srcs[i] = dest;
+
+	zero_sum_result = 1;
+
+	tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
+		PAGE_SIZE, &zero_sum_result, 1);
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
+		dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
+			0, PAGE_SIZE, DMA_TO_DEVICE);
+		iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
+	}
+
+	cookie = iop_adma_tx_submit(tx);
+	iop_adma_issue_pending(dma_chan);
+	async_tx_ack(tx);
+	msleep(8);
+
+	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			"Self-test zero sum timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	if (zero_sum_result != 0) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			"Self-test zero sum failed compare, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	/* test memset */
+	tx = iop_adma_prep_dma_memset(dma_chan, 0, PAGE_SIZE, 1);
+	dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
+			PAGE_SIZE, DMA_FROM_DEVICE);
+	iop_adma_set_dest(dma_addr, tx, 0);
+
+	cookie = iop_adma_tx_submit(tx);
+	iop_adma_issue_pending(dma_chan);
+	async_tx_ack(tx);
+	msleep(8);
+
+	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			"Self-test memset timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) {
+		u32 *ptr = page_address(dest);
+		if (ptr[i]) {
+			dev_printk(KERN_ERR, dma_chan->device->dev,
+				"Self-test memset failed compare, disabling\n");
+			err = -ENODEV;
+			goto free_resources;
+		}
+	}
+
+	/* test for non-zero parity sum */
+	zero_sum_result = 0;
+	tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
+		PAGE_SIZE, &zero_sum_result, 1);
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
+		dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
+			0, PAGE_SIZE, DMA_TO_DEVICE);
+		iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
+	}
+
+	cookie = iop_adma_tx_submit(tx);
+	iop_adma_issue_pending(dma_chan);
+	async_tx_ack(tx);
+	msleep(8);
+
+	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			"Self-test non-zero sum timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	if (zero_sum_result != 1) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			"Self-test non-zero sum failed compare, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+free_resources:
+	iop_adma_free_chan_resources(dma_chan);
+out:
+	src_idx = IOP_ADMA_NUM_SRC_TEST;
+	while (src_idx--)
+		__free_page(xor_srcs[src_idx]);
+	__free_page(dest);
+	return err;
+}
+
+static int __devexit iop_adma_remove(struct platform_device *dev)
+{
+	struct iop_adma_device *device = platform_get_drvdata(dev);
+	struct dma_chan *chan, *_chan;
+	struct iop_adma_chan *iop_chan;
+	int i;
+	struct iop_adma_platform_data *plat_data = dev->dev.platform_data;
+
+	dma_async_device_unregister(&device->common);
+
+	for (i = 0; i < 3; i++) {
+		unsigned int irq;
+		irq = platform_get_irq(dev, i);
+		free_irq(irq, device);
+	}
+
+	dma_free_coherent(&dev->dev, plat_data->pool_size,
+			device->dma_desc_pool_virt, device->dma_desc_pool);
+
+	do {
+		struct resource *res;
+		res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+		release_mem_region(res->start, res->end - res->start);
+	} while (0);
+
+	list_for_each_entry_safe(chan, _chan, &device->common.channels,
+				device_node) {
+		iop_chan = to_iop_adma_chan(chan);
+		list_del(&chan->device_node);
+		kfree(iop_chan);
+	}
+	kfree(device);
+
+	return 0;
+}
+
+static int __devinit iop_adma_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int ret = 0, i;
+	struct iop_adma_device *adev;
+	struct iop_adma_chan *iop_chan;
+	struct dma_device *dma_dev;
+	struct iop_adma_platform_data *plat_data = pdev->dev.platform_data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				res->end - res->start, pdev->name))
+		return -EBUSY;
+
+	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+	if (!adev)
+		return -ENOMEM;
+	dma_dev = &adev->common;
+
+	/* allocate coherent memory for hardware descriptors
+	 * note: writecombine gives slightly better performance, but
+	 * requires that we explicitly flush the writes
+	 */
+	if ((adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
+					plat_data->pool_size,
+					&adev->dma_desc_pool,
+					GFP_KERNEL)) == NULL) {
+		ret = -ENOMEM;
+		goto err_free_adev;
+	}
+
+	dev_dbg(&pdev->dev, "%s: allocted descriptor pool virt %p phys %p\n",
+		__FUNCTION__, adev->dma_desc_pool_virt,
+		(void *) adev->dma_desc_pool);
+
+	adev->id = plat_data->hw_id;
+
+	/* discover transaction capabilites from the platform data */
+	dma_dev->cap_mask = plat_data->cap_mask;
+
+	adev->pdev = pdev;
+	platform_set_drvdata(pdev, adev);
+
+	INIT_LIST_HEAD(&dma_dev->channels);
+
+	/* set base routines */
+	dma_dev->device_alloc_chan_resources = iop_adma_alloc_chan_resources;
+	dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
+	dma_dev->device_is_tx_complete = iop_adma_is_complete;
+	dma_dev->device_issue_pending = iop_adma_issue_pending;
+	dma_dev->device_dependency_added = iop_adma_dependency_added;
+	dma_dev->dev = &pdev->dev;
+
+	/* set prep routines based on capability */
+	if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
+		dma_dev->device_prep_dma_memcpy = iop_adma_prep_dma_memcpy;
+	if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
+		dma_dev->device_prep_dma_memset = iop_adma_prep_dma_memset;
+	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+		dma_dev->max_xor = iop_adma_get_max_xor();
+		dma_dev->device_prep_dma_xor = iop_adma_prep_dma_xor;
+	}
+	if (dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask))
+		dma_dev->device_prep_dma_zero_sum =
+			iop_adma_prep_dma_zero_sum;
+	if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask))
+		dma_dev->device_prep_dma_interrupt =
+			iop_adma_prep_dma_interrupt;
+
+	iop_chan = kzalloc(sizeof(*iop_chan), GFP_KERNEL);
+	if (!iop_chan) {
+		ret = -ENOMEM;
+		goto err_free_dma;
+	}
+	iop_chan->device = adev;
+
+	iop_chan->mmr_base = devm_ioremap(&pdev->dev, res->start,
+					res->end - res->start);
+	if (!iop_chan->mmr_base) {
+		ret = -ENOMEM;
+		goto err_free_iop_chan;
+	}
+	tasklet_init(&iop_chan->irq_tasklet, iop_adma_tasklet, (unsigned long)
+		iop_chan);
+
+	/* clear errors before enabling interrupts */
+	iop_adma_device_clear_err_status(iop_chan);
+
+	for (i = 0; i < 3; i++) {
+		irq_handler_t handler[] = { iop_adma_eot_handler,
+					iop_adma_eoc_handler,
+					iop_adma_err_handler };
+		int irq = platform_get_irq(pdev, i);
+		if (irq < 0) {
+			ret = -ENXIO;
+			goto err_free_iop_chan;
+		} else {
+			ret = devm_request_irq(&pdev->dev, irq,
+					handler[i], 0, pdev->name, iop_chan);
+			if (ret)
+				goto err_free_iop_chan;
+		}
+	}
+
+	spin_lock_init(&iop_chan->lock);
+	init_timer(&iop_chan->cleanup_watchdog);
+	iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
+	iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
+	INIT_LIST_HEAD(&iop_chan->chain);
+	INIT_LIST_HEAD(&iop_chan->all_slots);
+	INIT_RCU_HEAD(&iop_chan->common.rcu);
+	iop_chan->common.device = dma_dev;
+	list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
+
+	if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
+		ret = iop_adma_memcpy_self_test(adev);
+		dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
+		if (ret)
+			goto err_free_iop_chan;
+	}
+
+	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) ||
+		dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) {
+		ret = iop_adma_xor_zero_sum_self_test(adev);
+		dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
+		if (ret)
+			goto err_free_iop_chan;
+	}
+
+	dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: "
+	  "( %s%s%s%s%s%s%s%s%s%s)\n",
+	  dma_has_cap(DMA_PQ_XOR, dma_dev->cap_mask) ? "pq_xor " : "",
+	  dma_has_cap(DMA_PQ_UPDATE, dma_dev->cap_mask) ? "pq_update " : "",
+	  dma_has_cap(DMA_PQ_ZERO_SUM, dma_dev->cap_mask) ? "pq_zero_sum " : "",
+	  dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+	  dma_has_cap(DMA_DUAL_XOR, dma_dev->cap_mask) ? "dual_xor " : "",
+	  dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask) ? "xor_zero_sum " : "",
+	  dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
+	  dma_has_cap(DMA_MEMCPY_CRC32C, dma_dev->cap_mask) ? "cpy+crc " : "",
+	  dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+	  dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+
+	dma_async_device_register(dma_dev);
+	goto out;
+
+ err_free_iop_chan:
+	kfree(iop_chan);
+ err_free_dma:
+	dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
+			adev->dma_desc_pool_virt, adev->dma_desc_pool);
+ err_free_adev:
+	kfree(adev);
+ out:
+	return ret;
+}
+
+static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
+{
+	struct iop_adma_desc_slot *sw_desc, *grp_start;
+	dma_cookie_t cookie;
+	int slot_cnt, slots_per_op;
+
+	dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+	spin_lock_bh(&iop_chan->lock);
+	slot_cnt = iop_chan_memcpy_slot_count(0, &slots_per_op);
+	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+	if (sw_desc) {
+		grp_start = sw_desc->group_head;
+
+		list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+		sw_desc->async_tx.ack = 1;
+		iop_desc_init_memcpy(grp_start, 0);
+		iop_desc_set_byte_count(grp_start, iop_chan, 0);
+		iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+		iop_desc_set_memcpy_src_addr(grp_start, 0);
+
+		cookie = iop_chan->common.cookie;
+		cookie++;
+		if (cookie <= 1)
+			cookie = 2;
+
+		/* initialize the completed cookie to be less than
+		 * the most recently used cookie
+		 */
+		iop_chan->completed_cookie = cookie - 1;
+		iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+
+		/* channel should not be busy */
+		BUG_ON(iop_chan_is_busy(iop_chan));
+
+		/* clear any prior error-status bits */
+		iop_adma_device_clear_err_status(iop_chan);
+
+		/* disable operation */
+		iop_chan_disable(iop_chan);
+
+		/* set the descriptor address */
+		iop_chan_set_next_descriptor(iop_chan, sw_desc->async_tx.phys);
+
+		/* 1/ don't add pre-chained descriptors
+		 * 2/ dummy read to flush next_desc write
+		 */
+		BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+		/* run the descriptor */
+		iop_chan_enable(iop_chan);
+	} else
+		dev_printk(KERN_ERR, iop_chan->device->common.dev,
+			 "failed to allocate null descriptor\n");
+	spin_unlock_bh(&iop_chan->lock);
+}
+
+static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+{
+	struct iop_adma_desc_slot *sw_desc, *grp_start;
+	dma_cookie_t cookie;
+	int slot_cnt, slots_per_op;
+
+	dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+	spin_lock_bh(&iop_chan->lock);
+	slot_cnt = iop_chan_xor_slot_count(0, 2, &slots_per_op);
+	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+	if (sw_desc) {
+		grp_start = sw_desc->group_head;
+		list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+		sw_desc->async_tx.ack = 1;
+		iop_desc_init_null_xor(grp_start, 2, 0);
+		iop_desc_set_byte_count(grp_start, iop_chan, 0);
+		iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+		iop_desc_set_xor_src_addr(grp_start, 0, 0);
+		iop_desc_set_xor_src_addr(grp_start, 1, 0);
+
+		cookie = iop_chan->common.cookie;
+		cookie++;
+		if (cookie <= 1)
+			cookie = 2;
+
+		/* initialize the completed cookie to be less than
+		 * the most recently used cookie
+		 */
+		iop_chan->completed_cookie = cookie - 1;
+		iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+
+		/* channel should not be busy */
+		BUG_ON(iop_chan_is_busy(iop_chan));
+
+		/* clear any prior error-status bits */
+		iop_adma_device_clear_err_status(iop_chan);
+
+		/* disable operation */
+		iop_chan_disable(iop_chan);
+
+		/* set the descriptor address */
+		iop_chan_set_next_descriptor(iop_chan, sw_desc->async_tx.phys);
+
+		/* 1/ don't add pre-chained descriptors
+		 * 2/ dummy read to flush next_desc write
+		 */
+		BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+		/* run the descriptor */
+		iop_chan_enable(iop_chan);
+	} else
+		dev_printk(KERN_ERR, iop_chan->device->common.dev,
+			"failed to allocate null descriptor\n");
+	spin_unlock_bh(&iop_chan->lock);
+}
+
+static struct platform_driver iop_adma_driver = {
+	.probe		= iop_adma_probe,
+	.remove		= iop_adma_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "iop-adma",
+	},
+};
+
+static int __init iop_adma_init (void)
+{
+	/* it's currently unsafe to unload this module */
+	/* if forced, worst case is that rmmod hangs */
+	__unsafe(THIS_MODULE);
+
+	return platform_driver_register(&iop_adma_driver);
+}
+
+static void __exit iop_adma_exit (void)
+{
+	platform_driver_unregister(&iop_adma_driver);
+	return;
+}
+
+module_init(iop_adma_init);
+module_exit(iop_adma_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("IOP ADMA Engine Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 807c402..debf1d8 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -6,11 +6,9 @@
 # $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
 #
 
-menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)'
+menuconfig EDAC
+	tristate "EDAC - error detection and reporting (EXPERIMENTAL)"
 	depends on HAS_IOMEM
-
-config EDAC
-	tristate "EDAC core system error reporting (EXPERIMENTAL)"
 	depends on X86 && EXPERIMENTAL
 	help
 	  EDAC is designed to report errors in the core system.
@@ -30,13 +28,12 @@
 	  There is also a mailing list for the EDAC project, which can
 	  be found via the sourceforge page.
 
+if EDAC
 
 comment "Reporting subsystems"
-	depends on EDAC
 
 config EDAC_DEBUG
 	bool "Debugging"
-	depends on EDAC
 	help
 	  This turns on debugging information for the entire EDAC
 	  sub-system. You can insert module with "debug_level=x", current
@@ -45,7 +42,6 @@
 
 config EDAC_MM_EDAC
 	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
-	depends on EDAC
 	default y
 	help
 	  Some systems are able to detect and correct errors in main
@@ -100,15 +96,13 @@
 
 choice
 	prompt "Error detecting method"
-	depends on EDAC
 	default EDAC_POLL
 
 config EDAC_POLL
 	bool "Poll for errors"
-	depends on EDAC
 	help
 	  Poll the chipset periodically to detect errors.
 
 endchoice
 
-endmenu
+endif # EDAC
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 7b62230..804875d 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1906,6 +1906,7 @@
 
 static int edac_kernel_thread(void *arg)
 {
+	set_freezable();
 	while (!kthread_should_stop()) {
 		do_edac_check();
 
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index 5932c72..d011a76 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -4,27 +4,44 @@
 	depends on EXPERIMENTAL=n
 
 config FIREWIRE
-	tristate "IEEE 1394 (FireWire) support (JUJU alternative stack, experimental)"
+	tristate "IEEE 1394 (FireWire) support - alternative stack, EXPERIMENTAL"
 	depends on EXPERIMENTAL
 	select CRC_ITU_T
 	help
-	  IEEE 1394 describes a high performance serial bus, which is also
-	  known as FireWire(tm) or i.Link(tm) and is used for connecting all
-	  sorts of devices (most notably digital video cameras) to your
-	  computer.
-
-	  If you have FireWire hardware and want to use it, say Y here.  This
-	  is the core support only, you will also need to select a driver for
-	  your IEEE 1394 adapter.
-
-	  To compile this driver as a module, say M here: the module will be
-	  called fw-core.
-
-	  This is the "JUJU" FireWire stack, an alternative implementation
+	  This is the "Juju" FireWire stack, a new alternative implementation
 	  designed for robustness and simplicity.  You can build either this
 	  stack, or the classic stack (the ieee1394 driver, ohci1394 etc.)
 	  or both.
 
+	  To compile this driver as a module, say M here: the module will be
+	  called firewire-core.  It functionally replaces ieee1394, raw1394,
+	  and video1394.
+
+          NOTE:
+
+	  You should only build ONE of the stacks, unless you REALLY know what
+	  you are doing.  If you install both, you should configure them only as
+	  modules rather than link them statically, and you should blacklist one
+	  of the concurrent low-level drivers in /etc/modprobe.conf.  Add either
+
+	      blacklist firewire-ohci
+	  or
+	      blacklist ohci1394
+
+	  there depending on which driver you DON'T want to have auto-loaded.
+	  You can optionally do the same with the other IEEE 1394/ FireWire
+	  drivers.
+
+	  If you have an old modprobe which doesn't implement the blacklist
+	  directive, use either
+
+	       install firewire-ohci /bin/true
+	  or
+	       install ohci1394 /bin/true
+
+	  and so on, depending on which modules you DON't want to have
+	  auto-loaded.
+
 config FIREWIRE_OHCI
 	tristate "Support for OHCI FireWire host controllers"
 	depends on PCI && FIREWIRE
@@ -34,11 +51,13 @@
 	  is the only chipset in use, so say Y here.
 
 	  To compile this driver as a module, say M here:  The module will be
-	  called fw-ohci.
+	  called firewire-ohci.  It replaces ohci1394 of the classic IEEE 1394
+	  stack.
 
-	  If you also build ohci1394 of the classic IEEE 1394 driver stack,
-	  blacklist either ohci1394 or fw-ohci to let hotplug load the desired
-	  driver.
+          NOTE:
+
+	  If you also build ohci1394 of the classic stack, blacklist either
+	  ohci1394 or firewire-ohci to let hotplug load only the desired driver.
 
 config FIREWIRE_SBP2
 	tristate "Support for storage devices (SBP-2 protocol driver)"
@@ -50,12 +69,14 @@
 	  like scanners.
 
 	  To compile this driver as a module, say M here:  The module will be
-	  called fw-sbp2.
+	  called firewire-sbp2.  It replaces sbp2 of the classic IEEE 1394
+	  stack.
 
 	  You should also enable support for disks, CD-ROMs, etc. in the SCSI
 	  configuration section.
 
-	  If you also build sbp2 of the classic IEEE 1394 driver stack,
-	  blacklist either sbp2 or fw-sbp2 to let hotplug load the desired
-	  driver.
+          NOTE:
+
+	  If you also build sbp2 of the classic stack, blacklist either sbp2
+	  or firewire-sbp2 to let hotplug load only the desired driver.
 
diff --git a/drivers/firewire/Makefile b/drivers/firewire/Makefile
index fc7d59d..a7c31e9 100644
--- a/drivers/firewire/Makefile
+++ b/drivers/firewire/Makefile
@@ -2,9 +2,11 @@
 # Makefile for the Linux IEEE 1394 implementation
 #
 
-fw-core-y += fw-card.o fw-topology.o fw-transaction.o fw-iso.o \
-	fw-device.o fw-cdev.o
+firewire-core-y += fw-card.o fw-topology.o fw-transaction.o fw-iso.o \
+                   fw-device.o fw-cdev.o
+firewire-ohci-y += fw-ohci.o
+firewire-sbp2-y += fw-sbp2.o
 
-obj-$(CONFIG_FIREWIRE) += fw-core.o
-obj-$(CONFIG_FIREWIRE_OHCI) += fw-ohci.o
-obj-$(CONFIG_FIREWIRE_SBP2) += fw-sbp2.o
+obj-$(CONFIG_FIREWIRE) += firewire-core.o
+obj-$(CONFIG_FIREWIRE_OHCI) += firewire-ohci.o
+obj-$(CONFIG_FIREWIRE_SBP2) += firewire-sbp2.o
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 636151a..0aeab32 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -336,8 +336,11 @@
 	}
 
  pick_me:
-	/* Now figure out what gap count to set. */
-	if (card->topology_type == FW_TOPOLOGY_A &&
+	/*
+	 * Pick a gap count from 1394a table E-1.  The table doesn't cover
+	 * the typically much larger 1394b beta repeater delays though.
+	 */
+	if (!card->beta_repeaters_present &&
 	    card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
 		gap_count = gap_count_table[card->root_node->max_hops];
 	else
@@ -407,11 +410,6 @@
 	card->link_speed = link_speed;
 	card->guid = guid;
 
-	/* Activate link_on bit and contender bit in our self ID packets.*/
-	if (card->driver->update_phy_reg(card, 4, 0,
-					 PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
-		return -EIO;
-
 	/*
 	 * The subsystem grabs a reference when the card is added and
 	 * drops it when the driver calls fw_core_remove_card.
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index 0fa5bd5..7538864 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -365,7 +365,7 @@
 		    response->response.data, response->response.length);
 }
 
-static ssize_t ioctl_send_request(struct client *client, void *buffer)
+static int ioctl_send_request(struct client *client, void *buffer)
 {
 	struct fw_device *device = client->device;
 	struct fw_cdev_send_request *request = buffer;
@@ -397,7 +397,7 @@
 			request->tcode & 0x1f,
 			device->node->node_id,
 			request->generation,
-			device->node->max_speed,
+			device->max_speed,
 			request->offset,
 			response->response.data, request->length,
 			complete_transaction, response);
@@ -640,6 +640,7 @@
 static int ioctl_create_iso_context(struct client *client, void *buffer)
 {
 	struct fw_cdev_create_iso_context *request = buffer;
+	struct fw_iso_context *context;
 
 	if (request->channel > 63)
 		return -EINVAL;
@@ -661,15 +662,17 @@
 		return -EINVAL;
 	}
 
+	context =  fw_iso_context_create(client->device->card,
+					 request->type,
+					 request->channel,
+					 request->speed,
+					 request->header_size,
+					 iso_callback, client);
+	if (IS_ERR(context))
+		return PTR_ERR(context);
+
 	client->iso_closure = request->closure;
-	client->iso_context = fw_iso_context_create(client->device->card,
-						    request->type,
-						    request->channel,
-						    request->speed,
-						    request->header_size,
-						    iso_callback, client);
-	if (IS_ERR(client->iso_context))
-		return PTR_ERR(client->iso_context);
+	client->iso_context = context;
 
 	/* We only support one context at this time. */
 	request->handle = 0;
@@ -677,12 +680,21 @@
 	return 0;
 }
 
+/* Macros for decoding the iso packet control header. */
+#define GET_PAYLOAD_LENGTH(v)	((v) & 0xffff)
+#define GET_INTERRUPT(v)	(((v) >> 16) & 0x01)
+#define GET_SKIP(v)		(((v) >> 17) & 0x01)
+#define GET_TAG(v)		(((v) >> 18) & 0x02)
+#define GET_SY(v)		(((v) >> 20) & 0x04)
+#define GET_HEADER_LENGTH(v)	(((v) >> 24) & 0xff)
+
 static int ioctl_queue_iso(struct client *client, void *buffer)
 {
 	struct fw_cdev_queue_iso *request = buffer;
 	struct fw_cdev_iso_packet __user *p, *end, *next;
 	struct fw_iso_context *ctx = client->iso_context;
 	unsigned long payload, buffer_end, header_length;
+	u32 control;
 	int count;
 	struct {
 		struct fw_iso_packet packet;
@@ -717,8 +729,14 @@
 	end = (void __user *)p + request->size;
 	count = 0;
 	while (p < end) {
-		if (__copy_from_user(&u.packet, p, sizeof(*p)))
+		if (get_user(control, &p->control))
 			return -EFAULT;
+		u.packet.payload_length = GET_PAYLOAD_LENGTH(control);
+		u.packet.interrupt = GET_INTERRUPT(control);
+		u.packet.skip = GET_SKIP(control);
+		u.packet.tag = GET_TAG(control);
+		u.packet.sy = GET_SY(control);
+		u.packet.header_length = GET_HEADER_LENGTH(control);
 
 		if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {
 			header_length = u.packet.header_length;
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index c1ce465..2b65863 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -401,8 +401,7 @@
 
 	offset = 0xfffff0000400ULL + index * 4;
 	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
-			device->node_id,
-			device->generation, SCODE_100,
+			device->node_id, device->generation, device->max_speed,
 			offset, NULL, 4, complete_transaction, &callback_data);
 
 	wait_for_completion(&callback_data.done);
@@ -418,6 +417,8 @@
 	u32 stack[16], sp, key;
 	int i, end, length;
 
+	device->max_speed = SCODE_100;
+
 	/* First read the bus info block. */
 	for (i = 0; i < 5; i++) {
 		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
@@ -434,6 +435,33 @@
 			return -1;
 	}
 
+	device->max_speed = device->node->max_speed;
+
+	/*
+	 * Determine the speed of
+	 *   - devices with link speed less than PHY speed,
+	 *   - devices with 1394b PHY (unless only connected to 1394a PHYs),
+	 *   - all devices if there are 1394b repeaters.
+	 * Note, we cannot use the bus info block's link_spd as starting point
+	 * because some buggy firmwares set it lower than necessary and because
+	 * 1394-1995 nodes do not have the field.
+	 */
+	if ((rom[2] & 0x7) < device->max_speed ||
+	    device->max_speed == SCODE_BETA ||
+	    device->card->beta_repeaters_present) {
+		u32 dummy;
+
+		/* for S1600 and S3200 */
+		if (device->max_speed == SCODE_BETA)
+			device->max_speed = device->card->link_speed;
+
+		while (device->max_speed > SCODE_100) {
+			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
+				break;
+			device->max_speed--;
+		}
+	}
+
 	/*
 	 * Now parse the config rom.  The config rom is a recursive
 	 * directory structure so we parse it using a stack of
@@ -680,8 +708,10 @@
 		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
 		fw_device_shutdown(&device->work.work);
 	else
-		fw_notify("created new fw device %s (%d config rom retries)\n",
-			  device->device.bus_id, device->config_rom_retries);
+		fw_notify("created new fw device %s "
+			  "(%d config rom retries, S%d00)\n",
+			  device->device.bus_id, device->config_rom_retries,
+			  1 << device->max_speed);
 
 	/*
 	 * Reschedule the IRM work if we just finished reading the
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index 0ba9d64..d13e6a6 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -40,6 +40,7 @@
 	struct fw_node *node;
 	int node_id;
 	int generation;
+	unsigned max_speed;
 	struct fw_card *card;
 	struct device device;
 	struct list_head link;
@@ -99,6 +100,7 @@
 #define CSR_DEPENDENT_INFO	0x14
 #define CSR_MODEL		0x17
 #define CSR_INSTANCE		0x18
+#define CSR_DIRECTORY_ID	0x20
 
 #define SBP2_COMMAND_SET_SPECIFIER	0x38
 #define SBP2_COMMAND_SET		0x39
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index c17342d..41476ab 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -268,7 +268,7 @@
 
 	dma_sync_single_for_device(dev, ab_bus, PAGE_SIZE, DMA_BIDIRECTIONAL);
 
-	ctx->last_buffer->descriptor.branch_address = ab_bus | 1;
+	ctx->last_buffer->descriptor.branch_address = cpu_to_le32(ab_bus | 1);
 	ctx->last_buffer->next = ab;
 	ctx->last_buffer = ab;
 
@@ -373,8 +373,8 @@
 
 		offset = offsetof(struct ar_buffer, data);
 		dma_unmap_single(ohci->card.device,
-				 ab->descriptor.data_address - offset,
-				 PAGE_SIZE, DMA_BIDIRECTIONAL);
+			le32_to_cpu(ab->descriptor.data_address) - offset,
+			PAGE_SIZE, DMA_BIDIRECTIONAL);
 
 		buffer = ab;
 		ab = ab->next;
@@ -417,11 +417,21 @@
 	ctx->current_buffer = ab.next;
 	ctx->pointer = ctx->current_buffer->data;
 
-	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab.descriptor.branch_address);
+	return 0;
+}
+
+static void ar_context_run(struct ar_context *ctx)
+{
+	struct ar_buffer *ab = ctx->current_buffer;
+	dma_addr_t ab_bus;
+	size_t offset;
+
+	offset = offsetof(struct ar_buffer, data);
+	ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+
+	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab_bus | 1);
 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
 	flush_writes(ctx->ohci);
-
-	return 0;
 }
 
 static void context_tasklet(unsigned long data)
@@ -991,7 +1001,7 @@
 
 	event = reg_read(ohci, OHCI1394_IntEventClear);
 
-	if (!event)
+	if (!event || !~event)
 		return IRQ_NONE;
 
 	reg_write(ohci, OHCI1394_IntEventClear, event);
@@ -1038,11 +1048,78 @@
 	return IRQ_HANDLED;
 }
 
+static int software_reset(struct fw_ohci *ohci)
+{
+	int i;
+
+	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
+
+	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
+		if ((reg_read(ohci, OHCI1394_HCControlSet) &
+		     OHCI1394_HCControl_softReset) == 0)
+			return 0;
+		msleep(1);
+	}
+
+	return -EBUSY;
+}
+
 static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
 {
 	struct fw_ohci *ohci = fw_ohci(card);
 	struct pci_dev *dev = to_pci_dev(card->device);
 
+	if (software_reset(ohci)) {
+		fw_error("Failed to reset ohci card.\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * Now enable LPS, which we need in order to start accessing
+	 * most of the registers.  In fact, on some cards (ALI M5251),
+	 * accessing registers in the SClk domain without LPS enabled
+	 * will lock up the machine.  Wait 50msec to make sure we have
+	 * full link enabled.
+	 */
+	reg_write(ohci, OHCI1394_HCControlSet,
+		  OHCI1394_HCControl_LPS |
+		  OHCI1394_HCControl_postedWriteEnable);
+	flush_writes(ohci);
+	msleep(50);
+
+	reg_write(ohci, OHCI1394_HCControlClear,
+		  OHCI1394_HCControl_noByteSwapData);
+
+	reg_write(ohci, OHCI1394_LinkControlSet,
+		  OHCI1394_LinkControl_rcvSelfID |
+		  OHCI1394_LinkControl_cycleTimerEnable |
+		  OHCI1394_LinkControl_cycleMaster);
+
+	reg_write(ohci, OHCI1394_ATRetries,
+		  OHCI1394_MAX_AT_REQ_RETRIES |
+		  (OHCI1394_MAX_AT_RESP_RETRIES << 4) |
+		  (OHCI1394_MAX_PHYS_RESP_RETRIES << 8));
+
+	ar_context_run(&ohci->ar_request_ctx);
+	ar_context_run(&ohci->ar_response_ctx);
+
+	reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
+	reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
+	reg_write(ohci, OHCI1394_IntEventClear, ~0);
+	reg_write(ohci, OHCI1394_IntMaskClear, ~0);
+	reg_write(ohci, OHCI1394_IntMaskSet,
+		  OHCI1394_selfIDComplete |
+		  OHCI1394_RQPkt | OHCI1394_RSPkt |
+		  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
+		  OHCI1394_isochRx | OHCI1394_isochTx |
+		  OHCI1394_masterIntEnable |
+		  OHCI1394_cycle64Seconds);
+
+	/* Activate link_on bit and contender bit in our self ID packets.*/
+	if (ohci_update_phy_reg(card, 4, 0,
+				PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
+		return -EIO;
+
 	/*
 	 * When the link is not yet enabled, the atomic config rom
 	 * update mechanism described below in ohci_set_config_rom()
@@ -1700,22 +1777,6 @@
 	.stop_iso		= ohci_stop_iso,
 };
 
-static int software_reset(struct fw_ohci *ohci)
-{
-	int i;
-
-	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
-
-	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-		if ((reg_read(ohci, OHCI1394_HCControlSet) &
-		     OHCI1394_HCControl_softReset) == 0)
-			return 0;
-		msleep(1);
-	}
-
-	return -EBUSY;
-}
-
 static int __devinit
 pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
@@ -1761,33 +1822,6 @@
 		goto fail_iomem;
 	}
 
-	if (software_reset(ohci)) {
-		fw_error("Failed to reset ohci card.\n");
-		err = -EBUSY;
-		goto fail_registers;
-	}
-
-	/*
-	 * Now enable LPS, which we need in order to start accessing
-	 * most of the registers.  In fact, on some cards (ALI M5251),
-	 * accessing registers in the SClk domain without LPS enabled
-	 * will lock up the machine.  Wait 50msec to make sure we have
-	 * full link enabled.
-	 */
-	reg_write(ohci, OHCI1394_HCControlSet,
-		  OHCI1394_HCControl_LPS |
-		  OHCI1394_HCControl_postedWriteEnable);
-	flush_writes(ohci);
-	msleep(50);
-
-	reg_write(ohci, OHCI1394_HCControlClear,
-		  OHCI1394_HCControl_noByteSwapData);
-
-	reg_write(ohci, OHCI1394_LinkControlSet,
-		  OHCI1394_LinkControl_rcvSelfID |
-		  OHCI1394_LinkControl_cycleTimerEnable |
-		  OHCI1394_LinkControl_cycleMaster);
-
 	ar_context_init(&ohci->ar_request_ctx, ohci,
 			OHCI1394_AsReqRcvContextControlSet);
 
@@ -1800,11 +1834,6 @@
 	context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE,
 		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
 
-	reg_write(ohci, OHCI1394_ATRetries,
-		  OHCI1394_MAX_AT_REQ_RETRIES |
-		  (OHCI1394_MAX_AT_RESP_RETRIES << 4) |
-		  (OHCI1394_MAX_PHYS_RESP_RETRIES << 8));
-
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
 	ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
@@ -1834,18 +1863,6 @@
 		goto fail_registers;
 	}
 
-	reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
-	reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
-	reg_write(ohci, OHCI1394_IntEventClear, ~0);
-	reg_write(ohci, OHCI1394_IntMaskClear, ~0);
-	reg_write(ohci, OHCI1394_IntMaskSet,
-		  OHCI1394_selfIDComplete |
-		  OHCI1394_RQPkt | OHCI1394_RSPkt |
-		  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
-		  OHCI1394_isochRx | OHCI1394_isochTx |
-		  OHCI1394_masterIntEnable |
-		  OHCI1394_cycle64Seconds);
-
 	bus_options = reg_read(ohci, OHCI1394_BusOptions);
 	max_receive = (bus_options >> 12) & 0xf;
 	link_speed = bus_options & 0x7;
@@ -1907,6 +1924,45 @@
 	fw_notify("Removed fw-ohci device.\n");
 }
 
+#ifdef CONFIG_PM
+static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct fw_ohci *ohci = pci_get_drvdata(pdev);
+	int err;
+
+	software_reset(ohci);
+	free_irq(pdev->irq, ohci);
+	err = pci_save_state(pdev);
+	if (err) {
+		fw_error("pci_save_state failed\n");
+		return err;
+	}
+	err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	if (err) {
+		fw_error("pci_set_power_state failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int pci_resume(struct pci_dev *pdev)
+{
+	struct fw_ohci *ohci = pci_get_drvdata(pdev);
+	int err;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	err = pci_enable_device(pdev);
+	if (err) {
+		fw_error("pci_enable_device failed\n");
+		return err;
+	}
+
+	return ohci_enable(&ohci->card, ohci->config_rom, CONFIG_ROM_SIZE);
+}
+#endif
+
 static struct pci_device_id pci_table[] = {
 	{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) },
 	{ }
@@ -1919,6 +1975,10 @@
 	.id_table	= pci_table,
 	.probe		= pci_probe,
 	.remove		= pci_remove,
+#ifdef CONFIG_PM
+	.resume		= pci_resume,
+	.suspend	= pci_suspend,
+#endif
 };
 
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 6830041..7c53be0 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -30,10 +30,13 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/mod_devicetable.h>
 #include <linux/device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
+#include <linux/string.h>
 #include <linux/timer.h>
 
 #include <scsi/scsi.h>
@@ -46,6 +49,18 @@
 #include "fw-topology.h"
 #include "fw-device.h"
 
+/*
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
+ *
+ * Concurrent logins are useful together with cluster filesystems.
+ */
+static int sbp2_param_exclusive_login = 1;
+module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
+MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
+		 "(default = Y, use N for concurrent initiators)");
+
 /* I don't know why the SCSI stack doesn't define something like this... */
 typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
 
@@ -154,7 +169,7 @@
 #define MANAGEMENT_ORB_LUN(v)			((v))
 #define MANAGEMENT_ORB_FUNCTION(v)		((v) << 16)
 #define MANAGEMENT_ORB_RECONNECT(v)		((v) << 20)
-#define MANAGEMENT_ORB_EXCLUSIVE		((1) << 28)
+#define MANAGEMENT_ORB_EXCLUSIVE(v)		((v) ? 1 << 28 : 0)
 #define MANAGEMENT_ORB_REQUEST_FORMAT(v)	((v) << 29)
 #define MANAGEMENT_ORB_NOTIFY			((1) << 31)
 
@@ -205,9 +220,8 @@
 	scsi_done_fn_t done;
 	struct fw_unit *unit;
 
-	struct sbp2_pointer page_table[SG_ALL];
+	struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
 	dma_addr_t page_table_bus;
-	dma_addr_t request_buffer_bus;
 };
 
 /*
@@ -347,8 +361,7 @@
 	spin_unlock_irqrestore(&device->card->lock, flags);
 
 	fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
-			node_id, generation,
-			device->node->max_speed, offset,
+			node_id, generation, device->max_speed, offset,
 			&orb->pointer, sizeof(orb->pointer),
 			complete_transaction, orb);
 }
@@ -383,7 +396,7 @@
 complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 {
 	struct sbp2_management_orb *orb =
-	    (struct sbp2_management_orb *)base_orb;
+		container_of(base_orb, struct sbp2_management_orb, base);
 
 	if (status)
 		memcpy(&orb->status, status, sizeof(*status));
@@ -403,21 +416,11 @@
 	if (orb == NULL)
 		return -ENOMEM;
 
-	/*
-	 * The sbp2 device is going to send a block read request to
-	 * read out the request from host memory, so map it for dma.
-	 */
-	orb->base.request_bus =
-		dma_map_single(device->card->device, &orb->request,
-			       sizeof(orb->request), DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->base.request_bus))
-		goto out;
-
 	orb->response_bus =
 		dma_map_single(device->card->device, &orb->response,
 			       sizeof(orb->response), DMA_FROM_DEVICE);
 	if (dma_mapping_error(orb->response_bus))
-		goto out;
+		goto fail_mapping_response;
 
 	orb->request.response.high    = 0;
 	orb->request.response.low     = orb->response_bus;
@@ -432,14 +435,9 @@
 	orb->request.status_fifo.high = sd->address_handler.offset >> 32;
 	orb->request.status_fifo.low  = sd->address_handler.offset;
 
-	/*
-	 * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive
-	 * login and 1 second reconnect time.  The reconnect setting
-	 * is probably fine, but the exclusive login should be an option.
-	 */
 	if (function == SBP2_LOGIN_REQUEST) {
 		orb->request.misc |=
-			MANAGEMENT_ORB_EXCLUSIVE |
+			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
 			MANAGEMENT_ORB_RECONNECT(0);
 	}
 
@@ -448,6 +446,12 @@
 	init_completion(&orb->done);
 	orb->base.callback = complete_management_orb;
 
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->base.request_bus))
+		goto fail_mapping_request;
+
 	sbp2_send_orb(&orb->base, unit,
 		      node_id, generation, sd->management_agent_address);
 
@@ -479,9 +483,10 @@
  out:
 	dma_unmap_single(device->card->device, orb->base.request_bus,
 			 sizeof(orb->request), DMA_TO_DEVICE);
+ fail_mapping_request:
 	dma_unmap_single(device->card->device, orb->response_bus,
 			 sizeof(orb->response), DMA_FROM_DEVICE);
-
+ fail_mapping_response:
 	if (response)
 		fw_memcpy_from_be32(response,
 				    orb->response, sizeof(orb->response));
@@ -511,7 +516,7 @@
 		return -ENOMEM;
 
 	fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
-			sd->node_id, sd->generation, SCODE_400,
+			sd->node_id, sd->generation, device->max_speed,
 			sd->command_block_agent_address + SBP2_AGENT_RESET,
 			&zero, sizeof(zero), complete_agent_reset_write, t);
 
@@ -521,17 +526,15 @@
 static void sbp2_reconnect(struct work_struct *work);
 static struct scsi_host_template scsi_driver_template;
 
-static void
-release_sbp2_device(struct kref *kref)
+static void release_sbp2_device(struct kref *kref)
 {
 	struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
 	struct Scsi_Host *host =
 		container_of((void *)sd, struct Scsi_Host, hostdata[0]);
 
+	scsi_remove_host(host);
 	sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
 				 SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
-
-	scsi_remove_host(host);
 	fw_core_remove_address_handler(&sd->address_handler);
 	fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
 	put_device(&sd->unit->device);
@@ -833,7 +836,8 @@
 static void
 complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 {
-	struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb;
+	struct sbp2_command_orb *orb =
+		container_of(base_orb, struct sbp2_command_orb, base);
 	struct fw_unit *unit = orb->unit;
 	struct fw_device *device = fw_device(unit->device.parent);
 	struct scatterlist *sg;
@@ -880,12 +884,7 @@
 
 	if (orb->page_table_bus != 0)
 		dma_unmap_single(device->card->device, orb->page_table_bus,
-				 sizeof(orb->page_table_bus), DMA_TO_DEVICE);
-
-	if (orb->request_buffer_bus != 0)
-		dma_unmap_single(device->card->device, orb->request_buffer_bus,
-				 sizeof(orb->request_buffer_bus),
-				 DMA_FROM_DEVICE);
+				 sizeof(orb->page_table), DMA_TO_DEVICE);
 
 	orb->cmd->result = result;
 	orb->done(orb->cmd);
@@ -900,7 +899,6 @@
 	struct fw_device *device = fw_device(unit->device.parent);
 	struct scatterlist *sg;
 	int sg_len, l, i, j, count;
-	size_t size;
 	dma_addr_t sg_addr;
 
 	sg = (struct scatterlist *)orb->cmd->request_buffer;
@@ -935,6 +933,11 @@
 		sg_len = sg_dma_len(sg + i);
 		sg_addr = sg_dma_address(sg + i);
 		while (sg_len) {
+			/* FIXME: This won't get us out of the pinch. */
+			if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
+				fw_error("page table overflow\n");
+				goto fail_page_table;
+			}
 			l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
 			orb->page_table[j].low = sg_addr;
 			orb->page_table[j].high = (l << 16);
@@ -944,7 +947,13 @@
 		}
 	}
 
-	size = sizeof(orb->page_table[0]) * j;
+	fw_memcpy_to_be32(orb->page_table, orb->page_table,
+			  sizeof(orb->page_table[0]) * j);
+	orb->page_table_bus =
+		dma_map_single(device->card->device, orb->page_table,
+			       sizeof(orb->page_table), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->page_table_bus))
+		goto fail_page_table;
 
 	/*
 	 * The data_descriptor pointer is the one case where we need
@@ -953,20 +962,12 @@
 	 * initiator (i.e. us), but data_descriptor can refer to data
 	 * on other nodes so we need to put our ID in descriptor.high.
 	 */
-
-	orb->page_table_bus =
-		dma_map_single(device->card->device, orb->page_table,
-			       size, DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->page_table_bus))
-		goto fail_page_table;
 	orb->request.data_descriptor.high = sd->address_high;
 	orb->request.data_descriptor.low  = orb->page_table_bus;
 	orb->request.misc |=
 		COMMAND_ORB_PAGE_TABLE_PRESENT |
 		COMMAND_ORB_DATA_SIZE(j);
 
-	fw_memcpy_to_be32(orb->page_table, orb->page_table, size);
-
 	return 0;
 
  fail_page_table:
@@ -991,7 +992,7 @@
 	 * transfer direction not handled.
 	 */
 	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
-		fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+		fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
 		cmd->result = DID_ERROR << 16;
 		done(cmd);
 		return 0;
@@ -1005,11 +1006,6 @@
 
 	/* Initialize rcode to something not RCODE_COMPLETE. */
 	orb->base.rcode = -1;
-	orb->base.request_bus =
-		dma_map_single(device->card->device, &orb->request,
-			       sizeof(orb->request), DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->base.request_bus))
-		goto fail_mapping;
 
 	orb->unit = unit;
 	orb->done = done;
@@ -1024,8 +1020,8 @@
 	 * if we set this to max_speed + 7, we get the right value.
 	 */
 	orb->request.misc =
-		COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) |
-		COMMAND_ORB_SPEED(device->node->max_speed) |
+		COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
+		COMMAND_ORB_SPEED(device->max_speed) |
 		COMMAND_ORB_NOTIFY;
 
 	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
@@ -1036,7 +1032,7 @@
 			COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
 
 	if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
-		goto fail_map_payload;
+		goto fail_mapping;
 
 	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
 
@@ -1045,15 +1041,17 @@
 	memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
 
 	orb->base.callback = complete_command_orb;
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->base.request_bus))
+		goto fail_mapping;
 
 	sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
 		      sd->command_block_agent_address + SBP2_ORB_POINTER);
 
 	return 0;
 
- fail_map_payload:
-	dma_unmap_single(device->card->device, orb->base.request_bus,
-			 sizeof(orb->request), DMA_TO_DEVICE);
  fail_mapping:
 	kfree(orb);
  fail_alloc:
@@ -1087,7 +1085,8 @@
 		fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
 		sdev->fix_capacity = 1;
 	}
-
+	if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+		blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
 	return 0;
 }
 
@@ -1108,6 +1107,58 @@
 	return SUCCESS;
 }
 
+/*
+ * Format of /sys/bus/scsi/devices/.../ieee1394_id:
+ * u64 EUI-64 : u24 directory_ID : u16 LUN  (all printed in hexadecimal)
+ *
+ * This is the concatenation of target port identifier and logical unit
+ * identifier as per SAM-2...SAM-4 annex A.
+ */
+static ssize_t
+sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct sbp2_device *sd;
+	struct fw_unit *unit;
+	struct fw_device *device;
+	u32 directory_id;
+	struct fw_csr_iterator ci;
+	int key, value, lun;
+
+	if (!sdev)
+		return 0;
+	sd = (struct sbp2_device *)sdev->host->hostdata;
+	unit = sd->unit;
+	device = fw_device(unit->device.parent);
+
+	/* implicit directory ID */
+	directory_id = ((unit->directory - device->config_rom) * 4
+			+ CSR_CONFIG_ROM) & 0xffffff;
+
+	/* explicit directory ID, overrides implicit ID if present */
+	fw_csr_iterator_init(&ci, unit->directory);
+	while (fw_csr_iterator_next(&ci, &key, &value))
+		if (key == CSR_DIRECTORY_ID) {
+			directory_id = value;
+			break;
+		}
+
+	/* FIXME: Make this work for multi-lun devices. */
+	lun = 0;
+
+	return sprintf(buf, "%08x%08x:%06x:%04x\n",
+			device->config_rom[3], device->config_rom[4],
+			directory_id, lun);
+}
+
+static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
+
+static struct device_attribute *sbp2_scsi_sysfs_attrs[] = {
+	&dev_attr_ieee1394_id,
+	NULL
+};
+
 static struct scsi_host_template scsi_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "SBP-2 IEEE-1394",
@@ -1121,6 +1172,7 @@
 	.use_clustering		= ENABLE_CLUSTERING,
 	.cmd_per_lun		= 1,
 	.can_queue		= 1,
+	.sdev_attrs		= sbp2_scsi_sysfs_attrs,
 };
 
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 7aebb8a..39e5cd1 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -135,17 +135,17 @@
 	int i;
 
 	for (i = 0; i < node->port_count; i++) {
-		if (node->ports[i].node == NULL)
+		if (node->ports[i] == NULL)
 			continue;
 
-		if (node->ports[i].node->max_hops > max_child_hops)
-			max_child_hops = node->ports[i].node->max_hops;
+		if (node->ports[i]->max_hops > max_child_hops)
+			max_child_hops = node->ports[i]->max_hops;
 
-		if (node->ports[i].node->max_depth > depths[0]) {
+		if (node->ports[i]->max_depth > depths[0]) {
 			depths[1] = depths[0];
-			depths[0] = node->ports[i].node->max_depth;
-		} else if (node->ports[i].node->max_depth > depths[1])
-			depths[1] = node->ports[i].node->max_depth;
+			depths[0] = node->ports[i]->max_depth;
+		} else if (node->ports[i]->max_depth > depths[1])
+			depths[1] = node->ports[i]->max_depth;
 	}
 
 	node->max_depth = depths[0] + 1;
@@ -172,7 +172,8 @@
 	struct list_head stack, *h;
 	u32 *next_sid, *end, q;
 	int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
-	int gap_count, topology_type;
+	int gap_count;
+	bool beta_repeaters_present;
 
 	local_node = NULL;
 	node = NULL;
@@ -182,7 +183,7 @@
 	phy_id = 0;
 	irm_node = NULL;
 	gap_count = SELF_ID_GAP_COUNT(*sid);
-	topology_type = 0;
+	beta_repeaters_present = false;
 
 	while (sid < end) {
 		next_sid = count_ports(sid, &port_count, &child_port_count);
@@ -214,7 +215,7 @@
 
 		node = fw_node_create(q, port_count, card->color);
 		if (node == NULL) {
-			fw_error("Out of memory while building topology.");
+			fw_error("Out of memory while building topology.\n");
 			return NULL;
 		}
 
@@ -224,11 +225,6 @@
 		if (SELF_ID_CONTENDER(q))
 			irm_node = node;
 
-		if (node->phy_speed == SCODE_BETA)
-			topology_type |= FW_TOPOLOGY_B;
-		else
-			topology_type |= FW_TOPOLOGY_A;
-
 		parent_count = 0;
 
 		for (i = 0; i < port_count; i++) {
@@ -249,12 +245,12 @@
 				break;
 
 			case SELFID_PORT_CHILD:
-				node->ports[i].node = child;
+				node->ports[i] = child;
 				/*
 				 * Fix up parent reference for this
 				 * child node.
 				 */
-				child->ports[child->color].node = node;
+				child->ports[child->color] = node;
 				child->color = card->color;
 				child = fw_node(child->link.next);
 				break;
@@ -278,6 +274,10 @@
 		list_add_tail(&node->link, &stack);
 		stack_depth += 1 - child_port_count;
 
+		if (node->phy_speed == SCODE_BETA &&
+		    parent_count + child_port_count > 1)
+			beta_repeaters_present = true;
+
 		/*
 		 * If all PHYs does not report the same gap count
 		 * setting, we fall back to 63 which will force a gap
@@ -295,7 +295,7 @@
 	card->root_node = node;
 	card->irm_node = irm_node;
 	card->gap_count = gap_count;
-	card->topology_type = topology_type;
+	card->beta_repeaters_present = beta_repeaters_present;
 
 	return local_node;
 }
@@ -321,7 +321,7 @@
 		node->color = card->color;
 
 		for (i = 0; i < node->port_count; i++) {
-			child = node->ports[i].node;
+			child = node->ports[i];
 			if (!child)
 				continue;
 			if (child->color == card->color)
@@ -382,11 +382,11 @@
 	struct fw_node *tree;
 	int i;
 
-	tree = node1->ports[port].node;
-	node0->ports[port].node = tree;
+	tree = node1->ports[port];
+	node0->ports[port] = tree;
 	for (i = 0; i < tree->port_count; i++) {
-		if (tree->ports[i].node == node1) {
-			tree->ports[i].node = node0;
+		if (tree->ports[i] == node1) {
+			tree->ports[i] = node0;
 			break;
 		}
 	}
@@ -437,19 +437,17 @@
 			card->irm_node = node0;
 
 		for (i = 0; i < node0->port_count; i++) {
-			if (node0->ports[i].node && node1->ports[i].node) {
+			if (node0->ports[i] && node1->ports[i]) {
 				/*
 				 * This port didn't change, queue the
 				 * connected node for further
 				 * investigation.
 				 */
-				if (node0->ports[i].node->color == card->color)
+				if (node0->ports[i]->color == card->color)
 					continue;
-				list_add_tail(&node0->ports[i].node->link,
-					      &list0);
-				list_add_tail(&node1->ports[i].node->link,
-					      &list1);
-			} else if (node0->ports[i].node) {
+				list_add_tail(&node0->ports[i]->link, &list0);
+				list_add_tail(&node1->ports[i]->link, &list1);
+			} else if (node0->ports[i]) {
 				/*
 				 * The nodes connected here were
 				 * unplugged; unref the lost nodes and
@@ -457,10 +455,10 @@
 				 * them.
 				 */
 
-				for_each_fw_node(card, node0->ports[i].node,
+				for_each_fw_node(card, node0->ports[i],
 						 report_lost_node);
-				node0->ports[i].node = NULL;
-			} else if (node1->ports[i].node) {
+				node0->ports[i] = NULL;
+			} else if (node1->ports[i]) {
 				/*
 				 * One or more node were connected to
 				 * this port. Move the new nodes into
@@ -468,7 +466,7 @@
 				 * callbacks for them.
 				 */
 				move_tree(node0, node1, i);
-				for_each_fw_node(card, node0->ports[i].node,
+				for_each_fw_node(card, node0->ports[i],
 						 report_found_node);
 			}
 		}
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index 363b6cb..1b56b4a 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -20,12 +20,6 @@
 #define __fw_topology_h
 
 enum {
-	FW_TOPOLOGY_A =		0x01,
-	FW_TOPOLOGY_B =		0x02,
-	FW_TOPOLOGY_MIXED =	0x03,
-};
-
-enum {
 	FW_NODE_CREATED =   0x00,
 	FW_NODE_UPDATED =   0x01,
 	FW_NODE_DESTROYED = 0x02,
@@ -33,21 +27,16 @@
 	FW_NODE_LINK_OFF =  0x04,
 };
 
-struct fw_port {
-	struct fw_node *node;
-	unsigned speed : 3; /* S100, S200, ... S3200 */
-};
-
 struct fw_node {
 	u16 node_id;
 	u8 color;
 	u8 port_count;
-	unsigned link_on : 1;
-	unsigned initiated_reset : 1;
-	unsigned b_path : 1;
-	u8 phy_speed : 3; /* As in the self ID packet. */
-	u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on
-			   * the path from the local node to this node. */
+	u8 link_on : 1;
+	u8 initiated_reset : 1;
+	u8 b_path : 1;
+	u8 phy_speed : 2; /* As in the self ID packet. */
+	u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
+			   * local node to this node. */
 	u8 max_depth : 4; /* Maximum depth to any leaf node */
 	u8 max_hops : 4;  /* Max hops in this sub tree */
 	atomic_t ref_count;
@@ -58,7 +47,7 @@
 	/* Upper layer specific data. */
 	void *data;
 
-	struct fw_port ports[0];
+	struct fw_node *ports[0];
 };
 
 static inline struct fw_node *
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index acdc3be..5abed19 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -81,7 +81,6 @@
 
 #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
 #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
 
 static inline void
 fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
@@ -246,7 +245,7 @@
 	struct fw_node *irm_node;
 	int color;
 	int gap_count;
-	int topology_type;
+	bool beta_repeaters_present;
 
 	int index;
 
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 88f4621..05f02a3 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -84,4 +84,13 @@
 	  Say Y or M here to enable the driver for use by Dell systems
 	  management software such as Dell OpenManage.
 
+config DMIID
+    bool "Export DMI identification via sysfs to userspace"
+    depends on DMI
+    default y
+	help
+	  Say Y here if you want to query SMBIOS/DMI system identification
+	  information from userspace through /sys/class/dmi/id/ or if you want
+	  DMI-based module auto-loading.
+
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 98e395f..8d4ebc8 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_EFI_PCDP)		+= pcdp.o
 obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
 obj-$(CONFIG_DCDBAS)		+= dcdbas.o
+obj-$(CONFIG_DMIID)		+= dmi-id.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 1865b56..18cdcb3 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -149,8 +149,9 @@
 	return count;
 }
 
-static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
-			     size_t count)
+static ssize_t smi_data_read(struct kobject *kobj,
+			     struct bin_attribute *bin_attr,
+			     char *buf, loff_t pos, size_t count)
 {
 	size_t max_read;
 	ssize_t ret;
@@ -170,8 +171,9 @@
 	return ret;
 }
 
-static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
-			      size_t count)
+static ssize_t smi_data_write(struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t pos, size_t count)
 {
 	ssize_t ret;
 
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
index 58a8518..dcdba0f 100644
--- a/drivers/firmware/dcdbas.h
+++ b/drivers/firmware/dcdbas.h
@@ -67,8 +67,7 @@
 #define DCDBAS_BIN_ATTR_RW(_name) \
 struct bin_attribute bin_attr_##_name = { \
 	.attr =  { .name = __stringify(_name), \
-		   .mode = 0600, \
-		   .owner = THIS_MODULE }, \
+		   .mode = 0600 }, \
 	.read =  _name##_read, \
 	.write = _name##_write, \
 }
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index fc702e4..477a3d0 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -543,8 +543,9 @@
 	return ret_count;
 }
 
-static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
-	loff_t pos, size_t count)
+static ssize_t read_rbu_data(struct kobject *kobj,
+			     struct bin_attribute *bin_attr,
+			     char *buffer, loff_t pos, size_t count)
 {
 	ssize_t ret_count = 0;
 
@@ -591,8 +592,9 @@
 	spin_unlock(&rbu_data.lock);
 }
 
-static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
-	loff_t pos, size_t count)
+static ssize_t read_rbu_image_type(struct kobject *kobj,
+				   struct bin_attribute *bin_attr,
+				   char *buffer, loff_t pos, size_t count)
 {
 	int size = 0;
 	if (!pos)
@@ -600,8 +602,9 @@
 	return size;
 }
 
-static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
-	loff_t pos, size_t count)
+static ssize_t write_rbu_image_type(struct kobject *kobj,
+				    struct bin_attribute *bin_attr,
+				    char *buffer, loff_t pos, size_t count)
 {
 	int rc = count;
 	int req_firm_rc = 0;
@@ -660,8 +663,9 @@
 	return rc;
 }
 
-static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
-	loff_t pos, size_t count)
+static ssize_t read_rbu_packet_size(struct kobject *kobj,
+				    struct bin_attribute *bin_attr,
+				    char *buffer, loff_t pos, size_t count)
 {
 	int size = 0;
 	if (!pos) {
@@ -672,8 +676,9 @@
 	return size;
 }
 
-static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
-	loff_t pos, size_t count)
+static ssize_t write_rbu_packet_size(struct kobject *kobj,
+				     struct bin_attribute *bin_attr,
+				     char *buffer, loff_t pos, size_t count)
 {
 	unsigned long temp;
 	spin_lock(&rbu_data.lock);
@@ -687,18 +692,18 @@
 }
 
 static struct bin_attribute rbu_data_attr = {
-	.attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
+	.attr = {.name = "data", .mode = 0444},
 	.read = read_rbu_data,
 };
 
 static struct bin_attribute rbu_image_type_attr = {
-	.attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
+	.attr = {.name = "image_type", .mode = 0644},
 	.read = read_rbu_image_type,
 	.write = write_rbu_image_type,
 };
 
 static struct bin_attribute rbu_packet_size_attr = {
-	.attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
+	.attr = {.name = "packet_size", .mode = 0644},
 	.read = read_rbu_packet_size,
 	.write = write_rbu_packet_size,
 };
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
new file mode 100644
index 0000000..59c3b5a
--- /dev/null
+++ b/drivers/firmware/dmi-id.c
@@ -0,0 +1,222 @@
+/*
+ * Export SMBIOS/DMI info via sysfs to userspace
+ *
+ * Copyright 2007, Lennart Poettering
+ *
+ * Licensed under GPLv2
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/device.h>
+#include <linux/autoconf.h>
+
+#define DEFINE_DMI_ATTR(_name, _mode, _show)		\
+static struct device_attribute sys_dmi_##_name##_attr =	\
+	__ATTR(_name, _mode, _show, NULL);
+
+#define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field)			\
+static ssize_t sys_dmi_##_name##_show(struct device *dev,		\
+				      struct device_attribute *attr,	\
+				      char *page)			\
+{									\
+	ssize_t len;							\
+	len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \
+	page[len-1] = '\n';						\
+	return len;							\
+}									\
+DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show);
+
+DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor,		0444, DMI_BIOS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_version,		0444, DMI_BIOS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_date,		0444, DMI_BIOS_DATE);
+DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor,		0444, DMI_SYS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(product_name,		0444, DMI_PRODUCT_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(product_version,	0444, DMI_PRODUCT_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(product_serial,	0400, DMI_PRODUCT_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(product_uuid,		0400, DMI_PRODUCT_UUID);
+DEFINE_DMI_ATTR_WITH_SHOW(board_vendor,		0444, DMI_BOARD_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(board_name,		0444, DMI_BOARD_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(board_version,	0444, DMI_BOARD_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(board_serial,		0400, DMI_BOARD_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag,	0444, DMI_BOARD_ASSET_TAG);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor,	0444, DMI_CHASSIS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_type,		0444, DMI_CHASSIS_TYPE);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_version,	0444, DMI_CHASSIS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial,	0400, DMI_CHASSIS_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag,	0444, DMI_CHASSIS_ASSET_TAG);
+
+static void ascii_filter(char *d, const char *s)
+{
+	/* Filter out characters we don't want to see in the modalias string */
+	for (; *s; s++)
+		if (*s > ' ' && *s < 127 && *s != ':')
+			*(d++) = *s;
+
+	*d = 0;
+}
+
+static ssize_t get_modalias(char *buffer, size_t buffer_size)
+{
+	static const struct mafield {
+		const char *prefix;
+		int field;
+	} fields[] = {
+		{ "bvn", DMI_BIOS_VENDOR },
+		{ "bvr", DMI_BIOS_VERSION },
+		{ "bd",  DMI_BIOS_DATE },
+		{ "svn", DMI_SYS_VENDOR },
+		{ "pn",  DMI_PRODUCT_NAME },
+		{ "pvr", DMI_PRODUCT_VERSION },
+		{ "rvn", DMI_BOARD_VENDOR },
+		{ "rn",  DMI_BOARD_NAME },
+		{ "rvr", DMI_BOARD_VERSION },
+		{ "cvn", DMI_CHASSIS_VENDOR },
+		{ "ct",  DMI_CHASSIS_TYPE },
+		{ "cvr", DMI_CHASSIS_VERSION },
+		{ NULL,  DMI_NONE }
+	};
+
+	ssize_t l, left;
+	char *p;
+	const struct mafield *f;
+
+	strcpy(buffer, "dmi");
+	p = buffer + 3; left = buffer_size - 4;
+
+	for (f = fields; f->prefix && left > 0; f++) {
+		const char *c;
+		char *t;
+
+		c = dmi_get_system_info(f->field);
+		if (!c)
+			continue;
+
+		t = kmalloc(strlen(c) + 1, GFP_KERNEL);
+		if (!t)
+			break;
+		ascii_filter(t, c);
+		l = scnprintf(p, left, ":%s%s", f->prefix, t);
+		kfree(t);
+
+		p += l;
+		left -= l;
+	}
+
+	p[0] = ':';
+	p[1] = 0;
+
+	return p - buffer + 1;
+}
+
+static ssize_t sys_dmi_modalias_show(struct device *dev,
+				     struct device_attribute *attr, char *page)
+{
+	ssize_t r;
+	r = get_modalias(page, PAGE_SIZE-1);
+	page[r] = '\n';
+	page[r+1] = 0;
+	return r+1;
+}
+
+DEFINE_DMI_ATTR(modalias, 0444, sys_dmi_modalias_show);
+
+static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2];
+
+static struct attribute_group sys_dmi_attribute_group = {
+	.attrs = sys_dmi_attributes,
+};
+
+static struct attribute_group* sys_dmi_attribute_groups[] = {
+	&sys_dmi_attribute_group,
+	NULL
+};
+
+static int dmi_dev_uevent(struct device *dev, char **envp,
+			    int num_envp, char *buffer, int buffer_size)
+{
+	strcpy(buffer, "MODALIAS=");
+	get_modalias(buffer+9, buffer_size-9);
+	envp[0] = buffer;
+	envp[1] = NULL;
+
+	return 0;
+}
+
+static struct class dmi_class = {
+	.name = "dmi",
+	.dev_release = (void(*)(struct device *)) kfree,
+	.dev_uevent = dmi_dev_uevent,
+};
+
+static struct device *dmi_dev;
+
+/* Initialization */
+
+#define ADD_DMI_ATTR(_name, _field) \
+	if (dmi_get_system_info(_field)) \
+		sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr;
+
+extern int dmi_available;
+
+static int __init dmi_id_init(void)
+{
+	int ret, i;
+
+	if (!dmi_available)
+		return -ENODEV;
+
+	/* Not necessarily all DMI fields are available on all
+	 * systems, hence let's built an attribute table of just
+	 * what's available */
+	i = 0;
+	ADD_DMI_ATTR(bios_vendor,       DMI_BIOS_VENDOR);
+	ADD_DMI_ATTR(bios_version,      DMI_BIOS_VERSION);
+	ADD_DMI_ATTR(bios_date,         DMI_BIOS_DATE);
+	ADD_DMI_ATTR(sys_vendor,        DMI_SYS_VENDOR);
+	ADD_DMI_ATTR(product_name,      DMI_PRODUCT_NAME);
+	ADD_DMI_ATTR(product_version,   DMI_PRODUCT_VERSION);
+	ADD_DMI_ATTR(product_serial,    DMI_PRODUCT_SERIAL);
+	ADD_DMI_ATTR(product_uuid,      DMI_PRODUCT_UUID);
+	ADD_DMI_ATTR(board_vendor,      DMI_BOARD_VENDOR);
+	ADD_DMI_ATTR(board_name,        DMI_BOARD_NAME);
+	ADD_DMI_ATTR(board_version,     DMI_BOARD_VERSION);
+	ADD_DMI_ATTR(board_serial,      DMI_BOARD_SERIAL);
+	ADD_DMI_ATTR(board_asset_tag,   DMI_BOARD_ASSET_TAG);
+	ADD_DMI_ATTR(chassis_vendor,    DMI_CHASSIS_VENDOR);
+	ADD_DMI_ATTR(chassis_type,      DMI_CHASSIS_TYPE);
+	ADD_DMI_ATTR(chassis_version,   DMI_CHASSIS_VERSION);
+	ADD_DMI_ATTR(chassis_serial,    DMI_CHASSIS_SERIAL);
+	ADD_DMI_ATTR(chassis_asset_tag, DMI_CHASSIS_ASSET_TAG);
+	sys_dmi_attributes[i++] = &sys_dmi_modalias_attr.attr;
+
+	ret = class_register(&dmi_class);
+	if (ret)
+		return ret;
+
+	dmi_dev = kzalloc(sizeof(*dmi_dev), GFP_KERNEL);
+	if (!dmi_dev) {
+		ret = -ENOMEM;
+		goto fail_class_unregister;
+	}
+
+	dmi_dev->class = &dmi_class;
+	strcpy(dmi_dev->bus_id, "id");
+	dmi_dev->groups = sys_dmi_attribute_groups;
+
+	ret = device_register(dmi_dev);
+	if (ret)
+		goto fail_class_unregister;
+
+	return 0;
+
+fail_class_unregister:
+
+	class_unregister(&dmi_class);
+
+	return ret;
+}
+
+arch_initcall(dmi_id_init);
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 37deee6..f7318b3 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -84,6 +84,7 @@
 
 static char *dmi_ident[DMI_STRING_MAX];
 static LIST_HEAD(dmi_devices);
+int dmi_available;
 
 /*
  *	Save a DMI string
@@ -102,6 +103,51 @@
 	dmi_ident[slot] = p;
 }
 
+static void __init dmi_save_uuid(struct dmi_header *dm, int slot, int index)
+{
+	u8 *d = (u8*) dm + index;
+	char *s;
+	int is_ff = 1, is_00 = 1, i;
+
+	if (dmi_ident[slot])
+		return;
+
+	for (i = 0; i < 16 && (is_ff || is_00); i++) {
+		if(d[i] != 0x00) is_ff = 0;
+		if(d[i] != 0xFF) is_00 = 0;
+	}
+
+	if (is_ff || is_00)
+		return;
+
+	s = dmi_alloc(16*2+4+1);
+	if (!s)
+		return;
+
+	sprintf(s,
+		"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+		d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+		d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+
+        dmi_ident[slot] = s;
+}
+
+static void __init dmi_save_type(struct dmi_header *dm, int slot, int index)
+{
+	u8 *d = (u8*) dm + index;
+	char *s;
+
+	if (dmi_ident[slot])
+		return;
+
+	s = dmi_alloc(4);
+	if (!s)
+		return;
+
+	sprintf(s, "%u", *d & 0x7F);
+	dmi_ident[slot] = s;
+}
+
 static void __init dmi_save_devices(struct dmi_header *dm)
 {
 	int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
@@ -192,11 +238,21 @@
 		dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
 		dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
 		dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
+		dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
 		break;
 	case 2:		/* Base Board Information */
 		dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
 		dmi_save_ident(dm, DMI_BOARD_NAME, 5);
 		dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
+		dmi_save_ident(dm, DMI_BOARD_SERIAL, 7);
+		dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8);
+		break;
+	case 3:		/* Chassis Information */
+		dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4);
+		dmi_save_type(dm, DMI_CHASSIS_TYPE, 5);
+		dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6);
+		dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);
+		dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
 		break;
 	case 10:	/* Onboard Devices Information */
 		dmi_save_devices(dm);
@@ -243,18 +299,20 @@
 		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
 			goto out;
 
-               /* This is called as a core_initcall() because it isn't
-                * needed during early boot.  This also means we can
-                * iounmap the space when we're done with it.
-		*/
+		/* This is called as a core_initcall() because it isn't
+		 * needed during early boot.  This also means we can
+		 * iounmap the space when we're done with it.
+		 */
 		p = dmi_ioremap(efi.smbios, 32);
 		if (p == NULL)
 			goto out;
 
 		rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
 		dmi_iounmap(p, 32);
-		if (!rc)
+		if (!rc) {
+			dmi_available = 1;
 			return;
+		}
 	}
 	else {
 		/*
@@ -268,8 +326,10 @@
 
 		for (q = p; q < p + 0x10000; q += 16) {
 			rc = dmi_present(q);
-			if (!rc)
+			if (!rc) {
+				dmi_available = 1;
 				return;
+			}
 		}
 	}
  out:	printk(KERN_INFO "DMI not present or invalid.\n");
@@ -404,3 +464,4 @@
 
 	return year;
 }
+
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index d8806e4..0fb730e 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -74,7 +74,7 @@
 
 #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
 struct edd_attribute edd_attr_##_name = { 	\
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
 	.show	= _show,				\
 	.test	= _test,				\
 };
@@ -669,7 +669,7 @@
 	struct edd_info *info = edd_dev_get_info(edev);
 
 	if (edd_dev_is_type(edev, "PCI")) {
-		return pci_find_slot(info->params.interface_path.pci.bus,
+		return pci_get_bus_and_slot(info->params.interface_path.pci.bus,
 				     PCI_DEVFN(info->params.interface_path.pci.slot,
 					       info->params.interface_path.pci.
 					       function));
@@ -682,9 +682,12 @@
 {
 
 	struct pci_dev *pci_dev = edd_get_pci_dev(edev);
+	int ret;
 	if (!pci_dev)
 		return 1;
-	return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
+	ret = sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
+	pci_dev_put(pci_dev);
+	return ret;
 }
 
 static inline void
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 1324984..bfd2d67 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -131,21 +131,21 @@
 
 #define EFI_ATTR(_name, _mode, _show, _store) \
 struct subsys_attribute efi_attr_##_name = { \
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+	.attr = {.name = __stringify(_name), .mode = _mode}, \
 	.show = _show, \
 	.store = _store, \
 };
 
 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
 struct efivar_attribute efivar_attr_##_name = { \
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+	.attr = {.name = __stringify(_name), .mode = _mode}, \
 	.show = _show, \
 	.store = _store, \
 };
 
 #define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
 struct subsys_attribute var_subsys_attr_##_name = { \
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+	.attr = {.name = __stringify(_name), .mode = _mode}, \
 	.show = _show, \
 	.store = _store, \
 };
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index 2b4b76e..58e9f8e 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -15,6 +15,7 @@
 #include <linux/console.h>
 #include <linux/efi.h>
 #include <linux/serial.h>
+#include <linux/serial_8250.h>
 #include <asm/vga.h>
 #include "pcdp.h"
 
@@ -27,7 +28,7 @@
 	char parity;
 
 	mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
-	p += sprintf(p, "console=uart,%s,0x%lx",
+	p += sprintf(p, "uart8250,%s,0x%lx",
 		mmio ? "mmio" : "io", uart->addr.address);
 	if (uart->baud) {
 		p += sprintf(p, ",%lu", uart->baud);
@@ -41,7 +42,8 @@
 		}
 	}
 
-	return early_serial_console_init(options);
+	add_preferred_console("uart", 8250, &options[9]);
+	return setup_early_serial8250_console(options);
 #else
 	return -ENODEV;
 #endif
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8fbe9fd..3b63b0b 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1,8 +1,12 @@
 #
 # HID driver configuration
 #
-menu "HID Devices"
+menuconfig HID_SUPPORT
+	bool "HID Devices"
 	depends on INPUT
+	default y
+
+if HID_SUPPORT
 
 config HID
 	tristate "Generic HID support"
@@ -24,6 +28,7 @@
 
 config HID_DEBUG
 	bool "HID debugging support"
+	default y if !EMBEDDED
 	depends on HID
 	---help---
 	This option lets the HID layer output diagnostics about its internal
@@ -38,5 +43,4 @@
 
 source "drivers/hid/usbhid/Kconfig"
 
-endmenu
-
+endif # HID_SUPPORT
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6ec04e7..317cf8a 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -40,6 +40,13 @@
 #define DRIVER_DESC "HID core driver"
 #define DRIVER_LICENSE "GPL"
 
+#ifdef CONFIG_HID_DEBUG
+int hid_debug = 0;
+module_param_named(debug, hid_debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Turn HID debugging mode on and off");
+EXPORT_SYMBOL_GPL(hid_debug);
+#endif
+
 /*
  * Register a new report for a device.
  */
@@ -78,7 +85,7 @@
 	struct hid_field *field;
 
 	if (report->maxfield == HID_MAX_FIELDS) {
-		dbg("too many fields in report");
+		dbg_hid("too many fields in report\n");
 		return NULL;
 	}
 
@@ -106,7 +113,7 @@
 	usage = parser->local.usage[0];
 
 	if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
-		dbg("collection stack overflow");
+		dbg_hid("collection stack overflow\n");
 		return -1;
 	}
 
@@ -114,7 +121,7 @@
 		collection = kmalloc(sizeof(struct hid_collection) *
 				parser->device->collection_size * 2, GFP_KERNEL);
 		if (collection == NULL) {
-			dbg("failed to reallocate collection array");
+			dbg_hid("failed to reallocate collection array\n");
 			return -1;
 		}
 		memcpy(collection, parser->device->collection,
@@ -150,7 +157,7 @@
 static int close_collection(struct hid_parser *parser)
 {
 	if (!parser->collection_stack_ptr) {
-		dbg("collection stack underflow");
+		dbg_hid("collection stack underflow\n");
 		return -1;
 	}
 	parser->collection_stack_ptr--;
@@ -178,7 +185,7 @@
 static int hid_add_usage(struct hid_parser *parser, unsigned usage)
 {
 	if (parser->local.usage_index >= HID_MAX_USAGES) {
-		dbg("usage index exceeded");
+		dbg_hid("usage index exceeded\n");
 		return -1;
 	}
 	parser->local.usage[parser->local.usage_index] = usage;
@@ -202,12 +209,12 @@
 	int i;
 
 	if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
-		dbg("hid_register_report failed");
+		dbg_hid("hid_register_report failed\n");
 		return -1;
 	}
 
 	if (parser->global.logical_maximum < parser->global.logical_minimum) {
-		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+		dbg_hid("logical range invalid %d %d\n", parser->global.logical_minimum, parser->global.logical_maximum);
 		return -1;
 	}
 
@@ -287,7 +294,7 @@
 		case HID_GLOBAL_ITEM_TAG_PUSH:
 
 			if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
-				dbg("global enviroment stack overflow");
+				dbg_hid("global enviroment stack overflow\n");
 				return -1;
 			}
 
@@ -298,7 +305,7 @@
 		case HID_GLOBAL_ITEM_TAG_POP:
 
 			if (!parser->global_stack_ptr) {
-				dbg("global enviroment stack underflow");
+				dbg_hid("global enviroment stack underflow\n");
 				return -1;
 			}
 
@@ -342,27 +349,27 @@
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
 			if ((parser->global.report_size = item_udata(item)) > 32) {
-				dbg("invalid report_size %d", parser->global.report_size);
+				dbg_hid("invalid report_size %d\n", parser->global.report_size);
 				return -1;
 			}
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
 			if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
-				dbg("invalid report_count %d", parser->global.report_count);
+				dbg_hid("invalid report_count %d\n", parser->global.report_count);
 				return -1;
 			}
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_ID:
 			if ((parser->global.report_id = item_udata(item)) == 0) {
-				dbg("report_id 0 is invalid");
+				dbg_hid("report_id 0 is invalid\n");
 				return -1;
 			}
 			return 0;
 
 		default:
-			dbg("unknown global tag 0x%x", item->tag);
+			dbg_hid("unknown global tag 0x%x\n", item->tag);
 			return -1;
 	}
 }
@@ -377,7 +384,7 @@
 	unsigned n;
 
 	if (item->size == 0) {
-		dbg("item data expected for local item");
+		dbg_hid("item data expected for local item\n");
 		return -1;
 	}
 
@@ -395,14 +402,14 @@
 				 * items and the first delimiter set.
 				 */
 				if (parser->local.delimiter_depth != 0) {
-					dbg("nested delimiters");
+					dbg_hid("nested delimiters\n");
 					return -1;
 				}
 				parser->local.delimiter_depth++;
 				parser->local.delimiter_branch++;
 			} else {
 				if (parser->local.delimiter_depth < 1) {
-					dbg("bogus close delimiter");
+					dbg_hid("bogus close delimiter\n");
 					return -1;
 				}
 				parser->local.delimiter_depth--;
@@ -412,7 +419,7 @@
 		case HID_LOCAL_ITEM_TAG_USAGE:
 
 			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
+				dbg_hid("alternative usage ignored\n");
 				return 0;
 			}
 
@@ -424,7 +431,7 @@
 		case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
 
 			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
+				dbg_hid("alternative usage ignored\n");
 				return 0;
 			}
 
@@ -437,7 +444,7 @@
 		case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
 
 			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
+				dbg_hid("alternative usage ignored\n");
 				return 0;
 			}
 
@@ -446,14 +453,14 @@
 
 			for (n = parser->local.usage_minimum; n <= data; n++)
 				if (hid_add_usage(parser, n)) {
-					dbg("hid_add_usage failed\n");
+					dbg_hid("hid_add_usage failed\n");
 					return -1;
 				}
 			return 0;
 
 		default:
 
-			dbg("unknown local item tag 0x%x", item->tag);
+			dbg_hid("unknown local item tag 0x%x\n", item->tag);
 			return 0;
 	}
 	return 0;
@@ -487,7 +494,7 @@
 			ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
 			break;
 		default:
-			dbg("unknown main item tag 0x%x", item->tag);
+			dbg_hid("unknown main item tag 0x%x\n", item->tag);
 			ret = 0;
 	}
 
@@ -502,7 +509,7 @@
 
 static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
 {
-	dbg("reserved item type, tag 0x%x", item->tag);
+	dbg_hid("reserved item type, tag 0x%x\n", item->tag);
 	return 0;
 }
 
@@ -667,14 +674,14 @@
 	while ((start = fetch_item(start, end, &item)) != NULL) {
 
 		if (item.format != HID_ITEM_FORMAT_SHORT) {
-			dbg("unexpected long global item");
+			dbg_hid("unexpected long global item\n");
 			hid_free_device(device);
 			vfree(parser);
 			return NULL;
 		}
 
 		if (dispatch_type[item.type](parser, &item)) {
-			dbg("item %u %u %u %u parsing failed\n",
+			dbg_hid("item %u %u %u %u parsing failed\n",
 				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
 			hid_free_device(device);
 			vfree(parser);
@@ -683,13 +690,13 @@
 
 		if (start == end) {
 			if (parser->collection_stack_ptr) {
-				dbg("unbalanced collection at end of report description");
+				dbg_hid("unbalanced collection at end of report description\n");
 				hid_free_device(device);
 				vfree(parser);
 				return NULL;
 			}
 			if (parser->local.delimiter_depth) {
-				dbg("unbalanced delimiter at end of report description");
+				dbg_hid("unbalanced delimiter at end of report description\n");
 				hid_free_device(device);
 				vfree(parser);
 				return NULL;
@@ -699,7 +706,7 @@
 		}
 	}
 
-	dbg("item fetching failed at offset %d\n", (int)(end - start));
+	dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
 	hid_free_device(device);
 	vfree(parser);
 	return NULL;
@@ -915,13 +922,13 @@
 	hid_dump_input(field->usage + offset, value);
 
 	if (offset >= field->report_count) {
-		dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
+		dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count);
 		hid_dump_field(field, 8);
 		return -1;
 	}
 	if (field->logical_minimum < 0) {
 		if (value != snto32(s32ton(value, size), size)) {
-			dbg("value %d is out of range", value);
+			dbg_hid("value %d is out of range\n", value);
 			return -1;
 		}
 	}
@@ -934,19 +941,17 @@
 {
 	struct hid_report_enum *report_enum = hid->report_enum + type;
 	struct hid_report *report;
-	int n, rsize;
+	int n, rsize, i;
 
 	if (!hid)
 		return -ENODEV;
 
 	if (!size) {
-		dbg("empty report");
+		dbg_hid("empty report\n");
 		return -1;
 	}
 
-#ifdef CONFIG_HID_DEBUG
-	printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
-#endif
+	dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
 
 	n = 0;                          /* Normally report number is 0 */
 	if (report_enum->numbered) {    /* Device uses numbered reports, data[0] is report number */
@@ -954,25 +959,21 @@
 		size--;
 	}
 
-#ifdef CONFIG_HID_DEBUG
-	{
-		int i;
-		printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
-		for (i = 0; i < size; i++)
-			printk(" %02x", data[i]);
-		printk("\n");
-	}
-#endif
+	/* dump the report descriptor */
+	dbg_hid("report %d (size %u) = ", n, size);
+	for (i = 0; i < size; i++)
+		dbg_hid_line(" %02x", data[i]);
+	dbg_hid_line("\n");
 
 	if (!(report = report_enum->report_id_hash[n])) {
-		dbg("undefined report_id %d received", n);
+		dbg_hid("undefined report_id %d received\n", n);
 		return -1;
 	}
 
 	rsize = ((report->size - 1) >> 3) + 1;
 
 	if (size < rsize) {
-		dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
+		dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
 		memset(data + size, 0, rsize - size);
 	}
 
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 83c4126..a13757b 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -347,6 +347,9 @@
 void hid_resolv_usage(unsigned usage) {
 	const struct hid_usage_entry *p;
 
+	if (!hid_debug)
+		return;
+
 	resolv_usage_page(usage >> 16);
 	printk(".");
 	for (p = hid_usage_table; p->description; p++)
@@ -369,6 +372,9 @@
 void hid_dump_field(struct hid_field *field, int n) {
 	int j;
 
+	if (!hid_debug)
+		return;
+
 	if (field->physical) {
 		tab(n);
 		printk("Physical(");
@@ -466,6 +472,9 @@
 	unsigned i,k;
 	static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
 
+	if (!hid_debug)
+		return;
+
 	for (i = 0; i < HID_REPORT_TYPES; i++) {
 		report_enum = device->report_enum + i;
 		list = report_enum->report_list.next;
@@ -489,6 +498,9 @@
 EXPORT_SYMBOL_GPL(hid_dump_device);
 
 void hid_dump_input(struct hid_usage *usage, __s32 value) {
+	if (!hid_debug)
+		return;
+
 	printk("hid-debug: input ");
 	hid_resolv_usage(usage->hid);
 	printk(" = %d\n", value);
@@ -758,6 +770,9 @@
 
 void hid_resolv_event(__u8 type, __u16 code) {
 
+	if (!hid_debug)
+		return;
+
 	printk("%s.%s", events[type] ? events[type] : "?",
 		names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
 }
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7f81789..8edbd30 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -60,6 +60,19 @@
 	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
 };
 
+/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
+#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
+static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
+	  0,216,  0,213,175,156,  0,  0,  0,  0,
+	144,  0,  0,  0,  0,  0,  0,  0,  0,212,
+	174,167,152,161,112,  0,  0,  0,154,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,183,184,185,186,187,
+	188,189,190,191,192,193,194,  0,  0,  0
+};
+
 static const struct {
 	__s32 x;
 	__s32 y;
@@ -308,9 +321,7 @@
 		
 		clear_bit(old_keycode, dev->keybit);
 		set_bit(usage->code, dev->keybit);
-#ifdef CONFIG_HID_DEBUG
-		printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
-#endif
+		dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
 		/* Set the keybit for the old keycode if the old keycode is used
 		 * by another key */
 		if (hidinput_find_key (hid, 0, old_keycode))
@@ -333,11 +344,9 @@
 
 	field->hidinput = hidinput;
 
-#ifdef CONFIG_HID_DEBUG
-	printk(KERN_DEBUG "Mapping: ");
+	dbg_hid("Mapping: ");
 	hid_resolv_usage(usage->hid);
-	printk(" ---> ");
-#endif
+	dbg_hid_line(" ---> ");
 
 	if (field->flags & HID_MAIN_ITEM_CONSTANT)
 		goto ignore;
@@ -378,6 +387,21 @@
 					}
 			}
 
+			/* Special handling for Logitech Cordless Desktop */
+			if (field->application != HID_GD_MOUSE) {
+				if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
+					int hid = usage->hid & HID_USAGE;
+					if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
+						code = logitech_expanded_keymap[hid];
+				}
+			} else {
+				if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
+					int hid = usage->hid & HID_USAGE;
+					if (hid == 7 || hid == 8)
+						goto ignore;
+				}
+			}
+
 			map_key(code);
 			break;
 
@@ -566,6 +590,11 @@
 				case 0x0e5: map_key_clear(KEY_BASSBOOST);	break;
 				case 0x0e9: map_key_clear(KEY_VOLUMEUP);	break;
 				case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);	break;
+
+				/* reserved in HUT 1.12. Reported on Petalynx remote */
+				case 0x0f6: map_key_clear(KEY_NEXT);		break;
+				case 0x0fa: map_key_clear(KEY_BACK);		break;
+
 				case 0x183: map_key_clear(KEY_CONFIG);		break;
 				case 0x184: map_key_clear(KEY_WORDPROCESSOR);	break;
 				case 0x185: map_key_clear(KEY_EDITOR);		break;
@@ -598,7 +627,9 @@
 				case 0x21b: map_key_clear(KEY_COPY);		break;
 				case 0x21c: map_key_clear(KEY_CUT);		break;
 				case 0x21d: map_key_clear(KEY_PASTE);		break;
-				case 0x221: map_key_clear(KEY_FIND);		break;
+				case 0x21f: map_key_clear(KEY_FIND);		break;
+				case 0x221: map_key_clear(KEY_SEARCH);		break;
+				case 0x222: map_key_clear(KEY_GOTO);		break;
 				case 0x223: map_key_clear(KEY_HOMEPAGE);	break;
 				case 0x224: map_key_clear(KEY_BACK);		break;
 				case 0x225: map_key_clear(KEY_FORWARD);		break;
@@ -688,7 +719,28 @@
 			break;
 
 		case HID_UP_MSVENDOR:
-			goto ignore;
+
+			/* special case - Chicony Chicony KU-0418 tactical pad */
+			if (device->vendor == 0x04f2 && device->product == 0x0418) {
+				set_bit(EV_REP, input->evbit);
+				switch(usage->hid & HID_USAGE) {
+					case 0xff01: map_key_clear(BTN_1);		break;
+					case 0xff02: map_key_clear(BTN_2);		break;
+					case 0xff03: map_key_clear(BTN_3);		break;
+					case 0xff04: map_key_clear(BTN_4);		break;
+					case 0xff05: map_key_clear(BTN_5);		break;
+					case 0xff06: map_key_clear(BTN_6);		break;
+					case 0xff07: map_key_clear(BTN_7);		break;
+					case 0xff08: map_key_clear(BTN_8);		break;
+					case 0xff09: map_key_clear(BTN_9);		break;
+					case 0xff0a: map_key_clear(BTN_A);		break;
+					case 0xff0b: map_key_clear(BTN_B);		break;
+					default:    goto ignore;
+				}
+			} else {
+				goto ignore;
+			}
+			break;
 
 		case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
 
@@ -704,10 +756,10 @@
 			}
 			break;
 
-		case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
-
+		case HID_UP_LOGIVENDOR:
 			set_bit(EV_REP, input->evbit);
 			switch(usage->hid & HID_USAGE) {
+				/* Reported on Logitech Ultra X Media Remote */
 				case 0x004: map_key_clear(KEY_AGAIN);		break;
 				case 0x00d: map_key_clear(KEY_HOME);		break;
 				case 0x024: map_key_clear(KEY_SHUFFLE);		break;
@@ -725,6 +777,14 @@
 				case 0x04d: map_key_clear(KEY_SUBTITLE);	break;
 				case 0x051: map_key_clear(KEY_RED);		break;
 				case 0x052: map_key_clear(KEY_CLOSE);		break;
+
+				/* Reported on Petalynx Maxter remote */
+				case 0x05a: map_key_clear(KEY_TEXT);		break;
+				case 0x05b: map_key_clear(KEY_RED);		break;
+				case 0x05c: map_key_clear(KEY_GREEN);		break;
+				case 0x05d: map_key_clear(KEY_YELLOW);		break;
+				case 0x05e: map_key_clear(KEY_BLUE);		break;
+
 				default:    goto ignore;
 			}
 			break;
@@ -818,16 +878,24 @@
 			field->dpad = usage->code;
 	}
 
+	/* for those devices which produce Consumer volume usage as relative,
+	 * we emulate pressing volumeup/volumedown appropriate number of times
+	 * in hidinput_hid_event()
+	 */
+	if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+			(usage->code == ABS_VOLUME)) {
+		set_bit(KEY_VOLUMEUP, input->keybit);
+		set_bit(KEY_VOLUMEDOWN, input->keybit);
+	}
+
 	hid_resolv_event(usage->type, usage->code);
-#ifdef CONFIG_HID_DEBUG
-	printk("\n");
-#endif
+
+	dbg_hid_line("\n");
+
 	return;
 
 ignore:
-#ifdef CONFIG_HID_DEBUG
-	printk("IGNORED\n");
-#endif
+	dbg_hid_line("IGNORED\n");
 	return;
 }
 
@@ -896,18 +964,33 @@
 	}
 
 	if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
-		dbg("Maximum Effects - %d",value);
+		dbg_hid("Maximum Effects - %d\n",value);
 		return;
 	}
 
 	if (usage->hid == (HID_UP_PID | 0x7fUL)) {
-		dbg("PID Pool Report\n");
+		dbg_hid("PID Pool Report\n");
 		return;
 	}
 
 	if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
 		return;
 
+	if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+			(usage->code == ABS_VOLUME)) {
+		int count = abs(value);
+		int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
+		int i;
+
+		for (i = 0; i < count; i++) {
+			input_event(input, EV_KEY, direction, 1);
+			input_sync(input);
+			input_event(input, EV_KEY, direction, 0);
+			input_sync(input);
+		}
+		return;
+	}
+
 	input_event(input, usage->type, usage->code, value);
 
 	if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
@@ -976,7 +1059,7 @@
 			if (IS_INPUT_APPLICATION(hid->collection[i].usage))
 				break;
 
-	if (i == hid->maxcollection)
+	if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
 		return -1;
 
 	if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
@@ -994,7 +1077,7 @@
 				if (!hidinput || !input_dev) {
 					kfree(hidinput);
 					input_free_device(input_dev);
-					err("Out of memory during hid input probe");
+					err_hid("Out of memory during hid input probe");
 					return -1;
 				}
 
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index d91b9da..b2baeae 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -60,6 +60,12 @@
 		" quirks=vendorID:productID:quirks"
 		" where vendorID, productID, and quirks are all in"
 		" 0x-prefixed hex");
+static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
+module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
+MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
+		" rdesc_quirks=vendorID:productID:rdesc_quirks"
+		" where vendorID, productID, and rdesc_quirks are all in"
+		" 0x-prefixed hex");
 /*
  * Input submission and I/O error handler.
  */
@@ -127,7 +133,7 @@
 			hid_io_error(hid);
 		break;
 	default:
-		err("can't reset device, %s-%s/input%d, status %d",
+		err_hid("can't reset device, %s-%s/input%d, status %d",
 				hid_to_usb_dev(hid)->bus->bus_name,
 				hid_to_usb_dev(hid)->devpath,
 				usbhid->ifnum, rc);
@@ -220,7 +226,7 @@
 	if (status) {
 		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
 		if (status != -EPERM) {
-			err("can't resubmit intr, %s-%s/input%d, status %d",
+			err_hid("can't resubmit intr, %s-%s/input%d, status %d",
 					hid_to_usb_dev(hid)->bus->bus_name,
 					hid_to_usb_dev(hid)->devpath,
 					usbhid->ifnum, status);
@@ -240,10 +246,10 @@
 	usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
 	usbhid->urbout->dev = hid_to_usb_dev(hid);
 
-	dbg("submitting out urb");
+	dbg_hid("submitting out urb\n");
 
 	if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
-		err("usb_submit_urb(out) failed");
+		err_hid("usb_submit_urb(out) failed");
 		return -1;
 	}
 
@@ -287,12 +293,12 @@
 	usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
 	usbhid->cr->wLength = cpu_to_le16(len);
 
-	dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
+	dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n",
 		usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
 		usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
 
 	if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
-		err("usb_submit_urb(ctrl) failed");
+		err_hid("usb_submit_urb(ctrl) failed");
 		return -1;
 	}
 
@@ -474,7 +480,7 @@
 	if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
 					!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
 					10*HZ)) {
-		dbg("timeout waiting for ctrl or out queue to clear");
+		dbg_hid("timeout waiting for ctrl or out queue to clear\n");
 		return -1;
 	}
 
@@ -633,20 +639,6 @@
 }
 
 /*
- * Cherry Cymotion keyboard have an invalid HID report descriptor,
- * that needs fixing before we can parse it.
- */
-
-static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
-{
-	if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
-		info("Fixing up Cherry Cymotion report descriptor");
-		rdesc[11] = rdesc[16] = 0xff;
-		rdesc[12] = rdesc[17] = 0x03;
-	}
-}
-
-/*
  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
  * to "operational".  Without this, the ps3 controller will not report any
  * events.
@@ -667,51 +659,11 @@
 				 USB_CTRL_GET_TIMEOUT);
 
 	if (result < 0)
-		err("%s failed: %d\n", __func__, result);
+		err_hid("%s failed: %d\n", __func__, result);
 
 	kfree(buf);
 }
 
-/*
- * Certain Logitech keyboards send in report #3 keys which are far
- * above the logical maximum described in descriptor. This extends
- * the original value of 0x28c of logical maximum to 0x104d
- */
-static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
-{
-	if (rsize >= 90 && rdesc[83] == 0x26
-			&& rdesc[84] == 0x8c
-			&& rdesc[85] == 0x02) {
-		info("Fixing up Logitech keyboard report descriptor");
-		rdesc[84] = rdesc[89] = 0x4d;
-		rdesc[85] = rdesc[90] = 0x10;
-	}
-}
-
-/*
- * Some USB barcode readers from cypress have usage min and usage max in
- * the wrong order
- */
-static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
-{
-	short fixed = 0;
-	int i;
-
-	for (i = 0; i < rsize - 4; i++) {
-		if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
-			unsigned char tmp;
-
-			rdesc[i] = 0x19; rdesc[i+2] = 0x29;
-			tmp = rdesc[i+3];
-			rdesc[i+3] = rdesc[i+1];
-			rdesc[i+1] = tmp;
-		}
-	}
-
-	if (fixed)
-		info("Fixing up Cypress report descriptor");
-}
-
 static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 {
 	struct usb_host_interface *interface = intf->cur_altsetting;
@@ -746,7 +698,7 @@
 	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
 	    (!interface->desc.bNumEndpoints ||
 	     usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
-		dbg("class descriptor not present\n");
+		dbg_hid("class descriptor not present\n");
 		return NULL;
 	}
 
@@ -755,41 +707,34 @@
 			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
 
 	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
-		dbg("weird size of report descriptor (%u)", rsize);
+		dbg_hid("weird size of report descriptor (%u)\n", rsize);
 		return NULL;
 	}
 
 	if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
-		dbg("couldn't allocate rdesc memory");
+		dbg_hid("couldn't allocate rdesc memory\n");
 		return NULL;
 	}
 
 	hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
 
 	if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
-		dbg("reading report descriptor failed");
+		dbg_hid("reading report descriptor failed\n");
 		kfree(rdesc);
 		return NULL;
 	}
 
-	if ((quirks & HID_QUIRK_CYMOTION))
-		hid_fixup_cymotion_descriptor(rdesc, rsize);
+	usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
+			le16_to_cpu(dev->descriptor.idProduct), rdesc,
+			rsize, rdesc_quirks_param);
 
-	if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
-		hid_fixup_logitech_descriptor(rdesc, rsize);
-
-	if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
-		hid_fixup_cypress_descriptor(rdesc, rsize);
-
-#ifdef CONFIG_HID_DEBUG
-	printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
+	dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
 	for (n = 0; n < rsize; n++)
-		printk(" %02x", (unsigned char) rdesc[n]);
-	printk("\n");
-#endif
+		dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
+	dbg_hid_line("\n");
 
 	if (!(hid = hid_parse_report(rdesc, n))) {
-		dbg("parsing report descriptor failed");
+		dbg_hid("parsing report descriptor failed\n");
 		kfree(rdesc);
 		return NULL;
 	}
@@ -861,7 +806,7 @@
 	}
 
 	if (!usbhid->urbin) {
-		err("couldn't find an input interrupt endpoint");
+		err_hid("couldn't find an input interrupt endpoint");
 		goto fail;
 	}
 
@@ -956,7 +901,7 @@
 	usb_kill_urb(usbhid->urbctrl);
 
 	del_timer_sync(&usbhid->io_retry);
-	flush_scheduled_work();
+	cancel_work_sync(&usbhid->reset_work);
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_disconnect(hid);
@@ -978,7 +923,7 @@
 	int i;
 	char *c;
 
-	dbg("HID probe called for ifnum %d",
+	dbg_hid("HID probe called for ifnum %d\n",
 			intf->altsetting->desc.bInterfaceNumber);
 
 	if (!(hid = usb_hid_configure(intf)))
@@ -1064,20 +1009,22 @@
 }
 
 /* Treat USB reset pretty much the same as suspend/resume */
-static void hid_pre_reset(struct usb_interface *intf)
+static int hid_pre_reset(struct usb_interface *intf)
 {
 	/* FIXME: What if the interface is already suspended? */
 	hid_suspend(intf, PMSG_ON);
+	return 0;
 }
 
-static void hid_post_reset(struct usb_interface *intf)
+/* Same routine used for post_reset and reset_resume */
+static int hid_post_reset(struct usb_interface *intf)
 {
 	struct usb_device *dev = interface_to_usbdev (intf);
 
 	hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
 	/* FIXME: Any more reinitialization needed? */
 
-	hid_resume(intf);
+	return hid_resume(intf);
 }
 
 static struct usb_device_id hid_usb_ids [] = {
@@ -1094,6 +1041,7 @@
 	.disconnect =	hid_disconnect,
 	.suspend =	hid_suspend,
 	.resume =	hid_resume,
+	.reset_resume =	hid_post_reset,
 	.pre_reset =	hid_pre_reset,
 	.post_reset =	hid_post_reset,
 	.id_table =	hid_usb_ids,
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c
index c5cd410..4b7ab6a 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/usbhid/hid-lgff.c
@@ -78,7 +78,7 @@
 		report->field[0]->value[1] = 0x08;
 		report->field[0]->value[2] = x;
 		report->field[0]->value[3] = y;
-		dbg("(x, y)=(%04x, %04x)", x, y);
+		dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
 		break;
 
@@ -93,7 +93,7 @@
 		report->field[0]->value[1] = 0x00;
 		report->field[0]->value[2] = left;
 		report->field[0]->value[3] = right;
-		dbg("(left, right)=(%04x, %04x)", left, right);
+		dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
 		break;
 	}
@@ -113,20 +113,20 @@
 
 	/* Find the report to use */
 	if (list_empty(report_list)) {
-		err("No output report found");
+		err_hid("No output report found");
 		return -1;
 	}
 
 	/* Check that the report looks ok */
 	report = list_entry(report_list->next, struct hid_report, list);
 	if (!report) {
-		err("NULL output report");
+		err_hid("NULL output report");
 		return -1;
 	}
 
 	field = report->field[0];
 	if (!field) {
-		err("NULL field");
+		err_hid("NULL field");
 		return -1;
 	}
 
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index f5a90e9..0113261 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -738,6 +738,7 @@
 	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
 	pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
 	pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
+	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
 	pidff->set_effect[PID_START_DELAY].value[0] = 0;
 
 	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index f6c4145..775b9f3 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -105,6 +105,9 @@
 #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
 #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
 
+#define USB_VENDOR_ID_GAMERON		0x0810
+#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
+
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
 #define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039
@@ -196,8 +199,10 @@
 #define USB_VENDOR_ID_LOGITECH		0x046d
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
 #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
+#define USB_DEVICE_ID_LOGITECH_KBD	0xc311
 #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
+#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
 #define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
 #define USB_DEVICE_ID_DINOVO_EDGE	0xc714
 
@@ -209,6 +214,13 @@
 #define USB_DEVICE_ID_MGE_UPS		0xffff
 #define USB_DEVICE_ID_MGE_UPS1		0x0001
 
+#define USB_VENDOR_ID_MICROSOFT		0x045e
+#define USB_DEVICE_ID_SIDEWINDER_GV	0x003b
+
+#define USB_VENDOR_ID_NCR		0x0404
+#define USB_DEVICE_ID_NCR_FIRST		0x0300
+#define USB_DEVICE_ID_NCR_LAST		0x03ff
+
 #define USB_VENDOR_ID_NEC		0x073e
 #define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
 
@@ -220,6 +232,9 @@
 #define USB_VENDOR_ID_PANTHERLORD	0x0810
 #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK	0x0001
 
+#define USB_VENDOR_ID_PETALYNX		0x18b1
+#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE	0x0037
+
 #define USB_VENDOR_ID_PLAYDOTCOM	0x0b43
 #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII	0x0003
 
@@ -278,6 +293,7 @@
 	{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -285,11 +301,10 @@
 	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
 	
-	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
-
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
 
 	{ USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
 
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
@@ -409,9 +424,7 @@
 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
 
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
 
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
 
@@ -426,6 +439,7 @@
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -448,9 +462,28 @@
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
 
 	{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
 
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
+	{ 0, 0 }
+};
+
+/* Quirks for devices which require report descriptor fixup go here */
+static const struct hid_rdesc_blacklist {
+	__u16 idVendor;
+	__u16 idProduct;
+	__u32 quirks;
+} hid_rdesc_blacklist[] = {
+
+	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
+
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
+
+	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
+
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
 
 	{ 0, 0 }
 };
@@ -493,7 +526,7 @@
 	}
 
 	if (bl_entry != NULL)
-		dbg("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+		dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
 				bl_entry->quirks, bl_entry->idVendor,
 				bl_entry->idProduct);
 
@@ -521,13 +554,13 @@
 	int list_edited = 0;
 
 	if (!idVendor) {
-		dbg("Cannot add a quirk with idVendor = 0");
+		dbg_hid("Cannot add a quirk with idVendor = 0\n");
 		return -EINVAL;
 	}
 
 	q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);
 	if (!q_new) {
-		dbg("Could not allocate quirks_list_struct");
+		dbg_hid("Could not allocate quirks_list_struct\n");
 		return -ENOMEM;
 	}
 
@@ -559,7 +592,6 @@
 	return 0;
 }
 
-
 /**
  * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
  *
@@ -643,7 +675,7 @@
 			bl_entry = &hid_blacklist[n];
 
 	if (bl_entry != NULL)
-		dbg("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+		dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
 				bl_entry->quirks, bl_entry->idVendor, 
 				bl_entry->idProduct);
 	return bl_entry;
@@ -675,6 +707,12 @@
 				idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
 			return HID_QUIRK_IGNORE;
 
+	/* NCR devices must not be queried for reports */
+	if (idVendor == USB_VENDOR_ID_NCR &&
+			idProduct >= USB_DEVICE_ID_NCR_FIRST &&
+			idProduct <= USB_DEVICE_ID_NCR_LAST)
+			return HID_QUIRK_NOGET;
+
 	down_read(&dquirks_rwsem);
 	bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
 	if (!bl_entry)
@@ -686,3 +724,126 @@
 	return quirks;
 }
 
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
+{
+	if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+		printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
+		rdesc[11] = rdesc[16] = 0xff;
+		rdesc[12] = rdesc[17] = 0x03;
+	}
+}
+
+
+/*
+ * Certain Logitech keyboards send in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
+{
+	if (rsize >= 90 && rdesc[83] == 0x26
+			&& rdesc[84] == 0x8c
+			&& rdesc[85] == 0x02) {
+		printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
+		rdesc[84] = rdesc[89] = 0x4d;
+		rdesc[85] = rdesc[90] = 0x10;
+	}
+}
+
+/* Petalynx Maxter Remote has maximum for consumer page set too low */
+static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
+{
+	if (rsize >= 60 && rdesc[39] == 0x2a
+			&& rdesc[40] == 0xf5
+			&& rdesc[41] == 0x00
+			&& rdesc[59] == 0x26
+			&& rdesc[60] == 0xf9
+			&& rdesc[61] == 0x00) {
+		printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
+		rdesc[60] = 0xfa;
+		rdesc[40] = 0xfa;
+	}
+}
+
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
+{
+	short fixed = 0;
+	int i;
+
+	for (i = 0; i < rsize - 4; i++) {
+		if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
+			unsigned char tmp;
+
+			rdesc[i] = 0x19; rdesc[i+2] = 0x29;
+			tmp = rdesc[i+3];
+			rdesc[i+3] = rdesc[i+1];
+			rdesc[i+1] = tmp;
+		}
+	}
+
+	if (fixed)
+		printk(KERN_INFO "Fixing up Cypress report descriptor\n");
+}
+
+
+static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+{
+	if ((quirks & HID_QUIRK_RDESC_CYMOTION))
+		usbhid_fixup_cymotion_descriptor(rdesc, rsize);
+
+	if (quirks & HID_QUIRK_RDESC_LOGITECH)
+		usbhid_fixup_logitech_descriptor(rdesc, rsize);
+
+	if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
+		usbhid_fixup_cypress_descriptor(rdesc, rsize);
+
+	if (quirks & HID_QUIRK_RDESC_PETALYNX)
+		usbhid_fixup_petalynx_descriptor(rdesc, rsize);
+}
+
+/**
+ * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
+ *
+ * Description:
+ *	Walks the hid_rdesc_blacklist[] array and checks whether the device
+ *	is known to have broken report descriptor that needs to be fixed up
+ *	prior to entering the HID parser
+ *
+ * Returns: nothing
+ */
+void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
+				    char *rdesc, unsigned rsize, char **quirks_param)
+{
+	int n, m;
+	u16 paramVendor, paramProduct;
+	u32 quirks;
+
+	/* static rdesc quirk entries */
+	for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
+		if (hid_rdesc_blacklist[n].idVendor == idVendor &&
+				hid_rdesc_blacklist[n].idProduct == idProduct)
+			__usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
+					rdesc, rsize);
+
+	/* runtime rdesc quirk entries handling */
+	for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
+		m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
+				&paramVendor, &paramProduct, &quirks);
+
+		if (m != 3)
+			printk(KERN_WARNING
+				"Could not parse HID quirk module param %s\n",
+				quirks_param[n]);
+		else if (paramVendor == idVendor && paramProduct == idProduct)
+			__usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
+	}
+
+}
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
index ab5ba6e..555bb48 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/usbhid/hid-tmff.c
@@ -70,7 +70,7 @@
 
 	tmff->rumble->value[0] = left;
 	tmff->rumble->value[1] = right;
-	dbg("(left,right)=(%08x, %08x)", left, right);
+	dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
 	usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
 
 	return 0;
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c
index a7fbffc..5a68827 100644
--- a/drivers/hid/usbhid/hid-zpff.c
+++ b/drivers/hid/usbhid/hid-zpff.c
@@ -21,10 +21,6 @@
  */
 
 
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg)
-
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
@@ -49,14 +45,14 @@
 
 	left = effect->u.rumble.strong_magnitude;
 	right = effect->u.rumble.weak_magnitude;
-	debug("called with 0x%04x 0x%04x", left, right);
+	dbg_hid("called with 0x%04x 0x%04x\n", left, right);
 
 	left = left * 0x7f / 0xffff;
 	right = right * 0x7f / 0xffff;
 
 	zpff->report->field[2]->value[0] = left;
 	zpff->report->field[3]->value[0] = right;
-	debug("running with 0x%02x 0x%02x", left, right);
+	dbg_hid("running with 0x%02x 0x%02x\n", left, right);
 	usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
 
 	return 0;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 488d61b..e793127 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -779,7 +779,7 @@
 
 	retval = usb_register_dev(usbhid->intf, &hiddev_class);
 	if (retval) {
-		err("Not able to get a minor for this device.");
+		err_hid("Not able to get a minor for this device.");
 		kfree(hiddev);
 		return -1;
 	}
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 1309787..b76b02f 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -125,7 +125,7 @@
 resubmit:
 	i = usb_submit_urb (urb, GFP_ATOMIC);
 	if (i)
-		err ("can't resubmit intr, %s-%s/input0, status %d",
+		err_hid ("can't resubmit intr, %s-%s/input0, status %d",
 				kbd->usbdev->bus->bus_name,
 				kbd->usbdev->devpath, i);
 }
@@ -151,7 +151,7 @@
 	*(kbd->leds) = kbd->newleds;
 	kbd->led->dev = kbd->usbdev;
 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err("usb_submit_urb(leds) failed");
+		err_hid("usb_submit_urb(leds) failed");
 
 	return 0;
 }
@@ -169,7 +169,7 @@
 	*(kbd->leds) = kbd->newleds;
 	kbd->led->dev = kbd->usbdev;
 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err("usb_submit_urb(leds) failed");
+		err_hid("usb_submit_urb(leds) failed");
 }
 
 static int usb_kbd_open(struct input_dev *dev)
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4d1cb5b..13eea47 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -620,7 +620,7 @@
 
 config SENSORS_APPLESMC
 	tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
-	depends on HWMON && INPUT && X86
+	depends on INPUT && X86
 	select NEW_LEDS
 	select LEDS_CLASS
 	default n
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 0c160675..fd1281f 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -491,6 +491,12 @@
 
 /* Sysfs Files */
 
+static ssize_t applesmc_name_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "applesmc\n");
+}
+
 static ssize_t applesmc_position_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
@@ -913,6 +919,8 @@
 	.brightness_set		= applesmc_brightness_set,
 };
 
+static DEVICE_ATTR(name, 0444, applesmc_name_show, NULL);
+
 static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL);
 static DEVICE_ATTR(calibrate, 0644,
 			applesmc_calibrate_show, applesmc_calibrate_store);
@@ -1197,10 +1205,14 @@
 		goto out_driver;
 	}
 
+	ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr);
+	if (ret)
+		goto out_device;
+
 	/* Create key enumeration sysfs files */
 	ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group);
 	if (ret)
-		goto out_device;
+		goto out_name;
 
 	/* create fan files */
 	count = applesmc_get_fan_count();
@@ -1300,6 +1312,8 @@
 	sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
 out_key_enumeration:
 	sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
+out_name:
+	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
 out_device:
 	platform_device_unregister(pdev);
 out_driver:
@@ -1325,6 +1339,7 @@
 	sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
 	sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
 	sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
+	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
 	platform_device_unregister(pdev);
 	platform_driver_unregister(&applesmc_driver);
 	release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 75e3911..6d54c8c 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -176,6 +176,23 @@
 		goto exit_free;
 	}
 
+	/* Check if we have problem with errata AE18 of Core processors:
+	   Readings might stop update when processor visited too deep sleep,
+	   fixed for stepping D0 (6EC).
+	*/
+
+	if ((c->x86_model == 0xe) && (c->x86_mask < 0xc)) {
+		/* check for microcode update */
+		rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx);
+		if (edx < 0x39) {
+			err = -ENODEV;
+			dev_err(&pdev->dev,
+				"Errata AE18 not fixed, update BIOS or "
+				"microcode of the CPU!\n");
+			goto exit_free;
+		}
+	}
+
 	/* Some processors have Tjmax 85 following magic should detect it
 	   Intel won't disclose the information without signed NDA, but
 	   individuals cannot sign it. Catch(ed) 22.
@@ -193,6 +210,19 @@
 		}
 	}
 
+	/* Intel says that above should not work for desktop Core2 processors,
+	   but it seems to work. There is no other way how get the absolute
+	   readings. Warn the user about this. First check if are desktop,
+	   bit 50 of MSR_IA32_PLATFORM_ID should be 0.
+	*/
+
+	rdmsr_safe_on_cpu(data->id, MSR_IA32_PLATFORM_ID, &eax, &edx);
+
+	if ((c->x86_model == 0xf) && (!(edx & 0x00040000))) {
+		dev_warn(&pdev->dev, "Using undocumented features, absolute "
+			 "temperature might be wrong!\n");
+	}
+
 	platform_set_drvdata(pdev, data);
 
 	if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
@@ -330,9 +360,6 @@
 	int i, err = -ENODEV;
 	struct pdev_entry *p, *n;
 
-	printk(KERN_NOTICE DRVNAME ": This driver uses undocumented features "
-		"of Core CPU. Temperature might be wrong!\n");
-
 	/* quick check if we run Intel */
 	if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL)
 		goto exit;
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index c849c0c..d5ac422 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -53,8 +53,8 @@
 
 /* The DS1621 registers */
 #define DS1621_REG_TEMP			0xAA /* word, RO */
-#define DS1621_REG_TEMP_MIN		0xA1 /* word, RW */
-#define DS1621_REG_TEMP_MAX		0xA2 /* word, RW */
+#define DS1621_REG_TEMP_MIN		0xA2 /* word, RW */
+#define DS1621_REG_TEMP_MAX		0xA1 /* word, RW */
 #define DS1621_REG_CONF			0xAC /* byte, RW */
 #define DS1621_COM_START		0xEE /* no data */
 #define DS1621_COM_STOP			0x22 /* no data */
@@ -328,9 +328,9 @@
 
 		/* reset alarms if necessary */
 		new_conf = data->conf;
-		if (data->temp < data->temp_min)
+		if (data->temp > data->temp_min)
 			new_conf &= ~DS1621_ALARM_TEMP_LOW;
-		if (data->temp > data->temp_max)
+		if (data->temp < data->temp_max)
 			new_conf &= ~DS1621_ALARM_TEMP_HIGH;
 		if (data->conf != new_conf)
 			ds1621_write_value(client, DS1621_REG_CONF,
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 5aab23b..f17e771 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -132,7 +132,9 @@
 		val &= 0x7f;
 		return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000);
 	default:		/* report 0 for unknown */
-		printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
+		if (vrm)
+			printk(KERN_WARNING "hwmon-vid: Requested unsupported "
+			       "VRM version (%u)\n", (unsigned int)vrm);
 		return 0;
 	}
 }
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 7eaae38..275d392 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -96,6 +96,10 @@
 	struct lm70 *p_lm70;
 	int status;
 
+	/* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */
+	if ((spi->mode & (SPI_CPOL|SPI_CPHA)) || !(spi->mode & SPI_3WIRE))
+		return -EINVAL;
+
 	p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL);
 	if (!p_lm70)
 		return -ENOMEM;
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index a5b774b..12cb40a 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -965,8 +965,10 @@
 	case W687THF_DEVID:
 		sio_data->type = w83687thf;
 		break;
+	case 0xff:	/* No device at all */
+		goto exit;
 	default:
-		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", val);
+		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val);
 		goto exit;
 	}
 
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index 5889907..014dfa5 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -34,10 +34,6 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-algo-pca.
 
-config I2C_ALGO8XX
-	tristate "MPC8xx CPM I2C interface"
-	depends on 8xx
-
 config I2C_ALGO_SGI
 	tristate "I2C SGI interfaces"
 	depends on SGI_IP22 || SGI_IP32 || X86_VISWS
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 838dc1c..1c77e14 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -207,6 +207,7 @@
 	    ATI IXP300
 	    ATI IXP400
 	    ATI SB600
+	    ATI SB700
 	    Serverworks OSB4
 	    Serverworks CSB5
 	    Serverworks CSB6
@@ -390,11 +391,6 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-prosavage.
 
-config I2C_RPXLITE
-	tristate "Embedded Planet RPX Lite/Classic support"
-	depends on RPXLITE || RPXCLASSIC
-	select I2C_ALGO8XX
-
 config I2C_S3C2410
 	tristate "S3C2410 I2C Driver"
 	depends on ARCH_S3C2410
@@ -512,6 +508,22 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-sis96x.
 
+config I2C_TAOS_EVM
+	tristate "TAOS evaluation module"
+	depends on EXPERIMENTAL
+	select SERIO
+	select SERIO_SERPORT
+	default n
+	help
+	  This supports TAOS evaluation modules on serial port. In order to
+	  use this driver, you will need the inputattach tool, which is part
+	  of the input-utils package.
+
+	  If unsure, say N.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-taos-evm.
+
 config I2C_STUB
 	tristate "I2C/SMBus Test Stub"
 	depends on EXPERIMENTAL && m
@@ -548,7 +560,7 @@
 	  will be called i2c-versatile.
 
 config I2C_ACORN
-	bool "Acorn IOC/IOMD I2C bus support"
+	tristate "Acorn IOC/IOMD I2C bus support"
 	depends on ARCH_ACORN
 	default y
 	select I2C_ALGOBIT
@@ -635,4 +647,13 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-pnx.
 
+config I2C_PMCMSP
+	tristate "PMC MSP I2C TWI Controller"
+	depends on PMC_MSP
+	help
+	  This driver supports the PMC TWI controller on MSP devices.
+
+	  This driver can also be built as module. If so, the module
+	  will be called i2c-pmcmsp.
+
 endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 14d1432..a6db4e3 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -32,10 +32,10 @@
 obj-$(CONFIG_I2C_PASEMI)	+= i2c-pasemi.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
+obj-$(CONFIG_I2C_PMCMSP)	+= i2c-pmcmsp.o
 obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o
 obj-$(CONFIG_I2C_PROSAVAGE)	+= i2c-prosavage.o
 obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o
-obj-$(CONFIG_I2C_RPXLITE)	+= i2c-rpx.o
 obj-$(CONFIG_I2C_S3C2410)	+= i2c-s3c2410.o
 obj-$(CONFIG_I2C_SAVAGE4)	+= i2c-savage4.o
 obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o
@@ -44,6 +44,7 @@
 obj-$(CONFIG_I2C_SIS630)	+= i2c-sis630.o
 obj-$(CONFIG_I2C_SIS96X)	+= i2c-sis96x.o
 obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o
+obj-$(CONFIG_I2C_TAOS_EVM)	+= i2c-taos-evm.o
 obj-$(CONFIG_I2C_TINY_USB)	+= i2c-tiny-usb.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_ACORN)		+= i2c-acorn.o
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 09bd7f4..7c2be35 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -94,4 +94,4 @@
 	return i2c_bit_add_bus(&ioc_ops);
 }
 
-__initcall(i2c_ioc_init);
+module_init(i2c_ioc_init);
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index a7dd546..025f194 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -63,14 +63,14 @@
 	gpio_set_value(pdata->scl_pin, state);
 }
 
-int i2c_gpio_getsda(void *data)
+static int i2c_gpio_getsda(void *data)
 {
 	struct i2c_gpio_platform_data *pdata = data;
 
 	return gpio_get_value(pdata->sda_pin);
 }
 
-int i2c_gpio_getscl(void *data)
+static int i2c_gpio_getscl(void *data)
 {
 	struct i2c_gpio_platform_data *pdata = data;
 
@@ -142,7 +142,13 @@
 	adap->algo_data = bit_data;
 	adap->dev.parent = &pdev->dev;
 
-	ret = i2c_bit_add_bus(adap);
+	/*
+	 * If "dev->id" is negative we consider it as zero.
+	 * The reason to do so is to avoid sysfs names that only make
+	 * sense when there are multiple adapters.
+	 */
+	adap->nr = pdev->id >= 0 ? pdev->id : 0;
+	ret = i2c_bit_add_numbered_bus(adap);
 	if (ret)
 		goto err_add_bus;
 
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 611b571..8f5c686 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -22,12 +22,12 @@
 
 /*
     SUPPORTED DEVICES	PCI ID
-    82801AA		2413           
-    82801AB		2423           
-    82801BA		2443           
-    82801CA/CAM		2483           
-    82801DB		24C3   (HW PEC supported, 32 byte buffer not supported)
-    82801EB		24D3   (HW PEC supported, 32 byte buffer not supported)
+    82801AA		2413
+    82801AB		2423
+    82801BA		2443
+    82801CA/CAM		2483
+    82801DB		24C3   (HW PEC supported)
+    82801EB		24D3   (HW PEC supported)
     6300ESB		25A4
     ICH6		266A
     ICH7		27DA
@@ -74,6 +74,13 @@
 #define SMBHSTCFG_SMB_SMI_EN	2
 #define SMBHSTCFG_I2C_EN	4
 
+/* Auxillary control register bits, ICH4+ only */
+#define SMBAUXCTL_CRC		1
+#define SMBAUXCTL_E32B		2
+
+/* kill bit for SMBHSTCNT */
+#define SMBHSTCNT_KILL		2
+
 /* Other settings */
 #define MAX_TIMEOUT		100
 #define ENABLE_INT9		0	/* set to 0x01 to enable - untested */
@@ -91,10 +98,15 @@
 #define I801_START		0x40
 #define I801_PEC_EN		0x80	/* ICH4 only */
 
-
-static int i801_transaction(void);
-static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
-				  int command, int hwpec);
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE	0x80
+#define SMBHSTSTS_INUSE_STS	0x40
+#define SMBHSTSTS_SMBALERT_STS	0x20
+#define SMBHSTSTS_FAILED	0x10
+#define SMBHSTSTS_BUS_ERR	0x08
+#define SMBHSTSTS_DEV_ERR	0x04
+#define SMBHSTSTS_INTR		0x02
+#define SMBHSTSTS_HOST_BUSY	0x01
 
 static unsigned long i801_smba;
 static unsigned char i801_original_hstcfg;
@@ -102,7 +114,7 @@
 static struct pci_dev *I801_dev;
 static int isich4;
 
-static int i801_transaction(void)
+static int i801_transaction(int xact)
 {
 	int temp;
 	int result = 0;
@@ -127,33 +139,40 @@
 		}
 	}
 
-	outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+	/* the current contents of SMBHSTCNT can be overwritten, since PEC,
+	 * INTREN, SMBSCMD are passed in xact */
+	outb_p(xact | I801_START, SMBHSTCNT);
 
 	/* We will always wait for a fraction of a second! */
 	do {
 		msleep(1);
 		temp = inb_p(SMBHSTSTS);
-	} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+	} while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
 
 	/* If the SMBus is still busy, we give up */
 	if (timeout >= MAX_TIMEOUT) {
 		dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
 		result = -1;
+		/* try to stop the current command */
+		dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
+		outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
+		msleep(1);
+		outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
 	}
 
-	if (temp & 0x10) {
+	if (temp & SMBHSTSTS_FAILED) {
 		result = -1;
 		dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
 	}
 
-	if (temp & 0x08) {
+	if (temp & SMBHSTSTS_BUS_ERR) {
 		result = -1;
 		dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
 			"until next hard reset. (sorry!)\n");
 		/* Clock stops and slave is stuck in mid-transmission */
 	}
 
-	if (temp & 0x04) {
+	if (temp & SMBHSTSTS_DEV_ERR) {
 		result = -1;
 		dev_dbg(&I801_dev->dev, "Error: no response!\n");
 	}
@@ -172,44 +191,70 @@
 	return result;
 }
 
-/* All-inclusive block transaction function */
-static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
-				  int command, int hwpec)
+/* wait for INTR bit as advised by Intel */
+static void i801_wait_hwpec(void)
+{
+	int timeout = 0;
+	int temp;
+
+	do {
+		msleep(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((!(temp & SMBHSTSTS_INTR))
+		 && (timeout++ < MAX_TIMEOUT));
+
+	if (timeout >= MAX_TIMEOUT) {
+		dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
+	}
+	outb_p(temp, SMBHSTSTS);
+}
+
+static int i801_block_transaction_by_block(union i2c_smbus_data *data,
+					   char read_write, int hwpec)
+{
+	int i, len;
+
+	inb_p(SMBHSTCNT); /* reset the data buffer index */
+
+	/* Use 32-byte buffer to process this transaction */
+	if (read_write == I2C_SMBUS_WRITE) {
+		len = data->block[0];
+		outb_p(len, SMBHSTDAT0);
+		for (i = 0; i < len; i++)
+			outb_p(data->block[i+1], SMBBLKDAT);
+	}
+
+	if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
+			     I801_PEC_EN * hwpec))
+		return -1;
+
+	if (read_write == I2C_SMBUS_READ) {
+		len = inb_p(SMBHSTDAT0);
+		if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+			return -1;
+
+		data->block[0] = len;
+		for (i = 0; i < len; i++)
+			data->block[i + 1] = inb_p(SMBBLKDAT);
+	}
+	return 0;
+}
+
+static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
+					       char read_write, int hwpec)
 {
 	int i, len;
 	int smbcmd;
 	int temp;
 	int result = 0;
 	int timeout;
-	unsigned char hostc, errmask;
+	unsigned char errmask;
 
-	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
-		if (read_write == I2C_SMBUS_WRITE) {
-			/* set I2C_EN bit in configuration register */
-			pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
-			pci_write_config_byte(I801_dev, SMBHSTCFG,
-					      hostc | SMBHSTCFG_I2C_EN);
-		} else {
-			dev_err(&I801_dev->dev,
-				"I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
-			return -1;
-		}
-	}
+	len = data->block[0];
 
 	if (read_write == I2C_SMBUS_WRITE) {
-		len = data->block[0];
-		if (len < 1)
-			len = 1;
-		if (len > 32)
-			len = 32;
 		outb_p(len, SMBHSTDAT0);
 		outb_p(data->block[1], SMBBLKDAT);
-	} else {
-		len = 32;	/* max for reads */
-	}
-
-	if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
-		/* set 32 byte buffer */
 	}
 
 	for (i = 1; i <= len; i++) {
@@ -227,13 +272,13 @@
 		/* Make sure the SMBus host is ready to start transmitting */
 		temp = inb_p(SMBHSTSTS);
 		if (i == 1) {
-			/* Erronenous conditions before transaction: 
+			/* Erronenous conditions before transaction:
 			 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
-			errmask=0x9f; 
+			errmask = 0x9f;
 		} else {
-			/* Erronenous conditions during transaction: 
+			/* Erronenous conditions during transaction:
 			 * Failed, Bus_Err, Dev_Err, Intr */
-			errmask=0x1e; 
+			errmask = 0x1e;
 		}
 		if (temp & errmask) {
 			dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
@@ -242,14 +287,11 @@
 			if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
 				dev_err(&I801_dev->dev,
 					"Reset failed! (%02x)\n", temp);
-				result = -1;
-                                goto END;
+				return -1;
 			}
-			if (i != 1) {
+			if (i != 1)
 				/* if die in middle of block transaction, fail */
-				result = -1;
-				goto END;
-			}
+				return -1;
 		}
 
 		if (i == 1)
@@ -261,33 +303,38 @@
 			msleep(1);
 			temp = inb_p(SMBHSTSTS);
 		}
-		    while ((!(temp & 0x80))
-			   && (timeout++ < MAX_TIMEOUT));
+		while ((!(temp & SMBHSTSTS_BYTE_DONE))
+		       && (timeout++ < MAX_TIMEOUT));
 
 		/* If the SMBus is still busy, we give up */
 		if (timeout >= MAX_TIMEOUT) {
+			/* try to stop the current command */
+			dev_dbg(&I801_dev->dev, "Terminating the current "
+						"operation\n");
+			outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
+			msleep(1);
+			outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
+				SMBHSTCNT);
 			result = -1;
 			dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
 		}
 
-		if (temp & 0x10) {
+		if (temp & SMBHSTSTS_FAILED) {
 			result = -1;
 			dev_dbg(&I801_dev->dev,
 				"Error: Failed bus transaction\n");
-		} else if (temp & 0x08) {
+		} else if (temp & SMBHSTSTS_BUS_ERR) {
 			result = -1;
 			dev_err(&I801_dev->dev, "Bus collision!\n");
-		} else if (temp & 0x04) {
+		} else if (temp & SMBHSTSTS_DEV_ERR) {
 			result = -1;
 			dev_dbg(&I801_dev->dev, "Error: no response!\n");
 		}
 
 		if (i == 1 && read_write == I2C_SMBUS_READ) {
 			len = inb_p(SMBHSTDAT0);
-			if (len < 1)
-				len = 1;
-			if (len > 32)
-				len = 32;
+			if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+				return -1;
 			data->block[0] = len;
 		}
 
@@ -310,25 +357,58 @@
 			inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
 
 		if (result < 0)
-			goto END;
+			return result;
 	}
+	return result;
+}
 
-	if (hwpec) {
-		/* wait for INTR bit as advised by Intel */
-		timeout = 0;
-		do {
-			msleep(1);
-			temp = inb_p(SMBHSTSTS);
-		} while ((!(temp & 0x02))
-			   && (timeout++ < MAX_TIMEOUT));
+static int i801_set_block_buffer_mode(void)
+{
+	outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
+	if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
+		return -1;
+	return 0;
+}
 
-		if (timeout >= MAX_TIMEOUT) {
-			dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
+/* Block transaction function */
+static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
+				  int command, int hwpec)
+{
+	int result = 0;
+	unsigned char hostc;
+
+	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+		if (read_write == I2C_SMBUS_WRITE) {
+			/* set I2C_EN bit in configuration register */
+			pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
+			pci_write_config_byte(I801_dev, SMBHSTCFG,
+					      hostc | SMBHSTCFG_I2C_EN);
+		} else {
+			dev_err(&I801_dev->dev,
+				"I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
+			return -1;
 		}
-		outb_p(temp, SMBHSTSTS); 
 	}
-	result = 0;
-END:
+
+	if (read_write == I2C_SMBUS_WRITE) {
+		if (data->block[0] < 1)
+			data->block[0] = 1;
+		if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+			data->block[0] = I2C_SMBUS_BLOCK_MAX;
+	} else {
+		data->block[0] = 32;	/* max for reads */
+	}
+
+	if (isich4 && i801_set_block_buffer_mode() == 0 )
+		result = i801_block_transaction_by_block(data, read_write,
+							 hwpec);
+	else
+		result = i801_block_transaction_byte_by_byte(data, read_write,
+							     hwpec);
+
+	if (result == 0 && hwpec)
+		i801_wait_hwpec();
+
 	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
 		/* restore saved configuration register value */
 		pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
@@ -393,19 +473,22 @@
 		return -1;
 	}
 
-	outb_p(hwpec, SMBAUXCTL);	/* enable/disable hardware PEC */
+	if (hwpec)	/* enable/disable hardware PEC */
+		outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
+	else
+		outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
 
 	if(block)
 		ret = i801_block_transaction(data, read_write, size, hwpec);
-	else {
-		outb_p(xact | ENABLE_INT9, SMBHSTCNT);
-		ret = i801_transaction();
-	}
+	else
+		ret = i801_transaction(xact | ENABLE_INT9);
 
 	/* Some BIOSes don't like it when PEC is enabled at reboot or resume
-	   time, so we forcibly disable it after every transaction. */
+	   time, so we forcibly disable it after every transaction. Turn off
+	   E32B for the same reason. */
 	if (hwpec)
-		outb_p(0, SMBAUXCTL);
+		outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
+		       SMBAUXCTL);
 
 	if(block)
 		return ret;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 90e2d93..440342b 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -491,6 +491,7 @@
 	new_adapter->id = I2C_HW_IOP3XX;
 	new_adapter->owner = THIS_MODULE;
 	new_adapter->dev.parent = &pdev->dev;
+	new_adapter->nr = pdev->id;
 
 	/*
 	 * Default values...should these come in from board code?
@@ -508,7 +509,7 @@
 	platform_set_drvdata(pdev, new_adapter);
 	new_adapter->algo_data = adapter_data;
 
-	i2c_add_adapter(new_adapter);
+	i2c_add_numbered_adapter(new_adapter);
 
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index c6b6898..851c3ed 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -74,6 +74,25 @@
 	return IRQ_HANDLED;
 }
 
+/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
+ * the bus, because it wants to send ACK.
+ * Following sequence of enabling/disabling and sending start/stop generates
+ * the pulse, so it's all OK.
+ */
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+	writeccr(i2c, 0);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
 	unsigned long orig_jiffies = jiffies;
@@ -153,6 +172,7 @@
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
 	writeccr(i2c, CCR_MEN);
+	writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +265,9 @@
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
 			pr_debug("I2C: timeout\n");
+			if (readb(i2c->base + MPC_I2C_SR) ==
+			    (CSR_MCF | CSR_MBB | CSR_RXAK))
+				mpc_i2c_fixup(i2c);
 			return -EIO;
 		}
 		schedule();
@@ -327,9 +350,10 @@
 	platform_set_drvdata(pdev, i2c);
 
 	i2c->adap = mpc_ops;
+	i2c->adap.nr = pdev->id;
 	i2c_set_adapdata(&i2c->adap, i2c);
 	i2c->adap.dev.parent = &pdev->dev;
-	if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
+	if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) {
 		printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
 		goto fail_add;
 	}
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index a55b333..251154a 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -527,6 +527,7 @@
 	drv_data->adapter.class = I2C_CLASS_HWMON;
 	drv_data->adapter.timeout = pdata->timeout;
 	drv_data->adapter.retries = pdata->retries;
+	drv_data->adapter.nr = pd->id;
 	platform_set_drvdata(pd, drv_data);
 	i2c_set_adapdata(&drv_data->adapter, drv_data);
 
@@ -539,7 +540,7 @@
 			drv_data->irq);
 		rc = -EINVAL;
 		goto exit_unmap_regs;
-	} else if ((rc = i2c_add_adapter(&drv_data->adapter)) != 0) {
+	} else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) {
 		dev_err(&drv_data->adapter.dev,
 			"mv64xxx: Can't add i2c adapter, rc: %d\n", -rc);
 		goto exit_free_irq;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 3cd0d63..c48140f 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -61,6 +61,7 @@
 	struct i2c_adapter adapter;
 	int base;
 	int size;
+	int blockops;
 };
 
 
@@ -80,6 +81,8 @@
 #define NVIDIA_SMB_ADDR		(smbus->base + 0x02)	/* address */
 #define NVIDIA_SMB_CMD		(smbus->base + 0x03)	/* command */
 #define NVIDIA_SMB_DATA		(smbus->base + 0x04)	/* 32 data registers */
+#define NVIDIA_SMB_BCNT		(smbus->base + 0x24)	/* number of data
+							   bytes */
 
 #define NVIDIA_SMB_STS_DONE	0x80
 #define NVIDIA_SMB_STS_ALRM	0x40
@@ -92,6 +95,7 @@
 #define NVIDIA_SMB_PRTCL_BYTE			0x04
 #define NVIDIA_SMB_PRTCL_BYTE_DATA		0x06
 #define NVIDIA_SMB_PRTCL_WORD_DATA		0x08
+#define NVIDIA_SMB_PRTCL_BLOCK_DATA		0x0a
 #define NVIDIA_SMB_PRTCL_PEC			0x80
 
 static struct pci_driver nforce2_driver;
@@ -103,6 +107,8 @@
 {
 	struct nforce2_smbus *smbus = adap->algo_data;
 	unsigned char protocol, pec, temp;
+	u8 len;
+	int i;
 
 	protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
 		NVIDIA_SMB_PRTCL_WRITE;
@@ -137,6 +143,25 @@
 			protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
 			break;
 
+		case I2C_SMBUS_BLOCK_DATA:
+			outb_p(command, NVIDIA_SMB_CMD);
+			if (read_write == I2C_SMBUS_WRITE) {
+				len = data->block[0];
+				if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
+					dev_err(&adap->dev,
+						"Transaction failed "
+						"(requested block size: %d)\n",
+						len);
+					return -1;
+				}
+				outb_p(len, NVIDIA_SMB_BCNT);
+				for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
+					outb_p(data->block[i + 1],
+					       NVIDIA_SMB_DATA+i);
+			}
+			protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
+			break;
+
 		default:
 			dev_err(&adap->dev, "Unsupported transaction %d\n", size);
 			return -1;
@@ -174,6 +199,14 @@
 		case I2C_SMBUS_WORD_DATA:
 			data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8);
 			break;
+
+		case I2C_SMBUS_BLOCK_DATA:
+			len = inb_p(NVIDIA_SMB_BCNT);
+			len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
+			for (i = 0; i < len; i++)
+				data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
+			data->block[0] = len;
+			break;
 	}
 
 	return 0;
@@ -184,7 +217,9 @@
 {
 	/* other functionality might be possible, but is not tested */
 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
-	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
+	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	       (((struct nforce2_smbus*)adapter->algo_data)->blockops ?
+		I2C_FUNC_SMBUS_BLOCK_DATA : 0);
 }
 
 static struct i2c_algorithm smbus_algorithm = {
@@ -268,6 +303,13 @@
 		return -ENOMEM;
 	pci_set_drvdata(dev, smbuses);
 
+	switch(dev->device) {
+	case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS:
+	case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS:
+		smbuses[0].blockops = 1;
+		smbuses[1].blockops = 1;
+	}
+
 	/* SMBus adapter 1 */
 	res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
 	if (res1 < 0) {
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 5a52bf5e..debc76c 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -23,7 +23,7 @@
    Supports:
 	Intel PIIX4, 440MX
 	Serverworks OSB4, CSB5, CSB6, HT-1000
-	ATI IXP200, IXP300, IXP400, SB600
+	ATI IXP200, IXP300, IXP400, SB600, SB700
 	SMSC Victory66
 
    Note: we assume there can only be one device, with one SMBus interface.
@@ -399,6 +399,8 @@
 	  .driver_data = 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SMBUS),
 	  .driver_data = 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SMBUS),
+	  .driver_data = 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
 	  .driver_data = 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
new file mode 100644
index 0000000..17cecf1
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -0,0 +1,653 @@
+/*
+ * Specific bus support for PMC-TWI compliant implementation on MSP71xx.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#define DRV_NAME	"pmcmsptwi"
+
+#define MSP_TWI_SF_CLK_REG_OFFSET	0x00
+#define MSP_TWI_HS_CLK_REG_OFFSET	0x04
+#define MSP_TWI_CFG_REG_OFFSET		0x08
+#define MSP_TWI_CMD_REG_OFFSET		0x0c
+#define MSP_TWI_ADD_REG_OFFSET		0x10
+#define MSP_TWI_DAT_0_REG_OFFSET	0x14
+#define MSP_TWI_DAT_1_REG_OFFSET	0x18
+#define MSP_TWI_INT_STS_REG_OFFSET	0x1c
+#define MSP_TWI_INT_MSK_REG_OFFSET	0x20
+#define MSP_TWI_BUSY_REG_OFFSET		0x24
+
+#define MSP_TWI_INT_STS_DONE			(1 << 0)
+#define MSP_TWI_INT_STS_LOST_ARBITRATION	(1 << 1)
+#define MSP_TWI_INT_STS_NO_RESPONSE		(1 << 2)
+#define MSP_TWI_INT_STS_DATA_COLLISION		(1 << 3)
+#define MSP_TWI_INT_STS_BUSY			(1 << 4)
+#define MSP_TWI_INT_STS_ALL			0x1f
+
+#define MSP_MAX_BYTES_PER_RW		8
+#define MSP_MAX_POLL			5
+#define MSP_POLL_DELAY			10
+#define MSP_IRQ_TIMEOUT			(MSP_MAX_POLL * MSP_POLL_DELAY)
+
+/* IO Operation macros */
+#define pmcmsptwi_readl		__raw_readl
+#define pmcmsptwi_writel	__raw_writel
+
+/* TWI command type */
+enum pmcmsptwi_cmd_type {
+	MSP_TWI_CMD_WRITE	= 0,	/* Write only */
+	MSP_TWI_CMD_READ	= 1,	/* Read only */
+	MSP_TWI_CMD_WRITE_READ	= 2,	/* Write then Read */
+};
+
+/* The possible results of the xferCmd */
+enum pmcmsptwi_xfer_result {
+	MSP_TWI_XFER_OK	= 0,
+	MSP_TWI_XFER_TIMEOUT,
+	MSP_TWI_XFER_BUSY,
+	MSP_TWI_XFER_DATA_COLLISION,
+	MSP_TWI_XFER_NO_RESPONSE,
+	MSP_TWI_XFER_LOST_ARBITRATION,
+};
+
+/* Corresponds to a PMCTWI clock configuration register */
+struct pmcmsptwi_clock {
+	u8 filter;	/* Bits 15:12,	default = 0x03 */
+	u16 clock;	/* Bits 9:0,	default = 0x001f */
+};
+
+struct pmcmsptwi_clockcfg {
+	struct pmcmsptwi_clock standard;  /* The standard/fast clock config */
+	struct pmcmsptwi_clock highspeed; /* The highspeed clock config */
+};
+
+/* Corresponds to the main TWI configuration register */
+struct pmcmsptwi_cfg {
+	u8 arbf;	/* Bits 15:12,	default=0x03 */
+	u8 nak;		/* Bits 11:8,	default=0x03 */
+	u8 add10;	/* Bit 7,	default=0x00 */
+	u8 mst_code;	/* Bits 6:4,	default=0x00 */
+	u8 arb;		/* Bit 1,	default=0x01 */
+	u8 highspeed;	/* Bit 0,	default=0x00 */
+};
+
+/* A single pmctwi command to issue */
+struct pmcmsptwi_cmd {
+	u16 addr;	/* The slave address (7 or 10 bits) */
+	enum pmcmsptwi_cmd_type type;	/* The command type */
+	u8 write_len;	/* Number of bytes in the write buffer */
+	u8 read_len;	/* Number of bytes in the read buffer */
+	u8 *write_data;	/* Buffer of characters to send */
+	u8 *read_data;	/* Buffer to fill with incoming data */
+};
+
+/* The private data */
+struct pmcmsptwi_data {
+	void __iomem *iobase;			/* iomapped base for IO */
+	int irq;				/* IRQ to use (0 disables) */
+	struct completion wait;			/* Completion for xfer */
+	struct mutex lock;			/* Used for threadsafeness */
+	enum pmcmsptwi_xfer_result last_result;	/* result of last xfer */
+};
+
+/* The default settings */
+const static struct pmcmsptwi_clockcfg pmcmsptwi_defclockcfg = {
+	.standard = {
+		.filter	= 0x3,
+		.clock	= 0x1f,
+	},
+	.highspeed = {
+		.filter	= 0x3,
+		.clock	= 0x1f,
+	},
+};
+
+const static struct pmcmsptwi_cfg pmcmsptwi_defcfg = {
+	.arbf		= 0x03,
+	.nak		= 0x03,
+	.add10		= 0x00,
+	.mst_code	= 0x00,
+	.arb		= 0x01,
+	.highspeed	= 0x00,
+};
+
+static struct pmcmsptwi_data pmcmsptwi_data;
+
+static struct i2c_adapter pmcmsptwi_adapter;
+
+/* inline helper functions */
+static inline u32 pmcmsptwi_clock_to_reg(
+			const struct pmcmsptwi_clock *clock)
+{
+	return ((clock->filter & 0xf) << 12) | (clock->clock & 0x03ff);
+}
+
+static inline void pmcmsptwi_reg_to_clock(
+			u32 reg, struct pmcmsptwi_clock *clock)
+{
+	clock->filter = (reg >> 12) & 0xf;
+	clock->clock = reg & 0x03ff;
+}
+
+static inline u32 pmcmsptwi_cfg_to_reg(const struct pmcmsptwi_cfg *cfg)
+{
+	return ((cfg->arbf & 0xf) << 12) |
+		((cfg->nak & 0xf) << 8) |
+		((cfg->add10 & 0x1) << 7) |
+		((cfg->mst_code & 0x7) << 4) |
+		((cfg->arb & 0x1) << 1) |
+		(cfg->highspeed & 0x1);
+}
+
+static inline void pmcmsptwi_reg_to_cfg(u32 reg, struct pmcmsptwi_cfg *cfg)
+{
+	cfg->arbf = (reg >> 12) & 0xf;
+	cfg->nak = (reg >> 8) & 0xf;
+	cfg->add10 = (reg >> 7) & 0x1;
+	cfg->mst_code = (reg >> 4) & 0x7;
+	cfg->arb = (reg >> 1) & 0x1;
+	cfg->highspeed = reg & 0x1;
+}
+
+/*
+ * Sets the current clock configuration
+ */
+static void pmcmsptwi_set_clock_config(const struct pmcmsptwi_clockcfg *cfg,
+					struct pmcmsptwi_data *data)
+{
+	mutex_lock(&data->lock);
+	pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->standard),
+				data->iobase + MSP_TWI_SF_CLK_REG_OFFSET);
+	pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->highspeed),
+				data->iobase + MSP_TWI_HS_CLK_REG_OFFSET);
+	mutex_unlock(&data->lock);
+}
+
+/*
+ * Gets the current TWI bus configuration
+ */
+static void pmcmsptwi_get_twi_config(struct pmcmsptwi_cfg *cfg,
+					struct pmcmsptwi_data *data)
+{
+	mutex_lock(&data->lock);
+	pmcmsptwi_reg_to_cfg(pmcmsptwi_readl(
+				data->iobase + MSP_TWI_CFG_REG_OFFSET), cfg);
+	mutex_unlock(&data->lock);
+}
+
+/*
+ * Sets the current TWI bus configuration
+ */
+static void pmcmsptwi_set_twi_config(const struct pmcmsptwi_cfg *cfg,
+					struct pmcmsptwi_data *data)
+{
+	mutex_lock(&data->lock);
+	pmcmsptwi_writel(pmcmsptwi_cfg_to_reg(cfg),
+				data->iobase + MSP_TWI_CFG_REG_OFFSET);
+	mutex_unlock(&data->lock);
+}
+
+/*
+ * Parses the 'int_sts' register and returns a well-defined error code
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_get_result(u32 reg)
+{
+	if (reg & MSP_TWI_INT_STS_LOST_ARBITRATION) {
+		dev_dbg(&pmcmsptwi_adapter.dev,
+			"Result: Lost arbitration\n");
+		return MSP_TWI_XFER_LOST_ARBITRATION;
+	} else if (reg & MSP_TWI_INT_STS_NO_RESPONSE) {
+		dev_dbg(&pmcmsptwi_adapter.dev,
+			"Result: No response\n");
+		return MSP_TWI_XFER_NO_RESPONSE;
+	} else if (reg & MSP_TWI_INT_STS_DATA_COLLISION) {
+		dev_dbg(&pmcmsptwi_adapter.dev,
+			"Result: Data collision\n");
+		return MSP_TWI_XFER_DATA_COLLISION;
+	} else if (reg & MSP_TWI_INT_STS_BUSY) {
+		dev_dbg(&pmcmsptwi_adapter.dev,
+			"Result: Bus busy\n");
+		return MSP_TWI_XFER_BUSY;
+	}
+
+	dev_dbg(&pmcmsptwi_adapter.dev, "Result: Operation succeeded\n");
+	return MSP_TWI_XFER_OK;
+}
+
+/*
+ * In interrupt mode, handle the interrupt.
+ * NOTE: Assumes data->lock is held.
+ */
+static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr)
+{
+	struct pmcmsptwi_data *data = ptr;
+
+	u32 reason = pmcmsptwi_readl(data->iobase +
+					MSP_TWI_INT_STS_REG_OFFSET);
+	pmcmsptwi_writel(reason, data->iobase + MSP_TWI_INT_STS_REG_OFFSET);
+
+	dev_dbg(&pmcmsptwi_adapter.dev, "Got interrupt 0x%08x\n", reason);
+	if (!(reason & MSP_TWI_INT_STS_DONE))
+		return IRQ_NONE;
+
+	data->last_result = pmcmsptwi_get_result(reason);
+	complete(&data->wait);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Probe for and register the device and return 0 if there is one.
+ */
+static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
+{
+	struct resource *res;
+	int rc = -ENODEV;
+
+	/* get the static platform resources */
+	res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pldev->dev, "IOMEM resource not found\n");
+		goto ret_err;
+	}
+
+	/* reserve the memory region */
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+				pldev->name)) {
+		dev_err(&pldev->dev,
+			"Unable to get memory/io address region 0x%08x\n",
+			res->start);
+		rc = -EBUSY;
+		goto ret_err;
+	}
+
+	/* remap the memory */
+	pmcmsptwi_data.iobase = ioremap_nocache(res->start,
+						res->end - res->start + 1);
+	if (!pmcmsptwi_data.iobase) {
+		dev_err(&pldev->dev,
+			"Unable to ioremap address 0x%08x\n", res->start);
+		rc = -EIO;
+		goto ret_unreserve;
+	}
+
+	/* request the irq */
+	pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
+	if (pmcmsptwi_data.irq) {
+		rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
+			IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+			pldev->name, &pmcmsptwi_data);
+		if (rc == 0) {
+			/*
+			 * Enable 'DONE' interrupt only.
+			 *
+			 * If you enable all interrupts, you will get one on
+			 * error and another when the operation completes.
+			 * This way you only have to handle one interrupt,
+			 * but you can still check all result flags.
+			 */
+			pmcmsptwi_writel(MSP_TWI_INT_STS_DONE,
+					pmcmsptwi_data.iobase +
+					MSP_TWI_INT_MSK_REG_OFFSET);
+		} else {
+			dev_warn(&pldev->dev,
+				"Could not assign TWI IRQ handler "
+				"to irq %d (continuing with poll)\n",
+				pmcmsptwi_data.irq);
+			pmcmsptwi_data.irq = 0;
+		}
+	}
+
+	init_completion(&pmcmsptwi_data.wait);
+	mutex_init(&pmcmsptwi_data.lock);
+
+	pmcmsptwi_set_clock_config(&pmcmsptwi_defclockcfg, &pmcmsptwi_data);
+	pmcmsptwi_set_twi_config(&pmcmsptwi_defcfg, &pmcmsptwi_data);
+
+	printk(KERN_INFO DRV_NAME ": Registering MSP71xx I2C adapter\n");
+
+	pmcmsptwi_adapter.dev.parent = &pldev->dev;
+	platform_set_drvdata(pldev, &pmcmsptwi_adapter);
+	i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
+
+	rc = i2c_add_adapter(&pmcmsptwi_adapter);
+	if (rc) {
+		dev_err(&pldev->dev, "Unable to register I2C adapter\n");
+		goto ret_unmap;
+	}
+
+	return 0;
+
+ret_unmap:
+	platform_set_drvdata(pldev, NULL);
+	if (pmcmsptwi_data.irq) {
+		pmcmsptwi_writel(0,
+			pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
+		free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
+	}
+
+	iounmap(pmcmsptwi_data.iobase);
+
+ret_unreserve:
+	release_mem_region(res->start, res->end - res->start + 1);
+
+ret_err:
+	return rc;
+}
+
+/*
+ * Release the device and return 0 if there is one.
+ */
+static int __devexit pmcmsptwi_remove(struct platform_device *pldev)
+{
+	struct resource *res;
+
+	i2c_del_adapter(&pmcmsptwi_adapter);
+
+	platform_set_drvdata(pldev, NULL);
+	if (pmcmsptwi_data.irq) {
+		pmcmsptwi_writel(0,
+			pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
+		free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
+	}
+
+	iounmap(pmcmsptwi_data.iobase);
+
+	res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start + 1);
+
+	return 0;
+}
+
+/*
+ * Polls the 'busy' register until the command is complete.
+ * NOTE: Assumes data->lock is held.
+ */
+static void pmcmsptwi_poll_complete(struct pmcmsptwi_data *data)
+{
+	int i;
+
+	for (i = 0; i < MSP_MAX_POLL; i++) {
+		u32 val = pmcmsptwi_readl(data->iobase +
+						MSP_TWI_BUSY_REG_OFFSET);
+		if (val == 0) {
+			u32 reason = pmcmsptwi_readl(data->iobase +
+						MSP_TWI_INT_STS_REG_OFFSET);
+			pmcmsptwi_writel(reason, data->iobase +
+						MSP_TWI_INT_STS_REG_OFFSET);
+			data->last_result = pmcmsptwi_get_result(reason);
+			return;
+		}
+		udelay(MSP_POLL_DELAY);
+	}
+
+	dev_dbg(&pmcmsptwi_adapter.dev, "Result: Poll timeout\n");
+	data->last_result = MSP_TWI_XFER_TIMEOUT;
+}
+
+/*
+ * Do the transfer (low level):
+ *   May use interrupt-driven or polling, depending on if an IRQ is
+ *   presently registered.
+ * NOTE: Assumes data->lock is held.
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_do_xfer(
+			u32 reg, struct pmcmsptwi_data *data)
+{
+	dev_dbg(&pmcmsptwi_adapter.dev, "Writing cmd reg 0x%08x\n", reg);
+	pmcmsptwi_writel(reg, data->iobase + MSP_TWI_CMD_REG_OFFSET);
+	if (data->irq) {
+		unsigned long timeleft = wait_for_completion_timeout(
+						&data->wait, MSP_IRQ_TIMEOUT);
+		if (timeleft == 0) {
+			dev_dbg(&pmcmsptwi_adapter.dev,
+				"Result: IRQ timeout\n");
+			complete(&data->wait);
+			data->last_result = MSP_TWI_XFER_TIMEOUT;
+		}
+	} else
+		pmcmsptwi_poll_complete(data);
+
+	return data->last_result;
+}
+
+/*
+ * Helper routine, converts 'pmctwi_cmd' struct to register format
+ */
+static inline u32 pmcmsptwi_cmd_to_reg(const struct pmcmsptwi_cmd *cmd)
+{
+	return ((cmd->type & 0x3) << 8) |
+		(((cmd->write_len - 1) & 0x7) << 4) |
+		((cmd->read_len - 1) & 0x7);
+}
+
+/*
+ * Do the transfer (high level)
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
+			struct pmcmsptwi_cmd *cmd,
+			struct pmcmsptwi_data *data)
+{
+	enum pmcmsptwi_xfer_result retval;
+
+	if ((cmd->type == MSP_TWI_CMD_WRITE && cmd->write_len == 0) ||
+	    (cmd->type == MSP_TWI_CMD_READ && cmd->read_len == 0) ||
+	    (cmd->type == MSP_TWI_CMD_WRITE_READ &&
+	    (cmd->read_len == 0 || cmd->write_len == 0))) {
+		dev_err(&pmcmsptwi_adapter.dev,
+			"%s: Cannot transfer less than 1 byte\n",
+			__FUNCTION__);
+		return -EINVAL;
+	}
+
+	if (cmd->read_len > MSP_MAX_BYTES_PER_RW ||
+	    cmd->write_len > MSP_MAX_BYTES_PER_RW) {
+		dev_err(&pmcmsptwi_adapter.dev,
+			"%s: Cannot transfer more than %d bytes\n",
+			__FUNCTION__, MSP_MAX_BYTES_PER_RW);
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->lock);
+	dev_dbg(&pmcmsptwi_adapter.dev,
+		"Setting address to 0x%04x\n", cmd->addr);
+	pmcmsptwi_writel(cmd->addr, data->iobase + MSP_TWI_ADD_REG_OFFSET);
+
+	if (cmd->type == MSP_TWI_CMD_WRITE ||
+	    cmd->type == MSP_TWI_CMD_WRITE_READ) {
+		__be64 tmp = cpu_to_be64p((u64 *)cmd->write_data);
+		tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8;
+		dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp);
+		pmcmsptwi_writel(tmp & 0x00000000ffffffffLL,
+				data->iobase + MSP_TWI_DAT_0_REG_OFFSET);
+		if (cmd->write_len > 4)
+			pmcmsptwi_writel(tmp >> 32,
+				data->iobase + MSP_TWI_DAT_1_REG_OFFSET);
+	}
+
+	retval = pmcmsptwi_do_xfer(pmcmsptwi_cmd_to_reg(cmd), data);
+	if (retval != MSP_TWI_XFER_OK)
+		goto xfer_err;
+
+	if (cmd->type == MSP_TWI_CMD_READ ||
+	    cmd->type == MSP_TWI_CMD_WRITE_READ) {
+		int i;
+		u64 rmsk = ~(0xffffffffffffffffLL << (cmd->read_len * 8));
+		u64 tmp = (u64)pmcmsptwi_readl(data->iobase +
+					MSP_TWI_DAT_0_REG_OFFSET);
+		if (cmd->read_len > 4)
+			tmp |= (u64)pmcmsptwi_readl(data->iobase +
+					MSP_TWI_DAT_1_REG_OFFSET) << 32;
+		tmp &= rmsk;
+		dev_dbg(&pmcmsptwi_adapter.dev, "Read 0x%016llx\n", tmp);
+
+		for (i = 0; i < cmd->read_len; i++)
+			cmd->read_data[i] = tmp >> i;
+	}
+
+xfer_err:
+	mutex_unlock(&data->lock);
+
+	return retval;
+}
+
+/* -- Algorithm functions -- */
+
+/*
+ * Sends an i2c command out on the adapter
+ */
+static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
+				struct i2c_msg *msg, int num)
+{
+	struct pmcmsptwi_data *data = i2c_get_adapdata(adap);
+	struct pmcmsptwi_cmd cmd;
+	struct pmcmsptwi_cfg oldcfg, newcfg;
+	int ret;
+
+	if (num > 2) {
+		dev_dbg(&adap->dev, "%d messages unsupported\n", num);
+		return -EINVAL;
+	} else if (num == 2) {
+		/* Check for a dual write-then-read command */
+		struct i2c_msg *nextmsg = msg + 1;
+		if (!(msg->flags & I2C_M_RD) &&
+		    (nextmsg->flags & I2C_M_RD) &&
+		    msg->addr == nextmsg->addr) {
+			cmd.type = MSP_TWI_CMD_WRITE_READ;
+			cmd.write_len = msg->len;
+			cmd.write_data = msg->buf;
+			cmd.read_len = nextmsg->len;
+			cmd.read_data = nextmsg->buf;
+		} else {
+			dev_dbg(&adap->dev,
+				"Non write-read dual messages unsupported\n");
+			return -EINVAL;
+		}
+	} else if (msg->flags & I2C_M_RD) {
+		cmd.type = MSP_TWI_CMD_READ;
+		cmd.read_len = msg->len;
+		cmd.read_data = msg->buf;
+		cmd.write_len = 0;
+		cmd.write_data = NULL;
+	} else {
+		cmd.type = MSP_TWI_CMD_WRITE;
+		cmd.read_len = 0;
+		cmd.read_data = NULL;
+		cmd.write_len = msg->len;
+		cmd.write_data = msg->buf;
+	}
+
+	if (msg->len == 0) {
+		dev_err(&adap->dev, "Zero-byte messages unsupported\n");
+		return -EINVAL;
+	}
+
+	cmd.addr = msg->addr;
+
+	if (msg->flags & I2C_M_TEN) {
+		pmcmsptwi_get_twi_config(&newcfg, data);
+		memcpy(&oldcfg, &newcfg, sizeof(oldcfg));
+
+		/* Set the special 10-bit address flag */
+		newcfg.add10 = 1;
+
+		pmcmsptwi_set_twi_config(&newcfg, data);
+	}
+
+	/* Execute the command */
+	ret = pmcmsptwi_xfer_cmd(&cmd, data);
+
+	if (msg->flags & I2C_M_TEN)
+		pmcmsptwi_set_twi_config(&oldcfg, data);
+
+	dev_dbg(&adap->dev, "I2C %s of %d bytes ",
+		(msg->flags & I2C_M_RD) ? "read" : "write", msg->len);
+	if (ret != MSP_TWI_XFER_OK) {
+		/*
+		 * TODO: We could potentially loop and retry in the case
+		 * of MSP_TWI_XFER_TIMEOUT.
+		 */
+		dev_dbg(&adap->dev, "failed\n");
+		return -1;
+	}
+
+	dev_dbg(&adap->dev, "succeeded\n");
+	return 0;
+}
+
+static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
+		I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL;
+}
+
+/* -- Initialization -- */
+
+static struct i2c_algorithm pmcmsptwi_algo = {
+	.master_xfer	= pmcmsptwi_master_xfer,
+	.functionality	= pmcmsptwi_i2c_func,
+};
+
+static struct i2c_adapter pmcmsptwi_adapter = {
+	.owner		= THIS_MODULE,
+	.class		= I2C_CLASS_HWMON,
+	.algo		= &pmcmsptwi_algo,
+	.name		= DRV_NAME,
+};
+
+static struct platform_driver pmcmsptwi_driver = {
+	.probe  = pmcmsptwi_probe,
+	.remove	= __devexit_p(pmcmsptwi_remove),
+	.driver = {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init pmcmsptwi_init(void)
+{
+	return platform_driver_register(&pmcmsptwi_driver);
+}
+
+static void __exit pmcmsptwi_exit(void)
+{
+	platform_driver_unregister(&pmcmsptwi_driver);
+}
+
+MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver");
+MODULE_LICENSE("GPL");
+
+module_init(pmcmsptwi_init);
+module_exit(pmcmsptwi_exit);
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 1425d224..0ab4f26 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -121,8 +121,7 @@
 		if (rc)
 			goto bail;
 		rc = pmac_i2c_xfer(bus, addrdir, 1, command,
-				   read ? data->block : &data->block[1],
-				   data->block[0]);
+				   &data->block[1], data->block[0]);
 		break;
 
         default:
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 8a0a99b..9d6b790 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -837,20 +837,10 @@
 	.functionality	= i2c_pxa_functionality,
 };
 
-static struct pxa_i2c i2c_pxa = {
-	.lock	= __SPIN_LOCK_UNLOCKED(i2c_pxa.lock),
-	.adap	= {
-		.owner		= THIS_MODULE,
-		.algo		= &i2c_pxa_algorithm,
-		.name		= "pxa2xx-i2c.0",
-		.retries	= 5,
-	},
-};
-
 #define res_len(r)		((r)->end - (r)->start + 1)
 static int i2c_pxa_probe(struct platform_device *dev)
 {
-	struct pxa_i2c *i2c = &i2c_pxa;
+	struct pxa_i2c *i2c;
 	struct resource *res;
 	struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
 	int ret;
@@ -864,15 +854,20 @@
 	if (!request_mem_region(res->start, res_len(res), res->name))
 		return -ENOMEM;
 
-	i2c = kmalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
+	i2c = kzalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
 	if (!i2c) {
 		ret = -ENOMEM;
 		goto emalloc;
 	}
 
-	memcpy(i2c, &i2c_pxa, sizeof(struct pxa_i2c));
+	i2c->adap.owner   = THIS_MODULE;
+	i2c->adap.algo    = &i2c_pxa_algorithm;
+	i2c->adap.retries = 5;
+
+	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
-	i2c->adap.name[strlen(i2c->adap.name) - 1] = '0' + dev->id % 10;
+
+	sprintf(i2c->adap.name, "pxa_i2c-i2c.%u", dev->id);
 
 	i2c->reg_base = ioremap(res->start, res_len(res));
 	if (!i2c->reg_base) {
@@ -926,7 +921,14 @@
 		i2c->adap.class = plat->class;
 	}
 
-	ret = i2c_add_adapter(&i2c->adap);
+	/*
+	 * If "dev->id" is negative we consider it as zero.
+	 * The reason to do so is to avoid sysfs names that only make
+	 * sense when there are multiple adapters.
+	 */
+	i2c->adap.nr = dev->id >= 0 ? dev->id : 0;
+
+	ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
 		printk(KERN_INFO "I2C: Failed to add bus\n");
 		goto eadapt;
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c
deleted file mode 100644
index 8764df0..0000000
--- a/drivers/i2c/busses/i2c-rpx.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Embedded Planet RPX Lite MPC8xx CPM I2C interface.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
- *
- * moved into proper i2c interface;
- * Brad Parker (brad@heeltoe.com)
- *
- * RPX lite specific parts of the i2c interface
- * Update:  There actually isn't anything RPXLite-specific about this module.
- * This should work for most any 8xx board.  The console messages have been 
- * changed to eliminate RPXLite references.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/stddef.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-8xx.h>
-#include <asm/mpc8xx.h>
-#include <asm/commproc.h>
-
-
-static void
-rpx_iic_init(struct i2c_algo_8xx_data *data)
-{
-	volatile cpm8xx_t *cp;
-	volatile immap_t *immap;
-
-	cp = cpmp;	/* Get pointer to Communication Processor */
-	immap = (immap_t *)IMAP_ADDR;	/* and to internal registers */
-
-	data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
-
-	/* Check for and use a microcode relocation patch.
-	*/
-	if ((data->reloc = data->iip->iic_rpbase))
-		data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase];
-		
-	data->i2c = (i2c8xx_t *)&(immap->im_i2c);
-	data->cp = cp;
-
-	/* Initialize Port B IIC pins.
-	*/
-	cp->cp_pbpar |= 0x00000030;
-	cp->cp_pbdir |= 0x00000030;
-	cp->cp_pbodr |= 0x00000030;
-
-	/* Allocate space for two transmit and two receive buffer
-	 * descriptors in the DP ram.
-	 */
-	data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8);
-		
-	/* ptr to i2c area */
-	data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c);
-}
-
-static int rpx_install_isr(int irq, void (*func)(void *), void *data)
-{
-	/* install interrupt handler */
-	cpm_install_handler(irq, func, data);
-
-	return 0;
-}
-
-static struct i2c_algo_8xx_data rpx_data = {
-	.setisr = rpx_install_isr
-};
-
-static struct i2c_adapter rpx_ops = {
-	.owner		= THIS_MODULE,
-	.name		= "m8xx",
-	.id		= I2C_HW_MPC8XX_EPON,
-	.algo_data	= &rpx_data,
-};
-
-int __init i2c_rpx_init(void)
-{
-	printk(KERN_INFO "i2c-rpx: i2c MPC8xx driver\n");
-
-	/* reset hardware to sane state */
-	rpx_iic_init(&rpx_data);
-
-	if (i2c_8xx_add_bus(&rpx_ops) < 0) {
-		printk(KERN_ERR "i2c-rpx: Unable to register with I2C\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-void __exit i2c_rpx_exit(void)
-{
-	i2c_8xx_del_bus(&rpx_ops);
-}
-
-MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
-MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
-
-module_init(i2c_rpx_init);
-module_exit(i2c_rpx_exit);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index e68a96f..e4540fc 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -830,7 +830,8 @@
 
 	i2c->irq = res;
 		
-	dev_dbg(&pdev->dev, "irq resource %p (%ld)\n", res, res->start);
+	dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res,
+		(unsigned long)res->start);
 
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret < 0) {
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index b7fb65c..8adf4ab 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -25,8 +25,6 @@
 /* This interfaces to the I2C bus of the Savage4 to gain access to
    the BT869 and possibly other I2C devices. The DDC bus is not
    yet supported because its register is not memory-mapped.
-   However we leave the DDC code here, commented out, to make
-   it easier to add later.
 */
 
 #include <linux/kernel.h>
@@ -37,36 +35,19 @@
 #include <linux/i2c-algo-bit.h>
 #include <asm/io.h>
 
-/* 3DFX defines */
-#define PCI_CHIP_SAVAGE3D	0x8A20
-#define PCI_CHIP_SAVAGE3D_MV	0x8A21
+/* device IDs */
 #define PCI_CHIP_SAVAGE4	0x8A22
 #define PCI_CHIP_SAVAGE2000	0x9102
-#define PCI_CHIP_PROSAVAGE_PM	0x8A25
-#define PCI_CHIP_PROSAVAGE_KM	0x8A26
-#define PCI_CHIP_SAVAGE_MX_MV	0x8c10
-#define PCI_CHIP_SAVAGE_MX	0x8c11
-#define PCI_CHIP_SAVAGE_IX_MV	0x8c12
-#define PCI_CHIP_SAVAGE_IX	0x8c13
 
 #define REG			0xff20	/* Serial Port 1 Register */
 
 /* bit locations in the register */
-#define DDC_ENAB		0x00040000
-#define DDC_SCL_OUT		0x00080000
-#define DDC_SDA_OUT		0x00100000
-#define DDC_SCL_IN		0x00200000
-#define DDC_SDA_IN		0x00400000
 #define I2C_ENAB		0x00000020
 #define I2C_SCL_OUT		0x00000001
 #define I2C_SDA_OUT		0x00000002
 #define I2C_SCL_IN		0x00000008
 #define I2C_SDA_IN		0x00000010
 
-/* initialization states */
-#define INIT2			0x20
-#define INIT3			0x04
-
 /* delays */
 #define CYCLE_DELAY		10
 #define TIMEOUT			(HZ / 2)
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index a6feed4..283769c 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -129,6 +129,7 @@
 
 static struct pci_driver sis5595_driver;
 static unsigned short sis5595_base;
+static struct pci_dev *sis5595_pdev;
 
 static u8 sis5595_read(u8 reg)
 {
@@ -379,6 +380,8 @@
 
 static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+	int err;
+
 	if (sis5595_setup(dev)) {
 		dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n");
 		return -ENODEV;
@@ -389,20 +392,24 @@
 
 	sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
 		sis5595_base + SMB_INDEX);
-	return i2c_add_adapter(&sis5595_adapter);
-}
+	err = i2c_add_adapter(&sis5595_adapter);
+	if (err) {
+		release_region(sis5595_base + SMB_INDEX, 2);
+		return err;
+	}
 
-static void __devexit sis5595_remove(struct pci_dev *dev)
-{
-	i2c_del_adapter(&sis5595_adapter);
-	release_region(sis5595_base + SMB_INDEX, 2);
+	/* Always return failure here.  This is to allow other drivers to bind
+	 * to this pci device.  We don't really want to have control over the
+	 * pci device, we only wanted to read as few register values from it.
+	 */
+	sis5595_pdev =  pci_dev_get(dev);
+	return -ENODEV;
 }
 
 static struct pci_driver sis5595_driver = {
 	.name		= "sis5595_smbus",
 	.id_table	= sis5595_ids,
 	.probe		= sis5595_probe,
-	.remove		= __devexit_p(sis5595_remove),
 };
 
 static int __init i2c_sis5595_init(void)
@@ -413,6 +420,12 @@
 static void __exit i2c_sis5595_exit(void)
 {
 	pci_unregister_driver(&sis5595_driver);
+	if (sis5595_pdev) {
+		i2c_del_adapter(&sis5595_adapter);
+		release_region(sis5595_base + SMB_INDEX, 2);
+		pci_dev_put(sis5595_pdev);
+		sis5595_pdev = NULL;
+	}
 }
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c
new file mode 100644
index 0000000..1b0cfd5
--- /dev/null
+++ b/drivers/i2c/busses/i2c-taos-evm.c
@@ -0,0 +1,330 @@
+/*
+ * Driver for the TAOS evaluation modules
+ * These devices include an I2C master which can be controlled over the
+ * serial port.
+ *
+ * Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#define TAOS_BUFFER_SIZE	63
+
+#define TAOS_STATE_INIT		0
+#define TAOS_STATE_IDLE		1
+#define TAOS_STATE_SEND		2
+#define TAOS_STATE_RECV		3
+
+#define TAOS_CMD_RESET		0x12
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+struct taos_data {
+	struct i2c_adapter adapter;
+	struct i2c_client *client;
+	int state;
+	u8 addr;		/* last used address */
+	unsigned char buffer[TAOS_BUFFER_SIZE];
+	unsigned int pos;	/* position inside the buffer */
+};
+
+/* TAOS TSL2550 EVM */
+static struct i2c_board_info tsl2550_info = {
+	I2C_BOARD_INFO("tsl2550", 0x39),
+	.type	= "tsl2550",
+};
+
+/* Instantiate i2c devices based on the adapter name */
+static struct i2c_client *taos_instantiate_device(struct i2c_adapter *adapter)
+{
+	if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) {
+		dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n",
+			tsl2550_info.driver_name, tsl2550_info.addr);
+		return i2c_new_device(adapter, &tsl2550_info);
+	}
+
+	return NULL;
+}
+
+static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+			   unsigned short flags, char read_write, u8 command,
+			   int size, union i2c_smbus_data *data)
+{
+	struct serio *serio = adapter->algo_data;
+	struct taos_data *taos = serio_get_drvdata(serio);
+	char *p;
+
+	/* Encode our transaction. "@" is for the device address, "$" for the
+	   SMBus command and "#" for the data. */
+	p = taos->buffer;
+
+	/* The device remembers the last used address, no need to send it
+	   again if it's the same */
+	if (addr != taos->addr)
+		p += sprintf(p, "@%02X", addr);
+
+	switch (size) {
+	case I2C_SMBUS_BYTE:
+		if (read_write == I2C_SMBUS_WRITE)
+			sprintf(p, "$#%02X", command);
+		else
+			sprintf(p, "$");
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		if (read_write == I2C_SMBUS_WRITE)
+			sprintf(p, "$%02X#%02X", command, data->byte);
+		else
+			sprintf(p, "$%02X", command);
+		break;
+	default:
+		dev_dbg(&adapter->dev, "Unsupported transaction size %d\n",
+			size);
+		return -EINVAL;
+	}
+
+	/* Send the transaction to the TAOS EVM */
+	dev_dbg(&adapter->dev, "Command buffer: %s\n", taos->buffer);
+	taos->pos = 0;
+	taos->state = TAOS_STATE_SEND;
+	serio_write(serio, taos->buffer[0]);
+	wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+					 msecs_to_jiffies(250));
+	if (taos->state != TAOS_STATE_IDLE) {
+		dev_err(&adapter->dev, "Transaction failed "
+			"(state=%d, pos=%d)\n", taos->state, taos->pos);
+		taos->addr = 0;
+		return -EIO;
+	}
+	taos->addr = addr;
+
+	/* Start the transaction and read the answer */
+	taos->pos = 0;
+	taos->state = TAOS_STATE_RECV;
+	serio_write(serio, read_write == I2C_SMBUS_WRITE ? '>' : '<');
+	wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+					 msecs_to_jiffies(150));
+	if (taos->state != TAOS_STATE_IDLE
+	 || taos->pos != 6) {
+		dev_err(&adapter->dev, "Transaction timeout (pos=%d)\n",
+			taos->pos);
+		return -EIO;
+	}
+	dev_dbg(&adapter->dev, "Answer buffer: %s\n", taos->buffer);
+
+	/* Interpret the returned string */
+	p = taos->buffer + 2;
+	p[3] = '\0';
+	if (!strcmp(p, "NAK"))
+		return -ENODEV;
+
+	if (read_write == I2C_SMBUS_WRITE) {
+		if (!strcmp(p, "ACK"))
+			return 0;
+	} else {
+		if (p[0] == 'x') {
+			data->byte = simple_strtol(p + 1, NULL, 16);
+			return 0;
+		}
+	}
+
+	return -EIO;
+}
+
+static u32 taos_smbus_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static const struct i2c_algorithm taos_algorithm = {
+	.smbus_xfer	= taos_smbus_xfer,
+	.functionality	= taos_smbus_func,
+};
+
+static irqreturn_t taos_interrupt(struct serio *serio, unsigned char data,
+				  unsigned int flags)
+{
+	struct taos_data *taos = serio_get_drvdata(serio);
+
+	switch (taos->state) {
+	case TAOS_STATE_INIT:
+		taos->buffer[taos->pos++] = data;
+		if (data == ':'
+		 || taos->pos == TAOS_BUFFER_SIZE - 1) {
+			taos->buffer[taos->pos] = '\0';
+			taos->state = TAOS_STATE_IDLE;
+			wake_up_interruptible(&wq);
+		}
+		break;
+	case TAOS_STATE_SEND:
+		if (taos->buffer[++taos->pos])
+			serio_write(serio, taos->buffer[taos->pos]);
+		else {
+			taos->state = TAOS_STATE_IDLE;
+			wake_up_interruptible(&wq);
+		}
+		break;
+	case TAOS_STATE_RECV:
+		taos->buffer[taos->pos++] = data;
+		if (data == ']') {
+			taos->buffer[taos->pos] = '\0';
+			taos->state = TAOS_STATE_IDLE;
+			wake_up_interruptible(&wq);
+		}
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* Extract the adapter name from the buffer received after reset.
+   The buffer is modified and a pointer inside the buffer is returned. */
+static char *taos_adapter_name(char *buffer)
+{
+	char *start, *end;
+
+	start = strstr(buffer, "TAOS ");
+	if (!start)
+		return NULL;
+
+	end = strchr(start, '\r');
+	if (!end)
+		return NULL;
+	*end = '\0';
+
+	return start;
+}
+
+static int taos_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct taos_data *taos;
+	struct i2c_adapter *adapter;
+	char *name;
+	int err;
+
+	taos = kzalloc(sizeof(struct taos_data), GFP_KERNEL);
+	if (!taos) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	taos->state = TAOS_STATE_INIT;
+	serio_set_drvdata(serio, taos);
+
+	err = serio_open(serio, drv);
+	if (err)
+		goto exit_kfree;
+
+	adapter = &taos->adapter;
+	adapter->owner = THIS_MODULE;
+	adapter->algo = &taos_algorithm;
+	adapter->algo_data = serio;
+	adapter->dev.parent = &serio->dev;
+
+	/* Reset the TAOS evaluation module to identify it */
+	serio_write(serio, TAOS_CMD_RESET);
+	wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+					 msecs_to_jiffies(2000));
+
+	if (taos->state != TAOS_STATE_IDLE) {
+		err = -ENODEV;
+		dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, "
+			"pos=%d)\n", taos->state, taos->pos);
+		goto exit_close;
+	}
+
+	name = taos_adapter_name(taos->buffer);
+	if (!name) {
+		err = -ENODEV;
+		dev_err(&serio->dev, "TAOS EVM identification failed\n");
+		goto exit_close;
+	}
+	strlcpy(adapter->name, name, sizeof(adapter->name));
+
+	err = i2c_add_adapter(adapter);
+	if (err)
+		goto exit_close;
+	dev_dbg(&serio->dev, "Connected to TAOS EVM\n");
+
+	taos->client = taos_instantiate_device(adapter);
+	return 0;
+
+ exit_close:
+	serio_close(serio);
+ exit_kfree:
+	serio_set_drvdata(serio, NULL);
+	kfree(taos);
+ exit:
+	return err;
+}
+
+static void taos_disconnect(struct serio *serio)
+{
+	struct taos_data *taos = serio_get_drvdata(serio);
+
+	if (taos->client)
+		i2c_unregister_device(taos->client);
+	i2c_del_adapter(&taos->adapter);
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	kfree(taos);
+
+	dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n");
+}
+
+static struct serio_device_id taos_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_TAOSEVM,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(serio, taos_serio_ids);
+
+static struct serio_driver taos_drv = {
+	.driver		= {
+		.name	= "taos-evm",
+	},
+	.description	= "TAOS evaluation module driver",
+	.id_table	= taos_serio_ids,
+	.connect	= taos_connect,
+	.disconnect	= taos_disconnect,
+	.interrupt	= taos_interrupt,
+};
+
+static int __init taos_init(void)
+{
+	return serio_register_driver(&taos_drv);
+}
+
+static void __exit taos_exit(void)
+{
+	serio_unregister_driver(&taos_drv);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("TAOS evaluation module driver");
+MODULE_LICENSE("GPL");
+
+module_init(taos_init);
+module_exit(taos_exit);
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
index 9079990..cb9abe7 100644
--- a/drivers/i2c/busses/i2c-tiny-usb.c
+++ b/drivers/i2c/busses/i2c-tiny-usb.c
@@ -208,7 +208,7 @@
 	dev->adapter.class = I2C_CLASS_HWMON;
 	dev->adapter.algo = &usb_algorithm;
 	dev->adapter.algo_data = dev;
-	snprintf(dev->adapter.name, I2C_NAME_SIZE,
+	snprintf(dev->adapter.name, sizeof(dev->adapter.name),
 		 "i2c-tiny-usb at bus %03d device %03d",
 		 dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
 
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 7a2bc06..edc2750 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -235,7 +235,7 @@
 		if (!(vt596_features & FEATURE_I2CBLOCK))
 			goto exit_unsupported;
 		if (read_write == I2C_SMBUS_READ)
-			outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
+			outb_p(data->block[0], SMBHSTDAT0);
 		/* Fall through */
 	case I2C_SMBUS_BLOCK_DATA:
 		outb_p(command, SMBHSTCMD);
@@ -397,8 +397,7 @@
 	case PCI_DEVICE_ID_VIA_82C686_4:
 		/* The VT82C686B (rev 0x40) does support I2C block
 		   transactions, but the VT82C686A (rev 0x30) doesn't */
-		if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
-		 && temp >= 0x40)
+		if (pdev->revision >= 0x40)
 			vt596_features |= FEATURE_I2CBLOCK;
 		break;
 	}
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 0d6bd4f..e6c4a2b 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -310,8 +310,6 @@
 		break;
 
 	case I2C_SMBUS_I2C_BLOCK_DATA:
-		if (rw == I2C_SMBUS_READ)
-			data->block[0] = I2C_SMBUS_BLOCK_MAX; /* For now */
 		len = data->block[0];
 		if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
 			return -EINVAL;
@@ -388,7 +386,7 @@
 };
 
 static struct scx200_acb_iface *scx200_acb_list;
-static DECLARE_MUTEX(scx200_acb_list_mutex);
+static DEFINE_MUTEX(scx200_acb_list_mutex);
 
 static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
 {
@@ -472,10 +470,10 @@
 		return -ENODEV;
 	}
 
-	down(&scx200_acb_list_mutex);
+	mutex_lock(&scx200_acb_list_mutex);
 	iface->next = scx200_acb_list;
 	scx200_acb_list = iface;
-	up(&scx200_acb_list_mutex);
+	mutex_unlock(&scx200_acb_list_mutex);
 
 	return 0;
 }
@@ -633,10 +631,10 @@
 {
 	struct scx200_acb_iface *iface;
 
-	down(&scx200_acb_list_mutex);
+	mutex_lock(&scx200_acb_list_mutex);
 	while ((iface = scx200_acb_list) != NULL) {
 		scx200_acb_list = iface->next;
-		up(&scx200_acb_list_mutex);
+		mutex_unlock(&scx200_acb_list_mutex);
 
 		i2c_del_adapter(&iface->adapter);
 
@@ -648,9 +646,9 @@
 			release_region(iface->base, 8);
 
 		kfree(iface);
-		down(&scx200_acb_list_mutex);
+		mutex_lock(&scx200_acb_list_mutex);
 	}
-	up(&scx200_acb_list_mutex);
+	mutex_unlock(&scx200_acb_list_mutex);
 }
 
 module_init(scx200_acb_init);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index ea085a0..2e1c24f 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -5,7 +5,7 @@
 menu "Miscellaneous I2C Chip support"
 
 config SENSORS_DS1337
-	tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
+	tristate "Dallas DS1337 and DS1339 Real Time Clock (DEPRECATED)"
 	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for Dallas Semiconductor
@@ -14,8 +14,11 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1337.
 
+	  This driver is deprecated and will be dropped soon. Use
+	  rtc-ds1307 instead.
+
 config SENSORS_DS1374
-	tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
+	tristate "Dallas DS1374 Real Time Clock (DEPRECATED)"
 	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for Dallas Semiconductor
@@ -24,6 +27,19 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1374.
 
+	  This driver is deprecated and will be dropped soon. Use
+	  rtc-ds1374 instead.
+
+config DS1682
+	tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
+	depends on EXPERIMENTAL
+	help
+	  If you say yes here you get support for Dallas Semiconductor
+	  DS1682 Total Elapsed Time Recorder.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ds1682.
+
 config SENSORS_EEPROM
 	tristate "EEPROM reader"
 	depends on EXPERIMENTAL
@@ -101,7 +117,7 @@
 	  will be called tps65010.
 
 config SENSORS_M41T00
-	tristate "ST M41T00 RTC chip"
+	tristate "ST M41T00 RTC chip (DEPRECATED)"
 	depends on PPC32
 	help
 	  If you say yes here you get support for the ST M41T00 RTC chip.
@@ -109,6 +125,9 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called m41t00.
 
+	  This driver is deprecated and will be dropped soon. Use
+	  rtc-ds1307 or rtc-m41t80 instead.
+
 config SENSORS_MAX6875
 	tristate "Maxim MAX6875 Power supply supervisor"
 	depends on EXPERIMENTAL
@@ -124,4 +143,24 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called max6875.
 
+config SENSORS_TSL2550
+	tristate "Taos TSL2550 ambient light sensor"
+	depends on EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Taos TSL2550
+	  ambient light sensor.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tsl2550.
+
+config MENELAUS
+	bool "TWL92330/Menelaus PM chip"
+	depends on I2C=y && ARCH_OMAP24XX
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  TWL92330/Menelaus Power Management chip. This include voltage
+	  regulators, Dual slot memory card tranceivers, real-time clock
+	  and other features that are often used in portable devices like
+	  cell phones and PDAs.
+
 endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 779868e..ca924e1 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_SENSORS_DS1337)	+= ds1337.o
 obj-$(CONFIG_SENSORS_DS1374)	+= ds1374.o
+obj-$(CONFIG_DS1682)		+= ds1682.o
 obj-$(CONFIG_SENSORS_EEPROM)	+= eeprom.o
 obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
 obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
@@ -12,6 +13,8 @@
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
+obj-$(CONFIG_MENELAUS)		+= menelaus.o
+obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c
new file mode 100644
index 0000000..5879f0f
--- /dev/null
+++ b/drivers/i2c/chips/ds1682.c
@@ -0,0 +1,259 @@
+/*
+ * Dallas Semiconductor DS1682 Elapsed Time Recorder device driver
+ *
+ * Written by: Grant Likely <grant.likely@secretlab.ca>
+ *
+ * Copyright (C) 2007 Secret Lab Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * The DS1682 elapsed timer recorder is a simple device that implements
+ * one elapsed time counter, one event counter, an alarm signal and 10
+ * bytes of general purpose EEPROM.
+ *
+ * This driver provides access to the DS1682 counters and user data via
+ * the sysfs.  The following attributes are added to the device node:
+ *     elapsed_time (u32): Total elapsed event time in ms resolution
+ *     alarm_time (u32): When elapsed time exceeds the value in alarm_time,
+ *                       then the alarm pin is asserted.
+ *     event_count (u16): number of times the event pin has gone low.
+ *     eeprom (u8[10]): general purpose EEPROM
+ *
+ * Counter registers and user data are both read/write unless the device
+ * has been write protected.  This driver does not support turning off write
+ * protection.  Once write protection is turned on, it is impossible to
+ * turn it off again, so I have left the feature out of this driver to avoid
+ * accidental enabling, but it is trivial to add write protect support.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/sysfs.h>
+#include <linux/ctype.h>
+#include <linux/hwmon-sysfs.h>
+
+/* Device registers */
+#define DS1682_REG_CONFIG		0x00
+#define DS1682_REG_ALARM		0x01
+#define DS1682_REG_ELAPSED		0x05
+#define DS1682_REG_EVT_CNTR		0x09
+#define DS1682_REG_EEPROM		0x0b
+#define DS1682_REG_RESET		0x1d
+#define DS1682_REG_WRITE_DISABLE	0x1e
+#define DS1682_REG_WRITE_MEM_DISABLE	0x1f
+
+#define DS1682_EEPROM_SIZE		10
+
+/*
+ * Generic counter attributes
+ */
+static ssize_t ds1682_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	struct i2c_client *client = to_i2c_client(dev);
+	__le32 val = 0;
+	int rc;
+
+	dev_dbg(dev, "ds1682_show() called on %s\n", attr->attr.name);
+
+	/* Read the register */
+	rc = i2c_smbus_read_i2c_block_data(client, sattr->index, sattr->nr,
+					   (u8 *) & val);
+	if (rc < 0)
+		return -EIO;
+
+	/* Special case: the 32 bit regs are time values with 1/4s
+	 * resolution, scale them up to milliseconds */
+	if (sattr->nr == 4)
+		return sprintf(buf, "%llu\n", ((u64) le32_to_cpu(val)) * 250);
+
+	/* Format the output string and return # of bytes */
+	return sprintf(buf, "%li\n", (long)le32_to_cpu(val));
+}
+
+static ssize_t ds1682_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	struct i2c_client *client = to_i2c_client(dev);
+	char *endp;
+	u64 val;
+	__le32 val_le;
+	int rc;
+
+	dev_dbg(dev, "ds1682_store() called on %s\n", attr->attr.name);
+
+	/* Decode input */
+	val = simple_strtoull(buf, &endp, 0);
+	if (buf == endp) {
+		dev_dbg(dev, "input string not a number\n");
+		return -EINVAL;
+	}
+
+	/* Special case: the 32 bit regs are time values with 1/4s
+	 * resolution, scale input down to quarter-seconds */
+	if (sattr->nr == 4)
+		do_div(val, 250);
+
+	/* write out the value */
+	val_le = cpu_to_le32(val);
+	rc = i2c_smbus_write_i2c_block_data(client, sattr->index, sattr->nr,
+					    (u8 *) & val_le);
+	if (rc < 0) {
+		dev_err(dev, "register write failed; reg=0x%x, size=%i\n",
+			sattr->index, sattr->nr);
+		return -EIO;
+	}
+
+	return count;
+}
+
+/*
+ * Simple register attributes
+ */
+static SENSOR_DEVICE_ATTR_2(elapsed_time, S_IRUGO | S_IWUSR, ds1682_show,
+			    ds1682_store, 4, DS1682_REG_ELAPSED);
+static SENSOR_DEVICE_ATTR_2(alarm_time, S_IRUGO | S_IWUSR, ds1682_show,
+			    ds1682_store, 4, DS1682_REG_ALARM);
+static SENSOR_DEVICE_ATTR_2(event_count, S_IRUGO | S_IWUSR, ds1682_show,
+			    ds1682_store, 2, DS1682_REG_EVT_CNTR);
+
+static const struct attribute_group ds1682_group = {
+	.attrs = (struct attribute *[]) {
+		&sensor_dev_attr_elapsed_time.dev_attr.attr,
+		&sensor_dev_attr_alarm_time.dev_attr.attr,
+		&sensor_dev_attr_event_count.dev_attr.attr,
+		NULL,
+	},
+};
+
+/*
+ * User data attribute
+ */
+static ssize_t ds1682_eeprom_read(struct kobject *kobj, struct bin_attribute *attr,
+				  char *buf, loff_t off, size_t count)
+{
+	struct i2c_client *client = kobj_to_i2c_client(kobj);
+	int rc;
+
+	dev_dbg(&client->dev, "ds1682_eeprom_read(p=%p, off=%lli, c=%zi)\n",
+		buf, off, count);
+
+	if (off >= DS1682_EEPROM_SIZE)
+		return 0;
+
+	if (off + count > DS1682_EEPROM_SIZE)
+		count = DS1682_EEPROM_SIZE - off;
+
+	rc = i2c_smbus_read_i2c_block_data(client, DS1682_REG_EEPROM + off,
+					   count, buf);
+	if (rc < 0)
+		return -EIO;
+
+	return count;
+}
+
+static ssize_t ds1682_eeprom_write(struct kobject *kobj, struct bin_attribute *attr,
+				   char *buf, loff_t off, size_t count)
+{
+	struct i2c_client *client = kobj_to_i2c_client(kobj);
+
+	dev_dbg(&client->dev, "ds1682_eeprom_write(p=%p, off=%lli, c=%zi)\n",
+		buf, off, count);
+
+	if (off >= DS1682_EEPROM_SIZE)
+		return -ENOSPC;
+
+	if (off + count > DS1682_EEPROM_SIZE)
+		count = DS1682_EEPROM_SIZE - off;
+
+	/* Write out to the device */
+	if (i2c_smbus_write_i2c_block_data(client, DS1682_REG_EEPROM + off,
+					   count, buf) < 0)
+		return -EIO;
+
+	return count;
+}
+
+static struct bin_attribute ds1682_eeprom_attr = {
+	.attr = {
+		.name = "eeprom",
+		.mode = S_IRUGO | S_IWUSR,
+		.owner = THIS_MODULE,
+	},
+	.size = DS1682_EEPROM_SIZE,
+	.read = ds1682_eeprom_read,
+	.write = ds1682_eeprom_write,
+};
+
+/*
+ * Called when a ds1682 device is matched with this driver
+ */
+static int ds1682_probe(struct i2c_client *client)
+{
+	int rc;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_I2C_BLOCK)) {
+		dev_err(&client->dev, "i2c bus does not support the ds1682\n");
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	rc = sysfs_create_group(&client->dev.kobj, &ds1682_group);
+	if (rc)
+		goto exit;
+
+	rc = sysfs_create_bin_file(&client->dev.kobj, &ds1682_eeprom_attr);
+	if (rc)
+		goto exit_bin_attr;
+
+	return 0;
+
+ exit_bin_attr:
+	sysfs_remove_group(&client->dev.kobj, &ds1682_group);
+ exit:
+	return rc;
+}
+
+static int ds1682_remove(struct i2c_client *client)
+{
+	sysfs_remove_bin_file(&client->dev.kobj, &ds1682_eeprom_attr);
+	sysfs_remove_group(&client->dev.kobj, &ds1682_group);
+	return 0;
+}
+
+static struct i2c_driver ds1682_driver = {
+	.driver = {
+		.name = "ds1682",
+	},
+	.probe = ds1682_probe,
+	.remove = ds1682_remove,
+};
+
+static int __init ds1682_init(void)
+{
+	return i2c_add_driver(&ds1682_driver);
+}
+
+static void __exit ds1682_exit(void)
+{
+	i2c_del_driver(&ds1682_driver);
+}
+
+MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
+MODULE_DESCRIPTION("DS1682 Elapsed Time Indicator driver");
+MODULE_LICENSE("GPL");
+
+module_init(ds1682_init);
+module_exit(ds1682_exit);
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index bfce13c..d3da1fb 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -88,8 +88,10 @@
 		dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
 
 		if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
-			for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_BLOCK_MAX)
-				if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_BLOCK_MAX)
+			for (i = slice << 5; i < (slice + 1) << 5; i += 32)
+				if (i2c_smbus_read_i2c_block_data(client, i,
+							32, data->data + i)
+							!= 32)
 					goto exit;
 		} else {
 			if (i2c_smbus_write_byte(client, slice << 5)) {
@@ -110,7 +112,8 @@
 	mutex_unlock(&data->update_lock);
 }
 
-static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+			   char *buf, loff_t off, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
 	struct eeprom_data *data = i2c_get_clientdata(client);
@@ -143,7 +146,6 @@
 	.attr = {
 		.name = "eeprom",
 		.mode = S_IRUGO,
-		.owner = THIS_MODULE,
 	},
 	.size = EEPROM_SIZE,
 	.read = eeprom_read,
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 76645c1..64692f6 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -106,6 +106,7 @@
 					    I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
 			if (i2c_smbus_read_i2c_block_data(client,
 							  MAX6875_CMD_BLK_READ,
+							  SLICE_SIZE,
 							  buf) != SLICE_SIZE) {
 				goto exit_up;
 			}
@@ -125,8 +126,9 @@
 	mutex_unlock(&data->update_lock);
 }
 
-static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
-			    size_t count)
+static ssize_t max6875_read(struct kobject *kobj,
+			    struct bin_attribute *bin_attr,
+			    char *buf, loff_t off, size_t count)
 {
 	struct i2c_client *client = kobj_to_i2c_client(kobj);
 	struct max6875_data *data = i2c_get_clientdata(client);
@@ -152,7 +154,6 @@
 	.attr = {
 		.name = "eeprom",
 		.mode = S_IRUGO,
-		.owner = THIS_MODULE,
 	},
 	.size = USER_EEPROM_SIZE,
 	.read = max6875_read,
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
new file mode 100644
index 0000000..48a7e2f
--- /dev/null
+++ b/drivers/i2c/chips/menelaus.c
@@ -0,0 +1,1281 @@
+#define DEBUG
+/*
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Some parts based tps65010.c:
+ * Copyright (C) 2004 Texas Instruments and
+ * Copyright (C) 2004-2005 David Brownell
+ *
+ * Some parts based on tlv320aic24.c:
+ * Copyright (C) by Kai Svahn <kai.svahn@nokia.com>
+ *
+ * Changes for interrupt handling and clean-up by
+ * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
+ * Cleanup and generalized support for voltage setting by
+ * Juha Yrjola
+ * Added support for controlling VCORE and regulator sleep states,
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/menelaus.h>
+
+#define DRIVER_NAME			"menelaus"
+
+#define pr_err(fmt, arg...)	printk(KERN_ERR DRIVER_NAME ": ", ## arg);
+
+#define MENELAUS_I2C_ADDRESS		0x72
+
+#define MENELAUS_REV			0x01
+#define MENELAUS_VCORE_CTRL1		0x02
+#define MENELAUS_VCORE_CTRL2		0x03
+#define MENELAUS_VCORE_CTRL3		0x04
+#define MENELAUS_VCORE_CTRL4		0x05
+#define MENELAUS_VCORE_CTRL5		0x06
+#define MENELAUS_DCDC_CTRL1		0x07
+#define MENELAUS_DCDC_CTRL2		0x08
+#define MENELAUS_DCDC_CTRL3		0x09
+#define MENELAUS_LDO_CTRL1		0x0A
+#define MENELAUS_LDO_CTRL2		0x0B
+#define MENELAUS_LDO_CTRL3		0x0C
+#define MENELAUS_LDO_CTRL4		0x0D
+#define MENELAUS_LDO_CTRL5		0x0E
+#define MENELAUS_LDO_CTRL6		0x0F
+#define MENELAUS_LDO_CTRL7		0x10
+#define MENELAUS_LDO_CTRL8		0x11
+#define MENELAUS_SLEEP_CTRL1		0x12
+#define MENELAUS_SLEEP_CTRL2		0x13
+#define MENELAUS_DEVICE_OFF		0x14
+#define MENELAUS_OSC_CTRL		0x15
+#define MENELAUS_DETECT_CTRL		0x16
+#define MENELAUS_INT_MASK1		0x17
+#define MENELAUS_INT_MASK2		0x18
+#define MENELAUS_INT_STATUS1		0x19
+#define MENELAUS_INT_STATUS2		0x1A
+#define MENELAUS_INT_ACK1		0x1B
+#define MENELAUS_INT_ACK2		0x1C
+#define MENELAUS_GPIO_CTRL		0x1D
+#define MENELAUS_GPIO_IN		0x1E
+#define MENELAUS_GPIO_OUT		0x1F
+#define MENELAUS_BBSMS			0x20
+#define MENELAUS_RTC_CTRL		0x21
+#define MENELAUS_RTC_UPDATE		0x22
+#define MENELAUS_RTC_SEC		0x23
+#define MENELAUS_RTC_MIN		0x24
+#define MENELAUS_RTC_HR			0x25
+#define MENELAUS_RTC_DAY		0x26
+#define MENELAUS_RTC_MON		0x27
+#define MENELAUS_RTC_YR			0x28
+#define MENELAUS_RTC_WKDAY		0x29
+#define MENELAUS_RTC_AL_SEC		0x2A
+#define MENELAUS_RTC_AL_MIN		0x2B
+#define MENELAUS_RTC_AL_HR		0x2C
+#define MENELAUS_RTC_AL_DAY		0x2D
+#define MENELAUS_RTC_AL_MON		0x2E
+#define MENELAUS_RTC_AL_YR		0x2F
+#define MENELAUS_RTC_COMP_MSB		0x30
+#define MENELAUS_RTC_COMP_LSB		0x31
+#define MENELAUS_S1_PULL_EN		0x32
+#define MENELAUS_S1_PULL_DIR		0x33
+#define MENELAUS_S2_PULL_EN		0x34
+#define MENELAUS_S2_PULL_DIR		0x35
+#define MENELAUS_MCT_CTRL1		0x36
+#define MENELAUS_MCT_CTRL2		0x37
+#define MENELAUS_MCT_CTRL3		0x38
+#define MENELAUS_MCT_PIN_ST		0x39
+#define MENELAUS_DEBOUNCE1		0x3A
+
+#define IH_MENELAUS_IRQS		12
+#define MENELAUS_MMC_S1CD_IRQ		0	/* MMC slot 1 card change */
+#define MENELAUS_MMC_S2CD_IRQ		1	/* MMC slot 2 card change */
+#define MENELAUS_MMC_S1D1_IRQ		2	/* MMC DAT1 low in slot 1 */
+#define MENELAUS_MMC_S2D1_IRQ		3	/* MMC DAT1 low in slot 2 */
+#define MENELAUS_LOWBAT_IRQ		4	/* Low battery */
+#define MENELAUS_HOTDIE_IRQ		5	/* Hot die detect */
+#define MENELAUS_UVLO_IRQ		6	/* UVLO detect */
+#define MENELAUS_TSHUT_IRQ		7	/* Thermal shutdown */
+#define MENELAUS_RTCTMR_IRQ		8	/* RTC timer */
+#define MENELAUS_RTCALM_IRQ		9	/* RTC alarm */
+#define MENELAUS_RTCERR_IRQ		10	/* RTC error */
+#define MENELAUS_PSHBTN_IRQ		11	/* Push button */
+#define MENELAUS_RESERVED12_IRQ		12	/* Reserved */
+#define MENELAUS_RESERVED13_IRQ		13	/* Reserved */
+#define MENELAUS_RESERVED14_IRQ		14	/* Reserved */
+#define MENELAUS_RESERVED15_IRQ		15	/* Reserved */
+
+static void menelaus_work(struct work_struct *_menelaus);
+
+struct menelaus_chip {
+	struct mutex		lock;
+	struct i2c_client	*client;
+	struct work_struct	work;
+#ifdef CONFIG_RTC_DRV_TWL92330
+	struct rtc_device	*rtc;
+	u8			rtc_control;
+	unsigned		uie:1;
+#endif
+	unsigned		vcore_hw_mode:1;
+	u8			mask1, mask2;
+	void			(*handlers[16])(struct menelaus_chip *);
+	void			(*mmc_callback)(void *data, u8 mask);
+	void			*mmc_callback_data;
+};
+
+static struct menelaus_chip *the_menelaus;
+
+static int menelaus_write_reg(int reg, u8 value)
+{
+	int val = i2c_smbus_write_byte_data(the_menelaus->client, reg, value);
+
+	if (val < 0) {
+		pr_err("write error");
+		return val;
+	}
+
+	return 0;
+}
+
+static int menelaus_read_reg(int reg)
+{
+	int val = i2c_smbus_read_byte_data(the_menelaus->client, reg);
+
+	if (val < 0)
+		pr_err("read error");
+
+	return val;
+}
+
+static int menelaus_enable_irq(int irq)
+{
+	if (irq > 7) {
+		irq -= 8;
+		the_menelaus->mask2 &= ~(1 << irq);
+		return menelaus_write_reg(MENELAUS_INT_MASK2,
+				the_menelaus->mask2);
+	} else {
+		the_menelaus->mask1 &= ~(1 << irq);
+		return menelaus_write_reg(MENELAUS_INT_MASK1,
+				the_menelaus->mask1);
+	}
+}
+
+static int menelaus_disable_irq(int irq)
+{
+	if (irq > 7) {
+		irq -= 8;
+		the_menelaus->mask2 |= (1 << irq);
+		return menelaus_write_reg(MENELAUS_INT_MASK2,
+				the_menelaus->mask2);
+	} else {
+		the_menelaus->mask1 |= (1 << irq);
+		return menelaus_write_reg(MENELAUS_INT_MASK1,
+				the_menelaus->mask1);
+	}
+}
+
+static int menelaus_ack_irq(int irq)
+{
+	if (irq > 7)
+		return menelaus_write_reg(MENELAUS_INT_ACK2, 1 << (irq - 8));
+	else
+		return menelaus_write_reg(MENELAUS_INT_ACK1, 1 << irq);
+}
+
+/* Adds a handler for an interrupt. Does not run in interrupt context */
+static int menelaus_add_irq_work(int irq,
+		void (*handler)(struct menelaus_chip *))
+{
+	int ret = 0;
+
+	mutex_lock(&the_menelaus->lock);
+	the_menelaus->handlers[irq] = handler;
+	ret = menelaus_enable_irq(irq);
+	mutex_unlock(&the_menelaus->lock);
+
+	return ret;
+}
+
+/* Removes handler for an interrupt */
+static int menelaus_remove_irq_work(int irq)
+{
+	int ret = 0;
+
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_disable_irq(irq);
+	the_menelaus->handlers[irq] = NULL;
+	mutex_unlock(&the_menelaus->lock);
+
+	return ret;
+}
+
+/*
+ * Gets scheduled when a card detect interrupt happens. Note that in some cases
+ * this line is wired to card cover switch rather than the card detect switch
+ * in each slot. In this case the cards are not seen by menelaus.
+ * FIXME: Add handling for D1 too
+ */
+static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw)
+{
+	int reg;
+	unsigned char card_mask = 0;
+
+	reg = menelaus_read_reg(MENELAUS_MCT_PIN_ST);
+	if (reg < 0)
+		return;
+
+	if (!(reg & 0x1))
+		card_mask |= (1 << 0);
+
+	if (!(reg & 0x2))
+		card_mask |= (1 << 1);
+
+	if (menelaus_hw->mmc_callback)
+		menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data,
+					  card_mask);
+}
+
+/*
+ * Toggles the MMC slots between open-drain and push-pull mode.
+ */
+int menelaus_set_mmc_opendrain(int slot, int enable)
+{
+	int ret, val;
+
+	if (slot != 1 && slot != 2)
+		return -EINVAL;
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_read_reg(MENELAUS_MCT_CTRL1);
+	if (ret < 0) {
+		mutex_unlock(&the_menelaus->lock);
+		return ret;
+	}
+	val = ret;
+	if (slot == 1) {
+		if (enable)
+			val |= 1 << 2;
+		else
+			val &= ~(1 << 2);
+	} else {
+		if (enable)
+			val |= 1 << 3;
+		else
+			val &= ~(1 << 3);
+	}
+	ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val);
+	mutex_unlock(&the_menelaus->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(menelaus_set_mmc_opendrain);
+
+int menelaus_set_slot_sel(int enable)
+{
+	int ret;
+
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_read_reg(MENELAUS_GPIO_CTRL);
+	if (ret < 0)
+		goto out;
+	ret |= 0x02;
+	if (enable)
+		ret |= 1 << 5;
+	else
+		ret &= ~(1 << 5);
+	ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	return ret;
+}
+EXPORT_SYMBOL(menelaus_set_slot_sel);
+
+int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en)
+{
+	int ret, val;
+
+	if (slot != 1 && slot != 2)
+		return -EINVAL;
+	if (power >= 3)
+		return -EINVAL;
+
+	mutex_lock(&the_menelaus->lock);
+
+	ret = menelaus_read_reg(MENELAUS_MCT_CTRL2);
+	if (ret < 0)
+		goto out;
+	val = ret;
+	if (slot == 1) {
+		if (cd_en)
+			val |= (1 << 4) | (1 << 6);
+		else
+			val &= ~((1 << 4) | (1 << 6));
+	} else {
+		if (cd_en)
+			val |= (1 << 5) | (1 << 7);
+		else
+			val &= ~((1 << 5) | (1 << 7));
+	}
+	ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val);
+	if (ret < 0)
+		goto out;
+
+	ret = menelaus_read_reg(MENELAUS_MCT_CTRL3);
+	if (ret < 0)
+		goto out;
+	val = ret;
+	if (slot == 1) {
+		if (enable)
+			val |= 1 << 0;
+		else
+			val &= ~(1 << 0);
+	} else {
+		int b;
+
+		if (enable)
+			ret |= 1 << 1;
+		else
+			ret &= ~(1 << 1);
+		b = menelaus_read_reg(MENELAUS_MCT_CTRL2);
+		b &= ~0x03;
+		b |= power;
+		ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b);
+		if (ret < 0)
+			goto out;
+	}
+	/* Disable autonomous shutdown */
+	val &= ~(0x03 << 2);
+	ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	return ret;
+}
+EXPORT_SYMBOL(menelaus_set_mmc_slot);
+
+int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask),
+				   void *data)
+{
+	int ret = 0;
+
+	the_menelaus->mmc_callback_data = data;
+	the_menelaus->mmc_callback = callback;
+	ret = menelaus_add_irq_work(MENELAUS_MMC_S1CD_IRQ,
+				    menelaus_mmc_cd_work);
+	if (ret < 0)
+		return ret;
+	ret = menelaus_add_irq_work(MENELAUS_MMC_S2CD_IRQ,
+				    menelaus_mmc_cd_work);
+	if (ret < 0)
+		return ret;
+	ret = menelaus_add_irq_work(MENELAUS_MMC_S1D1_IRQ,
+				    menelaus_mmc_cd_work);
+	if (ret < 0)
+		return ret;
+	ret = menelaus_add_irq_work(MENELAUS_MMC_S2D1_IRQ,
+				    menelaus_mmc_cd_work);
+
+	return ret;
+}
+EXPORT_SYMBOL(menelaus_register_mmc_callback);
+
+void menelaus_unregister_mmc_callback(void)
+{
+	menelaus_remove_irq_work(MENELAUS_MMC_S1CD_IRQ);
+	menelaus_remove_irq_work(MENELAUS_MMC_S2CD_IRQ);
+	menelaus_remove_irq_work(MENELAUS_MMC_S1D1_IRQ);
+	menelaus_remove_irq_work(MENELAUS_MMC_S2D1_IRQ);
+
+	the_menelaus->mmc_callback = NULL;
+	the_menelaus->mmc_callback_data = 0;
+}
+EXPORT_SYMBOL(menelaus_unregister_mmc_callback);
+
+struct menelaus_vtg {
+	const char *name;
+	u8 vtg_reg;
+	u8 vtg_shift;
+	u8 vtg_bits;
+	u8 mode_reg;
+};
+
+struct menelaus_vtg_value {
+	u16 vtg;
+	u16 val;
+};
+
+static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV,
+				int vtg_val, int mode)
+{
+	int val, ret;
+	struct i2c_client *c = the_menelaus->client;
+
+	mutex_lock(&the_menelaus->lock);
+	if (vtg == 0)
+		goto set_voltage;
+
+	ret = menelaus_read_reg(vtg->vtg_reg);
+	if (ret < 0)
+		goto out;
+	val = ret & ~(((1 << vtg->vtg_bits) - 1) << vtg->vtg_shift);
+	val |= vtg_val << vtg->vtg_shift;
+
+	dev_dbg(&c->dev, "Setting voltage '%s'"
+			 "to %d mV (reg 0x%02x, val 0x%02x)\n",
+			vtg->name, mV, vtg->vtg_reg, val);
+
+	ret = menelaus_write_reg(vtg->vtg_reg, val);
+	if (ret < 0)
+		goto out;
+set_voltage:
+	ret = menelaus_write_reg(vtg->mode_reg, mode);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	if (ret == 0) {
+		/* Wait for voltage to stabilize */
+		msleep(1);
+	}
+	return ret;
+}
+
+static int menelaus_get_vtg_value(int vtg, const struct menelaus_vtg_value *tbl,
+				  int n)
+{
+	int i;
+
+	for (i = 0; i < n; i++, tbl++)
+		if (tbl->vtg == vtg)
+			return tbl->val;
+	return -EINVAL;
+}
+
+/*
+ * Vcore can be programmed in two ways:
+ * SW-controlled: Required voltage is programmed into VCORE_CTRL1
+ * HW-controlled: Required range (roof-floor) is programmed into VCORE_CTRL3
+ * and VCORE_CTRL4
+ *
+ * Call correct 'set' function accordingly
+ */
+
+static const struct menelaus_vtg_value vcore_values[] = {
+	{ 1000, 0 },
+	{ 1025, 1 },
+	{ 1050, 2 },
+	{ 1075, 3 },
+	{ 1100, 4 },
+	{ 1125, 5 },
+	{ 1150, 6 },
+	{ 1175, 7 },
+	{ 1200, 8 },
+	{ 1225, 9 },
+	{ 1250, 10 },
+	{ 1275, 11 },
+	{ 1300, 12 },
+	{ 1325, 13 },
+	{ 1350, 14 },
+	{ 1375, 15 },
+	{ 1400, 16 },
+	{ 1425, 17 },
+	{ 1450, 18 },
+};
+
+int menelaus_set_vcore_sw(unsigned int mV)
+{
+	int val, ret;
+	struct i2c_client *c = the_menelaus->client;
+
+	val = menelaus_get_vtg_value(mV, vcore_values,
+				     ARRAY_SIZE(vcore_values));
+	if (val < 0)
+		return -EINVAL;
+
+	dev_dbg(&c->dev, "Setting VCORE to %d mV (val 0x%02x)\n", mV, val);
+
+	/* Set SW mode and the voltage in one go. */
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
+	if (ret == 0)
+		the_menelaus->vcore_hw_mode = 0;
+	mutex_unlock(&the_menelaus->lock);
+	msleep(1);
+
+	return ret;
+}
+
+int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV)
+{
+	int fval, rval, val, ret;
+	struct i2c_client *c = the_menelaus->client;
+
+	rval = menelaus_get_vtg_value(roof_mV, vcore_values,
+				      ARRAY_SIZE(vcore_values));
+	if (rval < 0)
+		return -EINVAL;
+	fval = menelaus_get_vtg_value(floor_mV, vcore_values,
+				      ARRAY_SIZE(vcore_values));
+	if (fval < 0)
+		return -EINVAL;
+
+	dev_dbg(&c->dev, "Setting VCORE FLOOR to %d mV and ROOF to %d mV\n",
+	       floor_mV, roof_mV);
+
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_write_reg(MENELAUS_VCORE_CTRL3, fval);
+	if (ret < 0)
+		goto out;
+	ret = menelaus_write_reg(MENELAUS_VCORE_CTRL4, rval);
+	if (ret < 0)
+		goto out;
+	if (!the_menelaus->vcore_hw_mode) {
+		val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
+		/* HW mode, turn OFF byte comparator */
+		val |= ((1 << 7) | (1 << 5));
+		ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
+		the_menelaus->vcore_hw_mode = 1;
+	}
+	msleep(1);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	return ret;
+}
+
+static const struct menelaus_vtg vmem_vtg = {
+	.name = "VMEM",
+	.vtg_reg = MENELAUS_LDO_CTRL1,
+	.vtg_shift = 0,
+	.vtg_bits = 2,
+	.mode_reg = MENELAUS_LDO_CTRL3,
+};
+
+static const struct menelaus_vtg_value vmem_values[] = {
+	{ 1500, 0 },
+	{ 1800, 1 },
+	{ 1900, 2 },
+	{ 2500, 3 },
+};
+
+int menelaus_set_vmem(unsigned int mV)
+{
+	int val;
+
+	if (mV == 0)
+		return menelaus_set_voltage(&vmem_vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vmem_values, ARRAY_SIZE(vmem_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(&vmem_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vmem);
+
+static const struct menelaus_vtg vio_vtg = {
+	.name = "VIO",
+	.vtg_reg = MENELAUS_LDO_CTRL1,
+	.vtg_shift = 2,
+	.vtg_bits = 2,
+	.mode_reg = MENELAUS_LDO_CTRL4,
+};
+
+static const struct menelaus_vtg_value vio_values[] = {
+	{ 1500, 0 },
+	{ 1800, 1 },
+	{ 2500, 2 },
+	{ 2800, 3 },
+};
+
+int menelaus_set_vio(unsigned int mV)
+{
+	int val;
+
+	if (mV == 0)
+		return menelaus_set_voltage(&vio_vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vio_values, ARRAY_SIZE(vio_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(&vio_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vio);
+
+static const struct menelaus_vtg_value vdcdc_values[] = {
+	{ 1500, 0 },
+	{ 1800, 1 },
+	{ 2000, 2 },
+	{ 2200, 3 },
+	{ 2400, 4 },
+	{ 2800, 5 },
+	{ 3000, 6 },
+	{ 3300, 7 },
+};
+
+static const struct menelaus_vtg vdcdc2_vtg = {
+	.name = "VDCDC2",
+	.vtg_reg = MENELAUS_DCDC_CTRL1,
+	.vtg_shift = 0,
+	.vtg_bits = 3,
+	.mode_reg = MENELAUS_DCDC_CTRL2,
+};
+
+static const struct menelaus_vtg vdcdc3_vtg = {
+	.name = "VDCDC3",
+	.vtg_reg = MENELAUS_DCDC_CTRL1,
+	.vtg_shift = 3,
+	.vtg_bits = 3,
+	.mode_reg = MENELAUS_DCDC_CTRL3,
+};
+
+int menelaus_set_vdcdc(int dcdc, unsigned int mV)
+{
+	const struct menelaus_vtg *vtg;
+	int val;
+
+	if (dcdc != 2 && dcdc != 3)
+		return -EINVAL;
+	if (dcdc == 2)
+		vtg = &vdcdc2_vtg;
+	else
+		vtg = &vdcdc3_vtg;
+
+	if (mV == 0)
+		return menelaus_set_voltage(vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vdcdc_values,
+				     ARRAY_SIZE(vdcdc_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(vtg, mV, val, 0x03);
+}
+
+static const struct menelaus_vtg_value vmmc_values[] = {
+	{ 1850, 0 },
+	{ 2800, 1 },
+	{ 3000, 2 },
+	{ 3100, 3 },
+};
+
+static const struct menelaus_vtg vmmc_vtg = {
+	.name = "VMMC",
+	.vtg_reg = MENELAUS_LDO_CTRL1,
+	.vtg_shift = 6,
+	.vtg_bits = 2,
+	.mode_reg = MENELAUS_LDO_CTRL7,
+};
+
+int menelaus_set_vmmc(unsigned int mV)
+{
+	int val;
+
+	if (mV == 0)
+		return menelaus_set_voltage(&vmmc_vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vmmc_values, ARRAY_SIZE(vmmc_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(&vmmc_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vmmc);
+
+
+static const struct menelaus_vtg_value vaux_values[] = {
+	{ 1500, 0 },
+	{ 1800, 1 },
+	{ 2500, 2 },
+	{ 2800, 3 },
+};
+
+static const struct menelaus_vtg vaux_vtg = {
+	.name = "VAUX",
+	.vtg_reg = MENELAUS_LDO_CTRL1,
+	.vtg_shift = 4,
+	.vtg_bits = 2,
+	.mode_reg = MENELAUS_LDO_CTRL6,
+};
+
+int menelaus_set_vaux(unsigned int mV)
+{
+	int val;
+
+	if (mV == 0)
+		return menelaus_set_voltage(&vaux_vtg, 0, 0, 0);
+
+	val = menelaus_get_vtg_value(mV, vaux_values, ARRAY_SIZE(vaux_values));
+	if (val < 0)
+		return -EINVAL;
+	return menelaus_set_voltage(&vaux_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vaux);
+
+int menelaus_get_slot_pin_states(void)
+{
+	return menelaus_read_reg(MENELAUS_MCT_PIN_ST);
+}
+EXPORT_SYMBOL(menelaus_get_slot_pin_states);
+
+int menelaus_set_regulator_sleep(int enable, u32 val)
+{
+	int t, ret;
+	struct i2c_client *c = the_menelaus->client;
+
+	mutex_lock(&the_menelaus->lock);
+	ret = menelaus_write_reg(MENELAUS_SLEEP_CTRL2, val);
+	if (ret < 0)
+		goto out;
+
+	dev_dbg(&c->dev, "regulator sleep configuration: %02x\n", val);
+
+	ret = menelaus_read_reg(MENELAUS_GPIO_CTRL);
+	if (ret < 0)
+		goto out;
+	t = ((1 << 6) | 0x04);
+	if (enable)
+		ret |= t;
+	else
+		ret &= ~t;
+	ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret);
+out:
+	mutex_unlock(&the_menelaus->lock);
+	return ret;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* Handles Menelaus interrupts. Does not run in interrupt context */
+static void menelaus_work(struct work_struct *_menelaus)
+{
+	struct menelaus_chip *menelaus =
+			container_of(_menelaus, struct menelaus_chip, work);
+	void (*handler)(struct menelaus_chip *menelaus);
+
+	while (1) {
+		unsigned isr;
+
+		isr = (menelaus_read_reg(MENELAUS_INT_STATUS2)
+				& ~menelaus->mask2) << 8;
+		isr |= menelaus_read_reg(MENELAUS_INT_STATUS1)
+				& ~menelaus->mask1;
+		if (!isr)
+			break;
+
+		while (isr) {
+			int irq = fls(isr) - 1;
+			isr &= ~(1 << irq);
+
+			mutex_lock(&menelaus->lock);
+			menelaus_disable_irq(irq);
+			menelaus_ack_irq(irq);
+			handler = menelaus->handlers[irq];
+			if (handler)
+				handler(menelaus);
+			menelaus_enable_irq(irq);
+			mutex_unlock(&menelaus->lock);
+		}
+	}
+	enable_irq(menelaus->client->irq);
+}
+
+/*
+ * We cannot use I2C in interrupt context, so we just schedule work.
+ */
+static irqreturn_t menelaus_irq(int irq, void *_menelaus)
+{
+	struct menelaus_chip *menelaus = _menelaus;
+
+	disable_irq_nosync(irq);
+	(void)schedule_work(&menelaus->work);
+
+	return IRQ_HANDLED;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/*
+ * The RTC needs to be set once, then it runs on backup battery power.
+ * It supports alarms, including system wake alarms (from some modes);
+ * and 1/second IRQs if requested.
+ */
+#ifdef CONFIG_RTC_DRV_TWL92330
+
+#define RTC_CTRL_RTC_EN		(1 << 0)
+#define RTC_CTRL_AL_EN		(1 << 1)
+#define RTC_CTRL_MODE12		(1 << 2)
+#define RTC_CTRL_EVERY_MASK	(3 << 3)
+#define RTC_CTRL_EVERY_SEC	(0 << 3)
+#define RTC_CTRL_EVERY_MIN	(1 << 3)
+#define RTC_CTRL_EVERY_HR	(2 << 3)
+#define RTC_CTRL_EVERY_DAY	(3 << 3)
+
+#define RTC_UPDATE_EVERY	0x08
+
+#define RTC_HR_PM		(1 << 7)
+
+static void menelaus_to_time(char *regs, struct rtc_time *t)
+{
+	t->tm_sec = BCD2BIN(regs[0]);
+	t->tm_min = BCD2BIN(regs[1]);
+	if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
+		t->tm_hour = BCD2BIN(regs[2] & 0x1f) - 1;
+		if (regs[2] & RTC_HR_PM)
+			t->tm_hour += 12;
+	} else
+		t->tm_hour = BCD2BIN(regs[2] & 0x3f);
+	t->tm_mday = BCD2BIN(regs[3]);
+	t->tm_mon = BCD2BIN(regs[4]) - 1;
+	t->tm_year = BCD2BIN(regs[5]) + 100;
+}
+
+static int time_to_menelaus(struct rtc_time *t, int regnum)
+{
+	int	hour, status;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_sec));
+	if (status < 0)
+		goto fail;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_min));
+	if (status < 0)
+		goto fail;
+
+	if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
+		hour = t->tm_hour + 1;
+		if (hour > 12)
+			hour = RTC_HR_PM | BIN2BCD(hour - 12);
+		else
+			hour = BIN2BCD(hour);
+	} else
+		hour = BIN2BCD(t->tm_hour);
+	status = menelaus_write_reg(regnum++, hour);
+	if (status < 0)
+		goto fail;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mday));
+	if (status < 0)
+		goto fail;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mon + 1));
+	if (status < 0)
+		goto fail;
+
+	status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_year - 100));
+	if (status < 0)
+		goto fail;
+
+	return 0;
+fail:
+	dev_err(&the_menelaus->client->dev, "rtc write reg %02x, err %d\n",
+			--regnum, status);
+	return status;
+}
+
+static int menelaus_read_time(struct device *dev, struct rtc_time *t)
+{
+	struct i2c_msg	msg[2];
+	char		regs[7];
+	int		status;
+
+	/* block read date and time registers */
+	regs[0] = MENELAUS_RTC_SEC;
+
+	msg[0].addr = MENELAUS_I2C_ADDRESS;
+	msg[0].flags = 0;
+	msg[0].len = 1;
+	msg[0].buf = regs;
+
+	msg[1].addr = MENELAUS_I2C_ADDRESS;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = sizeof(regs);
+	msg[1].buf = regs;
+
+	status = i2c_transfer(the_menelaus->client->adapter, msg, 2);
+	if (status != 2) {
+		dev_err(dev, "%s error %d\n", "read", status);
+		return -EIO;
+	}
+
+	menelaus_to_time(regs, t);
+	t->tm_wday = BCD2BIN(regs[6]);
+
+	return 0;
+}
+
+static int menelaus_set_time(struct device *dev, struct rtc_time *t)
+{
+	int		status;
+
+	/* write date and time registers */
+	status = time_to_menelaus(t, MENELAUS_RTC_SEC);
+	if (status < 0)
+		return status;
+	status = menelaus_write_reg(MENELAUS_RTC_WKDAY, BIN2BCD(t->tm_wday));
+	if (status < 0) {
+		dev_err(&the_menelaus->client->dev, "rtc write reg %02x",
+				"err %d\n", MENELAUS_RTC_WKDAY, status);
+		return status;
+	}
+
+	/* now commit the write */
+	status = menelaus_write_reg(MENELAUS_RTC_UPDATE, RTC_UPDATE_EVERY);
+	if (status < 0)
+		dev_err(&the_menelaus->client->dev, "rtc commit time, err %d\n",
+				status);
+
+	return 0;
+}
+
+static int menelaus_read_alarm(struct device *dev, struct rtc_wkalrm *w)
+{
+	struct i2c_msg	msg[2];
+	char		regs[6];
+	int		status;
+
+	/* block read alarm registers */
+	regs[0] = MENELAUS_RTC_AL_SEC;
+
+	msg[0].addr = MENELAUS_I2C_ADDRESS;
+	msg[0].flags = 0;
+	msg[0].len = 1;
+	msg[0].buf = regs;
+
+	msg[1].addr = MENELAUS_I2C_ADDRESS;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = sizeof(regs);
+	msg[1].buf = regs;
+
+	status = i2c_transfer(the_menelaus->client->adapter, msg, 2);
+	if (status != 2) {
+		dev_err(dev, "%s error %d\n", "alarm read", status);
+		return -EIO;
+	}
+
+	menelaus_to_time(regs, &w->time);
+
+	w->enabled = !!(the_menelaus->rtc_control & RTC_CTRL_AL_EN);
+
+	/* NOTE we *could* check if actually pending... */
+	w->pending = 0;
+
+	return 0;
+}
+
+static int menelaus_set_alarm(struct device *dev, struct rtc_wkalrm *w)
+{
+	int		status;
+
+	if (the_menelaus->client->irq <= 0 && w->enabled)
+		return -ENODEV;
+
+	/* clear previous alarm enable */
+	if (the_menelaus->rtc_control & RTC_CTRL_AL_EN) {
+		the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+		status = menelaus_write_reg(MENELAUS_RTC_CTRL,
+				the_menelaus->rtc_control);
+		if (status < 0)
+			return status;
+	}
+
+	/* write alarm registers */
+	status = time_to_menelaus(&w->time, MENELAUS_RTC_AL_SEC);
+	if (status < 0)
+		return status;
+
+	/* enable alarm if requested */
+	if (w->enabled) {
+		the_menelaus->rtc_control |= RTC_CTRL_AL_EN;
+		status = menelaus_write_reg(MENELAUS_RTC_CTRL,
+				the_menelaus->rtc_control);
+	}
+
+	return status;
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+static void menelaus_rtc_update_work(struct menelaus_chip *m)
+{
+	/* report 1/sec update */
+	local_irq_disable();
+	rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_UF);
+	local_irq_enable();
+}
+
+static int menelaus_ioctl(struct device *dev, unsigned cmd, unsigned long arg)
+{
+	int	status;
+
+	if (the_menelaus->client->irq <= 0)
+		return -ENOIOCTLCMD;
+
+	switch (cmd) {
+	/* alarm IRQ */
+	case RTC_AIE_ON:
+		if (the_menelaus->rtc_control & RTC_CTRL_AL_EN)
+			return 0;
+		the_menelaus->rtc_control |= RTC_CTRL_AL_EN;
+		break;
+	case RTC_AIE_OFF:
+		if (!(the_menelaus->rtc_control & RTC_CTRL_AL_EN))
+			return 0;
+		the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+		break;
+	/* 1/second "update" IRQ */
+	case RTC_UIE_ON:
+		if (the_menelaus->uie)
+			return 0;
+		status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ);
+		status = menelaus_add_irq_work(MENELAUS_RTCTMR_IRQ,
+				menelaus_rtc_update_work);
+		if (status == 0)
+			the_menelaus->uie = 1;
+		return status;
+	case RTC_UIE_OFF:
+		if (!the_menelaus->uie)
+			return 0;
+		status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ);
+		if (status == 0)
+			the_menelaus->uie = 0;
+		return status;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control);
+}
+
+#else
+#define menelaus_ioctl	NULL
+#endif
+
+/* REVISIT no compensation register support ... */
+
+static const struct rtc_class_ops menelaus_rtc_ops = {
+	.ioctl			= menelaus_ioctl,
+	.read_time		= menelaus_read_time,
+	.set_time		= menelaus_set_time,
+	.read_alarm		= menelaus_read_alarm,
+	.set_alarm		= menelaus_set_alarm,
+};
+
+static void menelaus_rtc_alarm_work(struct menelaus_chip *m)
+{
+	/* report alarm */
+	local_irq_disable();
+	rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_AF);
+	local_irq_enable();
+
+	/* then disable it; alarms are oneshot */
+	the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+	menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control);
+}
+
+static inline void menelaus_rtc_init(struct menelaus_chip *m)
+{
+	int	alarm = (m->client->irq > 0);
+
+	/* assume 32KDETEN pin is pulled high */
+	if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) {
+		dev_dbg(&m->client->dev, "no 32k oscillator\n");
+		return;
+	}
+
+	/* support RTC alarm; it can issue wakeups */
+	if (alarm) {
+		if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ,
+				menelaus_rtc_alarm_work) < 0) {
+			dev_err(&m->client->dev, "can't handle RTC alarm\n");
+			return;
+		}
+		device_init_wakeup(&m->client->dev, 1);
+	}
+
+	/* be sure RTC is enabled; allow 1/sec irqs; leave 12hr mode alone */
+	m->rtc_control = menelaus_read_reg(MENELAUS_RTC_CTRL);
+	if (!(m->rtc_control & RTC_CTRL_RTC_EN)
+			|| (m->rtc_control & RTC_CTRL_AL_EN)
+			|| (m->rtc_control & RTC_CTRL_EVERY_MASK)) {
+		if (!(m->rtc_control & RTC_CTRL_RTC_EN)) {
+			dev_warn(&m->client->dev, "rtc clock needs setting\n");
+			m->rtc_control |= RTC_CTRL_RTC_EN;
+		}
+		m->rtc_control &= ~RTC_CTRL_EVERY_MASK;
+		m->rtc_control &= ~RTC_CTRL_AL_EN;
+		menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control);
+	}
+
+	m->rtc = rtc_device_register(DRIVER_NAME,
+			&m->client->dev,
+			&menelaus_rtc_ops, THIS_MODULE);
+	if (IS_ERR(m->rtc)) {
+		if (alarm) {
+			menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ);
+			device_init_wakeup(&m->client->dev, 0);
+		}
+		dev_err(&m->client->dev, "can't register RTC: %d\n",
+				(int) PTR_ERR(m->rtc));
+		the_menelaus->rtc = NULL;
+	}
+}
+
+#else
+
+static inline void menelaus_rtc_init(struct menelaus_chip *m)
+{
+	/* nothing */
+}
+
+#endif
+
+/*-----------------------------------------------------------------------*/
+
+static struct i2c_driver menelaus_i2c_driver;
+
+static int menelaus_probe(struct i2c_client *client)
+{
+	struct menelaus_chip	*menelaus;
+	int			rev = 0, val;
+	int			err = 0;
+	struct menelaus_platform_data *menelaus_pdata =
+					client->dev.platform_data;
+
+	if (the_menelaus) {
+		dev_dbg(&client->dev, "only one %s for now\n",
+				DRIVER_NAME);
+		return -ENODEV;
+	}
+
+	menelaus = kzalloc(sizeof *menelaus, GFP_KERNEL);
+	if (!menelaus)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, menelaus);
+
+	the_menelaus = menelaus;
+	menelaus->client = client;
+
+	/* If a true probe check the device */
+	rev = menelaus_read_reg(MENELAUS_REV);
+	if (rev < 0) {
+		pr_err("device not found");
+		err = -ENODEV;
+		goto fail1;
+	}
+
+	/* Ack and disable all Menelaus interrupts */
+	menelaus_write_reg(MENELAUS_INT_ACK1, 0xff);
+	menelaus_write_reg(MENELAUS_INT_ACK2, 0xff);
+	menelaus_write_reg(MENELAUS_INT_MASK1, 0xff);
+	menelaus_write_reg(MENELAUS_INT_MASK2, 0xff);
+	menelaus->mask1 = 0xff;
+	menelaus->mask2 = 0xff;
+
+	/* Set output buffer strengths */
+	menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73);
+
+	if (client->irq > 0) {
+		err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED,
+				  DRIVER_NAME, menelaus);
+		if (err) {
+			dev_dbg(&client->dev,  "can't get IRQ %d, err %d",
+					client->irq, err);
+			goto fail1;
+		}
+	}
+
+	mutex_init(&menelaus->lock);
+	INIT_WORK(&menelaus->work, menelaus_work);
+
+	pr_info("Menelaus rev %d.%d\n", rev >> 4, rev & 0x0f);
+
+	val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
+	if (val < 0)
+		goto fail2;
+	if (val & (1 << 7))
+		menelaus->vcore_hw_mode = 1;
+	else
+		menelaus->vcore_hw_mode = 0;
+
+	if (menelaus_pdata != NULL && menelaus_pdata->late_init != NULL) {
+		err = menelaus_pdata->late_init(&client->dev);
+		if (err < 0)
+			goto fail2;
+	}
+
+	menelaus_rtc_init(menelaus);
+
+	return 0;
+fail2:
+	free_irq(client->irq, menelaus);
+	flush_scheduled_work();
+fail1:
+	kfree(menelaus);
+	return err;
+}
+
+static int __exit menelaus_remove(struct i2c_client *client)
+{
+	struct menelaus_chip	*menelaus = i2c_get_clientdata(client);
+
+	free_irq(client->irq, menelaus);
+	kfree(menelaus);
+	i2c_set_clientdata(client, NULL);
+	the_menelaus = NULL;
+	return 0;
+}
+
+static struct i2c_driver menelaus_i2c_driver = {
+	.driver = {
+		.name		= DRIVER_NAME,
+	},
+	.probe		= menelaus_probe,
+	.remove		= __exit_p(menelaus_remove),
+};
+
+static int __init menelaus_init(void)
+{
+	int res;
+
+	res = i2c_add_driver(&menelaus_i2c_driver);
+	if (res < 0) {
+		pr_err("driver registration failed\n");
+		return res;
+	}
+
+	return 0;
+}
+
+static void __exit menelaus_exit(void)
+{
+	i2c_del_driver(&menelaus_i2c_driver);
+
+	/* FIXME: Shutdown menelaus parts that can be shut down */
+}
+
+MODULE_AUTHOR("Texas Instruments, Inc. (and others)");
+MODULE_DESCRIPTION("I2C interface for Menelaus.");
+MODULE_LICENSE("GPL");
+
+module_init(menelaus_init);
+module_exit(menelaus_exit);
diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
new file mode 100644
index 0000000..3de4b19
--- /dev/null
+++ b/drivers/i2c/chips/tsl2550.c
@@ -0,0 +1,460 @@
+/*
+ *  tsl2550.c - Linux kernel modules for ambient light sensor
+ *
+ *  Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ *  Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#define TSL2550_DRV_NAME	"tsl2550"
+#define DRIVER_VERSION		"1.1.1"
+
+/*
+ * Defines
+ */
+
+#define TSL2550_POWER_DOWN		0x00
+#define TSL2550_POWER_UP		0x03
+#define TSL2550_STANDARD_RANGE		0x18
+#define TSL2550_EXTENDED_RANGE		0x1d
+#define TSL2550_READ_ADC0		0x43
+#define TSL2550_READ_ADC1		0x83
+
+/*
+ * Structs
+ */
+
+struct tsl2550_data {
+	struct i2c_client *client;
+	struct mutex update_lock;
+
+	unsigned int power_state : 1;
+	unsigned int operating_mode : 1;
+};
+
+/*
+ * Global data
+ */
+
+static const u8 TSL2550_MODE_RANGE[2] = {
+	TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
+};
+
+/*
+ * Management functions
+ */
+
+static int tsl2550_set_operating_mode(struct i2c_client *client, int mode)
+{
+	struct tsl2550_data *data = i2c_get_clientdata(client);
+
+	int ret = i2c_smbus_write_byte(client, TSL2550_MODE_RANGE[mode]);
+
+	data->operating_mode = mode;
+
+	return ret;
+}
+
+static int tsl2550_set_power_state(struct i2c_client *client, int state)
+{
+	struct tsl2550_data *data = i2c_get_clientdata(client);
+	int ret;
+
+	if (state == 0)
+		ret = i2c_smbus_write_byte(client, TSL2550_POWER_DOWN);
+	else {
+		ret = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
+
+		/* On power up we should reset operating mode also... */
+		tsl2550_set_operating_mode(client, data->operating_mode);
+	}
+
+	data->power_state = state;
+
+	return ret;
+}
+
+static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd)
+{
+	unsigned long end;
+	int loop = 0, ret = 0;
+
+	/*
+	 * Read ADC channel waiting at most 400ms (see data sheet for further
+	 * info).
+	 * To avoid long busy wait we spin for few milliseconds then
+	 * start sleeping.
+	 */
+	end = jiffies + msecs_to_jiffies(400);
+	while (time_before(jiffies, end)) {
+		i2c_smbus_write_byte(client, cmd);
+
+		if (loop++ < 5)
+			mdelay(1);
+		else
+			msleep(1);
+
+		ret = i2c_smbus_read_byte(client);
+		if (ret < 0)
+			return ret;
+		else if (ret & 0x0080)
+			break;
+	}
+	if (!(ret & 0x80))
+		return -EIO;
+	return ret & 0x7f;	/* remove the "valid" bit */
+}
+
+/*
+ * LUX calculation
+ */
+
+#define	TSL2550_MAX_LUX		1846
+
+static const u8 ratio_lut[] = {
+	100, 100, 100, 100, 100, 100, 100, 100,
+	100, 100, 100, 100, 100, 100, 99, 99,
+	99, 99, 99, 99, 99, 99, 99, 99,
+	99, 99, 99, 98, 98, 98, 98, 98,
+	98, 98, 97, 97, 97, 97, 97, 96,
+	96, 96, 96, 95, 95, 95, 94, 94,
+	93, 93, 93, 92, 92, 91, 91, 90,
+	89, 89, 88, 87, 87, 86, 85, 84,
+	83, 82, 81, 80, 79, 78, 77, 75,
+	74, 73, 71, 69, 68, 66, 64, 62,
+	60, 58, 56, 54, 52, 49, 47, 44,
+	42, 41, 40, 40, 39, 39, 38, 38,
+	37, 37, 37, 36, 36, 36, 35, 35,
+	35, 35, 34, 34, 34, 34, 33, 33,
+	33, 33, 32, 32, 32, 32, 32, 31,
+	31, 31, 31, 31, 30, 30, 30, 30,
+	30,
+};
+
+static const u16 count_lut[] = {
+	0, 1, 2, 3, 4, 5, 6, 7,
+	8, 9, 10, 11, 12, 13, 14, 15,
+	16, 18, 20, 22, 24, 26, 28, 30,
+	32, 34, 36, 38, 40, 42, 44, 46,
+	49, 53, 57, 61, 65, 69, 73, 77,
+	81, 85, 89, 93, 97, 101, 105, 109,
+	115, 123, 131, 139, 147, 155, 163, 171,
+	179, 187, 195, 203, 211, 219, 227, 235,
+	247, 263, 279, 295, 311, 327, 343, 359,
+	375, 391, 407, 423, 439, 455, 471, 487,
+	511, 543, 575, 607, 639, 671, 703, 735,
+	767, 799, 831, 863, 895, 927, 959, 991,
+	1039, 1103, 1167, 1231, 1295, 1359, 1423, 1487,
+	1551, 1615, 1679, 1743, 1807, 1871, 1935, 1999,
+	2095, 2223, 2351, 2479, 2607, 2735, 2863, 2991,
+	3119, 3247, 3375, 3503, 3631, 3759, 3887, 4015,
+};
+
+/*
+ * This function is described into Taos TSL2550 Designer's Notebook
+ * pages 2, 3.
+ */
+static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
+{
+	unsigned int lux;
+
+	/* Look up count from channel values */
+	u16 c0 = count_lut[ch0];
+	u16 c1 = count_lut[ch1];
+
+	/*
+	 * Calculate ratio.
+	 * Note: the "128" is a scaling factor
+	 */
+	u8 r = 128;
+
+	/* Avoid division by 0 and count 1 cannot be greater than count 0 */
+	if (c0 && (c1 <= c0))
+		r = c1 * 128 / c0;
+	else
+		return -1;
+
+	/* Calculate LUX */
+	lux = ((c0 - c1) * ratio_lut[r]) / 256;
+
+	/* LUX range check */
+	return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
+}
+
+/*
+ * SysFS support
+ */
+
+static ssize_t tsl2550_show_power_state(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
+
+	return sprintf(buf, "%u\n", data->power_state);
+}
+
+static ssize_t tsl2550_store_power_state(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tsl2550_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int ret;
+
+	if (val < 0 || val > 1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	ret = tsl2550_set_power_state(client, val);
+	mutex_unlock(&data->update_lock);
+
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
+		   tsl2550_show_power_state, tsl2550_store_power_state);
+
+static ssize_t tsl2550_show_operating_mode(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
+
+	return sprintf(buf, "%u\n", data->operating_mode);
+}
+
+static ssize_t tsl2550_store_operating_mode(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tsl2550_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int ret;
+
+	if (val < 0 || val > 1)
+		return -EINVAL;
+
+	if (data->power_state == 0)
+		return -EBUSY;
+
+	mutex_lock(&data->update_lock);
+	ret = tsl2550_set_operating_mode(client, val);
+	mutex_unlock(&data->update_lock);
+
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
+		   tsl2550_show_operating_mode, tsl2550_store_operating_mode);
+
+static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
+{
+	u8 ch0, ch1;
+	int ret;
+
+	ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
+	if (ret < 0)
+		return ret;
+	ch0 = ret;
+
+	mdelay(1);
+
+	ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
+	if (ret < 0)
+		return ret;
+	ch1 = ret;
+
+	/* Do the job */
+	ret = tsl2550_calculate_lux(ch0, ch1);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t tsl2550_show_lux1_input(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tsl2550_data *data = i2c_get_clientdata(client);
+	int ret;
+
+	/* No LUX data if not operational */
+	if (!data->power_state)
+		return -EBUSY;
+
+	mutex_lock(&data->update_lock);
+	ret = __tsl2550_show_lux(client, buf);
+	mutex_unlock(&data->update_lock);
+
+	return ret;
+}
+
+static DEVICE_ATTR(lux1_input, S_IRUGO,
+		   tsl2550_show_lux1_input, NULL);
+
+static struct attribute *tsl2550_attributes[] = {
+	&dev_attr_power_state.attr,
+	&dev_attr_operating_mode.attr,
+	&dev_attr_lux1_input.attr,
+	NULL
+};
+
+static const struct attribute_group tsl2550_attr_group = {
+	.attrs = tsl2550_attributes,
+};
+
+/*
+ * Initialization function
+ */
+
+static int tsl2550_init_client(struct i2c_client *client)
+{
+	struct tsl2550_data *data = i2c_get_clientdata(client);
+	int err;
+
+	/*
+	 * Probe the chip. To do so we try to power up the device and then to
+	 * read back the 0x03 code
+	 */
+	err = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
+	if (err < 0)
+		return err;
+	mdelay(1);
+	if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP)
+		return -ENODEV;
+	data->power_state = 1;
+
+	/* Set the default operating mode */
+	err = i2c_smbus_write_byte(client,
+				   TSL2550_MODE_RANGE[data->operating_mode]);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+
+static struct i2c_driver tsl2550_driver;
+static int __devinit tsl2550_probe(struct i2c_client *client)
+{
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct tsl2550_data *data;
+	int *opmode, err = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
+		err = -EIO;
+		goto exit;
+	}
+
+	data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	data->client = client;
+	i2c_set_clientdata(client, data);
+
+	/* Check platform data */
+	opmode = client->dev.platform_data;
+	if (opmode) {
+		if (*opmode < 0 || *opmode > 1) {
+			dev_err(&client->dev, "invalid operating_mode (%d)\n",
+					*opmode);
+			err = -EINVAL;
+			goto exit_kfree;
+		}
+		data->operating_mode = *opmode;
+	} else
+		data->operating_mode = 0;	/* default mode is standard */
+	dev_info(&client->dev, "%s operating mode\n",
+			data->operating_mode ? "extended" : "standard");
+
+	mutex_init(&data->update_lock);
+
+	/* Initialize the TSL2550 chip */
+	err = tsl2550_init_client(client);
+	if (err)
+		goto exit_kfree;
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
+	if (err)
+		goto exit_kfree;
+
+	dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+
+	return 0;
+
+exit_kfree:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int __devexit tsl2550_remove(struct i2c_client *client)
+{
+	sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
+
+	/* Power down the device */
+	tsl2550_set_power_state(client, 0);
+
+	kfree(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+static struct i2c_driver tsl2550_driver = {
+	.driver = {
+		.name	= TSL2550_DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe	= tsl2550_probe,
+	.remove	= __devexit_p(tsl2550_remove),
+};
+
+static int __init tsl2550_init(void)
+{
+	return i2c_add_driver(&tsl2550_driver);
+}
+
+static void __exit tsl2550_exit(void)
+{
+	i2c_del_driver(&tsl2550_driver);
+}
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(tsl2550_init);
+module_exit(tsl2550_exit);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 64f8e56..6971a62 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -207,6 +207,7 @@
  * i2c_new_device - instantiate an i2c device for use with a new style driver
  * @adap: the adapter managing the device
  * @info: describes one I2C device; bus_num is ignored
+ * Context: can sleep
  *
  * Create a device to work with a new style i2c driver, where binding is
  * handled through driver model probe()/remove() methods.  This call is not
@@ -255,6 +256,7 @@
 /**
  * i2c_unregister_device - reverse effect of i2c_new_device()
  * @client: value returned from i2c_new_device()
+ * Context: can sleep
  */
 void i2c_unregister_device(struct i2c_client *client)
 {
@@ -379,6 +381,7 @@
 /**
  * i2c_add_adapter - declare i2c adapter, use dynamic bus number
  * @adapter: the adapter to add
+ * Context: can sleep
  *
  * This routine is used to declare an I2C adapter when its bus number
  * doesn't matter.  Examples: for I2C adapters dynamically added by
@@ -416,6 +419,7 @@
 /**
  * i2c_add_numbered_adapter - declare i2c adapter, use static bus number
  * @adap: the adapter to register (with adap->nr initialized)
+ * Context: can sleep
  *
  * This routine is used to declare an I2C adapter when its bus number
  * matters.  Example: for I2C adapters from system-on-chip CPUs, or
@@ -463,6 +467,14 @@
 }
 EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
 
+/**
+ * i2c_del_adapter - unregister I2C adapter
+ * @adap: the adapter being unregistered
+ * Context: can sleep
+ *
+ * This unregisters an I2C adapter which was previously registered
+ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+ */
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
 	struct list_head  *item, *_n;
@@ -598,6 +610,7 @@
 /**
  * i2c_del_driver - unregister I2C driver
  * @driver: the driver being unregistered
+ * Context: can sleep
  */
 void i2c_del_driver(struct i2c_driver *driver)
 {
@@ -697,9 +710,10 @@
 	if (client->driver)
 		client->dev.driver = &client->driver->driver;
 
-	if (client->driver && !is_newstyle_driver(client->driver))
+	if (client->driver && !is_newstyle_driver(client->driver)) {
 		client->dev.release = i2c_client_release;
-	else
+		client->dev.uevent_suppress = 1;
+	} else
 		client->dev.release = i2c_client_dev_release;
 
 	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
@@ -1330,10 +1344,14 @@
 EXPORT_SYMBOL(i2c_smbus_write_block_data);
 
 /* Returns the number of read bytes */
-s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
+s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
+				  u8 length, u8 *values)
 {
 	union i2c_smbus_data data;
 
+	if (length > I2C_SMBUS_BLOCK_MAX)
+		length = I2C_SMBUS_BLOCK_MAX;
+	data.block[0] = length;
 	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
 	                      I2C_SMBUS_READ,command,
 	                      I2C_SMBUS_I2C_BLOCK_DATA,&data))
@@ -1454,7 +1472,7 @@
 		break;
 	case I2C_SMBUS_I2C_BLOCK_DATA:
 		if (read_write == I2C_SMBUS_READ) {
-			msg[1].len = I2C_SMBUS_BLOCK_MAX;
+			msg[1].len = data->block[0];
 		} else {
 			msg[0].len = data->block[0] + 1;
 			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
@@ -1510,9 +1528,7 @@
 				data->word = msgbuf1[0] | (msgbuf1[1] << 8);
 				break;
 			case I2C_SMBUS_I2C_BLOCK_DATA:
-				/* fixed at 32 for now */
-				data->block[0] = I2C_SMBUS_BLOCK_MAX;
-				for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
+				for (i = 0; i < data->block[0]; i++)
 					data->block[i+1] = msgbuf1[i];
 				break;
 			case I2C_SMBUS_BLOCK_DATA:
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index e7a7097..64eee95 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -283,6 +283,7 @@
 		    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
 		    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
 		    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
+		    (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
 		    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
 		    (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
 			dev_dbg(&client->adapter->dev,
@@ -329,10 +330,18 @@
 
 		if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
 		    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+		    (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
 		    (data_arg.read_write == I2C_SMBUS_WRITE)) {
 			if (copy_from_user(&temp, data_arg.data, datasize))
 				return -EFAULT;
 		}
+		if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
+			/* Convert old I2C block commands to the new
+			   convention. This preserves binary compatibility. */
+			data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
+			if (data_arg.read_write == I2C_SMBUS_READ)
+				temp.block[0] = I2C_SMBUS_BLOCK_MAX;
+		}
 		res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
 		      data_arg.read_write,
 		      data_arg.command,data_arg.size,&temp);
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 66f8262..c89b5f4 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -18,10 +18,10 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/scatterlist.h>
+#include <linux/io.h>
 
 #include <asm/dma.h>
 #include <asm/ecard.h>
-#include <asm/io.h>
 
 #define ICS_IDENT_OFFSET		0x2280
 
@@ -448,23 +448,21 @@
 			ICS_ARCIN_V6_INTRSTAT_1)) & 1;
 }
 
-static int icside_dma_timeout(ide_drive_t *drive)
+static void icside_dma_timeout(ide_drive_t *drive)
 {
 	printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
 
 	if (icside_dma_test_irq(drive))
-		return 0;
+		return;
 
-	ide_dump_status(drive, "DMA timeout",
-		HWIF(drive)->INB(IDE_STATUS_REG));
+	ide_dump_status(drive, "DMA timeout", HWIF(drive)->INB(IDE_STATUS_REG));
 
-	return icside_dma_end(drive);
+	icside_dma_end(drive);
 }
 
-static int icside_dma_lostirq(ide_drive_t *drive)
+static void icside_dma_lost_irq(ide_drive_t *drive)
 {
 	printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-	return 1;
 }
 
 static void icside_dma_init(ide_hwif_t *hwif)
@@ -490,8 +488,8 @@
 	hwif->dma_start		= icside_dma_start;
 	hwif->ide_dma_end	= icside_dma_end;
 	hwif->ide_dma_test_irq	= icside_dma_test_irq;
-	hwif->ide_dma_timeout	= icside_dma_timeout;
-	hwif->ide_dma_lostirq	= icside_dma_lostirq;
+	hwif->dma_timeout	= icside_dma_timeout;
+	hwif->dma_lost_irq	= icside_dma_lost_irq;
 
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index ca0341c..886091b 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -819,7 +819,7 @@
 		hwif->dma_host_off = &cris_dma_off;
 		hwif->dma_host_on = &cris_dma_on;
 		hwif->dma_off_quietly = &cris_dma_off;
-		hwif->udma_four = 0;
+		hwif->cbl = ATA_CBL_PATA40;
 		hwif->ultra_mask = cris_ultra_mask;
 		hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
 		hwif->autodma = 1;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 252ab82..1486eb2 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -481,7 +481,7 @@
 		else
 			printk("  Unknown Error Type: ");
 
-		if (sense->sense_key < ARY_LEN(sense_key_texts))
+		if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
 			s = sense_key_texts[sense->sense_key];
 
 		printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
@@ -491,7 +491,7 @@
 				 sense->ascq);
 			s = buf;
 		} else {
-			int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
+			int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
 			unsigned long key = (sense->sense_key << 16);
 			key |= (sense->asc << 8);
 			if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
@@ -524,7 +524,7 @@
 
 		if (failed_command != NULL) {
 
-			int lo=0, mid, hi= ARY_LEN (packet_command_texts);
+			int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
 			s = NULL;
 
 			while (hi > lo) {
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index ad1f2ed..228b29c 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -498,8 +498,6 @@
  * Descriptions of ATAPI error codes.
  */
 
-#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
-
 /* This stuff should be in cdrom.h, since it is now generic... */
 
 /* ATAPI sense keys (from table 140 of ATAPI 2.6) */
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7fff773..b1304a7 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1037,6 +1037,17 @@
 
 static int ide_disk_probe(ide_drive_t *drive);
 
+/*
+ * On HPA drives the capacity needs to be
+ * reinitilized on resume otherwise the disk
+ * can not be used and a hard reset is required
+ */
+static void ide_disk_resume(ide_drive_t *drive)
+{
+	if (idedisk_supports_hpa(drive->id))
+		init_idedisk_capacity(drive);
+}
+
 static void ide_device_shutdown(ide_drive_t *drive)
 {
 #ifdef	CONFIG_ALPHA
@@ -1071,6 +1082,7 @@
 	},
 	.probe			= ide_disk_probe,
 	.remove			= ide_disk_remove,
+	.resume			= ide_disk_resume,
 	.shutdown		= ide_device_shutdown,
 	.version		= IDEDISK_VERSION,
 	.media			= ide_disk,
@@ -1178,11 +1190,11 @@
 	return generic_ide_ioctl(drive, file, bdev, cmd, arg);
 
 read_val:
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	spin_lock_irqsave(&ide_lock, flags);
 	err = *val;
 	spin_unlock_irqrestore(&ide_lock, flags);
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	return err >= 0 ? put_user(err, (long __user *)arg) : err;
 
 set_val:
@@ -1192,9 +1204,9 @@
 		if (!capable(CAP_SYS_ADMIN))
 			err = -EACCES;
 		else {
-			down(&ide_setting_sem);
+			mutex_lock(&ide_setting_mtx);
 			err = setfunc(drive, arg);
-			up(&ide_setting_sem);
+			mutex_unlock(&ide_setting_mtx);
 		}
 	}
 	return err;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index b77b7d1..5fe1d72 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -91,43 +91,45 @@
 
 static const struct drive_list_entry drive_whitelist [] = {
 
-	{ "Micropolis 2112A"	,       "ALL"		},
-	{ "CONNER CTMA 4000"	,       "ALL"		},
-	{ "CONNER CTT8000-A"	,       "ALL"		},
-	{ "ST34342A"		,	"ALL"		},
+	{ "Micropolis 2112A"	,       NULL		},
+	{ "CONNER CTMA 4000"	,       NULL		},
+	{ "CONNER CTT8000-A"	,       NULL		},
+	{ "ST34342A"		,	NULL		},
 	{ NULL			,	NULL		}
 };
 
 static const struct drive_list_entry drive_blacklist [] = {
 
-	{ "WDC AC11000H"	,	"ALL"		},
-	{ "WDC AC22100H"	,	"ALL"		},
-	{ "WDC AC32500H"	,	"ALL"		},
-	{ "WDC AC33100H"	,	"ALL"		},
-	{ "WDC AC31600H"	,	"ALL"		},
+	{ "WDC AC11000H"	,	NULL 		},
+	{ "WDC AC22100H"	,	NULL 		},
+	{ "WDC AC32500H"	,	NULL 		},
+	{ "WDC AC33100H"	,	NULL 		},
+	{ "WDC AC31600H"	,	NULL 		},
 	{ "WDC AC32100H"	,	"24.09P07"	},
 	{ "WDC AC23200L"	,	"21.10N21"	},
-	{ "Compaq CRD-8241B"	,	"ALL"		},
-	{ "CRD-8400B"		,	"ALL"		},
-	{ "CRD-8480B",			"ALL"		},
-	{ "CRD-8482B",			"ALL"		},
- 	{ "CRD-84"		,	"ALL"		},
-	{ "SanDisk SDP3B"	,	"ALL"		},
-	{ "SanDisk SDP3B-64"	,	"ALL"		},
-	{ "SANYO CD-ROM CRD"	,	"ALL"		},
-	{ "HITACHI CDR-8"	,	"ALL"		},
-	{ "HITACHI CDR-8335"	,	"ALL"		},
-	{ "HITACHI CDR-8435"	,	"ALL"		},
-	{ "Toshiba CD-ROM XM-6202B"	,	"ALL"		},
-	{ "CD-532E-A"		,	"ALL"		},
-	{ "E-IDE CD-ROM CR-840",	"ALL"		},
-	{ "CD-ROM Drive/F5A",	"ALL"		},
-	{ "WPI CDD-820",		"ALL"		},
-	{ "SAMSUNG CD-ROM SC-148C",	"ALL"		},
-	{ "SAMSUNG CD-ROM SC",	"ALL"		},
-	{ "SanDisk SDP3B-64"	,	"ALL"		},
-	{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",	"ALL"		},
-	{ "_NEC DV5800A",               "ALL"           },  
+	{ "Compaq CRD-8241B"	,	NULL 		},
+	{ "CRD-8400B"		,	NULL 		},
+	{ "CRD-8480B",			NULL 		},
+	{ "CRD-8482B",			NULL 		},
+	{ "CRD-84"		,	NULL 		},
+	{ "SanDisk SDP3B"	,	NULL 		},
+	{ "SanDisk SDP3B-64"	,	NULL 		},
+	{ "SANYO CD-ROM CRD"	,	NULL 		},
+	{ "HITACHI CDR-8"	,	NULL 		},
+	{ "HITACHI CDR-8335"	,	NULL 		},
+	{ "HITACHI CDR-8435"	,	NULL 		},
+	{ "Toshiba CD-ROM XM-6202B"	,	NULL 		},
+	{ "TOSHIBA CD-ROM XM-1702BC",	NULL 		},
+	{ "CD-532E-A"		,	NULL 		},
+	{ "E-IDE CD-ROM CR-840",	NULL 		},
+	{ "CD-ROM Drive/F5A",	NULL 		},
+	{ "WPI CDD-820",		NULL 		},
+	{ "SAMSUNG CD-ROM SC-148C",	NULL 		},
+	{ "SAMSUNG CD-ROM SC",	NULL 		},
+	{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",	NULL 		},
+	{ "_NEC DV5800A",               NULL            },
+	{ "SAMSUNG CD-ROM SN-124",	"N001" },
+	{ "Seagate STT20000A",		NULL  },
 	{ NULL			,	NULL		}
 
 };
@@ -145,8 +147,8 @@
 {
 	for ( ; drive_table->id_model ; drive_table++)
 		if ((!strcmp(drive_table->id_model, id->model)) &&
-		    ((strstr(id->fw_rev, drive_table->id_firmware)) ||
-		     (!strcmp(drive_table->id_firmware, "ALL"))))
+		    (!drive_table->id_firmware ||
+		     strstr(id->fw_rev, drive_table->id_firmware)))
 			return 1;
 	return 0;
 }
@@ -700,8 +702,22 @@
 			mask = id->dma_mword & hwif->mwdma_mask;
 		break;
 	case XFER_SW_DMA_0:
-		if (id->field_valid & 2)
+		if (id->field_valid & 2) {
 			mask = id->dma_1word & hwif->swdma_mask;
+		} else if (id->tDMA) {
+			/*
+			 * ide_fix_driveid() doesn't convert ->tDMA to the
+			 * CPU endianness so we need to do it here
+			 */
+			u8 mode = le16_to_cpu(id->tDMA);
+
+			/*
+			 * if the mode is valid convert it to the mask
+			 * (the maximum allowed mode is XFER_SW_DMA_2)
+			 */
+			if (mode <= 2)
+				mask = ((2 << mode) - 1) & hwif->swdma_mask;
+		}
 		break;
 	default:
 		BUG();
@@ -845,27 +861,27 @@
 	return rc;
 }
 
-EXPORT_SYMBOL_GPL(ide_set_dma);
-
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-int __ide_dma_lostirq (ide_drive_t *drive)
+void ide_dma_lost_irq (ide_drive_t *drive)
 {
 	printk("%s: DMA interrupt recovery\n", drive->name);
-	return 1;
 }
 
-EXPORT_SYMBOL(__ide_dma_lostirq);
+EXPORT_SYMBOL(ide_dma_lost_irq);
 
-int __ide_dma_timeout (ide_drive_t *drive)
+void ide_dma_timeout (ide_drive_t *drive)
 {
-	printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
-	if (HWIF(drive)->ide_dma_test_irq(drive))
-		return 0;
+	ide_hwif_t *hwif = HWIF(drive);
 
-	return HWIF(drive)->ide_dma_end(drive);
+	printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
+
+	if (hwif->ide_dma_test_irq(drive))
+		return;
+
+	hwif->ide_dma_end(drive);
 }
 
-EXPORT_SYMBOL(__ide_dma_timeout);
+EXPORT_SYMBOL(ide_dma_timeout);
 
 /*
  * Needed for allowing full modular support of ide-driver
@@ -1016,10 +1032,10 @@
 		hwif->ide_dma_end = &__ide_dma_end;
 	if (!hwif->ide_dma_test_irq)
 		hwif->ide_dma_test_irq = &__ide_dma_test_irq;
-	if (!hwif->ide_dma_timeout)
-		hwif->ide_dma_timeout = &__ide_dma_timeout;
-	if (!hwif->ide_dma_lostirq)
-		hwif->ide_dma_lostirq = &__ide_dma_lostirq;
+	if (!hwif->dma_timeout)
+		hwif->dma_timeout = &ide_dma_timeout;
+	if (!hwif->dma_lost_irq)
+		hwif->dma_lost_irq = &ide_dma_lost_irq;
 
 	if (hwif->chipset != ide_trm290) {
 		u8 dma_stat = hwif->INB(hwif->dma_status);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index f429be8..a21f585 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1258,19 +1258,25 @@
 	set_bit(PC_DMA_RECOMMENDED, &pc->flags);
 }
 
-static int
+static void
 idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
 {
-	/*
-	 * just support eject for now, it would not be hard to make the
-	 * REQ_BLOCK_PC support fully-featured
-	 */
-	if (rq->cmd[0] != IDEFLOPPY_START_STOP_CMD)
-		return 1;
-
 	idefloppy_init_pc(pc);
+	pc->callback = &idefloppy_rw_callback;
 	memcpy(pc->c, rq->cmd, sizeof(pc->c));
-	return 0;
+	pc->rq = rq;
+	pc->b_count = rq->data_len;
+	if (rq->data_len && rq_data_dir(rq) == WRITE)
+		set_bit(PC_WRITING, &pc->flags);
+	pc->buffer = rq->data;
+	if (rq->bio)
+		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
+		
+	/*
+	 * possibly problematic, doesn't look like ide-floppy correctly
+	 * handled scattered requests if dma fails...
+	 */
+	pc->request_transfer = pc->buffer_size = rq->data_len;
 }
 
 /*
@@ -1317,10 +1323,7 @@
 		pc = (idefloppy_pc_t *) rq->buffer;
 	} else if (blk_pc_request(rq)) {
 		pc = idefloppy_next_pc_storage(drive);
-		if (idefloppy_blockpc_cmd(floppy, pc, rq)) {
-			idefloppy_do_end_request(drive, 0, 0);
-			return ide_stopped;
-		}
+		idefloppy_blockpc_cmd(floppy, pc, rq);
 	} else {
 		blk_dump_rq_flags(rq,
 			"ide-floppy: unsupported command in queue");
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index bfe8f1b..c5b5011 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -1350,7 +1350,7 @@
 						hwif->INB(IDE_STATUS_REG));
 	} else {
 		printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
-		(void) hwif->ide_dma_timeout(drive);
+		hwif->dma_timeout(drive);
 	}
 
 	/*
@@ -1466,7 +1466,7 @@
 				startstop = handler(drive);
 			} else if (drive_is_ready(drive)) {
 				if (drive->waiting_for_dma)
-					(void) hwgroup->hwif->ide_dma_lostirq(drive);
+					hwgroup->hwif->dma_lost_irq(drive);
 				(void)ide_ack_intr(hwif);
 				printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
 				startstop = handler(drive);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index f0be5f6..92578b6 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -574,7 +574,10 @@
 	ide_hwif_t *hwif = drive->hwif;
 	struct hd_driveid *id = drive->id;
 
-	if (hwif->udma_four == 0)
+	if (hwif->cbl == ATA_CBL_PATA40_SHORT)
+		return 1;
+
+	if (hwif->cbl != ATA_CBL_PATA80)
 		goto no_80w;
 
 	/* Check for SATA but only if we are ATA5 or higher */
@@ -600,7 +603,8 @@
 
 	printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
 			    "limiting max speed to UDMA33\n",
-			    drive->name, hwif->udma_four ? "drive" : "host");
+			    drive->name,
+			    hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
 
 	drive->udma33_warned = 1;
 
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 3cebed7..5a4c5ea 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -144,7 +144,7 @@
 	local_irq_enable();
 	ide_fix_driveid(id);
 
-#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
+#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
 	/*
 	 * EATA SCSI controllers do a hardware ATA emulation:
 	 * Ignore them if there is a driver for them available.
@@ -154,7 +154,7 @@
 		printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
 		goto err_misc;
 	}
-#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */
+#endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */
 
 	/*
 	 *  WIN_IDENTIFY returns little-endian info,
@@ -574,11 +574,11 @@
 			/* look for ATAPI device */
 			(void) do_probe(drive, WIN_PIDENTIFY);
 		}
-		if (strstr(drive->id->model, "E X A B Y T E N E S T"))
-			enable_nest(drive);
 		if (!drive->present)
 			/* drive not found */
 			return 0;
+		if (strstr(drive->id->model, "E X A B Y T E N E S T"))
+			enable_nest(drive);
 	
 		/* identification failed? */
 		if (!drive->id_read) {
@@ -717,7 +717,7 @@
  * This routine only knows how to look for drive units 0 and 1
  * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
  */
-static void probe_hwif(ide_hwif_t *hwif)
+static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
 {
 	unsigned int unit;
 	unsigned long flags;
@@ -820,6 +820,9 @@
 		return;
 	}
 
+	if (fixup)
+		fixup(hwif);
+
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		ide_drive_t *drive = &hwif->drives[unit];
 
@@ -874,10 +877,7 @@
 
 int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
 {
-	probe_hwif(hwif);
-
-	if (fixup)
-		fixup(hwif);
+	probe_hwif(hwif, fixup);
 
 	if (!hwif_init(hwif)) {
 		printk(KERN_INFO "%s: failed to initialize IDE interface\n",
@@ -1025,7 +1025,7 @@
 	BUG_ON(irqs_disabled());	
 	BUG_ON(hwif == NULL);
 
-	down(&ide_cfg_sem);
+	mutex_lock(&ide_cfg_mtx);
 	hwif->hwgroup = NULL;
 #if MAX_HWIFS > 1
 	/*
@@ -1073,14 +1073,14 @@
 		hwgroup->hwif->next = hwif;
 		spin_unlock_irq(&ide_lock);
 	} else {
-		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
+		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t),
+					GFP_KERNEL | __GFP_ZERO,
 					hwif_to_node(hwif->drives[0].hwif));
 		if (!hwgroup)
 	       		goto out_up;
 
 		hwif->hwgroup = hwgroup;
 
-		memset(hwgroup, 0, sizeof(ide_hwgroup_t));
 		hwgroup->hwif     = hwif->next = hwif;
 		hwgroup->rq       = NULL;
 		hwgroup->handler  = NULL;
@@ -1154,7 +1154,7 @@
 		printk(" (%sed with %s)",
 			hwif->sharing_irq ? "shar" : "serializ", match->name);
 	printk("\n");
-	up(&ide_cfg_sem);
+	mutex_unlock(&ide_cfg_mtx);
 	return 0;
 out_unlink:
 	spin_lock_irq(&ide_lock);
@@ -1177,7 +1177,7 @@
 	}
 	spin_unlock_irq(&ide_lock);
 out_up:
-	up(&ide_cfg_sem);
+	mutex_unlock(&ide_cfg_mtx);
 	return 1;
 }
 
@@ -1404,7 +1404,7 @@
 
 	for (index = 0; index < MAX_HWIFS; ++index)
 		if (probe[index])
-			probe_hwif(&ide_hwifs[index]);
+			probe_hwif(&ide_hwifs[index], NULL);
 	for (index = 0; index < MAX_HWIFS; ++index)
 		if (probe[index])
 			hwif_init(&ide_hwifs[index]);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index d50bd99..fc1d8ae 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -67,6 +67,8 @@
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
 		case ide_au1xxx:	name = "au1xxx";	break;
+		case ide_etrax100:	name = "etrax100";	break;
+		case ide_acorn:		name = "acorn";		break;
 		default:		name = "(unknown)";	break;
 	}
 	len = sprintf(page, "%s\n", name);
@@ -154,7 +156,7 @@
 {
 	ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
 
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	while ((*p) && strcmp((*p)->name, name) < 0)
 		p = &((*p)->next);
 	if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
@@ -175,10 +177,10 @@
 	if (auto_remove)
 		setting->auto_remove = 1;
 	*p = setting;
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	return 0;
 abort:
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	kfree(setting);
 	return -1;
 }
@@ -222,7 +224,7 @@
  *
  *	Automatically remove all the driver specific settings for this
  *	drive. This function may not be called from IRQ context. The
- *	caller must hold ide_setting_sem.
+ *	caller must hold ide_setting_mtx.
  */
 
 static void auto_remove_settings (ide_drive_t *drive)
@@ -267,7 +269,7 @@
  *	@setting: drive setting
  *
  *	Read a drive setting and return the value. The caller
- *	must hold the ide_setting_sem when making this call.
+ *	must hold the ide_setting_mtx when making this call.
  *
  *	BUGS: the data return and error are the same return value
  *	so an error -EINVAL and true return of the same value cannot
@@ -304,7 +306,7 @@
  *	@val: value
  *
  *	Write a drive setting if it is possible. The caller
- *	must hold the ide_setting_sem when making this call.
+ *	must hold the ide_setting_mtx when making this call.
  *
  *	BUGS: the data return and error are the same return value
  *	so an error -EINVAL and true return of the same value cannot
@@ -365,7 +367,7 @@
  *	@drive: drive being configured
  *
  *	Add the generic parts of the system settings to the /proc files.
- *	The caller must not be holding the ide_setting_sem.
+ *	The caller must not be holding the ide_setting_mtx.
  */
 
 void ide_add_generic_settings (ide_drive_t *drive)
@@ -406,7 +408,7 @@
 
 	proc_ide_settings_warn();
 
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
 	out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
 	while(setting) {
@@ -426,7 +428,7 @@
 		setting = setting->next;
 	}
 	len = out - page;
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
@@ -506,16 +508,16 @@
 				++p;
 			}
 
-			down(&ide_setting_sem);
+			mutex_lock(&ide_setting_mtx);
 			setting = ide_find_setting_by_name(drive, name);
 			if (!setting)
 			{
-				up(&ide_setting_sem);
+				mutex_unlock(&ide_setting_mtx);
 				goto parse_error;
 			}
 			if (for_real)
 				ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
-			up(&ide_setting_sem);
+			mutex_unlock(&ide_setting_mtx);
 		}
 	} while (!for_real++);
 	free_page((unsigned long)buf);
@@ -703,7 +705,7 @@
  *	Clean up the driver specific /proc files and IDE settings
  *	for a given drive.
  *
- *	Takes ide_setting_sem and ide_lock.
+ *	Takes ide_setting_mtx and ide_lock.
  *	Caller must hold none of the locks.
  */
 
@@ -713,10 +715,10 @@
 
 	ide_remove_proc_entries(drive->proc, driver->proc);
 
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	spin_lock_irqsave(&ide_lock, flags);
 	/*
-	 * ide_setting_sem protects the settings list
+	 * ide_setting_mtx protects the settings list
 	 * ide_lock protects the use of settings
 	 *
 	 * so we need to hold both, ide_settings_sem because we want to
@@ -724,11 +726,11 @@
 	 * a setting out that is being used.
 	 *
 	 * OTOH both ide_{read,write}_setting are only ever used under
-	 * ide_setting_sem.
+	 * ide_setting_mtx.
 	 */
 	auto_remove_settings(drive);
 	spin_unlock_irqrestore(&ide_lock, flags);
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 }
 
 EXPORT_SYMBOL(ide_proc_unregister_driver);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 30175c7..aa06daf 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -238,7 +238,7 @@
 static u8 wait_drive_not_busy(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	int retries = 100;
+	int retries;
 	u8 stat;
 
 	/*
@@ -246,10 +246,14 @@
 	 * This can take up to 10 usec, but we will wait max 1 ms
 	 * (drive_cmd_intr() waits that long).
 	 */
-	while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
-		udelay(10);
+	for (retries = 0; retries < 100; retries++) {
+		if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT)
+			udelay(10);
+		else
+			break;
+	}
 
-	if (!retries)
+	if (stat & BUSY_STAT)
 		printk(KERN_ERR "%s: drive still BUSY!\n", drive->name);
 
 	return stat;
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index c0864b1..e6cb859 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -102,66 +102,16 @@
 #define EZ(v,unit)		((v)?ENOUGH(v,unit):0)
 
 #define XFER_MODE	0xf0
-#define XFER_UDMA_133	0x48
-#define XFER_UDMA_100	0x44
-#define XFER_UDMA_66	0x42
-#define XFER_UDMA	0x40
 #define XFER_MWDMA	0x20
-#define XFER_SWDMA	0x10
 #define XFER_EPIO	0x01
 #define XFER_PIO	0x00
 
-static short ide_find_best_mode(ide_drive_t *drive, int map)
+static short ide_find_best_pio_mode(ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
 	short best = 0;
 
-	if (!id)
-		return XFER_PIO_SLOW;
-
-	if ((map & XFER_UDMA) && (id->field_valid & 4)) {	/* Want UDMA and UDMA bitmap valid */
-
-		if ((map & XFER_UDMA_133) == XFER_UDMA_133)
-			if ((best = (id->dma_ultra & 0x0040) ? XFER_UDMA_6 : 0)) return best;
-
-		if ((map & XFER_UDMA_100) == XFER_UDMA_100)
-			if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
-
-		if ((map & XFER_UDMA_66) == XFER_UDMA_66)
-			if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 :
-                	    	    (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
-
-                if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
-                	    (id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
-                	    (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : 0)) return best;
-	}
-
-	if ((map & XFER_MWDMA) && (id->field_valid & 2)) {	/* Want MWDMA and drive has EIDE fields */
-
-		if ((best = (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
-                	    (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
-                	    (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : 0)) return best;
-	}
-
-	if (map & XFER_SWDMA) {					/* Want SWDMA */
-
- 		if (id->field_valid & 2) {			/* EIDE SWDMA */
-
-			if ((best = (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
-      				    (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
-				    (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0)) return best;
-		}
-
-		if (id->capability & 1) {			/* Pre-EIDE style SWDMA */
-
-			if ((best = (id->tDMA == 2) ? XFER_SW_DMA_2 :
-				    (id->tDMA == 1) ? XFER_SW_DMA_1 :
-				    (id->tDMA == 0) ? XFER_SW_DMA_0 : 0)) return best;
-		}
-	}
-
-
-	if ((map & XFER_EPIO) && (id->field_valid & 2)) {	/* EIDE PIO modes */
+	if (id->field_valid & 2) {	/* EIDE PIO modes */
 
 		if ((best = (drive->id->eide_pio_modes & 4) ? XFER_PIO_5 :
 			    (drive->id->eide_pio_modes & 2) ? XFER_PIO_4 :
@@ -262,7 +212,7 @@
  */
 
 	if ((speed & XFER_MODE) != XFER_PIO) {
-		ide_timing_compute(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO), &p, T, UT);
+		ide_timing_compute(drive, ide_find_best_pio_mode(drive), &p, T, UT);
 		ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
 	}
 
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 6002713..8cd7694 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -169,7 +169,7 @@
 static int idebus_parameter;	/* holds the "idebus=" parameter */
 static int system_bus_speed;	/* holds what we think is VESA/PCI bus speed */
 
-DECLARE_MUTEX(ide_cfg_sem);
+DEFINE_MUTEX(ide_cfg_mtx);
  __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
 
 #ifdef CONFIG_IDEPCI_PCIBUS_ORDER
@@ -460,6 +460,8 @@
 	hwif->mwdma_mask		= tmp_hwif->mwdma_mask;
 	hwif->swdma_mask		= tmp_hwif->swdma_mask;
 
+	hwif->cbl			= tmp_hwif->cbl;
+
 	hwif->chipset			= tmp_hwif->chipset;
 	hwif->hold			= tmp_hwif->hold;
 
@@ -496,8 +498,8 @@
 	hwif->ide_dma_clear_irq		= tmp_hwif->ide_dma_clear_irq;
 	hwif->dma_host_on		= tmp_hwif->dma_host_on;
 	hwif->dma_host_off		= tmp_hwif->dma_host_off;
-	hwif->ide_dma_lostirq		= tmp_hwif->ide_dma_lostirq;
-	hwif->ide_dma_timeout		= tmp_hwif->ide_dma_timeout;
+	hwif->dma_lost_irq		= tmp_hwif->dma_lost_irq;
+	hwif->dma_timeout		= tmp_hwif->dma_timeout;
 
 	hwif->OUTB			= tmp_hwif->OUTB;
 	hwif->OUTBSYNC			= tmp_hwif->OUTBSYNC;
@@ -533,7 +535,6 @@
 	hwif->extra_base		= tmp_hwif->extra_base;
 	hwif->extra_ports		= tmp_hwif->extra_ports;
 	hwif->autodma			= tmp_hwif->autodma;
-	hwif->udma_four			= tmp_hwif->udma_four;
 
 	hwif->hwif_data			= tmp_hwif->hwif_data;
 }
@@ -564,7 +565,7 @@
 {
 	ide_drive_t *drive;
 	ide_hwif_t *hwif, *g;
-	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
+	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
 	ide_hwgroup_t *hwgroup;
 	int irq_count = 0, unit;
 
@@ -572,7 +573,7 @@
 
 	BUG_ON(in_interrupt());
 	BUG_ON(irqs_disabled());
-	down(&ide_cfg_sem);
+	mutex_lock(&ide_cfg_mtx);
 	spin_lock_irq(&ide_lock);
 	hwif = &ide_hwifs[index];
 	if (!hwif->present)
@@ -679,7 +680,7 @@
 
 abort:
 	spin_unlock_irq(&ide_lock);
-	up(&ide_cfg_sem);
+	mutex_unlock(&ide_cfg_mtx);
 }
 
 EXPORT_SYMBOL(ide_unregister);
@@ -817,9 +818,9 @@
  *	Locks for IDE setting functionality
  */
 
-DECLARE_MUTEX(ide_setting_sem);
+DEFINE_MUTEX(ide_setting_mtx);
 
-EXPORT_SYMBOL_GPL(ide_setting_sem);
+EXPORT_SYMBOL_GPL(ide_setting_mtx);
 
 /**
  *	ide_spin_wait_hwgroup	-	wait for group
@@ -1013,6 +1014,7 @@
 	struct request rq;
 	struct request_pm_state rqpm;
 	ide_task_t args;
+	int err;
 
 	/* Call ACPI _STM only once */
 	if (!(drive->dn % 2))
@@ -1029,7 +1031,16 @@
 	rqpm.pm_step = ide_pm_state_start_resume;
 	rqpm.pm_state = PM_EVENT_ON;
 
-	return ide_do_drive_cmd(drive, &rq, ide_head_wait);
+	err = ide_do_drive_cmd(drive, &rq, ide_head_wait);
+
+	if (err == 0 && dev->driver) {
+		ide_driver_t *drv = to_ide_driver(dev->driver);
+
+		if (drv->resume)
+			drv->resume(drive);
+	}
+
+	return err;
 }
 
 int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
@@ -1038,9 +1049,13 @@
 	unsigned long flags;
 	ide_driver_t *drv;
 	void __user *p = (void __user *)arg;
-	int err = 0, (*setfunc)(ide_drive_t *, int);
+	int err, (*setfunc)(ide_drive_t *, int);
 	u8 *val;
 
+	err = scsi_cmd_ioctl(file, bdev->bd_disk->queue, bdev->bd_disk, cmd, p);
+	if (err != -ENOTTY)
+		return err;
+
 	switch (cmd) {
 	case HDIO_GET_32BIT:	    val = &drive->io_32bit;	 goto read_val;
 	case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
@@ -1160,10 +1175,6 @@
 			return 0;
 		}
 
-		case CDROMEJECT:
-		case CDROMCLOSETRAY:
-			return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p);
-
 		case HDIO_GET_BUSSTATE:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
@@ -1182,11 +1193,11 @@
 	}
 
 read_val:
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	spin_lock_irqsave(&ide_lock, flags);
 	err = *val;
 	spin_unlock_irqrestore(&ide_lock, flags);
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	return err >= 0 ? put_user(err, (long __user *)arg) : err;
 
 set_val:
@@ -1196,9 +1207,9 @@
 		if (!capable(CAP_SYS_ADMIN))
 			err = -EACCES;
 		else {
-			down(&ide_setting_sem);
+			mutex_lock(&ide_setting_mtx);
 			err = setfunc(drive, arg);
-			up(&ide_setting_sem);
+			mutex_unlock(&ide_setting_mtx);
 		}
 	}
 	return err;
@@ -1538,7 +1549,11 @@
 				goto bad_option;
 			case -7: /* ata66 */
 #ifdef CONFIG_BLK_DEV_IDEPCI
-				hwif->udma_four = 1;
+				/*
+				 * Use ATA_CBL_PATA40_SHORT so drive side
+				 * cable detection is also overriden.
+				 */
+				hwif->cbl = ATA_CBL_PATA40_SHORT;
 				goto obsolete_option;
 #else
 				goto bad_hwif;
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 45ed035..8f2db8d 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -130,7 +130,7 @@
 	
 #ifdef HD_TYPE
 static struct hd_i_struct hd_info[] = { HD_TYPE };
-static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
+static int NR_HD = ARRAY_SIZE(hd_info);
 #else
 static struct hd_i_struct hd_info[MAX_HD];
 static int NR_HD;
@@ -623,7 +623,8 @@
 	cyl   = track / disk->head;
 #ifdef DEBUG
 	printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
-		req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
+		req->rq_disk->disk_name,
+		req_data_dir(req) == READ ? "read" : "writ",
 		cyl, head, sec, nsect, req->buffer);
 #endif
 	if (blk_fs_request(req)) {
@@ -718,74 +719,25 @@
 	device_timer.function = hd_times_out;
 	blk_queue_hardsect_size(hd_queue, 512);
 
-#ifdef __i386__
 	if (!NR_HD) {
-		extern struct drive_info drive_info;
-		unsigned char *BIOS = (unsigned char *) &drive_info;
-		unsigned long flags;
-		int cmos_disks;
-
-		for (drive=0 ; drive<2 ; drive++) {
-			hd_info[drive].cyl = *(unsigned short *) BIOS;
-			hd_info[drive].head = *(2+BIOS);
-			hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
-			hd_info[drive].ctl = *(8+BIOS);
-			hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
-			hd_info[drive].sect = *(14+BIOS);
-#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
-			if (hd_info[drive].cyl && NR_HD == drive)
-				NR_HD++;
-#endif
-			BIOS += 16;
-		}
-
-	/*
-		We query CMOS about hard disks : it could be that 
-		we have a SCSI/ESDI/etc controller that is BIOS
-		compatible with ST-506, and thus showing up in our
-		BIOS table, but not register compatible, and therefore
-		not present in CMOS.
-
-		Furthermore, we will assume that our ST-506 drives
-		<if any> are the primary drives in the system, and 
-		the ones reflected as drive 1 or 2.
-
-		The first drive is stored in the high nibble of CMOS
-		byte 0x12, the second in the low nibble.  This will be
-		either a 4 bit drive type or 0xf indicating use byte 0x19 
-		for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
-
-		Needless to say, a non-zero value means we have 
-		an AT controller hard disk for that drive.
-
-		Currently the rtc_lock is a bit academic since this
-		driver is non-modular, but someday... ?         Paul G.
-	*/
-
-		spin_lock_irqsave(&rtc_lock, flags);
-		cmos_disks = CMOS_READ(0x12);
-		spin_unlock_irqrestore(&rtc_lock, flags);
-
-		if (cmos_disks & 0xf0) {
-			if (cmos_disks & 0x0f)
-				NR_HD = 2;
-			else
-				NR_HD = 1;
-		}
-	}
-#endif /* __i386__ */
-#ifdef __arm__
-	if (!NR_HD) {
-		/* We don't know anything about the drive.  This means
+		/*
+		 * We don't know anything about the drive.  This means
 		 * that you *MUST* specify the drive parameters to the
 		 * kernel yourself.
+		 *
+		 * If we were on an i386, we used to read this info from
+		 * the BIOS or CMOS.  This doesn't work all that well,
+		 * since this assumes that this is a primary or secondary
+		 * drive, and if we're using this legacy driver, it's
+		 * probably an auxilliary controller added to recover
+		 * legacy data off an ST-506 drive.  Either way, it's
+		 * definitely safest to have the user explicitly specify
+		 * the information.
 		 */
 		printk("hd: no drives specified - use hd=cyl,head,sectors"
 			" on kernel command line\n");
-	}
-#endif
-	if (!NR_HD)
 		goto out;
+	}
 
 	for (drive=0 ; drive < NR_HD ; drive++) {
 		struct gendisk *disk = alloc_disk(64);
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index c211fc7..b557c45 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -77,15 +77,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
-static void macide_mediabay_interrupt(int irq, void *dev_id)
-{
-	int state = baboon->mb_status & 0x04;
-
-	printk(KERN_INFO "macide: media bay %s detected\n", state? "removal":"insertion");
-}
-#endif
-
 /*
  * Probe for a Macintosh IDE interface
  */
@@ -128,11 +119,6 @@
 			ide_drive_t *drive = &ide_hwifs[index].drives[0];
 			drive->capacity64 = drive->cyl*drive->head*drive->sect;
 
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
-			request_irq(IRQ_BABOON_2, macide_mediabay_interrupt,
-					IRQ_FLG_FAST, "mediabay",
-					macide_mediabay_interrupt);
-#endif
 		}
 		break;
 
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
index d1414a7..7783745 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/legacy/qd65xx.c
@@ -258,8 +258,7 @@
 	int recovery_time = 415; /* worst case values from the dos driver */
 
 	if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
-		pio = ide_get_best_pio_mode(drive, pio, 255, &d);
-		pio = min_t(u8, pio, 4);
+		pio = ide_get_best_pio_mode(drive, pio, 4, &d);
 
 		switch (pio) {
 			case 0: break;
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index ca95e99..2e7013a 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -381,9 +381,7 @@
 
 static int auide_dma_check(ide_drive_t *drive)
 {
-	u8 speed;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+	u8 speed = ide_max_dma_mode(drive);
 
 	if( dbdma_init_done == 0 ){
 		auide_hwif.white_list = ide_in_drive_list(drive->id,
@@ -394,7 +392,6 @@
 		auide_ddma_init(&auide_hwif);
 		dbdma_init_done = 1;
 	}
-#endif
 
 	/* Is the drive in our DMA black list? */
 
@@ -409,8 +406,6 @@
 	else
 		drive->using_dma = 1;
 
-	speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA);
-	
 	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
 		return 0;
 
@@ -456,10 +451,9 @@
 	drive->using_dma = 0;
 }
 
-static int auide_dma_lostirq(ide_drive_t *drive)
+static void auide_dma_lost_irq(ide_drive_t *drive)
 {
 	printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-	return 0;
 }
 
 static void auide_ddma_tx_callback(int irq, void *param)
@@ -489,16 +483,16 @@
   
 #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
 
-static int auide_dma_timeout(ide_drive_t *drive)
+static void auide_dma_timeout(ide_drive_t *drive)
 {
-//      printk("%s\n", __FUNCTION__);
+	ide_hwif_t *hwif = HWIF(drive);
 
 	printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
 
-	if (HWIF(drive)->ide_dma_test_irq(drive))
-		return 0;
+	if (hwif->ide_dma_test_irq(drive))
+		return;
 
-	return HWIF(drive)->ide_dma_end(drive);
+	hwif->ide_dma_end(drive);
 }
 					
 
@@ -721,7 +715,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 	hwif->dma_off_quietly		= &auide_dma_off_quietly;
-	hwif->ide_dma_timeout           = &auide_dma_timeout;
+	hwif->dma_timeout		= &auide_dma_timeout;
 
 	hwif->ide_dma_check             = &auide_dma_check;
 	hwif->dma_exec_cmd              = &auide_dma_exec_cmd;
@@ -731,7 +725,7 @@
 	hwif->ide_dma_test_irq          = &auide_dma_test_irq;
 	hwif->dma_host_off		= &auide_dma_host_off;
 	hwif->dma_host_on		= &auide_dma_host_on;
-	hwif->ide_dma_lostirq           = &auide_dma_lostirq;
+	hwif->dma_lost_irq		= &auide_dma_lost_irq;
 	hwif->ide_dma_on                = &auide_dma_on;
 
 	hwif->autodma                   = 1;
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index b173bc6..e5d0936 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/aec62xx.c		Version 0.21	Apr 21, 2007
+ * linux/drivers/ide/pci/aec62xx.c		Version 0.24	May 24, 2007
  *
  * Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2007		MontaVista Software, Inc. <source@mvista.com>
@@ -140,25 +140,10 @@
 	return(ide_config_drive_speed(drive, speed));
 }
 
-static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed)
-{
-	switch (HWIF(drive)->pci_dev->device) {
-		case PCI_DEVICE_ID_ARTOP_ATP865:
-		case PCI_DEVICE_ID_ARTOP_ATP865R:
-		case PCI_DEVICE_ID_ARTOP_ATP860:
-		case PCI_DEVICE_ID_ARTOP_ATP860R:
-			return ((int) aec6260_tune_chipset(drive, speed));
-		case PCI_DEVICE_ID_ARTOP_ATP850UF:
-			return ((int) aec6210_tune_chipset(drive, speed));
-		default:
-			return -1;
-	}
-}
-
 static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
 {
 	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
-	(void) aec62xx_tune_chipset(drive, pio + XFER_PIO_0);
+	(void) HWIF(drive)->speedproc(drive, pio + XFER_PIO_0);
 }
 
 static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
@@ -172,12 +157,9 @@
 	return -1;
 }
 
-static int aec62xx_irq_timeout (ide_drive_t *drive)
+static void aec62xx_dma_lost_irq (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
-
-	switch(dev->device) {
+	switch (HWIF(drive)->pci_dev->device) {
 		case PCI_DEVICE_ID_ARTOP_ATP860:
 		case PCI_DEVICE_ID_ARTOP_ATP860R:
 		case PCI_DEVICE_ID_ARTOP_ATP865:
@@ -186,7 +168,6 @@
 		default:
 			break;
 	}
-	return 0;
 }
 
 static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
@@ -224,64 +205,46 @@
 
 static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev	= hwif->pci_dev;
+	u8 reg54 = 0,  mask	= hwif->channel ? 0xf0 : 0x0f;
+	unsigned long flags;
 
-	hwif->autodma = 0;
 	hwif->tuneproc = &aec62xx_tune_drive;
-	hwif->speedproc = &aec62xx_tune_chipset;
 
-	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
-		hwif->serialized = hwif->channel;
-
-	if (hwif->mate)
-		hwif->mate->serialized = hwif->serialized;
+	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+		if(hwif->mate)
+			hwif->mate->serialized = hwif->serialized = 1;
+		hwif->speedproc = &aec6210_tune_chipset;
+	} else
+		hwif->speedproc = &aec6260_tune_chipset;
 
 	if (!hwif->dma_base) {
-		hwif->drives[0].autotune = 1;
-		hwif->drives[1].autotune = 1;
+		hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
 		return;
 	}
 
 	hwif->ultra_mask = hwif->cds->udma_mask;
-
-	/* atp865 and atp865r */
-	if (hwif->ultra_mask == 0x3f) {
-		/* check bit 0x10 of DMA status register */
-		if (inb(pci_resource_start(dev, 4) + 2) & 0x10)
- 			hwif->ultra_mask = 0x7f; /* udma0-6 */
-	}
-
 	hwif->mwdma_mask = 0x07;
 
 	hwif->ide_dma_check	= &aec62xx_config_drive_xfer_rate;
-	hwif->ide_dma_lostirq	= &aec62xx_irq_timeout;
+	hwif->dma_lost_irq	= &aec62xx_dma_lost_irq;
+
+	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+		spin_lock_irqsave(&ide_lock, flags);
+		pci_read_config_byte (dev, 0x54, &reg54);
+		pci_write_config_byte(dev, 0x54, (reg54 & ~mask));
+		spin_unlock_irqrestore(&ide_lock, flags);
+	} else if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+		u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
+
+		pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
+
+		hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+	}
 
 	if (!noautodma)
 		hwif->autodma = 1;
-	hwif->drives[0].autodma = hwif->autodma;
-	hwif->drives[1].autodma = hwif->autodma;
-}
-
-static void __devinit init_dma_aec62xx(ide_hwif_t *hwif, unsigned long dmabase)
-{
-	struct pci_dev *dev	= hwif->pci_dev;
-
-	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
-		u8 reg54h = 0;
-		unsigned long flags;
-
-		spin_lock_irqsave(&ide_lock, flags);
-		pci_read_config_byte(dev, 0x54, &reg54h);
-		pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
-		spin_unlock_irqrestore(&ide_lock, flags);
-	} else {
-		u8 ata66	= 0;
-		pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
-	        if (!(hwif->udma_four))
-			hwif->udma_four = (ata66&(hwif->channel?0x02:0x01))?0:1;
-	}
-
-	ide_setup_dma(hwif, dmabase, 8);
+	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
 }
 
 static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d)
@@ -291,16 +254,12 @@
 
 static int __devinit init_setup_aec6x80(struct pci_dev *dev, ide_pci_device_t *d)
 {
-	unsigned long bar4reg = pci_resource_start(dev, 4);
+	unsigned long dma_base = pci_resource_start(dev, 4);
 
-	if (inb(bar4reg+2) & 0x10) {
-		strcpy(d->name, "AEC6880");
-		if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
-			strcpy(d->name, "AEC6880R");
-	} else {
-		strcpy(d->name, "AEC6280");
-		if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
-			strcpy(d->name, "AEC6280R");
+	if (inb(dma_base + 2) & 0x10) {
+		d->name = (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) ?
+			  "AEC6880R" : "AEC6880";
+		d->udma_mask = 0x7f; /* udma0-6 */
 	}
 
 	return ide_setup_pci_device(dev, d);
@@ -312,7 +271,6 @@
 		.init_setup	= init_setup_aec62xx,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -323,7 +281,6 @@
 		.init_setup	= init_setup_aec62xx,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= NOAUTODMA,
 		.bootable	= OFF_BOARD,
@@ -333,28 +290,25 @@
 		.init_setup	= init_setup_aec62xx,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
 		.bootable	= NEVER_BOARD,
 		.udma_mask	= 0x1f, /* udma0-4 */
 	},{	/* 3 */
-		.name		= "AEC6X80",
+		.name		= "AEC6280",
 		.init_setup	= init_setup_aec6x80,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.bootable	= OFF_BOARD,
 		.udma_mask	= 0x3f, /* udma0-5 */
 	},{	/* 4 */
-		.name		= "AEC6X80R",
+		.name		= "AEC6280R",
 		.init_setup	= init_setup_aec6x80,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -370,13 +324,16 @@
  *
  *	Called when the PCI registration layer (or the IDE initialization)
  *	finds a device matching our IDE device tables.
+ *
+ *	NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
+ *	chips, pass a local copy of 'struct pci_device_id' down the call chain.
  */
  
 static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	ide_pci_device_t *d = &aec62xx_chipsets[id->driver_data];
+	ide_pci_device_t d = aec62xx_chipsets[id->driver_data];
 
-	return d->init_setup(dev, d);
+	return d.init_setup(dev, &d);
 }
 
 static struct pci_device_id aec62xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 27525ec..ba0fb92b 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/alim15x3.c		Version 0.21	2007/02/03
+ * linux/drivers/ide/pci/alim15x3.c		Version 0.25	Jun 9 2007
  *
  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
@@ -10,6 +10,7 @@
  *  Copyright (C) 2002 Alan Cox <alan@redhat.com>
  *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
  *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
+ *  Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
  *
  *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
  *
@@ -36,6 +37,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/init.h>
+#include <linux/dmi.h>
 
 #include <asm/io.h>
 
@@ -506,7 +508,7 @@
 	u8 tmpbyte;
 	struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0));
 
-	pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
+	m5229_revision = dev->revision;
 
 	isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
 
@@ -583,6 +585,35 @@
 	return 0;
 }
 
+/*
+ *	Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+	{
+		.ident = "HP Pavilion N5430",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"),
+		},
+	},
+	{ }
+};
+
+static int ali_cable_override(struct pci_dev *pdev)
+{
+	/* Fujitsu P2000 */
+	if (pdev->subsystem_vendor == 0x10CF &&
+	    pdev->subsystem_device == 0x10AF)
+		return 1;
+
+	/* Systems by DMI */
+	if (dmi_check_system(cable_dmi_table))
+		return 1;
+
+	return 0;
+}
+
 /**
  *	ata66_ali15x3	-	check for UDMA 66 support
  *	@hwif: IDE interface
@@ -594,37 +625,31 @@
  *	FIXME: frobs bits that are not defined on newer ALi devicea
  */
 
-static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
+static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
-	unsigned int ata66	= 0;
-	u8 cable_80_pin[2]	= { 0, 0 };
-
 	unsigned long flags;
-	u8 tmpbyte;
+	u8 cbl = ATA_CBL_PATA40, tmpbyte;
 
 	local_irq_save(flags);
 
 	if (m5229_revision >= 0xC2) {
 		/*
-		 * Ultra66 cable detection (from Host View)
-		 * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
+		 * m5229 80-pin cable detection (from Host View)
+		 *
+		 * 0x4a bit0 is 0 => primary channel has 80-pin
+		 * 0x4a bit1 is 0 => secondary channel has 80-pin
+		 *
+		 * Certain laptops use short but suitable cables
+		 * and don't implement the detect logic.
 		 */
-		pci_read_config_byte(dev, 0x4a, &tmpbyte);
-		/*
-		 * 0x4a, bit0 is 0 => primary channel
-		 * has 80-pin (from host view)
-		 */
-		if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1;
-		/*
-		 * 0x4a, bit1 is 0 => secondary channel
-		 * has 80-pin (from host view)
-		 */
-		if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1;
-		/*
-		 * Allow ata66 if cable of current channel has 80 pins
-		 */
-		ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
+		if (ali_cable_override(dev))
+			cbl = ATA_CBL_PATA40_SHORT;
+		else {
+			pci_read_config_byte(dev, 0x4a, &tmpbyte);
+			if ((tmpbyte & (1 << hwif->channel)) == 0)
+				cbl = ATA_CBL_PATA80;
+		}
 	} else {
 		/*
 		 * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
@@ -657,7 +682,7 @@
 
 	local_irq_restore(flags);
 
-	return(ata66);
+	return cbl;
 }
 
 /**
@@ -708,8 +733,9 @@
 		hwif->dma_setup = &ali15x3_dma_setup;
 		if (!noautodma)
 			hwif->autodma = 1;
-		if (!(hwif->udma_four))
-			hwif->udma_four = ata66_ali15x3(hwif);
+
+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+			hwif->cbl = ata66_ali15x3(hwif);
 	}
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index becb1a5..8d30b99 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,10 +1,11 @@
 /*
- * Version 2.13
+ * Version 2.20
  *
  * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
  * IDE driver for Linux.
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
  *
  * Based on the work of:
  *      Andre Hedrick
@@ -37,11 +38,6 @@
 #define AMD_ADDRESS_SETUP	(0x0c + amd_config->base)
 #define AMD_UDMA_TIMING		(0x10 + amd_config->base)
 
-#define AMD_UDMA		0x07
-#define AMD_UDMA_33		0x01
-#define AMD_UDMA_66		0x02
-#define AMD_UDMA_100		0x03
-#define AMD_UDMA_133		0x04
 #define AMD_CHECK_SWDMA		0x08
 #define AMD_BAD_SWDMA		0x10
 #define AMD_BAD_FIFO		0x20
@@ -53,30 +49,33 @@
 
 static struct amd_ide_chip {
 	unsigned short id;
-	unsigned long base;
-	unsigned char flags;
+	u8 base;
+	u8 udma_mask;
+	u8 flags;
 } amd_ide_chips[] = {
-	{ PCI_DEVICE_ID_AMD_COBRA_7401,		0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },
-	{ PCI_DEVICE_ID_AMD_VIPER_7409,		0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },
-	{ PCI_DEVICE_ID_AMD_VIPER_7411,		0x40, AMD_UDMA_100 | AMD_BAD_FIFO },
-	{ PCI_DEVICE_ID_AMD_OPUS_7441,		0x40, AMD_UDMA_100 },
-	{ PCI_DEVICE_ID_AMD_8111_IDE,		0x40, AMD_UDMA_133 | AMD_CHECK_SERENADE },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	0x50, AMD_UDMA_100 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_AMD_CS5536_IDE,			0x40, AMD_UDMA_100 },
+	{ PCI_DEVICE_ID_AMD_COBRA_7401,		 0x40, ATA_UDMA2, AMD_BAD_SWDMA },
+	{ PCI_DEVICE_ID_AMD_VIPER_7409,		 0x40, ATA_UDMA4, AMD_CHECK_SWDMA },
+	{ PCI_DEVICE_ID_AMD_VIPER_7411,		 0x40, ATA_UDMA5, AMD_BAD_FIFO },
+	{ PCI_DEVICE_ID_AMD_OPUS_7441,		 0x40, ATA_UDMA5, },
+	{ PCI_DEVICE_ID_AMD_8111_IDE,		 0x40, ATA_UDMA6, AMD_CHECK_SERENADE },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	 0x50, ATA_UDMA5, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_AMD_CS5536_IDE,		 0x40, ATA_UDMA5, },
 	{ 0 }
 };
 
@@ -85,7 +84,7 @@
 static unsigned int amd_80w;
 static unsigned int amd_clock;
 
-static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
 static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
 
 /*
@@ -124,9 +123,8 @@
 	amd_print("Driver Version:                     2.13");
 	amd_print("South Bridge:                       %s", pci_name(bmide_dev));
 
-	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
-	amd_print("Revision:                           IDE %#x", t);
-	amd_print("Highest DMA rate:                   %s", amd_dma[amd_config->flags & AMD_UDMA]);
+	amd_print("Revision:                           IDE %#x", dev->revision);
+	amd_print("Highest DMA rate:                   UDMA%s", amd_dma[fls(amd_config->udma_mask) - 1]);
 
 	amd_print("BM-DMA base:                        %#lx", amd_base);
 	amd_print("PCI clock:                          %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10);
@@ -219,12 +217,12 @@
 	pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
 		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
 
-	switch (amd_config->flags & AMD_UDMA) {
-		case AMD_UDMA_33:  t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
-		case AMD_UDMA_66:  t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
-		case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
-		case AMD_UDMA_133: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
-		default: return;
+	switch (amd_config->udma_mask) {
+	case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+	case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
+	case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
+	case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
+	default: return;
 	}
 
 	pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
@@ -242,13 +240,11 @@
 	struct ide_timing t, p;
 	int T, UT;
 
-	if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
-		if (ide_config_drive_speed(drive, speed))
-			printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n",
-				drive->dn >> 1, drive->dn & 1);
+	if (speed != XFER_PIO_SLOW)
+		ide_config_drive_speed(drive, speed);
 
 	T = 1000000000 / amd_clock;
-	UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2);
+	UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
 
 	ide_timing_compute(drive, speed, &t, T, UT);
 
@@ -277,29 +273,19 @@
 static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio)
 {
 	if (pio == 255) {
-		amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+		amd_set_drive(drive, ide_find_best_pio_mode(drive));
 		return;
 	}
 
 	amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
 }
 
-/*
- * amd74xx_dmaproc() is a callback from upper layers that can do
- * a lot, but we use it for DMA/PIO tuning only, delegating everything
- * else to the default ide_dmaproc().
- */
-
 static int amd74xx_ide_dma_check(ide_drive_t *drive)
 {
-	int w80 = HWIF(drive)->udma_four;
+	u8 speed = ide_max_dma_mode(drive);
 
-	u8 speed = ide_find_best_mode(drive,
-		XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
-		((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0));
+	if (speed == 0)
+		speed = ide_find_best_pio_mode(drive);
 
 	amd_set_drive(drive, speed);
 
@@ -325,8 +311,7 @@
  */
 
 	if (amd_config->flags & AMD_CHECK_SWDMA) {
-		pci_read_config_byte(dev, PCI_REVISION_ID, &t);
-		if (t <= 7)
+		if (dev->revision <= 7)
 			amd_config->flags |= AMD_BAD_SWDMA;
 	}
 
@@ -334,10 +319,10 @@
  * Check 80-wire cable presence.
  */
 
-	switch (amd_config->flags & AMD_UDMA) {
+	switch (amd_config->udma_mask) {
 
-		case AMD_UDMA_133:
-		case AMD_UDMA_100:
+		case ATA_UDMA6:
+		case ATA_UDMA5:
 			pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
 			pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
 			amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
@@ -349,7 +334,7 @@
 				}
 			break;
 
-		case AMD_UDMA_66:
+		case ATA_UDMA4:
 			/* no host side cable detection */
 			amd_80w = 0x03;
 			break;
@@ -370,7 +355,7 @@
 	if ((amd_config->flags & AMD_CHECK_SERENADE) &&
 		dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
 		dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
-			amd_config->flags = AMD_UDMA_100;
+			amd_config->udma_mask = ATA_UDMA5;
 
 /*
  * Determine the system bus clock.
@@ -395,8 +380,9 @@
  */
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
-	printk(KERN_INFO "%s: %s (rev %02x) %s controller\n",
-		amd_chipset->name, pci_name(dev), t, amd_dma[amd_config->flags & AMD_UDMA]);
+	printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
+		amd_chipset->name, pci_name(dev), dev->revision,
+		amd_dma[fls(amd_config->udma_mask) - 1]);
 
 /*
  * Register /proc/ide/amd74xx entry
@@ -437,12 +423,19 @@
 		return;
 
         hwif->atapi_dma = 1;
-        hwif->ultra_mask = 0x7f;
-        hwif->mwdma_mask = 0x07;
-        hwif->swdma_mask = 0x07;
 
-	if (!hwif->udma_four)
-		hwif->udma_four = (amd_80w >> hwif->channel) & 1;
+	hwif->ultra_mask = amd_config->udma_mask;
+	hwif->mwdma_mask = 0x07;
+	if ((amd_config->flags & AMD_BAD_SWDMA) == 0)
+		hwif->swdma_mask = 0x07;
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+		if ((amd_80w >> hwif->channel) & 1)
+			hwif->cbl = ATA_CBL_PATA80;
+		else
+			hwif->cbl = ATA_CBL_PATA40;
+	}
+
         hwif->ide_dma_check = &amd74xx_ide_dma_check;
         if (!noautodma)
                 hwif->autodma = 1;
@@ -494,7 +487,9 @@
 	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
 	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
 	/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"),
-	/* 20 */ DECLARE_AMD_DEV("AMD5536"),
+	/* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"),
+	/* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"),
+	/* 22 */ DECLARE_AMD_DEV("AMD5536"),
 };
 
 static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -534,7 +529,9 @@
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 },
-	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21 },
+	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22 },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 0e52ad7..2761510 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -264,10 +264,11 @@
 	hwif->swdma_mask = 0x04;
 
 	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+
 	if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
-		hwif->udma_four = 1;
+		hwif->cbl = ATA_CBL_PATA80;
 	else
-		hwif->udma_four = 0;
+		hwif->cbl = ATA_CBL_PATA40;
 
 	hwif->dma_host_on = &atiixp_dma_host_on;
 	hwif->dma_host_off = &atiixp_dma_host_off;
@@ -317,6 +318,7 @@
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 7c57dc6..1e89dd6 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/cmd64x.c		Version 1.47	Mar 19, 2007
+ * linux/drivers/ide/pci/cmd64x.c		Version 1.50	May 10, 2007
  *
  * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
  *           Due to massive hardware bugs, UltraDMA is only supported
@@ -52,9 +52,6 @@
 #define   ARTTIM23_DIS_RA2	0x04
 #define   ARTTIM23_DIS_RA3	0x08
 #define   ARTTIM23_INTR_CH1	0x10
-#define ARTTIM2		0x57
-#define ARTTIM3		0x57
-#define DRWTIM23	0x58
 #define DRWTIM2		0x58
 #define BRST		0x59
 #define DRWTIM3		0x5b
@@ -91,7 +88,6 @@
 	u8 reg72 = 0, reg73 = 0;			/* primary */
 	u8 reg7a = 0, reg7b = 0;			/* secondary */
 	u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0;	/* extra */
-	u8 rev = 0;
 
 	p += sprintf(p, "\nController: %d\n", index);
 	p += sprintf(p, "PCI-%x Chipset.\n", dev->device);
@@ -106,9 +102,8 @@
 	(void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
 
 	/* PCI0643/6 originally didn't have the primary channel enable bit */
-	(void) pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
 	if ((dev->device == PCI_DEVICE_ID_CMD_643) ||
-	    (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 3))
+	    (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 3))
 		reg51 |= CNTRL_ENA_1ST;
 
 	p += sprintf(p, "---------------- Primary Channel "
@@ -469,71 +464,43 @@
 
 static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
 {
-	u32 class_rev = 0;
 	u8 mrdmode = 0;
 
-	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-	class_rev &= 0xff;
+	if (dev->device == PCI_DEVICE_ID_CMD_646) {
+		u8 rev = 0;
 
-	switch(dev->device) {
-		case PCI_DEVICE_ID_CMD_643:
+		pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+
+		switch (rev) {
+		case 0x07:
+		case 0x05:
+			printk("%s: UltraDMA capable", name);
 			break;
-		case PCI_DEVICE_ID_CMD_646:
-			printk(KERN_INFO "%s: chipset revision 0x%02X, ", name, class_rev);
-			switch(class_rev) {
-				case 0x07:
-				case 0x05:
-					printk("UltraDMA Capable");
-					break;
-				case 0x03:
-					printk("MultiWord DMA Force Limited");
-					break;
-				case 0x01:
-				default:
-					printk("MultiWord DMA Limited, IRQ workaround enabled");
-					break;
-				}
-			printk("\n");
-                        break;
-		case PCI_DEVICE_ID_CMD_648:
-		case PCI_DEVICE_ID_CMD_649:
-			break;
+		case 0x03:
 		default:
+			printk("%s: MultiWord DMA force limited", name);
 			break;
+		case 0x01:
+			printk("%s: MultiWord DMA limited, "
+			       "IRQ workaround enabled\n", name);
+			break;
+		}
 	}
 
 	/* Set a good latency timer and cache line size value. */
 	(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
 	/* FIXME: pci_set_master() to ensure a good latency timer value */
 
-	/* Setup interrupts. */
-	(void) pci_read_config_byte(dev, MRDMODE, &mrdmode);
-	mrdmode &= ~(0x30);
-	(void) pci_write_config_byte(dev, MRDMODE, mrdmode);
-
-	/* Use MEMORY READ LINE for reads.
-	 * NOTE: Although not mentioned in the PCI0646U specs,
-	 *       these bits are write only and won't be read
-	 *       back as set or not.  The PCI0646U2 specs clarify
-	 *       this point.
+	/*
+	 * Enable interrupts, select MEMORY READ LINE for reads.
+	 *
+	 * NOTE: although not mentioned in the PCI0646U specs,
+	 * bits 0-1 are write only and won't be read back as
+	 * set or not -- PCI0646U2 specs clarify this point.
 	 */
-	(void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02);
-
-	/* Set reasonable active/recovery/address-setup values. */
-	(void) pci_write_config_byte(dev, ARTTIM0,  0x40);
-	(void) pci_write_config_byte(dev, DRWTIM0,  0x3f);
-	(void) pci_write_config_byte(dev, ARTTIM1,  0x40);
-	(void) pci_write_config_byte(dev, DRWTIM1,  0x3f);
-#ifdef __i386__
-	(void) pci_write_config_byte(dev, ARTTIM23, 0x1c);
-#else
-	(void) pci_write_config_byte(dev, ARTTIM23, 0x5c);
-#endif
-	(void) pci_write_config_byte(dev, DRWTIM23, 0x3f);
-	(void) pci_write_config_byte(dev, DRWTIM3,  0x3f);
-#ifdef CONFIG_PPC
-	(void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);
-#endif /* CONFIG_PPC */
+	(void) pci_read_config_byte (dev, MRDMODE, &mrdmode);
+	mrdmode &= ~0x30;
+	(void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
 
 #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
 
@@ -548,29 +515,27 @@
 	return 0;
 }
 
-static unsigned int __devinit ata66_cmd64x(ide_hwif_t *hwif)
+static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
 {
-	u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01;
+	struct pci_dev  *dev	= hwif->pci_dev;
+	u8 bmidecsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
 
-	switch(hwif->pci_dev->device) {
-		case PCI_DEVICE_ID_CMD_643:
-		case PCI_DEVICE_ID_CMD_646:
-			return ata66;
-		default:
-			break;
+	switch (dev->device) {
+	case PCI_DEVICE_ID_CMD_648:
+	case PCI_DEVICE_ID_CMD_649:
+ 		pci_read_config_byte(dev, BMIDECSR, &bmidecsr);
+		return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+	default:
+		return ATA_CBL_PATA40;
 	}
-	pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);
-	return (ata66 & mask) ? 1 : 0;
 }
 
 static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
-	unsigned int class_rev;
+	u8 rev			= 0;
 
-	hwif->autodma = 0;
-	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-	class_rev &= 0xff;
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
 
 	hwif->tuneproc  = &cmd64x_tune_drive;
 	hwif->speedproc = &cmd64x_tune_chipset;
@@ -580,8 +545,8 @@
 	if (!hwif->dma_base)
 		return;
 
-	hwif->atapi_dma = 1;
-
+	hwif->atapi_dma  = 1;
+	hwif->mwdma_mask = 0x07;
 	hwif->ultra_mask = hwif->cds->udma_mask;
 
 	/*
@@ -596,16 +561,15 @@
 	 *
 	 * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
 	 */
-	if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5)
+	if (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 5)
 		hwif->ultra_mask = 0x00;
 
-	hwif->mwdma_mask = 0x07;
-
 	hwif->ide_dma_check = &cmd64x_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_cmd64x(hwif);
 
-	switch(dev->device) {
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_cmd64x(hwif);
+
+	switch (dev->device) {
 	case PCI_DEVICE_ID_CMD_648:
 	case PCI_DEVICE_ID_CMD_649:
 	alt_irq_bits:
@@ -614,10 +578,10 @@
 		break;
 	case PCI_DEVICE_ID_CMD_646:
 		hwif->chipset = ide_cmd646;
-		if (class_rev == 0x01) {
+		if (rev == 0x01) {
 			hwif->ide_dma_end = &cmd646_1_ide_dma_end;
 			break;
-		} else if (class_rev >= 0x03)
+		} else if (rev >= 0x03)
 			goto alt_irq_bits;
 		/* fall thru */
 	default:
@@ -626,11 +590,9 @@
 		break;
 	}
 
-
 	if (!noautodma)
 		hwif->autodma = 1;
-	hwif->drives[0].autodma = hwif->autodma;
-	hwif->drives[1].autodma = hwif->autodma;
+	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
 }
 
 static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
@@ -640,14 +602,11 @@
 
 static int __devinit init_setup_cmd646(struct pci_dev *dev, ide_pci_device_t *d)
 {
-	u8 rev = 0;
-
 	/*
 	 * The original PCI0646 didn't have the primary channel enable bit,
 	 * it appeared starting with PCI0646U (i.e. revision ID 3).
 	 */
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-	if (rev < 3)
+	if (dev->revision < 3)
 		d->enablebits[0].reg = 0;
 
 	return ide_setup_pci_device(dev, d);
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index 1eec1f3..b5c00d1 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -236,7 +236,7 @@
 	 */
 
 	pci_set_master(cs5530_0);
-	pci_set_mwi(cs5530_0);
+	pci_try_set_mwi(cs5530_0);
 
 	/*
 	 * Set PCI CacheLineSize to 16-bytes:
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 41925c4..10f61f3 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -187,7 +187,8 @@
 
 	/* if a 80 wire cable was detected */
 	pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
-	return (bit & 1);
+
+	return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
 /****
@@ -212,8 +213,7 @@
 	hwif->ultra_mask = 0x1F;
 	hwif->mwdma_mask = 0x07;
 
-
-	hwif->udma_four = cs5535_cable_detect(hwif->pci_dev);
+	hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
 
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index f2c5a14..0d51a11 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -198,32 +198,41 @@
 static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	ide_pci_device_t *d = &generic_chipsets[id->driver_data];
-	u16 command;
 	int ret = -ENODEV;
 
 	/* Don't use the generic entry unless instructed to do so */
 	if (id->driver_data == 0 && ide_generic_all == 0)
 			goto out;
 
-	if (dev->vendor == PCI_VENDOR_ID_UMC &&
-	    dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
-	    (!(PCI_FUNC(dev->devfn) & 1)))
-		goto out; /* UM8886A/BF pair */
-
-	if (dev->vendor == PCI_VENDOR_ID_OPTI &&
-	    dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
-	    (!(PCI_FUNC(dev->devfn) & 1)))
-		goto out;
-
-	if (dev->vendor == PCI_VENDOR_ID_JMICRON) {
-		if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && PCI_FUNC(dev->devfn) != 1)
+	switch (dev->vendor) {
+	case PCI_VENDOR_ID_UMC:
+		if (dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
+				!(PCI_FUNC(dev->devfn) & 1))
+			goto out; /* UM8886A/BF pair */
+		break;
+	case PCI_VENDOR_ID_OPTI:
+		if (dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
+				!(PCI_FUNC(dev->devfn) & 1))
 			goto out;
+		break;
+	case PCI_VENDOR_ID_JMICRON:
+		if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 &&
+				PCI_FUNC(dev->devfn) != 1)
+			goto out;
+		break;
+	case PCI_VENDOR_ID_NS:
+		if (dev->device == PCI_DEVICE_ID_NS_87410 &&
+				(dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+			goto out;
+		break;
 	}
 
 	if (dev->vendor != PCI_VENDOR_ID_JMICRON) {
+		u16 command;
 		pci_read_config_word(dev, PCI_COMMAND, &command);
 		if (!(command & PCI_COMMAND_IO)) {
-			printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name);
+			printk(KERN_INFO "Skipping disabled %s IDE "
+					"controller.\n", d->name);
 			goto out;
 		}
 	}
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index fcbc560..e9b07a9 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/hpt366.c		Version 1.03	May 4, 2007
+ * linux/drivers/ide/pci/hpt366.c		Version 1.10	Jun 29, 2007
  *
  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
@@ -77,7 +77,7 @@
  *   since they may tamper with its fields
  * - prefix the driver startup messages with the real chip name
  * - claim the extra 240 bytes of I/O space for all chips
- * - optimize the rate masking/filtering and the drive list lookup code
+ * - optimize the UltraDMA filtering and the drive list lookup code
  * - use pci_get_slot() to get to the function 1 of HPT36x/374
  * - cache offset of the channel's misc. control registers (MCRs) being used
  *   throughout the driver
@@ -99,18 +99,20 @@
  *   stop duplicating it for each channel by storing the pointer in the pci_dev
  *   structure: first, at the init_setup stage, point it to a static "template"
  *   with only the chip type and its specific base DPLL frequency, the highest
- *   supported DMA mode, and the chip settings table pointer filled, then, at
- *   the init_chipset stage, allocate per-chip instance  and fill it with the
- *   rest of the necessary information
+ *   UltraDMA mode, and the chip settings table pointer filled,  then, at the
+ *   init_chipset stage, allocate per-chip instance  and fill it with the rest
+ *   of the necessary information
  * - get rid of the constant thresholds in the HPT37x PCI clock detection code,
  *   switch  to calculating  PCI clock frequency based on the chip's base DPLL
  *   frequency
  * - switch to using the  DPLL clock and enable UltraATA/133 mode by default on
- *   anything  newer than HPT370/A
+ *   anything  newer than HPT370/A (except HPT374 that is not capable of this
+ *   mode according to the manual)
  * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
  *   also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
  *   unify HPT36x/37x timing setup code and the speedproc handlers by joining
  *   the register setting lists into the table indexed by the clock selected
+ * - set the correct hwif->ultra_mask for each individual chip
  *	Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
  */
 
@@ -181,6 +183,7 @@
 	"IC35L040AVER07-0",
 	"IC35L060AVER07-0",
 	"WDC AC310200R",
+	"MAXTOR STM3320620A",
 	NULL
 };
 
@@ -365,7 +368,6 @@
 };
 
 #define HPT366_DEBUG_DRIVE_INFO		0
-#define HPT374_ALLOW_ATA133_6		1
 #define HPT371_ALLOW_ATA133_6		1
 #define HPT302_ALLOW_ATA133_6		1
 #define HPT372_ALLOW_ATA133_6		1
@@ -390,7 +392,7 @@
 
 struct hpt_info {
 	u8 chip_type;		/* Chip type */
-	u8 max_mode;		/* Speeds allowed */
+	u8 max_ultra;		/* Max. UltraDMA mode allowed */
 	u8 dpll_clk;		/* DPLL clock in MHz */
 	u8 pci_clk;		/* PCI  clock in MHz */
 	u32 **settings; 	/* Chipset settings table */
@@ -429,77 +431,77 @@
 
 static struct hpt_info hpt36x __devinitdata = {
 	.chip_type	= HPT36x,
-	.max_mode	= (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1,
+	.max_ultra	= HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? 4 : 3) : 2,
 	.dpll_clk	= 0,	/* no DPLL */
 	.settings	= hpt36x_settings
 };
 
 static struct hpt_info hpt370 __devinitdata = {
 	.chip_type	= HPT370,
-	.max_mode	= HPT370_ALLOW_ATA100_5 ? 3 : 2,
+	.max_ultra	= HPT370_ALLOW_ATA100_5 ? 5 : 4,
 	.dpll_clk	= 48,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt370a __devinitdata = {
 	.chip_type	= HPT370A,
-	.max_mode	= HPT370_ALLOW_ATA100_5 ? 3 : 2,
+	.max_ultra	= HPT370_ALLOW_ATA100_5 ? 5 : 4,
 	.dpll_clk	= 48,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt374 __devinitdata = {
 	.chip_type	= HPT374,
-	.max_mode	= HPT374_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= 5,
 	.dpll_clk	= 48,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt372 __devinitdata = {
 	.chip_type	= HPT372,
-	.max_mode	= HPT372_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT372_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 55,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt372a __devinitdata = {
 	.chip_type	= HPT372A,
-	.max_mode	= HPT372_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT372_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 66,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt302 __devinitdata = {
 	.chip_type	= HPT302,
-	.max_mode	= HPT302_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT372_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 66,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt371 __devinitdata = {
 	.chip_type	= HPT371,
-	.max_mode	= HPT371_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT371_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 66,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt372n __devinitdata = {
 	.chip_type	= HPT372N,
-	.max_mode	= HPT372_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT372_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 77,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt302n __devinitdata = {
 	.chip_type	= HPT302N,
-	.max_mode	= HPT302_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT302_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 77,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt371n __devinitdata = {
 	.chip_type	= HPT371N,
-	.max_mode	= HPT371_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT371_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 77,
 	.settings	= hpt37x_settings
 };
@@ -522,53 +524,38 @@
 static u8 hpt3xx_udma_filter(ide_drive_t *drive)
 {
 	struct hpt_info *info	= pci_get_drvdata(HWIF(drive)->pci_dev);
-	u8 chip_type		= info->chip_type;
-	u8 mode			= info->max_mode;
 	u8 mask;
 
-	switch (mode) {
-		case 0x04:
-			mask = 0x7f;
-			break;
-		case 0x03:
+	switch (info->chip_type) {
+	case HPT370A:
+		if (!HPT370_ALLOW_ATA100_5 ||
+		    check_in_drive_list(drive, bad_ata100_5))
+			return 0x1f;
+		else
+			return 0x3f;
+	case HPT370:
+		if (!HPT370_ALLOW_ATA100_5 ||
+		    check_in_drive_list(drive, bad_ata100_5))
+			mask = 0x1f;
+		else
 			mask = 0x3f;
-			if (chip_type >= HPT374)
-				break;
-			if (!check_in_drive_list(drive, bad_ata100_5))
-				goto check_bad_ata33;
-			/* fall thru */
-		case 0x02:
+		break;
+	case HPT36x:
+		if (!HPT366_ALLOW_ATA66_4 ||
+		    check_in_drive_list(drive, bad_ata66_4))
+			mask = 0x0f;
+		else
 			mask = 0x1f;
 
-			/*
-			 * CHECK ME, Does this need to be changed to HPT374 ??
-			 */
-			if (chip_type >= HPT370)
-				goto check_bad_ata33;
-			if (HPT366_ALLOW_ATA66_4 &&
-			    !check_in_drive_list(drive, bad_ata66_4))
-				goto check_bad_ata33;
-
-			mask = 0x0f;
-			if (HPT366_ALLOW_ATA66_3 &&
-			    !check_in_drive_list(drive, bad_ata66_3))
-				goto check_bad_ata33;
-			/* fall thru */
-		case 0x01:
+		if (!HPT366_ALLOW_ATA66_3 ||
+		    check_in_drive_list(drive, bad_ata66_3))
 			mask = 0x07;
-
-		check_bad_ata33:
-			if (chip_type >= HPT370A)
-				break;
-			if (!check_in_drive_list(drive, bad_ata33))
-				break;
-			/* fall thru */
-		case 0x00:
-		default:
-			mask = 0x00;
-			break;
+		break;
+	default:
+		return 0x7f;
 	}
-	return mask;
+
+	return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
 }
 
 static u32 get_speed_setting(u8 speed, struct hpt_info *info)
@@ -736,7 +723,7 @@
  * This is specific to the HPT366 UDMA chipset
  * by HighPoint|Triones Technologies, Inc.
  */
-static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
+static void hpt366_dma_lost_irq(ide_drive_t *drive)
 {
 	struct pci_dev *dev = HWIF(drive)->pci_dev;
 	u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
@@ -748,7 +735,7 @@
 		drive->name, __FUNCTION__, mcr1, mcr3, scr1);
 	if (scr1 & 0x10)
 		pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
-	return __ide_dma_lostirq(drive);
+	ide_dma_lost_irq(drive);
 }
 
 static void hpt370_clear_engine(ide_drive_t *drive)
@@ -798,10 +785,10 @@
 	return __ide_dma_end(drive);
 }
 
-static int hpt370_ide_dma_timeout(ide_drive_t *drive)
+static void hpt370_dma_timeout(ide_drive_t *drive)
 {
 	hpt370_irq_timeout(drive);
-	return __ide_dma_timeout(drive);
+	ide_dma_timeout(drive);
 }
 
 /* returns 1 if DMA IRQ issued, 0 otherwise */
@@ -1149,7 +1136,7 @@
 		  * Select 66 MHz DPLL clock only if UltraATA/133 mode is
 		  * supported/enabled, use 50 MHz DPLL clock otherwise...
 		  */
-		if (info->max_mode == 0x04) {
+		if (info->max_ultra == 6) {
 			dpll_clk = 66;
 			clock = ATA_CLOCK_66MHZ;
 		} else if (dpll_clk) {	/* HPT36x chips don't have DPLL */
@@ -1242,7 +1229,7 @@
 	struct pci_dev	*dev		= hwif->pci_dev;
 	struct hpt_info *info		= pci_get_drvdata(dev);
 	int serialize			= HPT_SERIALIZE_IO;
-	u8  scr1 = 0, ata66		= (hwif->channel) ? 0x01 : 0x02;
+	u8  scr1 = 0, ata66		= hwif->channel ? 0x01 : 0x02;
 	u8  chip_type			= info->chip_type;
 	u8  new_mcr, old_mcr 		= 0;
 
@@ -1255,7 +1242,9 @@
 	hwif->intrproc			= &hpt3xx_intrproc;
 	hwif->maskproc			= &hpt3xx_maskproc;
 	hwif->busproc			= &hpt3xx_busproc;
-	hwif->udma_filter		= &hpt3xx_udma_filter;
+
+	if (chip_type <= HPT370A)
+		hwif->udma_filter	= &hpt3xx_udma_filter;
 
 	/*
 	 * HPT3xxN chips have some complications:
@@ -1304,7 +1293,7 @@
 		return;
 	}
 
-	hwif->ultra_mask = 0x7f;
+	hwif->ultra_mask = hwif->cds->udma_mask;
 	hwif->mwdma_mask = 0x07;
 
 	/*
@@ -1341,8 +1330,8 @@
 	} else
 		pci_read_config_byte (dev, 0x5a, &scr1);
 
-	if (!hwif->udma_four)
-		hwif->udma_four = (scr1 & ata66) ? 0 : 1;
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 
 	hwif->ide_dma_check		= &hpt366_config_drive_xfer_rate;
 
@@ -1352,9 +1341,9 @@
 	} else if (chip_type >= HPT370) {
 		hwif->dma_start 	= &hpt370_ide_dma_start;
 		hwif->ide_dma_end	= &hpt370_ide_dma_end;
-		hwif->ide_dma_timeout	= &hpt370_ide_dma_timeout;
+		hwif->dma_timeout	= &hpt370_dma_timeout;
 	} else
-		hwif->ide_dma_lostirq	= &hpt366_ide_dma_lostirq;
+		hwif->dma_lost_irq	= &hpt366_dma_lost_irq;
 
 	if (!noautodma)
 		hwif->autodma = 1;
@@ -1424,11 +1413,9 @@
 static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
 {
 	struct hpt_info *info;
-	u8 rev = 0, mcr1 = 0;
+	u8 mcr1 = 0;
 
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-	if (rev > 1) {
+	if (dev->revision > 1) {
 		d->name = "HPT371N";
 
 		info = &hpt371n;
@@ -1453,11 +1440,8 @@
 static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d)
 {
 	struct hpt_info *info;
-	u8 rev = 0;
 
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-	if (rev > 1) {
+	if (dev->revision > 1) {
 		d->name = "HPT372N";
 
 		info = &hpt372n;
@@ -1471,11 +1455,8 @@
 static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d)
 {
 	struct hpt_info *info;
-	u8 rev = 0;
 
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-	if (rev > 1) {
+	if (dev->revision > 1) {
 		d->name = "HPT302N";
 
 		info = &hpt302n;
@@ -1489,7 +1470,7 @@
 static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
 {
 	struct pci_dev *dev2;
-	u8 rev = 0;
+	u8 rev = dev->revision;
 	static char   *chipset_names[] = { "HPT366", "HPT366",  "HPT368",
 					   "HPT370", "HPT370A", "HPT372",
 					   "HPT372N" };
@@ -1500,11 +1481,35 @@
 	if (PCI_FUNC(dev->devfn) & 1)
 		return -ENODEV;
 
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+	switch (rev) {
+	case 0:
+	case 1:
+	case 2:
+		/*
+		 * HPT36x chips have one channel per function and have
+		 * both channel enable bits located differently and visible
+		 * to both functions -- really stupid design decision... :-(
+		 * Bit 4 is for the primary channel, bit 5 for the secondary.
+		 */
+		d->channels = 1;
+		d->enablebits[0].mask = d->enablebits[0].val = 0x10;
 
-	if (rev > 6)
+		d->udma_mask = HPT366_ALLOW_ATA66_3 ?
+			      (HPT366_ALLOW_ATA66_4 ? 0x1f : 0x0f) : 0x07;
+		break;
+	case 3:
+	case 4:
+		d->udma_mask = HPT370_ALLOW_ATA100_5 ? 0x3f : 0x1f;
+		break;
+	default:
 		rev = 6;
-		
+		/* fall thru */
+	case 5:
+	case 6:
+		d->udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f;
+		break;
+	}
+
 	d->name = chipset_names[rev];
 
 	pci_set_drvdata(dev, info[rev]);
@@ -1512,19 +1517,20 @@
 	if (rev > 2)
 		goto init_single;
 
-	/*
-	 * HPT36x chips are single channel and
-	 * do not seem to have the channel enable bit...
-	 */
-	d->channels = 1;
-	d->enablebits[0].reg = 0;
-
 	if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
-	  	u8  pin1 = 0, pin2 = 0;
+		u8  mcr1 = 0, pin1 = 0, pin2 = 0;
 		int ret;
 
 		pci_set_drvdata(dev2, info[rev]);
 
+		/*
+		 * Now we'll have to force both channels enabled if
+		 * at least one of them has been enabled by BIOS...
+		 */
+		pci_read_config_byte(dev, 0x50, &mcr1);
+		if (mcr1 & 0x30)
+			pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
+
 		pci_read_config_byte(dev,  PCI_INTERRUPT_PIN, &pin1);
 		pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
 		if (pin1 != pin2 && dev->irq == dev2->irq) {
@@ -1562,6 +1568,7 @@
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	},{	/* 2 */
@@ -1573,6 +1580,7 @@
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= HPT302_ALLOW_ATA133_6 ? 0x7f : 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	},{	/* 3 */
@@ -1584,6 +1592,7 @@
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= HPT371_ALLOW_ATA133_6 ? 0x7f : 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	},{	/* 4 */
@@ -1595,6 +1604,7 @@
 		.channels	= 2,	/* 4 */
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	},{	/* 5 */
@@ -1606,6 +1616,7 @@
 		.channels	= 2,	/* 4 */
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	}
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index c04a026..ff48c23 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -231,7 +231,7 @@
 
 static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
 {
-	u8 reg42h = 0, ata66 = 0;
+	u8 reg42h = 0;
 
 	hwif->speedproc = &it8213_tune_chipset;
 	hwif->tuneproc	= &it8213_tuneproc;
@@ -250,11 +250,11 @@
 	hwif->swdma_mask = 0x04;
 
 	pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
-	ata66 = (reg42h & 0x02) ? 0 : 1;
 
 	hwif->ide_dma_check = &it8213_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66;
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 
 	/*
 	 *	The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 5faaff8..8197b65 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -1,6 +1,6 @@
 
 /*
- * linux/drivers/ide/pci/it821x.c		Version 0.10	Mar 10 2007
+ * linux/drivers/ide/pci/it821x.c		Version 0.16	Jul 3 2007
  *
  * Copyright (C) 2004		Red Hat <alan@redhat.com>
  * Copyright (C) 2007		Bartlomiej Zolnierkiewicz
@@ -262,7 +262,7 @@
 	}
 
 	if (itdev->smart)
-		goto set_drive_speed;
+		return 0;
 
 	/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
 	itdev->want[unit][1] = pio_want[set_pio];
@@ -271,7 +271,6 @@
 	it821x_clock_strategy(drive);
 	it821x_program(drive, itdev->pio[unit]);
 
-set_drive_speed:
 	return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
 }
 
@@ -455,12 +454,12 @@
 			default:
 				return 1;
 		}
+
+		return ide_config_drive_speed(drive, speed);
 	}
-	/*
-	 *	In smart mode the clocking is done by the host controller
-	 * 	snooping the mode we picked. The rest of it is not our problem
-	 */
-	return ide_config_drive_speed(drive, speed);
+
+	/* don't touch anything in the smart mode */
+	return 0;
 }
 
 /**
@@ -492,10 +491,10 @@
  *	the needed logic onboard.
  */
 
-static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif)
+static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
 {
 	/* The reference driver also only does disk side */
-	return 1;
+	return ATA_CBL_PATA80;
 }
 
 /**
@@ -559,17 +558,10 @@
 				if(idbits[129] != 1)
 					printk("(%dK stripe)", idbits[146]);
 				printk(".\n");
-			/* Now the core code will have wrongly decided no DMA
-			   so we need to fix this */
-			hwif->dma_off_quietly(drive);
-#ifdef CONFIG_IDEDMA_ONLYDISK
-			if (drive->media == ide_disk)
-#endif
-				ide_set_dma(drive);
 		} else {
 			/* Non RAID volume. Fixups to stop the core code
 			   doing unsupported things */
-			id->field_valid &= 1;
+			id->field_valid &= 3;
 			id->queue_depth = 0;
 			id->command_set_1 = 0;
 			id->command_set_2 &= 0xC400;
@@ -584,6 +576,16 @@
 			printk(KERN_INFO "%s: Performing identify fixups.\n",
 				drive->name);
 		}
+
+		/*
+		 * Set MWDMA0 mode as enabled/support - just to tell
+		 * IDE core that DMA is supported (it821x hardware
+		 * takes care of DMA mode programming).
+		 */
+		if (id->capability & 1) {
+			id->dma_mword |= 0x0101;
+			drive->current_speed = XFER_MW_DMA_0;
+		}
 	}
 
 }
@@ -658,11 +660,11 @@
 
 	hwif->ultra_mask = 0x7f;
 	hwif->mwdma_mask = 0x07;
-	hwif->swdma_mask = 0x07;
 
 	hwif->ide_dma_check = &it821x_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_it821x(hwif);
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_it821x(hwif);
 
 	/*
 	 *	The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 76ed251..a6008f6 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -25,10 +25,10 @@
  *	ata66_jmicron		-	Cable check
  *	@hwif: IDE port
  *
- *	Return 1 if the cable is 80pin
+ *	Returns the cable type.
  */
 
-static int __devinit ata66_jmicron(ide_hwif_t *hwif)
+static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
 {
 	struct pci_dev *pdev = hwif->pci_dev;
 
@@ -70,16 +70,17 @@
 	{
 	case PORT_PATA0:
 		if (control & (1 << 3))	/* 40/80 pin primary */
-			return 0;
-		return 1;
+			return ATA_CBL_PATA40;
+		return ATA_CBL_PATA80;
 	case PORT_PATA1:
 		if (control5 & (1 << 19))	/* 40/80 pin secondary */
-			return 0;
-		return 1;
+			return ATA_CBL_PATA40;
+		return ATA_CBL_PATA80;
 	case PORT_SATA:
 		break;
 	}
-	return 1; /* Avoid bogus "control reaches end of non-void function" */
+	/* Avoid bogus "control reaches end of non-void function" */
+	return ATA_CBL_PATA80;
 }
 
 static void jmicron_tuneproc (ide_drive_t *drive, byte mode_wanted)
@@ -159,8 +160,9 @@
 	hwif->mwdma_mask = 0x07;
 
 	hwif->ide_dma_check = &jmicron_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_jmicron(hwif);
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_jmicron(hwif);
 
 	hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index cc0bfdc..ee5020d 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -225,7 +225,10 @@
 
 static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
 {
-	return get_indexed_reg(hwif, 0x0b) & 0x04;
+	if (get_indexed_reg(hwif, 0x0b) & 0x04)
+		return ATA_CBL_PATA40;
+	else
+		return ATA_CBL_PATA80;
 }
 
 static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
@@ -306,11 +309,13 @@
  */
 static long __devinit detect_pll_input_clock(unsigned long dma_base)
 {
+	struct timeval start_time, end_time;
 	long start_count, end_count;
-	long pll_input;
+	long pll_input, usec_elapsed;
 	u8 scr1;
 
 	start_count = read_counter(dma_base);
+	do_gettimeofday(&start_time);
 
 	/* Start the test mode */
 	outb(0x01, dma_base + 0x01);
@@ -322,6 +327,7 @@
 	mdelay(10);
 
 	end_count = read_counter(dma_base);
+	do_gettimeofday(&end_time);
 
 	/* Stop the test mode */
 	outb(0x01, dma_base + 0x01);
@@ -333,7 +339,10 @@
 	 * Calculate the input clock in Hz
 	 * (the clock counter is 30 bit wide and counts down)
 	 */
-	pll_input = ((start_count - end_count) & 0x3ffffff) * 100;
+	usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
+		(end_time.tv_usec - start_time.tv_usec);
+	pll_input = ((start_count - end_count) & 0x3ffffff) / 10 *
+		(10000000 / usec_elapsed);
 
 	DBG("start[%ld] end[%ld]\n", start_count, end_count);
 
@@ -503,8 +512,8 @@
 
 	hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
 
-	if (!hwif->udma_four)
-		hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1;
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = pdcnew_cable_detect(hwif);
 
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 2384468..41ac4a9 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -152,8 +152,10 @@
 static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
 {
 	u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
+
 	pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
-	return (CIS & mask) ? 1 : 0;
+
+	return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
 
 /*
@@ -267,18 +269,24 @@
 	return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
 }
 
-static int pdc202xx_ide_dma_lostirq(ide_drive_t *drive)
+static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
 {
-	if (HWIF(drive)->resetproc != NULL)
-		HWIF(drive)->resetproc(drive);
-	return __ide_dma_lostirq(drive);
+	ide_hwif_t *hwif = HWIF(drive);
+
+	if (hwif->resetproc != NULL)
+		hwif->resetproc(drive);
+
+	ide_dma_lost_irq(drive);
 }
 
-static int pdc202xx_ide_dma_timeout(ide_drive_t *drive)
+static void pdc202xx_dma_timeout(ide_drive_t *drive)
 {
-	if (HWIF(drive)->resetproc != NULL)
-		HWIF(drive)->resetproc(drive);
-	return __ide_dma_timeout(drive);
+	ide_hwif_t *hwif = HWIF(drive);
+
+	if (hwif->resetproc != NULL)
+		hwif->resetproc(drive);
+
+	ide_dma_timeout(drive);
 }
 
 static void pdc202xx_reset_host (ide_hwif_t *hwif)
@@ -347,12 +355,13 @@
 	hwif->err_stops_fifo = 1;
 
 	hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate;
-	hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq;
-	hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout;
+	hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
+	hwif->dma_timeout = &pdc202xx_dma_timeout;
 
 	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
-		if (!(hwif->udma_four))
-			hwif->udma_four = (pdc202xx_old_cable_detect(hwif)) ? 0 : 1;
+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+			hwif->cbl = pdc202xx_old_cable_detect(hwif);
+
 		hwif->dma_start = &pdc202xx_old_ide_dma_start;
 		hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
 	} 
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 8b219dd..1372c35 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/pci/piix.c	Version 0.47	February 8, 2007
+ *  linux/drivers/ide/pci/piix.c	Version 0.50	Jun 10, 2007
  *
  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -394,14 +394,45 @@
 	hwif->OUTB(dma_stat, hwif->dma_status);
 }
 
-static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+struct ich_laptop {
+	u16 device;
+	u16 subvendor;
+	u16 subdevice;
+};
+
+/*
+ *	List of laptops that use short cables rather than 80 wire
+ */
+
+static const struct ich_laptop ich_laptop[] = {
+	/* devid, subvendor, subdev */
+	{ 0x27DF, 0x0005, 0x0280 },	/* ICH7 on Acer 5602WLMi */
+	{ 0x27DF, 0x1025, 0x0110 },	/* ICH7 on Acer 3682WLMi */
+	{ 0x27DF, 0x1043, 0x1267 },	/* ICH7 on Asus W5F */
+	{ 0x24CA, 0x1025, 0x0061 },	/* ICH4 on Acer Aspire 2023WLMi */
+	/* end marker */
+	{ 0, }
+};
+
+static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *pdev = hwif->pci_dev;
+	const struct ich_laptop *lap = &ich_laptop[0];
 	u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
 
-	pci_read_config_byte(dev, 0x54, &reg54h);
+	/* check for specials */
+	while (lap->device) {
+		if (lap->device == pdev->device &&
+		    lap->subvendor == pdev->subsystem_vendor &&
+		    lap->subdevice == pdev->subsystem_device) {
+			return ATA_CBL_PATA40_SHORT;
+		}
+		lap++;
+	}
 
-	return (reg54h & mask) ? 1 : 0;
+	pci_read_config_byte(pdev, 0x54, &reg54h);
+
+	return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
 /**
@@ -444,8 +475,8 @@
 	hwif->swdma_mask = 0x04;
 
 	if (hwif->ultra_mask & 0x78) {
-		if (!hwif->udma_four)
-			hwif->udma_four = piix_cable_detect(hwif);
+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+			hwif->cbl = piix_cable_detect(hwif);
 	}
 
 	if (no_piix_dma)
@@ -541,18 +572,16 @@
 {
 	struct pci_dev *pdev = NULL;
 	u16 cfg;
-	u8 rev;
 	while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
 	{
 		/* Look for 450NX PXB. Check for problem configurations
 		   A PCI quirk checks bit 6 already */
-		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
 		pci_read_config_word(pdev, 0x41, &cfg);
 		/* Only on the original revision: IDE DMA can hang */
-		if(rev == 0x00)
+		if (pdev->revision == 0x00)
 			no_piix_dma = 1;
 		/* On all revisions below 5 PXB bus lock must be disabled for IDE */
-		else if(cfg & (1<<14) && rev < 5)
+		else if (cfg & (1<<14) && pdev->revision < 5)
 			no_piix_dma = 2;
 	}
 	if(no_piix_dma)
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 55bc0a3..7b87488 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -716,7 +716,7 @@
 	hwif->atapi_dma = 1;
 
 	/* we support 80c cable only. */
-	hwif->udma_four = 1;
+	hwif->cbl = ATA_CBL_PATA80;
 
 	hwif->autodma = 0;
 	if (!noautodma)
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 6234f80..ed04e0c 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/serverworks.c		Version 0.9	Mar 4 2007
+ * linux/drivers/ide/pci/serverworks.c		Version 0.20	Jun 3 2007
  *
  * Copyright (C) 1998-2000 Michel Aubry
  * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -55,7 +55,6 @@
 	NULL
 };
 
-static u8 svwks_revision = 0;
 static struct pci_dev *isa_dev;
 
 static int check_in_drive_lists (ide_drive_t *drive, const char **list)
@@ -71,9 +70,6 @@
 	struct pci_dev *dev     = HWIF(drive)->pci_dev;
 	u8 mask = 0;
 
-	if (!svwks_revision)
-		pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
-
 	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
 		return 0x1f;
 	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
@@ -88,9 +84,9 @@
 			return 0;
 		/* Check the OSB4 DMA33 enable bit */
 		return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0;
-	} else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) {
+	} else if (dev->revision < SVWKS_CSB5_REVISION_NEW) {
 		return 0x07;
-	} else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) {
+	} else if (dev->revision >= SVWKS_CSB5_REVISION_NEW) {
 		u8 btr = 0, mode;
 		pci_read_config_byte(dev, 0x5A, &btr);
 		mode = btr & 0x3;
@@ -151,65 +147,11 @@
 	if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 &&
 		drive->media == ide_disk && speed >= XFER_UDMA_0)
 			BUG();
-			
-	pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing);
-	pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing);
+
 	pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
 	pci_read_config_word(dev, 0x4A, &csb5_pio);
 	pci_read_config_byte(dev, 0x54, &ultra_enable);
 
-	/* Per Specified Design by OEM, and ASIC Architect */
-	if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
-		if (!drive->init_speed) {
-			u8 dma_stat = inb(hwif->dma_status);
-
-dma_pio:
-			if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
-			    ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
-				drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
-				return 0;
-			} else if ((dma_timing) &&
-				   ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
-				u8 dmaspeed = dma_timing;
-
-				dma_timing &= ~0xFF;
-				if ((dmaspeed & 0x20) == 0x20)
-					dmaspeed = XFER_MW_DMA_2;
-				else if ((dmaspeed & 0x21) == 0x21)
-					dmaspeed = XFER_MW_DMA_1;
-				else if ((dmaspeed & 0x77) == 0x77)
-					dmaspeed = XFER_MW_DMA_0;
-				else
-					goto dma_pio;
-				drive->current_speed = drive->init_speed = dmaspeed;
-				return 0;
-			} else if (pio_timing) {
-				u8 piospeed = pio_timing;
-
-				pio_timing &= ~0xFF;
-				if ((piospeed & 0x20) == 0x20)
-					piospeed = XFER_PIO_4;
-				else if ((piospeed & 0x22) == 0x22)
-					piospeed = XFER_PIO_3;
-				else if ((piospeed & 0x34) == 0x34)
-					piospeed = XFER_PIO_2;
-				else if ((piospeed & 0x47) == 0x47)
-					piospeed = XFER_PIO_1;
-				else if ((piospeed & 0x5d) == 0x5d)
-					piospeed = XFER_PIO_0;
-				else
-					goto oem_setup_failed;
-				drive->current_speed = drive->init_speed = piospeed;
-				return 0;
-			}
-		}
-	}
-
-oem_setup_failed:
-
-	pio_timing	&= ~0xFF;
-	dma_timing	&= ~0xFF;
 	ultra_timing	&= ~(0x0F << (4*unit));
 	ultra_enable	&= ~(0x01 << drive->dn);
 	csb5_pio	&= ~(0x0F << (4*drive->dn));
@@ -288,9 +230,6 @@
 	unsigned int reg;
 	u8 btr;
 
-	/* save revision id to determine DMA capability */
-	pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
-
 	/* force Master Latency Timer value to 64 PCICLKs */
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
 
@@ -369,7 +308,7 @@
 		if (!(PCI_FUNC(dev->devfn) & 1))
 			btr |= 0x2;
 		else
-			btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
+			btr |= (dev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
 		pci_write_config_byte(dev, 0x5A, btr);
 	}
 	/* Setup HT1000 SouthBridge Controller - Single Channel Only */
@@ -383,9 +322,9 @@
 	return dev->irq;
 }
 
-static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
 {
-	return 1;
+	return ATA_CBL_PATA80;
 }
 
 /* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits
@@ -395,7 +334,7 @@
  * Bit 14 clear = primary IDE channel does not have 80-pin cable.
  * Bit 14 set   = primary IDE channel has 80-pin cable.
  */
-static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
@@ -403,8 +342,8 @@
 	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
 	     dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE))
 		return ((1 << (hwif->channel + 14)) &
-			dev->subsystem_device) ? 1 : 0;
-	return 0;
+			dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+	return ATA_CBL_PATA40;
 }
 
 /* Sun Cobalt Alpine hardware avoids the 80-pin cable
@@ -413,18 +352,18 @@
  *
  * WARNING: this only works on Alpine hardware!
  */
-static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
 		return ((1 << (hwif->channel + 14)) &
-			dev->subsystem_device) ? 1 : 0;
-	return 0;
+			dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+	return ATA_CBL_PATA40;
 }
 
-static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 
@@ -443,9 +382,9 @@
 	/* Per Specified Design by OEM, and ASIC Architect */
 	if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
 	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
-		return 1;
+		return ATA_CBL_PATA80;
 
-	return 0;
+	return ATA_CBL_PATA40;
 }
 
 static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
@@ -476,8 +415,8 @@
 
 	hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
 	if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
-		if (!hwif->udma_four)
-			hwif->udma_four = ata66_svwks(hwif);
+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+			hwif->cbl = ata66_svwks(hwif);
 	}
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index d3185e2..d396b29 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -316,14 +316,6 @@
 	sgiioc4_clearirq(drive);
 }
 
-static int
-sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
-{
-	HWIF(drive)->resetproc(drive);
-
-	return __ide_dma_lostirq(drive);
-}
-
 static void
 sgiioc4_resetproc(ide_drive_t * drive)
 {
@@ -331,6 +323,14 @@
 	sgiioc4_clearirq(drive);
 }
 
+static void
+sgiioc4_dma_lost_irq(ide_drive_t * drive)
+{
+	sgiioc4_resetproc(drive);
+
+	ide_dma_lost_irq(drive);
+}
+
 static u8
 sgiioc4_INB(unsigned long port)
 {
@@ -607,8 +607,8 @@
 	hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
 	hwif->dma_host_on = &sgiioc4_dma_host_on;
 	hwif->dma_host_off = &sgiioc4_dma_host_off;
-	hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
-	hwif->ide_dma_timeout = &__ide_dma_timeout;
+	hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
+	hwif->dma_timeout = &ide_dma_timeout;
 
 	hwif->INB = &sgiioc4_INB;
 }
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 1a4444e..1c3e354 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -933,16 +933,17 @@
  *	interface.
  */
 
-static unsigned int __devinit ata66_siimage(ide_hwif_t *hwif)
+static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
 {
 	unsigned long addr = siimage_selreg(hwif, 0);
-	if (pci_get_drvdata(hwif->pci_dev) == NULL) {
-		u8 ata66 = 0;
-		pci_read_config_byte(hwif->pci_dev, addr, &ata66);
-		return (ata66 & 0x01) ? 1 : 0;
-	}
+	u8 ata66 = 0;
 
-	return (hwif->INB(addr) & 0x01) ? 1 : 0;
+	if (pci_get_drvdata(hwif->pci_dev) == NULL)
+		pci_read_config_byte(hwif->pci_dev, addr, &ata66);
+	else
+		ata66 = hwif->INB(addr);
+
+	return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
 /**
@@ -988,8 +989,9 @@
 		hwif->atapi_dma = 1;
 
 	hwif->ide_dma_check = &siimage_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_siimage(hwif);
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_siimage(hwif);
 
 	if (hwif->mmio) {
 		hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index bb6cc4a..756a9b6 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/sis5513.c	Version 0.20	Mar 4, 2007
+ * linux/drivers/ide/pci/sis5513.c	Version 0.25	Jun 10, 2007
  *
  * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
@@ -659,9 +659,7 @@
 
 		/* Special case for SiS630 : 630S/ET is ATA_100a */
 		if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {
-			u8 hostrev;
-			pci_read_config_byte(host, PCI_REVISION_ID, &hostrev);
-			if (hostrev >= 0x30)
+			if (host->revision >= 0x30)
 				chipset_family = ATA_100a;
 		}
 		pci_dev_put(host);
@@ -702,7 +700,6 @@
 			u16 trueid;
 			u8 prefctl;
 			u8 idecfg;
-			u8 sbrev;
 
 			pci_read_config_byte(dev, 0x4a, &idecfg);
 			pci_write_config_byte(dev, 0x4a, idecfg | 0x10);
@@ -712,11 +709,10 @@
 			if (trueid == 0x5517) { /* SiS 961/961B */
 
 				lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
-				pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
 				pci_read_config_byte(dev, 0x49, &prefctl);
 				pci_dev_put(lpc_bridge);
 
-				if (sbrev == 0x10 && (prefctl & 0x80)) {
+				if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
 					printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
 					chipset_family = ATA_133a;
 				} else {
@@ -796,10 +792,33 @@
 	return 0;
 }
 
-static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
+struct sis_laptop {
+	u16 device;
+	u16 subvendor;
+	u16 subdevice;
+};
+
+static const struct sis_laptop sis_laptop[] = {
+	/* devid, subvendor, subdev */
+	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */
+	/* end marker */
+	{ 0, }
+};
+
+static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
 {
+	struct pci_dev *pdev = hwif->pci_dev;
+	const struct sis_laptop *lap = &sis_laptop[0];
 	u8 ata66 = 0;
 
+	while (lap->device) {
+		if (lap->device == pdev->device &&
+		    lap->subvendor == pdev->subsystem_vendor &&
+		    lap->subdevice == pdev->subsystem_device)
+			return ATA_CBL_PATA40_SHORT;
+		lap++;
+	}
+
 	if (chipset_family >= ATA_133) {
 		u16 regw = 0;
 		u16 reg_addr = hwif->channel ? 0x52: 0x50;
@@ -811,7 +830,8 @@
 		pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
 		ata66 = (reg48h & mask) ? 0 : 1;
 	}
-        return ata66;
+
+	return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
 static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
@@ -841,8 +861,8 @@
 	if (!chipset_family)
 		return;
 
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_sis5513(hwif);
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_sis5513(hwif);
 
 	if (chipset_family > ATA_16) {
 		hwif->ide_dma_check = &sis5513_config_xfer_rate;
@@ -872,6 +892,7 @@
 static struct pci_device_id sis5513_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_1180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 7c383d9..a7323d2 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -195,7 +195,7 @@
  * This function is called when the IDE timer expires, the drive
  * indicates that it is READY, and we were waiting for DMA to complete.
  */
-static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
+static void sl82c105_dma_lost_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -222,9 +222,6 @@
 	}
 
 	sl82c105_reset_host(dev);
-
-	/* __ide_dma_lostirq would return 1, so we do as well */
-	return 1;
 }
 
 /*
@@ -244,15 +241,12 @@
 	ide_dma_start(drive);
 }
 
-static int sl82c105_ide_dma_timeout(ide_drive_t *drive)
+static void sl82c105_dma_timeout(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
 
-	DBG(("sl82c105_ide_dma_timeout(drive:%s)\n", drive->name));
-
-	sl82c105_reset_host(dev);
-	return __ide_dma_timeout(drive);
+	sl82c105_reset_host(HWIF(drive)->pci_dev);
+	ide_dma_timeout(drive);
 }
 
 static int sl82c105_ide_dma_on(ide_drive_t *drive)
@@ -344,7 +338,6 @@
 static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
 {
 	struct pci_dev *bridge;
-	u8 rev;
 
 	/*
 	 * The bridge should be part of the same device, but function 0.
@@ -366,10 +359,9 @@
 	/*
 	 * We need to find function 0's revision, not function 1
 	 */
-	pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
 	pci_dev_put(bridge);
 
-	return rev;
+	return bridge->revision;
 }
 
 /*
@@ -441,9 +433,9 @@
 	hwif->ide_dma_check		= &sl82c105_ide_dma_check;
 	hwif->ide_dma_on		= &sl82c105_ide_dma_on;
 	hwif->dma_off_quietly		= &sl82c105_dma_off_quietly;
-	hwif->ide_dma_lostirq		= &sl82c105_ide_dma_lostirq;
+	hwif->dma_lost_irq		= &sl82c105_dma_lost_irq;
 	hwif->dma_start			= &sl82c105_dma_start;
-	hwif->ide_dma_timeout		= &sl82c105_ide_dma_timeout;
+	hwif->dma_timeout		= &sl82c105_dma_timeout;
 
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index c40f291..575dbbd 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -199,10 +199,9 @@
 	hwif->mwdma_mask = 0x06;
 	hwif->swdma_mask = 0x04;
 
-	if (!hwif->udma_four) {
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
 		/* bit[0(1)]: 0:80, 1:40 */
-		hwif->udma_four = (reg47 & mask) ? 0 : 1;
-	}
+		hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 
 	hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate;
 
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index cee619b..8de1f8e 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -220,13 +220,13 @@
 	hwif->ide_dma_check	= &tc86c001_config_drive_xfer_rate;
 	hwif->dma_start 	= &tc86c001_dma_start;
 
-	if (!hwif->udma_four) {
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
 		/*
 		 * System Control  1 Register bit 13 (PDIAGN):
 		 * 0=80-pin cable, 1=40-pin cable
 		 */
 		scr1 = hwif->INW(sc_base + 0x00);
-		hwif->udma_four = (scr1 & 0x2000) ? 0 : 1;
+		hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 	}
 
 	if (!noautodma)
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index a508550..27e92fb 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -1,6 +1,6 @@
 /*
  *
- * Version 3.38
+ * Version 3.45
  *
  * VIA IDE driver for Linux. Supported southbridges:
  *
@@ -9,6 +9,7 @@
  *   vt8235, vt8237, vt8237a
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
  *
  * Based on the work of:
  *	Michel Aubry
@@ -33,6 +34,8 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ide.h>
+#include <linux/dmi.h>
+
 #include <asm/io.h>
 
 #ifdef CONFIG_PPC_CHRP
@@ -41,8 +44,6 @@
 
 #include "ide-timing.h"
 
-#define DISPLAY_VIA_TIMINGS
-
 #define VIA_IDE_ENABLE		0x40
 #define VIA_IDE_CONFIG		0x41
 #define VIA_FIFO_CONFIG		0x43
@@ -54,18 +55,12 @@
 #define VIA_ADDRESS_SETUP	0x4c
 #define VIA_UDMA_TIMING		0x50
 
-#define VIA_UDMA		0x007
-#define VIA_UDMA_NONE		0x000
-#define VIA_UDMA_33		0x001
-#define VIA_UDMA_66		0x002
-#define VIA_UDMA_100		0x003
-#define VIA_UDMA_133		0x004
-#define VIA_BAD_PREQ		0x010	/* Crashes if PREQ# till DDACK# set */
-#define VIA_BAD_CLK66		0x020	/* 66 MHz clock doesn't work correctly */
-#define VIA_SET_FIFO		0x040	/* Needs to have FIFO split set */
-#define VIA_NO_UNMASK		0x080	/* Doesn't work with IRQ unmasking on */
-#define VIA_BAD_ID		0x100	/* Has wrong vendor ID (0x1107) */
-#define VIA_BAD_AST		0x200	/* Don't touch Address Setup Timing */
+#define VIA_BAD_PREQ		0x01 /* Crashes if PREQ# till DDACK# set */
+#define VIA_BAD_CLK66		0x02 /* 66 MHz clock doesn't work correctly */
+#define VIA_SET_FIFO		0x04 /* Needs to have FIFO split set */
+#define VIA_NO_UNMASK		0x08 /* Doesn't work with IRQ unmasking on */
+#define VIA_BAD_ID		0x10 /* Has wrong vendor ID (0x1107) */
+#define VIA_BAD_AST		0x20 /* Don't touch Address Setup Timing */
 
 /*
  * VIA SouthBridge chips.
@@ -76,36 +71,37 @@
 	u16 id;
 	u8 rev_min;
 	u8 rev_max;
-	u16 flags;
+	u8 udma_mask;
+	u8 flags;
 } via_isa_bridges[] = {
-	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8237s",	PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8237a",	PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8233c",	PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, VIA_UDMA_100 },
-	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, VIA_UDMA_100 },
-	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, VIA_UDMA_100 },
-	{ "vt82c686b",	PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, VIA_UDMA_100 },
-	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, VIA_UDMA_66 },
-	{ "vt82c686",	PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
-	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, VIA_UDMA_66 },
-	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
-	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO },
-	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ },
-	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO },
-	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },
-	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
-	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },
-	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8237s",	PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8237a",	PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8233c",	PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, ATA_UDMA5, },
+	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, ATA_UDMA5, },
+	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, ATA_UDMA5, },
+	{ "vt82c686b",	PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, ATA_UDMA5, },
+	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, ATA_UDMA4, },
+	{ "vt82c686",	PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, ATA_UDMA4, },
+	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO },
+	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO },
+	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f,      0x00, VIA_SET_FIFO },
+	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK },
+	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
 	{ NULL }
 };
 
 static unsigned int via_clock;
-static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
 
 struct via82cxxx_dev
 {
@@ -140,12 +136,12 @@
 	pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
 		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
 
-	switch (vdev->via_config->flags & VIA_UDMA) {
-		case VIA_UDMA_33:  t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
-		case VIA_UDMA_66:  t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
-		case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
-		case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
-		default: return;
+	switch (vdev->via_config->udma_mask) {
+	case ATA_UDMA2: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+	case ATA_UDMA4: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
+	case ATA_UDMA5: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+	case ATA_UDMA6: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+	default: return;
 	}
 
 	pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
@@ -173,12 +169,12 @@
 
 	T = 1000000000 / via_clock;
 
-	switch (vdev->via_config->flags & VIA_UDMA) {
-		case VIA_UDMA_33:   UT = T;   break;
-		case VIA_UDMA_66:   UT = T/2; break;
-		case VIA_UDMA_100:  UT = T/3; break;
-		case VIA_UDMA_133:  UT = T/4; break;
-		default: UT = T;
+	switch (vdev->via_config->udma_mask) {
+	case ATA_UDMA2: UT = T;   break;
+	case ATA_UDMA4: UT = T/2; break;
+	case ATA_UDMA5: UT = T/3; break;
+	case ATA_UDMA6: UT = T/4; break;
+	default:	UT = T;
 	}
 
 	ide_timing_compute(drive, speed, &t, T, UT);
@@ -208,8 +204,7 @@
 static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
 {
 	if (pio == 255) {
-		via_set_drive(drive,
-			ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+		via_set_drive(drive, ide_find_best_pio_mode(drive));
 		return;
 	}
 
@@ -226,16 +221,10 @@
  
 static int via82cxxx_ide_dma_check (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
-	u16 w80 = hwif->udma_four;
+	u8 speed = ide_max_dma_mode(drive);
 
-	u16 speed = ide_find_best_mode(drive,
-		XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
-		(vdev->via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
-		(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
-		(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
-		(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
+	if (speed == 0)
+		speed = ide_find_best_pio_mode(drive);
 
 	via_set_drive(drive, speed);
 
@@ -248,16 +237,14 @@
 static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
 {
 	struct via_isa_bridge *via_config;
-	u8 t;
 
 	for (via_config = via_isa_bridges; via_config->id; via_config++)
 		if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA +
 			!!(via_config->flags & VIA_BAD_ID),
 			via_config->id, NULL))) {
 
-			pci_read_config_byte(*isa, PCI_REVISION_ID, &t);
-			if (t >= via_config->rev_min &&
-			    t <= via_config->rev_max)
+			if ((*isa)->revision >= via_config->rev_min &&
+			    (*isa)->revision <= via_config->rev_max)
 				break;
 			pci_dev_put(*isa);
 		}
@@ -272,8 +259,8 @@
 {
 	int i;
 
-	switch (vdev->via_config->flags & VIA_UDMA) {
-		case VIA_UDMA_66:
+	switch (vdev->via_config->udma_mask) {
+		case ATA_UDMA4:
 			for (i = 24; i >= 0; i -= 8)
 				if (((u >> (i & 16)) & 8) &&
 				    ((u >> i) & 0x20) &&
@@ -286,7 +273,7 @@
 				}
 			break;
 
-		case VIA_UDMA_100:
+		case ATA_UDMA5:
 			for (i = 24; i >= 0; i -= 8)
 				if (((u >> i) & 0x10) ||
 				    (((u >> i) & 0x20) &&
@@ -298,7 +285,7 @@
 				}
 			break;
 
-		case VIA_UDMA_133:
+		case ATA_UDMA6:
 			for (i = 24; i >= 0; i -= 8)
 				if (((u >> i) & 0x10) ||
 				    (((u >> i) & 0x20) &&
@@ -353,7 +340,7 @@
 
 	via_cable_detect(vdev, u);
 
-	if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) {
+	if (via_config->udma_mask == ATA_UDMA4) {
 		/* Enable Clk66 */
 		pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
 	} else if (via_config->flags & VIA_BAD_CLK66) {
@@ -415,17 +402,54 @@
 	 * Print the boot message.
 	 */
 
-	pci_read_config_byte(isa, PCI_REVISION_ID, &t);
-	printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s "
+	printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
 		"controller on pci%s\n",
-		via_config->name, t,
-		via_dma[via_config->flags & VIA_UDMA],
+		via_config->name, isa->revision,
+		via_config->udma_mask ? "U" : "MW",
+		via_dma[via_config->udma_mask ?
+			(fls(via_config->udma_mask) - 1) : 0],
 		pci_name(dev));
 
 	pci_dev_put(isa);
 	return 0;
 }
 
+/*
+ *	Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+	{
+		.ident = "Acer Ferrari 3400",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),
+			DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),
+		},
+	},
+	{ }
+};
+
+static int via_cable_override(void)
+{
+	/* Systems by DMI */
+	if (dmi_check_system(cable_dmi_table))
+		return 1;
+	return 0;
+}
+
+static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
+{
+	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
+
+	if (via_cable_override())
+		return ATA_CBL_PATA40_SHORT;
+
+	if ((vdev->via_80w >> hwif->channel) & 1)
+		return ATA_CBL_PATA80;
+	else
+		return ATA_CBL_PATA40;
+}
+
 static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
 {
 	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
@@ -454,12 +478,14 @@
 		return;
 
 	hwif->atapi_dma = 1;
-	hwif->ultra_mask = 0x7f;
+
+	hwif->ultra_mask = vdev->via_config->udma_mask;
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-	if (!hwif->udma_four)
-		hwif->udma_four = (vdev->via_80w >> hwif->channel) & 1;
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = via82cxxx_cable_detect(hwif);
+
 	hwif->ide_dma_check = &via82cxxx_ide_dma_check;
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 45fc36f..e46f4720 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -942,8 +942,8 @@
 				return 1;
 		case XFER_UDMA_4:
 		case XFER_UDMA_3:
-			if (HWIF(drive)->udma_four == 0)
-				return 1;		
+			if (drive->hwif->cbl != ATA_CBL_PATA80)
+				return 1;
 		case XFER_UDMA_2:
 		case XFER_UDMA_1:
 		case XFER_UDMA_0:
@@ -1244,7 +1244,7 @@
 	hwif->chipset = ide_pmac;
 	hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
 	hwif->hold = pmif->mediabay;
-	hwif->udma_four = pmif->cable_80;
+	hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 	hwif->drives[0].unmask = 1;
 	hwif->drives[1].unmask = 1;
 	hwif->tuneproc = pmac_ide_tuneproc;
@@ -1821,28 +1821,11 @@
 		enable = 0;
 
 	if (enable) {
-		short mode;
-		
-		map = XFER_MWDMA;
-		if (pmif->kind == controller_kl_ata4
-		    || pmif->kind == controller_un_ata6
-		    || pmif->kind == controller_k2_ata6
-		    || pmif->kind == controller_sh_ata6) {
-			map |= XFER_UDMA;
-			if (pmif->cable_80) {
-				map |= XFER_UDMA_66;
-				if (pmif->kind == controller_un_ata6 ||
-				    pmif->kind == controller_k2_ata6 ||
-				    pmif->kind == controller_sh_ata6)
-					map |= XFER_UDMA_100;
-				if (pmif->kind == controller_sh_ata6)
-					map |= XFER_UDMA_133;
-			}
-		}
-		mode = ide_find_best_mode(drive, map);
-		if (mode & XFER_UDMA)
+		u8 mode = ide_max_dma_mode(drive);
+
+		if (mode >= XFER_UDMA_0)
 			drive->using_dma = pmac_ide_udma_enable(drive, mode);
-		else if (mode & XFER_MWDMA)
+		else if (mode >= XFER_MW_DMA_0)
 			drive->using_dma = pmac_ide_mdma_enable(drive, mode);
 		hwif->OUTB(0, IDE_CONTROL_REG);
 		/* Apply settings to controller */
@@ -2004,20 +1987,19 @@
 {
 }
 
-static int
-pmac_ide_dma_lostirq (ide_drive_t *drive)
+static void
+pmac_ide_dma_lost_irq (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
 	volatile struct dbdma_regs __iomem *dma;
 	unsigned long status;
 
 	if (pmif == NULL)
-		return 0;
+		return;
 	dma = pmif->dma_regs;
 
 	status = readl(&dma->status);
 	printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
-	return 0;
 }
 
 /*
@@ -2057,8 +2039,8 @@
 	hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
 	hwif->dma_host_off = &pmac_ide_dma_host_off;
 	hwif->dma_host_on = &pmac_ide_dma_host_on;
-	hwif->ide_dma_timeout = &__ide_dma_timeout;
-	hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
+	hwif->dma_timeout = &ide_dma_timeout;
+	hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
 
 	hwif->atapi_dma = 1;
 	switch(pmif->kind) {
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 67035ba..c88d332 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -872,11 +872,15 @@
 	 *	are post init.
 	 */
 
-	list_for_each_safe(l, n, &ide_pci_drivers)
-	{
+	list_for_each_safe(l, n, &ide_pci_drivers) {
 		list_del(l);
 		d = list_entry(l, struct pci_driver, node);
-		__pci_register_driver(d, d->driver.owner, d->driver.mod_name);
+		if (__pci_register_driver(d, d->driver.owner,
+					d->driver.mod_name)) {
+			printk(KERN_ERR "%s: failed to register driver "
+					"for %s\n", __FUNCTION__,
+					 d->driver.mod_name);
+		}
 	}
 }
 #endif
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 2081413..6572211 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2280,7 +2280,7 @@
 	} while (video);
 
 	if (found_ohci_card)
-		class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+		device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
 			   IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
 }
 
@@ -2295,9 +2295,9 @@
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	class_device_create(hpsb_protocol_class, NULL, MKDEV(
-		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), 
-		NULL, "dv1394-%d", id);
+	device_create(hpsb_protocol_class, NULL, MKDEV(
+		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+		"dv1394-%d", id);
 
 	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
 	dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 2296d43..93362ee 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -47,6 +47,7 @@
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/workqueue.h>
 
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
@@ -235,6 +236,9 @@
 /* This is called after an "ifdown" */
 static int ether1394_stop(struct net_device *dev)
 {
+	/* flush priv->wake */
+	flush_scheduled_work();
+
 	netif_stop_queue(dev);
 	return 0;
 }
@@ -531,6 +535,37 @@
 }
 
 /*
+ * Wake the queue up after commonly encountered transmit failure conditions are
+ * hopefully over.  Currently only tlabel exhaustion is accounted for.
+ */
+static void ether1394_wake_queue(struct work_struct *work)
+{
+	struct eth1394_priv *priv;
+	struct hpsb_packet *packet;
+
+	priv = container_of(work, struct eth1394_priv, wake);
+	packet = hpsb_alloc_packet(0);
+
+	/* This is really bad, but unjam the queue anyway. */
+	if (!packet)
+		goto out;
+
+	packet->host = priv->host;
+	packet->node_id = priv->wake_node;
+	/*
+	 * A transaction label is all we really want.  If we get one, it almost
+	 * always means we can get a lot more because the ieee1394 core recycled
+	 * a whole batch of tlabels, at last.
+	 */
+	if (hpsb_get_tlabel(packet) == 0)
+		hpsb_free_tlabel(packet);
+
+	hpsb_free_packet(packet);
+out:
+	netif_wake_queue(priv->wake_dev);
+}
+
+/*
  * This function is called every time a card is found. It is generally called
  * when the module is installed. This is where we add all of our ethernet
  * devices. One for each host.
@@ -564,16 +599,15 @@
 	}
 
 	SET_MODULE_OWNER(dev);
-#if 0
-	/* FIXME - Is this the correct parent device anyway? */
 	SET_NETDEV_DEV(dev, &host->device);
-#endif
 
 	priv = netdev_priv(dev);
 	INIT_LIST_HEAD(&priv->ip_node_list);
 	spin_lock_init(&priv->lock);
 	priv->host = host;
 	priv->local_fifo = fifo_addr;
+	INIT_WORK(&priv->wake, ether1394_wake_queue);
+	priv->wake_dev = dev;
 
 	hi = hpsb_create_hostinfo(&eth1394_highlevel, host, sizeof(*hi));
 	if (hi == NULL) {
@@ -1390,22 +1424,17 @@
 				       u64 addr, void *data, int tx_len)
 {
 	p->node_id = node;
-	p->data = NULL;
+
+	if (hpsb_get_tlabel(p))
+		return -EAGAIN;
 
 	p->tcode = TCODE_WRITEB;
-	p->header[1] = host->node_id << 16 | addr >> 32;
-	p->header[2] = addr & 0xffffffff;
-
 	p->header_size = 16;
 	p->expect_response = 1;
-
-	if (hpsb_get_tlabel(p)) {
-		ETH1394_PRINT_G(KERN_ERR, "Out of tlabels\n");
-		return -1;
-	}
 	p->header[0] =
 		p->node_id << 16 | p->tlabel << 10 | 1 << 8 | TCODE_WRITEB << 4;
-
+	p->header[1] = host->node_id << 16 | addr >> 32;
+	p->header[2] = addr & 0xffffffff;
 	p->header[3] = tx_len << 16;
 	p->data_size = (tx_len + 3) & ~3;
 	p->data = data;
@@ -1451,7 +1480,7 @@
 
 	packet = ether1394_alloc_common_packet(priv->host);
 	if (!packet)
-		return -1;
+		return -ENOMEM;
 
 	if (ptask->tx_type == ETH1394_GASP) {
 		int length = tx_len + 2 * sizeof(quadlet_t);
@@ -1462,7 +1491,7 @@
 					       ptask->addr, ptask->skb->data,
 					       tx_len)) {
 		hpsb_free_packet(packet);
-		return -1;
+		return -EAGAIN;
 	}
 
 	ptask->packet = packet;
@@ -1471,7 +1500,7 @@
 
 	if (hpsb_send_packet(packet) < 0) {
 		ether1394_free_packet(packet);
-		return -1;
+		return -EIO;
 	}
 
 	return 0;
@@ -1514,13 +1543,18 @@
 
 	ptask->outstanding_pkts--;
 	if (ptask->outstanding_pkts > 0 && !fail) {
-		int tx_len;
+		int tx_len, err;
 
 		/* Add the encapsulation header to the fragment */
 		tx_len = ether1394_encapsulate(ptask->skb, ptask->max_payload,
 					       &ptask->hdr);
-		if (ether1394_send_packet(ptask, tx_len))
+		err = ether1394_send_packet(ptask, tx_len);
+		if (err) {
+			if (err == -EAGAIN)
+				ETH1394_PRINT_G(KERN_ERR, "Out of tlabels\n");
+
 			ether1394_dg_complete(ptask, 1);
+		}
 	} else {
 		ether1394_dg_complete(ptask, fail);
 	}
@@ -1529,7 +1563,7 @@
 /* Transmit a packet (called by kernel) */
 static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct eth1394hdr *eth;
+	struct eth1394hdr hdr_buf;
 	struct eth1394_priv *priv = netdev_priv(dev);
 	__be16 proto;
 	unsigned long flags;
@@ -1559,16 +1593,17 @@
 	if (!skb)
 		goto fail;
 
-	/* Get rid of the fake eth1394 header, but save a pointer */
-	eth = (struct eth1394hdr *)skb->data;
+	/* Get rid of the fake eth1394 header, but first make a copy.
+	 * We might need to rebuild the header on tx failure. */
+	memcpy(&hdr_buf, skb->data, sizeof(hdr_buf));
 	skb_pull(skb, ETH1394_HLEN);
 
-	proto = eth->h_proto;
+	proto = hdr_buf.h_proto;
 	dg_size = skb->len;
 
 	/* Set the transmission type for the packet.  ARP packets and IP
 	 * broadcast packets are sent via GASP. */
-	if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
+	if (memcmp(hdr_buf.h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
 	    proto == htons(ETH_P_ARP) ||
 	    (proto == htons(ETH_P_IP) &&
 	     IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
@@ -1580,7 +1615,7 @@
 		if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
 			priv->bc_dgl++;
 	} else {
-		__be64 guid = get_unaligned((u64 *)eth->h_dest);
+		__be64 guid = get_unaligned((u64 *)hdr_buf.h_dest);
 
 		node = eth1394_find_node_guid(&priv->ip_node_list,
 					      be64_to_cpu(guid));
@@ -1633,10 +1668,26 @@
 	/* Add the encapsulation header to the fragment */
 	tx_len = ether1394_encapsulate(skb, max_payload, &ptask->hdr);
 	dev->trans_start = jiffies;
-	if (ether1394_send_packet(ptask, tx_len))
-		goto fail;
+	if (ether1394_send_packet(ptask, tx_len)) {
+		if (dest_node == (LOCAL_BUS | ALL_NODES))
+			goto fail;
 
-	netif_wake_queue(dev);
+		/* At this point we want to restore the packet.  When we return
+		 * here with NETDEV_TX_BUSY we will get another entrance in this
+		 * routine with the same skb and we need it to look the same.
+		 * So we pull 4 more bytes, then build the header again. */
+		skb_pull(skb, 4);
+		ether1394_header(skb, dev, ntohs(hdr_buf.h_proto),
+				 hdr_buf.h_dest, NULL, 0);
+
+		/* Most failures of ether1394_send_packet are recoverable. */
+		netif_stop_queue(dev);
+		priv->wake_node = dest_node;
+		schedule_work(&priv->wake);
+		kmem_cache_free(packet_task_cache, ptask);
+		return NETDEV_TX_BUSY;
+	}
+
 	return NETDEV_TX_OK;
 fail:
 	if (ptask)
@@ -1650,9 +1701,6 @@
 	priv->stats.tx_errors++;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	if (netif_queue_stopped(dev))
-		netif_wake_queue(dev);
-
 	/*
 	 * FIXME: According to a patch from 2003-02-26, "returning non-zero
 	 * causes serious problems" here, allegedly.  Before that patch,
diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
index a3439ee..4f3e2dd 100644
--- a/drivers/ieee1394/eth1394.h
+++ b/drivers/ieee1394/eth1394.h
@@ -66,6 +66,10 @@
 	int bc_dgl;			/* Outgoing broadcast datagram label */
 	struct list_head ip_node_list;	/* List of IP capable nodes	 */
 	struct unit_directory *ud_list[ALL_NODES]; /* Cached unit dir list */
+
+	struct work_struct wake;	/* Wake up after xmit failure	 */
+	struct net_device *wake_dev;	/* Stupid backlink for .wake	 */
+	nodeid_t wake_node;		/* Destination of failed xmit	 */
 };
 
 
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 83a49331..b642546 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -483,37 +483,6 @@
 	return retval;
 }
 
-/**
- * hpsb_listen_channel - enable receving a certain isochronous channel
- *
- * Reception is handled through the @hl's iso_receive op.
- */
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			unsigned int channel)
-{
-	if (channel > 63) {
-		HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-		return -EINVAL;
-	}
-	if (host->iso_listen_count[channel]++ == 0)
-		return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
-	return 0;
-}
-
-/**
- * hpsb_unlisten_channel - disable receving a certain isochronous channel
- */
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			   unsigned int channel)
-{
-	if (channel > 63) {
-		HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-		return;
-	}
-	if (--host->iso_listen_count[channel] == 0)
-		host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
-}
-
 static void init_hpsb_highlevel(struct hpsb_host *host)
 {
 	INIT_LIST_HEAD(&dummy_zero_addr.host_list);
@@ -570,20 +539,6 @@
 	read_unlock_irqrestore(&hl_irqs_lock, flags);
 }
 
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
-{
-	unsigned long flags;
-	struct hpsb_highlevel *hl;
-	int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
-
-	read_lock_irqsave(&hl_irqs_lock, flags);
-	list_for_each_entry(hl, &hl_irqs, irq_list) {
-		if (hl->iso_receive)
-			hl->iso_receive(host, channel, data, length);
-	}
-	read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
 void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			   void *data, size_t length)
 {
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
index 63474f7..eb9fe32 100644
--- a/drivers/ieee1394/highlevel.h
+++ b/drivers/ieee1394/highlevel.h
@@ -26,9 +26,7 @@
 struct hpsb_highlevel {
 	const char *name;
 
-	/* Any of the following pointers can legally be NULL, except for
-	 * iso_receive which can only be NULL when you don't request
-	 * channels. */
+	/* Any of the following pointers can legally be NULL. */
 
 	/* New host initialized.  Will also be called during
 	 * hpsb_register_highlevel for all hosts already installed. */
@@ -43,13 +41,6 @@
 	 * You can not expect to be able to do stock hpsb_reads. */
 	void (*host_reset)(struct hpsb_host *host);
 
-	/* An isochronous packet was received.  Channel contains the channel
-	 * number for your convenience, it is also contained in the included
-	 * packet header (first quadlet, CRCs are missing).  You may get called
-	 * for channel/host combinations you did not request. */
-	void (*iso_receive)(struct hpsb_host *host, int channel,
-			    quadlet_t *data, size_t length);
-
 	/* A write request was received on either the FCP_COMMAND (direction =
 	 * 0) or the FCP_RESPONSE (direction = 1) register.  The cts arg
 	 * contains the cts field (first byte of data). */
@@ -109,7 +100,6 @@
 int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
 		     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
 		     u16 flags);
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
 void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			   void *data, size_t length);
 
@@ -125,10 +115,6 @@
 			    struct hpsb_address_ops *ops, u64 start, u64 end);
 int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
 			      u64 start);
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			unsigned int channel);
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			   unsigned int channel);
 
 void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
 void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index bd0755c..8dd09d8 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -154,15 +154,16 @@
 
 	memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
 	h->device.parent = dev;
+	set_dev_node(&h->device, dev_to_node(dev));
 	snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
 
-	h->class_dev.dev = &h->device;
-	h->class_dev.class = &hpsb_host_class;
-	snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
+	h->host_dev.parent = &h->device;
+	h->host_dev.class = &hpsb_host_class;
+	snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
 
 	if (device_register(&h->device))
 		goto fail;
-	if (class_device_register(&h->class_dev)) {
+	if (device_register(&h->host_dev)) {
 		device_unregister(&h->device);
 		goto fail;
 	}
@@ -202,7 +203,7 @@
 	host->driver = &dummy_driver;
 	highlevel_remove_host(host);
 
-	class_device_unregister(&host->class_dev);
+	device_unregister(&host->host_dev);
 	device_unregister(&host->device);
 }
 
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index feb55d0..e4e8aeb 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -28,8 +28,6 @@
 	struct timer_list timeout;
 	unsigned long timeout_interval;
 
-	unsigned char iso_listen_count[64];
-
 	int node_count;      /* number of identified nodes on this bus */
 	int selfid_count;    /* total number of SelfIDs received */
 	int nodes_active;    /* number of nodes with active link layer */
@@ -57,7 +55,7 @@
 	struct hpsb_host_driver *driver;
 	struct pci_dev *pdev;
 	struct device device;
-	struct class_device class_dev;
+	struct device host_dev;
 
 	struct delayed_work delayed_reset;
 	unsigned config_roms:31;
@@ -99,12 +97,6 @@
 	/* Cancel all outstanding async requests without resetting the bus.
 	 * Return void. */
 	CANCEL_REQUESTS,
-
-	/* Start or stop receiving isochronous channel in arg.  Return void.
-	 * This acts as an optimization hint, hosts are not required not to
-	 * listen on unrequested channels. */
-	ISO_LISTEN_CHANNEL,
-	ISO_UNLISTEN_CHANNEL
 };
 
 enum isoctl_cmd {
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 8f71b6a..ee452595 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -30,6 +30,7 @@
 #include <linux/moduleparam.h>
 #include <linux/bitops.h>
 #include <linux/kdev_t.h>
+#include <linux/freezer.h>
 #include <linux/suspend.h>
 #include <linux/kthread.h>
 #include <linux/preempt.h>
@@ -1028,11 +1029,6 @@
 		handle_incoming_packet(host, tcode, data, size, write_acked);
 		break;
 
-
-	case TCODE_ISO_DATA:
-		highlevel_iso_receive(host, data, size);
-		break;
-
 	case TCODE_CYCLE_START:
 		/* simply ignore this packet if it is passed on */
 		break;
@@ -1133,8 +1129,6 @@
 	struct list_head tmp;
 	int may_schedule;
 
-	current->flags |= PF_NOFREEZE;
-
 	while (!kthread_should_stop()) {
 
 		INIT_LIST_HEAD(&tmp);
@@ -1316,7 +1310,6 @@
 EXPORT_SYMBOL(hpsb_make_lockpacket);
 EXPORT_SYMBOL(hpsb_make_lock64packet);
 EXPORT_SYMBOL(hpsb_make_phypacket);
-EXPORT_SYMBOL(hpsb_make_isopacket);
 EXPORT_SYMBOL(hpsb_read);
 EXPORT_SYMBOL(hpsb_write);
 EXPORT_SYMBOL(hpsb_packet_success);
@@ -1327,8 +1320,6 @@
 EXPORT_SYMBOL(hpsb_register_addrspace);
 EXPORT_SYMBOL(hpsb_unregister_addrspace);
 EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
-EXPORT_SYMBOL(hpsb_listen_channel);
-EXPORT_SYMBOL(hpsb_unlisten_channel);
 EXPORT_SYMBOL(hpsb_get_hostinfo);
 EXPORT_SYMBOL(hpsb_create_hostinfo);
 EXPORT_SYMBOL(hpsb_destroy_hostinfo);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index ad52652..21d50f7 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -24,9 +24,8 @@
 
 	nodeid_t node_id;
 
-	/* Async and Iso types should be clear, raw means send-as-is, do not
-	 * CRC!  Byte swapping shall still be done in this case. */
-	enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+	/* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
+	enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
 
 	/* Okay, this is core internal and a no care for hosts.
 	 * queued   = queued for sending
@@ -37,7 +36,7 @@
 		hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
 	} __attribute__((packed)) state;
 
-	/* These are core internal. */
+	/* These are core-internal. */
 	signed char tlabel;
 	signed char ack_code;
 	unsigned char tcode;
@@ -62,11 +61,15 @@
 	/* Store jiffies for implementing bus timeouts. */
 	unsigned long sendtime;
 
-	/* Sizes are in bytes. *data can be DMA-mapped. */
+	/* Core-internal.  */
 	size_t allocated_data_size;	/* as allocated */
+
+	/* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
 	size_t data_size;		/* as filled in */
 	size_t header_size;		/* as filled in, not counting the CRC */
-	quadlet_t *data;
+
+	/* Buffers */
+	quadlet_t *data;		/* can be DMA-mapped */
 	quadlet_t header[5];
 	quadlet_t embedded_data[0];	/* keep as last member */
 };
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 40078ce..c39c70a 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -89,18 +89,6 @@
 	packet->expect_response = 1;
 }
 
-static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
-			    int tag, int sync)
-{
-	packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
-	    | (TCODE_ISO_DATA << 4) | sync;
-
-	packet->header_size = 4;
-	packet->data_size = length;
-	packet->type = hpsb_iso;
-	packet->tcode = TCODE_ISO_DATA;
-}
-
 static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
 {
 	packet->header[0] = data;
@@ -491,24 +479,6 @@
 	return p;
 }
 
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
-					int length, int channel,
-					int tag, int sync)
-{
-	struct hpsb_packet *p;
-
-	p = hpsb_alloc_packet(length);
-	if (!p)
-		return NULL;
-
-	p->host = host;
-	fill_iso_packet(p, length, channel, tag, sync);
-
-	p->generation = get_hpsb_generation(host);
-
-	return p;
-}
-
 /*
  * FIXME - these functions should probably read from / write to user space to
  * avoid in kernel buffers for user space callers
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 86b8ee6..d2d5bc3 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -19,8 +19,6 @@
 					   nodeid_t node, u64 addr, int extcode,
 					   octlet_t *data, octlet_t arg);
 struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length,
-					int channel, int tag, int sync);
 struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
 					  nodeid_t node, u64 addr,
 					  quadlet_t *buffer, size_t length);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 835937e..2ffd534 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/freezer.h>
 #include <asm/atomic.h>
+#include <asm/semaphore.h>
 
 #include "csr.h"
 #include "highlevel.h"
@@ -145,8 +146,6 @@
  * but now we are much simpler because of the LDM.
  */
 
-static DEFINE_MUTEX(nodemgr_serialize);
-
 struct host_info {
 	struct hpsb_host *host;
 	struct list_head list;
@@ -154,7 +153,7 @@
 };
 
 static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size);
 static void nodemgr_resume_ne(struct node_entry *ne);
 static void nodemgr_remove_ne(struct node_entry *ne);
@@ -165,37 +164,38 @@
 	.match		= nodemgr_bus_match,
 };
 
-static void host_cls_release(struct class_device *class_dev)
+static void host_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device);
+	put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
 }
 
 struct class hpsb_host_class = {
 	.name		= "ieee1394_host",
-	.release	= host_cls_release,
+	.dev_release	= host_cls_release,
 };
 
-static void ne_cls_release(struct class_device *class_dev)
+static void ne_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
+	put_device(&container_of((dev), struct node_entry, node_dev)->device);
 }
 
 static struct class nodemgr_ne_class = {
 	.name		= "ieee1394_node",
-	.release	= ne_cls_release,
+	.dev_release	= ne_cls_release,
 };
 
-static void ud_cls_release(struct class_device *class_dev)
+static void ud_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct unit_directory, class_dev)->device);
+	put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
 }
 
 /* The name here is only so that unit directory hotplug works with old
- * style hotplug, which only ever did unit directories anyway. */
+ * style hotplug, which only ever did unit directories anyway.
+ */
 static struct class nodemgr_ud_class = {
 	.name		= "ieee1394",
-	.release	= ud_cls_release,
-	.uevent		= nodemgr_uevent,
+	.dev_release	= ud_cls_release,
+	.dev_uevent	= nodemgr_uevent,
 };
 
 static struct hpsb_highlevel nodemgr_highlevel;
@@ -283,7 +283,7 @@
 	memcpy(buf,							\
 	       CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(class->td_kv),	\
 	       len);							\
-	while ((buf + len - 1) == '\0')					\
+	while (buf[len - 1] == '\0')					\
 		len--;							\
 	buf[len++] = '\n';						\
 	buf[len] = '\0';						\
@@ -730,11 +730,11 @@
 
 static void nodemgr_remove_uds(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *tmp, *ud;
 
-	/* Iteration over nodemgr_ud_class.children has to be protected by
-	 * nodemgr_ud_class.sem, but class_device_unregister() will eventually
+	/* Iteration over nodemgr_ud_class.devices has to be protected by
+	 * nodemgr_ud_class.sem, but device_unregister() will eventually
 	 * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
 	 * release the semaphore, and then unregister the ud. Since this code
 	 * may be called from other contexts besides the knodemgrds, protect the
@@ -744,9 +744,9 @@
 	for (;;) {
 		ud = NULL;
 		down(&nodemgr_ud_class.sem);
-		list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-			tmp = container_of(cdev, struct unit_directory,
-					   class_dev);
+		list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+			tmp = container_of(dev, struct unit_directory,
+					   unit_dev);
 			if (tmp->ne == ne) {
 				ud = tmp;
 				break;
@@ -755,7 +755,7 @@
 		up(&nodemgr_ud_class.sem);
 		if (ud == NULL)
 			break;
-		class_device_unregister(&ud->class_dev);
+		device_unregister(&ud->unit_dev);
 		device_unregister(&ud->device);
 	}
 	mutex_unlock(&nodemgr_serialize_remove_uds);
@@ -772,10 +772,9 @@
 
 	HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-
 	nodemgr_remove_uds(ne);
 
-	class_device_unregister(&ne->class_dev);
+	device_unregister(&ne->node_dev);
 	device_unregister(dev);
 
 	put_device(dev);
@@ -783,7 +782,9 @@
 
 static int __nodemgr_remove_host_dev(struct device *dev, void *data)
 {
-	nodemgr_remove_ne(container_of(dev, struct node_entry, device));
+	if (dev->bus == &ieee1394_bus_type)
+		nodemgr_remove_ne(container_of(dev, struct node_entry,
+				  device));
 	return 0;
 }
 
@@ -850,14 +851,14 @@
 	snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
 		 (unsigned long long)(ne->guid));
 
-	ne->class_dev.dev = &ne->device;
-	ne->class_dev.class = &nodemgr_ne_class;
-	snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
-		 (unsigned long long)(ne->guid));
+	ne->node_dev.parent = &ne->device;
+	ne->node_dev.class = &nodemgr_ne_class;
+	snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
+		(unsigned long long)(ne->guid));
 
 	if (device_register(&ne->device))
 		goto fail_devreg;
-	if (class_device_register(&ne->class_dev))
+	if (device_register(&ne->node_dev))
 		goto fail_classdevreg;
 	get_device(&ne->device);
 
@@ -885,12 +886,12 @@
 
 static struct node_entry *find_entry_by_guid(u64 guid)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne, *ret_ne = NULL;
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 
 		if (ne->guid == guid) {
 			ret_ne = ne;
@@ -906,12 +907,12 @@
 static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
 					       nodeid_t nodeid)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne, *ret_ne = NULL;
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 
 		if (ne->host == host && ne->nodeid == nodeid) {
 			ret_ne = ne;
@@ -935,14 +936,14 @@
 	snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
 		 ne->device.bus_id, ud->id);
 
-	ud->class_dev.dev = &ud->device;
-	ud->class_dev.class = &nodemgr_ud_class;
-	snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
+	ud->unit_dev.parent = &ud->device;
+	ud->unit_dev.class = &nodemgr_ud_class;
+	snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
 		 ne->device.bus_id, ud->id);
 
 	if (device_register(&ud->device))
 		goto fail_devreg;
-	if (class_device_register(&ud->class_dev))
+	if (device_register(&ud->unit_dev))
 		goto fail_classdevreg;
 	get_device(&ud->device);
 
@@ -976,7 +977,8 @@
 
 	ud->ne = ne;
 	ud->ignore_driver = ignore_drivers;
-	ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE;
+	ud->address = ud_kv->offset + CSR1212_REGISTER_SPACE_BASE;
+	ud->directory_id = ud->address & 0xffffff;
 	ud->ud_kv = ud_kv;
 	ud->id = (*id)++;
 
@@ -1085,6 +1087,10 @@
 
 			break;
 
+		case CSR1212_KV_ID_DIRECTORY_ID:
+			ud->directory_id = kv->value.immediate;
+			break;
+
 		default:
 			break;
 		}
@@ -1154,7 +1160,7 @@
 
 #ifdef CONFIG_HOTPLUG
 
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size)
 {
 	struct unit_directory *ud;
@@ -1164,10 +1170,10 @@
 	/* ieee1394:venNmoNspNverN */
 	char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
 
-	if (!cdev)
+	if (!dev)
 		return -ENODEV;
 
-	ud = container_of(cdev, struct unit_directory, class_dev);
+	ud = container_of(dev, struct unit_directory, unit_dev);
 
 	if (ud->ne->in_limbo || ud->ignore_driver)
 		return -ENODEV;
@@ -1202,7 +1208,7 @@
 
 #else
 
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size)
 {
 	return -ENODEV;
@@ -1373,8 +1379,10 @@
 
 static void nodemgr_suspend_ne(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
+	int error;
 
 	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
@@ -1383,15 +1391,24 @@
 	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver &&
-		    (!ud->device.driver->suspend ||
-		      ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		error = 1; /* release if suspend is not implemented */
+		if (drv->suspend) {
+			down(&ud->device.sem);
+			error = drv->suspend(&ud->device, PMSG_SUSPEND);
+			up(&ud->device.sem);
+		}
+		if (error)
 			device_release_driver(&ud->device);
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 }
@@ -1399,20 +1416,29 @@
 
 static void nodemgr_resume_ne(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
 
 	ne->in_limbo = 0;
 	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver && ud->device.driver->resume)
-			ud->device.driver->resume(&ud->device);
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		if (drv->resume) {
+			down(&ud->device.sem);
+			drv->resume(&ud->device);
+			up(&ud->device.sem);
+		}
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 
@@ -1423,23 +1449,32 @@
 
 static void nodemgr_update_pdrv(struct node_entry *ne)
 {
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
 	struct hpsb_protocol_driver *pdrv;
-	struct class_device *cdev;
+	int error;
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver) {
-			pdrv = container_of(ud->device.driver,
-					    struct hpsb_protocol_driver,
-					    driver);
-			if (pdrv->update && pdrv->update(ud))
-				device_release_driver(&ud->device);
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		error = 0;
+		pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
+		if (pdrv->update) {
+			down(&ud->device.sem);
+			error = pdrv->update(ud);
+			up(&ud->device.sem);
 		}
+		if (error)
+			device_release_driver(&ud->device);
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 }
@@ -1504,7 +1539,7 @@
 static void nodemgr_node_probe(struct host_info *hi, int generation)
 {
 	struct hpsb_host *host = hi->host;
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne;
 
 	/* Do some processing of the nodes we've probed. This pulls them
@@ -1517,13 +1552,13 @@
 	 * improvement...) */
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 		if (!ne->needs_probe)
 			nodemgr_probe_ne(hi, ne, generation);
 	}
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 		if (ne->needs_probe)
 			nodemgr_probe_ne(hi, ne, generation);
 	}
@@ -1664,6 +1699,7 @@
 	unsigned int g, generation = 0;
 	int i, reset_cycles = 0;
 
+	set_freezable();
 	/* Setup our device-model entries */
 	nodemgr_create_host_dev_files(host);
 
@@ -1681,18 +1717,12 @@
 		if (kthread_should_stop())
 			goto exit;
 
-		if (mutex_lock_interruptible(&nodemgr_serialize)) {
-			if (try_to_freeze())
-				continue;
-			goto exit;
-		}
-
 		/* Pause for 1/4 second in 1/16 second intervals,
 		 * to make sure things settle down. */
 		g = get_hpsb_generation(host);
 		for (i = 0; i < 4 ; i++) {
 			if (msleep_interruptible(63) || kthread_should_stop())
-				goto unlock_exit;
+				goto exit;
 
 			/* Now get the generation in which the node ID's we collect
 			 * are valid.  During the bus scan we will use this generation
@@ -1710,7 +1740,6 @@
 		if (!nodemgr_check_irm_capability(host, reset_cycles) ||
 		    !nodemgr_do_irm_duties(host, reset_cycles)) {
 			reset_cycles++;
-			mutex_unlock(&nodemgr_serialize);
 			continue;
 		}
 		reset_cycles = 0;
@@ -1727,11 +1756,7 @@
 
 		/* Update some of our sysfs symlinks */
 		nodemgr_update_host_dev_links(host);
-
-		mutex_unlock(&nodemgr_serialize);
 	}
-unlock_exit:
-	mutex_unlock(&nodemgr_serialize);
 exit:
 	HPSB_VERBOSE("NodeMgr: Exiting thread");
 	return 0;
@@ -1751,13 +1776,13 @@
  */
 int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct hpsb_host *host;
 	int error = 0;
 
 	down(&hpsb_host_class.sem);
-	list_for_each_entry(cdev, &hpsb_host_class.children, node) {
-		host = container_of(cdev, struct hpsb_host, class_dev);
+	list_for_each_entry(dev, &hpsb_host_class.devices, node) {
+		host = container_of(dev, struct hpsb_host, host_dev);
 
 		if ((error = cb(host, data)))
 			break;
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index e7ac683..919e92e 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -75,6 +75,7 @@
 	struct csr1212_keyval *model_name_kv;
 	quadlet_t specifier_id;
 	quadlet_t version;
+	quadlet_t directory_id;
 
 	unsigned int id;
 
@@ -83,7 +84,7 @@
 	int length;		/* Number of quadlets */
 
 	struct device device;
-	struct class_device class_dev;
+	struct device unit_dev;
 
 	struct csr1212_keyval *ud_kv;
 	u32 lun;		/* logical unit number immediate value */
@@ -106,7 +107,7 @@
 	u32 capabilities;
 
 	struct device device;
-	struct class_device class_dev;
+	struct device node_dev;
 
 	/* Means this node is not attached anymore */
 	int in_limbo;
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 5dadfd2..5667c81 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -138,19 +138,6 @@
 #define DBGMSG(fmt, args...) do {} while (0)
 #endif
 
-#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
-#define OHCI_DMA_ALLOC(fmt, args...) \
-	HPSB_ERR("%s(%s)alloc(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
-		++global_outstanding_dmas, ## args)
-#define OHCI_DMA_FREE(fmt, args...) \
-	HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
-		--global_outstanding_dmas, ## args)
-static int global_outstanding_dmas = 0;
-#else
-#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0)
-#define OHCI_DMA_FREE(fmt, args...) do {} while (0)
-#endif
-
 /* print general (card independent) information */
 #define PRINT_G(level, fmt, args...) \
 printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
@@ -170,7 +157,6 @@
 static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
 			     enum context_type type, int ctx, int num_desc,
 			     int buf_size, int split_buf_size, int context_base);
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
 static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
 
 static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
@@ -533,9 +519,6 @@
 	initialize_dma_trm_ctx(&ohci->at_req_context);
 	initialize_dma_trm_ctx(&ohci->at_resp_context);
 	
-	/* Initialize IR Legacy DMA channel mask */
-	ohci->ir_legacy_channels = 0;
-
 	/* Accept AR requests from all nodes */
 	reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
 
@@ -733,7 +716,6 @@
                                 pci_map_single(ohci->dev, packet->data,
                                                packet->data_size,
                                                PCI_DMA_TODEVICE));
-			OHCI_DMA_ALLOC("single, block transmit packet");
 
                         d->prg_cpu[idx]->end.branchAddress = 0;
                         d->prg_cpu[idx]->end.status = 0;
@@ -783,7 +765,6 @@
                 d->prg_cpu[idx]->end.address = cpu_to_le32(
 				pci_map_single(ohci->dev, packet->data,
 				packet->data_size, PCI_DMA_TODEVICE));
-		OHCI_DMA_ALLOC("single, iso transmit packet");
 
                 d->prg_cpu[idx]->end.branchAddress = 0;
                 d->prg_cpu[idx]->end.status = 0;
@@ -884,36 +865,9 @@
 		return -EOVERFLOW;
 	}
 
-	/* Decide whether we have an iso, a request, or a response packet */
 	if (packet->type == hpsb_raw)
 		d = &ohci->at_req_context;
-	else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
-		/* The legacy IT DMA context is initialized on first
-		 * use.  However, the alloc cannot be run from
-		 * interrupt context, so we bail out if that is the
-		 * case. I don't see anyone sending ISO packets from
-		 * interrupt context anyway... */
-
-		if (ohci->it_legacy_context.ohci == NULL) {
-			if (in_interrupt()) {
-				PRINT(KERN_ERR,
-				      "legacy IT context cannot be initialized during interrupt");
-				return -EINVAL;
-			}
-
-			if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
-					      DMA_CTX_ISO, 0, IT_NUM_DESC,
-					      OHCI1394_IsoXmitContextBase) < 0) {
-				PRINT(KERN_ERR,
-				      "error initializing legacy IT context");
-				return -ENOMEM;
-			}
-
-			initialize_dma_trm_ctx(&ohci->it_legacy_context);
-		}
-
-		d = &ohci->it_legacy_context;
-	} else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
+	else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
 		d = &ohci->at_resp_context;
 	else
 		d = &ohci->at_req_context;
@@ -932,9 +886,7 @@
 static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
 {
 	struct ti_ohci *ohci = host->hostdata;
-	int retval = 0;
-	unsigned long flags;
-	int phy_reg;
+	int retval = 0, phy_reg;
 
 	switch (cmd) {
 	case RESET_BUS:
@@ -1027,117 +979,6 @@
 		dma_trm_reset(&ohci->at_resp_context);
 		break;
 
-	case ISO_LISTEN_CHANNEL:
-        {
-		u64 mask;
-		struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
-		int ir_legacy_active;
-
-		if (arg<0 || arg>63) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 listen channel %d is out of range",
-			      __FUNCTION__, arg);
-			return -EFAULT;
-		}
-
-		mask = (u64)0x1<<arg;
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (ohci->ISO_channel_usage & mask) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 listen channel %d is already used",
-			      __FUNCTION__, arg);
-			spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-			return -EFAULT;
-		}
-
-		ir_legacy_active = ohci->ir_legacy_channels;
-
-		ohci->ISO_channel_usage |= mask;
-		ohci->ir_legacy_channels |= mask;
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-
-		if (!ir_legacy_active) {
-			if (ohci1394_register_iso_tasklet(ohci,
-					  &ohci->ir_legacy_tasklet) < 0) {
-				PRINT(KERN_ERR, "No IR DMA context available");
-				return -EBUSY;
-			}
-
-			/* the IR context can be assigned to any DMA context
-			 * by ohci1394_register_iso_tasklet */
-			d->ctx = ohci->ir_legacy_tasklet.context;
-			d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
-				32*d->ctx;
-			d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
-				32*d->ctx;
-			d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
-			d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
-
-			initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
-			if (printk_ratelimit())
-				DBGMSG("IR legacy activated");
-		}
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (arg>31)
-			reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
-				  1<<(arg-32));
-		else
-			reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
-				  1<<arg);
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-                DBGMSG("Listening enabled on channel %d", arg);
-                break;
-        }
-	case ISO_UNLISTEN_CHANNEL:
-        {
-		u64 mask;
-
-		if (arg<0 || arg>63) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 unlisten channel %d is out of range",
-			      __FUNCTION__, arg);
-			return -EFAULT;
-		}
-
-		mask = (u64)0x1<<arg;
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (!(ohci->ISO_channel_usage & mask)) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 unlisten channel %d is not used",
-			      __FUNCTION__, arg);
-			spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-			return -EFAULT;
-		}
-
-		ohci->ISO_channel_usage &= ~mask;
-		ohci->ir_legacy_channels &= ~mask;
-
-		if (arg>31)
-			reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear,
-				  1<<(arg-32));
-		else
-			reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear,
-				  1<<arg);
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-                DBGMSG("Listening disabled on channel %d", arg);
-
-		if (ohci->ir_legacy_channels == 0) {
-			stop_dma_rcv_ctx(&ohci->ir_legacy_context);
-			DBGMSG("ISO legacy receive context stopped");
-		}
-
-                break;
-        }
 	default:
 		PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
 			cmd);
@@ -2869,12 +2710,10 @@
 		list_del_init(&packet->driver_list);
 		hpsb_packet_sent(ohci->host, packet, ack);
 
-		if (datasize) {
+		if (datasize)
 			pci_unmap_single(ohci->dev,
 					 cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
 					 datasize, PCI_DMA_TODEVICE);
-			OHCI_DMA_FREE("single Xmit data packet");
-		}
 
 		d->sent_ind = (d->sent_ind+1)%d->num_desc;
 		d->free_prgs++;
@@ -2885,22 +2724,6 @@
 	spin_unlock_irqrestore(&d->lock, flags);
 }
 
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d)
-{
-	if (d->ctrlClear) {
-		ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
-
-		if (d->type == DMA_CTX_ISO) {
-			/* disable interrupts */
-			reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx);
-			ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet);
-		} else {
-			tasklet_kill(&d->task);
-		}
-	}
-}
-
-
 static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
 {
 	int i;
@@ -2913,23 +2736,19 @@
 
 	if (d->buf_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->buf_cpu[i] && d->buf_bus[i]) {
+			if (d->buf_cpu[i] && d->buf_bus[i])
 				pci_free_consistent(
 					ohci->dev, d->buf_size,
 					d->buf_cpu[i], d->buf_bus[i]);
-				OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i);
-			}
 		kfree(d->buf_cpu);
 		kfree(d->buf_bus);
 	}
 	if (d->prg_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->prg_cpu[i] && d->prg_bus[i]) {
-				pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
-				OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i);
-			}
+			if (d->prg_cpu[i] && d->prg_bus[i])
+				pci_pool_free(d->prg_pool, d->prg_cpu[i],
+					      d->prg_bus[i]);
 		pci_pool_destroy(d->prg_pool);
-		OHCI_DMA_FREE("dma_rcv prg pool");
 		kfree(d->prg_cpu);
 		kfree(d->prg_bus);
 	}
@@ -2998,13 +2817,10 @@
 	}
 	num_allocs++;
 
-	OHCI_DMA_ALLOC("dma_rcv prg pool");
-
 	for (i=0; i<d->num_desc; i++) {
 		d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
 						     d->buf_size,
 						     d->buf_bus+i);
-		OHCI_DMA_ALLOC("consistent dma_rcv buf[%d]", i);
 
 		if (d->buf_cpu[i] != NULL) {
 			memset(d->buf_cpu[i], 0, d->buf_size);
@@ -3016,7 +2832,6 @@
 		}
 
 		d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-		OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
 
                 if (d->prg_cpu[i] != NULL) {
                         memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
@@ -3030,18 +2845,11 @@
 
         spin_lock_init(&d->lock);
 
-	if (type == DMA_CTX_ISO) {
-		ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
-					  OHCI_ISO_MULTICHANNEL_RECEIVE,
-					  dma_rcv_tasklet, (unsigned long) d);
-	} else {
-		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-		d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+	d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+	d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+	d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
 
-		tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d);
-	}
-
+	tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
 	return 0;
 }
 
@@ -3057,12 +2865,10 @@
 
 	if (d->prg_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->prg_cpu[i] && d->prg_bus[i]) {
-				pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
-				OHCI_DMA_FREE("pool dma_trm prg[%d]", i);
-			}
+			if (d->prg_cpu[i] && d->prg_bus[i])
+				pci_pool_free(d->prg_pool, d->prg_cpu[i],
+					      d->prg_bus[i]);
 		pci_pool_destroy(d->prg_pool);
-		OHCI_DMA_FREE("dma_trm prg pool");
 		kfree(d->prg_cpu);
 		kfree(d->prg_bus);
 	}
@@ -3108,11 +2914,8 @@
 	}
 	num_allocs++;
 
-	OHCI_DMA_ALLOC("dma_rcv prg pool");
-
 	for (i = 0; i < d->num_desc; i++) {
 		d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-		OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
 
                 if (d->prg_cpu[i] != NULL) {
                         memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
@@ -3127,28 +2930,10 @@
         spin_lock_init(&d->lock);
 
 	/* initialize tasklet */
-	if (type == DMA_CTX_ISO) {
-		ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT,
-					  dma_trm_tasklet, (unsigned long) d);
-		if (ohci1394_register_iso_tasklet(ohci,
-						  &ohci->it_legacy_tasklet) < 0) {
-			PRINT(KERN_ERR, "No IT DMA context available");
-			free_dma_trm_ctx(d);
-			return -EBUSY;
-		}
-
-		/* IT can be assigned to any context by register_iso_tasklet */
-		d->ctx = ohci->it_legacy_tasklet.context;
-		d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx;
-		d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx;
-		d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx;
-	} else {
-		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-		d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-		tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d);
-	}
-
+	d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+	d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+	d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+	tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
 	return 0;
 }
 
@@ -3294,7 +3079,6 @@
 	ohci->csr_config_rom_cpu =
 		pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
 				     &ohci->csr_config_rom_bus);
-	OHCI_DMA_ALLOC("consistent csr_config_rom");
 	if (ohci->csr_config_rom_cpu == NULL)
 		FAIL(-ENOMEM, "Failed to allocate buffer config rom");
 	ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
@@ -3303,8 +3087,6 @@
 	ohci->selfid_buf_cpu =
 		pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
                       &ohci->selfid_buf_bus);
-	OHCI_DMA_ALLOC("consistent selfid_buf");
-
 	if (ohci->selfid_buf_cpu == NULL)
 		FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
 	ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
@@ -3377,20 +3159,6 @@
 	ohci->ISO_channel_usage = 0;
         spin_lock_init(&ohci->IR_channel_lock);
 
-	/* Allocate the IR DMA context right here so we don't have
-	 * to do it in interrupt path - note that this doesn't
-	 * waste much memory and avoids the jugglery required to
-	 * allocate it in IRQ path. */
-	if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
-			      DMA_CTX_ISO, 0, IR_NUM_DESC,
-			      IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
-			      OHCI1394_IsoRcvContextBase) < 0) {
-		FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
-	}
-
-	/* We hopefully don't have to pre-allocate IT DMA like we did
-	 * for IR DMA above. Allocate it on-demand and mark inactive. */
-	ohci->it_legacy_context.ohci = NULL;
 	spin_lock_init(&ohci->event_lock);
 
 	/*
@@ -3483,20 +3251,16 @@
 		free_dma_rcv_ctx(&ohci->ar_resp_context);
 		free_dma_trm_ctx(&ohci->at_req_context);
 		free_dma_trm_ctx(&ohci->at_resp_context);
-		free_dma_rcv_ctx(&ohci->ir_legacy_context);
-		free_dma_trm_ctx(&ohci->it_legacy_context);
 
 	case OHCI_INIT_HAVE_SELFID_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
 				    ohci->selfid_buf_cpu,
 				    ohci->selfid_buf_bus);
-		OHCI_DMA_FREE("consistent selfid_buf");
 
 	case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
 				    ohci->csr_config_rom_cpu,
 				    ohci->csr_config_rom_bus);
-		OHCI_DMA_FREE("consistent csr_config_rom");
 
 	case OHCI_INIT_HAVE_IOMAPPING:
 		iounmap(ohci->registers);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index f1ad539..4320bf01 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -190,23 +190,10 @@
 	unsigned long ir_multichannel_used; /* ditto */
         spinlock_t IR_channel_lock;
 
-	/* iso receive (legacy API) */
-	u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
-				   it only accounts for channels listened to
-				   by the legacy API, so that we can know when
-				   it is safe to free the legacy API context */
-
-	struct dma_rcv_ctx ir_legacy_context;
-	struct ohci1394_iso_tasklet ir_legacy_tasklet;
-
         /* iso transmit */
 	int nb_iso_xmit_ctx;
 	unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
 
-	/* iso transmit (legacy API) */
-	struct dma_trm_ctx it_legacy_context;
-	struct ohci1394_iso_tasklet it_legacy_tasklet;
-
         u64 ISO_channel_usage;
 
         /* IEEE-1394 part follows */
@@ -221,7 +208,6 @@
 
 	/* Tasklets for iso receive and transmit, used by video1394
 	 * and dv1394 */
-
 	struct list_head iso_tasklet_list;
 	spinlock_t iso_tasklet_list_lock;
 
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 0742bef..d1a5bcd 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -477,7 +477,11 @@
         struct lynx_send_data *d;
         struct hpsb_packet *packet;
 
+#if 0 /* has been removed from ieee1394 core */
         d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
+#else
+	d = &lynx->async;
+#endif
         if (!list_empty(&d->pcl_queue)) {
                 PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
                 BUG();
@@ -511,9 +515,11 @@
         case hpsb_async:
                 pcl.buffer[0].control |= PCL_CMD_XMT;
                 break;
+#if 0 /* has been removed from ieee1394 core */
         case hpsb_iso:
                 pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
                 break;
+#endif
         case hpsb_raw:
                 pcl.buffer[0].control |= PCL_CMD_UNFXMT;
                 break;
@@ -542,9 +548,11 @@
         case hpsb_raw:
                 d = &lynx->async;
                 break;
+#if 0 /* has been removed from ieee1394 core */
         case hpsb_iso:
                 d = &lynx->iso_send;
                 break;
+#endif
         default:
                 PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
                       packet->type);
@@ -797,7 +805,7 @@
 		}
 
                 break;
-
+#if 0 /* has been removed from ieee1394 core */
         case ISO_LISTEN_CHANNEL:
                 spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
 
@@ -819,7 +827,7 @@
 
                 spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
                 break;
-
+#endif
         default:
                 PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
                 retval = -1;
@@ -1009,11 +1017,11 @@
                                 pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
                                                  packet->data_size, PCI_DMA_TODEVICE);
                         }
-
+#if 0 /* has been removed from ieee1394 core */
                         if (!list_empty(&lynx->iso_send.queue)) {
                                 send_next(lynx, hpsb_iso);
                         }
-
+#endif
                         spin_unlock(&lynx->iso_send.queue_lock);
 
                         if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
index 50daabf..a06aaad 100644
--- a/drivers/ieee1394/raw1394-private.h
+++ b/drivers/ieee1394/raw1394-private.h
@@ -36,11 +36,6 @@
 
         u8 __user *fcp_buffer;
 
-	/* old ISO API */
-        u64 listen_channels;
-        quadlet_t __user *iso_buffer;
-        size_t iso_buffer_length;
-
         u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
 
 	/* new rawiso API */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index d382500..336e5ff 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -98,21 +98,6 @@
 
 static void queue_complete_cb(struct pending_request *req);
 
-#include <asm/current.h>
-static void print_old_iso_deprecation(void)
-{
-	static pid_t p;
-
-	if (p == current->pid)
-		return;
-	p = current->pid;
-	printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
-	       " isochronous request types which will be removed in a next"
-	       " kernel release\n", current->comm);
-	printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
-	       " newer interface\n");
-}
-
 static struct pending_request *__alloc_pending_request(gfp_t flags)
 {
 	struct pending_request *req;
@@ -297,67 +282,6 @@
 	spin_unlock_irqrestore(&host_info_lock, flags);
 }
 
-static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
-			size_t length)
-{
-	unsigned long flags;
-	struct host_info *hi;
-	struct file_info *fi;
-	struct pending_request *req, *req_next;
-	struct iso_block_store *ibs = NULL;
-	LIST_HEAD(reqs);
-
-	if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
-		HPSB_INFO("dropped iso packet");
-		return;
-	}
-
-	spin_lock_irqsave(&host_info_lock, flags);
-	hi = find_host_info(host);
-
-	if (hi != NULL) {
-		list_for_each_entry(fi, &hi->file_info_list, list) {
-			if (!(fi->listen_channels & (1ULL << channel)))
-				continue;
-
-			req = __alloc_pending_request(GFP_ATOMIC);
-			if (!req)
-				break;
-
-			if (!ibs) {
-				ibs = kmalloc(sizeof(*ibs) + length,
-					      GFP_ATOMIC);
-				if (!ibs) {
-					kfree(req);
-					break;
-				}
-
-				atomic_add(length, &iso_buffer_size);
-				atomic_set(&ibs->refcount, 0);
-				ibs->data_size = length;
-				memcpy(ibs->data, data, length);
-			}
-
-			atomic_inc(&ibs->refcount);
-
-			req->file_info = fi;
-			req->ibs = ibs;
-			req->data = ibs->data;
-			req->req.type = RAW1394_REQ_ISO_RECEIVE;
-			req->req.generation = get_hpsb_generation(host);
-			req->req.misc = 0;
-			req->req.recvb = ptr2int(fi->iso_buffer);
-			req->req.length = min(length, fi->iso_buffer_length);
-
-			list_add_tail(&req->list, &reqs);
-		}
-	}
-	spin_unlock_irqrestore(&host_info_lock, flags);
-
-	list_for_each_entry_safe(req, req_next, &reqs, list)
-	    queue_complete_req(req);
-}
-
 static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			int cts, u8 * data, size_t length)
 {
@@ -434,7 +358,11 @@
 
 	__u64 sendb;
 	__u64 recvb;
-} __attribute__((packed));
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
 
 static const char __user *raw1394_compat_write(const char __user *buf)
 {
@@ -459,7 +387,7 @@
 static int
 raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
 {
-	struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+	struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
 	if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
 	    P(type) ||
 	    P(error) ||
@@ -587,7 +515,7 @@
 
 	req->req.length = 0;
 	queue_complete_req(req);
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int state_initialized(struct file_info *fi, struct pending_request *req)
@@ -601,7 +529,7 @@
 		req->req.generation = atomic_read(&internal_generation);
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	switch (req->req.type) {
@@ -673,44 +601,7 @@
 	}
 
 	queue_complete_req(req);
-	return sizeof(struct raw1394_request);
-}
-
-static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
-{
-	int channel = req->req.misc;
-
-	if ((channel > 63) || (channel < -64)) {
-		req->req.error = RAW1394_ERROR_INVALID_ARG;
-	} else if (channel >= 0) {
-		/* allocate channel req.misc */
-		if (fi->listen_channels & (1ULL << channel)) {
-			req->req.error = RAW1394_ERROR_ALREADY;
-		} else {
-			if (hpsb_listen_channel
-			    (&raw1394_highlevel, fi->host, channel)) {
-				req->req.error = RAW1394_ERROR_ALREADY;
-			} else {
-				fi->listen_channels |= 1ULL << channel;
-				fi->iso_buffer = int2ptr(req->req.recvb);
-				fi->iso_buffer_length = req->req.length;
-			}
-		}
-	} else {
-		/* deallocate channel (one's complement neg) req.misc */
-		channel = ~channel;
-
-		if (fi->listen_channels & (1ULL << channel)) {
-			hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
-					      channel);
-			fi->listen_channels &= ~(1ULL << channel);
-		} else {
-			req->req.error = RAW1394_ERROR_INVALID_ARG;
-		}
-	}
-
-	req->req.length = 0;
-	queue_complete_req(req);
+	return 0;
 }
 
 static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
@@ -865,7 +756,7 @@
 	if (req->req.error) {
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	hpsb_set_packet_complete_task(packet,
@@ -883,51 +774,7 @@
 		hpsb_free_tlabel(packet);
 		queue_complete_req(req);
 	}
-	return sizeof(struct raw1394_request);
-}
-
-static int handle_iso_send(struct file_info *fi, struct pending_request *req,
-			   int channel)
-{
-	unsigned long flags;
-	struct hpsb_packet *packet;
-
-	packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
-				     (req->req.misc >> 16) & 0x3,
-				     req->req.misc & 0xf);
-	if (!packet)
-		return -ENOMEM;
-
-	packet->speed_code = req->req.address & 0x3;
-
-	req->packet = packet;
-
-	if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-			   req->req.length)) {
-		req->req.error = RAW1394_ERROR_MEMFAULT;
-		req->req.length = 0;
-		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
-	}
-
-	req->req.length = 0;
-	hpsb_set_packet_complete_task(packet,
-				      (void (*)(void *))queue_complete_req,
-				      req);
-
-	spin_lock_irqsave(&fi->reqlists_lock, flags);
-	list_add_tail(&req->list, &fi->req_pending);
-	spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-	/* Update the generation of the packet just before sending. */
-	packet->generation = req->req.generation;
-
-	if (hpsb_send_packet(packet) < 0) {
-		req->req.error = RAW1394_ERROR_SEND_ERROR;
-		queue_complete_req(req);
-	}
-
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int handle_async_send(struct file_info *fi, struct pending_request *req)
@@ -936,16 +783,18 @@
 	struct hpsb_packet *packet;
 	int header_length = req->req.misc & 0xffff;
 	int expect_response = req->req.misc >> 16;
+	size_t data_size;
 
 	if (header_length > req->req.length || header_length < 12 ||
 	    header_length > FIELD_SIZEOF(struct hpsb_packet, header)) {
 		req->req.error = RAW1394_ERROR_INVALID_ARG;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
-	packet = hpsb_alloc_packet(req->req.length - header_length);
+	data_size = req->req.length - header_length;
+	packet = hpsb_alloc_packet(data_size);
 	req->packet = packet;
 	if (!packet)
 		return -ENOMEM;
@@ -955,16 +804,16 @@
 		req->req.error = RAW1394_ERROR_MEMFAULT;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	if (copy_from_user
 	    (packet->data, int2ptr(req->req.sendb) + header_length,
-	     packet->data_size)) {
+	     data_size)) {
 		req->req.error = RAW1394_ERROR_MEMFAULT;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	packet->type = hpsb_async;
@@ -974,7 +823,7 @@
 	packet->host = fi->host;
 	packet->expect_response = expect_response;
 	packet->header_size = header_length;
-	packet->data_size = req->req.length - header_length;
+	packet->data_size = data_size;
 
 	req->req.length = 0;
 	hpsb_set_packet_complete_task(packet,
@@ -992,7 +841,7 @@
 		queue_complete_req(req);
 	}
 
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
@@ -1867,7 +1716,7 @@
 		spin_lock_irqsave(&host_info_lock, flags);
 		list_add_tail(&addr->addr_list, &fi->addr_list);
 		spin_unlock_irqrestore(&host_info_lock, flags);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 	retval =
 	    hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
@@ -1885,7 +1734,7 @@
 		return (-EALREADY);
 	}
 	free_pending_request(req);	/* immediate success or fail */
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int arm_unregister(struct file_info *fi, struct pending_request *req)
@@ -1953,7 +1802,7 @@
 		vfree(addr->addr_space_buffer);
 		kfree(addr);
 		free_pending_request(req);	/* immediate success or fail */
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 	retval =
 	    hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
@@ -1969,7 +1818,7 @@
 	vfree(addr->addr_space_buffer);
 	kfree(addr);
 	free_pending_request(req);	/* immediate success or fail */
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 /* Copy data from ARM buffer(s) to user buffer. */
@@ -2011,7 +1860,7 @@
 				 * queue no response, and therefore nobody
 				 * will free it. */
 				free_pending_request(req);
-				return sizeof(struct raw1394_request);
+				return 0;
 			} else {
 				DBGMSG("arm_get_buf request exceeded mapping");
 				spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2063,7 +1912,7 @@
 				 * queue no response, and therefore nobody
 				 * will free it. */
 				free_pending_request(req);
-				return sizeof(struct raw1394_request);
+				return 0;
 			} else {
 				DBGMSG("arm_set_buf request exceeded mapping");
 				spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2084,7 +1933,7 @@
 	    (req->req.misc == RAW1394_NOTIFY_ON)) {
 		fi->notification = (u8) req->req.misc;
 		free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 	/* error EINVAL (22) invalid argument */
 	return (-EINVAL);
@@ -2117,12 +1966,12 @@
 		req->req.length = 0;
 		queue_complete_req(req);
 	}
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int get_config_rom(struct file_info *fi, struct pending_request *req)
 {
-	int ret = sizeof(struct raw1394_request);
+	int ret = 0;
 	quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
 	int status;
 
@@ -2152,7 +2001,7 @@
 
 static int update_config_rom(struct file_info *fi, struct pending_request *req)
 {
-	int ret = sizeof(struct raw1394_request);
+	int ret = 0;
 	quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -2219,7 +2068,7 @@
 
 			hpsb_update_config_rom_image(fi->host);
 			free_pending_request(req);
-			return sizeof(struct raw1394_request);
+			return 0;
 		}
 	}
 
@@ -2284,7 +2133,7 @@
 		/* we have to free the request, because we queue no response,
 		 * and therefore nobody will free it */
 		free_pending_request(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	} else {
 		for (dentry =
 		     fi->csr1212_dirs[dr]->value.directory.dentries_head;
@@ -2309,11 +2158,7 @@
 
 	case RAW1394_REQ_ECHO:
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
-
-	case RAW1394_REQ_ISO_SEND:
-		print_old_iso_deprecation();
-		return handle_iso_send(fi, req, node);
+		return 0;
 
 	case RAW1394_REQ_ARM_REGISTER:
 		return arm_register(fi, req);
@@ -2330,27 +2175,30 @@
 	case RAW1394_REQ_RESET_NOTIFY:
 		return reset_notification(fi, req);
 
+	case RAW1394_REQ_ISO_SEND:
 	case RAW1394_REQ_ISO_LISTEN:
-		print_old_iso_deprecation();
-		handle_iso_listen(fi, req);
-		return sizeof(struct raw1394_request);
+		printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
+		req->req.error = RAW1394_ERROR_COMPAT;
+		req->req.misc = RAW1394_KERNELAPI_VERSION;
+		queue_complete_req(req);
+		return 0;
 
 	case RAW1394_REQ_FCP_LISTEN:
 		handle_fcp_listen(fi, req);
-		return sizeof(struct raw1394_request);
+		return 0;
 
 	case RAW1394_REQ_RESET_BUS:
 		if (req->req.misc == RAW1394_LONG_RESET) {
 			DBGMSG("busreset called (type: LONG)");
 			hpsb_reset_bus(fi->host, LONG_RESET);
 			free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
-			return sizeof(struct raw1394_request);
+			return 0;
 		}
 		if (req->req.misc == RAW1394_SHORT_RESET) {
 			DBGMSG("busreset called (type: SHORT)");
 			hpsb_reset_bus(fi->host, SHORT_RESET);
 			free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
-			return sizeof(struct raw1394_request);
+			return 0;
 		}
 		/* error EINVAL (22) invalid argument */
 		return (-EINVAL);
@@ -2369,7 +2217,7 @@
 		req->req.generation = get_hpsb_generation(fi->host);
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	switch (req->req.type) {
@@ -2382,7 +2230,7 @@
 	if (req->req.length == 0) {
 		req->req.error = RAW1394_ERROR_INVALID_ARG;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	return handle_async_request(fi, req, node);
@@ -2393,7 +2241,7 @@
 {
 	struct file_info *fi = (struct file_info *)file->private_data;
 	struct pending_request *req;
-	ssize_t retval = 0;
+	ssize_t retval = -EBADFD;
 
 #ifdef CONFIG_COMPAT
 	if (count == sizeof(struct compat_raw1394_req) &&
@@ -2435,6 +2283,9 @@
 
 	if (retval < 0) {
 		free_pending_request(req);
+	} else {
+		BUG_ON(retval);
+		retval = count;
 	}
 
 	return retval;
@@ -2800,6 +2651,103 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+struct raw1394_iso_packets32 {
+        __u32 n_packets;
+        compat_uptr_t infos;
+} __attribute__((packed));
+
+struct raw1394_cycle_timer32 {
+        __u32 cycle_timer;
+        __u64 local_time;
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
+
+#define RAW1394_IOC_ISO_RECV_PACKETS32          \
+        _IOW ('#', 0x25, struct raw1394_iso_packets32)
+#define RAW1394_IOC_ISO_XMIT_PACKETS32          \
+        _IOW ('#', 0x27, struct raw1394_iso_packets32)
+#define RAW1394_IOC_GET_CYCLE_TIMER32           \
+        _IOR ('#', 0x30, struct raw1394_cycle_timer32)
+
+static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
+                                          struct raw1394_iso_packets32 __user *arg)
+{
+	compat_uptr_t infos32;
+	void *infos;
+	long err = -EFAULT;
+	struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
+
+	if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
+	    !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
+		infos = compat_ptr(infos32);
+		if (!copy_to_user(&dst->infos, &infos, sizeof infos))
+			err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst);
+	}
+	return err;
+}
+
+static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
+{
+	struct raw1394_cycle_timer32 ct;
+	int err;
+
+	err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+	if (!err)
+		if (copy_to_user(uaddr, &ct, sizeof(ct)))
+			err = -EFAULT;
+	return err;
+}
+
+static long raw1394_compat_ioctl(struct file *file,
+				 unsigned int cmd, unsigned long arg)
+{
+	struct file_info *fi = file->private_data;
+	void __user *argp = (void __user *)arg;
+	long err;
+
+	lock_kernel();
+	switch (cmd) {
+	/* These requests have same format as long as 'int' has same size. */
+	case RAW1394_IOC_ISO_RECV_INIT:
+	case RAW1394_IOC_ISO_RECV_START:
+	case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+	case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+	case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
+	case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
+	case RAW1394_IOC_ISO_RECV_FLUSH:
+	case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+	case RAW1394_IOC_ISO_XMIT_INIT:
+	case RAW1394_IOC_ISO_XMIT_START:
+	case RAW1394_IOC_ISO_XMIT_SYNC:
+	case RAW1394_IOC_ISO_GET_STATUS:
+	case RAW1394_IOC_ISO_SHUTDOWN:
+	case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+		err = raw1394_ioctl(NULL, file, cmd, arg);
+		break;
+	/* These request have different format. */
+	case RAW1394_IOC_ISO_RECV_PACKETS32:
+		err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
+		break;
+	case RAW1394_IOC_ISO_XMIT_PACKETS32:
+		err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
+		break;
+	case RAW1394_IOC_GET_CYCLE_TIMER32:
+		err = raw1394_read_cycle_timer32(fi, argp);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+	unlock_kernel();
+
+	return err;
+}
+#endif
+
 static unsigned int raw1394_poll(struct file *file, poll_table * pt)
 {
 	struct file_info *fi = file->private_data;
@@ -2859,14 +2807,7 @@
 	if (fi->iso_state != RAW1394_ISO_INACTIVE)
 		raw1394_iso_shutdown(fi);
 
-	for (i = 0; i < 64; i++) {
-		if (fi->listen_channels & (1ULL << i)) {
-			hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
-		}
-	}
-
 	spin_lock_irqsave(&host_info_lock, flags);
-	fi->listen_channels = 0;
 
 	fail = 0;
 	/* set address-entries invalid */
@@ -3028,7 +2969,6 @@
 	.add_host = add_host,
 	.remove_host = remove_host,
 	.host_reset = host_reset,
-	.iso_receive = iso_receive,
 	.fcp_request = fcp_request,
 };
 
@@ -3039,7 +2979,9 @@
 	.write = raw1394_write,
 	.mmap = raw1394_mmap,
 	.ioctl = raw1394_ioctl,
-	// .compat_ioctl = ... someone needs to do this
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = raw1394_compat_ioctl,
+#endif
 	.poll = raw1394_poll,
 	.open = raw1394_open,
 	.release = raw1394_release,
@@ -3052,9 +2994,9 @@
 	hpsb_register_highlevel(&raw1394_highlevel);
 
 	if (IS_ERR
-	    (class_device_create
-	     (hpsb_protocol_class, NULL,
-	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+	    (device_create(
+	      hpsb_protocol_class, NULL,
+	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
 	      RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
 		goto out_unreg;
@@ -3081,9 +3023,9 @@
 	goto out;
 
       out_dev:
-	class_device_destroy(hpsb_protocol_class,
-			     MKDEV(IEEE1394_MAJOR,
-				   IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+	device_destroy(hpsb_protocol_class,
+		       MKDEV(IEEE1394_MAJOR,
+			     IEEE1394_MINOR_BLOCK_RAW1394 * 16));
       out_unreg:
 	hpsb_unregister_highlevel(&raw1394_highlevel);
       out:
@@ -3092,9 +3034,9 @@
 
 static void __exit cleanup_raw1394(void)
 {
-	class_device_destroy(hpsb_protocol_class,
-			     MKDEV(IEEE1394_MAJOR,
-				   IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+	device_destroy(hpsb_protocol_class,
+		       MKDEV(IEEE1394_MAJOR,
+			     IEEE1394_MINOR_BLOCK_RAW1394 * 16));
 	cdev_del(&raw1394_cdev);
 	hpsb_unregister_highlevel(&raw1394_highlevel);
 	hpsb_unregister_protocol(&raw1394_driver);
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 7bd22ee..963ac20 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -17,11 +17,11 @@
 #define RAW1394_REQ_ASYNC_WRITE     101
 #define RAW1394_REQ_LOCK            102
 #define RAW1394_REQ_LOCK64          103
-#define RAW1394_REQ_ISO_SEND        104
+#define RAW1394_REQ_ISO_SEND        104 /* removed ABI, now a no-op */
 #define RAW1394_REQ_ASYNC_SEND      105
 #define RAW1394_REQ_ASYNC_STREAM    106
 
-#define RAW1394_REQ_ISO_LISTEN      200
+#define RAW1394_REQ_ISO_LISTEN      200 /* removed ABI, now a no-op */
 #define RAW1394_REQ_FCP_LISTEN      201
 #define RAW1394_REQ_RESET_BUS       202
 #define RAW1394_REQ_GET_ROM         203
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 4cb6fa2..e882cb9 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -70,6 +70,7 @@
 #include <linux/stringify.h>
 #include <linux/types.h>
 #include <linux/wait.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 #include <asm/errno.h>
@@ -117,14 +118,13 @@
 		 "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
 
 /*
- * Set serialize_io to 1 if you'd like only one scsi command sent
- * down to us at a time (debugging). This might be necessary for very
- * badly behaved sbp2 devices.
+ * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
+ * This is and always has been buggy in multiple subtle ways. See above TODOs.
  */
 static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
-		 "(default = 1, faster = 0)");
+module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
+MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
+		 "(default = Y, faster but buggy = N)");
 
 /*
  * Bump up max_sectors if you'd like to support very large sized
@@ -153,9 +153,9 @@
  * are possible on OXFW911 and newer Oxsemi bridges.
  */
 static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
+module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
 MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
-		 "(default = 1)");
+		 "(default = Y, use N for concurrent initiators)");
 
 /*
  * If any of the following workarounds is required for your device to work,
@@ -193,6 +193,27 @@
 	", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
 	", or a combination)");
 
+/*
+ * This influences the format of the sysfs attribute
+ * /sys/bus/scsi/devices/.../ieee1394_id.
+ *
+ * The default format is like in older kernels:  %016Lx:%d:%d
+ * It contains the target's EUI-64, a number given to the logical unit by
+ * the ieee1394 driver's nodemgr (starting at 0), and the LUN.
+ *
+ * The long format is:  %016Lx:%06x:%04x
+ * It contains the target's EUI-64, the unit directory's directory_ID as per
+ * IEEE 1212 clause 7.7.19, and the LUN.  This format comes closest to the
+ * format of SBP(-3) target port and logical unit identifier as per SAM (SCSI
+ * Architecture Model) rev.2 to 4 annex A.  Therefore and because it is
+ * independent of the implementation of the ieee1394 nodemgr, the longer format
+ * is recommended for future use.
+ */
+static int sbp2_long_sysfs_ieee1394_id;
+module_param_named(long_ieee1394_id, sbp2_long_sysfs_ieee1394_id, bool, 0644);
+MODULE_PARM_DESC(long_ieee1394_id, "8+3+2 bytes format of ieee1394_id in sysfs "
+		 "(default = backwards-compatible = N, SAM-conforming = Y)");
+
 
 #define SBP2_INFO(fmt, args...)	HPSB_INFO("sbp2: "fmt, ## args)
 #define SBP2_ERR(fmt, args...)	HPSB_ERR("sbp2: "fmt, ## args)
@@ -1488,69 +1509,6 @@
 	}
 }
 
-static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
-					struct sbp2_fwhost_info *hi,
-					struct sbp2_command_info *cmd,
-					struct scatterlist *sgpnt,
-					u32 orb_direction,
-					unsigned int scsi_request_bufflen,
-					void *scsi_request_buffer,
-					enum dma_data_direction dma_dir)
-{
-	cmd->dma_dir = dma_dir;
-	cmd->dma_size = scsi_request_bufflen;
-	cmd->dma_type = CMD_DMA_SINGLE;
-	cmd->cmd_dma = dma_map_single(hi->host->device.parent,
-				      scsi_request_buffer,
-				      cmd->dma_size, cmd->dma_dir);
-	orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-	orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-	/* handle case where we get a command w/o s/g enabled
-	 * (but check for transfers larger than 64K) */
-	if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
-		orb->data_descriptor_lo = cmd->cmd_dma;
-		orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
-
-	} else {
-		/* The buffer is too large. Turn this into page tables. */
-
-		struct sbp2_unrestricted_page_table *sg_element =
-						&cmd->scatter_gather_element[0];
-		u32 sg_count, sg_len;
-		dma_addr_t sg_addr;
-
-		orb->data_descriptor_lo = cmd->sge_dma;
-		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-
-		/* fill out our SBP-2 page tables; split up the large buffer */
-		sg_count = 0;
-		sg_len = scsi_request_bufflen;
-		sg_addr = cmd->cmd_dma;
-		while (sg_len) {
-			sg_element[sg_count].segment_base_lo = sg_addr;
-			if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-				sg_element[sg_count].length_segment_base_hi =
-					PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-				sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-				sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-			} else {
-				sg_element[sg_count].length_segment_base_hi =
-					PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-				sg_len = 0;
-			}
-			sg_count++;
-		}
-
-		orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
-		sbp2util_cpu_to_be32_buffer(sg_element,
-				(sizeof(struct sbp2_unrestricted_page_table)) *
-				sg_count);
-	}
-}
-
 static void sbp2_create_command_orb(struct sbp2_lu *lu,
 				    struct sbp2_command_info *cmd,
 				    unchar *scsi_cmd,
@@ -1594,13 +1552,9 @@
 		orb->data_descriptor_hi = 0x0;
 		orb->data_descriptor_lo = 0x0;
 		orb->misc |= ORB_SET_DIRECTION(1);
-	} else if (scsi_use_sg)
+	} else
 		sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
 					 orb_direction, dma_dir);
-	else
-		sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction,
-					    scsi_request_bufflen,
-					    scsi_request_buffer, dma_dir);
 
 	sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
 
@@ -1689,15 +1643,15 @@
 			     void (*done)(struct scsi_cmnd *))
 {
 	unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
-	unsigned int request_bufflen = SCpnt->request_bufflen;
+	unsigned int request_bufflen = scsi_bufflen(SCpnt);
 	struct sbp2_command_info *cmd;
 
 	cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
 	if (!cmd)
 		return -EIO;
 
-	sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg,
-				request_bufflen, SCpnt->request_buffer,
+	sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
+				request_bufflen, scsi_sglist(SCpnt),
 				SCpnt->sc_data_direction);
 	sbp2_link_orb_command(lu, cmd);
 
@@ -2099,8 +2053,14 @@
 	if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0]))
 		return 0;
 
-	return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)lu->ne->guid,
-		       lu->ud->id, ORB_SET_LUN(lu->lun));
+	if (sbp2_long_sysfs_ieee1394_id)
+		return sprintf(buf, "%016Lx:%06x:%04x\n",
+				(unsigned long long)lu->ne->guid,
+				lu->ud->directory_id, ORB_SET_LUN(lu->lun));
+	else
+		return sprintf(buf, "%016Lx:%d:%d\n",
+				(unsigned long long)lu->ne->guid,
+				lu->ud->id, ORB_SET_LUN(lu->lun));
 }
 
 MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 44402b9..333a4bb 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -67,7 +67,7 @@
 #define ORB_SET_LUN(v)			((v) & 0xffff)
 #define ORB_SET_FUNCTION(v)		(((v) & 0xf) << 16)
 #define ORB_SET_RECONNECT(v)		(((v) & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(v)		(((v) & 0x1) << 28)
+#define ORB_SET_EXCLUSIVE(v)		((v) ? 1 << 28 : 0)
 #define ORB_SET_LOGIN_RESP_LENGTH(v)	((v) & 0xffff)
 #define ORB_SET_PASSWD_LENGTH(v)	(((v) & 0xffff) << 16)
 
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 87ebd08..bd28adf 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1340,9 +1340,9 @@
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-	class_device_create(hpsb_protocol_class, NULL, MKDEV(
-		IEEE1394_MAJOR,	minor), 
-		NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+	device_create(hpsb_protocol_class, NULL,
+		      MKDEV(IEEE1394_MAJOR, minor),
+		      "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 }
 
 
@@ -1351,8 +1351,8 @@
 	struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
 
 	if (ohci)
-		class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
-			IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
+		device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+			       IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
 	return;
 }
 
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 994decc..a193dfb 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -1,14 +1,14 @@
-menu "InfiniBand support"
-	depends on HAS_IOMEM
-
-config INFINIBAND
-	depends on PCI || BROKEN
+menuconfig INFINIBAND
 	tristate "InfiniBand support"
+	depends on PCI || BROKEN
+	depends on HAS_IOMEM
 	---help---
 	  Core support for InfiniBand (IB).  Make sure to also select
 	  any protocols you wish to use as well as drivers for your
 	  InfiniBand hardware.
 
+if INFINIBAND
+
 config INFINIBAND_USER_MAD
 	tristate "InfiniBand userspace MAD support"
 	depends on INFINIBAND
@@ -20,7 +20,6 @@
 
 config INFINIBAND_USER_ACCESS
 	tristate "InfiniBand userspace access (verbs and CM)"
-	depends on INFINIBAND
 	---help---
 	  Userspace InfiniBand access support.  This enables the
 	  kernel side of userspace verbs and the userspace
@@ -37,7 +36,7 @@
 
 config INFINIBAND_ADDR_TRANS
 	bool
-	depends on INFINIBAND && INET
+	depends on INET
 	default y
 
 source "drivers/infiniband/hw/mthca/Kconfig"
@@ -54,4 +53,4 @@
 
 source "drivers/infiniband/ulp/iser/Kconfig"
 
-endmenu
+endif # INFINIBAND
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index ecd1a30..db2633e 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -3,7 +3,7 @@
  * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
  * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
- * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2004-2007 Voltaire Corporation.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -34,7 +34,6 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $
  */
 
 #include <linux/slab.h>
@@ -42,6 +41,7 @@
 
 #include "agent.h"
 #include "smi.h"
+#include "mad_priv.h"
 
 #define SPFX "ib_agent: "
 
@@ -87,8 +87,13 @@
 	struct ib_mad_send_buf *send_buf;
 	struct ib_ah *ah;
 	int ret;
+	struct ib_mad_send_wr_private *mad_send_wr;
 
-	port_priv = ib_get_agent_port(device, port_num);
+	if (device->node_type == RDMA_NODE_IB_SWITCH)
+		port_priv = ib_get_agent_port(device, 0);
+	else
+		port_priv = ib_get_agent_port(device, port_num);
+
 	if (!port_priv) {
 		printk(KERN_ERR SPFX "Unable to find port agent\n");
 		return -ENODEV;
@@ -113,6 +118,14 @@
 
 	memcpy(send_buf->mad, mad, sizeof *mad);
 	send_buf->ah = ah;
+
+	if (device->node_type == RDMA_NODE_IB_SWITCH) {
+		mad_send_wr = container_of(send_buf,
+					   struct ib_mad_send_wr_private,
+					   send_buf);
+		mad_send_wr->send_wr.wr.ud.port_num = port_num;
+	}
+
 	if ((ret = ib_post_send_mad(send_buf, NULL))) {
 		printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret);
 		goto err2;
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 558c9a0..e85f701 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 
 #include <rdma/ib_cache.h>
 
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index eff591d..9820c67 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -87,6 +87,7 @@
 struct cm_device {
 	struct list_head list;
 	struct ib_device *device;
+	u8 ack_delay;
 	struct cm_port port[0];
 };
 
@@ -95,7 +96,7 @@
 	union ib_gid dgid;
 	struct ib_ah_attr ah_attr;
 	u16 pkey_index;
-	u8 packet_life_time;
+	u8 timeout;
 };
 
 struct cm_work {
@@ -154,6 +155,7 @@
 	u8 retry_count;
 	u8 rnr_retry_count;
 	u8 service_timeout;
+	u8 target_ack_delay;
 
 	struct list_head work_list;
 	atomic_t work_count;
@@ -293,7 +295,7 @@
 	av->port = port;
 	ib_init_ah_from_path(cm_dev->device, port->port_num, path,
 			     &av->ah_attr);
-	av->packet_life_time = path->packet_life_time;
+	av->timeout = path->packet_life_time + 1;
 	return 0;
 }
 
@@ -306,7 +308,9 @@
 	do {
 		spin_lock_irqsave(&cm.lock, flags);
 		ret = idr_get_new_above(&cm.local_id_table, cm_id_priv,
-					next_id++, &id);
+					next_id, &id);
+		if (!ret)
+			next_id = ((unsigned) id + 1) & MAX_ID_MASK;
 		spin_unlock_irqrestore(&cm.lock, flags);
 	} while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
 
@@ -316,12 +320,10 @@
 
 static void cm_free_id(__be32 local_id)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&cm.lock, flags);
+	spin_lock_irq(&cm.lock);
 	idr_remove(&cm.local_id_table,
 		   (__force int) (local_id ^ cm.random_id_operand));
-	spin_unlock_irqrestore(&cm.lock, flags);
+	spin_unlock_irq(&cm.lock);
 }
 
 static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
@@ -343,11 +345,10 @@
 static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
 {
 	struct cm_id_private *cm_id_priv;
-	unsigned long flags;
 
-	spin_lock_irqsave(&cm.lock, flags);
+	spin_lock_irq(&cm.lock);
 	cm_id_priv = cm_get_id(local_id, remote_id);
-	spin_unlock_irqrestore(&cm.lock, flags);
+	spin_unlock_irq(&cm.lock);
 
 	return cm_id_priv;
 }
@@ -644,6 +645,25 @@
 	return 1 << max(iba_time - 8, 0);
 }
 
+/*
+ * calculate: 4.096x2^ack_timeout = 4.096x2^ack_delay + 2x4.096x2^life_time
+ * Because of how ack_timeout is stored, adding one doubles the timeout.
+ * To avoid large timeouts, select the max(ack_delay, life_time + 1), and
+ * increment it (round up) only if the other is within 50%.
+ */
+static u8 cm_ack_timeout(u8 ca_ack_delay, u8 packet_life_time)
+{
+	int ack_timeout = packet_life_time + 1;
+
+	if (ack_timeout >= ca_ack_delay)
+		ack_timeout += (ca_ack_delay >= (ack_timeout - 1));
+	else
+		ack_timeout = ca_ack_delay +
+			      (ack_timeout >= (ca_ack_delay - 1));
+
+	return min(31, ack_timeout);
+}
+
 static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
 {
 	if (timewait_info->inserted_remote_id) {
@@ -687,7 +707,7 @@
 	 * timewait before notifying the user that we've exited timewait.
 	 */
 	cm_id_priv->id.state = IB_CM_TIMEWAIT;
-	wait_time = cm_convert_to_ms(cm_id_priv->av.packet_life_time + 1);
+	wait_time = cm_convert_to_ms(cm_id_priv->av.timeout);
 	queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
 			   msecs_to_jiffies(wait_time));
 	cm_id_priv->timewait_info = NULL;
@@ -711,31 +731,30 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_work *work;
-	unsigned long flags;
 
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
 retest:
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	switch (cm_id->state) {
 	case IB_CM_LISTEN:
 		cm_id->state = IB_CM_IDLE;
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-		spin_lock_irqsave(&cm.lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
+		spin_lock_irq(&cm.lock);
 		rb_erase(&cm_id_priv->service_node, &cm.listen_service_table);
-		spin_unlock_irqrestore(&cm.lock, flags);
+		spin_unlock_irq(&cm.lock);
 		break;
 	case IB_CM_SIDR_REQ_SENT:
 		cm_id->state = IB_CM_IDLE;
 		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		break;
 	case IB_CM_SIDR_REQ_RCVD:
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
 		break;
 	case IB_CM_REQ_SENT:
 		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
 			       &cm_id_priv->id.device->node_guid,
 			       sizeof cm_id_priv->id.device->node_guid,
@@ -745,9 +764,9 @@
 		if (err == -ENOMEM) {
 			/* Do not reject to allow future retries. */
 			cm_reset_to_idle(cm_id_priv);
-			spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+			spin_unlock_irq(&cm_id_priv->lock);
 		} else {
-			spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+			spin_unlock_irq(&cm_id_priv->lock);
 			ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
 				       NULL, 0, NULL, 0);
 		}
@@ -760,25 +779,25 @@
 	case IB_CM_MRA_REQ_SENT:
 	case IB_CM_REP_RCVD:
 	case IB_CM_MRA_REP_SENT:
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
 			       NULL, 0, NULL, 0);
 		break;
 	case IB_CM_ESTABLISHED:
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		ib_send_cm_dreq(cm_id, NULL, 0);
 		goto retest;
 	case IB_CM_DREQ_SENT:
 		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		cm_enter_timewait(cm_id_priv);
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		break;
 	case IB_CM_DREQ_RCVD:
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		ib_send_cm_drep(cm_id, NULL, 0);
 		break;
 	default:
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		break;
 	}
 
@@ -910,7 +929,8 @@
 	cm_req_set_primary_sl(req_msg, param->primary_path->sl);
 	cm_req_set_primary_subnet_local(req_msg, 1); /* local only... */
 	cm_req_set_primary_local_ack_timeout(req_msg,
-		min(31, param->primary_path->packet_life_time + 1));
+		cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+			       param->primary_path->packet_life_time));
 
 	if (param->alternate_path) {
 		req_msg->alt_local_lid = param->alternate_path->slid;
@@ -925,7 +945,8 @@
 		cm_req_set_alt_sl(req_msg, param->alternate_path->sl);
 		cm_req_set_alt_subnet_local(req_msg, 1); /* local only... */
 		cm_req_set_alt_local_ack_timeout(req_msg,
-			min(31, param->alternate_path->packet_life_time + 1));
+			cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+				       param->alternate_path->packet_life_time));
 	}
 
 	if (param->private_data && param->private_data_len)
@@ -1167,7 +1188,6 @@
 static void cm_process_work(struct cm_id_private *cm_id_priv,
 			    struct cm_work *work)
 {
-	unsigned long flags;
 	int ret;
 
 	/* We will typically only have the current event to report. */
@@ -1175,9 +1195,9 @@
 	cm_free_work(work);
 
 	while (!ret && !atomic_add_negative(-1, &cm_id_priv->work_count)) {
-		spin_lock_irqsave(&cm_id_priv->lock, flags);
+		spin_lock_irq(&cm_id_priv->lock);
 		work = cm_dequeue_work(cm_id_priv);
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		BUG_ON(!work);
 		ret = cm_id_priv->id.cm_handler(&cm_id_priv->id,
 						&work->cm_event);
@@ -1248,7 +1268,6 @@
 			       struct cm_id_private *cm_id_priv)
 {
 	struct ib_mad_send_buf *msg = NULL;
-	unsigned long flags;
 	int ret;
 
 	/* Quick state check to discard duplicate REQs. */
@@ -1259,7 +1278,7 @@
 	if (ret)
 		return;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	switch (cm_id_priv->id.state) {
 	case IB_CM_MRA_REQ_SENT:
 		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
@@ -1274,14 +1293,14 @@
 	default:
 		goto unlock;
 	}
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	ret = ib_post_send_mad(msg, NULL);
 	if (ret)
 		goto free;
 	return;
 
-unlock:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock:	spin_unlock_irq(&cm_id_priv->lock);
 free:	cm_free_msg(msg);
 }
 
@@ -1291,30 +1310,32 @@
 	struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv;
 	struct cm_timewait_info *timewait_info;
 	struct cm_req_msg *req_msg;
-	unsigned long flags;
 
 	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 
-	/* Check for duplicate REQ and stale connections. */
-	spin_lock_irqsave(&cm.lock, flags);
+	/* Check for possible duplicate REQ. */
+	spin_lock_irq(&cm.lock);
 	timewait_info = cm_insert_remote_id(cm_id_priv->timewait_info);
-	if (!timewait_info)
-		timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
-
 	if (timewait_info) {
 		cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
 					   timewait_info->work.remote_id);
-		cm_cleanup_timewait(cm_id_priv->timewait_info);
-		spin_unlock_irqrestore(&cm.lock, flags);
+		spin_unlock_irq(&cm.lock);
 		if (cur_cm_id_priv) {
 			cm_dup_req_handler(work, cur_cm_id_priv);
 			cm_deref_id(cur_cm_id_priv);
-		} else
-			cm_issue_rej(work->port, work->mad_recv_wc,
-				     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
-				     NULL, 0);
-		listen_cm_id_priv = NULL;
-		goto out;
+		}
+		return NULL;
+	}
+
+	/* Check for stale connections. */
+	timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
+	if (timewait_info) {
+		cm_cleanup_timewait(cm_id_priv->timewait_info);
+		spin_unlock_irq(&cm.lock);
+		cm_issue_rej(work->port, work->mad_recv_wc,
+			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
+			     NULL, 0);
+		return NULL;
 	}
 
 	/* Find matching listen request. */
@@ -1323,7 +1344,7 @@
 					   req_msg->private_data);
 	if (!listen_cm_id_priv) {
 		cm_cleanup_timewait(cm_id_priv->timewait_info);
-		spin_unlock_irqrestore(&cm.lock, flags);
+		spin_unlock_irq(&cm.lock);
 		cm_issue_rej(work->port, work->mad_recv_wc,
 			     IB_CM_REJ_INVALID_SERVICE_ID, CM_MSG_RESPONSE_REQ,
 			     NULL, 0);
@@ -1333,7 +1354,7 @@
 	atomic_inc(&cm_id_priv->refcount);
 	cm_id_priv->id.state = IB_CM_REQ_RCVD;
 	atomic_inc(&cm_id_priv->work_count);
-	spin_unlock_irqrestore(&cm.lock, flags);
+	spin_unlock_irq(&cm.lock);
 out:
 	return listen_cm_id_priv;
 }
@@ -1435,7 +1456,8 @@
 	cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
 	rep_msg->resp_resources = param->responder_resources;
 	rep_msg->initiator_depth = param->initiator_depth;
-	cm_rep_set_target_ack_delay(rep_msg, param->target_ack_delay);
+	cm_rep_set_target_ack_delay(rep_msg,
+				    cm_id_priv->av.port->cm_dev->ack_delay);
 	cm_rep_set_failover(rep_msg, param->failover_accepted);
 	cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
 	cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
@@ -1586,7 +1608,6 @@
 	struct cm_id_private *cm_id_priv;
 	struct cm_rep_msg *rep_msg;
 	struct ib_mad_send_buf *msg = NULL;
-	unsigned long flags;
 	int ret;
 
 	rep_msg = (struct cm_rep_msg *) work->mad_recv_wc->recv_buf.mad;
@@ -1599,7 +1620,7 @@
 	if (ret)
 		goto deref;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->id.state == IB_CM_ESTABLISHED)
 		cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
 			      cm_id_priv->private_data,
@@ -1611,14 +1632,14 @@
 			      cm_id_priv->private_data_len);
 	else
 		goto unlock;
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	ret = ib_post_send_mad(msg, NULL);
 	if (ret)
 		goto free;
 	goto deref;
 
-unlock:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock:	spin_unlock_irq(&cm_id_priv->lock);
 free:	cm_free_msg(msg);
 deref:	cm_deref_id(cm_id_priv);
 }
@@ -1627,7 +1648,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_rep_msg *rep_msg;
-	unsigned long flags;
 	int ret;
 
 	rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1639,13 +1659,13 @@
 
 	cm_format_rep_event(work);
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	switch (cm_id_priv->id.state) {
 	case IB_CM_REQ_SENT:
 	case IB_CM_MRA_REQ_RCVD:
 		break;
 	default:
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		ret = -EINVAL;
 		goto error;
 	}
@@ -1658,7 +1678,7 @@
 	/* Check for duplicate REP. */
 	if (cm_insert_remote_id(cm_id_priv->timewait_info)) {
 		spin_unlock(&cm.lock);
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		ret = -EINVAL;
 		goto error;
 	}
@@ -1668,7 +1688,7 @@
 			 &cm.remote_id_table);
 		cm_id_priv->timewait_info->inserted_remote_id = 0;
 		spin_unlock(&cm.lock);
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		cm_issue_rej(work->port, work->mad_recv_wc,
 			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP,
 			     NULL, 0);
@@ -1684,6 +1704,13 @@
 	cm_id_priv->responder_resources = rep_msg->initiator_depth;
 	cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
 	cm_id_priv->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg);
+	cm_id_priv->target_ack_delay = cm_rep_get_target_ack_delay(rep_msg);
+	cm_id_priv->av.timeout =
+			cm_ack_timeout(cm_id_priv->target_ack_delay,
+				       cm_id_priv->av.timeout - 1);
+	cm_id_priv->alt_av.timeout =
+			cm_ack_timeout(cm_id_priv->target_ack_delay,
+				       cm_id_priv->alt_av.timeout - 1);
 
 	/* todo: handle peer_to_peer */
 
@@ -1691,7 +1718,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -1707,7 +1734,6 @@
 static int cm_establish_handler(struct cm_work *work)
 {
 	struct cm_id_private *cm_id_priv;
-	unsigned long flags;
 	int ret;
 
 	/* See comment in cm_establish about lookup. */
@@ -1715,9 +1741,9 @@
 	if (!cm_id_priv)
 		return -EINVAL;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->id.state != IB_CM_ESTABLISHED) {
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		goto out;
 	}
 
@@ -1725,7 +1751,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -1741,7 +1767,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_rtu_msg *rtu_msg;
-	unsigned long flags;
 	int ret;
 
 	rtu_msg = (struct cm_rtu_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1752,10 +1777,10 @@
 
 	work->cm_event.private_data = &rtu_msg->private_data;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->id.state != IB_CM_REP_SENT &&
 	    cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		goto out;
 	}
 	cm_id_priv->id.state = IB_CM_ESTABLISHED;
@@ -1764,7 +1789,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -1927,7 +1952,6 @@
 	struct cm_id_private *cm_id_priv;
 	struct cm_dreq_msg *dreq_msg;
 	struct ib_mad_send_buf *msg = NULL;
-	unsigned long flags;
 	int ret;
 
 	dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1940,7 +1964,7 @@
 
 	work->cm_event.private_data = &dreq_msg->private_data;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->local_qpn != cm_dreq_get_remote_qpn(dreq_msg))
 		goto unlock;
 
@@ -1959,7 +1983,7 @@
 		cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
 			       cm_id_priv->private_data,
 			       cm_id_priv->private_data_len);
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 
 		if (ib_post_send_mad(msg, NULL))
 			cm_free_msg(msg);
@@ -1972,7 +1996,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -1980,7 +2004,7 @@
 		cm_deref_id(cm_id_priv);
 	return 0;
 
-unlock:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock:	spin_unlock_irq(&cm_id_priv->lock);
 deref:	cm_deref_id(cm_id_priv);
 	return -EINVAL;
 }
@@ -1989,7 +2013,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_drep_msg *drep_msg;
-	unsigned long flags;
 	int ret;
 
 	drep_msg = (struct cm_drep_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2000,10 +2023,10 @@
 
 	work->cm_event.private_data = &drep_msg->private_data;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->id.state != IB_CM_DREQ_SENT &&
 	    cm_id_priv->id.state != IB_CM_DREQ_RCVD) {
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		goto out;
 	}
 	cm_enter_timewait(cm_id_priv);
@@ -2012,7 +2035,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -2102,17 +2125,16 @@
 {
 	struct cm_timewait_info *timewait_info;
 	struct cm_id_private *cm_id_priv;
-	unsigned long flags;
 	__be32 remote_id;
 
 	remote_id = rej_msg->local_comm_id;
 
 	if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {
-		spin_lock_irqsave(&cm.lock, flags);
+		spin_lock_irq(&cm.lock);
 		timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),
 						  remote_id);
 		if (!timewait_info) {
-			spin_unlock_irqrestore(&cm.lock, flags);
+			spin_unlock_irq(&cm.lock);
 			return NULL;
 		}
 		cm_id_priv = idr_find(&cm.local_id_table, (__force int)
@@ -2124,7 +2146,7 @@
 			else
 				cm_id_priv = NULL;
 		}
-		spin_unlock_irqrestore(&cm.lock, flags);
+		spin_unlock_irq(&cm.lock);
 	} else if (cm_rej_get_msg_rejected(rej_msg) == CM_MSG_RESPONSE_REQ)
 		cm_id_priv = cm_acquire_id(rej_msg->remote_comm_id, 0);
 	else
@@ -2137,7 +2159,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_rej_msg *rej_msg;
-	unsigned long flags;
 	int ret;
 
 	rej_msg = (struct cm_rej_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2147,7 +2168,7 @@
 
 	cm_format_rej_event(work);
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	switch (cm_id_priv->id.state) {
 	case IB_CM_REQ_SENT:
 	case IB_CM_MRA_REQ_RCVD:
@@ -2171,7 +2192,7 @@
 		cm_enter_timewait(cm_id_priv);
 		break;
 	default:
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		ret = -EINVAL;
 		goto out;
 	}
@@ -2179,7 +2200,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -2290,7 +2311,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_mra_msg *mra_msg;
-	unsigned long flags;
 	int timeout, ret;
 
 	mra_msg = (struct cm_mra_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2302,9 +2322,9 @@
 	work->cm_event.param.mra_rcvd.service_timeout =
 					cm_mra_get_service_timeout(mra_msg);
 	timeout = cm_convert_to_ms(cm_mra_get_service_timeout(mra_msg)) +
-		  cm_convert_to_ms(cm_id_priv->av.packet_life_time);
+		  cm_convert_to_ms(cm_id_priv->av.timeout);
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	switch (cm_id_priv->id.state) {
 	case IB_CM_REQ_SENT:
 		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
@@ -2337,7 +2357,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -2345,7 +2365,7 @@
 		cm_deref_id(cm_id_priv);
 	return 0;
 out:
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 	cm_deref_id(cm_id_priv);
 	return -EINVAL;
 }
@@ -2374,7 +2394,8 @@
 	cm_lap_set_sl(lap_msg, alternate_path->sl);
 	cm_lap_set_subnet_local(lap_msg, 1); /* local only... */
 	cm_lap_set_local_ack_timeout(lap_msg,
-		min(31, alternate_path->packet_life_time + 1));
+		cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+			       alternate_path->packet_life_time));
 
 	if (private_data && private_data_len)
 		memcpy(lap_msg->private_data, private_data, private_data_len);
@@ -2405,6 +2426,9 @@
 	ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av);
 	if (ret)
 		goto out;
+	cm_id_priv->alt_av.timeout =
+			cm_ack_timeout(cm_id_priv->target_ack_delay,
+				       cm_id_priv->alt_av.timeout - 1);
 
 	ret = cm_alloc_msg(cm_id_priv, &msg);
 	if (ret)
@@ -2460,7 +2484,6 @@
 	struct cm_lap_msg *lap_msg;
 	struct ib_cm_lap_event_param *param;
 	struct ib_mad_send_buf *msg = NULL;
-	unsigned long flags;
 	int ret;
 
 	/* todo: verify LAP request and send reject APR if invalid. */
@@ -2475,7 +2498,7 @@
 	cm_format_path_from_lap(cm_id_priv, param->alternate_path, lap_msg);
 	work->cm_event.private_data = &lap_msg->private_data;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->id.state != IB_CM_ESTABLISHED)
 		goto unlock;
 
@@ -2492,7 +2515,7 @@
 			      cm_id_priv->service_timeout,
 			      cm_id_priv->private_data,
 			      cm_id_priv->private_data_len);
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 
 		if (ib_post_send_mad(msg, NULL))
 			cm_free_msg(msg);
@@ -2510,7 +2533,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -2518,7 +2541,7 @@
 		cm_deref_id(cm_id_priv);
 	return 0;
 
-unlock:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock:	spin_unlock_irq(&cm_id_priv->lock);
 deref:	cm_deref_id(cm_id_priv);
 	return -EINVAL;
 }
@@ -2593,7 +2616,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct cm_apr_msg *apr_msg;
-	unsigned long flags;
 	int ret;
 
 	apr_msg = (struct cm_apr_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2607,11 +2629,11 @@
 	work->cm_event.param.apr_rcvd.info_len = apr_msg->info_length;
 	work->cm_event.private_data = &apr_msg->private_data;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->id.state != IB_CM_ESTABLISHED ||
 	    (cm_id_priv->id.lap_state != IB_CM_LAP_SENT &&
 	     cm_id_priv->id.lap_state != IB_CM_MRA_LAP_RCVD)) {
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		goto out;
 	}
 	cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;
@@ -2621,7 +2643,7 @@
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -2756,7 +2778,6 @@
 	struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
 	struct cm_sidr_req_msg *sidr_req_msg;
 	struct ib_wc *wc;
-	unsigned long flags;
 
 	cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
 	if (IS_ERR(cm_id))
@@ -2773,27 +2794,26 @@
 				work->mad_recv_wc->recv_buf.grh,
 				&cm_id_priv->av);
 	cm_id_priv->id.remote_id = sidr_req_msg->request_id;
-	cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
 	cm_id_priv->tid = sidr_req_msg->hdr.tid;
 	atomic_inc(&cm_id_priv->work_count);
 
-	spin_lock_irqsave(&cm.lock, flags);
+	spin_lock_irq(&cm.lock);
 	cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
 	if (cur_cm_id_priv) {
-		spin_unlock_irqrestore(&cm.lock, flags);
+		spin_unlock_irq(&cm.lock);
 		goto out; /* Duplicate message. */
 	}
+	cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
 	cur_cm_id_priv = cm_find_listen(cm_id->device,
 					sidr_req_msg->service_id,
 					sidr_req_msg->private_data);
 	if (!cur_cm_id_priv) {
-		rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
-		spin_unlock_irqrestore(&cm.lock, flags);
-		/* todo: reply with no match */
+		spin_unlock_irq(&cm.lock);
+		cm_reject_sidr_req(cm_id_priv, IB_SIDR_UNSUPPORTED);
 		goto out; /* No match. */
 	}
 	atomic_inc(&cur_cm_id_priv->refcount);
-	spin_unlock_irqrestore(&cm.lock, flags);
+	spin_unlock_irq(&cm.lock);
 
 	cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
 	cm_id_priv->id.context = cur_cm_id_priv->id.context;
@@ -2894,7 +2914,6 @@
 {
 	struct cm_sidr_rep_msg *sidr_rep_msg;
 	struct cm_id_private *cm_id_priv;
-	unsigned long flags;
 
 	sidr_rep_msg = (struct cm_sidr_rep_msg *)
 				work->mad_recv_wc->recv_buf.mad;
@@ -2902,14 +2921,14 @@
 	if (!cm_id_priv)
 		return -EINVAL; /* Unmatched reply. */
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->id.state != IB_CM_SIDR_REQ_SENT) {
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		goto out;
 	}
 	cm_id_priv->id.state = IB_CM_IDLE;
 	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	cm_format_sidr_rep_event(work);
 	cm_process_work(cm_id_priv, work);
@@ -2925,14 +2944,13 @@
 	struct cm_id_private *cm_id_priv;
 	struct ib_cm_event cm_event;
 	enum ib_cm_state state;
-	unsigned long flags;
 	int ret;
 
 	memset(&cm_event, 0, sizeof cm_event);
 	cm_id_priv = msg->context[0];
 
 	/* Discard old sends or ones without a response. */
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	state = (enum ib_cm_state) (unsigned long) msg->context[1];
 	if (msg != cm_id_priv->msg || state != cm_id_priv->id.state)
 		goto discard;
@@ -2959,7 +2977,7 @@
 	default:
 		goto discard;
 	}
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 	cm_event.param.send_status = wc_status;
 
 	/* No other events can occur on the cm_id at this point. */
@@ -2969,7 +2987,7 @@
 		ib_destroy_cm_id(&cm_id_priv->id);
 	return;
 discard:
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 	cm_free_msg(msg);
 }
 
@@ -3264,8 +3282,7 @@
 			*qp_attr_mask |= IB_QP_ALT_PATH;
 			qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
 			qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
-			qp_attr->alt_timeout =
-					cm_id_priv->alt_av.packet_life_time + 1;
+			qp_attr->alt_timeout = cm_id_priv->alt_av.timeout;
 			qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
 		}
 		ret = 0;
@@ -3303,8 +3320,7 @@
 				*qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
 						 IB_QP_RNR_RETRY |
 						 IB_QP_MAX_QP_RD_ATOMIC;
-				qp_attr->timeout =
-					cm_id_priv->av.packet_life_time + 1;
+				qp_attr->timeout = cm_id_priv->av.timeout;
 				qp_attr->retry_cnt = cm_id_priv->retry_count;
 				qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
 				qp_attr->max_rd_atomic =
@@ -3318,8 +3334,7 @@
 			*qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE;
 			qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
 			qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
-			qp_attr->alt_timeout =
-				cm_id_priv->alt_av.packet_life_time + 1;
+			qp_attr->alt_timeout = cm_id_priv->alt_av.timeout;
 			qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
 			qp_attr->path_mig_state = IB_MIG_REARM;
 		}
@@ -3359,6 +3374,16 @@
 }
 EXPORT_SYMBOL(ib_cm_init_qp_attr);
 
+void cm_get_ack_delay(struct cm_device *cm_dev)
+{
+	struct ib_device_attr attr;
+
+	if (ib_query_device(cm_dev->device, &attr))
+		cm_dev->ack_delay = 0; /* acks will rely on packet life time */
+	else
+		cm_dev->ack_delay = attr.local_ca_ack_delay;
+}
+
 static void cm_add_one(struct ib_device *device)
 {
 	struct cm_device *cm_dev;
@@ -3383,6 +3408,7 @@
 		return;
 
 	cm_dev->device = device;
+	cm_get_ack_delay(cm_dev);
 
 	set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
 	for (i = 1; i <= device->phys_port_cnt; i++) {
diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
index 4d3aee9..aec9c7a 100644
--- a/drivers/infiniband/core/cm_msgs.h
+++ b/drivers/infiniband/core/cm_msgs.h
@@ -35,6 +35,7 @@
 #define CM_MSGS_H
 
 #include <rdma/ib_mad.h>
+#include <rdma/ib_cm.h>
 
 /*
  * Parameters to routines below should be in network-byte order, and values
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 2eb52b7..23af7a0 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2326,7 +2326,6 @@
 	rep.private_data_len = conn_param->private_data_len;
 	rep.responder_resources = conn_param->responder_resources;
 	rep.initiator_depth = conn_param->initiator_depth;
-	rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT;
 	rep.failover_accepted = 0;
 	rep.flow_control = conn_param->flow_control;
 	rep.rnr_retry_count = conn_param->rnr_retry_count;
@@ -2773,8 +2772,8 @@
 	int ret;
 
 	get_random_bytes(&next_port, sizeof next_port);
-	next_port = (next_port % (sysctl_local_port_range[1] -
-				  sysctl_local_port_range[0])) +
+	next_port = ((unsigned int) next_port %
+		    (sysctl_local_port_range[1] - sysctl_local_port_range[0])) +
 		    sysctl_local_port_range[0];
 	cma_wq = create_singlethread_workqueue("rdma_cm");
 	if (!cma_wq)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 592c90a..3ada17c 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include "core_priv.h"
 
@@ -149,6 +150,18 @@
 	return 0;
 }
 
+static int start_port(struct ib_device *device)
+{
+	return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1;
+}
+
+
+static int end_port(struct ib_device *device)
+{
+	return (device->node_type == RDMA_NODE_IB_SWITCH) ?
+		0 : device->phys_port_cnt;
+}
+
 /**
  * ib_alloc_device - allocate an IB device struct
  * @size:size of structure to allocate
@@ -208,6 +221,45 @@
 	return 0;
 }
 
+static int read_port_table_lengths(struct ib_device *device)
+{
+	struct ib_port_attr *tprops = NULL;
+	int num_ports, ret = -ENOMEM;
+	u8 port_index;
+
+	tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
+	if (!tprops)
+		goto out;
+
+	num_ports = end_port(device) - start_port(device) + 1;
+
+	device->pkey_tbl_len = kmalloc(sizeof *device->pkey_tbl_len * num_ports,
+				       GFP_KERNEL);
+	device->gid_tbl_len = kmalloc(sizeof *device->gid_tbl_len * num_ports,
+				      GFP_KERNEL);
+	if (!device->pkey_tbl_len || !device->gid_tbl_len)
+		goto err;
+
+	for (port_index = 0; port_index < num_ports; ++port_index) {
+		ret = ib_query_port(device, port_index + start_port(device),
+					tprops);
+		if (ret)
+			goto err;
+		device->pkey_tbl_len[port_index] = tprops->pkey_tbl_len;
+		device->gid_tbl_len[port_index]  = tprops->gid_tbl_len;
+	}
+
+	ret = 0;
+	goto out;
+
+err:
+	kfree(device->gid_tbl_len);
+	kfree(device->pkey_tbl_len);
+out:
+	kfree(tprops);
+	return ret;
+}
+
 /**
  * ib_register_device - Register an IB device with IB core
  * @device:Device to register
@@ -239,10 +291,19 @@
 	spin_lock_init(&device->event_handler_lock);
 	spin_lock_init(&device->client_data_lock);
 
+	ret = read_port_table_lengths(device);
+	if (ret) {
+		printk(KERN_WARNING "Couldn't create table lengths cache for device %s\n",
+		       device->name);
+		goto out;
+	}
+
 	ret = ib_device_register_sysfs(device);
 	if (ret) {
 		printk(KERN_WARNING "Couldn't register device %s with driver model\n",
 		       device->name);
+		kfree(device->gid_tbl_len);
+		kfree(device->pkey_tbl_len);
 		goto out;
 	}
 
@@ -284,6 +345,9 @@
 
 	list_del(&device->core_list);
 
+	kfree(device->gid_tbl_len);
+	kfree(device->pkey_tbl_len);
+
 	mutex_unlock(&device_mutex);
 
 	spin_lock_irqsave(&device->client_data_lock, flags);
@@ -506,10 +570,7 @@
 		  u8 port_num,
 		  struct ib_port_attr *port_attr)
 {
-	if (device->node_type == RDMA_NODE_IB_SWITCH) {
-		if (port_num)
-			return -EINVAL;
-	} else if (port_num < 1 || port_num > device->phys_port_cnt)
+	if (port_num < start_port(device) || port_num > end_port(device))
 		return -EINVAL;
 
 	return device->query_port(device, port_num, port_attr);
@@ -581,10 +642,7 @@
 		   u8 port_num, int port_modify_mask,
 		   struct ib_port_modify *port_modify)
 {
-	if (device->node_type == RDMA_NODE_IB_SWITCH) {
-		if (port_num)
-			return -EINVAL;
-	} else if (port_num < 1 || port_num > device->phys_port_cnt)
+	if (port_num < start_port(device) || port_num > end_port(device))
 		return -EINVAL;
 
 	return device->modify_port(device, port_num, port_modify_mask,
@@ -592,6 +650,68 @@
 }
 EXPORT_SYMBOL(ib_modify_port);
 
+/**
+ * ib_find_gid - Returns the port number and GID table index where
+ *   a specified GID value occurs.
+ * @device: The device to query.
+ * @gid: The GID value to search for.
+ * @port_num: The port number of the device where the GID value was found.
+ * @index: The index into the GID table where the GID was found.  This
+ *   parameter may be NULL.
+ */
+int ib_find_gid(struct ib_device *device, union ib_gid *gid,
+		u8 *port_num, u16 *index)
+{
+	union ib_gid tmp_gid;
+	int ret, port, i;
+
+	for (port = start_port(device); port <= end_port(device); ++port) {
+		for (i = 0; i < device->gid_tbl_len[port - start_port(device)]; ++i) {
+			ret = ib_query_gid(device, port, i, &tmp_gid);
+			if (ret)
+				return ret;
+			if (!memcmp(&tmp_gid, gid, sizeof *gid)) {
+				*port_num = port;
+				if (index)
+					*index = i;
+				return 0;
+			}
+		}
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(ib_find_gid);
+
+/**
+ * ib_find_pkey - Returns the PKey table index where a specified
+ *   PKey value occurs.
+ * @device: The device to query.
+ * @port_num: The port number of the device to search for the PKey.
+ * @pkey: The PKey value to search for.
+ * @index: The index into the PKey table where the PKey was found.
+ */
+int ib_find_pkey(struct ib_device *device,
+		 u8 port_num, u16 pkey, u16 *index)
+{
+	int ret, i;
+	u16 tmp_pkey;
+
+	for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) {
+		ret = ib_query_pkey(device, port_num, i, &tmp_pkey);
+		if (ret)
+			return ret;
+
+		if (pkey == tmp_pkey) {
+			*index = i;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(ib_find_pkey);
+
 static int __init ib_core_init(void)
 {
 	int ret;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 85ccf13..6b8faca 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -675,10 +675,16 @@
 	struct ib_mad_port_private *port_priv;
 	struct ib_mad_agent_private *recv_mad_agent = NULL;
 	struct ib_device *device = mad_agent_priv->agent.device;
-	u8 port_num = mad_agent_priv->agent.port_num;
+	u8 port_num;
 	struct ib_wc mad_wc;
 	struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
 
+	if (device->node_type == RDMA_NODE_IB_SWITCH &&
+	    smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+		port_num = send_wr->wr.ud.port_num;
+	else
+		port_num = mad_agent_priv->agent.port_num;
+
 	/*
 	 * Directed route handling starts if the initial LID routed part of
 	 * a request or the ending LID routed part of a response is empty.
@@ -1839,6 +1845,7 @@
 	struct ib_mad_private *recv, *response;
 	struct ib_mad_list_head *mad_list;
 	struct ib_mad_agent_private *mad_agent;
+	int port_num;
 
 	response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL);
 	if (!response)
@@ -1872,25 +1879,50 @@
 	if (!validate_mad(&recv->mad.mad, qp_info->qp->qp_num))
 		goto out;
 
+	if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH)
+		port_num = wc->port_num;
+	else
+		port_num = port_priv->port_num;
+
 	if (recv->mad.mad.mad_hdr.mgmt_class ==
 	    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+		enum smi_forward_action retsmi;
+
 		if (smi_handle_dr_smp_recv(&recv->mad.smp,
 					   port_priv->device->node_type,
-					   port_priv->port_num,
+					   port_num,
 					   port_priv->device->phys_port_cnt) ==
 					   IB_SMI_DISCARD)
 			goto out;
 
-		if (smi_check_forward_dr_smp(&recv->mad.smp) == IB_SMI_LOCAL)
+		retsmi = smi_check_forward_dr_smp(&recv->mad.smp);
+		if (retsmi == IB_SMI_LOCAL)
 			goto local;
 
-		if (smi_handle_dr_smp_send(&recv->mad.smp,
-					   port_priv->device->node_type,
-					   port_priv->port_num) == IB_SMI_DISCARD)
-			goto out;
+		if (retsmi == IB_SMI_SEND) { /* don't forward */
+			if (smi_handle_dr_smp_send(&recv->mad.smp,
+						   port_priv->device->node_type,
+						   port_num) == IB_SMI_DISCARD)
+				goto out;
 
-		if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD)
+			if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD)
+				goto out;
+		} else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) {
+			/* forward case for switches */
+			memcpy(response, recv, sizeof(*response));
+			response->header.recv_wc.wc = &response->header.wc;
+			response->header.recv_wc.recv_buf.mad = &response->mad.mad;
+			response->header.recv_wc.recv_buf.grh = &response->grh;
+
+			if (!agent_send_response(&response->mad.mad,
+						 &response->grh, wc,
+						 port_priv->device,
+						 smi_get_fwd_port(&recv->mad.smp),
+						 qp_info->qp->qp_num))
+				response = NULL;
+
 			goto out;
+		}
 	}
 
 local:
@@ -1919,7 +1951,7 @@
 				agent_send_response(&response->mad.mad,
 						    &recv->grh, wc,
 						    port_priv->device,
-						    port_priv->port_num,
+						    port_num,
 						    qp_info->qp->qp_num);
 				goto out;
 			}
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index 1e13ab4..15b4c4d 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/core/sa.h b/drivers/infiniband/core/sa.h
index 24c93fd..b1d4bbf 100644
--- a/drivers/infiniband/core/sa.h
+++ b/drivers/infiniband/core/sa.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
  * Copyright (c) 2006 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 6469406..20ab6b3 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
  * Copyright (c) 2006 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -56,6 +56,7 @@
 struct ib_sa_sm_ah {
 	struct ib_ah        *ah;
 	struct kref          ref;
+	u16		     pkey_index;
 	u8		     src_path_mask;
 };
 
@@ -382,6 +383,13 @@
 	kref_init(&new_ah->ref);
 	new_ah->src_path_mask = (1 << port_attr.lmc) - 1;
 
+	new_ah->pkey_index = 0;
+	if (ib_find_pkey(port->agent->device, port->port_num,
+			 IB_DEFAULT_PKEY_FULL, &new_ah->pkey_index) &&
+	    ib_find_pkey(port->agent->device, port->port_num,
+			 IB_DEFAULT_PKEY_PARTIAL, &new_ah->pkey_index))
+		printk(KERN_ERR "Couldn't find index for default PKey\n");
+
 	memset(&ah_attr, 0, sizeof ah_attr);
 	ah_attr.dlid     = port_attr.sm_lid;
 	ah_attr.sl       = port_attr.sm_sl;
@@ -512,6 +520,35 @@
 }
 EXPORT_SYMBOL(ib_init_ah_from_path);
 
+static int alloc_mad(struct ib_sa_query *query, gfp_t gfp_mask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&query->port->ah_lock, flags);
+	kref_get(&query->port->sm_ah->ref);
+	query->sm_ah = query->port->sm_ah;
+	spin_unlock_irqrestore(&query->port->ah_lock, flags);
+
+	query->mad_buf = ib_create_send_mad(query->port->agent, 1,
+					    query->sm_ah->pkey_index,
+					    0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA,
+					    gfp_mask);
+	if (!query->mad_buf) {
+		kref_put(&query->sm_ah->ref, free_sm_ah);
+		return -ENOMEM;
+	}
+
+	query->mad_buf->ah = query->sm_ah->ah;
+
+	return 0;
+}
+
+static void free_mad(struct ib_sa_query *query)
+{
+	ib_free_send_mad(query->mad_buf);
+	kref_put(&query->sm_ah->ref, free_sm_ah);
+}
+
 static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
 {
 	unsigned long flags;
@@ -548,20 +585,11 @@
 	query->mad_buf->context[0] = query;
 	query->id = id;
 
-	spin_lock_irqsave(&query->port->ah_lock, flags);
-	kref_get(&query->port->sm_ah->ref);
-	query->sm_ah = query->port->sm_ah;
-	spin_unlock_irqrestore(&query->port->ah_lock, flags);
-
-	query->mad_buf->ah = query->sm_ah->ah;
-
 	ret = ib_post_send_mad(query->mad_buf, NULL);
 	if (ret) {
 		spin_lock_irqsave(&idr_lock, flags);
 		idr_remove(&query_idr, id);
 		spin_unlock_irqrestore(&idr_lock, flags);
-
-		kref_put(&query->sm_ah->ref, free_sm_ah);
 	}
 
 	/*
@@ -647,13 +675,10 @@
 	if (!query)
 		return -ENOMEM;
 
-	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
-						     0, IB_MGMT_SA_HDR,
-						     IB_MGMT_SA_DATA, gfp_mask);
-	if (!query->sa_query.mad_buf) {
-		ret = -ENOMEM;
+	query->sa_query.port     = port;
+	ret = alloc_mad(&query->sa_query, gfp_mask);
+	if (ret)
 		goto err1;
-	}
 
 	ib_sa_client_get(client);
 	query->sa_query.client = client;
@@ -665,7 +690,6 @@
 
 	query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
 	query->sa_query.release  = ib_sa_path_rec_release;
-	query->sa_query.port     = port;
 	mad->mad_hdr.method	 = IB_MGMT_METHOD_GET;
 	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_PATH_REC);
 	mad->sa_hdr.comp_mask	 = comp_mask;
@@ -683,7 +707,7 @@
 err2:
 	*sa_query = NULL;
 	ib_sa_client_put(query->sa_query.client);
-	ib_free_send_mad(query->sa_query.mad_buf);
+	free_mad(&query->sa_query);
 
 err1:
 	kfree(query);
@@ -773,13 +797,10 @@
 	if (!query)
 		return -ENOMEM;
 
-	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
-						     0, IB_MGMT_SA_HDR,
-						     IB_MGMT_SA_DATA, gfp_mask);
-	if (!query->sa_query.mad_buf) {
-		ret = -ENOMEM;
+	query->sa_query.port     = port;
+	ret = alloc_mad(&query->sa_query, gfp_mask);
+	if (ret)
 		goto err1;
-	}
 
 	ib_sa_client_get(client);
 	query->sa_query.client = client;
@@ -791,7 +812,6 @@
 
 	query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
 	query->sa_query.release  = ib_sa_service_rec_release;
-	query->sa_query.port     = port;
 	mad->mad_hdr.method	 = method;
 	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
 	mad->sa_hdr.comp_mask	 = comp_mask;
@@ -810,7 +830,7 @@
 err2:
 	*sa_query = NULL;
 	ib_sa_client_put(query->sa_query.client);
-	ib_free_send_mad(query->sa_query.mad_buf);
+	free_mad(&query->sa_query);
 
 err1:
 	kfree(query);
@@ -869,13 +889,10 @@
 	if (!query)
 		return -ENOMEM;
 
-	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
-						     0, IB_MGMT_SA_HDR,
-						     IB_MGMT_SA_DATA, gfp_mask);
-	if (!query->sa_query.mad_buf) {
-		ret = -ENOMEM;
+	query->sa_query.port     = port;
+	ret = alloc_mad(&query->sa_query, gfp_mask);
+	if (ret)
 		goto err1;
-	}
 
 	ib_sa_client_get(client);
 	query->sa_query.client = client;
@@ -887,7 +904,6 @@
 
 	query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
 	query->sa_query.release  = ib_sa_mcmember_rec_release;
-	query->sa_query.port     = port;
 	mad->mad_hdr.method	 = method;
 	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
 	mad->sa_hdr.comp_mask	 = comp_mask;
@@ -906,7 +922,7 @@
 err2:
 	*sa_query = NULL;
 	ib_sa_client_put(query->sa_query.client);
-	ib_free_send_mad(query->sa_query.mad_buf);
+	free_mad(&query->sa_query);
 
 err1:
 	kfree(query);
@@ -939,8 +955,7 @@
 	idr_remove(&query_idr, query->id);
 	spin_unlock_irqrestore(&idr_lock, flags);
 
-	ib_free_send_mad(mad_send_wc->send_buf);
-	kref_put(&query->sm_ah->ref, free_sm_ah);
+	free_mad(query);
 	ib_sa_client_put(query->client);
 	query->release(query);
 }
diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c
index 2bca753..8723675 100644
--- a/drivers/infiniband/core/smi.c
+++ b/drivers/infiniband/core/smi.c
@@ -192,7 +192,7 @@
 			}
 			/* smp->hop_ptr updated when sending */
 			return (node_type == RDMA_NODE_IB_SWITCH ?
-				IB_SMI_HANDLE: IB_SMI_DISCARD);
+				IB_SMI_HANDLE : IB_SMI_DISCARD);
 		}
 
 		/* C14-13:4 -- hop_ptr = 0 -> give to SM */
@@ -211,7 +211,7 @@
 	if (!ib_get_smp_direction(smp)) {
 		/* C14-9:2 -- intermediate hop */
 		if (hop_ptr && hop_ptr < hop_cnt)
-			return IB_SMI_SEND;
+			return IB_SMI_FORWARD;
 
 		/* C14-9:3 -- at the end of the DR segment of path */
 		if (hop_ptr == hop_cnt)
@@ -224,7 +224,7 @@
 	} else {
 		/* C14-13:2  -- intermediate hop */
 		if (2 <= hop_ptr && hop_ptr <= hop_cnt)
-			return IB_SMI_SEND;
+			return IB_SMI_FORWARD;
 
 		/* C14-13:3 -- at the end of the DR segment of path */
 		if (hop_ptr == 1)
@@ -233,3 +233,13 @@
 	}
 	return IB_SMI_LOCAL;
 }
+
+/*
+ * Return the forwarding port number from initial_path for outgoing SMP and
+ * from return_path for returning SMP
+ */
+int smi_get_fwd_port(struct ib_smp *smp)
+{
+	return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
+		smp->return_path[smp->hop_ptr-1]);
+}
diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h
index 9a4b349..1cfc298 100644
--- a/drivers/infiniband/core/smi.h
+++ b/drivers/infiniband/core/smi.h
@@ -48,10 +48,12 @@
 enum smi_forward_action {
 	IB_SMI_LOCAL,	/* SMP should be completed up the stack */
 	IB_SMI_SEND,	/* received DR SMP should be forwarded to the send queue */
+	IB_SMI_FORWARD	/* SMP should be forwarded (for switches only) */
 };
 
 enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
 				       int port_num, int phys_port_cnt);
+int smi_get_fwd_port(struct ib_smp *smp);
 extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp);
 extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
 					      u8 node_type, int port_num);
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 08c299e..70b77ae 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -311,7 +311,7 @@
 		return sprintf(buf, "N/A (no PMA)\n");
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
-	out_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
 	if (!in_mad || !out_mad) {
 		ret = -ENOMEM;
 		goto out;
@@ -479,7 +479,6 @@
 
 		element->attr.attr.name  = element->name;
 		element->attr.attr.mode  = S_IRUGO;
-		element->attr.attr.owner = THIS_MODULE;
 		element->attr.show       = show;
 		element->index		 = i;
 
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 2586a3e..424983f 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -823,7 +823,6 @@
 	param.private_data_len    = cmd.len;
 	param.responder_resources = cmd.responder_resources;
 	param.initiator_depth     = cmd.initiator_depth;
-	param.target_ack_delay    = cmd.target_ack_delay;
 	param.failover_accepted   = cmd.failover_accepted;
 	param.flow_control        = cmd.flow_control;
 	param.rnr_retry_count     = cmd.rnr_retry_count;
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index f32ca5f..26d0470 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -36,6 +36,7 @@
 
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <linux/sched.h>
 
 #include "uverbs.h"
 
@@ -120,6 +121,7 @@
 
 	cur_base = addr & PAGE_MASK;
 
+	ret = 0;
 	while (npages) {
 		ret = get_user_pages(current, current->mm, cur_base,
 				     min_t(int, npages,
@@ -209,8 +211,10 @@
 	__ib_umem_release(umem->context->device, umem, 1);
 
 	mm = get_task_mm(current);
-	if (!mm)
+	if (!mm) {
+		kfree(umem);
 		return;
+	}
 
 	diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
 
@@ -222,13 +226,15 @@
 	 * up here and not be able to take the mmap_sem.  In that case
 	 * we defer the vm_locked accounting to the system workqueue.
 	 */
-	if (context->closing && !down_write_trylock(&mm->mmap_sem)) {
-		INIT_WORK(&umem->work, ib_umem_account);
-		umem->mm   = mm;
-		umem->diff = diff;
+	if (context->closing) {
+		if (!down_write_trylock(&mm->mmap_sem)) {
+			INIT_WORK(&umem->work, ib_umem_account);
+			umem->mm   = mm;
+			umem->diff = diff;
 
-		schedule_work(&umem->work);
-		return;
+			schedule_work(&umem->work);
+			return;
+		}
 	} else
 		down_write(&mm->mmap_sem);
 
diff --git a/drivers/infiniband/hw/amso1100/Kconfig b/drivers/infiniband/hw/amso1100/Kconfig
index 809cb14..e6ce5f2 100644
--- a/drivers/infiniband/hw/amso1100/Kconfig
+++ b/drivers/infiniband/hw/amso1100/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_AMSO1100
 	tristate "Ammasso 1100 HCA support"
-	depends on PCI && INET && INFINIBAND
+	depends on PCI && INET
 	---help---
 	  This is a low-level driver for the Ammasso 1100 host
 	  channel adapter (HCA).
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 58bc272..0aecea6 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -672,7 +672,7 @@
 	 * rdma interface.
 	 */
 	in_dev = in_dev_get(netdev);
-	in_dev->cnf.arp_ignore = 1;
+	IN_DEV_CONF_SET(in_dev, ARP_IGNORE, 1);
 	in_dev_put(in_dev);
 
 	return 0;
diff --git a/drivers/infiniband/hw/cxgb3/Kconfig b/drivers/infiniband/hw/cxgb3/Kconfig
index 77977f55dc..2acec3f 100644
--- a/drivers/infiniband/hw/cxgb3/Kconfig
+++ b/drivers/infiniband/hw/cxgb3/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_CXGB3
 	tristate "Chelsio RDMA Driver"
-	depends on CHELSIO_T3 && INFINIBAND && INET
+	depends on CHELSIO_T3 && INET
 	select GENERIC_ALLOCATOR
 	---help---
 	  This is an iWARP/RDMA driver for the Chelsio T3 1GbE and
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 76049af..1518b41 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -144,7 +144,7 @@
 	}
 	wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
 	memset(wqe, 0, sizeof(*wqe));
-	build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 3, 1, qpid, 7);
+	build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 3, 0, qpid, 7);
 	wqe->flags = cpu_to_be32(MODQP_WRITE_EC);
 	sge_cmd = qpid << 8 | 3;
 	wqe->sge_cmd = cpu_to_be64(sge_cmd);
@@ -548,7 +548,7 @@
 			V_EC_UP_TOKEN(T3_CTL_QP_TID) | F_EC_VALID)) << 32;
 	wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
 	memset(wqe, 0, sizeof(*wqe));
-	build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 0, 1,
+	build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 0, 0,
 		       T3_CTL_QP_TID, 7);
 	wqe->flags = cpu_to_be32(MODQP_WRITE_EC);
 	sge_cmd = (3ULL << 56) | FW_RI_SGEEC_START << 8 | 3;
@@ -833,7 +833,7 @@
 	wqe->ird = cpu_to_be32(attr->ird);
 	wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);
 	wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size);
-	wqe->rsvd = 0;
+	wqe->irs = cpu_to_be32(attr->irs);
 	skb->priority = 0;	/* 0=>ToeQ; 1=>CtrlQ */
 	return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
 }
diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
index ff7290e..c84d4ac 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
@@ -294,6 +294,7 @@
 	u64 qp_dma_addr;
 	u32 qp_dma_size;
 	u32 flags;
+	u32 irs;
 };
 
 struct t3_rdma_init_wr {
@@ -314,7 +315,7 @@
 	__be32 ird;
 	__be64 qp_dma_addr;	/* 7 */
 	__be32 qp_dma_size;	/* 8 */
-	u32 rsvd;
+	u32 irs;
 };
 
 struct t3_genbit {
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index b2faff5..3b41dc0 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -254,8 +254,6 @@
 	cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
 	dst_release(ep->dst);
 	l2t_release(L2DATA(ep->com.tdev), ep->l2t);
-	if (ep->com.tdev->type == T3B)
-		release_tid(ep->com.tdev, ep->hwtid, NULL);
 	put_ep(&ep->com);
 }
 
@@ -515,7 +513,7 @@
 	req->len = htonl(len);
 	req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
 			   V_TX_SNDBUF(snd_win>>15));
-	req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+	req->flags = htonl(F_TX_INIT);
 	req->sndseq = htonl(ep->snd_seq);
 	BUG_ON(ep->mpa_skb);
 	ep->mpa_skb = skb;
@@ -566,7 +564,7 @@
 	req->len = htonl(mpalen);
 	req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
 			   V_TX_SNDBUF(snd_win>>15));
-	req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+	req->flags = htonl(F_TX_INIT);
 	req->sndseq = htonl(ep->snd_seq);
 	BUG_ON(ep->mpa_skb);
 	ep->mpa_skb = skb;
@@ -618,7 +616,7 @@
 	req->len = htonl(len);
 	req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
 			   V_TX_SNDBUF(snd_win>>15));
-	req->flags = htonl(F_TX_MORE | F_TX_IMM_ACK | F_TX_INIT);
+	req->flags = htonl(F_TX_INIT);
 	req->sndseq = htonl(ep->snd_seq);
 	ep->mpa_skb = skb;
 	state_set(&ep->com, MPA_REP_SENT);
@@ -641,6 +639,7 @@
 	cxgb3_insert_tid(ep->com.tdev, &t3c_client, ep, tid);
 
 	ep->snd_seq = ntohl(req->snd_isn);
+	ep->rcv_seq = ntohl(req->rcv_isn);
 
 	set_emss(ep, ntohs(req->tcp_opt));
 
@@ -1023,6 +1022,9 @@
 	skb_pull(skb, sizeof(*hdr));
 	skb_trim(skb, dlen);
 
+	ep->rcv_seq += dlen;
+	BUG_ON(ep->rcv_seq != (ntohl(hdr->seq) + dlen));
+
 	switch (state_read(&ep->com)) {
 	case MPA_REQ_SENT:
 		process_mpa_reply(ep, skb);
@@ -1060,7 +1062,6 @@
 	struct iwch_ep *ep = ctx;
 	struct cpl_wr_ack *hdr = cplhdr(skb);
 	unsigned int credits = ntohs(hdr->credits);
-	enum iwch_qp_attr_mask  mask;
 
 	PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
 
@@ -1072,30 +1073,6 @@
 	ep->mpa_skb = NULL;
 	dst_confirm(ep->dst);
 	if (state_read(&ep->com) == MPA_REP_SENT) {
-		struct iwch_qp_attributes attrs;
-
-		/* bind QP to EP and move to RTS */
-		attrs.mpa_attr = ep->mpa_attr;
-		attrs.max_ird = ep->ord;
-		attrs.max_ord = ep->ord;
-		attrs.llp_stream_handle = ep;
-		attrs.next_state = IWCH_QP_STATE_RTS;
-
-		/* bind QP and TID with INIT_WR */
-		mask = IWCH_QP_ATTR_NEXT_STATE |
-				     IWCH_QP_ATTR_LLP_STREAM_HANDLE |
-				     IWCH_QP_ATTR_MPA_ATTR |
-				     IWCH_QP_ATTR_MAX_IRD |
-				     IWCH_QP_ATTR_MAX_ORD;
-
-		ep->com.rpl_err = iwch_modify_qp(ep->com.qp->rhp,
-				     ep->com.qp, mask, &attrs, 1);
-
-		if (!ep->com.rpl_err) {
-			state_set(&ep->com, FPDU_MODE);
-			established_upcall(ep);
-		}
-
 		ep->com.rpl_done = 1;
 		PDBG("waking up ep %p\n", ep);
 		wake_up(&ep->com.waitq);
@@ -1124,6 +1101,15 @@
 	return CPL_RET_BUF_DONE;
 }
 
+/*
+ * Return whether a failed active open has allocated a TID
+ */
+static inline int act_open_has_tid(int status)
+{
+	return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST &&
+	       status != CPL_ERR_ARP_MISS;
+}
+
 static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 {
 	struct iwch_ep *ep = ctx;
@@ -1133,7 +1119,7 @@
 	     status2errno(rpl->status));
 	connect_reply_upcall(ep, status2errno(rpl->status));
 	state_set(&ep->com, DEAD);
-	if (ep->com.tdev->type == T3B)
+	if (ep->com.tdev->type == T3B && act_open_has_tid(rpl->status))
 		release_tid(ep->com.tdev, GET_TID(rpl), NULL);
 	cxgb3_free_atid(ep->com.tdev, ep->atid);
 	dst_release(ep->dst);
@@ -1378,6 +1364,7 @@
 
 	PDBG("%s ep %p\n", __FUNCTION__, ep);
 	ep->snd_seq = ntohl(req->snd_isn);
+	ep->rcv_seq = ntohl(req->rcv_isn);
 
 	set_emss(ep, ntohs(req->tcp_opt));
 
@@ -1485,6 +1472,13 @@
 	int ret;
 	int state;
 
+	if (is_neg_adv_abort(req->status)) {
+		PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
+		     ep->hwtid);
+		t3_l2t_send_event(ep->com.tdev, ep->l2t);
+		return CPL_RET_BUF_DONE;
+	}
+
 	/*
 	 * We get 2 peer aborts from the HW.  The first one must
 	 * be ignored except for scribbling that we need one more.
@@ -1494,13 +1488,6 @@
 		return CPL_RET_BUF_DONE;
 	}
 
-	if (is_neg_adv_abort(req->status)) {
-		PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
-		     ep->hwtid);
-		t3_l2t_send_event(ep->com.tdev, ep->l2t);
-		return CPL_RET_BUF_DONE;
-	}
-
 	state = state_read(&ep->com);
 	PDBG("%s ep %p state %u\n", __FUNCTION__, ep, state);
 	switch (state) {
@@ -1732,10 +1719,8 @@
 	struct iwch_qp *qp = get_qhp(h, conn_param->qpn);
 
 	PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
-	if (state_read(&ep->com) == DEAD) {
-		put_ep(&ep->com);
+	if (state_read(&ep->com) == DEAD)
 		return -ECONNRESET;
-	}
 
 	BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
 	BUG_ON(!qp);
@@ -1755,17 +1740,8 @@
 	ep->ird = conn_param->ird;
 	ep->ord = conn_param->ord;
 	PDBG("%s %d ird %d ord %d\n", __FUNCTION__, __LINE__, ep->ird, ep->ord);
+
 	get_ep(&ep->com);
-	err = send_mpa_reply(ep, conn_param->private_data,
-			     conn_param->private_data_len);
-	if (err) {
-		ep->com.cm_id = NULL;
-		ep->com.qp = NULL;
-		cm_id->rem_ref(cm_id);
-		abort_connection(ep, NULL, GFP_KERNEL);
-		put_ep(&ep->com);
-		return err;
-	}
 
 	/* bind QP to EP and move to RTS */
 	attrs.mpa_attr = ep->mpa_attr;
@@ -1783,16 +1759,28 @@
 
 	err = iwch_modify_qp(ep->com.qp->rhp,
 			     ep->com.qp, mask, &attrs, 1);
+	if (err)
+		goto err;
 
-	if (err) {
-		ep->com.cm_id = NULL;
-		ep->com.qp = NULL;
-		cm_id->rem_ref(cm_id);
-		abort_connection(ep, NULL, GFP_KERNEL);
-	} else {
-		state_set(&ep->com, FPDU_MODE);
-		established_upcall(ep);
-	}
+	err = send_mpa_reply(ep, conn_param->private_data,
+			     conn_param->private_data_len);
+	if (err)
+		goto err;
+
+	/* wait for wr_ack */
+	wait_event(ep->com.waitq, ep->com.rpl_done);
+	err = ep->com.rpl_err;
+	if (err)
+		goto err;
+
+	state_set(&ep->com, FPDU_MODE);
+	established_upcall(ep);
+	put_ep(&ep->com);
+	return 0;
+err:
+	ep->com.cm_id = NULL;
+	ep->com.qp = NULL;
+	cm_id->rem_ref(cm_id);
 	put_ep(&ep->com);
 	return err;
 }
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
index 21a388c..6107e7c 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
@@ -175,6 +175,7 @@
 	unsigned int atid;
 	u32 hwtid;
 	u32 snd_seq;
+	u32 rcv_seq;
 	struct l2t_entry *l2t;
 	struct dst_entry *dst;
 	struct sk_buff *mpa_skb;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index e7c2c39..f0c7775 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1163,9 +1163,10 @@
 	dev->ibdev.post_recv = iwch_post_receive;
 
 
-	dev->ibdev.iwcm =
-	    (struct iw_cm_verbs *) kmalloc(sizeof(struct iw_cm_verbs),
-					   GFP_KERNEL);
+	dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
+	if (!dev->ibdev.iwcm)
+		return -ENOMEM;
+
 	dev->ibdev.iwcm->connect = iwch_connect;
 	dev->ibdev.iwcm->accept = iwch_accept_cr;
 	dev->ibdev.iwcm->reject = iwch_reject_cr;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 714dddb..dd89b6b 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -628,9 +628,9 @@
 	/* immediate data starts here. */
 	term = (struct terminate_message *)wqe->send.sgl;
 	build_term_codes(rsp_msg, &term->layer_etype, &term->ecode);
-	build_fw_riwrh((void *)wqe, T3_WR_SEND,
-		       T3_COMPLETION_FLAG | T3_NOTIFY_FLAG, 1,
-		       qhp->ep->hwtid, 5);
+	wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_SEND) |
+			 V_FW_RIWR_FLAGS(T3_COMPLETION_FLAG | T3_NOTIFY_FLAG));
+	wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid));
 	skb->priority = CPL_PRIORITY_DATA;
 	return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
 }
@@ -732,6 +732,7 @@
 	init_attr.qp_dma_addr = qhp->wq.dma_addr;
 	init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
 	init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
+	init_attr.irs = qhp->ep->rcv_seq;
 	PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
 	     "flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
 	     init_attr.rq_addr, init_attr.rq_size,
diff --git a/drivers/infiniband/hw/ehca/Kconfig b/drivers/infiniband/hw/ehca/Kconfig
index 1a85459..59f807d 100644
--- a/drivers/infiniband/hw/ehca/Kconfig
+++ b/drivers/infiniband/hw/ehca/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_EHCA
 	tristate "eHCA support"
-	depends on IBMEBUS && INFINIBAND
+	depends on IBMEBUS
 	---help---
 	This driver supports the IBM pSeries eHCA InfiniBand adapter.
 
diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
index 0d6e2c4..3cd6bf3 100644
--- a/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/drivers/infiniband/hw/ehca/ehca_av.c
@@ -118,7 +118,7 @@
 		}
 		memcpy(&av->av.grh.word_1, &gid, sizeof(gid));
 	}
-	av->av.pmtu = EHCA_MAX_MTU;
+	av->av.pmtu = shca->max_mtu;
 
 	/* dgid comes in grh.word_3 */
 	memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid,
@@ -137,6 +137,8 @@
 	struct ehca_av *av;
 	struct ehca_ud_av new_ehca_av;
 	struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+	struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca,
+					      ib_device);
 	u32 cur_pid = current->tgid;
 
 	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
@@ -192,7 +194,7 @@
 		memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid));
 	}
 
-	new_ehca_av.pmtu = EHCA_MAX_MTU;
+	new_ehca_av.pmtu = shca->max_mtu;
 
 	memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid,
 	       sizeof(ah_attr->grh.dgid));
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 1d286d3..daf823e 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -5,6 +5,7 @@
  *
  *  Authors: Heiko J Schick <schickhj@de.ibm.com>
  *           Christoph Raisch <raisch@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *
  *  Copyright (c) 2005 IBM Corporation
  *
@@ -86,11 +87,17 @@
 	struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
 };
 
+struct ehca_sma_attr {
+	u16 lid, lmc, sm_sl, sm_lid;
+	u16 pkey_tbl_len, pkeys[16];
+};
+
 struct ehca_sport {
 	struct ib_cq *ibcq_aqp1;
 	struct ib_qp *ibqp_aqp1;
 	enum ib_rate  rate;
 	enum ib_port_state port_state;
+	struct ehca_sma_attr saved_attr;
 };
 
 struct ehca_shca {
@@ -107,6 +114,8 @@
 	struct ehca_pd *pd;
 	struct h_galpas galpas;
 	struct mutex modify_mutex;
+	u64 hca_cap;
+	int max_mtu;
 };
 
 struct ehca_pd {
@@ -115,9 +124,20 @@
 	u32 ownpid;
 };
 
+enum ehca_ext_qp_type {
+	EQPT_NORMAL    = 0,
+	EQPT_LLQP      = 1,
+	EQPT_SRQBASE   = 2,
+	EQPT_SRQ       = 3,
+};
+
 struct ehca_qp {
-	struct ib_qp ib_qp;
+	union {
+		struct ib_qp ib_qp;
+		struct ib_srq ib_srq;
+	};
 	u32 qp_type;
+	enum ehca_ext_qp_type ext_type;
 	struct ipz_queue ipz_squeue;
 	struct ipz_queue ipz_rqueue;
 	struct h_galpas galpas;
@@ -140,6 +160,10 @@
 	u32 mm_count_galpa;
 };
 
+#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
+#define HAS_SQ(qp) (qp->ext_type != EQPT_SRQ)
+#define HAS_RQ(qp) (qp->ext_type != EQPT_SRQBASE)
+
 /* must be power of 2 */
 #define QP_HASHTAB_LEN 8
 
@@ -156,8 +180,8 @@
 	spinlock_t cb_lock;
 	struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
 	struct list_head entry;
-	u32 nr_callbacks; /* #events assigned to cpu by scaling code */
-	u32 nr_events;    /* #events seen */
+	u32 nr_callbacks;   /* #events assigned to cpu by scaling code */
+	atomic_t nr_events; /* #events seen */
 	wait_queue_head_t wait_completion;
 	spinlock_t task_lock;
 	u32 ownpid;
@@ -275,9 +299,8 @@
 int ehca_init_mrmw_cache(void);
 void ehca_cleanup_mrmw_cache(void);
 
-extern spinlock_t ehca_qp_idr_lock;
-extern spinlock_t ehca_cq_idr_lock;
-extern spinlock_t hcall_lock;
+extern rwlock_t ehca_qp_idr_lock;
+extern rwlock_t ehca_cq_idr_lock;
 extern struct idr ehca_qp_idr;
 extern struct idr ehca_cq_idr;
 
@@ -305,6 +328,7 @@
 	u32 qp_num;
 	u32 token;
 	u32 qp_type;
+	u32 ext_type;
 	u32 qkey;
 	/* qp_num assigned by ehca: sqp0/1 may have got different numbers */
 	u32 real_qp_num;
@@ -320,14 +344,42 @@
 	struct ipz_eq_handle eq_handle;
 };
 
+enum ehca_service_type {
+	ST_RC  = 0,
+	ST_UC  = 1,
+	ST_RD  = 2,
+	ST_UD  = 3,
+};
+
+enum ehca_ll_comp_flags {
+	LLQP_SEND_COMP = 0x20,
+	LLQP_RECV_COMP = 0x40,
+	LLQP_COMP_MASK = 0x60,
+};
+
 struct ehca_alloc_qp_parms {
-	int servicetype;
+/* input parameters */
+	enum ehca_service_type servicetype;
 	int sigtype;
-	int daqp_ctrl;
-	int max_send_sge;
-	int max_recv_sge;
+	enum ehca_ext_qp_type ext_type;
+	enum ehca_ll_comp_flags ll_comp_flags;
+
+	int max_send_wr, max_recv_wr;
+	int max_send_sge, max_recv_sge;
 	int ud_av_l_key_ctl;
 
+	u32 token;
+	struct ipz_eq_handle eq_handle;
+	struct ipz_pd pd;
+	struct ipz_cq_handle send_cq_handle, recv_cq_handle;
+
+	u32 srq_qpn, srq_token, srq_limit;
+
+/* output parameters */
+	u32 real_qp_num;
+	struct ipz_qp_handle qp_handle;
+	struct h_galpas galpas;
+
 	u16 act_nr_send_wqes;
 	u16 act_nr_recv_wqes;
 	u8  act_nr_recv_sges;
@@ -335,9 +387,6 @@
 
 	u32 nr_rq_pages;
 	u32 nr_sq_pages;
-
-	struct ipz_eq_handle ipz_eq_handle;
-	struct ipz_pd pd;
 };
 
 int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp);
diff --git a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
index 5665f21..fb3df5c 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
@@ -228,8 +228,8 @@
 #define MQPCB_QP_NUMBER                         EHCA_BMASK_IBM(8,31)
 #define MQPCB_MASK_QP_ENABLE                    EHCA_BMASK_IBM(48,48)
 #define MQPCB_QP_ENABLE                         EHCA_BMASK_IBM(31,31)
-#define MQPCB_MASK_CURR_SQR_LIMIT               EHCA_BMASK_IBM(49,49)
-#define MQPCB_CURR_SQR_LIMIT                    EHCA_BMASK_IBM(15,31)
+#define MQPCB_MASK_CURR_SRQ_LIMIT               EHCA_BMASK_IBM(49,49)
+#define MQPCB_CURR_SRQ_LIMIT                    EHCA_BMASK_IBM(16,31)
 #define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG       EHCA_BMASK_IBM(50,50)
 #define MQPCB_MASK_SHARED_RQ_HNDL               EHCA_BMASK_IBM(51,51)
 
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 67f0670..01d4a14 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -56,11 +56,11 @@
 {
 	unsigned int qp_num = qp->real_qp_num;
 	unsigned int key = qp_num & (QP_HASHTAB_LEN-1);
-	unsigned long spl_flags;
+	unsigned long flags;
 
-	spin_lock_irqsave(&cq->spinlock, spl_flags);
+	spin_lock_irqsave(&cq->spinlock, flags);
 	hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]);
-	spin_unlock_irqrestore(&cq->spinlock, spl_flags);
+	spin_unlock_irqrestore(&cq->spinlock, flags);
 
 	ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x",
 		 cq->cq_number, qp_num);
@@ -74,9 +74,9 @@
 	unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
 	struct hlist_node *iter;
 	struct ehca_qp *qp;
-	unsigned long spl_flags;
+	unsigned long flags;
 
-	spin_lock_irqsave(&cq->spinlock, spl_flags);
+	spin_lock_irqsave(&cq->spinlock, flags);
 	hlist_for_each(iter, &cq->qp_hashtab[key]) {
 		qp = hlist_entry(iter, struct ehca_qp, list_entries);
 		if (qp->real_qp_num == real_qp_num) {
@@ -88,7 +88,7 @@
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&cq->spinlock, spl_flags);
+	spin_unlock_irqrestore(&cq->spinlock, flags);
 	if (ret)
 		ehca_err(cq->ib_cq.device,
 			 "qp not found cq_num=%x real_qp_num=%x",
@@ -146,6 +146,7 @@
 	spin_lock_init(&my_cq->spinlock);
 	spin_lock_init(&my_cq->cb_lock);
 	spin_lock_init(&my_cq->task_lock);
+	atomic_set(&my_cq->nr_events, 0);
 	init_waitqueue_head(&my_cq->wait_completion);
 	my_cq->ownpid = current->tgid;
 
@@ -162,9 +163,9 @@
 			goto create_cq_exit1;
 		}
 
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+		write_lock_irqsave(&ehca_cq_idr_lock, flags);
 		ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token);
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+		write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 	} while (ret == -EAGAIN);
 
@@ -293,9 +294,9 @@
 			 "cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret);
 
 create_cq_exit2:
-	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+	write_lock_irqsave(&ehca_cq_idr_lock, flags);
 	idr_remove(&ehca_cq_idr, my_cq->token);
-	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+	write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 create_cq_exit1:
 	kmem_cache_free(cq_cache, my_cq);
@@ -303,16 +304,6 @@
 	return cq;
 }
 
-static int get_cq_nr_events(struct ehca_cq *my_cq)
-{
-	int ret;
-	unsigned long flags;
-	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-	ret = my_cq->nr_events;
-	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-	return ret;
-}
-
 int ehca_destroy_cq(struct ib_cq *cq)
 {
 	u64 h_ret;
@@ -339,17 +330,18 @@
 		}
 	}
 
-	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-	while (my_cq->nr_events) {
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-		wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq));
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-		/* recheck nr_events to assure no cqe has just arrived */
-	}
-
+	/*
+	 * remove the CQ from the idr first to make sure
+	 * no more interrupt tasklets will touch this CQ
+	 */
+	write_lock_irqsave(&ehca_cq_idr_lock, flags);
 	idr_remove(&ehca_cq_idr, my_cq->token);
-	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+	write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
+	/* now wait until all pending events have completed */
+	wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
+
+	/* nobody's using our CQ any longer -- we can destroy it */
 	h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
 	if (h_ret == H_R_STATE) {
 		/* cq in err: read err data and destroy it forcibly */
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index 32b55a4..bbd3c6a 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -45,11 +45,25 @@
 
 int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
 {
-	int ret = 0;
+	int i, ret = 0;
 	struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
 					      ib_device);
 	struct hipz_query_hca *rblock;
 
+	static const u32 cap_mapping[] = {
+		IB_DEVICE_RESIZE_MAX_WR,      HCA_CAP_WQE_RESIZE,
+		IB_DEVICE_BAD_PKEY_CNTR,      HCA_CAP_BAD_P_KEY_CTR,
+		IB_DEVICE_BAD_QKEY_CNTR,      HCA_CAP_Q_KEY_VIOL_CTR,
+		IB_DEVICE_RAW_MULTI,          HCA_CAP_RAW_PACKET_MCAST,
+		IB_DEVICE_AUTO_PATH_MIG,      HCA_CAP_AUTO_PATH_MIG,
+		IB_DEVICE_CHANGE_PHY_PORT,    HCA_CAP_SQD_RTS_PORT_CHANGE,
+		IB_DEVICE_UD_AV_PORT_ENFORCE, HCA_CAP_AH_PORT_NR_CHECK,
+		IB_DEVICE_CURR_QP_STATE_MOD,  HCA_CAP_CUR_QP_STATE_MOD,
+		IB_DEVICE_SHUTDOWN_PORT,      HCA_CAP_SHUTDOWN_PORT,
+		IB_DEVICE_INIT_TYPE,          HCA_CAP_INIT_TYPE,
+		IB_DEVICE_PORT_ACTIVE_EVENT,  HCA_CAP_PORT_ACTIVE_EVENT,
+	};
+
 	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
 		ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
@@ -96,6 +110,13 @@
 	props->max_total_mcast_qp_attach
 		= min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX);
 
+	/* translate device capabilities */
+	props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
+		IB_DEVICE_RC_RNR_NAK_GEN | IB_DEVICE_N_NOTIFY_CQ;
+	for (i = 0; i < ARRAY_SIZE(cap_mapping); i += 2)
+		if (rblock->hca_cap_indicators & cap_mapping[i + 1])
+			props->device_cap_flags |= cap_mapping[i];
+
 query_device1:
 	ehca_free_fw_ctrlblock(rblock);
 
@@ -172,6 +193,40 @@
 	return ret;
 }
 
+int ehca_query_sma_attr(struct ehca_shca *shca,
+			u8 port, struct ehca_sma_attr *attr)
+{
+	int ret = 0;
+	struct hipz_query_port *rblock;
+
+	rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+	if (!rblock) {
+		ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+		return -ENOMEM;
+	}
+
+	if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+		ehca_err(&shca->ib_device, "Can't query port properties");
+		ret = -EINVAL;
+		goto query_sma_attr1;
+	}
+
+	memset(attr, 0, sizeof(struct ehca_sma_attr));
+
+	attr->lid    = rblock->lid;
+	attr->lmc    = rblock->lmc;
+	attr->sm_sl  = rblock->sm_sl;
+	attr->sm_lid = rblock->sm_lid;
+
+	attr->pkey_tbl_len = rblock->pkey_tbl_len;
+	memcpy(attr->pkeys, rblock->pkey_entries, sizeof(attr->pkeys));
+
+query_sma_attr1:
+	ehca_free_fw_ctrlblock(rblock);
+
+	return ret;
+}
+
 int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
 {
 	int ret = 0;
@@ -261,7 +316,7 @@
 	}
 
 	if (mutex_lock_interruptible(&shca->modify_mutex))
-                return -ERESTARTSYS;
+		return -ERESTARTSYS;
 
 	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
@@ -290,7 +345,7 @@
 	ehca_free_fw_ctrlblock(rblock);
 
 modify_port1:
-        mutex_unlock(&shca->modify_mutex);
+	mutex_unlock(&shca->modify_mutex);
 
 	return ret;
 }
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 100329b..96eba38 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -5,6 +5,8 @@
  *
  *  Authors: Heiko J Schick <schickhj@de.ibm.com>
  *           Khadija Souissi <souissi@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *
  *  Copyright (c) 2005 IBM Corporation
  *
@@ -59,6 +61,7 @@
 #define NEQE_EVENT_CODE        EHCA_BMASK_IBM(2,7)
 #define NEQE_PORT_NUMBER       EHCA_BMASK_IBM(8,15)
 #define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16)
+#define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16,16)
 
 #define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52,63)
 #define ERROR_DATA_TYPE        EHCA_BMASK_IBM(0,7)
@@ -178,12 +181,11 @@
 {
 	struct ib_event event;
 	struct ehca_qp *qp;
-	unsigned long flags;
 	u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);
 
-	spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+	read_lock(&ehca_qp_idr_lock);
 	qp = idr_find(&ehca_qp_idr, token);
-	spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+	read_unlock(&ehca_qp_idr_lock);
 
 
 	if (!qp)
@@ -207,18 +209,22 @@
 			      u64 eqe)
 {
 	struct ehca_cq *cq;
-	unsigned long flags;
 	u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe);
 
-	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+	read_lock(&ehca_cq_idr_lock);
 	cq = idr_find(&ehca_cq_idr, token);
-	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+	if (cq)
+		atomic_inc(&cq->nr_events);
+	read_unlock(&ehca_cq_idr_lock);
 
 	if (!cq)
 		return;
 
 	ehca_error_data(shca, cq, cq->ipz_cq_handle.handle);
 
+	if (atomic_dec_and_test(&cq->nr_events))
+		wake_up(&cq->wait_completion);
+
 	return;
 }
 
@@ -281,30 +287,61 @@
 	return;
 }
 
-static void parse_ec(struct ehca_shca *shca, u64 eqe)
+static void dispatch_port_event(struct ehca_shca *shca, int port_num,
+				enum ib_event_type type, const char *msg)
 {
 	struct ib_event event;
+
+	ehca_info(&shca->ib_device, "port %d %s.", port_num, msg);
+	event.device = &shca->ib_device;
+	event.event = type;
+	event.element.port_num = port_num;
+	ib_dispatch_event(&event);
+}
+
+static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
+{
+	struct ehca_sma_attr  new_attr;
+	struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr;
+
+	ehca_query_sma_attr(shca, port_num, &new_attr);
+
+	if (new_attr.sm_sl  != old_attr->sm_sl ||
+	    new_attr.sm_lid != old_attr->sm_lid)
+		dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE,
+				    "SM changed");
+
+	if (new_attr.lid != old_attr->lid ||
+	    new_attr.lmc != old_attr->lmc)
+		dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE,
+				    "LID changed");
+
+	if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len ||
+	    memcmp(new_attr.pkeys, old_attr->pkeys,
+		   sizeof(u16) * new_attr.pkey_tbl_len))
+		dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE,
+				    "P_Key changed");
+
+	*old_attr = new_attr;
+}
+
+static void parse_ec(struct ehca_shca *shca, u64 eqe)
+{
 	u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
 	u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
 
 	switch (ec) {
 	case 0x30: /* port availability change */
 		if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
-			ehca_info(&shca->ib_device,
-				  "port %x is active.", port);
-			event.device = &shca->ib_device;
-			event.event = IB_EVENT_PORT_ACTIVE;
-			event.element.port_num = port;
 			shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
-			ib_dispatch_event(&event);
+			dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+					    "is active");
+			ehca_query_sma_attr(shca, port,
+					    &shca->sport[port - 1].saved_attr);
 		} else {
-			ehca_info(&shca->ib_device,
-				  "port %x is inactive.", port);
-			event.device = &shca->ib_device;
-			event.event = IB_EVENT_PORT_ERR;
-			event.element.port_num = port;
 			shca->sport[port - 1].port_state = IB_PORT_DOWN;
-			ib_dispatch_event(&event);
+			dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+					    "is inactive");
 		}
 		break;
 	case 0x31:
@@ -312,24 +349,19 @@
 		 * disruptive change is caused by
 		 * LID, PKEY or SM change
 		 */
-		ehca_warn(&shca->ib_device,
-			  "disruptive port %x configuration change", port);
+		if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) {
+			ehca_warn(&shca->ib_device, "disruptive port "
+				  "%d configuration change", port);
 
-		ehca_info(&shca->ib_device,
-			  "port %x is inactive.", port);
-		event.device = &shca->ib_device;
-		event.event = IB_EVENT_PORT_ERR;
-		event.element.port_num = port;
-		shca->sport[port - 1].port_state = IB_PORT_DOWN;
-		ib_dispatch_event(&event);
+			shca->sport[port - 1].port_state = IB_PORT_DOWN;
+			dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+					    "is inactive");
 
-		ehca_info(&shca->ib_device,
-			  "port %x is active.", port);
-		event.device = &shca->ib_device;
-		event.event = IB_EVENT_PORT_ACTIVE;
-		event.element.port_num = port;
-		shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
-		ib_dispatch_event(&event);
+			shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
+			dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+					    "is active");
+		} else
+			notify_port_conf_change(shca, port);
 		break;
 	case 0x32: /* adapter malfunction */
 		ehca_err(&shca->ib_device, "Adapter malfunction.");
@@ -404,7 +436,6 @@
 {
 	u64 eqe_value;
 	u32 token;
-	unsigned long flags;
 	struct ehca_cq *cq;
 
 	eqe_value = eqe->entry;
@@ -412,27 +443,24 @@
 	if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
 		ehca_dbg(&shca->ib_device, "Got completion event");
 		token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+		read_lock(&ehca_cq_idr_lock);
 		cq = idr_find(&ehca_cq_idr, token);
+		if (cq)
+			atomic_inc(&cq->nr_events);
+		read_unlock(&ehca_cq_idr_lock);
 		if (cq == NULL) {
-			spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 			ehca_err(&shca->ib_device,
 				 "Invalid eqe for non-existing cq token=%x",
 				 token);
 			return;
 		}
 		reset_eq_pending(cq);
-		cq->nr_events++;
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 		if (ehca_scaling_code)
 			queue_comp_task(cq);
 		else {
 			comp_event_callback(cq);
-			spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-			cq->nr_events--;
-			if (!cq->nr_events)
+			if (atomic_dec_and_test(&cq->nr_events))
 				wake_up(&cq->wait_completion);
-			spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 		}
 	} else {
 		ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -476,17 +504,17 @@
 		eqe_value = eqe_cache[eqe_cnt].eqe->entry;
 		if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
 			token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
-			spin_lock(&ehca_cq_idr_lock);
+			read_lock(&ehca_cq_idr_lock);
 			eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
+			if (eqe_cache[eqe_cnt].cq)
+				atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events);
+			read_unlock(&ehca_cq_idr_lock);
 			if (!eqe_cache[eqe_cnt].cq) {
-				spin_unlock(&ehca_cq_idr_lock);
 				ehca_err(&shca->ib_device,
 					 "Invalid eqe for non-existing cq "
 					 "token=%x", token);
 				continue;
 			}
-			eqe_cache[eqe_cnt].cq->nr_events++;
-			spin_unlock(&ehca_cq_idr_lock);
 		} else
 			eqe_cache[eqe_cnt].cq = NULL;
 		eqe_cnt++;
@@ -517,11 +545,8 @@
 			else {
 				struct ehca_cq *cq = eq->eqe_cache[i].cq;
 				comp_event_callback(cq);
-				spin_lock(&ehca_cq_idr_lock);
-				cq->nr_events--;
-				if (!cq->nr_events)
+				if (atomic_dec_and_test(&cq->nr_events))
 					wake_up(&cq->wait_completion);
-				spin_unlock(&ehca_cq_idr_lock);
 			}
 		} else {
 			ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -621,13 +646,10 @@
 	while (!list_empty(&cct->cq_list)) {
 		cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
 		spin_unlock_irqrestore(&cct->task_lock, flags);
-		comp_event_callback(cq);
 
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-		cq->nr_events--;
-		if (!cq->nr_events)
+		comp_event_callback(cq);
+		if (atomic_dec_and_test(&cq->nr_events))
 			wake_up(&cq->wait_completion);
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
 		spin_lock_irqsave(&cct->task_lock, flags);
 		spin_lock(&cq->task_lock);
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index 6ed06ee..3346cb0 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -47,7 +47,6 @@
 
 #include <linux/interrupt.h>
 #include <linux/types.h>
-#include <asm/atomic.h>
 
 int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
 
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index 37e7fe0..77aeca6 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -49,6 +49,9 @@
 int ehca_query_port(struct ib_device *ibdev, u8 port,
 		    struct ib_port_attr *props);
 
+int ehca_query_sma_attr(struct ehca_shca *shca, u8 port,
+			struct ehca_sma_attr *attr);
+
 int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey);
 
 int ehca_query_gid(struct ib_device *ibdev, u8 port, int index,
@@ -154,6 +157,21 @@
 int ehca_post_recv(struct ib_qp *qp, struct ib_recv_wr *recv_wr,
 		   struct ib_recv_wr **bad_recv_wr);
 
+int ehca_post_srq_recv(struct ib_srq *srq,
+		       struct ib_recv_wr *recv_wr,
+		       struct ib_recv_wr **bad_recv_wr);
+
+struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+			       struct ib_srq_init_attr *init_attr,
+			       struct ib_udata *udata);
+
+int ehca_modify_srq(struct ib_srq *srq, struct ib_srq_attr *attr,
+		    enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
+
+int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
+
+int ehca_destroy_srq(struct ib_srq *srq);
+
 u64 ehca_define_sqp(struct ehca_shca *shca, struct ehca_qp *ibqp,
 		    struct ib_qp_init_attr *qp_init_attr);
 
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index c3f99f3..28ba2dd 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -94,17 +94,15 @@
 MODULE_PARM_DESC(static_rate,
 		 "set permanent static rate (default: disabled)");
 MODULE_PARM_DESC(scaling_code,
-		 "set scaling code (0: disabled, 1: enabled/default)");
+		 "set scaling code (0: disabled/default, 1: enabled)");
 
-spinlock_t ehca_qp_idr_lock;
-spinlock_t ehca_cq_idr_lock;
-spinlock_t hcall_lock;
+DEFINE_RWLOCK(ehca_qp_idr_lock);
+DEFINE_RWLOCK(ehca_cq_idr_lock);
 DEFINE_IDR(ehca_qp_idr);
 DEFINE_IDR(ehca_cq_idr);
 
-
-static struct list_head shca_list; /* list of all registered ehcas */
-static spinlock_t shca_list_lock;
+static LIST_HEAD(shca_list); /* list of all registered ehcas */
+static DEFINE_SPINLOCK(shca_list_lock);
 
 static struct timer_list poll_eqs_timer;
 
@@ -205,11 +203,35 @@
 #define EHCA_HCAAVER  EHCA_BMASK_IBM(32,39)
 #define EHCA_REVID    EHCA_BMASK_IBM(40,63)
 
+static struct cap_descr {
+	u64 mask;
+	char *descr;
+} hca_cap_descr[] = {
+	{ HCA_CAP_AH_PORT_NR_CHECK, "HCA_CAP_AH_PORT_NR_CHECK" },
+	{ HCA_CAP_ATOMIC, "HCA_CAP_ATOMIC" },
+	{ HCA_CAP_AUTO_PATH_MIG, "HCA_CAP_AUTO_PATH_MIG" },
+	{ HCA_CAP_BAD_P_KEY_CTR, "HCA_CAP_BAD_P_KEY_CTR" },
+	{ HCA_CAP_SQD_RTS_PORT_CHANGE, "HCA_CAP_SQD_RTS_PORT_CHANGE" },
+	{ HCA_CAP_CUR_QP_STATE_MOD, "HCA_CAP_CUR_QP_STATE_MOD" },
+	{ HCA_CAP_INIT_TYPE, "HCA_CAP_INIT_TYPE" },
+	{ HCA_CAP_PORT_ACTIVE_EVENT, "HCA_CAP_PORT_ACTIVE_EVENT" },
+	{ HCA_CAP_Q_KEY_VIOL_CTR, "HCA_CAP_Q_KEY_VIOL_CTR" },
+	{ HCA_CAP_WQE_RESIZE, "HCA_CAP_WQE_RESIZE" },
+	{ HCA_CAP_RAW_PACKET_MCAST, "HCA_CAP_RAW_PACKET_MCAST" },
+	{ HCA_CAP_SHUTDOWN_PORT, "HCA_CAP_SHUTDOWN_PORT" },
+	{ HCA_CAP_RC_LL_QP, "HCA_CAP_RC_LL_QP" },
+	{ HCA_CAP_SRQ, "HCA_CAP_SRQ" },
+	{ HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" },
+	{ HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" },
+	{ HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
+};
+
 int ehca_sense_attributes(struct ehca_shca *shca)
 {
-	int ret = 0;
+	int i, ret = 0;
 	u64 h_ret;
 	struct hipz_query_hca *rblock;
+	struct hipz_query_port *port;
 
 	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
@@ -222,7 +244,7 @@
 		ehca_gen_err("Cannot query device properties. h_ret=%lx",
 			     h_ret);
 		ret = -EPERM;
-		goto num_ports1;
+		goto sense_attributes1;
 	}
 
 	if (ehca_nr_ports == 1)
@@ -242,18 +264,44 @@
 		ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid);
 
 		if ((hcaaver == 1) && (revid == 0))
-			shca->hw_level = 0;
+			shca->hw_level = 0x11;
 		else if ((hcaaver == 1) && (revid == 1))
-			shca->hw_level = 1;
+			shca->hw_level = 0x12;
 		else if ((hcaaver == 1) && (revid == 2))
-			shca->hw_level = 2;
+			shca->hw_level = 0x13;
+		else if ((hcaaver == 2) && (revid == 0))
+			shca->hw_level = 0x21;
+		else if ((hcaaver == 2) && (revid == 0x10))
+			shca->hw_level = 0x22;
+		else {
+			ehca_gen_warn("unknown hardware version"
+				      " - assuming default level");
+			shca->hw_level = 0x22;
+		}
 	}
 	ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
 
 	shca->sport[0].rate = IB_RATE_30_GBPS;
 	shca->sport[1].rate = IB_RATE_30_GBPS;
 
-num_ports1:
+	shca->hca_cap = rblock->hca_cap_indicators;
+	ehca_gen_dbg(" ... HCA capabilities:");
+	for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
+		if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
+			ehca_gen_dbg("   %s", hca_cap_descr[i].descr);
+
+	port = (struct hipz_query_port *) rblock;
+	h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
+	if (h_ret != H_SUCCESS) {
+		ehca_gen_err("Cannot query port properties. h_ret=%lx",
+			     h_ret);
+		ret = -EPERM;
+		goto sense_attributes1;
+	}
+
+	shca->max_mtu = port->max_mtu;
+
+sense_attributes1:
 	ehca_free_fw_ctrlblock(rblock);
 	return ret;
 }
@@ -293,7 +341,7 @@
 	strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
 	shca->ib_device.owner               = THIS_MODULE;
 
-	shca->ib_device.uverbs_abi_ver	    = 6;
+	shca->ib_device.uverbs_abi_ver	    = 7;
 	shca->ib_device.uverbs_cmd_mask	    =
 		(1ull << IB_USER_VERBS_CMD_GET_CONTEXT)		|
 		(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)	|
@@ -361,6 +409,20 @@
 	/* shca->ib_device.process_mad	    = ehca_process_mad;	    */
 	shca->ib_device.mmap		    = ehca_mmap;
 
+	if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+		shca->ib_device.uverbs_cmd_mask |=
+			(1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
+			(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
+			(1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
+			(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+
+		shca->ib_device.create_srq          = ehca_create_srq;
+		shca->ib_device.modify_srq          = ehca_modify_srq;
+		shca->ib_device.query_srq           = ehca_query_srq;
+		shca->ib_device.destroy_srq         = ehca_destroy_srq;
+		shca->ib_device.post_srq_recv       = ehca_post_srq_recv;
+	}
+
 	return ret;
 }
 
@@ -800,14 +862,6 @@
 
 	printk(KERN_INFO "eHCA Infiniband Device Driver "
 	       "(Rel.: SVNEHCA_0023)\n");
-	idr_init(&ehca_qp_idr);
-	idr_init(&ehca_cq_idr);
-	spin_lock_init(&ehca_qp_idr_lock);
-	spin_lock_init(&ehca_cq_idr_lock);
-	spin_lock_init(&hcall_lock);
-
-	INIT_LIST_HEAD(&shca_list);
-	spin_lock_init(&shca_list_lock);
 
 	if ((ret = ehca_create_comp_pool())) {
 		ehca_gen_err("Cannot create comp pool.");
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 84c5bb4..add79bd 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -2050,13 +2050,10 @@
 	switch (hipz_rc) {
 	case H_SUCCESS:	             /* successful completion */
 		return 0;
-	case H_ADAPTER_PARM:         /* invalid adapter handle */
-	case H_RT_PARM:              /* invalid resource type */
 	case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */
-	case H_MLENGTH_PARM:         /* invalid memory length */
-	case H_MEM_ACCESS_PARM:      /* invalid access controls */
 	case H_CONSTRAINED:          /* resource constraint */
-		return -EINVAL;
+	case H_NO_MEM:
+		return -ENOMEM;
 	case H_BUSY:                 /* long busy */
 		return -EBUSY;
 	default:
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index b5bc787..7467125 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -3,7 +3,9 @@
  *
  *  QP functions
  *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *  Authors: Joachim Fenkes <fenkes@de.ibm.com>
+ *           Stefan Roscher <stefan.roscher@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
  *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
  *           Reinhard Ernst <rernst@de.ibm.com>
  *           Heiko J Schick <schickhj@de.ibm.com>
@@ -234,13 +236,6 @@
 	return index;
 }
 
-enum ehca_service_type {
-	ST_RC = 0,
-	ST_UC = 1,
-	ST_RD = 2,
-	ST_UD = 3
-};
-
 /*
  * ibqptype2servicetype returns hcp service type corresponding to given
  * ib qp type used by create_qp()
@@ -268,15 +263,34 @@
 }
 
 /*
- * init_qp_queues initializes/constructs r/squeue and registers queue pages.
+ * init userspace queue info from ipz_queue data
  */
-static inline int init_qp_queues(struct ehca_shca *shca,
-				 struct ehca_qp *my_qp,
-				 int nr_sq_pages,
-				 int nr_rq_pages,
-				 int swqe_size,
-				 int rwqe_size,
-				 int nr_send_sges, int nr_receive_sges)
+static inline void queue2resp(struct ipzu_queue_resp *resp,
+			      struct ipz_queue *queue)
+{
+	resp->qe_size = queue->qe_size;
+	resp->act_nr_of_sg = queue->act_nr_of_sg;
+	resp->queue_length = queue->queue_length;
+	resp->pagesize = queue->pagesize;
+	resp->toggle_state = queue->toggle_state;
+}
+
+static inline int ll_qp_msg_size(int nr_sge)
+{
+	return 128 << nr_sge;
+}
+
+/*
+ * init_qp_queue initializes/constructs r/squeue and registers queue pages.
+ */
+static inline int init_qp_queue(struct ehca_shca *shca,
+				struct ehca_qp *my_qp,
+				struct ipz_queue *queue,
+				int q_type,
+				u64 expected_hret,
+				int nr_q_pages,
+				int wqe_size,
+				int nr_sges)
 {
 	int ret, cnt, ipz_rc;
 	void *vpage;
@@ -284,127 +298,93 @@
 	struct ib_device *ib_dev = &shca->ib_device;
 	struct ipz_adapter_handle ipz_hca_handle = shca->ipz_hca_handle;
 
-	ipz_rc = ipz_queue_ctor(&my_qp->ipz_squeue,
-				nr_sq_pages,
-				EHCA_PAGESIZE, swqe_size, nr_send_sges);
+	if (!nr_q_pages)
+		return 0;
+
+	ipz_rc = ipz_queue_ctor(queue, nr_q_pages, EHCA_PAGESIZE,
+				wqe_size, nr_sges);
 	if (!ipz_rc) {
-		ehca_err(ib_dev,"Cannot allocate page for squeue. ipz_rc=%x",
+		ehca_err(ib_dev, "Cannot allocate page for queue. ipz_rc=%x",
 			 ipz_rc);
 		return -EBUSY;
 	}
 
-	ipz_rc = ipz_queue_ctor(&my_qp->ipz_rqueue,
-				nr_rq_pages,
-				EHCA_PAGESIZE, rwqe_size, nr_receive_sges);
-	if (!ipz_rc) {
-		ehca_err(ib_dev, "Cannot allocate page for rqueue. ipz_rc=%x",
-			 ipz_rc);
-		ret = -EBUSY;
-		goto init_qp_queues0;
-	}
-	/* register SQ pages */
-	for (cnt = 0; cnt < nr_sq_pages; cnt++) {
-		vpage = ipz_qpageit_get_inc(&my_qp->ipz_squeue);
+	/* register queue pages */
+	for (cnt = 0; cnt < nr_q_pages; cnt++) {
+		vpage = ipz_qpageit_get_inc(queue);
 		if (!vpage) {
-			ehca_err(ib_dev, "SQ ipz_qpageit_get_inc() "
+			ehca_err(ib_dev, "ipz_qpageit_get_inc() "
 				 "failed p_vpage= %p", vpage);
 			ret = -EINVAL;
-			goto init_qp_queues1;
+			goto init_qp_queue1;
 		}
 		rpage = virt_to_abs(vpage);
 
 		h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
 						 my_qp->ipz_qp_handle,
-						 &my_qp->pf, 0, 0,
+						 NULL, 0, q_type,
 						 rpage, 1,
 						 my_qp->galpas.kernel);
-		if (h_ret < H_SUCCESS) {
-			ehca_err(ib_dev, "SQ hipz_qp_register_rpage()"
-				 " failed rc=%lx", h_ret);
-			ret = ehca2ib_return_code(h_ret);
-			goto init_qp_queues1;
-		}
-	}
-
-	ipz_qeit_reset(&my_qp->ipz_squeue);
-
-	/* register RQ pages */
-	for (cnt = 0; cnt < nr_rq_pages; cnt++) {
-		vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue);
-		if (!vpage) {
-			ehca_err(ib_dev, "RQ ipz_qpageit_get_inc() "
-				 "failed p_vpage = %p", vpage);
-			ret = -EINVAL;
-			goto init_qp_queues1;
-		}
-
-		rpage = virt_to_abs(vpage);
-
-		h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
-						 my_qp->ipz_qp_handle,
-						 &my_qp->pf, 0, 1,
-						 rpage, 1,my_qp->galpas.kernel);
-		if (h_ret < H_SUCCESS) {
-			ehca_err(ib_dev, "RQ hipz_qp_register_rpage() failed "
-				 "rc=%lx", h_ret);
-			ret = ehca2ib_return_code(h_ret);
-			goto init_qp_queues1;
-		}
-		if (cnt == (nr_rq_pages - 1)) {	/* last page! */
-			if (h_ret != H_SUCCESS) {
-				ehca_err(ib_dev, "RQ hipz_qp_register_rpage() "
+		if (cnt == (nr_q_pages - 1)) {	/* last page! */
+			if (h_ret != expected_hret) {
+				ehca_err(ib_dev, "hipz_qp_register_rpage() "
 					 "h_ret= %lx ", h_ret);
 				ret = ehca2ib_return_code(h_ret);
-				goto init_qp_queues1;
+				goto init_qp_queue1;
 			}
 			vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue);
 			if (vpage) {
 				ehca_err(ib_dev, "ipz_qpageit_get_inc() "
 					 "should not succeed vpage=%p", vpage);
 				ret = -EINVAL;
-				goto init_qp_queues1;
+				goto init_qp_queue1;
 			}
 		} else {
 			if (h_ret != H_PAGE_REGISTERED) {
-				ehca_err(ib_dev, "RQ hipz_qp_register_rpage() "
+				ehca_err(ib_dev, "hipz_qp_register_rpage() "
 					 "h_ret= %lx ", h_ret);
 				ret = ehca2ib_return_code(h_ret);
-				goto init_qp_queues1;
+				goto init_qp_queue1;
 			}
 		}
 	}
 
-	ipz_qeit_reset(&my_qp->ipz_rqueue);
+	ipz_qeit_reset(queue);
 
 	return 0;
 
-init_qp_queues1:
-	ipz_queue_dtor(&my_qp->ipz_rqueue);
-init_qp_queues0:
-	ipz_queue_dtor(&my_qp->ipz_squeue);
+init_qp_queue1:
+	ipz_queue_dtor(queue);
 	return ret;
 }
 
-struct ib_qp *ehca_create_qp(struct ib_pd *pd,
-			     struct ib_qp_init_attr *init_attr,
-			     struct ib_udata *udata)
+/*
+ * Create an ib_qp struct that is either a QP or an SRQ, depending on
+ * the value of the is_srq parameter. If init_attr and srq_init_attr share
+ * fields, the field out of init_attr is used.
+ */
+struct ehca_qp *internal_create_qp(struct ib_pd *pd,
+				   struct ib_qp_init_attr *init_attr,
+				   struct ib_srq_init_attr *srq_init_attr,
+				   struct ib_udata *udata, int is_srq)
 {
-	static int da_rc_msg_size[]={ 128, 256, 512, 1024, 2048, 4096 };
-	static int da_ud_sq_msg_size[]={ 128, 384, 896, 1920, 3968 };
 	struct ehca_qp *my_qp;
 	struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
 	struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
 					      ib_device);
 	struct ib_ucontext *context = NULL;
 	u64 h_ret;
-	int max_send_sge, max_recv_sge, ret;
+	int is_llqp = 0, has_srq = 0;
+	int qp_type, max_send_sge, max_recv_sge, ret;
 
 	/* h_call's out parameters */
 	struct ehca_alloc_qp_parms parms;
-	u32 swqe_size = 0, rwqe_size = 0;
-	u8 daqp_completion, isdaqp;
+	u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
 	unsigned long flags;
 
+	memset(&parms, 0, sizeof(parms));
+	qp_type = init_attr->qp_type;
+
 	if (init_attr->sq_sig_type != IB_SIGNAL_REQ_WR &&
 		init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
 		ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
@@ -412,39 +392,96 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	/* save daqp completion bits */
-	daqp_completion = init_attr->qp_type & 0x60;
-	/* save daqp bit */
-	isdaqp = (init_attr->qp_type & 0x80) ? 1 : 0;
-	init_attr->qp_type = init_attr->qp_type & 0x1F;
+	/* save LLQP info */
+	if (qp_type & 0x80) {
+		is_llqp = 1;
+		parms.ext_type = EQPT_LLQP;
+		parms.ll_comp_flags = qp_type & LLQP_COMP_MASK;
+	}
+	qp_type &= 0x1F;
+	init_attr->qp_type &= 0x1F;
 
-	if (init_attr->qp_type != IB_QPT_UD &&
-	    init_attr->qp_type != IB_QPT_SMI &&
-	    init_attr->qp_type != IB_QPT_GSI &&
-	    init_attr->qp_type != IB_QPT_UC &&
-	    init_attr->qp_type != IB_QPT_RC) {
-		ehca_err(pd->device, "wrong QP Type=%x", init_attr->qp_type);
+	/* handle SRQ base QPs */
+	if (init_attr->srq) {
+		struct ehca_qp *my_srq =
+			container_of(init_attr->srq, struct ehca_qp, ib_srq);
+
+		has_srq = 1;
+		parms.ext_type = EQPT_SRQBASE;
+		parms.srq_qpn = my_srq->real_qp_num;
+		parms.srq_token = my_srq->token;
+	}
+
+	if (is_llqp && has_srq) {
+		ehca_err(pd->device, "LLQPs can't have an SRQ");
 		return ERR_PTR(-EINVAL);
 	}
-	if ((init_attr->qp_type != IB_QPT_RC && init_attr->qp_type != IB_QPT_UD)
-	    && isdaqp) {
-		ehca_err(pd->device, "unsupported LL QP Type=%x",
-			 init_attr->qp_type);
+
+	/* handle SRQs */
+	if (is_srq) {
+		parms.ext_type = EQPT_SRQ;
+		parms.srq_limit = srq_init_attr->attr.srq_limit;
+		if (init_attr->cap.max_recv_sge > 3) {
+			ehca_err(pd->device, "no more than three SGEs "
+				 "supported for SRQ  pd=%p  max_sge=%x",
+				 pd, init_attr->cap.max_recv_sge);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	/* check QP type */
+	if (qp_type != IB_QPT_UD &&
+	    qp_type != IB_QPT_UC &&
+	    qp_type != IB_QPT_RC &&
+	    qp_type != IB_QPT_SMI &&
+	    qp_type != IB_QPT_GSI) {
+		ehca_err(pd->device, "wrong QP Type=%x", qp_type);
 		return ERR_PTR(-EINVAL);
-	} else if (init_attr->qp_type == IB_QPT_RC && isdaqp &&
-		   (init_attr->cap.max_send_wr > 255 ||
-		    init_attr->cap.max_recv_wr > 255 )) {
-		       ehca_err(pd->device, "Invalid Number of max_sq_wr =%x "
-				"or max_rq_wr=%x for QP Type=%x",
-				init_attr->cap.max_send_wr,
-				init_attr->cap.max_recv_wr,init_attr->qp_type);
-		       return ERR_PTR(-EINVAL);
-	} else if (init_attr->qp_type == IB_QPT_UD && isdaqp &&
-		  init_attr->cap.max_send_wr > 255) {
-		ehca_err(pd->device,
-			 "Invalid Number of max_send_wr=%x for UD QP_TYPE=%x",
-			 init_attr->cap.max_send_wr, init_attr->qp_type);
-		return ERR_PTR(-EINVAL);
+	}
+
+	if (is_llqp) {
+		switch (qp_type) {
+		case IB_QPT_RC:
+			if ((init_attr->cap.max_send_wr > 255) ||
+			    (init_attr->cap.max_recv_wr > 255)) {
+				ehca_err(pd->device,
+					 "Invalid Number of max_sq_wr=%x "
+					 "or max_rq_wr=%x for RC LLQP",
+					 init_attr->cap.max_send_wr,
+					 init_attr->cap.max_recv_wr);
+				return ERR_PTR(-EINVAL);
+			}
+			break;
+		case IB_QPT_UD:
+			if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
+				ehca_err(pd->device, "UD LLQP not supported "
+					 "by this adapter");
+				return ERR_PTR(-ENOSYS);
+			}
+			if (!(init_attr->cap.max_send_sge <= 5
+			    && init_attr->cap.max_send_sge >= 1
+			    && init_attr->cap.max_recv_sge <= 5
+			    && init_attr->cap.max_recv_sge >= 1)) {
+				ehca_err(pd->device,
+					 "Invalid Number of max_send_sge=%x "
+					 "or max_recv_sge=%x for UD LLQP",
+					 init_attr->cap.max_send_sge,
+					 init_attr->cap.max_recv_sge);
+				return ERR_PTR(-EINVAL);
+			} else if (init_attr->cap.max_send_wr > 255) {
+				ehca_err(pd->device,
+					 "Invalid Number of "
+					 "ax_send_wr=%x for UD QP_TYPE=%x",
+					 init_attr->cap.max_send_wr, qp_type);
+				return ERR_PTR(-EINVAL);
+			}
+			break;
+		default:
+			ehca_err(pd->device, "unsupported LL QP Type=%x",
+				 qp_type);
+			return ERR_PTR(-EINVAL);
+			break;
+		}
 	}
 
 	if (pd->uobject && udata)
@@ -456,16 +493,17 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memset (&parms, 0, sizeof(struct ehca_alloc_qp_parms));
 	spin_lock_init(&my_qp->spinlock_s);
 	spin_lock_init(&my_qp->spinlock_r);
+	my_qp->qp_type = qp_type;
+	my_qp->ext_type = parms.ext_type;
 
-	my_qp->recv_cq =
-		container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);
-	my_qp->send_cq =
-		container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
-
-	my_qp->init_attr = *init_attr;
+	if (init_attr->recv_cq)
+		my_qp->recv_cq =
+			container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);
+	if (init_attr->send_cq)
+		my_qp->send_cq =
+			container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
 
 	do {
 		if (!idr_pre_get(&ehca_qp_idr, GFP_KERNEL)) {
@@ -474,9 +512,9 @@
 			goto create_qp_exit0;
 		}
 
-		spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+		write_lock_irqsave(&ehca_qp_idr_lock, flags);
 		ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token);
-		spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+		write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
 	} while (ret == -EAGAIN);
 
@@ -486,10 +524,10 @@
 		goto create_qp_exit0;
 	}
 
-	parms.servicetype = ibqptype2servicetype(init_attr->qp_type);
+	parms.servicetype = ibqptype2servicetype(qp_type);
 	if (parms.servicetype < 0) {
 		ret = -EINVAL;
-		ehca_err(pd->device, "Invalid qp_type=%x", init_attr->qp_type);
+		ehca_err(pd->device, "Invalid qp_type=%x", qp_type);
 		goto create_qp_exit0;
 	}
 
@@ -501,21 +539,25 @@
 	/* UD_AV CIRCUMVENTION */
 	max_send_sge = init_attr->cap.max_send_sge;
 	max_recv_sge = init_attr->cap.max_recv_sge;
-	if (IB_QPT_UD == init_attr->qp_type ||
-	    IB_QPT_GSI == init_attr->qp_type ||
-	    IB_QPT_SMI == init_attr->qp_type) {
+	if (parms.servicetype == ST_UD && !is_llqp) {
 		max_send_sge += 2;
 		max_recv_sge += 2;
 	}
 
-	parms.ipz_eq_handle = shca->eq.ipz_eq_handle;
-	parms.daqp_ctrl = isdaqp | daqp_completion;
+	parms.token = my_qp->token;
+	parms.eq_handle = shca->eq.ipz_eq_handle;
 	parms.pd = my_pd->fw_pd;
-	parms.max_recv_sge = max_recv_sge;
+	if (my_qp->send_cq)
+		parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle;
+	if (my_qp->recv_cq)
+		parms.recv_cq_handle = my_qp->recv_cq->ipz_cq_handle;
+
+	parms.max_send_wr = init_attr->cap.max_send_wr;
+	parms.max_recv_wr = init_attr->cap.max_recv_wr;
 	parms.max_send_sge = max_send_sge;
+	parms.max_recv_sge = max_recv_sge;
 
-	h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, my_qp, &parms);
-
+	h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms);
 	if (h_ret != H_SUCCESS) {
 		ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lx",
 			 h_ret);
@@ -523,18 +565,20 @@
 		goto create_qp_exit1;
 	}
 
-	my_qp->ib_qp.qp_num = my_qp->real_qp_num;
+	ib_qp_num = my_qp->real_qp_num = parms.real_qp_num;
+	my_qp->ipz_qp_handle = parms.qp_handle;
+	my_qp->galpas = parms.galpas;
 
-	switch (init_attr->qp_type) {
+	switch (qp_type) {
 	case IB_QPT_RC:
-	        if (isdaqp == 0) {
+		if (!is_llqp) {
 			swqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[
 					     (parms.act_nr_send_sges)]);
 			rwqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[
 					     (parms.act_nr_recv_sges)]);
-		} else { /* for daqp we need to use msg size, not wqe size */
-		        swqe_size = da_rc_msg_size[max_send_sge];
-			rwqe_size = da_rc_msg_size[max_recv_sge];
+		} else { /* for LLQP we need to use msg size, not wqe size */
+			swqe_size = ll_qp_msg_size(max_send_sge);
+			rwqe_size = ll_qp_msg_size(max_recv_sge);
 			parms.act_nr_send_sges = 1;
 			parms.act_nr_recv_sges = 1;
 		}
@@ -549,29 +593,27 @@
 	case IB_QPT_UD:
 	case IB_QPT_GSI:
 	case IB_QPT_SMI:
-		/* UD circumvention */
-		parms.act_nr_recv_sges -= 2;
-		parms.act_nr_send_sges -= 2;
-		if (isdaqp) {
-		        swqe_size = da_ud_sq_msg_size[max_send_sge];
-			rwqe_size = da_rc_msg_size[max_recv_sge];
+		if (is_llqp) {
+			swqe_size = ll_qp_msg_size(parms.act_nr_send_sges);
+			rwqe_size = ll_qp_msg_size(parms.act_nr_recv_sges);
 			parms.act_nr_send_sges = 1;
 			parms.act_nr_recv_sges = 1;
 		} else {
+			/* UD circumvention */
+			parms.act_nr_send_sges -= 2;
+			parms.act_nr_recv_sges -= 2;
 			swqe_size = offsetof(struct ehca_wqe,
 					     u.ud_av.sg_list[parms.act_nr_send_sges]);
 			rwqe_size = offsetof(struct ehca_wqe,
 					     u.ud_av.sg_list[parms.act_nr_recv_sges]);
 		}
 
-		if (IB_QPT_GSI == init_attr->qp_type ||
-		    IB_QPT_SMI == init_attr->qp_type) {
+		if (IB_QPT_GSI == qp_type || IB_QPT_SMI == qp_type) {
 			parms.act_nr_send_wqes = init_attr->cap.max_send_wr;
 			parms.act_nr_recv_wqes = init_attr->cap.max_recv_wr;
 			parms.act_nr_send_sges = init_attr->cap.max_send_sge;
 			parms.act_nr_recv_sges = init_attr->cap.max_recv_sge;
-			my_qp->ib_qp.qp_num =
-				(init_attr->qp_type == IB_QPT_SMI) ? 0 : 1;
+			ib_qp_num = (qp_type == IB_QPT_SMI) ? 0 : 1;
 		}
 
 		break;
@@ -580,108 +622,234 @@
 		break;
 	}
 
-	/* initializes r/squeue and registers queue pages */
-	ret = init_qp_queues(shca, my_qp,
-			     parms.nr_sq_pages, parms.nr_rq_pages,
-			     swqe_size, rwqe_size,
-			     parms.act_nr_send_sges, parms.act_nr_recv_sges);
-	if (ret) {
-		ehca_err(pd->device,
-			 "Couldn't initialize r/squeue and pages ret=%x", ret);
-		goto create_qp_exit2;
+	/* initialize r/squeue and register queue pages */
+	if (HAS_SQ(my_qp)) {
+		ret = init_qp_queue(
+			shca, my_qp, &my_qp->ipz_squeue, 0,
+			HAS_RQ(my_qp) ? H_PAGE_REGISTERED : H_SUCCESS,
+			parms.nr_sq_pages, swqe_size,
+			parms.act_nr_send_sges);
+		if (ret) {
+			ehca_err(pd->device, "Couldn't initialize squeue "
+				 "and pages  ret=%x", ret);
+			goto create_qp_exit2;
+		}
 	}
 
-	my_qp->ib_qp.pd = &my_pd->ib_pd;
-	my_qp->ib_qp.device = my_pd->ib_pd.device;
+	if (HAS_RQ(my_qp)) {
+		ret = init_qp_queue(
+			shca, my_qp, &my_qp->ipz_rqueue, 1,
+			H_SUCCESS, parms.nr_rq_pages, rwqe_size,
+			parms.act_nr_recv_sges);
+		if (ret) {
+			ehca_err(pd->device, "Couldn't initialize rqueue "
+				 "and pages ret=%x", ret);
+			goto create_qp_exit3;
+		}
+	}
 
-	my_qp->ib_qp.recv_cq = init_attr->recv_cq;
-	my_qp->ib_qp.send_cq = init_attr->send_cq;
+	if (is_srq) {
+		my_qp->ib_srq.pd = &my_pd->ib_pd;
+		my_qp->ib_srq.device = my_pd->ib_pd.device;
 
-	my_qp->ib_qp.qp_type = init_attr->qp_type;
+		my_qp->ib_srq.srq_context = init_attr->qp_context;
+		my_qp->ib_srq.event_handler = init_attr->event_handler;
+	} else {
+		my_qp->ib_qp.qp_num = ib_qp_num;
+		my_qp->ib_qp.pd = &my_pd->ib_pd;
+		my_qp->ib_qp.device = my_pd->ib_pd.device;
 
-	my_qp->qp_type = init_attr->qp_type;
-	my_qp->ib_qp.srq = init_attr->srq;
+		my_qp->ib_qp.recv_cq = init_attr->recv_cq;
+		my_qp->ib_qp.send_cq = init_attr->send_cq;
 
-	my_qp->ib_qp.qp_context = init_attr->qp_context;
-	my_qp->ib_qp.event_handler = init_attr->event_handler;
+		my_qp->ib_qp.qp_type = qp_type;
+		my_qp->ib_qp.srq = init_attr->srq;
+
+		my_qp->ib_qp.qp_context = init_attr->qp_context;
+		my_qp->ib_qp.event_handler = init_attr->event_handler;
+	}
 
 	init_attr->cap.max_inline_data = 0; /* not supported yet */
 	init_attr->cap.max_recv_sge = parms.act_nr_recv_sges;
 	init_attr->cap.max_recv_wr = parms.act_nr_recv_wqes;
 	init_attr->cap.max_send_sge = parms.act_nr_send_sges;
 	init_attr->cap.max_send_wr = parms.act_nr_send_wqes;
+	my_qp->init_attr = *init_attr;
 
 	/* NOTE: define_apq0() not supported yet */
-	if (init_attr->qp_type == IB_QPT_GSI) {
+	if (qp_type == IB_QPT_GSI) {
 		h_ret = ehca_define_sqp(shca, my_qp, init_attr);
 		if (h_ret != H_SUCCESS) {
 			ehca_err(pd->device, "ehca_define_sqp() failed rc=%lx",
 				 h_ret);
 			ret = ehca2ib_return_code(h_ret);
-			goto create_qp_exit3;
+			goto create_qp_exit4;
 		}
 	}
-	if (init_attr->send_cq) {
-		struct ehca_cq *cq = container_of(init_attr->send_cq,
-						  struct ehca_cq, ib_cq);
-		ret = ehca_cq_assign_qp(cq, my_qp);
+
+	if (my_qp->send_cq) {
+		ret = ehca_cq_assign_qp(my_qp->send_cq, my_qp);
 		if (ret) {
 			ehca_err(pd->device, "Couldn't assign qp to send_cq ret=%x",
 				 ret);
-			goto create_qp_exit3;
+			goto create_qp_exit4;
 		}
-		my_qp->send_cq = cq;
 	}
+
 	/* copy queues, galpa data to user space */
 	if (context && udata) {
-		struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue;
-		struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue;
 		struct ehca_create_qp_resp resp;
 		memset(&resp, 0, sizeof(resp));
 
 		resp.qp_num = my_qp->real_qp_num;
 		resp.token = my_qp->token;
 		resp.qp_type = my_qp->qp_type;
+		resp.ext_type = my_qp->ext_type;
 		resp.qkey = my_qp->qkey;
 		resp.real_qp_num = my_qp->real_qp_num;
-		/* rqueue properties */
-		resp.ipz_rqueue.qe_size = ipz_rqueue->qe_size;
-		resp.ipz_rqueue.act_nr_of_sg = ipz_rqueue->act_nr_of_sg;
-		resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length;
-		resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize;
-		resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state;
-		/* squeue properties */
-		resp.ipz_squeue.qe_size = ipz_squeue->qe_size;
-		resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg;
-		resp.ipz_squeue.queue_length = ipz_squeue->queue_length;
-		resp.ipz_squeue.pagesize = ipz_squeue->pagesize;
-		resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state;
+		if (HAS_SQ(my_qp))
+			queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue);
+		if (HAS_RQ(my_qp))
+			queue2resp(&resp.ipz_rqueue, &my_qp->ipz_rqueue);
+
 		if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
 			ehca_err(pd->device, "Copy to udata failed");
 			ret = -EINVAL;
-			goto create_qp_exit3;
+			goto create_qp_exit4;
 		}
 	}
 
-	return &my_qp->ib_qp;
+	return my_qp;
+
+create_qp_exit4:
+	if (HAS_RQ(my_qp))
+		ipz_queue_dtor(&my_qp->ipz_rqueue);
 
 create_qp_exit3:
-	ipz_queue_dtor(&my_qp->ipz_rqueue);
-	ipz_queue_dtor(&my_qp->ipz_squeue);
+	if (HAS_SQ(my_qp))
+		ipz_queue_dtor(&my_qp->ipz_squeue);
 
 create_qp_exit2:
 	hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
 
 create_qp_exit1:
-	spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+	write_lock_irqsave(&ehca_qp_idr_lock, flags);
 	idr_remove(&ehca_qp_idr, my_qp->token);
-	spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+	write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
 create_qp_exit0:
 	kmem_cache_free(qp_cache, my_qp);
 	return ERR_PTR(ret);
 }
 
+struct ib_qp *ehca_create_qp(struct ib_pd *pd,
+			     struct ib_qp_init_attr *qp_init_attr,
+			     struct ib_udata *udata)
+{
+	struct ehca_qp *ret;
+
+	ret = internal_create_qp(pd, qp_init_attr, NULL, udata, 0);
+	return IS_ERR(ret) ? (struct ib_qp *) ret : &ret->ib_qp;
+}
+
+int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+			struct ib_uobject *uobject);
+
+struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+			       struct ib_srq_init_attr *srq_init_attr,
+			       struct ib_udata *udata)
+{
+	struct ib_qp_init_attr qp_init_attr;
+	struct ehca_qp *my_qp;
+	struct ib_srq *ret;
+	struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
+					      ib_device);
+	struct hcp_modify_qp_control_block *mqpcb;
+	u64 hret, update_mask;
+
+	/* For common attributes, internal_create_qp() takes its info
+	 * out of qp_init_attr, so copy all common attrs there.
+	 */
+	memset(&qp_init_attr, 0, sizeof(qp_init_attr));
+	qp_init_attr.event_handler = srq_init_attr->event_handler;
+	qp_init_attr.qp_context = srq_init_attr->srq_context;
+	qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
+	qp_init_attr.qp_type = IB_QPT_RC;
+	qp_init_attr.cap.max_recv_wr = srq_init_attr->attr.max_wr;
+	qp_init_attr.cap.max_recv_sge = srq_init_attr->attr.max_sge;
+
+	my_qp = internal_create_qp(pd, &qp_init_attr, srq_init_attr, udata, 1);
+	if (IS_ERR(my_qp))
+		return (struct ib_srq *) my_qp;
+
+	/* copy back return values */
+	srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;
+	srq_init_attr->attr.max_sge = qp_init_attr.cap.max_recv_sge;
+
+	/* drive SRQ into RTR state */
+	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+	if (!mqpcb) {
+		ehca_err(pd->device, "Could not get zeroed page for mqpcb "
+			 "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
+		ret = ERR_PTR(-ENOMEM);
+		goto create_srq1;
+	}
+
+	mqpcb->qp_state = EHCA_QPS_INIT;
+	mqpcb->prim_phys_port = 1;
+	update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+	hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+				my_qp->ipz_qp_handle,
+				&my_qp->pf,
+				update_mask,
+				mqpcb, my_qp->galpas.kernel);
+	if (hret != H_SUCCESS) {
+		ehca_err(pd->device, "Could not modify SRQ to INIT"
+			 "ehca_qp=%p qp_num=%x hret=%lx",
+			 my_qp, my_qp->real_qp_num, hret);
+		goto create_srq2;
+	}
+
+	mqpcb->qp_enable = 1;
+	update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1);
+	hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+				my_qp->ipz_qp_handle,
+				&my_qp->pf,
+				update_mask,
+				mqpcb, my_qp->galpas.kernel);
+	if (hret != H_SUCCESS) {
+		ehca_err(pd->device, "Could not enable SRQ"
+			 "ehca_qp=%p qp_num=%x hret=%lx",
+			 my_qp, my_qp->real_qp_num, hret);
+		goto create_srq2;
+	}
+
+	mqpcb->qp_state  = EHCA_QPS_RTR;
+	update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+	hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+				my_qp->ipz_qp_handle,
+				&my_qp->pf,
+				update_mask,
+				mqpcb, my_qp->galpas.kernel);
+	if (hret != H_SUCCESS) {
+		ehca_err(pd->device, "Could not modify SRQ to RTR"
+			 "ehca_qp=%p qp_num=%x hret=%lx",
+			 my_qp, my_qp->real_qp_num, hret);
+		goto create_srq2;
+	}
+
+	return &my_qp->ib_srq;
+
+create_srq2:
+	ret = ERR_PTR(ehca2ib_return_code(hret));
+	ehca_free_fw_ctrlblock(mqpcb);
+
+create_srq1:
+	internal_destroy_qp(pd->device, my_qp, my_qp->ib_srq.uobject);
+
+	return ret;
+}
+
 /*
  * prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts
  * set purge bit of bad wqe and subsequent wqes to avoid reentering sqe
@@ -765,7 +933,7 @@
 	u64 h_ret;
 	int bad_wqe_cnt = 0;
 	int squeue_locked = 0;
-	unsigned long spl_flags = 0;
+	unsigned long flags = 0;
 
 	/* do query_qp to obtain current attr values */
 	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
@@ -886,6 +1054,17 @@
 		 "ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x",
 		 my_qp, ibqp->qp_num, statetrans);
 
+	/* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set
+	 * in non-LL UD QPs.
+	 */
+	if ((my_qp->qp_type == IB_QPT_UD) &&
+	    (my_qp->ext_type != EQPT_LLQP) &&
+	    (statetrans == IB_QPST_INIT2RTR) &&
+	    (shca->hw_level >= 0x22)) {
+		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
+		mqpcb->send_grh_flag = 1;
+	}
+
 	/* sqe -> rts: set purge bit of bad wqe before actual trans */
 	if ((my_qp->qp_type == IB_QPT_UD ||
 	     my_qp->qp_type == IB_QPT_GSI ||
@@ -895,7 +1074,7 @@
 		if (!ibqp->uobject) {
 			struct ehca_wqe *wqe;
 			/* lock send queue */
-			spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
+			spin_lock_irqsave(&my_qp->spinlock_s, flags);
 			squeue_locked = 1;
 			/* mark next free wqe */
 			wqe = (struct ehca_wqe*)
@@ -1181,7 +1360,7 @@
 
 modify_qp_exit2:
 	if (squeue_locked) { /* this means: sqe -> rts */
-		spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags);
+		spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
 		my_qp->sqerr_purgeflag = 1;
 	}
 
@@ -1312,6 +1491,9 @@
 	qp_attr->alt_port_num = qpcb->alt_phys_port;
 	qp_attr->alt_timeout = qpcb->timeout_al;
 
+	qp_attr->max_dest_rd_atomic = qpcb->rdma_nr_atomic_resp_res;
+	qp_attr->max_rd_atomic = qpcb->rdma_atomic_outst_dest_qp;
+
 	/* primary av */
 	qp_attr->ah_attr.sl = qpcb->service_level;
 
@@ -1367,53 +1549,170 @@
 	return ret;
 }
 
-int ehca_destroy_qp(struct ib_qp *ibqp)
+int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+		    enum ib_srq_attr_mask attr_mask, struct ib_udata *udata)
 {
-	struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
-	struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
+	struct ehca_qp *my_qp =
+		container_of(ibsrq, struct ehca_qp, ib_srq);
+	struct ehca_pd *my_pd =
+		container_of(ibsrq->pd, struct ehca_pd, ib_pd);
+	struct ehca_shca *shca =
+		container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
+	struct hcp_modify_qp_control_block *mqpcb;
+	u64 update_mask;
+	u64 h_ret;
+	int ret = 0;
+
+	u32 cur_pid = current->tgid;
+	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+	    my_pd->ownpid != cur_pid) {
+		ehca_err(ibsrq->pd->device, "Invalid caller pid=%x ownpid=%x",
+			 cur_pid, my_pd->ownpid);
+		return -EINVAL;
+	}
+
+	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+	if (!mqpcb) {
+		ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
+			 "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
+		return -ENOMEM;
+	}
+
+	update_mask = 0;
+	if (attr_mask & IB_SRQ_LIMIT) {
+		attr_mask &= ~IB_SRQ_LIMIT;
+		update_mask |=
+			EHCA_BMASK_SET(MQPCB_MASK_CURR_SRQ_LIMIT, 1)
+			| EHCA_BMASK_SET(MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG, 1);
+		mqpcb->curr_srq_limit =
+			EHCA_BMASK_SET(MQPCB_CURR_SRQ_LIMIT, attr->srq_limit);
+		mqpcb->qp_aff_asyn_ev_log_reg =
+			EHCA_BMASK_SET(QPX_AAELOG_RESET_SRQ_LIMIT, 1);
+	}
+
+	/* by now, all bits in attr_mask should have been cleared */
+	if (attr_mask) {
+		ehca_err(ibsrq->device, "invalid attribute mask bits set  "
+			 "attr_mask=%x", attr_mask);
+		ret = -EINVAL;
+		goto modify_srq_exit0;
+	}
+
+	if (ehca_debug_level)
+		ehca_dmp(mqpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+	h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle,
+				 NULL, update_mask, mqpcb,
+				 my_qp->galpas.kernel);
+
+	if (h_ret != H_SUCCESS) {
+		ret = ehca2ib_return_code(h_ret);
+		ehca_err(ibsrq->device, "hipz_h_modify_qp() failed rc=%lx "
+			 "ehca_qp=%p qp_num=%x",
+			 h_ret, my_qp, my_qp->real_qp_num);
+	}
+
+modify_srq_exit0:
+	ehca_free_fw_ctrlblock(mqpcb);
+
+	return ret;
+}
+
+int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+{
+	struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
+	struct ehca_pd *my_pd = container_of(srq->pd, struct ehca_pd, ib_pd);
+	struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
 					      ib_device);
+	struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+	struct hcp_modify_qp_control_block *qpcb;
+	u32 cur_pid = current->tgid;
+	int ret = 0;
+	u64 h_ret;
+
+	if (my_pd->ib_pd.uobject  && my_pd->ib_pd.uobject->context  &&
+	    my_pd->ownpid != cur_pid) {
+		ehca_err(srq->device, "Invalid caller pid=%x ownpid=%x",
+			 cur_pid, my_pd->ownpid);
+		return -EINVAL;
+	}
+
+	qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+	if (!qpcb) {
+		ehca_err(srq->device, "Out of memory for qpcb "
+			 "ehca_qp=%p qp_num=%x", my_qp, my_qp->real_qp_num);
+		return -ENOMEM;
+	}
+
+	h_ret = hipz_h_query_qp(adapter_handle, my_qp->ipz_qp_handle,
+				NULL, qpcb, my_qp->galpas.kernel);
+
+	if (h_ret != H_SUCCESS) {
+		ret = ehca2ib_return_code(h_ret);
+		ehca_err(srq->device, "hipz_h_query_qp() failed "
+			 "ehca_qp=%p qp_num=%x h_ret=%lx",
+			 my_qp, my_qp->real_qp_num, h_ret);
+		goto query_srq_exit1;
+	}
+
+	srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1;
+	srq_attr->srq_limit = EHCA_BMASK_GET(
+		MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
+
+	if (ehca_debug_level)
+		ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+query_srq_exit1:
+	ehca_free_fw_ctrlblock(qpcb);
+
+	return ret;
+}
+
+int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+			struct ib_uobject *uobject)
+{
+	struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device);
 	struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
 					     ib_pd);
 	u32 cur_pid = current->tgid;
-	u32 qp_num = ibqp->qp_num;
+	u32 qp_num = my_qp->real_qp_num;
 	int ret;
 	u64 h_ret;
 	u8 port_num;
 	enum ib_qp_type	qp_type;
 	unsigned long flags;
 
-	if (ibqp->uobject) {
+	if (uobject) {
 		if (my_qp->mm_count_galpa ||
 		    my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
-			ehca_err(ibqp->device, "Resources still referenced in "
-				 "user space qp_num=%x", ibqp->qp_num);
+			ehca_err(dev, "Resources still referenced in "
+				 "user space qp_num=%x", qp_num);
 			return -EINVAL;
 		}
 		if (my_pd->ownpid != cur_pid) {
-			ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x",
+			ehca_err(dev, "Invalid caller pid=%x ownpid=%x",
 				 cur_pid, my_pd->ownpid);
 			return -EINVAL;
 		}
 	}
 
 	if (my_qp->send_cq) {
-		ret = ehca_cq_unassign_qp(my_qp->send_cq,
-					      my_qp->real_qp_num);
+		ret = ehca_cq_unassign_qp(my_qp->send_cq, qp_num);
 		if (ret) {
-			ehca_err(ibqp->device, "Couldn't unassign qp from "
+			ehca_err(dev, "Couldn't unassign qp from "
 				 "send_cq ret=%x qp_num=%x cq_num=%x", ret,
-				 my_qp->ib_qp.qp_num, my_qp->send_cq->cq_number);
+				 qp_num, my_qp->send_cq->cq_number);
 			return ret;
 		}
 	}
 
-	spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+	write_lock_irqsave(&ehca_qp_idr_lock, flags);
 	idr_remove(&ehca_qp_idr, my_qp->token);
-	spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+	write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
 	h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
 	if (h_ret != H_SUCCESS) {
-		ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx "
+		ehca_err(dev, "hipz_h_destroy_qp() failed rc=%lx "
 			 "ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num);
 		return ehca2ib_return_code(h_ret);
 	}
@@ -1424,7 +1723,7 @@
 	/* no support for IB_QPT_SMI yet */
 	if (qp_type == IB_QPT_GSI) {
 		struct ib_event event;
-		ehca_info(ibqp->device, "device %s: port %x is inactive.",
+		ehca_info(dev, "device %s: port %x is inactive.",
 			  shca->ib_device.name, port_num);
 		event.device = &shca->ib_device;
 		event.event = IB_EVENT_PORT_ERR;
@@ -1433,12 +1732,28 @@
 		ib_dispatch_event(&event);
 	}
 
-	ipz_queue_dtor(&my_qp->ipz_rqueue);
-	ipz_queue_dtor(&my_qp->ipz_squeue);
+	if (HAS_RQ(my_qp))
+		ipz_queue_dtor(&my_qp->ipz_rqueue);
+	if (HAS_SQ(my_qp))
+		ipz_queue_dtor(&my_qp->ipz_squeue);
 	kmem_cache_free(qp_cache, my_qp);
 	return 0;
 }
 
+int ehca_destroy_qp(struct ib_qp *qp)
+{
+	return internal_destroy_qp(qp->device,
+				   container_of(qp, struct ehca_qp, ib_qp),
+				   qp->uobject);
+}
+
+int ehca_destroy_srq(struct ib_srq *srq)
+{
+	return internal_destroy_qp(srq->device,
+				   container_of(srq, struct ehca_qp, ib_srq),
+				   srq->uobject);
+}
+
 int ehca_init_qp_cache(void)
 {
 	qp_cache = kmem_cache_create("ehca_cache_qp",
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index caec9de..61da65e 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -3,8 +3,9 @@
  *
  *  post_send/recv, poll_cq, req_notify
  *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *  Authors: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *           Reinhard Ernst <rernst@de.ibm.com>
  *
  *  Copyright (c) 2005 IBM Corporation
@@ -362,10 +363,10 @@
 	struct ehca_wqe *wqe_p;
 	int wqe_cnt = 0;
 	int ret = 0;
-	unsigned long spl_flags;
+	unsigned long flags;
 
 	/* LOCK the QUEUE */
-	spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
+	spin_lock_irqsave(&my_qp->spinlock_s, flags);
 
 	/* loop processes list of send reqs */
 	for (cur_send_wr = send_wr; cur_send_wr != NULL;
@@ -406,26 +407,31 @@
 	} /* eof for cur_send_wr */
 
 post_send_exit0:
-	/* UNLOCK the QUEUE */
-	spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags);
 	iosync(); /* serialize GAL register access */
 	hipz_update_sqa(my_qp, wqe_cnt);
+	spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
 	return ret;
 }
 
-int ehca_post_recv(struct ib_qp *qp,
-		   struct ib_recv_wr *recv_wr,
-		   struct ib_recv_wr **bad_recv_wr)
+static int internal_post_recv(struct ehca_qp *my_qp,
+			      struct ib_device *dev,
+			      struct ib_recv_wr *recv_wr,
+			      struct ib_recv_wr **bad_recv_wr)
 {
-	struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
 	struct ib_recv_wr *cur_recv_wr;
 	struct ehca_wqe *wqe_p;
 	int wqe_cnt = 0;
 	int ret = 0;
-	unsigned long spl_flags;
+	unsigned long flags;
+
+	if (unlikely(!HAS_RQ(my_qp))) {
+		ehca_err(dev, "QP has no RQ  ehca_qp=%p qp_num=%x ext_type=%d",
+			 my_qp, my_qp->real_qp_num, my_qp->ext_type);
+		return -ENODEV;
+	}
 
 	/* LOCK the QUEUE */
-	spin_lock_irqsave(&my_qp->spinlock_r, spl_flags);
+	spin_lock_irqsave(&my_qp->spinlock_r, flags);
 
 	/* loop processes list of send reqs */
 	for (cur_recv_wr = recv_wr; cur_recv_wr != NULL;
@@ -439,8 +445,8 @@
 				*bad_recv_wr = cur_recv_wr;
 			if (wqe_cnt == 0) {
 				ret = -ENOMEM;
-				ehca_err(qp->device, "Too many posted WQEs "
-					 "qp_num=%x", qp->qp_num);
+				ehca_err(dev, "Too many posted WQEs "
+					 "qp_num=%x", my_qp->real_qp_num);
 			}
 			goto post_recv_exit0;
 		}
@@ -455,23 +461,39 @@
 			*bad_recv_wr = cur_recv_wr;
 			if (wqe_cnt == 0) {
 				ret = -EINVAL;
-				ehca_err(qp->device, "Could not write WQE "
-					 "qp_num=%x", qp->qp_num);
+				ehca_err(dev, "Could not write WQE "
+					 "qp_num=%x", my_qp->real_qp_num);
 			}
 			goto post_recv_exit0;
 		}
 		wqe_cnt++;
-		ehca_gen_dbg("ehca_qp=%p qp_num=%x wqe_cnt=%d",
-		     my_qp, qp->qp_num, wqe_cnt);
+		ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d",
+			 my_qp, my_qp->real_qp_num, wqe_cnt);
 	} /* eof for cur_recv_wr */
 
 post_recv_exit0:
-	spin_unlock_irqrestore(&my_qp->spinlock_r, spl_flags);
 	iosync(); /* serialize GAL register access */
 	hipz_update_rqa(my_qp, wqe_cnt);
+	spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
 	return ret;
 }
 
+int ehca_post_recv(struct ib_qp *qp,
+		   struct ib_recv_wr *recv_wr,
+		   struct ib_recv_wr **bad_recv_wr)
+{
+	return internal_post_recv(container_of(qp, struct ehca_qp, ib_qp),
+				  qp->device, recv_wr, bad_recv_wr);
+}
+
+int ehca_post_srq_recv(struct ib_srq *srq,
+		       struct ib_recv_wr *recv_wr,
+		       struct ib_recv_wr **bad_recv_wr)
+{
+	return internal_post_recv(container_of(srq, struct ehca_qp, ib_srq),
+				  srq->device, recv_wr, bad_recv_wr);
+}
+
 /*
  * ib_wc_opcode table converts ehca wc opcode to ib
  * Since we use zero to indicate invalid opcode, the actual ib opcode must
@@ -494,6 +516,7 @@
 	int ret = 0;
 	struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
 	struct ehca_cqe *cqe;
+	struct ehca_qp *my_qp;
 	int cqe_count = 0;
 
 poll_cq_one_read_cqe:
@@ -513,7 +536,7 @@
 	if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) {
 		struct ehca_qp *qp=ehca_cq_get_qp(my_cq, cqe->local_qp_number);
 		int purgeflag;
-		unsigned long spl_flags;
+		unsigned long flags;
 		if (!qp) {
 			ehca_err(cq->device, "cq_num=%x qp_num=%x "
 				 "could not find qp -> ignore cqe",
@@ -523,9 +546,9 @@
 			/* ignore this purged cqe */
 			goto poll_cq_one_read_cqe;
 		}
-		spin_lock_irqsave(&qp->spinlock_s, spl_flags);
+		spin_lock_irqsave(&qp->spinlock_s, flags);
 		purgeflag = qp->sqerr_purgeflag;
-		spin_unlock_irqrestore(&qp->spinlock_s, spl_flags);
+		spin_unlock_irqrestore(&qp->spinlock_s, flags);
 
 		if (purgeflag) {
 			ehca_dbg(cq->device, "Got CQE with purged bit qp_num=%x "
@@ -545,7 +568,7 @@
 	}
 
 	/* tracing cqe */
-	if (ehca_debug_level) {
+	if (unlikely(ehca_debug_level)) {
 		ehca_dbg(cq->device,
 			 "Received COMPLETION ehca_cq=%p cq_num=%x -----",
 			 my_cq, my_cq->cq_number);
@@ -579,7 +602,11 @@
 	} else
 		wc->status = IB_WC_SUCCESS;
 
-	wc->qp = NULL;
+	read_lock(&ehca_qp_idr_lock);
+	my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
+	wc->qp = &my_qp->ib_qp;
+	read_unlock(&ehca_qp_idr_lock);
+
 	wc->byte_len = cqe->nr_bytes_transferred;
 	wc->pkey_index = cqe->pkey_index;
 	wc->slid = cqe->rlid;
@@ -589,7 +616,7 @@
 	wc->imm_data = cpu_to_be32(cqe->immediate_data);
 	wc->sl = cqe->service_level;
 
-	if (wc->status != IB_WC_SUCCESS)
+	if (unlikely(wc->status != IB_WC_SUCCESS))
 		ehca_dbg(cq->device,
 			 "ehca_cq=%p cq_num=%x WARNING unsuccessful cqe "
 			 "OPType=%x status=%x qp_num=%x src_qp=%x wr_id=%lx "
@@ -610,7 +637,7 @@
 	int nr;
 	struct ib_wc *current_wc = wc;
 	int ret = 0;
-	unsigned long spl_flags;
+	unsigned long flags;
 
 	if (num_entries < 1) {
 		ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p "
@@ -619,14 +646,14 @@
 		goto poll_cq_exit0;
 	}
 
-	spin_lock_irqsave(&my_cq->spinlock, spl_flags);
+	spin_lock_irqsave(&my_cq->spinlock, flags);
 	for (nr = 0; nr < num_entries; nr++) {
 		ret = ehca_poll_cq_one(cq, current_wc);
 		if (ret)
 			break;
 		current_wc++;
 	} /* eof for nr */
-	spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
+	spin_unlock_irqrestore(&my_cq->spinlock, flags);
 	if (ret == -EAGAIN  || !ret)
 		ret = nr;
 
@@ -637,7 +664,6 @@
 int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags)
 {
 	struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
-	unsigned long spl_flags;
 	int ret = 0;
 
 	switch (notify_flags & IB_CQ_SOLICITED_MASK) {
@@ -652,6 +678,7 @@
 	}
 
 	if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) {
+		unsigned long spl_flags;
 		spin_lock_irqsave(&my_cq->spinlock, spl_flags);
 		ret = ipz_qeit_is_valid(&my_cq->ipz_queue);
 		spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index 973c4b5..03b185f 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -59,6 +59,7 @@
 #include <linux/cpu.h>
 #include <linux/device.h>
 
+#include <asm/atomic.h>
 #include <asm/abs_addr.h>
 #include <asm/ibmebus.h>
 #include <asm/io.h>
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index 73db920..3031b3b 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -253,16 +253,16 @@
 	u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
 	u32 cur_pid = current->tgid;
 	u32 ret;
-	unsigned long flags;
 	struct ehca_cq *cq;
 	struct ehca_qp *qp;
 	struct ehca_pd *pd;
+	struct ib_uobject *uobject;
 
 	switch (q_type) {
 	case  1: /* CQ */
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+		read_lock(&ehca_cq_idr_lock);
 		cq = idr_find(&ehca_cq_idr, idr_handle);
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+		read_unlock(&ehca_cq_idr_lock);
 
 		/* make sure this mmap really belongs to the authorized user */
 		if (!cq)
@@ -288,9 +288,9 @@
 		break;
 
 	case 2: /* QP */
-		spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+		read_lock(&ehca_qp_idr_lock);
 		qp = idr_find(&ehca_qp_idr, idr_handle);
-		spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+		read_unlock(&ehca_qp_idr_lock);
 
 		/* make sure this mmap really belongs to the authorized user */
 		if (!qp)
@@ -304,7 +304,8 @@
 			return -ENOMEM;
 		}
 
-		if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context)
+		uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
+		if (!uobject || uobject->context != context)
 			return -EINVAL;
 
 		ret = ehca_mmap_qp(vma, qp, rsrc_type);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index 7f0beec..4776a8b 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -5,6 +5,7 @@
  *
  *  Authors: Christoph Raisch <raisch@de.ibm.com>
  *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *           Gerd Bayer <gerd.bayer@de.ibm.com>
  *           Waleri Fomin <fomin@de.ibm.com>
  *
@@ -62,6 +63,12 @@
 #define H_ALL_RES_QP_MAX_SEND_SGE       EHCA_BMASK_IBM(32, 39)
 #define H_ALL_RES_QP_MAX_RECV_SGE       EHCA_BMASK_IBM(40, 47)
 
+#define H_ALL_RES_QP_UD_AV_LKEY         EHCA_BMASK_IBM(32, 63)
+#define H_ALL_RES_QP_SRQ_QP_TOKEN       EHCA_BMASK_IBM(0, 31)
+#define H_ALL_RES_QP_SRQ_QP_HANDLE      EHCA_BMASK_IBM(0, 64)
+#define H_ALL_RES_QP_SRQ_LIMIT          EHCA_BMASK_IBM(48, 63)
+#define H_ALL_RES_QP_SRQ_QPN            EHCA_BMASK_IBM(40, 63)
+
 #define H_ALL_RES_QP_ACT_OUTST_SEND_WR  EHCA_BMASK_IBM(16, 31)
 #define H_ALL_RES_QP_ACT_OUTST_RECV_WR  EHCA_BMASK_IBM(48, 63)
 #define H_ALL_RES_QP_ACT_SEND_SGE       EHCA_BMASK_IBM(8, 15)
@@ -74,10 +81,7 @@
 #define H_MP_SHUTDOWN                   EHCA_BMASK_IBM(48, 48)
 #define H_MP_RESET_QKEY_CTR             EHCA_BMASK_IBM(49, 49)
 
-/* direct access qp controls */
-#define DAQP_CTRL_ENABLE    0x01
-#define DAQP_CTRL_SEND_COMP 0x20
-#define DAQP_CTRL_RECV_COMP 0x40
+static DEFINE_SPINLOCK(hcall_lock);
 
 static u32 get_longbusy_msecs(int longbusy_rc)
 {
@@ -155,7 +159,7 @@
 {
 	long ret;
 	int i, sleep_msecs, lock_is_set = 0;
-	unsigned long flags;
+	unsigned long flags = 0;
 
 	ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
 		     "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
@@ -284,54 +288,54 @@
 }
 
 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
-			     struct ehca_qp *qp,
 			     struct ehca_alloc_qp_parms *parms)
 {
 	u64 ret;
-	u64 allocate_controls;
-	u64 max_r10_reg;
+	u64 allocate_controls, max_r10_reg, r11, r12;
 	u64 outs[PLPAR_HCALL9_BUFSIZE];
-	u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1;
-	u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1;
-	int daqp_ctrl = parms->daqp_ctrl;
 
 	allocate_controls =
-		EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS,
-			       (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0)
+		EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
 		| EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
 		| EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
 		| EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
 		| EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
-				 (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0)
+				 !!(parms->ll_comp_flags & LLQP_RECV_COMP))
 		| EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
-				 (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0)
+				 !!(parms->ll_comp_flags & LLQP_SEND_COMP))
 		| EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
 				 parms->ud_av_l_key_ctl)
 		| EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
 
 	max_r10_reg =
 		EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
-			       max_nr_send_wqes)
+			       parms->max_send_wr + 1)
 		| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
-				 max_nr_receive_wqes)
+				 parms->max_recv_wr + 1)
 		| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
 				 parms->max_send_sge)
 		| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
 				 parms->max_recv_sge);
 
+	r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
+
+	if (parms->ext_type == EQPT_SRQ)
+		r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
+	else
+		r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
+
 	ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
 				adapter_handle.handle,	           /* r4  */
 				allocate_controls,	           /* r5  */
-				qp->send_cq->ipz_cq_handle.handle,
-				qp->recv_cq->ipz_cq_handle.handle,
-				parms->ipz_eq_handle.handle,
-				((u64)qp->token << 32) | parms->pd.value,
-				max_r10_reg,	                   /* r10 */
-				parms->ud_av_l_key_ctl,            /* r11 */
-				0);
-	qp->ipz_qp_handle.handle = outs[0];
-	qp->real_qp_num = (u32)outs[1];
-	parms->act_nr_send_sges =
+				parms->send_cq_handle.handle,
+				parms->recv_cq_handle.handle,
+				parms->eq_handle.handle,
+				((u64)parms->token << 32) | parms->pd.value,
+				max_r10_reg, r11, r12);
+
+	parms->qp_handle.handle = outs[0];
+	parms->real_qp_num = (u32)outs[1];
+	parms->act_nr_send_wqes =
 		(u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
 	parms->act_nr_recv_wqes =
 		(u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
@@ -345,7 +349,7 @@
 		(u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
 
 	if (ret == H_SUCCESS)
-		hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]);
+		hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
 
 	if (ret == H_NOT_ENOUGH_RESOURCES)
 		ehca_gen_err("Not enough resources. ret=%lx", ret);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h
index 2869f7d..60ce02b 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.h
+++ b/drivers/infiniband/hw/ehca/hcp_if.h
@@ -78,7 +78,6 @@
  * initialize resources, create empty QPPTs (2 rings).
  */
 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
-			     struct ehca_qp *qp,
 			     struct ehca_alloc_qp_parms *parms);
 
 u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h
index fad9136..dad6dea 100644
--- a/drivers/infiniband/hw/ehca/hipz_hw.h
+++ b/drivers/infiniband/hw/ehca/hipz_hw.h
@@ -163,6 +163,7 @@
 
 #define QPX_SQADDER EHCA_BMASK_IBM(48,63)
 #define QPX_RQADDER EHCA_BMASK_IBM(48,63)
+#define QPX_AAELOG_RESET_SRQ_LIMIT EHCA_BMASK_IBM(3,3)
 
 #define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm,x)
 
@@ -360,6 +361,24 @@
 	u32 max_neq;
 } __attribute__ ((packed));
 
+#define HCA_CAP_AH_PORT_NR_CHECK      EHCA_BMASK_IBM( 0,  0)
+#define HCA_CAP_ATOMIC                EHCA_BMASK_IBM( 1,  1)
+#define HCA_CAP_AUTO_PATH_MIG         EHCA_BMASK_IBM( 2,  2)
+#define HCA_CAP_BAD_P_KEY_CTR         EHCA_BMASK_IBM( 3,  3)
+#define HCA_CAP_SQD_RTS_PORT_CHANGE   EHCA_BMASK_IBM( 4,  4)
+#define HCA_CAP_CUR_QP_STATE_MOD      EHCA_BMASK_IBM( 5,  5)
+#define HCA_CAP_INIT_TYPE             EHCA_BMASK_IBM( 6,  6)
+#define HCA_CAP_PORT_ACTIVE_EVENT     EHCA_BMASK_IBM( 7,  7)
+#define HCA_CAP_Q_KEY_VIOL_CTR        EHCA_BMASK_IBM( 8,  8)
+#define HCA_CAP_WQE_RESIZE            EHCA_BMASK_IBM( 9,  9)
+#define HCA_CAP_RAW_PACKET_MCAST      EHCA_BMASK_IBM(10, 10)
+#define HCA_CAP_SHUTDOWN_PORT         EHCA_BMASK_IBM(11, 11)
+#define HCA_CAP_RC_LL_QP              EHCA_BMASK_IBM(12, 12)
+#define HCA_CAP_SRQ                   EHCA_BMASK_IBM(13, 13)
+#define HCA_CAP_UD_LL_QP              EHCA_BMASK_IBM(16, 16)
+#define HCA_CAP_RESIZE_MR             EHCA_BMASK_IBM(17, 17)
+#define HCA_CAP_MINI_QP               EHCA_BMASK_IBM(18, 18)
+
 /* query port response block */
 struct hipz_query_port {
 	u32 state;
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
index 57f141a..007f088 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.h
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
@@ -105,7 +105,6 @@
  * step in struct ipz_queue, will wrap in ringbuffer
  * returns address (kv) of Queue Entry BEFORE increment
  * warning don't use in parallel with ipz_qpageit_get_inc()
- * warning unpredictable results may occur if steps>act_nr_of_queue_entries
  */
 static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
 {
@@ -121,31 +120,24 @@
 }
 
 /*
+ * return a bool indicating whether current Queue Entry is valid
+ */
+static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
+{
+	struct ehca_cqe *cqe = ipz_qeit_get(queue);
+	return ((cqe->cqe_flags >> 7) == (queue->toggle_state & 1));
+}
+
+/*
  * return current Queue Entry, increment Queue Entry iterator by one
  * step in struct ipz_queue, will wrap in ringbuffer
  * returns address (kv) of Queue Entry BEFORE increment
  * returns 0 and does not increment, if wrong valid state
  * warning don't use in parallel with ipz_qpageit_get_inc()
- * warning unpredictable results may occur if steps>act_nr_of_queue_entries
  */
 static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
 {
-	struct ehca_cqe *cqe = ipz_qeit_get(queue);
-	u32 cqe_flags = cqe->cqe_flags;
-
-	if ((cqe_flags >> 7) != (queue->toggle_state & 1))
-		return NULL;
-
-	ipz_qeit_get_inc(queue);
-	return cqe;
-}
-
-static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
-{
-	struct ehca_cqe *cqe = ipz_qeit_get(queue);
-	u32 cqe_flags = cqe->cqe_flags;
-
-	return cqe_flags >> 7 == (queue->toggle_state & 1);
+	return ipz_qeit_is_valid(queue) ? ipz_qeit_get_inc(queue) : NULL;
 }
 
 /*
diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig
index 90c1454..044da58 100644
--- a/drivers/infiniband/hw/ipath/Kconfig
+++ b/drivers/infiniband/hw/ipath/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_IPATH
 	tristate "QLogic InfiniPath Driver"
-	depends on (PCI_MSI || HT_IRQ) && 64BIT && INFINIBAND && NET
+	depends on (PCI_MSI || HT_IRQ) && 64BIT && NET
 	---help---
 	This is a driver for QLogic InfiniPath host channel adapters,
 	including InfiniBand verbs support.  This driver allows these
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
index 10c008f..b4b786d 100644
--- a/drivers/infiniband/hw/ipath/ipath_common.h
+++ b/drivers/infiniband/hw/ipath/ipath_common.h
@@ -189,8 +189,7 @@
 #define IPATH_RUNTIME_FORCE_WC_ORDER	0x4
 #define IPATH_RUNTIME_RCVHDR_COPY	0x8
 #define IPATH_RUNTIME_MASTER	0x10
-#define IPATH_RUNTIME_PBC_REWRITE 0x20
-#define IPATH_RUNTIME_LOOSE_DMA_ALIGN 0x40
+/* 0x20 and 0x40 are no longer used, but are reserved for ABI compatibility */
 
 /*
  * This structure is returned by ipath_userinit() immediately after
@@ -432,8 +431,15 @@
 #define IPATH_CMD_UNUSED_1	25
 #define IPATH_CMD_UNUSED_2	26
 #define IPATH_CMD_PIOAVAILUPD	27	/* force an update of PIOAvail reg */
+#define IPATH_CMD_POLL_TYPE	28	/* set the kind of polling we want */
 
-#define IPATH_CMD_MAX		27
+#define IPATH_CMD_MAX		28
+
+/*
+ * Poll types
+ */
+#define IPATH_POLL_TYPE_URGENT	 0x01
+#define IPATH_POLL_TYPE_OVERFLOW 0x02
 
 struct ipath_port_info {
 	__u32 num_active;	/* number of active units */
@@ -474,6 +480,8 @@
 		__u16 part_key;
 		/* user address of __u32 bitmask of active slaves */
 		__u64 slave_mask_addr;
+		/* type of polling we want */
+		__u16 poll_type;
 	} cmd;
 };
 
@@ -502,13 +510,30 @@
 	struct ipath_iovec sps_iov[4];
 };
 
-/* Passed into diag data special file's ->write method. */
+/*
+ * diagnostics can send a packet by "writing" one of the following
+ * two structs to diag data special file
+ * The first is the legacy version for backward compatibility
+ */
 struct ipath_diag_pkt {
 	__u32 unit;
 	__u64 data;
 	__u32 len;
 };
 
+/* The second diag_pkt struct is the expanded version that allows
+ * more control over the packet, specifically, by allowing a custom
+ * pbc (+ extra) qword, so that special modes and deliberate
+ * changes to CRCs can be used. The elements were also re-ordered
+ * for better alignment and to avoid padding issues.
+ */
+struct ipath_diag_xpkt {
+	__u64 data;
+	__u64 pbc_wd;
+	__u32 unit;
+	__u32 len;
+};
+
 /*
  * Data layout in I2C flash (for GUID, etc.)
  * All fields are little-endian binary unless otherwise stated
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
index 3e9241b..a6f04d2 100644
--- a/drivers/infiniband/hw/ipath/ipath_cq.c
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -90,6 +90,8 @@
 	wc->queue[head].sl = entry->sl;
 	wc->queue[head].dlid_path_bits = entry->dlid_path_bits;
 	wc->queue[head].port_num = entry->port_num;
+	/* Make sure queue entry is written before the head index. */
+	smp_wmb();
 	wc->head = next;
 
 	if (cq->notify == IB_CQ_NEXT_COMP ||
@@ -139,7 +141,8 @@
 
 		if (tail == wc->head)
 			break;
-
+		/* Make sure entry is read after head index is read. */
+		smp_rmb();
 		qp = ipath_lookup_qpn(&to_idev(cq->ibcq.device)->qp_table,
 				      wc->queue[tail].qp_num);
 		entry->qp = &qp->ibqp;
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
index 42bfbdb..19c56e6 100644
--- a/drivers/infiniband/hw/ipath/ipath_debug.h
+++ b/drivers/infiniband/hw/ipath/ipath_debug.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index 63e8368..a698f19 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -323,13 +323,14 @@
 {
 	u32 __iomem *piobuf;
 	u32 plen, clen, pbufn;
-	struct ipath_diag_pkt dp;
+	struct ipath_diag_pkt odp;
+	struct ipath_diag_xpkt dp;
 	u32 *tmpbuf = NULL;
 	struct ipath_devdata *dd;
 	ssize_t ret = 0;
 	u64 val;
 
-	if (count < sizeof(dp)) {
+	if (count != sizeof(dp)) {
 		ret = -EINVAL;
 		goto bail;
 	}
@@ -339,6 +340,29 @@
 		goto bail;
 	}
 
+	/*
+	 * Due to padding/alignment issues (lessened with new struct)
+	 * the old and new structs are the same length. We need to
+	 * disambiguate them, which we can do because odp.len has never
+	 * been less than the total of LRH+BTH+DETH so far, while
+	 * dp.unit (same offset) unit is unlikely to get that high.
+	 * Similarly, dp.data, the pointer to user at the same offset
+	 * as odp.unit, is almost certainly at least one (512byte)page
+	 * "above" NULL. The if-block below can be omitted if compatibility
+	 * between a new driver and older diagnostic code is unimportant.
+	 * compatibility the other direction (new diags, old driver) is
+	 * handled in the diagnostic code, with a warning.
+	 */
+	if (dp.unit >= 20 && dp.data < 512) {
+		/* very probable version mismatch. Fix it up */
+		memcpy(&odp, &dp, sizeof(odp));
+		/* We got a legacy dp, copy elements to dp */
+		dp.unit = odp.unit;
+		dp.data = odp.data;
+		dp.len = odp.len;
+		dp.pbc_wd = 0; /* Indicate we need to compute PBC wd */
+	}
+
 	/* send count must be an exact number of dwords */
 	if (dp.len & 3) {
 		ret = -EINVAL;
@@ -371,9 +395,10 @@
 		ret = -ENODEV;
 		goto bail;
 	}
+	/* Check link state, but not if we have custom PBC */
 	val = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
-	if (val != IPATH_IBSTATE_INIT && val != IPATH_IBSTATE_ARM &&
-	    val != IPATH_IBSTATE_ACTIVE) {
+	if (!dp.pbc_wd && val != IPATH_IBSTATE_INIT &&
+		val != IPATH_IBSTATE_ARM && val != IPATH_IBSTATE_ACTIVE) {
 		ipath_cdbg(VERBOSE, "unit %u not ready (state %llx)\n",
 			   dd->ipath_unit, (unsigned long long) val);
 		ret = -EINVAL;
@@ -419,9 +444,13 @@
 		ipath_cdbg(VERBOSE, "unit %u 0x%x+1w pio%d\n",
 			   dd->ipath_unit, plen - 1, pbufn);
 
+	if (dp.pbc_wd == 0)
+		/* Legacy operation, use computed pbc_wd */
+		dp.pbc_wd = plen;
+
 	/* we have to flush after the PBC for correctness on some cpus
 	 * or WC buffer can be written out of order */
-	writeq(plen, piobuf);
+	writeq(dp.pbc_wd, piobuf);
 	ipath_flush_wc();
 	/* copy all by the trigger word, then flush, so it's written
 	 * to chip before trigger word, then write trigger word, then
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index e3a2232..9361f5a 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -104,6 +104,9 @@
 #define PCI_DEVICE_ID_INFINIPATH_HT 0xd
 #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
 
+/* Number of seconds before our card status check...  */
+#define STATUS_TIMEOUT 60
+
 static const struct pci_device_id ipath_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
@@ -119,6 +122,18 @@
 	.id_table = ipath_pci_tbl,
 };
 
+static void ipath_check_status(struct work_struct *work)
+{
+	struct ipath_devdata *dd = container_of(work, struct ipath_devdata,
+						status_work.work);
+
+	/*
+	 * If we don't have any interrupts, let the user know and
+	 * don't bother checking again.
+	 */
+	if (dd->ipath_int_counter == 0)
+		dev_err(&dd->pcidev->dev, "No interrupts detected.\n");
+}
 
 static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
 			     u32 *bar0, u32 *bar1)
@@ -187,6 +202,8 @@
 	dd->pcidev = pdev;
 	pci_set_drvdata(pdev, dd);
 
+	INIT_DELAYED_WORK(&dd->status_work, ipath_check_status);
+
 	list_add(&dd->ipath_list, &ipath_dev_list);
 
 bail_unlock:
@@ -270,7 +287,6 @@
 	struct ipath_devdata *dd;
 	unsigned long long addr;
 	u32 bar0 = 0, bar1 = 0;
-	u8 rev;
 
 	dd = ipath_alloc_devdata(pdev);
 	if (IS_ERR(dd)) {
@@ -432,13 +448,7 @@
 	dd->ipath_deviceid = ent->device;	/* save for later use */
 	dd->ipath_vendorid = ent->vendor;
 
-	ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-	if (ret) {
-		ipath_dev_err(dd, "Failed to read PCI revision ID unit "
-			      "%u: err %d\n", dd->ipath_unit, -ret);
-		goto bail_regions;	/* shouldn't ever happen */
-	}
-	dd->ipath_pcirev = rev;
+	dd->ipath_pcirev = pdev->revision;
 
 #if defined(__powerpc__)
 	/* There isn't a generic way to specify writethrough mappings */
@@ -511,6 +521,9 @@
 	ipath_diag_add(dd);
 	ipath_register_ib_device(dd);
 
+	/* Check that card status in STATUS_TIMEOUT seconds. */
+	schedule_delayed_work(&dd->status_work, HZ * STATUS_TIMEOUT);
+
 	goto bail;
 
 bail_irqsetup:
@@ -638,6 +651,9 @@
 	 */
 	ipath_shutdown_device(dd);
 
+	cancel_delayed_work(&dd->status_work);
+	flush_scheduled_work();
+
 	if (dd->verbs_dev)
 		ipath_unregister_ib_device(dd->verbs_dev);
 
@@ -706,9 +722,9 @@
 	u64 sendctrl, sendorig;
 
 	ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
-	sendorig = dd->ipath_sendctrl | INFINIPATH_S_DISARM;
+	sendorig = dd->ipath_sendctrl;
 	for (i = first; i < last; i++) {
-		sendctrl = sendorig |
+		sendctrl = sendorig  | INFINIPATH_S_DISARM |
 			(i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
 		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
 				 sendctrl);
@@ -719,12 +735,12 @@
 	 * while we were looping; no critical bits that would require
 	 * locking.
 	 *
-	 * Write a 0, and then the original value, reading scratch in
+	 * disable PIOAVAILUPD, then re-enable, reading scratch in
 	 * between.  This seems to avoid a chip timing race that causes
 	 * pioavail updates to memory to stop.
 	 */
 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-			 0);
+			 sendorig & ~IPATH_S_PIOBUFAVAILUPD);
 	sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
 			 dd->ipath_sendctrl);
@@ -1021,14 +1037,10 @@
 		goto bail;
 	}
 
-	/* There is already a thread processing this queue. */
-	if (test_and_set_bit(0, &dd->ipath_rcv_pending))
-		goto bail;
-
 	l = dd->ipath_port0head;
 	hdrqtail = (u32) le64_to_cpu(*dd->ipath_hdrqtailptr);
 	if (l == hdrqtail)
-		goto done;
+		goto bail;
 
 reloop:
 	for (i = 0; l != hdrqtail; i++) {
@@ -1163,10 +1175,6 @@
 	ipath_stats.sps_avgpkts_call =
 		ipath_stats.sps_port0pkts / ++totcalls;
 
-done:
-	clear_bit(0, &dd->ipath_rcv_pending);
-	smp_mb__after_clear_bit();
-
 bail:;
 }
 
@@ -1596,6 +1604,35 @@
 	return ret;
 }
 
+
+/*
+ * Flush all sends that might be in the ready to send state, as well as any
+ * that are in the process of being sent.   Used whenever we need to be
+ * sure the send side is idle.  Cleans up all buffer state by canceling
+ * all pio buffers, and issuing an abort, which cleans up anything in the
+ * launch fifo.  The cancel is superfluous on some chip versions, but
+ * it's safer to always do it.
+ * PIOAvail bits are updated by the chip as if normal send had happened.
+ */
+void ipath_cancel_sends(struct ipath_devdata *dd)
+{
+	ipath_dbg("Cancelling all in-progress send buffers\n");
+	dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */
+	/*
+	 * the abort bit is auto-clearing.  We read scratch to be sure
+	 * that cancels and the abort have taken effect in the chip.
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+		INFINIPATH_S_ABORT);
+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+	ipath_disarm_piobufs(dd, 0,
+		(unsigned)(dd->ipath_piobcnt2k + dd->ipath_piobcnt4k));
+
+	/* and again, be sure all have hit the chip */
+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+}
+
+
 static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
 {
 	static const char *what[4] = {
@@ -1617,14 +1654,8 @@
 			   INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
 	/* flush all queued sends when going to DOWN or INIT, to be sure that
 	 * they don't block MAD packets */
-	if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) {
-		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-				 INFINIPATH_S_ABORT);
-		ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
-		                    (unsigned)(dd->ipath_piobcnt2k +
-				    dd->ipath_piobcnt4k) -
-				    dd->ipath_lastport_piobuf);
-	}
+	if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT)
+		ipath_cancel_sends(dd);
 
 	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
 			 dd->ipath_ibcctrl | which);
@@ -1846,6 +1877,87 @@
 	ipath_write_kreg(dd, where, value);
 }
 
+/*
+ * Following deal with the "obviously simple" task of overriding the state
+ * of the LEDS, which normally indicate link physical and logical status.
+ * The complications arise in dealing with different hardware mappings
+ * and the board-dependent routine being called from interrupts.
+ * and then there's the requirement to _flash_ them.
+ */
+#define LED_OVER_FREQ_SHIFT 8
+#define LED_OVER_FREQ_MASK (0xFF<<LED_OVER_FREQ_SHIFT)
+/* Below is "non-zero" to force override, but both actual LEDs are off */
+#define LED_OVER_BOTH_OFF (8)
+
+void ipath_run_led_override(unsigned long opaque)
+{
+	struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
+	int timeoff;
+	int pidx;
+	u64 lstate, ltstate, val;
+
+	if (!(dd->ipath_flags & IPATH_INITTED))
+		return;
+
+	pidx = dd->ipath_led_override_phase++ & 1;
+	dd->ipath_led_override = dd->ipath_led_override_vals[pidx];
+	timeoff = dd->ipath_led_override_timeoff;
+
+	/*
+	 * below potentially restores the LED values per current status,
+	 * should also possibly setup the traffic-blink register,
+	 * but leave that to per-chip functions.
+	 */
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+	ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+		  INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+	lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+		 INFINIPATH_IBCS_LINKSTATE_MASK;
+
+	dd->ipath_f_setextled(dd, lstate, ltstate);
+	mod_timer(&dd->ipath_led_override_timer, jiffies + timeoff);
+}
+
+void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
+{
+	int timeoff, freq;
+
+	if (!(dd->ipath_flags & IPATH_INITTED))
+		return;
+
+	/* First check if we are blinking. If not, use 1HZ polling */
+	timeoff = HZ;
+	freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT;
+
+	if (freq) {
+		/* For blink, set each phase from one nybble of val */
+		dd->ipath_led_override_vals[0] = val & 0xF;
+		dd->ipath_led_override_vals[1] = (val >> 4) & 0xF;
+		timeoff = (HZ << 4)/freq;
+	} else {
+		/* Non-blink set both phases the same. */
+		dd->ipath_led_override_vals[0] = val & 0xF;
+		dd->ipath_led_override_vals[1] = val & 0xF;
+	}
+	dd->ipath_led_override_timeoff = timeoff;
+
+	/*
+	 * If the timer has not already been started, do so. Use a "quick"
+	 * timeout so the function will be called soon, to look at our request.
+	 */
+	if (atomic_inc_return(&dd->ipath_led_override_timer_active) == 1) {
+		/* Need to start timer */
+		init_timer(&dd->ipath_led_override_timer);
+		dd->ipath_led_override_timer.function =
+						 ipath_run_led_override;
+		dd->ipath_led_override_timer.data = (unsigned long) dd;
+		dd->ipath_led_override_timer.expires = jiffies + 1;
+		add_timer(&dd->ipath_led_override_timer);
+	} else {
+		atomic_dec(&dd->ipath_led_override_timer_active);
+	}
+}
+
 /**
  * ipath_shutdown_device - shut down a device
  * @dd: the infinipath device
@@ -1886,17 +1998,9 @@
 	 */
 	udelay(5);
 
-	/*
-	 * abort any armed or launched PIO buffers that didn't go. (self
-	 * clearing).  Will cause any packet currently being transmitted to
-	 * go out with an EBP, and may also cause a short packet error on
-	 * the receiver.
-	 */
-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-			 INFINIPATH_S_ABORT);
-
 	ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
 			    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+	ipath_cancel_sends(dd);
 
 	/* disable IBC */
 	dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
@@ -1909,7 +2013,6 @@
 	 * Turn the LEDs off explictly for the same reason.
 	 */
 	dd->ipath_f_quiet_serdes(dd);
-	dd->ipath_f_setextled(dd, 0, 0);
 
 	if (dd->ipath_stats_timer_active) {
 		del_timer_sync(&dd->ipath_stats_timer);
@@ -1925,6 +2028,9 @@
 			 ~0ULL & ~INFINIPATH_HWE_MEMBISTFAILED);
 	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL);
 	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+
+	ipath_cdbg(VERBOSE, "Flush time and errors to EEPROM\n");
+	ipath_update_eeprom_log(dd);
 }
 
 /**
@@ -2085,6 +2191,16 @@
 		goto bail;
 	}
 
+	if (atomic_read(&dd->ipath_led_override_timer_active)) {
+		/* Need to stop LED timer, _then_ shut off LEDs */
+		del_timer_sync(&dd->ipath_led_override_timer);
+		atomic_set(&dd->ipath_led_override_timer_active, 0);
+	}
+
+	/* Shut off LEDs after we are sure timer is not running */
+	dd->ipath_led_override = LED_OVER_BOTH_OFF;
+	dd->ipath_f_setextled(dd, 0, 0);
+
 	dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit);
 
 	if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) {
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
index 030185f..6b91479 100644
--- a/drivers/infiniband/hw/ipath/ipath_eeprom.c
+++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -95,39 +95,37 @@
 			enum i2c_type line,
 			enum i2c_state new_line_state)
 {
-	u64 read_val, write_val, mask, *gpioval;
+	u64 out_mask, dir_mask, *gpioval;
+	unsigned long flags = 0;
 
 	gpioval = &dd->ipath_gpio_out;
-	read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
-	if (line == i2c_line_scl)
-		mask = dd->ipath_gpio_scl;
-	else
-		mask = dd->ipath_gpio_sda;
-
-	if (new_line_state == i2c_line_high)
-		/* tri-state the output rather than force high */
-		write_val = read_val & ~mask;
-	else
-		/* config line to be an output */
-		write_val = read_val | mask;
-	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
-
-	/* set high and verify */
-	if (new_line_state == i2c_line_high)
-		write_val = 0x1UL;
-	else
-		write_val = 0x0UL;
 
 	if (line == i2c_line_scl) {
-		write_val <<= dd->ipath_gpio_scl_num;
-		*gpioval = *gpioval & ~(1UL << dd->ipath_gpio_scl_num);
-		*gpioval |= write_val;
+		dir_mask = dd->ipath_gpio_scl;
+		out_mask = (1UL << dd->ipath_gpio_scl_num);
 	} else {
-		write_val <<= dd->ipath_gpio_sda_num;
-		*gpioval = *gpioval & ~(1UL << dd->ipath_gpio_sda_num);
-		*gpioval |= write_val;
+		dir_mask = dd->ipath_gpio_sda;
+		out_mask = (1UL << dd->ipath_gpio_sda_num);
 	}
+
+	spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+	if (new_line_state == i2c_line_high) {
+		/* tri-state the output rather than force high */
+		dd->ipath_extctrl &= ~dir_mask;
+	} else {
+		/* config line to be an output */
+		dd->ipath_extctrl |= dir_mask;
+	}
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl);
+
+	/* set output as well (no real verify) */
+	if (new_line_state == i2c_line_high)
+		*gpioval |= out_mask;
+	else
+		*gpioval &= ~out_mask;
+
 	ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval);
+	spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
 
 	return 0;
 }
@@ -145,8 +143,9 @@
 			enum i2c_type line,
 			enum i2c_state *curr_statep)
 {
-	u64 read_val, write_val, mask;
+	u64 read_val, mask;
 	int ret;
+	unsigned long flags = 0;
 
 	/* check args */
 	if (curr_statep == NULL) {
@@ -154,15 +153,21 @@
 		goto bail;
 	}
 
-	read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
 	/* config line to be an input */
 	if (line == i2c_line_scl)
 		mask = dd->ipath_gpio_scl;
 	else
 		mask = dd->ipath_gpio_sda;
-	write_val = read_val & ~mask;
-	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+
+	spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+	dd->ipath_extctrl &= ~mask;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl);
+	/*
+	 * Below is very unlikely to reflect true input state if Output
+	 * Enable actually changed.
+	 */
 	read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+	spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
 
 	if (read_val & mask)
 		*curr_statep = i2c_line_high;
@@ -192,6 +197,7 @@
 
 static void scl_out(struct ipath_devdata *dd, u8 bit)
 {
+	udelay(1);
 	i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low);
 
 	i2c_wait_for_writes(dd);
@@ -314,12 +320,18 @@
 	int clock_cycles_left = 9;
 	u64 *gpioval = &dd->ipath_gpio_out;
 	int ret;
+	unsigned long flags;
 
-	eeprom_init = 1;
+	spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+	/* Make sure shadows are consistent */
+	dd->ipath_extctrl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
 	*gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out);
+	spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
+
 	ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
 		   "is %llx\n", (unsigned long long) *gpioval);
 
+	eeprom_init = 1;
 	/*
 	 * This is to get the i2c into a known state, by first going low,
 	 * then tristate sda (and then tristate scl as first thing
@@ -355,8 +367,8 @@
  * @len: number of bytes to receive
  */
 
-int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
-		      void *buffer, int len)
+static int ipath_eeprom_internal_read(struct ipath_devdata *dd,
+					u8 eeprom_offset, void *buffer, int len)
 {
 	/* compiler complains unless initialized */
 	u8 single_byte = 0;
@@ -406,6 +418,7 @@
 	return ret;
 }
 
+
 /**
  * ipath_eeprom_write - writes data to the eeprom via I2C
  * @dd: the infinipath device
@@ -413,8 +426,8 @@
  * @buffer: data to write
  * @len: number of bytes to write
  */
-int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
-		       const void *buffer, int len)
+int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset,
+				const void *buffer, int len)
 {
 	u8 single_byte;
 	int sub_len;
@@ -488,6 +501,38 @@
 	return ret;
 }
 
+/*
+ * The public entry-points ipath_eeprom_read() and ipath_eeprom_write()
+ * are now just wrappers around the internal functions.
+ */
+int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+			void *buff, int len)
+{
+	int ret;
+
+	ret = down_interruptible(&dd->ipath_eep_sem);
+	if (!ret) {
+		ret = ipath_eeprom_internal_read(dd, eeprom_offset, buff, len);
+		up(&dd->ipath_eep_sem);
+	}
+
+	return ret;
+}
+
+int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
+			const void *buff, int len)
+{
+	int ret;
+
+	ret = down_interruptible(&dd->ipath_eep_sem);
+	if (!ret) {
+		ret = ipath_eeprom_internal_write(dd, eeprom_offset, buff, len);
+		up(&dd->ipath_eep_sem);
+	}
+
+	return ret;
+}
+
 static u8 flash_csum(struct ipath_flash *ifp, int adjust)
 {
 	u8 *ip = (u8 *) ifp;
@@ -515,7 +560,7 @@
 	void *buf;
 	struct ipath_flash *ifp;
 	__be64 guid;
-	int len;
+	int len, eep_stat;
 	u8 csum, *bguid;
 	int t = dd->ipath_unit;
 	struct ipath_devdata *dd0 = ipath_lookup(0);
@@ -559,7 +604,11 @@
 		goto bail;
 	}
 
-	if (ipath_eeprom_read(dd, 0, buf, len)) {
+	down(&dd->ipath_eep_sem);
+	eep_stat = ipath_eeprom_internal_read(dd, 0, buf, len);
+	up(&dd->ipath_eep_sem);
+
+	if (eep_stat) {
 		ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
 		goto done;
 	}
@@ -634,8 +683,192 @@
 	ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n",
 		   (unsigned long long) be64_to_cpu(dd->ipath_guid));
 
+	memcpy(&dd->ipath_eep_st_errs, &ifp->if_errcntp, IPATH_EEP_LOG_CNT);
+	/*
+	 * Power-on (actually "active") hours are kept as little-endian value
+	 * in EEPROM, but as seconds in a (possibly as small as 24-bit)
+	 * atomic_t while running.
+	 */
+	atomic_set(&dd->ipath_active_time, 0);
+	dd->ipath_eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8);
+
 done:
 	vfree(buf);
 
 bail:;
 }
+
+/**
+ * ipath_update_eeprom_log - copy active-time and error counters to eeprom
+ * @dd: the infinipath device
+ *
+ * Although the time is kept as seconds in the ipath_devdata struct, it is
+ * rounded to hours for re-write, as we have only 16 bits in EEPROM.
+ * First-cut code reads whole (expected) struct ipath_flash, modifies,
+ * re-writes. Future direction: read/write only what we need, assuming
+ * that the EEPROM had to have been "good enough" for driver init, and
+ * if not, we aren't making it worse.
+ *
+ */
+
+int ipath_update_eeprom_log(struct ipath_devdata *dd)
+{
+	void *buf;
+	struct ipath_flash *ifp;
+	int len, hi_water;
+	uint32_t new_time, new_hrs;
+	u8 csum;
+	int ret, idx;
+	unsigned long flags;
+
+	/* first, check if we actually need to do anything. */
+	ret = 0;
+	for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+		if (dd->ipath_eep_st_new_errs[idx]) {
+			ret = 1;
+			break;
+		}
+	}
+	new_time = atomic_read(&dd->ipath_active_time);
+
+	if (ret == 0 && new_time < 3600)
+		return 0;
+
+	/*
+	 * The quick-check above determined that there is something worthy
+	 * of logging, so get current contents and do a more detailed idea.
+	 */
+	len = offsetof(struct ipath_flash, if_future);
+	buf = vmalloc(len);
+	ret = 1;
+	if (!buf) {
+		ipath_dev_err(dd, "Couldn't allocate memory to read %u "
+				"bytes from eeprom for logging\n", len);
+		goto bail;
+	}
+
+	/* Grab semaphore and read current EEPROM. If we get an
+	 * error, let go, but if not, keep it until we finish write.
+	 */
+	ret = down_interruptible(&dd->ipath_eep_sem);
+	if (ret) {
+		ipath_dev_err(dd, "Unable to acquire EEPROM for logging\n");
+		goto free_bail;
+	}
+	ret = ipath_eeprom_internal_read(dd, 0, buf, len);
+	if (ret) {
+		up(&dd->ipath_eep_sem);
+		ipath_dev_err(dd, "Unable read EEPROM for logging\n");
+		goto free_bail;
+	}
+	ifp = (struct ipath_flash *)buf;
+
+	csum = flash_csum(ifp, 0);
+	if (csum != ifp->if_csum) {
+		up(&dd->ipath_eep_sem);
+		ipath_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
+				csum, ifp->if_csum);
+		ret = 1;
+		goto free_bail;
+	}
+	hi_water = 0;
+	spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+	for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+		int new_val = dd->ipath_eep_st_new_errs[idx];
+		if (new_val) {
+			/*
+			 * If we have seen any errors, add to EEPROM values
+			 * We need to saturate at 0xFF (255) and we also
+			 * would need to adjust the checksum if we were
+			 * trying to minimize EEPROM traffic
+			 * Note that we add to actual current count in EEPROM,
+			 * in case it was altered while we were running.
+			 */
+			new_val += ifp->if_errcntp[idx];
+			if (new_val > 0xFF)
+				new_val = 0xFF;
+			if (ifp->if_errcntp[idx] != new_val) {
+				ifp->if_errcntp[idx] = new_val;
+				hi_water = offsetof(struct ipath_flash,
+						if_errcntp) + idx;
+			}
+			/*
+			 * update our shadow (used to minimize EEPROM
+			 * traffic), to match what we are about to write.
+			 */
+			dd->ipath_eep_st_errs[idx] = new_val;
+			dd->ipath_eep_st_new_errs[idx] = 0;
+		}
+	}
+	/*
+	 * now update active-time. We would like to round to the nearest hour
+	 * but unless atomic_t are sure to be proper signed ints we cannot,
+	 * because we need to account for what we "transfer" to EEPROM and
+	 * if we log an hour at 31 minutes, then we would need to set
+	 * active_time to -29 to accurately count the _next_ hour.
+	 */
+	if (new_time > 3600) {
+		new_hrs = new_time / 3600;
+		atomic_sub((new_hrs * 3600), &dd->ipath_active_time);
+		new_hrs += dd->ipath_eep_hrs;
+		if (new_hrs > 0xFFFF)
+			new_hrs = 0xFFFF;
+		dd->ipath_eep_hrs = new_hrs;
+		if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) {
+			ifp->if_powerhour[0] = new_hrs & 0xFF;
+			hi_water = offsetof(struct ipath_flash, if_powerhour);
+		}
+		if ((new_hrs >> 8) != ifp->if_powerhour[1]) {
+			ifp->if_powerhour[1] = new_hrs >> 8;
+			hi_water = offsetof(struct ipath_flash, if_powerhour)
+					+ 1;
+		}
+	}
+	/*
+	 * There is a tiny possibility that we could somehow fail to write
+	 * the EEPROM after updating our shadows, but problems from holding
+	 * the spinlock too long are a much bigger issue.
+	 */
+	spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+	if (hi_water) {
+		/* we made some change to the data, uopdate cksum and write */
+		csum = flash_csum(ifp, 1);
+		ret = ipath_eeprom_internal_write(dd, 0, buf, hi_water + 1);
+	}
+	up(&dd->ipath_eep_sem);
+	if (ret)
+		ipath_dev_err(dd, "Failed updating EEPROM\n");
+
+free_bail:
+	vfree(buf);
+bail:
+	return ret;
+
+}
+
+/**
+ * ipath_inc_eeprom_err - increment one of the four error counters
+ * that are logged to EEPROM.
+ * @dd: the infinipath device
+ * @eidx: 0..3, the counter to increment
+ * @incr: how much to add
+ *
+ * Each counter is 8-bits, and saturates at 255 (0xFF). They
+ * are copied to the EEPROM (aka flash) whenever ipath_update_eeprom_log()
+ * is called, but it can only be called in a context that allows sleep.
+ * This function can be called even at interrupt level.
+ */
+
+void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr)
+{
+	uint new_val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+	new_val = dd->ipath_eep_st_new_errs[eidx] + incr;
+	if (new_val > 255)
+		new_val = 255;
+	dd->ipath_eep_st_new_errs[eidx] = new_val;
+	spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+	return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 1272aaf..33ab0d6 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -396,7 +396,8 @@
 			   "TID %u, vaddr %lx, physaddr %llx pgp %p\n",
 			   tid, vaddr, (unsigned long long) physaddr,
 			   pagep[i]);
-		dd->ipath_f_put_tid(dd, &tidbase[tid], 1, physaddr);
+		dd->ipath_f_put_tid(dd, &tidbase[tid], RCVHQ_RCV_TYPE_EXPECTED,
+				    physaddr);
 		/*
 		 * don't check this tid in ipath_portshadow, since we
 		 * just filled it in; start with the next one.
@@ -422,7 +423,8 @@
 			if (dd->ipath_pageshadow[porttid + tid]) {
 				ipath_cdbg(VERBOSE, "Freeing TID %u\n",
 					   tid);
-				dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+				dd->ipath_f_put_tid(dd, &tidbase[tid],
+						    RCVHQ_RCV_TYPE_EXPECTED,
 						    dd->ipath_tidinvalid);
 				pci_unmap_page(dd->pcidev,
 					dd->ipath_physshadow[porttid + tid],
@@ -538,7 +540,8 @@
 		if (dd->ipath_pageshadow[porttid + tid]) {
 			ipath_cdbg(VERBOSE, "PID %u freeing TID %u\n",
 				   pd->port_pid, tid);
-			dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+			dd->ipath_f_put_tid(dd, &tidbase[tid],
+					    RCVHQ_RCV_TYPE_EXPECTED,
 					    dd->ipath_tidinvalid);
 			pci_unmap_page(dd->pcidev,
 				dd->ipath_physshadow[porttid + tid],
@@ -921,7 +924,8 @@
 					    (u64 __iomem *)
 					    ((char __iomem *)
 					     dd->ipath_kregbase +
-					     dd->ipath_rcvegrbase), 0, pa);
+					     dd->ipath_rcvegrbase),
+					    RCVHQ_RCV_TYPE_EAGER, pa);
 			pa += egrsize;
 		}
 		cond_resched();	/* don't hog the cpu */
@@ -1337,68 +1341,133 @@
 	return ret;
 }
 
+static unsigned int ipath_poll_urgent(struct ipath_portdata *pd,
+				      struct file *fp,
+				      struct poll_table_struct *pt)
+{
+	unsigned pollflag = 0;
+	struct ipath_devdata *dd;
+
+	dd = pd->port_dd;
+
+	if (test_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag)) {
+		pollflag |= POLLERR;
+		clear_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag);
+	}
+
+	if (test_bit(IPATH_PORT_WAITING_URG, &pd->int_flag)) {
+		pollflag |= POLLIN | POLLRDNORM;
+		clear_bit(IPATH_PORT_WAITING_URG, &pd->int_flag);
+	}
+
+	if (!pollflag) {
+		set_bit(IPATH_PORT_WAITING_URG, &pd->port_flag);
+		if (pd->poll_type & IPATH_POLL_TYPE_OVERFLOW)
+			set_bit(IPATH_PORT_WAITING_OVERFLOW,
+				&pd->port_flag);
+
+		poll_wait(fp, &pd->port_wait, pt);
+	}
+
+	return pollflag;
+}
+
+static unsigned int ipath_poll_next(struct ipath_portdata *pd,
+				    struct file *fp,
+				    struct poll_table_struct *pt)
+{
+	u32 head, tail;
+	unsigned pollflag = 0;
+	struct ipath_devdata *dd;
+
+	dd = pd->port_dd;
+
+	head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
+	tail = *(volatile u64 *)pd->port_rcvhdrtail_kvaddr;
+
+	if (test_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag)) {
+		pollflag |= POLLERR;
+		clear_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag);
+	}
+
+	if (tail != head ||
+	    test_bit(IPATH_PORT_WAITING_RCV, &pd->int_flag)) {
+		pollflag |= POLLIN | POLLRDNORM;
+		clear_bit(IPATH_PORT_WAITING_RCV, &pd->int_flag);
+	}
+
+	if (!pollflag) {
+		set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
+		if (pd->poll_type & IPATH_POLL_TYPE_OVERFLOW)
+			set_bit(IPATH_PORT_WAITING_OVERFLOW,
+				&pd->port_flag);
+
+		set_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
+			&dd->ipath_rcvctrl);
+
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+				 dd->ipath_rcvctrl);
+
+		if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */
+			ipath_write_ureg(dd, ur_rcvhdrhead,
+					 dd->ipath_rhdrhead_intr_off | head,
+					 pd->port_port);
+
+		poll_wait(fp, &pd->port_wait, pt);
+	}
+
+	return pollflag;
+}
+
 static unsigned int ipath_poll(struct file *fp,
 			       struct poll_table_struct *pt)
 {
 	struct ipath_portdata *pd;
-	u32 head, tail;
-	int bit;
-	unsigned pollflag = 0;
-	struct ipath_devdata *dd;
+	unsigned pollflag;
 
 	pd = port_fp(fp);
 	if (!pd)
-		goto bail;
-	dd = pd->port_dd;
+		pollflag = 0;
+	else if (pd->poll_type & IPATH_POLL_TYPE_URGENT)
+		pollflag = ipath_poll_urgent(pd, fp, pt);
+	else
+		pollflag = ipath_poll_next(pd, fp, pt);
 
-	bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT;
-	set_bit(bit, &dd->ipath_rcvctrl);
-
-	/*
-	 * Before blocking, make sure that head is still == tail,
-	 * reading from the chip, so we can be sure the interrupt
-	 * enable has made it to the chip.  If not equal, disable
-	 * interrupt again and return immediately.  This avoids races,
-	 * and the overhead of the chip read doesn't matter much at
-	 * this point, since we are waiting for something anyway.
-	 */
-
-	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-			 dd->ipath_rcvctrl);
-
-	head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
-	tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
-
-	if (tail == head) {
-		set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
-		if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */
-			(void)ipath_write_ureg(dd, ur_rcvhdrhead,
-					       dd->ipath_rhdrhead_intr_off
-					       | head, pd->port_port);
-		poll_wait(fp, &pd->port_wait, pt);
-
-		if (test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) {
-			/* timed out, no packets received */
-			clear_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
-			pd->port_rcvwait_to++;
-		}
-		else
-			pollflag = POLLIN | POLLRDNORM;
-	}
-	else {
-		/* it's already happened; don't do wait_event overhead */
-		pollflag = POLLIN | POLLRDNORM;
-		pd->port_rcvnowait++;
-	}
-
-	clear_bit(bit, &dd->ipath_rcvctrl);
-	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-			 dd->ipath_rcvctrl);
-
-bail:
 	return pollflag;
 }
 
+static int ipath_supports_subports(int user_swmajor, int user_swminor)
+{
+	/* no subport implementation prior to software version 1.3 */
+	return (user_swmajor > 1) || (user_swminor >= 3);
+}
+
+static int ipath_compatible_subports(int user_swmajor, int user_swminor)
+{
+	/* this code is written long-hand for clarity */
+	if (IPATH_USER_SWMAJOR != user_swmajor) {
+		/* no promise of compatibility if major mismatch */
+		return 0;
+	}
+	if (IPATH_USER_SWMAJOR == 1) {
+		switch (IPATH_USER_SWMINOR) {
+		case 0:
+		case 1:
+		case 2:
+			/* no subport implementation so cannot be compatible */
+			return 0;
+		case 3:
+			/* 3 is only compatible with itself */
+			return user_swminor == 3;
+		default:
+			/* >= 4 are compatible (or are expected to be) */
+			return user_swminor >= 4;
+		}
+	}
+	/* make no promises yet for future major versions */
+	return 0;
+}
+
 static int init_subports(struct ipath_devdata *dd,
 			 struct ipath_portdata *pd,
 			 const struct ipath_user_info *uinfo)
@@ -1408,20 +1477,32 @@
 	size_t size;
 
 	/*
-	 * If the user is requesting zero or one port,
+	 * If the user is requesting zero subports,
 	 * skip the subport allocation.
 	 */
-	if (uinfo->spu_subport_cnt <= 1)
+	if (uinfo->spu_subport_cnt <= 0)
 		goto bail;
 
-	/* Old user binaries don't know about new subport implementation */
-	if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR) {
+	/* Self-consistency check for ipath_compatible_subports() */
+	if (ipath_supports_subports(IPATH_USER_SWMAJOR, IPATH_USER_SWMINOR) &&
+	    !ipath_compatible_subports(IPATH_USER_SWMAJOR,
+				       IPATH_USER_SWMINOR)) {
 		dev_info(&dd->pcidev->dev,
-			 "Mismatched user minor version (%d) and driver "
-                         "minor version (%d) while port sharing. Ensure "
+			 "Inconsistent ipath_compatible_subports()\n");
+		goto bail;
+	}
+
+	/* Check for subport compatibility */
+	if (!ipath_compatible_subports(uinfo->spu_userversion >> 16,
+				       uinfo->spu_userversion & 0xffff)) {
+		dev_info(&dd->pcidev->dev,
+			 "Mismatched user version (%d.%d) and driver "
+			 "version (%d.%d) while port sharing. Ensure "
                          "that driver and library are from the same "
                          "release.\n",
+			 (int) (uinfo->spu_userversion >> 16),
                          (int) (uinfo->spu_userversion & 0xffff),
+			 IPATH_USER_SWMAJOR,
 	                 IPATH_USER_SWMINOR);
 		goto bail;
 	}
@@ -1725,14 +1806,13 @@
 	return fp->private_data ? 0 : -ENOMEM;
 }
 
-
 /* Get port early, so can set affinity prior to memory allocation */
 static int ipath_assign_port(struct file *fp,
 			      const struct ipath_user_info *uinfo)
 {
 	int ret;
 	int i_minor;
-	unsigned swminor;
+	unsigned swmajor, swminor;
 
 	/* Check to be sure we haven't already initialized this file */
 	if (port_fp(fp)) {
@@ -1741,7 +1821,8 @@
 	}
 
 	/* for now, if major version is different, bail */
-	if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
+	swmajor = uinfo->spu_userversion >> 16;
+	if (swmajor != IPATH_USER_SWMAJOR) {
 		ipath_dbg("User major version %d not same as driver "
 			  "major %d\n", uinfo->spu_userversion >> 16,
 			  IPATH_USER_SWMAJOR);
@@ -1756,7 +1837,8 @@
 
 	mutex_lock(&ipath_mutex);
 
-	if (swminor == IPATH_USER_SWMINOR && uinfo->spu_subport_cnt &&
+	if (ipath_compatible_subports(swmajor, swminor) &&
+	    uinfo->spu_subport_cnt &&
 	    (ret = find_shared_port(fp, uinfo))) {
 		mutex_unlock(&ipath_mutex);
 		if (ret > 0)
@@ -2020,7 +2102,8 @@
 	info.port = pd->port_port;
 	info.subport = subport;
 	/* Don't return new fields if old library opened the port. */
-	if ((pd->userversion & 0xffff) == IPATH_USER_SWMINOR) {
+	if (ipath_supports_subports(pd->userversion >> 16,
+				    pd->userversion & 0xffff)) {
 		/* Number of user ports available for this device. */
 		info.num_ports = pd->port_dd->ipath_cfgports - 1;
 		info.num_subports = pd->port_subport_cnt;
@@ -2123,6 +2206,11 @@
 		src = NULL;
 		dest = NULL;
 		break;
+	case IPATH_CMD_POLL_TYPE:
+		copy = sizeof(cmd.cmd.poll_type);
+		dest = &cmd.cmd.poll_type;
+		src = &ucmd->cmd.poll_type;
+		break;
 	default:
 		ret = -EINVAL;
 		goto bail;
@@ -2195,6 +2283,9 @@
 	case IPATH_CMD_PIOAVAILUPD:
 		ret = ipath_force_pio_avail_update(pd->port_dd);
 		break;
+	case IPATH_CMD_POLL_TYPE:
+		pd->poll_type = cmd.cmd.poll_type;
+		break;
 	}
 
 	if (ret >= 0)
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index ebd5c7b..2e689b9 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -257,9 +257,14 @@
 		/* Notimpl InitType (actually, an SMA decision) */
 		/* VLHighLimit is 0 (only one VL) */
 		; /* VLArbitrationHighCap is 0 (only one VL) */
+	/*
+	 * Note: the chips support a maximum MTU of 4096, but the driver
+	 * hasn't implemented this feature yet, so set the maximum
+	 * to 2048.
+	 */
 	portinfo[10] = 	/* VLArbitrationLowCap is 0 (only one VL) */
 		/* InitTypeReply is SMA decision */
-		(5 << 16)	/* MTUCap 4096 */
+		(4 << 16)	/* MTUCap 2048 */
 		| (7 << 13)	/* VLStallCount */
 		| (0x1f << 8)	/* HOQLife */
 		| (1 << 4)
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
index 4171198..650745d 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -36,6 +36,7 @@
  * HT chip.
  */
 
+#include <linux/vmalloc.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/htirq.h>
@@ -439,6 +440,7 @@
 	u32 bits, ctrl;
 	int isfatal = 0;
 	char bitsmsg[64];
+	int log_idx;
 
 	hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
 
@@ -467,6 +469,11 @@
 
 	hwerrs &= dd->ipath_hwerrmask;
 
+	/* We log some errors to EEPROM, check if we have any of those. */
+	for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)
+		if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)
+			ipath_inc_eeprom_err(dd, log_idx, 1);
+
 	/*
 	 * make sure we get this much out, unless told to be quiet,
 	 * it's a parity error we may recover from,
@@ -502,9 +509,7 @@
 		if (!hwerrs) {
 			ipath_dbg("Clearing freezemode on ignored or "
 				  "recovered hardware error\n");
-			ctrl &= ~INFINIPATH_C_FREEZEMODE;
-			ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-					 ctrl);
+			ipath_clear_freeze(dd);
 		}
 	}
 
@@ -672,10 +677,16 @@
 	if (n)
 		snprintf(name, namelen, "%s", n);
 
+	if (dd->ipath_boardrev != 6 && dd->ipath_boardrev != 7 &&
+	    dd->ipath_boardrev != 11) {
+		ipath_dev_err(dd, "Unsupported InfiniPath board %s!\n", name);
+		ret = 1;
+		goto bail;
+	}
 	if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 ||
-		dd->ipath_minrev > 3)) {
+		dd->ipath_minrev > 4)) {
 		/*
-		 * This version of the driver only supports Rev 3.2 and 3.3
+		 * This version of the driver only supports Rev 3.2 - 3.4
 		 */
 		ipath_dev_err(dd,
 			      "Unsupported InfiniPath hardware revision %u.%u!\n",
@@ -689,36 +700,11 @@
 	 * copies
 	 */
 	dd->ipath_flags |= IPATH_32BITCOUNTERS;
+	dd->ipath_flags |= IPATH_GPIO_INTR;
 	if (dd->ipath_htspeed != 800)
 		ipath_dev_err(dd,
 			      "Incorrectly configured for HT @ %uMHz\n",
 			      dd->ipath_htspeed);
-	if (dd->ipath_boardrev == 7 || dd->ipath_boardrev == 11 ||
-	    dd->ipath_boardrev == 6)
-		dd->ipath_flags |= IPATH_GPIO_INTR;
-	else
-		dd->ipath_flags |= IPATH_POLL_RX_INTR;
-	if (dd->ipath_boardrev == 8) {	/* LS/X-1 */
-		u64 val;
-		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
-		if (val & INFINIPATH_EXTS_SERDESSEL) {
-			/*
-			 * hardware disabled
-			 *
-			 * This means that the chip is hardware disabled,
-			 * and will not be able to bring up the link,
-			 * in any case.  We special case this and abort
-			 * early, to avoid later messages.  We also set
-			 * the DISABLED status bit
-			 */
-			ipath_dbg("Unit %u is hardware-disabled\n",
-				  dd->ipath_unit);
-			*dd->ipath_statusp |= IPATH_STATUS_DISABLED;
-			/* this value is handled differently */
-			ret = 2;
-			goto bail;
-		}
-	}
 	ret = 0;
 
 bail:
@@ -1058,12 +1044,24 @@
 				     u64 lst, u64 ltst)
 {
 	u64 extctl;
+	unsigned long flags = 0;
 
 	/* the diags use the LED to indicate diag info, so we leave
 	 * the external LED alone when the diags are running */
 	if (ipath_diag_inuse)
 		return;
 
+	/* Allow override of LED display for, e.g. Locating system in rack */
+	if (dd->ipath_led_override) {
+		ltst = (dd->ipath_led_override & IPATH_LED_PHYS)
+			? INFINIPATH_IBCS_LT_STATE_LINKUP
+			: INFINIPATH_IBCS_LT_STATE_DISABLED;
+		lst = (dd->ipath_led_override & IPATH_LED_LOG)
+			? INFINIPATH_IBCS_L_STATE_ACTIVE
+			: INFINIPATH_IBCS_L_STATE_DOWN;
+	}
+
+	spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
 	/*
 	 * start by setting both LED control bits to off, then turn
 	 * on the appropriate bit(s).
@@ -1092,6 +1090,7 @@
 	}
 	dd->ipath_extctrl = extctl;
 	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+	spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
 }
 
 static void ipath_init_ht_variables(struct ipath_devdata *dd)
@@ -1157,6 +1156,22 @@
 
 	dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
 	dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+
+	/*
+	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
+	 * 2 is Some Misc, 3 is reserved for future.
+	 */
+	dd->ipath_eep_st_masks[0].hwerrs_to_log =
+		INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+		INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;
+
+	dd->ipath_eep_st_masks[1].hwerrs_to_log =
+		INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+		INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
+
+	dd->ipath_eep_st_masks[2].errs_to_log =
+		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+
 }
 
 /**
@@ -1372,7 +1387,7 @@
  * ipath_pe_put_tid - write a TID in chip
  * @dd: the infinipath device
  * @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
  * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
  *
  * This exists as a separate routine to allow for special locking etc.
@@ -1393,7 +1408,7 @@
 				 "40 bits, using only 40!!!\n", pa);
 			pa &= INFINIPATH_RT_ADDR_MASK;
 		}
-		if (type == 0)
+		if (type == RCVHQ_RCV_TYPE_EAGER)
 			pa |= dd->ipath_tidtemplate;
 		else {
 			/* in words (fixed, full page).  */
@@ -1433,7 +1448,8 @@
 				   port * dd->ipath_rcvtidcnt *
 				   sizeof(*tidbase));
 	for (i = 0; i < dd->ipath_rcvtidcnt; i++)
-		ipath_ht_put_tid(dd, &tidbase[i], 1, dd->ipath_tidinvalid);
+		ipath_ht_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
+				 dd->ipath_tidinvalid);
 
 	tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
 				   dd->ipath_rcvegrbase +
@@ -1441,7 +1457,8 @@
 				   sizeof(*tidbase));
 
 	for (i = 0; i < dd->ipath_rcvegrcnt; i++)
-		ipath_ht_put_tid(dd, &tidbase[i], 0, dd->ipath_tidinvalid);
+		ipath_ht_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER,
+				 dd->ipath_tidinvalid);
 }
 
 /**
@@ -1528,11 +1545,6 @@
 		writel(16, piobuf);
 		piobuf += pioincr;
 	}
-	/*
-	 * self-clearing
-	 */
-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-			 INFINIPATH_S_ABORT);
 
 	ipath_get_eeprom_info(dd);
 	if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' &&
@@ -1543,8 +1555,10 @@
 		 * with 128, rather than 112.
 		 */
 		dd->ipath_flags |= IPATH_GPIO_INTR;
-		dd->ipath_flags &= ~IPATH_POLL_RX_INTR;
-	}
+	} else
+		ipath_dev_err(dd, "Unsupported InfiniPath serial "
+			      "number %.16s!\n", dd->ipath_serial);
+
 	return 0;
 }
 
@@ -1561,7 +1575,6 @@
 	}
 	dev_info(&dd->pcidev->dev,
 		"Recovering from TXE PIO parity error\n");
-	ipath_disarm_senderrbufs(dd, 1);
 	return 1;
 }
 
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
index 4e2e3df..9868ccd 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -296,13 +296,6 @@
 #define IPATH_GPIO_SCL (1ULL << \
 	(_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
 
-/*
- * Rev2 silicon allows suppressing check for ArmLaunch errors.
- * this can speed up short packet sends on systems that do
- * not guaranteee write-order.
- */
-#define INFINIPATH_XGXS_SUPPRESS_ARMLAUNCH_ERR (1ULL<<63)
-
 /* 6120 specific hardware errors... */
 static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
 	INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
@@ -347,6 +340,7 @@
 	u32 bits, ctrl;
 	int isfatal = 0;
 	char bitsmsg[64];
+	int log_idx;
 
 	hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
 	if (!hwerrs) {
@@ -374,6 +368,11 @@
 
 	hwerrs &= dd->ipath_hwerrmask;
 
+	/* We log some errors to EEPROM, check if we have any of those. */
+	for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)
+		if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)
+			ipath_inc_eeprom_err(dd, log_idx, 1);
+
 	/*
 	 * make sure we get this much out, unless told to be quiet,
 	 * or it's occurred within the last 5 seconds
@@ -431,10 +430,12 @@
 			*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
 			dd->ipath_flags &= ~IPATH_INITTED;
 		} else {
-			ipath_dbg("Clearing freezemode on ignored hardware "
-				  "error\n");
-			ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-			   		 dd->ipath_control);
+			static u32 freeze_cnt;
+
+			freeze_cnt++;
+			ipath_dbg("Clearing freezemode on ignored or recovered "
+				  "hardware error (%u)\n", freeze_cnt);
+			ipath_clear_freeze(dd);
 		}
 	}
 
@@ -680,17 +681,6 @@
 		val |= dd->ipath_rx_pol_inv <<
 			INFINIPATH_XGXS_RX_POL_SHIFT;
 	}
-	if (dd->ipath_minrev >= 2) {
-		/* Rev 2. can tolerate multiple writes to PBC, and
-		 * allowing them can provide lower latency on some
-		 * CPUs, but this feature is off by default, only
-		 * turned on by setting D63 of XGXSconfig reg.
-		 * May want to make this conditional more
-		 * fine-grained in future. This is not exactly
-		 * related to XGXS, but where the bit ended up.
-		 */
-		val |= INFINIPATH_XGXS_SUPPRESS_ARMLAUNCH_ERR;
-	}
 	if (val != prev_val)
 		ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
 
@@ -791,12 +781,24 @@
 				     u64 ltst)
 {
 	u64 extctl;
+	unsigned long flags = 0;
 
 	/* the diags use the LED to indicate diag info, so we leave
 	 * the external LED alone when the diags are running */
 	if (ipath_diag_inuse)
 		return;
 
+	/* Allow override of LED display for, e.g. Locating system in rack */
+	if (dd->ipath_led_override) {
+		ltst = (dd->ipath_led_override & IPATH_LED_PHYS)
+			? INFINIPATH_IBCS_LT_STATE_LINKUP
+			: INFINIPATH_IBCS_LT_STATE_DISABLED;
+		lst = (dd->ipath_led_override & IPATH_LED_LOG)
+			? INFINIPATH_IBCS_L_STATE_ACTIVE
+			: INFINIPATH_IBCS_L_STATE_DOWN;
+	}
+
+	spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
 	extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
 				       INFINIPATH_EXTC_LED2PRIPORT_ON);
 
@@ -806,6 +808,7 @@
 		extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
 	dd->ipath_extctrl = extctl;
 	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+	spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
 }
 
 /**
@@ -955,6 +958,27 @@
 
 	dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
 	dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+
+	/*
+	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
+	 * 2 is Some Misc, 3 is reserved for future.
+	 */
+	dd->ipath_eep_st_masks[0].hwerrs_to_log =
+		INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+		INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;
+
+	/* Ignore errors in PIO/PBC on systems with unordered write-combining */
+	if (ipath_unordered_wc())
+		dd->ipath_eep_st_masks[0].hwerrs_to_log &= ~TXE_PIO_PARITY;
+
+	dd->ipath_eep_st_masks[1].hwerrs_to_log =
+		INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+		INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
+
+	dd->ipath_eep_st_masks[2].errs_to_log =
+		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+
+
 }
 
 /* setup the MSI stuff again after a reset.  I'd like to just call
@@ -1082,7 +1106,7 @@
  * ipath_pe_put_tid - write a TID in chip
  * @dd: the infinipath device
  * @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
  * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
  *
  * This exists as a separate routine to allow for special locking etc.
@@ -1108,7 +1132,7 @@
 				      "BUG: Physical page address 0x%lx "
 				      "has bits set in 31-29\n", pa);
 
-		if (type == 0)
+		if (type == RCVHQ_RCV_TYPE_EAGER)
 			pa |= dd->ipath_tidtemplate;
 		else /* for now, always full 4KB page */
 			pa |= 2 << 29;
@@ -1132,7 +1156,7 @@
  * ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher
  * @dd: the infinipath device
  * @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
  * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
  *
  * This exists as a separate routine to allow for selection of the
@@ -1157,7 +1181,7 @@
 				      "BUG: Physical page address 0x%lx "
 				      "has bits set in 31-29\n", pa);
 
-		if (type == 0)
+		if (type == RCVHQ_RCV_TYPE_EAGER)
 			pa |= dd->ipath_tidtemplate;
 		else /* for now, always full 4KB page */
 			pa |= 2 << 29;
@@ -1196,7 +1220,8 @@
 		 port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
 
 	for (i = 0; i < dd->ipath_rcvtidcnt; i++)
-		ipath_pe_put_tid(dd, &tidbase[i], 0, tidinv);
+		ipath_pe_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
+				 tidinv);
 
 	tidbase = (u64 __iomem *)
 		((char __iomem *)(dd->ipath_kregbase) +
@@ -1204,7 +1229,8 @@
 		 port * dd->ipath_rcvegrcnt * sizeof(*tidbase));
 
 	for (i = 0; i < dd->ipath_rcvegrcnt; i++)
-		ipath_pe_put_tid(dd, &tidbase[i], 1, tidinv);
+		ipath_pe_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER,
+				 tidinv);
 }
 
 /**
@@ -1311,13 +1337,6 @@
 
 	dd = pd->port_dd;
 
-	if (dd != NULL && dd->ipath_minrev >= 2) {
-		ipath_cdbg(PROC, "IBA6120 Rev2, allow multiple PBC write\n");
-		kinfo->spi_runtime_flags |= IPATH_RUNTIME_PBC_REWRITE;
-		ipath_cdbg(PROC, "IBA6120 Rev2, allow loose DMA alignment\n");
-		kinfo->spi_runtime_flags |= IPATH_RUNTIME_LOOSE_DMA_ALIGN;
-	}
-
 done:
 	kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE;
 	return 0;
@@ -1354,7 +1373,6 @@
 		dev_info(&dd->pcidev->dev,
 			"Recovering from TXE PIO parity error\n");
 	}
-	ipath_disarm_senderrbufs(dd, 1);
 	return 1;
 }
 
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 7045ba6..49951d5 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -133,7 +133,8 @@
 				   dd->ipath_ibmaxlen, PCI_DMA_FROMDEVICE);
 		dd->ipath_f_put_tid(dd, e + (u64 __iomem *)
 				    ((char __iomem *) dd->ipath_kregbase +
-				     dd->ipath_rcvegrbase), 0,
+				     dd->ipath_rcvegrbase),
+				    RCVHQ_RCV_TYPE_EAGER,
 				    dd->ipath_port0_skbinfo[e].phys);
 	}
 
@@ -310,7 +311,12 @@
 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize);
 	dd->ipath_piosize2k = val & ~0U;
 	dd->ipath_piosize4k = val >> 32;
-	dd->ipath_ibmtu = 4096;	/* default to largest legal MTU */
+	/*
+	 * Note: the chips support a maximum MTU of 4096, but the driver
+	 * hasn't implemented this feature yet, so set the initial value
+	 * to 2048.
+	 */
+	dd->ipath_ibmtu = 2048;
 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
 	dd->ipath_piobcnt2k = val & ~0U;
 	dd->ipath_piobcnt4k = val >> 32;
@@ -340,6 +346,10 @@
 
 	spin_lock_init(&dd->ipath_tid_lock);
 
+	spin_lock_init(&dd->ipath_gpio_lock);
+	spin_lock_init(&dd->ipath_eep_st_lock);
+	sema_init(&dd->ipath_eep_sem, 1);
+
 done:
 	*pdp = pd;
 	return ret;
@@ -646,7 +656,7 @@
 	ret = dd->ipath_f_get_boardname(dd, boardn, sizeof boardn);
 
 	snprintf(dd->ipath_boardversion, sizeof(dd->ipath_boardversion),
-		 "Driver %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
+		 "ChipABI %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
 		 "SW Compat %u\n",
 		 IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn,
 		 (unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) &
@@ -727,7 +737,7 @@
 	uports = dd->ipath_cfgports ? dd->ipath_cfgports - 1 : 0;
 	if (ipath_kpiobufs == 0) {
 		/* not set by user (this is default) */
-		if (piobufs >= (uports * IPATH_MIN_USER_PORT_BUFCNT) + 32)
+		if (piobufs > 144)
 			kpiobufs = 32;
 		else
 			kpiobufs = 16;
@@ -767,6 +777,12 @@
 		   piobufs, dd->ipath_pbufsport, uports);
 
 	dd->ipath_f_early_init(dd);
+	/*
+	 * cancel any possible active sends from early driver load.
+	 * Follows early_init because some chips have to initialize
+	 * PIO buffers in early_init to avoid false parity errors.
+	 */
+	ipath_cancel_sends(dd);
 
 	/* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
 	 * done after early_init */
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index a90d3b5..47aa434 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -93,7 +93,8 @@
 
 	if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
 		int i;
-		if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG)) {
+		if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG) &&
+			dd->ipath_lastcancel > jiffies) {
 			__IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG,
 					  "SendbufErrs %lx %lx", sbuf[0],
 					  sbuf[1]);
@@ -108,7 +109,8 @@
 					ipath_clrpiobuf(dd, i);
 				ipath_disarm_piobufs(dd, i, 1);
 			}
-		dd->ipath_lastcancel = jiffies+3; /* no armlaunch for a bit */
+		/* ignore armlaunch errs for a bit */
+		dd->ipath_lastcancel = jiffies+3;
 	}
 }
 
@@ -131,6 +133,17 @@
 	 INFINIPATH_E_INVALIDADDR)
 
 /*
+ * this is similar to E_SUM_ERRS, but can't ignore armlaunch, don't ignore
+ * errors not related to freeze and cancelling buffers.  Can't ignore
+ * armlaunch because could get more while still cleaning up, and need
+ * to cancel those as they happen.
+ */
+#define E_SPKT_ERRS_IGNORE \
+	 (INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \
+	 INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SMINPKTLEN | \
+	 INFINIPATH_E_SPKTLEN)
+
+/*
  * these are errors that can occur when the link changes state while
  * a packet is being sent or received.  This doesn't cover things
  * like EBP or VCRC that can be the result of a sending having the
@@ -290,12 +303,7 @@
 		 * Flush all queued sends when link went to DOWN or INIT,
 		 * to be sure that they don't block SMA and other MAD packets
 		 */
-		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-				 INFINIPATH_S_ABORT);
-		ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
-							(unsigned)(dd->ipath_piobcnt2k +
-					dd->ipath_piobcnt4k) -
-					dd->ipath_lastport_piobuf);
+		ipath_cancel_sends(dd);
 	}
 	else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM ||
 	    lstate == IPATH_IBSTATE_ACTIVE) {
@@ -505,6 +513,7 @@
 	int i, iserr = 0;
 	int chkerrpkts = 0, noprint = 0;
 	unsigned supp_msgs;
+	int log_idx;
 
 	supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
 
@@ -518,6 +527,13 @@
 	if (errs & INFINIPATH_E_HARDWARE) {
 		/* reuse same msg buf */
 		dd->ipath_f_handle_hwerrors(dd, msg, sizeof msg);
+	} else {
+		u64 mask;
+		for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx) {
+			mask = dd->ipath_eep_st_masks[log_idx].errs_to_log;
+			if (errs & mask)
+				ipath_inc_eeprom_err(dd, log_idx, 1);
+		}
 	}
 
 	if (!noprint && (errs & ~dd->ipath_e_bitsextant))
@@ -675,6 +691,17 @@
 					chkerrpkts = 1;
 				dd->ipath_lastrcvhdrqtails[i] = tl;
 				pd->port_hdrqfull++;
+				if (test_bit(IPATH_PORT_WAITING_OVERFLOW,
+					     &pd->port_flag)) {
+					clear_bit(
+					  IPATH_PORT_WAITING_OVERFLOW,
+					  &pd->port_flag);
+					set_bit(
+					  IPATH_PORT_WAITING_OVERFLOW,
+					  &pd->int_flag);
+					wake_up_interruptible(
+					  &pd->port_wait);
+				}
 			}
 		}
 	}
@@ -744,6 +771,72 @@
 	return chkerrpkts;
 }
 
+
+/*
+ * try to cleanup as much as possible for anything that might have gone
+ * wrong while in freeze mode, such as pio buffers being written by user
+ * processes (causing armlaunch), send errors due to going into freeze mode,
+ * etc., and try to avoid causing extra interrupts while doing so.
+ * Forcibly update the in-memory pioavail register copies after cleanup
+ * because the chip won't do it for anything changing while in freeze mode
+ * (we don't want to wait for the next pio buffer state change).
+ * Make sure that we don't lose any important interrupts by using the chip
+ * feature that says that writing 0 to a bit in *clear that is set in
+ * *status will cause an interrupt to be generated again (if allowed by
+ * the *mask value).
+ */
+void ipath_clear_freeze(struct ipath_devdata *dd)
+{
+	int i, im;
+	__le64 val;
+
+	/* disable error interrupts, to avoid confusion */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
+
+	/*
+	 * clear all sends, because they have may been
+	 * completed by usercode while in freeze mode, and
+	 * therefore would not be sent, and eventually
+	 * might cause the process to run out of bufs
+	 */
+	ipath_cancel_sends(dd);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+			 dd->ipath_control);
+
+	/* ensure pio avail updates continue */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+		 dd->ipath_sendctrl & ~IPATH_S_PIOBUFAVAILUPD);
+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+		 dd->ipath_sendctrl);
+
+	/*
+	 * We just enabled pioavailupdate, so dma copy is almost certainly
+	 * not yet right, so read the registers directly.  Similar to init
+	 */
+	for (i = 0; i < dd->ipath_pioavregs; i++) {
+		/* deal with 6110 chip bug */
+		im = i > 3 ? ((i&1) ? i-1 : i+1) : i;
+		val = ipath_read_kreg64(dd, 0x1000+(im*sizeof(u64)));
+		dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
+			= le64_to_cpu(val);
+	}
+
+	/*
+	 * force new interrupt if any hwerr, error or interrupt bits are
+	 * still set, and clear "safe" send packet errors related to freeze
+	 * and cancelling sends.  Re-enable error interrupts before possible
+	 * force of re-interrupt on pending interrupts.
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+		E_SPKT_ERRS_IGNORE);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+		~dd->ipath_maskederrs);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+}
+
+
 /* this is separate to allow for better optimization of ipath_intr() */
 
 static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
@@ -872,14 +965,25 @@
 		   dd->ipath_i_rcvurg_mask);
 	for (i = 1; i < dd->ipath_cfgports; i++) {
 		struct ipath_portdata *pd = dd->ipath_pd[i];
-		if (portr & (1 << i) && pd && pd->port_cnt &&
-			test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) {
-			clear_bit(IPATH_PORT_WAITING_RCV,
-				  &pd->port_flag);
-			clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
-				  &dd->ipath_rcvctrl);
-			wake_up_interruptible(&pd->port_wait);
-			rcvdint = 1;
+		if (portr & (1 << i) && pd && pd->port_cnt) {
+			if (test_bit(IPATH_PORT_WAITING_RCV,
+				     &pd->port_flag)) {
+				clear_bit(IPATH_PORT_WAITING_RCV,
+					  &pd->port_flag);
+				set_bit(IPATH_PORT_WAITING_RCV,
+					&pd->int_flag);
+				clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
+					  &dd->ipath_rcvctrl);
+				wake_up_interruptible(&pd->port_wait);
+				rcvdint = 1;
+			} else if (test_bit(IPATH_PORT_WAITING_URG,
+					    &pd->port_flag)) {
+				clear_bit(IPATH_PORT_WAITING_URG,
+					  &pd->port_flag);
+				set_bit(IPATH_PORT_WAITING_URG,
+					&pd->int_flag);
+				wake_up_interruptible(&pd->port_wait);
+			}
 		}
 	}
 	if (rcvdint) {
@@ -905,6 +1009,9 @@
 
 	ipath_stats.sps_ints++;
 
+	if (dd->ipath_int_counter != (u32) -1)
+		dd->ipath_int_counter++;
+
 	if (!(dd->ipath_flags & IPATH_PRESENT)) {
 		/*
 		 * This return value is not great, but we do not want the
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 12194f3..3105005 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -1,7 +1,7 @@
 #ifndef _IPATH_KERNEL_H
 #define _IPATH_KERNEL_H
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -57,6 +57,24 @@
 extern struct infinipath_stats ipath_stats;
 
 #define IPATH_CHIP_SWVERSION IPATH_CHIP_VERS_MAJ
+/*
+ * First-cut critierion for "device is active" is
+ * two thousand dwords combined Tx, Rx traffic per
+ * 5-second interval. SMA packets are 64 dwords,
+ * and occur "a few per second", presumably each way.
+ */
+#define IPATH_TRAFFIC_ACTIVE_THRESHOLD (2000)
+/*
+ * Struct used to indicate which errors are logged in each of the
+ * error-counters that are logged to EEPROM. A counter is incremented
+ * _once_ (saturating at 255) for each event with any bits set in
+ * the error or hwerror register masks below.
+ */
+#define IPATH_EEP_LOG_CNT (4)
+struct ipath_eep_log_mask {
+	u64 errs_to_log;
+	u64 hwerrs_to_log;
+};
 
 struct ipath_portdata {
 	void **port_rcvegrbuf;
@@ -109,6 +127,8 @@
 	u32 port_tidcursor;
 	/* next expected TID to check */
 	unsigned long port_flag;
+	/* what happened */
+	unsigned long int_flag;
 	/* WAIT_RCV that timed out, no interrupt */
 	u32 port_rcvwait_to;
 	/* WAIT_PIO that timed out, no interrupt */
@@ -137,6 +157,8 @@
 	u32 userversion;
 	/* Bitmask of active slaves */
 	u32 active_slaves;
+	/* Type of packets or conditions we want to poll for */
+	u16 poll_type;
 };
 
 struct sk_buff;
@@ -275,6 +297,8 @@
 	u32 ipath_lastport_piobuf;
 	/* is a stats timer active */
 	u32 ipath_stats_timer_active;
+	/* number of interrupts for this device -- saturates... */
+	u32 ipath_int_counter;
 	/* dwords sent read from counter */
 	u32 ipath_lastsword;
 	/* dwords received read from counter */
@@ -369,9 +393,6 @@
 	struct class_device *diag_class_dev;
 	/* timer used to prevent stats overflow, error throttling, etc. */
 	struct timer_list ipath_stats_timer;
-	/* check for stale messages in rcv queue */
-	/* only allow one intr at a time. */
-	unsigned long ipath_rcv_pending;
 	void *ipath_dummy_hdrq;	/* used after port close */
 	dma_addr_t ipath_dummy_hdrq_phys;
 
@@ -399,6 +420,8 @@
 	u64 ipath_gpio_out;
 	/* shadow the gpio mask register */
 	u64 ipath_gpio_mask;
+	/* shadow the gpio output enable, etc... */
+	u64 ipath_extctrl;
 	/* kr_revision shadow */
 	u64 ipath_revision;
 	/*
@@ -473,8 +496,6 @@
 	u32 ipath_cregbase;
 	/* shadow the control register contents */
 	u32 ipath_control;
-	/* shadow the gpio output contents */
-	u32 ipath_extctrl;
 	/* PCI revision register (HTC rev on FPGA) */
 	u32 ipath_pcirev;
 
@@ -552,6 +573,9 @@
 	u32 ipath_overrun_thresh_errs;
 	u32 ipath_lli_errs;
 
+	/* status check work */
+	struct delayed_work status_work;
+
 	/*
 	 * Not all devices managed by a driver instance are the same
 	 * type, so these fields must be per-device.
@@ -575,6 +599,37 @@
 	u16 ipath_gpio_scl_num;
 	u64 ipath_gpio_sda;
 	u64 ipath_gpio_scl;
+
+	/* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
+	spinlock_t ipath_gpio_lock;
+
+	/* used to override LED behavior */
+	u8 ipath_led_override;  /* Substituted for normal value, if non-zero */
+	u16 ipath_led_override_timeoff; /* delta to next timer event */
+	u8 ipath_led_override_vals[2]; /* Alternates per blink-frame */
+	u8 ipath_led_override_phase; /* Just counts, LSB picks from vals[] */
+	atomic_t ipath_led_override_timer_active;
+	/* Used to flash LEDs in override mode */
+	struct timer_list ipath_led_override_timer;
+
+	/* Support (including locks) for EEPROM logging of errors and time */
+	/* control access to actual counters, timer */
+	spinlock_t ipath_eep_st_lock;
+	/* control high-level access to EEPROM */
+	struct semaphore ipath_eep_sem;
+	/* Below inc'd by ipath_snap_cntrs(), locked by ipath_eep_st_lock */
+	uint64_t ipath_traffic_wds;
+	/* active time is kept in seconds, but logged in hours */
+	atomic_t ipath_active_time;
+	/* Below are nominal shadow of EEPROM, new since last EEPROM update */
+	uint8_t ipath_eep_st_errs[IPATH_EEP_LOG_CNT];
+	uint8_t ipath_eep_st_new_errs[IPATH_EEP_LOG_CNT];
+	uint16_t ipath_eep_hrs;
+	/*
+	 * masks for which bits of errs, hwerrs that cause
+	 * each of the counters to increment.
+	 */
+	struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT];
 };
 
 /* Private data for file operations */
@@ -592,6 +647,7 @@
 void ipath_disable_wc(struct ipath_devdata *dd);
 int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
 void ipath_shutdown_device(struct ipath_devdata *);
+void ipath_clear_freeze(struct ipath_devdata *);
 
 struct file_operations;
 int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
@@ -627,6 +683,7 @@
 
 void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first,
 			  unsigned cnt);
+void ipath_cancel_sends(struct ipath_devdata *);
 
 int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *);
 void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *);
@@ -685,7 +742,6 @@
 		 * are 64bit */
 #define IPATH_32BITCOUNTERS 0x20000
 		/* can miss port0 rx interrupts */
-#define IPATH_POLL_RX_INTR  0x40000
 #define IPATH_DISABLED      0x80000 /* administratively disabled */
 		/* Use GPIO interrupts for new counters */
 #define IPATH_GPIO_ERRINTRS 0x100000
@@ -704,6 +760,10 @@
 #define IPATH_PORT_WAITING_PIO   3
 		/* master has not finished initializing */
 #define IPATH_PORT_MASTER_UNINIT 4
+		/* waiting for an urgent packet to arrive */
+#define IPATH_PORT_WAITING_URG 5
+		/* waiting for a header overflow */
+#define IPATH_PORT_WAITING_OVERFLOW 6
 
 /* free up any allocated data at closes */
 void ipath_free_data(struct ipath_portdata *dd);
@@ -713,10 +773,21 @@
 void ipath_init_iba6120_funcs(struct ipath_devdata *);
 void ipath_init_iba6110_funcs(struct ipath_devdata *);
 void ipath_get_eeprom_info(struct ipath_devdata *);
+int ipath_update_eeprom_log(struct ipath_devdata *dd);
+void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
 u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
 void ipath_disarm_senderrbufs(struct ipath_devdata *, int);
 
 /*
+ * Set LED override, only the two LSBs have "public" meaning, but
+ * any non-zero value substitutes them for the Link and LinkTrain
+ * LED states.
+ */
+#define IPATH_LED_PHYS 1 /* Physical (linktraining) GREEN LED */
+#define IPATH_LED_LOG 2  /* Logical (link) YELLOW LED */
+void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
+
+/*
  * number of words used for protocol header if not set by ipath_userinit();
  */
 #define IPATH_DFLT_RCVHDRSIZE 9
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
index dd487c1..85a4aef 100644
--- a/drivers/infiniband/hw/ipath/ipath_keys.c
+++ b/drivers/infiniband/hw/ipath/ipath_keys.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
index 05a1d2b..82616b7 100644
--- a/drivers/infiniband/hw/ipath/ipath_layer.c
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.h b/drivers/infiniband/hw/ipath/ipath_layer.h
index 3854a4e..415709c 100644
--- a/drivers/infiniband/hw/ipath/ipath_layer.h
+++ b/drivers/infiniband/hw/ipath/ipath_layer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index 25908b0..d61c030 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -103,7 +103,7 @@
 	/* This is already in network order */
 	nip->sys_guid = to_idev(ibdev)->sys_image_guid;
 	nip->node_guid = dd->ipath_guid;
-	nip->port_guid = nip->sys_guid;
+	nip->port_guid = dd->ipath_guid;
 	nip->partition_cap = cpu_to_be16(ipath_get_npkeys(dd));
 	nip->device_id = cpu_to_be16(dd->ipath_deviceid);
 	majrev = dd->ipath_majrev;
@@ -292,7 +292,12 @@
 	/* pip->vl_arb_high_cap; // only one VL */
 	/* pip->vl_arb_low_cap; // only one VL */
 	/* InitTypeReply = 0 */
-	pip->inittypereply_mtucap = IB_MTU_4096;
+	/*
+	 * Note: the chips support a maximum MTU of 4096, but the driver
+	 * hasn't implemented this feature yet, so set the maximum value
+	 * to 2048.
+	 */
+	pip->inittypereply_mtucap = IB_MTU_2048;
 	// HCAs ignore VLStallCount and HOQLife
 	/* pip->vlstallcnt_hoqlife; */
 	pip->operationalvl_pei_peo_fpi_fpo = 0x10;	/* OVLs = 1 */
diff --git a/drivers/infiniband/hw/ipath/ipath_mmap.c b/drivers/infiniband/hw/ipath/ipath_mmap.c
index 937bc33..fa830e2 100644
--- a/drivers/infiniband/hw/ipath/ipath_mmap.c
+++ b/drivers/infiniband/hw/ipath/ipath_mmap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c
index bdeef8d..e442470 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
index bfef08e..1324b35 100644
--- a/drivers/infiniband/hw/ipath/ipath_qp.c
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -336,7 +336,7 @@
 	qp->qkey = 0;
 	qp->qp_access_flags = 0;
 	qp->s_busy = 0;
-	qp->s_flags &= ~IPATH_S_SIGNAL_REQ_WR;
+	qp->s_flags &= IPATH_S_SIGNAL_REQ_WR;
 	qp->s_hdrwords = 0;
 	qp->s_psn = 0;
 	qp->r_psn = 0;
@@ -507,16 +507,13 @@
 		    attr->port_num > ibqp->device->phys_port_cnt)
 			goto inval;
 
+	/*
+	 * Note: the chips support a maximum MTU of 4096, but the driver
+	 * hasn't implemented this feature yet, so don't allow Path MTU
+	 * values greater than 2048.
+	 */
 	if (attr_mask & IB_QP_PATH_MTU)
-		if (attr->path_mtu > IB_MTU_4096)
-			goto inval;
-
-	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
-		if (attr->max_dest_rd_atomic > 1)
-			goto inval;
-
-	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC)
-		if (attr->max_rd_atomic > 1)
+		if (attr->path_mtu > IB_MTU_2048)
 			goto inval;
 
 	if (attr_mask & IB_QP_PATH_MIG_STATE)
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
index 1915771..46744ea 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -125,8 +125,10 @@
 			if (len > pmtu) {
 				len = pmtu;
 				qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
-			} else
+			} else {
 				qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY);
+				e->sent = 1;
+			}
 			ohdr->u.aeth = ipath_compute_aeth(qp);
 			hwords++;
 			qp->s_ack_rdma_psn = e->psn;
@@ -143,6 +145,7 @@
 				cpu_to_be32(e->atomic_data);
 			hwords += sizeof(ohdr->u.at) / sizeof(u32);
 			bth2 = e->psn;
+			e->sent = 1;
 		}
 		bth0 = qp->s_ack_state << 24;
 		break;
@@ -158,6 +161,7 @@
 			ohdr->u.aeth = ipath_compute_aeth(qp);
 			hwords++;
 			qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST);
+			qp->s_ack_queue[qp->s_tail_ack_queue].sent = 1;
 		}
 		bth0 = qp->s_ack_state << 24;
 		bth2 = qp->s_ack_rdma_psn++ & IPATH_PSN_MASK;
@@ -188,7 +192,7 @@
 	}
 	qp->s_hdrwords = hwords;
 	qp->s_cur_size = len;
-	*bth0p = bth0;
+	*bth0p = bth0 | (1 << 22); /* Set M bit */
 	*bth2p = bth2;
 	return 1;
 
@@ -240,7 +244,7 @@
 
 	/* header size in 32-bit words LRH+BTH = (8+12)/4. */
 	hwords = 5;
-	bth0 = 0;
+	bth0 = 1 << 22; /* Set M bit */
 
 	/* Send a request. */
 	wqe = get_swqe_ptr(qp, qp->s_cur);
@@ -604,7 +608,7 @@
 	}
 	/* read pkey_index w/o lock (its atomic) */
 	bth0 = ipath_get_pkey(dev->dd, qp->s_pkey_index) |
-		OP(ACKNOWLEDGE) << 24;
+		(OP(ACKNOWLEDGE) << 24) | (1 << 22);
 	if (qp->r_nak_state)
 		ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) |
 					    (qp->r_nak_state <<
@@ -806,13 +810,15 @@
  * Called at interrupt level with the QP s_lock held and interrupts disabled.
  * Returns 1 if OK, 0 if current operation should be aborted (NAK).
  */
-static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
+static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode,
+		     u64 val)
 {
 	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
 	struct ib_wc wc;
 	struct ipath_swqe *wqe;
 	int ret = 0;
 	u32 ack_psn;
+	int diff;
 
 	/*
 	 * Remove the QP from the timeout queue (or RNR timeout queue).
@@ -840,7 +846,19 @@
 	 * The MSN might be for a later WQE than the PSN indicates so
 	 * only complete WQEs that the PSN finishes.
 	 */
-	while (ipath_cmp24(ack_psn, wqe->lpsn) >= 0) {
+	while ((diff = ipath_cmp24(ack_psn, wqe->lpsn)) >= 0) {
+		/*
+		 * RDMA_READ_RESPONSE_ONLY is a special case since
+		 * we want to generate completion events for everything
+		 * before the RDMA read, copy the data, then generate
+		 * the completion for the read.
+		 */
+		if (wqe->wr.opcode == IB_WR_RDMA_READ &&
+		    opcode == OP(RDMA_READ_RESPONSE_ONLY) &&
+		    diff == 0) {
+			ret = 1;
+			goto bail;
+		}
 		/*
 		 * If this request is a RDMA read or atomic, and the ACK is
 		 * for a later operation, this ACK NAKs the RDMA read or
@@ -851,12 +869,10 @@
 		 * is sent but before the response is received.
 		 */
 		if ((wqe->wr.opcode == IB_WR_RDMA_READ &&
-		     (opcode != OP(RDMA_READ_RESPONSE_LAST) ||
-		      ipath_cmp24(ack_psn, wqe->lpsn) != 0)) ||
+		     (opcode != OP(RDMA_READ_RESPONSE_LAST) || diff != 0)) ||
 		    ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
 		      wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) &&
-		     (opcode != OP(ATOMIC_ACKNOWLEDGE) ||
-		      ipath_cmp24(wqe->psn, psn) != 0))) {
+		     (opcode != OP(ATOMIC_ACKNOWLEDGE) || diff != 0))) {
 			/*
 			 * The last valid PSN seen is the previous
 			 * request's.
@@ -870,6 +886,9 @@
 			 */
 			goto bail;
 		}
+		if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+		    wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+			*(u64 *) wqe->sg_list[0].vaddr = val;
 		if (qp->s_num_rd_atomic &&
 		    (wqe->wr.opcode == IB_WR_RDMA_READ ||
 		     wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
@@ -1079,6 +1098,7 @@
 	int diff;
 	u32 pad;
 	u32 aeth;
+	u64 val;
 
 	spin_lock_irqsave(&qp->s_lock, flags);
 
@@ -1118,8 +1138,6 @@
 			data += sizeof(__be32);
 		}
 		if (opcode == OP(ATOMIC_ACKNOWLEDGE)) {
-			u64 val;
-
 			if (!header_in_data) {
 				__be32 *p = ohdr->u.at.atomic_ack_eth;
 
@@ -1127,12 +1145,13 @@
 					be32_to_cpu(p[1]);
 			} else
 				val = be64_to_cpu(((__be64 *) data)[0]);
-			*(u64 *) wqe->sg_list[0].vaddr = val;
-		}
-		if (!do_rc_ack(qp, aeth, psn, opcode) ||
+		} else
+			val = 0;
+		if (!do_rc_ack(qp, aeth, psn, opcode, val) ||
 		    opcode != OP(RDMA_READ_RESPONSE_FIRST))
 			goto ack_done;
 		hdrsize += 4;
+		wqe = get_swqe_ptr(qp, qp->s_last);
 		if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
 			goto ack_op_err;
 		/*
@@ -1176,13 +1195,12 @@
 		goto bail;
 
 	case OP(RDMA_READ_RESPONSE_ONLY):
-		if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
-			dev->n_rdma_seq++;
-			ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+		if (!header_in_data)
+			aeth = be32_to_cpu(ohdr->u.aeth);
+		else
+			aeth = be32_to_cpu(((__be32 *) data)[0]);
+		if (!do_rc_ack(qp, aeth, psn, opcode, 0))
 			goto ack_done;
-		}
-		if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
-			goto ack_op_err;
 		/* Get the number of bytes the message was padded by. */
 		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
 		/*
@@ -1197,6 +1215,7 @@
 		 * have to be careful to copy the data to the right
 		 * location.
 		 */
+		wqe = get_swqe_ptr(qp, qp->s_last);
 		qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge,
 						  wqe, psn, pmtu);
 		goto read_last;
@@ -1230,7 +1249,8 @@
 			data += sizeof(__be32);
 		}
 		ipath_copy_sge(&qp->s_rdma_read_sge, data, tlen);
-		(void) do_rc_ack(qp, aeth, psn, OP(RDMA_READ_RESPONSE_LAST));
+		(void) do_rc_ack(qp, aeth, psn,
+				 OP(RDMA_READ_RESPONSE_LAST), 0);
 		goto ack_done;
 	}
 
@@ -1344,8 +1364,11 @@
 			e = NULL;
 			break;
 		}
-		if (ipath_cmp24(psn, e->psn) >= 0)
+		if (ipath_cmp24(psn, e->psn) >= 0) {
+			if (prev == qp->s_tail_ack_queue)
+				old_req = 0;
 			break;
+		}
 	}
 	switch (opcode) {
 	case OP(RDMA_READ_REQUEST): {
@@ -1460,6 +1483,22 @@
 	spin_unlock_irqrestore(&qp->s_lock, flags);
 }
 
+static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n)
+{
+	unsigned long flags;
+	unsigned next;
+
+	next = n + 1;
+	if (next > IPATH_MAX_RDMA_ATOMIC)
+		next = 0;
+	spin_lock_irqsave(&qp->s_lock, flags);
+	if (n == qp->s_tail_ack_queue) {
+		qp->s_tail_ack_queue = next;
+		qp->s_ack_state = OP(ACKNOWLEDGE);
+	}
+	spin_unlock_irqrestore(&qp->s_lock, flags);
+}
+
 /**
  * ipath_rc_rcv - process an incoming RC packet
  * @dev: the device this packet came in on
@@ -1672,6 +1711,9 @@
 	case OP(RDMA_WRITE_FIRST):
 	case OP(RDMA_WRITE_ONLY):
 	case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_WRITE)))
+			goto nack_inv;
 		/* consume RWQE */
 		/* RETH comes after BTH */
 		if (!header_in_data)
@@ -1701,9 +1743,6 @@
 			qp->r_sge.sge.length = 0;
 			qp->r_sge.sge.sge_length = 0;
 		}
-		if (unlikely(!(qp->qp_access_flags &
-			       IB_ACCESS_REMOTE_WRITE)))
-			goto nack_acc;
 		if (opcode == OP(RDMA_WRITE_FIRST))
 			goto send_middle;
 		else if (opcode == OP(RDMA_WRITE_ONLY))
@@ -1717,13 +1756,17 @@
 		u32 len;
 		u8 next;
 
-		if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ)))
-			goto nack_acc;
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_READ)))
+			goto nack_inv;
 		next = qp->r_head_ack_queue + 1;
 		if (next > IPATH_MAX_RDMA_ATOMIC)
 			next = 0;
-		if (unlikely(next == qp->s_tail_ack_queue))
-			goto nack_inv;
+		if (unlikely(next == qp->s_tail_ack_queue)) {
+			if (!qp->s_ack_queue[next].sent)
+				goto nack_inv;
+			ipath_update_ack_queue(qp, next);
+		}
 		e = &qp->s_ack_queue[qp->r_head_ack_queue];
 		/* RETH comes after BTH */
 		if (!header_in_data)
@@ -1758,6 +1801,7 @@
 			e->rdma_sge.sge.sge_length = 0;
 		}
 		e->opcode = opcode;
+		e->sent = 0;
 		e->psn = psn;
 		/*
 		 * We need to increment the MSN here instead of when we
@@ -1789,12 +1833,15 @@
 
 		if (unlikely(!(qp->qp_access_flags &
 			       IB_ACCESS_REMOTE_ATOMIC)))
-			goto nack_acc;
+			goto nack_inv;
 		next = qp->r_head_ack_queue + 1;
 		if (next > IPATH_MAX_RDMA_ATOMIC)
 			next = 0;
-		if (unlikely(next == qp->s_tail_ack_queue))
-			goto nack_inv;
+		if (unlikely(next == qp->s_tail_ack_queue)) {
+			if (!qp->s_ack_queue[next].sent)
+				goto nack_inv;
+			ipath_update_ack_queue(qp, next);
+		}
 		if (!header_in_data)
 			ateth = &ohdr->u.atomic_eth;
 		else
@@ -1819,6 +1866,7 @@
 				      be64_to_cpu(ateth->compare_data),
 				      sdata);
 		e->opcode = opcode;
+		e->sent = 0;
 		e->psn = psn & IPATH_PSN_MASK;
 		qp->r_msn++;
 		qp->r_psn++;
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
index c182bcd..708eba3 100644
--- a/drivers/infiniband/hw/ipath/ipath_registers.h
+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index d9c2a9b..8525674 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -194,6 +194,8 @@
 			ret = 0;
 			goto bail;
 		}
+		/* Make sure entry is read after head index is read. */
+		smp_rmb();
 		wqe = get_rwqe_ptr(rq, tail);
 		if (++tail >= rq->size)
 			tail = 0;
@@ -267,7 +269,7 @@
 	spin_lock_irqsave(&sqp->s_lock, flags);
 
 	if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_SEND_OK) ||
-	    qp->s_rnr_timeout) {
+	    sqp->s_rnr_timeout) {
 		spin_unlock_irqrestore(&sqp->s_lock, flags);
 		goto done;
 	}
@@ -319,12 +321,22 @@
 		break;
 
 	case IB_WR_RDMA_WRITE_WITH_IMM:
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_WRITE))) {
+			wc.status = IB_WC_REM_INV_REQ_ERR;
+			goto err;
+		}
 		wc.wc_flags = IB_WC_WITH_IMM;
 		wc.imm_data = wqe->wr.imm_data;
 		if (!ipath_get_rwqe(qp, 1))
 			goto rnr_nak;
 		/* FALLTHROUGH */
 	case IB_WR_RDMA_WRITE:
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_WRITE))) {
+			wc.status = IB_WC_REM_INV_REQ_ERR;
+			goto err;
+		}
 		if (wqe->length == 0)
 			break;
 		if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length,
@@ -354,8 +366,10 @@
 
 	case IB_WR_RDMA_READ:
 		if (unlikely(!(qp->qp_access_flags &
-			       IB_ACCESS_REMOTE_READ)))
-			goto acc_err;
+			       IB_ACCESS_REMOTE_READ))) {
+			wc.status = IB_WC_REM_INV_REQ_ERR;
+			goto err;
+		}
 		if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length,
 					    wqe->wr.wr.rdma.remote_addr,
 					    wqe->wr.wr.rdma.rkey,
@@ -369,8 +383,10 @@
 	case IB_WR_ATOMIC_CMP_AND_SWP:
 	case IB_WR_ATOMIC_FETCH_AND_ADD:
 		if (unlikely(!(qp->qp_access_flags &
-			       IB_ACCESS_REMOTE_ATOMIC)))
-			goto acc_err;
+			       IB_ACCESS_REMOTE_ATOMIC))) {
+			wc.status = IB_WC_REM_INV_REQ_ERR;
+			goto err;
+		}
 		if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64),
 					    wqe->wr.wr.atomic.remote_addr,
 					    wqe->wr.wr.atomic.rkey,
@@ -396,6 +412,8 @@
 
 		if (len > sge->length)
 			len = sge->length;
+		if (len > sge->sge_length)
+			len = sge->sge_length;
 		BUG_ON(len == 0);
 		ipath_copy_sge(&qp->r_sge, sge->vaddr, len);
 		sge->vaddr += len;
@@ -503,11 +521,9 @@
 	 * could be called.  If we are still in the tasklet function,
 	 * tasklet_hi_schedule() will not call us until the next time
 	 * tasklet_hi_schedule() is called.
-	 * We clear the tasklet flag now since we are committing to return
-	 * from the tasklet function.
+	 * We leave the busy flag set so that another post send doesn't
+	 * try to put the same QP on the piowait list again.
 	 */
-	clear_bit(IPATH_S_BUSY, &qp->s_busy);
-	tasklet_unlock(&qp->s_task);
 	want_buffer(dev->dd);
 	dev->n_piowait++;
 }
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
index 03acae6..40c36ec 100644
--- a/drivers/infiniband/hw/ipath/ipath_srq.c
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -80,6 +80,8 @@
 		wqe->num_sge = wr->num_sge;
 		for (i = 0; i < wr->num_sge; i++)
 			wqe->sg_list[i] = wr->sg_list[i];
+		/* Make sure queue entry is written before the head index. */
+		smp_wmb();
 		wq->head = next;
 		spin_unlock_irqrestore(&srq->rq.lock, flags);
 	}
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
index d8b5e4c..73ed17d 100644
--- a/drivers/infiniband/hw/ipath/ipath_stats.c
+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -55,6 +55,7 @@
 	u64 val64;
 	unsigned long t0, t1;
 	u64 ret;
+	unsigned long flags;
 
 	t0 = jiffies;
 	/* If fast increment counters are only 32 bits, snapshot them,
@@ -91,12 +92,18 @@
 	if (creg == dd->ipath_cregs->cr_wordsendcnt) {
 		if (val != dd->ipath_lastsword) {
 			dd->ipath_sword += val - dd->ipath_lastsword;
+			spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+			dd->ipath_traffic_wds += val - dd->ipath_lastsword;
+			spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
 			dd->ipath_lastsword = val;
 		}
 		val64 = dd->ipath_sword;
 	} else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
 		if (val != dd->ipath_lastrword) {
 			dd->ipath_rword += val - dd->ipath_lastrword;
+			spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+			dd->ipath_traffic_wds += val - dd->ipath_lastrword;
+			spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
 			dd->ipath_lastrword = val;
 		}
 		val64 = dd->ipath_rword;
@@ -200,6 +207,7 @@
 	struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
 	u32 val;
 	static unsigned cnt;
+	unsigned long flags;
 
 	/*
 	 * don't access the chip while running diags, or memory diags can
@@ -210,9 +218,20 @@
 		/* but re-arm the timer, for diags case; won't hurt other */
 		goto done;
 
+	/*
+	 * We now try to maintain a "active timer", based on traffic
+	 * exceeding a threshold, so we need to check the word-counts
+	 * even if they are 64-bit.
+	 */
+	ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+	ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+	spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+	if (dd->ipath_traffic_wds  >= IPATH_TRAFFIC_ACTIVE_THRESHOLD)
+		atomic_add(5, &dd->ipath_active_time); /* S/B #define */
+	dd->ipath_traffic_wds = 0;
+	spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+
 	if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
-		ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
-		ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
 		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
 		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
 	}
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
index 4dc398d..16238cd 100644
--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -596,6 +596,43 @@
 	return ret;
 }
 
+static ssize_t store_led_override(struct device *dev,
+			  struct device_attribute *attr,
+			  const char *buf,
+			  size_t count)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	int ret;
+	u16 val;
+
+	ret = ipath_parse_ushort(buf, &val);
+	if (ret > 0)
+		ipath_set_led_override(dd, val);
+	else
+		ipath_dev_err(dd, "attempt to set invalid LED override\n");
+	return ret;
+}
+
+static ssize_t show_logged_errs(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	int idx, count;
+
+	/* force consistency with actual EEPROM */
+	if (ipath_update_eeprom_log(dd) != 0)
+		return -ENXIO;
+
+	count = 0;
+	for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+		count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
+			dd->ipath_eep_st_errs[idx],
+			idx == (IPATH_EEP_LOG_CNT - 1) ? '\n' : ' ');
+	}
+
+	return count;
+}
 
 static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
 static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
@@ -625,6 +662,8 @@
 static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
 static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
 static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
+static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
+static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
 
 static struct attribute *dev_attributes[] = {
 	&dev_attr_guid.attr,
@@ -641,6 +680,8 @@
 	&dev_attr_unit.attr,
 	&dev_attr_enabled.attr,
 	&dev_attr_rx_pol_inv.attr,
+	&dev_attr_led_override.attr,
+	&dev_attr_logged_errors.attr,
 	NULL
 };
 
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
index 1c2b03c..8380fbc 100644
--- a/drivers/infiniband/hw/ipath/ipath_uc.c
+++ b/drivers/infiniband/hw/ipath/ipath_uc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -58,7 +58,6 @@
 		wc->port_num = 0;
 		ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 0);
 	}
-	wqe = get_swqe_ptr(qp, qp->s_last);
 }
 
 /**
@@ -87,7 +86,7 @@
 
 	/* header size in 32-bit words LRH+BTH = (8+12)/4. */
 	hwords = 5;
-	bth0 = 0;
+	bth0 = 1 << 22; /* Set M bit */
 
 	/* Get the next send request. */
 	wqe = get_swqe_ptr(qp, qp->s_last);
@@ -97,8 +96,10 @@
 		 * Signal the completion of the last send
 		 * (if there is one).
 		 */
-		if (qp->s_last != qp->s_tail)
+		if (qp->s_last != qp->s_tail) {
 			complete_last_send(qp, wqe, &wc);
+			wqe = get_swqe_ptr(qp, qp->s_last);
+		}
 
 		/* Check if send work queue is empty. */
 		if (qp->s_tail == qp->s_head)
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
index a518f7c..f9a3338 100644
--- a/drivers/infiniband/hw/ipath/ipath_ud.c
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -176,6 +176,8 @@
 			dev->n_pkt_drops++;
 			goto bail_sge;
 		}
+		/* Make sure entry is read after head index is read. */
+		smp_rmb();
 		wqe = get_rwqe_ptr(rq, tail);
 		if (++tail >= rq->size)
 			tail = 0;
@@ -231,6 +233,8 @@
 
 		if (len > length)
 			len = length;
+		if (len > sge->sge_length)
+			len = sge->sge_length;
 		BUG_ON(len == 0);
 		ipath_copy_sge(&rsge, sge->vaddr, len);
 		sge->vaddr += len;
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
index 8536aeb..27034d3 100644
--- a/drivers/infiniband/hw/ipath/ipath_user_pages.c
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index bb70845..65f7181 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -164,9 +164,11 @@
 	while (length) {
 		u32 len = sge->length;
 
-		BUG_ON(len == 0);
 		if (len > length)
 			len = length;
+		if (len > sge->sge_length)
+			len = sge->sge_length;
+		BUG_ON(len == 0);
 		memcpy(sge->vaddr, data, len);
 		sge->vaddr += len;
 		sge->length -= len;
@@ -202,9 +204,11 @@
 	while (length) {
 		u32 len = sge->length;
 
-		BUG_ON(len == 0);
 		if (len > length)
 			len = length;
+		if (len > sge->sge_length)
+			len = sge->sge_length;
+		BUG_ON(len == 0);
 		sge->vaddr += len;
 		sge->length -= len;
 		sge->sge_length -= len;
@@ -323,6 +327,8 @@
 		wqe->num_sge = wr->num_sge;
 		for (i = 0; i < wr->num_sge; i++)
 			wqe->sg_list[i] = wr->sg_list[i];
+		/* Make sure queue entry is written before the head index. */
+		smp_wmb();
 		wq->head = next;
 		spin_unlock_irqrestore(&qp->r_rq.lock, flags);
 	}
@@ -948,6 +954,7 @@
 		qp = list_entry(dev->piowait.next, struct ipath_qp,
 				piowait);
 		list_del_init(&qp->piowait);
+		clear_bit(IPATH_S_BUSY, &qp->s_busy);
 		tasklet_hi_schedule(&qp->s_task);
 	}
 	spin_unlock_irqrestore(&dev->pending_lock, flags);
@@ -981,6 +988,8 @@
 	props->max_ah = ib_ipath_max_ahs;
 	props->max_cqe = ib_ipath_max_cqes;
 	props->max_mr = dev->lk_table.max;
+	props->max_fmr = dev->lk_table.max;
+	props->max_map_per_fmr = 32767;
 	props->max_pd = ib_ipath_max_pds;
 	props->max_qp_rd_atom = IPATH_MAX_RDMA_ATOMIC;
 	props->max_qp_init_rd_atom = 255;
@@ -1051,7 +1060,12 @@
 	props->max_vl_num = 1;		/* VLCap = VL0 */
 	props->init_type_reply = 0;
 
-	props->max_mtu = IB_MTU_4096;
+	/*
+	 * Note: the chips support a maximum MTU of 4096, but the driver
+	 * hasn't implemented this feature yet, so set the maximum value
+	 * to 2048.
+	 */
+	props->max_mtu = IB_MTU_2048;
 	switch (dev->dd->ipath_ibmtu) {
 	case 4096:
 		mtu = IB_MTU_4096;
@@ -1361,13 +1375,6 @@
 {
 	struct ipath_devdata *dd = (struct ipath_devdata *) arg;
 
-	/*
-	 * If port 0 receive packet interrupts are not available, or
-	 * can be missed, poll the receive queue
-	 */
-	if (dd->ipath_flags & IPATH_POLL_RX_INTR)
-		ipath_kreceive(dd);
-
 	/* Handle verbs layer timeouts. */
 	ipath_ib_timer(dd->verbs_dev);
 
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
index 088b837..f3d1f2c 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -321,6 +321,7 @@
  */
 struct ipath_ack_entry {
 	u8 opcode;
+	u8 sent;
 	u32 psn;
 	union {
 		struct ipath_sge_state rdma_sge;
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
index 085e28b..9e5abf9 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -165,10 +165,9 @@
 {
 	struct rb_node **n = &mcast_tree.rb_node;
 	struct rb_node *pn = NULL;
-	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&mcast_lock, flags);
+	spin_lock_irq(&mcast_lock);
 
 	while (*n) {
 		struct ipath_mcast *tmcast;
@@ -228,7 +227,7 @@
 	ret = 0;
 
 bail:
-	spin_unlock_irqrestore(&mcast_lock, flags);
+	spin_unlock_irq(&mcast_lock);
 
 	return ret;
 }
@@ -289,17 +288,16 @@
 	struct ipath_mcast *mcast = NULL;
 	struct ipath_mcast_qp *p, *tmp;
 	struct rb_node *n;
-	unsigned long flags;
 	int last = 0;
 	int ret;
 
-	spin_lock_irqsave(&mcast_lock, flags);
+	spin_lock_irq(&mcast_lock);
 
 	/* Find the GID in the mcast table. */
 	n = mcast_tree.rb_node;
 	while (1) {
 		if (n == NULL) {
-			spin_unlock_irqrestore(&mcast_lock, flags);
+			spin_unlock_irq(&mcast_lock);
 			ret = -EINVAL;
 			goto bail;
 		}
@@ -334,7 +332,7 @@
 		break;
 	}
 
-	spin_unlock_irqrestore(&mcast_lock, flags);
+	spin_unlock_irq(&mcast_lock);
 
 	if (p) {
 		/*
@@ -348,9 +346,9 @@
 		atomic_dec(&mcast->refcount);
 		wait_event(mcast->wait, !atomic_read(&mcast->refcount));
 		ipath_mcast_free(mcast);
-		spin_lock(&dev->n_mcast_grps_lock);
+		spin_lock_irq(&dev->n_mcast_grps_lock);
 		dev->n_mcast_grps_allocated--;
-		spin_unlock(&dev->n_mcast_grps_lock);
+		spin_unlock_irq(&dev->n_mcast_grps_lock);
 	}
 
 	ret = 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c b/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c
index 0095bb7..1d7bd82 100644
--- a/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c
+++ b/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
index 04696e6..3428acb 100644
--- a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
+++ b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -63,12 +63,29 @@
 	 * of 2 address matching the length (which has to be a power of 2).
 	 * For rev1, that means the base address, for rev2, it will be just
 	 * the PIO buffers themselves.
+	 * For chips with two sets of buffers, the calculations are
+	 * somewhat more complicated; we need to sum, and the piobufbase
+	 * register has both offsets, 2K in low 32 bits, 4K in high 32 bits.
+	 * The buffers are still packed, so a single range covers both.
 	 */
-	pioaddr = addr + dd->ipath_piobufbase;
-	piolen = (dd->ipath_piobcnt2k +
-		  dd->ipath_piobcnt4k) *
-		ALIGN(dd->ipath_piobcnt2k +
-		      dd->ipath_piobcnt4k, dd->ipath_palign);
+	if (dd->ipath_piobcnt2k && dd->ipath_piobcnt4k) { /* 2 sizes */
+		unsigned long pio2kbase, pio4kbase;
+		pio2kbase = dd->ipath_piobufbase & 0xffffffffUL;
+		pio4kbase = (dd->ipath_piobufbase >> 32) & 0xffffffffUL;
+		if (pio2kbase < pio4kbase) { /* all, for now */
+			pioaddr = addr + pio2kbase;
+			piolen = pio4kbase - pio2kbase +
+				dd->ipath_piobcnt4k * dd->ipath_4kalign;
+		} else {
+			pioaddr = addr + pio4kbase;
+			piolen = pio2kbase - pio4kbase +
+				dd->ipath_piobcnt2k * dd->ipath_palign;
+		}
+	} else {  /* single buffer size (2K, currently) */
+		pioaddr = addr + dd->ipath_piobufbase;
+		piolen = dd->ipath_piobcnt2k * dd->ipath_palign +
+			dd->ipath_piobcnt4k * dd->ipath_4kalign;
+	}
 
 	for (bits = 0; !(piolen & (1ULL << bits)); bits++)
 		/* do nothing */ ;
diff --git a/drivers/infiniband/hw/mlx4/Kconfig b/drivers/infiniband/hw/mlx4/Kconfig
index b8912cd..4175a4b 100644
--- a/drivers/infiniband/hw/mlx4/Kconfig
+++ b/drivers/infiniband/hw/mlx4/Kconfig
@@ -1,6 +1,5 @@
 config MLX4_INFINIBAND
 	tristate "Mellanox ConnectX HCA support"
-	depends on INFINIBAND
 	select MLX4_CORE
 	---help---
 	  This driver provides low-level InfiniBand support for
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index b2a290c..660b27a 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -354,8 +354,8 @@
 	if (is_send) {
 		wq = &(*cur_qp)->sq;
 		wqe_ctr = be16_to_cpu(cqe->wqe_index);
-		wq->tail += wqe_ctr - (u16) wq->tail;
-		wc->wr_id = wq->wrid[wq->tail & (wq->max - 1)];
+		wq->tail += (u16) (wqe_ctr - (u16) wq->tail);
+		wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
 		++wq->tail;
 	} else if ((*cur_qp)->ibqp.srq) {
 		srq = to_msrq((*cur_qp)->ibqp.srq);
@@ -364,7 +364,7 @@
 		mlx4_ib_free_srq_wqe(srq, wqe_ctr);
 	} else {
 		wq	  = &(*cur_qp)->rq;
-		wc->wr_id = wq->wrid[wq->tail & (wq->max - 1)];
+		wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
 		++wq->tail;
 	}
 
@@ -478,7 +478,8 @@
 {
 	u32 prod_index;
 	int nfreed = 0;
-	struct mlx4_cqe *cqe;
+	struct mlx4_cqe *cqe, *dest;
+	u8 owner_bit;
 
 	/*
 	 * First we need to find the current producer index, so we
@@ -501,9 +502,13 @@
 			if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK))
 				mlx4_ib_free_srq_wqe(srq, be16_to_cpu(cqe->wqe_index));
 			++nfreed;
-		} else if (nfreed)
-			memcpy(get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe),
-			       cqe, sizeof *cqe);
+		} else if (nfreed) {
+			dest = get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe);
+			owner_bit = dest->owner_sr_opcode & MLX4_CQE_OWNER_MASK;
+			memcpy(dest, cqe, sizeof *cqe);
+			dest->owner_sr_opcode = owner_bit |
+				(dest->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK);
+		}
 	}
 
 	if (nfreed) {
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 402f3a2..dde8fe9 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -120,12 +120,12 @@
 	props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma;
 	props->max_res_rd_atom	   = props->max_qp_rd_atom * props->max_qp;
 	props->max_srq		   = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs;
-	props->max_srq_wr	   = dev->dev->caps.max_srq_wqes;
+	props->max_srq_wr	   = dev->dev->caps.max_srq_wqes - 1;
 	props->max_srq_sge	   = dev->dev->caps.max_srq_sge;
 	props->local_ca_ack_delay  = dev->dev->caps.local_ca_ack_delay;
 	props->atomic_cap	   = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ?
 		IB_ATOMIC_HCA : IB_ATOMIC_NONE;
-	props->max_pkeys	   = dev->dev->caps.pkey_table_len;
+	props->max_pkeys	   = dev->dev->caps.pkey_table_len[1];
 	props->max_mcast_grp	   = dev->dev->caps.num_mgms + dev->dev->caps.num_amgms;
 	props->max_mcast_qp_attach = dev->dev->caps.num_qp_per_mgm;
 	props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
@@ -168,9 +168,9 @@
 	props->state		= out_mad->data[32] & 0xf;
 	props->phys_state	= out_mad->data[33] >> 4;
 	props->port_cap_flags	= be32_to_cpup((__be32 *) (out_mad->data + 20));
-	props->gid_tbl_len	= to_mdev(ibdev)->dev->caps.gid_table_len;
-	props->max_msg_sz	= 0x80000000;
-	props->pkey_tbl_len	= to_mdev(ibdev)->dev->caps.pkey_table_len;
+	props->gid_tbl_len	= to_mdev(ibdev)->dev->caps.gid_table_len[port];
+	props->max_msg_sz	= to_mdev(ibdev)->dev->caps.max_msg_sz;
+	props->pkey_tbl_len	= to_mdev(ibdev)->dev->caps.pkey_table_len[port];
 	props->bad_pkey_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 46));
 	props->qkey_viol_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 48));
 	props->active_width	= out_mad->data[31] & 0xf;
@@ -280,8 +280,14 @@
 		return PTR_ERR(mailbox);
 
 	memset(mailbox->buf, 0, 256);
-	*(u8 *) mailbox->buf	     = !!reset_qkey_viols << 6;
-	((__be32 *) mailbox->buf)[2] = cpu_to_be32(cap_mask);
+
+	if (dev->dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
+		*(u8 *) mailbox->buf	     = !!reset_qkey_viols << 6;
+		((__be32 *) mailbox->buf)[2] = cpu_to_be32(cap_mask);
+	} else {
+		((u8 *) mailbox->buf)[3]     = !!reset_qkey_viols;
+		((__be32 *) mailbox->buf)[1] = cpu_to_be32(cap_mask);
+	}
 
 	err = mlx4_cmd(dev->dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
 		       MLX4_CMD_TIME_CLASS_B);
@@ -517,11 +523,13 @@
 		(1ull << IB_USER_VERBS_CMD_DESTROY_CQ)		|
 		(1ull << IB_USER_VERBS_CMD_CREATE_QP)		|
 		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_QUERY_QP)		|
 		(1ull << IB_USER_VERBS_CMD_DESTROY_QP)		|
 		(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)	|
 		(1ull << IB_USER_VERBS_CMD_DETACH_MCAST)	|
 		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|
 		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_QUERY_SRQ)		|
 		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
 
 	ibdev->ib_dev.query_device	= mlx4_ib_query_device;
@@ -540,10 +548,12 @@
 	ibdev->ib_dev.destroy_ah	= mlx4_ib_destroy_ah;
 	ibdev->ib_dev.create_srq	= mlx4_ib_create_srq;
 	ibdev->ib_dev.modify_srq	= mlx4_ib_modify_srq;
+	ibdev->ib_dev.query_srq		= mlx4_ib_query_srq;
 	ibdev->ib_dev.destroy_srq	= mlx4_ib_destroy_srq;
 	ibdev->ib_dev.post_srq_recv	= mlx4_ib_post_srq_recv;
 	ibdev->ib_dev.create_qp		= mlx4_ib_create_qp;
 	ibdev->ib_dev.modify_qp		= mlx4_ib_modify_qp;
+	ibdev->ib_dev.query_qp		= mlx4_ib_query_qp;
 	ibdev->ib_dev.destroy_qp	= mlx4_ib_destroy_qp;
 	ibdev->ib_dev.post_send		= mlx4_ib_post_send;
 	ibdev->ib_dev.post_recv		= mlx4_ib_post_recv;
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 93dac71..705ff2f 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -35,6 +35,7 @@
 
 #include <linux/compiler.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_umem.h>
@@ -95,7 +96,8 @@
 struct mlx4_ib_wq {
 	u64		       *wrid;
 	spinlock_t		lock;
-	int			max;
+	int			wqe_cnt;
+	int			max_post;
 	int			max_gs;
 	int			offset;
 	int			wqe_shift;
@@ -113,6 +115,7 @@
 
 	u32			doorbell_qpn;
 	__be32			sq_signal_bits;
+	int			sq_spare_wqes;
 	struct mlx4_ib_wq	sq;
 
 	struct ib_umem	       *umem;
@@ -123,6 +126,7 @@
 	u8			alt_port;
 	u8			atomic_rd_en;
 	u8			resp_depth;
+	u8			sq_no_prefetch;
 	u8			state;
 };
 
@@ -252,6 +256,7 @@
 				  struct ib_udata *udata);
 int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 		       enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
+int mlx4_ib_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
 int mlx4_ib_destroy_srq(struct ib_srq *srq);
 void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index);
 int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
@@ -263,6 +268,8 @@
 int mlx4_ib_destroy_qp(struct ib_qp *qp);
 int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 		      int attr_mask, struct ib_udata *udata);
+int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
+		     struct ib_qp_init_attr *qp_init_attr);
 int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		      struct ib_send_wr **bad_wr);
 int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 5cd7069..4004218 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -109,6 +109,20 @@
 	return get_wqe(qp, qp->sq.offset + (n << qp->sq.wqe_shift));
 }
 
+/*
+ * Stamp a SQ WQE so that it is invalid if prefetched by marking the
+ * first four bytes of every 64 byte chunk with 0xffffffff, except for
+ * the very first chunk of the WQE.
+ */
+static void stamp_send_wqe(struct mlx4_ib_qp *qp, int n)
+{
+	u32 *wqe = get_send_wqe(qp, n);
+	int i;
+
+	for (i = 16; i < 1 << (qp->sq.wqe_shift - 2); i += 16)
+		wqe[i] = 0xffffffff;
+}
+
 static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type)
 {
 	struct ib_event event;
@@ -178,6 +192,8 @@
 	case IB_QPT_GSI:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			ALIGN(MLX4_IB_UD_HEADER_SIZE +
+			      DIV_ROUND_UP(MLX4_IB_UD_HEADER_SIZE,
+					   MLX4_INLINE_ALIGN) *
 			      sizeof (struct mlx4_wqe_inline_seg),
 			      sizeof (struct mlx4_wqe_data_seg)) +
 			ALIGN(4 +
@@ -188,14 +204,42 @@
 	}
 }
 
-static int set_qp_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
-		       enum ib_qp_type type, struct mlx4_ib_qp *qp)
+static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+		       int is_user, int has_srq, struct mlx4_ib_qp *qp)
 {
-	/* Sanity check QP size before proceeding */
+	/* Sanity check RQ size before proceeding */
+	if (cap->max_recv_wr  > dev->dev->caps.max_wqes  ||
+	    cap->max_recv_sge > dev->dev->caps.max_rq_sg)
+		return -EINVAL;
+
+	if (has_srq) {
+		/* QPs attached to an SRQ should have no RQ */
+		if (cap->max_recv_wr)
+			return -EINVAL;
+
+		qp->rq.wqe_cnt = qp->rq.max_gs = 0;
+	} else {
+		/* HW requires >= 1 RQ entry with >= 1 gather entry */
+		if (is_user && (!cap->max_recv_wr || !cap->max_recv_sge))
+			return -EINVAL;
+
+		qp->rq.wqe_cnt	 = roundup_pow_of_two(max(1U, cap->max_recv_wr));
+		qp->rq.max_gs	 = roundup_pow_of_two(max(1U, cap->max_recv_sge));
+		qp->rq.wqe_shift = ilog2(qp->rq.max_gs * sizeof (struct mlx4_wqe_data_seg));
+	}
+
+	cap->max_recv_wr  = qp->rq.max_post = qp->rq.wqe_cnt;
+	cap->max_recv_sge = qp->rq.max_gs;
+
+	return 0;
+}
+
+static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+			      enum ib_qp_type type, struct mlx4_ib_qp *qp)
+{
+	/* Sanity check SQ size before proceeding */
 	if (cap->max_send_wr	 > dev->dev->caps.max_wqes  ||
-	    cap->max_recv_wr	 > dev->dev->caps.max_wqes  ||
 	    cap->max_send_sge	 > dev->dev->caps.max_sq_sg ||
-	    cap->max_recv_sge	 > dev->dev->caps.max_rq_sg ||
 	    cap->max_inline_data + send_wqe_overhead(type) +
 	    sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz)
 		return -EINVAL;
@@ -208,13 +252,6 @@
 	    cap->max_send_sge + 2 > dev->dev->caps.max_sq_sg)
 		return -EINVAL;
 
-	qp->rq.max = cap->max_recv_wr ? roundup_pow_of_two(cap->max_recv_wr) : 0;
-	qp->sq.max = cap->max_send_wr ? roundup_pow_of_two(cap->max_send_wr) : 0;
-
-	qp->rq.wqe_shift = ilog2(roundup_pow_of_two(cap->max_recv_sge *
-						    sizeof (struct mlx4_wqe_data_seg)));
-	qp->rq.max_gs    = (1 << qp->rq.wqe_shift) / sizeof (struct mlx4_wqe_data_seg);
-
 	qp->sq.wqe_shift = ilog2(roundup_pow_of_two(max(cap->max_send_sge *
 							sizeof (struct mlx4_wqe_data_seg),
 							cap->max_inline_data +
@@ -223,22 +260,39 @@
 	qp->sq.max_gs    = ((1 << qp->sq.wqe_shift) - send_wqe_overhead(type)) /
 		sizeof (struct mlx4_wqe_data_seg);
 
-	qp->buf_size = (qp->rq.max << qp->rq.wqe_shift) +
-		(qp->sq.max << qp->sq.wqe_shift);
+	/*
+	 * We need to leave 2 KB + 1 WQE of headroom in the SQ to
+	 * allow HW to prefetch.
+	 */
+	qp->sq_spare_wqes = (2048 >> qp->sq.wqe_shift) + 1;
+	qp->sq.wqe_cnt = roundup_pow_of_two(cap->max_send_wr + qp->sq_spare_wqes);
+
+	qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
+		(qp->sq.wqe_cnt << qp->sq.wqe_shift);
 	if (qp->rq.wqe_shift > qp->sq.wqe_shift) {
 		qp->rq.offset = 0;
-		qp->sq.offset = qp->rq.max << qp->rq.wqe_shift;
+		qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift;
 	} else {
-		qp->rq.offset = qp->sq.max << qp->sq.wqe_shift;
+		qp->rq.offset = qp->sq.wqe_cnt << qp->sq.wqe_shift;
 		qp->sq.offset = 0;
 	}
 
-	cap->max_send_wr  = qp->sq.max;
-	cap->max_recv_wr  = qp->rq.max;
+	cap->max_send_wr  = qp->sq.max_post = qp->sq.wqe_cnt - qp->sq_spare_wqes;
 	cap->max_send_sge = qp->sq.max_gs;
-	cap->max_recv_sge = qp->rq.max_gs;
-	cap->max_inline_data = (1 << qp->sq.wqe_shift) - send_wqe_overhead(type) -
-		sizeof (struct mlx4_wqe_inline_seg);
+	/* We don't support inline sends for kernel QPs (yet) */
+	cap->max_inline_data = 0;
+
+	return 0;
+}
+
+static int set_user_sq_size(struct mlx4_ib_qp *qp,
+			    struct mlx4_ib_create_qp *ucmd)
+{
+	qp->sq.wqe_cnt   = 1 << ucmd->log_sq_bb_count;
+	qp->sq.wqe_shift = ucmd->log_sq_stride;
+
+	qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
+		(qp->sq.wqe_cnt << qp->sq.wqe_shift);
 
 	return 0;
 }
@@ -247,9 +301,7 @@
 			    struct ib_qp_init_attr *init_attr,
 			    struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
 {
-	struct mlx4_wqe_ctrl_seg *ctrl;
 	int err;
-	int i;
 
 	mutex_init(&qp->mutex);
 	spin_lock_init(&qp->sq.lock);
@@ -264,7 +316,7 @@
 	qp->sq.head	    = 0;
 	qp->sq.tail	    = 0;
 
-	err = set_qp_size(dev, &init_attr->cap, init_attr->qp_type, qp);
+	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
 	if (err)
 		goto err;
 
@@ -276,6 +328,12 @@
 			goto err;
 		}
 
+		qp->sq_no_prefetch = ucmd.sq_no_prefetch;
+
+		err = set_user_sq_size(qp, &ucmd);
+		if (err)
+			goto err;
+
 		qp->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr,
 				       qp->buf_size, 0);
 		if (IS_ERR(qp->umem)) {
@@ -292,16 +350,26 @@
 		if (err)
 			goto err_mtt;
 
-		err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
-					  ucmd.db_addr, &qp->db);
-		if (err)
-			goto err_mtt;
+		if (!init_attr->srq) {
+			err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
+						  ucmd.db_addr, &qp->db);
+			if (err)
+				goto err_mtt;
+		}
 	} else {
-		err = mlx4_ib_db_alloc(dev, &qp->db, 0);
+		qp->sq_no_prefetch = 0;
+
+		err = set_kernel_sq_size(dev, &init_attr->cap, init_attr->qp_type, qp);
 		if (err)
 			goto err;
 
-		*qp->db.db = 0;
+		if (!init_attr->srq) {
+			err = mlx4_ib_db_alloc(dev, &qp->db, 0);
+			if (err)
+				goto err;
+
+			*qp->db.db = 0;
+		}
 
 		if (mlx4_buf_alloc(dev->dev, qp->buf_size, PAGE_SIZE * 2, &qp->buf)) {
 			err = -ENOMEM;
@@ -317,21 +385,13 @@
 		if (err)
 			goto err_mtt;
 
-		for (i = 0; i < qp->sq.max; ++i) {
-			ctrl = get_send_wqe(qp, i);
-			ctrl->owner_opcode = cpu_to_be32(1 << 31);
-		}
-
-		qp->sq.wrid  = kmalloc(qp->sq.max * sizeof (u64), GFP_KERNEL);
-		qp->rq.wrid  = kmalloc(qp->rq.max * sizeof (u64), GFP_KERNEL);
+		qp->sq.wrid  = kmalloc(qp->sq.wqe_cnt * sizeof (u64), GFP_KERNEL);
+		qp->rq.wrid  = kmalloc(qp->rq.wqe_cnt * sizeof (u64), GFP_KERNEL);
 
 		if (!qp->sq.wrid || !qp->rq.wrid) {
 			err = -ENOMEM;
 			goto err_wrid;
 		}
-
-		/* We don't support inline sends for kernel QPs (yet) */
-		init_attr->cap.max_inline_data = 0;
 	}
 
 	err = mlx4_qp_alloc(dev->dev, sqpn, &qp->mqp);
@@ -355,7 +415,7 @@
 	return 0;
 
 err_wrid:
-	if (pd->uobject)
+	if (pd->uobject && !init_attr->srq)
 		mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
 	else {
 		kfree(qp->sq.wrid);
@@ -372,7 +432,7 @@
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
 
 err_db:
-	if (!pd->uobject)
+	if (!pd->uobject && !init_attr->srq)
 		mlx4_ib_db_free(dev, &qp->db);
 
 err:
@@ -450,14 +510,16 @@
 	mlx4_mtt_cleanup(dev->dev, &qp->mtt);
 
 	if (is_user) {
-		mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
-				      &qp->db);
+		if (!qp->ibqp.srq)
+			mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
+					      &qp->db);
 		ib_umem_release(qp->umem);
 	} else {
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
-		mlx4_ib_db_free(dev, &qp->db);
+		if (!qp->ibqp.srq)
+			mlx4_ib_db_free(dev, &qp->db);
 	}
 }
 
@@ -543,24 +605,6 @@
 	return 0;
 }
 
-static void init_port(struct mlx4_ib_dev *dev, int port)
-{
-	struct mlx4_init_port_param param;
-	int err;
-
-	memset(&param, 0, sizeof param);
-
-	param.port_width_cap = dev->dev->caps.port_width_cap;
-	param.vl_cap	     = dev->dev->caps.vl_cap;
-	param.mtu	     = ib_mtu_enum_to_int(dev->dev->caps.mtu_cap);
-	param.max_gid	     = dev->dev->caps.gid_table_len;
-	param.max_pkey	     = dev->dev->caps.pkey_table_len;
-
-	err = mlx4_INIT_PORT(dev->dev, &param, port);
-	if (err)
-		printk(KERN_WARNING "INIT_PORT failed, return code %d.\n", err);
-}
-
 static int to_mlx4_st(enum ib_qp_type type)
 {
 	switch (type) {
@@ -573,7 +617,7 @@
 	}
 }
 
-static __be32 to_mlx4_access_flags(struct mlx4_ib_qp *qp, struct ib_qp_attr *attr,
+static __be32 to_mlx4_access_flags(struct mlx4_ib_qp *qp, const struct ib_qp_attr *attr,
 				   int attr_mask)
 {
 	u8 dest_rd_atomic;
@@ -603,7 +647,7 @@
 	return cpu_to_be32(hw_access_flags);
 }
 
-static void store_sqp_attrs(struct mlx4_ib_sqp *sqp, struct ib_qp_attr *attr,
+static void store_sqp_attrs(struct mlx4_ib_sqp *sqp, const struct ib_qp_attr *attr,
 			    int attr_mask)
 {
 	if (attr_mask & IB_QP_PKEY_INDEX)
@@ -619,7 +663,7 @@
 	path->sched_queue = (path->sched_queue & 0xbf) | ((port - 1) << 6);
 }
 
-static int mlx4_set_path(struct mlx4_ib_dev *dev, struct ib_ah_attr *ah,
+static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
 			 struct mlx4_qp_path *path, u8 port)
 {
 	path->grh_mylmc     = ah->src_path_bits & 0x7f;
@@ -634,9 +678,9 @@
 	path->counter_index = 0xff;
 
 	if (ah->ah_flags & IB_AH_GRH) {
-		if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len) {
+		if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len[port]) {
 			printk(KERN_ERR "sgid_index (%u) too large. max is %d\n",
-			       ah->grh.sgid_index, dev->dev->caps.gid_table_len - 1);
+			       ah->grh.sgid_index, dev->dev->caps.gid_table_len[port] - 1);
 			return -1;
 		}
 
@@ -655,14 +699,14 @@
 	return 0;
 }
 
-int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
-		      int attr_mask, struct ib_udata *udata)
+static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
+			       const struct ib_qp_attr *attr, int attr_mask,
+			       enum ib_qp_state cur_state, enum ib_qp_state new_state)
 {
 	struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
 	struct mlx4_ib_qp *qp = to_mqp(ibqp);
 	struct mlx4_qp_context *context;
 	enum mlx4_qp_optpar optpar = 0;
-	enum ib_qp_state cur_state, new_state;
 	int sqd_event;
 	int err = -EINVAL;
 
@@ -670,34 +714,6 @@
 	if (!context)
 		return -ENOMEM;
 
-	mutex_lock(&qp->mutex);
-
-	cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state;
-	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
-
-	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask))
-		goto out;
-
-	if ((attr_mask & IB_QP_PKEY_INDEX) &&
-	     attr->pkey_index >= dev->dev->caps.pkey_table_len) {
-		goto out;
-	}
-
-	if ((attr_mask & IB_QP_PORT) &&
-	    (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) {
-		goto out;
-	}
-
-	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
-	    attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) {
-		goto out;
-	}
-
-	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
-	    attr->max_dest_rd_atomic > 1 << dev->dev->caps.max_qp_dest_rdma) {
-		goto out;
-	}
-
 	context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) |
 				     (to_mlx4_st(ibqp->qp_type) << 16));
 	context->flags     |= cpu_to_be32(1 << 8); /* DE? */
@@ -731,14 +747,17 @@
 		context->mtu_msgmax = (attr->path_mtu << 5) | 31;
 	}
 
-	if (qp->rq.max)
-		context->rq_size_stride = ilog2(qp->rq.max) << 3;
+	if (qp->rq.wqe_cnt)
+		context->rq_size_stride = ilog2(qp->rq.wqe_cnt) << 3;
 	context->rq_size_stride |= qp->rq.wqe_shift - 4;
 
-	if (qp->sq.max)
-		context->sq_size_stride = ilog2(qp->sq.max) << 3;
+	if (qp->sq.wqe_cnt)
+		context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
 	context->sq_size_stride |= qp->sq.wqe_shift - 4;
 
+	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+		context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
+
 	if (qp->ibqp.uobject)
 		context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
 	else
@@ -760,11 +779,6 @@
 		optpar |= MLX4_QP_OPTPAR_PKEY_INDEX;
 	}
 
-	if (attr_mask & IB_QP_RNR_RETRY) {
-		context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
-		optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
-	}
-
 	if (attr_mask & IB_QP_AV) {
 		if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path,
 				  attr_mask & IB_QP_PORT ? attr->port_num : qp->port)) {
@@ -782,13 +796,14 @@
 	}
 
 	if (attr_mask & IB_QP_ALT_PATH) {
-		if (attr->alt_pkey_index >= dev->dev->caps.pkey_table_len)
-			return -EINVAL;
-
 		if (attr->alt_port_num == 0 ||
 		    attr->alt_port_num > dev->dev->caps.num_ports)
 			return -EINVAL;
 
+		if (attr->alt_pkey_index >=
+		    dev->dev->caps.pkey_table_len[attr->alt_port_num])
+			return -EINVAL;
+
 		if (mlx4_set_path(dev, &attr->alt_ah_attr, &context->alt_path,
 				  attr->alt_port_num))
 			return -EINVAL;
@@ -800,6 +815,12 @@
 
 	context->pd	    = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
 	context->params1    = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+
+	if (attr_mask & IB_QP_RNR_RETRY) {
+		context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
+		optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
+	}
+
 	if (attr_mask & IB_QP_RETRY_CNT) {
 		context->params1 |= cpu_to_be32(attr->retry_cnt << 16);
 		optpar |= MLX4_QP_OPTPAR_RETRY_COUNT;
@@ -849,7 +870,7 @@
 	if (ibqp->srq)
 		context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
 
-	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+	if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
 		context->db_rec_addr = cpu_to_be64(qp->db.dma);
 
 	if (cur_state == IB_QPS_INIT &&
@@ -869,6 +890,24 @@
 	else
 		sqd_event = 0;
 
+	/*
+	 * Before passing a kernel QP to the HW, make sure that the
+	 * ownership bits of the send queue are set and the SQ
+	 * headroom is stamped so that the hardware doesn't start
+	 * processing stale work requests.
+	 */
+	if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
+		struct mlx4_wqe_ctrl_seg *ctrl;
+		int i;
+
+		for (i = 0; i < qp->sq.wqe_cnt; ++i) {
+			ctrl = get_send_wqe(qp, i);
+			ctrl->owner_opcode = cpu_to_be32(1 << 31);
+
+			stamp_send_wqe(qp, i);
+		}
+	}
+
 	err = mlx4_qp_modify(dev->dev, &qp->mtt, to_mlx4_state(cur_state),
 			     to_mlx4_state(new_state), context, optpar,
 			     sqd_event, &qp->mqp);
@@ -895,7 +934,9 @@
 	 */
 	if (is_qp0(dev, qp)) {
 		if (cur_state != IB_QPS_RTR && new_state == IB_QPS_RTR)
-			init_port(dev, qp->port);
+			if (mlx4_INIT_PORT(dev->dev, qp->port))
+				printk(KERN_WARNING "INIT_PORT failed for port %d\n",
+				       qp->port);
 
 		if (cur_state != IB_QPS_RESET && cur_state != IB_QPS_ERR &&
 		    (new_state == IB_QPS_RESET || new_state == IB_QPS_ERR))
@@ -916,15 +957,90 @@
 		qp->rq.tail = 0;
 		qp->sq.head = 0;
 		qp->sq.tail = 0;
-		*qp->db.db  = 0;
+		if (!ibqp->srq)
+			*qp->db.db  = 0;
 	}
 
 out:
-	mutex_unlock(&qp->mutex);
 	kfree(context);
 	return err;
 }
 
+static const struct ib_qp_attr mlx4_ib_qp_attr = { .port_num = 1 };
+static const int mlx4_ib_qp_attr_mask_table[IB_QPT_UD + 1] = {
+		[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
+				IB_QP_PORT			|
+				IB_QP_QKEY),
+		[IB_QPT_UC]  = (IB_QP_PKEY_INDEX		|
+				IB_QP_PORT			|
+				IB_QP_ACCESS_FLAGS),
+		[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
+				IB_QP_PORT			|
+				IB_QP_ACCESS_FLAGS),
+		[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
+				IB_QP_QKEY),
+		[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
+				IB_QP_QKEY),
+};
+
+int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		      int attr_mask, struct ib_udata *udata)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
+	struct mlx4_ib_qp *qp = to_mqp(ibqp);
+	enum ib_qp_state cur_state, new_state;
+	int err = -EINVAL;
+
+	mutex_lock(&qp->mutex);
+
+	cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state;
+	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
+
+	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask))
+		goto out;
+
+	if ((attr_mask & IB_QP_PORT) &&
+	    (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) {
+		goto out;
+	}
+
+	if (attr_mask & IB_QP_PKEY_INDEX) {
+		int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
+		if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p])
+			goto out;
+	}
+
+	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
+	    attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) {
+		goto out;
+	}
+
+	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
+	    attr->max_dest_rd_atomic > dev->dev->caps.max_qp_dest_rdma) {
+		goto out;
+	}
+
+	if (cur_state == new_state && cur_state == IB_QPS_RESET) {
+		err = 0;
+		goto out;
+	}
+
+	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_ERR) {
+		err = __mlx4_ib_modify_qp(ibqp, &mlx4_ib_qp_attr,
+					  mlx4_ib_qp_attr_mask_table[ibqp->qp_type],
+					  IB_QPS_RESET, IB_QPS_INIT);
+		if (err)
+			goto out;
+		cur_state = IB_QPS_INIT;
+	}
+
+	err = __mlx4_ib_modify_qp(ibqp, attr, attr_mask, cur_state, new_state);
+
+out:
+	mutex_unlock(&qp->mutex);
+	return err;
+}
+
 static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 			    void *wqe)
 {
@@ -935,6 +1051,7 @@
 	u16 pkey;
 	int send_size;
 	int header_size;
+	int spc;
 	int i;
 
 	send_size = 0;
@@ -952,6 +1069,7 @@
 			(be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20) & 0xff;
 		sqp->ud_header.grh.flow_label    =
 			ah->av.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
+		sqp->ud_header.grh.hop_limit     = ah->av.hop_limit;
 		ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.port_pd) >> 24,
 				  ah->av.gid_index, &sqp->ud_header.grh.source_gid);
 		memcpy(sqp->ud_header.grh.destination_gid.raw,
@@ -1009,10 +1127,43 @@
 		printk("\n");
 	}
 
-	inl->byte_count = cpu_to_be32(1 << 31 | header_size);
-	memcpy(inl + 1, sqp->header_buf, header_size);
+	/*
+	 * Inline data segments may not cross a 64 byte boundary.  If
+	 * our UD header is bigger than the space available up to the
+	 * next 64 byte boundary in the WQE, use two inline data
+	 * segments to hold the UD header.
+	 */
+	spc = MLX4_INLINE_ALIGN -
+		((unsigned long) (inl + 1) & (MLX4_INLINE_ALIGN - 1));
+	if (header_size <= spc) {
+		inl->byte_count = cpu_to_be32(1 << 31 | header_size);
+		memcpy(inl + 1, sqp->header_buf, header_size);
+		i = 1;
+	} else {
+		inl->byte_count = cpu_to_be32(1 << 31 | spc);
+		memcpy(inl + 1, sqp->header_buf, spc);
 
-	return ALIGN(sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
+		inl = (void *) (inl + 1) + spc;
+		memcpy(inl + 1, sqp->header_buf + spc, header_size - spc);
+		/*
+		 * Need a barrier here to make sure all the data is
+		 * visible before the byte_count field is set.
+		 * Otherwise the HCA prefetcher could grab the 64-byte
+		 * chunk with this inline segment and get a valid (!=
+		 * 0xffffffff) byte count but stale data, and end up
+		 * generating a packet with bad headers.
+		 *
+		 * The first inline segment's byte_count field doesn't
+		 * need a barrier, because it comes after a
+		 * control/MLX segment and therefore is at an offset
+		 * of 16 mod 64.
+		 */
+		wmb();
+		inl->byte_count = cpu_to_be32(1 << 31 | (header_size - spc));
+		i = 2;
+	}
+
+	return ALIGN(i * sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
 }
 
 static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq)
@@ -1021,7 +1172,7 @@
 	struct mlx4_ib_cq *cq;
 
 	cur = wq->head - wq->tail;
-	if (likely(cur + nreq < wq->max))
+	if (likely(cur + nreq < wq->max_post))
 		return 0;
 
 	cq = to_mcq(ib_cq);
@@ -1029,7 +1180,7 @@
 	cur = wq->head - wq->tail;
 	spin_unlock(&cq->lock);
 
-	return cur + nreq >= wq->max;
+	return cur + nreq >= wq->max_post;
 }
 
 int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
@@ -1062,8 +1213,8 @@
 			goto out;
 		}
 
-		ctrl = wqe = get_send_wqe(qp, ind & (qp->sq.max - 1));
-		qp->sq.wrid[ind & (qp->sq.max - 1)] = wr->wr_id;
+		ctrl = wqe = get_send_wqe(qp, ind & (qp->sq.wqe_cnt - 1));
+		qp->sq.wrid[ind & (qp->sq.wqe_cnt - 1)] = wr->wr_id;
 
 		ctrl->srcrb_flags =
 			(wr->send_flags & IB_SEND_SIGNALED ?
@@ -1192,13 +1343,22 @@
 		 */
 		wmb();
 
-		if (wr->opcode < 0 || wr->opcode > ARRAY_SIZE(mlx4_ib_opcode)) {
+		if (wr->opcode < 0 || wr->opcode >= ARRAY_SIZE(mlx4_ib_opcode)) {
 			err = -EINVAL;
 			goto out;
 		}
 
 		ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] |
-			(ind & qp->sq.max ? cpu_to_be32(1 << 31) : 0);
+			(ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0);
+
+		/*
+		 * We can improve latency by not stamping the last
+		 * send queue WQE until after ringing the doorbell, so
+		 * only stamp here if there are still more WQEs to post.
+		 */
+		if (wr->next)
+			stamp_send_wqe(qp, (ind + qp->sq_spare_wqes) &
+				       (qp->sq.wqe_cnt - 1));
 
 		++ind;
 	}
@@ -1221,6 +1381,9 @@
 		 * and reach the HCA out of order.
 		 */
 		mmiowb();
+
+		stamp_send_wqe(qp, (ind + qp->sq_spare_wqes - 1) &
+			       (qp->sq.wqe_cnt - 1));
 	}
 
 	spin_unlock_irqrestore(&qp->rq.lock, flags);
@@ -1241,7 +1404,7 @@
 
 	spin_lock_irqsave(&qp->rq.lock, flags);
 
-	ind = qp->rq.head & (qp->rq.max - 1);
+	ind = qp->rq.head & (qp->rq.wqe_cnt - 1);
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.send_cq)) {
@@ -1272,7 +1435,7 @@
 
 		qp->rq.wrid[ind] = wr->wr_id;
 
-		ind = (ind + 1) & (qp->rq.max - 1);
+		ind = (ind + 1) & (qp->rq.wqe_cnt - 1);
 	}
 
 out:
@@ -1292,3 +1455,140 @@
 
 	return err;
 }
+
+static inline enum ib_qp_state to_ib_qp_state(enum mlx4_qp_state mlx4_state)
+{
+	switch (mlx4_state) {
+	case MLX4_QP_STATE_RST:      return IB_QPS_RESET;
+	case MLX4_QP_STATE_INIT:     return IB_QPS_INIT;
+	case MLX4_QP_STATE_RTR:      return IB_QPS_RTR;
+	case MLX4_QP_STATE_RTS:      return IB_QPS_RTS;
+	case MLX4_QP_STATE_SQ_DRAINING:
+	case MLX4_QP_STATE_SQD:      return IB_QPS_SQD;
+	case MLX4_QP_STATE_SQER:     return IB_QPS_SQE;
+	case MLX4_QP_STATE_ERR:      return IB_QPS_ERR;
+	default:		     return -1;
+	}
+}
+
+static inline enum ib_mig_state to_ib_mig_state(int mlx4_mig_state)
+{
+	switch (mlx4_mig_state) {
+	case MLX4_QP_PM_ARMED:		return IB_MIG_ARMED;
+	case MLX4_QP_PM_REARM:		return IB_MIG_REARM;
+	case MLX4_QP_PM_MIGRATED:	return IB_MIG_MIGRATED;
+	default: return -1;
+	}
+}
+
+static int to_ib_qp_access_flags(int mlx4_flags)
+{
+	int ib_flags = 0;
+
+	if (mlx4_flags & MLX4_QP_BIT_RRE)
+		ib_flags |= IB_ACCESS_REMOTE_READ;
+	if (mlx4_flags & MLX4_QP_BIT_RWE)
+		ib_flags |= IB_ACCESS_REMOTE_WRITE;
+	if (mlx4_flags & MLX4_QP_BIT_RAE)
+		ib_flags |= IB_ACCESS_REMOTE_ATOMIC;
+
+	return ib_flags;
+}
+
+static void to_ib_ah_attr(struct mlx4_dev *dev, struct ib_ah_attr *ib_ah_attr,
+				struct mlx4_qp_path *path)
+{
+	memset(ib_ah_attr, 0, sizeof *path);
+	ib_ah_attr->port_num	  = path->sched_queue & 0x40 ? 2 : 1;
+
+	if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->caps.num_ports)
+		return;
+
+	ib_ah_attr->dlid	  = be16_to_cpu(path->rlid);
+	ib_ah_attr->sl		  = (path->sched_queue >> 2) & 0xf;
+	ib_ah_attr->src_path_bits = path->grh_mylmc & 0x7f;
+	ib_ah_attr->static_rate   = path->static_rate ? path->static_rate - 5 : 0;
+	ib_ah_attr->ah_flags      = (path->grh_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
+	if (ib_ah_attr->ah_flags) {
+		ib_ah_attr->grh.sgid_index = path->mgid_index;
+		ib_ah_attr->grh.hop_limit  = path->hop_limit;
+		ib_ah_attr->grh.traffic_class =
+			(be32_to_cpu(path->tclass_flowlabel) >> 20) & 0xff;
+		ib_ah_attr->grh.flow_label =
+			be32_to_cpu(path->tclass_flowlabel) & 0xffffff;
+		memcpy(ib_ah_attr->grh.dgid.raw,
+			path->rgid, sizeof ib_ah_attr->grh.dgid.raw);
+	}
+}
+
+int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
+		     struct ib_qp_init_attr *qp_init_attr)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
+	struct mlx4_ib_qp *qp = to_mqp(ibqp);
+	struct mlx4_qp_context context;
+	int mlx4_state;
+	int err;
+
+	if (qp->state == IB_QPS_RESET) {
+		qp_attr->qp_state = IB_QPS_RESET;
+		goto done;
+	}
+
+	err = mlx4_qp_query(dev->dev, &qp->mqp, &context);
+	if (err)
+		return -EINVAL;
+
+	mlx4_state = be32_to_cpu(context.flags) >> 28;
+
+	qp_attr->qp_state	     = to_ib_qp_state(mlx4_state);
+	qp_attr->path_mtu	     = context.mtu_msgmax >> 5;
+	qp_attr->path_mig_state	     =
+		to_ib_mig_state((be32_to_cpu(context.flags) >> 11) & 0x3);
+	qp_attr->qkey		     = be32_to_cpu(context.qkey);
+	qp_attr->rq_psn		     = be32_to_cpu(context.rnr_nextrecvpsn) & 0xffffff;
+	qp_attr->sq_psn		     = be32_to_cpu(context.next_send_psn) & 0xffffff;
+	qp_attr->dest_qp_num	     = be32_to_cpu(context.remote_qpn) & 0xffffff;
+	qp_attr->qp_access_flags     =
+		to_ib_qp_access_flags(be32_to_cpu(context.params2));
+
+	if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
+		to_ib_ah_attr(dev->dev, &qp_attr->ah_attr, &context.pri_path);
+		to_ib_ah_attr(dev->dev, &qp_attr->alt_ah_attr, &context.alt_path);
+		qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f;
+		qp_attr->alt_port_num	= qp_attr->alt_ah_attr.port_num;
+	}
+
+	qp_attr->pkey_index = context.pri_path.pkey_index & 0x7f;
+	qp_attr->port_num   = context.pri_path.sched_queue & 0x40 ? 2 : 1;
+
+	/* qp_attr->en_sqd_async_notify is only applicable in modify qp */
+	qp_attr->sq_draining = mlx4_state == MLX4_QP_STATE_SQ_DRAINING;
+
+	qp_attr->max_rd_atomic = 1 << ((be32_to_cpu(context.params1) >> 21) & 0x7);
+
+	qp_attr->max_dest_rd_atomic =
+		1 << ((be32_to_cpu(context.params2) >> 21) & 0x7);
+	qp_attr->min_rnr_timer	    =
+		(be32_to_cpu(context.rnr_nextrecvpsn) >> 24) & 0x1f;
+	qp_attr->timeout	    = context.pri_path.ackto >> 3;
+	qp_attr->retry_cnt	    = (be32_to_cpu(context.params1) >> 16) & 0x7;
+	qp_attr->rnr_retry	    = (be32_to_cpu(context.params1) >> 13) & 0x7;
+	qp_attr->alt_timeout	    = context.alt_path.ackto >> 3;
+
+done:
+	qp_attr->cur_qp_state	     = qp_attr->qp_state;
+	if (!ibqp->uobject) {
+		qp_attr->cap.max_send_wr     = qp->sq.wqe_cnt;
+		qp_attr->cap.max_recv_wr     = qp->rq.wqe_cnt;
+		qp_attr->cap.max_send_sge    = qp->sq.max_gs;
+		qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
+		qp_attr->cap.max_inline_data = (1 << qp->sq.wqe_shift) -
+			send_wqe_overhead(qp->ibqp.qp_type) -
+			sizeof (struct mlx4_wqe_inline_seg);
+		qp_init_attr->cap	     = qp_attr->cap;
+	}
+
+	return 0;
+}
+
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index 42ab4a8..408748f 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -240,6 +240,24 @@
 	return 0;
 }
 
+int mlx4_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ibsrq->device);
+	struct mlx4_ib_srq *srq = to_msrq(ibsrq);
+	int ret;
+	int limit_watermark;
+
+	ret = mlx4_srq_query(dev->dev, &srq->msrq, &limit_watermark);
+	if (ret)
+		return ret;
+
+	srq_attr->srq_limit = be16_to_cpu(limit_watermark);
+	srq_attr->max_wr    = srq->msrq.max - 1;
+	srq_attr->max_sge   = srq->msrq.max_gs;
+
+	return 0;
+}
+
 int mlx4_ib_destroy_srq(struct ib_srq *srq)
 {
 	struct mlx4_ib_dev *dev = to_mdev(srq->device);
@@ -297,6 +315,12 @@
 			break;
 		}
 
+		if (unlikely(srq->head == srq->tail)) {
+			err = -ENOMEM;
+			*bad_wr = wr;
+			break;
+		}
+
 		srq->wrid[srq->head] = wr->wr_id;
 
 		next      = get_wqe(srq, srq->head);
diff --git a/drivers/infiniband/hw/mlx4/user.h b/drivers/infiniband/hw/mlx4/user.h
index 5b8eddc..e2d11be 100644
--- a/drivers/infiniband/hw/mlx4/user.h
+++ b/drivers/infiniband/hw/mlx4/user.h
@@ -39,7 +39,7 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define MLX4_IB_UVERBS_ABI_VERSION	1
+#define MLX4_IB_UVERBS_ABI_VERSION	3
 
 /*
  * Make sure that all structs defined in this file remain laid out so
@@ -87,6 +87,10 @@
 struct mlx4_ib_create_qp {
 	__u64	buf_addr;
 	__u64	db_addr;
+	__u8	log_sq_bb_count;
+	__u8	log_sq_stride;
+	__u8	sq_no_prefetch;
+	__u8	reserved[5];
 };
 
 #endif /* MLX4_IB_USER_H */
diff --git a/drivers/infiniband/hw/mthca/Kconfig b/drivers/infiniband/hw/mthca/Kconfig
index 9aa5a44..03efc07 100644
--- a/drivers/infiniband/hw/mthca/Kconfig
+++ b/drivers/infiniband/hw/mthca/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_MTHCA
 	tristate "Mellanox HCA support"
-	depends on PCI && INFINIBAND
+	depends on PCI
 	---help---
 	  This is a low-level driver for Mellanox InfiniHost host
 	  channel adapters (HCAs), including the MT23108 PCI-X HCA
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index f930e55..a763067 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -255,7 +255,7 @@
 			dma_list[i] = t;
 			pci_unmap_addr_set(&buf->page_list[i], mapping, t);
 
-			memset(buf->page_list[i].buf, 0, PAGE_SIZE);
+			clear_page(buf->page_list[i].buf);
 		}
 	}
 
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index 27caf3b..4b111a8 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -279,6 +279,7 @@
 			(be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff;
 		header->grh.flow_label    =
 			ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff);
+		header->grh.hop_limit     = ah->av->hop_limit;
 		ib_get_cached_gid(&dev->ib_dev,
 				  be32_to_cpu(ah->av->port_pd) >> 24,
 				  ah->av->gid_index % dev->limits.gid_table_len,
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 7131446..f40558d 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -37,6 +37,7 @@
 #include <linux/completion.h>
 #include <linux/pci.h>
 #include <linux/errno.h>
+#include <linux/sched.h>
 #include <asm/io.h>
 #include <rdma/ib_mad.h>
 
@@ -771,7 +772,7 @@
 
 	MTHCA_GET(dev->fw_ver,   outbox, QUERY_FW_VER_OFFSET);
 	/*
-	 * FW subminor version is at more signifant bits than minor
+	 * FW subminor version is at more significant bits than minor
 	 * version, so swap here.
 	 */
 	dev->fw_ver = (dev->fw_ver & 0xffff00000000ull) |
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index ca224d0..be6e1e0 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -37,6 +37,7 @@
  */
 
 #include <linux/hardirq.h>
+#include <linux/sched.h>
 
 #include <asm/io.h>
 
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 8ec9fa1..8592b26 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -522,7 +522,7 @@
 		dma_list[i] = t;
 		pci_unmap_addr_set(&eq->page_list[i], mapping, t);
 
-		memset(eq->page_list[i].buf, 0, PAGE_SIZE);
+		clear_page(eq->page_list[i].buf);
 	}
 
 	for (i = 0; i < eq->nent; ++i)
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 773145e..aa563e6 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -1250,12 +1250,14 @@
 int __mthca_restart_one(struct pci_dev *pdev)
 {
 	struct mthca_dev *mdev;
+	int hca_type;
 
 	mdev = pci_get_drvdata(pdev);
 	if (!mdev)
 		return -ENODEV;
+	hca_type = mdev->hca_type;
 	__mthca_remove_one(pdev);
-	return __mthca_init_one(pdev, mdev->hca_type);
+	return __mthca_init_one(pdev, hca_type);
 }
 
 static int __devinit mthca_init_one(struct pci_dev *pdev,
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 48f7c65..e61f3e6 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -36,6 +36,7 @@
 
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
+#include <linux/sched.h>
 
 #include <asm/page.h>
 
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 72fabb8..11f1d99 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -37,6 +37,7 @@
 
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 
 #include <asm/io.h>
 
@@ -295,7 +296,7 @@
 	}
 }
 
-static void store_attrs(struct mthca_sqp *sqp, struct ib_qp_attr *attr,
+static void store_attrs(struct mthca_sqp *sqp, const struct ib_qp_attr *attr,
 			int attr_mask)
 {
 	if (attr_mask & IB_QP_PKEY_INDEX)
@@ -327,7 +328,7 @@
 		mthca_warn(dev, "INIT_IB returned status %02x.\n", status);
 }
 
-static __be32 get_hw_access_flags(struct mthca_qp *qp, struct ib_qp_attr *attr,
+static __be32 get_hw_access_flags(struct mthca_qp *qp, const struct ib_qp_attr *attr,
 				  int attr_mask)
 {
 	u8 dest_rd_atomic;
@@ -510,7 +511,7 @@
 	return err;
 }
 
-static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah,
+static int mthca_path_set(struct mthca_dev *dev, const struct ib_ah_attr *ah,
 			  struct mthca_qp_path *path, u8 port)
 {
 	path->g_mylmc     = ah->src_path_bits & 0x7f;
@@ -538,12 +539,12 @@
 	return 0;
 }
 
-int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
-		    struct ib_udata *udata)
+static int __mthca_modify_qp(struct ib_qp *ibqp,
+			     const struct ib_qp_attr *attr, int attr_mask,
+			     enum ib_qp_state cur_state, enum ib_qp_state new_state)
 {
 	struct mthca_dev *dev = to_mdev(ibqp->device);
 	struct mthca_qp *qp = to_mqp(ibqp);
-	enum ib_qp_state cur_state, new_state;
 	struct mthca_mailbox *mailbox;
 	struct mthca_qp_param *qp_param;
 	struct mthca_qp_context *qp_context;
@@ -551,60 +552,6 @@
 	u8 status;
 	int err = -EINVAL;
 
-	mutex_lock(&qp->mutex);
-
-	if (attr_mask & IB_QP_CUR_STATE) {
-		cur_state = attr->cur_qp_state;
-	} else {
-		spin_lock_irq(&qp->sq.lock);
-		spin_lock(&qp->rq.lock);
-		cur_state = qp->state;
-		spin_unlock(&qp->rq.lock);
-		spin_unlock_irq(&qp->sq.lock);
-	}
-
-	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
-
-	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) {
-		mthca_dbg(dev, "Bad QP transition (transport %d) "
-			  "%d->%d with attr 0x%08x\n",
-			  qp->transport, cur_state, new_state,
-			  attr_mask);
-		goto out;
-	}
-
-	if (cur_state == new_state && cur_state == IB_QPS_RESET) {
-		err = 0;
-		goto out;
-	}
-
-	if ((attr_mask & IB_QP_PKEY_INDEX) &&
-	     attr->pkey_index >= dev->limits.pkey_table_len) {
-		mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
-			  attr->pkey_index, dev->limits.pkey_table_len-1);
-		goto out;
-	}
-
-	if ((attr_mask & IB_QP_PORT) &&
-	    (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
-		mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
-		goto out;
-	}
-
-	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
-	    attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
-		mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
-			  attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
-		goto out;
-	}
-
-	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
-	    attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
-		mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
-			  attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
-		goto out;
-	}
-
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
 	if (IS_ERR(mailbox)) {
 		err = PTR_ERR(mailbox);
@@ -891,6 +838,98 @@
 
 out_mailbox:
 	mthca_free_mailbox(dev, mailbox);
+out:
+	return err;
+}
+
+static const struct ib_qp_attr dummy_init_attr = { .port_num = 1 };
+static const int dummy_init_attr_mask[] = {
+	[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
+			IB_QP_PORT			|
+			IB_QP_QKEY),
+	[IB_QPT_UC]  = (IB_QP_PKEY_INDEX		|
+			IB_QP_PORT			|
+			IB_QP_ACCESS_FLAGS),
+	[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
+			IB_QP_PORT			|
+			IB_QP_ACCESS_FLAGS),
+	[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
+			IB_QP_QKEY),
+	[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
+			IB_QP_QKEY),
+};
+
+int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+		    struct ib_udata *udata)
+{
+	struct mthca_dev *dev = to_mdev(ibqp->device);
+	struct mthca_qp *qp = to_mqp(ibqp);
+	enum ib_qp_state cur_state, new_state;
+	int err = -EINVAL;
+
+	mutex_lock(&qp->mutex);
+	if (attr_mask & IB_QP_CUR_STATE) {
+		cur_state = attr->cur_qp_state;
+	} else {
+		spin_lock_irq(&qp->sq.lock);
+		spin_lock(&qp->rq.lock);
+		cur_state = qp->state;
+		spin_unlock(&qp->rq.lock);
+		spin_unlock_irq(&qp->sq.lock);
+	}
+
+	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
+
+	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) {
+		mthca_dbg(dev, "Bad QP transition (transport %d) "
+			  "%d->%d with attr 0x%08x\n",
+			  qp->transport, cur_state, new_state,
+			  attr_mask);
+		goto out;
+	}
+
+	if ((attr_mask & IB_QP_PKEY_INDEX) &&
+	     attr->pkey_index >= dev->limits.pkey_table_len) {
+		mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
+			  attr->pkey_index, dev->limits.pkey_table_len-1);
+		goto out;
+	}
+
+	if ((attr_mask & IB_QP_PORT) &&
+	    (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
+		mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
+		goto out;
+	}
+
+	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
+	    attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
+		mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
+			  attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
+		goto out;
+	}
+
+	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
+	    attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
+		mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
+			  attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
+		goto out;
+	}
+
+	if (cur_state == new_state && cur_state == IB_QPS_RESET) {
+		err = 0;
+		goto out;
+	}
+
+	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_ERR) {
+		err = __mthca_modify_qp(ibqp, &dummy_init_attr,
+					dummy_init_attr_mask[ibqp->qp_type],
+					IB_QPS_RESET, IB_QPS_INIT);
+		if (err)
+			goto out;
+		cur_state = IB_QPS_INIT;
+	}
+
+	err = __mthca_modify_qp(ibqp, attr, attr_mask, cur_state, new_state);
 
 out:
 	mutex_unlock(&qp->mutex);
@@ -1552,7 +1591,7 @@
 	int i;
 	int size;
 	int size0 = 0;
-	u32 f0;
+	u32 f0 = 0;
 	int ind;
 	u8 op0 = 0;
 
@@ -1907,7 +1946,7 @@
 	int i;
 	int size;
 	int size0 = 0;
-	u32 f0;
+	u32 f0 = 0;
 	int ind;
 	u8 op0 = 0;
 
@@ -2245,10 +2284,10 @@
 	struct mthca_next_seg *next;
 
 	/*
-	 * For SRQs, all WQEs generate a CQE, so we're always at the
-	 * end of the doorbell chain.
+	 * For SRQs, all receive WQEs generate a CQE, so we're always
+	 * at the end of the doorbell chain.
 	 */
-	if (qp->ibqp.srq) {
+	if (qp->ibqp.srq && !is_send) {
 		*new_wqe = 0;
 		return;
 	}
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 61974b0..b8f05a5 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -34,6 +34,7 @@
 
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/sched.h>
 
 #include <asm/io.h>
 
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index af78ccc..1f76bad 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_IPOIB
 	tristate "IP-over-InfiniBand"
-	depends on INFINIBAND && NETDEVICES && INET && (IPV6 || IPV6=n)
+	depends on NETDEVICES && INET && (IPV6 || IPV6=n)
 	---help---
 	  Support for the IP-over-InfiniBand protocol (IPoIB). This
 	  transports IP packets over InfiniBand so you can use your IB
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 87310ee..285c143 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -132,12 +132,46 @@
 	__be32 mtu;
 };
 
+/*
+ * Quoting 10.3.1 Queue Pair and EE Context States:
+ *
+ * Note, for QPs that are associated with an SRQ, the Consumer should take the
+ * QP through the Error State before invoking a Destroy QP or a Modify QP to the
+ * Reset State.  The Consumer may invoke the Destroy QP without first performing
+ * a Modify QP to the Error State and waiting for the Affiliated Asynchronous
+ * Last WQE Reached Event. However, if the Consumer does not wait for the
+ * Affiliated Asynchronous Last WQE Reached Event, then WQE and Data Segment
+ * leakage may occur. Therefore, it is good programming practice to tear down a
+ * QP that is associated with an SRQ by using the following process:
+ *
+ * - Put the QP in the Error State
+ * - Wait for the Affiliated Asynchronous Last WQE Reached Event;
+ * - either:
+ *       drain the CQ by invoking the Poll CQ verb and either wait for CQ
+ *       to be empty or the number of Poll CQ operations has exceeded
+ *       CQ capacity size;
+ * - or
+ *       post another WR that completes on the same CQ and wait for this
+ *       WR to return as a WC;
+ * - and then invoke a Destroy QP or Reset QP.
+ *
+ * We use the second option and wait for a completion on the
+ * same CQ before destroying QPs attached to our SRQ.
+ */
+
+enum ipoib_cm_state {
+	IPOIB_CM_RX_LIVE,
+	IPOIB_CM_RX_ERROR, /* Ignored by stale task */
+	IPOIB_CM_RX_FLUSH  /* Last WQE Reached event observed */
+};
+
 struct ipoib_cm_rx {
 	struct ib_cm_id     *id;
 	struct ib_qp        *qp;
 	struct list_head     list;
 	struct net_device   *dev;
 	unsigned long        jiffies;
+	enum ipoib_cm_state  state;
 };
 
 struct ipoib_cm_tx {
@@ -165,10 +199,15 @@
 	struct ib_srq  	       *srq;
 	struct ipoib_cm_rx_buf *srq_ring;
 	struct ib_cm_id        *id;
-	struct list_head        passive_ids;
+	struct list_head        passive_ids;   /* state: LIVE */
+	struct list_head        rx_error_list; /* state: ERROR */
+	struct list_head        rx_flush_list; /* state: FLUSH, drain not started */
+	struct list_head        rx_drain_list; /* state: FLUSH, drain started */
+	struct list_head        rx_reap_list;  /* state: FLUSH, drain done */
 	struct work_struct      start_task;
 	struct work_struct      reap_task;
 	struct work_struct      skb_task;
+	struct work_struct      rx_reap_task;
 	struct delayed_work     stale_task;
 	struct sk_buff_head     skb_queue;
 	struct list_head        start_list;
@@ -201,15 +240,17 @@
 	struct list_head multicast_list;
 	struct rb_root multicast_tree;
 
-	struct delayed_work pkey_task;
+	struct delayed_work pkey_poll_task;
 	struct delayed_work mcast_task;
 	struct work_struct flush_task;
 	struct work_struct restart_task;
 	struct delayed_work ah_reap_task;
+	struct work_struct pkey_event_task;
 
 	struct ib_device *ca;
 	u8            	  port;
 	u16           	  pkey;
+	u16               pkey_index;
 	struct ib_pd  	 *pd;
 	struct ib_mr  	 *mr;
 	struct ib_cq  	 *cq;
@@ -333,12 +374,13 @@
 
 int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
 void ipoib_ib_dev_flush(struct work_struct *work);
+void ipoib_pkey_event(struct work_struct *work);
 void ipoib_ib_dev_cleanup(struct net_device *dev);
 
 int ipoib_ib_dev_open(struct net_device *dev);
 int ipoib_ib_dev_up(struct net_device *dev);
 int ipoib_ib_dev_down(struct net_device *dev, int flush);
-int ipoib_ib_dev_stop(struct net_device *dev);
+int ipoib_ib_dev_stop(struct net_device *dev, int flush);
 
 int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
 void ipoib_dev_cleanup(struct net_device *dev);
@@ -386,6 +428,7 @@
 
 void ipoib_pkey_poll(struct work_struct *work);
 int ipoib_pkey_dev_delay_open(struct net_device *dev);
+void ipoib_drain_cq(struct net_device *dev);
 
 #ifdef CONFIG_INFINIBAND_IPOIB_CM
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index eec833b..08b4676 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -37,6 +37,7 @@
 #include <net/dst.h>
 #include <net/icmp.h>
 #include <linux/icmpv6.h>
+#include <linux/delay.h>
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG_DATA
 static int data_debug_level;
@@ -55,11 +56,15 @@
 #define IPOIB_CM_RX_DELAY       (3 * 256 * HZ)
 #define IPOIB_CM_RX_UPDATE_MASK (0x3)
 
-struct ipoib_cm_id {
-	struct ib_cm_id *id;
-	int flags;
-	u32 remote_qpn;
-	u32 remote_mtu;
+static struct ib_qp_attr ipoib_cm_err_attr = {
+	.qp_state = IB_QPS_ERR
+};
+
+#define IPOIB_CM_RX_DRAIN_WRID 0x7fffffff
+
+static struct ib_send_wr ipoib_cm_rx_drain_wr = {
+	.wr_id = IPOIB_CM_RX_DRAIN_WRID,
+	.opcode = IB_WR_SEND,
 };
 
 static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
@@ -143,22 +148,61 @@
 
 	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
-	for (; i >= 0; --i)
-		ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+	for (; i > 0; --i)
+		ib_dma_unmap_single(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
 
 	dev_kfree_skb_any(skb);
 	return NULL;
 }
 
+static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv* priv)
+{
+	struct ib_send_wr *bad_wr;
+	struct ipoib_cm_rx *p;
+
+	/* We only reserved 1 extra slot in CQ for drain WRs, so
+	 * make sure we have at most 1 outstanding WR. */
+	if (list_empty(&priv->cm.rx_flush_list) ||
+	    !list_empty(&priv->cm.rx_drain_list))
+		return;
+
+	/*
+	 * QPs on flush list are error state.  This way, a "flush
+	 * error" WC will be immediately generated for each WR we post.
+	 */
+	p = list_entry(priv->cm.rx_flush_list.next, typeof(*p), list);
+	if (ib_post_send(p->qp, &ipoib_cm_rx_drain_wr, &bad_wr))
+		ipoib_warn(priv, "failed to post drain wr\n");
+
+	list_splice_init(&priv->cm.rx_flush_list, &priv->cm.rx_drain_list);
+}
+
+static void ipoib_cm_rx_event_handler(struct ib_event *event, void *ctx)
+{
+	struct ipoib_cm_rx *p = ctx;
+	struct ipoib_dev_priv *priv = netdev_priv(p->dev);
+	unsigned long flags;
+
+	if (event->event != IB_EVENT_QP_LAST_WQE_REACHED)
+		return;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	list_move(&p->list, &priv->cm.rx_flush_list);
+	p->state = IPOIB_CM_RX_FLUSH;
+	ipoib_cm_start_rx_drain(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
 static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
 					   struct ipoib_cm_rx *p)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ib_qp_init_attr attr = {
-		.send_cq = priv->cq, /* does not matter, we never send anything */
+		.event_handler = ipoib_cm_rx_event_handler,
+		.send_cq = priv->cq, /* For drain WR */
 		.recv_cq = priv->cq,
 		.srq = priv->cm.srq,
-		.cap.max_send_wr = 1, /* FIXME: 0 Seems not to work */
+		.cap.max_send_wr = 1, /* For drain WR */
 		.cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */
 		.sq_sig_type = IB_SIGNAL_ALL_WR,
 		.qp_type = IB_QPT_RC,
@@ -198,6 +242,27 @@
 		ipoib_warn(priv, "failed to modify QP to RTR: %d\n", ret);
 		return ret;
 	}
+
+	/*
+	 * Current Mellanox HCA firmware won't generate completions
+	 * with error for drain WRs unless the QP has been moved to
+	 * RTS first. This work-around leaves a window where a QP has
+	 * moved to error asynchronously, but this will eventually get
+	 * fixed in firmware, so let's not error out if modify QP
+	 * fails.
+	 */
+	qp_attr.qp_state = IB_QPS_RTS;
+	ret = ib_cm_init_qp_attr(cm_id, &qp_attr, &qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to init QP attr for RTS: %d\n", ret);
+		return 0;
+	}
+	ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to modify QP to RTS: %d\n", ret);
+		return 0;
+	}
+
 	return 0;
 }
 
@@ -216,7 +281,6 @@
 	rep.private_data_len = sizeof data;
 	rep.flow_control = 0;
 	rep.rnr_retry_count = req->rnr_retry_count;
-	rep.target_ack_delay = 20; /* FIXME */
 	rep.srq = 1;
 	rep.qp_num = qp->qp_num;
 	rep.starting_psn = psn;
@@ -237,6 +301,11 @@
 		return -ENOMEM;
 	p->dev = dev;
 	p->id = cm_id;
+	cm_id->context = p;
+	p->state = IPOIB_CM_RX_LIVE;
+	p->jiffies = jiffies;
+	INIT_LIST_HEAD(&p->list);
+
 	p->qp = ipoib_cm_create_rx_qp(dev, p);
 	if (IS_ERR(p->qp)) {
 		ret = PTR_ERR(p->qp);
@@ -248,23 +317,24 @@
 	if (ret)
 		goto err_modify;
 
+	spin_lock_irq(&priv->lock);
+	queue_delayed_work(ipoib_workqueue,
+			   &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
+	/* Add this entry to passive ids list head, but do not re-add it
+	 * if IB_EVENT_QP_LAST_WQE_REACHED has moved it to flush list. */
+	p->jiffies = jiffies;
+	if (p->state == IPOIB_CM_RX_LIVE)
+		list_move(&p->list, &priv->cm.passive_ids);
+	spin_unlock_irq(&priv->lock);
+
 	ret = ipoib_cm_send_rep(dev, cm_id, p->qp, &event->param.req_rcvd, psn);
 	if (ret) {
 		ipoib_warn(priv, "failed to send REP: %d\n", ret);
-		goto err_rep;
+		if (ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE))
+			ipoib_warn(priv, "unable to move qp to error state\n");
 	}
-
-	cm_id->context = p;
-	p->jiffies = jiffies;
-	spin_lock_irq(&priv->lock);
-	if (list_empty(&priv->cm.passive_ids))
-		queue_delayed_work(ipoib_workqueue,
-				   &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
-	list_add(&p->list, &priv->cm.passive_ids);
-	spin_unlock_irq(&priv->lock);
 	return 0;
 
-err_rep:
 err_modify:
 	ib_destroy_qp(p->qp);
 err_qp:
@@ -277,7 +347,6 @@
 {
 	struct ipoib_cm_rx *p;
 	struct ipoib_dev_priv *priv;
-	int ret;
 
 	switch (event->event) {
 	case IB_CM_REQ_RECEIVED:
@@ -289,20 +358,9 @@
 	case IB_CM_REJ_RECEIVED:
 		p = cm_id->context;
 		priv = netdev_priv(p->dev);
-		spin_lock_irq(&priv->lock);
-		if (list_empty(&p->list))
-			ret = 0; /* Connection is going away already. */
-		else {
-			list_del_init(&p->list);
-			ret = -ECONNRESET;
-		}
-		spin_unlock_irq(&priv->lock);
-		if (ret) {
-			ib_destroy_qp(p->qp);
-			kfree(p);
-			return ret;
-		}
-		return 0;
+		if (ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE))
+			ipoib_warn(priv, "unable to move qp to error state\n");
+		/* Fall through */
 	default:
 		return 0;
 	}
@@ -354,8 +412,15 @@
 		       wr_id, wc->status);
 
 	if (unlikely(wr_id >= ipoib_recvq_size)) {
-		ipoib_warn(priv, "cm recv completion event with wrid %d (> %d)\n",
-			   wr_id, ipoib_recvq_size);
+		if (wr_id == (IPOIB_CM_RX_DRAIN_WRID & ~IPOIB_CM_OP_SRQ)) {
+			spin_lock_irqsave(&priv->lock, flags);
+			list_splice_init(&priv->cm.rx_drain_list, &priv->cm.rx_reap_list);
+			ipoib_cm_start_rx_drain(priv);
+			queue_work(ipoib_workqueue, &priv->cm.rx_reap_task);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		} else
+			ipoib_warn(priv, "cm recv completion event with wrid %d (> %d)\n",
+				   wr_id, ipoib_recvq_size);
 		return;
 	}
 
@@ -374,9 +439,9 @@
 		if (p && time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
 			spin_lock_irqsave(&priv->lock, flags);
 			p->jiffies = jiffies;
-			/* Move this entry to list head, but do
-			 * not re-add it if it has been removed. */
-			if (!list_empty(&p->list))
+			/* Move this entry to list head, but do not re-add it
+			 * if it has been moved out of list. */
+			if (p->state == IPOIB_CM_RX_LIVE)
 				list_move(&p->list, &priv->cm.passive_ids);
 			spin_unlock_irqrestore(&priv->lock, flags);
 		}
@@ -592,8 +657,7 @@
 	if (IS_ERR(priv->cm.id)) {
 		printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
 		ret = PTR_ERR(priv->cm.id);
-		priv->cm.id = NULL;
-		return ret;
+		goto err_cm;
 	}
 
 	ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num),
@@ -601,34 +665,76 @@
 	if (ret) {
 		printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name,
 		       IPOIB_CM_IETF_ID | priv->qp->qp_num);
-		ib_destroy_cm_id(priv->cm.id);
-		priv->cm.id = NULL;
-		return ret;
+		goto err_listen;
 	}
+
 	return 0;
+
+err_listen:
+	ib_destroy_cm_id(priv->cm.id);
+err_cm:
+	priv->cm.id = NULL;
+	return ret;
 }
 
 void ipoib_cm_dev_stop(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
-	struct ipoib_cm_rx *p;
+	struct ipoib_cm_rx *p, *n;
+	unsigned long begin;
+	LIST_HEAD(list);
+	int ret;
 
 	if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id)
 		return;
 
 	ib_destroy_cm_id(priv->cm.id);
 	priv->cm.id = NULL;
+
 	spin_lock_irq(&priv->lock);
 	while (!list_empty(&priv->cm.passive_ids)) {
 		p = list_entry(priv->cm.passive_ids.next, typeof(*p), list);
-		list_del_init(&p->list);
+		list_move(&p->list, &priv->cm.rx_error_list);
+		p->state = IPOIB_CM_RX_ERROR;
 		spin_unlock_irq(&priv->lock);
+		ret = ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE);
+		if (ret)
+			ipoib_warn(priv, "unable to move qp to error state: %d\n", ret);
+		spin_lock_irq(&priv->lock);
+	}
+
+	/* Wait for all RX to be drained */
+	begin = jiffies;
+
+	while (!list_empty(&priv->cm.rx_error_list) ||
+	       !list_empty(&priv->cm.rx_flush_list) ||
+	       !list_empty(&priv->cm.rx_drain_list)) {
+		if (time_after(jiffies, begin + 5 * HZ)) {
+			ipoib_warn(priv, "RX drain timing out\n");
+
+			/*
+			 * assume the HW is wedged and just free up everything.
+			 */
+			list_splice_init(&priv->cm.rx_flush_list, &list);
+			list_splice_init(&priv->cm.rx_error_list, &list);
+			list_splice_init(&priv->cm.rx_drain_list, &list);
+			break;
+		}
+		spin_unlock_irq(&priv->lock);
+		msleep(1);
+		ipoib_drain_cq(dev);
+		spin_lock_irq(&priv->lock);
+	}
+
+	list_splice_init(&priv->cm.rx_reap_list, &list);
+
+	spin_unlock_irq(&priv->lock);
+
+	list_for_each_entry_safe(p, n, &list, list) {
 		ib_destroy_cm_id(p->id);
 		ib_destroy_qp(p->qp);
 		kfree(p);
-		spin_lock_irq(&priv->lock);
 	}
-	spin_unlock_irq(&priv->lock);
 
 	cancel_delayed_work(&priv->cm.stale_task);
 }
@@ -645,9 +751,9 @@
 
 	p->mtu = be32_to_cpu(data->mtu);
 
-	if (p->mtu < priv->dev->mtu + IPOIB_ENCAP_LEN) {
-		ipoib_warn(priv, "Rejecting connection: mtu %d < device mtu %d + 4\n",
-			   p->mtu, priv->dev->mtu);
+	if (p->mtu <= IPOIB_ENCAP_LEN) {
+		ipoib_warn(priv, "Rejecting connection: mtu %d <= %d\n",
+			   p->mtu, IPOIB_ENCAP_LEN);
 		return -EINVAL;
 	}
 
@@ -1041,7 +1147,6 @@
 {
 	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
 						   cm.skb_task);
-	struct net_device *dev = priv->dev;
 	struct sk_buff *skb;
 
 	unsigned mtu = priv->mcast_mtu;
@@ -1055,7 +1160,7 @@
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 		else if (skb->protocol == htons(ETH_P_IPV6))
-			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
+			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev);
 #endif
 		dev_kfree_skb_any(skb);
 		spin_lock_irq(&priv->tx_lock);
@@ -1079,24 +1184,44 @@
 		queue_work(ipoib_workqueue, &priv->cm.skb_task);
 }
 
+static void ipoib_cm_rx_reap(struct work_struct *work)
+{
+	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
+						   cm.rx_reap_task);
+	struct ipoib_cm_rx *p, *n;
+	LIST_HEAD(list);
+
+	spin_lock_irq(&priv->lock);
+	list_splice_init(&priv->cm.rx_reap_list, &list);
+	spin_unlock_irq(&priv->lock);
+
+	list_for_each_entry_safe(p, n, &list, list) {
+		ib_destroy_cm_id(p->id);
+		ib_destroy_qp(p->qp);
+		kfree(p);
+	}
+}
+
 static void ipoib_cm_stale_task(struct work_struct *work)
 {
 	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
 						   cm.stale_task.work);
 	struct ipoib_cm_rx *p;
+	int ret;
 
 	spin_lock_irq(&priv->lock);
 	while (!list_empty(&priv->cm.passive_ids)) {
-		/* List if sorted by LRU, start from tail,
+		/* List is sorted by LRU, start from tail,
 		 * stop when we see a recently used entry */
 		p = list_entry(priv->cm.passive_ids.prev, typeof(*p), list);
 		if (time_before_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT))
 			break;
-		list_del_init(&p->list);
+		list_move(&p->list, &priv->cm.rx_error_list);
+		p->state = IPOIB_CM_RX_ERROR;
 		spin_unlock_irq(&priv->lock);
-		ib_destroy_cm_id(p->id);
-		ib_destroy_qp(p->qp);
-		kfree(p);
+		ret = ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE);
+		if (ret)
+			ipoib_warn(priv, "unable to move qp to error state: %d\n", ret);
 		spin_lock_irq(&priv->lock);
 	}
 
@@ -1164,9 +1289,14 @@
 	INIT_LIST_HEAD(&priv->cm.passive_ids);
 	INIT_LIST_HEAD(&priv->cm.reap_list);
 	INIT_LIST_HEAD(&priv->cm.start_list);
+	INIT_LIST_HEAD(&priv->cm.rx_error_list);
+	INIT_LIST_HEAD(&priv->cm.rx_flush_list);
+	INIT_LIST_HEAD(&priv->cm.rx_drain_list);
+	INIT_LIST_HEAD(&priv->cm.rx_reap_list);
 	INIT_WORK(&priv->cm.start_task, ipoib_cm_tx_start);
 	INIT_WORK(&priv->cm.reap_task, ipoib_cm_tx_reap);
 	INIT_WORK(&priv->cm.skb_task, ipoib_cm_skb_reap);
+	INIT_WORK(&priv->cm.rx_reap_task, ipoib_cm_rx_reap);
 	INIT_DELAYED_WORK(&priv->cm.stale_task, ipoib_cm_stale_task);
 
 	skb_queue_head_init(&priv->cm.skb_queue);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 68d72c6..1094488 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -197,6 +197,13 @@
 	}
 
 	/*
+	 * Drop packets that this interface sent, ie multicast packets
+	 * that the HCA has replicated.
+	 */
+	if (wc->slid == priv->local_lid && wc->src_qp == priv->qp->qp_num)
+		goto repost;
+
+	/*
 	 * If we can't allocate a new RX buffer, dump
 	 * this packet and reuse the old buffer.
 	 */
@@ -213,24 +220,18 @@
 	skb_put(skb, wc->byte_len);
 	skb_pull(skb, IB_GRH_BYTES);
 
-	if (wc->slid != priv->local_lid ||
-	    wc->src_qp != priv->qp->qp_num) {
-		skb->protocol = ((struct ipoib_header *) skb->data)->proto;
-		skb_reset_mac_header(skb);
-		skb_pull(skb, IPOIB_ENCAP_LEN);
+	skb->protocol = ((struct ipoib_header *) skb->data)->proto;
+	skb_reset_mac_header(skb);
+	skb_pull(skb, IPOIB_ENCAP_LEN);
 
-		dev->last_rx = jiffies;
-		++priv->stats.rx_packets;
-		priv->stats.rx_bytes += skb->len;
+	dev->last_rx = jiffies;
+	++priv->stats.rx_packets;
+	priv->stats.rx_bytes += skb->len;
 
-		skb->dev = dev;
-		/* XXX get correct PACKET_ type here */
-		skb->pkt_type = PACKET_HOST;
-		netif_receive_skb(skb);
-	} else {
-		ipoib_dbg_data(priv, "dropping loopback packet\n");
-		dev_kfree_skb_any(skb);
-	}
+	skb->dev = dev;
+	/* XXX get correct PACKET_ type here */
+	skb->pkt_type = PACKET_HOST;
+	netif_receive_skb(skb);
 
 repost:
 	if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
@@ -448,6 +449,13 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	int ret;
 
+	if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &priv->pkey_index)) {
+		ipoib_warn(priv, "P_Key 0x%04x not found\n", priv->pkey);
+		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+		return -1;
+	}
+	set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+
 	ret = ipoib_init_qp(dev);
 	if (ret) {
 		ipoib_warn(priv, "ipoib_init_qp returned %d\n", ret);
@@ -457,14 +465,14 @@
 	ret = ipoib_ib_post_receives(dev);
 	if (ret) {
 		ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret);
-		ipoib_ib_dev_stop(dev);
+		ipoib_ib_dev_stop(dev, 1);
 		return -1;
 	}
 
 	ret = ipoib_cm_dev_open(dev);
 	if (ret) {
-		ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret);
-		ipoib_ib_dev_stop(dev);
+		ipoib_warn(priv, "ipoib_cm_dev_open returned %d\n", ret);
+		ipoib_ib_dev_stop(dev, 1);
 		return -1;
 	}
 
@@ -516,7 +524,7 @@
 	if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
 		mutex_lock(&pkey_mutex);
 		set_bit(IPOIB_PKEY_STOP, &priv->flags);
-		cancel_delayed_work(&priv->pkey_task);
+		cancel_delayed_work(&priv->pkey_poll_task);
 		mutex_unlock(&pkey_mutex);
 		if (flush)
 			flush_workqueue(ipoib_workqueue);
@@ -543,13 +551,30 @@
 	return pending;
 }
 
-int ipoib_ib_dev_stop(struct net_device *dev)
+void ipoib_drain_cq(struct net_device *dev)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	int i, n;
+	do {
+		n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
+		for (i = 0; i < n; ++i) {
+			if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
+				ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
+			else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
+				ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
+			else
+				ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
+		}
+	} while (n == IPOIB_NUM_WC);
+}
+
+int ipoib_ib_dev_stop(struct net_device *dev, int flush)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ib_qp_attr qp_attr;
 	unsigned long begin;
 	struct ipoib_tx_buf *tx_req;
-	int i, n;
+	int i;
 
 	clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
 	netif_poll_disable(dev);
@@ -604,17 +629,7 @@
 			goto timeout;
 		}
 
-		do {
-			n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
-			for (i = 0; i < n; ++i) {
-				if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
-					ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
-				else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
-					ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
-				else
-					ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
-			}
-		} while (n == IPOIB_NUM_WC);
+		ipoib_drain_cq(dev);
 
 		msleep(1);
 	}
@@ -629,7 +644,8 @@
 	/* Wait for all AHs to be reaped */
 	set_bit(IPOIB_STOP_REAPER, &priv->flags);
 	cancel_delayed_work(&priv->ah_reap_task);
-	flush_workqueue(ipoib_workqueue);
+	if (flush)
+		flush_workqueue(ipoib_workqueue);
 
 	begin = jiffies;
 
@@ -673,13 +689,24 @@
 	return 0;
 }
 
-void ipoib_ib_dev_flush(struct work_struct *work)
+static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
 {
-	struct ipoib_dev_priv *cpriv, *priv =
-		container_of(work, struct ipoib_dev_priv, flush_task);
+	struct ipoib_dev_priv *cpriv;
 	struct net_device *dev = priv->dev;
+	u16 new_index;
 
-	if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) {
+	mutex_lock(&priv->vlan_mutex);
+
+	/*
+	 * Flush any child interfaces too -- they might be up even if
+	 * the parent is down.
+	 */
+	list_for_each_entry(cpriv, &priv->child_intfs, list)
+		__ipoib_ib_dev_flush(cpriv, pkey_event);
+
+	mutex_unlock(&priv->vlan_mutex);
+
+	if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) {
 		ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
 		return;
 	}
@@ -689,10 +716,32 @@
 		return;
 	}
 
+	if (pkey_event) {
+		if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) {
+			clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+			ipoib_ib_dev_down(dev, 0);
+			ipoib_pkey_dev_delay_open(dev);
+			return;
+		}
+		set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+
+		/* restart QP only if P_Key index is changed */
+		if (new_index == priv->pkey_index) {
+			ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
+			return;
+		}
+		priv->pkey_index = new_index;
+	}
+
 	ipoib_dbg(priv, "flushing\n");
 
 	ipoib_ib_dev_down(dev, 0);
 
+	if (pkey_event) {
+		ipoib_ib_dev_stop(dev, 0);
+		ipoib_ib_dev_open(dev);
+	}
+
 	/*
 	 * The device could have been brought down between the start and when
 	 * we get here, don't bring it back up if it's not configured up
@@ -701,14 +750,24 @@
 		ipoib_ib_dev_up(dev);
 		ipoib_mcast_restart_task(&priv->restart_task);
 	}
+}
 
-	mutex_lock(&priv->vlan_mutex);
+void ipoib_ib_dev_flush(struct work_struct *work)
+{
+	struct ipoib_dev_priv *priv =
+		container_of(work, struct ipoib_dev_priv, flush_task);
 
-	/* Flush any child interfaces too */
-	list_for_each_entry(cpriv, &priv->child_intfs, list)
-		ipoib_ib_dev_flush(&cpriv->flush_task);
+	ipoib_dbg(priv, "Flushing %s\n", priv->dev->name);
+	__ipoib_ib_dev_flush(priv, 0);
+}
 
-	mutex_unlock(&priv->vlan_mutex);
+void ipoib_pkey_event(struct work_struct *work)
+{
+	struct ipoib_dev_priv *priv =
+		container_of(work, struct ipoib_dev_priv, pkey_event_task);
+
+	ipoib_dbg(priv, "Flushing %s and restarting its QP\n", priv->dev->name);
+	__ipoib_ib_dev_flush(priv, 1);
 }
 
 void ipoib_ib_dev_cleanup(struct net_device *dev)
@@ -736,7 +795,7 @@
 void ipoib_pkey_poll(struct work_struct *work)
 {
 	struct ipoib_dev_priv *priv =
-		container_of(work, struct ipoib_dev_priv, pkey_task.work);
+		container_of(work, struct ipoib_dev_priv, pkey_poll_task.work);
 	struct net_device *dev = priv->dev;
 
 	ipoib_pkey_dev_check_presence(dev);
@@ -747,7 +806,7 @@
 		mutex_lock(&pkey_mutex);
 		if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))
 			queue_delayed_work(ipoib_workqueue,
-					   &priv->pkey_task,
+					   &priv->pkey_poll_task,
 					   HZ);
 		mutex_unlock(&pkey_mutex);
 	}
@@ -766,7 +825,7 @@
 		mutex_lock(&pkey_mutex);
 		clear_bit(IPOIB_PKEY_STOP, &priv->flags);
 		queue_delayed_work(ipoib_workqueue,
-				   &priv->pkey_task,
+				   &priv->pkey_poll_task,
 				   HZ);
 		mutex_unlock(&pkey_mutex);
 		return 1;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 0a428f2..894b1dcd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -107,7 +107,7 @@
 		return -EINVAL;
 
 	if (ipoib_ib_dev_up(dev)) {
-		ipoib_ib_dev_stop(dev);
+		ipoib_ib_dev_stop(dev, 1);
 		return -EINVAL;
 	}
 
@@ -152,7 +152,7 @@
 	flush_workqueue(ipoib_workqueue);
 
 	ipoib_ib_dev_down(dev, 1);
-	ipoib_ib_dev_stop(dev);
+	ipoib_ib_dev_stop(dev, 1);
 
 	if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
 		struct ipoib_dev_priv *cpriv;
@@ -988,7 +988,8 @@
 	INIT_LIST_HEAD(&priv->dead_ahs);
 	INIT_LIST_HEAD(&priv->multicast_list);
 
-	INIT_DELAYED_WORK(&priv->pkey_task,    ipoib_pkey_poll);
+	INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
+	INIT_WORK(&priv->pkey_event_task, ipoib_pkey_event);
 	INIT_DELAYED_WORK(&priv->mcast_task,   ipoib_mcast_join_task);
 	INIT_WORK(&priv->flush_task,   ipoib_ib_dev_flush);
 	INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 54fbead..aae3670 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -524,7 +524,7 @@
 		return;
 
 	if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid))
-		ipoib_warn(priv, "ib_gid_entry_get() failed\n");
+		ipoib_warn(priv, "ib_query_gid() failed\n");
 	else
 		memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 5c3c6a4..982eb88 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -33,8 +33,6 @@
  * $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $
  */
 
-#include <rdma/ib_cache.h>
-
 #include "ipoib.h"
 
 int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
@@ -49,7 +47,7 @@
 	if (!qp_attr)
 		goto out;
 
-	if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
+	if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
 		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
 		ret = -ENXIO;
 		goto out;
@@ -94,26 +92,16 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	int ret;
-	u16 pkey_index;
 	struct ib_qp_attr qp_attr;
 	int attr_mask;
 
-	/*
-	 * Search through the port P_Key table for the requested pkey value.
-	 * The port has to be assigned to the respective IB partition in
-	 * advance.
-	 */
-	ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index);
-	if (ret) {
-		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
-		return ret;
-	}
-	set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+	if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
+		return -1;
 
 	qp_attr.qp_state = IB_QPS_INIT;
 	qp_attr.qkey = 0;
 	qp_attr.port_num = priv->port;
-	qp_attr.pkey_index = pkey_index;
+	qp_attr.pkey_index = priv->pkey_index;
 	attr_mask =
 	    IB_QP_QKEY |
 	    IB_QP_PORT |
@@ -185,7 +173,7 @@
 	size = ipoib_sendq_size + ipoib_recvq_size + 1;
 	ret = ipoib_cm_dev_init(dev);
 	if (!ret)
-		size += ipoib_recvq_size;
+		size += ipoib_recvq_size + 1 /* 1 extra for rx_drain_qp */;
 
 	priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
 	if (IS_ERR(priv->cq)) {
@@ -259,14 +247,18 @@
 	struct ipoib_dev_priv *priv =
 		container_of(handler, struct ipoib_dev_priv, event_handler);
 
-	if ((record->event == IB_EVENT_PORT_ERR    ||
-	     record->event == IB_EVENT_PKEY_CHANGE ||
-	     record->event == IB_EVENT_PORT_ACTIVE ||
-	     record->event == IB_EVENT_LID_CHANGE  ||
-	     record->event == IB_EVENT_SM_CHANGE   ||
-	     record->event == IB_EVENT_CLIENT_REREGISTER) &&
-	    record->element.port_num == priv->port) {
+	if (record->element.port_num != priv->port)
+		return;
+
+	if (record->event == IB_EVENT_PORT_ERR    ||
+	    record->event == IB_EVENT_PORT_ACTIVE ||
+	    record->event == IB_EVENT_LID_CHANGE  ||
+	    record->event == IB_EVENT_SM_CHANGE   ||
+	    record->event == IB_EVENT_CLIENT_REREGISTER) {
 		ipoib_dbg(priv, "Port state change event\n");
 		queue_work(ipoib_workqueue, &priv->flush_task);
+	} else if (record->event == IB_EVENT_PKEY_CHANGE) {
+		ipoib_dbg(priv, "P_Key change event on port:%d\n", priv->port);
+		queue_work(ipoib_workqueue, &priv->pkey_event_task);
 	}
 }
diff --git a/drivers/infiniband/ulp/iser/Kconfig b/drivers/infiniband/ulp/iser/Kconfig
index aecbb90..fe604c8 100644
--- a/drivers/infiniband/ulp/iser/Kconfig
+++ b/drivers/infiniband/ulp/iser/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_ISER
 	tristate "iSCSI Extensions for RDMA (iSER)"
-	depends on INFINIBAND && SCSI && INET
+	depends on SCSI && INET
 	select SCSI_ISCSI_ATTRS
 	---help---
 	  Support for the iSCSI Extensions for RDMA (iSER) Protocol
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index dd221ed..effdee2 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -134,19 +134,9 @@
 {
 	struct iscsi_iser_conn     *iser_conn  = ctask->conn->dd_data;
 	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
-	struct scsi_cmnd  *sc = ctask->sc;
 
 	iser_ctask->command_sent = 0;
 	iser_ctask->iser_conn    = iser_conn;
-
-	if (sc->sc_data_direction == DMA_TO_DEVICE) {
-		BUG_ON(ctask->total_length == 0);
-
-		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
-			   ctask->itt, ctask->total_length, ctask->imm_count,
-			   ctask->unsol_count);
-	}
-
 	iser_ctask_rdma_init(iser_ctask);
 }
 
@@ -219,6 +209,14 @@
 	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
 	int error = 0;
 
+	if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
+		BUG_ON(scsi_bufflen(ctask->sc) == 0);
+
+		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
+			   ctask->itt, scsi_bufflen(ctask->sc),
+			   ctask->imm_count, ctask->unsol_count);
+	}
+
 	debug_scsi("ctask deq [cid %d itt 0x%x]\n",
 		   conn->id, ctask->itt);
 
@@ -375,7 +373,8 @@
 static struct iscsi_cls_session *
 iscsi_iser_session_create(struct iscsi_transport *iscsit,
 			 struct scsi_transport_template *scsit,
-			  uint32_t initial_cmdsn, uint32_t *hostno)
+			 uint16_t cmds_max, uint16_t qdepth,
+			 uint32_t initial_cmdsn, uint32_t *hostno)
 {
 	struct iscsi_cls_session *cls_session;
 	struct iscsi_session *session;
@@ -386,7 +385,13 @@
 	struct iscsi_iser_cmd_task *iser_ctask;
 	struct iser_desc *desc;
 
+	/*
+	 * we do not support setting can_queue cmd_per_lun from userspace yet
+	 * because we preallocate so many resources
+	 */
 	cls_session = iscsi_session_setup(iscsit, scsit,
+					  ISCSI_DEF_XMIT_CMDS_MAX,
+					  ISCSI_MAX_CMD_PER_LUN,
 					  sizeof(struct iscsi_iser_cmd_task),
 					  sizeof(struct iser_desc),
 					  initial_cmdsn, &hn);
@@ -545,7 +550,7 @@
 static struct scsi_host_template iscsi_iser_sht = {
 	.name                   = "iSCSI Initiator over iSER, v." DRV_VER,
 	.queuecommand           = iscsi_queuecommand,
-	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,
 	.sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
 	.max_sectors		= 1024,
 	.cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
@@ -574,8 +579,12 @@
 				  ISCSI_EXP_STATSN |
 				  ISCSI_PERSISTENT_PORT |
 				  ISCSI_PERSISTENT_ADDRESS |
-				  ISCSI_TARGET_NAME |
-				  ISCSI_TPGT,
+				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+				  ISCSI_USERNAME | ISCSI_PASSWORD |
+				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+				  ISCSI_HOST_NETDEV_NAME |
+				  ISCSI_HOST_INITIATOR_NAME,
 	.host_template          = &iscsi_iser_sht,
 	.conndata_size		= sizeof(struct iscsi_conn),
 	.max_lun                = ISCSI_ISER_MAX_LUN,
@@ -592,6 +601,9 @@
 	.get_session_param	= iscsi_session_get_param,
 	.start_conn             = iscsi_iser_conn_start,
 	.stop_conn              = iscsi_conn_stop,
+	/* iscsi host params */
+	.get_host_param		= iscsi_host_get_param,
+	.set_host_param		= iscsi_host_set_param,
 	/* IO */
 	.send_pdu		= iscsi_conn_send_pdu,
 	.get_stats		= iscsi_iser_conn_get_stats,
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 8960196..e235370 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -98,7 +98,7 @@
 #define ISER_MAX_TX_MISC_PDUS		6 /* NOOP_OUT(2), TEXT(1),         *
 					   * SCSI_TMFUNC(2), LOGOUT(1) */
 
-#define ISER_QP_MAX_RECV_DTOS		(ISCSI_XMIT_CMDS_MAX + \
+#define ISER_QP_MAX_RECV_DTOS		(ISCSI_DEF_XMIT_CMDS_MAX + \
 					ISER_MAX_RX_MISC_PDUS    +  \
 					ISER_MAX_TX_MISC_PDUS)
 
@@ -110,7 +110,7 @@
 
 #define ISER_INFLIGHT_DATAOUTS		8
 
-#define ISER_QP_MAX_REQ_DTOS		(ISCSI_XMIT_CMDS_MAX *    \
+#define ISER_QP_MAX_REQ_DTOS		(ISCSI_DEF_XMIT_CMDS_MAX *    \
 					(1 + ISER_INFLIGHT_DATAOUTS) + \
 					ISER_MAX_TX_MISC_PDUS        + \
 					ISER_MAX_RX_MISC_PDUS)
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 3651072..9ea5b9a 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -351,18 +351,12 @@
 	else
 		data_buf = &iser_ctask->data[ISER_DIR_OUT];
 
-	if (sc->use_sg) { /* using a scatter list */
-		data_buf->buf  = sc->request_buffer;
-		data_buf->size = sc->use_sg;
-	} else if (sc->request_bufflen) {
-		/* using a single buffer - convert it into one entry SG */
-		sg_init_one(&data_buf->sg_single,
-			    sc->request_buffer, sc->request_bufflen);
-		data_buf->buf   = &data_buf->sg_single;
-		data_buf->size  = 1;
+	if (scsi_sg_count(sc)) { /* using a scatter list */
+		data_buf->buf  = scsi_sglist(sc);
+		data_buf->size = scsi_sg_count(sc);
 	}
 
-	data_buf->data_len = sc->request_bufflen;
+	data_buf->data_len = scsi_bufflen(sc);
 
 	if (hdr->flags & ISCSI_FLAG_CMD_READ) {
 		err = iser_prepare_read_cmd(ctask, edtl);
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 3702e23..2044de1 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -155,8 +155,8 @@
 	params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1;
 	/* make the pool size twice the max number of SCSI commands *
 	 * the ML is expected to queue, watermark for unmap at 50%  */
-	params.pool_size	 = ISCSI_XMIT_CMDS_MAX * 2;
-	params.dirty_watermark	 = ISCSI_XMIT_CMDS_MAX;
+	params.pool_size	 = ISCSI_DEF_XMIT_CMDS_MAX * 2;
+	params.dirty_watermark	 = ISCSI_DEF_XMIT_CMDS_MAX;
 	params.cache		 = 0;
 	params.flush_function	 = NULL;
 	params.access		 = (IB_ACCESS_LOCAL_WRITE  |
diff --git a/drivers/infiniband/ulp/srp/Kconfig b/drivers/infiniband/ulp/srp/Kconfig
index 8fe3be4..3432dce 100644
--- a/drivers/infiniband/ulp/srp/Kconfig
+++ b/drivers/infiniband/ulp/srp/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_SRP
 	tristate "InfiniBand SCSI RDMA Protocol"
-	depends on INFINIBAND && SCSI
+	depends on SCSI
 	---help---
 	  Support for the SCSI RDMA Protocol over InfiniBand.  This
 	  allows you to access storage devices that speak SRP over
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 39bf057..f01ca18 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -455,10 +455,7 @@
 			   struct srp_target_port *target,
 			   struct srp_request *req)
 {
-	struct scatterlist *scat;
-	int nents;
-
-	if (!scmnd->request_buffer ||
+	if (!scsi_sglist(scmnd) ||
 	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
 	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
 		return;
@@ -468,20 +465,8 @@
 		req->fmr = NULL;
 	}
 
-	/*
-	 * This handling of non-SG commands can be killed when the
-	 * SCSI midlayer no longer generates non-SG commands.
-	 */
-	if (likely(scmnd->use_sg)) {
-		nents = scmnd->use_sg;
-		scat  = scmnd->request_buffer;
-	} else {
-		nents = 1;
-		scat  = &req->fake_sg;
-	}
-
-	ib_dma_unmap_sg(target->srp_host->dev->dev, scat, nents,
-			scmnd->sc_data_direction);
+	ib_dma_unmap_sg(target->srp_host->dev->dev, scsi_sglist(scmnd),
+			scsi_sg_count(scmnd), scmnd->sc_data_direction);
 }
 
 static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
@@ -595,6 +580,7 @@
 	int ret;
 	struct srp_device *dev = target->srp_host->dev;
 	struct ib_device *ibdev = dev->dev;
+	struct scatterlist *sg;
 
 	if (!dev->fmr_pool)
 		return -ENODEV;
@@ -604,16 +590,16 @@
 		return -EINVAL;
 
 	len = page_cnt = 0;
-	for (i = 0; i < sg_cnt; ++i) {
-		unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
+	scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
+		unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
 
-		if (ib_sg_dma_address(ibdev, &scat[i]) & ~dev->fmr_page_mask) {
+		if (ib_sg_dma_address(ibdev, sg) & ~dev->fmr_page_mask) {
 			if (i > 0)
 				return -EINVAL;
 			else
 				++page_cnt;
 		}
-		if ((ib_sg_dma_address(ibdev, &scat[i]) + dma_len) &
+		if ((ib_sg_dma_address(ibdev, sg) + dma_len) &
 		    ~dev->fmr_page_mask) {
 			if (i < sg_cnt - 1)
 				return -EINVAL;
@@ -633,12 +619,12 @@
 		return -ENOMEM;
 
 	page_cnt = 0;
-	for (i = 0; i < sg_cnt; ++i) {
-		unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
+	scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
+		unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
 
 		for (j = 0; j < dma_len; j += dev->fmr_page_size)
 			dma_pages[page_cnt++] =
-				(ib_sg_dma_address(ibdev, &scat[i]) &
+				(ib_sg_dma_address(ibdev, sg) &
 				 dev->fmr_page_mask) + j;
 	}
 
@@ -673,7 +659,7 @@
 	struct srp_device *dev;
 	struct ib_device *ibdev;
 
-	if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
+	if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
 		return sizeof (struct srp_cmd);
 
 	if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
@@ -683,18 +669,8 @@
 		return -EINVAL;
 	}
 
-	/*
-	 * This handling of non-SG commands can be killed when the
-	 * SCSI midlayer no longer generates non-SG commands.
-	 */
-	if (likely(scmnd->use_sg)) {
-		nents = scmnd->use_sg;
-		scat  = scmnd->request_buffer;
-	} else {
-		nents = 1;
-		scat  = &req->fake_sg;
-		sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
-	}
+	nents = scsi_sg_count(scmnd);
+	scat  = scsi_sglist(scmnd);
 
 	dev = target->srp_host->dev;
 	ibdev = dev->dev;
@@ -724,6 +700,7 @@
 		 * descriptor.
 		 */
 		struct srp_indirect_buf *buf = (void *) cmd->add_data;
+		struct scatterlist *sg;
 		u32 datalen = 0;
 		int i;
 
@@ -732,11 +709,11 @@
 			sizeof (struct srp_indirect_buf) +
 			count * sizeof (struct srp_direct_buf);
 
-		for (i = 0; i < count; ++i) {
-			unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
+		scsi_for_each_sg(scmnd, sg, count, i) {
+			unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
 
 			buf->desc_list[i].va  =
-				cpu_to_be64(ib_sg_dma_address(ibdev, &scat[i]));
+				cpu_to_be64(ib_sg_dma_address(ibdev, sg));
 			buf->desc_list[i].key =
 				cpu_to_be32(dev->mr->rkey);
 			buf->desc_list[i].len = cpu_to_be32(dma_len);
@@ -802,9 +779,9 @@
 		}
 
 		if (rsp->flags & (SRP_RSP_FLAG_DOOVER | SRP_RSP_FLAG_DOUNDER))
-			scmnd->resid = be32_to_cpu(rsp->data_out_res_cnt);
+			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
 		else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
-			scmnd->resid = be32_to_cpu(rsp->data_in_res_cnt);
+			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
 
 		if (!req->tsk_mgmt) {
 			scmnd->host_scribble = (void *) -1L;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 1d53c7b..e3573e7 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -106,11 +106,6 @@
 	struct srp_iu	       *cmd;
 	struct srp_iu	       *tsk_mgmt;
 	struct ib_pool_fmr     *fmr;
-	/*
-	 * Fake scatterlist used when scmnd->use_sg==0.  Can be killed
-	 * when the SCSI midlayer no longer generates non-SG commands.
-	 */
-	struct scatterlist	fake_sg;
 	struct completion	done;
 	short			index;
 	u8			cmd_done;
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index f814fb3..2d87357 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -39,6 +39,19 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ff-memless.
 
+config INPUT_POLLDEV
+	tristate "Polled input device skeleton"
+	help
+	  Say Y here if you are using a driver for an input
+	  device that periodically polls hardware state. This
+	  option is only useful for out-of-tree drivers since
+	  in-tree drivers select it automatically.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called input-polldev.
+
 comment "Userland interfaces"
 
 config INPUT_MOUSEDEV
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 8a2dd98..15eb752 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -8,6 +8,7 @@
 input-core-objs := input.o ff-core.o
 
 obj-$(CONFIG_INPUT_FF_MEMLESS)	+= ff-memless.o
+obj-$(CONFIG_INPUT_POLLDEV)	+= input-polldev.o
 
 obj-$(CONFIG_INPUT_MOUSEDEV)	+= mousedev.o
 obj-$(CONFIG_INPUT_JOYDEV)	+= joydev.o
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b234729..ab4b2d9 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -30,6 +30,7 @@
 	wait_queue_head_t wait;
 	struct evdev_client *grab;
 	struct list_head client_list;
+	struct device dev;
 };
 
 struct evdev_client {
@@ -94,8 +95,10 @@
 	return input_flush_device(&evdev->handle, file);
 }
 
-static void evdev_free(struct evdev *evdev)
+static void evdev_free(struct device *dev)
 {
+	struct evdev *evdev = container_of(dev, struct evdev, dev);
+
 	evdev_table[evdev->minor] = NULL;
 	kfree(evdev);
 }
@@ -114,12 +117,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--evdev->open) {
-		if (evdev->exist)
-			input_close_device(&evdev->handle);
-		else
-			evdev_free(evdev);
-	}
+	if (!--evdev->open && evdev->exist)
+		input_close_device(&evdev->handle);
+
+	put_device(&evdev->dev);
 
 	return 0;
 }
@@ -139,24 +140,32 @@
 	if (!evdev || !evdev->exist)
 		return -ENODEV;
 
+	get_device(&evdev->dev);
+
 	client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_evdev;
+	}
 
 	client->evdev = evdev;
 	list_add_tail(&client->node, &evdev->client_list);
 
 	if (!evdev->open++ && evdev->exist) {
 		error = input_open_device(&evdev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_evdev:
+	put_device(&evdev->dev);
+	return error;
 }
 
 #ifdef CONFIG_COMPAT
@@ -625,8 +634,6 @@
 			 const struct input_device_id *id)
 {
 	struct evdev *evdev;
-	struct class_device *cdev;
-	dev_t devt;
 	int minor;
 	int error;
 
@@ -649,38 +656,32 @@
 	evdev->handle.name = evdev->name;
 	evdev->handle.handler = handler;
 	evdev->handle.private = evdev;
-	sprintf(evdev->name, "event%d", minor);
+	snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
+
+	snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
+		 "event%d", minor);
+	evdev->dev.class = &input_class;
+	evdev->dev.parent = &dev->dev;
+	evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
+	evdev->dev.release = evdev_free;
+	device_initialize(&evdev->dev);
 
 	evdev_table[minor] = evdev;
 
-	devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-
-	cdev = class_device_create(&input_class, &dev->cdev, devt,
-				   dev->cdev.dev, evdev->name);
-	if (IS_ERR(cdev)) {
-		error = PTR_ERR(cdev);
-		goto err_free_evdev;
-	}
-
-	/* temporary symlink to keep userspace happy */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, evdev->name);
+	error = device_add(&evdev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_evdev;
 
 	error = input_register_handle(&evdev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_evdev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_evdev:
+	device_del(&evdev->dev);
  err_free_evdev:
-	kfree(evdev);
-	evdev_table[minor] = NULL;
+	put_device(&evdev->dev);
 	return error;
 }
 
@@ -690,20 +691,19 @@
 	struct evdev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&evdev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	evdev->exist = 0;
 
 	if (evdev->open) {
 		input_flush_device(handle, NULL);
 		input_close_device(handle);
-		wake_up_interruptible(&evdev->wait);
 		list_for_each_entry(client, &evdev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
-	} else
-		evdev_free(evdev);
+		wake_up_interruptible(&evdev->wait);
+	}
+
+	put_device(&evdev->dev);
 }
 
 static const struct input_device_id evdev_ids[] = {
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index bd686a2..20896d5 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -445,6 +445,7 @@
 
 static int gameport_thread(void *nothing)
 {
+	set_freezable();
 	do {
 		gameport_handle_event();
 		wait_event_interruptible(gameport_wait,
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
new file mode 100644
index 0000000..b773d4c
--- /dev/null
+++ b/drivers/input/input-polldev.c
@@ -0,0 +1,176 @@
+/*
+ * Generic implementation of a polled input device
+
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * 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/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/input-polldev.h>
+
+MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
+MODULE_DESCRIPTION("Generic implementation of a polled input device");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+
+static DEFINE_MUTEX(polldev_mutex);
+static int polldev_users;
+static struct workqueue_struct *polldev_wq;
+
+static int input_polldev_start_workqueue(void)
+{
+	int retval;
+
+	retval = mutex_lock_interruptible(&polldev_mutex);
+	if (retval)
+		return retval;
+
+	if (!polldev_users) {
+		polldev_wq = create_singlethread_workqueue("ipolldevd");
+		if (!polldev_wq) {
+			printk(KERN_ERR "input-polldev: failed to create "
+				"ipolldevd workqueue\n");
+			retval = -ENOMEM;
+			goto out;
+		}
+	}
+
+	polldev_users++;
+
+ out:
+	mutex_unlock(&polldev_mutex);
+	return retval;
+}
+
+static void input_polldev_stop_workqueue(void)
+{
+	mutex_lock(&polldev_mutex);
+
+	if (!--polldev_users)
+		destroy_workqueue(polldev_wq);
+
+	mutex_unlock(&polldev_mutex);
+}
+
+static void input_polled_device_work(struct work_struct *work)
+{
+	struct input_polled_dev *dev =
+		container_of(work, struct input_polled_dev, work.work);
+
+	dev->poll(dev);
+	queue_delayed_work(polldev_wq, &dev->work,
+			   msecs_to_jiffies(dev->poll_interval));
+}
+
+static int input_open_polled_device(struct input_dev *input)
+{
+	struct input_polled_dev *dev = input->private;
+	int error;
+
+	error = input_polldev_start_workqueue();
+	if (error)
+		return error;
+
+	if (dev->flush)
+		dev->flush(dev);
+
+	queue_delayed_work(polldev_wq, &dev->work,
+			   msecs_to_jiffies(dev->poll_interval));
+
+	return 0;
+}
+
+static void input_close_polled_device(struct input_dev *input)
+{
+	struct input_polled_dev *dev = input->private;
+
+	cancel_rearming_delayed_workqueue(polldev_wq, &dev->work);
+	input_polldev_stop_workqueue();
+}
+
+/**
+ * input_allocate_polled_device - allocated memory polled device
+ *
+ * The function allocates memory for a polled device and also
+ * for an input device associated with this polled device.
+ */
+struct input_polled_dev *input_allocate_polled_device(void)
+{
+	struct input_polled_dev *dev;
+
+	dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->input = input_allocate_device();
+	if (!dev->input) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+EXPORT_SYMBOL(input_allocate_polled_device);
+
+/**
+ * input_free_polled_device - free memory allocated for polled device
+ * @dev: device to free
+ *
+ * The function frees memory allocated for polling device and drops
+ * reference to the associated input device (if present).
+ */
+void input_free_polled_device(struct input_polled_dev *dev)
+{
+	if (dev) {
+		input_free_device(dev->input);
+		kfree(dev);
+	}
+}
+EXPORT_SYMBOL(input_free_polled_device);
+
+/**
+ * input_register_polled_device - register polled device
+ * @dev: device to register
+ *
+ * The function registers previously initialized polled input device
+ * with input layer. The device should be allocated with call to
+ * input_allocate_polled_device(). Callers should also set up poll()
+ * method and set up capabilities (id, name, phys, bits) of the
+ * corresponing input_dev structure.
+ */
+int input_register_polled_device(struct input_polled_dev *dev)
+{
+	struct input_dev *input = dev->input;
+
+	INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
+	if (!dev->poll_interval)
+		dev->poll_interval = 500;
+	input->private = dev;
+	input->open = input_open_polled_device;
+	input->close = input_close_polled_device;
+
+	return input_register_device(input);
+}
+EXPORT_SYMBOL(input_register_polled_device);
+
+/**
+ * input_unregister_polled_device - unregister polled device
+ * @dev: device to unregister
+ *
+ * The function unregisters previously registered polled input
+ * device from input layer. Polling is stopped and device is
+ * ready to be freed with call to input_free_polled_device().
+ * Callers should not attempt to access dev->input pointer
+ * after calling this function.
+ */
+void input_unregister_polled_device(struct input_polled_dev *dev)
+{
+	input_unregister_device(dev->input);
+	dev->input = NULL;
+}
+EXPORT_SYMBOL(input_unregister_polled_device);
+
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccd8aba..75b4d2a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -442,7 +442,7 @@
 		printk(KERN_ERR
 			"input: failed to attach handler %s to device %s, "
 			"error: %d\n",
-			handler->name, kobject_name(&dev->cdev.kobj), error);
+			handler->name, kobject_name(&dev->dev.kobj), error);
 
 	return error;
 }
@@ -527,7 +527,7 @@
 static int input_devices_seq_show(struct seq_file *seq, void *v)
 {
 	struct input_dev *dev = container_of(v, struct input_dev, node);
-	const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+	const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
 	struct input_handle *handle;
 
 	seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
@@ -682,15 +682,17 @@
 static inline void input_proc_exit(void) { }
 #endif
 
-#define INPUT_DEV_STRING_ATTR_SHOW(name)					\
-static ssize_t input_dev_show_##name(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-										\
-	return scnprintf(buf, PAGE_SIZE, "%s\n",				\
-			 input_dev->name ? input_dev->name : "");		\
-}										\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+#define INPUT_DEV_STRING_ATTR_SHOW(name)				\
+static ssize_t input_dev_show_##name(struct device *dev,		\
+				     struct device_attribute *attr,	\
+				     char *buf)				\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+									\
+	return scnprintf(buf, PAGE_SIZE, "%s\n",			\
+			 input_dev->name ? input_dev->name : "");	\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
 
 INPUT_DEV_STRING_ATTR_SHOW(name);
 INPUT_DEV_STRING_ATTR_SHOW(phys);
@@ -744,7 +746,9 @@
 	return len;
 }
 
-static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+static ssize_t input_dev_show_modalias(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
 {
 	struct input_dev *id = to_input_dev(dev);
 	ssize_t len;
@@ -753,13 +757,13 @@
 
 	return min_t(int, len, PAGE_SIZE);
 }
-static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
 
 static struct attribute *input_dev_attrs[] = {
-	&class_device_attr_name.attr,
-	&class_device_attr_phys.attr,
-	&class_device_attr_uniq.attr,
-	&class_device_attr_modalias.attr,
+	&dev_attr_name.attr,
+	&dev_attr_phys.attr,
+	&dev_attr_uniq.attr,
+	&dev_attr_modalias.attr,
 	NULL
 };
 
@@ -767,13 +771,15 @@
 	.attrs	= input_dev_attrs,
 };
 
-#define INPUT_DEV_ID_ATTR(name)							\
-static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-	return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);		\
-}										\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+#define INPUT_DEV_ID_ATTR(name)						\
+static ssize_t input_dev_show_id_##name(struct device *dev,		\
+					struct device_attribute *attr,	\
+					char *buf)			\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+	return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);	\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
 
 INPUT_DEV_ID_ATTR(bustype);
 INPUT_DEV_ID_ATTR(vendor);
@@ -781,10 +787,10 @@
 INPUT_DEV_ID_ATTR(version);
 
 static struct attribute *input_dev_id_attrs[] = {
-	&class_device_attr_bustype.attr,
-	&class_device_attr_vendor.attr,
-	&class_device_attr_product.attr,
-	&class_device_attr_version.attr,
+	&dev_attr_bustype.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_product.attr,
+	&dev_attr_version.attr,
 	NULL
 };
 
@@ -813,15 +819,17 @@
 	return len;
 }
 
-#define INPUT_DEV_CAP_ATTR(ev, bm)						\
-static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-	int len = input_print_bitmap(buf, PAGE_SIZE,				\
-				     input_dev->bm##bit, ev##_MAX, 1);		\
-	return min_t(int, len, PAGE_SIZE);					\
-}										\
-static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+#define INPUT_DEV_CAP_ATTR(ev, bm)					\
+static ssize_t input_dev_show_cap_##bm(struct device *dev,		\
+				       struct device_attribute *attr,	\
+				       char *buf)			\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+	int len = input_print_bitmap(buf, PAGE_SIZE,			\
+				     input_dev->bm##bit, ev##_MAX, 1);	\
+	return min_t(int, len, PAGE_SIZE);				\
+}									\
+static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
 
 INPUT_DEV_CAP_ATTR(EV, ev);
 INPUT_DEV_CAP_ATTR(KEY, key);
@@ -834,15 +842,15 @@
 INPUT_DEV_CAP_ATTR(SW, sw);
 
 static struct attribute *input_dev_caps_attrs[] = {
-	&class_device_attr_ev.attr,
-	&class_device_attr_key.attr,
-	&class_device_attr_rel.attr,
-	&class_device_attr_abs.attr,
-	&class_device_attr_msc.attr,
-	&class_device_attr_led.attr,
-	&class_device_attr_snd.attr,
-	&class_device_attr_ff.attr,
-	&class_device_attr_sw.attr,
+	&dev_attr_ev.attr,
+	&dev_attr_key.attr,
+	&dev_attr_rel.attr,
+	&dev_attr_abs.attr,
+	&dev_attr_msc.attr,
+	&dev_attr_led.attr,
+	&dev_attr_snd.attr,
+	&dev_attr_ff.attr,
+	&dev_attr_sw.attr,
 	NULL
 };
 
@@ -858,9 +866,9 @@
 	NULL
 };
 
-static void input_dev_release(struct class_device *class_dev)
+static void input_dev_release(struct device *device)
 {
-	struct input_dev *dev = to_input_dev(class_dev);
+	struct input_dev *dev = to_input_dev(device);
 
 	input_ff_destroy(dev);
 	kfree(dev);
@@ -947,10 +955,10 @@
 			return err;					\
 	} while (0)
 
-static int input_dev_uevent(struct class_device *cdev, char **envp,
+static int input_dev_uevent(struct device *device, char **envp,
 			    int num_envp, char *buffer, int buffer_size)
 {
-	struct input_dev *dev = to_input_dev(cdev);
+	struct input_dev *dev = to_input_dev(device);
 	int i = 0;
 	int len = 0;
 
@@ -988,10 +996,14 @@
 	return 0;
 }
 
+static struct device_type input_dev_type = {
+	.groups		= input_dev_attr_groups,
+	.release	= input_dev_release,
+	.uevent		= input_dev_uevent,
+};
+
 struct class input_class = {
-	.name			= "input",
-	.release		= input_dev_release,
-	.uevent			= input_dev_uevent,
+	.name		= "input",
 };
 EXPORT_SYMBOL_GPL(input_class);
 
@@ -1010,9 +1022,9 @@
 
 	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
 	if (dev) {
-		dev->cdev.class = &input_class;
-		dev->cdev.groups = input_dev_attr_groups;
-		class_device_initialize(&dev->cdev);
+		dev->dev.type = &input_dev_type;
+		dev->dev.class = &input_class;
+		device_initialize(&dev->dev);
 		mutex_init(&dev->mutex);
 		INIT_LIST_HEAD(&dev->h_list);
 		INIT_LIST_HEAD(&dev->node);
@@ -1131,17 +1143,17 @@
 
 	list_add_tail(&dev->node, &input_dev_list);
 
-	snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
 		 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
 
-	if (!dev->cdev.dev)
-		dev->cdev.dev = dev->dev.parent;
+	if (dev->cdev.dev)
+		dev->dev.parent = dev->cdev.dev;
 
-	error = class_device_add(&dev->cdev);
+	error = device_add(&dev->dev);
 	if (error)
 		return error;
 
-	path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
 	printk(KERN_INFO "input: %s as %s\n",
 		dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
 	kfree(path);
@@ -1173,7 +1185,7 @@
 
 	list_del_init(&dev->node);
 
-	class_device_unregister(&dev->cdev);
+	device_unregister(&dev->dev);
 
 	input_wakeup_procfs_readers();
 }
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 06f0541..a9a0180 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,6 +43,8 @@
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head client_list;
+	struct device dev;
+
 	struct js_corr corr[ABS_MAX + 1];
 	struct JS_DATA_SAVE_TYPE glue;
 	int nabs;
@@ -138,8 +140,10 @@
 	return retval < 0 ? retval : 0;
 }
 
-static void joydev_free(struct joydev *joydev)
+static void joydev_free(struct device *dev)
 {
+	struct joydev *joydev = container_of(dev, struct joydev, dev);
+
 	joydev_table[joydev->minor] = NULL;
 	kfree(joydev);
 }
@@ -154,12 +158,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--joydev->open) {
-		if (joydev->exist)
-			input_close_device(&joydev->handle);
-		else
-			joydev_free(joydev);
-	}
+	if (!--joydev->open && joydev->exist)
+		input_close_device(&joydev->handle);
+
+	put_device(&joydev->dev);
 
 	return 0;
 }
@@ -178,24 +180,32 @@
 	if (!joydev || !joydev->exist)
 		return -ENODEV;
 
+	get_device(&joydev->dev);
+
 	client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_joydev;
+	}
 
 	client->joydev = joydev;
 	list_add_tail(&client->node, &joydev->client_list);
 
 	if (!joydev->open++ && joydev->exist) {
 		error = input_open_device(&joydev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_joydev:
+	put_device(&joydev->dev);
+	return error;
 }
 
 static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -481,8 +491,6 @@
 			  const struct input_device_id *id)
 {
 	struct joydev *joydev;
-	struct class_device *cdev;
-	dev_t devt;
 	int i, j, t, minor;
 	int error;
 
@@ -505,7 +513,7 @@
 	joydev->handle.name = joydev->name;
 	joydev->handle.handler = handler;
 	joydev->handle.private = joydev;
-	sprintf(joydev->name, "js%d", minor);
+	snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
 
 	for (i = 0; i < ABS_MAX + 1; i++)
 		if (test_bit(i, dev->absbit)) {
@@ -547,36 +555,30 @@
 		joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
 	}
 
+	snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
+		 "js%d", minor);
+	joydev->dev.class = &input_class;
+	joydev->dev.parent = &dev->dev;
+	joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
+	joydev->dev.release = joydev_free;
+	device_initialize(&joydev->dev);
+
 	joydev_table[minor] = joydev;
 
-	devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-
-	cdev = class_device_create(&input_class, &dev->cdev, devt,
-				   dev->cdev.dev, joydev->name);
-	if (IS_ERR(cdev)) {
-		error = PTR_ERR(cdev);
-		goto err_free_joydev;
-	}
-
-	/* temporary symlink to keep userspace happy */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, joydev->name);
+	error = device_add(&joydev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_joydev;
 
 	error = input_register_handle(&joydev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_joydev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_joydev:
+	device_del(&joydev->dev);
  err_free_joydev:
-	joydev_table[minor] = NULL;
-	kfree(joydev);
+	put_device(&joydev->dev);
 	return error;
 }
 
@@ -587,18 +589,18 @@
 	struct joydev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&joydev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
-	class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	joydev->exist = 0;
 
 	if (joydev->open) {
 		input_close_device(handle);
-		wake_up_interruptible(&joydev->wait);
 		list_for_each_entry(client, &joydev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
-	} else
-		joydev_free(joydev);
+		wake_up_interruptible(&joydev->wait);
+	}
+
+	put_device(&joydev->dev);
 }
 
 static const struct input_device_id joydev_blacklist[] = {
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index b002345..12db72d 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -268,4 +268,11 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called xpad.
 
+config JOYSTICK_XPAD_FF
+	bool "X-Box gamepad rumble support"
+	depends on JOYSTICK_XPAD && INPUT
+	select INPUT_FF_MEMLESS
+	---help---
+	  Say Y here if you want to take advantage of xbox 360 rumble features.
+
 endif
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 86ad102..b069ee1 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -54,7 +54,7 @@
 
 module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0);
 MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
-module_param_array_named(dev2, db9_cfg[1].args, int, &db9_cfg[0].nargs, 0);
+module_param_array_named(dev2, db9_cfg[1].args, int, &db9_cfg[1].nargs, 0);
 MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
 module_param_array_named(dev3, db9_cfg[2].args, int, &db9_cfg[2].nargs, 0);
 MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 555319e..4ed3a3e 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -320,10 +320,10 @@
 
 static int dig_mode_start(struct gameport *gameport, u32 *packet)
 {
-	int i, seq_len = sizeof(init_seq)/sizeof(int);
+	int i;
 	int flags, tries = 0, bads = 0;
 
-	for (i = 0; i < seq_len; i++) {     /* Send magic sequence */
+	for (i = 0; i < ARRAY_SIZE(init_seq); i++) {     /* Send magic sequence */
 		if (init_seq[i])
 			gameport_trigger(gameport);
 		udelay(GRIP_INIT_DELAY);
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index fb129c4..682244b 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -370,10 +370,8 @@
 
 /*
  * Disable spring, enable force feedback.
- * FIXME: We should use iforce_set_autocenter() et al here.
  */
-
-	iforce_send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000");
+	iforce_set_autocenter(input_dev, 0);
 
 /*
  * Find appropriate device entry
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 21c4e13..3154ccd 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -246,6 +246,8 @@
 
 int iforce_get_id_packet(struct iforce *iforce, char *packet)
 {
+	int status;
+
 	switch (iforce->bus) {
 
 	case IFORCE_USB:
@@ -254,18 +256,22 @@
 		iforce->cr.bRequest = packet[0];
 		iforce->ctrl->dev = iforce->usbdev;
 
-		if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC))
+		status = usb_submit_urb(iforce->ctrl, GFP_ATOMIC);
+		if (status) {
+			err("usb_submit_urb failed %d", status);
 			return -1;
+		}
 
 		wait_event_interruptible_timeout(iforce->wait,
 			iforce->ctrl->status != -EINPROGRESS, HZ);
 
 		if (iforce->ctrl->status) {
+			dbg("iforce->ctrl->status = %d", iforce->ctrl->status);
 			usb_unlink_urb(iforce->ctrl);
 			return -1;
 		}
 #else
-		err("iforce_get_id_packet: iforce->bus = USB!");
+		dbg("iforce_get_id_packet: iforce->bus = USB!");
 #endif
 		break;
 
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 750099d..1457b73 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -65,6 +65,7 @@
 	XMIT_INC(iforce->xmit.tail, n);
 
 	if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
+		clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
 		warn("usb_submit_urb failed %d\n", n);
 	}
 
@@ -163,8 +164,8 @@
 	usb_fill_int_urb(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
 			iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
 
-	usb_fill_bulk_urb(iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),
-			iforce + 1, 32, iforce_usb_out, iforce);
+	usb_fill_int_urb(iforce->out, dev, usb_sndintpipe(dev, epout->bEndpointAddress),
+			iforce + 1, 32, iforce_usb_out, iforce, epout->bInterval);
 
 	usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
 			(void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 8c8cd95..244089c 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -8,6 +8,7 @@
  *                    Ivan Hawkes <blackhawk@ivanhawkes.com>
  *               2005 Dominic Cerquetti <binary1230@yahoo.com>
  *               2006 Adam Buchbinder <adam.buchbinder@gmail.com>
+ *               2007 Jan Kratochvil <honza@jikos.cz>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -28,6 +29,7 @@
  *  - information from     http://euc.jp/periphs/xbox-controller.ja.html
  *  - the iForce driver    drivers/char/joystick/iforce.c
  *  - the skeleton-driver  drivers/usb/usb-skeleton.c
+ *  - Xbox 360 information http://www.free60.org/wiki/Gamepad
  *
  * Thanks to:
  *  - ITO Takayuki for providing essential xpad information on his website
@@ -88,6 +90,9 @@
 #define MAP_DPAD_TO_AXES       1
 #define MAP_DPAD_UNKNOWN       -1
 
+#define XTYPE_XBOX        0
+#define XTYPE_XBOX360     1
+
 static int dpad_to_buttons;
 module_param(dpad_to_buttons, bool, S_IRUGO);
 MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
@@ -97,40 +102,42 @@
 	u16 idProduct;
 	char *name;
 	u8 dpad_mapping;
+	u8 xtype;
 } xpad_device[] = {
-	{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES },
-	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES },
-	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES },
-	{ 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES },
-	{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS },
-	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES },
-	{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES },
-	{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES },
-	{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES },
-	{ 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS },
-	{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS },
-	{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
-	{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
-	{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES },
-	{ 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES },
-	{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES},
-	{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES },
-	{ 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES },
-	{ 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES },
-	{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES },
-	{ 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES },
-	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES },
-	{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES },
-	{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS },
-	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS },
-	{ 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES },
-	{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN }
+	{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+	{ 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
 };
 
 static const signed short xpad_btn[] = {
@@ -146,6 +153,12 @@
 	-1				/* terminating entry */
 };
 
+static const signed short xpad360_btn[] = {  /* buttons for x360 controller */
+	BTN_TL, BTN_TR,		/* Button LB/RB */
+	BTN_MODE,		/* The big X button */
+	-1
+};
+
 static const signed short xpad_abs[] = {
 	ABS_X, ABS_Y,		/* left stick */
 	ABS_RX, ABS_RY,		/* right stick */
@@ -159,8 +172,12 @@
 	-1			/* terminating entry */
 };
 
+/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
+ * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
+ * but we need only one of them. */
 static struct usb_device_id xpad_table [] = {
 	{ USB_INTERFACE_INFO('X', 'B', 0) },	/* X-Box USB-IF not approved class */
+	{ USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) },	/* X-Box 360 controller */
 	{ }
 };
 
@@ -174,9 +191,16 @@
 	unsigned char *idata;		/* input data */
 	dma_addr_t idata_dma;
 
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+	struct urb *irq_out;		/* urb for interrupt out report */
+	unsigned char *odata;		/* output data */
+	dma_addr_t odata_dma;
+#endif
+
 	char phys[65];			/* physical device path */
 
 	int dpad_mapping;		/* map d-pad to buttons or to axes */
+	int xtype;			/* type of xbox device */
 };
 
 /*
@@ -212,8 +236,8 @@
 	} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
 		input_report_key(dev, BTN_LEFT,  data[2] & 0x04);
 		input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
-		input_report_key(dev, BTN_0,     data[2] & 0x01); // up
-		input_report_key(dev, BTN_1,     data[2] & 0x02); // down
+		input_report_key(dev, BTN_0,     data[2] & 0x01); /* up */
+		input_report_key(dev, BTN_1,     data[2] & 0x02); /* down */
 	}
 
 	/* start/back buttons and stick press left/right */
@@ -235,6 +259,64 @@
 	input_sync(dev);
 }
 
+/*
+ *	xpad360_process_packet
+ *
+ *	Completes a request by converting the data into events for the
+ *	input subsystem. It is version for xbox 360 controller
+ *
+ *	The used report descriptor was taken from:
+ *		http://www.free60.org/wiki/Gamepad
+ */
+
+static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
+{
+	struct input_dev *dev = xpad->dev;
+
+	/* digital pad */
+	if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
+		input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
+		input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+	} else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
+		/* dpad as buttons (right, left, down, up) */
+		input_report_key(dev, BTN_LEFT, data[2] & 0x04);
+		input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
+		input_report_key(dev, BTN_0, data[2] & 0x01);	/* up */
+		input_report_key(dev, BTN_1, data[2] & 0x02);	/* down */
+	}
+
+	/* start/back buttons */
+	input_report_key(dev, BTN_START,  data[2] & 0x10);
+	input_report_key(dev, BTN_BACK,   data[2] & 0x20);
+
+	/* stick press left/right */
+	input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
+	input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
+
+	/* buttons A,B,X,Y,TL,TR and MODE */
+	input_report_key(dev, BTN_A,	data[3] & 0x10);
+	input_report_key(dev, BTN_B,	data[3] & 0x20);
+	input_report_key(dev, BTN_X,	data[3] & 0x40);
+	input_report_key(dev, BTN_Y,	data[3] & 0x80);
+	input_report_key(dev, BTN_TL,	data[3] & 0x01);
+	input_report_key(dev, BTN_TR,	data[3] & 0x02);
+	input_report_key(dev, BTN_MODE,	data[3] & 0x04);
+
+	/* left stick */
+	input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6]));
+	input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8]));
+
+	/* right stick */
+	input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10]));
+	input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12]));
+
+	/* triggers left/right */
+	input_report_abs(dev, ABS_Z, data[4]);
+	input_report_abs(dev, ABS_RZ, data[5]);
+
+	input_sync(dev);
+}
+
 static void xpad_irq_in(struct urb *urb)
 {
 	struct usb_xpad *xpad = urb->context;
@@ -255,7 +337,10 @@
 		goto exit;
 	}
 
-	xpad_process_packet(xpad, 0, xpad->idata);
+	if (xpad->xtype == XTYPE_XBOX360)
+		xpad360_process_packet(xpad, 0, xpad->idata);
+	else
+		xpad_process_packet(xpad, 0, xpad->idata);
 
 exit:
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -264,7 +349,114 @@
 		     __FUNCTION__, retval);
 }
 
-static int xpad_open (struct input_dev *dev)
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+static void xpad_irq_out(struct urb *urb)
+{
+	int retval;
+
+	switch (urb->status) {
+		case 0:
+		/* success */
+		break;
+		case -ECONNRESET:
+		case -ENOENT:
+		case -ESHUTDOWN:
+			/* this urb is terminated, clean up */
+			dbg("%s - urb shutting down with status: %d",  __FUNCTION__, urb->status);
+			return;
+		default:
+			dbg("%s - nonzero urb status received: %d",  __FUNCTION__, urb->status);
+			goto exit;
+	}
+
+exit:
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		err("%s - usb_submit_urb failed with result %d",
+		   __FUNCTION__, retval);
+}
+
+static int xpad_play_effect(struct input_dev *dev, void *data,
+			    struct ff_effect *effect)
+{
+	struct usb_xpad *xpad = input_get_drvdata(dev);
+
+	if (effect->type == FF_RUMBLE) {
+		__u16 strong = effect->u.rumble.strong_magnitude;
+		__u16 weak = effect->u.rumble.weak_magnitude;
+		xpad->odata[0] = 0x00;
+		xpad->odata[1] = 0x08;
+		xpad->odata[2] = 0x00;
+		xpad->odata[3] = strong / 256;
+		xpad->odata[4] = weak / 256;
+		xpad->odata[5] = 0x00;
+		xpad->odata[6] = 0x00;
+		xpad->odata[7] = 0x00;
+		usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+	}
+
+	return 0;
+}
+
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad)
+{
+	struct usb_endpoint_descriptor *ep_irq_out;
+	int error = -ENOMEM;
+
+	if (xpad->xtype != XTYPE_XBOX360)
+		return 0;
+
+	xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
+				       GFP_ATOMIC, &xpad->odata_dma );
+	if (!xpad->odata)
+		goto fail1;
+
+	xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
+	if (!xpad->irq_out)
+		goto fail2;
+
+	ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
+	usb_fill_int_urb(xpad->irq_out, xpad->udev,
+			 usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
+			 xpad->odata, XPAD_PKT_LEN,
+			 xpad_irq_out, xpad, ep_irq_out->bInterval);
+	xpad->irq_out->transfer_dma = xpad->odata_dma;
+	xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+
+	error = input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+	if (error)
+		goto fail2;
+
+	return 0;
+
+ fail2:	usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
+ fail1:	return error;
+}
+
+static void xpad_stop_ff(struct usb_xpad *xpad)
+{
+	if (xpad->xtype == XTYPE_XBOX360)
+		usb_kill_urb(xpad->irq_out);
+}
+
+static void xpad_deinit_ff(struct usb_xpad *xpad)
+{
+	if (xpad->xtype == XTYPE_XBOX360) {
+		usb_free_urb(xpad->irq_out);
+		usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
+				xpad->odata, xpad->odata_dma);
+	}
+}
+
+#else
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
+static void xpad_stop_ff(struct usb_xpad *xpad) { }
+static void xpad_deinit_ff(struct usb_xpad *xpad) { }
+#endif
+
+static int xpad_open(struct input_dev *dev)
 {
 	struct usb_xpad *xpad = input_get_drvdata(dev);
 
@@ -275,11 +467,12 @@
 	return 0;
 }
 
-static void xpad_close (struct input_dev *dev)
+static void xpad_close(struct input_dev *dev)
 {
 	struct usb_xpad *xpad = input_get_drvdata(dev);
 
 	usb_kill_urb(xpad->irq_in);
+	xpad_stop_ff(xpad);
 }
 
 static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
@@ -335,6 +528,7 @@
 
 	xpad->udev = udev;
 	xpad->dpad_mapping = xpad_device[i].dpad_mapping;
+	xpad->xtype = xpad_device[i].xtype;
 	if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
 		xpad->dpad_mapping = dpad_to_buttons;
 	xpad->dev = input_dev;
@@ -356,6 +550,9 @@
 	/* set up buttons */
 	for (i = 0; xpad_btn[i] >= 0; i++)
 		set_bit(xpad_btn[i], input_dev->keybit);
+	if (xpad->xtype == XTYPE_XBOX360)
+		for (i = 0; xpad360_btn[i] >= 0; i++)
+			set_bit(xpad360_btn[i], input_dev->keybit);
 	if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
 		for (i = 0; xpad_btn_pad[i] >= 0; i++)
 			set_bit(xpad_btn_pad[i], input_dev->keybit);
@@ -367,6 +564,10 @@
 		for (i = 0; xpad_abs_pad[i] >= 0; i++)
 		    xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
 
+	error = xpad_init_ff(intf, xpad);
+	if (error)
+		goto fail2;
+
 	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
 	usb_fill_int_urb(xpad->irq_in, udev,
 			 usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
@@ -396,10 +597,10 @@
 
 	usb_set_intfdata(intf, NULL);
 	if (xpad) {
-		usb_kill_urb(xpad->irq_in);
 		input_unregister_device(xpad->dev);
+		xpad_deinit_ff(xpad);
 		usb_free_urb(xpad->irq_in);
-		usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN,
+		usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
 				xpad->idata, xpad->idata_dma);
 		kfree(xpad);
 	}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index bd707b8..c97d5eb 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -164,6 +164,9 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called amikbd.
 
+config ATARI_KBD_CORE
+	bool
+
 config KEYBOARD_ATARI
 	tristate "Atari keyboard"
 	depends on ATARI
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index be1fe46..41fc3d0 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -89,7 +89,7 @@
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
 	173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
-	159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
+	159,  0,115,  0,164,  0,  0,116,158,  0,172,166,  0,  0,  0,142,
 	157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
 	226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
@@ -111,7 +111,7 @@
 	 82, 83, 80, 76, 77, 72, 69, 98,  0, 96, 81,  0, 78, 73, 55,183,
 
 	184,185,186,187, 74, 94, 92, 93,  0,  0,  0,125,126,127,112,  0,
-	  0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
+	  0,139,172,163,165,115,152,172,166,140,160,154,113,114,167,168,
 	148,149,147,140
 };
 
@@ -219,7 +219,8 @@
 	unsigned long time;
 	unsigned long err_count;
 
-	struct work_struct event_work;
+	struct delayed_work event_work;
+	unsigned long event_jiffies;
 	struct mutex event_mutex;
 	unsigned long event_mask;
 };
@@ -408,9 +409,10 @@
 			goto out;
 		case ATKBD_RET_ACK:
 		case ATKBD_RET_NAK:
-			printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
-			       "Some program might be trying access hardware directly.\n",
-			       data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
+			if (printk_ratelimit())
+				printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
+				       "Some program might be trying access hardware directly.\n",
+				       data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
 			goto out;
 		case ATKBD_RET_HANGEUL:
 		case ATKBD_RET_HANJA:
@@ -565,7 +567,7 @@
 
 static void atkbd_event_work(struct work_struct *work)
 {
-	struct atkbd *atkbd = container_of(work, struct atkbd, event_work);
+	struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
 
 	mutex_lock(&atkbd->event_mutex);
 
@@ -579,12 +581,30 @@
 }
 
 /*
+ * Schedule switch for execution. We need to throttle requests,
+ * otherwise keyboard may become unresponsive.
+ */
+static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)
+{
+	unsigned long delay = msecs_to_jiffies(50);
+
+	if (time_after(jiffies, atkbd->event_jiffies + delay))
+		delay = 0;
+
+	atkbd->event_jiffies = jiffies;
+	set_bit(event_bit, &atkbd->event_mask);
+	wmb();
+	schedule_delayed_work(&atkbd->event_work, delay);
+}
+
+/*
  * Event callback from the input module. Events that change the state of
  * the hardware are processed here. If action can not be performed in
  * interrupt context it is offloaded to atkbd_event_work.
  */
 
-static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int atkbd_event(struct input_dev *dev,
+			unsigned int type, unsigned int code, int value)
 {
 	struct atkbd *atkbd = input_get_drvdata(dev);
 
@@ -594,19 +614,12 @@
 	switch (type) {
 
 		case EV_LED:
-			set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask);
-			wmb();
-			schedule_work(&atkbd->event_work);
+			atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
 			return 0;
 
 		case EV_REP:
-
-			if (!atkbd->softrepeat) {
-				set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask);
-				wmb();
-				schedule_work(&atkbd->event_work);
-			}
-
+			if (!atkbd->softrepeat)
+				atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
 			return 0;
 	}
 
@@ -940,7 +953,7 @@
 
 	atkbd->dev = dev;
 	ps2_init(&atkbd->ps2dev, serio);
-	INIT_WORK(&atkbd->event_work, atkbd_event_work);
+	INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
 	mutex_init(&atkbd->event_mutex);
 
 	switch (serio->id.type) {
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
index 06eaf76..ebe5eac 100644
--- a/drivers/input/keyboard/pxa27x_keyboard.c
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -104,7 +104,7 @@
 	KPREC = 0x7F;
 
 	/* Enable unit clock */
-	pxa_set_cken(CKEN19_KEYPAD, 1);
+	pxa_set_cken(CKEN_KEYPAD, 1);
 
 	return 0;
 }
@@ -112,7 +112,7 @@
 static void pxakbd_close(struct input_dev *dev)
 {
 	/* Disable clock unit */
-	pxa_set_cken(CKEN19_KEYPAD, 0);
+	pxa_set_cken(CKEN_KEYPAD, 0);
 }
 
 #ifdef CONFIG_PM
@@ -140,7 +140,7 @@
 		KPREC = pdata->reg_kprec;
 
 		/* Enable unit clock */
-		pxa_set_cken(CKEN19_KEYPAD, 1);
+		pxa_set_cken(CKEN_KEYPAD, 1);
 	}
 
 	mutex_unlock(&input_dev->mutex);
@@ -185,7 +185,7 @@
 			    DRIVER_NAME, pdev);
 	if (error) {
 		printk(KERN_ERR "Cannot request keypad IRQ\n");
-		pxa_set_cken(CKEN19_KEYPAD, 0);
+		pxa_set_cken(CKEN_KEYPAD, 0);
 		goto err_free_dev;
 	}
 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 842a7b4..9b26574 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -65,9 +65,13 @@
 config INPUT_WISTRON_BTNS
 	tristate "x86 Wistron laptop button interface"
 	depends on X86 && !X86_64
+	select INPUT_POLLDEV
+	select NEW_LEDS
+	select LEDS_CLASS
 	help
 	  Say Y here for support of Winstron laptop button interface, used on
-	  laptops of various brands, including Acer and Fujitsu-Siemens.
+	  laptops of various brands, including Acer and Fujitsu-Siemens. If
+	  available, mail and wifi leds will be controlable via /sys/class/leds.
 
 	  To compile this driver as a module, choose M here: the module will
 	  be called wistron_btns.
@@ -170,17 +174,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called uinput.
 
-config INPUT_POLLDEV
-	tristate "Polled input device skeleton"
-	help
-	  Say Y here if you are using a driver for an input
-	  device that periodically polls hardware state. This
-	  option is only useful for out-of-tree drivers since
-	  in-tree drivers select it automatically.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called input-polldev.
-
 config HP_SDC_RTC
 	tristate "HP SDC Real Time Clock"
 	depends on GSC || HP300
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 8b2f779..3585b50 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -4,7 +4,6 @@
 
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_INPUT_POLLDEV)		+= input-polldev.o
 obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o
 obj-$(CONFIG_INPUT_PCSPKR)		+= pcspkr.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
diff --git a/drivers/input/misc/input-polldev.c b/drivers/input/misc/input-polldev.c
deleted file mode 100644
index 1b2b9c9..0000000
--- a/drivers/input/misc/input-polldev.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Generic implementation of a polled input device
-
- * Copyright (c) 2007 Dmitry Torokhov
- *
- * 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/jiffies.h>
-#include <linux/mutex.h>
-#include <linux/input-polldev.h>
-
-static DEFINE_MUTEX(polldev_mutex);
-static int polldev_users;
-static struct workqueue_struct *polldev_wq;
-
-static int input_polldev_start_workqueue(void)
-{
-	int retval;
-
-	retval = mutex_lock_interruptible(&polldev_mutex);
-	if (retval)
-		return retval;
-
-	if (!polldev_users) {
-		polldev_wq = create_singlethread_workqueue("ipolldevd");
-		if (!polldev_wq) {
-			printk(KERN_ERR "input-polldev: failed to create "
-				"ipolldevd workqueue\n");
-			retval = -ENOMEM;
-			goto out;
-		}
-	}
-
-	polldev_users++;
-
- out:
-	mutex_unlock(&polldev_mutex);
-	return retval;
-}
-
-static void input_polldev_stop_workqueue(void)
-{
-	mutex_lock(&polldev_mutex);
-
-	if (!--polldev_users)
-		destroy_workqueue(polldev_wq);
-
-	mutex_unlock(&polldev_mutex);
-}
-
-static void input_polled_device_work(struct work_struct *work)
-{
-	struct input_polled_dev *dev =
-		container_of(work, struct input_polled_dev, work.work);
-
-	dev->poll(dev);
-	queue_delayed_work(polldev_wq, &dev->work,
-			   msecs_to_jiffies(dev->poll_interval));
-}
-
-static int input_open_polled_device(struct input_dev *input)
-{
-	struct input_polled_dev *dev = input->private;
-	int error;
-
-	error = input_polldev_start_workqueue();
-	if (error)
-		return error;
-
-	if (dev->flush)
-		dev->flush(dev);
-
-	queue_delayed_work(polldev_wq, &dev->work,
-			   msecs_to_jiffies(dev->poll_interval));
-
-	return 0;
-}
-
-static void input_close_polled_device(struct input_dev *input)
-{
-	struct input_polled_dev *dev = input->private;
-
-	cancel_rearming_delayed_workqueue(polldev_wq, &dev->work);
-	input_polldev_stop_workqueue();
-}
-
-/**
- * input_allocate_polled_device - allocated memory polled device
- *
- * The function allocates memory for a polled device and also
- * for an input device associated with this polled device.
- */
-struct input_polled_dev *input_allocate_polled_device(void)
-{
-	struct input_polled_dev *dev;
-
-	dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);
-	if (!dev)
-		return NULL;
-
-	dev->input = input_allocate_device();
-	if (!dev->input) {
-		kfree(dev);
-		return NULL;
-	}
-
-	return dev;
-}
-EXPORT_SYMBOL(input_allocate_polled_device);
-
-/**
- * input_free_polled_device - free memory allocated for polled device
- * @dev: device to free
- *
- * The function frees memory allocated for polling device and drops
- * reference to the associated input device (if present).
- */
-void input_free_polled_device(struct input_polled_dev *dev)
-{
-	if (dev) {
-		input_free_device(dev->input);
-		kfree(dev);
-	}
-}
-EXPORT_SYMBOL(input_free_polled_device);
-
-/**
- * input_register_polled_device - register polled device
- * @dev: device to register
- *
- * The function registers previously initialized polled input device
- * with input layer. The device should be allocated with call to
- * input_allocate_polled_device(). Callers should also set up poll()
- * method and set up capabilities (id, name, phys, bits) of the
- * corresponing input_dev structure.
- */
-int input_register_polled_device(struct input_polled_dev *dev)
-{
-	struct input_dev *input = dev->input;
-
-	INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
-	if (!dev->poll_interval)
-		dev->poll_interval = 500;
-	input->private = dev;
-	input->open = input_open_polled_device;
-	input->close = input_close_polled_device;
-
-	return input_register_device(input);
-}
-EXPORT_SYMBOL(input_register_polled_device);
-
-/**
- * input_unregister_polled_device - unregister polled device
- * @dev: device to unregister
- *
- * The function unregisters previously registered polled input
- * device from input layer. Polling is stopped and device is
- * ready to be freed with call to input_free_polled_device().
- * Callers should not attempt to access dev->input pointer
- * after calling this function.
- */
-void input_unregister_polled_device(struct input_polled_dev *dev)
-{
-	input_unregister_device(dev->input);
-	dev->input = NULL;
-}
-EXPORT_SYMBOL(input_unregister_polled_device);
-
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 961aad7..60121f1 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -20,37 +20,31 @@
 #include <linux/io.h>
 #include <linux/dmi.h>
 #include <linux/init.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
 #include <linux/interrupt.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/mc146818rtc.h>
 #include <linux/module.h>
 #include <linux/preempt.h>
 #include <linux/string.h>
-#include <linux/timer.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
+#include <linux/leds.h>
 
-/*
- * Number of attempts to read data from queue per poll;
- * the queue can hold up to 31 entries
- */
-#define MAX_POLL_ITERATIONS 64
-
-#define POLL_FREQUENCY 10 /* Number of polls per second */
-
-#if POLL_FREQUENCY > HZ
-#error "POLL_FREQUENCY too high"
-#endif
+/* How often we poll keys - msecs */
+#define POLL_INTERVAL_DEFAULT	500 /* when idle */
+#define POLL_INTERVAL_BURST	100 /* when a key was recently pressed */
 
 /* BIOS subsystem IDs */
 #define WIFI		0x35
 #define BLUETOOTH	0x34
+#define MAIL_LED	0x31
 
 MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
 MODULE_DESCRIPTION("Wistron laptop button driver");
 MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.2");
+MODULE_VERSION("0.3");
 
 static int force; /* = 0; */
 module_param(force, bool, 0);
@@ -248,9 +242,10 @@
 #define FE_WIFI_LED 0x02
 #define FE_UNTESTED 0x80
 
-static const struct key_entry *keymap; /* = NULL; Current key map */
+static struct key_entry *keymap; /* = NULL; Current key map */
 static int have_wifi;
 static int have_bluetooth;
+static int have_leds;
 
 static int __init dmi_matched(struct dmi_system_id *dmi)
 {
@@ -263,6 +258,8 @@
 		else if (key->type == KE_BLUETOOTH)
 			have_bluetooth = 1;
 	}
+	have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED);
+
 	return 1;
 }
 
@@ -966,21 +963,249 @@
 
  /* Input layer interface */
 
-static struct input_dev *input_dev;
+static struct input_polled_dev *wistron_idev;
+static unsigned long jiffies_last_press;
+static int wifi_enabled;
+static int bluetooth_enabled;
+
+static void report_key(struct input_dev *dev, unsigned int keycode)
+{
+	input_report_key(dev, keycode, 1);
+	input_sync(dev);
+	input_report_key(dev, keycode, 0);
+	input_sync(dev);
+}
+
+static void report_switch(struct input_dev *dev, unsigned int code, int value)
+{
+	input_report_switch(dev, code, value);
+	input_sync(dev);
+}
+
+
+ /* led management */
+static void wistron_mail_led_set(struct led_classdev *led_cdev,
+				enum led_brightness value)
+{
+	bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
+}
+
+/* same as setting up wifi card, but for laptops on which the led is managed */
+static void wistron_wifi_led_set(struct led_classdev *led_cdev,
+				enum led_brightness value)
+{
+	bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
+}
+
+static struct led_classdev wistron_mail_led = {
+	.name			= "mail:green",
+	.brightness_set		= wistron_mail_led_set,
+};
+
+static struct led_classdev wistron_wifi_led = {
+	.name			= "wifi:red",
+	.brightness_set		= wistron_wifi_led_set,
+};
+
+static void __devinit wistron_led_init(struct device *parent)
+{
+	if (have_leds & FE_WIFI_LED) {
+		u16 wifi = bios_get_default_setting(WIFI);
+		if (wifi & 1) {
+			wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
+			if (led_classdev_register(parent, &wistron_wifi_led))
+				have_leds &= ~FE_WIFI_LED;
+			else
+				bios_set_state(WIFI, wistron_wifi_led.brightness);
+
+		} else
+			have_leds &= ~FE_WIFI_LED;
+	}
+
+	if (have_leds & FE_MAIL_LED) {
+		/* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
+		wistron_mail_led.brightness = LED_OFF;
+		if (led_classdev_register(parent, &wistron_mail_led))
+			have_leds &= ~FE_MAIL_LED;
+		else
+			bios_set_state(MAIL_LED, wistron_mail_led.brightness);
+	}
+}
+
+static void __devexit wistron_led_remove(void)
+{
+	if (have_leds & FE_MAIL_LED)
+		led_classdev_unregister(&wistron_mail_led);
+
+	if (have_leds & FE_WIFI_LED)
+		led_classdev_unregister(&wistron_wifi_led);
+}
+
+static inline void wistron_led_suspend(void)
+{
+	if (have_leds & FE_MAIL_LED)
+		led_classdev_suspend(&wistron_mail_led);
+
+	if (have_leds & FE_WIFI_LED)
+		led_classdev_suspend(&wistron_wifi_led);
+}
+
+static inline void wistron_led_resume(void)
+{
+	if (have_leds & FE_MAIL_LED)
+		led_classdev_resume(&wistron_mail_led);
+
+	if (have_leds & FE_WIFI_LED)
+		led_classdev_resume(&wistron_wifi_led);
+}
+
+static struct key_entry *wistron_get_entry_by_scancode(int code)
+{
+	struct key_entry *key;
+
+	for (key = keymap; key->type != KE_END; key++)
+		if (code == key->code)
+			return key;
+
+	return NULL;
+}
+
+static struct key_entry *wistron_get_entry_by_keycode(int keycode)
+{
+	struct key_entry *key;
+
+	for (key = keymap; key->type != KE_END; key++)
+		if (key->type == KE_KEY && keycode == key->keycode)
+			return key;
+
+	return NULL;
+}
+
+static void handle_key(u8 code)
+{
+	const struct key_entry *key = wistron_get_entry_by_scancode(code);
+
+	if (key) {
+		switch (key->type) {
+		case KE_KEY:
+			report_key(wistron_idev->input, key->keycode);
+			break;
+
+		case KE_SW:
+			report_switch(wistron_idev->input,
+				      key->sw.code, key->sw.value);
+			break;
+
+		case KE_WIFI:
+			if (have_wifi) {
+				wifi_enabled = !wifi_enabled;
+				bios_set_state(WIFI, wifi_enabled);
+			}
+			break;
+
+		case KE_BLUETOOTH:
+			if (have_bluetooth) {
+				bluetooth_enabled = !bluetooth_enabled;
+				bios_set_state(BLUETOOTH, bluetooth_enabled);
+			}
+			break;
+
+		default:
+			BUG();
+		}
+		jiffies_last_press = jiffies;
+	} else
+		printk(KERN_NOTICE
+			"wistron_btns: Unknown key code %02X\n", code);
+}
+
+static void poll_bios(bool discard)
+{
+	u8 qlen;
+	u16 val;
+
+	for (;;) {
+		qlen = CMOS_READ(cmos_address);
+		if (qlen == 0)
+			break;
+		val = bios_pop_queue();
+		if (val != 0 && !discard)
+			handle_key((u8)val);
+	}
+}
+
+static void wistron_flush(struct input_polled_dev *dev)
+{
+	/* Flush stale event queue */
+	poll_bios(true);
+}
+
+static void wistron_poll(struct input_polled_dev *dev)
+{
+	poll_bios(false);
+
+	/* Increase poll frequency if user is currently pressing keys (< 2s ago) */
+	if (time_before(jiffies, jiffies_last_press + 2 * HZ))
+		dev->poll_interval = POLL_INTERVAL_BURST;
+	else
+		dev->poll_interval = POLL_INTERVAL_DEFAULT;
+}
+
+static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+	const struct key_entry *key = wistron_get_entry_by_scancode(scancode);
+
+	if (key && key->type == KE_KEY) {
+		*keycode = key->keycode;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+	struct key_entry *key;
+	int old_keycode;
+
+	if (keycode < 0 || keycode > KEY_MAX)
+		return -EINVAL;
+
+	key = wistron_get_entry_by_scancode(scancode);
+	if (key && key->type == KE_KEY) {
+		old_keycode = key->keycode;
+		key->keycode = keycode;
+		set_bit(keycode, dev->keybit);
+		if (!wistron_get_entry_by_keycode(old_keycode))
+			clear_bit(old_keycode, dev->keybit);
+		return 0;
+	}
+
+	return -EINVAL;
+}
 
 static int __devinit setup_input_dev(void)
 {
 	const struct key_entry *key;
+	struct input_dev *input_dev;
 	int error;
 
-	input_dev = input_allocate_device();
-	if (!input_dev)
+	wistron_idev = input_allocate_polled_device();
+	if (!wistron_idev)
 		return -ENOMEM;
 
+	wistron_idev->flush = wistron_flush;
+	wistron_idev->poll = wistron_poll;
+	wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
+
+	input_dev = wistron_idev->input;
 	input_dev->name = "Wistron laptop buttons";
 	input_dev->phys = "wistron/input0";
 	input_dev->id.bustype = BUS_HOST;
-	input_dev->cdev.dev = &wistron_device->dev;
+	input_dev->dev.parent = &wistron_device->dev;
+
+	input_dev->getkeycode = wistron_getkeycode;
+	input_dev->setkeycode = wistron_setkeycode;
 
 	for (key = keymap; key->type != KE_END; key++) {
 		switch (key->type) {
@@ -995,7 +1220,7 @@
 				break;
 
 			default:
-				;
+				break;
 		}
 	}
 
@@ -1005,100 +1230,20 @@
 			"please report success or failure to eric.piel"
 			"@tremplin-utc.net\n");
 
-	error = input_register_device(input_dev);
+	error = input_register_polled_device(wistron_idev);
 	if (error) {
-		input_free_device(input_dev);
+		input_free_polled_device(wistron_idev);
 		return error;
 	}
 
 	return 0;
 }
 
-static void report_key(unsigned keycode)
-{
-	input_report_key(input_dev, keycode, 1);
-	input_sync(input_dev);
-	input_report_key(input_dev, keycode, 0);
-	input_sync(input_dev);
-}
-
-static void report_switch(unsigned code, int value)
-{
-	input_report_switch(input_dev, code, value);
-	input_sync(input_dev);
-}
-
- /* Driver core */
-
-static int wifi_enabled;
-static int bluetooth_enabled;
-
-static void poll_bios(unsigned long);
-
-static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0);
-
-static void handle_key(u8 code)
-{
-	const struct key_entry *key;
-
-	for (key = keymap; key->type != KE_END; key++) {
-		if (code == key->code) {
-			switch (key->type) {
-			case KE_KEY:
-				report_key(key->keycode);
-				break;
-
-			case KE_SW:
-				report_switch(key->sw.code, key->sw.value);
-				break;
-
-			case KE_WIFI:
-				if (have_wifi) {
-					wifi_enabled = !wifi_enabled;
-					bios_set_state(WIFI, wifi_enabled);
-				}
-				break;
-
-			case KE_BLUETOOTH:
-				if (have_bluetooth) {
-					bluetooth_enabled = !bluetooth_enabled;
-					bios_set_state(BLUETOOTH, bluetooth_enabled);
-				}
-				break;
-
-			case KE_END:
-				break;
-			default:
-				BUG();
-			}
-			return;
-		}
-	}
-	printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code);
-}
-
-static void poll_bios(unsigned long discard)
-{
-	u8 qlen;
-	u16 val;
-
-	for (;;) {
-		qlen = CMOS_READ(cmos_address);
-		if (qlen == 0)
-			break;
-		val = bios_pop_queue();
-		if (val != 0 && !discard)
-			handle_key((u8)val);
-	}
-
-	mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
-}
+/* Driver core */
 
 static int __devinit wistron_probe(struct platform_device *dev)
 {
-	int err = setup_input_dev();
-	if (err)
-		return err;
+	int err;
 
 	bios_attach();
 	cmos_address = bios_get_cmos_address();
@@ -1125,15 +1270,21 @@
 			bios_set_state(BLUETOOTH, bluetooth_enabled);
 	}
 
-	poll_bios(1); /* Flush stale event queue and arm timer */
+	wistron_led_init(&dev->dev);
+	err = setup_input_dev();
+	if (err) {
+		bios_detach();
+		return err;
+	}
 
 	return 0;
 }
 
 static int __devexit wistron_remove(struct platform_device *dev)
 {
-	del_timer_sync(&poll_timer);
-	input_unregister_device(input_dev);
+	wistron_led_remove();
+	input_unregister_polled_device(wistron_idev);
+	input_free_polled_device(wistron_idev);
 	bios_detach();
 
 	return 0;
@@ -1142,14 +1293,13 @@
 #ifdef CONFIG_PM
 static int wistron_suspend(struct platform_device *dev, pm_message_t state)
 {
-	del_timer_sync(&poll_timer);
-
 	if (have_wifi)
 		bios_set_state(WIFI, 0);
 
 	if (have_bluetooth)
 		bios_set_state(BLUETOOTH, 0);
 
+	wistron_led_suspend();
 	return 0;
 }
 
@@ -1161,7 +1311,8 @@
 	if (have_bluetooth)
 		bios_set_state(BLUETOOTH, bluetooth_enabled);
 
-	poll_bios(1);
+	wistron_led_resume();
+	poll_bios(true);
 
 	return 0;
 }
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index eb0167e..7bbea09 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -48,7 +48,7 @@
 	  If unsure, say Y.
 
 config MOUSE_PS2_LOGIPS2PP
-	bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED
+	bool "Logitech PS/2++ mouse protocol extension" if EMBEDDED
 	default y
 	depends on MOUSE_PS2
 	help
@@ -216,4 +216,20 @@
 	help
 	  Say Y here to support HIL pointers.
 
+config MOUSE_GPIO
+	tristate "GPIO mouse"
+	depends on GENERIC_GPIO
+	select INPUT_POLLDEV
+	help
+	  This driver simulates a mouse on GPIO lines of various CPUs (and some
+	  other chips).
+
+	  Say Y here if your device has buttons or a simple joystick connected
+	  directly to GPIO lines. Your board-specific setup logic must also
+	  provide a platform device and platform data saying which GPIOs are
+	  used.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gpio_mouse.
+
 endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index aa4ba87..9e6e363 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o
 obj-$(CONFIG_MOUSE_HIL)		+= hil_ptr.o
 obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o
+obj-$(CONFIG_MOUSE_GPIO)	+= gpio_mouse.o
 
 psmouse-objs := psmouse-base.o synaptics.o
 
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index cf3e466..2c5f11a 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -251,11 +251,15 @@
 
 	dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
 
-	for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++);
-	*version = (param[0] << 8) | (param[1] << 4) | i;
+	if (version) {
+		for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++)
+			/* empty */;
+		*version = (param[0] << 8) | (param[1] << 4) | i;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(alps_model_data); i++)
-		if (!memcmp(param, alps_model_data[i].signature, sizeof(alps_model_data[i].signature)))
+		if (!memcmp(param, alps_model_data[i].signature,
+			    sizeof(alps_model_data[i].signature)))
 			return alps_model_data + i;
 
 	return NULL;
@@ -380,32 +384,46 @@
 	return 0;
 }
 
-static int alps_reconnect(struct psmouse *psmouse)
+static int alps_hw_init(struct psmouse *psmouse, int *version)
 {
 	struct alps_data *priv = psmouse->private;
-	int version;
 
-	psmouse_reset(psmouse);
-
-	if (!(priv->i = alps_get_model(psmouse, &version)))
+	priv->i = alps_get_model(psmouse, version);
+	if (!priv->i)
 		return -1;
 
 	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
 		return -1;
 
 	if (alps_tap_mode(psmouse, 1)) {
-		printk(KERN_WARNING "alps.c: Failed to reenable hardware tapping\n");
+		printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
 		return -1;
 	}
 
 	if (alps_absolute_mode(psmouse)) {
-		printk(KERN_ERR "alps.c: Failed to reenable absolute mode\n");
+		printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
 		return -1;
 	}
 
 	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
 		return -1;
 
+	/* ALPS needs stream mode, otherwise it won't report any data */
+	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
+		printk(KERN_ERR "alps.c: Failed to enable stream mode\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int alps_reconnect(struct psmouse *psmouse)
+{
+	psmouse_reset(psmouse);
+
+	if (alps_hw_init(psmouse, NULL))
+		return -1;
+
 	return 0;
 }
 
@@ -430,23 +448,9 @@
 		goto init_fail;
 
 	priv->dev2 = dev2;
+	psmouse->private = priv;
 
-	priv->i = alps_get_model(psmouse, &version);
-	if (!priv->i)
-		goto init_fail;
-
-	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
-		goto init_fail;
-
-	if (alps_tap_mode(psmouse, 1))
-		printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
-
-	if (alps_absolute_mode(psmouse)) {
-		printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
-		goto init_fail;
-	}
-
-	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
+	if (alps_hw_init(psmouse, &version))
 		goto init_fail;
 
 	dev1->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
@@ -493,13 +497,13 @@
 	/* We are having trouble resyncing ALPS touchpads so disable it for now */
 	psmouse->resync_time = 0;
 
-	psmouse->private = priv;
 	return 0;
 
 init_fail:
 	psmouse_reset(psmouse);
 	input_free_device(dev2);
 	kfree(priv);
+	psmouse->private = NULL;
 	return -1;
 }
 
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
new file mode 100644
index 0000000..0936d6b
--- /dev/null
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -0,0 +1,196 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/gpio_mouse.h>
+
+#include <asm/gpio.h>
+
+/*
+ * Timer function which is run every scan_ms ms when the device is opened.
+ * The dev input varaible is set to the the input_dev pointer.
+ */
+static void gpio_mouse_scan(struct input_polled_dev *dev)
+{
+	struct gpio_mouse_platform_data *gpio = dev->private;
+	struct input_dev *input = dev->input;
+	int x, y;
+
+	if (gpio->bleft >= 0)
+		input_report_key(input, BTN_LEFT,
+				gpio_get_value(gpio->bleft) ^ gpio->polarity);
+	if (gpio->bmiddle >= 0)
+		input_report_key(input, BTN_MIDDLE,
+				gpio_get_value(gpio->bmiddle) ^ gpio->polarity);
+	if (gpio->bright >= 0)
+		input_report_key(input, BTN_RIGHT,
+				gpio_get_value(gpio->bright) ^ gpio->polarity);
+
+	x = (gpio_get_value(gpio->right) ^ gpio->polarity)
+		- (gpio_get_value(gpio->left) ^ gpio->polarity);
+	y = (gpio_get_value(gpio->down) ^ gpio->polarity)
+		- (gpio_get_value(gpio->up) ^ gpio->polarity);
+
+	input_report_rel(input, REL_X, x);
+	input_report_rel(input, REL_Y, y);
+	input_sync(input);
+}
+
+static int __init gpio_mouse_probe(struct platform_device *pdev)
+{
+	struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
+	struct input_polled_dev *input_poll;
+	struct input_dev *input;
+	int pin, i;
+	int error;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data\n");
+		error = -ENXIO;
+		goto out;
+	}
+
+	if (pdata->scan_ms < 0) {
+		dev_err(&pdev->dev, "invalid scan time\n");
+		error = -EINVAL;
+		goto out;
+	}
+
+	for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+		pin = pdata->pins[i];
+
+		if (pin < 0) {
+
+			if (i <= GPIO_MOUSE_PIN_RIGHT) {
+				/* Mouse direction is required. */
+				dev_err(&pdev->dev,
+					"missing GPIO for directions\n");
+				error = -EINVAL;
+				goto out_free_gpios;
+			}
+
+			if (i == GPIO_MOUSE_PIN_BLEFT)
+				dev_dbg(&pdev->dev, "no left button defined\n");
+
+		} else {
+			error = gpio_request(pin, "gpio_mouse");
+			if (error) {
+				dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
+					pin, i);
+				goto out_free_gpios;
+			}
+
+			gpio_direction_input(pin);
+		}
+	}
+
+	input_poll = input_allocate_polled_device();
+	if (!input_poll) {
+		dev_err(&pdev->dev, "not enough memory for input device\n");
+		error = -ENOMEM;
+		goto out_free_gpios;
+	}
+
+	platform_set_drvdata(pdev, input_poll);
+
+	/* set input-polldev handlers */
+	input_poll->private = pdata;
+	input_poll->poll = gpio_mouse_scan;
+	input_poll->poll_interval = pdata->scan_ms;
+
+	input = input_poll->input;
+	input->name = pdev->name;
+	input->id.bustype = BUS_HOST;
+	input->dev.parent = &pdev->dev;
+
+	input_set_capability(input, EV_REL, REL_X);
+	input_set_capability(input, EV_REL, REL_Y);
+	if (pdata->bleft >= 0)
+		input_set_capability(input, EV_KEY, BTN_LEFT);
+	if (pdata->bmiddle >= 0)
+		input_set_capability(input, EV_KEY, BTN_MIDDLE);
+	if (pdata->bright >= 0)
+		input_set_capability(input, EV_KEY, BTN_RIGHT);
+
+	error = input_register_polled_device(input_poll);
+	if (error) {
+		dev_err(&pdev->dev, "could not register input device\n");
+		goto out_free_polldev;
+	}
+
+	dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",
+			pdata->scan_ms,
+			pdata->bleft < 0 ? "" : "left ",
+			pdata->bmiddle < 0 ? "" : "middle ",
+			pdata->bright < 0 ? "" : "right");
+
+	return 0;
+
+ out_free_polldev:
+	input_free_polled_device(input_poll);
+	platform_set_drvdata(pdev, NULL);
+
+ out_free_gpios:
+	while (--i >= 0) {
+		pin = pdata->pins[i];
+		if (pin)
+			gpio_free(pin);
+	}
+ out:
+	return error;
+}
+
+static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+{
+	struct input_polled_dev *input = platform_get_drvdata(pdev);
+	struct gpio_mouse_platform_data *pdata = input->private;
+	int pin, i;
+
+	input_unregister_polled_device(input);
+	input_free_polled_device(input);
+
+	for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+		pin = pdata->pins[i];
+		if (pin >= 0)
+			gpio_free(pin);
+	}
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+struct platform_driver gpio_mouse_device_driver = {
+	.remove		= __devexit_p(gpio_mouse_remove),
+	.driver		= {
+		.name	= "gpio_mouse",
+	}
+};
+
+static int __init gpio_mouse_init(void)
+{
+	return platform_driver_probe(&gpio_mouse_device_driver,
+			gpio_mouse_probe);
+}
+module_init(gpio_mouse_init);
+
+static void __exit gpio_mouse_exit(void)
+{
+	platform_driver_unregister(&gpio_mouse_device_driver);
+}
+module_exit(gpio_mouse_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("GPIO mouse driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 9df74b7..0c5660d 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -221,6 +221,7 @@
 		{ 66,	PS2PP_KIND_MX,					/* MX3100 reciver */
 				PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
 				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL },
+		{ 72,	PS2PP_KIND_TRACKMAN,	0 },			/* T-CH11: TrackMan Marble */
 		{ 73,	0,			PS2PP_SIDE_BTN },
 		{ 75,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
 		{ 76,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index f15f695..b9f0fb2 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -178,6 +178,15 @@
 	}
 
 /*
+ * Cortron PS2 Trackball reports SIDE button on the 4th bit of the first
+ * byte.
+ */
+	if (psmouse->type == PSMOUSE_CORTRON) {
+		input_report_key(dev, BTN_SIDE, (packet[0] >> 3) & 1);
+		packet[0] |= 0x08;
+	}
+
+/*
  * Generic PS/2 Mouse
  */
 
@@ -539,6 +548,20 @@
 	return 0;
 }
 
+/*
+ * Cortron PS/2 protocol detection. There's no special way to detect it, so it
+ * must be forced by sysfs protocol writing.
+ */
+static int cortron_detect(struct psmouse *psmouse, int set_properties)
+{
+	if (set_properties) {
+		psmouse->vendor = "Cortron";
+		psmouse->name = "PS/2 Trackball";
+		set_bit(BTN_SIDE, psmouse->dev->keybit);
+	}
+
+	return 0;
+}
 
 /*
  * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
@@ -740,6 +763,12 @@
 	},
 #endif
 	{
+		.type		= PSMOUSE_CORTRON,
+		.name		= "CortronPS/2",
+		.alias		= "cortps",
+		.detect		= cortron_detect,
+	},
+	{
 		.type		= PSMOUSE_AUTO,
 		.name		= "auto",
 		.alias		= "any",
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 3964e8a..1317bdd 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -88,6 +88,7 @@
 	PSMOUSE_LIFEBOOK,
 	PSMOUSE_TRACKPOINT,
 	PSMOUSE_TOUCHKIT_PS2,
+	PSMOUSE_CORTRON,
 	PSMOUSE_AUTO		/* This one should always be last */
 };
 
@@ -118,7 +119,6 @@
 		.attr	= {							\
 			.name	= __stringify(_name),				\
 			.mode	= _mode,					\
-			.owner	= THIS_MODULE,					\
 		},								\
 		.show	= psmouse_attr_show_helper,				\
 		.store	= psmouse_attr_set_helper,				\
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 8675f95..9173916 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -64,6 +64,7 @@
 	wait_queue_head_t wait;
 	struct list_head client_list;
 	struct input_handle handle;
+	struct device dev;
 
 	struct list_head mixdev_node;
 	int mixdev_open;
@@ -112,7 +113,7 @@
 static struct input_handler mousedev_handler;
 
 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
-static struct mousedev mousedev_mix;
+static struct mousedev *mousedev_mix;
 static LIST_HEAD(mousedev_mix_list);
 
 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
@@ -218,10 +219,10 @@
 
 	if (value) {
 		set_bit(index, &mousedev->packet.buttons);
-		set_bit(index, &mousedev_mix.packet.buttons);
+		set_bit(index, &mousedev_mix->packet.buttons);
 	} else {
 		clear_bit(index, &mousedev->packet.buttons);
-		clear_bit(index, &mousedev_mix.packet.buttons);
+		clear_bit(index, &mousedev_mix->packet.buttons);
 	}
 }
 
@@ -287,11 +288,11 @@
 			 * motion packet so we won't mess current position.
 			 */
 			set_bit(0, &mousedev->packet.buttons);
-			set_bit(0, &mousedev_mix.packet.buttons);
-			mousedev_notify_readers(mousedev, &mousedev_mix.packet);
-			mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
+			set_bit(0, &mousedev_mix->packet.buttons);
+			mousedev_notify_readers(mousedev, &mousedev_mix->packet);
+			mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
 			clear_bit(0, &mousedev->packet.buttons);
-			clear_bit(0, &mousedev_mix.packet.buttons);
+			clear_bit(0, &mousedev_mix->packet.buttons);
 		}
 		mousedev->touch = mousedev->pkt_count = 0;
 		mousedev->frac_dx = 0;
@@ -343,7 +344,7 @@
 				}
 
 				mousedev_notify_readers(mousedev, &mousedev->packet);
-				mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
+				mousedev_notify_readers(mousedev_mix, &mousedev->packet);
 
 				mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
 				mousedev->packet.abs_event = 0;
@@ -362,8 +363,10 @@
 	return retval < 0 ? retval : 0;
 }
 
-static void mousedev_free(struct mousedev *mousedev)
+static void mousedev_free(struct device *dev)
 {
+	struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
+
 	mousedev_table[mousedev->minor] = NULL;
 	kfree(mousedev);
 }
@@ -372,15 +375,16 @@
 {
 	int error;
 
-	if (mousedev_mix.open) {
+	if (mousedev_mix->open) {
 		error = input_open_device(&mousedev->handle);
 		if (error)
 			return error;
 
 		mousedev->open++;
-		mousedev->mixdev_open++;
+		mousedev->mixdev_open = 1;
 	}
 
+	get_device(&mousedev->dev);
 	list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
 
 	return 0;
@@ -395,36 +399,40 @@
 	}
 
 	list_del_init(&mousedev->mixdev_node);
+	put_device(&mousedev->dev);
 }
 
 static void mixdev_open_devices(void)
 {
 	struct mousedev *mousedev;
 
+	if (mousedev_mix->open++)
+		return;
+
 	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
-		if (mousedev->exist && !mousedev->open) {
-			if (input_open_device(&mousedev->handle))
-				continue;
+		if (!mousedev->mixdev_open) {
+			if (!mousedev->open && mousedev->exist)
+				if (input_open_device(&mousedev->handle))
+					continue;
 
 			mousedev->open++;
-			mousedev->mixdev_open++;
+			mousedev->mixdev_open = 1;
 		}
 	}
 }
 
 static void mixdev_close_devices(void)
 {
-	struct mousedev *mousedev, *next;
+	struct mousedev *mousedev;
 
-	list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+	if (--mousedev_mix->open)
+		return;
+
+	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
 		if (mousedev->mixdev_open) {
 			mousedev->mixdev_open = 0;
-			if (!--mousedev->open) {
-				if (mousedev->exist)
-					input_close_device(&mousedev->handle);
-				else
-					mousedev_free(mousedev);
-			}
+			if (!--mousedev->open && mousedev->exist)
+				input_close_device(&mousedev->handle);
 		}
 	}
 }
@@ -439,14 +447,12 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--mousedev->open) {
-		if (mousedev->minor == MOUSEDEV_MIX)
-			mixdev_close_devices();
-		else if (mousedev->exist)
-			input_close_device(&mousedev->handle);
-		else
-			mousedev_free(mousedev);
-	}
+	if (mousedev->minor == MOUSEDEV_MIX)
+		mixdev_close_devices();
+	else if (!--mousedev->open && mousedev->exist)
+		input_close_device(&mousedev->handle);
+
+	put_device(&mousedev->dev);
 
 	return 0;
 }
@@ -473,9 +479,13 @@
 	if (!mousedev)
 		return -ENODEV;
 
+	get_device(&mousedev->dev);
+
 	client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_mousedev;
+	}
 
 	spin_lock_init(&client->packet_lock);
 	client->pos_x = xres / 2;
@@ -483,21 +493,23 @@
 	client->mousedev = mousedev;
 	list_add_tail(&client->node, &mousedev->client_list);
 
-	if (!mousedev->open++) {
-		if (mousedev->minor == MOUSEDEV_MIX)
-			mixdev_open_devices();
-		else if (mousedev->exist) {
-			error = input_open_device(&mousedev->handle);
-			if (error) {
-				list_del(&client->node);
-				kfree(client);
-				return error;
-			}
-		}
+	if (mousedev->minor == MOUSEDEV_MIX)
+		mixdev_open_devices();
+	else if (!mousedev->open++ && mousedev->exist) {
+		error = input_open_device(&mousedev->handle);
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_mousedev:
+	put_device(&mousedev->dev);
+	return error;
 }
 
 static inline int mousedev_limit_delta(int delta, int limit)
@@ -680,12 +692,80 @@
 	.fasync =	mousedev_fasync,
 };
 
+static struct mousedev *mousedev_create(struct input_dev *dev,
+					struct input_handler *handler,
+					int minor)
+{
+	struct mousedev *mousedev;
+	int error;
+
+	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
+	if (!mousedev) {
+		error = -ENOMEM;
+		goto err_out;
+	}
+
+	INIT_LIST_HEAD(&mousedev->client_list);
+	INIT_LIST_HEAD(&mousedev->mixdev_node);
+	init_waitqueue_head(&mousedev->wait);
+
+	if (minor == MOUSEDEV_MIX)
+		strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
+	else
+		snprintf(mousedev->name, sizeof(mousedev->name),
+			 "mouse%d", minor);
+
+	mousedev->minor = minor;
+	mousedev->exist = 1;
+	mousedev->handle.dev = dev;
+	mousedev->handle.name = mousedev->name;
+	mousedev->handle.handler = handler;
+	mousedev->handle.private = mousedev;
+
+	strlcpy(mousedev->dev.bus_id, mousedev->name,
+		sizeof(mousedev->dev.bus_id));
+	mousedev->dev.class = &input_class;
+	if (dev)
+		mousedev->dev.parent = &dev->dev;
+	mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
+	mousedev->dev.release = mousedev_free;
+	device_initialize(&mousedev->dev);
+
+	mousedev_table[minor] = mousedev;
+
+	error = device_add(&mousedev->dev);
+	if (error)
+		goto err_free_mousedev;
+
+	return mousedev;
+
+ err_free_mousedev:
+	put_device(&mousedev->dev);
+ err_out:
+	return ERR_PTR(error);
+}
+
+static void mousedev_destroy(struct mousedev *mousedev)
+{
+	struct mousedev_client *client;
+
+	device_del(&mousedev->dev);
+	mousedev->exist = 0;
+
+	if (mousedev->open) {
+		input_close_device(&mousedev->handle);
+		list_for_each_entry(client, &mousedev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+		wake_up_interruptible(&mousedev->wait);
+	}
+
+	put_device(&mousedev->dev);
+}
+
 static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
 			    const struct input_device_id *id)
 {
 	struct mousedev *mousedev;
-	struct class_device *cdev;
-	dev_t devt;
 	int minor;
 	int error;
 
@@ -695,42 +775,13 @@
 		return -ENFILE;
 	}
 
-	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
-	if (!mousedev)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(&mousedev->client_list);
-	INIT_LIST_HEAD(&mousedev->mixdev_node);
-	init_waitqueue_head(&mousedev->wait);
-
-	mousedev->minor = minor;
-	mousedev->exist = 1;
-	mousedev->handle.dev = dev;
-	mousedev->handle.name = mousedev->name;
-	mousedev->handle.handler = handler;
-	mousedev->handle.private = mousedev;
-	sprintf(mousedev->name, "mouse%d", minor);
-
-	mousedev_table[minor] = mousedev;
-
-	devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-
-	cdev = class_device_create(&input_class, &dev->cdev, devt,
-				   dev->cdev.dev, mousedev->name);
-	if (IS_ERR(cdev)) {
-		error = PTR_ERR(cdev);
-		goto err_free_mousedev;
-	}
-
-	/* temporary symlink to keep userspace happy */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, mousedev->name);
-	if (error)
-		goto err_cdev_destroy;
+	mousedev = mousedev_create(dev, handler, minor);
+	if (IS_ERR(mousedev))
+		return PTR_ERR(mousedev);
 
 	error = input_register_handle(&mousedev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_mousedev;
 
 	error = mixdev_add_device(mousedev);
 	if (error)
@@ -740,37 +791,18 @@
 
  err_unregister_handle:
 	input_unregister_handle(&mousedev->handle);
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
- err_free_mousedev:
-	mousedev_table[minor] = NULL;
-	kfree(mousedev);
+ err_delete_mousedev:
+	device_unregister(&mousedev->dev);
 	return error;
 }
 
 static void mousedev_disconnect(struct input_handle *handle)
 {
 	struct mousedev *mousedev = handle->private;
-	struct mousedev_client *client;
-
-	input_unregister_handle(handle);
-
-	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
-	mousedev->exist = 0;
 
 	mixdev_remove_device(mousedev);
-
-	if (mousedev->open) {
-		input_close_device(handle);
-		wake_up_interruptible(&mousedev->wait);
-		list_for_each_entry(client, &mousedev->client_list, node)
-			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
-	} else
-		mousedev_free(mousedev);
+	input_unregister_handle(handle);
+	mousedev_destroy(mousedev);
 }
 
 static const struct input_device_id mousedev_ids[] = {
@@ -822,25 +854,16 @@
 
 static int __init mousedev_init(void)
 {
-	struct class_device *cdev;
 	int error;
 
+	mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
+	if (IS_ERR(mousedev_mix))
+		return PTR_ERR(mousedev_mix);
+
 	error = input_register_handler(&mousedev_handler);
-	if (error)
+	if (error) {
+		mousedev_destroy(mousedev_mix);
 		return error;
-
-	memset(&mousedev_mix, 0, sizeof(struct mousedev));
-	INIT_LIST_HEAD(&mousedev_mix.client_list);
-	init_waitqueue_head(&mousedev_mix.wait);
-	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
-	mousedev_mix.exist = 1;
-	mousedev_mix.minor = MOUSEDEV_MIX;
-
-	cdev = class_device_create(&input_class, NULL,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
-	if (IS_ERR(cdev)) {
-		input_unregister_handler(&mousedev_handler);
-		return PTR_ERR(cdev);
 	}
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -863,9 +886,8 @@
 	if (psaux_registered)
 		misc_deregister(&psaux_mouse);
 #endif
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
 	input_unregister_handler(&mousedev_handler);
+	mousedev_destroy(mousedev_mix);
 }
 
 module_init(mousedev_init);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 6858bc5..4fca1e7 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -69,6 +69,15 @@
 
 static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
 	{
+		/* AUX LOOP command does not raise AUX IRQ */
+		.ident = "ASUS P65UP5",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"),
+			DMI_MATCH(DMI_BOARD_VERSION, "REV 2.X"),
+		},
+	},
+	{
 		.ident = "Compaq Proliant 8500",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
@@ -92,6 +101,15 @@
 			DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
 		},
 	},
+	{
+		/* AUX LOOP does not work properly */
+		.ident = "ULI EV4873",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ULI"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+		},
+	},
 	{ }
 };
 
@@ -182,6 +200,17 @@
 		},
 	},
 	{
+		/*
+		 * Like DV4017EA does not raise AUXERR for errors on MUX ports.
+		 */
+		.ident = "HP Pavilion ZT1000",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
+		},
+	},
+	{
 		.ident = "Toshiba P10",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 5595087..d31ece8 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -170,7 +170,7 @@
 /*
  * Clear the input buffer.
  */
-static void __init ps2_clear_input(struct ps2if *ps2if)
+static void __devinit ps2_clear_input(struct ps2if *ps2if)
 {
 	int maxread = 100;
 
@@ -228,7 +228,7 @@
 /*
  * Add one device to this driver.
  */
-static int ps2_probe(struct sa1111_dev *dev)
+static int __devinit ps2_probe(struct sa1111_dev *dev)
 {
 	struct ps2if *ps2if;
 	struct serio *serio;
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 5895202..372ca49 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -384,6 +384,7 @@
 
 static int serio_thread(void *nothing)
 {
+	set_freezable();
 	do {
 		serio_handle_event();
 		wait_event_interruptible(serio_wait,
@@ -769,8 +770,10 @@
 
 static void serio_cleanup(struct serio *serio)
 {
+	mutex_lock(&serio->drv_mutex);
 	if (serio->drv && serio->drv->cleanup)
 		serio->drv->cleanup(serio);
+	mutex_unlock(&serio->drv_mutex);
 }
 
 static void serio_shutdown(struct device *dev)
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 8873576..0403622 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -160,7 +160,7 @@
 {
 	struct serio_raw_list *list = file->private_data;
 	struct serio_raw *serio_raw = list->serio_raw;
-	char c;
+	char uninitialized_var(c);
 	ssize_t retval = 0;
 
 	if (!serio_raw->serio)
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index cc0a498..94683f5 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -82,8 +82,8 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.5 (May-15-2004)"
-#define DRIVER_AUTHOR  "Bryan W. Headley/Chris Atenasio"
+#define DRIVER_VERSION "v2.3 (May 2, 2007)"
+#define DRIVER_AUTHOR  "Bryan W. Headley/Chris Atenasio/Cedric Brun/Rene van Paassen"
 #define DRIVER_DESC    "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)"
 
 /*
@@ -112,7 +112,7 @@
  * (returned as Report 3 - absolute coordinates from the mouse)
  *
  *        bit7  bit6  bit5  bit4  bit3  bit2  bit1  bit0
- * byte0   0     0     0     0     0     0     1     0
+ * byte0   0     0     0     0     0     0     1     1
  * byte1  X7    X6    X5    X4    X3    X2    X1    X0
  * byte2  X15   X14   X13   X12   X11   X10   X9    X8
  * byte3  Y7    Y6    Y5    Y4    Y3    Y2    Y1    Y0
@@ -134,7 +134,7 @@
  * (returned as Report 5 - macrokeys from the mouse)
  *
  *        bit7  bit6  bit5  bit4  bit3  bit2  bit1  bit0
- * byte0   0     0     0     0     0     1     0     0
+ * byte0   0     0     0     0     0     1     0     1
  * byte1   0     0     0    BS2   BS    Tip   IR    DV
  * byte2   0     0     0     0     0     0     1     0
  * byte3   0     0     0    K4    K3    K2    K1    K0
@@ -218,15 +218,9 @@
 #define AIPTEK_WHEEL_DISABLE				(-10101)
 
 	/* ToolCode values, which BTW are 0x140 .. 0x14f
-	 * We have things set up such that if TOOL_BUTTON_FIRED_BIT is
-	 * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx.
-	 *
-	 * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will
-	 * get reset.
+	 * We have things set up such that if the tool button has changed,
+	 * the tools get reset.
 	 */
-#define TOOL_BUTTON(x)					((x) & 0x14f)
-#define TOOL_BUTTON_FIRED(x)				((x) & 0x200)
-#define TOOL_BUTTON_FIRED_BIT				0x200
 	/* toolMode codes
 	 */
 #define AIPTEK_TOOL_BUTTON_PEN_MODE			BTN_TOOL_PEN
@@ -264,9 +258,9 @@
 
 	/* Mouse button programming
 	 */
-#define AIPTEK_MOUSE_LEFT_BUTTON		0x01
-#define AIPTEK_MOUSE_RIGHT_BUTTON		0x02
-#define AIPTEK_MOUSE_MIDDLE_BUTTON		0x04
+#define AIPTEK_MOUSE_LEFT_BUTTON		0x04
+#define AIPTEK_MOUSE_RIGHT_BUTTON		0x08
+#define AIPTEK_MOUSE_MIDDLE_BUTTON		0x10
 
 	/* Stylus button programming
 	 */
@@ -294,7 +288,6 @@
 	int modelCode;		/* Tablet model code (not unique) */
 	int firmwareCode;	/* prom/eeprom version            */
 	char usbPath[64 + 1];	/* device's physical usb path     */
-	char inputPath[64 + 1];	/* input device path              */
 };
 
 struct aiptek_settings {
@@ -327,9 +320,32 @@
 	int inDelay;				/* jitter: in jitter delay?      */
 	unsigned long endDelay;			/* jitter: time when delay ends  */
 	int previousJitterable;			/* jitterable prev value     */
+
+	int lastMacro;				/* macro key to reset            */
+	int previousToolMode;			/* pen, pencil, brush, etc. tool */
 	unsigned char *data;			/* incoming packet data          */
 };
 
+static const int eventTypes[] = {
+        EV_KEY, EV_ABS, EV_REL, EV_MSC,
+};
+
+static const int absEvents[] = {
+        ABS_X, ABS_Y, ABS_PRESSURE, ABS_TILT_X, ABS_TILT_Y,
+        ABS_WHEEL, ABS_MISC,
+};
+
+static const int relEvents[] = {
+        REL_X, REL_Y, REL_WHEEL,
+};
+
+static const int buttonEvents[] = {
+	BTN_LEFT, BTN_RIGHT, BTN_MIDDLE,
+	BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH,
+	BTN_TOOL_BRUSH, BTN_TOOL_MOUSE, BTN_TOOL_LENS, BTN_TOUCH,
+	BTN_STYLUS, BTN_STYLUS2,
+};
+
 /*
  * Permit easy lookup of keyboard events to send, versus
  * the bitmap which comes from the tablet. This hides the
@@ -345,23 +361,39 @@
 };
 
 /***********************************************************************
- * Relative reports deliver values in 2's complement format to
- * deal with negative offsets.
+ * Map values to strings and back. Every map shoudl have the following
+ * as its last element: { NULL, AIPTEK_INVALID_VALUE }.
  */
-static int aiptek_convert_from_2s_complement(unsigned char c)
-{
-	int ret;
-	unsigned char b = c;
-	int negate = 0;
+#define AIPTEK_INVALID_VALUE	-1
 
-	if ((b & 0x80) != 0) {
-		b = ~b;
-		b--;
-		negate = 1;
-	}
-	ret = b;
-	ret = (negate == 1) ? -ret : ret;
-	return ret;
+struct aiptek_map {
+	const char *string;
+	int value;
+};
+
+static int map_str_to_val(const struct aiptek_map *map, const char *str, size_t count)
+{
+	const struct aiptek_map *p;
+
+	if (str[count - 1] == '\n')
+		count--;
+
+	for (p = map; p->string; p++)
+	        if (!strncmp(str, p->string, count))
+			return p->value;
+
+	return AIPTEK_INVALID_VALUE;
+}
+
+static const char *map_val_to_str(const struct aiptek_map *map, int val)
+{
+	const struct aiptek_map *p;
+
+	for (p = map; p->value != AIPTEK_INVALID_VALUE; p++)
+		if (val == p->value)
+			return p->string;
+
+	return "unknown";
 }
 
 /***********************************************************************
@@ -385,6 +417,9 @@
  * Proximity. Why two events? I thought it interesting to know if the
  * Proximity event occurred while the tablet was in absolute or relative
  * mode.
+ * Update: REL_MISC proved not to be such a good idea. With REL_MISC you
+ * get an event transmitted each time. ABS_MISC works better, since it
+ * can be set and re-set. Thus, only using ABS_MISC from now on.
  *
  * Other tablets use the notion of a certain minimum stylus pressure
  * to infer proximity. While that could have been done, that is yet
@@ -441,8 +476,8 @@
 			aiptek->diagnostic =
 			    AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE;
 		} else {
-			x = aiptek_convert_from_2s_complement(data[2]);
-			y = aiptek_convert_from_2s_complement(data[3]);
+			x = (signed char) data[2];
+			y = (signed char) data[3];
 
 			/* jitterable keeps track of whether any button has been pressed.
 			 * We're also using it to remap the physical mouse button mask
@@ -451,18 +486,20 @@
 			 * that a non-zero value indicates that one or more
 			 * mouse button was pressed.)
 			 */
-			jitterable = data[5] & 0x07;
+			jitterable = data[1] & 0x07;
 
-			left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
-			right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
-			middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
+			left = (data[1] & aiptek->curSetting.mouseButtonLeft >> 2) != 0 ? 1 : 0;
+			right = (data[1] & aiptek->curSetting.mouseButtonRight >> 2) != 0 ? 1 : 0;
+			middle = (data[1] & aiptek->curSetting.mouseButtonMiddle >> 2) != 0 ? 1 : 0;
 
 			input_report_key(inputdev, BTN_LEFT, left);
 			input_report_key(inputdev, BTN_MIDDLE, middle);
 			input_report_key(inputdev, BTN_RIGHT, right);
+
+			input_report_abs(inputdev, ABS_MISC,
+					 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
 			input_report_rel(inputdev, REL_X, x);
 			input_report_rel(inputdev, REL_Y, y);
-			input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
 
 			/* Wheel support is in the form of a single-event
 			 * firing.
@@ -472,6 +509,11 @@
 						 aiptek->curSetting.wheel);
 				aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
 			}
+			if (aiptek->lastMacro != -1) {
+			        input_report_key(inputdev,
+						 macroKeyEvents[aiptek->lastMacro], 0);
+				aiptek->lastMacro = -1;
+			}
 			input_sync(inputdev);
 		}
 	}
@@ -489,8 +531,8 @@
 			y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
 			z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
 
-			p = (data[5] & 0x01) != 0 ? 1 : 0;
-			dv = (data[5] & 0x02) != 0 ? 1 : 0;
+			dv = (data[5] & 0x01) != 0 ? 1 : 0;
+			p = (data[5] & 0x02) != 0 ? 1 : 0;
 			tip = (data[5] & 0x04) != 0 ? 1 : 0;
 
 			/* Use jitterable to re-arrange button masks
@@ -505,16 +547,18 @@
 			 * all 'bad' reports...
 			 */
 			if (dv != 0) {
-				/* If we've not already sent a tool_button_?? code, do
-				 * so now. Then set FIRED_BIT so it won't be resent unless
-				 * the user forces FIRED_BIT off.
+				/* If the selected tool changed, reset the old
+				 * tool key, and set the new one.
 				 */
-				if (TOOL_BUTTON_FIRED
-				    (aiptek->curSetting.toolMode) == 0) {
+				if (aiptek->previousToolMode !=
+				    aiptek->curSetting.toolMode) {
+				        input_report_key(inputdev,
+							 aiptek->previousToolMode, 0);
 					input_report_key(inputdev,
-							 TOOL_BUTTON(aiptek->curSetting.toolMode),
+							 aiptek->curSetting.toolMode,
 							 1);
-					aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+					aiptek->previousToolMode =
+					          aiptek->curSetting.toolMode;
 				}
 
 				if (p != 0) {
@@ -550,6 +594,11 @@
 					}
 				}
 				input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS);
+				if (aiptek->lastMacro != -1) {
+			                input_report_key(inputdev,
+							 macroKeyEvents[aiptek->lastMacro], 0);
+					aiptek->lastMacro = -1;
+				}
 				input_sync(inputdev);
 			}
 		}
@@ -568,23 +617,25 @@
 
 			jitterable = data[5] & 0x1c;
 
-			p = (data[5] & 0x01) != 0 ? 1 : 0;
-			dv = (data[5] & 0x02) != 0 ? 1 : 0;
+			dv = (data[5] & 0x01) != 0 ? 1 : 0;
+			p = (data[5] & 0x02) != 0 ? 1 : 0;
 			left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
 			right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
 			middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
 
 			if (dv != 0) {
-				/* If we've not already sent a tool_button_?? code, do
-				 * so now. Then set FIRED_BIT so it won't be resent unless
-				 * the user forces FIRED_BIT off.
+				/* If the selected tool changed, reset the old
+				 * tool key, and set the new one.
 				 */
-				if (TOOL_BUTTON_FIRED
-				    (aiptek->curSetting.toolMode) == 0) {
+				if (aiptek->previousToolMode !=
+				    aiptek->curSetting.toolMode) {
+				        input_report_key(inputdev,
+							 aiptek->previousToolMode, 0);
 					input_report_key(inputdev,
-							 TOOL_BUTTON(aiptek->curSetting.toolMode),
+							 aiptek->curSetting.toolMode,
 							 1);
-					aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+					aiptek->previousToolMode =
+					          aiptek->curSetting.toolMode;
 				}
 
 				if (p != 0) {
@@ -605,7 +656,12 @@
 						aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
 					}
 				}
-				input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+				input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+				if (aiptek->lastMacro != -1) {
+			                input_report_key(inputdev,
+							 macroKeyEvents[aiptek->lastMacro], 0);
+				        aiptek->lastMacro = -1;
+				}
 				input_sync(inputdev);
 			}
 		}
@@ -615,98 +671,83 @@
 	else if (data[0] == 4) {
 		jitterable = data[1] & 0x18;
 
-		p = (data[1] & 0x01) != 0 ? 1 : 0;
-		dv = (data[1] & 0x02) != 0 ? 1 : 0;
+		dv = (data[1] & 0x01) != 0 ? 1 : 0;
+		p = (data[1] & 0x02) != 0 ? 1 : 0;
 		tip = (data[1] & 0x04) != 0 ? 1 : 0;
 		bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0;
 		pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
 
-		macro = data[3];
+		macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
 		z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
 
-		if (dv != 0) {
-			/* If we've not already sent a tool_button_?? code, do
-			 * so now. Then set FIRED_BIT so it won't be resent unless
-			 * the user forces FIRED_BIT off.
+		if (dv) {
+		        /* If the selected tool changed, reset the old
+			 * tool key, and set the new one.
 			 */
-			if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+		        if (aiptek->previousToolMode !=
+			    aiptek->curSetting.toolMode) {
+			        input_report_key(inputdev,
+						 aiptek->previousToolMode, 0);
 				input_report_key(inputdev,
-						 TOOL_BUTTON(aiptek->curSetting.toolMode),
+						 aiptek->curSetting.toolMode,
 						 1);
-				aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+				aiptek->previousToolMode =
+				        aiptek->curSetting.toolMode;
 			}
-
-			if (p != 0) {
-				input_report_key(inputdev, BTN_TOUCH, tip);
-				input_report_key(inputdev, BTN_STYLUS, bs);
-				input_report_key(inputdev, BTN_STYLUS2, pck);
-				input_report_abs(inputdev, ABS_PRESSURE, z);
-			}
-
-			/* For safety, we're sending key 'break' codes for the
-			 * neighboring macro keys.
-			 */
-			if (macro > 0) {
-				input_report_key(inputdev,
-						 macroKeyEvents[macro - 1], 0);
-			}
-			if (macro < 25) {
-				input_report_key(inputdev,
-						 macroKeyEvents[macro + 1], 0);
-			}
-			input_report_key(inputdev, macroKeyEvents[macro], p);
-			input_report_abs(inputdev, ABS_MISC,
-					 p | AIPTEK_REPORT_TOOL_STYLUS);
-			input_sync(inputdev);
 		}
+
+		if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+		        input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+			aiptek->lastMacro = -1;
+		}
+
+		if (macro != -1 && macro != aiptek->lastMacro) {
+			input_report_key(inputdev, macroKeyEvents[macro], 1);
+			aiptek->lastMacro = macro;
+		}
+		input_report_abs(inputdev, ABS_MISC,
+				 p | AIPTEK_REPORT_TOOL_STYLUS);
+		input_sync(inputdev);
 	}
 	/* Report 5s come from the macro keys when pressed by mouse
 	 */
 	else if (data[0] == 5) {
 		jitterable = data[1] & 0x1c;
 
-		p = (data[1] & 0x01) != 0 ? 1 : 0;
-		dv = (data[1] & 0x02) != 0 ? 1 : 0;
+		dv = (data[1] & 0x01) != 0 ? 1 : 0;
+		p = (data[1] & 0x02) != 0 ? 1 : 0;
 		left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
 		right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
 		middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
-		macro = data[3];
+		macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0;
 
-		if (dv != 0) {
-			/* If we've not already sent a tool_button_?? code, do
-			 * so now. Then set FIRED_BIT so it won't be resent unless
-			 * the user forces FIRED_BIT off.
+		if (dv) {
+		        /* If the selected tool changed, reset the old
+			 * tool key, and set the new one.
 			 */
-			if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
-				input_report_key(inputdev,
-						 TOOL_BUTTON(aiptek->curSetting.toolMode),
-						 1);
-				aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+		        if (aiptek->previousToolMode !=
+			    aiptek->curSetting.toolMode) {
+		                input_report_key(inputdev,
+						 aiptek->previousToolMode, 0);
+			        input_report_key(inputdev,
+						 aiptek->curSetting.toolMode, 1);
+			        aiptek->previousToolMode = aiptek->curSetting.toolMode;
 			}
-
-			if (p != 0) {
-				input_report_key(inputdev, BTN_LEFT, left);
-				input_report_key(inputdev, BTN_MIDDLE, middle);
-				input_report_key(inputdev, BTN_RIGHT, right);
-			}
-
-			/* For safety, we're sending key 'break' codes for the
-			 * neighboring macro keys.
-			 */
-			if (macro > 0) {
-				input_report_key(inputdev,
-						 macroKeyEvents[macro - 1], 0);
-			}
-			if (macro < 25) {
-				input_report_key(inputdev,
-						 macroKeyEvents[macro + 1], 0);
-			}
-
-			input_report_key(inputdev, macroKeyEvents[macro], 1);
-			input_report_rel(inputdev, ABS_MISC,
-					 p | AIPTEK_REPORT_TOOL_MOUSE);
-			input_sync(inputdev);
 		}
+
+		if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+		        input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+			aiptek->lastMacro = -1;
+		}
+
+		if (macro != -1 && macro != aiptek->lastMacro) {
+			input_report_key(inputdev, macroKeyEvents[macro], 1);
+			aiptek->lastMacro = macro;
+		}
+
+		input_report_abs(inputdev, ABS_MISC,
+				 p | AIPTEK_REPORT_TOOL_MOUSE);
+		input_sync(inputdev);
 	}
 	/* We have no idea which tool can generate a report 6. Theoretically,
 	 * neither need to, having been given reports 4 & 5 for such use.
@@ -725,15 +766,18 @@
 					 0);
 		}
 
-		/* If we've not already sent a tool_button_?? code, do
-		 * so now. Then set FIRED_BIT so it won't be resent unless
-		 * the user forces FIRED_BIT off.
-		 */
-		if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+		/* If the selected tool changed, reset the old
+		   tool key, and set the new one.
+		*/
+		if (aiptek->previousToolMode !=
+		    aiptek->curSetting.toolMode) {
+		        input_report_key(inputdev,
+					 aiptek->previousToolMode, 0);
 			input_report_key(inputdev,
-					 TOOL_BUTTON(aiptek->curSetting.
-						     toolMode), 1);
-			aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+					 aiptek->curSetting.toolMode,
+					 1);
+			aiptek->previousToolMode =
+				aiptek->curSetting.toolMode;
 		}
 
 		input_report_key(inputdev, macroKeyEvents[macro], 1);
@@ -1007,9 +1051,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%dx%d\n",
 			aiptek->inputdev->absmax[ABS_X] + 1,
 			aiptek->inputdev->absmax[ABS_Y] + 1);
@@ -1024,117 +1065,35 @@
 static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL);
 
 /***********************************************************************
- * support routines for the 'product_id' file
- */
-static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-
-	if (aiptek == NULL)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "0x%04x\n",
-			aiptek->inputdev->id.product);
-}
-
-static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor_id' file
- */
-static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-
-	if (aiptek == NULL)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);
-}
-
-static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor' file
- */
-static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-	int retval;
-
-	if (aiptek == NULL)
-		return 0;
-
-	retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer);
-	return retval;
-}
-
-static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL);
-
-/***********************************************************************
- * support routines for the 'product' file
- */
-static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-	int retval;
-
-	if (aiptek == NULL)
-		return 0;
-
-	retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product);
-	return retval;
-}
-
-static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL);
-
-/***********************************************************************
  * support routines for the 'pointer_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
+static struct aiptek_map pointer_mode_map[] = {
+	{ "stylus",	AIPTEK_POINTER_ONLY_STYLUS_MODE },
+	{ "mouse",	AIPTEK_POINTER_ONLY_MOUSE_MODE },
+	{ "either",	AIPTEK_POINTER_EITHER_MODE },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.pointerMode) {
-	case AIPTEK_POINTER_ONLY_STYLUS_MODE:
-		s = "stylus";
-		break;
-
-	case AIPTEK_POINTER_ONLY_MOUSE_MODE:
-		s = "mouse";
-		break;
-
-	case AIPTEK_POINTER_EITHER_MODE:
-		s = "either";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(pointer_mode_map,
+					aiptek->curSetting.pointerMode));
 }
 
 static ssize_t
 store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	if (aiptek == NULL)
-		return 0;
+	int new_mode = map_str_to_val(pointer_mode_map, buf, count);
 
-	if (strcmp(buf, "stylus") == 0) {
-		aiptek->newSetting.pointerMode =
-		    AIPTEK_POINTER_ONLY_STYLUS_MODE;
-	} else if (strcmp(buf, "mouse") == 0) {
-		aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE;
-	} else if (strcmp(buf, "either") == 0) {
-		aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE;
-	}
+	if (new_mode == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
+
+	aiptek->newSetting.pointerMode = new_mode;
 	return count;
 }
 
@@ -1146,44 +1105,32 @@
  * support routines for the 'coordinate_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
+
+static struct aiptek_map coordinate_mode_map[] = {
+	{ "absolute",	AIPTEK_COORDINATE_ABSOLUTE_MODE },
+	{ "relative",	AIPTEK_COORDINATE_RELATIVE_MODE },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.coordinateMode) {
-	case AIPTEK_COORDINATE_ABSOLUTE_MODE:
-		s = "absolute";
-		break;
-
-	case AIPTEK_COORDINATE_RELATIVE_MODE:
-		s = "relative";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(coordinate_mode_map,
+					aiptek->curSetting.coordinateMode));
 }
 
 static ssize_t
 store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	if (aiptek == NULL)
-		return 0;
+	int new_mode = map_str_to_val(coordinate_mode_map, buf, count);
 
-	if (strcmp(buf, "absolute") == 0) {
-		aiptek->newSetting.pointerMode =
-		    AIPTEK_COORDINATE_ABSOLUTE_MODE;
-	} else if (strcmp(buf, "relative") == 0) {
-		aiptek->newSetting.pointerMode =
-		    AIPTEK_COORDINATE_RELATIVE_MODE;
-	}
+	if (new_mode == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
+
+	aiptek->newSetting.coordinateMode = new_mode;
 	return count;
 }
 
@@ -1195,73 +1142,37 @@
  * support routines for the 'tool_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
+
+static struct aiptek_map tool_mode_map[] = {
+	{ "mouse",	AIPTEK_TOOL_BUTTON_MOUSE_MODE },
+	{ "eraser",	AIPTEK_TOOL_BUTTON_ERASER_MODE },
+	{ "pencil",	AIPTEK_TOOL_BUTTON_PENCIL_MODE },
+	{ "pen",	AIPTEK_TOOL_BUTTON_PEN_MODE },
+	{ "brush",	AIPTEK_TOOL_BUTTON_BRUSH_MODE },
+	{ "airbrush",	AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE },
+	{ "lens",	AIPTEK_TOOL_BUTTON_LENS_MODE },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) {
-	case AIPTEK_TOOL_BUTTON_MOUSE_MODE:
-		s = "mouse";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_ERASER_MODE:
-		s = "eraser";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_PENCIL_MODE:
-		s = "pencil";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_PEN_MODE:
-		s = "pen";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_BRUSH_MODE:
-		s = "brush";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE:
-		s = "airbrush";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_LENS_MODE:
-		s = "lens";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(tool_mode_map,
+					aiptek->curSetting.toolMode));
 }
 
 static ssize_t
 store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	if (aiptek == NULL)
-		return 0;
+	int new_mode = map_str_to_val(tool_mode_map, buf, count);
 
-	if (strcmp(buf, "mouse") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE;
-	} else if (strcmp(buf, "eraser") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE;
-	} else if (strcmp(buf, "pencil") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE;
-	} else if (strcmp(buf, "pen") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE;
-	} else if (strcmp(buf, "brush") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE;
-	} else if (strcmp(buf, "airbrush") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE;
-	} else if (strcmp(buf, "lens") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE;
-	}
+	if (new_mode == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
+	aiptek->newSetting.toolMode = new_mode;
 	return count;
 }
 
@@ -1277,9 +1188,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) {
 		return snprintf(buf, PAGE_SIZE, "disable\n");
 	} else {
@@ -1294,9 +1202,6 @@
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	int x;
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (strcmp(buf, "disable") == 0) {
 		aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE;
 	} else {
@@ -1319,9 +1224,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) {
 		return snprintf(buf, PAGE_SIZE, "disable\n");
 	} else {
@@ -1336,9 +1238,6 @@
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	int y;
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (strcmp(buf, "disable") == 0) {
 		aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE;
 	} else {
@@ -1361,9 +1260,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay);
 }
 
@@ -1372,9 +1268,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10);
 	return count;
 }
@@ -1391,9 +1284,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			aiptek->curSetting.programmableDelay);
 }
@@ -1403,9 +1293,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10);
 	return count;
 }
@@ -1415,23 +1302,6 @@
 		   show_tabletProgrammableDelay, store_tabletProgrammableDelay);
 
 /***********************************************************************
- * support routines for the 'input_path' file. Note that this file
- * only displays current setting.
- */
-static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-
-	if (aiptek == NULL)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n",
-			aiptek->features.inputPath);
-}
-
-static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL);
-
-/***********************************************************************
  * support routines for the 'event_count' file. Note that this file
  * only displays current setting.
  */
@@ -1439,9 +1309,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount);
 }
 
@@ -1456,9 +1323,6 @@
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *retMsg;
 
-	if (aiptek == NULL)
-		return 0;
-
 	switch (aiptek->diagnostic) {
 	case AIPTEK_DIAGNOSTIC_NA:
 		retMsg = "no errors\n";
@@ -1493,45 +1357,32 @@
  * support routines for the 'stylus_upper' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
+
+static struct aiptek_map stylus_button_map[] = {
+	{ "upper",	AIPTEK_STYLUS_UPPER_BUTTON },
+	{ "lower",	AIPTEK_STYLUS_LOWER_BUTTON },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.stylusButtonUpper) {
-	case AIPTEK_STYLUS_UPPER_BUTTON:
-		s = "upper";
-		break;
-
-	case AIPTEK_STYLUS_LOWER_BUTTON:
-		s = "lower";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(stylus_button_map,
+					aiptek->curSetting.stylusButtonUpper));
 }
 
 static ssize_t
 store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(stylus_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "upper") == 0) {
-		aiptek->newSetting.stylusButtonUpper =
-		    AIPTEK_STYLUS_UPPER_BUTTON;
-	} else if (strcmp(buf, "lower") == 0) {
-		aiptek->newSetting.stylusButtonUpper =
-		    AIPTEK_STYLUS_LOWER_BUTTON;
-	}
+	aiptek->newSetting.stylusButtonUpper = new_button;
 	return count;
 }
 
@@ -1543,45 +1394,26 @@
  * support routines for the 'stylus_lower' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
+
 static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.stylusButtonLower) {
-	case AIPTEK_STYLUS_UPPER_BUTTON:
-		s = "upper";
-		break;
-
-	case AIPTEK_STYLUS_LOWER_BUTTON:
-		s = "lower";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(stylus_button_map,
+					aiptek->curSetting.stylusButtonLower));
 }
 
 static ssize_t
 store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(stylus_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "upper") == 0) {
-		aiptek->newSetting.stylusButtonLower =
-		    AIPTEK_STYLUS_UPPER_BUTTON;
-	} else if (strcmp(buf, "lower") == 0) {
-		aiptek->newSetting.stylusButtonLower =
-		    AIPTEK_STYLUS_LOWER_BUTTON;
-	}
+	aiptek->newSetting.stylusButtonLower = new_button;
 	return count;
 }
 
@@ -1593,49 +1425,33 @@
  * support routines for the 'mouse_left' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
+
+static struct aiptek_map mouse_button_map[] = {
+	{ "left",	AIPTEK_MOUSE_LEFT_BUTTON },
+	{ "middle",	AIPTEK_MOUSE_MIDDLE_BUTTON },
+	{ "right",	AIPTEK_MOUSE_RIGHT_BUTTON },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.mouseButtonLeft) {
-	case AIPTEK_MOUSE_LEFT_BUTTON:
-		s = "left";
-		break;
-
-	case AIPTEK_MOUSE_MIDDLE_BUTTON:
-		s = "middle";
-		break;
-
-	case AIPTEK_MOUSE_RIGHT_BUTTON:
-		s = "right";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(mouse_button_map,
+					aiptek->curSetting.mouseButtonLeft));
 }
 
 static ssize_t
 store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(mouse_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "left") == 0) {
-		aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON;
-	} else if (strcmp(buf, "middle") == 0) {
-		aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON;
-	} else if (strcmp(buf, "right") == 0) {
-		aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON;
-	}
+	aiptek->newSetting.mouseButtonLeft = new_button;
 	return count;
 }
 
@@ -1650,48 +1466,22 @@
 static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.mouseButtonMiddle) {
-	case AIPTEK_MOUSE_LEFT_BUTTON:
-		s = "left";
-		break;
-
-	case AIPTEK_MOUSE_MIDDLE_BUTTON:
-		s = "middle";
-		break;
-
-	case AIPTEK_MOUSE_RIGHT_BUTTON:
-		s = "right";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(mouse_button_map,
+					aiptek->curSetting.mouseButtonMiddle));
 }
 
 static ssize_t
 store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(mouse_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "left") == 0) {
-		aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON;
-	} else if (strcmp(buf, "middle") == 0) {
-		aiptek->newSetting.mouseButtonMiddle =
-		    AIPTEK_MOUSE_MIDDLE_BUTTON;
-	} else if (strcmp(buf, "right") == 0) {
-		aiptek->newSetting.mouseButtonMiddle =
-		    AIPTEK_MOUSE_RIGHT_BUTTON;
-	}
+	aiptek->newSetting.mouseButtonMiddle = new_button;
 	return count;
 }
 
@@ -1706,47 +1496,22 @@
 static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.mouseButtonRight) {
-	case AIPTEK_MOUSE_LEFT_BUTTON:
-		s = "left";
-		break;
-
-	case AIPTEK_MOUSE_MIDDLE_BUTTON:
-		s = "middle";
-		break;
-
-	case AIPTEK_MOUSE_RIGHT_BUTTON:
-		s = "right";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(mouse_button_map,
+					aiptek->curSetting.mouseButtonRight));
 }
 
 static ssize_t
 store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(mouse_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "left") == 0) {
-		aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON;
-	} else if (strcmp(buf, "middle") == 0) {
-		aiptek->newSetting.mouseButtonRight =
-		    AIPTEK_MOUSE_MIDDLE_BUTTON;
-	} else if (strcmp(buf, "right") == 0) {
-		aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON;
-	}
+	aiptek->newSetting.mouseButtonRight = new_button;
 	return count;
 }
 
@@ -1762,9 +1527,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {
 		return snprintf(buf, PAGE_SIZE, "disable\n");
 	} else {
@@ -1778,9 +1540,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);
 	return count;
 }
@@ -1794,11 +1553,6 @@
  */
 static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-
-	if (aiptek == NULL)
-		return 0;
-
 	/* There is nothing useful to display, so a one-line manual
 	 * is in order...
 	 */
@@ -1811,9 +1565,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	/* We do not care what you write to this file. Merely the action
 	 * of writing to this file triggers a tablet reprogramming.
 	 */
@@ -1837,9 +1588,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode);
 }
 
@@ -1853,9 +1601,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode);
 }
 
@@ -1869,86 +1614,39 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%04x\n",
 			aiptek->features.firmwareCode);
 }
 
 static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);
 
-/***********************************************************************
- * This routine removes all existing sysfs files managed by this device
- * driver.
- */
-static void aiptek_delete_files(struct device *dev)
-{
-	device_remove_file(dev, &dev_attr_size);
-	device_remove_file(dev, &dev_attr_product_id);
-	device_remove_file(dev, &dev_attr_vendor_id);
-	device_remove_file(dev, &dev_attr_vendor);
-	device_remove_file(dev, &dev_attr_product);
-	device_remove_file(dev, &dev_attr_pointer_mode);
-	device_remove_file(dev, &dev_attr_coordinate_mode);
-	device_remove_file(dev, &dev_attr_tool_mode);
-	device_remove_file(dev, &dev_attr_xtilt);
-	device_remove_file(dev, &dev_attr_ytilt);
-	device_remove_file(dev, &dev_attr_jitter);
-	device_remove_file(dev, &dev_attr_delay);
-	device_remove_file(dev, &dev_attr_input_path);
-	device_remove_file(dev, &dev_attr_event_count);
-	device_remove_file(dev, &dev_attr_diagnostic);
-	device_remove_file(dev, &dev_attr_odm_code);
-	device_remove_file(dev, &dev_attr_model_code);
-	device_remove_file(dev, &dev_attr_firmware_code);
-	device_remove_file(dev, &dev_attr_stylus_lower);
-	device_remove_file(dev, &dev_attr_stylus_upper);
-	device_remove_file(dev, &dev_attr_mouse_left);
-	device_remove_file(dev, &dev_attr_mouse_middle);
-	device_remove_file(dev, &dev_attr_mouse_right);
-	device_remove_file(dev, &dev_attr_wheel);
-	device_remove_file(dev, &dev_attr_execute);
-}
+static struct attribute *aiptek_attributes[] = {
+	&dev_attr_size.attr,
+	&dev_attr_pointer_mode.attr,
+	&dev_attr_coordinate_mode.attr,
+	&dev_attr_tool_mode.attr,
+	&dev_attr_xtilt.attr,
+	&dev_attr_ytilt.attr,
+	&dev_attr_jitter.attr,
+	&dev_attr_delay.attr,
+	&dev_attr_event_count.attr,
+	&dev_attr_diagnostic.attr,
+	&dev_attr_odm_code.attr,
+	&dev_attr_model_code.attr,
+	&dev_attr_firmware_code.attr,
+	&dev_attr_stylus_lower.attr,
+	&dev_attr_stylus_upper.attr,
+	&dev_attr_mouse_left.attr,
+	&dev_attr_mouse_middle.attr,
+	&dev_attr_mouse_right.attr,
+	&dev_attr_wheel.attr,
+	&dev_attr_execute.attr,
+	NULL
+};
 
-/***********************************************************************
- * This routine creates the sysfs files managed by this device
- * driver.
- */
-static int aiptek_add_files(struct device *dev)
-{
-	int ret;
-
-	if ((ret = device_create_file(dev, &dev_attr_size)) ||
-	    (ret = device_create_file(dev, &dev_attr_product_id)) ||
-	    (ret = device_create_file(dev, &dev_attr_vendor_id)) ||
-	    (ret = device_create_file(dev, &dev_attr_vendor)) ||
-	    (ret = device_create_file(dev, &dev_attr_product)) ||
-	    (ret = device_create_file(dev, &dev_attr_pointer_mode)) ||
-	    (ret = device_create_file(dev, &dev_attr_coordinate_mode)) ||
-	    (ret = device_create_file(dev, &dev_attr_tool_mode)) ||
-	    (ret = device_create_file(dev, &dev_attr_xtilt)) ||
-	    (ret = device_create_file(dev, &dev_attr_ytilt)) ||
-	    (ret = device_create_file(dev, &dev_attr_jitter)) ||
-	    (ret = device_create_file(dev, &dev_attr_delay)) ||
-	    (ret = device_create_file(dev, &dev_attr_input_path)) ||
-	    (ret = device_create_file(dev, &dev_attr_event_count)) ||
-	    (ret = device_create_file(dev, &dev_attr_diagnostic)) ||
-	    (ret = device_create_file(dev, &dev_attr_odm_code)) ||
-	    (ret = device_create_file(dev, &dev_attr_model_code)) ||
-	    (ret = device_create_file(dev, &dev_attr_firmware_code)) ||
-	    (ret = device_create_file(dev, &dev_attr_stylus_lower)) ||
-	    (ret = device_create_file(dev, &dev_attr_stylus_upper)) ||
-	    (ret = device_create_file(dev, &dev_attr_mouse_left)) ||
-	    (ret = device_create_file(dev, &dev_attr_mouse_middle)) ||
-	    (ret = device_create_file(dev, &dev_attr_mouse_right)) ||
-	    (ret = device_create_file(dev, &dev_attr_wheel)) ||
-	    (ret = device_create_file(dev, &dev_attr_execute))) {
-		err("aiptek: killing own sysfs device files\n");
-		aiptek_delete_files(dev);
-	}
-	return ret;
-}
+static struct attribute_group aiptek_attribute_group = {
+	.attrs	= aiptek_attributes,
+};
 
 /***********************************************************************
  * This routine is called when a tablet has been identified. It basically
@@ -1961,8 +1659,6 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct aiptek *aiptek;
 	struct input_dev *inputdev;
-	struct input_handle *inputhandle;
-	struct list_head *node, *next;
 	int i;
 	int speeds[] = { 0,
 		AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -1984,17 +1680,23 @@
 
 	aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
 	inputdev = input_allocate_device();
-	if (!aiptek || !inputdev)
+	if (!aiptek || !inputdev) {
+		warn("aiptek: cannot allocate memory or input device");
 		goto fail1;
+        }
 
 	aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
 					GFP_ATOMIC, &aiptek->data_dma);
-	if (!aiptek->data)
+        if (!aiptek->data) {
+		warn("aiptek: cannot allocate usb buffer");
 		goto fail1;
+	}
 
 	aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!aiptek->urb)
+	if (!aiptek->urb) {
+	        warn("aiptek: cannot allocate urb");
 		goto fail2;
+	}
 
 	aiptek->inputdev = inputdev;
 	aiptek->usbdev = usbdev;
@@ -2002,6 +1704,7 @@
 	aiptek->inDelay = 0;
 	aiptek->endDelay = 0;
 	aiptek->previousJitterable = 0;
+	aiptek->lastMacro = -1;
 
 	/* Set up the curSettings struct. Said struct contains the current
 	 * programmable parameters. The newSetting struct contains changes
@@ -2054,36 +1757,23 @@
 	/* Now program the capacities of the tablet, in terms of being
 	 * an input device.
 	 */
-	inputdev->evbit[0] |= BIT(EV_KEY)
-	    | BIT(EV_ABS)
-	    | BIT(EV_REL)
-	    | BIT(EV_MSC);
+	for (i = 0; i < ARRAY_SIZE(eventTypes); ++i)
+	        __set_bit(eventTypes[i], inputdev->evbit);
 
-	inputdev->absbit[0] |= BIT(ABS_MISC);
+	for (i = 0; i < ARRAY_SIZE(absEvents); ++i)
+	        __set_bit(absEvents[i], inputdev->absbit);
 
-	inputdev->relbit[0] |=
-	    (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
+	for (i = 0; i < ARRAY_SIZE(relEvents); ++i)
+	        __set_bit(relEvents[i], inputdev->relbit);
 
-	inputdev->keybit[LONG(BTN_LEFT)] |=
-	    (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
+	__set_bit(MSC_SERIAL, inputdev->mscbit);
 
-	inputdev->keybit[LONG(BTN_DIGI)] |=
-	    (BIT(BTN_TOOL_PEN) |
-	     BIT(BTN_TOOL_RUBBER) |
-	     BIT(BTN_TOOL_PENCIL) |
-	     BIT(BTN_TOOL_AIRBRUSH) |
-	     BIT(BTN_TOOL_BRUSH) |
-	     BIT(BTN_TOOL_MOUSE) |
-	     BIT(BTN_TOOL_LENS) |
-	     BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
+	/* Set up key and button codes */
+	for (i = 0; i < ARRAY_SIZE(buttonEvents); ++i)
+		__set_bit(buttonEvents[i], inputdev->keybit);
 
-	inputdev->mscbit[0] = BIT(MSC_SERIAL);
-
-	/* Programming the tablet macro keys needs to be done with a for loop
-	 * as the keycodes are discontiguous.
-	 */
 	for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
-		set_bit(macroKeyEvents[i], inputdev->keybit);
+		__set_bit(macroKeyEvents[i], inputdev->keybit);
 
 	/*
 	 * Program the input device coordinate capacities. We do not yet
@@ -2134,25 +1824,11 @@
 		}
 	}
 
-	/* Register the tablet as an Input Device
-	 */
-	err = input_register_device(aiptek->inputdev);
-	if (err)
+	/* Murphy says that some day someone will have a tablet that fails the
+	   above test. That's you, Frederic Rodrigo */
+	if (i == ARRAY_SIZE(speeds)) {
+		info("input: Aiptek tried all speeds, no sane response");
 		goto fail2;
-
-	/* We now will look for the evdev device which is mapped to
-	 * the tablet. The partial name is kept in the link list of
-	 * input_handles associated with this input device.
-	 * What identifies an evdev input_handler is that it begins
-	 * with 'event', continues with a digit, and that in turn
-	 * is mapped to input/eventN.
-	 */
-	list_for_each_safe(node, next, &inputdev->h_list) {
-		inputhandle = to_handle(node);
-		if (strncmp(inputhandle->name, "event", 5) == 0) {
-			strcpy(aiptek->features.inputPath, inputhandle->name);
-			break;
-		}
 	}
 
 	/* Associate this driver's struct with the usb interface.
@@ -2161,18 +1837,27 @@
 
 	/* Set up the sysfs files
 	 */
-	aiptek_add_files(&intf->dev);
+	err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);
+	if (err) {
+		warn("aiptek: cannot create sysfs group err: %d", err);
+		goto fail3;
+        }
 
-	/* Make sure the evdev module is loaded. Assuming evdev IS a module :-)
+	/* Register the tablet as an Input Device
 	 */
-	if (request_module("evdev") != 0)
-		info("aiptek: error loading 'evdev' module");
-
+	err = input_register_device(aiptek->inputdev);
+	if (err) {
+		warn("aiptek: input_register_device returned err: %d", err);
+		goto fail4;
+        }
 	return 0;
 
+ fail4:	sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
+ fail3: usb_free_urb(aiptek->urb);
  fail2:	usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
 			aiptek->data_dma);
- fail1:	input_free_device(inputdev);
+ fail1: usb_set_intfdata(intf, NULL);
+	input_free_device(inputdev);
 	kfree(aiptek);
 	return err;
 }
@@ -2192,7 +1877,7 @@
 		 */
 		usb_kill_urb(aiptek->urb);
 		input_unregister_device(aiptek->inputdev);
-		aiptek_delete_files(&intf->dev);
+		sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
 		usb_free_urb(aiptek->urb);
 		usb_buffer_free(interface_to_usbdev(intf),
 				AIPTEK_PACKET_LENGTH,
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index ef01a80..6542edb 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -11,7 +11,7 @@
  *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
  *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
  *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2006 Ping Cheng		<pingc@wacom.com>
+ *  Copyright (c) 2002-2007 Ping Cheng		<pingc@wacom.com>
  *
  *  ChangeLog:
  *      v0.1 (vp)  - Initial release
@@ -62,8 +62,9 @@
  *                 - Minor data report fix
  *      v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
  *		   - where wacom_sys.c deals with system specific code,
- * 		   - and wacom_wac.c deals with Wacom specific code
+ *		   - and wacom_wac.c deals with Wacom specific code
  *		   - Support Intuos3 4x6
+ *      v1.47 (pc) - Added support for Bamboo
  */
 
 /*
@@ -84,7 +85,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.46"
+#define DRIVER_VERSION "v1.47"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
 #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
 #define DRIVER_LICENSE "GPL"
@@ -123,6 +124,7 @@
 extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern __u16 wacom_le16_to_cpu(unsigned char *data);
 extern __u16 wacom_be16_to_cpu(unsigned char *data);
 extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 83bddef..064e123 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -138,6 +138,12 @@
 	usb_kill_urb(wacom->irq);
 }
 
+void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_1) | BIT(BTN_5);
+	input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+}
+
 void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
 	input_dev->evbit[0] |= BIT(EV_MSC);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 7661f03..fc03ba2 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -178,7 +178,8 @@
 
 			case 2: /* Mouse with wheel */
 				wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
-				if (wacom->features->type == WACOM_G4) {
+				if (wacom->features->type == WACOM_G4 ||
+						wacom->features->type == WACOM_MO) {
 					rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
 					wacom_report_rel(wcombo, REL_WHEEL, -rw);
 				} else
@@ -190,7 +191,8 @@
 				id = CURSOR_DEVICE_ID;
 				wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
 				wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
-				if (wacom->features->type == WACOM_G4)
+				if (wacom->features->type == WACOM_G4 ||
+						wacom->features->type == WACOM_MO)
 					wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
 				else
 					wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
@@ -226,7 +228,8 @@
 	}
 
 	/* send pad data */
-	if (wacom->features->type == WACOM_G4) {
+	switch (wacom->features->type) {
+	    case WACOM_G4:
 		if (data[7] & 0xf8) {
 			wacom_input_sync(wcombo); /* sync last event */
 			wacom->id[1] = 1;
@@ -247,6 +250,33 @@
 			wacom_report_abs(wcombo, ABS_MISC, 0);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		}
+		break;
+	    case WACOM_MO:
+		if ((data[7] & 0xf8) || (data[8] & 0x80)) {
+			wacom_input_sync(wcombo); /* sync last event */
+			wacom->id[1] = 1;
+			wacom->serial[1] = (data[7] & 0xf8);
+			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+			wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+		} else if (wacom->id[1]) {
+			wacom_input_sync(wcombo); /* sync last event */
+			wacom->id[1] = 0;
+			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+			wacom_report_abs(wcombo, ABS_MISC, 0);
+			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+		}
+		break;
 	}
 	return 1;
 }
@@ -331,7 +361,7 @@
 			wacom_report_key(wcombo, BTN_EXTRA, 0);
 			wacom_report_abs(wcombo, ABS_THROTTLE, 0);
 			wacom_report_abs(wcombo, ABS_RZ, 0);
- 		} else {
+		} else {
 			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
 			wacom_report_abs(wcombo, ABS_TILT_X, 0);
 			wacom_report_abs(wcombo, ABS_TILT_Y, 0);
@@ -423,9 +453,9 @@
                 return result-1;
 
 	/* Only large I3 and I1 & I2 support Lense Cursor */
- 	if((wacom->tool[idx] == BTN_TOOL_LENS)
+	if ((wacom->tool[idx] == BTN_TOOL_LENS)
 			&& ((wacom->features->type == INTUOS3)
-		 	|| (wacom->features->type == INTUOS3S)))
+			|| (wacom->features->type == INTUOS3S)))
 		return 0;
 
 	/* Cintiq doesn't send data when RDY bit isn't set */
@@ -517,6 +547,7 @@
 			break;
 		case WACOM_G4:
 		case GRAPHIRE:
+		case WACOM_MO:
 			return (wacom_graphire_irq(wacom_wac, wcombo));
 			break;
 		case PTU:
@@ -538,6 +569,8 @@
 void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
 	switch (wacom_wac->features->type) {
+		case WACOM_MO:
+			input_dev_mo(input_dev, wacom_wac);
 		case WACOM_G4:
 			input_dev_g4(input_dev, wacom_wac);
 			/* fall through */
@@ -579,6 +612,7 @@
 	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
 	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
 	{ "Wacom PenPartner2",   8,   3250,  2320,  255, 63, GRAPHIRE },
+	{ "Wacom Bamboo",        9,  14760,  9225,  511, 63, WACOM_MO },
 	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
 	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
 	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
@@ -627,6 +661,7 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index a5e12e8..a302e22 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -25,6 +25,7 @@
 	INTUOS3,
 	INTUOS3L,
 	CINTIQ,
+	WACOM_MO,
 	MAX_TYPE
 };
 
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 4f09180..6937177 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -12,17 +12,17 @@
 if INPUT_TOUCHSCREEN
 
 config TOUCHSCREEN_ADS7846
-	tristate "ADS 7846/7843 based touchscreens"
+	tristate "ADS7846/TSC2046 and ADS7843 based touchscreens"
 	depends on SPI_MASTER
 	depends on HWMON = n || HWMON
 	help
 	  Say Y here if you have a touchscreen interface using the
-	  ADS7846 or ADS7843 controller, and your board-specific setup
-	  code includes that in its table of SPI devices.
+	  ADS7846/TSC2046 or ADS7843 controller, and your board-specific
+	  setup code includes that in its table of SPI devices.
 
 	  If HWMON is selected, and the driver is told the reference voltage
 	  on your board, you will also get hwmon interfaces for the voltage
-	  (and on ads7846, temperature) sensors of this chip.
+	  (and on ads7846/tsc2046, temperature) sensors of this chip.
 
 	  If unsure, say N (but it's safe to say "Y").
 
@@ -177,6 +177,7 @@
 	  - some other eTurboTouch
 	  - Gunze AHL61
 	  - DMC TSC-10/25
+	  - IRTOUCHSYSTEMS/UNITOP
 
 	  Have a look at <http://linux.chapter7.ch/touchkit/> for
 	  a usage description and the required user-space stuff.
@@ -219,4 +220,9 @@
 	bool "DMC TSC-10/25 device support" if EMBEDDED
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
+config TOUCHSCREEN_USB_IRTOUCH
+	default y
+	bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
 endif
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 693e3b2..1c9069c 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -39,6 +39,7 @@
 /*
  * This code has been heavily tested on a Nokia 770, and lightly
  * tested on other ads7846 devices (OSK/Mistral, Lubbock).
+ * TSC2046 is just newer ads7846 silicon.
  * Support for ads7843 tested on Atmel at91sam926x-EK.
  * Support for ads7845 has only been stubbed in.
  *
@@ -847,7 +848,7 @@
 	 * may not.  So we stick to very-portable 8 bit words, both RX and TX.
 	 */
 	spi->bits_per_word = 8;
-	spi->mode = SPI_MODE_1;
+	spi->mode = SPI_MODE_0;
 	err = spi_setup(spi);
 	if (err < 0)
 		return err;
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index 61c1502..1a15475 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -1,7 +1,6 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-
 #include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/delay.h>
@@ -18,12 +17,12 @@
 #define	PHDR	0xa400012e
 #define SCPDR	0xa4000136
 
-static void do_softint(void *data);
+static void do_softint(struct work_struct *work);
 
 static struct input_dev *hp680_ts_dev;
-static DECLARE_WORK(work, do_softint);
+static DECLARE_DELAYED_WORK(work, do_softint);
 
-static void do_softint(void *data)
+static void do_softint(struct work_struct *work)
 {
 	int absx = 0, absy = 0;
 	u8 scpdr;
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 6582816..36f9440 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -288,10 +288,11 @@
 	struct ucb1400 *ucb = _ucb;
 	struct task_struct *tsk = current;
 	int valid = 0;
+	struct sched_param param = { .sched_priority = 1 };
 
-	tsk->policy = SCHED_FIFO;
-	tsk->rt_priority = 1;
+	sched_setscheduler(tsk, SCHED_FIFO, &param);
 
+	set_freezable();
 	while (!kthread_should_stop()) {
 		unsigned int x, y, p;
 		long timeout;
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 8e18e6c..b407028 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -9,6 +9,7 @@
  *  - eTurboTouch
  *  - Gunze AHL61
  *  - DMC TSC-10/25
+ *  - IRTOUCHSYSTEMS/UNITOP
  *
  * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -91,7 +92,7 @@
 };
 
 
-#if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO)
+#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO)
 #define MULTI_PACKET
 #endif
 
@@ -110,10 +111,11 @@
 	DEVTYPE_ETURBO,
 	DEVTYPE_GUNZE,
 	DEVTYPE_DMC_TSC10,
+	DEVTYPE_IRTOUCH,
 };
 
 static struct usb_device_id usbtouch_devices[] = {
-#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
 	{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
 	{USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
 	{USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
@@ -123,33 +125,38 @@
 	{USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
 	{USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT},
 	{USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT},
 	{USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT},
 	{USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_3M
+#ifdef CONFIG_TOUCHSCREEN_USB_3M
 	{USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+#ifdef CONFIG_TOUCHSCREEN_USB_ITM
 	{USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
 	{USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
 	{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
 	{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+	{USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+	{USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+#endif
+
 	{}
 };
 
@@ -158,7 +165,7 @@
  * eGalax part
  */
 
-#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
 
 #define EGALAX_PKT_TYPE_MASK		0xFE
 #define EGALAX_PKT_TYPE_REPT		0x80
@@ -197,7 +204,7 @@
 /*****************************************************************************
  * PanJit Part
  */
-#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
 static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
 	dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1];
@@ -212,7 +219,7 @@
 /*****************************************************************************
  * 3M/Microtouch Part
  */
-#ifdef CONFIG_USB_TOUCHSCREEN_3M
+#ifdef CONFIG_TOUCHSCREEN_USB_3M
 
 #define MTOUCHUSB_ASYNC_REPORT          1
 #define MTOUCHUSB_RESET                 7
@@ -262,7 +269,7 @@
 /*****************************************************************************
  * ITM Part
  */
-#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+#ifdef CONFIG_TOUCHSCREEN_USB_ITM
 static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
 	int touch;
@@ -296,7 +303,7 @@
 /*****************************************************************************
  * eTurboTouch part
  */
-#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
 static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
 	unsigned int shift;
@@ -327,7 +334,7 @@
 /*****************************************************************************
  * Gunze part
  */
-#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
 static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
 	if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
@@ -348,7 +355,7 @@
  *   http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf
  *   http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf
  */
-#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
 
 /* supported data rates. currently using 130 */
 #define TSC10_RATE_POINT	0x50
@@ -416,10 +423,25 @@
 
 
 /*****************************************************************************
+ * IRTOUCH Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+	dev->x = (pkt[3] << 8) | pkt[2];
+	dev->y = (pkt[5] << 8) | pkt[4];
+	dev->touch = (pkt[1] & 0x03) ? 1 : 0;
+
+	return 1;
+}
+#endif
+
+
+/*****************************************************************************
  * the different device descriptors
  */
 static struct usbtouch_device_info usbtouch_dev_info[] = {
-#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
 	[DEVTYPE_EGALAX] = {
 		.min_xc		= 0x0,
 		.max_xc		= 0x07ff,
@@ -433,7 +455,7 @@
 	},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
 	[DEVTYPE_PANJIT] = {
 		.min_xc		= 0x0,
 		.max_xc		= 0x0fff,
@@ -444,7 +466,7 @@
 	},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_3M
+#ifdef CONFIG_TOUCHSCREEN_USB_3M
 	[DEVTYPE_3M] = {
 		.min_xc		= 0x0,
 		.max_xc		= 0x4000,
@@ -456,7 +478,7 @@
 	},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+#ifdef CONFIG_TOUCHSCREEN_USB_ITM
 	[DEVTYPE_ITM] = {
 		.min_xc		= 0x0,
 		.max_xc		= 0x0fff,
@@ -468,7 +490,7 @@
 	},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
 	[DEVTYPE_ETURBO] = {
 		.min_xc		= 0x0,
 		.max_xc		= 0x07ff,
@@ -482,7 +504,7 @@
 	},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
 	[DEVTYPE_GUNZE] = {
 		.min_xc		= 0x0,
 		.max_xc		= 0x0fff,
@@ -493,7 +515,7 @@
 	},
 #endif
 
-#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
 	[DEVTYPE_DMC_TSC10] = {
 		.min_xc		= 0x0,
 		.max_xc		= 0x03ff,
@@ -504,6 +526,17 @@
 		.read_data	= dmc_tsc10_read_data,
 	},
 #endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+	[DEVTYPE_IRTOUCH] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x0fff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x0fff,
+		.rept_size	= 8,
+		.read_data	= irtouch_read_data,
+	},
+#endif
 };
 
 
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 8238b13..d2f882e 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -109,9 +109,11 @@
 	int open;
 	int minor;
 	char name[8];
+	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head client_list;
-	struct input_handle handle;
+	struct device dev;
+
 	int x, y, pressure;
 	struct ts_calibration cal;
 };
@@ -163,9 +165,13 @@
 	if (!tsdev || !tsdev->exist)
 		return -ENODEV;
 
+	get_device(&tsdev->dev);
+
 	client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_tsdev;
+	}
 
 	client->tsdev = tsdev;
 	client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
@@ -173,19 +179,25 @@
 
 	if (!tsdev->open++ && tsdev->exist) {
 		error = input_open_device(&tsdev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_tsdev:
+	put_device(&tsdev->dev);
+	return error;
 }
 
-static void tsdev_free(struct tsdev *tsdev)
+static void tsdev_free(struct device *dev)
 {
+	struct tsdev *tsdev = container_of(dev, struct tsdev, dev);
+
 	tsdev_table[tsdev->minor] = NULL;
 	kfree(tsdev);
 }
@@ -200,12 +212,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--tsdev->open) {
-		if (tsdev->exist)
-			input_close_device(&tsdev->handle);
-		else
-			tsdev_free(tsdev);
-	}
+	if (!--tsdev->open && tsdev->exist)
+		input_close_device(&tsdev->handle);
+
+	put_device(&tsdev->dev);
 
 	return 0;
 }
@@ -361,7 +371,7 @@
 		int x, y, tmp;
 
 		do_gettimeofday(&time);
-		client->event[client->head].millisecs = time.tv_usec / 100;
+		client->event[client->head].millisecs = time.tv_usec / 1000;
 		client->event[client->head].pressure = tsdev->pressure;
 
 		x = tsdev->x;
@@ -388,8 +398,6 @@
 			 const struct input_device_id *id)
 {
 	struct tsdev *tsdev;
-	struct class_device *cdev;
-	dev_t devt;
 	int minor, delta;
 	int error;
 
@@ -407,14 +415,13 @@
 	INIT_LIST_HEAD(&tsdev->client_list);
 	init_waitqueue_head(&tsdev->wait);
 
-	sprintf(tsdev->name, "ts%d", minor);
-
 	tsdev->exist = 1;
 	tsdev->minor = minor;
 	tsdev->handle.dev = dev;
 	tsdev->handle.name = tsdev->name;
 	tsdev->handle.handler = handler;
 	tsdev->handle.private = tsdev;
+	snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
 
 	/* Precompute the rough calibration matrix */
 	delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
@@ -429,36 +436,30 @@
 	tsdev->cal.yscale = (yres << 8) / delta;
 	tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
 
+	snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
+		 "ts%d", minor);
+	tsdev->dev.class = &input_class;
+	tsdev->dev.parent = &dev->dev;
+	tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor);
+	tsdev->dev.release = tsdev_free;
+	device_initialize(&tsdev->dev);
+
 	tsdev_table[minor] = tsdev;
 
-	devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-
-	cdev = class_device_create(&input_class, &dev->cdev, devt,
-				   dev->cdev.dev, tsdev->name);
-	if (IS_ERR(cdev)) {
-		error = PTR_ERR(cdev);
-		goto err_free_tsdev;
-	}
-
-	/* temporary symlink to keep userspace happy */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, tsdev->name);
+	error = device_add(&tsdev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_tsdev;
 
 	error = input_register_handle(&tsdev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_tsdev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_tsdev:
+	device_del(&tsdev->dev);
  err_free_tsdev:
-	tsdev_table[minor] = NULL;
-	kfree(tsdev);
+	put_device(&tsdev->dev);
 	return error;
 }
 
@@ -468,19 +469,18 @@
 	struct tsdev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&tsdev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	tsdev->exist = 0;
 
 	if (tsdev->open) {
 		input_close_device(handle);
-		wake_up_interruptible(&tsdev->wait);
 		list_for_each_entry(client, &tsdev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
-	} else
-		tsdev_free(tsdev);
+		wake_up_interruptible(&tsdev->wait);
+	}
+
+	put_device(&tsdev->dev);
 }
 
 static const struct input_device_id tsdev_ids[] = {
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index d42fe89cd..cf906c8 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -2,12 +2,10 @@
 # ISDN device configuration
 #
 
-menu "ISDN subsystem"
-	depends on !S390
-
-config ISDN
+menuconfig ISDN
 	tristate "ISDN support"
 	depends on NET
+	depends on !S390
 	---help---
 	  ISDN ("Integrated Services Digital Networks", called RNIS in France)
 	  is a special type of fully digital telephone service; it's mostly
@@ -21,14 +19,14 @@
 
 	  Select this option if you want your kernel to support ISDN.
 
+if ISDN
 
 menu "Old ISDN4Linux"
-	depends on NET && ISDN
 
 config ISDN_I4L
-	tristate "Old ISDN4Linux (obsolete)"
+	tristate "Old ISDN4Linux (deprecated)"
 	---help---
-	  This driver allows you to use an ISDN-card for networking
+	  This driver allows you to use an ISDN adapter for networking
 	  connections and as dialin/out device.  The isdn-tty's have a built
 	  in AT-compatible modem emulator.  Network devices support autodial,
 	  channel-bundling, callback and caller-authentication without having
@@ -39,8 +37,9 @@
 
 	  ISDN support in the linux kernel is moving towards a new API,
 	  called CAPI (Common ISDN Application Programming Interface).
-	  Therefore the old ISDN4Linux layer is becoming obsolete. It is 
-	  still usable, though, if you select this option.
+	  Therefore the old ISDN4Linux layer will eventually become obsolete.
+	  It is still available, though, for use with adapters that are not
+	  supported by the new CAPI subsystem yet.
 
 if ISDN_I4L
 source "drivers/isdn/i4l/Kconfig"
@@ -49,20 +48,21 @@
 endmenu
 
 comment "CAPI subsystem"
-	depends on NET && ISDN
 
 config ISDN_CAPI
 	tristate "CAPI2.0 support"
-	depends on ISDN
 	help
 	  This provides the CAPI (Common ISDN Application Programming
 	  Interface, a standard making it easy for programs to access ISDN
 	  hardware, see <http://www.capi.org/>.  This is needed for AVM's set
 	  of active ISDN controllers like B1, T1, M1.
 
+if ISDN_CAPI
+
 source "drivers/isdn/capi/Kconfig"
 
 source "drivers/isdn/hardware/Kconfig"
 
-endmenu
+endif # ISDN_CAPI
 
+endif # ISDN
diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig
index c92f9d7..e1afd60 100644
--- a/drivers/isdn/capi/Kconfig
+++ b/drivers/isdn/capi/Kconfig
@@ -3,7 +3,6 @@
 #
 config ISDN_DRV_AVMB1_VERBOSE_REASON
 	bool "Verbose reason code reporting"
-	depends on ISDN_CAPI
 	default y
 	help
 	  If you say Y here, the CAPI drivers will give verbose reasons for
@@ -12,7 +11,6 @@
 
 config CAPI_TRACE
 	bool "CAPI trace support"
-	depends on ISDN_CAPI
 	default y
 	help
 	  If you say Y here, the kernelcapi driver can make verbose traces
@@ -23,7 +21,7 @@
 
 config ISDN_CAPI_MIDDLEWARE
 	bool "CAPI2.0 Middleware support (EXPERIMENTAL)"
-	depends on ISDN_CAPI && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  This option will enhance the capabilities of the /dev/capi20
 	  interface.  It will provide a means of moving a data connection,
@@ -33,7 +31,6 @@
 
 config ISDN_CAPI_CAPI20
 	tristate "CAPI2.0 /dev/capi support"
-	depends on ISDN_CAPI
 	help
 	  This option will provide the CAPI 2.0 interface to userspace
 	  applications via /dev/capi20. Applications should use the
@@ -56,7 +53,7 @@
 
 config ISDN_CAPI_CAPIDRV
 	tristate "CAPI2.0 capidrv interface support"
-	depends on ISDN_CAPI && ISDN_I4L
+	depends on ISDN_I4L
 	help
 	  This option provides the glue code to hook up CAPI driven cards to
 	  the legacy isdn4linux link layer.  If you have a card which is
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 81661b8..f449dae 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -549,7 +549,7 @@
 		capimsg_setu8 (skb->data, 5, CAPI_REQ);
 		capimsg_setu16(skb->data, 6, mp->msgid++);
 		capimsg_setu32(skb->data, 8, mp->ncci);	/* NCCI */
-		capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
+		capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
 		capimsg_setu16(skb->data, 16, len);	/* Data length */
 		capimsg_setu16(skb->data, 18, datahandle);
 		capimsg_setu16(skb->data, 20, 0);	/* Flags */
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 3ed34f7..9f73bc2 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -258,7 +258,7 @@
 	if ((!ap) || (ap->release_in_progress))
 		return;
 
-	down(&ap->recv_sem);
+	mutex_lock(&ap->recv_mtx);
 	while ((skb = skb_dequeue(&ap->recv_queue))) {
 		if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
 			ap->nrecvdatapkt++;
@@ -267,7 +267,7 @@
 
 		ap->recv_message(ap, skb);
 	}
-	up(&ap->recv_sem);
+	mutex_unlock(&ap->recv_mtx);
 }
 
 void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb)
@@ -547,7 +547,7 @@
 	ap->nsentctlpkt = 0;
 	ap->nsentdatapkt = 0;
 	ap->callback = NULL;
-	init_MUTEX(&ap->recv_sem);
+	mutex_init(&ap->recv_mtx);
 	skb_queue_head_init(&ap->recv_queue);
 	INIT_WORK(&ap->recv_work, recv_handler);
 	ap->release_in_progress = 0;
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 31f4fd8..845a797 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -243,36 +243,15 @@
 
 // ---------------------------------------------------------------------------
 
-
-static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos)
-{
-	struct capi_driver *drv = NULL;
-	struct list_head *l;
-	loff_t i;
-
-	i = 0;
-	list_for_each(l, &capi_drivers) {
-		drv = list_entry(l, struct capi_driver, list);
-		if (i++ == pos)
-			return drv;
-	}
-	return NULL;
-}
-
 static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
 {
-	struct capi_driver *drv;
 	read_lock(&capi_drivers_list_lock);
-	drv = capi_driver_get_idx(*pos);
-	return drv;
+	return seq_list_start(&capi_drivers, *pos);
 }
 
 static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct capi_driver *drv = (struct capi_driver *)v;
-	++*pos;
-	if (drv->list.next == &capi_drivers) return NULL;
-	return list_entry(drv->list.next, struct capi_driver, list);
+	return seq_list_next(v, &capi_drivers, pos);
 }
 
 static void capi_driver_stop(struct seq_file *seq, void *v)
@@ -282,7 +261,8 @@
 
 static int capi_driver_show(struct seq_file *seq, void *v)
 {
-	struct capi_driver *drv = (struct capi_driver *)v;
+	struct capi_driver *drv = list_entry(v, struct capi_driver, list);
+
 	seq_printf(seq, "%-32s %s\n", drv->name, drv->revision);
 	return 0;
 }
diff --git a/drivers/isdn/hardware/Kconfig b/drivers/isdn/hardware/Kconfig
index 139f197..30d028d 100644
--- a/drivers/isdn/hardware/Kconfig
+++ b/drivers/isdn/hardware/Kconfig
@@ -2,7 +2,6 @@
 # ISDN hardware drivers
 #
 comment "CAPI hardware drivers"
-	depends on NET && ISDN && ISDN_CAPI
 
 source "drivers/isdn/hardware/avm/Kconfig"
 
diff --git a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig
index 29a32a8..5dbcbe3 100644
--- a/drivers/isdn/hardware/avm/Kconfig
+++ b/drivers/isdn/hardware/avm/Kconfig
@@ -2,23 +2,22 @@
 # ISDN AVM drivers
 #
 
-menu "Active AVM cards"
-	depends on NET && ISDN && ISDN_CAPI!=n
-
-config CAPI_AVM
-	bool "Support AVM cards"
+menuconfig CAPI_AVM
+	bool "Active AVM cards"
 	help
 	  Enable support for AVM active ISDN cards.
 
+if CAPI_AVM
+
 config ISDN_DRV_AVMB1_B1ISA
 	tristate "AVM B1 ISA support"
-	depends on CAPI_AVM && ISDN_CAPI && ISA
+	depends on ISA
 	help
 	  Enable support for the ISA version of the AVM B1 card.
 
 config ISDN_DRV_AVMB1_B1PCI
 	tristate "AVM B1 PCI support"
-	depends on CAPI_AVM && ISDN_CAPI && PCI
+	depends on PCI
 	help
 	  Enable support for the PCI version of the AVM B1 card.
 
@@ -30,14 +29,13 @@
 
 config ISDN_DRV_AVMB1_T1ISA
 	tristate "AVM T1/T1-B ISA support"
-	depends on CAPI_AVM && ISDN_CAPI && ISA
+	depends on ISA
 	help
 	  Enable support for the AVM T1 T1B card.
 	  Note: This is a PRI card and handle 30 B-channels.
 
 config ISDN_DRV_AVMB1_B1PCMCIA
 	tristate "AVM B1/M1/M2 PCMCIA support"
-	depends on CAPI_AVM && ISDN_CAPI
 	help
 	  Enable support for the PCMCIA version of the AVM B1 card.
 
@@ -50,17 +48,16 @@
 
 config ISDN_DRV_AVMB1_T1PCI
 	tristate "AVM T1/T1-B PCI support"
-	depends on CAPI_AVM && ISDN_CAPI && PCI
+	depends on PCI
 	help
 	  Enable support for the AVM T1 T1B card.
 	  Note: This is a PRI card and handle 30 B-channels.
 
 config ISDN_DRV_AVMB1_C4
 	tristate "AVM C4/C2 support"
-	depends on CAPI_AVM && ISDN_CAPI && PCI
+	depends on PCI
 	help
 	  Enable support for the AVM C4/C2 PCI cards.
 	  These cards handle 4/2 BRI ISDN lines (8/4 channels).
 
-endmenu
-
+endif # CAPI_AVM
diff --git a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig
index 01d4afd..6082b6a 100644
--- a/drivers/isdn/hardware/eicon/Kconfig
+++ b/drivers/isdn/hardware/eicon/Kconfig
@@ -2,52 +2,50 @@
 # ISDN DIVAS Eicon driver
 #
 
-menu "Active Eicon DIVA Server cards"
-	depends on NET && ISDN && ISDN_CAPI!=n
-
-config CAPI_EICON
-	bool "Support Eicon cards"
+menuconfig CAPI_EICON
+	bool "Active Eicon DIVA Server cards"
 	help
 	  Enable support for Eicon Networks active ISDN cards.
 
+if CAPI_EICON
+
 config ISDN_DIVAS
 	tristate "Support Eicon DIVA Server cards"
-	depends on CAPI_EICON && PROC_FS && PCI
+	depends on PROC_FS && PCI
 	help
 	  Say Y here if you have an Eicon Networks DIVA Server PCI ISDN card.
 	  In order to use this card, additional firmware is necessary, which
 	  has to be downloaded into the card using the divactrl utility.
 
+if ISDN_DIVAS
+
 config ISDN_DIVAS_BRIPCI
 	bool "DIVA Server BRI/PCI support"
-	depends on ISDN_DIVAS
 	help
 	  Enable support for DIVA Server BRI-PCI.
 
 config ISDN_DIVAS_PRIPCI
 	bool "DIVA Server PRI/PCI support"
-	depends on ISDN_DIVAS
 	help
 	  Enable support for DIVA Server PRI-PCI.
 
 config ISDN_DIVAS_DIVACAPI
 	tristate "DIVA CAPI2.0 interface support"
-	depends on ISDN_DIVAS && ISDN_CAPI
 	help
 	  You need this to provide the CAPI interface
 	  for DIVA Server cards.
 
 config ISDN_DIVAS_USERIDI
 	tristate "DIVA User-IDI interface support"
-	depends on ISDN_DIVAS
 	help
 	  Enable support for user-mode IDI interface.
 
 config ISDN_DIVAS_MAINT
 	tristate "DIVA Maint driver support"
-	depends on ISDN_DIVAS && m
+	depends on m
 	help
 	  Enable Divas Maintenance driver.
 
-endmenu
+endif # ISDN_DIVAS
 
+endif # CAPI_EICON
diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
index ff284ae..82edc1c 100644
--- a/drivers/isdn/hardware/eicon/capifunc.c
+++ b/drivers/isdn/hardware/eicon/capifunc.c
@@ -189,21 +189,21 @@
 {
 	appl->xbuffer_used[ref] = true;
 	DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
-	    return (void *) ref;
+	    return (void *)(long)ref;
 }
 
 void *TransmitBufferGet(APPL * appl, void *p)
 {
-	if (appl->xbuffer_internal[(dword) p])
-		return appl->xbuffer_internal[(dword) p];
+	if (appl->xbuffer_internal[(dword)(long)p])
+		return appl->xbuffer_internal[(dword)(long)p];
 
-	return appl->xbuffer_ptr[(dword) p];
+	return appl->xbuffer_ptr[(dword)(long)p];
 }
 
 void TransmitBufferFree(APPL * appl, void *p)
 {
-	appl->xbuffer_used[(dword) p] = false;
-	DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword) p) + 1))
+	appl->xbuffer_used[(dword)(long)p] = false;
+	DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword)(long)p) + 1))
 }
 
 void *ReceiveBufferGet(APPL * appl, int Num)
@@ -301,7 +301,7 @@
 	/* if DATA_B3_IND, copy data too */
 	if (command == _DATA_B3_I) {
 		dword data = GET_DWORD(&msg.info.data_b3_ind.Data);
-		memcpy(write + length, (void *) data, dlength);
+		memcpy(write + length, (void *)(long)data, dlength);
 	}
 
 #ifndef DIVA_NO_DEBUGLIB
@@ -318,7 +318,7 @@
 			if (myDriverDebugHandle.dbgMask & DL_BLK) {
 				xlog("\x00\x02", &msg, 0x81, length);
 				for (i = 0; i < dlength; i += 256) {
-				  DBG_BLK((((char *) GET_DWORD(&msg.info.data_b3_ind.Data)) + i,
+				  DBG_BLK((((char *)(long)GET_DWORD(&msg.info.data_b3_ind.Data)) + i,
 				  	((dlength - i) < 256) ? (dlength - i) : 256))
 				  if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
 					  break; /* not more if not explicitely requested */
diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
index 14298b8..d755d90 100644
--- a/drivers/isdn/hardware/eicon/diva_didd.c
+++ b/drivers/isdn/hardware/eicon/diva_didd.c
@@ -99,7 +99,7 @@
 	return (0);
 }
 
-static void DIVA_EXIT_FUNCTION remove_proc(void)
+static void remove_proc(void)
 {
 	remove_proc_entry(DRIVERLNAME, proc_net_eicon);
 	remove_proc_entry("net/eicon", NULL);
diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
index df61e51..d36a4c0 100644
--- a/drivers/isdn/hardware/eicon/divasfunc.c
+++ b/drivers/isdn/hardware/eicon/divasfunc.c
@@ -195,7 +195,7 @@
 /*
  * disconnect from didd
  */
-static void DIVA_EXIT_FUNCTION disconnect_didd(void)
+static void disconnect_didd(void)
 {
 	IDI_SYNC_REQ req;
 
@@ -231,7 +231,7 @@
 /*
  * exit
  */
-void DIVA_EXIT_FUNCTION divasfunc_exit(void)
+void divasfunc_exit(void)
 {
 	divasa_xdi_driver_unload();
 	disconnect_didd();
diff --git a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
index 4cbc68c..db87d51 100644
--- a/drivers/isdn/hardware/eicon/idifunc.c
+++ b/drivers/isdn/hardware/eicon/idifunc.c
@@ -106,6 +106,7 @@
 	} else {
 		DBG_ERR(("could not create user mode idi card %d",
 			 adapter_nr));
+		diva_os_free(0, card);
 	}
 }
 
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
index 784232a..ccd35d0 100644
--- a/drivers/isdn/hardware/eicon/message.c
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -1,4 +1,3 @@
-
 /*
  *
   Copyright (c) Eicon Networks, 2002.
@@ -533,7 +532,7 @@
         if (m->header.command == _DATA_B3_R)
         {
 
-          m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
+          m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
 
         }
 
@@ -1032,7 +1031,7 @@
       {
 
         TransmitBufferFree (plci->appl,
-          (byte   *)(((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
+          (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
 
       }
 
@@ -3118,7 +3117,7 @@
        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
       {
 
-        data->P = (byte   *)(*((dword   *)(parms[0].info)));
+        data->P = (byte *)(long)(*((dword *)(parms[0].info)));
 
       }
       else
@@ -3151,7 +3150,7 @@
        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
       {
 
-        TransmitBufferFree (appl, (byte   *)(*((dword   *)(parms[0].info))));
+        TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
 
       }
     }
@@ -4057,7 +4056,7 @@
     {
       if (m->header.command == _DATA_B3_R)
 
-        TransmitBufferFree (appl, (byte   *)(m->info.data_b3_req.Data));
+        TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
 
       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
       break;
@@ -7134,7 +7133,7 @@
   case N_UDATA:
     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
     {
-      plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
+      plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
       plci->NL.R = plci->RData;
       plci->NL.RNum = 1;
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index 871310d..3d1bdc8 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -255,54 +255,38 @@
 	return (0);
 }
 
-static struct pci_dev *dev_a4t __devinitdata = NULL;
-
-int __devinit
-setup_bkm_a4t(struct IsdnCard *card)
+static int __devinit a4t_pci_probe(struct pci_dev *dev_a4t,
+				   struct IsdnCardState *cs,
+				   u_int *found,
+				   u_int *pci_memaddr)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-	u_int pci_memaddr = 0, found = 0;
+	u16 sub_sys;
+	u16 sub_vendor;
+
+	sub_vendor = dev_a4t->subsystem_vendor;
+	sub_sys = dev_a4t->subsystem_device;
+	if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
+		if (pci_enable_device(dev_a4t))
+			return (0);	/* end loop & function */
+		*found = 1;
+		*pci_memaddr = pci_resource_start(dev_a4t, 0);
+		cs->irq = dev_a4t->irq;
+		return (1);		/* end loop */
+	}
+
+	return (-1);			/* continue looping */
+}
+
+static int __devinit a4t_cs_init(struct IsdnCard *card,
+				 struct IsdnCardState *cs,
+				 u_int pci_memaddr)
+{
 	I20_REGISTER_FILE *pI20_Regs;
-#ifdef CONFIG_PCI
-#endif
 
-	strcpy(tmp, bkm_a4t_revision);
-	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
-		cs->subtyp = BKM_A4T;
-	} else
-		return (0);
-
-#ifdef CONFIG_PCI
-	while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
-		PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
-		u16 sub_sys;
-		u16 sub_vendor;
-
-		sub_vendor = dev_a4t->subsystem_vendor;
-		sub_sys = dev_a4t->subsystem_device;
-		if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
-			if (pci_enable_device(dev_a4t))
-				return(0);
-			found = 1;
-			pci_memaddr = pci_resource_start(dev_a4t, 0);
-			cs->irq = dev_a4t->irq;
-			break;
-		}
-	}
-	if (!found) {
-		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
-		return (0);
-	}
 	if (!cs->irq) {		/* IRQ range check ?? */
 		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
 		return (0);
 	}
-	if (!pci_memaddr) {
-		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
-		return (0);
-	}
 	cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
 	/* Check suspecious address */
 	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
@@ -317,11 +301,7 @@
 	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
 	cs->hw.ax.isac_ale = GCS_1;
 	cs->hw.ax.jade_ale = GCS_3;
-#else
-	printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]);
-	printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
-	return (0);
-#endif				/* CONFIG_PCI */
+
 	printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
 	       CardType[card->typ], cs->hw.ax.base, cs->irq);
 
@@ -339,5 +319,43 @@
 	ISACVersion(cs, "Telekom A4T:");
 	/* Jade version */
 	JadeVersion(cs, "Telekom A4T:");
+
 	return (1);
 }
+
+static struct pci_dev *dev_a4t __devinitdata = NULL;
+
+int __devinit
+setup_bkm_a4t(struct IsdnCard *card)
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	u_int pci_memaddr = 0, found = 0;
+	int ret;
+
+	strcpy(tmp, bkm_a4t_revision);
+	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		cs->subtyp = BKM_A4T;
+	} else
+		return (0);
+
+	while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
+		PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
+		ret = a4t_pci_probe(dev_a4t, cs, &found, &pci_memaddr);
+		if (!ret)
+			return (0);
+		if (ret > 0)
+			break;
+	}
+	if (!found) {
+		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
+		return (0);
+	}
+	if (!pci_memaddr) {
+		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
+		return (0);
+	}
+
+	return a4t_cs_init(card, cs, pci_memaddr);
+}
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index 3403106..6339bb4 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -287,7 +287,6 @@
 #ifdef CONFIG_PCI
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u_char pci_rev_id;
 	u_int found = 0;
 	u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5;
 
@@ -335,8 +334,7 @@
 		}
 #ifdef ATTEMPT_PCI_REMAPPING
 /* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
-		pci_read_config_byte(dev_a8, PCI_REVISION_ID, &pci_rev_id);
-		if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) {
+		if ((pci_ioaddr1 & 0x80) && (dev_a8->revision == 1)) {
 			printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
 				CardType[card->typ],
 				sct_quadro_subtypes[cs->subtyp]);
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index da4196f2..5f7907e 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -361,11 +361,11 @@
 
 int nrcards;
 
-extern char *l1_revision;
-extern char *l2_revision;
-extern char *l3_revision;
-extern char *lli_revision;
-extern char *tei_revision;
+extern const char *l1_revision;
+extern const char *l2_revision;
+extern const char *l3_revision;
+extern const char *lli_revision;
+extern const char *tei_revision;
 
 char *HiSax_getrev(const char *revision)
 {
@@ -847,95 +847,10 @@
 	return 3;
 }
 
-static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
+static int hisax_cs_setup_card(struct IsdnCard *card)
 {
-	int ret = 0;
-	struct IsdnCard *card = cards + cardnr;
-	struct IsdnCardState *cs;
+	int ret;
 
-	cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
-	if (!cs) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for IsdnCardState(card %d)\n",
-		       cardnr + 1);
-		goto out;
-	}
-	card->cs = cs;
-	spin_lock_init(&cs->statlock);
-	spin_lock_init(&cs->lock);
-	cs->chanlimit = 2;	/* maximum B-channel number */
-	cs->logecho = 0;	/* No echo logging */
-	cs->cardnr = cardnr;
-	cs->debug = L1_DEB_WARN;
-	cs->HW_Flags = 0;
-	cs->busy_flag = busy_flag;
-	cs->irq_flags = I4L_IRQ_FLAG;
-#if TEI_PER_CARD
-	if (card->protocol == ISDN_PTYPE_NI1)
-		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#else
-	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#endif
-	cs->protocol = card->protocol;
-
-	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
-		printk(KERN_WARNING
-		       "HiSax: Card Type %d out of range\n", card->typ);
-		goto outf_cs;
-	}
-	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
-		goto outf_cs;
-	}
-	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for status_buf(card %d)\n",
-		       cardnr + 1);
-		goto outf_dlog;
-	}
-	cs->stlist = NULL;
-	cs->status_read = cs->status_buf;
-	cs->status_write = cs->status_buf;
-	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
-	cs->typ = card->typ;
-#ifdef MODULE
-	cs->iif.owner = lockowner;
-#endif
-	strcpy(cs->iif.id, id);
-	cs->iif.channels = 2;
-	cs->iif.maxbufsize = MAX_DATA_SIZE;
-	cs->iif.hl_hdrlen = MAX_HEADER_LEN;
-	cs->iif.features =
-		ISDN_FEATURE_L2_X75I |
-		ISDN_FEATURE_L2_HDLC |
-		ISDN_FEATURE_L2_HDLC_56K |
-		ISDN_FEATURE_L2_TRANS |
-		ISDN_FEATURE_L3_TRANS |
-#ifdef	CONFIG_HISAX_1TR6
-		ISDN_FEATURE_P_1TR6 |
-#endif
-#ifdef	CONFIG_HISAX_EURO
-		ISDN_FEATURE_P_EURO |
-#endif
-#ifdef	CONFIG_HISAX_NI1
-		ISDN_FEATURE_P_NI1 |
-#endif
-		0;
-
-	cs->iif.command = HiSax_command;
-	cs->iif.writecmd = NULL;
-	cs->iif.writebuf_skb = HiSax_writebuf_skb;
-	cs->iif.readstat = HiSax_readstatus;
-	register_isdn(&cs->iif);
-	cs->myid = cs->iif.channels;
-	printk(KERN_INFO
-	       "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
-	       (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
-	       (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
-	       (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
-	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
-	       "NONE", cs->iif.id, cs->myid);
 	switch (card->typ) {
 #if CARD_TELES0
 	case ISDN_CTYPE_16_0:
@@ -1094,13 +1009,115 @@
 		printk(KERN_WARNING
 		       "HiSax: Support for %s Card not selected\n",
 		       CardType[card->typ]);
-		ll_unload(cs);
+		ret = 0;
+		break;
+	}
+
+	return ret;
+}
+
+static int hisax_cs_new(int cardnr, char *id, struct IsdnCard *card,
+			struct IsdnCardState **cs_out, int *busy_flag,
+			struct module *lockowner)
+{
+	struct IsdnCardState *cs;
+
+	*cs_out = NULL;
+
+	cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+	if (!cs) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for IsdnCardState(card %d)\n",
+		       cardnr + 1);
+		goto out;
+	}
+	card->cs = cs;
+	spin_lock_init(&cs->statlock);
+	spin_lock_init(&cs->lock);
+	cs->chanlimit = 2;	/* maximum B-channel number */
+	cs->logecho = 0;	/* No echo logging */
+	cs->cardnr = cardnr;
+	cs->debug = L1_DEB_WARN;
+	cs->HW_Flags = 0;
+	cs->busy_flag = busy_flag;
+	cs->irq_flags = I4L_IRQ_FLAG;
+#if TEI_PER_CARD
+	if (card->protocol == ISDN_PTYPE_NI1)
+		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#else
+	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#endif
+	cs->protocol = card->protocol;
+
+	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
+		printk(KERN_WARNING
+		       "HiSax: Card Type %d out of range\n", card->typ);
 		goto outf_cs;
 	}
-	if (!ret) {
-		ll_unload(cs);
+	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
 		goto outf_cs;
 	}
+	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for status_buf(card %d)\n",
+		       cardnr + 1);
+		goto outf_dlog;
+	}
+	cs->stlist = NULL;
+	cs->status_read = cs->status_buf;
+	cs->status_write = cs->status_buf;
+	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
+	cs->typ = card->typ;
+#ifdef MODULE
+	cs->iif.owner = lockowner;
+#endif
+	strcpy(cs->iif.id, id);
+	cs->iif.channels = 2;
+	cs->iif.maxbufsize = MAX_DATA_SIZE;
+	cs->iif.hl_hdrlen = MAX_HEADER_LEN;
+	cs->iif.features =
+		ISDN_FEATURE_L2_X75I |
+		ISDN_FEATURE_L2_HDLC |
+		ISDN_FEATURE_L2_HDLC_56K |
+		ISDN_FEATURE_L2_TRANS |
+		ISDN_FEATURE_L3_TRANS |
+#ifdef	CONFIG_HISAX_1TR6
+		ISDN_FEATURE_P_1TR6 |
+#endif
+#ifdef	CONFIG_HISAX_EURO
+		ISDN_FEATURE_P_EURO |
+#endif
+#ifdef	CONFIG_HISAX_NI1
+		ISDN_FEATURE_P_NI1 |
+#endif
+		0;
+
+	cs->iif.command = HiSax_command;
+	cs->iif.writecmd = NULL;
+	cs->iif.writebuf_skb = HiSax_writebuf_skb;
+	cs->iif.readstat = HiSax_readstatus;
+	register_isdn(&cs->iif);
+	cs->myid = cs->iif.channels;
+
+	*cs_out = cs;
+	return 1;	/* success */
+
+outf_dlog:
+	kfree(cs->dlog);
+outf_cs:
+	kfree(cs);
+	card->cs = NULL;
+out:
+	return 0;	/* error */
+}
+
+static int hisax_cs_setup(int cardnr, struct IsdnCard *card,
+			  struct IsdnCardState *cs)
+{
+	int ret;
+
 	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
 		printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
 		ll_unload(cs);
@@ -1143,11 +1160,41 @@
 	if (!test_bit(HW_ISAR, &cs->HW_Flags))
 		ll_run(cs, 0);
 
-	ret = 1;
+	return 1;
+
+outf_cs:
+	kfree(cs);
+	card->cs = NULL;
+	return ret;
+}
+
+static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
+{
+	int ret;
+	struct IsdnCard *card = cards + cardnr;
+	struct IsdnCardState *cs;
+
+	ret = hisax_cs_new(cardnr, id, card, &cs, busy_flag, lockowner);
+	if (!ret)
+		return 0;
+
+	printk(KERN_INFO
+	       "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
+	       (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
+	       (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
+	       (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
+	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
+	       "NONE", cs->iif.id, cs->myid);
+
+	ret = hisax_cs_setup_card(card);
+	if (!ret) {
+		ll_unload(cs);
+		goto outf_cs;
+	}
+
+	ret = hisax_cs_setup(cardnr, card, cs);
 	goto out;
 
- outf_dlog:
-	kfree(cs->dlog);
  outf_cs:
 	kfree(cs);
 	card->cs = NULL;
@@ -1551,7 +1598,7 @@
 	if (retval == 0) { // yuck
 		cards[i].typ = 0;
 		nrcards--;
-		return retval;
+		return -EINVAL;
 	}
 	cs = cards[i].cs;
 	hisax_d_if->cs = cs;
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index b45de9d..b73027f 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -300,98 +300,72 @@
 	return IRQ_HANDLED;
 }
 
-
-static struct pci_dev *dev_netjet __devinitdata = NULL;
-
-/* called by config.c */
-int __devinit
-setup_enternow_pci(struct IsdnCard *card)
+static int __devinit en_pci_probe(struct pci_dev *dev_netjet,
+				  struct IsdnCardState *cs)
 {
-	int bytecnt;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-#ifdef CONFIG_PCI
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-        strcpy(tmp, enternow_pci_rev);
-	printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_ENTERNOW)
+	if (pci_enable_device(dev_netjet))
 		return(0);
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-
-	for ( ;; )
-	{
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-                        /* checks Sub-Vendor ID because system crashes with Traverse-Card */
-			if ((dev_netjet->subsystem_vendor != 0x55) ||
-				(dev_netjet->subsystem_device != 0x02)) {
-				printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
-                                printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
-                                return(0);
-                        }
-		} else {
-                        printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
-			return(0);
-		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
-
-		/* Reset an */
-		cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
-		outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
-		/* 20 ms Pause */
-		mdelay(20);
-
-		cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
-		outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
-		mdelay(10);
-
-		cs->hw.njet.auxd = 0x00; // war 0xc0
-		cs->hw.njet.dmactrl = 0;
-
-		outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL);
-		outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1);
-		outb(cs->hw.njet.auxd, cs->hw.njet.auxa);
-
-		break;
+	cs->irq = dev_netjet->irq;
+	if (!cs->irq) {
+		printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
+		return(0);
 	}
-#else
+	cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+	if (!cs->hw.njet.base) {
+		printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
+		return(0);
+	}
+	/* checks Sub-Vendor ID because system crashes with Traverse-Card */
+	if ((dev_netjet->subsystem_vendor != 0x55) ||
+	    (dev_netjet->subsystem_device != 0x02)) {
+		printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
+		printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
+		return(0);
+	}
 
-	printk(KERN_WARNING "enter:now PCI: NO_PCI_BIOS\n");
-	printk(KERN_WARNING "enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab\n");
-	return (0);
+	return(1);
+}
 
-#endif /* CONFIG_PCI */
+static void __devinit en_cs_init(struct IsdnCard *card,
+				 struct IsdnCardState *cs)
+{
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
 
-	bytecnt = 256;
+	/* Reset an */
+	cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
+	outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
+	/* 20 ms Pause */
+	mdelay(20);
+
+	cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
+	outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
+	mdelay(10);
+
+	cs->hw.njet.auxd = 0x00; // war 0xc0
+	cs->hw.njet.dmactrl = 0;
+
+	outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL);
+	outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1);
+	outb(cs->hw.njet.auxd, cs->hw.njet.auxa);
+}
+
+static int __devinit en_cs_init_rest(struct IsdnCard *card,
+				     struct IsdnCardState *cs)
+{
+	const int bytecnt = 256;
 
 	printk(KERN_INFO
 		"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
 		cs->hw.njet.base, cs->irq);
 	if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) {
 		printk(KERN_WARNING
-			   "HiSax: %s config port %lx-%lx already in use\n",
-			   CardType[card->typ],
-			   cs->hw.njet.base,
-			   cs->hw.njet.base + bytecnt);
+		       "HiSax: enter:now config port %lx-%lx already in use\n",
+		       cs->hw.njet.base,
+		       cs->hw.njet.base + bytecnt);
 		return (0);
 	}
+
 	setup_Amd7930(cs);
 	cs->hw.njet.last_is0 = 0;
         /* macro rByteAMD */
@@ -407,5 +381,44 @@
 	cs->irq_func = &enpci_interrupt;
 	cs->irq_flags |= IRQF_SHARED;
 
-        return (1);
+	return (1);
+}
+
+static struct pci_dev *dev_netjet __devinitdata = NULL;
+
+/* called by config.c */
+int __devinit
+setup_enternow_pci(struct IsdnCard *card)
+{
+	int ret;
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+
+        strcpy(tmp, enternow_pci_rev);
+	printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_ENTERNOW)
+		return(0);
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+	for ( ;; )
+	{
+		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
+			ret = en_pci_probe(dev_netjet, cs);
+			if (!ret)
+				return(0);
+		} else {
+                        printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
+			return(0);
+		}
+
+		en_cs_init(card, cs);
+		break;
+	}
+
+        return en_cs_init_rest(card, cs);
 }
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 8a48a3c..077080a 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -6,7 +6,7 @@
  *              based on existing driver for CCD hfc ISA cards
  * Copyright    by Werner Cornelius  <werner@isdn4linux.de>
  *              by Karsten Keil      <keil@isdn4linux.de>
- * 
+ *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
  *
@@ -67,8 +67,6 @@
 };
 
 
-#ifdef CONFIG_PCI
-
 /******************************************/
 /* free hardware resources used by driver */
 /******************************************/
@@ -237,7 +235,7 @@
 	if (fifo_state)
 	        cs->hw.hfcpci.fifo_en |= fifo_state;
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
-}   
+}
 
 /***************************************/
 /* clear the desired B-channel tx fifo */
@@ -263,7 +261,7 @@
 	if (fifo_state)
 	        cs->hw.hfcpci.fifo_en |= fifo_state;
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
-}   
+}
 
 /*********************************************/
 /* read a complete B-frame out of the buffer */
@@ -511,7 +509,6 @@
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;
-	return;
 }
 
 /**************************/
@@ -582,7 +579,6 @@
 
 	dev_kfree_skb_any(cs->tx_skb);
 	cs->tx_skb = NULL;
-	return;
 }
 
 /**************************/
@@ -729,7 +725,6 @@
 	dev_kfree_skb_any(bcs->tx_skb);
 	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	return;
 }
 
 /**********************************************/
@@ -924,7 +919,6 @@
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;
-	return;
 }				/* receive_emsg */
 
 /*********************/
@@ -1350,13 +1344,13 @@
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
 			}
 			if (fifo2) {
-			        cs->hw.hfcpci.last_bfifo_cnt[1] = 0;  
+			        cs->hw.hfcpci.last_bfifo_cnt[1] = 0;
 				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
 				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
 				cs->hw.hfcpci.ctmt &= ~2;
 				cs->hw.hfcpci.conn &= ~0x18;
 			} else {
-			        cs->hw.hfcpci.last_bfifo_cnt[0] = 0;  
+			        cs->hw.hfcpci.last_bfifo_cnt[0] = 0;
 				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
 				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
 				cs->hw.hfcpci.ctmt &= ~1;
@@ -1642,8 +1636,6 @@
 /* this variable is used as card index when more than one cards are present */
 static struct pci_dev *dev_hfcpci __devinitdata = NULL;
 
-#endif				/* CONFIG_PCI */
-
 int __devinit
 setup_hfcpci(struct IsdnCard *card)
 {
@@ -1656,96 +1648,99 @@
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
+
 	strcpy(tmp, hfcpci_revision);
 	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-#ifdef CONFIG_PCI
+
 	cs->hw.hfcpci.int_s1 = 0;
 	cs->dc.hfcpci.ph_state = 0;
 	cs->hw.hfcpci.fifo = 255;
-	if (cs->typ == ISDN_CTYPE_HFC_PCI) {
-		i = 0;
-		while (id_list[i].vendor_id) {
-			tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
-						     id_list[i].device_id,
-						     dev_hfcpci);
-			i++;
-			if (tmp_hfcpci) {
-				if (pci_enable_device(tmp_hfcpci))
-					continue;
-				pci_set_master(tmp_hfcpci);
-				if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
-					continue;
-				else
-					break;
-			}
-		}
+	if (cs->typ != ISDN_CTYPE_HFC_PCI)
+		return(0);
 
+	i = 0;
+	while (id_list[i].vendor_id) {
+		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+					     id_list[i].device_id,
+					     dev_hfcpci);
+		i++;
 		if (tmp_hfcpci) {
-			i--;
-			dev_hfcpci = tmp_hfcpci;	/* old device */
-			cs->hw.hfcpci.dev = dev_hfcpci;
-			cs->irq = dev_hfcpci->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
-				return (0);
-			}
-			cs->hw.hfcpci.pci_io = (char *)(unsigned long)dev_hfcpci->resource[1].start;
-			printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
-		} else {
-			printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
-			return (0);
+			if (pci_enable_device(tmp_hfcpci))
+				continue;
+			pci_set_master(tmp_hfcpci);
+			if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
+				continue;
+			else
+				break;
 		}
-		if (!cs->hw.hfcpci.pci_io) {
-			printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
-			return (0);
-		}
-		/* Allocate memory for FIFOS */
-		/* Because the HFC-PCI needs a 32K physical alignment, we */
-		/* need to allocate the double mem and align the address */
-		if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
-			printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
-			return 0;
-		}
-		cs->hw.hfcpci.fifos = (void *)
-		    (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
-		pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
-		cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
-		printk(KERN_INFO
-		       "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n",
-		       cs->hw.hfcpci.pci_io,
-		       cs->hw.hfcpci.fifos,
-		       (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
-		       cs->irq, HZ);
-		spin_lock_irqsave(&cs->lock, flags);
-		pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
-		cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
-		cs->hw.hfcpci.int_m1 = 0;
-		Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-		Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
-		/* At this point the needed PCI config is done */
-		/* fifos are still not enabled */
-		INIT_WORK(&cs->tqueue,  hfcpci_bh);
-		cs->setstack_d = setstack_hfcpci;
-		cs->BC_Send_Data = &hfcpci_send_data;
-		cs->readisac = NULL;
-		cs->writeisac = NULL;
-		cs->readisacfifo = NULL;
-		cs->writeisacfifo = NULL;
-		cs->BC_Read_Reg = NULL;
-		cs->BC_Write_Reg = NULL;
-		cs->irq_func = &hfcpci_interrupt;
-		cs->irq_flags |= IRQF_SHARED;
-		cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
-		cs->hw.hfcpci.timer.data = (long) cs;
-		init_timer(&cs->hw.hfcpci.timer);
-		cs->cardmsg = &hfcpci_card_msg;
-		cs->auxcmd = &hfcpci_auxcmd;
-		spin_unlock_irqrestore(&cs->lock, flags);
-		return (1);
-	} else
-		return (0);	/* no valid card type */
-#else
-	printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
-	return (0);
-#endif				/* CONFIG_PCI */
+	}
+
+	if (!tmp_hfcpci) {
+		printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
+		return (0);
+	}
+
+	i--;
+	dev_hfcpci = tmp_hfcpci;	/* old device */
+	cs->hw.hfcpci.dev = dev_hfcpci;
+	cs->irq = dev_hfcpci->irq;
+	if (!cs->irq) {
+		printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
+		return (0);
+	}
+	cs->hw.hfcpci.pci_io = (char *)(unsigned long)dev_hfcpci->resource[1].start;
+	printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
+
+	if (!cs->hw.hfcpci.pci_io) {
+		printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
+		return (0);
+	}
+	/* Allocate memory for FIFOS */
+	/* Because the HFC-PCI needs a 32K physical alignment, we */
+	/* need to allocate the double mem and align the address */
+	if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
+		printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+		return 0;
+	}
+	cs->hw.hfcpci.fifos = (void *)
+	    (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
+	pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
+	cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
+	printk(KERN_INFO
+	       "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n",
+	       cs->hw.hfcpci.pci_io,
+	       cs->hw.hfcpci.fifos,
+	       (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
+	       cs->irq, HZ);
+
+	spin_lock_irqsave(&cs->lock, flags);
+
+	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
+	cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
+	cs->hw.hfcpci.int_m1 = 0;
+	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+	/* At this point the needed PCI config is done */
+	/* fifos are still not enabled */
+
+	INIT_WORK(&cs->tqueue,  hfcpci_bh);
+	cs->setstack_d = setstack_hfcpci;
+	cs->BC_Send_Data = &hfcpci_send_data;
+	cs->readisac = NULL;
+	cs->writeisac = NULL;
+	cs->readisacfifo = NULL;
+	cs->writeisacfifo = NULL;
+	cs->BC_Read_Reg = NULL;
+	cs->BC_Write_Reg = NULL;
+	cs->irq_func = &hfcpci_interrupt;
+	cs->irq_flags |= IRQF_SHARED;
+	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
+	cs->hw.hfcpci.timer.data = (long) cs;
+	init_timer(&cs->hw.hfcpci.timer);
+	cs->cardmsg = &hfcpci_card_msg;
+	cs->auxcmd = &hfcpci_auxcmd;
+
+	spin_unlock_irqrestore(&cs->lock, flags);
+
+	return (1);
 }
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index 1f18f19..b1a26e0 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -485,7 +485,6 @@
 {
 	int k;
 
-	spin_lock_init(&urb->lock);
 	urb->dev = dev;
 	urb->pipe = pipe;
 	urb->complete = complete;
@@ -578,16 +577,14 @@
 			    "HFC-S USB: Stopping iso chain for fifo %i.%i",
 			    fifo->fifonum, i);
 #endif
-			usb_unlink_urb(fifo->iso[i].purb);
+			usb_kill_urb(fifo->iso[i].purb);
 			usb_free_urb(fifo->iso[i].purb);
 			fifo->iso[i].purb = NULL;
 		}
 	}
-	if (fifo->urb) {
-		usb_unlink_urb(fifo->urb);
-		usb_free_urb(fifo->urb);
-		fifo->urb = NULL;
-	}
+	usb_kill_urb(fifo->urb);
+	usb_free_urb(fifo->urb);
+	fifo->urb = NULL;
 	fifo->active = 0;
 }
 
@@ -1305,7 +1302,11 @@
 	}
 	/* default Prot: EURO ISDN, should be a module_param */
 	hfc->protocol = 2;
-	hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
+	i = hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
+	if (i) {
+		printk(KERN_INFO "HFC-S USB: hisax_register -> %d\n", i);
+		return i;
+	}
 
 #ifdef CONFIG_HISAX_DEBUG
 	hfc_debug = debug;
@@ -1626,11 +1627,9 @@
 #endif
 			/* init the chip and register the driver */
 			if (usb_init(context)) {
-				if (context->ctrl_urb) {
-					usb_unlink_urb(context->ctrl_urb);
-					usb_free_urb(context->ctrl_urb);
-					context->ctrl_urb = NULL;
-				}
+				usb_kill_urb(context->ctrl_urb);
+				usb_free_urb(context->ctrl_urb);
+				context->ctrl_urb = NULL;
 				kfree(context);
 				return (-EIO);
 			}
@@ -1682,21 +1681,15 @@
 				    i);
 #endif
 			}
-			if (context->fifos[i].urb) {
-				usb_unlink_urb(context->fifos[i].urb);
-				usb_free_urb(context->fifos[i].urb);
-				context->fifos[i].urb = NULL;
-			}
+			usb_kill_urb(context->fifos[i].urb);
+			usb_free_urb(context->fifos[i].urb);
+			context->fifos[i].urb = NULL;
 		}
 		context->fifos[i].active = 0;
 	}
-	/* wait for all URBS to terminate */
-	mdelay(10);
-	if (context->ctrl_urb) {
-		usb_unlink_urb(context->ctrl_urb);
-		usb_free_urb(context->ctrl_urb);
-		context->ctrl_urb = NULL;
-	}
+	usb_kill_urb(context->ctrl_urb);
+	usb_free_urb(context->ctrl_urb);
+	context->ctrl_urb = NULL;
 	hisax_unregister(&context->d_if);
 	kfree(context);		/* free our structure again */
 }				/* hfc_usb_disconnect */
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index 9e088fc..7993e01 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -859,7 +859,11 @@
 	for (i = 0; i < 2; i++)
 		b_if[i] = &adapter->bcs[i].b_if;
 
-	hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp", protocol);
+	if (hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp",
+			protocol) != 0) {
+		kfree(adapter);
+		adapter = NULL;
+	}
 
 	return adapter;
 }
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
index c09ffb1..fa2db87 100644
--- a/drivers/isdn/hisax/nj_s.c
+++ b/drivers/isdn/hisax/nj_s.c
@@ -148,107 +148,87 @@
 	return(0);
 }
 
-static struct pci_dev *dev_netjet __devinitdata = NULL;
-
-int __devinit
-setup_netjet_s(struct IsdnCard *card)
+static int __devinit njs_pci_probe(struct pci_dev *dev_netjet,
+				   struct IsdnCardState *cs)
 {
-	int bytecnt,cfg;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
+	int cfg;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-	strcpy(tmp, NETjet_S_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_NETJET_S)
+	if (pci_enable_device(dev_netjet))
 		return(0);
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-
-#ifdef CONFIG_PCI
-
-	for ( ;; )
-	{
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			pci_set_master(dev_netjet);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			/* the TJ300 and TJ320 must be detected, the IRQ handling is different
-			 * unfortunatly the chips use the same device ID, but the TJ320 has
-			 * the bit20 in status PCI cfg register set
-			 */
-			pci_read_config_dword(dev_netjet, 0x04, &cfg);
-			if (cfg & 0x00100000)
-				cs->subtyp = 1; /* TJ320 */
-			else
-				cs->subtyp = 0; /* TJ300 */
-			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
-			if ((dev_netjet->subsystem_vendor == 0x55) &&
-				(dev_netjet->subsystem_device == 0x02)) {
-				printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
-				printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
-				return(0);
-			}
-			/* end new code */
-		} else {
-			printk(KERN_WARNING "NETjet-S: No PCI card found\n");
-			return(0);
-		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-
-		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-		mdelay(10);
-
-		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-		mdelay(10);
-
-		cs->hw.njet.auxd = 0xC0;
-		cs->hw.njet.dmactrl = 0;
-
-		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-		switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
-		{
-			case 0 :
-				break;
-
-			case 3 :
-				printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
-				continue;
-
-			default :
-				printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
-				return 0;
-                }
-                break;
+	pci_set_master(dev_netjet);
+	cs->irq = dev_netjet->irq;
+	if (!cs->irq) {
+		printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
+		return(0);
 	}
-#else
+	cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+	if (!cs->hw.njet.base) {
+		printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
+		return(0);
+	}
+	/* the TJ300 and TJ320 must be detected, the IRQ handling is different
+	 * unfortunatly the chips use the same device ID, but the TJ320 has
+	 * the bit20 in status PCI cfg register set
+	 */
+	pci_read_config_dword(dev_netjet, 0x04, &cfg);
+	if (cfg & 0x00100000)
+		cs->subtyp = 1; /* TJ320 */
+	else
+		cs->subtyp = 0; /* TJ300 */
+	/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
+	if ((dev_netjet->subsystem_vendor == 0x55) &&
+		(dev_netjet->subsystem_device == 0x02)) {
+		printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
+		printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
+		return(0);
+	}
+	/* end new code */
 
-	printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n");
-	printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n");
-	return (0);
+	return(1);
+}
 
-#endif /* CONFIG_PCI */
+static int __devinit njs_cs_init(struct IsdnCard *card,
+				 struct IsdnCardState *cs)
+{
 
-	bytecnt = 256;
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+
+	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	mdelay(10);
+
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	mdelay(10);
+
+	cs->hw.njet.auxd = 0xC0;
+	cs->hw.njet.dmactrl = 0;
+
+	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+	switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
+	{
+		case 0 :
+			return 1;	/* end loop */
+
+		case 3 :
+			printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
+			return -1;	/* continue looping */
+
+		default :
+			printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
+			return 0;	/* end loop & function */
+	}
+	return 1;			/* end loop */
+}
+
+static int __devinit njs_cs_init_rest(struct IsdnCard *card,
+				      struct IsdnCardState *cs)
+{
+	const int bytecnt = 256;
 
 	printk(KERN_INFO
 		"NETjet-S: %s card configured at %#lx IRQ %d\n",
@@ -273,5 +253,47 @@
 	cs->irq_func = &netjet_s_interrupt;
 	cs->irq_flags |= IRQF_SHARED;
 	ISACVersion(cs, "NETjet-S:");
+
 	return (1);
 }
+
+static struct pci_dev *dev_netjet __devinitdata = NULL;
+
+int __devinit
+setup_netjet_s(struct IsdnCard *card)
+{
+	int ret;
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+	strcpy(tmp, NETjet_S_revision);
+	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_NETJET_S)
+		return(0);
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+	for ( ;; )
+	{
+		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
+			ret = njs_pci_probe(dev_netjet, cs);
+			if (!ret)
+				return(0);
+		} else {
+			printk(KERN_WARNING "NETjet-S: No PCI card found\n");
+			return(0);
+		}
+
+		ret = njs_cs_init(card, cs);
+		if (!ret)
+			return(0);
+		if (ret > 0)
+			break;
+		/* otherwise, ret < 0, continue looping */
+	}
+
+	return njs_cs_init_rest(card, cs);
+}
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 8202cf3..f017d38 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -128,93 +128,69 @@
 	return(0);
 }
 
-static struct pci_dev *dev_netjet __devinitdata = NULL;
-
-int __devinit
-setup_netjet_u(struct IsdnCard *card)
+static int __devinit nju_pci_probe(struct pci_dev *dev_netjet,
+				   struct IsdnCardState *cs)
 {
-	int bytecnt;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-#ifdef CONFIG_PCI
-#endif
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-	strcpy(tmp, NETjet_U_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_NETJET_U)
+	if (pci_enable_device(dev_netjet))
 		return(0);
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-
-#ifdef CONFIG_PCI
-
-	for ( ;; )
-	{
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			pci_set_master(dev_netjet);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-		} else {
-			printk(KERN_WARNING "NETspider-U: No PCI card found\n");
-			return(0);
-		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-		mdelay(10);
-
-		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-		mdelay(10);
-
-		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-		mdelay(10);
-
-		cs->hw.njet.auxd = 0xC0;
-		cs->hw.njet.dmactrl = 0;
-
-		byteout(cs->hw.njet.auxa, 0);
-		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-		switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
-		{
-			case 3 :
-				break;
-
-			case 0 :
-				printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
-				continue;
-
-			default :
-				printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
-				return 0;
-                }
-                break;
+	pci_set_master(dev_netjet);
+	cs->irq = dev_netjet->irq;
+	if (!cs->irq) {
+		printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
+		return(0);
 	}
-#else
+	cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+	if (!cs->hw.njet.base) {
+		printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
+		return(0);
+	}
 
-	printk(KERN_WARNING "NETspider-U: NO_PCI_BIOS\n");
-	printk(KERN_WARNING "NETspider-U: unable to config NETspider-U PCI\n");
-	return (0);
+	return (1);
+}
 
-#endif /* CONFIG_PCI */
+static int __devinit nju_cs_init(struct IsdnCard *card,
+				 struct IsdnCardState *cs)
+{
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+	mdelay(10);
 
-	bytecnt = 256;
+	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	mdelay(10);
+
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	mdelay(10);
+
+	cs->hw.njet.auxd = 0xC0;
+	cs->hw.njet.dmactrl = 0;
+
+	byteout(cs->hw.njet.auxa, 0);
+	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+	switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
+	{
+		case 3 :
+			return 1;	/* end loop */
+
+		case 0 :
+			printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
+			return -1;	/* continue looping */
+
+		default :
+			printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
+			return 0;	/* end loop & function */
+	}
+	return 1;			/* end loop */
+}
+
+static int __devinit nju_cs_init_rest(struct IsdnCard *card,
+				      struct IsdnCardState *cs)
+{
+	const int bytecnt = 256;
 
 	printk(KERN_INFO
 		"NETspider-U: PCI card configured at %#lx IRQ %d\n",
@@ -239,5 +215,48 @@
 	cs->irq_func = &netjet_u_interrupt;
 	cs->irq_flags |= IRQF_SHARED;
 	ICCVersion(cs, "NETspider-U:");
+
 	return (1);
 }
+
+static struct pci_dev *dev_netjet __devinitdata = NULL;
+
+int __devinit
+setup_netjet_u(struct IsdnCard *card)
+{
+	int ret;
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+
+	strcpy(tmp, NETjet_U_revision);
+	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_NETJET_U)
+		return(0);
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+	for ( ;; )
+	{
+		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
+			ret = nju_pci_probe(dev_netjet, cs);
+			if (!ret)
+				return(0);
+		} else {
+			printk(KERN_WARNING "NETspider-U: No PCI card found\n");
+			return(0);
+		}
+
+		ret = nju_cs_init(card, cs);
+		if (!ret)
+			return (0);
+		if (ret > 0)
+			break;
+		/* ret < 0 == continue looping */
+	}
+
+	return nju_cs_init_rest(card, cs);
+}
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 030d162..ad06f3c 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -451,6 +451,9 @@
 			spin_unlock_irqrestore(&cs->lock, flags);
 			return(0);
 		case CARD_RELEASE:
+			if (cs->hw.sedl.bus == SEDL_BUS_PCI)
+				/* disable all IRQ */
+				byteout(cs->hw.sedl.cfg_reg+ 5, 0);
 			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
 				spin_lock_irqsave(&cs->lock, flags);
 				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
@@ -468,6 +471,9 @@
 			return(0);
 		case CARD_INIT:
 			spin_lock_irqsave(&cs->lock, flags);
+			if (cs->hw.sedl.bus == SEDL_BUS_PCI)
+				/* enable all IRQ */
+				byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
 			reset_sedlbauer(cs);
 			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
 				clear_pending_isac_ints(cs);
@@ -667,7 +673,7 @@
 		byteout(cs->hw.sedl.cfg_reg, 0xff);
 		byteout(cs->hw.sedl.cfg_reg, 0x00);
 		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+		byteout(cs->hw.sedl.cfg_reg+ 5, 0); /* disable all IRQ */
 		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
 		mdelay(2);
 		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index bb3a28a..1375123 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -107,12 +107,17 @@
 	for (i = 0; i < 2; i++)
 		b_if[i] = &adapter->bcs[i].b_if;
 
-	hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", protocol);
+	if (hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb",
+			protocol) != 0)
+		goto err_b1;
+
 	st5481_start(adapter);
 
 	usb_set_intfdata(intf, adapter);
 	return 0;
 
+ err_b1:
+	st5481_release_b(&adapter->bcs[1]);
  err_b:
 	st5481_release_b(&adapter->bcs[0]);
  err_d:
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index ff15951..4ada66b 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -407,7 +407,6 @@
 {
 	int k;
 
-	spin_lock_init(&urb->lock);
 	urb->dev=dev;
 	urb->pipe=pipe;
 	urb->interval = 1;
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 3ef567b..e91c187 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -86,7 +86,6 @@
 
 
 menu "ISDN feature submodules"
-	depends on ISDN
 
 config ISDN_DRV_LOOP
 	tristate "isdnloop support"
@@ -100,7 +99,7 @@
 
 config ISDN_DIVERSION
 	tristate "Support isdn diversion services"
-	depends on ISDN && ISDN_I4L
+	depends on ISDN_I4L
 	help
 	  This option allows you to use some supplementary diversion
 	  services in conjunction with the HiSax driver on an EURO/DSS1
@@ -120,13 +119,13 @@
 endmenu
 
 comment "ISDN4Linux hardware drivers"
-	depends on NET && ISDN && ISDN_I4L
+	depends on ISDN_I4L
 
 source "drivers/isdn/hisax/Kconfig"
 
 
 menu "Active cards"
-	depends on NET && ISDN && ISDN_I4L!=n
+	depends on ISDN_I4L!=n
 
 source "drivers/isdn/icn/Kconfig"
 
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index ea5f30d..4e5f87c 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -2693,8 +2693,9 @@
 	int limit = ISDN_MSNLEN - 1;	/* MUST match the size of interface var to avoid
 					buffer overflow */
 
-	while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
+	while (strchr(" 0123456789,#.*WPTSR-", *p) && *p && --cnt>0) {
 		if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
+		    ((*p == 'R') && first) ||
 		    (*p == '*') || (*p == '#')) {
 			*q++ = *p;
 			limit--;
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 1e699bc..82d957b 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -12,6 +12,7 @@
 #include "icn.h"
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 static int portbase = ICN_BASEADDR;
 static unsigned long membase = ICN_MEMADDR;
diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
index c5a307e..0b4c4f1 100644
--- a/drivers/isdn/sc/message.c
+++ b/drivers/isdn/sc/message.c
@@ -16,7 +16,7 @@
  *     +1 (416) 297-8565
  *     +1 (416) 297-6433 Facsimile
  */
-
+#include <linux/sched.h>
 #include "includes.h"
 #include "hardware.h"
 #include "message.h"
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index e8e37d8..33fa28a 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -1,12 +1,17 @@
 #
 # KVM configuration
 #
-menu "Virtualization"
+menuconfig VIRTUALIZATION
+	bool "Virtualization"
 	depends on X86
+	default y
+
+if VIRTUALIZATION
 
 config KVM
 	tristate "Kernel-based Virtual Machine (KVM) support"
 	depends on X86 && EXPERIMENTAL
+	depends on X86_CMPXCHG64 || 64BIT
 	---help---
 	  Support hosting fully virtualized guest machines using hardware
 	  virtualization extensions.  You will need a fairly recent
@@ -35,4 +40,4 @@
 	  Provides support for KVM on AMD processors equipped with the AMD-V
 	  (SVM) extensions.
 
-endmenu
+endif # VIRTUALIZATION
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 41634fd..a7c5e6b 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -10,13 +10,17 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
 #include <linux/mm.h>
+#include <asm/signal.h>
 
 #include "vmx.h"
 #include <linux/kvm.h>
 #include <linux/kvm_para.h>
 
 #define CR0_PE_MASK (1ULL << 0)
+#define CR0_MP_MASK (1ULL << 1)
 #define CR0_TS_MASK (1ULL << 3)
 #define CR0_NE_MASK (1ULL << 5)
 #define CR0_WP_MASK (1ULL << 16)
@@ -41,7 +45,8 @@
 	(CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK \
 	 | CR0_NW_MASK | CR0_CD_MASK)
 #define KVM_VM_CR0_ALWAYS_ON \
-	(CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK)
+	(CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK | CR0_TS_MASK \
+	 | CR0_MP_MASK)
 #define KVM_GUEST_CR4_MASK \
 	(CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK)
 #define KVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK)
@@ -50,10 +55,10 @@
 #define INVALID_PAGE (~(hpa_t)0)
 #define UNMAPPED_GVA (~(gpa_t)0)
 
-#define KVM_MAX_VCPUS 1
+#define KVM_MAX_VCPUS 4
 #define KVM_ALIAS_SLOTS 4
 #define KVM_MEMORY_SLOTS 4
-#define KVM_NUM_MMU_PAGES 256
+#define KVM_NUM_MMU_PAGES 1024
 #define KVM_MIN_FREE_MMU_PAGES 5
 #define KVM_REFILL_PAGES 25
 #define KVM_MAX_CPUID_ENTRIES 40
@@ -79,6 +84,11 @@
 #define KVM_PIO_PAGE_OFFSET 1
 
 /*
+ * vcpu->requests bit members
+ */
+#define KVM_TLB_FLUSH 0
+
+/*
  * Address types:
  *
  *  gva - guest virtual address
@@ -136,7 +146,7 @@
 	gfn_t gfn;
 	union kvm_mmu_page_role role;
 
-	hpa_t page_hpa;
+	u64 *spt;
 	unsigned long slot_bitmap; /* One bit set per slot which has memory
 				    * in this shadow page.
 				    */
@@ -231,6 +241,7 @@
 	struct page *guest_pages[2];
 	unsigned guest_page_offset;
 	int in;
+	int port;
 	int size;
 	int string;
 	int down;
@@ -251,8 +262,70 @@
 	u32 halt_exits;
 	u32 request_irq_exits;
 	u32 irq_exits;
+	u32 light_exits;
+	u32 efer_reload;
 };
 
+struct kvm_io_device {
+	void (*read)(struct kvm_io_device *this,
+		     gpa_t addr,
+		     int len,
+		     void *val);
+	void (*write)(struct kvm_io_device *this,
+		      gpa_t addr,
+		      int len,
+		      const void *val);
+	int (*in_range)(struct kvm_io_device *this, gpa_t addr);
+	void (*destructor)(struct kvm_io_device *this);
+
+	void             *private;
+};
+
+static inline void kvm_iodevice_read(struct kvm_io_device *dev,
+				     gpa_t addr,
+				     int len,
+				     void *val)
+{
+	dev->read(dev, addr, len, val);
+}
+
+static inline void kvm_iodevice_write(struct kvm_io_device *dev,
+				      gpa_t addr,
+				      int len,
+				      const void *val)
+{
+	dev->write(dev, addr, len, val);
+}
+
+static inline int kvm_iodevice_inrange(struct kvm_io_device *dev, gpa_t addr)
+{
+	return dev->in_range(dev, addr);
+}
+
+static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
+{
+	if (dev->destructor)
+		dev->destructor(dev);
+}
+
+/*
+ * It would be nice to use something smarter than a linear search, TBD...
+ * Thankfully we dont expect many devices to register (famous last words :),
+ * so until then it will suffice.  At least its abstracted so we can change
+ * in one place.
+ */
+struct kvm_io_bus {
+	int                   dev_count;
+#define NR_IOBUS_DEVS 6
+	struct kvm_io_device *devs[NR_IOBUS_DEVS];
+};
+
+void kvm_io_bus_init(struct kvm_io_bus *bus);
+void kvm_io_bus_destroy(struct kvm_io_bus *bus);
+struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, gpa_t addr);
+void kvm_io_bus_register_dev(struct kvm_io_bus *bus,
+			     struct kvm_io_device *dev);
+
 struct kvm_vcpu {
 	struct kvm *kvm;
 	union {
@@ -265,6 +338,8 @@
 	u64 host_tsc;
 	struct kvm_run *run;
 	int interrupt_window_open;
+	int guest_mode;
+	unsigned long requests;
 	unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
 #define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long)
 	unsigned long irq_pending[NR_IRQ_WORDS];
@@ -284,15 +359,20 @@
 	u64 apic_base;
 	u64 ia32_misc_enable_msr;
 	int nmsrs;
+	int save_nmsrs;
+	int msr_offset_efer;
+#ifdef CONFIG_X86_64
+	int msr_offset_kernel_gs_base;
+#endif
 	struct vmx_msr_entry *guest_msrs;
 	struct vmx_msr_entry *host_msrs;
 
-	struct list_head free_pages;
-	struct kvm_mmu_page page_header_buf[KVM_NUM_MMU_PAGES];
 	struct kvm_mmu mmu;
 
 	struct kvm_mmu_memory_cache mmu_pte_chain_cache;
 	struct kvm_mmu_memory_cache mmu_rmap_desc_cache;
+	struct kvm_mmu_memory_cache mmu_page_cache;
+	struct kvm_mmu_memory_cache mmu_page_header_cache;
 
 	gfn_t last_pt_write_gfn;
 	int   last_pt_write_count;
@@ -303,6 +383,12 @@
 	char *host_fx_image;
 	char *guest_fx_image;
 	int fpu_active;
+	int guest_fpu_loaded;
+	struct vmx_host_state {
+		int loaded;
+		u16 fs_sel, gs_sel, ldt_sel;
+		int fs_gs_ldt_reload_needed;
+	} vmx_host_state;
 
 	int mmio_needed;
 	int mmio_read_completed;
@@ -329,6 +415,7 @@
 			u32 ar;
 		} tr, es, ds, fs, gs;
 	} rmode;
+	int halt_request; /* real mode on Intel only */
 
 	int cpuid_nent;
 	struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];
@@ -360,12 +447,15 @@
 	struct list_head active_mmu_pages;
 	int n_free_mmu_pages;
 	struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
+	int nvcpus;
 	struct kvm_vcpu vcpus[KVM_MAX_VCPUS];
 	int memory_config_version;
 	int busy;
 	unsigned long rmap_overflow;
 	struct list_head vm_list;
 	struct file *filp;
+	struct kvm_io_bus mmio_bus;
+	struct kvm_io_bus pio_bus;
 };
 
 struct descriptor_table {
@@ -486,6 +576,7 @@
 		  int size, unsigned long count, int string, int down,
 		  gva_t address, int rep, unsigned port);
 void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
+int kvm_emulate_halt(struct kvm_vcpu *vcpu);
 int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address);
 int emulate_clts(struct kvm_vcpu *vcpu);
 int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr,
@@ -507,6 +598,9 @@
 void load_msrs(struct vmx_msr_entry *e, int n);
 void save_msrs(struct vmx_msr_entry *e, int n);
 void kvm_resched(struct kvm_vcpu *vcpu);
+void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);
+void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
+void kvm_flush_remote_tlbs(struct kvm *kvm);
 
 int kvm_read_guest(struct kvm_vcpu *vcpu,
 	       gva_t addr,
@@ -520,10 +614,12 @@
 
 unsigned long segment_base(u16 selector);
 
-void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);
-void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);
+void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+		       const u8 *old, const u8 *new, int bytes);
 int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
 void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
+int kvm_mmu_load(struct kvm_vcpu *vcpu);
+void kvm_mmu_unload(struct kvm_vcpu *vcpu);
 
 int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run);
 
@@ -535,6 +631,14 @@
 	return vcpu->mmu.page_fault(vcpu, gva, error_code);
 }
 
+static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu)
+{
+	if (likely(vcpu->mmu.root_hpa != INVALID_PAGE))
+		return 0;
+
+	return kvm_mmu_load(vcpu);
+}
+
 static inline int is_long_mode(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_X86_64
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 0d89260..1b206f1 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -16,33 +16,33 @@
  */
 
 #include "kvm.h"
+#include "x86_emulate.h"
+#include "segment_descriptor.h"
 
 #include <linux/kvm.h>
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <linux/magic.h>
-#include <asm/processor.h>
 #include <linux/percpu.h>
 #include <linux/gfp.h>
-#include <asm/msr.h>
 #include <linux/mm.h>
 #include <linux/miscdevice.h>
 #include <linux/vmalloc.h>
-#include <asm/uaccess.h>
 #include <linux/reboot.h>
-#include <asm/io.h>
 #include <linux/debugfs.h>
 #include <linux/highmem.h>
 #include <linux/file.h>
-#include <asm/desc.h>
 #include <linux/sysdev.h>
 #include <linux/cpu.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/mount.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/smp.h>
+#include <linux/anon_inodes.h>
 
-#include "x86_emulate.h"
-#include "segment_descriptor.h"
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/desc.h>
 
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
@@ -50,8 +50,12 @@
 static DEFINE_SPINLOCK(kvm_lock);
 static LIST_HEAD(vm_list);
 
+static cpumask_t cpus_hardware_enabled;
+
 struct kvm_arch_ops *kvm_arch_ops;
 
+static void hardware_disable(void *ignored);
+
 #define STAT_OFFSET(x) offsetof(struct kvm_vcpu, stat.x)
 
 static struct kvm_stats_debugfs_item {
@@ -71,13 +75,13 @@
 	{ "halt_exits", STAT_OFFSET(halt_exits) },
 	{ "request_irq", STAT_OFFSET(request_irq_exits) },
 	{ "irq_exits", STAT_OFFSET(irq_exits) },
+	{ "light_exits", STAT_OFFSET(light_exits) },
+	{ "efer_reload", STAT_OFFSET(efer_reload) },
 	{ NULL }
 };
 
 static struct dentry *debugfs_dir;
 
-struct vfsmount *kvmfs_mnt;
-
 #define MAX_IO_MSRS 256
 
 #define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL
@@ -99,55 +103,6 @@
 static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
 			   unsigned long arg);
 
-static struct inode *kvmfs_inode(struct file_operations *fops)
-{
-	int error = -ENOMEM;
-	struct inode *inode = new_inode(kvmfs_mnt->mnt_sb);
-
-	if (!inode)
-		goto eexit_1;
-
-	inode->i_fop = fops;
-
-	/*
-	 * Mark the inode dirty from the very beginning,
-	 * that way it will never be moved to the dirty
-	 * list because mark_inode_dirty() will think
-	 * that it already _is_ on the dirty list.
-	 */
-	inode->i_state = I_DIRTY;
-	inode->i_mode = S_IRUSR | S_IWUSR;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	return inode;
-
-eexit_1:
-	return ERR_PTR(error);
-}
-
-static struct file *kvmfs_file(struct inode *inode, void *private_data)
-{
-	struct file *file = get_empty_filp();
-
-	if (!file)
-		return ERR_PTR(-ENFILE);
-
-	file->f_path.mnt = mntget(kvmfs_mnt);
-	file->f_path.dentry = d_alloc_anon(inode);
-	if (!file->f_path.dentry)
-		return ERR_PTR(-ENOMEM);
-	file->f_mapping = inode->i_mapping;
-
-	file->f_pos = 0;
-	file->f_flags = O_RDWR;
-	file->f_op = inode->i_fop;
-	file->f_mode = FMODE_READ | FMODE_WRITE;
-	file->f_version = 0;
-	file->private_data = private_data;
-	return file;
-}
-
 unsigned long segment_base(u16 selector)
 {
 	struct descriptor_table gdt;
@@ -252,6 +207,28 @@
 }
 EXPORT_SYMBOL_GPL(kvm_write_guest);
 
+void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
+{
+	if (!vcpu->fpu_active || vcpu->guest_fpu_loaded)
+		return;
+
+	vcpu->guest_fpu_loaded = 1;
+	fx_save(vcpu->host_fx_image);
+	fx_restore(vcpu->guest_fx_image);
+}
+EXPORT_SYMBOL_GPL(kvm_load_guest_fpu);
+
+void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
+{
+	if (!vcpu->guest_fpu_loaded)
+		return;
+
+	vcpu->guest_fpu_loaded = 0;
+	fx_save(vcpu->guest_fx_image);
+	fx_restore(vcpu->host_fx_image);
+}
+EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
+
 /*
  * Switches to specified vcpu, until a matching vcpu_put()
  */
@@ -284,6 +261,48 @@
 	mutex_unlock(&vcpu->mutex);
 }
 
+static void ack_flush(void *_completed)
+{
+	atomic_t *completed = _completed;
+
+	atomic_inc(completed);
+}
+
+void kvm_flush_remote_tlbs(struct kvm *kvm)
+{
+	int i, cpu, needed;
+	cpumask_t cpus;
+	struct kvm_vcpu *vcpu;
+	atomic_t completed;
+
+	atomic_set(&completed, 0);
+	cpus_clear(cpus);
+	needed = 0;
+	for (i = 0; i < kvm->nvcpus; ++i) {
+		vcpu = &kvm->vcpus[i];
+		if (test_and_set_bit(KVM_TLB_FLUSH, &vcpu->requests))
+			continue;
+		cpu = vcpu->cpu;
+		if (cpu != -1 && cpu != raw_smp_processor_id())
+			if (!cpu_isset(cpu, cpus)) {
+				cpu_set(cpu, cpus);
+				++needed;
+			}
+	}
+
+	/*
+	 * We really want smp_call_function_mask() here.  But that's not
+	 * available, so ipi all cpus in parallel and wait for them
+	 * to complete.
+	 */
+	for (cpu = first_cpu(cpus); cpu != NR_CPUS; cpu = next_cpu(cpu, cpus))
+		smp_call_function_single(cpu, ack_flush, &completed, 1, 0);
+	while (atomic_read(&completed) != needed) {
+		cpu_relax();
+		barrier();
+	}
+}
+
 static struct kvm *kvm_create_vm(void)
 {
 	struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
@@ -292,8 +311,13 @@
 	if (!kvm)
 		return ERR_PTR(-ENOMEM);
 
+	kvm_io_bus_init(&kvm->pio_bus);
 	spin_lock_init(&kvm->lock);
 	INIT_LIST_HEAD(&kvm->active_mmu_pages);
+	spin_lock(&kvm_lock);
+	list_add(&kvm->vm_list, &vm_list);
+	spin_unlock(&kvm_lock);
+	kvm_io_bus_init(&kvm->mmio_bus);
 	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
 		struct kvm_vcpu *vcpu = &kvm->vcpus[i];
 
@@ -301,10 +325,6 @@
 		vcpu->cpu = -1;
 		vcpu->kvm = kvm;
 		vcpu->mmu.root_hpa = INVALID_PAGE;
-		INIT_LIST_HEAD(&vcpu->free_pages);
-		spin_lock(&kvm_lock);
-		list_add(&kvm->vm_list, &vm_list);
-		spin_unlock(&kvm_lock);
 	}
 	return kvm;
 }
@@ -357,6 +377,16 @@
 		}
 }
 
+static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)
+{
+	if (!vcpu->vmcs)
+		return;
+
+	vcpu_load(vcpu);
+	kvm_mmu_unload(vcpu);
+	vcpu_put(vcpu);
+}
+
 static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
 {
 	if (!vcpu->vmcs)
@@ -377,6 +407,11 @@
 {
 	unsigned int i;
 
+	/*
+	 * Unpin any mmu pages first.
+	 */
+	for (i = 0; i < KVM_MAX_VCPUS; ++i)
+		kvm_unload_vcpu_mmu(&kvm->vcpus[i]);
 	for (i = 0; i < KVM_MAX_VCPUS; ++i)
 		kvm_free_vcpu(&kvm->vcpus[i]);
 }
@@ -391,6 +426,8 @@
 	spin_lock(&kvm_lock);
 	list_del(&kvm->vm_list);
 	spin_unlock(&kvm_lock);
+	kvm_io_bus_destroy(&kvm->pio_bus);
+	kvm_io_bus_destroy(&kvm->mmio_bus);
 	kvm_free_vcpus(kvm);
 	kvm_free_physmem(kvm);
 	kfree(kvm);
@@ -946,7 +983,7 @@
 void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
 {
 	int i;
-	struct kvm_memory_slot *memslot = NULL;
+	struct kvm_memory_slot *memslot;
 	unsigned long rel_gfn;
 
 	for (i = 0; i < kvm->nmemslots; ++i) {
@@ -955,7 +992,7 @@
 		if (gfn >= memslot->base_gfn
 		    && gfn < memslot->base_gfn + memslot->npages) {
 
-			if (!memslot || !memslot->dirty_bitmap)
+			if (!memslot->dirty_bitmap)
 				return;
 
 			rel_gfn = gfn - memslot->base_gfn;
@@ -1014,12 +1051,31 @@
 	return X86EMUL_UNHANDLEABLE;
 }
 
+static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
+						gpa_t addr)
+{
+	/*
+	 * Note that its important to have this wrapper function because
+	 * in the very near future we will be checking for MMIOs against
+	 * the LAPIC as well as the general MMIO bus
+	 */
+	return kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr);
+}
+
+static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu,
+					       gpa_t addr)
+{
+	return kvm_io_bus_find_dev(&vcpu->kvm->pio_bus, addr);
+}
+
 static int emulator_read_emulated(unsigned long addr,
 				  void *val,
 				  unsigned int bytes,
 				  struct x86_emulate_ctxt *ctxt)
 {
-	struct kvm_vcpu *vcpu = ctxt->vcpu;
+	struct kvm_vcpu      *vcpu = ctxt->vcpu;
+	struct kvm_io_device *mmio_dev;
+	gpa_t                 gpa;
 
 	if (vcpu->mmio_read_completed) {
 		memcpy(val, vcpu->mmio_data, bytes);
@@ -1028,18 +1084,26 @@
 	} else if (emulator_read_std(addr, val, bytes, ctxt)
 		   == X86EMUL_CONTINUE)
 		return X86EMUL_CONTINUE;
-	else {
-		gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
 
-		if (gpa == UNMAPPED_GVA)
-			return X86EMUL_PROPAGATE_FAULT;
-		vcpu->mmio_needed = 1;
-		vcpu->mmio_phys_addr = gpa;
-		vcpu->mmio_size = bytes;
-		vcpu->mmio_is_write = 0;
+	gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+	if (gpa == UNMAPPED_GVA)
+		return X86EMUL_PROPAGATE_FAULT;
 
-		return X86EMUL_UNHANDLEABLE;
+	/*
+	 * Is this MMIO handled locally?
+	 */
+	mmio_dev = vcpu_find_mmio_dev(vcpu, gpa);
+	if (mmio_dev) {
+		kvm_iodevice_read(mmio_dev, gpa, bytes, val);
+		return X86EMUL_CONTINUE;
 	}
+
+	vcpu->mmio_needed = 1;
+	vcpu->mmio_phys_addr = gpa;
+	vcpu->mmio_size = bytes;
+	vcpu->mmio_is_write = 0;
+
+	return X86EMUL_UNHANDLEABLE;
 }
 
 static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
@@ -1047,18 +1111,20 @@
 {
 	struct page *page;
 	void *virt;
+	unsigned offset = offset_in_page(gpa);
 
 	if (((gpa + bytes - 1) >> PAGE_SHIFT) != (gpa >> PAGE_SHIFT))
 		return 0;
 	page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
 	if (!page)
 		return 0;
-	kvm_mmu_pre_write(vcpu, gpa, bytes);
 	mark_page_dirty(vcpu->kvm, gpa >> PAGE_SHIFT);
 	virt = kmap_atomic(page, KM_USER0);
-	memcpy(virt + offset_in_page(gpa), val, bytes);
+	if (memcmp(virt + offset_in_page(gpa), val, bytes)) {
+		kvm_mmu_pte_write(vcpu, gpa, virt + offset, val, bytes);
+		memcpy(virt + offset_in_page(gpa), val, bytes);
+	}
 	kunmap_atomic(virt, KM_USER0);
-	kvm_mmu_post_write(vcpu, gpa, bytes);
 	return 1;
 }
 
@@ -1067,8 +1133,9 @@
 				   unsigned int bytes,
 				   struct x86_emulate_ctxt *ctxt)
 {
-	struct kvm_vcpu *vcpu = ctxt->vcpu;
-	gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+	struct kvm_vcpu      *vcpu = ctxt->vcpu;
+	struct kvm_io_device *mmio_dev;
+	gpa_t                 gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
 
 	if (gpa == UNMAPPED_GVA) {
 		kvm_arch_ops->inject_page_fault(vcpu, addr, 2);
@@ -1078,6 +1145,15 @@
 	if (emulator_write_phys(vcpu, gpa, val, bytes))
 		return X86EMUL_CONTINUE;
 
+	/*
+	 * Is this MMIO handled locally?
+	 */
+	mmio_dev = vcpu_find_mmio_dev(vcpu, gpa);
+	if (mmio_dev) {
+		kvm_iodevice_write(mmio_dev, gpa, bytes, val);
+		return X86EMUL_CONTINUE;
+	}
+
 	vcpu->mmio_needed = 1;
 	vcpu->mmio_phys_addr = gpa;
 	vcpu->mmio_size = bytes;
@@ -1246,6 +1322,17 @@
 }
 EXPORT_SYMBOL_GPL(emulate_instruction);
 
+int kvm_emulate_halt(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->irq_summary)
+		return 1;
+
+	vcpu->run->exit_reason = KVM_EXIT_HLT;
+	++vcpu->stat.halt_exits;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_emulate_halt);
+
 int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	unsigned long nr, a0, a1, a2, a3, a4, a5, ret;
@@ -1446,6 +1533,7 @@
 	case MSR_IA32_MC0_MISC+16:
 	case MSR_IA32_UCODE_REV:
 	case MSR_IA32_PERF_STATUS:
+	case MSR_IA32_EBL_CR_POWERON:
 		/* MTRR registers */
 	case 0xfe:
 	case 0x200 ... 0x2ff:
@@ -1704,6 +1792,20 @@
 	return 0;
 }
 
+void kernel_pio(struct kvm_io_device *pio_dev, struct kvm_vcpu *vcpu)
+{
+	/* TODO: String I/O for in kernel device */
+
+	if (vcpu->pio.in)
+		kvm_iodevice_read(pio_dev, vcpu->pio.port,
+				  vcpu->pio.size,
+				  vcpu->pio_data);
+	else
+		kvm_iodevice_write(pio_dev, vcpu->pio.port,
+				   vcpu->pio.size,
+				   vcpu->pio_data);
+}
+
 int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
 		  int size, unsigned long count, int string, int down,
 		  gva_t address, int rep, unsigned port)
@@ -1712,6 +1814,7 @@
 	int i;
 	int nr_pages = 1;
 	struct page *page;
+	struct kvm_io_device *pio_dev;
 
 	vcpu->run->exit_reason = KVM_EXIT_IO;
 	vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
@@ -1723,17 +1826,27 @@
 	vcpu->pio.cur_count = count;
 	vcpu->pio.size = size;
 	vcpu->pio.in = in;
+	vcpu->pio.port = port;
 	vcpu->pio.string = string;
 	vcpu->pio.down = down;
 	vcpu->pio.guest_page_offset = offset_in_page(address);
 	vcpu->pio.rep = rep;
 
+	pio_dev = vcpu_find_pio_dev(vcpu, port);
 	if (!string) {
 		kvm_arch_ops->cache_regs(vcpu);
 		memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4);
 		kvm_arch_ops->decache_regs(vcpu);
+		if (pio_dev) {
+			kernel_pio(pio_dev, vcpu);
+			complete_pio(vcpu);
+			return 1;
+		}
 		return 0;
 	}
+	/* TODO: String I/O for in kernel device */
+	if (pio_dev)
+		printk(KERN_ERR "kvm_setup_pio: no string io support\n");
 
 	if (!count) {
 		kvm_arch_ops->skip_emulated_instruction(vcpu);
@@ -2250,34 +2363,12 @@
 	struct inode *inode;
 	struct file *file;
 
+	r = anon_inode_getfd(&fd, &inode, &file,
+			     "kvm-vcpu", &kvm_vcpu_fops, vcpu);
+	if (r)
+		return r;
 	atomic_inc(&vcpu->kvm->filp->f_count);
-	inode = kvmfs_inode(&kvm_vcpu_fops);
-	if (IS_ERR(inode)) {
-		r = PTR_ERR(inode);
-		goto out1;
-	}
-
-	file = kvmfs_file(inode, vcpu);
-	if (IS_ERR(file)) {
-		r = PTR_ERR(file);
-		goto out2;
-	}
-
-	r = get_unused_fd();
-	if (r < 0)
-		goto out3;
-	fd = r;
-	fd_install(fd, file);
-
 	return fd;
-
-out3:
-	fput(file);
-out2:
-	iput(inode);
-out1:
-	fput(vcpu->kvm->filp);
-	return r;
 }
 
 /*
@@ -2340,6 +2431,11 @@
 	if (r < 0)
 		goto out_free_vcpus;
 
+	spin_lock(&kvm_lock);
+	if (n >= kvm->nvcpus)
+		kvm->nvcpus = n + 1;
+	spin_unlock(&kvm_lock);
+
 	return r;
 
 out_free_vcpus:
@@ -2353,6 +2449,27 @@
 	return r;
 }
 
+static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
+{
+	u64 efer;
+	int i;
+	struct kvm_cpuid_entry *e, *entry;
+
+	rdmsrl(MSR_EFER, efer);
+	entry = NULL;
+	for (i = 0; i < vcpu->cpuid_nent; ++i) {
+		e = &vcpu->cpuid_entries[i];
+		if (e->function == 0x80000001) {
+			entry = e;
+			break;
+		}
+	}
+	if (entry && (entry->edx & EFER_NX) && !(efer & EFER_NX)) {
+		entry->edx &= ~(1 << 20);
+		printk(KERN_INFO ": guest NX capability removed\n");
+	}
+}
+
 static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
 				    struct kvm_cpuid *cpuid,
 				    struct kvm_cpuid_entry __user *entries)
@@ -2367,6 +2484,7 @@
 			   cpuid->nent * sizeof(struct kvm_cpuid_entry)))
 		goto out;
 	vcpu->cpuid_nent = cpuid->nent;
+	cpuid_fix_nx_cap(vcpu);
 	return 0;
 
 out:
@@ -2715,41 +2833,18 @@
 	struct file *file;
 	struct kvm *kvm;
 
-	inode = kvmfs_inode(&kvm_vm_fops);
-	if (IS_ERR(inode)) {
-		r = PTR_ERR(inode);
-		goto out1;
-	}
-
 	kvm = kvm_create_vm();
-	if (IS_ERR(kvm)) {
-		r = PTR_ERR(kvm);
-		goto out2;
+	if (IS_ERR(kvm))
+		return PTR_ERR(kvm);
+	r = anon_inode_getfd(&fd, &inode, &file, "kvm-vm", &kvm_vm_fops, kvm);
+	if (r) {
+		kvm_destroy_vm(kvm);
+		return r;
 	}
 
-	file = kvmfs_file(inode, kvm);
-	if (IS_ERR(file)) {
-		r = PTR_ERR(file);
-		goto out3;
-	}
 	kvm->filp = file;
 
-	r = get_unused_fd();
-	if (r < 0)
-		goto out4;
-	fd = r;
-	fd_install(fd, file);
-
 	return fd;
-
-out4:
-	fput(file);
-out3:
-	kvm_destroy_vm(kvm);
-out2:
-	iput(inode);
-out1:
-	return r;
 }
 
 static long kvm_dev_ioctl(struct file *filp,
@@ -2839,7 +2934,7 @@
 		 * in vmx root mode.
 		 */
 		printk(KERN_INFO "kvm: exiting hardware virtualization\n");
-		on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
+		on_each_cpu(hardware_disable, NULL, 0, 1);
 	}
 	return NOTIFY_OK;
 }
@@ -2882,33 +2977,88 @@
 	spin_unlock(&kvm_lock);
 }
 
+static void hardware_enable(void *junk)
+{
+	int cpu = raw_smp_processor_id();
+
+	if (cpu_isset(cpu, cpus_hardware_enabled))
+		return;
+	cpu_set(cpu, cpus_hardware_enabled);
+	kvm_arch_ops->hardware_enable(NULL);
+}
+
+static void hardware_disable(void *junk)
+{
+	int cpu = raw_smp_processor_id();
+
+	if (!cpu_isset(cpu, cpus_hardware_enabled))
+		return;
+	cpu_clear(cpu, cpus_hardware_enabled);
+	decache_vcpus_on_cpu(cpu);
+	kvm_arch_ops->hardware_disable(NULL);
+}
+
 static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
 			   void *v)
 {
 	int cpu = (long)v;
 
 	switch (val) {
-	case CPU_DOWN_PREPARE:
-	case CPU_DOWN_PREPARE_FROZEN:
+	case CPU_DYING:
+	case CPU_DYING_FROZEN:
 	case CPU_UP_CANCELED:
 	case CPU_UP_CANCELED_FROZEN:
 		printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
 		       cpu);
-		decache_vcpus_on_cpu(cpu);
-		smp_call_function_single(cpu, kvm_arch_ops->hardware_disable,
-					 NULL, 0, 1);
+		smp_call_function_single(cpu, hardware_disable, NULL, 0, 1);
 		break;
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
 		printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
 		       cpu);
-		smp_call_function_single(cpu, kvm_arch_ops->hardware_enable,
-					 NULL, 0, 1);
+		smp_call_function_single(cpu, hardware_enable, NULL, 0, 1);
 		break;
 	}
 	return NOTIFY_OK;
 }
 
+void kvm_io_bus_init(struct kvm_io_bus *bus)
+{
+	memset(bus, 0, sizeof(*bus));
+}
+
+void kvm_io_bus_destroy(struct kvm_io_bus *bus)
+{
+	int i;
+
+	for (i = 0; i < bus->dev_count; i++) {
+		struct kvm_io_device *pos = bus->devs[i];
+
+		kvm_iodevice_destructor(pos);
+	}
+}
+
+struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, gpa_t addr)
+{
+	int i;
+
+	for (i = 0; i < bus->dev_count; i++) {
+		struct kvm_io_device *pos = bus->devs[i];
+
+		if (pos->in_range(pos, addr))
+			return pos;
+	}
+
+	return NULL;
+}
+
+void kvm_io_bus_register_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev)
+{
+	BUG_ON(bus->dev_count > (NR_IOBUS_DEVS-1));
+
+	bus->devs[bus->dev_count++] = dev;
+}
+
 static struct notifier_block kvm_cpu_notifier = {
 	.notifier_call = kvm_cpu_hotplug,
 	.priority = 20, /* must be > scheduler priority */
@@ -2960,14 +3110,13 @@
 
 static int kvm_suspend(struct sys_device *dev, pm_message_t state)
 {
-	decache_vcpus_on_cpu(raw_smp_processor_id());
-	on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
+	hardware_disable(NULL);
 	return 0;
 }
 
 static int kvm_resume(struct sys_device *dev)
 {
-	on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
+	hardware_enable(NULL);
 	return 0;
 }
 
@@ -2984,18 +3133,6 @@
 
 hpa_t bad_page_address;
 
-static int kvmfs_get_sb(struct file_system_type *fs_type, int flags,
-			const char *dev_name, void *data, struct vfsmount *mnt)
-{
-	return get_sb_pseudo(fs_type, "kvm:", NULL, KVMFS_SUPER_MAGIC, mnt);
-}
-
-static struct file_system_type kvm_fs_type = {
-	.name		= "kvmfs",
-	.get_sb		= kvmfs_get_sb,
-	.kill_sb	= kill_anon_super,
-};
-
 int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
 {
 	int r;
@@ -3020,7 +3157,7 @@
 	if (r < 0)
 		goto out;
 
-	on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
+	on_each_cpu(hardware_enable, NULL, 0, 1);
 	r = register_cpu_notifier(&kvm_cpu_notifier);
 	if (r)
 		goto out_free_1;
@@ -3052,7 +3189,7 @@
 	unregister_reboot_notifier(&kvm_reboot_notifier);
 	unregister_cpu_notifier(&kvm_cpu_notifier);
 out_free_1:
-	on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
+	on_each_cpu(hardware_disable, NULL, 0, 1);
 	kvm_arch_ops->hardware_unsetup();
 out:
 	kvm_arch_ops = NULL;
@@ -3066,7 +3203,7 @@
 	sysdev_class_unregister(&kvm_sysdev_class);
 	unregister_reboot_notifier(&kvm_reboot_notifier);
 	unregister_cpu_notifier(&kvm_cpu_notifier);
-	on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
+	on_each_cpu(hardware_disable, NULL, 0, 1);
 	kvm_arch_ops->hardware_unsetup();
 	kvm_arch_ops = NULL;
 }
@@ -3080,14 +3217,6 @@
 	if (r)
 		goto out4;
 
-	r = register_filesystem(&kvm_fs_type);
-	if (r)
-		goto out3;
-
-	kvmfs_mnt = kern_mount(&kvm_fs_type);
-	r = PTR_ERR(kvmfs_mnt);
-	if (IS_ERR(kvmfs_mnt))
-		goto out2;
 	kvm_init_debug();
 
 	kvm_init_msr_list();
@@ -3104,10 +3233,6 @@
 
 out:
 	kvm_exit_debug();
-	mntput(kvmfs_mnt);
-out2:
-	unregister_filesystem(&kvm_fs_type);
-out3:
 	kvm_mmu_module_exit();
 out4:
 	return r;
@@ -3117,8 +3242,6 @@
 {
 	kvm_exit_debug();
 	__free_page(pfn_to_page(bad_page_address >> PAGE_SHIFT));
-	mntput(kvmfs_mnt);
-	unregister_filesystem(&kvm_fs_type);
 	kvm_mmu_module_exit();
 }
 
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index e8e2281..b297a6b 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -16,15 +16,18 @@
  * the COPYING file in the top-level directory.
  *
  */
+
+#include "vmx.h"
+#include "kvm.h"
+
 #include <linux/types.h>
 #include <linux/string.h>
-#include <asm/page.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/module.h>
 
-#include "vmx.h"
-#include "kvm.h"
+#include <asm/page.h>
+#include <asm/cmpxchg.h>
 
 #undef MMU_DEBUG
 
@@ -90,25 +93,11 @@
 #define PT32_DIR_PSE36_MASK (((1ULL << PT32_DIR_PSE36_SIZE) - 1) << PT32_DIR_PSE36_SHIFT)
 
 
-#define PT32_PTE_COPY_MASK \
-	(PT_PRESENT_MASK | PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_GLOBAL_MASK)
-
-#define PT64_PTE_COPY_MASK (PT64_NX_MASK | PT32_PTE_COPY_MASK)
-
 #define PT_FIRST_AVAIL_BITS_SHIFT 9
 #define PT64_SECOND_AVAIL_BITS_SHIFT 52
 
-#define PT_SHADOW_PS_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
 #define PT_SHADOW_IO_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
 
-#define PT_SHADOW_WRITABLE_SHIFT (PT_FIRST_AVAIL_BITS_SHIFT + 1)
-#define PT_SHADOW_WRITABLE_MASK (1ULL << PT_SHADOW_WRITABLE_SHIFT)
-
-#define PT_SHADOW_USER_SHIFT (PT_SHADOW_WRITABLE_SHIFT + 1)
-#define PT_SHADOW_USER_MASK (1ULL << (PT_SHADOW_USER_SHIFT))
-
-#define PT_SHADOW_BITS_OFFSET (PT_SHADOW_WRITABLE_SHIFT - PT_WRITABLE_SHIFT)
-
 #define VALID_PAGE(x) ((x) != INVALID_PAGE)
 
 #define PT64_LEVEL_BITS 9
@@ -165,6 +154,8 @@
 
 static struct kmem_cache *pte_chain_cache;
 static struct kmem_cache *rmap_desc_cache;
+static struct kmem_cache *mmu_page_cache;
+static struct kmem_cache *mmu_page_header_cache;
 
 static int is_write_protection(struct kvm_vcpu *vcpu)
 {
@@ -202,6 +193,15 @@
 		== (PT_WRITABLE_MASK | PT_PRESENT_MASK);
 }
 
+static void set_shadow_pte(u64 *sptep, u64 spte)
+{
+#ifdef CONFIG_X86_64
+	set_64bit((unsigned long *)sptep, spte);
+#else
+	set_64bit((unsigned long long *)sptep, spte);
+#endif
+}
+
 static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
 				  struct kmem_cache *base_cache, int min,
 				  gfp_t gfp_flags)
@@ -235,6 +235,14 @@
 		goto out;
 	r = mmu_topup_memory_cache(&vcpu->mmu_rmap_desc_cache,
 				   rmap_desc_cache, 1, gfp_flags);
+	if (r)
+		goto out;
+	r = mmu_topup_memory_cache(&vcpu->mmu_page_cache,
+				   mmu_page_cache, 4, gfp_flags);
+	if (r)
+		goto out;
+	r = mmu_topup_memory_cache(&vcpu->mmu_page_header_cache,
+				   mmu_page_header_cache, 4, gfp_flags);
 out:
 	return r;
 }
@@ -258,6 +266,8 @@
 {
 	mmu_free_memory_cache(&vcpu->mmu_pte_chain_cache);
 	mmu_free_memory_cache(&vcpu->mmu_rmap_desc_cache);
+	mmu_free_memory_cache(&vcpu->mmu_page_cache);
+	mmu_free_memory_cache(&vcpu->mmu_page_header_cache);
 }
 
 static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc,
@@ -433,19 +443,18 @@
 		BUG_ON(!(*spte & PT_WRITABLE_MASK));
 		rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
 		rmap_remove(vcpu, spte);
-		kvm_arch_ops->tlb_flush(vcpu);
-		*spte &= ~(u64)PT_WRITABLE_MASK;
+		set_shadow_pte(spte, *spte & ~PT_WRITABLE_MASK);
+		kvm_flush_remote_tlbs(vcpu->kvm);
 	}
 }
 
 #ifdef MMU_DEBUG
-static int is_empty_shadow_page(hpa_t page_hpa)
+static int is_empty_shadow_page(u64 *spt)
 {
 	u64 *pos;
 	u64 *end;
 
-	for (pos = __va(page_hpa), end = pos + PAGE_SIZE / sizeof(u64);
-		      pos != end; pos++)
+	for (pos = spt, end = pos + PAGE_SIZE / sizeof(u64); pos != end; pos++)
 		if (*pos != 0) {
 			printk(KERN_ERR "%s: %p %llx\n", __FUNCTION__,
 			       pos, *pos);
@@ -455,13 +464,13 @@
 }
 #endif
 
-static void kvm_mmu_free_page(struct kvm_vcpu *vcpu, hpa_t page_hpa)
+static void kvm_mmu_free_page(struct kvm_vcpu *vcpu,
+			      struct kvm_mmu_page *page_head)
 {
-	struct kvm_mmu_page *page_head = page_header(page_hpa);
-
-	ASSERT(is_empty_shadow_page(page_hpa));
-	page_head->page_hpa = page_hpa;
-	list_move(&page_head->link, &vcpu->free_pages);
+	ASSERT(is_empty_shadow_page(page_head->spt));
+	list_del(&page_head->link);
+	mmu_memory_cache_free(&vcpu->mmu_page_cache, page_head->spt);
+	mmu_memory_cache_free(&vcpu->mmu_page_header_cache, page_head);
 	++vcpu->kvm->n_free_mmu_pages;
 }
 
@@ -475,12 +484,15 @@
 {
 	struct kvm_mmu_page *page;
 
-	if (list_empty(&vcpu->free_pages))
+	if (!vcpu->kvm->n_free_mmu_pages)
 		return NULL;
 
-	page = list_entry(vcpu->free_pages.next, struct kvm_mmu_page, link);
-	list_move(&page->link, &vcpu->kvm->active_mmu_pages);
-	ASSERT(is_empty_shadow_page(page->page_hpa));
+	page = mmu_memory_cache_alloc(&vcpu->mmu_page_header_cache,
+				      sizeof *page);
+	page->spt = mmu_memory_cache_alloc(&vcpu->mmu_page_cache, PAGE_SIZE);
+	set_page_private(virt_to_page(page->spt), (unsigned long)page);
+	list_add(&page->link, &vcpu->kvm->active_mmu_pages);
+	ASSERT(is_empty_shadow_page(page->spt));
 	page->slot_bitmap = 0;
 	page->multimapped = 0;
 	page->parent_pte = parent_pte;
@@ -638,7 +650,7 @@
 	u64 *pt;
 	u64 ent;
 
-	pt = __va(page->page_hpa);
+	pt = page->spt;
 
 	if (page->role.level == PT_PAGE_TABLE_LEVEL) {
 		for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
@@ -646,7 +658,7 @@
 				rmap_remove(vcpu, &pt[i]);
 			pt[i] = 0;
 		}
-		kvm_arch_ops->tlb_flush(vcpu);
+		kvm_flush_remote_tlbs(vcpu->kvm);
 		return;
 	}
 
@@ -659,6 +671,7 @@
 		ent &= PT64_BASE_ADDR_MASK;
 		mmu_page_remove_parent_pte(vcpu, page_header(ent), &pt[i]);
 	}
+	kvm_flush_remote_tlbs(vcpu->kvm);
 }
 
 static void kvm_mmu_put_page(struct kvm_vcpu *vcpu,
@@ -685,12 +698,12 @@
 		}
 		BUG_ON(!parent_pte);
 		kvm_mmu_put_page(vcpu, page, parent_pte);
-		*parent_pte = 0;
+		set_shadow_pte(parent_pte, 0);
 	}
 	kvm_mmu_page_unlink_children(vcpu, page);
 	if (!page->root_count) {
 		hlist_del(&page->hash_link);
-		kvm_mmu_free_page(vcpu, page->page_hpa);
+		kvm_mmu_free_page(vcpu, page);
 	} else
 		list_move(&page->link, &vcpu->kvm->active_mmu_pages);
 }
@@ -717,6 +730,17 @@
 	return r;
 }
 
+static void mmu_unshadow(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+	struct kvm_mmu_page *page;
+
+	while ((page = kvm_mmu_lookup_page(vcpu, gfn)) != NULL) {
+		pgprintk("%s: zap %lx %x\n",
+			 __FUNCTION__, gfn, page->role.word);
+		kvm_mmu_zap_page(vcpu, page);
+	}
+}
+
 static void page_header_update_slot(struct kvm *kvm, void *pte, gpa_t gpa)
 {
 	int slot = memslot_id(kvm, gfn_to_memslot(kvm, gpa >> PAGE_SHIFT));
@@ -805,7 +829,7 @@
 				return -ENOMEM;
 			}
 
-			table[index] = new_table->page_hpa | PT_PRESENT_MASK
+			table[index] = __pa(new_table->spt) | PT_PRESENT_MASK
 				| PT_WRITABLE_MASK | PT_USER_MASK;
 		}
 		table_addr = table[index] & PT64_BASE_ADDR_MASK;
@@ -817,11 +841,12 @@
 	int i;
 	struct kvm_mmu_page *page;
 
+	if (!VALID_PAGE(vcpu->mmu.root_hpa))
+		return;
 #ifdef CONFIG_X86_64
 	if (vcpu->mmu.shadow_root_level == PT64_ROOT_LEVEL) {
 		hpa_t root = vcpu->mmu.root_hpa;
 
-		ASSERT(VALID_PAGE(root));
 		page = page_header(root);
 		--page->root_count;
 		vcpu->mmu.root_hpa = INVALID_PAGE;
@@ -832,7 +857,6 @@
 		hpa_t root = vcpu->mmu.pae_root[i];
 
 		if (root) {
-			ASSERT(VALID_PAGE(root));
 			root &= PT64_BASE_ADDR_MASK;
 			page = page_header(root);
 			--page->root_count;
@@ -857,7 +881,7 @@
 		ASSERT(!VALID_PAGE(root));
 		page = kvm_mmu_get_page(vcpu, root_gfn, 0,
 					PT64_ROOT_LEVEL, 0, 0, NULL);
-		root = page->page_hpa;
+		root = __pa(page->spt);
 		++page->root_count;
 		vcpu->mmu.root_hpa = root;
 		return;
@@ -878,7 +902,7 @@
 		page = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
 					PT32_ROOT_LEVEL, !is_paging(vcpu),
 					0, NULL);
-		root = page->page_hpa;
+		root = __pa(page->spt);
 		++page->root_count;
 		vcpu->mmu.pae_root[i] = root | PT_PRESENT_MASK;
 	}
@@ -928,9 +952,7 @@
 	context->free = nonpaging_free;
 	context->root_level = 0;
 	context->shadow_root_level = PT32E_ROOT_LEVEL;
-	mmu_alloc_roots(vcpu);
-	ASSERT(VALID_PAGE(context->root_hpa));
-	kvm_arch_ops->set_cr3(vcpu, context->root_hpa);
+	context->root_hpa = INVALID_PAGE;
 	return 0;
 }
 
@@ -944,59 +966,6 @@
 {
 	pgprintk("%s: cr3 %lx\n", __FUNCTION__, vcpu->cr3);
 	mmu_free_roots(vcpu);
-	if (unlikely(vcpu->kvm->n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
-		kvm_mmu_free_some_pages(vcpu);
-	mmu_alloc_roots(vcpu);
-	kvm_mmu_flush_tlb(vcpu);
-	kvm_arch_ops->set_cr3(vcpu, vcpu->mmu.root_hpa);
-}
-
-static inline void set_pte_common(struct kvm_vcpu *vcpu,
-			     u64 *shadow_pte,
-			     gpa_t gaddr,
-			     int dirty,
-			     u64 access_bits,
-			     gfn_t gfn)
-{
-	hpa_t paddr;
-
-	*shadow_pte |= access_bits << PT_SHADOW_BITS_OFFSET;
-	if (!dirty)
-		access_bits &= ~PT_WRITABLE_MASK;
-
-	paddr = gpa_to_hpa(vcpu, gaddr & PT64_BASE_ADDR_MASK);
-
-	*shadow_pte |= access_bits;
-
-	if (is_error_hpa(paddr)) {
-		*shadow_pte |= gaddr;
-		*shadow_pte |= PT_SHADOW_IO_MARK;
-		*shadow_pte &= ~PT_PRESENT_MASK;
-		return;
-	}
-
-	*shadow_pte |= paddr;
-
-	if (access_bits & PT_WRITABLE_MASK) {
-		struct kvm_mmu_page *shadow;
-
-		shadow = kvm_mmu_lookup_page(vcpu, gfn);
-		if (shadow) {
-			pgprintk("%s: found shadow page for %lx, marking ro\n",
-				 __FUNCTION__, gfn);
-			access_bits &= ~PT_WRITABLE_MASK;
-			if (is_writeble_pte(*shadow_pte)) {
-				    *shadow_pte &= ~PT_WRITABLE_MASK;
-				    kvm_arch_ops->tlb_flush(vcpu);
-			}
-		}
-	}
-
-	if (access_bits & PT_WRITABLE_MASK)
-		mark_page_dirty(vcpu->kvm, gaddr >> PAGE_SHIFT);
-
-	page_header_update_slot(vcpu->kvm, shadow_pte, gaddr);
-	rmap_add(vcpu, shadow_pte);
 }
 
 static void inject_page_fault(struct kvm_vcpu *vcpu,
@@ -1006,23 +975,6 @@
 	kvm_arch_ops->inject_page_fault(vcpu, addr, err_code);
 }
 
-static inline int fix_read_pf(u64 *shadow_ent)
-{
-	if ((*shadow_ent & PT_SHADOW_USER_MASK) &&
-	    !(*shadow_ent & PT_USER_MASK)) {
-		/*
-		 * If supervisor write protect is disabled, we shadow kernel
-		 * pages as user pages so we can trap the write access.
-		 */
-		*shadow_ent |= PT_USER_MASK;
-		*shadow_ent &= ~PT_WRITABLE_MASK;
-
-		return 1;
-
-	}
-	return 0;
-}
-
 static void paging_free(struct kvm_vcpu *vcpu)
 {
 	nonpaging_free(vcpu);
@@ -1047,10 +999,7 @@
 	context->free = paging_free;
 	context->root_level = level;
 	context->shadow_root_level = level;
-	mmu_alloc_roots(vcpu);
-	ASSERT(VALID_PAGE(context->root_hpa));
-	kvm_arch_ops->set_cr3(vcpu, context->root_hpa |
-		    (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)));
+	context->root_hpa = INVALID_PAGE;
 	return 0;
 }
 
@@ -1069,10 +1018,7 @@
 	context->free = paging_free;
 	context->root_level = PT32_ROOT_LEVEL;
 	context->shadow_root_level = PT32E_ROOT_LEVEL;
-	mmu_alloc_roots(vcpu);
-	ASSERT(VALID_PAGE(context->root_hpa));
-	kvm_arch_ops->set_cr3(vcpu, context->root_hpa |
-		    (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)));
+	context->root_hpa = INVALID_PAGE;
 	return 0;
 }
 
@@ -1107,18 +1053,33 @@
 
 int kvm_mmu_reset_context(struct kvm_vcpu *vcpu)
 {
-	int r;
-
 	destroy_kvm_mmu(vcpu);
-	r = init_kvm_mmu(vcpu);
-	if (r < 0)
-		goto out;
-	r = mmu_topup_memory_caches(vcpu);
-out:
-	return r;
+	return init_kvm_mmu(vcpu);
 }
 
-static void mmu_pre_write_zap_pte(struct kvm_vcpu *vcpu,
+int kvm_mmu_load(struct kvm_vcpu *vcpu)
+{
+	int r;
+
+	spin_lock(&vcpu->kvm->lock);
+	r = mmu_topup_memory_caches(vcpu);
+	if (r)
+		goto out;
+	mmu_alloc_roots(vcpu);
+	kvm_arch_ops->set_cr3(vcpu, vcpu->mmu.root_hpa);
+	kvm_mmu_flush_tlb(vcpu);
+out:
+	spin_unlock(&vcpu->kvm->lock);
+	return r;
+}
+EXPORT_SYMBOL_GPL(kvm_mmu_load);
+
+void kvm_mmu_unload(struct kvm_vcpu *vcpu)
+{
+	mmu_free_roots(vcpu);
+}
+
+static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
 				  struct kvm_mmu_page *page,
 				  u64 *spte)
 {
@@ -1135,9 +1096,25 @@
 		}
 	}
 	*spte = 0;
+	kvm_flush_remote_tlbs(vcpu->kvm);
 }
 
-void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
+static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
+				  struct kvm_mmu_page *page,
+				  u64 *spte,
+				  const void *new, int bytes)
+{
+	if (page->role.level != PT_PAGE_TABLE_LEVEL)
+		return;
+
+	if (page->role.glevels == PT32_ROOT_LEVEL)
+		paging32_update_pte(vcpu, page, spte, new, bytes);
+	else
+		paging64_update_pte(vcpu, page, spte, new, bytes);
+}
+
+void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+		       const u8 *old, const u8 *new, int bytes)
 {
 	gfn_t gfn = gpa >> PAGE_SHIFT;
 	struct kvm_mmu_page *page;
@@ -1149,6 +1126,7 @@
 	unsigned pte_size;
 	unsigned page_offset;
 	unsigned misaligned;
+	unsigned quadrant;
 	int level;
 	int flooded = 0;
 	int npte;
@@ -1169,6 +1147,7 @@
 			continue;
 		pte_size = page->role.glevels == PT32_ROOT_LEVEL ? 4 : 8;
 		misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1);
+		misaligned |= bytes < 4;
 		if (misaligned || flooded) {
 			/*
 			 * Misaligned accesses are too much trouble to fix
@@ -1200,21 +1179,20 @@
 				page_offset <<= 1;
 				npte = 2;
 			}
+			quadrant = page_offset >> PAGE_SHIFT;
 			page_offset &= ~PAGE_MASK;
+			if (quadrant != page->role.quadrant)
+				continue;
 		}
-		spte = __va(page->page_hpa);
-		spte += page_offset / sizeof(*spte);
+		spte = &page->spt[page_offset / sizeof(*spte)];
 		while (npte--) {
-			mmu_pre_write_zap_pte(vcpu, page, spte);
+			mmu_pte_write_zap_pte(vcpu, page, spte);
+			mmu_pte_write_new_pte(vcpu, page, spte, new, bytes);
 			++spte;
 		}
 	}
 }
 
-void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
-{
-}
-
 int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
 {
 	gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva);
@@ -1243,13 +1221,6 @@
 				    struct kvm_mmu_page, link);
 		kvm_mmu_zap_page(vcpu, page);
 	}
-	while (!list_empty(&vcpu->free_pages)) {
-		page = list_entry(vcpu->free_pages.next,
-				  struct kvm_mmu_page, link);
-		list_del(&page->link);
-		__free_page(pfn_to_page(page->page_hpa >> PAGE_SHIFT));
-		page->page_hpa = INVALID_PAGE;
-	}
 	free_page((unsigned long)vcpu->mmu.pae_root);
 }
 
@@ -1260,18 +1231,7 @@
 
 	ASSERT(vcpu);
 
-	for (i = 0; i < KVM_NUM_MMU_PAGES; i++) {
-		struct kvm_mmu_page *page_header = &vcpu->page_header_buf[i];
-
-		INIT_LIST_HEAD(&page_header->link);
-		if ((page = alloc_page(GFP_KERNEL)) == NULL)
-			goto error_1;
-		set_page_private(page, (unsigned long)page_header);
-		page_header->page_hpa = (hpa_t)page_to_pfn(page) << PAGE_SHIFT;
-		memset(__va(page_header->page_hpa), 0, PAGE_SIZE);
-		list_add(&page_header->link, &vcpu->free_pages);
-		++vcpu->kvm->n_free_mmu_pages;
-	}
+	vcpu->kvm->n_free_mmu_pages = KVM_NUM_MMU_PAGES;
 
 	/*
 	 * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64.
@@ -1296,7 +1256,6 @@
 {
 	ASSERT(vcpu);
 	ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
-	ASSERT(list_empty(&vcpu->free_pages));
 
 	return alloc_mmu_pages(vcpu);
 }
@@ -1305,7 +1264,6 @@
 {
 	ASSERT(vcpu);
 	ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
-	ASSERT(!list_empty(&vcpu->free_pages));
 
 	return init_kvm_mmu(vcpu);
 }
@@ -1331,7 +1289,7 @@
 		if (!test_bit(slot, &page->slot_bitmap))
 			continue;
 
-		pt = __va(page->page_hpa);
+		pt = page->spt;
 		for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
 			/* avoid RMW */
 			if (pt[i] & PT_WRITABLE_MASK) {
@@ -1354,7 +1312,7 @@
 	}
 
 	mmu_free_memory_caches(vcpu);
-	kvm_arch_ops->tlb_flush(vcpu);
+	kvm_flush_remote_tlbs(vcpu->kvm);
 	init_kvm_mmu(vcpu);
 }
 
@@ -1364,6 +1322,10 @@
 		kmem_cache_destroy(pte_chain_cache);
 	if (rmap_desc_cache)
 		kmem_cache_destroy(rmap_desc_cache);
+	if (mmu_page_cache)
+		kmem_cache_destroy(mmu_page_cache);
+	if (mmu_page_header_cache)
+		kmem_cache_destroy(mmu_page_header_cache);
 }
 
 int kvm_mmu_module_init(void)
@@ -1379,6 +1341,18 @@
 	if (!rmap_desc_cache)
 		goto nomem;
 
+	mmu_page_cache = kmem_cache_create("kvm_mmu_page",
+					   PAGE_SIZE,
+					   PAGE_SIZE, 0, NULL, NULL);
+	if (!mmu_page_cache)
+		goto nomem;
+
+	mmu_page_header_cache = kmem_cache_create("kvm_mmu_page_header",
+						  sizeof(struct kvm_mmu_page),
+						  0, 0, NULL, NULL);
+	if (!mmu_page_header_cache)
+		goto nomem;
+
 	return 0;
 
 nomem:
@@ -1482,7 +1456,7 @@
 	int i;
 
 	list_for_each_entry(page, &vcpu->kvm->active_mmu_pages, link) {
-		u64 *pt = __va(page->page_hpa);
+		u64 *pt = page->spt;
 
 		if (page->role.level != PT_PAGE_TABLE_LEVEL)
 			continue;
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 73ffbff..a7c5cb0 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -31,7 +31,6 @@
 	#define PT_INDEX(addr, level) PT64_INDEX(addr, level)
 	#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
 	#define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
-	#define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK
 	#ifdef CONFIG_X86_64
 	#define PT_MAX_FULL_LEVELS 4
 	#else
@@ -46,7 +45,6 @@
 	#define PT_INDEX(addr, level) PT32_INDEX(addr, level)
 	#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
 	#define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
-	#define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK
 	#define PT_MAX_FULL_LEVELS 2
 #else
 	#error Invalid PTTYPE value
@@ -192,40 +190,143 @@
 	mark_page_dirty(kvm, walker->table_gfn[walker->level - 1]);
 }
 
-static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte,
-			   u64 *shadow_pte, u64 access_bits, gfn_t gfn)
+static void FNAME(set_pte_common)(struct kvm_vcpu *vcpu,
+				  u64 *shadow_pte,
+				  gpa_t gaddr,
+				  pt_element_t *gpte,
+				  u64 access_bits,
+				  int user_fault,
+				  int write_fault,
+				  int *ptwrite,
+				  struct guest_walker *walker,
+				  gfn_t gfn)
 {
-	ASSERT(*shadow_pte == 0);
-	access_bits &= guest_pte;
-	*shadow_pte = (guest_pte & PT_PTE_COPY_MASK);
-	set_pte_common(vcpu, shadow_pte, guest_pte & PT_BASE_ADDR_MASK,
-		       guest_pte & PT_DIRTY_MASK, access_bits, gfn);
+	hpa_t paddr;
+	int dirty = *gpte & PT_DIRTY_MASK;
+	u64 spte = *shadow_pte;
+	int was_rmapped = is_rmap_pte(spte);
+
+	pgprintk("%s: spte %llx gpte %llx access %llx write_fault %d"
+		 " user_fault %d gfn %lx\n",
+		 __FUNCTION__, spte, (u64)*gpte, access_bits,
+		 write_fault, user_fault, gfn);
+
+	if (write_fault && !dirty) {
+		*gpte |= PT_DIRTY_MASK;
+		dirty = 1;
+		FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
+	}
+
+	spte |= PT_PRESENT_MASK | PT_ACCESSED_MASK | PT_DIRTY_MASK;
+	spte |= *gpte & PT64_NX_MASK;
+	if (!dirty)
+		access_bits &= ~PT_WRITABLE_MASK;
+
+	paddr = gpa_to_hpa(vcpu, gaddr & PT64_BASE_ADDR_MASK);
+
+	spte |= PT_PRESENT_MASK;
+	if (access_bits & PT_USER_MASK)
+		spte |= PT_USER_MASK;
+
+	if (is_error_hpa(paddr)) {
+		spte |= gaddr;
+		spte |= PT_SHADOW_IO_MARK;
+		spte &= ~PT_PRESENT_MASK;
+		set_shadow_pte(shadow_pte, spte);
+		return;
+	}
+
+	spte |= paddr;
+
+	if ((access_bits & PT_WRITABLE_MASK)
+	    || (write_fault && !is_write_protection(vcpu) && !user_fault)) {
+		struct kvm_mmu_page *shadow;
+
+		spte |= PT_WRITABLE_MASK;
+		if (user_fault) {
+			mmu_unshadow(vcpu, gfn);
+			goto unshadowed;
+		}
+
+		shadow = kvm_mmu_lookup_page(vcpu, gfn);
+		if (shadow) {
+			pgprintk("%s: found shadow page for %lx, marking ro\n",
+				 __FUNCTION__, gfn);
+			access_bits &= ~PT_WRITABLE_MASK;
+			if (is_writeble_pte(spte)) {
+				spte &= ~PT_WRITABLE_MASK;
+				kvm_arch_ops->tlb_flush(vcpu);
+			}
+			if (write_fault)
+				*ptwrite = 1;
+		}
+	}
+
+unshadowed:
+
+	if (access_bits & PT_WRITABLE_MASK)
+		mark_page_dirty(vcpu->kvm, gaddr >> PAGE_SHIFT);
+
+	set_shadow_pte(shadow_pte, spte);
+	page_header_update_slot(vcpu->kvm, shadow_pte, gaddr);
+	if (!was_rmapped)
+		rmap_add(vcpu, shadow_pte);
 }
 
-static void FNAME(set_pde)(struct kvm_vcpu *vcpu, u64 guest_pde,
-			   u64 *shadow_pte, u64 access_bits, gfn_t gfn)
+static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t *gpte,
+			   u64 *shadow_pte, u64 access_bits,
+			   int user_fault, int write_fault, int *ptwrite,
+			   struct guest_walker *walker, gfn_t gfn)
+{
+	access_bits &= *gpte;
+	FNAME(set_pte_common)(vcpu, shadow_pte, *gpte & PT_BASE_ADDR_MASK,
+			      gpte, access_bits, user_fault, write_fault,
+			      ptwrite, walker, gfn);
+}
+
+static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
+			      u64 *spte, const void *pte, int bytes)
+{
+	pt_element_t gpte;
+
+	if (bytes < sizeof(pt_element_t))
+		return;
+	gpte = *(const pt_element_t *)pte;
+	if (~gpte & (PT_PRESENT_MASK | PT_ACCESSED_MASK))
+		return;
+	pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
+	FNAME(set_pte)(vcpu, &gpte, spte, PT_USER_MASK | PT_WRITABLE_MASK, 0,
+		       0, NULL, NULL,
+		       (gpte & PT_BASE_ADDR_MASK) >> PAGE_SHIFT);
+}
+
+static void FNAME(set_pde)(struct kvm_vcpu *vcpu, pt_element_t *gpde,
+			   u64 *shadow_pte, u64 access_bits,
+			   int user_fault, int write_fault, int *ptwrite,
+			   struct guest_walker *walker, gfn_t gfn)
 {
 	gpa_t gaddr;
 
-	ASSERT(*shadow_pte == 0);
-	access_bits &= guest_pde;
+	access_bits &= *gpde;
 	gaddr = (gpa_t)gfn << PAGE_SHIFT;
 	if (PTTYPE == 32 && is_cpuid_PSE36())
-		gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) <<
+		gaddr |= (*gpde & PT32_DIR_PSE36_MASK) <<
 			(32 - PT32_DIR_PSE36_SHIFT);
-	*shadow_pte = guest_pde & PT_PTE_COPY_MASK;
-	set_pte_common(vcpu, shadow_pte, gaddr,
-		       guest_pde & PT_DIRTY_MASK, access_bits, gfn);
+	FNAME(set_pte_common)(vcpu, shadow_pte, gaddr,
+			      gpde, access_bits, user_fault, write_fault,
+			      ptwrite, walker, gfn);
 }
 
 /*
  * Fetch a shadow pte for a specific level in the paging hierarchy.
  */
 static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
-			      struct guest_walker *walker)
+			 struct guest_walker *walker,
+			 int user_fault, int write_fault, int *ptwrite)
 {
 	hpa_t shadow_addr;
 	int level;
+	u64 *shadow_ent;
 	u64 *prev_shadow_ent = NULL;
 	pt_element_t *guest_ent = walker->ptep;
 
@@ -242,37 +343,23 @@
 
 	for (; ; level--) {
 		u32 index = SHADOW_PT_INDEX(addr, level);
-		u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index;
 		struct kvm_mmu_page *shadow_page;
 		u64 shadow_pte;
 		int metaphysical;
 		gfn_t table_gfn;
 		unsigned hugepage_access = 0;
 
+		shadow_ent = ((u64 *)__va(shadow_addr)) + index;
 		if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) {
 			if (level == PT_PAGE_TABLE_LEVEL)
-				return shadow_ent;
+				break;
 			shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK;
 			prev_shadow_ent = shadow_ent;
 			continue;
 		}
 
-		if (level == PT_PAGE_TABLE_LEVEL) {
-
-			if (walker->level == PT_DIRECTORY_LEVEL) {
-				if (prev_shadow_ent)
-					*prev_shadow_ent |= PT_SHADOW_PS_MARK;
-				FNAME(set_pde)(vcpu, *guest_ent, shadow_ent,
-					       walker->inherited_ar,
-					       walker->gfn);
-			} else {
-				ASSERT(walker->level == PT_PAGE_TABLE_LEVEL);
-				FNAME(set_pte)(vcpu, *guest_ent, shadow_ent,
-					       walker->inherited_ar,
-					       walker->gfn);
-			}
-			return shadow_ent;
-		}
+		if (level == PT_PAGE_TABLE_LEVEL)
+			break;
 
 		if (level - 1 == PT_PAGE_TABLE_LEVEL
 		    && walker->level == PT_DIRECTORY_LEVEL) {
@@ -289,90 +376,24 @@
 		shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
 					       metaphysical, hugepage_access,
 					       shadow_ent);
-		shadow_addr = shadow_page->page_hpa;
+		shadow_addr = __pa(shadow_page->spt);
 		shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK
 			| PT_WRITABLE_MASK | PT_USER_MASK;
 		*shadow_ent = shadow_pte;
 		prev_shadow_ent = shadow_ent;
 	}
-}
 
-/*
- * The guest faulted for write.  We need to
- *
- * - check write permissions
- * - update the guest pte dirty bit
- * - update our own dirty page tracking structures
- */
-static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu,
-			       u64 *shadow_ent,
-			       struct guest_walker *walker,
-			       gva_t addr,
-			       int user,
-			       int *write_pt)
-{
-	pt_element_t *guest_ent;
-	int writable_shadow;
-	gfn_t gfn;
-	struct kvm_mmu_page *page;
-
-	if (is_writeble_pte(*shadow_ent))
-		return !user || (*shadow_ent & PT_USER_MASK);
-
-	writable_shadow = *shadow_ent & PT_SHADOW_WRITABLE_MASK;
-	if (user) {
-		/*
-		 * User mode access.  Fail if it's a kernel page or a read-only
-		 * page.
-		 */
-		if (!(*shadow_ent & PT_SHADOW_USER_MASK) || !writable_shadow)
-			return 0;
-		ASSERT(*shadow_ent & PT_USER_MASK);
-	} else
-		/*
-		 * Kernel mode access.  Fail if it's a read-only page and
-		 * supervisor write protection is enabled.
-		 */
-		if (!writable_shadow) {
-			if (is_write_protection(vcpu))
-				return 0;
-			*shadow_ent &= ~PT_USER_MASK;
-		}
-
-	guest_ent = walker->ptep;
-
-	if (!is_present_pte(*guest_ent)) {
-		*shadow_ent = 0;
-		return 0;
+	if (walker->level == PT_DIRECTORY_LEVEL) {
+		FNAME(set_pde)(vcpu, guest_ent, shadow_ent,
+			       walker->inherited_ar, user_fault, write_fault,
+			       ptwrite, walker, walker->gfn);
+	} else {
+		ASSERT(walker->level == PT_PAGE_TABLE_LEVEL);
+		FNAME(set_pte)(vcpu, guest_ent, shadow_ent,
+			       walker->inherited_ar, user_fault, write_fault,
+			       ptwrite, walker, walker->gfn);
 	}
-
-	gfn = walker->gfn;
-
-	if (user) {
-		/*
-		 * Usermode page faults won't be for page table updates.
-		 */
-		while ((page = kvm_mmu_lookup_page(vcpu, gfn)) != NULL) {
-			pgprintk("%s: zap %lx %x\n",
-				 __FUNCTION__, gfn, page->role.word);
-			kvm_mmu_zap_page(vcpu, page);
-		}
-	} else if (kvm_mmu_lookup_page(vcpu, gfn)) {
-		pgprintk("%s: found shadow page for %lx, marking ro\n",
-			 __FUNCTION__, gfn);
-		mark_page_dirty(vcpu->kvm, gfn);
-		FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
-		*guest_ent |= PT_DIRTY_MASK;
-		*write_pt = 1;
-		return 0;
-	}
-	mark_page_dirty(vcpu->kvm, gfn);
-	*shadow_ent |= PT_WRITABLE_MASK;
-	FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
-	*guest_ent |= PT_DIRTY_MASK;
-	rmap_add(vcpu, shadow_ent);
-
-	return 1;
+	return shadow_ent;
 }
 
 /*
@@ -397,7 +418,6 @@
 	int fetch_fault = error_code & PFERR_FETCH_MASK;
 	struct guest_walker walker;
 	u64 *shadow_pte;
-	int fixed;
 	int write_pt = 0;
 	int r;
 
@@ -421,27 +441,20 @@
 		pgprintk("%s: guest page fault\n", __FUNCTION__);
 		inject_page_fault(vcpu, addr, walker.error_code);
 		FNAME(release_walker)(&walker);
+		vcpu->last_pt_write_count = 0; /* reset fork detector */
 		return 0;
 	}
 
-	shadow_pte = FNAME(fetch)(vcpu, addr, &walker);
-	pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__,
-		 shadow_pte, *shadow_pte);
-
-	/*
-	 * Update the shadow pte.
-	 */
-	if (write_fault)
-		fixed = FNAME(fix_write_pf)(vcpu, shadow_pte, &walker, addr,
-					    user_fault, &write_pt);
-	else
-		fixed = fix_read_pf(shadow_pte);
-
-	pgprintk("%s: updated shadow pte %p %llx\n", __FUNCTION__,
-		 shadow_pte, *shadow_pte);
+	shadow_pte = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
+				  &write_pt);
+	pgprintk("%s: shadow pte %p %llx ptwrite %d\n", __FUNCTION__,
+		 shadow_pte, *shadow_pte, write_pt);
 
 	FNAME(release_walker)(&walker);
 
+	if (!write_pt)
+		vcpu->last_pt_write_count = 0; /* reset fork detector */
+
 	/*
 	 * mmio: emulate if accessible, otherwise its a guest fault.
 	 */
@@ -478,7 +491,5 @@
 #undef PT_INDEX
 #undef SHADOW_PT_INDEX
 #undef PT_LEVEL_MASK
-#undef PT_PTE_COPY_MASK
-#undef PT_NON_PTE_COPY_MASK
 #undef PT_DIR_BASE_ADDR_MASK
 #undef PT_MAX_FULL_LEVELS
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 9c15f32..bc818cc 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -14,15 +14,17 @@
  *
  */
 
+#include "kvm_svm.h"
+#include "x86_emulate.h"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
 #include <linux/profile.h>
-#include <asm/desc.h>
+#include <linux/sched.h>
 
-#include "kvm_svm.h"
-#include "x86_emulate.h"
+#include <asm/desc.h>
 
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
@@ -377,7 +379,7 @@
 	int cpu;
 	struct page *iopm_pages;
 	struct page *msrpm_pages;
-	void *msrpm_va;
+	void *iopm_va, *msrpm_va;
 	int r;
 
 	kvm_emulator_want_group7_invlpg();
@@ -386,8 +388,10 @@
 
 	if (!iopm_pages)
 		return -ENOMEM;
-	memset(page_address(iopm_pages), 0xff,
-					PAGE_SIZE * (1 << IOPM_ALLOC_ORDER));
+
+	iopm_va = page_address(iopm_pages);
+	memset(iopm_va, 0xff, PAGE_SIZE * (1 << IOPM_ALLOC_ORDER));
+	clear_bit(0x80, iopm_va); /* allow direct access to PC debug port */
 	iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
 
 
@@ -578,7 +582,7 @@
 		goto out2;
 
 	vcpu->svm->vmcb = page_address(page);
-	memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
+	clear_page(vcpu->svm->vmcb);
 	vcpu->svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
 	vcpu->svm->asid_generation = 0;
 	memset(vcpu->svm->db_regs, 0, sizeof(vcpu->svm->db_regs));
@@ -586,9 +590,9 @@
 
 	fx_init(vcpu);
 	vcpu->fpu_active = 1;
-	vcpu->apic_base = 0xfee00000 |
-			/*for vcpu 0*/ MSR_IA32_APICBASE_BSP |
-			MSR_IA32_APICBASE_ENABLE;
+	vcpu->apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
+	if (vcpu == &vcpu->kvm->vcpus[0])
+		vcpu->apic_base |= MSR_IA32_APICBASE_BSP;
 
 	return 0;
 
@@ -954,7 +958,7 @@
 	 * VMCB is undefined after a SHUTDOWN intercept
 	 * so reinitialize it.
 	 */
-	memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
+	clear_page(vcpu->svm->vmcb);
 	init_vmcb(vcpu->svm->vmcb);
 
 	kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
@@ -1112,12 +1116,7 @@
 {
 	vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1;
 	skip_emulated_instruction(vcpu);
-	if (vcpu->irq_summary)
-		return 1;
-
-	kvm_run->exit_reason = KVM_EXIT_HLT;
-	++vcpu->stat.halt_exits;
-	return 0;
+	return kvm_emulate_halt(vcpu);
 }
 
 static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -1472,6 +1471,11 @@
 	asm volatile ("mov %0, %%dr3" : : "r"(db_regs[3]));
 }
 
+static void svm_flush_tlb(struct kvm_vcpu *vcpu)
+{
+	force_new_asid(vcpu);
+}
+
 static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	u16 fs_selector;
@@ -1480,11 +1484,20 @@
 	int r;
 
 again:
+	r = kvm_mmu_reload(vcpu);
+	if (unlikely(r))
+		return r;
+
 	if (!vcpu->mmio_read_completed)
 		do_interrupt_requests(vcpu, kvm_run);
 
 	clgi();
 
+	vcpu->guest_mode = 1;
+	if (vcpu->requests)
+		if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests))
+		    svm_flush_tlb(vcpu);
+
 	pre_svm_run(vcpu);
 
 	save_host_msrs(vcpu);
@@ -1616,6 +1629,8 @@
 #endif
 		: "cc", "memory" );
 
+	vcpu->guest_mode = 0;
+
 	if (vcpu->fpu_active) {
 		fx_save(vcpu->guest_fx_image);
 		fx_restore(vcpu->host_fx_image);
@@ -1680,11 +1695,6 @@
 	return r;
 }
 
-static void svm_flush_tlb(struct kvm_vcpu *vcpu)
-{
-	force_new_asid(vcpu);
-}
-
 static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
 {
 	vcpu->svm->vmcb->save.cr3 = root;
@@ -1726,6 +1736,12 @@
 
 static int is_disabled(void)
 {
+	u64 vm_cr;
+
+	rdmsrl(MSR_VM_CR, vm_cr);
+	if (vm_cr & (1 << SVM_VM_CR_SVM_DISABLE))
+		return 1;
+
 	return 0;
 }
 
diff --git a/drivers/kvm/svm.h b/drivers/kvm/svm.h
index 5e93814..3b1b0f3 100644
--- a/drivers/kvm/svm.h
+++ b/drivers/kvm/svm.h
@@ -175,8 +175,11 @@
 #define SVM_CPUID_FUNC 0x8000000a
 
 #define MSR_EFER_SVME_MASK (1ULL << 12)
+#define MSR_VM_CR       0xc0010114
 #define MSR_VM_HSAVE_PA 0xc0010117ULL
 
+#define SVM_VM_CR_SVM_DISABLE 4
+
 #define SVM_SELECTOR_S_SHIFT 4
 #define SVM_SELECTOR_DPL_SHIFT 5
 #define SVM_SELECTOR_P_SHIFT 7
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 724db00..80628f6 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -17,27 +17,35 @@
 
 #include "kvm.h"
 #include "vmx.h"
+#include "segment_descriptor.h"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/profile.h>
+#include <linux/sched.h>
+
 #include <asm/io.h>
 #include <asm/desc.h>
 
-#include "segment_descriptor.h"
-
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+static int init_rmode_tss(struct kvm *kvm);
+
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
 
+static struct page *vmx_io_bitmap_a;
+static struct page *vmx_io_bitmap_b;
+
 #ifdef CONFIG_X86_64
 #define HOST_IS_64 1
 #else
 #define HOST_IS_64 0
 #endif
+#define EFER_SAVE_RESTORE_BITS ((u64)EFER_SCE)
 
 static struct vmcs_descriptor {
 	int size;
@@ -81,18 +89,17 @@
 };
 #define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
 
-#ifdef CONFIG_X86_64
-static unsigned msr_offset_kernel_gs_base;
-#define NR_64BIT_MSRS 4
-/*
- * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt
- * mechanism (cpu bug AA24)
- */
-#define NR_BAD_MSRS 2
-#else
-#define NR_64BIT_MSRS 0
-#define NR_BAD_MSRS 0
-#endif
+static inline u64 msr_efer_save_restore_bits(struct vmx_msr_entry msr)
+{
+	return (u64)msr.data & EFER_SAVE_RESTORE_BITS;
+}
+
+static inline int msr_efer_need_save_restore(struct kvm_vcpu *vcpu)
+{
+	int efer_offset = vcpu->msr_offset_efer;
+	return msr_efer_save_restore_bits(vcpu->host_msrs[efer_offset]) !=
+		msr_efer_save_restore_bits(vcpu->guest_msrs[efer_offset]);
+}
 
 static inline int is_page_fault(u32 intr_info)
 {
@@ -114,13 +121,23 @@
 		== (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
 }
 
-static struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
+static int __find_msr_index(struct kvm_vcpu *vcpu, u32 msr)
 {
 	int i;
 
 	for (i = 0; i < vcpu->nmsrs; ++i)
 		if (vcpu->guest_msrs[i].index == msr)
-			return &vcpu->guest_msrs[i];
+			return i;
+	return -1;
+}
+
+static struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
+{
+	int i;
+
+	i = __find_msr_index(vcpu, msr);
+	if (i >= 0)
+		return &vcpu->guest_msrs[i];
 	return NULL;
 }
 
@@ -146,6 +163,7 @@
 		vmcs_clear(vcpu->vmcs);
 	if (per_cpu(current_vmcs, cpu) == vcpu->vmcs)
 		per_cpu(current_vmcs, cpu) = NULL;
+	rdtscll(vcpu->host_tsc);
 }
 
 static void vcpu_clear(struct kvm_vcpu *vcpu)
@@ -233,6 +251,127 @@
 	vmcs_writel(field, vmcs_readl(field) | mask);
 }
 
+static void update_exception_bitmap(struct kvm_vcpu *vcpu)
+{
+	u32 eb;
+
+	eb = 1u << PF_VECTOR;
+	if (!vcpu->fpu_active)
+		eb |= 1u << NM_VECTOR;
+	if (vcpu->guest_debug.enabled)
+		eb |= 1u << 1;
+	if (vcpu->rmode.active)
+		eb = ~0;
+	vmcs_write32(EXCEPTION_BITMAP, eb);
+}
+
+static void reload_tss(void)
+{
+#ifndef CONFIG_X86_64
+
+	/*
+	 * VT restores TR but not its size.  Useless.
+	 */
+	struct descriptor_table gdt;
+	struct segment_descriptor *descs;
+
+	get_gdt(&gdt);
+	descs = (void *)gdt.base;
+	descs[GDT_ENTRY_TSS].type = 9; /* available TSS */
+	load_TR_desc();
+#endif
+}
+
+static void load_transition_efer(struct kvm_vcpu *vcpu)
+{
+	u64 trans_efer;
+	int efer_offset = vcpu->msr_offset_efer;
+
+	trans_efer = vcpu->host_msrs[efer_offset].data;
+	trans_efer &= ~EFER_SAVE_RESTORE_BITS;
+	trans_efer |= msr_efer_save_restore_bits(
+				vcpu->guest_msrs[efer_offset]);
+	wrmsrl(MSR_EFER, trans_efer);
+	vcpu->stat.efer_reload++;
+}
+
+static void vmx_save_host_state(struct kvm_vcpu *vcpu)
+{
+	struct vmx_host_state *hs = &vcpu->vmx_host_state;
+
+	if (hs->loaded)
+		return;
+
+	hs->loaded = 1;
+	/*
+	 * Set host fs and gs selectors.  Unfortunately, 22.2.3 does not
+	 * allow segment selectors with cpl > 0 or ti == 1.
+	 */
+	hs->ldt_sel = read_ldt();
+	hs->fs_gs_ldt_reload_needed = hs->ldt_sel;
+	hs->fs_sel = read_fs();
+	if (!(hs->fs_sel & 7))
+		vmcs_write16(HOST_FS_SELECTOR, hs->fs_sel);
+	else {
+		vmcs_write16(HOST_FS_SELECTOR, 0);
+		hs->fs_gs_ldt_reload_needed = 1;
+	}
+	hs->gs_sel = read_gs();
+	if (!(hs->gs_sel & 7))
+		vmcs_write16(HOST_GS_SELECTOR, hs->gs_sel);
+	else {
+		vmcs_write16(HOST_GS_SELECTOR, 0);
+		hs->fs_gs_ldt_reload_needed = 1;
+	}
+
+#ifdef CONFIG_X86_64
+	vmcs_writel(HOST_FS_BASE, read_msr(MSR_FS_BASE));
+	vmcs_writel(HOST_GS_BASE, read_msr(MSR_GS_BASE));
+#else
+	vmcs_writel(HOST_FS_BASE, segment_base(hs->fs_sel));
+	vmcs_writel(HOST_GS_BASE, segment_base(hs->gs_sel));
+#endif
+
+#ifdef CONFIG_X86_64
+	if (is_long_mode(vcpu)) {
+		save_msrs(vcpu->host_msrs + vcpu->msr_offset_kernel_gs_base, 1);
+	}
+#endif
+	load_msrs(vcpu->guest_msrs, vcpu->save_nmsrs);
+	if (msr_efer_need_save_restore(vcpu))
+		load_transition_efer(vcpu);
+}
+
+static void vmx_load_host_state(struct kvm_vcpu *vcpu)
+{
+	struct vmx_host_state *hs = &vcpu->vmx_host_state;
+
+	if (!hs->loaded)
+		return;
+
+	hs->loaded = 0;
+	if (hs->fs_gs_ldt_reload_needed) {
+		load_ldt(hs->ldt_sel);
+		load_fs(hs->fs_sel);
+		/*
+		 * If we have to reload gs, we must take care to
+		 * preserve our gs base.
+		 */
+		local_irq_disable();
+		load_gs(hs->gs_sel);
+#ifdef CONFIG_X86_64
+		wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
+#endif
+		local_irq_enable();
+
+		reload_tss();
+	}
+	save_msrs(vcpu->guest_msrs, vcpu->save_nmsrs);
+	load_msrs(vcpu->host_msrs, vcpu->save_nmsrs);
+	if (msr_efer_need_save_restore(vcpu))
+		load_msrs(vcpu->host_msrs + vcpu->msr_offset_efer, 1);
+}
+
 /*
  * Switches to specified vcpu, until a matching vcpu_put(), but assumes
  * vcpu mutex is already taken.
@@ -241,6 +380,7 @@
 {
 	u64 phys_addr = __pa(vcpu->vmcs);
 	int cpu;
+	u64 tsc_this, delta;
 
 	cpu = get_cpu();
 
@@ -274,14 +414,43 @@
 
 		rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
 		vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+
+		/*
+		 * Make sure the time stamp counter is monotonous.
+		 */
+		rdtscll(tsc_this);
+		delta = vcpu->host_tsc - tsc_this;
+		vmcs_write64(TSC_OFFSET, vmcs_read64(TSC_OFFSET) + delta);
 	}
 }
 
 static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
 {
+	vmx_load_host_state(vcpu);
+	kvm_put_guest_fpu(vcpu);
 	put_cpu();
 }
 
+static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->fpu_active)
+		return;
+	vcpu->fpu_active = 1;
+	vmcs_clear_bits(GUEST_CR0, CR0_TS_MASK);
+	if (vcpu->cr0 & CR0_TS_MASK)
+		vmcs_set_bits(GUEST_CR0, CR0_TS_MASK);
+	update_exception_bitmap(vcpu);
+}
+
+static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)
+{
+	if (!vcpu->fpu_active)
+		return;
+	vcpu->fpu_active = 0;
+	vmcs_set_bits(GUEST_CR0, CR0_TS_MASK);
+	update_exception_bitmap(vcpu);
+}
+
 static void vmx_vcpu_decache(struct kvm_vcpu *vcpu)
 {
 	vcpu_clear(vcpu);
@@ -330,41 +499,61 @@
 }
 
 /*
+ * Swap MSR entry in host/guest MSR entry array.
+ */
+void move_msr_up(struct kvm_vcpu *vcpu, int from, int to)
+{
+	struct vmx_msr_entry tmp;
+	tmp = vcpu->guest_msrs[to];
+	vcpu->guest_msrs[to] = vcpu->guest_msrs[from];
+	vcpu->guest_msrs[from] = tmp;
+	tmp = vcpu->host_msrs[to];
+	vcpu->host_msrs[to] = vcpu->host_msrs[from];
+	vcpu->host_msrs[from] = tmp;
+}
+
+/*
  * Set up the vmcs to automatically save and restore system
  * msrs.  Don't touch the 64-bit msrs if the guest is in legacy
  * mode, as fiddling with msrs is very expensive.
  */
 static void setup_msrs(struct kvm_vcpu *vcpu)
 {
-	int nr_skip, nr_good_msrs;
+	int save_nmsrs;
 
-	if (is_long_mode(vcpu))
-		nr_skip = NR_BAD_MSRS;
-	else
-		nr_skip = NR_64BIT_MSRS;
-	nr_good_msrs = vcpu->nmsrs - nr_skip;
-
-	/*
-	 * MSR_K6_STAR is only needed on long mode guests, and only
-	 * if efer.sce is enabled.
-	 */
-	if (find_msr_entry(vcpu, MSR_K6_STAR)) {
-		--nr_good_msrs;
+	save_nmsrs = 0;
 #ifdef CONFIG_X86_64
-		if (is_long_mode(vcpu) && (vcpu->shadow_efer & EFER_SCE))
-			++nr_good_msrs;
-#endif
-	}
+	if (is_long_mode(vcpu)) {
+		int index;
 
-	vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR,
-		    virt_to_phys(vcpu->guest_msrs + nr_skip));
-	vmcs_writel(VM_EXIT_MSR_STORE_ADDR,
-		    virt_to_phys(vcpu->guest_msrs + nr_skip));
-	vmcs_writel(VM_EXIT_MSR_LOAD_ADDR,
-		    virt_to_phys(vcpu->host_msrs + nr_skip));
-	vmcs_write32(VM_EXIT_MSR_STORE_COUNT, nr_good_msrs); /* 22.2.2 */
-	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, nr_good_msrs);  /* 22.2.2 */
-	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */
+		index = __find_msr_index(vcpu, MSR_SYSCALL_MASK);
+		if (index >= 0)
+			move_msr_up(vcpu, index, save_nmsrs++);
+		index = __find_msr_index(vcpu, MSR_LSTAR);
+		if (index >= 0)
+			move_msr_up(vcpu, index, save_nmsrs++);
+		index = __find_msr_index(vcpu, MSR_CSTAR);
+		if (index >= 0)
+			move_msr_up(vcpu, index, save_nmsrs++);
+		index = __find_msr_index(vcpu, MSR_KERNEL_GS_BASE);
+		if (index >= 0)
+			move_msr_up(vcpu, index, save_nmsrs++);
+		/*
+		 * MSR_K6_STAR is only needed on long mode guests, and only
+		 * if efer.sce is enabled.
+		 */
+		index = __find_msr_index(vcpu, MSR_K6_STAR);
+		if ((index >= 0) && (vcpu->shadow_efer & EFER_SCE))
+			move_msr_up(vcpu, index, save_nmsrs++);
+	}
+#endif
+	vcpu->save_nmsrs = save_nmsrs;
+
+#ifdef CONFIG_X86_64
+	vcpu->msr_offset_kernel_gs_base =
+		__find_msr_index(vcpu, MSR_KERNEL_GS_BASE);
+#endif
+	vcpu->msr_offset_efer = __find_msr_index(vcpu, MSR_EFER);
 }
 
 /*
@@ -392,23 +581,6 @@
 	vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc);
 }
 
-static void reload_tss(void)
-{
-#ifndef CONFIG_X86_64
-
-	/*
-	 * VT restores TR but not its size.  Useless.
-	 */
-	struct descriptor_table gdt;
-	struct segment_descriptor *descs;
-
-	get_gdt(&gdt);
-	descs = (void *)gdt.base;
-	descs[GDT_ENTRY_TSS].type = 9; /* available TSS */
-	load_TR_desc();
-#endif
-}
-
 /*
  * Reads an msr value (of 'msr_index') into 'pdata'.
  * Returns 0 on success, non-0 otherwise.
@@ -468,10 +640,15 @@
 static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
 {
 	struct vmx_msr_entry *msr;
+	int ret = 0;
+
 	switch (msr_index) {
 #ifdef CONFIG_X86_64
 	case MSR_EFER:
-		return kvm_set_msr_common(vcpu, msr_index, data);
+		ret = kvm_set_msr_common(vcpu, msr_index, data);
+		if (vcpu->vmx_host_state.loaded)
+			load_transition_efer(vcpu);
+		break;
 	case MSR_FS_BASE:
 		vmcs_writel(GUEST_FS_BASE, data);
 		break;
@@ -495,14 +672,14 @@
 		msr = find_msr_entry(vcpu, msr_index);
 		if (msr) {
 			msr->data = data;
+			if (vcpu->vmx_host_state.loaded)
+				load_msrs(vcpu->guest_msrs, vcpu->save_nmsrs);
 			break;
 		}
-		return kvm_set_msr_common(vcpu, msr_index, data);
-		msr->data = data;
-		break;
+		ret = kvm_set_msr_common(vcpu, msr_index, data);
 	}
 
-	return 0;
+	return ret;
 }
 
 /*
@@ -528,10 +705,8 @@
 static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
 {
 	unsigned long dr7 = 0x400;
-	u32 exception_bitmap;
 	int old_singlestep;
 
-	exception_bitmap = vmcs_read32(EXCEPTION_BITMAP);
 	old_singlestep = vcpu->guest_debug.singlestep;
 
 	vcpu->guest_debug.enabled = dbg->enabled;
@@ -547,13 +722,9 @@
 			dr7 |= 0 << (i*4+16); /* execution breakpoint */
 		}
 
-		exception_bitmap |= (1u << 1);  /* Trap debug exceptions */
-
 		vcpu->guest_debug.singlestep = dbg->singlestep;
-	} else {
-		exception_bitmap &= ~(1u << 1); /* Ignore debug exceptions */
+	} else
 		vcpu->guest_debug.singlestep = 0;
-	}
 
 	if (old_singlestep && !vcpu->guest_debug.singlestep) {
 		unsigned long flags;
@@ -563,7 +734,7 @@
 		vmcs_writel(GUEST_RFLAGS, flags);
 	}
 
-	vmcs_write32(EXCEPTION_BITMAP, exception_bitmap);
+	update_exception_bitmap(vcpu);
 	vmcs_writel(GUEST_DR7, dr7);
 
 	return 0;
@@ -638,7 +809,7 @@
 	free_pages((unsigned long)vmcs, vmcs_descriptor.order);
 }
 
-static __exit void free_kvm_area(void)
+static void free_kvm_area(void)
 {
 	int cpu;
 
@@ -677,14 +848,6 @@
 	free_kvm_area();
 }
 
-static void update_exception_bitmap(struct kvm_vcpu *vcpu)
-{
-	if (vcpu->rmode.active)
-		vmcs_write32(EXCEPTION_BITMAP, ~0);
-	else
-		vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR);
-}
-
 static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
 {
 	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -791,6 +954,8 @@
 	fix_rmode_seg(VCPU_SREG_DS, &vcpu->rmode.ds);
 	fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs);
 	fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);
+
+	init_rmode_tss(vcpu->kvm);
 }
 
 #ifdef CONFIG_X86_64
@@ -835,6 +1000,8 @@
 
 static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
+	vmx_fpu_deactivate(vcpu);
+
 	if (vcpu->rmode.active && (cr0 & CR0_PE_MASK))
 		enter_pmode(vcpu);
 
@@ -850,26 +1017,20 @@
 	}
 #endif
 
-	if (!(cr0 & CR0_TS_MASK)) {
-		vcpu->fpu_active = 1;
-		vmcs_clear_bits(EXCEPTION_BITMAP, CR0_TS_MASK);
-	}
-
 	vmcs_writel(CR0_READ_SHADOW, cr0);
 	vmcs_writel(GUEST_CR0,
 		    (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON);
 	vcpu->cr0 = cr0;
+
+	if (!(cr0 & CR0_TS_MASK) || !(cr0 & CR0_PE_MASK))
+		vmx_fpu_activate(vcpu);
 }
 
 static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
 	vmcs_writel(GUEST_CR3, cr3);
-
-	if (!(vcpu->cr0 & CR0_TS_MASK)) {
-		vcpu->fpu_active = 0;
-		vmcs_set_bits(GUEST_CR0, CR0_TS_MASK);
-		vmcs_set_bits(EXCEPTION_BITMAP, 1 << NM_VECTOR);
-	}
+	if (vcpu->cr0 & CR0_PE_MASK)
+		vmx_fpu_deactivate(vcpu);
 }
 
 static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -935,23 +1096,11 @@
 	var->unusable = (ar >> 16) & 1;
 }
 
-static void vmx_set_segment(struct kvm_vcpu *vcpu,
-			    struct kvm_segment *var, int seg)
+static u32 vmx_segment_access_rights(struct kvm_segment *var)
 {
-	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
 	u32 ar;
 
-	vmcs_writel(sf->base, var->base);
-	vmcs_write32(sf->limit, var->limit);
-	vmcs_write16(sf->selector, var->selector);
-	if (vcpu->rmode.active && var->s) {
-		/*
-		 * Hack real-mode segments into vm86 compatibility.
-		 */
-		if (var->base == 0xffff0000 && var->selector == 0xf000)
-			vmcs_writel(sf->base, 0xf0000);
-		ar = 0xf3;
-	} else if (var->unusable)
+	if (var->unusable)
 		ar = 1 << 16;
 	else {
 		ar = var->type & 15;
@@ -965,6 +1114,35 @@
 	}
 	if (ar == 0) /* a 0 value means unusable */
 		ar = AR_UNUSABLE_MASK;
+
+	return ar;
+}
+
+static void vmx_set_segment(struct kvm_vcpu *vcpu,
+			    struct kvm_segment *var, int seg)
+{
+	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	u32 ar;
+
+	if (vcpu->rmode.active && seg == VCPU_SREG_TR) {
+		vcpu->rmode.tr.selector = var->selector;
+		vcpu->rmode.tr.base = var->base;
+		vcpu->rmode.tr.limit = var->limit;
+		vcpu->rmode.tr.ar = vmx_segment_access_rights(var);
+		return;
+	}
+	vmcs_writel(sf->base, var->base);
+	vmcs_write32(sf->limit, var->limit);
+	vmcs_write16(sf->selector, var->selector);
+	if (vcpu->rmode.active && var->s) {
+		/*
+		 * Hack real-mode segments into vm86 compatibility.
+		 */
+		if (var->base == 0xffff0000 && var->selector == 0xf000)
+			vmcs_writel(sf->base, 0xf0000);
+		ar = 0xf3;
+	} else
+		ar = vmx_segment_access_rights(var);
 	vmcs_write32(sf->ar_bytes, ar);
 }
 
@@ -1016,16 +1194,16 @@
 	}
 
 	page = kmap_atomic(p1, KM_USER0);
-	memset(page, 0, PAGE_SIZE);
+	clear_page(page);
 	*(u16*)(page + 0x66) = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
 	kunmap_atomic(page, KM_USER0);
 
 	page = kmap_atomic(p2, KM_USER0);
-	memset(page, 0, PAGE_SIZE);
+	clear_page(page);
 	kunmap_atomic(page, KM_USER0);
 
 	page = kmap_atomic(p3, KM_USER0);
-	memset(page, 0, PAGE_SIZE);
+	clear_page(page);
 	*(page + RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1) = ~0;
 	kunmap_atomic(page, KM_USER0);
 
@@ -1064,7 +1242,7 @@
 	struct descriptor_table dt;
 	int i;
 	int ret = 0;
-	extern asmlinkage void kvm_vmx_return(void);
+	unsigned long kvm_vmx_return;
 
 	if (!init_rmode_tss(vcpu->kvm)) {
 		ret = -ENOMEM;
@@ -1074,9 +1252,9 @@
 	memset(vcpu->regs, 0, sizeof(vcpu->regs));
 	vcpu->regs[VCPU_REGS_RDX] = get_rdx_init_val();
 	vcpu->cr8 = 0;
-	vcpu->apic_base = 0xfee00000 |
-			/*for vcpu 0*/ MSR_IA32_APICBASE_BSP |
-			MSR_IA32_APICBASE_ENABLE;
+	vcpu->apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
+	if (vcpu == &vcpu->kvm->vcpus[0])
+		vcpu->apic_base |= MSR_IA32_APICBASE_BSP;
 
 	fx_init(vcpu);
 
@@ -1127,8 +1305,8 @@
 	vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0);
 
 	/* I/O */
-	vmcs_write64(IO_BITMAP_A, 0);
-	vmcs_write64(IO_BITMAP_B, 0);
+	vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
+	vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
 
 	guest_write_tsc(0);
 
@@ -1148,12 +1326,11 @@
 			       CPU_BASED_HLT_EXITING         /* 20.6.2 */
 			       | CPU_BASED_CR8_LOAD_EXITING    /* 20.6.2 */
 			       | CPU_BASED_CR8_STORE_EXITING   /* 20.6.2 */
-			       | CPU_BASED_UNCOND_IO_EXITING   /* 20.6.2 */
+			       | CPU_BASED_ACTIVATE_IO_BITMAP  /* 20.6.2 */
 			       | CPU_BASED_MOV_DR_EXITING
 			       | CPU_BASED_USE_TSC_OFFSETING   /* 21.3 */
 			);
 
-	vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR);
 	vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
 	vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
 	vmcs_write32(CR3_TARGET_COUNT, 0);           /* 22.2.1 */
@@ -1183,8 +1360,11 @@
 	get_idt(&dt);
 	vmcs_writel(HOST_IDTR_BASE, dt.base);   /* 22.2.4 */
 
-
-	vmcs_writel(HOST_RIP, (unsigned long)kvm_vmx_return); /* 22.2.5 */
+	asm ("mov $.Lkvm_vmx_return, %0" : "=r"(kvm_vmx_return));
+	vmcs_writel(HOST_RIP, kvm_vmx_return); /* 22.2.5 */
+	vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
+	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
+	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0);
 
 	rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk);
 	vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs);
@@ -1208,10 +1388,6 @@
 		vcpu->host_msrs[j].reserved = 0;
 		vcpu->host_msrs[j].data = data;
 		vcpu->guest_msrs[j] = vcpu->host_msrs[j];
-#ifdef CONFIG_X86_64
-		if (index == MSR_KERNEL_GS_BASE)
-			msr_offset_kernel_gs_base = j;
-#endif
 		++vcpu->nmsrs;
 	}
 
@@ -1239,6 +1415,8 @@
 #ifdef CONFIG_X86_64
 	vmx_set_efer(vcpu, 0);
 #endif
+	vmx_fpu_activate(vcpu);
+	update_exception_bitmap(vcpu);
 
 	return 0;
 
@@ -1363,7 +1541,11 @@
 	if (!vcpu->rmode.active)
 		return 0;
 
-	if (vec == GP_VECTOR && err_code == 0)
+	/*
+	 * Instruction with address size override prefix opcode 0x67
+	 * Cause the #SS fault with 0 error code in VM86 mode.
+	 */
+	if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
 		if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE)
 			return 1;
 	return 0;
@@ -1398,10 +1580,7 @@
 	}
 
 	if (is_no_device(intr_info)) {
-		vcpu->fpu_active = 1;
-		vmcs_clear_bits(EXCEPTION_BITMAP, 1 << NM_VECTOR);
-		if (!(vcpu->cr0 & CR0_TS_MASK))
-			vmcs_clear_bits(GUEST_CR0, CR0_TS_MASK);
+		vmx_fpu_activate(vcpu);
 		return 1;
 	}
 
@@ -1443,8 +1622,13 @@
 
 	if (vcpu->rmode.active &&
 	    handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK,
-								error_code))
+								error_code)) {
+		if (vcpu->halt_request) {
+			vcpu->halt_request = 0;
+			return kvm_emulate_halt(vcpu);
+		}
 		return 1;
+	}
 
 	if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == (INTR_TYPE_EXCEPTION | 1)) {
 		kvm_run->exit_reason = KVM_EXIT_DEBUG;
@@ -1593,11 +1777,10 @@
 		break;
 	case 2: /* clts */
 		vcpu_load_rsp_rip(vcpu);
-		vcpu->fpu_active = 1;
-		vmcs_clear_bits(EXCEPTION_BITMAP, 1 << NM_VECTOR);
-		vmcs_clear_bits(GUEST_CR0, CR0_TS_MASK);
+		vmx_fpu_deactivate(vcpu);
 		vcpu->cr0 &= ~CR0_TS_MASK;
 		vmcs_writel(CR0_READ_SHADOW, vcpu->cr0);
+		vmx_fpu_activate(vcpu);
 		skip_emulated_instruction(vcpu);
 		return 1;
 	case 1: /*mov from cr*/
@@ -1732,12 +1915,7 @@
 static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	skip_emulated_instruction(vcpu);
-	if (vcpu->irq_summary)
-		return 1;
-
-	kvm_run->exit_reason = KVM_EXIT_HLT;
-	++vcpu->stat.halt_exits;
-	return 0;
+	return kvm_emulate_halt(vcpu);
 }
 
 static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -1768,7 +1946,7 @@
 };
 
 static const int kvm_vmx_max_exit_handlers =
-	sizeof(kvm_vmx_exit_handlers) / sizeof(*kvm_vmx_exit_handlers);
+	ARRAY_SIZE(kvm_vmx_exit_handlers);
 
 /*
  * The guest has exited.  See if we can fix it or if we need userspace
@@ -1808,63 +1986,44 @@
 		(vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF));
 }
 
+static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
+{
+}
+
 static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	u8 fail;
-	u16 fs_sel, gs_sel, ldt_sel;
-	int fs_gs_ldt_reload_needed;
 	int r;
 
-again:
-	/*
-	 * Set host fs and gs selectors.  Unfortunately, 22.2.3 does not
-	 * allow segment selectors with cpl > 0 or ti == 1.
-	 */
-	fs_sel = read_fs();
-	gs_sel = read_gs();
-	ldt_sel = read_ldt();
-	fs_gs_ldt_reload_needed = (fs_sel & 7) | (gs_sel & 7) | ldt_sel;
-	if (!fs_gs_ldt_reload_needed) {
-		vmcs_write16(HOST_FS_SELECTOR, fs_sel);
-		vmcs_write16(HOST_GS_SELECTOR, gs_sel);
-	} else {
-		vmcs_write16(HOST_FS_SELECTOR, 0);
-		vmcs_write16(HOST_GS_SELECTOR, 0);
-	}
-
-#ifdef CONFIG_X86_64
-	vmcs_writel(HOST_FS_BASE, read_msr(MSR_FS_BASE));
-	vmcs_writel(HOST_GS_BASE, read_msr(MSR_GS_BASE));
-#else
-	vmcs_writel(HOST_FS_BASE, segment_base(fs_sel));
-	vmcs_writel(HOST_GS_BASE, segment_base(gs_sel));
-#endif
-
-	if (!vcpu->mmio_read_completed)
-		do_interrupt_requests(vcpu, kvm_run);
-
+preempted:
 	if (vcpu->guest_debug.enabled)
 		kvm_guest_debug_pre(vcpu);
 
-	if (vcpu->fpu_active) {
-		fx_save(vcpu->host_fx_image);
-		fx_restore(vcpu->guest_fx_image);
-	}
+again:
+	if (!vcpu->mmio_read_completed)
+		do_interrupt_requests(vcpu, kvm_run);
+
+	vmx_save_host_state(vcpu);
+	kvm_load_guest_fpu(vcpu);
+
+	r = kvm_mmu_reload(vcpu);
+	if (unlikely(r))
+		goto out;
+
 	/*
 	 * Loading guest fpu may have cleared host cr0.ts
 	 */
 	vmcs_writel(HOST_CR0, read_cr0());
 
-#ifdef CONFIG_X86_64
-	if (is_long_mode(vcpu)) {
-		save_msrs(vcpu->host_msrs + msr_offset_kernel_gs_base, 1);
-		load_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
-	}
-#endif
+	local_irq_disable();
+
+	vcpu->guest_mode = 1;
+	if (vcpu->requests)
+		if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests))
+		    vmx_flush_tlb(vcpu);
 
 	asm (
 		/* Store host registers */
-		"pushf \n\t"
 #ifdef CONFIG_X86_64
 		"push %%rax; push %%rbx; push %%rdx;"
 		"push %%rsi; push %%rdi; push %%rbp;"
@@ -1909,12 +2068,11 @@
 		"mov %c[rcx](%3), %%ecx \n\t" /* kills %3 (ecx) */
 #endif
 		/* Enter guest mode */
-		"jne launched \n\t"
+		"jne .Llaunched \n\t"
 		ASM_VMX_VMLAUNCH "\n\t"
-		"jmp kvm_vmx_return \n\t"
-		"launched: " ASM_VMX_VMRESUME "\n\t"
-		".globl kvm_vmx_return \n\t"
-		"kvm_vmx_return: "
+		"jmp .Lkvm_vmx_return \n\t"
+		".Llaunched: " ASM_VMX_VMRESUME "\n\t"
+		".Lkvm_vmx_return: "
 		/* Save guest registers, load host registers, keep flags */
 #ifdef CONFIG_X86_64
 		"xchg %3,     (%%rsp) \n\t"
@@ -1957,7 +2115,6 @@
 		"pop %%ecx; popa \n\t"
 #endif
 		"setbe %0 \n\t"
-		"popf \n\t"
 	      : "=q" (fail)
 	      : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP),
 		"c"(vcpu),
@@ -1981,89 +2138,61 @@
 		[cr2]"i"(offsetof(struct kvm_vcpu, cr2))
 	      : "cc", "memory" );
 
-	/*
-	 * Reload segment selectors ASAP. (it's needed for a functional
-	 * kernel: x86 relies on having __KERNEL_PDA in %fs and x86_64
-	 * relies on having 0 in %gs for the CPU PDA to work.)
-	 */
-	if (fs_gs_ldt_reload_needed) {
-		load_ldt(ldt_sel);
-		load_fs(fs_sel);
-		/*
-		 * If we have to reload gs, we must take care to
-		 * preserve our gs base.
-		 */
-		local_irq_disable();
-		load_gs(gs_sel);
-#ifdef CONFIG_X86_64
-		wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
-#endif
-		local_irq_enable();
+	vcpu->guest_mode = 0;
+	local_irq_enable();
 
-		reload_tss();
-	}
 	++vcpu->stat.exits;
 
-#ifdef CONFIG_X86_64
-	if (is_long_mode(vcpu)) {
-		save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
-		load_msrs(vcpu->host_msrs, NR_BAD_MSRS);
-	}
-#endif
-
-	if (vcpu->fpu_active) {
-		fx_save(vcpu->guest_fx_image);
-		fx_restore(vcpu->host_fx_image);
-	}
-
 	vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0;
 
 	asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
 
-	if (fail) {
+	if (unlikely(fail)) {
 		kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
 		kvm_run->fail_entry.hardware_entry_failure_reason
 			= vmcs_read32(VM_INSTRUCTION_ERROR);
 		r = 0;
-	} else {
-		/*
-		 * Profile KVM exit RIPs:
-		 */
-		if (unlikely(prof_on == KVM_PROFILING))
-			profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
+		goto out;
+	}
+	/*
+	 * Profile KVM exit RIPs:
+	 */
+	if (unlikely(prof_on == KVM_PROFILING))
+		profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
 
-		vcpu->launched = 1;
-		r = kvm_handle_exit(kvm_run, vcpu);
-		if (r > 0) {
-			/* Give scheduler a change to reschedule. */
-			if (signal_pending(current)) {
-				++vcpu->stat.signal_exits;
-				post_kvm_run_save(vcpu, kvm_run);
-				kvm_run->exit_reason = KVM_EXIT_INTR;
-				return -EINTR;
-			}
+	vcpu->launched = 1;
+	r = kvm_handle_exit(kvm_run, vcpu);
+	if (r > 0) {
+		/* Give scheduler a change to reschedule. */
+		if (signal_pending(current)) {
+			r = -EINTR;
+			kvm_run->exit_reason = KVM_EXIT_INTR;
+			++vcpu->stat.signal_exits;
+			goto out;
+		}
 
-			if (dm_request_for_irq_injection(vcpu, kvm_run)) {
-				++vcpu->stat.request_irq_exits;
-				post_kvm_run_save(vcpu, kvm_run);
-				kvm_run->exit_reason = KVM_EXIT_INTR;
-				return -EINTR;
-			}
-
-			kvm_resched(vcpu);
+		if (dm_request_for_irq_injection(vcpu, kvm_run)) {
+			r = -EINTR;
+			kvm_run->exit_reason = KVM_EXIT_INTR;
+			++vcpu->stat.request_irq_exits;
+			goto out;
+		}
+		if (!need_resched()) {
+			++vcpu->stat.light_exits;
 			goto again;
 		}
 	}
 
+out:
+	if (r > 0) {
+		kvm_resched(vcpu);
+		goto preempted;
+	}
+
 	post_kvm_run_save(vcpu, kvm_run);
 	return r;
 }
 
-static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
-{
-	vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3));
-}
-
 static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
 				  unsigned long addr,
 				  u32 err_code)
@@ -2127,7 +2256,6 @@
 	vmcs_clear(vmcs);
 	vcpu->vmcs = vmcs;
 	vcpu->launched = 0;
-	vcpu->fpu_active = 1;
 
 	return 0;
 
@@ -2193,11 +2321,50 @@
 
 static int __init vmx_init(void)
 {
-	return kvm_init_arch(&vmx_arch_ops, THIS_MODULE);
+	void *iova;
+	int r;
+
+	vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+	if (!vmx_io_bitmap_a)
+		return -ENOMEM;
+
+	vmx_io_bitmap_b = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+	if (!vmx_io_bitmap_b) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Allow direct access to the PC debug port (it is often used for I/O
+	 * delays, but the vmexits simply slow things down).
+	 */
+	iova = kmap(vmx_io_bitmap_a);
+	memset(iova, 0xff, PAGE_SIZE);
+	clear_bit(0x80, iova);
+	kunmap(vmx_io_bitmap_a);
+
+	iova = kmap(vmx_io_bitmap_b);
+	memset(iova, 0xff, PAGE_SIZE);
+	kunmap(vmx_io_bitmap_b);
+
+	r = kvm_init_arch(&vmx_arch_ops, THIS_MODULE);
+	if (r)
+		goto out1;
+
+	return 0;
+
+out1:
+	__free_page(vmx_io_bitmap_b);
+out:
+	__free_page(vmx_io_bitmap_a);
+	return r;
 }
 
 static void __exit vmx_exit(void)
 {
+	__free_page(vmx_io_bitmap_b);
+	__free_page(vmx_io_bitmap_a);
+
 	kvm_exit_arch();
 }
 
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 7ade090..f60012d 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -98,8 +98,11 @@
 	0, 0, 0, 0,
 	/* 0x40 - 0x4F */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	/* 0x50 - 0x5F */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	/* 0x50 - 0x57 */
+	0, 0, 0, 0, 0, 0, 0, 0,
+	/* 0x58 - 0x5F */
+	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
 	/* 0x60 - 0x6F */
 	0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -128,9 +131,9 @@
 	/* 0xB0 - 0xBF */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0xC0 - 0xC7 */
-	ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0,
-	0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov,
-	    DstMem | SrcImm | ModRM | Mov,
+	ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
+	0, ImplicitOps, 0, 0,
+	ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov,
 	/* 0xC8 - 0xCF */
 	0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0xD0 - 0xD7 */
@@ -143,7 +146,8 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0xF0 - 0xF7 */
 	0, 0, 0, 0,
-	0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
+	ImplicitOps, 0,
+	ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
 	/* 0xF8 - 0xFF */
 	0, 0, 0, 0,
 	0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM
@@ -152,7 +156,7 @@
 static u16 twobyte_table[256] = {
 	/* 0x00 - 0x0F */
 	0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
-	0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+	0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
 	/* 0x10 - 0x1F */
 	0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x20 - 0x2F */
@@ -481,6 +485,7 @@
 	int mode = ctxt->mode;
 	unsigned long modrm_ea;
 	int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
+	int no_wb = 0;
 
 	/* Shadow copy of register state. Committed on successful emulation. */
 	unsigned long _regs[NR_VCPU_REGS];
@@ -1047,7 +1052,7 @@
 						      _regs[VCPU_REGS_RSP]),
 				     &dst.val, dst.bytes, ctxt)) != 0)
 				goto done;
-			dst.val = dst.orig_val;	/* skanky: disable writeback */
+			no_wb = 1;
 			break;
 		default:
 			goto cannot_emulate;
@@ -1056,7 +1061,7 @@
 	}
 
 writeback:
-	if ((d & Mov) || (dst.orig_val != dst.val)) {
+	if (!no_wb) {
 		switch (dst.type) {
 		case OP_REG:
 			/* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
@@ -1149,6 +1154,23 @@
 	case 0xae ... 0xaf:	/* scas */
 		DPRINTF("Urk! I don't handle SCAS.\n");
 		goto cannot_emulate;
+	case 0xf4:              /* hlt */
+		ctxt->vcpu->halt_request = 1;
+		goto done;
+	case 0xc3: /* ret */
+		dst.ptr = &_eip;
+		goto pop_instruction;
+	case 0x58 ... 0x5f: /* pop reg */
+		dst.ptr = (unsigned long *)&_regs[b & 0x7];
+
+pop_instruction:
+		if ((rc = ops->read_std(register_address(ctxt->ss_base,
+			_regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt)) != 0)
+			goto done;
+
+		register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
+		no_wb = 1; /* Disable writeback. */
+		break;
 	}
 	goto writeback;
 
@@ -1302,8 +1324,10 @@
 
 twobyte_special_insn:
 	/* Disable writeback. */
-	dst.orig_val = dst.val;
+	no_wb = 1;
 	switch (b) {
+	case 0x09:		/* wbinvd */
+		break;
 	case 0x0d:		/* GrpP (prefetch) */
 	case 0x18:		/* Grp16 (prefetch/nop) */
 		break;
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 58926da..dbe9626 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -2,7 +2,7 @@
 menuconfig MACINTOSH_DRIVERS
 	bool "Macintosh device drivers"
 	depends on PPC || MAC || X86
-	default y
+	default y if (PPC_PMAC || MAC)
 
 if MACINTOSH_DRIVERS
 
@@ -113,9 +113,8 @@
 
 config PMAC_APM_EMU
 	tristate "APM emulation"
-	select SYS_SUPPORTS_APM_EMULATION
 	select APM_EMULATION
-	depends on ADB_PMU && PM
+	depends on ADB_PMU && PM && PPC32
 
 config PMAC_MEDIABAY
 	bool "Support PowerBook hotswap media bay"
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index adfea3c..bc77c5e 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -248,21 +248,15 @@
 static int
 adb_probe_task(void *x)
 {
-	sigset_t blocked;
-
 	strcpy(current->comm, "kadbprobe");
 
-	sigfillset(&blocked);
-	sigprocmask(SIG_BLOCK, &blocked, NULL);
-	flush_signals(current);
-
 	printk(KERN_INFO "adb: starting probe task...\n");
 	do_adb_reset_bus();
 	printk(KERN_INFO "adb: finished probe task...\n");
-	
+
 	adb_probe_task_pid = 0;
 	up(&adb_probe_mutex);
-	
+
 	return 0;
 }
 
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index b77ef51..b46817f 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -628,16 +628,16 @@
  */
 static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct adbhid *adbhid = dev->private;
+	struct adbhid *adbhid = input_get_drvdata(dev);
 	unsigned char leds;
 
 	switch (type) {
 	case EV_LED:
-	  leds = (test_bit(LED_SCROLLL, dev->led) ? 4 : 0)
-	       | (test_bit(LED_NUML,    dev->led) ? 1 : 0)
-	       | (test_bit(LED_CAPSL,   dev->led) ? 2 : 0);
-	  real_leds(leds, adbhid->id);
-	  return 0;
+		leds =  (test_bit(LED_SCROLLL, dev->led) ? 4 : 0) |
+			(test_bit(LED_NUML,    dev->led) ? 1 : 0) |
+			(test_bit(LED_CAPSL,   dev->led) ? 2 : 0);
+		real_leds(leds, adbhid->id);
+		return 0;
 	}
 
 	return -1;
@@ -649,7 +649,7 @@
 	switch (code) {
 	case ADB_MSG_PRE_RESET:
 	case ADB_MSG_POWERDOWN:
-	    	/* Stop the repeat timer. Autopoll is already off at this point */
+		/* Stop the repeat timer. Autopoll is already off at this point */
 		{
 			int i;
 			for (i = 1; i < 16; i++) {
@@ -699,7 +699,7 @@
 	hid->current_handler_id = current_handler_id;
 	hid->mouse_kind = mouse_kind;
 	hid->flags = 0;
-	input_dev->private = hid;
+	input_set_drvdata(input_dev, hid);
 	input_dev->name = hid->name;
 	input_dev->phys = hid->phys;
 	input_dev->id.bustype = BUS_ADB;
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index bd55e6a..f25685b 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -335,6 +335,7 @@
 {
 	struct thermostat* th = arg;
 
+	set_freezable();
 	while(!kthread_should_stop()) {
 		try_to_freeze();
 		msleep_interruptible(2000);
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 11ced17..e18d265 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -92,6 +92,7 @@
 
 	DBG("wf: thread started\n");
 
+	set_freezable();
 	while(!kthread_should_stop()) {
 		if (time_after_eq(jiffies, next)) {
 			wf_notify(WF_EVENT_TICK, NULL);
@@ -212,7 +213,6 @@
 	list_add(&new_ct->link, &wf_controls);
 
 	new_ct->attr.attr.name = new_ct->name;
-	new_ct->attr.attr.owner = THIS_MODULE;
 	new_ct->attr.attr.mode = 0644;
 	new_ct->attr.show = wf_show_control;
 	new_ct->attr.store = wf_store_control;
@@ -325,7 +325,6 @@
 	list_add(&new_sr->link, &wf_sensors);
 
 	new_sr->attr.attr.name = new_sr->name;
-	new_sr->attr.attr.owner = THIS_MODULE;
 	new_sr->attr.attr.mode = 0444;
 	new_sr->attr.show = wf_show_sensor;
 	new_sr->attr.store = NULL;
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 1043b39..351982b 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -67,26 +67,6 @@
 	.detach_client	= wf_sat_detach,
 };
 
-/*
- * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested
- * length down to the low-level driver, so we use this, which
- * works well enough with the SMU i2c driver code...
- */
-static int sat_read_block(struct i2c_client *client, u8 command,
-			  u8 *values, int len)
-{
-	union i2c_smbus_data data;
-	int err;
-
-	data.block[0] = len;
-	err = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
-			     I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA,
-			     &data);
-	if (!err)
-		memcpy(values, data.block, len);
-	return err;
-}
-
 struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
 						  unsigned int *size)
 {
@@ -124,8 +104,8 @@
 		return NULL;
 
 	for (i = 0; i < len; i += 4) {
-		err = sat_read_block(&sat->i2c, 0xa, data, 4);
-		if (err) {
+		err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data);
+		if (err < 0) {
 			printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
 			       err);
 			goto fail;
@@ -157,8 +137,8 @@
 {
 	int err;
 
-	err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16);
-	if (err)
+	err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache);
+	if (err < 0)
 		return err;
 	sat->last_read = jiffies;
 #ifdef LOTSA_DEBUG
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 7df934d..531d4d1 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -2,19 +2,17 @@
 # Block device driver configuration
 #
 
-if BLOCK
-
-menu "Multi-device support (RAID and LVM)"
-
-config MD
+menuconfig MD
 	bool "Multiple devices driver support (RAID and LVM)"
+	depends on BLOCK
 	help
 	  Support multiple physical spindles through a single logical device.
 	  Required for RAID and logical volume management.
 
+if MD
+
 config BLK_DEV_MD
 	tristate "RAID support"
-	depends on MD
 	---help---
 	  This driver lets you combine several hard disk partitions into one
 	  logical block device. This can be used to simply append one
@@ -109,6 +107,8 @@
 config MD_RAID456
 	tristate "RAID-4/RAID-5/RAID-6 mode"
 	depends on BLK_DEV_MD
+	select ASYNC_MEMCPY
+	select ASYNC_XOR
 	---help---
 	  A RAID-5 set of N drives with a capacity of C MB per drive provides
 	  the capacity of C * (N - 1) MB, and protects against a failure
@@ -189,7 +189,6 @@
 
 config BLK_DEV_DM
 	tristate "Device mapper support"
-	depends on MD
 	---help---
 	  Device-mapper is a low level volume manager.  It works by allowing
 	  people to specify mappings for ranges of logical sectors.  Various
@@ -262,6 +261,12 @@
 	---help---
 	  Multipath support for EMC CX/AX series hardware.
 
+config DM_MULTIPATH_RDAC
+	tristate "LSI/Engenio RDAC multipath support (EXPERIMENTAL)"
+	depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+	---help---
+	  Multipath support for LSI/Engenio RDAC.
+
 config DM_DELAY
 	tristate "I/O delaying target (EXPERIMENTAL)"
 	depends on BLK_DEV_DM && EXPERIMENTAL
@@ -271,6 +276,4 @@
 
 	If unsure, say N.
 
-endmenu
-
-endif
+endif # MD
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 3875408..c49366c 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -7,6 +7,7 @@
 dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
 dm-snapshot-objs := dm-snap.o dm-exception-store.o
 dm-mirror-objs	:= dm-log.o dm-raid1.o
+dm-rdac-objs	:= dm-mpath-rdac.o
 md-mod-objs     := md.o bitmap.o
 raid456-objs	:= raid5.o raid6algos.o raid6recov.o raid6tables.o \
 		   raid6int1.o raid6int2.o raid6int4.o \
@@ -17,7 +18,7 @@
 hostprogs-y	:= mktables
 
 # Note: link order is important.  All raid personalities
-# and xor.o must come before md.o, as they each initialise 
+# and must come before md.o, as they each initialise 
 # themselves, and md.o may use the personalities when it 
 # auto-initialised.
 
@@ -25,7 +26,7 @@
 obj-$(CONFIG_MD_RAID0)		+= raid0.o
 obj-$(CONFIG_MD_RAID1)		+= raid1.o
 obj-$(CONFIG_MD_RAID10)		+= raid10.o
-obj-$(CONFIG_MD_RAID456)	+= raid456.o xor.o
+obj-$(CONFIG_MD_RAID456)	+= raid456.o
 obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
 obj-$(CONFIG_MD_FAULTY)		+= faulty.o
 obj-$(CONFIG_BLK_DEV_MD)	+= md-mod.o
@@ -34,6 +35,7 @@
 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
+obj-$(CONFIG_DM_MULTIPATH_RDAC)	+= dm-rdac.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 5a4a74c..927cb34 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -255,51 +255,88 @@
 
 }
 
-static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
+static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
 {
 	mdk_rdev_t *rdev;
 	struct list_head *tmp;
+	mddev_t *mddev = bitmap->mddev;
 
 	ITERATE_RDEV(mddev, rdev, tmp)
 		if (test_bit(In_sync, &rdev->flags)
-		    && !test_bit(Faulty, &rdev->flags))
+		    && !test_bit(Faulty, &rdev->flags)) {
+			int size = PAGE_SIZE;
+			if (page->index == bitmap->file_pages-1)
+				size = roundup(bitmap->last_page_size,
+					       bdev_hardsect_size(rdev->bdev));
+			/* Just make sure we aren't corrupting data or
+			 * metadata
+			 */
+			if (bitmap->offset < 0) {
+				/* DATA  BITMAP METADATA  */
+				if (bitmap->offset
+				    + page->index * (PAGE_SIZE/512)
+				    + size/512 > 0)
+					/* bitmap runs in to metadata */
+					return -EINVAL;
+				if (rdev->data_offset + mddev->size*2
+				    > rdev->sb_offset*2 + bitmap->offset)
+					/* data runs in to bitmap */
+					return -EINVAL;
+			} else if (rdev->sb_offset*2 < rdev->data_offset) {
+				/* METADATA BITMAP DATA */
+				if (rdev->sb_offset*2
+				    + bitmap->offset
+				    + page->index*(PAGE_SIZE/512) + size/512
+				    > rdev->data_offset)
+					/* bitmap runs in to data */
+					return -EINVAL;
+			} else {
+				/* DATA METADATA BITMAP - no problems */
+			}
 			md_super_write(mddev, rdev,
-				       (rdev->sb_offset<<1) + offset
+				       (rdev->sb_offset<<1) + bitmap->offset
 				       + page->index * (PAGE_SIZE/512),
-				       PAGE_SIZE,
+				       size,
 				       page);
+		}
 
 	if (wait)
 		md_super_wait(mddev);
 	return 0;
 }
 
+static void bitmap_file_kick(struct bitmap *bitmap);
 /*
  * write out a page to a file
  */
-static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+static void write_page(struct bitmap *bitmap, struct page *page, int wait)
 {
 	struct buffer_head *bh;
 
-	if (bitmap->file == NULL)
-		return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+	if (bitmap->file == NULL) {
+		switch (write_sb_page(bitmap, page, wait)) {
+		case -EINVAL:
+			bitmap->flags |= BITMAP_WRITE_ERROR;
+		}
+	} else {
 
-	bh = page_buffers(page);
+		bh = page_buffers(page);
 
-	while (bh && bh->b_blocknr) {
-		atomic_inc(&bitmap->pending_writes);
-		set_buffer_locked(bh);
-		set_buffer_mapped(bh);
-		submit_bh(WRITE, bh);
-		bh = bh->b_this_page;
+		while (bh && bh->b_blocknr) {
+			atomic_inc(&bitmap->pending_writes);
+			set_buffer_locked(bh);
+			set_buffer_mapped(bh);
+			submit_bh(WRITE, bh);
+			bh = bh->b_this_page;
+		}
+
+		if (wait) {
+			wait_event(bitmap->write_wait,
+				   atomic_read(&bitmap->pending_writes)==0);
+		}
 	}
-
-	if (wait) {
-		wait_event(bitmap->write_wait,
-			   atomic_read(&bitmap->pending_writes)==0);
-		return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0;
-	}
-	return 0;
+	if (bitmap->flags & BITMAP_WRITE_ERROR)
+		bitmap_file_kick(bitmap);
 }
 
 static void end_bitmap_write(struct buffer_head *bh, int uptodate)
@@ -419,17 +456,17 @@
  */
 
 /* update the event counter and sync the superblock to disk */
-int bitmap_update_sb(struct bitmap *bitmap)
+void bitmap_update_sb(struct bitmap *bitmap)
 {
 	bitmap_super_t *sb;
 	unsigned long flags;
 
 	if (!bitmap || !bitmap->mddev) /* no bitmap for this array */
-		return 0;
+		return;
 	spin_lock_irqsave(&bitmap->lock, flags);
 	if (!bitmap->sb_page) { /* no superblock */
 		spin_unlock_irqrestore(&bitmap->lock, flags);
-		return 0;
+		return;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
@@ -437,7 +474,7 @@
 	if (!bitmap->mddev->degraded)
 		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
 	kunmap_atomic(sb, KM_USER0);
-	return write_page(bitmap, bitmap->sb_page, 1);
+	write_page(bitmap, bitmap->sb_page, 1);
 }
 
 /* print out the bitmap file superblock */
@@ -566,20 +603,22 @@
 	MASK_UNSET
 };
 
-/* record the state of the bitmap in the superblock */
-static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
-				enum bitmap_mask_op op)
+/* record the state of the bitmap in the superblock.  Return the old value */
+static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
+			     enum bitmap_mask_op op)
 {
 	bitmap_super_t *sb;
 	unsigned long flags;
+	int old;
 
 	spin_lock_irqsave(&bitmap->lock, flags);
 	if (!bitmap->sb_page) { /* can't set the state */
 		spin_unlock_irqrestore(&bitmap->lock, flags);
-		return;
+		return 0;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
+	old = le32_to_cpu(sb->state) & bits;
 	switch (op) {
 		case MASK_SET: sb->state |= cpu_to_le32(bits);
 				break;
@@ -588,6 +627,7 @@
 		default: BUG();
 	}
 	kunmap_atomic(sb, KM_USER0);
+	return old;
 }
 
 /*
@@ -681,18 +721,23 @@
 {
 	char *path, *ptr = NULL;
 
-	bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
-	bitmap_update_sb(bitmap);
+	if (bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET) == 0) {
+		bitmap_update_sb(bitmap);
 
-	if (bitmap->file) {
-		path = kmalloc(PAGE_SIZE, GFP_KERNEL);
-		if (path)
-			ptr = file_path(bitmap->file, path, PAGE_SIZE);
+		if (bitmap->file) {
+			path = kmalloc(PAGE_SIZE, GFP_KERNEL);
+			if (path)
+				ptr = file_path(bitmap->file, path, PAGE_SIZE);
 
-		printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
-		       bmname(bitmap), ptr ? ptr : "");
+			printk(KERN_ALERT
+			      "%s: kicking failed bitmap file %s from array!\n",
+			      bmname(bitmap), ptr ? ptr : "");
 
-		kfree(path);
+			kfree(path);
+		} else
+			printk(KERN_ALERT
+			       "%s: disabling internal bitmap due to errors\n",
+			       bmname(bitmap));
 	}
 
 	bitmap_file_put(bitmap);
@@ -763,16 +808,15 @@
 /* this gets called when the md device is ready to unplug its underlying
  * (slave) device queues -- before we let any writes go down, we need to
  * sync the dirty pages of the bitmap file to disk */
-int bitmap_unplug(struct bitmap *bitmap)
+void bitmap_unplug(struct bitmap *bitmap)
 {
 	unsigned long i, flags;
 	int dirty, need_write;
 	struct page *page;
 	int wait = 0;
-	int err;
 
 	if (!bitmap)
-		return 0;
+		return;
 
 	/* look at each page to see if there are any set bits that need to be
 	 * flushed out to disk */
@@ -780,7 +824,7 @@
 		spin_lock_irqsave(&bitmap->lock, flags);
 		if (!bitmap->filemap) {
 			spin_unlock_irqrestore(&bitmap->lock, flags);
-			return 0;
+			return;
 		}
 		page = bitmap->filemap[i];
 		dirty = test_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
@@ -792,7 +836,7 @@
 		spin_unlock_irqrestore(&bitmap->lock, flags);
 
 		if (dirty | need_write)
-			err = write_page(bitmap, page, 0);
+			write_page(bitmap, page, 0);
 	}
 	if (wait) { /* if any writes were performed, we need to wait on them */
 		if (bitmap->file)
@@ -803,7 +847,6 @@
 	}
 	if (bitmap->flags & BITMAP_WRITE_ERROR)
 		bitmap_file_kick(bitmap);
-	return 0;
 }
 
 static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
@@ -852,21 +895,21 @@
 			bmname(bitmap),
 			(unsigned long) i_size_read(file->f_mapping->host),
 			bytes + sizeof(bitmap_super_t));
-		goto out;
+		goto err;
 	}
 
 	ret = -ENOMEM;
 
 	bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
 	if (!bitmap->filemap)
-		goto out;
+		goto err;
 
 	/* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */
 	bitmap->filemap_attr = kzalloc(
 		roundup( DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
 		GFP_KERNEL);
 	if (!bitmap->filemap_attr)
-		goto out;
+		goto err;
 
 	oldindex = ~0L;
 
@@ -899,7 +942,7 @@
 			}
 			if (IS_ERR(page)) { /* read error */
 				ret = PTR_ERR(page);
-				goto out;
+				goto err;
 			}
 
 			oldindex = index;
@@ -914,15 +957,18 @@
 				memset(paddr + offset, 0xff,
 				       PAGE_SIZE - offset);
 				kunmap_atomic(paddr, KM_USER0);
-				ret = write_page(bitmap, page, 1);
-				if (ret) {
+				write_page(bitmap, page, 1);
+
+				ret = -EIO;
+				if (bitmap->flags & BITMAP_WRITE_ERROR) {
 					/* release, page not in filemap yet */
 					put_page(page);
-					goto out;
+					goto err;
 				}
 			}
 
 			bitmap->filemap[bitmap->file_pages++] = page;
+			bitmap->last_page_size = count;
 		}
 		paddr = kmap_atomic(page, KM_USER0);
 		if (bitmap->flags & BITMAP_HOSTENDIAN)
@@ -949,11 +995,15 @@
 		md_wakeup_thread(bitmap->mddev->thread);
 	}
 
-out:
 	printk(KERN_INFO "%s: bitmap initialized from disk: "
-		"read %lu/%lu pages, set %lu bits, status: %d\n",
-		bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, ret);
+		"read %lu/%lu pages, set %lu bits\n",
+		bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt);
 
+	return 0;
+
+ err:
+	printk(KERN_INFO "%s: bitmap initialisation failed: %d\n",
+	       bmname(bitmap), ret);
 	return ret;
 }
 
@@ -990,19 +1040,18 @@
  *			out to disk
  */
 
-int bitmap_daemon_work(struct bitmap *bitmap)
+void bitmap_daemon_work(struct bitmap *bitmap)
 {
 	unsigned long j;
 	unsigned long flags;
 	struct page *page = NULL, *lastpage = NULL;
-	int err = 0;
 	int blocks;
 	void *paddr;
 
 	if (bitmap == NULL)
-		return 0;
+		return;
 	if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
-		return 0;
+		return;
 	bitmap->daemon_lastrun = jiffies;
 
 	for (j = 0; j < bitmap->chunks; j++) {
@@ -1025,14 +1074,8 @@
 					clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
 
 				spin_unlock_irqrestore(&bitmap->lock, flags);
-				if (need_write) {
-					switch (write_page(bitmap, page, 0)) {
-					case 0:
-						break;
-					default:
-						bitmap_file_kick(bitmap);
-					}
-				}
+				if (need_write)
+					write_page(bitmap, page, 0);
 				continue;
 			}
 
@@ -1041,13 +1084,11 @@
 				if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
 					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
-					err = write_page(bitmap, lastpage, 0);
+					write_page(bitmap, lastpage, 0);
 				} else {
 					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 				}
-				if (err)
-					bitmap_file_kick(bitmap);
 			} else
 				spin_unlock_irqrestore(&bitmap->lock, flags);
 			lastpage = page;
@@ -1090,14 +1131,13 @@
 		if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
 			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 			spin_unlock_irqrestore(&bitmap->lock, flags);
-			err = write_page(bitmap, lastpage, 0);
+			write_page(bitmap, lastpage, 0);
 		} else {
 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 			spin_unlock_irqrestore(&bitmap->lock, flags);
 		}
 	}
 
-	return err;
 }
 
 static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1510,7 +1550,9 @@
 
 	mddev->thread->timeout = bitmap->daemon_sleep * HZ;
 
-	return bitmap_update_sb(bitmap);
+	bitmap_update_sb(bitmap);
+
+	return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0;
 
  error:
 	bitmap_free(bitmap);
diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h
index c6be888..16ee3b0 100644
--- a/drivers/md/dm-bio-list.h
+++ b/drivers/md/dm-bio-list.h
@@ -8,7 +8,6 @@
 #define DM_BIO_LIST_H
 
 #include <linux/bio.h>
-#include <linux/prefetch.h>
 
 struct bio_list {
 	struct bio *head;
@@ -31,8 +30,7 @@
 }
 
 #define bio_list_for_each(bio, bl) \
-	for (bio = (bl)->head; bio && ({ prefetch(bio->bi_next); 1; }); \
-	     bio = bio->bi_next)
+	for (bio = (bl)->head; bio; bio = bio->bi_next)
 
 static inline unsigned bio_list_size(const struct bio_list *bl)
 {
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 7b0fcfc..ba952a0 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -30,7 +30,7 @@
 /*
  * per bio private data
  */
-struct crypt_io {
+struct dm_crypt_io {
 	struct dm_target *target;
 	struct bio *base_bio;
 	struct work_struct work;
@@ -106,7 +106,7 @@
 
 static struct kmem_cache *_crypt_io_pool;
 
-static void clone_init(struct crypt_io *, struct bio *);
+static void clone_init(struct dm_crypt_io *, struct bio *);
 
 /*
  * Different IV generation algorithms:
@@ -382,7 +382,7 @@
 
  static void dm_crypt_bio_destructor(struct bio *bio)
  {
-	struct crypt_io *io = bio->bi_private;
+	struct dm_crypt_io *io = bio->bi_private;
 	struct crypt_config *cc = io->target->private;
 
 	bio_free(bio, cc->bs);
@@ -393,7 +393,7 @@
  * This should never violate the device limitations
  * May return a smaller bio when running out of pages
  */
-static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size)
+static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
 {
 	struct crypt_config *cc = io->target->private;
 	struct bio *clone;
@@ -479,7 +479,7 @@
  * One of the bios was finished. Check for completion of
  * the whole request and correctly clean up the buffer.
  */
-static void dec_pending(struct crypt_io *io, int error)
+static void dec_pending(struct dm_crypt_io *io, int error)
 {
 	struct crypt_config *cc = (struct crypt_config *) io->target->private;
 
@@ -503,7 +503,7 @@
 static struct workqueue_struct *_kcryptd_workqueue;
 static void kcryptd_do_work(struct work_struct *work);
 
-static void kcryptd_queue_io(struct crypt_io *io)
+static void kcryptd_queue_io(struct dm_crypt_io *io)
 {
 	INIT_WORK(&io->work, kcryptd_do_work);
 	queue_work(_kcryptd_workqueue, &io->work);
@@ -511,7 +511,7 @@
 
 static int crypt_endio(struct bio *clone, unsigned int done, int error)
 {
-	struct crypt_io *io = clone->bi_private;
+	struct dm_crypt_io *io = clone->bi_private;
 	struct crypt_config *cc = io->target->private;
 	unsigned read_io = bio_data_dir(clone) == READ;
 
@@ -545,7 +545,7 @@
 	return error;
 }
 
-static void clone_init(struct crypt_io *io, struct bio *clone)
+static void clone_init(struct dm_crypt_io *io, struct bio *clone)
 {
 	struct crypt_config *cc = io->target->private;
 
@@ -556,7 +556,7 @@
 	clone->bi_destructor = dm_crypt_bio_destructor;
 }
 
-static void process_read(struct crypt_io *io)
+static void process_read(struct dm_crypt_io *io)
 {
 	struct crypt_config *cc = io->target->private;
 	struct bio *base_bio = io->base_bio;
@@ -587,7 +587,7 @@
 	generic_make_request(clone);
 }
 
-static void process_write(struct crypt_io *io)
+static void process_write(struct dm_crypt_io *io)
 {
 	struct crypt_config *cc = io->target->private;
 	struct bio *base_bio = io->base_bio;
@@ -644,7 +644,7 @@
 	}
 }
 
-static void process_read_endio(struct crypt_io *io)
+static void process_read_endio(struct dm_crypt_io *io)
 {
 	struct crypt_config *cc = io->target->private;
 	struct convert_context ctx;
@@ -657,7 +657,7 @@
 
 static void kcryptd_do_work(struct work_struct *work)
 {
-	struct crypt_io *io = container_of(work, struct crypt_io, work);
+	struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
 
 	if (io->post_process)
 		process_read_endio(io);
@@ -939,10 +939,7 @@
 		     union map_info *map_context)
 {
 	struct crypt_config *cc = ti->private;
-	struct crypt_io *io;
-
-	if (bio_barrier(bio))
-		return -EOPNOTSUPP;
+	struct dm_crypt_io *io;
 
 	io = mempool_alloc(cc->io_pool, GFP_NOIO);
 	io->target = ti;
@@ -1062,9 +1059,7 @@
 {
 	int r;
 
-	_crypt_io_pool = kmem_cache_create("dm-crypt_io",
-	                                   sizeof(struct crypt_io),
-	                                   0, 0, NULL, NULL);
+	_crypt_io_pool = KMEM_CACHE(dm_crypt_io, 0);
 	if (!_crypt_io_pool)
 		return -ENOMEM;
 
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 52c7cf9..6928c13 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -20,7 +20,7 @@
 
 struct delay_c {
 	struct timer_list delay_timer;
-	struct semaphore timer_lock;
+	struct mutex timer_lock;
 	struct work_struct flush_expired_bios;
 	struct list_head delayed_bios;
 	atomic_t may_delay;
@@ -37,7 +37,7 @@
 	unsigned writes;
 };
 
-struct delay_info {
+struct dm_delay_info {
 	struct delay_c *context;
 	struct list_head list;
 	struct bio *bio;
@@ -58,12 +58,12 @@
 
 static void queue_timeout(struct delay_c *dc, unsigned long expires)
 {
-	down(&dc->timer_lock);
+	mutex_lock(&dc->timer_lock);
 
 	if (!timer_pending(&dc->delay_timer) || expires < dc->delay_timer.expires)
 		mod_timer(&dc->delay_timer, expires);
 
-	up(&dc->timer_lock);
+	mutex_unlock(&dc->timer_lock);
 }
 
 static void flush_bios(struct bio *bio)
@@ -80,7 +80,7 @@
 
 static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all)
 {
-	struct delay_info *delayed, *next;
+	struct dm_delay_info *delayed, *next;
 	unsigned long next_expires = 0;
 	int start_timer = 0;
 	BIO_LIST(flush_bios);
@@ -193,13 +193,11 @@
 		goto bad;
 	}
 
-	init_timer(&dc->delay_timer);
-	dc->delay_timer.function = handle_delayed_timer;
-	dc->delay_timer.data = (unsigned long)dc;
+	setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc);
 
 	INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
 	INIT_LIST_HEAD(&dc->delayed_bios);
-	init_MUTEX(&dc->timer_lock);
+	mutex_init(&dc->timer_lock);
 	atomic_set(&dc->may_delay, 1);
 
 	ti->private = dc;
@@ -227,7 +225,7 @@
 
 static int delay_bio(struct delay_c *dc, int delay, struct bio *bio)
 {
-	struct delay_info *delayed;
+	struct dm_delay_info *delayed;
 	unsigned long expires = 0;
 
 	if (!delay || !atomic_read(&dc->may_delay))
@@ -338,10 +336,7 @@
 		goto bad_queue;
 	}
 
-	delayed_cache = kmem_cache_create("dm-delay",
-					  sizeof(struct delay_info),
-					  __alignof__(struct delay_info),
-					  0, NULL, NULL);
+	delayed_cache = KMEM_CACHE(dm_delay_info, 0);
 	if (!delayed_cache) {
 		DMERR("Couldn't create delayed bio cache.");
 		goto bad_memcache;
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 07e0a0c..3d65917 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -125,9 +125,11 @@
 	uint32_t callback_count;
 	struct commit_callback *callbacks;
 	struct dm_io_client *io_client;
+
+	struct workqueue_struct *metadata_wq;
 };
 
-static inline unsigned int sectors_to_pages(unsigned int sectors)
+static unsigned sectors_to_pages(unsigned sectors)
 {
 	return sectors / (PAGE_SIZE >> 9);
 }
@@ -156,10 +158,24 @@
 	ps->area = NULL;
 }
 
+struct mdata_req {
+	struct io_region *where;
+	struct dm_io_request *io_req;
+	struct work_struct work;
+	int result;
+};
+
+static void do_metadata(struct work_struct *work)
+{
+	struct mdata_req *req = container_of(work, struct mdata_req, work);
+
+	req->result = dm_io(req->io_req, 1, req->where, NULL);
+}
+
 /*
  * Read or write a chunk aligned and sized block of data from a device.
  */
-static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
+static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
 {
 	struct io_region where = {
 		.bdev = ps->snap->cow->bdev,
@@ -173,8 +189,23 @@
 		.client = ps->io_client,
 		.notify.fn = NULL,
 	};
+	struct mdata_req req;
 
-	return dm_io(&io_req, 1, &where, NULL);
+	if (!metadata)
+		return dm_io(&io_req, 1, &where, NULL);
+
+	req.where = &where;
+	req.io_req = &io_req;
+
+	/*
+	 * Issue the synchronous I/O from a different thread
+	 * to avoid generic_make_request recursion.
+	 */
+	INIT_WORK(&req.work, do_metadata);
+	queue_work(ps->metadata_wq, &req.work);
+	flush_workqueue(ps->metadata_wq);
+
+	return req.result;
 }
 
 /*
@@ -189,7 +220,7 @@
 	/* convert a metadata area index to a chunk index */
 	chunk = 1 + ((ps->exceptions_per_area + 1) * area);
 
-	r = chunk_io(ps, chunk, rw);
+	r = chunk_io(ps, chunk, rw, 0);
 	if (r)
 		return r;
 
@@ -230,7 +261,7 @@
 	if (r)
 		return r;
 
-	r = chunk_io(ps, 0, READ);
+	r = chunk_io(ps, 0, READ, 1);
 	if (r)
 		goto bad;
 
@@ -292,7 +323,7 @@
 	dh->version = cpu_to_le32(ps->version);
 	dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
 
-	return chunk_io(ps, 0, WRITE);
+	return chunk_io(ps, 0, WRITE, 1);
 }
 
 /*
@@ -393,7 +424,7 @@
 	return 0;
 }
 
-static inline struct pstore *get_info(struct exception_store *store)
+static struct pstore *get_info(struct exception_store *store)
 {
 	return (struct pstore *) store->context;
 }
@@ -409,6 +440,7 @@
 {
 	struct pstore *ps = get_info(store);
 
+	destroy_workqueue(ps->metadata_wq);
 	dm_io_client_destroy(ps->io_client);
 	vfree(ps->callbacks);
 	free_area(ps);
@@ -457,11 +489,6 @@
 		/*
 		 * Sanity checks.
 		 */
-		if (!ps->valid) {
-			DMWARN("snapshot is marked invalid");
-			return -EINVAL;
-		}
-
 		if (ps->version != SNAPSHOT_DISK_VERSION) {
 			DMWARN("unable to handle snapshot disk version %d",
 			       ps->version);
@@ -469,6 +496,12 @@
 		}
 
 		/*
+		 * Metadata are valid, but snapshot is invalidated
+		 */
+		if (!ps->valid)
+			return 1;
+
+		/*
 		 * Read the metadata.
 		 */
 		r = read_exceptions(ps);
@@ -480,7 +513,7 @@
 }
 
 static int persistent_prepare(struct exception_store *store,
-			      struct exception *e)
+			      struct dm_snap_exception *e)
 {
 	struct pstore *ps = get_info(store);
 	uint32_t stride;
@@ -505,7 +538,7 @@
 }
 
 static void persistent_commit(struct exception_store *store,
-			      struct exception *e,
+			      struct dm_snap_exception *e,
 			      void (*callback) (void *, int success),
 			      void *callback_context)
 {
@@ -588,6 +621,12 @@
 	atomic_set(&ps->pending_count, 0);
 	ps->callbacks = NULL;
 
+	ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
+	if (!ps->metadata_wq) {
+		DMERR("couldn't start header metadata update thread");
+		return -ENOMEM;
+	}
+
 	store->destroy = persistent_destroy;
 	store->read_metadata = persistent_read_metadata;
 	store->prepare_exception = persistent_prepare;
@@ -616,7 +655,8 @@
 	return 0;
 }
 
-static int transient_prepare(struct exception_store *store, struct exception *e)
+static int transient_prepare(struct exception_store *store,
+			     struct dm_snap_exception *e)
 {
 	struct transient_c *tc = (struct transient_c *) store->context;
 	sector_t size = get_dev_size(store->snap->cow->bdev);
@@ -631,9 +671,9 @@
 }
 
 static void transient_commit(struct exception_store *store,
-		      struct exception *e,
-		      void (*callback) (void *, int success),
-		      void *callback_context)
+			     struct dm_snap_exception *e,
+			     void (*callback) (void *, int success),
+			     void *callback_context)
 {
 	/* Just succeed */
 	callback(callback_context, 1);
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 352c6fb..f3a7724 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -293,7 +293,10 @@
 		 * bvec for bio_get/set_region() and decrement bi_max_vecs
 		 * to hide it from bio_add_page().
 		 */
-		num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2;
+		num_bvecs = dm_sector_div_up(remaining,
+					     (PAGE_SIZE >> SECTOR_SHIFT));
+		num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev),
+				      num_bvecs);
 		bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios);
 		bio->bi_sector = where->sector + (where->count - remaining);
 		bio->bi_bdev = where->bdev;
diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c
new file mode 100644
index 0000000..8b776b8
--- /dev/null
+++ b/drivers/md/dm-mpath-rdac.c
@@ -0,0 +1,700 @@
+/*
+ * Engenio/LSI RDAC DM HW handler
+ *
+ * Copyright (C) 2005 Mike Christie. All rights reserved.
+ * Copyright (C) Chandra Seetharaman, IBM Corp. 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+
+#define DM_MSG_PREFIX "multipath rdac"
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+#define RDAC_DM_HWH_NAME "rdac"
+#define RDAC_DM_HWH_VER "0.4"
+
+/*
+ * LSI mode page stuff
+ *
+ * These struct definitions and the forming of the
+ * mode page were taken from the LSI RDAC 2.4 GPL'd
+ * driver, and then converted to Linux conventions.
+ */
+#define RDAC_QUIESCENCE_TIME 20;
+/*
+ * Page Codes
+ */
+#define RDAC_PAGE_CODE_REDUNDANT_CONTROLLER 0x2c
+
+/*
+ * Controller modes definitions
+ */
+#define RDAC_MODE_TRANSFER_ALL_LUNS		0x01
+#define RDAC_MODE_TRANSFER_SPECIFIED_LUNS	0x02
+
+/*
+ * RDAC Options field
+ */
+#define RDAC_FORCED_QUIESENCE 0x02
+
+#define RDAC_FAILOVER_TIMEOUT (60 * HZ)
+
+struct rdac_mode_6_hdr {
+	u8	data_len;
+	u8	medium_type;
+	u8	device_params;
+	u8	block_desc_len;
+};
+
+struct rdac_mode_10_hdr {
+	u16	data_len;
+	u8	medium_type;
+	u8	device_params;
+	u16	reserved;
+	u16	block_desc_len;
+};
+
+struct rdac_mode_common {
+	u8	controller_serial[16];
+	u8	alt_controller_serial[16];
+	u8	rdac_mode[2];
+	u8	alt_rdac_mode[2];
+	u8	quiescence_timeout;
+	u8	rdac_options;
+};
+
+struct rdac_pg_legacy {
+	struct rdac_mode_6_hdr hdr;
+	u8	page_code;
+	u8	page_len;
+	struct rdac_mode_common common;
+#define MODE6_MAX_LUN	32
+	u8	lun_table[MODE6_MAX_LUN];
+	u8	reserved2[32];
+	u8	reserved3;
+	u8	reserved4;
+};
+
+struct rdac_pg_expanded {
+	struct rdac_mode_10_hdr hdr;
+	u8	page_code;
+	u8	subpage_code;
+	u8	page_len[2];
+	struct rdac_mode_common common;
+	u8	lun_table[256];
+	u8	reserved3;
+	u8	reserved4;
+};
+
+struct c9_inquiry {
+	u8	peripheral_info;
+	u8	page_code;	/* 0xC9 */
+	u8	reserved1;
+	u8	page_len;
+	u8	page_id[4];	/* "vace" */
+	u8	avte_cvp;
+	u8	path_prio;
+	u8	reserved2[38];
+};
+
+#define SUBSYS_ID_LEN	16
+#define SLOT_ID_LEN	2
+
+struct c4_inquiry {
+	u8	peripheral_info;
+	u8	page_code;	/* 0xC4 */
+	u8	reserved1;
+	u8	page_len;
+	u8	page_id[4];	/* "subs" */
+	u8	subsys_id[SUBSYS_ID_LEN];
+	u8	revision[4];
+	u8	slot_id[SLOT_ID_LEN];
+	u8	reserved[2];
+};
+
+struct rdac_controller {
+	u8			subsys_id[SUBSYS_ID_LEN];
+	u8			slot_id[SLOT_ID_LEN];
+	int			use_10_ms;
+	struct kref		kref;
+	struct list_head	node; /* list of all controllers */
+	spinlock_t		lock;
+	int			submitted;
+	struct list_head	cmd_list; /* list of commands to be submitted */
+	union			{
+		struct rdac_pg_legacy legacy;
+		struct rdac_pg_expanded expanded;
+	} mode_select;
+};
+struct c8_inquiry {
+	u8	peripheral_info;
+	u8	page_code; /* 0xC8 */
+	u8	reserved1;
+	u8	page_len;
+	u8	page_id[4]; /* "edid" */
+	u8	reserved2[3];
+	u8	vol_uniq_id_len;
+	u8	vol_uniq_id[16];
+	u8	vol_user_label_len;
+	u8	vol_user_label[60];
+	u8	array_uniq_id_len;
+	u8	array_unique_id[16];
+	u8	array_user_label_len;
+	u8	array_user_label[60];
+	u8	lun[8];
+};
+
+struct c2_inquiry {
+	u8	peripheral_info;
+	u8	page_code;	/* 0xC2 */
+	u8	reserved1;
+	u8	page_len;
+	u8	page_id[4];	/* "swr4" */
+	u8	sw_version[3];
+	u8	sw_date[3];
+	u8	features_enabled;
+	u8	max_lun_supported;
+	u8	partitions[239]; /* Total allocation length should be 0xFF */
+};
+
+struct rdac_handler {
+	struct list_head	entry; /* list waiting to submit MODE SELECT */
+	unsigned		timeout;
+	struct rdac_controller	*ctlr;
+#define UNINITIALIZED_LUN	(1 << 8)
+	unsigned		lun;
+	unsigned char		sense[SCSI_SENSE_BUFFERSIZE];
+	struct dm_path		*path;
+	struct work_struct	work;
+#define	SEND_C2_INQUIRY		1
+#define	SEND_C4_INQUIRY		2
+#define	SEND_C8_INQUIRY		3
+#define	SEND_C9_INQUIRY		4
+#define	SEND_MODE_SELECT	5
+	int			cmd_to_send;
+	union			{
+		struct c2_inquiry c2;
+		struct c4_inquiry c4;
+		struct c8_inquiry c8;
+		struct c9_inquiry c9;
+	} inq;
+};
+
+static LIST_HEAD(ctlr_list);
+static DEFINE_SPINLOCK(list_lock);
+static struct workqueue_struct *rdac_wkqd;
+
+static inline int had_failures(struct request *req, int error)
+{
+	return (error || host_byte(req->errors) != DID_OK ||
+			msg_byte(req->errors) != COMMAND_COMPLETE);
+}
+
+static void rdac_resubmit_all(struct rdac_handler *h)
+{
+	struct rdac_controller *ctlr = h->ctlr;
+	struct rdac_handler *tmp, *h1;
+
+	spin_lock(&ctlr->lock);
+	list_for_each_entry_safe(h1, tmp, &ctlr->cmd_list, entry) {
+		h1->cmd_to_send = SEND_C9_INQUIRY;
+		queue_work(rdac_wkqd, &h1->work);
+		list_del(&h1->entry);
+	}
+	ctlr->submitted = 0;
+	spin_unlock(&ctlr->lock);
+}
+
+static void mode_select_endio(struct request *req, int error)
+{
+	struct rdac_handler *h = req->end_io_data;
+	struct scsi_sense_hdr sense_hdr;
+	int sense = 0, fail = 0;
+
+	if (had_failures(req, error)) {
+		fail = 1;
+		goto failed;
+	}
+
+	if (status_byte(req->errors) == CHECK_CONDITION) {
+		scsi_normalize_sense(req->sense, SCSI_SENSE_BUFFERSIZE,
+				&sense_hdr);
+		sense = (sense_hdr.sense_key << 16) | (sense_hdr.asc << 8) |
+				sense_hdr.ascq;
+		/* If it is retryable failure, submit the c9 inquiry again */
+		if (sense == 0x59136 || sense == 0x68b02 || sense == 0xb8b02 ||
+		    sense == 0x62900) {
+			/* 0x59136    - Command lock contention
+			 * 0x[6b]8b02 - Quiesense in progress or achieved
+			 * 0x62900    - Power On, Reset, or Bus Device Reset
+			 */
+			h->cmd_to_send = SEND_C9_INQUIRY;
+			queue_work(rdac_wkqd, &h->work);
+			goto done;
+		}
+		if (sense)
+			DMINFO("MODE_SELECT failed on %s with sense 0x%x",
+						h->path->dev->name, sense);
+ 	}
+failed:
+	if (fail || sense)
+		dm_pg_init_complete(h->path, MP_FAIL_PATH);
+	else
+		dm_pg_init_complete(h->path, 0);
+
+done:
+	rdac_resubmit_all(h);
+	__blk_put_request(req->q, req);
+}
+
+static struct request *get_rdac_req(struct rdac_handler *h,
+			void *buffer, unsigned buflen, int rw)
+{
+	struct request *rq;
+	struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+	rq = blk_get_request(q, rw, GFP_KERNEL);
+
+	if (!rq) {
+		DMINFO("get_rdac_req: blk_get_request failed");
+		return NULL;
+	}
+
+	if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_KERNEL)) {
+		blk_put_request(rq);
+		DMINFO("get_rdac_req: blk_rq_map_kern failed");
+		return NULL;
+	}
+
+ 	memset(&rq->cmd, 0, BLK_MAX_CDB);
+	rq->sense = h->sense;
+	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	rq->sense_len = 0;
+
+	rq->end_io_data = h;
+	rq->timeout = h->timeout;
+	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+	rq->cmd_flags = REQ_FAILFAST | REQ_NOMERGE;
+	return rq;
+}
+
+static struct request *rdac_failover_get(struct rdac_handler *h)
+{
+	struct request *rq;
+	struct rdac_mode_common *common;
+	unsigned data_size;
+
+	if (h->ctlr->use_10_ms) {
+		struct rdac_pg_expanded *rdac_pg;
+
+		data_size = sizeof(struct rdac_pg_expanded);
+		rdac_pg = &h->ctlr->mode_select.expanded;
+		memset(rdac_pg, 0, data_size);
+		common = &rdac_pg->common;
+		rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40;
+		rdac_pg->subpage_code = 0x1;
+		rdac_pg->page_len[0] = 0x01;
+		rdac_pg->page_len[1] = 0x28;
+		rdac_pg->lun_table[h->lun] = 0x81;
+	} else {
+		struct rdac_pg_legacy *rdac_pg;
+
+		data_size = sizeof(struct rdac_pg_legacy);
+		rdac_pg = &h->ctlr->mode_select.legacy;
+		memset(rdac_pg, 0, data_size);
+		common = &rdac_pg->common;
+		rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
+		rdac_pg->page_len = 0x68;
+		rdac_pg->lun_table[h->lun] = 0x81;
+	}
+	common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;
+	common->quiescence_timeout = RDAC_QUIESCENCE_TIME;
+	common->rdac_options = RDAC_FORCED_QUIESENCE;
+
+	/* get request for block layer packet command */
+	rq = get_rdac_req(h, &h->ctlr->mode_select, data_size, WRITE);
+	if (!rq) {
+		DMERR("rdac_failover_get: no rq");
+		return NULL;
+	}
+
+	/* Prepare the command. */
+	if (h->ctlr->use_10_ms) {
+		rq->cmd[0] = MODE_SELECT_10;
+		rq->cmd[7] = data_size >> 8;
+		rq->cmd[8] = data_size & 0xff;
+	} else {
+		rq->cmd[0] = MODE_SELECT;
+		rq->cmd[4] = data_size;
+	}
+	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+
+	return rq;
+}
+
+/* Acquires h->ctlr->lock */
+static void submit_mode_select(struct rdac_handler *h)
+{
+	struct request *rq;
+	struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+	spin_lock(&h->ctlr->lock);
+	if (h->ctlr->submitted) {
+		list_add(&h->entry, &h->ctlr->cmd_list);
+		goto drop_lock;
+	}
+
+	if (!q) {
+		DMINFO("submit_mode_select: no queue");
+		goto fail_path;
+	}
+
+	rq = rdac_failover_get(h);
+	if (!rq) {
+		DMERR("submit_mode_select: no rq");
+		goto fail_path;
+	}
+
+	DMINFO("queueing MODE_SELECT command on %s", h->path->dev->name);
+
+	blk_execute_rq_nowait(q, NULL, rq, 1, mode_select_endio);
+	h->ctlr->submitted = 1;
+	goto drop_lock;
+fail_path:
+	dm_pg_init_complete(h->path, MP_FAIL_PATH);
+drop_lock:
+	spin_unlock(&h->ctlr->lock);
+}
+
+static void release_ctlr(struct kref *kref)
+{
+	struct rdac_controller *ctlr;
+	ctlr = container_of(kref, struct rdac_controller, kref);
+
+	spin_lock(&list_lock);
+	list_del(&ctlr->node);
+	spin_unlock(&list_lock);
+	kfree(ctlr);
+}
+
+static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id)
+{
+	struct rdac_controller *ctlr, *tmp;
+
+	spin_lock(&list_lock);
+
+	list_for_each_entry(tmp, &ctlr_list, node) {
+		if ((memcmp(tmp->subsys_id, subsys_id, SUBSYS_ID_LEN) == 0) &&
+			  (memcmp(tmp->slot_id, slot_id, SLOT_ID_LEN) == 0)) {
+			kref_get(&tmp->kref);
+			spin_unlock(&list_lock);
+			return tmp;
+		}
+	}
+	ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC);
+	if (!ctlr)
+		goto done;
+
+	/* initialize fields of controller */
+	memcpy(ctlr->subsys_id, subsys_id, SUBSYS_ID_LEN);
+	memcpy(ctlr->slot_id, slot_id, SLOT_ID_LEN);
+	kref_init(&ctlr->kref);
+	spin_lock_init(&ctlr->lock);
+	ctlr->submitted = 0;
+	ctlr->use_10_ms = -1;
+	INIT_LIST_HEAD(&ctlr->cmd_list);
+	list_add(&ctlr->node, &ctlr_list);
+done:
+	spin_unlock(&list_lock);
+	return ctlr;
+}
+
+static void c4_endio(struct request *req, int error)
+{
+	struct rdac_handler *h = req->end_io_data;
+	struct c4_inquiry *sp;
+
+	if (had_failures(req, error)) {
+		dm_pg_init_complete(h->path, MP_FAIL_PATH);
+		goto done;
+	}
+
+	sp = &h->inq.c4;
+
+	h->ctlr = get_controller(sp->subsys_id, sp->slot_id);
+
+	if (h->ctlr) {
+		h->cmd_to_send = SEND_C9_INQUIRY;
+		queue_work(rdac_wkqd, &h->work);
+	} else
+		dm_pg_init_complete(h->path, MP_FAIL_PATH);
+done:
+	__blk_put_request(req->q, req);
+}
+
+static void c2_endio(struct request *req, int error)
+{
+	struct rdac_handler *h = req->end_io_data;
+	struct c2_inquiry *sp;
+
+	if (had_failures(req, error)) {
+		dm_pg_init_complete(h->path, MP_FAIL_PATH);
+		goto done;
+	}
+
+	sp = &h->inq.c2;
+
+	/* If more than MODE6_MAX_LUN luns are supported, use mode select 10 */
+	if (sp->max_lun_supported >= MODE6_MAX_LUN)
+		h->ctlr->use_10_ms = 1;
+	else
+		h->ctlr->use_10_ms = 0;
+
+	h->cmd_to_send = SEND_MODE_SELECT;
+	queue_work(rdac_wkqd, &h->work);
+done:
+	__blk_put_request(req->q, req);
+}
+
+static void c9_endio(struct request *req, int error)
+{
+	struct rdac_handler *h = req->end_io_data;
+	struct c9_inquiry *sp;
+
+	if (had_failures(req, error)) {
+		dm_pg_init_complete(h->path, MP_FAIL_PATH);
+		goto done;
+	}
+
+	/* We need to look at the sense keys here to take clear action.
+	 * For now simple logic: If the host is in AVT mode or if controller
+	 * owns the lun, return dm_pg_init_complete(), otherwise submit
+	 * MODE SELECT.
+	 */
+	sp = &h->inq.c9;
+
+	/* If in AVT mode, return success */
+	if ((sp->avte_cvp >> 7) == 0x1) {
+		dm_pg_init_complete(h->path, 0);
+		goto done;
+	}
+
+	/* If the controller on this path owns the LUN, return success */
+	if (sp->avte_cvp & 0x1) {
+		dm_pg_init_complete(h->path, 0);
+		goto done;
+	}
+
+	if (h->ctlr) {
+		if (h->ctlr->use_10_ms == -1)
+			h->cmd_to_send = SEND_C2_INQUIRY;
+		else
+			h->cmd_to_send = SEND_MODE_SELECT;
+	} else
+		h->cmd_to_send = SEND_C4_INQUIRY;
+	queue_work(rdac_wkqd, &h->work);
+done:
+	__blk_put_request(req->q, req);
+}
+
+static void c8_endio(struct request *req, int error)
+{
+	struct rdac_handler *h = req->end_io_data;
+	struct c8_inquiry *sp;
+
+	if (had_failures(req, error)) {
+		dm_pg_init_complete(h->path, MP_FAIL_PATH);
+		goto done;
+	}
+
+	/* We need to look at the sense keys here to take clear action.
+	 * For now simple logic: Get the lun from the inquiry page.
+	 */
+	sp = &h->inq.c8;
+	h->lun = sp->lun[7]; /* currently it uses only one byte */
+	h->cmd_to_send = SEND_C9_INQUIRY;
+	queue_work(rdac_wkqd, &h->work);
+done:
+	__blk_put_request(req->q, req);
+}
+
+static void submit_inquiry(struct rdac_handler *h, int page_code,
+		unsigned int len, rq_end_io_fn endio)
+{
+	struct request *rq;
+	struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+	if (!q)
+		goto fail_path;
+
+	rq = get_rdac_req(h, &h->inq, len, READ);
+	if (!rq)
+		goto fail_path;
+
+	/* Prepare the command. */
+	rq->cmd[0] = INQUIRY;
+	rq->cmd[1] = 1;
+	rq->cmd[2] = page_code;
+	rq->cmd[4] = len;
+	rq->cmd_len = COMMAND_SIZE(INQUIRY);
+	blk_execute_rq_nowait(q, NULL, rq, 1, endio);
+	return;
+
+fail_path:
+	dm_pg_init_complete(h->path, MP_FAIL_PATH);
+}
+
+static void service_wkq(struct work_struct *work)
+{
+	struct rdac_handler *h = container_of(work, struct rdac_handler, work);
+
+	switch (h->cmd_to_send) {
+	case SEND_C2_INQUIRY:
+		submit_inquiry(h, 0xC2, sizeof(struct c2_inquiry), c2_endio);
+		break;
+	case SEND_C4_INQUIRY:
+		submit_inquiry(h, 0xC4, sizeof(struct c4_inquiry), c4_endio);
+		break;
+	case SEND_C8_INQUIRY:
+		submit_inquiry(h, 0xC8, sizeof(struct c8_inquiry), c8_endio);
+		break;
+	case SEND_C9_INQUIRY:
+		submit_inquiry(h, 0xC9, sizeof(struct c9_inquiry), c9_endio);
+		break;
+	case SEND_MODE_SELECT:
+		submit_mode_select(h);
+		break;
+	default:
+		BUG();
+	}
+}
+/*
+ * only support subpage2c until we confirm that this is just a matter of
+ * of updating firmware or not, and RDAC (basic AVT works already) for now
+ * but we can add these in in when we get time and testers
+ */
+static int rdac_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+	struct rdac_handler *h;
+	unsigned timeout;
+
+	if (argc == 0) {
+		/* No arguments: use defaults */
+		timeout = RDAC_FAILOVER_TIMEOUT;
+	} else if (argc != 1) {
+		DMWARN("incorrect number of arguments");
+		return -EINVAL;
+	} else {
+		if (sscanf(argv[1], "%u", &timeout) != 1) {
+			DMWARN("invalid timeout value");
+			return -EINVAL;
+		}
+	}
+
+	h = kzalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+
+	hwh->context = h;
+	h->timeout = timeout;
+	h->lun = UNINITIALIZED_LUN;
+	INIT_WORK(&h->work, service_wkq);
+	DMWARN("using RDAC command with timeout %u", h->timeout);
+
+	return 0;
+}
+
+static void rdac_destroy(struct hw_handler *hwh)
+{
+	struct rdac_handler *h = hwh->context;
+
+	if (h->ctlr)
+		kref_put(&h->ctlr->kref, release_ctlr);
+	kfree(h);
+	hwh->context = NULL;
+}
+
+static unsigned rdac_error(struct hw_handler *hwh, struct bio *bio)
+{
+	/* Try default handler */
+	return dm_scsi_err_handler(hwh, bio);
+}
+
+static void rdac_pg_init(struct hw_handler *hwh, unsigned bypassed,
+			struct dm_path *path)
+{
+	struct rdac_handler *h = hwh->context;
+
+	h->path = path;
+	switch (h->lun) {
+	case UNINITIALIZED_LUN:
+		submit_inquiry(h, 0xC8, sizeof(struct c8_inquiry), c8_endio);
+		break;
+	default:
+		submit_inquiry(h, 0xC9, sizeof(struct c9_inquiry), c9_endio);
+	}
+}
+
+static struct hw_handler_type rdac_handler = {
+	.name = RDAC_DM_HWH_NAME,
+	.module = THIS_MODULE,
+	.create = rdac_create,
+	.destroy = rdac_destroy,
+	.pg_init = rdac_pg_init,
+	.error = rdac_error,
+};
+
+static int __init rdac_init(void)
+{
+	int r = dm_register_hw_handler(&rdac_handler);
+
+	if (r < 0) {
+		DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r);
+		return r;
+	}
+
+	rdac_wkqd = create_singlethread_workqueue("rdac_wkqd");
+	if (!rdac_wkqd) {
+		DMERR("Failed to create workqueue rdac_wkqd.");
+		dm_unregister_hw_handler(&rdac_handler);
+		return -ENOMEM;
+	}
+
+	DMINFO("%s: version %s loaded", RDAC_DM_HWH_NAME, RDAC_DM_HWH_VER);
+	return 0;
+}
+
+static void __exit rdac_exit(void)
+{
+	int r = dm_unregister_hw_handler(&rdac_handler);
+
+	destroy_workqueue(rdac_wkqd);
+	if (r < 0)
+		DMERR("%s: unregister failed %d", RDAC_DM_HWH_NAME, r);
+}
+
+module_init(rdac_init);
+module_exit(rdac_exit);
+
+MODULE_DESCRIPTION("DM Multipath LSI/Engenio RDAC support");
+MODULE_AUTHOR("Mike Christie, Chandra Seetharaman");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RDAC_DM_HWH_VER);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index de54b39..d6ca9d0 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -83,7 +83,7 @@
 	struct work_struct trigger_event;
 
 	/*
-	 * We must use a mempool of mpath_io structs so that we
+	 * We must use a mempool of dm_mpath_io structs so that we
 	 * can resubmit bios on error.
 	 */
 	mempool_t *mpio_pool;
@@ -92,7 +92,7 @@
 /*
  * Context information attached to each bio we process.
  */
-struct mpath_io {
+struct dm_mpath_io {
 	struct pgpath *pgpath;
 	struct dm_bio_details details;
 };
@@ -122,7 +122,7 @@
 	return pgpath;
 }
 
-static inline void free_pgpath(struct pgpath *pgpath)
+static void free_pgpath(struct pgpath *pgpath)
 {
 	kfree(pgpath);
 }
@@ -299,8 +299,8 @@
 		dm_noflush_suspending(m->ti));
 }
 
-static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
-		  unsigned was_queued)
+static int map_io(struct multipath *m, struct bio *bio,
+		  struct dm_mpath_io *mpio, unsigned was_queued)
 {
 	int r = DM_MAPIO_REMAPPED;
 	unsigned long flags;
@@ -374,7 +374,7 @@
 	int r;
 	unsigned long flags;
 	struct bio *bio = NULL, *next;
-	struct mpath_io *mpio;
+	struct dm_mpath_io *mpio;
 	union map_info *info;
 
 	spin_lock_irqsave(&m->lock, flags);
@@ -795,12 +795,9 @@
 			 union map_info *map_context)
 {
 	int r;
-	struct mpath_io *mpio;
+	struct dm_mpath_io *mpio;
 	struct multipath *m = (struct multipath *) ti->private;
 
-	if (bio_barrier(bio))
-		return -EOPNOTSUPP;
-
 	mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
 	dm_bio_record(&mpio->details, bio);
 
@@ -1014,7 +1011,7 @@
  * end_io handling
  */
 static int do_end_io(struct multipath *m, struct bio *bio,
-		     int error, struct mpath_io *mpio)
+		     int error, struct dm_mpath_io *mpio)
 {
 	struct hw_handler *hwh = &m->hw_handler;
 	unsigned err_flags = MP_FAIL_PATH;	/* Default behavior */
@@ -1075,8 +1072,8 @@
 static int multipath_end_io(struct dm_target *ti, struct bio *bio,
 			    int error, union map_info *map_context)
 {
-	struct multipath *m = (struct multipath *) ti->private;
-	struct mpath_io *mpio = (struct mpath_io *) map_context->ptr;
+	struct multipath *m = ti->private;
+	struct dm_mpath_io *mpio = map_context->ptr;
 	struct pgpath *pgpath = mpio->pgpath;
 	struct path_selector *ps;
 	int r;
@@ -1346,22 +1343,20 @@
 	int r;
 
 	/* allocate a slab for the dm_ios */
-	_mpio_cache = kmem_cache_create("dm_mpath", sizeof(struct mpath_io),
-					0, 0, NULL, NULL);
+	_mpio_cache = KMEM_CACHE(dm_mpath_io, 0);
 	if (!_mpio_cache)
 		return -ENOMEM;
 
 	r = dm_register_target(&multipath_target);
 	if (r < 0) {
-		DMERR("%s: register failed %d", multipath_target.name, r);
+		DMERR("register failed %d", r);
 		kmem_cache_destroy(_mpio_cache);
 		return -EINVAL;
 	}
 
 	kmultipathd = create_workqueue("kmpathd");
 	if (!kmultipathd) {
-		DMERR("%s: failed to create workqueue kmpathd",
-				multipath_target.name);
+		DMERR("failed to create workqueue kmpathd");
 		dm_unregister_target(&multipath_target);
 		kmem_cache_destroy(_mpio_cache);
 		return -ENOMEM;
@@ -1382,8 +1377,7 @@
 
 	r = dm_unregister_target(&multipath_target);
 	if (r < 0)
-		DMERR("%s: target unregister failed %d",
-		      multipath_target.name, r);
+		DMERR("target unregister failed %d", r);
 	kmem_cache_destroy(_mpio_cache);
 }
 
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index ef124b7..1a876f9 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -24,6 +24,7 @@
 #define DM_IO_PAGES 64
 
 #define DM_RAID1_HANDLE_ERRORS 0x01
+#define errors_handled(p)	((p)->features & DM_RAID1_HANDLE_ERRORS)
 
 static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped);
 
@@ -85,6 +86,7 @@
 	struct list_head clean_regions;
 	struct list_head quiesced_regions;
 	struct list_head recovered_regions;
+	struct list_head failed_recovered_regions;
 };
 
 enum {
@@ -132,6 +134,7 @@
 	/* recovery */
 	region_t nr_regions;
 	int in_sync;
+	int log_failure;
 
 	struct mirror *default_mirror;	/* Default mirror */
 
@@ -204,6 +207,7 @@
 	INIT_LIST_HEAD(&rh->clean_regions);
 	INIT_LIST_HEAD(&rh->quiesced_regions);
 	INIT_LIST_HEAD(&rh->recovered_regions);
+	INIT_LIST_HEAD(&rh->failed_recovered_regions);
 
 	rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
 						      sizeof(struct region));
@@ -368,6 +372,7 @@
 
 	LIST_HEAD(clean);
 	LIST_HEAD(recovered);
+	LIST_HEAD(failed_recovered);
 
 	/*
 	 * Quickly grab the lists.
@@ -378,10 +383,8 @@
 		list_splice(&rh->clean_regions, &clean);
 		INIT_LIST_HEAD(&rh->clean_regions);
 
-		list_for_each_entry (reg, &clean, list) {
-			rh->log->type->clear_region(rh->log, reg->key);
+		list_for_each_entry(reg, &clean, list)
 			list_del(&reg->hash_list);
-		}
 	}
 
 	if (!list_empty(&rh->recovered_regions)) {
@@ -391,6 +394,15 @@
 		list_for_each_entry (reg, &recovered, list)
 			list_del(&reg->hash_list);
 	}
+
+	if (!list_empty(&rh->failed_recovered_regions)) {
+		list_splice(&rh->failed_recovered_regions, &failed_recovered);
+		INIT_LIST_HEAD(&rh->failed_recovered_regions);
+
+		list_for_each_entry(reg, &failed_recovered, list)
+			list_del(&reg->hash_list);
+	}
+
 	spin_unlock(&rh->region_lock);
 	write_unlock_irq(&rh->hash_lock);
 
@@ -405,10 +417,17 @@
 		mempool_free(reg, rh->region_pool);
 	}
 
-	rh->log->type->flush(rh->log);
-
-	list_for_each_entry_safe (reg, next, &clean, list)
+	list_for_each_entry_safe(reg, next, &failed_recovered, list) {
+		complete_resync_work(reg, errors_handled(rh->ms) ? 0 : 1);
 		mempool_free(reg, rh->region_pool);
+	}
+
+	list_for_each_entry_safe(reg, next, &clean, list) {
+		rh->log->type->clear_region(rh->log, reg->key);
+		mempool_free(reg, rh->region_pool);
+	}
+
+	rh->log->type->flush(rh->log);
 }
 
 static void rh_inc(struct region_hash *rh, region_t region)
@@ -555,21 +574,25 @@
 	return reg;
 }
 
-/* FIXME: success ignored for now */
 static void rh_recovery_end(struct region *reg, int success)
 {
 	struct region_hash *rh = reg->rh;
 
 	spin_lock_irq(&rh->region_lock);
-	list_add(&reg->list, &reg->rh->recovered_regions);
+	if (success)
+		list_add(&reg->list, &reg->rh->recovered_regions);
+	else {
+		reg->state = RH_NOSYNC;
+		list_add(&reg->list, &reg->rh->failed_recovered_regions);
+	}
 	spin_unlock_irq(&rh->region_lock);
 
 	wake(rh->ms);
 }
 
-static void rh_flush(struct region_hash *rh)
+static int rh_flush(struct region_hash *rh)
 {
-	rh->log->type->flush(rh->log);
+	return rh->log->type->flush(rh->log);
 }
 
 static void rh_delay(struct region_hash *rh, struct bio *bio)
@@ -633,7 +656,14 @@
 {
 	struct region *reg = (struct region *) context;
 
-	/* FIXME: better error handling */
+	if (read_err)
+		/* Read error means the failure of default mirror. */
+		DMERR_LIMIT("Unable to read primary mirror during recovery");
+
+	if (write_err)
+		DMERR_LIMIT("Write error during recovery (error = 0x%x)",
+			    write_err);
+
 	rh_recovery_end(reg, !(read_err || write_err));
 }
 
@@ -863,12 +893,15 @@
 	 */
 	rh_inc_pending(&ms->rh, &sync);
 	rh_inc_pending(&ms->rh, &nosync);
-	rh_flush(&ms->rh);
+	ms->log_failure = rh_flush(&ms->rh) ? 1 : 0;
 
 	/*
 	 * Dispatch io.
 	 */
-	while ((bio = bio_list_pop(&sync)))
+	if (unlikely(ms->log_failure))
+		while ((bio = bio_list_pop(&sync)))
+			bio_endio(bio, bio->bi_size, -EIO);
+	else while ((bio = bio_list_pop(&sync)))
 		do_write(ms, bio);
 
 	while ((bio = bio_list_pop(&recover)))
@@ -1145,6 +1178,15 @@
 	argv += args_used;
 	argc -= args_used;
 
+	/*
+	 * Any read-balancing addition depends on the
+	 * DM_RAID1_HANDLE_ERRORS flag being present.
+	 * This is because the decision to balance depends
+	 * on the sync state of a region.  If the above
+	 * flag is not present, we ignore errors; and
+	 * the sync state may be inaccurate.
+	 */
+
 	if (argc) {
 		ti->error = "Too many mirror arguments";
 		free_context(ms, ti, ms->nr_mirrors);
@@ -1288,12 +1330,12 @@
 		for (m = 0; m < ms->nr_mirrors; m++)
 			DMEMIT("%s ", ms->mirror[m].dev->name);
 
-		DMEMIT("%llu/%llu",
+		DMEMIT("%llu/%llu 0 ",
 			(unsigned long long)ms->rh.log->type->
 				get_sync_count(ms->rh.log),
 			(unsigned long long)ms->nr_regions);
 
-		sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
+		sz += ms->rh.log->type->status(ms->rh.log, type, result+sz, maxlen-sz);
 
 		break;
 
@@ -1335,8 +1377,7 @@
 
 	r = dm_register_target(&mirror_target);
 	if (r < 0) {
-		DMERR("%s: Failed to register mirror target",
-		      mirror_target.name);
+		DMERR("Failed to register mirror target");
 		dm_dirty_log_exit();
 	}
 
@@ -1349,7 +1390,7 @@
 
 	r = dm_unregister_target(&mirror_target);
 	if (r < 0)
-		DMERR("%s: unregister failed %d", mirror_target.name, r);
+		DMERR("unregister failed %d", r);
 
 	dm_dirty_log_exit();
 }
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
index a348a97..391dfa2 100644
--- a/drivers/md/dm-round-robin.c
+++ b/drivers/md/dm-round-robin.c
@@ -205,7 +205,7 @@
 	int r = dm_unregister_path_selector(&rr_ps);
 
 	if (r < 0)
-		DMERR("round-robin: unregister failed %d", r);
+		DMERR("unregister failed %d", r);
 }
 
 module_init(dm_rr_init);
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 0821a2b..83ddbfe 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -42,8 +42,8 @@
 static struct workqueue_struct *ksnapd;
 static void flush_queued_bios(struct work_struct *work);
 
-struct pending_exception {
-	struct exception e;
+struct dm_snap_pending_exception {
+	struct dm_snap_exception e;
 
 	/*
 	 * Origin buffers waiting for this to complete are held
@@ -63,7 +63,7 @@
 	 * group of pending_exceptions.  It is always last to get freed.
 	 * These fields get set up when writing to the origin.
 	 */
-	struct pending_exception *primary_pe;
+	struct dm_snap_pending_exception *primary_pe;
 
 	/*
 	 * Number of pending_exceptions processing this chunk.
@@ -137,7 +137,7 @@
 	kfree(_origins);
 }
 
-static inline unsigned int origin_hash(struct block_device *bdev)
+static unsigned origin_hash(struct block_device *bdev)
 {
 	return bdev->bd_dev & ORIGIN_MASK;
 }
@@ -231,7 +231,7 @@
 static void exit_exception_table(struct exception_table *et, struct kmem_cache *mem)
 {
 	struct list_head *slot;
-	struct exception *ex, *next;
+	struct dm_snap_exception *ex, *next;
 	int i, size;
 
 	size = et->hash_mask + 1;
@@ -245,18 +245,19 @@
 	vfree(et->table);
 }
 
-static inline uint32_t exception_hash(struct exception_table *et, chunk_t chunk)
+static uint32_t exception_hash(struct exception_table *et, chunk_t chunk)
 {
 	return chunk & et->hash_mask;
 }
 
-static void insert_exception(struct exception_table *eh, struct exception *e)
+static void insert_exception(struct exception_table *eh,
+			     struct dm_snap_exception *e)
 {
 	struct list_head *l = &eh->table[exception_hash(eh, e->old_chunk)];
 	list_add(&e->hash_list, l);
 }
 
-static inline void remove_exception(struct exception *e)
+static void remove_exception(struct dm_snap_exception *e)
 {
 	list_del(&e->hash_list);
 }
@@ -265,11 +266,11 @@
  * Return the exception data for a sector, or NULL if not
  * remapped.
  */
-static struct exception *lookup_exception(struct exception_table *et,
-					  chunk_t chunk)
+static struct dm_snap_exception *lookup_exception(struct exception_table *et,
+						  chunk_t chunk)
 {
 	struct list_head *slot;
-	struct exception *e;
+	struct dm_snap_exception *e;
 
 	slot = &et->table[exception_hash(et, chunk)];
 	list_for_each_entry (e, slot, hash_list)
@@ -279,9 +280,9 @@
 	return NULL;
 }
 
-static inline struct exception *alloc_exception(void)
+static struct dm_snap_exception *alloc_exception(void)
 {
-	struct exception *e;
+	struct dm_snap_exception *e;
 
 	e = kmem_cache_alloc(exception_cache, GFP_NOIO);
 	if (!e)
@@ -290,24 +291,24 @@
 	return e;
 }
 
-static inline void free_exception(struct exception *e)
+static void free_exception(struct dm_snap_exception *e)
 {
 	kmem_cache_free(exception_cache, e);
 }
 
-static inline struct pending_exception *alloc_pending_exception(void)
+static struct dm_snap_pending_exception *alloc_pending_exception(void)
 {
 	return mempool_alloc(pending_pool, GFP_NOIO);
 }
 
-static inline void free_pending_exception(struct pending_exception *pe)
+static void free_pending_exception(struct dm_snap_pending_exception *pe)
 {
 	mempool_free(pe, pending_pool);
 }
 
 int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new)
 {
-	struct exception *e;
+	struct dm_snap_exception *e;
 
 	e = alloc_exception();
 	if (!e)
@@ -334,7 +335,7 @@
 /*
  * Rounds a number down to a power of 2.
  */
-static inline uint32_t round_down(uint32_t n)
+static uint32_t round_down(uint32_t n)
 {
 	while (n & (n - 1))
 		n &= (n - 1);
@@ -384,7 +385,7 @@
  * Round a number up to the nearest 'size' boundary.  size must
  * be a power of 2.
  */
-static inline ulong round_up(ulong n, ulong size)
+static ulong round_up(ulong n, ulong size)
 {
 	size--;
 	return (n + size) & ~size;
@@ -522,9 +523,12 @@
 
 	/* Metadata must only be loaded into one table at once */
 	r = s->store.read_metadata(&s->store);
-	if (r) {
+	if (r < 0) {
 		ti->error = "Failed to read snapshot metadata";
 		goto bad6;
+	} else if (r > 0) {
+		s->valid = 0;
+		DMWARN("Snapshot is marked invalid.");
 	}
 
 	bio_list_init(&s->queued_bios);
@@ -577,7 +581,7 @@
 
 static void snapshot_dtr(struct dm_target *ti)
 {
-	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+	struct dm_snapshot *s = ti->private;
 
 	flush_workqueue(ksnapd);
 
@@ -655,14 +659,14 @@
 	dm_table_event(s->table);
 }
 
-static void get_pending_exception(struct pending_exception *pe)
+static void get_pending_exception(struct dm_snap_pending_exception *pe)
 {
 	atomic_inc(&pe->ref_count);
 }
 
-static struct bio *put_pending_exception(struct pending_exception *pe)
+static struct bio *put_pending_exception(struct dm_snap_pending_exception *pe)
 {
-	struct pending_exception *primary_pe;
+	struct dm_snap_pending_exception *primary_pe;
 	struct bio *origin_bios = NULL;
 
 	primary_pe = pe->primary_pe;
@@ -692,9 +696,9 @@
 	return origin_bios;
 }
 
-static void pending_complete(struct pending_exception *pe, int success)
+static void pending_complete(struct dm_snap_pending_exception *pe, int success)
 {
-	struct exception *e;
+	struct dm_snap_exception *e;
 	struct dm_snapshot *s = pe->snap;
 	struct bio *origin_bios = NULL;
 	struct bio *snapshot_bios = NULL;
@@ -748,7 +752,8 @@
 
 static void commit_callback(void *context, int success)
 {
-	struct pending_exception *pe = (struct pending_exception *) context;
+	struct dm_snap_pending_exception *pe = context;
+
 	pending_complete(pe, success);
 }
 
@@ -758,7 +763,7 @@
  */
 static void copy_callback(int read_err, unsigned int write_err, void *context)
 {
-	struct pending_exception *pe = (struct pending_exception *) context;
+	struct dm_snap_pending_exception *pe = context;
 	struct dm_snapshot *s = pe->snap;
 
 	if (read_err || write_err)
@@ -773,7 +778,7 @@
 /*
  * Dispatches the copy operation to kcopyd.
  */
-static void start_copy(struct pending_exception *pe)
+static void start_copy(struct dm_snap_pending_exception *pe)
 {
 	struct dm_snapshot *s = pe->snap;
 	struct io_region src, dest;
@@ -803,11 +808,11 @@
  * NOTE: a write lock must be held on snap->lock before calling
  * this.
  */
-static struct pending_exception *
+static struct dm_snap_pending_exception *
 __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
 {
-	struct exception *e;
-	struct pending_exception *pe;
+	struct dm_snap_exception *e;
+	struct dm_snap_pending_exception *pe;
 	chunk_t chunk = sector_to_chunk(s, bio->bi_sector);
 
 	/*
@@ -816,7 +821,7 @@
 	e = lookup_exception(&s->pending, chunk);
 	if (e) {
 		/* cast the exception to a pending exception */
-		pe = container_of(e, struct pending_exception, e);
+		pe = container_of(e, struct dm_snap_pending_exception, e);
 		goto out;
 	}
 
@@ -836,7 +841,7 @@
 	e = lookup_exception(&s->pending, chunk);
 	if (e) {
 		free_pending_exception(pe);
-		pe = container_of(e, struct pending_exception, e);
+		pe = container_of(e, struct dm_snap_pending_exception, e);
 		goto out;
 	}
 
@@ -860,8 +865,8 @@
 	return pe;
 }
 
-static inline void remap_exception(struct dm_snapshot *s, struct exception *e,
-				   struct bio *bio)
+static void remap_exception(struct dm_snapshot *s, struct dm_snap_exception *e,
+			    struct bio *bio)
 {
 	bio->bi_bdev = s->cow->bdev;
 	bio->bi_sector = chunk_to_sector(s, e->new_chunk) +
@@ -871,11 +876,11 @@
 static int snapshot_map(struct dm_target *ti, struct bio *bio,
 			union map_info *map_context)
 {
-	struct exception *e;
-	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+	struct dm_snap_exception *e;
+	struct dm_snapshot *s = ti->private;
 	int r = DM_MAPIO_REMAPPED;
 	chunk_t chunk;
-	struct pending_exception *pe = NULL;
+	struct dm_snap_pending_exception *pe = NULL;
 
 	chunk = sector_to_chunk(s, bio->bi_sector);
 
@@ -884,9 +889,6 @@
 	if (!s->valid)
 		return -EIO;
 
-	if (unlikely(bio_barrier(bio)))
-		return -EOPNOTSUPP;
-
 	/* FIXME: should only take write lock if we need
 	 * to copy an exception */
 	down_write(&s->lock);
@@ -945,7 +947,7 @@
 
 static void snapshot_resume(struct dm_target *ti)
 {
-	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+	struct dm_snapshot *s = ti->private;
 
 	down_write(&s->lock);
 	s->active = 1;
@@ -955,7 +957,7 @@
 static int snapshot_status(struct dm_target *ti, status_type_t type,
 			   char *result, unsigned int maxlen)
 {
-	struct dm_snapshot *snap = (struct dm_snapshot *) ti->private;
+	struct dm_snapshot *snap = ti->private;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -999,8 +1001,8 @@
 {
 	int r = DM_MAPIO_REMAPPED, first = 0;
 	struct dm_snapshot *snap;
-	struct exception *e;
-	struct pending_exception *pe, *next_pe, *primary_pe = NULL;
+	struct dm_snap_exception *e;
+	struct dm_snap_pending_exception *pe, *next_pe, *primary_pe = NULL;
 	chunk_t chunk;
 	LIST_HEAD(pe_queue);
 
@@ -1147,19 +1149,16 @@
 
 static void origin_dtr(struct dm_target *ti)
 {
-	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	struct dm_dev *dev = ti->private;
 	dm_put_device(ti, dev);
 }
 
 static int origin_map(struct dm_target *ti, struct bio *bio,
 		      union map_info *map_context)
 {
-	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	struct dm_dev *dev = ti->private;
 	bio->bi_bdev = dev->bdev;
 
-	if (unlikely(bio_barrier(bio)))
-		return -EOPNOTSUPP;
-
 	/* Only tell snapshots if this is a write */
 	return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
 }
@@ -1172,7 +1171,7 @@
  */
 static void origin_resume(struct dm_target *ti)
 {
-	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	struct dm_dev *dev = ti->private;
 	struct dm_snapshot *snap;
 	struct origin *o;
 	chunk_t chunk_size = 0;
@@ -1190,7 +1189,7 @@
 static int origin_status(struct dm_target *ti, status_type_t type, char *result,
 			 unsigned int maxlen)
 {
-	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	struct dm_dev *dev = ti->private;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -1249,21 +1248,14 @@
 		goto bad2;
 	}
 
-	exception_cache = kmem_cache_create("dm-snapshot-ex",
-					    sizeof(struct exception),
-					    __alignof__(struct exception),
-					    0, NULL, NULL);
+	exception_cache = KMEM_CACHE(dm_snap_exception, 0);
 	if (!exception_cache) {
 		DMERR("Couldn't create exception cache.");
 		r = -ENOMEM;
 		goto bad3;
 	}
 
-	pending_cache =
-	    kmem_cache_create("dm-snapshot-in",
-			      sizeof(struct pending_exception),
-			      __alignof__(struct pending_exception),
-			      0, NULL, NULL);
+	pending_cache = KMEM_CACHE(dm_snap_pending_exception, 0);
 	if (!pending_cache) {
 		DMERR("Couldn't create pending cache.");
 		r = -ENOMEM;
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 15fa2ae..650e0f1 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -30,7 +30,7 @@
  * An exception is used where an old chunk of data has been
  * replaced by a new one.
  */
-struct exception {
+struct dm_snap_exception {
 	struct list_head hash_list;
 
 	chunk_t old_chunk;
@@ -58,13 +58,13 @@
 	 * Find somewhere to store the next exception.
 	 */
 	int (*prepare_exception) (struct exception_store *store,
-				  struct exception *e);
+				  struct dm_snap_exception *e);
 
 	/*
 	 * Update the metadata with this exception.
 	 */
 	void (*commit_exception) (struct exception_store *store,
-				  struct exception *e,
+				  struct dm_snap_exception *e,
 				  void (*callback) (void *, int success),
 				  void *callback_context);
 
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 2717a35..846614e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -45,7 +45,7 @@
  * One of these is allocated per target within a bio.  Hopefully
  * this will be simplified out one day.
  */
-struct target_io {
+struct dm_target_io {
 	struct dm_io *io;
 	struct dm_target *ti;
 	union map_info info;
@@ -54,7 +54,7 @@
 union map_info *dm_get_mapinfo(struct bio *bio)
 {
 	if (bio && bio->bi_private)
-		return &((struct target_io *)bio->bi_private)->info;
+		return &((struct dm_target_io *)bio->bi_private)->info;
 	return NULL;
 }
 
@@ -132,14 +132,12 @@
 	int r;
 
 	/* allocate a slab for the dm_ios */
-	_io_cache = kmem_cache_create("dm_io",
-				      sizeof(struct dm_io), 0, 0, NULL, NULL);
+	_io_cache = KMEM_CACHE(dm_io, 0);
 	if (!_io_cache)
 		return -ENOMEM;
 
 	/* allocate a slab for the target ios */
-	_tio_cache = kmem_cache_create("dm_tio", sizeof(struct target_io),
-				       0, 0, NULL, NULL);
+	_tio_cache = KMEM_CACHE(dm_target_io, 0);
 	if (!_tio_cache) {
 		kmem_cache_destroy(_io_cache);
 		return -ENOMEM;
@@ -163,9 +161,7 @@
 {
 	kmem_cache_destroy(_tio_cache);
 	kmem_cache_destroy(_io_cache);
-
-	if (unregister_blkdev(_major, _name) < 0)
-		DMERR("unregister_blkdev failed");
+	unregister_blkdev(_major, _name);
 
 	_major = 0;
 
@@ -325,22 +321,22 @@
 	return r;
 }
 
-static inline struct dm_io *alloc_io(struct mapped_device *md)
+static struct dm_io *alloc_io(struct mapped_device *md)
 {
 	return mempool_alloc(md->io_pool, GFP_NOIO);
 }
 
-static inline void free_io(struct mapped_device *md, struct dm_io *io)
+static void free_io(struct mapped_device *md, struct dm_io *io)
 {
 	mempool_free(io, md->io_pool);
 }
 
-static inline struct target_io *alloc_tio(struct mapped_device *md)
+static struct dm_target_io *alloc_tio(struct mapped_device *md)
 {
 	return mempool_alloc(md->tio_pool, GFP_NOIO);
 }
 
-static inline void free_tio(struct mapped_device *md, struct target_io *tio)
+static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
 {
 	mempool_free(tio, md->tio_pool);
 }
@@ -498,7 +494,7 @@
 static int clone_endio(struct bio *bio, unsigned int done, int error)
 {
 	int r = 0;
-	struct target_io *tio = bio->bi_private;
+	struct dm_target_io *tio = bio->bi_private;
 	struct mapped_device *md = tio->io->md;
 	dm_endio_fn endio = tio->ti->type->end_io;
 
@@ -558,7 +554,7 @@
 }
 
 static void __map_bio(struct dm_target *ti, struct bio *clone,
-		      struct target_io *tio)
+		      struct dm_target_io *tio)
 {
 	int r;
 	sector_t sector;
@@ -672,7 +668,7 @@
 	struct bio *clone, *bio = ci->bio;
 	struct dm_target *ti = dm_table_find_target(ci->map, ci->sector);
 	sector_t len = 0, max = max_io_len(ci->md, ci->sector, ti);
-	struct target_io *tio;
+	struct dm_target_io *tio;
 
 	/*
 	 * Allocate a target io object.
@@ -802,6 +798,15 @@
 	int rw = bio_data_dir(bio);
 	struct mapped_device *md = q->queuedata;
 
+	/*
+	 * There is no use in forwarding any barrier request since we can't
+	 * guarantee it is (or can be) handled by the targets correctly.
+	 */
+	if (unlikely(bio_barrier(bio))) {
+		bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+		return 0;
+	}
+
 	down_read(&md->io_lock);
 
 	disk_stat_inc(dm_disk(md), ios[rw]);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 2f796b1..462ee65 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -18,13 +18,45 @@
 
 #define DM_NAME "device-mapper"
 
-#define DMERR(f, arg...) printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
-#define DMWARN(f, arg...) printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
-#define DMINFO(f, arg...) printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMERR(f, arg...) \
+	printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMERR_LIMIT(f, arg...) \
+	do { \
+		if (printk_ratelimit())	\
+			printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
+			       f "\n", ## arg); \
+	} while (0)
+
+#define DMWARN(f, arg...) \
+	printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMWARN_LIMIT(f, arg...) \
+	do { \
+		if (printk_ratelimit())	\
+			printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
+			       f "\n", ## arg); \
+	} while (0)
+
+#define DMINFO(f, arg...) \
+	printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMINFO_LIMIT(f, arg...) \
+	do { \
+		if (printk_ratelimit())	\
+			printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
+			       "\n", ## arg); \
+	} while (0)
+
 #ifdef CONFIG_DM_DEBUG
-#  define DMDEBUG(f, arg...) printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
+#  define DMDEBUG(f, arg...) \
+	printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
+#  define DMDEBUG_LIMIT(f, arg...) \
+	do { \
+		if (printk_ratelimit())	\
+			printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
+			       "\n", ## arg); \
+	} while (0)
 #else
 #  define DMDEBUG(f, arg...) do {} while (0)
+#  define DMDEBUG_LIMIT(f, arg...) do {} while (0)
 #endif
 
 #define DMEMIT(x...) sz += ((sz >= maxlen) ? \
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index dbc234e..7e05237 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -29,7 +29,7 @@
 static struct workqueue_struct *_kcopyd_wq;
 static struct work_struct _kcopyd_work;
 
-static inline void wake(void)
+static void wake(void)
 {
 	queue_work(_kcopyd_wq, &_kcopyd_work);
 }
@@ -226,10 +226,7 @@
 
 static int jobs_init(void)
 {
-	_job_cache = kmem_cache_create("kcopyd-jobs",
-				       sizeof(struct kcopyd_job),
-				       __alignof__(struct kcopyd_job),
-				       0, NULL, NULL);
+	_job_cache = KMEM_CACHE(kcopyd_job, 0);
 	if (!_job_cache)
 		return -ENOMEM;
 
@@ -258,7 +255,7 @@
  * Functions to push and pop a job onto the head of a given job
  * list.
  */
-static inline struct kcopyd_job *pop(struct list_head *jobs)
+static struct kcopyd_job *pop(struct list_head *jobs)
 {
 	struct kcopyd_job *job = NULL;
 	unsigned long flags;
@@ -274,7 +271,7 @@
 	return job;
 }
 
-static inline void push(struct list_head *jobs, struct kcopyd_job *job)
+static void push(struct list_head *jobs, struct kcopyd_job *job)
 {
 	unsigned long flags;
 
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index d5ecd2d..1927410 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -139,8 +139,6 @@
 	if (!conf)
 		return NULL;
 
-	mddev->private = conf;
-
 	cnt = 0;
 	conf->array_size = 0;
 
@@ -232,7 +230,7 @@
 	 * First calculate the device offsets.
 	 */
 	conf->disks[0].offset = 0;
-	for (i=1; i<mddev->raid_disks; i++)
+	for (i = 1; i < raid_disks; i++)
 		conf->disks[i].offset =
 			conf->disks[i-1].offset +
 			conf->disks[i-1].size;
@@ -244,7 +242,7 @@
 	     curr_offset < conf->array_size;
 	     curr_offset += conf->hash_spacing) {
 
-		while (i < mddev->raid_disks-1 &&
+		while (i < raid_disks-1 &&
 		       curr_offset >= conf->disks[i+1].offset)
 			i++;
 
@@ -299,9 +297,11 @@
 	 */
 	linear_conf_t *newconf;
 
-	if (rdev->raid_disk != mddev->raid_disks)
+	if (rdev->saved_raid_disk != mddev->raid_disks)
 		return -EINVAL;
 
+	rdev->raid_disk = rdev->saved_raid_disk;
+
 	newconf = linear_conf(mddev,mddev->raid_disks+1);
 
 	if (!newconf)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c10ce91..65ddc88 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1298,8 +1298,9 @@
 	ITERATE_RDEV(mddev,rdev2,tmp)
 		if (rdev2->desc_nr+1 > max_dev)
 			max_dev = rdev2->desc_nr+1;
-	
-	sb->max_dev = cpu_to_le32(max_dev);
+
+	if (max_dev > le32_to_cpu(sb->max_dev))
+		sb->max_dev = cpu_to_le32(max_dev);
 	for (i=0; i<max_dev;i++)
 		sb->dev_roles[i] = cpu_to_le16(0xfffe);
 	
@@ -1365,10 +1366,14 @@
 	}
 	/* make sure rdev->size exceeds mddev->size */
 	if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) {
-		if (mddev->pers)
-			/* Cannot change size, so fail */
-			return -ENOSPC;
-		else
+		if (mddev->pers) {
+			/* Cannot change size, so fail
+			 * If mddev->level <= 0, then we don't care
+			 * about aligning sizes (e.g. linear)
+			 */
+			if (mddev->level > 0)
+				return -ENOSPC;
+		} else
 			mddev->size = rdev->size;
 	}
 
@@ -1635,7 +1640,6 @@
 
 static void md_update_sb(mddev_t * mddev, int force_change)
 {
-	int err;
 	struct list_head *tmp;
 	mdk_rdev_t *rdev;
 	int sync_req;
@@ -1722,7 +1726,7 @@
 		"md: updating %s RAID superblock on device (in sync %d)\n",
 		mdname(mddev),mddev->in_sync);
 
-	err = bitmap_update_sb(mddev->bitmap);
+	bitmap_update_sb(mddev->bitmap);
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		char b[BDEVNAME_SIZE];
 		dprintk(KERN_INFO "md: ");
@@ -2068,9 +2072,11 @@
 		err = super_types[super_format].
 			load_super(rdev, NULL, super_minor);
 		if (err == -EINVAL) {
-			printk(KERN_WARNING 
-				"md: %s has invalid sb, not importing!\n",
-				bdevname(rdev->bdev,b));
+			printk(KERN_WARNING
+				"md: %s does not have a valid v%d.%d "
+			       "superblock, not importing!\n",
+				bdevname(rdev->bdev,b),
+			       super_format, super_minor);
 			goto abort_free;
 		}
 		if (err < 0) {
@@ -2142,6 +2148,9 @@
 			rdev->desc_nr = i++;
 			rdev->raid_disk = rdev->desc_nr;
 			set_bit(In_sync, &rdev->flags);
+		} else if (rdev->raid_disk >= mddev->raid_disks) {
+			rdev->raid_disk = -1;
+			clear_bit(In_sync, &rdev->flags);
 		}
 	}
 
@@ -3166,13 +3175,33 @@
 	 * Drop all container device buffers, from now on
 	 * the only valid external interface is through the md
 	 * device.
-	 * Also find largest hardsector size
 	 */
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		if (test_bit(Faulty, &rdev->flags))
 			continue;
 		sync_blockdev(rdev->bdev);
 		invalidate_bdev(rdev->bdev);
+
+		/* perform some consistency tests on the device.
+		 * We don't want the data to overlap the metadata,
+		 * Internal Bitmap issues has handled elsewhere.
+		 */
+		if (rdev->data_offset < rdev->sb_offset) {
+			if (mddev->size &&
+			    rdev->data_offset + mddev->size*2
+			    > rdev->sb_offset*2) {
+				printk("md: %s: data overlaps metadata\n",
+				       mdname(mddev));
+				return -EINVAL;
+			}
+		} else {
+			if (rdev->sb_offset*2 + rdev->sb_size/512
+			    > rdev->data_offset) {
+				printk("md: %s: metadata overlaps data\n",
+				       mdname(mddev));
+				return -EINVAL;
+			}
+		}
 	}
 
 	md_probe(mddev->unit, NULL, NULL);
@@ -4634,7 +4663,6 @@
 	 * many dirty RAID5 blocks.
 	 */
 
-	current->flags |= PF_NOFREEZE;
 	allow_signal(SIGKILL);
 	while (!kthread_should_stop()) {
 
@@ -5082,7 +5110,7 @@
 	mdk_rdev_t * rdev;
 	struct list_head *tmp;
 	int idle;
-	unsigned long curr_events;
+	long curr_events;
 
 	idle = 1;
 	ITERATE_RDEV(mddev,rdev,tmp) {
@@ -5090,20 +5118,29 @@
 		curr_events = disk_stat_read(disk, sectors[0]) + 
 				disk_stat_read(disk, sectors[1]) - 
 				atomic_read(&disk->sync_io);
-		/* The difference between curr_events and last_events
-		 * will be affected by any new non-sync IO (making
-		 * curr_events bigger) and any difference in the amount of
-		 * in-flight syncio (making current_events bigger or smaller)
-		 * The amount in-flight is currently limited to
-		 * 32*64K in raid1/10 and 256*PAGE_SIZE in raid5/6
-		 * which is at most 4096 sectors.
-		 * These numbers are fairly fragile and should be made
-		 * more robust, probably by enforcing the
-		 * 'window size' that md_do_sync sort-of uses.
+		/* sync IO will cause sync_io to increase before the disk_stats
+		 * as sync_io is counted when a request starts, and
+		 * disk_stats is counted when it completes.
+		 * So resync activity will cause curr_events to be smaller than
+		 * when there was no such activity.
+		 * non-sync IO will cause disk_stat to increase without
+		 * increasing sync_io so curr_events will (eventually)
+		 * be larger than it was before.  Once it becomes
+		 * substantially larger, the test below will cause
+		 * the array to appear non-idle, and resync will slow
+		 * down.
+		 * If there is a lot of outstanding resync activity when
+		 * we set last_event to curr_events, then all that activity
+		 * completing might cause the array to appear non-idle
+		 * and resync will be slowed down even though there might
+		 * not have been non-resync activity.  This will only
+		 * happen once though.  'last_events' will soon reflect
+		 * the state where there is little or no outstanding
+		 * resync requests, and further resync activity will
+		 * always make curr_events less than last_events.
 		 *
-		 * Note: the following is an unsigned comparison.
 		 */
-		if ((long)curr_events - (long)rdev->last_events > 4096) {
+		if (curr_events - rdev->last_events > 4096) {
 			rdev->last_events = curr_events;
 			idle = 0;
 		}
@@ -5764,7 +5801,7 @@
 	for (i = 0; i < dev_cnt; i++) {
 		dev_t dev = detected_devices[i];
 
-		rdev = md_import_device(dev,0, 0);
+		rdev = md_import_device(dev,0, 90);
 		if (IS_ERR(rdev))
 			continue;
 
@@ -5806,7 +5843,7 @@
 	}
 }
 
-module_init(md_init)
+subsys_initcall(md_init);
 module_exit(md_exit)
 
 static int get_ro(char *buffer, struct kernel_param *kp)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index dfe3214..2c404f7 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -415,7 +415,7 @@
 	raid0_conf_t *conf = mddev_to_conf(mddev);
 	struct strip_zone *zone;
 	mdk_rdev_t *tmp_dev;
-	unsigned long chunk;
+	sector_t chunk;
 	sector_t block, rsect;
 	const int rw = bio_data_dir(bio);
 
@@ -470,7 +470,6 @@
 
 		sector_div(x, zone->nb_dev);
 		chunk = x;
-		BUG_ON(x != (sector_t)chunk);
 
 		x = block >> chunksize_bits;
 		tmp_dev = zone->dev[sector_div(x, zone->nb_dev)];
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 3a95cc5..00c78b7 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1240,17 +1240,24 @@
 			}
 		r1_bio->read_disk = primary;
 		for (i=0; i<mddev->raid_disks; i++)
-			if (r1_bio->bios[i]->bi_end_io == end_sync_read &&
-			    test_bit(BIO_UPTODATE, &r1_bio->bios[i]->bi_flags)) {
+			if (r1_bio->bios[i]->bi_end_io == end_sync_read) {
 				int j;
 				int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9);
 				struct bio *pbio = r1_bio->bios[primary];
 				struct bio *sbio = r1_bio->bios[i];
-				for (j = vcnt; j-- ; )
-					if (memcmp(page_address(pbio->bi_io_vec[j].bv_page),
-						   page_address(sbio->bi_io_vec[j].bv_page),
-						   PAGE_SIZE))
-						break;
+
+				if (test_bit(BIO_UPTODATE, &sbio->bi_flags)) {
+					for (j = vcnt; j-- ; ) {
+						struct page *p, *s;
+						p = pbio->bi_io_vec[j].bv_page;
+						s = sbio->bi_io_vec[j].bv_page;
+						if (memcmp(page_address(p),
+							   page_address(s),
+							   PAGE_SIZE))
+							break;
+					}
+				} else
+					j = 0;
 				if (j >= 0)
 					mddev->resync_mismatches += r1_bio->sectors;
 				if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
@@ -1519,8 +1526,7 @@
 			blk_remove_plug(mddev->queue);
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			/* flush any pending bitmap writes to disk before proceeding w/ I/O */
-			if (bitmap_unplug(mddev->bitmap) != 0)
-				printk("%s: bitmap file write failed!\n", mdname(mddev));
+			bitmap_unplug(mddev->bitmap);
 
 			while (bio) { /* submit pending writes */
 				struct bio *next = bio->bi_next;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 82249a6..a95ada1 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1510,8 +1510,7 @@
 			blk_remove_plug(mddev->queue);
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			/* flush any pending bitmap writes to disk before proceeding w/ I/O */
-			if (bitmap_unplug(mddev->bitmap) != 0)
-				printk("%s: bitmap file write failed!\n", mdname(mddev));
+			bitmap_unplug(mddev->bitmap);
 
 			while (bio) { /* submit pending writes */
 				struct bio *next = bio->bi_next;
@@ -1867,6 +1866,7 @@
 			int d = r10_bio->devs[i].devnum;
 			bio = r10_bio->devs[i].bio;
 			bio->bi_end_io = NULL;
+			clear_bit(BIO_UPTODATE, &bio->bi_flags);
 			if (conf->mirrors[d].rdev == NULL ||
 			    test_bit(Faulty, &conf->mirrors[d].rdev->flags))
 				continue;
@@ -2037,6 +2037,11 @@
 	/* 'size' is now the number of chunks in the array */
 	/* calculate "used chunks per device" in 'stride' */
 	stride = size * conf->copies;
+
+	/* We need to round up when dividing by raid_disks to
+	 * get the stride size.
+	 */
+	stride += conf->raid_disks - 1;
 	sector_div(stride, conf->raid_disks);
 	mddev->size = stride  << (conf->chunk_shift-1);
 
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 061375e..0b66afe 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -52,6 +52,7 @@
 #include "raid6.h"
 
 #include <linux/raid/bitmap.h>
+#include <linux/async_tx.h>
 
 /*
  * Stripe cache
@@ -80,7 +81,6 @@
 /*
  * The following can be used to debug the driver
  */
-#define RAID5_DEBUG	0
 #define RAID5_PARANOIA	1
 #if RAID5_PARANOIA && defined(CONFIG_SMP)
 # define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
@@ -88,8 +88,7 @@
 # define CHECK_DEVLOCK()
 #endif
 
-#define PRINTK(x...) ((void)(RAID5_DEBUG && printk(x)))
-#if RAID5_DEBUG
+#ifdef DEBUG
 #define inline
 #define __inline__
 #endif
@@ -104,6 +103,23 @@
 	disk++;
 	return (disk < raid_disks) ? disk : 0;
 }
+
+static void return_io(struct bio *return_bi)
+{
+	struct bio *bi = return_bi;
+	while (bi) {
+		int bytes = bi->bi_size;
+
+		return_bi = bi->bi_next;
+		bi->bi_next = NULL;
+		bi->bi_size = 0;
+		bi->bi_end_io(bi, bytes,
+			      test_bit(BIO_UPTODATE, &bi->bi_flags)
+			        ? 0 : -EIO);
+		bi = return_bi;
+	}
+}
+
 static void print_raid5_conf (raid5_conf_t *conf);
 
 static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
@@ -125,6 +141,7 @@
 			}
 			md_wakeup_thread(conf->mddev->thread);
 		} else {
+			BUG_ON(sh->ops.pending);
 			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
 				atomic_dec(&conf->preread_active_stripes);
 				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
@@ -152,7 +169,8 @@
 
 static inline void remove_hash(struct stripe_head *sh)
 {
-	PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
+	pr_debug("remove_hash(), stripe %llu\n",
+		(unsigned long long)sh->sector);
 
 	hlist_del_init(&sh->hash);
 }
@@ -161,7 +179,8 @@
 {
 	struct hlist_head *hp = stripe_hash(conf, sh->sector);
 
-	PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
+	pr_debug("insert_hash(), stripe %llu\n",
+		(unsigned long long)sh->sector);
 
 	CHECK_DEVLOCK();
 	hlist_add_head(&sh->hash, hp);
@@ -224,9 +243,10 @@
 
 	BUG_ON(atomic_read(&sh->count) != 0);
 	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
-	
+	BUG_ON(sh->ops.pending || sh->ops.ack || sh->ops.complete);
+
 	CHECK_DEVLOCK();
-	PRINTK("init_stripe called, stripe %llu\n", 
+	pr_debug("init_stripe called, stripe %llu\n",
 		(unsigned long long)sh->sector);
 
 	remove_hash(sh);
@@ -240,11 +260,11 @@
 	for (i = sh->disks; i--; ) {
 		struct r5dev *dev = &sh->dev[i];
 
-		if (dev->toread || dev->towrite || dev->written ||
+		if (dev->toread || dev->read || dev->towrite || dev->written ||
 		    test_bit(R5_LOCKED, &dev->flags)) {
-			printk("sector=%llx i=%d %p %p %p %d\n",
+			printk(KERN_ERR "sector=%llx i=%d %p %p %p %p %d\n",
 			       (unsigned long long)sh->sector, i, dev->toread,
-			       dev->towrite, dev->written,
+			       dev->read, dev->towrite, dev->written,
 			       test_bit(R5_LOCKED, &dev->flags));
 			BUG();
 		}
@@ -260,11 +280,11 @@
 	struct hlist_node *hn;
 
 	CHECK_DEVLOCK();
-	PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
+	pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector);
 	hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
 		if (sh->sector == sector && sh->disks == disks)
 			return sh;
-	PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
+	pr_debug("__stripe %llu not in cache\n", (unsigned long long)sector);
 	return NULL;
 }
 
@@ -276,7 +296,7 @@
 {
 	struct stripe_head *sh;
 
-	PRINTK("get_stripe, sector %llu\n", (unsigned long long)sector);
+	pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector);
 
 	spin_lock_irq(&conf->device_lock);
 
@@ -324,6 +344,579 @@
 	return sh;
 }
 
+/* test_and_ack_op() ensures that we only dequeue an operation once */
+#define test_and_ack_op(op, pend) \
+do {							\
+	if (test_bit(op, &sh->ops.pending) &&		\
+		!test_bit(op, &sh->ops.complete)) {	\
+		if (test_and_set_bit(op, &sh->ops.ack)) \
+			clear_bit(op, &pend);		\
+		else					\
+			ack++;				\
+	} else						\
+		clear_bit(op, &pend);			\
+} while (0)
+
+/* find new work to run, do not resubmit work that is already
+ * in flight
+ */
+static unsigned long get_stripe_work(struct stripe_head *sh)
+{
+	unsigned long pending;
+	int ack = 0;
+
+	pending = sh->ops.pending;
+
+	test_and_ack_op(STRIPE_OP_BIOFILL, pending);
+	test_and_ack_op(STRIPE_OP_COMPUTE_BLK, pending);
+	test_and_ack_op(STRIPE_OP_PREXOR, pending);
+	test_and_ack_op(STRIPE_OP_BIODRAIN, pending);
+	test_and_ack_op(STRIPE_OP_POSTXOR, pending);
+	test_and_ack_op(STRIPE_OP_CHECK, pending);
+	if (test_and_clear_bit(STRIPE_OP_IO, &sh->ops.pending))
+		ack++;
+
+	sh->ops.count -= ack;
+	BUG_ON(sh->ops.count < 0);
+
+	return pending;
+}
+
+static int
+raid5_end_read_request(struct bio *bi, unsigned int bytes_done, int error);
+static int
+raid5_end_write_request (struct bio *bi, unsigned int bytes_done, int error);
+
+static void ops_run_io(struct stripe_head *sh)
+{
+	raid5_conf_t *conf = sh->raid_conf;
+	int i, disks = sh->disks;
+
+	might_sleep();
+
+	for (i = disks; i--; ) {
+		int rw;
+		struct bio *bi;
+		mdk_rdev_t *rdev;
+		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
+			rw = WRITE;
+		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
+			rw = READ;
+		else
+			continue;
+
+		bi = &sh->dev[i].req;
+
+		bi->bi_rw = rw;
+		if (rw == WRITE)
+			bi->bi_end_io = raid5_end_write_request;
+		else
+			bi->bi_end_io = raid5_end_read_request;
+
+		rcu_read_lock();
+		rdev = rcu_dereference(conf->disks[i].rdev);
+		if (rdev && test_bit(Faulty, &rdev->flags))
+			rdev = NULL;
+		if (rdev)
+			atomic_inc(&rdev->nr_pending);
+		rcu_read_unlock();
+
+		if (rdev) {
+			if (test_bit(STRIPE_SYNCING, &sh->state) ||
+				test_bit(STRIPE_EXPAND_SOURCE, &sh->state) ||
+				test_bit(STRIPE_EXPAND_READY, &sh->state))
+				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
+
+			bi->bi_bdev = rdev->bdev;
+			pr_debug("%s: for %llu schedule op %ld on disc %d\n",
+				__FUNCTION__, (unsigned long long)sh->sector,
+				bi->bi_rw, i);
+			atomic_inc(&sh->count);
+			bi->bi_sector = sh->sector + rdev->data_offset;
+			bi->bi_flags = 1 << BIO_UPTODATE;
+			bi->bi_vcnt = 1;
+			bi->bi_max_vecs = 1;
+			bi->bi_idx = 0;
+			bi->bi_io_vec = &sh->dev[i].vec;
+			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
+			bi->bi_io_vec[0].bv_offset = 0;
+			bi->bi_size = STRIPE_SIZE;
+			bi->bi_next = NULL;
+			if (rw == WRITE &&
+			    test_bit(R5_ReWrite, &sh->dev[i].flags))
+				atomic_add(STRIPE_SECTORS,
+					&rdev->corrected_errors);
+			generic_make_request(bi);
+		} else {
+			if (rw == WRITE)
+				set_bit(STRIPE_DEGRADED, &sh->state);
+			pr_debug("skip op %ld on disc %d for sector %llu\n",
+				bi->bi_rw, i, (unsigned long long)sh->sector);
+			clear_bit(R5_LOCKED, &sh->dev[i].flags);
+			set_bit(STRIPE_HANDLE, &sh->state);
+		}
+	}
+}
+
+static struct dma_async_tx_descriptor *
+async_copy_data(int frombio, struct bio *bio, struct page *page,
+	sector_t sector, struct dma_async_tx_descriptor *tx)
+{
+	struct bio_vec *bvl;
+	struct page *bio_page;
+	int i;
+	int page_offset;
+
+	if (bio->bi_sector >= sector)
+		page_offset = (signed)(bio->bi_sector - sector) * 512;
+	else
+		page_offset = (signed)(sector - bio->bi_sector) * -512;
+	bio_for_each_segment(bvl, bio, i) {
+		int len = bio_iovec_idx(bio, i)->bv_len;
+		int clen;
+		int b_offset = 0;
+
+		if (page_offset < 0) {
+			b_offset = -page_offset;
+			page_offset += b_offset;
+			len -= b_offset;
+		}
+
+		if (len > 0 && page_offset + len > STRIPE_SIZE)
+			clen = STRIPE_SIZE - page_offset;
+		else
+			clen = len;
+
+		if (clen > 0) {
+			b_offset += bio_iovec_idx(bio, i)->bv_offset;
+			bio_page = bio_iovec_idx(bio, i)->bv_page;
+			if (frombio)
+				tx = async_memcpy(page, bio_page, page_offset,
+					b_offset, clen,
+					ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_SRC,
+					tx, NULL, NULL);
+			else
+				tx = async_memcpy(bio_page, page, b_offset,
+					page_offset, clen,
+					ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_DST,
+					tx, NULL, NULL);
+		}
+		if (clen < len) /* hit end of page */
+			break;
+		page_offset +=  len;
+	}
+
+	return tx;
+}
+
+static void ops_complete_biofill(void *stripe_head_ref)
+{
+	struct stripe_head *sh = stripe_head_ref;
+	struct bio *return_bi = NULL;
+	raid5_conf_t *conf = sh->raid_conf;
+	int i, more_to_read = 0;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	/* clear completed biofills */
+	for (i = sh->disks; i--; ) {
+		struct r5dev *dev = &sh->dev[i];
+		/* check if this stripe has new incoming reads */
+		if (dev->toread)
+			more_to_read++;
+
+		/* acknowledge completion of a biofill operation */
+		/* and check if we need to reply to a read request
+		*/
+		if (test_bit(R5_Wantfill, &dev->flags) && !dev->toread) {
+			struct bio *rbi, *rbi2;
+			clear_bit(R5_Wantfill, &dev->flags);
+
+			/* The access to dev->read is outside of the
+			 * spin_lock_irq(&conf->device_lock), but is protected
+			 * by the STRIPE_OP_BIOFILL pending bit
+			 */
+			BUG_ON(!dev->read);
+			rbi = dev->read;
+			dev->read = NULL;
+			while (rbi && rbi->bi_sector <
+				dev->sector + STRIPE_SECTORS) {
+				rbi2 = r5_next_bio(rbi, dev->sector);
+				spin_lock_irq(&conf->device_lock);
+				if (--rbi->bi_phys_segments == 0) {
+					rbi->bi_next = return_bi;
+					return_bi = rbi;
+				}
+				spin_unlock_irq(&conf->device_lock);
+				rbi = rbi2;
+			}
+		}
+	}
+	clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
+	clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
+
+	return_io(return_bi);
+
+	if (more_to_read)
+		set_bit(STRIPE_HANDLE, &sh->state);
+	release_stripe(sh);
+}
+
+static void ops_run_biofill(struct stripe_head *sh)
+{
+	struct dma_async_tx_descriptor *tx = NULL;
+	raid5_conf_t *conf = sh->raid_conf;
+	int i;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	for (i = sh->disks; i--; ) {
+		struct r5dev *dev = &sh->dev[i];
+		if (test_bit(R5_Wantfill, &dev->flags)) {
+			struct bio *rbi;
+			spin_lock_irq(&conf->device_lock);
+			dev->read = rbi = dev->toread;
+			dev->toread = NULL;
+			spin_unlock_irq(&conf->device_lock);
+			while (rbi && rbi->bi_sector <
+				dev->sector + STRIPE_SECTORS) {
+				tx = async_copy_data(0, rbi, dev->page,
+					dev->sector, tx);
+				rbi = r5_next_bio(rbi, dev->sector);
+			}
+		}
+	}
+
+	atomic_inc(&sh->count);
+	async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
+		ops_complete_biofill, sh);
+}
+
+static void ops_complete_compute5(void *stripe_head_ref)
+{
+	struct stripe_head *sh = stripe_head_ref;
+	int target = sh->ops.target;
+	struct r5dev *tgt = &sh->dev[target];
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	set_bit(R5_UPTODATE, &tgt->flags);
+	BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
+	clear_bit(R5_Wantcompute, &tgt->flags);
+	set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+	set_bit(STRIPE_HANDLE, &sh->state);
+	release_stripe(sh);
+}
+
+static struct dma_async_tx_descriptor *
+ops_run_compute5(struct stripe_head *sh, unsigned long pending)
+{
+	/* kernel stack size limits the total number of disks */
+	int disks = sh->disks;
+	struct page *xor_srcs[disks];
+	int target = sh->ops.target;
+	struct r5dev *tgt = &sh->dev[target];
+	struct page *xor_dest = tgt->page;
+	int count = 0;
+	struct dma_async_tx_descriptor *tx;
+	int i;
+
+	pr_debug("%s: stripe %llu block: %d\n",
+		__FUNCTION__, (unsigned long long)sh->sector, target);
+	BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
+
+	for (i = disks; i--; )
+		if (i != target)
+			xor_srcs[count++] = sh->dev[i].page;
+
+	atomic_inc(&sh->count);
+
+	if (unlikely(count == 1))
+		tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
+			0, NULL, ops_complete_compute5, sh);
+	else
+		tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+			ASYNC_TX_XOR_ZERO_DST, NULL,
+			ops_complete_compute5, sh);
+
+	/* ack now if postxor is not set to be run */
+	if (tx && !test_bit(STRIPE_OP_POSTXOR, &pending))
+		async_tx_ack(tx);
+
+	return tx;
+}
+
+static void ops_complete_prexor(void *stripe_head_ref)
+{
+	struct stripe_head *sh = stripe_head_ref;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	set_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+}
+
+static struct dma_async_tx_descriptor *
+ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+{
+	/* kernel stack size limits the total number of disks */
+	int disks = sh->disks;
+	struct page *xor_srcs[disks];
+	int count = 0, pd_idx = sh->pd_idx, i;
+
+	/* existing parity data subtracted */
+	struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	for (i = disks; i--; ) {
+		struct r5dev *dev = &sh->dev[i];
+		/* Only process blocks that are known to be uptodate */
+		if (dev->towrite && test_bit(R5_Wantprexor, &dev->flags))
+			xor_srcs[count++] = dev->page;
+	}
+
+	tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+		ASYNC_TX_DEP_ACK | ASYNC_TX_XOR_DROP_DST, tx,
+		ops_complete_prexor, sh);
+
+	return tx;
+}
+
+static struct dma_async_tx_descriptor *
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+{
+	int disks = sh->disks;
+	int pd_idx = sh->pd_idx, i;
+
+	/* check if prexor is active which means only process blocks
+	 * that are part of a read-modify-write (Wantprexor)
+	 */
+	int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	for (i = disks; i--; ) {
+		struct r5dev *dev = &sh->dev[i];
+		struct bio *chosen;
+		int towrite;
+
+		towrite = 0;
+		if (prexor) { /* rmw */
+			if (dev->towrite &&
+			    test_bit(R5_Wantprexor, &dev->flags))
+				towrite = 1;
+		} else { /* rcw */
+			if (i != pd_idx && dev->towrite &&
+				test_bit(R5_LOCKED, &dev->flags))
+				towrite = 1;
+		}
+
+		if (towrite) {
+			struct bio *wbi;
+
+			spin_lock(&sh->lock);
+			chosen = dev->towrite;
+			dev->towrite = NULL;
+			BUG_ON(dev->written);
+			wbi = dev->written = chosen;
+			spin_unlock(&sh->lock);
+
+			while (wbi && wbi->bi_sector <
+				dev->sector + STRIPE_SECTORS) {
+				tx = async_copy_data(1, wbi, dev->page,
+					dev->sector, tx);
+				wbi = r5_next_bio(wbi, dev->sector);
+			}
+		}
+	}
+
+	return tx;
+}
+
+static void ops_complete_postxor(void *stripe_head_ref)
+{
+	struct stripe_head *sh = stripe_head_ref;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+	set_bit(STRIPE_HANDLE, &sh->state);
+	release_stripe(sh);
+}
+
+static void ops_complete_write(void *stripe_head_ref)
+{
+	struct stripe_head *sh = stripe_head_ref;
+	int disks = sh->disks, i, pd_idx = sh->pd_idx;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	for (i = disks; i--; ) {
+		struct r5dev *dev = &sh->dev[i];
+		if (dev->written || i == pd_idx)
+			set_bit(R5_UPTODATE, &dev->flags);
+	}
+
+	set_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
+	set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+
+	set_bit(STRIPE_HANDLE, &sh->state);
+	release_stripe(sh);
+}
+
+static void
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+{
+	/* kernel stack size limits the total number of disks */
+	int disks = sh->disks;
+	struct page *xor_srcs[disks];
+
+	int count = 0, pd_idx = sh->pd_idx, i;
+	struct page *xor_dest;
+	int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+	unsigned long flags;
+	dma_async_tx_callback callback;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	/* check if prexor is active which means only process blocks
+	 * that are part of a read-modify-write (written)
+	 */
+	if (prexor) {
+		xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			if (dev->written)
+				xor_srcs[count++] = dev->page;
+		}
+	} else {
+		xor_dest = sh->dev[pd_idx].page;
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			if (i != pd_idx)
+				xor_srcs[count++] = dev->page;
+		}
+	}
+
+	/* check whether this postxor is part of a write */
+	callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
+		ops_complete_write : ops_complete_postxor;
+
+	/* 1/ if we prexor'd then the dest is reused as a source
+	 * 2/ if we did not prexor then we are redoing the parity
+	 * set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST
+	 * for the synchronous xor case
+	 */
+	flags = ASYNC_TX_DEP_ACK | ASYNC_TX_ACK |
+		(prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);
+
+	atomic_inc(&sh->count);
+
+	if (unlikely(count == 1)) {
+		flags &= ~(ASYNC_TX_XOR_DROP_DST | ASYNC_TX_XOR_ZERO_DST);
+		tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
+			flags, tx, callback, sh);
+	} else
+		tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+			flags, tx, callback, sh);
+}
+
+static void ops_complete_check(void *stripe_head_ref)
+{
+	struct stripe_head *sh = stripe_head_ref;
+	int pd_idx = sh->pd_idx;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	if (test_and_clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending) &&
+		sh->ops.zero_sum_result == 0)
+		set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+
+	set_bit(STRIPE_OP_CHECK, &sh->ops.complete);
+	set_bit(STRIPE_HANDLE, &sh->state);
+	release_stripe(sh);
+}
+
+static void ops_run_check(struct stripe_head *sh)
+{
+	/* kernel stack size limits the total number of disks */
+	int disks = sh->disks;
+	struct page *xor_srcs[disks];
+	struct dma_async_tx_descriptor *tx;
+
+	int count = 0, pd_idx = sh->pd_idx, i;
+	struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+
+	pr_debug("%s: stripe %llu\n", __FUNCTION__,
+		(unsigned long long)sh->sector);
+
+	for (i = disks; i--; ) {
+		struct r5dev *dev = &sh->dev[i];
+		if (i != pd_idx)
+			xor_srcs[count++] = dev->page;
+	}
+
+	tx = async_xor_zero_sum(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+		&sh->ops.zero_sum_result, 0, NULL, NULL, NULL);
+
+	if (tx)
+		set_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
+	else
+		clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
+
+	atomic_inc(&sh->count);
+	tx = async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
+		ops_complete_check, sh);
+}
+
+static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
+{
+	int overlap_clear = 0, i, disks = sh->disks;
+	struct dma_async_tx_descriptor *tx = NULL;
+
+	if (test_bit(STRIPE_OP_BIOFILL, &pending)) {
+		ops_run_biofill(sh);
+		overlap_clear++;
+	}
+
+	if (test_bit(STRIPE_OP_COMPUTE_BLK, &pending))
+		tx = ops_run_compute5(sh, pending);
+
+	if (test_bit(STRIPE_OP_PREXOR, &pending))
+		tx = ops_run_prexor(sh, tx);
+
+	if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
+		tx = ops_run_biodrain(sh, tx);
+		overlap_clear++;
+	}
+
+	if (test_bit(STRIPE_OP_POSTXOR, &pending))
+		ops_run_postxor(sh, tx);
+
+	if (test_bit(STRIPE_OP_CHECK, &pending))
+		ops_run_check(sh);
+
+	if (test_bit(STRIPE_OP_IO, &pending))
+		ops_run_io(sh);
+
+	if (overlap_clear)
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			if (test_and_clear_bit(R5_Overlap, &dev->flags))
+				wake_up(&sh->raid_conf->wait_for_overlap);
+		}
+}
+
 static int grow_one_stripe(raid5_conf_t *conf)
 {
 	struct stripe_head *sh;
@@ -537,8 +1130,8 @@
 		if (bi == &sh->dev[i].req)
 			break;
 
-	PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n", 
-		(unsigned long long)sh->sector, i, atomic_read(&sh->count), 
+	pr_debug("end_read_request %llu/%d, count: %d, uptodate %d.\n",
+		(unsigned long long)sh->sector, i, atomic_read(&sh->count),
 		uptodate);
 	if (i == disks) {
 		BUG();
@@ -613,7 +1206,7 @@
 		if (bi == &sh->dev[i].req)
 			break;
 
-	PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n", 
+	pr_debug("end_write_request %llu/%d, count %d, uptodate: %d.\n",
 		(unsigned long long)sh->sector, i, atomic_read(&sh->count),
 		uptodate);
 	if (i == disks) {
@@ -658,7 +1251,7 @@
 {
 	char b[BDEVNAME_SIZE];
 	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
-	PRINTK("raid5: error called\n");
+	pr_debug("raid5: error called\n");
 
 	if (!test_bit(Faulty, &rdev->flags)) {
 		set_bit(MD_CHANGE_DEVS, &mddev->flags);
@@ -916,137 +1509,13 @@
 	}
 }
 
-#define check_xor() 	do { 						\
-			   if (count == MAX_XOR_BLOCKS) {		\
-				xor_block(count, STRIPE_SIZE, ptr);	\
-				count = 1;				\
-			   }						\
+#define check_xor()	do {						  \
+				if (count == MAX_XOR_BLOCKS) {		  \
+				xor_blocks(count, STRIPE_SIZE, dest, ptr);\
+				count = 0;				  \
+			   }						  \
 			} while(0)
 
-
-static void compute_block(struct stripe_head *sh, int dd_idx)
-{
-	int i, count, disks = sh->disks;
-	void *ptr[MAX_XOR_BLOCKS], *p;
-
-	PRINTK("compute_block, stripe %llu, idx %d\n", 
-		(unsigned long long)sh->sector, dd_idx);
-
-	ptr[0] = page_address(sh->dev[dd_idx].page);
-	memset(ptr[0], 0, STRIPE_SIZE);
-	count = 1;
-	for (i = disks ; i--; ) {
-		if (i == dd_idx)
-			continue;
-		p = page_address(sh->dev[i].page);
-		if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
-			ptr[count++] = p;
-		else
-			printk(KERN_ERR "compute_block() %d, stripe %llu, %d"
-				" not present\n", dd_idx,
-				(unsigned long long)sh->sector, i);
-
-		check_xor();
-	}
-	if (count != 1)
-		xor_block(count, STRIPE_SIZE, ptr);
-	set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
-}
-
-static void compute_parity5(struct stripe_head *sh, int method)
-{
-	raid5_conf_t *conf = sh->raid_conf;
-	int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
-	void *ptr[MAX_XOR_BLOCKS];
-	struct bio *chosen;
-
-	PRINTK("compute_parity5, stripe %llu, method %d\n",
-		(unsigned long long)sh->sector, method);
-
-	count = 1;
-	ptr[0] = page_address(sh->dev[pd_idx].page);
-	switch(method) {
-	case READ_MODIFY_WRITE:
-		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
-		for (i=disks ; i-- ;) {
-			if (i==pd_idx)
-				continue;
-			if (sh->dev[i].towrite &&
-			    test_bit(R5_UPTODATE, &sh->dev[i].flags)) {
-				ptr[count++] = page_address(sh->dev[i].page);
-				chosen = sh->dev[i].towrite;
-				sh->dev[i].towrite = NULL;
-
-				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-					wake_up(&conf->wait_for_overlap);
-
-				BUG_ON(sh->dev[i].written);
-				sh->dev[i].written = chosen;
-				check_xor();
-			}
-		}
-		break;
-	case RECONSTRUCT_WRITE:
-		memset(ptr[0], 0, STRIPE_SIZE);
-		for (i= disks; i-- ;)
-			if (i!=pd_idx && sh->dev[i].towrite) {
-				chosen = sh->dev[i].towrite;
-				sh->dev[i].towrite = NULL;
-
-				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-					wake_up(&conf->wait_for_overlap);
-
-				BUG_ON(sh->dev[i].written);
-				sh->dev[i].written = chosen;
-			}
-		break;
-	case CHECK_PARITY:
-		break;
-	}
-	if (count>1) {
-		xor_block(count, STRIPE_SIZE, ptr);
-		count = 1;
-	}
-	
-	for (i = disks; i--;)
-		if (sh->dev[i].written) {
-			sector_t sector = sh->dev[i].sector;
-			struct bio *wbi = sh->dev[i].written;
-			while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
-				copy_data(1, wbi, sh->dev[i].page, sector);
-				wbi = r5_next_bio(wbi, sector);
-			}
-
-			set_bit(R5_LOCKED, &sh->dev[i].flags);
-			set_bit(R5_UPTODATE, &sh->dev[i].flags);
-		}
-
-	switch(method) {
-	case RECONSTRUCT_WRITE:
-	case CHECK_PARITY:
-		for (i=disks; i--;)
-			if (i != pd_idx) {
-				ptr[count++] = page_address(sh->dev[i].page);
-				check_xor();
-			}
-		break;
-	case READ_MODIFY_WRITE:
-		for (i = disks; i--;)
-			if (sh->dev[i].written) {
-				ptr[count++] = page_address(sh->dev[i].page);
-				check_xor();
-			}
-	}
-	if (count != 1)
-		xor_block(count, STRIPE_SIZE, ptr);
-	
-	if (method != CHECK_PARITY) {
-		set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-		set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
-	} else
-		clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-}
-
 static void compute_parity6(struct stripe_head *sh, int method)
 {
 	raid6_conf_t *conf = sh->raid_conf;
@@ -1058,7 +1527,7 @@
 	qd_idx = raid6_next_disk(pd_idx, disks);
 	d0_idx = raid6_next_disk(qd_idx, disks);
 
-	PRINTK("compute_parity, stripe %llu, method %d\n",
+	pr_debug("compute_parity, stripe %llu, method %d\n",
 		(unsigned long long)sh->sector, method);
 
 	switch(method) {
@@ -1132,20 +1601,20 @@
 static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
 {
 	int i, count, disks = sh->disks;
-	void *ptr[MAX_XOR_BLOCKS], *p;
+	void *ptr[MAX_XOR_BLOCKS], *dest, *p;
 	int pd_idx = sh->pd_idx;
 	int qd_idx = raid6_next_disk(pd_idx, disks);
 
-	PRINTK("compute_block_1, stripe %llu, idx %d\n",
+	pr_debug("compute_block_1, stripe %llu, idx %d\n",
 		(unsigned long long)sh->sector, dd_idx);
 
 	if ( dd_idx == qd_idx ) {
 		/* We're actually computing the Q drive */
 		compute_parity6(sh, UPDATE_PARITY);
 	} else {
-		ptr[0] = page_address(sh->dev[dd_idx].page);
-		if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
-		count = 1;
+		dest = page_address(sh->dev[dd_idx].page);
+		if (!nozero) memset(dest, 0, STRIPE_SIZE);
+		count = 0;
 		for (i = disks ; i--; ) {
 			if (i == dd_idx || i == qd_idx)
 				continue;
@@ -1159,8 +1628,8 @@
 
 			check_xor();
 		}
-		if (count != 1)
-			xor_block(count, STRIPE_SIZE, ptr);
+		if (count)
+			xor_blocks(count, STRIPE_SIZE, dest, ptr);
 		if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
 		else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
 	}
@@ -1183,7 +1652,7 @@
 	BUG_ON(faila == failb);
 	if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }
 
-	PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
+	pr_debug("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
 	       (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb);
 
 	if ( failb == disks-1 ) {
@@ -1229,7 +1698,79 @@
 	}
 }
 
+static int
+handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
+{
+	int i, pd_idx = sh->pd_idx, disks = sh->disks;
+	int locked = 0;
 
+	if (rcw) {
+		/* if we are not expanding this is a proper write request, and
+		 * there will be bios with new data to be drained into the
+		 * stripe cache
+		 */
+		if (!expand) {
+			set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+			sh->ops.count++;
+		}
+
+		set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+		sh->ops.count++;
+
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+
+			if (dev->towrite) {
+				set_bit(R5_LOCKED, &dev->flags);
+				if (!expand)
+					clear_bit(R5_UPTODATE, &dev->flags);
+				locked++;
+			}
+		}
+	} else {
+		BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
+			test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
+
+		set_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+		set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+		set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+
+		sh->ops.count += 3;
+
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			if (i == pd_idx)
+				continue;
+
+			/* For a read-modify write there may be blocks that are
+			 * locked for reading while others are ready to be
+			 * written so we distinguish these blocks by the
+			 * R5_Wantprexor bit
+			 */
+			if (dev->towrite &&
+			    (test_bit(R5_UPTODATE, &dev->flags) ||
+			    test_bit(R5_Wantcompute, &dev->flags))) {
+				set_bit(R5_Wantprexor, &dev->flags);
+				set_bit(R5_LOCKED, &dev->flags);
+				clear_bit(R5_UPTODATE, &dev->flags);
+				locked++;
+			}
+		}
+	}
+
+	/* keep the parity disk locked while asynchronous operations
+	 * are in flight
+	 */
+	set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);
+	clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+	locked++;
+
+	pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
+		__FUNCTION__, (unsigned long long)sh->sector,
+		locked, sh->ops.pending);
+
+	return locked;
+}
 
 /*
  * Each stripe/dev can have one or more bion attached.
@@ -1242,7 +1783,7 @@
 	raid5_conf_t *conf = sh->raid_conf;
 	int firstwrite=0;
 
-	PRINTK("adding bh b#%llu to stripe s#%llu\n",
+	pr_debug("adding bh b#%llu to stripe s#%llu\n",
 		(unsigned long long)bi->bi_sector,
 		(unsigned long long)sh->sector);
 
@@ -1271,7 +1812,7 @@
 	spin_unlock_irq(&conf->device_lock);
 	spin_unlock(&sh->lock);
 
-	PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n",
+	pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
 		(unsigned long long)bi->bi_sector,
 		(unsigned long long)sh->sector, dd_idx);
 
@@ -1326,6 +1867,729 @@
 	return pd_idx;
 }
 
+static void
+handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
+				struct stripe_head_state *s, int disks,
+				struct bio **return_bi)
+{
+	int i;
+	for (i = disks; i--; ) {
+		struct bio *bi;
+		int bitmap_end = 0;
+
+		if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+			mdk_rdev_t *rdev;
+			rcu_read_lock();
+			rdev = rcu_dereference(conf->disks[i].rdev);
+			if (rdev && test_bit(In_sync, &rdev->flags))
+				/* multiple read failures in one stripe */
+				md_error(conf->mddev, rdev);
+			rcu_read_unlock();
+		}
+		spin_lock_irq(&conf->device_lock);
+		/* fail all writes first */
+		bi = sh->dev[i].towrite;
+		sh->dev[i].towrite = NULL;
+		if (bi) {
+			s->to_write--;
+			bitmap_end = 1;
+		}
+
+		if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+			wake_up(&conf->wait_for_overlap);
+
+		while (bi && bi->bi_sector <
+			sh->dev[i].sector + STRIPE_SECTORS) {
+			struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
+			clear_bit(BIO_UPTODATE, &bi->bi_flags);
+			if (--bi->bi_phys_segments == 0) {
+				md_write_end(conf->mddev);
+				bi->bi_next = *return_bi;
+				*return_bi = bi;
+			}
+			bi = nextbi;
+		}
+		/* and fail all 'written' */
+		bi = sh->dev[i].written;
+		sh->dev[i].written = NULL;
+		if (bi) bitmap_end = 1;
+		while (bi && bi->bi_sector <
+		       sh->dev[i].sector + STRIPE_SECTORS) {
+			struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
+			clear_bit(BIO_UPTODATE, &bi->bi_flags);
+			if (--bi->bi_phys_segments == 0) {
+				md_write_end(conf->mddev);
+				bi->bi_next = *return_bi;
+				*return_bi = bi;
+			}
+			bi = bi2;
+		}
+
+		/* fail any reads if this device is non-operational and
+		 * the data has not reached the cache yet.
+		 */
+		if (!test_bit(R5_Wantfill, &sh->dev[i].flags) &&
+		    (!test_bit(R5_Insync, &sh->dev[i].flags) ||
+		      test_bit(R5_ReadError, &sh->dev[i].flags))) {
+			bi = sh->dev[i].toread;
+			sh->dev[i].toread = NULL;
+			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+				wake_up(&conf->wait_for_overlap);
+			if (bi) s->to_read--;
+			while (bi && bi->bi_sector <
+			       sh->dev[i].sector + STRIPE_SECTORS) {
+				struct bio *nextbi =
+					r5_next_bio(bi, sh->dev[i].sector);
+				clear_bit(BIO_UPTODATE, &bi->bi_flags);
+				if (--bi->bi_phys_segments == 0) {
+					bi->bi_next = *return_bi;
+					*return_bi = bi;
+				}
+				bi = nextbi;
+			}
+		}
+		spin_unlock_irq(&conf->device_lock);
+		if (bitmap_end)
+			bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+					STRIPE_SECTORS, 0, 0);
+	}
+
+}
+
+/* __handle_issuing_new_read_requests5 - returns 0 if there are no more disks
+ * to process
+ */
+static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
+			struct stripe_head_state *s, int disk_idx, int disks)
+{
+	struct r5dev *dev = &sh->dev[disk_idx];
+	struct r5dev *failed_dev = &sh->dev[s->failed_num];
+
+	/* don't schedule compute operations or reads on the parity block while
+	 * a check is in flight
+	 */
+	if ((disk_idx == sh->pd_idx) &&
+	     test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
+		return ~0;
+
+	/* is the data in this block needed, and can we get it? */
+	if (!test_bit(R5_LOCKED, &dev->flags) &&
+	    !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread ||
+	    (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
+	     s->syncing || s->expanding || (s->failed &&
+	     (failed_dev->toread || (failed_dev->towrite &&
+	     !test_bit(R5_OVERWRITE, &failed_dev->flags)
+	     ))))) {
+		/* 1/ We would like to get this block, possibly by computing it,
+		 * but we might not be able to.
+		 *
+		 * 2/ Since parity check operations potentially make the parity
+		 * block !uptodate it will need to be refreshed before any
+		 * compute operations on data disks are scheduled.
+		 *
+		 * 3/ We hold off parity block re-reads until check operations
+		 * have quiesced.
+		 */
+		if ((s->uptodate == disks - 1) &&
+		    !test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
+			set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+			set_bit(R5_Wantcompute, &dev->flags);
+			sh->ops.target = disk_idx;
+			s->req_compute = 1;
+			sh->ops.count++;
+			/* Careful: from this point on 'uptodate' is in the eye
+			 * of raid5_run_ops which services 'compute' operations
+			 * before writes. R5_Wantcompute flags a block that will
+			 * be R5_UPTODATE by the time it is needed for a
+			 * subsequent operation.
+			 */
+			s->uptodate++;
+			return 0; /* uptodate + compute == disks */
+		} else if ((s->uptodate < disks - 1) &&
+			test_bit(R5_Insync, &dev->flags)) {
+			/* Note: we hold off compute operations while checks are
+			 * in flight, but we still prefer 'compute' over 'read'
+			 * hence we only read if (uptodate < * disks-1)
+			 */
+			set_bit(R5_LOCKED, &dev->flags);
+			set_bit(R5_Wantread, &dev->flags);
+			if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+				sh->ops.count++;
+			s->locked++;
+			pr_debug("Reading block %d (sync=%d)\n", disk_idx,
+				s->syncing);
+		}
+	}
+
+	return ~0;
+}
+
+static void handle_issuing_new_read_requests5(struct stripe_head *sh,
+			struct stripe_head_state *s, int disks)
+{
+	int i;
+
+	/* Clear completed compute operations.  Parity recovery
+	 * (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled
+	 * later on in this routine
+	 */
+	if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
+		!test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
+		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+	}
+
+	/* look for blocks to read/compute, skip this if a compute
+	 * is already in flight, or if the stripe contents are in the
+	 * midst of changing due to a write
+	 */
+	if (!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
+		!test_bit(STRIPE_OP_PREXOR, &sh->ops.pending) &&
+		!test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+		for (i = disks; i--; )
+			if (__handle_issuing_new_read_requests5(
+				sh, s, i, disks) == 0)
+				break;
+	}
+	set_bit(STRIPE_HANDLE, &sh->state);
+}
+
+static void handle_issuing_new_read_requests6(struct stripe_head *sh,
+			struct stripe_head_state *s, struct r6_state *r6s,
+			int disks)
+{
+	int i;
+	for (i = disks; i--; ) {
+		struct r5dev *dev = &sh->dev[i];
+		if (!test_bit(R5_LOCKED, &dev->flags) &&
+		    !test_bit(R5_UPTODATE, &dev->flags) &&
+		    (dev->toread || (dev->towrite &&
+		     !test_bit(R5_OVERWRITE, &dev->flags)) ||
+		     s->syncing || s->expanding ||
+		     (s->failed >= 1 &&
+		      (sh->dev[r6s->failed_num[0]].toread ||
+		       s->to_write)) ||
+		     (s->failed >= 2 &&
+		      (sh->dev[r6s->failed_num[1]].toread ||
+		       s->to_write)))) {
+			/* we would like to get this block, possibly
+			 * by computing it, but we might not be able to
+			 */
+			if (s->uptodate == disks-1) {
+				pr_debug("Computing stripe %llu block %d\n",
+				       (unsigned long long)sh->sector, i);
+				compute_block_1(sh, i, 0);
+				s->uptodate++;
+			} else if ( s->uptodate == disks-2 && s->failed >= 2 ) {
+				/* Computing 2-failure is *very* expensive; only
+				 * do it if failed >= 2
+				 */
+				int other;
+				for (other = disks; other--; ) {
+					if (other == i)
+						continue;
+					if (!test_bit(R5_UPTODATE,
+					      &sh->dev[other].flags))
+						break;
+				}
+				BUG_ON(other < 0);
+				pr_debug("Computing stripe %llu blocks %d,%d\n",
+				       (unsigned long long)sh->sector,
+				       i, other);
+				compute_block_2(sh, i, other);
+				s->uptodate += 2;
+			} else if (test_bit(R5_Insync, &dev->flags)) {
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantread, &dev->flags);
+				s->locked++;
+				pr_debug("Reading block %d (sync=%d)\n",
+					i, s->syncing);
+			}
+		}
+	}
+	set_bit(STRIPE_HANDLE, &sh->state);
+}
+
+
+/* handle_completed_write_requests
+ * any written block on an uptodate or failed drive can be returned.
+ * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
+ * never LOCKED, so we don't need to test 'failed' directly.
+ */
+static void handle_completed_write_requests(raid5_conf_t *conf,
+	struct stripe_head *sh, int disks, struct bio **return_bi)
+{
+	int i;
+	struct r5dev *dev;
+
+	for (i = disks; i--; )
+		if (sh->dev[i].written) {
+			dev = &sh->dev[i];
+			if (!test_bit(R5_LOCKED, &dev->flags) &&
+				test_bit(R5_UPTODATE, &dev->flags)) {
+				/* We can return any write requests */
+				struct bio *wbi, *wbi2;
+				int bitmap_end = 0;
+				pr_debug("Return write for disc %d\n", i);
+				spin_lock_irq(&conf->device_lock);
+				wbi = dev->written;
+				dev->written = NULL;
+				while (wbi && wbi->bi_sector <
+					dev->sector + STRIPE_SECTORS) {
+					wbi2 = r5_next_bio(wbi, dev->sector);
+					if (--wbi->bi_phys_segments == 0) {
+						md_write_end(conf->mddev);
+						wbi->bi_next = *return_bi;
+						*return_bi = wbi;
+					}
+					wbi = wbi2;
+				}
+				if (dev->towrite == NULL)
+					bitmap_end = 1;
+				spin_unlock_irq(&conf->device_lock);
+				if (bitmap_end)
+					bitmap_endwrite(conf->mddev->bitmap,
+							sh->sector,
+							STRIPE_SECTORS,
+					 !test_bit(STRIPE_DEGRADED, &sh->state),
+							0);
+			}
+		}
+}
+
+static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
+		struct stripe_head *sh,	struct stripe_head_state *s, int disks)
+{
+	int rmw = 0, rcw = 0, i;
+	for (i = disks; i--; ) {
+		/* would I have to read this buffer for read_modify_write */
+		struct r5dev *dev = &sh->dev[i];
+		if ((dev->towrite || i == sh->pd_idx) &&
+		    !test_bit(R5_LOCKED, &dev->flags) &&
+		    !(test_bit(R5_UPTODATE, &dev->flags) ||
+		      test_bit(R5_Wantcompute, &dev->flags))) {
+			if (test_bit(R5_Insync, &dev->flags))
+				rmw++;
+			else
+				rmw += 2*disks;  /* cannot read it */
+		}
+		/* Would I have to read this buffer for reconstruct_write */
+		if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
+		    !test_bit(R5_LOCKED, &dev->flags) &&
+		    !(test_bit(R5_UPTODATE, &dev->flags) ||
+		    test_bit(R5_Wantcompute, &dev->flags))) {
+			if (test_bit(R5_Insync, &dev->flags)) rcw++;
+			else
+				rcw += 2*disks;
+		}
+	}
+	pr_debug("for sector %llu, rmw=%d rcw=%d\n",
+		(unsigned long long)sh->sector, rmw, rcw);
+	set_bit(STRIPE_HANDLE, &sh->state);
+	if (rmw < rcw && rmw > 0)
+		/* prefer read-modify-write, but need to get some data */
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			if ((dev->towrite || i == sh->pd_idx) &&
+			    !test_bit(R5_LOCKED, &dev->flags) &&
+			    !(test_bit(R5_UPTODATE, &dev->flags) ||
+			    test_bit(R5_Wantcompute, &dev->flags)) &&
+			    test_bit(R5_Insync, &dev->flags)) {
+				if (
+				  test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+					pr_debug("Read_old block "
+						"%d for r-m-w\n", i);
+					set_bit(R5_LOCKED, &dev->flags);
+					set_bit(R5_Wantread, &dev->flags);
+					if (!test_and_set_bit(
+						STRIPE_OP_IO, &sh->ops.pending))
+						sh->ops.count++;
+					s->locked++;
+				} else {
+					set_bit(STRIPE_DELAYED, &sh->state);
+					set_bit(STRIPE_HANDLE, &sh->state);
+				}
+			}
+		}
+	if (rcw <= rmw && rcw > 0)
+		/* want reconstruct write, but need to get some data */
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			if (!test_bit(R5_OVERWRITE, &dev->flags) &&
+			    i != sh->pd_idx &&
+			    !test_bit(R5_LOCKED, &dev->flags) &&
+			    !(test_bit(R5_UPTODATE, &dev->flags) ||
+			    test_bit(R5_Wantcompute, &dev->flags)) &&
+			    test_bit(R5_Insync, &dev->flags)) {
+				if (
+				  test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+					pr_debug("Read_old block "
+						"%d for Reconstruct\n", i);
+					set_bit(R5_LOCKED, &dev->flags);
+					set_bit(R5_Wantread, &dev->flags);
+					if (!test_and_set_bit(
+						STRIPE_OP_IO, &sh->ops.pending))
+						sh->ops.count++;
+					s->locked++;
+				} else {
+					set_bit(STRIPE_DELAYED, &sh->state);
+					set_bit(STRIPE_HANDLE, &sh->state);
+				}
+			}
+		}
+	/* now if nothing is locked, and if we have enough data,
+	 * we can start a write request
+	 */
+	/* since handle_stripe can be called at any time we need to handle the
+	 * case where a compute block operation has been submitted and then a
+	 * subsequent call wants to start a write request.  raid5_run_ops only
+	 * handles the case where compute block and postxor are requested
+	 * simultaneously.  If this is not the case then new writes need to be
+	 * held off until the compute completes.
+	 */
+	if ((s->req_compute ||
+	    !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) &&
+		(s->locked == 0 && (rcw == 0 || rmw == 0) &&
+		!test_bit(STRIPE_BIT_DELAY, &sh->state)))
+		s->locked += handle_write_operations5(sh, rcw == 0, 0);
+}
+
+static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
+		struct stripe_head *sh,	struct stripe_head_state *s,
+		struct r6_state *r6s, int disks)
+{
+	int rcw = 0, must_compute = 0, pd_idx = sh->pd_idx, i;
+	int qd_idx = r6s->qd_idx;
+	for (i = disks; i--; ) {
+		struct r5dev *dev = &sh->dev[i];
+		/* Would I have to read this buffer for reconstruct_write */
+		if (!test_bit(R5_OVERWRITE, &dev->flags)
+		    && i != pd_idx && i != qd_idx
+		    && (!test_bit(R5_LOCKED, &dev->flags)
+			    ) &&
+		    !test_bit(R5_UPTODATE, &dev->flags)) {
+			if (test_bit(R5_Insync, &dev->flags)) rcw++;
+			else {
+				pr_debug("raid6: must_compute: "
+					"disk %d flags=%#lx\n", i, dev->flags);
+				must_compute++;
+			}
+		}
+	}
+	pr_debug("for sector %llu, rcw=%d, must_compute=%d\n",
+	       (unsigned long long)sh->sector, rcw, must_compute);
+	set_bit(STRIPE_HANDLE, &sh->state);
+
+	if (rcw > 0)
+		/* want reconstruct write, but need to get some data */
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			if (!test_bit(R5_OVERWRITE, &dev->flags)
+			    && !(s->failed == 0 && (i == pd_idx || i == qd_idx))
+			    && !test_bit(R5_LOCKED, &dev->flags) &&
+			    !test_bit(R5_UPTODATE, &dev->flags) &&
+			    test_bit(R5_Insync, &dev->flags)) {
+				if (
+				  test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+					pr_debug("Read_old stripe %llu "
+						"block %d for Reconstruct\n",
+					     (unsigned long long)sh->sector, i);
+					set_bit(R5_LOCKED, &dev->flags);
+					set_bit(R5_Wantread, &dev->flags);
+					s->locked++;
+				} else {
+					pr_debug("Request delayed stripe %llu "
+						"block %d for Reconstruct\n",
+					     (unsigned long long)sh->sector, i);
+					set_bit(STRIPE_DELAYED, &sh->state);
+					set_bit(STRIPE_HANDLE, &sh->state);
+				}
+			}
+		}
+	/* now if nothing is locked, and if we have enough data, we can start a
+	 * write request
+	 */
+	if (s->locked == 0 && rcw == 0 &&
+	    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
+		if (must_compute > 0) {
+			/* We have failed blocks and need to compute them */
+			switch (s->failed) {
+			case 0:
+				BUG();
+			case 1:
+				compute_block_1(sh, r6s->failed_num[0], 0);
+				break;
+			case 2:
+				compute_block_2(sh, r6s->failed_num[0],
+						r6s->failed_num[1]);
+				break;
+			default: /* This request should have been failed? */
+				BUG();
+			}
+		}
+
+		pr_debug("Computing parity for stripe %llu\n",
+			(unsigned long long)sh->sector);
+		compute_parity6(sh, RECONSTRUCT_WRITE);
+		/* now every locked buffer is ready to be written */
+		for (i = disks; i--; )
+			if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
+				pr_debug("Writing stripe %llu block %d\n",
+				       (unsigned long long)sh->sector, i);
+				s->locked++;
+				set_bit(R5_Wantwrite, &sh->dev[i].flags);
+			}
+		/* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
+		set_bit(STRIPE_INSYNC, &sh->state);
+
+		if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+			atomic_dec(&conf->preread_active_stripes);
+			if (atomic_read(&conf->preread_active_stripes) <
+			    IO_THRESHOLD)
+				md_wakeup_thread(conf->mddev->thread);
+		}
+	}
+}
+
+static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
+				struct stripe_head_state *s, int disks)
+{
+	set_bit(STRIPE_HANDLE, &sh->state);
+	/* Take one of the following actions:
+	 * 1/ start a check parity operation if (uptodate == disks)
+	 * 2/ finish a check parity operation and act on the result
+	 * 3/ skip to the writeback section if we previously
+	 *    initiated a recovery operation
+	 */
+	if (s->failed == 0 &&
+	    !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+		if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
+			BUG_ON(s->uptodate != disks);
+			clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
+			sh->ops.count++;
+			s->uptodate--;
+		} else if (
+		       test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) {
+			clear_bit(STRIPE_OP_CHECK, &sh->ops.ack);
+			clear_bit(STRIPE_OP_CHECK, &sh->ops.pending);
+
+			if (sh->ops.zero_sum_result == 0)
+				/* parity is correct (on disc,
+				 * not in buffer any more)
+				 */
+				set_bit(STRIPE_INSYNC, &sh->state);
+			else {
+				conf->mddev->resync_mismatches +=
+					STRIPE_SECTORS;
+				if (test_bit(
+				     MD_RECOVERY_CHECK, &conf->mddev->recovery))
+					/* don't try to repair!! */
+					set_bit(STRIPE_INSYNC, &sh->state);
+				else {
+					set_bit(STRIPE_OP_COMPUTE_BLK,
+						&sh->ops.pending);
+					set_bit(STRIPE_OP_MOD_REPAIR_PD,
+						&sh->ops.pending);
+					set_bit(R5_Wantcompute,
+						&sh->dev[sh->pd_idx].flags);
+					sh->ops.target = sh->pd_idx;
+					sh->ops.count++;
+					s->uptodate++;
+				}
+			}
+		}
+	}
+
+	/* check if we can clear a parity disk reconstruct */
+	if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
+		test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+
+		clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending);
+		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
+		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+	}
+
+	/* Wait for check parity and compute block operations to complete
+	 * before write-back
+	 */
+	if (!test_bit(STRIPE_INSYNC, &sh->state) &&
+		!test_bit(STRIPE_OP_CHECK, &sh->ops.pending) &&
+		!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) {
+		struct r5dev *dev;
+		/* either failed parity check, or recovery is happening */
+		if (s->failed == 0)
+			s->failed_num = sh->pd_idx;
+		dev = &sh->dev[s->failed_num];
+		BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
+		BUG_ON(s->uptodate != disks);
+
+		set_bit(R5_LOCKED, &dev->flags);
+		set_bit(R5_Wantwrite, &dev->flags);
+		if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+			sh->ops.count++;
+
+		clear_bit(STRIPE_DEGRADED, &sh->state);
+		s->locked++;
+		set_bit(STRIPE_INSYNC, &sh->state);
+	}
+}
+
+
+static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
+				struct stripe_head_state *s,
+				struct r6_state *r6s, struct page *tmp_page,
+				int disks)
+{
+	int update_p = 0, update_q = 0;
+	struct r5dev *dev;
+	int pd_idx = sh->pd_idx;
+	int qd_idx = r6s->qd_idx;
+
+	set_bit(STRIPE_HANDLE, &sh->state);
+
+	BUG_ON(s->failed > 2);
+	BUG_ON(s->uptodate < disks);
+	/* Want to check and possibly repair P and Q.
+	 * However there could be one 'failed' device, in which
+	 * case we can only check one of them, possibly using the
+	 * other to generate missing data
+	 */
+
+	/* If !tmp_page, we cannot do the calculations,
+	 * but as we have set STRIPE_HANDLE, we will soon be called
+	 * by stripe_handle with a tmp_page - just wait until then.
+	 */
+	if (tmp_page) {
+		if (s->failed == r6s->q_failed) {
+			/* The only possible failed device holds 'Q', so it
+			 * makes sense to check P (If anything else were failed,
+			 * we would have used P to recreate it).
+			 */
+			compute_block_1(sh, pd_idx, 1);
+			if (!page_is_zero(sh->dev[pd_idx].page)) {
+				compute_block_1(sh, pd_idx, 0);
+				update_p = 1;
+			}
+		}
+		if (!r6s->q_failed && s->failed < 2) {
+			/* q is not failed, and we didn't use it to generate
+			 * anything, so it makes sense to check it
+			 */
+			memcpy(page_address(tmp_page),
+			       page_address(sh->dev[qd_idx].page),
+			       STRIPE_SIZE);
+			compute_parity6(sh, UPDATE_PARITY);
+			if (memcmp(page_address(tmp_page),
+				   page_address(sh->dev[qd_idx].page),
+				   STRIPE_SIZE) != 0) {
+				clear_bit(STRIPE_INSYNC, &sh->state);
+				update_q = 1;
+			}
+		}
+		if (update_p || update_q) {
+			conf->mddev->resync_mismatches += STRIPE_SECTORS;
+			if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+				/* don't try to repair!! */
+				update_p = update_q = 0;
+		}
+
+		/* now write out any block on a failed drive,
+		 * or P or Q if they need it
+		 */
+
+		if (s->failed == 2) {
+			dev = &sh->dev[r6s->failed_num[1]];
+			s->locked++;
+			set_bit(R5_LOCKED, &dev->flags);
+			set_bit(R5_Wantwrite, &dev->flags);
+		}
+		if (s->failed >= 1) {
+			dev = &sh->dev[r6s->failed_num[0]];
+			s->locked++;
+			set_bit(R5_LOCKED, &dev->flags);
+			set_bit(R5_Wantwrite, &dev->flags);
+		}
+
+		if (update_p) {
+			dev = &sh->dev[pd_idx];
+			s->locked++;
+			set_bit(R5_LOCKED, &dev->flags);
+			set_bit(R5_Wantwrite, &dev->flags);
+		}
+		if (update_q) {
+			dev = &sh->dev[qd_idx];
+			s->locked++;
+			set_bit(R5_LOCKED, &dev->flags);
+			set_bit(R5_Wantwrite, &dev->flags);
+		}
+		clear_bit(STRIPE_DEGRADED, &sh->state);
+
+		set_bit(STRIPE_INSYNC, &sh->state);
+	}
+}
+
+static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
+				struct r6_state *r6s)
+{
+	int i;
+
+	/* We have read all the blocks in this stripe and now we need to
+	 * copy some of them into a target stripe for expand.
+	 */
+	struct dma_async_tx_descriptor *tx = NULL;
+	clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+	for (i = 0; i < sh->disks; i++)
+		if (i != sh->pd_idx && (r6s && i != r6s->qd_idx)) {
+			int dd_idx, pd_idx, j;
+			struct stripe_head *sh2;
+
+			sector_t bn = compute_blocknr(sh, i);
+			sector_t s = raid5_compute_sector(bn, conf->raid_disks,
+						conf->raid_disks -
+						conf->max_degraded, &dd_idx,
+						&pd_idx, conf);
+			sh2 = get_active_stripe(conf, s, conf->raid_disks,
+						pd_idx, 1);
+			if (sh2 == NULL)
+				/* so far only the early blocks of this stripe
+				 * have been requested.  When later blocks
+				 * get requested, we will try again
+				 */
+				continue;
+			if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
+			   test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
+				/* must have already done this block */
+				release_stripe(sh2);
+				continue;
+			}
+
+			/* place all the copies on one channel */
+			tx = async_memcpy(sh2->dev[dd_idx].page,
+				sh->dev[i].page, 0, 0, STRIPE_SIZE,
+				ASYNC_TX_DEP_ACK, tx, NULL, NULL);
+
+			set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
+			set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
+			for (j = 0; j < conf->raid_disks; j++)
+				if (j != sh2->pd_idx &&
+				    (r6s && j != r6s->qd_idx) &&
+				    !test_bit(R5_Expanded, &sh2->dev[j].flags))
+					break;
+			if (j == conf->raid_disks) {
+				set_bit(STRIPE_EXPAND_READY, &sh2->state);
+				set_bit(STRIPE_HANDLE, &sh2->state);
+			}
+			release_stripe(sh2);
+
+			/* done submitting copies, wait for them to complete */
+			if (i + 1 >= sh->disks) {
+				async_tx_ack(tx);
+				dma_wait_for_async_tx(tx);
+			}
+		}
+}
 
 /*
  * handle_stripe - do things to a stripe.
@@ -1339,81 +2603,70 @@
  *    schedule a write of some buffers
  *    return confirmation of parity correctness
  *
- * Parity calculations are done inside the stripe lock
  * buffers are taken off read_list or write_list, and bh_cache buffers
  * get BH_Lock set before the stripe lock is released.
  *
  */
- 
+
 static void handle_stripe5(struct stripe_head *sh)
 {
 	raid5_conf_t *conf = sh->raid_conf;
-	int disks = sh->disks;
-	struct bio *return_bi= NULL;
-	struct bio *bi;
-	int i;
-	int syncing, expanding, expanded;
-	int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
-	int non_overwrite = 0;
-	int failed_num=0;
+	int disks = sh->disks, i;
+	struct bio *return_bi = NULL;
+	struct stripe_head_state s;
 	struct r5dev *dev;
+	unsigned long pending = 0;
 
-	PRINTK("handling stripe %llu, cnt=%d, pd_idx=%d\n",
-		(unsigned long long)sh->sector, atomic_read(&sh->count),
-		sh->pd_idx);
+	memset(&s, 0, sizeof(s));
+	pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
+		"ops=%lx:%lx:%lx\n", (unsigned long long)sh->sector, sh->state,
+		atomic_read(&sh->count), sh->pd_idx,
+		sh->ops.pending, sh->ops.ack, sh->ops.complete);
 
 	spin_lock(&sh->lock);
 	clear_bit(STRIPE_HANDLE, &sh->state);
 	clear_bit(STRIPE_DELAYED, &sh->state);
 
-	syncing = test_bit(STRIPE_SYNCING, &sh->state);
-	expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-	expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+	s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
+	s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+	s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
 	/* Now to look around and see what can be done */
 
 	rcu_read_lock();
 	for (i=disks; i--; ) {
 		mdk_rdev_t *rdev;
-		dev = &sh->dev[i];
+		struct r5dev *dev = &sh->dev[i];
 		clear_bit(R5_Insync, &dev->flags);
 
-		PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
-			i, dev->flags, dev->toread, dev->towrite, dev->written);
-		/* maybe we can reply to a read */
-		if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
-			struct bio *rbi, *rbi2;
-			PRINTK("Return read for disc %d\n", i);
-			spin_lock_irq(&conf->device_lock);
-			rbi = dev->toread;
-			dev->toread = NULL;
-			if (test_and_clear_bit(R5_Overlap, &dev->flags))
-				wake_up(&conf->wait_for_overlap);
-			spin_unlock_irq(&conf->device_lock);
-			while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-				copy_data(0, rbi, dev->page, dev->sector);
-				rbi2 = r5_next_bio(rbi, dev->sector);
-				spin_lock_irq(&conf->device_lock);
-				if (--rbi->bi_phys_segments == 0) {
-					rbi->bi_next = return_bi;
-					return_bi = rbi;
-				}
-				spin_unlock_irq(&conf->device_lock);
-				rbi = rbi2;
-			}
-		}
+		pr_debug("check %d: state 0x%lx toread %p read %p write %p "
+			"written %p\n",	i, dev->flags, dev->toread, dev->read,
+			dev->towrite, dev->written);
+
+		/* maybe we can request a biofill operation
+		 *
+		 * new wantfill requests are only permitted while
+		 * STRIPE_OP_BIOFILL is clear
+		 */
+		if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&
+			!test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+			set_bit(R5_Wantfill, &dev->flags);
 
 		/* now count some things */
-		if (test_bit(R5_LOCKED, &dev->flags)) locked++;
-		if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
+		if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
+		if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
+		if (test_bit(R5_Wantcompute, &dev->flags)) s.compute++;
 
-		
-		if (dev->toread) to_read++;
+		if (test_bit(R5_Wantfill, &dev->flags))
+			s.to_fill++;
+		else if (dev->toread)
+			s.to_read++;
 		if (dev->towrite) {
-			to_write++;
+			s.to_write++;
 			if (!test_bit(R5_OVERWRITE, &dev->flags))
-				non_overwrite++;
+				s.non_overwrite++;
 		}
-		if (dev->written) written++;
+		if (dev->written)
+			s.written++;
 		rdev = rcu_dereference(conf->disks[i].rdev);
 		if (!rdev || !test_bit(In_sync, &rdev->flags)) {
 			/* The ReadError flag will just be confusing now */
@@ -1422,306 +2675,131 @@
 		}
 		if (!rdev || !test_bit(In_sync, &rdev->flags)
 		    || test_bit(R5_ReadError, &dev->flags)) {
-			failed++;
-			failed_num = i;
+			s.failed++;
+			s.failed_num = i;
 		} else
 			set_bit(R5_Insync, &dev->flags);
 	}
 	rcu_read_unlock();
-	PRINTK("locked=%d uptodate=%d to_read=%d"
+
+	if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+		sh->ops.count++;
+
+	pr_debug("locked=%d uptodate=%d to_read=%d"
 		" to_write=%d failed=%d failed_num=%d\n",
-		locked, uptodate, to_read, to_write, failed, failed_num);
+		s.locked, s.uptodate, s.to_read, s.to_write,
+		s.failed, s.failed_num);
 	/* check if the array has lost two devices and, if so, some requests might
 	 * need to be failed
 	 */
-	if (failed > 1 && to_read+to_write+written) {
-		for (i=disks; i--; ) {
-			int bitmap_end = 0;
-
-			if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-				mdk_rdev_t *rdev;
-				rcu_read_lock();
-				rdev = rcu_dereference(conf->disks[i].rdev);
-				if (rdev && test_bit(In_sync, &rdev->flags))
-					/* multiple read failures in one stripe */
-					md_error(conf->mddev, rdev);
-				rcu_read_unlock();
-			}
-
-			spin_lock_irq(&conf->device_lock);
-			/* fail all writes first */
-			bi = sh->dev[i].towrite;
-			sh->dev[i].towrite = NULL;
-			if (bi) { to_write--; bitmap_end = 1; }
-
-			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-				wake_up(&conf->wait_for_overlap);
-
-			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-				struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-				clear_bit(BIO_UPTODATE, &bi->bi_flags);
-				if (--bi->bi_phys_segments == 0) {
-					md_write_end(conf->mddev);
-					bi->bi_next = return_bi;
-					return_bi = bi;
-				}
-				bi = nextbi;
-			}
-			/* and fail all 'written' */
-			bi = sh->dev[i].written;
-			sh->dev[i].written = NULL;
-			if (bi) bitmap_end = 1;
-			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
-				struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
-				clear_bit(BIO_UPTODATE, &bi->bi_flags);
-				if (--bi->bi_phys_segments == 0) {
-					md_write_end(conf->mddev);
-					bi->bi_next = return_bi;
-					return_bi = bi;
-				}
-				bi = bi2;
-			}
-
-			/* fail any reads if this device is non-operational */
-			if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
-			    test_bit(R5_ReadError, &sh->dev[i].flags)) {
-				bi = sh->dev[i].toread;
-				sh->dev[i].toread = NULL;
-				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-					wake_up(&conf->wait_for_overlap);
-				if (bi) to_read--;
-				while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-					struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-					clear_bit(BIO_UPTODATE, &bi->bi_flags);
-					if (--bi->bi_phys_segments == 0) {
-						bi->bi_next = return_bi;
-						return_bi = bi;
-					}
-					bi = nextbi;
-				}
-			}
-			spin_unlock_irq(&conf->device_lock);
-			if (bitmap_end)
-				bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-						STRIPE_SECTORS, 0, 0);
-		}
-	}
-	if (failed > 1 && syncing) {
+	if (s.failed > 1 && s.to_read+s.to_write+s.written)
+		handle_requests_to_failed_array(conf, sh, &s, disks,
+						&return_bi);
+	if (s.failed > 1 && s.syncing) {
 		md_done_sync(conf->mddev, STRIPE_SECTORS,0);
 		clear_bit(STRIPE_SYNCING, &sh->state);
-		syncing = 0;
+		s.syncing = 0;
 	}
 
 	/* might be able to return some write requests if the parity block
 	 * is safe, or on a failed drive
 	 */
 	dev = &sh->dev[sh->pd_idx];
-	if ( written &&
-	     ( (test_bit(R5_Insync, &dev->flags) && !test_bit(R5_LOCKED, &dev->flags) &&
-		test_bit(R5_UPTODATE, &dev->flags))
-	       || (failed == 1 && failed_num == sh->pd_idx))
-	    ) {
-	    /* any written block on an uptodate or failed drive can be returned.
-	     * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but 
-	     * never LOCKED, so we don't need to test 'failed' directly.
-	     */
-	    for (i=disks; i--; )
-		if (sh->dev[i].written) {
-		    dev = &sh->dev[i];
-		    if (!test_bit(R5_LOCKED, &dev->flags) &&
-			 test_bit(R5_UPTODATE, &dev->flags) ) {
-			/* We can return any write requests */
-			    struct bio *wbi, *wbi2;
-			    int bitmap_end = 0;
-			    PRINTK("Return write for disc %d\n", i);
-			    spin_lock_irq(&conf->device_lock);
-			    wbi = dev->written;
-			    dev->written = NULL;
-			    while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-				    wbi2 = r5_next_bio(wbi, dev->sector);
-				    if (--wbi->bi_phys_segments == 0) {
-					    md_write_end(conf->mddev);
-					    wbi->bi_next = return_bi;
-					    return_bi = wbi;
-				    }
-				    wbi = wbi2;
-			    }
-			    if (dev->towrite == NULL)
-				    bitmap_end = 1;
-			    spin_unlock_irq(&conf->device_lock);
-			    if (bitmap_end)
-				    bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-						    STRIPE_SECTORS,
-						    !test_bit(STRIPE_DEGRADED, &sh->state), 0);
-		    }
-		}
-	}
+	if ( s.written &&
+	     ((test_bit(R5_Insync, &dev->flags) &&
+	       !test_bit(R5_LOCKED, &dev->flags) &&
+	       test_bit(R5_UPTODATE, &dev->flags)) ||
+	       (s.failed == 1 && s.failed_num == sh->pd_idx)))
+		handle_completed_write_requests(conf, sh, disks, &return_bi);
 
 	/* Now we might consider reading some blocks, either to check/generate
 	 * parity, or to satisfy requests
 	 * or to load a block that is being partially written.
 	 */
-	if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) {
-		for (i=disks; i--;) {
-			dev = &sh->dev[i];
-			if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-			    (dev->toread ||
-			     (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
-			     syncing ||
-			     expanding ||
-			     (failed && (sh->dev[failed_num].toread ||
-					 (sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags))))
-				    )
-				) {
-				/* we would like to get this block, possibly
-				 * by computing it, but we might not be able to
-				 */
-				if (uptodate == disks-1) {
-					PRINTK("Computing block %d\n", i);
-					compute_block(sh, i);
-					uptodate++;
-				} else if (test_bit(R5_Insync, &dev->flags)) {
-					set_bit(R5_LOCKED, &dev->flags);
-					set_bit(R5_Wantread, &dev->flags);
-					locked++;
-					PRINTK("Reading block %d (sync=%d)\n", 
-						i, syncing);
-				}
-			}
-		}
-		set_bit(STRIPE_HANDLE, &sh->state);
+	if (s.to_read || s.non_overwrite ||
+	    (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding ||
+	    test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+		handle_issuing_new_read_requests5(sh, &s, disks);
+
+	/* Now we check to see if any write operations have recently
+	 * completed
+	 */
+
+	/* leave prexor set until postxor is done, allows us to distinguish
+	 * a rmw from a rcw during biodrain
+	 */
+	if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) &&
+		test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+
+		clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+		clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack);
+		clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+
+		for (i = disks; i--; )
+			clear_bit(R5_Wantprexor, &sh->dev[i].flags);
 	}
 
-	/* now to consider writing and what else, if anything should be read */
-	if (to_write) {
-		int rmw=0, rcw=0;
-		for (i=disks ; i--;) {
-			/* would I have to read this buffer for read_modify_write */
+	/* if only POSTXOR is set then this is an 'expand' postxor */
+	if (test_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete) &&
+		test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+
+		clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
+		clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.ack);
+		clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+
+		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
+		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+
+		/* All the 'written' buffers and the parity block are ready to
+		 * be written back to disk
+		 */
+		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
+		for (i = disks; i--; ) {
 			dev = &sh->dev[i];
-			if ((dev->towrite || i == sh->pd_idx) &&
-			    (!test_bit(R5_LOCKED, &dev->flags) 
-				    ) &&
-			    !test_bit(R5_UPTODATE, &dev->flags)) {
-				if (test_bit(R5_Insync, &dev->flags)
-/*				    && !(!mddev->insync && i == sh->pd_idx) */
-					)
-					rmw++;
-				else rmw += 2*disks;  /* cannot read it */
-			}
-			/* Would I have to read this buffer for reconstruct_write */
-			if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
-			    (!test_bit(R5_LOCKED, &dev->flags) 
-				    ) &&
-			    !test_bit(R5_UPTODATE, &dev->flags)) {
-				if (test_bit(R5_Insync, &dev->flags)) rcw++;
-				else rcw += 2*disks;
+			if (test_bit(R5_LOCKED, &dev->flags) &&
+				(i == sh->pd_idx || dev->written)) {
+				pr_debug("Writing block %d\n", i);
+				set_bit(R5_Wantwrite, &dev->flags);
+				if (!test_and_set_bit(
+				    STRIPE_OP_IO, &sh->ops.pending))
+					sh->ops.count++;
+				if (!test_bit(R5_Insync, &dev->flags) ||
+				    (i == sh->pd_idx && s.failed == 0))
+					set_bit(STRIPE_INSYNC, &sh->state);
 			}
 		}
-		PRINTK("for sector %llu, rmw=%d rcw=%d\n", 
-			(unsigned long long)sh->sector, rmw, rcw);
-		set_bit(STRIPE_HANDLE, &sh->state);
-		if (rmw < rcw && rmw > 0)
-			/* prefer read-modify-write, but need to get some data */
-			for (i=disks; i--;) {
-				dev = &sh->dev[i];
-				if ((dev->towrite || i == sh->pd_idx) &&
-				    !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-				    test_bit(R5_Insync, &dev->flags)) {
-					if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-					{
-						PRINTK("Read_old block %d for r-m-w\n", i);
-						set_bit(R5_LOCKED, &dev->flags);
-						set_bit(R5_Wantread, &dev->flags);
-						locked++;
-					} else {
-						set_bit(STRIPE_DELAYED, &sh->state);
-						set_bit(STRIPE_HANDLE, &sh->state);
-					}
-				}
-			}
-		if (rcw <= rmw && rcw > 0)
-			/* want reconstruct write, but need to get some data */
-			for (i=disks; i--;) {
-				dev = &sh->dev[i];
-				if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
-				    !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-				    test_bit(R5_Insync, &dev->flags)) {
-					if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-					{
-						PRINTK("Read_old block %d for Reconstruct\n", i);
-						set_bit(R5_LOCKED, &dev->flags);
-						set_bit(R5_Wantread, &dev->flags);
-						locked++;
-					} else {
-						set_bit(STRIPE_DELAYED, &sh->state);
-						set_bit(STRIPE_HANDLE, &sh->state);
-					}
-				}
-			}
-		/* now if nothing is locked, and if we have enough data, we can start a write request */
-		if (locked == 0 && (rcw == 0 ||rmw == 0) &&
-		    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
-			PRINTK("Computing parity...\n");
-			compute_parity5(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
-			/* now every locked buffer is ready to be written */
-			for (i=disks; i--;)
-				if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
-					PRINTK("Writing block %d\n", i);
-					locked++;
-					set_bit(R5_Wantwrite, &sh->dev[i].flags);
-					if (!test_bit(R5_Insync, &sh->dev[i].flags)
-					    || (i==sh->pd_idx && failed == 0))
-						set_bit(STRIPE_INSYNC, &sh->state);
-				}
-			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-				atomic_dec(&conf->preread_active_stripes);
-				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-					md_wakeup_thread(conf->mddev->thread);
-			}
+		if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+			atomic_dec(&conf->preread_active_stripes);
+			if (atomic_read(&conf->preread_active_stripes) <
+				IO_THRESHOLD)
+				md_wakeup_thread(conf->mddev->thread);
 		}
 	}
 
+	/* Now to consider new write requests and what else, if anything
+	 * should be read.  We do not handle new writes when:
+	 * 1/ A 'write' operation (copy+xor) is already in flight.
+	 * 2/ A 'check' operation is in flight, as it may clobber the parity
+	 *    block.
+	 */
+	if (s.to_write && !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending) &&
+			  !test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
+		handle_issuing_new_write_requests5(conf, sh, &s, disks);
+
 	/* maybe we need to check and possibly fix the parity for this stripe
-	 * Any reads will already have been scheduled, so we just see if enough data
-	 * is available
+	 * Any reads will already have been scheduled, so we just see if enough
+	 * data is available.  The parity check is held off while parity
+	 * dependent operations are in flight.
 	 */
-	if (syncing && locked == 0 &&
-	    !test_bit(STRIPE_INSYNC, &sh->state)) {
-		set_bit(STRIPE_HANDLE, &sh->state);
-		if (failed == 0) {
-			BUG_ON(uptodate != disks);
-			compute_parity5(sh, CHECK_PARITY);
-			uptodate--;
-			if (page_is_zero(sh->dev[sh->pd_idx].page)) {
-				/* parity is correct (on disc, not in buffer any more) */
-				set_bit(STRIPE_INSYNC, &sh->state);
-			} else {
-				conf->mddev->resync_mismatches += STRIPE_SECTORS;
-				if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
-					/* don't try to repair!! */
-					set_bit(STRIPE_INSYNC, &sh->state);
-				else {
-					compute_block(sh, sh->pd_idx);
-					uptodate++;
-				}
-			}
-		}
-		if (!test_bit(STRIPE_INSYNC, &sh->state)) {
-			/* either failed parity check, or recovery is happening */
-			if (failed==0)
-				failed_num = sh->pd_idx;
-			dev = &sh->dev[failed_num];
-			BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
-			BUG_ON(uptodate != disks);
+	if ((s.syncing && s.locked == 0 &&
+	     !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
+	     !test_bit(STRIPE_INSYNC, &sh->state)) ||
+	      test_bit(STRIPE_OP_CHECK, &sh->ops.pending) ||
+	      test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending))
+		handle_parity_checks5(conf, sh, &s, disks);
 
-			set_bit(R5_LOCKED, &dev->flags);
-			set_bit(R5_Wantwrite, &dev->flags);
-			clear_bit(STRIPE_DEGRADED, &sh->state);
-			locked++;
-			set_bit(STRIPE_INSYNC, &sh->state);
-		}
-	}
-	if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+	if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
 		md_done_sync(conf->mddev, STRIPE_SECTORS,1);
 		clear_bit(STRIPE_SYNCING, &sh->state);
 	}
@@ -1729,186 +2807,102 @@
 	/* If the failed drive is just a ReadError, then we might need to progress
 	 * the repair/check process
 	 */
-	if (failed == 1 && ! conf->mddev->ro &&
-	    test_bit(R5_ReadError, &sh->dev[failed_num].flags)
-	    && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags)
-	    && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)
+	if (s.failed == 1 && !conf->mddev->ro &&
+	    test_bit(R5_ReadError, &sh->dev[s.failed_num].flags)
+	    && !test_bit(R5_LOCKED, &sh->dev[s.failed_num].flags)
+	    && test_bit(R5_UPTODATE, &sh->dev[s.failed_num].flags)
 		) {
-		dev = &sh->dev[failed_num];
+		dev = &sh->dev[s.failed_num];
 		if (!test_bit(R5_ReWrite, &dev->flags)) {
 			set_bit(R5_Wantwrite, &dev->flags);
+			if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+				sh->ops.count++;
 			set_bit(R5_ReWrite, &dev->flags);
 			set_bit(R5_LOCKED, &dev->flags);
-			locked++;
+			s.locked++;
 		} else {
 			/* let's read it back */
 			set_bit(R5_Wantread, &dev->flags);
+			if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+				sh->ops.count++;
 			set_bit(R5_LOCKED, &dev->flags);
-			locked++;
+			s.locked++;
 		}
 	}
 
-	if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
+	/* Finish postxor operations initiated by the expansion
+	 * process
+	 */
+	if (test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete) &&
+		!test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending)) {
+
+		clear_bit(STRIPE_EXPANDING, &sh->state);
+
+		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
+		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+
+		for (i = conf->raid_disks; i--; ) {
+			set_bit(R5_Wantwrite, &sh->dev[i].flags);
+			if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+				sh->ops.count++;
+		}
+	}
+
+	if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
+		!test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
 		/* Need to write out all blocks after computing parity */
 		sh->disks = conf->raid_disks;
-		sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks);
-		compute_parity5(sh, RECONSTRUCT_WRITE);
-		for (i= conf->raid_disks; i--;) {
-			set_bit(R5_LOCKED, &sh->dev[i].flags);
-			locked++;
-			set_bit(R5_Wantwrite, &sh->dev[i].flags);
-		}
-		clear_bit(STRIPE_EXPANDING, &sh->state);
-	} else if (expanded) {
+		sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
+			conf->raid_disks);
+		s.locked += handle_write_operations5(sh, 0, 1);
+	} else if (s.expanded &&
+		!test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
 		clear_bit(STRIPE_EXPAND_READY, &sh->state);
 		atomic_dec(&conf->reshape_stripes);
 		wake_up(&conf->wait_for_overlap);
 		md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
 	}
 
-	if (expanding && locked == 0) {
-		/* We have read all the blocks in this stripe and now we need to
-		 * copy some of them into a target stripe for expand.
-		 */
-		clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-		for (i=0; i< sh->disks; i++)
-			if (i != sh->pd_idx) {
-				int dd_idx, pd_idx, j;
-				struct stripe_head *sh2;
+	if (s.expanding && s.locked == 0)
+		handle_stripe_expansion(conf, sh, NULL);
 
-				sector_t bn = compute_blocknr(sh, i);
-				sector_t s = raid5_compute_sector(bn, conf->raid_disks,
-								  conf->raid_disks-1,
-								  &dd_idx, &pd_idx, conf);
-				sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1);
-				if (sh2 == NULL)
-					/* so far only the early blocks of this stripe
-					 * have been requested.  When later blocks
-					 * get requested, we will try again
-					 */
-					continue;
-				if(!test_bit(STRIPE_EXPANDING, &sh2->state) ||
-				   test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
-					/* must have already done this block */
-					release_stripe(sh2);
-					continue;
-				}
-				memcpy(page_address(sh2->dev[dd_idx].page),
-				       page_address(sh->dev[i].page),
-				       STRIPE_SIZE);
-				set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
-				set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
-				for (j=0; j<conf->raid_disks; j++)
-					if (j != sh2->pd_idx &&
-					    !test_bit(R5_Expanded, &sh2->dev[j].flags))
-						break;
-				if (j == conf->raid_disks) {
-					set_bit(STRIPE_EXPAND_READY, &sh2->state);
-					set_bit(STRIPE_HANDLE, &sh2->state);
-				}
-				release_stripe(sh2);
-			}
-	}
+	if (sh->ops.count)
+		pending = get_stripe_work(sh);
 
 	spin_unlock(&sh->lock);
 
-	while ((bi=return_bi)) {
-		int bytes = bi->bi_size;
+	if (pending)
+		raid5_run_ops(sh, pending);
 
-		return_bi = bi->bi_next;
-		bi->bi_next = NULL;
-		bi->bi_size = 0;
-		bi->bi_end_io(bi, bytes,
-			      test_bit(BIO_UPTODATE, &bi->bi_flags)
-			        ? 0 : -EIO);
-	}
-	for (i=disks; i-- ;) {
-		int rw;
-		struct bio *bi;
-		mdk_rdev_t *rdev;
-		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-			rw = WRITE;
-		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
-			rw = READ;
-		else
-			continue;
- 
-		bi = &sh->dev[i].req;
- 
-		bi->bi_rw = rw;
-		if (rw == WRITE)
-			bi->bi_end_io = raid5_end_write_request;
-		else
-			bi->bi_end_io = raid5_end_read_request;
- 
-		rcu_read_lock();
-		rdev = rcu_dereference(conf->disks[i].rdev);
-		if (rdev && test_bit(Faulty, &rdev->flags))
-			rdev = NULL;
-		if (rdev)
-			atomic_inc(&rdev->nr_pending);
-		rcu_read_unlock();
- 
-		if (rdev) {
-			if (syncing || expanding || expanded)
-				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
+	return_io(return_bi);
 
-			bi->bi_bdev = rdev->bdev;
-			PRINTK("for %llu schedule op %ld on disc %d\n",
-				(unsigned long long)sh->sector, bi->bi_rw, i);
-			atomic_inc(&sh->count);
-			bi->bi_sector = sh->sector + rdev->data_offset;
-			bi->bi_flags = 1 << BIO_UPTODATE;
-			bi->bi_vcnt = 1;	
-			bi->bi_max_vecs = 1;
-			bi->bi_idx = 0;
-			bi->bi_io_vec = &sh->dev[i].vec;
-			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
-			bi->bi_io_vec[0].bv_offset = 0;
-			bi->bi_size = STRIPE_SIZE;
-			bi->bi_next = NULL;
-			if (rw == WRITE &&
-			    test_bit(R5_ReWrite, &sh->dev[i].flags))
-				atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
-			generic_make_request(bi);
-		} else {
-			if (rw == WRITE)
-				set_bit(STRIPE_DEGRADED, &sh->state);
-			PRINTK("skip op %ld on disc %d for sector %llu\n",
-				bi->bi_rw, i, (unsigned long long)sh->sector);
-			clear_bit(R5_LOCKED, &sh->dev[i].flags);
-			set_bit(STRIPE_HANDLE, &sh->state);
-		}
-	}
 }
 
 static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
 {
 	raid6_conf_t *conf = sh->raid_conf;
 	int disks = sh->disks;
-	struct bio *return_bi= NULL;
-	struct bio *bi;
-	int i;
-	int syncing, expanding, expanded;
-	int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
-	int non_overwrite = 0;
-	int failed_num[2] = {0, 0};
+	struct bio *return_bi = NULL;
+	int i, pd_idx = sh->pd_idx;
+	struct stripe_head_state s;
+	struct r6_state r6s;
 	struct r5dev *dev, *pdev, *qdev;
-	int pd_idx = sh->pd_idx;
-	int qd_idx = raid6_next_disk(pd_idx, disks);
-	int p_failed, q_failed;
 
-	PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n",
-	       (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count),
-	       pd_idx, qd_idx);
+	r6s.qd_idx = raid6_next_disk(pd_idx, disks);
+	pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
+		"pd_idx=%d, qd_idx=%d\n",
+	       (unsigned long long)sh->sector, sh->state,
+	       atomic_read(&sh->count), pd_idx, r6s.qd_idx);
+	memset(&s, 0, sizeof(s));
 
 	spin_lock(&sh->lock);
 	clear_bit(STRIPE_HANDLE, &sh->state);
 	clear_bit(STRIPE_DELAYED, &sh->state);
 
-	syncing = test_bit(STRIPE_SYNCING, &sh->state);
-	expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-	expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+	s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
+	s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+	s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
 	/* Now to look around and see what can be done */
 
 	rcu_read_lock();
@@ -1917,12 +2911,12 @@
 		dev = &sh->dev[i];
 		clear_bit(R5_Insync, &dev->flags);
 
-		PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
+		pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
 			i, dev->flags, dev->toread, dev->towrite, dev->written);
 		/* maybe we can reply to a read */
 		if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
 			struct bio *rbi, *rbi2;
-			PRINTK("Return read for disc %d\n", i);
+			pr_debug("Return read for disc %d\n", i);
 			spin_lock_irq(&conf->device_lock);
 			rbi = dev->toread;
 			dev->toread = NULL;
@@ -1943,17 +2937,19 @@
 		}
 
 		/* now count some things */
-		if (test_bit(R5_LOCKED, &dev->flags)) locked++;
-		if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
+		if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
+		if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
 
 
-		if (dev->toread) to_read++;
+		if (dev->toread)
+			s.to_read++;
 		if (dev->towrite) {
-			to_write++;
+			s.to_write++;
 			if (!test_bit(R5_OVERWRITE, &dev->flags))
-				non_overwrite++;
+				s.non_overwrite++;
 		}
-		if (dev->written) written++;
+		if (dev->written)
+			s.written++;
 		rdev = rcu_dereference(conf->disks[i].rdev);
 		if (!rdev || !test_bit(In_sync, &rdev->flags)) {
 			/* The ReadError flag will just be confusing now */
@@ -1962,96 +2958,27 @@
 		}
 		if (!rdev || !test_bit(In_sync, &rdev->flags)
 		    || test_bit(R5_ReadError, &dev->flags)) {
-			if ( failed < 2 )
-				failed_num[failed] = i;
-			failed++;
+			if (s.failed < 2)
+				r6s.failed_num[s.failed] = i;
+			s.failed++;
 		} else
 			set_bit(R5_Insync, &dev->flags);
 	}
 	rcu_read_unlock();
-	PRINTK("locked=%d uptodate=%d to_read=%d"
+	pr_debug("locked=%d uptodate=%d to_read=%d"
 	       " to_write=%d failed=%d failed_num=%d,%d\n",
-	       locked, uptodate, to_read, to_write, failed,
-	       failed_num[0], failed_num[1]);
-	/* check if the array has lost >2 devices and, if so, some requests might
-	 * need to be failed
+	       s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
+	       r6s.failed_num[0], r6s.failed_num[1]);
+	/* check if the array has lost >2 devices and, if so, some requests
+	 * might need to be failed
 	 */
-	if (failed > 2 && to_read+to_write+written) {
-		for (i=disks; i--; ) {
-			int bitmap_end = 0;
-
-			if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-				mdk_rdev_t *rdev;
-				rcu_read_lock();
-				rdev = rcu_dereference(conf->disks[i].rdev);
-				if (rdev && test_bit(In_sync, &rdev->flags))
-					/* multiple read failures in one stripe */
-					md_error(conf->mddev, rdev);
-				rcu_read_unlock();
-			}
-
-			spin_lock_irq(&conf->device_lock);
-			/* fail all writes first */
-			bi = sh->dev[i].towrite;
-			sh->dev[i].towrite = NULL;
-			if (bi) { to_write--; bitmap_end = 1; }
-
-			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-				wake_up(&conf->wait_for_overlap);
-
-			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-				struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-				clear_bit(BIO_UPTODATE, &bi->bi_flags);
-				if (--bi->bi_phys_segments == 0) {
-					md_write_end(conf->mddev);
-					bi->bi_next = return_bi;
-					return_bi = bi;
-				}
-				bi = nextbi;
-			}
-			/* and fail all 'written' */
-			bi = sh->dev[i].written;
-			sh->dev[i].written = NULL;
-			if (bi) bitmap_end = 1;
-			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
-				struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
-				clear_bit(BIO_UPTODATE, &bi->bi_flags);
-				if (--bi->bi_phys_segments == 0) {
-					md_write_end(conf->mddev);
-					bi->bi_next = return_bi;
-					return_bi = bi;
-				}
-				bi = bi2;
-			}
-
-			/* fail any reads if this device is non-operational */
-			if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
-			    test_bit(R5_ReadError, &sh->dev[i].flags)) {
-				bi = sh->dev[i].toread;
-				sh->dev[i].toread = NULL;
-				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-					wake_up(&conf->wait_for_overlap);
-				if (bi) to_read--;
-				while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-					struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-					clear_bit(BIO_UPTODATE, &bi->bi_flags);
-					if (--bi->bi_phys_segments == 0) {
-						bi->bi_next = return_bi;
-						return_bi = bi;
-					}
-					bi = nextbi;
-				}
-			}
-			spin_unlock_irq(&conf->device_lock);
-			if (bitmap_end)
-				bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-						STRIPE_SECTORS, 0, 0);
-		}
-	}
-	if (failed > 2 && syncing) {
+	if (s.failed > 2 && s.to_read+s.to_write+s.written)
+		handle_requests_to_failed_array(conf, sh, &s, disks,
+						&return_bi);
+	if (s.failed > 2 && s.syncing) {
 		md_done_sync(conf->mddev, STRIPE_SECTORS,0);
 		clear_bit(STRIPE_SYNCING, &sh->state);
-		syncing = 0;
+		s.syncing = 0;
 	}
 
 	/*
@@ -2059,279 +2986,41 @@
 	 * are safe, or on a failed drive
 	 */
 	pdev = &sh->dev[pd_idx];
-	p_failed = (failed >= 1 && failed_num[0] == pd_idx)
-		|| (failed >= 2 && failed_num[1] == pd_idx);
-	qdev = &sh->dev[qd_idx];
-	q_failed = (failed >= 1 && failed_num[0] == qd_idx)
-		|| (failed >= 2 && failed_num[1] == qd_idx);
+	r6s.p_failed = (s.failed >= 1 && r6s.failed_num[0] == pd_idx)
+		|| (s.failed >= 2 && r6s.failed_num[1] == pd_idx);
+	qdev = &sh->dev[r6s.qd_idx];
+	r6s.q_failed = (s.failed >= 1 && r6s.failed_num[0] == r6s.qd_idx)
+		|| (s.failed >= 2 && r6s.failed_num[1] == r6s.qd_idx);
 
-	if ( written &&
-	     ( p_failed || ((test_bit(R5_Insync, &pdev->flags)
+	if ( s.written &&
+	     ( r6s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
 			     && !test_bit(R5_LOCKED, &pdev->flags)
-			     && test_bit(R5_UPTODATE, &pdev->flags))) ) &&
-	     ( q_failed || ((test_bit(R5_Insync, &qdev->flags)
+			     && test_bit(R5_UPTODATE, &pdev->flags)))) &&
+	     ( r6s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
 			     && !test_bit(R5_LOCKED, &qdev->flags)
-			     && test_bit(R5_UPTODATE, &qdev->flags))) ) ) {
-		/* any written block on an uptodate or failed drive can be
-		 * returned.  Note that if we 'wrote' to a failed drive,
-		 * it will be UPTODATE, but never LOCKED, so we don't need
-		 * to test 'failed' directly.
-		 */
-		for (i=disks; i--; )
-			if (sh->dev[i].written) {
-				dev = &sh->dev[i];
-				if (!test_bit(R5_LOCKED, &dev->flags) &&
-				    test_bit(R5_UPTODATE, &dev->flags) ) {
-					/* We can return any write requests */
-					int bitmap_end = 0;
-					struct bio *wbi, *wbi2;
-					PRINTK("Return write for stripe %llu disc %d\n",
-					       (unsigned long long)sh->sector, i);
-					spin_lock_irq(&conf->device_lock);
-					wbi = dev->written;
-					dev->written = NULL;
-					while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-						wbi2 = r5_next_bio(wbi, dev->sector);
-						if (--wbi->bi_phys_segments == 0) {
-							md_write_end(conf->mddev);
-							wbi->bi_next = return_bi;
-							return_bi = wbi;
-						}
-						wbi = wbi2;
-					}
-					if (dev->towrite == NULL)
-						bitmap_end = 1;
-					spin_unlock_irq(&conf->device_lock);
-					if (bitmap_end)
-						bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-								STRIPE_SECTORS,
-								!test_bit(STRIPE_DEGRADED, &sh->state), 0);
-				}
-			}
-	}
+			     && test_bit(R5_UPTODATE, &qdev->flags)))))
+		handle_completed_write_requests(conf, sh, disks, &return_bi);
 
 	/* Now we might consider reading some blocks, either to check/generate
 	 * parity, or to satisfy requests
 	 * or to load a block that is being partially written.
 	 */
-	if (to_read || non_overwrite || (to_write && failed) ||
-	    (syncing && (uptodate < disks)) || expanding) {
-		for (i=disks; i--;) {
-			dev = &sh->dev[i];
-			if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-			    (dev->toread ||
-			     (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
-			     syncing ||
-			     expanding ||
-			     (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
-			     (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
-				    )
-				) {
-				/* we would like to get this block, possibly
-				 * by computing it, but we might not be able to
-				 */
-				if (uptodate == disks-1) {
-					PRINTK("Computing stripe %llu block %d\n",
-					       (unsigned long long)sh->sector, i);
-					compute_block_1(sh, i, 0);
-					uptodate++;
-				} else if ( uptodate == disks-2 && failed >= 2 ) {
-					/* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
-					int other;
-					for (other=disks; other--;) {
-						if ( other == i )
-							continue;
-						if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) )
-							break;
-					}
-					BUG_ON(other < 0);
-					PRINTK("Computing stripe %llu blocks %d,%d\n",
-					       (unsigned long long)sh->sector, i, other);
-					compute_block_2(sh, i, other);
-					uptodate += 2;
-				} else if (test_bit(R5_Insync, &dev->flags)) {
-					set_bit(R5_LOCKED, &dev->flags);
-					set_bit(R5_Wantread, &dev->flags);
-					locked++;
-					PRINTK("Reading block %d (sync=%d)\n",
-						i, syncing);
-				}
-			}
-		}
-		set_bit(STRIPE_HANDLE, &sh->state);
-	}
+	if (s.to_read || s.non_overwrite || (s.to_write && s.failed) ||
+	    (s.syncing && (s.uptodate < disks)) || s.expanding)
+		handle_issuing_new_read_requests6(sh, &s, &r6s, disks);
 
 	/* now to consider writing and what else, if anything should be read */
-	if (to_write) {
-		int rcw=0, must_compute=0;
-		for (i=disks ; i--;) {
-			dev = &sh->dev[i];
-			/* Would I have to read this buffer for reconstruct_write */
-			if (!test_bit(R5_OVERWRITE, &dev->flags)
-			    && i != pd_idx && i != qd_idx
-			    && (!test_bit(R5_LOCKED, &dev->flags)
-				    ) &&
-			    !test_bit(R5_UPTODATE, &dev->flags)) {
-				if (test_bit(R5_Insync, &dev->flags)) rcw++;
-				else {
-					PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags);
-					must_compute++;
-				}
-			}
-		}
-		PRINTK("for sector %llu, rcw=%d, must_compute=%d\n",
-		       (unsigned long long)sh->sector, rcw, must_compute);
-		set_bit(STRIPE_HANDLE, &sh->state);
-
-		if (rcw > 0)
-			/* want reconstruct write, but need to get some data */
-			for (i=disks; i--;) {
-				dev = &sh->dev[i];
-				if (!test_bit(R5_OVERWRITE, &dev->flags)
-				    && !(failed == 0 && (i == pd_idx || i == qd_idx))
-				    && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-				    test_bit(R5_Insync, &dev->flags)) {
-					if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-					{
-						PRINTK("Read_old stripe %llu block %d for Reconstruct\n",
-						       (unsigned long long)sh->sector, i);
-						set_bit(R5_LOCKED, &dev->flags);
-						set_bit(R5_Wantread, &dev->flags);
-						locked++;
-					} else {
-						PRINTK("Request delayed stripe %llu block %d for Reconstruct\n",
-						       (unsigned long long)sh->sector, i);
-						set_bit(STRIPE_DELAYED, &sh->state);
-						set_bit(STRIPE_HANDLE, &sh->state);
-					}
-				}
-			}
-		/* now if nothing is locked, and if we have enough data, we can start a write request */
-		if (locked == 0 && rcw == 0 &&
-		    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
-			if ( must_compute > 0 ) {
-				/* We have failed blocks and need to compute them */
-				switch ( failed ) {
-				case 0:	BUG();
-				case 1: compute_block_1(sh, failed_num[0], 0); break;
-				case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
-				default: BUG();	/* This request should have been failed? */
-				}
-			}
-
-			PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector);
-			compute_parity6(sh, RECONSTRUCT_WRITE);
-			/* now every locked buffer is ready to be written */
-			for (i=disks; i--;)
-				if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
-					PRINTK("Writing stripe %llu block %d\n",
-					       (unsigned long long)sh->sector, i);
-					locked++;
-					set_bit(R5_Wantwrite, &sh->dev[i].flags);
-				}
-			/* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
-			set_bit(STRIPE_INSYNC, &sh->state);
-
-			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-				atomic_dec(&conf->preread_active_stripes);
-				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-					md_wakeup_thread(conf->mddev->thread);
-			}
-		}
-	}
+	if (s.to_write)
+		handle_issuing_new_write_requests6(conf, sh, &s, &r6s, disks);
 
 	/* maybe we need to check and possibly fix the parity for this stripe
-	 * Any reads will already have been scheduled, so we just see if enough data
-	 * is available
+	 * Any reads will already have been scheduled, so we just see if enough
+	 * data is available
 	 */
-	if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
-		int update_p = 0, update_q = 0;
-		struct r5dev *dev;
+	if (s.syncing && s.locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state))
+		handle_parity_checks6(conf, sh, &s, &r6s, tmp_page, disks);
 
-		set_bit(STRIPE_HANDLE, &sh->state);
-
-		BUG_ON(failed>2);
-		BUG_ON(uptodate < disks);
-		/* Want to check and possibly repair P and Q.
-		 * However there could be one 'failed' device, in which
-		 * case we can only check one of them, possibly using the
-		 * other to generate missing data
-		 */
-
-		/* If !tmp_page, we cannot do the calculations,
-		 * but as we have set STRIPE_HANDLE, we will soon be called
-		 * by stripe_handle with a tmp_page - just wait until then.
-		 */
-		if (tmp_page) {
-			if (failed == q_failed) {
-				/* The only possible failed device holds 'Q', so it makes
-				 * sense to check P (If anything else were failed, we would
-				 * have used P to recreate it).
-				 */
-				compute_block_1(sh, pd_idx, 1);
-				if (!page_is_zero(sh->dev[pd_idx].page)) {
-					compute_block_1(sh,pd_idx,0);
-					update_p = 1;
-				}
-			}
-			if (!q_failed && failed < 2) {
-				/* q is not failed, and we didn't use it to generate
-				 * anything, so it makes sense to check it
-				 */
-				memcpy(page_address(tmp_page),
-				       page_address(sh->dev[qd_idx].page),
-				       STRIPE_SIZE);
-				compute_parity6(sh, UPDATE_PARITY);
-				if (memcmp(page_address(tmp_page),
-					   page_address(sh->dev[qd_idx].page),
-					   STRIPE_SIZE)!= 0) {
-					clear_bit(STRIPE_INSYNC, &sh->state);
-					update_q = 1;
-				}
-			}
-			if (update_p || update_q) {
-				conf->mddev->resync_mismatches += STRIPE_SECTORS;
-				if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
-					/* don't try to repair!! */
-					update_p = update_q = 0;
-			}
-
-			/* now write out any block on a failed drive,
-			 * or P or Q if they need it
-			 */
-
-			if (failed == 2) {
-				dev = &sh->dev[failed_num[1]];
-				locked++;
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantwrite, &dev->flags);
-			}
-			if (failed >= 1) {
-				dev = &sh->dev[failed_num[0]];
-				locked++;
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantwrite, &dev->flags);
-			}
-
-			if (update_p) {
-				dev = &sh->dev[pd_idx];
-				locked ++;
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantwrite, &dev->flags);
-			}
-			if (update_q) {
-				dev = &sh->dev[qd_idx];
-				locked++;
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantwrite, &dev->flags);
-			}
-			clear_bit(STRIPE_DEGRADED, &sh->state);
-
-			set_bit(STRIPE_INSYNC, &sh->state);
-		}
-	}
-
-	if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+	if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
 		md_done_sync(conf->mddev, STRIPE_SECTORS,1);
 		clear_bit(STRIPE_SYNCING, &sh->state);
 	}
@@ -2339,9 +3028,9 @@
 	/* If the failed drives are just a ReadError, then we might need
 	 * to progress the repair/check process
 	 */
-	if (failed <= 2 && ! conf->mddev->ro)
-		for (i=0; i<failed;i++) {
-			dev = &sh->dev[failed_num[i]];
+	if (s.failed <= 2 && !conf->mddev->ro)
+		for (i = 0; i < s.failed; i++) {
+			dev = &sh->dev[r6s.failed_num[i]];
 			if (test_bit(R5_ReadError, &dev->flags)
 			    && !test_bit(R5_LOCKED, &dev->flags)
 			    && test_bit(R5_UPTODATE, &dev->flags)
@@ -2358,7 +3047,7 @@
 			}
 		}
 
-	if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
+	if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
 		/* Need to write out all blocks after computing P&Q */
 		sh->disks = conf->raid_disks;
 		sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
@@ -2366,82 +3055,24 @@
 		compute_parity6(sh, RECONSTRUCT_WRITE);
 		for (i = conf->raid_disks ; i-- ;  ) {
 			set_bit(R5_LOCKED, &sh->dev[i].flags);
-			locked++;
+			s.locked++;
 			set_bit(R5_Wantwrite, &sh->dev[i].flags);
 		}
 		clear_bit(STRIPE_EXPANDING, &sh->state);
-	} else if (expanded) {
+	} else if (s.expanded) {
 		clear_bit(STRIPE_EXPAND_READY, &sh->state);
 		atomic_dec(&conf->reshape_stripes);
 		wake_up(&conf->wait_for_overlap);
 		md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
 	}
 
-	if (expanding && locked == 0) {
-		/* We have read all the blocks in this stripe and now we need to
-		 * copy some of them into a target stripe for expand.
-		 */
-		clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-		for (i = 0; i < sh->disks ; i++)
-			if (i != pd_idx && i != qd_idx) {
-				int dd_idx2, pd_idx2, j;
-				struct stripe_head *sh2;
-
-				sector_t bn = compute_blocknr(sh, i);
-				sector_t s = raid5_compute_sector(
-					bn, conf->raid_disks,
-					conf->raid_disks - conf->max_degraded,
-					&dd_idx2, &pd_idx2, conf);
-				sh2 = get_active_stripe(conf, s,
-							conf->raid_disks,
-						       pd_idx2, 1);
-				if (sh2 == NULL)
-					/* so for only the early blocks of
-					 * this stripe have been requests.
-					 * When later blocks get requests, we
-					 * will try again
-					 */
-					continue;
-				if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
-				    test_bit(R5_Expanded,
-					     &sh2->dev[dd_idx2].flags)) {
-					/* must have already done this block */
-					release_stripe(sh2);
-					continue;
-				}
-				memcpy(page_address(sh2->dev[dd_idx2].page),
-				       page_address(sh->dev[i].page),
-				       STRIPE_SIZE);
-				set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags);
-				set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags);
-				for (j = 0 ; j < conf->raid_disks ; j++)
-					if (j != sh2->pd_idx &&
-					    j != raid6_next_disk(sh2->pd_idx,
-							   sh2->disks) &&
-					    !test_bit(R5_Expanded,
-						      &sh2->dev[j].flags))
-						break;
-				if (j == conf->raid_disks) {
-					set_bit(STRIPE_EXPAND_READY,
-						&sh2->state);
-					set_bit(STRIPE_HANDLE, &sh2->state);
-				}
-				release_stripe(sh2);
-			}
-	}
+	if (s.expanding && s.locked == 0)
+		handle_stripe_expansion(conf, sh, &r6s);
 
 	spin_unlock(&sh->lock);
 
-	while ((bi=return_bi)) {
-		int bytes = bi->bi_size;
+	return_io(return_bi);
 
-		return_bi = bi->bi_next;
-		bi->bi_next = NULL;
-		bi->bi_size = 0;
-		bi->bi_end_io(bi, bytes,
-			      test_bit(BIO_UPTODATE, &bi->bi_flags)
-			        ? 0 : -EIO);
-	}
 	for (i=disks; i-- ;) {
 		int rw;
 		struct bio *bi;
@@ -2470,11 +3101,11 @@
 		rcu_read_unlock();
 
 		if (rdev) {
-			if (syncing || expanding || expanded)
+			if (s.syncing || s.expanding || s.expanded)
 				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
 			bi->bi_bdev = rdev->bdev;
-			PRINTK("for %llu schedule op %ld on disc %d\n",
+			pr_debug("for %llu schedule op %ld on disc %d\n",
 				(unsigned long long)sh->sector, bi->bi_rw, i);
 			atomic_inc(&sh->count);
 			bi->bi_sector = sh->sector + rdev->data_offset;
@@ -2494,7 +3125,7 @@
 		} else {
 			if (rw == WRITE)
 				set_bit(STRIPE_DEGRADED, &sh->state);
-			PRINTK("skip op %ld on disc %d for sector %llu\n",
+			pr_debug("skip op %ld on disc %d for sector %llu\n",
 				bi->bi_rw, i, (unsigned long long)sh->sector);
 			clear_bit(R5_LOCKED, &sh->dev[i].flags);
 			set_bit(STRIPE_HANDLE, &sh->state);
@@ -2738,7 +3369,7 @@
 	}
 
 
-	PRINTK("raid5_align_endio : io error...handing IO for a retry\n");
+	pr_debug("raid5_align_endio : io error...handing IO for a retry\n");
 
 	add_bio_to_retry(raid_bi, conf);
 	return 0;
@@ -2776,7 +3407,7 @@
 	mdk_rdev_t *rdev;
 
 	if (!in_chunk_boundary(mddev, raid_bio)) {
-		PRINTK("chunk_aligned_read : non aligned\n");
+		pr_debug("chunk_aligned_read : non aligned\n");
 		return 0;
 	}
 	/*
@@ -2900,7 +3531,7 @@
 
  		new_sector = raid5_compute_sector(logical_sector, disks, data_disks,
 						  &dd_idx, &pd_idx, conf);
-		PRINTK("raid5: make_request, sector %llu logical %llu\n",
+		pr_debug("raid5: make_request, sector %llu logical %llu\n",
 			(unsigned long long)new_sector, 
 			(unsigned long long)logical_sector);
 
@@ -3273,7 +3904,7 @@
 	raid5_conf_t *conf = mddev_to_conf(mddev);
 	int handled;
 
-	PRINTK("+++ raid5d active\n");
+	pr_debug("+++ raid5d active\n");
 
 	md_check_recovery(mddev);
 
@@ -3308,8 +3939,10 @@
 			handled++;
 		}
 
-		if (list_empty(&conf->handle_list))
+		if (list_empty(&conf->handle_list)) {
+			async_tx_issue_pending_all();
 			break;
+		}
 
 		first = conf->handle_list.next;
 		sh = list_entry(first, struct stripe_head, lru);
@@ -3325,13 +3958,13 @@
 
 		spin_lock_irq(&conf->device_lock);
 	}
-	PRINTK("%d stripes handled\n", handled);
+	pr_debug("%d stripes handled\n", handled);
 
 	spin_unlock_irq(&conf->device_lock);
 
 	unplug_slaves(mddev);
 
-	PRINTK("--- raid5d inactive\n");
+	pr_debug("--- raid5d inactive\n");
 }
 
 static ssize_t
@@ -3507,7 +4140,7 @@
 	atomic_set(&conf->preread_active_stripes, 0);
 	atomic_set(&conf->active_aligned_reads, 0);
 
-	PRINTK("raid5: run(%s) called.\n", mdname(mddev));
+	pr_debug("raid5: run(%s) called.\n", mdname(mddev));
 
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		raid_disk = rdev->raid_disk;
@@ -3690,7 +4323,7 @@
 	return 0;
 }
 
-#if RAID5_DEBUG
+#ifdef DEBUG
 static void print_sh (struct seq_file *seq, struct stripe_head *sh)
 {
 	int i;
@@ -3737,7 +4370,7 @@
 			       conf->disks[i].rdev &&
 			       test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
 	seq_printf (seq, "]");
-#if RAID5_DEBUG
+#ifdef DEBUG
 	seq_printf (seq, "\n");
 	printall(seq, conf);
 #endif
diff --git a/drivers/md/xor.c b/drivers/md/xor.c
deleted file mode 100644
index 324897c..0000000
--- a/drivers/md/xor.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * xor.c : Multiple Devices driver for Linux
- *
- * Copyright (C) 1996, 1997, 1998, 1999, 2000,
- * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson.
- *
- * Dispatch optimized RAID-5 checksumming functions.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * You should have received a copy of the GNU General Public License
- * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define BH_TRACE 0
-#include <linux/module.h>
-#include <linux/raid/md.h>
-#include <linux/raid/xor.h>
-#include <asm/xor.h>
-
-/* The xor routines to use.  */
-static struct xor_block_template *active_template;
-
-void
-xor_block(unsigned int count, unsigned int bytes, void **ptr)
-{
-	unsigned long *p0, *p1, *p2, *p3, *p4;
-
-	p0 = (unsigned long *) ptr[0];
-	p1 = (unsigned long *) ptr[1];
-	if (count == 2) {
-		active_template->do_2(bytes, p0, p1);
-		return;
-	}
-
-	p2 = (unsigned long *) ptr[2];
-	if (count == 3) {
-		active_template->do_3(bytes, p0, p1, p2);
-		return;
-	}
-
-	p3 = (unsigned long *) ptr[3];
-	if (count == 4) {
-		active_template->do_4(bytes, p0, p1, p2, p3);
-		return;
-	}
-
-	p4 = (unsigned long *) ptr[4];
-	active_template->do_5(bytes, p0, p1, p2, p3, p4);
-}
-
-/* Set of all registered templates.  */
-static struct xor_block_template *template_list;
-
-#define BENCH_SIZE (PAGE_SIZE)
-
-static void
-do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
-{
-	int speed;
-	unsigned long now;
-	int i, count, max;
-
-	tmpl->next = template_list;
-	template_list = tmpl;
-
-	/*
-	 * Count the number of XORs done during a whole jiffy, and use
-	 * this to calculate the speed of checksumming.  We use a 2-page
-	 * allocation to have guaranteed color L1-cache layout.
-	 */
-	max = 0;
-	for (i = 0; i < 5; i++) {
-		now = jiffies;
-		count = 0;
-		while (jiffies == now) {
-			mb();
-			tmpl->do_2(BENCH_SIZE, b1, b2);
-			mb();
-			count++;
-			mb();
-		}
-		if (count > max)
-			max = count;
-	}
-
-	speed = max * (HZ * BENCH_SIZE / 1024);
-	tmpl->speed = speed;
-
-	printk("   %-10s: %5d.%03d MB/sec\n", tmpl->name,
-	       speed / 1000, speed % 1000);
-}
-
-static int
-calibrate_xor_block(void)
-{
-	void *b1, *b2;
-	struct xor_block_template *f, *fastest;
-
-	b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
-	if (! b1) {
-		printk("raid5: Yikes!  No memory available.\n");
-		return -ENOMEM;
-	}
-	b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
-
-	/*
-	 * If this arch/cpu has a short-circuited selection, don't loop through all
-	 * the possible functions, just test the best one
-	 */
-
-	fastest = NULL;
-
-#ifdef XOR_SELECT_TEMPLATE
-		fastest = XOR_SELECT_TEMPLATE(fastest);
-#endif
-
-#define xor_speed(templ)	do_xor_speed((templ), b1, b2)
-
-	if (fastest) {
-		printk(KERN_INFO "raid5: automatically using best checksumming function: %s\n",
-			fastest->name);
-		xor_speed(fastest);
-	} else {
-		printk(KERN_INFO "raid5: measuring checksumming speed\n");
-		XOR_TRY_TEMPLATES;
-		fastest = template_list;
-		for (f = fastest; f; f = f->next)
-			if (f->speed > fastest->speed)
-				fastest = f;
-	}
-
-	printk("raid5: using function: %s (%d.%03d MB/sec)\n",
-	       fastest->name, fastest->speed / 1000, fastest->speed % 1000);
-
-#undef xor_speed
-
-	free_pages((unsigned long)b1, 2);
-
-	active_template = fastest;
-	return 0;
-}
-
-static __exit void xor_exit(void) { }
-
-EXPORT_SYMBOL(xor_block);
-MODULE_LICENSE("GPL");
-
-module_init(calibrate_xor_block);
-module_exit(xor_exit);
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index c120114..5c63c8e 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -4,5 +4,6 @@
 
 config VIDEO_SAA7146_VV
 	tristate
+	depends on VIDEO_DEV
 	select VIDEO_BUF
 	select VIDEO_SAA7146
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index efd2b74..03ef88a 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -11,7 +11,7 @@
 	---help---
 	  Say Y to select Digital TV adapters
 
-if DVB_CAPTURE_DRIVERS
+if DVB_CAPTURE_DRIVERS && DVB_CORE
 
 comment "Supported SAA7146 based PCI Adapters"
 	depends on DVB_CORE && PCI && I2C
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index 1a1c3bc..bff00b5 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -1,8 +1,11 @@
 b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
-	flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o \
-	flexcop-dma.o
+	flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
 
+ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
+b2c2-flexcop-objs += flexcop-dma.o
+endif
+
 b2c2-flexcop-pci-objs = flexcop-pci.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
 
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 0393a3d..e908e3c 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1721,9 +1721,6 @@
 		symbol_put(dst_ca_attach);
 #endif
 	}
-#ifdef CONFIG_DVB_CORE_ATTACH
-	symbol_put(dst_attach);
-#endif
 	kfree(state);
 }
 
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 34d7abc..b40af48 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -118,6 +118,7 @@
 	struct dvb_demux demux;
 	struct usb_device *udev;
 	struct mutex sem;
+	struct mutex wq_sem;
 	struct dvb_adapter adapter;
 	struct dvb_device *fedev;
 	struct dmxdev dmxdev;
@@ -482,14 +483,14 @@
 	struct cinergyt2 *cinergyt2 = dvbdev->priv;
 	int err = -ERESTARTSYS;
 
-	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
-		return -ERESTARTSYS;
+	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
+		goto out;
 
-	if ((err = dvb_generic_open(inode, file))) {
-		mutex_unlock(&cinergyt2->sem);
-		return err;
-	}
+	if (mutex_lock_interruptible(&cinergyt2->sem))
+		goto out_unlock1;
 
+	if ((err = dvb_generic_open(inode, file)))
+		goto out_unlock2;
 
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
 		cinergyt2_sleep(cinergyt2, 0);
@@ -498,8 +499,12 @@
 
 	atomic_inc(&cinergyt2->inuse);
 
+out_unlock2:
 	mutex_unlock(&cinergyt2->sem);
-	return 0;
+out_unlock1:
+	mutex_unlock(&cinergyt2->wq_sem);
+out:
+	return err;
 }
 
 static void cinergyt2_unregister(struct cinergyt2 *cinergyt2)
@@ -519,16 +524,17 @@
 	struct dvb_device *dvbdev = file->private_data;
 	struct cinergyt2 *cinergyt2 = dvbdev->priv;
 
-	if (mutex_lock_interruptible(&cinergyt2->sem))
-		return -ERESTARTSYS;
+	mutex_lock(&cinergyt2->wq_sem);
 
 	if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
-		cancel_delayed_work(&cinergyt2->query_work);
-		flush_scheduled_work();
+		cancel_rearming_delayed_work(&cinergyt2->query_work);
+
+		mutex_lock(&cinergyt2->sem);
 		cinergyt2_sleep(cinergyt2, 1);
+		mutex_unlock(&cinergyt2->sem);
 	}
 
-	mutex_unlock(&cinergyt2->sem);
+	mutex_unlock(&cinergyt2->wq_sem);
 
 	if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) {
 		warn("delayed unregister in release");
@@ -839,13 +845,13 @@
 
 static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
 {
-	cancel_delayed_work(&cinergyt2->rc_query_work);
+	cancel_rearming_delayed_work(&cinergyt2->rc_query_work);
 	input_unregister_device(cinergyt2->rc_input_dev);
 }
 
 static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2)
 {
-	cancel_delayed_work(&cinergyt2->rc_query_work);
+	cancel_rearming_delayed_work(&cinergyt2->rc_query_work);
 }
 
 static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2)
@@ -908,6 +914,7 @@
 	usb_set_intfdata (intf, (void *) cinergyt2);
 
 	mutex_init(&cinergyt2->sem);
+	mutex_init(&cinergyt2->wq_sem);
 	init_waitqueue_head (&cinergyt2->poll_wq);
 	INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query);
 
@@ -975,11 +982,8 @@
 {
 	struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
 
-	flush_scheduled_work();
-
 	cinergyt2_unregister_rc(cinergyt2);
-
-	cancel_delayed_work(&cinergyt2->query_work);
+	cancel_rearming_delayed_work(&cinergyt2->query_work);
 	wake_up_interruptible(&cinergyt2->poll_wq);
 
 	cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
@@ -993,21 +997,21 @@
 {
 	struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
 
-	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
+	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
 		return -ERESTARTSYS;
 
 	if (1) {
-		struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-
 		cinergyt2_suspend_rc(cinergyt2);
-		cancel_delayed_work(&cinergyt2->query_work);
+		cancel_rearming_delayed_work(&cinergyt2->query_work);
+
+		mutex_lock(&cinergyt2->sem);
 		if (cinergyt2->streaming)
 			cinergyt2_stop_stream_xfer(cinergyt2);
-		flush_scheduled_work();
 		cinergyt2_sleep(cinergyt2, 1);
+		mutex_unlock(&cinergyt2->sem);
 	}
 
-	mutex_unlock(&cinergyt2->sem);
+	mutex_unlock(&cinergyt2->wq_sem);
 	return 0;
 }
 
@@ -1015,9 +1019,15 @@
 {
 	struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
 	struct dvbt_set_parameters_msg *param = &cinergyt2->param;
+	int err = -ERESTARTSYS;
 
-	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
-		return -ERESTARTSYS;
+	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
+		goto out;
+
+	if (mutex_lock_interruptible(&cinergyt2->sem))
+		goto out_unlock1;
+
+	err = 0;
 
 	if (!cinergyt2->sleeping) {
 		cinergyt2_sleep(cinergyt2, 0);
@@ -1030,7 +1040,10 @@
 	cinergyt2_resume_rc(cinergyt2);
 
 	mutex_unlock(&cinergyt2->sem);
-	return 0;
+out_unlock1:
+	mutex_unlock(&cinergyt2->wq_sem);
+out:
+	return err;
 }
 
 static const struct usb_device_id cinergyt2_table [] __devinitdata = {
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index f4e4ca2..b6c7f66 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -523,6 +523,7 @@
 
 	dvb_frontend_init(fe);
 
+	set_freezable();
 	while (1) {
 		up(&fepriv->sem);	    /* is locked when we enter the thread... */
 restart:
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index e23d8a0..a9fa333 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -200,7 +200,7 @@
 {
 	struct dvb_device *dvbdev;
 	struct file_operations *dvbdevfops;
-
+	struct class_device *clsdev;
 	int id;
 
 	mutex_lock(&dvbdev_register_lock);
@@ -242,8 +242,15 @@
 
 	mutex_unlock(&dvbdev_register_lock);
 
-	class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
-			    adap->device, "dvb%d.%s%d", adap->num, dnames[type], id);
+	clsdev = class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR,
+				     nums2minor(adap->num, type, id)),
+				     adap->device, "dvb%d.%s%d", adap->num,
+				     dnames[type], id);
+	if (IS_ERR(clsdev)) {
+		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
+		       __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+		return PTR_ERR(clsdev);
+	}
 
 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 		adap->num, dnames[type], id, nums2minor(adap->num, type, id),
@@ -431,7 +438,7 @@
 	unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
 }
 
-module_init(init_dvbdev);
+subsys_initcall(init_dvbdev);
 module_exit(exit_dvbdev);
 
 MODULE_DESCRIPTION("DVB Core Driver");
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
index ccc429c..0f2d4b4 100644
--- a/drivers/media/dvb/frontends/tda10086.c
+++ b/drivers/media/dvb/frontends/tda10086.c
@@ -41,6 +41,7 @@
 	/* private demod data */
 	u32 frequency;
 	u32 symbol_rate;
+	bool has_lock;
 };
 
 static int debug = 0;
@@ -116,7 +117,7 @@
 	// misc setup
 	tda10086_write_byte(state, 0x01, 0x94);
 	tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
-	tda10086_write_byte(state, 0x03, 0x64);
+	tda10086_write_byte(state, 0x03, 0xe4);
 	tda10086_write_byte(state, 0x04, 0x43);
 	tda10086_write_byte(state, 0x0c, 0x0c);
 	tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
@@ -146,7 +147,7 @@
 	// setup AGC
 	tda10086_write_byte(state, 0x05, 0x0B);
 	tda10086_write_byte(state, 0x37, 0x63);
-	tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it
+	tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
 	tda10086_write_byte(state, 0x40, 0x64);
 	tda10086_write_byte(state, 0x41, 0x4f);
 	tda10086_write_byte(state, 0x42, 0x43);
@@ -398,6 +399,10 @@
 
 	dprintk ("%s\n", __FUNCTION__);
 
+	// modify parameters for tuning
+	tda10086_write_byte(state, 0x02, 0x35);
+	state->has_lock = false;
+
 	// set params
 	if (fe->ops.tuner_ops.set_params) {
 		fe->ops.tuner_ops.set_params(fe, fe_params);
@@ -542,8 +547,14 @@
 		*fe_status |= FE_HAS_VITERBI;
 	if (val & 0x08)
 		*fe_status |= FE_HAS_SYNC;
-	if (val & 0x10)
+	if (val & 0x10) {
 		*fe_status |= FE_HAS_LOCK;
+		if (!state->has_lock) {
+			state->has_lock = true;
+			// modify parameters for stable reception
+			tda10086_write_byte(state, 0x02, 0x00);
+		}
+	}
 
 	return 0;
 }
@@ -555,7 +566,7 @@
 
 	dprintk ("%s\n", __FUNCTION__);
 
-	_str = tda10086_read_byte(state, 0x43);
+	_str = 0xff - tda10086_read_byte(state, 0x43);
 	*signal = (_str << 8) | _str;
 
 	return 0;
@@ -568,7 +579,7 @@
 
 	dprintk ("%s\n", __FUNCTION__);
 
-	_snr = tda10086_read_byte(state, 0x1c);
+	_snr = 0xff - tda10086_read_byte(state, 0x1c);
 	*snr = (_snr << 8) | _snr;
 
 	return 0;
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
index 79f971d..bd3ebc2 100644
--- a/drivers/media/dvb/frontends/tda826x.c
+++ b/drivers/media/dvb/frontends/tda826x.c
@@ -89,8 +89,8 @@
 	buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
 	buf[3] = div >> 7;
 	buf[4] = div << 1;
-	buf[5] = 0xff; // basedband filter to max
-	buf[6] = 0xfe; // gains at max + no RF attenuation
+	buf[5] = 0x77; // baseband cut-off 19 MHz
+	buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
 	buf[7] = 0x83; // charge pumps at high, tests off
 	buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
 	buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 2557ac9..b611f2b 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -529,7 +529,7 @@
 	if (bi->type != BUDGET_FS_ACTIVY)
 		saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
 
-	if (budget_register(budget) == 0)
+	if ((ret = budget_register(budget)) == 0)
 		return 0; /* Everything OK */
 
 	/* An error occurred, cleanup resources */
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index a6ac82a..194b102 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -9,7 +9,7 @@
 	---help---
 	  Say Y here to enable selecting AM/FM radio adapters.
 
-if RADIO_ADAPTERS
+if RADIO_ADAPTERS && VIDEO_DEV
 
 config RADIO_CADET
 	tristate "ADS Cadet AM/FM Tuner"
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index fdf5d6e..5e6f17d 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -94,7 +94,6 @@
 
 	u32 iobase;
 	u32 length;
-	u8  chiprev;
 	u16 model;
 
 	u32 current_frequency;
@@ -415,7 +414,6 @@
 		goto err_pci;
 	}
 
-	pci_read_config_byte( pci_dev, PCI_REVISION_ID, &card->chiprev );
 	pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model );
 
 	pci_set_drvdata( pci_dev, card );
@@ -436,7 +434,7 @@
 	gemtek_pci_mute( card );
 
 	printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
-		card->chiprev, card->iobase, card->iobase + card->length - 1 );
+		pci_dev->revision, card->iobase, card->iobase + card->length - 1 );
 
 	return 0;
 
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 5cb3f54..4d45a40 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -11,7 +11,7 @@
 	  webcams, analog TV, and hybrid analog/digital TV.
 	  Some of those devices also supports FM radio.
 
-if VIDEO_CAPTURE_DRIVERS
+if VIDEO_CAPTURE_DRIVERS && VIDEO_DEV
 
 config VIDEO_ADV_DEBUG
 	bool "Enable advanced debug functionality"
@@ -691,7 +691,7 @@
 	depends on USB
 	default y
 
-if V4L_USB_DRIVERS
+if V4L_USB_DRIVERS && USB
 
 source "drivers/media/video/pvrusb2/Kconfig"
 
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 1c38723..b1fedb0 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -1331,7 +1331,7 @@
 
 /* Call with btv->lock down. */
 static void
-set_input(struct bttv *btv, unsigned int input)
+set_input(struct bttv *btv, unsigned int input, unsigned int norm)
 {
 	unsigned long flags;
 
@@ -1350,7 +1350,7 @@
 	}
 	audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
 		       TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
-	set_tvnorm(btv,btv->tvnorm);
+	set_tvnorm(btv, norm);
 	i2c_vidiocschan(btv);
 }
 
@@ -1441,7 +1441,7 @@
 
 	init_bt848(btv);
 	btv->pll.pll_current = -1;
-	set_input(btv,btv->input);
+	set_input(btv, btv->input, btv->tvnorm);
 }
 
 static int get_control(struct bttv *btv, struct v4l2_control *c)
@@ -2011,8 +2011,7 @@
 			return 0;
 		}
 
-		btv->tvnorm = v->norm;
-		set_input(btv,v->channel);
+		set_input(btv, v->channel, v->norm);
 		mutex_unlock(&btv->lock);
 		return 0;
 	}
@@ -2148,7 +2147,7 @@
 		if (*i > bttv_tvcards[btv->c.type].video_inputs)
 			return -EINVAL;
 		mutex_lock(&btv->lock);
-		set_input(btv,*i);
+		set_input(btv, *i, btv->tvnorm);
 		mutex_unlock(&btv->lock);
 		return 0;
 	}
@@ -4780,7 +4779,7 @@
 		bt848_hue(btv,32768);
 		bt848_sat(btv,32768);
 		audio_mute(btv, 1);
-		set_input(btv,0);
+		set_input(btv, 0, btv->tvnorm);
 		bttv_crop_reset(&btv->crop[0], btv->tvnorm);
 		btv->crop[1] = btv->crop[0]; /* current = default */
 		disclaim_vbi_lines(btv);
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h
index b2c22a0..8e2a87cd 100644
--- a/drivers/media/video/cafe_ccic-regs.h
+++ b/drivers/media/video/cafe_ccic-regs.h
@@ -150,6 +150,12 @@
 #define REG_GL_IMASK   0x300c  /* Interrupt mask register */
 #define   GIMSK_CCIC_EN          0x00000004    /* CCIC Interrupt enable */
 
+#define REG_GL_FCR	0x3038  /* GPIO functional control register */
+#define	  GFCR_GPIO_ON	  0x08		/* Camera GPIO enabled */
+#define REG_GL_GPIOR	0x315c	/* GPIO register */
+#define   GGPIO_OUT  		0x80000	/* GPIO output */
+#define   GGPIO_VAL  		0x00008	/* Output pin value */
+
 #define REG_LEN                REG_GL_IMASK + 4
 
 
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 96254db..c08f650 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -775,6 +775,12 @@
 	spin_lock_irqsave(&cam->dev_lock, flags);
 	cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
 	/*
+	 * Part one of the sensor dance: turn the global
+	 * GPIO signal on.
+	 */
+	cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);
+	cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL);
+	/*
 	 * Put the sensor into operational mode (assumes OLPC-style
 	 * wiring).  Control 0 is reset - set to 1 to operate.
 	 * Control 1 is power down, set to 0 to operate.
@@ -784,6 +790,7 @@
 	cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
 //	mdelay(1); /* Enough? */
 	spin_unlock_irqrestore(&cam->dev_lock, flags);
+	msleep(5); /* Just to be sure */
 }
 
 static void cafe_ctlr_power_down(struct cafe_camera *cam)
@@ -792,6 +799,8 @@
 
 	spin_lock_irqsave(&cam->dev_lock, flags);
 	cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1);
+	cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);
+	cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT);
 	cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN);
 	spin_unlock_irqrestore(&cam->dev_lock, flags);
 }
@@ -851,6 +860,7 @@
 	ret = 0;
 	cam->state = S_IDLE;
   out:
+	cafe_ctlr_power_down(cam);
 	mutex_unlock(&cam->s_mutex);
 	return ret;
 }
@@ -2103,10 +2113,16 @@
 	ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam);
 	if (ret)
 		goto out_iounmap;
+	/*
+	 * Initialize the controller and leave it powered up.  It will
+	 * stay that way until the sensor driver shows up.
+	 */
 	cafe_ctlr_init(cam);
 	cafe_ctlr_power_up(cam);
 	/*
-	 * Set up I2C/SMBUS communications
+	 * Set up I2C/SMBUS communications.  We have to drop the mutex here
+	 * because the sensor could attach in this call chain, leading to
+	 * unsightly deadlocks.
 	 */
 	mutex_unlock(&cam->s_mutex);  /* attach can deadlock */
 	ret = cafe_smbus_setup(cam);
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index b0466b8..a80b1cb 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1034,6 +1034,8 @@
 
 	if (unlikely(UNSET == core->tuner_type))
 		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
 
 	strcpy(t->name, "Television");
 	t->type       = V4L2_TUNER_ANALOG_TV;
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 259ea08..1cc2d28 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -906,6 +906,7 @@
 	u32 mode = 0;
 
 	dprintk("cx88: tvaudio thread started\n");
+	set_freezable();
 	for (;;) {
 		msleep_interruptible(1000);
 		if (kthread_should_stop())
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 2c450bd..5b6a403 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -1,7 +1,6 @@
 config VIDEO_EM28XX
 	tristate "Empia EM2800/2820/2840 USB video capture support"
-	depends on VIDEO_V4L1 && I2C && PCI
-	select VIDEO_BUF
+	depends on VIDEO_V4L1 && I2C
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
 	select VIDEO_IR
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig
index 0cc98a0..1aaeaa0 100644
--- a/drivers/media/video/ivtv/Kconfig
+++ b/drivers/media/video/ivtv/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_IVTV
 	tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
-	depends on VIDEO_V4L1 && VIDEO_V4L2 && USB && I2C && EXPERIMENTAL && PCI
+	depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL
 	select FW_LOADER
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
index 15012f8..91e9e90 100644
--- a/drivers/media/video/ivtv/ivtv-cards.h
+++ b/drivers/media/video/ivtv/ivtv-cards.h
@@ -86,7 +86,7 @@
 			  V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
 			  V4L2_CAP_SLICED_VBI_CAPTURE)
 #define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \
-			  V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_POS)
+			  V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
 
 struct ivtv_card_video_input {
 	u8  video_type; 	/* video input type */
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index e29f949..efc6635 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -652,6 +652,7 @@
 	itv->dma_timer.data = (unsigned long)itv;
 
 	itv->cur_dma_stream = -1;
+	itv->cur_pio_stream = -1;
 	itv->audio_stereo_mode = AUDIO_STEREO;
 	itv->audio_bilingual_mode = AUDIO_MONO_LEFT;
 
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 9a412d6..e6e56f1 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -67,14 +67,6 @@
 
 #include <media/ivtv.h>
 
-#ifdef CONFIG_LIRC_I2C
-#  error "This driver is not compatible with the LIRC I2C kernel configuration option."
-#endif /* CONFIG_LIRC_I2C */
-
-#ifndef CONFIG_PCI
-#  error "This driver requires kernel PCI support."
-#endif /* CONFIG_PCI */
-
 #define IVTV_ENCODER_OFFSET	0x00000000
 #define IVTV_ENCODER_SIZE	0x00800000	/* Last half isn't needed 0x01000000 */
 
@@ -245,6 +237,7 @@
 #define IVTV_IRQ_ENC_VBI_CAP		(0x1 << 29)
 #define IVTV_IRQ_ENC_VIM_RST		(0x1 << 28)
 #define IVTV_IRQ_ENC_DMA_COMPLETE	(0x1 << 27)
+#define IVTV_IRQ_ENC_PIO_COMPLETE	(0x1 << 25)
 #define IVTV_IRQ_DEC_AUD_MODE_CHG	(0x1 << 24)
 #define IVTV_IRQ_DEC_DATA_REQ		(0x1 << 22)
 #define IVTV_IRQ_DEC_DMA_COMPLETE	(0x1 << 20)
@@ -255,7 +248,8 @@
 #define IVTV_IRQ_DEC_VSYNC		(0x1 << 10)
 
 /* IRQ Masks */
-#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|IVTV_IRQ_DMA_READ)
+#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\
+		IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE)
 
 #define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS)
 #define IVTV_IRQ_MASK_DECODE  (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG)
@@ -382,6 +376,9 @@
 #define IVTV_F_S_STREAMOFF	7	/* signal end of stream EOS */
 #define IVTV_F_S_APPL_IO        8	/* this stream is used read/written by an application */
 
+#define IVTV_F_S_PIO_PENDING	9	/* this stream has pending PIO */
+#define IVTV_F_S_PIO_HAS_VBI	1       /* the current PIO request also requests VBI data */
+
 /* per-ivtv, i_flags */
 #define IVTV_F_I_DMA		   0 	/* DMA in progress */
 #define IVTV_F_I_UDMA		   1 	/* UDMA in progress */
@@ -398,8 +395,11 @@
 #define IVTV_F_I_DECODING_YUV	   12 	/* this stream is YUV frame decoding */
 #define IVTV_F_I_ENC_PAUSED	   13 	/* the encoder is paused */
 #define IVTV_F_I_VALID_DEC_TIMINGS 14 	/* last_dec_timing is valid */
-#define IVTV_F_I_WORK_HANDLER_VBI  15	/* there is work to be done for VBI */
-#define IVTV_F_I_WORK_HANDLER_YUV  16	/* there is work to be done for YUV */
+#define IVTV_F_I_HAVE_WORK  	   15	/* Used in the interrupt handler: there is work to be done */
+#define IVTV_F_I_WORK_HANDLER_VBI  16	/* there is work to be done for VBI */
+#define IVTV_F_I_WORK_HANDLER_YUV  17	/* there is work to be done for YUV */
+#define IVTV_F_I_WORK_HANDLER_PIO  18	/* there is work to be done for PIO */
+#define IVTV_F_I_PIO		   19	/* PIO in progress */
 
 /* Event notifications */
 #define IVTV_F_I_EV_DEC_STOPPED	   28	/* decoder stopped event */
@@ -492,6 +492,7 @@
 
 	/* Base Dev SG Array for cx23415/6 */
 	struct ivtv_SG_element *SGarray;
+	struct ivtv_SG_element *PIOarray;
 	dma_addr_t SG_handle;
 	int SG_length;
 
@@ -714,6 +715,7 @@
 	atomic_t decoding;	/* count number of active decoding streams */
 	u32 irq_rr_idx; /* Round-robin stream index */
 	int cur_dma_stream;	/* index of stream doing DMA */
+	int cur_pio_stream;	/* index of stream doing PIO */
 	u32 dma_data_req_offset;
 	u32 dma_data_req_size;
 	int output_mode;        /* NONE, MPG, YUV, UDMA YUV, passthrough */
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 8976487..555d5e6 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -32,6 +32,8 @@
 #include "ivtv-yuv.h"
 #include "ivtv-controls.h"
 #include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include <media/saa7115.h>
 
 /* This function tries to claim the stream for a specific file descriptor.
    If no one else is using this stream then the stream is claimed and
@@ -786,6 +788,13 @@
 		ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
 		/* Select correct audio input (i.e. TV tuner or Line in) */
 		ivtv_audio_set_io(itv);
+		if (itv->hw_flags & IVTV_HW_SAA711X)
+		{
+			struct v4l2_crystal_freq crystal_freq;
+			crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
+			crystal_freq.flags = 0;
+			ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
+		}
 		/* Done! Unmute and continue. */
 		ivtv_unmute(itv);
 		ivtv_release_stream(s);
@@ -872,6 +881,13 @@
 		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
 		/* Select the correct audio input (i.e. radio tuner) */
 		ivtv_audio_set_io(itv);
+		if (itv->hw_flags & IVTV_HW_SAA711X)
+		{
+			struct v4l2_crystal_freq crystal_freq;
+			crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
+			crystal_freq.flags = SAA7115_FREQ_FL_APLL;
+			ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
+		}
 		/* Done! Unmute and continue. */
 		ivtv_unmute(itv);
 	}
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 794a6a0..57af176 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -362,8 +362,6 @@
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
 			return -EINVAL;
-		fmt->fmt.pix.left = itv->main_rect.left;
-		fmt->fmt.pix.top = itv->main_rect.top;
 		fmt->fmt.pix.width = itv->main_rect.width;
 		fmt->fmt.pix.height = itv->main_rect.height;
 		fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -402,8 +400,6 @@
 		break;
 
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		fmt->fmt.pix.left = 0;
-		fmt->fmt.pix.top = 0;
 		fmt->fmt.pix.width = itv->params.width;
 		fmt->fmt.pix.height = itv->params.height;
 		fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -498,15 +494,13 @@
 		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
 			return -EINVAL;
 		field = fmt->fmt.pix.field;
-		r.top = fmt->fmt.pix.top;
-		r.left = fmt->fmt.pix.left;
+		r.top = 0;
+		r.left = 0;
 		r.width = fmt->fmt.pix.width;
 		r.height = fmt->fmt.pix.height;
 		ivtv_get_fmt(itv, streamtype, fmt);
 		if (itv->output_mode != OUT_UDMA_YUV) {
 			/* TODO: would setting the rect also be valid for this mode? */
-			fmt->fmt.pix.top = r.top;
-			fmt->fmt.pix.left = r.left;
 			fmt->fmt.pix.width = r.width;
 			fmt->fmt.pix.height = r.height;
 		}
@@ -538,11 +532,6 @@
 				itv->yuv_info.yuv_forced_update = 1;
 				return 0;
 			}
-			if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
-				 r.width, r.height, r.left, r.top))
-				itv->main_rect = r;
-			else
-				return -EINVAL;
 		}
 		return 0;
 	}
@@ -805,9 +794,39 @@
 		return ivtv_get_fmt(itv, id->type, fmt);
 	}
 
+	case VIDIOC_CROPCAP: {
+		struct v4l2_cropcap *cropcap = arg;
+
+		if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+		    cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+			return -EINVAL;
+		cropcap->bounds.top = cropcap->bounds.left = 0;
+		cropcap->bounds.width = 720;
+		if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			cropcap->bounds.height = itv->is_50hz ? 576 : 480;
+			cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
+			cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
+		} else {
+			cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
+			cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
+			cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
+		}
+		cropcap->defrect = cropcap->bounds;
+		return 0;
+	}
+
 	case VIDIOC_S_CROP: {
 		struct v4l2_crop *crop = arg;
 
+		if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+		    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+			if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+				 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
+				itv->main_rect = crop->c;
+				return 0;
+			}
+			return -EINVAL;
+		}
 		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 			return -EINVAL;
 		return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
@@ -816,6 +835,11 @@
 	case VIDIOC_G_CROP: {
 		struct v4l2_crop *crop = arg;
 
+		if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+		    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+			crop->c = itv->main_rect;
+			return 0;
+		}
 		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 			return -EINVAL;
 		return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
@@ -983,7 +1007,7 @@
 		if (itv->hw_flags & IVTV_HW_CX25840) {
 			itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
 		}
-		IVTV_DEBUG_INFO("Switching standard to %llx.\n", itv->std);
+		IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
 
 		/* Tuner */
 		ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
@@ -1141,8 +1165,6 @@
 		fb->fmt.pixelformat = itv->osd_pixelformat;
 		fb->fmt.width = itv->osd_rect.width;
 		fb->fmt.height = itv->osd_rect.height;
-		fb->fmt.left = itv->osd_rect.left;
-		fb->fmt.top = itv->osd_rect.top;
 		fb->base = (void *)itv->osd_video_pbase;
 		if (itv->osd_global_alpha_state)
 			fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
@@ -1215,7 +1237,7 @@
 					(s->buffers - s->q_free.buffers) * 100 / s->buffers,
 					(s->buffers * s->buf_size) / 1024, s->buffers);
 		}
-		IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", itv->mpg_data_received, itv->vbi_data_inserted);
+		IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
 		IVTV_INFO("==================  END STATUS CARD #%d  ==================\n", itv->num);
 		break;
 	}
@@ -1463,6 +1485,7 @@
 	case VIDIOC_S_FMT:
 	case VIDIOC_TRY_FMT:
 	case VIDIOC_ENUM_FMT:
+	case VIDIOC_CROPCAP:
 	case VIDIOC_G_CROP:
 	case VIDIOC_S_CROP:
 	case VIDIOC_G_FREQUENCY:
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index c3a047b..ba98bf0 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -31,8 +31,6 @@
 
 #define DMA_MAGIC_COOKIE 0x000001fe
 
-#define SLICED_VBI_PIO 1
-
 static void ivtv_dma_dec_start(struct ivtv_stream *s);
 
 static const int ivtv_stream_map[] = {
@@ -42,12 +40,40 @@
 	IVTV_ENC_STREAM_TYPE_VBI,
 };
 
-static inline int ivtv_use_pio(struct ivtv_stream *s)
-{
-	struct ivtv *itv = s->itv;
 
-	return s->dma == PCI_DMA_NONE ||
-	    (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
+static void ivtv_pio_work_handler(struct ivtv *itv)
+{
+	struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
+	struct ivtv_buffer *buf;
+	struct list_head *p;
+	int i = 0;
+
+	IVTV_DEBUG_DMA("ivtv_pio_work_handler\n");
+	if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
+			s->v4l2dev == NULL || !ivtv_use_pio(s)) {
+		itv->cur_pio_stream = -1;
+		/* trigger PIO complete user interrupt */
+		write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
+		return;
+	}
+	IVTV_DEBUG_DMA("Process PIO %s\n", s->name);
+	buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list);
+	list_for_each(p, &s->q_dma.list) {
+		struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
+		u32 size = s->PIOarray[i].size & 0x3ffff;
+
+		/* Copy the data from the card to the buffer */
+		if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+			memcpy_fromio(buf->buf, itv->dec_mem + s->PIOarray[i].src - IVTV_DECODER_OFFSET, size);
+		}
+		else {
+			memcpy_fromio(buf->buf, itv->enc_mem + s->PIOarray[i].src, size);
+		}
+		if (s->PIOarray[i].size & 0x80000000)
+			break;
+		i++;
+	}
+	write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
 }
 
 void ivtv_irq_work_handler(struct work_struct *work)
@@ -56,8 +82,11 @@
 
 	DEFINE_WAIT(wait);
 
+	if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
+		ivtv_pio_work_handler(itv);
+
 	if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags))
-		vbi_work_handler(itv);
+		ivtv_vbi_work_handler(itv);
 
 	if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
 		ivtv_yuv_work_handler(itv);
@@ -173,8 +202,7 @@
 	}
 	s->buffers_stolen = rc;
 
-	/* got the buffers, now fill in SGarray (DMA) or copy the data from the card
-	   to the buffers (PIO). */
+	/* got the buffers, now fill in SGarray (DMA) */
 	buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
 	memset(buf->buf, 0, 128);
 	list_for_each(p, &s->q_predma.list) {
@@ -182,21 +210,11 @@
 
 		if (skip_bufs-- > 0)
 			continue;
-		if (!ivtv_use_pio(s)) {
-			s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
-			s->SGarray[idx].src = cpu_to_le32(offset);
-			s->SGarray[idx].size = cpu_to_le32(s->buf_size);
-		}
+		s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
+		s->SGarray[idx].src = cpu_to_le32(offset);
+		s->SGarray[idx].size = cpu_to_le32(s->buf_size);
 		buf->bytesused = (size < s->buf_size) ? size : s->buf_size;
 
-		/* If PIO, then copy the data from the card to the buffer */
-		if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
-			memcpy_fromio(buf->buf, itv->dec_mem + offset - IVTV_DECODER_OFFSET, buf->bytesused);
-		}
-		else if (ivtv_use_pio(s)) {
-			memcpy_fromio(buf->buf, itv->enc_mem + offset, buf->bytesused);
-		}
-
 		s->q_predma.bytesused += buf->bytesused;
 		size -= buf->bytesused;
 		offset += s->buf_size;
@@ -224,11 +242,6 @@
 	u32 *u32buf;
 	int x = 0;
 
-	if (ivtv_use_pio(s)) {
-		if (s->q_predma.bytesused)
-			ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
-		s->SG_length = 0;
-	}
 	IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
 			s->name, s->dma_offset);
 	list_for_each(p, &s->q_dma.list) {
@@ -278,10 +291,14 @@
 	if (buf)
 		buf->bytesused += s->dma_last_offset;
 	if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) {
-		/* Parse and Groom VBI Data */
-		s->q_dma.bytesused -= buf->bytesused;
-		ivtv_process_vbi_data(itv, buf, 0, s->type);
-		s->q_dma.bytesused += buf->bytesused;
+		list_for_each(p, &s->q_dma.list) {
+			buf = list_entry(p, struct ivtv_buffer, list);
+
+			/* Parse and Groom VBI Data */
+			s->q_dma.bytesused -= buf->bytesused;
+			ivtv_process_vbi_data(itv, buf, 0, s->type);
+			s->q_dma.bytesused += buf->bytesused;
+		}
 		if (s->id == -1) {
 			ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
 			return;
@@ -351,10 +368,14 @@
 	struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
 	int i;
 
+	IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
+
 	if (s->q_predma.bytesused)
 		ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
-	IVTV_DEBUG_DMA("start DMA for %s\n", s->name);
-	s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
+
+	if (ivtv_use_dma(s))
+		s->SGarray[s->SG_length - 1].size =
+			cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
 
 	/* If this is an MPEG stream, and VBI data is also pending, then append the
 	   VBI DMA to the MPEG DMA and transfer both sets of data at once.
@@ -368,7 +389,8 @@
 	if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length &&
 			s->SG_length + s_vbi->SG_length <= s->buffers) {
 		ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
-		s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
+		if (ivtv_use_dma(s_vbi))
+			s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
 		for (i = 0; i < s_vbi->SG_length; i++) {
 			s->SGarray[s->SG_length++] = s_vbi->SGarray[i];
 		}
@@ -381,14 +403,26 @@
 	/* Mark last buffer size for Interrupt flag */
 	s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
 
-	/* Sync Hardware SG List of buffers */
-	ivtv_stream_sync_for_device(s);
-	write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
-	write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
-	set_bit(IVTV_F_I_DMA, &itv->i_flags);
-	itv->cur_dma_stream = s->type;
-	itv->dma_timer.expires = jiffies + HZ / 10;
-	add_timer(&itv->dma_timer);
+	if (ivtv_use_pio(s)) {
+		for (i = 0; i < s->SG_length; i++) {
+			s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src);
+			s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size);
+		}
+		set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags);
+		set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+		set_bit(IVTV_F_I_PIO, &itv->i_flags);
+		itv->cur_pio_stream = s->type;
+	}
+	else {
+		/* Sync Hardware SG List of buffers */
+		ivtv_stream_sync_for_device(s);
+		write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
+		write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
+		set_bit(IVTV_F_I_DMA, &itv->i_flags);
+		itv->cur_dma_stream = s->type;
+		itv->dma_timer.expires = jiffies + HZ / 10;
+		add_timer(&itv->dma_timer);
+	}
 }
 
 static void ivtv_dma_dec_start(struct ivtv_stream *s)
@@ -489,6 +523,40 @@
 	wake_up(&itv->dma_waitq);
 }
 
+static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
+{
+	struct ivtv_stream *s;
+
+	if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) {
+		itv->cur_pio_stream = -1;
+		return;
+	}
+	s = &itv->streams[itv->cur_pio_stream];
+	IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name);
+	s->SG_length = 0;
+	clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
+	clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+	itv->cur_pio_stream = -1;
+	dma_post(s);
+	if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+		ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0);
+	else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
+		ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1);
+	else if (s->type == IVTV_ENC_STREAM_TYPE_PCM)
+		ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2);
+	clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+	if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
+		u32 tmp;
+
+		s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+		tmp = s->dma_offset;
+		s->dma_offset = itv->vbi.dma_offset;
+		dma_post(s);
+		s->dma_offset = tmp;
+	}
+	wake_up(&itv->dma_waitq);
+}
+
 static void ivtv_irq_dma_err(struct ivtv *itv)
 {
 	u32 data[CX2341X_MBOX_MAX_DATA];
@@ -532,13 +600,7 @@
 	clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
 	s = &itv->streams[ivtv_stream_map[data[0]]];
 	if (!stream_enc_dma_append(s, data)) {
-		if (ivtv_use_pio(s)) {
-			dma_post(s);
-			ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[0]);
-		}
-		else {
-			set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
-		}
+		set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
 	}
 }
 
@@ -551,15 +613,6 @@
 	IVTV_DEBUG_IRQ("ENC START VBI CAP\n");
 	s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
 
-	if (ivtv_use_pio(s)) {
-		if (stream_enc_dma_append(s, data))
-			return;
-		if (s->q_predma.bytesused)
-			ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
-		s->SG_length = 0;
-		dma_post(s);
-		return;
-	}
 	/* If more than two VBI buffers are pending, then
 	   clear the old ones and start with this new one.
 	   This can happen during transition stages when MPEG capturing is
@@ -582,11 +635,11 @@
 	if (!stream_enc_dma_append(s, data) &&
 			!test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) {
 		set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
-		set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
+		set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
 	}
 }
 
-static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv)
+static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
 {
 	u32 data[CX2341X_MBOX_MAX_DATA];
 	struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
@@ -594,7 +647,7 @@
 	IVTV_DEBUG_IRQ("DEC VBI REINSERT\n");
 	if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) &&
 			!stream_enc_dma_append(s, data)) {
-		dma_post(s);
+		set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags);
 	}
 }
 
@@ -657,7 +710,6 @@
 	}
 	if (frame != (itv->lastVsyncFrame & 1)) {
 		struct ivtv_stream *s = ivtv_get_output_stream(itv);
-		int work = 0;
 
 		itv->lastVsyncFrame += 1;
 		if (frame == 0) {
@@ -678,7 +730,7 @@
 		/* Send VBI to saa7127 */
 		if (frame) {
 			set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
-			work = 1;
+			set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
 		}
 
 		/* Check if we need to update the yuv registers */
@@ -691,11 +743,9 @@
 				itv->yuv_info.new_frame_info[last_dma_frame].update = 0;
 				itv->yuv_info.yuv_forced_update = 0;
 				set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
-				work = 1;
+				set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
 			}
 		}
-		if (work)
-			queue_work(itv->irq_work_queues, &itv->irq_work_queue);
 	}
 }
 
@@ -755,6 +805,10 @@
 		ivtv_irq_enc_dma_complete(itv);
 	}
 
+	if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) {
+		ivtv_irq_enc_pio_complete(itv);
+	}
+
 	if (combo & IVTV_IRQ_DMA_ERR) {
 		ivtv_irq_dma_err(itv);
 	}
@@ -768,7 +822,7 @@
 	}
 
 	if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) {
-		ivtv_irq_dev_vbi_reinsert(itv);
+		ivtv_irq_dec_vbi_reinsert(itv);
 	}
 
 	if (combo & IVTV_IRQ_ENC_EOS) {
@@ -813,6 +867,22 @@
 		}
 	}
 
+	if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) {
+		for (i = 0; i < IVTV_MAX_STREAMS; i++) {
+			int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS;
+			struct ivtv_stream *s = &itv->streams[idx];
+
+			if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags))
+				continue;
+			if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG)
+				ivtv_dma_enc_start(s);
+			break;
+		}
+	}
+
+	if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags))
+		queue_work(itv->irq_work_queues, &itv->irq_work_queue);
+
 	spin_unlock(&itv->dma_reg_lock);
 
 	/* If we've just handled a 'forced' vsync, it's safest to say it
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
index ccfcef1..a04f938 100644
--- a/drivers/media/video/ivtv/ivtv-queue.c
+++ b/drivers/media/video/ivtv/ivtv-queue.c
@@ -195,14 +195,26 @@
 		s->dma != PCI_DMA_NONE ? "DMA " : "",
 		s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
 
-	/* Allocate DMA SG Arrays */
-	if (s->dma != PCI_DMA_NONE) {
-		s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
-		if (s->SGarray == NULL) {
-			IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
+	if (ivtv_might_use_pio(s)) {
+		s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
+		if (s->PIOarray == NULL) {
+			IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name);
 			return -ENOMEM;
 		}
-		s->SG_length = 0;
+	}
+
+	/* Allocate DMA SG Arrays */
+	s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
+	if (s->SGarray == NULL) {
+		IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
+		if (ivtv_might_use_pio(s)) {
+			kfree(s->PIOarray);
+			s->PIOarray = NULL;
+		}
+		return -ENOMEM;
+	}
+	s->SG_length = 0;
+	if (ivtv_might_use_dma(s)) {
 		s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma);
 		ivtv_stream_sync_for_cpu(s);
 	}
@@ -219,7 +231,7 @@
 			break;
 		}
 		INIT_LIST_HEAD(&buf->list);
-		if (s->dma != PCI_DMA_NONE) {
+		if (ivtv_might_use_dma(s)) {
 			buf->dma_handle = pci_map_single(s->itv->dev,
 				buf->buf, s->buf_size + 256, s->dma);
 			ivtv_buf_sync_for_cpu(s, buf);
@@ -242,7 +254,7 @@
 
 	/* empty q_free */
 	while ((buf = ivtv_dequeue(s, &s->q_free))) {
-		if (s->dma != PCI_DMA_NONE)
+		if (ivtv_might_use_dma(s))
 			pci_unmap_single(s->itv->dev, buf->dma_handle,
 				s->buf_size + 256, s->dma);
 		kfree(buf->buf);
@@ -256,6 +268,9 @@
 				 sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
 			s->SG_handle = IVTV_DMA_UNMAPPED;
 		}
+		kfree(s->SGarray);
+		kfree(s->PIOarray);
+		s->PIOarray = NULL;
 		s->SGarray = NULL;
 		s->SG_length = 0;
 	}
diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h
index 903edd4..2ed8d54 100644
--- a/drivers/media/video/ivtv/ivtv-queue.h
+++ b/drivers/media/video/ivtv/ivtv-queue.h
@@ -20,18 +20,43 @@
  */
 
 #define IVTV_DMA_UNMAPPED	((u32) -1)
+#define SLICED_VBI_PIO 1
 
 /* ivtv_buffer utility functions */
+
+static inline int ivtv_might_use_pio(struct ivtv_stream *s)
+{
+	return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI);
+}
+
+static inline int ivtv_use_pio(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+
+	return s->dma == PCI_DMA_NONE ||
+	    (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
+}
+
+static inline int ivtv_might_use_dma(struct ivtv_stream *s)
+{
+	return s->dma != PCI_DMA_NONE;
+}
+
+static inline int ivtv_use_dma(struct ivtv_stream *s)
+{
+	return !ivtv_use_pio(s);
+}
+
 static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf)
 {
-	if (s->dma != PCI_DMA_NONE)
+	if (ivtv_use_dma(s))
 		pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle,
 				s->buf_size + 256, s->dma);
 }
 
 static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf)
 {
-	if (s->dma != PCI_DMA_NONE)
+	if (ivtv_use_dma(s))
 		pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle,
 				s->buf_size + 256, s->dma);
 }
@@ -53,12 +78,14 @@
 
 static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s)
 {
-	pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle,
-		sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
+	if (ivtv_use_dma(s))
+		pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle,
+			sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
 }
 
 static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s)
 {
-	pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle,
-		sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
+	if (ivtv_use_dma(s))
+		pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle,
+			sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
 }
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 01a41a8..6af88ae 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -868,7 +868,7 @@
 	if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
 		return 0;
 
-	IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", pts, flags);
+	IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
 
 	/* Stop Decoder */
 	if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) {
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c
index 5efa5a8..3ba46e0 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.c
+++ b/drivers/media/video/ivtv/ivtv-vbi.c
@@ -450,7 +450,7 @@
 }
 
 
-void vbi_work_handler(struct ivtv *itv)
+void ivtv_vbi_work_handler(struct ivtv *itv)
 {
 	struct v4l2_sliced_vbi_data data;
 
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h
index cdaea69..ec211b4 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.h
+++ b/drivers/media/video/ivtv/ivtv-vbi.h
@@ -23,4 +23,4 @@
 int ivtv_used_line(struct ivtv *itv, int line, int field);
 void ivtv_disable_vbi(struct ivtv *itv);
 void ivtv_set_vbi(unsigned long arg);
-void vbi_work_handler(struct ivtv *itv);
+void ivtv_vbi_work_handler(struct ivtv *itv);
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 664aba8..7533fc2 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1809,7 +1809,6 @@
 {
 	int ret = -EBUSY;
 	unsigned long mchip_adr;
-	u8 revision;
 
 	if (meye.mchip_dev != NULL) {
 		printk(KERN_ERR "meye: only one device allowed!\n");
@@ -1885,7 +1884,6 @@
 		goto outreqirq;
 	}
 
-	pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision);
 	pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);
 	pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);
 
@@ -1939,7 +1937,7 @@
 	printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n",
 	       MEYE_DRIVER_VERSION);
 	printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n",
-	       revision, mchip_adr, meye.mchip_irq);
+	       meye.mchip_dev->revision, mchip_adr, meye.mchip_irq);
 
 	return 0;
 
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index e1821eb..d5ee262 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/freezer.h>
 #include <linux/videodev.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
@@ -468,6 +469,7 @@
 
 
 	v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
 		msp_sleep(state, -1);
@@ -646,7 +648,7 @@
 	int val, i, std, count;
 
 	v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
-
+	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
 		msp_sleep(state,-1);
@@ -940,7 +942,7 @@
 	int val, i;
 
 	v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
-
+	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
 		msp_sleep(state, -1);
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 03bc369..3ceb8a6 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -720,12 +720,22 @@
 	struct ov7670_format_struct *ovfmt;
 	struct ov7670_win_size *wsize;
 	struct ov7670_info *info = i2c_get_clientdata(c);
-	unsigned char com7;
+	unsigned char com7, clkrc;
 
 	ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize);
 	if (ret)
 		return ret;
 	/*
+	 * HACK: if we're running rgb565 we need to grab then rewrite
+	 * CLKRC.  If we're *not*, however, then rewriting clkrc hoses
+	 * the colors.
+	 */
+	if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
+		ret = ov7670_read(c, REG_CLKRC, &clkrc);
+		if (ret)
+			return ret;
+	}
+	/*
 	 * COM7 is a pain in the ass, it doesn't like to be read then
 	 * quickly written afterward.  But we have everything we need
 	 * to set it absolutely here, as long as the format-specific
@@ -744,7 +754,10 @@
 	if (wsize->regs)
 		ret = ov7670_write_array(c, wsize->regs);
 	info->fmt = ovfmt;
-	return 0;
+
+	if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0)
+		ret = ov7670_write(c, REG_CLKRC, clkrc);
+	return ret;
 }
 
 /*
@@ -1267,7 +1280,9 @@
 	ret = ov7670_detect(client);
 	if (ret)
 		goto out_free_info;
-	i2c_attach_client(client);
+	ret = i2c_attach_client(client);
+	if (ret)
+		goto out_free_info;
 	return 0;
 
   out_free_info:
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 74839f9..c1a392e 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -75,10 +75,6 @@
 	int norm;
 	int input;
 	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
 };
 
 #define   I2C_SAA7111        0x48
@@ -96,6 +92,17 @@
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
+static inline void
+saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
+{
+	struct saa7111 *decoder = i2c_get_clientdata(client);
+
+	if (decoder->reg[reg] != value) {
+		decoder->reg[reg] = value;
+		i2c_smbus_write_byte_data(client, reg, value);
+	}
+}
+
 static int
 saa7111_write_block (struct i2c_client *client,
 		     const u8          *data,
@@ -439,28 +446,14 @@
 	{
 		struct video_picture *pic = arg;
 
-		if (decoder->bright != pic->brightness) {
-			/* We want 0 to 255 we get 0-65535 */
-			decoder->bright = pic->brightness;
-			saa7111_write(client, 0x0a, decoder->bright >> 8);
-		}
-		if (decoder->contrast != pic->contrast) {
-			/* We want 0 to 127 we get 0-65535 */
-			decoder->contrast = pic->contrast;
-			saa7111_write(client, 0x0b,
-				      decoder->contrast >> 9);
-		}
-		if (decoder->sat != pic->colour) {
-			/* We want 0 to 127 we get 0-65535 */
-			decoder->sat = pic->colour;
-			saa7111_write(client, 0x0c, decoder->sat >> 9);
-		}
-		if (decoder->hue != pic->hue) {
-			/* We want -128 to 127 we get 0-65535 */
-			decoder->hue = pic->hue;
-			saa7111_write(client, 0x0d,
-				      (decoder->hue - 32768) >> 8);
-		}
+		/* We want 0 to 255 we get 0-65535 */
+		saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8);
+		/* We want 0 to 127 we get 0-65535 */
+		saa7111_write(client, 0x0b, pic->contrast >> 9);
+		/* We want 0 to 127 we get 0-65535 */
+		saa7111_write(client, 0x0c, pic->colour >> 9);
+		/* We want -128 to 127 we get 0-65535 */
+		saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
 	}
 		break;
 
@@ -524,10 +517,6 @@
 	decoder->norm = VIDEO_MODE_NTSC;
 	decoder->input = 0;
 	decoder->enable = 1;
-	decoder->bright = 32768;
-	decoder->contrast = 32768;
-	decoder->hue = 32768;
-	decoder->sat = 32768;
 	i2c_set_clientdata(client, decoder);
 
 	i = i2c_attach_client(client);
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 7b56041..30395d6 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -1005,7 +1005,7 @@
 int saa7134_tvaudio_fini(struct saa7134_dev *dev)
 {
 	/* shutdown tvaudio thread */
-	if (dev->thread.pid >= 0) {
+	if (dev->thread.pid > 0) {
 		dev->thread.shutdown = 1;
 		wake_up_interruptible(&dev->thread.wq);
 		wait_for_completion(&dev->thread.exit);
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index 1b9b074..c40b92c 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -205,9 +205,13 @@
 		/* 0x01 -> ??? no change ??? */
 		/* 0x02 -> PAL BDGHI / SECAM L */
 		/* 0x04 -> ??? PAL others / SECAM others ??? */
-		cb &= ~0x02;
-		if (t->std & V4L2_STD_SECAM)
-			cb |= 0x02;
+		cb &= ~0x03;
+		if (t->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM
+			cb |= PHILIPS_MF_SET_PAL_L;
+		else if (t->std & V4L2_STD_SECAM_LC)
+			cb |= PHILIPS_MF_SET_PAL_L2;
+		else /* V4L2_STD_B|V4L2_STD_GH */
+			cb |= PHILIPS_MF_SET_BG;
 		break;
 
 	case TUNER_TEMIC_4046FM5:
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index c9bf9db..9da338d 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -271,7 +271,7 @@
 	struct CHIPDESC  *desc = chiplist + chip->type;
 
 	v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name);
-
+	set_freezable();
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (!kthread_should_stop())
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index 9118a62..7df071eb 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -1414,6 +1414,11 @@
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return;
 
+	/* any urb with wrong status is ignored without acknowledgement */
+	if (urb->status == -ENOENT) {
+		return;
+	}
+
 	f = &usbvision->curFrame;
 
 	/* Manage streaming interruption */
@@ -1436,18 +1441,21 @@
 	if (usbvision->streaming == Stream_On) {
 
 		/* If we collected enough data let's parse! */
-		if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) {	/* 12 == header_length */
-			/*If we don't have a frame we're current working on, complain */
-			if(!list_empty(&(usbvision->inqueue))) {
-				if (!(*f)) {
-					(*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame);
-				}
-				usbvision_parse_data(usbvision);
+		if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) &&
+		    (!list_empty(&(usbvision->inqueue))) ) {
+			if (!(*f)) {
+				(*f) = list_entry(usbvision->inqueue.next,
+						  struct usbvision_frame,
+						  frame);
 			}
-			else {
-				PDEBUG(DBG_IRQ, "received data, but no one needs it");
-				scratch_reset(usbvision);
-			}
+			usbvision_parse_data(usbvision);
+		}
+		else {
+			/*If we don't have a frame
+			  we're current working on, complain */
+			PDEBUG(DBG_IRQ,
+			       "received data, but no one needs it");
+			scratch_reset(usbvision);
 		}
 	}
 	else {
@@ -1466,10 +1474,10 @@
 	urb->dev = usbvision->dev;
 	errCode = usb_submit_urb (urb, GFP_ATOMIC);
 
-	/* Disable this warning.  By design of the driver. */
-	//	if(errCode) {
-	//		err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode);
-	//	}
+	if(errCode) {
+		err("%s: usb_submit_urb failed: error %d",
+		    __FUNCTION__, errCode);
+	}
 
 	return;
 }
@@ -2394,7 +2402,7 @@
 {
 	struct usb_device *dev = usbvision->dev;
 	int bufIdx, errCode, regValue;
-	const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+	int sb_size;
 
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return -EFAULT;
@@ -2408,11 +2416,14 @@
 		usbvision->last_error = errCode;
 		return -EBUSY;
 	}
+	sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
 
-	regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+	regValue = (16 - usbvision_read_reg(usbvision,
+					    USBVISION_ALTER_REG)) & 0x0F;
 
 	usbvision->usb_bandwidth = regValue >> 1;
-	PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+	PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
+	       usbvision->usb_bandwidth);
 
 
 
@@ -2428,7 +2439,11 @@
 			return -ENOMEM;
 		}
 		usbvision->sbuf[bufIdx].urb = urb;
-		usbvision->sbuf[bufIdx].data = usb_buffer_alloc(usbvision->dev, sb_size, GFP_KERNEL,&urb->transfer_dma);
+		usbvision->sbuf[bufIdx].data =
+			usb_buffer_alloc(usbvision->dev,
+					 sb_size,
+					 GFP_KERNEL,
+					 &urb->transfer_dma);
 		urb->dev = dev;
 		urb->context = usbvision;
 		urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
@@ -2442,21 +2457,26 @@
 		for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
 		     k += usbvision->isocPacketSize) {
 			urb->iso_frame_desc[j].offset = k;
-			urb->iso_frame_desc[j].length = usbvision->isocPacketSize;
+			urb->iso_frame_desc[j].length =
+				usbvision->isocPacketSize;
 		}
 	}
 
 
 	/* Submit all URBs */
 	for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
-			errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL);
+			errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb,
+						 GFP_KERNEL);
 		if (errCode) {
-			err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode);
+			err("%s: usb_submit_urb(%d) failed: error %d",
+			    __FUNCTION__, bufIdx, errCode);
 		}
 	}
 
 	usbvision->streaming = Stream_Idle;
-	PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
+	PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
+	       __FUNCTION__,
+	       usbvision->video_endp);
 	return 0;
 }
 
@@ -2470,7 +2490,7 @@
 void usbvision_stop_isoc(struct usb_usbvision *usbvision)
 {
 	int bufIdx, errCode, regValue;
-	const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+	int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
 
 	if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
 		return;
@@ -2499,15 +2519,19 @@
 		errCode = usb_set_interface(usbvision->dev, usbvision->iface,
 					    usbvision->ifaceAlt);
 		if (errCode < 0) {
-			err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode);
+			err("%s: usb_set_interface() failed: error %d",
+			    __FUNCTION__, errCode);
 			usbvision->last_error = errCode;
 		}
-		regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
-		usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
-		PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
+		regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+		usbvision->isocPacketSize =
+			(regValue == 0) ? 0 : (regValue * 64) - 1;
+		PDEBUG(DBG_ISOC, "ISO Packet Length:%d",
+		       usbvision->isocPacketSize);
 
 		usbvision->usb_bandwidth = regValue >> 1;
-		PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+		PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
+		       usbvision->usb_bandwidth);
 	}
 }
 
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index bd6f642..c759d00 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -146,7 +146,6 @@
 #define USBVISION_CLIPMASK_SIZE		(MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
 
 #define USBVISION_URB_FRAMES		32
-#define USBVISION_MAX_ISOC_PACKET_SIZE 	959			// NT1003 Specs Document says 1023
 
 #define USBVISION_NUM_HEADERMARKER	20
 #define USBVISION_NUMFRAMES		3  /* Maximum number of frames an application can get */
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
index fcc5467..e617925 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/video-buf-dvb.c
@@ -47,6 +47,7 @@
 	int err;
 
 	dprintk("dvb thread started\n");
+	set_freezable();
 	videobuf_read_start(&dvb->dvbq);
 
 	for (;;) {
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index f7e1d19..3ef4d01 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -573,6 +573,7 @@
 	dprintk(1,"thread started\n");
 
 	mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+	set_freezable();
 
 	for (;;) {
 		vivi_sleep(dma_q);
diff --git a/drivers/message/fusion/linux_compat.h b/drivers/message/fusion/linux_compat.h
deleted file mode 100644
index bb2bf5a..0000000
--- a/drivers/message/fusion/linux_compat.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* drivers/message/fusion/linux_compat.h */
-
-#ifndef FUSION_LINUX_COMPAT_H
-#define FUSION_LINUX_COMPAT_H
-
-#include <linux/version.h>
-#include <scsi/scsi_device.h>
-
-#endif /* _LINUX_COMPAT_H */
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 75223bf..6a92e3d 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2006 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Logic Corporation.
  *
  *
  *           Name:  mpi.h
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    mpi.h Version:  01.05.12
+ *    mpi.h Version:  01.05.13
  *
  *  Version History
  *  ---------------
@@ -78,6 +78,7 @@
  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
  *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
+ *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
  */
 
@@ -108,7 +109,7 @@
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x0E)
+#define MPI_HEADER_VERSION_UNIT             (0x10)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index 0e4c8e7..eda7697 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2006 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_cnfg.h
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    mpi_cnfg.h Version:  01.05.13
+ *    mpi_cnfg.h Version:  01.05.15
  *
  *  Version History
  *  ---------------
@@ -293,6 +293,21 @@
  *                      Added more AccessStatus values for SAS Device Page 0.
  *                      Added bit for SATA Asynchronous Notification Support in
  *                      Flags field of SAS Device Page 0.
+ *  02-28-07  01.05.14  Added ExtFlags field to Manufacturing Page 4.
+ *                      Added Disable SMART Polling for CapabilitiesFlags of
+ *                      IOC Page 6.
+ *                      Added Disable SMART Polling to DeviceSettings of BIOS
+ *                      Page 1.
+ *                      Added Multi-Port Domain bit for DiscoveryStatus field
+ *                      of SAS IO Unit Page.
+ *                      Added Multi-Port Domain Illegal flag for SAS IO Unit
+ *                      Page 1 AdditionalControlFlags field.
+ *  05-24-07  01.05.15  Added Hide Physical Disks with Non-Integrated RAID
+ *                      Metadata bit to Manufacturing Page 4 ExtFlags field.
+ *                      Added Internal Connector to End Device Present bit to
+ *                      Expander Page 0 Flags field.
+ *                      Fixed define for
+ *                      MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
  *  --------------------------------------------------------------------------
  */
 
@@ -639,7 +654,7 @@
     U8                              InfoSize1;          /* 0Bh */
     U8                              InquirySize;        /* 0Ch */
     U8                              Flags;              /* 0Dh */
-    U16                             Reserved2;          /* 0Eh */
+    U16                             ExtFlags;           /* 0Eh */
     U8                              InquiryData[56];    /* 10h */
     U32                             ISVolumeSettings;   /* 48h */
     U32                             IMEVolumeSettings;  /* 4Ch */
@@ -658,7 +673,7 @@
 } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
   ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
 
-#define MPI_MANUFACTURING4_PAGEVERSION                  (0x04)
+#define MPI_MANUFACTURING4_PAGEVERSION                  (0x05)
 
 /* defines for the Flags field */
 #define MPI_MANPAGE4_FORCE_BAD_BLOCK_TABLE              (0x80)
@@ -670,6 +685,12 @@
 #define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE             (0x02)
 #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
 
+/* defines for the ExtFlags field */
+#define MPI_MANPAGE4_EXTFLAGS_HIDE_NON_IR_METADATA      (0x0008)
+#define MPI_MANPAGE4_EXTFLAGS_SAS_CACHE_DISABLE         (0x0004)
+#define MPI_MANPAGE4_EXTFLAGS_SATA_CACHE_DISABLE        (0x0002)
+#define MPI_MANPAGE4_EXTFLAGS_LEGACY_MODE               (0x0001)
+
 
 #ifndef MPI_MANPAGE5_NUM_FORCEWWID
 #define MPI_MANPAGE5_NUM_FORCEWWID      (1)
@@ -781,7 +802,7 @@
 } CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9,
   ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t;
 
-#define MPI_MANUFACTURING6_PAGEVERSION                  (0x00)
+#define MPI_MANUFACTURING9_PAGEVERSION                  (0x00)
 
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_10
@@ -1138,6 +1159,8 @@
 
 /* IOC Page 6 Capabilities Flags */
 
+#define MPI_IOCPAGE6_CAP_FLAGS_DISABLE_SMART_POLLING    (0x00000008)
+
 #define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE       (0x00000006)
 #define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE       (0x00000000)
 #define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE      (0x00000002)
@@ -1208,6 +1231,7 @@
 #define MPI_BIOSPAGE1_IOCSET_ALTERNATE_CHS              (0x00000008)
 
 /* values for the DeviceSettings field */
+#define MPI_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING      (0x00000010)
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN            (0x00000008)
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_RM_LUN             (0x00000004)
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN         (0x00000002)
@@ -2281,11 +2305,11 @@
 typedef struct _CONFIG_PAGE_RAID_VOL_1
 {
     CONFIG_PAGE_HEADER      Header;         /* 00h */
-    U8                      VolumeID;       /* 01h */
-    U8                      VolumeBus;      /* 02h */
-    U8                      VolumeIOC;      /* 03h */
-    U8                      Reserved0;      /* 04h */
-    U8                      GUID[24];       /* 05h */
+    U8                      VolumeID;       /* 04h */
+    U8                      VolumeBus;      /* 05h */
+    U8                      VolumeIOC;      /* 06h */
+    U8                      Reserved0;      /* 07h */
+    U8                      GUID[24];       /* 08h */
     U8                      Name[32];       /* 20h */
     U64                     WWID;           /* 40h */
     U32                     Reserved1;      /* 48h */
@@ -2340,7 +2364,7 @@
 } RAID_PHYS_DISK0_STATUS, MPI_POINTER PTR_RAID_PHYS_DISK0_STATUS,
   RaidPhysDiskStatus_t, MPI_POINTER pRaidPhysDiskStatus_t;
 
-/* RAID Volume 2 IM Physical Disk DiskStatus flags */
+/* RAID Physical Disk PhysDiskStatus flags */
 
 #define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC           (0x01)
 #define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED              (0x02)
@@ -2544,6 +2568,7 @@
 #define MPI_SAS_IOUNIT0_DS_TABLE_LINK                       (0x00000400)
 #define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE               (0x00000800)
 #define MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS                 (0x00001000)
+#define MPI_SAS_IOUNIT0_DS_MULTI_PORT_DOMAIN                (0x00002000)
 
 
 typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
@@ -2607,6 +2632,7 @@
 #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION           (0x0001)
 
 /* values for SAS IO Unit Page 1 AdditionalControlFlags */
+#define MPI_SAS_IOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL          (0x0080)
 #define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION    (0x0040)
 #define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT    (0x0020)
 #define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET   (0x0010)
@@ -2734,6 +2760,7 @@
 #define MPI_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE         (0x00000800)
 
 /* values for SAS Expander Page 0 Flags field */
+#define MPI_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE    (0x04)
 #define MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG      (0x02)
 #define MPI_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS      (0x01)
 
@@ -2774,7 +2801,7 @@
 /* see mpi_sas.h for values for SAS Expander Page 1 AttachedDeviceInfo values */
 
 /* values for SAS Expander Page 1 DiscoveryInfo field */
-#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY DISABLED     (0x04)
+#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED     (0x04)
 #define MPI_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE   (0x02)
 #define MPI_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES   (0x01)
 
@@ -2895,11 +2922,11 @@
     U8                                  AttachedPhyIdentifier;  /* 16h */
     U8                                  Reserved2;              /* 17h */
     U32                                 AttachedDeviceInfo;     /* 18h */
-    U8                                  ProgrammedLinkRate;     /* 20h */
-    U8                                  HwLinkRate;             /* 21h */
-    U8                                  ChangeCount;            /* 22h */
-    U8                                  Flags;                  /* 23h */
-    U32                                 PhyInfo;                /* 24h */
+    U8                                  ProgrammedLinkRate;     /* 1Ch */
+    U8                                  HwLinkRate;             /* 1Dh */
+    U8                                  ChangeCount;            /* 1Eh */
+    U8                                  Flags;                  /* 1Fh */
+    U32                                 PhyInfo;                /* 20h */
 } CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
   SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
 
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index ddc7ae0..a1f4790 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -3,28 +3,28 @@
  MPI Header File Change History
  ==============================
 
- Copyright (c) 2000-2006 LSI Logic Corporation.
+ Copyright (c) 2000-2007 LSI Logic Corporation.
 
  ---------------------------------------
- Header Set Release Version:    01.05.14
- Header Set Release Date:       10-11-06
+ Header Set Release Version:    01.05.16
+ Header Set Release Date:       05-24-07
  ---------------------------------------
 
  Filename               Current version     Prior version
  ----------             ---------------     -------------
- mpi.h                  01.05.12            01.05.11
- mpi_ioc.h              01.05.12            01.05.11
- mpi_cnfg.h             01.05.13            01.05.12
- mpi_init.h             01.05.08            01.05.07
+ mpi.h                  01.05.13            01.05.12
+ mpi_ioc.h              01.05.14            01.05.13
+ mpi_cnfg.h             01.05.15            01.05.14
+ mpi_init.h             01.05.09            01.05.09
  mpi_targ.h             01.05.06            01.05.06
  mpi_fc.h               01.05.01            01.05.01
  mpi_lan.h              01.05.01            01.05.01
- mpi_raid.h             01.05.02            01.05.02
+ mpi_raid.h             01.05.03            01.05.03
  mpi_tool.h             01.05.03            01.05.03
  mpi_inb.h              01.05.01            01.05.01
- mpi_sas.h              01.05.04            01.05.03
+ mpi_sas.h              01.05.04            01.05.04
  mpi_type.h             01.05.02            01.05.02
- mpi_history.txt        01.05.14            01.05.13
+ mpi_history.txt        01.05.14            01.05.14
 
 
  *  Date      Version   Description
@@ -95,6 +95,7 @@
  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
  *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
+ *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
 
 mpi_ioc.h
@@ -191,6 +192,13 @@
  *                      data structure.
  *                      Added new ImageType values for FWDownload and FWUpload
  *                      requests.
+ *  02-28-07  01.05.13  Added MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT for SAS
+ *                      Broadcast Event Data (replacing _RESERVED2).
+ *                      For Discovery Error Event Data DiscoveryStatus field,
+ *                      replaced _MULTPL_PATHS with _UNSUPPORTED_DEVICE and
+ *                      added _MULTI_PORT_DOMAIN.
+ *  05-24-07  01.05.14  Added Common Boot Block type to FWDownload Request.
+ *                      Added Common Boot Block type to FWUpload Request.
  *  --------------------------------------------------------------------------
 
 mpi_cnfg.h
@@ -473,6 +481,21 @@
  *                      Added more AccessStatus values for SAS Device Page 0.
  *                      Added bit for SATA Asynchronous Notification Support in
  *                      Flags field of SAS Device Page 0.
+ *  02-28-07  01.05.14  Added ExtFlags field to Manufacturing Page 4.
+ *                      Added Disable SMART Polling for CapabilitiesFlags of
+ *                      IOC Page 6.
+ *                      Added Disable SMART Polling to DeviceSettings of BIOS
+ *                      Page 1.
+ *                      Added Multi-Port Domain bit for DiscoveryStatus field
+ *                      of SAS IO Unit Page.
+ *                      Added Multi-Port Domain Illegal flag for SAS IO Unit
+ *                      Page 1 AdditionalControlFlags field.
+ *  05-24-07  01.05.15  Added Hide Physical Disks with Non-Integrated RAID
+ *                      Metadata bit to Manufacturing Page 4 ExtFlags field.
+ *                      Added Internal Connector to End Device Present bit to
+ *                      Expander Page 0 Flags field.
+ *                      Fixed define for
+ *                      MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
  *  --------------------------------------------------------------------------
 
 mpi_init.h
@@ -517,6 +540,8 @@
  *                      unique in the first 32 characters.
  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
  *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
+ *  02-28-07  01.05.09  Defined two new MsgFlags bits for SCSI Task Management
+ *                      Request: Do Not Send Task IU and Soft Reset Option.
  *  --------------------------------------------------------------------------
 
 mpi_targ.h
@@ -571,7 +596,7 @@
  *  11-02-00  01.01.01  Original release for post 1.0 work
  *  12-04-00  01.01.02  Added messages for Common Transport Send and
  *                      Primitive Send.
- *  01-09-01  01.01.03  Modified some of the new flags to have an MPI prefix
+ *  01-09-01  01.01.03  Modifed some of the new flags to have an MPI prefix
  *                      and modified the FcPrimitiveSend flags.
  *  01-25-01  01.01.04  Move InitiatorIndex in LinkServiceRsp reply to a larger
  *                      field.
@@ -634,6 +659,8 @@
  *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  01-15-05  01.05.02  Added defines for the two new RAID Actions for
  *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
+ *  02-28-07  01.05.03  Added new RAID Action, Device FW Update Mode, and
+ *                      associated defines.
  *  --------------------------------------------------------------------------
 
 mpi_tool.h
@@ -682,7 +709,22 @@
 
 mpi_history.txt         Parts list history
 
-Filename    01.05.13   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
+Filename    01.05.15   01.05.15
+----------  --------   --------
+mpi.h       01.05.12   01.05.13
+mpi_ioc.h   01.05.13   01.05.14
+mpi_cnfg.h  01.05.14   01.05.15
+mpi_init.h  01.05.09   01.05.09
+mpi_targ.h  01.05.06   01.05.06
+mpi_fc.h    01.05.01   01.05.01
+mpi_lan.h   01.05.01   01.05.01
+mpi_raid.h  01.05.03   01.05.03
+mpi_tool.h  01.05.03   01.05.03
+mpi_inb.h   01.05.01   01.05.01
+mpi_sas.h   01.05.04   01.05.04
+mpi_type.h  01.05.02   01.05.02
+
+Filename    01.05.14   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
 ----------  --------   --------   --------   --------   --------   --------
 mpi.h       01.05.12   01.05.11   01.05.10   01.05.09   01.05.08   01.05.07
 mpi_ioc.h   01.05.12   01.05.11   01.05.10   01.05.09   01.05.09   01.05.08
diff --git a/drivers/message/fusion/lsi/mpi_inb.h b/drivers/message/fusion/lsi/mpi_inb.h
deleted file mode 100644
index ff16730..0000000
--- a/drivers/message/fusion/lsi/mpi_inb.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- *  Copyright (c) 2003-2004 LSI Logic Corporation.
- *
- *
- *           Name:  mpi_inb.h
- *          Title:  MPI Inband structures and definitions
- *  Creation Date:  September 30, 2003
- *
- *    mpi_inb.h Version:  01.05.01
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  05-11-04  01.03.01  Original release.
- *  08-19-04  01.05.01  Original release for MPI v1.5.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI_INB_H
-#define MPI_INB_H
-
-/******************************************************************************
-*
-*        I n b a n d    M e s s a g e s
-*
-*******************************************************************************/
-
-
-/****************************************************************************/
-/* Inband Buffer Post Request                                               */
-/****************************************************************************/
-
-typedef struct _MSG_INBAND_BUFFER_POST_REQUEST
-{
-    U8                      Reserved1;          /* 00h */
-    U8                      BufferCount;        /* 01h */
-    U8                      ChainOffset;        /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
-    U8                      Reserved3;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U32                     Reserved4;          /* 0Ch */
-    SGE_TRANS_SIMPLE_UNION  SGL;                /* 10h */
-} MSG_INBAND_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REQUEST,
-  MpiInbandBufferPostRequest_t , MPI_POINTER pMpiInbandBufferPostRequest_t;
-
-
-typedef struct _WWN_FC_FORMAT
-{
-    U64                     NodeName;           /* 00h */
-    U64                     PortName;           /* 08h */
-} WWN_FC_FORMAT, MPI_POINTER PTR_WWN_FC_FORMAT,
-  WwnFcFormat_t, MPI_POINTER pWwnFcFormat_t;
-
-typedef struct _WWN_SAS_FORMAT
-{
-    U64                     WorldWideID;        /* 00h */
-    U32                     Reserved1;          /* 08h */
-    U32                     Reserved2;          /* 0Ch */
-} WWN_SAS_FORMAT, MPI_POINTER PTR_WWN_SAS_FORMAT,
-  WwnSasFormat_t, MPI_POINTER pWwnSasFormat_t;
-
-typedef union _WWN_INBAND_FORMAT
-{
-    WWN_FC_FORMAT           Fc;
-    WWN_SAS_FORMAT          Sas;
-} WWN_INBAND_FORMAT, MPI_POINTER PTR_WWN_INBAND_FORMAT,
-  WwnInbandFormat, MPI_POINTER pWwnInbandFormat;
-
-
-/* Inband Buffer Post reply message */
-
-typedef struct _MSG_INBAND_BUFFER_POST_REPLY
-{
-    U16                     Reserved1;          /* 00h */
-    U8                      MsgLength;          /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
-    U8                      Reserved3;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U16                     Reserved4;          /* 0Ch */
-    U16                     IOCStatus;          /* 0Eh */
-    U32                     IOCLogInfo;         /* 10h */
-    U32                     TransferLength;     /* 14h */
-    U32                     TransactionContext; /* 18h */
-    WWN_INBAND_FORMAT       Wwn;                /* 1Ch */
-    U32                     IOCIdentifier[4];   /* 2Ch */
-} MSG_INBAND_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REPLY,
-  MpiInbandBufferPostReply_t, MPI_POINTER pMpiInbandBufferPostReply_t;
-
-
-/****************************************************************************/
-/* Inband Send Request                                                      */
-/****************************************************************************/
-
-typedef struct _MSG_INBAND_SEND_REQUEST
-{
-    U16                     Reserved1;          /* 00h */
-    U8                      ChainOffset;        /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
-    U8                      Reserved3;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U32                     Reserved4;          /* 0Ch */
-    WWN_INBAND_FORMAT       Wwn;                /* 10h */
-    U32                     Reserved5;          /* 20h */
-    SGE_IO_UNION            SGL;                /* 24h */
-} MSG_INBAND_SEND_REQUEST, MPI_POINTER PTR_MSG_INBAND_SEND_REQUEST,
-  MpiInbandSendRequest_t , MPI_POINTER pMpiInbandSendRequest_t;
-
-
-/* Inband Send reply message */
-
-typedef struct _MSG_INBAND_SEND_REPLY
-{
-    U16                     Reserved1;          /* 00h */
-    U8                      MsgLength;          /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
-    U8                      Reserved3;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U16                     Reserved4;          /* 0Ch */
-    U16                     IOCStatus;          /* 0Eh */
-    U32                     IOCLogInfo;         /* 10h */
-    U32                     ResponseLength;     /* 14h */
-} MSG_INBAND_SEND_REPLY, MPI_POINTER PTR_MSG_INBAND_SEND_REPLY,
-  MpiInbandSendReply_t, MPI_POINTER pMpiInbandSendReply_t;
-
-
-/****************************************************************************/
-/* Inband Response Request                                                  */
-/****************************************************************************/
-
-typedef struct _MSG_INBAND_RSP_REQUEST
-{
-    U16                     Reserved1;          /* 00h */
-    U8                      ChainOffset;        /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
-    U8                      Reserved3;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U32                     Reserved4;          /* 0Ch */
-    WWN_INBAND_FORMAT       Wwn;                /* 10h */
-    U32                     IOCIdentifier[4];   /* 20h */
-    U32                     ResponseLength;     /* 30h */
-    SGE_IO_UNION            SGL;                /* 34h */
-} MSG_INBAND_RSP_REQUEST, MPI_POINTER PTR_MSG_INBAND_RSP_REQUEST,
-  MpiInbandRspRequest_t , MPI_POINTER pMpiInbandRspRequest_t;
-
-
-/* Inband Response reply message */
-
-typedef struct _MSG_INBAND_RSP_REPLY
-{
-    U16                     Reserved1;          /* 00h */
-    U8                      MsgLength;          /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
-    U8                      Reserved3;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U16                     Reserved4;          /* 0Ch */
-    U16                     IOCStatus;          /* 0Eh */
-    U32                     IOCLogInfo;         /* 10h */
-} MSG_INBAND_RSP_REPLY, MPI_POINTER PTR_MSG_INBAND_RSP_REPLY,
-  MpiInbandRspReply_t, MPI_POINTER pMpiInbandRspReply_t;
-
-
-/****************************************************************************/
-/* Inband Abort Request                                                     */
-/****************************************************************************/
-
-typedef struct _MSG_INBAND_ABORT_REQUEST
-{
-    U8                      Reserved1;          /* 00h */
-    U8                      AbortType;          /* 01h */
-    U8                      ChainOffset;        /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
-    U8                      Reserved3;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U32                     Reserved4;          /* 0Ch */
-    U32                     ContextToAbort;     /* 10h */
-} MSG_INBAND_ABORT_REQUEST, MPI_POINTER PTR_MSG_INBAND_ABORT_REQUEST,
-  MpiInbandAbortRequest_t , MPI_POINTER pMpiInbandAbortRequest_t;
-
-#define MPI_INBAND_ABORT_TYPE_ALL_BUFFERS       (0x00)
-#define MPI_INBAND_ABORT_TYPE_EXACT_BUFFER      (0x01)
-#define MPI_INBAND_ABORT_TYPE_SEND_REQUEST      (0x02)
-#define MPI_INBAND_ABORT_TYPE_RESPONSE_REQUEST  (0x03)
-
-
-/* Inband Abort reply message */
-
-typedef struct _MSG_INBAND_ABORT_REPLY
-{
-    U8                      Reserved1;          /* 00h */
-    U8                      AbortType;          /* 01h */
-    U8                      MsgLength;          /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
-    U8                      Reserved3;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U16                     Reserved4;          /* 0Ch */
-    U16                     IOCStatus;          /* 0Eh */
-    U32                     IOCLogInfo;         /* 10h */
-} MSG_INBAND_ABORT_REPLY, MPI_POINTER PTR_MSG_INBAND_ABORT_REPLY,
-  MpiInbandAbortReply_t, MPI_POINTER pMpiInbandAbortReply_t;
-
-
-#endif
-
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index ec9dff2..3a02615 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2006 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_init.h
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    mpi_init.h Version:  01.05.08
+ *    mpi_init.h Version:  01.05.09
  *
  *  Version History
  *  ---------------
@@ -54,6 +54,8 @@
  *                      unique in the first 32 characters.
  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
  *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
+ *  02-28-07  01.05.09  Defined two new MsgFlags bits for SCSI Task Management
+ *                      Request: Do Not Send Task IU and Soft Reset Option.
  *  --------------------------------------------------------------------------
  */
 
@@ -432,10 +434,14 @@
 #define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA               (0x08)
 
 /* MsgFlags bits */
+#define MPI_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU   (0x01)
+
 #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION   (0x00)
 #define MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION      (0x02)
 #define MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION (0x04)
 
+#define MPI_SCSITASKMGMT_MSGFLAGS_SOFT_RESET_OPTION     (0x08)
+
 /* SCSI Task Management Reply */
 typedef struct _MSG_SCSI_TASK_MGMT_REPLY
 {
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 6c33e33..b1893d1 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2006 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_ioc.h
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    mpi_ioc.h Version:  01.05.12
+ *    mpi_ioc.h Version:  01.05.14
  *
  *  Version History
  *  ---------------
@@ -106,6 +106,13 @@
  *                      data structure.
  *                      Added new ImageType values for FWDownload and FWUpload
  *                      requests.
+ *  02-28-07  01.05.13  Added MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT for SAS
+ *                      Broadcast Event Data (replacing _RESERVED2).
+ *                      For Discovery Error Event Data DiscoveryStatus field,
+ *                      replaced _MULTPL_PATHS with _UNSUPPORTED_DEVICE and
+ *                      added _MULTI_PORT_DOMAIN.
+ *  05-24-07  01.05.14  Added Common Boot Block type to FWDownload Request.
+ *                      Added Common Boot Block type to FWUpload Request.
  *  --------------------------------------------------------------------------
  */
 
@@ -792,7 +799,7 @@
 
 #define MPI_EVENT_PRIMITIVE_CHANGE              (0x01)
 #define MPI_EVENT_PRIMITIVE_EXPANDER            (0x03)
-#define MPI_EVENT_PRIMITIVE_RESERVED2           (0x04)
+#define MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT  (0x04)
 #define MPI_EVENT_PRIMITIVE_RESERVED3           (0x05)
 #define MPI_EVENT_PRIMITIVE_RESERVED4           (0x06)
 #define MPI_EVENT_PRIMITIVE_CHANGE0_RESERVED    (0x07)
@@ -857,8 +864,9 @@
 #define MPI_EVENT_DSCVRY_ERR_DS_SMP_CRC_ERROR               (0x00000100)
 #define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE          (0x00000200)
 #define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE              (0x00000400)
-#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS                (0x00000800)
+#define MPI_EVENT_DSCVRY_ERR_DS_UNSUPPORTED_DEVICE          (0x00000800)
 #define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS            (0x00001000)
+#define MPI_EVENT_DSCVRY_ERR_DS_MULTI_PORT_DOMAIN           (0x00002000)
 
 /* SAS SMP Error Event data */
 
@@ -990,6 +998,7 @@
 #define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1          (0x07)
 #define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2          (0x08)
 #define MPI_FW_DOWNLOAD_ITYPE_MEGARAID          (0x09)
+#define MPI_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
 
 
 typedef struct _FWDownloadTCSGE
@@ -1038,17 +1047,18 @@
 } MSG_FW_UPLOAD, MPI_POINTER PTR_MSG_FW_UPLOAD,
   FWUpload_t, MPI_POINTER pFWUpload_t;
 
-#define MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM      (0x00)
-#define MPI_FW_UPLOAD_ITYPE_FW_FLASH        (0x01)
-#define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH      (0x02)
-#define MPI_FW_UPLOAD_ITYPE_NVDATA          (0x03)
-#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER      (0x04)
-#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP       (0x05)
-#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING   (0x06)
-#define MPI_FW_UPLOAD_ITYPE_CONFIG_1        (0x07)
-#define MPI_FW_UPLOAD_ITYPE_CONFIG_2        (0x08)
-#define MPI_FW_UPLOAD_ITYPE_MEGARAID        (0x09)
-#define MPI_FW_UPLOAD_ITYPE_COMPLETE        (0x0A)
+#define MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM          (0x00)
+#define MPI_FW_UPLOAD_ITYPE_FW_FLASH            (0x01)
+#define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH          (0x02)
+#define MPI_FW_UPLOAD_ITYPE_NVDATA              (0x03)
+#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER          (0x04)
+#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP           (0x05)
+#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING       (0x06)
+#define MPI_FW_UPLOAD_ITYPE_CONFIG_1            (0x07)
+#define MPI_FW_UPLOAD_ITYPE_CONFIG_2            (0x08)
+#define MPI_FW_UPLOAD_ITYPE_MEGARAID            (0x09)
+#define MPI_FW_UPLOAD_ITYPE_COMPLETE            (0x0A)
+#define MPI_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK   (0x0B)
 
 typedef struct _FWUploadTCSGE
 {
diff --git a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h
index 802255d..32819b1 100644
--- a/drivers/message/fusion/lsi/mpi_raid.h
+++ b/drivers/message/fusion/lsi/mpi_raid.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2001-2005 LSI Logic Corporation.
+ *  Copyright (c) 2001-2007 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_raid.h
  *          Title:  MPI RAID message and structures
  *  Creation Date:  February 27, 2001
  *
- *    mpi_raid.h Version:  01.05.02
+ *    mpi_raid.h Version:  01.05.03
  *
  *  Version History
  *  ---------------
@@ -32,6 +32,8 @@
  *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  01-15-05  01.05.02  Added defines for the two new RAID Actions for
  *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
+ *  02-28-07  01.05.03  Added new RAID Action, Device FW Update Mode, and
+ *                      associated defines.
  *  --------------------------------------------------------------------------
  */
 
@@ -90,6 +92,7 @@
 #define MPI_RAID_ACTION_INACTIVATE_VOLUME           (0x12)
 #define MPI_RAID_ACTION_SET_RESYNC_RATE             (0x13)
 #define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE         (0x14)
+#define MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE       (0x15)
 
 /* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */
 #define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC           (0x00000001)
@@ -111,6 +114,10 @@
 /* ActionDataWord defines for use with MPI_RAID_ACTION_SET_DATA_SCRUB_RATE action */
 #define MPI_RAID_ACTION_ADATA_DATA_SCRUB_RATE_MASK  (0x000000FF)
 
+/* ActionDataWord defines for use with MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
+#define MPI_RAID_ACTION_ADATA_ENABLE_FW_UPDATE          (0x00000001)
+#define MPI_RAID_ACTION_ADATA_MASK_FW_UPDATE_TIMEOUT    (0x0000FF00)
+#define MPI_RAID_ACTION_ADATA_SHIFT_FW_UPDATE_TIMEOUT   (8)
 
 
 /* RAID Action reply message */
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 5021d1a..5a10c87 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -64,6 +64,7 @@
 #endif
 
 #include "mptbase.h"
+#include "lsi/mpi_log_fc.h"
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #define my_NAME		"Fusion MPT base driver"
@@ -6349,14 +6350,37 @@
 static void
 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
 {
-	static char *subcl_str[8] = {
-		"FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
-		"FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
-	};
-	u8 subcl = (log_info >> 24) & 0x7;
+	char *desc = "unknown";
 
-	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
-			ioc->name, log_info, subcl_str[subcl]);
+	switch (log_info & 0xFF000000) {
+	case MPI_IOCLOGINFO_FC_INIT_BASE:
+		desc = "FCP Initiator";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_BASE:
+		desc = "FCP Target";
+		break;
+	case MPI_IOCLOGINFO_FC_LAN_BASE:
+		desc = "LAN";
+		break;
+	case MPI_IOCLOGINFO_FC_MSG_BASE:
+		desc = "MPI Message Layer";
+		break;
+	case MPI_IOCLOGINFO_FC_LINK_BASE:
+		desc = "FC Link";
+		break;
+	case MPI_IOCLOGINFO_FC_CTX_BASE:
+		desc = "Context Manager";
+		break;
+	case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
+		desc = "Invalid Field Offset";
+		break;
+	case MPI_IOCLOGINFO_FC_STATE_CHANGE:
+		desc = "State Change Info";
+		break;
+	}
+
+	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
+			ioc->name, log_info, desc, (log_info & 0xFFFFFF));
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index d25d3be..05eb6e5 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -75,8 +75,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2007 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.04.04"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.04"
+#define MPT_LINUX_VERSION_COMMON	"3.04.05"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.05"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -436,7 +436,7 @@
 typedef struct _mpt_ioctl_events {
 	u32	event;		/* Specified by define above */
 	u32	eventContext;	/* Index or counter */
-	int	data[2];	/* First 8 bytes of Event Data */
+	u32	data[2];	/* First 8 bytes of Event Data */
 } MPT_IOCTL_EVENTS;
 
 /*
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 9d0f304..58e6c31 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -5,7 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index f7e72c5..180b3c1 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 0caaf64..b766445 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -43,7 +43,6 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#include "linux_compat.h"	/* linux-2.6 tweaks */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 7dd34bd..7e8a90c 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -5,7 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 2000-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index fe438bf..8d08c2b 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -5,7 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 2000-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 1d2d03f..9e5424e 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *  Copyright (c) 2005-2007 Dell
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index fa0f776..d356173 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -44,7 +44,6 @@
 */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-#include "linux_compat.h"	/* linux-2.6 tweaks */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -260,30 +259,13 @@
 	/* Map the data portion, if any.
 	 * sges_left  = 0 if no data transfer.
 	 */
-	if ( (sges_left = SCpnt->use_sg) ) {
-		sges_left = pci_map_sg(ioc->pcidev,
-			       (struct scatterlist *) SCpnt->request_buffer,
- 			       SCpnt->use_sg,
-			       SCpnt->sc_data_direction);
-		if (sges_left == 0)
-			return FAILED;
-	} else if (SCpnt->request_bufflen) {
-		SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
-				      SCpnt->request_buffer,
-				      SCpnt->request_bufflen,
-				      SCpnt->sc_data_direction);
-		dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
-				ioc->name, SCpnt, SCpnt->request_bufflen));
-		mptscsih_add_sge((char *) &pReq->SGL,
-			0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
-			SCpnt->SCp.dma_handle);
-
-		return SUCCESS;
-	}
+	sges_left = scsi_dma_map(SCpnt);
+	if (sges_left < 0)
+		return FAILED;
 
 	/* Handle the SG case.
 	 */
-	sg = (struct scatterlist *) SCpnt->request_buffer;
+	sg = scsi_sglist(SCpnt);
 	sg_done  = 0;
 	sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
 	chainSge = NULL;
@@ -465,7 +447,12 @@
 	MPT_FRAME_HDR *mf;
 	SEPRequest_t 	 *SEPMsg;
 
-	if (ioc->bus_type == FC)
+	if (ioc->bus_type != SAS)
+		return;
+
+	/* Not supported for hidden raid components
+	 */
+	if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
 		return;
 
 	if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
@@ -662,7 +649,7 @@
 		scsi_state = pScsiReply->SCSIState;
 		scsi_status = pScsiReply->SCSIStatus;
 		xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
-		sc->resid = sc->request_bufflen - xfer_cnt;
+		scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
 		log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
 
 		/*
@@ -767,7 +754,7 @@
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
-			sc->resid = sc->request_bufflen - xfer_cnt;
+			scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
 			if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
 				sc->result=DID_SOFT_ERROR << 16;
 			else /* Sufficient data transfer occurred */
@@ -816,7 +803,7 @@
 			break;
 
 		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */
-			sc->resid=0;
+			scsi_set_resid(sc, 0);
 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
 		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
 			sc->result = (DID_OK << 16) | scsi_status;
@@ -899,23 +886,18 @@
 			    scsi_state, scsi_status, log_info));
 
 			dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
-			    "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
-			    sc->device->host->host_no, sc->device->channel, sc->device->id,
-			    sc->device->lun, sc->resid, sc->request_bufflen,
-			    xfer_cnt));
+				      "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
+				      sc->device->host->host_no,
+				      sc->device->channel, sc->device->id,
+				      sc->device->lun, scsi_get_resid(sc),
+				      scsi_bufflen(sc), xfer_cnt));
 		}
 #endif
 
 	} /* end of address reply case */
 
 	/* Unmap the DMA buffers, if any. */
-	if (sc->use_sg) {
-		pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
-			    sc->use_sg, sc->sc_data_direction);
-	} else if (sc->request_bufflen) {
-		pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
-				sc->request_bufflen, sc->sc_data_direction);
-	}
+	scsi_dma_unmap(sc);
 
 	sc->scsi_done(sc);		/* Issue the command callback */
 
@@ -970,17 +952,8 @@
 			/* Set status, free OS resources (SG DMA buffers)
 			 * Do OS callback
 			 */
-			if (SCpnt->use_sg) {
-				pci_unmap_sg(ioc->pcidev,
-					(struct scatterlist *) SCpnt->request_buffer,
-					SCpnt->use_sg,
-					SCpnt->sc_data_direction);
-			} else if (SCpnt->request_bufflen) {
-				pci_unmap_single(ioc->pcidev,
-					SCpnt->SCp.dma_handle,
-					SCpnt->request_bufflen,
-					SCpnt->sc_data_direction);
-			}
+			scsi_dma_unmap(SCpnt);
+
 			SCpnt->result = DID_RESET << 16;
 			SCpnt->host_scribble = NULL;
 
@@ -1023,14 +996,19 @@
 			mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
 			if (mf == NULL)
 				continue;
+			/* If the device is a hidden raid component, then its
+			 * expected that the mf->function will be RAID_SCSI_IO
+			 */
+			if (vdevice->vtarget->tflags &
+			    MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
+			    MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
+				continue;
+
 			int_to_scsilun(vdevice->lun, &lun);
 			if ((mf->Bus != vdevice->vtarget->channel) ||
 			    (mf->TargetID != vdevice->vtarget->id) ||
 			    memcmp(lun.scsi_lun, mf->LUN, 8))
 				continue;
-			dsprintk(( "search_running: found (sc=%p, mf = %p) "
-			    "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
-			    mf, mf->Bus, mf->TargetID, vdevice->lun));
 
 			/* Cleanup
 			 */
@@ -1039,19 +1017,12 @@
 			mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
 			if ((unsigned char *)mf != sc->host_scribble)
 				continue;
-			if (sc->use_sg) {
-				pci_unmap_sg(hd->ioc->pcidev,
-				(struct scatterlist *) sc->request_buffer,
-					sc->use_sg,
-					sc->sc_data_direction);
-			} else if (sc->request_bufflen) {
-				pci_unmap_single(hd->ioc->pcidev,
-					sc->SCp.dma_handle,
-					sc->request_bufflen,
-					sc->sc_data_direction);
-			}
+			scsi_dma_unmap(sc);
 			sc->host_scribble = NULL;
 			sc->result = DID_NO_CONNECT << 16;
+			dsprintk(( "search_running: found (sc=%p, mf = %p) "
+			    "channel %d id %d, lun %d \n", sc, mf,
+			    vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun));
 			sc->scsi_done(sc);
 		}
 	}
@@ -1380,10 +1351,10 @@
 	 *    will be no data transfer!  GRRRRR...
 	 */
 	if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
-		datalen = SCpnt->request_bufflen;
+		datalen = scsi_bufflen(SCpnt);
 		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */
 	} else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
-		datalen = SCpnt->request_bufflen;
+		datalen = scsi_bufflen(SCpnt);
 		scsidir = MPI_SCSIIO_CONTROL_WRITE;	/* DATA OUT (host-->ioc-->dev) */
 	} else {
 		datalen = 0;
@@ -1768,20 +1739,45 @@
 	u32		 ctx2abort;
 	int		 scpnt_idx;
 	int		 retval;
-	VirtDevice	 *vdev;
+	VirtDevice	 *vdevice;
 	ulong	 	 sn = SCpnt->serial_number;
+	MPT_ADAPTER	*ioc;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
 		SCpnt->result = DID_RESET << 16;
 		SCpnt->scsi_done(SCpnt);
-		dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
-			   "Can't locate host! (sc=%p)\n",
-			   SCpnt));
+		dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: Can't locate "
+		    "host! (sc=%p)\n", SCpnt));
 		return FAILED;
 	}
 
+	ioc = hd->ioc;
+	printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
+	       ioc->name, SCpnt);
+	scsi_print_command(SCpnt);
+
+	vdevice = SCpnt->device->hostdata;
+	if (!vdevice || !vdevice->vtarget) {
+		dtmprintk((MYIOC_s_DEBUG_FMT "task abort: device has been "
+		    "deleted (sc=%p)\n", ioc->name, SCpnt));
+		SCpnt->result = DID_NO_CONNECT << 16;
+		SCpnt->scsi_done(SCpnt);
+		retval = 0;
+		goto out;
+	}
+
+	/* Task aborts are not supported for hidden raid components.
+	 */
+	if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+		dtmprintk((MYIOC_s_DEBUG_FMT "task abort: hidden raid "
+		    "component (sc=%p)\n", ioc->name, SCpnt));
+		SCpnt->result = DID_RESET << 16;
+		retval = FAILED;
+		goto out;
+	}
+
 	/* Find this command
 	 */
 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
@@ -1790,21 +1786,20 @@
 		 */
 		SCpnt->result = DID_RESET << 16;
 		dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
-			   "Command not in the active list! (sc=%p)\n",
-			   hd->ioc->name, SCpnt));
-		return SUCCESS;
+		   "Command not in the active list! (sc=%p)\n", ioc->name,
+		   SCpnt));
+		retval = 0;
+		goto out;
 	}
 
-	if (hd->resetPending)
-		return FAILED;
+	if (hd->resetPending) {
+		retval = FAILED;
+		goto out;
+	}
 
 	if (hd->timeouts < -1)
 		hd->timeouts++;
 
-	printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
-	       hd->ioc->name, SCpnt);
-	scsi_print_command(SCpnt);
-
 	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
 	 * (the IO to be ABORT'd)
 	 *
@@ -1817,18 +1812,17 @@
 
 	hd->abortSCpnt = SCpnt;
 
-	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-		vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
-		ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
+	    vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
+	    ctx2abort, mptscsih_get_tm_timeout(ioc));
 
 	if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
 	    SCpnt->serial_number == sn)
 		retval = FAILED;
 
-	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
-		hd->ioc->name,
-		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+ out:
+	printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
+	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
 
 	if (retval == 0)
 		return SUCCESS;
@@ -1850,32 +1844,47 @@
 {
 	MPT_SCSI_HOST	*hd;
 	int		 retval;
-	VirtDevice	 *vdev;
+	VirtDevice	 *vdevice;
+	MPT_ADAPTER	*ioc;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-		dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
-			   "Can't locate host! (sc=%p)\n",
-			   SCpnt));
+		dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: Can't "
+		    "locate host! (sc=%p)\n", SCpnt));
 		return FAILED;
 	}
 
-	if (hd->resetPending)
-		return FAILED;
-
-	printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
-	       hd->ioc->name, SCpnt);
+	ioc = hd->ioc;
+	printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
+	       ioc->name, SCpnt);
 	scsi_print_command(SCpnt);
 
-	vdev = SCpnt->device->hostdata;
-	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-		vdev->vtarget->channel, vdev->vtarget->id,
-		0, 0, mptscsih_get_tm_timeout(hd->ioc));
+	if (hd->resetPending) {
+		retval = FAILED;
+		goto out;
+	}
 
-	printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
-		hd->ioc->name,
-		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+	vdevice = SCpnt->device->hostdata;
+	if (!vdevice || !vdevice->vtarget) {
+		retval = 0;
+		goto out;
+	}
+
+	/* Target reset to hidden raid component is not supported
+	 */
+	if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+		retval = FAILED;
+		goto out;
+	}
+
+	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+	    vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
+	    mptscsih_get_tm_timeout(ioc));
+
+ out:
+	printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
+	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
 
 	if (retval == 0)
 		return SUCCESS;
@@ -1899,18 +1908,19 @@
 	MPT_SCSI_HOST	*hd;
 	int		 retval;
 	VirtDevice	 *vdev;
+	MPT_ADAPTER	*ioc;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-		dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
-			   "Can't locate host! (sc=%p)\n",
-			   SCpnt ) );
+		dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: Can't "
+		    "locate host! (sc=%p)\n", SCpnt ));
 		return FAILED;
 	}
 
-	printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
-	       hd->ioc->name, SCpnt);
+	ioc = hd->ioc;
+	printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
+	       ioc->name, SCpnt);
 	scsi_print_command(SCpnt);
 
 	if (hd->timeouts < -1)
@@ -1918,11 +1928,10 @@
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-		vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
+	    vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
 
-	printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
-		hd->ioc->name,
-		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+	printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
+	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
 
 	if (retval == 0)
 		return SUCCESS;
@@ -1943,37 +1952,38 @@
 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
 {
 	MPT_SCSI_HOST *  hd;
-	int              status = SUCCESS;
+	int              retval;
+	MPT_ADAPTER	*ioc;
 
 	/*  If we can't locate the host to reset, then we failed. */
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-		dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
-			     "Can't locate host! (sc=%p)\n",
-			     SCpnt ) );
+		dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: Can't "
+		    "locate host! (sc=%p)\n", SCpnt));
 		return FAILED;
 	}
 
-	printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
-	       hd->ioc->name, SCpnt);
+	ioc = hd->ioc;
+	printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
+	    ioc->name, SCpnt);
 
 	/*  If our attempts to reset the host failed, then return a failed
 	 *  status.  The host will be taken off line by the SCSI mid-layer.
 	 */
-	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
-		status = FAILED;
+	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
+		retval = FAILED;
 	} else {
 		/*  Make sure TM pending is cleared and TM state is set to
 		 *  NONE.
 		 */
+		retval = 0;
 		hd->tmPending = 0;
 		hd->tmState = TM_STATE_NONE;
 	}
 
-	dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
-		     "Status = %s\n",
-		     (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
+	printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
+	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
 
-	return status;
+	return retval;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2463,11 +2473,11 @@
 				ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
 				ioc->events[idx].eventContext = ioc->eventContext;
 
-				ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
-					(MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
-					(sc->device->channel << 8) || sc->device->id;
+				ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
+					(MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
+					(sc->device->channel << 8) | sc->device->id;
 
-				ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
+				ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
 
 				ioc->eventContext++;
 				if (hd->ioc->pcidev->vendor ==
@@ -3150,6 +3160,16 @@
 {
 	INTERNAL_CMD		 iocmd;
 
+	/* Ignore hidden raid components, this is handled when the command
+	 * is sent to the volume
+	 */
+	if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
+		return;
+
+	if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
+	    !vdevice->configured_lun)
+		return;
+
 	/* Following parameters will not change
 	 * in this routine.
 	 */
@@ -3164,9 +3184,7 @@
 	iocmd.id = vdevice->vtarget->id;
 	iocmd.lun = vdevice->lun;
 
-	if ((vdevice->vtarget->type == TYPE_DISK) &&
-	    (vdevice->configured_lun))
-		mptscsih_do_cmd(hd, &iocmd);
+	mptscsih_do_cmd(hd, &iocmd);
 }
 
 EXPORT_SYMBOL(mptscsih_remove);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 843c01a..8eccdfe 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index d75f7ff..6b3e0c0 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsi.com)
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -44,7 +44,6 @@
 */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-#include "linux_compat.h"	/* linux-2.6 tweaks */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -727,13 +726,15 @@
 	struct _MPT_SCSI_HOST *hd =
 		(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
 	VirtTarget *vtarget = scsi_target(sdev)->hostdata;
-	int ret = mptscsih_slave_configure(sdev);
+	int ret;
+
+	mptspi_initTarget(hd, vtarget, sdev);
+
+	ret = mptscsih_slave_configure(sdev);
 
 	if (ret)
 		return ret;
 
-	mptspi_initTarget(hd, vtarget, sdev);
-
 	ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x"
 		" max_offset=0x%02x max_width=%d\n", hd->ioc->name,
 		sdev->id, spi_min_period(scsi_target(sdev)),
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index f4ac21e..5afa0e3 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -1,9 +1,6 @@
 
-menu "I2O device support"
-	depends on PCI
-
-config I2O
-	tristate "I2O support"
+menuconfig I2O
+	tristate "I2O device support"
 	depends on PCI
 	---help---
 	  The Intelligent Input/Output (I2O) architecture allows hardware
@@ -25,9 +22,10 @@
 
 	  If unsure, say N.
 
+if I2O
+
 config I2O_LCT_NOTIFY_ON_CHANGES
 	bool "Enable LCT notification"
-	depends on I2O
 	default y
 	---help---
 	  Only say N here if you have a I2O controller from SUN. The SUN
@@ -39,7 +37,6 @@
 
 config I2O_EXT_ADAPTEC
 	bool "Enable Adaptec extensions"
-	depends on I2O
 	default y
 	---help---
 	  Say Y for support of raidutils for Adaptec I2O controllers. You also
@@ -57,7 +54,7 @@
 
 config I2O_CONFIG
 	tristate "I2O Configuration support"
-	depends on I2O
+	depends on VIRT_TO_BUS
 	---help---
 	  Say Y for support of the configuration interface for the I2O adapters.
 	  If you have a RAID controller from Adaptec and you want to use the
@@ -78,7 +75,6 @@
 
 config I2O_BUS
 	tristate "I2O Bus Adapter OSM"
-	depends on I2O
 	---help---
 	  Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM
 	  provides access to the busses on the I2O controller. The main purpose
@@ -89,7 +85,7 @@
 
 config I2O_BLOCK
 	tristate "I2O Block OSM"
-	depends on I2O && BLOCK
+	depends on BLOCK
 	---help---
 	  Include support for the I2O Block OSM. The Block OSM presents disk
 	  and other structured block devices to the operating system. If you
@@ -102,7 +98,7 @@
 
 config I2O_SCSI
 	tristate "I2O SCSI OSM"
-	depends on I2O && SCSI
+	depends on SCSI
 	---help---
 	  Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel
 	  I2O controller. You can use both the SCSI and Block OSM together if
@@ -114,7 +110,6 @@
 
 config I2O_PROC
 	tristate "I2O /proc support"
-	depends on I2O
 	---help---
 	  If you say Y here and to "/proc file system support", you will be
 	  able to read I2O related information from the virtual directory
@@ -123,5 +118,4 @@
 	  To compile this support as a module, choose M here: the
 	  module will be called i2o_proc.
 
-endmenu
-
+endif # I2O
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 8abe45e..ce62d8b 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -24,7 +24,7 @@
 	if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
 		return;		// No status in this reply
 
-	printk(KERN_DEBUG "%s%s: ", severity, str);
+	printk("%s%s: ", severity, str);
 
 	if (cmd < 0x1F)		// Utility cmd
 		i2o_report_util_cmd(cmd);
@@ -32,7 +32,7 @@
 	else if (cmd >= 0xA0 && cmd <= 0xEF)	// Executive cmd
 		i2o_report_exec_cmd(cmd);
 	else
-		printk(KERN_DEBUG "Cmd = %0#2x, ", cmd);	// Other cmds
+		printk("Cmd = %0#2x, ", cmd);	// Other cmds
 
 	if (msg[0] & MSG_FAIL) {
 		i2o_report_fail_status(req_status, msg);
@@ -44,7 +44,7 @@
 	if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF))
 		i2o_report_common_dsc(detailed_status);
 	else
-		printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n",
+		printk(" / DetailedStatus = %0#4x.\n",
 		       detailed_status);
 }
 
@@ -89,10 +89,10 @@
 	};
 
 	if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
-		printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
+		printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
 		       req_status);
 	else
-		printk(KERN_DEBUG "TRANSPORT_%s.\n",
+		printk("TRANSPORT_%s.\n",
 		       FAIL_STATUS[req_status & 0x0F]);
 
 	/* Dump some details */
@@ -104,7 +104,7 @@
 	printk(KERN_ERR "  FailingHostUnit = 0x%04X,  FailingIOP = 0x%03X\n",
 	       msg[5] >> 16, msg[5] & 0xFFF);
 
-	printk(KERN_ERR "  Severity:  0x%02X ", (msg[4] >> 16) & 0xFF);
+	printk(KERN_ERR "  Severity:  0x%02X\n", (msg[4] >> 16) & 0xFF);
 	if (msg[4] & (1 << 16))
 		printk(KERN_DEBUG "(FormatError), "
 		       "this msg can never be delivered/processed.\n");
@@ -142,9 +142,9 @@
 	};
 
 	if (req_status >= ARRAY_SIZE(REPLY_STATUS))
-		printk(KERN_DEBUG "RequestStatus = %0#2x", req_status);
+		printk("RequestStatus = %0#2x", req_status);
 	else
-		printk(KERN_DEBUG "%s", REPLY_STATUS[req_status]);
+		printk("%s", REPLY_STATUS[req_status]);
 }
 
 /*
@@ -187,10 +187,10 @@
 	};
 
 	if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE)
-		printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n",
+		printk(" / DetailedStatus = %0#4x.\n",
 		       detailed_status);
 	else
-		printk(KERN_DEBUG " / %s.\n", COMMON_DSC[detailed_status]);
+		printk(" / %s.\n", COMMON_DSC[detailed_status]);
 }
 
 /*
@@ -200,49 +200,49 @@
 {
 	switch (cmd) {
 	case I2O_CMD_UTIL_NOP:
-		printk(KERN_DEBUG "UTIL_NOP, ");
+		printk("UTIL_NOP, ");
 		break;
 	case I2O_CMD_UTIL_ABORT:
-		printk(KERN_DEBUG "UTIL_ABORT, ");
+		printk("UTIL_ABORT, ");
 		break;
 	case I2O_CMD_UTIL_CLAIM:
-		printk(KERN_DEBUG "UTIL_CLAIM, ");
+		printk("UTIL_CLAIM, ");
 		break;
 	case I2O_CMD_UTIL_RELEASE:
-		printk(KERN_DEBUG "UTIL_CLAIM_RELEASE, ");
+		printk("UTIL_CLAIM_RELEASE, ");
 		break;
 	case I2O_CMD_UTIL_CONFIG_DIALOG:
-		printk(KERN_DEBUG "UTIL_CONFIG_DIALOG, ");
+		printk("UTIL_CONFIG_DIALOG, ");
 		break;
 	case I2O_CMD_UTIL_DEVICE_RESERVE:
-		printk(KERN_DEBUG "UTIL_DEVICE_RESERVE, ");
+		printk("UTIL_DEVICE_RESERVE, ");
 		break;
 	case I2O_CMD_UTIL_DEVICE_RELEASE:
-		printk(KERN_DEBUG "UTIL_DEVICE_RELEASE, ");
+		printk("UTIL_DEVICE_RELEASE, ");
 		break;
 	case I2O_CMD_UTIL_EVT_ACK:
-		printk(KERN_DEBUG "UTIL_EVENT_ACKNOWLEDGE, ");
+		printk("UTIL_EVENT_ACKNOWLEDGE, ");
 		break;
 	case I2O_CMD_UTIL_EVT_REGISTER:
-		printk(KERN_DEBUG "UTIL_EVENT_REGISTER, ");
+		printk("UTIL_EVENT_REGISTER, ");
 		break;
 	case I2O_CMD_UTIL_LOCK:
-		printk(KERN_DEBUG "UTIL_LOCK, ");
+		printk("UTIL_LOCK, ");
 		break;
 	case I2O_CMD_UTIL_LOCK_RELEASE:
-		printk(KERN_DEBUG "UTIL_LOCK_RELEASE, ");
+		printk("UTIL_LOCK_RELEASE, ");
 		break;
 	case I2O_CMD_UTIL_PARAMS_GET:
-		printk(KERN_DEBUG "UTIL_PARAMS_GET, ");
+		printk("UTIL_PARAMS_GET, ");
 		break;
 	case I2O_CMD_UTIL_PARAMS_SET:
-		printk(KERN_DEBUG "UTIL_PARAMS_SET, ");
+		printk("UTIL_PARAMS_SET, ");
 		break;
 	case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY:
-		printk(KERN_DEBUG "UTIL_REPLY_FAULT_NOTIFY, ");
+		printk("UTIL_REPLY_FAULT_NOTIFY, ");
 		break;
 	default:
-		printk(KERN_DEBUG "Cmd = %0#2x, ", cmd);
+		printk("Cmd = %0#2x, ", cmd);
 	}
 }
 
@@ -253,106 +253,106 @@
 {
 	switch (cmd) {
 	case I2O_CMD_ADAPTER_ASSIGN:
-		printk(KERN_DEBUG "EXEC_ADAPTER_ASSIGN, ");
+		printk("EXEC_ADAPTER_ASSIGN, ");
 		break;
 	case I2O_CMD_ADAPTER_READ:
-		printk(KERN_DEBUG "EXEC_ADAPTER_READ, ");
+		printk("EXEC_ADAPTER_READ, ");
 		break;
 	case I2O_CMD_ADAPTER_RELEASE:
-		printk(KERN_DEBUG "EXEC_ADAPTER_RELEASE, ");
+		printk("EXEC_ADAPTER_RELEASE, ");
 		break;
 	case I2O_CMD_BIOS_INFO_SET:
-		printk(KERN_DEBUG "EXEC_BIOS_INFO_SET, ");
+		printk("EXEC_BIOS_INFO_SET, ");
 		break;
 	case I2O_CMD_BOOT_DEVICE_SET:
-		printk(KERN_DEBUG "EXEC_BOOT_DEVICE_SET, ");
+		printk("EXEC_BOOT_DEVICE_SET, ");
 		break;
 	case I2O_CMD_CONFIG_VALIDATE:
-		printk(KERN_DEBUG "EXEC_CONFIG_VALIDATE, ");
+		printk("EXEC_CONFIG_VALIDATE, ");
 		break;
 	case I2O_CMD_CONN_SETUP:
-		printk(KERN_DEBUG "EXEC_CONN_SETUP, ");
+		printk("EXEC_CONN_SETUP, ");
 		break;
 	case I2O_CMD_DDM_DESTROY:
-		printk(KERN_DEBUG "EXEC_DDM_DESTROY, ");
+		printk("EXEC_DDM_DESTROY, ");
 		break;
 	case I2O_CMD_DDM_ENABLE:
-		printk(KERN_DEBUG "EXEC_DDM_ENABLE, ");
+		printk("EXEC_DDM_ENABLE, ");
 		break;
 	case I2O_CMD_DDM_QUIESCE:
-		printk(KERN_DEBUG "EXEC_DDM_QUIESCE, ");
+		printk("EXEC_DDM_QUIESCE, ");
 		break;
 	case I2O_CMD_DDM_RESET:
-		printk(KERN_DEBUG "EXEC_DDM_RESET, ");
+		printk("EXEC_DDM_RESET, ");
 		break;
 	case I2O_CMD_DDM_SUSPEND:
-		printk(KERN_DEBUG "EXEC_DDM_SUSPEND, ");
+		printk("EXEC_DDM_SUSPEND, ");
 		break;
 	case I2O_CMD_DEVICE_ASSIGN:
-		printk(KERN_DEBUG "EXEC_DEVICE_ASSIGN, ");
+		printk("EXEC_DEVICE_ASSIGN, ");
 		break;
 	case I2O_CMD_DEVICE_RELEASE:
-		printk(KERN_DEBUG "EXEC_DEVICE_RELEASE, ");
+		printk("EXEC_DEVICE_RELEASE, ");
 		break;
 	case I2O_CMD_HRT_GET:
-		printk(KERN_DEBUG "EXEC_HRT_GET, ");
+		printk("EXEC_HRT_GET, ");
 		break;
 	case I2O_CMD_ADAPTER_CLEAR:
-		printk(KERN_DEBUG "EXEC_IOP_CLEAR, ");
+		printk("EXEC_IOP_CLEAR, ");
 		break;
 	case I2O_CMD_ADAPTER_CONNECT:
-		printk(KERN_DEBUG "EXEC_IOP_CONNECT, ");
+		printk("EXEC_IOP_CONNECT, ");
 		break;
 	case I2O_CMD_ADAPTER_RESET:
-		printk(KERN_DEBUG "EXEC_IOP_RESET, ");
+		printk("EXEC_IOP_RESET, ");
 		break;
 	case I2O_CMD_LCT_NOTIFY:
-		printk(KERN_DEBUG "EXEC_LCT_NOTIFY, ");
+		printk("EXEC_LCT_NOTIFY, ");
 		break;
 	case I2O_CMD_OUTBOUND_INIT:
-		printk(KERN_DEBUG "EXEC_OUTBOUND_INIT, ");
+		printk("EXEC_OUTBOUND_INIT, ");
 		break;
 	case I2O_CMD_PATH_ENABLE:
-		printk(KERN_DEBUG "EXEC_PATH_ENABLE, ");
+		printk("EXEC_PATH_ENABLE, ");
 		break;
 	case I2O_CMD_PATH_QUIESCE:
-		printk(KERN_DEBUG "EXEC_PATH_QUIESCE, ");
+		printk("EXEC_PATH_QUIESCE, ");
 		break;
 	case I2O_CMD_PATH_RESET:
-		printk(KERN_DEBUG "EXEC_PATH_RESET, ");
+		printk("EXEC_PATH_RESET, ");
 		break;
 	case I2O_CMD_STATIC_MF_CREATE:
-		printk(KERN_DEBUG "EXEC_STATIC_MF_CREATE, ");
+		printk("EXEC_STATIC_MF_CREATE, ");
 		break;
 	case I2O_CMD_STATIC_MF_RELEASE:
-		printk(KERN_DEBUG "EXEC_STATIC_MF_RELEASE, ");
+		printk("EXEC_STATIC_MF_RELEASE, ");
 		break;
 	case I2O_CMD_STATUS_GET:
-		printk(KERN_DEBUG "EXEC_STATUS_GET, ");
+		printk("EXEC_STATUS_GET, ");
 		break;
 	case I2O_CMD_SW_DOWNLOAD:
-		printk(KERN_DEBUG "EXEC_SW_DOWNLOAD, ");
+		printk("EXEC_SW_DOWNLOAD, ");
 		break;
 	case I2O_CMD_SW_UPLOAD:
-		printk(KERN_DEBUG "EXEC_SW_UPLOAD, ");
+		printk("EXEC_SW_UPLOAD, ");
 		break;
 	case I2O_CMD_SW_REMOVE:
-		printk(KERN_DEBUG "EXEC_SW_REMOVE, ");
+		printk("EXEC_SW_REMOVE, ");
 		break;
 	case I2O_CMD_SYS_ENABLE:
-		printk(KERN_DEBUG "EXEC_SYS_ENABLE, ");
+		printk("EXEC_SYS_ENABLE, ");
 		break;
 	case I2O_CMD_SYS_MODIFY:
-		printk(KERN_DEBUG "EXEC_SYS_MODIFY, ");
+		printk("EXEC_SYS_MODIFY, ");
 		break;
 	case I2O_CMD_SYS_QUIESCE:
-		printk(KERN_DEBUG "EXEC_SYS_QUIESCE, ");
+		printk("EXEC_SYS_QUIESCE, ");
 		break;
 	case I2O_CMD_SYS_TAB_SET:
-		printk(KERN_DEBUG "EXEC_SYS_TAB_SET, ");
+		printk("EXEC_SYS_TAB_SET, ");
 		break;
 	default:
-		printk(KERN_DEBUG "Cmd = %#02x, ", cmd);
+		printk("Cmd = %#02x, ", cmd);
 	}
 }
 
@@ -361,28 +361,28 @@
 	printk(KERN_INFO "%s: State = ", c->name);
 	switch (((i2o_status_block *) c->status_block.virt)->iop_state) {
 	case 0x01:
-		printk(KERN_DEBUG "INIT\n");
+		printk("INIT\n");
 		break;
 	case 0x02:
-		printk(KERN_DEBUG "RESET\n");
+		printk("RESET\n");
 		break;
 	case 0x04:
-		printk(KERN_DEBUG "HOLD\n");
+		printk("HOLD\n");
 		break;
 	case 0x05:
-		printk(KERN_DEBUG "READY\n");
+		printk("READY\n");
 		break;
 	case 0x08:
-		printk(KERN_DEBUG "OPERATIONAL\n");
+		printk("OPERATIONAL\n");
 		break;
 	case 0x10:
-		printk(KERN_DEBUG "FAILED\n");
+		printk("FAILED\n");
 		break;
 	case 0x11:
-		printk(KERN_DEBUG "FAULTED\n");
+		printk("FAULTED\n");
 		break;
 	default:
-		printk(KERN_DEBUG "%x (unknown !!)\n",
+		printk("%x (unknown !!)\n",
 		       ((i2o_status_block *) c->status_block.virt)->iop_state);
 	}
 };
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index b9df143..489d7c5 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -62,7 +62,7 @@
 {
 	int rc = 0;
 
-	down(&dev->lock);
+	mutex_lock(&dev->lock);
 
 	rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);
 	if (!rc)
@@ -72,7 +72,7 @@
 		pr_debug("i2o: claim of device %d failed %d\n",
 			 dev->lct_data.tid, rc);
 
-	up(&dev->lock);
+	mutex_unlock(&dev->lock);
 
 	return rc;
 }
@@ -96,7 +96,7 @@
 	int tries;
 	int rc = 0;
 
-	down(&dev->lock);
+	mutex_lock(&dev->lock);
 
 	/*
 	 *      If the controller takes a nonblocking approach to
@@ -118,7 +118,7 @@
 		pr_debug("i2o: claim release of device %d failed %d\n",
 			 dev->lct_data.tid, rc);
 
-	up(&dev->lock);
+	mutex_unlock(&dev->lock);
 
 	return rc;
 }
@@ -198,7 +198,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&dev->list);
-	init_MUTEX(&dev->lock);
+	mutex_init(&dev->lock);
 
 	dev->device.bus = &i2o_bus_type;
 	dev->device.release = &i2o_device_release;
@@ -326,7 +326,7 @@
 	u16 table_size;
 	u32 buf;
 
-	down(&c->lct_lock);
+	mutex_lock(&c->lct_lock);
 
 	kfree(c->lct);
 
@@ -335,7 +335,7 @@
 
 	lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL);
 	if (!lct) {
-		up(&c->lct_lock);
+		mutex_unlock(&c->lct_lock);
 		return -ENOMEM;
 	}
 
@@ -408,7 +408,7 @@
 			i2o_device_remove(dev);
 	}
 
-	up(&c->lct_lock);
+	mutex_unlock(&c->lct_lock);
 
 	return 0;
 }
@@ -485,7 +485,7 @@
 	u8 *resblk;		/* 8 bytes for header */
 	int rc;
 
-	resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC);
+	resblk = kmalloc(buflen + 8, GFP_KERNEL);
 	if (!resblk)
 		return -ENOMEM;
 
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index d3235f2..e0d474b 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -123,8 +123,12 @@
 	}
 
 	rc = driver_register(&drv->driver);
-	if (rc)
-		destroy_workqueue(drv->event_queue);
+	if (rc) {
+		if (drv->event) {
+			destroy_workqueue(drv->event_queue);
+			drv->event_queue = NULL;
+		}
+	}
 
 	return rc;
 };
@@ -256,7 +260,7 @@
 	int i;
 	struct i2o_driver *drv;
 
-	for (i = 0; i < I2O_MAX_DRIVERS; i++) {
+	for (i = 0; i < i2o_max_drivers; i++) {
 		drv = i2o_drivers[i];
 
 		if (drv)
@@ -276,7 +280,7 @@
 	int i;
 	struct i2o_driver *drv;
 
-	for (i = 0; i < I2O_MAX_DRIVERS; i++) {
+	for (i = 0; i < i2o_max_drivers; i++) {
 		drv = i2o_drivers[i];
 
 		if (drv)
@@ -295,7 +299,7 @@
 	int i;
 	struct i2o_driver *drv;
 
-	for (i = 0; i < I2O_MAX_DRIVERS; i++) {
+	for (i = 0; i < i2o_max_drivers; i++) {
 		drv = i2o_drivers[i];
 
 		if (drv)
@@ -314,7 +318,7 @@
 	int i;
 	struct i2o_driver *drv;
 
-	for (i = 0; i < I2O_MAX_DRIVERS; i++) {
+	for (i = 0; i < i2o_max_drivers; i++) {
 		drv = i2o_drivers[i];
 
 		if (drv)
@@ -335,17 +339,15 @@
 
 	spin_lock_init(&i2o_drivers_lock);
 
-	if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
-	    ((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
-	     (2 * i2o_max_drivers - 1))) {
-		osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and "
-			 "a power of 2\n", i2o_max_drivers);
+	if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) {
+		osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n",
+			 i2o_max_drivers);
 		i2o_max_drivers = I2O_MAX_DRIVERS;
 	}
 	osm_info("max drivers = %d\n", i2o_max_drivers);
 
 	i2o_drivers =
-	    kzalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
+	    kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL);
 	if (!i2o_drivers)
 		return -ENOMEM;
 
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 5278aad..8c83ee3 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -131,8 +131,10 @@
 	int rc = 0;
 
 	wait = i2o_exec_wait_alloc();
-	if (!wait)
+	if (!wait) {
+		i2o_msg_nop(c, msg);
 		return -ENOMEM;
+	}
 
 	if (tcntxt == 0xffffffff)
 		tcntxt = 0x80000000;
@@ -337,6 +339,8 @@
 	rc = device_create_file(dev, &dev_attr_product_id);
 	if (rc) goto err_vid;
 
+	i2o_dev->iop->exec = i2o_dev;
+
 	return 0;
 
 err_vid:
@@ -537,7 +541,7 @@
 	struct device *dev;
 	struct i2o_message *msg;
 
-	down(&c->lct_lock);
+	mutex_lock(&c->lct_lock);
 
 	dev = &c->pdev->dev;
 
@@ -561,7 +565,7 @@
 
 	i2o_msg_post(c, msg);
 
-	up(&c->lct_lock);
+	mutex_unlock(&c->lct_lock);
 
 	return 0;
 };
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index b17c4b2..64a52bd 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -215,7 +215,7 @@
 	struct i2o_message *msg;
 
 	msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
-	if (IS_ERR(msg) == I2O_QUEUE_EMPTY)
+	if (IS_ERR(msg))
 		return PTR_ERR(msg);
 
 	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 8ba275a..84e046e 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -554,8 +554,6 @@
 		return -ENXIO;
 	}
 
-	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
-
 	sb = c->status_block.virt;
 
 	if (get_user(size, &user_msg[0])) {
@@ -573,24 +571,30 @@
 
 	size <<= 2;		// Convert to bytes
 
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
+
+	rcode = -EFAULT;
 	/* Copy in the user's I2O command */
 	if (copy_from_user(msg, user_msg, size)) {
 		osm_warn("unable to copy user message\n");
-		return -EFAULT;
+		goto out;
 	}
 	i2o_dump_message(msg);
 
 	if (get_user(reply_size, &user_reply[0]) < 0)
-		return -EFAULT;
+		goto out;
 
 	reply_size >>= 16;
 	reply_size <<= 2;
 
+	rcode = -ENOMEM;
 	reply = kzalloc(reply_size, GFP_KERNEL);
 	if (!reply) {
 		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
 		       c->name);
-		return -ENOMEM;
+		goto out;
 	}
 
 	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
@@ -661,13 +665,14 @@
 	}
 
 	rcode = i2o_msg_post_wait(c, msg, 60);
+	msg = NULL;
 	if (rcode) {
 		reply[4] = ((u32) rcode) << 24;
 		goto sg_list_cleanup;
 	}
 
 	if (sg_offset) {
-		u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
+		u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE];
 		/* Copy back the Scatter Gather buffers back to user space */
 		u32 j;
 		// TODO 64bit fix
@@ -675,7 +680,7 @@
 		int sg_size;
 
 		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
+		memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
 		// get user msg size in u32s
 		if (get_user(size, &user_msg[0])) {
 			rcode = -EFAULT;
@@ -684,7 +689,7 @@
 		size = size >> 16;
 		size *= 4;
 		/* Copy in the user's I2O command */
-		if (copy_from_user(msg, user_msg, size)) {
+		if (copy_from_user(rmsg, user_msg, size)) {
 			rcode = -EFAULT;
 			goto sg_list_cleanup;
 		}
@@ -692,7 +697,7 @@
 		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
 
 		// TODO 64bit fix
-		sg = (struct sg_simple_element *)(msg + sg_offset);
+		sg = (struct sg_simple_element *)(rmsg + sg_offset);
 		for (j = 0; j < sg_count; j++) {
 			/* Copy out the SG list to user's buffer if necessary */
 			if (!
@@ -714,7 +719,7 @@
 		}
 	}
 
-      sg_list_cleanup:
+sg_list_cleanup:
 	/* Copy back the reply to user space */
 	if (reply_size) {
 		// we wrote our own values for context - now restore the user supplied ones
@@ -723,7 +728,6 @@
 			       "%s: Could not copy message context FROM user\n",
 			       c->name);
 			rcode = -EFAULT;
-			goto sg_list_cleanup;
 		}
 		if (copy_to_user(user_reply, reply, reply_size)) {
 			printk(KERN_WARNING
@@ -731,12 +735,14 @@
 			rcode = -EFAULT;
 		}
 	}
-
 	for (i = 0; i < sg_index; i++)
 		i2o_dma_free(&c->pdev->dev, &sg_list[i]);
 
-      cleanup:
+cleanup:
 	kfree(reply);
+out:
+	if (msg)
+		i2o_msg_nop(c, msg);
 	return rcode;
 }
 
@@ -793,8 +799,6 @@
 		return -ENXIO;
 	}
 
-	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
-
 	sb = c->status_block.virt;
 
 	if (get_user(size, &user_msg[0]))
@@ -810,12 +814,17 @@
 
 	size <<= 2;		// Convert to bytes
 
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
+
+	rcode = -EFAULT;
 	/* Copy in the user's I2O command */
 	if (copy_from_user(msg, user_msg, size))
-		return -EFAULT;
+		goto out;
 
 	if (get_user(reply_size, &user_reply[0]) < 0)
-		return -EFAULT;
+		goto out;
 
 	reply_size >>= 16;
 	reply_size <<= 2;
@@ -824,7 +833,8 @@
 	if (!reply) {
 		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
 		       c->name);
-		return -ENOMEM;
+		rcode = -ENOMEM;
+		goto out;
 	}
 
 	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
@@ -891,13 +901,14 @@
 	}
 
 	rcode = i2o_msg_post_wait(c, msg, 60);
+	msg = NULL;
 	if (rcode) {
 		reply[4] = ((u32) rcode) << 24;
 		goto sg_list_cleanup;
 	}
 
 	if (sg_offset) {
-		u32 msg[128];
+		u32 rmsg[128];
 		/* Copy back the Scatter Gather buffers back to user space */
 		u32 j;
 		// TODO 64bit fix
@@ -905,7 +916,7 @@
 		int sg_size;
 
 		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
+		memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
 		// get user msg size in u32s
 		if (get_user(size, &user_msg[0])) {
 			rcode = -EFAULT;
@@ -914,7 +925,7 @@
 		size = size >> 16;
 		size *= 4;
 		/* Copy in the user's I2O command */
-		if (copy_from_user(msg, user_msg, size)) {
+		if (copy_from_user(rmsg, user_msg, size)) {
 			rcode = -EFAULT;
 			goto sg_list_cleanup;
 		}
@@ -922,7 +933,7 @@
 		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
 
 		// TODO 64bit fix
-		sg = (struct sg_simple_element *)(msg + sg_offset);
+		sg = (struct sg_simple_element *)(rmsg + sg_offset);
 		for (j = 0; j < sg_count; j++) {
 			/* Copy out the SG list to user's buffer if necessary */
 			if (!
@@ -944,7 +955,7 @@
 		}
 	}
 
-      sg_list_cleanup:
+sg_list_cleanup:
 	/* Copy back the reply to user space */
 	if (reply_size) {
 		// we wrote our own values for context - now restore the user supplied ones
@@ -964,8 +975,11 @@
 	for (i = 0; i < sg_index; i++)
 		kfree(sg_list[i]);
 
-      cleanup:
+cleanup:
 	kfree(reply);
+out:
+	if (msg)
+		i2o_msg_nop(c, msg);
 	return rcode;
 }
 #endif
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 1045c8a..aa6fb94 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -377,12 +377,8 @@
 		osm_err("SCSI error %08x\n", error);
 
 	dev = &c->pdev->dev;
-	if (cmd->use_sg)
-		dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
-			     cmd->sc_data_direction);
-	else if (cmd->SCp.dma_handle)
-		dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen,
-				 cmd->sc_data_direction);
+
+	scsi_dma_unmap(cmd);
 
 	cmd->scsi_done(cmd);
 
@@ -664,21 +660,15 @@
 
 	if (sgl_offset != SGL_OFFSET_0) {
 		/* write size of data addressed by SGL */
-		*mptr++ = cpu_to_le32(SCpnt->request_bufflen);
+		*mptr++ = cpu_to_le32(scsi_bufflen(SCpnt));
 
 		/* Now fill in the SGList and command */
-		if (SCpnt->use_sg) {
-			if (!i2o_dma_map_sg(c, SCpnt->request_buffer,
-					    SCpnt->use_sg,
+
+		if (scsi_sg_count(SCpnt)) {
+			if (!i2o_dma_map_sg(c, scsi_sglist(SCpnt),
+					    scsi_sg_count(SCpnt),
 					    SCpnt->sc_data_direction, &mptr))
 				goto nomem;
-		} else {
-			SCpnt->SCp.dma_handle =
-			    i2o_dma_map_single(c, SCpnt->request_buffer,
-					       SCpnt->request_bufflen,
-					       SCpnt->sc_data_direction, &mptr);
-			if (dma_mapping_error(SCpnt->SCp.dma_handle))
-				goto nomem;
 		}
 	}
 
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 3305c12..a1ec16a07 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -1067,7 +1067,7 @@
 
 	INIT_LIST_HEAD(&c->devices);
 	spin_lock_init(&c->lock);
-	init_MUTEX(&c->lct_lock);
+	mutex_init(&c->lct_lock);
 
 	device_initialize(&c->device);
 
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index b0b4458..8135e4c 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -41,6 +41,9 @@
 	struct resource			*regs_claim;
 	struct sm501_platdata		*platdata;
 
+	unsigned int			 in_suspend;
+	unsigned long			 pm_misc;
+
 	int				 unit_power[20];
 	unsigned int			 pdev_id;
 	unsigned int			 irq;
@@ -169,10 +172,41 @@
 		fmt_freq(decode_div(pll2, pm1, 8,  1<<12, 15, misc_div)),
 		fmt_freq(decode_div(pll2, pm1, 0,  1<<4,  15, misc_div)));
 }
-#else
-static void sm501_dump_clk(struct sm501_devdata *sm)
+
+static void sm501_dump_regs(struct sm501_devdata *sm)
 {
+	void __iomem *regs = sm->regs;
+
+	dev_info(sm->dev, "System Control   %08x\n",
+			readl(regs + SM501_SYSTEM_CONTROL));
+	dev_info(sm->dev, "Misc Control     %08x\n",
+			readl(regs + SM501_MISC_CONTROL));
+	dev_info(sm->dev, "GPIO Control Low %08x\n",
+			readl(regs + SM501_GPIO31_0_CONTROL));
+	dev_info(sm->dev, "GPIO Control Hi  %08x\n",
+			readl(regs + SM501_GPIO63_32_CONTROL));
+	dev_info(sm->dev, "DRAM Control     %08x\n",
+			readl(regs + SM501_DRAM_CONTROL));
+	dev_info(sm->dev, "Arbitration Ctrl %08x\n",
+			readl(regs + SM501_ARBTRTN_CONTROL));
+	dev_info(sm->dev, "Misc Timing      %08x\n",
+			readl(regs + SM501_MISC_TIMING));
 }
+
+static void sm501_dump_gate(struct sm501_devdata *sm)
+{
+	dev_info(sm->dev, "CurrentGate      %08x\n",
+			readl(sm->regs + SM501_CURRENT_GATE));
+	dev_info(sm->dev, "CurrentClock     %08x\n",
+			readl(sm->regs + SM501_CURRENT_CLOCK));
+	dev_info(sm->dev, "PowerModeControl %08x\n",
+			readl(sm->regs + SM501_POWER_MODE_CONTROL));
+}
+
+#else
+static inline void sm501_dump_gate(struct sm501_devdata *sm) { }
+static inline void sm501_dump_regs(struct sm501_devdata *sm) { }
+static inline void sm501_dump_clk(struct sm501_devdata *sm) { }
 #endif
 
 /* sm501_sync_regs
@@ -185,9 +219,21 @@
 	readl(sm->regs);
 }
 
+static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
+{
+	/* during suspend/resume, we are currently not allowed to sleep,
+	 * so change to using mdelay() instead of msleep() if we
+	 * are in one of these paths */
+
+	if (sm->in_suspend)
+		mdelay(delay);
+	else
+		msleep(delay);
+}
+
 /* sm501_misc_control
  *
- * alters the misceleneous control parameters
+ * alters the miscellaneous control parameters
 */
 
 int sm501_misc_control(struct device *dev,
@@ -368,7 +414,7 @@
 	dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
 		gate, clock, mode);
 
-	msleep(16);
+	sm501_mdelay(sm, 16);
 
  already:
 	mutex_unlock(&sm->clock_lock);
@@ -538,7 +584,7 @@
 	dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
 		 gate, clock, mode);
 
-	msleep(16);
+	sm501_mdelay(sm, 16);
 	mutex_unlock(&sm->clock_lock);
 
 	sm501_dump_clk(sm);
@@ -767,6 +813,9 @@
 /* sm501_init_reg
  *
  * Helper function for the init code to setup a register
+ *
+ * clear the bits which are set in r->mask, and then set
+ * the bits set in r->set.
 */
 
 static inline void sm501_init_reg(struct sm501_devdata *sm,
@@ -776,8 +825,8 @@
 	unsigned long tmp;
 
 	tmp = readl(sm->regs + reg);
-	tmp |= r->set;
 	tmp &= ~r->mask;
+	tmp |= r->set;
 	writel(tmp, sm->regs + reg);
 }
 
@@ -797,15 +846,33 @@
 	sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low);
 	sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high);
 
+	if (init->m1xclk) {
+		dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk);
+		sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk);
+	}
+
 	if (init->mclk) {
 		dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk);
 		sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk);
 	}
 
-	if (init->m1xclk) {
-		dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk);
-		sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk);
-	}
+}
+
+/* Check the PLL sources for the M1CLK and M1XCLK
+ *
+ * If the M1CLK and M1XCLKs are not sourced from the same PLL, then
+ * there is a risk (see errata AB-5) that the SM501 will cease proper
+ * function. If this happens, then it is likely the SM501 will
+ * hang the system.
+*/
+
+static int sm501_check_clocks(struct sm501_devdata *sm)
+{
+	unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK);
+	unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC);
+	unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC);
+
+	return ((msrc == 0 && m1src != 0) || (msrc != 0 && m1src == 0));
 }
 
 static unsigned int sm501_mem_local[] = {
@@ -826,6 +893,7 @@
 {
 	resource_size_t mem_avail;
 	unsigned long dramctrl;
+	unsigned long devid;
 	int ret;
 
 	mutex_init(&sm->clock_lock);
@@ -833,17 +901,20 @@
 
 	INIT_LIST_HEAD(&sm->devices);
 
-	dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+	devid = readl(sm->regs + SM501_DEVICEID);
 
+	if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) {
+		dev_err(sm->dev, "incorrect device id %08lx\n", devid);
+		return -EINVAL;
+	}
+
+	dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
 	mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
 
-	dev_info(sm->dev, "SM501 At %p: Version %08x, %ld Mb, IRQ %d\n",
-		 sm->regs, readl(sm->regs + SM501_DEVICEID),
-		 (unsigned long)mem_avail >> 20, sm->irq);
+	dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n",
+		 sm->regs, devid, (unsigned long)mem_avail >> 20, sm->irq);
 
-	dev_info(sm->dev, "CurrentGate      %08x\n", readl(sm->regs+0x38));
-	dev_info(sm->dev, "CurrentClock     %08x\n", readl(sm->regs+0x3c));
-	dev_info(sm->dev, "PowerModeControl %08x\n", readl(sm->regs+0x54));
+	sm501_dump_gate(sm);
 
 	ret = device_create_file(sm->dev, &dev_attr_dbg_regs);
 	if (ret)
@@ -864,6 +935,13 @@
 		}
 	}
 
+	ret = sm501_check_clocks(sm);
+	if (ret) {
+		dev_err(sm->dev, "M1X and M clocks sourced from different "
+					"PLLs\n");
+		return -EINVAL;
+	}
+
 	/* always create a framebuffer */
 	sm501_register_display(sm, &mem_avail);
 
@@ -933,6 +1011,57 @@
 
 }
 
+#ifdef CONFIG_PM
+/* power management support */
+
+static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct sm501_devdata *sm = platform_get_drvdata(pdev);
+
+	sm->in_suspend = 1;
+	sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
+
+	sm501_dump_regs(sm);
+	return 0;
+}
+
+static int sm501_plat_resume(struct platform_device *pdev)
+{
+	struct sm501_devdata *sm = platform_get_drvdata(pdev);
+
+	sm501_dump_regs(sm);
+	sm501_dump_gate(sm);
+	sm501_dump_clk(sm);
+
+	/* check to see if we are in the same state as when suspended */
+
+	if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
+		dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n");
+		writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
+
+		/* our suspend causes the controller state to change,
+		 * either by something attempting setup, power loss,
+		 * or an external reset event on power change */
+
+		if (sm->platdata && sm->platdata->init) {
+			sm501_init_regs(sm, sm->platdata->init);
+		}
+	}
+
+	/* dump our state from resume */
+
+	sm501_dump_regs(sm);
+	sm501_dump_clk(sm);
+
+	sm->in_suspend = 0;
+
+	return 0;
+}
+#else
+#define sm501_plat_suspend NULL
+#define sm501_plat_resume NULL
+#endif
+
 /* Initialisation data for PCI devices */
 
 static struct sm501_initdata sm501_pci_initdata = {
@@ -950,8 +1079,12 @@
 	},
 
 	.devices	= SM501_USE_ALL,
-	.mclk		= 100 * MHZ,
-	.m1xclk		= 160 * MHZ,
+
+	/* Errata AB-3 says that 72MHz is the fastest available
+	 * for 33MHZ PCI with proper bus-mastering operation */
+
+	.mclk		= 72 * MHZ,
+	.m1xclk		= 144 * MHZ,
 };
 
 static struct sm501_platdata_fbsub sm501_pdata_fbsub = {
@@ -1126,6 +1259,8 @@
 	},
 	.probe		= sm501_plat_probe,
 	.remove		= sm501_plat_remove,
+	.suspend	= sm501_plat_suspend,
+	.resume		= sm501_plat_resume,
 };
 
 static int __init sm501_base_init(void)
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index cb8c264..fdbaa77 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -207,17 +207,9 @@
 	struct ucb1x00_ts *ts = _ts;
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
-	int valid;
+	int valid = 0;
 
-	/*
-	 * We could run as a real-time thread.  However, thus far
-	 * this doesn't seem to be necessary.
-	 */
-//	tsk->policy = SCHED_FIFO;
-//	tsk->rt_priority = 1;
-
-	valid = 0;
-
+	set_freezable();
 	add_wait_queue(&ts->irq_wait, &wait);
 	while (!kthread_should_stop()) {
 		unsigned int x, y, p;
@@ -300,7 +292,7 @@
 
 static int ucb1x00_ts_open(struct input_dev *idev)
 {
-	struct ucb1x00_ts *ts = idev->private;
+	struct ucb1x00_ts *ts = input_get_drvdata(idev);
 	int ret = 0;
 
 	BUG_ON(ts->rtask);
@@ -337,7 +329,7 @@
  */
 static void ucb1x00_ts_close(struct input_dev *idev)
 {
-	struct ucb1x00_ts *ts = idev->private;
+	struct ucb1x00_ts *ts = input_get_drvdata(idev);
 
 	if (ts->rtask)
 		kthread_stop(ts->rtask);
@@ -389,7 +381,6 @@
 	ts->idev = idev;
 	ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
 
-	idev->private    = ts;
 	idev->name       = "Touchscreen panel";
 	idev->id.product = ts->ucb->id;
 	idev->open       = ucb1x00_ts_open;
@@ -400,6 +391,8 @@
 	__set_bit(ABS_Y, idev->absbit);
 	__set_bit(ABS_PRESSURE, idev->absbit);
 
+	input_set_drvdata(idev, ts);
+
 	err = input_register_device(idev);
 	if (err)
 		goto fail;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2f2fbff..1d516f2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -2,11 +2,15 @@
 # Misc strange devices
 #
 
-menu "Misc devices"
+menuconfig MISC_DEVICES
+	bool "Misc devices"
+	default y
+
+if MISC_DEVICES
 
 config IBM_ASM
 	tristate "Device driver for IBM RSA service processor"
-	depends on X86 && PCI && EXPERIMENTAL
+	depends on X86 && PCI && INPUT && EXPERIMENTAL
 	---help---
 	  This option enables device driver support for in-band access to the
 	  IBM RSA (Condor) service processor in eServer xSeries systems.
@@ -34,6 +38,11 @@
 	  If you choose to build module, its name will be phantom. If unsure,
 	  say N here.
 
+config EEPROM_93CX6
+	tristate "EEPROM 93CX6 support"
+	---help---
+	  This is a driver for the EEPROM chipsets 93c46 and 93c66.
+	  The driver supports both read as well as write commands.
 
 	  If unsure, say N.
 
@@ -187,13 +196,4 @@
 
 	  If you are not sure, say Y here.
 
-config BLINK
-	tristate "Keyboard blink driver"
-	help
-	  Driver that when loaded will blink the keyboard LEDs continuously.
-	  This is useful for debugging and for kernels that cannot necessarily
-	  output something to the screen like kexec kernels to give the user
-	  a visual indication that the kernel is doing something.
-
-
-endmenu
+endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5b6d46d..b5ce0e3 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -7,7 +7,6 @@
 obj-$(CONFIG_HDPU_FEATURES)	+= hdpuftrs/
 obj-$(CONFIG_MSI_LAPTOP)     += msi-laptop.o
 obj-$(CONFIG_ASUS_LAPTOP)     += asus-laptop.o
-obj-$(CONFIG_BLINK)		+= blink.o
 obj-$(CONFIG_LKDTM)		+= lkdtm.o
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
 obj-$(CONFIG_TIFM_7XX1)       	+= tifm_7xx1.o
@@ -15,3 +14,4 @@
 obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
 obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
 obj-$(CONFIG_THINKPAD_ACPI)	+= thinkpad_acpi.o
+obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 4f9060a..7798f590e 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -737,8 +737,7 @@
 	struct device_attribute dev_attr_##_name = {			\
 		.attr = {						\
 			.name = __stringify(_name),			\
-			.mode = 0,					\
-			.owner = THIS_MODULE },				\
+			.mode = 0 },					\
 		.show   = NULL,						\
 		.store  = NULL,						\
 	}
diff --git a/drivers/misc/blink.c b/drivers/misc/blink.c
deleted file mode 100644
index 634431c..0000000
--- a/drivers/misc/blink.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-
-static void do_blink(unsigned long data);
-
-static DEFINE_TIMER(blink_timer, do_blink, 0 ,0);
-
-static void do_blink(unsigned long data)
-{
-	static long count;
-	if (panic_blink)
-		panic_blink(count++);
-	blink_timer.expires = jiffies + msecs_to_jiffies(1);
-	add_timer(&blink_timer);
-}
-
-static int blink_init(void)
-{
-	printk(KERN_INFO "Enabling keyboard blinking\n");
-	do_blink(0);
-	return 0;
-}
-
-module_init(blink_init);
-
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 0000000..ea55654
--- /dev/null
+++ b/drivers/misc/eeprom_93cx6.c
@@ -0,0 +1,241 @@
+/*
+	Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.com>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the
+	Free Software Foundation, Inc.,
+	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+	Module: eeprom_93cx6
+	Abstract: EEPROM reader routines for 93cx6 chipsets.
+	Supported chipsets: 93c46 & 93c66.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/eeprom_93cx6.h>
+
+MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
+MODULE_LICENSE("GPL");
+
+static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
+{
+	eeprom->reg_data_clock = 1;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * Add a short delay for the pulse to work.
+	 * According to the specifications the "maximum minimum"
+	 * time should be 450ns.
+	 */
+	ndelay(450);
+}
+
+static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
+{
+	eeprom->reg_data_clock = 0;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * Add a short delay for the pulse to work.
+	 * According to the specifications the "maximum minimum"
+	 * time should be 450ns.
+	 */
+	ndelay(450);
+}
+
+static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
+{
+	/*
+	 * Clear all flags, and enable chip select.
+	 */
+	eeprom->register_read(eeprom);
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+	eeprom->reg_data_clock = 0;
+	eeprom->reg_chip_select = 1;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * kick a pulse.
+	 */
+	eeprom_93cx6_pulse_high(eeprom);
+	eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
+{
+	/*
+	 * Clear chip_select and data_in flags.
+	 */
+	eeprom->register_read(eeprom);
+	eeprom->reg_data_in = 0;
+	eeprom->reg_chip_select = 0;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * kick a pulse.
+	 */
+	eeprom_93cx6_pulse_high(eeprom);
+	eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
+	const u16 data, const u16 count)
+{
+	unsigned int i;
+
+	eeprom->register_read(eeprom);
+
+	/*
+	 * Clear data flags.
+	 */
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+
+	/*
+	 * Start writing all bits.
+	 */
+	for (i = count; i > 0; i--) {
+		/*
+		 * Check if this bit needs to be set.
+		 */
+		eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+
+		/*
+		 * Write the bit to the eeprom register.
+		 */
+		eeprom->register_write(eeprom);
+
+		/*
+		 * Kick a pulse.
+		 */
+		eeprom_93cx6_pulse_high(eeprom);
+		eeprom_93cx6_pulse_low(eeprom);
+	}
+
+	eeprom->reg_data_in = 0;
+	eeprom->register_write(eeprom);
+}
+
+static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
+	u16 *data, const u16 count)
+{
+	unsigned int i;
+	u16 buf = 0;
+
+	eeprom->register_read(eeprom);
+
+	/*
+	 * Clear data flags.
+	 */
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+
+	/*
+	 * Start reading all bits.
+	 */
+	for (i = count; i > 0; i--) {
+		eeprom_93cx6_pulse_high(eeprom);
+
+		eeprom->register_read(eeprom);
+
+		/*
+		 * Clear data_in flag.
+		 */
+		eeprom->reg_data_in = 0;
+
+		/*
+		 * Read if the bit has been set.
+		 */
+		if (eeprom->reg_data_out)
+			buf |= (1 << (i - 1));
+
+		eeprom_93cx6_pulse_low(eeprom);
+	}
+
+	*data = buf;
+}
+
+/**
+ * eeprom_93cx6_read - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read the eeprom data as host-endian word
+ * into the given data pointer.
+ */
+void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
+	u16 *data)
+{
+	u16 command;
+
+	/*
+	 * Initialize the eeprom register
+	 */
+	eeprom_93cx6_startup(eeprom);
+
+	/*
+	 * Select the read opcode and the word to be read.
+	 */
+	command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
+	eeprom_93cx6_write_bits(eeprom, command,
+		PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+	/*
+	 * Read the requested 16 bits.
+	 */
+	eeprom_93cx6_read_bits(eeprom, data, 16);
+
+	/*
+	 * Cleanup eeprom register.
+	 */
+	eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
+
+/**
+ * eeprom_93cx6_multiread - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of words that should be read.
+ *
+ * This function will read all requested words from the eeprom,
+ * this is done by calling eeprom_93cx6_read() multiple times.
+ * But with the additional change that while the eeprom_93cx6_read
+ * will return host ordered bytes, this method will return little
+ * endian words.
+ */
+void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
+	__le16 *data, const u16 words)
+{
+	unsigned int i;
+	u16 tmp;
+
+	for (i = 0; i < words; i++) {
+		tmp = 0;
+		eeprom_93cx6_read(eeprom, word + i, &tmp);
+		data[i] = cpu_to_le16(tmp);
+	}
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
+
diff --git a/drivers/misc/ibmasm/command.c b/drivers/misc/ibmasm/command.c
index 07a085c..b5df347 100644
--- a/drivers/misc/ibmasm/command.c
+++ b/drivers/misc/ibmasm/command.c
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -72,7 +72,7 @@
 static void free_command(struct kobject *kobj)
 {
 	struct command *cmd = to_command(kobj);
- 
+
 	list_del(&cmd->queue_node);
 	atomic_dec(&command_count);
 	dbg("command count: %d\n", atomic_read(&command_count));
@@ -113,14 +113,14 @@
 		exec_next_command(sp);
 	}
 }
-	
+
 /**
  * exec_command
  * send a command to a service processor
  * Commands are executed sequentially. One command (sp->current_command)
  * is sent to the service processor. Once the interrupt handler gets a
  * message of type command_response, the message is copied into
- * the current commands buffer, 
+ * the current commands buffer,
  */
 void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
 {
@@ -160,7 +160,7 @@
 	}
 }
 
-/** 
+/**
  * Sleep until a command has failed or a response has been received
  * and the command status been updated by the interrupt handler.
  * (see receive_response).
@@ -182,8 +182,8 @@
 {
 	struct command *cmd = sp->current_command;
 
-	if (!sp->current_command) 
-		return; 
+	if (!sp->current_command)
+		return;
 
 	memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size));
 	cmd->status = IBMASM_CMD_COMPLETE;
diff --git a/drivers/misc/ibmasm/dot_command.c b/drivers/misc/ibmasm/dot_command.c
index 13c52f8..3dd2dfb 100644
--- a/drivers/misc/ibmasm/dot_command.c
+++ b/drivers/misc/ibmasm/dot_command.c
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -44,11 +44,11 @@
 		size = message_size;
 
 	switch (header->type) {
-	case sp_event: 
+	case sp_event:
 		ibmasm_receive_event(sp, message, size);
 		break;
 	case sp_command_response:
-		ibmasm_receive_command_response(sp, message, size); 
+		ibmasm_receive_command_response(sp, message, size);
 		break;
 	case sp_heartbeat:
 		ibmasm_receive_heartbeat(sp, message, size);
@@ -95,7 +95,7 @@
 	strcat(vpd_data, IBMASM_DRIVER_VPD);
 	vpd_data[10] = 0;
 	vpd_data[15] = 0;
-	
+
 	ibmasm_exec_command(sp, command);
 	ibmasm_wait_for_response(command, IBMASM_CMD_TIMEOUT_NORMAL);
 
@@ -118,7 +118,7 @@
  * During driver init this function is called with os state "up".
  * This causes the service processor to start sending heartbeats the
  * driver.
- * During driver exit the function is called with os state "down", 
+ * During driver exit the function is called with os state "down",
  * causing the service processor to stop the heartbeats.
  */
 int ibmasm_send_os_state(struct service_processor *sp, int os_state)
diff --git a/drivers/misc/ibmasm/dot_command.h b/drivers/misc/ibmasm/dot_command.h
index 2d21c27..6cbba1a 100644
--- a/drivers/misc/ibmasm/dot_command.h
+++ b/drivers/misc/ibmasm/dot_command.h
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c
index fe1e819..fda6a4d 100644
--- a/drivers/misc/ibmasm/event.c
+++ b/drivers/misc/ibmasm/event.c
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -51,7 +51,7 @@
  * event readers.
  * There is no reader marker in the buffer, therefore readers are
  * responsible for keeping up with the writer, or they will loose events.
- */ 
+ */
 void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size)
 {
 	struct event_buffer *buffer = sp->event_buffer;
@@ -77,13 +77,13 @@
 
 static inline int event_available(struct event_buffer *b, struct event_reader *r)
 {
-	return 	(r->next_serial_number < b->next_serial_number);
+	return (r->next_serial_number < b->next_serial_number);
 }
 
 /**
  * get_next_event
  * Called by event readers (initiated from user space through the file
- * system). 
+ * system).
  * Sleeps until a new event is available.
  */
 int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader)
diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
index 7fd7a43..3036e78 100644
--- a/drivers/misc/ibmasm/heartbeat.c
+++ b/drivers/misc/ibmasm/heartbeat.c
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
diff --git a/drivers/misc/ibmasm/i2o.h b/drivers/misc/ibmasm/i2o.h
index 958c957..bf2c738 100644
--- a/drivers/misc/ibmasm/i2o.h
+++ b/drivers/misc/ibmasm/i2o.h
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -26,9 +26,9 @@
 	u8	version;
 	u8	message_flags;
 	u16	message_size;
-	u8	target;           
+	u8	target;
 	u8	initiator_and_target;
-	u8	initiator;        
+	u8	initiator;
 	u8	function;
 	u32	initiator_context;
 };
@@ -64,12 +64,12 @@
 	size = sizeof(struct i2o_header) + data_size;
 
 	i2o_size = size / sizeof(u32);
-	
+
 	if (size % sizeof(u32))
 	       i2o_size++;
 
 	return i2o_size;
-}	
+}
 
 static inline u32 incoming_data_size(struct i2o_message *i2o_message)
 {
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index 48d5abe..de860bc 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -58,8 +58,8 @@
 	return buf;
 }
 
-#define IBMASM_CMD_PENDING	0	
-#define IBMASM_CMD_COMPLETE	1	
+#define IBMASM_CMD_PENDING	0
+#define IBMASM_CMD_COMPLETE	1
 #define IBMASM_CMD_FAILED	2
 
 #define IBMASM_CMD_TIMEOUT_NORMAL	45
@@ -163,55 +163,55 @@
 };
 
 /* command processing */
-extern struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
-extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
-extern void ibmasm_wait_for_response(struct command *cmd, int timeout);
-extern void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);
+struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
+void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
+void ibmasm_wait_for_response(struct command *cmd, int timeout);
+void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);
 
 /* event processing */
-extern int ibmasm_event_buffer_init(struct service_processor *sp);
-extern void ibmasm_event_buffer_exit(struct service_processor *sp);
-extern void ibmasm_receive_event(struct service_processor *sp, void *data,  unsigned int data_size);
-extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
-extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
-extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
-extern void ibmasm_cancel_next_event(struct event_reader *reader);
+int ibmasm_event_buffer_init(struct service_processor *sp);
+void ibmasm_event_buffer_exit(struct service_processor *sp);
+void ibmasm_receive_event(struct service_processor *sp, void *data,  unsigned int data_size);
+void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
+void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
+int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
+void ibmasm_cancel_next_event(struct event_reader *reader);
 
 /* heartbeat - from SP to OS */
-extern void ibmasm_register_panic_notifier(void);
-extern void ibmasm_unregister_panic_notifier(void);
-extern int ibmasm_heartbeat_init(struct service_processor *sp);
-extern void ibmasm_heartbeat_exit(struct service_processor *sp);
-extern void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size);
+void ibmasm_register_panic_notifier(void);
+void ibmasm_unregister_panic_notifier(void);
+int ibmasm_heartbeat_init(struct service_processor *sp);
+void ibmasm_heartbeat_exit(struct service_processor *sp);
+void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size);
 
 /* reverse heartbeat - from OS to SP */
-extern void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
-extern int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
-extern void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);
+void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
+int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
+void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);
 
 /* dot commands */
-extern void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);
-extern int ibmasm_send_driver_vpd(struct service_processor *sp);
-extern int ibmasm_send_os_state(struct service_processor *sp, int os_state);
+void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);
+int ibmasm_send_driver_vpd(struct service_processor *sp);
+int ibmasm_send_os_state(struct service_processor *sp, int os_state);
 
 /* low level message processing */
-extern int ibmasm_send_i2o_message(struct service_processor *sp);
-extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);
+int ibmasm_send_i2o_message(struct service_processor *sp);
+irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);
 
 /* remote console */
-extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
-extern int ibmasm_init_remote_input_dev(struct service_processor *sp);
-extern void ibmasm_free_remote_input_dev(struct service_processor *sp);
+void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
+int ibmasm_init_remote_input_dev(struct service_processor *sp);
+void ibmasm_free_remote_input_dev(struct service_processor *sp);
 
 /* file system */
-extern int ibmasmfs_register(void);
-extern void ibmasmfs_unregister(void);
-extern void ibmasmfs_add_sp(struct service_processor *sp);
+int ibmasmfs_register(void);
+void ibmasmfs_unregister(void);
+void ibmasmfs_add_sp(struct service_processor *sp);
 
 /* uart */
 #ifdef CONFIG_SERIAL_8250
-extern void ibmasm_register_uart(struct service_processor *sp);
-extern void ibmasm_unregister_uart(struct service_processor *sp);
+void ibmasm_register_uart(struct service_processor *sp);
+void ibmasm_unregister_uart(struct service_processor *sp);
 #else
 #define ibmasm_register_uart(sp)	do { } while(0)
 #define ibmasm_unregister_uart(sp)	do { } while(0)
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index c436d3d..eb7b073 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -17,12 +17,12 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
 /*
- * Parts of this code are based on an article by Jonathan Corbet 
+ * Parts of this code are based on an article by Jonathan Corbet
  * that appeared in Linux Weekly News.
  */
 
@@ -55,22 +55,22 @@
  * For each service processor the following files are created:
  *
  * command: execute dot commands
- * 	write: execute a dot command on the service processor
- * 	read: return the result of a previously executed dot command
+ *	write: execute a dot command on the service processor
+ *	read: return the result of a previously executed dot command
  *
  * events: listen for service processor events
- * 	read: sleep (interruptible) until an event occurs
+ *	read: sleep (interruptible) until an event occurs
  *      write: wakeup sleeping event listener
  *
  * reverse_heartbeat: send a heartbeat to the service processor
- * 	read: sleep (interruptible) until the reverse heartbeat fails
+ *	read: sleep (interruptible) until the reverse heartbeat fails
  *      write: wakeup sleeping heartbeat listener
  *
  * remote_video/width
  * remote_video/height
  * remote_video/width: control remote display settings
- * 	write: set value
- * 	read: read value
+ *	write: set value
+ *	read: read value
  */
 
 #include <linux/fs.h>
@@ -155,7 +155,7 @@
 
 static struct dentry *ibmasmfs_create_file (struct super_block *sb,
 			struct dentry *parent,
-		       	const char *name,
+			const char *name,
 			const struct file_operations *fops,
 			void *data,
 			int mode)
@@ -261,7 +261,7 @@
 	struct ibmasmfs_command_data *command_data = file->private_data;
 
 	if (command_data->command)
-		command_put(command_data->command);	
+		command_put(command_data->command);
 
 	kfree(command_data);
 	return 0;
@@ -348,7 +348,7 @@
 static int event_file_open(struct inode *inode, struct file *file)
 {
 	struct ibmasmfs_event_data *event_data;
-	struct service_processor *sp; 
+	struct service_processor *sp;
 
 	if (!inode->i_private)
 		return -ENODEV;
@@ -573,7 +573,7 @@
 		kfree(buff);
 		return -EFAULT;
 	}
-	
+
 	value = simple_strtoul(buff, NULL, 10);
 	writel(value, address);
 	kfree(buff);
diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
index a3c589b..4b2398e 100644
--- a/drivers/misc/ibmasm/lowlevel.c
+++ b/drivers/misc/ibmasm/lowlevel.c
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
diff --git a/drivers/misc/ibmasm/lowlevel.h b/drivers/misc/ibmasm/lowlevel.h
index e5ed59c..7667665 100644
--- a/drivers/misc/ibmasm/lowlevel.h
+++ b/drivers/misc/ibmasm/lowlevel.h
@@ -17,7 +17,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -48,9 +48,9 @@
 #define INTR_CONTROL_REGISTER  0x13A4
 
 #define SCOUT_COM_A_BASE         0x0000
-#define SCOUT_COM_B_BASE         0x0100   
-#define SCOUT_COM_C_BASE         0x0200   
-#define SCOUT_COM_D_BASE         0x0300   
+#define SCOUT_COM_B_BASE         0x0100
+#define SCOUT_COM_C_BASE         0x0200
+#define SCOUT_COM_D_BASE         0x0300
 
 static inline int sp_interrupt_pending(void __iomem *base_address)
 {
@@ -86,12 +86,12 @@
 
 static inline void enable_uart_interrupts(void __iomem *base_address)
 {
-	ibmasm_enable_interrupts(base_address, UART_INTR_MASK); 
+	ibmasm_enable_interrupts(base_address, UART_INTR_MASK);
 }
 
 static inline void disable_uart_interrupts(void __iomem *base_address)
 {
-	ibmasm_disable_interrupts(base_address, UART_INTR_MASK); 
+	ibmasm_disable_interrupts(base_address, UART_INTR_MASK);
 }
 
 #define valid_mfa(mfa)	( (mfa) != NO_MFAS_AVAILABLE )
@@ -111,7 +111,7 @@
 
 static inline void set_mfa_outbound(void __iomem *base_address, u32 mfa)
 {
-   	writel(mfa, base_address + OUTBOUND_QUEUE_PORT);
+	writel(mfa, base_address + OUTBOUND_QUEUE_PORT);
 }
 
 static inline u32 get_mfa_inbound(void __iomem *base_address)
@@ -126,7 +126,7 @@
 
 static inline void set_mfa_inbound(void __iomem *base_address, u32 mfa)
 {
-   	writel(mfa, base_address + INBOUND_QUEUE_PORT);
+	writel(mfa, base_address + INBOUND_QUEUE_PORT);
 }
 
 static inline struct i2o_message *get_i2o_message(void __iomem *base_address, u32 mfa)
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 2f3bddf..fb03a85 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -18,9 +18,9 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
- * This driver is based on code originally written by Pete Reynolds 
+ * This driver is based on code originally written by Pete Reynolds
  * and others.
  *
  */
@@ -30,13 +30,13 @@
  *
  * 1) When loaded it sends a message to the service processor,
  * indicating that an OS is * running. This causes the service processor
- * to send periodic heartbeats to the OS. 
+ * to send periodic heartbeats to the OS.
  *
  * 2) Answers the periodic heartbeats sent by the service processor.
  * Failure to do so would result in system reboot.
  *
  * 3) Acts as a pass through for dot commands sent from user applications.
- * The interface for this is the ibmasmfs file system. 
+ * The interface for this is the ibmasmfs file system.
  *
  * 4) Allows user applications to register for event notification. Events
  * are sent to the driver through interrupts. They can be read from user
@@ -105,7 +105,7 @@
 	}
 
 	sp->irq = pdev->irq;
-	sp->base_address = ioremap(pci_resource_start(pdev, 0), 
+	sp->base_address = ioremap(pci_resource_start(pdev, 0),
 					pci_resource_len(pdev, 0));
 	if (sp->base_address == 0) {
 		dev_err(sp->dev, "Failed to ioremap pci memory\n");
diff --git a/drivers/misc/ibmasm/r_heartbeat.c b/drivers/misc/ibmasm/r_heartbeat.c
index f8fdb2d..bec9e2c 100644
--- a/drivers/misc/ibmasm/r_heartbeat.c
+++ b/drivers/misc/ibmasm/r_heartbeat.c
@@ -16,7 +16,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
@@ -36,10 +36,10 @@
 	unsigned char			command[3];
 } rhb_dot_cmd = {
 	.header = {
-		.type = 	sp_read,
+		.type =		sp_read,
 		.command_size = 3,
 		.data_size =	0,
-		.status = 	0
+		.status =	0
 	},
 	.command = { 4, 3, 6 }
 };
@@ -76,9 +76,9 @@
 		if (cmd->status != IBMASM_CMD_COMPLETE)
 			times_failed++;
 
-		wait_event_interruptible_timeout(rhb->wait, 
+		wait_event_interruptible_timeout(rhb->wait,
 			rhb->stopped,
-			REVERSE_HEARTBEAT_TIMEOUT * HZ); 	
+			REVERSE_HEARTBEAT_TIMEOUT * HZ);
 
 		if (signal_pending(current) || rhb->stopped) {
 			result = -EINTR;
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index a40fda6..0550ce0 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -28,11 +28,10 @@
 #include "ibmasm.h"
 #include "remote.h"
 
-static int xmax = 1600;
-static int ymax = 1200;
+#define MOUSE_X_MAX	1600
+#define MOUSE_Y_MAX	1200
 
-
-static unsigned short xlate_high[XLATE_SIZE] = {
+static const unsigned short xlate_high[XLATE_SIZE] = {
 	[KEY_SYM_ENTER & 0xff] = KEY_ENTER,
 	[KEY_SYM_KPSLASH & 0xff] = KEY_KPSLASH,
 	[KEY_SYM_KPSTAR & 0xff] = KEY_KPASTERISK,
@@ -81,7 +80,8 @@
 	[KEY_SYM_NUM_LOCK & 0xff] = KEY_NUMLOCK,
 	[KEY_SYM_SCR_LOCK & 0xff] = KEY_SCROLLLOCK,
 };
-static unsigned short xlate[XLATE_SIZE] = {
+
+static const unsigned short xlate[XLATE_SIZE] = {
 	[NO_KEYCODE] = KEY_RESERVED,
 	[KEY_SYM_SPACE] = KEY_SPACE,
 	[KEY_SYM_TILDE] = KEY_GRAVE,        [KEY_SYM_BKTIC] = KEY_GRAVE,
@@ -133,19 +133,16 @@
 	[KEY_SYM_Z] = KEY_Z,                [KEY_SYM_z] = KEY_Z,
 };
 
-static char remote_mouse_name[] = "ibmasm RSA I remote mouse";
-static char remote_keybd_name[] = "ibmasm RSA I remote keyboard";
-
 static void print_input(struct remote_input *input)
 {
 	if (input->type == INPUT_TYPE_MOUSE) {
 		unsigned char buttons = input->mouse_buttons;
 		dbg("remote mouse movement: (x,y)=(%d,%d)%s%s%s%s\n",
 			input->data.mouse.x, input->data.mouse.y,
-			(buttons)?" -- buttons:":"",
-			(buttons & REMOTE_BUTTON_LEFT)?"left ":"",
-			(buttons & REMOTE_BUTTON_MIDDLE)?"middle ":"",
-			(buttons & REMOTE_BUTTON_RIGHT)?"right":""
+			(buttons) ? " -- buttons:" : "",
+			(buttons & REMOTE_BUTTON_LEFT) ? "left " : "",
+			(buttons & REMOTE_BUTTON_MIDDLE) ? "middle " : "",
+			(buttons & REMOTE_BUTTON_RIGHT) ? "right" : ""
 		      );
 	} else {
 		dbg("remote keypress (code, flag, down):"
@@ -180,7 +177,7 @@
 		key = xlate_high[code & 0xff];
 	else
 		key = xlate[code];
-	input_report_key(dev, key, (input->data.keyboard.key_down) ? 1 : 0);
+	input_report_key(dev, key, input->data.keyboard.key_down);
 	input_sync(dev);
 }
 
@@ -228,20 +225,22 @@
 	mouse_dev->id.vendor = pdev->vendor;
 	mouse_dev->id.product = pdev->device;
 	mouse_dev->id.version = 1;
+	mouse_dev->dev.parent = sp->dev;
 	mouse_dev->evbit[0]  = BIT(EV_KEY) | BIT(EV_ABS);
 	mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
 		BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
 	set_bit(BTN_TOUCH, mouse_dev->keybit);
-	mouse_dev->name = remote_mouse_name;
-	input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
-	input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
+	mouse_dev->name = "ibmasm RSA I remote mouse";
+	input_set_abs_params(mouse_dev, ABS_X, 0, MOUSE_X_MAX, 0, 0);
+	input_set_abs_params(mouse_dev, ABS_Y, 0, MOUSE_Y_MAX, 0, 0);
 
-	mouse_dev->id.bustype = BUS_PCI;
+	keybd_dev->id.bustype = BUS_PCI;
 	keybd_dev->id.vendor = pdev->vendor;
 	keybd_dev->id.product = pdev->device;
-	mouse_dev->id.version = 2;
+	keybd_dev->id.version = 2;
+	keybd_dev->dev.parent = sp->dev;
 	keybd_dev->evbit[0]  = BIT(EV_KEY);
-	keybd_dev->name = remote_keybd_name;
+	keybd_dev->name = "ibmasm RSA I remote keyboard";
 
 	for (i = 0; i < XLATE_SIZE; i++) {
 		if (xlate_high[i])
diff --git a/drivers/misc/ibmasm/remote.h b/drivers/misc/ibmasm/remote.h
index b7076a8..72acf5a 100644
--- a/drivers/misc/ibmasm/remote.h
+++ b/drivers/misc/ibmasm/remote.h
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  * Orignally written by Pete Reynolds
  */
@@ -73,7 +73,7 @@
 
 
 
-struct remote_input { 
+struct remote_input {
 	union {
 		struct mouse_input	mouse;
 		struct keyboard_input	keyboard;
@@ -85,7 +85,7 @@
 	unsigned char	pad3;
 };
 
-#define mouse_addr(sp) 		(sp->base_address + CONDOR_MOUSE_DATA)
+#define mouse_addr(sp)		(sp->base_address + CONDOR_MOUSE_DATA)
 #define display_width(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX)
 #define display_height(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY)
 #define display_depth(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS)
@@ -93,7 +93,7 @@
 #define vnc_status(sp)		(mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS)
 #define isr_control(sp)		(mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
 
-#define mouse_interrupt_pending(sp) 	readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
+#define mouse_interrupt_pending(sp)	readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
 #define clear_mouse_interrupt(sp)	writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
 #define enable_mouse_interrupts(sp)	writel(1, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
 #define disable_mouse_interrupts(sp)	writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c
index 9783caf..93baa35 100644
--- a/drivers/misc/ibmasm/uart.c
+++ b/drivers/misc/ibmasm/uart.c
@@ -18,7 +18,7 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Author: Max Asböck <amax@us.ibm.com>
  *
  */
 
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 41e901f..932a415 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -23,6 +23,8 @@
  * msi-laptop.c - MSI S270 laptop support. This laptop is sold under
  * various brands, including "Cytron/TCM/Medion/Tchibo MD96100".
  *
+ * Driver also supports S271, S420 models.
+ *
  * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/:
  *
  *   lcd_level - Screen brightness: contains a single integer in the
@@ -281,25 +283,56 @@
 
 /* Initialization */
 
+static int dmi_check_cb(struct dmi_system_id *id)
+{
+        printk("msi-laptop: Identified laptop model '%s'.\n", id->ident);
+        return 0;
+}
+
 static struct dmi_system_id __initdata msi_dmi_table[] = {
 	{
 		.ident = "MSI S270",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
-		}
+			DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
+			DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
+		},
+		.callback = dmi_check_cb
+	},
+	{
+		.ident = "MSI S271",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MS-1058"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "0581"),
+			DMI_MATCH(DMI_BOARD_NAME, "MS-1058")
+		},
+		.callback = dmi_check_cb
+	},
+	{
+		.ident = "MSI S420",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MS-1412"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+			DMI_MATCH(DMI_BOARD_NAME, "MS-1412")
+		},
+		.callback = dmi_check_cb
 	},
 	{
 		.ident = "Medion MD96100",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
-		}
+			DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
+			DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
+		},
+		.callback = dmi_check_cb
 	},
 	{ }
 };
 
-
 static int __init msi_init(void)
 {
 	int ret;
@@ -394,3 +427,8 @@
 MODULE_DESCRIPTION("MSI Laptop Support");
 MODULE_VERSION(MSI_DRIVER_VERSION);
 MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
+MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 35b139b..5108b7c 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -47,6 +47,7 @@
 	struct cdev cdev;
 
 	struct mutex open_lock;
+	spinlock_t ioctl_lock;
 };
 
 static unsigned char phantom_devices[PHANTOM_MAX_MINORS];
@@ -59,8 +60,11 @@
 		atomic_set(&dev->counter, 0);
 		iowrite32(PHN_CTL_IRQ, dev->iaddr + PHN_CONTROL);
 		iowrite32(0x43, dev->caddr + PHN_IRQCTL);
-	} else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING))
+		ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
+	} else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING)) {
 		iowrite32(0, dev->caddr + PHN_IRQCTL);
+		ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
+	}
 
 	dev->status = newstat;
 
@@ -71,8 +75,8 @@
  * File ops
  */
 
-static int phantom_ioctl(struct inode *inode, struct file *file, u_int cmd,
-	u_long arg)
+static long phantom_ioctl(struct file *file, unsigned int cmd,
+		unsigned long arg)
 {
 	struct phantom_device *dev = file->private_data;
 	struct phm_regs rs;
@@ -92,24 +96,32 @@
 		if (r.reg > 7)
 			return -EINVAL;
 
+		spin_lock(&dev->ioctl_lock);
 		if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) &&
-				phantom_status(dev, dev->status | PHB_RUNNING))
+				phantom_status(dev, dev->status | PHB_RUNNING)){
+			spin_unlock(&dev->ioctl_lock);
 			return -ENODEV;
+		}
 
 		pr_debug("phantom: writing %x to %u\n", r.value, r.reg);
 		iowrite32(r.value, dev->iaddr + r.reg);
+		ioread32(dev->iaddr); /* PCI posting */
 
 		if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ))
 			phantom_status(dev, dev->status & ~PHB_RUNNING);
+		spin_unlock(&dev->ioctl_lock);
 		break;
 	case PHN_SET_REGS:
 		if (copy_from_user(&rs, argp, sizeof(rs)))
 			return -EFAULT;
 
 		pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask);
+		spin_lock(&dev->ioctl_lock);
 		for (i = 0; i < min(rs.count, 8U); i++)
 			if ((1 << i) & rs.mask)
 				iowrite32(rs.values[i], dev->oaddr + i);
+		ioread32(dev->iaddr); /* PCI posting */
+		spin_unlock(&dev->ioctl_lock);
 		break;
 	case PHN_GET_REG:
 		if (copy_from_user(&r, argp, sizeof(r)))
@@ -128,9 +140,11 @@
 			return -EFAULT;
 
 		pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask);
+		spin_lock(&dev->ioctl_lock);
 		for (i = 0; i < min(rs.count, 8U); i++)
 			if ((1 << i) & rs.mask)
 				rs.values[i] = ioread32(dev->iaddr + i);
+		spin_unlock(&dev->ioctl_lock);
 
 		if (copy_to_user(argp, &rs, sizeof(rs)))
 			return -EFAULT;
@@ -199,7 +213,7 @@
 static struct file_operations phantom_file_ops = {
 	.open = phantom_open,
 	.release = phantom_release,
-	.ioctl = phantom_ioctl,
+	.unlocked_ioctl = phantom_ioctl,
 	.poll = phantom_poll,
 };
 
@@ -212,6 +226,7 @@
 
 	iowrite32(0, dev->iaddr);
 	iowrite32(0xc0, dev->iaddr);
+	ioread32(dev->iaddr); /* PCI posting */
 
 	atomic_inc(&dev->counter);
 	wake_up_interruptible(&dev->wait);
@@ -282,11 +297,13 @@
 	}
 
 	mutex_init(&pht->open_lock);
+	spin_lock_init(&pht->ioctl_lock);
 	init_waitqueue_head(&pht->wait);
 	cdev_init(&pht->cdev, &phantom_file_ops);
 	pht->cdev.owner = THIS_MODULE;
 
 	iowrite32(0, pht->caddr + PHN_IRQCTL);
+	ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
 	retval = request_irq(pdev->irq, phantom_isr,
 			IRQF_SHARED | IRQF_DISABLED, "phantom", pht);
 	if (retval) {
@@ -337,6 +354,7 @@
 	cdev_del(&pht->cdev);
 
 	iowrite32(0, pht->caddr + PHN_IRQCTL);
+	ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
 	free_irq(pdev->irq, pht);
 
 	pci_iounmap(pdev, pht->oaddr);
@@ -358,6 +376,7 @@
 	struct phantom_device *dev = pci_get_drvdata(pdev);
 
 	iowrite32(0, dev->caddr + PHN_IRQCTL);
+	ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
 
 	return 0;
 }
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 8ee0321..9623eaf 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -1917,7 +1917,8 @@
  */
 static int sony_pic_disable(struct acpi_device *device)
 {
-	if (ACPI_FAILURE(acpi_evaluate_object(device->handle, "_DIS", 0, NULL)))
+	if (ACPI_FAILURE(acpi_evaluate_object(device->handle,
+			"_DIS", NULL, NULL)))
 		return -ENXIO;
 
 	dprintk("Device disabled\n");
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 6c36a55..95c0b96 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -740,7 +740,7 @@
 }
 
 static struct device_attribute dev_attr_hotkey_enable =
-	__ATTR(enable, S_IWUSR | S_IRUGO,
+	__ATTR(hotkey_enable, S_IWUSR | S_IRUGO,
 		hotkey_enable_show, hotkey_enable_store);
 
 /* sysfs hotkey mask --------------------------------------------------- */
@@ -775,7 +775,7 @@
 }
 
 static struct device_attribute dev_attr_hotkey_mask =
-	__ATTR(mask, S_IWUSR | S_IRUGO,
+	__ATTR(hotkey_mask, S_IWUSR | S_IRUGO,
 		hotkey_mask_show, hotkey_mask_store);
 
 /* sysfs hotkey bios_enabled ------------------------------------------- */
@@ -787,7 +787,7 @@
 }
 
 static struct device_attribute dev_attr_hotkey_bios_enabled =
-	__ATTR(bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
+	__ATTR(hotkey_bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
 
 /* sysfs hotkey bios_mask ---------------------------------------------- */
 static ssize_t hotkey_bios_mask_show(struct device *dev,
@@ -798,7 +798,7 @@
 }
 
 static struct device_attribute dev_attr_hotkey_bios_mask =
-	__ATTR(bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
+	__ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
 
 /* --------------------------------------------------------------------- */
 
@@ -824,8 +824,7 @@
 		str_supported(tp_features.hotkey));
 
 	if (tp_features.hotkey) {
-		hotkey_dev_attributes = create_attr_set(4,
-						TPACPI_HOTKEY_SYSFS_GROUP);
+		hotkey_dev_attributes = create_attr_set(4, NULL);
 		if (!hotkey_dev_attributes)
 			return -ENOMEM;
 		res = add_to_attr_set(hotkey_dev_attributes,
@@ -1050,7 +1049,7 @@
 }
 
 static struct device_attribute dev_attr_bluetooth_enable =
-	__ATTR(enable, S_IWUSR | S_IRUGO,
+	__ATTR(bluetooth_enable, S_IWUSR | S_IRUGO,
 		bluetooth_enable_show, bluetooth_enable_store);
 
 /* --------------------------------------------------------------------- */
@@ -1061,7 +1060,6 @@
 };
 
 static const struct attribute_group bluetooth_attr_group = {
-	.name = TPACPI_BLUETH_SYSFS_GROUP,
 	.attrs = bluetooth_attributes,
 };
 
@@ -1215,7 +1213,7 @@
 }
 
 static struct device_attribute dev_attr_wan_enable =
-	__ATTR(enable, S_IWUSR | S_IRUGO,
+	__ATTR(wwan_enable, S_IWUSR | S_IRUGO,
 		wan_enable_show, wan_enable_store);
 
 /* --------------------------------------------------------------------- */
@@ -1226,7 +1224,6 @@
 };
 
 static const struct attribute_group wan_attr_group = {
-	.name = TPACPI_WAN_SYSFS_GROUP,
 	.attrs = wan_attributes,
 };
 
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index 440145a..72d62f2 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -278,8 +278,6 @@
  * Bluetooth subdriver
  */
 
-#define TPACPI_BLUETH_SYSFS_GROUP "bluetooth"
-
 enum {
 	/* ACPI GBDC/SBDC bits */
 	TP_ACPI_BLUETOOTH_HWPRESENT	= 0x01,	/* Bluetooth hw available */
@@ -416,8 +414,6 @@
  * Hotkey subdriver
  */
 
-#define TPACPI_HOTKEY_SYSFS_GROUP "hotkey"
-
 static int hotkey_orig_status;
 static int hotkey_orig_mask;
 
@@ -553,8 +549,6 @@
  * Wan subdriver
  */
 
-#define TPACPI_WAN_SYSFS_GROUP "wwan"
-
 enum {
 	/* ACPI GWAN/SWAN bits */
 	TP_ACPI_WANCARD_HWPRESENT	= 0x01,	/* Wan hw available */
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index c08ad8f..2d1b3df 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -343,7 +343,7 @@
 	if (!fm->addr)
 		goto err_out_free;
 
-	rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
+	rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
 	if (rc)
 		goto err_out_unmap;
 
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 9320a8c..a49cb97 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -14,3 +14,21 @@
 	  mount the filesystem. Almost everyone wishing MMC support
 	  should say Y or M here.
 
+config MMC_BLOCK_BOUNCE
+	bool "Use bounce buffer for simple hosts"
+	depends on MMC_BLOCK
+	default y
+	help
+	  SD/MMC is a high latency protocol where it is crucial to
+	  send large requests in order to get high performance. Many
+	  controllers, however, are restricted to continuous memory
+	  (i.e. they can't do scatter-gather), something the kernel
+	  rarely can provide.
+
+	  Say Y here to help these restricted hosts by bouncing
+	  requests back and forth from a large buffer. You will get
+	  a big performance gain at the cost of up to 64 KiB of
+	  physical memory.
+
+	  If unsure, say Y here.
+
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index a7562f7..cbd4b6e 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -135,23 +135,6 @@
 	struct mmc_data		data;
 };
 
-static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req)
-{
-	struct mmc_blk_data *md = mq->data;
-	int stat = BLKPREP_OK;
-
-	/*
-	 * If we have no device, we haven't finished initialising.
-	 */
-	if (!md || !mq->card) {
-		printk(KERN_ERR "%s: killing request - no device/host\n",
-		       req->rq_disk->disk_name);
-		stat = BLKPREP_KILL;
-	}
-
-	return stat;
-}
-
 static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
 {
 	int err;
@@ -279,7 +262,9 @@
 		}
 
 		brq.data.sg = mq->sg;
-		brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
+		brq.data.sg_len = mmc_queue_map_sg(mq);
+
+		mmc_queue_bounce_pre(mq);
 
 		if (brq.data.blocks !=
 		    (req->nr_sectors >> (md->block_bits - 9))) {
@@ -296,6 +281,9 @@
 		}
 
 		mmc_wait_for_req(card->host, &brq.mrq);
+
+		mmc_queue_bounce_post(mq);
+
 		if (brq.cmd.error) {
 			printk(KERN_ERR "%s: error %d sending read/write command\n",
 			       req->rq_disk->disk_name, brq.cmd.error);
@@ -460,7 +448,6 @@
 	if (ret)
 		goto err_putdisk;
 
-	md->queue.prep_fn = mmc_blk_prep_rq;
 	md->queue.issue_fn = mmc_blk_issue_rq;
 	md->queue.data = md;
 
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 2e77963..b53dac8 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -11,49 +11,33 @@
  */
 #include <linux/module.h>
 #include <linux/blkdev.h>
+#include <linux/freezer.h>
 #include <linux/kthread.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include "queue.h"
 
+#define MMC_QUEUE_BOUNCESZ	65536
+
 #define MMC_QUEUE_SUSPENDED	(1 << 0)
 
 /*
- * Prepare a MMC request.  Essentially, this means passing the
- * preparation off to the media driver.  The media driver will
- * create a mmc_io_request in req->special.
+ * Prepare a MMC request. This just filters out odd stuff.
  */
 static int mmc_prep_request(struct request_queue *q, struct request *req)
 {
-	struct mmc_queue *mq = q->queuedata;
-	int ret = BLKPREP_KILL;
-
-	if (blk_special_request(req)) {
-		/*
-		 * Special commands already have the command
-		 * blocks already setup in req->special.
-		 */
-		BUG_ON(!req->special);
-
-		ret = BLKPREP_OK;
-	} else if (blk_fs_request(req) || blk_pc_request(req)) {
-		/*
-		 * Block I/O requests need translating according
-		 * to the protocol.
-		 */
-		ret = mq->prep_fn(mq, req);
-	} else {
-		/*
-		 * Everything else is invalid.
-		 */
+	/*
+	 * We only like normal block requests.
+	 */
+	if (!blk_fs_request(req) && !blk_pc_request(req)) {
 		blk_dump_rq_flags(req, "MMC bad request");
+		return BLKPREP_KILL;
 	}
 
-	if (ret == BLKPREP_OK)
-		req->cmd_flags |= REQ_DONTPREP;
+	req->cmd_flags |= REQ_DONTPREP;
 
-	return ret;
+	return BLKPREP_OK;
 }
 
 static int mmc_queue_thread(void *d)
@@ -61,11 +45,7 @@
 	struct mmc_queue *mq = d;
 	struct request_queue *q = mq->queue;
 
-	/*
-	 * Set iothread to ensure that we aren't put to sleep by
-	 * the process freezing.  We handle suspension ourselves.
-	 */
-	current->flags |= PF_MEMALLOC|PF_NOFREEZE;
+	current->flags |= PF_MEMALLOC;
 
 	down(&mq->thread_sem);
 	do {
@@ -137,6 +117,7 @@
 	struct mmc_host *host = card->host;
 	u64 limit = BLK_BOUNCE_HIGH;
 	int ret;
+	unsigned int bouncesz;
 
 	if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
 		limit = *mmc_dev(host)->dma_mask;
@@ -146,21 +127,61 @@
 	if (!mq->queue)
 		return -ENOMEM;
 
-	blk_queue_prep_rq(mq->queue, mmc_prep_request);
-	blk_queue_bounce_limit(mq->queue, limit);
-	blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
-	blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
-	blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
-	blk_queue_max_segment_size(mq->queue, host->max_seg_size);
-
 	mq->queue->queuedata = mq;
 	mq->req = NULL;
 
-	mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
-			 GFP_KERNEL);
-	if (!mq->sg) {
-		ret = -ENOMEM;
-		goto cleanup_queue;
+	blk_queue_prep_rq(mq->queue, mmc_prep_request);
+
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+	if (host->max_hw_segs == 1) {
+		bouncesz = MMC_QUEUE_BOUNCESZ;
+
+		if (bouncesz > host->max_req_size)
+			bouncesz = host->max_req_size;
+		if (bouncesz > host->max_seg_size)
+			bouncesz = host->max_seg_size;
+
+		mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+		if (!mq->bounce_buf) {
+			printk(KERN_WARNING "%s: unable to allocate "
+				"bounce buffer\n", mmc_card_name(card));
+		} else {
+			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
+			blk_queue_max_sectors(mq->queue, bouncesz / 512);
+			blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
+			blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
+			blk_queue_max_segment_size(mq->queue, bouncesz);
+
+			mq->sg = kmalloc(sizeof(struct scatterlist),
+				GFP_KERNEL);
+			if (!mq->sg) {
+				ret = -ENOMEM;
+				goto free_bounce_buf;
+			}
+
+			mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
+				bouncesz / 512, GFP_KERNEL);
+			if (!mq->bounce_sg) {
+				ret = -ENOMEM;
+				goto free_sg;
+			}
+		}
+	}
+#endif
+
+	if (!mq->bounce_buf) {
+		blk_queue_bounce_limit(mq->queue, limit);
+		blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
+		blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
+		blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
+		blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+
+		mq->sg = kmalloc(sizeof(struct scatterlist) *
+			host->max_phys_segs, GFP_KERNEL);
+		if (!mq->sg) {
+			ret = -ENOMEM;
+			goto cleanup_queue;
+		}
 	}
 
 	init_MUTEX(&mq->thread_sem);
@@ -168,14 +189,21 @@
 	mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
 	if (IS_ERR(mq->thread)) {
 		ret = PTR_ERR(mq->thread);
-		goto free_sg;
+		goto free_bounce_sg;
 	}
 
 	return 0;
-
+ free_bounce_sg:
+ 	if (mq->bounce_sg)
+ 		kfree(mq->bounce_sg);
+ 	mq->bounce_sg = NULL;
  free_sg:
 	kfree(mq->sg);
 	mq->sg = NULL;
+ free_bounce_buf:
+	if (mq->bounce_buf)
+		kfree(mq->bounce_buf);
+	mq->bounce_buf = NULL;
  cleanup_queue:
 	blk_cleanup_queue(mq->queue);
 	return ret;
@@ -197,9 +225,17 @@
 	/* Then terminate our worker thread */
 	kthread_stop(mq->thread);
 
+ 	if (mq->bounce_sg)
+ 		kfree(mq->bounce_sg);
+ 	mq->bounce_sg = NULL;
+
 	kfree(mq->sg);
 	mq->sg = NULL;
 
+	if (mq->bounce_buf)
+		kfree(mq->bounce_buf);
+	mq->bounce_buf = NULL;
+
 	blk_cleanup_queue(mq->queue);
 
 	mq->card = NULL;
@@ -250,3 +286,108 @@
 	}
 }
 
+static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
+	struct scatterlist *src, unsigned int src_len)
+{
+	unsigned int chunk;
+	char *dst_buf, *src_buf;
+	unsigned int dst_size, src_size;
+
+	dst_buf = NULL;
+	src_buf = NULL;
+	dst_size = 0;
+	src_size = 0;
+
+	while (src_len) {
+		BUG_ON(dst_len == 0);
+
+		if (dst_size == 0) {
+			dst_buf = page_address(dst->page) + dst->offset;
+			dst_size = dst->length;
+		}
+
+		if (src_size == 0) {
+			src_buf = page_address(src->page) + src->offset;
+			src_size = src->length;
+		}
+
+		chunk = min(dst_size, src_size);
+
+		memcpy(dst_buf, src_buf, chunk);
+
+		dst_buf += chunk;
+		src_buf += chunk;
+		dst_size -= chunk;
+		src_size -= chunk;
+
+		if (dst_size == 0) {
+			dst++;
+			dst_len--;
+		}
+
+		if (src_size == 0) {
+			src++;
+			src_len--;
+		}
+	}
+}
+
+unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
+{
+	unsigned int sg_len;
+
+	if (!mq->bounce_buf)
+		return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
+
+	BUG_ON(!mq->bounce_sg);
+
+	sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);
+
+	mq->bounce_sg_len = sg_len;
+
+	/*
+	 * Shortcut in the event we only get a single entry.
+	 */
+	if (sg_len == 1) {
+		memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
+		return 1;
+	}
+
+	mq->sg[0].page = virt_to_page(mq->bounce_buf);
+	mq->sg[0].offset = offset_in_page(mq->bounce_buf);
+	mq->sg[0].length = 0;
+
+	while (sg_len) {
+		mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
+		sg_len--;
+	}
+
+	return 1;
+}
+
+void mmc_queue_bounce_pre(struct mmc_queue *mq)
+{
+	if (!mq->bounce_buf)
+		return;
+
+	if (mq->bounce_sg_len == 1)
+		return;
+	if (rq_data_dir(mq->req) != WRITE)
+		return;
+
+	copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
+}
+
+void mmc_queue_bounce_post(struct mmc_queue *mq)
+{
+	if (!mq->bounce_buf)
+		return;
+
+	if (mq->bounce_sg_len == 1)
+		return;
+	if (rq_data_dir(mq->req) != READ)
+		return;
+
+	copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
+}
+
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index c9f139e..64e66e0 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -10,18 +10,13 @@
 	struct semaphore	thread_sem;
 	unsigned int		flags;
 	struct request		*req;
-	int			(*prep_fn)(struct mmc_queue *, struct request *);
 	int			(*issue_fn)(struct mmc_queue *, struct request *);
 	void			*data;
 	struct request_queue	*queue;
 	struct scatterlist	*sg;
-};
-
-struct mmc_io_request {
-	struct request		*rq;
-	int			num;
-	struct mmc_command	selcmd;		/* mmc_queue private */
-	struct mmc_command	cmd[4];		/* max 4 commands */
+	char			*bounce_buf;
+	struct scatterlist	*bounce_sg;
+	unsigned int		bounce_sg_len;
 };
 
 extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
@@ -29,4 +24,8 @@
 extern void mmc_queue_suspend(struct mmc_queue *);
 extern void mmc_queue_resume(struct mmc_queue *);
 
+extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
+extern void mmc_queue_bounce_pre(struct mmc_queue *);
+extern void mmc_queue_bounce_post(struct mmc_queue *);
+
 #endif
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 1075b02..3fdd08c 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -7,5 +7,6 @@
 endif
 
 obj-$(CONFIG_MMC)		+= mmc_core.o
-mmc_core-y			:= core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
+mmc_core-y			:= core.o sysfs.o bus.o host.o \
+				   mmc.o mmc_ops.o sd.o sd_ops.o
 
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
new file mode 100644
index 0000000..348b566
--- /dev/null
+++ b/drivers/mmc/core/bus.c
@@ -0,0 +1,253 @@
+/*
+ *  linux/drivers/mmc/core/bus.c
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright (C) 2007 Pierre Ossman
+ *
+ * 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.
+ *
+ *  MMC card bus driver model
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "sysfs.h"
+#include "core.h"
+#include "bus.h"
+
+#define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
+#define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
+
+static ssize_t mmc_type_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	switch (card->type) {
+	case MMC_TYPE_MMC:
+		return sprintf(buf, "MMC\n");
+	case MMC_TYPE_SD:
+		return sprintf(buf, "SD\n");
+	default:
+		return -EFAULT;
+	}
+}
+
+static struct device_attribute mmc_dev_attrs[] = {
+	MMC_ATTR_RO(type),
+	__ATTR_NULL,
+};
+
+/*
+ * This currently matches any MMC driver to any MMC card - drivers
+ * themselves make the decision whether to drive this card in their
+ * probe method.
+ */
+static int mmc_bus_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static int
+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
+		int buf_size)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	int retval = 0, i = 0, length = 0;
+
+#define add_env(fmt,val) do {					\
+	retval = add_uevent_var(envp, num_envp, &i,		\
+				buf, buf_size, &length,		\
+				fmt, val);			\
+	if (retval)						\
+		return retval;					\
+} while (0);
+
+	switch (card->type) {
+	case MMC_TYPE_MMC:
+		add_env("MMC_TYPE=%s", "MMC");
+		break;
+	case MMC_TYPE_SD:
+		add_env("MMC_TYPE=%s", "SD");
+		break;
+	}
+
+	add_env("MMC_NAME=%s", mmc_card_name(card));
+
+#undef add_env
+
+	envp[i] = NULL;
+
+	return 0;
+}
+
+static int mmc_bus_probe(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	return drv->probe(card);
+}
+
+static int mmc_bus_remove(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	drv->remove(card);
+
+	return 0;
+}
+
+static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	int ret = 0;
+
+	if (dev->driver && drv->suspend)
+		ret = drv->suspend(card, state);
+	return ret;
+}
+
+static int mmc_bus_resume(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	int ret = 0;
+
+	if (dev->driver && drv->resume)
+		ret = drv->resume(card);
+	return ret;
+}
+
+static struct bus_type mmc_bus_type = {
+	.name		= "mmc",
+	.dev_attrs	= mmc_dev_attrs,
+	.match		= mmc_bus_match,
+	.uevent		= mmc_bus_uevent,
+	.probe		= mmc_bus_probe,
+	.remove		= mmc_bus_remove,
+	.suspend	= mmc_bus_suspend,
+	.resume		= mmc_bus_resume,
+};
+
+int mmc_register_bus(void)
+{
+	return bus_register(&mmc_bus_type);
+}
+
+void mmc_unregister_bus(void)
+{
+	bus_unregister(&mmc_bus_type);
+}
+
+/**
+ *	mmc_register_driver - register a media driver
+ *	@drv: MMC media driver
+ */
+int mmc_register_driver(struct mmc_driver *drv)
+{
+	drv->drv.bus = &mmc_bus_type;
+	return driver_register(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_register_driver);
+
+/**
+ *	mmc_unregister_driver - unregister a media driver
+ *	@drv: MMC media driver
+ */
+void mmc_unregister_driver(struct mmc_driver *drv)
+{
+	drv->drv.bus = &mmc_bus_type;
+	driver_unregister(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_unregister_driver);
+
+static void mmc_release_card(struct device *dev)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	kfree(card);
+}
+
+/*
+ * Allocate and initialise a new MMC card structure.
+ */
+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+{
+	struct mmc_card *card;
+
+	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+	if (!card)
+		return ERR_PTR(-ENOMEM);
+
+	memset(card, 0, sizeof(struct mmc_card));
+
+	card->host = host;
+
+	device_initialize(&card->dev);
+
+	card->dev.parent = mmc_classdev(host);
+	card->dev.bus = &mmc_bus_type;
+	card->dev.release = mmc_release_card;
+
+	return card;
+}
+
+/*
+ * Register a new MMC card with the driver model.
+ */
+int mmc_add_card(struct mmc_card *card)
+{
+	int ret;
+
+	snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+		 "%s:%04x", mmc_hostname(card->host), card->rca);
+
+	card->dev.uevent_suppress = 1;
+
+	ret = device_add(&card->dev);
+	if (ret)
+		return ret;
+
+	if (card->host->bus_ops->sysfs_add) {
+		ret = card->host->bus_ops->sysfs_add(card->host, card);
+		if (ret) {
+			device_del(&card->dev);
+			return ret;
+		 }
+	}
+
+	card->dev.uevent_suppress = 0;
+
+	kobject_uevent(&card->dev.kobj, KOBJ_ADD);
+
+	mmc_card_set_present(card);
+
+	return 0;
+}
+
+/*
+ * Unregister a new MMC card with the driver model, and
+ * (eventually) free it.
+ */
+void mmc_remove_card(struct mmc_card *card)
+{
+	if (mmc_card_present(card)) {
+		if (card->host->bus_ops->sysfs_remove)
+			card->host->bus_ops->sysfs_remove(card->host, card);
+		device_del(&card->dev);
+	}
+
+	put_device(&card->dev);
+}
+
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h
new file mode 100644
index 0000000..4f35431
--- /dev/null
+++ b/drivers/mmc/core/bus.h
@@ -0,0 +1,22 @@
+/*
+ *  linux/drivers/mmc/core/bus.h
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _MMC_CORE_BUS_H
+#define _MMC_CORE_BUS_H
+
+struct mmc_card *mmc_alloc_card(struct mmc_host *host);
+int mmc_add_card(struct mmc_card *card);
+void mmc_remove_card(struct mmc_card *card);
+
+int mmc_register_bus(void);
+void mmc_unregister_bus(void);
+
+#endif
+
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7385acf..b5d8a6d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -27,7 +27,8 @@
 #include <linux/mmc/sd.h>
 
 #include "core.h"
-#include "sysfs.h"
+#include "bus.h"
+#include "host.h"
 
 #include "mmc_ops.h"
 #include "sd_ops.h"
@@ -35,6 +36,25 @@
 extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
 extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
 
+static struct workqueue_struct *workqueue;
+
+/*
+ * Internal function. Schedule delayed work in the MMC work queue.
+ */
+static int mmc_schedule_delayed_work(struct delayed_work *work,
+				     unsigned long delay)
+{
+	return queue_delayed_work(workqueue, work, delay);
+}
+
+/*
+ * Internal function. Flush all scheduled work from the MMC work queue.
+ */
+static void mmc_flush_scheduled_work(void)
+{
+	flush_workqueue(workqueue);
+}
+
 /**
  *	mmc_request_done - finish processing an MMC request
  *	@host: MMC host which completed request
@@ -369,22 +389,6 @@
 }
 
 /*
- * Allocate a new MMC card
- */
-struct mmc_card *mmc_alloc_card(struct mmc_host *host)
-{
-	struct mmc_card *card;
-
-	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
-	if (!card)
-		return ERR_PTR(-ENOMEM);
-
-	mmc_init_card(card, host);
-
-	return card;
-}
-
-/*
  * Apply power to the MMC stack.  This is a two-stage process.
  * First, we enable power to the card without the clock running.
  * We then wait a bit for the power to stabilise.  Finally,
@@ -512,7 +516,7 @@
 EXPORT_SYMBOL(mmc_detect_change);
 
 
-static void mmc_rescan(struct work_struct *work)
+void mmc_rescan(struct work_struct *work)
 {
 	struct mmc_host *host =
 		container_of(work, struct mmc_host, detect.work);
@@ -561,69 +565,13 @@
 	}
 }
 
-
-/**
- *	mmc_alloc_host - initialise the per-host structure.
- *	@extra: sizeof private data structure
- *	@dev: pointer to host device model structure
- *
- *	Initialise the per-host structure.
- */
-struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+void mmc_start_host(struct mmc_host *host)
 {
-	struct mmc_host *host;
-
-	host = mmc_alloc_host_sysfs(extra, dev);
-	if (host) {
-		spin_lock_init(&host->lock);
-		init_waitqueue_head(&host->wq);
-		INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-
-		/*
-		 * By default, hosts do not support SGIO or large requests.
-		 * They have to set these according to their abilities.
-		 */
-		host->max_hw_segs = 1;
-		host->max_phys_segs = 1;
-		host->max_seg_size = PAGE_CACHE_SIZE;
-
-		host->max_req_size = PAGE_CACHE_SIZE;
-		host->max_blk_size = 512;
-		host->max_blk_count = PAGE_CACHE_SIZE / 512;
-	}
-
-	return host;
+	mmc_power_off(host);
+	mmc_detect_change(host, 0);
 }
 
-EXPORT_SYMBOL(mmc_alloc_host);
-
-/**
- *	mmc_add_host - initialise host hardware
- *	@host: mmc host
- */
-int mmc_add_host(struct mmc_host *host)
-{
-	int ret;
-
-	ret = mmc_add_host_sysfs(host);
-	if (ret == 0) {
-		mmc_power_off(host);
-		mmc_detect_change(host, 0);
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(mmc_add_host);
-
-/**
- *	mmc_remove_host - remove host hardware
- *	@host: mmc host
- *
- *	Unregister and remove all cards associated with this host,
- *	and power down the MMC bus.
- */
-void mmc_remove_host(struct mmc_host *host)
+void mmc_stop_host(struct mmc_host *host)
 {
 #ifdef CONFIG_MMC_DEBUG
 	unsigned long flags;
@@ -648,24 +596,8 @@
 	BUG_ON(host->card);
 
 	mmc_power_off(host);
-	mmc_remove_host_sysfs(host);
 }
 
-EXPORT_SYMBOL(mmc_remove_host);
-
-/**
- *	mmc_free_host - free the host structure
- *	@host: mmc host
- *
- *	Free the host once all references to it have been dropped.
- */
-void mmc_free_host(struct mmc_host *host)
-{
-	mmc_free_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_free_host);
-
 #ifdef CONFIG_PM
 
 /**
@@ -726,4 +658,31 @@
 
 #endif
 
+static int __init mmc_init(void)
+{
+	int ret;
+
+	workqueue = create_singlethread_workqueue("kmmcd");
+	if (!workqueue)
+		return -ENOMEM;
+
+	ret = mmc_register_bus();
+	if (ret == 0) {
+		ret = mmc_register_host_class();
+		if (ret)
+			mmc_unregister_bus();
+	}
+	return ret;
+}
+
+static void __exit mmc_exit(void)
+{
+	mmc_unregister_host_class();
+	mmc_unregister_bus();
+	destroy_workqueue(workqueue);
+}
+
+module_init(mmc_init);
+module_exit(mmc_exit);
+
 MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 177264d..ae006b3 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -18,6 +18,8 @@
 struct mmc_bus_ops {
 	void (*remove)(struct mmc_host *);
 	void (*detect)(struct mmc_host *);
+	int (*sysfs_add)(struct mmc_host *, struct mmc_card *card);
+	void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card);
 	void (*suspend)(struct mmc_host *);
 	void (*resume)(struct mmc_host *);
 };
@@ -54,8 +56,6 @@
 u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
 void mmc_set_timing(struct mmc_host *host, unsigned int timing);
 
-struct mmc_card *mmc_alloc_card(struct mmc_host *host);
-
 static inline void mmc_delay(unsigned int ms)
 {
 	if (ms < 1000 / HZ) {
@@ -66,5 +66,9 @@
 	}
 }
 
+void mmc_rescan(struct work_struct *work);
+void mmc_start_host(struct mmc_host *host);
+void mmc_stop_host(struct mmc_host *host);
+
 #endif
 
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
new file mode 100644
index 0000000..1433d95
--- /dev/null
+++ b/drivers/mmc/core/host.c
@@ -0,0 +1,156 @@
+/*
+ *  linux/drivers/mmc/core/host.c
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright (C) 2007 Pierre Ossman
+ *
+ * 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.
+ *
+ *  MMC host class device management
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/pagemap.h>
+
+#include <linux/mmc/host.h>
+
+#include "core.h"
+#include "host.h"
+
+#define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)
+
+static void mmc_host_classdev_release(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+	kfree(host);
+}
+
+static struct class mmc_host_class = {
+	.name		= "mmc_host",
+	.dev_release	= mmc_host_classdev_release,
+};
+
+int mmc_register_host_class(void)
+{
+	return class_register(&mmc_host_class);
+}
+
+void mmc_unregister_host_class(void)
+{
+	class_unregister(&mmc_host_class);
+}
+
+static DEFINE_IDR(mmc_host_idr);
+static DEFINE_SPINLOCK(mmc_host_lock);
+
+/**
+ *	mmc_alloc_host - initialise the per-host structure.
+ *	@extra: sizeof private data structure
+ *	@dev: pointer to host device model structure
+ *
+ *	Initialise the per-host structure.
+ */
+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+{
+	struct mmc_host *host;
+
+	host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+	if (!host)
+		return NULL;
+
+	memset(host, 0, sizeof(struct mmc_host) + extra);
+
+	host->parent = dev;
+	host->class_dev.parent = dev;
+	host->class_dev.class = &mmc_host_class;
+	device_initialize(&host->class_dev);
+
+	spin_lock_init(&host->lock);
+	init_waitqueue_head(&host->wq);
+	INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+
+	/*
+	 * By default, hosts do not support SGIO or large requests.
+	 * They have to set these according to their abilities.
+	 */
+	host->max_hw_segs = 1;
+	host->max_phys_segs = 1;
+	host->max_seg_size = PAGE_CACHE_SIZE;
+
+	host->max_req_size = PAGE_CACHE_SIZE;
+	host->max_blk_size = 512;
+	host->max_blk_count = PAGE_CACHE_SIZE / 512;
+
+	return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ *	mmc_add_host - initialise host hardware
+ *	@host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+	int err;
+
+	if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+		return -ENOMEM;
+
+	spin_lock(&mmc_host_lock);
+	err = idr_get_new(&mmc_host_idr, host, &host->index);
+	spin_unlock(&mmc_host_lock);
+	if (err)
+		return err;
+
+	snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+		 "mmc%d", host->index);
+
+	err = device_add(&host->class_dev);
+	if (err)
+		return err;
+
+	mmc_start_host(host);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_add_host);
+
+/**
+ *	mmc_remove_host - remove host hardware
+ *	@host: mmc host
+ *
+ *	Unregister and remove all cards associated with this host,
+ *	and power down the MMC bus.
+ */
+void mmc_remove_host(struct mmc_host *host)
+{
+	mmc_stop_host(host);
+
+	device_del(&host->class_dev);
+
+	spin_lock(&mmc_host_lock);
+	idr_remove(&mmc_host_idr, host->index);
+	spin_unlock(&mmc_host_lock);
+}
+
+EXPORT_SYMBOL(mmc_remove_host);
+
+/**
+ *	mmc_free_host - free the host structure
+ *	@host: mmc host
+ *
+ *	Free the host once all references to it have been dropped.
+ */
+void mmc_free_host(struct mmc_host *host)
+{
+	put_device(&host->class_dev);
+}
+
+EXPORT_SYMBOL(mmc_free_host);
+
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
new file mode 100644
index 0000000..c2dc3d2
--- /dev/null
+++ b/drivers/mmc/core/host.h
@@ -0,0 +1,18 @@
+/*
+ *  linux/drivers/mmc/core/host.h
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _MMC_CORE_HOST_H
+#define _MMC_CORE_HOST_H
+
+int mmc_register_host_class(void);
+void mmc_unregister_host_class(void);
+
+#endif
+
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 42cc286..66f85bf 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -18,6 +18,7 @@
 
 #include "core.h"
 #include "sysfs.h"
+#include "bus.h"
 #include "mmc_ops.h"
 
 static const unsigned int tran_exp[] = {
@@ -236,7 +237,7 @@
  * In the case of a resume, "curcard" will contain the card
  * we're trying to reinitialise.
  */
-static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	struct mmc_card *oldcard)
 {
 	struct mmc_card *card;
@@ -413,8 +414,7 @@
 	mmc_release_host(host);
 
 	if (err != MMC_ERR_NONE) {
-		mmc_remove_card(host->card);
-		host->card = NULL;
+		mmc_remove(host);
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
@@ -422,6 +422,53 @@
 	}
 }
 
+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+	card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+	card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute mmc_dev_attrs[] = {
+	MMC_ATTR_RO(cid),
+	MMC_ATTR_RO(csd),
+	MMC_ATTR_RO(date),
+	MMC_ATTR_RO(fwrev),
+	MMC_ATTR_RO(hwrev),
+	MMC_ATTR_RO(manfid),
+	MMC_ATTR_RO(name),
+	MMC_ATTR_RO(oemid),
+	MMC_ATTR_RO(serial),
+	__ATTR_NULL,
+};
+
+/*
+ * Adds sysfs entries as relevant.
+ */
+static int mmc_sysfs_add(struct mmc_host *host, struct mmc_card *card)
+{
+	int ret;
+
+	ret = mmc_add_attrs(card, mmc_dev_attrs);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Removes the sysfs entries added by mmc_sysfs_add().
+ */
+static void mmc_sysfs_remove(struct mmc_host *host, struct mmc_card *card)
+{
+	mmc_remove_attrs(card, mmc_dev_attrs);
+}
+
 #ifdef CONFIG_MMC_UNSAFE_RESUME
 
 /*
@@ -453,11 +500,9 @@
 
 	mmc_claim_host(host);
 
-	err = mmc_sd_init_card(host, host->ocr, host->card);
+	err = mmc_init_card(host, host->ocr, host->card);
 	if (err != MMC_ERR_NONE) {
-		mmc_remove_card(host->card);
-		host->card = NULL;
-
+		mmc_remove(host);
 		mmc_detach_bus(host);
 	}
 
@@ -474,6 +519,8 @@
 static const struct mmc_bus_ops mmc_ops = {
 	.remove = mmc_remove,
 	.detect = mmc_detect,
+	.sysfs_add = mmc_sysfs_add,
+	.sysfs_remove = mmc_sysfs_remove,
 	.suspend = mmc_suspend,
 	.resume = mmc_resume,
 };
@@ -512,13 +559,13 @@
 	/*
 	 * Detect and init the card.
 	 */
-	err = mmc_sd_init_card(host, host->ocr, NULL);
+	err = mmc_init_card(host, host->ocr, NULL);
 	if (err != MMC_ERR_NONE)
 		goto err;
 
 	mmc_release_host(host);
 
-	err = mmc_register_card(host->card);
+	err = mmc_add_card(host->card);
 	if (err)
 		goto reclaim_host;
 
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index c1dfd03..1240684 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -15,14 +15,14 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
 
 #include "core.h"
 #include "sysfs.h"
+#include "bus.h"
 #include "mmc_ops.h"
 #include "sd_ops.h"
 
-#include "core.h"
-
 static const unsigned int tran_exp[] = {
 	10000,		100000,		1000000,	10000000,
 	0,		0,		0,		0
@@ -192,6 +192,16 @@
 	int err;
 	u8 *status;
 
+	if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+		return MMC_ERR_NONE;
+
+	if (!(card->csd.cmdclass & CCC_SWITCH)) {
+		printk(KERN_WARNING "%s: card lacks mandatory switch "
+			"function, performance might suffer.\n",
+			mmc_hostname(card->host));
+		return MMC_ERR_NONE;
+	}
+
 	err = MMC_ERR_FAILED;
 
 	status = kmalloc(64, GFP_KERNEL);
@@ -204,10 +214,9 @@
 
 	err = mmc_sd_switch(card, 0, 0, 1, status);
 	if (err != MMC_ERR_NONE) {
-		/*
-		 * Card not supporting high-speed will ignore the
-		 * command.
-		 */
+		printk(KERN_WARNING "%s: problem reading switch "
+			"capabilities, performance might suffer.\n",
+			mmc_hostname(card->host));
 		err = MMC_ERR_NONE;
 		goto out;
 	}
@@ -229,6 +238,12 @@
 	int err;
 	u8 *status;
 
+	if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+		return MMC_ERR_NONE;
+
+	if (!(card->csd.cmdclass & CCC_SWITCH))
+		return MMC_ERR_NONE;
+
 	if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
 		return MMC_ERR_NONE;
 
@@ -402,7 +417,7 @@
 	/*
 	 * Switch to wider bus (if supported).
 	 */
-	if ((host->caps && MMC_CAP_4_BIT_DATA) &&
+	if ((host->caps & MMC_CAP_4_BIT_DATA) &&
 		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
 		err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
 		if (err != MMC_ERR_NONE)
@@ -411,6 +426,21 @@
 		mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
 	}
 
+	/*
+	 * Check if read-only switch is active.
+	 */
+	if (!oldcard) {
+		if (!host->ops->get_ro) {
+			printk(KERN_WARNING "%s: host does not "
+				"support reading read-only "
+				"switch. assuming write-enable.\n",
+				mmc_hostname(host));
+		} else {
+			if (host->ops->get_ro(host))
+				mmc_card_set_readonly(card);
+		}
+	}
+
 	if (!oldcard)
 		host->card = card;
 
@@ -456,8 +486,7 @@
 	mmc_release_host(host);
 
 	if (err != MMC_ERR_NONE) {
-		mmc_remove_card(host->card);
-		host->card = NULL;
+		mmc_sd_remove(host);
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
@@ -465,6 +494,55 @@
 	}
 }
 
+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+	card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+	card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR_FN(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute mmc_sd_dev_attrs[] = {
+	MMC_ATTR_RO(cid),
+	MMC_ATTR_RO(csd),
+	MMC_ATTR_RO(scr),
+	MMC_ATTR_RO(date),
+	MMC_ATTR_RO(fwrev),
+	MMC_ATTR_RO(hwrev),
+	MMC_ATTR_RO(manfid),
+	MMC_ATTR_RO(name),
+	MMC_ATTR_RO(oemid),
+	MMC_ATTR_RO(serial),
+	__ATTR_NULL,
+};
+
+/*
+ * Adds sysfs entries as relevant.
+ */
+static int mmc_sd_sysfs_add(struct mmc_host *host, struct mmc_card *card)
+{
+	int ret;
+
+	ret = mmc_add_attrs(card, mmc_sd_dev_attrs);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Removes the sysfs entries added by mmc_sysfs_add().
+ */
+static void mmc_sd_sysfs_remove(struct mmc_host *host, struct mmc_card *card)
+{
+	mmc_remove_attrs(card, mmc_sd_dev_attrs);
+}
+
 #ifdef CONFIG_MMC_UNSAFE_RESUME
 
 /*
@@ -498,9 +576,7 @@
 
 	err = mmc_sd_init_card(host, host->ocr, host->card);
 	if (err != MMC_ERR_NONE) {
-		mmc_remove_card(host->card);
-		host->card = NULL;
-
+		mmc_sd_remove(host);
 		mmc_detach_bus(host);
 	}
 
@@ -517,6 +593,8 @@
 static const struct mmc_bus_ops mmc_sd_ops = {
 	.remove = mmc_sd_remove,
 	.detect = mmc_sd_detect,
+	.sysfs_add = mmc_sd_sysfs_add,
+	.sysfs_remove = mmc_sd_sysfs_remove,
 	.suspend = mmc_sd_suspend,
 	.resume = mmc_sd_resume,
 };
@@ -568,7 +646,7 @@
 
 	mmc_release_host(host);
 
-	err = mmc_register_card(host->card);
+	err = mmc_add_card(host->card);
 	if (err)
 		goto reclaim_host;
 
diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c
index 843b1fb..00a97e7 100644
--- a/drivers/mmc/core/sysfs.c
+++ b/drivers/mmc/core/sysfs.c
@@ -2,6 +2,7 @@
  *  linux/drivers/mmc/core/sysfs.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
  *
  * 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
@@ -9,352 +10,34 @@
  *
  *  MMC sysfs/driver model support.
  */
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/device.h>
-#include <linux/idr.h>
-#include <linux/workqueue.h>
 
 #include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
 
 #include "sysfs.h"
 
-#define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
-#define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
-#define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)
-
-#define MMC_ATTR(name, fmt, args...)					\
-static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	struct mmc_card *card = dev_to_mmc_card(dev);			\
-	return sprintf(buf, fmt, args);					\
-}
-
-MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
-	card->raw_cid[2], card->raw_cid[3]);
-MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
-	card->raw_csd[2], card->raw_csd[3]);
-MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
-MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
-MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
-MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
-MMC_ATTR(name, "%s\n", card->cid.prod_name);
-MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
-MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
-
-#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
-
-static struct device_attribute mmc_dev_attrs[] = {
-	MMC_ATTR_RO(cid),
-	MMC_ATTR_RO(csd),
-	MMC_ATTR_RO(date),
-	MMC_ATTR_RO(fwrev),
-	MMC_ATTR_RO(hwrev),
-	MMC_ATTR_RO(manfid),
-	MMC_ATTR_RO(name),
-	MMC_ATTR_RO(oemid),
-	MMC_ATTR_RO(serial),
-	__ATTR_NULL
-};
-
-static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
-
-
-static void mmc_release_card(struct device *dev)
+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs)
 {
-	struct mmc_card *card = dev_to_mmc_card(dev);
+	int error = 0;
+	int i;
 
-	kfree(card);
-}
-
-/*
- * This currently matches any MMC driver to any MMC card - drivers
- * themselves make the decision whether to drive this card in their
- * probe method.
- */
-static int mmc_bus_match(struct device *dev, struct device_driver *drv)
-{
-	return 1;
-}
-
-static int
-mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
-		int buf_size)
-{
-	struct mmc_card *card = dev_to_mmc_card(dev);
-	char ccc[13];
-	int retval = 0, i = 0, length = 0;
-
-#define add_env(fmt,val) do {					\
-	retval = add_uevent_var(envp, num_envp, &i,		\
-				buf, buf_size, &length,		\
-				fmt, val);			\
-	if (retval)						\
-		return retval;					\
-} while (0);
-
-	for (i = 0; i < 12; i++)
-		ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
-	ccc[12] = '\0';
-
-	add_env("MMC_CCC=%s", ccc);
-	add_env("MMC_MANFID=%06x", card->cid.manfid);
-	add_env("MMC_NAME=%s", mmc_card_name(card));
-	add_env("MMC_OEMID=%04x", card->cid.oemid);
-#undef add_env
-	envp[i] = NULL;
-
-	return 0;
-}
-
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
-{
-	struct mmc_driver *drv = to_mmc_driver(dev->driver);
-	struct mmc_card *card = dev_to_mmc_card(dev);
-	int ret = 0;
-
-	if (dev->driver && drv->suspend)
-		ret = drv->suspend(card, state);
-	return ret;
-}
-
-static int mmc_bus_resume(struct device *dev)
-{
-	struct mmc_driver *drv = to_mmc_driver(dev->driver);
-	struct mmc_card *card = dev_to_mmc_card(dev);
-	int ret = 0;
-
-	if (dev->driver && drv->resume)
-		ret = drv->resume(card);
-	return ret;
-}
-
-static int mmc_bus_probe(struct device *dev)
-{
-	struct mmc_driver *drv = to_mmc_driver(dev->driver);
-	struct mmc_card *card = dev_to_mmc_card(dev);
-
-	return drv->probe(card);
-}
-
-static int mmc_bus_remove(struct device *dev)
-{
-	struct mmc_driver *drv = to_mmc_driver(dev->driver);
-	struct mmc_card *card = dev_to_mmc_card(dev);
-
-	drv->remove(card);
-
-	return 0;
-}
-
-static struct bus_type mmc_bus_type = {
-	.name		= "mmc",
-	.dev_attrs	= mmc_dev_attrs,
-	.match		= mmc_bus_match,
-	.uevent		= mmc_bus_uevent,
-	.probe		= mmc_bus_probe,
-	.remove		= mmc_bus_remove,
-	.suspend	= mmc_bus_suspend,
-	.resume		= mmc_bus_resume,
-};
-
-/**
- *	mmc_register_driver - register a media driver
- *	@drv: MMC media driver
- */
-int mmc_register_driver(struct mmc_driver *drv)
-{
-	drv->drv.bus = &mmc_bus_type;
-	return driver_register(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_register_driver);
-
-/**
- *	mmc_unregister_driver - unregister a media driver
- *	@drv: MMC media driver
- */
-void mmc_unregister_driver(struct mmc_driver *drv)
-{
-	drv->drv.bus = &mmc_bus_type;
-	driver_unregister(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_unregister_driver);
-
-
-/*
- * Internal function.  Initialise a MMC card structure.
- */
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
-{
-	memset(card, 0, sizeof(struct mmc_card));
-	card->host = host;
-	device_initialize(&card->dev);
-	card->dev.parent = mmc_classdev(host);
-	card->dev.bus = &mmc_bus_type;
-	card->dev.release = mmc_release_card;
-}
-
-/*
- * Internal function.  Register a new MMC card with the driver model.
- */
-int mmc_register_card(struct mmc_card *card)
-{
-	int ret;
-
-	snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
-		 "%s:%04x", mmc_hostname(card->host), card->rca);
-
-	ret = device_add(&card->dev);
-	if (ret == 0) {
-		if (mmc_card_sd(card)) {
-			ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
-			if (ret)
-				device_del(&card->dev);
+	for (i = 0; attr_name(attrs[i]); i++) {
+		error = device_create_file(&card->dev, &attrs[i]);
+		if (error) {
+			while (--i >= 0)
+				device_remove_file(&card->dev, &attrs[i]);
+			break;
 		}
 	}
-	if (ret == 0)
-		mmc_card_set_present(card);
-	return ret;
+
+	return error;
 }
 
-/*
- * Internal function.  Unregister a new MMC card with the
- * driver model, and (eventually) free it.
- */
-void mmc_remove_card(struct mmc_card *card)
+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs)
 {
-	if (mmc_card_present(card)) {
-		if (mmc_card_sd(card))
-			device_remove_file(&card->dev, &mmc_dev_attr_scr);
+	int i;
 
-		device_del(&card->dev);
-	}
-
-	put_device(&card->dev);
+	for (i = 0; attr_name(attrs[i]); i++)
+		device_remove_file(&card->dev, &attrs[i]);
 }
 
-
-static void mmc_host_classdev_release(struct device *dev)
-{
-	struct mmc_host *host = cls_dev_to_mmc_host(dev);
-	kfree(host);
-}
-
-static struct class mmc_host_class = {
-	.name		= "mmc_host",
-	.dev_release	= mmc_host_classdev_release,
-};
-
-static DEFINE_IDR(mmc_host_idr);
-static DEFINE_SPINLOCK(mmc_host_lock);
-
-/*
- * Internal function. Allocate a new MMC host.
- */
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
-{
-	struct mmc_host *host;
-
-	host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
-	if (host) {
-		memset(host, 0, sizeof(struct mmc_host) + extra);
-
-		host->parent = dev;
-		host->class_dev.parent = dev;
-		host->class_dev.class = &mmc_host_class;
-		device_initialize(&host->class_dev);
-	}
-
-	return host;
-}
-
-/*
- * Internal function. Register a new MMC host with the MMC class.
- */
-int mmc_add_host_sysfs(struct mmc_host *host)
-{
-	int err;
-
-	if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
-		return -ENOMEM;
-
-	spin_lock(&mmc_host_lock);
-	err = idr_get_new(&mmc_host_idr, host, &host->index);
-	spin_unlock(&mmc_host_lock);
-	if (err)
-		return err;
-
-	snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
-		 "mmc%d", host->index);
-
-	return device_add(&host->class_dev);
-}
-
-/*
- * Internal function. Unregister a MMC host with the MMC class.
- */
-void mmc_remove_host_sysfs(struct mmc_host *host)
-{
-	device_del(&host->class_dev);
-
-	spin_lock(&mmc_host_lock);
-	idr_remove(&mmc_host_idr, host->index);
-	spin_unlock(&mmc_host_lock);
-}
-
-/*
- * Internal function. Free a MMC host.
- */
-void mmc_free_host_sysfs(struct mmc_host *host)
-{
-	put_device(&host->class_dev);
-}
-
-static struct workqueue_struct *workqueue;
-
-/*
- * Internal function. Schedule delayed work in the MMC work queue.
- */
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
-{
-	return queue_delayed_work(workqueue, work, delay);
-}
-
-/*
- * Internal function. Flush all scheduled work from the MMC work queue.
- */
-void mmc_flush_scheduled_work(void)
-{
-	flush_workqueue(workqueue);
-}
-
-static int __init mmc_init(void)
-{
-	int ret;
-
-	workqueue = create_singlethread_workqueue("kmmcd");
-	if (!workqueue)
-		return -ENOMEM;
-
-	ret = bus_register(&mmc_bus_type);
-	if (ret == 0) {
-		ret = class_register(&mmc_host_class);
-		if (ret)
-			bus_unregister(&mmc_bus_type);
-	}
-	return ret;
-}
-
-static void __exit mmc_exit(void)
-{
-	class_unregister(&mmc_host_class);
-	bus_unregister(&mmc_bus_type);
-	destroy_workqueue(workqueue);
-}
-
-module_init(mmc_init);
-module_exit(mmc_exit);
diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h
index 80e29b3..4b8f670 100644
--- a/drivers/mmc/core/sysfs.h
+++ b/drivers/mmc/core/sysfs.h
@@ -11,17 +11,16 @@
 #ifndef _MMC_CORE_SYSFS_H
 #define _MMC_CORE_SYSFS_H
 
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
-int mmc_register_card(struct mmc_card *card);
-void mmc_remove_card(struct mmc_card *card);
+#define MMC_ATTR_FN(name, fmt, args...)					\
+static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
+{									\
+	struct mmc_card *card = container_of(dev, struct mmc_card, dev);\
+	return sprintf(buf, fmt, args);					\
+}
 
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
-int mmc_add_host_sysfs(struct mmc_host *host);
-void mmc_remove_host_sysfs(struct mmc_host *host);
-void mmc_free_host_sysfs(struct mmc_host *host);
+#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
 
-int mmc_schedule_work(struct work_struct *work);
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
-void mmc_flush_scheduled_work(void);
+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs);
+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs);
 
 #endif
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index e37943c..28c8818 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -78,8 +78,6 @@
 
 #define DRIVER_NAME "at91_mci"
 
-#undef	SUPPORT_4WIRE
-
 #define FL_SENT_COMMAND	(1 << 0)
 #define FL_SENT_STOP	(1 << 1)
 
@@ -131,7 +129,7 @@
 /*
  * Copy from sg to a dma block - used for transfers
  */
-static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
+static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
 {
 	unsigned int len, i, size;
 	unsigned *dmabuf = host->buffer;
@@ -180,7 +178,7 @@
 /*
  * Prepare a dma read
  */
-static void at91mci_pre_dma_read(struct at91mci_host *host)
+static void at91_mci_pre_dma_read(struct at91mci_host *host)
 {
 	int i;
 	struct scatterlist *sg;
@@ -248,7 +246,7 @@
 /*
  * Handle after a dma read
  */
-static void at91mci_post_dma_read(struct at91mci_host *host)
+static void at91_mci_post_dma_read(struct at91mci_host *host)
 {
 	struct mmc_command *cmd;
 	struct mmc_data *data;
@@ -268,8 +266,6 @@
 	}
 
 	while (host->in_use_index < host->transfer_index) {
-		unsigned int *buffer;
-
 		struct scatterlist *sg;
 
 		pr_debug("finishing index %d\n", host->in_use_index);
@@ -280,29 +276,31 @@
 
 		dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
 
-		/* Swap the contents of the buffer */
-		buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
-		pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
-
 		data->bytes_xfered += sg->length;
 
 		if (cpu_is_at91rm9200()) {	/* AT91RM9200 errata */
+			unsigned int *buffer;
 			int index;
 
+			/* Swap the contents of the buffer */
+			buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+			pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
+
 			for (index = 0; index < (sg->length / 4); index++)
 				buffer[index] = swab32(buffer[index]);
+
+			kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
 		}
 
-		kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
 		flush_dcache_page(sg->page);
 	}
 
 	/* Is there another transfer to trigger? */
 	if (host->transfer_index < data->sg_len)
-		at91mci_pre_dma_read(host);
+		at91_mci_pre_dma_read(host);
 	else {
+		at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
 		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
-		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 	}
 
 	pr_debug("post dma read done\n");
@@ -323,7 +321,6 @@
 
 	/* Now wait for cmd ready */
 	at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
-	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
 
 	cmd = host->cmd;
 	if (!cmd) return;
@@ -331,18 +328,53 @@
 	data = cmd->data;
 	if (!data) return;
 
+	if (cmd->data->flags & MMC_DATA_MULTI) {
+		pr_debug("multiple write : wait for BLKE...\n");
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
+	} else
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
 	data->bytes_xfered = host->total_length;
 }
 
+/*Handle after command sent ready*/
+static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
+{
+	if (!host->cmd)
+		return 1;
+	else if (!host->cmd->data) {
+		if (host->flags & FL_SENT_STOP) {
+			/*After multi block write, we must wait for NOTBUSY*/
+			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+		} else return 1;
+	} else if (host->cmd->data->flags & MMC_DATA_WRITE) {
+		/*After sendding multi-block-write command, start DMA transfer*/
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE);
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
+		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
+	}
+
+	/* command not completed, have to wait */
+	return 0;
+}
+
+
 /*
  * Enable the controller
  */
 static void at91_mci_enable(struct at91mci_host *host)
 {
+	unsigned int mr;
+
 	at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
 	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
 	at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
-	at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
+	mr = AT91_MCI_PDCMODE | 0x34a;
+
+	if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+		mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
+
+	at91_mci_write(host, AT91_MCI_MR, mr);
 
 	/* use Slot A or B (only one at same time) */
 	at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
@@ -358,9 +390,8 @@
 
 /*
  * Send a command
- * return the interrupts to enable
  */
-static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
 {
 	unsigned int cmdr, mr;
 	unsigned int block_length;
@@ -371,8 +402,7 @@
 
 	host->cmd = cmd;
 
-	/* Not sure if this is needed */
-#if 0
+	/* Needed for leaving busy state before CMD1 */
 	if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
 		pr_debug("Clearing timeout\n");
 		at91_mci_write(host, AT91_MCI_ARGR, 0);
@@ -382,7 +412,7 @@
 			pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
 		}
 	}
-#endif
+
 	cmdr = cmd->opcode;
 
 	if (mmc_resp_type(cmd) == MMC_RSP_NONE)
@@ -417,7 +447,7 @@
 		blocks = 0;
 	}
 
-	if (cmd->opcode == MMC_STOP_TRANSMISSION)
+	if (host->flags & FL_SENT_STOP)
 		cmdr |= AT91_MCI_TRCMD_STOP;
 
 	if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
@@ -439,50 +469,48 @@
 		at91_mci_write(host, ATMEL_PDC_TCR, 0);
 		at91_mci_write(host, ATMEL_PDC_TNPR, 0);
 		at91_mci_write(host, ATMEL_PDC_TNCR, 0);
+		ier = AT91_MCI_CMDRDY;
+	} else {
+		/* zero block length and PDC mode */
+		mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
+		at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
 
-		at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
-		at91_mci_write(host, AT91_MCI_CMDR, cmdr);
-		return AT91_MCI_CMDRDY;
-	}
+		/*
+		 * Disable the PDC controller
+		 */
+		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 
-	mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;	/* zero block length and PDC mode */
-	at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+		if (cmdr & AT91_MCI_TRCMD_START) {
+			data->bytes_xfered = 0;
+			host->transfer_index = 0;
+			host->in_use_index = 0;
+			if (cmdr & AT91_MCI_TRDIR) {
+				/*
+				 * Handle a read
+				 */
+				host->buffer = NULL;
+				host->total_length = 0;
 
-	/*
-	 * Disable the PDC controller
-	 */
-	at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+				at91_mci_pre_dma_read(host);
+				ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
+			}
+			else {
+				/*
+				 * Handle a write
+				 */
+				host->total_length = block_length * blocks;
+				host->buffer = dma_alloc_coherent(NULL,
+						host->total_length,
+						&host->physical_address, GFP_KERNEL);
 
-	if (cmdr & AT91_MCI_TRCMD_START) {
-		data->bytes_xfered = 0;
-		host->transfer_index = 0;
-		host->in_use_index = 0;
-		if (cmdr & AT91_MCI_TRDIR) {
-			/*
-			 * Handle a read
-			 */
-			host->buffer = NULL;
-			host->total_length = 0;
+				at91_mci_sg_to_dma(host, data);
 
-			at91mci_pre_dma_read(host);
-			ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
-		}
-		else {
-			/*
-			 * Handle a write
-			 */
-			host->total_length = block_length * blocks;
-			host->buffer = dma_alloc_coherent(NULL,
-						  host->total_length,
-						  &host->physical_address, GFP_KERNEL);
+				pr_debug("Transmitting %d bytes\n", host->total_length);
 
-			at91mci_sg_to_dma(host, data);
-
-			pr_debug("Transmitting %d bytes\n", host->total_length);
-
-			at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
-			at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
-			ier = AT91_MCI_TXBUFE;
+				at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
+				at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
+				ier = AT91_MCI_CMDRDY;
+			}
 		}
 	}
 
@@ -497,39 +525,24 @@
 	if (cmdr & AT91_MCI_TRCMD_START) {
 		if (cmdr & AT91_MCI_TRDIR)
 			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
-		else
-			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 	}
-	return ier;
-}
 
-/*
- * Wait for a command to complete
- */
-static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
-	unsigned int ier;
-
-	ier = at91_mci_send_command(host, cmd);
-
-	pr_debug("setting ier to %08X\n", ier);
-
-	/* Stop on errors or the required value */
+	/* Enable selected interrupts */
 	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
 }
 
 /*
  * Process the next step in the request
  */
-static void at91mci_process_next(struct at91mci_host *host)
+static void at91_mci_process_next(struct at91mci_host *host)
 {
 	if (!(host->flags & FL_SENT_COMMAND)) {
 		host->flags |= FL_SENT_COMMAND;
-		at91mci_process_command(host, host->request->cmd);
+		at91_mci_send_command(host, host->request->cmd);
 	}
 	else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
 		host->flags |= FL_SENT_STOP;
-		at91mci_process_command(host, host->request->stop);
+		at91_mci_send_command(host, host->request->stop);
 	}
 	else
 		mmc_request_done(host->mmc, host->request);
@@ -538,7 +551,7 @@
 /*
  * Handle a command that has been completed
  */
-static void at91mci_completed_command(struct at91mci_host *host)
+static void at91_mci_completed_command(struct at91mci_host *host)
 {
 	struct mmc_command *cmd = host->cmd;
 	unsigned int status;
@@ -563,8 +576,7 @@
 	if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
 			AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
 			AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
-		if ((status & AT91_MCI_RCRCE) &&
-			((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
+		if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
 			cmd->error = MMC_ERR_NONE;
 		}
 		else {
@@ -584,7 +596,7 @@
 	else
 		cmd->error = MMC_ERR_NONE;
 
-	at91mci_process_next(host);
+	at91_mci_process_next(host);
 }
 
 /*
@@ -596,7 +608,7 @@
 	host->request = mrq;
 	host->flags = 0;
 
-	at91mci_process_next(host);
+	at91_mci_process_next(host);
 }
 
 /*
@@ -699,29 +711,33 @@
 			at91_mci_handle_transmitted(host);
 		}
 
+		if (int_status & AT91_MCI_ENDRX) {
+			pr_debug("ENDRX\n");
+			at91_mci_post_dma_read(host);
+		}
+
 		if (int_status & AT91_MCI_RXBUFF) {
 			pr_debug("RX buffer full\n");
-			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+			at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
+			completed = 1;
 		}
 
 		if (int_status & AT91_MCI_ENDTX)
 			pr_debug("Transmit has ended\n");
 
-		if (int_status & AT91_MCI_ENDRX) {
-			pr_debug("Receive has ended\n");
-			at91mci_post_dma_read(host);
-		}
-
 		if (int_status & AT91_MCI_NOTBUSY) {
 			pr_debug("Card is ready\n");
-			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+			completed = 1;
 		}
 
 		if (int_status & AT91_MCI_DTIP)
 			pr_debug("Data transfer in progress\n");
 
-		if (int_status & AT91_MCI_BLKE)
+		if (int_status & AT91_MCI_BLKE) {
 			pr_debug("Block transfer has ended\n");
+			completed = 1;
+		}
 
 		if (int_status & AT91_MCI_TXRDY)
 			pr_debug("Ready to transmit\n");
@@ -731,14 +747,14 @@
 
 		if (int_status & AT91_MCI_CMDRDY) {
 			pr_debug("Command ready\n");
-			completed = 1;
+			completed = at91_mci_handle_cmdrdy(host);
 		}
 	}
 
 	if (completed) {
 		pr_debug("Completed command\n");
 		at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-		at91mci_completed_command(host);
+		at91_mci_completed_command(host);
 	} else
 		at91_mci_write(host, AT91_MCI_IDR, int_status);
 
@@ -831,11 +847,11 @@
 	host->bus_mode = 0;
 	host->board = pdev->dev.platform_data;
 	if (host->board->wire4) {
-#ifdef SUPPORT_4WIRE
-		mmc->caps |= MMC_CAP_4_BIT_DATA;
-#else
-		printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
-#endif
+		if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+			mmc->caps |= MMC_CAP_4_BIT_DATA;
+		else
+			printk("AT91 MMC: 4 wire bus mode not supported"
+				" - using 1 wire\n");
 	}
 
 	/*
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index f967226..52b63f1 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -76,8 +76,7 @@
 #endif
 };
 
-#define AU1XMMC_CONTROLLER_COUNT \
-	(sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0]))
+#define AU1XMMC_CONTROLLER_COUNT (ARRAY_SIZE(au1xmmc_card_table))
 
 /* This array stores pointers for the hosts (used by the IRQ handler) */
 struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 1914e65..b0824a3 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -522,28 +522,10 @@
 		}
 
 		if (status & OMAP_MMC_STAT_CARD_ERR) {
-			if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
-				u32 response = OMAP_MMC_READ(host, RSP6)
-					| (OMAP_MMC_READ(host, RSP7) << 16);
-				/* STOP sometimes sets must-ignore bits */
-				if (!(response & (R1_CC_ERROR
-								| R1_ILLEGAL_COMMAND
-								| R1_COM_CRC_ERROR))) {
-					end_command = 1;
-					continue;
-				}
-			}
-
-			dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n",
+			dev_dbg(mmc_dev(host->mmc),
+				"ignoring card status error (CMD%d)\n",
 				host->cmd->opcode);
-			if (host->cmd) {
-				host->cmd->error = MMC_ERR_FAILED;
-				end_command = 1;
-			}
-			if (host->data) {
-				host->data->error = MMC_ERR_FAILED;
-				transfer_error = 1;
-			}
+			end_command = 1;
 		}
 
 		/*
diff --git a/drivers/mmc/host/pxamci.h b/drivers/mmc/host/pxamci.h
index 1b16322..df17c28 100644
--- a/drivers/mmc/host/pxamci.h
+++ b/drivers/mmc/host/pxamci.h
@@ -1,25 +1,3 @@
-#undef MMC_STRPCL
-#undef MMC_STAT
-#undef MMC_CLKRT
-#undef MMC_SPI
-#undef MMC_CMDAT
-#undef MMC_RESTO
-#undef MMC_RDTO
-#undef MMC_BLKLEN
-#undef MMC_NOB
-#undef MMC_PRTBUF
-#undef MMC_I_MASK
-#undef END_CMD_RES
-#undef PRG_DONE
-#undef DATA_TRAN_DONE
-#undef MMC_I_REG
-#undef MMC_CMD
-#undef MMC_ARGH
-#undef MMC_ARGL
-#undef MMC_RES
-#undef MMC_RXFIFO
-#undef MMC_TXFIFO
-
 #define MMC_STRPCL	0x0000
 #define STOP_CLOCK		(1 << 0)
 #define START_CLOCK		(2 << 0)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a359efd..10d15c3 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -70,6 +70,14 @@
 		.driver_data	= SDHCI_QUIRK_SINGLE_POWER_WRITE,
 	},
 
+	{
+		.vendor		= PCI_VENDOR_ID_ENE,
+		.device		= PCI_DEVICE_ID_ENE_CB712_SD_2,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= SDHCI_QUIRK_SINGLE_POWER_WRITE,
+	},
+
 	{	/* Generic SD host controller */
 		PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
 	},
@@ -1022,7 +1030,7 @@
 		writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
 	}
 
-	intmask &= SDHCI_INT_BUS_POWER;
+	intmask &= ~SDHCI_INT_BUS_POWER;
 
 	if (intmask) {
 		printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 9205540..451adcc 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -1,10 +1,9 @@
 #
 # Makefile for the memory technology device drivers.
 #
-# $Id: Makefile.common,v 1.7 2005/07/11 10:39:27 gleixner Exp $
 
 # Core functionality.
-mtd-y				:= mtdcore.o
+mtd-y				:= mtdcore.o mtdsuper.o
 mtd-$(CONFIG_MTD_PARTITIONS)	+= mtdpart.o
 obj-$(CONFIG_MTD)		+= $(mtd-y)
 
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 78872c3..b96ac8e 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -84,7 +84,7 @@
 #elif defined(CONFIG_MOMENCO_OCELOT)
 	0x2f000000,
         0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
         0xff000000,
 ##else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index a4873ab..e8f686f 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -650,7 +650,7 @@
  */
 static int msize = 0;
 #if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
-static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE
+static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE;
 #else
 static int asize = 0;
 #endif
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b665e4a..f88ebc5 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -258,12 +258,6 @@
 	help
 	  Support for the flash chip on Tsunami TIG bus.
 
-config MTD_LASAT
-	tristate "LASAT flash device"
-	depends on LASAT && MTD_CFI
-	help
-	  Support for the flash chips on the Lasat 100 and 200 boards.
-
 config MTD_NETtel
 	tristate "CFI flash device on SnapGear/SecureEdge"
 	depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 3acbb5d..970b189 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -47,7 +47,6 @@
 obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
 obj-$(CONFIG_MTD_ALCHEMY)       += alchemy-flash.o
-obj-$(CONFIG_MTD_LASAT)		+= lasat.o
 obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
 obj-$(CONFIG_MTD_EDB7312)	+= edb7312.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c
deleted file mode 100644
index e343763..0000000
--- a/drivers/mtd/maps/lasat.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Flash device on Lasat 100 and 200 boards
- *
- * (C) 2002 Brian Murphy <brian@murphy.dk>
- *
- * 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.
- *
- * $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/lasat/lasat.h>
-
-static struct mtd_info *lasat_mtd;
-
-static struct mtd_partition partition_info[LASAT_MTD_LAST];
-static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
-
-static void lasat_set_vpp(struct map_info *map, int vpp)
-{
-	if (vpp)
-	    *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
-	else
-	    *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
-}
-
-static struct map_info lasat_map = {
-	.name = "LASAT flash",
-	.bankwidth = 4,
-	.set_vpp = lasat_set_vpp
-};
-
-static int __init init_lasat(void)
-{
-	int i;
-	/* since we use AMD chips and set_vpp is not implimented
-	 * for these (yet) we still have to permanently enable flash write */
-	printk(KERN_NOTICE "Unprotecting flash\n");
-	ENABLE_VPP((&lasat_map));
-
-	lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
-	lasat_map.virt = ioremap_nocache(
-		        lasat_map.phys, lasat_board_info.li_flash_size);
-	lasat_map.size = lasat_board_info.li_flash_size;
-
-	simple_map_init(&lasat_map);
-
-	for (i=0; i < LASAT_MTD_LAST; i++)
-		partition_info[i].name = lasat_mtd_partnames[i];
-
-	lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
-
-	if (!lasat_mtd)
-	    lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
-
-	if (lasat_mtd) {
-		u32 size, offset = 0;
-
-		lasat_mtd->owner = THIS_MODULE;
-
-		for (i=0; i < LASAT_MTD_LAST; i++) {
-			size = lasat_flash_partition_size(i);
-			partition_info[i].size = size;
-			partition_info[i].offset = offset;
-			offset += size;
-		}
-
-		add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
-		return 0;
-	}
-
-	iounmap(lasat_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_lasat(void)
-{
-	if (lasat_mtd) {
-		del_mtd_partitions(lasat_mtd);
-		map_destroy(lasat_mtd);
-	}
-	if (lasat_map.virt) {
-		iounmap(lasat_map.virt);
-		lasat_map.virt = 0;
-	}
-}
-
-module_init(init_lasat);
-module_exit(cleanup_lasat);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
-MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver");
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 389fea2..14ffb1a 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/major.h>
-#include <linux/root_dev.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
@@ -89,10 +88,6 @@
 	uclinux_ram_mtdinfo = mtd;
 	add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS);
 
-	printk("uclinux[mtd]: set %s to be root filesystem\n",
-	     	uclinux_romfs[0].name);
-	ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
-
 	return(0);
 }
 
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 51bc7e2..ef89780 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -16,6 +16,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
+#include <linux/freezer.h>
 #include <linux/spinlock.h>
 #include <linux/hdreg.h>
 #include <linux/init.h>
@@ -80,7 +81,7 @@
 	struct request_queue *rq = tr->blkcore_priv->rq;
 
 	/* we might get involved when memory gets low, so use PF_MEMALLOC */
-	current->flags |= PF_MEMALLOC | PF_NOFREEZE;
+	current->flags |= PF_MEMALLOC;
 
 	spin_lock_irq(rq->queue_lock);
 	while (!kthread_should_stop()) {
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
new file mode 100644
index 0000000..aca3319
--- /dev/null
+++ b/drivers/mtd/mtdsuper.c
@@ -0,0 +1,232 @@
+/* MTD-based superblock management
+ *
+ * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
+ * Written by:  David Howells <dhowells@redhat.com>
+ *              David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/mtd/super.h>
+#include <linux/namei.h>
+#include <linux/ctype.h>
+
+/*
+ * compare superblocks to see if they're equivalent
+ * - they are if the underlying MTD device is the same
+ */
+static int get_sb_mtd_compare(struct super_block *sb, void *_mtd)
+{
+	struct mtd_info *mtd = _mtd;
+
+	if (sb->s_mtd == mtd) {
+		DEBUG(2, "MTDSB: Match on device %d (\"%s\")\n",
+		      mtd->index, mtd->name);
+		return 1;
+	}
+
+	DEBUG(2, "MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
+	      sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name);
+	return 0;
+}
+
+/*
+ * mark the superblock by the MTD device it is using
+ * - set the device number to be the correct MTD block device for pesuperstence
+ *   of NFS exports
+ */
+static int get_sb_mtd_set(struct super_block *sb, void *_mtd)
+{
+	struct mtd_info *mtd = _mtd;
+
+	sb->s_mtd = mtd;
+	sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
+	return 0;
+}
+
+/*
+ * get a superblock on an MTD-backed filesystem
+ */
+static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
+			  const char *dev_name, void *data,
+			  struct mtd_info *mtd,
+			  int (*fill_super)(struct super_block *, void *, int),
+			  struct vfsmount *mnt)
+{
+	struct super_block *sb;
+	int ret;
+
+	sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd);
+	if (IS_ERR(sb))
+		goto out_error;
+
+	if (sb->s_root)
+		goto already_mounted;
+
+	/* fresh new superblock */
+	DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n",
+	      mtd->index, mtd->name);
+
+	ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
+	if (ret < 0) {
+		up_write(&sb->s_umount);
+		deactivate_super(sb);
+		return ret;
+	}
+
+	/* go */
+	sb->s_flags |= MS_ACTIVE;
+	return simple_set_mnt(mnt, sb);
+
+	/* new mountpoint for an already mounted superblock */
+already_mounted:
+	DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n",
+	      mtd->index, mtd->name);
+	ret = simple_set_mnt(mnt, sb);
+	goto out_put;
+
+out_error:
+	ret = PTR_ERR(sb);
+out_put:
+	put_mtd_device(mtd);
+	return ret;
+}
+
+/*
+ * get a superblock on an MTD-backed filesystem by MTD device number
+ */
+static int get_sb_mtd_nr(struct file_system_type *fs_type, int flags,
+			 const char *dev_name, void *data, int mtdnr,
+			 int (*fill_super)(struct super_block *, void *, int),
+			 struct vfsmount *mnt)
+{
+	struct mtd_info *mtd;
+
+	mtd = get_mtd_device(NULL, mtdnr);
+	if (IS_ERR(mtd)) {
+		DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
+		return PTR_ERR(mtd);
+	}
+
+	return get_sb_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super,
+			      mnt);
+}
+
+/*
+ * set up an MTD-based superblock
+ */
+int get_sb_mtd(struct file_system_type *fs_type, int flags,
+	       const char *dev_name, void *data,
+	       int (*fill_super)(struct super_block *, void *, int),
+	       struct vfsmount *mnt)
+{
+	struct nameidata nd;
+	int mtdnr, ret;
+
+	if (!dev_name)
+		return -EINVAL;
+
+	DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name);
+
+	/* the preferred way of mounting in future; especially when
+	 * CONFIG_BLOCK=n - we specify the underlying MTD device by number or
+	 * by name, so that we don't require block device support to be present
+	 * in the kernel. */
+	if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
+		if (dev_name[3] == ':') {
+			struct mtd_info *mtd;
+
+			/* mount by MTD device name */
+			DEBUG(1, "MTDSB: mtd:%%s, name \"%s\"\n",
+			      dev_name + 4);
+
+			for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
+				mtd = get_mtd_device(NULL, mtdnr);
+				if (!IS_ERR(mtd)) {
+					if (!strcmp(mtd->name, dev_name + 4))
+						return get_sb_mtd_aux(
+							fs_type, flags,
+							dev_name, data, mtd,
+							fill_super, mnt);
+
+					put_mtd_device(mtd);
+				}
+			}
+
+			printk(KERN_NOTICE "MTD:"
+			       " MTD device with name \"%s\" not found.\n",
+			       dev_name + 4);
+
+		} else if (isdigit(dev_name[3])) {
+			/* mount by MTD device number name */
+			char *endptr;
+
+			mtdnr = simple_strtoul(dev_name + 3, &endptr, 0);
+			if (!*endptr) {
+				/* It was a valid number */
+				DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n",
+				      mtdnr);
+				return get_sb_mtd_nr(fs_type, flags,
+						     dev_name, data,
+						     mtdnr, fill_super, mnt);
+			}
+		}
+	}
+
+	/* try the old way - the hack where we allowed users to mount
+	 * /dev/mtdblock$(n) but didn't actually _use_ the blockdev
+	 */
+	ret = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
+
+	DEBUG(1, "MTDSB: path_lookup() returned %d, inode %p\n",
+	      ret, nd.dentry ? nd.dentry->d_inode : NULL);
+
+	if (ret)
+		return ret;
+
+	ret = -EINVAL;
+
+	if (!S_ISBLK(nd.dentry->d_inode->i_mode))
+		goto out;
+
+	if (nd.mnt->mnt_flags & MNT_NODEV) {
+		ret = -EACCES;
+		goto out;
+	}
+
+	if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR)
+		goto not_an_MTD_device;
+
+	mtdnr = iminor(nd.dentry->d_inode);
+	path_release(&nd);
+
+	return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super,
+			     mnt);
+
+not_an_MTD_device:
+	if (!(flags & MS_SILENT))
+		printk(KERN_NOTICE
+		       "MTD: Attempt to mount non-MTD device \"%s\"\n",
+		       dev_name);
+out:
+	path_release(&nd);
+	return ret;
+
+}
+
+EXPORT_SYMBOL_GPL(get_sb_mtd);
+
+/*
+ * destroy an MTD-based superblock
+ */
+void kill_mtd_super(struct super_block *sb)
+{
+	generic_shutdown_super(sb);
+	put_mtd_device(sb->s_mtd);
+	sb->s_mtd = NULL;
+}
+
+EXPORT_SYMBOL_GPL(kill_mtd_super);
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index fe94ae9a..e3744eb 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -101,7 +101,7 @@
 	struct nand_chip *chip = mtd->priv;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
-		void __iomem *addr
+		void __iomem *addr;
 		unsigned char bits;
 
 		addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 595208f..17c8680 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -59,7 +59,7 @@
 #elif defined(CONFIG_MOMENCO_OCELOT)
 	0x2f000000,
 	0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
 	0xff000000,
 #else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index eb7d4d4..082073a 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -81,7 +81,7 @@
  */
 static struct mtd_partition partition_info_hi[] = {
       { .name = "PPChameleon HI Nand Flash",
-	offset = 0,
+	.offset = 0,
 	.size = 128 * 1024 * 1024
       }
 };
@@ -424,9 +424,9 @@
 
 	/* Release iomaps */
 	this = (struct nand_chip *) &ppchameleon_mtd[1];
-	iounmap((void *) this->IO_ADDR_R;
+	iounmap((void *) this->IO_ADDR_R);
 	this = (struct nand_chip *) &ppchameleonevb_mtd[1];
-	iounmap((void *) this->IO_ADDR_R;
+	iounmap((void *) this->IO_ADDR_R);
 
 	/* Free the MTD device structure */
 	kfree (ppchameleon_mtd);
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 74002945..7c6b223 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -368,7 +368,7 @@
 	int err, pnum, scrub = 0, idx = vol_id2idx(ubi, vol_id);
 	struct ubi_vid_hdr *vid_hdr;
 	struct ubi_volume *vol = ubi->volumes[idx];
-	uint32_t crc, crc1;
+	uint32_t uninitialized_var(crc);
 
 	err = leb_read_lock(ubi, vol_id, lnum);
 	if (err)
@@ -451,7 +451,7 @@
 	}
 
 	if (check) {
-		crc1 = crc32(UBI_CRC32_INIT, buf, len);
+		uint32_t crc1 = crc32(UBI_CRC32_INIT, buf, len);
 		if (crc1 != crc) {
 			ubi_warn("CRC error: calculated %#08x, must be %#08x",
 				 crc1, crc);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 9ecaf77..ab2174a 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1346,6 +1346,7 @@
 	ubi_msg("background thread \"%s\" started, PID %d",
 		ubi->bgt_name, current->pid);
 
+	set_freezable();
 	for (;;) {
 		int err;
 
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index da1a22c..ab18343 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -990,7 +990,7 @@
 				if (skb != NULL) {
 					skb_reserve(skb, 2);	/* 16 byte alignment */
 					skb_put(skb,totlen);
-					eth_copy_and_sum(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen,0);
+					skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen);
 					skb->protocol = eth_type_trans(skb, dev);
 					netif_rx(skb);
 					dev->last_rx = jiffies;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index f26ca33..6deb20f 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -324,7 +324,7 @@
 	{"3c980C Python-T",
 	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3cSOHO100-TX Hurricane",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 	{"3c555 Laptop Hurricane",
 	 PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, },
 	{"3c556 Laptop Tornado",
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 0877fc3..e89ace1 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -333,9 +333,9 @@
 
                         skb_reserve (skb, 2);           /* 16 byte align */
                         skb_put (skb, len);             /* make room */
-                        eth_copy_and_sum(skb,
+                        skb_copy_to_linear_data(skb,
                                          (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
-                                         len, 0);
+                                         len);
                         skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
 			dev->last_rx = jiffies;
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index e8c9f278..e970e64 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -26,7 +26,6 @@
 
 	TODO:
 	* Test Tx checksumming thoroughly
-	* Implement dev->tx_timeout
 
 	Low priority TODO:
 	* Complete reset on PciErr
@@ -107,11 +106,6 @@
 
 #define PFX			DRV_NAME ": "
 
-#ifndef TRUE
-#define FALSE 0
-#define TRUE (!FALSE)
-#endif
-
 #define CP_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
 				 NETIF_MSG_PROBE 	| \
 				 NETIF_MSG_LINK)
@@ -435,20 +429,12 @@
 
 	spin_lock_irqsave(&cp->lock, flags);
 	cp->vlgrp = grp;
-	cp->cpcmd |= RxVlanOn;
-	cpw16(CpCmd, cp->cpcmd);
-	spin_unlock_irqrestore(&cp->lock, flags);
-}
+	if (grp)
+		cp->cpcmd |= RxVlanOn;
+	else
+		cp->cpcmd &= ~RxVlanOn;
 
-static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	cp->cpcmd &= ~RxVlanOn;
 	cpw16(CpCmd, cp->cpcmd);
-	vlan_group_set_device(cp->vlgrp, vid, NULL);
 	spin_unlock_irqrestore(&cp->lock, flags);
 }
 #endif /* CP_VLAN_TAG_USED */
@@ -669,7 +655,7 @@
 	if (status & (TxOK | TxErr | TxEmpty | SWInt))
 		cp_tx(cp);
 	if (status & LinkChg)
-		mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+		mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
 
 	spin_unlock(&cp->lock);
 
@@ -1196,7 +1182,7 @@
 		goto err_out_hw;
 
 	netif_carrier_off(dev);
-	mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
+	mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
 	netif_start_queue(dev);
 
 	return 0;
@@ -1231,6 +1217,30 @@
 	return 0;
 }
 
+static void cp_tx_timeout(struct net_device *dev)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
+	int rc;
+
+	printk(KERN_WARNING "%s: Transmit timeout, status %2x %4x %4x %4x\n",
+	       dev->name, cpr8(Cmd), cpr16(CpCmd),
+	       cpr16(IntrStatus), cpr16(IntrMask));
+
+	spin_lock_irqsave(&cp->lock, flags);
+
+	cp_stop_hw(cp);
+	cp_clean_rings(cp);
+	rc = cp_init_rings(cp);
+	cp_start_hw(cp);
+
+	netif_wake_queue(dev);
+
+	spin_unlock_irqrestore(&cp->lock, flags);
+
+	return;
+}
+
 #ifdef BROKEN
 static int cp_change_mtu(struct net_device *dev, int new_mtu)
 {
@@ -1812,7 +1822,6 @@
 	void __iomem *regs;
 	resource_size_t pciaddr;
 	unsigned int addr_len, i, pci_using_dac;
-	u8 pci_rev;
 
 #ifndef MODULE
 	static int version_printed;
@@ -1820,13 +1829,11 @@
 		printk("%s", version);
 #endif
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
 	if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
-	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) {
+	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) {
 		dev_err(&pdev->dev,
 			   "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
-		           pdev->vendor, pdev->device, pci_rev);
+		           pdev->vendor, pdev->device, pdev->revision);
 		dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
 		return -ENODEV;
 	}
@@ -1936,15 +1943,12 @@
 	dev->change_mtu = cp_change_mtu;
 #endif
 	dev->ethtool_ops = &cp_ethtool_ops;
-#if 0
 	dev->tx_timeout = cp_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
-#endif
 
 #if CP_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = cp_vlan_rx_register;
-	dev->vlan_rx_kill_vid = cp_vlan_rx_kill_vid;
 #endif
 
 	if (pci_using_dac)
@@ -2059,7 +2063,7 @@
 
 	spin_lock_irqsave (&cp->lock, flags);
 
-	mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+	mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
 
 	spin_unlock_irqrestore (&cp->lock, flags);
 
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index a844b1f..327eaa7 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -931,7 +931,6 @@
 	int i, addr_len, option;
 	void __iomem *ioaddr;
 	static int board_idx = -1;
-	u8 pci_rev;
 
 	assert (pdev != NULL);
 	assert (ent != NULL);
@@ -949,13 +948,11 @@
 	}
 #endif
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
 	if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
-	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) {
+	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) {
 		dev_info(&pdev->dev,
 			   "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
-		       	   pdev->vendor, pdev->device, pci_rev);
+		       	   pdev->vendor, pdev->device, pdev->revision);
 		dev_info(&pdev->dev,
 			   "Use the \"8139cp\" driver for improved performance and stability.\n");
 	}
@@ -2017,7 +2014,7 @@
 #if RX_BUF_IDX == 3
 			wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
 #else
-			eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+			skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
 #endif
 			skb_put (skb, pkt_size);
 
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 414de5b..04ddec0 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -73,6 +73,9 @@
 	u32 *reg_offset;		/* Register mapping table */
 	spinlock_t page_lock;		/* Page register locks */
 	unsigned long priv;		/* Private field to store bus IDs etc. */
+#ifdef AX88796_PLATFORM
+	unsigned char rxcr_base;	/* default value for RXCR */
+#endif
 };
 
 /* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -86,11 +89,19 @@
 /* Some generic ethernet register configurations. */
 #define E8390_TX_IRQ_MASK	0xa	/* For register EN0_ISR */
 #define E8390_RX_IRQ_MASK	0x5
+
+#ifdef AX88796_PLATFORM
+#define E8390_RXCONFIG		(ei_status.rxcr_base | 0x04)
+#define E8390_RXOFF		(ei_status.rxcr_base | 0x20)
+#else
 #define E8390_RXCONFIG		0x4	/* EN0_RXCR: broadcasts, no multicast,errors */
 #define E8390_RXOFF		0x20	/* EN0_RXCR: Accept no packets */
+#endif
+
 #define E8390_TXCONFIG		0x00	/* EN0_TXCR: Normal transmit mode */
 #define E8390_TXOFF		0x02	/* EN0_TXCR: Transmitter off */
 
+
 /*  Register accessed at EN_CMD, the 8390 base addr.  */
 #define E8390_STOP	0x01	/* Stop and reset the chip */
 #define E8390_START	0x02	/* Start the chip, clear reset */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c5baa19..43d0317 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3,10 +3,7 @@
 # Network device configuration
 #
 
-menu "Network device support"
-	depends on NET
-
-config NETDEVICES
+menuconfig NETDEVICES
 	default y if UML
 	bool "Network device support"
 	---help---
@@ -28,6 +25,14 @@
 # that for each of the symbols.
 if NETDEVICES
 
+config NETDEVICES_MULTIQUEUE
+	bool "Netdevice multiple hardware queue support"
+	---help---
+	  Say Y here if you want to allow the network stack to use multiple
+	  hardware TX queues on an ethernet device.
+
+	  Most people will say N here.
+
 config IFB
 	tristate "Intermediate Functional Block support"
 	depends on NET_CLS_ACT
@@ -77,6 +82,16 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called bonding.
 
+config MACVLAN
+	tristate "MAC-VLAN support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	---help---
+	  This allows one to create virtual interfaces that map packets to
+	  or from specific MAC addresses to a particular interface.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called macvlan.
+
 config EQUALIZER
 	tristate "EQL (serial line load balancing) support"
 	---help---
@@ -151,11 +166,9 @@
 #	Ethernet
 #
 
-menu "Ethernet (10 or 100Mbit)"
-	depends on !UML
-
-config NET_ETHERNET
+menuconfig NET_ETHERNET
 	bool "Ethernet (10 or 100Mbit)"
+	depends on !UML
 	---help---
 	  Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
 	  type of Local Area Network (LAN) in universities and companies.
@@ -180,9 +193,10 @@
 	  kernel: saying N will just cause the configurator to skip all
 	  the questions about Ethernet network cards. If unsure, say N.
 
+if NET_ETHERNET
+
 config MII
 	tristate "Generic Media Independent Interface device support"
-	depends on NET_ETHERNET
 	help
 	  Most ethernet controllers have MII transceiver either as an external
 	  or internal device.  It is safe to say Y or M here even if your
@@ -190,8 +204,8 @@
 
 config MACB
 	tristate "Atmel MACB support"
-	depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263)
-	select MII
+	depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
+	select PHYLIB
 	help
 	  The Atmel MACB ethernet interface is found on many AT32 and AT91
 	  parts. Say Y to include support for the MACB chip.
@@ -201,9 +215,18 @@
 
 source "drivers/net/arm/Kconfig"
 
+config AX88796
+	tristate "ASIX AX88796 NE2000 clone support"
+	depends on ARM || MIPS
+	select CRC32
+	select MII
+	help
+	  AX88796 driver, using platform bus to provide
+	  chip detection and resources
+
 config MACE
 	tristate "MACE (Power Mac ethernet) support"
-	depends on NET_ETHERNET && PPC_PMAC && PPC32
+	depends on PPC_PMAC && PPC32
 	select CRC32
 	help
 	  Power Macintoshes and clones with Ethernet built-in on the
@@ -226,7 +249,7 @@
 
 config BMAC
 	tristate "BMAC (G3 ethernet) support"
-	depends on NET_ETHERNET && PPC_PMAC && PPC32
+	depends on PPC_PMAC && PPC32
 	select CRC32
 	help
 	  Say Y for support of BMAC Ethernet interfaces. These are used on G3
@@ -237,7 +260,7 @@
 
 config ARIADNE
 	tristate "Ariadne support"
-	depends on NET_ETHERNET && ZORRO
+	depends on ZORRO
 	help
 	  If you have a Village Tronic Ariadne Ethernet adapter, say Y.
 	  Otherwise, say N.
@@ -247,7 +270,7 @@
 
 config A2065
 	tristate "A2065 support"
-	depends on NET_ETHERNET && ZORRO
+	depends on ZORRO
 	select CRC32
 	help
 	  If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
@@ -258,7 +281,7 @@
 
 config HYDRA
 	tristate "Hydra support"
-	depends on NET_ETHERNET && ZORRO
+	depends on ZORRO
 	select CRC32
 	help
 	  If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
@@ -268,7 +291,7 @@
 
 config ZORRO8390
 	tristate "Zorro NS8390-based Ethernet support"
-	depends on NET_ETHERNET && ZORRO
+	depends on ZORRO
 	select CRC32
 	help
 	  This driver is for Zorro Ethernet cards using an NS8390-compatible
@@ -281,7 +304,7 @@
 
 config APNE
 	tristate "PCMCIA NE2000 support"
-	depends on NET_ETHERNET && AMIGA_PCMCIA
+	depends on AMIGA_PCMCIA
 	select CRC32
 	help
 	  If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
@@ -292,7 +315,7 @@
 
 config APOLLO_ELPLUS
 	tristate "Apollo 3c505 support"
-	depends on NET_ETHERNET && APOLLO
+	depends on APOLLO
 	help
 	  Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
 	  If you don't have one made for Apollos, you can use one from a PC,
@@ -301,7 +324,7 @@
 
 config MAC8390
 	bool "Macintosh NS 8390 based ethernet cards"
-	depends on NET_ETHERNET && MAC
+	depends on MAC
 	select CRC32
 	help
 	  If you want to include a driver to support Nubus or LC-PDS
@@ -311,7 +334,7 @@
 
 config MAC89x0
 	tristate "Macintosh CS89x0 based ethernet cards"
-	depends on NET_ETHERNET && MAC
+	depends on MAC
 	---help---
 	  Support for CS89x0 chipset based Ethernet cards.  If you have a
 	  Nubus or LC-PDS network (Ethernet) card of this type, say Y and
@@ -324,7 +347,7 @@
 
 config MACSONIC
 	tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
-	depends on NET_ETHERNET && MAC
+	depends on MAC
 	---help---
 	  Support for NatSemi SONIC based Ethernet devices.  This includes
 	  the onboard Ethernet in many Quadras as well as some LC-PDS,
@@ -338,7 +361,7 @@
 
 config MACMACE
 	bool "Macintosh (AV) onboard MACE ethernet"
-	depends on NET_ETHERNET && MAC
+	depends on MAC
 	select CRC32
 	help
 	  Support for the onboard AMD 79C940 MACE Ethernet controller used in
@@ -348,7 +371,7 @@
 
 config MVME147_NET
 	tristate "MVME147 (Lance) Ethernet support"
-	depends on NET_ETHERNET && MVME147
+	depends on MVME147
 	select CRC32
 	help
 	  Support for the on-board Ethernet interface on the Motorola MVME147
@@ -358,7 +381,7 @@
 
 config MVME16x_NET
 	tristate "MVME16x Ethernet support"
-	depends on NET_ETHERNET && MVME16x
+	depends on MVME16x
 	help
 	  This is the driver for the Ethernet interface on the Motorola
 	  MVME162, 166, 167, 172 and 177 boards.  Say Y here to include the
@@ -367,7 +390,7 @@
 
 config BVME6000_NET
 	tristate "BVME6000 Ethernet support"
-	depends on NET_ETHERNET && BVME6000
+	depends on BVME6000
 	help
 	  This is the driver for the Ethernet interface on BVME4000 and
 	  BVME6000 VME boards.  Say Y here to include the driver for this chip
@@ -376,31 +399,15 @@
 
 config ATARILANCE
 	tristate "Atari Lance support"
-	depends on NET_ETHERNET && ATARI
+	depends on ATARI
 	help
 	  Say Y to include support for several Atari Ethernet adapters based
 	  on the AMD Lance chipset: RieblCard (with or without battery), or
 	  PAMCard VME (also the version by Rhotron, with different addresses).
 
-config ATARI_BIONET
-	tristate "BioNet-100 support"
-	depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
-	help
-	  Say Y to include support for BioData's BioNet-100 Ethernet adapter
-	  for the ACSI port. The driver works (has to work...) with a polled
-	  I/O scheme, so it's rather slow :-(
-
-config ATARI_PAMSNET
-	tristate "PAMsNet support"
-	depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
-	help
-	  Say Y to include support for the PAMsNet Ethernet adapter for the
-	  ACSI port ("ACSI node"). The driver works (has to work...) with a
-	  polled I/O scheme, so it's rather slow :-(
-
 config SUN3LANCE
 	tristate "Sun3/Sun3x on-board LANCE support"
-	depends on NET_ETHERNET && (SUN3 || SUN3X)
+	depends on SUN3 || SUN3X
 	help
 	  Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
 	  featured an AMD Lance 10Mbit Ethernet controller on board; say Y
@@ -413,7 +420,7 @@
 
 config SUN3_82586
 	bool "Sun3 on-board Intel 82586 support"
-	depends on NET_ETHERNET && SUN3
+	depends on SUN3
 	help
 	  This driver enables support for the on-board Intel 82586 based
 	  Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards.  Note
@@ -422,7 +429,7 @@
 
 config HPLANCE
 	bool "HP on-board LANCE support"
-	depends on NET_ETHERNET && DIO
+	depends on DIO
 	select CRC32
 	help
 	  If you want to use the builtin "LANCE" Ethernet controller on an
@@ -430,21 +437,28 @@
 
 config LASI_82596
 	tristate "Lasi ethernet"
-	depends on NET_ETHERNET && GSC
+	depends on GSC
 	help
 	  Say Y here to support the builtin Intel 82596 ethernet controller
 	  found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
 
+config SNI_82596
+	tristate "SNI RM ethernet"
+	depends on NET_ETHERNET && SNI_RM
+	help
+	  Say Y here to support the on-board Intel 82596 ethernet controller
+	  built into SNI RM machines.
+
 config MIPS_JAZZ_SONIC
 	tristate "MIPS JAZZ onboard SONIC Ethernet support"
-	depends on NET_ETHERNET && MACH_JAZZ
+	depends on MACH_JAZZ
 	help
 	  This is the driver for the onboard card of MIPS Magnum 4000,
 	  Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
 
 config MIPS_AU1X00_ENET
 	bool "MIPS AU1000 Ethernet support"
-	depends on NET_ETHERNET && SOC_AU1X00
+	depends on SOC_AU1X00
 	select PHYLIB
 	select CRC32
 	help
@@ -453,11 +467,11 @@
 
 config NET_SB1250_MAC
 	tristate "SB1250 Ethernet support"
-	depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC
+	depends on SIBYTE_SB1xxx_SOC
 
 config SGI_IOC3_ETH
 	bool "SGI IOC3 Ethernet"
-	depends on NET_ETHERNET && PCI && SGI_IP27
+	depends on PCI && SGI_IP27
 	select CRC32
 	select MII
 	help
@@ -487,7 +501,7 @@
 
 config MIPS_SIM_NET
 	tristate "MIPS simulator Network device"
-	depends on NET_ETHERNET && MIPS_SIM
+	depends on MIPS_SIM
 	help
 	  The MIPSNET device is a simple Ethernet network device which is
 	  emulated by the MIPS Simulator.
@@ -495,11 +509,11 @@
 
 config SGI_O2MACE_ETH
 	tristate "SGI O2 MACE Fast Ethernet support"
-	depends on NET_ETHERNET && SGI_IP32=y
+	depends on SGI_IP32=y
 
 config STNIC
 	tristate "National DP83902AV  support"
-	depends on NET_ETHERNET && SUPERH
+	depends on SUPERH
 	select CRC32
 	help
 	  Support for cards based on the National Semiconductor DP83902AV
@@ -511,7 +525,7 @@
 
 config SUNLANCE
 	tristate "Sun LANCE support"
-	depends on NET_ETHERNET && SBUS
+	depends on SBUS
 	select CRC32
 	help
 	  This driver supports the "le" interface present on all 32-bit Sparc
@@ -524,7 +538,7 @@
 
 config HAPPYMEAL
 	tristate "Sun Happy Meal 10/100baseT support"
-	depends on NET_ETHERNET && (SBUS || PCI)
+	depends on SBUS || PCI
 	select CRC32
 	help
 	  This driver supports the "hme" interface present on most Ultra
@@ -537,7 +551,7 @@
 
 config SUNBMAC
 	tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
-	depends on NET_ETHERNET && SBUS && EXPERIMENTAL
+	depends on SBUS && EXPERIMENTAL
 	select CRC32
 	help
 	  This driver supports the "be" interface available as an Sbus option.
@@ -548,7 +562,7 @@
 
 config SUNQE
 	tristate "Sun QuadEthernet support"
-	depends on NET_ETHERNET && SBUS
+	depends on SBUS
 	select CRC32
 	help
 	  This driver supports the "qe" 10baseT Ethernet device, available as
@@ -560,7 +574,7 @@
 
 config SUNGEM
 	tristate "Sun GEM support"
-	depends on NET_ETHERNET && PCI
+	depends on PCI
 	select CRC32
 	help
 	  Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0.  See also
@@ -568,15 +582,21 @@
 
 config CASSINI
 	tristate "Sun Cassini support"
-	depends on NET_ETHERNET && PCI
+	depends on PCI
 	select CRC32
 	help
 	  Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
 	  <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
 
+config SUNVNET
+	tristate "Sun Virtual Network support"
+	depends on SUN_LDOMS
+	help
+	  Support for virtual network devices under Sun Logical Domains.
+
 config NET_VENDOR_3COM
 	bool "3COM cards"
-	depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
+	depends on ISA || EISA || MCA || PCI
 	help
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -736,7 +756,7 @@
 
 config LANCE
 	tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
-	depends on NET_ETHERNET && ISA && ISA_DMA_API
+	depends on ISA && ISA_DMA_API
 	help
 	  If you have a network (Ethernet) card of this type, say Y and read
 	  the Ethernet-HOWTO, available from
@@ -748,7 +768,7 @@
 
 config NET_VENDOR_SMC
 	bool "Western Digital/SMC cards"
-	depends on NET_ETHERNET && (ISA || MCA || EISA || MAC)
+	depends on ISA || MCA || EISA || MAC
 	help
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -818,24 +838,6 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called smc-ultra32.
 
-config SMC91X
-	tristate "SMC 91C9x/91C1xxx support"
-	select CRC32
-	select MII
-	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN)
-	help
-	  This is a driver for SMC's 91x series of Ethernet chipsets,
-	  including the SMC91C94 and the SMC91C111. Say Y if you want it
-	  compiled into the kernel, and read the file
-	  <file:Documentation/networking/smc9.txt>  and the Ethernet-HOWTO,
-	  available from  <http://www.linuxdoc.org/docs.html#howto>.
-
-	  This driver is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called smc91x.  If you want to compile it as a
-	  module, say M here and read <file:Documentation/kbuild/modules.txt>
-	  as well as <file:Documentation/networking/net-modules.txt>.
-
 config SMC9194
 	tristate "SMC 9194 support"
 	depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
@@ -852,10 +854,28 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called smc9194.
 
+config SMC91X
+	tristate "SMC 91C9x/91C1xxx support"
+	select CRC32
+	select MII
+	depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN
+	help
+	  This is a driver for SMC's 91x series of Ethernet chipsets,
+	  including the SMC91C94 and the SMC91C111. Say Y if you want it
+	  compiled into the kernel, and read the file
+	  <file:Documentation/networking/smc9.txt>  and the Ethernet-HOWTO,
+	  available from  <http://www.linuxdoc.org/docs.html#howto>.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called smc91x.  If you want to compile it as a
+	  module, say M here and read <file:Documentation/kbuild/modules.txt>
+	  as well as <file:Documentation/networking/net-modules.txt>.
+
 config NET_NETX
 	tristate "NetX Ethernet support"
 	select MII
-	depends on NET_ETHERNET && ARCH_NETX
+	depends on ARCH_NETX
 	help
 	  This is support for the Hilscher netX builtin Ethernet ports
 
@@ -865,7 +885,7 @@
 
 config DM9000
 	tristate "DM9000 support"
-	depends on (ARM || MIPS) && NET_ETHERNET
+	depends on ARM || BLACKFIN || MIPS
 	select CRC32
 	select MII
 	---help---
@@ -879,7 +899,7 @@
 	tristate "SMSC LAN911[5678] support"
 	select CRC32
 	select MII
-	depends on NET_ETHERNET && ARCH_PXA
+	depends on ARCH_PXA
 	help
 	  This is a driver for SMSC's LAN911x series of Ethernet chipsets
 	  including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -893,7 +913,7 @@
 
 config NET_VENDOR_RACAL
 	bool "Racal-Interlan (Micom) NI cards"
-	depends on NET_ETHERNET && ISA
+	depends on ISA
 	help
 	  If you have a network (Ethernet) card belonging to this class, such
 	  as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
@@ -945,7 +965,7 @@
 
 config AT1700
 	tristate "AT1700/1720 support (EXPERIMENTAL)"
-	depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL
+	depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -958,7 +978,7 @@
 
 config DEPCA
 	tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
-	depends on NET_ETHERNET && (ISA || EISA || MCA)
+	depends on ISA || EISA || MCA
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -972,7 +992,7 @@
 
 config HP100
 	tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
-	depends on NET_ETHERNET && (ISA || EISA || PCI)
+	depends on ISA || EISA || PCI
 	help
 	  If you have a network (Ethernet) card of this type, say Y and read
 	  the Ethernet-HOWTO, available from
@@ -984,7 +1004,7 @@
 
 config NET_ISA
 	bool "Other ISA cards"
-	depends on NET_ETHERNET && ISA
+	depends on ISA
 	---help---
 	  If your network (Ethernet) card hasn't been mentioned yet and its
 	  bus system (that's the way the cards talks to the other components
@@ -1147,7 +1167,7 @@
 
 config NE2_MCA
 	tristate "NE/2 (ne2000 MCA version) support"
-	depends on NET_ETHERNET && MCA_LEGACY
+	depends on MCA_LEGACY
 	select CRC32
 	help
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -1160,7 +1180,7 @@
 
 config IBMLANA
 	tristate "IBM LAN Adapter/A support"
-	depends on NET_ETHERNET && MCA && MCA_LEGACY
+	depends on MCA && MCA_LEGACY
 	---help---
 	  This is a Micro Channel Ethernet adapter.  You need to set
 	  CONFIG_MCA to use this driver.  It is both available as an in-kernel
@@ -1176,7 +1196,7 @@
 
 config IBMVETH
 	tristate "IBM LAN Virtual Ethernet support"
-	depends on NET_ETHERNET && PPC_PSERIES
+	depends on PPC_PSERIES
 	---help---
 	  This driver supports virtual ethernet adapters on newer IBM iSeries
 	  and pSeries systems.
@@ -1187,7 +1207,7 @@
 
 config IBM_EMAC
 	tristate "PowerPC 4xx on-chip Ethernet support"
-	depends on 4xx
+	depends on 4xx && !PPC_MERGE
 	help
 	  This driver supports the PowerPC 4xx EMAC family of on-chip
           Ethernet controllers.
@@ -1257,7 +1277,7 @@
 
 config NET_PCI
 	bool "EISA, VLB, PCI and on board controllers"
-	depends on NET_ETHERNET && (ISA || EISA || PCI)
+	depends on ISA || EISA || PCI
 	help
 	  This is another class of network cards which attach directly to the
 	  bus. If you have one of those, say Y and read the Ethernet-HOWTO,
@@ -1313,6 +1333,7 @@
 	  To compile this driver as a module, choose M here and read
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called amd8111e.
+
 config AMD8111E_NAPI
 	bool "Enable NAPI support"
 	depends on AMD8111_ETH
@@ -1778,7 +1799,7 @@
 
 config NET_POCKET
 	bool "Pocket and portable adapters"
-	depends on NET_ETHERNET && PARPORT
+	depends on PARPORT
 	---help---
 	  Cute little network (Ethernet) devices which attach to the parallel
 	  port ("pocket adapters"), commonly used with laptops. If you have
@@ -1847,14 +1868,14 @@
 
 config SGISEEQ
 	tristate "SGI Seeq ethernet controller support"
-	depends on NET_ETHERNET && SGI_IP22
+	depends on SGI_IP22
 	help
 	  Say Y here if you have an Seeq based Ethernet network card. This is
 	  used in many Silicon Graphics machines.
 
 config DECLANCE
 	tristate "DEC LANCE ethernet controller support"
-	depends on NET_ETHERNET && MACH_DECSTATION
+	depends on MACH_DECSTATION
 	select CRC32
 	help
 	  This driver is for the series of Ethernet controllers produced by
@@ -1884,7 +1905,7 @@
 
 config NE_H8300
 	tristate "NE2000 compatible support for H8/300"
-	depends on H8300 && NET_ETHERNET
+	depends on H8300
 	help
 	  Say Y here if you want to use the NE2000 compatible
 	  controller on the Renesas H8/300 processor.
@@ -1892,7 +1913,7 @@
 source "drivers/net/fec_8xx/Kconfig"
 source "drivers/net/fs_enet/Kconfig"
 
-endmenu
+endif # NET_ETHERNET
 
 #
 #	Gigabit Ethernet
@@ -2101,7 +2122,7 @@
 	  with better performance and more complete ethtool support.
 
 	  It does not support the link failover and network management 
-	  features that "portable" vendor supplied sk98lin driver does.
+	  features available in the hardware.
 
 	  This driver supports adapters based on the original Yukon chipset:
 	  Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
@@ -2114,7 +2135,7 @@
 	  will be called skge.  This is recommended.
 
 config SKY2
-	tristate "SysKonnect Yukon2 support (EXPERIMENTAL)"
+	tristate "SysKonnect Yukon2 support"
 	depends on PCI
 	select CRC32
 	---help---
@@ -2129,96 +2150,19 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called sky2.  This is recommended.
 
-config SK98LIN
-	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
-	depends on PCI
-	---help---
-	  Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
-	  compliant Gigabit Ethernet Adapter.
+config SKY2_DEBUG
+       bool "Debugging interface"
+       depends on SKY2 && DEBUG_FS
+       help
+	 This option adds the ability to dump driver state for debugging.
+	 The file debugfs/sky2/ethX displays the state of the internal
+	 transmit and receive rings.
 
-	  This driver supports the original Yukon chipset. This driver is
-	  deprecated and will be removed from the kernel in the near future,
-	  it has been replaced by the skge driver. skge is cleaner and
-	  seems to work better.
-
-	  This driver does not support the newer Yukon2 chipset. A separate
-	  driver, sky2, is provided to support Yukon2-based adapters.
-
-	  The following adapters are supported by this driver:
-	    - 3Com 3C940 Gigabit LOM Ethernet Adapter
-	    - 3Com 3C941 Gigabit LOM Ethernet Adapter
-	    - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
-	    - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
-	    - EG1032 v2 Instant Gigabit Network Adapter
-	    - EG1064 v2 Instant Gigabit Network Adapter
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
-	    - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
-	    - Marvell RDK-8001 Adapter
-	    - Marvell RDK-8002 Adapter
-	    - Marvell RDK-8003 Adapter
-	    - Marvell RDK-8004 Adapter
-	    - Marvell RDK-8006 Adapter
-	    - Marvell RDK-8007 Adapter
-	    - Marvell RDK-8008 Adapter
-	    - Marvell RDK-8009 Adapter
-	    - Marvell RDK-8010 Adapter
-	    - Marvell RDK-8011 Adapter
-	    - Marvell RDK-8012 Adapter
-	    - Marvell RDK-8052 Adapter
-	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
-	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
-	    - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
-	    - SK-9521 10/100/1000Base-T Adapter
-	    - SK-9521 V2.0 10/100/1000Base-T Adapter
-	    - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
-	    - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
-	    - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
-	    - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
-	    - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
-	    - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
-	    - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
-	    - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
-	    - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
-	    - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
-	    - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
-	    - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
-	    - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
-	    - SMC EZ Card 1000 (SMC9452TXV.2)
-	  
-	  The adapters support Jumbo Frames.
-	  The dual link adapters support link-failover and dual port features.
-	  Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support 
-	  the scatter-gather functionality with sendfile(). Please refer to 
-	  <file:Documentation/networking/sk98lin.txt> for more information about
-	  optional driver parameters.
-	  Questions concerning this driver may be addressed to:
-	      <linux@syskonnect.de>
-	  
-	  If you want to compile this driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/kbuild/modules.txt>. The module will
-	  be called sk98lin. This is recommended.
+	 If unsure, say N.
 
 config VIA_VELOCITY
 	tristate "VIA Velocity support"
-	depends on NET_PCI && PCI
+	depends on PCI
 	select CRC32
 	select CRC_CCITT
 	select MII
@@ -2264,6 +2208,16 @@
 	     To compile this driver as a module, choose M here: the module
 	     will be called tsi108_eth.
 
+config GELIC_NET
+	tristate "PS3 Gigabit Ethernet driver"
+	depends on PPC_PS3
+	help
+	  This driver supports the network device on the PS3 game
+	  console.  This driver has built-in support for Ethernet.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ps3_gelic.
+
 config GIANFAR
 	tristate "Gianfar Ethernet"
 	depends on 85xx || 83xx || PPC_86xx
@@ -2280,7 +2234,7 @@
 config UCC_GETH
 	tristate "Freescale QE Gigabit Ethernet"
 	depends on QUICC_ENGINE
-	select UCC_FAST
+	select PHYLIB
 	help
 	  This driver supports the Gigabit Ethernet mode of the QUICC Engine,
 	  which is available on some Freescale SOCs.
@@ -2303,7 +2257,7 @@
 
 config MV643XX_ETH
 	tristate "MV-643XX Ethernet support"
-	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32)
+	depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32)
 	select MII
 	help
 	  This driver supports the gigabit Ethernet on the Marvell MV643XX
@@ -2838,6 +2792,19 @@
 	  which can lead to bad results if the ATM peer loses state and
 	  changes its encapsulation unilaterally.
 
+config PPPOL2TP
+	tristate "PPP over L2TP (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && PPP
+	help
+	  Support for PPP-over-L2TP socket family. L2TP is a protocol
+	  used by ISPs and enterprises to tunnel PPP traffic over UDP
+	  tunnels. L2TP is replacing PPTP for VPN uses.
+
+	  This kernel component handles only L2TP data packets: a
+	  userland daemon handles L2TP the control protocol (tunnel
+	  and session setup). One such daemon is OpenL2TP
+	  (http://openl2tp.sourceforge.net/).
+
 config SLIP
 	tristate "SLIP (serial line) support"
 	---help---
@@ -2948,8 +2915,6 @@
 	If you want to log kernel messages over the network, enable this.
 	See <file:Documentation/networking/netconsole.txt> for details.
 
-endif #NETDEVICES
-
 config NETPOLL
 	def_bool NETCONSOLE
 
@@ -2961,4 +2926,4 @@
 config NET_POLL_CONTROLLER
 	def_bool NETPOLL
 
-endmenu
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a77affa..eb41676 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -34,6 +34,7 @@
 obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
 obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
 obj-$(CONFIG_CASSINI) += cassini.o
+obj-$(CONFIG_SUNVNET) += sunvnet.o
 
 obj-$(CONFIG_MACE) += mace.o
 obj-$(CONFIG_BMAC) += bmac.o
@@ -60,10 +61,11 @@
 obj-$(CONFIG_BNX2) += bnx2.o
 spidernet-y += spider_net.o spider_net_ethtool.o
 obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
+obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
+ps3_gelic-objs += ps3_gelic_net.o
 obj-$(CONFIG_TC35815) += tc35815.o
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
-obj-$(CONFIG_SK98LIN) += sk98lin/
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
@@ -107,6 +109,7 @@
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o
+obj-$(CONFIG_AX88796) += ax88796.o
 
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
@@ -119,12 +122,14 @@
 obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
 obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
 obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
+obj-$(CONFIG_PPPOL2TP) += pppox.o pppol2tp.o
 
 obj-$(CONFIG_SLIP) += slip.o
 obj-$(CONFIG_SLHC) += slhc.o
 
 obj-$(CONFIG_DUMMY) += dummy.o
 obj-$(CONFIG_IFB) += ifb.o
+obj-$(CONFIG_MACVLAN) += macvlan.o
 obj-$(CONFIG_DE600) += de600.o
 obj-$(CONFIG_DE620) += de620.o
 obj-$(CONFIG_LANCE) += lance.o
@@ -157,6 +162,7 @@
 obj-$(CONFIG_AC3200) += ac3200.o 8390.o
 obj-$(CONFIG_APRICOT) += 82596.o
 obj-$(CONFIG_LASI_82596) += lasi_82596.o
+obj-$(CONFIG_SNI_82596) += sni_82596.o
 obj-$(CONFIG_MVME16x_NET) += 82596.o
 obj-$(CONFIG_BVME6000_NET) += 82596.o
 obj-$(CONFIG_SC92031) += sc92031.o
@@ -175,8 +181,6 @@
 obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
-obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
-obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o
 obj-$(CONFIG_A2065) += a2065.o
 obj-$(CONFIG_HYDRA) += hydra.o
 obj-$(CONFIG_ARIADNE) += ariadne.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 1c3e293..3b79c6c 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -75,8 +75,6 @@
 extern struct net_device *sun3lance_probe(int unit);
 extern struct net_device *sun3_82586_probe(int unit);
 extern struct net_device *apne_probe(int unit);
-extern struct net_device *bionet_probe(int unit);
-extern struct net_device *pamsnet_probe(int unit);
 extern struct net_device *cs89x0_probe(int unit);
 extern struct net_device *hplance_probe(int unit);
 extern struct net_device *bagetlance_probe(int unit);
@@ -264,12 +262,6 @@
 #ifdef CONFIG_APNE		/* A1200 PCMCIA NE2000 */
 	{apne_probe, 0},
 #endif
-#ifdef CONFIG_ATARI_BIONET	/* Atari Bionet Ethernet board */
-	{bionet_probe, 0},
-#endif
-#ifdef CONFIG_ATARI_PAMSNET	/* Atari PAMsNet Ethernet board */
-	{pamsnet_probe, 0},
-#endif
 #ifdef CONFIG_MVME147_NET	/* MVME147 internal Ethernet */
 	{mvme147lance_probe, 0},
 #endif
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 81d5a37..a45de69 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -322,9 +322,9 @@
 
 			skb_reserve (skb, 2);		/* 16 byte align */
 			skb_put (skb, len);		/* make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 					 (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
-					 len, 0);
+					 len);
 			skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
 			dev->last_rx = jiffies;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 7122b7b..b78a4e5 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -159,10 +159,6 @@
 };
 MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
 
-#ifndef SET_NETDEV_DEV
-#define SET_NETDEV_DEV(net, pdev)	do{} while(0)
-#endif
-
 #define ace_sync_irq(irq)	synchronize_irq(irq)
 
 #ifndef offset_in_page
@@ -480,12 +476,10 @@
 #if ACENIC_DO_VLAN
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = ace_vlan_rx_register;
-	dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid;
 #endif
-	if (1) {
-		dev->tx_timeout = &ace_watchdog;
-		dev->watchdog_timeo = 5*HZ;
-	}
+
+	dev->tx_timeout = &ace_watchdog;
+	dev->watchdog_timeo = 5*HZ;
 
 	dev->open = &ace_open;
 	dev->stop = &ace_close;
@@ -2283,19 +2277,6 @@
 	ace_unmask_irq(dev);
 	local_irq_restore(flags);
 }
-
-
-static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	unsigned long flags;
-
-	local_irq_save(flags);
-	ace_mask_irq(dev);
-	vlan_group_set_device(ap->vlgrp, vid, NULL);
-	ace_unmask_irq(dev);
-	local_irq_restore(flags);
-}
 #endif /* ACENIC_DO_VLAN */
 
 
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index 8ca8534..60ed183 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -787,7 +787,6 @@
 static int read_eeprom_byte(struct net_device *dev, unsigned long offset);
 #if ACENIC_DO_VLAN
 static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp);
-static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
 #endif
 
 #endif /* _ACENIC_H_ */
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 675fe91..a61b2f8 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -155,7 +155,7 @@
 */
 static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val)
 {
-	unsigned int repeat = REPEAT_CNT
+	unsigned int repeat = REPEAT_CNT;
 	void __iomem *mmio = lp->mmio;
 	unsigned int reg_val;
 
@@ -1728,15 +1728,8 @@
 	lp->vlgrp = grp;
 	spin_unlock_irq(&lp->lock);
 }
-
-static void amd8111e_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	spin_lock_irq(&lp->lock);
-	vlan_group_set_device(lp->vlgrp, vid, NULL);
-	spin_unlock_irq(&lp->lock);
-}
 #endif
+
 static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
 {
 	writel( VAL1|MPPLBA, lp->mmio + CMD3);
@@ -1996,7 +1989,6 @@
 #if AMD8111E_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX ;
 	dev->vlan_rx_register =amd8111e_vlan_rx_register;
-	dev->vlan_rx_kill_vid = amd8111e_vlan_rx_kill_vid;
 #endif
 
 	lp = netdev_priv(dev);
@@ -2049,7 +2041,6 @@
 #if AMD8111E_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register =amd8111e_vlan_rx_register;
-	dev->vlan_rx_kill_vid = amd8111e_vlan_rx_kill_vid;
 #endif
 	/* Probe the external PHY */
 	amd8111e_probe_ext_phy(dev);
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
index 2007510..e65080a 100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/amd8111e.h
@@ -615,7 +615,7 @@
 #define SSTATE  2
 
 /* Assume contoller gets data 10 times the maximum processing time */
-#define  REPEAT_CNT			10;
+#define  REPEAT_CNT			10
 
 /* amd8111e decriptor flag definitions */
 typedef enum {
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig
index 7284cca..4030274 100644
--- a/drivers/net/arcnet/Kconfig
+++ b/drivers/net/arcnet/Kconfig
@@ -2,10 +2,8 @@
 # Arcnet configuration
 #
 
-menu "ARCnet devices"
+menuconfig ARCNET
 	depends on NETDEVICES && (ISA || PCI)
-
-config ARCNET
 	tristate "ARCnet support"
 	---help---
 	  If you have a network card of this type, say Y and check out the
@@ -25,9 +23,10 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module will
 	  be called arcnet.
 
+if ARCNET
+
 config ARCNET_1201
 	tristate "Enable standard ARCNet packet format (RFC 1201)"
-	depends on ARCNET
 	help
 	  This allows you to use RFC1201 with your ARCnet card via the virtual
 	  arc0 device.  You need to say Y here to communicate with
@@ -38,7 +37,6 @@
 
 config ARCNET_1051
 	tristate "Enable old ARCNet packet format (RFC 1051)"
-	depends on ARCNET
 	---help---
 	  This allows you to use RFC1051 with your ARCnet card via the virtual
 	  arc0s device. You only need arc0s if you want to talk to ARCnet
@@ -53,7 +51,6 @@
 
 config ARCNET_RAW
 	tristate "Enable raw mode packet interface"
-	depends on ARCNET
 	help
 	  ARCnet "raw mode" packet encapsulation, no soft headers.  Unlikely
 	  to work unless talking to a copy of the same Linux arcnet driver,
@@ -61,7 +58,6 @@
 
 config ARCNET_CAP
 	tristate "Enable CAP mode packet interface"
-	depends on ARCNET
 	help
 	  ARCnet "cap mode" packet encapsulation. Used to get the hardware
           acknowledge back to userspace. After the initial protocol byte every
@@ -80,7 +76,6 @@
 
 config ARCNET_COM90xx
 	tristate "ARCnet COM90xx (normal) chipset driver"
-	depends on ARCNET
 	help
 	  This is the chipset driver for the standard COM90xx cards. If you
 	  have always used the old ARCnet driver without knowing what type of
@@ -92,7 +87,6 @@
 
 config ARCNET_COM90xxIO
 	tristate "ARCnet COM90xx (IO mapped) chipset driver"
-	depends on ARCNET
 	---help---
 	  This is the chipset driver for the COM90xx cards, using them in
 	  IO-mapped mode instead of memory-mapped mode. This is slower than
@@ -105,7 +99,6 @@
 
 config ARCNET_RIM_I
 	tristate "ARCnet COM90xx (RIM I) chipset driver"
-	depends on ARCNET
 	---help---
 	  This is yet another chipset driver for the COM90xx cards, but this
 	  time only using memory-mapped mode, and no IO ports at all. This
@@ -118,7 +111,6 @@
 
 config ARCNET_COM20020
 	tristate "ARCnet COM20020 chipset driver"
-	depends on ARCNET
 	help
 	  This is the driver for the new COM20020 chipset. It supports such
 	  things as promiscuous mode, so packet sniffing is possible, and
@@ -136,5 +128,4 @@
 	tristate "Support for COM20020 on PCI"
 	depends on ARCNET_COM20020 && PCI
 
-endmenu
-
+endif # ARCNET
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index a241ae7..bc5a38a 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -746,7 +746,7 @@
 
 	    skb_reserve(skb,2);		/* 16 byte align */
 	    skb_put(skb,pkt_len);	/* Make room */
-	    eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0);
+	    skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
 	    skb->protocol=eth_type_trans(skb,dev);
 #if 0
 	    printk(KERN_DEBUG "RX pkt type 0x%04x from ",
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 678e4f4..f9cc2b6 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -4,7 +4,7 @@
 #
 config ARM_AM79C961A
 	bool "ARM EBSA110 AM79C961A support"
-	depends on NET_ETHERNET && ARM && ARCH_EBSA110
+	depends on ARM && ARCH_EBSA110
 	select CRC32
 	help
 	  If you wish to compile a kernel for the EBSA-110, then you should
@@ -12,21 +12,21 @@
 
 config ARM_ETHER1
 	tristate "Acorn Ether1 support"
-	depends on NET_ETHERNET && ARM && ARCH_ACORN
+	depends on ARM && ARCH_ACORN
 	help
 	  If you have an Acorn system with one of these (AKA25) network cards,
 	  you should say Y to this option if you wish to use it with Linux.
 
 config ARM_ETHER3
 	tristate "Acorn/ANT Ether3 support"
-	depends on NET_ETHERNET && ARM && ARCH_ACORN
+	depends on ARM && ARCH_ACORN
 	help
 	  If you have an Acorn system with one of these network cards, you
 	  should say Y to this option if you wish to use it with Linux.
 
 config ARM_ETHERH
 	tristate "I-cubed EtherH/ANT EtherM support"
-	depends on NET_ETHERNET && ARM && ARCH_ACORN
+	depends on ARM && ARCH_ACORN
 	select CRC32
 	help
 	  If you have an Acorn system with one of these network cards, you
@@ -34,7 +34,7 @@
 
 config ARM_AT91_ETHER
 	tristate "AT91RM9200 Ethernet support"
-	depends on NET_ETHERNET && ARM && ARCH_AT91RM9200
+	depends on ARM && ARCH_AT91RM9200
 	select MII
 	help
 	  If you wish to compile a kernel for the AT91RM9200 and enable
@@ -42,7 +42,8 @@
 
 config EP93XX_ETH
 	tristate "EP93xx Ethernet support"
-	depends on NET_ETHERNET && ARM && ARCH_EP93XX
+	depends on ARM && ARCH_EP93XX
+	select MII
 	help
 	  This is a driver for the ethernet hardware included in EP93xx CPUs.
 	  Say Y if you are building a kernel for EP93xx based devices.
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 8f0d7ce..2143eeb 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -634,7 +634,7 @@
 {
 	unsigned long flags;
 	local_irq_save(flags);
-	am79c961_interrupt(dev->irq, dev, NULL);
+	am79c961_interrupt(dev->irq, dev);
 	local_irq_restore(flags);
 }
 #endif
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 2438c5b..f6ece1d 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -258,7 +258,7 @@
 			skb_reserve(skb, 2);
 			dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr,
 						length, DMA_FROM_DEVICE);
-			eth_copy_and_sum(skb, ep->rx_buf[entry], length, 0);
+			skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
 			skb_put(skb, length);
 			skb->protocol = eth_type_trans(skb, dev);
 
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
deleted file mode 100644
index 3d87bd2..0000000
--- a/drivers/net/atari_bionet.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/* bionet.c     BioNet-100 device driver for linux68k.
- *
- * Version:	@(#)bionet.c	1.0	02/06/96
- *
- * Author:	Hartmut Laue <laue@ifk-mp.uni-kiel.de>
- * and		Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
- *
- * Little adaptions for integration into pl7 by Roman Hodek
- *
- * Some changes in bionet_poll_rx by Karl-Heinz Lohner
- *
-	What is it ?
-	------------
-	This driver controls the BIONET-100 LAN-Adapter which connects
-	an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
-
-	This version can be compiled as a loadable module (See the
-	compile command at the bottom of this file).
-	At load time, you can optionally set the debugging level and the
-	fastest response time on the command line of 'insmod'.
-
-	'bionet_debug'
-		controls the amount of diagnostic messages:
-	  0  : no messages
-	  >0 : see code for meaning of printed messages
-
-	'bionet_min_poll_time' (always >=1)
-		gives the time (in jiffies) between polls. Low values
-		increase the system load (beware!)
-
-	When loaded, a net device with the name 'bio0' becomes available,
-	which can be controlled with the usual 'ifconfig' command.
-
-	It is possible to compile this driver into the kernel like other
-	(net) drivers. For this purpose, some source files (e.g. config-files
-	makefiles, Space.c) must be changed accordingly. (You may refer to
-	other drivers how to do it.) In this case, the device will be detected
-	at boot time and (probably) appear as 'eth0'.
-
-	This code is based on several sources:
-	- The driver code for a parallel port ethernet adapter by
-	  Donald Becker (see file 'atp.c' from the PC linux distribution)
-	- The ACSI code by Roman Hodek for the ATARI-ACSI harddisk support
-	  and DMA handling.
-	- Very limited information about moving packets in and out of the
-	  BIONET-adapter from the TCP package for TOS by BioData GmbH.
-
-	Theory of Operation
-	-------------------
-	Because the ATARI DMA port is usually shared between several
-	devices (eg. harddisk, floppy) we cannot block the ACSI bus
-	while waiting for interrupts. Therefore we use a polling mechanism
-	to fetch packets from the adapter. For the same reason, we send
-	packets without checking that the previous packet has been sent to
-	the LAN. We rely on the higher levels of the networking code to detect
-	missing packets and resend them.
-
-	Before we access the ATARI DMA controller, we check if another
-	process is using the DMA. If not, we lock the DMA, perform one or
-	more packet transfers and unlock the DMA before returning.
-	We do not use 'stdma_lock' unconditionally because it is unclear
-	if the networking code can be set to sleep, which will happen if
-	another (possibly slow) device is using the DMA controller.
-
-	The polling is done via timer interrupts which periodically
-	'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
-	between polls varies depending on an estimate of the net activity.
-	The allowed range is given by the variable 'bionet_min_poll_time'
-	for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
-	for the higher (slowest) limit.
-
-	Whenever a packet arrives, we switch to fastest response by setting
-	the polling time to its lowest limit. If the following poll fails,
-	because no packets have arrived, we increase the time for the next
-	poll. When the net activity is low, the polling time effectively
-	stays at its maximum value, resulting in the lowest load for the
-	machine.
- */
-
-#define MAX_POLL_TIME	10
-
-static char version[] =
-	"bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n";
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-
-
-/* use 0 for production, 1 for verification, >2 for debug
- */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-/*
- * Global variable 'bionet_debug'. Can be set at load time by 'insmod'
- */
-unsigned int bionet_debug = NET_DEBUG;
-module_param(bionet_debug, int, 0);
-MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)");
-MODULE_LICENSE("GPL");
-
-static unsigned int bionet_min_poll_time = 2;
-
-
-/* Information that need to be kept for each board.
- */
-struct net_local {
-	struct net_device_stats stats;
-	long open_time;			/* for debugging */
-	int  poll_time;			/* polling time varies with net load */
-};
-
-static struct nic_pkt_s {		/* packet format */
-	unsigned char	status;
-	unsigned char	dummy;
-	unsigned char	l_lo, l_hi;
-	unsigned char	buffer[3000];
-} *nic_packet;
-unsigned char *phys_nic_packet;
-
-/* Index to functions, as function prototypes.
- */
-static int bionet_open(struct net_device *dev);
-static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void bionet_poll_rx(struct net_device *);
-static int bionet_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void bionet_tick(unsigned long);
-
-static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0);
-
-#define STRAM_ADDR(a)	(((a) & 0xff000000) == 0)
-
-/* The following routines access the ethernet board connected to the
- * ACSI port via the st_dma chip.
- */
-#define NODE_ADR 0x60
-
-#define C_READ 8
-#define C_WRITE 0x0a
-#define C_GETEA 0x0f
-#define C_SETCR 0x0e
-
-static int
-sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) {
-	unsigned int c;
-
-	dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88);
-	dma_wd.fdc_acces_seccount = cmd;
-	dma_wd.dma_mode_status = (mod | 0x8a);
-
-	if( !acsi_wait_for_IRQ(HZ/2) )	/* wait for cmd ack */
-		return -1;		/* timeout */
-
-	c = dma_wd.fdc_acces_seccount;
-	return (c & 0xff);
-}
-
-
-static void
-set_status(int cr) {
-	sendcmd(0,0x100,NODE_ADR | C_SETCR);    /* CMD: SET CR */
-	sendcmd(1,0x100,cr);
-
-	dma_wd.dma_mode_status = 0x80;
-}
-
-static int
-get_status(unsigned char *adr) {
-	int i,c;
-
-	DISABLE_IRQ();
-	c = sendcmd(0,0x00,NODE_ADR | C_GETEA);  /* CMD: GET ETH ADR*/
-	if( c < 0 ) goto gsend;
-
-	/* now read status bytes */
-
-	for (i=0; i<6; i++) {
-		dma_wd.fdc_acces_seccount = 0;	/* request next byte */
-
-    		if( !acsi_wait_for_IRQ(HZ/2) ) {	/* wait for cmd ack */
-			c = -1;
-			goto gsend;		/* timeout */
-		}
-		c = dma_wd.fdc_acces_seccount;
-		*adr++ = (unsigned char)c;
-	}
-	c = 1;
-gsend:
-  	dma_wd.dma_mode_status = 0x80;
-	return c;
-}
-
-static irqreturn_t
-bionet_intr(int irq, void *data) {
-	return IRQ_HANDLED;
-}
-
-
-static int
-get_frame(unsigned long paddr, int odd) {
-	int c;
-	unsigned long flags;
-
-	DISABLE_IRQ();
-	local_irq_save(flags);
-
-	dma_wd.dma_mode_status		= 0x9a;
-	dma_wd.dma_mode_status		= 0x19a;
-	dma_wd.dma_mode_status		= 0x9a;
-	dma_wd.fdc_acces_seccount	= 0x04;		/* sector count (was 5) */
-	dma_wd.dma_lo			= (unsigned char)paddr;
-	paddr >>= 8;
-	dma_wd.dma_md			= (unsigned char)paddr;
-	paddr >>= 8;
-	dma_wd.dma_hi			= (unsigned char)paddr;
-	local_irq_restore(flags);
-
-	c = sendcmd(0,0x00,NODE_ADR | C_READ);	/* CMD: READ */
-	if( c < 128 ) goto rend;
-
-	/* now read block */
-
-	c = sendcmd(1,0x00,odd);	/* odd flag for address shift */
-	dma_wd.dma_mode_status	= 0x0a;
-
-	if( !acsi_wait_for_IRQ(100) ) {	/* wait for DMA to complete */
-		c = -1;
-		goto rend;
-	}
-	dma_wd.dma_mode_status	= 0x8a;
-	dma_wd.dma_mode_status	= 0x18a;
-	dma_wd.dma_mode_status	= 0x8a;
-	c = dma_wd.fdc_acces_seccount;
-
-	dma_wd.dma_mode_status	= 0x88;
-	c = dma_wd.fdc_acces_seccount;
-	c = 1;
-
-rend:
-	dma_wd.dma_mode_status	= 0x80;
-	udelay(40);
-	acsi_wait_for_noIRQ(20);
-	return c;
-}
-
-
-static int
-hardware_send_packet(unsigned long paddr, int cnt) {
-	unsigned int c;
-	unsigned long flags;
-
-	DISABLE_IRQ();
-	local_irq_save(flags);
-
-	dma_wd.dma_mode_status	= 0x19a;
-	dma_wd.dma_mode_status	= 0x9a;
-	dma_wd.dma_mode_status	= 0x19a;
-	dma_wd.dma_lo		= (unsigned char)paddr;
-	paddr >>= 8;
-	dma_wd.dma_md		= (unsigned char)paddr;
-	paddr >>= 8;
-	dma_wd.dma_hi		= (unsigned char)paddr;
-
-	dma_wd.fdc_acces_seccount	= 0x4;		/* sector count */
-	local_irq_restore(flags);
-
-	c = sendcmd(0,0x100,NODE_ADR | C_WRITE);	/* CMD: WRITE */
-	c = sendcmd(1,0x100,cnt&0xff);
-	c = sendcmd(1,0x100,cnt>>8);
-
-	/* now write block */
-
-	dma_wd.dma_mode_status	= 0x10a;	/* DMA enable */
-	if( !acsi_wait_for_IRQ(100) )		/* wait for DMA to complete */
-		goto end;
-
-	dma_wd.dma_mode_status	= 0x19a;	/* DMA disable ! */
-	c = dma_wd.fdc_acces_seccount;
-
-end:
-	c = sendcmd(1,0x100,0);
-	c = sendcmd(1,0x100,0);
-
-	dma_wd.dma_mode_status	= 0x180;
-	udelay(40);
-	acsi_wait_for_noIRQ(20);
-	return( c & 0x02);
-}
-
-
-/* Check for a network adaptor of this type, and return '0' if one exists.
- */
-struct net_device * __init bionet_probe(int unit)
-{
-	struct net_device *dev;
-	unsigned char station_addr[6];
-	static unsigned version_printed;
-	static int no_more_found;	/* avoid "Probing for..." printed 4 times */
-	int i;
-	int err;
-
-	if (!MACH_IS_ATARI || no_more_found)
-		return ERR_PTR(-ENODEV);
-
-	dev = alloc_etherdev(sizeof(struct net_local));
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-	SET_MODULE_OWNER(dev);
-
-	printk("Probing for BioNet 100 Adapter...\n");
-
-	stdma_lock(bionet_intr, NULL);
-	i = get_status(station_addr);	/* Read the station address PROM.  */
-	ENABLE_IRQ();
-	stdma_release();
-
-	/* Check the first three octets of the S.A. for the manufactor's code.
-	 */
-
-	if( i < 0
-	||  station_addr[0] != 'B'
-	||  station_addr[1] != 'I'
-	||  station_addr[2] != 'O' ) {
-		no_more_found = 1;
-		printk( "No BioNet 100 found.\n" );
-		free_netdev(dev);
-		return ERR_PTR(-ENODEV);
-	}
-
-	if (bionet_debug > 0 && version_printed++ == 0)
-		printk(version);
-
-	printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n",
-		dev->name, "BioNet 100",
-		station_addr[0], station_addr[1], station_addr[2],
-		station_addr[3], station_addr[4], station_addr[5]);
-
-	/* Initialize the device structure. */
-
-	nic_packet = (struct nic_pkt_s *)acsi_buffer;
-	phys_nic_packet = (unsigned char *)phys_acsi_buffer;
-	if (bionet_debug > 0) {
-		printk("nic_packet at 0x%p, phys at 0x%p\n",
-			nic_packet, phys_nic_packet );
-	}
-
-	dev->open		= bionet_open;
-	dev->stop		= bionet_close;
-	dev->hard_start_xmit	= bionet_send_packet;
-	dev->get_stats		= net_get_stats;
-
-	/* Fill in the fields of the device structure with ethernet-generic
-	 * values. This should be in a common file instead of per-driver.
-	 */
-
-	for (i = 0; i < ETH_ALEN; i++) {
-#if 0
-		dev->broadcast[i] = 0xff;
-#endif
-		dev->dev_addr[i]  = station_addr[i];
-	}
-	err = register_netdev(dev);
-	if (!err)
-		return dev;
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine should set everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
- */
-static int
-bionet_open(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-
-	if (bionet_debug > 0)
-		printk("bionet_open\n");
-	stdma_lock(bionet_intr, NULL);
-
-	/* Reset the hardware here.
-	 */
-	set_status(4);
-	lp->open_time = 0;	/*jiffies*/
-	lp->poll_time = MAX_POLL_TIME;
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	stdma_release();
-	bionet_timer.data = (long)dev;
-	bionet_timer.expires = jiffies + lp->poll_time;
-	add_timer(&bionet_timer);
-	return 0;
-}
-
-static int
-bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	 */
-	local_irq_save(flags);
-
-	if (stdma_islocked()) {
-		local_irq_restore(flags);
-		lp->stats.tx_errors++;
-	}
-	else {
-		int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-		unsigned long buf = virt_to_phys(skb->data);
-		int stat;
-
-		stdma_lock(bionet_intr, NULL);
-		local_irq_restore(flags);
-		if( !STRAM_ADDR(buf+length-1) ) {
-			skb_copy_from_linear_data(skb, nic_packet->buffer,
-						  length);
-			buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
-		}
-
-		if (bionet_debug >1) {
-			u_char *data = nic_packet->buffer, *p;
-			int i;
-
-			printk( "%s: TX pkt type 0x%4x from ", dev->name,
-				  ((u_short *)data)[6]);
-
-			for( p = &data[6], i = 0; i < 6; i++ )
-				printk("%02x%s", *p++,i != 5 ? ":" : "" );
-			printk(" to ");
-
-			for( p = data, i = 0; i < 6; i++ )
-				printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
-
-			printk( "%s: ", dev->name );
-			printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
-			       " %02x%02x%02x%02x len %d\n",
-				  data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
-				  data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
-				  data[28], data[29], data[30], data[31], data[32], data[33],
-				  length );
-		}
-		dma_cache_maintenance(buf, length, 1);
-
-		stat = hardware_send_packet(buf, length);
-		ENABLE_IRQ();
-		stdma_release();
-
-		dev->trans_start = jiffies;
-		dev->tbusy	 = 0;
-		lp->stats.tx_packets++;
-		lp->stats.tx_bytes+=length;
-	}
-	dev_kfree_skb(skb);
-
-	return 0;
-}
-
-/* We have a good packet(s), get it/them out of the buffers.
- */
-static void
-bionet_poll_rx(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-	int boguscount = 10;
-	int pkt_len, status;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	/* ++roman: Take care at locking the ST-DMA... This must be done with ints
-	 * off, since otherwise an int could slip in between the question and the
-	 * locking itself, and then we'd go to sleep... And locking itself is
-	 * necessary to keep the floppy_change timer from working with ST-DMA
-	 * registers. */
-	if (stdma_islocked()) {
-		local_irq_restore(flags);
-		return;
-	}
-	stdma_lock(bionet_intr, NULL);
-	DISABLE_IRQ();
-	local_irq_restore(flags);
-
-	if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
-
-	while(boguscount--) {
-		status = get_frame((unsigned long)phys_nic_packet, 0);
-
-		if( status == 0 ) break;
-
-		/* Good packet... */
-
-		dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0);
-
-		pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo;
-
-		lp->poll_time = bionet_min_poll_time;    /* fast poll */
-		if( pkt_len >= 60 && pkt_len <= 1520 ) {
-					/*	^^^^ war 1514  KHL */
-			/* Malloc up new buffer.
-			 */
-			struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 );
-			if (skb == NULL) {
-				printk("%s: Memory squeeze, dropping packet.\n",
-					dev->name);
-				lp->stats.rx_dropped++;
-				break;
-			}
-
-			skb_reserve( skb, 2 );		/* 16 Byte align  */
-			skb_put( skb, pkt_len );	/* make room */
-
-			/* 'skb->data' points to the start of sk_buff data area.
-			 */
-			skb_copy_to_linear_data(skb, nic_packet->buffer,
-						pkt_len);
-			skb->protocol = eth_type_trans( skb, dev );
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			lp->stats.rx_packets++;
-			lp->stats.rx_bytes+=pkt_len;
-
-	/* If any worth-while packets have been received, dev_rint()
-	   has done a mark_bh(INET_BH) for us and will work on them
-	   when we get to the bottom-half routine.
-	 */
-
- 			if (bionet_debug >1) {
- 				u_char *data = nic_packet->buffer, *p;
- 				int i;
-
- 				printk( "%s: RX pkt type 0x%4x from ", dev->name,
- 					  ((u_short *)data)[6]);
-
-
- 				for( p = &data[6], i = 0; i < 6; i++ )
- 					printk("%02x%s", *p++,i != 5 ? ":" : "" );
- 				printk(" to ");
- 				for( p = data, i = 0; i < 6; i++ )
- 					printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
-
- 				printk( "%s: ", dev->name );
- 				printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
- 				       " %02x%02x%02x%02x len %d\n",
- 					  data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
- 					  data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
- 					  data[28], data[29], data[30], data[31], data[32], data[33],
- 						  pkt_len );
- 			}
- 		}
- 		else {
- 			printk(" Packet has wrong length: %04d bytes\n", pkt_len);
- 			lp->stats.rx_errors++;
- 		}
- 	}
-	stdma_release();
-	ENABLE_IRQ();
-	return;
-}
-
-/* bionet_tick: called by bionet_timer. Reads packets from the adapter,
- * passes them to the higher layers and restarts the timer.
- */
-static void
-bionet_tick(unsigned long data) {
-	struct net_device	 *dev = (struct net_device *)data;
-	struct net_local *lp = netdev_priv(dev);
-
-	if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 )
-		printk("bionet_tick: %ld\n", lp->open_time);
-
-	if( !stdma_islocked() ) bionet_poll_rx(dev);
-
-	bionet_timer.expires = jiffies + lp->poll_time;
-	add_timer(&bionet_timer);
-}
-
-/* The inverse routine to bionet_open().
- */
-static int
-bionet_close(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-
-	if (bionet_debug > 0)
-		printk("bionet_close, open_time=%ld\n", lp->open_time);
-	del_timer(&bionet_timer);
-	stdma_lock(bionet_intr, NULL);
-
-	set_status(0);
-	lp->open_time = 0;
-
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	stdma_release();
-	return 0;
-}
-
-/* Get the current statistics.
-   This may be called with the card open or closed.
- */
-static struct net_device_stats *net_get_stats(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	return &lp->stats;
-}
-
-
-#ifdef MODULE
-
-static struct net_device *bio_dev;
-
-int init_module(void)
-{
-	bio_dev = bionet_probe(-1);
-	if (IS_ERR(bio_dev))
-		return PTR_ERR(bio_dev);
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	unregister_netdev(bio_dev);
-	free_netdev(bio_dev);
-}
-
-#endif /* MODULE */
-
-/* Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
-	-b m68k-linuxaout -Wall -Wstrict-prototypes -O2
-	-fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
deleted file mode 100644
index 54714409..0000000
--- a/drivers/net/atari_pamsnet.c
+++ /dev/null
@@ -1,896 +0,0 @@
-/* atari_pamsnet.c     PAMsNet device driver for linux68k.
- *
- * Version:	@(#)PAMsNet.c	0.2ß	03/31/96
- *
- * Author:  Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de>
- *                       <Torsten.Lang@jung.de>
- *
- * This driver is based on my driver PAMSDMA.c for MiNT-Net and
- * on the driver bionet.c written by
- *          Hartmut Laue <laue@ifk-mp.uni-kiel.de>
- * and      Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
- *
- * Little adaptions for integration into pl7 by Roman Hodek
- *
-	What is it ?
-	------------
-	This driver controls the PAMsNet LAN-Adapter which connects
-	an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
-
-	This version can be compiled as a loadable module (See the
-	compile command at the bottom of this file).
-	At load time, you can optionally set the debugging level and the
-	fastest response time on the command line of 'insmod'.
-
-	'pamsnet_debug'
-		controls the amount of diagnostic messages:
-	  0  : no messages
-	  >0 : see code for meaning of printed messages
-
-	'pamsnet_min_poll_time' (always >=1)
-		gives the time (in jiffies) between polls. Low values
-		increase the system load (beware!)
-
-	When loaded, a net device with the name 'eth?' becomes available,
-	which can be controlled with the usual 'ifconfig' command.
-
-	It is possible to compile this driver into the kernel like other
-	(net) drivers. For this purpose, some source files (e.g. config-files
-	makefiles, Space.c) must be changed accordingly. (You may refer to
-	other drivers how to do it.) In this case, the device will be detected
-	at boot time and (probably) appear as 'eth0'.
-
-	Theory of Operation
-	-------------------
-	Because the ATARI DMA port is usually shared between several
-	devices (eg. harddisk, floppy) we cannot block the ACSI bus
-	while waiting for interrupts. Therefore we use a polling mechanism
-	to fetch packets from the adapter. For the same reason, we send
-	packets without checking that the previous packet has been sent to
-	the LAN. We rely on the higher levels of the networking code to detect
-	missing packets and resend them.
-
-	Before we access the ATARI DMA controller, we check if another
-	process is using the DMA. If not, we lock the DMA, perform one or
-	more packet transfers and unlock the DMA before returning.
-	We do not use 'stdma_lock' unconditionally because it is unclear
-	if the networking code can be set to sleep, which will happen if
-	another (possibly slow) device is using the DMA controller.
-
-	The polling is done via timer interrupts which periodically
-	'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
-	between polls varies depending on an estimate of the net activity.
-	The allowed range is given by the variable 'bionet_min_poll_time'
-	for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
-	for the higher (slowest) limit.
-
-	Whenever a packet arrives, we switch to fastest response by setting
-	the polling time to its lowest limit. If the following poll fails,
-	because no packets have arrived, we increase the time for the next
-	poll. When the net activity is low, the polling time effectively
-	stays at its maximum value, resulting in the lowest load for the
-	machine.
- */
-
-#define MAX_POLL_TIME	10
-
-static char *version =
-	"pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n";
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/errno.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_acsi.h>
-
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#undef READ
-#undef WRITE
-
-/* use 0 for production, 1 for verification, >2 for debug
- */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-/*
- * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod'
- */
-unsigned int pamsnet_debug = NET_DEBUG;
-module_param(pamsnet_debug, int, 0);
-MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)");
-MODULE_LICENSE("GPL");
-
-static unsigned int pamsnet_min_poll_time = 2;
-
-
-/* Information that need to be kept for each board.
- */
-struct net_local {
-	struct net_device_stats stats;
-	long open_time;			/* for debugging */
-	int  poll_time;			/* polling time varies with net load */
-};
-
-static struct nic_pkt_s {		/* packet format */
-	unsigned char	buffer[2048];
-} *nic_packet = 0;
-unsigned char *phys_nic_packet;
-
-typedef unsigned char HADDR[6]; /* 6-byte hardware address of lance */
-
-/* Index to functions, as function prototypes.
- */
-static void	start (int target);
-static int	stop (int target);
-static int	testpkt (int target);
-static int	sendpkt (int target, unsigned char *buffer, int length);
-static int	receivepkt (int target, unsigned char *buffer);
-static int	inquiry (int target, unsigned char *buffer);
-static HADDR	*read_hw_addr(int target, unsigned char *buffer);
-static void	setup_dma (void *address, unsigned rw_flag, int num_blocks);
-static int	send_first (int target, unsigned char byte);
-static int	send_1_5 (int lun, unsigned char *command, int dma);
-static int	get_status (void);
-static int	calc_received (void *start_address);
-
-static int pamsnet_open(struct net_device *dev);
-static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void pamsnet_poll_rx(struct net_device *);
-static int pamsnet_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void pamsnet_tick(unsigned long);
-
-static irqreturn_t pamsnet_intr(int irq, void *data);
-
-static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0);
-
-#define STRAM_ADDR(a)	(((a) & 0xff000000) == 0)
-
-typedef struct
-{
-	unsigned char reserved1[0x38];
-	HADDR  hwaddr;
-	unsigned char reserved2[0x1c2];
-} DMAHWADDR;
-
-/*
- * Definitions of commands understood by the PAMs DMA adaptor.
- *
- * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable
- * by the PAM's Net software.
- *
- * LUN 0 works as a harddisk. You can boot the PAM's Net driver there.
- * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW
- *       area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address
- *       of the adaptor.
- * LUN 6 works as a harddisk and lets you access the firmware ROM.
- * LUN 7 lets you send and receive packets.
- *
- * Some commands like the INQUIRY command work identical on all used LUNs.
- *
- * UNKNOWN1 seems to read some data.
- *          Command length is 6 bytes.
- * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The
- *          following bytes seem to be something like an allocation length.
- *          Command length is 6 bytes.
- * READPKT  reads a packet received by the DMA adaptor.
- *          Command length is 6 bytes.
- * WRITEPKT sends a packet transferred by the following DMA phase. The length
- *          of the packet is transferred in command bytes 3 and 4.
- *          The adaptor automatically replaces the src hw address in an ethernet
- *          packet by its own hw address.
- *          Command length is 6 bytes.
- * INQUIRY  has the same function as the INQUIRY command supported by harddisks
- *          and other SCSI devices. It lets you detect which device you found
- *          at a given address.
- *          Command length is 6 bytes.
- * START    initializes the DMA adaptor. After this command it is able to send
- *          and receive packets. There is no status byte returned!
- *          Command length is 1 byte.
- * NUMPKTS  gives back the number of received packets waiting in the queue in
- *          the status byte.
- *          Command length is 1 byte.
- * UNKNOWN3
- * UNKNOWN4 Function of these three commands is unknown.
- * UNKNOWN5 The command length of these three commands is 1 byte.
- * DESELECT immediately deselects the DMA adaptor. May important with interrupt
- *          driven operation.
- *          Command length is 1 byte.
- * STOP     resets the DMA adaptor. After this command packets can no longer
- *          be received or transferred.
- *          Command length is 6 byte.
- */
-
-enum {UNKNOWN1=3, READPKT=8, UNKNOWN2, WRITEPKT=10, INQUIRY=18, START,
-      NUMPKTS=22, UNKNOWN3, UNKNOWN4, UNKNOWN5, DESELECT, STOP};
-
-#define READSECTOR  READPKT
-#define WRITESECTOR WRITEPKT
-
-u_char *inquire8="MV      PAM's NET/GK";
-
-#define DMALOW   dma_wd.dma_lo
-#define DMAMID   dma_wd.dma_md
-#define DMAHIGH  dma_wd.dma_hi
-#define DACCESS  dma_wd.fdc_acces_seccount
-
-#define MFP_GPIP mfp.par_dt_reg
-
-/* Some useful functions */
-
-#define INT      (!(MFP_GPIP & 0x20))
-#define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;})
-#define WRITEMODE(value)					\
-	({	u_short dummy = value;				\
-		__asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy));	\
-		DELAY;						\
-	})
-#define WRITEBOTH(value1, value2)				\
-	({	u_long dummy = (u_long)(value1)<<16 | (u_short)(value2);	\
-		__asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy));	\
-		DELAY;						\
-	})
-
-/* Definitions for DMODE */
-
-#define READ        0x000
-#define WRITE       0x100
-
-#define DMA_FDC     0x080
-#define DMA_ACSI    0x000
-
-#define DMA_DISABLE 0x040
-
-#define SEC_COUNT   0x010
-#define DMA_WINDOW  0x000
-
-#define REG_ACSI    0x008
-#define REG_FDC     0x000
-
-#define A1          0x002
-
-/* Timeout constants */
-
-#define TIMEOUTCMD HZ/2   /* ca. 500ms */
-#define TIMEOUTDMA HZ     /* ca. 1s */
-#define COMMAND_DELAY 500 /* ca. 0.5ms */
-
-unsigned rw;
-int lance_target = -1;
-int if_up = 0;
-
-/* The following routines access the ethernet board connected to the
- * ACSI port via the st_dma chip.
- */
-
-/* The following lowlevel routines work on physical addresses only and assume
- * that eventually needed buffers are
- * - completely located in ST RAM
- * - are contigous in the physical address space
- */
-
-/* Setup the DMA counter */
-
-static void
-setup_dma (address, rw_flag, num_blocks)
-	void *address;
-	unsigned rw_flag;
-	int num_blocks;
-{
-	WRITEMODE((unsigned) rw_flag          | DMA_FDC | SEC_COUNT | REG_ACSI |
-		  A1);
-	WRITEMODE((unsigned)(rw_flag ^ WRITE) | DMA_FDC | SEC_COUNT | REG_ACSI |
-		  A1);
-	WRITEMODE((unsigned) rw_flag          | DMA_FDC | SEC_COUNT | REG_ACSI |
-		  A1);
-	DMALOW  = (unsigned char)((unsigned long)address & 0xFF);
-	DMAMID  = (unsigned char)(((unsigned long)address >>  8) & 0xFF);
-	DMAHIGH = (unsigned char)(((unsigned long)address >> 16) & 0xFF);
-	WRITEBOTH((unsigned)num_blocks & 0xFF,
-		  rw_flag | DMA_FDC | DMA_WINDOW | REG_ACSI | A1);
-	rw = rw_flag;
-}
-
-/* Send the first byte of an command block */
-
-static int
-send_first (target, byte)
-	int target;
-	unsigned char byte;
-{
-	rw = READ;
-	acsi_delay_end(COMMAND_DELAY);
-	/*
-	 * wake up ACSI
-	 */
-	WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI);
-	/*
-	 * write command byte
-	 */
-	WRITEBOTH((target << 5) | (byte & 0x1F), DMA_FDC |
-	          DMA_WINDOW | REG_ACSI | A1);
-	return (!acsi_wait_for_IRQ(TIMEOUTCMD));
-}
-
-/* Send the rest of an command block */
-
-static int
-send_1_5 (lun, command, dma)
-	int lun;
-	unsigned char *command;
-	int dma;
-{
-	int i, j;
-
-	for (i=0; i<5; i++) {
-		WRITEBOTH((!i ? (((lun & 0x7) << 5) | (command[i] & 0x1F))
-			      : command[i]),
-			  rw | REG_ACSI | DMA_WINDOW |
-			   ((i < 4) ? DMA_FDC
-				    : (dma ? DMA_ACSI
-					   : DMA_FDC)) | A1);
-		if (i < 4 && (j = !acsi_wait_for_IRQ(TIMEOUTCMD)))
-			return (j);
-	}
-	return (0);
-}
-
-/* Read a status byte */
-
-static int
-get_status (void)
-{
-	WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI | A1);
-	acsi_delay_start();
-	return ((int)(DACCESS & 0xFF));
-}
-
-/* Calculate the number of received bytes */
-
-static int
-calc_received (start_address)
-	void *start_address;
-{
-	return (int)(
-		(((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW)
-	      - (unsigned long)start_address);
-}
-
-/* The following midlevel routines still work on physical addresses ... */
-
-/* start() starts the PAM's DMA adaptor */
-
-static void
-start (target)
-	int target;
-{
-	send_first(target, START);
-}
-
-/* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */
-
-static int
-stop (target)
-	int target;
-{
-	int ret = -1;
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, STOP))
-		goto bad;
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] =
-	cmd_buffer[3] = cmd_buffer[4] = 0;
-	if (send_1_5(7, cmd_buffer, 0) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status())
-		goto bad;
-	ret = 0;
-bad:
-	return (ret);
-}
-
-/* testpkt() returns the number of received packets waiting in the queue */
-
-static int
-testpkt(target)
-	int target;
-{
-	int ret = -1;
-
-	if (send_first(target, NUMPKTS))
-		goto bad;
-	ret = get_status();
-bad:
-	return (ret);
-}
-
-/* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */
-/* Please note: The buffer is for internal use only but must be defined!   */
-
-static int
-inquiry (target, buffer)
-	int target;
-	unsigned char *buffer;
-{
-	int ret = -1;
-	unsigned char *vbuffer = phys_to_virt((unsigned long)buffer);
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, INQUIRY))
-		goto bad;
-	setup_dma(buffer, READ, 1);
-	vbuffer[8] = vbuffer[27] = 0; /* Avoid confusion with previous read data */
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
-	cmd_buffer[3] = 48;
-	if (send_1_5(5, cmd_buffer, 1) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status() ||
-	    (calc_received(buffer) < 32))
-		goto bad;
-	dma_cache_maintenance((unsigned long)(buffer+8), 20, 0);
-	if (memcmp(inquire8, vbuffer+8, 20))
-		goto bad;
-	ret = 0;
-bad:
-	if (!!NET_DEBUG) {
-		vbuffer[8+20]=0;
-		printk("inquiry of target %d: %s\n", target, vbuffer+8);
-	}
-	return (ret);
-}
-
-/*
- * read_hw_addr() reads the sector containing the hwaddr and returns
- * a pointer to it (virtual address!) or 0 in case of an error
- */
-
-static HADDR
-*read_hw_addr(target, buffer)
-	int target;
-	unsigned char *buffer;
-{
-	HADDR *ret = 0;
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, READSECTOR))
-		goto bad;
-	setup_dma(buffer, READ, 1);
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
-	cmd_buffer[3] = 1;
-	if (send_1_5(5, cmd_buffer, 1) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status())
-		goto bad;
-	ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr));
-	dma_cache_maintenance((unsigned long)buffer, 512, 0);
-bad:
-	return (ret);
-}
-
-static irqreturn_t
-pamsnet_intr(irq, data, fp)
-	int irq;
-	void *data;
-{
-	return IRQ_HANDLED;
-}
-
-/* receivepkt() loads a packet to a given buffer and returns its length */
-
-static int
-receivepkt (target, buffer)
-	int target;
-	unsigned char *buffer;
-{
-	int ret = -1;
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, READPKT))
-		goto bad;
-	setup_dma(buffer, READ, 3);
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
-	cmd_buffer[3] = 3;
-	if (send_1_5(7, cmd_buffer, 1) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status())
-		goto bad;
-	ret = calc_received(buffer);
-bad:
-	return (ret);
-}
-
-/* sendpkt() sends a packet and returns a value of zero when the packet was sent
-             successfully */
-
-static int
-sendpkt (target, buffer, length)
-	int target;
-	unsigned char *buffer;
-	int length;
-{
-	int ret = -1;
-	unsigned char cmd_buffer[5];
-
-	if (send_first(target, WRITEPKT))
-		goto bad;
-	setup_dma(buffer, WRITE, 3);
-	cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[4] = 0;
-	cmd_buffer[2] = length >> 8;
-	cmd_buffer[3] = length & 0xFF;
-	if (send_1_5(7, cmd_buffer, 1) ||
-	    !acsi_wait_for_IRQ(TIMEOUTDMA) ||
-	    get_status())
-		goto bad;
-	ret = 0;
-bad:
-	return (ret);
-}
-
-/* The following higher level routines work on virtual addresses and convert them to
- * physical addresses when passed to the lowlevel routines. It's up to the higher level
- * routines to copy data from Alternate RAM to ST RAM if neccesary!
- */
-
-/* Check for a network adaptor of this type, and return '0' if one exists.
- */
-
-struct net_device * __init pamsnet_probe (int unit)
-{
-	struct net_device *dev;
-	int i;
-	HADDR *hwaddr;
-	int err;
-
-	unsigned char station_addr[6];
-	static unsigned version_printed;
-	/* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */
-	static int no_more_found;
-
-	if (no_more_found)
-		return ERR_PTR(-ENODEV);
-	no_more_found = 1;
-
-	dev = alloc_etherdev(sizeof(struct net_local));
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-	SET_MODULE_OWNER(dev);
-
-	printk("Probing for PAM's Net/GK Adapter...\n");
-
-	/* Allocate the DMA buffer here since we need it for probing! */
-
-	nic_packet = (struct nic_pkt_s *)acsi_buffer;
-	phys_nic_packet = (unsigned char *)phys_acsi_buffer;
-	if (pamsnet_debug > 0) {
-		printk("nic_packet at 0x%p, phys at 0x%p\n",
-			   nic_packet, phys_nic_packet );
-	}
-
-	stdma_lock(pamsnet_intr, NULL);
-	DISABLE_IRQ();
-
-	for (i=0; i<8; i++) {
-		/* Do two inquiries to cover cases with strange equipment on previous ID */
-		/* blocking the ACSI bus (like the SLMC804 laser printer controller...   */
-		inquiry(i, phys_nic_packet);
-		if (!inquiry(i, phys_nic_packet)) {
-			lance_target = i;
-			break;
-		}
-	}
-
-	if (!!NET_DEBUG)
-		printk("ID: %d\n",i);
-
-	if (lance_target >= 0) {
-		if (!(hwaddr = read_hw_addr(lance_target, phys_nic_packet)))
-			lance_target = -1;
-		else
-			memcpy (station_addr, hwaddr, ETH_ALEN);
-	}
-
-	ENABLE_IRQ();
-	stdma_release();
-
-	if (lance_target < 0) {
-		printk("No PAM's Net/GK found.\n");
-		free_netdev(dev);
-		return ERR_PTR(-ENODEV);
-	}
-
-	if (pamsnet_debug > 0 && version_printed++ == 0)
-		printk(version);
-
-	printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n",
-		dev->name, "PAM's Net/GK", lance_target,
-		station_addr[0], station_addr[1], station_addr[2],
-		station_addr[3], station_addr[4], station_addr[5]);
-
-	/* Initialize the device structure. */
-	dev->open		= pamsnet_open;
-	dev->stop		= pamsnet_close;
-	dev->hard_start_xmit	= pamsnet_send_packet;
-	dev->get_stats		= net_get_stats;
-
-	/* Fill in the fields of the device structure with ethernet-generic
-	 * values. This should be in a common file instead of per-driver.
-	 */
-
-	for (i = 0; i < ETH_ALEN; i++) {
-#if 0
-		dev->broadcast[i] = 0xff;
-#endif
-		dev->dev_addr[i]  = station_addr[i];
-	}
-	err = register_netdev(dev);
-	if (!err)
-		return dev;
-
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine should set everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
- */
-static int
-pamsnet_open(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-
-	if (pamsnet_debug > 0)
-		printk("pamsnet_open\n");
-	stdma_lock(pamsnet_intr, NULL);
-	DISABLE_IRQ();
-
-	/* Reset the hardware here.
-	 */
-	if (!if_up)
-		start(lance_target);
-	if_up = 1;
-	lp->open_time = 0;	/*jiffies*/
-	lp->poll_time = MAX_POLL_TIME;
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	ENABLE_IRQ();
-	stdma_release();
-	pamsnet_timer.data = (long)dev;
-	pamsnet_timer.expires = jiffies + lp->poll_time;
-	add_timer(&pamsnet_timer);
-	return 0;
-}
-
-static int
-pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	 */
-	local_irq_save(flags);
-
-	if (stdma_islocked()) {
-		local_irq_restore(flags);
-		lp->stats.tx_errors++;
-	}
-	else {
-		int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-		unsigned long buf = virt_to_phys(skb->data);
-		int stat;
-
-		stdma_lock(pamsnet_intr, NULL);
-		DISABLE_IRQ();
-
-		local_irq_restore(flags);
-		if( !STRAM_ADDR(buf+length-1) ) {
-			skb_copy_from_linear_data(skb, nic_packet->buffer,
-						  length);
-			buf = (unsigned long)phys_nic_packet;
-		}
-
-		dma_cache_maintenance(buf, length, 1);
-
-		stat = sendpkt(lance_target, (unsigned char *)buf, length);
-		ENABLE_IRQ();
-		stdma_release();
-
-		dev->trans_start = jiffies;
-		dev->tbusy	 = 0;
-		lp->stats.tx_packets++;
-		lp->stats.tx_bytes+=length;
-	}
-	dev_kfree_skb(skb);
-
-	return 0;
-}
-
-/* We have a good packet(s), get it/them out of the buffers.
- */
-static void
-pamsnet_poll_rx(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-	int boguscount;
-	int pkt_len;
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	/* ++roman: Take care at locking the ST-DMA... This must be done with ints
-	 * off, since otherwise an int could slip in between the question and the
-	 * locking itself, and then we'd go to sleep... And locking itself is
-	 * necessary to keep the floppy_change timer from working with ST-DMA
-	 * registers. */
-	if (stdma_islocked()) {
-		local_irq_restore(flags);
-		return;
-	}
-	stdma_lock(pamsnet_intr, NULL);
-	DISABLE_IRQ();
-	local_irq_restore(flags);
-
-	boguscount = testpkt(lance_target);
-	if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
-
-	while(boguscount--) {
-		pkt_len = receivepkt(lance_target, phys_nic_packet);
-
-		if( pkt_len < 60 ) break;
-
-		/* Good packet... */
-
-		dma_cache_maintenance((unsigned long)phys_nic_packet, pkt_len, 0);
-
-		lp->poll_time = pamsnet_min_poll_time;    /* fast poll */
-		if( pkt_len >= 60 && pkt_len <= 2048 ) {
-			if (pkt_len > 1514)
-				pkt_len = 1514;
-
-			/* Malloc up new buffer.
-			 */
-			skb = alloc_skb(pkt_len, GFP_ATOMIC);
-			if (skb == NULL) {
-				printk("%s: Memory squeeze, dropping packet.\n",
-					dev->name);
-				lp->stats.rx_dropped++;
-				break;
-			}
-			skb->len = pkt_len;
-			skb->dev = dev;
-
-			/* 'skb->data' points to the start of sk_buff data area.
-			 */
-			skb_copy_to_linear_data(skb, nic_packet->buffer,
-						pkt_len);
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			lp->stats.rx_packets++;
-			lp->stats.rx_bytes+=pkt_len;
-		}
-	}
-
-	/* If any worth-while packets have been received, dev_rint()
-	   has done a mark_bh(INET_BH) for us and will work on them
-	   when we get to the bottom-half routine.
-	 */
-
-	ENABLE_IRQ();
-	stdma_release();
-	return;
-}
-
-/* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter,
- * passes them to the higher layers and restarts the timer.
- */
-static void
-pamsnet_tick(unsigned long data) {
-	struct net_device	 *dev = (struct net_device *)data;
-	struct net_local *lp = netdev_priv(dev);
-
-	if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 )
-		printk("pamsnet_tick: %ld\n", lp->open_time);
-
-	pamsnet_poll_rx(dev);
-
-	pamsnet_timer.expires = jiffies + lp->poll_time;
-	add_timer(&pamsnet_timer);
-}
-
-/* The inverse routine to pamsnet_open().
- */
-static int
-pamsnet_close(struct net_device *dev) {
-	struct net_local *lp = netdev_priv(dev);
-
-	if (pamsnet_debug > 0)
-		printk("pamsnet_close, open_time=%ld\n", lp->open_time);
-	del_timer(&pamsnet_timer);
-	stdma_lock(pamsnet_intr, NULL);
-	DISABLE_IRQ();
-
-	if (if_up)
-		stop(lance_target);
-	if_up = 0;
-
-	lp->open_time = 0;
-
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	ENABLE_IRQ();
-	stdma_release();
-	return 0;
-}
-
-/* Get the current statistics.
-   This may be called with the card open or closed.
- */
-static struct net_device_stats *net_get_stats(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	return &lp->stats;
-}
-
-
-#ifdef MODULE
-
-static struct net_device *pam_dev;
-
-int init_module(void)
-{
-	pam_dev = pamsnet_probe(-1);
-	if (IS_ERR(pam_dev))
-		return PTR_ERR(pam_dev);
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	unregister_netdev(pam_dev);
-	free_netdev(pam_dev);
-}
-
-#endif /* MODULE */
-
-/* Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
-	-b m68k-linuxaout -Wall -Wstrict-prototypes -O2
-	-fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
index b1c6034..ff4765f6 100644
--- a/drivers/net/atl1/atl1.h
+++ b/drivers/net/atl1/atl1.h
@@ -43,6 +43,7 @@
 struct atl1_adapter;
 
 #define ATL1_MAX_INTR		3
+#define ATL1_MAX_TX_BUF_LEN	0x3000	/* 12288 bytes */
 
 #define ATL1_DEFAULT_TPD	256
 #define ATL1_MAX_TPD		1024
@@ -57,29 +58,45 @@
 #define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc)
 
 /*
+ * This detached comment is preserved for documentation purposes only.
+ * It was originally attached to some code that got deleted, but seems
+ * important enough to keep around...
+ *
+ * <begin detached comment>
  * Some workarounds require millisecond delays and are run during interrupt
  * context.  Most notably, when establishing link, the phy may need tweaking
  * but cannot process phy register reads/writes faster than millisecond
  * intervals...and we establish link due to a "link status change" interrupt.
+ * <end detached comment>
  */
 
 /*
- * wrapper around a pointer to a socket buffer,
- * so a DMA handle can be stored along with the buffer
+ * atl1_ring_header represents a single, contiguous block of DMA space
+ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
+ * message blocks (cmb, smb) described below
+ */
+struct atl1_ring_header {
+	void *desc;		/* virtual address */
+	dma_addr_t dma;		/* physical address*/
+	unsigned int size;	/* length in bytes */
+};
+
+/*
+ * atl1_buffer is wrapper around a pointer to a socket buffer
+ * so a DMA handle can be stored along with the skb
  */
 struct atl1_buffer {
-	struct sk_buff *skb;
-	u16 length;
-	u16 alloced;
+	struct sk_buff *skb;	/* socket buffer */
+	u16 length;		/* rx buffer length */
+	u16 alloced;		/* 1 if skb allocated */
 	dma_addr_t dma;
 };
 
-#define MAX_TX_BUF_LEN		0x3000	/* 12KB */
-
+/* transmit packet descriptor (tpd) ring */
 struct atl1_tpd_ring {
-	void *desc;		/* pointer to the descriptor ring memory */
-	dma_addr_t dma;		/* physical adress of the descriptor ring */
-	u16 size;		/* length of descriptor ring in bytes */
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
 	u16 count;		/* number of descriptors in the ring */
 	u16 hw_idx;		/* hardware index */
 	atomic_t next_to_clean;
@@ -87,36 +104,34 @@
 	struct atl1_buffer *buffer_info;
 };
 
+/* receive free descriptor (rfd) ring */
 struct atl1_rfd_ring {
-	void *desc;
-	dma_addr_t dma;
-	u16 size;
-	u16 count;
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
 	atomic_t next_to_use;
 	u16 next_to_clean;
 	struct atl1_buffer *buffer_info;
 };
 
+/* receive return descriptor (rrd) ring */
 struct atl1_rrd_ring {
-	void *desc;
-	dma_addr_t dma;
-	unsigned int size;
-	u16 count;
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	unsigned int size;	/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
 	u16 next_to_use;
 	atomic_t next_to_clean;
 };
 
-struct atl1_ring_header {
-	void *desc;		/* pointer to the descriptor ring memory */
-	dma_addr_t dma;		/* physical adress of the descriptor ring */
-	unsigned int size;	/* length of descriptor ring in bytes */
-};
-
+/* coalescing message block (cmb) */
 struct atl1_cmb {
 	struct coals_msg_block *cmb;
 	dma_addr_t dma;
 };
 
+/* statistics message block (smb) */
 struct atl1_smb {
 	struct stats_msg_block *smb;
 	dma_addr_t dma;
@@ -141,24 +156,26 @@
 	u64 tx_aborted_errors;
 	u64 tx_window_errors;
 	u64 tx_carrier_errors;
-
-	u64 tx_pause;		/* num Pause packet transmitted. */
-	u64 excecol;		/* num tx packets aborted due to excessive collisions. */
-	u64 deffer;		/* num deferred tx packets */
-	u64 scc;		/* num packets subsequently transmitted successfully w/ single prior collision. */
-	u64 mcc;		/* num packets subsequently transmitted successfully w/ multiple prior collisions. */
+	u64 tx_pause;		/* num pause packets transmitted. */
+	u64 excecol;		/* num tx packets w/ excessive collisions. */
+	u64 deffer;		/* num tx packets deferred */
+	u64 scc;		/* num packets subsequently transmitted
+				 * successfully w/ single prior collision. */
+	u64 mcc;		/* num packets subsequently transmitted
+				 * successfully w/ multiple prior collisions. */
 	u64 latecol;		/* num tx packets  w/ late collisions. */
-	u64 tx_underun;		/* num tx packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
-	u64 tx_trunc;		/* num tx packets truncated due to size exceeding MTU, regardless whether truncated by Selene or not. (The name doesn't really reflect the meaning in this case.) */
+	u64 tx_underun;		/* num tx packets aborted due to transmit
+				 * FIFO underrun, or TRD FIFO underrun */
+	u64 tx_trunc;		/* num tx packets truncated due to size
+				 * exceeding MTU, regardless whether truncated
+				 * by the chip or not. (The name doesn't really
+				 * reflect the meaning in this case.) */
 	u64 rx_pause;		/* num Pause packets received. */
 	u64 rx_rrd_ov;
 	u64 rx_trunc;
 };
 
-/* board specific private data structure */
-#define ATL1_REGS_LEN	8
-
-/* Structure containing variables used by the shared code */
+/* hardware structure */
 struct atl1_hw {
 	u8 __iomem *hw_addr;
 	struct atl1_adapter *back;
@@ -167,24 +184,35 @@
 	enum atl1_dma_req_block dmar_block;
 	enum atl1_dma_req_block dmaw_block;
 	u8 preamble_len;
-	u8 max_retry;		/* Retransmission maximum, after which the packet will be discarded */
-	u8 jam_ipg;		/* IPG to start JAM for collision based flow control in half-duplex mode. In units of 8-bit time */
-	u8 ipgt;		/* Desired back to back inter-packet gap. The default is 96-bit time */
-	u8 min_ifg;		/* Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped */
+	u8 max_retry;		/* Retransmission maximum, after which the
+				 * packet will be discarded */
+	u8 jam_ipg;		/* IPG to start JAM for collision based flow
+				 * control in half-duplex mode. In units of
+				 * 8-bit time */
+	u8 ipgt;		/* Desired back to back inter-packet gap.
+				 * The default is 96-bit time */
+	u8 min_ifg;		/* Minimum number of IFG to enforce in between
+				 * receive frames. Frame gap below such IFP
+				 * is dropped */
 	u8 ipgr1;		/* 64bit Carrier-Sense window */
 	u8 ipgr2;		/* 96-bit IPG window */
-	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned burst. Each TPD is 16 bytes long */
-	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned burst. Each RFD is 12 bytes long */
+	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned
+				 * burst. Each TPD is 16 bytes long */
+	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned
+				 * burst. Each RFD is 12 bytes long */
 	u8 rfd_fetch_gap;
-	u8 rrd_burst;		/* Threshold number of RRDs that can be retired in a burst. Each RRD is 16 bytes long */
+	u8 rrd_burst;		/* Threshold number of RRDs that can be retired
+				 * in a burst. Each RRD is 16 bytes long */
 	u8 tpd_fetch_th;
 	u8 tpd_fetch_gap;
 	u16 tx_jumbo_task_th;
-	u16 txf_burst;		/* Number of data bytes to read in a cache-aligned burst. Each SRAM entry is
-				   8 bytes long */
-	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN packets should add 4 bytes */
+	u16 txf_burst;		/* Number of data bytes to read in a cache-
+				 * aligned burst. Each SRAM entry is 8 bytes */
+	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN
+				 * packets should add 4 bytes */
 	u16 rx_jumbo_lkah;
-	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after every 512ns passes. */
+	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after
+				 * every 512ns passes. */
 	u16 lcol;		/* Collision Window */
 
 	u16 cmb_tpd;
@@ -194,49 +222,35 @@
 	u32 smb_timer;
 	u16 media_type;
 	u16 autoneg_advertised;
-	u16 pci_cmd_word;
 
 	u16 mii_autoneg_adv_reg;
 	u16 mii_1000t_ctrl_reg;
 
-	u32 mem_rang;
-	u32 txcw;
 	u32 max_frame_size;
 	u32 min_frame_size;
-	u32 mc_filter_type;
-	u32 num_mc_addrs;
-	u32 collision_delta;
-	u32 tx_packet_delta;
-	u16 phy_spd_default;
 
 	u16 dev_rev;
-	u8 revision_id;
 
 	/* spi flash */
 	u8 flash_vendor;
 
-	u8 dma_fairness;
 	u8 mac_addr[ETH_ALEN];
 	u8 perm_mac_addr[ETH_ALEN];
 
-	/* bool phy_preamble_sup; */
 	bool phy_configured;
 };
 
 struct atl1_adapter {
-	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
 	struct net_device_stats net_stats;
 	struct atl1_sft_stats soft_stats;
-
 	struct vlan_group *vlgrp;
 	u32 rx_buffer_len;
 	u32 wol;
 	u16 link_speed;
 	u16 link_duplex;
 	spinlock_t lock;
-	atomic_t irq_sem;
 	struct work_struct tx_timeout_task;
 	struct work_struct link_chg_task;
 	struct work_struct pcie_dma_to_rst_task;
@@ -244,9 +258,7 @@
 	struct timer_list phy_config_timer;
 	bool phy_timer_pending;
 
-	bool mac_disabled;
-
-	/* All descriptor rings' memory */
+	/* all descriptor rings' memory */
 	struct atl1_ring_header ring_header;
 
 	/* TX */
@@ -259,25 +271,16 @@
 	u64 hw_csum_err;
 	u64 hw_csum_good;
 
-	u32 gorcl;
-	u64 gorcl_old;
-
-	/* Interrupt Moderator timer ( 2us resolution) */
-	u16 imt;
-	/* Interrupt Clear timer (2us resolution) */
-	u16 ict;
-
-	/* MII interface info */
-	struct mii_if_info mii;
+	u16 imt;	/* interrupt moderator timer (2us resolution */
+	u16 ict;	/* interrupt clear timer (2us resolution */
+	struct mii_if_info mii;		/* MII interface info */
 
 	/* structs defined in atl1_hw.h */
-	u32 bd_number;		/* board number */
+	u32 bd_number;			/* board number */
 	bool pci_using_64;
 	struct atl1_hw hw;
 	struct atl1_smb smb;
 	struct atl1_cmb cmb;
-
-	u32 pci_state[16];
 };
 
 #endif	/* _ATL1_H_ */
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
index 78cf00f..fd1e156 100644
--- a/drivers/net/atl1/atl1_main.c
+++ b/drivers/net/atl1/atl1_main.c
@@ -38,7 +38,7 @@
  * TODO:
  * Fix TSO; tx performance is horrible with TSO enabled.
  * Wake on LAN.
- * Add more ethtool functions, including set ring parameters.
+ * Add more ethtool functions.
  * Fix abstruse irq enable/disable condition described here:
  *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
  *
@@ -75,6 +75,7 @@
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/mii.h>
+#include <linux/interrupt.h>
 #include <net/checksum.h>
 
 #include <asm/atomic.h>
@@ -118,10 +119,6 @@
 {
 	struct atl1_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-
-	/* PCI config space info */
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
 
 	hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
 	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
@@ -162,13 +159,70 @@
 	hw->cmb_tx_timer = 1;	/* about 2us */
 	hw->smb_timer = 100000;	/* about 200ms */
 
-	atomic_set(&adapter->irq_sem, 0);
 	spin_lock_init(&adapter->lock);
 	spin_lock_init(&adapter->mb_lock);
 
 	return 0;
 }
 
+static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	u16 result;
+
+	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+
+	return result;
+}
+
+static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
+	int val)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	atl1_write_phy_reg(&adapter->hw, reg_num, val);
+}
+
+/*
+ * atl1_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	int retval;
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+
+	return retval;
+}
+
+/*
+ * atl1_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		return atl1_mii_ioctl(netdev, ifr, cmd);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 /*
  * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
  * @adapter: board private structure
@@ -192,19 +246,22 @@
 		goto err_nomem;
 	}
 	rfd_ring->buffer_info =
-	    (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+		(struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
 
-	/* real ring DMA buffer */
-	ring_header->size = size = sizeof(struct tx_packet_desc) *
-					tpd_ring->count
-	    + sizeof(struct rx_free_desc) * rfd_ring->count
-	    + sizeof(struct rx_return_desc) * rrd_ring->count
-	    + sizeof(struct coals_msg_block)
-	    + sizeof(struct stats_msg_block)
-	    + 40;		/* "40: for 8 bytes align" huh? -- CHS */
+	/* real ring DMA buffer
+	 * each ring/block may need up to 8 bytes for alignment, hence the
+	 * additional 40 bytes tacked onto the end.
+	 */
+	ring_header->size = size =
+		sizeof(struct tx_packet_desc) * tpd_ring->count
+		+ sizeof(struct rx_free_desc) * rfd_ring->count
+		+ sizeof(struct rx_return_desc) * rrd_ring->count
+		+ sizeof(struct coals_msg_block)
+		+ sizeof(struct stats_msg_block)
+		+ 40;
 
 	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
-						&ring_header->dma);
+		&ring_header->dma);
 	if (unlikely(!ring_header->desc)) {
 		dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
 		goto err_nomem;
@@ -218,8 +275,6 @@
 	tpd_ring->dma += offset;
 	tpd_ring->desc = (u8 *) ring_header->desc + offset;
 	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
-	atomic_set(&tpd_ring->next_to_use, 0);
-	atomic_set(&tpd_ring->next_to_clean, 0);
 
 	/* init RFD ring */
 	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
@@ -227,9 +282,7 @@
 	rfd_ring->dma += offset;
 	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
 	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
-	rfd_ring->next_to_clean = 0;
-	/* rfd_ring->next_to_use = rfd_ring->count - 1; */
-	atomic_set(&rfd_ring->next_to_use, 0);
+
 
 	/* init RRD ring */
 	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
@@ -237,23 +290,22 @@
 	rrd_ring->dma += offset;
 	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
 	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
-	rrd_ring->next_to_use = 0;
-	atomic_set(&rrd_ring->next_to_clean, 0);
+
 
 	/* init CMB */
 	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
 	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
 	adapter->cmb.dma += offset;
-	adapter->cmb.cmb =
-	    (struct coals_msg_block *) ((u8 *) rrd_ring->desc +
-				   (rrd_ring->size + offset));
+	adapter->cmb.cmb = (struct coals_msg_block *)
+		((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
 
 	/* init SMB */
 	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
 	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
 	adapter->smb.dma += offset;
 	adapter->smb.smb = (struct stats_msg_block *)
-	    ((u8 *) adapter->cmb.cmb + (sizeof(struct coals_msg_block) + offset));
+		((u8 *) adapter->cmb.cmb +
+		(sizeof(struct coals_msg_block) + offset));
 
 	return ATL1_SUCCESS;
 
@@ -262,14 +314,682 @@
 	return -ENOMEM;
 }
 
+void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+
+	atomic_set(&tpd_ring->next_to_use, 0);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+
+	rfd_ring->next_to_clean = 0;
+	atomic_set(&rfd_ring->next_to_use, 0);
+
+	rrd_ring->next_to_use = 0;
+	atomic_set(&rrd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_clean_rx_ring - Free RFD Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Rx ring sk_buffs */
+	for (i = 0; i < rfd_ring->count; i++) {
+		buffer_info = &rfd_ring->buffer_info[i];
+		if (buffer_info->dma) {
+			pci_unmap_page(pdev, buffer_info->dma,
+				buffer_info->length, PCI_DMA_FROMDEVICE);
+			buffer_info->dma = 0;
+		}
+		if (buffer_info->skb) {
+			dev_kfree_skb(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+	}
+
+	size = sizeof(struct atl1_buffer) * rfd_ring->count;
+	memset(rfd_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(rfd_ring->desc, 0, rfd_ring->size);
+
+	rfd_ring->next_to_clean = 0;
+	atomic_set(&rfd_ring->next_to_use, 0);
+
+	rrd_ring->next_to_use = 0;
+	atomic_set(&rrd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Tx ring sk_buffs */
+	for (i = 0; i < tpd_ring->count; i++) {
+		buffer_info = &tpd_ring->buffer_info[i];
+		if (buffer_info->dma) {
+			pci_unmap_page(pdev, buffer_info->dma,
+				buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = 0;
+		}
+	}
+
+	for (i = 0; i < tpd_ring->count; i++) {
+		buffer_info = &tpd_ring->buffer_info[i];
+		if (buffer_info->skb) {
+			dev_kfree_skb_any(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+	}
+
+	size = sizeof(struct atl1_buffer) * tpd_ring->count;
+	memset(tpd_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(tpd_ring->desc, 0, tpd_ring->size);
+
+	atomic_set(&tpd_ring->next_to_use, 0);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+void atl1_free_ring_resources(struct atl1_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_ring_header *ring_header = &adapter->ring_header;
+
+	atl1_clean_tx_ring(adapter);
+	atl1_clean_rx_ring(adapter);
+
+	kfree(tpd_ring->buffer_info);
+	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+		ring_header->dma);
+
+	tpd_ring->buffer_info = NULL;
+	tpd_ring->desc = NULL;
+	tpd_ring->dma = 0;
+
+	rfd_ring->buffer_info = NULL;
+	rfd_ring->desc = NULL;
+	rfd_ring->dma = 0;
+
+	rrd_ring->desc = NULL;
+	rrd_ring->dma = 0;
+}
+
+static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
+{
+	u32 value;
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	/* Config MAC CTRL Register */
+	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+	/* duplex */
+	if (FULL_DUPLEX == adapter->link_duplex)
+		value |= MAC_CTRL_DUPLX;
+	/* speed */
+	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
+			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+		  MAC_CTRL_SPEED_SHIFT);
+	/* flow control */
+	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+	/* PAD & CRC */
+	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+	/* preamble length */
+	value |= (((u32) adapter->hw.preamble_len
+		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+	/* vlan */
+	if (adapter->vlgrp)
+		value |= MAC_CTRL_RMV_VLAN;
+	/* rx checksum
+	   if (adapter->rx_csum)
+	   value |= MAC_CTRL_RX_CHKSUM_EN;
+	 */
+	/* filter mode */
+	value |= MAC_CTRL_BC_EN;
+	if (netdev->flags & IFF_PROMISC)
+		value |= MAC_CTRL_PROMIS_EN;
+	else if (netdev->flags & IFF_ALLMULTI)
+		value |= MAC_CTRL_MC_ALL_EN;
+	/* value |= MAC_CTRL_LOOPBACK; */
+	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
+}
+
+/*
+ * atl1_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_set_mac(struct net_device *netdev, void *p)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+	atl1_set_mac_addr(&adapter->hw);
+	return 0;
+}
+
+static u32 atl1_check_link(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	u32 ret_val;
+	u16 speed, duplex, phy_data;
+	int reconfig = 0;
+
+	/* MII_BMSR must read twice */
+	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+	if (!(phy_data & BMSR_LSTATUS)) {	/* link down */
+		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
+			dev_info(&adapter->pdev->dev, "link is down\n");
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+		return ATL1_SUCCESS;
+	}
+
+	/* Link Up */
+	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+	if (ret_val)
+		return ret_val;
+
+	switch (hw->media_type) {
+	case MEDIA_TYPE_1000M_FULL:
+		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_100M_FULL:
+		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_100M_HALF:
+		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_10M_FULL:
+		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_10M_HALF:
+		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+			reconfig = 1;
+		break;
+	}
+
+	/* link result is our setting */
+	if (!reconfig) {
+		if (adapter->link_speed != speed
+		    || adapter->link_duplex != duplex) {
+			adapter->link_speed = speed;
+			adapter->link_duplex = duplex;
+			atl1_setup_mac_ctrl(adapter);
+			dev_info(&adapter->pdev->dev,
+				"%s link is up %d Mbps %s\n",
+				netdev->name, adapter->link_speed,
+				adapter->link_duplex == FULL_DUPLEX ?
+				"full duplex" : "half duplex");
+		}
+		if (!netif_carrier_ok(netdev)) {	/* Link down -> Up */
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+		return ATL1_SUCCESS;
+	}
+
+	/* change orignal link status */
+	if (netif_carrier_ok(netdev)) {
+		adapter->link_speed = SPEED_0;
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+	}
+
+	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
+	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
+		switch (hw->media_type) {
+		case MEDIA_TYPE_100M_FULL:
+			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+			           MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_100M_HALF:
+			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_10M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		default:	/* MEDIA_TYPE_10M_HALF: */
+			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		}
+		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+		return ATL1_SUCCESS;
+	}
+
+	/* auto-neg, insert timer to re-config phy */
+	if (!adapter->phy_timer_pending) {
+		adapter->phy_timer_pending = true;
+		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+	}
+
+	return ATL1_SUCCESS;
+}
+
+static void atl1_check_for_link(struct atl1_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	u16 phy_data = 0;
+
+	spin_lock(&adapter->lock);
+	adapter->phy_timer_pending = false;
+	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	spin_unlock(&adapter->lock);
+
+	/* notify upper layer link down ASAP */
+	if (!(phy_data & BMSR_LSTATUS)) {	/* Link Down */
+		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
+			dev_info(&adapter->pdev->dev, "%s link is down\n",
+				netdev->name);
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	}
+	schedule_work(&adapter->link_chg_task);
+}
+
+/*
+ * atl1_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1_set_multi(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	struct dev_mc_list *mc_ptr;
+	u32 rctl;
+	u32 hash_value;
+
+	/* Check for Promiscuous and All Multicast modes */
+	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+	if (netdev->flags & IFF_PROMISC)
+		rctl |= MAC_CTRL_PROMIS_EN;
+	else if (netdev->flags & IFF_ALLMULTI) {
+		rctl |= MAC_CTRL_MC_ALL_EN;
+		rctl &= ~MAC_CTRL_PROMIS_EN;
+	} else
+		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+
+	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+
+	/* clear the old settings from the multicast hash table */
+	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+	/* compute mc addresses' hash value ,and put it into hash table */
+	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+		hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
+		atl1_hash_set(hw, hash_value);
+	}
+}
+
+/*
+ * atl1_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int old_mtu = netdev->mtu;
+	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+
+	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+		return -EINVAL;
+	}
+
+	adapter->hw.max_frame_size = max_frame;
+	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+	adapter->rx_buffer_len = (max_frame + 7) & ~7;
+	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+
+	netdev->mtu = new_mtu;
+	if ((old_mtu != new_mtu) && netif_running(netdev)) {
+		atl1_down(adapter);
+		atl1_up(adapter);
+	}
+
+	return 0;
+}
+
+static void set_flow_ctrl_old(struct atl1_adapter *adapter)
+{
+	u32 hi, lo, value;
+
+	/* RFD Flow Control */
+	value = adapter->rfd_ring.count;
+	hi = value / 16;
+	if (hi < 2)
+		hi = 2;
+	lo = value * 7 / 8;
+
+	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+	/* RRD Flow Control */
+	value = adapter->rrd_ring.count;
+	lo = value / 16;
+	hi = value * 7 / 8;
+	if (lo < 2)
+		lo = 2;
+	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+static void set_flow_ctrl_new(struct atl1_hw *hw)
+{
+	u32 hi, lo, value;
+
+	/* RXF Flow Control */
+	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
+	lo = value / 16;
+	if (lo < 192)
+		lo = 192;
+	hi = value * 7 / 8;
+	if (hi < lo)
+		hi = lo + 16;
+	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+	/* RRD Flow Control */
+	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
+	lo = value / 8;
+	hi = value * 7 / 8;
+	if (lo < 2)
+		lo = 2;
+	if (hi < lo)
+		hi = lo + 3;
+	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+/*
+ * atl1_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static u32 atl1_configure(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	u32 value;
+
+	/* clear interrupt status */
+	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+
+	/* set MAC Address */
+	value = (((u32) hw->mac_addr[2]) << 24) |
+		(((u32) hw->mac_addr[3]) << 16) |
+		(((u32) hw->mac_addr[4]) << 8) |
+		(((u32) hw->mac_addr[5]));
+	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+
+	/* tx / rx ring */
+
+	/* HI base address */
+	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
+		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
+	/* LO base address */
+	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
+	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
+	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
+	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
+	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
+
+	/* element count */
+	value = adapter->rrd_ring.count;
+	value <<= 16;
+	value += adapter->rfd_ring.count;
+	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
+	iowrite32(adapter->tpd_ring.count, hw->hw_addr +
+		REG_DESC_TPD_RING_SIZE);
+
+	/* Load Ptr */
+	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+
+	/* config Mailbox */
+	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
+		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
+		((atomic_read(&adapter->rrd_ring.next_to_clean)
+		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+		((atomic_read(&adapter->rfd_ring.next_to_use)
+		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAILBOX);
+
+	/* config IPG/IFG */
+	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
+		 << MAC_IPG_IFG_IPGT_SHIFT) |
+		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+		<< MAC_IPG_IFG_MIFG_SHIFT) |
+		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+		<< MAC_IPG_IFG_IPGR1_SHIFT) |
+		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+		<< MAC_IPG_IFG_IPGR2_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
+
+	/* config  Half-Duplex Control */
+	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
+
+	/* set Interrupt Moderator Timer */
+	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
+	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
+
+	/* set Interrupt Clear Timer */
+	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+
+	/* set MTU, 4 : VLAN */
+	iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU);
+
+	/* jumbo size & rrd retirement timer */
+	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
+		 << RXQ_JMBOSZ_TH_SHIFT) |
+		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+		<< RXQ_JMBO_LKAH_SHIFT) |
+		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+		<< RXQ_RRD_TIMER_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
+
+	/* Flow Control */
+	switch (hw->dev_rev) {
+	case 0x8001:
+	case 0x9001:
+	case 0x9002:
+	case 0x9003:
+		set_flow_ctrl_old(adapter);
+		break;
+	default:
+		set_flow_ctrl_new(hw);
+		break;
+	}
+
+	/* config TXQ */
+	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
+		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
+		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
+		TXQ_CTRL_EN;
+	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
+
+	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
+	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
+		<< TX_JUMBO_TASK_TH_SHIFT) |
+		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+		<< TX_TPD_MIN_IPG_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
+
+	/* config RXQ */
+	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
+		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
+		RXQ_CTRL_EN;
+	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
+
+	/* config DMA Engine */
+	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+		((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
+		DMA_CTRL_DMAW_EN;
+	value |= (u32) hw->dma_ord;
+	if (atl1_rcb_128 == hw->rcb_value)
+		value |= DMA_CTRL_RCB_VALUE;
+	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
+
+	/* config CMB / SMB */
+	value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16);
+	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
+	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
+	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
+	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
+
+	/* --- enable CMB / SMB */
+	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
+	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
+
+	value = ioread32(adapter->hw.hw_addr + REG_ISR);
+	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
+		value = 1;	/* config failed */
+	else
+		value = 0;
+
+	/* clear all interrupt status */
+	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
+	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
+	return value;
+}
+
+/*
+ * atl1_pcie_patch - Patch for PCIE module
+ */
+static void atl1_pcie_patch(struct atl1_adapter *adapter)
+{
+	u32 value;
+
+	/* much vendor magic here */
+	value = 0x6500;
+	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+	/* pcie flow control mode change */
+	value = ioread32(adapter->hw.hw_addr + 0x1008);
+	value |= 0x8000;
+	iowrite32(value, adapter->hw.hw_addr + 0x1008);
+}
+
+/*
+ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+ * on PCI Command register is disable.
+ * The function enable this bit.
+ * Brackett, 2006/03/15
+ */
+static void atl1_via_workaround(struct atl1_adapter *adapter)
+{
+	unsigned long value;
+
+	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+	if (value & PCI_COMMAND_INTX_DISABLE)
+		value &= ~PCI_COMMAND_INTX_DISABLE;
+	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+}
+
 /*
  * atl1_irq_enable - Enable default interrupt generation settings
  * @adapter: board private structure
  */
 static void atl1_irq_enable(struct atl1_adapter *adapter)
 {
-	if (likely(!atomic_dec_and_test(&adapter->irq_sem)))
-		iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+	iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+	ioread32(adapter->hw.hw_addr + REG_IMR);
+}
+
+/*
+ * atl1_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static void atl1_irq_disable(struct atl1_adapter *adapter)
+{
+	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+	ioread32(adapter->hw.hw_addr + REG_IMR);
+	synchronize_irq(adapter->pdev->irq);
 }
 
 static void atl1_clear_phy_int(struct atl1_adapter *adapter)
@@ -292,25 +1012,19 @@
 	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
 	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
 	adapter->soft_stats.multicast += smb->rx_mcast;
-	adapter->soft_stats.collisions += (smb->tx_1_col +
-					   smb->tx_2_col * 2 +
-					   smb->tx_late_col +
-					   smb->tx_abort_col *
-					   adapter->hw.max_retry);
+	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
+		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
 
 	/* Rx Errors */
-	adapter->soft_stats.rx_errors += (smb->rx_frag +
-					  smb->rx_fcs_err +
-					  smb->rx_len_err +
-					  smb->rx_sz_ov +
-					  smb->rx_rxf_ov +
-					  smb->rx_rrd_ov + smb->rx_align_err);
+	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
+		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
+		smb->rx_rrd_ov + smb->rx_align_err);
 	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
 	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
 	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
 	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
 	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
-						 smb->rx_rxf_ov);
+		smb->rx_rxf_ov);
 
 	adapter->soft_stats.rx_pause += smb->rx_pause;
 	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
@@ -318,8 +1032,7 @@
 
 	/* Tx Errors */
 	adapter->soft_stats.tx_errors += (smb->tx_late_col +
-					  smb->tx_abort_col +
-					  smb->tx_underrun + smb->tx_trunc);
+		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
 	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
 	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
 	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
@@ -341,36 +1054,101 @@
 	adapter->net_stats.collisions = adapter->soft_stats.collisions;
 	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
 	adapter->net_stats.rx_over_errors =
-	    adapter->soft_stats.rx_missed_errors;
+		adapter->soft_stats.rx_missed_errors;
 	adapter->net_stats.rx_length_errors =
-	    adapter->soft_stats.rx_length_errors;
+		adapter->soft_stats.rx_length_errors;
 	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
 	adapter->net_stats.rx_frame_errors =
-	    adapter->soft_stats.rx_frame_errors;
+		adapter->soft_stats.rx_frame_errors;
 	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
 	adapter->net_stats.rx_missed_errors =
-	    adapter->soft_stats.rx_missed_errors;
+		adapter->soft_stats.rx_missed_errors;
 	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
 	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
 	adapter->net_stats.tx_aborted_errors =
-	    adapter->soft_stats.tx_aborted_errors;
+		adapter->soft_stats.tx_aborted_errors;
 	adapter->net_stats.tx_window_errors =
-	    adapter->soft_stats.tx_window_errors;
+		adapter->soft_stats.tx_window_errors;
 	adapter->net_stats.tx_carrier_errors =
-	    adapter->soft_stats.tx_carrier_errors;
+		adapter->soft_stats.tx_carrier_errors;
+}
+
+/*
+ * atl1_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	return &adapter->net_stats;
+}
+
+static void atl1_update_mailbox(struct atl1_adapter *adapter)
+{
+	unsigned long flags;
+	u32 tpd_next_to_use;
+	u32 rfd_next_to_use;
+	u32 rrd_next_to_clean;
+	u32 value;
+
+	spin_lock_irqsave(&adapter->mb_lock, flags);
+
+	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+
+	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+		MB_RFD_PROD_INDX_SHIFT) |
+		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+		MB_RRD_CONS_INDX_SHIFT) |
+		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+		MB_TPD_PROD_INDX_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+
+	spin_unlock_irqrestore(&adapter->mb_lock, flags);
+}
+
+static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
+	struct rx_return_desc *rrd, u16 offset)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+
+	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
+		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
+		if (++rfd_ring->next_to_clean == rfd_ring->count) {
+			rfd_ring->next_to_clean = 0;
+		}
+	}
+}
+
+static void atl1_update_rfd_index(struct atl1_adapter *adapter,
+	struct rx_return_desc *rrd)
+{
+	u16 num_buf;
+
+	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
+		adapter->rx_buffer_len;
+	if (rrd->num_buf == num_buf)
+		/* clean alloc flag for bad rrd */
+		atl1_clean_alloc_flag(adapter, rrd, num_buf);
 }
 
 static void atl1_rx_checksum(struct atl1_adapter *adapter,
-					struct rx_return_desc *rrd,
-					struct sk_buff *skb)
+	struct rx_return_desc *rrd, struct sk_buff *skb)
 {
+	struct pci_dev *pdev = adapter->pdev;
+
 	skb->ip_summed = CHECKSUM_NONE;
 
 	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
 		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
 					ERR_FLAG_CODE | ERR_FLAG_OV)) {
 			adapter->hw_csum_err++;
-			dev_dbg(&adapter->pdev->dev, "rx checksum error\n");
+			dev_printk(KERN_DEBUG, &pdev->dev,
+				"rx checksum error\n");
 			return;
 		}
 	}
@@ -389,7 +1167,7 @@
 	}
 
 	/* IPv4, but hardware thinks its checksum is wrong */
-	dev_dbg(&adapter->pdev->dev,
+	dev_printk(KERN_DEBUG, &pdev->dev,
 		"hw csum wrong, pkt_flag:%x, err_flag:%x\n",
 		rrd->pkt_flg, rrd->err_flg);
 	skb->ip_summed = CHECKSUM_COMPLETE;
@@ -504,34 +1282,17 @@
 			/* rrd seems to be bad */
 			if (unlikely(i-- > 0)) {
 				/* rrd may not be DMAed completely */
-				dev_dbg(&adapter->pdev->dev,
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
 					"incomplete RRD DMA transfer\n");
 				udelay(1);
 				goto chk_rrd;
 			}
 			/* bad rrd */
-			dev_dbg(&adapter->pdev->dev, "bad RRD\n");
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+				"bad RRD\n");
 			/* see if update RFD index */
-			if (rrd->num_buf > 1) {
-				u16 num_buf;
-				num_buf =
-				    (rrd->xsz.xsum_sz.pkt_size +
-				     adapter->rx_buffer_len -
-				     1) / adapter->rx_buffer_len;
-				if (rrd->num_buf == num_buf) {
-					/* clean alloc flag for bad rrd */
-					while (rfd_ring->next_to_clean !=
-					       (rrd->buf_indx + num_buf)) {
-						rfd_ring->buffer_info[rfd_ring->
-								      next_to_clean].alloced = 0;
-						if (++rfd_ring->next_to_clean ==
-						    rfd_ring->count) {
-							rfd_ring->
-							    next_to_clean = 0;
-						}
-					}
-				}
-			}
+			if (rrd->num_buf > 1)
+				atl1_update_rfd_index(adapter, rrd);
 
 			/* update rrd */
 			rrd->xsz.valid = 0;
@@ -545,12 +1306,7 @@
 		}
 rrd_ok:
 		/* clean alloc flag for bad rrd */
-		while (rfd_ring->next_to_clean != rrd->buf_indx) {
-			rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced =
-			    0;
-			if (++rfd_ring->next_to_clean == rfd_ring->count)
-				rfd_ring->next_to_clean = 0;
-		}
+		atl1_clean_alloc_flag(adapter, rrd, 0);
 
 		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
 		if (++rfd_ring->next_to_clean == rfd_ring->count)
@@ -634,14 +1390,13 @@
 	struct atl1_buffer *buffer_info;
 	u16 sw_tpd_next_to_clean;
 	u16 cmb_tpd_next_to_clean;
-	u8 update = 0;
 
 	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
 	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
 
 	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
 		struct tx_packet_desc *tpd;
-		update = 1;
+
 		tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
 		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
 		if (buffer_info->dma) {
@@ -667,610 +1422,13 @@
 		netif_wake_queue(adapter->netdev);
 }
 
-static void atl1_check_for_link(struct atl1_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u16 phy_data = 0;
-
-	spin_lock(&adapter->lock);
-	adapter->phy_timer_pending = false;
-	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	spin_unlock(&adapter->lock);
-
-	/* notify upper layer link down ASAP */
-	if (!(phy_data & BMSR_LSTATUS)) {	/* Link Down */
-		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
-			dev_info(&adapter->pdev->dev, "%s link is down\n",
-				netdev->name);
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-	}
-	schedule_work(&adapter->link_chg_task);
-}
-
-/*
- * atl1_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
- */
-static irqreturn_t atl1_intr(int irq, void *data)
-{
-	/*struct atl1_adapter *adapter = ((struct net_device *)data)->priv;*/
-	struct atl1_adapter *adapter = netdev_priv(data);
-	u32 status;
-	u8 update_rx;
-	int max_ints = 10;
-
-	status = adapter->cmb.cmb->int_stats;
-	if (!status)
-		return IRQ_NONE;
-
-	update_rx = 0;
-
-	do {
-		/* clear CMB interrupt status at once */
-		adapter->cmb.cmb->int_stats = 0;
-
-		if (status & ISR_GPHY)	/* clear phy status */
-			atl1_clear_phy_int(adapter);
-
-		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
-		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
-
-		/* check if SMB intr */
-		if (status & ISR_SMB)
-			atl1_inc_smb(adapter);
-
-		/* check if PCIE PHY Link down */
-		if (status & ISR_PHY_LINKDOWN) {
-			dev_dbg(&adapter->pdev->dev, "pcie phy link down %x\n",
-				status);
-			if (netif_running(adapter->netdev)) {	/* reset MAC */
-				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-				schedule_work(&adapter->pcie_dma_to_rst_task);
-				return IRQ_HANDLED;
-			}
-		}
-
-		/* check if DMA read/write error ? */
-		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
-			dev_dbg(&adapter->pdev->dev,
-				"pcie DMA r/w error (status = 0x%x)\n",
-				status);
-			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-			schedule_work(&adapter->pcie_dma_to_rst_task);
-			return IRQ_HANDLED;
-		}
-
-		/* link event */
-		if (status & ISR_GPHY) {
-			adapter->soft_stats.tx_carrier_errors++;
-			atl1_check_for_link(adapter);
-		}
-
-		/* transmit event */
-		if (status & ISR_CMB_TX)
-			atl1_intr_tx(adapter);
-
-		/* rx exception */
-		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
-			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-				ISR_HOST_RRD_OV))
-				dev_dbg(&adapter->pdev->dev,
-					"rx exception, ISR = 0x%x\n", status);
-			atl1_intr_rx(adapter);
-		}
-
-		if (--max_ints < 0)
-			break;
-
-	} while ((status = adapter->cmb.cmb->int_stats));
-
-	/* re-enable Interrupt */
-	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
-	return IRQ_HANDLED;
-}
-
-/*
- * atl1_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
- */
-static void atl1_set_multi(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	struct dev_mc_list *mc_ptr;
-	u32 rctl;
-	u32 hash_value;
-
-	/* Check for Promiscuous and All Multicast modes */
-	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
-	if (netdev->flags & IFF_PROMISC)
-		rctl |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI) {
-		rctl |= MAC_CTRL_MC_ALL_EN;
-		rctl &= ~MAC_CTRL_PROMIS_EN;
-	} else
-		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
-
-	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
-
-	/* clear the old settings from the multicast hash table */
-	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
-	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
-
-	/* compute mc addresses' hash value ,and put it into hash table */
-	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
-		hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
-		atl1_hash_set(hw, hash_value);
-	}
-}
-
-static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
-{
-	u32 value;
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	/* Config MAC CTRL Register */
-	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
-	/* duplex */
-	if (FULL_DUPLEX == adapter->link_duplex)
-		value |= MAC_CTRL_DUPLX;
-	/* speed */
-	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
-			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
-		  MAC_CTRL_SPEED_SHIFT);
-	/* flow control */
-	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-	/* PAD & CRC */
-	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-	/* preamble length */
-	value |= (((u32) adapter->hw.preamble_len
-		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-	/* vlan */
-	if (adapter->vlgrp)
-		value |= MAC_CTRL_RMV_VLAN;
-	/* rx checksum
-	   if (adapter->rx_csum)
-	   value |= MAC_CTRL_RX_CHKSUM_EN;
-	 */
-	/* filter mode */
-	value |= MAC_CTRL_BC_EN;
-	if (netdev->flags & IFF_PROMISC)
-		value |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI)
-		value |= MAC_CTRL_MC_ALL_EN;
-	/* value |= MAC_CTRL_LOOPBACK; */
-	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
-}
-
-static u32 atl1_check_link(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 ret_val;
-	u16 speed, duplex, phy_data;
-	int reconfig = 0;
-
-	/* MII_BMSR must read twice */
-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
-	if (!(phy_data & BMSR_LSTATUS)) {	/* link down */
-		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
-			dev_info(&adapter->pdev->dev, "link is down\n");
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-		return ATL1_SUCCESS;
-	}
-
-	/* Link Up */
-	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
-	if (ret_val)
-		return ret_val;
-
-	switch (hw->media_type) {
-	case MEDIA_TYPE_1000M_FULL:
-		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_FULL:
-		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_HALF:
-		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_FULL:
-		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_HALF:
-		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	}
-
-	/* link result is our setting */
-	if (!reconfig) {
-		if (adapter->link_speed != speed
-		    || adapter->link_duplex != duplex) {
-			adapter->link_speed = speed;
-			adapter->link_duplex = duplex;
-			atl1_setup_mac_ctrl(adapter);
-			dev_info(&adapter->pdev->dev,
-				"%s link is up %d Mbps %s\n",
-				netdev->name, adapter->link_speed,
-				adapter->link_duplex == FULL_DUPLEX ?
-				"full duplex" : "half duplex");
-		}
-		if (!netif_carrier_ok(netdev)) {	/* Link down -> Up */
-			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
-		}
-		return ATL1_SUCCESS;
-	}
-
-	/* change orignal link status */
-	if (netif_carrier_ok(netdev)) {
-		adapter->link_speed = SPEED_0;
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-	}
-
-	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
-	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
-		switch (hw->media_type) {
-		case MEDIA_TYPE_100M_FULL:
-			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
-			           MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_100M_HALF:
-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_10M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		default:	/* MEDIA_TYPE_10M_HALF: */
-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		}
-		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-		return ATL1_SUCCESS;
-	}
-
-	/* auto-neg, insert timer to re-config phy */
-	if (!adapter->phy_timer_pending) {
-		adapter->phy_timer_pending = true;
-		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
-	}
-
-	return ATL1_SUCCESS;
-}
-
-static void set_flow_ctrl_old(struct atl1_adapter *adapter)
-{
-	u32 hi, lo, value;
-
-	/* RFD Flow Control */
-	value = adapter->rfd_ring.count;
-	hi = value / 16;
-	if (hi < 2)
-		hi = 2;
-	lo = value * 7 / 8;
-
-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-	    ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
-
-	/* RRD Flow Control */
-	value = adapter->rrd_ring.count;
-	lo = value / 16;
-	hi = value * 7 / 8;
-	if (lo < 2)
-		lo = 2;
-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
-	    ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
-}
-
-static void set_flow_ctrl_new(struct atl1_hw *hw)
-{
-	u32 hi, lo, value;
-
-	/* RXF Flow Control */
-	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
-	lo = value / 16;
-	if (lo < 192)
-		lo = 192;
-	hi = value * 7 / 8;
-	if (hi < lo)
-		hi = lo + 16;
-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-	    ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
-
-	/* RRD Flow Control */
-	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
-	lo = value / 8;
-	hi = value * 7 / 8;
-	if (lo < 2)
-		lo = 2;
-	if (hi < lo)
-		hi = lo + 3;
-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
-	    ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
-}
-
-/*
- * atl1_configure - Configure Transmit&Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx /Rx unit of the MAC after a reset.
- */
-static u32 atl1_configure(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	u32 value;
-
-	/* clear interrupt status */
-	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
-
-	/* set MAC Address */
-	value = (((u32) hw->mac_addr[2]) << 24) |
-		(((u32) hw->mac_addr[3]) << 16) |
-		(((u32) hw->mac_addr[4]) << 8) |
-		(((u32) hw->mac_addr[5]));
-	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
-	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
-	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
-
-	/* tx / rx ring */
-
-	/* HI base address */
-	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
-		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
-	/* LO base address */
-	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
-	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
-	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
-	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
-	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
-
-	/* element count */
-	value = adapter->rrd_ring.count;
-	value <<= 16;
-	value += adapter->rfd_ring.count;
-	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
-	iowrite32(adapter->tpd_ring.count, hw->hw_addr + REG_DESC_TPD_RING_SIZE);
-
-	/* Load Ptr */
-	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
-
-	/* config Mailbox */
-	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
-		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
-	    ((atomic_read(&adapter->rrd_ring.next_to_clean)
-	      & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
-	    ((atomic_read(&adapter->rfd_ring.next_to_use)
-	      & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAILBOX);
-
-	/* config IPG/IFG */
-	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
-		 << MAC_IPG_IFG_IPGT_SHIFT) |
-	    (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
-	     << MAC_IPG_IFG_MIFG_SHIFT) |
-	    (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
-	     << MAC_IPG_IFG_IPGR1_SHIFT) |
-	    (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
-	     << MAC_IPG_IFG_IPGR2_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
-
-	/* config  Half-Duplex Control */
-	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
-	    (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
-	     << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
-	    MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
-	    (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
-	    (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
-	     << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
-
-	/* set Interrupt Moderator Timer */
-	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
-	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
-
-	/* set Interrupt Clear Timer */
-	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
-
-	/* set MTU, 4 : VLAN */
-	iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU);
-
-	/* jumbo size & rrd retirement timer */
-	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
-		 << RXQ_JMBOSZ_TH_SHIFT) |
-	    (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
-	     << RXQ_JMBO_LKAH_SHIFT) |
-	    (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
-	     << RXQ_RRD_TIMER_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
-
-	/* Flow Control */
-	switch (hw->dev_rev) {
-	case 0x8001:
-	case 0x9001:
-	case 0x9002:
-	case 0x9003:
-		set_flow_ctrl_old(adapter);
-		break;
-	default:
-		set_flow_ctrl_new(hw);
-		break;
-	}
-
-	/* config TXQ */
-	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
-		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
-	    (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
-	     << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
-	    (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
-	     << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN;
-	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
-
-	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
-	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
-		 << TX_JUMBO_TASK_TH_SHIFT) |
-	    (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
-	     << TX_TPD_MIN_IPG_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
-
-	/* config RXQ */
-	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
-		 << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
-	    (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
-	     << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
-	    (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
-	     << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) |
-	    RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
-	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
-
-	/* config DMA Engine */
-	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
-		 << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
-	    ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
-	     << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
-	    DMA_CTRL_DMAR_EN | DMA_CTRL_DMAW_EN;
-	value |= (u32) hw->dma_ord;
-	if (atl1_rcb_128 == hw->rcb_value)
-		value |= DMA_CTRL_RCB_VALUE;
-	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
-
-	/* config CMB / SMB */
-	value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16);
-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
-	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
-	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
-
-	/* --- enable CMB / SMB */
-	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
-	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
-
-	value = ioread32(adapter->hw.hw_addr + REG_ISR);
-	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
-		value = 1;	/* config failed */
-	else
-		value = 0;
-
-	/* clear all interrupt status */
-	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
-	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
-	return value;
-}
-
-/*
- * atl1_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- */
-static void atl1_irq_disable(struct atl1_adapter *adapter)
-{
-	atomic_inc(&adapter->irq_sem);
-	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-	ioread32(adapter->hw.hw_addr + REG_IMR);
-	synchronize_irq(adapter->pdev->irq);
-}
-
-static void atl1_vlan_rx_register(struct net_device *netdev,
-				struct vlan_group *grp)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	u32 ctrl;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	/* atl1_irq_disable(adapter); */
-	adapter->vlgrp = grp;
-
-	if (grp) {
-		/* enable VLAN tag insert/strip */
-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-		ctrl |= MAC_CTRL_RMV_VLAN;
-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	} else {
-		/* disable VLAN tag insert/strip */
-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-		ctrl &= ~MAC_CTRL_RMV_VLAN;
-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	}
-
-	/* atl1_irq_enable(adapter); */
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-/* FIXME: justify or remove -- CHS */
-static void atl1_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
-	/* We don't do Vlan filtering */
-	return;
-}
-
-/* FIXME: this looks wrong too -- CHS */
-static void atl1_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	/* atl1_irq_disable(adapter); */
-	vlan_group_set_device(adapter->vlgrp, vid, NULL);
-	/* atl1_irq_enable(adapter); */
-	spin_unlock_irqrestore(&adapter->lock, flags);
-	/* We don't do Vlan filtering */
-	return;
-}
-
-static void atl1_restore_vlan(struct atl1_adapter *adapter)
-{
-	atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
-	if (adapter->vlgrp) {
-		u16 vid;
-		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
-			if (!vlan_group_get_device(adapter->vlgrp, vid))
-				continue;
-			atl1_vlan_rx_add_vid(adapter->netdev, vid);
-		}
-	}
-}
-
 static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring)
 {
 	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
 	u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
-	return ((next_to_clean >
-		 next_to_use) ? next_to_clean - next_to_use -
-		1 : tpd_ring->count + next_to_clean - next_to_use - 1);
+	return ((next_to_clean > next_to_use) ?
+		next_to_clean - next_to_use - 1 :
+		tpd_ring->count + next_to_clean - next_to_use - 1);
 }
 
 static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
@@ -1293,9 +1451,7 @@
 			iph->tot_len = 0;
 			iph->check = 0;
 			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-								 iph->daddr, 0,
-								 IPPROTO_TCP,
-								 0);
+				iph->daddr, 0, IPPROTO_TCP, 0);
 			ipofst = skb_network_offset(skb);
 			if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */
 				tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
@@ -1303,7 +1459,8 @@
 			tso->tsopl |= (iph->ihl &
 				CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
 			tso->tsopl |= (tcp_hdrlen(skb) &
-				TSO_PARAM_TCPHDRLEN_MASK) << TSO_PARAM_TCPHDRLEN_SHIFT;
+				TSO_PARAM_TCPHDRLEN_MASK) <<
+				TSO_PARAM_TCPHDRLEN_SHIFT;
 			tso->tsopl |= (skb_shinfo(skb)->gso_size &
 				TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT;
 			tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT;
@@ -1316,7 +1473,7 @@
 }
 
 static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
-			struct csum_param *csum)
+	struct csum_param *csum)
 {
 	u8 css, cso;
 
@@ -1324,7 +1481,7 @@
 		cso = skb_transport_offset(skb);
 		css = cso + skb->csum_offset;
 		if (unlikely(cso & 0x1)) {
-			dev_dbg(&adapter->pdev->dev,
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
 				"payload offset not an even number\n");
 			return -1;
 		}
@@ -1339,8 +1496,8 @@
 	return true;
 }
 
-static void atl1_tx_map(struct atl1_adapter *adapter,
-				struct sk_buff *skb, bool tcp_seg)
+static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+	bool tcp_seg)
 {
 	/* We enter this function holding a spinlock. */
 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
@@ -1377,26 +1534,25 @@
 
 		if (first_buf_len > proto_hdr_len) {
 			len12 = first_buf_len - proto_hdr_len;
-			m = (len12 + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+			m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) /
+				ATL1_MAX_TX_BUF_LEN;
 			for (i = 0; i < m; i++) {
 				buffer_info =
 				    &tpd_ring->buffer_info[tpd_next_to_use];
 				buffer_info->skb = NULL;
 				buffer_info->length =
-				    (MAX_TX_BUF_LEN >=
-				     len12) ? MAX_TX_BUF_LEN : len12;
+				    (ATL1_MAX_TX_BUF_LEN >=
+				     len12) ? ATL1_MAX_TX_BUF_LEN : len12;
 				len12 -= buffer_info->length;
 				page = virt_to_page(skb->data +
-						 (proto_hdr_len +
-						  i * MAX_TX_BUF_LEN));
+					(proto_hdr_len +
+					i * ATL1_MAX_TX_BUF_LEN));
 				offset = (unsigned long)(skb->data +
-							(proto_hdr_len +
-							i * MAX_TX_BUF_LEN)) &
-							~PAGE_MASK;
-				buffer_info->dma =
-				    pci_map_page(adapter->pdev, page, offset,
-						 buffer_info->length,
-						 PCI_DMA_TODEVICE);
+					(proto_hdr_len +
+					i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK;
+				buffer_info->dma = pci_map_page(adapter->pdev,
+					page, offset, buffer_info->length,
+					PCI_DMA_TODEVICE);
 				if (++tpd_next_to_use == tpd_ring->count)
 					tpd_next_to_use = 0;
 			}
@@ -1407,8 +1563,7 @@
 		page = virt_to_page(skb->data);
 		offset = (unsigned long)skb->data & ~PAGE_MASK;
 		buffer_info->dma = pci_map_page(adapter->pdev, page,
-						offset, first_buf_len,
-						PCI_DMA_TODEVICE);
+			offset, first_buf_len, PCI_DMA_TODEVICE);
 		if (++tpd_next_to_use == tpd_ring->count)
 			tpd_next_to_use = 0;
 	}
@@ -1420,19 +1575,19 @@
 		frag = &skb_shinfo(skb)->frags[f];
 		lenf = frag->size;
 
-		m = (lenf + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+		m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN;
 		for (i = 0; i < m; i++) {
 			buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
 			if (unlikely(buffer_info->skb))
 				BUG();
 			buffer_info->skb = NULL;
-			buffer_info->length =
-			    (lenf > MAX_TX_BUF_LEN) ? MAX_TX_BUF_LEN : lenf;
+			buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ?
+				ATL1_MAX_TX_BUF_LEN : lenf;
 			lenf -= buffer_info->length;
-			buffer_info->dma =
-			    pci_map_page(adapter->pdev, frag->page,
-					 frag->page_offset + i * MAX_TX_BUF_LEN,
-					 buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = pci_map_page(adapter->pdev,
+				frag->page,
+				frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
+				buffer_info->length, PCI_DMA_TODEVICE);
 
 			if (++tpd_next_to_use == tpd_ring->count)
 				tpd_next_to_use = 0;
@@ -1444,7 +1599,7 @@
 }
 
 static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
-			       union tpd_descr *descr)
+       union tpd_descr *descr)
 {
 	/* We enter this function holding a spinlock. */
 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
@@ -1488,31 +1643,6 @@
 	atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use);
 }
 
-static void atl1_update_mailbox(struct atl1_adapter *adapter)
-{
-	unsigned long flags;
-	u32 tpd_next_to_use;
-	u32 rfd_next_to_use;
-	u32 rrd_next_to_clean;
-	u32 value;
-
-	spin_lock_irqsave(&adapter->mb_lock, flags);
-
-	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
-	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
-	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
-
-	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
-		MB_RFD_PROD_INDX_SHIFT) |
-		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
-		MB_RRD_CONS_INDX_SHIFT) |
-		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
-		MB_TPD_PROD_INDX_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
-
-	spin_unlock_irqrestore(&adapter->mb_lock, flags);
-}
-
 static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct atl1_adapter *adapter = netdev_priv(netdev);
@@ -1548,8 +1678,8 @@
 	for (f = 0; f < nr_frags; f++) {
 		frag_size = skb_shinfo(skb)->frags[f].size;
 		if (frag_size)
-			count +=
-			    (frag_size + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+			count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
+				ATL1_MAX_TX_BUF_LEN;
 	}
 
 	/* mss will be nonzero if we're doing segment offload (TSO/GSO) */
@@ -1565,7 +1695,8 @@
 			/* need additional TPD ? */
 			if (proto_hdr_len != len)
 				count += (len - proto_hdr_len +
-					MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+					ATL1_MAX_TX_BUF_LEN - 1) /
+					ATL1_MAX_TX_BUF_LEN;
 		}
 	}
 
@@ -1573,7 +1704,7 @@
 	if (!spin_trylock(&adapter->lock)) {
 		/* Can't get lock - tell upper layer to requeue */
 		local_irq_restore(flags);
-		dev_dbg(&adapter->pdev->dev, "tx locked\n");
+		dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx locked\n");
 		return NETDEV_TX_LOCKED;
 	}
 
@@ -1581,7 +1712,7 @@
 		/* not enough descriptors */
 		netif_stop_queue(netdev);
 		spin_unlock_irqrestore(&adapter->lock, flags);
-		dev_dbg(&adapter->pdev->dev, "tx busy\n");
+		dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx busy\n");
 		return NETDEV_TX_BUSY;
 	}
 
@@ -1623,131 +1754,208 @@
 }
 
 /*
- * atl1_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
+ * atl1_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
  */
-static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
+static irqreturn_t atl1_intr(int irq, void *data)
+{
+	struct atl1_adapter *adapter = netdev_priv(data);
+	u32 status;
+	u8 update_rx;
+	int max_ints = 10;
+
+	status = adapter->cmb.cmb->int_stats;
+	if (!status)
+		return IRQ_NONE;
+
+	update_rx = 0;
+
+	do {
+		/* clear CMB interrupt status at once */
+		adapter->cmb.cmb->int_stats = 0;
+
+		if (status & ISR_GPHY)	/* clear phy status */
+			atl1_clear_phy_int(adapter);
+
+		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+
+		/* check if SMB intr */
+		if (status & ISR_SMB)
+			atl1_inc_smb(adapter);
+
+		/* check if PCIE PHY Link down */
+		if (status & ISR_PHY_LINKDOWN) {
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+				"pcie phy link down %x\n", status);
+			if (netif_running(adapter->netdev)) {	/* reset MAC */
+				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+				schedule_work(&adapter->pcie_dma_to_rst_task);
+				return IRQ_HANDLED;
+			}
+		}
+
+		/* check if DMA read/write error ? */
+		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+				"pcie DMA r/w error (status = 0x%x)\n",
+				status);
+			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+			schedule_work(&adapter->pcie_dma_to_rst_task);
+			return IRQ_HANDLED;
+		}
+
+		/* link event */
+		if (status & ISR_GPHY) {
+			adapter->soft_stats.tx_carrier_errors++;
+			atl1_check_for_link(adapter);
+		}
+
+		/* transmit event */
+		if (status & ISR_CMB_TX)
+			atl1_intr_tx(adapter);
+
+		/* rx exception */
+		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+				ISR_HOST_RRD_OV))
+				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+					"rx exception, ISR = 0x%x\n", status);
+			atl1_intr_rx(adapter);
+		}
+
+		if (--max_ints < 0)
+			break;
+
+	} while ((status = adapter->cmb.cmb->int_stats));
+
+	/* re-enable Interrupt */
+	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+	return IRQ_HANDLED;
+}
+
+/*
+ * atl1_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_watchdog(unsigned long data)
+{
+	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+
+	/* Reset the timer */
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+/*
+ * atl1_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_phy_config(unsigned long data)
+{
+	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+	struct atl1_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	adapter->phy_timer_pending = false;
+	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+	atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
+	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+/*
+ * atl1_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1_tx_timeout(struct net_device *netdev)
 {
 	struct atl1_adapter *adapter = netdev_priv(netdev);
-	return &adapter->net_stats;
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->tx_timeout_task);
 }
 
 /*
- * atl1_clean_rx_ring - Free RFD Buffers
- * @adapter: board private structure
+ * Orphaned vendor comment left intact here:
+ * <vendor comment>
+ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+ * will assert. We do soft reset <0x1400=1> according
+ * with the SPEC. BUT, it seemes that PCIE or DMA
+ * state-machine will not be reset. DMAR_TO_INT will
+ * assert again and again.
+ * </vendor comment>
  */
-static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+static void atl1_tx_timeout_task(struct work_struct *work)
 {
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
+	struct atl1_adapter *adapter =
+		container_of(work, struct atl1_adapter, tx_timeout_task);
+	struct net_device *netdev = adapter->netdev;
 
-	/* Free all the Rx ring sk_buffs */
-	for (i = 0; i < rfd_ring->count; i++) {
-		buffer_info = &rfd_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			pci_unmap_page(pdev,
-					buffer_info->dma,
-					buffer_info->length,
-					PCI_DMA_FROMDEVICE);
-			buffer_info->dma = 0;
-		}
-		if (buffer_info->skb) {
-			dev_kfree_skb(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	size = sizeof(struct atl1_buffer) * rfd_ring->count;
-	memset(rfd_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(rfd_ring->desc, 0, rfd_ring->size);
-
-	rfd_ring->next_to_clean = 0;
-	atomic_set(&rfd_ring->next_to_use, 0);
-
-	rrd_ring->next_to_use = 0;
-	atomic_set(&rrd_ring->next_to_clean, 0);
+	netif_device_detach(netdev);
+	atl1_down(adapter);
+	atl1_up(adapter);
+	netif_device_attach(netdev);
 }
 
 /*
- * atl1_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
+ * atl1_link_chg_task - deal with link change event Out of interrupt context
  */
-static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+static void atl1_link_chg_task(struct work_struct *work)
 {
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
+	struct atl1_adapter *adapter =
+               container_of(work, struct atl1_adapter, link_chg_task);
+	unsigned long flags;
 
-	/* Free all the Tx ring sk_buffs */
-	for (i = 0; i < tpd_ring->count; i++) {
-		buffer_info = &tpd_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			pci_unmap_page(pdev, buffer_info->dma,
-				       buffer_info->length, PCI_DMA_TODEVICE);
-			buffer_info->dma = 0;
-		}
-	}
-
-	for (i = 0; i < tpd_ring->count; i++) {
-		buffer_info = &tpd_ring->buffer_info[i];
-		if (buffer_info->skb) {
-			dev_kfree_skb_any(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	size = sizeof(struct atl1_buffer) * tpd_ring->count;
-	memset(tpd_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(tpd_ring->desc, 0, tpd_ring->size);
-
-	atomic_set(&tpd_ring->next_to_use, 0);
-	atomic_set(&tpd_ring->next_to_clean, 0);
+	spin_lock_irqsave(&adapter->lock, flags);
+	atl1_check_link(adapter);
+	spin_unlock_irqrestore(&adapter->lock, flags);
 }
 
-/*
- * atl1_free_ring_resources - Free Tx / RX descriptor Resources
- * @adapter: board private structure
- *
- * Free all transmit software resources
- */
-void atl1_free_ring_resources(struct atl1_adapter *adapter)
+static void atl1_vlan_rx_register(struct net_device *netdev,
+	struct vlan_group *grp)
 {
-	struct pci_dev *pdev = adapter->pdev;
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_ring_header *ring_header = &adapter->ring_header;
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	u32 ctrl;
 
-	atl1_clean_tx_ring(adapter);
-	atl1_clean_rx_ring(adapter);
+	spin_lock_irqsave(&adapter->lock, flags);
+	/* atl1_irq_disable(adapter); */
+	adapter->vlgrp = grp;
 
-	kfree(tpd_ring->buffer_info);
-	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
-			    ring_header->dma);
+	if (grp) {
+		/* enable VLAN tag insert/strip */
+		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+		ctrl |= MAC_CTRL_RMV_VLAN;
+		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+	} else {
+		/* disable VLAN tag insert/strip */
+		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+		ctrl &= ~MAC_CTRL_RMV_VLAN;
+		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+	}
 
-	tpd_ring->buffer_info = NULL;
-	tpd_ring->desc = NULL;
-	tpd_ring->dma = 0;
+	/* atl1_irq_enable(adapter); */
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
 
-	rfd_ring->buffer_info = NULL;
-	rfd_ring->desc = NULL;
-	rfd_ring->dma = 0;
+static void atl1_restore_vlan(struct atl1_adapter *adapter)
+{
+	atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
 
-	rrd_ring->desc = NULL;
-	rrd_ring->dma = 0;
+int atl1_reset(struct atl1_adapter *adapter)
+{
+	int ret;
+
+	ret = atl1_reset_hw(&adapter->hw);
+	if (ret != ATL1_SUCCESS)
+		return ret;
+	return atl1_init_hw(&adapter->hw);
 }
 
 s32 atl1_up(struct atl1_adapter *adapter)
@@ -1758,6 +1966,7 @@
 
 	/* hardware has been reset, we need to reload some things */
 	atl1_set_multi(netdev);
+	atl1_init_ring_ptrs(adapter);
 	atl1_restore_vlan(adapter);
 	err = atl1_alloc_rx_buffers(adapter);
 	if (unlikely(!err))		/* no RX BUFFER allocated */
@@ -1785,11 +1994,6 @@
 	atl1_check_link(adapter);
 	return 0;
 
-	/* FIXME: unreachable code! -- CHS */
-	/* free irq disable any interrupt */
-	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-	free_irq(adapter->pdev->irq, netdev);
-
 err_up:
 	pci_disable_msi(adapter->pdev);
 	/* free rx_buffers */
@@ -1821,172 +2025,6 @@
 }
 
 /*
- * atl1_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int old_mtu = netdev->mtu;
-	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-
-	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
-	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
-		return -EINVAL;
-	}
-
-	adapter->hw.max_frame_size = max_frame;
-	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
-	adapter->rx_buffer_len = (max_frame + 7) & ~7;
-	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
-
-	netdev->mtu = new_mtu;
-	if ((old_mtu != new_mtu) && netif_running(netdev)) {
-		atl1_down(adapter);
-		atl1_up(adapter);
-	}
-
-	return 0;
-}
-
-/*
- * atl1_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_set_mac(struct net_device *netdev, void *p)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-
-	atl1_set_mac_addr(&adapter->hw);
-	return 0;
-}
-
-/*
- * atl1_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_watchdog(unsigned long data)
-{
-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-
-	/* Reset the timer */
-	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-}
-
-static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u16 result;
-
-	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
-
-	return result;
-}
-
-static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, int val)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	atl1_write_phy_reg(&adapter->hw, reg_num, val);
-}
-
-/*
- * atl1_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	int retval;
-
-	if (!netif_running(netdev))
-		return -EINVAL;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-
-	return retval;
-}
-
-/*
- * atl1_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return atl1_mii_ioctl(netdev, ifr, cmd);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/*
- * atl1_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- */
-static void atl1_tx_timeout(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	/* Do the reset outside of interrupt context */
-	schedule_work(&adapter->tx_timeout_task);
-}
-
-/*
- * atl1_phy_config - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_phy_config(unsigned long data)
-{
-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-	struct atl1_hw *hw = &adapter->hw;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	adapter->phy_timer_pending = false;
-	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
-	atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
-	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-int atl1_reset(struct atl1_adapter *adapter)
-{
-	int ret;
-
-	ret = atl1_reset_hw(&adapter->hw);
-	if (ret != ATL1_SUCCESS)
-		return ret;
-	return atl1_init_hw(&adapter->hw);
-}
-
-/*
  * atl1_open - Called when a network interface is made active
  * @netdev: network interface device structure
  *
@@ -2038,6 +2076,105 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	u32 ctrl = 0;
+	u32 wufc = adapter->wol;
+
+	netif_device_detach(netdev);
+	if (netif_running(netdev))
+		atl1_down(adapter);
+
+	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+	if (ctrl & BMSR_LSTATUS)
+		wufc &= ~ATL1_WUFC_LNKC;
+
+	/* reduce speed to 10/100M */
+	if (wufc) {
+		atl1_phy_enter_power_saving(hw);
+		/* if resume, let driver to re- setup link */
+		hw->phy_configured = false;
+		atl1_set_mac_addr(hw);
+		atl1_set_multi(netdev);
+
+		ctrl = 0;
+		/* turn on magic packet wol */
+		if (wufc & ATL1_WUFC_MAG)
+			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+		/* turn on Link change WOL */
+		if (wufc & ATL1_WUFC_LNKC)
+			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+
+		/* turn on all-multi mode if wake on multicast is enabled */
+		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+		ctrl &= ~MAC_CTRL_DBG;
+		ctrl &= ~MAC_CTRL_PROMIS_EN;
+		if (wufc & ATL1_WUFC_MC)
+			ctrl |= MAC_CTRL_MC_ALL_EN;
+		else
+			ctrl &= ~MAC_CTRL_MC_ALL_EN;
+
+		/* turn on broadcast mode if wake on-BC is enabled */
+		if (wufc & ATL1_WUFC_BC)
+			ctrl |= MAC_CTRL_BC_EN;
+		else
+			ctrl &= ~MAC_CTRL_BC_EN;
+
+		/* enable RX */
+		ctrl |= MAC_CTRL_RX_EN;
+		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+		pci_enable_wake(pdev, PCI_D3cold, 1);
+	} else {
+		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_enable_wake(pdev, PCI_D3cold, 0);
+	}
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int atl1_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	u32 ret_val;
+
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev);
+
+	ret_val = pci_enable_device(pdev);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+	atl1_reset(adapter);
+
+	if (netif_running(netdev))
+		atl1_up(adapter);
+	netif_device_attach(netdev);
+
+	atl1_via_workaround(adapter);
+
+	return 0;
+}
+#else
+#define atl1_suspend NULL
+#define atl1_resume NULL
+#endif
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void atl1_poll_controller(struct net_device *netdev)
 {
@@ -2048,69 +2185,6 @@
 #endif
 
 /*
- * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
- * will assert. We do soft reset <0x1400=1> according
- * with the SPEC. BUT, it seemes that PCIE or DMA
- * state-machine will not be reset. DMAR_TO_INT will
- * assert again and again.
- */
-static void atl1_tx_timeout_task(struct work_struct *work)
-{
-	struct atl1_adapter *adapter =
-		container_of(work, struct atl1_adapter, tx_timeout_task);
-	struct net_device *netdev = adapter->netdev;
-
-	netif_device_detach(netdev);
-	atl1_down(adapter);
-	atl1_up(adapter);
-	netif_device_attach(netdev);
-}
-
-/*
- * atl1_link_chg_task - deal with link change event Out of interrupt context
- */
-static void atl1_link_chg_task(struct work_struct *work)
-{
-	struct atl1_adapter *adapter =
-               container_of(work, struct atl1_adapter, link_chg_task);
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	atl1_check_link(adapter);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-/*
- * atl1_pcie_patch - Patch for PCIE module
- */
-static void atl1_pcie_patch(struct atl1_adapter *adapter)
-{
-	u32 value;
-	value = 0x6500;
-	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
-	/* pcie flow control mode change */
-	value = ioread32(adapter->hw.hw_addr + 0x1008);
-	value |= 0x8000;
-	iowrite32(value, adapter->hw.hw_addr + 0x1008);
-}
-
-/*
- * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
- * on PCI Command register is disable.
- * The function enable this bit.
- * Brackett, 2006/03/15
- */
-static void atl1_via_workaround(struct atl1_adapter *adapter)
-{
-	unsigned long value;
-
-	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
-	if (value & PCI_COMMAND_INTX_DISABLE)
-		value &= ~PCI_COMMAND_INTX_DISABLE;
-	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
-}
-
-/*
  * atl1_probe - Device Initialization Routine
  * @pdev: PCI device information struct
  * @ent: entry in atl1_pci_tbl
@@ -2122,7 +2196,7 @@
  * and a hardware reset occur.
  */
 static int __devinit atl1_probe(struct pci_dev *pdev,
-			      const struct pci_device_id *ent)
+	const struct pci_device_id *ent)
 {
 	struct net_device *netdev;
 	struct atl1_adapter *adapter;
@@ -2176,7 +2250,7 @@
 	}
 	/* get device revision number */
 	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
-					(REG_MASTER_CTRL + 2));
+		(REG_MASTER_CTRL + 2));
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 
 	/* set default ring resource counts */
@@ -2203,8 +2277,7 @@
 	netdev->poll_controller = atl1_poll_controller;
 #endif
 	netdev->vlan_rx_register = atl1_vlan_rx_register;
-	netdev->vlan_rx_add_vid = atl1_vlan_rx_add_vid;
-	netdev->vlan_rx_kill_vid = atl1_vlan_rx_kill_vid;
+
 	netdev->ethtool_ops = &atl1_ethtool_ops;
 	adapter->bd_number = cards_found;
 	adapter->pci_using_64 = pci_using_64;
@@ -2330,7 +2403,8 @@
 	 * address, we need to save the permanent one.
 	 */
 	if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
-		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN);
+		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
+			ETH_ALEN);
 		atl1_set_mac_addr(&adapter->hw);
 	}
 
@@ -2342,112 +2416,11 @@
 	pci_disable_device(pdev);
 }
 
-#ifdef CONFIG_PM
-static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	u32 ctrl = 0;
-	u32 wufc = adapter->wol;
-
-	netif_device_detach(netdev);
-	if (netif_running(netdev))
-		atl1_down(adapter);
-
-	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
-	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
-	if (ctrl & BMSR_LSTATUS)
-		wufc &= ~ATL1_WUFC_LNKC;
-
-	/* reduce speed to 10/100M */
-	if (wufc) {
-		atl1_phy_enter_power_saving(hw);
-		/* if resume, let driver to re- setup link */
-		hw->phy_configured = false;
-		atl1_set_mac_addr(hw);
-		atl1_set_multi(netdev);
-
-		ctrl = 0;
-		/* turn on magic packet wol */
-		if (wufc & ATL1_WUFC_MAG)
-			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
-
-		/* turn on Link change WOL */
-		if (wufc & ATL1_WUFC_LNKC)
-			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
-		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
-
-		/* turn on all-multi mode if wake on multicast is enabled */
-		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
-		ctrl &= ~MAC_CTRL_DBG;
-		ctrl &= ~MAC_CTRL_PROMIS_EN;
-		if (wufc & ATL1_WUFC_MC)
-			ctrl |= MAC_CTRL_MC_ALL_EN;
-		else
-			ctrl &= ~MAC_CTRL_MC_ALL_EN;
-
-		/* turn on broadcast mode if wake on-BC is enabled */
-		if (wufc & ATL1_WUFC_BC)
-			ctrl |= MAC_CTRL_BC_EN;
-		else
-			ctrl &= ~MAC_CTRL_BC_EN;
-
-		/* enable RX */
-		ctrl |= MAC_CTRL_RX_EN;
-		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
-		pci_enable_wake(pdev, PCI_D3hot, 1);
-		pci_enable_wake(pdev, PCI_D3cold, 1);	/* 4 == D3 cold */
-	} else {
-		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		pci_enable_wake(pdev, PCI_D3cold, 0);	/* 4 == D3 cold */
-	}
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-static int atl1_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u32 ret_val;
-
-	pci_set_power_state(pdev, 0);
-	pci_restore_state(pdev);
-
-	ret_val = pci_enable_device(pdev);
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
-	atl1_reset(adapter);
-
-	if (netif_running(netdev))
-		atl1_up(adapter);
-	netif_device_attach(netdev);
-
-	atl1_via_workaround(adapter);
-
-	return 0;
-}
-#else
-#define atl1_suspend NULL
-#define atl1_resume NULL
-#endif
-
 static struct pci_driver atl1_driver = {
 	.name = atl1_driver_name,
 	.id_table = atl1_pci_tbl,
 	.probe = atl1_probe,
 	.remove = __devexit_p(atl1_remove),
-	/* Power Managment Hooks */
-	/* probably broken right now -- CHS */
 	.suspend = atl1_suspend,
 	.resume = atl1_resume
 };
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index c39ab80..e86b369 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -34,7 +34,7 @@
  *
  *
  */
-
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -1205,8 +1205,8 @@
 				continue;
 			}
 			skb_reserve(skb, 2);	/* 16 byte IP header align */
-			eth_copy_and_sum(skb,
-				(unsigned char *)pDB->vaddr, frmlen, 0);
+			skb_copy_to_linear_data(skb,
+				(unsigned char *)pDB->vaddr, frmlen);
 			skb_put(skb, frmlen);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);	/* pass the packet to upper layers */
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
new file mode 100644
index 0000000..1d88236
--- /dev/null
+++ b/drivers/net/ax88796.c
@@ -0,0 +1,952 @@
+/* drivers/net/ax88796.c
+ *
+ * Copyright 2005,2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Asix AX88796 10/100 Ethernet controller support
+ *	Based on ne.c, by Donald Becker, et-al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+#include <net/ax88796.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+static int phy_debug = 0;
+
+/* Rename the lib8390.c functions to show that they are in this driver */
+#define __ei_open       ax_ei_open
+#define __ei_close      ax_ei_close
+#define __ei_poll	ax_ei_poll
+#define __ei_tx_timeout ax_ei_tx_timeout
+#define __ei_interrupt  ax_ei_interrupt
+#define ____alloc_ei_netdev ax__alloc_ei_netdev
+#define __NS8390_init   ax_NS8390_init
+
+/* force unsigned long back to 'void __iomem *' */
+#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
+
+#define ei_inb(_a)	readb(ax_convert_addr(_a))
+#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
+
+#define ei_inb_p(_a)	ei_inb(_a)
+#define ei_outb_p(_v, _a) ei_outb(_v, _a)
+
+/* define EI_SHIFT() to take into account our register offsets */
+#define EI_SHIFT(x)     (ei_local->reg_offset[(x)])
+
+/* Ensure we have our RCR base value */
+#define AX88796_PLATFORM
+
+static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
+
+#include "lib8390.c"
+
+#define DRV_NAME "ax88796"
+#define DRV_VERSION "1.00"
+
+/* from ne.c */
+#define NE_CMD		EI_SHIFT(0x00)
+#define NE_RESET	EI_SHIFT(0x1f)
+#define NE_DATAPORT	EI_SHIFT(0x10)
+
+#define NE1SM_START_PG	0x20	/* First page of TX buffer */
+#define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
+#define NESM_START_PG	0x40	/* First page of TX buffer */
+#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+/* device private data */
+
+struct ax_device {
+	struct timer_list	 mii_timer;
+	spinlock_t		 mii_lock;
+	struct mii_if_info	 mii;
+
+	u32			 msg_enable;
+	void __iomem		*map2;
+	struct platform_device	*dev;
+	struct resource		*mem;
+	struct resource		*mem2;
+	struct ax_plat_data	*plat;
+
+	unsigned char		 running;
+	unsigned char		 resume_open;
+
+	u32			 reg_offsets[0x20];
+};
+
+static inline struct ax_device *to_ax_dev(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	return (struct ax_device *)(ei_local+1);
+}
+
+/* ax_initial_check
+ *
+ * do an initial probe for the card to check wether it exists
+ * and is functional
+ */
+
+static int ax_initial_check(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *ioaddr = ei_local->mem;
+	int reg0;
+	int regd;
+
+	reg0 = ei_inb(ioaddr);
+	if (reg0 == 0xFF)
+		return -ENODEV;
+
+	ei_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+	regd = ei_inb(ioaddr + 0x0d);
+	ei_outb(0xff, ioaddr + 0x0d);
+	ei_outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+	ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+	if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
+		ei_outb(reg0, ioaddr);
+		ei_outb(regd, ioaddr + 0x0d);	/* Restore the old values. */
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+
+static void ax_reset_8390(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long reset_start_time = jiffies;
+	void __iomem *addr = (void __iomem *)dev->base_addr;
+
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
+		if (jiffies - reset_start_time > 2*HZ/100) {
+			printk(KERN_WARNING "%s: %s did not complete.\n",
+			       __FUNCTION__, dev->name);
+			break;
+		}
+	}
+
+	ei_outb(ENISR_RESET, addr + EN0_ISR);	/* Ack intr. */
+}
+
+
+static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			    int ring_page)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *nic_base = ei_local->mem;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk(KERN_EMERG "%s: DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n",
+			dev->name, __FUNCTION__,
+		       ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+	ei_outb(0, nic_base + EN0_RCNTHI);
+	ei_outb(0, nic_base + EN0_RSARLO);		/* On page boundary */
+	ei_outb(ring_page, nic_base + EN0_RSARHI);
+	ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.word16)
+		readsw(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	else
+		readsb(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+
+	le16_to_cpus(&hdr->count);
+}
+
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for hints.
+   The NEx000 doesn't share the on-board packet memory -- you have to put
+   the packet out through the "remote DMA" dataport using ei_outb. */
+
+static void ax_block_input(struct net_device *dev, int count,
+			   struct sk_buff *skb, int ring_offset)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *nic_base = ei_local->mem;
+	char *buf = skb->data;
+
+	if (ei_status.dmaing) {
+		printk(KERN_EMERG "%s: DMAing conflict in ax_block_input "
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+
+	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+	ei_outb(count >> 8, nic_base + EN0_RCNTHI);
+	ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
+	ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
+	ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.word16) {
+		readsw(nic_base + NE_DATAPORT, buf, count >> 1);
+		if (count & 0x01)
+			buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
+
+	} else {
+		readsb(nic_base + NE_DATAPORT, buf, count);
+	}
+
+	ei_status.dmaing &= ~1;
+}
+
+static void ax_block_output(struct net_device *dev, int count,
+			    const unsigned char *buf, const int start_page)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *nic_base = ei_local->mem;
+	unsigned long dma_start;
+
+	/* Round the count up for word writes.  Do we need to do this?
+	   What effect will an odd byte count have on the 8390?
+	   I should check someday. */
+
+	if (ei_status.word16 && (count & 0x01))
+		count++;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk(KERN_EMERG "%s: DMAing conflict in %s."
+			"[DMAstat:%d][irqlock:%d]\n",
+			dev->name, __FUNCTION__,
+		       ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);
+
+	/* Now the normal output. */
+	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+	ei_outb(count >> 8,   nic_base + EN0_RCNTHI);
+	ei_outb(0x00, nic_base + EN0_RSARLO);
+	ei_outb(start_page, nic_base + EN0_RSARHI);
+
+	ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16) {
+		writesw(nic_base + NE_DATAPORT, buf, count>>1);
+	} else {
+		writesb(nic_base + NE_DATAPORT, buf, count);
+	}
+
+	dma_start = jiffies;
+
+	while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
+		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
+			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+			ax_reset_8390(dev);
+			ax_NS8390_init(dev,1);
+			break;
+		}
+	}
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+	return;
+}
+
+/* definitions for accessing MII/EEPROM interface */
+
+#define AX_MEMR			EI_SHIFT(0x14)
+#define AX_MEMR_MDC		(1<<0)
+#define AX_MEMR_MDIR		(1<<1)
+#define AX_MEMR_MDI		(1<<2)
+#define AX_MEMR_MDO		(1<<3)
+#define AX_MEMR_EECS		(1<<4)
+#define AX_MEMR_EEI		(1<<5)
+#define AX_MEMR_EEO		(1<<6)
+#define AX_MEMR_EECLK		(1<<7)
+
+/* ax_mii_ei_outbits
+ *
+ * write the specified set of bits to the phy
+*/
+
+static void
+ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len)
+{
+	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
+	unsigned int memr;
+
+	/* clock low, data to output mode */
+	memr = ei_inb(memr_addr);
+	memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR);
+	ei_outb(memr, memr_addr);
+
+	for (len--; len >= 0; len--) {
+		if (bits & (1 << len))
+			memr |= AX_MEMR_MDO;
+		else
+			memr &= ~AX_MEMR_MDO;
+
+		ei_outb(memr, memr_addr);
+
+		/* clock high */
+
+		ei_outb(memr | AX_MEMR_MDC, memr_addr);
+		udelay(1);
+
+		/* clock low */
+		ei_outb(memr, memr_addr);
+	}
+
+	/* leaves the clock line low, mdir input */
+	memr |= AX_MEMR_MDIR;
+	ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR);
+}
+
+/* ax_phy_ei_inbits
+ *
+ * read a specified number of bits from the phy
+*/
+
+static unsigned int
+ax_phy_ei_inbits(struct net_device *dev, int no)
+{
+	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
+	unsigned int memr;
+	unsigned int result = 0;
+
+	/* clock low, data to input mode */
+	memr = ei_inb(memr_addr);
+	memr &= ~AX_MEMR_MDC;
+	memr |= AX_MEMR_MDIR;
+	ei_outb(memr, memr_addr);
+
+	for (no--; no >= 0; no--) {
+		ei_outb(memr | AX_MEMR_MDC, memr_addr);
+
+		udelay(1);
+
+		if (ei_inb(memr_addr) & AX_MEMR_MDI)
+			result |= (1<<no);
+
+		ei_outb(memr, memr_addr);
+	}
+
+	return result;
+}
+
+/* ax_phy_issueaddr
+ *
+ * use the low level bit shifting routines to send the address
+ * and command to the specified phy
+*/
+
+static void
+ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc)
+{
+	if (phy_debug)
+		pr_debug("%s: dev %p, %04x, %04x, %d\n",
+			__FUNCTION__, dev, phy_addr, reg, opc);
+
+	ax_mii_ei_outbits(dev, 0x3f, 6);	/* pre-amble */
+	ax_mii_ei_outbits(dev, 1, 2);		/* frame-start */
+	ax_mii_ei_outbits(dev, opc, 2);		/* op code */
+	ax_mii_ei_outbits(dev, phy_addr, 5);	/* phy address */
+	ax_mii_ei_outbits(dev, reg, 5);		/* reg address */
+}
+
+static int
+ax_phy_read(struct net_device *dev, int phy_addr, int reg)
+{
+	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	unsigned long flags;
+ 	unsigned int result;
+
+      	spin_lock_irqsave(&ei_local->page_lock, flags);
+
+	ax_phy_issueaddr(dev, phy_addr, reg, 2);
+
+	result = ax_phy_ei_inbits(dev, 17);
+	result &= ~(3<<16);
+
+      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+	if (phy_debug)
+		pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__,
+			 phy_addr, reg, result);
+
+	return result;
+}
+
+static void
+ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
+{
+	struct ei_device *ei = (struct ei_device *) netdev_priv(dev);
+	unsigned long flags;
+
+	printk(KERN_DEBUG "%s: %p, %04x, %04x %04x\n",
+	       __FUNCTION__, dev, phy_addr, reg, value);
+
+      	spin_lock_irqsave(&ei->page_lock, flags);
+
+	ax_phy_issueaddr(dev, phy_addr, reg, 1);
+	ax_mii_ei_outbits(dev, 2, 2);		/* send TA */
+	ax_mii_ei_outbits(dev, value, 16);
+
+      	spin_unlock_irqrestore(&ei->page_lock, flags);
+}
+
+static void ax_mii_expiry(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct ax_device  *ax = to_ax_dev(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ax->mii_lock, flags);
+	mii_check_media(&ax->mii, netif_msg_link(ax), 0);
+	spin_unlock_irqrestore(&ax->mii_lock, flags);
+
+	if (ax->running) {
+		ax->mii_timer.expires = jiffies + HZ*2;
+		add_timer(&ax->mii_timer);
+	}
+}
+
+static int ax_open(struct net_device *dev)
+{
+	struct ax_device  *ax = to_ax_dev(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
+	int ret;
+
+	dev_dbg(&ax->dev->dev, "%s: open\n", dev->name);
+
+	ret = request_irq(dev->irq, ax_ei_interrupt, 0, dev->name, dev);
+	if (ret)
+		return ret;
+
+	ret = ax_ei_open(dev);
+	if (ret)
+		return ret;
+
+	/* turn the phy on (if turned off) */
+
+	ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17));
+	ax->running = 1;
+
+	/* start the MII timer */
+
+	init_timer(&ax->mii_timer);
+
+	ax->mii_timer.expires  = jiffies+1;
+	ax->mii_timer.data     = (unsigned long) dev;
+	ax->mii_timer.function = ax_mii_expiry;
+
+	add_timer(&ax->mii_timer);
+
+	return 0;
+}
+
+static int ax_close(struct net_device *dev)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	dev_dbg(&ax->dev->dev, "%s: close\n", dev->name);
+
+	/* turn the phy off */
+
+	ei_outb(ax->plat->gpoc_val | (1<<6),
+	       ei_local->mem + EI_SHIFT(0x17));
+
+	ax->running = 0;
+	wmb();
+
+	del_timer_sync(&ax->mii_timer);
+	ax_ei_close(dev);
+
+	free_irq(dev->irq, dev);
+	return 0;
+}
+
+static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	unsigned long flags;
+	int rc;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&ax->mii_lock, flags);
+	rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL);
+	spin_unlock_irqrestore(&ax->mii_lock, flags);
+
+	return rc;
+}
+
+/* ethtool ops */
+
+static void ax_get_drvinfo(struct net_device *dev,
+			   struct ethtool_drvinfo *info)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, ax->dev->name);
+}
+
+static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ax->mii_lock, flags);
+	mii_ethtool_gset(&ax->mii, cmd);
+	spin_lock_irqsave(&ax->mii_lock, flags);
+
+	return 0;
+}
+
+static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&ax->mii_lock, flags);
+	rc = mii_ethtool_sset(&ax->mii, cmd);
+	spin_lock_irqsave(&ax->mii_lock, flags);
+
+	return rc;
+}
+
+static int ax_nway_reset(struct net_device *dev)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	return mii_nway_restart(&ax->mii);
+}
+
+static u32 ax_get_link(struct net_device *dev)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	return mii_link_ok(&ax->mii);
+}
+
+static const struct ethtool_ops ax_ethtool_ops = {
+	.get_drvinfo		= ax_get_drvinfo,
+	.get_settings		= ax_get_settings,
+	.set_settings		= ax_set_settings,
+	.nway_reset		= ax_nway_reset,
+	.get_link		= ax_get_link,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
+};
+
+/* setup code */
+
+static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
+{
+	void __iomem *ioaddr = ei_local->mem;
+	struct ax_device *ax = to_ax_dev(dev);
+
+	/* Select page 0*/
+	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD);
+
+	/* set to byte access */
+	ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
+	ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
+}
+
+/* ax_init_dev
+ *
+ * initialise the specified device, taking care to note the MAC
+ * address it may already have (if configured), ensure
+ * the device is ready to be used by lib8390.c and registerd with
+ * the network layer.
+ */
+
+static int ax_init_dev(struct net_device *dev, int first_init)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
+	void __iomem *ioaddr = ei_local->mem;
+	unsigned int start_page;
+	unsigned int stop_page;
+	int ret;
+	int i;
+
+	ret = ax_initial_check(dev);
+	if (ret)
+		goto err_out;
+
+	/* setup goes here */
+
+	ax_initial_setup(dev, ei_local);
+
+	/* read the mac from the card prom if we need it */
+
+	if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) {
+		unsigned char SA_prom[32];
+
+		for(i = 0; i < sizeof(SA_prom); i+=2) {
+			SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
+			SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT);
+		}
+
+		if (ax->plat->wordlength == 2)
+			for (i = 0; i < 16; i++)
+				SA_prom[i] = SA_prom[i+i];
+
+		memcpy(dev->dev_addr,  SA_prom, 6);
+	}
+
+	if (ax->plat->wordlength == 2) {
+		/* We must set the 8390 for word mode. */
+		ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
+		start_page = NESM_START_PG;
+		stop_page = NESM_STOP_PG;
+	} else {
+		start_page = NE1SM_START_PG;
+		stop_page = NE1SM_STOP_PG;
+	}
+
+	/* load the mac-address from the device if this is the
+	 * first time we've initialised */
+
+	if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) {
+		ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+			ei_local->mem + E8390_CMD); /* 0x61 */
+
+		for (i = 0 ; i < ETHER_ADDR_LEN ; i++)
+			dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
+	}
+
+	ax_reset_8390(dev);
+
+	ei_status.name = "AX88796";
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = (ax->plat->wordlength == 2);
+	ei_status.rx_start_page = start_page + TX_PAGES;
+
+#ifdef PACKETBUF_MEMSIZE
+	 /* Allow the packet buffer size to be overridden by know-it-alls. */
+	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+	ei_status.reset_8390	= &ax_reset_8390;
+	ei_status.block_input	= &ax_block_input;
+	ei_status.block_output	= &ax_block_output;
+	ei_status.get_8390_hdr	= &ax_get_8390_hdr;
+	ei_status.priv = 0;
+
+	dev->open		= ax_open;
+	dev->stop		= ax_close;
+	dev->do_ioctl		= ax_ioctl;
+	dev->ethtool_ops	= &ax_ethtool_ops;
+
+	ax->msg_enable		= NETIF_MSG_LINK;
+	ax->mii.phy_id_mask	= 0x1f;
+	ax->mii.reg_num_mask	= 0x1f;
+	ax->mii.phy_id		= 0x10;		/* onboard phy */
+	ax->mii.force_media	= 0;
+	ax->mii.full_duplex	= 0;
+	ax->mii.mdio_read	= ax_phy_read;
+	ax->mii.mdio_write	= ax_phy_write;
+	ax->mii.dev		= dev;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ax_ei_poll;
+#endif
+	ax_NS8390_init(dev, 0);
+
+	if (first_init) {
+		printk("AX88796: %dbit, irq %d, %lx, MAC: ",
+		       ei_status.word16 ? 16:8, dev->irq, dev->base_addr);
+
+		for (i = 0; i < ETHER_ADDR_LEN; i++)
+			printk("%2.2x%c", dev->dev_addr[i],
+			       (i < (ETHER_ADDR_LEN-1) ? ':' : ' '));
+
+		printk("\n");
+	}
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto out_irq;
+
+	return 0;
+
+ out_irq:
+	/* cleanup irq */
+	free_irq(dev->irq, dev);
+ err_out:
+	return ret;
+}
+
+static int ax_remove(struct platform_device *_dev)
+{
+	struct net_device *dev = platform_get_drvdata(_dev);
+	struct ax_device  *ax;
+
+	ax = to_ax_dev(dev);
+
+	unregister_netdev(dev);
+	free_irq(dev->irq, dev);
+
+	iounmap(ei_status.mem);
+	release_resource(ax->mem);
+	kfree(ax->mem);
+
+	if (ax->map2) {
+		iounmap(ax->map2);
+		release_resource(ax->mem2);
+		kfree(ax->mem2);
+	}
+
+	free_netdev(dev);
+
+	return 0;
+}
+
+/* ax_probe
+ *
+ * This is the entry point when the platform device system uses to
+ * notify us of a new device to attach to. Allocate memory, find
+ * the resources and information passed, and map the necessary registers.
+*/
+
+static int ax_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct ax_device  *ax;
+	struct resource   *res;
+	size_t size;
+	int ret;
+
+	dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
+	if (dev == NULL)
+		return -ENOMEM;
+
+	/* ok, let's setup our device */
+	ax = to_ax_dev(dev);
+
+	memset(ax, 0, sizeof(struct ax_device));
+
+	spin_lock_init(&ax->mii_lock);
+
+	ax->dev = pdev;
+	ax->plat = pdev->dev.platform_data;
+	platform_set_drvdata(pdev, dev);
+
+	ei_status.rxcr_base  = ax->plat->rcr_val;
+
+	/* find the platform resources */
+
+	dev->irq  = platform_get_irq(pdev, 0);
+	if (dev->irq < 0) {
+		dev_err(&pdev->dev, "no IRQ specified\n");
+		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no MEM specified\n");
+		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	size = (res->end - res->start) + 1;
+
+	/* setup the register offsets from either the platform data
+	 * or by using the size of the resource provided */
+
+	if (ax->plat->reg_offsets)
+		ei_status.reg_offset = ax->plat->reg_offsets;
+	else {
+		ei_status.reg_offset = ax->reg_offsets;
+		for (ret = 0; ret < 0x18; ret++)
+			ax->reg_offsets[ret] = (size / 0x18) * ret;
+	}
+
+	ax->mem = request_mem_region(res->start, size, pdev->name);
+	if (ax->mem == NULL) {
+		dev_err(&pdev->dev, "cannot reserve registers\n");
+ 		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	ei_status.mem = ioremap(res->start, size);
+	dev->base_addr = (long)ei_status.mem;
+
+	if (ei_status.mem == NULL) {
+		dev_err(&pdev->dev, "Cannot ioremap area (%08zx,%08zx)\n",
+			res->start, res->end);
+
+ 		ret = -ENXIO;
+		goto exit_req;
+	}
+
+	/* look for reset area */
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res == NULL) {
+		if (!ax->plat->reg_offsets) {
+			for (ret = 0; ret < 0x20; ret++)
+				ax->reg_offsets[ret] = (size / 0x20) * ret;
+		}
+
+		ax->map2 = NULL;
+	} else {
+ 		size = (res->end - res->start) + 1;
+
+		ax->mem2 = request_mem_region(res->start, size, pdev->name);
+		if (ax->mem == NULL) {
+			dev_err(&pdev->dev, "cannot reserve registers\n");
+			ret = -ENXIO;
+			goto exit_mem1;
+		}
+
+		ax->map2 = ioremap(res->start, size);
+		if (ax->map2 == NULL) {
+			dev_err(&pdev->dev, "cannot map reset register");
+			ret = -ENXIO;
+			goto exit_mem2;
+		}
+
+		ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
+	}
+
+	/* got resources, now initialise and register device */
+
+	ret = ax_init_dev(dev, 1);
+	if (!ret)
+		return 0;
+
+	if (ax->map2 == NULL)
+		goto exit_mem1;
+
+	iounmap(ax->map2);
+
+ exit_mem2:
+	release_resource(ax->mem2);
+	kfree(ax->mem2);
+
+ exit_mem1:
+	iounmap(ei_status.mem);
+
+ exit_req:
+	release_resource(ax->mem);
+	kfree(ax->mem);
+
+ exit_mem:
+	free_netdev(dev);
+
+	return ret;
+}
+
+/* suspend and resume */
+
+#ifdef CONFIG_PM
+static int ax_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct net_device *ndev = platform_get_drvdata(dev);
+	struct ax_device  *ax = to_ax_dev(ndev);
+
+	ax->resume_open = ax->running;
+
+	netif_device_detach(ndev);
+	ax_close(ndev);
+
+	return 0;
+}
+
+static int ax_resume(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct ax_device  *ax = to_ax_dev(ndev);
+
+	ax_initial_setup(ndev, netdev_priv(ndev));
+	ax_NS8390_init(ndev, ax->resume_open);
+	netif_device_attach(ndev);
+
+	if (ax->resume_open)
+		ax_open(ndev);
+
+	return 0;
+}
+
+#else
+#define ax_suspend NULL
+#define ax_resume  NULL
+#endif
+
+static struct platform_driver axdrv = {
+	.driver	= {
+		.name		= "ax88796",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= ax_probe,
+	.remove		= ax_remove,
+	.suspend	= ax_suspend,
+	.resume		= ax_resume,
+};
+
+static int __init axdrv_init(void)
+{
+	return platform_driver_register(&axdrv);
+}
+
+static void __exit axdrv_exit(void)
+{
+	platform_driver_unregister(&axdrv);
+}
+
+module_init(axdrv_init);
+module_exit(axdrv_exit);
+
+MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 879a2ff..96fb0ec 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -15,6 +15,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/if_ether.h>
+#include <linux/if_vlan.h>
 #include <linux/etherdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -68,8 +69,8 @@
 	  (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
 #define NEXT_TX(N)		(((N) + 1) & (B44_TX_RING_SIZE - 1))
 
-#define RX_PKT_BUF_SZ		(1536 + bp->rx_offset + 64)
-#define TX_PKT_BUF_SZ		(B44_MAX_MTU + ETH_HLEN + 8)
+#define RX_PKT_OFFSET		30
+#define RX_PKT_BUF_SZ		(1536 + RX_PKT_OFFSET + 64)
 
 /* minimum number of free TX descriptors required to wake up TX process */
 #define B44_TX_WAKEUP_THRESH		(B44_TX_RING_SIZE / 4)
@@ -599,8 +600,7 @@
 
 	spin_unlock_irq(&bp->lock);
 
-	bp->timer.expires = jiffies + HZ;
-	add_timer(&bp->timer);
+	mod_timer(&bp->timer, round_jiffies(jiffies + HZ));
 }
 
 static void b44_tx(struct b44 *bp)
@@ -653,7 +653,7 @@
 		src_map = &bp->rx_buffers[src_idx];
 	dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
 	map = &bp->rx_buffers[dest_idx];
-	skb = dev_alloc_skb(RX_PKT_BUF_SZ);
+	skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ);
 	if (skb == NULL)
 		return -ENOMEM;
 
@@ -669,7 +669,7 @@
 		if (!dma_mapping_error(mapping))
 			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
 		dev_kfree_skb_any(skb);
-		skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+		skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
 		if (skb == NULL)
 			return -ENOMEM;
 		mapping = pci_map_single(bp->pdev, skb->data,
@@ -684,11 +684,9 @@
 		}
 	}
 
-	skb->dev = bp->dev;
-	skb_reserve(skb, bp->rx_offset);
+	rh = (struct rx_header *) skb->data;
+	skb_reserve(skb, RX_PKT_OFFSET);
 
-	rh = (struct rx_header *)
-		(skb->data - bp->rx_offset);
 	rh->len = 0;
 	rh->flags = 0;
 
@@ -698,13 +696,13 @@
 	if (src_map != NULL)
 		src_map->skb = NULL;
 
-	ctrl  = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset));
+	ctrl  = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
 	if (dest_idx == (B44_RX_RING_SIZE - 1))
 		ctrl |= DESC_CTRL_EOT;
 
 	dp = &bp->rx_ring[dest_idx];
 	dp->ctrl = cpu_to_le32(ctrl);
-	dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
+	dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
 
 	if (bp->flags & B44_FLAG_RX_RING_HACK)
 		b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
@@ -783,7 +781,7 @@
 					    PCI_DMA_FROMDEVICE);
 		rh = (struct rx_header *) skb->data;
 		len = le16_to_cpu(rh->len);
-		if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
+		if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
 		    (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
 		drop_it:
 			b44_recycle_rx(bp, cons, bp->rx_prod);
@@ -815,8 +813,8 @@
 			pci_unmap_single(bp->pdev, map,
 					 skb_size, PCI_DMA_FROMDEVICE);
 			/* Leave out rx_header */
-                	skb_put(skb, len+bp->rx_offset);
-            	        skb_pull(skb,bp->rx_offset);
+                	skb_put(skb, len + RX_PKT_OFFSET);
+            	        skb_pull(skb, RX_PKT_OFFSET);
 		} else {
 			struct sk_buff *copy_skb;
 
@@ -828,7 +826,7 @@
 			skb_reserve(copy_skb, 2);
 			skb_put(copy_skb, len);
 			/* DMA sync done above, copy just the actual packet */
-			skb_copy_from_linear_data_offset(skb, bp->rx_offset,
+			skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET,
 							 copy_skb->data, len);
 			skb = copy_skb;
 		}
@@ -969,7 +967,6 @@
 static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct b44 *bp = netdev_priv(dev);
-	struct sk_buff *bounce_skb;
 	int rc = NETDEV_TX_OK;
 	dma_addr_t mapping;
 	u32 len, entry, ctrl;
@@ -987,12 +984,13 @@
 
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 	if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
+		struct sk_buff *bounce_skb;
+
 		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
 		if (!dma_mapping_error(mapping))
 			pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
 
-		bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
-					     GFP_ATOMIC|GFP_DMA);
+		bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
 		if (!bounce_skb)
 			goto err_out;
 
@@ -1001,13 +999,12 @@
 		if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
 			if (!dma_mapping_error(mapping))
 				pci_unmap_single(bp->pdev, mapping,
-					 len, PCI_DMA_TODEVICE);
+						 len, PCI_DMA_TODEVICE);
 			dev_kfree_skb_any(bounce_skb);
 			goto err_out;
 		}
 
-		skb_copy_from_linear_data(skb, skb_put(bounce_skb, len),
-					  skb->len);
+		skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
 		dev_kfree_skb_any(skb);
 		skb = bounce_skb;
 	}
@@ -1396,12 +1393,12 @@
 	bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
 	if (reset_kind == B44_PARTIAL_RESET) {
 		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-				      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+				      (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
 	} else {
 		bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
 		bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
 		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-				      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+				      (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
 		bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
 
 		bw32(bp, B44_DMARX_PTR, bp->rx_pending);
@@ -2093,11 +2090,6 @@
 
 	bp->phy_addr = eeprom[90] & 0x1f;
 
-	/* With this, plus the rx_header prepended to the data by the
-	 * hardware, we'll land the ethernet header on a 2-byte boundary.
-	 */
-	bp->rx_offset = 30;
-
 	bp->imask = IMASK_DEF;
 
 	bp->core_unit = ssb_core_unit(bp);
@@ -2348,11 +2340,11 @@
 	netif_device_attach(bp->dev);
 	spin_unlock_irq(&bp->lock);
 
-	bp->timer.expires = jiffies + HZ;
-	add_timer(&bp->timer);
-
 	b44_enable_ints(bp);
 	netif_wake_queue(dev);
+
+	mod_timer(&bp->timer, jiffies + 1);
+
 	return 0;
 }
 
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 18fc133..e537e63 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -443,8 +443,6 @@
 #define B44_FLAG_TX_RING_HACK	0x40000000
 #define B44_FLAG_WOL_ENABLE	0x80000000
 
-	u32			rx_offset;
-
 	u32			msg_enable;
 
 	struct timer_list	timer;
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 88b33c6..d23861c 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -54,8 +54,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.5.10"
-#define DRV_MODULE_RELDATE	"May 1, 2007"
+#define DRV_MODULE_VERSION	"1.6.2"
+#define DRV_MODULE_RELDATE	"July 6, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -550,6 +550,9 @@
 {
 	u32 fw_link_status = 0;
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return;
+
 	if (bp->link_up) {
 		u32 bmsr;
 
@@ -601,12 +604,21 @@
 	REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status);
 }
 
+static char *
+bnx2_xceiver_str(struct bnx2 *bp)
+{
+	return ((bp->phy_port == PORT_FIBRE) ? "SerDes" :
+		((bp->phy_flags & PHY_SERDES_FLAG) ? "Remote Copper" :
+		 "Copper"));
+}
+
 static void
 bnx2_report_link(struct bnx2 *bp)
 {
 	if (bp->link_up) {
 		netif_carrier_on(bp->dev);
-		printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name);
+		printk(KERN_INFO PFX "%s NIC %s Link is Up, ", bp->dev->name,
+		       bnx2_xceiver_str(bp));
 
 		printk("%d Mbps ", bp->line_speed);
 
@@ -630,7 +642,8 @@
 	}
 	else {
 		netif_carrier_off(bp->dev);
-		printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name);
+		printk(KERN_ERR PFX "%s NIC %s Link is Down\n", bp->dev->name,
+		       bnx2_xceiver_str(bp));
 	}
 
 	bnx2_report_fw_link(bp);
@@ -1100,6 +1113,9 @@
 		return 0;
 	}
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return 0;
+
 	link_up = bp->link_up;
 
 	bnx2_enable_bmsr1(bp);
@@ -1210,12 +1226,74 @@
 	return adv;
 }
 
+static int bnx2_fw_sync(struct bnx2 *, u32, int);
+
 static int
-bnx2_setup_serdes_phy(struct bnx2 *bp)
+bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
+{
+	u32 speed_arg = 0, pause_adv;
+
+	pause_adv = bnx2_phy_get_pause_adv(bp);
+
+	if (bp->autoneg & AUTONEG_SPEED) {
+		speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG;
+		if (bp->advertising & ADVERTISED_10baseT_Half)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF;
+		if (bp->advertising & ADVERTISED_10baseT_Full)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL;
+		if (bp->advertising & ADVERTISED_100baseT_Half)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF;
+		if (bp->advertising & ADVERTISED_100baseT_Full)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL;
+		if (bp->advertising & ADVERTISED_1000baseT_Full)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
+		if (bp->advertising & ADVERTISED_2500baseX_Full)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
+	} else {
+		if (bp->req_line_speed == SPEED_2500)
+			speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
+		else if (bp->req_line_speed == SPEED_1000)
+			speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
+		else if (bp->req_line_speed == SPEED_100) {
+			if (bp->req_duplex == DUPLEX_FULL)
+				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL;
+			else
+				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF;
+		} else if (bp->req_line_speed == SPEED_10) {
+			if (bp->req_duplex == DUPLEX_FULL)
+				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL;
+			else
+				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF;
+		}
+	}
+
+	if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP))
+		speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE;
+	if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_1000XPSE_ASYM))
+		speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE;
+
+	if (port == PORT_TP)
+		speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE |
+			     BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED;
+
+	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB_ARG0, speed_arg);
+
+	spin_unlock_bh(&bp->phy_lock);
+	bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0);
+	spin_lock_bh(&bp->phy_lock);
+
+	return 0;
+}
+
+static int
+bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port)
 {
 	u32 adv, bmcr;
 	u32 new_adv = 0;
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return (bnx2_setup_remote_phy(bp, port));
+
 	if (!(bp->autoneg & AUTONEG_SPEED)) {
 		u32 new_bmcr;
 		int force_link_down = 0;
@@ -1323,7 +1401,9 @@
 }
 
 #define ETHTOOL_ALL_FIBRE_SPEED						\
-	(ADVERTISED_1000baseT_Full)
+	(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ?			\
+		(ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\
+		(ADVERTISED_1000baseT_Full)
 
 #define ETHTOOL_ALL_COPPER_SPEED					\
 	(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |		\
@@ -1335,6 +1415,188 @@
 
 #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
 
+static void
+bnx2_set_default_remote_link(struct bnx2 *bp)
+{
+	u32 link;
+
+	if (bp->phy_port == PORT_TP)
+		link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_COPPER_LINK);
+	else
+		link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_SERDES_LINK);
+
+	if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) {
+		bp->req_line_speed = 0;
+		bp->autoneg |= AUTONEG_SPEED;
+		bp->advertising = ADVERTISED_Autoneg;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
+			bp->advertising |= ADVERTISED_10baseT_Half;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL)
+			bp->advertising |= ADVERTISED_10baseT_Full;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
+			bp->advertising |= ADVERTISED_100baseT_Half;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL)
+			bp->advertising |= ADVERTISED_100baseT_Full;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
+			bp->advertising |= ADVERTISED_1000baseT_Full;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
+			bp->advertising |= ADVERTISED_2500baseX_Full;
+	} else {
+		bp->autoneg = 0;
+		bp->advertising = 0;
+		bp->req_duplex = DUPLEX_FULL;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_10) {
+			bp->req_line_speed = SPEED_10;
+			if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
+				bp->req_duplex = DUPLEX_HALF;
+		}
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_100) {
+			bp->req_line_speed = SPEED_100;
+			if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
+				bp->req_duplex = DUPLEX_HALF;
+		}
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
+			bp->req_line_speed = SPEED_1000;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
+			bp->req_line_speed = SPEED_2500;
+	}
+}
+
+static void
+bnx2_set_default_link(struct bnx2 *bp)
+{
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return bnx2_set_default_remote_link(bp);
+
+	bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
+	bp->req_line_speed = 0;
+	if (bp->phy_flags & PHY_SERDES_FLAG) {
+		u32 reg;
+
+		bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
+
+		reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
+		reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
+		if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
+			bp->autoneg = 0;
+			bp->req_line_speed = bp->line_speed = SPEED_1000;
+			bp->req_duplex = DUPLEX_FULL;
+		}
+	} else
+		bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
+}
+
+static void
+bnx2_send_heart_beat(struct bnx2 *bp)
+{
+	u32 msg;
+	u32 addr;
+
+	spin_lock(&bp->indirect_lock);
+	msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK);
+	addr = bp->shmem_base + BNX2_DRV_PULSE_MB;
+	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr);
+	REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg);
+	spin_unlock(&bp->indirect_lock);
+}
+
+static void
+bnx2_remote_phy_event(struct bnx2 *bp)
+{
+	u32 msg;
+	u8 link_up = bp->link_up;
+	u8 old_port;
+
+	msg = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
+
+	if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED)
+		bnx2_send_heart_beat(bp);
+
+	msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED;
+
+	if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN)
+		bp->link_up = 0;
+	else {
+		u32 speed;
+
+		bp->link_up = 1;
+		speed = msg & BNX2_LINK_STATUS_SPEED_MASK;
+		bp->duplex = DUPLEX_FULL;
+		switch (speed) {
+			case BNX2_LINK_STATUS_10HALF:
+				bp->duplex = DUPLEX_HALF;
+			case BNX2_LINK_STATUS_10FULL:
+				bp->line_speed = SPEED_10;
+				break;
+			case BNX2_LINK_STATUS_100HALF:
+				bp->duplex = DUPLEX_HALF;
+			case BNX2_LINK_STATUS_100BASE_T4:
+			case BNX2_LINK_STATUS_100FULL:
+				bp->line_speed = SPEED_100;
+				break;
+			case BNX2_LINK_STATUS_1000HALF:
+				bp->duplex = DUPLEX_HALF;
+			case BNX2_LINK_STATUS_1000FULL:
+				bp->line_speed = SPEED_1000;
+				break;
+			case BNX2_LINK_STATUS_2500HALF:
+				bp->duplex = DUPLEX_HALF;
+			case BNX2_LINK_STATUS_2500FULL:
+				bp->line_speed = SPEED_2500;
+				break;
+			default:
+				bp->line_speed = 0;
+				break;
+		}
+
+		spin_lock(&bp->phy_lock);
+		bp->flow_ctrl = 0;
+		if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
+		    (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
+			if (bp->duplex == DUPLEX_FULL)
+				bp->flow_ctrl = bp->req_flow_ctrl;
+		} else {
+			if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED)
+				bp->flow_ctrl |= FLOW_CTRL_TX;
+			if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED)
+				bp->flow_ctrl |= FLOW_CTRL_RX;
+		}
+
+		old_port = bp->phy_port;
+		if (msg & BNX2_LINK_STATUS_SERDES_LINK)
+			bp->phy_port = PORT_FIBRE;
+		else
+			bp->phy_port = PORT_TP;
+
+		if (old_port != bp->phy_port)
+			bnx2_set_default_link(bp);
+
+		spin_unlock(&bp->phy_lock);
+	}
+	if (bp->link_up != link_up)
+		bnx2_report_link(bp);
+
+	bnx2_set_mac_link(bp);
+}
+
+static int
+bnx2_set_remote_link(struct bnx2 *bp)
+{
+	u32 evt_code;
+
+	evt_code = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_EVT_CODE_MB);
+	switch (evt_code) {
+		case BNX2_FW_EVT_CODE_LINK_EVENT:
+			bnx2_remote_phy_event(bp);
+			break;
+		case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT:
+		default:
+			bnx2_send_heart_beat(bp);
+			break;
+	}
+	return 0;
+}
+
 static int
 bnx2_setup_copper_phy(struct bnx2 *bp)
 {
@@ -1433,13 +1695,13 @@
 }
 
 static int
-bnx2_setup_phy(struct bnx2 *bp)
+bnx2_setup_phy(struct bnx2 *bp, u8 port)
 {
 	if (bp->loopback == MAC_LOOPBACK)
 		return 0;
 
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
-		return (bnx2_setup_serdes_phy(bp));
+		return (bnx2_setup_serdes_phy(bp, port));
 	}
 	else {
 		return (bnx2_setup_copper_phy(bp));
@@ -1659,6 +1921,9 @@
 
         REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		goto setup_phy;
+
 	bnx2_read_phy(bp, MII_PHYSID1, &val);
 	bp->phy_id = val << 16;
 	bnx2_read_phy(bp, MII_PHYSID2, &val);
@@ -1676,7 +1941,9 @@
 		rc = bnx2_init_copper_phy(bp);
 	}
 
-	bnx2_setup_phy(bp);
+setup_phy:
+	if (!rc)
+		rc = bnx2_setup_phy(bp, bp->phy_port);
 
 	return rc;
 }
@@ -1778,6 +2045,15 @@
 	val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12);
 	val |= (BCM_PAGE_BITS - 8) << 16;
 	REG_WR(bp, BNX2_CTX_COMMAND, val);
+	for (i = 0; i < 10; i++) {
+		val = REG_RD(bp, BNX2_CTX_COMMAND);
+		if (!(val & BNX2_CTX_COMMAND_MEM_INIT))
+			break;
+		udelay(2);
+	}
+	if (val & BNX2_CTX_COMMAND_MEM_INIT)
+		return -EBUSY;
+
 	for (i = 0; i < bp->ctx_pages; i++) {
 		int j;
 
@@ -1811,6 +2087,7 @@
 	vcid = 96;
 	while (vcid) {
 		u32 vcid_addr, pcid_addr, offset;
+		int i;
 
 		vcid--;
 
@@ -1831,16 +2108,20 @@
 			pcid_addr = vcid_addr;
 		}
 
-		REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
-		REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+		for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) {
+			vcid_addr += (i << PHY_CTX_SHIFT);
+			pcid_addr += (i << PHY_CTX_SHIFT);
 
-		/* Zero out the context. */
-		for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) {
-			CTX_WR(bp, 0x00, offset, 0);
+			REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
+			REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+
+			/* Zero out the context. */
+			for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
+				CTX_WR(bp, 0x00, offset, 0);
+
+			REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
+			REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
 		}
-
-		REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
-		REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
 	}
 }
 
@@ -1970,6 +2251,9 @@
 		bnx2_set_link(bp);
 		spin_unlock(&bp->phy_lock);
 	}
+	if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_TIMER_ABORT))
+		bnx2_set_remote_link(bp);
+
 }
 
 static void
@@ -2283,6 +2567,7 @@
 {
 	struct net_device *dev = dev_instance;
 	struct bnx2 *bp = netdev_priv(dev);
+	struct status_block *sblk = bp->status_blk;
 
 	/* When using INTx, it is possible for the interrupt to arrive
 	 * at the CPU before the status block posted prior to the
@@ -2290,7 +2575,7 @@
 	 * When using MSI, the MSI message will always complete after
 	 * the status block write.
 	 */
-	if ((bp->status_blk->status_idx == bp->last_status_idx) &&
+	if ((sblk->status_idx == bp->last_status_idx) &&
 	    (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
 	     BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
 		return IRQ_NONE;
@@ -2299,16 +2584,25 @@
 		BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
 		BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
 
+	/* Read back to deassert IRQ immediately to avoid too many
+	 * spurious interrupts.
+	 */
+	REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+
 	/* Return here if interrupt is shared and is disabled. */
 	if (unlikely(atomic_read(&bp->intr_sem) != 0))
 		return IRQ_HANDLED;
 
-	netif_rx_schedule(dev);
+	if (netif_rx_schedule_prep(dev)) {
+		bp->last_status_idx = sblk->status_idx;
+		__netif_rx_schedule(dev);
+	}
 
 	return IRQ_HANDLED;
 }
 
-#define STATUS_ATTN_EVENTS	STATUS_ATTN_BITS_LINK_STATE
+#define STATUS_ATTN_EVENTS	(STATUS_ATTN_BITS_LINK_STATE | \
+				 STATUS_ATTN_BITS_TIMER_ABORT)
 
 static inline int
 bnx2_has_work(struct bnx2 *bp)
@@ -3548,6 +3842,36 @@
 	return rc;
 }
 
+static void
+bnx2_init_remote_phy(struct bnx2 *bp)
+{
+	u32 val;
+
+	bp->phy_flags &= ~REMOTE_PHY_CAP_FLAG;
+	if (!(bp->phy_flags & PHY_SERDES_FLAG))
+		return;
+
+	val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_CAP_MB);
+	if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE)
+		return;
+
+	if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) {
+		if (netif_running(bp->dev)) {
+			val = BNX2_DRV_ACK_CAP_SIGNATURE |
+			      BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
+			REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB,
+				   val);
+		}
+		bp->phy_flags |= REMOTE_PHY_CAP_FLAG;
+
+		val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
+		if (val & BNX2_LINK_STATUS_SERDES_LINK)
+			bp->phy_port = PORT_FIBRE;
+		else
+			bp->phy_port = PORT_TP;
+	}
+}
+
 static int
 bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
 {
@@ -3628,6 +3952,12 @@
 	if (rc)
 		return rc;
 
+	spin_lock_bh(&bp->phy_lock);
+	bnx2_init_remote_phy(bp);
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		bnx2_set_default_remote_link(bp);
+	spin_unlock_bh(&bp->phy_lock);
+
 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
 		/* Adjust the voltage regular to two steps lower.  The default
 		 * of this register is 0x0000000e. */
@@ -3691,9 +4021,11 @@
 
 	/* Initialize context mapping and zero out the quick contexts.  The
 	 * context block must have already been enabled. */
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		bnx2_init_5709_context(bp);
-	else
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		rc = bnx2_init_5709_context(bp);
+		if (rc)
+			return rc;
+	} else
 		bnx2_init_context(bp);
 
 	if ((rc = bnx2_init_cpus(bp)) != 0)
@@ -3772,7 +4104,10 @@
 	REG_WR(bp, BNX2_HC_CMD_TICKS,
 	       (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
 
-	REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
+	if (CHIP_NUM(bp) == CHIP_NUM_5708)
+		REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
+	else
+		REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
 	REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */
 
 	if (CHIP_ID(bp) == CHIP_ID_5706_A1)
@@ -3799,10 +4134,15 @@
 	/* Initialize the receive filter. */
 	bnx2_set_rx_mode(bp->dev);
 
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+		val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
+		REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+	}
 	rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
 			  0);
 
-	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
+	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
 	REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
 
 	udelay(20);
@@ -4045,8 +4385,8 @@
 
 	spin_lock_bh(&bp->phy_lock);
 	bnx2_init_phy(bp);
-	spin_unlock_bh(&bp->phy_lock);
 	bnx2_set_link(bp);
+	spin_unlock_bh(&bp->phy_lock);
 	return 0;
 }
 
@@ -4576,6 +4916,9 @@
 static void
 bnx2_5708_serdes_timer(struct bnx2 *bp)
 {
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return;
+
 	if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) {
 		bp->serdes_an_pending = 0;
 		return;
@@ -4607,7 +4950,6 @@
 bnx2_timer(unsigned long data)
 {
 	struct bnx2 *bp = (struct bnx2 *) data;
-	u32 msg;
 
 	if (!netif_running(bp->dev))
 		return;
@@ -4615,11 +4957,15 @@
 	if (atomic_read(&bp->intr_sem) != 0)
 		goto bnx2_restart_timer;
 
-	msg = (u32) ++bp->fw_drv_pulse_wr_seq;
-	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
+	bnx2_send_heart_beat(bp);
 
 	bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
 
+	/* workaround occasional corrupted counters */
+	if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks)
+		REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
+					    BNX2_HC_COMMAND_STATS_NOW);
+
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
 		if (CHIP_NUM(bp) == CHIP_NUM_5706)
 			bnx2_5706_serdes_timer(bp);
@@ -4786,19 +5132,6 @@
 
 	bnx2_netif_start(bp);
 }
-
-/* Called with rtnl_lock */
-static void
-bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	bnx2_netif_stop(bp);
-	vlan_group_set_device(bp->vlgrp, vid, NULL);
-	bnx2_set_rx_mode(dev);
-
-	bnx2_netif_start(bp);
-}
 #endif
 
 /* Called with netif_tx_lock.
@@ -5067,17 +5400,25 @@
 bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct bnx2 *bp = netdev_priv(dev);
+	int support_serdes = 0, support_copper = 0;
 
 	cmd->supported = SUPPORTED_Autoneg;
-	if (bp->phy_flags & PHY_SERDES_FLAG) {
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
+		support_serdes = 1;
+		support_copper = 1;
+	} else if (bp->phy_port == PORT_FIBRE)
+		support_serdes = 1;
+	else
+		support_copper = 1;
+
+	if (support_serdes) {
 		cmd->supported |= SUPPORTED_1000baseT_Full |
 			SUPPORTED_FIBRE;
 		if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)
 			cmd->supported |= SUPPORTED_2500baseX_Full;
 
-		cmd->port = PORT_FIBRE;
 	}
-	else {
+	if (support_copper) {
 		cmd->supported |= SUPPORTED_10baseT_Half |
 			SUPPORTED_10baseT_Full |
 			SUPPORTED_100baseT_Half |
@@ -5085,9 +5426,10 @@
 			SUPPORTED_1000baseT_Full |
 			SUPPORTED_TP;
 
-		cmd->port = PORT_TP;
 	}
 
+	spin_lock_bh(&bp->phy_lock);
+	cmd->port = bp->phy_port;
 	cmd->advertising = bp->advertising;
 
 	if (bp->autoneg & AUTONEG_SPEED) {
@@ -5105,6 +5447,7 @@
 		cmd->speed = -1;
 		cmd->duplex = -1;
 	}
+	spin_unlock_bh(&bp->phy_lock);
 
 	cmd->transceiver = XCVR_INTERNAL;
 	cmd->phy_address = bp->phy_addr;
@@ -5120,6 +5463,15 @@
 	u8 req_duplex = bp->req_duplex;
 	u16 req_line_speed = bp->req_line_speed;
 	u32 advertising = bp->advertising;
+	int err = -EINVAL;
+
+	spin_lock_bh(&bp->phy_lock);
+
+	if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE)
+		goto err_out_unlock;
+
+	if (cmd->port != bp->phy_port && !(bp->phy_flags & REMOTE_PHY_CAP_FLAG))
+		goto err_out_unlock;
 
 	if (cmd->autoneg == AUTONEG_ENABLE) {
 		autoneg |= AUTONEG_SPEED;
@@ -5132,44 +5484,41 @@
 			(cmd->advertising == ADVERTISED_100baseT_Half) ||
 			(cmd->advertising == ADVERTISED_100baseT_Full)) {
 
-			if (bp->phy_flags & PHY_SERDES_FLAG)
-				return -EINVAL;
+			if (cmd->port == PORT_FIBRE)
+				goto err_out_unlock;
 
 			advertising = cmd->advertising;
 
 		} else if (cmd->advertising == ADVERTISED_2500baseX_Full) {
-			if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
-				return -EINVAL;
-		} else if (cmd->advertising == ADVERTISED_1000baseT_Full) {
+			if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ||
+			    (cmd->port == PORT_TP))
+				goto err_out_unlock;
+		} else if (cmd->advertising == ADVERTISED_1000baseT_Full)
 			advertising = cmd->advertising;
-		}
-		else if (cmd->advertising == ADVERTISED_1000baseT_Half) {
-			return -EINVAL;
-		}
+		else if (cmd->advertising == ADVERTISED_1000baseT_Half)
+			goto err_out_unlock;
 		else {
-			if (bp->phy_flags & PHY_SERDES_FLAG) {
+			if (cmd->port == PORT_FIBRE)
 				advertising = ETHTOOL_ALL_FIBRE_SPEED;
-			}
-			else {
+			else
 				advertising = ETHTOOL_ALL_COPPER_SPEED;
-			}
 		}
 		advertising |= ADVERTISED_Autoneg;
 	}
 	else {
-		if (bp->phy_flags & PHY_SERDES_FLAG) {
+		if (cmd->port == PORT_FIBRE) {
 			if ((cmd->speed != SPEED_1000 &&
 			     cmd->speed != SPEED_2500) ||
 			    (cmd->duplex != DUPLEX_FULL))
-				return -EINVAL;
+				goto err_out_unlock;
 
 			if (cmd->speed == SPEED_2500 &&
 			    !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
-				return -EINVAL;
+				goto err_out_unlock;
 		}
-		else if (cmd->speed == SPEED_1000) {
-			return -EINVAL;
-		}
+		else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500)
+			goto err_out_unlock;
+
 		autoneg &= ~AUTONEG_SPEED;
 		req_line_speed = cmd->speed;
 		req_duplex = cmd->duplex;
@@ -5181,13 +5530,12 @@
 	bp->req_line_speed = req_line_speed;
 	bp->req_duplex = req_duplex;
 
-	spin_lock_bh(&bp->phy_lock);
+	err = bnx2_setup_phy(bp, cmd->port);
 
-	bnx2_setup_phy(bp);
-
+err_out_unlock:
 	spin_unlock_bh(&bp->phy_lock);
 
-	return 0;
+	return err;
 }
 
 static void
@@ -5198,11 +5546,7 @@
 	strcpy(info->driver, DRV_MODULE_NAME);
 	strcpy(info->version, DRV_MODULE_VERSION);
 	strcpy(info->bus_info, pci_name(bp->pdev));
-	info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0';
-	info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0';
-	info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0';
-	info->fw_version[1] = info->fw_version[3] = '.';
-	info->fw_version[5] = 0;
+	strcpy(info->fw_version, bp->fw_version);
 }
 
 #define BNX2_REGDUMP_LEN		(32 * 1024)
@@ -5314,6 +5658,14 @@
 
 	spin_lock_bh(&bp->phy_lock);
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
+		int rc;
+
+		rc = bnx2_setup_remote_phy(bp, bp->phy_port);
+		spin_unlock_bh(&bp->phy_lock);
+		return rc;
+	}
+
 	/* Force a link down visible on the other side */
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
 		bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
@@ -5430,6 +5782,10 @@
 		0xff;
 
 	bp->stats_ticks = coal->stats_block_coalesce_usecs;
+	if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+		if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
+			bp->stats_ticks = USEC_PER_SEC;
+	}
 	if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00;
 	bp->stats_ticks &= 0xffff00;
 
@@ -5523,7 +5879,7 @@
 
 	spin_lock_bh(&bp->phy_lock);
 
-	bnx2_setup_phy(bp);
+	bnx2_setup_phy(bp, bp->phy_port);
 
 	spin_unlock_bh(&bp->phy_lock);
 
@@ -5862,7 +6218,7 @@
 	struct bnx2 *bp = netdev_priv(dev);
 
 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		return (ethtool_op_set_tx_hw_csum(dev, data));
+		return (ethtool_op_set_tx_ipv6_csum(dev, data));
 	else
 		return (ethtool_op_set_tx_csum(dev, data));
 }
@@ -5919,6 +6275,9 @@
 	case SIOCGMIIREG: {
 		u32 mii_regval;
 
+		if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+			return -EOPNOTSUPP;
+
 		if (!netif_running(dev))
 			return -EAGAIN;
 
@@ -5935,6 +6294,9 @@
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
+		if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+			return -EOPNOTSUPP;
+
 		if (!netif_running(dev))
 			return -EAGAIN;
 
@@ -6096,7 +6458,7 @@
 {
 	struct bnx2 *bp;
 	unsigned long mem_len;
-	int rc;
+	int rc, i, j;
 	u32 reg;
 	u64 dma_mask, persist_dma_mask;
 
@@ -6253,7 +6615,35 @@
 		goto err_out_unmap;
 	}
 
-	bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+	for (i = 0, j = 0; i < 3; i++) {
+		u8 num, k, skip0;
+
+		num = (u8) (reg >> (24 - (i * 8)));
+		for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) {
+			if (num >= k || !skip0 || k == 1) {
+				bp->fw_version[j++] = (num / k) + '0';
+				skip0 = 0;
+			}
+		}
+		if (i != 2)
+			bp->fw_version[j++] = '.';
+	}
+	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_BC_STATE_CONDITION);
+	reg &= BNX2_CONDITION_MFW_RUN_MASK;
+	if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN &&
+	    reg != BNX2_CONDITION_MFW_RUN_NONE) {
+		int i;
+		u32 addr = REG_RD_IND(bp, bp->shmem_base + BNX2_MFW_VER_PTR);
+
+		bp->fw_version[j++] = ' ';
+		for (i = 0; i < 3; i++) {
+			reg = REG_RD_IND(bp, addr + i * 4);
+			reg = swab32(reg);
+			memcpy(&bp->fw_version[j], &reg, 4);
+			j += 4;
+		}
+	}
 
 	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER);
 	bp->mac_addr[0] = (u8) (reg >> 8);
@@ -6295,7 +6685,9 @@
 	else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
 		bp->phy_flags |= PHY_SERDES_FLAG;
 
+	bp->phy_port = PORT_TP;
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
+		bp->phy_port = PORT_FIBRE;
 		bp->flags |= NO_WOL_FLAG;
 		if (CHIP_NUM(bp) != CHIP_NUM_5706) {
 			bp->phy_addr = 2;
@@ -6304,6 +6696,8 @@
 			if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
 				bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
 		}
+		bnx2_init_remote_phy(bp);
+
 	} else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
 		   CHIP_NUM(bp) == CHIP_NUM_5708)
 		bp->phy_flags |= PHY_CRC_FIX_FLAG;
@@ -6343,10 +6737,9 @@
 		while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD,
 						  PCI_DEVICE_ID_AMD_8132_BRIDGE,
 						  amd_8132))) {
-			u8 rev;
 
-			pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev);
-			if (rev >= 0x10 && rev <= 0x13) {
+			if (amd_8132->revision >= 0x10 &&
+			    amd_8132->revision <= 0x13) {
 				disable_msi = 1;
 				pci_dev_put(amd_8132);
 				break;
@@ -6354,23 +6747,7 @@
 		}
 	}
 
-	bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
-	bp->req_line_speed = 0;
-	if (bp->phy_flags & PHY_SERDES_FLAG) {
-		bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
-
-		reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
-		reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
-		if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
-			bp->autoneg = 0;
-			bp->req_line_speed = bp->line_speed = SPEED_1000;
-			bp->req_duplex = DUPLEX_FULL;
-		}
-	}
-	else {
-		bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
-	}
-
+	bnx2_set_default_link(bp);
 	bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
 
 	init_timer(&bp->timer);
@@ -6453,7 +6830,6 @@
 	dev->watchdog_timeo = TX_TIMEOUT;
 #ifdef BCM_VLAN
 	dev->vlan_rx_register = bnx2_vlan_rx_register;
-	dev->vlan_rx_kill_vid = bnx2_vlan_rx_kill_vid;
 #endif
 	dev->poll = bnx2_poll;
 	dev->ethtool_ops = &bnx2_ethtool_ops;
@@ -6471,10 +6847,10 @@
 	memcpy(dev->perm_addr, bp->mac_addr, 6);
 	bp->name = board_info[ent->driver_data].name;
 
+	dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
-	else
-		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+		dev->features |= NETIF_F_IPV6_CSUM;
+
 #ifdef BCM_VLAN
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 #endif
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index bd6288d..d8cd1af 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -1373,6 +1373,7 @@
 #define BNX2_MISC_NEW_CORE_CTL				0x000008c8
 #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS	 (1L<<0)
 #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ		 (1L<<1)
+#define BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE		 (1L<<16)
 #define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN		 (0x3fffL<<2)
 #define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC		 (0xffffL<<16)
 
@@ -6337,6 +6338,8 @@
 
 #define RX_COPY_THRESH			92
 
+#define BNX2_MISC_ENABLE_DEFAULT	0x7ffffff
+
 #define DMA_READ_CHANS	5
 #define DMA_WRITE_CHANS	3
 
@@ -6536,6 +6539,7 @@
 #define PHY_INT_MODE_AUTO_POLLING_FLAG	0x100
 #define PHY_INT_MODE_LINK_READY_FLAG	0x200
 #define PHY_DIS_EARLY_DAC_FLAG		0x400
+#define REMOTE_PHY_CAP_FLAG		0x800
 
 	u32			mii_bmcr;
 	u32			mii_bmsr;
@@ -6624,6 +6628,7 @@
 	u16			req_line_speed;
 	u8			req_duplex;
 
+	u8			phy_port;
 	u8			link_up;
 
 	u16			line_speed;
@@ -6655,7 +6660,7 @@
 
 	u32			shmem_base;
 
-	u32			fw_ver;
+	char			fw_version[32];
 
 	int			pm_cap;
 	int			pcix_cap;
@@ -6769,7 +6774,7 @@
  * the firmware has timed out, the driver will assume there is no firmware
  * running and there won't be any firmware-driver synchronization during a
  * driver reset. */
-#define FW_ACK_TIME_OUT_MS                  100
+#define FW_ACK_TIME_OUT_MS                  1000
 
 
 #define BNX2_DRV_RESET_SIGNATURE		0x00000000
@@ -6787,6 +6792,7 @@
 #define BNX2_DRV_MSG_CODE_DIAG			 0x07000000
 #define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL	 0x09000000
 #define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN		 0x0b000000
+#define BNX2_DRV_MSG_CODE_CMD_SET_LINK		 0x10000000
 
 #define BNX2_DRV_MSG_DATA			 0x00ff0000
 #define BNX2_DRV_MSG_DATA_WAIT0			 0x00010000
@@ -6835,6 +6841,7 @@
 #define BNX2_LINK_STATUS_SERDES_LINK		 (1<<20)
 #define BNX2_LINK_STATUS_PARTNER_AD_2500FULL	 (1<<21)
 #define BNX2_LINK_STATUS_PARTNER_AD_2500HALF	 (1<<22)
+#define BNX2_LINK_STATUS_HEART_BEAT_EXPIRED	 (1<<31)
 
 #define BNX2_DRV_PULSE_MB			0x00000010
 #define BNX2_DRV_PULSE_SEQ_MASK			 0x00007fff
@@ -6844,6 +6851,30 @@
  * This is used for debugging. */
 #define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE	 0x00080000
 
+#define BNX2_DRV_MB_ARG0			0x00000014
+#define BNX2_NETLINK_SET_LINK_SPEED_10HALF	 (1<<0)
+#define BNX2_NETLINK_SET_LINK_SPEED_10FULL	 (1<<1)
+#define BNX2_NETLINK_SET_LINK_SPEED_10		 \
+	(BNX2_NETLINK_SET_LINK_SPEED_10HALF |	 \
+	 BNX2_NETLINK_SET_LINK_SPEED_10FULL)
+#define BNX2_NETLINK_SET_LINK_SPEED_100HALF	 (1<<2)
+#define BNX2_NETLINK_SET_LINK_SPEED_100FULL	 (1<<3)
+#define BNX2_NETLINK_SET_LINK_SPEED_100		 \
+	(BNX2_NETLINK_SET_LINK_SPEED_100HALF |	 \
+	 BNX2_NETLINK_SET_LINK_SPEED_100FULL)
+#define BNX2_NETLINK_SET_LINK_SPEED_1GHALF	 (1<<4)
+#define BNX2_NETLINK_SET_LINK_SPEED_1GFULL	 (1<<5)
+#define BNX2_NETLINK_SET_LINK_SPEED_2G5HALF	 (1<<6)
+#define BNX2_NETLINK_SET_LINK_SPEED_2G5FULL	 (1<<7)
+#define BNX2_NETLINK_SET_LINK_SPEED_10GHALF	 (1<<8)
+#define BNX2_NETLINK_SET_LINK_SPEED_10GFULL	 (1<<9)
+#define BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG	 (1<<10)
+#define BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE	 (1<<11)
+#define BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE	 (1<<12)
+#define BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE	 (1<<13)
+#define BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED	 (1<<14)
+#define BNX2_NETLINK_SET_LINK_PHY_RESET		 (1<<15)
+
 #define BNX2_DEV_INFO_SIGNATURE			0x00000020
 #define BNX2_DEV_INFO_SIGNATURE_MAGIC		 0x44564900
 #define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK	 0xffffff00
@@ -7005,6 +7036,8 @@
 #define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK	 0xffff
 #define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE	 0x10000
 
+#define BNX2_MFW_VER_PTR			0x00000014c
+
 #define BNX2_BC_STATE_RESET_TYPE		0x000001c0
 #define BNX2_BC_STATE_RESET_TYPE_SIG		 0x00005254
 #define BNX2_BC_STATE_RESET_TYPE_SIG_MASK	 0x0000ffff
@@ -7058,12 +7091,42 @@
 #define BNX2_BC_STATE_ERR_NO_RXP		 (BNX2_BC_STATE_SIGN | 0x0600)
 #define BNX2_BC_STATE_ERR_TOO_MANY_RBUF		 (BNX2_BC_STATE_SIGN | 0x0700)
 
+#define BNX2_BC_STATE_CONDITION			0x000001c8
+#define BNX2_CONDITION_MFW_RUN_UNKNOWN		 0x00000000
+#define BNX2_CONDITION_MFW_RUN_IPMI		 0x00002000
+#define BNX2_CONDITION_MFW_RUN_UMP		 0x00004000
+#define BNX2_CONDITION_MFW_RUN_NCSI		 0x00006000
+#define BNX2_CONDITION_MFW_RUN_NONE		 0x0000e000
+#define BNX2_CONDITION_MFW_RUN_MASK		 0x0000e000
+
 #define BNX2_BC_STATE_DEBUG_CMD			0x1dc
 #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE	 0x42440000
 #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK	 0xffff0000
 #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK	 0xffff
 #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE	 0xffff
 
+#define BNX2_FW_EVT_CODE_MB			0x354
+#define BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT 0x00000000
+#define BNX2_FW_EVT_CODE_LINK_EVENT		 0x00000001
+
+#define BNX2_DRV_ACK_CAP_MB			0x364
+#define BNX2_DRV_ACK_CAP_SIGNATURE		 0x35450000
+#define BNX2_CAPABILITY_SIGNATURE_MASK		 0xFFFF0000
+
+#define BNX2_FW_CAP_MB				0x368
+#define BNX2_FW_CAP_SIGNATURE			 0xaa550000
+#define BNX2_FW_ACK_DRV_SIGNATURE		 0x52500000
+#define BNX2_FW_CAP_SIGNATURE_MASK		 0xffff0000
+#define BNX2_FW_CAP_REMOTE_PHY_CAPABLE		 0x00000001
+#define BNX2_FW_CAP_REMOTE_PHY_PRESENT		 0x00000002
+
+#define BNX2_RPHY_SIGNATURE			0x36c
+#define BNX2_RPHY_LOAD_SIGNATURE		 0x5a5a5a5a
+
+#define BNX2_RPHY_FLAGS				0x370
+#define BNX2_RPHY_SERDES_LINK			0x374
+#define BNX2_RPHY_COPPER_LINK			0x378
+
 #define HOST_VIEW_SHMEM_BASE			0x167c00
 
 #endif
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 7e03f41..f829e4a 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2303,19 +2303,18 @@
 }
 
 /*
- * set link state for bonding master: if we have an active partnered
+ * set link state for bonding master: if we have an active 
  * aggregator, we're up, if not, we're down.  Presumes that we cannot
  * have an active aggregator if there are no slaves with link up.
  *
+ * This behavior complies with IEEE 802.3 section 43.3.9.
+ *
  * Called by bond_set_carrier(). Return zero if carrier state does not
  * change, nonzero if it does.
  */
 int bond_3ad_set_carrier(struct bonding *bond)
 {
-	struct aggregator *agg;
-
-	agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
-	if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) {
+	if (__get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator))) {
 		if (!netif_carrier_ok(bond->dev)) {
 			netif_carrier_on(bond->dev);
 			return 1;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 223517d..cb9cb30 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -187,7 +187,7 @@
 
 /*---------------------------- General routines -----------------------------*/
 
-const char *bond_mode_name(int mode)
+static const char *bond_mode_name(int mode)
 {
 	switch (mode) {
 	case BOND_MODE_ROUNDROBIN :
@@ -1224,7 +1224,8 @@
 
 /*---------------------------------- IOCTL ----------------------------------*/
 
-int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+static int bond_sethwaddr(struct net_device *bond_dev,
+			  struct net_device *slave_dev)
 {
 	dprintk("bond_dev=%p\n", bond_dev);
 	dprintk("slave_dev=%p\n", slave_dev);
@@ -1390,6 +1391,11 @@
 		goto err_free;
 	}
 
+	res = netdev_set_master(slave_dev, bond_dev);
+	if (res) {
+		dprintk("Error %d calling netdev_set_master\n", res);
+		goto err_close;
+	}
 	/* open the slave since the application closed it */
 	res = dev_open(slave_dev);
 	if (res) {
@@ -1397,12 +1403,6 @@
 		goto err_restore_mac;
 	}
 
-	res = netdev_set_master(slave_dev, bond_dev);
-	if (res) {
-		dprintk("Error %d calling netdev_set_master\n", res);
-		goto err_close;
-	}
-
 	new_slave->dev = slave_dev;
 	slave_dev->priv_flags |= IFF_BONDING;
 
@@ -4345,8 +4345,8 @@
 		bond_mc_list_destroy(bond);
 		/* Release the bonded slaves */
 		bond_release_all(bond_dev);
-		unregister_netdevice(bond_dev);
 		bond_deinit(bond_dev);
+		unregister_netdevice(bond_dev);
 	}
 
 #ifdef CONFIG_PROC_FS
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index a122baa..60cccf2 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -164,9 +164,9 @@
 				printk(KERN_INFO DRV_NAME
 					": %s is being deleted...\n",
 					bond->dev->name);
-				unregister_netdevice(bond->dev);
 				bond_deinit(bond->dev);
 		        	bond_destroy_sysfs_entry(bond);
+				unregister_netdevice(bond->dev);
 				rtnl_unlock();
 				goto out;
 			}
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 41aa78b..6dcbd25 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -22,8 +22,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"3.1.2"
-#define DRV_RELDATE	"January 20, 2007"
+#define DRV_VERSION	"3.1.3"
+#define DRV_RELDATE	"June 13, 2007"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
@@ -301,13 +301,11 @@
 void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
 int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
-int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
 void bond_mii_monitor(struct net_device *bond_dev);
 void bond_loadbalance_arp_mon(struct net_device *bond_dev);
 void bond_activebackup_arp_mon(struct net_device *bond_dev);
 void bond_set_mode_ops(struct bonding *bond, int mode);
 int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
-const char *bond_mode_name(int mode);
 void bond_select_active_slave(struct bonding *bond);
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
 void bond_register_arp(struct bonding *);
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 4aec747..f6e4030 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -3422,21 +3422,19 @@
 static void cas_check_pci_invariants(struct cas *cp)
 {
 	struct pci_dev *pdev = cp->pdev;
-	u8 rev;
 
 	cp->cas_flags = 0;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
 	if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
 	    (pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) {
-		if (rev >= CAS_ID_REVPLUS)
+		if (pdev->revision >= CAS_ID_REVPLUS)
 			cp->cas_flags |= CAS_FLAG_REG_PLUS;
-		if (rev < CAS_ID_REVPLUS02u)
+		if (pdev->revision < CAS_ID_REVPLUS02u)
 			cp->cas_flags |= CAS_FLAG_TARGET_ABORT;
 
 		/* Original Cassini supports HW CSUM, but it's not
 		 * enabled by default as it can trigger TX hangs.
 		 */
-		if (rev < CAS_ID_REV2)
+		if (pdev->revision < CAS_ID_REV2)
 			cp->cas_flags |= CAS_FLAG_NO_HW_CSUM;
 	} else {
 		/* Only sun has original cassini chips.  */
@@ -4919,10 +4917,13 @@
 	pci_cmd &= ~PCI_COMMAND_SERR;
 	pci_cmd |= PCI_COMMAND_PARITY;
 	pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
-	pci_set_mwi(pdev);
+	if (pci_try_set_mwi(pdev))
+		printk(KERN_WARNING PFX "Could not enable MWI for %s\n",
+		       pci_name(pdev));
+
 	/*
 	 * On some architectures, the default cache line size set
-	 * by pci_set_mwi reduces perforamnce.  We have to increase
+	 * by pci_try_set_mwi reduces perforamnce.  We have to increase
 	 * it for this case.  To start, we'll print some configuration
 	 * data.
 	 */
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 125c9b1..231ce43 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -883,15 +883,6 @@
 	t1_set_vlan_accel(adapter, grp != NULL);
 	spin_unlock_irq(&adapter->async_lock);
 }
-
-static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct adapter *adapter = dev->priv;
-
-	spin_lock_irq(&adapter->async_lock);
-	vlan_group_set_device(adapter->vlan_grp, vid, NULL);
-	spin_unlock_irq(&adapter->async_lock);
-}
 #endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1099,7 +1090,6 @@
 			netdev->features |=
 				NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 			netdev->vlan_rx_register = vlan_rx_register;
-			netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
 #endif
 
 			/* T204: disable TSO */
diff --git a/drivers/net/chelsio/suni1x10gexp_regs.h b/drivers/net/chelsio/suni1x10gexp_regs.h
index 269d097..d0f87d8 100644
--- a/drivers/net/chelsio/suni1x10gexp_regs.h
+++ b/drivers/net/chelsio/suni1x10gexp_regs.h
@@ -105,7 +105,7 @@
 #define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_LOW(filterId) (0x204A + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
 #define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_MID(filterId) (0x204B + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
 #define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_HIGH(filterId)(0x204C + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
-#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID(filterId)      (0x2062 + mSUNI1x10GEXP_MAC_VID_FILTER_OFFSET(filterId)
+#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID(filterId)      (0x2062 + mSUNI1x10GEXP_MAC_VID_FILTER_OFFSET(filterId))
 #define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_LOW                     0x204A
 #define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_MID                     0x204B
 #define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_HIGH                    0x204C
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 80c3d8f..ab72563 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -71,27 +71,29 @@
 	QUEUES_BOUND = (1 << 3),
 };
 
+struct fl_pg_chunk {
+	struct page *page;
+	void *va;
+	unsigned int offset;
+};
+
 struct rx_desc;
 struct rx_sw_desc;
 
-struct sge_fl_page {
-	struct skb_frag_struct frag;
-	unsigned char *va;
-};
-
-struct sge_fl {			/* SGE per free-buffer list state */
-	unsigned int buf_size;	/* size of each Rx buffer */
-	unsigned int credits;	/* # of available Rx buffers */
-	unsigned int size;	/* capacity of free list */
-	unsigned int cidx;	/* consumer index */
-	unsigned int pidx;	/* producer index */
-	unsigned int gen;	/* free list generation */
-	unsigned int cntxt_id;	/* SGE context id for the free list */
-	struct sge_fl_page page;
-	struct rx_desc *desc;	/* address of HW Rx descriptor ring */
-	struct rx_sw_desc *sdesc;	/* address of SW Rx descriptor ring */
-	dma_addr_t phys_addr;	/* physical address of HW ring start */
-	unsigned long empty;	/* # of times queue ran out of buffers */
+struct sge_fl {                     /* SGE per free-buffer list state */
+	unsigned int buf_size;      /* size of each Rx buffer */
+	unsigned int credits;       /* # of available Rx buffers */
+	unsigned int size;          /* capacity of free list */
+	unsigned int cidx;          /* consumer index */
+	unsigned int pidx;          /* producer index */
+	unsigned int gen;           /* free list generation */
+	struct fl_pg_chunk pg_chunk;/* page chunk cache */
+	unsigned int use_pages;     /* whether FL uses pages or sk_buffs */
+	struct rx_desc *desc;       /* address of HW Rx descriptor ring */
+	struct rx_sw_desc *sdesc;   /* address of SW Rx descriptor ring */
+	dma_addr_t   phys_addr;     /* physical address of HW ring start */
+	unsigned int cntxt_id;      /* SGE context id for the free list */
+	unsigned long empty;        /* # of times queue ran out of buffers */
 	unsigned long alloc_failed; /* # of times buffer allocation failed */
 };
 
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c
index 73a41e6..ee140e6 100644
--- a/drivers/net/cxgb3/ael1002.c
+++ b/drivers/net/cxgb3/ael1002.c
@@ -219,7 +219,13 @@
 		unsigned int status;
 
 		status = t3_read_reg(phy->adapter,
-				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr));
+				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
+		    t3_read_reg(phy->adapter,
+				XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
+		    t3_read_reg(phy->adapter,
+				XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
+		    t3_read_reg(phy->adapter,
+				XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
 		*link_ok = !(status & F_LOWSIG0);
 	}
 	if (speed)
@@ -247,5 +253,5 @@
 void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
 			     int phy_addr, const struct mdio_ops *mdio_ops)
 {
-	cphy_init(phy, adapter, 1, &xaui_direct_ops, mdio_ops);
+	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops);
 }
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 8d13796..1637800 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -101,6 +101,7 @@
 	TCB_SIZE = 128,		/* TCB size */
 	NMTUS = 16,		/* size of MTU table */
 	NCCTRL_WIN = 32,	/* # of congestion control windows */
+	PROTO_SRAM_LINES = 128, /* size of TP sram */
 };
 
 #define MAX_RX_COALESCING_LEN 16224U
@@ -124,6 +125,30 @@
 };
 
 enum {
+	TP_VERSION_MAJOR	= 1,
+	TP_VERSION_MINOR	= 0,
+	TP_VERSION_MICRO	= 44
+};
+
+#define S_TP_VERSION_MAJOR		16
+#define M_TP_VERSION_MAJOR		0xFF
+#define V_TP_VERSION_MAJOR(x)		((x) << S_TP_VERSION_MAJOR)
+#define G_TP_VERSION_MAJOR(x)		\
+	    (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR)
+
+#define S_TP_VERSION_MINOR		8
+#define M_TP_VERSION_MINOR		0xFF
+#define V_TP_VERSION_MINOR(x)		((x) << S_TP_VERSION_MINOR)
+#define G_TP_VERSION_MINOR(x)		\
+	    (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR)
+
+#define S_TP_VERSION_MICRO		0
+#define M_TP_VERSION_MICRO		0xFF
+#define V_TP_VERSION_MICRO(x)		((x) << S_TP_VERSION_MICRO)
+#define G_TP_VERSION_MICRO(x)		\
+	    (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO)
+
+enum {
 	SGE_QSETS = 8,		/* # of SGE Tx/Rx/RspQ sets */
 	SGE_RXQ_PER_SET = 2,	/* # of Rx queues per set */
 	SGE_TXQ_PER_SET = 3	/* # of Tx queues per set */
@@ -654,6 +679,9 @@
 int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);
 int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data);
 int t3_seeprom_wp(struct adapter *adapter, int enable);
+int t3_check_tpsram_version(struct adapter *adapter);
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size);
+int t3_set_proto_sram(struct adapter *adap, u8 *data);
 int t3_read_flash(struct adapter *adapter, unsigned int addr,
 		  unsigned int nwords, u32 *data, int byte_oriented);
 int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 67b4b21..6fd1e52 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -43,6 +43,7 @@
 #include <linux/proc_fs.h>
 #include <linux/rtnetlink.h>
 #include <linux/firmware.h>
+#include <linux/log2.h>
 #include <asm/uaccess.h>
 
 #include "common.h"
@@ -1818,8 +1819,8 @@
 			return -EBUSY;
 		if (copy_from_user(&m, useraddr, sizeof(m)))
 			return -EFAULT;
-		if (!m.rx_pg_sz || (m.rx_pg_sz & (m.rx_pg_sz - 1)) ||
-			!m.tx_pg_sz || (m.tx_pg_sz & (m.tx_pg_sz - 1)))
+		if (!is_power_of_2(m.rx_pg_sz) ||
+			!is_power_of_2(m.tx_pg_sz))
 			return -EINVAL;	/* not power of 2 */
 		if (!(m.rx_pg_sz & 0x14000))
 			return -EINVAL;	/* not 16KB or 64KB */
@@ -2067,22 +2068,63 @@
 	t3_synchronize_rx(adapter, pi);
 }
 
-static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	/* nothing */
-}
-
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void cxgb_netpoll(struct net_device *dev)
 {
 	struct adapter *adapter = dev->priv;
-	struct sge_qset *qs = dev2qset(dev);
+	struct port_info *pi = netdev_priv(dev);
+	int qidx;
 
-	t3_intr_handler(adapter, qs->rspq.polling) (adapter->pdev->irq,
-						    adapter);
+	for (qidx = pi->first_qset; qidx < pi->first_qset + pi->nqsets; qidx++) {
+		struct sge_qset *qs = &adapter->sge.qs[qidx];
+		void *source;
+		
+		if (adapter->flags & USING_MSIX)
+			source = qs;
+		else
+			source = adapter;
+
+		t3_intr_handler(adapter, qs->rspq.polling) (0, source);
+	}
 }
 #endif
 
+#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin"
+int update_tpsram(struct adapter *adap)
+{
+	const struct firmware *tpsram;
+	char buf[64];
+	struct device *dev = &adap->pdev->dev;
+	int ret;
+	char rev;
+	
+	rev = adap->params.rev == T3_REV_B2 ? 'b' : 'a';
+
+	snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
+		 TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+
+	ret = request_firmware(&tpsram, buf, dev);
+	if (ret < 0) {
+		dev_err(dev, "could not load TP SRAM: unable to load %s\n",
+			buf);
+		return ret;
+	}
+	
+	ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
+	if (ret)
+		goto release_tpsram;	
+
+	ret = t3_set_proto_sram(adap, tpsram->data);
+	if (ret)
+		dev_err(dev, "loading protocol SRAM failed\n");
+
+release_tpsram:
+	release_firmware(tpsram);
+	
+	return ret;
+}
+
+
 /*
  * Periodic accumulation of MAC statistics.
  */
@@ -2409,7 +2451,6 @@
 
 		netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 		netdev->vlan_rx_register = vlan_rx_register;
-		netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
 
 		netdev->open = cxgb_open;
 		netdev->stop = cxgb_close;
@@ -2433,6 +2474,13 @@
 		goto out_free_dev;
 	}
 
+	err = t3_check_tpsram_version(adapter);
+	if (err == -EINVAL)
+		err = update_tpsram(adapter);
+
+	if (err)
+		goto out_free_dev;
+		
 	/*
 	 * The card is now ready to go.  If any errors occur during device
 	 * registration we do not fail the whole card but rather proceed only
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index e5a5534..aa80313 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -1160,6 +1160,8 @@
 
 #define A_TP_MOD_CHANNEL_WEIGHT 0x434
 
+#define A_TP_MOD_RATE_LIMIT 0x438
+
 #define A_TP_PIO_ADDR 0x440
 
 #define A_TP_PIO_DATA 0x444
@@ -1214,6 +1216,15 @@
 #define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \
 			       M_TXDROPCNTCH0RCVD)
 
+#define A_TP_PROXY_FLOW_CNTL 0x4b0
+
+#define A_TP_EMBED_OP_FIELD0 0x4e8
+#define A_TP_EMBED_OP_FIELD1 0x4ec
+#define A_TP_EMBED_OP_FIELD2 0x4f0
+#define A_TP_EMBED_OP_FIELD3 0x4f4
+#define A_TP_EMBED_OP_FIELD4 0x4f8
+#define A_TP_EMBED_OP_FIELD5 0x4fc
+
 #define A_ULPRX_CTL 0x500
 
 #define S_ROUND_ROBIN    4
@@ -1882,6 +1893,10 @@
 #define V_COPYALLFRAMES(x) ((x) << S_COPYALLFRAMES)
 #define F_COPYALLFRAMES    V_COPYALLFRAMES(1U)
 
+#define S_DISBCAST    1
+#define V_DISBCAST(x) ((x) << S_DISBCAST)
+#define F_DISBCAST    V_DISBCAST(1U)
+
 #define A_XGM_RX_HASH_LOW 0x814
 
 #define A_XGM_RX_HASH_HIGH 0x818
@@ -2128,6 +2143,8 @@
 #define F_RESETPLL01    V_RESETPLL01(1U)
 
 #define A_XGM_SERDES_STAT0 0x8f0
+#define A_XGM_SERDES_STAT1 0x8f4
+#define A_XGM_SERDES_STAT2 0x8f8
 
 #define S_LOWSIG0    0
 #define V_LOWSIG0(x) ((x) << S_LOWSIG0)
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 3666586..a2cfd68 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -46,23 +46,16 @@
 
 #define SGE_RX_SM_BUF_SIZE 1536
 
-/*
- * If USE_RX_PAGE is defined, the small freelist populated with (partial)
- * pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must
- * be a multiple of the host page size).
- */
-#define USE_RX_PAGE
-#define RX_PAGE_SIZE 2048
-
-/*
- * skb freelist packets are copied into a new skb (and the freelist one is 
- * reused) if their len is <= 
- */
 #define SGE_RX_COPY_THRES  256
+#define SGE_RX_PULL_LEN    128
 
 /*
- * Minimum number of freelist entries before we start dropping TUNNEL frames.
+ * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
+ * It must be a divisor of PAGE_SIZE.  If set to 0 FL0 will use sk_buffs
+ * directly.
  */
+#define FL0_PG_CHUNK_SIZE  2048
+
 #define SGE_RX_DROP_THRES 16
 
 /*
@@ -100,12 +93,12 @@
 	struct sk_buff *skb;
 };
 
-struct rx_sw_desc {		/* SW state per Rx descriptor */
+struct rx_sw_desc {                /* SW state per Rx descriptor */
 	union {
 		struct sk_buff *skb;
-		struct sge_fl_page page;
-	} t;
-	 DECLARE_PCI_UNMAP_ADDR(dma_addr);
+		struct fl_pg_chunk pg_chunk;
+	};
+	DECLARE_PCI_UNMAP_ADDR(dma_addr);
 };
 
 struct rsp_desc {		/* response queue descriptor */
@@ -351,27 +344,26 @@
 
 		pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr),
 				 q->buf_size, PCI_DMA_FROMDEVICE);
-
-		if (q->buf_size != RX_PAGE_SIZE) {
-			kfree_skb(d->t.skb);
-			d->t.skb = NULL;
+		if (q->use_pages) {
+			put_page(d->pg_chunk.page);
+			d->pg_chunk.page = NULL;
 		} else {
-			if (d->t.page.frag.page)
-				put_page(d->t.page.frag.page);
-			d->t.page.frag.page = NULL;
+			kfree_skb(d->skb);
+			d->skb = NULL;
 		}
 		if (++cidx == q->size)
 			cidx = 0;
 	}
 
-	if (q->page.frag.page)
-		put_page(q->page.frag.page);
-	q->page.frag.page = NULL;
+	if (q->pg_chunk.page) {
+		__free_page(q->pg_chunk.page);
+		q->pg_chunk.page = NULL;
+	}
 }
 
 /**
  *	add_one_rx_buf - add a packet buffer to a free-buffer list
- *	@va: va of the buffer to add
+ *	@va:  buffer start VA
  *	@len: the buffer length
  *	@d: the HW Rx descriptor to write
  *	@sd: the SW Rx descriptor to write
@@ -381,7 +373,7 @@
  *	Add a buffer of the given length to the supplied HW and SW Rx
  *	descriptors.
  */
-static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
+static inline void add_one_rx_buf(void *va, unsigned int len,
 				  struct rx_desc *d, struct rx_sw_desc *sd,
 				  unsigned int gen, struct pci_dev *pdev)
 {
@@ -397,6 +389,27 @@
 	d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
 }
 
+static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
+{
+	if (!q->pg_chunk.page) {
+		q->pg_chunk.page = alloc_page(gfp);
+		if (unlikely(!q->pg_chunk.page))
+			return -ENOMEM;
+		q->pg_chunk.va = page_address(q->pg_chunk.page);
+		q->pg_chunk.offset = 0;
+	}
+	sd->pg_chunk = q->pg_chunk;
+
+	q->pg_chunk.offset += q->buf_size;
+	if (q->pg_chunk.offset == PAGE_SIZE)
+		q->pg_chunk.page = NULL;
+	else {
+		q->pg_chunk.va += q->buf_size;
+		get_page(q->pg_chunk.page);
+	}
+	return 0;
+}
+
 /**
  *	refill_fl - refill an SGE free-buffer list
  *	@adapter: the adapter
@@ -410,49 +423,29 @@
  */
 static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
 {
+	void *buf_start;
 	struct rx_sw_desc *sd = &q->sdesc[q->pidx];
 	struct rx_desc *d = &q->desc[q->pidx];
-	struct sge_fl_page *p = &q->page;
 
 	while (n--) {
-		unsigned char *va;
-
-		if (unlikely(q->buf_size != RX_PAGE_SIZE)) {
-			struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
-
-			if (!skb) {
-				q->alloc_failed++;
+		if (q->use_pages) {
+			if (unlikely(alloc_pg_chunk(q, sd, gfp))) {
+nomem:				q->alloc_failed++;
 				break;
 			}
-			va = skb->data;
-			sd->t.skb = skb;
+			buf_start = sd->pg_chunk.va;
 		} else {
-			if (!p->frag.page) {
-				p->frag.page = alloc_pages(gfp, 0);
-				if (unlikely(!p->frag.page)) {
-					q->alloc_failed++;
-					break;
-				} else {
-					p->frag.size = RX_PAGE_SIZE;
-					p->frag.page_offset = 0;
-					p->va = page_address(p->frag.page);
-				}
-			}
+			struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
 
-			memcpy(&sd->t, p, sizeof(*p));
-			va = p->va;
+			if (!skb)
+				goto nomem;
 
-			p->frag.page_offset += RX_PAGE_SIZE;
-			BUG_ON(p->frag.page_offset > PAGE_SIZE);
-			p->va += RX_PAGE_SIZE;
-			if (p->frag.page_offset == PAGE_SIZE)
-				p->frag.page = NULL;
-			else
-				get_page(p->frag.page);
+			sd->skb = skb;
+			buf_start = skb->data;
 		}
 
-		add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev);
-
+		add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen,
+			       adap->pdev);
 		d++;
 		sd++;
 		if (++q->pidx == q->size) {
@@ -487,7 +480,7 @@
 	struct rx_desc *from = &q->desc[idx];
 	struct rx_desc *to = &q->desc[q->pidx];
 
-	memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc));
+	q->sdesc[q->pidx] = q->sdesc[idx];
 	to->addr_lo = from->addr_lo;	/* already big endian */
 	to->addr_hi = from->addr_hi;	/* likewise */
 	wmb();
@@ -650,6 +643,132 @@
 }
 
 /**
+ *	get_packet - return the next ingress packet buffer from a free list
+ *	@adap: the adapter that received the packet
+ *	@fl: the SGE free list holding the packet
+ *	@len: the packet length including any SGE padding
+ *	@drop_thres: # of remaining buffers before we start dropping packets
+ *
+ *	Get the next packet from a free list and complete setup of the
+ *	sk_buff.  If the packet is small we make a copy and recycle the
+ *	original buffer, otherwise we use the original buffer itself.  If a
+ *	positive drop threshold is supplied packets are dropped and their
+ *	buffers recycled if (a) the number of remaining buffers is under the
+ *	threshold and the packet is too big to copy, or (b) the packet should
+ *	be copied but there is no memory for the copy.
+ */
+static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
+				  unsigned int len, unsigned int drop_thres)
+{
+	struct sk_buff *skb = NULL;
+	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+	prefetch(sd->skb->data);
+	fl->credits--;
+
+	if (len <= SGE_RX_COPY_THRES) {
+		skb = alloc_skb(len, GFP_ATOMIC);
+		if (likely(skb != NULL)) {
+			__skb_put(skb, len);
+			pci_dma_sync_single_for_cpu(adap->pdev,
+					    pci_unmap_addr(sd, dma_addr), len,
+					    PCI_DMA_FROMDEVICE);
+			memcpy(skb->data, sd->skb->data, len);
+			pci_dma_sync_single_for_device(adap->pdev,
+					    pci_unmap_addr(sd, dma_addr), len,
+					    PCI_DMA_FROMDEVICE);
+		} else if (!drop_thres)
+			goto use_orig_buf;
+recycle:
+		recycle_rx_buf(adap, fl, fl->cidx);
+		return skb;
+	}
+
+	if (unlikely(fl->credits < drop_thres))
+		goto recycle;
+
+use_orig_buf:
+	pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+			 fl->buf_size, PCI_DMA_FROMDEVICE);
+	skb = sd->skb;
+	skb_put(skb, len);
+	__refill_fl(adap, fl);
+	return skb;
+}
+
+/**
+ *	get_packet_pg - return the next ingress packet buffer from a free list
+ *	@adap: the adapter that received the packet
+ *	@fl: the SGE free list holding the packet
+ *	@len: the packet length including any SGE padding
+ *	@drop_thres: # of remaining buffers before we start dropping packets
+ *
+ *	Get the next packet from a free list populated with page chunks.
+ *	If the packet is small we make a copy and recycle the original buffer,
+ *	otherwise we attach the original buffer as a page fragment to a fresh
+ *	sk_buff.  If a positive drop threshold is supplied packets are dropped
+ *	and their buffers recycled if (a) the number of remaining buffers is
+ *	under the threshold and the packet is too big to copy, or (b) there's
+ *	no system memory.
+ *
+ * 	Note: this function is similar to @get_packet but deals with Rx buffers
+ * 	that are page chunks rather than sk_buffs.
+ */
+static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
+				     unsigned int len, unsigned int drop_thres)
+{
+	struct sk_buff *skb = NULL;
+	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+	if (len <= SGE_RX_COPY_THRES) {
+		skb = alloc_skb(len, GFP_ATOMIC);
+		if (likely(skb != NULL)) {
+			__skb_put(skb, len);
+			pci_dma_sync_single_for_cpu(adap->pdev,
+					    pci_unmap_addr(sd, dma_addr), len,
+					    PCI_DMA_FROMDEVICE);
+			memcpy(skb->data, sd->pg_chunk.va, len);
+			pci_dma_sync_single_for_device(adap->pdev,
+					    pci_unmap_addr(sd, dma_addr), len,
+					    PCI_DMA_FROMDEVICE);
+		} else if (!drop_thres)
+			return NULL;
+recycle:
+		fl->credits--;
+		recycle_rx_buf(adap, fl, fl->cidx);
+		return skb;
+	}
+
+	if (unlikely(fl->credits <= drop_thres))
+		goto recycle;
+
+	skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
+	if (unlikely(!skb)) {
+		if (!drop_thres)
+			return NULL;
+		goto recycle;
+	}
+
+	pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+			 fl->buf_size, PCI_DMA_FROMDEVICE);
+	__skb_put(skb, SGE_RX_PULL_LEN);
+	memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
+	skb_fill_page_desc(skb, 0, sd->pg_chunk.page,
+			   sd->pg_chunk.offset + SGE_RX_PULL_LEN,
+			   len - SGE_RX_PULL_LEN);
+	skb->len = len;
+	skb->data_len = len - SGE_RX_PULL_LEN;
+	skb->truesize += skb->data_len;
+
+	fl->credits--;
+	/*
+	 * We do not refill FLs here, we let the caller do it to overlap a
+	 * prefetch.
+	 */
+	return skb;
+}
+
+/**
  *	get_imm_packet - return the next ingress packet buffer from a response
  *	@resp: the response descriptor containing the packet data
  *
@@ -1690,8 +1809,8 @@
 	struct port_info *pi;
 
 	skb_pull(skb, sizeof(*p) + pad);
-	skb->dev->last_rx = jiffies;
 	skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
+	skb->dev->last_rx = jiffies;
 	pi = netdev_priv(skb->dev);
 	if (pi->rx_csum_offload && p->csum_valid && p->csum == 0xffff &&
 	    !p->fragment) {
@@ -1715,85 +1834,6 @@
 		netif_rx(skb);
 }
 
-#define SKB_DATA_SIZE 128
-
-static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p,
-			  unsigned int len)
-{
-	skb->len = len;
-	if (len <= SKB_DATA_SIZE) {
-		skb_copy_to_linear_data(skb, p->va, len);
-		skb->tail += len;
-		put_page(p->frag.page);
-	} else {
-		skb_copy_to_linear_data(skb, p->va, SKB_DATA_SIZE);
-		skb_shinfo(skb)->frags[0].page = p->frag.page;
-		skb_shinfo(skb)->frags[0].page_offset =
-		    p->frag.page_offset + SKB_DATA_SIZE;
-		skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE;
-		skb_shinfo(skb)->nr_frags = 1;
-		skb->data_len = len - SKB_DATA_SIZE;
-		skb->tail += SKB_DATA_SIZE;
-		skb->truesize += skb->data_len;
-	}
-}
-
-/**
-*      get_packet - return the next ingress packet buffer from a free list
-*      @adap: the adapter that received the packet
-*      @fl: the SGE free list holding the packet
-*      @len: the packet length including any SGE padding
-*      @drop_thres: # of remaining buffers before we start dropping packets
-*
-*      Get the next packet from a free list and complete setup of the
-*      sk_buff.  If the packet is small we make a copy and recycle the
-*      original buffer, otherwise we use the original buffer itself.  If a
-*      positive drop threshold is supplied packets are dropped and their
-*      buffers recycled if (a) the number of remaining buffers is under the
-*      threshold and the packet is too big to copy, or (b) the packet should
-*      be copied but there is no memory for the copy.
-*/
-static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
-				  unsigned int len, unsigned int drop_thres)
-{
-	struct sk_buff *skb = NULL;
-	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-
-	prefetch(sd->t.skb->data);
-
-	if (len <= SGE_RX_COPY_THRES) {
-		skb = alloc_skb(len, GFP_ATOMIC);
-		if (likely(skb != NULL)) {
-			struct rx_desc *d = &fl->desc[fl->cidx];
-			dma_addr_t mapping =
-			    (dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 |
-					 be32_to_cpu(d->addr_lo));
-
-			__skb_put(skb, len);
-			pci_dma_sync_single_for_cpu(adap->pdev, mapping, len,
-						    PCI_DMA_FROMDEVICE);
-			skb_copy_from_linear_data(sd->t.skb, skb->data, len);
-			pci_dma_sync_single_for_device(adap->pdev, mapping, len,
-						       PCI_DMA_FROMDEVICE);
-		} else if (!drop_thres)
-			goto use_orig_buf;
-recycle:
-		recycle_rx_buf(adap, fl, fl->cidx);
-		return skb;
-	}
-
-	if (unlikely(fl->credits < drop_thres))
-		goto recycle;
-
-use_orig_buf:
-	pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
-			 fl->buf_size, PCI_DMA_FROMDEVICE);
-	skb = sd->t.skb;
-	skb_put(skb, len);
-	__refill_fl(adap, fl);
-	return skb;
-}
-
 /**
  *	handle_rsp_cntrl_info - handles control information in a response
  *	@qs: the queue set corresponding to the response
@@ -1935,7 +1975,7 @@
 		} else if (flags & F_RSPD_IMM_DATA_VALID) {
 			skb = get_imm_packet(r);
 			if (unlikely(!skb)) {
-			      no_mem:
+no_mem:
 				q->next_holdoff = NOMEM_INTR_DELAY;
 				q->nomem++;
 				/* consume one credit since we tried */
@@ -1945,53 +1985,29 @@
 			q->imm_data++;
 			ethpad = 0;
 		} else if ((len = ntohl(r->len_cq)) != 0) {
-			struct sge_fl *fl =
-			    (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+			struct sge_fl *fl;
 
-			if (fl->buf_size == RX_PAGE_SIZE) {
-				struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-				struct sge_fl_page *p = &sd->t.page;
+			fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+			if (fl->use_pages) {
+				void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
 
-				prefetch(p->va);
-				prefetch(p->va + L1_CACHE_BYTES);
-
+				prefetch(addr);
+#if L1_CACHE_BYTES < 128
+				prefetch(addr + L1_CACHE_BYTES);
+#endif
 				__refill_fl(adap, fl);
 
-				pci_unmap_single(adap->pdev,
-						 pci_unmap_addr(sd, dma_addr),
-						 fl->buf_size,
-						 PCI_DMA_FROMDEVICE);
-
-				if (eth) {
-					if (unlikely(fl->credits <
-						     SGE_RX_DROP_THRES))
-						goto eth_recycle;
-
-					skb = alloc_skb(SKB_DATA_SIZE,
-							GFP_ATOMIC);
-					if (unlikely(!skb)) {
-eth_recycle:
-						q->rx_drops++;
-						recycle_rx_buf(adap, fl,
-							       fl->cidx);
-						goto eth_done;
-					}
-				} else {
-					skb = alloc_skb(SKB_DATA_SIZE,
-							GFP_ATOMIC);
-					if (unlikely(!skb))
-						goto no_mem;
-				}
-
-				skb_data_init(skb, p, G_RSPD_LEN(len));
-eth_done:
-				fl->credits--;
-				q->eth_pkts++;
-			} else {
-				fl->credits--;
+				skb = get_packet_pg(adap, fl, G_RSPD_LEN(len),
+						 eth ? SGE_RX_DROP_THRES : 0);
+			} else
 				skb = get_packet(adap, fl, G_RSPD_LEN(len),
 						 eth ? SGE_RX_DROP_THRES : 0);
-			}
+			if (unlikely(!skb)) {
+				if (!eth)
+					goto no_mem;
+				q->rx_drops++;
+			} else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
+				__skb_pull(skb, 2);
 
 			if (++fl->cidx == fl->size)
 				fl->cidx = 0;
@@ -2016,20 +2032,15 @@
 			q->credits = 0;
 		}
 
-		if (skb) {
-			/* Preserve the RSS info in csum & priority */
-			skb->csum = rss_hi;
-			skb->priority = rss_lo;
-
+		if (likely(skb != NULL)) {
 			if (eth)
 				rx_eth(adap, q, skb, ethpad);
 			else {
-				if (unlikely(r->rss_hdr.opcode ==
-					     CPL_TRACE_PKT))
-					__skb_pull(skb, ethpad);
-
-				ngathered = rx_offload(&adap->tdev, q,
-						       skb, offload_skbs,
+				/* Preserve the RSS info in csum & priority */
+				skb->csum = rss_hi;
+				skb->priority = rss_lo;
+				ngathered = rx_offload(&adap->tdev, q, skb,
+						       offload_skbs,
 						       ngathered);
 			}
 		}
@@ -2217,7 +2228,6 @@
 	struct sge_rspq *q = &qs->rspq;
 
 	spin_lock(&q->lock);
-	BUG_ON(napi_is_scheduled(qs->netdev));
 
 	if (handle_responses(adap, q) < 0)
 		q->unhandled_irqs++;
@@ -2636,25 +2646,15 @@
 	q->txq[TXQ_ETH].stop_thres = nports *
 	    flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
 
-	if (!is_offload(adapter)) {
-#ifdef USE_RX_PAGE
-		q->fl[0].buf_size = RX_PAGE_SIZE;
+#if FL0_PG_CHUNK_SIZE > 0
+	q->fl[0].buf_size = FL0_PG_CHUNK_SIZE;
 #else
-		q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 +
-		    sizeof(struct cpl_rx_pkt);
+	q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data);
 #endif
-		q->fl[1].buf_size = MAX_FRAME_SIZE + 2 +
-		    sizeof(struct cpl_rx_pkt);
-	} else {
-#ifdef USE_RX_PAGE
-		q->fl[0].buf_size = RX_PAGE_SIZE;
-#else
-		q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE +
-		    sizeof(struct cpl_rx_data);
-#endif
-		q->fl[1].buf_size = (16 * 1024) -
-		    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
-	}
+	q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0;
+	q->fl[1].buf_size = is_offload(adapter) ?
+		(16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
+		MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
 
 	spin_lock(&adapter->sge.reg_lock);
 
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index fb485d0..dd3149d 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -847,6 +847,64 @@
 	return 0;
 }
 
+/**
+ *	t3_check_tpsram_version - read the tp sram version
+ *	@adapter: the adapter
+ *
+ *	Reads the protocol sram version from serial eeprom.
+ */
+int t3_check_tpsram_version(struct adapter *adapter)
+{
+	int ret;
+	u32 vers;
+	unsigned int major, minor;
+
+	/* Get version loaded in SRAM */
+	t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
+	ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
+			      1, 1, 5, 1);
+	if (ret)
+		return ret;
+	
+	vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
+
+	major = G_TP_VERSION_MAJOR(vers);
+	minor = G_TP_VERSION_MINOR(vers);
+
+	if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR) 
+		return 0;
+
+	return -EINVAL;
+}
+
+/**
+ *	t3_check_tpsram - check if provided protocol SRAM 
+ *			  is compatible with this driver
+ *	@adapter: the adapter
+ *	@tp_sram: the firmware image to write
+ *	@size: image size
+ *
+ *	Checks if an adapter's tp sram is compatible with the driver.
+ *	Returns 0 if the versions are compatible, a negative error otherwise.
+ */
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size)
+{
+	u32 csum;
+	unsigned int i;
+	const u32 *p = (const u32 *)tp_sram;
+
+	/* Verify checksum */
+	for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+		csum += ntohl(p[i]);
+	if (csum != 0xffffffff) {
+		CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
+		       csum);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 enum fw_version_type {
 	FW_VERSION_N3,
 	FW_VERSION_T3
@@ -921,7 +979,7 @@
 /*
  *	t3_load_fw - download firmware
  *	@adapter: the adapter
- *	@fw_data: the firrware image to write
+ *	@fw_data: the firmware image to write
  *	@size: image size
  *
  *	Write the supplied firmware image to the card's serial flash.
@@ -2362,7 +2420,7 @@
 		     F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
 	t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
 		     F_MTUENABLE | V_WINDOWSCALEMODE(1) |
-		     V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
+		     V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1));
 	t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
 		     V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
 		     V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
@@ -2371,16 +2429,18 @@
 			 F_IPV6ENABLE | F_NICMODE);
 	t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
 	t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
-	t3_set_reg_field(adap, A_TP_PARA_REG6,
-			 adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
-			 0);
+	t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
+			 adap->params.rev > 0 ? F_ENABLEESND :
+			 F_T3A_ENABLEESND);
 
 	t3_set_reg_field(adap, A_TP_PC_CONFIG,
-			 F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
-			 F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
-			 F_RXCONGESTIONMODE);
+			 F_ENABLEEPCMDAFULL,
+			 F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
+			 F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
 	t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
-
+	t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
+	t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
+	
 	if (adap->params.rev > 0) {
 		tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
 		t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
@@ -2390,9 +2450,10 @@
 	} else
 		t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
 
-	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212);
-	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212);
-	t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212);
+	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
+	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
+	t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
+	t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
 }
 
 /* Desired TP timer resolution in usec */
@@ -2468,6 +2529,7 @@
 		val |= F_RXCOALESCEENABLE;
 		if (psh)
 			val |= F_RXCOALESCEPSHEN;
+		size = min(MAX_RX_COALESCING_LEN, size);
 		t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
 			     V_MAXRXDATA(MAX_RX_COALESCING_LEN));
 	}
@@ -2496,11 +2558,11 @@
 	 * it can accomodate max size TCP/IP headers when SACK and timestamps
 	 * are enabled and still have at least 8 bytes of payload.
 	 */
-	mtus[0] = 88;
-	mtus[1] = 256;
-	mtus[2] = 512;
-	mtus[3] = 576;
-	mtus[4] = 808;
+	mtus[1] = 88;
+	mtus[1] = 88;
+	mtus[2] = 256;
+	mtus[3] = 512;
+	mtus[4] = 576;
 	mtus[5] = 1024;
 	mtus[6] = 1280;
 	mtus[7] = 1492;
@@ -2682,6 +2744,34 @@
 	t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
 }
 
+/**
+ *	t3_set_proto_sram - set the contents of the protocol sram
+ *	@adapter: the adapter
+ *	@data: the protocol image
+ *
+ *	Write the contents of the protocol SRAM.
+ */
+int t3_set_proto_sram(struct adapter *adap, u8 *data)
+{
+	int i;
+	u32 *buf = (u32 *)data;
+
+	for (i = 0; i < PROTO_SRAM_LINES; i++) {
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++));
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++));
+		
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
+		if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
+			return -EIO;
+	}
+	t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
+
+	return 0;
+}
+
 void t3_config_trace_filter(struct adapter *adapter,
 			    const struct trace_params *tp, int filter_index,
 			    int invert, int enable)
@@ -2802,7 +2892,7 @@
 		t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
 		t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN |
 			     F_PORT0ACTIVE | F_ENFORCEPKT);
-		t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000);
+		t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff);
 	} else {
 		t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
 		t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
@@ -3097,7 +3187,7 @@
 	else
 		t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
 
-	t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000);
+	t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
 	init_hw_for_avail_ports(adapter, adapter->params.nports);
 	t3_sge_init(adapter, &adapter->params.sge);
 
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
index b112317..eb508bf 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/cxgb3/version.h
@@ -39,6 +39,6 @@
 
 /* Firmware version */
 #define FW_VERSION_MAJOR 4
-#define FW_VERSION_MINOR 0
+#define FW_VERSION_MINOR 3
 #define FW_VERSION_MICRO 0
 #endif				/* __CHELSIO_VERSION_H */
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c
index a506792..c302b1a 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/cxgb3/xgmac.c
@@ -231,6 +231,28 @@
 	return 0;
 }
 
+static void disable_exact_filters(struct cmac *mac)
+{
+	unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
+
+	for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
+		u32 v = t3_read_reg(mac->adapter, reg);
+		t3_write_reg(mac->adapter, reg, v);
+	}
+	t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1);	/* flush */
+}
+
+static void enable_exact_filters(struct cmac *mac)
+{
+	unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
+
+	for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
+		u32 v = t3_read_reg(mac->adapter, reg);
+		t3_write_reg(mac->adapter, reg, v);
+	}
+	t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1);	/* flush */
+}
+
 /* Calculate the RX hash filter index of an Ethernet address */
 static int hash_hw_addr(const u8 * addr)
 {
@@ -281,6 +303,14 @@
 	return 0;
 }
 
+static int rx_fifo_hwm(int mtu)
+{
+	int hwm;
+
+	hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
+	return min(hwm, MAC_RXFIFO_SIZE - 8192);
+}
+
 int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
 {
 	int hwm, lwm;
@@ -305,12 +335,41 @@
 	hwm = min(hwm, MAC_RXFIFO_SIZE - 8192);
 	lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
 
+	if (adap->params.rev == T3_REV_B2 &&
+	    (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
+		disable_exact_filters(mac);
+		v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
+		t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
+				 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
+
+		/* drain rx FIFO */
+		if (t3_wait_op_done(adap,
+				    A_XGM_RX_MAX_PKT_SIZE_ERR_CNT +
+				    mac->offset,
+				    1 << 31, 1, 20, 5)) {
+			t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
+			enable_exact_filters(mac);
+			return -EIO;
+		}
+		t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
+		t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
+		enable_exact_filters(mac);
+	} else
+		t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
+
+	/*
+	 * Adjust the PAUSE frame watermarks.  We always set the LWM, and the
+	 * HWM only if flow-control is enabled.
+	 */
+	hwm = rx_fifo_hwm(mtu);
+	lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
 	v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
 	v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
 	v |= V_RXFIFOPAUSELWM(lwm / 8);
 	if (G_RXFIFOPAUSEHWM(v))
 		v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
 		    V_RXFIFOPAUSEHWM(hwm / 8);
+
 	t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
 
 	/* Adjust the TX FIFO threshold based on the MTU */
@@ -329,7 +388,6 @@
 			     (hwm - lwm) * 4 / 8);
 	t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
 		     MAC_RXFIFO_SIZE * 4 * 8 / 512);
-
 	return 0;
 }
 
@@ -357,6 +415,15 @@
 				 V_PORTSPEED(M_PORTSPEED), val);
 	}
 
+	val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
+	val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
+	if (fc & PAUSE_TX)
+		val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(
+						t3_read_reg(adap,
+						A_XGM_RX_MAX_PKT_SIZE
+						+ oft)) / 8);
+	t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
+
 	t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
 			 (fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
 	return 0;
@@ -436,6 +503,10 @@
 	unsigned int rx_xcnt;
 	int status;
 
+	status = 0;
+	tx_xcnt = 1;		/* By default tx_xcnt is making progress */
+	tx_tcnt = mac->tx_tcnt;	/* If tx_mcnt is progressing ignore tx_tcnt */
+	rx_xcnt = 1;		/* By default rx_xcnt is making progress */
 	if (tx_mcnt == mac->tx_mcnt) {
 		tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
 						A_XGM_TX_SPI4_SOP_EOP_CNT +
@@ -446,37 +517,44 @@
 			tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
 						      A_TP_PIO_DATA)));
 		} else {
-			mac->toggle_cnt = 0;
-			return 0;
+			goto rxcheck;
 		}
 	} else {
 		mac->toggle_cnt = 0;
-		return 0;
+		goto rxcheck;
 	}
 
 	if (((tx_tcnt != mac->tx_tcnt) &&
 	     (tx_xcnt == 0) && (mac->tx_xcnt == 0)) ||
 	    ((mac->tx_mcnt == tx_mcnt) &&
 	     (tx_xcnt != 0) && (mac->tx_xcnt != 0))) {
-		if (mac->toggle_cnt > 4)
+		if (mac->toggle_cnt > 4) {
 			status = 2;
-		else 
+			goto out;
+		} else {
 			status = 1;
+			goto out;
+		}
 	} else {
 		mac->toggle_cnt = 0;
-		return 0;
+		goto rxcheck;
 	}
 
+rxcheck:
 	if (rx_mcnt != mac->rx_mcnt)
 		rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
 						A_XGM_RX_SPI4_SOP_EOP_CNT +
 						mac->offset)));
-	else 
-		return 0;
+	else
+		goto out;
 
-	if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0) 
+	if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 &&
+	    mac->rx_xcnt == 0) {
 		status = 2;
-	
+		goto out;
+	}
+
+out:
 	mac->tx_tcnt = tx_tcnt;
 	mac->tx_xcnt = tx_xcnt;
 	mac->tx_mcnt = s->tx_frames;
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 95d854e..b2577f4 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -932,8 +932,6 @@
 	/* Kick the lance: transmit now */
 	writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
 
-	spin_unlock_irq(&lp->lock);
-
 	dev->trans_start = jiffies;
 	dev_kfree_skb(skb);
 
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 571d82f..7df23dc 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -566,6 +566,7 @@
 		bp->base.mem = ioremap_nocache(bar_start, bar_len);
 		if (!bp->base.mem) {
 			printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
+			err = -ENOMEM;
 			goto err_out_region;
 		}
 	} else {
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 74ec64a..04e3710 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -250,7 +250,6 @@
 			np->an_enable = 1;
 		mii_set_media (dev);
 	}
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id);
 
 	err = register_netdev (dev);
 	if (err)
@@ -866,9 +865,9 @@
 							    PCI_DMA_FROMDEVICE);
 				/* 16 byte align the IP header */
 				skb_reserve (skb, 2);
-				eth_copy_and_sum (skb,
+				skb_copy_to_linear_data (skb,
 						  np->rx_skbuff[entry]->data,
-						  pkt_len, 0);
+						  pkt_len);
 				skb_put (skb, pkt_len);
 				pci_dma_sync_single_for_device(np->pdev,
 				  			       desc->fraginfo &
@@ -879,7 +878,7 @@
 			skb->protocol = eth_type_trans (skb, dev);
 #if 0
 			/* Checksum done by hw, but csum value unavailable. */
-			if (np->pci_rev_id >= 0x0c &&
+			if (np->pdev->pci_rev_id >= 0x0c &&
 				!(frame_status & (TCPError | UDPError | IPError))) {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
 			}
diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h
index 814c449..e443065 100644
--- a/drivers/net/dl2k.h
+++ b/drivers/net/dl2k.h
@@ -668,7 +668,6 @@
 	unsigned int rx_flow:1;		/* Rx flow control enable */
 	unsigned int phy_media:1;	/* 1: fiber, 0: copper */
 	unsigned int link_status:1;	/* Current link status */
-	unsigned char pci_rev_id;	/* PCI revision ID */
 	struct netdev_desc *last_tx;	/* Last Tx descriptor used. */
 	unsigned long cur_rx, old_rx;	/* Producer/consumer ring indices */
 	unsigned long cur_tx, old_tx;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 264fa0e..c3de81b 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -104,6 +104,18 @@
 #define PRINTK(args...)   printk(KERN_DEBUG args)
 #endif
 
+#ifdef CONFIG_BLACKFIN
+#define readsb	insb
+#define readsw	insw
+#define readsl	insl
+#define writesb	outsb
+#define writesw	outsw
+#define writesl	outsl
+#define DM9000_IRQ_FLAGS	(IRQF_SHARED | IRQF_TRIGGER_HIGH)
+#else
+#define DM9000_IRQ_FLAGS	IRQF_SHARED
+#endif
+
 /*
  * Transmit timeout, default 5 seconds.
  */
@@ -431,6 +443,9 @@
 		db->io_addr = (void __iomem *)base;
 		db->io_data = (void __iomem *)(base + 4);
 
+		/* ensure at least we have a default set of IO routines */
+		dm9000_set_io(db, 2);
+
 	} else {
 		db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 		db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -614,7 +629,7 @@
 
 	PRINTK2("entering dm9000_open\n");
 
-	if (request_irq(dev->irq, &dm9000_interrupt, IRQF_SHARED, dev->name, dev))
+	if (request_irq(dev->irq, &dm9000_interrupt, DM9000_IRQ_FLAGS, dev->name, dev))
 		return -EAGAIN;
 
 	/* Initialize DM9000 board */
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 60673bc..756a6bc 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -34,11 +34,12 @@
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/moduleparam.h>
+#include <linux/rtnetlink.h>
+#include <net/rtnetlink.h>
 
 static int numdummies = 1;
 
 static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *dummy_get_stats(struct net_device *dev);
 
 static int dummy_set_address(struct net_device *dev, void *p)
 {
@@ -56,13 +57,13 @@
 {
 }
 
-static void __init dummy_setup(struct net_device *dev)
+static void dummy_setup(struct net_device *dev)
 {
 	/* Initialize the device structure. */
-	dev->get_stats = dummy_get_stats;
 	dev->hard_start_xmit = dummy_xmit;
 	dev->set_multicast_list = set_multicast_list;
 	dev->set_mac_address = dummy_set_address;
+	dev->destructor = free_netdev;
 
 	/* Fill in device structure with ethernet-generic values. */
 	ether_setup(dev);
@@ -76,77 +77,80 @@
 
 static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_device_stats *stats = netdev_priv(dev);
-
-	stats->tx_packets++;
-	stats->tx_bytes+=skb->len;
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
 
 	dev_kfree_skb(skb);
 	return 0;
 }
 
-static struct net_device_stats *dummy_get_stats(struct net_device *dev)
+static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
 {
-	return netdev_priv(dev);
+	if (tb[IFLA_ADDRESS]) {
+		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+			return -EINVAL;
+		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+			return -EADDRNOTAVAIL;
+	}
+	return 0;
 }
 
-static struct net_device **dummies;
+static struct rtnl_link_ops dummy_link_ops __read_mostly = {
+	.kind		= "dummy",
+	.setup		= dummy_setup,
+	.validate	= dummy_validate,
+};
 
 /* Number of dummy devices to be set up by this module. */
 module_param(numdummies, int, 0);
 MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
 
-static int __init dummy_init_one(int index)
+static int __init dummy_init_one(void)
 {
 	struct net_device *dev_dummy;
 	int err;
 
-	dev_dummy = alloc_netdev(sizeof(struct net_device_stats),
-				 "dummy%d", dummy_setup);
-
+	dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
 	if (!dev_dummy)
 		return -ENOMEM;
 
-	if ((err = register_netdev(dev_dummy))) {
-		free_netdev(dev_dummy);
-		dev_dummy = NULL;
-	} else {
-		dummies[index] = dev_dummy;
-	}
+	err = dev_alloc_name(dev_dummy, dev_dummy->name);
+	if (err < 0)
+		goto err;
 
+	dev_dummy->rtnl_link_ops = &dummy_link_ops;
+	err = register_netdevice(dev_dummy);
+	if (err < 0)
+		goto err;
+	return 0;
+
+err:
+	free_netdev(dev_dummy);
 	return err;
 }
 
-static void dummy_free_one(int index)
-{
-	unregister_netdev(dummies[index]);
-	free_netdev(dummies[index]);
-}
-
 static int __init dummy_init_module(void)
 {
 	int i, err = 0;
-	dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL);
-	if (!dummies)
-		return -ENOMEM;
+
+	rtnl_lock();
+	err = __rtnl_link_register(&dummy_link_ops);
+
 	for (i = 0; i < numdummies && !err; i++)
-		err = dummy_init_one(i);
-	if (err) {
-		i--;
-		while (--i >= 0)
-			dummy_free_one(i);
-	}
+		err = dummy_init_one();
+	if (err < 0)
+		__rtnl_link_unregister(&dummy_link_ops);
+	rtnl_unlock();
+
 	return err;
 }
 
 static void __exit dummy_cleanup_module(void)
 {
-	int i;
-	for (i = 0; i < numdummies; i++)
-		dummy_free_one(i);
-	kfree(dummies);
+	rtnl_link_unregister(&dummy_link_ops);
 }
 
 module_init(dummy_init_module);
 module_exit(dummy_cleanup_module);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_RTNL_LINK("dummy");
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 6169663..6b6401e 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -159,7 +159,7 @@
 
 #define DRV_NAME		"e100"
 #define DRV_EXT			"-NAPI"
-#define DRV_VERSION		"3.5.17-k4"DRV_EXT
+#define DRV_VERSION		"3.5.23-k4"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
 #define DRV_COPYRIGHT		"Copyright(c) 1999-2006 Intel Corporation"
 #define PFX			DRV_NAME ": "
@@ -285,6 +285,12 @@
 	rus_mask         = 0x3C,
 };
 
+enum ru_state  {
+	RU_SUSPENDED = 0,
+	RU_RUNNING	 = 1,
+	RU_UNINITIALIZED = -1,
+};
+
 enum scb_stat_ack {
 	stat_ack_not_ours    = 0x00,
 	stat_ack_sw_gen      = 0x04,
@@ -526,6 +532,7 @@
 	struct rx *rx_to_use;
 	struct rx *rx_to_clean;
 	struct rfd blank_rfd;
+	enum ru_state ru_running;
 
 	spinlock_t cb_lock			____cacheline_aligned;
 	spinlock_t cmd_lock;
@@ -576,7 +583,6 @@
 	u32 rx_tco_frames;
 	u32 rx_over_length_errors;
 
-	u8 rev_id;
 	u16 leds;
 	u16 eeprom_wc;
 	u16 eeprom[256];
@@ -930,9 +936,8 @@
 	struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
 	struct param_range cbs  = { .min = 64, .max = 256, .count = 128 };
 
-	pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
 	/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
-	nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id;
+	nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision;
 	if(nic->mac == mac_unknown)
 		nic->mac = mac_82557_D100_A;
 
@@ -947,7 +952,7 @@
 		((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
 
 	/* Template for a freshly allocated RFD */
-	nic->blank_rfd.command = cpu_to_le16(cb_el & cb_s);
+	nic->blank_rfd.command = cpu_to_le16(cb_el);
 	nic->blank_rfd.rbd = 0xFFFFFFFF;
 	nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
 
@@ -1017,10 +1022,16 @@
 		config->mwi_enable = 0x1;	/* 1=enable, 0=disable */
 		config->standard_tcb = 0x0;	/* 1=standard, 0=extended */
 		config->rx_long_ok = 0x1;	/* 1=VLANs ok, 0=standard */
-		if(nic->mac >= mac_82559_D101M)
+		if (nic->mac >= mac_82559_D101M) {
 			config->tno_intr = 0x1;		/* TCO stats enable */
-		else
+			/* Enable TCO in extended config */
+			if (nic->mac >= mac_82551_10) {
+				config->byte_count = 0x20; /* extended bytes */
+				config->rx_d102_mode = 0x1; /* GMRC for TCO */
+			}
+		} else {
 			config->standard_stat_counter = 0x0;
+		}
 	}
 
 	DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -1266,7 +1277,7 @@
 	if (nic->flags & ich)
 		goto noloaducode;
 
-	/* Search for ucode match against h/w rev_id */
+	/* Search for ucode match against h/w revision */
 	for (opts = ucode_opts; opts->mac; opts++) {
 		int i;
 		u32 *ucode = opts->ucode;
@@ -1742,11 +1753,19 @@
 	return 0;
 }
 
-static inline void e100_start_receiver(struct nic *nic)
+static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
 {
-	/* Start if RFA is non-NULL */
-	if(nic->rx_to_clean->skb)
-		e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr);
+	if(!nic->rxs) return;
+	if(RU_SUSPENDED != nic->ru_running) return;
+
+	/* handle init time starts */
+	if(!rx) rx = nic->rxs;
+
+	/* (Re)start RU if suspended or idle and RFA is non-NULL */
+	if(rx->skb) {
+		e100_exec_cmd(nic, ruc_start, rx->dma_addr);
+		nic->ru_running = RU_RUNNING;
+	}
 }
 
 #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
@@ -1775,7 +1794,7 @@
 		put_unaligned(cpu_to_le32(rx->dma_addr),
 			(u32 *)&prev_rfd->link);
 		wmb();
-		prev_rfd->command &= ~cpu_to_le16(cb_el & cb_s);
+		prev_rfd->command &= ~cpu_to_le16(cb_el);
 		pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
 			sizeof(struct rfd), PCI_DMA_TODEVICE);
 	}
@@ -1813,6 +1832,10 @@
 	pci_unmap_single(nic->pdev, rx->dma_addr,
 		RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
 
+	/* this allows for a fast restart without re-enabling interrupts */
+	if(le16_to_cpu(rfd->command) & cb_el)
+		nic->ru_running = RU_SUSPENDED;
+
 	/* Pull off the RFD and put the actual data (minus eth hdr) */
 	skb_reserve(skb, sizeof(struct rfd));
 	skb_put(skb, actual_size);
@@ -1843,18 +1866,45 @@
 	unsigned int work_to_do)
 {
 	struct rx *rx;
+	int restart_required = 0;
+	struct rx *rx_to_start = NULL;
+
+	/* are we already rnr? then pay attention!!! this ensures that
+	 * the state machine progression never allows a start with a
+	 * partially cleaned list, avoiding a race between hardware
+	 * and rx_to_clean when in NAPI mode */
+	if(RU_SUSPENDED == nic->ru_running)
+		restart_required = 1;
 
 	/* Indicate newly arrived packets */
 	for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
-		if(e100_rx_indicate(nic, rx, work_done, work_to_do))
+		int err = e100_rx_indicate(nic, rx, work_done, work_to_do);
+		if(-EAGAIN == err) {
+			/* hit quota so have more work to do, restart once
+			 * cleanup is complete */
+			restart_required = 0;
+			break;
+		} else if(-ENODATA == err)
 			break; /* No more to clean */
 	}
 
+	/* save our starting point as the place we'll restart the receiver */
+	if(restart_required)
+		rx_to_start = nic->rx_to_clean;
+
 	/* Alloc new skbs to refill list */
 	for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
 		if(unlikely(e100_rx_alloc_skb(nic, rx)))
 			break; /* Better luck next time (see watchdog) */
 	}
+
+	if(restart_required) {
+		// ack the rnr?
+		writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
+		e100_start_receiver(nic, rx_to_start);
+		if(work_done)
+			(*work_done)++;
+	}
 }
 
 static void e100_rx_clean_list(struct nic *nic)
@@ -1862,6 +1912,8 @@
 	struct rx *rx;
 	unsigned int i, count = nic->params.rfds.count;
 
+	nic->ru_running = RU_UNINITIALIZED;
+
 	if(nic->rxs) {
 		for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
 			if(rx->skb) {
@@ -1883,6 +1935,7 @@
 	unsigned int i, count = nic->params.rfds.count;
 
 	nic->rx_to_use = nic->rx_to_clean = NULL;
+	nic->ru_running = RU_UNINITIALIZED;
 
 	if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
 		return -ENOMEM;
@@ -1897,6 +1950,7 @@
 	}
 
 	nic->rx_to_use = nic->rx_to_clean = nic->rxs;
+	nic->ru_running = RU_SUSPENDED;
 
 	return 0;
 }
@@ -1916,6 +1970,10 @@
 	/* Ack interrupt(s) */
 	iowrite8(stat_ack, &nic->csr->scb.stat_ack);
 
+	/* We hit Receive No Resource (RNR); restart RU after cleaning */
+	if(stat_ack & stat_ack_rnr)
+		nic->ru_running = RU_SUSPENDED;
+
 	if(likely(netif_rx_schedule_prep(netdev))) {
 		e100_disable_irq(nic);
 		__netif_rx_schedule(netdev);
@@ -2007,7 +2065,7 @@
 	if((err = e100_hw_init(nic)))
 		goto err_clean_cbs;
 	e100_set_multicast_list(nic->netdev);
-	e100_start_receiver(nic);
+	e100_start_receiver(nic, NULL);
 	mod_timer(&nic->watchdog, jiffies);
 	if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
 		nic->netdev->name, nic->netdev)))
@@ -2088,7 +2146,7 @@
 		mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
 			BMCR_LOOPBACK);
 
-	e100_start_receiver(nic);
+	e100_start_receiver(nic, NULL);
 
 	if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
 		err = -ENOMEM;
@@ -2178,7 +2236,7 @@
 	u32 *buff = p;
 	int i;
 
-	regs->version = (1 << 24) | nic->rev_id;
+	regs->version = (1 << 24) | nic->pdev->revision;
 	buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
 		ioread8(&nic->csr->scb.cmd_lo) << 16 |
 		ioread16(&nic->csr->scb.status);
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 49be393..f48b659 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1142,13 +1142,16 @@
 	    !e1000_check_mng_mode(&adapter->hw))
 		e1000_get_hw_control(adapter);
 
-	strcpy(netdev->name, "eth%d");
-	if ((err = register_netdev(netdev)))
-		goto err_register;
-
 	/* tell the stack to leave us alone until e1000_open() is called */
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
+#ifdef CONFIG_E1000_NAPI
+	netif_poll_disable(netdev);
+#endif
+
+	strcpy(netdev->name, "eth%d");
+	if ((err = register_netdev(netdev)))
+		goto err_register;
 
 	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
 
@@ -1263,8 +1266,7 @@
 	hw->device_id = pdev->device;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_id = pdev->subsystem_device;
-
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+	hw->revision_id = pdev->revision;
 
 	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
@@ -1325,7 +1327,10 @@
 	spin_lock_init(&adapter->tx_queue_lock);
 #endif
 
-	atomic_set(&adapter->irq_sem, 1);
+	/* Explicitly disable IRQ since the NIC can be in any state. */
+	atomic_set(&adapter->irq_sem, 0);
+	e1000_irq_disable(adapter);
+
 	spin_lock_init(&adapter->stats_lock);
 
 	set_bit(__E1000_DOWN, &adapter->flags);
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 98003419..3c54014 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1801,7 +1801,7 @@
 
 #if 1 || USE_IP_CSUM
 				/* Packet is in one chunk -- we can copy + cksum. */
-				eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				skb_copy_from_linear_data(sp->rx_skbuff[entry],
@@ -2292,10 +2292,15 @@
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct speedo_private *sp = netdev_priv(dev);
 	void __iomem *ioaddr = sp->regs;
+	int rc;
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
-	pci_enable_device(pdev);
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
 	pci_set_master(pdev);
 
 	if (!netif_running(dev))
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 602872d..6628fa6 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,13 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0058"
+#define DRV_VERSION	"EHEA_0070"
+
+/* eHEA capability flags */
+#define DLPAR_PORT_ADD_REM 1
+#define DLPAR_MEM_ADD      2
+#define DLPAR_MEM_REM      4
+#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM)
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
 	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -107,6 +113,8 @@
 /* Memory Regions */
 #define EHEA_MR_ACC_CTRL       0x00800000
 
+#define EHEA_BUSMAP_START      0x8000000000000000ULL
+
 #define EHEA_WATCH_DOG_TIMEOUT 10*HZ
 
 /* utility functions */
@@ -136,10 +144,10 @@
 	(0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff))
 
 #define EHEA_BMASK_SET(mask, value) \
-        ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
+	((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
 
 #define EHEA_BMASK_GET(mask, value) \
-        (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
+	(EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
 
 /*
  * Generic ehea page
@@ -180,6 +188,12 @@
 				   set to 0 if unused */
 };
 
+struct ehea_busmap {
+	unsigned int entries;		/* total number of entries */
+	unsigned int valid_sections;	/* number of valid sections */
+	u64 *vaddr;
+};
+
 struct ehea_qp;
 struct ehea_cq;
 struct ehea_eq;
@@ -190,7 +204,7 @@
  * Queue attributes passed to ehea_create_qp()
  */
 struct ehea_qp_init_attr {
-        /* input parameter */
+	/* input parameter */
 	u32 qp_token;           /* queue token */
 	u8 low_lat_rq1;
 	u8 signalingtype;       /* cqe generation flag */
@@ -212,7 +226,7 @@
 	u64 recv_cq_handle;
 	u64 aff_eq_handle;
 
-        /* output parameter */
+	/* output parameter */
 	u32 qp_nr;
 	u16 act_nr_send_wqes;
 	u16 act_nr_rwqes_rq1;
@@ -279,12 +293,12 @@
  * Completion Queue attributes
  */
 struct ehea_cq_attr {
-        /* input parameter */
+	/* input parameter */
 	u32 max_nr_of_cqes;
 	u32 cq_token;
 	u64 eq_handle;
 
-        /* output parameter */
+	/* output parameter */
 	u32 act_nr_of_cqes;
 	u32 nr_pages;
 };
@@ -376,6 +390,8 @@
 	struct ehea_mr mr;
 	u32 pd;                    /* protection domain */
 	u64 max_mc_mac;            /* max number of multicast mac addresses */
+	int active_ports;
+	struct list_head list;
 };
 
 
@@ -425,6 +441,9 @@
 	int max_entries_rq3;
 };
 
+enum ehea_flag_bits {
+	__EHEA_STOP_XFER
+};
 
 void ehea_set_ethtool_ops(struct net_device *netdev);
 int ehea_sense_port_attr(struct ehea_port *port);
diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ehea/ehea_hw.h
index 1246757..1af7ca4 100644
--- a/drivers/net/ehea/ehea_hw.h
+++ b/drivers/net/ehea/ehea_hw.h
@@ -211,34 +211,34 @@
 }
 
 #define epa_store_eq(epa, offset, value)\
-        epa_store(epa, EQTEMM_OFFSET(offset), value)
+	epa_store(epa, EQTEMM_OFFSET(offset), value)
 #define epa_load_eq(epa, offset)\
-        epa_load(epa, EQTEMM_OFFSET(offset))
+	epa_load(epa, EQTEMM_OFFSET(offset))
 
 #define epa_store_cq(epa, offset, value)\
-        epa_store(epa, CQTEMM_OFFSET(offset), value)
+	epa_store(epa, CQTEMM_OFFSET(offset), value)
 #define epa_load_cq(epa, offset)\
-        epa_load(epa, CQTEMM_OFFSET(offset))
+	epa_load(epa, CQTEMM_OFFSET(offset))
 
 #define epa_store_qp(epa, offset, value)\
-        epa_store(epa, QPTEMM_OFFSET(offset), value)
+	epa_store(epa, QPTEMM_OFFSET(offset), value)
 #define epa_load_qp(epa, offset)\
-        epa_load(epa, QPTEMM_OFFSET(offset))
+	epa_load(epa, QPTEMM_OFFSET(offset))
 
 #define epa_store_qped(epa, offset, value)\
-        epa_store(epa, QPEDMM_OFFSET(offset), value)
+	epa_store(epa, QPEDMM_OFFSET(offset), value)
 #define epa_load_qped(epa, offset)\
-        epa_load(epa, QPEDMM_OFFSET(offset))
+	epa_load(epa, QPEDMM_OFFSET(offset))
 
 #define epa_store_mrmw(epa, offset, value)\
-        epa_store(epa, MRMWMM_OFFSET(offset), value)
+	epa_store(epa, MRMWMM_OFFSET(offset), value)
 #define epa_load_mrmw(epa, offset)\
-        epa_load(epa, MRMWMM_OFFSET(offset))
+	epa_load(epa, MRMWMM_OFFSET(offset))
 
 #define epa_store_base(epa, offset, value)\
-        epa_store(epa, HCAGR_OFFSET(offset), value)
+	epa_store(epa, HCAGR_OFFSET(offset), value)
 #define epa_load_base(epa, offset)\
-        epa_load(epa, HCAGR_OFFSET(offset))
+	epa_load(epa, HCAGR_OFFSET(offset))
 
 static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes)
 {
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index f6e0cb1..1d1571cf3 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -79,9 +79,14 @@
 MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
 
 static int port_name_cnt = 0;
+static LIST_HEAD(adapter_list);
+u64 ehea_driver_flags = 0;
+struct workqueue_struct *ehea_driver_wq;
+struct work_struct ehea_rereg_mr_task;
+
 
 static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
-                                        const struct of_device_id *id);
+					const struct of_device_id *id);
 
 static int __devexit ehea_remove(struct ibmebus_dev *dev);
 
@@ -236,15 +241,19 @@
 
 		rwqe = ehea_get_next_rwqe(qp, rq_nr);
 		rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
-		            | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
+			    | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
 		rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
-		rwqe->sg_list[0].vaddr = (u64)skb->data;
+		rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
 		rwqe->sg_list[0].len = packet_size;
 		rwqe->data_segments = 1;
 
 		index++;
 		index &= max_index_mask;
+
+		if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
+			goto out;
 	}
+
 	q_skba->index = index;
 
 	/* Ring doorbell */
@@ -253,7 +262,7 @@
 		ehea_update_rq2a(pr->qp, i);
 	else
 		ehea_update_rq3a(pr->qp, i);
-
+out:
 	return ret;
 }
 
@@ -427,8 +436,8 @@
 						break;
 				}
 				skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
-					       cqe->num_bytes_transfered - 4);
-				ehea_fill_skb(dev, skb, cqe);
+						 cqe->num_bytes_transfered - 4);
+				ehea_fill_skb(port->netdev, skb, cqe);
 			} else if (rq == 2) {  /* RQ2 */
 				skb = get_skb_by_index(skb_arr_rq2,
 						       skb_arr_rq2_len, cqe);
@@ -451,7 +460,8 @@
 				processed_rq3++;
 			}
 
-			if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
+			if ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
+			    && port->vgrp)
 				vlan_hwaccel_receive_skb(skb, port->vgrp,
 							 cqe->vlan_tag);
 			else
@@ -617,7 +627,7 @@
 
 	for (i = 0; i < EHEA_MAX_PORTS; i++)
 		if (adapter->port[i])
-	                if (adapter->port[i]->logical_port_id == logical_port)
+			if (adapter->port[i]->logical_port_id == logical_port)
 				return adapter->port[i];
 	return NULL;
 }
@@ -1320,7 +1330,7 @@
 			sg1entry->len = skb_data_size - headersize;
 
 			tmp_addr = (u64)(skb->data + headersize);
-			sg1entry->vaddr = tmp_addr;
+			sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
 			swqe->descriptors++;
 		}
 	} else
@@ -1351,7 +1361,7 @@
 			sg1entry->l_key = lkey;
 			sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
 			tmp_addr = (u64)(skb->data + SWQE2_MAX_IMM);
-			sg1entry->vaddr = tmp_addr;
+			sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
 			swqe->descriptors++;
 		}
 	} else {
@@ -1390,7 +1400,7 @@
 			sg1entry->len = frag->size;
 			tmp_addr =  (u64)(page_address(frag->page)
 					  + frag->page_offset);
-			sg1entry->vaddr = tmp_addr;
+			sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
 			swqe->descriptors++;
 			sg1entry_contains_frag_data = 1;
 		}
@@ -1405,7 +1415,7 @@
 
 			tmp_addr = (u64)(page_address(frag->page)
 					 + frag->page_offset);
-			sgentry->vaddr = tmp_addr;
+			sgentry->vaddr = ehea_map_vaddr(tmp_addr);
 			swqe->descriptors++;
 		}
 	}
@@ -1694,6 +1704,7 @@
 {
 	if (skb->protocol == htons(ETH_P_IP)) {
 		const struct iphdr *iph = ip_hdr(skb);
+
 		/* IPv4 */
 		swqe->tx_control |= EHEA_SWQE_CRC
 				 | EHEA_SWQE_IP_CHECKSUM
@@ -1704,13 +1715,12 @@
 		write_ip_start_end(swqe, skb);
 
 		if (iph->protocol == IPPROTO_UDP) {
-			if ((iph->frag_off & IP_MF) ||
-			    (iph->frag_off & IP_OFFSET))
+			if ((iph->frag_off & IP_MF)
+			    || (iph->frag_off & IP_OFFSET))
 				/* IP fragment, so don't change cs */
 				swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
 			else
 				write_udp_offset_end(swqe, skb);
-
 		} else if (iph->protocol == IPPROTO_TCP) {
 			write_tcp_offset_end(swqe, skb);
 		}
@@ -1738,6 +1748,7 @@
 
 	if (skb->protocol == htons(ETH_P_IP)) {
 		const struct iphdr *iph = ip_hdr(skb);
+
 		/* IPv4 */
 		write_ip_start_end(swqe, skb);
 
@@ -1750,8 +1761,8 @@
 			write_tcp_offset_end(swqe, skb);
 
 		} else if (iph->protocol == IPPROTO_UDP) {
-			if ((iph->frag_off & IP_MF) ||
-			    (iph->frag_off & IP_OFFSET))
+			if ((iph->frag_off & IP_MF)
+			    || (iph->frag_off & IP_OFFSET))
 				/* IP fragment, so don't change cs */
 				swqe->tx_control |= EHEA_SWQE_CRC
 						 | EHEA_SWQE_IMM_DATA_PRESENT;
@@ -1876,6 +1887,9 @@
 		ehea_dump(swqe, 512, "swqe");
 	}
 
+	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
+		goto out;
+
 	ehea_post_swqe(pr->qp, swqe);
 	pr->tx_packets++;
 
@@ -1890,7 +1904,7 @@
 	}
 	dev->trans_start = jiffies;
 	spin_unlock(&pr->xmit_lock);
-
+out:
 	return NETDEV_TX_OK;
 }
 
@@ -1910,10 +1924,7 @@
 		goto out;
 	}
 
-	if (grp)
-		memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
-	else
-		memset(cb1->vlan_filter, 0xFF, sizeof(cb1->vlan_filter));
+	memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
 
 	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
 				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
@@ -1947,7 +1958,7 @@
 	}
 
 	index = (vid / 64);
-	cb1->vlan_filter[index] |= ((u64)(1 << (vid & 0x3F)));
+	cb1->vlan_filter[index] |= ((u64)(0x8000000000000000 >> (vid & 0x3F)));
 
 	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
 				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
@@ -1982,7 +1993,7 @@
 	}
 
 	index = (vid / 64);
-	cb1->vlan_filter[index] &= ~((u64)(1 << (vid & 0x3F)));
+	cb1->vlan_filter[index] &= ~((u64)(0x8000000000000000 >> (vid & 0x3F)));
 
 	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
 				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
@@ -2221,6 +2232,9 @@
 out_clean_pr:
 	ehea_clean_all_portres(port);
 out:
+	if (ret)
+		ehea_info("Failed starting %s. ret=%i", dev->name, ret);
+
 	return ret;
 }
 
@@ -2260,8 +2274,13 @@
 			msleep(1);
 
 	ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
-	ret = ehea_clean_all_portres(port);
 	port->state = EHEA_PORT_DOWN;
+
+	ret = ehea_clean_all_portres(port);
+	if (ret)
+		ehea_info("Failed freeing resources for %s. ret=%i",
+			  dev->name, ret);
+
 	return ret;
 }
 
@@ -2293,15 +2312,11 @@
 	netif_stop_queue(dev);
 	netif_poll_disable(dev);
 
-	ret = ehea_down(dev);
-	if (ret)
-		ehea_error("ehea_down failed. not all resources are freed");
+	ehea_down(dev);
 
 	ret = ehea_up(dev);
-	if (ret) {
-		ehea_error("Reset device %s failed: ret=%d", dev->name, ret);
+	if (ret)
 		goto out;
-	}
 
 	if (netif_msg_timer(port))
 		ehea_info("Device %s resetted successfully", dev->name);
@@ -2313,6 +2328,88 @@
 	return;
 }
 
+static void ehea_rereg_mrs(struct work_struct *work)
+{
+	int ret, i;
+	struct ehea_adapter *adapter;
+
+	ehea_info("LPAR memory enlarged - re-initializing driver");
+
+	list_for_each_entry(adapter, &adapter_list, list)
+		if (adapter->active_ports) {
+			/* Shutdown all ports */
+			for (i = 0; i < EHEA_MAX_PORTS; i++) {
+				struct ehea_port *port = adapter->port[i];
+
+				if (port) {
+					struct net_device *dev = port->netdev;
+
+					if (dev->flags & IFF_UP) {
+						ehea_info("stopping %s",
+							  dev->name);
+						down(&port->port_lock);
+						netif_stop_queue(dev);
+						netif_poll_disable(dev);
+						ehea_down(dev);
+						up(&port->port_lock);
+					}
+				}
+			}
+
+			/* Unregister old memory region */
+			ret = ehea_rem_mr(&adapter->mr);
+			if (ret) {
+				ehea_error("unregister MR failed - driver"
+					   " inoperable!");
+				goto out;
+			}
+		}
+
+	ehea_destroy_busmap();
+
+	ret = ehea_create_busmap();
+	if (ret)
+		goto out;
+
+	clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
+
+	list_for_each_entry(adapter, &adapter_list, list)
+		if (adapter->active_ports) {
+			/* Register new memory region */
+			ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
+			if (ret) {
+				ehea_error("register MR failed - driver"
+					   " inoperable!");
+				goto out;
+			}
+
+			/* Restart all ports */
+			for (i = 0; i < EHEA_MAX_PORTS; i++) {
+				struct ehea_port *port = adapter->port[i];
+
+				if (port) {
+					struct net_device *dev = port->netdev;
+
+					if (dev->flags & IFF_UP) {
+						ehea_info("restarting %s",
+							  dev->name);
+						down(&port->port_lock);
+
+						ret = ehea_up(dev);
+						if (!ret) {
+							netif_poll_enable(dev);
+							netif_wake_queue(dev);
+						}
+
+						up(&port->port_lock);
+					}
+				}
+			}
+		}
+out:
+	return;
+}
+
 static void ehea_tx_watchdog(struct net_device *dev)
 {
 	struct ehea_port *port = netdev_priv(dev);
@@ -2409,7 +2506,7 @@
 }
 
 static int ehea_driver_sysfs_add(struct device *dev,
-                                 struct device_driver *driver)
+				 struct device_driver *driver)
 {
 	int ret;
 
@@ -2426,7 +2523,7 @@
 }
 
 static void ehea_driver_sysfs_remove(struct device *dev,
-                                     struct device_driver *driver)
+				     struct device_driver *driver)
 {
 	struct device_driver *drv = driver;
 
@@ -2455,7 +2552,7 @@
 	}
 
 	ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
-        if (ret) {
+	if (ret) {
 		ehea_error("failed to register attributes, ret=%d", ret);
 		goto out_unreg_of_dev;
 	}
@@ -2574,6 +2671,8 @@
 	ehea_info("%s: Jumbo frames are %sabled", dev->name,
 		  jumbo == 1 ? "en" : "dis");
 
+	adapter->active_ports++;
+
 	return port;
 
 out_unreg_port:
@@ -2597,12 +2696,14 @@
 	ehea_unregister_port(port);
 	kfree(port->mc_list);
 	free_netdev(port->netdev);
+	port->adapter->active_ports--;
 }
 
 static int ehea_setup_ports(struct ehea_adapter *adapter)
 {
 	struct device_node *lhea_dn;
 	struct device_node *eth_dn = NULL;
+
 	const u32 *dn_log_port_id;
 	int i = 0;
 
@@ -2610,7 +2711,7 @@
 	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
 
 		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
-						    NULL);
+						 NULL);
 		if (!dn_log_port_id) {
 			ehea_error("bad device node: eth_dn name=%s",
 				   eth_dn->full_name);
@@ -2650,7 +2751,7 @@
 	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
 
 		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
-						    NULL);
+						 NULL);
 		if (dn_log_port_id)
 			if (*dn_log_port_id == logical_port_id)
 				return eth_dn;
@@ -2788,10 +2889,12 @@
 		goto out;
 	}
 
+	list_add(&adapter->list, &adapter_list);
+
 	adapter->ebus_dev = dev;
 
 	adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
-					    NULL);
+					 NULL);
 	if (adapter_handle)
 		adapter->handle = *adapter_handle;
 
@@ -2891,7 +2994,10 @@
 
 	ehea_destroy_eq(adapter->neq);
 	ehea_remove_adapter_mr(adapter);
+	list_del(&adapter->list);
+
 	kfree(adapter);
+
 	return 0;
 }
 
@@ -2923,6 +3029,15 @@
 	return ret;
 }
 
+static ssize_t ehea_show_capabilities(struct device_driver *drv,
+				      char *buf)
+{
+	return sprintf(buf, "%d", EHEA_CAPABILITIES);
+}
+
+static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
+		   ehea_show_capabilities, NULL);
+
 int __init ehea_module_init(void)
 {
 	int ret;
@@ -2930,12 +3045,32 @@
 	printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
 	       DRV_VERSION);
 
+	ehea_driver_wq = create_workqueue("ehea_driver_wq");
+
+	INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
+
 	ret = check_module_parm();
 	if (ret)
 		goto out;
-	ret = ibmebus_register_driver(&ehea_driver);
+
+	ret = ehea_create_busmap();
 	if (ret)
+		goto out;
+
+	ret = ibmebus_register_driver(&ehea_driver);
+	if (ret) {
 		ehea_error("failed registering eHEA device driver on ebus");
+		goto out;
+	}
+
+	ret = driver_create_file(&ehea_driver.driver,
+				 &driver_attr_capabilities);
+	if (ret) {
+		ehea_error("failed to register capabilities attribute, ret=%d",
+			   ret);
+		ibmebus_unregister_driver(&ehea_driver);
+		goto out;
+	}
 
 out:
 	return ret;
@@ -2943,7 +3078,9 @@
 
 static void __exit ehea_module_exit(void)
 {
+	driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
 	ibmebus_unregister_driver(&ehea_driver);
+	ehea_destroy_busmap();
 }
 
 module_init(ehea_module_init);
diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h
index d17a45a..89b6353 100644
--- a/drivers/net/ehea/ehea_phyp.h
+++ b/drivers/net/ehea/ehea_phyp.h
@@ -60,6 +60,9 @@
 	}
 }
 
+/* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */
+#define EHEA_MAX_RPAGE 512
+
 /* Notification Event Queue (NEQ) Entry bit masks */
 #define NEQE_EVENT_CODE		EHEA_BMASK_IBM(2, 7)
 #define NEQE_PORTNUM  		EHEA_BMASK_IBM(32, 47)
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index f24a886..a36fa6c2 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -31,6 +31,13 @@
 #include "ehea_phyp.h"
 #include "ehea_qmr.h"
 
+
+struct ehea_busmap ehea_bmap = { 0, 0, NULL };
+extern u64 ehea_driver_flags;
+extern struct workqueue_struct *ehea_driver_wq;
+extern struct work_struct ehea_rereg_mr_task;
+
+
 static void *hw_qpageit_get_inc(struct hw_queue *queue)
 {
 	void *retvalue = hw_qeit_get(queue);
@@ -211,7 +218,7 @@
 	u64 hret;
 	u64 adapter_handle = cq->adapter->handle;
 
-        /* deregister all previous registered pages */
+	/* deregister all previous registered pages */
 	hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force);
 	if (hret != H_SUCCESS)
 		return hret;
@@ -362,7 +369,7 @@
 	if (hret != H_SUCCESS) {
 		ehea_error("destroy EQ failed");
 		return -EIO;
-        }
+	}
 
 	return 0;
 }
@@ -507,58 +514,124 @@
 
 u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
 {
-        u64 hret;
-        struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
+	u64 hret;
+	struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
 
 
-        ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
-        hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
-        if (hret != H_SUCCESS)
-                return hret;
+	ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
+	hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
+	if (hret != H_SUCCESS)
+		return hret;
 
-        hw_queue_dtor(&qp->hw_squeue);
-        hw_queue_dtor(&qp->hw_rqueue1);
+	hw_queue_dtor(&qp->hw_squeue);
+	hw_queue_dtor(&qp->hw_rqueue1);
 
-        if (qp_attr->rq_count > 1)
-                hw_queue_dtor(&qp->hw_rqueue2);
-        if (qp_attr->rq_count > 2)
-                hw_queue_dtor(&qp->hw_rqueue3);
-        kfree(qp);
+	if (qp_attr->rq_count > 1)
+		hw_queue_dtor(&qp->hw_rqueue2);
+	if (qp_attr->rq_count > 2)
+		hw_queue_dtor(&qp->hw_rqueue3);
+	kfree(qp);
 
-        return hret;
+	return hret;
 }
 
 int ehea_destroy_qp(struct ehea_qp *qp)
 {
-        u64 hret;
-        if (!qp)
-                return 0;
+	u64 hret;
+	if (!qp)
+		return 0;
 
-        if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
-                ehea_error_data(qp->adapter, qp->fw_handle);
-                hret = ehea_destroy_qp_res(qp, FORCE_FREE);
-        }
+	if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
+		ehea_error_data(qp->adapter, qp->fw_handle);
+		hret = ehea_destroy_qp_res(qp, FORCE_FREE);
+	}
 
-        if (hret != H_SUCCESS) {
-                ehea_error("destroy QP failed");
-                return -EIO;
-        }
+	if (hret != H_SUCCESS) {
+		ehea_error("destroy QP failed");
+		return -EIO;
+	}
 
-        return 0;
+	return 0;
+}
+
+int ehea_create_busmap( void )
+{
+	u64 vaddr = EHEA_BUSMAP_START;
+	unsigned long abs_max_pfn = 0;
+	unsigned long sec_max_pfn;
+	int i;
+
+	/*
+	 * Sections are not in ascending order -> Loop over all sections and
+	 * find the highest PFN to compute the required map size.
+	*/
+	ehea_bmap.valid_sections = 0;
+
+	for (i = 0; i < NR_MEM_SECTIONS; i++)
+		if (valid_section_nr(i)) {
+			sec_max_pfn = section_nr_to_pfn(i);
+			if (sec_max_pfn > abs_max_pfn)
+				abs_max_pfn = sec_max_pfn;
+			ehea_bmap.valid_sections++;
+		}
+
+	ehea_bmap.entries = abs_max_pfn / EHEA_PAGES_PER_SECTION + 1;
+	ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr));
+
+	if (!ehea_bmap.vaddr)
+		return -ENOMEM;
+
+	for (i = 0 ; i < ehea_bmap.entries; i++) {
+		unsigned long pfn = section_nr_to_pfn(i);
+
+		if (pfn_valid(pfn)) {
+			ehea_bmap.vaddr[i] = vaddr;
+			vaddr += EHEA_SECTSIZE;
+		} else
+			ehea_bmap.vaddr[i] = 0;
+	}
+
+	return 0;
+}
+
+void ehea_destroy_busmap( void )
+{
+	vfree(ehea_bmap.vaddr);
+}
+
+u64 ehea_map_vaddr(void *caddr)
+{
+	u64 mapped_addr;
+	unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS;
+
+	if (likely(index < ehea_bmap.entries)) {
+		mapped_addr = ehea_bmap.vaddr[index];
+		if (likely(mapped_addr))
+			mapped_addr |= (((unsigned long)caddr)
+					& (EHEA_SECTSIZE - 1));
+		else
+			mapped_addr = -1;
+	} else
+		mapped_addr = -1;
+
+	if (unlikely(mapped_addr == -1))
+		if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
+			queue_work(ehea_driver_wq, &ehea_rereg_mr_task);
+
+	return mapped_addr;
 }
 
 int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
 {
-	int i, k, ret;
-	u64 hret, pt_abs, start, end, nr_pages;
-	u32 acc_ctrl = EHEA_MR_ACC_CTRL;
+	int ret;
 	u64 *pt;
+	void *pg;
+	u64 hret, pt_abs, i, j, m, mr_len;
+	u32 acc_ctrl = EHEA_MR_ACC_CTRL;
 
-	start = KERNELBASE;
-	end = (u64)high_memory;
-	nr_pages = (end - start) / EHEA_PAGESIZE;
+	mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE;
 
-	pt =  kzalloc(PAGE_SIZE, GFP_KERNEL);
+	pt =  kzalloc(EHEA_MAX_RPAGE * sizeof(u64), GFP_KERNEL);
 	if (!pt) {
 		ehea_error("no mem");
 		ret = -ENOMEM;
@@ -566,7 +639,8 @@
 	}
 	pt_abs = virt_to_abs(pt);
 
-	hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start,
+	hret = ehea_h_alloc_resource_mr(adapter->handle,
+					EHEA_BUSMAP_START, mr_len,
 					acc_ctrl, adapter->pd,
 					&mr->handle, &mr->lkey);
 	if (hret != H_SUCCESS) {
@@ -575,49 +649,43 @@
 		goto out;
 	}
 
-	mr->vaddr = KERNELBASE;
-	k = 0;
+	for (i = 0 ; i < ehea_bmap.entries; i++)
+		if (ehea_bmap.vaddr[i]) {
+			void *sectbase = __va(i << SECTION_SIZE_BITS);
+			unsigned long k = 0;
 
-	while (nr_pages > 0) {
-		if (nr_pages > 1) {
-			u64 num_pages = min(nr_pages, (u64)512);
-			for (i = 0; i < num_pages; i++)
-				pt[i] = virt_to_abs((void*)(((u64)start) +
-							    ((k++) *
-							     EHEA_PAGESIZE)));
+			for (j = 0; j < (PAGES_PER_SECTION / EHEA_MAX_RPAGE);
+			      j++) {
 
-			hret = ehea_h_register_rpage_mr(adapter->handle,
-							mr->handle, 0,
-							0, (u64)pt_abs,
-							num_pages);
-			nr_pages -= num_pages;
-		} else {
-			u64 abs_adr = virt_to_abs((void*)(((u64)start) +
-							  (k * EHEA_PAGESIZE)));
+				for (m = 0; m < EHEA_MAX_RPAGE; m++) {
+					pg = sectbase + ((k++) * EHEA_PAGESIZE);
+					pt[m] = virt_to_abs(pg);
+				}
 
-			hret = ehea_h_register_rpage_mr(adapter->handle,
-							mr->handle, 0,
-							0, abs_adr,1);
-			nr_pages--;
+				hret = ehea_h_register_rpage_mr(adapter->handle,
+								mr->handle,
+								0, 0, pt_abs,
+								EHEA_MAX_RPAGE);
+				if ((hret != H_SUCCESS)
+				    && (hret != H_PAGE_REGISTERED)) {
+					ehea_h_free_resource(adapter->handle,
+							     mr->handle,
+							     FORCE_FREE);
+					ehea_error("register_rpage_mr failed");
+					ret = -EIO;
+					goto out;
+				}
+			}
 		}
 
-		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) {
-			ehea_h_free_resource(adapter->handle,
-					     mr->handle, FORCE_FREE);
-			ehea_error("register_rpage_mr failed");
-			ret = -EIO;
-			goto out;
-		}
-	}
-
 	if (hret != H_SUCCESS) {
-		ehea_h_free_resource(adapter->handle, mr->handle,
-				     FORCE_FREE);
-		ehea_error("register_rpage failed for last page");
+		ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
+		ehea_error("registering mr failed");
 		ret = -EIO;
 		goto out;
 	}
 
+	mr->vaddr = EHEA_BUSMAP_START;
 	mr->adapter = adapter;
 	ret = 0;
 out:
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index c0eb3e0..b71f845 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -36,8 +36,14 @@
  * page size of ehea hardware queues
  */
 
-#define EHEA_PAGESHIFT  12
-#define EHEA_PAGESIZE   4096UL
+#define EHEA_PAGESHIFT         12
+#define EHEA_PAGESIZE          (1UL << EHEA_PAGESHIFT)
+#define EHEA_SECTSIZE          (1UL << 24)
+#define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> PAGE_SHIFT)
+
+#if (1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE
+#error eHEA module can't work if kernel sectionsize < ehea sectionsize
+#endif
 
 /* Some abbreviations used here:
  *
@@ -372,4 +378,8 @@
 
 void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
 
+int ehea_create_busmap( void );
+void ehea_destroy_busmap( void );
+u64 ehea_map_vaddr(void *caddr);
+
 #endif	/* __EHEA_QMR_H__ */
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 5e51794..1197784 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1201,7 +1201,7 @@
 							    ep->rx_ring[entry].bufaddr,
 							    ep->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
-				eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(ep->pci_dev,
 							       ep->rx_ring[entry].bufaddr,
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index abe9b08..ff9f177 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -1727,8 +1727,8 @@
 				/* Call copy + cksum if available. */
 
 #if ! defined(__alpha__)
-				eth_copy_and_sum(skb,
-					np->cur_rx->skbuff->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb,
+					np->cur_rx->skbuff->data, pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 255b091..03023dd 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -648,7 +648,7 @@
 		fep->stats.rx_dropped++;
 	} else {
 		skb_put(skb,pkt_len-4);	/* Make room */
-		eth_copy_and_sum(skb, data, pkt_len-4, 0);
+		skb_copy_to_linear_data(skb, data, pkt_len-4);
 		skb->protocol=eth_type_trans(skb,dev);
 		netif_rx(skb);
 	}
diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
index a84c232..afb34de 100644
--- a/drivers/net/fec_8xx/Kconfig
+++ b/drivers/net/fec_8xx/Kconfig
@@ -1,6 +1,6 @@
 config FEC_8XX
 	tristate "Motorola 8xx FEC driver"
-	depends on NET_ETHERNET && 8xx
+	depends on 8XX
 	select MII
 
 config FEC_8XX_GENERIC_PHY
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
index 88efe97..e5502af 100644
--- a/drivers/net/fec_8xx/fec_main.c
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -550,7 +550,7 @@
 				skbn = dev_alloc_skb(pkt_len + 2);
 				if (skbn != NULL) {
 					skb_reserve(skbn, 2);	/* align IP header */
-					skb_copy_from_linear_data(skb
+					skb_copy_from_linear_data(skb,
 								  skbn->data,
 								  pkt_len);
 					/* swap */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 7a01802..136827f 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -195,7 +195,7 @@
 #define NVREG_IRQ_TX_FORCED		0x0100
 #define NVREG_IRQ_RECOVER_ERROR		0x8000
 #define NVREG_IRQMASK_THROUGHPUT	0x00df
-#define NVREG_IRQMASK_CPU		0x0040
+#define NVREG_IRQMASK_CPU		0x0060
 #define NVREG_IRQ_TX_ALL		(NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED)
 #define NVREG_IRQ_RX_ALL		(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED)
 #define NVREG_IRQ_OTHER			(NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RECOVER_ERROR)
@@ -550,6 +550,8 @@
 /* PHY defines */
 #define PHY_OUI_MARVELL	0x5043
 #define PHY_OUI_CICADA	0x03f1
+#define PHY_OUI_VITESSE	0x01c1
+#define PHY_OUI_REALTEK	0x01c1
 #define PHYID1_OUI_MASK	0x03ff
 #define PHYID1_OUI_SHFT	6
 #define PHYID2_OUI_MASK	0xfc00
@@ -557,12 +559,36 @@
 #define PHYID2_MODEL_MASK		0x03f0
 #define PHY_MODEL_MARVELL_E3016		0x220
 #define PHY_MARVELL_E3016_INITMASK	0x0300
-#define PHY_INIT1	0x0f000
-#define PHY_INIT2	0x0e00
-#define PHY_INIT3	0x01000
-#define PHY_INIT4	0x0200
-#define PHY_INIT5	0x0004
-#define PHY_INIT6	0x02000
+#define PHY_CICADA_INIT1	0x0f000
+#define PHY_CICADA_INIT2	0x0e00
+#define PHY_CICADA_INIT3	0x01000
+#define PHY_CICADA_INIT4	0x0200
+#define PHY_CICADA_INIT5	0x0004
+#define PHY_CICADA_INIT6	0x02000
+#define PHY_VITESSE_INIT_REG1	0x1f
+#define PHY_VITESSE_INIT_REG2	0x10
+#define PHY_VITESSE_INIT_REG3	0x11
+#define PHY_VITESSE_INIT_REG4	0x12
+#define PHY_VITESSE_INIT_MSK1	0xc
+#define PHY_VITESSE_INIT_MSK2	0x0180
+#define PHY_VITESSE_INIT1	0x52b5
+#define PHY_VITESSE_INIT2	0xaf8a
+#define PHY_VITESSE_INIT3	0x8
+#define PHY_VITESSE_INIT4	0x8f8a
+#define PHY_VITESSE_INIT5	0xaf86
+#define PHY_VITESSE_INIT6	0x8f86
+#define PHY_VITESSE_INIT7	0xaf82
+#define PHY_VITESSE_INIT8	0x0100
+#define PHY_VITESSE_INIT9	0x8f82
+#define PHY_VITESSE_INIT10	0x0
+#define PHY_REALTEK_INIT_REG1	0x1f
+#define PHY_REALTEK_INIT_REG2	0x19
+#define PHY_REALTEK_INIT_REG3	0x13
+#define PHY_REALTEK_INIT1	0x0000
+#define PHY_REALTEK_INIT2	0x8e00
+#define PHY_REALTEK_INIT3	0x0001
+#define PHY_REALTEK_INIT4	0xad17
+
 #define PHY_GIGABIT	0x0100
 
 #define PHY_TIMEOUT	0x1
@@ -1096,6 +1122,28 @@
 			return PHY_ERROR;
 		}
 	}
+	if (np->phy_oui == PHY_OUI_REALTEK) {
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+	}
 
 	/* set advertise register */
 	reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
@@ -1141,14 +1189,14 @@
 	/* phy vendor specific configuration */
 	if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {
 		phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
-		phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
-		phy_reserved |= (PHY_INIT3 | PHY_INIT4);
+		phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2);
+		phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4);
 		if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {
 			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
 		phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
-		phy_reserved |= PHY_INIT5;
+		phy_reserved |= PHY_CICADA_INIT5;
 		if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {
 			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
 			return PHY_ERROR;
@@ -1156,12 +1204,106 @@
 	}
 	if (np->phy_oui == PHY_OUI_CICADA) {
 		phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
-		phy_reserved |= PHY_INIT6;
+		phy_reserved |= PHY_CICADA_INIT6;
 		if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {
 			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
 	}
+	if (np->phy_oui == PHY_OUI_VITESSE) {
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+		phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+		phy_reserved |= PHY_VITESSE_INIT3;
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+		phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+		phy_reserved |= PHY_VITESSE_INIT3;
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+		phy_reserved &= ~PHY_VITESSE_INIT_MSK2;
+		phy_reserved |= PHY_VITESSE_INIT8;
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+	}
+	if (np->phy_oui == PHY_OUI_REALTEK) {
+		/* reset could have cleared these out, set them back */
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+	}
+
 	/* some phys clear out pause advertisment on reset, set it back */
 	mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
 
@@ -4605,12 +4747,7 @@
 	writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
 
 	spin_unlock_irq(&np->lock);
-};
-
-static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	/* nothing to do */
-};
+}
 
 /* The mgmt unit and driver use a semaphore to access the phy during init */
 static int nv_mgmt_acquire_sema(struct net_device *dev)
@@ -4830,8 +4967,10 @@
 
 	drain_ring(dev);
 
-	if (np->wolenabled)
+	if (np->wolenabled) {
+		writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
 		nv_start_rx(dev);
+	}
 
 	/* FIXME: power down nic */
 
@@ -4956,7 +5095,6 @@
 		np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
 		dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
 		dev->vlan_rx_register = nv_vlan_rx_register;
-		dev->vlan_rx_kill_vid = nv_vlan_rx_kill_vid;
 	}
 
 	np->msi_flags = 0;
@@ -5088,15 +5226,13 @@
 	np->wolenabled = 0;
 
 	if (id->driver_data & DEV_HAS_POWER_CNTRL) {
-		u8 revision_id;
-		pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id);
 
 		/* take phy and nic out of low power mode */
 		powerstate = readl(base + NvRegPowerState2);
 		powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
 		if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
 		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) &&
-		    revision_id >= 0xA3)
+		    pci_dev->revision >= 0xA3)
 			powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
 		writel(powerstate, base + NvRegPowerState2);
 	}
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 6aaee67..e27ee21 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -1,6 +1,6 @@
 config FS_ENET
        tristate "Freescale Ethernet Driver"
-       depends on NET_ETHERNET && (CPM1 || CPM2)
+       depends on CPM1 || CPM2
        select MII
 
 config FS_ENET_HAS_SCC
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index f5b3cba..d7a1a58 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -130,6 +130,9 @@
 static void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
 static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
+static void gfar_configure_serdes(struct net_device *dev);
+extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value);
+extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum);
 #ifdef CONFIG_GFAR_NAPI
 static int gfar_poll(struct net_device *dev, int *budget);
 #endif
@@ -140,7 +143,6 @@
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
 static void gfar_vlan_rx_register(struct net_device *netdev,
 		                struct vlan_group *grp);
-static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
 void gfar_halt(struct net_device *dev);
 void gfar_start(struct net_device *dev);
 static void gfar_clear_exact_match(struct net_device *dev);
@@ -284,7 +286,6 @@
 
 	if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
 		dev->vlan_rx_register = gfar_vlan_rx_register;
-		dev->vlan_rx_kill_vid = gfar_vlan_rx_kill_vid;
 
 		dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 
@@ -453,6 +454,9 @@
 
 	phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
 
+	if (interface == PHY_INTERFACE_MODE_SGMII)
+		gfar_configure_serdes(dev);
+
 	if (IS_ERR(phydev)) {
 		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
 		return PTR_ERR(phydev);
@@ -467,6 +471,27 @@
 	return 0;
 }
 
+static void gfar_configure_serdes(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_mii __iomem *regs =
+			(void __iomem *)&priv->regs->gfar_mii_regs;
+
+	/* Initialise TBI i/f to communicate with serdes (lynx phy) */
+
+	/* Single clk mode, mii mode off(for aerdes communication) */
+	gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
+
+	/* Supported pause and full-duplex, no half-duplex */
+	gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE,
+			ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
+			ADVERTISE_1000XPSE_ASYM);
+
+	/* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
+	gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
+			BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
+}
+
 static void init_registers(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
@@ -946,7 +971,7 @@
 		flags |= TXFCB_UDP;
 		fcb->phcs = udp_hdr(skb)->check;
 	} else
-		fcb->phcs = udp_hdr(skb)->check;
+		fcb->phcs = tcp_hdr(skb)->check;
 
 	/* l3os is the distance between the start of the
 	 * frame (skb->data) and the start of the IP hdr.
@@ -1133,20 +1158,6 @@
 	spin_unlock_irqrestore(&priv->rxlock, flags);
 }
 
-
-static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
-{
-	struct gfar_private *priv = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->rxlock, flags);
-
-	vlan_group_set_device(priv->vlgrp, vid, NULL);
-
-	spin_unlock_irqrestore(&priv->rxlock, flags);
-}
-
-
 static int gfar_change_mtu(struct net_device *dev, int new_mtu)
 {
 	int tempsize, tempval;
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 39e9e32..d8e779c 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -136,6 +136,12 @@
 #define MIIMCFG_RESET           0x80000000
 #define MIIMIND_BUSY            0x00000001
 
+/* TBI register addresses */
+#define MII_TBICON		0x11
+
+/* TBICON register bit fields */
+#define TBICON_CLK_SELECT	0x0020
+
 /* MAC register bits */
 #define MACCFG1_SOFT_RESET	0x80000000
 #define MACCFG1_RESET_RX_MC	0x00080000
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index bcc6b82..ac3596f 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -31,7 +31,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <asm/ocp.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
@@ -43,13 +42,18 @@
 #include "gianfar.h"
 #include "gianfar_mii.h"
 
-/* Write value to the PHY at mii_id at register regnum,
- * on the bus, waiting until the write is done before returning.
- * All PHY configuration is done through the TSEC1 MIIM regs */
-int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+/*
+ * Write value to the PHY at mii_id at register regnum,
+ * on the bus attached to the local interface, which may be different from the
+ * generic mdio bus (tied to a single interface), waiting until the write is
+ * done before returning. This is helpful in programming interfaces like
+ * the TBI which control interfaces like onchip SERDES and are always tied to
+ * the local mdio pins, which may not be the same as system mdio bus, used for
+ * controlling the external PHYs, for example.
+ */
+int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id,
+			  int regnum, u16 value)
 {
-	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
-
 	/* Set the PHY address and the register address we want to write */
 	gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
 
@@ -63,12 +67,19 @@
 	return 0;
 }
 
-/* Read the bus for PHY at addr mii_id, register regnum, and
- * return the value.  Clears miimcom first.  All PHY
- * configuration has to be done through the TSEC1 MIIM regs */
-int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+/*
+ * Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value.  Clears miimcom first.  All PHY operation
+ * done on the bus attached to the local interface,
+ * which may be different from the generic mdio bus
+ * This is helpful in programming interfaces like
+ * the TBI which, inturn, control interfaces like onchip SERDES
+ * and are always tied to the local mdio pins, which may not be the
+ * same as system mdio bus, used for controlling the external PHYs, for eg.
+ */
+int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum)
+
 {
-	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
 	u16 value;
 
 	/* Set the PHY address and the register address we want to read */
@@ -88,6 +99,27 @@
 	return value;
 }
 
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+	/* Write to the local MII regs */
+	return(gfar_local_mdio_write(regs, mii_id, regnum, value));
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value.  Clears miimcom first.  All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+	/* Read the local MII regs */
+	return(gfar_local_mdio_read(regs, mii_id, regnum));
+}
 
 /* Reset the MIIM registers, and wait for the bus to free */
 int gfar_mdio_reset(struct mii_bus *bus)
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 2521b11..15254dc 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -1575,8 +1575,8 @@
 							    PCI_DMA_FROMDEVICE);
 				/* Call copy + cksum if available. */
 #if 1 || USE_IP_COPYSUM
-				eth_copy_and_sum(skb,
-					hmp->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb,
+					hmp->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 8118a67..8caa591c 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -3005,7 +3005,7 @@
 	return cards > 0 ? 0 : -ENODEV;
 }
 
-static void __exit hp100_isa_cleanup(void)
+static void hp100_isa_cleanup(void)
 {
 	int i;
 
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 3bec0f7..d96eb72 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -915,17 +915,36 @@
 {
 	struct ibmveth_adapter *adapter = dev->priv;
 	int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
-	int i;
+	int reinit = 0;
+	int i, rc;
 
 	if (new_mtu < IBMVETH_MAX_MTU)
 		return -EINVAL;
 
+	for (i = 0; i < IbmVethNumBufferPools; i++)
+		if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size)
+			break;
+
+	if (i == IbmVethNumBufferPools)
+		return -EINVAL;
+
 	/* Look for an active buffer pool that can hold the new MTU */
 	for(i = 0; i<IbmVethNumBufferPools; i++) {
-		if (!adapter->rx_buff_pool[i].active)
-			continue;
+		if (!adapter->rx_buff_pool[i].active) {
+			adapter->rx_buff_pool[i].active = 1;
+			reinit = 1;
+		}
+
 		if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
-			dev->mtu = new_mtu;
+			if (reinit && netif_running(adapter->netdev)) {
+				adapter->pool_config = 1;
+				ibmveth_close(adapter->netdev);
+				adapter->pool_config = 0;
+				dev->mtu = new_mtu;
+				if ((rc = ibmveth_open(adapter->netdev)))
+					return rc;
+			} else
+				dev->mtu = new_mtu;
 			return 0;
 		}
 	}
@@ -1243,16 +1262,19 @@
 
 	if (attr == &veth_active_attr) {
 		if (value && !pool->active) {
-			if(ibmveth_alloc_buffer_pool(pool)) {
-                                ibmveth_error_printk("unable to alloc pool\n");
-                                return -ENOMEM;
-                        }
-			pool->active = 1;
-			adapter->pool_config = 1;
-			ibmveth_close(netdev);
-			adapter->pool_config = 0;
-			if ((rc = ibmveth_open(netdev)))
-				return rc;
+			if (netif_running(netdev)) {
+				if(ibmveth_alloc_buffer_pool(pool)) {
+					ibmveth_error_printk("unable to alloc pool\n");
+					return -ENOMEM;
+				}
+				pool->active = 1;
+				adapter->pool_config = 1;
+				ibmveth_close(netdev);
+				adapter->pool_config = 0;
+				if ((rc = ibmveth_open(netdev)))
+					return rc;
+			} else
+				pool->active = 1;
 		} else if (!value && pool->active) {
 			int mtu = netdev->mtu + IBMVETH_BUFF_OH;
 			int i;
@@ -1281,23 +1303,29 @@
 		if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
 			return -EINVAL;
 		else {
-			adapter->pool_config = 1;
-			ibmveth_close(netdev);
-			adapter->pool_config = 0;
-			pool->size = value;
-			if ((rc = ibmveth_open(netdev)))
-				return rc;
+			if (netif_running(netdev)) {
+				adapter->pool_config = 1;
+				ibmveth_close(netdev);
+				adapter->pool_config = 0;
+				pool->size = value;
+				if ((rc = ibmveth_open(netdev)))
+					return rc;
+			} else
+				pool->size = value;
 		}
 	} else if (attr == &veth_size_attr) {
 		if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
 			return -EINVAL;
 		else {
-			adapter->pool_config = 1;
-			ibmveth_close(netdev);
-			adapter->pool_config = 0;
-			pool->buff_size = value;
-			if ((rc = ibmveth_open(netdev)))
-				return rc;
+			if (netif_running(netdev)) {
+				adapter->pool_config = 1;
+				ibmveth_close(netdev);
+				adapter->pool_config = 0;
+				pool->buff_size = value;
+				if ((rc = ibmveth_open(netdev)))
+					return rc;
+			} else
+				pool->buff_size = value;
 		}
 	}
 
@@ -1309,7 +1337,7 @@
 
 #define ATTR(_name, _mode)      \
         struct attribute veth_##_name##_attr = {               \
-        .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
+        .name = __stringify(_name), .mode = _mode, \
         };
 
 static ATTR(active, 0644);
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 07b4c0d..f5c3598 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -136,13 +136,14 @@
 
 }
 
-static void __init ifb_setup(struct net_device *dev)
+static void ifb_setup(struct net_device *dev)
 {
 	/* Initialize the device structure. */
 	dev->get_stats = ifb_get_stats;
 	dev->hard_start_xmit = ifb_xmit;
 	dev->open = &ifb_open;
 	dev->stop = &ifb_close;
+	dev->destructor = free_netdev;
 
 	/* Fill in device structure with ethernet-generic values. */
 	ether_setup(dev);
@@ -197,12 +198,6 @@
 	return stats;
 }
 
-static struct net_device **ifbs;
-
-/* Number of ifb devices to be set up by this module. */
-module_param(numifbs, int, 0);
-MODULE_PARM_DESC(numifbs, "Number of ifb devices");
-
 static int ifb_close(struct net_device *dev)
 {
 	struct ifb_private *dp = netdev_priv(dev);
@@ -226,6 +221,28 @@
 	return 0;
 }
 
+static int ifb_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+	if (tb[IFLA_ADDRESS]) {
+		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+			return -EINVAL;
+		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+			return -EADDRNOTAVAIL;
+	}
+	return 0;
+}
+
+static struct rtnl_link_ops ifb_link_ops __read_mostly = {
+	.kind		= "ifb",
+	.priv_size	= sizeof(struct ifb_private),
+	.setup		= ifb_setup,
+	.validate	= ifb_validate,
+};
+
+/* Number of ifb devices to be set up by this module. */
+module_param(numifbs, int, 0);
+MODULE_PARM_DESC(numifbs, "Number of ifb devices");
+
 static int __init ifb_init_one(int index)
 {
 	struct net_device *dev_ifb;
@@ -237,49 +254,44 @@
 	if (!dev_ifb)
 		return -ENOMEM;
 
-	if ((err = register_netdev(dev_ifb))) {
-		free_netdev(dev_ifb);
-		dev_ifb = NULL;
-	} else {
-		ifbs[index] = dev_ifb;
-	}
+	err = dev_alloc_name(dev_ifb, dev_ifb->name);
+	if (err < 0)
+		goto err;
 
+	dev_ifb->rtnl_link_ops = &ifb_link_ops;
+	err = register_netdevice(dev_ifb);
+	if (err < 0)
+		goto err;
+	return 0;
+
+err:
+	free_netdev(dev_ifb);
 	return err;
 }
 
-static void ifb_free_one(int index)
-{
-	unregister_netdev(ifbs[index]);
-	free_netdev(ifbs[index]);
-}
-
 static int __init ifb_init_module(void)
 {
-	int i, err = 0;
-	ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL);
-	if (!ifbs)
-		return -ENOMEM;
+	int i, err;
+
+	rtnl_lock();
+	err = __rtnl_link_register(&ifb_link_ops);
+
 	for (i = 0; i < numifbs && !err; i++)
 		err = ifb_init_one(i);
-	if (err) {
-		i--;
-		while (--i >= 0)
-			ifb_free_one(i);
-	}
+	if (err)
+		__rtnl_link_unregister(&ifb_link_ops);
+	rtnl_unlock();
 
 	return err;
 }
 
 static void __exit ifb_cleanup_module(void)
 {
-	int i;
-
-	for (i = 0; i < numifbs; i++)
-		ifb_free_one(i);
-	kfree(ifbs);
+	rtnl_link_unregister(&ifb_link_ops);
 }
 
 module_init(ifb_init_module);
 module_exit(ifb_cleanup_module);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jamal Hadi Salim");
+MODULE_ALIAS_RTNL_LINK("ifb");
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index f749e07..3ca1e8e 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -352,13 +352,12 @@
 
 static int nic_init(struct ioc3 *ioc3)
 {
-	const char *type;
+	const char *unknown = "unknown";
+	const char *type = unknown;
 	u8 crc;
 	u8 serial[6];
 	int save = 0, i;
 
-	type = "unknown";
-
 	while (1) {
 		u64 reg;
 		reg = nic_find(ioc3, &save);
@@ -392,7 +391,7 @@
 	}
 
 	printk("Found %s NIC", type);
-	if (type != "unknown") {
+	if (type != unknown) {
 		printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x,"
 			" CRC %02x", serial[0], serial[1], serial[2],
 			serial[3], serial[4], serial[5], crc);
@@ -1103,20 +1102,28 @@
  * MiniDINs; all other subdevices are left swinging in the wind, leave
  * them disabled.
  */
-static inline int ioc3_is_menet(struct pci_dev *pdev)
-{
-	struct pci_dev *dev;
 
-	return pdev->bus->parent == NULL
-	       && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(0, 0)))
-	       && dev->vendor == PCI_VENDOR_ID_SGI
-	       && dev->device == PCI_DEVICE_ID_SGI_IOC3
-	       && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(1, 0)))
-	       && dev->vendor == PCI_VENDOR_ID_SGI
-	       && dev->device == PCI_DEVICE_ID_SGI_IOC3
-	       && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(2, 0)))
-	       && dev->vendor == PCI_VENDOR_ID_SGI
-	       && dev->device == PCI_DEVICE_ID_SGI_IOC3;
+static int ioc3_adjacent_is_ioc3(struct pci_dev *pdev, int slot)
+{
+	struct pci_dev *dev = pci_get_slot(pdev->bus, PCI_DEVFN(slot, 0));
+	int ret = 0;
+
+	if (dev) {
+		if (dev->vendor == PCI_VENDOR_ID_SGI &&
+			dev->device == PCI_DEVICE_ID_SGI_IOC3)
+			ret = 1;
+		pci_dev_put(dev);
+	}
+
+	return ret;
+}
+
+static int ioc3_is_menet(struct pci_dev *pdev)
+{
+	return pdev->bus->parent == NULL &&
+	       ioc3_adjacent_is_ioc3(pdev, 0) &&
+	       ioc3_adjacent_is_ioc3(pdev, 1) &&
+	       ioc3_adjacent_is_ioc3(pdev, 2);
 }
 
 #ifdef CONFIG_SERIAL_8250
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 3098960..3078c41 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -509,7 +509,7 @@
 	IRDA_DEBUG(0, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", 
 		   __FUNCTION__, iir, lsr, iobase);
 
-	IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%d\n", 
+	IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%td\n",
 		   __FUNCTION__, self->transmitting, self->tx_buff.len,
 		   self->tx_buff.data - self->tx_buff.head);
 
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index 2174291..bdd5c97 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -4,7 +4,7 @@
 * Version:       0.1.1
 * Description:   Irda KingSun/DonShine USB Dongle
 * Status:        Experimental
-* Author:        Alex Villac�s Lasso <a_villacis@palosanto.com>
+* Author:        Alex Villacís Lasso <a_villacis@palosanto.com>
 *
 *  	Based on stir4200 and mcs7780 drivers, with (strange?) differences
 *
@@ -652,6 +652,6 @@
 }
 module_exit(kingsun_cleanup);
 
-MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>");
+MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
 MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 9043bf4..36ab983 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -79,7 +79,7 @@
 MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
 MODULE_LICENSE("GPL");
 
-static int smsc_nopnp;
+static int smsc_nopnp = 1;
 module_param_named(nopnp, smsc_nopnp, bool, 0);
 MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
 
@@ -416,6 +416,13 @@
 {
 	int ret = 0;
 
+#ifdef CONFIG_PCI
+	if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
+		/* Ignore errors from preconfiguration */
+		IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
+	}
+#endif
+
 	if (ircc_fir > 0 && ircc_sir > 0) {
 		IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
 		IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
@@ -459,13 +466,6 @@
 		return ret;
 	}
 
-#ifdef CONFIG_PCI
-	if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
-		/* Ignore errors from preconfiguration */
-		IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
-	}
-#endif
-
 	dev_count = 0;
 
 	if (smsc_nopnp || !pnp_platform_devices ||
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index bf78ef1..0538ca9 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -44,6 +44,7 @@
 #include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
@@ -1660,8 +1661,8 @@
 	idev = ndev->priv;
 
 	spin_lock_init(&idev->lock);
-	init_MUTEX(&idev->sem);
-	down(&idev->sem);
+	mutex_init(&idev->mtx);
+	mutex_lock(&idev->mtx);
 	idev->pdev = pdev;
 
 	if (vlsi_irda_init(ndev) < 0)
@@ -1689,12 +1690,12 @@
 	IRDA_MESSAGE("%s: registered device %s\n", drivername, ndev->name);
 
 	pci_set_drvdata(pdev, ndev);
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 
 	return 0;
 
 out_freedev:
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 	free_netdev(ndev);
 out_disable:
 	pci_disable_device(pdev);
@@ -1716,12 +1717,12 @@
 	unregister_netdev(ndev);
 
 	idev = ndev->priv;
-	down(&idev->sem);
+	mutex_lock(&idev->mtx);
 	if (idev->proc_entry) {
 		remove_proc_entry(ndev->name, vlsi_proc_root);
 		idev->proc_entry = NULL;
 	}
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 
 	free_netdev(ndev);
 
@@ -1751,7 +1752,7 @@
 		return 0;
 	}
 	idev = ndev->priv;	
-	down(&idev->sem);
+	mutex_lock(&idev->mtx);
 	if (pdev->current_state != 0) {			/* already suspended */
 		if (state.event > pdev->current_state) {	/* simply go deeper */
 			pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -1759,7 +1760,7 @@
 		}
 		else
 			IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, pci_name(pdev), pdev->current_state, state.event);
-		up(&idev->sem);
+		mutex_unlock(&idev->mtx);
 		return 0;
 	}
 
@@ -1775,7 +1776,7 @@
 	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 	pdev->current_state = state.event;
 	idev->resume_ok = 1;
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 	return 0;
 }
 
@@ -1790,9 +1791,9 @@
 		return 0;
 	}
 	idev = ndev->priv;	
-	down(&idev->sem);
+	mutex_lock(&idev->mtx);
 	if (pdev->current_state == 0) {
-		up(&idev->sem);
+		mutex_unlock(&idev->mtx);
 		IRDA_WARNING("%s - %s: already resumed\n",
 			     __FUNCTION__, pci_name(pdev));
 		return 0;
@@ -1814,7 +1815,7 @@
 		 * device and independently resume_ok should catch any garbage config.
 		 */
 		IRDA_WARNING("%s - hm, nothing to resume?\n", __FUNCTION__);
-		up(&idev->sem);
+		mutex_unlock(&idev->mtx);
 		return 0;
 	}
 
@@ -1824,7 +1825,7 @@
 		netif_device_attach(ndev);
 	}
 	idev->resume_ok = 0;
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 	return 0;
 }
 
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 2d3b773..ca12a60 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -728,7 +728,7 @@
 	struct timeval		last_rx;
 
 	spinlock_t		lock;
-	struct semaphore	sem;
+	struct mutex		mtx;
 
 	u8			resume_ok;	
 	struct proc_dir_entry	*proc_entry;
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 6683afc..d9ce1ae 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -111,7 +111,7 @@
 		skb = dev_alloc_skb(desc->pkt_length + 2);
 		if (likely(skb != NULL)) {
 			skb_reserve(skb, 2);
-			eth_copy_and_sum(skb, buf, desc->pkt_length, 0);
+			skb_copy_to_linear_data(skb, buf, desc->pkt_length);
 			skb_put(skb, desc->pkt_length);
 			skb->protocol = eth_type_trans(skb, nds[desc->channel]);
 
@@ -222,7 +222,7 @@
 static void ixpdev_poll_controller(struct net_device *dev)
 {
 	disable_irq(IRQ_IXP2000_THDA0);
-	ixpdev_interrupt(IRQ_IXP2000_THDA0, dev, NULL);
+	ixpdev_interrupt(IRQ_IXP2000_THDA0, dev);
 	enable_irq(IRQ_IXP2000_THDA0);
 }
 #endif
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 0fe96c8..a2f37e5 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -1186,9 +1186,9 @@
 				}
 				skb_reserve(skb,2);	/* 16 byte align */
 				skb_put(skb,pkt_len);	/* Make room */
-				eth_copy_and_sum(skb,
+				skb_copy_to_linear_data(skb,
 					(unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
-					pkt_len,0);
+					pkt_len);
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
 				dev->last_rx = jiffies;
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 6b49fc4..efbae4b 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -83,95 +83,39 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
-#include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/pdc.h>
-#include <asm/cache.h>
 #include <asm/parisc-device.h>
 
 #define LASI_82596_DRIVER_VERSION "LASI 82596 driver - Revision: 1.30"
 
-/* DEBUG flags
- */
-
-#define DEB_INIT	0x0001
-#define DEB_PROBE	0x0002
-#define DEB_SERIOUS	0x0004
-#define DEB_ERRORS	0x0008
-#define DEB_MULTI	0x0010
-#define DEB_TDR		0x0020
-#define DEB_OPEN	0x0040
-#define DEB_RESET	0x0080
-#define DEB_ADDCMD	0x0100
-#define DEB_STATUS	0x0200
-#define DEB_STARTTX	0x0400
-#define DEB_RXADDR	0x0800
-#define DEB_TXADDR	0x1000
-#define DEB_RXFRAME	0x2000
-#define DEB_INTS	0x4000
-#define DEB_STRUCT	0x8000
-#define DEB_ANY		0xffff
-
-
-#define DEB(x,y)	if (i596_debug & (x)) { y; }
-
-
-#define  CHECK_WBACK(priv, addr,len) \
-	do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0)
-
-#define  CHECK_INV(priv, addr,len) \
-	do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0)
-
-#define  CHECK_WBACK_INV(priv, addr,len) \
-	do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
-
-
 #define PA_I82596_RESET		0	/* Offsets relative to LASI-LAN-Addr.*/
 #define PA_CPU_PORT_L_ACCESS	4
 #define PA_CHANNEL_ATTENTION	8
 
+#define OPT_SWAP_PORT	0x0001	/* Need to wordswp on the MPU port */
 
-/*
- * Define various macros for Channel Attention, word swapping etc., dependent
- * on architecture.  MVME and BVME are 680x0 based, otherwise it is Intel.
- */
+#define DMA_ALLOC                        dma_alloc_noncoherent
+#define DMA_FREE                         dma_free_noncoherent
+#define DMA_WBACK(ndev, addr, len) \
+	do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0)
 
-#ifdef __BIG_ENDIAN
-#define WSWAPrfd(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPrbd(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPiscp(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPscb(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPcmd(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPtbd(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPchar(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define ISCP_BUSY	0x00010000
-#define MACH_IS_APRICOT	0
-#else
-#define WSWAPrfd(x)     ((struct i596_rfd *)(x))
-#define WSWAPrbd(x)     ((struct i596_rbd *)(x))
-#define WSWAPiscp(x)    ((struct i596_iscp *)(x))
-#define WSWAPscb(x)     ((struct i596_scb *)(x))
-#define WSWAPcmd(x)     ((struct i596_cmd *)(x))
-#define WSWAPtbd(x)     ((struct i596_tbd *)(x))
-#define WSWAPchar(x)    ((char *)(x))
-#define ISCP_BUSY	0x0001
-#define MACH_IS_APRICOT	1
-#endif
+#define DMA_INV(ndev, addr, len) \
+	do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_FROM_DEVICE); } while (0)
 
-/*
- * The MPU_PORT command allows direct access to the 82596. With PORT access
- * the following commands are available (p5-18). The 32-bit port command
- * must be word-swapped with the most significant word written first.
- * This only applies to VME boards.
- */
-#define PORT_RESET		0x00	/* reset 82596 */
-#define PORT_SELFTEST		0x01	/* selftest */
-#define PORT_ALTSCP		0x02	/* alternate SCB address */
-#define PORT_ALTDUMP		0x03	/* Alternate DUMP address */
+#define DMA_WBACK_INV(ndev, addr, len) \
+	do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
 
-static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+#define SYSBUS      0x0000006c;
+
+/* big endian CPU, 82596 "big" endian mode */
+#define SWAP32(x)   (((u32)(x)<<16) | ((((u32)(x)))>>16))
+#define SWAP16(x)   (x)
+
+#include "lib82596.c"
 
 MODULE_AUTHOR("Richard Hirst");
 MODULE_DESCRIPTION("i82596 driver");
@@ -179,255 +123,15 @@
 module_param(i596_debug, int, 0);
 MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask");
 
-/* Copy frames shorter than rx_copybreak, otherwise pass on up in
- * a full sized sk_buff.  Value of 100 stolen from tulip.c (!alpha).
- */
-static int rx_copybreak = 100;
-
-#define MAX_DRIVERS	4	/* max count of drivers */
-
-#define PKT_BUF_SZ	1536
-#define MAX_MC_CNT	64
-
-#define I596_NULL ((u32)0xffffffff)
-
-#define CMD_EOL		0x8000	/* The last command of the list, stop. */
-#define CMD_SUSP	0x4000	/* Suspend after doing cmd. */
-#define CMD_INTR	0x2000	/* Interrupt after doing cmd. */
-
-#define CMD_FLEX	0x0008	/* Enable flexible memory model */
-
-enum commands {
-	CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
-	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
-};
-
-#define STAT_C		0x8000	/* Set to 0 after execution */
-#define STAT_B		0x4000	/* Command being executed */
-#define STAT_OK		0x2000	/* Command executed ok */
-#define STAT_A		0x1000	/* Command aborted */
-
-#define	 CUC_START	0x0100
-#define	 CUC_RESUME	0x0200
-#define	 CUC_SUSPEND    0x0300
-#define	 CUC_ABORT	0x0400
-#define	 RX_START	0x0010
-#define	 RX_RESUME	0x0020
-#define	 RX_SUSPEND	0x0030
-#define	 RX_ABORT	0x0040
-
-#define TX_TIMEOUT	5
-
-#define OPT_SWAP_PORT	0x0001	/* Need to wordswp on the MPU port */
-
-
-struct i596_reg {
-	unsigned short porthi;
-	unsigned short portlo;
-	u32            ca;
-};
-
-#define EOF		0x8000
-#define SIZE_MASK	0x3fff
-
-struct i596_tbd {
-	unsigned short size;
-	unsigned short pad;
-	dma_addr_t     next;
-	dma_addr_t     data;
-	u32 cache_pad[5];		/* Total 32 bytes... */
-};
-
-/* The command structure has two 'next' pointers; v_next is the address of
- * the next command as seen by the CPU, b_next is the address of the next
- * command as seen by the 82596.  The b_next pointer, as used by the 82596
- * always references the status field of the next command, rather than the
- * v_next field, because the 82596 is unaware of v_next.  It may seem more
- * logical to put v_next at the end of the structure, but we cannot do that
- * because the 82596 expects other fields to be there, depending on command
- * type.
- */
-
-struct i596_cmd {
-	struct i596_cmd *v_next;	/* Address from CPUs viewpoint */
-	unsigned short status;
-	unsigned short command;
-	dma_addr_t     b_next;	/* Address from i596 viewpoint */
-};
-
-struct tx_cmd {
-	struct i596_cmd cmd;
-	dma_addr_t     tbd;
-	unsigned short size;
-	unsigned short pad;
-	struct sk_buff *skb;		/* So we can free it after tx */
-	dma_addr_t dma_addr;
-#ifdef __LP64__
-	u32 cache_pad[6];		/* Total 64 bytes... */
-#else
-	u32 cache_pad[1];		/* Total 32 bytes... */
-#endif
-};
-
-struct tdr_cmd {
-	struct i596_cmd cmd;
-	unsigned short status;
-	unsigned short pad;
-};
-
-struct mc_cmd {
-	struct i596_cmd cmd;
-	short mc_cnt;
-	char mc_addrs[MAX_MC_CNT*6];
-};
-
-struct sa_cmd {
-	struct i596_cmd cmd;
-	char eth_addr[8];
-};
-
-struct cf_cmd {
-	struct i596_cmd cmd;
-	char i596_config[16];
-};
-
-struct i596_rfd {
-	unsigned short stat;
-	unsigned short cmd;
-	dma_addr_t     b_next;	/* Address from i596 viewpoint */
-	dma_addr_t     rbd;
-	unsigned short count;
-	unsigned short size;
-	struct i596_rfd *v_next;	/* Address from CPUs viewpoint */
-	struct i596_rfd *v_prev;
-#ifndef __LP64__
-	u32 cache_pad[2];		/* Total 32 bytes... */
-#endif
-};
-
-struct i596_rbd {
-    /* hardware data */
-    unsigned short count;
-    unsigned short zero1;
-    dma_addr_t     b_next;
-    dma_addr_t     b_data;		/* Address from i596 viewpoint */
-    unsigned short size;
-    unsigned short zero2;
-    /* driver data */
-    struct sk_buff *skb;
-    struct i596_rbd *v_next;
-    dma_addr_t     b_addr;		/* This rbd addr from i596 view */
-    unsigned char *v_data;		/* Address from CPUs viewpoint */
-					/* Total 32 bytes... */
-#ifdef __LP64__
-    u32 cache_pad[4];
-#endif
-};
-
-/* These values as chosen so struct i596_private fits in one page... */
-
-#define TX_RING_SIZE 32
-#define RX_RING_SIZE 16
-
-struct i596_scb {
-	unsigned short status;
-	unsigned short command;
-	dma_addr_t    cmd;
-	dma_addr_t    rfd;
-	u32           crc_err;
-	u32           align_err;
-	u32           resource_err;
-	u32           over_err;
-	u32           rcvdt_err;
-	u32           short_err;
-	unsigned short t_on;
-	unsigned short t_off;
-};
-
-struct i596_iscp {
-	u32           stat;
-	dma_addr_t    scb;
-};
-
-struct i596_scp {
-	u32           sysbus;
-	u32            pad;
-	dma_addr_t    iscp;
-};
-
-struct i596_private {
-	volatile struct i596_scp scp		__attribute__((aligned(32)));
-	volatile struct i596_iscp iscp		__attribute__((aligned(32)));
-	volatile struct i596_scb scb		__attribute__((aligned(32)));
-	struct sa_cmd sa_cmd			__attribute__((aligned(32)));
-	struct cf_cmd cf_cmd			__attribute__((aligned(32)));
-	struct tdr_cmd tdr_cmd			__attribute__((aligned(32)));
-	struct mc_cmd mc_cmd			__attribute__((aligned(32)));
-	struct i596_rfd rfds[RX_RING_SIZE]	__attribute__((aligned(32)));
-	struct i596_rbd rbds[RX_RING_SIZE]	__attribute__((aligned(32)));
-	struct tx_cmd tx_cmds[TX_RING_SIZE]	__attribute__((aligned(32)));
-	struct i596_tbd tbds[TX_RING_SIZE]	__attribute__((aligned(32)));
-	u32    stat;
-	int last_restart;
-	struct i596_rfd *rfd_head;
-	struct i596_rbd *rbd_head;
-	struct i596_cmd *cmd_tail;
-	struct i596_cmd *cmd_head;
-	int cmd_backlog;
-	u32    last_cmd;
-	struct net_device_stats stats;
-	int next_tx_cmd;
-	int options;
-	spinlock_t lock;
-	dma_addr_t dma_addr;
-	struct device *dev;
-};
-
-static const char init_setup[] =
-{
-	0x8E,			/* length, prefetch on */
-	0xC8,			/* fifo to 8, monitor off */
-	0x80,			/* don't save bad frames */
-	0x2E,			/* No source address insertion, 8 byte preamble */
-	0x00,			/* priority and backoff defaults */
-	0x60,			/* interframe spacing */
-	0x00,			/* slot time LSB */
-	0xf2,			/* slot time and retries */
-	0x00,			/* promiscuous mode */
-	0x00,			/* collision detect */
-	0x40,			/* minimum frame length */
-	0xff,
-	0x00,
-	0x7f /*  *multi IA */ };
-
-static int i596_open(struct net_device *dev);
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id);
-static int i596_close(struct net_device *dev);
-static struct net_device_stats *i596_get_stats(struct net_device *dev);
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
-static void i596_tx_timeout (struct net_device *dev);
-static void print_eth(unsigned char *buf, char *str);
-static void set_multicast_list(struct net_device *dev);
-
-static int rx_ring_size = RX_RING_SIZE;
-static int ticks_limit = 100;
-static int max_cmd_backlog = TX_RING_SIZE-1;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev);
-#endif
-
-
-static inline void CA(struct net_device *dev)
+static inline void ca(struct net_device *dev)
 {
 	gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION);
 }
 
 
-static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
 {
-	struct i596_private *lp = dev->priv;
+	struct i596_private *lp = netdev_priv(dev);
 
 	u32 v = (u32) (c) | (u32) (x);
 	u16 a, b;
@@ -445,1078 +149,15 @@
 	gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS);
 }
 
-
-static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
-	CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
-	while (--delcnt && lp->iscp.stat) {
-		udelay(10);
-		CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
-	}
-	if (!delcnt) {
-		printk("%s: %s, iscp.stat %04x, didn't clear\n",
-		     dev->name, str, lp->iscp.stat);
-		return -1;
-	}
-	else
-		return 0;
-}
-
-
-static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
-	CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
-	while (--delcnt && lp->scb.command) {
-		udelay(10);
-		CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
-	}
-	if (!delcnt) {
-		printk("%s: %s, status %4.4x, cmd %4.4x.\n",
-		     dev->name, str, lp->scb.status, lp->scb.command);
-		return -1;
-	}
-	else
-		return 0;
-}
-
-
-static void i596_display_data(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	struct i596_cmd *cmd;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-
-	printk("lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
-	       &lp->scp, lp->scp.sysbus, lp->scp.iscp);
-	printk("iscp at %p, iscp.stat = %08x, .scb = %08x\n",
-	       &lp->iscp, lp->iscp.stat, lp->iscp.scb);
-	printk("scb at %p, scb.status = %04x, .command = %04x,"
-		" .cmd = %08x, .rfd = %08x\n",
-	       &lp->scb, lp->scb.status, lp->scb.command,
-		lp->scb.cmd, lp->scb.rfd);
-	printk("   errors: crc %x, align %x, resource %x,"
-               " over %x, rcvdt %x, short %x\n",
-		lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err,
-		lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err);
-	cmd = lp->cmd_head;
-	while (cmd != NULL) {
-		printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %08x\n",
-		  cmd, cmd->status, cmd->command, cmd->b_next);
-		cmd = cmd->v_next;
-	}
-	rfd = lp->rfd_head;
-	printk("rfd_head = %p\n", rfd);
-	do {
-		printk("   %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
-                        " count %04x\n",
-			rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd,
-			rfd->count);
-		rfd = rfd->v_next;
-	} while (rfd != lp->rfd_head);
-	rbd = lp->rbd_head;
-	printk("rbd_head = %p\n", rbd);
-	do {
-		printk("   %p .count %04x, b_next %08x, b_data %08x, size %04x\n",
-			rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
-		rbd = rbd->v_next;
-	} while (rbd != lp->rbd_head);
-	CHECK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static void i596_error(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
-	pcc2[0x28] = 1;
-	pcc2[0x2b] = 0x1d;
-	printk("%s: Error interrupt\n", dev->name);
-	i596_display_data(dev);
-}
-#endif
-
-#define virt_to_dma(lp,v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)(lp)))
-
-static inline void init_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	int i;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-
-	/* First build the Receive Buffer Descriptor List */
-
-	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
-		dma_addr_t dma_addr;
-		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4);
-
-		if (skb == NULL)
-			panic("%s: alloc_skb() failed", __FILE__);
-		skb_reserve(skb, 2);
-		dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ,
-					  DMA_FROM_DEVICE);
-		skb->dev = dev;
-		rbd->v_next = rbd+1;
-		rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1));
-		rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd));
-		rbd->skb = skb;
-		rbd->v_data = skb->data;
-		rbd->b_data = WSWAPchar(dma_addr);
-		rbd->size = PKT_BUF_SZ;
-	}
-	lp->rbd_head = lp->rbds;
-	rbd = lp->rbds + rx_ring_size - 1;
-	rbd->v_next = lp->rbds;
-	rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
-	/* Now build the Receive Frame Descriptor List */
-
-	for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
-		rfd->rbd = I596_NULL;
-		rfd->v_next = rfd+1;
-		rfd->v_prev = rfd-1;
-		rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1));
-		rfd->cmd = CMD_FLEX;
-	}
-	lp->rfd_head = lp->rfds;
-	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-	rfd = lp->rfds;
-	rfd->rbd = WSWAPrbd(virt_to_dma(lp,lp->rbd_head));
-	rfd->v_prev = lp->rfds + rx_ring_size - 1;
-	rfd = lp->rfds + rx_ring_size - 1;
-	rfd->v_next = lp->rfds;
-	rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-	rfd->cmd = CMD_EOL|CMD_FLEX;
-
-	CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-static inline void remove_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	struct i596_rbd *rbd;
-	int i;
-
-	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
-		if (rbd->skb == NULL)
-			break;
-		dma_unmap_single(lp->dev,
-				 (dma_addr_t)WSWAPchar(rbd->b_data),
-				 PKT_BUF_SZ, DMA_FROM_DEVICE);
-		dev_kfree_skb(rbd->skb);
-	}
-}
-
-
-static void rebuild_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	int i;
-
-	/* Ensure rx frame/buffer descriptors are tidy */
-
-	for (i = 0; i < rx_ring_size; i++) {
-		lp->rfds[i].rbd = I596_NULL;
-		lp->rfds[i].cmd = CMD_FLEX;
-	}
-	lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
-	lp->rfd_head = lp->rfds;
-	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-	lp->rbd_head = lp->rbds;
-	lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
-	CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-static int init_i596_mem(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	unsigned long flags;
-
-	disable_irq(dev->irq);	/* disable IRQs from LAN */
-	DEB(DEB_INIT,
-		printk("RESET 82596 port: %lx (with IRQ %d disabled)\n",
-		       (dev->base_addr + PA_I82596_RESET),
-		       dev->irq));
-
-	gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
-	udelay(100);			/* Wait 100us - seems to help */
-
-	/* change the scp address */
-
-	lp->last_cmd = jiffies;
-
-
-	lp->scp.sysbus = 0x0000006c;
-	lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp)));
-	lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb)));
-	lp->iscp.stat = ISCP_BUSY;
-	lp->cmd_backlog = 0;
-
-	lp->cmd_head = NULL;
-        lp->scb.cmd = I596_NULL;
-
-	DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name));
-
-	CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp));
-	CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp));
-
-	MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp));
-
-	CA(dev);
-
-	if (wait_istat(dev, lp, 1000, "initialization timed out"))
-		goto failed;
-	DEB(DEB_INIT, printk("%s: i82596 initialization successful\n", dev->name));
-
-	/* Ensure rx frame/buffer descriptors are tidy */
-	rebuild_rx_bufs(dev);
-
-	lp->scb.command = 0;
-	CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
-	enable_irq(dev->irq);	/* enable IRQs from LAN */
-
-	DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name));
-	memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup));
-	lp->cf_cmd.cmd.command = CmdConfigure;
-	CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd));
-	i596_add_cmd(dev, &lp->cf_cmd.cmd);
-
-	DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name));
-	memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
-	lp->sa_cmd.cmd.command = CmdSASetup;
-	CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd));
-	i596_add_cmd(dev, &lp->sa_cmd.cmd);
-
-	DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name));
-	lp->tdr_cmd.cmd.command = CmdTDR;
-	CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd));
-	i596_add_cmd(dev, &lp->tdr_cmd.cmd);
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	if (wait_cmd(dev, lp, 1000, "timed out waiting to issue RX_START")) {
-		spin_unlock_irqrestore (&lp->lock, flags);
-		goto failed;
-	}
-	DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name));
-	lp->scb.command = RX_START;
-	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-	CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
-	CA(dev);
-
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	if (wait_cmd(dev, lp, 1000, "RX_START not processed"))
-		goto failed;
-	DEB(DEB_INIT, printk("%s: Receive unit started OK\n", dev->name));
-
-	return 0;
-
-failed:
-	printk("%s: Failed to initialise 82596\n", dev->name);
-	MPU_PORT(dev, PORT_RESET, 0);
-	return -1;
-}
-
-
-static inline int i596_rx(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-	int frames = 0;
-
-	DEB(DEB_RXFRAME, printk("i596_rx(), rfd_head %p, rbd_head %p\n",
-			lp->rfd_head, lp->rbd_head));
-
-
-	rfd = lp->rfd_head;		/* Ref next frame to check */
-
-	CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
-	while ((rfd->stat) & STAT_C) {	/* Loop while complete frames */
-		if (rfd->rbd == I596_NULL)
-			rbd = NULL;
-		else if (rfd->rbd == lp->rbd_head->b_addr) {
-			rbd = lp->rbd_head;
-			CHECK_INV(lp, rbd, sizeof(struct i596_rbd));
-		}
-		else {
-			printk("%s: rbd chain broken!\n", dev->name);
-			/* XXX Now what? */
-			rbd = NULL;
-		}
-		DEB(DEB_RXFRAME, printk("  rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
-			rfd, rfd->rbd, rfd->stat));
-
-		if (rbd != NULL && ((rfd->stat) & STAT_OK)) {
-			/* a good frame */
-			int pkt_len = rbd->count & 0x3fff;
-			struct sk_buff *skb = rbd->skb;
-			int rx_in_place = 0;
-
-			DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));
-			frames++;
-
-			/* Check if the packet is long enough to just accept
-			 * without copying to a properly sized skbuff.
-			 */
-
-			if (pkt_len > rx_copybreak) {
-				struct sk_buff *newskb;
-				dma_addr_t dma_addr;
-
-				dma_unmap_single(lp->dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
-				/* Get fresh skbuff to replace filled one. */
-				newskb = dev_alloc_skb(PKT_BUF_SZ + 4);
-				if (newskb == NULL) {
-					skb = NULL;	/* drop pkt */
-					goto memory_squeeze;
-				}
-				skb_reserve(newskb, 2);
-
-				/* Pass up the skb already on the Rx ring. */
-				skb_put(skb, pkt_len);
-				rx_in_place = 1;
-				rbd->skb = newskb;
-				newskb->dev = dev;
-				dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE);
-				rbd->v_data = newskb->data;
-				rbd->b_data = WSWAPchar(dma_addr);
-				CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
-			}
-			else
-				skb = dev_alloc_skb(pkt_len + 2);
-memory_squeeze:
-			if (skb == NULL) {
-				/* XXX tulip.c can defer packets here!! */
-				printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
-				lp->stats.rx_dropped++;
-			}
-			else {
-				if (!rx_in_place) {
-					/* 16 byte align the data fields */
-					dma_sync_single_for_cpu(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
-					skb_reserve(skb, 2);
-					memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);
-					dma_sync_single_for_device(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
-				}
-				skb->len = pkt_len;
-				skb->protocol=eth_type_trans(skb,dev);
-				netif_rx(skb);
-				dev->last_rx = jiffies;
-				lp->stats.rx_packets++;
-				lp->stats.rx_bytes+=pkt_len;
-			}
-		}
-		else {
-			DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n",
-					dev->name, rfd->stat));
-			lp->stats.rx_errors++;
-			if ((rfd->stat) & 0x0001)
-				lp->stats.collisions++;
-			if ((rfd->stat) & 0x0080)
-				lp->stats.rx_length_errors++;
-			if ((rfd->stat) & 0x0100)
-				lp->stats.rx_over_errors++;
-			if ((rfd->stat) & 0x0200)
-				lp->stats.rx_fifo_errors++;
-			if ((rfd->stat) & 0x0400)
-				lp->stats.rx_frame_errors++;
-			if ((rfd->stat) & 0x0800)
-				lp->stats.rx_crc_errors++;
-			if ((rfd->stat) & 0x1000)
-				lp->stats.rx_length_errors++;
-		}
-
-		/* Clear the buffer descriptor count and EOF + F flags */
-
-		if (rbd != NULL && (rbd->count & 0x4000)) {
-			rbd->count = 0;
-			lp->rbd_head = rbd->v_next;
-			CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
-		}
-
-		/* Tidy the frame descriptor, marking it as end of list */
-
-		rfd->rbd = I596_NULL;
-		rfd->stat = 0;
-		rfd->cmd = CMD_EOL|CMD_FLEX;
-		rfd->count = 0;
-
-		/* Remove end-of-list from old end descriptor */
-
-		rfd->v_prev->cmd = CMD_FLEX;
-
-		/* Update record of next frame descriptor to process */
-
-		lp->scb.rfd = rfd->b_next;
-		lp->rfd_head = rfd->v_next;
-		CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd));
-		CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd));
-		rfd = lp->rfd_head;
-		CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
-	}
-
-	DEB(DEB_RXFRAME, printk("frames %d\n", frames));
-
-	return 0;
-}
-
-
-static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
-{
-	struct i596_cmd *ptr;
-
-	while (lp->cmd_head != NULL) {
-		ptr = lp->cmd_head;
-		lp->cmd_head = ptr->v_next;
-		lp->cmd_backlog--;
-
-		switch ((ptr->command) & 0x7) {
-		case CmdTx:
-			{
-				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
-				struct sk_buff *skb = tx_cmd->skb;
-				dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
-
-				dev_kfree_skb(skb);
-
-				lp->stats.tx_errors++;
-				lp->stats.tx_aborted_errors++;
-
-				ptr->v_next = NULL;
-				ptr->b_next = I596_NULL;
-				tx_cmd->cmd.command = 0;  /* Mark as free */
-				break;
-			}
-		default:
-			ptr->v_next = NULL;
-			ptr->b_next = I596_NULL;
-		}
-		CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd));
-	}
-
-	wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out");
-	lp->scb.cmd = I596_NULL;
-	CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-}
-
-
-static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
-{
-	unsigned long flags;
-
-	DEB(DEB_RESET, printk("i596_reset\n"));
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	wait_cmd(dev, lp, 100, "i596_reset timed out");
-
-	netif_stop_queue(dev);
-
-	/* FIXME: this command might cause an lpmc */
-	lp->scb.command = CUC_ABORT | RX_ABORT;
-	CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-	CA(dev);
-
-	/* wait for shutdown */
-	wait_cmd(dev, lp, 1000, "i596_reset 2 timed out");
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	i596_cleanup_cmd(dev,lp);
-	i596_rx(dev);
-
-	netif_start_queue(dev);
-	init_i596_mem(dev);
-}
-
-
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
-{
-	struct i596_private *lp = dev->priv;
-	unsigned long flags;
-
-	DEB(DEB_ADDCMD, printk("i596_add_cmd cmd_head %p\n", lp->cmd_head));
-
-	cmd->status = 0;
-	cmd->command |= (CMD_EOL | CMD_INTR);
-	cmd->v_next = NULL;
-	cmd->b_next = I596_NULL;
-	CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd));
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	if (lp->cmd_head != NULL) {
-		lp->cmd_tail->v_next = cmd;
-		lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status));
-		CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd));
-	} else {
-		lp->cmd_head = cmd;
-		wait_cmd(dev, lp, 100, "i596_add_cmd timed out");
-		lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status));
-		lp->scb.command = CUC_START;
-		CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-		CA(dev);
-	}
-	lp->cmd_tail = cmd;
-	lp->cmd_backlog++;
-
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	if (lp->cmd_backlog > max_cmd_backlog) {
-		unsigned long tickssofar = jiffies - lp->last_cmd;
-
-		if (tickssofar < ticks_limit)
-			return;
-
-		printk("%s: command unit timed out, status resetting.\n", dev->name);
-#if 1
-		i596_reset(dev, lp);
-#endif
-	}
-}
-
-#if 0
-/* this function makes a perfectly adequate probe...  but we have a
-   device list */
-static int i596_test(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	volatile int *tint;
-	u32 data;
-
-	tint = (volatile int *)(&(lp->scp));
-	data = virt_to_dma(lp,tint);
-
-	tint[1] = -1;
-	CHECK_WBACK(lp, tint, PAGE_SIZE);
-
-	MPU_PORT(dev, 1, data);
-
-	for(data = 1000000; data; data--) {
-		CHECK_INV(lp, tint, PAGE_SIZE);
-		if(tint[1] != -1)
-			break;
-
-	}
-
-	printk("i596_test result %d\n", tint[1]);
-
-}
-#endif
-
-
-static int i596_open(struct net_device *dev)
-{
-	DEB(DEB_OPEN, printk("%s: i596_open() irq %d.\n", dev->name, dev->irq));
-
-	if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
-		printk("%s: IRQ %d not free\n", dev->name, dev->irq);
-		goto out;
-	}
-
-	init_rx_bufs(dev);
-
-	if (init_i596_mem(dev)) {
-		printk("%s: Failed to init memory\n", dev->name);
-		goto out_remove_rx_bufs;
-	}
-
-	netif_start_queue(dev);
-
-	return 0;
-
-out_remove_rx_bufs:
-	remove_rx_bufs(dev);
-	free_irq(dev->irq, dev);
-out:
-	return -EAGAIN;
-}
-
-static void i596_tx_timeout (struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-
-	/* Transmitter timeout, serious problems. */
-	DEB(DEB_ERRORS, printk("%s: transmit timed out, status resetting.\n",
-			dev->name));
-
-	lp->stats.tx_errors++;
-
-	/* Try to restart the adaptor */
-	if (lp->last_restart == lp->stats.tx_packets) {
-		DEB(DEB_ERRORS, printk("Resetting board.\n"));
-		/* Shutdown and restart */
-		i596_reset (dev, lp);
-	} else {
-		/* Issue a channel attention signal */
-		DEB(DEB_ERRORS, printk("Kicking board.\n"));
-		lp->scb.command = CUC_START | RX_START;
-		CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
-		CA (dev);
-		lp->last_restart = lp->stats.tx_packets;
-	}
-
-	dev->trans_start = jiffies;
-	netif_wake_queue (dev);
-}
-
-
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	struct tx_cmd *tx_cmd;
-	struct i596_tbd *tbd;
-	short length = skb->len;
-	dev->trans_start = jiffies;
-
-	DEB(DEB_STARTTX, printk("%s: i596_start_xmit(%x,%p) called\n", dev->name,
-				skb->len, skb->data));
-
-	if (length < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			return 0;
-		length = ETH_ZLEN;
-	}
-
-	netif_stop_queue(dev);
-
-	tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
-	tbd = lp->tbds + lp->next_tx_cmd;
-
-	if (tx_cmd->cmd.command) {
-		DEB(DEB_ERRORS, printk("%s: xmit ring full, dropping packet.\n",
-				dev->name));
-		lp->stats.tx_dropped++;
-
-		dev_kfree_skb(skb);
-	} else {
-		if (++lp->next_tx_cmd == TX_RING_SIZE)
-			lp->next_tx_cmd = 0;
-		tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd));
-		tbd->next = I596_NULL;
-
-		tx_cmd->cmd.command = CMD_FLEX | CmdTx;
-		tx_cmd->skb = skb;
-
-		tx_cmd->pad = 0;
-		tx_cmd->size = 0;
-		tbd->pad = 0;
-		tbd->size = EOF | length;
-
-		tx_cmd->dma_addr = dma_map_single(lp->dev, skb->data, skb->len,
-				DMA_TO_DEVICE);
-		tbd->data = WSWAPchar(tx_cmd->dma_addr);
-
-		DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
-		CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd));
-		CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd));
-		i596_add_cmd(dev, &tx_cmd->cmd);
-
-		lp->stats.tx_packets++;
-		lp->stats.tx_bytes += length;
-	}
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-static void print_eth(unsigned char *add, char *str)
-{
-	int i;
-
-	printk("i596 0x%p, ", add);
-	for (i = 0; i < 6; i++)
-		printk(" %02X", add[i + 6]);
-	printk(" -->");
-	for (i = 0; i < 6; i++)
-		printk(" %02X", add[i]);
-	printk(" %02X%02X, %s\n", add[12], add[13], str);
-}
-
-
 #define LAN_PROM_ADDR	0xF0810000
 
-static int __devinit i82596_probe(struct net_device *dev,
-				  struct device *gen_dev)
-{
-	int i;
-	struct i596_private *lp;
-	char eth_addr[6];
-	dma_addr_t dma_addr;
-
-	/* This lot is ensure things have been cache line aligned. */
-	BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
-	BUILD_BUG_ON(sizeof(struct i596_rbd) &  31);
-	BUILD_BUG_ON(sizeof(struct tx_cmd)   &  31);
-	BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
-#ifndef __LP64__
-	BUILD_BUG_ON(sizeof(struct i596_private) > 4096);
-#endif
-
-	if (!dev->base_addr || !dev->irq)
-		return -ENODEV;
-
-	if (pdc_lan_station_id(eth_addr, dev->base_addr)) {
-		for (i=0; i < 6; i++) {
-			eth_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
-		}
-		printk(KERN_INFO "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
-	}
-
-	dev->mem_start = (unsigned long) dma_alloc_noncoherent(gen_dev,
-		sizeof(struct i596_private), &dma_addr, GFP_KERNEL);
-	if (!dev->mem_start) {
-		printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = eth_addr[i];
-
-	/* The 82596-specific entries in the device structure. */
-	dev->open = i596_open;
-	dev->stop = i596_close;
-	dev->hard_start_xmit = i596_start_xmit;
-	dev->get_stats = i596_get_stats;
-	dev->set_multicast_list = set_multicast_list;
-	dev->tx_timeout = i596_tx_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = i596_poll_controller;
-#endif
-
-	dev->priv = (void *)(dev->mem_start);
-
-	lp = dev->priv;
-	memset(lp, 0, sizeof(struct i596_private));
-
-	lp->scb.command = 0;
-	lp->scb.cmd = I596_NULL;
-	lp->scb.rfd = I596_NULL;
-	spin_lock_init(&lp->lock);
-	lp->dma_addr = dma_addr;
-	lp->dev = gen_dev;
-
-	CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private));
-
-	i = register_netdev(dev);
-	if (i) {
-		lp = dev->priv;
-		dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
-				    (void *)dev->mem_start, lp->dma_addr);
-		return i;
-	};
-
-	DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr));
-	for (i = 0; i < 6; i++)
-		DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
-	DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
-	DEB(DEB_INIT, printk(KERN_INFO "%s: lp at 0x%p (%d bytes), lp->scb at 0x%p\n",
-		dev->name, lp, (int)sizeof(struct i596_private), &lp->scb));
-
-	return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	i596_interrupt(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-static irqreturn_t i596_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct i596_private *lp;
-	unsigned short status, ack_cmd = 0;
-
-	if (dev == NULL) {
-		printk("%s: irq %d for unknown device.\n", __FUNCTION__, irq);
-		return IRQ_NONE;
-	}
-
-	lp = dev->priv;
-
-	spin_lock (&lp->lock);
-
-	wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
-	status = lp->scb.status;
-
-	DEB(DEB_INTS, printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n",
-			dev->name, irq, status));
-
-	ack_cmd = status & 0xf000;
-
-	if (!ack_cmd) {
-		DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name));
-		spin_unlock (&lp->lock);
-		return IRQ_NONE;
-	}
-
-	if ((status & 0x8000) || (status & 0x2000)) {
-		struct i596_cmd *ptr;
-
-		if ((status & 0x8000))
-			DEB(DEB_INTS, printk("%s: i596 interrupt completed command.\n", dev->name));
-		if ((status & 0x2000))
-			DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
-
-		while (lp->cmd_head != NULL) {
-			CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd));
-			if (!(lp->cmd_head->status & STAT_C))
-				break;
-
-			ptr = lp->cmd_head;
-
-			DEB(DEB_STATUS, printk("cmd_head->status = %04x, ->command = %04x\n",
-				       lp->cmd_head->status, lp->cmd_head->command));
-			lp->cmd_head = ptr->v_next;
-			lp->cmd_backlog--;
-
-			switch ((ptr->command) & 0x7) {
-			case CmdTx:
-			    {
-				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
-				struct sk_buff *skb = tx_cmd->skb;
-
-				if ((ptr->status) & STAT_OK) {
-					DEB(DEB_TXADDR, print_eth(skb->data, "tx-done"));
-				} else {
-					lp->stats.tx_errors++;
-					if ((ptr->status) & 0x0020)
-						lp->stats.collisions++;
-					if (!((ptr->status) & 0x0040))
-						lp->stats.tx_heartbeat_errors++;
-					if ((ptr->status) & 0x0400)
-						lp->stats.tx_carrier_errors++;
-					if ((ptr->status) & 0x0800)
-						lp->stats.collisions++;
-					if ((ptr->status) & 0x1000)
-						lp->stats.tx_aborted_errors++;
-				}
-				dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
-				dev_kfree_skb_irq(skb);
-
-				tx_cmd->cmd.command = 0; /* Mark free */
-				break;
-			    }
-			case CmdTDR:
-			    {
-				unsigned short status = ((struct tdr_cmd *)ptr)->status;
-
-				if (status & 0x8000) {
-					DEB(DEB_ANY, printk("%s: link ok.\n", dev->name));
-				} else {
-					if (status & 0x4000)
-						printk("%s: Transceiver problem.\n", dev->name);
-					if (status & 0x2000)
-						printk("%s: Termination problem.\n", dev->name);
-					if (status & 0x1000)
-						printk("%s: Short circuit.\n", dev->name);
-
-					DEB(DEB_TDR, printk("%s: Time %d.\n", dev->name, status & 0x07ff));
-				}
-				break;
-			    }
-			case CmdConfigure:
-				/* Zap command so set_multicast_list() knows it is free */
-				ptr->command = 0;
-				break;
-			}
-			ptr->v_next = NULL;
-		        ptr->b_next = I596_NULL;
-			CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd));
-			lp->last_cmd = jiffies;
-		}
-
-		/* This mess is arranging that only the last of any outstanding
-		 * commands has the interrupt bit set.  Should probably really
-		 * only add to the cmd queue when the CU is stopped.
-		 */
-		ptr = lp->cmd_head;
-		while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
-			struct i596_cmd *prev = ptr;
-
-			ptr->command &= 0x1fff;
-			ptr = ptr->v_next;
-			CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd));
-		}
-
-		if ((lp->cmd_head != NULL))
-			ack_cmd |= CUC_START;
-		lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status));
-		CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb));
-	}
-	if ((status & 0x1000) || (status & 0x4000)) {
-		if ((status & 0x4000))
-			DEB(DEB_INTS, printk("%s: i596 interrupt received a frame.\n", dev->name));
-		i596_rx(dev);
-		/* Only RX_START if stopped - RGH 07-07-96 */
-		if (status & 0x1000) {
-			if (netif_running(dev)) {
-				DEB(DEB_ERRORS, printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status));
-				ack_cmd |= RX_START;
-				lp->stats.rx_errors++;
-				lp->stats.rx_fifo_errors++;
-				rebuild_rx_bufs(dev);
-			}
-		}
-	}
-	wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
-	lp->scb.command = ack_cmd;
-	CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
-	/* DANGER: I suspect that some kind of interrupt
-	 acknowledgement aside from acking the 82596 might be needed
-	 here...  but it's running acceptably without */
-
-	CA(dev);
-
-	wait_cmd(dev, lp, 100, "i596 interrupt, exit timeout");
-	DEB(DEB_INTS, printk("%s: exiting interrupt.\n", dev->name));
-
-	spin_unlock (&lp->lock);
-	return IRQ_HANDLED;
-}
-
-static int i596_close(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	unsigned long flags;
-
-	netif_stop_queue(dev);
-
-	DEB(DEB_INIT, printk("%s: Shutting down ethercard, status was %4.4x.\n",
-		       dev->name, lp->scb.status));
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	wait_cmd(dev, lp, 100, "close1 timed out");
-	lp->scb.command = CUC_ABORT | RX_ABORT;
-	CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
-	CA(dev);
-
-	wait_cmd(dev, lp, 100, "close2 timed out");
-	spin_unlock_irqrestore(&lp->lock, flags);
-	DEB(DEB_STRUCT,i596_display_data(dev));
-	i596_cleanup_cmd(dev,lp);
-
-	disable_irq(dev->irq);
-
-	free_irq(dev->irq, dev);
-	remove_rx_bufs(dev);
-
-	return 0;
-}
-
-static struct net_device_stats *
- i596_get_stats(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-
-	return &lp->stats;
-}
-
-/*
- *    Set or clear the multicast filter for this adaptor.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	int config = 0, cnt;
-
-	DEB(DEB_MULTI, printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
-		dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF",
-		dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
-
-	if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) {
-		lp->cf_cmd.i596_config[8] |= 0x01;
-		config = 1;
-	}
-	if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) {
-		lp->cf_cmd.i596_config[8] &= ~0x01;
-		config = 1;
-	}
-	if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) {
-		lp->cf_cmd.i596_config[11] &= ~0x20;
-		config = 1;
-	}
-	if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) {
-		lp->cf_cmd.i596_config[11] |= 0x20;
-		config = 1;
-	}
-	if (config) {
-		if (lp->cf_cmd.cmd.command)
-			printk("%s: config change request already queued\n",
-			       dev->name);
-		else {
-			lp->cf_cmd.cmd.command = CmdConfigure;
-			CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd));
-			i596_add_cmd(dev, &lp->cf_cmd.cmd);
-		}
-	}
-
-	cnt = dev->mc_count;
-	if (cnt > MAX_MC_CNT)
-	{
-		cnt = MAX_MC_CNT;
-		printk("%s: Only %d multicast addresses supported",
-			dev->name, cnt);
-	}
-
-	if (dev->mc_count > 0) {
-		struct dev_mc_list *dmi;
-		unsigned char *cp;
-		struct mc_cmd *cmd;
-
-		cmd = &lp->mc_cmd;
-		cmd->cmd.command = CmdMulticastList;
-		cmd->mc_cnt = dev->mc_count * 6;
-		cp = cmd->mc_addrs;
-		for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
-			memcpy(cp, dmi->dmi_addr, 6);
-			if (i596_debug > 1)
-				DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
-						dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5]));
-		}
-		CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd));
-		i596_add_cmd(dev, &cmd->cmd);
-	}
-}
-
-static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "lasi_82596 debug mask");
-
-static int num_drivers;
-static struct net_device *netdevs[MAX_DRIVERS];
-
 static int __devinit
 lan_init_chip(struct parisc_device *dev)
 {
 	struct	net_device *netdevice;
+	struct i596_private *lp;
 	int	retval;
-
-	if (num_drivers >= MAX_DRIVERS) {
-		/* max count of possible i82596 drivers reached */
-		return -ENOMEM;
-	}
-
-	if (num_drivers == 0)
-		printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
+	int i;
 
 	if (!dev->irq) {
 		printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
@@ -1527,28 +168,45 @@
 	printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
 			dev->irq);
 
-	netdevice = alloc_etherdev(0);
+	netdevice = alloc_etherdev(sizeof(struct i596_private));
 	if (!netdevice)
 		return -ENOMEM;
+	SET_NETDEV_DEV(netdevice, &dev->dev);
+	parisc_set_drvdata (dev, netdevice);
 
 	netdevice->base_addr = dev->hpa.start;
 	netdevice->irq = dev->irq;
 
-	retval = i82596_probe(netdevice, &dev->dev);
+	if (pdc_lan_station_id(netdevice->dev_addr, netdevice->base_addr)) {
+		for (i = 0; i < 6; i++) {
+			netdevice->dev_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
+		}
+		printk(KERN_INFO
+		       "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
+	}
+
+	lp = netdev_priv(netdevice);
+	lp->options = dev->id.sversion == 0x72 ? OPT_SWAP_PORT : 0;
+
+	retval = i82596_probe(netdevice);
 	if (retval) {
 		free_netdev(netdevice);
 		return -ENODEV;
 	}
-
-	if (dev->id.sversion == 0x72) {
-		((struct i596_private *)netdevice->priv)->options = OPT_SWAP_PORT;
-	}
-
-	netdevs[num_drivers++] = netdevice;
-
 	return retval;
 }
 
+static int __devexit lan_remove_chip (struct parisc_device *pdev)
+{
+	struct net_device *dev = parisc_get_drvdata(pdev);
+	struct i596_private *lp = netdev_priv(dev);
+
+	unregister_netdev (dev);
+	DMA_FREE(&pdev->dev, sizeof(struct i596_private),
+		 (void *)lp->dma, lp->dma_addr);
+	free_netdev (dev);
+	return 0;
+}
 
 static struct parisc_device_id lan_tbl[] = {
 	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a },
@@ -1562,12 +220,12 @@
 	.name		= "lasi_82596",
 	.id_table	= lan_tbl,
 	.probe		= lan_init_chip,
+	.remove         = __devexit_p(lan_remove_chip),
 };
 
 static int __devinit lasi_82596_init(void)
 {
-	if (debug >= 0)
-		i596_debug = debug;
+	printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
 	return register_parisc_driver(&lan_driver);
 }
 
@@ -1575,25 +233,6 @@
 
 static void __exit lasi_82596_exit(void)
 {
-	int i;
-
-	for (i=0; i<MAX_DRIVERS; i++) {
-		struct i596_private *lp;
-		struct net_device *netdevice;
-
-		netdevice = netdevs[i];
-		if (!netdevice)
-			continue;
-
-		unregister_netdev(netdevice);
-
-		lp = netdevice->priv;
-		dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
-				       (void *)netdevice->mem_start, lp->dma_addr);
-		free_netdev(netdevice);
-	}
-	num_drivers = 0;
-
 	unregister_parisc_driver(&lan_driver);
 }
 
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
new file mode 100644
index 0000000..5884f5b
--- /dev/null
+++ b/drivers/net/lib82596.c
@@ -0,0 +1,1434 @@
+/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
+   munged into HPPA boxen .
+
+   This driver is based upon 82596.c, original credits are below...
+   but there were too many hoops which HP wants jumped through to
+   keep this code in there in a sane manner.
+
+   3 primary sources of the mess --
+   1) hppa needs *lots* of cacheline flushing to keep this kind of
+   MMIO running.
+
+   2) The 82596 needs to see all of its pointers as their physical
+   address.  Thus virt_to_bus/bus_to_virt are *everywhere*.
+
+   3) The implementation HP is using seems to be significantly pickier
+   about when and how the command and RX units are started.  some
+   command ordering was changed.
+
+   Examination of the mach driver leads one to believe that there
+   might be a saner way to pull this off...  anyone who feels like a
+   full rewrite can be my guest.
+
+   Split 02/13/2000 Sam Creasey (sammy@oh.verio.com)
+
+   02/01/2000  Initial modifications for parisc by Helge Deller (deller@gmx.de)
+   03/02/2000  changes for better/correct(?) cache-flushing (deller)
+*/
+
+/* 82596.c: A generic 82596 ethernet driver for linux. */
+/*
+   Based on Apricot.c
+   Written 1994 by Mark Evans.
+   This driver is for the Apricot 82596 bus-master interface
+
+   Modularised 12/94 Mark Evans
+
+
+   Modified to support the 82596 ethernet chips on 680x0 VME boards.
+   by Richard Hirst <richard@sleepie.demon.co.uk>
+   Renamed to be 82596.c
+
+   980825:  Changed to receive directly in to sk_buffs which are
+   allocated at open() time.  Eliminates copy on incoming frames
+   (small ones are still copied).  Shared data now held in a
+   non-cached page, so we can run on 68060 in copyback mode.
+
+   TBD:
+   * look at deferring rx frames rather than discarding (as per tulip)
+   * handle tx ring full as per tulip
+   * performace test to tune rx_copybreak
+
+   Most of my modifications relate to the braindead big-endian
+   implementation by Intel.  When the i596 is operating in
+   'big-endian' mode, it thinks a 32 bit value of 0x12345678
+   should be stored as 0x56781234.  This is a real pain, when
+   you have linked lists which are shared by the 680x0 and the
+   i596.
+
+   Driver skeleton
+   Written 1993 by Donald Becker.
+   Copyright 1993 United States Government as represented by the Director,
+   National Security Agency. This software may only be used and distributed
+   according to the terms of the GNU General Public License as modified by SRC,
+   incorporated herein by reference.
+
+   The author may be reached as becker@scyld.com, or C/O
+   Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+/* DEBUG flags
+ */
+
+#define DEB_INIT	0x0001
+#define DEB_PROBE	0x0002
+#define DEB_SERIOUS	0x0004
+#define DEB_ERRORS	0x0008
+#define DEB_MULTI	0x0010
+#define DEB_TDR		0x0020
+#define DEB_OPEN	0x0040
+#define DEB_RESET	0x0080
+#define DEB_ADDCMD	0x0100
+#define DEB_STATUS	0x0200
+#define DEB_STARTTX	0x0400
+#define DEB_RXADDR	0x0800
+#define DEB_TXADDR	0x1000
+#define DEB_RXFRAME	0x2000
+#define DEB_INTS	0x4000
+#define DEB_STRUCT	0x8000
+#define DEB_ANY		0xffff
+
+
+#define DEB(x, y)	if (i596_debug & (x)) { y; }
+
+
+/*
+ * The MPU_PORT command allows direct access to the 82596. With PORT access
+ * the following commands are available (p5-18). The 32-bit port command
+ * must be word-swapped with the most significant word written first.
+ * This only applies to VME boards.
+ */
+#define PORT_RESET		0x00	/* reset 82596 */
+#define PORT_SELFTEST		0x01	/* selftest */
+#define PORT_ALTSCP		0x02	/* alternate SCB address */
+#define PORT_ALTDUMP		0x03	/* Alternate DUMP address */
+
+static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+
+/* Copy frames shorter than rx_copybreak, otherwise pass on up in
+ * a full sized sk_buff.  Value of 100 stolen from tulip.c (!alpha).
+ */
+static int rx_copybreak = 100;
+
+#define PKT_BUF_SZ	1536
+#define MAX_MC_CNT	64
+
+#define ISCP_BUSY	0x0001
+
+#define I596_NULL ((u32)0xffffffff)
+
+#define CMD_EOL		0x8000	/* The last command of the list, stop. */
+#define CMD_SUSP	0x4000	/* Suspend after doing cmd. */
+#define CMD_INTR	0x2000	/* Interrupt after doing cmd. */
+
+#define CMD_FLEX	0x0008	/* Enable flexible memory model */
+
+enum commands {
+	CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
+	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
+};
+
+#define STAT_C		0x8000	/* Set to 0 after execution */
+#define STAT_B		0x4000	/* Command being executed */
+#define STAT_OK		0x2000	/* Command executed ok */
+#define STAT_A		0x1000	/* Command aborted */
+
+#define	 CUC_START	0x0100
+#define	 CUC_RESUME	0x0200
+#define	 CUC_SUSPEND    0x0300
+#define	 CUC_ABORT	0x0400
+#define	 RX_START	0x0010
+#define	 RX_RESUME	0x0020
+#define	 RX_SUSPEND	0x0030
+#define	 RX_ABORT	0x0040
+
+#define TX_TIMEOUT	5
+
+
+struct i596_reg {
+	unsigned short porthi;
+	unsigned short portlo;
+	u32            ca;
+};
+
+#define EOF		0x8000
+#define SIZE_MASK	0x3fff
+
+struct i596_tbd {
+	unsigned short size;
+	unsigned short pad;
+	dma_addr_t     next;
+	dma_addr_t     data;
+	u32 cache_pad[5];		/* Total 32 bytes... */
+};
+
+/* The command structure has two 'next' pointers; v_next is the address of
+ * the next command as seen by the CPU, b_next is the address of the next
+ * command as seen by the 82596.  The b_next pointer, as used by the 82596
+ * always references the status field of the next command, rather than the
+ * v_next field, because the 82596 is unaware of v_next.  It may seem more
+ * logical to put v_next at the end of the structure, but we cannot do that
+ * because the 82596 expects other fields to be there, depending on command
+ * type.
+ */
+
+struct i596_cmd {
+	struct i596_cmd *v_next;	/* Address from CPUs viewpoint */
+	unsigned short status;
+	unsigned short command;
+	dma_addr_t     b_next;	/* Address from i596 viewpoint */
+};
+
+struct tx_cmd {
+	struct i596_cmd cmd;
+	dma_addr_t     tbd;
+	unsigned short size;
+	unsigned short pad;
+	struct sk_buff *skb;		/* So we can free it after tx */
+	dma_addr_t dma_addr;
+#ifdef __LP64__
+	u32 cache_pad[6];		/* Total 64 bytes... */
+#else
+	u32 cache_pad[1];		/* Total 32 bytes... */
+#endif
+};
+
+struct tdr_cmd {
+	struct i596_cmd cmd;
+	unsigned short status;
+	unsigned short pad;
+};
+
+struct mc_cmd {
+	struct i596_cmd cmd;
+	short mc_cnt;
+	char mc_addrs[MAX_MC_CNT*6];
+};
+
+struct sa_cmd {
+	struct i596_cmd cmd;
+	char eth_addr[8];
+};
+
+struct cf_cmd {
+	struct i596_cmd cmd;
+	char i596_config[16];
+};
+
+struct i596_rfd {
+	unsigned short stat;
+	unsigned short cmd;
+	dma_addr_t     b_next;	/* Address from i596 viewpoint */
+	dma_addr_t     rbd;
+	unsigned short count;
+	unsigned short size;
+	struct i596_rfd *v_next;	/* Address from CPUs viewpoint */
+	struct i596_rfd *v_prev;
+#ifndef __LP64__
+	u32 cache_pad[2];		/* Total 32 bytes... */
+#endif
+};
+
+struct i596_rbd {
+    /* hardware data */
+    unsigned short count;
+    unsigned short zero1;
+    dma_addr_t     b_next;
+    dma_addr_t     b_data;		/* Address from i596 viewpoint */
+    unsigned short size;
+    unsigned short zero2;
+    /* driver data */
+    struct sk_buff *skb;
+    struct i596_rbd *v_next;
+    dma_addr_t     b_addr;		/* This rbd addr from i596 view */
+    unsigned char *v_data;		/* Address from CPUs viewpoint */
+					/* Total 32 bytes... */
+#ifdef __LP64__
+    u32 cache_pad[4];
+#endif
+};
+
+/* These values as chosen so struct i596_dma fits in one page... */
+
+#define TX_RING_SIZE 32
+#define RX_RING_SIZE 16
+
+struct i596_scb {
+	unsigned short status;
+	unsigned short command;
+	dma_addr_t    cmd;
+	dma_addr_t    rfd;
+	u32           crc_err;
+	u32           align_err;
+	u32           resource_err;
+	u32           over_err;
+	u32           rcvdt_err;
+	u32           short_err;
+	unsigned short t_on;
+	unsigned short t_off;
+};
+
+struct i596_iscp {
+	u32           stat;
+	dma_addr_t    scb;
+};
+
+struct i596_scp {
+	u32           sysbus;
+	u32           pad;
+	dma_addr_t    iscp;
+};
+
+struct i596_dma {
+	struct i596_scp scp		        __attribute__((aligned(32)));
+	volatile struct i596_iscp iscp		__attribute__((aligned(32)));
+	volatile struct i596_scb scb		__attribute__((aligned(32)));
+	struct sa_cmd sa_cmd			__attribute__((aligned(32)));
+	struct cf_cmd cf_cmd			__attribute__((aligned(32)));
+	struct tdr_cmd tdr_cmd			__attribute__((aligned(32)));
+	struct mc_cmd mc_cmd			__attribute__((aligned(32)));
+	struct i596_rfd rfds[RX_RING_SIZE]	__attribute__((aligned(32)));
+	struct i596_rbd rbds[RX_RING_SIZE]	__attribute__((aligned(32)));
+	struct tx_cmd tx_cmds[TX_RING_SIZE]	__attribute__((aligned(32)));
+	struct i596_tbd tbds[TX_RING_SIZE]	__attribute__((aligned(32)));
+};
+
+struct i596_private {
+	struct i596_dma *dma;
+	u32    stat;
+	int last_restart;
+	struct i596_rfd *rfd_head;
+	struct i596_rbd *rbd_head;
+	struct i596_cmd *cmd_tail;
+	struct i596_cmd *cmd_head;
+	int cmd_backlog;
+	u32    last_cmd;
+	struct net_device_stats stats;
+	int next_tx_cmd;
+	int options;
+	spinlock_t lock;       /* serialize access to chip */
+	dma_addr_t dma_addr;
+	void __iomem *mpu_port;
+	void __iomem *ca;
+};
+
+static const char init_setup[] =
+{
+	0x8E,		/* length, prefetch on */
+	0xC8,		/* fifo to 8, monitor off */
+	0x80,		/* don't save bad frames */
+	0x2E,		/* No source address insertion, 8 byte preamble */
+	0x00,		/* priority and backoff defaults */
+	0x60,		/* interframe spacing */
+	0x00,		/* slot time LSB */
+	0xf2,		/* slot time and retries */
+	0x00,		/* promiscuous mode */
+	0x00,		/* collision detect */
+	0x40,		/* minimum frame length */
+	0xff,
+	0x00,
+	0x7f /*  *multi IA */ };
+
+static int i596_open(struct net_device *dev);
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t i596_interrupt(int irq, void *dev_id);
+static int i596_close(struct net_device *dev);
+static struct net_device_stats *i596_get_stats(struct net_device *dev);
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
+static void i596_tx_timeout (struct net_device *dev);
+static void print_eth(unsigned char *buf, char *str);
+static void set_multicast_list(struct net_device *dev);
+static inline void ca(struct net_device *dev);
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x);
+
+static int rx_ring_size = RX_RING_SIZE;
+static int ticks_limit = 100;
+static int max_cmd_backlog = TX_RING_SIZE-1;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev);
+#endif
+
+
+static inline int wait_istat(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+	DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+	while (--delcnt && dma->iscp.stat) {
+		udelay(10);
+		DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+	}
+	if (!delcnt) {
+		printk(KERN_ERR "%s: %s, iscp.stat %04x, didn't clear\n",
+		     dev->name, str, SWAP16(dma->iscp.stat));
+		return -1;
+	} else
+		return 0;
+}
+
+
+static inline int wait_cmd(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+	DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+	while (--delcnt && dma->scb.command) {
+		udelay(10);
+		DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+	}
+	if (!delcnt) {
+		printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n",
+		       dev->name, str,
+		       SWAP16(dma->scb.status),
+		       SWAP16(dma->scb.command));
+		return -1;
+	} else
+		return 0;
+}
+
+
+static void i596_display_data(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	struct i596_cmd *cmd;
+	struct i596_rfd *rfd;
+	struct i596_rbd *rbd;
+
+	printk(KERN_DEBUG "lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
+	       &dma->scp, dma->scp.sysbus, SWAP32(dma->scp.iscp));
+	printk(KERN_DEBUG "iscp at %p, iscp.stat = %08x, .scb = %08x\n",
+	       &dma->iscp, SWAP32(dma->iscp.stat), SWAP32(dma->iscp.scb));
+	printk(KERN_DEBUG "scb at %p, scb.status = %04x, .command = %04x,"
+		" .cmd = %08x, .rfd = %08x\n",
+	       &dma->scb, SWAP16(dma->scb.status), SWAP16(dma->scb.command),
+		SWAP16(dma->scb.cmd), SWAP32(dma->scb.rfd));
+	printk(KERN_DEBUG "   errors: crc %x, align %x, resource %x,"
+	       " over %x, rcvdt %x, short %x\n",
+	       SWAP32(dma->scb.crc_err), SWAP32(dma->scb.align_err),
+	       SWAP32(dma->scb.resource_err), SWAP32(dma->scb.over_err),
+	       SWAP32(dma->scb.rcvdt_err), SWAP32(dma->scb.short_err));
+	cmd = lp->cmd_head;
+	while (cmd != NULL) {
+		printk(KERN_DEBUG
+		       "cmd at %p, .status = %04x, .command = %04x,"
+		       " .b_next = %08x\n",
+		       cmd, SWAP16(cmd->status), SWAP16(cmd->command),
+		       SWAP32(cmd->b_next));
+		cmd = cmd->v_next;
+	}
+	rfd = lp->rfd_head;
+	printk(KERN_DEBUG "rfd_head = %p\n", rfd);
+	do {
+		printk(KERN_DEBUG
+		       "   %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
+		       " count %04x\n",
+		       rfd, SWAP16(rfd->stat), SWAP16(rfd->cmd),
+		       SWAP32(rfd->b_next), SWAP32(rfd->rbd),
+		       SWAP16(rfd->count));
+		rfd = rfd->v_next;
+	} while (rfd != lp->rfd_head);
+	rbd = lp->rbd_head;
+	printk(KERN_DEBUG "rbd_head = %p\n", rbd);
+	do {
+		printk(KERN_DEBUG
+		       "   %p .count %04x, b_next %08x, b_data %08x,"
+		       " size %04x\n",
+			rbd, SWAP16(rbd->count), SWAP32(rbd->b_next),
+		       SWAP32(rbd->b_data), SWAP16(rbd->size));
+		rbd = rbd->v_next;
+	} while (rbd != lp->rbd_head);
+	DMA_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+#define virt_to_dma(lp, v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)((lp)->dma)))
+
+static inline int init_rx_bufs(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	int i;
+	struct i596_rfd *rfd;
+	struct i596_rbd *rbd;
+
+	/* First build the Receive Buffer Descriptor List */
+
+	for (i = 0, rbd = dma->rbds; i < rx_ring_size; i++, rbd++) {
+		dma_addr_t dma_addr;
+		struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+
+		if (skb == NULL)
+			return -1;
+		skb_reserve(skb, 2);
+		dma_addr = dma_map_single(dev->dev.parent, skb->data,
+					  PKT_BUF_SZ, DMA_FROM_DEVICE);
+		rbd->v_next = rbd+1;
+		rbd->b_next = SWAP32(virt_to_dma(lp, rbd+1));
+		rbd->b_addr = SWAP32(virt_to_dma(lp, rbd));
+		rbd->skb = skb;
+		rbd->v_data = skb->data;
+		rbd->b_data = SWAP32(dma_addr);
+		rbd->size = SWAP16(PKT_BUF_SZ);
+	}
+	lp->rbd_head = dma->rbds;
+	rbd = dma->rbds + rx_ring_size - 1;
+	rbd->v_next = dma->rbds;
+	rbd->b_next = SWAP32(virt_to_dma(lp, dma->rbds));
+
+	/* Now build the Receive Frame Descriptor List */
+
+	for (i = 0, rfd = dma->rfds; i < rx_ring_size; i++, rfd++) {
+		rfd->rbd = I596_NULL;
+		rfd->v_next = rfd+1;
+		rfd->v_prev = rfd-1;
+		rfd->b_next = SWAP32(virt_to_dma(lp, rfd+1));
+		rfd->cmd = SWAP16(CMD_FLEX);
+	}
+	lp->rfd_head = dma->rfds;
+	dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+	rfd = dma->rfds;
+	rfd->rbd = SWAP32(virt_to_dma(lp, lp->rbd_head));
+	rfd->v_prev = dma->rfds + rx_ring_size - 1;
+	rfd = dma->rfds + rx_ring_size - 1;
+	rfd->v_next = dma->rfds;
+	rfd->b_next = SWAP32(virt_to_dma(lp, dma->rfds));
+	rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+
+	DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+	return 0;
+}
+
+static inline void remove_rx_bufs(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_rbd *rbd;
+	int i;
+
+	for (i = 0, rbd = lp->dma->rbds; i < rx_ring_size; i++, rbd++) {
+		if (rbd->skb == NULL)
+			break;
+		dma_unmap_single(dev->dev.parent,
+				 (dma_addr_t)SWAP32(rbd->b_data),
+				 PKT_BUF_SZ, DMA_FROM_DEVICE);
+		dev_kfree_skb(rbd->skb);
+	}
+}
+
+
+static void rebuild_rx_bufs(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	int i;
+
+	/* Ensure rx frame/buffer descriptors are tidy */
+
+	for (i = 0; i < rx_ring_size; i++) {
+		dma->rfds[i].rbd = I596_NULL;
+		dma->rfds[i].cmd = SWAP16(CMD_FLEX);
+	}
+	dma->rfds[rx_ring_size-1].cmd = SWAP16(CMD_EOL|CMD_FLEX);
+	lp->rfd_head = dma->rfds;
+	dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+	lp->rbd_head = dma->rbds;
+	dma->rfds[0].rbd = SWAP32(virt_to_dma(lp, dma->rbds));
+
+	DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+static int init_i596_mem(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	unsigned long flags;
+
+	mpu_port(dev, PORT_RESET, 0);
+	udelay(100);			/* Wait 100us - seems to help */
+
+	/* change the scp address */
+
+	lp->last_cmd = jiffies;
+
+	dma->scp.sysbus = SYSBUS;
+	dma->scp.iscp = SWAP32(virt_to_dma(lp, &(dma->iscp)));
+	dma->iscp.scb = SWAP32(virt_to_dma(lp, &(dma->scb)));
+	dma->iscp.stat = SWAP32(ISCP_BUSY);
+	lp->cmd_backlog = 0;
+
+	lp->cmd_head = NULL;
+	dma->scb.cmd = I596_NULL;
+
+	DEB(DEB_INIT, printk(KERN_DEBUG "%s: starting i82596.\n", dev->name));
+
+	DMA_WBACK(dev, &(dma->scp), sizeof(struct i596_scp));
+	DMA_WBACK(dev, &(dma->iscp), sizeof(struct i596_iscp));
+	DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+	mpu_port(dev, PORT_ALTSCP, virt_to_dma(lp, &dma->scp));
+	ca(dev);
+	if (wait_istat(dev, dma, 1000, "initialization timed out"))
+		goto failed;
+	DEB(DEB_INIT, printk(KERN_DEBUG
+			     "%s: i82596 initialization successful\n",
+			     dev->name));
+
+	if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
+		printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
+		goto failed;
+	}
+
+	/* Ensure rx frame/buffer descriptors are tidy */
+	rebuild_rx_bufs(dev);
+
+	dma->scb.command = 0;
+	DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+	DEB(DEB_INIT, printk(KERN_DEBUG
+			     "%s: queuing CmdConfigure\n", dev->name));
+	memcpy(dma->cf_cmd.i596_config, init_setup, 14);
+	dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+	DMA_WBACK(dev, &(dma->cf_cmd), sizeof(struct cf_cmd));
+	i596_add_cmd(dev, &dma->cf_cmd.cmd);
+
+	DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdSASetup\n", dev->name));
+	memcpy(dma->sa_cmd.eth_addr, dev->dev_addr, 6);
+	dma->sa_cmd.cmd.command = SWAP16(CmdSASetup);
+	DMA_WBACK(dev, &(dma->sa_cmd), sizeof(struct sa_cmd));
+	i596_add_cmd(dev, &dma->sa_cmd.cmd);
+
+	DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdTDR\n", dev->name));
+	dma->tdr_cmd.cmd.command = SWAP16(CmdTDR);
+	DMA_WBACK(dev, &(dma->tdr_cmd), sizeof(struct tdr_cmd));
+	i596_add_cmd(dev, &dma->tdr_cmd.cmd);
+
+	spin_lock_irqsave (&lp->lock, flags);
+
+	if (wait_cmd(dev, dma, 1000, "timed out waiting to issue RX_START")) {
+		spin_unlock_irqrestore (&lp->lock, flags);
+		goto failed_free_irq;
+	}
+	DEB(DEB_INIT, printk(KERN_DEBUG "%s: Issuing RX_START\n", dev->name));
+	dma->scb.command = SWAP16(RX_START);
+	dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+	DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+	ca(dev);
+
+	spin_unlock_irqrestore (&lp->lock, flags);
+	if (wait_cmd(dev, dma, 1000, "RX_START not processed"))
+		goto failed_free_irq;
+	DEB(DEB_INIT, printk(KERN_DEBUG
+			     "%s: Receive unit started OK\n", dev->name));
+	return 0;
+
+failed_free_irq:
+	free_irq(dev->irq, dev);
+failed:
+	printk(KERN_ERR "%s: Failed to initialise 82596\n", dev->name);
+	mpu_port(dev, PORT_RESET, 0);
+	return -1;
+}
+
+
+static inline int i596_rx(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_rfd *rfd;
+	struct i596_rbd *rbd;
+	int frames = 0;
+
+	DEB(DEB_RXFRAME, printk(KERN_DEBUG
+				"i596_rx(), rfd_head %p, rbd_head %p\n",
+				lp->rfd_head, lp->rbd_head));
+
+
+	rfd = lp->rfd_head;		/* Ref next frame to check */
+
+	DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+	while (rfd->stat & SWAP16(STAT_C)) {	/* Loop while complete frames */
+		if (rfd->rbd == I596_NULL)
+			rbd = NULL;
+		else if (rfd->rbd == lp->rbd_head->b_addr) {
+			rbd = lp->rbd_head;
+			DMA_INV(dev, rbd, sizeof(struct i596_rbd));
+		} else {
+			printk(KERN_ERR "%s: rbd chain broken!\n", dev->name);
+			/* XXX Now what? */
+			rbd = NULL;
+		}
+		DEB(DEB_RXFRAME, printk(KERN_DEBUG
+				      "  rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
+				      rfd, rfd->rbd, rfd->stat));
+
+		if (rbd != NULL && (rfd->stat & SWAP16(STAT_OK))) {
+			/* a good frame */
+			int pkt_len = SWAP16(rbd->count) & 0x3fff;
+			struct sk_buff *skb = rbd->skb;
+			int rx_in_place = 0;
+
+			DEB(DEB_RXADDR, print_eth(rbd->v_data, "received"));
+			frames++;
+
+			/* Check if the packet is long enough to just accept
+			 * without copying to a properly sized skbuff.
+			 */
+
+			if (pkt_len > rx_copybreak) {
+				struct sk_buff *newskb;
+				dma_addr_t dma_addr;
+
+				dma_unmap_single(dev->dev.parent,
+						 (dma_addr_t)SWAP32(rbd->b_data),
+						 PKT_BUF_SZ, DMA_FROM_DEVICE);
+				/* Get fresh skbuff to replace filled one. */
+				newskb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+				if (newskb == NULL) {
+					skb = NULL;	/* drop pkt */
+					goto memory_squeeze;
+				}
+				skb_reserve(newskb, 2);
+
+				/* Pass up the skb already on the Rx ring. */
+				skb_put(skb, pkt_len);
+				rx_in_place = 1;
+				rbd->skb = newskb;
+				dma_addr = dma_map_single(dev->dev.parent,
+							  newskb->data,
+							  PKT_BUF_SZ,
+							  DMA_FROM_DEVICE);
+				rbd->v_data = newskb->data;
+				rbd->b_data = SWAP32(dma_addr);
+				DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+			} else
+				skb = netdev_alloc_skb(dev, pkt_len + 2);
+memory_squeeze:
+			if (skb == NULL) {
+				/* XXX tulip.c can defer packets here!! */
+				printk(KERN_ERR
+				       "%s: i596_rx Memory squeeze, dropping packet.\n",
+				       dev->name);
+				lp->stats.rx_dropped++;
+			} else {
+				if (!rx_in_place) {
+					/* 16 byte align the data fields */
+					dma_sync_single_for_cpu(dev->dev.parent,
+								(dma_addr_t)SWAP32(rbd->b_data),
+								PKT_BUF_SZ, DMA_FROM_DEVICE);
+					skb_reserve(skb, 2);
+					memcpy(skb_put(skb, pkt_len), rbd->v_data, pkt_len);
+					dma_sync_single_for_device(dev->dev.parent,
+								   (dma_addr_t)SWAP32(rbd->b_data),
+								   PKT_BUF_SZ, DMA_FROM_DEVICE);
+				}
+				skb->len = pkt_len;
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				dev->last_rx = jiffies;
+				lp->stats.rx_packets++;
+				lp->stats.rx_bytes += pkt_len;
+			}
+		} else {
+			DEB(DEB_ERRORS, printk(KERN_DEBUG
+					       "%s: Error, rfd.stat = 0x%04x\n",
+					       dev->name, rfd->stat));
+			lp->stats.rx_errors++;
+			if (rfd->stat & SWAP16(0x0100))
+				lp->stats.collisions++;
+			if (rfd->stat & SWAP16(0x8000))
+				lp->stats.rx_length_errors++;
+			if (rfd->stat & SWAP16(0x0001))
+				lp->stats.rx_over_errors++;
+			if (rfd->stat & SWAP16(0x0002))
+				lp->stats.rx_fifo_errors++;
+			if (rfd->stat & SWAP16(0x0004))
+				lp->stats.rx_frame_errors++;
+			if (rfd->stat & SWAP16(0x0008))
+				lp->stats.rx_crc_errors++;
+			if (rfd->stat & SWAP16(0x0010))
+				lp->stats.rx_length_errors++;
+		}
+
+		/* Clear the buffer descriptor count and EOF + F flags */
+
+		if (rbd != NULL && (rbd->count & SWAP16(0x4000))) {
+			rbd->count = 0;
+			lp->rbd_head = rbd->v_next;
+			DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+		}
+
+		/* Tidy the frame descriptor, marking it as end of list */
+
+		rfd->rbd = I596_NULL;
+		rfd->stat = 0;
+		rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+		rfd->count = 0;
+
+		/* Update record of next frame descriptor to process */
+
+		lp->dma->scb.rfd = rfd->b_next;
+		lp->rfd_head = rfd->v_next;
+		DMA_WBACK_INV(dev, rfd, sizeof(struct i596_rfd));
+
+		/* Remove end-of-list from old end descriptor */
+
+		rfd->v_prev->cmd = SWAP16(CMD_FLEX);
+		DMA_WBACK_INV(dev, rfd->v_prev, sizeof(struct i596_rfd));
+		rfd = lp->rfd_head;
+		DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+	}
+
+	DEB(DEB_RXFRAME, printk(KERN_DEBUG "frames %d\n", frames));
+
+	return 0;
+}
+
+
+static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+{
+	struct i596_cmd *ptr;
+
+	while (lp->cmd_head != NULL) {
+		ptr = lp->cmd_head;
+		lp->cmd_head = ptr->v_next;
+		lp->cmd_backlog--;
+
+		switch (SWAP16(ptr->command) & 0x7) {
+		case CmdTx:
+			{
+				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+				struct sk_buff *skb = tx_cmd->skb;
+				dma_unmap_single(dev->dev.parent,
+						 tx_cmd->dma_addr,
+						 skb->len, DMA_TO_DEVICE);
+
+				dev_kfree_skb(skb);
+
+				lp->stats.tx_errors++;
+				lp->stats.tx_aborted_errors++;
+
+				ptr->v_next = NULL;
+				ptr->b_next = I596_NULL;
+				tx_cmd->cmd.command = 0;  /* Mark as free */
+				break;
+			}
+		default:
+			ptr->v_next = NULL;
+			ptr->b_next = I596_NULL;
+		}
+		DMA_WBACK_INV(dev, ptr, sizeof(struct i596_cmd));
+	}
+
+	wait_cmd(dev, lp->dma, 100, "i596_cleanup_cmd timed out");
+	lp->dma->scb.cmd = I596_NULL;
+	DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+}
+
+
+static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
+{
+	unsigned long flags;
+
+	DEB(DEB_RESET, printk(KERN_DEBUG "i596_reset\n"));
+
+	spin_lock_irqsave (&lp->lock, flags);
+
+	wait_cmd(dev, lp->dma, 100, "i596_reset timed out");
+
+	netif_stop_queue(dev);
+
+	/* FIXME: this command might cause an lpmc */
+	lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+	DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+	ca(dev);
+
+	/* wait for shutdown */
+	wait_cmd(dev, lp->dma, 1000, "i596_reset 2 timed out");
+	spin_unlock_irqrestore (&lp->lock, flags);
+
+	i596_cleanup_cmd(dev, lp);
+	i596_rx(dev);
+
+	netif_start_queue(dev);
+	init_i596_mem(dev);
+}
+
+
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	unsigned long flags;
+
+	DEB(DEB_ADDCMD, printk(KERN_DEBUG "i596_add_cmd cmd_head %p\n",
+			       lp->cmd_head));
+
+	cmd->status = 0;
+	cmd->command |= SWAP16(CMD_EOL | CMD_INTR);
+	cmd->v_next = NULL;
+	cmd->b_next = I596_NULL;
+	DMA_WBACK(dev, cmd, sizeof(struct i596_cmd));
+
+	spin_lock_irqsave (&lp->lock, flags);
+
+	if (lp->cmd_head != NULL) {
+		lp->cmd_tail->v_next = cmd;
+		lp->cmd_tail->b_next = SWAP32(virt_to_dma(lp, &cmd->status));
+		DMA_WBACK(dev, lp->cmd_tail, sizeof(struct i596_cmd));
+	} else {
+		lp->cmd_head = cmd;
+		wait_cmd(dev, dma, 100, "i596_add_cmd timed out");
+		dma->scb.cmd = SWAP32(virt_to_dma(lp, &cmd->status));
+		dma->scb.command = SWAP16(CUC_START);
+		DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+		ca(dev);
+	}
+	lp->cmd_tail = cmd;
+	lp->cmd_backlog++;
+
+	spin_unlock_irqrestore (&lp->lock, flags);
+
+	if (lp->cmd_backlog > max_cmd_backlog) {
+		unsigned long tickssofar = jiffies - lp->last_cmd;
+
+		if (tickssofar < ticks_limit)
+			return;
+
+		printk(KERN_ERR
+		       "%s: command unit timed out, status resetting.\n",
+		       dev->name);
+#if 1
+		i596_reset(dev, lp);
+#endif
+	}
+}
+
+static int i596_open(struct net_device *dev)
+{
+	DEB(DEB_OPEN, printk(KERN_DEBUG
+			     "%s: i596_open() irq %d.\n", dev->name, dev->irq));
+
+	if (init_rx_bufs(dev)) {
+		printk(KERN_ERR "%s: Failed to init rx bufs\n", dev->name);
+		return -EAGAIN;
+	}
+	if (init_i596_mem(dev)) {
+		printk(KERN_ERR "%s: Failed to init memory\n", dev->name);
+		goto out_remove_rx_bufs;
+	}
+	netif_start_queue(dev);
+
+	return 0;
+
+out_remove_rx_bufs:
+	remove_rx_bufs(dev);
+	return -EAGAIN;
+}
+
+static void i596_tx_timeout (struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+
+	/* Transmitter timeout, serious problems. */
+	DEB(DEB_ERRORS, printk(KERN_DEBUG
+			       "%s: transmit timed out, status resetting.\n",
+			       dev->name));
+
+	lp->stats.tx_errors++;
+
+	/* Try to restart the adaptor */
+	if (lp->last_restart == lp->stats.tx_packets) {
+		DEB(DEB_ERRORS, printk(KERN_DEBUG "Resetting board.\n"));
+		/* Shutdown and restart */
+		i596_reset (dev, lp);
+	} else {
+		/* Issue a channel attention signal */
+		DEB(DEB_ERRORS, printk(KERN_DEBUG "Kicking board.\n"));
+		lp->dma->scb.command = SWAP16(CUC_START | RX_START);
+		DMA_WBACK_INV(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+		ca (dev);
+		lp->last_restart = lp->stats.tx_packets;
+	}
+
+	dev->trans_start = jiffies;
+	netif_wake_queue (dev);
+}
+
+
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct tx_cmd *tx_cmd;
+	struct i596_tbd *tbd;
+	short length = skb->len;
+	dev->trans_start = jiffies;
+
+	DEB(DEB_STARTTX, printk(KERN_DEBUG
+				"%s: i596_start_xmit(%x,%p) called\n",
+				dev->name, skb->len, skb->data));
+
+	if (length < ETH_ZLEN) {
+		if (skb_padto(skb, ETH_ZLEN))
+			return 0;
+		length = ETH_ZLEN;
+	}
+
+	netif_stop_queue(dev);
+
+	tx_cmd = lp->dma->tx_cmds + lp->next_tx_cmd;
+	tbd = lp->dma->tbds + lp->next_tx_cmd;
+
+	if (tx_cmd->cmd.command) {
+		DEB(DEB_ERRORS, printk(KERN_DEBUG
+				       "%s: xmit ring full, dropping packet.\n",
+				       dev->name));
+		lp->stats.tx_dropped++;
+
+		dev_kfree_skb(skb);
+	} else {
+		if (++lp->next_tx_cmd == TX_RING_SIZE)
+			lp->next_tx_cmd = 0;
+		tx_cmd->tbd = SWAP32(virt_to_dma(lp, tbd));
+		tbd->next = I596_NULL;
+
+		tx_cmd->cmd.command = SWAP16(CMD_FLEX | CmdTx);
+		tx_cmd->skb = skb;
+
+		tx_cmd->pad = 0;
+		tx_cmd->size = 0;
+		tbd->pad = 0;
+		tbd->size = SWAP16(EOF | length);
+
+		tx_cmd->dma_addr = dma_map_single(dev->dev.parent, skb->data,
+						  skb->len, DMA_TO_DEVICE);
+		tbd->data = SWAP32(tx_cmd->dma_addr);
+
+		DEB(DEB_TXADDR, print_eth(skb->data, "tx-queued"));
+		DMA_WBACK_INV(dev, tx_cmd, sizeof(struct tx_cmd));
+		DMA_WBACK_INV(dev, tbd, sizeof(struct i596_tbd));
+		i596_add_cmd(dev, &tx_cmd->cmd);
+
+		lp->stats.tx_packets++;
+		lp->stats.tx_bytes += length;
+	}
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static void print_eth(unsigned char *add, char *str)
+{
+	int i;
+
+	printk(KERN_DEBUG "i596 0x%p, ", add);
+	for (i = 0; i < 6; i++)
+		printk(" %02X", add[i + 6]);
+	printk(" -->");
+	for (i = 0; i < 6; i++)
+		printk(" %02X", add[i]);
+	printk(" %02X%02X, %s\n", add[12], add[13], str);
+}
+
+static int __devinit i82596_probe(struct net_device *dev)
+{
+	int i;
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma;
+
+	/* This lot is ensure things have been cache line aligned. */
+	BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
+	BUILD_BUG_ON(sizeof(struct i596_rbd) &  31);
+	BUILD_BUG_ON(sizeof(struct tx_cmd)   &  31);
+	BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
+#ifndef __LP64__
+	BUILD_BUG_ON(sizeof(struct i596_dma) > 4096);
+#endif
+
+	if (!dev->base_addr || !dev->irq)
+		return -ENODEV;
+
+	dma = (struct i596_dma *) DMA_ALLOC(dev->dev.parent,
+		sizeof(struct i596_dma), &lp->dma_addr, GFP_KERNEL);
+	if (!dma) {
+		printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
+		return -ENOMEM;
+	}
+
+	/* The 82596-specific entries in the device structure. */
+	dev->open = i596_open;
+	dev->stop = i596_close;
+	dev->hard_start_xmit = i596_start_xmit;
+	dev->get_stats = i596_get_stats;
+	dev->set_multicast_list = set_multicast_list;
+	dev->tx_timeout = i596_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = i596_poll_controller;
+#endif
+
+	memset(dma, 0, sizeof(struct i596_dma));
+	lp->dma = dma;
+
+	dma->scb.command = 0;
+	dma->scb.cmd = I596_NULL;
+	dma->scb.rfd = I596_NULL;
+	spin_lock_init(&lp->lock);
+
+	DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+
+	i = register_netdev(dev);
+	if (i) {
+		DMA_FREE(dev->dev.parent, sizeof(struct i596_dma),
+				    (void *)dma, lp->dma_addr);
+		return i;
+	};
+
+	DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,",
+			      dev->name, dev->base_addr));
+	for (i = 0; i < 6; i++)
+		DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
+	DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
+	DEB(DEB_INIT, printk(KERN_INFO
+			     "%s: dma at 0x%p (%d bytes), lp->scb at 0x%p\n",
+			     dev->name, dma, (int)sizeof(struct i596_dma),
+			     &dma->scb));
+
+	return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	i596_interrupt(dev->irq, dev);
+	enable_irq(dev->irq);
+}
+#endif
+
+static irqreturn_t i596_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct i596_private *lp;
+	struct i596_dma *dma;
+	unsigned short status, ack_cmd = 0;
+
+	if (dev == NULL) {
+		printk(KERN_WARNING "%s: irq %d for unknown device.\n",
+		       __FUNCTION__, irq);
+		return IRQ_NONE;
+	}
+
+	lp = netdev_priv(dev);
+	dma = lp->dma;
+
+	spin_lock (&lp->lock);
+
+	wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+	status = SWAP16(dma->scb.status);
+
+	DEB(DEB_INTS, printk(KERN_DEBUG
+			     "%s: i596 interrupt, IRQ %d, status %4.4x.\n",
+			dev->name, irq, status));
+
+	ack_cmd = status & 0xf000;
+
+	if (!ack_cmd) {
+		DEB(DEB_ERRORS, printk(KERN_DEBUG
+				       "%s: interrupt with no events\n",
+				       dev->name));
+		spin_unlock (&lp->lock);
+		return IRQ_NONE;
+	}
+
+	if ((status & 0x8000) || (status & 0x2000)) {
+		struct i596_cmd *ptr;
+
+		if ((status & 0x8000))
+			DEB(DEB_INTS,
+			    printk(KERN_DEBUG
+				   "%s: i596 interrupt completed command.\n",
+				   dev->name));
+		if ((status & 0x2000))
+			DEB(DEB_INTS,
+			    printk(KERN_DEBUG
+				   "%s: i596 interrupt command unit inactive %x.\n",
+				   dev->name, status & 0x0700));
+
+		while (lp->cmd_head != NULL) {
+			DMA_INV(dev, lp->cmd_head, sizeof(struct i596_cmd));
+			if (!(lp->cmd_head->status & SWAP16(STAT_C)))
+				break;
+
+			ptr = lp->cmd_head;
+
+			DEB(DEB_STATUS,
+			    printk(KERN_DEBUG
+				   "cmd_head->status = %04x, ->command = %04x\n",
+				   SWAP16(lp->cmd_head->status),
+				   SWAP16(lp->cmd_head->command)));
+			lp->cmd_head = ptr->v_next;
+			lp->cmd_backlog--;
+
+			switch (SWAP16(ptr->command) & 0x7) {
+			case CmdTx:
+			    {
+				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+				struct sk_buff *skb = tx_cmd->skb;
+
+				if (ptr->status & SWAP16(STAT_OK)) {
+					DEB(DEB_TXADDR,
+					    print_eth(skb->data, "tx-done"));
+				} else {
+					lp->stats.tx_errors++;
+					if (ptr->status & SWAP16(0x0020))
+						lp->stats.collisions++;
+					if (!(ptr->status & SWAP16(0x0040)))
+						lp->stats.tx_heartbeat_errors++;
+					if (ptr->status & SWAP16(0x0400))
+						lp->stats.tx_carrier_errors++;
+					if (ptr->status & SWAP16(0x0800))
+						lp->stats.collisions++;
+					if (ptr->status & SWAP16(0x1000))
+						lp->stats.tx_aborted_errors++;
+				}
+				dma_unmap_single(dev->dev.parent,
+						 tx_cmd->dma_addr,
+						 skb->len, DMA_TO_DEVICE);
+				dev_kfree_skb_irq(skb);
+
+				tx_cmd->cmd.command = 0; /* Mark free */
+				break;
+			    }
+			case CmdTDR:
+			    {
+				unsigned short status = SWAP16(((struct tdr_cmd *)ptr)->status);
+
+				if (status & 0x8000) {
+					DEB(DEB_ANY,
+					    printk(KERN_DEBUG "%s: link ok.\n",
+						   dev->name));
+				} else {
+					if (status & 0x4000)
+						printk(KERN_ERR
+						       "%s: Transceiver problem.\n",
+						       dev->name);
+					if (status & 0x2000)
+						printk(KERN_ERR
+						       "%s: Termination problem.\n",
+						       dev->name);
+					if (status & 0x1000)
+						printk(KERN_ERR
+						       "%s: Short circuit.\n",
+						       dev->name);
+
+					DEB(DEB_TDR,
+					    printk(KERN_DEBUG "%s: Time %d.\n",
+						   dev->name, status & 0x07ff));
+				}
+				break;
+			    }
+			case CmdConfigure:
+				/*
+				 * Zap command so set_multicast_list() know
+				 * it is free
+				 */
+				ptr->command = 0;
+				break;
+			}
+			ptr->v_next = NULL;
+			ptr->b_next = I596_NULL;
+			DMA_WBACK(dev, ptr, sizeof(struct i596_cmd));
+			lp->last_cmd = jiffies;
+		}
+
+		/* This mess is arranging that only the last of any outstanding
+		 * commands has the interrupt bit set.  Should probably really
+		 * only add to the cmd queue when the CU is stopped.
+		 */
+		ptr = lp->cmd_head;
+		while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
+			struct i596_cmd *prev = ptr;
+
+			ptr->command &= SWAP16(0x1fff);
+			ptr = ptr->v_next;
+			DMA_WBACK_INV(dev, prev, sizeof(struct i596_cmd));
+		}
+
+		if (lp->cmd_head != NULL)
+			ack_cmd |= CUC_START;
+		dma->scb.cmd = SWAP32(virt_to_dma(lp, &lp->cmd_head->status));
+		DMA_WBACK_INV(dev, &dma->scb, sizeof(struct i596_scb));
+	}
+	if ((status & 0x1000) || (status & 0x4000)) {
+		if ((status & 0x4000))
+			DEB(DEB_INTS,
+			    printk(KERN_DEBUG
+				   "%s: i596 interrupt received a frame.\n",
+				   dev->name));
+		i596_rx(dev);
+		/* Only RX_START if stopped - RGH 07-07-96 */
+		if (status & 0x1000) {
+			if (netif_running(dev)) {
+				DEB(DEB_ERRORS,
+				    printk(KERN_DEBUG
+					   "%s: i596 interrupt receive unit inactive, status 0x%x\n",
+					   dev->name, status));
+				ack_cmd |= RX_START;
+				lp->stats.rx_errors++;
+				lp->stats.rx_fifo_errors++;
+				rebuild_rx_bufs(dev);
+			}
+		}
+	}
+	wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+	dma->scb.command = SWAP16(ack_cmd);
+	DMA_WBACK(dev, &dma->scb, sizeof(struct i596_scb));
+
+	/* DANGER: I suspect that some kind of interrupt
+	 acknowledgement aside from acking the 82596 might be needed
+	 here...  but it's running acceptably without */
+
+	ca(dev);
+
+	wait_cmd(dev, dma, 100, "i596 interrupt, exit timeout");
+	DEB(DEB_INTS, printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name));
+
+	spin_unlock (&lp->lock);
+	return IRQ_HANDLED;
+}
+
+static int i596_close(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	unsigned long flags;
+
+	netif_stop_queue(dev);
+
+	DEB(DEB_INIT,
+	    printk(KERN_DEBUG
+		   "%s: Shutting down ethercard, status was %4.4x.\n",
+		   dev->name, SWAP16(lp->dma->scb.status)));
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	wait_cmd(dev, lp->dma, 100, "close1 timed out");
+	lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+	DMA_WBACK(dev, &lp->dma->scb, sizeof(struct i596_scb));
+
+	ca(dev);
+
+	wait_cmd(dev, lp->dma, 100, "close2 timed out");
+	spin_unlock_irqrestore(&lp->lock, flags);
+	DEB(DEB_STRUCT, i596_display_data(dev));
+	i596_cleanup_cmd(dev, lp);
+
+	free_irq(dev->irq, dev);
+	remove_rx_bufs(dev);
+
+	return 0;
+}
+
+static struct net_device_stats *i596_get_stats(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+
+	return &lp->stats;
+}
+
+/*
+ *    Set or clear the multicast filter for this adaptor.
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	int config = 0, cnt;
+
+	DEB(DEB_MULTI,
+	    printk(KERN_DEBUG
+		   "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
+		   dev->name, dev->mc_count,
+		   dev->flags & IFF_PROMISC ? "ON" : "OFF",
+		   dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
+
+	if ((dev->flags & IFF_PROMISC) &&
+	    !(dma->cf_cmd.i596_config[8] & 0x01)) {
+		dma->cf_cmd.i596_config[8] |= 0x01;
+		config = 1;
+	}
+	if (!(dev->flags & IFF_PROMISC) &&
+	    (dma->cf_cmd.i596_config[8] & 0x01)) {
+		dma->cf_cmd.i596_config[8] &= ~0x01;
+		config = 1;
+	}
+	if ((dev->flags & IFF_ALLMULTI) &&
+	    (dma->cf_cmd.i596_config[11] & 0x20)) {
+		dma->cf_cmd.i596_config[11] &= ~0x20;
+		config = 1;
+	}
+	if (!(dev->flags & IFF_ALLMULTI) &&
+	    !(dma->cf_cmd.i596_config[11] & 0x20)) {
+		dma->cf_cmd.i596_config[11] |= 0x20;
+		config = 1;
+	}
+	if (config) {
+		if (dma->cf_cmd.cmd.command)
+			printk(KERN_INFO
+			       "%s: config change request already queued\n",
+			       dev->name);
+		else {
+			dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+			DMA_WBACK_INV(dev, &dma->cf_cmd, sizeof(struct cf_cmd));
+			i596_add_cmd(dev, &dma->cf_cmd.cmd);
+		}
+	}
+
+	cnt = dev->mc_count;
+	if (cnt > MAX_MC_CNT) {
+		cnt = MAX_MC_CNT;
+		printk(KERN_NOTICE "%s: Only %d multicast addresses supported",
+			dev->name, cnt);
+	}
+
+	if (dev->mc_count > 0) {
+		struct dev_mc_list *dmi;
+		unsigned char *cp;
+		struct mc_cmd *cmd;
+
+		cmd = &dma->mc_cmd;
+		cmd->cmd.command = SWAP16(CmdMulticastList);
+		cmd->mc_cnt = SWAP16(dev->mc_count * 6);
+		cp = cmd->mc_addrs;
+		for (dmi = dev->mc_list;
+		     cnt && dmi != NULL;
+		     dmi = dmi->next, cnt--, cp += 6) {
+			memcpy(cp, dmi->dmi_addr, 6);
+			if (i596_debug > 1)
+				DEB(DEB_MULTI,
+				    printk(KERN_DEBUG
+					   "%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
+					   dev->name, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]));
+		}
+		DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd));
+		i596_add_cmd(dev, &cmd->cmd);
+	}
+}
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0e04f7a..a4bb026 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -17,13 +17,12 @@
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/mii.h>
-#include <linux/mutex.h>
 #include <linux/dma-mapping.h>
-#include <linux/ethtool.h>
 #include <linux/platform_device.h>
+#include <linux/phy.h>
 
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 
 #include "macb.h"
 
@@ -85,172 +84,202 @@
 		memcpy(bp->dev->dev_addr, addr, sizeof(addr));
 }
 
-static void macb_enable_mdio(struct macb *bp)
+static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
-	unsigned long flags;
-	u32 reg;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	reg = macb_readl(bp, NCR);
-	reg |= MACB_BIT(MPE);
-	macb_writel(bp, NCR, reg);
-	macb_writel(bp, IER, MACB_BIT(MFD));
-	spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static void macb_disable_mdio(struct macb *bp)
-{
-	unsigned long flags;
-	u32 reg;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	reg = macb_readl(bp, NCR);
-	reg &= ~MACB_BIT(MPE);
-	macb_writel(bp, NCR, reg);
-	macb_writel(bp, IDR, MACB_BIT(MFD));
-	spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static int macb_mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = bus->priv;
 	int value;
 
-	mutex_lock(&bp->mdio_mutex);
-
-	macb_enable_mdio(bp);
 	macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
 			      | MACB_BF(RW, MACB_MAN_READ)
-			      | MACB_BF(PHYA, phy_id)
-			      | MACB_BF(REGA, location)
+			      | MACB_BF(PHYA, mii_id)
+			      | MACB_BF(REGA, regnum)
 			      | MACB_BF(CODE, MACB_MAN_CODE)));
 
-	wait_for_completion(&bp->mdio_complete);
+	/* wait for end of transfer */
+	while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
+		cpu_relax();
 
 	value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
-	macb_disable_mdio(bp);
-	mutex_unlock(&bp->mdio_mutex);
 
 	return value;
 }
 
-static void macb_mdio_write(struct net_device *dev, int phy_id,
-			    int location, int val)
+static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+			   u16 value)
 {
-	struct macb *bp = netdev_priv(dev);
-
-	dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n",
-		phy_id, location, val);
-
-	mutex_lock(&bp->mdio_mutex);
-	macb_enable_mdio(bp);
+	struct macb *bp = bus->priv;
 
 	macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
 			      | MACB_BF(RW, MACB_MAN_WRITE)
-			      | MACB_BF(PHYA, phy_id)
-			      | MACB_BF(REGA, location)
+			      | MACB_BF(PHYA, mii_id)
+			      | MACB_BF(REGA, regnum)
 			      | MACB_BF(CODE, MACB_MAN_CODE)
-			      | MACB_BF(DATA, val)));
+			      | MACB_BF(DATA, value)));
 
-	wait_for_completion(&bp->mdio_complete);
+	/* wait for end of transfer */
+	while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
+		cpu_relax();
 
-	macb_disable_mdio(bp);
-	mutex_unlock(&bp->mdio_mutex);
-}
-
-static int macb_phy_probe(struct macb *bp)
-{
-	int phy_address;
-	u16 phyid1, phyid2;
-
-	for (phy_address = 0; phy_address < 32; phy_address++) {
-		phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1);
-		phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2);
-
-		if (phyid1 != 0xffff && phyid1 != 0x0000
-		    && phyid2 != 0xffff && phyid2 != 0x0000)
-			break;
-	}
-
-	if (phy_address == 32)
-		return -ENODEV;
-
-	dev_info(&bp->pdev->dev,
-		 "detected PHY at address %d (ID %04x:%04x)\n",
-		 phy_address, phyid1, phyid2);
-
-	bp->mii.phy_id = phy_address;
 	return 0;
 }
 
-static void macb_set_media(struct macb *bp, int media)
+static int macb_mdio_reset(struct mii_bus *bus)
 {
-	u32 reg;
-
-	spin_lock_irq(&bp->lock);
-	reg = macb_readl(bp, NCFGR);
-	reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
-	if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL))
-		reg |= MACB_BIT(SPD);
-	if (media & ADVERTISE_FULL)
-		reg |= MACB_BIT(FD);
-	macb_writel(bp, NCFGR, reg);
-	spin_unlock_irq(&bp->lock);
+	return 0;
 }
 
-static void macb_check_media(struct macb *bp, int ok_to_print, int init_media)
+static void macb_handle_link_change(struct net_device *dev)
 {
-	struct mii_if_info *mii = &bp->mii;
-	unsigned int old_carrier, new_carrier;
-	int advertise, lpa, media, duplex;
+	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
+	unsigned long flags;
 
-	/* if forced media, go no further */
-	if (mii->force_media)
-		return;
+	int status_change = 0;
 
-	/* check current and old link status */
-	old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
-	new_carrier = (unsigned int) mii_link_ok(mii);
+	spin_lock_irqsave(&bp->lock, flags);
 
-	/* if carrier state did not change, assume nothing else did */
-	if (!init_media && old_carrier == new_carrier)
-		return;
+	if (phydev->link) {
+		if ((bp->speed != phydev->speed) ||
+		    (bp->duplex != phydev->duplex)) {
+			u32 reg;
 
-	/* no carrier, nothing much to do */
-	if (!new_carrier) {
-		netif_carrier_off(mii->dev);
-		printk(KERN_INFO "%s: link down\n", mii->dev->name);
-		return;
+			reg = macb_readl(bp, NCFGR);
+			reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+
+			if (phydev->duplex)
+				reg |= MACB_BIT(FD);
+			if (phydev->speed)
+				reg |= MACB_BIT(SPD);
+
+			macb_writel(bp, NCFGR, reg);
+
+			bp->speed = phydev->speed;
+			bp->duplex = phydev->duplex;
+			status_change = 1;
+		}
 	}
 
-	/*
-	 * we have carrier, see who's on the other end
-	 */
-	netif_carrier_on(mii->dev);
+	if (phydev->link != bp->link) {
+		if (phydev->link)
+			netif_schedule(dev);
+		else {
+			bp->speed = 0;
+			bp->duplex = -1;
+		}
+		bp->link = phydev->link;
 
-	/* get MII advertise and LPA values */
-	if (!init_media && mii->advertising) {
-		advertise = mii->advertising;
+		status_change = 1;
+	}
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	if (status_change) {
+		if (phydev->link)
+			printk(KERN_INFO "%s: link up (%d/%s)\n",
+			       dev->name, phydev->speed,
+			       DUPLEX_FULL == phydev->duplex ? "Full":"Half");
+		else
+			printk(KERN_INFO "%s: link down\n", dev->name);
+	}
+}
+
+/* based on au1000_eth. c*/
+static int macb_mii_probe(struct net_device *dev)
+{
+	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = NULL;
+	struct eth_platform_data *pdata;
+	int phy_addr;
+
+	/* find the first phy */
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+		if (bp->mii_bus.phy_map[phy_addr]) {
+			phydev = bp->mii_bus.phy_map[phy_addr];
+			break;
+		}
+	}
+
+	if (!phydev) {
+		printk (KERN_ERR "%s: no PHY found\n", dev->name);
+		return -1;
+	}
+
+	pdata = bp->pdev->dev.platform_data;
+	/* TODO : add pin_irq */
+
+	/* attach the mac to the phy */
+	if (pdata && pdata->is_rmii) {
+		phydev = phy_connect(dev, phydev->dev.bus_id,
+			&macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII);
 	} else {
-		advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
-		mii->advertising = advertise;
+		phydev = phy_connect(dev, phydev->dev.bus_id,
+			&macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII);
 	}
-	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
 
-	/* figure out media and duplex from advertise and LPA values */
-	media = mii_nway_result(lpa & advertise);
-	duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+	if (IS_ERR(phydev)) {
+		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		return PTR_ERR(phydev);
+	}
 
-	if (ok_to_print)
-		printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
-		       mii->dev->name,
-		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
-		       duplex ? "full" : "half", lpa);
+	/* mask with MAC supported features */
+	phydev->supported &= PHY_BASIC_FEATURES;
 
-	mii->full_duplex = duplex;
+	phydev->advertising = phydev->supported;
 
-	/* Let the MAC know about the new link state */
-	macb_set_media(bp, media);
+	bp->link = 0;
+	bp->speed = 0;
+	bp->duplex = -1;
+	bp->phy_dev = phydev;
+
+	return 0;
+}
+
+static int macb_mii_init(struct macb *bp)
+{
+	struct eth_platform_data *pdata;
+	int err = -ENXIO, i;
+
+	/* Enable managment port */
+	macb_writel(bp, NCR, MACB_BIT(MPE));
+
+	bp->mii_bus.name = "MACB_mii_bus",
+	bp->mii_bus.read = &macb_mdio_read,
+	bp->mii_bus.write = &macb_mdio_write,
+	bp->mii_bus.reset = &macb_mdio_reset,
+	bp->mii_bus.id = bp->pdev->id,
+	bp->mii_bus.priv = bp,
+	bp->mii_bus.dev = &bp->dev->dev;
+	pdata = bp->pdev->dev.platform_data;
+
+	if (pdata)
+		bp->mii_bus.phy_mask = pdata->phy_mask;
+
+	bp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	if (!bp->mii_bus.irq) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		bp->mii_bus.irq[i] = PHY_POLL;
+
+	platform_set_drvdata(bp->dev, &bp->mii_bus);
+
+	if (mdiobus_register(&bp->mii_bus))
+		goto err_out_free_mdio_irq;
+
+	if (macb_mii_probe(bp->dev) != 0) {
+		goto err_out_unregister_bus;
+	}
+
+	return 0;
+
+err_out_unregister_bus:
+	mdiobus_unregister(&bp->mii_bus);
+err_out_free_mdio_irq:
+	kfree(bp->mii_bus.irq);
+err_out:
+	return err;
 }
 
 static void macb_update_stats(struct macb *bp)
@@ -265,16 +294,6 @@
 		*p += __raw_readl(reg);
 }
 
-static void macb_periodic_task(struct work_struct *work)
-{
-	struct macb *bp = container_of(work, struct macb, periodic_task.work);
-
-	macb_update_stats(bp);
-	macb_check_media(bp, 1, 0);
-
-	schedule_delayed_work(&bp->periodic_task, HZ);
-}
-
 static void macb_tx(struct macb *bp)
 {
 	unsigned int tail;
@@ -519,9 +538,6 @@
 	spin_lock(&bp->lock);
 
 	while (status) {
-		if (status & MACB_BIT(MFD))
-			complete(&bp->mdio_complete);
-
 		/* close possible race with dev_close */
 		if (unlikely(!netif_running(dev))) {
 			macb_writel(bp, IDR, ~0UL);
@@ -535,7 +551,8 @@
 				 * until we have processed the buffers
 				 */
 				macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
-				dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n");
+				dev_dbg(&bp->pdev->dev,
+					"scheduling RX softirq\n");
 				__netif_rx_schedule(dev);
 			}
 		}
@@ -765,7 +782,7 @@
 	macb_writel(bp, TBQP, bp->tx_ring_dma);
 
 	/* Enable TX and RX */
-	macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE));
+	macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
 
 	/* Enable interrupts */
 	macb_writel(bp, IER, (MACB_BIT(RCOMP)
@@ -776,18 +793,126 @@
 			      | MACB_BIT(TCOMP)
 			      | MACB_BIT(ISR_ROVR)
 			      | MACB_BIT(HRESP)));
+
 }
 
-static void macb_init_phy(struct net_device *dev)
+/*
+ * The hash address register is 64 bits long and takes up two
+ * locations in the memory map.  The least significant bits are stored
+ * in EMAC_HSL and the most significant bits in EMAC_HSH.
+ *
+ * The unicast hash enable and the multicast hash enable bits in the
+ * network configuration register enable the reception of hash matched
+ * frames. The destination address is reduced to a 6 bit index into
+ * the 64 bit hash register using the following hash function.  The
+ * hash function is an exclusive or of every sixth bit of the
+ * destination address.
+ *
+ * hi[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
+ * hi[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
+ * hi[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
+ * hi[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
+ * hi[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
+ * hi[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
+ *
+ * da[0] represents the least significant bit of the first byte
+ * received, that is, the multicast/unicast indicator, and da[47]
+ * represents the most significant bit of the last byte received.  If
+ * the hash index, hi[n], points to a bit that is set in the hash
+ * register then the frame will be matched according to whether the
+ * frame is multicast or unicast.  A multicast match will be signalled
+ * if the multicast hash enable bit is set, da[0] is 1 and the hash
+ * index points to a bit set in the hash register.  A unicast match
+ * will be signalled if the unicast hash enable bit is set, da[0] is 0
+ * and the hash index points to a bit set in the hash register.  To
+ * receive all multicast frames, the hash register should be set with
+ * all ones and the multicast hash enable bit should be set in the
+ * network configuration register.
+ */
+
+static inline int hash_bit_value(int bitnr, __u8 *addr)
 {
+	if (addr[bitnr / 8] & (1 << (bitnr % 8)))
+		return 1;
+	return 0;
+}
+
+/*
+ * Return the hash index value for the specified address.
+ */
+static int hash_get_index(__u8 *addr)
+{
+	int i, j, bitval;
+	int hash_index = 0;
+
+	for (j = 0; j < 6; j++) {
+		for (i = 0, bitval = 0; i < 8; i++)
+			bitval ^= hash_bit_value(i*6 + j, addr);
+
+		hash_index |= (bitval << j);
+	}
+
+	return hash_index;
+}
+
+/*
+ * Add multicast addresses to the internal multicast-hash table.
+ */
+static void macb_sethashtable(struct net_device *dev)
+{
+	struct dev_mc_list *curr;
+	unsigned long mc_filter[2];
+	unsigned int i, bitnr;
 	struct macb *bp = netdev_priv(dev);
 
-	/* Set some reasonable default settings */
-	macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE,
-			ADVERTISE_CSMA | ADVERTISE_ALL);
-	macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR,
-			(BMCR_SPEED100 | BMCR_ANENABLE
-			 | BMCR_ANRESTART | BMCR_FULLDPLX));
+	mc_filter[0] = mc_filter[1] = 0;
+
+	curr = dev->mc_list;
+	for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
+		if (!curr) break;	/* unexpected end of list */
+
+		bitnr = hash_get_index(curr->dmi_addr);
+		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
+	}
+
+	macb_writel(bp, HRB, mc_filter[0]);
+	macb_writel(bp, HRT, mc_filter[1]);
+}
+
+/*
+ * Enable/Disable promiscuous and multicast modes.
+ */
+static void macb_set_rx_mode(struct net_device *dev)
+{
+	unsigned long cfg;
+	struct macb *bp = netdev_priv(dev);
+
+	cfg = macb_readl(bp, NCFGR);
+
+	if (dev->flags & IFF_PROMISC)
+		/* Enable promiscuous mode */
+		cfg |= MACB_BIT(CAF);
+	else if (dev->flags & (~IFF_PROMISC))
+		 /* Disable promiscuous mode */
+		cfg &= ~MACB_BIT(CAF);
+
+	if (dev->flags & IFF_ALLMULTI) {
+		/* Enable all multicast mode */
+		macb_writel(bp, HRB, -1);
+		macb_writel(bp, HRT, -1);
+		cfg |= MACB_BIT(NCFGR_MTI);
+	} else if (dev->mc_count > 0) {
+		/* Enable specific multicasts */
+		macb_sethashtable(dev);
+		cfg |= MACB_BIT(NCFGR_MTI);
+	} else if (dev->flags & (~IFF_ALLMULTI)) {
+		/* Disable all multicast mode */
+		macb_writel(bp, HRB, 0);
+		macb_writel(bp, HRT, 0);
+		cfg &= ~MACB_BIT(NCFGR_MTI);
+	}
+
+	macb_writel(bp, NCFGR, cfg);
 }
 
 static int macb_open(struct net_device *dev)
@@ -797,6 +922,10 @@
 
 	dev_dbg(&bp->pdev->dev, "open\n");
 
+	/* if the phy is not yet register, retry later*/
+	if (!bp->phy_dev)
+		return -EAGAIN;
+
 	if (!is_valid_ether_addr(dev->dev_addr))
 		return -EADDRNOTAVAIL;
 
@@ -810,13 +939,12 @@
 
 	macb_init_rings(bp);
 	macb_init_hw(bp);
-	macb_init_phy(dev);
 
-	macb_check_media(bp, 1, 1);
+	/* schedule a link state check */
+	phy_start(bp->phy_dev);
+
 	netif_start_queue(dev);
 
-	schedule_delayed_work(&bp->periodic_task, HZ);
-
 	return 0;
 }
 
@@ -825,10 +953,11 @@
 	struct macb *bp = netdev_priv(dev);
 	unsigned long flags;
 
-	cancel_rearming_delayed_work(&bp->periodic_task);
-
 	netif_stop_queue(dev);
 
+	if (bp->phy_dev)
+		phy_stop(bp->phy_dev);
+
 	spin_lock_irqsave(&bp->lock, flags);
 	macb_reset_hw(bp);
 	netif_carrier_off(dev);
@@ -845,6 +974,9 @@
 	struct net_device_stats *nstat = &bp->stats;
 	struct macb_stats *hwstat = &bp->hw_stats;
 
+	/* read stats from hardware */
+	macb_update_stats(bp);
+
 	/* Convert HW stats into netdevice stats */
 	nstat->rx_errors = (hwstat->rx_fcs_errors +
 			    hwstat->rx_align_errors +
@@ -882,18 +1014,27 @@
 static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
 
-	return mii_ethtool_gset(&bp->mii, cmd);
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_gset(phydev, cmd);
 }
 
 static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
 
-	return mii_ethtool_sset(&bp->mii, cmd);
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phydev, cmd);
 }
 
-static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void macb_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
 {
 	struct macb *bp = netdev_priv(dev);
 
@@ -902,104 +1043,34 @@
 	strcpy(info->bus_info, bp->pdev->dev.bus_id);
 }
 
-static int macb_nway_reset(struct net_device *dev)
-{
-	struct macb *bp = netdev_priv(dev);
-	return mii_nway_restart(&bp->mii);
-}
-
 static struct ethtool_ops macb_ethtool_ops = {
 	.get_settings		= macb_get_settings,
 	.set_settings		= macb_set_settings,
 	.get_drvinfo		= macb_get_drvinfo,
-	.nway_reset		= macb_nway_reset,
 	.get_link		= ethtool_op_get_link,
 };
 
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct macb *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
 }
 
-static ssize_t macb_mii_show(const struct device *_dev, char *buf,
-			unsigned long addr)
-{
-	struct net_device *dev = to_net_dev(_dev);
-	struct macb *bp = netdev_priv(dev);
-	ssize_t ret = -EINVAL;
-
-	if (netif_running(dev)) {
-		int value;
-		value = macb_mdio_read(dev, bp->mii.phy_id, addr);
-		ret = sprintf(buf, "0x%04x\n", (uint16_t)value);
-	}
-
-	return ret;
-}
-
-#define MII_ENTRY(name, addr)					\
-static ssize_t show_##name(struct device *_dev,			\
-			   struct device_attribute *attr,	\
-			   char *buf)				\
-{								\
-	return macb_mii_show(_dev, buf, addr);			\
-}								\
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
-
-MII_ENTRY(bmcr, MII_BMCR);
-MII_ENTRY(bmsr, MII_BMSR);
-MII_ENTRY(physid1, MII_PHYSID1);
-MII_ENTRY(physid2, MII_PHYSID2);
-MII_ENTRY(advertise, MII_ADVERTISE);
-MII_ENTRY(lpa, MII_LPA);
-MII_ENTRY(expansion, MII_EXPANSION);
-
-static struct attribute *macb_mii_attrs[] = {
-	&dev_attr_bmcr.attr,
-	&dev_attr_bmsr.attr,
-	&dev_attr_physid1.attr,
-	&dev_attr_physid2.attr,
-	&dev_attr_advertise.attr,
-	&dev_attr_lpa.attr,
-	&dev_attr_expansion.attr,
-	NULL,
-};
-
-static struct attribute_group macb_mii_group = {
-	.name	= "mii",
-	.attrs	= macb_mii_attrs,
-};
-
-static void macb_unregister_sysfs(struct net_device *net)
-{
-	struct device *_dev = &net->dev;
-
-	sysfs_remove_group(&_dev->kobj, &macb_mii_group);
-}
-
-static int macb_register_sysfs(struct net_device *net)
-{
-	struct device *_dev = &net->dev;
-	int ret;
-
-	ret = sysfs_create_group(&_dev->kobj, &macb_mii_group);
-	if (ret)
-		printk(KERN_WARNING
-		       "%s: sysfs mii attribute registration failed: %d\n",
-		       net->name, ret);
-	return ret;
-}
 static int __devinit macb_probe(struct platform_device *pdev)
 {
 	struct eth_platform_data *pdata;
 	struct resource *regs;
 	struct net_device *dev;
 	struct macb *bp;
+	struct phy_device *phydev;
 	unsigned long pclk_hz;
 	u32 config;
 	int err = -ENXIO;
@@ -1073,6 +1144,7 @@
 	dev->stop = macb_close;
 	dev->hard_start_xmit = macb_start_xmit;
 	dev->get_stats = macb_get_stats;
+	dev->set_multicast_list = macb_set_rx_mode;
 	dev->do_ioctl = macb_ioctl;
 	dev->poll = macb_poll;
 	dev->weight = 64;
@@ -1080,10 +1152,6 @@
 
 	dev->base_addr = regs->start;
 
-	INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task);
-	mutex_init(&bp->mdio_mutex);
-	init_completion(&bp->mdio_complete);
-
 	/* Set MII management clock divider */
 	pclk_hz = clk_get_rate(bp->pclk);
 	if (pclk_hz <= 20000000)
@@ -1096,20 +1164,9 @@
 		config = MACB_BF(CLK, MACB_CLK_DIV64);
 	macb_writel(bp, NCFGR, config);
 
-	bp->mii.dev = dev;
-	bp->mii.mdio_read = macb_mdio_read;
-	bp->mii.mdio_write = macb_mdio_write;
-	bp->mii.phy_id_mask = 0x1f;
-	bp->mii.reg_num_mask = 0x1f;
-
 	macb_get_hwaddr(bp);
-	err = macb_phy_probe(bp);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n");
-		goto err_out_free_irq;
-	}
-
 	pdata = pdev->dev.platform_data;
+
 	if (pdata && pdata->is_rmii)
 #if defined(CONFIG_ARCH_AT91)
 		macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) );
@@ -1131,9 +1188,11 @@
 		goto err_out_free_irq;
 	}
 
-	platform_set_drvdata(pdev, dev);
+	if (macb_mii_init(bp) != 0) {
+		goto err_out_unregister_netdev;
+	}
 
-	macb_register_sysfs(dev);
+	platform_set_drvdata(pdev, dev);
 
 	printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d "
 	       "(%02x:%02x:%02x:%02x:%02x:%02x)\n",
@@ -1141,8 +1200,15 @@
 	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
 	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
+	phydev = bp->phy_dev;
+	printk(KERN_INFO "%s: attached PHY driver [%s] "
+		"(mii_bus:phy_addr=%s, irq=%d)\n",
+		dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
+
 	return 0;
 
+err_out_unregister_netdev:
+	unregister_netdev(dev);
 err_out_free_irq:
 	free_irq(dev->irq, dev);
 err_out_iounmap:
@@ -1153,7 +1219,9 @@
 	clk_put(bp->hclk);
 #endif
 	clk_disable(bp->pclk);
+#ifndef CONFIG_ARCH_AT91
 err_out_put_pclk:
+#endif
 	clk_put(bp->pclk);
 err_out_free_dev:
 	free_netdev(dev);
@@ -1171,7 +1239,8 @@
 
 	if (dev) {
 		bp = netdev_priv(dev);
-		macb_unregister_sysfs(dev);
+		mdiobus_unregister(&bp->mii_bus);
+		kfree(bp->mii_bus.irq);
 		unregister_netdev(dev);
 		free_irq(dev->irq, dev);
 		iounmap(bp->regs);
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index b3bb218..4e3283e 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -383,11 +383,11 @@
 
 	unsigned int		rx_pending, tx_pending;
 
-	struct delayed_work	periodic_task;
-
-	struct mutex		mdio_mutex;
-	struct completion	mdio_complete;
-	struct mii_if_info	mii;
+	struct mii_bus		mii_bus;
+	struct phy_device	*phy_dev;
+	unsigned int 		link;
+	unsigned int 		speed;
+	unsigned int 		duplex;
 };
 
 #endif /* _MACB_H */
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index fef3193..9a343b96 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -577,7 +577,7 @@
 	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mb = mp->mace;
 	int intr, fs;
-	unsigned int flags;
+	unsigned long flags;
 
 	/* don't want the dma interrupt handler to fire */
 	local_irq_save(flags);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
new file mode 100644
index 0000000..dc74d00
--- /dev/null
+++ b/drivers/net/macvlan.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * The code this is based on carried the following copyright notice:
+ * ---
+ * (C) Copyright 2001-2006
+ * Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
+ * Re-worked by Ben Greear <greearb@candelatech.com>
+ * ---
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_arp.h>
+#include <linux/if_link.h>
+#include <linux/if_macvlan.h>
+#include <net/rtnetlink.h>
+
+#define MACVLAN_HASH_SIZE	(1 << BITS_PER_BYTE)
+
+struct macvlan_port {
+	struct net_device	*dev;
+	struct hlist_head	vlan_hash[MACVLAN_HASH_SIZE];
+	struct list_head	vlans;
+};
+
+struct macvlan_dev {
+	struct net_device	*dev;
+	struct list_head	list;
+	struct hlist_node	hlist;
+	struct macvlan_port	*port;
+	struct net_device	*lowerdev;
+};
+
+
+static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
+					       const unsigned char *addr)
+{
+	struct macvlan_dev *vlan;
+	struct hlist_node *n;
+
+	hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) {
+		if (!compare_ether_addr(vlan->dev->dev_addr, addr))
+			return vlan;
+	}
+	return NULL;
+}
+
+static void macvlan_broadcast(struct sk_buff *skb,
+			      const struct macvlan_port *port)
+{
+	const struct ethhdr *eth = eth_hdr(skb);
+	const struct macvlan_dev *vlan;
+	struct hlist_node *n;
+	struct net_device *dev;
+	struct sk_buff *nskb;
+	unsigned int i;
+
+	for (i = 0; i < MACVLAN_HASH_SIZE; i++) {
+		hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) {
+			dev = vlan->dev;
+			if (unlikely(!(dev->flags & IFF_UP)))
+				continue;
+
+			nskb = skb_clone(skb, GFP_ATOMIC);
+			if (nskb == NULL) {
+				dev->stats.rx_errors++;
+				dev->stats.rx_dropped++;
+				continue;
+			}
+
+			dev->stats.rx_bytes += skb->len + ETH_HLEN;
+			dev->stats.rx_packets++;
+			dev->stats.multicast++;
+			dev->last_rx = jiffies;
+
+			nskb->dev = dev;
+			if (!compare_ether_addr(eth->h_dest, dev->broadcast))
+				nskb->pkt_type = PACKET_BROADCAST;
+			else
+				nskb->pkt_type = PACKET_MULTICAST;
+
+			netif_rx(nskb);
+		}
+	}
+}
+
+/* called under rcu_read_lock() from netif_receive_skb */
+static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
+{
+	const struct ethhdr *eth = eth_hdr(skb);
+	const struct macvlan_port *port;
+	const struct macvlan_dev *vlan;
+	struct net_device *dev;
+
+	port = rcu_dereference(skb->dev->macvlan_port);
+	if (port == NULL)
+		return skb;
+
+	if (is_multicast_ether_addr(eth->h_dest)) {
+		macvlan_broadcast(skb, port);
+		return skb;
+	}
+
+	vlan = macvlan_hash_lookup(port, eth->h_dest);
+	if (vlan == NULL)
+		return skb;
+
+	dev = vlan->dev;
+	if (unlikely(!(dev->flags & IFF_UP))) {
+		kfree_skb(skb);
+		return NULL;
+	}
+
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (skb == NULL) {
+		dev->stats.rx_errors++;
+		dev->stats.rx_dropped++;
+		return NULL;
+	}
+
+	dev->stats.rx_bytes += skb->len + ETH_HLEN;
+	dev->stats.rx_packets++;
+	dev->last_rx = jiffies;
+
+	skb->dev = dev;
+	skb->pkt_type = PACKET_HOST;
+
+	netif_rx(skb);
+	return NULL;
+}
+
+static int macvlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	const struct macvlan_dev *vlan = netdev_priv(dev);
+	unsigned int len = skb->len;
+	int ret;
+
+	skb->dev = vlan->lowerdev;
+	ret = dev_queue_xmit(skb);
+
+	if (likely(ret == NET_XMIT_SUCCESS)) {
+		dev->stats.tx_packets++;
+		dev->stats.tx_bytes += len;
+	} else {
+		dev->stats.tx_errors++;
+		dev->stats.tx_aborted_errors++;
+	}
+	return NETDEV_TX_OK;
+}
+
+static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
+			       unsigned short type, void *daddr, void *saddr,
+			       unsigned len)
+{
+	const struct macvlan_dev *vlan = netdev_priv(dev);
+	struct net_device *lowerdev = vlan->lowerdev;
+
+	return lowerdev->hard_header(skb, lowerdev, type, daddr,
+				     saddr ? : dev->dev_addr, len);
+}
+
+static int macvlan_open(struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct macvlan_port *port = vlan->port;
+	struct net_device *lowerdev = vlan->lowerdev;
+	int err;
+
+	err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN);
+	if (err < 0)
+		return err;
+	if (dev->flags & IFF_ALLMULTI)
+		dev_set_allmulti(lowerdev, 1);
+
+	hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[dev->dev_addr[5]]);
+	return 0;
+}
+
+static int macvlan_stop(struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct net_device *lowerdev = vlan->lowerdev;
+
+	dev_mc_unsync(lowerdev, dev);
+	if (dev->flags & IFF_ALLMULTI)
+		dev_set_allmulti(lowerdev, -1);
+
+	dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN);
+
+	hlist_del_rcu(&vlan->hlist);
+	synchronize_rcu();
+	return 0;
+}
+
+static void macvlan_change_rx_flags(struct net_device *dev, int change)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct net_device *lowerdev = vlan->lowerdev;
+
+	if (change & IFF_ALLMULTI)
+		dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
+
+static void macvlan_set_multicast_list(struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	dev_mc_sync(vlan->lowerdev, dev);
+}
+
+static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu)
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+/*
+ * macvlan network devices have devices nesting below it and are a special
+ * "super class" of normal network devices; split their locks off into a
+ * separate class since they always nest.
+ */
+static struct lock_class_key macvlan_netdev_xmit_lock_key;
+
+#define MACVLAN_FEATURES \
+	(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
+	 NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
+	 NETIF_F_TSO_ECN | NETIF_F_TSO6)
+
+#define MACVLAN_STATE_MASK \
+	((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
+
+static int macvlan_init(struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	const struct net_device *lowerdev = vlan->lowerdev;
+
+	dev->state		= (dev->state & ~MACVLAN_STATE_MASK) |
+				  (lowerdev->state & MACVLAN_STATE_MASK);
+	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
+	dev->iflink		= lowerdev->ifindex;
+
+	lockdep_set_class(&dev->_xmit_lock, &macvlan_netdev_xmit_lock_key);
+	return 0;
+}
+
+static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
+					struct ethtool_drvinfo *drvinfo)
+{
+	snprintf(drvinfo->driver, 32, "macvlan");
+	snprintf(drvinfo->version, 32, "0.1");
+}
+
+static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev)
+{
+	const struct macvlan_dev *vlan = netdev_priv(dev);
+	struct net_device *lowerdev = vlan->lowerdev;
+
+	if (lowerdev->ethtool_ops->get_rx_csum == NULL)
+		return 0;
+	return lowerdev->ethtool_ops->get_rx_csum(lowerdev);
+}
+
+static const struct ethtool_ops macvlan_ethtool_ops = {
+	.get_link		= ethtool_op_get_link,
+	.get_rx_csum		= macvlan_ethtool_get_rx_csum,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.get_tso		= ethtool_op_get_tso,
+	.get_ufo		= ethtool_op_get_ufo,
+	.get_sg			= ethtool_op_get_sg,
+	.get_drvinfo		= macvlan_ethtool_get_drvinfo,
+};
+
+static void macvlan_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+
+	dev->init		= macvlan_init;
+	dev->open		= macvlan_open;
+	dev->stop		= macvlan_stop;
+	dev->change_mtu		= macvlan_change_mtu;
+	dev->change_rx_flags	= macvlan_change_rx_flags;
+	dev->set_multicast_list	= macvlan_set_multicast_list;
+	dev->hard_header	= macvlan_hard_header;
+	dev->hard_start_xmit	= macvlan_hard_start_xmit;
+	dev->destructor		= free_netdev;
+	dev->ethtool_ops	= &macvlan_ethtool_ops;
+	dev->tx_queue_len	= 0;
+}
+
+static int macvlan_port_create(struct net_device *dev)
+{
+	struct macvlan_port *port;
+	unsigned int i;
+
+	if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK)
+		return -EINVAL;
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	if (port == NULL)
+		return -ENOMEM;
+
+	port->dev = dev;
+	INIT_LIST_HEAD(&port->vlans);
+	for (i = 0; i < MACVLAN_HASH_SIZE; i++)
+		INIT_HLIST_HEAD(&port->vlan_hash[i]);
+	rcu_assign_pointer(dev->macvlan_port, port);
+	return 0;
+}
+
+static void macvlan_port_destroy(struct net_device *dev)
+{
+	struct macvlan_port *port = dev->macvlan_port;
+
+	rcu_assign_pointer(dev->macvlan_port, NULL);
+	synchronize_rcu();
+	kfree(port);
+}
+
+static void macvlan_transfer_operstate(struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	const struct net_device *lowerdev = vlan->lowerdev;
+
+	if (lowerdev->operstate == IF_OPER_DORMANT)
+		netif_dormant_on(dev);
+	else
+		netif_dormant_off(dev);
+
+	if (netif_carrier_ok(lowerdev)) {
+		if (!netif_carrier_ok(dev))
+			netif_carrier_on(dev);
+	} else {
+		if (netif_carrier_ok(lowerdev))
+			netif_carrier_off(dev);
+	}
+}
+
+static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+	if (tb[IFLA_ADDRESS]) {
+		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+			return -EINVAL;
+		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+			return -EADDRNOTAVAIL;
+	}
+	return 0;
+}
+
+static int macvlan_newlink(struct net_device *dev,
+			   struct nlattr *tb[], struct nlattr *data[])
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct macvlan_port *port;
+	struct net_device *lowerdev;
+	int err;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+
+	lowerdev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK]));
+	if (lowerdev == NULL)
+		return -ENODEV;
+
+	if (!tb[IFLA_MTU])
+		dev->mtu = lowerdev->mtu;
+	else if (dev->mtu > lowerdev->mtu)
+		return -EINVAL;
+
+	if (!tb[IFLA_ADDRESS])
+		random_ether_addr(dev->dev_addr);
+
+	if (lowerdev->macvlan_port == NULL) {
+		err = macvlan_port_create(lowerdev);
+		if (err < 0)
+			return err;
+	}
+	port = lowerdev->macvlan_port;
+
+	vlan->lowerdev = lowerdev;
+	vlan->dev      = dev;
+	vlan->port     = port;
+
+	err = register_netdevice(dev);
+	if (err < 0)
+		return err;
+
+	list_add_tail(&vlan->list, &port->vlans);
+	macvlan_transfer_operstate(dev);
+	return 0;
+}
+
+static void macvlan_dellink(struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct macvlan_port *port = vlan->port;
+
+	list_del(&vlan->list);
+	unregister_netdevice(dev);
+
+	if (list_empty(&port->vlans))
+		macvlan_port_destroy(dev);
+}
+
+static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
+	.kind		= "macvlan",
+	.priv_size	= sizeof(struct macvlan_dev),
+	.setup		= macvlan_setup,
+	.validate	= macvlan_validate,
+	.newlink	= macvlan_newlink,
+	.dellink	= macvlan_dellink,
+};
+
+static int macvlan_device_event(struct notifier_block *unused,
+				unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+	struct macvlan_dev *vlan, *next;
+	struct macvlan_port *port;
+
+	port = dev->macvlan_port;
+	if (port == NULL)
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_CHANGE:
+		list_for_each_entry(vlan, &port->vlans, list)
+			macvlan_transfer_operstate(vlan->dev);
+		break;
+	case NETDEV_FEAT_CHANGE:
+		list_for_each_entry(vlan, &port->vlans, list) {
+			vlan->dev->features = dev->features & MACVLAN_FEATURES;
+			netdev_features_change(vlan->dev);
+		}
+		break;
+	case NETDEV_UNREGISTER:
+		list_for_each_entry_safe(vlan, next, &port->vlans, list)
+			macvlan_dellink(vlan->dev);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block macvlan_notifier_block __read_mostly = {
+	.notifier_call	= macvlan_device_event,
+};
+
+static int __init macvlan_init_module(void)
+{
+	int err;
+
+	register_netdevice_notifier(&macvlan_notifier_block);
+	macvlan_handle_frame_hook = macvlan_handle_frame;
+
+	err = rtnl_link_register(&macvlan_link_ops);
+	if (err < 0)
+		goto err1;
+	return 0;
+err1:
+	macvlan_handle_frame_hook = macvlan_handle_frame;
+	unregister_netdevice_notifier(&macvlan_notifier_block);
+	return err;
+}
+
+static void __exit macvlan_cleanup_module(void)
+{
+	rtnl_link_unregister(&macvlan_link_ops);
+	macvlan_handle_frame_hook = NULL;
+	unregister_netdevice_notifier(&macvlan_notifier_block);
+}
+
+module_init(macvlan_init_module);
+module_exit(macvlan_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("Driver for MAC address based VLANs");
+MODULE_ALIAS_RTNL_LINK("macvlan");
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 0343ea1..92b403b 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -8,15 +8,16 @@
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
  */
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <linux/kernel.h> /* printk() */
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/errno.h>  /* error codes */
-#include <linux/types.h>  /* size_t */
-#include <linux/interrupt.h> /* mark_bh */
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
 
 #include <linux/in.h>
 #include <linux/in6.h>
@@ -33,7 +34,6 @@
 
 #include <asm/io.h>
 #include <asm/scatterlist.h>
-#include <linux/dma-mapping.h>
 
 #include "meth.h"
 
@@ -51,8 +51,6 @@
 
 
 static const char *meth_str="SGI O2 Fast Ethernet";
-MODULE_AUTHOR("Ilya Volynets <ilya@theIlya.com>");
-MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
 
 #define HAVE_TX_TIMEOUT
 /* The maximum time waited (in jiffies) before assuming a Tx failed. (400ms) */
@@ -784,15 +782,15 @@
 /*
  * The init function.
  */
-static struct net_device *meth_init(void)
+static int __init meth_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
 	struct meth_private *priv;
-	int ret;
+	int err;
 
 	dev = alloc_etherdev(sizeof(struct meth_private));
 	if (!dev)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	dev->open            = meth_open;
 	dev->stop            = meth_release;
@@ -808,11 +806,12 @@
 
 	priv = netdev_priv(dev);
 	spin_lock_init(&priv->meth_lock);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	ret = register_netdev(dev);
-	if (ret) {
+	err = register_netdev(dev);
+	if (err) {
 		free_netdev(dev);
-		return ERR_PTR(ret);
+		return err;
 	}
 
 	printk(KERN_INFO "%s: SGI MACE Ethernet rev. %d\n",
@@ -820,21 +819,44 @@
 	return 0;
 }
 
-static struct net_device *meth_dev;
+static int __exit meth_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+
+	unregister_netdev(dev);
+	free_netdev(dev);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver meth_driver = {
+	.probe	= meth_probe,
+	.remove	= __devexit_p(meth_remove),
+	.driver = {
+		.name	= "meth",
+	}
+};
 
 static int __init meth_init_module(void)
 {
-	meth_dev = meth_init();
-	if (IS_ERR(meth_dev))
-		return PTR_ERR(meth_dev);
-	return 0;
+	int err;
+
+	err = platform_driver_register(&meth_driver);
+	if (err)
+		printk(KERN_ERR "Driver registration failed\n");
+
+	return err;
 }
 
 static void __exit meth_exit_module(void)
 {
-	unregister_netdev(meth_dev);
-	free_netdev(meth_dev);
+	platform_driver_unregister(&meth_driver);
 }
 
 module_init(meth_init_module);
 module_exit(meth_exit_module);
+
+MODULE_AUTHOR("Ilya Volynets <ilya@theIlya.com>");
+MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 638a279..9853c74 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -240,7 +240,7 @@
 	 * TODO: probe for these or load them from PARAM
 	 */
 	netdev->base_addr = 0x4200;
-	netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
+	netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 +
 	              inl(mipsnet_reg_address(netdev, interruptInfo));
 
 	// Get the io region now, get irq on open()
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index dfbd580..f8d63d3 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -51,8 +51,8 @@
 
 	if (obj < bitmap->max) {
 		set_bit(obj, bitmap->table);
+		bitmap->last = (obj + 1) & (bitmap->max - 1);
 		obj |= bitmap->top;
-		bitmap->last = obj + 1;
 	} else
 		obj = -1;
 
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
index 437d78a..39253d0 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/mlx4/cq.c
@@ -61,7 +61,7 @@
 	__be32			solicit_producer_index;
 	__be32			consumer_index;
 	__be32			producer_index;
-	u8			reserved6[2];
+	u32			reserved6[2];
 	__be64			db_rec_addr;
 };
 
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 0f11adb..27a82ce 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -490,9 +490,11 @@
 
 	if (eq_table->have_irq)
 		free_irq(dev->pdev->irq, dev);
-	for (i = 0; i < MLX4_NUM_EQ; ++i)
+	for (i = 0; i < MLX4_EQ_CATAS; ++i)
 		if (eq_table->eq[i].have_irq)
 			free_irq(eq_table->eq[i].irq, eq_table->eq + i);
+	if (eq_table->eq[MLX4_EQ_CATAS].have_irq)
+		free_irq(eq_table->eq[MLX4_EQ_CATAS].irq, dev);
 }
 
 static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev)
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index c427173..c45cbe4 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -37,6 +37,12 @@
 #include "fw.h"
 #include "icm.h"
 
+enum {
+	MLX4_COMMAND_INTERFACE_MIN_REV		= 2,
+	MLX4_COMMAND_INTERFACE_MAX_REV		= 3,
+	MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS	= 3,
+};
+
 extern void __buggy_use_of_MLX4_GET(void);
 extern void __buggy_use_of_MLX4_PUT(void);
 
@@ -90,7 +96,7 @@
 	int i;
 
 	mlx4_dbg(dev, "DEV_CAP flags:\n");
-	for (i = 0; i < 32; ++i)
+	for (i = 0; i < ARRAY_SIZE(fname); ++i)
 		if (fname[i] && (flags & (1 << i)))
 			mlx4_dbg(dev, "    %s\n", fname[i]);
 }
@@ -103,6 +109,7 @@
 	u16 size;
 	u16 stat_rate;
 	int err;
+	int i;
 
 #define QUERY_DEV_CAP_OUT_SIZE		       0x100
 #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET		0x10
@@ -131,6 +138,7 @@
 #define QUERY_DEV_CAP_ACK_DELAY_OFFSET		0x35
 #define QUERY_DEV_CAP_MTU_WIDTH_OFFSET		0x36
 #define QUERY_DEV_CAP_VL_PORT_OFFSET		0x37
+#define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET		0x38
 #define QUERY_DEV_CAP_MAX_GID_OFFSET		0x3b
 #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET	0x3c
 #define QUERY_DEV_CAP_MAX_PKEY_OFFSET		0x3f
@@ -172,7 +180,6 @@
 
 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
 			   MLX4_CMD_TIME_CLASS_A);
-
 	if (err)
 		goto out;
 
@@ -212,18 +219,12 @@
 	dev_cap->max_rdma_global = 1 << (field & 0x3f);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
 	dev_cap->local_ca_ack_delay = field & 0x1f;
-	MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
-	dev_cap->max_mtu	= field >> 4;
-	dev_cap->max_port_width = field & 0xf;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
-	dev_cap->max_vl    = field >> 4;
 	dev_cap->num_ports = field & 0xf;
-	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
-	dev_cap->max_gids = 1 << (field & 0xf);
+	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
+	dev_cap->max_msg_sz = 1 << (field & 0x1f);
 	MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
 	dev_cap->stat_rate_support = stat_rate;
-	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
-	dev_cap->max_pkeys = 1 << (field & 0xf);
 	MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
 	dev_cap->reserved_uars = field >> 4;
@@ -300,6 +301,42 @@
 	MLX4_GET(dev_cap->max_icm_sz, outbox,
 		 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
 
+	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
+		for (i = 1; i <= dev_cap->num_ports; ++i) {
+			MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
+			dev_cap->max_vl[i]	   = field >> 4;
+			MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
+			dev_cap->max_mtu[i]	   = field >> 4;
+			dev_cap->max_port_width[i] = field & 0xf;
+			MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
+			dev_cap->max_gids[i]	   = 1 << (field & 0xf);
+			MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
+			dev_cap->max_pkeys[i]	   = 1 << (field & 0xf);
+		}
+	} else {
+#define QUERY_PORT_MTU_OFFSET			0x01
+#define QUERY_PORT_WIDTH_OFFSET			0x06
+#define QUERY_PORT_MAX_GID_PKEY_OFFSET		0x07
+#define QUERY_PORT_MAX_VL_OFFSET		0x0b
+
+		for (i = 1; i <= dev_cap->num_ports; ++i) {
+			err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT,
+					   MLX4_CMD_TIME_CLASS_B);
+			if (err)
+				goto out;
+
+			MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET);
+			dev_cap->max_mtu[i]	   = field & 0xf;
+			MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET);
+			dev_cap->max_port_width[i] = field & 0xf;
+			MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET);
+			dev_cap->max_gids[i]	   = 1 << (field >> 4);
+			dev_cap->max_pkeys[i]	   = 1 << (field & 0xf);
+			MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET);
+			dev_cap->max_vl[i]	   = field & 0xf;
+		}
+	}
+
 	if (dev_cap->bmme_flags & 1)
 		mlx4_dbg(dev, "Base MM extensions: yes "
 			 "(flags %d, rsvd L_Key %08x)\n",
@@ -334,8 +371,8 @@
 	mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
 		 dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz);
 	mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n",
-		 dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu,
-		 dev_cap->max_port_width);
+		 dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu[1],
+		 dev_cap->max_port_width[1]);
 	mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n",
 		 dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
 	mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
@@ -452,10 +489,12 @@
 	u32 *outbox;
 	int err = 0;
 	u64 fw_ver;
+	u16 cmd_if_rev;
 	u8 lg;
 
 #define QUERY_FW_OUT_SIZE             0x100
 #define QUERY_FW_VER_OFFSET            0x00
+#define QUERY_FW_CMD_IF_REV_OFFSET     0x0a
 #define QUERY_FW_MAX_CMD_OFFSET        0x0f
 #define QUERY_FW_ERR_START_OFFSET      0x30
 #define QUERY_FW_ERR_SIZE_OFFSET       0x38
@@ -477,21 +516,40 @@
 
 	MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET);
 	/*
-	 * FW subminor version is at more signifant bits than minor
+	 * FW subminor version is at more significant bits than minor
 	 * version, so swap here.
 	 */
 	dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) |
 		((fw_ver & 0xffff0000ull) >> 16) |
 		((fw_ver & 0x0000ffffull) << 16);
 
+	MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
+	if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV ||
+	    cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) {
+		mlx4_err(dev, "Installed FW has unsupported "
+			 "command interface revision %d.\n",
+			 cmd_if_rev);
+		mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n",
+			 (int) (dev->caps.fw_ver >> 32),
+			 (int) (dev->caps.fw_ver >> 16) & 0xffff,
+			 (int) dev->caps.fw_ver & 0xffff);
+		mlx4_err(dev, "This driver version supports only revisions %d to %d.\n",
+			 MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV);
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS)
+		dev->flags |= MLX4_FLAG_OLD_PORT_CMDS;
+
 	MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
 	cmd->max_cmds = 1 << lg;
 
-	mlx4_dbg(dev, "FW version %d.%d.%03d, max commands %d\n",
+	mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n",
 		 (int) (dev->caps.fw_ver >> 32),
 		 (int) (dev->caps.fw_ver >> 16) & 0xffff,
 		 (int) dev->caps.fw_ver & 0xffff,
-		 cmd->max_cmds);
+		 cmd_if_rev, cmd->max_cmds);
 
 	MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET);
 	MLX4_GET(fw->catas_size,   outbox, QUERY_FW_ERR_SIZE_OFFSET);
@@ -687,13 +745,15 @@
 	return err;
 }
 
-int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port)
+int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
 {
 	struct mlx4_cmd_mailbox *mailbox;
 	u32 *inbox;
 	int err;
 	u32 flags;
+	u16 field;
 
+	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
 #define INIT_PORT_IN_SIZE          256
 #define INIT_PORT_FLAGS_OFFSET     0x00
 #define INIT_PORT_FLAG_SIG         (1 << 18)
@@ -708,32 +768,32 @@
 #define INIT_PORT_NODE_GUID_OFFSET 0x18
 #define INIT_PORT_SI_GUID_OFFSET   0x20
 
-	mailbox = mlx4_alloc_cmd_mailbox(dev);
-	if (IS_ERR(mailbox))
-		return PTR_ERR(mailbox);
-	inbox = mailbox->buf;
+		mailbox = mlx4_alloc_cmd_mailbox(dev);
+		if (IS_ERR(mailbox))
+			return PTR_ERR(mailbox);
+		inbox = mailbox->buf;
 
-	memset(inbox, 0, INIT_PORT_IN_SIZE);
+		memset(inbox, 0, INIT_PORT_IN_SIZE);
 
-	flags = 0;
-	flags |= param->set_guid0     ? INIT_PORT_FLAG_G0  : 0;
-	flags |= param->set_node_guid ? INIT_PORT_FLAG_NG  : 0;
-	flags |= param->set_si_guid   ? INIT_PORT_FLAG_SIG : 0;
-	flags |= (param->vl_cap & 0xf) << INIT_PORT_VL_SHIFT;
-	flags |= (param->port_width_cap & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
-	MLX4_PUT(inbox, flags,            INIT_PORT_FLAGS_OFFSET);
+		flags = 0;
+		flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT;
+		flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
+		MLX4_PUT(inbox, flags,		  INIT_PORT_FLAGS_OFFSET);
 
-	MLX4_PUT(inbox, param->mtu,       INIT_PORT_MTU_OFFSET);
-	MLX4_PUT(inbox, param->max_gid,   INIT_PORT_MAX_GID_OFFSET);
-	MLX4_PUT(inbox, param->max_pkey,  INIT_PORT_MAX_PKEY_OFFSET);
-	MLX4_PUT(inbox, param->guid0,     INIT_PORT_GUID0_OFFSET);
-	MLX4_PUT(inbox, param->node_guid, INIT_PORT_NODE_GUID_OFFSET);
-	MLX4_PUT(inbox, param->si_guid,   INIT_PORT_SI_GUID_OFFSET);
+		field = 128 << dev->caps.mtu_cap[port];
+		MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET);
+		field = dev->caps.gid_table_len[port];
+		MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET);
+		field = dev->caps.pkey_table_len[port];
+		MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET);
 
-	err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
-		       MLX4_CMD_TIME_CLASS_A);
+		err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
+			       MLX4_CMD_TIME_CLASS_A);
 
-	mlx4_free_cmd_mailbox(dev, mailbox);
+		mlx4_free_cmd_mailbox(dev, mailbox);
+	} else
+		err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
+			       MLX4_CMD_TIME_CLASS_A);
 
 	return err;
 }
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 2616fa5..7e1dd9e 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -59,13 +59,14 @@
 	int max_responder_per_qp;
 	int max_rdma_global;
 	int local_ca_ack_delay;
-	int max_mtu;
-	int max_port_width;
-	int max_vl;
 	int num_ports;
-	int max_gids;
+	u32 max_msg_sz;
+	int max_mtu[MLX4_MAX_PORTS + 1];
+	int max_port_width[MLX4_MAX_PORTS + 1];
+	int max_vl[MLX4_MAX_PORTS + 1];
+	int max_gids[MLX4_MAX_PORTS + 1];
+	int max_pkeys[MLX4_MAX_PORTS + 1];
 	u16 stat_rate_support;
-	int max_pkeys;
 	u32 flags;
 	int reserved_uars;
 	int uar_size;
diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c
index 65854f9..9ae951b 100644
--- a/drivers/net/mlx4/intf.c
+++ b/drivers/net/mlx4/intf.c
@@ -135,9 +135,6 @@
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_interface *intf;
 
-	INIT_LIST_HEAD(&priv->ctx_list);
-	spin_lock_init(&priv->ctx_lock);
-
 	mutex_lock(&intf_mutex);
 
 	list_add_tail(&priv->dev_list, &dev_list);
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 20b8c0d..a4f2e04 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -88,6 +88,7 @@
 static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 {
 	int err;
+	int i;
 
 	err = mlx4_QUERY_DEV_CAP(dev, dev_cap);
 	if (err) {
@@ -117,11 +118,15 @@
 	}
 
 	dev->caps.num_ports	     = dev_cap->num_ports;
+	for (i = 1; i <= dev->caps.num_ports; ++i) {
+		dev->caps.vl_cap[i]	    = dev_cap->max_vl[i];
+		dev->caps.mtu_cap[i]	    = dev_cap->max_mtu[i];
+		dev->caps.gid_table_len[i]  = dev_cap->max_gids[i];
+		dev->caps.pkey_table_len[i] = dev_cap->max_pkeys[i];
+		dev->caps.port_width_cap[i] = dev_cap->max_port_width[i];
+	}
+
 	dev->caps.num_uars	     = dev_cap->uar_size / PAGE_SIZE;
-	dev->caps.vl_cap	     = dev_cap->max_vl;
-	dev->caps.mtu_cap	     = dev_cap->max_mtu;
-	dev->caps.gid_table_len	     = dev_cap->max_gids;
-	dev->caps.pkey_table_len     = dev_cap->max_pkeys;
 	dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay;
 	dev->caps.bf_reg_size	     = dev_cap->bf_reg_size;
 	dev->caps.bf_regs_per_page   = dev_cap->bf_regs_per_page;
@@ -148,8 +153,8 @@
 	dev->caps.reserved_mrws	     = dev_cap->reserved_mrws;
 	dev->caps.reserved_uars	     = dev_cap->reserved_uars;
 	dev->caps.reserved_pds	     = dev_cap->reserved_pds;
-	dev->caps.port_width_cap     = dev_cap->max_port_width;
 	dev->caps.mtt_entry_sz	     = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz;
+	dev->caps.max_msg_sz         = dev_cap->max_msg_sz;
 	dev->caps.page_size_cap	     = ~(u32) (dev_cap->min_page_sz - 1);
 	dev->caps.flags		     = dev_cap->flags;
 	dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
@@ -787,6 +792,8 @@
 
 	dev       = &priv->dev;
 	dev->pdev = pdev;
+	INIT_LIST_HEAD(&priv->ctx_list);
+	spin_lock_init(&priv->ctx_lock);
 
 	/*
 	 * Now reset the HCA before we touch the PCI capabilities or
@@ -905,6 +912,8 @@
 	{ PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */
 	{ PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */
 	{ PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */
+	{ PCI_VDEVICE(MELLANOX, 0x6732) }, /* MT25408 "Hermon" DDR PCIe gen2 */
+	{ PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */
 	{ 0, }
 };
 
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 3d3b6d2..d9c91a7 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -37,6 +37,7 @@
 #ifndef MLX4_H
 #define MLX4_H
 
+#include <linux/mutex.h>
 #include <linux/radix-tree.h>
 
 #include <linux/mlx4/device.h>
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index b33864d..d0808fa 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -324,15 +324,17 @@
 				       MLX4_MPT_FLAG_MIO	 |
 				       MLX4_MPT_FLAG_REGION	 |
 				       mr->access);
-	if (mr->mtt.order < 0)
-		mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
 
 	mpt_entry->key	       = cpu_to_be32(key_to_hw_index(mr->key));
 	mpt_entry->pd	       = cpu_to_be32(mr->pd);
 	mpt_entry->start       = cpu_to_be64(mr->iova);
 	mpt_entry->length      = cpu_to_be64(mr->size);
 	mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
-	mpt_entry->mtt_seg     = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt));
+	if (mr->mtt.order < 0) {
+		mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
+		mpt_entry->mtt_seg = 0;
+	} else
+		mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt));
 
 	err = mlx4_SW2HW_MPT(dev, mailbox,
 			     key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1));
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 7f8b7d5..19b48c7 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -113,8 +113,7 @@
 	struct mlx4_cmd_mailbox *mailbox;
 	int ret = 0;
 
-	if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
-	    new_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
+	if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE ||
 	    !op[cur_state][new_state])
 		return -EINVAL;
 
@@ -278,3 +277,24 @@
 	mlx4_CONF_SPECIAL_QP(dev, 0);
 	mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap);
 }
+
+int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
+		  struct mlx4_qp_context *context)
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	int err;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+
+	err = mlx4_cmd_box(dev, 0, mailbox->dma, qp->qpn, 0,
+			   MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A);
+	if (!err)
+		memcpy(context, mailbox->buf + 8, sizeof *context);
+
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_qp_query);
+
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c
index 2134f83..b061c86 100644
--- a/drivers/net/mlx4/srq.c
+++ b/drivers/net/mlx4/srq.c
@@ -102,6 +102,13 @@
 			MLX4_CMD_TIME_CLASS_B);
 }
 
+static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+			  int srq_num)
+{
+	return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ,
+			    MLX4_CMD_TIME_CLASS_A);
+}
+
 int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
 		   u64 db_rec, struct mlx4_srq *srq)
 {
@@ -205,6 +212,29 @@
 }
 EXPORT_SYMBOL_GPL(mlx4_srq_arm);
 
+int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark)
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_srq_context *srq_context;
+	int err;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+
+	srq_context = mailbox->buf;
+
+	err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn);
+	if (err)
+		goto err_out;
+	*limit_watermark = srq_context->limit_watermark;
+
+err_out:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_srq_query);
+
 int __devinit mlx4_init_srq_table(struct mlx4_dev *dev)
 {
 	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 5d14be7..deca653 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -60,6 +60,7 @@
 #include <linux/crc32.h>
 #include <linux/moduleparam.h>
 #include <linux/io.h>
+#include <linux/log2.h>
 #include <net/checksum.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -71,7 +72,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.3.0-1.233"
+#define MYRI10GE_VERSION_STR "1.3.1-1.248"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -279,6 +280,8 @@
 module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");
 
+static int myri10ge_reset_recover = 1;
+
 static int myri10ge_wcfifo = 0;
 module_param(myri10ge_wcfifo, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
@@ -1057,7 +1060,6 @@
 	struct myri10ge_tx_buf *tx = &mgp->tx;
 	struct sk_buff *skb;
 	int idx, len;
-	int limit = 0;
 
 	while (tx->pkt_done != mcp_index) {
 		idx = tx->done & tx->mask;
@@ -1088,11 +1090,6 @@
 							      bus), len,
 					       PCI_DMA_TODEVICE);
 		}
-
-		/* limit potential for livelock by only handling
-		 * 2 full tx rings per call */
-		if (unlikely(++limit > 2 * tx->mask))
-			break;
 	}
 	/* start the queue if we've stopped it */
 	if (netif_queue_stopped(mgp->dev)
@@ -1154,9 +1151,11 @@
 	struct mcp_irq_data *stats = mgp->fw_stats;
 
 	if (unlikely(stats->stats_updated)) {
-		if (mgp->link_state != stats->link_up) {
-			mgp->link_state = stats->link_up;
-			if (mgp->link_state) {
+		unsigned link_up = ntohl(stats->link_up);
+		if (mgp->link_state != link_up) {
+			mgp->link_state = link_up;
+
+			if (mgp->link_state == MXGEFW_LINK_UP) {
 				if (netif_msg_link(mgp))
 					printk(KERN_INFO
 					       "myri10ge: %s: link up\n",
@@ -1166,8 +1165,11 @@
 			} else {
 				if (netif_msg_link(mgp))
 					printk(KERN_INFO
-					       "myri10ge: %s: link down\n",
-					       mgp->dev->name);
+					       "myri10ge: %s: link %s\n",
+					       mgp->dev->name,
+					       (link_up == MXGEFW_LINK_MYRINET ?
+						"mismatch (Myrinet detected)" :
+						"down"));
 				netif_carrier_off(mgp->dev);
 				mgp->link_changes++;
 			}
@@ -1472,6 +1474,7 @@
 	.set_sg = ethtool_op_set_sg,
 	.get_tso = ethtool_op_get_tso,
 	.set_tso = ethtool_op_set_tso,
+	.get_link = ethtool_op_get_link,
 	.get_strings = myri10ge_get_strings,
 	.get_stats_count = myri10ge_get_stats_count,
 	.get_ethtool_stats = myri10ge_get_ethtool_stats,
@@ -1796,7 +1799,7 @@
 	 */
 	big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
 	if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) {
-		while ((big_pow2 & (big_pow2 - 1)) != 0)
+		while (!is_power_of_2(big_pow2))
 			big_pow2++;
 		mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
 	} else {
@@ -2729,8 +2732,14 @@
 		 * For now, just report it */
 		reboot = myri10ge_read_reboot(mgp);
 		printk(KERN_ERR
-		       "myri10ge: %s: NIC rebooted (0x%x), resetting\n",
-		       mgp->dev->name, reboot);
+		       "myri10ge: %s: NIC rebooted (0x%x),%s resetting\n",
+		       mgp->dev->name, reboot,
+		       myri10ge_reset_recover ? " " : " not");
+		if (myri10ge_reset_recover == 0)
+			return;
+
+		myri10ge_reset_recover--;
+
 		/*
 		 * A rebooted nic will come back with config space as
 		 * it was after power was applied to PCIe bus.
@@ -2840,6 +2849,8 @@
 		return -ENOMEM;
 	}
 
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
 	mgp = netdev_priv(netdev);
 	memset(mgp, 0, sizeof(*mgp));
 	mgp->dev = netdev;
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 4cf0d3f..6bb48ba 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -671,7 +671,7 @@
 #define NATSEMI_CREATE_FILE(_dev, _name) \
          device_create_file(&_dev->dev, &dev_attr_##_name)
 #define NATSEMI_REMOVE_FILE(_dev, _name) \
-         device_create_file(&_dev->dev, &dev_attr_##_name)
+         device_remove_file(&_dev->dev, &dev_attr_##_name)
 
 NATSEMI_ATTR(dspcfg_workaround);
 
@@ -690,7 +690,7 @@
 {
 	struct netdev_private *np = netdev_priv(to_net_dev(dev));
 	int new_setting;
-	u32 flags;
+	unsigned long flags;
 
         /* Find out the new setting */
         if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
@@ -2357,8 +2357,8 @@
 					np->rx_dma[entry],
 					buflen,
 					PCI_DMA_FROMDEVICE);
-				eth_copy_and_sum(skb,
-					np->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb,
+					np->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(np->pci_dev,
 					np->rx_dma[entry],
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 995c0a5..cfdeaf7 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -669,10 +669,15 @@
 static int ne2k_pci_resume (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
+	int rc;
 
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev);
-	pci_enable_device(pdev);
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
 	NS8390_init(dev, 1);
 	netif_device_attach(dev);
 
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index ad6688e..325269d 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -68,9 +68,10 @@
 #define _NETXEN_NIC_LINUX_SUBVERSION 2
 #define NETXEN_NIC_LINUX_VERSIONID  "3.4.2"
 
-#define NUM_FLASH_SECTORS (64)
-#define FLASH_SECTOR_SIZE (64 * 1024)
-#define FLASH_TOTAL_SIZE  (NUM_FLASH_SECTORS * FLASH_SECTOR_SIZE)
+#define NETXEN_NUM_FLASH_SECTORS (64)
+#define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
+#define NETXEN_FLASH_TOTAL_SIZE  (NETXEN_NUM_FLASH_SECTORS \
+					* NETXEN_FLASH_SECTOR_SIZE)
 
 #define PHAN_VENDOR_ID 0x4040
 
@@ -677,28 +678,28 @@
 
 /* Flash memory map */
 typedef enum {
-	CRBINIT_START = 0,	/* Crbinit section */
-	BRDCFG_START = 0x4000,	/* board config */
-	INITCODE_START = 0x6000,	/* pegtune code */
-	BOOTLD_START = 0x10000,	/* bootld */
-	IMAGE_START = 0x43000,	/* compressed image */
-	SECONDARY_START = 0x200000,	/* backup images */
-	PXE_START = 0x3E0000,	/* user defined region */
-	USER_START = 0x3E8000,	/* User defined region for new boards */
-	FIXED_START = 0x3F0000	/* backup of crbinit */
+	NETXEN_CRBINIT_START = 0,	/* Crbinit section */
+	NETXEN_BRDCFG_START = 0x4000,	/* board config */
+	NETXEN_INITCODE_START = 0x6000,	/* pegtune code */
+	NETXEN_BOOTLD_START = 0x10000,	/* bootld */
+	NETXEN_IMAGE_START = 0x43000,	/* compressed image */
+	NETXEN_SECONDARY_START = 0x200000,	/* backup images */
+	NETXEN_PXE_START = 0x3E0000,	/* user defined region */
+	NETXEN_USER_START = 0x3E8000,	/* User defined region for new boards */
+	NETXEN_FIXED_START = 0x3F0000	/* backup of crbinit */
 } netxen_flash_map_t;
 
-#define USER_START_OLD PXE_START	/* for backward compatibility */
+#define NETXEN_USER_START_OLD NETXEN_PXE_START	/* for backward compatibility */
 
-#define FLASH_START		(CRBINIT_START)
-#define INIT_SECTOR		(0)
-#define PRIMARY_START 		(BOOTLD_START)
-#define FLASH_CRBINIT_SIZE 	(0x4000)
-#define FLASH_BRDCFG_SIZE 	(sizeof(struct netxen_board_info))
-#define FLASH_USER_SIZE		(sizeof(struct netxen_user_info)/sizeof(u32))
-#define FLASH_SECONDARY_SIZE 	(USER_START-SECONDARY_START)
-#define NUM_PRIMARY_SECTORS	(0x20)
-#define NUM_CONFIG_SECTORS 	(1)
+#define NETXEN_FLASH_START		(NETXEN_CRBINIT_START)
+#define NETXEN_INIT_SECTOR		(0)
+#define NETXEN_PRIMARY_START 		(NETXEN_BOOTLD_START)
+#define NETXEN_FLASH_CRBINIT_SIZE 	(0x4000)
+#define NETXEN_FLASH_BRDCFG_SIZE 	(sizeof(struct netxen_board_info))
+#define NETXEN_FLASH_USER_SIZE		(sizeof(struct netxen_user_info)/sizeof(u32))
+#define NETXEN_FLASH_SECONDARY_SIZE 	(NETXEN_USER_START-NETXEN_SECONDARY_START)
+#define NETXEN_NUM_PRIMARY_SECTORS	(0x20)
+#define NETXEN_NUM_CONFIG_SECTORS 	(1)
 #define PFX "NetXen: "
 extern char netxen_nic_driver_name[];
 
@@ -936,6 +937,7 @@
 	struct netxen_ring_ctx *ctx_desc;
 	struct pci_dev *ctx_desc_pdev;
 	dma_addr_t ctx_desc_phys_addr;
+	int intr_scheme;
 	int (*enable_phy_interrupts) (struct netxen_adapter *);
 	int (*disable_phy_interrupts) (struct netxen_adapter *);
 	void (*handle_phy_intr) (struct netxen_adapter *);
@@ -950,6 +952,24 @@
 	int (*stop_port) (struct netxen_adapter *);
 };				/* netxen_adapter structure */
 
+/*
+ * NetXen dma watchdog control structure
+ *
+ *	Bit 0		: enabled => R/O: 1 watchdog active, 0 inactive
+ *	Bit 1		: disable_request => 1 req disable dma watchdog
+ *	Bit 2		: enable_request =>  1 req enable dma watchdog
+ *	Bit 3-31	: unused
+ */
+
+#define netxen_set_dma_watchdog_disable_req(config_word) \
+	_netxen_set_bits(config_word, 1, 1, 1)
+#define netxen_set_dma_watchdog_enable_req(config_word) \
+	_netxen_set_bits(config_word, 2, 1, 1)
+#define netxen_get_dma_watchdog_enabled(config_word) \
+	((config_word) & 0x1)
+#define netxen_get_dma_watchdog_disabled(config_word) \
+	(((config_word) >> 1) & 0x1)
+
 /* Max number of xmit producer threads that can run simultaneously */
 #define	MAX_XMIT_PRODUCERS		16
 
@@ -1029,8 +1049,8 @@
 /* Functions from netxen_nic_init.c */
 void netxen_free_adapter_offload(struct netxen_adapter *adapter);
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
-void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
-void netxen_load_firmware(struct netxen_adapter *adapter);
+int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
+int netxen_load_firmware(struct netxen_adapter *adapter);
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
 int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
 int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, 
@@ -1048,6 +1068,7 @@
 int netxen_do_rom_se(struct netxen_adapter *adapter, int addr);
 
 /* Functions from netxen_nic_isr.c */
+int netxen_nic_link_ok(struct netxen_adapter *adapter);
 void netxen_nic_isr_other(struct netxen_adapter *adapter);
 void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 link);
 void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable);
@@ -1076,40 +1097,6 @@
 int netxen_nic_set_mac(struct net_device *netdev, void *p);
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
 
-static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
-{
-	/*
-	 * ISR_INT_MASK: Can be read from window 0 or 1.
-	 */
-	writel(0x7ff, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
-
-}
-
-static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
-{
-	u32 mask;
-
-	switch (adapter->ahw.board_type) {
-	case NETXEN_NIC_GBE:
-		mask = 0x77b;
-		break;
-	case NETXEN_NIC_XGBE:
-		mask = 0x77f;
-		break;
-	default:
-		mask = 0x7ff;
-		break;
-	}
-
-	writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
-
-	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
-		mask = 0xbff;
-		writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
-		writel(mask, PCI_OFFSET_SECOND_RANGE(adapter,
-						     ISR_INT_TARGET_MASK));
-	}
-}
 
 /*
  * NetXen Board information
@@ -1162,6 +1149,62 @@
 		name = "Unknown";
 }
 
+static inline int
+dma_watchdog_shutdown_request(struct netxen_adapter *adapter)
+{
+	u32 ctrl;
+
+	/* check if already inactive */
+	if (netxen_nic_hw_read_wx(adapter,
+	    NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
+		printk(KERN_ERR "failed to read dma watchdog status\n");
+
+	if (netxen_get_dma_watchdog_enabled(ctrl) == 0)
+		return 1;
+
+	/* Send the disable request */
+	netxen_set_dma_watchdog_disable_req(ctrl);
+	netxen_crb_writelit_adapter(adapter,
+		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
+
+	return 0;
+}
+
+static inline int
+dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter)
+{
+	u32 ctrl;
+
+	if (netxen_nic_hw_read_wx(adapter,
+	    NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
+		printk(KERN_ERR "failed to read dma watchdog status\n");
+
+	return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) &&
+		(netxen_get_dma_watchdog_disabled(ctrl) == 0));
+}
+
+static inline int
+dma_watchdog_wakeup(struct netxen_adapter *adapter)
+{
+	u32 ctrl;
+
+	if (netxen_nic_hw_read_wx(adapter,
+		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
+		printk(KERN_ERR "failed to read dma watchdog status\n");
+
+	if (netxen_get_dma_watchdog_enabled(ctrl))
+		return 1;
+
+	/* send the wakeup request */
+	netxen_set_dma_watchdog_enable_req(ctrl);
+
+	netxen_crb_writelit_adapter(adapter,
+		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
+
+	return 0;
+}
+
+
 int netxen_is_flash_supported(struct netxen_adapter *adapter);
 int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]);
 extern void netxen_change_ringparam(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 16fabb3..0175f6c 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -94,7 +94,7 @@
 
 static int netxen_nic_get_eeprom_len(struct net_device *dev)
 {
-	return FLASH_TOTAL_SIZE;
+	return NETXEN_FLASH_TOTAL_SIZE;
 }
 
 static void
@@ -470,7 +470,7 @@
 		return 0;
 	}
 
-	if (offset == BOOTLD_START) {
+	if (offset == NETXEN_BOOTLD_START) {
 		ret = netxen_flash_erase_primary(adapter);
 		if (ret != FLASH_SUCCESS) {
 			printk(KERN_ERR "%s: Flash erase failed.\n", 
@@ -478,10 +478,10 @@
 			return ret;
 		}
 
-		ret = netxen_rom_se(adapter, USER_START);
+		ret = netxen_rom_se(adapter, NETXEN_USER_START);
 		if (ret != FLASH_SUCCESS)
 			return ret;
-		ret = netxen_rom_se(adapter, FIXED_START);
+		ret = netxen_rom_se(adapter, NETXEN_FIXED_START);
 		if (ret != FLASH_SUCCESS)
 			return ret;
 
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 608e37b..3276866 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -687,4 +687,6 @@
 
 #define PCIE_MAX_MASTER_SPLIT	(0x14048)
 
+#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL		(0x14)
+
 #endif				/* __NETXEN_NIC_HDR_H_ */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index baff17a..aac1542 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -257,7 +257,7 @@
 #define ADDR_IN_RANGE(addr, low, high)	\
 	(((addr) <= (high)) && ((addr) >= (low)))
 
-#define NETXEN_FLASH_BASE	(BOOTLD_START)
+#define NETXEN_FLASH_BASE	(NETXEN_BOOTLD_START)
 #define NETXEN_PHANTOM_MEM_BASE	(NETXEN_FLASH_BASE)
 #define NETXEN_MAX_MTU		8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
 #define NETXEN_MIN_MTU		64
@@ -377,7 +377,7 @@
 						   recv_crb_registers[ctx].
 						   crb_rcvpeg_state));
 		while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
-			udelay(100);
+			msleep(1);
 			/* Window 1 call */
 			state = readl(NETXEN_CRB_NORMALIZE(adapter,
 							   recv_crb_registers
@@ -392,7 +392,11 @@
 			return err;
 		}
 	}
-	DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n");
+	adapter->intr_scheme = readl(
+		NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
+	printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name,
+			adapter->intr_scheme);
+	DPRINTK(INFO, "Receive Peg ready too. starting stuff\n");
 
 	addr = netxen_alloc(adapter->ahw.pdev,
 			    sizeof(struct netxen_ring_ctx) +
@@ -611,7 +615,7 @@
 	u32 *pmac = (u32 *) & mac[0];
 
 	if (netxen_get_flash_block(adapter,
-				   USER_START +
+				   NETXEN_USER_START +
 				   offsetof(struct netxen_new_user_info,
 					    mac_addr),
 				   FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
@@ -619,7 +623,7 @@
 	}
 	if (*mac == ~0ULL) {
 		if (netxen_get_flash_block(adapter,
-					   USER_START_OLD +
+					   NETXEN_USER_START_OLD +
 					   offsetof(struct netxen_user_old_info,
 						    mac_addr),
 					   FLASH_NUM_PORTS * sizeof(u64),
@@ -697,7 +701,7 @@
 		adapter->curr_window = 0;
 }
 
-void netxen_load_firmware(struct netxen_adapter *adapter)
+int netxen_load_firmware(struct netxen_adapter *adapter)
 {
 	int i;
 	u32 data, size = 0;
@@ -709,15 +713,24 @@
 	writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
 
 	for (i = 0; i < size; i++) {
-		if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
-			DPRINTK(ERR,
-				"Error in netxen_rom_fast_read(). Will skip"
-				"loading flash image\n");
-			return;
-		}
+		int retries = 10;
+		if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
+			return -EIO;
+
 		off = netxen_nic_pci_set_window(adapter, memaddr);
 		addr = pci_base_offset(adapter, off);
 		writel(data, addr);
+		do {
+			if (readl(addr) == data)
+				break;
+			msleep(100);
+			writel(data, addr);
+		} while (--retries);
+		if (!retries) {
+			printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n",
+					netxen_nic_driver_name, memaddr);
+			return -EIO;
+		}
 		flashaddr += 4;
 		memaddr += 4;
 	}
@@ -727,7 +740,7 @@
 	       NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
 	writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
 
-	udelay(100);
+	return 0;
 }
 
 int
@@ -942,7 +955,7 @@
 int
 netxen_nic_erase_pxe(struct netxen_adapter *adapter)
 {
-	if (netxen_rom_fast_write(adapter, PXE_START, 0) == -1) {
+	if (netxen_rom_fast_write(adapter, NETXEN_PXE_START, 0) == -1) {
 		printk(KERN_ERR "%s: erase pxe failed\n", 
 			netxen_nic_driver_name);
 		return -1;
@@ -953,7 +966,7 @@
 int netxen_nic_get_board_info(struct netxen_adapter *adapter)
 {
 	int rv = 0;
-	int addr = BRDCFG_START;
+	int addr = NETXEN_BRDCFG_START;
 	struct netxen_board_info *boardinfo;
 	int index;
 	u32 *ptr32;
@@ -1115,7 +1128,7 @@
 	u32 fw_build = 0;
 	char brd_name[NETXEN_MAX_SHORT_NAME];
 	struct netxen_new_user_info user_info;
-	int i, addr = USER_START;
+	int i, addr = NETXEN_USER_START;
 	__le32 *ptr32;
 
 	struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index a368924..1811bcb 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -139,6 +139,8 @@
 		return err;
 	}
 	/* Window 1 call */
+	writel(INTR_SCHEME_PERPORT,
+	       NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST));
 	writel(MPORT_MULTI_FUNCTION_MODE,
 	       NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
 	writel(PHAN_INITIALIZE_ACK,
@@ -405,10 +407,7 @@
 static inline int
 do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
 {
-	if (jiffies > (last_schedule_time + (8 * HZ))) {
-		last_schedule_time = jiffies;
-		schedule();
-	}
+	cond_resched();
 
 	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
 	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
@@ -585,7 +584,7 @@
 {
 	int ret = FLASH_SUCCESS;
 	int val;
-	char *buffer = kmalloc(FLASH_SECTOR_SIZE, GFP_KERNEL);
+	char *buffer = kmalloc(NETXEN_FLASH_SECTOR_SIZE, GFP_KERNEL);
 
 	if (!buffer)
 		return -ENOMEM;	
@@ -601,13 +600,13 @@
 		goto out_kfree;
 
 	/* copy  sector 0 to sector 63 */
-	ret = netxen_rom_fast_read_words(adapter, CRBINIT_START, 
-						buffer, FLASH_SECTOR_SIZE);
+	ret = netxen_rom_fast_read_words(adapter, NETXEN_CRBINIT_START, 
+					buffer, NETXEN_FLASH_SECTOR_SIZE);
 	if (ret != FLASH_SUCCESS)
 		goto out_kfree;
 
-	ret = netxen_rom_fast_write_words(adapter, FIXED_START, 
-						buffer, FLASH_SECTOR_SIZE);
+	ret = netxen_rom_fast_write_words(adapter, NETXEN_FIXED_START, 
+					buffer, NETXEN_FLASH_SECTOR_SIZE);
 	if (ret != FLASH_SUCCESS)
 		goto out_kfree;
 
@@ -654,7 +653,8 @@
 	int count = 0, erased_errors = 0;
 	int range;
 
-	range = (addr == USER_START) ? FIXED_START : addr + FLASH_SECTOR_SIZE;
+	range = (addr == NETXEN_USER_START) ? 
+		NETXEN_FIXED_START : addr + NETXEN_FLASH_SECTOR_SIZE;
 	
 	for (i = addr; i < range; i += 4) {
 		netxen_rom_fast_read(adapter, i, &val);
@@ -689,7 +689,7 @@
 	int i;
 
 	for (i = start; i < end; i++) {
-		ret = netxen_rom_se(adapter, i * FLASH_SECTOR_SIZE);
+		ret = netxen_rom_se(adapter, i * NETXEN_FLASH_SECTOR_SIZE);
 		if (ret)
 			break;
 		ret = netxen_rom_wip_poll(adapter);
@@ -706,8 +706,8 @@
 	int ret = FLASH_SUCCESS;
 	int start, end;
 
-	start = SECONDARY_START / FLASH_SECTOR_SIZE;
-	end   = USER_START / FLASH_SECTOR_SIZE;
+	start = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE;
+	end   = NETXEN_USER_START / NETXEN_FLASH_SECTOR_SIZE;
 	ret = netxen_flash_erase_sections(adapter, start, end);
 
 	return ret;
@@ -719,8 +719,8 @@
 	int ret = FLASH_SUCCESS;
 	int start, end;
 
-	start = PRIMARY_START / FLASH_SECTOR_SIZE;
-	end   = SECONDARY_START / FLASH_SECTOR_SIZE;
+	start = NETXEN_PRIMARY_START / NETXEN_FLASH_SECTOR_SIZE;
+	end   = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE;
 	ret = netxen_flash_erase_sections(adapter, start, end);
 
 	return ret;
@@ -853,10 +853,10 @@
 				netxen_nic_pci_change_crbwindow(adapter, 1);
 			}
 			if (init_delay == 1) {
-				ssleep(1);
+				msleep(2000);
 				init_delay = 0;
 			}
-			msleep(1);
+			msleep(20);
 		}
 		kfree(buf);
 
@@ -932,10 +932,6 @@
 void netxen_free_adapter_offload(struct netxen_adapter *adapter)
 {
 	if (adapter->dummy_dma.addr) {
-		writel(0, NETXEN_CRB_NORMALIZE(adapter,
-			CRB_HOST_DUMMY_BUF_ADDR_HI));
-		writel(0, NETXEN_CRB_NORMALIZE(adapter,
-			CRB_HOST_DUMMY_BUF_ADDR_LO));
 		pci_free_consistent(adapter->ahw.pdev,
 				    NETXEN_HOST_DUMMY_DMA_SIZE,
 				    adapter->dummy_dma.addr,
@@ -944,25 +940,32 @@
 	}
 }
 
-void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
+int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
 {
 	u32 val = 0;
-	int loops = 0;
+	int retries = 30;
 
 	if (!pegtune_val) {
-		val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
-		while (val != PHAN_INITIALIZE_COMPLETE && 
-			val != PHAN_INITIALIZE_ACK && loops < 200000) {
-			udelay(100);
-			schedule();
-			val =
-			    readl(NETXEN_CRB_NORMALIZE
+		do {
+			val = readl(NETXEN_CRB_NORMALIZE
 				  (adapter, CRB_CMDPEG_STATE));
-			loops++;
+			pegtune_val = readl(NETXEN_CRB_NORMALIZE
+				  (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+
+			if (val == PHAN_INITIALIZE_COMPLETE ||
+				val == PHAN_INITIALIZE_ACK)
+				return 0;
+
+			msleep(1000);
+		} while (--retries);
+		if (!retries) {
+			printk(KERN_WARNING "netxen_phantom_init: init failed, "
+					"pegtune_val=%x\n", pegtune_val);
+			return -1;
 		}
-		if (val != PHAN_INITIALIZE_COMPLETE)
-			printk("WARNING: Initial boot wait loop failed...\n");
 	}
+
+	return 0;
 }
 
 int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
@@ -1036,18 +1039,23 @@
 	if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
 		return;
 
-	netdev = adapter->netdev;
-	if ((netif_running(netdev)) && !netif_carrier_ok(netdev)) {
-		printk(KERN_INFO "%s port %d, %s carrier is now ok\n",
-		       netxen_nic_driver_name, adapter->portnum, netdev->name);
-		netif_carrier_on(netdev);
-	}
-
-	if (netif_queue_stopped(netdev))
-		netif_wake_queue(netdev);
-
 	if (adapter->handle_phy_intr)
 		adapter->handle_phy_intr(adapter);
+
+	netdev = adapter->netdev;
+	if ((netif_running(netdev)) && !netif_carrier_ok(netdev) &&
+			netxen_nic_link_ok(adapter) ) {
+		printk(KERN_INFO "%s %s (port %d), Link is up\n",
+			       netxen_nic_driver_name, netdev->name, adapter->portnum);
+		netif_carrier_on(netdev);
+		netif_wake_queue(netdev);
+	} else if(!(netif_running(netdev)) && netif_carrier_ok(netdev)) {
+		printk(KERN_ERR "%s %s Link is Down\n",
+				netxen_nic_driver_name, netdev->name);
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+	}
+
 	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
 }
 
@@ -1114,6 +1122,7 @@
 		adapter->stats.csummed++;
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	}
+	skb->dev = netdev;
 	if (desc_ctx == RCV_DESC_LRO_CTXID) {
 		/* True length was only available on the last pkt */
 		skb_put(skb, buffer->lro_length);
@@ -1218,6 +1227,7 @@
 		       NETXEN_CRB_NORMALIZE(adapter,
 					    recv_crb_registers[adapter->portnum].
 					    crb_rcv_status_consumer));
+		wmb();
 	}
 
 	return count;
@@ -1270,11 +1280,13 @@
 		if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) {
 			pci_unmap_single(pdev, frag->dma, frag->length,
 					 PCI_DMA_TODEVICE);
+			frag->dma = 0ULL;
 			for (i = 1; i < buffer->frag_count; i++) {
 				DPRINTK(INFO, "getting fragment no %d\n", i);
 				frag++;	/* Get the next frag */
 				pci_unmap_page(pdev, frag->dma, frag->length,
 					       PCI_DMA_TODEVICE);
+				frag->dma = 0ULL;
 			}
 
 			adapter->stats.skbfreed++;
@@ -1440,6 +1452,7 @@
 			writel(msg,
 			       DB_NORMALIZE(adapter,
 					    NETXEN_RCV_PRODUCER_OFFSET));
+			wmb();
 		}
 	}
 }
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
index b213b06..b2de6b6 100644
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ b/drivers/net/netxen/netxen_nic_isr.c
@@ -169,6 +169,24 @@
 	netxen_nic_isr_other(adapter);
 }
 
+int netxen_nic_link_ok(struct netxen_adapter *adapter)
+{
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		return ((adapter->ahw.qg_linksup) & 1);
+
+	case NETXEN_NIC_XGBE:
+		return ((adapter->ahw.xg_linkup) & 1);
+
+	default:
+		printk(KERN_ERR"%s: Function: %s, Unknown board type\n",
+			netxen_nic_driver_name, __FUNCTION__);
+		break;
+	}
+
+	return 0;
+}
+
 void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -183,6 +201,10 @@
 		printk(KERN_INFO "%s: %s NIC Link is down\n",
 		       netxen_nic_driver_name, netdev->name);
 		adapter->ahw.xg_linkup = 0;
+		if (netif_running(netdev)) {
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
 		/* read twice to clear sticky bits */
 		/* WINDOW = 0 */
 		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1);
@@ -196,5 +218,7 @@
 		printk(KERN_INFO "%s: %s NIC Link is up\n",
 		       netxen_nic_driver_name, netdev->name);
 		adapter->ahw.xg_linkup = 1;
+		netif_carrier_on(netdev);
+		netif_wake_queue(netdev);
 	}
 }
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 2c5c6d2..b703ccf 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -54,8 +54,6 @@
 #define NETXEN_ADAPTER_UP_MAGIC 777
 #define NETXEN_NIC_PEG_TUNE 0
 
-u8 nx_p2_id = NX_P2_C0;
-
 #define DMA_32BIT_MASK	0x00000000ffffffffULL
 #define DMA_35BIT_MASK	0x00000007ffffffffULL
 
@@ -156,6 +154,103 @@
 #define	ADAPTER_LIST_SIZE 12
 int netxen_cards_found;
 
+static void netxen_nic_disable_int(struct netxen_adapter *adapter)
+{
+	uint32_t	mask = 0x7ff;
+	int retries = 32;
+
+	DPRINTK(1, INFO, "Entered ISR Disable \n");
+
+	switch (adapter->portnum) {
+	case 0:
+		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+		break;
+	case 1:
+		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+		break;
+	case 2:
+		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+		break;
+	case 3:
+		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+		break;
+	}
+
+	if (adapter->intr_scheme != -1 &&
+	    adapter->intr_scheme != INTR_SCHEME_PERPORT)
+		writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+
+	/* Window = 0 or 1 */
+	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+		do {
+			writel(0xffffffff,
+			       PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS));
+			mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+			if (!(mask & 0x80))
+				break;
+			udelay(10);
+		} while (--retries);
+
+		if (!retries) {
+			printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
+					netxen_nic_driver_name);
+		}
+	}
+
+	DPRINTK(1, INFO, "Done with Disable Int\n");
+}
+
+static void netxen_nic_enable_int(struct netxen_adapter *adapter)
+{
+	u32 mask;
+
+	DPRINTK(1, INFO, "Entered ISR Enable \n");
+
+	if (adapter->intr_scheme != -1 &&
+		adapter->intr_scheme != INTR_SCHEME_PERPORT) {
+		switch (adapter->ahw.board_type) {
+		case NETXEN_NIC_GBE:
+			mask  =  0x77b;
+			break;
+		case NETXEN_NIC_XGBE:
+			mask  =  0x77f;
+			break;
+		default:
+			mask  =  0x7ff;
+			break;
+		}
+
+		writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+	}
+
+	switch (adapter->portnum) {
+	case 0:
+		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+		break;
+	case 1:
+		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+		break;
+	case 2:
+		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+		break;
+	case 3:
+		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+		break;
+	}
+
+	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+		mask = 0xbff;
+		if (adapter->intr_scheme != -1 &&
+			adapter->intr_scheme != INTR_SCHEME_PERPORT) {
+			writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+		}
+		writel(mask,
+		       PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK));
+	}
+
+	DPRINTK(1, INFO, "Done with enable Int\n");
+}
+
 /*
  * netxen_nic_probe()
  *
@@ -210,8 +305,7 @@
 		goto err_out_disable_pdev;
 
 	pci_set_master(pdev);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id);
-	if (nx_p2_id == NX_P2_C1 &&
+	if (pdev->revision == NX_P2_C1 &&
 	    (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
 	    (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
 		pci_using_dac = 1;
@@ -308,7 +402,13 @@
 
 	adapter->netdev  = netdev;
 	adapter->pdev    = pdev;
+
+	/* this will be read from FW later */
+	adapter->intr_scheme = -1;
+
+	/* This will be reset for mezz cards  */
 	adapter->portnum = pci_func_id;
+	adapter->status   &= ~NETXEN_NETDEV_STATUS;
 
 	netdev->open		   = netxen_nic_open;
 	netdev->stop		   = netxen_nic_close;
@@ -336,11 +436,9 @@
 	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
-	if (pci_enable_msi(pdev)) {
+	if (pci_enable_msi(pdev))
 		adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
-		printk(KERN_WARNING "%s: unable to allocate MSI interrupt"
-		       " error\n", netxen_nic_driver_name);
-	} else
+	else
 		adapter->flags |= NETXEN_NIC_MSI_ENABLED;
 
 	netdev->irq = pdev->irq;
@@ -355,13 +453,6 @@
 	/* initialize the adapter */
 	netxen_initialize_adapter_hw(adapter);
 
-#ifdef CONFIG_PPC
-	if ((adapter->ahw.boardcfg.board_type ==
-		NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) &&
-			(pci_func_id == 2))
-		    goto err_out_free_adapter;
-#endif /* CONFIG_PPC */
-
 	/*
 	 *  Adapter in our case is quad port so initialize it before
 	 *  initializing the ports
@@ -458,7 +549,7 @@
 	INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
 	adapter->ahw.pdev = pdev;
 	adapter->proc_cmd_buf_counter = 0;
-	adapter->ahw.revision_id = nx_p2_id;
+	adapter->ahw.revision_id = pdev->revision;
 
 	/* make sure Window == 1 */
 	netxen_nic_pci_change_crbwindow(adapter, 1);
@@ -509,22 +600,30 @@
 					NETXEN_CAM_RAM(0x1fc)));
 		if (val == 0x55555555) {
 		    /* This is the first boot after power up */
+		    netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
+			if (!(val & 0x4)) {
+				val |= 0x4;
+				netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val);
+				netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
+				if (!(val & 0x4))
+					printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n",
+							netxen_nic_driver_name);
+			}
 		    val = readl(NETXEN_CRB_NORMALIZE(adapter,
 					NETXEN_ROMUSB_GLB_SW_RESET));
 		    printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val);
 		    if (val != 0x80000f) {
 			/* clear the register for future unloads/loads */
-			writel(0, NETXEN_CRB_NORMALIZE(adapter,
-						NETXEN_CAM_RAM(0x1fc)));
-			printk(KERN_ERR "ERROR in NetXen HW init sequence.\n");
-			err = -ENODEV;
-			goto err_out_free_dev;
+				writel(0, NETXEN_CRB_NORMALIZE(adapter,
+							NETXEN_CAM_RAM(0x1fc)));
+				printk(KERN_ERR "ERROR in NetXen HW init sequence.\n");
+				err = -ENODEV;
+				goto err_out_free_dev;
 		    }
-
-		    /* clear the register for future unloads/loads */
-		    writel(0, NETXEN_CRB_NORMALIZE(adapter, 
-					    NETXEN_CAM_RAM(0x1fc)));
 		}
+
+		/* clear the register for future unloads/loads */
+		writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
 		printk(KERN_INFO "State: 0x%0x\n",
 			readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
 
@@ -632,8 +731,8 @@
 	struct netxen_rx_buffer *buffer;
 	struct netxen_recv_context *recv_ctx;
 	struct netxen_rcv_desc_ctx *rcv_desc;
-	int i;
-	int ctxid, ring;
+	int i, ctxid, ring;
+	static int init_firmware_done = 0;
 
 	adapter = pci_get_drvdata(pdev);
 	if (adapter == NULL)
@@ -641,32 +740,20 @@
 
 	netdev = adapter->netdev;
 
-	netxen_nic_disable_int(adapter);
-	if (adapter->irq)
-		free_irq(adapter->irq, adapter);
-	
+	unregister_netdev(netdev);
+
 	if (adapter->stop_port)
 		adapter->stop_port(adapter);
 
-	if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
-		pci_disable_msi(pdev);
-
-	if (adapter->portnum == 0)
-		netxen_free_adapter_offload(adapter);
+	netxen_nic_disable_int(adapter);
 
 	if (adapter->irq)
 		free_irq(adapter->irq, adapter);
-	if(adapter->portnum == 0) {
-		/* leave the hw in the same state as reboot */
-		writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
-		netxen_pinit_from_rom(adapter, 0);
-		udelay(500);
-		netxen_load_firmware(adapter);
-		netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
-	}
 
-	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
+	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+		init_firmware_done++;
 		netxen_free_hw_resources(adapter);
+	}
 
 	for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
 		recv_ctx = &adapter->recv_ctx[ctxid];
@@ -686,17 +773,73 @@
 		}
 	}
 
-	unregister_netdev(netdev);
+	if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+		pci_disable_msi(pdev);
 
 	vfree(adapter->cmd_buf_arr);
 
+	pci_disable_device(pdev);
+
+	if (adapter->portnum == 0) {
+		if (init_firmware_done) {
+			dma_watchdog_shutdown_request(adapter);
+			msleep(100);
+			i = 100;
+			while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
+				printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
+				msleep(100);
+				i--;
+			}
+
+			if (i == 0) {
+				printk(KERN_ERR "dma_watchdog_shutdown_request failed\n");
+				return;
+			}
+
+			/* clear the register for future unloads/loads */
+			writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
+			printk(KERN_INFO "State: 0x%0x\n",
+				readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
+
+			/* leave the hw in the same state as reboot */
+			writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+			if (netxen_pinit_from_rom(adapter, 0))
+				return;
+			msleep(1);
+			if (netxen_load_firmware(adapter))
+				return;
+			netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+		}
+
+		/* clear the register for future unloads/loads */
+		writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
+		printk(KERN_INFO "State: 0x%0x\n",
+			readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
+
+		dma_watchdog_shutdown_request(adapter);
+		msleep(100);
+		i = 100;
+		while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
+			printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
+			msleep(100);
+			i--;
+		}
+
+		if (i) {
+			netxen_free_adapter_offload(adapter);
+		} else {
+			printk(KERN_ERR "failed to dma shutdown\n");
+			return;
+		}
+
+	}
+
 	iounmap(adapter->ahw.db_base);
 	iounmap(adapter->ahw.pci_base0);
 	iounmap(adapter->ahw.pci_base1);
 	iounmap(adapter->ahw.pci_base2);
 
 	pci_release_regions(pdev);
-	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 
 	free_netdev(netdev);
@@ -793,7 +936,7 @@
 		if (buffrag->dma) {
 			pci_unmap_single(adapter->pdev, buffrag->dma,
 					 buffrag->length, PCI_DMA_TODEVICE);
-			buffrag->dma = (u64) NULL;
+			buffrag->dma = 0ULL;
 		}
 		for (j = 0; j < cmd_buff->frag_count; j++) {
 			buffrag++;
@@ -801,7 +944,7 @@
 				pci_unmap_page(adapter->pdev, buffrag->dma,
 					       buffrag->length, 
 					       PCI_DMA_TODEVICE);
-				buffrag->dma = (u64) NULL;
+				buffrag->dma = 0ULL;
 			}
 		}
 		/* Free the skb we received in netxen_nic_xmit_frame */
@@ -811,8 +954,10 @@
 		}
 		cmd_buff++;
 	}
-	FLUSH_SCHEDULED_WORK();
-	del_timer_sync(&adapter->watchdog_timer);
+	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+		FLUSH_SCHEDULED_WORK();
+		del_timer_sync(&adapter->watchdog_timer);
+	}
 
 	return 0;
 }
@@ -1098,28 +1243,26 @@
 netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
 {
 	u32 ret = 0;
+	u32 our_int = 0;
 
 	DPRINTK(INFO, "Entered handle ISR\n");
 	adapter->stats.ints++;
 
 	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
-		int count = 0;
-		u32 mask;
-		u32 our_int = 0;
 		our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
 		/* not our interrupt */
 		if ((our_int & (0x80 << adapter->portnum)) == 0)
 			return ret;
-		netxen_nic_disable_int(adapter);
-		/* Window = 0 or 1 */
-		do {
-			writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
-						ISR_INT_TARGET_STATUS));
-			mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
-		} while (((mask & 0x80) != 0) && (++count < 32));
-		if ((mask & 0x80) != 0)
-			printk("Could not disable interrupt completely\n");
+	}
 
+	netxen_nic_disable_int(adapter);
+
+	if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
+		/* claim interrupt */
+		if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+			writel(our_int & ~((u32)(0x80 << adapter->portnum)),
+			NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+		}
 	}
 
 	if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
@@ -1131,7 +1274,7 @@
 		} else {
 			static unsigned int intcount = 0;
 			if ((++intcount & 0xfff) == 0xfff)
-				printk(KERN_ERR
+				DPRINTK(KERN_ERR
 				       "%s: %s interrupt %d while in poll\n",
 				       netxen_nic_driver_name, netdev->name,
 				       intcount);
@@ -1253,6 +1396,7 @@
 	/*
 	 * Wait for some time to allow the dma to drain, if any.
 	 */
+	msleep(100);
 	pci_unregister_driver(&netxen_driver);
 	destroy_workqueue(netxen_workq);
 }
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index cef90a7..05e0577 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -454,16 +454,12 @@
 
 int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
 {
-	u32 reg;
 	u32 portnum = physical_port[adapter->portnum];
 
 	netxen_crb_writelit_adapter(adapter,
-		NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
-	netxen_nic_hw_read_wx(adapter,
-		NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), &reg, 4);
-	reg = (reg & ~0x2000UL);
+		NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447);
 	netxen_crb_writelit_adapter(adapter,
-		NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), reg);
+		NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
 
 	return 0;
 }
@@ -728,7 +724,7 @@
 	__u32 mac_cfg0;
 	u32 port = physical_port[adapter->portnum];
 
-	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+	if (port > NETXEN_NIU_MAX_GBE_PORTS)
 		return -EINVAL;
 	mac_cfg0 = 0;
 	netxen_gb_soft_reset(mac_cfg0);
@@ -761,7 +757,7 @@
 	__u32 reg;
 	u32 port = physical_port[adapter->portnum];
 
-	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+	if (port > NETXEN_NIU_MAX_GBE_PORTS)
 		return -EINVAL;
 
 	/* save previous contents */
@@ -898,7 +894,7 @@
 	__u32 reg;
 	u32 port = physical_port[adapter->portnum];
 
-	if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
+	if (port > NETXEN_NIU_MAX_XG_PORTS)
 		return -EINVAL;
 
 	if (netxen_nic_hw_read_wx(adapter,
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
index 9457fc7..10fe6fa 100644
--- a/drivers/net/netxen/netxen_nic_phan_reg.h
+++ b/drivers/net/netxen/netxen_nic_phan_reg.h
@@ -114,6 +114,20 @@
 #define CRB_V2P_3		    NETXEN_NIC_REG(0x29c)
 #define CRB_V2P(port)		    (CRB_V2P_0+((port)*4))
 #define CRB_DRIVER_VERSION	    NETXEN_NIC_REG(0x2a0)
+/* sw int status/mask registers */
+#define CRB_SW_INT_MASK_0	   NETXEN_NIC_REG(0x1d8)
+#define CRB_SW_INT_MASK_1	   NETXEN_NIC_REG(0x1e0)
+#define CRB_SW_INT_MASK_2	   NETXEN_NIC_REG(0x1e4)
+#define CRB_SW_INT_MASK_3	   NETXEN_NIC_REG(0x1e8)
+
+/*
+ * capabilities register, can be used to selectively enable/disable features
+ * for backward compability
+ */
+#define CRB_NIC_CAPABILITIES_HOST	NETXEN_NIC_REG(0x1a8)
+#define CRB_NIC_CAPABILITIES_FW	  	NETXEN_NIC_REG(0x1dc)
+
+#define INTR_SCHEME_PERPORT	      	0x1
 
 /* used for ethtool tests */
 #define CRB_SCRATCHPAD_TEST	    NETXEN_NIC_REG(0x280)
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index 8dbd6d1..5e7999d 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -936,7 +936,7 @@
 					{
 						skb_reserve(skb,2);
 						skb_put(skb,totlen);
-						eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0);
+						skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen);
 						skb->protocol=eth_type_trans(skb,dev);
 						netif_rx(skb);
 						dev->last_rx = jiffies;
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 3818edf..4ef5fe3 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -1096,7 +1096,7 @@
 #ifdef RCV_VIA_SKB
 				if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) {
 					skb_put(skb,len);
-					eth_copy_and_sum(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len,0);
+					skb_copy_to_linear_data(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len);
 				}
 				else {
 					struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
@@ -1108,7 +1108,7 @@
 				}
 #else
 				skb_put(skb,len);
-				eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
+				skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len);
 #endif
 				p->stats.rx_packets++;
 				p->stats.rx_bytes += len;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 3439f8c..104aab3 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -506,17 +506,6 @@
 	spin_unlock(&dev->tx_lock);
 	spin_unlock_irq(&dev->misc_lock);
 }
-
-static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid)
-{
-	struct ns83820 *dev = PRIV(ndev);
-
-	spin_lock_irq(&dev->misc_lock);
-	spin_lock(&dev->tx_lock);
-	vlan_group_set_device(dev->vlgrp, vid, NULL);
-	spin_unlock(&dev->tx_lock);
-	spin_unlock_irq(&dev->misc_lock);
-}
 #endif
 
 /* Packet Receiver
@@ -1842,11 +1831,13 @@
 
 	ndev = alloc_etherdev(sizeof(struct ns83820));
 	dev = PRIV(ndev);
-	dev->ndev = ndev;
+
 	err = -ENOMEM;
 	if (!dev)
 		goto out;
 
+	dev->ndev = ndev;
+
 	spin_lock_init(&dev->rx_info.lock);
 	spin_lock_init(&dev->tx_lock);
 	spin_lock_init(&dev->misc_lock);
@@ -2083,7 +2074,6 @@
 	/* We also support hardware vlan acceleration */
 	ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	ndev->vlan_rx_register = ns83820_vlan_rx_register;
-	ndev->vlan_rx_kill_vid = ns83820_vlan_rx_kill_vid;
 #endif
 
 	if (using_dac) {
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 8d38425..0b3066a 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -755,7 +755,7 @@
 	flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
 
 	pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
-			       PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
+			       PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
 
 	pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
 			       PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index df8998b..3cdbe118 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -1567,7 +1567,7 @@
 		if (skb) {
 			skb_reserve (skb, 2);	/* 16 byte align the IP fields. */
 
-			eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+			skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
 			skb_put (skb, pkt_size);
 
 			skb->protocol = eth_type_trans (skb, dev);
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 143ae2f..503f268 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -629,9 +629,9 @@
 	outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
     }
 
-    dev_kfree_skb(skb);
     pop_tx_status(dev);
     spin_unlock_irqrestore(&priv->lock, flags);    
+    dev_kfree_skb(skb);
     
     return 0;
 }
diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig
index 5d658bc..e8f55d8 100644
--- a/drivers/net/pcmcia/Kconfig
+++ b/drivers/net/pcmcia/Kconfig
@@ -19,7 +19,7 @@
 
 	  If unsure, say N.
 
-if NET_PCMCIA
+if NET_PCMCIA && PCMCIA
 
 config PCMCIA_3C589
 	tristate "3Com 3c589 PCMCIA support"
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 808fae1..50dff1b 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -521,6 +521,7 @@
 
 static int axnet_open(struct net_device *dev)
 {
+    int ret;
     axnet_dev_t *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
     
@@ -529,9 +530,11 @@
     if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
-    link->open++;
+    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+    if (ret)
+	    return ret;
 
-    request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+    link->open++;
 
     info->link_status = 0x00;
     init_timer(&info->watchdog);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 3f93d49..85d5f2c 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -109,7 +109,7 @@
     card type
  */
 typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, 
-	       XXX10304
+	       XXX10304, NEC, KME
 } cardtype_t;
 
 /*
@@ -374,6 +374,18 @@
 		link->io.NumPorts2 = 8;
 	    }
 	    break;
+	case MANFID_NEC:
+	    cardtype = NEC; /* MultiFunction Card */
+	    link->conf.ConfigBase = 0x800;
+	    link->conf.ConfigIndex = 0x47;
+	    link->io.NumPorts2 = 8;
+	    break;
+	case MANFID_KME:
+	    cardtype = KME; /* MultiFunction Card */
+	    link->conf.ConfigBase = 0x800;
+	    link->conf.ConfigIndex = 0x47;
+	    link->io.NumPorts2 = 8;
+	    break;
 	case MANFID_CONTEC:
 	    cardtype = CONTEC;
 	    break;
@@ -450,6 +462,8 @@
     case TDK:
     case LA501:
     case CONTEC:
+    case NEC:
+    case KME:
 	tuple.DesiredTuple = CISTPL_FUNCE;
 	tuple.TupleOffset = 0;
 	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
@@ -469,6 +483,10 @@
 		card_name = "TDK LAK-CD021";
 	    } else if( cardtype == LA501 ) {
 		card_name = "LA501";
+	    } else if( cardtype == NEC ) {
+		card_name = "PK-UG-J001";
+	    } else if( cardtype == KME ) {
+		card_name = "Panasonic";
 	    } else {
 		card_name = "C-NET(PC)C";
 	    }
@@ -678,8 +696,11 @@
 	PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
 	PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index d88e9b2..63de89e 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -960,6 +960,7 @@
 
 static int pcnet_open(struct net_device *dev)
 {
+    int ret;
     pcnet_dev_t *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
 
@@ -968,10 +969,12 @@
     if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
-    link->open++;
-
     set_misc_reg(dev);
-    request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+    if (ret)
+	    return ret;
+
+    link->open++;
 
     info->phy_id = info->eth_phy;
     info->link_status = 0x00;
@@ -1552,6 +1555,7 @@
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
 	PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card       ", 0xb569a6e5, 0x5bd4ff2c),
@@ -1577,6 +1581,7 @@
 	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
 	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
 	PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
 	PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
 	PCMCIA_DEVICE_PROD_ID123("CNet  ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
 	PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 9c171a7..465485a 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1235,9 +1235,9 @@
 					    lp->rx_dma_addr[entry],
 					    pkt_len,
 					    PCI_DMA_FROMDEVICE);
-		eth_copy_and_sum(skb,
+		skb_copy_to_linear_data(skb,
 				 (unsigned char *)(lp->rx_skbuff[entry]->data),
-				 pkt_len, 0);
+				 pkt_len);
 		pci_dma_sync_single_for_device(lp->pci_dev,
 					       lp->rx_dma_addr[entry],
 					       pkt_len,
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 09b6f25..dd09011 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -55,6 +55,11 @@
 	---help---
 	  Currently supports the BCM5411, BCM5421 and BCM5461 PHYs.
 
+config ICPLUS_PHY
+	tristate "Drivers for ICPlus PHYs"
+	---help---
+	  Currently supports the IP175C PHY.
+
 config FIXED_PHY
 	tristate "Drivers for PHY emulation on fixed speed/link"
 	---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index bcd1efb..8885650 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -11,4 +11,5 @@
 obj-$(CONFIG_SMSC_PHY)		+= smsc.o
 obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
 obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
+obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 68c99b4c..bb96691 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -89,6 +89,7 @@
 /*-----------------------------------------------------------------------------
  *  This is used for updating internal mii regs from the status
  *-----------------------------------------------------------------------------*/
+#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX)
 static int fixed_mdio_update_regs(struct fixed_info *fixed)
 {
 	u16 *regs = fixed->regs;
@@ -165,6 +166,7 @@
 	/*nothing here - no way/need to reset it*/
 	return 0;
 }
+#endif
 
 static int fixed_config_aneg(struct phy_device *phydev)
 {
@@ -194,6 +196,7 @@
  * number is used to create multiple fixed PHYs, so that several devices can
  * utilize them simultaneously.
  *-----------------------------------------------------------------------------*/
+#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX)
 static int fixed_mdio_register_device(int number, int speed, int duplex)
 {
 	struct mii_bus *new_bus;
@@ -301,6 +304,7 @@
 
 	return err;
 }
+#endif
 
 
 MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
new file mode 100644
index 0000000..af3f1f2
--- /dev/null
+++ b/drivers/net/phy/icplus.c
@@ -0,0 +1,134 @@
+/*
+ * Driver for ICPlus PHYs
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_AUTHOR("Michael Barkowski");
+MODULE_LICENSE("GPL");
+
+static int ip175c_config_init(struct phy_device *phydev)
+{
+	int err, i;
+	static int full_reset_performed = 0;
+
+	if (full_reset_performed == 0) {
+
+		/* master reset */
+		err = phydev->bus->write(phydev->bus, 30, 0, 0x175c);
+		if (err < 0)
+			return err;
+
+		/* ensure no bus delays overlap reset period */
+		err = phydev->bus->read(phydev->bus, 30, 0);
+
+		/* data sheet specifies reset period is 2 msec */
+		mdelay(2);
+
+		/* enable IP175C mode */
+		err = phydev->bus->write(phydev->bus, 29, 31, 0x175c);
+		if (err < 0)
+			return err;
+
+		/* Set MII0 speed and duplex (in PHY mode) */
+		err = phydev->bus->write(phydev->bus, 29, 22, 0x420);
+		if (err < 0)
+			return err;
+
+		/* reset switch ports */
+		for (i = 0; i < 5; i++) {
+			err = phydev->bus->write(phydev->bus, i,
+						 MII_BMCR, BMCR_RESET);
+			if (err < 0)
+				return err;
+		}
+
+		for (i = 0; i < 5; i++)
+			err = phydev->bus->read(phydev->bus, i, MII_BMCR);
+
+		mdelay(2);
+
+		full_reset_performed = 1;
+	}
+
+	if (phydev->addr != 4) {
+		phydev->state = PHY_RUNNING;
+		phydev->speed = SPEED_100;
+		phydev->duplex = DUPLEX_FULL;
+		phydev->link = 1;
+		netif_carrier_on(phydev->attached_dev);
+	}
+
+	return 0;
+}
+
+static int ip175c_read_status(struct phy_device *phydev)
+{
+	if (phydev->addr == 4) /* WAN port */
+		genphy_read_status(phydev);
+	else
+		/* Don't need to read status for switch ports */
+		phydev->irq = PHY_IGNORE_INTERRUPT;
+
+	return 0;
+}
+
+static int ip175c_config_aneg(struct phy_device *phydev)
+{
+	if (phydev->addr == 4) /* WAN port */
+		genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static struct phy_driver ip175c_driver = {
+	.phy_id		= 0x02430d80,
+	.name		= "ICPlus IP175C",
+	.phy_id_mask	= 0x0ffffff0,
+	.features	= PHY_BASIC_FEATURES,
+	.config_init	= &ip175c_config_init,
+	.config_aneg	= &ip175c_config_aneg,
+	.read_status	= &ip175c_read_status,
+	.driver		= { .owner = THIS_MODULE,},
+};
+
+static int __init ip175c_init(void)
+{
+	return phy_driver_register(&ip175c_driver);
+}
+
+static void __exit ip175c_exit(void)
+{
+	phy_driver_unregister(&ip175c_driver);
+}
+
+module_init(ip175c_init);
+module_exit(ip175c_exit);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 22aec5c..d2ede5f 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -54,6 +54,13 @@
 #define MII_M1111_PHY_LED_CONTROL	0x18
 #define MII_M1111_PHY_LED_DIRECT	0x4100
 #define MII_M1111_PHY_LED_COMBINE	0x411c
+#define MII_M1111_PHY_EXT_CR		0x14
+#define MII_M1111_RX_DELAY		0x80
+#define MII_M1111_TX_DELAY		0x2
+#define MII_M1111_PHY_EXT_SR		0x1b
+#define MII_M1111_HWCFG_MODE_MASK	0xf
+#define MII_M1111_HWCFG_MODE_RGMII	0xb
+#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK	0x4
 
 MODULE_DESCRIPTION("Marvell PHY driver");
 MODULE_AUTHOR("Andy Fleming");
@@ -131,6 +138,60 @@
 	return err;
 }
 
+static int m88e1111_config_init(struct phy_device *phydev)
+{
+	int err;
+
+	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) {
+		int temp;
+
+		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
+			temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
+			if (temp < 0)
+				return temp;
+
+			temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
+
+			err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
+			if (err < 0)
+				return err;
+		}
+
+		temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
+		if (temp < 0)
+			return temp;
+
+		temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+		temp |= MII_M1111_HWCFG_MODE_RGMII;
+
+		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+		if (err < 0)
+			return err;
+	}
+
+	if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+		int temp;
+
+		temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
+		if (temp < 0)
+			return temp;
+
+		temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+		temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
+
+		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+		if (err < 0)
+			return err;
+	}
+
+	err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
 static int m88e1145_config_init(struct phy_device *phydev)
 {
 	int err;
@@ -152,7 +213,7 @@
 	if (err < 0)
 		return err;
 
-	if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
 		int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
 		if (temp < 0)
 			return temp;
@@ -193,76 +254,84 @@
 	return 0;
 }
 
-static struct phy_driver m88e1101_driver = {
-	.phy_id = 0x01410c60,
-	.phy_id_mask = 0xfffffff0,
-	.name = "Marvell 88E1101",
-	.features = PHY_GBIT_FEATURES,
-	.flags = PHY_HAS_INTERRUPT,
-	.config_aneg = &marvell_config_aneg,
-	.read_status = &genphy_read_status,
-	.ack_interrupt = &marvell_ack_interrupt,
-	.config_intr = &marvell_config_intr,
-	.driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1111s_driver = {
-	.phy_id = 0x01410cc0,
-	.phy_id_mask = 0xfffffff0,
-	.name = "Marvell 88E1111",
-	.features = PHY_GBIT_FEATURES,
-	.flags = PHY_HAS_INTERRUPT,
-	.config_aneg = &marvell_config_aneg,
-	.read_status = &genphy_read_status,
-	.ack_interrupt = &marvell_ack_interrupt,
-	.config_intr = &marvell_config_intr,
-	.driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1145_driver = {
-	.phy_id = 0x01410cd0,
-	.phy_id_mask = 0xfffffff0,
-	.name = "Marvell 88E1145",
-	.features = PHY_GBIT_FEATURES,
-	.flags = PHY_HAS_INTERRUPT,
-	.config_init = &m88e1145_config_init,
-	.config_aneg = &marvell_config_aneg,
-	.read_status = &genphy_read_status,
-	.ack_interrupt = &marvell_ack_interrupt,
-	.config_intr = &marvell_config_intr,
-	.driver = {.owner = THIS_MODULE,},
+static struct phy_driver marvell_drivers[] = {
+	{
+		.phy_id = 0x01410c60,
+		.phy_id_mask = 0xfffffff0,
+		.name = "Marvell 88E1101",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.config_aneg = &marvell_config_aneg,
+		.read_status = &genphy_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.driver = {.owner = THIS_MODULE,},
+	},
+	{
+		.phy_id = 0x01410c90,
+		.phy_id_mask = 0xfffffff0,
+		.name = "Marvell 88E1112",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.config_init = &m88e1111_config_init,
+		.config_aneg = &marvell_config_aneg,
+		.read_status = &genphy_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.driver = {.owner = THIS_MODULE,},
+	},
+	{
+		.phy_id = 0x01410cc0,
+		.phy_id_mask = 0xfffffff0,
+		.name = "Marvell 88E1111",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.config_init = &m88e1111_config_init,
+		.config_aneg = &marvell_config_aneg,
+		.read_status = &genphy_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.driver = {.owner = THIS_MODULE,},
+	},
+	{
+		.phy_id = 0x01410cd0,
+		.phy_id_mask = 0xfffffff0,
+		.name = "Marvell 88E1145",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.config_init = &m88e1145_config_init,
+		.config_aneg = &marvell_config_aneg,
+		.read_status = &genphy_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.driver = {.owner = THIS_MODULE,},
+	}
 };
 
 static int __init marvell_init(void)
 {
 	int ret;
+	int i;
 
-	ret = phy_driver_register(&m88e1101_driver);
-	if (ret)
-		return ret;
+	for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
+		ret = phy_driver_register(&marvell_drivers[i]);
 
-	ret = phy_driver_register(&m88e1111s_driver);
-	if (ret)
-		goto err1111s;
-
-	ret = phy_driver_register(&m88e1145_driver);
-	if (ret)
-		goto err1145;
+		if (ret) {
+			while (i-- > 0)
+				phy_driver_unregister(&marvell_drivers[i]);
+			return ret;
+		}
+	}
 
 	return 0;
-
-      err1145:
-	phy_driver_unregister(&m88e1111s_driver);
-      err1111s:
-	phy_driver_unregister(&m88e1101_driver);
-	return ret;
 }
 
 static void __exit marvell_exit(void)
 {
-	phy_driver_unregister(&m88e1101_driver);
-	phy_driver_unregister(&m88e1111s_driver);
-	phy_driver_unregister(&m88e1145_driver);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
+		phy_driver_unregister(&marvell_drivers[i]);
 }
 
 module_init(marvell_init);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index fc4aee9..fc2f0e6 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -131,7 +131,8 @@
 	struct phy_device *phydev = to_phy_device(dev);
 	struct phy_driver *phydrv = to_phy_driver(drv);
 
-	return (phydrv->phy_id == (phydev->phy_id & phydrv->phy_id_mask));
+	return ((phydrv->phy_id & phydrv->phy_id_mask) ==
+		(phydev->phy_id & phydrv->phy_id_mask));
 }
 
 /* Suspend and resume.  Copied from platform_suspend and
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 792716b..596222b 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -84,7 +84,7 @@
 
 /* Vitesse 824x */
 static struct phy_driver vsc8244_driver = {
-	.phy_id		= 0x000fc6c2,
+	.phy_id		= 0x000fc6c0,
 	.name		= "Vitesse VSC8244",
 	.phy_id_mask	= 0x000fffc0,
 	.features	= PHY_GBIT_FEATURES,
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 5411687..3ef0092 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1708,7 +1708,18 @@
 		goto err;
 
 	if (proto == PPP_COMP) {
-		ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN);
+		int obuff_size;
+
+		switch(ppp->rcomp->compress_proto) {
+		case CI_MPPE:
+			obuff_size = ppp->mru + PPP_HDRLEN + 1;
+			break;
+		default:
+			obuff_size = ppp->mru + PPP_HDRLEN;
+			break;
+		}
+
+		ns = dev_alloc_skb(obuff_size);
 		if (ns == 0) {
 			printk(KERN_ERR "ppp_decompress_frame: no memory\n");
 			goto err;
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
new file mode 100644
index 0000000..5891a0f
--- /dev/null
+++ b/drivers/net/pppol2tp.c
@@ -0,0 +1,2486 @@
+/*****************************************************************************
+ * Linux PPP over L2TP (PPPoX/PPPoL2TP) Sockets
+ *
+ * PPPoX    --- Generic PPP encapsulation socket family
+ * PPPoL2TP --- PPP over L2TP (RFC 2661)
+ *
+ * Version:	1.0.0
+ *
+ * Authors:	Martijn van Oosterhout <kleptog@svana.org>
+ *		James Chapman (jchapman@katalix.com)
+ * Contributors:
+ *		Michal Ostrowski <mostrows@speakeasy.net>
+ *		Arnaldo Carvalho de Melo <acme@xconectiva.com.br>
+ *		David S. Miller (davem@redhat.com)
+ *
+ * License:
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ */
+
+/* This driver handles only L2TP data frames; control frames are handled by a
+ * userspace application.
+ *
+ * To send data in an L2TP session, userspace opens a PPPoL2TP socket and
+ * attaches it to a bound UDP socket with local tunnel_id / session_id and
+ * peer tunnel_id / session_id set. Data can then be sent or received using
+ * regular socket sendmsg() / recvmsg() calls. Kernel parameters of the socket
+ * can be read or modified using ioctl() or [gs]etsockopt() calls.
+ *
+ * When a PPPoL2TP socket is connected with local and peer session_id values
+ * zero, the socket is treated as a special tunnel management socket.
+ *
+ * Here's example userspace code to create a socket for sending/receiving data
+ * over an L2TP session:-
+ *
+ *	struct sockaddr_pppol2tp sax;
+ *	int fd;
+ *	int session_fd;
+ *
+ *	fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
+ *
+ *	sax.sa_family = AF_PPPOX;
+ *	sax.sa_protocol = PX_PROTO_OL2TP;
+ *	sax.pppol2tp.fd = tunnel_fd;	// bound UDP socket
+ *	sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr;
+ *	sax.pppol2tp.addr.sin_port = addr->sin_port;
+ *	sax.pppol2tp.addr.sin_family = AF_INET;
+ *	sax.pppol2tp.s_tunnel  = tunnel_id;
+ *	sax.pppol2tp.s_session = session_id;
+ *	sax.pppol2tp.d_tunnel  = peer_tunnel_id;
+ *	sax.pppol2tp.d_session = peer_session_id;
+ *
+ *	session_fd = connect(fd, (struct sockaddr *)&sax, sizeof(sax));
+ *
+ * A pppd plugin that allows PPP traffic to be carried over L2TP using
+ * this driver is available from the OpenL2TP project at
+ * http://openl2tp.sourceforge.net.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/inetdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/if_pppox.h>
+#include <linux/if_pppol2tp.h>
+#include <net/sock.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/file.h>
+#include <linux/hash.h>
+#include <linux/sort.h>
+#include <linux/proc_fs.h>
+#include <net/dst.h>
+#include <net/ip.h>
+#include <net/udp.h>
+#include <net/xfrm.h>
+
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+
+
+#define PPPOL2TP_DRV_VERSION	"V1.0"
+
+/* L2TP header constants */
+#define L2TP_HDRFLAG_T	   0x8000
+#define L2TP_HDRFLAG_L	   0x4000
+#define L2TP_HDRFLAG_S	   0x0800
+#define L2TP_HDRFLAG_O	   0x0200
+#define L2TP_HDRFLAG_P	   0x0100
+
+#define L2TP_HDR_VER_MASK  0x000F
+#define L2TP_HDR_VER	   0x0002
+
+/* Space for UDP, L2TP and PPP headers */
+#define PPPOL2TP_HEADER_OVERHEAD	40
+
+/* Just some random numbers */
+#define L2TP_TUNNEL_MAGIC	0x42114DDA
+#define L2TP_SESSION_MAGIC	0x0C04EB7D
+
+#define PPPOL2TP_HASH_BITS	4
+#define PPPOL2TP_HASH_SIZE	(1 << PPPOL2TP_HASH_BITS)
+
+/* Default trace flags */
+#define PPPOL2TP_DEFAULT_DEBUG_FLAGS	0
+
+#define PRINTK(_mask, _type, _lvl, _fmt, args...)			\
+	do {								\
+		if ((_mask) & (_type))					\
+			printk(_lvl "PPPOL2TP: " _fmt, ##args);		\
+	} while(0)
+
+/* Number of bytes to build transmit L2TP headers.
+ * Unfortunately the size is different depending on whether sequence numbers
+ * are enabled.
+ */
+#define PPPOL2TP_L2TP_HDR_SIZE_SEQ		10
+#define PPPOL2TP_L2TP_HDR_SIZE_NOSEQ		6
+
+struct pppol2tp_tunnel;
+
+/* Describes a session. It is the sk_user_data field in the PPPoL2TP
+ * socket. Contains information to determine incoming packets and transmit
+ * outgoing ones.
+ */
+struct pppol2tp_session
+{
+	int			magic;		/* should be
+						 * L2TP_SESSION_MAGIC */
+	int			owner;		/* pid that opened the socket */
+
+	struct sock		*sock;		/* Pointer to the session
+						 * PPPoX socket */
+	struct sock		*tunnel_sock;	/* Pointer to the tunnel UDP
+						 * socket */
+
+	struct pppol2tp_addr	tunnel_addr;	/* Description of tunnel */
+
+	struct pppol2tp_tunnel	*tunnel;	/* back pointer to tunnel
+						 * context */
+
+	char			name[20];	/* "sess xxxxx/yyyyy", where
+						 * x=tunnel_id, y=session_id */
+	int			mtu;
+	int			mru;
+	int			flags;		/* accessed by PPPIOCGFLAGS.
+						 * Unused. */
+	unsigned		recv_seq:1;	/* expect receive packets with
+						 * sequence numbers? */
+	unsigned		send_seq:1;	/* send packets with sequence
+						 * numbers? */
+	unsigned		lns_mode:1;	/* behave as LNS? LAC enables
+						 * sequence numbers under
+						 * control of LNS. */
+	int			debug;		/* bitmask of debug message
+						 * categories */
+	int			reorder_timeout; /* configured reorder timeout
+						  * (in jiffies) */
+	u16			nr;		/* session NR state (receive) */
+	u16			ns;		/* session NR state (send) */
+	struct sk_buff_head	reorder_q;	/* receive reorder queue */
+	struct pppol2tp_ioc_stats stats;
+	struct hlist_node	hlist;		/* Hash list node */
+};
+
+/* The sk_user_data field of the tunnel's UDP socket. It contains info to track
+ * all the associated sessions so incoming packets can be sorted out
+ */
+struct pppol2tp_tunnel
+{
+	int			magic;		/* Should be L2TP_TUNNEL_MAGIC */
+	rwlock_t		hlist_lock;	/* protect session_hlist */
+	struct hlist_head	session_hlist[PPPOL2TP_HASH_SIZE];
+						/* hashed list of sessions,
+						 * hashed by id */
+	int			debug;		/* bitmask of debug message
+						 * categories */
+	char			name[12];	/* "tunl xxxxx" */
+	struct pppol2tp_ioc_stats stats;
+
+	void (*old_sk_destruct)(struct sock *);
+
+	struct sock		*sock;		/* Parent socket */
+	struct list_head	list;		/* Keep a list of all open
+						 * prepared sockets */
+
+	atomic_t		ref_count;
+};
+
+/* Private data stored for received packets in the skb.
+ */
+struct pppol2tp_skb_cb {
+	u16			ns;
+	u16			nr;
+	u16			has_seq;
+	u16			length;
+	unsigned long		expires;
+};
+
+#define PPPOL2TP_SKB_CB(skb)	((struct pppol2tp_skb_cb *) &skb->cb[sizeof(struct inet_skb_parm)])
+
+static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
+static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel);
+
+static atomic_t pppol2tp_tunnel_count;
+static atomic_t pppol2tp_session_count;
+static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL };
+static struct proto_ops pppol2tp_ops;
+static LIST_HEAD(pppol2tp_tunnel_list);
+static DEFINE_RWLOCK(pppol2tp_tunnel_list_lock);
+
+/* Helpers to obtain tunnel/session contexts from sockets.
+ */
+static inline struct pppol2tp_session *pppol2tp_sock_to_session(struct sock *sk)
+{
+	struct pppol2tp_session *session;
+
+	if (sk == NULL)
+		return NULL;
+
+	session = (struct pppol2tp_session *)(sk->sk_user_data);
+	if (session == NULL)
+		return NULL;
+
+	BUG_ON(session->magic != L2TP_SESSION_MAGIC);
+
+	return session;
+}
+
+static inline struct pppol2tp_tunnel *pppol2tp_sock_to_tunnel(struct sock *sk)
+{
+	struct pppol2tp_tunnel *tunnel;
+
+	if (sk == NULL)
+		return NULL;
+
+	tunnel = (struct pppol2tp_tunnel *)(sk->sk_user_data);
+	if (tunnel == NULL)
+		return NULL;
+
+	BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+	return tunnel;
+}
+
+/* Tunnel reference counts. Incremented per session that is added to
+ * the tunnel.
+ */
+static inline void pppol2tp_tunnel_inc_refcount(struct pppol2tp_tunnel *tunnel)
+{
+	atomic_inc(&tunnel->ref_count);
+}
+
+static inline void pppol2tp_tunnel_dec_refcount(struct pppol2tp_tunnel *tunnel)
+{
+	if (atomic_dec_and_test(&tunnel->ref_count))
+		pppol2tp_tunnel_free(tunnel);
+}
+
+/* Session hash list.
+ * The session_id SHOULD be random according to RFC2661, but several
+ * L2TP implementations (Cisco and Microsoft) use incrementing
+ * session_ids.  So we do a real hash on the session_id, rather than a
+ * simple bitmask.
+ */
+static inline struct hlist_head *
+pppol2tp_session_id_hash(struct pppol2tp_tunnel *tunnel, u16 session_id)
+{
+	unsigned long hash_val = (unsigned long) session_id;
+	return &tunnel->session_hlist[hash_long(hash_val, PPPOL2TP_HASH_BITS)];
+}
+
+/* Lookup a session by id
+ */
+static struct pppol2tp_session *
+pppol2tp_session_find(struct pppol2tp_tunnel *tunnel, u16 session_id)
+{
+	struct hlist_head *session_list =
+		pppol2tp_session_id_hash(tunnel, session_id);
+	struct pppol2tp_session *session;
+	struct hlist_node *walk;
+
+	read_lock(&tunnel->hlist_lock);
+	hlist_for_each_entry(session, walk, session_list, hlist) {
+		if (session->tunnel_addr.s_session == session_id) {
+			read_unlock(&tunnel->hlist_lock);
+			return session;
+		}
+	}
+	read_unlock(&tunnel->hlist_lock);
+
+	return NULL;
+}
+
+/* Lookup a tunnel by id
+ */
+static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id)
+{
+	struct pppol2tp_tunnel *tunnel = NULL;
+
+	read_lock(&pppol2tp_tunnel_list_lock);
+	list_for_each_entry(tunnel, &pppol2tp_tunnel_list, list) {
+		if (tunnel->stats.tunnel_id == tunnel_id) {
+			read_unlock(&pppol2tp_tunnel_list_lock);
+			return tunnel;
+		}
+	}
+	read_unlock(&pppol2tp_tunnel_list_lock);
+
+	return NULL;
+}
+
+/*****************************************************************************
+ * Receive data handling
+ *****************************************************************************/
+
+/* Queue a skb in order. We come here only if the skb has an L2TP sequence
+ * number.
+ */
+static void pppol2tp_recv_queue_skb(struct pppol2tp_session *session, struct sk_buff *skb)
+{
+	struct sk_buff *skbp;
+	u16 ns = PPPOL2TP_SKB_CB(skb)->ns;
+
+	spin_lock(&session->reorder_q.lock);
+	skb_queue_walk(&session->reorder_q, skbp) {
+		if (PPPOL2TP_SKB_CB(skbp)->ns > ns) {
+			__skb_insert(skb, skbp->prev, skbp, &session->reorder_q);
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+			       "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n",
+			       session->name, ns, PPPOL2TP_SKB_CB(skbp)->ns,
+			       skb_queue_len(&session->reorder_q));
+			session->stats.rx_oos_packets++;
+			goto out;
+		}
+	}
+
+	__skb_queue_tail(&session->reorder_q, skb);
+
+out:
+	spin_unlock(&session->reorder_q.lock);
+}
+
+/* Dequeue a single skb.
+ */
+static void pppol2tp_recv_dequeue_skb(struct pppol2tp_session *session, struct sk_buff *skb)
+{
+	struct pppol2tp_tunnel *tunnel = session->tunnel;
+	int length = PPPOL2TP_SKB_CB(skb)->length;
+	struct sock *session_sock = NULL;
+
+	/* We're about to requeue the skb, so unlink it and return resources
+	 * to its current owner (a socket receive buffer).
+	 */
+	skb_unlink(skb, &session->reorder_q);
+	skb_orphan(skb);
+
+	tunnel->stats.rx_packets++;
+	tunnel->stats.rx_bytes += length;
+	session->stats.rx_packets++;
+	session->stats.rx_bytes += length;
+
+	if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+		/* Bump our Nr */
+		session->nr++;
+		PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+		       "%s: updated nr to %hu\n", session->name, session->nr);
+	}
+
+	/* If the socket is bound, send it in to PPP's input queue. Otherwise
+	 * queue it on the session socket.
+	 */
+	session_sock = session->sock;
+	if (session_sock->sk_state & PPPOX_BOUND) {
+		struct pppox_sock *po;
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: recv %d byte data frame, passing to ppp\n",
+		       session->name, length);
+
+		/* We need to forget all info related to the L2TP packet
+		 * gathered in the skb as we are going to reuse the same
+		 * skb for the inner packet.
+		 * Namely we need to:
+		 * - reset xfrm (IPSec) information as it applies to
+		 *   the outer L2TP packet and not to the inner one
+		 * - release the dst to force a route lookup on the inner
+		 *   IP packet since skb->dst currently points to the dst
+		 *   of the UDP tunnel
+		 * - reset netfilter information as it doesn't apply
+		 *   to the inner packet either
+		 */
+		secpath_reset(skb);
+		dst_release(skb->dst);
+		skb->dst = NULL;
+		nf_reset(skb);
+
+		po = pppox_sk(session_sock);
+		ppp_input(&po->chan, skb);
+	} else {
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+		       "%s: socket not bound\n", session->name);
+
+		/* Not bound. Nothing we can do, so discard. */
+		session->stats.rx_errors++;
+		kfree_skb(skb);
+	}
+
+	sock_put(session->sock);
+}
+
+/* Dequeue skbs from the session's reorder_q, subject to packet order.
+ * Skbs that have been in the queue for too long are simply discarded.
+ */
+static void pppol2tp_recv_dequeue(struct pppol2tp_session *session)
+{
+	struct sk_buff *skb;
+	struct sk_buff *tmp;
+
+	/* If the pkt at the head of the queue has the nr that we
+	 * expect to send up next, dequeue it and any other
+	 * in-sequence packets behind it.
+	 */
+	spin_lock(&session->reorder_q.lock);
+	skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
+		if (time_after(jiffies, PPPOL2TP_SKB_CB(skb)->expires)) {
+			session->stats.rx_seq_discards++;
+			session->stats.rx_errors++;
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+			       "%s: oos pkt %hu len %d discarded (too old), "
+			       "waiting for %hu, reorder_q_len=%d\n",
+			       session->name, PPPOL2TP_SKB_CB(skb)->ns,
+			       PPPOL2TP_SKB_CB(skb)->length, session->nr,
+			       skb_queue_len(&session->reorder_q));
+			__skb_unlink(skb, &session->reorder_q);
+			kfree_skb(skb);
+			continue;
+		}
+
+		if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+			if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) {
+				PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+				       "%s: holding oos pkt %hu len %d, "
+				       "waiting for %hu, reorder_q_len=%d\n",
+				       session->name, PPPOL2TP_SKB_CB(skb)->ns,
+				       PPPOL2TP_SKB_CB(skb)->length, session->nr,
+				       skb_queue_len(&session->reorder_q));
+				goto out;
+			}
+		}
+		spin_unlock(&session->reorder_q.lock);
+		pppol2tp_recv_dequeue_skb(session, skb);
+		spin_lock(&session->reorder_q.lock);
+	}
+
+out:
+	spin_unlock(&session->reorder_q.lock);
+}
+
+/* Internal receive frame. Do the real work of receiving an L2TP data frame
+ * here. The skb is not on a list when we get here.
+ * Returns 0 if the packet was a data packet and was successfully passed on.
+ * Returns 1 if the packet was not a good data packet and could not be
+ * forwarded.  All such packets are passed up to userspace to deal with.
+ */
+static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
+{
+	struct pppol2tp_session *session = NULL;
+	struct pppol2tp_tunnel *tunnel;
+	unsigned char *ptr;
+	u16 hdrflags;
+	u16 tunnel_id, session_id;
+	int length;
+	struct udphdr *uh;
+
+	tunnel = pppol2tp_sock_to_tunnel(sock);
+	if (tunnel == NULL)
+		goto error;
+
+	/* Short packet? */
+	if (skb->len < sizeof(struct udphdr)) {
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+		       "%s: recv short packet (len=%d)\n", tunnel->name, skb->len);
+		goto error;
+	}
+
+	/* Point to L2TP header */
+	ptr = skb->data + sizeof(struct udphdr);
+
+	/* Get L2TP header flags */
+	hdrflags = ntohs(*(__be16*)ptr);
+
+	/* Trace packet contents, if enabled */
+	if (tunnel->debug & PPPOL2TP_MSG_DATA) {
+		printk(KERN_DEBUG "%s: recv: ", tunnel->name);
+
+		for (length = 0; length < 16; length++)
+			printk(" %02X", ptr[length]);
+		printk("\n");
+	}
+
+	/* Get length of L2TP packet */
+	uh = (struct udphdr *) skb_transport_header(skb);
+	length = ntohs(uh->len) - sizeof(struct udphdr);
+
+	/* Too short? */
+	if (length < 12) {
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+		       "%s: recv short L2TP packet (len=%d)\n", tunnel->name, length);
+		goto error;
+	}
+
+	/* If type is control packet, it is handled by userspace. */
+	if (hdrflags & L2TP_HDRFLAG_T) {
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: recv control packet, len=%d\n", tunnel->name, length);
+		goto error;
+	}
+
+	/* Skip flags */
+	ptr += 2;
+
+	/* If length is present, skip it */
+	if (hdrflags & L2TP_HDRFLAG_L)
+		ptr += 2;
+
+	/* Extract tunnel and session ID */
+	tunnel_id = ntohs(*(__be16 *) ptr);
+	ptr += 2;
+	session_id = ntohs(*(__be16 *) ptr);
+	ptr += 2;
+
+	/* Find the session context */
+	session = pppol2tp_session_find(tunnel, session_id);
+	if (!session) {
+		/* Not found? Pass to userspace to deal with */
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+		       "%s: no socket found (%hu/%hu). Passing up.\n",
+		       tunnel->name, tunnel_id, session_id);
+		goto error;
+	}
+	sock_hold(session->sock);
+
+	/* The ref count on the socket was increased by the above call since
+	 * we now hold a pointer to the session. Take care to do sock_put()
+	 * when exiting this function from now on...
+	 */
+
+	/* Handle the optional sequence numbers.  If we are the LAC,
+	 * enable/disable sequence numbers under the control of the LNS.  If
+	 * no sequence numbers present but we were expecting them, discard
+	 * frame.
+	 */
+	if (hdrflags & L2TP_HDRFLAG_S) {
+		u16 ns, nr;
+		ns = ntohs(*(__be16 *) ptr);
+		ptr += 2;
+		nr = ntohs(*(__be16 *) ptr);
+		ptr += 2;
+
+		/* Received a packet with sequence numbers. If we're the LNS,
+		 * check if we sre sending sequence numbers and if not,
+		 * configure it so.
+		 */
+		if ((!session->lns_mode) && (!session->send_seq)) {
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_INFO,
+			       "%s: requested to enable seq numbers by LNS\n",
+			       session->name);
+			session->send_seq = -1;
+		}
+
+		/* Store L2TP info in the skb */
+		PPPOL2TP_SKB_CB(skb)->ns = ns;
+		PPPOL2TP_SKB_CB(skb)->nr = nr;
+		PPPOL2TP_SKB_CB(skb)->has_seq = 1;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+		       "%s: recv data ns=%hu, nr=%hu, session nr=%hu\n",
+		       session->name, ns, nr, session->nr);
+	} else {
+		/* No sequence numbers.
+		 * If user has configured mandatory sequence numbers, discard.
+		 */
+		if (session->recv_seq) {
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_WARNING,
+			       "%s: recv data has no seq numbers when required. "
+			       "Discarding\n", session->name);
+			session->stats.rx_seq_discards++;
+			session->stats.rx_errors++;
+			goto discard;
+		}
+
+		/* If we're the LAC and we're sending sequence numbers, the
+		 * LNS has requested that we no longer send sequence numbers.
+		 * If we're the LNS and we're sending sequence numbers, the
+		 * LAC is broken. Discard the frame.
+		 */
+		if ((!session->lns_mode) && (session->send_seq)) {
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_INFO,
+			       "%s: requested to disable seq numbers by LNS\n",
+			       session->name);
+			session->send_seq = 0;
+		} else if (session->send_seq) {
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_WARNING,
+			       "%s: recv data has no seq numbers when required. "
+			       "Discarding\n", session->name);
+			session->stats.rx_seq_discards++;
+			session->stats.rx_errors++;
+			goto discard;
+		}
+
+		/* Store L2TP info in the skb */
+		PPPOL2TP_SKB_CB(skb)->has_seq = 0;
+	}
+
+	/* If offset bit set, skip it. */
+	if (hdrflags & L2TP_HDRFLAG_O)
+		ptr += 2 + ntohs(*(__be16 *) ptr);
+
+	skb_pull(skb, ptr - skb->data);
+
+	/* Skip PPP header, if present.	 In testing, Microsoft L2TP clients
+	 * don't send the PPP header (PPP header compression enabled), but
+	 * other clients can include the header. So we cope with both cases
+	 * here. The PPP header is always FF03 when using L2TP.
+	 *
+	 * Note that skb->data[] isn't dereferenced from a u16 ptr here since
+	 * the field may be unaligned.
+	 */
+	if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03))
+		skb_pull(skb, 2);
+
+	/* Prepare skb for adding to the session's reorder_q.  Hold
+	 * packets for max reorder_timeout or 1 second if not
+	 * reordering.
+	 */
+	PPPOL2TP_SKB_CB(skb)->length = length;
+	PPPOL2TP_SKB_CB(skb)->expires = jiffies +
+		(session->reorder_timeout ? session->reorder_timeout : HZ);
+
+	/* Add packet to the session's receive queue. Reordering is done here, if
+	 * enabled. Saved L2TP protocol info is stored in skb->sb[].
+	 */
+	if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+		if (session->reorder_timeout != 0) {
+			/* Packet reordering enabled. Add skb to session's
+			 * reorder queue, in order of ns.
+			 */
+			pppol2tp_recv_queue_skb(session, skb);
+		} else {
+			/* Packet reordering disabled. Discard out-of-sequence
+			 * packets
+			 */
+			if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) {
+				session->stats.rx_seq_discards++;
+				session->stats.rx_errors++;
+				PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+				       "%s: oos pkt %hu len %d discarded, "
+				       "waiting for %hu, reorder_q_len=%d\n",
+				       session->name, PPPOL2TP_SKB_CB(skb)->ns,
+				       PPPOL2TP_SKB_CB(skb)->length, session->nr,
+				       skb_queue_len(&session->reorder_q));
+				goto discard;
+			}
+			skb_queue_tail(&session->reorder_q, skb);
+		}
+	} else {
+		/* No sequence numbers. Add the skb to the tail of the
+		 * reorder queue. This ensures that it will be
+		 * delivered after all previous sequenced skbs.
+		 */
+		skb_queue_tail(&session->reorder_q, skb);
+	}
+
+	/* Try to dequeue as many skbs from reorder_q as we can. */
+	pppol2tp_recv_dequeue(session);
+
+	return 0;
+
+discard:
+	kfree_skb(skb);
+	sock_put(session->sock);
+
+	return 0;
+
+error:
+	return 1;
+}
+
+/* UDP encapsulation receive handler. See net/ipv4/udp.c.
+ * Return codes:
+ * 0 : success.
+ * <0: error
+ * >0: skb should be passed up to userspace as UDP.
+ */
+static int pppol2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
+{
+	struct pppol2tp_tunnel *tunnel;
+
+	tunnel = pppol2tp_sock_to_tunnel(sk);
+	if (tunnel == NULL)
+		goto pass_up;
+
+	PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+	       "%s: received %d bytes\n", tunnel->name, skb->len);
+
+	if (pppol2tp_recv_core(sk, skb))
+		goto pass_up;
+
+	return 0;
+
+pass_up:
+	return 1;
+}
+
+/* Receive message. This is the recvmsg for the PPPoL2TP socket.
+ */
+static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock,
+			    struct msghdr *msg, size_t len,
+			    int flags)
+{
+	int err;
+	struct sk_buff *skb;
+	struct sock *sk = sock->sk;
+
+	err = -EIO;
+	if (sk->sk_state & PPPOX_BOUND)
+		goto end;
+
+	msg->msg_namelen = 0;
+
+	err = 0;
+	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+				flags & MSG_DONTWAIT, &err);
+	if (skb) {
+		err = memcpy_toiovec(msg->msg_iov, (unsigned char *) skb->data,
+				     skb->len);
+		if (err < 0)
+			goto do_skb_free;
+		err = skb->len;
+	}
+do_skb_free:
+	kfree_skb(skb);
+end:
+	return err;
+}
+
+/************************************************************************
+ * Transmit handling
+ ***********************************************************************/
+
+/* Tell how big L2TP headers are for a particular session. This
+ * depends on whether sequence numbers are being used.
+ */
+static inline int pppol2tp_l2tp_header_len(struct pppol2tp_session *session)
+{
+	if (session->send_seq)
+		return PPPOL2TP_L2TP_HDR_SIZE_SEQ;
+
+	return PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+}
+
+/* Build an L2TP header for the session into the buffer provided.
+ */
+static void pppol2tp_build_l2tp_header(struct pppol2tp_session *session,
+				       void *buf)
+{
+	__be16 *bufp = buf;
+	u16 flags = L2TP_HDR_VER;
+
+	if (session->send_seq)
+		flags |= L2TP_HDRFLAG_S;
+
+	/* Setup L2TP header.
+	 * FIXME: Can this ever be unaligned? Is direct dereferencing of
+	 * 16-bit header fields safe here for all architectures?
+	 */
+	*bufp++ = htons(flags);
+	*bufp++ = htons(session->tunnel_addr.d_tunnel);
+	*bufp++ = htons(session->tunnel_addr.d_session);
+	if (session->send_seq) {
+		*bufp++ = htons(session->ns);
+		*bufp++ = 0;
+		session->ns++;
+		PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+		       "%s: updated ns to %hu\n", session->name, session->ns);
+	}
+}
+
+/* This is the sendmsg for the PPPoL2TP pppol2tp_session socket.  We come here
+ * when a user application does a sendmsg() on the session socket. L2TP and
+ * PPP headers must be inserted into the user's data.
+ */
+static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
+			    size_t total_len)
+{
+	static const unsigned char ppph[2] = { 0xff, 0x03 };
+	struct sock *sk = sock->sk;
+	struct inet_sock *inet;
+	__wsum csum = 0;
+	struct sk_buff *skb;
+	int error;
+	int hdr_len;
+	struct pppol2tp_session *session;
+	struct pppol2tp_tunnel *tunnel;
+	struct udphdr *uh;
+
+	error = -ENOTCONN;
+	if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
+		goto error;
+
+	/* Get session and tunnel contexts */
+	error = -EBADF;
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto error;
+
+	tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+	if (tunnel == NULL)
+		goto error;
+
+	/* What header length is configured for this session? */
+	hdr_len = pppol2tp_l2tp_header_len(session);
+
+	/* Allocate a socket buffer */
+	error = -ENOMEM;
+	skb = sock_wmalloc(sk, NET_SKB_PAD + sizeof(struct iphdr) +
+			   sizeof(struct udphdr) + hdr_len +
+			   sizeof(ppph) + total_len,
+			   0, GFP_KERNEL);
+	if (!skb)
+		goto error;
+
+	/* Reserve space for headers. */
+	skb_reserve(skb, NET_SKB_PAD);
+	skb_reset_network_header(skb);
+	skb_reserve(skb, sizeof(struct iphdr));
+	skb_reset_transport_header(skb);
+
+	/* Build UDP header */
+	inet = inet_sk(session->tunnel_sock);
+	uh = (struct udphdr *) skb->data;
+	uh->source = inet->sport;
+	uh->dest = inet->dport;
+	uh->len = htons(hdr_len + sizeof(ppph) + total_len);
+	uh->check = 0;
+	skb_put(skb, sizeof(struct udphdr));
+
+	/* Build L2TP header */
+	pppol2tp_build_l2tp_header(session, skb->data);
+	skb_put(skb, hdr_len);
+
+	/* Add PPP header */
+	skb->data[0] = ppph[0];
+	skb->data[1] = ppph[1];
+	skb_put(skb, 2);
+
+	/* Copy user data into skb */
+	error = memcpy_fromiovec(skb->data, m->msg_iov, total_len);
+	if (error < 0) {
+		kfree_skb(skb);
+		goto error;
+	}
+	skb_put(skb, total_len);
+
+	/* Calculate UDP checksum if configured to do so */
+	if (session->tunnel_sock->sk_no_check != UDP_CSUM_NOXMIT)
+		csum = udp_csum_outgoing(sk, skb);
+
+	/* Debug */
+	if (session->send_seq)
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: send %Zd bytes, ns=%hu\n", session->name,
+		       total_len, session->ns - 1);
+	else
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: send %Zd bytes\n", session->name, total_len);
+
+	if (session->debug & PPPOL2TP_MSG_DATA) {
+		int i;
+		unsigned char *datap = skb->data;
+
+		printk(KERN_DEBUG "%s: xmit:", session->name);
+		for (i = 0; i < total_len; i++) {
+			printk(" %02X", *datap++);
+			if (i == 15) {
+				printk(" ...");
+				break;
+			}
+		}
+		printk("\n");
+	}
+
+	/* Queue the packet to IP for output */
+	error = ip_queue_xmit(skb, 1);
+
+	/* Update stats */
+	if (error >= 0) {
+		tunnel->stats.tx_packets++;
+		tunnel->stats.tx_bytes += skb->len;
+		session->stats.tx_packets++;
+		session->stats.tx_bytes += skb->len;
+	} else {
+		tunnel->stats.tx_errors++;
+		session->stats.tx_errors++;
+	}
+
+error:
+	return error;
+}
+
+/* Transmit function called by generic PPP driver.  Sends PPP frame
+ * over PPPoL2TP socket.
+ *
+ * This is almost the same as pppol2tp_sendmsg(), but rather than
+ * being called with a msghdr from userspace, it is called with a skb
+ * from the kernel.
+ *
+ * The supplied skb from ppp doesn't have enough headroom for the
+ * insertion of L2TP, UDP and IP headers so we need to allocate more
+ * headroom in the skb. This will create a cloned skb. But we must be
+ * careful in the error case because the caller will expect to free
+ * the skb it supplied, not our cloned skb. So we take care to always
+ * leave the original skb unfreed if we return an error.
+ */
+static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+	static const u8 ppph[2] = { 0xff, 0x03 };
+	struct sock *sk = (struct sock *) chan->private;
+	struct sock *sk_tun;
+	int hdr_len;
+	struct pppol2tp_session *session;
+	struct pppol2tp_tunnel *tunnel;
+	int rc;
+	int headroom;
+	int data_len = skb->len;
+	struct inet_sock *inet;
+	__wsum csum = 0;
+	struct sk_buff *skb2 = NULL;
+	struct udphdr *uh;
+
+	if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
+		goto abort;
+
+	/* Get session and tunnel contexts from the socket */
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto abort;
+
+	sk_tun = session->tunnel_sock;
+	if (sk_tun == NULL)
+		goto abort;
+	tunnel = pppol2tp_sock_to_tunnel(sk_tun);
+	if (tunnel == NULL)
+		goto abort;
+
+	/* What header length is configured for this session? */
+	hdr_len = pppol2tp_l2tp_header_len(session);
+
+	/* Check that there's enough headroom in the skb to insert IP,
+	 * UDP and L2TP and PPP headers. If not enough, expand it to
+	 * make room. Note that a new skb (or a clone) is
+	 * allocated. If we return an error from this point on, make
+	 * sure we free the new skb but do not free the original skb
+	 * since that is done by the caller for the error case.
+	 */
+	headroom = NET_SKB_PAD + sizeof(struct iphdr) +
+		sizeof(struct udphdr) + hdr_len + sizeof(ppph);
+	if (skb_headroom(skb) < headroom) {
+		skb2 = skb_realloc_headroom(skb, headroom);
+		if (skb2 == NULL)
+			goto abort;
+	} else
+		skb2 = skb;
+
+	/* Check that the socket has room */
+	if (atomic_read(&sk_tun->sk_wmem_alloc) < sk_tun->sk_sndbuf)
+		skb_set_owner_w(skb2, sk_tun);
+	else
+		goto discard;
+
+	/* Setup PPP header */
+	skb_push(skb2, sizeof(ppph));
+	skb2->data[0] = ppph[0];
+	skb2->data[1] = ppph[1];
+
+	/* Setup L2TP header */
+	skb_push(skb2, hdr_len);
+	pppol2tp_build_l2tp_header(session, skb2->data);
+
+	/* Setup UDP header */
+	inet = inet_sk(sk_tun);
+	skb_push(skb2, sizeof(struct udphdr));
+	skb_reset_transport_header(skb2);
+	uh = (struct udphdr *) skb2->data;
+	uh->source = inet->sport;
+	uh->dest = inet->dport;
+	uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len);
+	uh->check = 0;
+
+	/* Calculate UDP checksum if configured to do so */
+	if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT)
+		csum = udp_csum_outgoing(sk_tun, skb2);
+
+	/* Debug */
+	if (session->send_seq)
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: send %d bytes, ns=%hu\n", session->name,
+		       data_len, session->ns - 1);
+	else
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: send %d bytes\n", session->name, data_len);
+
+	if (session->debug & PPPOL2TP_MSG_DATA) {
+		int i;
+		unsigned char *datap = skb2->data;
+
+		printk(KERN_DEBUG "%s: xmit:", session->name);
+		for (i = 0; i < data_len; i++) {
+			printk(" %02X", *datap++);
+			if (i == 31) {
+				printk(" ...");
+				break;
+			}
+		}
+		printk("\n");
+	}
+
+	/* Get routing info from the tunnel socket */
+	skb2->dst = sk_dst_get(sk_tun);
+
+	/* Queue the packet to IP for output */
+	rc = ip_queue_xmit(skb2, 1);
+
+	/* Update stats */
+	if (rc >= 0) {
+		tunnel->stats.tx_packets++;
+		tunnel->stats.tx_bytes += skb2->len;
+		session->stats.tx_packets++;
+		session->stats.tx_bytes += skb2->len;
+	} else {
+		tunnel->stats.tx_errors++;
+		session->stats.tx_errors++;
+	}
+
+	/* Free the original skb */
+	kfree_skb(skb);
+
+	return 1;
+
+discard:
+	/* Free the new skb. Caller will free original skb. */
+	if (skb2 != skb)
+		kfree_skb(skb2);
+abort:
+	return 0;
+}
+
+/*****************************************************************************
+ * Session (and tunnel control) socket create/destroy.
+ *****************************************************************************/
+
+/* When the tunnel UDP socket is closed, all the attached sockets need to go
+ * too.
+ */
+static void pppol2tp_tunnel_closeall(struct pppol2tp_tunnel *tunnel)
+{
+	int hash;
+	struct hlist_node *walk;
+	struct hlist_node *tmp;
+	struct pppol2tp_session *session;
+	struct sock *sk;
+
+	if (tunnel == NULL)
+		BUG();
+
+	PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+	       "%s: closing all sessions...\n", tunnel->name);
+
+	write_lock(&tunnel->hlist_lock);
+	for (hash = 0; hash < PPPOL2TP_HASH_SIZE; hash++) {
+again:
+		hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) {
+			session = hlist_entry(walk, struct pppol2tp_session, hlist);
+
+			sk = session->sock;
+
+			PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+			       "%s: closing session\n", session->name);
+
+			hlist_del_init(&session->hlist);
+
+			/* Since we should hold the sock lock while
+			 * doing any unbinding, we need to release the
+			 * lock we're holding before taking that lock.
+			 * Hold a reference to the sock so it doesn't
+			 * disappear as we're jumping between locks.
+			 */
+			sock_hold(sk);
+			write_unlock(&tunnel->hlist_lock);
+			lock_sock(sk);
+
+			if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+				pppox_unbind_sock(sk);
+				sk->sk_state = PPPOX_DEAD;
+				sk->sk_state_change(sk);
+			}
+
+			/* Purge any queued data */
+			skb_queue_purge(&sk->sk_receive_queue);
+			skb_queue_purge(&sk->sk_write_queue);
+			skb_queue_purge(&session->reorder_q);
+
+			release_sock(sk);
+			sock_put(sk);
+
+			/* Now restart from the beginning of this hash
+			 * chain.  We always remove a session from the
+			 * list so we are guaranteed to make forward
+			 * progress.
+			 */
+			write_lock(&tunnel->hlist_lock);
+			goto again;
+		}
+	}
+	write_unlock(&tunnel->hlist_lock);
+}
+
+/* Really kill the tunnel.
+ * Come here only when all sessions have been cleared from the tunnel.
+ */
+static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel)
+{
+	/* Remove from socket list */
+	write_lock(&pppol2tp_tunnel_list_lock);
+	list_del_init(&tunnel->list);
+	write_unlock(&pppol2tp_tunnel_list_lock);
+
+	atomic_dec(&pppol2tp_tunnel_count);
+	kfree(tunnel);
+}
+
+/* Tunnel UDP socket destruct hook.
+ * The tunnel context is deleted only when all session sockets have been
+ * closed.
+ */
+static void pppol2tp_tunnel_destruct(struct sock *sk)
+{
+	struct pppol2tp_tunnel *tunnel;
+
+	tunnel = pppol2tp_sock_to_tunnel(sk);
+	if (tunnel == NULL)
+		goto end;
+
+	PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+	       "%s: closing...\n", tunnel->name);
+
+	/* Close all sessions */
+	pppol2tp_tunnel_closeall(tunnel);
+
+	/* No longer an encapsulation socket. See net/ipv4/udp.c */
+	(udp_sk(sk))->encap_type = 0;
+	(udp_sk(sk))->encap_rcv = NULL;
+
+	/* Remove hooks into tunnel socket */
+	tunnel->sock = NULL;
+	sk->sk_destruct = tunnel->old_sk_destruct;
+	sk->sk_user_data = NULL;
+
+	/* Call original (UDP) socket descructor */
+	if (sk->sk_destruct != NULL)
+		(*sk->sk_destruct)(sk);
+
+	pppol2tp_tunnel_dec_refcount(tunnel);
+
+end:
+	return;
+}
+
+/* Really kill the session socket. (Called from sock_put() if
+ * refcnt == 0.)
+ */
+static void pppol2tp_session_destruct(struct sock *sk)
+{
+	struct pppol2tp_session *session = NULL;
+
+	if (sk->sk_user_data != NULL) {
+		struct pppol2tp_tunnel *tunnel;
+
+		session = pppol2tp_sock_to_session(sk);
+		if (session == NULL)
+			goto out;
+
+		/* Don't use pppol2tp_sock_to_tunnel() here to
+		 * get the tunnel context because the tunnel
+		 * socket might have already been closed (its
+		 * sk->sk_user_data will be NULL) so use the
+		 * session's private tunnel ptr instead.
+		 */
+		tunnel = session->tunnel;
+		if (tunnel != NULL) {
+			BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+			/* If session_id is zero, this is a null
+			 * session context, which was created for a
+			 * socket that is being used only to manage
+			 * tunnels.
+			 */
+			if (session->tunnel_addr.s_session != 0) {
+				/* Delete the session socket from the
+				 * hash
+				 */
+				write_lock(&tunnel->hlist_lock);
+				hlist_del_init(&session->hlist);
+				write_unlock(&tunnel->hlist_lock);
+
+				atomic_dec(&pppol2tp_session_count);
+			}
+
+			/* This will delete the tunnel context if this
+			 * is the last session on the tunnel.
+			 */
+			session->tunnel = NULL;
+			session->tunnel_sock = NULL;
+			pppol2tp_tunnel_dec_refcount(tunnel);
+		}
+	}
+
+	kfree(session);
+out:
+	return;
+}
+
+/* Called when the PPPoX socket (session) is closed.
+ */
+static int pppol2tp_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	int error;
+
+	if (!sk)
+		return 0;
+
+	error = -EBADF;
+	lock_sock(sk);
+	if (sock_flag(sk, SOCK_DEAD) != 0)
+		goto error;
+
+	pppox_unbind_sock(sk);
+
+	/* Signal the death of the socket. */
+	sk->sk_state = PPPOX_DEAD;
+	sock_orphan(sk);
+	sock->sk = NULL;
+
+	/* Purge any queued data */
+	skb_queue_purge(&sk->sk_receive_queue);
+	skb_queue_purge(&sk->sk_write_queue);
+
+	release_sock(sk);
+
+	/* This will delete the session context via
+	 * pppol2tp_session_destruct() if the socket's refcnt drops to
+	 * zero.
+	 */
+	sock_put(sk);
+
+	return 0;
+
+error:
+	release_sock(sk);
+	return error;
+}
+
+/* Internal function to prepare a tunnel (UDP) socket to have PPPoX
+ * sockets attached to it.
+ */
+static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
+						   int *error)
+{
+	int err;
+	struct socket *sock = NULL;
+	struct sock *sk;
+	struct pppol2tp_tunnel *tunnel;
+	struct sock *ret = NULL;
+
+	/* Get the tunnel UDP socket from the fd, which was opened by
+	 * the userspace L2TP daemon.
+	 */
+	err = -EBADF;
+	sock = sockfd_lookup(fd, &err);
+	if (!sock) {
+		PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+		       "tunl %hu: sockfd_lookup(fd=%d) returned %d\n",
+		       tunnel_id, fd, err);
+		goto err;
+	}
+
+	/* Quick sanity checks */
+	err = -ESOCKTNOSUPPORT;
+	if (sock->type != SOCK_DGRAM) {
+		PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+		       "tunl %hu: fd %d wrong type, got %d, expected %d\n",
+		       tunnel_id, fd, sock->type, SOCK_DGRAM);
+		goto err;
+	}
+	err = -EAFNOSUPPORT;
+	if (sock->ops->family != AF_INET) {
+		PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+		       "tunl %hu: fd %d wrong family, got %d, expected %d\n",
+		       tunnel_id, fd, sock->ops->family, AF_INET);
+		goto err;
+	}
+
+	err = -ENOTCONN;
+	sk = sock->sk;
+
+	/* Check if this socket has already been prepped */
+	tunnel = (struct pppol2tp_tunnel *)sk->sk_user_data;
+	if (tunnel != NULL) {
+		/* User-data field already set */
+		err = -EBUSY;
+		BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+		/* This socket has already been prepped */
+		ret = tunnel->sock;
+		goto out;
+	}
+
+	/* This socket is available and needs prepping. Create a new tunnel
+	 * context and init it.
+	 */
+	sk->sk_user_data = tunnel = kzalloc(sizeof(struct pppol2tp_tunnel), GFP_KERNEL);
+	if (sk->sk_user_data == NULL) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	tunnel->magic = L2TP_TUNNEL_MAGIC;
+	sprintf(&tunnel->name[0], "tunl %hu", tunnel_id);
+
+	tunnel->stats.tunnel_id = tunnel_id;
+	tunnel->debug = PPPOL2TP_DEFAULT_DEBUG_FLAGS;
+
+	/* Hook on the tunnel socket destructor so that we can cleanup
+	 * if the tunnel socket goes away.
+	 */
+	tunnel->old_sk_destruct = sk->sk_destruct;
+	sk->sk_destruct = &pppol2tp_tunnel_destruct;
+
+	tunnel->sock = sk;
+	sk->sk_allocation = GFP_ATOMIC;
+
+	/* Misc init */
+	rwlock_init(&tunnel->hlist_lock);
+
+	/* Add tunnel to our list */
+	INIT_LIST_HEAD(&tunnel->list);
+	write_lock(&pppol2tp_tunnel_list_lock);
+	list_add(&tunnel->list, &pppol2tp_tunnel_list);
+	write_unlock(&pppol2tp_tunnel_list_lock);
+	atomic_inc(&pppol2tp_tunnel_count);
+
+	/* Bump the reference count. The tunnel context is deleted
+	 * only when this drops to zero.
+	 */
+	pppol2tp_tunnel_inc_refcount(tunnel);
+
+	/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
+	(udp_sk(sk))->encap_type = UDP_ENCAP_L2TPINUDP;
+	(udp_sk(sk))->encap_rcv = pppol2tp_udp_encap_recv;
+
+	ret = tunnel->sock;
+
+	*error = 0;
+out:
+	if (sock)
+		sockfd_put(sock);
+
+	return ret;
+
+err:
+	*error = err;
+	goto out;
+}
+
+static struct proto pppol2tp_sk_proto = {
+	.name	  = "PPPOL2TP",
+	.owner	  = THIS_MODULE,
+	.obj_size = sizeof(struct pppox_sock),
+};
+
+/* socket() handler. Initialize a new struct sock.
+ */
+static int pppol2tp_create(struct socket *sock)
+{
+	int error = -ENOMEM;
+	struct sock *sk;
+
+	sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1);
+	if (!sk)
+		goto out;
+
+	sock_init_data(sock, sk);
+
+	sock->state  = SS_UNCONNECTED;
+	sock->ops    = &pppol2tp_ops;
+
+	sk->sk_backlog_rcv = pppol2tp_recv_core;
+	sk->sk_protocol	   = PX_PROTO_OL2TP;
+	sk->sk_family	   = PF_PPPOX;
+	sk->sk_state	   = PPPOX_NONE;
+	sk->sk_type	   = SOCK_STREAM;
+	sk->sk_destruct	   = pppol2tp_session_destruct;
+
+	error = 0;
+
+out:
+	return error;
+}
+
+/* connect() handler. Attach a PPPoX socket to a tunnel UDP socket
+ */
+static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
+			    int sockaddr_len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr;
+	struct pppox_sock *po = pppox_sk(sk);
+	struct sock *tunnel_sock = NULL;
+	struct pppol2tp_session *session = NULL;
+	struct pppol2tp_tunnel *tunnel;
+	struct dst_entry *dst;
+	int error = 0;
+
+	lock_sock(sk);
+
+	error = -EINVAL;
+	if (sp->sa_protocol != PX_PROTO_OL2TP)
+		goto end;
+
+	/* Check for already bound sockets */
+	error = -EBUSY;
+	if (sk->sk_state & PPPOX_CONNECTED)
+		goto end;
+
+	/* We don't supporting rebinding anyway */
+	error = -EALREADY;
+	if (sk->sk_user_data)
+		goto end; /* socket is already attached */
+
+	/* Don't bind if s_tunnel is 0 */
+	error = -EINVAL;
+	if (sp->pppol2tp.s_tunnel == 0)
+		goto end;
+
+	/* Special case: prepare tunnel socket if s_session and
+	 * d_session is 0. Otherwise look up tunnel using supplied
+	 * tunnel id.
+	 */
+	if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) {
+		tunnel_sock = pppol2tp_prepare_tunnel_socket(sp->pppol2tp.fd,
+							     sp->pppol2tp.s_tunnel,
+							     &error);
+		if (tunnel_sock == NULL)
+			goto end;
+
+		tunnel = tunnel_sock->sk_user_data;
+	} else {
+		tunnel = pppol2tp_tunnel_find(sp->pppol2tp.s_tunnel);
+
+		/* Error if we can't find the tunnel */
+		error = -ENOENT;
+		if (tunnel == NULL)
+			goto end;
+
+		tunnel_sock = tunnel->sock;
+	}
+
+	/* Check that this session doesn't already exist */
+	error = -EEXIST;
+	session = pppol2tp_session_find(tunnel, sp->pppol2tp.s_session);
+	if (session != NULL)
+		goto end;
+
+	/* Allocate and initialize a new session context. */
+	session = kzalloc(sizeof(struct pppol2tp_session), GFP_KERNEL);
+	if (session == NULL) {
+		error = -ENOMEM;
+		goto end;
+	}
+
+	skb_queue_head_init(&session->reorder_q);
+
+	session->magic	     = L2TP_SESSION_MAGIC;
+	session->owner	     = current->pid;
+	session->sock	     = sk;
+	session->tunnel	     = tunnel;
+	session->tunnel_sock = tunnel_sock;
+	session->tunnel_addr = sp->pppol2tp;
+	sprintf(&session->name[0], "sess %hu/%hu",
+		session->tunnel_addr.s_tunnel,
+		session->tunnel_addr.s_session);
+
+	session->stats.tunnel_id  = session->tunnel_addr.s_tunnel;
+	session->stats.session_id = session->tunnel_addr.s_session;
+
+	INIT_HLIST_NODE(&session->hlist);
+
+	/* Inherit debug options from tunnel */
+	session->debug = tunnel->debug;
+
+	/* Default MTU must allow space for UDP/L2TP/PPP
+	 * headers.
+	 */
+	session->mtu = session->mru = 1500 - PPPOL2TP_HEADER_OVERHEAD;
+
+	/* If PMTU discovery was enabled, use the MTU that was discovered */
+	dst = sk_dst_get(sk);
+	if (dst != NULL) {
+		u32 pmtu = dst_mtu(__sk_dst_get(sk));
+		if (pmtu != 0)
+			session->mtu = session->mru = pmtu -
+				PPPOL2TP_HEADER_OVERHEAD;
+		dst_release(dst);
+	}
+
+	/* Special case: if source & dest session_id == 0x0000, this socket is
+	 * being created to manage the tunnel. Don't add the session to the
+	 * session hash list, just set up the internal context for use by
+	 * ioctl() and sockopt() handlers.
+	 */
+	if ((session->tunnel_addr.s_session == 0) &&
+	    (session->tunnel_addr.d_session == 0)) {
+		error = 0;
+		sk->sk_user_data = session;
+		goto out_no_ppp;
+	}
+
+	/* Get tunnel context from the tunnel socket */
+	tunnel = pppol2tp_sock_to_tunnel(tunnel_sock);
+	if (tunnel == NULL) {
+		error = -EBADF;
+		goto end;
+	}
+
+	/* Right now, because we don't have a way to push the incoming skb's
+	 * straight through the UDP layer, the only header we need to worry
+	 * about is the L2TP header. This size is different depending on
+	 * whether sequence numbers are enabled for the data channel.
+	 */
+	po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+
+	po->chan.private = sk;
+	po->chan.ops	 = &pppol2tp_chan_ops;
+	po->chan.mtu	 = session->mtu;
+
+	error = ppp_register_channel(&po->chan);
+	if (error)
+		goto end;
+
+	/* This is how we get the session context from the socket. */
+	sk->sk_user_data = session;
+
+	/* Add session to the tunnel's hash list */
+	write_lock(&tunnel->hlist_lock);
+	hlist_add_head(&session->hlist,
+		       pppol2tp_session_id_hash(tunnel,
+						session->tunnel_addr.s_session));
+	write_unlock(&tunnel->hlist_lock);
+
+	atomic_inc(&pppol2tp_session_count);
+
+out_no_ppp:
+	pppol2tp_tunnel_inc_refcount(tunnel);
+	sk->sk_state = PPPOX_CONNECTED;
+	PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+	       "%s: created\n", session->name);
+
+end:
+	release_sock(sk);
+
+	if (error != 0)
+		PRINTK(session ? session->debug : -1, PPPOL2TP_MSG_CONTROL, KERN_WARNING,
+		       "%s: connect failed: %d\n", session->name, error);
+
+	return error;
+}
+
+/* getname() support.
+ */
+static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
+			    int *usockaddr_len, int peer)
+{
+	int len = sizeof(struct sockaddr_pppol2tp);
+	struct sockaddr_pppol2tp sp;
+	int error = 0;
+	struct pppol2tp_session *session;
+
+	error = -ENOTCONN;
+	if (sock->sk->sk_state != PPPOX_CONNECTED)
+		goto end;
+
+	session = pppol2tp_sock_to_session(sock->sk);
+	if (session == NULL) {
+		error = -EBADF;
+		goto end;
+	}
+
+	sp.sa_family	= AF_PPPOX;
+	sp.sa_protocol	= PX_PROTO_OL2TP;
+	memcpy(&sp.pppol2tp, &session->tunnel_addr,
+	       sizeof(struct pppol2tp_addr));
+
+	memcpy(uaddr, &sp, len);
+
+	*usockaddr_len = len;
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/****************************************************************************
+ * ioctl() handlers.
+ *
+ * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP
+ * sockets. However, in order to control kernel tunnel features, we allow
+ * userspace to create a special "tunnel" PPPoX socket which is used for
+ * control only.  Tunnel PPPoX sockets have session_id == 0 and simply allow
+ * the user application to issue L2TP setsockopt(), getsockopt() and ioctl()
+ * calls.
+ ****************************************************************************/
+
+/* Session ioctl helper.
+ */
+static int pppol2tp_session_ioctl(struct pppol2tp_session *session,
+				  unsigned int cmd, unsigned long arg)
+{
+	struct ifreq ifr;
+	int err = 0;
+	struct sock *sk = session->sock;
+	int val = (int) arg;
+
+	PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG,
+	       "%s: pppol2tp_session_ioctl(cmd=%#x, arg=%#lx)\n",
+	       session->name, cmd, arg);
+
+	sock_hold(sk);
+
+	switch (cmd) {
+	case SIOCGIFMTU:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		err = -EFAULT;
+		if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq)))
+			break;
+		ifr.ifr_mtu = session->mtu;
+		if (copy_to_user((void __user *) arg, &ifr, sizeof(struct ifreq)))
+			break;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get mtu=%d\n", session->name, session->mtu);
+		err = 0;
+		break;
+
+	case SIOCSIFMTU:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		err = -EFAULT;
+		if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq)))
+			break;
+
+		session->mtu = ifr.ifr_mtu;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set mtu=%d\n", session->name, session->mtu);
+		err = 0;
+		break;
+
+	case PPPIOCGMRU:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		err = -EFAULT;
+		if (put_user(session->mru, (int __user *) arg))
+			break;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get mru=%d\n", session->name, session->mru);
+		err = 0;
+		break;
+
+	case PPPIOCSMRU:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		err = -EFAULT;
+		if (get_user(val,(int __user *) arg))
+			break;
+
+		session->mru = val;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set mru=%d\n", session->name, session->mru);
+		err = 0;
+		break;
+
+	case PPPIOCGFLAGS:
+		err = -EFAULT;
+		if (put_user(session->flags, (int __user *) arg))
+			break;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get flags=%d\n", session->name, session->flags);
+		err = 0;
+		break;
+
+	case PPPIOCSFLAGS:
+		err = -EFAULT;
+		if (get_user(val, (int __user *) arg))
+			break;
+		session->flags = val;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set flags=%d\n", session->name, session->flags);
+		err = 0;
+		break;
+
+	case PPPIOCGL2TPSTATS:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		if (copy_to_user((void __user *) arg, &session->stats,
+				 sizeof(session->stats)))
+			break;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get L2TP stats\n", session->name);
+		err = 0;
+		break;
+
+	default:
+		err = -ENOSYS;
+		break;
+	}
+
+	sock_put(sk);
+
+	return err;
+}
+
+/* Tunnel ioctl helper.
+ *
+ * Note the special handling for PPPIOCGL2TPSTATS below. If the ioctl data
+ * specifies a session_id, the session ioctl handler is called. This allows an
+ * application to retrieve session stats via a tunnel socket.
+ */
+static int pppol2tp_tunnel_ioctl(struct pppol2tp_tunnel *tunnel,
+				 unsigned int cmd, unsigned long arg)
+{
+	int err = 0;
+	struct sock *sk = tunnel->sock;
+	struct pppol2tp_ioc_stats stats_req;
+
+	PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG,
+	       "%s: pppol2tp_tunnel_ioctl(cmd=%#x, arg=%#lx)\n", tunnel->name,
+	       cmd, arg);
+
+	sock_hold(sk);
+
+	switch (cmd) {
+	case PPPIOCGL2TPSTATS:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		if (copy_from_user(&stats_req, (void __user *) arg,
+				   sizeof(stats_req))) {
+			err = -EFAULT;
+			break;
+		}
+		if (stats_req.session_id != 0) {
+			/* resend to session ioctl handler */
+			struct pppol2tp_session *session =
+				pppol2tp_session_find(tunnel, stats_req.session_id);
+			if (session != NULL)
+				err = pppol2tp_session_ioctl(session, cmd, arg);
+			else
+				err = -EBADR;
+			break;
+		}
+#ifdef CONFIG_XFRM
+		tunnel->stats.using_ipsec = (sk->sk_policy[0] || sk->sk_policy[1]) ? 1 : 0;
+#endif
+		if (copy_to_user((void __user *) arg, &tunnel->stats,
+				 sizeof(tunnel->stats))) {
+			err = -EFAULT;
+			break;
+		}
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get L2TP stats\n", tunnel->name);
+		err = 0;
+		break;
+
+	default:
+		err = -ENOSYS;
+		break;
+	}
+
+	sock_put(sk);
+
+	return err;
+}
+
+/* Main ioctl() handler.
+ * Dispatch to tunnel or session helpers depending on the socket.
+ */
+static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+			  unsigned long arg)
+{
+	struct sock *sk = sock->sk;
+	struct pppol2tp_session *session;
+	struct pppol2tp_tunnel *tunnel;
+	int err;
+
+	if (!sk)
+		return 0;
+
+	err = -EBADF;
+	if (sock_flag(sk, SOCK_DEAD) != 0)
+		goto end;
+
+	err = -ENOTCONN;
+	if ((sk->sk_user_data == NULL) ||
+	    (!(sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND))))
+		goto end;
+
+	/* Get session context from the socket */
+	err = -EBADF;
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto end;
+
+	/* Special case: if session's session_id is zero, treat ioctl as a
+	 * tunnel ioctl
+	 */
+	if ((session->tunnel_addr.s_session == 0) &&
+	    (session->tunnel_addr.d_session == 0)) {
+		err = -EBADF;
+		tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+		if (tunnel == NULL)
+			goto end;
+
+		err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg);
+		goto end;
+	}
+
+	err = pppol2tp_session_ioctl(session, cmd, arg);
+
+end:
+	return err;
+}
+
+/*****************************************************************************
+ * setsockopt() / getsockopt() support.
+ *
+ * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP
+ * sockets. In order to control kernel tunnel features, we allow userspace to
+ * create a special "tunnel" PPPoX socket which is used for control only.
+ * Tunnel PPPoX sockets have session_id == 0 and simply allow the user
+ * application to issue L2TP setsockopt(), getsockopt() and ioctl() calls.
+ *****************************************************************************/
+
+/* Tunnel setsockopt() helper.
+ */
+static int pppol2tp_tunnel_setsockopt(struct sock *sk,
+				      struct pppol2tp_tunnel *tunnel,
+				      int optname, int val)
+{
+	int err = 0;
+
+	switch (optname) {
+	case PPPOL2TP_SO_DEBUG:
+		tunnel->debug = val;
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set debug=%x\n", tunnel->name, tunnel->debug);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	return err;
+}
+
+/* Session setsockopt helper.
+ */
+static int pppol2tp_session_setsockopt(struct sock *sk,
+				       struct pppol2tp_session *session,
+				       int optname, int val)
+{
+	int err = 0;
+
+	switch (optname) {
+	case PPPOL2TP_SO_RECVSEQ:
+		if ((val != 0) && (val != 1)) {
+			err = -EINVAL;
+			break;
+		}
+		session->recv_seq = val ? -1 : 0;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set recv_seq=%d\n", session->name,
+		       session->recv_seq);
+		break;
+
+	case PPPOL2TP_SO_SENDSEQ:
+		if ((val != 0) && (val != 1)) {
+			err = -EINVAL;
+			break;
+		}
+		session->send_seq = val ? -1 : 0;
+		{
+			struct sock *ssk      = session->sock;
+			struct pppox_sock *po = pppox_sk(ssk);
+			po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ :
+				PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+		}
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set send_seq=%d\n", session->name, session->send_seq);
+		break;
+
+	case PPPOL2TP_SO_LNSMODE:
+		if ((val != 0) && (val != 1)) {
+			err = -EINVAL;
+			break;
+		}
+		session->lns_mode = val ? -1 : 0;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set lns_mode=%d\n", session->name,
+		       session->lns_mode);
+		break;
+
+	case PPPOL2TP_SO_DEBUG:
+		session->debug = val;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set debug=%x\n", session->name, session->debug);
+		break;
+
+	case PPPOL2TP_SO_REORDERTO:
+		session->reorder_timeout = msecs_to_jiffies(val);
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set reorder_timeout=%d\n", session->name,
+		       session->reorder_timeout);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	return err;
+}
+
+/* Main setsockopt() entry point.
+ * Does API checks, then calls either the tunnel or session setsockopt
+ * handler, according to whether the PPPoL2TP socket is a for a regular
+ * session or the special tunnel type.
+ */
+static int pppol2tp_setsockopt(struct socket *sock, int level, int optname,
+			       char __user *optval, int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct pppol2tp_session *session = sk->sk_user_data;
+	struct pppol2tp_tunnel *tunnel;
+	int val;
+	int err;
+
+	if (level != SOL_PPPOL2TP)
+		return udp_prot.setsockopt(sk, level, optname, optval, optlen);
+
+	if (optlen < sizeof(int))
+		return -EINVAL;
+
+	if (get_user(val, (int __user *)optval))
+		return -EFAULT;
+
+	err = -ENOTCONN;
+	if (sk->sk_user_data == NULL)
+		goto end;
+
+	/* Get session context from the socket */
+	err = -EBADF;
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto end;
+
+	/* Special case: if session_id == 0x0000, treat as operation on tunnel
+	 */
+	if ((session->tunnel_addr.s_session == 0) &&
+	    (session->tunnel_addr.d_session == 0)) {
+		err = -EBADF;
+		tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+		if (tunnel == NULL)
+			goto end;
+
+		err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val);
+	} else
+		err = pppol2tp_session_setsockopt(sk, session, optname, val);
+
+	err = 0;
+
+end:
+	return err;
+}
+
+/* Tunnel getsockopt helper. Called with sock locked.
+ */
+static int pppol2tp_tunnel_getsockopt(struct sock *sk,
+				      struct pppol2tp_tunnel *tunnel,
+				      int optname, int __user *val)
+{
+	int err = 0;
+
+	switch (optname) {
+	case PPPOL2TP_SO_DEBUG:
+		*val = tunnel->debug;
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get debug=%x\n", tunnel->name, tunnel->debug);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	return err;
+}
+
+/* Session getsockopt helper. Called with sock locked.
+ */
+static int pppol2tp_session_getsockopt(struct sock *sk,
+				       struct pppol2tp_session *session,
+				       int optname, int __user *val)
+{
+	int err = 0;
+
+	switch (optname) {
+	case PPPOL2TP_SO_RECVSEQ:
+		*val = session->recv_seq;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get recv_seq=%d\n", session->name, *val);
+		break;
+
+	case PPPOL2TP_SO_SENDSEQ:
+		*val = session->send_seq;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get send_seq=%d\n", session->name, *val);
+		break;
+
+	case PPPOL2TP_SO_LNSMODE:
+		*val = session->lns_mode;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get lns_mode=%d\n", session->name, *val);
+		break;
+
+	case PPPOL2TP_SO_DEBUG:
+		*val = session->debug;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get debug=%d\n", session->name, *val);
+		break;
+
+	case PPPOL2TP_SO_REORDERTO:
+		*val = (int) jiffies_to_msecs(session->reorder_timeout);
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get reorder_timeout=%d\n", session->name, *val);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+	}
+
+	return err;
+}
+
+/* Main getsockopt() entry point.
+ * Does API checks, then calls either the tunnel or session getsockopt
+ * handler, according to whether the PPPoX socket is a for a regular session
+ * or the special tunnel type.
+ */
+static int pppol2tp_getsockopt(struct socket *sock, int level,
+			       int optname, char __user *optval, int __user *optlen)
+{
+	struct sock *sk = sock->sk;
+	struct pppol2tp_session *session = sk->sk_user_data;
+	struct pppol2tp_tunnel *tunnel;
+	int val, len;
+	int err;
+
+	if (level != SOL_PPPOL2TP)
+		return udp_prot.getsockopt(sk, level, optname, optval, optlen);
+
+	if (get_user(len, (int __user *) optlen))
+		return -EFAULT;
+
+	len = min_t(unsigned int, len, sizeof(int));
+
+	if (len < 0)
+		return -EINVAL;
+
+	err = -ENOTCONN;
+	if (sk->sk_user_data == NULL)
+		goto end;
+
+	/* Get the session context */
+	err = -EBADF;
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto end;
+
+	/* Special case: if session_id == 0x0000, treat as operation on tunnel */
+	if ((session->tunnel_addr.s_session == 0) &&
+	    (session->tunnel_addr.d_session == 0)) {
+		err = -EBADF;
+		tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+		if (tunnel == NULL)
+			goto end;
+
+		err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val);
+	} else
+		err = pppol2tp_session_getsockopt(sk, session, optname, &val);
+
+	err = -EFAULT;
+	if (put_user(len, (int __user *) optlen))
+		goto end;
+
+	if (copy_to_user((void __user *) optval, &val, len))
+		goto end;
+
+	err = 0;
+end:
+	return err;
+}
+
+/*****************************************************************************
+ * /proc filesystem for debug
+ *****************************************************************************/
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/seq_file.h>
+
+struct pppol2tp_seq_data {
+	struct pppol2tp_tunnel *tunnel; /* current tunnel */
+	struct pppol2tp_session *session; /* NULL means get first session in tunnel */
+};
+
+static struct pppol2tp_session *next_session(struct pppol2tp_tunnel *tunnel, struct pppol2tp_session *curr)
+{
+	struct pppol2tp_session *session = NULL;
+	struct hlist_node *walk;
+	int found = 0;
+	int next = 0;
+	int i;
+
+	read_lock(&tunnel->hlist_lock);
+	for (i = 0; i < PPPOL2TP_HASH_SIZE; i++) {
+		hlist_for_each_entry(session, walk, &tunnel->session_hlist[i], hlist) {
+			if (curr == NULL) {
+				found = 1;
+				goto out;
+			}
+			if (session == curr) {
+				next = 1;
+				continue;
+			}
+			if (next) {
+				found = 1;
+				goto out;
+			}
+		}
+	}
+out:
+	read_unlock(&tunnel->hlist_lock);
+	if (!found)
+		session = NULL;
+
+	return session;
+}
+
+static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_tunnel *curr)
+{
+	struct pppol2tp_tunnel *tunnel = NULL;
+
+	read_lock(&pppol2tp_tunnel_list_lock);
+	if (list_is_last(&curr->list, &pppol2tp_tunnel_list)) {
+		goto out;
+	}
+	tunnel = list_entry(curr->list.next, struct pppol2tp_tunnel, list);
+out:
+	read_unlock(&pppol2tp_tunnel_list_lock);
+
+	return tunnel;
+}
+
+static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs)
+{
+	struct pppol2tp_seq_data *pd = SEQ_START_TOKEN;
+	loff_t pos = *offs;
+
+	if (!pos)
+		goto out;
+
+	BUG_ON(m->private == NULL);
+	pd = m->private;
+
+	if (pd->tunnel == NULL) {
+		if (!list_empty(&pppol2tp_tunnel_list))
+			pd->tunnel = list_entry(pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list);
+	} else {
+		pd->session = next_session(pd->tunnel, pd->session);
+		if (pd->session == NULL) {
+			pd->tunnel = next_tunnel(pd->tunnel);
+		}
+	}
+
+	/* NULL tunnel and session indicates end of list */
+	if ((pd->tunnel == NULL) && (pd->session == NULL))
+		pd = NULL;
+
+out:
+	return pd;
+}
+
+static void *pppol2tp_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return NULL;
+}
+
+static void pppol2tp_seq_stop(struct seq_file *p, void *v)
+{
+	/* nothing to do */
+}
+
+static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)
+{
+	struct pppol2tp_tunnel *tunnel = v;
+
+	seq_printf(m, "\nTUNNEL '%s', %c %d\n",
+		   tunnel->name,
+		   (tunnel == tunnel->sock->sk_user_data) ? 'Y':'N',
+		   atomic_read(&tunnel->ref_count) - 1);
+	seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n",
+		   tunnel->debug,
+		   tunnel->stats.tx_packets, tunnel->stats.tx_bytes,
+		   tunnel->stats.tx_errors,
+		   tunnel->stats.rx_packets, tunnel->stats.rx_bytes,
+		   tunnel->stats.rx_errors);
+}
+
+static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
+{
+	struct pppol2tp_session *session = v;
+
+	seq_printf(m, "  SESSION '%s' %08X/%d %04X/%04X -> "
+		   "%04X/%04X %d %c\n",
+		   session->name,
+		   ntohl(session->tunnel_addr.addr.sin_addr.s_addr),
+		   ntohs(session->tunnel_addr.addr.sin_port),
+		   session->tunnel_addr.s_tunnel,
+		   session->tunnel_addr.s_session,
+		   session->tunnel_addr.d_tunnel,
+		   session->tunnel_addr.d_session,
+		   session->sock->sk_state,
+		   (session == session->sock->sk_user_data) ?
+		   'Y' : 'N');
+	seq_printf(m, "   %d/%d/%c/%c/%s %08x %u\n",
+		   session->mtu, session->mru,
+		   session->recv_seq ? 'R' : '-',
+		   session->send_seq ? 'S' : '-',
+		   session->lns_mode ? "LNS" : "LAC",
+		   session->debug,
+		   jiffies_to_msecs(session->reorder_timeout));
+	seq_printf(m, "   %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n",
+		   session->nr, session->ns,
+		   session->stats.tx_packets,
+		   session->stats.tx_bytes,
+		   session->stats.tx_errors,
+		   session->stats.rx_packets,
+		   session->stats.rx_bytes,
+		   session->stats.rx_errors);
+}
+
+static int pppol2tp_seq_show(struct seq_file *m, void *v)
+{
+	struct pppol2tp_seq_data *pd = v;
+
+	/* display header on line 1 */
+	if (v == SEQ_START_TOKEN) {
+		seq_puts(m, "PPPoL2TP driver info, " PPPOL2TP_DRV_VERSION "\n");
+		seq_puts(m, "TUNNEL name, user-data-ok session-count\n");
+		seq_puts(m, " debug tx-pkts/bytes/errs rx-pkts/bytes/errs\n");
+		seq_puts(m, "  SESSION name, addr/port src-tid/sid "
+			 "dest-tid/sid state user-data-ok\n");
+		seq_puts(m, "   mtu/mru/rcvseq/sendseq/lns debug reorderto\n");
+		seq_puts(m, "   nr/ns tx-pkts/bytes/errs rx-pkts/bytes/errs\n");
+		goto out;
+	}
+
+	/* Show the tunnel or session context.
+	 */
+	if (pd->session == NULL)
+		pppol2tp_seq_tunnel_show(m, pd->tunnel);
+	else
+		pppol2tp_seq_session_show(m, pd->session);
+
+out:
+	return 0;
+}
+
+static struct seq_operations pppol2tp_seq_ops = {
+	.start		= pppol2tp_seq_start,
+	.next		= pppol2tp_seq_next,
+	.stop		= pppol2tp_seq_stop,
+	.show		= pppol2tp_seq_show,
+};
+
+/* Called when our /proc file is opened. We allocate data for use when
+ * iterating our tunnel / session contexts and store it in the private
+ * data of the seq_file.
+ */
+static int pppol2tp_proc_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *m;
+	struct pppol2tp_seq_data *pd;
+	int ret = 0;
+
+	ret = seq_open(file, &pppol2tp_seq_ops);
+	if (ret < 0)
+		goto out;
+
+	m = file->private_data;
+
+	/* Allocate and fill our proc_data for access later */
+	ret = -ENOMEM;
+	m->private = kzalloc(sizeof(struct pppol2tp_seq_data), GFP_KERNEL);
+	if (m->private == NULL)
+		goto out;
+
+	pd = m->private;
+	ret = 0;
+
+out:
+	return ret;
+}
+
+/* Called when /proc file access completes.
+ */
+static int pppol2tp_proc_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *m = (struct seq_file *)file->private_data;
+
+	kfree(m->private);
+	m->private = NULL;
+
+	return seq_release(inode, file);
+}
+
+static struct file_operations pppol2tp_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pppol2tp_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= pppol2tp_proc_release,
+};
+
+static struct proc_dir_entry *pppol2tp_proc;
+
+#endif /* CONFIG_PROC_FS */
+
+/*****************************************************************************
+ * Init and cleanup
+ *****************************************************************************/
+
+static struct proto_ops pppol2tp_ops = {
+	.family		= AF_PPPOX,
+	.owner		= THIS_MODULE,
+	.release	= pppol2tp_release,
+	.bind		= sock_no_bind,
+	.connect	= pppol2tp_connect,
+	.socketpair	= sock_no_socketpair,
+	.accept		= sock_no_accept,
+	.getname	= pppol2tp_getname,
+	.poll		= datagram_poll,
+	.listen		= sock_no_listen,
+	.shutdown	= sock_no_shutdown,
+	.setsockopt	= pppol2tp_setsockopt,
+	.getsockopt	= pppol2tp_getsockopt,
+	.sendmsg	= pppol2tp_sendmsg,
+	.recvmsg	= pppol2tp_recvmsg,
+	.mmap		= sock_no_mmap,
+	.ioctl		= pppox_ioctl,
+};
+
+static struct pppox_proto pppol2tp_proto = {
+	.create		= pppol2tp_create,
+	.ioctl		= pppol2tp_ioctl
+};
+
+static int __init pppol2tp_init(void)
+{
+	int err;
+
+	err = proto_register(&pppol2tp_sk_proto, 0);
+	if (err)
+		goto out;
+	err = register_pppox_proto(PX_PROTO_OL2TP, &pppol2tp_proto);
+	if (err)
+		goto out_unregister_pppol2tp_proto;
+
+#ifdef CONFIG_PROC_FS
+	pppol2tp_proc = create_proc_entry("pppol2tp", 0, proc_net);
+	if (!pppol2tp_proc) {
+		err = -ENOMEM;
+		goto out_unregister_pppox_proto;
+	}
+	pppol2tp_proc->proc_fops = &pppol2tp_proc_fops;
+#endif /* CONFIG_PROC_FS */
+	printk(KERN_INFO "PPPoL2TP kernel driver, %s\n",
+	       PPPOL2TP_DRV_VERSION);
+
+out:
+	return err;
+
+out_unregister_pppox_proto:
+	unregister_pppox_proto(PX_PROTO_OL2TP);
+out_unregister_pppol2tp_proto:
+	proto_unregister(&pppol2tp_sk_proto);
+	goto out;
+}
+
+static void __exit pppol2tp_exit(void)
+{
+	unregister_pppox_proto(PX_PROTO_OL2TP);
+
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("pppol2tp", proc_net);
+#endif
+	proto_unregister(&pppol2tp_sk_proto);
+}
+
+module_init(pppol2tp_init);
+module_exit(pppol2tp_exit);
+
+MODULE_AUTHOR("Martijn van Oosterhout <kleptog@svana.org>,"
+	      "James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("PPP over L2TP over UDP");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PPPOL2TP_DRV_VERSION);
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
new file mode 100644
index 0000000..08d2506
--- /dev/null
+++ b/drivers/net/ps3_gelic_net.c
@@ -0,0 +1,1576 @@
+/*
+ *  PS3 gelic network driver.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * This file is based on: spider_net.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ *           Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#include <linux/dma-mapping.h>
+#include <net/checksum.h>
+#include <asm/firmware.h>
+#include <asm/ps3.h>
+#include <asm/lv1call.h>
+
+#include "ps3_gelic_net.h"
+
+#define DRV_NAME "Gelic Network Driver"
+#define DRV_VERSION "1.0"
+
+MODULE_AUTHOR("SCE Inc.");
+MODULE_DESCRIPTION("Gelic Network driver");
+MODULE_LICENSE("GPL");
+
+static inline struct device *ctodev(struct gelic_net_card *card)
+{
+	return &card->dev->core;
+}
+static inline unsigned int bus_id(struct gelic_net_card *card)
+{
+	return card->dev->bus_id;
+}
+static inline unsigned int dev_id(struct gelic_net_card *card)
+{
+	return card->dev->dev_id;
+}
+
+/* set irq_mask */
+static int gelic_net_set_irq_mask(struct gelic_net_card *card, u64 mask)
+{
+	int status;
+
+	status = lv1_net_set_interrupt_mask(bus_id(card), dev_id(card),
+					    mask, 0);
+	if (status)
+		dev_info(ctodev(card),
+			 "lv1_net_set_interrupt_mask failed %d\n", status);
+	return status;
+}
+static inline void gelic_net_rx_irq_on(struct gelic_net_card *card)
+{
+	gelic_net_set_irq_mask(card, card->ghiintmask | GELIC_NET_RXINT);
+}
+static inline void gelic_net_rx_irq_off(struct gelic_net_card *card)
+{
+	gelic_net_set_irq_mask(card, card->ghiintmask & ~GELIC_NET_RXINT);
+}
+/**
+ * gelic_net_get_descr_status -- returns the status of a descriptor
+ * @descr: descriptor to look at
+ *
+ * returns the status as in the dmac_cmd_status field of the descriptor
+ */
+static enum gelic_net_descr_status
+gelic_net_get_descr_status(struct gelic_net_descr *descr)
+{
+	u32 cmd_status;
+
+	cmd_status = descr->dmac_cmd_status;
+	cmd_status >>= GELIC_NET_DESCR_IND_PROC_SHIFT;
+	return cmd_status;
+}
+
+/**
+ * gelic_net_set_descr_status -- sets the status of a descriptor
+ * @descr: descriptor to change
+ * @status: status to set in the descriptor
+ *
+ * changes the status to the specified value. Doesn't change other bits
+ * in the status
+ */
+static void gelic_net_set_descr_status(struct gelic_net_descr *descr,
+				       enum gelic_net_descr_status status)
+{
+	u32 cmd_status;
+
+	/* read the status */
+	cmd_status = descr->dmac_cmd_status;
+	/* clean the upper 4 bits */
+	cmd_status &= GELIC_NET_DESCR_IND_PROC_MASKO;
+	/* add the status to it */
+	cmd_status |= ((u32)status) << GELIC_NET_DESCR_IND_PROC_SHIFT;
+	/* and write it back */
+	descr->dmac_cmd_status = cmd_status;
+	/*
+	 * dma_cmd_status field is used to indicate whether the descriptor
+	 * is valid or not.
+	 * Usually caller of this function wants to inform that to the
+	 * hardware, so we assure here the hardware sees the change.
+	 */
+	wmb();
+}
+
+/**
+ * gelic_net_free_chain - free descriptor chain
+ * @card: card structure
+ * @descr_in: address of desc
+ */
+static void gelic_net_free_chain(struct gelic_net_card *card,
+				 struct gelic_net_descr *descr_in)
+{
+	struct gelic_net_descr *descr;
+
+	for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) {
+		dma_unmap_single(ctodev(card), descr->bus_addr,
+				 GELIC_NET_DESCR_SIZE, DMA_BIDIRECTIONAL);
+		descr->bus_addr = 0;
+	}
+}
+
+/**
+ * gelic_net_init_chain - links descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ * @start_descr: address of descriptor array
+ * @no: number of descriptors
+ *
+ * we manage a circular list that mirrors the hardware structure,
+ * except that the hardware uses bus addresses.
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_init_chain(struct gelic_net_card *card,
+				struct gelic_net_descr_chain *chain,
+				struct gelic_net_descr *start_descr, int no)
+{
+	int i;
+	struct gelic_net_descr *descr;
+
+	descr = start_descr;
+	memset(descr, 0, sizeof(*descr) * no);
+
+	/* set up the hardware pointers in each descriptor */
+	for (i = 0; i < no; i++, descr++) {
+		gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+		descr->bus_addr =
+			dma_map_single(ctodev(card), descr,
+				       GELIC_NET_DESCR_SIZE,
+				       DMA_BIDIRECTIONAL);
+
+		if (!descr->bus_addr)
+			goto iommu_error;
+
+		descr->next = descr + 1;
+		descr->prev = descr - 1;
+	}
+	/* make them as ring */
+	(descr - 1)->next = start_descr;
+	start_descr->prev = (descr - 1);
+
+	/* chain bus addr of hw descriptor */
+	descr = start_descr;
+	for (i = 0; i < no; i++, descr++) {
+		descr->next_descr_addr = descr->next->bus_addr;
+	}
+
+	chain->head = start_descr;
+	chain->tail = start_descr;
+
+	/* do not chain last hw descriptor */
+	(descr - 1)->next_descr_addr = 0;
+
+	return 0;
+
+iommu_error:
+	for (i--, descr--; 0 <= i; i--, descr--)
+		if (descr->bus_addr)
+			dma_unmap_single(ctodev(card), descr->bus_addr,
+					 GELIC_NET_DESCR_SIZE,
+					 DMA_BIDIRECTIONAL);
+	return -ENOMEM;
+}
+
+/**
+ * gelic_net_prepare_rx_descr - reinitializes a rx descriptor
+ * @card: card structure
+ * @descr: descriptor to re-init
+ *
+ * return 0 on succes, <0 on failure
+ *
+ * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
+ * Activate the descriptor state-wise
+ */
+static int gelic_net_prepare_rx_descr(struct gelic_net_card *card,
+				      struct gelic_net_descr *descr)
+{
+	int offset;
+	unsigned int bufsize;
+
+	if (gelic_net_get_descr_status(descr) !=  GELIC_NET_DESCR_NOT_IN_USE) {
+		dev_info(ctodev(card), "%s: ERROR status \n", __func__);
+	}
+	/* we need to round up the buffer size to a multiple of 128 */
+	bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
+
+	/* and we need to have it 128 byte aligned, therefore we allocate a
+	 * bit more */
+	descr->skb = netdev_alloc_skb(card->netdev,
+		bufsize + GELIC_NET_RXBUF_ALIGN - 1);
+	if (!descr->skb) {
+		descr->buf_addr = 0; /* tell DMAC don't touch memory */
+		dev_info(ctodev(card),
+			 "%s:allocate skb failed !!\n", __func__);
+		return -ENOMEM;
+	}
+	descr->buf_size = bufsize;
+	descr->dmac_cmd_status = 0;
+	descr->result_size = 0;
+	descr->valid_size = 0;
+	descr->data_error = 0;
+
+	offset = ((unsigned long)descr->skb->data) &
+		(GELIC_NET_RXBUF_ALIGN - 1);
+	if (offset)
+		skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
+	/* io-mmu-map the skb */
+	descr->buf_addr = dma_map_single(ctodev(card), descr->skb->data,
+					 GELIC_NET_MAX_MTU,
+					 DMA_FROM_DEVICE);
+	if (!descr->buf_addr) {
+		dev_kfree_skb_any(descr->skb);
+		descr->skb = NULL;
+		dev_info(ctodev(card),
+			 "%s:Could not iommu-map rx buffer\n", __func__);
+		gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+		return -ENOMEM;
+	} else {
+		gelic_net_set_descr_status(descr, GELIC_NET_DESCR_CARDOWNED);
+		return 0;
+	}
+}
+
+/**
+ * gelic_net_release_rx_chain - free all skb of rx descr
+ * @card: card structure
+ *
+ */
+static void gelic_net_release_rx_chain(struct gelic_net_card *card)
+{
+	struct gelic_net_descr *descr = card->rx_chain.head;
+
+	do {
+		if (descr->skb) {
+			dma_unmap_single(ctodev(card),
+					 descr->buf_addr,
+					 descr->skb->len,
+					 DMA_FROM_DEVICE);
+			descr->buf_addr = 0;
+			dev_kfree_skb_any(descr->skb);
+			descr->skb = NULL;
+			descr->dmac_cmd_status = GELIC_NET_DESCR_NOT_IN_USE;
+		}
+		descr = descr->next;
+	} while (descr != card->rx_chain.head);
+}
+
+/**
+ * gelic_net_fill_rx_chain - fills descriptors/skbs in the rx chains
+ * @card: card structure
+ *
+ * fills all descriptors in the rx chain: allocates skbs
+ * and iommu-maps them.
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_fill_rx_chain(struct gelic_net_card *card)
+{
+	struct gelic_net_descr *descr = card->rx_chain.head;
+	int ret;
+
+	do {
+		if (!descr->skb) {
+			ret = gelic_net_prepare_rx_descr(card, descr);
+			if (ret)
+				goto rewind;
+		}
+		descr = descr->next;
+	} while (descr != card->rx_chain.head);
+
+	return 0;
+rewind:
+	gelic_net_release_rx_chain(card);
+	return ret;
+}
+
+/**
+ * gelic_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_alloc_rx_skbs(struct gelic_net_card *card)
+{
+	struct gelic_net_descr_chain *chain;
+	int ret;
+	chain = &card->rx_chain;
+	ret = gelic_net_fill_rx_chain(card);
+	chain->head = card->rx_top->prev; /* point to the last */
+	return ret;
+}
+
+/**
+ * gelic_net_release_tx_descr - processes a used tx descriptor
+ * @card: card structure
+ * @descr: descriptor to release
+ *
+ * releases a used tx descriptor (unmapping, freeing of skb)
+ */
+static void gelic_net_release_tx_descr(struct gelic_net_card *card,
+			    struct gelic_net_descr *descr)
+{
+	struct sk_buff *skb;
+
+
+	if (descr->data_status & (1 << GELIC_NET_TXDESC_TAIL)) {
+		/* 2nd descriptor */
+		skb = descr->skb;
+		dma_unmap_single(ctodev(card), descr->buf_addr, skb->len,
+				 DMA_TO_DEVICE);
+		dev_kfree_skb_any(skb);
+	} else {
+		dma_unmap_single(ctodev(card), descr->buf_addr,
+				 descr->buf_size, DMA_TO_DEVICE);
+	}
+
+	descr->buf_addr = 0;
+	descr->buf_size = 0;
+	descr->next_descr_addr = 0;
+	descr->result_size = 0;
+	descr->valid_size = 0;
+	descr->data_status = 0;
+	descr->data_error = 0;
+	descr->skb = NULL;
+
+	/* set descr status */
+	descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE;
+}
+
+/**
+ * gelic_net_release_tx_chain - processes sent tx descriptors
+ * @card: adapter structure
+ * @stop: net_stop sequence
+ *
+ * releases the tx descriptors that gelic has finished with
+ */
+static void gelic_net_release_tx_chain(struct gelic_net_card *card, int stop)
+{
+	struct gelic_net_descr_chain *tx_chain;
+	enum gelic_net_descr_status status;
+	int release = 0;
+
+	for (tx_chain = &card->tx_chain;
+	     tx_chain->head != tx_chain->tail && tx_chain->tail;
+	     tx_chain->tail = tx_chain->tail->next) {
+		status = gelic_net_get_descr_status(tx_chain->tail);
+		switch (status) {
+		case GELIC_NET_DESCR_RESPONSE_ERROR:
+		case GELIC_NET_DESCR_PROTECTION_ERROR:
+		case GELIC_NET_DESCR_FORCE_END:
+			if (printk_ratelimit())
+				dev_info(ctodev(card),
+					 "%s: forcing end of tx descriptor " \
+					 "with status %x\n",
+					 __func__, status);
+			card->netdev_stats.tx_dropped++;
+			break;
+
+		case GELIC_NET_DESCR_COMPLETE:
+			card->netdev_stats.tx_packets++;
+			card->netdev_stats.tx_bytes +=
+				tx_chain->tail->skb->len;
+			break;
+
+		case GELIC_NET_DESCR_CARDOWNED:
+			/* pending tx request */
+		default:
+			/* any other value (== GELIC_NET_DESCR_NOT_IN_USE) */
+			goto out;
+		}
+		gelic_net_release_tx_descr(card, tx_chain->tail);
+		release = 1;
+	}
+out:
+	if (!stop && release)
+		netif_wake_queue(card->netdev);
+}
+
+/**
+ * gelic_net_set_multi - sets multicast addresses and promisc flags
+ * @netdev: interface device structure
+ *
+ * gelic_net_set_multi configures multicast addresses as needed for the
+ * netdev interface. It also sets up multicast, allmulti and promisc
+ * flags appropriately
+ */
+static void gelic_net_set_multi(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	struct dev_mc_list *mc;
+	unsigned int i;
+	uint8_t *p;
+	u64 addr;
+	int status;
+
+	/* clear all multicast address */
+	status = lv1_net_remove_multicast_address(bus_id(card), dev_id(card),
+						  0, 1);
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_remove_multicast_address failed %d\n",
+			status);
+	/* set broadcast address */
+	status = lv1_net_add_multicast_address(bus_id(card), dev_id(card),
+					       GELIC_NET_BROADCAST_ADDR, 0);
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_add_multicast_address failed, %d\n",
+			status);
+
+	if (netdev->flags & IFF_ALLMULTI
+		|| netdev->mc_count > GELIC_NET_MC_COUNT_MAX) { /* list max */
+		status = lv1_net_add_multicast_address(bus_id(card),
+						       dev_id(card),
+						       0, 1);
+		if (status)
+			dev_err(ctodev(card),
+				"lv1_net_add_multicast_address failed, %d\n",
+				status);
+		return;
+	}
+
+	/* set multicast address */
+	for (mc = netdev->mc_list; mc; mc = mc->next) {
+		addr = 0;
+		p = mc->dmi_addr;
+		for (i = 0; i < ETH_ALEN; i++) {
+			addr <<= 8;
+			addr |= *p++;
+		}
+		status = lv1_net_add_multicast_address(bus_id(card),
+						       dev_id(card),
+						       addr, 0);
+		if (status)
+			dev_err(ctodev(card),
+				"lv1_net_add_multicast_address failed, %d\n",
+				status);
+	}
+}
+
+/**
+ * gelic_net_enable_rxdmac - enables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
+ * in the GDADMACCNTR register
+ */
+static inline void gelic_net_enable_rxdmac(struct gelic_net_card *card)
+{
+	int status;
+
+	status = lv1_net_start_rx_dma(bus_id(card), dev_id(card),
+				card->rx_chain.tail->bus_addr, 0);
+	if (status)
+		dev_info(ctodev(card),
+			 "lv1_net_start_rx_dma failed, status=%d\n", status);
+}
+
+/**
+ * gelic_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_net_disable_rxdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static inline void gelic_net_disable_rxdmac(struct gelic_net_card *card)
+{
+	int status;
+
+	/* this hvc blocks until the DMA in progress really stopped */
+	status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0);
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_stop_rx_dma faild, %d\n", status);
+}
+
+/**
+ * gelic_net_disable_txdmac - disables the transmit DMA controller
+ * @card: card structure
+ *
+ * gelic_net_disable_txdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static inline void gelic_net_disable_txdmac(struct gelic_net_card *card)
+{
+	int status;
+
+	/* this hvc blocks until the DMA in progress really stopped */
+	status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0);
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_stop_tx_dma faild, status=%d\n", status);
+}
+
+/**
+ * gelic_net_stop - called upon ifconfig down
+ * @netdev: interface device structure
+ *
+ * always returns 0
+ */
+static int gelic_net_stop(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	netif_poll_disable(netdev);
+	netif_stop_queue(netdev);
+
+	/* turn off DMA, force end */
+	gelic_net_disable_rxdmac(card);
+	gelic_net_disable_txdmac(card);
+
+	gelic_net_set_irq_mask(card, 0);
+
+	/* disconnect event port */
+	free_irq(card->netdev->irq, card->netdev);
+	ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq);
+	card->netdev->irq = NO_IRQ;
+
+	netif_carrier_off(netdev);
+
+	/* release chains */
+	gelic_net_release_tx_chain(card, 1);
+	gelic_net_release_rx_chain(card);
+
+	gelic_net_free_chain(card, card->tx_top);
+	gelic_net_free_chain(card, card->rx_top);
+
+	return 0;
+}
+
+/**
+ * gelic_net_get_next_tx_descr - returns the next available tx descriptor
+ * @card: device structure to get descriptor from
+ *
+ * returns the address of the next descriptor, or NULL if not available.
+ */
+static struct gelic_net_descr *
+gelic_net_get_next_tx_descr(struct gelic_net_card *card)
+{
+	if (!card->tx_chain.head)
+		return NULL;
+	/*  see if we can two consecutive free descrs */
+	if (card->tx_chain.tail != card->tx_chain.head->next &&
+	    gelic_net_get_descr_status(card->tx_chain.head) ==
+	    GELIC_NET_DESCR_NOT_IN_USE &&
+	    card->tx_chain.tail != card->tx_chain.head->next->next &&
+	    gelic_net_get_descr_status(card->tx_chain.head->next) ==
+	     GELIC_NET_DESCR_NOT_IN_USE )
+		return card->tx_chain.head;
+	else
+		return NULL;
+
+}
+
+/**
+ * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field
+ * @descr: descriptor structure to fill out
+ * @skb: packet to consider
+ * @middle: middle of frame
+ *
+ * fills out the command and status field of the descriptor structure,
+ * depending on hardware checksum settings. This function assumes a wmb()
+ * has executed before.
+ */
+static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr,
+					  struct sk_buff *skb, int middle)
+{
+	u32 eofr;
+
+	if (middle)
+		eofr = 0;
+	else
+		eofr = GELIC_NET_DMAC_CMDSTAT_END_FRAME;
+
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOCS | eofr;
+	else {
+		/* is packet ip?
+		 * if yes: tcp? udp? */
+		if (skb->protocol == htons(ETH_P_IP)) {
+			if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+				descr->dmac_cmd_status =
+					GELIC_NET_DMAC_CMDSTAT_TCPCS | eofr;
+			else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+				descr->dmac_cmd_status =
+					GELIC_NET_DMAC_CMDSTAT_UDPCS | eofr;
+			else	/*
+				 * the stack should checksum non-tcp and non-udp
+				 * packets on his own: NETIF_F_IP_CSUM
+				 */
+				descr->dmac_cmd_status =
+					GELIC_NET_DMAC_CMDSTAT_NOCS | eofr;
+		}
+	}
+}
+
+/**
+ * gelic_net_prepare_tx_descr_v - get dma address of skb_data
+ * @card: card structure
+ * @descr: descriptor structure
+ * @skb: packet to use
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ */
+static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card,
+					struct gelic_net_descr *descr,
+					struct sk_buff *skb)
+{
+	dma_addr_t buf[2];
+	unsigned int vlan_len;
+
+	if (skb->len < GELIC_NET_VLAN_POS)
+		return -EINVAL;
+
+	memcpy(&descr->vlan, skb->data, GELIC_NET_VLAN_POS);
+	if (card->vlan_index != -1) {
+		descr->vlan.h_vlan_proto = htons(ETH_P_8021Q); /* vlan 0x8100*/
+		descr->vlan.h_vlan_TCI = htons(card->vlan_id[card->vlan_index]);
+		vlan_len = GELIC_NET_VLAN_POS + VLAN_HLEN; /* VLAN_HLEN=4 */
+	} else
+		vlan_len = GELIC_NET_VLAN_POS; /* no vlan tag */
+
+	/* first descr */
+	buf[0] = dma_map_single(ctodev(card), &descr->vlan,
+			     vlan_len, DMA_TO_DEVICE);
+
+	if (!buf[0]) {
+		dev_err(ctodev(card),
+			"dma map 1 failed (%p, %i). Dropping packet\n",
+			skb->data, vlan_len);
+		return -ENOMEM;
+	}
+
+	descr->buf_addr = buf[0];
+	descr->buf_size = vlan_len;
+	descr->skb = skb; /* not used */
+	descr->data_status = 0;
+	gelic_net_set_txdescr_cmdstat(descr, skb, 1); /* not the frame end */
+
+	/* second descr */
+	card->tx_chain.head = card->tx_chain.head->next;
+	descr->next_descr_addr = descr->next->bus_addr;
+	descr = descr->next;
+	if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE)
+		/* XXX will be removed */
+		dev_err(ctodev(card), "descr is not free!\n");
+
+	buf[1] = dma_map_single(ctodev(card), skb->data + GELIC_NET_VLAN_POS,
+			     skb->len - GELIC_NET_VLAN_POS,
+			     DMA_TO_DEVICE);
+
+	if (!buf[1]) {
+		dev_err(ctodev(card),
+			"dma map 2 failed (%p, %i). Dropping packet\n",
+			skb->data + GELIC_NET_VLAN_POS,
+			skb->len - GELIC_NET_VLAN_POS);
+		dma_unmap_single(ctodev(card), buf[0], vlan_len,
+				 DMA_TO_DEVICE);
+		return -ENOMEM;
+	}
+
+	descr->buf_addr = buf[1];
+	descr->buf_size = skb->len - GELIC_NET_VLAN_POS;
+	descr->skb = skb;
+	descr->data_status = 0;
+	descr->next_descr_addr = 0; /* terminate hw descr */
+	gelic_net_set_txdescr_cmdstat(descr, skb, 0);
+
+	return 0;
+}
+
+/**
+ * gelic_net_kick_txdma - enables TX DMA processing
+ * @card: card structure
+ * @descr: descriptor address to enable TX processing at
+ *
+ */
+static int gelic_net_kick_txdma(struct gelic_net_card *card,
+				struct gelic_net_descr *descr)
+{
+	int status = -ENXIO;
+	int count = 10;
+
+	if (card->tx_dma_progress)
+		return 0;
+
+	if (gelic_net_get_descr_status(descr) == GELIC_NET_DESCR_CARDOWNED) {
+		card->tx_dma_progress = 1;
+		/* sometimes we need retry here */
+		while (count--) {
+			status = lv1_net_start_tx_dma(bus_id(card),
+						      dev_id(card),
+						      descr->bus_addr, 0);
+			if (!status)
+				break;
+		}
+		if (!count)
+			dev_info(ctodev(card), "lv1_net_start_txdma failed," \
+				"status=%d %#lx\n",
+				 status, card->irq_status);
+	}
+	return status;
+}
+
+/**
+ * gelic_net_xmit - transmits a frame over the device
+ * @skb: packet to send out
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	struct gelic_net_descr *descr = NULL;
+	int result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->tx_dma_lock, flags);
+
+	gelic_net_release_tx_chain(card, 0);
+	if (!skb)
+		goto kick;
+	descr = gelic_net_get_next_tx_descr(card);
+	if (!descr) {
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+	result = gelic_net_prepare_tx_descr_v(card, descr, skb);
+
+	if (result)
+		goto error;
+
+	card->tx_chain.head = card->tx_chain.head->next;
+
+	if (descr->prev)
+		descr->prev->next_descr_addr = descr->bus_addr;
+kick:
+	/*
+	 * as hardware descriptor is modified in the above lines,
+	 * ensure that the hardware sees it
+	 */
+	wmb();
+	if (gelic_net_kick_txdma(card, card->tx_chain.tail))
+		goto error;
+
+	netdev->trans_start = jiffies;
+	spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+	return NETDEV_TX_OK;
+
+error:
+	card->netdev_stats.tx_dropped++;
+	spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+	return NETDEV_TX_LOCKED;
+}
+
+/**
+ * gelic_net_pass_skb_up - takes an skb from a descriptor and passes it on
+ * @descr: descriptor to process
+ * @card: card structure
+ *
+ * iommu-unmaps the skb, fills out skb structure and passes the data to the
+ * stack. The descriptor state is not changed.
+ */
+static void gelic_net_pass_skb_up(struct gelic_net_descr *descr,
+				 struct gelic_net_card *card)
+{
+	struct sk_buff *skb;
+	struct net_device *netdev;
+	u32 data_status, data_error;
+
+	data_status = descr->data_status;
+	data_error = descr->data_error;
+	netdev = card->netdev;
+	/* unmap skb buffer */
+	skb = descr->skb;
+	dma_unmap_single(ctodev(card), descr->buf_addr, GELIC_NET_MAX_MTU,
+			 DMA_FROM_DEVICE);
+
+	skb_put(skb, descr->valid_size? descr->valid_size : descr->result_size);
+	if (!descr->valid_size)
+		dev_info(ctodev(card), "buffer full %x %x %x\n",
+			 descr->result_size, descr->buf_size,
+			 descr->dmac_cmd_status);
+
+	descr->skb = NULL;
+	/*
+	 * the card put 2 bytes vlan tag in front
+	 * of the ethernet frame
+	 */
+	skb_pull(skb, 2);
+	skb->protocol = eth_type_trans(skb, netdev);
+
+	/* checksum offload */
+	if (card->rx_csum) {
+		if ((data_status & GELIC_NET_DATA_STATUS_CHK_MASK) &&
+		    (!(data_error & GELIC_NET_DATA_ERROR_CHK_MASK)))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			skb->ip_summed = CHECKSUM_NONE;
+	} else
+		skb->ip_summed = CHECKSUM_NONE;
+
+	/* update netdevice statistics */
+	card->netdev_stats.rx_packets++;
+	card->netdev_stats.rx_bytes += skb->len;
+
+	/* pass skb up to stack */
+	netif_receive_skb(skb);
+}
+
+/**
+ * gelic_net_decode_one_descr - processes an rx descriptor
+ * @card: card structure
+ *
+ * returns 1 if a packet has been sent to the stack, otherwise 0
+ *
+ * processes an rx descriptor by iommu-unmapping the data buffer and passing
+ * the packet up to the stack
+ */
+static int gelic_net_decode_one_descr(struct gelic_net_card *card)
+{
+	enum gelic_net_descr_status status;
+	struct gelic_net_descr_chain *chain = &card->rx_chain;
+	struct gelic_net_descr *descr = chain->tail;
+	int dmac_chain_ended;
+
+	status = gelic_net_get_descr_status(descr);
+	/* is this descriptor terminated with next_descr == NULL? */
+	dmac_chain_ended =
+		descr->dmac_cmd_status & GELIC_NET_DMAC_CMDSTAT_RXDCEIS;
+
+	if (status == GELIC_NET_DESCR_CARDOWNED)
+		return 0;
+
+	if (status == GELIC_NET_DESCR_NOT_IN_USE) {
+		dev_dbg(ctodev(card), "dormant descr? %p\n", descr);
+		return 0;
+	}
+
+	if ((status == GELIC_NET_DESCR_RESPONSE_ERROR) ||
+	    (status == GELIC_NET_DESCR_PROTECTION_ERROR) ||
+	    (status == GELIC_NET_DESCR_FORCE_END)) {
+		dev_info(ctodev(card), "dropping RX descriptor with state %x\n",
+			 status);
+		card->netdev_stats.rx_dropped++;
+		goto refill;
+	}
+
+	if ((status != GELIC_NET_DESCR_COMPLETE) &&
+	    (status != GELIC_NET_DESCR_FRAME_END)) {
+		dev_dbg(ctodev(card), "RX descriptor with state %x\n",
+			status);
+		goto refill;
+	}
+
+	/* ok, we've got a packet in descr */
+	gelic_net_pass_skb_up(descr, card); /* 1: skb_up sccess */
+
+refill:
+	descr->next_descr_addr = 0; /* unlink the descr */
+
+	/* change the descriptor state: */
+	gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+
+	/* refill one desc
+	 * FIXME: this can fail, but for now, just leave this
+	 * descriptor without skb
+	 */
+	gelic_net_prepare_rx_descr(card, descr);
+	chain->head = descr;
+	chain->tail = descr->next;
+	descr->prev->next_descr_addr = descr->bus_addr;
+
+	if (dmac_chain_ended) {
+		gelic_net_enable_rxdmac(card);
+		dev_dbg(ctodev(card), "reenable rx dma\n");
+	}
+
+	return 1;
+}
+
+/**
+ * gelic_net_poll - NAPI poll function called by the stack to return packets
+ * @netdev: interface device structure
+ * @budget: number of packets we can pass to the stack at most
+ *
+ * returns 0 if no more packets available to the driver/stack. Returns 1,
+ * if the quota is exceeded, but the driver has still packets.
+ *
+ */
+static int gelic_net_poll(struct net_device *netdev, int *budget)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	int packets_to_do, packets_done = 0;
+	int no_more_packets = 0;
+
+	packets_to_do = min(*budget, netdev->quota);
+
+	while (packets_to_do) {
+		if (gelic_net_decode_one_descr(card)) {
+			packets_done++;
+			packets_to_do--;
+		} else {
+			/* no more packets for the stack */
+			no_more_packets = 1;
+			break;
+		}
+	}
+	netdev->quota -= packets_done;
+	*budget -= packets_done;
+	if (no_more_packets) {
+		netif_rx_complete(netdev);
+		gelic_net_rx_irq_on(card);
+		return 0;
+	} else
+		return 1;
+}
+
+/**
+ * gelic_net_get_stats - get interface statistics
+ * @netdev: interface device structure
+ *
+ * returns the interface statistics residing in the gelic_net_card struct
+ */
+static struct net_device_stats *gelic_net_get_stats(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	return &card->netdev_stats;
+}
+
+/**
+ * gelic_net_change_mtu - changes the MTU of an interface
+ * @netdev: interface device structure
+ * @new_mtu: new MTU value
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	/* no need to re-alloc skbs or so -- the max mtu is about 2.3k
+	 * and mtu is outbound only anyway */
+	if ((new_mtu < GELIC_NET_MIN_MTU) ||
+	    (new_mtu > GELIC_NET_MAX_MTU)) {
+		return -EINVAL;
+	}
+	netdev->mtu = new_mtu;
+	return 0;
+}
+
+/**
+ * gelic_net_interrupt - event handler for gelic_net
+ */
+static irqreturn_t gelic_net_interrupt(int irq, void *ptr)
+{
+	unsigned long flags;
+	struct net_device *netdev = ptr;
+	struct gelic_net_card *card = netdev_priv(netdev);
+	u64 status;
+
+	status = card->irq_status;
+
+	if (!status)
+		return IRQ_NONE;
+
+	if (status & GELIC_NET_RXINT) {
+		gelic_net_rx_irq_off(card);
+		netif_rx_schedule(netdev);
+	}
+
+	if (status & GELIC_NET_TXINT) {
+		spin_lock_irqsave(&card->tx_dma_lock, flags);
+		card->tx_dma_progress = 0;
+		spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+		/* start pending DMA */
+		gelic_net_xmit(NULL, netdev);
+	}
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * gelic_net_poll_controller - artificial interrupt for netconsole etc.
+ * @netdev: interface device structure
+ *
+ * see Documentation/networking/netconsole.txt
+ */
+static void gelic_net_poll_controller(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	gelic_net_set_irq_mask(card, 0);
+	gelic_net_interrupt(netdev->irq, netdev);
+	gelic_net_set_irq_mask(card, card->ghiintmask);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+/**
+ * gelic_net_open_device - open device and map dma region
+ * @card: card structure
+ */
+static int gelic_net_open_device(struct gelic_net_card *card)
+{
+	int result;
+
+	result = ps3_sb_event_receive_port_setup(card->dev, PS3_BINDING_CPU_ANY,
+		&card->netdev->irq);
+
+	if (result) {
+		dev_info(ctodev(card),
+			 "%s:%d: gelic_net_open_device failed (%d)\n",
+			 __func__, __LINE__, result);
+		result = -EPERM;
+		goto fail_alloc_irq;
+	}
+
+	result = request_irq(card->netdev->irq, gelic_net_interrupt,
+			     IRQF_DISABLED, "gelic network", card->netdev);
+
+	if (result) {
+		dev_info(ctodev(card), "%s:%d: request_irq failed (%d)\n",
+			__func__, __LINE__, result);
+		goto fail_request_irq;
+	}
+
+	return 0;
+
+fail_request_irq:
+	ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq);
+	card->netdev->irq = NO_IRQ;
+fail_alloc_irq:
+	return result;
+}
+
+
+/**
+ * gelic_net_open - called upon ifonfig up
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * gelic_net_open allocates all the descriptors and memory needed for
+ * operation, sets up multicast list and enables interrupts
+ */
+static int gelic_net_open(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	dev_dbg(ctodev(card), " -> %s:%d\n", __func__, __LINE__);
+
+	gelic_net_open_device(card);
+
+	if (gelic_net_init_chain(card, &card->tx_chain,
+			card->descr, GELIC_NET_TX_DESCRIPTORS))
+		goto alloc_tx_failed;
+	if (gelic_net_init_chain(card, &card->rx_chain,
+				 card->descr + GELIC_NET_RX_DESCRIPTORS,
+				 GELIC_NET_RX_DESCRIPTORS))
+		goto alloc_rx_failed;
+
+	/* head of chain */
+	card->tx_top = card->tx_chain.head;
+	card->rx_top = card->rx_chain.head;
+	dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n",
+		card->rx_top, card->tx_top, sizeof(struct gelic_net_descr),
+		GELIC_NET_RX_DESCRIPTORS);
+	/* allocate rx skbs */
+	if (gelic_net_alloc_rx_skbs(card))
+		goto alloc_skbs_failed;
+
+	card->tx_dma_progress = 0;
+	card->ghiintmask = GELIC_NET_RXINT | GELIC_NET_TXINT;
+
+	gelic_net_set_irq_mask(card, card->ghiintmask);
+	gelic_net_enable_rxdmac(card);
+
+	netif_start_queue(netdev);
+	netif_carrier_on(netdev);
+	netif_poll_enable(netdev);
+
+	return 0;
+
+alloc_skbs_failed:
+	gelic_net_free_chain(card, card->rx_top);
+alloc_rx_failed:
+	gelic_net_free_chain(card, card->tx_top);
+alloc_tx_failed:
+	return -ENOMEM;
+}
+
+#ifdef GELIC_NET_ETHTOOL
+static void gelic_net_get_drvinfo (struct net_device *netdev,
+				   struct ethtool_drvinfo *info)
+{
+	strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1);
+	strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1);
+}
+
+static int gelic_net_get_settings(struct net_device *netdev,
+				  struct ethtool_cmd *cmd)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	int status;
+	u64 v1, v2;
+	int speed, duplex;
+
+	speed = duplex = -1;
+	status = lv1_net_control(bus_id(card), dev_id(card),
+			GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
+			&v1, &v2);
+	if (status) {
+		/* link down */
+	} else {
+		if (v1 & GELIC_NET_FULL_DUPLEX) {
+			duplex = DUPLEX_FULL;
+		} else {
+			duplex = DUPLEX_HALF;
+		}
+
+		if (v1 & GELIC_NET_SPEED_10 ) {
+			speed = SPEED_10;
+		} else if (v1 & GELIC_NET_SPEED_100) {
+			speed = SPEED_100;
+		} else if (v1 & GELIC_NET_SPEED_1000) {
+			speed = SPEED_1000;
+		}
+	}
+	cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg |
+			SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+			SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+			SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
+	cmd->advertising = cmd->supported;
+	cmd->speed = speed;
+	cmd->duplex = duplex;
+	cmd->autoneg = AUTONEG_ENABLE; /* always enabled */
+	cmd->port = PORT_TP;
+
+	return 0;
+}
+
+static u32 gelic_net_get_link(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	int status;
+	u64 v1, v2;
+	int link;
+
+	status = lv1_net_control(bus_id(card), dev_id(card),
+			GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
+			&v1, &v2);
+	if (status)
+		return 0; /* link down */
+
+	if (v1 & GELIC_NET_LINK_UP)
+		link = 1;
+	else
+		link = 0;
+
+	return link;
+}
+
+static int gelic_net_nway_reset(struct net_device *netdev)
+{
+	if (netif_running(netdev)) {
+		gelic_net_stop(netdev);
+		gelic_net_open(netdev);
+	}
+	return 0;
+}
+
+static u32 gelic_net_get_tx_csum(struct net_device *netdev)
+{
+	return (netdev->features & NETIF_F_IP_CSUM) != 0;
+}
+
+static int gelic_net_set_tx_csum(struct net_device *netdev, u32 data)
+{
+	if (data)
+		netdev->features |= NETIF_F_IP_CSUM;
+	else
+		netdev->features &= ~NETIF_F_IP_CSUM;
+
+	return 0;
+}
+
+static u32 gelic_net_get_rx_csum(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	return card->rx_csum;
+}
+
+static int gelic_net_set_rx_csum(struct net_device *netdev, u32 data)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	card->rx_csum = data;
+	return 0;
+}
+
+static struct ethtool_ops gelic_net_ethtool_ops = {
+	.get_drvinfo	= gelic_net_get_drvinfo,
+	.get_settings	= gelic_net_get_settings,
+	.get_link	= gelic_net_get_link,
+	.nway_reset	= gelic_net_nway_reset,
+	.get_tx_csum	= gelic_net_get_tx_csum,
+	.set_tx_csum	= gelic_net_set_tx_csum,
+	.get_rx_csum	= gelic_net_get_rx_csum,
+	.set_rx_csum	= gelic_net_set_rx_csum,
+};
+#endif
+
+/**
+ * gelic_net_tx_timeout_task - task scheduled by the watchdog timeout
+ * function (to be called not under interrupt status)
+ * @work: work is context of tx timout task
+ *
+ * called as task when tx hangs, resets interface (if interface is up)
+ */
+static void gelic_net_tx_timeout_task(struct work_struct *work)
+{
+	struct gelic_net_card *card =
+		container_of(work, struct gelic_net_card, tx_timeout_task);
+	struct net_device *netdev = card->netdev;
+
+	dev_info(ctodev(card), "%s:Timed out. Restarting... \n", __func__);
+
+	if (!(netdev->flags & IFF_UP))
+		goto out;
+
+	netif_device_detach(netdev);
+	gelic_net_stop(netdev);
+
+	gelic_net_open(netdev);
+	netif_device_attach(netdev);
+
+out:
+	atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * gelic_net_tx_timeout - called when the tx timeout watchdog kicks in.
+ * @netdev: interface device structure
+ *
+ * called, if tx hangs. Schedules a task that resets the interface
+ */
+static void gelic_net_tx_timeout(struct net_device *netdev)
+{
+	struct gelic_net_card *card;
+
+	card = netdev_priv(netdev);
+	atomic_inc(&card->tx_timeout_task_counter);
+	if (netdev->flags & IFF_UP)
+		schedule_work(&card->tx_timeout_task);
+	else
+		atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * gelic_net_setup_netdev_ops - initialization of net_device operations
+ * @netdev: net_device structure
+ *
+ * fills out function pointers in the net_device structure
+ */
+static void gelic_net_setup_netdev_ops(struct net_device *netdev)
+{
+	netdev->open = &gelic_net_open;
+	netdev->stop = &gelic_net_stop;
+	netdev->hard_start_xmit = &gelic_net_xmit;
+	netdev->get_stats = &gelic_net_get_stats;
+	netdev->set_multicast_list = &gelic_net_set_multi;
+	netdev->change_mtu = &gelic_net_change_mtu;
+	/* tx watchdog */
+	netdev->tx_timeout = &gelic_net_tx_timeout;
+	netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
+	/* NAPI */
+	netdev->poll = &gelic_net_poll;
+	netdev->weight = GELIC_NET_NAPI_WEIGHT;
+#ifdef GELIC_NET_ETHTOOL
+	netdev->ethtool_ops = &gelic_net_ethtool_ops;
+#endif
+}
+
+/**
+ * gelic_net_setup_netdev - initialization of net_device
+ * @card: card structure
+ *
+ * Returns 0 on success or <0 on failure
+ *
+ * gelic_net_setup_netdev initializes the net_device structure
+ **/
+static int gelic_net_setup_netdev(struct gelic_net_card *card)
+{
+	struct net_device *netdev = card->netdev;
+	struct sockaddr addr;
+	unsigned int i;
+	int status;
+	u64 v1, v2;
+
+	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &card->dev->core);
+	spin_lock_init(&card->tx_dma_lock);
+
+	card->rx_csum = GELIC_NET_RX_CSUM_DEFAULT;
+
+	gelic_net_setup_netdev_ops(netdev);
+
+	netdev->features = NETIF_F_IP_CSUM;
+
+	status = lv1_net_control(bus_id(card), dev_id(card),
+				 GELIC_NET_GET_MAC_ADDRESS,
+				 0, 0, 0, &v1, &v2);
+	if (status || !is_valid_ether_addr((u8 *)&v1)) {
+		dev_info(ctodev(card),
+			 "%s:lv1_net_control GET_MAC_ADDR failed %d\n",
+			 __func__, status);
+		return -EINVAL;
+	}
+	v1 <<= 16;
+	memcpy(addr.sa_data, &v1, ETH_ALEN);
+	memcpy(netdev->dev_addr, addr.sa_data, ETH_ALEN);
+	dev_info(ctodev(card), "MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 netdev->dev_addr[0], netdev->dev_addr[1],
+		 netdev->dev_addr[2], netdev->dev_addr[3],
+		 netdev->dev_addr[4], netdev->dev_addr[5]);
+
+	card->vlan_index = -1;	/* no vlan */
+	for (i = 0; i < GELIC_NET_VLAN_MAX; i++) {
+		status = lv1_net_control(bus_id(card), dev_id(card),
+					GELIC_NET_GET_VLAN_ID,
+					i + 1, /* index; one based */
+					0, 0, &v1, &v2);
+		if (status == GELIC_NET_VLAN_NO_ENTRY) {
+			dev_dbg(ctodev(card),
+				"GELIC_VLAN_ID no entry:%d, VLAN disabled\n",
+				status);
+			card->vlan_id[i] = 0;
+		} else if (status) {
+			dev_dbg(ctodev(card),
+				"%s:GELIC_NET_VLAN_ID faild, status=%d\n",
+				__func__, status);
+			card->vlan_id[i] = 0;
+		} else {
+			card->vlan_id[i] = (u32)v1;
+			dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1);
+		}
+	}
+	if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1])
+		card->vlan_index = GELIC_NET_VLAN_WIRED - 1;
+
+	status = register_netdev(netdev);
+	if (status) {
+		dev_err(ctodev(card), "%s:Couldn't register net_device: %d\n",
+			__func__, status);
+		return status;
+	}
+
+	return 0;
+}
+
+/**
+ * gelic_net_alloc_card - allocates net_device and card structure
+ *
+ * returns the card structure or NULL in case of errors
+ *
+ * the card and net_device structures are linked to each other
+ */
+static struct gelic_net_card *gelic_net_alloc_card(void)
+{
+	struct net_device *netdev;
+	struct gelic_net_card *card;
+	size_t alloc_size;
+
+	alloc_size = sizeof (*card) +
+		sizeof (struct gelic_net_descr) * GELIC_NET_RX_DESCRIPTORS +
+		sizeof (struct gelic_net_descr) * GELIC_NET_TX_DESCRIPTORS;
+	/*
+	 * we assume private data is allocated 32 bytes (or more) aligned
+	 * so that gelic_net_descr should be 32 bytes aligned.
+	 * Current alloc_etherdev() does do it because NETDEV_ALIGN
+	 * is 32.
+	 * check this assumption here.
+	 */
+	BUILD_BUG_ON(NETDEV_ALIGN < 32);
+	BUILD_BUG_ON(offsetof(struct gelic_net_card, irq_status) % 8);
+	BUILD_BUG_ON(offsetof(struct gelic_net_card, descr) % 32);
+
+	netdev = alloc_etherdev(alloc_size);
+	if (!netdev)
+		return NULL;
+
+	card = netdev_priv(netdev);
+	card->netdev = netdev;
+	INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task);
+	init_waitqueue_head(&card->waitq);
+	atomic_set(&card->tx_timeout_task_counter, 0);
+
+	return card;
+}
+
+/**
+ * ps3_gelic_driver_probe - add a device to the control of this driver
+ */
+static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev)
+{
+	struct gelic_net_card *card = gelic_net_alloc_card();
+	int result;
+
+	if (!card) {
+		dev_info(&dev->core, "gelic_net_alloc_card failed\n");
+		result = -ENOMEM;
+		goto fail_alloc_card;
+	}
+
+	ps3_system_bus_set_driver_data(dev, card);
+	card->dev = dev;
+
+	result = ps3_open_hv_device(dev);
+
+	if (result) {
+		dev_dbg(&dev->core, "ps3_open_hv_device failed\n");
+		goto fail_open;
+	}
+
+	result = ps3_dma_region_create(dev->d_region);
+
+	if (result) {
+		dev_dbg(&dev->core, "ps3_dma_region_create failed(%d)\n",
+			result);
+		BUG_ON("check region type");
+		goto fail_dma_region;
+	}
+
+	result = lv1_net_set_interrupt_status_indicator(bus_id(card),
+							dev_id(card),
+		ps3_mm_phys_to_lpar(__pa(&card->irq_status)),
+		0);
+
+	if (result) {
+		dev_dbg(&dev->core,
+			"lv1_net_set_interrupt_status_indicator failed: %s\n",
+			ps3_result(result));
+		result = -EIO;
+		goto fail_status_indicator;
+	}
+
+	result = gelic_net_setup_netdev(card);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+			"(%d)\n", __func__, __LINE__, result);
+		goto fail_setup_netdev;
+	}
+
+	return 0;
+
+fail_setup_netdev:
+	lv1_net_set_interrupt_status_indicator(bus_id(card),
+					       bus_id(card),
+					       0 , 0);
+fail_status_indicator:
+	ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+	ps3_close_hv_device(dev);
+fail_open:
+	ps3_system_bus_set_driver_data(dev, NULL);
+	free_netdev(card->netdev);
+fail_alloc_card:
+	return result;
+}
+
+/**
+ * ps3_gelic_driver_remove - remove a device from the control of this driver
+ */
+
+static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev)
+{
+	struct gelic_net_card *card = ps3_system_bus_get_driver_data(dev);
+
+	wait_event(card->waitq,
+		   atomic_read(&card->tx_timeout_task_counter) == 0);
+
+	lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card),
+					       0 , 0);
+
+	unregister_netdev(card->netdev);
+	free_netdev(card->netdev);
+
+	ps3_system_bus_set_driver_data(dev, NULL);
+
+	ps3_dma_region_free(dev->d_region);
+
+	ps3_close_hv_device(dev);
+
+	return 0;
+}
+
+static struct ps3_system_bus_driver ps3_gelic_driver = {
+	.match_id = PS3_MATCH_ID_GELIC,
+	.probe = ps3_gelic_driver_probe,
+	.remove = ps3_gelic_driver_remove,
+	.shutdown = ps3_gelic_driver_remove,
+	.core.name = "ps3_gelic_driver",
+	.core.owner = THIS_MODULE,
+};
+
+static int __init ps3_gelic_driver_init (void)
+{
+	return firmware_has_feature(FW_FEATURE_PS3_LV1)
+		? ps3_system_bus_driver_register(&ps3_gelic_driver)
+		: -ENODEV;
+}
+
+static void __exit ps3_gelic_driver_exit (void)
+{
+	ps3_system_bus_driver_unregister(&ps3_gelic_driver);
+}
+
+module_init (ps3_gelic_driver_init);
+module_exit (ps3_gelic_driver_exit);
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_GELIC);
+
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
new file mode 100644
index 0000000..5e1c286
--- /dev/null
+++ b/drivers/net/ps3_gelic_net.h
@@ -0,0 +1,239 @@
+/*
+ *  PS3 Platfom gelic network driver.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation.
+ *
+ * This file is based on: spider_net.h
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ *           Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _GELIC_NET_H
+#define _GELIC_NET_H
+
+#define GELIC_NET_DRV_NAME "Gelic Network Driver"
+#define GELIC_NET_DRV_VERSION "1.0"
+
+#define GELIC_NET_ETHTOOL               /* use ethtool */
+
+/* ioctl */
+#define GELIC_NET_GET_MODE              (SIOCDEVPRIVATE + 0)
+#define GELIC_NET_SET_MODE              (SIOCDEVPRIVATE + 1)
+
+/* descriptors */
+#define GELIC_NET_RX_DESCRIPTORS        128 /* num of descriptors */
+#define GELIC_NET_TX_DESCRIPTORS        128 /* num of descriptors */
+
+#define GELIC_NET_MAX_MTU               2308
+#define GELIC_NET_MIN_MTU               64
+#define GELIC_NET_RXBUF_ALIGN           128
+#define GELIC_NET_RX_CSUM_DEFAULT       1 /* hw chksum */
+#define GELIC_NET_WATCHDOG_TIMEOUT      5*HZ
+#define GELIC_NET_NAPI_WEIGHT           (GELIC_NET_RX_DESCRIPTORS)
+#define GELIC_NET_BROADCAST_ADDR        0xffffffffffffL
+#define GELIC_NET_VLAN_POS              (VLAN_ETH_ALEN * 2)
+#define GELIC_NET_VLAN_MAX              4
+#define GELIC_NET_MC_COUNT_MAX          32 /* multicast address list */
+
+enum gelic_net_int0_status {
+	GELIC_NET_GDTDCEINT  = 24,
+	GELIC_NET_GRFANMINT  = 28,
+};
+
+/* GHIINT1STS bits */
+enum gelic_net_int1_status {
+	GELIC_NET_GDADCEINT = 14,
+};
+
+/* interrupt mask */
+#define GELIC_NET_TXINT                   (1L << (GELIC_NET_GDTDCEINT + 32))
+
+#define GELIC_NET_RXINT0                  (1L << (GELIC_NET_GRFANMINT + 32))
+#define GELIC_NET_RXINT1                  (1L << GELIC_NET_GDADCEINT)
+#define GELIC_NET_RXINT                   (GELIC_NET_RXINT0 | GELIC_NET_RXINT1)
+
+ /* RX descriptor data_status bits */
+#define GELIC_NET_RXDMADU	0x80000000 /* destination MAC addr unknown */
+#define GELIC_NET_RXLSTFBF	0x40000000 /* last frame buffer            */
+#define GELIC_NET_RXIPCHK	0x20000000 /* IP checksum performed        */
+#define GELIC_NET_RXTCPCHK	0x10000000 /* TCP/UDP checksup performed   */
+#define GELIC_NET_RXIPSPKT	0x08000000 /* IPsec packet   */
+#define GELIC_NET_RXIPSAHPRT	0x04000000 /* IPsec AH protocol performed */
+#define GELIC_NET_RXIPSESPPRT	0x02000000 /* IPsec ESP protocol performed */
+#define GELIC_NET_RXSESPAH	0x01000000 /*
+					    * IPsec ESP protocol auth
+					    * performed
+					    */
+
+#define GELIC_NET_RXWTPKT	0x00C00000 /*
+					    * wakeup trigger packet
+					    * 01: Magic Packet (TM)
+					    * 10: ARP packet
+					    * 11: Multicast MAC addr
+					    */
+#define GELIC_NET_RXVLNPKT	0x00200000 /* VLAN packet */
+/* bit 20..16 reserved */
+#define GELIC_NET_RXRECNUM	0x0000ff00 /* reception receipt number */
+/* bit 7..0 reserved */
+
+#define GELIC_NET_TXDESC_TAIL		0
+#define GELIC_NET_DATA_STATUS_CHK_MASK	(GELIC_NET_RXIPCHK | GELIC_NET_RXTCPCHK)
+
+/* RX descriptor data_error bits */
+/* bit 31 reserved */
+#define GELIC_NET_RXALNERR	0x40000000 /* alignement error 10/100M */
+#define GELIC_NET_RXOVERERR	0x20000000 /* oversize error */
+#define GELIC_NET_RXRNTERR	0x10000000 /* Runt error */
+#define GELIC_NET_RXIPCHKERR	0x08000000 /* IP checksum  error */
+#define GELIC_NET_RXTCPCHKERR	0x04000000 /* TCP/UDP checksum  error */
+#define GELIC_NET_RXUMCHSP	0x02000000 /* unmatched sp on sp */
+#define GELIC_NET_RXUMCHSPI	0x01000000 /* unmatched SPI on SAD */
+#define GELIC_NET_RXUMCHSAD	0x00800000 /* unmatched SAD */
+#define GELIC_NET_RXIPSAHERR	0x00400000 /* auth error on AH protocol
+					    * processing */
+#define GELIC_NET_RXIPSESPAHERR	0x00200000 /* auth error on ESP protocol
+					    * processing */
+#define GELIC_NET_RXDRPPKT	0x00100000 /* drop packet */
+#define GELIC_NET_RXIPFMTERR	0x00080000 /* IP packet format error */
+/* bit 18 reserved */
+#define GELIC_NET_RXDATAERR	0x00020000 /* IP packet format error */
+#define GELIC_NET_RXCALERR	0x00010000 /* cariier extension length
+					    * error */
+#define GELIC_NET_RXCREXERR	0x00008000 /* carrier extention error */
+#define GELIC_NET_RXMLTCST	0x00004000 /* multicast address frame */
+/* bit 13..0 reserved */
+#define GELIC_NET_DATA_ERROR_CHK_MASK		\
+	(GELIC_NET_RXIPCHKERR | GELIC_NET_RXTCPCHKERR)
+
+
+/* tx descriptor command and status */
+#define GELIC_NET_DMAC_CMDSTAT_NOCS       0xa0080000 /* middle of frame */
+#define GELIC_NET_DMAC_CMDSTAT_TCPCS      0xa00a0000
+#define GELIC_NET_DMAC_CMDSTAT_UDPCS      0xa00b0000
+#define GELIC_NET_DMAC_CMDSTAT_END_FRAME  0x00040000 /* end of frame */
+
+#define GELIC_NET_DMAC_CMDSTAT_RXDCEIS	  0x00000002 /* descriptor chain end
+						      * interrupt status */
+
+#define GELIC_NET_DMAC_CMDSTAT_CHAIN_END  0x00000002 /* RXDCEIS:DMA stopped */
+#define GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE 0xb0000000
+#define GELIC_NET_DESCR_IND_PROC_SHIFT    28
+#define GELIC_NET_DESCR_IND_PROC_MASKO    0x0fffffff
+
+
+enum gelic_net_descr_status {
+	GELIC_NET_DESCR_COMPLETE            = 0x00, /* used in rx and tx */
+	GELIC_NET_DESCR_RESPONSE_ERROR      = 0x01, /* used in rx and tx */
+	GELIC_NET_DESCR_PROTECTION_ERROR    = 0x02, /* used in rx and tx */
+	GELIC_NET_DESCR_FRAME_END           = 0x04, /* used in rx */
+	GELIC_NET_DESCR_FORCE_END           = 0x05, /* used in rx and tx */
+	GELIC_NET_DESCR_CARDOWNED           = 0x0a, /* used in rx and tx */
+	GELIC_NET_DESCR_NOT_IN_USE                  /* any other value */
+};
+/* for lv1_net_control */
+#define GELIC_NET_GET_MAC_ADDRESS               0x0000000000000001
+#define GELIC_NET_GET_ETH_PORT_STATUS           0x0000000000000002
+#define GELIC_NET_SET_NEGOTIATION_MODE          0x0000000000000003
+#define GELIC_NET_GET_VLAN_ID                   0x0000000000000004
+
+#define GELIC_NET_LINK_UP                       0x0000000000000001
+#define GELIC_NET_FULL_DUPLEX                   0x0000000000000002
+#define GELIC_NET_AUTO_NEG                      0x0000000000000004
+#define GELIC_NET_SPEED_10                      0x0000000000000010
+#define GELIC_NET_SPEED_100                     0x0000000000000020
+#define GELIC_NET_SPEED_1000                    0x0000000000000040
+
+#define GELIC_NET_VLAN_ALL                      0x0000000000000001
+#define GELIC_NET_VLAN_WIRED                    0x0000000000000002
+#define GELIC_NET_VLAN_WIRELESS                 0x0000000000000003
+#define GELIC_NET_VLAN_PSP                      0x0000000000000004
+#define GELIC_NET_VLAN_PORT0                    0x0000000000000010
+#define GELIC_NET_VLAN_PORT1                    0x0000000000000011
+#define GELIC_NET_VLAN_PORT2                    0x0000000000000012
+#define GELIC_NET_VLAN_DAEMON_CLIENT_BSS        0x0000000000000013
+#define GELIC_NET_VLAN_LIBERO_CLIENT_BSS        0x0000000000000014
+#define GELIC_NET_VLAN_NO_ENTRY                 -6
+
+#define GELIC_NET_PORT                          2 /* for port status */
+
+/* size of hardware part of gelic descriptor */
+#define GELIC_NET_DESCR_SIZE	(32)
+struct gelic_net_descr {
+	/* as defined by the hardware */
+	u32 buf_addr;
+	u32 buf_size;
+	u32 next_descr_addr;
+	u32 dmac_cmd_status;
+	u32 result_size;
+	u32 valid_size;	/* all zeroes for tx */
+	u32 data_status;
+	u32 data_error;	/* all zeroes for tx */
+
+	/* used in the driver */
+	struct sk_buff *skb;
+	dma_addr_t bus_addr;
+	struct gelic_net_descr *next;
+	struct gelic_net_descr *prev;
+	struct vlan_ethhdr vlan;
+} __attribute__((aligned(32)));
+
+struct gelic_net_descr_chain {
+	/* we walk from tail to head */
+	struct gelic_net_descr *head;
+	struct gelic_net_descr *tail;
+};
+
+struct gelic_net_card {
+	struct net_device *netdev;
+	/*
+	 * hypervisor requires irq_status should be
+	 * 8 bytes aligned, but u64 member is
+	 * always disposed in that manner
+	 */
+	u64 irq_status;
+	u64 ghiintmask;
+
+	struct ps3_system_bus_device *dev;
+	u32 vlan_id[GELIC_NET_VLAN_MAX];
+	int vlan_index;
+
+	struct gelic_net_descr_chain tx_chain;
+	struct gelic_net_descr_chain rx_chain;
+	/* gurad dmac descriptor chain*/
+	spinlock_t chain_lock;
+
+	struct net_device_stats netdev_stats;
+	int rx_csum;
+	/* guard tx_dma_progress */
+	spinlock_t tx_dma_lock;
+	int tx_dma_progress;
+
+	struct work_struct tx_timeout_task;
+	atomic_t tx_timeout_task_counter;
+	wait_queue_head_t waitq;
+
+	struct gelic_net_descr *tx_top, *rx_top;
+	struct gelic_net_descr descr[0];
+};
+
+
+extern unsigned long p_to_lp(long pa);
+
+#endif /* _GELIC_NET_H */
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index d8766c0..8be8be4 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2433,37 +2433,22 @@
 	return -1;
 }
 
-static void ql_hw_csum_setup(struct sk_buff *skb,
+static void ql_hw_csum_setup(const struct sk_buff *skb,
 			     struct ob_mac_iocb_req *mac_iocb_ptr)
 {
-	struct ethhdr *eth;
-	struct iphdr *ip = NULL;
-	u8 offset = ETH_HLEN;
+	const struct iphdr *ip = ip_hdr(skb);
 
-	eth = (struct ethhdr *)(skb->data);
+	mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb);
+	mac_iocb_ptr->ip_hdr_len = ip->ihl;
 
-	if (eth->h_proto == __constant_htons(ETH_P_IP)) {
-		ip = (struct iphdr *)&skb->data[ETH_HLEN];
-	} else if (eth->h_proto == htons(ETH_P_8021Q) &&
-		   ((struct vlan_ethhdr *)skb->data)->
-		   h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) {
-		ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN];
-		offset = VLAN_ETH_HLEN;
+	if (ip->protocol == IPPROTO_TCP) {
+		mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
+			OB_3032MAC_IOCB_REQ_IC;
+	} else {
+		mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
+			OB_3032MAC_IOCB_REQ_IC;
 	}
 
-	if (ip) {
-		if (ip->protocol == IPPROTO_TCP) {
-			mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC | 
-			OB_3032MAC_IOCB_REQ_IC;
-			mac_iocb_ptr->ip_hdr_off = offset;
-			mac_iocb_ptr->ip_hdr_len = ip->ihl;
-		} else if (ip->protocol == IPPROTO_UDP) {
-			mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC | 
-			OB_3032MAC_IOCB_REQ_IC;
-			mac_iocb_ptr->ip_hdr_off = offset;
-			mac_iocb_ptr->ip_hdr_len = ip->ihl;
-		}
-	}
 }
 
 /*
@@ -4044,7 +4029,7 @@
 	if (pci_using_dac)
 		ndev->features |= NETIF_F_HIGHDMA;
 	if (qdev->device_id == QL3032_DEVICE_ID)
-		ndev->features |= (NETIF_F_HW_CSUM | NETIF_F_SG);
+		ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 
 	qdev->mem_map_registers =
 	    ioremap_nocache(pci_resource_start(pdev, 1),
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 45876a8..bb6896a 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1,53 +1,11 @@
 /*
-=========================================================================
- r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x.
- --------------------------------------------------------------------
-
- History:
- Feb  4 2002	- created initially by ShuChen <shuchen@realtek.com.tw>.
- May 20 2002	- Add link status force-mode and TBI mode support.
-	2004	- Massive updates. See kernel SCM system for details.
-=========================================================================
-  1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
-	 Command: 'insmod r8169 media = SET_MEDIA'
-	 Ex:	  'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
-
-	 SET_MEDIA can be:
- 		_10_Half	= 0x01
- 		_10_Full	= 0x02
- 		_100_Half	= 0x04
- 		_100_Full	= 0x08
- 		_1000_Full	= 0x10
-
-  2. Support TBI mode.
-=========================================================================
-VERSION 1.1	<2002/10/4>
-
-	The bit4:0 of MII register 4 is called "selector field", and have to be
-	00001b to indicate support of IEEE std 802.3 during NWay process of
-	exchanging Link Code Word (FLP).
-
-VERSION 1.2	<2002/11/30>
-
-	- Large style cleanup
-	- Use ether_crc in stock kernel (linux/crc32.h)
-	- Copy mc_filter setup code from 8139cp
-	  (includes an optimization, and avoids set_bit use)
-
-VERSION 1.6LK	<2004/04/14>
-
-	- Merge of Realtek's version 1.6
-	- Conversion to DMA API
-	- Suspend/resume
-	- Endianness
-	- Misc Rx/Tx bugs
-
-VERSION 2.2LK	<2005/01/25>
-
-	- RX csum, TX csum/SG, TSO
-	- VLAN
-	- baby (< 7200) Jumbo frames support
-	- Merge of Realtek's version 2.2 (new phy)
+ * r8169.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
  */
 
 #include <linux/module.h>
@@ -108,11 +66,6 @@
 #define rtl8169_rx_quota(count, quota)	count
 #endif
 
-/* media options */
-#define MAX_UNITS 8
-static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-static int num_media = 0;
-
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static const int max_interrupt_work = 20;
 
@@ -126,7 +79,7 @@
 #define RX_FIFO_THRESH	7	/* 7 means NO threshold, Rx buffer level before first PCI xfer. */
 #define RX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
 #define TX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
-#define EarlyTxThld 	0x3F	/* 0x3F means NO early transmit */
+#define EarlyTxThld	0x3F	/* 0x3F means NO early transmit */
 #define RxPacketMaxSize	0x3FE8	/* 16K - 1 - ETH_HLEN - VLAN - CRC... */
 #define SafeMtu		0x1c20	/* ... actually life sucks beyond ~7k */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
@@ -151,16 +104,17 @@
 #define RTL_R32(reg)		((unsigned long) readl (ioaddr + (reg)))
 
 enum mac_version {
-	RTL_GIGA_MAC_VER_01 = 0x00,
-	RTL_GIGA_MAC_VER_02 = 0x01,
-	RTL_GIGA_MAC_VER_03 = 0x02,
-	RTL_GIGA_MAC_VER_04 = 0x03,
-	RTL_GIGA_MAC_VER_05 = 0x04,
-	RTL_GIGA_MAC_VER_11 = 0x0b,
-	RTL_GIGA_MAC_VER_12 = 0x0c,
-	RTL_GIGA_MAC_VER_13 = 0x0d,
-	RTL_GIGA_MAC_VER_14 = 0x0e,
-	RTL_GIGA_MAC_VER_15 = 0x0f
+	RTL_GIGA_MAC_VER_01 = 0x01, // 8169
+	RTL_GIGA_MAC_VER_02 = 0x02, // 8169S
+	RTL_GIGA_MAC_VER_03 = 0x03, // 8110S
+	RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB
+	RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
+	RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
+	RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
+	RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf
+	RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec
+	RTL_GIGA_MAC_VER_14 = 0x0e, // 8101
+	RTL_GIGA_MAC_VER_15 = 0x0f  // 8101
 };
 
 enum phy_version {
@@ -180,11 +134,12 @@
 	u8 mac_version;
 	u32 RxConfigMask;	/* Clears the bits supported by this chip */
 } rtl_chip_info[] = {
-	_R("RTL8169",		RTL_GIGA_MAC_VER_01, 0xff7e1880),
-	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_02, 0xff7e1880),
-	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_03, 0xff7e1880),
-	_R("RTL8169sb/8110sb",	RTL_GIGA_MAC_VER_04, 0xff7e1880),
-	_R("RTL8169sc/8110sc",	RTL_GIGA_MAC_VER_05, 0xff7e1880),
+	_R("RTL8169",		RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169
+	_R("RTL8169s",		RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S
+	_R("RTL8110s",		RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S
+	_R("RTL8169sb/8110sb",	RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
+	_R("RTL8169sc/8110sc",	RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
+	_R("RTL8169sc/8110sc",	RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
 	_R("RTL8168b/8111b",	RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
 	_R("RTL8168b/8111b",	RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
 	_R("RTL8101e",		RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
@@ -199,20 +154,15 @@
 	RTL_CFG_2
 };
 
-static const struct {
-	unsigned int region;
-	unsigned int align;
-} rtl_cfg_info[] = {
-	[RTL_CFG_0] = { 1, NET_IP_ALIGN },
-	[RTL_CFG_1] = { 2, NET_IP_ALIGN },
-	[RTL_CFG_2] = { 2, 8 }
-};
+static void rtl_hw_start_8169(struct net_device *);
+static void rtl_hw_start_8168(struct net_device *);
+static void rtl_hw_start_8101(struct net_device *);
 
 static struct pci_device_id rtl8169_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8129), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8136), 0, 0, RTL_CFG_2 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8167), 0, 0, RTL_CFG_0 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8168), 0, 0, RTL_CFG_2 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8168), 0, 0, RTL_CFG_1 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8169), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK,	0x4300), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(0x1259,			0xc107), 0, 0, RTL_CFG_0 },
@@ -230,62 +180,63 @@
 	u32 msg_enable;
 } debug = { -1 };
 
-enum RTL8169_registers {
-	MAC0 = 0,		/* Ethernet hardware address. */
-	MAR0 = 8,		/* Multicast filter. */
-	CounterAddrLow = 0x10,
-	CounterAddrHigh = 0x14,
-	TxDescStartAddrLow = 0x20,
-	TxDescStartAddrHigh = 0x24,
-	TxHDescStartAddrLow = 0x28,
-	TxHDescStartAddrHigh = 0x2c,
-	FLASH = 0x30,
-	ERSR = 0x36,
-	ChipCmd = 0x37,
-	TxPoll = 0x38,
-	IntrMask = 0x3C,
-	IntrStatus = 0x3E,
-	TxConfig = 0x40,
-	RxConfig = 0x44,
-	RxMissed = 0x4C,
-	Cfg9346 = 0x50,
-	Config0 = 0x51,
-	Config1 = 0x52,
-	Config2 = 0x53,
-	Config3 = 0x54,
-	Config4 = 0x55,
-	Config5 = 0x56,
-	MultiIntr = 0x5C,
-	PHYAR = 0x60,
-	TBICSR = 0x64,
-	TBI_ANAR = 0x68,
-	TBI_LPAR = 0x6A,
-	PHYstatus = 0x6C,
-	RxMaxSize = 0xDA,
-	CPlusCmd = 0xE0,
-	IntrMitigate = 0xE2,
-	RxDescAddrLow = 0xE4,
-	RxDescAddrHigh = 0xE8,
-	EarlyTxThres = 0xEC,
-	FuncEvent = 0xF0,
-	FuncEventMask = 0xF4,
-	FuncPresetState = 0xF8,
-	FuncForceEvent = 0xFC,
+enum rtl_registers {
+	MAC0		= 0,	/* Ethernet hardware address. */
+	MAC4		= 4,
+	MAR0		= 8,	/* Multicast filter. */
+	CounterAddrLow		= 0x10,
+	CounterAddrHigh		= 0x14,
+	TxDescStartAddrLow	= 0x20,
+	TxDescStartAddrHigh	= 0x24,
+	TxHDescStartAddrLow	= 0x28,
+	TxHDescStartAddrHigh	= 0x2c,
+	FLASH		= 0x30,
+	ERSR		= 0x36,
+	ChipCmd		= 0x37,
+	TxPoll		= 0x38,
+	IntrMask	= 0x3c,
+	IntrStatus	= 0x3e,
+	TxConfig	= 0x40,
+	RxConfig	= 0x44,
+	RxMissed	= 0x4c,
+	Cfg9346		= 0x50,
+	Config0		= 0x51,
+	Config1		= 0x52,
+	Config2		= 0x53,
+	Config3		= 0x54,
+	Config4		= 0x55,
+	Config5		= 0x56,
+	MultiIntr	= 0x5c,
+	PHYAR		= 0x60,
+	TBICSR		= 0x64,
+	TBI_ANAR	= 0x68,
+	TBI_LPAR	= 0x6a,
+	PHYstatus	= 0x6c,
+	RxMaxSize	= 0xda,
+	CPlusCmd	= 0xe0,
+	IntrMitigate	= 0xe2,
+	RxDescAddrLow	= 0xe4,
+	RxDescAddrHigh	= 0xe8,
+	EarlyTxThres	= 0xec,
+	FuncEvent	= 0xf0,
+	FuncEventMask	= 0xf4,
+	FuncPresetState	= 0xf8,
+	FuncForceEvent	= 0xfc,
 };
 
-enum RTL8169_register_content {
+enum rtl_register_content {
 	/* InterruptStatusBits */
-	SYSErr = 0x8000,
-	PCSTimeout = 0x4000,
-	SWInt = 0x0100,
-	TxDescUnavail = 0x80,
-	RxFIFOOver = 0x40,
-	LinkChg = 0x20,
-	RxOverflow = 0x10,
-	TxErr = 0x08,
-	TxOK = 0x04,
-	RxErr = 0x02,
-	RxOK = 0x01,
+	SYSErr		= 0x8000,
+	PCSTimeout	= 0x4000,
+	SWInt		= 0x0100,
+	TxDescUnavail	= 0x0080,
+	RxFIFOOver	= 0x0040,
+	LinkChg		= 0x0020,
+	RxOverflow	= 0x0010,
+	TxErr		= 0x0008,
+	TxOK		= 0x0004,
+	RxErr		= 0x0002,
+	RxOK		= 0x0001,
 
 	/* RxStatusDesc */
 	RxFOVF	= (1 << 23),
@@ -295,26 +246,31 @@
 	RxCRC	= (1 << 19),
 
 	/* ChipCmdBits */
-	CmdReset = 0x10,
-	CmdRxEnb = 0x08,
-	CmdTxEnb = 0x04,
-	RxBufEmpty = 0x01,
+	CmdReset	= 0x10,
+	CmdRxEnb	= 0x08,
+	CmdTxEnb	= 0x04,
+	RxBufEmpty	= 0x01,
+
+	/* TXPoll register p.5 */
+	HPQ		= 0x80,		/* Poll cmd on the high prio queue */
+	NPQ		= 0x40,		/* Poll cmd on the low prio queue */
+	FSWInt		= 0x01,		/* Forced software interrupt */
 
 	/* Cfg9346Bits */
-	Cfg9346_Lock = 0x00,
-	Cfg9346_Unlock = 0xC0,
+	Cfg9346_Lock	= 0x00,
+	Cfg9346_Unlock	= 0xc0,
 
 	/* rx_mode_bits */
-	AcceptErr = 0x20,
-	AcceptRunt = 0x10,
-	AcceptBroadcast = 0x08,
-	AcceptMulticast = 0x04,
-	AcceptMyPhys = 0x02,
-	AcceptAllPhys = 0x01,
+	AcceptErr	= 0x20,
+	AcceptRunt	= 0x10,
+	AcceptBroadcast	= 0x08,
+	AcceptMulticast	= 0x04,
+	AcceptMyPhys	= 0x02,
+	AcceptAllPhys	= 0x01,
 
 	/* RxConfigBits */
-	RxCfgFIFOShift = 13,
-	RxCfgDMAShift = 8,
+	RxCfgFIFOShift	= 13,
+	RxCfgDMAShift	=  8,
 
 	/* TxConfigBits */
 	TxInterFrameGapShift = 24,
@@ -323,6 +279,10 @@
 	/* Config1 register p.24 */
 	PMEnable	= (1 << 0),	/* Power Management Enable */
 
+	/* Config2 register p. 25 */
+	PCI_Clock_66MHz = 0x01,
+	PCI_Clock_33MHz = 0x00,
+
 	/* Config3 register p.25 */
 	MagicPacket	= (1 << 5),	/* Wake up when receives a Magic Packet */
 	LinkUp		= (1 << 4),	/* Wake up when the cable connection is re-established */
@@ -343,36 +303,34 @@
 	TBINwComplete	= 0x01000000,
 
 	/* CPlusCmd p.31 */
+	PktCntrDisable	= (1 << 7),	// 8168
 	RxVlan		= (1 << 6),
 	RxChkSum	= (1 << 5),
 	PCIDAC		= (1 << 4),
 	PCIMulRW	= (1 << 3),
+	INTT_0		= 0x0000,	// 8168
+	INTT_1		= 0x0001,	// 8168
+	INTT_2		= 0x0002,	// 8168
+	INTT_3		= 0x0003,	// 8168
 
 	/* rtl8169_PHYstatus */
-	TBI_Enable = 0x80,
-	TxFlowCtrl = 0x40,
-	RxFlowCtrl = 0x20,
-	_1000bpsF = 0x10,
-	_100bps = 0x08,
-	_10bps = 0x04,
-	LinkStatus = 0x02,
-	FullDup = 0x01,
-
-	/* _MediaType */
-	_10_Half = 0x01,
-	_10_Full = 0x02,
-	_100_Half = 0x04,
-	_100_Full = 0x08,
-	_1000_Full = 0x10,
+	TBI_Enable	= 0x80,
+	TxFlowCtrl	= 0x40,
+	RxFlowCtrl	= 0x20,
+	_1000bpsF	= 0x10,
+	_100bps		= 0x08,
+	_10bps		= 0x04,
+	LinkStatus	= 0x02,
+	FullDup		= 0x01,
 
 	/* _TBICSRBit */
-	TBILinkOK = 0x02000000,
+	TBILinkOK	= 0x02000000,
 
 	/* DumpCounterCommand */
-	CounterDump = 0x8,
+	CounterDump	= 0x8,
 };
 
-enum _DescStatusBit {
+enum desc_status_bit {
 	DescOwn		= (1 << 31), /* Descriptor is owned by NIC */
 	RingEnd		= (1 << 30), /* End of descriptor ring */
 	FirstFrag	= (1 << 29), /* First segment of a packet */
@@ -405,15 +363,15 @@
 #define RsvdMask	0x3fffc000
 
 struct TxDesc {
-	u32 opts1;
-	u32 opts2;
-	u64 addr;
+	__le32 opts1;
+	__le32 opts2;
+	__le64 addr;
 };
 
 struct RxDesc {
-	u32 opts1;
-	u32 opts2;
-	u64 addr;
+	__le32 opts1;
+	__le32 opts2;
+	__le64 addr;
 };
 
 struct ring_info {
@@ -446,6 +404,8 @@
 	unsigned rx_buf_sz;
 	struct timer_list timer;
 	u16 cp_cmd;
+	u16 intr_event;
+	u16 napi_event;
 	u16 intr_mask;
 	int phy_auto_nego_reg;
 	int phy_1000_ctrl_reg;
@@ -455,6 +415,7 @@
 	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
 	void (*get_settings)(struct net_device *, struct ethtool_cmd *);
 	void (*phy_reset_enable)(void __iomem *);
+	void (*hw_start)(struct net_device *);
 	unsigned int (*phy_reset_pending)(void __iomem *);
 	unsigned int (*link_ok)(void __iomem *);
 	struct delayed_work task;
@@ -463,8 +424,6 @@
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param_array(media, int, &num_media, 0);
-MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
 module_param(rx_copybreak, int, 0);
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 module_param(use_dac, int, 0);
@@ -478,9 +437,9 @@
 static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance);
 static int rtl8169_init_ring(struct net_device *dev);
-static void rtl8169_hw_start(struct net_device *dev);
+static void rtl_hw_start(struct net_device *dev);
 static int rtl8169_close(struct net_device *dev);
-static void rtl8169_set_rx_mode(struct net_device *dev);
+static void rtl_set_rx_mode(struct net_device *dev);
 static void rtl8169_tx_timeout(struct net_device *dev);
 static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
 static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
@@ -493,35 +452,37 @@
 static int rtl8169_poll(struct net_device *dev, int *budget);
 #endif
 
-static const u16 rtl8169_intr_mask =
-	SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
-static const u16 rtl8169_napi_event =
-	RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
 static const unsigned int rtl8169_rx_config =
 	(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
-static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
+static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
 {
 	int i;
 
-	RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
+	RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value);
 
 	for (i = 20; i > 0; i--) {
-		/* Check if the RTL8169 has completed writing to the specified MII register */
+		/*
+		 * Check if the RTL8169 has completed writing to the specified
+		 * MII register.
+		 */
 		if (!(RTL_R32(PHYAR) & 0x80000000))
 			break;
 		udelay(25);
 	}
 }
 
-static int mdio_read(void __iomem *ioaddr, int RegAddr)
+static int mdio_read(void __iomem *ioaddr, int reg_addr)
 {
 	int i, value = -1;
 
-	RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
+	RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16);
 
 	for (i = 20; i > 0; i--) {
-		/* Check if the RTL8169 has completed retrieving data from the specified MII register */
+		/*
+		 * Check if the RTL8169 has completed retrieving data from
+		 * the specified MII register.
+		 */
 		if (RTL_R32(PHYAR) & 0x80000000) {
 			value = (int) (RTL_R32(PHYAR) & 0xFFFF);
 			break;
@@ -579,7 +540,8 @@
 }
 
 static void rtl8169_check_link_status(struct net_device *dev,
-				      struct rtl8169_private *tp, void __iomem *ioaddr)
+				      struct rtl8169_private *tp,
+				      void __iomem *ioaddr)
 {
 	unsigned long flags;
 
@@ -596,38 +558,6 @@
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
-static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
-{
-	struct {
-		u16 speed;
-		u8 duplex;
-		u8 autoneg;
-		u8 media;
-	} link_settings[] = {
-		{ SPEED_10,	DUPLEX_HALF, AUTONEG_DISABLE,	_10_Half },
-		{ SPEED_10,	DUPLEX_FULL, AUTONEG_DISABLE,	_10_Full },
-		{ SPEED_100,	DUPLEX_HALF, AUTONEG_DISABLE,	_100_Half },
-		{ SPEED_100,	DUPLEX_FULL, AUTONEG_DISABLE,	_100_Full },
-		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_DISABLE,	_1000_Full },
-		/* Make TBI happy */
-		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_ENABLE,	0xff }
-	}, *p;
-	unsigned char option;
-
-	option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
-
-	if ((option != 0xff) && !idx && netif_msg_drv(&debug))
-		printk(KERN_WARNING PFX "media option is deprecated.\n");
-
-	for (p = link_settings; p->media != 0xff; p++) {
-		if (p->media == option)
-			break;
-	}
-	*autoneg = p->autoneg;
-	*speed = p->speed;
-	*duplex = p->duplex;
-}
-
 static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -667,7 +597,7 @@
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
-	int i;
+	unsigned int i;
 	static struct {
 		u32 opt;
 		u16 reg;
@@ -886,16 +816,6 @@
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
-static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct rtl8169_private *tp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&tp->lock, flags);
-	vlan_group_set_device(tp->vlgrp, vid, NULL);
-	spin_unlock_irqrestore(&tp->lock, flags);
-}
-
 static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
 			       struct sk_buff *skb)
 {
@@ -903,8 +823,7 @@
 	int ret;
 
 	if (tp->vlgrp && (opts2 & RxVlanTag)) {
-		rtl8169_rx_hwaccel_skb(skb, tp->vlgrp,
-				       swab16(opts2 & 0xffff));
+		rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff));
 		ret = 0;
 	} else
 		ret = -1;
@@ -1125,7 +1044,6 @@
 	}
 }
 
-
 static const struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
 	.get_regs_len		= rtl8169_get_regs_len,
@@ -1151,8 +1069,8 @@
 	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
-static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
-				       int bitval)
+static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg,
+				       int bitnum, int bitval)
 {
 	int val;
 
@@ -1162,8 +1080,20 @@
 	mdio_write(ioaddr, reg, val & 0xffff);
 }
 
-static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_mac_version(struct rtl8169_private *tp,
+				    void __iomem *ioaddr)
 {
+	/*
+	 * The driver currently handles the 8168Bf and the 8168Be identically
+	 * but they can be identified more specifically through the test below
+	 * if needed:
+	 *
+	 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
+	 *
+	 * Same thing for the 8101Eb and the 8101Ec:
+	 *
+	 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
+	 */
 	const struct {
 		u32 mask;
 		int mac_version;
@@ -1173,6 +1103,7 @@
 		{ 0x34000000,	RTL_GIGA_MAC_VER_13 },
 		{ 0x30800000,	RTL_GIGA_MAC_VER_14 },
 		{ 0x30000000,	RTL_GIGA_MAC_VER_11 },
+		{ 0x98000000,	RTL_GIGA_MAC_VER_06 },
 		{ 0x18000000,	RTL_GIGA_MAC_VER_05 },
 		{ 0x10000000,	RTL_GIGA_MAC_VER_04 },
 		{ 0x04000000,	RTL_GIGA_MAC_VER_03 },
@@ -1181,7 +1112,7 @@
 	}, *p = mac_info;
 	u32 reg;
 
-	reg = RTL_R32(TxConfig) & 0x7c800000;
+	reg = RTL_R32(TxConfig) & 0xfc800000;
 	while ((reg & p->mask) != p->mask)
 		p++;
 	tp->mac_version = p->mac_version;
@@ -1192,7 +1123,8 @@
 	dprintk("mac_version = 0x%02x\n", tp->mac_version);
 }
 
-static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_phy_version(struct rtl8169_private *tp,
+				    void __iomem *ioaddr)
 {
 	const struct {
 		u16 mask;
@@ -1269,7 +1201,7 @@
 		  0xbf00 }	//w 0 15 0 bf00
 		}
 	}, *p = phy_magic;
-	int i;
+	unsigned int i;
 
 	rtl8169_print_mac_version(tp);
 	rtl8169_print_phy_version(tp);
@@ -1403,7 +1335,7 @@
 			      struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
-	int i;
+	unsigned int i;
 
 	tp->phy_reset_enable(ioaddr);
 	for (i = 0; i < 100; i++) {
@@ -1418,21 +1350,16 @@
 static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
-	static int board_idx = -1;
-	u8 autoneg, duplex;
-	u16 speed;
-
-	board_idx++;
 
 	rtl8169_hw_phy_config(dev);
 
 	dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
 	RTL_W8(0x82, 0x01);
 
-	if (tp->mac_version < RTL_GIGA_MAC_VER_03) {
-		dprintk("Set PCI Latency=0x40\n");
-		pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
-	}
+	pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
+
+	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+		pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
 
 	if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
 		dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
@@ -1441,16 +1368,52 @@
 		mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
 	}
 
-	rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
-
 	rtl8169_phy_reset(dev, tp);
 
-	rtl8169_set_speed(dev, autoneg, speed, duplex);
+	/*
+	 * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
+	 * only 8101. Don't panic.
+	 */
+	rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
 
 	if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
 		printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
 }
 
+static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	u32 high;
+	u32 low;
+
+	low  = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
+	high = addr[4] | (addr[5] << 8);
+
+	spin_lock_irq(&tp->lock);
+
+	RTL_W8(Cfg9346, Cfg9346_Unlock);
+	RTL_W32(MAC0, low);
+	RTL_W32(MAC4, high);
+	RTL_W8(Cfg9346, Cfg9346_Lock);
+
+	spin_unlock_irq(&tp->lock);
+}
+
+static int rtl_set_mac_address(struct net_device *dev, void *p)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	rtl_rar_set(tp, dev->dev_addr);
+
+	return 0;
+}
+
 static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -1477,15 +1440,49 @@
 	return -EOPNOTSUPP;
 }
 
+static const struct rtl_cfg_info {
+	void (*hw_start)(struct net_device *);
+	unsigned int region;
+	unsigned int align;
+	u16 intr_event;
+	u16 napi_event;
+} rtl_cfg_infos [] = {
+	[RTL_CFG_0] = {
+		.hw_start	= rtl_hw_start_8169,
+		.region		= 1,
+		.align		= 0,
+		.intr_event	= SYSErr | LinkChg | RxOverflow |
+				  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+		.napi_event	= RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+	},
+	[RTL_CFG_1] = {
+		.hw_start	= rtl_hw_start_8168,
+		.region		= 2,
+		.align		= 8,
+		.intr_event	= SYSErr | LinkChg | RxOverflow |
+				  TxErr | TxOK | RxOK | RxErr,
+		.napi_event	= TxErr | TxOK | RxOK | RxOverflow
+	},
+	[RTL_CFG_2] = {
+		.hw_start	= rtl_hw_start_8101,
+		.region		= 2,
+		.align		= 8,
+		.intr_event	= SYSErr | LinkChg | RxOverflow | PCSTimeout |
+				  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+		.napi_event	= RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+	}
+};
+
 static int __devinit
 rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	const unsigned int region = rtl_cfg_info[ent->driver_data].region;
+	const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
+	const unsigned int region = cfg->region;
 	struct rtl8169_private *tp;
 	struct net_device *dev;
 	void __iomem *ioaddr;
-	unsigned int pm_cap;
-	int i, rc;
+	unsigned int i;
+	int rc;
 
 	if (netif_msg_drv(&debug)) {
 		printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
@@ -1518,20 +1515,6 @@
 	if (rc < 0)
 		goto err_out_disable_2;
 
-	/* save power state before pci_enable_device overwrites it */
-	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-	if (pm_cap) {
-		u16 pwr_command, acpi_idle_state;
-
-		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
-		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
-	} else {
-		if (netif_msg_probe(tp)) {
-			dev_err(&pdev->dev,
-				"PowerManagement capability not found.\n");
-		}
-	}
-
 	/* make sure PCI base addr 1 is MMIO */
 	if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
 		if (netif_msg_probe(tp)) {
@@ -1595,7 +1578,7 @@
 	RTL_W8(ChipCmd, CmdReset);
 
 	/* Check that the chip has finished the reset. */
-	for (i = 100; i > 0; i--) {
+	for (i = 0; i < 100; i++) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
 		msleep_interruptible(1);
@@ -1657,11 +1640,12 @@
 	SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
 	dev->stop = rtl8169_close;
 	dev->tx_timeout = rtl8169_tx_timeout;
-	dev->set_multicast_list = rtl8169_set_rx_mode;
+	dev->set_multicast_list = rtl_set_rx_mode;
 	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
 	dev->base_addr = (unsigned long) ioaddr;
 	dev->change_mtu = rtl8169_change_mtu;
+	dev->set_mac_address = rtl_set_mac_address;
 
 #ifdef CONFIG_R8169_NAPI
 	dev->poll = rtl8169_poll;
@@ -1671,7 +1655,6 @@
 #ifdef CONFIG_R8169_VLAN
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = rtl8169_vlan_rx_register;
-	dev->vlan_rx_kill_vid = rtl8169_vlan_rx_kill_vid;
 #endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1681,7 +1664,10 @@
 	tp->intr_mask = 0xffff;
 	tp->pci_dev = pdev;
 	tp->mmio_addr = ioaddr;
-	tp->align = rtl_cfg_info[ent->driver_data].align;
+	tp->align = cfg->align;
+	tp->hw_start = cfg->hw_start;
+	tp->intr_event = cfg->intr_event;
+	tp->napi_event = cfg->napi_event;
 
 	init_timer(&tp->timer);
 	tp->timer.data = (unsigned long) dev;
@@ -1696,15 +1682,17 @@
 	pci_set_drvdata(pdev, dev);
 
 	if (netif_msg_probe(tp)) {
+		u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff;
+
 		printk(KERN_INFO "%s: %s at 0x%lx, "
 		       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
-		       "IRQ %d\n",
+		       "XID %08x IRQ %d\n",
 		       dev->name,
 		       rtl_chip_info[tp->chipset].name,
 		       dev->base_addr,
 		       dev->dev_addr[0], dev->dev_addr[1],
 		       dev->dev_addr[2], dev->dev_addr[3],
-		       dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+		       dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq);
 	}
 
 	rtl8169_init_phy(dev, tp);
@@ -1725,15 +1713,11 @@
 	goto out;
 }
 
-static void __devexit
-rtl8169_remove_one(struct pci_dev *pdev)
+static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct rtl8169_private *tp = netdev_priv(dev);
 
-	assert(dev != NULL);
-	assert(tp != NULL);
-
 	flush_scheduled_work();
 
 	unregister_netdev(dev);
@@ -1785,7 +1769,7 @@
 	if (retval < 0)
 		goto err_release_ring_2;
 
-	rtl8169_hw_start(dev);
+	rtl_hw_start(dev);
 
 	rtl8169_request_timer(dev);
 
@@ -1816,7 +1800,7 @@
 	RTL_R8(ChipCmd);
 }
 
-static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
+static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
 	u32 cfg = rtl8169_rx_config;
@@ -1829,47 +1813,92 @@
 		(InterFrameGap << TxInterFrameGapShift));
 }
 
-static void rtl8169_hw_start(struct net_device *dev)
+static void rtl_hw_start(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
-	struct pci_dev *pdev = tp->pci_dev;
-	u16 cmd;
-	u32 i;
+	unsigned int i;
 
 	/* Soft reset the chip. */
 	RTL_W8(ChipCmd, CmdReset);
 
 	/* Check that the chip has finished the reset. */
-	for (i = 100; i > 0; i--) {
+	for (i = 0; i < 100; i++) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
 		msleep_interruptible(1);
 	}
 
+	tp->hw_start(dev);
+
+	netif_start_queue(dev);
+}
+
+
+static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
+					 void __iomem *ioaddr)
+{
+	/*
+	 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
+	 * register to be written before TxDescAddrLow to work.
+	 * Switching from MMIO to I/O access fixes the issue as well.
+	 */
+	RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
+	RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK);
+	RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
+	RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK);
+}
+
+static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
+{
+	u16 cmd;
+
+	cmd = RTL_R16(CPlusCmd);
+	RTL_W16(CPlusCmd, cmd);
+	return cmd;
+}
+
+static void rtl_set_rx_max_size(void __iomem *ioaddr)
+{
+	/* Low hurts. Let's disable the filtering. */
+	RTL_W16(RxMaxSize, 16383);
+}
+
+static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
+{
+	struct {
+		u32 mac_version;
+		u32 clk;
+		u32 val;
+	} cfg2_info [] = {
+		{ RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
+		{ RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
+		{ RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
+		{ RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
+	}, *p = cfg2_info;
+	unsigned int i;
+	u32 clk;
+
+	clk = RTL_R8(Config2) & PCI_Clock_66MHz;
+	for (i = 0; i < ARRAY_SIZE(cfg2_info); i++) {
+		if ((p->mac_version == mac_version) && (p->clk == clk)) {
+			RTL_W32(0x7c, p->val);
+			break;
+		}
+	}
+}
+
+static void rtl_hw_start_8169(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
 	if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
 		RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
 		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
 	}
 
-	if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
-		pci_write_config_word(pdev, 0x68, 0x00);
-		pci_write_config_word(pdev, 0x69, 0x08);
-	}
-
-	/* Undocumented stuff. */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
-		/* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
-		if ((RTL_R8(Config2) & 0x07) & 0x01)
-			RTL_W32(0x7c, 0x0007ffff);
-
-		RTL_W32(0x7c, 0x0007ff00);
-
-		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-		cmd = cmd & 0xef;
-		pci_write_config_word(pdev, PCI_COMMAND, cmd);
-	}
-
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
 	    (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
@@ -1879,19 +1908,11 @@
 
 	RTL_W8(EarlyTxThres, EarlyTxThld);
 
-	/* Low hurts. Let's disable the filtering. */
-	RTL_W16(RxMaxSize, 16383);
+	rtl_set_rx_max_size(ioaddr);
 
-	if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_04))
-		rtl8169_set_rx_tx_config_registers(tp);
+	rtl_set_rx_tx_config_registers(tp);
 
-	cmd = RTL_R16(CPlusCmd);
-	RTL_W16(CPlusCmd, cmd);
-
-	tp->cp_cmd |= cmd | PCIMulRW;
+	tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
 
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
 	    (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
@@ -1902,29 +1923,15 @@
 
 	RTL_W16(CPlusCmd, tp->cp_cmd);
 
+	rtl8169_set_magic_reg(ioaddr, tp->mac_version);
+
 	/*
 	 * Undocumented corner. Supposedly:
 	 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
 	 */
 	RTL_W16(IntrMitigate, 0x0000);
 
-	/*
-	 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
-	 * register to be written before TxDescAddrLow to work.
-	 * Switching from MMIO to I/O access fixes the issue as well.
-	 */
-	RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
-	RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
-	RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
-	RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
-
-	if ((tp->mac_version != RTL_GIGA_MAC_VER_01) &&
-	    (tp->mac_version != RTL_GIGA_MAC_VER_02) &&
-	    (tp->mac_version != RTL_GIGA_MAC_VER_03) &&
-	    (tp->mac_version != RTL_GIGA_MAC_VER_04)) {
-		RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-		rtl8169_set_rx_tx_config_registers(tp);
-	}
+	rtl_set_rx_tx_desc_registers(tp, ioaddr);
 
 	RTL_W8(Cfg9346, Cfg9346_Lock);
 
@@ -1933,15 +1940,107 @@
 
 	RTL_W32(RxMissed, 0);
 
-	rtl8169_set_rx_mode(dev);
+	rtl_set_rx_mode(dev);
 
 	/* no early-rx interrupts */
 	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
 
 	/* Enable all known interrupts by setting the interrupt mask. */
-	RTL_W16(IntrMask, rtl8169_intr_mask);
+	RTL_W16(IntrMask, tp->intr_event);
 
-	netif_start_queue(dev);
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+}
+
+static void rtl_hw_start_8168(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+	u8 ctl;
+
+	RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+	RTL_W8(EarlyTxThres, EarlyTxThld);
+
+	rtl_set_rx_max_size(ioaddr);
+
+	rtl_set_rx_tx_config_registers(tp);
+
+	tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
+
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+
+	/* Tx performance tweak. */
+	pci_read_config_byte(pdev, 0x69, &ctl);
+	ctl = (ctl & ~0x70) | 0x50;
+	pci_write_config_byte(pdev, 0x69, ctl);
+
+	RTL_W16(IntrMitigate, 0x5151);
+
+	/* Work around for RxFIFO overflow. */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
+		tp->intr_event |= RxFIFOOver | PCSTimeout;
+		tp->intr_event &= ~RxOverflow;
+	}
+
+	rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+	RTL_W8(Cfg9346, Cfg9346_Lock);
+
+	RTL_R8(IntrMask);
+
+	RTL_W32(RxMissed, 0);
+
+	rtl_set_rx_mode(dev);
+
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
+
+	RTL_W16(IntrMask, tp->intr_event);
+}
+
+static void rtl_hw_start_8101(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
+		pci_write_config_word(pdev, 0x68, 0x00);
+		pci_write_config_word(pdev, 0x69, 0x08);
+	}
+
+	RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+	RTL_W8(EarlyTxThres, EarlyTxThld);
+
+	rtl_set_rx_max_size(ioaddr);
+
+	tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
+
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+
+	RTL_W16(IntrMitigate, 0x0000);
+
+	rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+	rtl_set_rx_tx_config_registers(tp);
+
+	RTL_W8(Cfg9346, Cfg9346_Lock);
+
+	RTL_R8(IntrMask);
+
+	RTL_W32(RxMissed, 0);
+
+	rtl_set_rx_mode(dev);
+
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
+
+	RTL_W16(IntrMask, tp->intr_event);
 }
 
 static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
@@ -1967,7 +2066,7 @@
 
 	netif_poll_enable(dev);
 
-	rtl8169_hw_start(dev);
+	rtl_hw_start(dev);
 
 	rtl8169_request_timer(dev);
 
@@ -2008,38 +2107,38 @@
 	rtl8169_mark_to_asic(desc, rx_buf_sz);
 }
 
-static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
-				struct RxDesc *desc, int rx_buf_sz,
-				unsigned int align)
+static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
+					    struct net_device *dev,
+					    struct RxDesc *desc, int rx_buf_sz,
+					    unsigned int align)
 {
 	struct sk_buff *skb;
 	dma_addr_t mapping;
-	int ret = 0;
+	unsigned int pad;
 
-	skb = dev_alloc_skb(rx_buf_sz + align);
+	pad = align ? align : NET_IP_ALIGN;
+
+	skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
 	if (!skb)
 		goto err_out;
 
-	skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
-	*sk_buff = skb;
+	skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
 
 	mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
 				 PCI_DMA_FROMDEVICE);
 
 	rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
-
 out:
-	return ret;
+	return skb;
 
 err_out:
-	ret = -ENOMEM;
 	rtl8169_make_unusable_by_asic(desc);
 	goto out;
 }
 
 static void rtl8169_rx_clear(struct rtl8169_private *tp)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < NUM_RX_DESC; i++) {
 		if (tp->Rx_skbuff[i]) {
@@ -2054,16 +2153,22 @@
 {
 	u32 cur;
 
-	for (cur = start; end - cur > 0; cur++) {
-		int ret, i = cur % NUM_RX_DESC;
+	for (cur = start; end - cur != 0; cur++) {
+		struct sk_buff *skb;
+		unsigned int i = cur % NUM_RX_DESC;
+
+		WARN_ON((s32)(end - cur) < 0);
 
 		if (tp->Rx_skbuff[i])
 			continue;
 
-		ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
-			tp->RxDescArray + i, tp->rx_buf_sz, tp->align);
-		if (ret < 0)
+		skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
+					   tp->RxDescArray + i,
+					   tp->rx_buf_sz, tp->align);
+		if (!skb)
 			break;
+
+		tp->Rx_skbuff[i] = skb;
 	}
 	return cur - start;
 }
@@ -2175,14 +2280,9 @@
 
 	ret = rtl8169_open(dev);
 	if (unlikely(ret < 0)) {
-		if (net_ratelimit()) {
-			struct rtl8169_private *tp = netdev_priv(dev);
-
-			if (netif_msg_drv(tp)) {
-				printk(PFX KERN_ERR
-				       "%s: reinit failure (status = %d)."
-				       " Rescheduling.\n", dev->name, ret);
-			}
+		if (net_ratelimit() && netif_msg_drv(tp)) {
+			printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+			       " Rescheduling.\n", dev->name, ret);
 		}
 		rtl8169_schedule_work(dev, rtl8169_reinit_task);
 	}
@@ -2209,16 +2309,12 @@
 
 	if (tp->dirty_rx == tp->cur_rx) {
 		rtl8169_init_ring_indexes(tp);
-		rtl8169_hw_start(dev);
+		rtl_hw_start(dev);
 		netif_wake_queue(dev);
 	} else {
-		if (net_ratelimit()) {
-			struct rtl8169_private *tp = netdev_priv(dev);
-
-			if (netif_msg_intr(tp)) {
-				printk(PFX KERN_EMERG
-				       "%s: Rx buffers shortage\n", dev->name);
-			}
+		if (net_ratelimit() && netif_msg_intr(tp)) {
+			printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+			       dev->name);
 		}
 		rtl8169_schedule_work(dev, rtl8169_reset_task);
 	}
@@ -2242,7 +2338,7 @@
 {
 	struct skb_shared_info *info = skb_shinfo(skb);
 	unsigned int cur_frag, entry;
-	struct TxDesc *txd;
+	struct TxDesc * uninitialized_var(txd);
 
 	entry = tp->cur_tx;
 	for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
@@ -2355,7 +2451,7 @@
 
 	smp_wmb();
 
-	RTL_W8(TxPoll, 0x40);	/* set polling bit */
+	RTL_W8(TxPoll, NPQ);	/* set polling bit */
 
 	if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
 		netif_stop_queue(dev);
@@ -2425,16 +2521,12 @@
 	rtl8169_schedule_work(dev, rtl8169_reinit_task);
 }
 
-static void
-rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
-		     void __iomem *ioaddr)
+static void rtl8169_tx_interrupt(struct net_device *dev,
+				 struct rtl8169_private *tp,
+				 void __iomem *ioaddr)
 {
 	unsigned int dirty_tx, tx_left;
 
-	assert(dev != NULL);
-	assert(tp != NULL);
-	assert(ioaddr != NULL);
-
 	dirty_tx = tp->dirty_tx;
 	smp_rmb();
 	tx_left = tp->cur_tx - dirty_tx;
@@ -2491,38 +2583,37 @@
 		skb->ip_summed = CHECKSUM_NONE;
 }
 
-static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
-				      struct RxDesc *desc, int rx_buf_sz,
-				      unsigned int align)
+static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
+				       struct rtl8169_private *tp, int pkt_size,
+				       dma_addr_t addr)
 {
-	int ret = -1;
+	struct sk_buff *skb;
+	bool done = false;
 
-	if (pkt_size < rx_copybreak) {
-		struct sk_buff *skb;
+	if (pkt_size >= rx_copybreak)
+		goto out;
 
-		skb = dev_alloc_skb(pkt_size + align);
-		if (skb) {
-			skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
-			eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
-			*sk_buff = skb;
-			rtl8169_mark_to_asic(desc, rx_buf_sz);
-			ret = 0;
-		}
-	}
-	return ret;
+	skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN);
+	if (!skb)
+		goto out;
+
+	pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
+				    PCI_DMA_FROMDEVICE);
+	skb_reserve(skb, NET_IP_ALIGN);
+	skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
+	*sk_buff = skb;
+	done = true;
+out:
+	return done;
 }
 
-static int
-rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
-		     void __iomem *ioaddr)
+static int rtl8169_rx_interrupt(struct net_device *dev,
+				struct rtl8169_private *tp,
+				void __iomem *ioaddr)
 {
 	unsigned int cur_rx, rx_left;
 	unsigned int delta, count;
 
-	assert(dev != NULL);
-	assert(tp != NULL);
-	assert(ioaddr != NULL);
-
 	cur_rx = tp->cur_rx;
 	rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
 	rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
@@ -2555,9 +2646,9 @@
 			rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
 		} else {
 			struct sk_buff *skb = tp->Rx_skbuff[entry];
+			dma_addr_t addr = le64_to_cpu(desc->addr);
 			int pkt_size = (status & 0x00001FFF) - 4;
-			void (*pci_action)(struct pci_dev *, dma_addr_t,
-				size_t, int) = pci_dma_sync_single_for_device;
+			struct pci_dev *pdev = tp->pci_dev;
 
 			/*
 			 * The driver does not support incoming fragmented
@@ -2573,19 +2664,16 @@
 
 			rtl8169_rx_csum(skb, desc);
 
-			pci_dma_sync_single_for_cpu(tp->pci_dev,
-				le64_to_cpu(desc->addr), tp->rx_buf_sz,
-				PCI_DMA_FROMDEVICE);
-
-			if (rtl8169_try_rx_copy(&skb, pkt_size, desc,
-						tp->rx_buf_sz, tp->align)) {
-				pci_action = pci_unmap_single;
+			if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
+				pci_dma_sync_single_for_device(pdev, addr,
+					pkt_size, PCI_DMA_FROMDEVICE);
+				rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+			} else {
+				pci_unmap_single(pdev, addr, pkt_size,
+						 PCI_DMA_FROMDEVICE);
 				tp->Rx_skbuff[entry] = NULL;
 			}
 
-			pci_action(tp->pci_dev, le64_to_cpu(desc->addr),
-				   tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
 			skb_put(skb, pkt_size);
 			skb->protocol = eth_type_trans(skb, dev);
 
@@ -2596,6 +2684,13 @@
 			tp->stats.rx_bytes += pkt_size;
 			tp->stats.rx_packets++;
 		}
+
+		/* Work around for AMD plateform. */
+		if ((desc->opts2 & 0xfffe000) &&
+		    (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
+			desc->opts2 = 0;
+			cur_rx++;
+		}
 	}
 
 	count = cur_rx - tp->cur_rx;
@@ -2619,11 +2714,9 @@
 	return count;
 }
 
-/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
-static irqreturn_t
-rtl8169_interrupt(int irq, void *dev_instance)
+static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
 {
-	struct net_device *dev = (struct net_device *) dev_instance;
+	struct net_device *dev = dev_instance;
 	struct rtl8169_private *tp = netdev_priv(dev);
 	int boguscnt = max_interrupt_work;
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -2648,9 +2741,17 @@
 		RTL_W16(IntrStatus,
 			(status & RxFIFOOver) ? (status | RxOverflow) : status);
 
-		if (!(status & rtl8169_intr_mask))
+		if (!(status & tp->intr_event))
 			break;
 
+                /* Work around for rx fifo overflow */
+                if (unlikely(status & RxFIFOOver) &&
+		    (tp->mac_version == RTL_GIGA_MAC_VER_11)) {
+			netif_stop_queue(dev);
+			rtl8169_tx_timeout(dev);
+			break;
+		}
+
 		if (unlikely(status & SYSErr)) {
 			rtl8169_pcierr_interrupt(dev);
 			break;
@@ -2660,8 +2761,8 @@
 			rtl8169_check_link_status(dev, tp, ioaddr);
 
 #ifdef CONFIG_R8169_NAPI
-		RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
-		tp->intr_mask = ~rtl8169_napi_event;
+		RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
+		tp->intr_mask = ~tp->napi_event;
 
 		if (likely(netif_rx_schedule_prep(dev)))
 			__netif_rx_schedule(dev);
@@ -2672,9 +2773,9 @@
 		break;
 #else
 		/* Rx interrupt */
-		if (status & (RxOK | RxOverflow | RxFIFOOver)) {
+		if (status & (RxOK | RxOverflow | RxFIFOOver))
 			rtl8169_rx_interrupt(dev, tp, ioaddr);
-		}
+
 		/* Tx interrupt */
 		if (status & (TxOK | TxErr))
 			rtl8169_tx_interrupt(dev, tp, ioaddr);
@@ -2718,7 +2819,7 @@
 		 * write is safe - FR
 		 */
 		smp_wmb();
-		RTL_W16(IntrMask, rtl8169_intr_mask);
+		RTL_W16(IntrMask, tp->intr_event);
 	}
 
 	return (work_done >= work_to_do);
@@ -2800,14 +2901,13 @@
 	return 0;
 }
 
-static void
-rtl8169_set_rx_mode(struct net_device *dev)
+static void rtl_set_rx_mode(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 	u32 mc_filter[2];	/* Multicast hash filter */
-	int i, rx_mode;
+	int rx_mode;
 	u32 tmp = 0;
 
 	if (dev->flags & IFF_PROMISC) {
@@ -2827,6 +2927,8 @@
 		mc_filter[1] = mc_filter[0] = 0xffffffff;
 	} else {
 		struct dev_mc_list *mclist;
+		unsigned int i;
+
 		rx_mode = AcceptBroadcast | AcceptMyPhys;
 		mc_filter[1] = mc_filter[0] = 0;
 		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
@@ -2851,10 +2953,11 @@
 		mc_filter[1] = 0xffffffff;
 	}
 
-	RTL_W32(RxConfig, tmp);
 	RTL_W32(MAR0 + 0, mc_filter[0]);
 	RTL_W32(MAR0 + 4, mc_filter[1]);
 
+	RTL_W32(RxConfig, tmp);
+
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
@@ -2942,14 +3045,12 @@
 #endif
 };
 
-static int __init
-rtl8169_init_module(void)
+static int __init rtl8169_init_module(void)
 {
 	return pci_register_driver(&rtl8169_pci_driver);
 }
 
-static void __exit
-rtl8169_cleanup_module(void)
+static void __exit rtl8169_cleanup_module(void)
 {
 	pci_unregister_driver(&rtl8169_pci_driver);
 }
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 25c73d4..5c2e41f 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -516,7 +516,7 @@
 }
 
 
-static int __init rr_init(struct net_device *dev)
+static int __devinit rr_init(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs __iomem *regs;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index e3e6d41..afef6c0 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -340,17 +340,6 @@
 /* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
 static int vlan_strip_flag;
 
-/* Unregister the vlan */
-static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
-{
-	struct s2io_nic *nic = dev->priv;
-	unsigned long flags;
-
-	spin_lock_irqsave(&nic->tx_lock, flags);
-	vlan_group_set_device(nic->vlgrp, vid, NULL);
-	spin_unlock_irqrestore(&nic->tx_lock, flags);
-}
-
 /*
  * Constants to be programmed into the Xena's registers, to configure
  * the XAUI.
@@ -480,11 +469,18 @@
 
 MODULE_DEVICE_TABLE(pci, s2io_tbl);
 
+static struct pci_error_handlers s2io_err_handler = {
+	.error_detected = s2io_io_error_detected,
+	.slot_reset = s2io_io_slot_reset,
+	.resume = s2io_io_resume,
+};
+
 static struct pci_driver s2io_driver = {
       .name = "S2IO",
       .id_table = s2io_tbl,
       .probe = s2io_init_nic,
       .remove = __devexit_p(s2io_rem_nic),
+      .err_handler = &s2io_err_handler,
 };
 
 /* A simplifier macro used both by init and free shared_mem Fns(). */
@@ -800,12 +796,14 @@
 	struct mac_info *mac_control;
 	struct config_param *config;
 	int lst_size, lst_per_page;
-	struct net_device *dev = nic->dev;
+	struct net_device *dev;
 	int page_num = 0;
 
 	if (!nic)
 		return;
 
+	dev = nic->dev;
+
 	mac_control = &nic->mac_control;
 	config = &nic->config;
 
@@ -1139,7 +1137,7 @@
 	 * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
 	 */
 	if ((nic->device_type == XFRAME_I_DEVICE) &&
-		(get_xena_rev_id(nic->pdev) < 4))
+		(nic->pdev->revision < 4))
 		writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
 
 	val64 = readq(&bar0->tx_fifo_partition_0);
@@ -1877,7 +1875,7 @@
 	herc = (sp->device_type == XFRAME_II_DEVICE);
 
 	if (flag == FALSE) {
-		if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
+		if ((!herc && (sp->pdev->revision >= 4)) || herc) {
 			if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE))
 				ret = 1;
 		} else {
@@ -1885,7 +1883,7 @@
 				ret = 1;
 		}
 	} else {
-		if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
+		if ((!herc && (sp->pdev->revision >= 4)) || herc) {
 			if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
 			     ADAPTER_STATUS_RMAC_PCC_IDLE))
 				ret = 1;
@@ -2700,6 +2698,9 @@
 	u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
 	int i;
 
+	if (pci_channel_offline(nic->pdev))
+		return;
+
 	disable_irq(dev->irq);
 
 	atomic_inc(&nic->isr_cnt);
@@ -2879,6 +2880,7 @@
 	struct tx_curr_get_info get_info, put_info;
 	struct sk_buff *skb;
 	struct TxD *txdlp;
+	u8 err_mask;
 
 	get_info = fifo_data->tx_curr_get_info;
 	memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info));
@@ -2897,8 +2899,8 @@
 			}
 
 			/* update t_code statistics */
-			err >>= 48;
-			switch(err) {
+			err_mask = err >> 48;
+			switch(err_mask) {
 				case 2:
 					nic->mac_control.stats_info->sw_stat.
 							tx_buf_abort_cnt++;
@@ -3225,6 +3227,8 @@
 	int i;
 	if (atomic_read(&nic->card_state) == CARD_DOWN)
 		return;
+	if (pci_channel_offline(nic->pdev))
+		return;
 	nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
 	/* Handling the XPAK counters update */
 	if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
@@ -3968,7 +3972,6 @@
 	/* Reset card, kill tasklet and free Tx and Rx buffers. */
 	s2io_card_down(sp);
 
-	sp->device_close_flag = TRUE;	/* Device is shut down. */
 	return 0;
 }
 
@@ -4324,6 +4327,10 @@
 	struct mac_info *mac_control;
 	struct config_param *config;
 
+	/* Pretend we handled any irq's from a disconnected card */
+	if (pci_channel_offline(sp->pdev))
+		return IRQ_NONE;
+
 	atomic_inc(&sp->isr_cnt);
 	mac_control = &sp->mac_control;
 	config = &sp->config;
@@ -6579,7 +6586,7 @@
 	} while(cnt < 5);
 }
 
-static void s2io_card_down(struct s2io_nic * sp)
+static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
 {
 	int cnt = 0;
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -6594,7 +6601,8 @@
 	atomic_set(&sp->card_state, CARD_DOWN);
 
 	/* disable Tx and Rx traffic on the NIC */
-	stop_nic(sp);
+	if (do_io)
+		stop_nic(sp);
 
 	s2io_rem_isr(sp);
 
@@ -6602,7 +6610,7 @@
 	tasklet_kill(&sp->task);
 
 	/* Check if the device is Quiescent and then Reset the NIC */
-	do {
+	while(do_io) {
 		/* As per the HW requirement we need to replenish the
 		 * receive buffer to avoid the ring bump. Since there is
 		 * no intention of processing the Rx frame at this pointwe are
@@ -6627,8 +6635,9 @@
 				  (unsigned long long) val64);
 			break;
 		}
-	} while (1);
-	s2io_reset(sp);
+	}
+	if (do_io)
+		s2io_reset(sp);
 
 	spin_lock_irqsave(&sp->tx_lock, flags);
 	/* Free all Tx buffers */
@@ -6643,6 +6652,11 @@
 	clear_bit(0, &(sp->link_state));
 }
 
+static void s2io_card_down(struct s2io_nic * sp)
+{
+	do_s2io_card_down(sp, 1);
+}
+
 static int s2io_card_up(struct s2io_nic * sp)
 {
 	int i, ret = 0;
@@ -6816,6 +6830,7 @@
 	u16 l3_csum, l4_csum;
 	unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
 	struct lro *lro;
+	u8 err_mask;
 
 	skb->dev = dev;
 
@@ -6824,8 +6839,8 @@
 		if (err & 0x1) {
 			sp->mac_control.stats_info->sw_stat.parity_err_cnt++;
 		}
-		err >>= 48;
-		switch(err) {
+		err_mask = err >> 48;
+		switch(err_mask) {
 			case 1:
 				sp->mac_control.stats_info->sw_stat.
 				rx_parity_err_cnt++;
@@ -6878,9 +6893,9 @@
 		* Note that in this case, since checksum will be incorrect,
 		* stack will validate the same.
 		*/
-		if (err != 0x5) {
-			DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
-				dev->name, err);
+		if (err_mask != 0x5) {
+			DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%x\n",
+				dev->name, err_mask);
 			sp->stats.rx_crc_errors++;
 			sp->mac_control.stats_info->sw_stat.mem_freed 
 				+= skb->truesize;
@@ -7063,23 +7078,6 @@
 }
 
 /**
- *  get_xena_rev_id - to identify revision ID of xena.
- *  @pdev : PCI Dev structure
- *  Description:
- *  Function to identify the Revision ID of xena.
- *  Return value:
- *  returns the revision ID of the device.
- */
-
-static int get_xena_rev_id(struct pci_dev *pdev)
-{
-	u8 id = 0;
-	int ret;
-	ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
-	return id;
-}
-
-/**
  *  s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
  *  @sp : private member of the device structure, which is a pointer to the
  *  s2io_nic structure.
@@ -7412,7 +7410,6 @@
 	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = s2io_vlan_rx_register;
-	dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
 
 	/*
 	 * will use eth_mac_addr() for  dev->set_mac_address
@@ -7538,7 +7535,7 @@
 	s2io_vpd_read(sp);
 	DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2007 Neterion Inc.\n");
 	DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name,
-		  sp->product_name, get_xena_rev_id(sp->pdev));
+		  sp->product_name, pdev->revision);
 	DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
 		  s2io_driver_version);
 	DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
@@ -8020,3 +8017,85 @@
 	sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
 	return;
 }
+
+/**
+ * s2io_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+                                               pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct s2io_nic *sp = netdev->priv;
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev)) {
+		/* Bring down the card, while avoiding PCI I/O */
+		do_s2io_card_down(sp, 0);
+	}
+	pci_disable_device(pdev);
+
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * s2io_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ * At this point, the card has exprienced a hard reset,
+ * followed by fixups by BIOS, and has its config space
+ * set up identically to what it was at cold boot.
+ */
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct s2io_nic *sp = netdev->priv;
+
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR "s2io: "
+		       "Cannot re-enable PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	pci_set_master(pdev);
+	s2io_reset(sp);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * s2io_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells
+ * us that its OK to resume normal operation.
+ */
+static void s2io_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct s2io_nic *sp = netdev->priv;
+
+	if (netif_running(netdev)) {
+		if (s2io_card_up(sp)) {
+			printk(KERN_ERR "s2io: "
+			       "Can't bring device back up after reset.\n");
+			return;
+		}
+
+		if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
+			s2io_card_down(sp);
+			printk(KERN_ERR "s2io: "
+			       "Can't resetore mac addr after reset.\n");
+			return;
+		}
+	}
+
+	netif_device_attach(netdev);
+	netif_wake_queue(netdev);
+}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 54baa0b..3887fe6 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -794,7 +794,6 @@
 
 	struct net_device_stats stats;
 	int high_dma_flag;
-	int device_close_flag;
 	int device_enabled_once;
 
 	char name[60];
@@ -1034,7 +1033,6 @@
 static int s2io_set_swapper(struct s2io_nic * sp);
 static void s2io_card_down(struct s2io_nic *nic);
 static int s2io_card_up(struct s2io_nic *nic);
-static int get_xena_rev_id(struct pci_dev *pdev);
 static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
 					int bit_state);
 static int s2io_add_isr(struct s2io_nic * sp);
@@ -1052,6 +1050,11 @@
 			   struct sk_buff *skb, u32 tcp_len);
 static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
 
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+			                      pci_channel_state_t state);
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev);
+static void s2io_io_resume(struct pci_dev *pdev);
+
 #define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
 #define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
 #define s2io_offload_type(skb) skb_shinfo(skb)->gso_type
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index ad94358..451486b 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -690,9 +690,9 @@
 				lp->stats.rx_packets++;
 				skb_reserve(skb, 2);	/* 16 byte align */
 				skb_put(skb, len);	/* make room */
-				eth_copy_and_sum(skb,
+				skb_copy_to_linear_data(skb,
 						 (unsigned char *) pData,
-						 len, 0);
+						 len);
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
 				dev->last_rx = jiffies;
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 132e214..e7fdcf1 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -1159,7 +1159,7 @@
 
 	__raw_writeq(0, sc->sbm_imr);
 
-	sbmac_intr(irq, netdev, NULL);
+	sbmac_intr(irq, netdev);
 
 #ifdef CONFIG_SBMAC_COALESCE
 	__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 2106bec..384b468 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -320,7 +320,7 @@
 				skb_put(skb, len);
 
 				/* Copy out of kseg1 to avoid silly cache flush. */
-				eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
+				skb_copy_to_linear_data(skb, pkt_pointer + 2, len);
 				skb->protocol = eth_type_trans(skb, dev);
 
 				/* We don't want to receive our own packets */
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index bc8de48..ec2ad9f 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -548,7 +548,7 @@
 		skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
 		if (skb) {
 			skb_reserve(skb, NET_IP_ALIGN);
-			eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+			skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
 			*sk_buff = skb;
 			sis190_give_to_asic(desc, rx_buf_sz);
 			ret = 0;
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 2cb2e15..7c6e480 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -573,7 +573,7 @@
  *	return error if it failed to found.
  */
 
-static int __init sis900_mii_probe(struct net_device * net_dev)
+static int __devinit sis900_mii_probe(struct net_device * net_dev)
 {
 	struct sis900_private * sis_priv = net_dev->priv;
 	const char *dev_name = pci_name(sis_priv->pci_dev);
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
deleted file mode 100644
index afd900d..0000000
--- a/drivers/net/sk98lin/Makefile
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Makefile for the SysKonnect SK-98xx device driver.
-#
-
-
-#
-# Standalone driver params
-# SKPARAM += -DSK_KERNEL_24
-# SKPARAM += -DSK_KERNEL_24_26
-# SKPARAM += -DSK_KERNEL_26
-# SKPARAM += -DSK_KERNEL_22_24
-
-obj-$(CONFIG_SK98LIN) += sk98lin.o
-sk98lin-objs    :=	\
-		skge.o		\
-		skethtool.o	\
-		skdim.o		\
-		skaddr.o	\
-		skgehwt.o	\
-		skgeinit.o	\
-		skgepnmi.o	\
-		skgesirq.o	\
-		ski2c.o		\
-		sklm80.o	\
-		skqueue.o	\
-		skrlmt.o	\
-		sktimer.o	\
-		skvpd.o		\
-		skxmac2.o
-
-# DBGDEF =  \
-# -DDEBUG
-
-ifdef DEBUG
-DBGDEF +=  \
--DSK_DEBUG_CHKMOD=0x00000000L \
--DSK_DEBUG_CHKCAT=0x00000000L
-endif
-
-
-# **** possible debug modules for SK_DEBUG_CHKMOD *****************
-# SK_DBGMOD_MERR        0x00000001L     /* general module error indication */
-# SK_DBGMOD_HWM         0x00000002L     /* Hardware init module */
-# SK_DBGMOD_RLMT        0x00000004L     /* RLMT module */
-# SK_DBGMOD_VPD         0x00000008L     /* VPD module */
-# SK_DBGMOD_I2C         0x00000010L     /* I2C module */
-# SK_DBGMOD_PNMI        0x00000020L     /* PNMI module */
-# SK_DBGMOD_CSUM        0x00000040L     /* CSUM module */
-# SK_DBGMOD_ADDR        0x00000080L     /* ADDR module */
-# SK_DBGMOD_DRV         0x00010000L     /* DRV module */
-
-# **** possible debug categories for SK_DEBUG_CHKCAT **************
-# *** common modules ***
-# SK_DBGCAT_INIT        0x00000001L     module/driver initialization
-# SK_DBGCAT_CTRL        0x00000002L     controlling: add/rmv MCA/MAC and other controls (IOCTL)
-# SK_DBGCAT_ERR         0x00000004L     error handling paths
-# SK_DBGCAT_TX          0x00000008L     transmit path
-# SK_DBGCAT_RX          0x00000010L     receive path
-# SK_DBGCAT_IRQ         0x00000020L     general IRQ handling
-# SK_DBGCAT_QUEUE       0x00000040L     any queue management
-# SK_DBGCAT_DUMP        0x00000080L     large data output e.g. hex dump
-# SK_DBGCAT_FATAL       0x00000100L     large data output e.g. hex dump
-
-# *** driver (file skge.c) ***
-# SK_DBGCAT_DRV_ENTRY           0x00010000      entry points
-# SK_DBGCAT_DRV_???             0x00020000      not used
-# SK_DBGCAT_DRV_MCA             0x00040000      multicast
-# SK_DBGCAT_DRV_TX_PROGRESS     0x00080000      tx path
-# SK_DBGCAT_DRV_RX_PROGRESS     0x00100000      rx path
-# SK_DBGCAT_DRV_PROGRESS        0x00200000      general runtime
-# SK_DBGCAT_DRV_???             0x00400000      not used
-# SK_DBGCAT_DRV_PROM            0x00800000      promiscuous mode
-# SK_DBGCAT_DRV_TX_FRAME        0x01000000      display tx frames
-# SK_DBGCAT_DRV_ERROR           0x02000000      error conditions
-# SK_DBGCAT_DRV_INT_SRC         0x04000000      interrupts sources
-# SK_DBGCAT_DRV_EVENT           0x08000000      driver events
-
-EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
-
-clean:
-	rm -f core *.o *.a *.s
-
-
-
-
-
-
diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
deleted file mode 100644
index 4e2dbbf..0000000
--- a/drivers/net/sk98lin/h/lm80.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name:	lm80.h	
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.6 $
- * Date:	$Date: 2003/05/13 17:26:52 $
- * Purpose:	Contains all defines for the LM80 Chip
- *		(National Semiconductor).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_LM80_H
-#define __INC_LM80_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * LM80 register definition
- *
- * All registers are 8 bit wide
- */
-#define LM80_CFG			0x00	/* Configuration Register */
-#define LM80_ISRC_1			0x01	/* Interrupt Status Register 1 */
-#define LM80_ISRC_2			0x02	/* Interrupt Status Register 2 */
-#define LM80_IMSK_1			0x03	/* Interrupt Mask Register 1 */
-#define LM80_IMSK_2			0x04	/* Interrupt Mask Register 2 */
-#define LM80_FAN_CTRL		0x05	/* Fan Devisor/RST#/OS# Register */
-#define LM80_TEMP_CTRL		0x06	/* OS# Config, Temp Res. Reg */
-	/* 0x07 - 0x1f reserved	*/
-	/* current values */
-#define LM80_VT0_IN			0x20	/* current Voltage 0 value */
-#define LM80_VT1_IN			0x21	/* current Voltage 1 value */
-#define LM80_VT2_IN			0x22	/* current Voltage 2 value */
-#define LM80_VT3_IN			0x23	/* current Voltage 3 value */
-#define LM80_VT4_IN			0x24	/* current Voltage 4 value */
-#define LM80_VT5_IN			0x25	/* current Voltage 5 value */
-#define LM80_VT6_IN			0x26	/* current Voltage 6 value */
-#define LM80_TEMP_IN		0x27	/* current Temperature value */
-#define LM80_FAN1_IN		0x28	/* current Fan 1 count */
-#define LM80_FAN2_IN		0x29	/* current Fan 2 count */
-	/* limit values */
-#define LM80_VT0_HIGH_LIM	0x2a	/* high limit val for Voltage 0 */
-#define LM80_VT0_LOW_LIM	0x2b	/* low limit val for Voltage 0 */
-#define LM80_VT1_HIGH_LIM	0x2c	/* high limit val for Voltage 1 */
-#define LM80_VT1_LOW_LIM	0x2d	/* low limit val for Voltage 1 */
-#define LM80_VT2_HIGH_LIM	0x2e	/* high limit val for Voltage 2 */
-#define LM80_VT2_LOW_LIM	0x2f	/* low limit val for Voltage 2 */
-#define LM80_VT3_HIGH_LIM	0x30	/* high limit val for Voltage 3 */
-#define LM80_VT3_LOW_LIM	0x31	/* low limit val for Voltage 3 */
-#define LM80_VT4_HIGH_LIM	0x32	/* high limit val for Voltage 4 */
-#define LM80_VT4_LOW_LIM	0x33	/* low limit val for Voltage 4 */
-#define LM80_VT5_HIGH_LIM	0x34	/* high limit val for Voltage 5 */
-#define LM80_VT5_LOW_LIM	0x35	/* low limit val for Voltage 5 */
-#define LM80_VT6_HIGH_LIM	0x36	/* high limit val for Voltage 6 */
-#define LM80_VT6_LOW_LIM	0x37	/* low limit val for Voltage 6 */
-#define LM80_THOT_LIM_UP	0x38	/* hot temperature limit (high) */
-#define LM80_THOT_LIM_LO	0x39	/* hot temperature limit (low) */
-#define LM80_TOS_LIM_UP		0x3a	/* OS temperature limit (high) */
-#define LM80_TOS_LIM_LO		0x3b	/* OS temperature limit (low) */
-#define LM80_FAN1_COUNT_LIM	0x3c	/* Fan 1 count limit (high) */
-#define LM80_FAN2_COUNT_LIM	0x3d	/* Fan 2 count limit (low) */
-	/* 0x3e - 0x3f reserved	*/
-
-/*
- * LM80 bit definitions
- */
-
-/*	LM80_CFG		Configuration Register */
-#define LM80_CFG_START		(1<<0)	/* start monitoring operation */
-#define LM80_CFG_INT_ENA	(1<<1)	/* enables the INT# Interrupt output */
-#define LM80_CFG_INT_POL	(1<<2)	/* INT# pol: 0 act low, 1 act high */
-#define LM80_CFG_INT_CLR	(1<<3)	/* disables INT#/RST_OUT#/OS# outputs */
-#define LM80_CFG_RESET		(1<<4)	/* signals a reset */
-#define LM80_CFG_CHASS_CLR	(1<<5)	/* clears Chassis Intrusion (CI) pin */
-#define LM80_CFG_GPO		(1<<6)	/* drives the GPO# pin */
-#define LM80_CFG_INIT		(1<<7)	/* restore power on defaults */
-
-/*	LM80_ISRC_1		Interrupt Status Register 1 */
-/*	LM80_IMSK_1		Interrupt Mask Register 1 */
-#define LM80_IS_VT0			(1<<0)	/* limit exceeded for Voltage 0 */
-#define LM80_IS_VT1			(1<<1)	/* limit exceeded for Voltage 1 */
-#define LM80_IS_VT2			(1<<2)	/* limit exceeded for Voltage 2 */
-#define LM80_IS_VT3			(1<<3)	/* limit exceeded for Voltage 3 */
-#define LM80_IS_VT4			(1<<4)	/* limit exceeded for Voltage 4 */
-#define LM80_IS_VT5			(1<<5)	/* limit exceeded for Voltage 5 */
-#define LM80_IS_VT6			(1<<6)	/* limit exceeded for Voltage 6 */
-#define LM80_IS_INT_IN		(1<<7)	/* state of INT_IN# */
-
-/*	LM80_ISRC_2		Interrupt Status Register 2 */
-/*	LM80_IMSK_2		Interrupt Mask Register 2 */
-#define LM80_IS_TEMP		(1<<0)	/* HOT temperature limit exceeded */
-#define LM80_IS_BTI			(1<<1)	/* state of BTI# pin */
-#define LM80_IS_FAN1		(1<<2)	/* count limit exceeded for Fan 1 */
-#define LM80_IS_FAN2		(1<<3)	/* count limit exceeded for Fan 2 */
-#define LM80_IS_CI			(1<<4)	/* Chassis Intrusion occured */
-#define LM80_IS_OS			(1<<5)	/* OS temperature limit exceeded */
-	/* bit 6 and 7 are reserved in LM80_ISRC_2 */
-#define LM80_IS_HT_IRQ_MD	(1<<6)	/* Hot temperature interrupt mode */
-#define LM80_IS_OT_IRQ_MD	(1<<7)	/* OS temperature interrupt mode */
-
-/*	LM80_FAN_CTRL		Fan Devisor/RST#/OS# Register */
-#define LM80_FAN1_MD_SEL	(1<<0)	/* Fan 1 mode select */
-#define LM80_FAN2_MD_SEL	(1<<1)	/* Fan 2 mode select */
-#define LM80_FAN1_PRM_CTL	(3<<2)	/* Fan 1 speed control */
-#define LM80_FAN2_PRM_CTL	(3<<4)	/* Fan 2 speed control */
-#define LM80_FAN_OS_ENA		(1<<6)	/* enable OS mode on RST_OUT#/OS# pins*/
-#define LM80_FAN_RST_ENA	(1<<7)	/* sets RST_OUT#/OS# pins in RST mode */
-
-/*	LM80_TEMP_CTRL		OS# Config, Temp Res. Reg */
-#define LM80_TEMP_OS_STAT	(1<<0)	/* mirrors the state of RST_OUT#/OS# */
-#define LM80_TEMP_OS_POL	(1<<1)	/* select OS# polarity */
-#define LM80_TEMP_OS_MODE	(1<<2)	/* selects Interrupt mode */
-#define LM80_TEMP_RES		(1<<3)	/* selects 9 or 11 bit temp resulution*/
-#define LM80_TEMP_LSB		(0xf<<4)/* 4 LSBs of 11 bit temp data */
-#define LM80_TEMP_LSB_9		(1<<7)	/* LSB of 9 bit temperature data */
-
-	/* 0x07 - 0x1f reserved	*/
-/*	LM80_VT0_IN		current Voltage 0 value */
-/*	LM80_VT1_IN		current Voltage 1 value */
-/*	LM80_VT2_IN		current Voltage 2 value */
-/*	LM80_VT3_IN		current Voltage 3 value */
-/*	LM80_VT4_IN		current Voltage 4 value */
-/*	LM80_VT5_IN		current Voltage 5 value */
-/*	LM80_VT6_IN		current Voltage 6 value */
-/*	LM80_TEMP_IN		current temperature value */
-/*	LM80_FAN1_IN		current Fan 1 count */
-/*	LM80_FAN2_IN		current Fan 2 count */
-/*	LM80_VT0_HIGH_LIM	high limit val for Voltage 0 */
-/*	LM80_VT0_LOW_LIM	low limit val for Voltage 0 */
-/*	LM80_VT1_HIGH_LIM	high limit val for Voltage 1 */
-/*	LM80_VT1_LOW_LIM	low limit val for Voltage 1 */
-/*	LM80_VT2_HIGH_LIM	high limit val for Voltage 2 */
-/*	LM80_VT2_LOW_LIM	low limit val for Voltage 2 */
-/*	LM80_VT3_HIGH_LIM	high limit val for Voltage 3 */
-/*	LM80_VT3_LOW_LIM	low limit val for Voltage 3 */
-/*	LM80_VT4_HIGH_LIM	high limit val for Voltage 4 */
-/*	LM80_VT4_LOW_LIM	low limit val for Voltage 4 */
-/*	LM80_VT5_HIGH_LIM	high limit val for Voltage 5 */
-/*	LM80_VT5_LOW_LIM	low limit val for Voltage 5 */
-/*	LM80_VT6_HIGH_LIM	high limit val for Voltage 6 */
-/*	LM80_VT6_LOW_LIM	low limit val for Voltage 6 */
-/*	LM80_THOT_LIM_UP	hot temperature limit (high) */
-/*	LM80_THOT_LIM_LO	hot temperature limit (low) */
-/*	LM80_TOS_LIM_UP		OS temperature limit (high) */
-/*	LM80_TOS_LIM_LO		OS temperature limit (low) */
-/*	LM80_FAN1_COUNT_LIM	Fan 1 count limit (high) */
-/*	LM80_FAN2_COUNT_LIM	Fan 2 count limit (low) */
-	/* 0x3e - 0x3f reserved	*/
-
-#define LM80_ADDR		0x28	/* LM80 default addr */
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_LM80_H */
diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
deleted file mode 100644
index 423ad06..0000000
--- a/drivers/net/sk98lin/h/skaddr.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/******************************************************************************
- *
- * Name:	skaddr.h
- * Project:	Gigabit Ethernet Adapters, ADDR-Modul
- * Version:	$Revision: 1.29 $
- * Date:	$Date: 2003/05/13 16:57:24 $
- * Purpose:	Header file for Address Management (MC, UC, Prom).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses and promiscuous mode
- * on GEnesis adapters.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	...
- *	"sktypes.h"
- *	"skqueue.h"
- *	"skaddr.h"
- *	...
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKADDR_H
-#define __INC_SKADDR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_MAC_ADDR_LEN				6	/* Length of MAC address. */
-#define	SK_MAX_ADDRS				14	/* #Addrs for exact match. */
-
-/* ----- Common return values ----- */
-
-#define SK_ADDR_SUCCESS				0	/* Function returned successfully. */
-#define SK_ADDR_ILLEGAL_PORT			100	/* Port number too high. */
-#define SK_ADDR_TOO_EARLY			101	/* Function called too early. */
-
-/* ----- Clear/Add flag bits ----- */
-
-#define SK_ADDR_PERMANENT			1	/* RLMT Address */
-
-/* ----- Additional Clear flag bits ----- */
-
-#define SK_MC_SW_ONLY				2	/* Do not update HW when clearing. */
-
-/* ----- Override flag bits ----- */
-
-#define SK_ADDR_LOGICAL_ADDRESS		0
-#define SK_ADDR_VIRTUAL_ADDRESS		(SK_ADDR_LOGICAL_ADDRESS)	/* old */
-#define SK_ADDR_PHYSICAL_ADDRESS	1
-#define SK_ADDR_CLEAR_LOGICAL		2
-#define SK_ADDR_SET_LOGICAL			4
-
-/* ----- Override return values ----- */
-
-#define SK_ADDR_OVERRIDE_SUCCESS	(SK_ADDR_SUCCESS)
-#define SK_ADDR_DUPLICATE_ADDRESS	1
-#define SK_ADDR_MULTICAST_ADDRESS	2
-
-/* ----- Partitioning of excact match table ----- */
-
-#define SK_ADDR_EXACT_MATCHES		16	/* #Exact match entries. */
-
-#define SK_ADDR_FIRST_MATCH_RLMT	1
-#define SK_ADDR_LAST_MATCH_RLMT		2
-#define SK_ADDR_FIRST_MATCH_DRV		3
-#define SK_ADDR_LAST_MATCH_DRV		(SK_ADDR_EXACT_MATCHES - 1)
-
-/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
-
-#define SK_MC_FILTERING_EXACT		0	/* Exact filtering. */
-#define SK_MC_FILTERING_INEXACT		1	/* Inexact filtering. */
-
-/* ----- Additional SkAddrMcAdd return values ----- */
-
-#define SK_MC_ILLEGAL_ADDRESS		2	/* Illegal address. */
-#define SK_MC_ILLEGAL_PORT			3	/* Illegal port (not the active one). */
-#define SK_MC_RLMT_OVERFLOW			4	/* Too many RLMT mc addresses. */
-
-/* Promiscuous mode bits ----- */
-
-#define SK_PROM_MODE_NONE			0	/* Normal receive. */
-#define SK_PROM_MODE_LLC			1	/* Receive all LLC frames. */
-#define SK_PROM_MODE_ALL_MC			2	/* Receive all multicast frames. */
-/* #define SK_PROM_MODE_NON_LLC		4 */	/* Receive all non-LLC frames. */
-
-/* Macros */
-
-#ifdef OLD_STUFF
-#ifndef SK_ADDR_EQUAL
-/*
- * "&" instead of "&&" allows better optimization on IA-64.
- * The replacement is safe here, as all bytes exist.
- */
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
-	(((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
-	(((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
-	(((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
-	(((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
-	(((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
-#else	/* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
-	(*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
-#endif	/* SK_ADDR_DWORD_COMPARE */
-#endif	/* SK_ADDR_EQUAL */
-#endif /* 0 */
-
-#ifndef SK_ADDR_EQUAL
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
-	(((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
-	(((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
-	(((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
-	(((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
-	(((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
-#else	/* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
-	*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
-	(*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
-	*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
-#endif	/* SK_ADDR_DWORD_COMPARE */
-#endif	/* SK_ADDR_EQUAL */
-
-/* typedefs *******************************************************************/
-
-typedef struct s_MacAddr {
-	SK_U8	a[SK_MAC_ADDR_LEN];
-} SK_MAC_ADDR;
-
-
-/* SK_FILTER is used to ensure alignment of the filter. */
-typedef union s_InexactFilter {
-	SK_U8	Bytes[8];
-	SK_U64	Val;	/* Dummy entry for alignment only. */
-} SK_FILTER64;
-
-
-typedef struct s_AddrNet SK_ADDR_NET;
-
-
-typedef struct s_AddrPort {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_MAC_ADDR	CurrentMacAddress;	/* Current physical MAC Address. */
-	SK_MAC_ADDR	PermanentMacAddress;	/* Permanent physical MAC Address. */
-	int		PromMode;		/* Promiscuous Mode. */
-
-/* ----- Private part ----- */
-
-	SK_MAC_ADDR	PreviousMacAddress;	/* Prev. phys. MAC Address. */
-	SK_BOOL		CurrentMacAddressSet;	/* CurrentMacAddress is set. */
-	SK_U8		Align01;
-
-	SK_U32		FirstExactMatchRlmt;
-	SK_U32		NextExactMatchRlmt;
-	SK_U32		FirstExactMatchDrv;
-	SK_U32		NextExactMatchDrv;
-	SK_MAC_ADDR	Exact[SK_ADDR_EXACT_MATCHES];
-	SK_FILTER64	InexactFilter;			/* For 64-bit hash register. */
-	SK_FILTER64	InexactRlmtFilter;		/* For 64-bit hash register. */
-	SK_FILTER64	InexactDrvFilter;		/* For 64-bit hash register. */
-} SK_ADDR_PORT;
-
-
-struct s_AddrNet {
-/* ----- Public part (read-only) ----- */
-
-	SK_MAC_ADDR		CurrentMacAddress;	/* Logical MAC Address. */
-	SK_MAC_ADDR		PermanentMacAddress;	/* Logical MAC Address. */
-
-/* ----- Private part ----- */
-
-	SK_U32			ActivePort;		/* View of module ADDR. */
-	SK_BOOL			CurrentMacAddressSet;	/* CurrentMacAddress is set. */
-	SK_U8			Align01;
-	SK_U16			Align02;
-};
-
-
-typedef struct s_Addr {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_ADDR_NET		Net[SK_MAX_NETS];
-	SK_ADDR_PORT	Port[SK_MAX_MACS];
-
-/* ----- Private part ----- */
-} SK_ADDR;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkAddr */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern	int	SkAddrInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int	Level);
-
-extern	int	SkAddrMcClear(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber,
-	int	Flags);
-
-extern	int	SkAddrMcAdd(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		PortNumber,
-	SK_MAC_ADDR	*pMc,
-	int		Flags);
-
-extern	int	SkAddrMcUpdate(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber);
-
-extern	int	SkAddrOverride(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		PortNumber,
-	SK_MAC_ADDR	SK_FAR *pNewAddr,
-	int		Flags);
-
-extern	int	SkAddrPromiscuousChange(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber,
-	int	NewPromMode);
-
-#ifndef SK_SLIM
-extern	int	SkAddrSwap(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	FromPortNumber,
-	SK_U32	ToPortNumber);
-#endif
-
-#else	/* defined(SK_KR_PROTO)) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style prototypes are not yet provided.
-
-#endif	/* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKADDR_H */
diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
deleted file mode 100644
index 6e256bd..0000000
--- a/drivers/net/sk98lin/h/skcsum.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/******************************************************************************
- *
- * Name:	skcsum.h
- * Project:	GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/08/20 13:59:57 $
- * Purpose:	Store/verify Internet checksum in send/receive packets.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2001 SysKonnect GmbH.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * Public header file for the "GEnesis" common module "CSUM".
- *
- * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
- * and is the code name of this SysKonnect project.
- *
- * Compilation Options:
- *
- *	SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
- *	empty module.
- *
- *	SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
- *	definitions. In this case, all SKCS_PROTO_xxx definitions must be made
- *	external.
- *
- *	SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
- *	definitions. In this case, all SKCS_STATUS_xxx definitions must be made
- *	external.
- *
- * Include File Hierarchy:
- *
- *	"h/skcsum.h"
- *	 "h/sktypes.h"
- *	 "h/skqueue.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKCSUM_H
-#define __INC_SKCSUM_H
-
-#include "h/sktypes.h"
-#include "h/skqueue.h"
-
-/* defines ********************************************************************/
-
-/*
- * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags'  if no user
- * overwrite.
- */
-#ifndef SKCS_OVERWRITE_PROTO	/* User overwrite? */
-#define SKCS_PROTO_IP	0x1	/* IP (Internet Protocol version 4) */
-#define SKCS_PROTO_TCP	0x2	/* TCP (Transmission Control Protocol) */
-#define SKCS_PROTO_UDP	0x4	/* UDP (User Datagram Protocol) */
-
-/* Indices for protocol statistics. */
-#define SKCS_PROTO_STATS_IP	0
-#define SKCS_PROTO_STATS_UDP	1
-#define SKCS_PROTO_STATS_TCP	2
-#define SKCS_NUM_PROTOCOLS	3	/* Number of supported protocols. */
-#endif	/* !SKCS_OVERWRITE_PROTO */
-
-/*
- * Define the default SKCS_STATUS type and values if no user overwrite.
- *
- *	SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
- *	SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
- *	SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
- *	SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
- *	SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
- *	SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
- *	SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
- *	SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
- *	SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
- *	SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
- *	SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. 
- */
-#ifndef SKCS_OVERWRITE_STATUS	/* User overwrite? */
-#define SKCS_STATUS	int	/* Define status type. */
-
-#define SKCS_STATUS_UNKNOWN_IP_VERSION	1
-#define SKCS_STATUS_IP_CSUM_ERROR		2
-#define SKCS_STATUS_IP_FRAGMENT			3
-#define SKCS_STATUS_IP_CSUM_OK			4
-#define SKCS_STATUS_TCP_CSUM_ERROR		5
-#define SKCS_STATUS_UDP_CSUM_ERROR		6
-#define SKCS_STATUS_TCP_CSUM_OK			7
-#define SKCS_STATUS_UDP_CSUM_OK			8
-/* needed for Microsoft */
-#define SKCS_STATUS_IP_CSUM_ERROR_UDP	9
-#define SKCS_STATUS_IP_CSUM_ERROR_TCP	10
-/* UDP checksum may be omitted */
-#define SKCS_STATUS_IP_CSUM_OK_NO_UDP	11
-#endif	/* !SKCS_OVERWRITE_STATUS */
-
-/* Clear protocol statistics event. */
-#define SK_CSUM_EVENT_CLEAR_PROTO_STATS	1
-
-/*
- * Add two values in one's complement.
- *
- * Note: One of the two input values may be "longer" than 16-bit, but then the
- * resulting sum may be 17 bits long. In this case, add zero to the result using
- * SKCS_OC_ADD() again.
- *
- *	Result = Value1 + Value2
- */
-#define SKCS_OC_ADD(Result, Value1, Value2) {				\
-	unsigned long Sum;						\
-									\
-	Sum = (unsigned long) (Value1) + (unsigned long) (Value2);	\
-	/* Add-in any carry. */						\
-	(Result) = (Sum & 0xffff) + (Sum >> 16);			\
-}
-
-/*
- * Subtract two values in one's complement.
- *
- *	Result = Value1 - Value2
- */
-#define SKCS_OC_SUB(Result, Value1, Value2)	\
-	SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff)
-
-/* typedefs *******************************************************************/
-
-/*
- * SKCS_PROTO_STATS - The CSUM protocol statistics structure.
- *
- * There is one instance of this structure for each protocol supported.
- */
-typedef struct s_CsProtocolStatistics {
-	SK_U64 RxOkCts;		/* Receive checksum ok. */
-	SK_U64 RxUnableCts;	/* Unable to verify receive checksum. */
-	SK_U64 RxErrCts;	/* Receive checksum error. */
-	SK_U64 TxOkCts;		/* Transmit checksum ok. */
-	SK_U64 TxUnableCts;	/* Unable to calculate checksum in hw. */
-} SKCS_PROTO_STATS;
-
-/*
- * s_Csum - The CSUM module context structure.
- */
-typedef struct s_Csum {
-	/* Enabled receive SK_PROTO_XXX bit flags. */
-	unsigned ReceiveFlags[SK_MAX_NETS];
-#ifdef TX_CSUM
-	unsigned TransmitFlags[SK_MAX_NETS];
-#endif /* TX_CSUM */
-
-	/* The protocol statistics structure; one per supported protocol. */
-	SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
-} SK_CSUM;
-
-/*
- * SKCS_PACKET_INFO - The packet information structure.
- */
-typedef struct s_CsPacketInfo {
-	/* Bit field specifiying the desired/found protocols. */
-	unsigned ProtocolFlags;
-
-	/* Length of complete IP header, including any option fields. */
-	unsigned IpHeaderLength;
-
-	/* IP header checksum. */
-	unsigned IpHeaderChecksum;
-
-	/* TCP/UDP pseudo header checksum. */
-	unsigned PseudoHeaderChecksum;
-} SKCS_PACKET_INFO;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_CS_CALCULATE_CHECKSUM
-extern unsigned SkCsCalculateChecksum(
-	void		*pData,
-	unsigned	Length);
-#endif /* SK_CS_CALCULATE_CHECKSUM */
-
-extern int SkCsEvent(
-	SK_AC		*pAc,
-	SK_IOC		Ioc,
-	SK_U32		Event,
-	SK_EVPARA	Param);
-
-extern SKCS_STATUS SkCsGetReceiveInfo(
-	SK_AC		*pAc,
-	void		*pIpHeader,
-	unsigned	Checksum1,
-	unsigned	Checksum2,
-	int			NetNumber);
-
-extern void SkCsSetReceiveFlags(
-	SK_AC		*pAc,
-	unsigned	ReceiveFlags,
-	unsigned	*pChecksum1Offset,
-	unsigned	*pChecksum2Offset,
-	int			NetNumber);
-
-#endif	/* __INC_SKCSUM_H */
diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
deleted file mode 100644
index 3cba171..0000000
--- a/drivers/net/sk98lin/h/skdebug.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdebug.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.14 $
- * Date:	$Date: 2003/05/13 17:26:00 $
- * Purpose:	SK specific DEBUG support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDEBUG_H
-#define __INC_SKDEBUG_H
-
-#ifdef	DEBUG
-#ifndef SK_DBG_MSG
-#define SK_DBG_MSG(pAC,comp,cat,arg) \
-		if ( ((comp) & SK_DBG_CHKMOD(pAC)) && 	\
-		      ((cat) & SK_DBG_CHKCAT(pAC)) ) { 	\
-			SK_DBG_PRINTF arg ;		\
-		}
-#endif
-#else
-#define SK_DBG_MSG(pAC,comp,lev,arg)
-#endif
-
-/* PLS NOTE:
- * =========
- * Due to any restrictions of kernel printf routines do not use other
- * format identifiers as: %x %d %c %s .
- * Never use any combined format identifiers such as: %lx %ld in your
- * printf - argument (arg) because some OS specific kernel printfs may
- * only support some basic identifiers.
- */
-
-/* Debug modules */
-
-#define SK_DBGMOD_MERR	0x00000001L	/* general module error indication */
-#define SK_DBGMOD_HWM	0x00000002L	/* Hardware init module */
-#define SK_DBGMOD_RLMT	0x00000004L	/* RLMT module */
-#define SK_DBGMOD_VPD	0x00000008L	/* VPD module */
-#define SK_DBGMOD_I2C	0x00000010L	/* I2C module */
-#define SK_DBGMOD_PNMI	0x00000020L	/* PNMI module */
-#define SK_DBGMOD_CSUM	0x00000040L	/* CSUM module */
-#define SK_DBGMOD_ADDR	0x00000080L	/* ADDR module */
-#define SK_DBGMOD_PECP	0x00000100L	/* PECP module */
-#define SK_DBGMOD_POWM	0x00000200L	/* Power Management module */
-
-/* Debug events */
-
-#define SK_DBGCAT_INIT	0x00000001L	/* module/driver initialization */
-#define SK_DBGCAT_CTRL	0x00000002L	/* controlling devices */
-#define SK_DBGCAT_ERR	0x00000004L	/* error handling paths */
-#define SK_DBGCAT_TX	0x00000008L	/* transmit path */
-#define SK_DBGCAT_RX	0x00000010L	/* receive path */
-#define SK_DBGCAT_IRQ	0x00000020L	/* general IRQ handling */
-#define SK_DBGCAT_QUEUE	0x00000040L	/* any queue management */
-#define SK_DBGCAT_DUMP	0x00000080L	/* large data output e.g. hex dump */
-#define SK_DBGCAT_FATAL	0x00000100L	/* fatal error */
-
-#endif	/* __INC_SKDEBUG_H */
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
deleted file mode 100644
index 91b8d4f..0000000
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdrv1st.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.4 $
- * Date:	$Date: 2003/11/12 14:28:14 $
- * Purpose:	First header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the first include file of the driver, which includes all
- * neccessary system header files and some of the GEnesis header files.
- * It also defines some basic items.
- *
- * Include File Hierarchy:
- *
- *	see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#define __INC_SKDRV1ST_H
-
-typedef struct s_AC	SK_AC;
-
-/* Set card versions */
-#define SK_FAR
-
-/* override some default functions with optimized linux functions */
-
-#define SK_PNMI_STORE_U16(p,v)		memcpy((char*)(p),(char*)&(v),2)
-#define SK_PNMI_STORE_U32(p,v)		memcpy((char*)(p),(char*)&(v),4)
-#define SK_PNMI_STORE_U64(p,v)		memcpy((char*)(p),(char*)&(v),8)
-#define SK_PNMI_READ_U16(p,v)		memcpy((char*)&(v),(char*)(p),2)
-#define SK_PNMI_READ_U32(p,v)		memcpy((char*)&(v),(char*)(p),4)
-#define SK_PNMI_READ_U64(p,v)		memcpy((char*)&(v),(char*)(p),8)
-
-#define SK_ADDR_EQUAL(a1,a2)		(!memcmp(a1,a2,6))
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <net/checksum.h>
-
-#define SK_CS_CALCULATE_CHECKSUM
-#ifndef CONFIG_X86_64
-#define SkCsCalculateChecksum(p,l)	((~ip_compute_csum(p, l)) & 0xffff)
-#else
-#define SkCsCalculateChecksum(p,l)	((~ip_fast_csum(p, l)) & 0xffff)
-#endif
-
-#include	"h/sktypes.h"
-#include	"h/skerror.h"
-#include	"h/skdebug.h"
-#include	"h/lm80.h"
-#include	"h/xmac_ii.h"
-
-#ifdef __LITTLE_ENDIAN
-#define SK_LITTLE_ENDIAN
-#else
-#define SK_BIG_ENDIAN
-#endif
-
-#define SK_NET_DEVICE	net_device
-
-
-/* we use gethrtime(), return unit: nanoseconds */
-#define SK_TICKS_PER_SEC	100
-
-#define	SK_MEM_MAPPED_IO
-
-// #define SK_RLMT_SLOW_LOOKAHEAD
-
-#define SK_MAX_MACS		2
-#define SK_MAX_NETS		2
-
-#define SK_IOC			char __iomem *
-
-typedef struct s_DrvRlmtMbuf SK_MBUF;
-
-#define	SK_CONST64	INT64_C
-#define	SK_CONSTU64	UINT64_C
-
-#define SK_MEMCPY(dest,src,size)	memcpy(dest,src,size)
-#define SK_MEMCMP(s1,s2,size)		memcmp(s1,s2,size)
-#define SK_MEMSET(dest,val,size)	memset(dest,val,size)
-#define SK_STRLEN(pStr)			strlen((char*)(pStr))
-#define SK_STRNCPY(pDest,pSrc,size)	strncpy((char*)(pDest),(char*)(pSrc),size)
-#define SK_STRCMP(pStr1,pStr2)		strcmp((char*)(pStr1),(char*)(pStr2))
-
-/* macros to access the adapter */
-#define SK_OUT8(b,a,v)		writeb((v), ((b)+(a)))	
-#define SK_OUT16(b,a,v)		writew((v), ((b)+(a)))	
-#define SK_OUT32(b,a,v)		writel((v), ((b)+(a)))	
-#define SK_IN8(b,a,pv)		(*(pv) = readb((b)+(a)))
-#define SK_IN16(b,a,pv)		(*(pv) = readw((b)+(a)))
-#define SK_IN32(b,a,pv)		(*(pv) = readl((b)+(a)))
-
-#define int8_t		char
-#define int16_t		short
-#define int32_t		long
-#define int64_t		long long
-#define uint8_t		u_char
-#define uint16_t	u_short
-#define uint32_t	u_long
-#define uint64_t	unsigned long long
-#define t_scalar_t	int
-#define t_uscalar_t	unsigned int
-#define uintptr_t	unsigned long
-
-#define __CONCAT__(A,B) A##B
-
-#define INT32_C(a)		__CONCAT__(a,L)
-#define INT64_C(a)		__CONCAT__(a,LL)
-#define UINT32_C(a)		__CONCAT__(a,UL)
-#define UINT64_C(a)		__CONCAT__(a,ULL)
-
-#ifdef DEBUG
-#define SK_DBG_PRINTF		printk
-#ifndef SK_DEBUG_CHKMOD
-#define SK_DEBUG_CHKMOD		0
-#endif
-#ifndef SK_DEBUG_CHKCAT
-#define SK_DEBUG_CHKCAT		0
-#endif
-/* those come from the makefile */
-#define SK_DBG_CHKMOD(pAC)	(SK_DEBUG_CHKMOD)
-#define SK_DBG_CHKCAT(pAC)	(SK_DEBUG_CHKCAT)
-
-extern void SkDbgPrintf(const char *format,...);
-
-#define SK_DBGMOD_DRV			0x00010000
-
-/**** possible driver debug categories ********************************/
-#define SK_DBGCAT_DRV_ENTRY		0x00010000
-#define SK_DBGCAT_DRV_SAP		0x00020000
-#define SK_DBGCAT_DRV_MCA		0x00040000
-#define SK_DBGCAT_DRV_TX_PROGRESS	0x00080000
-#define SK_DBGCAT_DRV_RX_PROGRESS	0x00100000
-#define SK_DBGCAT_DRV_PROGRESS		0x00200000
-#define SK_DBGCAT_DRV_MSG		0x00400000
-#define SK_DBGCAT_DRV_PROM		0x00800000
-#define SK_DBGCAT_DRV_TX_FRAME		0x01000000
-#define SK_DBGCAT_DRV_ERROR		0x02000000
-#define SK_DBGCAT_DRV_INT_SRC		0x04000000
-#define SK_DBGCAT_DRV_EVENT		0x08000000
-
-#endif
-
-#define SK_ERR_LOG		SkErrorLog
-
-extern void SkErrorLog(SK_AC*, int, int, char*);
-
-#endif
-
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
deleted file mode 100644
index 3fa6717..0000000
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ /dev/null
@@ -1,447 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdrv2nd.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/12/11 16:04:45 $
- * Purpose:	Second header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the second include file of the driver, which includes all other
- * neccessary files and defines all structures and constants used by the
- * driver and the common modules.
- *
- * Include File Hierarchy:
- *
- *	see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV2ND_H
-#define __INC_SKDRV2ND_H
-
-#include "h/skqueue.h"
-#include "h/skgehwt.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skgepnmi.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skaddr.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skrlmt.h"
-#include "h/skgedrv.h"
-
-
-extern SK_MBUF		*SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
-extern void		SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
-extern SK_U64		SkOsGetTime(SK_AC*);
-extern int		SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
-extern int		SkPciReadCfgWord(SK_AC*, int, SK_U16*);
-extern int		SkPciReadCfgByte(SK_AC*, int, SK_U8*);
-extern int		SkPciWriteCfgWord(SK_AC*, int, SK_U16);
-extern int		SkPciWriteCfgByte(SK_AC*, int, SK_U8);
-extern int		SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
-
-#ifdef SK_DIAG_SUPPORT
-extern int		SkDrvEnterDiagMode(SK_AC *pAc);
-extern int		SkDrvLeaveDiagMode(SK_AC *pAc);
-#endif
-
-struct s_DrvRlmtMbuf {
-	SK_MBUF		*pNext;		/* Pointer to next RLMT Mbuf. */
-	SK_U8		*pData;		/* Data buffer (virtually contig.). */
-	unsigned	Size;		/* Data buffer size. */
-	unsigned	Length;		/* Length of packet (<= Size). */
-	SK_U32		PortIdx;	/* Receiving/transmitting port. */
-#ifdef SK_RLMT_MBUF_PRIVATE
-	SK_RLMT_MBUF	Rlmt;		/* Private part for RLMT. */
-#endif  /* SK_RLMT_MBUF_PRIVATE */
-	struct sk_buff	*pOs;		/* Pointer to message block */
-};
-
-
-/*
- * Time macros
- */
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t)	(t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t)	((((unsigned long)t) * 100) / \
-										(SK_TICKS_PER_SEC))
-#endif
-
-/*
- * New SkOsGetTime
- */
-#define SkOsGetTimeCurrent(pAC, pUsec) {\
-	struct timeval t;\
-	do_gettimeofday(&t);\
-	*pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\
-}
-
-
-/*
- * ioctl definitions
- */
-#define		SK_IOCTL_BASE		(SIOCDEVPRIVATE)
-#define		SK_IOCTL_GETMIB		(SK_IOCTL_BASE + 0)
-#define		SK_IOCTL_SETMIB		(SK_IOCTL_BASE + 1)
-#define		SK_IOCTL_PRESETMIB	(SK_IOCTL_BASE + 2)
-#define		SK_IOCTL_GEN		(SK_IOCTL_BASE + 3)
-#define		SK_IOCTL_DIAG		(SK_IOCTL_BASE + 4)
-
-typedef struct s_IOCTL	SK_GE_IOCTL;
-
-struct s_IOCTL {
-	char __user *	pData;
-	unsigned int	Len;
-};
-
-
-/*
- * define sizes of descriptor rings in bytes
- */
-
-#define		TX_RING_SIZE	(8*1024)
-#define		RX_RING_SIZE	(24*1024)
-
-/*
- * Buffer size for ethernet packets
- */
-#define	ETH_BUF_SIZE	1540
-#define	ETH_MAX_MTU	1514
-#define ETH_MIN_MTU	60
-#define ETH_MULTICAST_BIT	0x01
-#define SK_JUMBO_MTU	9000
-
-/*
- * transmit priority selects the queue: LOW=asynchron, HIGH=synchron
- */
-#define TX_PRIO_LOW	0
-#define TX_PRIO_HIGH	1
-
-/*
- * alignment of rx/tx descriptors
- */
-#define DESCR_ALIGN	64
-
-/*
- * definitions for pnmi. TODO
- */
-#define SK_DRIVER_RESET(pAC, IoC)	0
-#define SK_DRIVER_SENDEVENT(pAC, IoC)	0
-#define SK_DRIVER_SELFTEST(pAC, IoC)	0
-/* For get mtu you must add an own function */
-#define SK_DRIVER_GET_MTU(pAc,IoC,i)	0
-#define SK_DRIVER_SET_MTU(pAc,IoC,i,v)	0
-#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v)	0
-
-/*
-** Interim definition of SK_DRV_TIMER placed in this file until 
-** common modules have been finalized
-*/
-#define SK_DRV_TIMER			11 
-#define	SK_DRV_MODERATION_TIMER		1
-#define SK_DRV_MODERATION_TIMER_LENGTH  1000000  /* 1 second */
-#define SK_DRV_RX_CLEANUP_TIMER		2
-#define SK_DRV_RX_CLEANUP_TIMER_LENGTH	1000000	 /* 100 millisecs */
-
-/*
-** Definitions regarding transmitting frames 
-** any calculating any checksum.
-*/
-#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
-#define C_LEN_ETHERMAC_HEADER_SRC_ADDR  6
-#define C_LEN_ETHERMAC_HEADER_LENTYPE   2
-#define C_LEN_ETHERMAC_HEADER           ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \
-                                          (C_LEN_ETHERMAC_HEADER_SRC_ADDR)  + \
-                                          (C_LEN_ETHERMAC_HEADER_LENTYPE) )
-
-#define C_LEN_ETHERMTU_MINSIZE          46
-#define C_LEN_ETHERMTU_MAXSIZE_STD      1500
-#define C_LEN_ETHERMTU_MAXSIZE_JUMBO    9000
-
-#define C_LEN_ETHERNET_MINSIZE          ( (C_LEN_ETHERMAC_HEADER) + \
-                                          (C_LEN_ETHERMTU_MINSIZE) )
-
-#define C_OFFSET_IPHEADER               C_LEN_ETHERMAC_HEADER
-#define C_OFFSET_IPHEADER_IPPROTO       9
-#define C_OFFSET_TCPHEADER_TCPCS        16
-#define C_OFFSET_UDPHEADER_UDPCS        6
-
-#define C_OFFSET_IPPROTO                ( (C_LEN_ETHERMAC_HEADER) + \
-                                          (C_OFFSET_IPHEADER_IPPROTO) )
-
-#define C_PROTO_ID_UDP                  17       /* refer to RFC 790 or Stevens'   */
-#define C_PROTO_ID_TCP                  6        /* TCP/IP illustrated for details */
-
-/* TX and RX descriptors *****************************************************/
-
-typedef struct s_RxD RXD; /* the receive descriptor */
-
-struct s_RxD {
-	volatile SK_U32	RBControl;	/* Receive Buffer Control */
-	SK_U32		VNextRxd;	/* Next receive descriptor,low dword */
-	SK_U32		VDataLow;	/* Receive buffer Addr, low dword */
-	SK_U32		VDataHigh;	/* Receive buffer Addr, high dword */
-	SK_U32		FrameStat;	/* Receive Frame Status word */
-	SK_U32		TimeStamp;	/* Time stamp from XMAC */
-	SK_U32		TcpSums;	/* TCP Sum 2 / TCP Sum 1 */
-	SK_U32		TcpSumStarts;	/* TCP Sum Start 2 / TCP Sum Start 1 */
-	RXD		*pNextRxd;	/* Pointer to next Rxd */
-	struct sk_buff	*pMBuf;		/* Pointer to Linux' socket buffer */
-};
-
-typedef struct s_TxD TXD; /* the transmit descriptor */
-
-struct s_TxD {
-	volatile SK_U32	TBControl;	/* Transmit Buffer Control */
-	SK_U32		VNextTxd;	/* Next transmit descriptor,low dword */
-	SK_U32		VDataLow;	/* Transmit Buffer Addr, low dword */
-	SK_U32		VDataHigh;	/* Transmit Buffer Addr, high dword */
-	SK_U32		FrameStat;	/* Transmit Frame Status Word */
-	SK_U32		TcpSumOfs;	/* Reserved / TCP Sum Offset */
-	SK_U16		TcpSumSt;	/* TCP Sum Start */
-	SK_U16		TcpSumWr;	/* TCP Sum Write */
-	SK_U32		TcpReserved;	/* not used */
-	TXD		*pNextTxd;	/* Pointer to next Txd */
-	struct sk_buff	*pMBuf;		/* Pointer to Linux' socket buffer */
-};
-
-/* Used interrupt bits in the interrupts source register *********************/
-
-#define DRIVER_IRQS	((IS_IRQ_SW)   | \
-			(IS_R1_F)      |(IS_R2_F)  | \
-			(IS_XS1_F)     |(IS_XA1_F) | \
-			(IS_XS2_F)     |(IS_XA2_F))
-
-#define SPECIAL_IRQS	((IS_HW_ERR)   |(IS_I2C_READY)  | \
-			(IS_EXT_REG)   |(IS_TIMINT)     | \
-			(IS_PA_TO_RX1) |(IS_PA_TO_RX2)  | \
-			(IS_PA_TO_TX1) |(IS_PA_TO_TX2)  | \
-			(IS_MAC1)      |(IS_LNK_SYNC_M1)| \
-			(IS_MAC2)      |(IS_LNK_SYNC_M2)| \
-			(IS_R1_C)      |(IS_R2_C)       | \
-			(IS_XS1_C)     |(IS_XA1_C)      | \
-			(IS_XS2_C)     |(IS_XA2_C))
-
-#define IRQ_MASK	((IS_IRQ_SW)   | \
-			(IS_R1_B)      |(IS_R1_F)     |(IS_R2_B) |(IS_R2_F) | \
-			(IS_XS1_B)     |(IS_XS1_F)    |(IS_XA1_B)|(IS_XA1_F)| \
-			(IS_XS2_B)     |(IS_XS2_F)    |(IS_XA2_B)|(IS_XA2_F)| \
-			(IS_HW_ERR)    |(IS_I2C_READY)| \
-			(IS_EXT_REG)   |(IS_TIMINT)   | \
-			(IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
-			(IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
-			(IS_MAC1)      |(IS_MAC2)     | \
-			(IS_R1_C)      |(IS_R2_C)     | \
-			(IS_XS1_C)     |(IS_XA1_C)    | \
-			(IS_XS2_C)     |(IS_XA2_C))
-
-#define IRQ_HWE_MASK	(IS_ERR_MSK) /* enable all HW irqs */
-
-typedef struct s_DevNet DEV_NET;
-
-struct s_DevNet {
-	int             PortNr;
-	int             NetNr;
-	SK_AC   *pAC;
-};  
-
-typedef struct s_TxPort		TX_PORT;
-
-struct s_TxPort {
-	/* the transmit descriptor rings */
-	caddr_t		pTxDescrRing;	/* descriptor area memory */
-	SK_U64		VTxDescrRing;	/* descr. area bus virt. addr. */
-	TXD		*pTxdRingHead;	/* Head of Tx rings */
-	TXD		*pTxdRingTail;	/* Tail of Tx rings */
-	TXD		*pTxdRingPrev;	/* descriptor sent previously */
-	int		TxdRingFree;	/* # of free entrys */
-	spinlock_t	TxDesRingLock;	/* serialize descriptor accesses */
-	SK_IOC		HwAddr;		/* bmu registers address */
-	int		PortIndex;	/* index number of port (0 or 1) */
-};
-
-typedef struct s_RxPort		RX_PORT;
-
-struct s_RxPort {
-	/* the receive descriptor rings */
-	caddr_t		pRxDescrRing;	/* descriptor area memory */
-	SK_U64		VRxDescrRing;   /* descr. area bus virt. addr. */
-	RXD		*pRxdRingHead;	/* Head of Rx rings */
-	RXD		*pRxdRingTail;	/* Tail of Rx rings */
-	RXD		*pRxdRingPrev;	/* descriptor given to BMU previously */
-	int		RxdRingFree;	/* # of free entrys */
-	int		RxCsum;		/* use receive checksum hardware */
-	spinlock_t	RxDesRingLock;	/* serialize descriptor accesses */
-	int		RxFillLimit;	/* limit for buffers in ring */
-	SK_IOC		HwAddr;		/* bmu registers address */
-	int		PortIndex;	/* index number of port (0 or 1) */
-};
-
-/* Definitions needed for interrupt moderation *******************************/
-
-#define IRQ_EOF_AS_TX     ((IS_XA1_F)     | (IS_XA2_F))
-#define IRQ_EOF_SY_TX     ((IS_XS1_F)     | (IS_XS2_F))
-#define IRQ_MASK_TX_ONLY  ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX))
-#define IRQ_MASK_RX_ONLY  ((IS_R1_F)      | (IS_R2_F))
-#define IRQ_MASK_SP_ONLY  (SPECIAL_IRQS)
-#define IRQ_MASK_TX_RX    ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_RX    ((SPECIAL_IRQS)    | (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_TX    ((SPECIAL_IRQS)    | (IRQ_MASK_TX_ONLY))
-#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS)    | (IRQ_MASK_TX_RX))
-
-#define C_INT_MOD_NONE                 1
-#define C_INT_MOD_STATIC               2
-#define C_INT_MOD_DYNAMIC              4
-
-#define C_CLK_FREQ_GENESIS      53215000 /* shorter: 53.125 MHz  */
-#define C_CLK_FREQ_YUKON        78215000 /* shorter: 78.125 MHz  */
-
-#define C_INTS_PER_SEC_DEFAULT      2000 
-#define C_INT_MOD_ENABLE_PERCENTAGE   50 /* if higher 50% enable */
-#define C_INT_MOD_DISABLE_PERCENTAGE  50 /* if lower 50% disable */
-#define C_INT_MOD_IPS_LOWER_RANGE     30
-#define C_INT_MOD_IPS_UPPER_RANGE     40000
-
-
-typedef struct s_DynIrqModInfo  DIM_INFO;
-struct s_DynIrqModInfo {
-	unsigned long   PrevTimeVal;
-	unsigned int    PrevSysLoad;
-	unsigned int    PrevUsedTime;
-	unsigned int    PrevTotalTime;
-	int             PrevUsedDescrRatio;
-	int             NbrProcessedDescr;
-        SK_U64          PrevPort0RxIntrCts;
-        SK_U64          PrevPort1RxIntrCts;
-        SK_U64          PrevPort0TxIntrCts;
-        SK_U64          PrevPort1TxIntrCts;
-	SK_BOOL         ModJustEnabled;     /* Moderation just enabled yes/no */
-
-	int             MaxModIntsPerSec;            /* Moderation Threshold */
-	int             MaxModIntsPerSecUpperLimit;  /* Upper limit for DIM  */
-	int             MaxModIntsPerSecLowerLimit;  /* Lower limit for DIM  */
-
-	long            MaskIrqModeration;   /* ModIrqType (eg. 'TxRx')      */
-	SK_BOOL         DisplayStats;        /* Stats yes/no                 */
-	SK_BOOL         AutoSizing;          /* Resize DIM-timer on/off      */
-	int             IntModTypeSelect;    /* EnableIntMod (eg. 'dynamic') */
-
-	SK_TIMER        ModTimer; /* just some timer */
-};
-
-typedef struct s_PerStrm	PER_STRM;
-
-#define SK_ALLOC_IRQ	0x00000001
-
-#ifdef SK_DIAG_SUPPORT
-#define	DIAG_ACTIVE		1
-#define	DIAG_NOTACTIVE		0
-#endif
-
-/****************************************************************************
- * Per board structure / Adapter Context structure:
- *	Allocated within attach(9e) and freed within detach(9e).
- *	Contains all 'per device' necessary handles, flags, locks etc.:
- */
-struct s_AC  {
-	SK_GEINIT	GIni;		/* GE init struct */
-	SK_PNMI		Pnmi;		/* PNMI data struct */
-	SK_VPD		vpd;		/* vpd data struct */
-	SK_QUEUE	Event;		/* Event queue */
-	SK_HWT		Hwt;		/* Hardware Timer control struct */
-	SK_TIMCTRL	Tim;		/* Software Timer control struct */
-	SK_I2C		I2c;		/* I2C relevant data structure */
-	SK_ADDR		Addr;		/* for Address module */
-	SK_CSUM		Csum;		/* for checksum module */
-	SK_RLMT		Rlmt;		/* for rlmt module */
-	spinlock_t	SlowPathLock;	/* Normal IRQ lock */
-	struct timer_list BlinkTimer;	/* for LED blinking */
-	int		LedsOn;
-	SK_PNMI_STRUCT_DATA PnmiStruct;	/* structure to get all Pnmi-Data */
-	int			RlmtMode;	/* link check mode to set */
-	int			RlmtNets;	/* Number of nets */
-	
-	SK_IOC		IoBase;		/* register set of adapter */
-	int		BoardLevel;	/* level of active hw init (0-2) */
-
-	SK_U32		AllocFlag;	/* flag allocation of resources */
-	struct pci_dev	*PciDev;	/* for access to pci config space */
-	struct SK_NET_DEVICE	*dev[2];	/* pointer to device struct */
-
-	int		RxBufSize;	/* length of receive buffers */
-        struct net_device_stats stats;	/* linux 'netstat -i' statistics */
-	int		Index;		/* internal board index number */
-
-	/* adapter RAM sizes for queues of active port */
-	int		RxQueueSize;	/* memory used for receive queue */
-	int		TxSQueueSize;	/* memory used for sync. tx queue */
-	int		TxAQueueSize;	/* memory used for async. tx queue */
-
-	int		PromiscCount;	/* promiscuous mode counter  */
-	int		AllMultiCount;  /* allmulticast mode counter */
-	int		MulticCount;	/* number of different MC    */
-					/*  addresses for this board */
-					/*  (may be more than HW can)*/
-
-	int		HWRevision;	/* Hardware revision */
-	int		ActivePort;	/* the active XMAC port */
-	int		MaxPorts;		/* number of activated ports */
-	int		TxDescrPerRing;	/* # of descriptors per tx ring */
-	int		RxDescrPerRing;	/* # of descriptors per rx ring */
-
-	caddr_t		pDescrMem;	/* Pointer to the descriptor area */
-	dma_addr_t	pDescrMemDMA;	/* PCI DMA address of area */
-
-	/* the port structures with descriptor rings */
-	TX_PORT		TxPort[SK_MAX_MACS][2];
-	RX_PORT		RxPort[SK_MAX_MACS];
-
-	SK_BOOL		CheckQueue;	/* check event queue soon */
-	SK_TIMER        DrvCleanupTimer;/* to check for pending descriptors */
-	DIM_INFO        DynIrqModInfo;  /* all data related to DIM */
-
-	/* Only for tests */
-	int		PortDown;
-	int		ChipsetType;	/*  Chipset family type 
-					 *  0 == Genesis family support
-					 *  1 == Yukon family support
-					 */
-#ifdef SK_DIAG_SUPPORT
-	SK_U32		DiagModeActive;		/* is diag active?	*/
-	SK_BOOL		DiagFlowCtrl;		/* for control purposes	*/
-	SK_PNMI_STRUCT_DATA PnmiBackup;		/* backup structure for all Pnmi-Data */
-	SK_BOOL         WasIfUp[SK_MAX_MACS];   /* for OpenClose while 
-						 * DIAG is busy with NIC 
-						 */
-#endif
-
-};
-
-
-#endif /* __INC_SKDRV2ND_H */
-
diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
deleted file mode 100644
index da062f7..0000000
--- a/drivers/net/sk98lin/h/skerror.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/******************************************************************************
- *
- * Name:	skerror.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.7 $
- * Date:	$Date: 2003/05/13 17:25:13 $
- * Purpose:	SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKERROR_H_
-#define _INC_SKERROR_H_
-
-/*
- * Define Error Classes
- */
-#define	SK_ERRCL_OTHER		(0)		/* Other error */
-#define	SK_ERRCL_CONFIG		(1L<<0)	/* Configuration error */
-#define	SK_ERRCL_INIT		(1L<<1)	/* Initialization error */
-#define	SK_ERRCL_NORES		(1L<<2)	/* Out of Resources error */
-#define	SK_ERRCL_SW			(1L<<3)	/* Internal Software error */
-#define	SK_ERRCL_HW			(1L<<4)	/* Hardware Failure */
-#define	SK_ERRCL_COMM		(1L<<5)	/* Communication error */
-
-
-/*
- * Define Error Code Bases
- */
-#define	SK_ERRBASE_RLMT		 100	/* Base Error number for RLMT */
-#define	SK_ERRBASE_HWINIT	 200	/* Base Error number for HWInit */
-#define	SK_ERRBASE_VPD		 300	/* Base Error number for VPD */
-#define	SK_ERRBASE_PNMI		 400	/* Base Error number for PNMI */
-#define	SK_ERRBASE_CSUM		 500	/* Base Error number for Checksum */
-#define	SK_ERRBASE_SIRQ		 600	/* Base Error number for Special IRQ */
-#define	SK_ERRBASE_I2C		 700	/* Base Error number for I2C module */
-#define	SK_ERRBASE_QUEUE	 800	/* Base Error number for Scheduler */
-#define	SK_ERRBASE_ADDR		 900	/* Base Error number for Address module */
-#define SK_ERRBASE_PECP		1000    /* Base Error number for PECP */
-#define	SK_ERRBASE_DRV		1100	/* Base Error number for Driver */
-
-#endif	/* _INC_SKERROR_H_ */
diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
deleted file mode 100644
index 44fd4c3..0000000
--- a/drivers/net/sk98lin/h/skgedrv.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgedrv.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/07/04 12:25:01 $
- * Purpose:	Interface with the driver
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEDRV_H_
-#define __INC_SKGEDRV_H_
-
-/* defines ********************************************************************/
-
-/*
- * Define the driver events.
- * Usually the events are defined by the destination module.
- * In case of the driver we put the definition of the events here.
- */
-#define SK_DRV_PORT_RESET		 1	/* The port needs to be reset */
-#define SK_DRV_NET_UP   		 2	/* The net is operational */
-#define SK_DRV_NET_DOWN			 3	/* The net is down */
-#define SK_DRV_SWITCH_SOFT		 4	/* Ports switch with both links connected */
-#define SK_DRV_SWITCH_HARD		 5	/* Port switch due to link failure */
-#define SK_DRV_RLMT_SEND		 6	/* Send a RLMT packet */
-#define SK_DRV_ADAP_FAIL		 7	/* The whole adapter fails */
-#define SK_DRV_PORT_FAIL		 8	/* One port fails */
-#define SK_DRV_SWITCH_INTERN	 9	/* Port switch by the driver itself */
-#define SK_DRV_POWER_DOWN		10	/* Power down mode */
-#define SK_DRV_TIMER			11	/* Timer for free use */
-#ifdef SK_NO_RLMT
-#define SK_DRV_LINK_UP  		12	/* Link Up event for driver */
-#define SK_DRV_LINK_DOWN		13	/* Link Down event for driver */
-#endif
-#define SK_DRV_DOWNSHIFT_DET	14	/* Downshift 4-Pair / 2-Pair (YUKON only) */
-#endif /* __INC_SKGEDRV_H_ */
diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
deleted file mode 100644
index f6282b7..0000000
--- a/drivers/net/sk98lin/h/skgehw.h
+++ /dev/null
@@ -1,2126 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgehw.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.56 $
- * Date:	$Date: 2003/09/23 09:01:00 $
- * Purpose:	Defines and Macros for the Gigabit Ethernet Adapter Product Family
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEHW_H
-#define __INC_SKGEHW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define BIT_31		(1UL << 31)
-#define BIT_30		(1L << 30)
-#define BIT_29		(1L << 29)
-#define BIT_28		(1L << 28)
-#define BIT_27		(1L << 27)
-#define BIT_26		(1L << 26)
-#define BIT_25		(1L << 25)
-#define BIT_24		(1L << 24)
-#define BIT_23		(1L << 23)
-#define BIT_22		(1L << 22)
-#define BIT_21		(1L << 21)
-#define BIT_20		(1L << 20)
-#define BIT_19		(1L << 19)
-#define BIT_18		(1L << 18)
-#define BIT_17		(1L << 17)
-#define BIT_16		(1L << 16)
-#define BIT_15		(1L << 15)
-#define BIT_14		(1L << 14)
-#define BIT_13		(1L << 13)
-#define BIT_12		(1L << 12)
-#define BIT_11		(1L << 11)
-#define BIT_10		(1L << 10)
-#define BIT_9		(1L << 9)
-#define BIT_8		(1L << 8)
-#define BIT_7		(1L << 7)
-#define BIT_6		(1L << 6)
-#define BIT_5		(1L << 5)
-#define BIT_4		(1L << 4)
-#define BIT_3		(1L << 3)
-#define BIT_2		(1L << 2)
-#define BIT_1		(1L << 1)
-#define BIT_0		1L
-
-#define BIT_15S		(1U << 15)
-#define BIT_14S		(1 << 14)
-#define BIT_13S		(1 << 13)
-#define BIT_12S		(1 << 12)
-#define BIT_11S		(1 << 11)
-#define BIT_10S		(1 << 10)
-#define BIT_9S		(1 << 9)
-#define BIT_8S		(1 << 8)
-#define BIT_7S 		(1 << 7)
-#define BIT_6S		(1 << 6)
-#define BIT_5S		(1 << 5)
-#define BIT_4S		(1 << 4)
-#define BIT_3S		(1 << 3)
-#define BIT_2S		(1 << 2)
-#define BIT_1S		(1 << 1)
-#define BIT_0S		1
-
-#define SHIFT31(x)	((x) << 31)
-#define SHIFT30(x)	((x) << 30)
-#define SHIFT29(x)	((x) << 29)
-#define SHIFT28(x)	((x) << 28)
-#define SHIFT27(x)	((x) << 27)
-#define SHIFT26(x)	((x) << 26)
-#define SHIFT25(x)	((x) << 25)
-#define SHIFT24(x)	((x) << 24)
-#define SHIFT23(x)	((x) << 23)
-#define SHIFT22(x)	((x) << 22)
-#define SHIFT21(x)	((x) << 21)
-#define SHIFT20(x)	((x) << 20)
-#define SHIFT19(x)	((x) << 19)
-#define SHIFT18(x)	((x) << 18)
-#define SHIFT17(x)	((x) << 17)
-#define SHIFT16(x)	((x) << 16)
-#define SHIFT15(x)	((x) << 15)
-#define SHIFT14(x)	((x) << 14)
-#define SHIFT13(x)	((x) << 13)
-#define SHIFT12(x)	((x) << 12)
-#define SHIFT11(x)	((x) << 11)
-#define SHIFT10(x)	((x) << 10)
-#define SHIFT9(x)	((x) << 9)
-#define SHIFT8(x)	((x) << 8)
-#define SHIFT7(x)	((x) << 7)
-#define SHIFT6(x)	((x) << 6)
-#define SHIFT5(x)	((x) << 5)
-#define SHIFT4(x)	((x) << 4)
-#define SHIFT3(x)	((x) << 3)
-#define SHIFT2(x)	((x) << 2)
-#define SHIFT1(x)	((x) << 1)
-#define SHIFT0(x)	((x) << 0)
-
-/*
- * Configuration Space header
- * Since this module is used for different OS', those may be
- * duplicate on some of them (e.g. Linux). But to keep the
- * common source, we have to live with this...
- */
-#define PCI_VENDOR_ID	0x00	/* 16 bit	Vendor ID */
-#define PCI_DEVICE_ID	0x02	/* 16 bit	Device ID */
-#define PCI_COMMAND		0x04	/* 16 bit	Command */
-#define PCI_STATUS		0x06	/* 16 bit	Status */
-#define PCI_REV_ID		0x08	/*  8 bit	Revision ID */
-#define PCI_CLASS_CODE	0x09	/* 24 bit	Class Code */
-#define PCI_CACHE_LSZ	0x0c	/*  8 bit	Cache Line Size */
-#define PCI_LAT_TIM		0x0d	/*  8 bit	Latency Timer */
-#define PCI_HEADER_T	0x0e	/*  8 bit	Header Type */
-#define PCI_BIST		0x0f	/*  8 bit	Built-in selftest */
-#define PCI_BASE_1ST	0x10	/* 32 bit	1st Base address */
-#define PCI_BASE_2ND	0x14	/* 32 bit	2nd Base address */
-	/* Byte 0x18..0x2b:	reserved */
-#define PCI_SUB_VID		0x2c	/* 16 bit	Subsystem Vendor ID */
-#define PCI_SUB_ID		0x2e	/* 16 bit	Subsystem ID */
-#define PCI_BASE_ROM	0x30	/* 32 bit	Expansion ROM Base Address */
-#define PCI_CAP_PTR		0x34	/*  8 bit 	Capabilities Ptr */
-	/* Byte 0x35..0x3b:	reserved */
-#define PCI_IRQ_LINE	0x3c	/*  8 bit	Interrupt Line */
-#define PCI_IRQ_PIN		0x3d	/*  8 bit	Interrupt Pin */
-#define PCI_MIN_GNT		0x3e	/*  8 bit	Min_Gnt */
-#define PCI_MAX_LAT		0x3f	/*  8 bit	Max_Lat */
-	/* Device Dependent Region */
-#define PCI_OUR_REG_1	0x40	/* 32 bit 	Our Register 1 */
-#define PCI_OUR_REG_2	0x44	/* 32 bit 	Our Register 2 */
-	/* Power Management Region */
-#define PCI_PM_CAP_ID	0x48	/*  8 bit 	Power Management Cap. ID */
-#define PCI_PM_NITEM	0x49	/*  8 bit 	Next Item Ptr */
-#define PCI_PM_CAP_REG	0x4a	/* 16 bit 	Power Management Capabilities */
-#define PCI_PM_CTL_STS	0x4c	/* 16 bit 	Power Manag. Control/Status */
-	/* Byte 0x4e:	reserved */
-#define PCI_PM_DAT_REG	0x4f	/*  8 bit 	Power Manag. Data Register */
-	/* VPD Region */
-#define PCI_VPD_CAP_ID	0x50	/*  8 bit 	VPD Cap. ID */
-#define PCI_VPD_NITEM	0x51	/*  8 bit 	Next Item Ptr */
-#define PCI_VPD_ADR_REG	0x52	/* 16 bit 	VPD Address Register */
-#define PCI_VPD_DAT_REG	0x54	/* 32 bit 	VPD Data Register */
-	/* Byte 0x58..0x59:	reserved */
-#define PCI_SER_LD_CTRL	0x5a	/* 16 bit 	SEEPROM Loader Ctrl (YUKON only) */
-	/* Byte 0x5c..0xff:	reserved */
-
-/*
- * I2C Address (PCI Config)
- *
- * Note: The temperature and voltage sensors are relocated on a different
- *	 I2C bus.
- */
-#define I2C_ADDR_VPD	0xa0	/* I2C address for the VPD EEPROM */
-
-/*
- * Define Bits and Values of the registers
- */
-/*	PCI_COMMAND	16 bit	Command */
-								/* Bit 15..11:	reserved */
-#define PCI_INT_DIS		BIT_10S		/* Interrupt INTx# disable (PCI 2.3) */
-#define PCI_FBTEN		BIT_9S		/* Fast Back-To-Back enable */
-#define PCI_SERREN		BIT_8S		/* SERR enable */
-#define PCI_ADSTEP		BIT_7S		/* Address Stepping */
-#define PCI_PERREN		BIT_6S		/* Parity Report Response enable */
-#define PCI_VGA_SNOOP	BIT_5S		/* VGA palette snoop */
-#define PCI_MWIEN		BIT_4S		/* Memory write an inv cycl ena */
-#define PCI_SCYCEN		BIT_3S		/* Special Cycle enable */
-#define PCI_BMEN		BIT_2S		/* Bus Master enable */
-#define PCI_MEMEN		BIT_1S		/* Memory Space Access enable */
-#define PCI_IOEN		BIT_0S		/* I/O Space Access enable */
-
-#define PCI_COMMAND_VAL	(PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\
-						 PCI_BMEN | PCI_MEMEN | PCI_IOEN)
-
-/*	PCI_STATUS	16 bit	Status */
-#define PCI_PERR		BIT_15S		/* Parity Error */
-#define PCI_SERR		BIT_14S		/* Signaled SERR */
-#define PCI_RMABORT		BIT_13S		/* Received Master Abort */
-#define PCI_RTABORT		BIT_12S		/* Received Target Abort */
-								/* Bit 11:	reserved */
-#define PCI_DEVSEL		(3<<9)		/* Bit 10.. 9:	DEVSEL Timing */
-#define PCI_DEV_FAST	(0<<9)		/*		fast */
-#define PCI_DEV_MEDIUM	(1<<9)		/*		medium */
-#define PCI_DEV_SLOW	(2<<9)		/*		slow */
-#define PCI_DATAPERR	BIT_8S		/* DATA Parity error detected */
-#define PCI_FB2BCAP		BIT_7S		/* Fast Back-to-Back Capability */
-#define PCI_UDF			BIT_6S		/* User Defined Features */
-#define PCI_66MHZCAP	BIT_5S		/* 66 MHz PCI bus clock capable */
-#define PCI_NEWCAP		BIT_4S		/* New cap. list implemented */
-#define PCI_INT_STAT	BIT_3S		/* Interrupt INTx# Status (PCI 2.3) */
-								/* Bit  2.. 0:	reserved */
-
-#define PCI_ERRBITS	(PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\
-			PCI_DATAPERR)
-
-/*	PCI_CLASS_CODE	24 bit	Class Code */
-/*	Byte 2:		Base Class		(02) */
-/*	Byte 1:		SubClass		(00) */
-/*	Byte 0:		Programming Interface	(00) */
-
-/*	PCI_CACHE_LSZ	8 bit	Cache Line Size */
-/*	Possible values: 0,2,4,8,16,32,64,128	*/
-
-/*	PCI_HEADER_T	8 bit	Header Type */
-#define PCI_HD_MF_DEV	BIT_7S	/* 0= single, 1= multi-func dev */
-#define PCI_HD_TYPE		0x7f	/* Bit 6..0:	Header Layout 0= normal */
-
-/*	PCI_BIST	8 bit	Built-in selftest */
-/*	Built-in Self test not supported (optional) */
-
-/*	PCI_BASE_1ST	32 bit	1st Base address */
-#define PCI_MEMSIZE		0x4000L		/* use 16 kB Memory Base */
-#define PCI_MEMBASE_MSK 0xffffc000L	/* Bit 31..14:	Memory Base Address */
-#define PCI_MEMSIZE_MSK 0x00003ff0L	/* Bit 13.. 4:	Memory Size Req. */
-#define PCI_PREFEN		BIT_3		/* Prefetchable */
-#define PCI_MEM_TYP		(3L<<2)		/* Bit	2.. 1:	Memory Type */
-#define PCI_MEM32BIT	(0L<<1)		/* Base addr anywhere in 32 Bit range */
-#define PCI_MEM1M		(1L<<1)		/* Base addr below 1 MegaByte */
-#define PCI_MEM64BIT	(2L<<1)		/* Base addr anywhere in 64 Bit range */
-#define PCI_MEMSPACE	BIT_0		/* Memory Space Indicator */
-
-/*	PCI_BASE_2ND	32 bit	2nd Base address */
-#define PCI_IOBASE		0xffffff00L	/* Bit 31.. 8:	I/O Base address */
-#define PCI_IOSIZE		0x000000fcL	/* Bit	7.. 2:	I/O Size Requirements */
-									/* Bit	1:	reserved */
-#define PCI_IOSPACE		BIT_0		/* I/O Space Indicator */
-
-/*	PCI_BASE_ROM	32 bit	Expansion ROM Base Address */
-#define PCI_ROMBASE_MSK	0xfffe0000L	/* Bit 31..17:	ROM Base address */
-#define PCI_ROMBASE_SIZ	(0x1cL<<14)	/* Bit 16..14:	Treat as Base or Size */
-#define PCI_ROMSIZE		(0x38L<<11)	/* Bit 13..11:	ROM Size Requirements */
-									/* Bit 10.. 1:	reserved */
-#define PCI_ROMEN		BIT_0		/* Address Decode enable */
-
-/* Device Dependent Region */
-/*	PCI_OUR_REG_1		32 bit	Our Register 1 */
-									/* Bit 31..29:	reserved */
-#define PCI_PHY_COMA	BIT_28		/* Set PHY to Coma Mode (YUKON only) */
-#define PCI_TEST_CAL	BIT_27		/* Test PCI buffer calib. (YUKON only) */
-#define PCI_EN_CAL		BIT_26		/* Enable PCI buffer calib. (YUKON only) */
-#define PCI_VIO			BIT_25		/* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
-#define PCI_DIS_BOOT	BIT_24		/* Disable BOOT via ROM */
-#define PCI_EN_IO		BIT_23		/* Mapping to I/O space */
-#define PCI_EN_FPROM	BIT_22		/* Enable FLASH mapping to memory */
-									/*		1 = Map Flash to memory */
-									/*		0 = Disable addr. dec */
-#define PCI_PAGESIZE	(3L<<20)	/* Bit 21..20:	FLASH Page Size	*/
-#define PCI_PAGE_16		(0L<<20)	/*		16 k pages	*/
-#define PCI_PAGE_32K	(1L<<20)	/*		32 k pages	*/
-#define PCI_PAGE_64K	(2L<<20)	/*		64 k pages	*/
-#define PCI_PAGE_128K	(3L<<20)	/*		128 k pages	*/
-									/* Bit 19:	reserved	*/
-#define PCI_PAGEREG		(7L<<16)	/* Bit 18..16:	Page Register	*/
-#define PCI_NOTAR		BIT_15		/* No turnaround cycle */
-#define PCI_FORCE_BE	BIT_14		/* Assert all BEs on MR */
-#define PCI_DIS_MRL		BIT_13		/* Disable Mem Read Line */
-#define PCI_DIS_MRM		BIT_12		/* Disable Mem Read Multiple */
-#define PCI_DIS_MWI		BIT_11		/* Disable Mem Write & Invalidate */
-#define PCI_DISC_CLS	BIT_10		/* Disc: cacheLsz bound */
-#define PCI_BURST_DIS	BIT_9		/* Burst Disable */
-#define PCI_DIS_PCI_CLK	BIT_8		/* Disable PCI clock driving */
-#define PCI_SKEW_DAS	(0xfL<<4)	/* Bit	7.. 4:	Skew Ctrl, DAS Ext */
-#define PCI_SKEW_BASE	0xfL		/* Bit	3.. 0:	Skew Ctrl, Base	*/
-
-
-/*	PCI_OUR_REG_2		32 bit	Our Register 2 */
-#define PCI_VPD_WR_THR	(0xffL<<24)	/* Bit 31..24:	VPD Write Threshold */
-#define PCI_DEV_SEL		(0x7fL<<17)	/* Bit 23..17:	EEPROM Device Select */
-#define PCI_VPD_ROM_SZ	(7L<<14)	/* Bit 16..14:	VPD ROM Size	*/
-									/* Bit 13..12:	reserved	*/
-#define PCI_PATCH_DIR	(0xfL<<8)	/* Bit 11.. 8:	Ext Patches dir 3..0 */
-#define PCI_PATCH_DIR_3	BIT_11
-#define PCI_PATCH_DIR_2	BIT_10
-#define PCI_PATCH_DIR_1	BIT_9
-#define PCI_PATCH_DIR_0	BIT_8
-#define PCI_EXT_PATCHS	(0xfL<<4)	/* Bit	7.. 4:	Extended Patches 3..0 */
-#define PCI_EXT_PATCH_3	BIT_7
-#define PCI_EXT_PATCH_2	BIT_6
-#define PCI_EXT_PATCH_1	BIT_5
-#define PCI_EXT_PATCH_0	BIT_4
-#define PCI_EN_DUMMY_RD	BIT_3		/* Enable Dummy Read */
-#define PCI_REV_DESC	BIT_2		/* Reverse Desc. Bytes */
-									/* Bit	1:	reserved */
-#define PCI_USEDATA64	BIT_0		/* Use 64Bit Data bus ext */
-
-
-/* Power Management Region */
-/*	PCI_PM_CAP_REG		16 bit	Power Management Capabilities */
-#define PCI_PME_SUP_MSK	(0x1f<<11)	/* Bit 15..11:	PM Event Support Mask */
-#define PCI_PME_D3C_SUP	BIT_15S		/* PME from D3cold Support (if Vaux) */
-#define PCI_PME_D3H_SUP	BIT_14S		/* PME from D3hot Support */
-#define PCI_PME_D2_SUP	BIT_13S		/* PME from D2 Support */
-#define PCI_PME_D1_SUP	BIT_12S		/* PME from D1 Support */
-#define PCI_PME_D0_SUP	BIT_11S		/* PME from D0 Support */
-#define PCI_PM_D2_SUP	BIT_10S		/* D2 Support in 33 MHz mode */
-#define PCI_PM_D1_SUP	BIT_9S		/* D1 Support */
-									/* Bit	8.. 6:	reserved */
-#define PCI_PM_DSI		BIT_5S		/* Device Specific Initialization */
-#define PCI_PM_APS		BIT_4S		/* Auxialiary Power Source */
-#define PCI_PME_CLOCK	BIT_3S		/* PM Event Clock */
-#define PCI_PM_VER_MSK		7		/* Bit	2.. 0:	PM PCI Spec. version */
-
-/*	PCI_PM_CTL_STS		16 bit	Power Management Control/Status */
-#define PCI_PME_STATUS	BIT_15S		/* PME Status (YUKON only) */
-#define PCI_PM_DAT_SCL	(3<<13)		/* Bit 14..13:	Data Reg. scaling factor */
-#define PCI_PM_DAT_SEL	(0xf<<9)	/* Bit 12.. 9:	PM data selector field */
-#define PCI_PME_EN		BIT_8S		/* Enable PME# generation (YUKON only) */
-									/* Bit	7.. 2:	reserved */
-#define PCI_PM_STATE_MSK	3		/* Bit	1.. 0:	Power Management State */
-
-#define PCI_PM_STATE_D0		0		/* D0:	Operational (default) */
-#define PCI_PM_STATE_D1		1		/* D1:	(YUKON only) */
-#define PCI_PM_STATE_D2		2		/* D2:	(YUKON only) */
-#define PCI_PM_STATE_D3 	3		/* D3:	HOT, Power Down and Reset */
-
-/* VPD Region */
-/*	PCI_VPD_ADR_REG		16 bit	VPD Address Register */
-#define PCI_VPD_FLAG	BIT_15S		/* starts VPD rd/wr cycle */
-#define PCI_VPD_ADR_MSK	0x7fffL		/* Bit 14.. 0:	VPD address mask */
-
-/*	Control Register File (Address Map) */
-
-/*
- *	Bank 0
- */
-#define B0_RAP			0x0000	/*  8 bit	Register Address Port */
-	/* 0x0001 - 0x0003:	reserved */
-#define B0_CTST			0x0004	/* 16 bit	Control/Status register */
-#define B0_LED			0x0006	/*  8 Bit	LED register */
-#define B0_POWER_CTRL	0x0007	/*  8 Bit	Power Control reg (YUKON only) */
-#define B0_ISRC			0x0008	/* 32 bit	Interrupt Source Register */
-#define B0_IMSK			0x000c	/* 32 bit	Interrupt Mask Register */
-#define B0_HWE_ISRC		0x0010	/* 32 bit	HW Error Interrupt Src Reg */
-#define B0_HWE_IMSK		0x0014	/* 32 bit	HW Error Interrupt Mask Reg */
-#define B0_SP_ISRC		0x0018	/* 32 bit	Special Interrupt Source Reg */
-	/* 0x001c:		reserved */
-
-/* B0 XMAC 1 registers (GENESIS only) */
-#define B0_XM1_IMSK		0x0020	/* 16 bit r/w	XMAC 1 Interrupt Mask Register*/
-	/* 0x0022 - 0x0027:	reserved */
-#define B0_XM1_ISRC		0x0028	/* 16 bit ro	XMAC 1 Interrupt Status Reg */
-	/* 0x002a - 0x002f:	reserved */
-#define B0_XM1_PHY_ADDR 0x0030	/* 16 bit r/w	XMAC 1 PHY Address Register */
-	/* 0x0032 - 0x0033:	reserved */
-#define B0_XM1_PHY_DATA 0x0034	/* 16 bit r/w	XMAC 1 PHY Data Register */
-	/* 0x0036 - 0x003f:	reserved */
-
-/* B0 XMAC 2 registers (GENESIS only) */
-#define B0_XM2_IMSK		0x0040	/* 16 bit r/w	XMAC 2 Interrupt Mask Register*/
-	/* 0x0042 - 0x0047:	reserved */
-#define B0_XM2_ISRC		0x0048	/* 16 bit ro	XMAC 2 Interrupt Status Reg */
-	/* 0x004a - 0x004f:	reserved */
-#define B0_XM2_PHY_ADDR 0x0050	/* 16 bit r/w	XMAC 2 PHY Address Register */
-	/* 0x0052 - 0x0053:	reserved */
-#define B0_XM2_PHY_DATA 0x0054	/* 16 bit r/w	XMAC 2 PHY Data Register */
-	/* 0x0056 - 0x005f:	reserved */
-
-/* BMU Control Status Registers */
-#define B0_R1_CSR		0x0060	/* 32 bit	BMU Ctrl/Stat Rx Queue 1 */
-#define B0_R2_CSR		0x0064	/* 32 bit	BMU Ctrl/Stat Rx Queue 2 */
-#define B0_XS1_CSR		0x0068	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
-#define B0_XA1_CSR		0x006c	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 1*/
-#define B0_XS2_CSR		0x0070	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
-#define B0_XA2_CSR		0x0074	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 2*/
-	/* 0x0078 - 0x007f:	reserved */
-
-/*
- *	Bank 1
- *	- completely empty (this is the RAP Block window)
- *	Note: if RAP = 1 this page is reserved
- */
-
-/*
- *	Bank 2
- */
-/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */
-#define B2_MAC_1		0x0100	/* NA reg	 MAC Address 1 */
-	/* 0x0106 - 0x0107:	reserved */
-#define B2_MAC_2		0x0108	/* NA reg	 MAC Address 2 */
-	/* 0x010e - 0x010f:	reserved */
-#define B2_MAC_3		0x0110	/* NA reg	 MAC Address 3 */
-	/* 0x0116 - 0x0117:	reserved */
-#define B2_CONN_TYP		0x0118	/*  8 bit	Connector type */
-#define B2_PMD_TYP		0x0119	/*  8 bit	PMD type */
-#define B2_MAC_CFG		0x011a	/*  8 bit	MAC Configuration / Chip Revision */
-#define B2_CHIP_ID		0x011b	/*  8 bit 	Chip Identification Number */
-	/* Eprom registers are currently of no use */
-#define B2_E_0			0x011c	/*  8 bit	EPROM Byte 0 (ext. SRAM size */
-#define B2_E_1			0x011d	/*  8 bit	EPROM Byte 1 (PHY type) */
-#define B2_E_2			0x011e	/*  8 bit	EPROM Byte 2 */
-#define B2_E_3			0x011f	/*  8 bit	EPROM Byte 3 */
-#define B2_FAR			0x0120	/* 32 bit	Flash-Prom Addr Reg/Cnt */
-#define B2_FDP			0x0124	/*  8 bit	Flash-Prom Data Port */
-	/* 0x0125 - 0x0127:	reserved */
-#define B2_LD_CTRL		0x0128	/*  8 bit	EPROM loader control register */
-#define B2_LD_TEST		0x0129	/*  8 bit	EPROM loader test register */
-	/* 0x012a - 0x012f:	reserved */
-#define B2_TI_INI		0x0130	/* 32 bit	Timer Init Value */
-#define B2_TI_VAL		0x0134	/* 32 bit	Timer Value */
-#define B2_TI_CTRL		0x0138	/*  8 bit	Timer Control */
-#define B2_TI_TEST		0x0139	/*  8 Bit	Timer Test */
-	/* 0x013a - 0x013f:	reserved */
-#define B2_IRQM_INI		0x0140	/* 32 bit	IRQ Moderation Timer Init Reg.*/
-#define B2_IRQM_VAL		0x0144	/* 32 bit	IRQ Moderation Timer Value */
-#define B2_IRQM_CTRL	0x0148	/*  8 bit	IRQ Moderation Timer Control */
-#define B2_IRQM_TEST	0x0149	/*  8 bit	IRQ Moderation Timer Test */
-#define B2_IRQM_MSK 	0x014c	/* 32 bit	IRQ Moderation Mask */
-#define B2_IRQM_HWE_MSK 0x0150	/* 32 bit	IRQ Moderation HW Error Mask */
-	/* 0x0154 - 0x0157:	reserved */
-#define B2_TST_CTRL1	0x0158	/*  8 bit	Test Control Register 1 */
-#define B2_TST_CTRL2	0x0159	/*  8 bit	Test Control Register 2 */
-	/* 0x015a - 0x015b:	reserved */
-#define B2_GP_IO		0x015c	/* 32 bit	General Purpose I/O Register */
-#define B2_I2C_CTRL		0x0160	/* 32 bit	I2C HW Control Register */
-#define B2_I2C_DATA		0x0164	/* 32 bit	I2C HW Data Register */
-#define B2_I2C_IRQ		0x0168	/* 32 bit	I2C HW IRQ Register */
-#define B2_I2C_SW		0x016c	/* 32 bit	I2C SW Port Register */
-
-/* Blink Source Counter (GENESIS only) */
-#define B2_BSC_INI		0x0170	/* 32 bit	Blink Source Counter Init Val */
-#define B2_BSC_VAL		0x0174	/* 32 bit	Blink Source Counter Value */
-#define B2_BSC_CTRL		0x0178	/*  8 bit	Blink Source Counter Control */
-#define B2_BSC_STAT		0x0179	/*  8 bit	Blink Source Counter Status */
-#define B2_BSC_TST		0x017a	/* 16 bit	Blink Source Counter Test Reg */
-	/* 0x017c - 0x017f:	reserved */
-
-/*
- *	Bank 3
- */
-/* RAM Random Registers */
-#define B3_RAM_ADDR		0x0180	/* 32 bit	RAM Address, to read or write */
-#define B3_RAM_DATA_LO	0x0184	/* 32 bit	RAM Data Word (low dWord) */
-#define B3_RAM_DATA_HI	0x0188	/* 32 bit	RAM Data Word (high dWord) */
-	/* 0x018c - 0x018f:	reserved */
-
-/* RAM Interface Registers */
-/*
- * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
- * not usable in SW. Please notice these are NOT real timeouts, these are
- * the number of qWords transferred continuously.
- */
-#define B3_RI_WTO_R1	0x0190	/*  8 bit	WR Timeout Queue R1		(TO0) */
-#define B3_RI_WTO_XA1	0x0191	/*  8 bit	WR Timeout Queue XA1	(TO1) */
-#define B3_RI_WTO_XS1	0x0192	/*  8 bit	WR Timeout Queue XS1	(TO2) */
-#define B3_RI_RTO_R1	0x0193	/*  8 bit	RD Timeout Queue R1		(TO3) */
-#define B3_RI_RTO_XA1	0x0194	/*  8 bit	RD Timeout Queue XA1	(TO4) */
-#define B3_RI_RTO_XS1	0x0195	/*  8 bit	RD Timeout Queue XS1	(TO5) */
-#define B3_RI_WTO_R2	0x0196	/*  8 bit	WR Timeout Queue R2		(TO6) */
-#define B3_RI_WTO_XA2	0x0197	/*  8 bit	WR Timeout Queue XA2	(TO7) */
-#define B3_RI_WTO_XS2	0x0198	/*  8 bit	WR Timeout Queue XS2	(TO8) */
-#define B3_RI_RTO_R2	0x0199	/*  8 bit	RD Timeout Queue R2		(TO9) */
-#define B3_RI_RTO_XA2	0x019a	/*  8 bit	RD Timeout Queue XA2	(TO10)*/
-#define B3_RI_RTO_XS2	0x019b	/*  8 bit	RD Timeout Queue XS2	(TO11)*/
-#define B3_RI_TO_VAL	0x019c	/*  8 bit	Current Timeout Count Val */
-	/* 0x019d - 0x019f:	reserved */
-#define B3_RI_CTRL		0x01a0	/* 16 bit	RAM Interface Control Register */
-#define B3_RI_TEST		0x01a2	/*  8 bit	RAM Interface Test Register */
-	/* 0x01a3 - 0x01af:	reserved */
-
-/* MAC Arbiter Registers (GENESIS only) */
-/* these are the no. of qWord transferred continuously and NOT real timeouts */
-#define B3_MA_TOINI_RX1	0x01b0	/*  8 bit	Timeout Init Val Rx Path MAC 1 */
-#define B3_MA_TOINI_RX2	0x01b1	/*  8 bit	Timeout Init Val Rx Path MAC 2 */
-#define B3_MA_TOINI_TX1	0x01b2	/*  8 bit	Timeout Init Val Tx Path MAC 1 */
-#define B3_MA_TOINI_TX2	0x01b3	/*  8 bit	Timeout Init Val Tx Path MAC 2 */
-#define B3_MA_TOVAL_RX1	0x01b4	/*  8 bit	Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_RX2	0x01b5	/*  8 bit	Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_TX1	0x01b6	/*  8 bit	Timeout Value Tx Path MAC 2 */
-#define B3_MA_TOVAL_TX2	0x01b7	/*  8 bit	Timeout Value Tx Path MAC 2 */
-#define B3_MA_TO_CTRL	0x01b8	/* 16 bit	MAC Arbiter Timeout Ctrl Reg */
-#define B3_MA_TO_TEST	0x01ba	/* 16 bit	MAC Arbiter Timeout Test Reg */
-	/* 0x01bc - 0x01bf:	reserved */
-#define B3_MA_RCINI_RX1	0x01c0	/*  8 bit	Recovery Init Val Rx Path MAC 1 */
-#define B3_MA_RCINI_RX2	0x01c1	/*  8 bit	Recovery Init Val Rx Path MAC 2 */
-#define B3_MA_RCINI_TX1	0x01c2	/*  8 bit	Recovery Init Val Tx Path MAC 1 */
-#define B3_MA_RCINI_TX2	0x01c3	/*  8 bit	Recovery Init Val Tx Path MAC 2 */
-#define B3_MA_RCVAL_RX1	0x01c4	/*  8 bit	Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_RX2	0x01c5	/*  8 bit	Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_TX1	0x01c6	/*  8 bit	Recovery Value Tx Path MAC 2 */
-#define B3_MA_RCVAL_TX2	0x01c7	/*  8 bit	Recovery Value Tx Path MAC 2 */
-#define B3_MA_RC_CTRL	0x01c8	/* 16 bit	MAC Arbiter Recovery Ctrl Reg */
-#define B3_MA_RC_TEST	0x01ca	/* 16 bit	MAC Arbiter Recovery Test Reg */
-	/* 0x01cc - 0x01cf:	reserved */
-
-/* Packet Arbiter Registers (GENESIS only) */
-/* these are real timeouts */
-#define B3_PA_TOINI_RX1	0x01d0	/* 16 bit	Timeout Init Val Rx Path MAC 1 */
-	/* 0x01d2 - 0x01d3:	reserved */
-#define B3_PA_TOINI_RX2	0x01d4	/* 16 bit	Timeout Init Val Rx Path MAC 2 */
-	/* 0x01d6 - 0x01d7:	reserved */
-#define B3_PA_TOINI_TX1	0x01d8	/* 16 bit	Timeout Init Val Tx Path MAC 1 */
-	/* 0x01da - 0x01db:	reserved */
-#define B3_PA_TOINI_TX2	0x01dc	/* 16 bit	Timeout Init Val Tx Path MAC 2 */
-	/* 0x01de - 0x01df:	reserved */
-#define B3_PA_TOVAL_RX1	0x01e0	/* 16 bit	Timeout Val Rx Path MAC 1 */
-	/* 0x01e2 - 0x01e3:	reserved */
-#define B3_PA_TOVAL_RX2	0x01e4	/* 16 bit	Timeout Val Rx Path MAC 2 */
-	/* 0x01e6 - 0x01e7:	reserved */
-#define B3_PA_TOVAL_TX1	0x01e8	/* 16 bit	Timeout Val Tx Path MAC 1 */
-	/* 0x01ea - 0x01eb:	reserved */
-#define B3_PA_TOVAL_TX2	0x01ec	/* 16 bit	Timeout Val Tx Path MAC 2 */
-	/* 0x01ee - 0x01ef:	reserved */
-#define B3_PA_CTRL	0x01f0	/* 16 bit	Packet Arbiter Ctrl Register */
-#define B3_PA_TEST	0x01f2	/* 16 bit	Packet Arbiter Test Register */
-	/* 0x01f4 - 0x01ff:	reserved */
-
-/*
- *	Bank 4 - 5
- */
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-#define TXA_ITI_INI		0x0200	/* 32 bit	Tx Arb Interval Timer Init Val*/
-#define TXA_ITI_VAL		0x0204	/* 32 bit	Tx Arb Interval Timer Value */
-#define TXA_LIM_INI		0x0208	/* 32 bit	Tx Arb Limit Counter Init Val */
-#define TXA_LIM_VAL		0x020c	/* 32 bit	Tx Arb Limit Counter Value */
-#define TXA_CTRL		0x0210	/*  8 bit	Tx Arbiter Control Register */
-#define TXA_TEST		0x0211	/*  8 bit	Tx Arbiter Test Register */
-#define TXA_STAT		0x0212	/*  8 bit	Tx Arbiter Status Register */
-	/* 0x0213 - 0x027f:	reserved */
-	/* 0x0280 - 0x0292:	MAC 2 */
-	/* 0x0213 - 0x027f:	reserved */
-
-/*
- *	Bank 6
- */
-/* External registers (GENESIS only) */
-#define B6_EXT_REG		0x0300
-
-/*
- *	Bank 7
- */
-/* This is a copy of the Configuration register file (lower half) */
-#define B7_CFG_SPC		0x0380
-
-/*
- *	Bank 8 - 15
- */
-/* Receive and Transmit Queue Registers, use Q_ADDR() to access */
-#define B8_Q_REGS		0x0400
-
-/* Queue Register Offsets, use Q_ADDR() to access */
-#define Q_D		0x00	/* 8*32	bit	Current Descriptor */
-#define Q_DA_L	0x20	/* 32 bit	Current Descriptor Address Low dWord */
-#define Q_DA_H	0x24	/* 32 bit	Current Descriptor Address High dWord */
-#define Q_AC_L	0x28	/* 32 bit	Current Address Counter Low dWord */
-#define Q_AC_H	0x2c	/* 32 bit	Current Address Counter High dWord */
-#define Q_BC	0x30	/* 32 bit	Current Byte Counter */
-#define Q_CSR	0x34	/* 32 bit	BMU Control/Status Register */
-#define Q_F		0x38	/* 32 bit	Flag Register */
-#define Q_T1	0x3c	/* 32 bit	Test Register 1 */
-#define Q_T1_TR	0x3c	/*  8 bit	Test Register 1 Transfer SM */
-#define Q_T1_WR	0x3d	/*  8 bit	Test Register 1 Write Descriptor SM */
-#define Q_T1_RD	0x3e	/*  8 bit	Test Register 1 Read Descriptor SM */
-#define Q_T1_SV	0x3f	/*  8 bit	Test Register 1 Supervisor SM */
-#define Q_T2	0x40	/* 32 bit	Test Register 2	*/
-#define Q_T3	0x44	/* 32 bit	Test Register 3	*/
-	/* 0x48 - 0x7f:	reserved */
-
-/*
- *	Bank 16 - 23
- */
-/* RAM Buffer Registers */
-#define B16_RAM_REGS	0x0800
-
-/* RAM Buffer Register Offsets, use RB_ADDR() to access */
-#define RB_START		0x00	/* 32 bit	RAM Buffer Start Address */
-#define RB_END			0x04	/* 32 bit	RAM Buffer End Address */
-#define RB_WP			0x08	/* 32 bit	RAM Buffer Write Pointer */
-#define RB_RP			0x0c	/* 32 bit	RAM Buffer Read Pointer */
-#define RB_RX_UTPP		0x10	/* 32 bit	Rx Upper Threshold, Pause Pack */
-#define RB_RX_LTPP		0x14	/* 32 bit	Rx Lower Threshold, Pause Pack */
-#define RB_RX_UTHP		0x18	/* 32 bit	Rx Upper Threshold, High Prio */
-#define RB_RX_LTHP		0x1c	/* 32 bit	Rx Lower Threshold, High Prio */
-	/* 0x10 - 0x1f:	reserved at Tx RAM Buffer Registers */
-#define RB_PC			0x20	/* 32 bit	RAM Buffer Packet Counter */
-#define RB_LEV			0x24	/* 32 bit	RAM Buffer Level Register */
-#define RB_CTRL			0x28	/*  8 bit	RAM Buffer Control Register */
-#define RB_TST1			0x29	/*  8 bit	RAM Buffer Test Register 1 */
-#define RB_TST2			0x2A	/*  8 bit	RAM Buffer Test Register 2 */
-	/* 0x2c - 0x7f:	reserved */
-
-/*
- *	Bank 24
- */
-/*
- * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only)
- * use MR_ADDR() to access
- */
-#define RX_MFF_EA		0x0c00	/* 32 bit	Receive MAC FIFO End Address */
-#define RX_MFF_WP		0x0c04	/* 32 bit 	Receive MAC FIFO Write Pointer */
-	/* 0x0c08 - 0x0c0b:	reserved */
-#define RX_MFF_RP		0x0c0c	/* 32 bit	Receive MAC FIFO Read Pointer */
-#define RX_MFF_PC		0x0c10	/* 32 bit	Receive MAC FIFO Packet Cnt */
-#define RX_MFF_LEV		0x0c14	/* 32 bit	Receive MAC FIFO Level */
-#define RX_MFF_CTRL1	0x0c18	/* 16 bit	Receive MAC FIFO Control Reg 1*/
-#define RX_MFF_STAT_TO	0x0c1a	/*  8 bit	Receive MAC Status Timeout */
-#define RX_MFF_TIST_TO	0x0c1b	/*  8 bit	Receive MAC Time Stamp Timeout */
-#define RX_MFF_CTRL2	0x0c1c	/*  8 bit	Receive MAC FIFO Control Reg 2*/
-#define RX_MFF_TST1		0x0c1d	/*  8 bit	Receive MAC FIFO Test Reg 1 */
-#define RX_MFF_TST2		0x0c1e	/*  8 bit	Receive MAC FIFO Test Reg 2 */
-	/* 0x0c1f:	reserved */
-#define RX_LED_INI		0x0c20	/* 32 bit	Receive LED Cnt Init Value */
-#define RX_LED_VAL		0x0c24	/* 32 bit	Receive LED Cnt Current Value */
-#define RX_LED_CTRL		0x0c28	/*  8 bit	Receive LED Cnt Control Reg */
-#define RX_LED_TST		0x0c29	/*  8 bit	Receive LED Cnt Test Register */
-	/* 0x0c2a - 0x0c2f:	reserved */
-#define LNK_SYNC_INI	0x0c30	/* 32 bit	Link Sync Cnt Init Value */
-#define LNK_SYNC_VAL	0x0c34	/* 32 bit	Link Sync Cnt Current Value */
-#define LNK_SYNC_CTRL	0x0c38	/*  8 bit	Link Sync Cnt Control Register */
-#define LNK_SYNC_TST	0x0c39	/*  8 bit	Link Sync Cnt Test Register */
-	/* 0x0c3a - 0x0c3b:	reserved */
-#define LNK_LED_REG		0x0c3c	/*  8 bit	Link LED Register */
-	/* 0x0c3d - 0x0c3f:	reserved */
-
-/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define RX_GMF_EA		0x0c40	/* 32 bit	Rx GMAC FIFO End Address */
-#define RX_GMF_AF_THR	0x0c44	/* 32 bit	Rx GMAC FIFO Almost Full Thresh. */
-#define RX_GMF_CTRL_T	0x0c48	/* 32 bit	Rx GMAC FIFO Control/Test */
-#define RX_GMF_FL_MSK	0x0c4c	/* 32 bit	Rx GMAC FIFO Flush Mask */
-#define RX_GMF_FL_THR	0x0c50	/* 32 bit	Rx GMAC FIFO Flush Threshold */
-	/* 0x0c54 - 0x0c5f:	reserved */
-#define RX_GMF_WP		0x0c60	/* 32 bit 	Rx GMAC FIFO Write Pointer */
-	/* 0x0c64 - 0x0c67:	reserved */
-#define RX_GMF_WLEV		0x0c68	/* 32 bit 	Rx GMAC FIFO Write Level */
-	/* 0x0c6c - 0x0c6f:	reserved */
-#define RX_GMF_RP		0x0c70	/* 32 bit 	Rx GMAC FIFO Read Pointer */
-	/* 0x0c74 - 0x0c77:	reserved */
-#define RX_GMF_RLEV		0x0c78	/* 32 bit 	Rx GMAC FIFO Read Level */
-	/* 0x0c7c - 0x0c7f:	reserved */
-
-/*
- *	Bank 25
- */
-	/* 0x0c80 - 0x0cbf:	MAC 2 */
-	/* 0x0cc0 - 0x0cff:	reserved */
-
-/*
- *	Bank 26
- */
-/*
- * Transmit MAC FIFO and Transmit LED Registers (GENESIS only),
- * use MR_ADDR() to access
- */
-#define TX_MFF_EA		0x0d00	/* 32 bit	Transmit MAC FIFO End Address */
-#define TX_MFF_WP		0x0d04	/* 32 bit 	Transmit MAC FIFO WR Pointer */
-#define TX_MFF_WSP		0x0d08	/* 32 bit	Transmit MAC FIFO WR Shadow Ptr */
-#define TX_MFF_RP		0x0d0c	/* 32 bit	Transmit MAC FIFO RD Pointer */
-#define TX_MFF_PC		0x0d10	/* 32 bit	Transmit MAC FIFO Packet Cnt */
-#define TX_MFF_LEV		0x0d14	/* 32 bit	Transmit MAC FIFO Level */
-#define TX_MFF_CTRL1	0x0d18	/* 16 bit	Transmit MAC FIFO Ctrl Reg 1 */
-#define TX_MFF_WAF		0x0d1a	/*  8 bit	Transmit MAC Wait after flush */
-	/* 0x0c1b:	reserved */
-#define TX_MFF_CTRL2	0x0d1c	/*  8 bit	Transmit MAC FIFO Ctrl Reg 2 */
-#define TX_MFF_TST1		0x0d1d	/*  8 bit	Transmit MAC FIFO Test Reg 1 */
-#define TX_MFF_TST2		0x0d1e	/*  8 bit	Transmit MAC FIFO Test Reg 2 */
-	/* 0x0d1f:	reserved */
-#define TX_LED_INI		0x0d20	/* 32 bit	Transmit LED Cnt Init Value */
-#define TX_LED_VAL		0x0d24	/* 32 bit	Transmit LED Cnt Current Val */
-#define TX_LED_CTRL		0x0d28	/*  8 bit	Transmit LED Cnt Control Reg */
-#define TX_LED_TST		0x0d29	/*  8 bit	Transmit LED Cnt Test Reg */
-	/* 0x0d2a - 0x0d3f:	reserved */
-
-/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define TX_GMF_EA		0x0d40	/* 32 bit	Tx GMAC FIFO End Address */
-#define TX_GMF_AE_THR	0x0d44	/* 32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
-#define TX_GMF_CTRL_T	0x0d48	/* 32 bit	Tx GMAC FIFO Control/Test */
-	/* 0x0d4c - 0x0d5f:	reserved */
-#define TX_GMF_WP		0x0d60	/* 32 bit 	Tx GMAC FIFO Write Pointer */
-#define TX_GMF_WSP		0x0d64	/* 32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
-#define TX_GMF_WLEV		0x0d68	/* 32 bit 	Tx GMAC FIFO Write Level */
-	/* 0x0d6c - 0x0d6f:	reserved */
-#define TX_GMF_RP		0x0d70	/* 32 bit 	Tx GMAC FIFO Read Pointer */
-#define TX_GMF_RSTP		0x0d74	/* 32 bit 	Tx GMAC FIFO Restart Pointer */
-#define TX_GMF_RLEV		0x0d78	/* 32 bit 	Tx GMAC FIFO Read Level */
-	/* 0x0d7c - 0x0d7f:	reserved */
-
-/*
- *	Bank 27
- */
-	/* 0x0d80 - 0x0dbf:	MAC 2 */
-	/* 0x0daa - 0x0dff:	reserved */
-
-/*
- *	Bank 28
- */
-/* Descriptor Poll Timer Registers */
-#define B28_DPT_INI		0x0e00	/* 24 bit	Descriptor Poll Timer Init Val */
-#define B28_DPT_VAL		0x0e04	/* 24 bit	Descriptor Poll Timer Curr Val */
-#define B28_DPT_CTRL	0x0e08	/*  8 bit	Descriptor Poll Timer Ctrl Reg */
-	/* 0x0e09:	reserved */
-#define B28_DPT_TST		0x0e0a	/*  8 bit	Descriptor Poll Timer Test Reg */
-	/* 0x0e0b:	reserved */
-
-/* Time Stamp Timer Registers (YUKON only) */
-	/* 0x0e10:	reserved */
-#define GMAC_TI_ST_VAL	0x0e14	/* 32 bit	Time Stamp Timer Curr Val */
-#define GMAC_TI_ST_CTRL	0x0e18	/*  8 bit	Time Stamp Timer Ctrl Reg */
-	/* 0x0e19:	reserved */
-#define GMAC_TI_ST_TST	0x0e1a	/*  8 bit	Time Stamp Timer Test Reg */
-	/* 0x0e1b - 0x0e7f:	reserved */
-
-/*
- *	Bank 29
- */
-	/* 0x0e80 - 0x0efc:	reserved */
-
-/*
- *	Bank 30
- */
-/* GMAC and GPHY Control Registers (YUKON only) */
-#define GMAC_CTRL		0x0f00	/* 32 bit	GMAC Control Reg */
-#define GPHY_CTRL		0x0f04	/* 32 bit	GPHY Control Reg */
-#define GMAC_IRQ_SRC	0x0f08	/*  8 bit	GMAC Interrupt Source Reg */
-	/* 0x0f09 - 0x0f0b:	reserved */
-#define GMAC_IRQ_MSK	0x0f0c	/*  8 bit	GMAC Interrupt Mask Reg */
-	/* 0x0f0d - 0x0f0f:	reserved */
-#define GMAC_LINK_CTRL	0x0f10	/* 16 bit	Link Control Reg */
-	/* 0x0f14 - 0x0f1f:	reserved */
-
-/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
-
-#define WOL_REG_OFFS	0x20	/* HW-Bug: Address is + 0x20 against spec. */
-
-#define WOL_CTRL_STAT	0x0f20	/* 16 bit	WOL Control/Status Reg */
-#define WOL_MATCH_CTL	0x0f22	/*  8 bit	WOL Match Control Reg */
-#define WOL_MATCH_RES	0x0f23	/*  8 bit	WOL Match Result Reg */
-#define WOL_MAC_ADDR_LO	0x0f24	/* 32 bit	WOL MAC Address Low */
-#define WOL_MAC_ADDR_HI	0x0f28	/* 16 bit	WOL MAC Address High */
-#define WOL_PATT_RPTR	0x0f2c	/*  8 bit	WOL Pattern Read Ptr */
-
-/* use this macro to access above registers */
-#define WOL_REG(Reg)	((Reg) + (pAC->GIni.GIWolOffs))
-
-
-/* WOL Pattern Length Registers (YUKON only) */
-
-#define WOL_PATT_LEN_LO	0x0f30		/* 32 bit	WOL Pattern Length 3..0 */
-#define WOL_PATT_LEN_HI	0x0f34		/* 24 bit	WOL Pattern Length 6..4 */
-
-/* WOL Pattern Counter Registers (YUKON only) */
-
-#define WOL_PATT_CNT_0	0x0f38		/* 32 bit	WOL Pattern Counter 3..0 */
-#define WOL_PATT_CNT_4	0x0f3c		/* 24 bit	WOL Pattern Counter 6..4 */
-	/* 0x0f40 - 0x0f7f:	reserved */
-
-/*
- *	Bank 31
- */
-/* 0x0f80 - 0x0fff:	reserved */
-
-/*
- *	Bank 32	- 33
- */
-#define WOL_PATT_RAM_1	0x1000	/*  WOL Pattern RAM Link 1 */
-
-/*
- *	Bank 0x22 - 0x3f
- */
-/* 0x1100 - 0x1fff:	reserved */
-
-/*
- *	Bank 0x40 - 0x4f
- */
-#define BASE_XMAC_1		0x2000	/* XMAC 1 registers */
-
-/*
- *	Bank 0x50 - 0x5f
- */
-
-#define BASE_GMAC_1		0x2800	/* GMAC 1 registers */
-
-/*
- *	Bank 0x60 - 0x6f
- */
-#define BASE_XMAC_2		0x3000	/* XMAC 2 registers */
-
-/*
- *	Bank 0x70 - 0x7f
- */
-#define BASE_GMAC_2		0x3800	/* GMAC 2 registers */
-
-/*
- *	Control Register Bit Definitions:
- */
-/*	B0_RAP		8 bit	Register Address Port */
-								/* Bit 7:	reserved */
-#define RAP_RAP			0x3f	/* Bit 6..0:	0 = block 0,..,6f = block 6f */
-
-/*	B0_CTST			16 bit	Control/Status register */
-								/* Bit 15..14:	reserved */
-#define CS_CLK_RUN_HOT	BIT_13S		/* CLK_RUN hot m. (YUKON-Lite only) */
-#define CS_CLK_RUN_RST	BIT_12S		/* CLK_RUN reset  (YUKON-Lite only) */
-#define CS_CLK_RUN_ENA	BIT_11S		/* CLK_RUN enable (YUKON-Lite only) */
-#define CS_VAUX_AVAIL	BIT_10S		/* VAUX available (YUKON only) */
-#define CS_BUS_CLOCK	BIT_9S		/* Bus Clock 0/1 = 33/66 MHz */
-#define CS_BUS_SLOT_SZ	BIT_8S		/* Slot Size 0/1 = 32/64 bit slot */
-#define CS_ST_SW_IRQ	BIT_7S		/* Set IRQ SW Request */
-#define CS_CL_SW_IRQ	BIT_6S		/* Clear IRQ SW Request */
-#define CS_STOP_DONE	BIT_5S		/* Stop Master is finished */
-#define CS_STOP_MAST	BIT_4S		/* Command Bit to stop the master */
-#define CS_MRST_CLR		BIT_3S		/* Clear Master reset	*/
-#define CS_MRST_SET		BIT_2S		/* Set Master reset	*/
-#define CS_RST_CLR		BIT_1S		/* Clear Software reset	*/
-#define CS_RST_SET		BIT_0S		/* Set   Software reset	*/
-
-/*	B0_LED			 8 Bit	LED register */
-								/* Bit  7.. 2:	reserved */
-#define LED_STAT_ON		BIT_1S		/* Status LED on	*/
-#define LED_STAT_OFF	BIT_0S		/* Status LED off	*/
-
-/*	B0_POWER_CTRL	 8 Bit	Power Control reg (YUKON only) */
-#define PC_VAUX_ENA		BIT_7		/* Switch VAUX Enable  */
-#define PC_VAUX_DIS		BIT_6       /* Switch VAUX Disable */
-#define PC_VCC_ENA		BIT_5       /* Switch VCC Enable  */
-#define PC_VCC_DIS		BIT_4       /* Switch VCC Disable */
-#define PC_VAUX_ON		BIT_3       /* Switch VAUX On  */
-#define PC_VAUX_OFF		BIT_2       /* Switch VAUX Off */
-#define PC_VCC_ON		BIT_1       /* Switch VCC On  */
-#define PC_VCC_OFF		BIT_0       /* Switch VCC Off */
-
-/*	B0_ISRC			32 bit	Interrupt Source Register */
-/*	B0_IMSK			32 bit	Interrupt Mask Register */
-/*	B0_SP_ISRC		32 bit	Special Interrupt Source Reg */
-/*	B2_IRQM_MSK 	32 bit	IRQ Moderation Mask */
-#define IS_ALL_MSK		0xbfffffffUL	/* All Interrupt bits */
-#define IS_HW_ERR		BIT_31		/* Interrupt HW Error */
-								/* Bit 30:	reserved */
-#define IS_PA_TO_RX1	BIT_29		/* Packet Arb Timeout Rx1 */
-#define IS_PA_TO_RX2	BIT_28		/* Packet Arb Timeout Rx2 */
-#define IS_PA_TO_TX1	BIT_27		/* Packet Arb Timeout Tx1 */
-#define IS_PA_TO_TX2	BIT_26		/* Packet Arb Timeout Tx2 */
-#define IS_I2C_READY	BIT_25		/* IRQ on end of I2C Tx */
-#define IS_IRQ_SW		BIT_24		/* SW forced IRQ	*/
-#define IS_EXT_REG		BIT_23		/* IRQ from LM80 or PHY (GENESIS only) */
-									/* IRQ from PHY (YUKON only) */
-#define IS_TIMINT		BIT_22		/* IRQ from Timer	*/
-#define IS_MAC1			BIT_21		/* IRQ from MAC 1	*/
-#define IS_LNK_SYNC_M1	BIT_20		/* Link Sync Cnt wrap MAC 1 */
-#define IS_MAC2			BIT_19		/* IRQ from MAC 2	*/
-#define IS_LNK_SYNC_M2	BIT_18		/* Link Sync Cnt wrap MAC 2 */
-/* Receive Queue 1 */
-#define IS_R1_B			BIT_17		/* Q_R1 End of Buffer */
-#define IS_R1_F			BIT_16		/* Q_R1 End of Frame */
-#define IS_R1_C			BIT_15		/* Q_R1 Encoding Error */
-/* Receive Queue 2 */
-#define IS_R2_B			BIT_14		/* Q_R2 End of Buffer */
-#define IS_R2_F			BIT_13		/* Q_R2 End of Frame */
-#define IS_R2_C			BIT_12		/* Q_R2 Encoding Error */
-/* Synchronous Transmit Queue 1 */
-#define IS_XS1_B		BIT_11		/* Q_XS1 End of Buffer */
-#define IS_XS1_F		BIT_10		/* Q_XS1 End of Frame */
-#define IS_XS1_C		BIT_9		/* Q_XS1 Encoding Error */
-/* Asynchronous Transmit Queue 1 */
-#define IS_XA1_B		BIT_8		/* Q_XA1 End of Buffer */
-#define IS_XA1_F		BIT_7		/* Q_XA1 End of Frame */
-#define IS_XA1_C		BIT_6		/* Q_XA1 Encoding Error */
-/* Synchronous Transmit Queue 2 */
-#define IS_XS2_B		BIT_5		/* Q_XS2 End of Buffer */
-#define IS_XS2_F		BIT_4		/* Q_XS2 End of Frame */
-#define IS_XS2_C		BIT_3		/* Q_XS2 Encoding Error */
-/* Asynchronous Transmit Queue 2 */
-#define IS_XA2_B		BIT_2		/* Q_XA2 End of Buffer */
-#define IS_XA2_F		BIT_1		/* Q_XA2 End of Frame */
-#define IS_XA2_C		BIT_0		/* Q_XA2 Encoding Error */
-
-
-/*	B0_HWE_ISRC		32 bit	HW Error Interrupt Src Reg */
-/*	B0_HWE_IMSK		32 bit	HW Error Interrupt Mask Reg */
-/*	B2_IRQM_HWE_MSK	32 bit	IRQ Moderation HW Error Mask */
-#define IS_ERR_MSK		0x00000fffL	/* 		All Error bits */
-								/* Bit 31..14:	reserved */
-#define IS_IRQ_TIST_OV	BIT_13	/* Time Stamp Timer Overflow (YUKON only) */
-#define IS_IRQ_SENSOR	BIT_12	/* IRQ from Sensor (YUKON only) */
-#define IS_IRQ_MST_ERR	BIT_11	/* IRQ master error detected */
-#define IS_IRQ_STAT		BIT_10	/* IRQ status exception */
-#define IS_NO_STAT_M1	BIT_9	/* No Rx Status from MAC 1 */
-#define IS_NO_STAT_M2	BIT_8	/* No Rx Status from MAC 2 */
-#define IS_NO_TIST_M1	BIT_7	/* No Time Stamp from MAC 1 */
-#define IS_NO_TIST_M2	BIT_6	/* No Time Stamp from MAC 2 */
-#define IS_RAM_RD_PAR	BIT_5	/* RAM Read  Parity Error */
-#define IS_RAM_WR_PAR	BIT_4	/* RAM Write Parity Error */
-#define IS_M1_PAR_ERR	BIT_3	/* MAC 1 Parity Error */
-#define IS_M2_PAR_ERR	BIT_2	/* MAC 2 Parity Error */
-#define IS_R1_PAR_ERR	BIT_1	/* Queue R1 Parity Error */
-#define IS_R2_PAR_ERR	BIT_0	/* Queue R2 Parity Error */
-
-/*	B2_CONN_TYP		 8 bit	Connector type */
-/*	B2_PMD_TYP		 8 bit	PMD type */
-/*	Values of connector and PMD type comply to SysKonnect internal std */
-
-/*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
-#define CFG_CHIP_R_MSK	(0xf<<4)	/* Bit 7.. 4: Chip Revision */
-									/* Bit 3.. 2:	reserved */
-#define CFG_DIS_M2_CLK	BIT_1S		/* Disable Clock for 2nd MAC */
-#define CFG_SNG_MAC		BIT_0S		/* MAC Config: 0=2 MACs / 1=1 MAC*/
-
-/*	B2_CHIP_ID		 8 bit 	Chip Identification Number */
-#define CHIP_ID_GENESIS		0x0a	/* Chip ID for GENESIS */
-#define CHIP_ID_YUKON		0xb0	/* Chip ID for YUKON */
-#define CHIP_ID_YUKON_LITE	0xb1	/* Chip ID for YUKON-Lite (Rev. A1-A3) */
-#define CHIP_ID_YUKON_LP	0xb2	/* Chip ID for YUKON-LP */
-
-#define CHIP_REV_YU_LITE_A1	3		/* Chip Rev. for YUKON-Lite A1,A2 */
-#define CHIP_REV_YU_LITE_A3	7		/* Chip Rev. for YUKON-Lite A3 */
-
-/*	B2_FAR			32 bit	Flash-Prom Addr Reg/Cnt */
-#define FAR_ADDR		0x1ffffL	/* Bit 16.. 0:	FPROM Address mask */
-
-/*	B2_LD_CTRL		 8 bit	EPROM loader control register */
-/*	Bits are currently reserved */
-
-/*	B2_LD_TEST		 8 bit	EPROM loader test register */
-								/* Bit 7.. 4:	reserved */
-#define LD_T_ON			BIT_3S	/* Loader Test mode on */
-#define LD_T_OFF		BIT_2S	/* Loader Test mode off */
-#define LD_T_STEP		BIT_1S	/* Decrement FPROM addr. Counter */
-#define LD_START		BIT_0S	/* Start loading FPROM */
-
-/*
- *	Timer Section
- */
-/*	B2_TI_CTRL		 8 bit	Timer control */
-/*	B2_IRQM_CTRL	 8 bit	IRQ Moderation Timer Control */
-								/* Bit 7.. 3:	reserved */
-#define TIM_START		BIT_2S	/* Start Timer */
-#define TIM_STOP		BIT_1S	/* Stop  Timer */
-#define TIM_CLR_IRQ		BIT_0S	/* Clear Timer IRQ (!IRQM) */
-
-/*	B2_TI_TEST		 8 Bit	Timer Test */
-/*	B2_IRQM_TEST	 8 bit	IRQ Moderation Timer Test */
-/*	B28_DPT_TST		 8 bit	Descriptor Poll Timer Test Reg */
-								/* Bit 7.. 3:	reserved */
-#define TIM_T_ON		BIT_2S	/* Test mode on */
-#define TIM_T_OFF		BIT_1S	/* Test mode off */
-#define TIM_T_STEP		BIT_0S	/* Test step */
-
-/*	B28_DPT_INI	32 bit	Descriptor Poll Timer Init Val */
-/*	B28_DPT_VAL	32 bit	Descriptor Poll Timer Curr Val */
-								/* Bit 31..24:	reserved */
-#define DPT_MSK		0x00ffffffL	/* Bit 23.. 0:	Desc Poll Timer Bits */
-
-/*	B28_DPT_CTRL	 8 bit	Descriptor Poll Timer Ctrl Reg */
-								/* Bit  7.. 2:	reserved */
-#define DPT_START		BIT_1S	/* Start Descriptor Poll Timer */
-#define DPT_STOP		BIT_0S	/* Stop  Descriptor Poll Timer */
-
-/*	B2_E_3			 8 bit 	lower 4 bits used for HW self test result */
-#define B2_E3_RES_MASK	0x0f
-
-/*	B2_TST_CTRL1	 8 bit	Test Control Register 1 */
-#define TST_FRC_DPERR_MR	BIT_7S	/* force DATAPERR on MST RD */
-#define TST_FRC_DPERR_MW	BIT_6S	/* force DATAPERR on MST WR */
-#define TST_FRC_DPERR_TR	BIT_5S	/* force DATAPERR on TRG RD */
-#define TST_FRC_DPERR_TW	BIT_4S	/* force DATAPERR on TRG WR */
-#define TST_FRC_APERR_M		BIT_3S	/* force ADDRPERR on MST */
-#define TST_FRC_APERR_T		BIT_2S	/* force ADDRPERR on TRG */
-#define TST_CFG_WRITE_ON	BIT_1S	/* Enable  Config Reg WR */
-#define TST_CFG_WRITE_OFF	BIT_0S	/* Disable Config Reg WR */
-
-/*	B2_TST_CTRL2	 8 bit	Test Control Register 2 */
-									/* Bit 7.. 4:	reserved */
-			/* force the following error on the next master read/write	*/
-#define TST_FRC_DPERR_MR64	BIT_3S	/* DataPERR RD 64	*/
-#define TST_FRC_DPERR_MW64	BIT_2S	/* DataPERR WR 64	*/
-#define TST_FRC_APERR_1M64	BIT_1S	/* AddrPERR on 1. phase */
-#define TST_FRC_APERR_2M64	BIT_0S	/* AddrPERR on 2. phase */
-
-/*	B2_GP_IO		32 bit	General Purpose I/O Register */
-							/* Bit 31..26:	reserved */
-#define GP_DIR_9	BIT_25	/* IO_9 direct, 0=In/1=Out */
-#define GP_DIR_8	BIT_24	/* IO_8 direct, 0=In/1=Out */
-#define GP_DIR_7	BIT_23	/* IO_7 direct, 0=In/1=Out */
-#define GP_DIR_6	BIT_22	/* IO_6 direct, 0=In/1=Out */
-#define GP_DIR_5	BIT_21	/* IO_5 direct, 0=In/1=Out */
-#define GP_DIR_4	BIT_20	/* IO_4 direct, 0=In/1=Out */
-#define GP_DIR_3	BIT_19	/* IO_3 direct, 0=In/1=Out */
-#define GP_DIR_2	BIT_18	/* IO_2 direct, 0=In/1=Out */
-#define GP_DIR_1	BIT_17	/* IO_1 direct, 0=In/1=Out */
-#define GP_DIR_0	BIT_16	/* IO_0 direct, 0=In/1=Out */
-						/* Bit 15..10:	reserved */
-#define GP_IO_9		BIT_9	/* IO_9 pin */
-#define GP_IO_8		BIT_8	/* IO_8 pin */
-#define GP_IO_7		BIT_7	/* IO_7 pin */
-#define GP_IO_6		BIT_6	/* IO_6 pin */
-#define GP_IO_5		BIT_5	/* IO_5 pin */
-#define GP_IO_4		BIT_4	/* IO_4 pin */
-#define GP_IO_3		BIT_3	/* IO_3 pin */
-#define GP_IO_2		BIT_2	/* IO_2 pin */
-#define GP_IO_1		BIT_1	/* IO_1 pin */
-#define GP_IO_0		BIT_0	/* IO_0 pin */
-
-/*	B2_I2C_CTRL		32 bit	I2C HW Control Register */
-#define I2C_FLAG		BIT_31		/* Start read/write if WR */
-#define I2C_ADDR		(0x7fffL<<16)	/* Bit 30..16:	Addr to be RD/WR */
-#define I2C_DEV_SEL		(0x7fL<<9)		/* Bit 15.. 9:	I2C Device Select */
-								/* Bit	8.. 5:	reserved	*/
-#define I2C_BURST_LEN	BIT_4		/* Burst Len, 1/4 bytes */
-#define I2C_DEV_SIZE	(7<<1)		/* Bit	3.. 1:	I2C Device Size	*/
-#define I2C_025K_DEV	(0<<1)		/*		0: 256 Bytes or smal. */
-#define I2C_05K_DEV		(1<<1)		/* 		1: 512	Bytes	*/
-#define I2C_1K_DEV		(2<<1)		/*		2: 1024 Bytes	*/
-#define I2C_2K_DEV		(3<<1)		/*		3: 2048	Bytes	*/
-#define I2C_4K_DEV		(4<<1)		/*		4: 4096 Bytes	*/
-#define I2C_8K_DEV		(5<<1)		/*		5: 8192 Bytes	*/
-#define I2C_16K_DEV		(6<<1)		/*		6: 16384 Bytes	*/
-#define I2C_32K_DEV		(7<<1)		/*		7: 32768 Bytes	*/
-#define I2C_STOP		BIT_0		/* Interrupt I2C transfer */
-
-/*	B2_I2C_IRQ		32 bit	I2C HW IRQ Register */
-								/* Bit 31.. 1	reserved */
-#define I2C_CLR_IRQ		BIT_0	/* Clear I2C IRQ */
-
-/*	B2_I2C_SW		32 bit (8 bit access)	I2C HW SW Port Register */
-								/* Bit  7.. 3:	reserved */
-#define I2C_DATA_DIR	BIT_2S		/* direction of I2C_DATA */
-#define I2C_DATA		BIT_1S		/* I2C Data Port	*/
-#define I2C_CLK			BIT_0S		/* I2C Clock Port	*/
-
-/*
- * I2C Address
- */
-#define I2C_SENS_ADDR	LM80_ADDR	/* I2C Sensor Address, (Volt and Temp)*/
-
-
-/*	B2_BSC_CTRL		 8 bit	Blink Source Counter Control */
-							/* Bit  7.. 2:	reserved */
-#define BSC_START	BIT_1S		/* Start Blink Source Counter */
-#define BSC_STOP	BIT_0S		/* Stop  Blink Source Counter */
-
-/*	B2_BSC_STAT		 8 bit	Blink Source Counter Status */
-							/* Bit  7.. 1:	reserved */
-#define BSC_SRC		BIT_0S		/* Blink Source, 0=Off / 1=On */
-
-/*	B2_BSC_TST		16 bit	Blink Source Counter Test Reg */
-#define BSC_T_ON	BIT_2S		/* Test mode on */
-#define BSC_T_OFF	BIT_1S		/* Test mode off */
-#define BSC_T_STEP	BIT_0S		/* Test step */
-
-
-/*	B3_RAM_ADDR		32 bit	RAM Address, to read or write */
-					/* Bit 31..19:	reserved */
-#define RAM_ADR_RAN	0x0007ffffL	/* Bit 18.. 0:	RAM Address Range */
-
-/* RAM Interface Registers */
-/*	B3_RI_CTRL		16 bit	RAM Iface Control Register */
-								/* Bit 15..10:	reserved */
-#define RI_CLR_RD_PERR	BIT_9S	/* Clear IRQ RAM Read Parity Err */
-#define RI_CLR_WR_PERR	BIT_8S	/* Clear IRQ RAM Write Parity Err*/
-								/* Bit	7.. 2:	reserved */
-#define RI_RST_CLR		BIT_1S	/* Clear RAM Interface Reset */
-#define RI_RST_SET		BIT_0S	/* Set   RAM Interface Reset */
-
-/*	B3_RI_TEST		 8 bit	RAM Iface Test Register */
-								/* Bit 15.. 4:	reserved */
-#define RI_T_EV			BIT_3S	/* Timeout Event occured */
-#define RI_T_ON			BIT_2S	/* Timeout Timer Test On */
-#define RI_T_OFF		BIT_1S	/* Timeout Timer Test Off */
-#define RI_T_STEP		BIT_0S	/* Timeout Timer Step */
-
-/* MAC Arbiter Registers */
-/*	B3_MA_TO_CTRL	16 bit	MAC Arbiter Timeout Ctrl Reg */
-								/* Bit 15.. 4:	reserved */
-#define MA_FOE_ON		BIT_3S	/* XMAC Fast Output Enable ON */
-#define MA_FOE_OFF		BIT_2S	/* XMAC Fast Output Enable OFF */
-#define MA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
-#define MA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
-
-/*	B3_MA_RC_CTRL	16 bit	MAC Arbiter Recovery Ctrl Reg */
-								/* Bit 15.. 8:	reserved */
-#define MA_ENA_REC_TX2	BIT_7S	/* Enable  Recovery Timer TX2 */
-#define MA_DIS_REC_TX2	BIT_6S	/* Disable Recovery Timer TX2 */
-#define MA_ENA_REC_TX1	BIT_5S	/* Enable  Recovery Timer TX1 */
-#define MA_DIS_REC_TX1	BIT_4S	/* Disable Recovery Timer TX1 */
-#define MA_ENA_REC_RX2	BIT_3S	/* Enable  Recovery Timer RX2 */
-#define MA_DIS_REC_RX2	BIT_2S	/* Disable Recovery Timer RX2 */
-#define MA_ENA_REC_RX1	BIT_1S	/* Enable  Recovery Timer RX1 */
-#define MA_DIS_REC_RX1	BIT_0S	/* Disable Recovery Timer RX1 */
-
-/* Packet Arbiter Registers */
-/*	B3_PA_CTRL		16 bit	Packet Arbiter Ctrl Register */
-								/* Bit 15..14:	reserved */
-#define PA_CLR_TO_TX2	BIT_13S	/* Clear IRQ Packet Timeout TX2 */
-#define PA_CLR_TO_TX1	BIT_12S	/* Clear IRQ Packet Timeout TX1 */
-#define PA_CLR_TO_RX2	BIT_11S	/* Clear IRQ Packet Timeout RX2 */
-#define PA_CLR_TO_RX1	BIT_10S	/* Clear IRQ Packet Timeout RX1 */
-#define PA_ENA_TO_TX2	BIT_9S	/* Enable  Timeout Timer TX2 */
-#define PA_DIS_TO_TX2	BIT_8S	/* Disable Timeout Timer TX2 */
-#define PA_ENA_TO_TX1	BIT_7S	/* Enable  Timeout Timer TX1 */
-#define PA_DIS_TO_TX1	BIT_6S	/* Disable Timeout Timer TX1 */
-#define PA_ENA_TO_RX2	BIT_5S	/* Enable  Timeout Timer RX2 */
-#define PA_DIS_TO_RX2	BIT_4S	/* Disable Timeout Timer RX2 */
-#define PA_ENA_TO_RX1	BIT_3S	/* Enable  Timeout Timer RX1 */
-#define PA_DIS_TO_RX1	BIT_2S	/* Disable Timeout Timer RX1 */
-#define PA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
-#define PA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
-
-#define PA_ENA_TO_ALL	(PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
-						PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
-
-/* Rx/Tx Path related Arbiter Test Registers */
-/*	B3_MA_TO_TEST	16 bit	MAC Arbiter Timeout Test Reg */
-/*	B3_MA_RC_TEST	16 bit	MAC Arbiter Recovery Test Reg */
-/*	B3_PA_TEST		16 bit	Packet Arbiter Test Register */
-/*			Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
-#define TX2_T_EV	BIT_15S		/* TX2 Timeout/Recv Event occured */
-#define TX2_T_ON	BIT_14S		/* TX2 Timeout/Recv Timer Test On */
-#define TX2_T_OFF	BIT_13S		/* TX2 Timeout/Recv Timer Tst Off */
-#define TX2_T_STEP	BIT_12S		/* TX2 Timeout/Recv Timer Step */
-#define TX1_T_EV	BIT_11S		/* TX1 Timeout/Recv Event occured */
-#define TX1_T_ON	BIT_10S		/* TX1 Timeout/Recv Timer Test On */
-#define TX1_T_OFF	BIT_9S		/* TX1 Timeout/Recv Timer Tst Off */
-#define TX1_T_STEP	BIT_8S		/* TX1 Timeout/Recv Timer Step */
-#define RX2_T_EV	BIT_7S		/* RX2 Timeout/Recv Event occured */
-#define RX2_T_ON	BIT_6S		/* RX2 Timeout/Recv Timer Test On */
-#define RX2_T_OFF	BIT_5S		/* RX2 Timeout/Recv Timer Tst Off */
-#define RX2_T_STEP	BIT_4S		/* RX2 Timeout/Recv Timer Step */
-#define RX1_T_EV	BIT_3S		/* RX1 Timeout/Recv Event occured */
-#define RX1_T_ON	BIT_2S		/* RX1 Timeout/Recv Timer Test On */
-#define RX1_T_OFF	BIT_1S		/* RX1 Timeout/Recv Timer Tst Off */
-#define RX1_T_STEP	BIT_0S		/* RX1 Timeout/Recv Timer Step */
-
-
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-/*	TXA_ITI_INI		32 bit	Tx Arb Interval Timer Init Val */
-/*	TXA_ITI_VAL		32 bit	Tx Arb Interval Timer Value */
-/*	TXA_LIM_INI		32 bit	Tx Arb Limit Counter Init Val */
-/*	TXA_LIM_VAL		32 bit	Tx Arb Limit Counter Value */
-								/* Bit 31..24:	reserved */
-#define TXA_MAX_VAL	0x00ffffffUL/* Bit 23.. 0:	Max TXA Timer/Cnt Val */
-
-/*	TXA_CTRL		 8 bit	Tx Arbiter Control Register */
-#define TXA_ENA_FSYNC	BIT_7S	/* Enable  force of sync Tx queue */
-#define TXA_DIS_FSYNC	BIT_6S	/* Disable force of sync Tx queue */
-#define TXA_ENA_ALLOC	BIT_5S	/* Enable  alloc of free bandwidth */
-#define TXA_DIS_ALLOC	BIT_4S	/* Disable alloc of free bandwidth */
-#define TXA_START_RC	BIT_3S	/* Start sync Rate Control */
-#define TXA_STOP_RC		BIT_2S	/* Stop  sync Rate Control */
-#define TXA_ENA_ARB		BIT_1S	/* Enable  Tx Arbiter */
-#define TXA_DIS_ARB		BIT_0S	/* Disable Tx Arbiter */
-
-/*	TXA_TEST		 8 bit	Tx Arbiter Test Register */
-								/* Bit 7.. 6:	reserved */
-#define TXA_INT_T_ON	BIT_5S	/* Tx Arb Interval Timer Test On */
-#define TXA_INT_T_OFF	BIT_4S	/* Tx Arb Interval Timer Test Off */
-#define TXA_INT_T_STEP	BIT_3S	/* Tx Arb Interval Timer Step */
-#define TXA_LIM_T_ON	BIT_2S	/* Tx Arb Limit Timer Test On */
-#define TXA_LIM_T_OFF	BIT_1S	/* Tx Arb Limit Timer Test Off */
-#define TXA_LIM_T_STEP	BIT_0S	/* Tx Arb Limit Timer Step */
-
-/*	TXA_STAT		 8 bit	Tx Arbiter Status Register */
-								/* Bit 7.. 1:	reserved */
-#define TXA_PRIO_XS		BIT_0S	/* sync queue has prio to send */
-
-/*	Q_BC			32 bit	Current Byte Counter */
-								/* Bit 31..16:	reserved */
-#define BC_MAX			0xffff	/* Bit 15.. 0:	Byte counter */
-
-/* BMU Control Status Registers */
-/*	B0_R1_CSR		32 bit	BMU Ctrl/Stat Rx Queue 1 */
-/*	B0_R2_CSR		32 bit	BMU Ctrl/Stat Rx Queue 2 */
-/*	B0_XA1_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
-/*	B0_XS1_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 1 */
-/*	B0_XA2_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
-/*	B0_XS2_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 2 */
-/*	Q_CSR			32 bit	BMU Control/Status Register */
-								/* Bit 31..25:	reserved */
-#define CSR_SV_IDLE		BIT_24		/* BMU SM Idle */
-								/* Bit 23..22:	reserved */
-#define CSR_DESC_CLR	BIT_21		/* Clear Reset for Descr */
-#define CSR_DESC_SET	BIT_20		/* Set   Reset for Descr */
-#define CSR_FIFO_CLR	BIT_19		/* Clear Reset for FIFO */
-#define CSR_FIFO_SET	BIT_18		/* Set   Reset for FIFO */
-#define CSR_HPI_RUN		BIT_17		/* Release HPI SM */
-#define CSR_HPI_RST		BIT_16		/* Reset   HPI SM to Idle */
-#define CSR_SV_RUN		BIT_15		/* Release Supervisor SM */
-#define CSR_SV_RST		BIT_14		/* Reset   Supervisor SM */
-#define CSR_DREAD_RUN	BIT_13		/* Release Descr Read SM */
-#define CSR_DREAD_RST	BIT_12		/* Reset   Descr Read SM */
-#define CSR_DWRITE_RUN	BIT_11		/* Release Descr Write SM */
-#define CSR_DWRITE_RST	BIT_10		/* Reset   Descr Write SM */
-#define CSR_TRANS_RUN	BIT_9		/* Release Transfer SM */
-#define CSR_TRANS_RST	BIT_8		/* Reset   Transfer SM */
-#define CSR_ENA_POL		BIT_7		/* Enable  Descr Polling */
-#define CSR_DIS_POL		BIT_6		/* Disable Descr Polling */
-#define CSR_STOP		BIT_5		/* Stop  Rx/Tx Queue */
-#define CSR_START		BIT_4		/* Start Rx/Tx Queue */
-#define CSR_IRQ_CL_P	BIT_3		/* (Rx)	Clear Parity IRQ */
-#define CSR_IRQ_CL_B	BIT_2		/* Clear EOB IRQ */
-#define CSR_IRQ_CL_F	BIT_1		/* Clear EOF IRQ */
-#define CSR_IRQ_CL_C	BIT_0		/* Clear ERR IRQ */
-
-#define CSR_SET_RESET	(CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
-						CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
-						CSR_TRANS_RST)
-#define CSR_CLR_RESET	(CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
-						CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
-						CSR_TRANS_RUN)
-
-/*	Q_F				32 bit	Flag Register */
-									/* Bit 31..28:	reserved */
-#define F_ALM_FULL		BIT_27		/* Rx FIFO: almost full */
-#define F_EMPTY			BIT_27		/* Tx FIFO: empty flag */
-#define F_FIFO_EOF		BIT_26		/* Tag (EOF Flag) bit in FIFO */
-#define F_WM_REACHED	BIT_25		/* Watermark reached */
-									/* reserved */
-#define F_FIFO_LEVEL	(0x1fL<<16)	/* Bit 23..16:	# of Qwords in FIFO */
-									/* Bit 15..11: 	reserved */
-#define F_WATER_MARK	0x0007ffL	/* Bit 10.. 0:	Watermark */
-
-/*	Q_T1			32 bit	Test Register 1 */
-/*		Holds four State Machine control Bytes */
-#define SM_CTRL_SV_MSK	(0xffL<<24)	/* Bit 31..24:	Control Supervisor SM */
-#define SM_CTRL_RD_MSK	(0xffL<<16)	/* Bit 23..16:	Control Read Desc SM */
-#define SM_CTRL_WR_MSK	(0xffL<<8)	/* Bit 15.. 8:	Control Write Desc SM */
-#define SM_CTRL_TR_MSK	0xffL		/* Bit	7.. 0:	Control Transfer SM */
-
-/*	Q_T1_TR			 8 bit	Test Register 1 Transfer SM */
-/*	Q_T1_WR			 8 bit	Test Register 1 Write Descriptor SM */
-/*	Q_T1_RD			 8 bit	Test Register 1 Read Descriptor SM */
-/*	Q_T1_SV			 8 bit	Test Register 1 Supervisor SM */
-
-/* The control status byte of each machine looks like ... */
-#define SM_STATE		0xf0	/* Bit 7.. 4:	State which shall be loaded */
-#define SM_LOAD			BIT_3S	/* Load the SM with SM_STATE */
-#define SM_TEST_ON		BIT_2S	/* Switch on SM Test Mode */
-#define SM_TEST_OFF		BIT_1S	/* Go off the Test Mode */
-#define SM_STEP			BIT_0S	/* Step the State Machine */
-/* The encoding of the states is not supported by the Diagnostics Tool */
-
-/*	Q_T2			32 bit	Test Register 2	*/
-								/* Bit 31.. 8:	reserved */
-#define T2_AC_T_ON		BIT_7	/* Address Counter Test Mode on */
-#define T2_AC_T_OFF		BIT_6	/* Address Counter Test Mode off */
-#define T2_BC_T_ON		BIT_5	/* Byte Counter Test Mode on */
-#define T2_BC_T_OFF		BIT_4	/* Byte Counter Test Mode off */
-#define T2_STEP04		BIT_3	/* Inc AC/Dec BC by 4 */
-#define T2_STEP03		BIT_2	/* Inc AC/Dec BC by 3 */
-#define T2_STEP02		BIT_1	/* Inc AC/Dec BC by 2 */
-#define T2_STEP01		BIT_0	/* Inc AC/Dec BC by 1 */
-
-/*	Q_T3			32 bit	Test Register 3	*/
-								/* Bit 31.. 7:	reserved */
-#define T3_MUX_MSK		(7<<4)	/* Bit  6.. 4:	Mux Position */
-								/* Bit  3:	reserved */
-#define T3_VRAM_MSK		7		/* Bit  2.. 0:	Virtual RAM Buffer Address */
-
-/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
-/*	RB_START		32 bit	RAM Buffer Start Address */
-/*	RB_END			32 bit	RAM Buffer End Address */
-/*	RB_WP			32 bit	RAM Buffer Write Pointer */
-/*	RB_RP			32 bit	RAM Buffer Read Pointer */
-/*	RB_RX_UTPP		32 bit	Rx Upper Threshold, Pause Pack */
-/*	RB_RX_LTPP		32 bit	Rx Lower Threshold, Pause Pack */
-/*	RB_RX_UTHP		32 bit	Rx Upper Threshold, High Prio */
-/*	RB_RX_LTHP		32 bit	Rx Lower Threshold, High Prio */
-/*	RB_PC			32 bit	RAM Buffer Packet Counter */
-/*	RB_LEV			32 bit	RAM Buffer Level Register */
-				/* Bit 31..19:	reserved */
-#define RB_MSK	0x0007ffff	/* Bit 18.. 0:	RAM Buffer Pointer Bits */
-
-/*	RB_TST2			 8 bit	RAM Buffer Test Register 2 */
-								/* Bit 7.. 4:	reserved */
-#define RB_PC_DEC		BIT_3S	/* Packet Counter Decrem */
-#define RB_PC_T_ON		BIT_2S	/* Packet Counter Test On */
-#define RB_PC_T_OFF		BIT_1S	/* Packet Counter Tst Off */
-#define RB_PC_INC		BIT_0S	/* Packet Counter Increm */
-
-/*	RB_TST1			 8 bit	RAM Buffer Test Register 1 */
-							/* Bit 7:	reserved */
-#define RB_WP_T_ON		BIT_6S	/* Write Pointer Test On */
-#define RB_WP_T_OFF		BIT_5S	/* Write Pointer Test Off */
-#define RB_WP_INC		BIT_4S	/* Write Pointer Increm */
-								/* Bit 3:	reserved */
-#define RB_RP_T_ON		BIT_2S	/* Read Pointer Test On */
-#define RB_RP_T_OFF		BIT_1S	/* Read Pointer Test Off */
-#define RB_RP_DEC		BIT_0S	/* Read Pointer Decrement */
-
-/*	RB_CTRL			 8 bit	RAM Buffer Control Register */
-								/* Bit 7.. 6:	reserved */
-#define RB_ENA_STFWD	BIT_5S	/* Enable  Store & Forward */
-#define RB_DIS_STFWD	BIT_4S	/* Disable Store & Forward */
-#define RB_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
-#define RB_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
-#define RB_RST_CLR		BIT_1S	/* Clear RAM Buf STM Reset */
-#define RB_RST_SET		BIT_0S	/* Set   RAM Buf STM Reset */
-
-
-/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
-
-/*	RX_MFF_EA		32 bit	Receive MAC FIFO End Address */
-/*	RX_MFF_WP		32 bit 	Receive MAC FIFO Write Pointer */
-/*	RX_MFF_RP		32 bit	Receive MAC FIFO Read Pointer */
-/*	RX_MFF_PC		32 bit	Receive MAC FIFO Packet Counter */
-/*	RX_MFF_LEV		32 bit	Receive MAC FIFO Level */
-/*	TX_MFF_EA		32 bit	Transmit MAC FIFO End Address */
-/*	TX_MFF_WP		32 bit 	Transmit MAC FIFO Write Pointer */
-/*	TX_MFF_WSP		32 bit	Transmit MAC FIFO WR Shadow Pointer */
-/*	TX_MFF_RP		32 bit	Transmit MAC FIFO Read Pointer */
-/*	TX_MFF_PC		32 bit	Transmit MAC FIFO Packet Cnt */
-/*	TX_MFF_LEV		32 bit	Transmit MAC FIFO Level */
-								/* Bit 31.. 6:	reserved */
-#define MFF_MSK			0x007fL	/* Bit	5.. 0:	MAC FIFO Address/Ptr Bits */
-
-/*	RX_MFF_CTRL1	16 bit	Receive MAC FIFO Control Reg 1 */
-								/* Bit 15..14:	reserved */
-#define MFF_ENA_RDY_PAT	BIT_13S		/* Enable  Ready Patch */
-#define MFF_DIS_RDY_PAT	BIT_12S		/* Disable Ready Patch */
-#define MFF_ENA_TIM_PAT	BIT_11S		/* Enable  Timing Patch */
-#define MFF_DIS_TIM_PAT	BIT_10S		/* Disable Timing Patch */
-#define MFF_ENA_ALM_FUL	BIT_9S		/* Enable  AlmostFull Sign */
-#define MFF_DIS_ALM_FUL	BIT_8S		/* Disable AlmostFull Sign */
-#define MFF_ENA_PAUSE	BIT_7S		/* Enable  Pause Signaling */
-#define MFF_DIS_PAUSE	BIT_6S		/* Disable Pause Signaling */
-#define MFF_ENA_FLUSH	BIT_5S		/* Enable  Frame Flushing */
-#define MFF_DIS_FLUSH	BIT_4S		/* Disable Frame Flushing */
-#define MFF_ENA_TIST	BIT_3S		/* Enable  Time Stamp Gener */
-#define MFF_DIS_TIST	BIT_2S		/* Disable Time Stamp Gener */
-#define MFF_CLR_INTIST	BIT_1S		/* Clear IRQ No Time Stamp */
-#define MFF_CLR_INSTAT	BIT_0S		/* Clear IRQ No Status */
-
-#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
-
-/*	TX_MFF_CTRL1	16 bit	Transmit MAC FIFO Control Reg 1 */
-#define MFF_CLR_PERR	BIT_15S		/* Clear Parity Error IRQ */
-								/* Bit 14:	reserved */
-#define MFF_ENA_PKT_REC	BIT_13S		/* Enable  Packet Recovery */
-#define MFF_DIS_PKT_REC BIT_12S		/* Disable Packet Recovery */
-/*	MFF_ENA_TIM_PAT	 (see RX_MFF_CTRL1) Bit 11:	Enable  Timing Patch */
-/*	MFF_DIS_TIM_PAT	 (see RX_MFF_CTRL1) Bit 10:	Disable Timing Patch */
-/*	MFF_ENA_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 9:	Enable  Almost Full Sign */
-/*	MFF_DIS_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 8:	Disable Almost Full Sign */
-#define MFF_ENA_W4E		BIT_7S		/* Enable  Wait for Empty */
-#define MFF_DIS_W4E		BIT_6S		/* Disable Wait for Empty */
-/*	MFF_ENA_FLUSH	 (see RX_MFF_CTRL1) Bit	 5:	Enable  Frame Flushing */
-/*	MFF_DIS_FLUSH	 (see RX_MFF_CTRL1) Bit	 4:	Disable Frame Flushing */
-#define MFF_ENA_LOOPB	BIT_3S		/* Enable  Loopback */
-#define MFF_DIS_LOOPB	BIT_2S		/* Disable Loopback */
-#define MFF_CLR_MAC_RST	BIT_1S		/* Clear XMAC Reset */
-#define MFF_SET_MAC_RST	BIT_0S		/* Set   XMAC Reset */
-
-#define MFF_TX_CTRL_DEF	(MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
-
-/*	RX_MFF_TST2	 	 8 bit	Receive MAC FIFO Test Register 2 */
-/*	TX_MFF_TST2	 	 8 bit	Transmit MAC FIFO Test Register 2 */
-								/* Bit 7:	reserved */
-#define MFF_WSP_T_ON	BIT_6S	/* Tx: Write Shadow Ptr TestOn */
-#define MFF_WSP_T_OFF	BIT_5S	/* Tx: Write Shadow Ptr TstOff */
-#define MFF_WSP_INC		BIT_4S	/* Tx: Write Shadow Ptr Increment */
-#define MFF_PC_DEC		BIT_3S	/* Packet Counter Decrement */
-#define MFF_PC_T_ON		BIT_2S	/* Packet Counter Test On */
-#define MFF_PC_T_OFF	BIT_1S	/* Packet Counter Test Off */
-#define MFF_PC_INC		BIT_0S	/* Packet Counter Increment */
-
-/*	RX_MFF_TST1	 	 8 bit	Receive MAC FIFO Test Register 1 */
-/*	TX_MFF_TST1	 	 8 bit	Transmit MAC FIFO Test Register 1 */
-					/* Bit 7:	reserved */
-#define MFF_WP_T_ON		BIT_6S	/* Write Pointer Test On */
-#define MFF_WP_T_OFF	BIT_5S	/* Write Pointer Test Off */
-#define MFF_WP_INC		BIT_4S	/* Write Pointer Increm */
-							/* Bit 3:	reserved */
-#define MFF_RP_T_ON		BIT_2S	/* Read Pointer Test On */
-#define MFF_RP_T_OFF	BIT_1S	/* Read Pointer Test Off */
-#define MFF_RP_DEC		BIT_0S	/* Read Pointer Decrement */
-
-/*	RX_MFF_CTRL2	 8 bit	Receive MAC FIFO Control Reg 2 */
-/*	TX_MFF_CTRL2	 8 bit	Transmit MAC FIFO Control Reg 2 */
-								/* Bit 7..4:	reserved */
-#define MFF_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
-#define MFF_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
-#define MFF_RST_CLR		BIT_1S	/* Clear MAC FIFO Reset */
-#define MFF_RST_SET		BIT_0S	/* Set   MAC FIFO Reset */
-
-
-/*	Link LED Counter Registers (GENESIS only) */
-
-/*	RX_LED_CTRL		 8 bit	Receive LED Cnt Control Reg */
-/*	TX_LED_CTRL		 8 bit	Transmit LED Cnt Control Reg */
-/*	LNK_SYNC_CTRL	 8 bit	Link Sync Cnt Control Register */
-							/* Bit 7.. 3:	reserved */
-#define LED_START		BIT_2S	/* Start Timer */
-#define LED_STOP		BIT_1S	/* Stop Timer */
-#define LED_STATE		BIT_0S	/* Rx/Tx: LED State, 1=LED on */
-#define LED_CLR_IRQ		BIT_0S	/* Lnk: 	Clear Link IRQ */
-
-/*	RX_LED_TST		 8 bit	Receive LED Cnt Test Register */
-/*	TX_LED_TST		 8 bit	Transmit LED Cnt Test Register */
-/*	LNK_SYNC_TST	 8 bit	Link Sync Cnt Test Register */
-							/* Bit 7.. 3:	reserved */
-#define LED_T_ON		BIT_2S	/* LED Counter Test mode On */
-#define LED_T_OFF		BIT_1S	/* LED Counter Test mode Off */
-#define LED_T_STEP		BIT_0S	/* LED Counter Step */
-
-/*	LNK_LED_REG	 	 8 bit	Link LED Register */
-								/* Bit 7.. 6:	reserved */
-#define LED_BLK_ON		BIT_5S	/* Link LED Blinking On */
-#define LED_BLK_OFF		BIT_4S	/* Link LED Blinking Off */
-#define LED_SYNC_ON		BIT_3S	/* Use Sync Wire to switch LED */
-#define LED_SYNC_OFF	BIT_2S	/* Disable Sync Wire Input */
-#define LED_ON			BIT_1S	/* switch LED on */
-#define LED_OFF			BIT_0S	/* switch LED off */
-
-/*	Receive and Transmit GMAC FIFO Registers (YUKON only) */
-
-/*	RX_GMF_EA		32 bit	Rx GMAC FIFO End Address */
-/*	RX_GMF_AF_THR	32 bit	Rx GMAC FIFO Almost Full Thresh. */
-/*	RX_GMF_WP		32 bit 	Rx GMAC FIFO Write Pointer */
-/*	RX_GMF_WLEV		32 bit 	Rx GMAC FIFO Write Level */
-/*	RX_GMF_RP		32 bit 	Rx GMAC FIFO Read Pointer */
-/*	RX_GMF_RLEV		32 bit 	Rx GMAC FIFO Read Level */
-/*	TX_GMF_EA		32 bit	Tx GMAC FIFO End Address */
-/*	TX_GMF_AE_THR	32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
-/*	TX_GMF_WP		32 bit 	Tx GMAC FIFO Write Pointer */
-/*	TX_GMF_WSP		32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
-/*	TX_GMF_WLEV		32 bit 	Tx GMAC FIFO Write Level */
-/*	TX_GMF_RP		32 bit 	Tx GMAC FIFO Read Pointer */
-/*	TX_GMF_RSTP		32 bit 	Tx GMAC FIFO Restart Pointer */
-/*	TX_GMF_RLEV		32 bit 	Tx GMAC FIFO Read Level */
-
-/*	RX_GMF_CTRL_T	32 bit	Rx GMAC FIFO Control/Test */
-						/* Bits 31..15:	reserved */
-#define GMF_WP_TST_ON	BIT_14		/* Write Pointer Test On */
-#define GMF_WP_TST_OFF	BIT_13		/* Write Pointer Test Off */
-#define GMF_WP_STEP		BIT_12		/* Write Pointer Step/Increment */
-						/* Bit 11:	reserved */
-#define GMF_RP_TST_ON	BIT_10		/* Read Pointer Test On */
-#define GMF_RP_TST_OFF	BIT_9		/* Read Pointer Test Off */
-#define GMF_RP_STEP		BIT_8		/* Read Pointer Step/Increment */
-#define GMF_RX_F_FL_ON	BIT_7		/* Rx FIFO Flush Mode On */
-#define GMF_RX_F_FL_OFF	BIT_6		/* Rx FIFO Flush Mode Off */
-#define GMF_CLI_RX_FO	BIT_5		/* Clear IRQ Rx FIFO Overrun */
-#define GMF_CLI_RX_FC	BIT_4		/* Clear IRQ Rx Frame Complete */
-#define GMF_OPER_ON		BIT_3		/* Operational Mode On */
-#define GMF_OPER_OFF	BIT_2		/* Operational Mode Off */
-#define GMF_RST_CLR		BIT_1		/* Clear GMAC FIFO Reset */
-#define GMF_RST_SET		BIT_0		/* Set   GMAC FIFO Reset */
-
-/*	TX_GMF_CTRL_T	32 bit	Tx GMAC FIFO Control/Test */
-						/* Bits 31..19:	reserved */
-#define GMF_WSP_TST_ON	BIT_18		/* Write Shadow Pointer Test On */
-#define GMF_WSP_TST_OFF	BIT_17		/* Write Shadow Pointer Test Off */
-#define GMF_WSP_STEP	BIT_16		/* Write Shadow Pointer Step/Increment */
-						/* Bits 15..7: same as for RX_GMF_CTRL_T */
-#define GMF_CLI_TX_FU	BIT_6		/* Clear IRQ Tx FIFO Underrun */
-#define GMF_CLI_TX_FC	BIT_5		/* Clear IRQ Tx Frame Complete */
-#define GMF_CLI_TX_PE	BIT_4		/* Clear IRQ Tx Parity Error */
-						/* Bits 3..0: same as for RX_GMF_CTRL_T */
-
-#define GMF_RX_CTRL_DEF		(GMF_OPER_ON | GMF_RX_F_FL_ON)
-#define GMF_TX_CTRL_DEF		GMF_OPER_ON
-
-#define RX_GMF_FL_THR_DEF	0x0a	/* Rx GMAC FIFO Flush Threshold default */
-
-/*	GMAC_TI_ST_CTRL	 8 bit	Time Stamp Timer Ctrl Reg (YUKON only) */
-								/* Bit 7.. 3:	reserved */
-#define GMT_ST_START	BIT_2S		/* Start Time Stamp Timer */
-#define GMT_ST_STOP		BIT_1S		/* Stop  Time Stamp Timer */
-#define GMT_ST_CLR_IRQ	BIT_0S		/* Clear Time Stamp Timer IRQ */
-
-/*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
-						/* Bits 31.. 8:	reserved */
-#define GMC_H_BURST_ON	BIT_7		/* Half Duplex Burst Mode On */
-#define GMC_H_BURST_OFF	BIT_6		/* Half Duplex Burst Mode Off */
-#define GMC_F_LOOPB_ON	BIT_5		/* FIFO Loopback On */
-#define GMC_F_LOOPB_OFF	BIT_4		/* FIFO Loopback Off */
-#define GMC_PAUSE_ON	BIT_3		/* Pause On */
-#define GMC_PAUSE_OFF	BIT_2		/* Pause Off */
-#define GMC_RST_CLR		BIT_1		/* Clear GMAC Reset */
-#define GMC_RST_SET		BIT_0		/* Set   GMAC Reset */
-
-/*	GPHY_CTRL		32 bit	GPHY Control Reg (YUKON only) */
-						/* Bits 31..29:	reserved */
-#define GPC_SEL_BDT		BIT_28	/* Select Bi-Dir. Transfer for MDC/MDIO */
-#define GPC_INT_POL_HI	BIT_27	/* IRQ Polarity is Active HIGH */
-#define GPC_75_OHM		BIT_26	/* Use 75 Ohm Termination instead of 50 */
-#define GPC_DIS_FC		BIT_25	/* Disable Automatic Fiber/Copper Detection */
-#define GPC_DIS_SLEEP	BIT_24	/* Disable Energy Detect */
-#define GPC_HWCFG_M_3	BIT_23	/* HWCFG_MODE[3] */
-#define GPC_HWCFG_M_2	BIT_22	/* HWCFG_MODE[2] */
-#define GPC_HWCFG_M_1	BIT_21	/* HWCFG_MODE[1] */
-#define GPC_HWCFG_M_0	BIT_20	/* HWCFG_MODE[0] */
-#define GPC_ANEG_0		BIT_19	/* ANEG[0] */
-#define GPC_ENA_XC		BIT_18	/* Enable MDI crossover */
-#define GPC_DIS_125		BIT_17	/* Disable 125 MHz clock */
-#define GPC_ANEG_3		BIT_16	/* ANEG[3] */
-#define GPC_ANEG_2		BIT_15	/* ANEG[2] */
-#define GPC_ANEG_1		BIT_14	/* ANEG[1] */
-#define GPC_ENA_PAUSE	BIT_13	/* Enable Pause (SYM_OR_REM) */
-#define GPC_PHYADDR_4	BIT_12	/* Bit 4 of Phy Addr */
-#define GPC_PHYADDR_3	BIT_11	/* Bit 3 of Phy Addr */
-#define GPC_PHYADDR_2	BIT_10	/* Bit 2 of Phy Addr */
-#define GPC_PHYADDR_1	BIT_9	/* Bit 1 of Phy Addr */
-#define GPC_PHYADDR_0	BIT_8	/* Bit 0 of Phy Addr */
-						/* Bits  7..2:	reserved */
-#define GPC_RST_CLR		BIT_1	/* Clear GPHY Reset */
-#define GPC_RST_SET		BIT_0	/* Set   GPHY Reset */
-
-#define GPC_HWCFG_GMII_COP	(GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \
-							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_HWCFG_GMII_FIB	(				 GPC_HWCFG_M_2 | \
-							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_ANEG_ADV_ALL_M	(GPC_ANEG_3 | GPC_ANEG_2 | \
-							 GPC_ANEG_1 | GPC_ANEG_0)
-
-/* forced speed and duplex mode (don't mix with other ANEG bits) */
-#define GPC_FRC10MBIT_HALF	0
-#define GPC_FRC10MBIT_FULL	GPC_ANEG_0
-#define GPC_FRC100MBIT_HALF	GPC_ANEG_1
-#define GPC_FRC100MBIT_FULL	(GPC_ANEG_0 | GPC_ANEG_1)
-
-/* auto-negotiation with limited advertised speeds */
-/* mix only with master/slave settings (for copper) */
-#define GPC_ADV_1000_HALF	GPC_ANEG_2
-#define GPC_ADV_1000_FULL	GPC_ANEG_3
-#define GPC_ADV_ALL			(GPC_ANEG_2 | GPC_ANEG_3)
-
-/* master/slave settings */
-/* only for copper with 1000 Mbps */
-#define GPC_FORCE_MASTER	0
-#define GPC_FORCE_SLAVE		GPC_ANEG_0
-#define GPC_PREF_MASTER		GPC_ANEG_1
-#define GPC_PREF_SLAVE		(GPC_ANEG_1 | GPC_ANEG_0)
-
-/*	GMAC_IRQ_SRC	 8 bit	GMAC Interrupt Source Reg (YUKON only) */
-/*	GMAC_IRQ_MSK	 8 bit	GMAC Interrupt Mask   Reg (YUKON only) */
-#define GM_IS_TX_CO_OV	BIT_5		/* Transmit Counter Overflow IRQ */
-#define GM_IS_RX_CO_OV	BIT_4		/* Receive Counter Overflow IRQ */
-#define GM_IS_TX_FF_UR	BIT_3		/* Transmit FIFO Underrun */
-#define GM_IS_TX_COMPL	BIT_2		/* Frame Transmission Complete */
-#define GM_IS_RX_FF_OR	BIT_1		/* Receive FIFO Overrun */
-#define GM_IS_RX_COMPL	BIT_0		/* Frame Reception Complete */
-
-#define GMAC_DEF_MSK	(GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \
-						GM_IS_TX_FF_UR)
-
-/*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
-						/* Bits 15.. 2:	reserved */
-#define GMLC_RST_CLR	BIT_1S		/* Clear GMAC Link Reset */
-#define GMLC_RST_SET	BIT_0S		/* Set   GMAC Link Reset */
-
-
-/*	WOL_CTRL_STAT	16 bit	WOL Control/Status Reg */
-#define WOL_CTL_LINK_CHG_OCC			BIT_15S
-#define WOL_CTL_MAGIC_PKT_OCC			BIT_14S
-#define WOL_CTL_PATTERN_OCC				BIT_13S
-
-#define WOL_CTL_CLEAR_RESULT			BIT_12S
-
-#define WOL_CTL_ENA_PME_ON_LINK_CHG		BIT_11S
-#define WOL_CTL_DIS_PME_ON_LINK_CHG		BIT_10S
-#define WOL_CTL_ENA_PME_ON_MAGIC_PKT	BIT_9S
-#define WOL_CTL_DIS_PME_ON_MAGIC_PKT	BIT_8S
-#define WOL_CTL_ENA_PME_ON_PATTERN		BIT_7S
-#define WOL_CTL_DIS_PME_ON_PATTERN		BIT_6S
-
-#define WOL_CTL_ENA_LINK_CHG_UNIT		BIT_5S
-#define WOL_CTL_DIS_LINK_CHG_UNIT		BIT_4S
-#define WOL_CTL_ENA_MAGIC_PKT_UNIT		BIT_3S
-#define WOL_CTL_DIS_MAGIC_PKT_UNIT		BIT_2S
-#define WOL_CTL_ENA_PATTERN_UNIT		BIT_1S
-#define WOL_CTL_DIS_PATTERN_UNIT		BIT_0S
-
-#define WOL_CTL_DEFAULT				\
-	(WOL_CTL_DIS_PME_ON_LINK_CHG |	\
-	WOL_CTL_DIS_PME_ON_PATTERN |	\
-	WOL_CTL_DIS_PME_ON_MAGIC_PKT |	\
-	WOL_CTL_DIS_LINK_CHG_UNIT |		\
-	WOL_CTL_DIS_PATTERN_UNIT |		\
-	WOL_CTL_DIS_MAGIC_PKT_UNIT)
-
-/*	WOL_MATCH_CTL	 8 bit	WOL Match Control Reg */
-#define WOL_CTL_PATT_ENA(x)				(BIT_0 << (x))
-
-#define SK_NUM_WOL_PATTERN		7
-#define SK_PATTERN_PER_WORD		4
-#define SK_BITMASK_PATTERN		7
-#define SK_POW_PATTERN_LENGTH	128
-
-#define WOL_LENGTH_MSK		0x7f
-#define WOL_LENGTH_SHIFT	8
-
-
-/* Receive and Transmit Descriptors ******************************************/
-
-/* Transmit Descriptor struct */
-typedef	struct s_HwTxd {
-	SK_U32 volatile	TxCtrl;	/* Transmit Buffer Control Field */
-	SK_U32	TxNext;			/* Physical Address Pointer to the next TxD */
-	SK_U32	TxAdrLo;		/* Physical Tx Buffer Address lower dword */
-	SK_U32	TxAdrHi;		/* Physical Tx Buffer Address upper dword */
-	SK_U32	TxStat;			/* Transmit Frame Status Word */
-#ifndef	SK_USE_REV_DESC
-	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
-	SK_U16	TxRes1;			/* 16 bit reserved field */
-	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
-	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
-#else	/* SK_USE_REV_DESC */
-	SK_U16	TxRes1;			/* 16 bit reserved field */
-	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
-	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
-	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
-#endif	/* SK_USE_REV_DESC */
-	SK_U32  TxRes2;			/* 32 bit reserved field */
-} SK_HWTXD;
-
-/* Receive Descriptor struct */
-typedef	struct s_HwRxd {
-	SK_U32 volatile RxCtrl;	/* Receive Buffer Control Field */
-	SK_U32	RxNext;			/* Physical Address Pointer to the next RxD */
-	SK_U32	RxAdrLo;		/* Physical Rx Buffer Address lower dword */
-	SK_U32	RxAdrHi;		/* Physical Rx Buffer Address upper dword */
-	SK_U32	RxStat;			/* Receive Frame Status Word */
-	SK_U32	RxTiSt;			/* Receive Time Stamp (from XMAC on GENESIS) */
-#ifndef	SK_USE_REV_DESC
-	SK_U16	RxTcpSum1;		/* TCP Checksum 1 */
-	SK_U16	RxTcpSum2;		/* TCP Checksum 2 */
-	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
-	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
-#else	/* SK_USE_REV_DESC */
-	SK_U16	RxTcpSum2;		/* TCP Checksum 2 */
-	SK_U16	RxTcpSum1;		/* TCP Checksum 1 */
-	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
-	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
-#endif	/* SK_USE_REV_DESC */
-} SK_HWRXD;
-
-/*
- * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
- * should set the define SK_USE_REV_DESC.
- * Structures are 'normaly' not endianess dependent. But in
- * this case the SK_U16 fields are bound to bit positions inside the
- * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord.
- * The bit positions inside a DWord are of course endianess dependent and
- * swaps if the DWord is swapped by the hardware.
- */
-
-
-/* Descriptor Bit Definition */
-/*	TxCtrl		Transmit Buffer Control Field */
-/*	RxCtrl		Receive  Buffer Control Field */
-#define BMU_OWN			BIT_31	/* OWN bit: 0=host/1=BMU */
-#define BMU_STF			BIT_30	/* Start of Frame */
-#define BMU_EOF			BIT_29	/* End of Frame */
-#define BMU_IRQ_EOB		BIT_28	/* Req "End of Buffer" IRQ */
-#define BMU_IRQ_EOF		BIT_27	/* Req "End of Frame" IRQ */
-/* TxCtrl specific bits */
-#define BMU_STFWD		BIT_26	/* (Tx)	Store & Forward Frame */
-#define BMU_NO_FCS		BIT_25	/* (Tx) Disable MAC FCS (CRC) generation */
-#define BMU_SW			BIT_24	/* (Tx)	1 bit res. for SW use */
-/* RxCtrl specific bits */
-#define BMU_DEV_0		BIT_26	/* (Rx)	Transfer data to Dev0 */
-#define BMU_STAT_VAL	BIT_25	/* (Rx)	Rx Status Valid */
-#define BMU_TIST_VAL	BIT_24	/* (Rx)	Rx TimeStamp Valid */
-								/* Bit 23..16:	BMU Check Opcodes */
-#define BMU_CHECK		(0x55L<<16)	/* Default BMU check */
-#define BMU_TCP_CHECK	(0x56L<<16)	/* Descr with TCP ext */
-#define BMU_UDP_CHECK	(0x57L<<16)	/* Descr with UDP ext (YUKON only) */
-#define BMU_BBC			0xffffL	/* Bit 15.. 0:	Buffer Byte Counter */
-
-/*	TxStat		Transmit Frame Status Word */
-/*	RxStat		Receive Frame Status Word */
-/*
- *Note: TxStat is reserved for ASIC loopback mode only
- *
- *	The Bits of the Status words are defined in xmac_ii.h
- *	(see XMR_FS bits)
- */
-
-/* macros ********************************************************************/
-
-/* Receive and Transmit Queues */
-#define Q_R1	0x0000		/* Receive Queue 1 */
-#define Q_R2	0x0080		/* Receive Queue 2 */
-#define Q_XS1	0x0200		/* Synchronous Transmit Queue 1 */
-#define Q_XA1	0x0280		/* Asynchronous Transmit Queue 1 */
-#define Q_XS2	0x0300		/* Synchronous Transmit Queue 2 */
-#define Q_XA2	0x0380		/* Asynchronous Transmit Queue 2 */
-
-/*
- *	Macro Q_ADDR()
- *
- *	Use this macro to access the Receive and Transmit Queue Registers.
- *
- * para:
- *	Queue	Queue to access.
- *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- *	Offs	Queue register offset.
- *				Values: Q_D, Q_DA_L ... Q_T2, Q_T3
- *
- * usage	SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal)
- */
-#define Q_ADDR(Queue, Offs)	(B8_Q_REGS + (Queue) + (Offs))
-
-/*
- *	Macro RB_ADDR()
- *
- *	Use this macro to access the RAM Buffer Registers.
- *
- * para:
- *	Queue	Queue to access.
- *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- *	Offs	Queue register offset.
- *				Values: RB_START, RB_END ... RB_LEV, RB_CTRL
- *
- * usage	SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal)
- */
-#define RB_ADDR(Queue, Offs)	(B16_RAM_REGS + (Queue) + (Offs))
-
-
-/* MAC Related Registers */
-#define MAC_1		0	/* belongs to the port near the slot */
-#define MAC_2		1	/* belongs to the port far away from the slot */
-
-/*
- *	Macro MR_ADDR()
- *
- *	Use this macro to access a MAC Related Registers inside the ASIC.
- *
- * para:
- *	Mac		MAC to access.
- *				Values: MAC_1, MAC_2
- *	Offs	MAC register offset.
- *				Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
- *						TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
- *
- * usage	SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
- */
-#define MR_ADDR(Mac, Offs)	(((Mac) << 7) + (Offs))
-
-#ifdef	SK_LITTLE_ENDIAN
-#define XM_WORD_LO	0
-#define XM_WORD_HI	1
-#else	/* !SK_LITTLE_ENDIAN */
-#define XM_WORD_LO	1
-#define XM_WORD_HI	0
-#endif	/* !SK_LITTLE_ENDIAN */
-
-
-/*
- * macros to access the XMAC (GENESIS only)
- *
- * XM_IN16(),		to read a 16 bit register (e.g. XM_MMU_CMD)
- * XM_OUT16(),		to write a 16 bit register (e.g. XM_MMU_CMD)
- * XM_IN32(),		to read a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_OUT32(),		to write a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_INADDR(),		to read a network address register (e.g. XM_SRC_CHK)
- * XM_OUTADDR(),	to write a network address register (e.g. XM_SRC_CHK)
- * XM_INHASH(),		to read the XM_HSM_CHK register
- * XM_OUTHASH()		to write the XM_HSM_CHK register
- *
- * para:
- *	Mac		XMAC to access		values: MAC_1 or MAC_2
- *	IoC		I/O context needed for SK I/O macros
- *	Reg		XMAC Register to read or write
- *	(p)Val	Value or pointer to the value which should be read or written
- *
- * usage:	XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value);
- */
-
-#define XMA(Mac, Reg)									\
-	((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
-
-#define XM_IN16(IoC, Mac, Reg, pVal)					\
-	SK_IN16((IoC), XMA((Mac), (Reg)), (pVal))
-
-#define XM_OUT16(IoC, Mac, Reg, Val)					\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (Val))
-
-#define XM_IN32(IoC, Mac, Reg, pVal) {					\
-	SK_IN16((IoC), XMA((Mac), (Reg)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]);		\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]);		\
-}
-
-#define XM_OUT32(IoC, Mac, Reg, Val) {										\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
-
-#define XM_INADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define XM_OUTADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff) |				\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff) |				\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff) |				\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-}
-
-#define XM_INHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word);			\
-	pByte[6] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define XM_OUTHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff)|					\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff)|					\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff)|					\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16)		\
-		(((SK_U16)(pByte[6]) & 0x00ff)|					\
-		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
-}
-
-/*
- * macros to access the GMAC (YUKON only)
- *
- * GM_IN16(),		to read  a 16 bit register (e.g. GM_GP_STAT)
- * GM_OUT16(),		to write a 16 bit register (e.g. GM_GP_CTRL)
- * GM_IN32(),		to read  a 32 bit register (e.g. GM_)
- * GM_OUT32(),		to write a 32 bit register (e.g. GM_)
- * GM_INADDR(),		to read  a network address register (e.g. GM_SRC_ADDR_1L)
- * GM_OUTADDR(),	to write a network address register (e.g. GM_SRC_ADDR_2L)
- * GM_INHASH(),		to read  the GM_MC_ADDR_H1 register
- * GM_OUTHASH()		to write the GM_MC_ADDR_H1 register
- *
- * para:
- *	Mac		GMAC to access		values: MAC_1 or MAC_2
- *	IoC		I/O context needed for SK I/O macros
- *	Reg		GMAC Register to read or write
- *	(p)Val	Value or pointer to the value which should be read or written
- *
- * usage:	GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value);
- */
-
-#define GMA(Mac, Reg)									\
-	((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
-
-#define GM_IN16(IoC, Mac, Reg, pVal)					\
-	SK_IN16((IoC), GMA((Mac), (Reg)), (pVal))
-
-#define GM_OUT16(IoC, Mac, Reg, Val)					\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (Val))
-
-#define GM_IN32(IoC, Mac, Reg, pVal) {					\
-	SK_IN16((IoC), GMA((Mac), (Reg)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]);		\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]);		\
-}
-
-#define GM_OUT32(IoC, Mac, Reg, Val) {										\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-#define GM_INADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define GM_OUTADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff) |				\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff) |				\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff) |				\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-}
-
-#define GM_INHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word);		\
-	pByte[6] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define GM_OUTHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff)|					\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff)|					\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff)|					\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16)		\
-		(((SK_U16)(pByte[6]) & 0x00ff)|					\
-		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
-}
-
-/*
- * Different MAC Types
- */
-#define SK_MAC_XMAC		0	/* Xaqti XMAC II */
-#define SK_MAC_GMAC		1	/* Marvell GMAC */
-
-/*
- * Different PHY Types
- */
-#define SK_PHY_XMAC			0	/* integrated in XMAC II */
-#define SK_PHY_BCOM			1	/* Broadcom BCM5400 */
-#define SK_PHY_LONE			2	/* Level One LXT1000 */
-#define SK_PHY_NAT			3	/* National DP83891 */
-#define SK_PHY_MARV_COPPER	4	/* Marvell 88E1011S */
-#define SK_PHY_MARV_FIBER	5	/* Marvell 88E1011S working on fiber */
-
-/*
- * PHY addresses (bits 12..8 of PHY address reg)
- */
-#define PHY_ADDR_XMAC	(0<<8)
-#define PHY_ADDR_BCOM	(1<<8)
-#define PHY_ADDR_LONE	(3<<8)
-#define PHY_ADDR_NAT	(0<<8)
-
-/* GPHY address (bits 15..11 of SMI control reg) */
-#define PHY_ADDR_MARV	0
-
-/*
- * macros to access the PHY
- *
- * PHY_READ()		read a 16 bit value from the PHY
- * PHY_WRITE()		write a 16 bit value to the PHY
- *
- * para:
- * 	IoC		I/O context needed for SK I/O macros
- * 	pPort	Pointer to port struct for PhyAddr
- * 	Mac		XMAC to access		values: MAC_1 or MAC_2
- * 	PhyReg	PHY Register to read or write
- * 	(p)Val	Value or pointer to the value which should be read or
- *			written.
- *
- * usage:	PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
- * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
- *          comes back. This is checked in DEBUG mode.
- */
-#ifndef DEBUG
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
-	SK_U16 Mmu;  														\
-																		\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
-		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
-	}  																	\
-}
-#else
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
-	SK_U16 Mmu;  														\
-	int __i = 0;														\
-																		\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-			__i++;														\
-			if (__i > 100000) {											\
-				SK_DBG_PRINTF("*****************************\n");		\
-				SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n");		\
-				SK_DBG_PRINTF("*****************************\n");		\
-				break;													\
-			}															\
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
-		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
-	}  																	\
-}
-#endif /* DEBUG */
-
-#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) {						\
-	SK_U16 Mmu;															\
-																		\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
-	}  																	\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
-	}  																	\
-}
-
-/*
- *	Macro PCI_C()
- *
- *	Use this macro to access PCI config register from the I/O space.
- *
- * para:
- *	Addr	PCI configuration register to access.
- *			Values:	PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
- *
- * usage	SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal);
- */
-#define PCI_C(Addr)	(B7_CFG_SPC + (Addr))	/* PCI Config Space */
-
-/*
- *	Macro SK_HW_ADDR(Base, Addr)
- *
- *	Calculates the effective HW address
- *
- * para:
- *	Base	I/O or memory base address
- *	Addr	Address offset
- *
- * usage:	May be used in SK_INxx and SK_OUTxx macros
- *		#define SK_IN8(pAC, Addr, pVal) ...\
- *			*pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
- */
-#ifdef SK_MEM_MAPPED_IO
-#define SK_HW_ADDR(Base, Addr)	((Base) + (Addr))
-#else  /* SK_MEM_MAPPED_IO */
-#define SK_HW_ADDR(Base, Addr)	\
-			((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0)))
-#endif /* SK_MEM_MAPPED_IO */
-
-#define SZ_LONG	(sizeof(SK_U32))
-
-/*
- *	Macro SK_HWAC_LINK_LED()
- *
- *	Use this macro to set the link LED mode.
- * para:
- *	pAC		Pointer to adapter context struct
- *	IoC		I/O context needed for SK I/O macros
- *  Port	Port number
- *	Mode	Mode to set for this LED
- */
-#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
-
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKGEHW_H */
diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
deleted file mode 100644
index e6b0016..0000000
--- a/drivers/net/sk98lin/h/skgehwt.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Name:	skhwt.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.7 $
- * Date:	$Date: 2003/09/16 12:55:08 $
- * Purpose:	Defines for the hardware timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEHWT.H	contains all defines and types for the timer functions
- */
-
-#ifndef	_SKGEHWT_H_
-#define _SKGEHWT_H_
-
-/*
- * SK Hardware Timer
- * - needed wherever the HWT module is used
- * - use in Adapters context name pAC->Hwt
- */
-typedef	struct s_Hwt {
-	SK_U32		TStart;	/* HWT start */
-	SK_U32		TStop;	/* HWT stop */
-	int		TActive;	/* HWT: flag : active/inactive */
-} SK_HWT;
-
-extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time);
-extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc);
-extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc);
-#endif	/* _SKGEHWT_H_ */
diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h
deleted file mode 100644
index d9b6f6d..0000000
--- a/drivers/net/sk98lin/h/skgei2c.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgei2c.h
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.25 $
- * Date:	$Date: 2003/10/20 09:06:05 $
- * Purpose:	Special defines for TWSI
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEI2C.H	contains all SK-98xx specific defines for the TWSI handling
- */
-
-#ifndef _INC_SKGEI2C_H_
-#define _INC_SKGEI2C_H_
-
-/*
- * Macros to access the B2_I2C_CTRL
- */
-#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
-	SK_OUT32(IoC, B2_I2C_CTRL,\
-		(flag ? 0x80000000UL : 0x0L) | \
-		(((SK_U32)reg << 16) & I2C_ADDR) | \
-		(((SK_U32)dev << 9) & I2C_DEV_SEL) | \
-		(dev_size & I2C_DEV_SIZE) | \
-		((burst << 4) & I2C_BURST_LEN))
-
-#define SK_I2C_STOP(IoC) {				\
-	SK_U32	I2cCtrl;				\
-	SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl);		\
-	SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP);	\
-}
-
-#define SK_I2C_GET_CTL(IoC, pI2cCtrl)	SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
-
-/*
- * Macros to access the TWSI SW Registers
- */
-#define SK_I2C_SET_BIT(IoC, SetBits) {			\
-	SK_U8	OrgBits;				\
-	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
-	SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits));	\
-}
-
-#define SK_I2C_CLR_BIT(IoC, ClrBits) {			\
-	SK_U8	OrgBits;				\
-	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
-	SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits)));	\
-}
-
-#define SK_I2C_GET_SW(IoC, pI2cSw)	SK_IN8(IoC, B2_I2C_SW, pI2cSw)
-
-/*
- * define the possible sensor states
- */
-#define	SK_SEN_IDLE		0	/* Idle: sensor not read */
-#define	SK_SEN_VALUE	1	/* Value Read cycle */
-#define	SK_SEN_VALEXT	2	/* Extended Value Read cycle */
-
-/*
- * Conversion factor to convert read Voltage sensor to milli Volt
- * Conversion factor to convert read Temperature sensor to 10th degree Celsius
- */
-#define	SK_LM80_VT_LSB		22	/* 22mV LSB resolution */
-#define	SK_LM80_TEMP_LSB	10	/* 1 degree LSB resolution */
-#define	SK_LM80_TEMPEXT_LSB	 5	/* 0.5 degree LSB resolution for ext. val. */
-
-/*
- * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
- * assuming: 6500rpm, 4 pulses, divisor 1
- */
-#define SK_LM80_FAN_FAKTOR	((22500L*60)/(1*2))
-
-/*
- * Define sensor management data
- * Maximum is reached on Genesis copper dual port and Yukon-64
- * Board specific maximum is in pAC->I2c.MaxSens
- */
-#define	SK_MAX_SENSORS	8	/* maximal no. of installed sensors */
-#define	SK_MIN_SENSORS	5	/* minimal no. of installed sensors */
-
-/*
- * To watch the state machine (SM) use the timer in two ways
- * instead of one as hitherto
- */
-#define	SK_TIMER_WATCH_SM		0	/* Watch the SM to finish in a spec. time */
-#define	SK_TIMER_NEW_GAUGING	1	/* Start a new gauging when timer expires */
-
-/*
- * Defines for the individual thresholds
- */
-
-/* Temperature sensor */
-#define	SK_SEN_TEMP_HIGH_ERR	800	/* Temperature High Err  Threshold */
-#define	SK_SEN_TEMP_HIGH_WARN	700	/* Temperature High Warn Threshold */
-#define	SK_SEN_TEMP_LOW_WARN	100	/* Temperature Low  Warn Threshold */
-#define	SK_SEN_TEMP_LOW_ERR		  0	/* Temperature Low  Err  Threshold */
-
-/* VCC which should be 5 V */
-#define	SK_SEN_PCI_5V_HIGH_ERR		5588	/* Voltage PCI High Err  Threshold */
-#define	SK_SEN_PCI_5V_HIGH_WARN		5346	/* Voltage PCI High Warn Threshold */
-#define	SK_SEN_PCI_5V_LOW_WARN		4664	/* Voltage PCI Low  Warn Threshold */
-#define	SK_SEN_PCI_5V_LOW_ERR		4422	/* Voltage PCI Low  Err  Threshold */
-
-/*
- * VIO may be 5 V or 3.3 V. Initialization takes two parts:
- * 1. Initialize lowest lower limit and highest higher limit.
- * 2. After the first value is read correct the upper or the lower limit to
- *    the appropriate C constant.
- *
- * Warning limits are +-5% of the exepected voltage.
- * Error limits are +-10% of the expected voltage.
- */
-
-/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
-
-#define	SK_SEN_PCI_IO_5V_HIGH_ERR	5566	/* + 10% V PCI-IO High Err Threshold */
-#define	SK_SEN_PCI_IO_5V_HIGH_WARN	5324	/* +  5% V PCI-IO High Warn Threshold */
-					/*		5000	mVolt */
-#define	SK_SEN_PCI_IO_5V_LOW_WARN	4686	/* -  5% V PCI-IO Low Warn Threshold */
-#define	SK_SEN_PCI_IO_5V_LOW_ERR	4444	/* - 10% V PCI-IO Low Err Threshold */
-
-#define	SK_SEN_PCI_IO_RANGE_LIMITER	4000	/* 4000 mV range delimiter */
-
-/* correction values for the second pass */
-#define	SK_SEN_PCI_IO_3V3_HIGH_ERR	3850	/* + 15% V PCI-IO High Err Threshold */
-#define	SK_SEN_PCI_IO_3V3_HIGH_WARN	3674	/* + 10% V PCI-IO High Warn Threshold */
-					/*		3300	mVolt */
-#define	SK_SEN_PCI_IO_3V3_LOW_WARN	2926	/* - 10% V PCI-IO Low Warn Threshold */
-#define	SK_SEN_PCI_IO_3V3_LOW_ERR	2772	/* - 15% V PCI-IO Low Err  Threshold */
-
-/*
- * VDD voltage
- */
-#define	SK_SEN_VDD_HIGH_ERR		3630	/* Voltage ASIC High Err  Threshold */
-#define	SK_SEN_VDD_HIGH_WARN	3476	/* Voltage ASIC High Warn Threshold */
-#define	SK_SEN_VDD_LOW_WARN		3146	/* Voltage ASIC Low  Warn Threshold */
-#define	SK_SEN_VDD_LOW_ERR		2970	/* Voltage ASIC Low  Err  Threshold */
-
-/*
- * PHY PLL 3V3 voltage
- */
-#define	SK_SEN_PLL_3V3_HIGH_ERR		3630	/* Voltage PMA High Err  Threshold */
-#define	SK_SEN_PLL_3V3_HIGH_WARN	3476	/* Voltage PMA High Warn Threshold */
-#define	SK_SEN_PLL_3V3_LOW_WARN		3146	/* Voltage PMA Low  Warn Threshold */
-#define	SK_SEN_PLL_3V3_LOW_ERR		2970	/* Voltage PMA Low  Err  Threshold */
-
-/*
- * VAUX (YUKON only)
- */
-#define	SK_SEN_VAUX_3V3_HIGH_ERR	3630	/* Voltage VAUX High Err Threshold */
-#define	SK_SEN_VAUX_3V3_HIGH_WARN	3476	/* Voltage VAUX High Warn Threshold */
-#define	SK_SEN_VAUX_3V3_LOW_WARN	3146	/* Voltage VAUX Low Warn Threshold */
-#define	SK_SEN_VAUX_3V3_LOW_ERR		2970	/* Voltage VAUX Low Err Threshold */
-#define	SK_SEN_VAUX_0V_WARN_ERR		   0	/* if VAUX not present */
-#define	SK_SEN_VAUX_RANGE_LIMITER	1000	/* 1000 mV range delimiter */
-
-/*
- * PHY 2V5 voltage
- */
-#define	SK_SEN_PHY_2V5_HIGH_ERR		2750	/* Voltage PHY High Err Threshold */
-#define	SK_SEN_PHY_2V5_HIGH_WARN	2640	/* Voltage PHY High Warn Threshold */
-#define	SK_SEN_PHY_2V5_LOW_WARN		2376	/* Voltage PHY Low Warn Threshold */
-#define	SK_SEN_PHY_2V5_LOW_ERR		2222	/* Voltage PHY Low Err Threshold */
-
-/*
- * ASIC Core 1V5 voltage (YUKON only)
- */
-#define	SK_SEN_CORE_1V5_HIGH_ERR	1650	/* Voltage ASIC Core High Err Threshold */
-#define	SK_SEN_CORE_1V5_HIGH_WARN	1575	/* Voltage ASIC Core High Warn Threshold */
-#define	SK_SEN_CORE_1V5_LOW_WARN	1425	/* Voltage ASIC Core Low Warn Threshold */
-#define	SK_SEN_CORE_1V5_LOW_ERR 	1350	/* Voltage ASIC Core Low Err Threshold */
-
-/*
- * FAN 1 speed
- */
-/* assuming: 6500rpm +-15%, 4 pulses,
- * warning at:	80 %
- * error at:	70 %
- * no upper limit
- */
-#define	SK_SEN_FAN_HIGH_ERR		20000	/* FAN Speed High Err Threshold */
-#define	SK_SEN_FAN_HIGH_WARN	20000	/* FAN Speed High Warn Threshold */
-#define	SK_SEN_FAN_LOW_WARN		 5200	/* FAN Speed Low Warn Threshold */
-#define	SK_SEN_FAN_LOW_ERR		 4550	/* FAN Speed Low Err Threshold */
-
-/*
- * Some Voltages need dynamic thresholds
- */
-#define	SK_SEN_DYN_INIT_NONE		 0  /* No dynamic init of thresholds */
-#define	SK_SEN_DYN_INIT_PCI_IO		10  /* Init PCI-IO with new thresholds */
-#define	SK_SEN_DYN_INIT_VAUX		11  /* Init VAUX with new thresholds */
-
-extern	int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
-#endif	/* n_INC_SKGEI2C_H */
diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
deleted file mode 100644
index 143e635..0000000
--- a/drivers/net/sk98lin/h/skgeinit.h
+++ /dev/null
@@ -1,797 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgeinit.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.83 $
- * Date:	$Date: 2003/09/16 14:07:37 $
- * Purpose:	Structures and prototypes for the GE Init Module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEINIT_H_
-#define __INC_SKGEINIT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_TEST_VAL		0x11335577UL
-
-/* modifying Link LED behaviour (used with SkGeLinkLED()) */
-#define SK_LNK_OFF		LED_OFF
-#define SK_LNK_ON		(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LNK_BLINK	(LED_ON | LED_BLK_ON  | LED_SYNC_ON)
-#define SK_LNK_PERM		(LED_ON | LED_BLK_OFF | LED_SYNC_ON)
-#define SK_LNK_TST		(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
-
-/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */
-#define SK_LED_OFF		LED_OFF
-#define SK_LED_ACTIVE	(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LED_STANDBY	(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
-
-/* addressing LED Registers in SkGeXmitLED() */
-#define XMIT_LED_INI	0
-#define XMIT_LED_CNT	(RX_LED_VAL - RX_LED_INI)
-#define XMIT_LED_CTRL	(RX_LED_CTRL- RX_LED_INI)
-#define XMIT_LED_TST	(RX_LED_TST - RX_LED_INI)
-
-/* parameter 'Mode' when calling SkGeXmitLED() */
-#define SK_LED_DIS	0
-#define SK_LED_ENA	1
-#define SK_LED_TST	2
-
-/* Counter and Timer constants, for a host clock of 62.5 MHz */
-#define SK_XMIT_DUR		0x002faf08UL	/*  50 ms */
-#define SK_BLK_DUR		0x01dcd650UL	/* 500 ms */
-
-#define SK_DPOLL_DEF	0x00ee6b28UL	/* 250 ms at 62.5 MHz */
-
-#define SK_DPOLL_MAX	0x00ffffffUL	/* 268 ms at 62.5 MHz */
-										/* 215 ms at 78.12 MHz */
-
-#define SK_FACT_62		100			/* is given in percent */
-#define SK_FACT_53		 85         /* on GENESIS:	53.12 MHz */
-#define SK_FACT_78		125			/* on YUKON:	78.12 MHz */
-
-/* Timeout values */
-#define SK_MAC_TO_53	72			/* MAC arbiter timeout */
-#define SK_PKT_TO_53	0x2000		/* Packet arbiter timeout */
-#define SK_PKT_TO_MAX	0xffff		/* Maximum value */
-#define SK_RI_TO_53		36			/* RAM interface timeout */
-
-#define SK_PHY_ACC_TO	600000		/* PHY access timeout */
-
-/* RAM Buffer High Pause Threshold values */
-#define SK_RB_ULPP		( 8 * 1024)	/* Upper Level in kB/8 */
-#define SK_RB_LLPP_S	(10 * 1024)	/* Lower Level for small Queues */
-#define SK_RB_LLPP_B	(16 * 1024)	/* Lower Level for big Queues */
-
-#ifndef SK_BMU_RX_WM
-#define SK_BMU_RX_WM	0x600		/* BMU Rx Watermark */
-#endif
-#ifndef SK_BMU_TX_WM
-#define SK_BMU_TX_WM	0x600		/* BMU Tx Watermark */
-#endif
-
-/* XMAC II Rx High Watermark */
-#define SK_XM_RX_HI_WM	0x05aa		/* 1450 */
-
-/* XMAC II Tx Threshold */
-#define SK_XM_THR_REDL	0x01fb		/* .. for redundant link usage */
-#define SK_XM_THR_SL	0x01fb		/* .. for single link adapters */
-#define SK_XM_THR_MULL	0x01fb		/* .. for multiple link usage */
-#define SK_XM_THR_JUMBO	0x03fc		/* .. for jumbo frame usage */
-
-/* values for GIPortUsage */
-#define SK_RED_LINK		1		/* redundant link usage */
-#define SK_MUL_LINK		2		/* multiple link usage */
-#define SK_JUMBO_LINK	3		/* driver uses jumbo frames */
-
-/* Minimum RAM Buffer Rx Queue Size */
-#define SK_MIN_RXQ_SIZE	16		/* 16 kB */
-
-/* Minimum RAM Buffer Tx Queue Size */
-#define SK_MIN_TXQ_SIZE	16		/* 16 kB */
-
-/* Queue Size units */
-#define QZ_UNITS		0x7
-#define QZ_STEP			8
-
-/* Percentage of queue size from whole memory */
-/* 80 % for receive */
-#define RAM_QUOTA_RX	80L
-/* 0% for sync transfer */
-#define	RAM_QUOTA_SYNC	0L
-/* the rest (20%) is taken for async transfer */
-
-/* Get the rounded queue size in Bytes in 8k steps */
-#define ROUND_QUEUE_SIZE(SizeInBytes)					\
-	((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) &	\
-	~(QZ_STEP-1))
-
-/* Get the rounded queue size in KBytes in 8k steps */
-#define ROUND_QUEUE_SIZE_KB(Kilobytes) \
-	ROUND_QUEUE_SIZE((Kilobytes) * 1024L)
-
-/* Types of RAM Buffer Queues */
-#define SK_RX_SRAM_Q	1	/* small receive queue */
-#define SK_RX_BRAM_Q	2	/* big receive queue */
-#define SK_TX_RAM_Q		3	/* small or big transmit queue */
-
-/* parameter 'Dir' when calling SkGeStopPort() */
-#define SK_STOP_TX	1	/* Stops the transmit path, resets the XMAC */
-#define SK_STOP_RX	2	/* Stops the receive path */
-#define SK_STOP_ALL	3	/* Stops Rx and Tx path, resets the XMAC */
-
-/* parameter 'RstMode' when calling SkGeStopPort() */
-#define SK_SOFT_RST	1	/* perform a software reset */
-#define SK_HARD_RST	2	/* perform a hardware reset */
-
-/* Init Levels */
-#define SK_INIT_DATA	0	/* Init level 0: init data structures */
-#define SK_INIT_IO		1	/* Init level 1: init with IOs */
-#define SK_INIT_RUN		2	/* Init level 2: init for run time */
-
-/* Link Mode Parameter */
-#define SK_LMODE_HALF		1	/* Half Duplex Mode */
-#define SK_LMODE_FULL		2	/* Full Duplex Mode */
-#define SK_LMODE_AUTOHALF	3	/* AutoHalf Duplex Mode */
-#define SK_LMODE_AUTOFULL	4	/* AutoFull Duplex Mode */
-#define SK_LMODE_AUTOBOTH	5	/* AutoBoth Duplex Mode */
-#define SK_LMODE_AUTOSENSE	6	/* configured mode auto sensing */
-#define SK_LMODE_INDETERMINATED	7	/* indeterminated */
-
-/* Auto-negotiation timeout in 100ms granularity */
-#define SK_AND_MAX_TO		6	/* Wait 600 msec before link comes up */
-
-/* Auto-negotiation error codes */
-#define SK_AND_OK			0	/* no error */
-#define SK_AND_OTHER		1	/* other error than below */
-#define SK_AND_DUP_CAP		2	/* Duplex capabilities error */
-
-
-/* Link Speed Capabilities */
-#define SK_LSPEED_CAP_AUTO			(1<<0)	/* Automatic resolution */
-#define SK_LSPEED_CAP_10MBPS		(1<<1)	/* 10 Mbps */
-#define SK_LSPEED_CAP_100MBPS		(1<<2)	/* 100 Mbps */
-#define SK_LSPEED_CAP_1000MBPS		(1<<3)	/* 1000 Mbps */
-#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Speed Parameter */
-#define SK_LSPEED_AUTO				1	/* Automatic resolution */
-#define SK_LSPEED_10MBPS			2	/* 10 Mbps */
-#define SK_LSPEED_100MBPS			3	/* 100 Mbps */
-#define SK_LSPEED_1000MBPS			4	/* 1000 Mbps */
-#define SK_LSPEED_INDETERMINATED	5	/* indeterminated */
-
-/* Link Speed Current State */
-#define SK_LSPEED_STAT_UNKNOWN		1
-#define SK_LSPEED_STAT_10MBPS		2
-#define SK_LSPEED_STAT_100MBPS 		3
-#define SK_LSPEED_STAT_1000MBPS		4
-#define SK_LSPEED_STAT_INDETERMINATED 5
-
-
-/* Link Capability Parameter */
-#define SK_LMODE_CAP_HALF		(1<<0)	/* Half Duplex Mode */
-#define SK_LMODE_CAP_FULL		(1<<1)	/* Full Duplex Mode */
-#define SK_LMODE_CAP_AUTOHALF	(1<<2)	/* AutoHalf Duplex Mode */
-#define SK_LMODE_CAP_AUTOFULL	(1<<3)	/* AutoFull Duplex Mode */
-#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Mode Current State */
-#define SK_LMODE_STAT_UNKNOWN	1	/* Unknown Duplex Mode */
-#define SK_LMODE_STAT_HALF		2	/* Half Duplex Mode */
-#define SK_LMODE_STAT_FULL		3	/* Full Duplex Mode */
-#define SK_LMODE_STAT_AUTOHALF	4	/* Half Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_AUTOFULL	5	/* Full Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_INDETERMINATED 6	/* indeterminated */
-
-/* Flow Control Mode Parameter (and capabilities) */
-#define SK_FLOW_MODE_NONE		1	/* No Flow-Control */
-#define SK_FLOW_MODE_LOC_SEND	2	/* Local station sends PAUSE */
-#define SK_FLOW_MODE_SYMMETRIC	3	/* Both stations may send PAUSE */
-#define SK_FLOW_MODE_SYM_OR_REM	4	/* Both stations may send PAUSE or
-					 * just the remote station may send PAUSE
-					 */
-#define SK_FLOW_MODE_INDETERMINATED 5	/* indeterminated */
-
-/* Flow Control Status Parameter */
-#define SK_FLOW_STAT_NONE		1	/* No Flow Control */
-#define SK_FLOW_STAT_REM_SEND	2	/* Remote Station sends PAUSE */
-#define SK_FLOW_STAT_LOC_SEND	3	/* Local station sends PAUSE */
-#define SK_FLOW_STAT_SYMMETRIC	4	/* Both station may send PAUSE */
-#define SK_FLOW_STAT_INDETERMINATED 5	/* indeterminated */
-
-/* Master/Slave Mode Capabilities */
-#define SK_MS_CAP_AUTO		(1<<0)	/* Automatic resolution */
-#define SK_MS_CAP_MASTER	(1<<1)	/* This station is master */
-#define SK_MS_CAP_SLAVE		(1<<2)	/* This station is slave */
-#define SK_MS_CAP_INDETERMINATED (1<<3)	/* indeterminated */
-
-/* Set Master/Slave Mode Parameter (and capabilities) */
-#define SK_MS_MODE_AUTO		1	/* Automatic resolution */
-#define SK_MS_MODE_MASTER	2	/* This station is master */
-#define SK_MS_MODE_SLAVE	3	/* This station is slave */
-#define SK_MS_MODE_INDETERMINATED 4	/* indeterminated */
-
-/* Master/Slave Status Parameter */
-#define SK_MS_STAT_UNSET	1	/* The M/S status is not set */
-#define SK_MS_STAT_MASTER	2	/* This station is master */
-#define SK_MS_STAT_SLAVE	3	/* This station is slave */
-#define SK_MS_STAT_FAULT	4	/* M/S resolution failed */
-#define SK_MS_STAT_INDETERMINATED 5	/* indeterminated */
-
-/* parameter 'Mode' when calling SkXmSetRxCmd() */
-#define SK_STRIP_FCS_ON		(1<<0)	/* Enable  FCS stripping of Rx frames */
-#define SK_STRIP_FCS_OFF	(1<<1)	/* Disable FCS stripping of Rx frames */
-#define SK_STRIP_PAD_ON		(1<<2)	/* Enable  pad byte stripping of Rx fr */
-#define SK_STRIP_PAD_OFF	(1<<3)	/* Disable pad byte stripping of Rx fr */
-#define SK_LENERR_OK_ON		(1<<4)	/* Don't chk fr for in range len error */
-#define SK_LENERR_OK_OFF	(1<<5)	/* Check frames for in range len error */
-#define SK_BIG_PK_OK_ON		(1<<6)	/* Don't set Rx Error bit for big frames */
-#define SK_BIG_PK_OK_OFF	(1<<7)	/* Set Rx Error bit for big frames */
-#define SK_SELF_RX_ON		(1<<8)	/* Enable  Rx of own packets */
-#define SK_SELF_RX_OFF		(1<<9)	/* Disable Rx of own packets */
-
-/* parameter 'Para' when calling SkMacSetRxTxEn() */
-#define SK_MAC_LOOPB_ON		(1<<0)	/* Enable  MAC Loopback Mode */
-#define SK_MAC_LOOPB_OFF	(1<<1)	/* Disable MAC Loopback Mode */
-#define SK_PHY_LOOPB_ON		(1<<2)	/* Enable  PHY Loopback Mode */
-#define SK_PHY_LOOPB_OFF	(1<<3)	/* Disable PHY Loopback Mode */
-#define SK_PHY_FULLD_ON		(1<<4)	/* Enable  GMII Full Duplex */
-#define SK_PHY_FULLD_OFF	(1<<5)	/* Disable GMII Full Duplex */
-
-/* States of PState */
-#define SK_PRT_RESET	0	/* the port is reset */
-#define SK_PRT_STOP		1	/* the port is stopped (similar to SW reset) */
-#define SK_PRT_INIT		2	/* the port is initialized */
-#define SK_PRT_RUN		3	/* the port has an active link */
-
-/* PHY power down modes */
-#define PHY_PM_OPERATIONAL_MODE		0	/* PHY operational mode */
-#define PHY_PM_DEEP_SLEEP			1	/* coma mode --> minimal power */
-#define PHY_PM_IEEE_POWER_DOWN		2	/* IEEE 22.2.4.1.5 compl. power down */
-#define PHY_PM_ENERGY_DETECT		3	/* energy detect */
-#define PHY_PM_ENERGY_DETECT_PLUS	4	/* energy detect plus */
-
-/* Default receive frame limit for Workaround of XMAC Errata */
-#define SK_DEF_RX_WA_LIM	SK_CONSTU64(100)
-
-/* values for GILedBlinkCtrl (LED Blink Control) */
-#define SK_ACT_LED_BLINK	(1<<0)	/* Active LED blinking */
-#define SK_DUP_LED_NORMAL	(1<<1)	/* Duplex LED normal */
-#define SK_LED_LINK100_ON	(1<<2)	/* Link 100M LED on */
-
-/* Link Partner Status */
-#define SK_LIPA_UNKNOWN	0	/* Link partner is in unknown state */
-#define SK_LIPA_MANUAL	1	/* Link partner is in detected manual state */
-#define SK_LIPA_AUTO	2	/* Link partner is in auto-negotiation state */
-
-/* Maximum Restarts before restart is ignored (3Com WA) */
-#define SK_MAX_LRESTART	3	/* Max. 3 times the link is restarted */
-
-/* Max. Auto-neg. timeouts before link detection in sense mode is reset */
-#define SK_MAX_ANEG_TO	10	/* Max. 10 times the sense mode is reset */
-
-/* structures *****************************************************************/
-
-/*
- * MAC specific functions
- */
-typedef struct s_GeMacFunc {
-	int  (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
-	int  (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
-							SK_U16 StatAddr, SK_U32 SK_FAR *pVal);
-	int  (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
-	int  (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
-						   SK_U16 IStatus, SK_U64 SK_FAR *pVal);
-} SK_GEMACFUNC;
-
-/*
- * Port Structure
- */
-typedef	struct s_GePort {
-#ifndef SK_DIAG
-	SK_TIMER	PWaTimer;	/* Workaround Timer */
-	SK_TIMER	HalfDupChkTimer;
-#endif /* SK_DIAG */
-	SK_U32	PPrevShorts;	/* Previous Short Counter checking */
-	SK_U32	PPrevFcs;		/* Previous FCS Error Counter checking */
-	SK_U64	PPrevRx;		/* Previous RxOk Counter checking */
-	SK_U64	PRxLim;			/* Previous RxOk Counter checking */
-	SK_U64	LastOctets;		/* For half duplex hang check */
-	int		PLinkResCt;		/* Link Restart Counter */
-	int		PAutoNegTimeOut;/* Auto-negotiation timeout current value */
-	int		PAutoNegTOCt;	/* Auto-negotiation Timeout Counter */
-	int		PRxQSize;		/* Port Rx Queue Size in kB */
-	int		PXSQSize;		/* Port Synchronous  Transmit Queue Size in kB */
-	int		PXAQSize;		/* Port Asynchronous Transmit Queue Size in kB */
-	SK_U32	PRxQRamStart;	/* Receive Queue RAM Buffer Start Address */
-	SK_U32	PRxQRamEnd;		/* Receive Queue RAM Buffer End Address */
-	SK_U32	PXsQRamStart;	/* Sync Tx Queue RAM Buffer Start Address */
-	SK_U32	PXsQRamEnd;		/* Sync Tx Queue RAM Buffer End Address */
-	SK_U32	PXaQRamStart;	/* Async Tx Queue RAM Buffer Start Address */
-	SK_U32	PXaQRamEnd;		/* Async Tx Queue RAM Buffer End Address */
-	SK_U32	PRxOverCnt;		/* Receive Overflow Counter */
-	int		PRxQOff;		/* Rx Queue Address Offset */
-	int		PXsQOff;		/* Synchronous Tx Queue Address Offset */
-	int		PXaQOff;		/* Asynchronous Tx Queue Address Offset */
-	int		PhyType;		/* PHY used on this port */
-	int		PState;			/* Port status (reset, stop, init, run) */
-	SK_U16	PhyId1;			/* PHY Id1 on this port */
-	SK_U16	PhyAddr;		/* MDIO/MDC PHY address */
-	SK_U16	PIsave;			/* Saved Interrupt status word */
-	SK_U16	PSsave;			/* Saved PHY status word */
-	SK_U16	PGmANegAdv;		/* Saved GPhy AutoNegAdvertisment register */
-	SK_BOOL	PHWLinkUp;		/* The hardware Link is up (wiring) */
-	SK_BOOL	PLinkBroken;	/* Is Link broken ? */
-	SK_BOOL	PCheckPar;		/* Do we check for parity errors ? */
-	SK_BOOL	HalfDupTimerActive;
-	SK_U8	PLinkCap;		/* Link Capabilities */
-	SK_U8	PLinkModeConf;	/* Link Mode configured */
-	SK_U8	PLinkMode;		/* Link Mode currently used */
-	SK_U8	PLinkModeStatus;/* Link Mode Status */
-	SK_U8	PLinkSpeedCap;	/* Link Speed Capabilities(10/100/1000 Mbps) */
-	SK_U8	PLinkSpeed;		/* configured Link Speed (10/100/1000 Mbps) */
-	SK_U8	PLinkSpeedUsed;	/* current Link Speed (10/100/1000 Mbps) */
-	SK_U8	PFlowCtrlCap;	/* Flow Control Capabilities */
-	SK_U8	PFlowCtrlMode;	/* Flow Control Mode */
-	SK_U8	PFlowCtrlStatus;/* Flow Control Status */
-	SK_U8	PMSCap;			/* Master/Slave Capabilities */
-	SK_U8	PMSMode;		/* Master/Slave Mode */
-	SK_U8	PMSStatus;		/* Master/Slave Status */
-	SK_BOOL	PAutoNegFail;	/* Auto-negotiation fail flag */
-	SK_U8	PLipaAutoNeg;	/* Auto-negotiation possible with Link Partner */
-	SK_U8	PCableLen;		/* Cable Length */
-	SK_U8	PMdiPairLen[4];	/* MDI[0..3] Pair Length */
-	SK_U8	PMdiPairSts[4];	/* MDI[0..3] Pair Diagnostic Status */
-	SK_U8	PPhyPowerState;	/* PHY current power state */
-	int		PMacColThres;	/* MAC Collision Threshold */
-	int		PMacJamLen;		/* MAC Jam length */
-	int		PMacJamIpgVal;	/* MAC Jam IPG */
-	int		PMacJamIpgData;	/* MAC IPG Jam to Data */
-	int		PMacIpgData;	/* MAC Data IPG */
-	SK_BOOL PMacLimit4;		/* reset collision counter and backoff algorithm */
-} SK_GEPORT;
-
-/*
- * Gigabit Ethernet Initialization Struct
- * (has to be included in the adapter context)
- */
-typedef	struct s_GeInit {
-	int			GIChipId;		/* Chip Identification Number */
-	int			GIChipRev;		/* Chip Revision Number */
-	SK_U8		GIPciHwRev;		/* PCI HW Revision Number */
-	SK_BOOL		GIGenesis;		/* Genesis adapter ? */
-	SK_BOOL		GIYukon;		/* YUKON-A1/Bx chip */
-	SK_BOOL		GIYukonLite;	/* YUKON-Lite chip */
-	SK_BOOL		GICopperType;	/* Copper Type adapter ? */
-	SK_BOOL		GIPciSlot64;	/* 64-bit PCI Slot */
-	SK_BOOL		GIPciClock66;	/* 66 MHz PCI Clock */
-	SK_BOOL		GIVauxAvail;	/* VAUX available (YUKON) */
-	SK_BOOL		GIYukon32Bit;	/* 32-Bit YUKON adapter */
-	SK_U16		GILedBlinkCtrl;	/* LED Blink Control */
-	int			GIMacsFound;	/* Number of MACs found on this adapter */
-	int			GIMacType;		/* MAC Type used on this adapter */
-	int			GIHstClkFact;	/* Host Clock Factor (62.5 / HstClk * 100) */
-	int			GIPortUsage;	/* Driver Port Usage */
-	int			GILevel;		/* Initialization Level completed */
-	int			GIRamSize;		/* The RAM size of the adapter in kB */
-	int			GIWolOffs;		/* WOL Register Offset (HW-Bug in Rev. A) */
-	SK_U32		GIRamOffs;		/* RAM Address Offset for addr calculation */
-	SK_U32		GIPollTimerVal;	/* Descr. Poll Timer Init Val (HstClk ticks) */
-	SK_U32		GIValIrqMask;	/* Value for Interrupt Mask */
-	SK_U32		GITimeStampCnt;	/* Time Stamp High Counter (YUKON only) */
-	SK_GEPORT	GP[SK_MAX_MACS];/* Port Dependent Information */
-	SK_GEMACFUNC GIFunc;		/* MAC depedent functions */
-} SK_GEINIT;
-
-/*
- * Error numbers and messages for skxmac2.c and skgeinit.c
- */
-#define SKERR_HWI_E001		(SK_ERRBASE_HWINIT)
-#define SKERR_HWI_E001MSG	"SkXmClrExactAddr() has got illegal parameters"
-#define SKERR_HWI_E002		(SKERR_HWI_E001+1)
-#define SKERR_HWI_E002MSG	"SkGeInit(): Level 1 call missing"
-#define SKERR_HWI_E003		(SKERR_HWI_E002+1)
-#define SKERR_HWI_E003MSG	"SkGeInit() called with illegal init Level"
-#define SKERR_HWI_E004		(SKERR_HWI_E003+1)
-#define SKERR_HWI_E004MSG	"SkGeInitPort(): Queue Size illegal configured"
-#define SKERR_HWI_E005		(SKERR_HWI_E004+1)
-#define SKERR_HWI_E005MSG	"SkGeInitPort(): cannot init running ports"
-#define SKERR_HWI_E006		(SKERR_HWI_E005+1)
-#define SKERR_HWI_E006MSG	"SkGeMacInit(): PState does not match HW state"
-#define SKERR_HWI_E007		(SKERR_HWI_E006+1)
-#define SKERR_HWI_E007MSG	"SkXmInitDupMd() called with invalid Dup Mode"
-#define SKERR_HWI_E008		(SKERR_HWI_E007+1)
-#define SKERR_HWI_E008MSG	"SkXmSetRxCmd() called with invalid Mode"
-#define SKERR_HWI_E009		(SKERR_HWI_E008+1)
-#define SKERR_HWI_E009MSG	"SkGeCfgSync() called although PXSQSize zero"
-#define SKERR_HWI_E010		(SKERR_HWI_E009+1)
-#define SKERR_HWI_E010MSG	"SkGeCfgSync() called with invalid parameters"
-#define SKERR_HWI_E011		(SKERR_HWI_E010+1)
-#define SKERR_HWI_E011MSG	"SkGeInitPort(): Receive Queue Size too small"
-#define SKERR_HWI_E012		(SKERR_HWI_E011+1)
-#define SKERR_HWI_E012MSG	"SkGeInitPort(): invalid Queue Size specified"
-#define SKERR_HWI_E013		(SKERR_HWI_E012+1)
-#define SKERR_HWI_E013MSG	"SkGeInitPort(): cfg changed for running queue"
-#define SKERR_HWI_E014		(SKERR_HWI_E013+1)
-#define SKERR_HWI_E014MSG	"SkGeInitPort(): unknown GIPortUsage specified"
-#define SKERR_HWI_E015		(SKERR_HWI_E014+1)
-#define SKERR_HWI_E015MSG	"Illegal Link mode parameter"
-#define SKERR_HWI_E016		(SKERR_HWI_E015+1)
-#define SKERR_HWI_E016MSG	"Illegal Flow control mode parameter"
-#define SKERR_HWI_E017		(SKERR_HWI_E016+1)
-#define SKERR_HWI_E017MSG	"Illegal value specified for GIPollTimerVal"
-#define SKERR_HWI_E018		(SKERR_HWI_E017+1)
-#define SKERR_HWI_E018MSG	"FATAL: SkGeStopPort() does not terminate (Tx)"
-#define SKERR_HWI_E019		(SKERR_HWI_E018+1)
-#define SKERR_HWI_E019MSG	"Illegal Speed parameter"
-#define SKERR_HWI_E020		(SKERR_HWI_E019+1)
-#define SKERR_HWI_E020MSG	"Illegal Master/Slave parameter"
-#define SKERR_HWI_E021		(SKERR_HWI_E020+1)
-#define	SKERR_HWI_E021MSG	"MacUpdateStats(): cannot update statistic counter"
-#define	SKERR_HWI_E022		(SKERR_HWI_E021+1)
-#define	SKERR_HWI_E022MSG	"MacStatistic(): illegal statistic base address"
-#define SKERR_HWI_E023		(SKERR_HWI_E022+1)
-#define SKERR_HWI_E023MSG	"SkGeInitPort(): Transmit Queue Size too small"
-#define SKERR_HWI_E024		(SKERR_HWI_E023+1)
-#define SKERR_HWI_E024MSG	"FATAL: SkGeStopPort() does not terminate (Rx)"
-#define SKERR_HWI_E025		(SKERR_HWI_E024+1)
-#define SKERR_HWI_E025MSG	""
-
-/* function prototypes ********************************************************/
-
-#ifndef	SK_KR_PROTO
-
-/*
- * public functions in skgeinit.c
- */
-extern void	SkGePollTxD(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL PollTxD);
-
-extern void	SkGeYellowLED(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		State);
-
-extern int	SkGeCfgSync(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U32	IntTime,
-	SK_U32	LimCount,
-	int		SyncMode);
-
-extern void	SkGeLoadLnkSyncCnt(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U32	CntVal);
-
-extern void	SkGeStopPort(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Dir,
-	int		RstMode);
-
-extern int	SkGeInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Level);
-
-extern void	SkGeDeInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC);
-
-extern int	SkGeInitPort(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkGeXmitLED(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Led,
-	int		Mode);
-
-extern int	SkGeInitAssignRamToQueues(
-	SK_AC	*pAC,
-	int		ActivePort,
-	SK_BOOL	DualNet);
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacSoftRst(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacHardRst(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkXmInitMac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkGmInitMac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void SkMacInitPhy(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	DoLoop);
-
-extern void SkMacIrqDisable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacFlushTxFifo(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacIrq(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern int	SkMacAutoNegDone(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacAutoNegLipaPhy(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U16	IStatus);
-
-extern int  SkMacRxTxEnable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacPromiscMode(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-
-extern void	SkMacHashing(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-
-extern void	SkXmPhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	SK_FAR *pVal);
-
-extern void	SkXmPhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkGmPhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	SK_FAR *pVal);
-
-extern void	SkGmPhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkXmClrExactAddr(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		StartNum,
-	int		StopNum);
-
-extern void	SkXmAutoNegLipaXmac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U16	IStatus);
-
-extern int SkXmUpdateStats(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkGmUpdateStats(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkXmMacStatistic(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	StatAddr,
-	SK_U32	SK_FAR *pVal);
-
-extern int SkGmMacStatistic(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	StatAddr,
-	SK_U32	SK_FAR *pVal);
-
-extern int SkXmResetCounter(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkGmResetCounter(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkXmOverflowStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16  IStatus,
-	SK_U64	SK_FAR *pStatus);
-
-extern int SkGmOverflowStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	MacStatus,
-	SK_U64	SK_FAR *pStatus);
-
-extern int SkGmCableDiagStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	StartTest);
-
-#ifdef SK_DIAG
-extern void	SkGePhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	*pVal);
-
-extern void	SkGePhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkMacSetRxCmd(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Mode);
-extern void	SkMacCrcGener(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-extern void	SkMacTimeStamp(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-extern void	SkXmSendCont(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-#endif /* SK_DIAG */
-
-#else	/* SK_KR_PROTO */
-
-/*
- * public functions in skgeinit.c
- */
-extern void	SkGePollTxD();
-extern void	SkGeYellowLED();
-extern int	SkGeCfgSync();
-extern void	SkGeLoadLnkSyncCnt();
-extern void	SkGeStopPort();
-extern int	SkGeInit();
-extern void	SkGeDeInit();
-extern int	SkGeInitPort();
-extern void	SkGeXmitLED();
-extern int	SkGeInitAssignRamToQueues();
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable();
-extern void	SkMacSoftRst();
-extern void	SkMacHardRst();
-extern void SkMacInitPhy();
-extern int  SkMacRxTxEnable();
-extern void SkMacPromiscMode();
-extern void SkMacHashing();
-extern void SkMacIrqDisable();
-extern void	SkMacFlushTxFifo();
-extern void	SkMacIrq();
-extern int	SkMacAutoNegDone();
-extern void	SkMacAutoNegLipaPhy();
-extern void	SkXmInitMac();
-extern void	SkXmPhyRead();
-extern void	SkXmPhyWrite();
-extern void	SkGmInitMac();
-extern void	SkGmPhyRead();
-extern void	SkGmPhyWrite();
-extern void	SkXmClrExactAddr();
-extern void	SkXmAutoNegLipaXmac();
-extern int	SkXmUpdateStats();
-extern int	SkGmUpdateStats();
-extern int	SkXmMacStatistic();
-extern int	SkGmMacStatistic();
-extern int	SkXmResetCounter();
-extern int	SkGmResetCounter();
-extern int	SkXmOverflowStatus();
-extern int	SkGmOverflowStatus();
-extern int	SkGmCableDiagStatus();
-
-#ifdef SK_DIAG
-extern void	SkGePhyRead();
-extern void	SkGePhyWrite();
-extern void	SkMacSetRxCmd();
-extern void	SkMacCrcGener();
-extern void	SkMacTimeStamp();
-extern void	SkXmSendCont();
-#endif /* SK_DIAG */
-
-#endif	/* SK_KR_PROTO */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKGEINIT_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
deleted file mode 100644
index ddd304f..0000000
--- a/drivers/net/sk98lin/h/skgepnm2.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnm2.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.36 $
- * Date:	$Date: 2003/05/23 12:45:13 $
- * Purpose:	Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNM2_H_
-#define _SKGEPNM2_H_
-
-/*
- * General definitions
- */
-#define SK_PNMI_CHIPSET_XMAC	1	/* XMAC11800FP */
-#define SK_PNMI_CHIPSET_YUKON	2	/* YUKON */
-
-#define	SK_PNMI_BUS_PCI		1	/* PCI bus*/
-
-/*
- * Actions
- */
-#define SK_PNMI_ACT_IDLE		1
-#define SK_PNMI_ACT_RESET		2
-#define SK_PNMI_ACT_SELFTEST	3
-#define SK_PNMI_ACT_RESETCNT	4
-
-/*
- * VPD releated defines
- */
-
-#define SK_PNMI_VPD_RW		1
-#define SK_PNMI_VPD_RO		2
-
-#define SK_PNMI_VPD_OK			0
-#define SK_PNMI_VPD_NOTFOUND	1
-#define SK_PNMI_VPD_CUT			2
-#define SK_PNMI_VPD_TIMEOUT		3
-#define SK_PNMI_VPD_FULL		4
-#define SK_PNMI_VPD_NOWRITE		5
-#define SK_PNMI_VPD_FATAL		6
-
-#define SK_PNMI_VPD_IGNORE	0
-#define SK_PNMI_VPD_CREATE	1
-#define SK_PNMI_VPD_DELETE	2
-
-
-/*
- * RLMT related defines
- */
-#define SK_PNMI_DEF_RLMT_CHG_THRES	240	/* 4 changes per minute */
-
-
-/*
- * VCT internal status values
- */
-#define SK_PNMI_VCT_PENDING	32
-#define SK_PNMI_VCT_TEST_DONE	64
-#define SK_PNMI_VCT_LINK	128
-
-/*
- * Internal table definitions
- */
-#define SK_PNMI_GET		0
-#define SK_PNMI_PRESET	1
-#define SK_PNMI_SET		2
-
-#define SK_PNMI_RO		0
-#define SK_PNMI_RW		1
-#define SK_PNMI_WO		2
-
-typedef struct s_OidTabEntry {
-	SK_U32			Id;
-	SK_U32			InstanceNo;
-	unsigned int	StructSize;
-	unsigned int	Offset;
-	int				Access;
-	int				(* Func)(SK_AC *pAc, SK_IOC pIo, int action,
-							 SK_U32 Id, char* pBuf, unsigned int* pLen,
-							 SK_U32 Instance, unsigned int TableIndex,
-							 SK_U32 NetNumber);
-	SK_U16			Param;
-} SK_PNMI_TAB_ENTRY;
-
-
-/*
- * Trap lengths
- */
-#define SK_PNMI_TRAP_SIMPLE_LEN			17
-#define SK_PNMI_TRAP_SENSOR_LEN_BASE	46
-#define SK_PNMI_TRAP_RLMT_CHANGE_LEN	23
-#define SK_PNMI_TRAP_RLMT_PORT_LEN		23
-
-/*
- * Number of MAC types supported
- */
-#define SK_PNMI_MAC_TYPES	(SK_MAC_GMAC + 1)
-
-/*
- * MAC statistic data list (overall set for MAC types used)
- */
-enum SK_MACSTATS {
-	SK_PNMI_HTX				= 0,
-	SK_PNMI_HTX_OCTET,
-	SK_PNMI_HTX_OCTETHIGH 	= SK_PNMI_HTX_OCTET,
-	SK_PNMI_HTX_OCTETLOW,
-	SK_PNMI_HTX_BROADCAST,
-	SK_PNMI_HTX_MULTICAST,
-	SK_PNMI_HTX_UNICAST,
-	SK_PNMI_HTX_BURST,
-	SK_PNMI_HTX_PMACC,
-	SK_PNMI_HTX_MACC,
-	SK_PNMI_HTX_COL,
-	SK_PNMI_HTX_SINGLE_COL,
-	SK_PNMI_HTX_MULTI_COL,
-	SK_PNMI_HTX_EXCESS_COL,
-	SK_PNMI_HTX_LATE_COL,
-	SK_PNMI_HTX_DEFFERAL,
-	SK_PNMI_HTX_EXCESS_DEF,
-	SK_PNMI_HTX_UNDERRUN,
-	SK_PNMI_HTX_CARRIER,
-	SK_PNMI_HTX_UTILUNDER,
-	SK_PNMI_HTX_UTILOVER,
-	SK_PNMI_HTX_64,
-	SK_PNMI_HTX_127,
-	SK_PNMI_HTX_255,
-	SK_PNMI_HTX_511,
-	SK_PNMI_HTX_1023,
-	SK_PNMI_HTX_MAX,
-	SK_PNMI_HTX_LONGFRAMES,
-	SK_PNMI_HTX_SYNC,
-	SK_PNMI_HTX_SYNC_OCTET,
-	SK_PNMI_HTX_RESERVED,
-	
-	SK_PNMI_HRX,
-	SK_PNMI_HRX_OCTET,
-	SK_PNMI_HRX_OCTETHIGH	= SK_PNMI_HRX_OCTET,
-	SK_PNMI_HRX_OCTETLOW,
-	SK_PNMI_HRX_BADOCTET,
-	SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET,
-	SK_PNMI_HRX_BADOCTETLOW,
-	SK_PNMI_HRX_BROADCAST,
-	SK_PNMI_HRX_MULTICAST,
-	SK_PNMI_HRX_UNICAST,
-	SK_PNMI_HRX_PMACC,
-	SK_PNMI_HRX_MACC,
-	SK_PNMI_HRX_PMACC_ERR,
-	SK_PNMI_HRX_MACC_UNKWN,
-	SK_PNMI_HRX_BURST,
-	SK_PNMI_HRX_MISSED,
-	SK_PNMI_HRX_FRAMING,
-	SK_PNMI_HRX_UNDERSIZE,
-	SK_PNMI_HRX_OVERFLOW,
-	SK_PNMI_HRX_JABBER,
-	SK_PNMI_HRX_CARRIER,
-	SK_PNMI_HRX_IRLENGTH,
-	SK_PNMI_HRX_SYMBOL,
-	SK_PNMI_HRX_SHORTS,
-	SK_PNMI_HRX_RUNT,
-	SK_PNMI_HRX_TOO_LONG,
-	SK_PNMI_HRX_FCS,
-	SK_PNMI_HRX_CEXT,
-	SK_PNMI_HRX_UTILUNDER,
-	SK_PNMI_HRX_UTILOVER,
-	SK_PNMI_HRX_64,
-	SK_PNMI_HRX_127,
-	SK_PNMI_HRX_255,
-	SK_PNMI_HRX_511,
-	SK_PNMI_HRX_1023,
-	SK_PNMI_HRX_MAX,
-	SK_PNMI_HRX_LONGFRAMES,
-	
-	SK_PNMI_HRX_RESERVED,
-	
-	SK_PNMI_MAX_IDX		/* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */
-};
-
-/*
- * MAC specific data
- */
-typedef struct s_PnmiStatAddr {
-	SK_U16		Reg;		/* MAC register containing the value */
-	SK_BOOL		GetOffset;	/* TRUE: Offset managed by PNMI (call GetStatVal())*/
-} SK_PNMI_STATADDR;
-
-
-/*
- * SK_PNMI_STRUCT_DATA copy offset evaluation macros
- */
-#define SK_PNMI_OFF(e)		((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_MAI_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_VPD_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e))
-#define SK_PNMI_SEN_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e))
-#define SK_PNMI_CHK_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e))
-#define SK_PNMI_STA_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e))
-#define SK_PNMI_CNF_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e))
-#define SK_PNMI_RLM_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e))
-#define SK_PNMI_MON_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e))
-#define SK_PNMI_TRP_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e))
-
-#define SK_PNMI_SET_STAT(b,s,o)	{SK_U32	Val32; char *pVal; \
-					Val32 = (s); \
-					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
-						&(((SK_PNMI_STRUCT_DATA *)0)-> \
-						ReturnStatus.ErrorStatus)); \
-					SK_PNMI_STORE_U32(pVal, Val32); \
-					Val32 = (o); \
-					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
-						&(((SK_PNMI_STRUCT_DATA *)0)-> \
-						ReturnStatus.ErrorOffset)); \
-					SK_PNMI_STORE_U32(pVal, Val32);}
-
-/*
- * Time macros
- */
-#ifndef SK_PNMI_HUNDREDS_SEC
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t)	(t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t)	(((t) * 100) / (SK_TICKS_PER_SEC))
-#endif /* !SK_TICKS_PER_SEC */
-#endif /* !SK_PNMI_HUNDREDS_SEC */
-
-/*
- * Macros to work around alignment problems
- */
-#ifndef SK_PNMI_STORE_U16
-#define SK_PNMI_STORE_U16(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1);}
-#endif
-
-#ifndef SK_PNMI_STORE_U32
-#define SK_PNMI_STORE_U32(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1); \
-					*((char *)(p) + 2) = \
-						*(((char *)&(v)) + 2); \
-					*((char *)(p) + 3) = \
-						*(((char *)&(v)) + 3);}
-#endif
-
-#ifndef SK_PNMI_STORE_U64
-#define SK_PNMI_STORE_U64(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1); \
-					*((char *)(p) + 2) = \
-						*(((char *)&(v)) + 2); \
-					*((char *)(p) + 3) = \
-						*(((char *)&(v)) + 3); \
-					*((char *)(p) + 4) = \
-						*(((char *)&(v)) + 4); \
-					*((char *)(p) + 5) = \
-						*(((char *)&(v)) + 5); \
-					*((char *)(p) + 6) = \
-						*(((char *)&(v)) + 6); \
-					*((char *)(p) + 7) = \
-						*(((char *)&(v)) + 7);}
-#endif
-
-#ifndef SK_PNMI_READ_U16
-#define SK_PNMI_READ_U16(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1);}
-#endif
-
-#ifndef SK_PNMI_READ_U32
-#define SK_PNMI_READ_U32(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1); \
-					*(((char *)&(v)) + 2) = \
-						*((char *)(p) + 2); \
-					*(((char *)&(v)) + 3) = \
-						*((char *)(p) + 3);}
-#endif
-
-#ifndef SK_PNMI_READ_U64
-#define SK_PNMI_READ_U64(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1); \
-					*(((char *)&(v)) + 2) = \
-						*((char *)(p) + 2); \
-					*(((char *)&(v)) + 3) = \
-						*((char *)(p) + 3); \
-					*(((char *)&(v)) + 4) = \
-						*((char *)(p) + 4); \
-					*(((char *)&(v)) + 5) = \
-						*((char *)(p) + 5); \
-					*(((char *)&(v)) + 6) = \
-						*((char *)(p) + 6); \
-					*(((char *)&(v)) + 7) = \
-						*((char *)(p) + 7);}
-#endif
-
-/*
- * Macros for Debug
- */
-#ifdef DEBUG
-
-#define SK_PNMI_CHECKFLAGS(vSt)	{if (pAC->Pnmi.MacUpdatedFlag > 0 || \
-					pAC->Pnmi.RlmtUpdatedFlag > 0 || \
-					pAC->Pnmi.SirqUpdatedFlag > 0) { \
-						SK_DBG_MSG(pAC, \
-						SK_DBGMOD_PNMI, \
-						SK_DBGCAT_CTRL,	\
-						("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \
-						vSt, \
-						pAC->Pnmi.MacUpdatedFlag, \
-						pAC->Pnmi.RlmtUpdatedFlag, \
-						pAC->Pnmi.SirqUpdatedFlag))}}
-
-#else	/* !DEBUG */
-
-#define SK_PNMI_CHECKFLAGS(vSt)	/* Nothing */
-
-#endif	/* !DEBUG */
-
-#endif	/* _SKGEPNM2_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
deleted file mode 100644
index 1ed214c..0000000
--- a/drivers/net/sk98lin/h/skgepnmi.h
+++ /dev/null
@@ -1,962 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnmi.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.62 $
- * Date:	$Date: 2003/08/15 12:31:52 $
- * Purpose:	Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNMI_H_
-#define _SKGEPNMI_H_
-
-/*
- * Include dependencies
- */
-#include "h/sktypes.h"
-#include "h/skerror.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skaddr.h"
-#include "h/skrlmt.h"
-#include "h/skvpd.h"
-
-/*
- * Management Database Version
- */
-#define SK_PNMI_MDB_VERSION		0x00030001	/* 3.1 */
-
-
-/*
- * Event definitions
- */
-#define SK_PNMI_EVT_SIRQ_OVERFLOW		1	/* Counter overflow */
-#define SK_PNMI_EVT_SEN_WAR_LOW			2	/* Lower war thres exceeded */
-#define SK_PNMI_EVT_SEN_WAR_UPP			3	/* Upper war thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_LOW			4	/* Lower err thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_UPP			5	/* Upper err thres exceeded */
-#define SK_PNMI_EVT_CHG_EST_TIMER		6	/* Timer event for RLMT Chg */
-#define SK_PNMI_EVT_UTILIZATION_TIMER	7	/* Timer event for Utiliza. */
-#define SK_PNMI_EVT_CLEAR_COUNTER		8	/* Clear statistic counters */
-#define SK_PNMI_EVT_XMAC_RESET			9	/* XMAC will be reset */
-
-#define SK_PNMI_EVT_RLMT_PORT_UP		10	/* Port came logically up */
-#define SK_PNMI_EVT_RLMT_PORT_DOWN		11	/* Port went logically down */
-#define SK_PNMI_EVT_RLMT_SEGMENTATION	13	/* Two SP root bridges found */
-#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN	14	/* Port went logically down */
-#define SK_PNMI_EVT_RLMT_ACTIVE_UP		15	/* Port came logically up */
-#define SK_PNMI_EVT_RLMT_SET_NETS		16	/* 1. Parameter is number of nets
-												1 = single net; 2 = dual net */
-#define SK_PNMI_EVT_VCT_RESET		17	/* VCT port reset timer event started with SET. */
-
-
-/*
- * Return values
- */
-#define SK_PNMI_ERR_OK				0
-#define SK_PNMI_ERR_GENERAL			1
-#define SK_PNMI_ERR_TOO_SHORT		2
-#define SK_PNMI_ERR_BAD_VALUE		3
-#define SK_PNMI_ERR_READ_ONLY		4
-#define SK_PNMI_ERR_UNKNOWN_OID		5
-#define SK_PNMI_ERR_UNKNOWN_INST	6
-#define SK_PNMI_ERR_UNKNOWN_NET 	7
-#define SK_PNMI_ERR_NOT_SUPPORTED	10
-
-
-/*
- * Return values of driver reset function SK_DRIVER_RESET() and
- * driver event function SK_DRIVER_EVENT()
- */
-#define SK_PNMI_ERR_OK			0
-#define SK_PNMI_ERR_FAIL		1
-
-
-/*
- * Return values of driver test function SK_DRIVER_SELFTEST()
- */
-#define SK_PNMI_TST_UNKNOWN		(1 << 0)
-#define SK_PNMI_TST_TRANCEIVER		(1 << 1)
-#define SK_PNMI_TST_ASIC		(1 << 2)
-#define SK_PNMI_TST_SENSOR		(1 << 3)
-#define SK_PNMI_TST_POWERMGMT		(1 << 4)
-#define SK_PNMI_TST_PCI			(1 << 5)
-#define SK_PNMI_TST_MAC			(1 << 6)
-
-
-/*
- * RLMT specific definitions
- */
-#define SK_PNMI_RLMT_STATUS_STANDBY	1
-#define SK_PNMI_RLMT_STATUS_ACTIVE	2
-#define SK_PNMI_RLMT_STATUS_ERROR	3
-
-#define SK_PNMI_RLMT_LSTAT_PHY_DOWN	1
-#define SK_PNMI_RLMT_LSTAT_AUTONEG	2
-#define SK_PNMI_RLMT_LSTAT_LOG_DOWN	3
-#define SK_PNMI_RLMT_LSTAT_LOG_UP	4
-#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5
-
-#define SK_PNMI_RLMT_MODE_CHK_LINK	(SK_RLMT_CHECK_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_RX	(SK_RLMT_CHECK_LOC_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_SPT	(SK_RLMT_CHECK_SEG)
-/* #define SK_PNMI_RLMT_MODE_CHK_EX */
-
-/*
- * OID definition
- */
-#ifndef _NDIS_	/* Check, whether NDIS already included OIDs */
-
-#define OID_GEN_XMIT_OK					0x00020101
-#define OID_GEN_RCV_OK					0x00020102
-#define OID_GEN_XMIT_ERROR				0x00020103
-#define OID_GEN_RCV_ERROR				0x00020104
-#define OID_GEN_RCV_NO_BUFFER			0x00020105
-
-/* #define OID_GEN_DIRECTED_BYTES_XMIT	0x00020201 */
-#define OID_GEN_DIRECTED_FRAMES_XMIT	0x00020202
-/* #define OID_GEN_MULTICAST_BYTES_XMIT	0x00020203 */
-#define OID_GEN_MULTICAST_FRAMES_XMIT	0x00020204
-/* #define OID_GEN_BROADCAST_BYTES_XMIT	0x00020205 */
-#define OID_GEN_BROADCAST_FRAMES_XMIT	0x00020206
-/* #define OID_GEN_DIRECTED_BYTES_RCV	0x00020207 */
-#define OID_GEN_DIRECTED_FRAMES_RCV		0x00020208
-/* #define OID_GEN_MULTICAST_BYTES_RCV	0x00020209 */
-#define OID_GEN_MULTICAST_FRAMES_RCV	0x0002020A
-/* #define OID_GEN_BROADCAST_BYTES_RCV	0x0002020B */
-#define OID_GEN_BROADCAST_FRAMES_RCV	0x0002020C
-#define OID_GEN_RCV_CRC_ERROR			0x0002020D
-#define OID_GEN_TRANSMIT_QUEUE_LENGTH	0x0002020E
-
-#define OID_802_3_PERMANENT_ADDRESS		0x01010101
-#define OID_802_3_CURRENT_ADDRESS		0x01010102
-/* #define OID_802_3_MULTICAST_LIST		0x01010103 */
-/* #define OID_802_3_MAXIMUM_LIST_SIZE	0x01010104 */
-/* #define OID_802_3_MAC_OPTIONS		0x01010105 */
-			
-#define OID_802_3_RCV_ERROR_ALIGNMENT	0x01020101
-#define OID_802_3_XMIT_ONE_COLLISION	0x01020102
-#define OID_802_3_XMIT_MORE_COLLISIONS	0x01020103
-#define OID_802_3_XMIT_DEFERRED			0x01020201
-#define OID_802_3_XMIT_MAX_COLLISIONS	0x01020202
-#define OID_802_3_RCV_OVERRUN			0x01020203
-#define OID_802_3_XMIT_UNDERRUN			0x01020204
-#define OID_802_3_XMIT_TIMES_CRS_LOST	0x01020206
-#define OID_802_3_XMIT_LATE_COLLISIONS	0x01020207
-
-/*
- * PnP and PM OIDs
- */
-#ifdef SK_POWER_MGMT
-#define OID_PNP_CAPABILITIES			0xFD010100
-#define OID_PNP_SET_POWER				0xFD010101
-#define OID_PNP_QUERY_POWER				0xFD010102
-#define OID_PNP_ADD_WAKE_UP_PATTERN		0xFD010103
-#define OID_PNP_REMOVE_WAKE_UP_PATTERN	0xFD010104
-#define OID_PNP_ENABLE_WAKE_UP			0xFD010106
-#endif /* SK_POWER_MGMT */
-
-#endif /* _NDIS_ */
-
-#define OID_SKGE_MDB_VERSION			0xFF010100
-#define OID_SKGE_SUPPORTED_LIST			0xFF010101
-#define OID_SKGE_VPD_FREE_BYTES			0xFF010102
-#define OID_SKGE_VPD_ENTRIES_LIST		0xFF010103
-#define OID_SKGE_VPD_ENTRIES_NUMBER		0xFF010104
-#define OID_SKGE_VPD_KEY				0xFF010105
-#define OID_SKGE_VPD_VALUE				0xFF010106
-#define OID_SKGE_VPD_ACCESS				0xFF010107
-#define OID_SKGE_VPD_ACTION				0xFF010108
-			
-#define OID_SKGE_PORT_NUMBER			0xFF010110
-#define OID_SKGE_DEVICE_TYPE			0xFF010111
-#define OID_SKGE_DRIVER_DESCR			0xFF010112
-#define OID_SKGE_DRIVER_VERSION			0xFF010113
-#define OID_SKGE_HW_DESCR				0xFF010114
-#define OID_SKGE_HW_VERSION				0xFF010115
-#define OID_SKGE_CHIPSET				0xFF010116
-#define OID_SKGE_ACTION					0xFF010117
-#define OID_SKGE_RESULT					0xFF010118
-#define OID_SKGE_BUS_TYPE				0xFF010119
-#define OID_SKGE_BUS_SPEED				0xFF01011A
-#define OID_SKGE_BUS_WIDTH				0xFF01011B
-/* 0xFF01011C unused */
-#define OID_SKGE_DIAG_ACTION			0xFF01011D
-#define OID_SKGE_DIAG_RESULT			0xFF01011E
-#define OID_SKGE_MTU					0xFF01011F
-#define OID_SKGE_PHYS_CUR_ADDR			0xFF010120
-#define OID_SKGE_PHYS_FAC_ADDR			0xFF010121
-#define OID_SKGE_PMD					0xFF010122
-#define OID_SKGE_CONNECTOR				0xFF010123
-#define OID_SKGE_LINK_CAP				0xFF010124
-#define OID_SKGE_LINK_MODE				0xFF010125
-#define OID_SKGE_LINK_MODE_STATUS		0xFF010126
-#define OID_SKGE_LINK_STATUS			0xFF010127
-#define OID_SKGE_FLOWCTRL_CAP			0xFF010128
-#define OID_SKGE_FLOWCTRL_MODE			0xFF010129
-#define OID_SKGE_FLOWCTRL_STATUS		0xFF01012A
-#define OID_SKGE_PHY_OPERATION_CAP		0xFF01012B
-#define OID_SKGE_PHY_OPERATION_MODE		0xFF01012C
-#define OID_SKGE_PHY_OPERATION_STATUS	0xFF01012D
-#define OID_SKGE_MULTICAST_LIST			0xFF01012E
-#define OID_SKGE_CURRENT_PACKET_FILTER	0xFF01012F
-
-#define OID_SKGE_TRAP					0xFF010130
-#define OID_SKGE_TRAP_NUMBER			0xFF010131
-
-#define OID_SKGE_RLMT_MODE				0xFF010140
-#define OID_SKGE_RLMT_PORT_NUMBER		0xFF010141
-#define OID_SKGE_RLMT_PORT_ACTIVE		0xFF010142
-#define OID_SKGE_RLMT_PORT_PREFERRED	0xFF010143
-#define OID_SKGE_INTERMEDIATE_SUPPORT	0xFF010160
-
-#define OID_SKGE_SPEED_CAP				0xFF010170
-#define OID_SKGE_SPEED_MODE				0xFF010171
-#define OID_SKGE_SPEED_STATUS			0xFF010172
-
-#define OID_SKGE_BOARDLEVEL				0xFF010180
-
-#define OID_SKGE_SENSOR_NUMBER			0xFF020100			
-#define OID_SKGE_SENSOR_INDEX			0xFF020101
-#define OID_SKGE_SENSOR_DESCR			0xFF020102
-#define OID_SKGE_SENSOR_TYPE			0xFF020103
-#define OID_SKGE_SENSOR_VALUE			0xFF020104
-#define OID_SKGE_SENSOR_WAR_THRES_LOW	0xFF020105
-#define OID_SKGE_SENSOR_WAR_THRES_UPP	0xFF020106
-#define OID_SKGE_SENSOR_ERR_THRES_LOW	0xFF020107
-#define OID_SKGE_SENSOR_ERR_THRES_UPP	0xFF020108
-#define OID_SKGE_SENSOR_STATUS			0xFF020109
-#define OID_SKGE_SENSOR_WAR_CTS			0xFF02010A
-#define OID_SKGE_SENSOR_ERR_CTS			0xFF02010B
-#define OID_SKGE_SENSOR_WAR_TIME		0xFF02010C
-#define OID_SKGE_SENSOR_ERR_TIME		0xFF02010D
-
-#define OID_SKGE_CHKSM_NUMBER			0xFF020110
-#define OID_SKGE_CHKSM_RX_OK_CTS		0xFF020111
-#define OID_SKGE_CHKSM_RX_UNABLE_CTS	0xFF020112
-#define OID_SKGE_CHKSM_RX_ERR_CTS		0xFF020113
-#define OID_SKGE_CHKSM_TX_OK_CTS		0xFF020114
-#define OID_SKGE_CHKSM_TX_UNABLE_CTS	0xFF020115
-
-#define OID_SKGE_STAT_TX				0xFF020120
-#define OID_SKGE_STAT_TX_OCTETS			0xFF020121
-#define OID_SKGE_STAT_TX_BROADCAST		0xFF020122
-#define OID_SKGE_STAT_TX_MULTICAST		0xFF020123
-#define OID_SKGE_STAT_TX_UNICAST		0xFF020124
-#define OID_SKGE_STAT_TX_LONGFRAMES		0xFF020125
-#define OID_SKGE_STAT_TX_BURST			0xFF020126
-#define OID_SKGE_STAT_TX_PFLOWC			0xFF020127
-#define OID_SKGE_STAT_TX_FLOWC			0xFF020128
-#define OID_SKGE_STAT_TX_SINGLE_COL		0xFF020129
-#define OID_SKGE_STAT_TX_MULTI_COL		0xFF02012A
-#define OID_SKGE_STAT_TX_EXCESS_COL		0xFF02012B
-#define OID_SKGE_STAT_TX_LATE_COL		0xFF02012C
-#define OID_SKGE_STAT_TX_DEFFERAL		0xFF02012D
-#define OID_SKGE_STAT_TX_EXCESS_DEF		0xFF02012E
-#define OID_SKGE_STAT_TX_UNDERRUN		0xFF02012F
-#define OID_SKGE_STAT_TX_CARRIER		0xFF020130
-/* #define OID_SKGE_STAT_TX_UTIL		0xFF020131 */
-#define OID_SKGE_STAT_TX_64				0xFF020132
-#define OID_SKGE_STAT_TX_127			0xFF020133
-#define OID_SKGE_STAT_TX_255			0xFF020134
-#define OID_SKGE_STAT_TX_511			0xFF020135
-#define OID_SKGE_STAT_TX_1023			0xFF020136
-#define OID_SKGE_STAT_TX_MAX			0xFF020137
-#define OID_SKGE_STAT_TX_SYNC			0xFF020138
-#define OID_SKGE_STAT_TX_SYNC_OCTETS	0xFF020139
-#define OID_SKGE_STAT_RX				0xFF02013A
-#define OID_SKGE_STAT_RX_OCTETS			0xFF02013B
-#define OID_SKGE_STAT_RX_BROADCAST		0xFF02013C
-#define OID_SKGE_STAT_RX_MULTICAST		0xFF02013D
-#define OID_SKGE_STAT_RX_UNICAST		0xFF02013E
-#define OID_SKGE_STAT_RX_PFLOWC			0xFF02013F
-#define OID_SKGE_STAT_RX_FLOWC			0xFF020140
-#define OID_SKGE_STAT_RX_PFLOWC_ERR		0xFF020141
-#define OID_SKGE_STAT_RX_FLOWC_UNKWN	0xFF020142
-#define OID_SKGE_STAT_RX_BURST			0xFF020143
-#define OID_SKGE_STAT_RX_MISSED			0xFF020144
-#define OID_SKGE_STAT_RX_FRAMING		0xFF020145
-#define OID_SKGE_STAT_RX_OVERFLOW		0xFF020146
-#define OID_SKGE_STAT_RX_JABBER			0xFF020147
-#define OID_SKGE_STAT_RX_CARRIER		0xFF020148
-#define OID_SKGE_STAT_RX_IR_LENGTH		0xFF020149
-#define OID_SKGE_STAT_RX_SYMBOL			0xFF02014A
-#define OID_SKGE_STAT_RX_SHORTS			0xFF02014B
-#define OID_SKGE_STAT_RX_RUNT			0xFF02014C
-#define OID_SKGE_STAT_RX_CEXT			0xFF02014D
-#define OID_SKGE_STAT_RX_TOO_LONG		0xFF02014E
-#define OID_SKGE_STAT_RX_FCS			0xFF02014F
-/* #define OID_SKGE_STAT_RX_UTIL		0xFF020150 */
-#define OID_SKGE_STAT_RX_64				0xFF020151
-#define OID_SKGE_STAT_RX_127			0xFF020152
-#define OID_SKGE_STAT_RX_255			0xFF020153
-#define OID_SKGE_STAT_RX_511			0xFF020154
-#define OID_SKGE_STAT_RX_1023			0xFF020155
-#define OID_SKGE_STAT_RX_MAX			0xFF020156
-#define OID_SKGE_STAT_RX_LONGFRAMES		0xFF020157
-
-#define OID_SKGE_RLMT_CHANGE_CTS		0xFF020160
-#define OID_SKGE_RLMT_CHANGE_TIME		0xFF020161
-#define OID_SKGE_RLMT_CHANGE_ESTIM		0xFF020162
-#define OID_SKGE_RLMT_CHANGE_THRES		0xFF020163
-
-#define OID_SKGE_RLMT_PORT_INDEX		0xFF020164
-#define OID_SKGE_RLMT_STATUS			0xFF020165
-#define OID_SKGE_RLMT_TX_HELLO_CTS		0xFF020166
-#define OID_SKGE_RLMT_RX_HELLO_CTS		0xFF020167
-#define OID_SKGE_RLMT_TX_SP_REQ_CTS		0xFF020168
-#define OID_SKGE_RLMT_RX_SP_CTS			0xFF020169
-
-#define OID_SKGE_RLMT_MONITOR_NUMBER	0xFF010150
-#define OID_SKGE_RLMT_MONITOR_INDEX		0xFF010151
-#define OID_SKGE_RLMT_MONITOR_ADDR		0xFF010152
-#define OID_SKGE_RLMT_MONITOR_ERRS		0xFF010153
-#define OID_SKGE_RLMT_MONITOR_TIMESTAMP	0xFF010154
-#define OID_SKGE_RLMT_MONITOR_ADMIN		0xFF010155
-
-#define OID_SKGE_TX_SW_QUEUE_LEN		0xFF020170
-#define OID_SKGE_TX_SW_QUEUE_MAX		0xFF020171
-#define OID_SKGE_TX_RETRY				0xFF020172
-#define OID_SKGE_RX_INTR_CTS			0xFF020173
-#define OID_SKGE_TX_INTR_CTS			0xFF020174
-#define OID_SKGE_RX_NO_BUF_CTS			0xFF020175
-#define OID_SKGE_TX_NO_BUF_CTS			0xFF020176
-#define OID_SKGE_TX_USED_DESCR_NO		0xFF020177
-#define OID_SKGE_RX_DELIVERED_CTS		0xFF020178
-#define OID_SKGE_RX_OCTETS_DELIV_CTS	0xFF020179
-#define OID_SKGE_RX_HW_ERROR_CTS		0xFF02017A
-#define OID_SKGE_TX_HW_ERROR_CTS		0xFF02017B
-#define OID_SKGE_IN_ERRORS_CTS			0xFF02017C
-#define OID_SKGE_OUT_ERROR_CTS			0xFF02017D
-#define OID_SKGE_ERR_RECOVERY_CTS		0xFF02017E
-#define OID_SKGE_SYSUPTIME				0xFF02017F
-
-#define OID_SKGE_ALL_DATA				0xFF020190
-
-/* Defines for VCT. */
-#define OID_SKGE_VCT_GET				0xFF020200
-#define OID_SKGE_VCT_SET				0xFF020201
-#define OID_SKGE_VCT_STATUS				0xFF020202
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define OID_SKGE_DIAG_MODE				0xFF020204
-#endif /* SK_DIAG_SUPPORT */
-
-/* New OIDs */
-#define OID_SKGE_DRIVER_RELDATE			0xFF020210
-#define OID_SKGE_DRIVER_FILENAME		0xFF020211
-#define OID_SKGE_CHIPID					0xFF020212
-#define OID_SKGE_RAMSIZE				0xFF020213
-#define OID_SKGE_VAUXAVAIL				0xFF020214
-#define OID_SKGE_PHY_TYPE				0xFF020215
-#define OID_SKGE_PHY_LP_MODE			0xFF020216
-
-/* VCT struct to store a backup copy of VCT data after a port reset. */
-typedef struct s_PnmiVct {
-	SK_U8			VctStatus;
-	SK_U8			PCableLen;
-	SK_U32			PMdiPairLen[4];
-	SK_U8			PMdiPairSts[4];
-} SK_PNMI_VCT;
-
-
-/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
-#define SK_PNMI_VCT_NONE		0
-#define SK_PNMI_VCT_OLD_VCT_DATA	1
-#define SK_PNMI_VCT_NEW_VCT_DATA	2
-#define SK_PNMI_VCT_OLD_DSP_DATA	4
-#define SK_PNMI_VCT_NEW_DSP_DATA	8
-#define SK_PNMI_VCT_RUNNING		16
-
-
-/* VCT cable test status. */
-#define SK_PNMI_VCT_NORMAL_CABLE		0
-#define SK_PNMI_VCT_SHORT_CABLE			1
-#define SK_PNMI_VCT_OPEN_CABLE			2
-#define SK_PNMI_VCT_TEST_FAIL			3
-#define SK_PNMI_VCT_IMPEDANCE_MISMATCH		4
-
-#define	OID_SKGE_TRAP_SEN_WAR_LOW		500
-#define OID_SKGE_TRAP_SEN_WAR_UPP		501
-#define	OID_SKGE_TRAP_SEN_ERR_LOW		502
-#define OID_SKGE_TRAP_SEN_ERR_UPP		503
-#define OID_SKGE_TRAP_RLMT_CHANGE_THRES	520
-#define OID_SKGE_TRAP_RLMT_CHANGE_PORT	521
-#define OID_SKGE_TRAP_RLMT_PORT_DOWN	522
-#define OID_SKGE_TRAP_RLMT_PORT_UP		523
-#define OID_SKGE_TRAP_RLMT_SEGMENTATION	524
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define SK_DIAG_ATTACHED	2
-#define SK_DIAG_RUNNING		1
-#define SK_DIAG_IDLE		0
-#endif /* SK_DIAG_SUPPORT */
-
-/*
- * Generic PNMI IOCTL subcommand definitions.
- */
-#define	SK_GET_SINGLE_VAR		1
-#define	SK_SET_SINGLE_VAR		2
-#define	SK_PRESET_SINGLE_VAR	3
-#define	SK_GET_FULL_MIB			4
-#define	SK_SET_FULL_MIB			5
-#define	SK_PRESET_FULL_MIB		6
-
-
-/*
- * Define error numbers and messages for syslog
- */
-#define SK_PNMI_ERR001		(SK_ERRBASE_PNMI + 1)
-#define SK_PNMI_ERR001MSG	"SkPnmiGetStruct: Unknown OID"
-#define SK_PNMI_ERR002		(SK_ERRBASE_PNMI + 2)
-#define SK_PNMI_ERR002MSG	"SkPnmiGetStruct: Cannot read VPD keys"
-#define SK_PNMI_ERR003		(SK_ERRBASE_PNMI + 3)
-#define SK_PNMI_ERR003MSG	"OidStruct: Called with wrong OID"
-#define SK_PNMI_ERR004		(SK_ERRBASE_PNMI + 4)
-#define SK_PNMI_ERR004MSG	"OidStruct: Called with wrong action"
-#define SK_PNMI_ERR005		(SK_ERRBASE_PNMI + 5)
-#define SK_PNMI_ERR005MSG	"Perform: Cannot reset driver"
-#define SK_PNMI_ERR006		(SK_ERRBASE_PNMI + 6)
-#define SK_PNMI_ERR006MSG	"Perform: Unknown OID action command"
-#define SK_PNMI_ERR007		(SK_ERRBASE_PNMI + 7)
-#define SK_PNMI_ERR007MSG	"General: Driver description not initialized"
-#define SK_PNMI_ERR008		(SK_ERRBASE_PNMI + 8)
-#define SK_PNMI_ERR008MSG	"Addr: Tried to get unknown OID"
-#define SK_PNMI_ERR009		(SK_ERRBASE_PNMI + 9)
-#define SK_PNMI_ERR009MSG	"Addr: Unknown OID"
-#define SK_PNMI_ERR010		(SK_ERRBASE_PNMI + 10)
-#define SK_PNMI_ERR010MSG	"CsumStat: Unknown OID"
-#define SK_PNMI_ERR011		(SK_ERRBASE_PNMI + 11)
-#define SK_PNMI_ERR011MSG	"SensorStat: Sensor descr string too long"
-#define SK_PNMI_ERR012		(SK_ERRBASE_PNMI + 12)
-#define SK_PNMI_ERR012MSG	"SensorStat: Unknown OID"
-#define SK_PNMI_ERR013		(SK_ERRBASE_PNMI + 13)
-#define SK_PNMI_ERR013MSG	""
-#define SK_PNMI_ERR014		(SK_ERRBASE_PNMI + 14)
-#define SK_PNMI_ERR014MSG	"Vpd: Cannot read VPD keys"
-#define SK_PNMI_ERR015		(SK_ERRBASE_PNMI + 15)
-#define SK_PNMI_ERR015MSG	"Vpd: Internal array for VPD keys to small"
-#define SK_PNMI_ERR016		(SK_ERRBASE_PNMI + 16)
-#define SK_PNMI_ERR016MSG	"Vpd: Key string too long"
-#define SK_PNMI_ERR017		(SK_ERRBASE_PNMI + 17)
-#define SK_PNMI_ERR017MSG	"Vpd: Invalid VPD status pointer"
-#define SK_PNMI_ERR018		(SK_ERRBASE_PNMI + 18)
-#define SK_PNMI_ERR018MSG	"Vpd: VPD data not valid"
-#define SK_PNMI_ERR019		(SK_ERRBASE_PNMI + 19)
-#define SK_PNMI_ERR019MSG	"Vpd: VPD entries list string too long"
-#define SK_PNMI_ERR021		(SK_ERRBASE_PNMI + 21)
-#define SK_PNMI_ERR021MSG	"Vpd: VPD data string too long"
-#define SK_PNMI_ERR022		(SK_ERRBASE_PNMI + 22)
-#define SK_PNMI_ERR022MSG	"Vpd: VPD data string too long should be errored before"
-#define SK_PNMI_ERR023		(SK_ERRBASE_PNMI + 23)
-#define SK_PNMI_ERR023MSG	"Vpd: Unknown OID in get action"
-#define SK_PNMI_ERR024		(SK_ERRBASE_PNMI + 24)
-#define SK_PNMI_ERR024MSG	"Vpd: Unknown OID in preset/set action"
-#define SK_PNMI_ERR025		(SK_ERRBASE_PNMI + 25)
-#define SK_PNMI_ERR025MSG	"Vpd: Cannot write VPD after modify entry"
-#define SK_PNMI_ERR026		(SK_ERRBASE_PNMI + 26)
-#define SK_PNMI_ERR026MSG	"Vpd: Cannot update VPD"
-#define SK_PNMI_ERR027		(SK_ERRBASE_PNMI + 27)
-#define SK_PNMI_ERR027MSG	"Vpd: Cannot delete VPD entry"
-#define SK_PNMI_ERR028		(SK_ERRBASE_PNMI + 28)
-#define SK_PNMI_ERR028MSG	"Vpd: Cannot update VPD after delete entry"
-#define SK_PNMI_ERR029		(SK_ERRBASE_PNMI + 29)
-#define SK_PNMI_ERR029MSG	"General: Driver description string too long"
-#define SK_PNMI_ERR030		(SK_ERRBASE_PNMI + 30)
-#define SK_PNMI_ERR030MSG	"General: Driver version not initialized"
-#define SK_PNMI_ERR031		(SK_ERRBASE_PNMI + 31)
-#define SK_PNMI_ERR031MSG	"General: Driver version string too long"
-#define SK_PNMI_ERR032		(SK_ERRBASE_PNMI + 32)
-#define SK_PNMI_ERR032MSG	"General: Cannot read VPD Name for HW descr"
-#define SK_PNMI_ERR033		(SK_ERRBASE_PNMI + 33)
-#define SK_PNMI_ERR033MSG	"General: HW description string too long"
-#define SK_PNMI_ERR034		(SK_ERRBASE_PNMI + 34)
-#define SK_PNMI_ERR034MSG	"General: Unknown OID"
-#define SK_PNMI_ERR035		(SK_ERRBASE_PNMI + 35)
-#define SK_PNMI_ERR035MSG	"Rlmt: Unknown OID"
-#define SK_PNMI_ERR036		(SK_ERRBASE_PNMI + 36)
-#define SK_PNMI_ERR036MSG	""
-#define SK_PNMI_ERR037		(SK_ERRBASE_PNMI + 37)
-#define SK_PNMI_ERR037MSG	"Rlmt: SK_RLMT_MODE_CHANGE event return not 0"
-#define SK_PNMI_ERR038		(SK_ERRBASE_PNMI + 38)
-#define SK_PNMI_ERR038MSG	"Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0"
-#define SK_PNMI_ERR039		(SK_ERRBASE_PNMI + 39)
-#define SK_PNMI_ERR039MSG	"RlmtStat: Unknown OID"
-#define SK_PNMI_ERR040		(SK_ERRBASE_PNMI + 40)
-#define SK_PNMI_ERR040MSG	"PowerManagement: Unknown OID"
-#define SK_PNMI_ERR041		(SK_ERRBASE_PNMI + 41)
-#define SK_PNMI_ERR041MSG	"MacPrivateConf: Unknown OID"
-#define SK_PNMI_ERR042		(SK_ERRBASE_PNMI + 42)
-#define SK_PNMI_ERR042MSG	"MacPrivateConf: SK_HWEV_SET_ROLE returned not 0"
-#define SK_PNMI_ERR043		(SK_ERRBASE_PNMI + 43)
-#define SK_PNMI_ERR043MSG	"MacPrivateConf: SK_HWEV_SET_LMODE returned not 0"
-#define SK_PNMI_ERR044		(SK_ERRBASE_PNMI + 44)
-#define SK_PNMI_ERR044MSG	"MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0"
-#define SK_PNMI_ERR045		(SK_ERRBASE_PNMI + 45)
-#define SK_PNMI_ERR045MSG	"MacPrivateConf: SK_HWEV_SET_SPEED returned not 0"
-#define SK_PNMI_ERR046		(SK_ERRBASE_PNMI + 46)
-#define SK_PNMI_ERR046MSG	"Monitor: Unknown OID"
-#define SK_PNMI_ERR047		(SK_ERRBASE_PNMI + 47)
-#define SK_PNMI_ERR047MSG	"SirqUpdate: Event function returns not 0"
-#define SK_PNMI_ERR048		(SK_ERRBASE_PNMI + 48)
-#define SK_PNMI_ERR048MSG	"RlmtUpdate: Event function returns not 0"
-#define SK_PNMI_ERR049		(SK_ERRBASE_PNMI + 49)
-#define SK_PNMI_ERR049MSG	"SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
-#define SK_PNMI_ERR050		(SK_ERRBASE_PNMI + 50)
-#define SK_PNMI_ERR050MSG	"SkPnmiInit: Invalid size of 'StatAddr' table!!"
-#define SK_PNMI_ERR051		(SK_ERRBASE_PNMI + 51)
-#define SK_PNMI_ERR051MSG	"SkPnmiEvent: Port switch suspicious"
-#define SK_PNMI_ERR052		(SK_ERRBASE_PNMI + 52)
-#define SK_PNMI_ERR052MSG	""
-#define SK_PNMI_ERR053		(SK_ERRBASE_PNMI + 53)
-#define SK_PNMI_ERR053MSG	"General: Driver release date not initialized"
-#define SK_PNMI_ERR054		(SK_ERRBASE_PNMI + 54)
-#define SK_PNMI_ERR054MSG	"General: Driver release date string too long"
-#define SK_PNMI_ERR055		(SK_ERRBASE_PNMI + 55)
-#define SK_PNMI_ERR055MSG	"General: Driver file name not initialized"
-#define SK_PNMI_ERR056		(SK_ERRBASE_PNMI + 56)
-#define SK_PNMI_ERR056MSG	"General: Driver file name string too long"
-
-/*
- * Management counter macros called by the driver
- */
-#define SK_PNMI_SET_DRIVER_DESCR(pAC,v)	((pAC)->Pnmi.pDriverDescription = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_VER(pAC,v)	((pAC)->Pnmi.pDriverVersion = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v)	((pAC)->Pnmi.pDriverReleaseDate = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v)	((pAC)->Pnmi.pDriverFileName = \
-	(char *)(v))
-
-#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \
-	{ \
-		(pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \
-		if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \
-			(pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \
-		} \
-	}
-#define SK_PNMI_CNT_TX_RETRY(pAC,p)	(((pAC)->Pnmi.Port[p].TxRetryCts)++)
-#define SK_PNMI_CNT_RX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].RxIntrCts)++)
-#define SK_PNMI_CNT_TX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].TxIntrCts)++)
-#define SK_PNMI_CNT_NO_RX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].RxNoBufCts)++)
-#define SK_PNMI_CNT_NO_TX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].TxNoBufCts)++)
-#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \
-	((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v));
-#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \
-	{ \
-		((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \
-		(pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \
-	}
-#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p)	(((pAC)->Pnmi.Port[p].ErrRecoveryCts)++);
-
-#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatSyncCts)++; \
-			(pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \
-		} \
-	}
-
-/*
- * Conversion Macros
- */
-#define SK_PNMI_PORT_INST2LOG(i)	((unsigned int)(i) - 1)
-#define SK_PNMI_PORT_LOG2INST(l)	((unsigned int)(l) + 1)
-#define SK_PNMI_PORT_PHYS2LOG(p)	((unsigned int)(p) + 1)
-#define SK_PNMI_PORT_LOG2PHYS(pAC,l)	((unsigned int)(l) - 1)
-#define SK_PNMI_PORT_PHYS2INST(pAC,p)	\
-	(pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2))
-#define SK_PNMI_PORT_INST2PHYS(pAC,i)	((unsigned int)(i) - 2)
-
-/*
- * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct
- */
-#define SK_PNMI_VPD_KEY_SIZE	5
-#define SK_PNMI_VPD_BUFSIZE		(VPD_SIZE)
-#define SK_PNMI_VPD_ENTRIES		(VPD_SIZE / 4)
-#define SK_PNMI_VPD_DATALEN		128 /*  Number of data bytes */
-
-#define SK_PNMI_MULTICAST_LISTLEN	64
-#define SK_PNMI_SENSOR_ENTRIES		(SK_MAX_SENSORS)
-#define SK_PNMI_CHECKSUM_ENTRIES	3
-#define SK_PNMI_MAC_ENTRIES			(SK_MAX_MACS + 1)
-#define SK_PNMI_MONITOR_ENTRIES		20
-#define SK_PNMI_TRAP_ENTRIES		10
-#define SK_PNMI_TRAPLEN				128
-#define SK_PNMI_STRINGLEN1			80
-#define SK_PNMI_STRINGLEN2			25
-#define SK_PNMI_TRAP_QUEUE_LEN		512
-
-typedef struct s_PnmiVpd {
-	char			VpdKey[SK_PNMI_VPD_KEY_SIZE];
-	char			VpdValue[SK_PNMI_VPD_DATALEN];
-	SK_U8			VpdAccess;
-	SK_U8			VpdAction;
-} SK_PNMI_VPD;
-
-typedef struct s_PnmiSensor {
-	SK_U8			SensorIndex;
-	char			SensorDescr[SK_PNMI_STRINGLEN2];
-	SK_U8			SensorType;
-	SK_U32			SensorValue;
-	SK_U32			SensorWarningThresholdLow;
-	SK_U32			SensorWarningThresholdHigh;
-	SK_U32			SensorErrorThresholdLow;
-	SK_U32			SensorErrorThresholdHigh;
-	SK_U8			SensorStatus;
-	SK_U64			SensorWarningCts;
-	SK_U64			SensorErrorCts;
-	SK_U64			SensorWarningTimestamp;
-	SK_U64			SensorErrorTimestamp;
-} SK_PNMI_SENSOR;
-
-typedef struct s_PnmiChecksum {
-	SK_U64			ChecksumRxOkCts;
-	SK_U64			ChecksumRxUnableCts;
-	SK_U64			ChecksumRxErrCts;
-	SK_U64			ChecksumTxOkCts;
-	SK_U64			ChecksumTxUnableCts;
-} SK_PNMI_CHECKSUM;
-
-typedef struct s_PnmiStat {
-	SK_U64			StatTxOkCts;
-	SK_U64			StatTxOctetsOkCts;
-	SK_U64			StatTxBroadcastOkCts;
-	SK_U64			StatTxMulticastOkCts;
-	SK_U64			StatTxUnicastOkCts;
-	SK_U64			StatTxLongFramesCts;
-	SK_U64			StatTxBurstCts;
-	SK_U64			StatTxPauseMacCtrlCts;
-	SK_U64			StatTxMacCtrlCts;
-	SK_U64			StatTxSingleCollisionCts;
-	SK_U64			StatTxMultipleCollisionCts;
-	SK_U64			StatTxExcessiveCollisionCts;
-	SK_U64			StatTxLateCollisionCts;
-	SK_U64			StatTxDeferralCts;
-	SK_U64			StatTxExcessiveDeferralCts;
-	SK_U64			StatTxFifoUnderrunCts;
-	SK_U64			StatTxCarrierCts;
-	SK_U64			Dummy1; /* StatTxUtilization */
-	SK_U64			StatTx64Cts;
-	SK_U64			StatTx127Cts;
-	SK_U64			StatTx255Cts;
-	SK_U64			StatTx511Cts;
-	SK_U64			StatTx1023Cts;
-	SK_U64			StatTxMaxCts;
-	SK_U64			StatTxSyncCts;
-	SK_U64			StatTxSyncOctetsCts;
-	SK_U64			StatRxOkCts;
-	SK_U64			StatRxOctetsOkCts;
-	SK_U64			StatRxBroadcastOkCts;
-	SK_U64			StatRxMulticastOkCts;
-	SK_U64			StatRxUnicastOkCts;
-	SK_U64			StatRxLongFramesCts;
-	SK_U64			StatRxPauseMacCtrlCts;
-	SK_U64			StatRxMacCtrlCts;
-	SK_U64			StatRxPauseMacCtrlErrorCts;
-	SK_U64			StatRxMacCtrlUnknownCts;
-	SK_U64			StatRxBurstCts;
-	SK_U64			StatRxMissedCts;
-	SK_U64			StatRxFramingCts;
-	SK_U64			StatRxFifoOverflowCts;
-	SK_U64			StatRxJabberCts;
-	SK_U64			StatRxCarrierCts;
-	SK_U64			StatRxIRLengthCts;
-	SK_U64			StatRxSymbolCts;
-	SK_U64			StatRxShortsCts;
-	SK_U64			StatRxRuntCts;
-	SK_U64			StatRxCextCts;
-	SK_U64			StatRxTooLongCts;
-	SK_U64			StatRxFcsCts;
-	SK_U64			Dummy2; /* StatRxUtilization */
-	SK_U64			StatRx64Cts;
-	SK_U64			StatRx127Cts;
-	SK_U64			StatRx255Cts;
-	SK_U64			StatRx511Cts;
-	SK_U64			StatRx1023Cts;
-	SK_U64			StatRxMaxCts;
-} SK_PNMI_STAT;
-
-typedef struct s_PnmiConf {
-	char			ConfMacCurrentAddr[6];
-	char			ConfMacFactoryAddr[6];
-	SK_U8			ConfPMD;
-	SK_U8			ConfConnector;
-	SK_U32			ConfPhyType;
-	SK_U32			ConfPhyMode;
-	SK_U8			ConfLinkCapability;
-	SK_U8			ConfLinkMode;
-	SK_U8			ConfLinkModeStatus;
-	SK_U8			ConfLinkStatus;
-	SK_U8			ConfFlowCtrlCapability;
-	SK_U8			ConfFlowCtrlMode;
-	SK_U8			ConfFlowCtrlStatus;
-	SK_U8			ConfPhyOperationCapability;
-	SK_U8			ConfPhyOperationMode;
-	SK_U8			ConfPhyOperationStatus;
-	SK_U8			ConfSpeedCapability;
-	SK_U8			ConfSpeedMode;
-	SK_U8			ConfSpeedStatus;
-} SK_PNMI_CONF;
-
-typedef struct s_PnmiRlmt {
-	SK_U32			RlmtIndex;
-	SK_U32			RlmtStatus;
-	SK_U64			RlmtTxHelloCts;
-	SK_U64			RlmtRxHelloCts;
-	SK_U64			RlmtTxSpHelloReqCts;
-	SK_U64			RlmtRxSpHelloCts;
-} SK_PNMI_RLMT;
-
-typedef struct s_PnmiRlmtMonitor {
-	SK_U32			RlmtMonitorIndex;
-	char			RlmtMonitorAddr[6];
-	SK_U64			RlmtMonitorErrorCts;
-	SK_U64			RlmtMonitorTimestamp;
-	SK_U8			RlmtMonitorAdmin;
-} SK_PNMI_RLMT_MONITOR;
-
-typedef struct s_PnmiRequestStatus {
-	SK_U32			ErrorStatus;
-	SK_U32			ErrorOffset;
-} SK_PNMI_REQUEST_STATUS;
-
-typedef struct s_PnmiStrucData {
-	SK_U32			MgmtDBVersion;
-	SK_PNMI_REQUEST_STATUS	ReturnStatus;
-	SK_U32			VpdFreeBytes;
-	char			VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE];
-	SK_U32			VpdEntriesNumber;
-	SK_PNMI_VPD		Vpd[SK_PNMI_VPD_ENTRIES];
-	SK_U32			PortNumber;
-	SK_U32			DeviceType;
-	char			DriverDescr[SK_PNMI_STRINGLEN1];
-	char			DriverVersion[SK_PNMI_STRINGLEN2];
-	char			DriverReleaseDate[SK_PNMI_STRINGLEN1];
-	char			DriverFileName[SK_PNMI_STRINGLEN1];
-	char			HwDescr[SK_PNMI_STRINGLEN1];
-	char			HwVersion[SK_PNMI_STRINGLEN2];
-	SK_U16			Chipset;
-	SK_U32			ChipId;
-	SK_U8			VauxAvail;
-	SK_U32			RamSize;
-	SK_U32			MtuSize;
-	SK_U32			Action;
-	SK_U32			TestResult;
-	SK_U8			BusType;
-	SK_U8			BusSpeed;
-	SK_U8			BusWidth;
-	SK_U8			SensorNumber;
-	SK_PNMI_SENSOR	Sensor[SK_PNMI_SENSOR_ENTRIES];
-	SK_U8			ChecksumNumber;
-	SK_PNMI_CHECKSUM	Checksum[SK_PNMI_CHECKSUM_ENTRIES];
-	SK_PNMI_STAT	Stat[SK_PNMI_MAC_ENTRIES];
-	SK_PNMI_CONF	Conf[SK_PNMI_MAC_ENTRIES];
-	SK_U8			RlmtMode;
-	SK_U32			RlmtPortNumber;
-	SK_U8			RlmtPortActive;
-	SK_U8			RlmtPortPreferred;
-	SK_U64			RlmtChangeCts;
-	SK_U64			RlmtChangeTime;
-	SK_U64			RlmtChangeEstimate;
-	SK_U64			RlmtChangeThreshold;
-	SK_PNMI_RLMT	Rlmt[SK_MAX_MACS];
-	SK_U32			RlmtMonitorNumber;
-	SK_PNMI_RLMT_MONITOR	RlmtMonitor[SK_PNMI_MONITOR_ENTRIES];
-	SK_U32			TrapNumber;
-	SK_U8			Trap[SK_PNMI_TRAP_QUEUE_LEN];
-	SK_U64			TxSwQueueLen;
-	SK_U64			TxSwQueueMax;
-	SK_U64			TxRetryCts;
-	SK_U64			RxIntrCts;
-	SK_U64			TxIntrCts;
-	SK_U64			RxNoBufCts;
-	SK_U64			TxNoBufCts;
-	SK_U64			TxUsedDescrNo;
-	SK_U64			RxDeliveredCts;
-	SK_U64			RxOctetsDeliveredCts;
-	SK_U64			RxHwErrorsCts;
-	SK_U64			TxHwErrorsCts;
-	SK_U64			InErrorsCts;
-	SK_U64			OutErrorsCts;
-	SK_U64			ErrRecoveryCts;
-	SK_U64			SysUpTime;
-} SK_PNMI_STRUCT_DATA;
-
-#define SK_PNMI_STRUCT_SIZE	(sizeof(SK_PNMI_STRUCT_DATA))
-#define SK_PNMI_MIN_STRUCT_SIZE	((unsigned int)(SK_UPTR)\
-				 &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
-														/*
-														 * ReturnStatus field
-														 * must be located
-														 * before VpdFreeBytes
-														 */
-
-/*
- * Various definitions
- */
-#define SK_PNMI_MAX_PROTOS		3
-
-#define SK_PNMI_CNT_NO			66	/* Must have the value of the enum
-									 * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK
-									 * for check while init phase 1
-									 */
-
-/*
- * Estimate data structure
- */
-typedef struct s_PnmiEstimate {
-	unsigned int	EstValueIndex;
-	SK_U64			EstValue[7];
-	SK_U64			Estimate;
-	SK_TIMER		EstTimer;
-} SK_PNMI_ESTIMATE;
-
-
-/*
- * VCT timer data structure
- */
-typedef struct s_VctTimer {
-	SK_TIMER		VctTimer;
-} SK_PNMI_VCT_TIMER;
-
-
-/*
- * PNMI specific adapter context structure
- */
-typedef struct s_PnmiPort {
-	SK_U64			StatSyncCts;
-	SK_U64			StatSyncOctetsCts;
-	SK_U64			StatRxLongFrameCts;
-	SK_U64			StatRxFrameTooLongCts;
-	SK_U64			StatRxPMaccErr;
-	SK_U64			TxSwQueueLen;
-	SK_U64			TxSwQueueMax;
-	SK_U64			TxRetryCts;
-	SK_U64			RxIntrCts;
-	SK_U64			TxIntrCts;
-	SK_U64			RxNoBufCts;
-	SK_U64			TxNoBufCts;
-	SK_U64			TxUsedDescrNo;
-	SK_U64			RxDeliveredCts;
-	SK_U64			RxOctetsDeliveredCts;
-	SK_U64			RxHwErrorsCts;
-	SK_U64			TxHwErrorsCts;
-	SK_U64			InErrorsCts;
-	SK_U64			OutErrorsCts;
-	SK_U64			ErrRecoveryCts;
-	SK_U64			RxShortZeroMark;
-	SK_U64			CounterOffset[SK_PNMI_CNT_NO];
-	SK_U32			CounterHigh[SK_PNMI_CNT_NO];
-	SK_BOOL			ActiveFlag;
-	SK_U8			Align[3];
-} SK_PNMI_PORT;
-
-
-typedef struct s_PnmiData {
-	SK_PNMI_PORT	Port	[SK_MAX_MACS];
-	SK_PNMI_PORT	BufPort	[SK_MAX_MACS]; /* 2002-09-13 pweber  */
-	SK_U64			VirtualCounterOffset[SK_PNMI_CNT_NO];
-	SK_U32			TestResult;
-	char			HwVersion[10];
-	SK_U16			Align01;
-
-	char			*pDriverDescription;
-	char			*pDriverVersion;
-	char			*pDriverReleaseDate;
-	char			*pDriverFileName;
-
-	int				MacUpdatedFlag;
-	int				RlmtUpdatedFlag;
-	int				SirqUpdatedFlag;
-
-	SK_U64			RlmtChangeCts;
-	SK_U64			RlmtChangeTime;
-	SK_PNMI_ESTIMATE	RlmtChangeEstimate;
-	SK_U64			RlmtChangeThreshold;
-
-	SK_U64			StartUpTime;
-	SK_U32			DeviceType;
-	char			PciBusSpeed;
-	char			PciBusWidth;
-	char			Chipset;
-	char			PMD;
-	char			Connector;
-	SK_BOOL			DualNetActiveFlag;
-	SK_U16			Align02;
-
-	char			TrapBuf[SK_PNMI_TRAP_QUEUE_LEN];
-	unsigned int	TrapBufFree;
-	unsigned int	TrapQueueBeg;
-	unsigned int	TrapQueueEnd;
-	unsigned int	TrapBufPad;
-	unsigned int	TrapUnique;
-	SK_U8		VctStatus[SK_MAX_MACS];
-	SK_PNMI_VCT	VctBackup[SK_MAX_MACS];
-	SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS];
-#ifdef SK_DIAG_SUPPORT
-	SK_U32			DiagAttached;
-#endif /* SK_DIAG_SUPPORT */
-} SK_PNMI;
-
-
-/*
- * Function prototypes
- */
-extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
-extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
-	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event,
-	SK_EVPARA Param);
-extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
-	unsigned int * pLen, SK_U32 NetIndex);
-
-#endif
diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
deleted file mode 100644
index 3eec627..0000000
--- a/drivers/net/sk98lin/h/skgesirq.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgesirq.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.30 $
- * Date:	$Date: 2003/07/04 12:34:13 $
- * Purpose:	SK specific Gigabit Ethernet special IRQ functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKGESIRQ_H_
-#define _INC_SKGESIRQ_H_
-
-/* Define return codes of SkGePortCheckUp and CheckShort */
-#define	SK_HW_PS_NONE		0	/* No action needed */
-#define	SK_HW_PS_RESTART	1	/* Restart needed */
-#define	SK_HW_PS_LINK		2	/* Link Up actions needed */
-
-/*
- * Define the Event the special IRQ/INI module can handle
- */
-#define SK_HWEV_WATIM			1	/* Timeout for WA Errata #2 XMAC */
-#define SK_HWEV_PORT_START		2	/* Port Start Event by RLMT */
-#define SK_HWEV_PORT_STOP		3	/* Port Stop Event by RLMT */
-#define SK_HWEV_CLEAR_STAT		4	/* Clear Statistics by PNMI */
-#define SK_HWEV_UPDATE_STAT		5	/* Update Statistics by PNMI */
-#define SK_HWEV_SET_LMODE		6	/* Set Link Mode by PNMI */
-#define SK_HWEV_SET_FLOWMODE	7	/* Set Flow Control Mode by PNMI */
-#define SK_HWEV_SET_ROLE		8	/* Set Master/Slave (Role) by PNMI */
-#define SK_HWEV_SET_SPEED		9	/* Set Link Speed by PNMI */
-#define SK_HWEV_HALFDUP_CHK		10	/* Half Duplex Hangup Workaround */
-
-#define SK_WA_ACT_TIME		(5000000UL)	/* 5 sec */
-#define SK_WA_INA_TIME		(100000UL)	/* 100 msec */
-
-#define SK_HALFDUP_CHK_TIME	(10000UL)	/* 10 msec */
-
-/*
- * Define the error numbers and messages
- */
-#define SKERR_SIRQ_E001		(SK_ERRBASE_SIRQ+0)
-#define SKERR_SIRQ_E001MSG	"Unknown event"
-#define SKERR_SIRQ_E002		(SKERR_SIRQ_E001+1)
-#define SKERR_SIRQ_E002MSG	"Packet timeout RX1"
-#define SKERR_SIRQ_E003		(SKERR_SIRQ_E002+1)
-#define SKERR_SIRQ_E003MSG	"Packet timeout RX2"
-#define SKERR_SIRQ_E004		(SKERR_SIRQ_E003+1)
-#define SKERR_SIRQ_E004MSG	"MAC 1 not correctly initialized"
-#define SKERR_SIRQ_E005		(SKERR_SIRQ_E004+1)
-#define SKERR_SIRQ_E005MSG	"MAC 2 not correctly initialized"
-#define SKERR_SIRQ_E006		(SKERR_SIRQ_E005+1)
-#define SKERR_SIRQ_E006MSG	"CHECK failure R1"
-#define SKERR_SIRQ_E007		(SKERR_SIRQ_E006+1)
-#define SKERR_SIRQ_E007MSG	"CHECK failure R2"
-#define SKERR_SIRQ_E008		(SKERR_SIRQ_E007+1)
-#define SKERR_SIRQ_E008MSG	"CHECK failure XS1"
-#define SKERR_SIRQ_E009		(SKERR_SIRQ_E008+1)
-#define SKERR_SIRQ_E009MSG	"CHECK failure XA1"
-#define SKERR_SIRQ_E010		(SKERR_SIRQ_E009+1)
-#define SKERR_SIRQ_E010MSG	"CHECK failure XS2"
-#define SKERR_SIRQ_E011		(SKERR_SIRQ_E010+1)
-#define SKERR_SIRQ_E011MSG	"CHECK failure XA2"
-#define SKERR_SIRQ_E012		(SKERR_SIRQ_E011+1)
-#define SKERR_SIRQ_E012MSG	"unexpected IRQ Master error"
-#define SKERR_SIRQ_E013		(SKERR_SIRQ_E012+1)
-#define SKERR_SIRQ_E013MSG	"unexpected IRQ Status error"
-#define SKERR_SIRQ_E014		(SKERR_SIRQ_E013+1)
-#define SKERR_SIRQ_E014MSG	"Parity error on RAM (read)"
-#define SKERR_SIRQ_E015		(SKERR_SIRQ_E014+1)
-#define SKERR_SIRQ_E015MSG	"Parity error on RAM (write)"
-#define SKERR_SIRQ_E016		(SKERR_SIRQ_E015+1)
-#define SKERR_SIRQ_E016MSG	"Parity error MAC 1"
-#define SKERR_SIRQ_E017		(SKERR_SIRQ_E016+1)
-#define SKERR_SIRQ_E017MSG	"Parity error MAC 2"
-#define SKERR_SIRQ_E018		(SKERR_SIRQ_E017+1)
-#define SKERR_SIRQ_E018MSG	"Parity error RX 1"
-#define SKERR_SIRQ_E019		(SKERR_SIRQ_E018+1)
-#define SKERR_SIRQ_E019MSG	"Parity error RX 2"
-#define SKERR_SIRQ_E020		(SKERR_SIRQ_E019+1)
-#define SKERR_SIRQ_E020MSG	"MAC transmit FIFO underrun"
-#define SKERR_SIRQ_E021		(SKERR_SIRQ_E020+1)
-#define SKERR_SIRQ_E021MSG	"Spurious TWSI interrupt"
-#define SKERR_SIRQ_E022		(SKERR_SIRQ_E021+1)
-#define SKERR_SIRQ_E022MSG	"Cable pair swap error"
-#define SKERR_SIRQ_E023		(SKERR_SIRQ_E022+1)
-#define SKERR_SIRQ_E023MSG	"Auto-negotiation error"
-#define SKERR_SIRQ_E024		(SKERR_SIRQ_E023+1)
-#define SKERR_SIRQ_E024MSG	"FIFO overflow error"
-#define SKERR_SIRQ_E025		(SKERR_SIRQ_E024+1)
-#define SKERR_SIRQ_E025MSG	"2 Pair Downshift detected"
-
-extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
-extern int  SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
-
-#endif	/* _INC_SKGESIRQ_H_ */
diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h
deleted file mode 100644
index 6a63f4a..0000000
--- a/drivers/net/sk98lin/h/ski2c.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/******************************************************************************
- *
- * Name:	ski2c.h
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.35 $
- * Date:	$Date: 2003/10/20 09:06:30 $
- * Purpose:	Defines to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKI2C.H	contains all I2C specific defines
- */
-
-#ifndef _SKI2C_H_
-#define _SKI2C_H_
-
-typedef struct  s_Sensor SK_SENSOR;
-
-#include "h/skgei2c.h"
-
-/*
- * Define the I2C events.
- */
-#define SK_I2CEV_IRQ	1	/* IRQ happened Event */
-#define SK_I2CEV_TIM	2	/* Timeout event */
-#define SK_I2CEV_CLEAR	3	/* Clear MIB Values */
-
-/*
- * Define READ and WRITE Constants.
- */
-#define I2C_READ	0
-#define I2C_WRITE	1
-#define I2C_BURST	1
-#define I2C_SINGLE	0
-
-#define SKERR_I2C_E001		(SK_ERRBASE_I2C+0)
-#define SKERR_I2C_E001MSG	"Sensor index unknown"
-#define SKERR_I2C_E002		(SKERR_I2C_E001+1)
-#define SKERR_I2C_E002MSG	"TWSI: transfer does not complete"
-#define SKERR_I2C_E003		(SKERR_I2C_E002+1)
-#define SKERR_I2C_E003MSG	"LM80: NAK on device send"
-#define SKERR_I2C_E004		(SKERR_I2C_E003+1)
-#define SKERR_I2C_E004MSG	"LM80: NAK on register send"
-#define SKERR_I2C_E005		(SKERR_I2C_E004+1)
-#define SKERR_I2C_E005MSG	"LM80: NAK on device (2) send"
-#define SKERR_I2C_E006		(SKERR_I2C_E005+1)
-#define SKERR_I2C_E006MSG	"Unknown event"
-#define SKERR_I2C_E007		(SKERR_I2C_E006+1)
-#define SKERR_I2C_E007MSG	"LM80 read out of state"
-#define SKERR_I2C_E008		(SKERR_I2C_E007+1)
-#define SKERR_I2C_E008MSG	"Unexpected sensor read completed"
-#define SKERR_I2C_E009		(SKERR_I2C_E008+1)
-#define SKERR_I2C_E009MSG	"WARNING: temperature sensor out of range"
-#define SKERR_I2C_E010		(SKERR_I2C_E009+1)
-#define SKERR_I2C_E010MSG	"WARNING: voltage sensor out of range"
-#define SKERR_I2C_E011		(SKERR_I2C_E010+1)
-#define SKERR_I2C_E011MSG	"ERROR: temperature sensor out of range"
-#define SKERR_I2C_E012		(SKERR_I2C_E011+1)
-#define SKERR_I2C_E012MSG	"ERROR: voltage sensor out of range"
-#define SKERR_I2C_E013		(SKERR_I2C_E012+1)
-#define SKERR_I2C_E013MSG	"ERROR: couldn't init sensor"
-#define SKERR_I2C_E014		(SKERR_I2C_E013+1)
-#define SKERR_I2C_E014MSG	"WARNING: fan sensor out of range"
-#define SKERR_I2C_E015		(SKERR_I2C_E014+1)
-#define SKERR_I2C_E015MSG	"ERROR: fan sensor out of range"
-#define SKERR_I2C_E016		(SKERR_I2C_E015+1)
-#define SKERR_I2C_E016MSG	"TWSI: active transfer does not complete"
-
-/*
- * Define Timeout values
- */
-#define SK_I2C_TIM_LONG		2000000L	/* 2 seconds */
-#define SK_I2C_TIM_SHORT	 100000L	/* 100 milliseconds */
-#define SK_I2C_TIM_WATCH	1000000L	/* 1 second */
-
-/*
- * Define trap and error log hold times
- */
-#ifndef	SK_SEN_ERR_TR_HOLD
-#define SK_SEN_ERR_TR_HOLD		(4*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_ERR_LOG_HOLD
-#define SK_SEN_ERR_LOG_HOLD		(60*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_WARN_TR_HOLD
-#define SK_SEN_WARN_TR_HOLD		(15*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_WARN_LOG_HOLD
-#define SK_SEN_WARN_LOG_HOLD	(15*60*SK_TICKS_PER_SEC)
-#endif
-
-/*
- * Defines for SenType
- */
-#define SK_SEN_UNKNOWN	0
-#define SK_SEN_TEMP		1
-#define SK_SEN_VOLT		2
-#define SK_SEN_FAN		3
-
-/*
- * Define for the SenErrorFlag
- */
-#define SK_SEN_ERR_NOT_PRESENT	0	/* Error Flag: Sensor not present */
-#define SK_SEN_ERR_OK			1	/* Error Flag: O.K. */
-#define SK_SEN_ERR_WARN			2	/* Error Flag: Warning */
-#define SK_SEN_ERR_ERR			3	/* Error Flag: Error */
-#define SK_SEN_ERR_FAULTY		4	/* Error Flag: Faulty */
-
-/*
- * Define the Sensor struct
- */
-struct	s_Sensor {
-	char	*SenDesc;			/* Description */
-	int		SenType;			/* Voltage or Temperature */
-	SK_I32	SenValue;			/* Current value of the sensor */
-	SK_I32	SenThreErrHigh;		/* High error Threshhold of this sensor */
-	SK_I32	SenThreWarnHigh;	/* High warning Threshhold of this sensor */
-	SK_I32	SenThreErrLow;		/* Lower error Threshold of the sensor */
-	SK_I32	SenThreWarnLow;		/* Lower warning Threshold of the sensor */
-	int		SenErrFlag;			/* Sensor indicated an error */
-	SK_BOOL	SenInit;			/* Is sensor initialized ? */
-	SK_U64	SenErrCts;			/* Error trap counter */
-	SK_U64	SenWarnCts;			/* Warning trap counter */
-	SK_U64	SenBegErrTS;		/* Begin error timestamp */
-	SK_U64	SenBegWarnTS;		/* Begin warning timestamp */
-	SK_U64	SenLastErrTrapTS;	/* Last error trap timestamp */
-	SK_U64	SenLastErrLogTS;	/* Last error log timestamp */
-	SK_U64	SenLastWarnTrapTS;	/* Last warning trap timestamp */
-	SK_U64	SenLastWarnLogTS;	/* Last warning log timestamp */
-	int		SenState;			/* Sensor State (see HW specific include) */
-	int		(*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
-								/* Sensors read function */
-	SK_U16	SenReg;				/* Register Address for this sensor */
-	SK_U8	SenDev;				/* Device Selection for this sensor */
-};
-
-typedef	struct	s_I2c {
-	SK_SENSOR	SenTable[SK_MAX_SENSORS];	/* Sensor Table */
-	int			CurrSens;	/* Which sensor is currently queried */
-	int			MaxSens;	/* Max. number of sensors */
-	int			TimerMode;	/* Use the timer also to watch the state machine */
-	int			InitLevel;	/* Initialized Level */
-#ifndef SK_DIAG
-	int			DummyReads;	/* Number of non-checked dummy reads */
-	SK_TIMER	SenTimer;	/* Sensors timer */
-#endif /* !SK_DIAG */
-} SK_I2C;
-
-extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
-#ifdef SK_DIAG
-extern	SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
-						 int Burst);
-#else /* !SK_DIAG */
-extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
-extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
-#endif /* !SK_DIAG */
-#endif /* n_SKI2C_H */
-
diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
deleted file mode 100644
index 2ec40d4..0000000
--- a/drivers/net/sk98lin/h/skqueue.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/******************************************************************************
- *
- * Name:	skqueue.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.16 $
- * Date:	$Date: 2003/09/16 12:50:32 $
- * Purpose:	Defines for the Event queue
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKQUEUE.H	contains all defines and types for the event queue
- */
-
-#ifndef _SKQUEUE_H_
-#define _SKQUEUE_H_
-
-
-/*
- * define the event classes to be served
- */
-#define	SKGE_DRV	1	/* Driver Event Class */
-#define	SKGE_RLMT	2	/* RLMT Event Class */
-#define	SKGE_I2C	3	/* I2C Event Class */
-#define	SKGE_PNMI	4	/* PNMI Event Class */
-#define	SKGE_CSUM	5	/* Checksum Event Class */
-#define	SKGE_HWAC	6	/* Hardware Access Event Class */
-
-#define	SKGE_SWT	9	/* Software Timer Event Class */
-#define	SKGE_LACP	10	/* LACP Aggregation Event Class */
-#define	SKGE_RSF	11	/* RSF Aggregation Event Class */
-#define	SKGE_MARKER	12	/* MARKER Aggregation Event Class */
-#define	SKGE_FD		13	/* FD Distributor Event Class */
-
-/*
- * define event queue as circular buffer
- */
-#define SK_MAX_EVENT	64
-
-/*
- * Parameter union for the Para stuff
- */
-typedef	union u_EvPara {
-	void	*pParaPtr;	/* Parameter Pointer */
-	SK_U64	Para64;		/* Parameter 64bit version */
-	SK_U32	Para32[2];	/* Parameter Array of 32bit parameters */
-} SK_EVPARA;
-
-/*
- * Event Queue
- *	skqueue.c
- * events are class/value pairs
- *	class	is addressee, e.g. RLMT, PNMI etc.
- *	value	is command, e.g. line state change, ring op change etc.
- */
-typedef	struct s_EventElem {
-	SK_U32		Class;			/* Event class */
-	SK_U32		Event;			/* Event value */
-	SK_EVPARA	Para;			/* Event parameter */
-} SK_EVENTELEM;
-
-typedef	struct s_Queue {
-	SK_EVENTELEM	EvQueue[SK_MAX_EVENT];
-	SK_EVENTELEM	*EvPut;
-	SK_EVENTELEM	*EvGet;
-} SK_QUEUE;
-
-extern	void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern	void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event,
-	SK_EVPARA Para);
-extern	int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc);
-
-
-/* Define Error Numbers and messages */
-#define	SKERR_Q_E001	(SK_ERRBASE_QUEUE+0)
-#define	SKERR_Q_E001MSG	"Event queue overflow"
-#define	SKERR_Q_E002	(SKERR_Q_E001+1)
-#define	SKERR_Q_E002MSG	"Undefined event class"
-#endif	/* _SKQUEUE_H_ */
-
diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
deleted file mode 100644
index ca75dfd..0000000
--- a/drivers/net/sk98lin/h/skrlmt.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/******************************************************************************
- *
- * Name:	skrlmt.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.37 $
- * Date:	$Date: 2003/04/15 09:43:43 $
- * Purpose:	Header file for Redundant Link ManagemenT.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the header file for Redundant Link ManagemenT.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	...
- *	"sktypes.h"
- *	"skqueue.h"
- *	"skaddr.h"
- *	"skrlmt.h"
- *	...
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKRLMT_H
-#define __INC_SKRLMT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-/* defines ********************************************************************/
-
-#define	SK_RLMT_NET_DOWN_TEMP	1	/* NET_DOWN due to last port down. */
-#define	SK_RLMT_NET_DOWN_FINAL	2	/* NET_DOWN due to RLMT_STOP. */
-
-/* ----- Default queue sizes - must be multiples of 8 KB ----- */
-
-/* Less than 8 KB free in RX queue => pause frames. */
-#define SK_RLMT_STANDBY_QRXSIZE	128	/* Size of rx standby queue in KB. */
-#define SK_RLMT_STANDBY_QXASIZE	32	/* Size of async standby queue in KB. */
-#define SK_RLMT_STANDBY_QXSSIZE	0	/* Size of sync standby queue in KB. */
-
-#define SK_RLMT_MAX_TX_BUF_SIZE	60	/* Maximum RLMT transmit size. */
-
-/* ----- PORT states ----- */
-
-#define SK_RLMT_PS_INIT			0	/* Port state: Init. */
-#define SK_RLMT_PS_LINK_DOWN	1	/* Port state: Link down. */
-#define SK_RLMT_PS_DOWN			2	/* Port state: Port down. */
-#define SK_RLMT_PS_GOING_UP		3	/* Port state: Going up. */
-#define SK_RLMT_PS_UP			4	/* Port state: Up. */
-
-/* ----- RLMT states ----- */
-
-#define SK_RLMT_RS_INIT			0	/* RLMT state: Init. */
-#define SK_RLMT_RS_NET_DOWN		1	/* RLMT state: Net down. */
-#define SK_RLMT_RS_NET_UP		2	/* RLMT state: Net up. */
-
-/* ----- PORT events ----- */
-
-#define SK_RLMT_LINK_UP			1001	/* Link came up. */
-#define SK_RLMT_LINK_DOWN		1002	/* Link went down. */
-#define SK_RLMT_PORT_ADDR		1003	/* Port address changed. */
-
-/* ----- RLMT events ----- */
-
-#define SK_RLMT_START			2001	/* Start RLMT. */
-#define SK_RLMT_STOP			2002	/* Stop RLMT. */
-#define SK_RLMT_PACKET_RECEIVED	2003	/* Packet was received for RLMT. */
-#define SK_RLMT_STATS_CLEAR		2004	/* Clear statistics. */
-#define SK_RLMT_STATS_UPDATE	2005	/* Update statistics. */
-#define SK_RLMT_PREFPORT_CHANGE	2006	/* Change preferred port. */
-#define SK_RLMT_MODE_CHANGE		2007	/* New RlmtMode. */
-#define SK_RLMT_SET_NETS		2008	/* Number of Nets (1 or 2). */
-
-/* ----- RLMT mode bits ----- */
-
-/*
- * CAUTION:	These defines are private to RLMT.
- *			Please use the RLMT mode defines below.
- */
-
-#define SK_RLMT_CHECK_LINK		  1		/* Check Link. */
-#define SK_RLMT_CHECK_LOC_LINK	  2		/* Check other link on same adapter. */
-#define SK_RLMT_CHECK_SEG		  4		/* Check segmentation. */
-
-#ifndef RLMT_CHECK_REMOTE
-#define SK_RLMT_CHECK_OTHERS	SK_RLMT_CHECK_LOC_LINK
-#else	/* RLMT_CHECK_REMOTE */
-#define SK_RLMT_CHECK_REM_LINK	  8		/* Check link(s) on other adapter(s). */
-#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED	3
-#define SK_RLMT_CHECK_OTHERS	\
-		(SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-#endif	/* RLMT_CHECK_REMOTE */
-
-#ifndef SK_RLMT_ENABLE_TRANSPARENT
-#define SK_RLMT_TRANSPARENT		  0		/* RLMT transparent - inactive. */
-#else	/* SK_RLMT_ENABLE_TRANSPARENT */
-#define SK_RLMT_TRANSPARENT		128		/* RLMT transparent. */
-#endif	/* SK_RLMT_ENABLE_TRANSPARENT */
-
-/* ----- RLMT modes ----- */
-
-/* Check Link State. */
-#define SK_RLMT_MODE_CLS	(SK_RLMT_CHECK_LINK)
-
-/* Check Local Ports: check other links on the same adapter. */
-#define SK_RLMT_MODE_CLP	(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK)
-
-/* Check Local Ports and Segmentation Status. */
-#define SK_RLMT_MODE_CLPSS	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG)
-
-#ifdef RLMT_CHECK_REMOTE
-/* Check Local and Remote Ports: check links (local or remote). */
-	Name of define TBD!
-#define SK_RLMT_MODE_CRP	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-
-/* Check Local and Remote Ports and Segmentation Status. */
-	Name of define TBD!
-#define SK_RLMT_MODE_CRPSS	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \
-		SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG)
-#endif	/* RLMT_CHECK_REMOTE */
-
-/* ----- RLMT lookahead result bits ----- */
-
-#define SK_RLMT_RX_RLMT			1	/* Give packet to RLMT. */
-#define SK_RLMT_RX_PROTOCOL		2	/* Give packet to protocol. */
-
-/* Macros */
-
-#if 0
-SK_AC		*pAC		/* adapter context */
-SK_U32		PortNum		/* receiving port */
-unsigned	PktLen		/* received packet's length */
-SK_BOOL		IsBc		/* Flag: packet is broadcast */
-unsigned	*pOffset	/* offs. of bytes to present to SK_RLMT_LOOKAHEAD */
-unsigned	*pNumBytes	/* #Bytes to present to SK_RLMT_LOOKAHEAD */
-#endif	/* 0 */
-
-#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \
-	SK_AC	*_pAC; \
-	SK_U32	_PortNum; \
-	_pAC = (pAC); \
-	_PortNum = (SK_U32)(PortNum); \
-	/* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \
-	_pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \
-    if (_pAC->Rlmt.RlmtOff) { \
-		*(pNumBytes) = 0; \
-    } \
-    else {\
-        if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \
-    		*(pNumBytes) = 0; \
-    	} \
-    	else if (IsBc) { \
-    		if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \
-    			*(pNumBytes) = 6; \
-    			*(pOffset) = 6; \
-    		} \
-    		else { \
-    			*(pNumBytes) = 0; \
-    		} \
-    	} \
-    	else { \
-    		if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \
-    			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-    			*(pNumBytes) = 0; \
-    		} \
-    		else { \
-    			*(pNumBytes) = 6; \
-    			*(pOffset) = 0; \
-    		} \
-    	} \
-    } \
-}
-
-#if 0
-SK_AC		*pAC		/* adapter context */
-SK_U32		PortNum		/* receiving port */
-SK_U8		*pLaPacket,	/* received packet's data (points to pOffset) */
-SK_BOOL		IsBc		/* Flag: packet is broadcast */
-SK_BOOL		IsMc		/* Flag: packet is multicast */
-unsigned	*pForRlmt	/* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */
-SK_RLMT_LOOKAHEAD() expects *pNumBytes from
-packet offset *pOffset (s.a.) at *pLaPacket.
-
-If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is
-BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler
-can trash unneeded parts of the if construction.
-#endif	/* 0 */
-
-#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \
-	SK_AC	*_pAC; \
-	SK_U32	_PortNum; \
-	SK_U8	*_pLaPacket; \
-	_pAC = (pAC); \
-	_PortNum = (SK_U32)(PortNum); \
-	_pLaPacket = (SK_U8 *)(pLaPacket); \
-	if (IsBc) {\
-		if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \
-			_PortNum].Net->NetNumber].CurrentMacAddress.a)) { \
-			_pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \
-			_pAC->Rlmt.CheckSwitch = SK_TRUE; \
-		} \
-		/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-		*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-	} \
-	else if (IsMc) { \
-		if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \
-			_pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \
-			if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \
-				*(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \
-			} \
-			else { \
-				*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-			} \
-		} \
-		else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \
-			*(pForRlmt) = SK_RLMT_RX_RLMT; \
-		} \
-		else { \
-			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-		} \
-	} \
-	else { \
-		if (SK_ADDR_EQUAL( \
-			_pLaPacket, \
-			_pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \
-			*(pForRlmt) = SK_RLMT_RX_RLMT; \
-		} \
-		else { \
-			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-		} \
-	} \
-}
-
-#ifdef SK_RLMT_FAST_LOOKAHEAD
-Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif	/* SK_RLMT_FAST_LOOKAHEAD */
-#ifdef SK_RLMT_SLOW_LOOKAHEAD
-Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif	/* SK_RLMT_SLOW_LOOKAHEAD */
-
-/* typedefs *******************************************************************/
-
-#ifdef SK_RLMT_MBUF_PRIVATE
-typedef struct s_RlmtMbuf {
-	some content
-} SK_RLMT_MBUF;
-#endif	/* SK_RLMT_MBUF_PRIVATE */
-
-
-#ifdef SK_LA_INFO
-typedef struct s_Rlmt_PacketInfo {
-	unsigned	PacketLength;			/* Length of packet. */
-	unsigned	PacketType;				/* Directed/Multicast/Broadcast. */
-} SK_RLMT_PINFO;
-#endif	/* SK_LA_INFO */
-
-
-typedef struct s_RootId {
-	SK_U8		Id[8];					/* Root Bridge Id. */
-} SK_RLMT_ROOT_ID;
-
-
-typedef struct s_port {
-	SK_MAC_ADDR	CheckAddr;
-	SK_BOOL		SuspectTx;
-} SK_PORT_CHECK;
-
-
-typedef struct s_RlmtNet SK_RLMT_NET;
-
-
-typedef struct s_RlmtPort {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U8			PortState;				/* Current state of this port. */
-
-	/* For PNMI */
-	SK_BOOL			LinkDown;
-	SK_BOOL			PortDown;
-	SK_U8			Align01;
-
-	SK_U32			PortNumber;				/* Number of port on adapter. */
-	SK_RLMT_NET *	Net;					/* Net port belongs to. */
-
-	SK_U64			TxHelloCts;
-	SK_U64			RxHelloCts;
-	SK_U64			TxSpHelloReqCts;
-	SK_U64			RxSpHelloCts;
-
-/* ----- Private part ----- */
-
-/*	SK_U64			PacketsRx; */				/* Total packets received. */
-	SK_U32			PacketsPerTimeSlot;		/* Packets rxed between TOs. */
-/*	SK_U32			DataPacketsPerTimeSlot; */	/* Data packets ... */
-	SK_U32			BpduPacketsPerTimeSlot;	/* BPDU packets rxed in TS. */
-	SK_U64			BcTimeStamp;			/* Time of last BC receive. */
-	SK_U64			GuTimeStamp;			/* Time of entering GOING_UP. */
-
-	SK_TIMER		UpTimer;				/* Timer struct Link/Port up. */
-	SK_TIMER		DownRxTimer;			/* Timer struct down rx. */
-	SK_TIMER		DownTxTimer;			/* Timer struct down tx. */
-
-	SK_U32			CheckingState;			/* Checking State. */
-
-	SK_ADDR_PORT *	AddrPort;
-
-	SK_U8			Random[4];				/* Random value. */
-	unsigned		PortsChecked;			/* #ports checked. */
-	unsigned		PortsSuspect;			/* #ports checked that are s. */
-	SK_PORT_CHECK	PortCheck[1];
-/*	SK_PORT_CHECK	PortCheck[SK_MAX_MACS - 1]; */
-
-	SK_BOOL			PortStarted;			/* Port is started. */
-	SK_BOOL			PortNoRx;				/* NoRx for >= 1 time slot. */
-	SK_BOOL			RootIdSet;
-	SK_RLMT_ROOT_ID	Root;					/* Root Bridge Id. */
-} SK_RLMT_PORT;
-
-
-struct s_RlmtNet {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U32			NetNumber;			/* Number of net. */
-
-	SK_RLMT_PORT *	Port[SK_MAX_MACS];	/* Ports that belong to this net. */
-	SK_U32			NumPorts;			/* Number of ports. */
-	SK_U32			PrefPort;			/* Preferred port. */
-
-	/* For PNMI */
-
-	SK_U32			ChgBcPrio;			/* Change Priority of last broadcast received */
-	SK_U32			RlmtMode;			/* Check ... */
-	SK_U32			ActivePort;			/* Active port. */
-	SK_U32			Preference;		/* 0xFFFFFFFF: Automatic. */
-
-	SK_U8			RlmtState;			/* Current RLMT state. */
-
-/* ----- Private part ----- */
-	SK_BOOL			RootIdSet;
-	SK_U16			Align01;
-
-	int				LinksUp;			/* #Links up. */
-	int				PortsUp;			/* #Ports up. */
-	SK_U32			TimeoutValue;		/* RLMT timeout value. */
-
-	SK_U32			CheckingState;		/* Checking State. */
-	SK_RLMT_ROOT_ID	Root;				/* Root Bridge Id. */
-
-	SK_TIMER		LocTimer;			/* Timer struct. */
-	SK_TIMER		SegTimer;			/* Timer struct. */
-};
-
-
-typedef struct s_Rlmt {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U32			NumNets;			/* Number of nets. */
-	SK_U32			NetsStarted;		/* Number of nets started. */
-	SK_RLMT_NET		Net[SK_MAX_NETS];	/* Array of available nets. */
-	SK_RLMT_PORT	Port[SK_MAX_MACS];	/* Array of available ports. */
-
-/* ----- Private part ----- */
-	SK_BOOL			CheckSwitch;
-	SK_BOOL			RlmtOff;            /* set to zero if the Mac addresses 
-                                           are equal or the second one 
-                                           is zero */
-	SK_U16			Align01;
-
-} SK_RLMT;
-
-
-extern	SK_MAC_ADDR	BridgeMcAddr;
-extern	SK_MAC_ADDR	SkRlmtMcAddr;
-
-/* function prototypes ********************************************************/
-
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkRlmt */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern	void	SkRlmtInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Level);
-
-extern	int	SkRlmtEvent(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		Event,
-	SK_EVPARA	Para);
-
-#else	/* defined(SK_KR_PROTO) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style function prototypes are not yet provided.
-
-#endif	/* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKRLMT_H */
diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
deleted file mode 100644
index 04e6d7c..0000000
--- a/drivers/net/sk98lin/h/sktimer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktimer.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/09/16 12:58:18 $
- * Purpose:	Defines for the timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKTIMER.H	contains all defines and types for the timer functions
- */
-
-#ifndef	_SKTIMER_H_
-#define _SKTIMER_H_
-
-#include "h/skqueue.h"
-
-/*
- * SK timer
- * - needed wherever a timer is used. Put this in your data structure
- *   wherever you want.
- */
-typedef	struct s_Timer SK_TIMER;
-
-struct s_Timer {
-	SK_TIMER	*TmNext;	/* linked list */
-	SK_U32		TmClass;	/* Timer Event class */
-	SK_U32		TmEvent;	/* Timer Event value */
-	SK_EVPARA	TmPara;		/* Timer Event parameter */
-	SK_U32		TmDelta;	/* delta time */
-	int			TmActive;	/* flag: active/inactive */
-};
-
-/*
- * Timer control struct.
- * - use in Adapters context name pAC->Tim
- */
-typedef	struct s_TimCtrl {
-	SK_TIMER	*StQueue;	/* Head of Timer queue */
-} SK_TIMCTRL;
-
-extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer);
-extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer,
-	SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para);
-extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc);
-#endif	/* _SKTIMER_H_ */
diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
deleted file mode 100644
index 40edc96..0000000
--- a/drivers/net/sk98lin/h/sktypes.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktypes.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.2 $
- * Date:	$Date: 2003/10/07 08:16:51 $
- * Purpose:	Define data types for Linux
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
- 
-/******************************************************************************
- *
- * Description:
- *
- * In this file, all data types that are needed by the common modules
- * are mapped to Linux data types.
- * 
- *
- * Include File Hierarchy:
- *
- *
- ******************************************************************************/
-
-#ifndef __INC_SKTYPES_H
-#define __INC_SKTYPES_H
-
-
-/* defines *******************************************************************/
-
-/*
- * Data types with a specific size. 'I' = signed, 'U' = unsigned.
- */
-#define SK_I8	s8
-#define SK_U8	u8
-#define SK_I16	s16
-#define SK_U16	u16
-#define SK_I32	s32
-#define SK_U32	u32
-#define SK_I64	s64
-#define SK_U64	u64
-
-#define SK_UPTR	ulong		/* casting pointer <-> integral */
-
-/*
-* Boolean type.
-*/
-#define SK_BOOL		SK_U8
-#define SK_FALSE	0
-#define SK_TRUE		(!SK_FALSE)
-
-/* typedefs *******************************************************************/
-
-/* function prototypes ********************************************************/
-
-#endif	/* __INC_SKTYPES_H */
diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
deleted file mode 100644
index a1a7294..0000000
--- a/drivers/net/sk98lin/h/skversion.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/******************************************************************************
- *
- * Name:	version.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.5 $
- * Date:	$Date: 2003/10/07 08:16:51 $
- * Purpose:	SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifdef	lint
-static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
-static const char SysKonnectBuildNumber[] =
-	"@(#)SK-BUILD: 6.23 PL: 01"; 
-#endif	/* !defined(lint) */
-
-#define BOOT_STRING	"sk98lin: Network Device Driver v6.23\n" \
-			"(C)Copyright 1999-2004 Marvell(R)."
-
-#define VER_STRING	"6.23"
-#define DRIVER_FILE_NAME	"sk98lin"
-#define DRIVER_REL_DATE		"Feb-13-2004"
-
-
diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
deleted file mode 100644
index fdd9e48..0000000
--- a/drivers/net/sk98lin/h/skvpd.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/******************************************************************************
- *
- * Name:	skvpd.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.15 $
- * Date:	$Date: 2003/01/13 10:39:38 $
- * Purpose:	Defines and Macros for VPD handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2003 SysKonnect GmbH.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * skvpd.h	contains Diagnostic specific defines for VPD handling
- */
-
-#ifndef __INC_SKVPD_H_
-#define __INC_SKVPD_H_
-
-/*
- * Define Resource Type Identifiers and VPD keywords
- */
-#define	RES_ID		0x82	/* Resource Type ID String (Product Name) */
-#define RES_VPD_R	0x90	/* start of VPD read only area */
-#define RES_VPD_W	0x91	/* start of VPD read/write area */
-#define RES_END		0x78	/* Resource Type End Tag */
-
-#ifndef VPD_NAME
-#define VPD_NAME	"Name"	/* Product Name, VPD name of RES_ID */
-#endif	/* VPD_NAME */
-#define VPD_PN		"PN"	/* Adapter Part Number */
-#define	VPD_EC		"EC"	/* Adapter Engineering Level */
-#define VPD_MN		"MN"	/* Manufacture ID */
-#define VPD_SN		"SN"	/* Serial Number */
-#define VPD_CP		"CP"	/* Extended Capability */
-#define VPD_RV		"RV"	/* Checksum and Reserved */
-#define	VPD_YA		"YA"	/* Asset Tag Identifier */
-#define VPD_VL		"VL"	/* First Error Log Message (SK specific) */
-#define VPD_VF		"VF"	/* Second Error Log Message (SK specific) */
-#define VPD_RW		"RW"	/* Remaining Read / Write Area */
-
-/* 'type' values for vpd_setup_para() */
-#define VPD_RO_KEY	1	/* RO keys are "PN", "EC", "MN", "SN", "RV" */
-#define VPD_RW_KEY	2	/* RW keys are "Yx", "Vx", and "RW" */
-
-/* 'op' values for vpd_setup_para() */
-#define	ADD_KEY		1	/* add the key at the pos "RV" or "RW" */
-#define OWR_KEY		2	/* overwrite key if already exists */
-
-/*
- * Define READ and WRITE Constants.
- */
-
-#define VPD_DEV_ID_GENESIS 	0x4300
-
-#define	VPD_SIZE_YUKON		256
-#define	VPD_SIZE_GENESIS	512
-#define	VPD_SIZE			512
-#define VPD_READ	0x0000
-#define VPD_WRITE	0x8000
-
-#define VPD_STOP(pAC,IoC)	VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
-
-#define VPD_GET_RES_LEN(p)	((unsigned int) \
-					(* (SK_U8 *)&(p)[1]) |\
-					((* (SK_U8 *)&(p)[2]) << 8))
-#define VPD_GET_VPD_LEN(p)	((unsigned int)(* (SK_U8 *)&(p)[2]))
-#define VPD_GET_VAL(p)		((char *)&(p)[3])
-
-#define VPD_MAX_LEN	50
-
-/* VPD status */
-	/* bit 7..1 reserved */
-#define VPD_VALID	(1<<0)	/* VPD data buffer, vpd_free_ro, */
-							/* and vpd_free_rw valid	 */
-
-/*
- * VPD structs
- */
-typedef	struct s_vpd_status {
-	unsigned short	Align01;			/* Alignment */
-	unsigned short	vpd_status;			/* VPD status, description see above */
-	int				vpd_free_ro;		/* unused bytes in read only area */
-	int				vpd_free_rw;		/* bytes available in read/write area */
-} SK_VPD_STATUS;
-
-typedef	struct s_vpd {
-	SK_VPD_STATUS	v;					/* VPD status structure */
-	char			vpd_buf[VPD_SIZE];	/* VPD buffer */
-	int				rom_size;			/* VPD ROM Size from PCI_OUR_REG_2 */
-	int				vpd_size;			/* saved VPD-size */
-} SK_VPD;
-
-typedef	struct s_vpd_para {
-	unsigned int	p_len;	/* parameter length */
-	char			*p_val;	/* points to the value */
-} SK_VPD_PARA;
-
-/*
- * structure of Large Resource Type Identifiers
- */
-
-/* was removed because of alignment problems */
-
-/*
- * structure of VPD keywords
- */
-typedef	struct s_vpd_key {
-	char			p_key[2];	/* 2 bytes ID string */
-	unsigned char	p_len;		/* 1 byte length */
-	char			p_val;		/* start of the value string */
-} SK_VPD_KEY;
-
-
-/*
- * System specific VPD macros
- */
-#ifndef SKDIAG
-#ifndef VPD_DO_IO
-#define VPD_OUT8(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgByte(pAC,Addr,Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgWord(pAC,Addr,Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgByte(pAC,Addr,pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgWord(pAC,Addr,pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgDWord(pAC,Addr,pVal)
-#else	/* VPD_DO_IO */
-#define VPD_OUT8(pAC,IoC,Addr,Val)	SK_OUT8(IoC,PCI_C(Addr),Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val)	SK_OUT16(IoC,PCI_C(Addr),Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal)	SK_IN8(IoC,PCI_C(Addr),pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal)	SK_IN16(IoC,PCI_C(Addr),pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal)	SK_IN32(IoC,PCI_C(Addr),pVal)
-#endif	/* VPD_DO_IO */
-#else	/* SKDIAG */
-#define VPD_OUT8(pAC,Ioc,Addr,Val) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciWriteCfgByte(pAC,Addr,Val);	\
-		else									\
-			SK_OUT8(pAC,PCI_C(Addr),Val);		\
-		}
-#define VPD_OUT16(pAC,Ioc,Addr,Val) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciWriteCfgWord(pAC,Addr,Val);	\
-		else						\
-			SK_OUT16(pAC,PCI_C(Addr),Val);		\
-		}
-#define VPD_IN8(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle) 			\
-			SkPciReadCfgByte(pAC,Addr,pVal);	\
-		else						\
-			SK_IN8(pAC,PCI_C(Addr),pVal); 		\
-		}
-#define VPD_IN16(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle) 			\
-			SkPciReadCfgWord(pAC,Addr,pVal);	\
-		else						\
-			SK_IN16(pAC,PCI_C(Addr),pVal); 		\
-		}
-#define VPD_IN32(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciReadCfgDWord(pAC,Addr,pVal);	\
-		else						\
-			SK_IN32(pAC,PCI_C(Addr),pVal);		\
-		}
-#endif	/* nSKDIAG */
-
-/* function prototypes ********************************************************/
-
-#ifndef	SK_KR_PROTO
-#ifdef SKDIAG
-extern SK_U32	VpdReadDWord(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	int			addr);
-#endif	/* SKDIAG */
-
-extern SK_VPD_STATUS	*VpdStat(
-	SK_AC		*pAC,
-	SK_IOC		IoC);
-
-extern int	VpdKeys(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			*len,
-	int			*elements);
-
-extern int	VpdRead(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	const char	*key,
-	char		*buf,
-	int			*len);
-
-extern SK_BOOL	VpdMayWrite(
-	char		*key);
-
-extern int	VpdWrite(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	const char	*key,
-	const char	*buf);
-
-extern int	VpdDelete(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*key);
-
-extern int	VpdUpdate(
-	SK_AC		*pAC,
-	SK_IOC		IoC);
-
-#ifdef	SKDIAG
-extern int	VpdReadBlock(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			addr,
-	int			len);
-
-extern int	VpdWriteBlock(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			addr,
-	int			len);
-#endif	/* SKDIAG */
-#else	/* SK_KR_PROTO */
-extern SK_U32	VpdReadDWord();
-extern SK_VPD_STATUS	*VpdStat();
-extern int	VpdKeys();
-extern int	VpdRead();
-extern SK_BOOL	VpdMayWrite();
-extern int	VpdWrite();
-extern int	VpdDelete();
-extern int	VpdUpdate();
-#endif	/* SK_KR_PROTO */
-
-#endif	/* __INC_SKVPD_H_ */
diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
deleted file mode 100644
index 7f8e6d0..0000000
--- a/drivers/net/sk98lin/h/xmac_ii.h
+++ /dev/null
@@ -1,1579 +0,0 @@
-/******************************************************************************
- *
- * Name:	xmac_ii.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.52 $
- * Date:	$Date: 2003/10/02 16:35:50 $
- * Purpose:	Defines and Macros for Gigabit Ethernet Controller
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_XMAC_H
-#define __INC_XMAC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * XMAC II registers
- *
- * The XMAC registers are 16 or 32 bits wide.
- * The XMACs host processor interface is set to 16 bit mode,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the XMAC registers
- * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(),
- * XM_INHASH(), and XM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note:	NA reg	= Network Address e.g DA, SA etc.
- *
- */
-#define XM_MMU_CMD		0x0000	/* 16 bit r/w	MMU Command Register */
-	/* 0x0004:		reserved */
-#define XM_POFF			0x0008	/* 32 bit r/w	Packet Offset Register */
-#define XM_BURST		0x000c	/* 32 bit r/w	Burst Register for half duplex*/
-#define XM_1L_VLAN_TAG	0x0010	/* 16 bit r/w	One Level VLAN Tag ID */
-#define XM_2L_VLAN_TAG	0x0014	/* 16 bit r/w	Two Level VLAN Tag ID */
-	/* 0x0018 - 0x001e:	reserved */
-#define XM_TX_CMD		0x0020	/* 16 bit r/w	Transmit Command Register */
-#define XM_TX_RT_LIM	0x0024	/* 16 bit r/w	Transmit Retry Limit Register */
-#define XM_TX_STIME		0x0028	/* 16 bit r/w	Transmit Slottime Register */
-#define XM_TX_IPG		0x002c	/* 16 bit r/w	Transmit Inter Packet Gap */
-#define XM_RX_CMD		0x0030	/* 16 bit r/w	Receive Command Register */
-#define XM_PHY_ADDR		0x0034	/* 16 bit r/w	PHY Address Register */
-#define XM_PHY_DATA		0x0038	/* 16 bit r/w	PHY Data Register */
-	/* 0x003c: 		reserved */
-#define XM_GP_PORT		0x0040	/* 32 bit r/w	General Purpose Port Register */
-#define XM_IMSK			0x0044	/* 16 bit r/w	Interrupt Mask Register */
-#define XM_ISRC			0x0048	/* 16 bit r/o	Interrupt Status Register */
-#define XM_HW_CFG		0x004c	/* 16 bit r/w	Hardware Config Register */
-	/* 0x0050 - 0x005e:	reserved */
-#define XM_TX_LO_WM		0x0060	/* 16 bit r/w	Tx FIFO Low Water Mark */
-#define XM_TX_HI_WM		0x0062	/* 16 bit r/w	Tx FIFO High Water Mark */
-#define XM_TX_THR		0x0064	/* 16 bit r/w	Tx Request Threshold */
-#define XM_HT_THR		0x0066	/* 16 bit r/w	Host Request Threshold */
-#define XM_PAUSE_DA		0x0068	/* NA reg r/w	Pause Destination Address */
-	/* 0x006e: 		reserved */
-#define XM_CTL_PARA		0x0070	/* 32 bit r/w	Control Parameter Register */
-#define XM_MAC_OPCODE	0x0074	/* 16 bit r/w	Opcode for MAC control frames */
-#define XM_MAC_PTIME	0x0076	/* 16 bit r/w	Pause time for MAC ctrl frames*/
-#define XM_TX_STAT		0x0078	/* 32 bit r/o	Tx Status LIFO Register */
-
-	/* 0x0080 - 0x00fc:	16 NA reg r/w	Exact Match Address Registers */
-	/* 				use the XM_EXM() macro to address */
-#define XM_EXM_START	0x0080	/* r/w	Start Address of the EXM Regs */
-
-	/*
-	 * XM_EXM(Reg)
-	 *
-	 * returns the XMAC address offset of specified Exact Match Addr Reg
-	 *
-	 * para:	Reg	EXM register to addr	(0 .. 15)
-	 *
-	 * usage:	XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]);
-	 */
-#define XM_EXM(Reg)	(XM_EXM_START + ((Reg) << 3))
-
-#define XM_SRC_CHK		0x0100	/* NA reg r/w	Source Check Address Register */
-#define XM_SA			0x0108	/* NA reg r/w	Station Address Register */
-#define XM_HSM			0x0110	/* 64 bit r/w	Hash Match Address Registers */
-#define XM_RX_LO_WM		0x0118	/* 16 bit r/w	Receive Low Water Mark */
-#define XM_RX_HI_WM		0x011a	/* 16 bit r/w	Receive High Water Mark */
-#define XM_RX_THR		0x011c	/* 32 bit r/w	Receive Request Threshold */
-#define XM_DEV_ID		0x0120	/* 32 bit r/o	Device ID Register */
-#define XM_MODE			0x0124	/* 32 bit r/w	Mode Register */
-#define XM_LSA			0x0128	/* NA reg r/o	Last Source Register */
-	/* 0x012e:		reserved */
-#define XM_TS_READ		0x0130	/* 32 bit r/o	Time Stamp Read Register */
-#define XM_TS_LOAD		0x0134	/* 32 bit r/o	Time Stamp Load Value */
-	/* 0x0138 - 0x01fe:	reserved */
-#define XM_STAT_CMD	0x0200	/* 16 bit r/w	Statistics Command Register */
-#define XM_RX_CNT_EV	0x0204	/* 32 bit r/o	Rx Counter Event Register */
-#define XM_TX_CNT_EV	0x0208	/* 32 bit r/o	Tx Counter Event Register */
-#define XM_RX_EV_MSK	0x020c	/* 32 bit r/w	Rx Counter Event Mask */
-#define XM_TX_EV_MSK	0x0210	/* 32 bit r/w	Tx Counter Event Mask */
-	/* 0x0204 - 0x027e:	reserved */
-#define XM_TXF_OK		0x0280	/* 32 bit r/o	Frames Transmitted OK Conuter */
-#define XM_TXO_OK_HI	0x0284	/* 32 bit r/o	Octets Transmitted OK High Cnt*/
-#define XM_TXO_OK_LO	0x0288	/* 32 bit r/o	Octets Transmitted OK Low Cnt */
-#define XM_TXF_BC_OK	0x028c	/* 32 bit r/o	Broadcast Frames Xmitted OK */
-#define XM_TXF_MC_OK	0x0290	/* 32 bit r/o	Multicast Frames Xmitted OK */
-#define XM_TXF_UC_OK	0x0294	/* 32 bit r/o	Unicast Frames Xmitted OK */
-#define XM_TXF_LONG		0x0298	/* 32 bit r/o	Tx Long Frame Counter */
-#define XM_TXE_BURST	0x029c	/* 32 bit r/o	Tx Burst Event Counter */
-#define XM_TXF_MPAUSE	0x02a0	/* 32 bit r/o	Tx Pause MAC Ctrl Frame Cnt */
-#define XM_TXF_MCTRL	0x02a4	/* 32 bit r/o	Tx MAC Ctrl Frame Counter */
-#define XM_TXF_SNG_COL	0x02a8	/* 32 bit r/o	Tx Single Collision Counter */
-#define XM_TXF_MUL_COL	0x02ac	/* 32 bit r/o	Tx Multiple Collision Counter */
-#define XM_TXF_ABO_COL	0x02b0	/* 32 bit r/o	Tx aborted due to Exces. Col. */
-#define XM_TXF_LAT_COL	0x02b4	/* 32 bit r/o	Tx Late Collision Counter */
-#define XM_TXF_DEF		0x02b8	/* 32 bit r/o	Tx Deferred Frame Counter */
-#define XM_TXF_EX_DEF	0x02bc	/* 32 bit r/o	Tx Excessive Deferall Counter */
-#define XM_TXE_FIFO_UR	0x02c0	/* 32 bit r/o	Tx FIFO Underrun Event Cnt */
-#define XM_TXE_CS_ERR	0x02c4	/* 32 bit r/o	Tx Carrier Sense Error Cnt */
-#define XM_TXP_UTIL		0x02c8	/* 32 bit r/o	Tx Utilization in % */
-	/* 0x02cc - 0x02ce:	reserved */
-#define XM_TXF_64B		0x02d0	/* 32 bit r/o	64 Byte Tx Frame Counter */
-#define XM_TXF_127B		0x02d4	/* 32 bit r/o	65-127 Byte Tx Frame Counter */
-#define XM_TXF_255B		0x02d8	/* 32 bit r/o	128-255 Byte Tx Frame Counter */
-#define XM_TXF_511B		0x02dc	/* 32 bit r/o	256-511 Byte Tx Frame Counter */
-#define XM_TXF_1023B	0x02e0	/* 32 bit r/o	512-1023 Byte Tx Frame Counter*/
-#define XM_TXF_MAX_SZ	0x02e4	/* 32 bit r/o	1024-MaxSize Byte Tx Frame Cnt*/
-	/* 0x02e8 - 0x02fe:	reserved */
-#define XM_RXF_OK		0x0300	/* 32 bit r/o	Frames Received OK */
-#define XM_RXO_OK_HI	0x0304	/* 32 bit r/o	Octets Received OK High Cnt */
-#define XM_RXO_OK_LO	0x0308	/* 32 bit r/o	Octets Received OK Low Counter*/
-#define XM_RXF_BC_OK	0x030c	/* 32 bit r/o	Broadcast Frames Received OK */
-#define XM_RXF_MC_OK	0x0310	/* 32 bit r/o	Multicast Frames Received OK */
-#define XM_RXF_UC_OK	0x0314	/* 32 bit r/o	Unicast Frames Received OK */
-#define XM_RXF_MPAUSE	0x0318	/* 32 bit r/o	Rx Pause MAC Ctrl Frame Cnt */
-#define XM_RXF_MCTRL	0x031c	/* 32 bit r/o	Rx MAC Ctrl Frame Counter */
-#define XM_RXF_INV_MP	0x0320	/* 32 bit r/o	Rx invalid Pause Frame Cnt */
-#define XM_RXF_INV_MOC	0x0324	/* 32 bit r/o	Rx Frames with inv. MAC Opcode*/
-#define XM_RXE_BURST	0x0328	/* 32 bit r/o	Rx Burst Event Counter */
-#define XM_RXE_FMISS	0x032c	/* 32 bit r/o	Rx Missed Frames Event Cnt */
-#define XM_RXF_FRA_ERR	0x0330	/* 32 bit r/o	Rx Framing Error Counter */
-#define XM_RXE_FIFO_OV	0x0334	/* 32 bit r/o	Rx FIFO overflow Event Cnt */
-#define XM_RXF_JAB_PKT	0x0338	/* 32 bit r/o	Rx Jabber Packet Frame Cnt */
-#define XM_RXE_CAR_ERR	0x033c	/* 32 bit r/o	Rx Carrier Event Error Cnt */
-#define XM_RXF_LEN_ERR	0x0340	/* 32 bit r/o	Rx in Range Length Error */
-#define XM_RXE_SYM_ERR	0x0344	/* 32 bit r/o	Rx Symbol Error Counter */
-#define XM_RXE_SHT_ERR	0x0348	/* 32 bit r/o	Rx Short Event Error Cnt */
-#define XM_RXE_RUNT		0x034c	/* 32 bit r/o	Rx Runt Event Counter */
-#define XM_RXF_LNG_ERR	0x0350	/* 32 bit r/o	Rx Frame too Long Error Cnt */
-#define XM_RXF_FCS_ERR	0x0354	/* 32 bit r/o	Rx Frame Check Seq. Error Cnt */
-	/* 0x0358 - 0x035a:	reserved */
-#define XM_RXF_CEX_ERR	0x035c	/* 32 bit r/o	Rx Carrier Ext Error Frame Cnt*/
-#define XM_RXP_UTIL		0x0360	/* 32 bit r/o	Rx Utilization in % */
-	/* 0x0364 - 0x0366:	reserved */
-#define XM_RXF_64B		0x0368	/* 32 bit r/o	64 Byte Rx Frame Counter */
-#define XM_RXF_127B		0x036c	/* 32 bit r/o	65-127 Byte Rx Frame Counter */
-#define XM_RXF_255B		0x0370	/* 32 bit r/o	128-255 Byte Rx Frame Counter */
-#define XM_RXF_511B		0x0374	/* 32 bit r/o	256-511 Byte Rx Frame Counter */
-#define XM_RXF_1023B	0x0378	/* 32 bit r/o	512-1023 Byte Rx Frame Counter*/
-#define XM_RXF_MAX_SZ	0x037c	/* 32 bit r/o	1024-MaxSize Byte Rx Frame Cnt*/
-	/* 0x02e8 - 0x02fe:	reserved */
-
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- *	(sc)	self clearing
- *	(ro)	read only
- */
-
-/*	XM_MMU_CMD	16 bit r/w	MMU Command Register */
-								/* Bit 15..13:	reserved */
-#define XM_MMU_PHY_RDY	(1<<12)	/* Bit 12:	PHY Read Ready */
-#define XM_MMU_PHY_BUSY	(1<<11)	/* Bit 11:	PHY Busy */
-#define XM_MMU_IGN_PF	(1<<10)	/* Bit 10:	Ignore Pause Frame */
-#define XM_MMU_MAC_LB	(1<<9)	/* Bit  9:	Enable MAC Loopback */
-								/* Bit  8:	reserved */
-#define XM_MMU_FRC_COL	(1<<7)	/* Bit  7:	Force Collision */
-#define XM_MMU_SIM_COL	(1<<6)	/* Bit  6:	Simulate Collision */
-#define XM_MMU_NO_PRE	(1<<5)	/* Bit  5:	No MDIO Preamble */
-#define XM_MMU_GMII_FD	(1<<4)	/* Bit  4:	GMII uses Full Duplex */
-#define XM_MMU_RAT_CTRL	(1<<3)	/* Bit  3:	Enable Rate Control */
-#define XM_MMU_GMII_LOOP (1<<2)	/* Bit  2:	PHY is in Loopback Mode */
-#define XM_MMU_ENA_RX	(1<<1)	/* Bit  1:	Enable Receiver */
-#define XM_MMU_ENA_TX	(1<<0)	/* Bit  0:	Enable Transmitter */
-
-
-/*	XM_TX_CMD	16 bit r/w	Transmit Command Register */
-								/* Bit 15..7:	reserved */
-#define XM_TX_BK2BK		(1<<6)	/* Bit  6:	Ignor Carrier Sense (Tx Bk2Bk)*/
-#define XM_TX_ENC_BYP	(1<<5)	/* Bit  5:	Set Encoder in Bypass Mode */
-#define XM_TX_SAM_LINE	(1<<4)	/* Bit  4: (sc)	Start utilization calculation */
-#define XM_TX_NO_GIG_MD	(1<<3)	/* Bit  3:	Disable Carrier Extension */
-#define XM_TX_NO_PRE	(1<<2)	/* Bit  2:	Disable Preamble Generation */
-#define XM_TX_NO_CRC	(1<<1)	/* Bit  1:	Disable CRC Generation */
-#define XM_TX_AUTO_PAD	(1<<0)	/* Bit  0:	Enable Automatic Padding */
-
-
-/*	XM_TX_RT_LIM	16 bit r/w	Transmit Retry Limit Register */
-								/* Bit 15..5:	reserved */
-#define XM_RT_LIM_MSK	0x1f	/* Bit  4..0:	Tx Retry Limit */
-
-
-/*	XM_TX_STIME	16 bit r/w	Transmit Slottime Register */
-								/* Bit 15..7:	reserved */
-#define XM_STIME_MSK	0x7f	/* Bit  6..0:	Tx Slottime bits */
-
-
-/*	XM_TX_IPG	16 bit r/w	Transmit Inter Packet Gap */
-								/* Bit 15..8:	reserved */
-#define XM_IPG_MSK		0xff	/* Bit  7..0:	IPG value bits */
-
-
-/*	XM_RX_CMD	16 bit r/w	Receive Command Register */
-								/* Bit 15..9:	reserved */
-#define XM_RX_LENERR_OK (1<<8)	/* Bit  8	don't set Rx Err bit for */
-								/*		inrange error packets */
-#define XM_RX_BIG_PK_OK	(1<<7)	/* Bit  7	don't set Rx Err bit for */
-								/*		jumbo packets */
-#define XM_RX_IPG_CAP	(1<<6)	/* Bit  6	repl. type field with IPG */
-#define XM_RX_TP_MD		(1<<5)	/* Bit  5:	Enable transparent Mode */
-#define XM_RX_STRIP_FCS	(1<<4)	/* Bit  4:	Enable FCS Stripping */
-#define XM_RX_SELF_RX	(1<<3)	/* Bit  3: 	Enable Rx of own packets */
-#define XM_RX_SAM_LINE	(1<<2)	/* Bit  2: (sc)	Start utilization calculation */
-#define XM_RX_STRIP_PAD	(1<<1)	/* Bit  1:	Strip pad bytes of Rx frames */
-#define XM_RX_DIS_CEXT	(1<<0)	/* Bit  0:	Disable carrier ext. check */
-
-
-/*	XM_PHY_ADDR	16 bit r/w	PHY Address Register */
-								/* Bit 15..5:	reserved */
-#define XM_PHY_ADDR_SZ	0x1f	/* Bit  4..0:	PHY Address bits */
-
-
-/*	XM_GP_PORT	32 bit r/w	General Purpose Port Register */
-								/* Bit 31..7:	reserved */
-#define XM_GP_ANIP		(1L<<6)	/* Bit  6: (ro)	Auto-Neg. in progress */
-#define XM_GP_FRC_INT	(1L<<5)	/* Bit  5: (sc)	Force Interrupt */
-								/* Bit  4:	reserved */
-#define XM_GP_RES_MAC	(1L<<3)	/* Bit  3: (sc)	Reset MAC and FIFOs */
-#define XM_GP_RES_STAT	(1L<<2)	/* Bit  2: (sc)	Reset the statistics module */
-								/* Bit  1:	reserved */
-#define XM_GP_INP_ASS	(1L<<0)	/* Bit  0: (ro) GP Input Pin asserted */
-
-
-/*	XM_IMSK		16 bit r/w	Interrupt Mask Register */
-/*	XM_ISRC		16 bit r/o	Interrupt Status Register */
-								/* Bit 15:	reserved */
-#define XM_IS_LNK_AE	(1<<14) /* Bit 14:	Link Asynchronous Event */
-#define XM_IS_TX_ABORT	(1<<13) /* Bit 13:	Transmit Abort, late Col. etc */
-#define XM_IS_FRC_INT	(1<<12) /* Bit 12:	Force INT bit set in GP */
-#define XM_IS_INP_ASS	(1<<11)	/* Bit 11:	Input Asserted, GP bit 0 set */
-#define XM_IS_LIPA_RC	(1<<10)	/* Bit 10:	Link Partner requests config */
-#define XM_IS_RX_PAGE	(1<<9)	/* Bit  9:	Page Received */
-#define XM_IS_TX_PAGE	(1<<8)	/* Bit  8:	Next Page Loaded for Transmit */
-#define XM_IS_AND		(1<<7)	/* Bit  7:	Auto-Negotiation Done */
-#define XM_IS_TSC_OV	(1<<6)	/* Bit  6:	Time Stamp Counter Overflow */
-#define XM_IS_RXC_OV	(1<<5)	/* Bit  5:	Rx Counter Event Overflow */
-#define XM_IS_TXC_OV	(1<<4)	/* Bit  4:	Tx Counter Event Overflow */
-#define XM_IS_RXF_OV	(1<<3)	/* Bit  3:	Receive FIFO Overflow */
-#define XM_IS_TXF_UR	(1<<2)	/* Bit  2:	Transmit FIFO Underrun */
-#define XM_IS_TX_COMP	(1<<1)	/* Bit  1:	Frame Tx Complete */
-#define XM_IS_RX_COMP	(1<<0)	/* Bit  0:	Frame Rx Complete */
-
-#define XM_DEF_MSK	(~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\
-			XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR))
-
-
-/*	XM_HW_CFG	16 bit r/w	Hardware Config Register */
-								/* Bit 15.. 4:	reserved */
-#define XM_HW_GEN_EOP	(1<<3)	/* Bit  3:	generate End of Packet pulse */
-#define XM_HW_COM4SIG	(1<<2)	/* Bit  2:	use Comma Detect for Sig. Det.*/
-								/* Bit  1:	reserved */
-#define XM_HW_GMII_MD	(1<<0)	/* Bit  0:	GMII Interface selected */
-
-
-/*	XM_TX_LO_WM	16 bit r/w	Tx FIFO Low Water Mark */
-/*	XM_TX_HI_WM	16 bit r/w	Tx FIFO High Water Mark */
-								/* Bit 15..10	reserved */
-#define XM_TX_WM_MSK	0x01ff	/* Bit  9.. 0	Tx FIFO Watermark bits */
-
-/*	XM_TX_THR	16 bit r/w	Tx Request Threshold */
-/*	XM_HT_THR	16 bit r/w	Host Request Threshold */
-/*	XM_RX_THR	16 bit r/w	Rx Request Threshold */
-								/* Bit 15..11	reserved */
-#define XM_THR_MSK		0x03ff	/* Bit 10.. 0	Rx/Tx Request Threshold bits */
-
-
-/*	XM_TX_STAT	32 bit r/o	Tx Status LIFO Register */
-#define XM_ST_VALID		(1UL<<31)	/* Bit 31:	Status Valid */
-#define XM_ST_BYTE_CNT	(0x3fffL<<17)	/* Bit 30..17:	Tx frame Length */
-#define XM_ST_RETRY_CNT	(0x1fL<<12)	/* Bit 16..12:	Retry Count */
-#define XM_ST_EX_COL	(1L<<11)	/* Bit 11:	Excessive Collisions */
-#define XM_ST_EX_DEF	(1L<<10)	/* Bit 10:	Excessive Deferral */
-#define XM_ST_BURST		(1L<<9)		/* Bit  9:	p. xmitted in burst md*/
-#define XM_ST_DEFER		(1L<<8)		/* Bit  8:	packet was defered */
-#define XM_ST_BC		(1L<<7)		/* Bit  7:	Broadcast packet */
-#define XM_ST_MC		(1L<<6)		/* Bit  6:	Multicast packet */
-#define XM_ST_UC		(1L<<5)		/* Bit  5:	Unicast packet */
-#define XM_ST_TX_UR		(1L<<4)		/* Bit  4:	FIFO Underrun occured */
-#define XM_ST_CS_ERR	(1L<<3)		/* Bit  3:	Carrier Sense Error */
-#define XM_ST_LAT_COL	(1L<<2)		/* Bit  2:	Late Collision Error */
-#define XM_ST_MUL_COL	(1L<<1)		/* Bit  1:	Multiple Collisions */
-#define XM_ST_SGN_COL	(1L<<0)		/* Bit  0:	Single Collision */
-
-/*	XM_RX_LO_WM	16 bit r/w	Receive Low Water Mark */
-/*	XM_RX_HI_WM	16 bit r/w	Receive High Water Mark */
-									/* Bit 15..11:	reserved */
-#define XM_RX_WM_MSK	0x03ff		/* Bit 11.. 0:	Rx FIFO Watermark bits */
-
-
-/*	XM_DEV_ID	32 bit r/o	Device ID Register */
-#define XM_DEV_OUI	(0x00ffffffUL<<8)	/* Bit 31..8:	Device OUI */
-#define XM_DEV_REV	(0x07L << 5)		/* Bit  7..5:	Chip Rev Num */
-
-
-/*	XM_MODE		32 bit r/w	Mode Register */
-									/* Bit 31..27:	reserved */
-#define XM_MD_ENA_REJ	(1L<<26)	/* Bit 26:	Enable Frame Reject */
-#define XM_MD_SPOE_E	(1L<<25)	/* Bit 25:	Send Pause on Edge */
-									/* 		extern generated */
-#define XM_MD_TX_REP	(1L<<24)	/* Bit 24:	Transmit Repeater Mode */
-#define XM_MD_SPOFF_I	(1L<<23)	/* Bit 23:	Send Pause on FIFO full */
-									/*		intern generated */
-#define XM_MD_LE_STW	(1L<<22)	/* Bit 22:	Rx Stat Word in Little Endian */
-#define XM_MD_TX_CONT	(1L<<21)	/* Bit 21:	Send Continuous */
-#define XM_MD_TX_PAUSE	(1L<<20)	/* Bit 20: (sc)	Send Pause Frame */
-#define XM_MD_ATS		(1L<<19)	/* Bit 19:	Append Time Stamp */
-#define XM_MD_SPOL_I	(1L<<18)	/* Bit 18:	Send Pause on Low */
-									/*		intern generated */
-#define XM_MD_SPOH_I	(1L<<17)	/* Bit 17:	Send Pause on High */
-									/*		intern generated */
-#define XM_MD_CAP		(1L<<16)	/* Bit 16:	Check Address Pair */
-#define XM_MD_ENA_HASH	(1L<<15)	/* Bit 15:	Enable Hashing */
-#define XM_MD_CSA		(1L<<14)	/* Bit 14:	Check Station Address */
-#define XM_MD_CAA		(1L<<13)	/* Bit 13:	Check Address Array */
-#define XM_MD_RX_MCTRL	(1L<<12)	/* Bit 12:	Rx MAC Control Frame */
-#define XM_MD_RX_RUNT	(1L<<11)	/* Bit 11:	Rx Runt Frames */
-#define XM_MD_RX_IRLE	(1L<<10)	/* Bit 10:	Rx in Range Len Err Frame */
-#define XM_MD_RX_LONG	(1L<<9)		/* Bit  9:	Rx Long Frame */
-#define XM_MD_RX_CRCE	(1L<<8)		/* Bit  8:	Rx CRC Error Frame */
-#define XM_MD_RX_ERR	(1L<<7)		/* Bit  7:	Rx Error Frame */
-#define XM_MD_DIS_UC	(1L<<6)		/* Bit  6:	Disable Rx Unicast */
-#define XM_MD_DIS_MC	(1L<<5)		/* Bit  5:	Disable Rx Multicast */
-#define XM_MD_DIS_BC	(1L<<4)		/* Bit  4:	Disable Rx Broadcast */
-#define XM_MD_ENA_PROM	(1L<<3)		/* Bit  3:	Enable Promiscuous */
-#define XM_MD_ENA_BE	(1L<<2)		/* Bit  2:	Enable Big Endian */
-#define XM_MD_FTF		(1L<<1)		/* Bit  1: (sc)	Flush Tx FIFO */
-#define XM_MD_FRF		(1L<<0)		/* Bit  0: (sc)	Flush Rx FIFO */
-
-#define XM_PAUSE_MODE	(XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
-#define XM_DEF_MODE		(XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
-				XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
-
-/*	XM_STAT_CMD	16 bit r/w	Statistics Command Register */
-								/* Bit 16..6:	reserved */
-#define XM_SC_SNP_RXC	(1<<5)	/* Bit  5: (sc)	Snap Rx Counters */
-#define XM_SC_SNP_TXC	(1<<4)	/* Bit  4: (sc)	Snap Tx Counters */
-#define XM_SC_CP_RXC	(1<<3)	/* Bit  3: 	Copy Rx Counters Continuously */
-#define XM_SC_CP_TXC	(1<<2)	/* Bit  2:	Copy Tx Counters Continuously */
-#define XM_SC_CLR_RXC	(1<<1)	/* Bit  1: (sc)	Clear Rx Counters */
-#define XM_SC_CLR_TXC	(1<<0)	/* Bit  0: (sc) Clear Tx Counters */
-
-
-/*	XM_RX_CNT_EV	32 bit r/o	Rx Counter Event Register */
-/*	XM_RX_EV_MSK	32 bit r/w	Rx Counter Event Mask */
-#define XMR_MAX_SZ_OV	(1UL<<31)	/* Bit 31:	1024-MaxSize Rx Cnt Ov*/
-#define XMR_1023B_OV	(1L<<30)	/* Bit 30:	512-1023Byte Rx Cnt Ov*/
-#define XMR_511B_OV		(1L<<29)	/* Bit 29:	256-511 Byte Rx Cnt Ov*/
-#define XMR_255B_OV		(1L<<28)	/* Bit 28:	128-255 Byte Rx Cnt Ov*/
-#define XMR_127B_OV		(1L<<27)	/* Bit 27:	65-127 Byte Rx Cnt Ov */
-#define XMR_64B_OV		(1L<<26)	/* Bit 26:	64 Byte Rx Cnt Ov */
-#define XMR_UTIL_OV		(1L<<25)	/* Bit 25:	Rx Util Cnt Overflow */
-#define XMR_UTIL_UR		(1L<<24)	/* Bit 24:	Rx Util Cnt Underrun */
-#define XMR_CEX_ERR_OV	(1L<<23)	/* Bit 23:	CEXT Err Cnt Ov */
-									/* Bit 22:	reserved */
-#define XMR_FCS_ERR_OV	(1L<<21)	/* Bit 21:	Rx FCS Error Cnt Ov */
-#define XMR_LNG_ERR_OV	(1L<<20)	/* Bit 20:	Rx too Long Err Cnt Ov*/
-#define XMR_RUNT_OV		(1L<<19)	/* Bit 19:	Runt Event Cnt Ov */
-#define XMR_SHT_ERR_OV	(1L<<18)	/* Bit 18:	Rx Short Ev Err Cnt Ov*/
-#define XMR_SYM_ERR_OV	(1L<<17)	/* Bit 17:	Rx Sym Err Cnt Ov */
-									/* Bit 16:	reserved */
-#define XMR_CAR_ERR_OV	(1L<<15)	/* Bit 15:	Rx Carr Ev Err Cnt Ov */
-#define XMR_JAB_PKT_OV	(1L<<14)	/* Bit 14:	Rx Jabb Packet Cnt Ov */
-#define XMR_FIFO_OV		(1L<<13)	/* Bit 13:	Rx FIFO Ov Ev Cnt Ov */
-#define XMR_FRA_ERR_OV	(1L<<12)	/* Bit 12:	Rx Framing Err Cnt Ov */
-#define XMR_FMISS_OV	(1L<<11)	/* Bit 11:	Rx Missed Ev Cnt Ov */
-#define XMR_BURST		(1L<<10)	/* Bit 10:	Rx Burst Event Cnt Ov */
-#define XMR_INV_MOC		(1L<<9)		/* Bit  9:	Rx with inv. MAC OC Ov*/
-#define XMR_INV_MP		(1L<<8)		/* Bit  8:	Rx inv Pause Frame Ov */
-#define XMR_MCTRL_OV	(1L<<7)		/* Bit  7:	Rx MAC Ctrl-F Cnt Ov */
-#define XMR_MPAUSE_OV	(1L<<6)		/* Bit  6:	Rx Pause MAC Ctrl-F Ov*/
-#define XMR_UC_OK_OV	(1L<<5)		/* Bit  5:	Rx Unicast Frame CntOv*/
-#define XMR_MC_OK_OV	(1L<<4)		/* Bit  4:	Rx Multicast Cnt Ov */
-#define XMR_BC_OK_OV	(1L<<3)		/* Bit  3:	Rx Broadcast Cnt Ov */
-#define XMR_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Rx OK Low CntOv*/
-#define XMR_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Rx OK Hi Cnt Ov*/
-#define XMR_OK_OV		(1L<<0)		/* Bit  0:	Frames Received Ok Ov */
-
-#define XMR_DEF_MSK		(XMR_OK_LO_OV | XMR_OK_HI_OV)
-
-/*	XM_TX_CNT_EV	32 bit r/o	Tx Counter Event Register */
-/*	XM_TX_EV_MSK	32 bit r/w	Tx Counter Event Mask */
-									/* Bit 31..26:	reserved */
-#define XMT_MAX_SZ_OV	(1L<<25)	/* Bit 25:	1024-MaxSize Tx Cnt Ov*/
-#define XMT_1023B_OV	(1L<<24)	/* Bit 24:	512-1023Byte Tx Cnt Ov*/
-#define XMT_511B_OV		(1L<<23)	/* Bit 23:	256-511 Byte Tx Cnt Ov*/
-#define XMT_255B_OV		(1L<<22)	/* Bit 22:	128-255 Byte Tx Cnt Ov*/
-#define XMT_127B_OV		(1L<<21)	/* Bit 21:	65-127 Byte Tx Cnt Ov */
-#define XMT_64B_OV		(1L<<20)	/* Bit 20:	64 Byte Tx Cnt Ov */
-#define XMT_UTIL_OV		(1L<<19)	/* Bit 19:	Tx Util Cnt Overflow */
-#define XMT_UTIL_UR		(1L<<18)	/* Bit 18:	Tx Util Cnt Underrun */
-#define XMT_CS_ERR_OV	(1L<<17)	/* Bit 17:	Tx Carr Sen Err Cnt Ov*/
-#define XMT_FIFO_UR_OV	(1L<<16)	/* Bit 16:	Tx FIFO Ur Ev Cnt Ov */
-#define XMT_EX_DEF_OV	(1L<<15)	/* Bit 15:	Tx Ex Deferall Cnt Ov */
-#define XMT_DEF			(1L<<14)	/* Bit 14:	Tx Deferred Cnt Ov */
-#define XMT_LAT_COL_OV	(1L<<13)	/* Bit 13:	Tx Late Col Cnt Ov */
-#define XMT_ABO_COL_OV	(1L<<12)	/* Bit 12:	Tx abo dueto Ex Col Ov*/
-#define XMT_MUL_COL_OV	(1L<<11)	/* Bit 11:	Tx Mult Col Cnt Ov */
-#define XMT_SNG_COL		(1L<<10)	/* Bit 10:	Tx Single Col Cnt Ov */
-#define XMT_MCTRL_OV	(1L<<9)		/* Bit  9:	Tx MAC Ctrl Counter Ov*/
-#define XMT_MPAUSE		(1L<<8)		/* Bit  8:	Tx Pause MAC Ctrl-F Ov*/
-#define XMT_BURST		(1L<<7)		/* Bit  7:	Tx Burst Event Cnt Ov */
-#define XMT_LONG		(1L<<6)		/* Bit  6:	Tx Long Frame Cnt Ov */
-#define XMT_UC_OK_OV	(1L<<5)		/* Bit  5:	Tx Unicast Cnt Ov */
-#define XMT_MC_OK_OV	(1L<<4)		/* Bit  4:	Tx Multicast Cnt Ov */
-#define XMT_BC_OK_OV	(1L<<3)		/* Bit  3:	Tx Broadcast Cnt Ov */
-#define XMT_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Tx OK Low CntOv*/
-#define XMT_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Tx OK Hi Cnt Ov*/
-#define XMT_OK_OV		(1L<<0)		/* Bit  0:	Frames Tx Ok Ov */
-
-#define XMT_DEF_MSK		(XMT_OK_LO_OV | XMT_OK_HI_OV)
-
-/*
- * Receive Frame Status Encoding
- */
-#define XMR_FS_LEN	(0x3fffUL<<18)	/* Bit 31..18:	Rx Frame Length */
-#define XMR_FS_2L_VLAN	(1L<<17)	/* Bit 17:	tagged wh 2Lev VLAN ID*/
-#define XMR_FS_1L_VLAN	(1L<<16)	/* Bit 16:	tagged wh 1Lev VLAN ID*/
-#define XMR_FS_BC		(1L<<15)	/* Bit 15:	Broadcast Frame */
-#define XMR_FS_MC		(1L<<14)	/* Bit 14:	Multicast Frame */
-#define XMR_FS_UC		(1L<<13)	/* Bit 13:	Unicast Frame */
-									/* Bit 12:	reserved */
-#define XMR_FS_BURST	(1L<<11)	/* Bit 11:	Burst Mode */
-#define XMR_FS_CEX_ERR	(1L<<10)	/* Bit 10:	Carrier Ext. Error */
-#define XMR_FS_802_3	(1L<<9)		/* Bit  9:	802.3 Frame */
-#define XMR_FS_COL_ERR	(1L<<8)		/* Bit  8:	Collision Error */
-#define XMR_FS_CAR_ERR	(1L<<7)		/* Bit  7:	Carrier Event Error */
-#define XMR_FS_LEN_ERR	(1L<<6)		/* Bit  6:	In-Range Length Error */
-#define XMR_FS_FRA_ERR	(1L<<5)		/* Bit  5:	Framing Error */
-#define XMR_FS_RUNT		(1L<<4)		/* Bit  4:	Runt Frame */
-#define XMR_FS_LNG_ERR	(1L<<3)		/* Bit  3:	Giant (Jumbo) Frame */
-#define XMR_FS_FCS_ERR	(1L<<2)		/* Bit  2:	Frame Check Sequ Err */
-#define XMR_FS_ERR		(1L<<1)		/* Bit  1:	Frame Error */
-#define XMR_FS_MCTRL	(1L<<0)		/* Bit  0:	MAC Control Packet */
-
-/*
- * XMR_FS_ERR will be set if
- *	XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
- *	XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
- * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
- * XMR_FS_ERR unless the corresponding bit in the Receive Command
- * Register is set.
- */
-#define XMR_FS_ANY_ERR	XMR_FS_ERR
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC-PHY Registers, indirect addressed over the XMAC
- */
-#define PHY_XMAC_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_XMAC_STAT		0x01	/* 16 bit r/w	PHY Status Register */
-#define PHY_XMAC_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_XMAC_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_XMAC_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_XMAC_AUNE_LP	0x05	/* 16 bit r/o	Link Partner Abi Reg */
-#define PHY_XMAC_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_XMAC_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_XMAC_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* 0x09 - 0x0e:		reserved */
-#define PHY_XMAC_EXT_STAT	0x0f	/* 16 bit r/o	Ext Status Register */
-#define PHY_XMAC_RES_ABI	0x10	/* 16 bit r/o	PHY Resolved Ability */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Broadcom-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_BCOM_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_BCOM_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_BCOM_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_BCOM_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_BCOM_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_BCOM_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_BCOM_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_BCOM_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_BCOM_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Broadcom-specific registers */
-#define PHY_BCOM_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Ctrl Reg */
-#define PHY_BCOM_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b - 0x0e:		reserved */
-#define PHY_BCOM_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_BCOM_P_EXT_CTRL	0x10	/* 16 bit r/w	PHY Extended Ctrl Reg */
-#define PHY_BCOM_P_EXT_STAT	0x11	/* 16 bit r/o	PHY Extended Stat Reg */
-#define PHY_BCOM_RE_CTR		0x12	/* 16 bit r/w	Receive Error Counter */
-#define PHY_BCOM_FC_CTR		0x13	/* 16 bit r/w	False Carrier Sense Cnt */
-#define PHY_BCOM_RNO_CTR	0x14	/* 16 bit r/w	Receiver NOT_OK Cnt */
-	/* 0x15 - 0x17:		reserved */
-#define PHY_BCOM_AUX_CTRL	0x18	/* 16 bit r/w	Auxiliary Control Reg */
-#define PHY_BCOM_AUX_STAT	0x19	/* 16 bit r/o	Auxiliary Stat Summary */
-#define PHY_BCOM_INT_STAT	0x1a	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_BCOM_INT_MASK	0x1b	/* 16 bit r/w	Interrupt Mask Reg */
-	/* 0x1c:		reserved */
-	/* 0x1d - 0x1f:		test registers */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Marvel-PHY Registers, indirect addressed over GMAC
- */
-#define PHY_MARV_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_MARV_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_MARV_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_MARV_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_MARV_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_MARV_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_MARV_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_MARV_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_MARV_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Marvel-specific registers */
-#define PHY_MARV_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Ctrl Reg */
-#define PHY_MARV_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b - 0x0e:		reserved */
-#define PHY_MARV_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_MARV_PHY_CTRL	0x10	/* 16 bit r/w	PHY Specific Ctrl Reg */
-#define PHY_MARV_PHY_STAT	0x11	/* 16 bit r/o	PHY Specific Stat Reg */
-#define PHY_MARV_INT_MASK	0x12	/* 16 bit r/w	Interrupt Mask Reg */
-#define PHY_MARV_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_MARV_EXT_CTRL	0x14	/* 16 bit r/w	Ext. PHY Specific Ctrl */
-#define PHY_MARV_RXE_CNT	0x15	/* 16 bit r/w	Receive Error Counter */
-#define PHY_MARV_EXT_ADR	0x16	/* 16 bit r/w	Ext. Ad. for Cable Diag. */
-	/* 0x17:		reserved */
-#define PHY_MARV_LED_CTRL	0x18	/* 16 bit r/w	LED Control Reg */
-#define PHY_MARV_LED_OVER	0x19	/* 16 bit r/w	Manual LED Override Reg */
-#define PHY_MARV_EXT_CTRL_2	0x1a	/* 16 bit r/w	Ext. PHY Specific Ctrl 2 */
-#define PHY_MARV_EXT_P_STAT	0x1b	/* 16 bit r/w	Ext. PHY Spec. Stat Reg */
-#define PHY_MARV_CABLE_DIAG	0x1c	/* 16 bit r/o	Cable Diagnostic Reg */
-	/* 0x1d - 0x1f:		reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Level One-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_LONE_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_LONE_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_LONE_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_LONE_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_LONE_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_LONE_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_LONE_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_LONE_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_LONE_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Level One-specific registers */
-#define PHY_LONE_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg*/
-#define PHY_LONE_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b -0x0e:		reserved */
-#define PHY_LONE_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_LONE_PORT_CFG	0x10	/* 16 bit r/w	Port Configuration Reg*/
-#define PHY_LONE_Q_STAT		0x11	/* 16 bit r/o	Quick Status Reg */
-#define PHY_LONE_INT_ENAB	0x12	/* 16 bit r/w	Interrupt Enable Reg */
-#define PHY_LONE_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_LONE_LED_CFG	0x14	/* 16 bit r/w	LED Configuration Reg */
-#define PHY_LONE_PORT_CTRL	0x15	/* 16 bit r/w	Port Control Reg */
-#define PHY_LONE_CIM		0x16	/* 16 bit r/o	CIM Reg */
-	/* 0x17 -0x1c:		reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * National-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_NAT_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_NAT_STAT		0x01	/* 16 bit r/w	PHY Status Register */
-#define PHY_NAT_ID0			0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_NAT_ID1			0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_NAT_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_NAT_AUNE_LP		0x05	/* 16 bit r/o	Link Partner Ability Reg */
-#define PHY_NAT_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_NAT_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_NAT_NEPG_LP		0x08	/* 16 bit r/o	Next Page Link Partner Reg */
-	/* National-specific registers */
-#define PHY_NAT_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg */
-#define PHY_NAT_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b -0x0e:		reserved */
-#define PHY_NAT_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Register */
-#define PHY_NAT_EXT_CTRL1	0x10	/* 16 bit r/o	Extended Control Reg1 */
-#define PHY_NAT_Q_STAT1		0x11	/* 16 bit r/o	Quick Status Reg1 */
-#define PHY_NAT_10B_OP		0x12	/* 16 bit r/o	10Base-T Operations Reg */
-#define PHY_NAT_EXT_CTRL2	0x13	/* 16 bit r/o	Extended Control Reg1 */
-#define PHY_NAT_Q_STAT2		0x14	/* 16 bit r/o	Quick Status Reg2 */
-	/* 0x15 -0x18:		reserved */
-#define PHY_NAT_PHY_ADDR	0x19	/* 16 bit r/o	PHY Address Register */
-
-
-/*----------------------------------------------------------------------------*/
-
-/*
- * PHY bit definitions
- * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are
- * XMAC/Broadcom/LevelOne/National/Marvell-specific.
- * All other are general.
- */
-
-/*****  PHY_XMAC_CTRL	16 bit r/w	PHY Control Register *****/
-/*****  PHY_BCOM_CTRL	16 bit r/w	PHY Control Register *****/
-/*****  PHY_MARV_CTRL	16 bit r/w	PHY Status Register *****/
-/*****  PHY_LONE_CTRL	16 bit r/w	PHY Control Register *****/
-#define PHY_CT_RESET	(1<<15)	/* Bit 15: (sc)	clear all PHY related regs */
-#define PHY_CT_LOOP		(1<<14)	/* Bit 14:	enable Loopback over PHY */
-#define PHY_CT_SPS_LSB	(1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */
-#define PHY_CT_ANE		(1<<12)	/* Bit 12:	Auto-Negotiation Enabled */
-#define PHY_CT_PDOWN	(1<<11)	/* Bit 11: (BC,L1) Power Down Mode */
-#define PHY_CT_ISOL		(1<<10)	/* Bit 10: (BC,L1) Isolate Mode */
-#define PHY_CT_RE_CFG	(1<<9)	/* Bit  9: (sc) Restart Auto-Negotiation */
-#define PHY_CT_DUP_MD	(1<<8)	/* Bit  8:	Duplex Mode */
-#define PHY_CT_COL_TST	(1<<7)	/* Bit  7: (BC,L1) Collision Test enabled */
-#define PHY_CT_SPS_MSB	(1<<6)	/* Bit  6: (BC,L1) Speed select, upper bit */
-								/* Bit  5..0:	reserved */
-
-#define PHY_CT_SP1000	PHY_CT_SPS_MSB	/* enable speed of 1000 Mbps */
-#define PHY_CT_SP100	PHY_CT_SPS_LSB	/* enable speed of  100 Mbps */
-#define PHY_CT_SP10		(0)				/* enable speed of   10 Mbps */
-
-
-/*****  PHY_XMAC_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_BCOM_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_MARV_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_LONE_STAT	16 bit r/w	PHY Status Register *****/
-								/* Bit 15..9:	reserved */
-				/*	(BC/L1) 100/10 Mbps cap bits ignored*/
-#define PHY_ST_EXT_ST	(1<<8)	/* Bit  8:	Extended Status Present */
-								/* Bit  7:	reserved */
-#define PHY_ST_PRE_SUP	(1<<6)	/* Bit  6: (BC/L1) preamble suppression */
-#define PHY_ST_AN_OVER	(1<<5)	/* Bit  5:	Auto-Negotiation Over */
-#define PHY_ST_REM_FLT	(1<<4)	/* Bit  4:	Remote Fault Condition Occured */
-#define PHY_ST_AN_CAP	(1<<3)	/* Bit  3:	Auto-Negotiation Capability */
-#define PHY_ST_LSYNC	(1<<2)	/* Bit  2:	Link Synchronized */
-#define PHY_ST_JAB_DET	(1<<1)	/* Bit  1: (BC/L1) Jabber Detected */
-#define PHY_ST_EXT_REG	(1<<0)	/* Bit  0:	Extended Register available */
-
-
-/*****	PHY_XMAC_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_BCOM_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_MARV_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_LONE_ID1		16 bit r/o	PHY ID1 Register */
-#define PHY_I1_OUI_MSK	(0x3f<<10)	/* Bit 15..10:	Organization Unique ID */
-#define PHY_I1_MOD_NUM	(0x3f<<4)	/* Bit  9.. 4:	Model Number */
-#define PHY_I1_REV_MSK	0x0f		/* Bit  3.. 0:	Revision Number */
-
-/* different Broadcom PHY Ids */
-#define PHY_BCOM_ID1_A1		0x6041
-#define PHY_BCOM_ID1_B2		0x6043
-#define PHY_BCOM_ID1_C0		0x6044
-#define PHY_BCOM_ID1_C5		0x6047
-
-
-/*****  PHY_XMAC_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_XMAC_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-#define PHY_AN_NXT_PG	(1<<15)	/* Bit 15:	Request Next Page */
-#define PHY_X_AN_ACK	(1<<14)	/* Bit 14: (ro)	Acknowledge Received */
-#define PHY_X_AN_RFB	(3<<12)	/* Bit 13..12:	Remote Fault Bits */
-								/* Bit 11.. 9:	reserved */
-#define PHY_X_AN_PAUSE	(3<<7)	/* Bit  8.. 7:	Pause Bits */
-#define PHY_X_AN_HD		(1<<6)	/* Bit  6:	Half Duplex */
-#define PHY_X_AN_FD		(1<<5)	/* Bit  5:	Full Duplex */
-								/* Bit  4.. 0:	reserved */
-
-/*****  PHY_BCOM_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_BCOM_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_B_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_B_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
-#define PHY_B_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_B_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/*****  PHY_LONE_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_LONE_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_L_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_L_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
-#define PHY_L_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_L_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/*****  PHY_NAT_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_NAT_AUNE_LP		16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_N_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_N_AN_100F	(1<<11)	/* Bit 11:	100Base-T2 FD Support */
-#define PHY_N_AN_100H	(1<<10)	/* Bit 10:	100Base-T2 HD Support */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_N_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/* field type definition for PHY_x_AN_SEL */
-#define PHY_SEL_TYPE	0x01	/* 00001 = Ethernet */
-
-/*****  PHY_XMAC_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-								/* Bit 15..4:	reserved */
-#define PHY_ANE_LP_NP	(1<<3)	/* Bit  3:	Link Partner can Next Page */
-#define PHY_ANE_LOC_NP	(1<<2)	/* Bit  2:	Local PHY can Next Page */
-#define PHY_ANE_RX_PG	(1<<1)	/* Bit  1:	Page Received */
-								/* Bit  0:	reserved */
-
-/*****  PHY_BCOM_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-/*****  PHY_LONE_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-/*****  PHY_MARV_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-								/* Bit 15..5:	reserved */
-#define PHY_ANE_PAR_DF	(1<<4)	/* Bit  4:	Parallel Detection Fault */
-/*	PHY_ANE_LP_NP		(see XMAC) Bit  3:	Link Partner can Next Page */
-/*	PHY_ANE_LOC_NP		(see XMAC) Bit  2:	Local PHY can Next Page */
-/*	PHY_ANE_RX_PG		(see XMAC) Bit  1:	Page Received */
-#define PHY_ANE_LP_CAP	(1<<0)	/* Bit  0:	Link Partner Auto-Neg. Cap. */ 	
-
-/*****  PHY_XMAC_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_BCOM_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_LONE_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_XMAC_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-/*****  PHY_BCOM_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-/*****  PHY_LONE_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-#define PHY_NP_MORE		(1<<15)	/* Bit 15:	More, Next Pages to follow */
-#define PHY_NP_ACK1		(1<<14)	/* Bit 14: (ro)	Ack1, for receiving a message */
-#define PHY_NP_MSG_VAL	(1<<13)	/* Bit 13:	Message Page valid */
-#define PHY_NP_ACK2		(1<<12)	/* Bit 12:	Ack2, comply with msg content */
-#define PHY_NP_TOG		(1<<11)	/* Bit 11:	Toggle Bit, ensure sync */
-#define PHY_NP_MSG		0x07ff	/* Bit 10..0:	Message from/to Link Partner */
-
-/*
- * XMAC-Specific
- */
-/*****  PHY_XMAC_EXT_STAT	16 bit r/w	Extended Status Register *****/
-#define PHY_X_EX_FD		(1<<15)	/* Bit 15:	Device Supports Full Duplex */
-#define PHY_X_EX_HD		(1<<14)	/* Bit 14:	Device Supports Half Duplex */
-								/* Bit 13..0:	reserved */
-
-/*****  PHY_XMAC_RES_ABI	16 bit r/o	PHY Resolved Ability *****/
-								/* Bit 15..9:	reserved */
-#define PHY_X_RS_PAUSE	(3<<7)	/* Bit  8..7:	selected Pause Mode */
-#define PHY_X_RS_HD		(1<<6)	/* Bit  6:	Half Duplex Mode selected */
-#define PHY_X_RS_FD		(1<<5)	/* Bit  5:	Full Duplex Mode selected */
-#define PHY_X_RS_ABLMIS (1<<4)	/* Bit  4:	duplex or pause cap mismatch */
-#define PHY_X_RS_PAUMIS (1<<3)	/* Bit  3:	pause capability mismatch */
-								/* Bit  2..0:	reserved */
-/*
- * Remote Fault Bits (PHY_X_AN_RFB) encoding
- */
-#define X_RFB_OK		(0<<12)	/* Bit 13..12	No errors, Link OK */
-#define X_RFB_LF		(1<<12)	/* Bit 13..12	Link Failure */
-#define X_RFB_OFF		(2<<12)	/* Bit 13..12	Offline */
-#define X_RFB_AN_ERR	(3<<12)	/* Bit 13..12	Auto-Negotiation Error */
-
-/*
- * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding
- */
-#define PHY_X_P_NO_PAUSE	(0<<7)	/* Bit  8..7:	no Pause Mode */
-#define PHY_X_P_SYM_MD		(1<<7)	/* Bit  8..7:	symmetric Pause Mode */
-#define PHY_X_P_ASYM_MD		(2<<7)	/* Bit  8..7:	asymmetric Pause Mode */
-#define PHY_X_P_BOTH_MD		(3<<7)	/* Bit  8..7:	both Pause Mode */
-
-
-/*
- * Broadcom-Specific
- */
-/*****  PHY_BCOM_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_B_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_B_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_B_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_B_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_B_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_B_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_BCOM_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-/*****  PHY_MARV_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_B_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_B_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_B_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_B_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
-#define PHY_B_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_B_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-									/* Bit  9..8:	reserved */
-#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_BCOM_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_B_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_B_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_B_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_B_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/*****  PHY_BCOM_P_EXT_CTRL	16 bit r/w	PHY Extended Control Reg *****/
-#define PHY_B_PEC_MAC_PHY	(1<<15)	/* Bit 15:	10BIT/GMI-Interface */
-#define PHY_B_PEC_DIS_CROSS	(1<<14)	/* Bit 14:	Disable MDI Crossover */
-#define PHY_B_PEC_TX_DIS	(1<<13)	/* Bit 13:	Tx output Disabled */
-#define PHY_B_PEC_INT_DIS	(1<<12)	/* Bit 12:	Interrupts Disabled */
-#define PHY_B_PEC_F_INT		(1<<11)	/* Bit 11:	Force Interrupt */
-#define PHY_B_PEC_BY_45		(1<<10)	/* Bit 10:	Bypass 4B5B-Decoder */
-#define PHY_B_PEC_BY_SCR	(1<<9)	/* Bit  9:	Bypass Scrambler */
-#define PHY_B_PEC_BY_MLT3	(1<<8)	/* Bit  8:	Bypass MLT3 Encoder */
-#define PHY_B_PEC_BY_RXA	(1<<7)	/* Bit  7:	Bypass Rx Alignm. */
-#define PHY_B_PEC_RES_SCR	(1<<6)	/* Bit  6:	Reset Scrambler */
-#define PHY_B_PEC_EN_LTR	(1<<5)	/* Bit  5:	Ena LED Traffic Mode */
-#define PHY_B_PEC_LED_ON	(1<<4)	/* Bit  4:	Force LED's on */
-#define PHY_B_PEC_LED_OFF	(1<<3)	/* Bit  3:	Force LED's off */
-#define PHY_B_PEC_EX_IPG	(1<<2)	/* Bit  2:	Extend Tx IPG Mode */
-#define PHY_B_PEC_3_LED		(1<<1)	/* Bit  1:	Three Link LED mode */
-#define PHY_B_PEC_HIGH_LA	(1<<0)	/* Bit  0:	GMII FIFO Elasticy */
-
-/*****  PHY_BCOM_P_EXT_STAT	16 bit r/o	PHY Extended Status Reg *****/
-									/* Bit 15..14:	reserved */
-#define PHY_B_PES_CROSS_STAT	(1<<13)	/* Bit 13:	MDI Crossover Status */
-#define PHY_B_PES_INT_STAT	(1<<12)	/* Bit 12:	Interrupt Status */
-#define PHY_B_PES_RRS		(1<<11)	/* Bit 11:	Remote Receiver Stat. */
-#define PHY_B_PES_LRS		(1<<10)	/* Bit 10:	Local Receiver Stat. */
-#define PHY_B_PES_LOCKED	(1<<9)	/* Bit  9:	Locked */
-#define PHY_B_PES_LS		(1<<8)	/* Bit  8:	Link Status */
-#define PHY_B_PES_RF		(1<<7)	/* Bit  7:	Remote Fault */
-#define PHY_B_PES_CE_ER		(1<<6)	/* Bit  6:	Carrier Ext Error */
-#define PHY_B_PES_BAD_SSD	(1<<5)	/* Bit  5:	Bad SSD */
-#define PHY_B_PES_BAD_ESD	(1<<4)	/* Bit  4:	Bad ESD */
-#define PHY_B_PES_RX_ER		(1<<3)	/* Bit  3:	Receive Error */
-#define PHY_B_PES_TX_ER		(1<<2)	/* Bit  2:	Transmit Error */
-#define PHY_B_PES_LOCK_ER	(1<<1)	/* Bit  1:	Lock Error */
-#define PHY_B_PES_MLT3_ER	(1<<0)	/* Bit  0:	MLT3 code Error */
-
-/*****  PHY_BCOM_FC_CTR		16 bit r/w	False Carrier Counter *****/
-									/* Bit 15..8:	reserved */
-#define PHY_B_FC_CTR		0xff	/* Bit  7..0:	False Carrier Counter */
-
-/*****  PHY_BCOM_RNO_CTR	16 bit r/w	Receive NOT_OK Counter *****/
-#define PHY_B_RC_LOC_MSK	0xff00	/* Bit 15..8:	Local Rx NOT_OK cnt */
-#define PHY_B_RC_REM_MSK	0x00ff	/* Bit  7..0:	Remote Rx NOT_OK cnt */
-
-/*****  PHY_BCOM_AUX_CTRL	16 bit r/w	Auxiliary Control Reg *****/
-#define PHY_B_AC_L_SQE		(1<<15)	/* Bit 15:	Low Squelch */
-#define PHY_B_AC_LONG_PACK	(1<<14)	/* Bit 14:	Rx Long Packets */
-#define PHY_B_AC_ER_CTRL	(3<<12)	/* Bit 13..12:	Edgerate Control */
-									/* Bit 11:	reserved */
-#define PHY_B_AC_TX_TST		(1<<10) /* Bit 10:	Tx test bit, always 1 */
-									/* Bit  9.. 8:	reserved */
-#define PHY_B_AC_DIS_PRF	(1<<7)	/* Bit  7:	dis part resp filter */
-									/* Bit  6:	reserved */
-#define PHY_B_AC_DIS_PM		(1<<5)	/* Bit  5:	dis power management */
-									/* Bit  4:	reserved */
-#define PHY_B_AC_DIAG		(1<<3)	/* Bit  3:	Diagnostic Mode */
-									/* Bit  2.. 0:	reserved */
-
-/*****  PHY_BCOM_AUX_STAT	16 bit r/o	Auxiliary Status Reg *****/
-#define PHY_B_AS_AN_C		(1<<15)	/* Bit 15:	AutoNeg complete */
-#define PHY_B_AS_AN_CA		(1<<14)	/* Bit 14:	AN Complete Ack */
-#define PHY_B_AS_ANACK_D	(1<<13)	/* Bit 13:	AN Ack Detect */
-#define PHY_B_AS_ANAB_D		(1<<12)	/* Bit 12:	AN Ability Detect */
-#define PHY_B_AS_NPW		(1<<11)	/* Bit 11:	AN Next Page Wait */
-#define PHY_B_AS_AN_RES_MSK	(7<<8)	/* Bit 10..8:	AN HDC */
-#define PHY_B_AS_PDF		(1<<7)	/* Bit  7:	Parallel Detect. Fault */
-#define PHY_B_AS_RF			(1<<6)	/* Bit  6:	Remote Fault */
-#define PHY_B_AS_ANP_R		(1<<5)	/* Bit  5:	AN Page Received */
-#define PHY_B_AS_LP_ANAB	(1<<4)	/* Bit  4:	LP AN Ability */
-#define PHY_B_AS_LP_NPAB	(1<<3)	/* Bit  3:	LP Next Page Ability */
-#define PHY_B_AS_LS			(1<<2)	/* Bit  2:	Link Status */
-#define PHY_B_AS_PRR		(1<<1)	/* Bit  1:	Pause Resolution-Rx */
-#define PHY_B_AS_PRT		(1<<0)	/* Bit  0:	Pause Resolution-Tx */
-
-#define PHY_B_AS_PAUSE_MSK	(PHY_B_AS_PRR | PHY_B_AS_PRT)
-
-/*****  PHY_BCOM_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-/*****  PHY_BCOM_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
-									/* Bit 15:	reserved */
-#define PHY_B_IS_PSE		(1<<14)	/* Bit 14:	Pair Swap Error */
-#define PHY_B_IS_MDXI_SC	(1<<13)	/* Bit 13:	MDIX Status Change */
-#define PHY_B_IS_HCT		(1<<12)	/* Bit 12:	counter above 32k */
-#define PHY_B_IS_LCT		(1<<11)	/* Bit 11:	counter above 128 */
-#define PHY_B_IS_AN_PR		(1<<10)	/* Bit 10:	Page Received */
-#define PHY_B_IS_NO_HDCL	(1<<9)	/* Bit  9:	No HCD Link */
-#define PHY_B_IS_NO_HDC		(1<<8)	/* Bit  8:	No HCD */
-#define PHY_B_IS_NEG_USHDC	(1<<7)	/* Bit  7:	Negotiated Unsup. HCD */
-#define PHY_B_IS_SCR_S_ER	(1<<6)	/* Bit  6:	Scrambler Sync Error */
-#define PHY_B_IS_RRS_CHANGE	(1<<5)	/* Bit  5:	Remote Rx Stat Change */
-#define PHY_B_IS_LRS_CHANGE	(1<<4)	/* Bit  4:	Local Rx Stat Change */
-#define PHY_B_IS_DUP_CHANGE	(1<<3)	/* Bit  3:	Duplex Mode Change */
-#define PHY_B_IS_LSP_CHANGE	(1<<2)	/* Bit  2:	Link Speed Change */
-#define PHY_B_IS_LST_CHANGE	(1<<1)	/* Bit  1:	Link Status Changed */
-#define PHY_B_IS_CRC_ER		(1<<0)	/* Bit  0:	CRC Error */
-
-#define PHY_B_DEF_MSK	(~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
-
-/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
-#define PHY_B_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
-#define PHY_B_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
-#define PHY_B_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
-#define PHY_B_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
-
-/*
- * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
- */
-#define PHY_B_RES_1000FD	(7<<8)	/* Bit 10..8:	1000Base-T Full Dup. */
-#define PHY_B_RES_1000HD	(6<<8)	/* Bit 10..8:	1000Base-T Half Dup. */
-/* others: 100/10: invalid for us */
-
-/*
- * Level One-Specific
- */
-/*****  PHY_LONE_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_L_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_L_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_L_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_L_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_L_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_L_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_LONE_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_L_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_L_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_L_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_L_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
-#define PHY_L_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_L_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-									/* Bit  9..8:	reserved */
-#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_LONE_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_L_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_L_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_L_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_L_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/*****  PHY_LONE_PORT_CFG	16 bit r/w	Port Configuration Reg *****/
-#define PHY_L_PC_REP_MODE	(1<<15)	/* Bit 15:	Repeater Mode */
-									/* Bit 14:	reserved */
-#define PHY_L_PC_TX_DIS		(1<<13)	/* Bit 13:	Tx output Disabled */
-#define PHY_L_PC_BY_SCR		(1<<12)	/* Bit 12:	Bypass Scrambler */
-#define PHY_L_PC_BY_45		(1<<11)	/* Bit 11:	Bypass 4B5B-Decoder */
-#define PHY_L_PC_JAB_DIS	(1<<10)	/* Bit 10:	Jabber Disabled */
-#define PHY_L_PC_SQE		(1<<9)	/* Bit  9:	Enable Heartbeat */
-#define PHY_L_PC_TP_LOOP	(1<<8)	/* Bit  8:	TP Loopback */
-#define PHY_L_PC_SSS		(1<<7)	/* Bit  7:	Smart Speed Selection */
-#define PHY_L_PC_FIFO_SIZE	(1<<6)	/* Bit  6:	FIFO Size */
-#define PHY_L_PC_PRE_EN		(1<<5)	/* Bit  5:	Preamble Enable */
-#define PHY_L_PC_CIM		(1<<4)	/* Bit  4:	Carrier Integrity Mon */
-#define PHY_L_PC_10_SER		(1<<3)	/* Bit  3:	Use Serial Output */
-#define PHY_L_PC_ANISOL		(1<<2)	/* Bit  2:	Unisolate Port */
-#define PHY_L_PC_TEN_BIT	(1<<1)	/* Bit  1:	10bit iface mode on */
-#define PHY_L_PC_ALTCLOCK	(1<<0)	/* Bit  0: (ro)	ALTCLOCK Mode on */
-
-/*****  PHY_LONE_Q_STAT		16 bit r/o	Quick Status Reg *****/
-#define PHY_L_QS_D_RATE		(3<<14)	/* Bit 15..14:	Data Rate */
-#define PHY_L_QS_TX_STAT	(1<<13)	/* Bit 13:	Transmitting */
-#define PHY_L_QS_RX_STAT	(1<<12)	/* Bit 12:	Receiving */
-#define PHY_L_QS_COL_STAT	(1<<11)	/* Bit 11:	Collision */
-#define PHY_L_QS_L_STAT		(1<<10)	/* Bit 10:	Link is up */
-#define PHY_L_QS_DUP_MOD	(1<<9)	/* Bit  9:	Full/Half Duplex */
-#define PHY_L_QS_AN			(1<<8)	/* Bit  8:	AutoNeg is On */
-#define PHY_L_QS_AN_C		(1<<7)	/* Bit  7:	AN is Complete */
-#define PHY_L_QS_LLE		(7<<4)	/* Bit  6:	Line Length Estim. */
-#define PHY_L_QS_PAUSE		(1<<3)	/* Bit  3:	LP advertised Pause */
-#define PHY_L_QS_AS_PAUSE	(1<<2)	/* Bit  2:	LP adv. asym. Pause */
-#define PHY_L_QS_ISOLATE	(1<<1)	/* Bit  1:	CIM Isolated */
-#define PHY_L_QS_EVENT		(1<<0)	/* Bit  0:	Event has occurred */
-
-/*****  PHY_LONE_INT_ENAB	16 bit r/w	Interrupt Enable Reg *****/
-/*****  PHY_LONE_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-									/* Bit 15..14:	reserved */
-#define PHY_L_IS_AN_F		(1<<13)	/* Bit 13:	Auto-Negotiation fault */
-									/* Bit 12:	not described */
-#define PHY_L_IS_CROSS		(1<<11)	/* Bit 11:	Crossover used */
-#define PHY_L_IS_POL		(1<<10)	/* Bit 10:	Polarity correct. used */
-#define PHY_L_IS_SS			(1<<9)	/* Bit  9:	Smart Speed Downgrade */
-#define PHY_L_IS_CFULL		(1<<8)	/* Bit  8:	Counter Full */
-#define PHY_L_IS_AN_C		(1<<7)	/* Bit  7:	AutoNeg Complete */
-#define PHY_L_IS_SPEED		(1<<6)	/* Bit  6:	Speed Changed */
-#define PHY_L_IS_DUP		(1<<5)	/* Bit  5:	Duplex Changed */
-#define PHY_L_IS_LS			(1<<4)	/* Bit  4:	Link Status Changed */
-#define PHY_L_IS_ISOL		(1<<3)	/* Bit  3:	Isolate Occured */
-#define PHY_L_IS_MDINT		(1<<2)	/* Bit  2: (ro)	STAT: MII Int Pending */
-#define PHY_L_IS_INTEN		(1<<1)	/* Bit  1:	ENAB: Enable IRQs */
-#define PHY_L_IS_FORCE		(1<<0)	/* Bit  0:	ENAB: Force Interrupt */
-
-/* int. mask */
-#define PHY_L_DEF_MSK		(PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
-
-/*****  PHY_LONE_LED_CFG	16 bit r/w	LED Configuration Reg *****/
-#define PHY_L_LC_LEDC		(3<<14)	/* Bit 15..14:	Col/Blink/On/Off */
-#define PHY_L_LC_LEDR		(3<<12)	/* Bit 13..12:	Rx/Blink/On/Off */
-#define PHY_L_LC_LEDT		(3<<10)	/* Bit 11..10:	Tx/Blink/On/Off */
-#define PHY_L_LC_LEDG		(3<<8)	/* Bit  9..8:	Giga/Blink/On/Off */
-#define PHY_L_LC_LEDS		(3<<6)	/* Bit  7..6:	10-100/Blink/On/Off */
-#define PHY_L_LC_LEDL		(3<<4)	/* Bit  5..4:	Link/Blink/On/Off */
-#define PHY_L_LC_LEDF		(3<<2)	/* Bit  3..2:	Duplex/Blink/On/Off */
-#define PHY_L_LC_PSTRECH	(1<<1)	/* Bit  1:	Strech LED Pulses */
-#define PHY_L_LC_FREQ		(1<<0)	/* Bit  0:	30/100 ms */
-
-/*****  PHY_LONE_PORT_CTRL	16 bit r/w	Port Control Reg *****/
-#define PHY_L_PC_TX_TCLK	(1<<15)	/* Bit 15:	Enable TX_TCLK */
-									/* Bit 14:	reserved */
-#define PHY_L_PC_ALT_NP		(1<<13)	/* Bit 14:	Alternate Next Page */
-#define PHY_L_PC_GMII_ALT	(1<<12)	/* Bit 13:	Alternate GMII driver */
-									/* Bit 11:	reserved */
-#define PHY_L_PC_TEN_CRS	(1<<10)	/* Bit 10:	Extend CRS*/
-									/* Bit  9..0:	not described */
-
-/*****  PHY_LONE_CIM		16 bit r/o	CIM Reg *****/
-#define PHY_L_CIM_ISOL		(255<<8)/* Bit 15..8:	Isolate Count */
-#define PHY_L_CIM_FALSE_CAR	(255<<0)/* Bit  7..0:	False Carrier Count */
-
-
-/*
- * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
- */
-#define PHY_L_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
-#define PHY_L_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
-#define PHY_L_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
-#define PHY_L_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
-
-
-/*
- * National-Specific
- */
-/*****  PHY_NAT_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_N_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_N_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_N_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_N_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_N_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_N_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-#define PHY_N_1000C_APC		(1<<7)	/* Bit  7:	Asymmetric Pause Cap. */
-									/* Bit  6..0:	reserved */
-
-/*****  PHY_NAT_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_N_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_N_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_N_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_N_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status*/
-#define PHY_N_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_N_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-#define PHY_N_1000C_LP_APC	(1<<9)	/* Bit  9:	LP Asym. Pause Cap. */
-									/* Bit  8:	reserved */
-#define PHY_N_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_NAT_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_N_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_N_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_N_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_N_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/* todo: those are still missing */
-/*****  PHY_NAT_EXT_CTRL1	16 bit r/o	Extended Control Reg1 *****/
-/*****  PHY_NAT_Q_STAT1		16 bit r/o	Quick Status Reg1 *****/
-/*****  PHY_NAT_10B_OP		16 bit r/o	10Base-T Operations Reg *****/
-/*****  PHY_NAT_EXT_CTRL2	16 bit r/o	Extended Control Reg1 *****/
-/*****  PHY_NAT_Q_STAT2		16 bit r/o	Quick Status Reg2 *****/
-/*****  PHY_NAT_PHY_ADDR	16 bit r/o	PHY Address Register *****/
-
-/*
- * Marvell-Specific
- */
-/*****  PHY_MARV_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_MARV_AUNE_LP	16 bit r/w	Link Part Ability Reg *****/
-#define PHY_M_AN_NXT_PG		BIT_15	/* Request Next Page */
-#define PHY_M_AN_ACK		BIT_14	/* (ro)	Acknowledge Received */
-#define PHY_M_AN_RF			BIT_13	/* Remote Fault */
-									/* Bit 12:	reserved */
-#define PHY_M_AN_ASP		BIT_11	/* Asymmetric Pause */
-#define PHY_M_AN_PC			BIT_10	/* MAC Pause implemented */
-#define PHY_M_AN_100_FD		BIT_8	/* Advertise 100Base-TX Full Duplex */
-#define PHY_M_AN_100_HD		BIT_7	/* Advertise 100Base-TX Half Duplex */
-#define PHY_M_AN_10_FD		BIT_6	/* Advertise 10Base-TX Full Duplex */
-#define PHY_M_AN_10_HD		BIT_5	/* Advertise 10Base-TX Half Duplex */
-
-/* special defines for FIBER (88E1011S only) */
-#define PHY_M_AN_ASP_X		BIT_8	/* Asymmetric Pause */
-#define PHY_M_AN_PC_X		BIT_7	/* MAC Pause implemented */
-#define PHY_M_AN_1000X_AHD	BIT_6	/* Advertise 10000Base-X Half Duplex */
-#define PHY_M_AN_1000X_AFD	BIT_5	/* Advertise 10000Base-X Full Duplex */
-
-/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
-#define PHY_M_P_NO_PAUSE_X	(0<<7)	/* Bit  8.. 7:	no Pause Mode */
-#define PHY_M_P_SYM_MD_X	(1<<7)	/* Bit  8.. 7:	symmetric Pause Mode */
-#define PHY_M_P_ASYM_MD_X	(2<<7)	/* Bit  8.. 7:	asymmetric Pause Mode */
-#define PHY_M_P_BOTH_MD_X	(3<<7)	/* Bit  8.. 7:	both Pause Mode */
-
-/*****  PHY_MARV_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_M_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_M_1000C_MSE		(1<<12)	/* Bit 12:	Manual Master/Slave Enable */
-#define PHY_M_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration (1=Master) */
-#define PHY_M_1000C_MPD		(1<<10)	/* Bit 10:	Multi-Port Device */
-#define PHY_M_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_M_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_MARV_PHY_CTRL	16 bit r/w	PHY Specific Ctrl Reg *****/
-#define PHY_M_PC_TX_FFD_MSK	(3<<14)	/* Bit 15..14:	Tx FIFO Depth Mask */
-#define PHY_M_PC_RX_FFD_MSK	(3<<12)	/* Bit 13..12:	Rx FIFO Depth Mask */
-#define PHY_M_PC_ASS_CRS_TX	(1<<11)	/* Bit 11:	Assert CRS on Transmit */
-#define PHY_M_PC_FL_GOOD	(1<<10)	/* Bit 10:	Force Link Good */
-#define PHY_M_PC_EN_DET_MSK	(3<<8)	/* Bit  9.. 8:	Energy Detect Mask */
-#define PHY_M_PC_ENA_EXT_D	(1<<7)	/* Bit  7:	Enable Ext. Distance (10BT) */
-#define PHY_M_PC_MDIX_MSK	(3<<5)	/* Bit  6.. 5:	MDI/MDIX Config. Mask */
-#define PHY_M_PC_DIS_125CLK	(1<<4)	/* Bit  4:	Disable 125 CLK */
-#define PHY_M_PC_MAC_POW_UP	(1<<3)	/* Bit  3:	MAC Power up */
-#define PHY_M_PC_SQE_T_ENA	(1<<2)	/* Bit  2:	SQE Test Enabled */
-#define PHY_M_PC_POL_R_DIS	(1<<1)	/* Bit  1:	Polarity Reversal Disabled */
-#define PHY_M_PC_DIS_JABBER	(1<<0)	/* Bit  0:	Disable Jabber */
-
-#define PHY_M_PC_EN_DET			SHIFT8(2)	/* Energy Detect (Mode 1) */
-#define PHY_M_PC_EN_DET_PLUS	SHIFT8(3)	/* Energy Detect Plus (Mode 2) */
-
-#define PHY_M_PC_MDI_XMODE(x)	SHIFT5(x)	
-#define PHY_M_PC_MAN_MDI	0    	/* 00 = Manual MDI configuration */
-#define PHY_M_PC_MAN_MDIX	1		/* 01 = Manual MDIX configuration */
-#define PHY_M_PC_ENA_AUTO	3		/* 11 = Enable Automatic Crossover */
-
-/*****  PHY_MARV_PHY_STAT	16 bit r/o	PHY Specific Status Reg *****/
-#define PHY_M_PS_SPEED_MSK	(3<<14)	/* Bit 15..14:	Speed Mask */
-#define PHY_M_PS_SPEED_1000	(1<<15)	/*       10 = 1000 Mbps */
-#define PHY_M_PS_SPEED_100	(1<<14)	/*       01 =  100 Mbps */
-#define PHY_M_PS_SPEED_10	0		/*       00 =   10 Mbps */
-#define PHY_M_PS_FULL_DUP	(1<<13)	/* Bit 13:	Full Duplex */
-#define PHY_M_PS_PAGE_REC	(1<<12)	/* Bit 12:	Page Received */
-#define PHY_M_PS_SPDUP_RES	(1<<11)	/* Bit 11:	Speed & Duplex Resolved */
-#define PHY_M_PS_LINK_UP	(1<<10)	/* Bit 10:	Link Up */
-#define PHY_M_PS_CABLE_MSK	(3<<7)	/* Bit  9.. 7:	Cable Length Mask */
-#define PHY_M_PS_MDI_X_STAT	(1<<6)	/* Bit  6:	MDI Crossover Stat (1=MDIX) */
-#define PHY_M_PS_DOWNS_STAT	(1<<5)	/* Bit  5:	Downshift Status (1=downsh.) */
-#define PHY_M_PS_ENDET_STAT	(1<<4)	/* Bit  4:	Energy Detect Status (1=act) */
-#define PHY_M_PS_TX_P_EN	(1<<3)	/* Bit  3:	Tx Pause Enabled */
-#define PHY_M_PS_RX_P_EN	(1<<2)	/* Bit  2:	Rx Pause Enabled */
-#define PHY_M_PS_POL_REV	(1<<1)	/* Bit  1:	Polarity Reversed */
-#define PHY_M_PC_JABBER		(1<<0)	/* Bit  0:	Jabber */
-
-#define PHY_M_PS_PAUSE_MSK	(PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
-
-/*****  PHY_MARV_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
-/*****  PHY_MARV_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-#define PHY_M_IS_AN_ERROR	(1<<15)	/* Bit 15:	Auto-Negotiation Error */
-#define PHY_M_IS_LSP_CHANGE	(1<<14)	/* Bit 14:	Link Speed Changed */
-#define PHY_M_IS_DUP_CHANGE	(1<<13)	/* Bit 13:	Duplex Mode Changed */
-#define PHY_M_IS_AN_PR		(1<<12)	/* Bit 12:	Page Received */
-#define PHY_M_IS_AN_COMPL	(1<<11)	/* Bit 11:	Auto-Negotiation Completed */
-#define PHY_M_IS_LST_CHANGE	(1<<10)	/* Bit 10:	Link Status Changed */
-#define PHY_M_IS_SYMB_ERROR	(1<<9)	/* Bit  9:	Symbol Error */
-#define PHY_M_IS_FALSE_CARR	(1<<8)	/* Bit  8:	False Carrier */
-#define PHY_M_IS_FIFO_ERROR	(1<<7)	/* Bit  7:	FIFO Overflow/Underrun Error */
-#define PHY_M_IS_MDI_CHANGE	(1<<6)	/* Bit  6:	MDI Crossover Changed */
-#define PHY_M_IS_DOWNSH_DET	(1<<5)	/* Bit  5:	Downshift Detected */
-#define PHY_M_IS_END_CHANGE	(1<<4)	/* Bit  4:	Energy Detect Changed */
-									/* Bit  3..2:	reserved */
-#define PHY_M_IS_POL_CHANGE	(1<<1)	/* Bit  1:	Polarity Changed */
-#define PHY_M_IS_JABBER		(1<<0)	/* Bit  0:	Jabber */
-
-#define PHY_M_DEF_MSK		(PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
-							PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
-
-/*****  PHY_MARV_EXT_CTRL	16 bit r/w	Ext. PHY Specific Ctrl *****/
-#define PHY_M_EC_M_DSC_MSK	(3<<10)	/* Bit 11..10:	Master downshift counter */
-#define PHY_M_EC_S_DSC_MSK	(3<<8)	/* Bit  9.. 8:	Slave  downshift counter */
-#define PHY_M_EC_MAC_S_MSK	(7<<4)	/* Bit  6.. 4:	Def. MAC interface speed */
-#define PHY_M_EC_FIB_AN_ENA	(1<<3)	/* Bit  3:	Fiber Auto-Neg. Enable */
-
-#define PHY_M_EC_M_DSC(x)		SHIFT10(x)	/* 00=1x; 01=2x; 10=3x; 11=4x */
-#define PHY_M_EC_S_DSC(x)		SHIFT8(x)	/* 00=dis; 01=1x; 10=2x; 11=3x */
-#define PHY_M_EC_MAC_S(x)		SHIFT4(x)	/* 01X=0; 110=2.5; 111=25 (MHz) */
-
-#define MAC_TX_CLK_0_MHZ	2
-#define MAC_TX_CLK_2_5_MHZ	6
-#define MAC_TX_CLK_25_MHZ	7
-
-/*****  PHY_MARV_LED_CTRL	16 bit r/w	LED Control Reg *****/
-#define PHY_M_LEDC_DIS_LED	(1<<15)	/* Bit 15:	Disable LED */
-#define PHY_M_LEDC_PULS_MSK	(7<<12)	/* Bit 14..12:  Pulse Stretch Mask */
-#define PHY_M_LEDC_F_INT	(1<<11)	/* Bit 11:	Force Interrupt */
-#define PHY_M_LEDC_BL_R_MSK	(7<<8)	/* Bit 10.. 8:  Blink Rate Mask */
-									/* Bit  7.. 5:	reserved */
-#define PHY_M_LEDC_LINK_MSK	(3<<3)	/* Bit  4.. 3:	Link Control Mask */
-#define PHY_M_LEDC_DP_CTRL	(1<<2)	/* Bit  2:	Duplex Control */
-#define PHY_M_LEDC_RX_CTRL	(1<<1)	/* Bit  1:	Rx activity / Link */
-#define PHY_M_LEDC_TX_CTRL	(1<<0)	/* Bit  0:	Tx activity / Link */
-
-#define PHY_M_LED_PULS_DUR(x)	SHIFT12(x)	/* Pulse Stretch Duration */
-
-#define	PULS_NO_STR		0		/* no pulse stretching */
-#define	PULS_21MS		1		/* 21 ms to 42 ms */
-#define PULS_42MS		2		/* 42 ms to 84 ms */
-#define PULS_84MS		3		/* 84 ms to 170 ms */
-#define PULS_170MS		4		/* 170 ms to 340 ms */
-#define PULS_340MS		5		/* 340 ms to 670 ms */
-#define PULS_670MS		6		/* 670 ms to 1.3 s */
-#define PULS_1300MS		7		/* 1.3 s to 2.7 s */
-
-#define PHY_M_LED_BLINK_RT(x)	SHIFT8(x)	/* Blink Rate */
-
-#define BLINK_42MS		0		/* 42 ms */
-#define BLINK_84MS		1		/* 84 ms */
-#define BLINK_170MS		2		/* 170 ms */
-#define BLINK_340MS		3		/* 340 ms */
-#define BLINK_670MS		4		/* 670 ms */
-								/* values 5 - 7: reserved */
-
-/*****  PHY_MARV_LED_OVER	16 bit r/w	Manual LED Override Reg *****/
-#define PHY_M_LED_MO_DUP(x)		SHIFT10(x)	/* Bit 11..10:  Duplex */
-#define PHY_M_LED_MO_10(x)		SHIFT8(x)	/* Bit  9.. 8:  Link 10 */
-#define PHY_M_LED_MO_100(x)		SHIFT6(x)	/* Bit  7.. 6:  Link 100 */
-#define PHY_M_LED_MO_1000(x)	SHIFT4(x)	/* Bit  5.. 4:  Link 1000 */
-#define PHY_M_LED_MO_RX(x)		SHIFT2(x)	/* Bit  3.. 2:  Rx */
-#define PHY_M_LED_MO_TX(x)		SHIFT0(x)	/* Bit  1.. 0:  Tx */
-
-#define MO_LED_NORM			0
-#define MO_LED_BLINK		1
-#define MO_LED_OFF			2
-#define MO_LED_ON			3
-
-/*****  PHY_MARV_EXT_CTRL_2	16 bit r/w	Ext. PHY Specific Ctrl 2 *****/
-									/* Bit 15.. 7:	reserved */
-#define PHY_M_EC2_FI_IMPED	(1<<6)	/* Bit  6:	Fiber Input  Impedance */
-#define PHY_M_EC2_FO_IMPED	(1<<5)	/* Bit  5:	Fiber Output Impedance */
-#define PHY_M_EC2_FO_M_CLK	(1<<4)	/* Bit  4:	Fiber Mode Clock Enable */
-#define PHY_M_EC2_FO_BOOST	(1<<3)	/* Bit  3:	Fiber Output Boost */
-#define PHY_M_EC2_FO_AM_MSK	7		/* Bit  2.. 0:	Fiber Output Amplitude */
-
-/*****	PHY_MARV_EXT_P_STAT 16 bit r/w	Ext. PHY Specific Status *****/
-#define PHY_M_FC_AUTO_SEL	(1<<15)	/* Bit 15:	Fiber/Copper Auto Sel. dis. */
-#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14:	Fiber/Copper Autoneg. reg acc */
-#define PHY_M_FC_RESULUTION (1<<13)	/* Bit 13:	Fiber/Copper Resulution */
-#define PHY_M_SER_IF_AN_BP  (1<<12) /* Bit 12:	Ser IF autoneg. bypass enable */
-#define PHY_M_SER_IF_BP_ST	(1<<11) /* Bit 11:	Ser IF autoneg. bypass status */
-#define PHY_M_IRQ_POLARITY	(1<<10) /* Bit 10:	IRQ polarity */
-									/* Bit 9..4: reserved */
-#define PHY_M_UNDOC1		(1<< 7) /* undocumented bit !! */
-#define PHY_M_MODE_MASK		(0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */
-
-
-/*****  PHY_MARV_CABLE_DIAG	16 bit r/o	Cable Diagnostic Reg *****/
-#define PHY_M_CABD_ENA_TEST	(1<<15)	/* Bit 15:	Enable Test */
-#define PHY_M_CABD_STAT_MSK	(3<<13)	/* Bit 14..13:	Status */
-									/* Bit 12.. 8:	reserved */
-#define PHY_M_CABD_DIST_MSK	0xff	/* Bit  7.. 0:	Distance */
-
-/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
-#define CABD_STAT_NORMAL	0
-#define CABD_STAT_SHORT		1
-#define CABD_STAT_OPEN		2
-#define CABD_STAT_FAIL		3
-
-
-/*
- * GMAC registers
- *
- * The GMAC registers are 16 or 32 bits wide.
- * The GMACs host processor interface is 16 bits wide,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the GMAC registers
- * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(),
- * GM_INHASH(), and GM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note:	NA reg	= Network Address e.g DA, SA etc.
- *
- */
-
-/* Port Registers */
-#define GM_GP_STAT		0x0000		/* 16 bit r/o	General Purpose Status */
-#define GM_GP_CTRL		0x0004		/* 16 bit r/w	General Purpose Control */
-#define GM_TX_CTRL		0x0008		/* 16 bit r/w	Transmit Control Reg. */
-#define GM_RX_CTRL		0x000c		/* 16 bit r/w	Receive Control Reg. */
-#define GM_TX_FLOW_CTRL	0x0010		/* 16 bit r/w	Transmit Flow-Control */
-#define GM_TX_PARAM		0x0014		/* 16 bit r/w	Transmit Parameter Reg. */
-#define GM_SERIAL_MODE	0x0018		/* 16 bit r/w	Serial Mode Register */
-
-/* Source Address Registers */
-#define GM_SRC_ADDR_1L	0x001c		/* 16 bit r/w	Source Address 1 (low) */
-#define GM_SRC_ADDR_1M	0x0020		/* 16 bit r/w	Source Address 1 (middle) */
-#define GM_SRC_ADDR_1H	0x0024		/* 16 bit r/w	Source Address 1 (high) */
-#define GM_SRC_ADDR_2L	0x0028		/* 16 bit r/w	Source Address 2 (low) */
-#define GM_SRC_ADDR_2M	0x002c		/* 16 bit r/w	Source Address 2 (middle) */
-#define GM_SRC_ADDR_2H	0x0030		/* 16 bit r/w	Source Address 2 (high) */
-
-/* Multicast Address Hash Registers */
-#define GM_MC_ADDR_H1	0x0034		/* 16 bit r/w	Multicast Address Hash 1 */
-#define GM_MC_ADDR_H2	0x0038		/* 16 bit r/w	Multicast Address Hash 2 */
-#define GM_MC_ADDR_H3	0x003c		/* 16 bit r/w	Multicast Address Hash 3 */
-#define GM_MC_ADDR_H4	0x0040		/* 16 bit r/w	Multicast Address Hash 4 */
-
-/* Interrupt Source Registers */
-#define GM_TX_IRQ_SRC	0x0044		/* 16 bit r/o	Tx Overflow IRQ Source */
-#define GM_RX_IRQ_SRC	0x0048		/* 16 bit r/o	Rx Overflow IRQ Source */
-#define GM_TR_IRQ_SRC	0x004c		/* 16 bit r/o	Tx/Rx Over. IRQ Source */
-
-/* Interrupt Mask Registers */
-#define GM_TX_IRQ_MSK	0x0050		/* 16 bit r/w	Tx Overflow IRQ Mask */
-#define GM_RX_IRQ_MSK	0x0054		/* 16 bit r/w	Rx Overflow IRQ Mask */
-#define GM_TR_IRQ_MSK	0x0058		/* 16 bit r/w	Tx/Rx Over. IRQ Mask */
-
-/* Serial Management Interface (SMI) Registers */
-#define GM_SMI_CTRL		0x0080		/* 16 bit r/w	SMI Control Register */
-#define GM_SMI_DATA		0x0084		/* 16 bit r/w	SMI Data Register */
-#define GM_PHY_ADDR		0x0088		/* 16 bit r/w	GPHY Address Register */
-
-/* MIB Counters */
-#define GM_MIB_CNT_BASE	0x0100		/* Base Address of MIB Counters */
-#define GM_MIB_CNT_SIZE	44			/* Number of MIB Counters */
-
-/*
- * MIB Counters base address definitions (low word) -
- * use offset 4 for access to high word	(32 bit r/o)
- */
-#define GM_RXF_UC_OK \
-			(GM_MIB_CNT_BASE + 0)	/* Unicast Frames Received OK */
-#define GM_RXF_BC_OK \
-			(GM_MIB_CNT_BASE + 8)	/* Broadcast Frames Received OK */
-#define GM_RXF_MPAUSE \
-			(GM_MIB_CNT_BASE + 16)	/* Pause MAC Ctrl Frames Received */
-#define GM_RXF_MC_OK \
-			(GM_MIB_CNT_BASE + 24)	/* Multicast Frames Received OK */
-#define GM_RXF_FCS_ERR \
-			(GM_MIB_CNT_BASE + 32)	/* Rx Frame Check Seq. Error */
-	/* GM_MIB_CNT_BASE + 40:	reserved */
-#define GM_RXO_OK_LO \
-			(GM_MIB_CNT_BASE + 48)	/* Octets Received OK Low */
-#define GM_RXO_OK_HI \
-			(GM_MIB_CNT_BASE + 56)	/* Octets Received OK High */
-#define GM_RXO_ERR_LO \
-			(GM_MIB_CNT_BASE + 64)	/* Octets Received Invalid Low */
-#define GM_RXO_ERR_HI \
-			(GM_MIB_CNT_BASE + 72)	/* Octets Received Invalid High */
-#define GM_RXF_SHT \
-			(GM_MIB_CNT_BASE + 80)	/* Frames <64 Byte Received OK */
-#define GM_RXE_FRAG \
-			(GM_MIB_CNT_BASE + 88)	/* Frames <64 Byte Received with FCS Err */
-#define GM_RXF_64B \
-			(GM_MIB_CNT_BASE + 96)	/* 64 Byte Rx Frame */
-#define GM_RXF_127B \
-			(GM_MIB_CNT_BASE + 104)	/* 65-127 Byte Rx Frame */
-#define GM_RXF_255B \
-			(GM_MIB_CNT_BASE + 112)	/* 128-255 Byte Rx Frame */
-#define GM_RXF_511B \
-			(GM_MIB_CNT_BASE + 120)	/* 256-511 Byte Rx Frame */
-#define GM_RXF_1023B \
-			(GM_MIB_CNT_BASE + 128)	/* 512-1023 Byte Rx Frame */
-#define GM_RXF_1518B \
-			(GM_MIB_CNT_BASE + 136)	/* 1024-1518 Byte Rx Frame */
-#define GM_RXF_MAX_SZ \
-			(GM_MIB_CNT_BASE + 144)	/* 1519-MaxSize Byte Rx Frame */
-#define GM_RXF_LNG_ERR \
-			(GM_MIB_CNT_BASE + 152)	/* Rx Frame too Long Error */
-#define GM_RXF_JAB_PKT \
-			(GM_MIB_CNT_BASE + 160)	/* Rx Jabber Packet Frame */
-	/* GM_MIB_CNT_BASE + 168:	reserved */
-#define GM_RXE_FIFO_OV \
-			(GM_MIB_CNT_BASE + 176)	/* Rx FIFO overflow Event */
-	/* GM_MIB_CNT_BASE + 184:	reserved */
-#define GM_TXF_UC_OK \
-			(GM_MIB_CNT_BASE + 192)	/* Unicast Frames Xmitted OK */
-#define GM_TXF_BC_OK \
-			(GM_MIB_CNT_BASE + 200)	/* Broadcast Frames Xmitted OK */
-#define GM_TXF_MPAUSE \
-			(GM_MIB_CNT_BASE + 208)	/* Pause MAC Ctrl Frames Xmitted */
-#define GM_TXF_MC_OK \
-			(GM_MIB_CNT_BASE + 216)	/* Multicast Frames Xmitted OK */
-#define GM_TXO_OK_LO \
-			(GM_MIB_CNT_BASE + 224)	/* Octets Transmitted OK Low */
-#define GM_TXO_OK_HI \
-			(GM_MIB_CNT_BASE + 232)	/* Octets Transmitted OK High */
-#define GM_TXF_64B \
-			(GM_MIB_CNT_BASE + 240)	/* 64 Byte Tx Frame */
-#define GM_TXF_127B \
-			(GM_MIB_CNT_BASE + 248)	/* 65-127 Byte Tx Frame */
-#define GM_TXF_255B \
-			(GM_MIB_CNT_BASE + 256)	/* 128-255 Byte Tx Frame */
-#define GM_TXF_511B \
-			(GM_MIB_CNT_BASE + 264)	/* 256-511 Byte Tx Frame */
-#define GM_TXF_1023B \
-			(GM_MIB_CNT_BASE + 272)	/* 512-1023 Byte Tx Frame */
-#define GM_TXF_1518B \
-			(GM_MIB_CNT_BASE + 280)	/* 1024-1518 Byte Tx Frame */
-#define GM_TXF_MAX_SZ \
-			(GM_MIB_CNT_BASE + 288)	/* 1519-MaxSize Byte Tx Frame */
-	/* GM_MIB_CNT_BASE + 296:	reserved */
-#define GM_TXF_COL \
-			(GM_MIB_CNT_BASE + 304)	/* Tx Collision */
-#define GM_TXF_LAT_COL \
-			(GM_MIB_CNT_BASE + 312)	/* Tx Late Collision */
-#define GM_TXF_ABO_COL \
-			(GM_MIB_CNT_BASE + 320)	/* Tx aborted due to Exces. Col. */
-#define GM_TXF_MUL_COL \
-			(GM_MIB_CNT_BASE + 328)	/* Tx Multiple Collision */
-#define GM_TXF_SNG_COL \
-			(GM_MIB_CNT_BASE + 336)	/* Tx Single Collision */
-#define GM_TXE_FIFO_UR \
-			(GM_MIB_CNT_BASE + 344)	/* Tx FIFO Underrun Event */
-
-/*----------------------------------------------------------------------------*/
-/*
- * GMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- *	(sc)	self clearing
- *	(r/o)	read only
- */
-
-/*	GM_GP_STAT	16 bit r/o	General Purpose Status Register */
-#define GM_GPSR_SPEED		(1<<15) /* Bit 15:	Port Speed (1 = 100 Mbps) */
-#define GM_GPSR_DUPLEX		(1<<14) /* Bit 14:	Duplex Mode (1 = Full) */
-#define GM_GPSR_FC_TX_DIS	(1<<13) /* Bit 13:	Tx Flow-Control Mode Disabled */
-#define GM_GPSR_LINK_UP		(1<<12)	/* Bit 12:	Link Up Status */
-#define GM_GPSR_PAUSE		(1<<11)	/* Bit 11:	Pause State */
-#define GM_GPSR_TX_ACTIVE	(1<<10)	/* Bit 10:	Tx in Progress */
-#define GM_GPSR_EXC_COL		(1<<9)	/* Bit  9:	Excessive Collisions Occured */
-#define GM_GPSR_LAT_COL		(1<<8)	/* Bit  8:	Late Collisions Occured */
-								/* Bit  7..6:	reserved */
-#define GM_GPSR_PHY_ST_CH	(1<<5)	/* Bit  5:	PHY Status Change */
-#define GM_GPSR_GIG_SPEED	(1<<4)	/* Bit  4:	Gigabit Speed (1 = 1000 Mbps) */
-#define GM_GPSR_PART_MODE	(1<<3)	/* Bit  3:	Partition mode */
-#define GM_GPSR_FC_RX_DIS	(1<<2)	/* Bit  2:	Rx Flow-Control Mode Disabled */
-#define GM_GPSR_PROM_EN		(1<<1)	/* Bit  1:	Promiscuous Mode Enabled */
-								/* Bit  0:	reserved */
-	
-/*	GM_GP_CTRL	16 bit r/w	General Purpose Control Register */
-								/* Bit 15:	reserved */
-#define GM_GPCR_PROM_ENA	(1<<14)	/* Bit 14:	Enable Promiscuous Mode */
-#define GM_GPCR_FC_TX_DIS	(1<<13) /* Bit 13:	Disable Tx Flow-Control Mode */
-#define GM_GPCR_TX_ENA		(1<<12) /* Bit 12:	Enable Transmit */
-#define GM_GPCR_RX_ENA		(1<<11) /* Bit 11:	Enable Receive */
-#define GM_GPCR_BURST_ENA	(1<<10)	/* Bit 10:	Enable Burst Mode */
-#define GM_GPCR_LOOP_ENA	(1<<9)	/* Bit  9:	Enable MAC Loopback Mode */
-#define GM_GPCR_PART_ENA	(1<<8)	/* Bit  8:	Enable Partition Mode */
-#define GM_GPCR_GIGS_ENA	(1<<7)	/* Bit  7:	Gigabit Speed (1000 Mbps) */
-#define GM_GPCR_FL_PASS		(1<<6)	/* Bit  6:	Force Link Pass */
-#define GM_GPCR_DUP_FULL	(1<<5)	/* Bit  5:	Full Duplex Mode */
-#define GM_GPCR_FC_RX_DIS	(1<<4)	/* Bit  4:	Disable Rx Flow-Control Mode */
-#define GM_GPCR_SPEED_100	(1<<3)  /* Bit  3:	Port Speed 100 Mbps */
-#define GM_GPCR_AU_DUP_DIS	(1<<2)	/* Bit  2:	Disable Auto-Update Duplex */
-#define GM_GPCR_AU_FCT_DIS	(1<<1)	/* Bit  1:	Disable Auto-Update Flow-C. */
-#define GM_GPCR_AU_SPD_DIS	(1<<0)	/* Bit  0:	Disable Auto-Update Speed */
-
-#define GM_GPCR_SPEED_1000	(GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
-#define GM_GPCR_AU_ALL_DIS	(GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
-							 GM_GPCR_AU_SPD_DIS)
-	
-/*	GM_TX_CTRL				16 bit r/w	Transmit Control Register */
-#define GM_TXCR_FORCE_JAM	(1<<15)	/* Bit 15:	Force Jam / Flow-Control */
-#define GM_TXCR_CRC_DIS		(1<<14)	/* Bit 14:	Disable insertion of CRC */
-#define GM_TXCR_PAD_DIS		(1<<13)	/* Bit 13:	Disable padding of packets */
-#define GM_TXCR_COL_THR_MSK	(7<<10)	/* Bit 12..10:	Collision Threshold */
-
-#define TX_COL_THR(x)		(SHIFT10(x) & GM_TXCR_COL_THR_MSK)
-
-#define TX_COL_DEF			0x04
-	
-/*	GM_RX_CTRL				16 bit r/w	Receive Control Register */
-#define GM_RXCR_UCF_ENA		(1<<15)	/* Bit 15:	Enable Unicast filtering */
-#define GM_RXCR_MCF_ENA		(1<<14)	/* Bit 14:	Enable Multicast filtering */
-#define GM_RXCR_CRC_DIS		(1<<13)	/* Bit 13:	Remove 4-byte CRC */
-#define GM_RXCR_PASS_FC		(1<<12)	/* Bit 12:	Pass FC packets to FIFO */
-	
-/*	GM_TX_PARAM				16 bit r/w	Transmit Parameter Register */
-#define GM_TXPA_JAMLEN_MSK	(0x03<<14)	/* Bit 15..14:	Jam Length */
-#define GM_TXPA_JAMIPG_MSK	(0x1f<<9)	/* Bit 13..9:	Jam IPG */
-#define GM_TXPA_JAMDAT_MSK	(0x1f<<4)	/* Bit  8..4:	IPG Jam to Data */
-								/* Bit  3..0:	reserved */
-
-#define TX_JAM_LEN_VAL(x)	(SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
-#define TX_JAM_IPG_VAL(x)	(SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
-#define TX_IPG_JAM_DATA(x)	(SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
-
-#define TX_JAM_LEN_DEF		0x03
-#define TX_JAM_IPG_DEF		0x0b
-#define TX_IPG_JAM_DEF		0x1c
-
-/*	GM_SERIAL_MODE			16 bit r/w	Serial Mode Register */
-#define GM_SMOD_DATABL_MSK	(0x1f<<11)	/* Bit 15..11:	Data Blinder (r/o) */
-#define GM_SMOD_LIMIT_4		(1<<10)	/* Bit 10:	4 consecutive Tx trials */
-#define GM_SMOD_VLAN_ENA	(1<<9)	/* Bit  9:	Enable VLAN  (Max. Frame Len) */
-#define GM_SMOD_JUMBO_ENA	(1<<8)	/* Bit  8:	Enable Jumbo (Max. Frame Len) */
-								/* Bit  7..5:	reserved */
-#define GM_SMOD_IPG_MSK		0x1f	/* Bit 4..0:	Inter-Packet Gap (IPG) */
-	
-#define DATA_BLIND_VAL(x)	(SHIFT11(x) & GM_SMOD_DATABL_MSK)
-#define DATA_BLIND_DEF		0x04
-
-#define IPG_DATA_VAL(x)		(x & GM_SMOD_IPG_MSK)
-#define IPG_DATA_DEF		0x1e
-
-/*	GM_SMI_CTRL				16 bit r/w	SMI Control Register */
-#define GM_SMI_CT_PHY_A_MSK	(0x1f<<11)	/* Bit 15..11:	PHY Device Address */
-#define GM_SMI_CT_REG_A_MSK	(0x1f<<6)	/* Bit 10.. 6:	PHY Register Address */
-#define GM_SMI_CT_OP_RD		(1<<5)	/* Bit  5:	OpCode Read (0=Write)*/
-#define GM_SMI_CT_RD_VAL	(1<<4)	/* Bit  4:	Read Valid (Read completed) */
-#define GM_SMI_CT_BUSY		(1<<3)	/* Bit  3:	Busy (Operation in progress) */
-								/* Bit   2..0:	reserved */
-	
-#define GM_SMI_CT_PHY_AD(x)	(SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
-#define GM_SMI_CT_REG_AD(x)	(SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
-
-	/*	GM_PHY_ADDR				16 bit r/w	GPHY Address Register */
-								/* Bit  15..6:	reserved */
-#define GM_PAR_MIB_CLR		(1<<5)	/* Bit  5:	Set MIB Clear Counter Mode */
-#define GM_PAR_MIB_TST		(1<<4)	/* Bit  4:	MIB Load Counter (Test Mode) */
-								/* Bit   3..0:	reserved */
-	
-/* Receive Frame Status Encoding */
-#define GMR_FS_LEN	(0xffffUL<<16)	/* Bit 31..16:	Rx Frame Length */
-								/* Bit  15..14:	reserved */
-#define GMR_FS_VLAN		(1L<<13)	/* Bit 13:	VLAN Packet */
-#define GMR_FS_JABBER	(1L<<12)	/* Bit 12:	Jabber Packet */
-#define GMR_FS_UN_SIZE	(1L<<11)	/* Bit 11:	Undersize Packet */
-#define GMR_FS_MC		(1L<<10)	/* Bit 10:	Multicast Packet */
-#define GMR_FS_BC		(1L<<9)		/* Bit  9:	Broadcast Packet */
-#define GMR_FS_RX_OK	(1L<<8)		/* Bit  8:	Receive OK (Good Packet) */
-#define GMR_FS_GOOD_FC	(1L<<7)		/* Bit  7:	Good Flow-Control Packet */
-#define GMR_FS_BAD_FC	(1L<<6)		/* Bit  6:	Bad  Flow-Control Packet */
-#define GMR_FS_MII_ERR	(1L<<5)		/* Bit  5:	MII Error */
-#define GMR_FS_LONG_ERR	(1L<<4)		/* Bit  4:	Too Long Packet */
-#define GMR_FS_FRAGMENT	(1L<<3)		/* Bit  3:	Fragment */
-								/* Bit  2:	reserved */
-#define GMR_FS_CRC_ERR	(1L<<1)		/* Bit  1:	CRC Error */
-#define GMR_FS_RX_FF_OV	(1L<<0)		/* Bit  0:	Rx FIFO Overflow */
-
-/*
- * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
- */
-#define GMR_FS_ANY_ERR	(GMR_FS_CRC_ERR | \
-			GMR_FS_LONG_ERR | \
-			GMR_FS_MII_ERR | \
-			GMR_FS_BAD_FC | \
-			GMR_FS_GOOD_FC | \
-			GMR_FS_JABBER)
-
-/* Rx GMAC FIFO Flush Mask (default) */
-#define RX_FF_FL_DEF_MSK	(GMR_FS_CRC_ERR | \
-			GMR_FS_RX_FF_OV | \
-			GMR_FS_MII_ERR | \
-			GMR_FS_BAD_FC | \
-			GMR_FS_GOOD_FC | \
-			GMR_FS_UN_SIZE | \
-			GMR_FS_JABBER)
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_XMAC_H */
diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
deleted file mode 100644
index 6e6c56a..0000000
--- a/drivers/net/sk98lin/skaddr.c
+++ /dev/null
@@ -1,1788 +0,0 @@
-/******************************************************************************
- *
- * Name:	skaddr.c
- * Project:	Gigabit Ethernet Adapters, ADDR-Module
- * Version:	$Revision: 1.52 $
- * Date:	$Date: 2003/06/02 13:46:15 $
- * Purpose:	Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses, address override,
- * and promiscuous mode on GEnesis and Yukon adapters.
- *
- * Address Layout:
- *	port address:		physical MAC address
- *	1st exact match:	logical MAC address (GEnesis only)
- *	2nd exact match:	RLMT multicast (GEnesis only)
- *	exact match 3-13:	OS-specific multicasts (GEnesis only)
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
-#endif /* DEBUG ||!LINT || !SK_SLIM */
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-
-#define XMAC_POLY	0xEDB88320UL	/* CRC32-Poly - XMAC: Little Endian */
-#define GMAC_POLY	0x04C11DB7L	/* CRC16-Poly - GMAC: Little Endian */
-#define HASH_BITS	6				/* #bits in hash */
-#define	SK_MC_BIT	0x01
-
-/* Error numbers and messages. */
-
-#define SKERR_ADDR_E001		(SK_ERRBASE_ADDR + 0)
-#define SKERR_ADDR_E001MSG	"Bad Flags."
-#define SKERR_ADDR_E002		(SKERR_ADDR_E001 + 1)
-#define SKERR_ADDR_E002MSG	"New Error."
-
-/* typedefs *******************************************************************/
-
-/* None. */
-
-/* global variables ***********************************************************/
-
-/* 64-bit hash values with all bits set. */
-
-static const SK_U16	OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
-
-/* local variables ************************************************************/
-
-#ifdef DEBUG
-static int	Next0[SK_MAX_MACS] = {0};
-#endif	/* DEBUG */
-
-static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			   SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			     int Flags);
-static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
-				       SK_U32 PortNumber, int NewPromMode);
-static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			   SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			     int Flags);
-static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
-				       SK_U32 PortNumber, int NewPromMode);
-
-/* functions ******************************************************************/
-
-/******************************************************************************
- *
- *	SkAddrInit - initialize data, set state to init
- *
- * Description:
- *
- *	SK_INIT_DATA
- *	============
- *
- *	This routine clears the multicast tables and resets promiscuous mode.
- *	Some entries are reserved for the "logical MAC address", the
- *	SK-RLMT multicast address, and the BPDU multicast address.
- *
- *
- *	SK_INIT_IO
- *	==========
- *
- *	All permanent MAC addresses are read from EPROM.
- *	If the current MAC addresses are not already set in software,
- *	they are set to the values of the permanent addresses.
- *	The current addresses are written to the corresponding MAC.
- *
- *
- *	SK_INIT_RUN
- *	===========
- *
- *	Nothing.
- *
- * Context:
- *	init, pageable
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- */
-int	SkAddrInit(
-SK_AC	*pAC,	/* the adapter context */
-SK_IOC	IoC,	/* I/O context */
-int		Level)	/* initialization level */
-{
-	int			j;
-	SK_U32		i;
-	SK_U8		*InAddr;
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
-            (SK_U16) sizeof(SK_ADDR));
-
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			pAPort = &pAC->Addr.Port[i];
-			pAPort->PromMode = SK_PROM_MODE_NONE;
-			
-			pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-			pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-			pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-			pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-		}
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 4;
-			}
-		}
-#endif	/* DEBUG */
-		/* pAC->Addr.InitDone = SK_INIT_DATA; */
-		break;
-
-    case SK_INIT_IO:
-#ifndef SK_NO_RLMT
-		for (i = 0; i < SK_MAX_NETS; i++) {
-			pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
-		}
-#endif /* !SK_NO_RLMT */
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 8;
-			}
-		}
-#endif	/* DEBUG */
-		
-		/* Read permanent logical MAC address from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
-			SK_IN8(IoC, B2_MAC_1 + j, InAddr);
-		}
-
-		if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
-			/* Set the current logical MAC address to the permanent one. */
-			pAC->Addr.Net[0].CurrentMacAddress =
-				pAC->Addr.Net[0].PermanentMacAddress;
-			pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
-		}
-
-		/* Set the current logical MAC address. */
-		pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
-			pAC->Addr.Net[0].CurrentMacAddress;
-#if SK_MAX_NETS > 1
-		/* Set logical MAC address for net 2 to (log | 3). */
-		if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
-			pAC->Addr.Net[1].PermanentMacAddress =
-				pAC->Addr.Net[0].PermanentMacAddress;
-			pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
-			/* Set the current logical MAC address to the permanent one. */
-			pAC->Addr.Net[1].CurrentMacAddress =
-				pAC->Addr.Net[1].PermanentMacAddress;
-			pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
-		}
-#endif	/* SK_MAX_NETS > 1 */
-
-#ifdef DEBUG
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
-					i,
-					pAC->Addr.Net[i].PermanentMacAddress.a[0],
-					pAC->Addr.Net[i].PermanentMacAddress.a[1],
-					pAC->Addr.Net[i].PermanentMacAddress.a[2],
-					pAC->Addr.Net[i].PermanentMacAddress.a[3],
-					pAC->Addr.Net[i].PermanentMacAddress.a[4],
-					pAC->Addr.Net[i].PermanentMacAddress.a[5]))
-			
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
-					i,
-					pAC->Addr.Net[i].CurrentMacAddress.a[0],
-					pAC->Addr.Net[i].CurrentMacAddress.a[1],
-					pAC->Addr.Net[i].CurrentMacAddress.a[2],
-					pAC->Addr.Net[i].CurrentMacAddress.a[3],
-					pAC->Addr.Net[i].CurrentMacAddress.a[4],
-					pAC->Addr.Net[i].CurrentMacAddress.a[5]))
-		}
-#endif	/* DEBUG */
-
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			pAPort = &pAC->Addr.Port[i];
-
-			/* Read permanent port addresses from Control Register File. */
-			for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-				InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
-				SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
-			}
-
-			if (!pAPort->CurrentMacAddressSet) {
-				/*
-				 * Set the current and previous physical MAC address
-				 * of this port to its permanent MAC address.
-				 */
-				pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
-				pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
-				pAPort->CurrentMacAddressSet = SK_TRUE;
-			}
-
-			/* Set port's current physical MAC address. */
-			OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-#ifdef GENESIS
-			if (pAC->GIni.GIGenesis) {
-				XM_OUTADDR(IoC, i, XM_SA, OutAddr);
-			}
-#endif /* GENESIS */
-#ifdef YUKON
-			if (!pAC->GIni.GIGenesis) {
-				GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
-			}
-#endif /* YUKON */
-#ifdef DEBUG
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-					pAPort->PermanentMacAddress.a[0],
-					pAPort->PermanentMacAddress.a[1],
-					pAPort->PermanentMacAddress.a[2],
-					pAPort->PermanentMacAddress.a[3],
-					pAPort->PermanentMacAddress.a[4],
-					pAPort->PermanentMacAddress.a[5]))
-			
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-					pAPort->CurrentMacAddress.a[0],
-					pAPort->CurrentMacAddress.a[1],
-					pAPort->CurrentMacAddress.a[2],
-					pAPort->CurrentMacAddress.a[3],
-					pAPort->CurrentMacAddress.a[4],
-					pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-		}
-		/* pAC->Addr.InitDone = SK_INIT_IO; */
-		break;
-
-	case SK_INIT_RUN:
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 16;
-			}
-		}
-#endif	/* DEBUG */
-
-		/* pAC->Addr.InitDone = SK_INIT_RUN; */
-		break;
-
-	default:	/* error */
-		break;
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrInit */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast table.
- *
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- *	It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
- *	to the adapter in use. The real work is done there.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int ReturnCode;
-	
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-	
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
-	}
-	else {
-		ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
-	}
-
-	return (ReturnCode);
-
-}	/* SkAddrMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrXmacMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast table
- *	(either entry 2 or entries 3-16 and InexactFilter) of the given port.
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int i;
-
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-
-		/* Clear RLMT multicast addresses. */
-		pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-	}
-	else {	/* not permanent => DRV */
-
-		/* Clear InexactFilter */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-		}
-
-		/* Clear DRV multicast addresses. */
-
-		pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-	}
-
-	if (!(Flags & SK_MC_SW_ONLY)) {
-		(void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrXmacMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrGmacMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast hashing table (InexactFilter)
- *	(either the RLMT or the driver bits) of the given port.
- *
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int i;
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif	/* DEBUG */
-
-	/* Clear InexactFilter */
-	for (i = 0; i < 8; i++) {
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-	}
-	
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-		
-		/* Copy DRV bits to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
-			
-			/* Clear InexactRlmtFilter. */
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
-
-		}		
-	}
-	else {	/* not permanent => DRV */
-		
-		/* Copy RLMT bits to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
-			
-			/* Clear InexactDrvFilter. */
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
-		}
-	}
-	
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif	/* DEBUG */
-	
-	if (!(Flags & SK_MC_SW_ONLY)) {
-		(void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
-	}
-	
-	return (SK_ADDR_SUCCESS);
-
-}	/* SkAddrGmacMcClear */
-
-#ifndef SK_ADDR_CHEAT
-
-/******************************************************************************
- *
- *	SkXmacMcHash - hash multicast address
- *
- * Description:
- *	This routine computes the hash value for a multicast address.
- *	A CRC32 algorithm is used.
- *
- * Notes:
- *	The code was adapted from the XaQti data sheet.
- *
- * Context:
- *	runtime, pageable
- *
- * Returns:
- *	Hash value of multicast address.
- */
-static SK_U32 SkXmacMcHash(
-unsigned char *pMc)	/* Multicast address */
-{
-	SK_U32 Idx;
-	SK_U32 Bit;
-	SK_U32 Data;
-	SK_U32 Crc;
-
-	Crc = 0xFFFFFFFFUL;
-	for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
-		Data = *pMc++;
-		for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
-			Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
-		}
-	}
-
-	return (Crc & ((1 << HASH_BITS) - 1));
-
-}	/* SkXmacMcHash */
-
-
-/******************************************************************************
- *
- *	SkGmacMcHash - hash multicast address
- *
- * Description:
- *	This routine computes the hash value for a multicast address.
- *	A CRC16 algorithm is used.
- *
- * Notes:
- *
- *
- * Context:
- *	runtime, pageable
- *
- * Returns:
- *	Hash value of multicast address.
- */
-static SK_U32 SkGmacMcHash(
-unsigned char *pMc)	/* Multicast address */
-{
-	SK_U32 Data;
-	SK_U32 TmpData;
-	SK_U32 Crc;
-	int Byte;
-	int Bit;
-
-	Crc = 0xFFFFFFFFUL;
-	for (Byte = 0; Byte < 6; Byte++) {
-		/* Get next byte. */
-		Data = (SK_U32) pMc[Byte];
-		
-		/* Change bit order in byte. */
-		TmpData = Data;
-		for (Bit = 0; Bit < 8; Bit++) {
-			if (TmpData & 1L) {
-				Data |=  1L << (7 - Bit);
-			}
-			else {
-				Data &= ~(1L << (7 - Bit));
-			}
-			TmpData >>= 1;
-		}
-		
-		Crc ^= (Data << 24);
-		for (Bit = 0; Bit < 8; Bit++) {
-			if (Crc & 0x80000000) {
-				Crc = (Crc << 1) ^ GMAC_POLY;
-			}
-			else {
-				Crc <<= 1;
-			}
-		}
-	}
-	
-	return (Crc & ((1 << HASH_BITS) - 1));
-
-}	/* SkGmacMcHash */
-
-#endif	/* !SK_ADDR_CHEAT */
-
-/******************************************************************************
- *
- *	SkAddrMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- *	It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
- *	adapter in use. The real work is done there.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- *	SK_MC_ILLEGAL_PORT
- *	SK_MC_RLMT_OVERFLOW
- */
-int	SkAddrMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int			Flags)		/* permanent/non-permanent */
-{
-	int ReturnCode;
-	
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-	
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
-	}
-	else {
-		ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
-	}
-
-	return (ReturnCode);
-
-}	/* SkAddrMcAdd */
-
-
-/******************************************************************************
- *
- *	SkAddrXmacMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- *	The multicast bit is only checked if there are no free exact match
- *	entries.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- *	SK_MC_RLMT_OVERFLOW
- */
-static int	SkAddrXmacMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int		Flags)		/* permanent/non-permanent */
-{
-	int	i;
-	SK_U8	Inexact;
-#ifndef SK_ADDR_CHEAT
-	SK_U32 HashBit;
-#endif	/* !defined(SK_ADDR_CHEAT) */
-
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-#ifdef xDEBUG
-		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
-			SK_ADDR_FIRST_MATCH_RLMT) {
-			Next0[PortNumber] |= 1;
-			return (SK_MC_RLMT_OVERFLOW);
-		}
-#endif	/* DEBUG */
-		
-		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
-			SK_ADDR_LAST_MATCH_RLMT) {
-			return (SK_MC_RLMT_OVERFLOW);
-		}
-
-		/* Set a RLMT multicast address. */
-
-		pAC->Addr.Port[PortNumber].Exact[
-			pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
-
-		return (SK_MC_FILTERING_EXACT);
-	}
-
-#ifdef xDEBUG
-	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
-		SK_ADDR_FIRST_MATCH_DRV) {
-			Next0[PortNumber] |= 2;
-		return (SK_MC_RLMT_OVERFLOW);
-	}
-#endif	/* DEBUG */
-	
-	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-
-		/* Set exact match entry. */
-		pAC->Addr.Port[PortNumber].Exact[
-			pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
-
-		/* Clear InexactFilter */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-		}
-	}
-	else {
-		if (!(pMc->a[0] & SK_MC_BIT)) {
-			/* Hashing only possible with multicast addresses */
-			return (SK_MC_ILLEGAL_ADDRESS);
-		}
-#ifndef SK_ADDR_CHEAT
-		/* Compute hash value of address. */
-		HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
-
-		/* Add bit to InexactFilter. */
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-#else	/* SK_ADDR_CHEAT */
-		/* Set all bits in InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
-		}
-#endif	/* SK_ADDR_CHEAT */
-	}
-
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-	}
-
-	if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-
-}	/* SkAddrXmacMcAdd */
-
-
-/******************************************************************************
- *
- *	SkAddrGmacMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- */
-static int	SkAddrGmacMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int		Flags)		/* permanent/non-permanent */
-{
-	int	i;
-#ifndef SK_ADDR_CHEAT
-	SK_U32 HashBit;
-#endif	/* !defined(SK_ADDR_CHEAT) */
-		
-	if (!(pMc->a[0] & SK_MC_BIT)) {
-		/* Hashing only possible with multicast addresses */
-		return (SK_MC_ILLEGAL_ADDRESS);
-	}
-	
-#ifndef SK_ADDR_CHEAT
-	
-	/* Compute hash value of address. */
-	HashBit = SkGmacMcHash(&pMc->a[0]);
-	
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-		
-		/* Add bit to InexactRlmtFilter. */
-		pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-		
-		/* Copy bit to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
-		}
-#ifdef DEBUG
-		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
-#endif	/* DEBUG */
-	}
-	else {	/* not permanent => DRV */
-		
-		/* Add bit to InexactDrvFilter. */
-		pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-		
-		/* Copy bit to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
-		}
-#ifdef DEBUG
-		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
-#endif	/* DEBUG */
-	}
-	
-#else	/* SK_ADDR_CHEAT */
-	
-	/* Set all bits in InexactFilter. */
-	for (i = 0; i < 8; i++) {
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
-	}
-#endif	/* SK_ADDR_CHEAT */
-		
-	return (SK_MC_FILTERING_INEXACT);
-	
-}	/* SkAddrGmacMcAdd */
-
-#endif /* !SK_SLIM */
-
-/******************************************************************************
- *
- *	SkAddrMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- *	It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
- *	to the adapter in use. The real work is done there.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-	int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
-	}
-#endif /* GENESIS */
-#ifdef YUKON
-	if (!pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
-	}
-#endif /* YUKON */
-	return (ReturnCode);
-
-}	/* SkAddrMcUpdate */
-
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- *	SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-	SK_U32		i;
-	SK_U8		Inexact;
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
-	
-	pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-
-	/* Start with 0 to also program the logical MAC address. */
-	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
-		/* Set exact match address i on XMAC */
-		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
-		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
-	}
-
-	/* Clear other permanent exact match addresses on XMAC */
-	if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
-		
-		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
-			SK_ADDR_LAST_MATCH_RLMT);
-	}
-
-	for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
-		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
-		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
-	}
-
-	/* Clear other non-permanent exact match addresses on XMAC */
-	if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-		
-		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
-			SK_ADDR_LAST_MATCH_DRV);
-	}
-
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAPort->InexactFilter.Bytes[i];
-	}
-
-	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
-		
-		/* Set all bits in 64-bit hash register. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if (Inexact != 0) {
-		
-		/* Set 64-bit hash register to InexactFilter. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else {
-		/* Disable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-
-	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
-		(void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	}
-
-	/* Set port's current physical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-	
-	XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
-
-#ifdef xDEBUG
-	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
-		SK_U8		InAddr8[6];
-		SK_U16		*InAddr;
-
-		/* Get exact match address i from port PortNumber. */
-		InAddr = (SK_U16 *) &InAddr8[0];
-		
-		XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
-		
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
-			 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
-				i,
-				PortNumber,
-				InAddr8[0],
-				InAddr8[1],
-				InAddr8[2],
-				InAddr8[3],
-				InAddr8[4],
-				InAddr8[5],
-				pAPort->Exact[i].a[0],
-				pAPort->Exact[i].a[1],
-				pAPort->Exact[i].a[2],
-				pAPort->Exact[i].a[3],
-				pAPort->Exact[i].a[4],
-				pAPort->Exact[i].a[5]))
-	}
-#endif /* DEBUG */
-
-	/* Determine return value. */
-	if (Inexact == 0 && pAPort->PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-	
-}	/* SkAddrXmacMcUpdate */
-
-#endif  /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- *	SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-#ifndef SK_SLIM
-	SK_U32		i;
-	SK_U8		Inexact;
-#endif	/* not SK_SLIM */
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
-	
-	pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-	
-#ifndef SK_SLIM
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAPort->InexactFilter.Bytes[i];
-	}
-	
-	/* Set 64-bit hash register to InexactFilter. */
-	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
-		&pAPort->InexactFilter.Bytes[0]);
-	
-	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {				
-		
-		/* Set all bits in 64-bit hash register. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else {	
-		/* Enable Hashing. */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	
-	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
-		(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	}
-#else /* SK_SLIM */
-
-	/* Set all bits in 64-bit hash register. */
-	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
-	/* Enable Hashing */
-	SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	
-	(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	
-#endif /* SK_SLIM */
-	
-	/* Set port's current physical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
-	
-	/* Set port's current logical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
-	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
-	
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-			pAPort->Exact[0].a[0],
-			pAPort->Exact[0].a[1],
-			pAPort->Exact[0].a[2],
-			pAPort->Exact[0].a[3],
-			pAPort->Exact[0].a[4],
-			pAPort->Exact[0].a[5]))
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-			pAPort->CurrentMacAddress.a[0],
-			pAPort->CurrentMacAddress.a[1],
-			pAPort->CurrentMacAddress.a[2],
-			pAPort->CurrentMacAddress.a[3],
-			pAPort->CurrentMacAddress.a[4],
-			pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-	
-#ifndef SK_SLIM
-	/* Determine return value. */
-	if (Inexact == 0 && pAPort->PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-#else /* SK_SLIM */
-	return (SK_MC_FILTERING_INEXACT);
-#endif /* SK_SLIM */
-	
-}	/* SkAddrGmacMcUpdate */
-
-#endif /* YUKON */
-
-#ifndef SK_NO_MAO
-
-/******************************************************************************
- *
- *	SkAddrOverride - override a port's MAC address
- *
- * Description:
- *	This routine overrides the MAC address of one port.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS if successful.
- *	SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
- *	SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
- *	SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
- */
-int	SkAddrOverride(
-SK_AC		*pAC,				/* adapter context */
-SK_IOC		IoC,				/* I/O context */
-SK_U32		PortNumber,			/* Port Number */
-SK_MAC_ADDR	SK_FAR *pNewAddr,	/* new MAC address */
-int			Flags)				/* logical/physical MAC address */
-{
-#ifndef SK_NO_RLMT
-	SK_EVPARA	Para;
-#endif /* !SK_NO_RLMT */
-	SK_U32		NetNumber;
-	SK_U32		i;
-	SK_U16		SK_FAR *OutAddr;
-
-#ifndef SK_NO_RLMT
-	NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
-#else
-	NetNumber = 0;
-#endif /* SK_NO_RLMT */
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-	if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
-		return (SK_ADDR_MULTICAST_ADDRESS);
-	}
-
-	if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
-		return (SK_ADDR_TOO_EARLY);
-	}
-
-	if (Flags & SK_ADDR_SET_LOGICAL) {	/* Activate logical MAC address. */
-		/* Parameter *pNewAddr is ignored. */
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-		}
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		pAC->Addr.Port[PortNumber].Exact[0] =
-			pAC->Addr.Net[NetNumber].CurrentMacAddress;
-
-		/* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-	else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
-		/* Deactivate logical MAC address. */
-		/* Parameter *pNewAddr is ignored. */
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-		}
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
-			pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
-		}
-
-		/* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-	else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) {	/* Physical MAC address. */
-		if (SK_ADDR_EQUAL(pNewAddr->a,
-			pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
-			return (SK_ADDR_DUPLICATE_ADDRESS);
-		}
-
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-
-			if (SK_ADDR_EQUAL(pNewAddr->a,
-				pAC->Addr.Port[i].CurrentMacAddress.a)) {
-				if (i == PortNumber) {
-					return (SK_ADDR_SUCCESS);
-				}
-				else {
-					return (SK_ADDR_DUPLICATE_ADDRESS);
-				}
-			}
-		}
-
-		pAC->Addr.Port[PortNumber].PreviousMacAddress =
-			pAC->Addr.Port[PortNumber].CurrentMacAddress;
-		pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-
-		/* Change port's physical MAC address. */
-		OutAddr = (SK_U16 SK_FAR *) pNewAddr;
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
-		}
-#endif /* GENESIS */
-#ifdef YUKON
-		if (!pAC->GIni.GIGenesis) {
-			GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
-		}
-#endif /* YUKON */
-
-#ifndef SK_NO_RLMT
-		/* Report address change to RLMT. */
-		Para.Para32[0] = PortNumber;
-		Para.Para32[0] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
-	}
-	else {	/* Logical MAC address. */
-		if (SK_ADDR_EQUAL(pNewAddr->a,
-			pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
-			return (SK_ADDR_SUCCESS);
-		}
-		
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-
-			if (SK_ADDR_EQUAL(pNewAddr->a,
-				pAC->Addr.Port[i].CurrentMacAddress.a)) {
-				return (SK_ADDR_DUPLICATE_ADDRESS);
-			}
-		}
-		
-		/*
-		 * In case that the physical and the logical MAC addresses are equal
-		 * we must also change the physical MAC address here.
-		 * In this case we have an adapter which initially was programmed with
-		 * two identical MAC addresses.
-		 */
-		if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
-				pAC->Addr.Port[PortNumber].Exact[0].a)) {
-			
-			pAC->Addr.Port[PortNumber].PreviousMacAddress =
-				pAC->Addr.Port[PortNumber].CurrentMacAddress;
-			pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-			
-#ifndef SK_NO_RLMT
-			/* Report address change to RLMT. */
-			Para.Para32[0] = PortNumber;
-			Para.Para32[0] = -1;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
-		}
-		
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
-		pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
-#ifdef DEBUG
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
-		
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-
-        /* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrOverride */
-
-
-#endif /* SK_NO_MAO */
-
-/******************************************************************************
- *
- *	SkAddrPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- *	It calls either SkAddrXmacPromiscuousChange or
- *	SkAddrGmacPromiscuousChange, according to the adapter in use.
- *	The real work is done there.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode =
-			SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
-	}
-#endif /* GENESIS */
-#ifdef YUKON
-	if (!pAC->GIni.GIGenesis) {
-		ReturnCode =
-			SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
-	}
-#endif /* YUKON */
-
-	return (ReturnCode);
-
-}	/* SkAddrPromiscuousChange */
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- *	SkAddrXmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	int			i;
-	SK_BOOL		InexactModeBit;
-	SK_U8		Inexact;
-	SK_U8		HwInexact;
-	SK_FILTER64	HwInexactFilter;
-	SK_U16		LoMode;		/* Lower 16 bits of XMAC Mode Register. */
-	int			CurPromMode = SK_PROM_MODE_NONE;
-
-	/* Read CurPromMode from Hardware. */
-	XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-
-	if ((LoMode & XM_MD_ENA_PROM) != 0) {
-		/* Promiscuous mode! */
-		CurPromMode |= SK_PROM_MODE_LLC;
-	}
-	
-	for (Inexact = 0xFF, i = 0; i < 8; i++) {
-		Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-	}
-	if (Inexact == 0xFF) {
-		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
-	}
-	else {
-		/* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
-		XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-		
-		InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
-
-		/* Read 64-bit hash register from XMAC */
-		XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
-
-		for (HwInexact = 0xFF, i = 0; i < 8; i++) {
-			HwInexact &= HwInexactFilter.Bytes[i];
-		}
-
-		if (InexactModeBit && (HwInexact == 0xFF)) {
-			CurPromMode |= SK_PROM_MODE_ALL_MC;
-		}
-	}
-
-	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
-	if (NewPromMode == CurPromMode) {
-		return (SK_ADDR_SUCCESS);
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC. */
-		
-		/* Set all bits in 64-bit hash register. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm MC. */
-		for (Inexact = 0, i = 0; i < 8; i++) {
-			Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-		}
-		if (Inexact == 0) {
-			/* Disable Hashing */
-			SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
-		}
-		else {
-			/* Set 64-bit hash register to InexactFilter. */
-			XM_OUTHASH(IoC, PortNumber, XM_HSM,
-				&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
-			/* Enable Hashing */
-			SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-		}
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_LLC) &&
-		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
-		/* Set the MAC in Promiscuous Mode */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
-		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC. */
-		/* Clear Promiscuous Mode */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-	
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrXmacPromiscuousChange */
-
-#endif /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- *	SkAddrGmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	SK_U16		ReceiveControl;	/* GMAC Receive Control Register */
-	int		CurPromMode = SK_PROM_MODE_NONE;
-
-	/* Read CurPromMode from Hardware. */
-	GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
-
-	if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
-		/* Promiscuous mode! */
-		CurPromMode |= SK_PROM_MODE_LLC;
-	}
-
-	if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
-		/* All Multicast mode! */
-		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
-	}
-
-	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
-	if (NewPromMode == CurPromMode) {
-		return (SK_ADDR_SUCCESS);
-	}
-	
-	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC */
-		
-		/* Set all bits in 64-bit hash register. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	
-	if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm. MC */
-
-		/* Set 64-bit hash register to InexactFilter. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
-			&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
-		/* Enable Hashing. */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_LLC) &&
-		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
-		
-		/* Set the MAC to Promiscuous Mode. */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
-		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC */
-		
-		/* Clear Promiscuous Mode. */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrGmacPromiscuousChange */
-
-#endif /* YUKON */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrSwap - swap address info
- *
- * Description:
- *	This routine swaps address info of two ports.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrSwap(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	FromPortNumber,		/* Port1 Index */
-SK_U32	ToPortNumber)		/* Port2 Index */
-{
-	int			i;
-	SK_U8		Byte;
-	SK_MAC_ADDR	MacAddr;
-	SK_U32		DWord;
-
-	if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	/*
-	 * Swap:
-	 * - Exact Match Entries (GEnesis and Yukon)
-	 *   Yukon uses first entry for the logical MAC
-	 *   address (stored in the second GMAC register).
-	 * - FirstExactMatchRlmt (GEnesis only)
-	 * - NextExactMatchRlmt (GEnesis only)
-	 * - FirstExactMatchDrv (GEnesis only)
-	 * - NextExactMatchDrv (GEnesis only)
-	 * - 64-bit filter (InexactFilter)
-	 * - Promiscuous Mode
-	 * of ports.
-	 */
-
-	for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
-		MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
-		pAC->Addr.Port[FromPortNumber].Exact[i] =
-			pAC->Addr.Port[ToPortNumber].Exact[i];
-		pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
-	}
-
-	for (i = 0; i < 8; i++) {
-		Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
-		pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
-			pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
-		pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
-	}
-	
-	i = pAC->Addr.Port[FromPortNumber].PromMode;
-	pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
-	pAC->Addr.Port[ToPortNumber].PromMode = i;
-	
-	if (pAC->GIni.GIGenesis) {
-		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
-		pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
-			pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
-		pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
-		pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
-			pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
-		pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
-		pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
-			pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
-		pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
-		pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
-			pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
-		pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
-	}
-	
-	/* CAUTION: Solution works if only ports of one adapter are in use. */
-	for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
-		Net->NetNumber].NumPorts; i++) {
-		if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
-			Port[i]->PortNumber == ToPortNumber) {
-			pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
-				ActivePort = i;
-			/* 20001207 RA: Was "ToPortNumber;". */
-		}
-	}
-	
-	(void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
-	(void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrSwap */
-
-#endif /* !SK_SLIM */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
deleted file mode 100644
index 37ce03f..0000000
--- a/drivers/net/sk98lin/skdim.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdim.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.5 $
- * Date:	$Date: 2003/11/28 12:55:40 $
- * Purpose:	All functions to maintain interrupt moderation
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage the dynamic interrupt moderation on both   
- * GEnesis and Yukon adapters.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef	lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
-#endif
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-#error C++ is not yet supported.
-extern "C" {
-#endif
-
-/*******************************************************************************
-**
-** Includes
-**
-*******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#include "h/skdrv1st.h"
-#endif
-
-#ifndef __INC_SKDRV2ND_H
-#include "h/skdrv2nd.h"
-#endif
-
-#include	<linux/kernel_stat.h>
-
-/*******************************************************************************
-**
-** Defines
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Typedefs
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local function prototypes 
-**
-*******************************************************************************/
-
-static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
-static SK_U64       GetIsrCalls(SK_AC *pAC);
-static SK_BOOL      IsIntModEnabled(SK_AC *pAC);
-static void         SetCurrIntCtr(SK_AC *pAC);
-static void         EnableIntMod(SK_AC *pAC); 
-static void         DisableIntMod(SK_AC *pAC);
-static void         ResizeDimTimerDuration(SK_AC *pAC);
-static void         DisplaySelectedModerationType(SK_AC *pAC);
-static void         DisplaySelectedModerationMask(SK_AC *pAC);
-static void         DisplayDescrRatio(SK_AC *pAC);
-
-/*******************************************************************************
-**
-** Global variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Global functions 
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function     : SkDimModerate
-** Description  : Called in every ISR to check if moderation is to be applied
-**                or not for the current number of interrupts
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimModerate(SK_AC *pAC) {
-    unsigned int CurrSysLoad    = 0;  /* expressed in percent */
-    unsigned int LoadIncrease   = 0;  /* expressed in percent */
-    SK_U64       ThresholdInts  = 0;
-    SK_U64       IsrCallsPerSec = 0;
-
-#define M_DIMINFO pAC->DynIrqModInfo
-
-    if (!IsIntModEnabled(pAC)) {
-        if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-            CurrSysLoad = GetCurrentSystemLoad(pAC);
-            if (CurrSysLoad > 75) {
-                    /* 
-                    ** More than 75% total system load! Enable the moderation 
-                    ** to shield the system against too many interrupts.
-                    */
-                    EnableIntMod(pAC);
-            } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
-                LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
-                if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
-                                         C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
-                    if (CurrSysLoad > 10) {
-                        /* 
-                        ** More than 50% increase with respect to the 
-                        ** previous load of the system. Most likely this 
-                        ** is due to our ISR-proc...
-                        */
-                        EnableIntMod(pAC);
-                    }
-                }
-            } else {
-                /*
-                ** Neither too much system load at all nor too much increase
-                ** with respect to the previous system load. Hence, we can leave
-                ** the ISR-handling like it is without enabling moderation.
-                */
-            }
-            M_DIMINFO.PrevSysLoad = CurrSysLoad;
-        }   
-    } else {
-        if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-            ThresholdInts  = ((M_DIMINFO.MaxModIntsPerSec *
-                                   C_INT_MOD_DISABLE_PERCENTAGE) / 100);
-            IsrCallsPerSec = GetIsrCalls(pAC);
-            if (IsrCallsPerSec <= ThresholdInts) {
-                /* 
-                ** The number of interrupts within the last second is 
-                ** lower than the disable_percentage of the desried 
-                ** maxrate. Therefore we can disable the moderation.
-                */
-                DisableIntMod(pAC);
-                M_DIMINFO.MaxModIntsPerSec = 
-                   (M_DIMINFO.MaxModIntsPerSecUpperLimit +
-                    M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
-            } else {
-                /*
-                ** The number of interrupts per sec is the same as expected.
-                ** Evalulate the descriptor-ratio. If it has changed, a resize 
-                ** in the moderation timer might be useful
-                */
-                if (M_DIMINFO.AutoSizing) {
-                    ResizeDimTimerDuration(pAC);
-                }
-            }
-        }
-    }
-
-    /*
-    ** Some information to the log...
-    */
-    if (M_DIMINFO.DisplayStats) {
-        DisplaySelectedModerationType(pAC);
-        DisplaySelectedModerationMask(pAC);
-        DisplayDescrRatio(pAC);
-    }
-
-    M_DIMINFO.NbrProcessedDescr = 0; 
-    SetCurrIntCtr(pAC);
-}
-
-/*******************************************************************************
-** Function     : SkDimStartModerationTimer
-** Description  : Starts the audit-timer for the dynamic interrupt moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimStartModerationTimer(SK_AC *pAC) {
-    SK_EVPARA    EventParam;   /* Event struct for timer event */
- 
-    SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
-    EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
-    SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
-                 SK_DRV_MODERATION_TIMER_LENGTH,
-                 SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*******************************************************************************
-** Function     : SkDimEnableModerationIfNeeded
-** Description  : Either enables or disables moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : This function is called when a particular adapter is opened
-**                There is no Disable function, because when all interrupts 
-**                might be disable, the moderation timer has no meaning at all
-******************************************************************************/
-
-void
-SkDimEnableModerationIfNeeded(SK_AC *pAC) {
-
-    if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
-        EnableIntMod(pAC);   /* notification print in this function */
-    } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-        SkDimStartModerationTimer(pAC);
-        if (M_DIMINFO.DisplayStats) {
-            printk("Dynamic moderation has been enabled\n");
-        }
-    } else {
-        if (M_DIMINFO.DisplayStats) {
-            printk("No moderation has been enabled\n");
-        }
-    }
-}
-
-/*******************************************************************************
-** Function     : SkDimDisplayModerationSettings
-** Description  : Displays the current settings regarding interrupt moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimDisplayModerationSettings(SK_AC *pAC) {
-    DisplaySelectedModerationType(pAC);
-    DisplaySelectedModerationMask(pAC);
-}
-
-/*******************************************************************************
-**
-** Local functions 
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function     : GetCurrentSystemLoad
-** Description  : Retrieves the current system load of the system. This load
-**                is evaluated for all processors within the system.
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : unsigned int: load expressed in percentage
-** Notes        : The possible range being returned is from 0 up to 100.
-**                Whereas 0 means 'no load at all' and 100 'system fully loaded'
-**                It is impossible to determine what actually causes the system
-**                to be in 100%, but maybe that is due to too much interrupts.
-*******************************************************************************/
-
-static unsigned int
-GetCurrentSystemLoad(SK_AC *pAC) {
-	unsigned long jif         = jiffies;
-	unsigned int  UserTime    = 0;
-	unsigned int  SystemTime  = 0;
-	unsigned int  NiceTime    = 0;
-	unsigned int  IdleTime    = 0;
-	unsigned int  TotalTime   = 0;
-	unsigned int  UsedTime    = 0;
-	unsigned int  SystemLoad  = 0;
-
-	/* unsigned int  NbrCpu      = 0; */
-
-	/*
-	** The following lines have been commented out, because
-	** from kernel 2.5.44 onwards, the kernel-owned structure
-	**
-	**      struct kernel_stat kstat
-	**
-	** is not marked as an exported symbol in the file
-	**
-	**      kernel/ksyms.c 
-	**
-	** As a consequence, using this driver as KLM is not possible
-	** and any access of the structure kernel_stat via the 
-	** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
-	**
-	** The kstat-information might be added again in future 
-	** versions of the 2.5.xx kernel, but for the time being, 
-	** number of interrupts will serve as indication how much 
-	** load we currently have... 
-	**
-	** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
-	**	UserTime   = UserTime   + kstat_cpu(NbrCpu).cpustat.user;
-	**	NiceTime   = NiceTime   + kstat_cpu(NbrCpu).cpustat.nice;
-	**	SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
-	** }
-	*/
-	SK_U64 ThresholdInts  = 0;
-	SK_U64 IsrCallsPerSec = 0;
-
-	ThresholdInts  = ((M_DIMINFO.MaxModIntsPerSec *
-			   C_INT_MOD_ENABLE_PERCENTAGE) + 100);
-	IsrCallsPerSec = GetIsrCalls(pAC);
-	if (IsrCallsPerSec >= ThresholdInts) {
-	    /*
-	    ** We do not know how much the real CPU-load is!
-	    ** Return 80% as a default in order to activate DIM
-	    */
-	    SystemLoad = 80;
-	    return (SystemLoad);  
-	} 
-
-	UsedTime  = UserTime + NiceTime + SystemTime;
-
-	IdleTime  = jif * num_online_cpus() - UsedTime;
-	TotalTime = UsedTime + IdleTime;
-
-	SystemLoad = ( 100 * (UsedTime  - M_DIMINFO.PrevUsedTime) ) /
-						(TotalTime - M_DIMINFO.PrevTotalTime);
-
-	if (M_DIMINFO.DisplayStats) {
-		printk("Current system load is: %u\n", SystemLoad);
-	}
-
-	M_DIMINFO.PrevTotalTime = TotalTime;
-	M_DIMINFO.PrevUsedTime  = UsedTime;
-
-	return (SystemLoad);
-}
-
-/*******************************************************************************
-** Function     : GetIsrCalls
-** Description  : Depending on the selected moderation mask, this function will
-**                return the number of interrupts handled in the previous time-
-**                frame. This evaluated number is based on the current number 
-**                of interrupts stored in PNMI-context and the previous stored 
-**                interrupts.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : int:   the number of interrupts being executed in the last
-**                       timeframe
-** Notes        : It makes only sense to call this function, when dynamic 
-**                interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetIsrCalls(SK_AC *pAC) {
-    SK_U64   RxPort0IntDiff = 0;
-    SK_U64   RxPort1IntDiff = 0;
-    SK_U64   TxPort0IntDiff = 0;
-    SK_U64   TxPort1IntDiff = 0;
-
-    if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
-        if (pAC->GIni.GIMacsFound == 2) {
-            TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1TxIntrCts;
-        }
-        TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0TxIntrCts;
-    } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
-        if (pAC->GIni.GIMacsFound == 2) {
-            RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-        }
-        RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-    } else {
-        if (pAC->GIni.GIMacsFound == 2) {
-            RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-            TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1TxIntrCts;
-        } 
-        RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-        TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0TxIntrCts;
-    }
-
-    return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function     : GetRxCalls
-** Description  : This function will return the number of times a receive inter-
-**                rupt was processed. This is needed to evaluate any resizing 
-**                factor.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : SK_U64: the number of RX-ints being processed
-** Notes        : It makes only sense to call this function, when dynamic 
-**                interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetRxCalls(SK_AC *pAC) {
-    SK_U64   RxPort0IntDiff = 0;
-    SK_U64   RxPort1IntDiff = 0;
-
-    if (pAC->GIni.GIMacsFound == 2) {
-        RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-    }
-    RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                     pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-
-    return (RxPort0IntDiff + RxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function     : SetCurrIntCtr
-** Description  : Will store the current number orf occured interrupts in the 
-**                adapter context. This is needed to evaluated the number of 
-**                interrupts within a current timeframe.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-static void
-SetCurrIntCtr(SK_AC *pAC) {
-    if (pAC->GIni.GIMacsFound == 2) {
-        pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
-        pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
-    } 
-    pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
-    pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
-}
-
-/*******************************************************************************
-** Function     : IsIntModEnabled()
-** Description  : Retrieves the current value of the interrupts moderation
-**                command register. Its content determines whether any 
-**                moderation is running or not.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : SK_TRUE  : if mod timer running
-**                SK_FALSE : if no moderation is being performed
-** Notes        : -
-*******************************************************************************/
-
-static SK_BOOL
-IsIntModEnabled(SK_AC *pAC) {
-    unsigned long CtrCmd;
-
-    SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
-    if ((CtrCmd & TIM_START) == TIM_START) {
-       return SK_TRUE;
-    } else {
-       return SK_FALSE;
-    }
-}
-
-/*******************************************************************************
-** Function     : EnableIntMod()
-** Description  : Enables the interrupt moderation using the values stored in
-**                in the pAC->DynIntMod data structure
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : -
-** Notes        : -
-*******************************************************************************/
-
-static void
-EnableIntMod(SK_AC *pAC) {
-    unsigned long ModBase;
-
-    if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-       ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    } else {
-       ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    }
-
-    SK_OUT32(pAC->IoBase, B2_IRQM_INI,  ModBase);
-    SK_OUT32(pAC->IoBase, B2_IRQM_MSK,  pAC->DynIrqModInfo.MaskIrqModeration);
-    SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
-    if (M_DIMINFO.DisplayStats) {
-        printk("Enabled interrupt moderation (%i ints/sec)\n",
-               M_DIMINFO.MaxModIntsPerSec);
-    }
-}
-
-/*******************************************************************************
-** Function     : DisableIntMod()
-** Description  : Disables the interrupt moderation independent of what inter-
-**                rupts are running or not
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : -
-** Notes        : -
-*******************************************************************************/
-
-static void 
-DisableIntMod(SK_AC *pAC) {
-
-    SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
-    if (M_DIMINFO.DisplayStats) {
-        printk("Disabled interrupt moderation\n");
-    }
-} 
-
-/*******************************************************************************
-** Function     : ResizeDimTimerDuration();
-** Description  : Checks the current used descriptor ratio and resizes the 
-**                duration timer (longer/smaller) if possible. 
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : -
-** Notes        : There are both maximum and minimum timer duration value. 
-**                This function assumes that interrupt moderation is already
-**                enabled!
-*******************************************************************************/
-
-static void 
-ResizeDimTimerDuration(SK_AC *pAC) {
-    SK_BOOL IncreaseTimerDuration;
-    int     TotalMaxNbrDescr;
-    int     UsedDescrRatio;
-    int     RatioDiffAbs;
-    int     RatioDiffRel;
-    int     NewMaxModIntsPerSec;
-    int     ModAdjValue;
-    long    ModBase;
-
-    /*
-    ** Check first if we are allowed to perform any modification
-    */
-    if (IsIntModEnabled(pAC)) { 
-        if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
-            return; 
-        } else {
-            if (M_DIMINFO.ModJustEnabled) {
-                M_DIMINFO.ModJustEnabled = SK_FALSE;
-                return;
-            }
-        }
-    }
-
-    /*
-    ** If we got until here, we have to evaluate the amount of the
-    ** descriptor ratio change...
-    */
-    TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
-    UsedDescrRatio   = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
-
-    if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
-        RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_FALSE;  /* in other words: DECREASE */
-    } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
-        RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_TRUE;   /* in other words: INCREASE */
-    } else {
-        RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_TRUE;   /* in other words: INCREASE */
-    }
-
-    /*
-    ** Now we can determine the change in percent
-    */
-    if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    }
-
-    if (IncreaseTimerDuration) {
-       NewMaxModIntsPerSec =  M_DIMINFO.MaxModIntsPerSec +
-                             (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
-    } else {
-       NewMaxModIntsPerSec =  M_DIMINFO.MaxModIntsPerSec -
-                             (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
-    }
-
-    /* 
-    ** Check if we exceed boundaries...
-    */
-    if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
-         (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
-        if (M_DIMINFO.DisplayStats) {
-            printk("Cannot change ModTim from %i to %i ints/sec\n",
-                   M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
-        }
-        return;
-    } else {
-        if (M_DIMINFO.DisplayStats) {
-            printk("Resized ModTim from %i to %i ints/sec\n",
-                   M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
-        }
-    }
-
-    M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
-
-    if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-        ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    } else {
-        ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    }
-
-    /* 
-    ** We do not need to touch any other registers
-    */
-    SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
-} 
-
-/*******************************************************************************
-** Function     : DisplaySelectedModerationType()
-** Description  : Displays what type of moderation we have
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationType(SK_AC *pAC) {
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
-             printk("Static int moderation runs with %i INTS/sec\n",
-                    pAC->DynIrqModInfo.MaxModIntsPerSec);
-        } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-             if (IsIntModEnabled(pAC)) {
-                printk("Dynamic int moderation runs with %i INTS/sec\n",
-                       pAC->DynIrqModInfo.MaxModIntsPerSec);
-             } else {
-                printk("Dynamic int moderation currently not applied\n");
-             }
-        } else {
-             printk("No interrupt moderation selected!\n");
-        }
-    }
-}
-
-/*******************************************************************************
-** Function     : DisplaySelectedModerationMask()
-** Description  : Displays what interrupts are moderated
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationMask(SK_AC *pAC) {
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
-            switch (pAC->DynIrqModInfo.MaskIrqModeration) {
-                case IRQ_MASK_TX_ONLY: 
-                   printk("Only Tx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_RX_ONLY: 
-                   printk("Only Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_ONLY: 
-                   printk("Only special-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_TX_RX: 
-                   printk("Tx- and Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_RX: 
-                   printk("Special- and Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_TX: 
-                   printk("Special- and Tx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_RX_TX_SP:
-                   printk("All Rx-, Tx and special-interrupts are moderated\n");
-                   break;
-                default:
-                   printk("Don't know what is moderated\n");
-                   break;
-            }
-        } else {
-            printk("No specific interrupts masked for moderation\n");
-        }
-    } 
-}
-
-/*******************************************************************************
-** Function     : DisplayDescrRatio
-** Description  : Like the name states...
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplayDescrRatio(SK_AC *pAC) {
-    int TotalMaxNbrDescr = 0;
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
-        printk("Ratio descriptors: %i/%i\n",
-               M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
-    }
-}
-
-/*******************************************************************************
-**
-** End of file
-**
-*******************************************************************************/
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
deleted file mode 100644
index 3646069..0000000
--- a/drivers/net/sk98lin/skethtool.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/******************************************************************************
- *
- * Name:        skethtool.c
- * Project:     GEnesis, PCI Gigabit Ethernet Adapter
- * Version:     $Revision: 1.7 $
- * Date:        $Date: 2004/09/29 13:32:07 $
- * Purpose:     All functions regarding ethtool handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2004 Marvell.
- *
- *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet 
- *      Server Adapters.
- *
- *	Author: Ralph Roesler (rroesler@syskonnect.de)
- *	        Mirko Lindner (mlindner@syskonnect.de)
- *
- *	Address all question to: linux@syskonnect.de
- *
- *	The technical manual for the adapters is available from SysKonnect's
- *	web pages: www.syskonnect.com
- *	
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- *****************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-#include "h/skversion.h"
-
-#include <linux/ethtool.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-
-/******************************************************************************
- *
- * Defines
- *
- *****************************************************************************/
-
-#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half  | SUPPORTED_10baseT_Full  | \
-                         SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
-                         SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
-                         SUPPORTED_TP)
-
-#define ADV_COPPER_ALL  (ADVERTISED_10baseT_Half  | ADVERTISED_10baseT_Full  | \
-                         ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-                         ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
-                         ADVERTISED_TP)
-
-#define SUPP_FIBRE_ALL  (SUPPORTED_1000baseT_Full | \
-                         SUPPORTED_FIBRE          | \
-                         SUPPORTED_Autoneg)
-
-#define ADV_FIBRE_ALL   (ADVERTISED_1000baseT_Full | \
-                         ADVERTISED_FIBRE          | \
-                         ADVERTISED_Autoneg)
-
-
-/******************************************************************************
- *
- * Local Functions
- *
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * 	getSettings - retrieves the current settings of the selected adapter
- *
- * Description:
- *	The current configuration of the selected adapter is returned.
- *	This configuration involves a)speed, b)duplex and c)autoneg plus
- *	a number of other variables.
- *
- * Returns:    always 0
- *
- */
-static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	const DEV_NET *pNet = netdev_priv(dev);
-	int port = pNet->PortNr;
-	const SK_AC *pAC = pNet->pAC;
-	const SK_GEPORT *pPort = &pAC->GIni.GP[port];
-
-	static int DuplexAutoNegConfMap[9][3]= {
-		{ -1                     , -1         , -1              },
-		{ 0                      , -1         , -1              },
-		{ SK_LMODE_HALF          , DUPLEX_HALF, AUTONEG_DISABLE },
-		{ SK_LMODE_FULL          , DUPLEX_FULL, AUTONEG_DISABLE },
-		{ SK_LMODE_AUTOHALF      , DUPLEX_HALF, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOFULL      , DUPLEX_FULL, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOBOTH      , DUPLEX_FULL, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOSENSE     , -1         , -1              },
-		{ SK_LMODE_INDETERMINATED, -1         , -1              }
-	};
-	static int SpeedConfMap[6][2] = {
-		{ 0                       , -1         },
-		{ SK_LSPEED_AUTO          , -1         },
-		{ SK_LSPEED_10MBPS        , SPEED_10   },
-		{ SK_LSPEED_100MBPS       , SPEED_100  },
-		{ SK_LSPEED_1000MBPS      , SPEED_1000 },
-		{ SK_LSPEED_INDETERMINATED, -1         }
-	};
-	static int AdvSpeedMap[6][2] = {
-		{ 0                       , -1         },
-		{ SK_LSPEED_AUTO          , -1         },
-		{ SK_LSPEED_10MBPS        , ADVERTISED_10baseT_Half   | ADVERTISED_10baseT_Full },
-		{ SK_LSPEED_100MBPS       , ADVERTISED_100baseT_Half  | ADVERTISED_100baseT_Full },
-		{ SK_LSPEED_1000MBPS      , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
-		{ SK_LSPEED_INDETERMINATED, -1         }
-	};
-
-	ecmd->phy_address = port;
-	ecmd->speed       = SpeedConfMap[pPort->PLinkSpeedUsed][1];
-	ecmd->duplex      = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
-	ecmd->autoneg     = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	if (pAC->GIni.GICopperType) {
-		ecmd->port        = PORT_TP;
-		ecmd->supported   = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
-		if (pAC->GIni.GIGenesis) {
-			ecmd->supported &= ~(SUPPORTED_10baseT_Half);
-			ecmd->supported &= ~(SUPPORTED_10baseT_Full);
-			ecmd->supported &= ~(SUPPORTED_100baseT_Half);
-			ecmd->supported &= ~(SUPPORTED_100baseT_Full);
-		} else {
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
-			} 
-#ifdef CHIP_ID_YUKON_FE
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
-			}
-#endif
-		}
-		if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
-			ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-				ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
-			} 
-		} else {
-			ecmd->advertising = ecmd->supported;
-		}
-
-		if (ecmd->autoneg == AUTONEG_ENABLE) 
-			ecmd->advertising |= ADVERTISED_Autoneg;
-	} else {
-		ecmd->port        = PORT_FIBRE;
-		ecmd->supported   = SUPP_FIBRE_ALL;
-		ecmd->advertising = ADV_FIBRE_ALL;
-	}
-	return 0;
-}
-
-/*
- * MIB infrastructure uses instance value starting at 1
- * based on board and port.
- */
-static inline u32 pnmiInstance(const DEV_NET *pNet)
-{
-	return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr;
-}
-
-/*****************************************************************************
- *
- *	setSettings - configures the settings of a selected adapter
- *
- * Description:
- *	Possible settings that may be altered are a)speed, b)duplex or 
- *	c)autonegotiation.
- *
- * Returns:
- *	0:	everything fine, no error
- *	<0:	the return value is the error code of the failure 
- */
-static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	u32 instance;
-	char buf[4];
-	int len = 1;
-
-	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100 
-	    && ecmd->speed != SPEED_1000)
-		return -EINVAL;
-
-	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
-		return -EINVAL;
-
-	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
-		return -EINVAL;
-
-	if (ecmd->autoneg == AUTONEG_DISABLE)
-		*buf = (ecmd->duplex == DUPLEX_FULL) 
-			? SK_LMODE_FULL : SK_LMODE_HALF;
-	else
-		*buf = (ecmd->duplex == DUPLEX_FULL) 
-			? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF;
-	
-	instance = pnmiInstance(pNet);
-	if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, 
-			   &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
-		return -EINVAL;
-
-	switch(ecmd->speed) {
-	case SPEED_1000:
-		*buf = SK_LSPEED_1000MBPS;
-		break;
-	case SPEED_100:
-		*buf = SK_LSPEED_100MBPS;
-		break;
-	case SPEED_10:
-		*buf = SK_LSPEED_10MBPS;
-	}
-
-	if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
-			 &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
-		return -EINVAL;
-
-	return 0;
-}
-
-/*****************************************************************************
- *
- * 	getDriverInfo - returns generic driver and adapter information
- *
- * Description:
- *	Generic driver information is returned via this function, such as
- *	the name of the driver, its version and and firmware version.
- *	In addition to this, the location of the selected adapter is 
- *	returned as a bus info string (e.g. '01:05.0').
- *	
- * Returns:	N/A
- *
- */
-static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	const DEV_NET	*pNet = netdev_priv(dev);
-	const SK_AC *pAC = pNet->pAC;
-	char vers[32];
-
-	snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)",
-		(pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf);
-
-	strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
-	strcpy(info->version, vers);
-	strcpy(info->fw_version, "N/A");
-	strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
-}
-
-/*
- * Ethtool statistics support.
- */
-static const char StringsStats[][ETH_GSTRING_LEN] = {
-	"rx_packets",	"tx_packets",
-	"rx_bytes",	"tx_bytes",
-	"rx_errors",	"tx_errors",	
-	"rx_dropped",	"tx_dropped",
-	"multicasts",	"collisions",	
-	"rx_length_errors",		"rx_buffer_overflow_errors",
-	"rx_crc_errors",		"rx_frame_errors",
-	"rx_too_short_errors",		"rx_too_long_errors",
-	"rx_carrier_extension_errors",	"rx_symbol_errors",
-	"rx_llc_mac_size_errors",	"rx_carrier_errors",	
-	"rx_jabber_errors",		"rx_missed_errors",
-	"tx_abort_collision_errors",	"tx_carrier_errors",
-	"tx_buffer_underrun_errors",	"tx_heartbeat_errors",
-	"tx_window_errors",
-};
-
-static int getStatsCount(struct net_device *dev)
-{
-	return ARRAY_SIZE(StringsStats);
-}
-
-static void getStrings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	switch(stringset) {
-	case ETH_SS_STATS:
-		memcpy(data, *StringsStats, sizeof(StringsStats));
-		break;
-	}
-}
-
-static void getEthtoolStats(struct net_device *dev,
-			    struct ethtool_stats *stats, u64 *data)
-{
-	const DEV_NET	*pNet = netdev_priv(dev);
-	const SK_AC *pAC = pNet->pAC;
-	const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
-
-	*data++ = pPnmiStruct->Stat[0].StatRxOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
-	*data++ = pPnmiStruct->InErrorsCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
-	*data++ = pPnmiStruct->RxNoBufCts;
-	*data++ = pPnmiStruct->TxNoBufCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxCextCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
-	*data++ = pAC->stats.tx_aborted_errors;
-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
-	*data++ = pAC->stats.tx_window_errors;
-}
-
-
-/*****************************************************************************
- *
- * 	toggleLeds - Changes the LED state of an adapter
- *
- * Description:
- *	This function changes the current state of all LEDs of an adapter so
- *	that it can be located by a user. 
- *
- * Returns:	N/A
- *
- */
-static void toggleLeds(DEV_NET *pNet, int on)
-{
-	SK_AC *pAC = pNet->pAC;
-	int port = pNet->PortNr;
-	void __iomem *io = pAC->IoBase;
-
-	if (pAC->GIni.GIGenesis) {
-		SK_OUT8(io, MR_ADDR(port,LNK_LED_REG), 
-			on ? SK_LNK_ON : SK_LNK_OFF);
-		SkGeYellowLED(pAC, io, 
-			      on ? (LED_ON >> 1) : (LED_OFF >> 1));
-		SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI),
-			    on ? SK_LED_TST : SK_LED_DIS);
-
-		if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM)
-			SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL, 
-				     on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF);
-		else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE)
-			SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG,
-				     on ? 0x0800 : PHY_L_LC_LEDT);
-		else
-			SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI),
-				    on ? SK_LED_TST : SK_LED_DIS);
-	} else {
-		const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON)  |
-				      PHY_M_LED_MO_10(MO_LED_ON)   |
-				      PHY_M_LED_MO_100(MO_LED_ON)  |
-				      PHY_M_LED_MO_1000(MO_LED_ON) | 
-				      PHY_M_LED_MO_RX(MO_LED_ON));
-		const u16  YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF)  |
-					PHY_M_LED_MO_10(MO_LED_OFF)   |
-					PHY_M_LED_MO_100(MO_LED_OFF)  |
-					PHY_M_LED_MO_1000(MO_LED_OFF) | 
-					PHY_M_LED_MO_RX(MO_LED_OFF));
-	
-
-		SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0);
-		SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER, 
-			     on ? YukLedOn : YukLedOff);
-	}
-}
-
-/*****************************************************************************
- *
- * 	skGeBlinkTimer - Changes the LED state of an adapter
- *
- * Description:
- *	This function changes the current state of all LEDs of an adapter so
- *	that it can be located by a user. If the requested time interval for
- *	this test has elapsed, this function cleans up everything that was 
- *	temporarily setup during the locate NIC test. This involves of course
- *	also closing or opening any adapter so that the initial board state 
- *	is recovered.
- *
- * Returns:	N/A
- *
- */
-void SkGeBlinkTimer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *) data;
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	toggleLeds(pNet, pAC->LedsOn);
-
-	pAC->LedsOn = !pAC->LedsOn;
-	mod_timer(&pAC->BlinkTimer, jiffies + HZ/4);
-}
-
-/*****************************************************************************
- *
- * 	locateDevice - start the locate NIC feature of the elected adapter 
- *
- * Description:
- *	This function is used if the user want to locate a particular NIC.
- *	All LEDs are regularly switched on and off, so the NIC can easily
- *	be identified.
- *
- * Returns:	
- *	==0:	everything fine, no error, locateNIC test was started
- *	!=0:	one locateNIC test runs already
- *
- */
-static int locateDevice(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
-		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
-
-	/* start blinking */
-	pAC->LedsOn = 0;
-	mod_timer(&pAC->BlinkTimer, jiffies);
-	msleep_interruptible(data * 1000);
-	del_timer_sync(&pAC->BlinkTimer);
-	toggleLeds(pNet, 0);
-
-	return 0;
-}
-
-/*****************************************************************************
- *
- * 	getPauseParams - retrieves the pause parameters
- *
- * Description:
- *	All current pause parameters of a selected adapter are placed 
- *	in the passed ethtool_pauseparam structure and are returned.
- *
- * Returns:	N/A
- *
- */
-static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause) 
-{
-	DEV_NET	*pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
-
-	epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
-		  (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM);
-
-	epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND);
-	epause->autoneg = epause->rx_pause || epause->tx_pause;
-}
-
-/*****************************************************************************
- *
- *	setPauseParams - configures the pause parameters of an adapter
- *
- * Description:
- *	This function sets the Rx or Tx pause parameters 
- *
- * Returns:
- *	==0:	everything fine, no error
- *	!=0:	the return value is the error code of the failure 
- */
-static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause)
-{
-	DEV_NET	*pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
-	u32	instance = pnmiInstance(pNet);
-	struct ethtool_pauseparam old;
-	u8	oldspeed = pPort->PLinkSpeedUsed;
-	char	buf[4];
-	int	len = 1;
-	int ret;
-
-	/*
-	** we have to determine the current settings to see if 
-	** the operator requested any modification of the flow 
-	** control parameters...
-	*/
-	getPauseParams(dev, &old);
-
-	/*
-	** perform modifications regarding the changes 
-	** requested by the operator
-	*/
-	if (epause->autoneg != old.autoneg) 
-		*buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC;
-	else {
-		if (epause->rx_pause && epause->tx_pause) 
-			*buf = SK_FLOW_MODE_SYMMETRIC;
-		else if (epause->rx_pause && !epause->tx_pause)
-			*buf =  SK_FLOW_MODE_SYM_OR_REM;
-		else if (!epause->rx_pause && epause->tx_pause)
-			*buf =  SK_FLOW_MODE_LOC_SEND;
-		else
-			*buf = SK_FLOW_MODE_NONE;
-	}
-
-	ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
-			 &buf, &len, instance, pNet->NetNr);
-
-	if (ret != SK_PNMI_ERR_OK) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
-			   ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret));
-		goto err;
-	}
-
-	/*
-	** It may be that autoneg has been disabled! Therefore
-	** set the speed to the previously used value...
-	*/
-	if (!epause->autoneg) {
-		len = 1;
-		ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
-				   &oldspeed, &len, instance, pNet->NetNr);
-		if (ret != SK_PNMI_ERR_OK) 
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
-				   ("ethtool (sk98lin): error setting speed (%i)\n", ret));
-	}
- err:
-        return ret ? -EIO : 0;
-}
-
-/* Only Yukon supports checksum offload. */
-static int setScatterGather(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-	return ethtool_op_set_sg(dev, data);
-}
-
-static int setTxCsum(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-
-	return ethtool_op_set_tx_csum(dev, data);
-}
-
-static u32 getRxCsum(struct net_device *dev)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	return pAC->RxPort[pNet->PortNr].RxCsum;
-}
-
-static int setRxCsum(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-
-	pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
-	return 0;
-}
-
-static int getRegsLen(struct net_device *dev)
-{
-	return 0x4000;
-}
-
-/*
- * Returns copy of whole control register region
- * Note: skip RAM address register because accessing it will
- * 	 cause bus hangs!
- */
-static void getRegs(struct net_device *dev, struct ethtool_regs *regs,
-			  void *p)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	const void __iomem *io = pNet->pAC->IoBase;
-
-	regs->version = 1;
-	memset(p, 0, regs->len);
-	memcpy_fromio(p, io, B3_RAM_ADDR);
-
-	memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-		      regs->len - B3_RI_WTO_R1);
-}
-
-const struct ethtool_ops SkGeEthtoolOps = {
-	.get_settings		= getSettings,
-	.set_settings		= setSettings,
-	.get_drvinfo		= getDriverInfo,
-	.get_strings		= getStrings,
-	.get_stats_count	= getStatsCount,
-	.get_ethtool_stats	= getEthtoolStats,
-	.phys_id		= locateDevice,
-	.get_pauseparam		= getPauseParams,
-	.set_pauseparam		= setPauseParams,
-	.get_link		= ethtool_op_get_link,
-	.get_perm_addr		= ethtool_op_get_perm_addr,
-	.get_sg			= ethtool_op_get_sg,
-	.set_sg			= setScatterGather,
-	.get_tx_csum		= ethtool_op_get_tx_csum,
-	.set_tx_csum		= setTxCsum,
-	.get_rx_csum		= getRxCsum,
-	.set_rx_csum		= setRxCsum,
-	.get_regs		= getRegs,
-	.get_regs_len		= getRegsLen,
-};
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
deleted file mode 100644
index bf21862..0000000
--- a/drivers/net/sk98lin/skge.c
+++ /dev/null
@@ -1,5211 +0,0 @@
-/******************************************************************************
- *
- * Name:	skge.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.45 $
- * Date:       	$Date: 2004/02/12 14:41:02 $
- * Purpose:	The main driver source module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet 
- *      Server Adapters.
- *
- *	Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
- *	SysKonnects GEnesis Solaris driver
- *	Author: Christoph Goos (cgoos@syskonnect.de)
- *	        Mirko Lindner (mlindner@syskonnect.de)
- *
- *	Address all question to: linux@syskonnect.de
- *
- *	The technical manual for the adapters is available from SysKonnect's
- *	web pages: www.syskonnect.com
- *	Goto "Support" and search Knowledge Base for "manual".
- *	
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Possible compiler options (#define xxx / -Dxxx):
- *
- *	debugging can be enable by changing SK_DEBUG_CHKMOD and
- *	SK_DEBUG_CHKCAT in makefile (described there).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- *	This is the main module of the Linux GE driver.
- *	
- *	All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h
- *	are part of SysKonnect's COMMON MODULES for the SK-98xx adapters.
- *	Those are used for drivers on multiple OS', so some thing may seem
- *	unnecessary complicated on Linux. Please do not try to 'clean up'
- *	them without VERY good reasons, because this will make it more
- *	difficult to keep the Linux driver in synchronisation with the
- *	other versions.
- *
- * Include file hierarchy:
- *
- *	<linux/module.h>
- *
- *	"h/skdrv1st.h"
- *		<linux/types.h>
- *		<linux/kernel.h>
- *		<linux/string.h>
- *		<linux/errno.h>
- *		<linux/ioport.h>
- *		<linux/slab.h>
- *		<linux/interrupt.h>
- *		<linux/pci.h>
- *		<linux/bitops.h>
- *		<asm/byteorder.h>
- *		<asm/io.h>
- *		<linux/netdevice.h>
- *		<linux/etherdevice.h>
- *		<linux/skbuff.h>
- *	    those three depending on kernel version used:
- *		<linux/bios32.h>
- *		<linux/init.h>
- *		<asm/uaccess.h>
- *		<net/checksum.h>
- *
- *		"h/skerror.h"
- *		"h/skdebug.h"
- *		"h/sktypes.h"
- *		"h/lm80.h"
- *		"h/xmac_ii.h"
- *
- *      "h/skdrv2nd.h"
- *		"h/skqueue.h"
- *		"h/skgehwt.h"
- *		"h/sktimer.h"
- *		"h/ski2c.h"
- *		"h/skgepnmi.h"
- *		"h/skvpd.h"
- *		"h/skgehw.h"
- *		"h/skgeinit.h"
- *		"h/skaddr.h"
- *		"h/skgesirq.h"
- *		"h/skrlmt.h"
- *
- ******************************************************************************/
-
-#include	"h/skversion.h"
-
-#include	<linux/in.h>
-#include	<linux/module.h>
-#include	<linux/moduleparam.h>
-#include	<linux/init.h>
-#include	<linux/dma-mapping.h>
-#include	<linux/ip.h>
-#include	<linux/mii.h>
-#include	<linux/mm.h>
-
-#include	"h/skdrv1st.h"
-#include	"h/skdrv2nd.h"
-
-/*******************************************************************************
- *
- * Defines
- *
- ******************************************************************************/
-
-/* for debuging on x86 only */
-/* #define BREAKPOINT() asm(" int $3"); */
-
-/* use the transmit hw checksum driver functionality */
-#define USE_SK_TX_CHECKSUM
-
-/* use the receive hw checksum driver functionality */
-#define USE_SK_RX_CHECKSUM
-
-/* use the scatter-gather functionality with sendfile() */
-#define SK_ZEROCOPY
-
-/* use of a transmit complete interrupt */
-#define USE_TX_COMPLETE
-
-/*
- * threshold for copying small receive frames
- * set to 0 to avoid copying, set to 9001 to copy all frames
- */
-#define SK_COPY_THRESHOLD	50
-
-/* number of adapters that can be configured via command line params */
-#define SK_MAX_CARD_PARAM	16
-
-
-
-/*
- * use those defines for a compile-in version of the driver instead
- * of command line parameters
- */
-// #define LINK_SPEED_A	{"Auto", }
-// #define LINK_SPEED_B	{"Auto", }
-// #define AUTO_NEG_A	{"Sense", }
-// #define AUTO_NEG_B	{"Sense", }
-// #define DUP_CAP_A	{"Both", }
-// #define DUP_CAP_B	{"Both", }
-// #define FLOW_CTRL_A	{"SymOrRem", }
-// #define FLOW_CTRL_B	{"SymOrRem", }
-// #define ROLE_A	{"Auto", }
-// #define ROLE_B	{"Auto", }
-// #define PREF_PORT	{"A", }
-// #define CON_TYPE 	{"Auto", }
-// #define RLMT_MODE	{"CheckLinkState", }
-
-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
-#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
-#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
-
-
-/* Set blink mode*/
-#define OEM_CONFIG_VALUE (	SK_ACT_LED_BLINK | \
-				SK_DUP_LED_NORMAL | \
-				SK_LED_LINK100_ON)
-
-
-/* Isr return value */
-#define SkIsrRetVar	irqreturn_t
-#define SkIsrRetNone	IRQ_NONE
-#define SkIsrRetHandled	IRQ_HANDLED
-
-
-/*******************************************************************************
- *
- * Local Function Prototypes
- *
- ******************************************************************************/
-
-static void	FreeResources(struct SK_NET_DEVICE *dev);
-static int	SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
-static SK_BOOL	BoardAllocMem(SK_AC *pAC);
-static void	BoardFreeMem(SK_AC *pAC);
-static void	BoardInitMem(SK_AC *pAC);
-static void	SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
-static SkIsrRetVar	SkGeIsr(int irq, void *dev_id);
-static SkIsrRetVar	SkGeIsrOnePort(int irq, void *dev_id);
-static int	SkGeOpen(struct SK_NET_DEVICE *dev);
-static int	SkGeClose(struct SK_NET_DEVICE *dev);
-static int	SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
-static int	SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
-static void	SkGeSetRxMode(struct SK_NET_DEVICE *dev);
-static struct	net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
-static int	SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
-static void	GetConfiguration(SK_AC*);
-static int	XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
-static void	FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
-static void	FillRxRing(SK_AC*, RX_PORT*);
-static SK_BOOL	FillRxDescriptor(SK_AC*, RX_PORT*);
-static void	ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
-static void	ClearAndStartRx(SK_AC*, int);
-static void	ClearTxIrq(SK_AC*, int, int);
-static void	ClearRxRing(SK_AC*, RX_PORT*);
-static void	ClearTxRing(SK_AC*, TX_PORT*);
-static int	SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
-static void	PortReInitBmu(SK_AC*, int);
-static int	SkGeIocMib(DEV_NET*, unsigned int, int);
-static int	SkGeInitPCI(SK_AC *pAC);
-static void	StartDrvCleanupTimer(SK_AC *pAC);
-static void	StopDrvCleanupTimer(SK_AC *pAC);
-static int	XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
-
-#ifdef SK_DIAG_SUPPORT
-static SK_U32   ParseDeviceNbrFromSlotName(const char *SlotName);
-static int      SkDrvInitAdapter(SK_AC *pAC, int devNbr);
-static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
-#endif
-
-/*******************************************************************************
- *
- * Extern Function Prototypes
- *
- ******************************************************************************/
-extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);	
-extern void SkDimDisplayModerationSettings(SK_AC *pAC);
-extern void SkDimStartModerationTimer(SK_AC *pAC);
-extern void SkDimModerate(SK_AC *pAC);
-extern void SkGeBlinkTimer(unsigned long data);
-
-#ifdef DEBUG
-static void	DumpMsg(struct sk_buff*, char*);
-static void	DumpData(char*, int);
-static void	DumpLong(char*, int);
-#endif
-
-/* global variables *********************************************************/
-static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
-extern const struct ethtool_ops SkGeEthtoolOps;
-
-/* local variables **********************************************************/
-static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
-static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgDWord - write a 32 bit value to pci config space
- *
- * Description:
- *	This routine writes a 32 bit value to the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-static inline int SkPciWriteCfgDWord(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U32 Val)		/* pointer to store the read value */
-{
-	pci_write_config_dword(pAC->PciDev, PciAddr, Val);
-	return(0);
-} /* SkPciWriteCfgDWord */
-
-/*****************************************************************************
- *
- * 	SkGeInitPCI - Init the PCI resources
- *
- * Description:
- *	This function initialize the PCI resources and IO
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-static __devinit int SkGeInitPCI(SK_AC *pAC)
-{
-	struct SK_NET_DEVICE *dev = pAC->dev[0];
-	struct pci_dev *pdev = pAC->PciDev;
-	int retval;
-
-	dev->mem_start = pci_resource_start (pdev, 0);
-	pci_set_master(pdev);
-
-	retval = pci_request_regions(pdev, "sk98lin");
-	if (retval)
-		goto out;
-
-#ifdef SK_BIG_ENDIAN
-	/*
-	 * On big endian machines, we use the adapter's aibility of
-	 * reading the descriptors as big endian.
-	 */
-	{
-		SK_U32		our2;
-		SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
-		our2 |= PCI_REV_DESC;
-		SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
-	}
-#endif
-
-	/*
-	 * Remap the regs into kernel space.
-	 */
-	pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
-	if (!pAC->IoBase) {
-		retval = -EIO;
-		goto out_release;
-	}
-
-	return 0;
-
- out_release:
-	pci_release_regions(pdev);
- out:
-	return retval;
-}
-
-
-/*****************************************************************************
- *
- * 	FreeResources - release resources allocated for adapter
- *
- * Description:
- *	This function releases the IRQ, unmaps the IO and
- *	frees the desriptor ring.
- *
- * Returns: N/A
- *	
- */
-static void FreeResources(struct SK_NET_DEVICE *dev)
-{
-SK_U32 AllocFlag;
-DEV_NET		*pNet;
-SK_AC		*pAC;
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	AllocFlag = pAC->AllocFlag;
-	if (pAC->PciDev) {
-		pci_release_regions(pAC->PciDev);
-	}
-	if (AllocFlag & SK_ALLOC_IRQ) {
-		free_irq(dev->irq, dev);
-	}
-	if (pAC->IoBase) {
-		iounmap(pAC->IoBase);
-	}
-	if (pAC->pDescrMem) {
-		BoardFreeMem(pAC);
-	}
-	
-} /* FreeResources */
-
-MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
-MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
-MODULE_LICENSE("GPL");
-
-#ifdef LINK_SPEED_A
-static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
-#else
-static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef LINK_SPEED_B
-static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
-#else
-static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_A
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
-#else
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_A
-static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;
-#else
-static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_A
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;
-#else
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_A
-static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;
-#else
-static char *Role_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_B
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;
-#else
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_B
-static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;
-#else
-static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_B
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;
-#else
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_B
-static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
-#else
-static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef CON_TYPE
-static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
-#else
-static char *ConType[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef PREF_PORT
-static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
-#else
-static char *PrefPort[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef RLMT_MODE
-static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
-#else
-static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-static int   IntsPerSec[SK_MAX_CARD_PARAM];
-static char *Moderation[SK_MAX_CARD_PARAM];
-static char *ModerationMask[SK_MAX_CARD_PARAM];
-static char *AutoSizing[SK_MAX_CARD_PARAM];
-static char *Stats[SK_MAX_CARD_PARAM];
-
-module_param_array(Speed_A, charp, NULL, 0);
-module_param_array(Speed_B, charp, NULL, 0);
-module_param_array(AutoNeg_A, charp, NULL, 0);
-module_param_array(AutoNeg_B, charp, NULL, 0);
-module_param_array(DupCap_A, charp, NULL, 0);
-module_param_array(DupCap_B, charp, NULL, 0);
-module_param_array(FlowCtrl_A, charp, NULL, 0);
-module_param_array(FlowCtrl_B, charp, NULL, 0);
-module_param_array(Role_A, charp, NULL, 0);
-module_param_array(Role_B, charp, NULL, 0);
-module_param_array(ConType, charp, NULL, 0);
-module_param_array(PrefPort, charp, NULL, 0);
-module_param_array(RlmtMode, charp, NULL, 0);
-/* used for interrupt moderation */
-module_param_array(IntsPerSec, int, NULL, 0);
-module_param_array(Moderation, charp, NULL, 0);
-module_param_array(Stats, charp, NULL, 0);
-module_param_array(ModerationMask, charp, NULL, 0);
-module_param_array(AutoSizing, charp, NULL, 0);
-
-/*****************************************************************************
- *
- * 	SkGeBoardInit - do level 0 and 1 initialization
- *
- * Description:
- *	This function prepares the board hardware for running. The desriptor
- *	ring is set up, the IRQ is allocated and the configuration settings
- *	are examined.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
-{
-short	i;
-unsigned long Flags;
-char	*DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
-char	*VerStr	= VER_STRING;
-int	Ret;			/* return code of request_irq */
-SK_BOOL	DualNet;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
-	for (i=0; i<SK_MAX_MACS; i++) {
-		pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0];
-		pAC->TxPort[i][0].PortIndex = i;
-		pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i];
-		pAC->RxPort[i].PortIndex = i;
-	}
-
-	/* Initialize the mutexes */
-	for (i=0; i<SK_MAX_MACS; i++) {
-		spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
-		spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
-	}
-	spin_lock_init(&pAC->SlowPathLock);
-
-	/* setup phy_id blink timer */
-	pAC->BlinkTimer.function = SkGeBlinkTimer;
-	pAC->BlinkTimer.data = (unsigned long) dev;
-	init_timer(&pAC->BlinkTimer);
-
-	/* level 0 init common modules here */
-	
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	/* Does a RESET on board ...*/
-	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
-		printk("HWInit (0) failed.\n");
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		return -EIO;
-	}
-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_DATA);
-	SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
-
-	pAC->BoardLevel = SK_INIT_DATA;
-	pAC->RxBufSize  = ETH_BUF_SIZE;
-
-	SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
-	SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
-
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	/* level 1 init common modules here (HW init) */
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
-		printk("sk98lin: HWInit (1) failed.\n");
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		return -EIO;
-	}
-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
-	SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
-
-	/* Set chipset type support */
-	pAC->ChipsetType = 0;
-	if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
-		(pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
-		pAC->ChipsetType = 1;
-	}
-
-	GetConfiguration(pAC);
-	if (pAC->RlmtNets == 2) {
-		pAC->GIni.GIPortUsage = SK_MUL_LINK;
-	}
-
-	pAC->BoardLevel = SK_INIT_IO;
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	if (pAC->GIni.GIMacsFound == 2) {
-		 Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
-	} else if (pAC->GIni.GIMacsFound == 1) {
-		Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED,
-			"sk98lin", dev);
-	} else {
-		printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
-		       pAC->GIni.GIMacsFound);
-		return -EIO;
-	}
-
-	if (Ret) {
-		printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
-		       dev->irq);
-		return Ret;
-	}
-	pAC->AllocFlag |= SK_ALLOC_IRQ;
-
-	/* Alloc memory for this board (Mem for RxD/TxD) : */
-	if(!BoardAllocMem(pAC)) {
-		printk("No memory for descriptor rings.\n");
-		return -ENOMEM;
-	}
-
-	BoardInitMem(pAC);
-	/* tschilling: New common function with minimum size check. */
-	DualNet = SK_FALSE;
-	if (pAC->RlmtNets == 2) {
-		DualNet = SK_TRUE;
-	}
-	
-	if (SkGeInitAssignRamToQueues(
-		pAC,
-		pAC->ActivePort,
-		DualNet)) {
-		BoardFreeMem(pAC);
-		printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
-		return -EIO;
-	}
-
-	return (0);
-} /* SkGeBoardInit */
-
-
-/*****************************************************************************
- *
- * 	BoardAllocMem - allocate the memory for the descriptor rings
- *
- * Description:
- *	This function allocates the memory for all descriptor rings.
- *	Each ring is aligned for the desriptor alignment and no ring
- *	has a 4 GByte boundary in it (because the upper 32 bit must
- *	be constant for all descriptiors in one rings).
- *
- * Returns:
- *	SK_TRUE, if all memory could be allocated
- *	SK_FALSE, if not
- */
-static __devinit SK_BOOL BoardAllocMem(SK_AC	*pAC)
-{
-caddr_t		pDescrMem;	/* pointer to descriptor memory area */
-size_t		AllocLength;	/* length of complete descriptor area */
-int		i;		/* loop counter */
-unsigned long	BusAddr;
-
-	
-	/* rings plus one for alignment (do not cross 4 GB boundary) */
-	/* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */
-#if (BITS_PER_LONG == 32)
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
-		+ RX_RING_SIZE + 8;
-#endif
-
-	pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
-					 &pAC->pDescrMemDMA);
-
-	if (pDescrMem == NULL) {
-		return (SK_FALSE);
-	}
-	pAC->pDescrMem = pDescrMem;
-	BusAddr = (unsigned long) pAC->pDescrMemDMA;
-
-	/* Descriptors need 8 byte alignment, and this is ensured
-	 * by pci_alloc_consistent.
-	 */
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-			("TX%d/A: pDescrMem: %lX,   PhysDescrMem: %lX\n",
-			i, (unsigned long) pDescrMem,
-			BusAddr));
-		pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
-		pAC->TxPort[i][0].VTxDescrRing = BusAddr;
-		pDescrMem += TX_RING_SIZE;
-		BusAddr += TX_RING_SIZE;
-	
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-			("RX%d: pDescrMem: %lX,   PhysDescrMem: %lX\n",
-			i, (unsigned long) pDescrMem,
-			(unsigned long)BusAddr));
-		pAC->RxPort[i].pRxDescrRing = pDescrMem;
-		pAC->RxPort[i].VRxDescrRing = BusAddr;
-		pDescrMem += RX_RING_SIZE;
-		BusAddr += RX_RING_SIZE;
-	} /* for */
-	
-	return (SK_TRUE);
-} /* BoardAllocMem */
-
-
-/****************************************************************************
- *
- *	BoardFreeMem - reverse of BoardAllocMem
- *
- * Description:
- *	Free all memory allocated in BoardAllocMem: adapter context,
- *	descriptor rings, locks.
- *
- * Returns:	N/A
- */
-static void BoardFreeMem(
-SK_AC		*pAC)
-{
-size_t		AllocLength;	/* length of complete descriptor area */
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("BoardFreeMem\n"));
-#if (BITS_PER_LONG == 32)
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
-		+ RX_RING_SIZE + 8;
-#endif
-
-	pci_free_consistent(pAC->PciDev, AllocLength,
-			    pAC->pDescrMem, pAC->pDescrMemDMA);
-	pAC->pDescrMem = NULL;
-} /* BoardFreeMem */
-
-
-/*****************************************************************************
- *
- * 	BoardInitMem - initiate the descriptor rings
- *
- * Description:
- *	This function sets the descriptor rings up in memory.
- *	The adapter is initialized with the descriptor start addresses.
- *
- * Returns:	N/A
- */
-static __devinit void BoardInitMem(SK_AC *pAC)
-{
-int	i;		/* loop counter */
-int	RxDescrSize;	/* the size of a rx descriptor rounded up to alignment*/
-int	TxDescrSize;	/* the size of a tx descriptor rounded up to alignment*/
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("BoardInitMem\n"));
-
-	RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
-	pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
-	TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
-	pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
-	
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		SetupRing(
-			pAC,
-			pAC->TxPort[i][0].pTxDescrRing,
-			pAC->TxPort[i][0].VTxDescrRing,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingHead,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingTail,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
-			&pAC->TxPort[i][0].TxdRingFree,
-			SK_TRUE);
-		SetupRing(
-			pAC,
-			pAC->RxPort[i].pRxDescrRing,
-			pAC->RxPort[i].VRxDescrRing,
-			&pAC->RxPort[i].pRxdRingHead,
-			&pAC->RxPort[i].pRxdRingTail,
-			&pAC->RxPort[i].pRxdRingPrev,
-			&pAC->RxPort[i].RxdRingFree,
-			SK_FALSE);
-	}
-} /* BoardInitMem */
-
-
-/*****************************************************************************
- *
- * 	SetupRing - create one descriptor ring
- *
- * Description:
- *	This function creates one descriptor ring in the given memory area.
- *	The head, tail and number of free descriptors in the ring are set.
- *
- * Returns:
- *	none
- */
-static void SetupRing(
-SK_AC		*pAC,
-void		*pMemArea,	/* a pointer to the memory area for the ring */
-uintptr_t	VMemArea,	/* the virtual bus address of the memory area */
-RXD		**ppRingHead,	/* address where the head should be written */
-RXD		**ppRingTail,	/* address where the tail should be written */
-RXD		**ppRingPrev,	/* address where the tail should be written */
-int		*pRingFree,	/* address where the # of free descr. goes */
-SK_BOOL		IsTx)		/* flag: is this a tx ring */
-{
-int	i;		/* loop counter */
-int	DescrSize;	/* the size of a descriptor rounded up to alignment*/
-int	DescrNum;	/* number of descriptors per ring */
-RXD	*pDescr;	/* pointer to a descriptor (receive or transmit) */
-RXD	*pNextDescr;	/* pointer to the next descriptor */
-RXD	*pPrevDescr;	/* pointer to the previous descriptor */
-uintptr_t VNextDescr;	/* the virtual bus address of the next descriptor */
-
-	if (IsTx == SK_TRUE) {
-		DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
-			DESCR_ALIGN;
-		DescrNum = TX_RING_SIZE / DescrSize;
-	} else {
-		DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
-			DESCR_ALIGN;
-		DescrNum = RX_RING_SIZE / DescrSize;
-	}
-	
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-		("Descriptor size: %d   Descriptor Number: %d\n",
-		DescrSize,DescrNum));
-	
-	pDescr = (RXD*) pMemArea;
-	pPrevDescr = NULL;
-	pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
-	VNextDescr = VMemArea + DescrSize;
-	for(i=0; i<DescrNum; i++) {
-		/* set the pointers right */
-		pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
-		pDescr->pNextRxd = pNextDescr;
-		if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN;
-
-		/* advance one step */
-		pPrevDescr = pDescr;
-		pDescr = pNextDescr;
-		pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
-		VNextDescr += DescrSize;
-	}
-	pPrevDescr->pNextRxd = (RXD*) pMemArea;
-	pPrevDescr->VNextRxd = VMemArea;
-	pDescr = (RXD*) pMemArea;
-	*ppRingHead = (RXD*) pMemArea;
-	*ppRingTail = *ppRingHead;
-	*ppRingPrev = pPrevDescr;
-	*pRingFree = DescrNum;
-} /* SetupRing */
-
-
-/*****************************************************************************
- *
- * 	PortReInitBmu - re-initiate the descriptor rings for one port
- *
- * Description:
- *	This function reinitializes the descriptor rings of one port
- *	in memory. The port must be stopped before.
- *	The HW is initialized with the descriptor start addresses.
- *
- * Returns:
- *	none
- */
-static void PortReInitBmu(
-SK_AC	*pAC,		/* pointer to adapter context */
-int	PortIndex)	/* index of the port for which to re-init */
-{
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("PortReInitBmu "));
-
-	/* set address of first descriptor of ring in BMU */
-	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
-		(uint32_t)(((caddr_t)
-		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
-		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
-		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
-		0xFFFFFFFF));
-	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
-		(uint32_t)(((caddr_t)
-		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
-		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
-		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
-	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
-		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
-		pAC->RxPort[PortIndex].pRxDescrRing +
-		pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
-	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
-		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
-		pAC->RxPort[PortIndex].pRxDescrRing +
-		pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
-} /* PortReInitBmu */
-
-
-/****************************************************************************
- *
- *	SkGeIsr - handle adapter interrupts
- *
- * Description:
- *	The interrupt routine is called when the network adapter
- *	generates an interrupt. It may also be called if another device
- *	shares this interrupt vector with the driver.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsr(int irq, void *dev_id)
-{
-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
-DEV_NET		*pNet;
-SK_AC		*pAC;
-SK_U32		IntSrc;		/* interrupts source register contents */	
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	/*
-	 * Check and process if its our interrupt
-	 */
-	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
-	if (IntSrc == 0) {
-		return SkIsrRetNone;
-	}
-
-	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
-		if (IntSrc & IS_IRQ_SW) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("Software IRQ\n"));
-		}
-#endif
-		if (IntSrc & IS_R1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF RX1 IRQ\n"));
-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 0);
-		}
-		if (IntSrc & IS_R2_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF RX2 IRQ\n"));
-			ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 1);
-		}
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF AS TX1 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 0);
-			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
-			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-		}
-		if (IntSrc & IS_XA2_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF AS TX2 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 1);
-			spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
-			FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
-			spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
-		}
-#if 0 /* only if sync. queues used */
-		if (IntSrc & IS_XS1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF SY TX1 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 1);
-			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
-			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-			ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
-		}
-		if (IntSrc & IS_XS2_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF SY TX2 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 1);
-			spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
-			FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
-			spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
-			ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
-		}
-#endif
-#endif
-
-		/* do all IO at once */
-		if (IntSrc & IS_R1_F)
-			ClearAndStartRx(pAC, 0);
-		if (IntSrc & IS_R2_F)
-			ClearAndStartRx(pAC, 1);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F)
-			ClearTxIrq(pAC, 0, TX_PRIO_LOW);
-		if (IntSrc & IS_XA2_F)
-			ClearTxIrq(pAC, 1, TX_PRIO_LOW);
-#endif
-		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
-	} /* while (IntSrc & IRQ_MASK != 0) */
-
-	IntSrc &= pAC->GIni.GIValIrqMask;
-	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
-			("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
-		pAC->CheckQueue = SK_FALSE;
-		spin_lock(&pAC->SlowPathLock);
-		if (IntSrc & SPECIAL_IRQS)
-			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
-
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock(&pAC->SlowPathLock);
-	}
-	/*
-	 * do it all again is case we cleared an interrupt that
-	 * came in after handling the ring (OUTs may be delayed
-	 * in hardware buffers, but are through after IN)
-	 *
-	 * rroesler: has been commented out and shifted to
-	 *           SkGeDrvEvent(), because it is timer
-	 *           guarded now
-	 *
-	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
-	ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
-	 */
-
-	if (pAC->CheckQueue) {
-		pAC->CheckQueue = SK_FALSE;
-		spin_lock(&pAC->SlowPathLock);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock(&pAC->SlowPathLock);
-	}
-
-	/* IRQ is processed - Enable IRQs again*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
-		return SkIsrRetHandled;
-} /* SkGeIsr */
-
-
-/****************************************************************************
- *
- *	SkGeIsrOnePort - handle adapter interrupts for single port adapter
- *
- * Description:
- *	The interrupt routine is called when the network adapter
- *	generates an interrupt. It may also be called if another device
- *	shares this interrupt vector with the driver.
- *	This is the same as above, but handles only one port.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id)
-{
-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
-DEV_NET		*pNet;
-SK_AC		*pAC;
-SK_U32		IntSrc;		/* interrupts source register contents */	
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	/*
-	 * Check and process if its our interrupt
-	 */
-	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
-	if (IntSrc == 0) {
-		return SkIsrRetNone;
-	}
-	
-	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
-		if (IntSrc & IS_IRQ_SW) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("Software IRQ\n"));
-		}
-#endif
-		if (IntSrc & IS_R1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF RX1 IRQ\n"));
-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 0);
-		}
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF AS TX1 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 0);
-			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
-			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-		}
-#if 0 /* only if sync. queues used */
-		if (IntSrc & IS_XS1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF SY TX1 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 0);
-			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
-			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-			ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
-		}
-#endif
-#endif
-
-		/* do all IO at once */
-		if (IntSrc & IS_R1_F)
-			ClearAndStartRx(pAC, 0);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F)
-			ClearTxIrq(pAC, 0, TX_PRIO_LOW);
-#endif
-		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
-	} /* while (IntSrc & IRQ_MASK != 0) */
-	
-	IntSrc &= pAC->GIni.GIValIrqMask;
-	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
-			("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
-		pAC->CheckQueue = SK_FALSE;
-		spin_lock(&pAC->SlowPathLock);
-		if (IntSrc & SPECIAL_IRQS)
-			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
-
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock(&pAC->SlowPathLock);
-	}
-	/*
-	 * do it all again is case we cleared an interrupt that
-	 * came in after handling the ring (OUTs may be delayed
-	 * in hardware buffers, but are through after IN)
-	 *
-	 * rroesler: has been commented out and shifted to
-	 *           SkGeDrvEvent(), because it is timer
-	 *           guarded now
-	 *
-	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
-	 */
-
-	/* IRQ is processed - Enable IRQs again*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
-		return SkIsrRetHandled;
-} /* SkGeIsrOnePort */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/****************************************************************************
- *
- * 	SkGePollController - polling receive, for netconsole
- *
- * Description:
- *	Polling receive - used by netconsole and other diagnostic tools
- *	to allow network i/o with interrupts disabled.
- *
- * Returns: N/A
- */
-static void SkGePollController(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	SkGeIsr(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-/****************************************************************************
- *
- *	SkGeOpen - handle start of initialized adapter
- *
- * Description:
- *	This function starts the initialized adapter.
- *	The board level variable is set and the adapter is
- *	brought to full functionality.
- *	The device flags are set for operation.
- *	Do all necessary level 2 initialization, enable interrupts and
- *	give start command to RLMT.
- *
- * Returns:
- *	0 on success
- *	!= 0 on error
- */
-static int SkGeOpen(
-struct SK_NET_DEVICE	*dev)
-{
-	DEV_NET			*pNet;
-	SK_AC			*pAC;
-	unsigned long	Flags;		/* for spin lock */
-	int				i;
-	SK_EVPARA		EvPara;		/* an event parameter union */
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-			return (-1);   /* still in use by diag; deny actions */
-		} 
-	}
-#endif
-
-	/* Set blink mode */
-	if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
-		pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
-
-	if (pAC->BoardLevel == SK_INIT_DATA) {
-		/* level 1 init common modules here */
-		if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
-			printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
-			return (-1);
-		}
-		SkI2cInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkEventInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkPnmiInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkAddrInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkRlmtInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkTimerInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		pAC->BoardLevel = SK_INIT_IO;
-	}
-
-	if (pAC->BoardLevel != SK_INIT_RUN) {
-		/* tschilling: Level 2 init modules here, check return value. */
-		if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
-			printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
-			return (-1);
-		}
-		SkI2cInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkEventInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkPnmiInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkAddrInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkRlmtInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkTimerInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		pAC->BoardLevel = SK_INIT_RUN;
-	}
-
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		/* Enable transmit descriptor polling. */
-		SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
-		FillRxRing(pAC, &pAC->RxPort[i]);
-	}
-	SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-	StartDrvCleanupTimer(pAC);
-	SkDimEnableModerationIfNeeded(pAC);	
-	SkDimDisplayModerationSettings(pAC);
-
-	pAC->GIni.GIValIrqMask &= IRQ_MASK;
-
-	/* enable Interrupts */
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
-	if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
-		EvPara.Para32[0] = pAC->RlmtNets;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
-			EvPara);
-		EvPara.Para32[0] = pAC->RlmtMode;
-		EvPara.Para32[1] = 0;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
-			EvPara);
-	}
-
-	EvPara.Para32[0] = pNet->NetNr;
-	EvPara.Para32[1] = -1;
-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-	SkEventDispatcher(pAC, pAC->IoBase);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	pAC->MaxPorts++;
-
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeOpen suceeded\n"));
-
-	return (0);
-} /* SkGeOpen */
-
-
-/****************************************************************************
- *
- *	SkGeClose - Stop initialized adapter
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkGeClose(
-struct SK_NET_DEVICE	*dev)
-{
-	DEV_NET		*pNet;
-	DEV_NET		*newPtrNet;
-	SK_AC		*pAC;
-
-	unsigned long	Flags;		/* for spin lock */
-	int		i;
-	int		PortIdx;
-	SK_EVPARA	EvPara;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->DiagFlowCtrl == SK_FALSE) {
-			/* 
-			** notify that the interface which has been closed
-			** by operator interaction must not be started up 
-			** again when the DIAG has finished. 
-			*/
-			newPtrNet = netdev_priv(pAC->dev[0]);
-			if (newPtrNet == pNet) {
-				pAC->WasIfUp[0] = SK_FALSE;
-			} else {
-				pAC->WasIfUp[1] = SK_FALSE;
-			}
-			return 0; /* return to system everything is fine... */
-		} else {
-			pAC->DiagFlowCtrl = SK_FALSE;
-		}
-	}
-#endif
-
-	netif_stop_queue(dev);
-
-	if (pAC->RlmtNets == 1)
-		PortIdx = pAC->ActivePort;
-	else
-		PortIdx = pNet->NetNr;
-
-        StopDrvCleanupTimer(pAC);
-
-	/*
-	 * Clear multicast table, promiscuous mode ....
-	 */
-	SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
-	SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-		SK_PROM_MODE_NONE);
-
-	if (pAC->MaxPorts == 1) {
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		EvPara.Para32[0] = pNet->NetNr;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		/* stop the hardware */
-		SkGeDeInit(pAC, pAC->IoBase);
-		pAC->BoardLevel = SK_INIT_DATA;
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	} else {
-
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		EvPara.Para32[0] = pNet->NetNr;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		
-		/* Stop port */
-		spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
-			[TX_PRIO_LOW].TxDesRingLock, Flags);
-		SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
-			SK_STOP_ALL, SK_HARD_RST);
-		spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
-			[TX_PRIO_LOW].TxDesRingLock, Flags);
-	}
-
-	if (pAC->RlmtNets == 1) {
-		/* clear all descriptor rings */
-		for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-			ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
-			ClearRxRing(pAC, &pAC->RxPort[i]);
-			ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
-		}
-	} else {
-		/* clear port descriptor rings */
-		ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
-		ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
-		ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
-	}
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeClose: done "));
-
-	SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
-	SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-
-	pAC->MaxPorts--;
-
-	return (0);
-} /* SkGeClose */
-
-
-/*****************************************************************************
- *
- * 	SkGeXmit - Linux frame transmit function
- *
- * Description:
- *	The system calls this function to send frames onto the wire.
- *	It puts the frame in the tx descriptor ring. If the ring is
- *	full then, the 'tbusy' flag is set.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- * WARNING: returning 1 in 'tbusy' case caused system crashes (double
- *	allocated skb's) !!!
- */
-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
-{
-DEV_NET		*pNet;
-SK_AC		*pAC;
-int			Rc;	/* return code of XmitFrame */
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-
-	if ((!skb_shinfo(skb)->nr_frags) ||
-		(pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
-		/* Don't activate scatter-gather and hardware checksum */
-
-		if (pAC->RlmtNets == 2)
-			Rc = XmitFrame(
-				pAC,
-				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
-				skb);
-		else
-			Rc = XmitFrame(
-				pAC,
-				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
-				skb);
-	} else {
-		/* scatter-gather and hardware TCP checksumming anabled*/
-		if (pAC->RlmtNets == 2)
-			Rc = XmitFrameSG(
-				pAC,
-				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
-				skb);
-		else
-			Rc = XmitFrameSG(
-				pAC,
-				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
-				skb);
-	}
-
-	/* Transmitter out of resources? */
-	if (Rc <= 0) {
-		netif_stop_queue(dev);
-	}
-
-	/* If not taken, give buffer ownership back to the
-	 * queueing layer.
-	 */
-	if (Rc < 0)
-		return (1);
-
-	dev->trans_start = jiffies;
-	return (0);
-} /* SkGeXmit */
-
-
-/*****************************************************************************
- *
- * 	XmitFrame - fill one socket buffer into the transmit ring
- *
- * Description:
- *	This function puts a message into the transmit descriptor ring
- *	if there is a descriptors left.
- *	Linux skb's consist of only one continuous buffer.
- *	The first step locks the ring. It is held locked
- *	all time to avoid problems with SWITCH_../PORT_RESET.
- *	Then the descriptoris allocated.
- *	The second part is linking the buffer to the descriptor.
- *	At the very last, the Control field of the descriptor
- *	is made valid for the BMU and a start TX command is given
- *	if necessary.
- *
- * Returns:
- *	> 0 - on succes: the number of bytes in the message
- *	= 0 - on resource shortage: this frame sent or dropped, now
- *		the ring is full ( -> set tbusy)
- *	< 0 - on failure: other problems ( -> return failure to upper layers)
- */
-static int XmitFrame(
-SK_AC 		*pAC,		/* pointer to adapter context           */
-TX_PORT		*pTxPort,	/* pointer to struct of port to send to */
-struct sk_buff	*pMessage)	/* pointer to send-message              */
-{
-	TXD		*pTxd;		/* the rxd to fill */
-	TXD		*pOldTxd;
-	unsigned long	 Flags;
-	SK_U64		 PhysAddr;
-	int		 BytesSend = pMessage->len;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
-
-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-#ifndef USE_TX_COMPLETE
-	FreeTxDescriptors(pAC, pTxPort);
-#endif
-	if (pTxPort->TxdRingFree == 0) {
-		/* 
-		** no enough free descriptors in ring at the moment.
-		** Maybe free'ing some old one help?
-		*/
-		FreeTxDescriptors(pAC, pTxPort);
-		if (pTxPort->TxdRingFree == 0) {
-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_TX_PROGRESS,
-				("XmitFrame failed\n"));
-			/* 
-			** the desired message can not be sent
-			** Because tbusy seems to be set, the message 
-			** should not be freed here. It will be used 
-			** by the scheduler of the ethernet handler 
-			*/
-			return (-1);
-		}
-	}
-
-	/*
-	** If the passed socket buffer is of smaller MTU-size than 60,
-	** copy everything into new buffer and fill all bytes between
-	** the original packet end and the new packet end of 60 with 0x00.
-	** This is to resolve faulty padding by the HW with 0xaa bytes.
-	*/
-	if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
-		if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-			return 0;
-		}
-		pMessage->len = C_LEN_ETHERNET_MINSIZE;
-	}
-
-	/* 
-	** advance head counter behind descriptor needed for this frame, 
-	** so that needed descriptor is reserved from that on. The next
-	** action will be to add the passed buffer to the TX-descriptor
-	*/
-	pTxd = pTxPort->pTxdRingHead;
-	pTxPort->pTxdRingHead = pTxd->pNextTxd;
-	pTxPort->TxdRingFree--;
-
-#ifdef SK_DUMP_TX
-	DumpMsg(pMessage, "XmitFrame");
-#endif
-
-	/* 
-	** First step is to map the data to be sent via the adapter onto
-	** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
-	** and 2.6 need to use pci_map_page() for that mapping.
-	*/
-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
-					virt_to_page(pMessage->data),
-					((unsigned long) pMessage->data & ~PAGE_MASK),
-					pMessage->len,
-					PCI_DMA_TODEVICE);
-	pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
-	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-	pTxd->pMBuf     = pMessage;
-
-	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
-		u16 hdrlen = skb_transport_offset(pMessage);
-		u16 offset = hdrlen + pMessage->csum_offset;
-
-		if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
-			(pAC->GIni.GIChipRev == 0) &&
-			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
-			pTxd->TBControl = BMU_TCP_CHECK;
-		} else {
-			pTxd->TBControl = BMU_UDP_CHECK;
-		}
-
-		pTxd->TcpSumOfs = 0;
-		pTxd->TcpSumSt  = hdrlen;
-		pTxd->TcpSumWr  = offset;
-
-		pTxd->TBControl |= BMU_OWN | BMU_STF | 
-				   BMU_SW  | BMU_EOF |
-#ifdef USE_TX_COMPLETE
-				   BMU_IRQ_EOF |
-#endif
-				   pMessage->len;
-        } else {
-		pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK | 
-				  BMU_SW  | BMU_EOF |
-#ifdef USE_TX_COMPLETE
-				   BMU_IRQ_EOF |
-#endif
-			pMessage->len;
-	}
-
-	/* 
-	** If previous descriptor already done, give TX start cmd 
-	*/
-	pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
-	if ((pOldTxd->TBControl & BMU_OWN) == 0) {
-		SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
-	}	
-
-	/* 
-	** after releasing the lock, the skb may immediately be free'd 
-	*/
-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-	if (pTxPort->TxdRingFree != 0) {
-		return (BytesSend);
-	} else {
-		return (0);
-	}
-
-} /* XmitFrame */
-
-/*****************************************************************************
- *
- * 	XmitFrameSG - fill one socket buffer into the transmit ring
- *                (use SG and TCP/UDP hardware checksumming)
- *
- * Description:
- *	This function puts a message into the transmit descriptor ring
- *	if there is a descriptors left.
- *
- * Returns:
- *	> 0 - on succes: the number of bytes in the message
- *	= 0 - on resource shortage: this frame sent or dropped, now
- *		the ring is full ( -> set tbusy)
- *	< 0 - on failure: other problems ( -> return failure to upper layers)
- */
-static int XmitFrameSG(
-SK_AC 		*pAC,		/* pointer to adapter context           */
-TX_PORT		*pTxPort,	/* pointer to struct of port to send to */
-struct sk_buff	*pMessage)	/* pointer to send-message              */
-{
-
-	TXD		*pTxd;
-	TXD		*pTxdFst;
-	TXD		*pTxdLst;
-	int 	 	 CurrFrag;
-	int		 BytesSend;
-	skb_frag_t	*sk_frag;
-	SK_U64		 PhysAddr;
-	unsigned long	 Flags;
-	SK_U32		 Control;
-
-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-#ifndef USE_TX_COMPLETE
-	FreeTxDescriptors(pAC, pTxPort);
-#endif
-	if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
-		FreeTxDescriptors(pAC, pTxPort);
-		if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_TX_PROGRESS,
-				("XmitFrameSG failed - Ring full\n"));
-				/* this message can not be sent now */
-			return(-1);
-		}
-	}
-
-	pTxd      = pTxPort->pTxdRingHead;
-	pTxdFst   = pTxd;
-	pTxdLst   = pTxd;
-	BytesSend = 0;
-
-	/* 
-	** Map the first fragment (header) into the DMA-space
-	*/
-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
-			virt_to_page(pMessage->data),
-			((unsigned long) pMessage->data & ~PAGE_MASK),
-			skb_headlen(pMessage),
-			PCI_DMA_TODEVICE);
-
-	pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
-	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-
-	/* 
-	** Does the HW need to evaluate checksum for TCP or UDP packets? 
-	*/
-	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
-		u16 hdrlen = skb_transport_offset(pMessage);
-		u16 offset = hdrlen + pMessage->csum_offset;
-
-		Control = BMU_STFWD;
-
-		/* 
-		** We have to use the opcode for tcp here,  because the
-		** opcode for udp is not working in the hardware yet 
-		** (Revision 2.0)
-		*/
-		if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
-			(pAC->GIni.GIChipRev == 0) &&
-			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
-			Control |= BMU_TCP_CHECK;
-		} else {
-			Control |= BMU_UDP_CHECK;
-		}
-
-		pTxd->TcpSumOfs = 0;
-		pTxd->TcpSumSt  = hdrlen;
-		pTxd->TcpSumWr  = offset;
-	} else
-		Control = BMU_CHECK | BMU_SW;
-
-	pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
-
-	pTxd = pTxd->pNextTxd;
-	pTxPort->TxdRingFree--;
-	BytesSend += skb_headlen(pMessage);
-
-	/* 
-	** Browse over all SG fragments and map each of them into the DMA space
-	*/
-	for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
-		sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
-		/* 
-		** we already have the proper value in entry
-		*/
-		PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
-						 sk_frag->page,
-						 sk_frag->page_offset,
-						 sk_frag->size,
-						 PCI_DMA_TODEVICE);
-
-		pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
-		pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-		pTxd->pMBuf     = pMessage;
-		
-		pTxd->TBControl = Control | BMU_OWN | sk_frag->size;
-
-		/* 
-		** Do we have the last fragment? 
-		*/
-		if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags )  {
-#ifdef USE_TX_COMPLETE
-			pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
-#else
-			pTxd->TBControl |= BMU_EOF;
-#endif
-			pTxdFst->TBControl |= BMU_OWN | BMU_SW;
-		}
-		pTxdLst = pTxd;
-		pTxd    = pTxd->pNextTxd;
-		pTxPort->TxdRingFree--;
-		BytesSend += sk_frag->size;
-	}
-
-	/* 
-	** If previous descriptor already done, give TX start cmd 
-	*/
-	if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
-		SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
-	}
-
-	pTxPort->pTxdRingPrev = pTxdLst;
-	pTxPort->pTxdRingHead = pTxd;
-
-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-
-	if (pTxPort->TxdRingFree > 0) {
-		return (BytesSend);
-	} else {
-		return (0);
-	}
-}
-
-/*****************************************************************************
- *
- * 	FreeTxDescriptors - release descriptors from the descriptor ring
- *
- * Description:
- *	This function releases descriptors from a transmit ring if they
- *	have been sent by the BMU.
- *	If a descriptors is sent, it can be freed and the message can
- *	be freed, too.
- *	The SOFTWARE controllable bit is used to prevent running around a
- *	completely free ring for ever. If this bit is no set in the
- *	frame (by XmitFrame), this frame has never been sent or is
- *	already freed.
- *	The Tx descriptor ring lock must be held while calling this function !!!
- *
- * Returns:
- *	none
- */
-static void FreeTxDescriptors(
-SK_AC	*pAC,		/* pointer to the adapter context */
-TX_PORT	*pTxPort)	/* pointer to destination port structure */
-{
-TXD	*pTxd;		/* pointer to the checked descriptor */
-TXD	*pNewTail;	/* pointer to 'end' of the ring */
-SK_U32	Control;	/* TBControl field of descriptor */
-SK_U64	PhysAddr;	/* address of DMA mapping */
-
-	pNewTail = pTxPort->pTxdRingTail;
-	pTxd     = pNewTail;
-	/*
-	** loop forever; exits if BMU_SW bit not set in start frame
-	** or BMU_OWN bit set in any frame
-	*/
-	while (1) {
-		Control = pTxd->TBControl;
-		if ((Control & BMU_SW) == 0) {
-			/*
-			** software controllable bit is set in first
-			** fragment when given to BMU. Not set means that
-			** this fragment was never sent or is already
-			** freed ( -> ring completely free now).
-			*/
-			pTxPort->pTxdRingTail = pTxd;
-			netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
-			return;
-		}
-		if (Control & BMU_OWN) {
-			pTxPort->pTxdRingTail = pTxd;
-			if (pTxPort->TxdRingFree > 0) {
-				netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
-			}
-			return;
-		}
-		
-		/* 
-		** release the DMA mapping, because until not unmapped
-		** this buffer is considered being under control of the
-		** adapter card!
-		*/
-		PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
-		PhysAddr |= (SK_U64) pTxd->VDataLow;
-		pci_unmap_page(pAC->PciDev, PhysAddr,
-				 pTxd->pMBuf->len,
-				 PCI_DMA_TODEVICE);
-
-		if (Control & BMU_EOF)
-			DEV_KFREE_SKB_ANY(pTxd->pMBuf);	/* free message */
-
-		pTxPort->TxdRingFree++;
-		pTxd->TBControl &= ~BMU_SW;
-		pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
-	} /* while(forever) */
-} /* FreeTxDescriptors */
-
-/*****************************************************************************
- *
- * 	FillRxRing - fill the receive ring with valid descriptors
- *
- * Description:
- *	This function fills the receive ring descriptors with data
- *	segments and makes them valid for the BMU.
- *	The active ring is filled completely, if possible.
- *	The non-active ring is filled only partial to save memory.
- *
- * Description of rx ring structure:
- *	head - points to the descriptor which will be used next by the BMU
- *	tail - points to the next descriptor to give to the BMU
- *	
- * Returns:	N/A
- */
-static void FillRxRing(
-SK_AC		*pAC,		/* pointer to the adapter context */
-RX_PORT		*pRxPort)	/* ptr to port struct for which the ring
-				   should be filled */
-{
-unsigned long	Flags;
-
-	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
-	while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {
-		if(!FillRxDescriptor(pAC, pRxPort))
-			break;
-	}
-	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* FillRxRing */
-
-
-/*****************************************************************************
- *
- * 	FillRxDescriptor - fill one buffer into the receive ring
- *
- * Description:
- *	The function allocates a new receive buffer and
- *	puts it into the next descriptor.
- *
- * Returns:
- *	SK_TRUE - a buffer was added to the ring
- *	SK_FALSE - a buffer could not be added
- */
-static SK_BOOL FillRxDescriptor(
-SK_AC		*pAC,		/* pointer to the adapter context struct */
-RX_PORT		*pRxPort)	/* ptr to port struct of ring to fill */
-{
-struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
-RXD		*pRxd;		/* the rxd to fill */
-SK_U16		Length;		/* data fragment length */
-SK_U64		PhysAddr;	/* physical address of a rx buffer */
-
-	pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);
-	if (pMsgBlock == NULL) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-			SK_DBGCAT_DRV_ENTRY,
-			("%s: Allocation of rx buffer failed !\n",
-			pAC->dev[pRxPort->PortIndex]->name));
-		SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);
-		return(SK_FALSE);
-	}
-	skb_reserve(pMsgBlock, 2); /* to align IP frames */
-	/* skb allocated ok, so add buffer */
-	pRxd = pRxPort->pRxdRingTail;
-	pRxPort->pRxdRingTail = pRxd->pNextRxd;
-	pRxPort->RxdRingFree--;
-	Length = pAC->RxBufSize;
-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
-		virt_to_page(pMsgBlock->data),
-		((unsigned long) pMsgBlock->data &
-		~PAGE_MASK),
-		pAC->RxBufSize - 2,
-		PCI_DMA_FROMDEVICE);
-
-	pRxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
-	pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-	pRxd->pMBuf     = pMsgBlock;
-	pRxd->RBControl = BMU_OWN       | 
-			  BMU_STF       | 
-			  BMU_IRQ_EOF   | 
-			  BMU_TCP_CHECK | 
-			  Length;
-	return (SK_TRUE);
-
-} /* FillRxDescriptor */
-
-
-/*****************************************************************************
- *
- * 	ReQueueRxBuffer - fill one buffer back into the receive ring
- *
- * Description:
- *	Fill a given buffer back into the rx ring. The buffer
- *	has been previously allocated and aligned, and its phys.
- *	address calculated, so this is no more necessary.
- *
- * Returns: N/A
- */
-static void ReQueueRxBuffer(
-SK_AC		*pAC,		/* pointer to the adapter context struct */
-RX_PORT		*pRxPort,	/* ptr to port struct of ring to fill */
-struct sk_buff	*pMsg,		/* pointer to the buffer */
-SK_U32		PhysHigh,	/* phys address high dword */
-SK_U32		PhysLow)	/* phys address low dword */
-{
-RXD		*pRxd;		/* the rxd to fill */
-SK_U16		Length;		/* data fragment length */
-
-	pRxd = pRxPort->pRxdRingTail;
-	pRxPort->pRxdRingTail = pRxd->pNextRxd;
-	pRxPort->RxdRingFree--;
-	Length = pAC->RxBufSize;
-
-	pRxd->VDataLow  = PhysLow;
-	pRxd->VDataHigh = PhysHigh;
-	pRxd->pMBuf     = pMsg;
-	pRxd->RBControl = BMU_OWN       | 
-			  BMU_STF       |
-			  BMU_IRQ_EOF   | 
-			  BMU_TCP_CHECK | 
-			  Length;
-	return;
-} /* ReQueueRxBuffer */
-
-/*****************************************************************************
- *
- * 	ReceiveIrq - handle a receive IRQ
- *
- * Description:
- *	This function is called when a receive IRQ is set.
- *	It walks the receive descriptor ring and sends up all
- *	frames that are complete.
- *
- * Returns:	N/A
- */
-static void ReceiveIrq(
-	SK_AC		*pAC,			/* pointer to adapter context */
-	RX_PORT		*pRxPort,		/* pointer to receive port struct */
-	SK_BOOL		SlowPathLock)	/* indicates if SlowPathLock is needed */
-{
-RXD				*pRxd;			/* pointer to receive descriptors */
-SK_U32			Control;		/* control field of descriptor */
-struct sk_buff	*pMsg;			/* pointer to message holding frame */
-struct sk_buff	*pNewMsg;		/* pointer to a new message for copying frame */
-int				FrameLength;	/* total length of received frame */
-SK_MBUF			*pRlmtMbuf;		/* ptr to a buffer for giving a frame to rlmt */
-SK_EVPARA		EvPara;			/* an event parameter union */	
-unsigned long	Flags;			/* for spin lock */
-int				PortIndex = pRxPort->PortIndex;
-unsigned int	Offset;
-unsigned int	NumBytes;
-unsigned int	ForRlmt;
-SK_BOOL			IsBc;
-SK_BOOL			IsMc;
-SK_BOOL  IsBadFrame; 			/* Bad frame */
-
-SK_U32			FrameStat;
-SK_U64			PhysAddr;
-
-rx_start:	
-	/* do forever; exit if BMU_OWN found */
-	for ( pRxd = pRxPort->pRxdRingHead ;
-		  pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
-		  pRxd = pRxd->pNextRxd,
-		  pRxPort->pRxdRingHead = pRxd,
-		  pRxPort->RxdRingFree ++) {
-
-		/*
-		 * For a better understanding of this loop
-		 * Go through every descriptor beginning at the head
-		 * Please note: the ring might be completely received so the OWN bit
-		 * set is not a good crirteria to leave that loop.
-		 * Therefore the RingFree counter is used.
-		 * On entry of this loop pRxd is a pointer to the Rxd that needs
-		 * to be checked next.
-		 */
-
-		Control = pRxd->RBControl;
-	
-		/* check if this descriptor is ready */
-		if ((Control & BMU_OWN) != 0) {
-			/* this descriptor is not yet ready */
-			/* This is the usual end of the loop */
-			/* We don't need to start the ring again */
-			FillRxRing(pAC, pRxPort);
-			return;
-		}
-                pAC->DynIrqModInfo.NbrProcessedDescr++;
-
-		/* get length of frame and check it */
-		FrameLength = Control & BMU_BBC;
-		if (FrameLength > pAC->RxBufSize) {
-			goto rx_failed;
-		}
-
-		/* check for STF and EOF */
-		if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
-			goto rx_failed;
-		}
-
-		/* here we have a complete frame in the ring */
-		pMsg = pRxd->pMBuf;
-
-		FrameStat = pRxd->FrameStat;
-
-		/* check for frame length mismatch */
-#define XMR_FS_LEN_SHIFT        18
-#define GMR_FS_LEN_SHIFT        16
-		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-			if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("skge: Frame length mismatch (%u/%u).\n",
-					FrameLength,
-					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
-				goto rx_failed;
-			}
-		}
-		else {
-			if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("skge: Frame length mismatch (%u/%u).\n",
-					FrameLength,
-					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
-				goto rx_failed;
-			}
-		}
-
-		/* Set Rx Status */
-		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-			IsBc = (FrameStat & XMR_FS_BC) != 0;
-			IsMc = (FrameStat & XMR_FS_MC) != 0;
-			IsBadFrame = (FrameStat &
-				(XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
-		} else {
-			IsBc = (FrameStat & GMR_FS_BC) != 0;
-			IsMc = (FrameStat & GMR_FS_MC) != 0;
-			IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
-							((FrameStat & GMR_FS_RX_OK) == 0));
-		}
-
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
-			("Received frame of length %d on port %d\n",
-			FrameLength, PortIndex));
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
-			("Number of free rx descriptors: %d\n",
-			pRxPort->RxdRingFree));
-/* DumpMsg(pMsg, "Rx");	*/
-
-		if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
-#if 0
-			(FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
-#endif
-			/* there is a receive error in this frame */
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_RX_PROGRESS,
-				("skge: Error in received frame, dropped!\n"
-				"Control: %x\nRxStat: %x\n",
-				Control, FrameStat));
-
-			ReQueueRxBuffer(pAC, pRxPort, pMsg,
-				pRxd->VDataHigh, pRxd->VDataLow);
-
-			continue;
-		}
-
-		/*
-		 * if short frame then copy data to reduce memory waste
-		 */
-		if ((FrameLength < SK_COPY_THRESHOLD) &&
-			((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {
-			/*
-			 * Short frame detected and allocation successfull
-			 */
-			/* use new skb and copy data */
-			skb_reserve(pNewMsg, 2);
-			skb_put(pNewMsg, FrameLength);
-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-			PhysAddr |= (SK_U64) pRxd->VDataLow;
-
-			pci_dma_sync_single_for_cpu(pAC->PciDev,
-						    (dma_addr_t) PhysAddr,
-						    FrameLength,
-						    PCI_DMA_FROMDEVICE);
-			skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength);
-
-			pci_dma_sync_single_for_device(pAC->PciDev,
-						       (dma_addr_t) PhysAddr,
-						       FrameLength,
-						       PCI_DMA_FROMDEVICE);
-			ReQueueRxBuffer(pAC, pRxPort, pMsg,
-				pRxd->VDataHigh, pRxd->VDataLow);
-
-			pMsg = pNewMsg;
-
-		}
-		else {
-			/*
-			 * if large frame, or SKB allocation failed, pass
-			 * the SKB directly to the networking
-			 */
-
-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-			PhysAddr |= (SK_U64) pRxd->VDataLow;
-
-			/* release the DMA mapping */
-			pci_unmap_single(pAC->PciDev,
-					 PhysAddr,
-					 pAC->RxBufSize - 2,
-					 PCI_DMA_FROMDEVICE);
-
-			/* set length in message */
-			skb_put(pMsg, FrameLength);
-		} /* frame > SK_COPY_TRESHOLD */
-
-#ifdef USE_SK_RX_CHECKSUM
-		pMsg->csum = pRxd->TcpSums & 0xffff;
-		pMsg->ip_summed = CHECKSUM_COMPLETE;
-#else
-		pMsg->ip_summed = CHECKSUM_NONE;
-#endif
-
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("V"));
-		ForRlmt = SK_RLMT_RX_PROTOCOL;
-#if 0
-		IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
-#endif
-		SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
-			IsBc, &Offset, &NumBytes);
-		if (NumBytes != 0) {
-#if 0
-			IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
-#endif
-			SK_RLMT_LOOKAHEAD(pAC, PortIndex,
-				&pMsg->data[Offset],
-				IsBc, IsMc, &ForRlmt);
-		}
-		if (ForRlmt == SK_RLMT_RX_PROTOCOL) {
-					SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("W"));
-			/* send up only frames from active port */
-			if ((PortIndex == pAC->ActivePort) ||
-				(pAC->RlmtNets == 2)) {
-				/* frame for upper layer */
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
-#ifdef xDEBUG
-				DumpMsg(pMsg, "Rx");
-#endif
-				SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
-					FrameLength, pRxPort->PortIndex);
-
-				pMsg->protocol = eth_type_trans(pMsg,
-					pAC->dev[pRxPort->PortIndex]);
-				netif_rx(pMsg);
-				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
-			}
-			else {
-				/* drop frame */
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("D"));
-				DEV_KFREE_SKB(pMsg);
-			}
-			
-		} /* if not for rlmt */
-		else {
-			/* packet for rlmt */
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
-			pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
-				pAC->IoBase, FrameLength);
-			if (pRlmtMbuf != NULL) {
-				pRlmtMbuf->pNext = NULL;
-				pRlmtMbuf->Length = FrameLength;
-				pRlmtMbuf->PortIdx = PortIndex;
-				EvPara.pParaPtr = pRlmtMbuf;
-				memcpy((char*)(pRlmtMbuf->pData),
-					   (char*)(pMsg->data),
-					   FrameLength);
-
-				/* SlowPathLock needed? */
-				if (SlowPathLock == SK_TRUE) {
-					spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-					SkEventQueue(pAC, SKGE_RLMT,
-						SK_RLMT_PACKET_RECEIVED,
-						EvPara);
-					pAC->CheckQueue = SK_TRUE;
-					spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-				} else {
-					SkEventQueue(pAC, SKGE_RLMT,
-						SK_RLMT_PACKET_RECEIVED,
-						EvPara);
-					pAC->CheckQueue = SK_TRUE;
-				}
-
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("Q"));
-			}
-			if ((pAC->dev[pRxPort->PortIndex]->flags &
-				(IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
-				(ForRlmt & SK_RLMT_RX_PROTOCOL) ==
-				SK_RLMT_RX_PROTOCOL) {
-				pMsg->protocol = eth_type_trans(pMsg,
-					pAC->dev[pRxPort->PortIndex]);
-				netif_rx(pMsg);
-				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
-			}
-			else {
-				DEV_KFREE_SKB(pMsg);
-			}
-
-		} /* if packet for rlmt */
-	} /* for ... scanning the RXD ring */
-
-	/* RXD ring is empty -> fill and restart */
-	FillRxRing(pAC, pRxPort);
-	/* do not start if called from Close */
-	if (pAC->BoardLevel > SK_INIT_DATA) {
-		ClearAndStartRx(pAC, PortIndex);
-	}
-	return;
-
-rx_failed:
-	/* remove error frame */
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
-		("Schrottdescriptor, length: 0x%x\n", FrameLength));
-
-	/* release the DMA mapping */
-
-	PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-	PhysAddr |= (SK_U64) pRxd->VDataLow;
-	pci_unmap_page(pAC->PciDev,
-			 PhysAddr,
-			 pAC->RxBufSize - 2,
-			 PCI_DMA_FROMDEVICE);
-	DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
-	pRxd->pMBuf = NULL;
-	pRxPort->RxdRingFree++;
-	pRxPort->pRxdRingHead = pRxd->pNextRxd;
-	goto rx_start;
-
-} /* ReceiveIrq */
-
-
-/*****************************************************************************
- *
- * 	ClearAndStartRx - give a start receive command to BMU, clear IRQ
- *
- * Description:
- *	This function sends a start command and a clear interrupt
- *	command for one receive queue to the BMU.
- *
- * Returns: N/A
- *	none
- */
-static void ClearAndStartRx(
-SK_AC	*pAC,		/* pointer to the adapter context */
-int	PortIndex)	/* index of the receive port (XMAC) */
-{
-	SK_OUT8(pAC->IoBase,
-		RxQueueAddr[PortIndex]+Q_CSR,
-		CSR_START | CSR_IRQ_CL_F);
-} /* ClearAndStartRx */
-
-
-/*****************************************************************************
- *
- * 	ClearTxIrq - give a clear transmit IRQ command to BMU
- *
- * Description:
- *	This function sends a clear tx IRQ command for one
- *	transmit queue to the BMU.
- *
- * Returns: N/A
- */
-static void ClearTxIrq(
-SK_AC	*pAC,		/* pointer to the adapter context */
-int	PortIndex,	/* index of the transmit port (XMAC) */
-int	Prio)		/* priority or normal queue */
-{
-	SK_OUT8(pAC->IoBase, 
-		TxQueueAddr[PortIndex][Prio]+Q_CSR,
-		CSR_IRQ_CL_F);
-} /* ClearTxIrq */
-
-
-/*****************************************************************************
- *
- * 	ClearRxRing - remove all buffers from the receive ring
- *
- * Description:
- *	This function removes all receive buffers from the ring.
- *	The receive BMU must be stopped before calling this function.
- *
- * Returns: N/A
- */
-static void ClearRxRing(
-SK_AC	*pAC,		/* pointer to adapter context */
-RX_PORT	*pRxPort)	/* pointer to rx port struct */
-{
-RXD		*pRxd;	/* pointer to the current descriptor */
-unsigned long	Flags;
-SK_U64		PhysAddr;
-
-	if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
-		return;
-	}
-	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
-	pRxd = pRxPort->pRxdRingHead;
-	do {
-		if (pRxd->pMBuf != NULL) {
-
-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-			PhysAddr |= (SK_U64) pRxd->VDataLow;
-			pci_unmap_page(pAC->PciDev,
-					 PhysAddr,
-					 pAC->RxBufSize - 2,
-					 PCI_DMA_FROMDEVICE);
-			DEV_KFREE_SKB(pRxd->pMBuf);
-			pRxd->pMBuf = NULL;
-		}
-		pRxd->RBControl &= BMU_OWN;
-		pRxd = pRxd->pNextRxd;
-		pRxPort->RxdRingFree++;
-	} while (pRxd != pRxPort->pRxdRingTail);
-	pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;
-	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* ClearRxRing */
-
-/*****************************************************************************
- *
- *	ClearTxRing - remove all buffers from the transmit ring
- *
- * Description:
- *	This function removes all transmit buffers from the ring.
- *	The transmit BMU must be stopped before calling this function
- *	and transmitting at the upper level must be disabled.
- *	The BMU own bit of all descriptors is cleared, the rest is
- *	done by calling FreeTxDescriptors.
- *
- * Returns: N/A
- */
-static void ClearTxRing(
-SK_AC	*pAC,		/* pointer to adapter context */
-TX_PORT	*pTxPort)	/* pointer to tx prt struct */
-{
-TXD		*pTxd;		/* pointer to the current descriptor */
-int		i;
-unsigned long	Flags;
-
-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-	pTxd = pTxPort->pTxdRingHead;
-	for (i=0; i<pAC->TxDescrPerRing; i++) {
-		pTxd->TBControl &= ~BMU_OWN;
-		pTxd = pTxd->pNextTxd;
-	}
-	FreeTxDescriptors(pAC, pTxPort);
-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-} /* ClearTxRing */
-
-/*****************************************************************************
- *
- * 	SkGeSetMacAddr - Set the hardware MAC address
- *
- * Description:
- *	This function sets the MAC address used by the adapter.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
-{
-
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC	*pAC = pNet->pAC;
-
-struct sockaddr	*addr = p;
-unsigned long	Flags;
-	
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeSetMacAddr starts now...\n"));
-	if(netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
-	
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
-	if (pAC->RlmtNets == 2)
-		SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
-			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
-	else
-		SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
-			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
-
-	
-	
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	return 0;
-} /* SkGeSetMacAddr */
-
-
-/*****************************************************************************
- *
- * 	SkGeSetRxMode - set receive mode
- *
- * Description:
- *	This function sets the receive mode of an adapter. The adapter
- *	supports promiscuous mode, allmulticast mode and a number of
- *	multicast addresses. If more multicast addresses the available
- *	are selected, a hash function in the hardware is used.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
-{
-
-DEV_NET		*pNet;
-SK_AC		*pAC;
-
-struct dev_mc_list	*pMcList;
-int			i;
-int			PortIdx;
-unsigned long		Flags;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeSetRxMode starts now... "));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	if (pAC->RlmtNets == 1)
-		PortIdx = pAC->ActivePort;
-	else
-		PortIdx = pNet->NetNr;
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	if (dev->flags & IFF_PROMISC) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("PROMISCUOUS mode\n"));
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_LLC);
-	} else if (dev->flags & IFF_ALLMULTI) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("ALLMULTI mode\n"));
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_ALL_MC);
-	} else {
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_NONE);
-		SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
-
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("Number of MC entries: %d ", dev->mc_count));
-		
-		pMcList = dev->mc_list;
-		for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) {
-			SkAddrMcAdd(pAC, pAC->IoBase, PortIdx,
-				(SK_MAC_ADDR*)pMcList->dmi_addr, 0);
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA,
-				("%02x:%02x:%02x:%02x:%02x:%02x\n",
-				pMcList->dmi_addr[0],
-				pMcList->dmi_addr[1],
-				pMcList->dmi_addr[2],
-				pMcList->dmi_addr[3],
-				pMcList->dmi_addr[4],
-				pMcList->dmi_addr[5]));
-		}
-		SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
-	}
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	
-	return;
-} /* SkGeSetRxMode */
-
-
-/*****************************************************************************
- *
- * 	SkGeChangeMtu - set the MTU to another value
- *
- * Description:
- *	This function sets is called whenever the MTU size is changed
- *	(ifconfig mtu xxx dev ethX). If the MTU is bigger than standard
- *	ethernet MTU size, long frame support is activated.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
-{
-DEV_NET		*pNet;
-struct net_device *pOtherDev;
-SK_AC		*pAC;
-unsigned long	Flags;
-int		i;
-SK_EVPARA 	EvPara;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeChangeMtu starts now...\n"));
-
-	pNet = netdev_priv(dev);
-	pAC  = pNet->pAC;
-
-	if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
-		return -EINVAL;
-	}
-
-	if(pAC->BoardLevel != SK_INIT_RUN) {
-		return -EINVAL;
-	}
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->DiagFlowCtrl == SK_FALSE) {
-			return -1; /* still in use, deny any actions of MTU */
-		} else {
-			pAC->DiagFlowCtrl = SK_FALSE;
-		}
-	}
-#endif
-
-	pOtherDev = pAC->dev[1 - pNet->NetNr];
-
-	if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
-	     && (NewMtu <= 1500))
-		return 0;
-
-	pAC->RxBufSize = NewMtu + 32;
-	dev->mtu = NewMtu;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("New MTU: %d\n", NewMtu));
-
-	/* 
-	** Prevent any reconfiguration while changing the MTU 
-	** by disabling any interrupts 
-	*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
-	/* 
-	** Notify RLMT that any ports are to be stopped
-	*/
-	EvPara.Para32[0] =  0;
-	EvPara.Para32[1] = -1;
-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		EvPara.Para32[0] =  1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-	} else {
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-	}
-
-	/*
-	** After calling the SkEventDispatcher(), RLMT is aware about
-	** the stopped ports -> configuration can take place!
-	*/
-	SkEventDispatcher(pAC, pAC->IoBase);
-
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
-		netif_stop_queue(pAC->dev[i]);
-
-	}
-
-	/*
-	** Depending on the desired MTU size change, a different number of 
-	** RX buffers need to be allocated
-	*/
-	if (NewMtu > 1500) {
-	    /* 
-	    ** Use less rx buffers 
-	    */
-	    for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		    pAC->RxPort[i].RxFillLimit =  pAC->RxDescrPerRing -
-						 (pAC->RxDescrPerRing / 4);
-		} else {
-		    if (i == pAC->ActivePort) {
-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 
-						    (pAC->RxDescrPerRing / 4);
-		    } else {
-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 
-						    (pAC->RxDescrPerRing / 10);
-		    }
-		}
-	    }
-	} else {
-	    /* 
-	    ** Use the normal amount of rx buffers 
-	    */
-	    for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		    pAC->RxPort[i].RxFillLimit = 1;
-		} else {
-		    if (i == pAC->ActivePort) {
-			pAC->RxPort[i].RxFillLimit = 1;
-		    } else {
-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
-						    (pAC->RxDescrPerRing / 4);
-		    }
-		}
-	    }
-	}
-	
-	SkGeDeInit(pAC, pAC->IoBase);
-
-	/*
-	** enable/disable hardware support for long frames
-	*/
-	if (NewMtu > 1500) {
-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
-		pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
-	} else {
-	    if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		pAC->GIni.GIPortUsage = SK_MUL_LINK;
-	    } else {
-		pAC->GIni.GIPortUsage = SK_RED_LINK;
-	    }
-	}
-
-	SkGeInit(   pAC, pAC->IoBase, SK_INIT_IO);
-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
-	SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
-	
-	/*
-	** tschilling:
-	** Speed and others are set back to default in level 1 init!
-	*/
-	GetConfiguration(pAC);
-	
-	SkGeInit(   pAC, pAC->IoBase, SK_INIT_RUN);
-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_RUN);
-	SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
-
-	/*
-	** clear and reinit the rx rings here
-	*/
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
-		ClearRxRing(pAC, &pAC->RxPort[i]);
-		FillRxRing(pAC, &pAC->RxPort[i]);
-
-		/* 
-		** Enable transmit descriptor polling
-		*/
-		SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
-		FillRxRing(pAC, &pAC->RxPort[i]);
-	};
-
-	SkGeYellowLED(pAC, pAC->IoBase, 1);
-	SkDimEnableModerationIfNeeded(pAC);	
-	SkDimDisplayModerationSettings(pAC);
-
-	netif_start_queue(pAC->dev[pNet->PortNr]);
-	for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
-		spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
-	}
-
-	/* 
-	** Enable Interrupts again 
-	*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
-
-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-	SkEventDispatcher(pAC, pAC->IoBase);
-
-	/* 
-	** Notify RLMT about the changing and restarting one (or more) ports
-	*/
-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		EvPara.Para32[0] = pAC->RlmtNets;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
-		EvPara.Para32[0] = pNet->PortNr;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-			
-		if (netif_running(pOtherDev)) {
-			DEV_NET *pOtherNet = netdev_priv(pOtherDev);
-			EvPara.Para32[0] = pOtherNet->PortNr;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-		}
-	} else {
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-	}
-
-	SkEventDispatcher(pAC, pAC->IoBase);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	
-	/*
-	** While testing this driver with latest kernel 2.5 (2.5.70), it 
-	** seems as if upper layers have a problem to handle a successful
-	** return value of '0'. If such a zero is returned, the complete 
-	** system hangs for several minutes (!), which is in acceptable.
-	**
-	** Currently it is not clear, what the exact reason for this problem
-	** is. The implemented workaround for 2.5 is to return the desired 
-	** new MTU size if all needed changes for the new MTU size where 
-	** performed. In kernels 2.2 and 2.4, a zero value is returned,
-	** which indicates the successful change of the mtu-size.
-	*/
-	return NewMtu;
-
-} /* SkGeChangeMtu */
-
-
-/*****************************************************************************
- *
- * 	SkGeStats - return ethernet device statistics
- *
- * Description:
- *	This function return statistic data about the ethernet device
- *	to the operating system.
- *
- * Returns:
- *	pointer to the statistic structure.
- */
-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
-{
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC	*pAC = pNet->pAC;
-SK_PNMI_STRUCT_DATA *pPnmiStruct;       /* structure for all Pnmi-Data */
-SK_PNMI_STAT    *pPnmiStat;             /* pointer to virtual XMAC stat. data */
-SK_PNMI_CONF    *pPnmiConf;             /* pointer to virtual link config. */
-unsigned int    Size;                   /* size of pnmi struct */
-unsigned long	Flags;			/* for spin lock */
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeStats starts now...\n"));
-	pPnmiStruct = &pAC->PnmiStruct;
-
-#ifdef SK_DIAG_SUPPORT
-        if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
-                (pAC->BoardLevel == SK_INIT_RUN)) {
-#endif
-        SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
-        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-        Size = SK_PNMI_STRUCT_SIZE;
-		SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
-        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-#ifdef SK_DIAG_SUPPORT
-	}
-#endif
-
-        pPnmiStat = &pPnmiStruct->Stat[0];
-        pPnmiConf = &pPnmiStruct->Conf[0];
-
-	pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF;
-	pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
-	pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
-	pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
-	
-        if (dev->mtu <= 1500) {
-                pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
-        } else {
-                pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
-                        pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
-	}
-
-
-	if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
-		pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
-
-	pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
-	pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
-	pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
-	pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF;
-	pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
-
-	/* detailed rx_errors: */
-	pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF;
-	pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
-	pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF;
-	pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF;
-	pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
-	pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF;
-
-	/* detailed tx_errors */
-	pAC->stats.tx_aborted_errors = (SK_U32) 0;
-	pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
-	pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF;
-	pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
-	pAC->stats.tx_window_errors = (SK_U32) 0;
-
-	return(&pAC->stats);
-} /* SkGeStats */
-
-/*
- * Basic MII register access
- */
-static int SkGeMiiIoctl(struct net_device *dev,
-			struct mii_ioctl_data *data, int cmd)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_IOC IoC = pAC->IoBase;
-	int Port = pNet->PortNr;
-	SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
-	unsigned long Flags;
-	int err = 0;
-	int reg = data->reg_num & 0x1f;
-	SK_U16 val = data->val_in;
-
-	if (!netif_running(dev))
-		return -ENODEV;	/* Phy still in reset */
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	switch(cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = pPrt->PhyAddr;
-
-		/* fallthru */
-	case SIOCGMIIREG:
-		if (pAC->GIni.GIGenesis)
-			SkXmPhyRead(pAC, IoC, Port, reg, &val);
-		else
-			SkGmPhyRead(pAC, IoC, Port, reg, &val);
-
-		data->val_out = val;
-		break;
-
-	case SIOCSMIIREG:
-		if (!capable(CAP_NET_ADMIN))
-			err = -EPERM;
-
-		else if (pAC->GIni.GIGenesis)
-			SkXmPhyWrite(pAC, IoC, Port, reg, val);
-		else
-			SkGmPhyWrite(pAC, IoC, Port, reg, val);
-		break;
-	default:
-		err = -EOPNOTSUPP;
-	}
-        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	return err;
-}
-
-
-/*****************************************************************************
- *
- * 	SkGeIoctl - IO-control function
- *
- * Description:
- *	This function is called if an ioctl is issued on the device.
- *	There are three subfunction for reading, writing and test-writing
- *	the private MIB data structure (useful for SysKonnect-internal tools).
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
-{
-DEV_NET		*pNet;
-SK_AC		*pAC;
-void		*pMemBuf;
-struct pci_dev  *pdev = NULL;
-SK_GE_IOCTL	Ioctl;
-unsigned int	Err = 0;
-int		Size = 0;
-int             Ret = 0;
-unsigned int	Length = 0;
-int		HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeIoctl starts now...\n"));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG)
-	    return SkGeMiiIoctl(dev, if_mii(rq), cmd);
-
-	if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
-		return -EFAULT;
-	}
-
-	switch(cmd) {
-	case SK_IOCTL_SETMIB:
-	case SK_IOCTL_PRESETMIB:
-		if (!capable(CAP_NET_ADMIN)) return -EPERM;
- 	case SK_IOCTL_GETMIB:
-		if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
-			Ioctl.Len<sizeof(pAC->PnmiStruct)?
-			Ioctl.Len : sizeof(pAC->PnmiStruct))) {
-			return -EFAULT;
-		}
-		Size = SkGeIocMib(pNet, Ioctl.Len, cmd);
-		if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct,
-			Ioctl.Len<Size? Ioctl.Len : Size)) {
-			return -EFAULT;
-		}
-		Ioctl.Len = Size;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			return -EFAULT;
-		}
-		break;
-	case SK_IOCTL_GEN:
-		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
-			Length = Ioctl.Len;
-		} else {
-			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
-		}
-		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
-			return -ENOMEM;
-		}
-		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		Ioctl.Len = Length;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-fault_gen:
-		kfree(pMemBuf); /* cleanup everything */
-		break;
-#ifdef SK_DIAG_SUPPORT
-       case SK_IOCTL_DIAG:
-		if (!capable(CAP_NET_ADMIN)) return -EPERM;
-		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
-			Length = Ioctl.Len;
-		} else {
-			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
-		}
-		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
-			return -ENOMEM;
-		}
-		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-		pdev = pAC->PciDev;
-		Length = 3 * sizeof(SK_U32);  /* Error, Bus and Device */
-		/* 
-		** While coding this new IOCTL interface, only a few lines of code
-		** are to to be added. Therefore no dedicated function has been 
-		** added. If more functionality is added, a separate function 
-		** should be used...
-		*/
-		* ((SK_U32 *)pMemBuf) = 0;
-		* ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
-		* ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
-		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-		Ioctl.Len = Length;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-fault_diag:
-		kfree(pMemBuf); /* cleanup everything */
-		break;
-#endif
-	default:
-		Err = -EOPNOTSUPP;
-	}
-
-	return(Err);
-
-} /* SkGeIoctl */
-
-
-/*****************************************************************************
- *
- * 	SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message
- *
- * Description:
- *	This function reads/writes the MIB data using PNMI (Private Network
- *	Management Interface).
- *	The destination for the data must be provided with the
- *	ioctl call and is given to the driver in the form of
- *	a user space address.
- *	Copying from the user-provided data area into kernel messages
- *	and back is done by copy_from_user and copy_to_user calls in
- *	SkGeIoctl.
- *
- * Returns:
- *	returned size from PNMI call
- */
-static int SkGeIocMib(
-DEV_NET		*pNet,	/* pointer to the adapter context */
-unsigned int	Size,	/* length of ioctl data */
-int		mode)	/* flag for set/preset */
-{
-unsigned long	Flags;	/* for spin lock */
-SK_AC		*pAC;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeIocMib starts now...\n"));
-	pAC = pNet->pAC;
-	/* access MIB */
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	switch(mode) {
-	case SK_IOCTL_GETMIB:
-		SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	case SK_IOCTL_PRESETMIB:
-		SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	case SK_IOCTL_SETMIB:
-		SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	default:
-		break;
-	}
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("MIB data access succeeded\n"));
-	return (Size);
-} /* SkGeIocMib */
-
-
-/*****************************************************************************
- *
- * 	GetConfiguration - read configuration information
- *
- * Description:
- *	This function reads per-adapter configuration information from
- *	the options provided on the command line.
- *
- * Returns:
- *	none
- */
-static void GetConfiguration(
-SK_AC	*pAC)	/* pointer to the adapter context structure */
-{
-SK_I32	Port;		/* preferred port */
-SK_BOOL	AutoSet;
-SK_BOOL DupSet;
-int	LinkSpeed          = SK_LSPEED_AUTO;	/* Link speed */
-int	AutoNeg            = 1;			/* autoneg off (0) or on (1) */
-int	DuplexCap          = 0;			/* 0=both,1=full,2=half */
-int	FlowCtrl           = SK_FLOW_MODE_SYM_OR_REM;	/* FlowControl  */
-int	MSMode             = SK_MS_MODE_AUTO;	/* master/slave mode    */
-
-SK_BOOL IsConTypeDefined   = SK_TRUE;
-SK_BOOL IsLinkSpeedDefined = SK_TRUE;
-SK_BOOL IsFlowCtrlDefined  = SK_TRUE;
-SK_BOOL IsRoleDefined      = SK_TRUE;
-SK_BOOL IsModeDefined      = SK_TRUE;
-/*
- *	The two parameters AutoNeg. and DuplexCap. map to one configuration
- *	parameter. The mapping is described by this table:
- *	DuplexCap ->	|	both	|	full	|	half	|
- *	AutoNeg		|		|		|		|
- *	-----------------------------------------------------------------
- *	Off		|    illegal	|	Full	|	Half	|
- *	-----------------------------------------------------------------
- *	On		|   AutoBoth	|   AutoFull	|   AutoHalf	|
- *	-----------------------------------------------------------------
- *	Sense		|   AutoSense	|   AutoSense	|   AutoSense	|
- */
-int	Capabilities[3][3] =
-		{ {                -1, SK_LMODE_FULL     , SK_LMODE_HALF     },
-		  {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
-		  {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
-
-#define DC_BOTH	0
-#define DC_FULL 1
-#define DC_HALF 2
-#define AN_OFF	0
-#define AN_ON	1
-#define AN_SENS	2
-#define M_CurrPort pAC->GIni.GP[Port]
-
-
-	/*
-	** Set the default values first for both ports!
-	*/
-	for (Port = 0; Port < SK_MAX_MACS; Port++) {
-		M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
-		M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
-		M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-		M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
-	}
-
-	/*
-	** Check merged parameter ConType. If it has not been used,
-	** verify any other parameter (e.g. AutoNeg) and use default values. 
-	**
-	** Stating both ConType and other lowlevel link parameters is also
-	** possible. If this is the case, the passed ConType-parameter is 
-	** overwritten by the lowlevel link parameter.
-	**
-	** The following settings are used for a merged ConType-parameter:
-	**
-	** ConType   DupCap   AutoNeg   FlowCtrl      Role      Speed
-	** -------   ------   -------   --------   ----------   -----
-	**  Auto      Both      On      SymOrRem      Auto       Auto
-	**  100FD     Full      Off       None      <ignored>    100
-	**  100HD     Half      Off       None      <ignored>    100
-	**  10FD      Full      Off       None      <ignored>    10
-	**  10HD      Half      Off       None      <ignored>    10
-	** 
-	** This ConType parameter is used for all ports of the adapter!
-	*/
-        if ( (ConType != NULL)                && 
-	     (pAC->Index < SK_MAX_CARD_PARAM) &&
-	     (ConType[pAC->Index] != NULL) ) {
-
-			/* Check chipset family */
-			if ((!pAC->ChipsetType) && 
-				(strcmp(ConType[pAC->Index],"Auto")!=0) &&
-				(strcmp(ConType[pAC->Index],"")!=0)) {
-				/* Set the speed parameter back */
-					printk("sk98lin: Illegal value \"%s\" " 
-							"for ConType."
-							" Using Auto.\n", 
-							ConType[pAC->Index]);
-
-					sprintf(ConType[pAC->Index], "Auto");	
-			}
-
-				if (strcmp(ConType[pAC->Index],"")==0) {
-			IsConTypeDefined = SK_FALSE; /* No ConType defined */
-				} else if (strcmp(ConType[pAC->Index],"Auto")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
-		    }
-                } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
-		    }
-                } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
-		    }
-                } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
-		    }
-                } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
-		    }
-                } else { 
-		    printk("sk98lin: Illegal value \"%s\" for ConType\n", 
-			ConType[pAC->Index]);
-		    IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
-		}
-        } else {
-	    IsConTypeDefined = SK_FALSE; /* No ConType defined */
-	}
-
-	/*
-	** Parse any parameter settings for port A:
-	** a) any LinkSpeed stated?
-	*/
-	if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		Speed_A[pAC->Index] != NULL) {
-		if (strcmp(Speed_A[pAC->Index],"")==0) {
-		    IsLinkSpeedDefined = SK_FALSE;
-		} else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
-		    LinkSpeed = SK_LSPEED_AUTO;
-		} else if (strcmp(Speed_A[pAC->Index],"10")==0) {
-		    LinkSpeed = SK_LSPEED_10MBPS;
-		} else if (strcmp(Speed_A[pAC->Index],"100")==0) {
-		    LinkSpeed = SK_LSPEED_100MBPS;
-		} else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
-		    LinkSpeed = SK_LSPEED_1000MBPS;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for Speed_A\n",
-			Speed_A[pAC->Index]);
-		    IsLinkSpeedDefined = SK_FALSE;
-		}
-	} else {
-	    IsLinkSpeedDefined = SK_FALSE;
-	}
-
-	/* 
-	** Check speed parameter: 
-	**    Only copper type adapter and GE V2 cards 
-	*/
-	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
-		((LinkSpeed != SK_LSPEED_AUTO) &&
-		(LinkSpeed != SK_LSPEED_1000MBPS))) {
-		printk("sk98lin: Illegal value for Speed_A. "
-			"Not a copper card or GE V2 card\n    Using "
-			"speed 1000\n");
-		LinkSpeed = SK_LSPEED_1000MBPS;
-	}
-	
-	/*	
-	** Decide whether to set new config value if somethig valid has
-	** been received.
-	*/
-	if (IsLinkSpeedDefined) {
-		pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
-	} 
-
-	/* 
-	** b) Any Autonegotiation and DuplexCapabilities set?
-	**    Please note that both belong together...
-	*/
-	AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
-	AutoSet = SK_FALSE;
-	if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		AutoNeg_A[pAC->Index] != NULL) {
-		AutoSet = SK_TRUE;
-		if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
-		    AutoSet = SK_FALSE;
-		} else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
-		    AutoNeg = AN_ON;
-		} else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
-		    AutoNeg = AN_OFF;
-		} else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
-		    AutoNeg = AN_SENS;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n",
-			AutoNeg_A[pAC->Index]);
-		}
-	}
-
-	DuplexCap = DC_BOTH;
-	DupSet    = SK_FALSE;
-	if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		DupCap_A[pAC->Index] != NULL) {
-		DupSet = SK_TRUE;
-		if (strcmp(DupCap_A[pAC->Index],"")==0) {
-		    DupSet = SK_FALSE;
-		} else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
-		    DuplexCap = DC_BOTH;
-		} else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
-		    DuplexCap = DC_FULL;
-		} else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
-		    DuplexCap = DC_HALF;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for DupCap_A\n",
-			DupCap_A[pAC->Index]);
-		}
-	}
-
-	/* 
-	** Check for illegal combinations 
-	*/
-	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
-		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
-		(DuplexCap == SK_LMODE_STAT_HALF)) &&
-		(pAC->ChipsetType)) {
-		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
-					"    Using Full Duplex.\n");
-				DuplexCap = DC_FULL;
-	}
-
-	if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
-		printk("sk98lin, Port A: DuplexCapabilities"
-			" ignored using Sense mode\n");
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
-		printk("sk98lin: Port A: Illegal combination"
-			" of values AutoNeg. and DuplexCap.\n    Using "
-			"Full Duplex\n");
-		DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
-		DuplexCap = DC_FULL;
-	}
-	
-	if (!AutoSet && DupSet) {
-		printk("sk98lin: Port A: Duplex setting not"
-			" possible in\n    default AutoNegotiation mode"
-			" (Sense).\n    Using AutoNegotiation On\n");
-		AutoNeg = AN_ON;
-	}
-	
-	/* 
-	** set the desired mode 
-	*/
-	if (AutoSet || DupSet) {
-	    pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
-	}
-	
-	/* 
-	** c) Any Flowcontrol-parameter set?
-	*/
-	if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		FlowCtrl_A[pAC->Index] != NULL) {
-		if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
-		    IsFlowCtrlDefined = SK_FALSE;
-		} else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
-		    FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
-		} else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
-		    FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
-		} else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
-		    FlowCtrl = SK_FLOW_MODE_LOC_SEND;
-		} else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
-		    FlowCtrl = SK_FLOW_MODE_NONE;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
-                        FlowCtrl_A[pAC->Index]);
-		    IsFlowCtrlDefined = SK_FALSE;
-		}
-	} else {
-	   IsFlowCtrlDefined = SK_FALSE;
-	}
-
-	if (IsFlowCtrlDefined) {
-	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
-		printk("sk98lin: Port A: FlowControl"
-			" impossible without AutoNegotiation,"
-			" disabled\n");
-		FlowCtrl = SK_FLOW_MODE_NONE;
-	    }
-	    pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
-	}
-
-	/*
-	** d) What is with the RoleParameter?
-	*/
-	if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		Role_A[pAC->Index] != NULL) {
-		if (strcmp(Role_A[pAC->Index],"")==0) {
-		   IsRoleDefined = SK_FALSE;
-		} else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
-		    MSMode = SK_MS_MODE_AUTO;
-		} else if (strcmp(Role_A[pAC->Index],"Master")==0) {
-		    MSMode = SK_MS_MODE_MASTER;
-		} else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
-		    MSMode = SK_MS_MODE_SLAVE;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for Role_A\n",
-			Role_A[pAC->Index]);
-		    IsRoleDefined = SK_FALSE;
-		}
-	} else {
-	   IsRoleDefined = SK_FALSE;
-	}
-
-	if (IsRoleDefined == SK_TRUE) {
-	    pAC->GIni.GP[0].PMSMode = MSMode;
-	}
-	
-
-	
-	/* 
-	** Parse any parameter settings for port B:
-	** a) any LinkSpeed stated?
-	*/
-	IsConTypeDefined   = SK_TRUE;
-	IsLinkSpeedDefined = SK_TRUE;
-	IsFlowCtrlDefined  = SK_TRUE;
-	IsModeDefined      = SK_TRUE;
-
-	if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		Speed_B[pAC->Index] != NULL) {
-		if (strcmp(Speed_B[pAC->Index],"")==0) {
-		    IsLinkSpeedDefined = SK_FALSE;
-		} else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
-		    LinkSpeed = SK_LSPEED_AUTO;
-		} else if (strcmp(Speed_B[pAC->Index],"10")==0) {
-		    LinkSpeed = SK_LSPEED_10MBPS;
-		} else if (strcmp(Speed_B[pAC->Index],"100")==0) {
-		    LinkSpeed = SK_LSPEED_100MBPS;
-		} else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
-		    LinkSpeed = SK_LSPEED_1000MBPS;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for Speed_B\n",
-			Speed_B[pAC->Index]);
-		    IsLinkSpeedDefined = SK_FALSE;
-		}
-	} else {
-	    IsLinkSpeedDefined = SK_FALSE;
-	}
-
-	/* 
-	** Check speed parameter:
-	**    Only copper type adapter and GE V2 cards 
-	*/
-	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
-		((LinkSpeed != SK_LSPEED_AUTO) &&
-		(LinkSpeed != SK_LSPEED_1000MBPS))) {
-		printk("sk98lin: Illegal value for Speed_B. "
-			"Not a copper card or GE V2 card\n    Using "
-			"speed 1000\n");
-		LinkSpeed = SK_LSPEED_1000MBPS;
-	}
-
-	/*      
-	** Decide whether to set new config value if somethig valid has
-	** been received.
-	*/
-        if (IsLinkSpeedDefined) {
-	    pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
-	}
-
-	/* 
-	** b) Any Autonegotiation and DuplexCapabilities set?
-	**    Please note that both belong together...
-	*/
-	AutoNeg = AN_SENS; /* default: do auto Sense */
-	AutoSet = SK_FALSE;
-	if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		AutoNeg_B[pAC->Index] != NULL) {
-		AutoSet = SK_TRUE;
-		if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
-		    AutoSet = SK_FALSE;
-		} else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
-		    AutoNeg = AN_ON;
-		} else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
-		    AutoNeg = AN_OFF;
-		} else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
-		    AutoNeg = AN_SENS;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n",
-			AutoNeg_B[pAC->Index]);
-		}
-	}
-
-	DuplexCap = DC_BOTH;
-	DupSet    = SK_FALSE;
-	if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		DupCap_B[pAC->Index] != NULL) {
-		DupSet = SK_TRUE;
-		if (strcmp(DupCap_B[pAC->Index],"")==0) {
-		    DupSet = SK_FALSE;
-		} else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
-		    DuplexCap = DC_BOTH;
-		} else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
-		    DuplexCap = DC_FULL;
-		} else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
-		    DuplexCap = DC_HALF;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for DupCap_B\n",
-			DupCap_B[pAC->Index]);
-		}
-	}
-
-	
-	/* 
-	** Check for illegal combinations 
-	*/
-	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
-		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
-		(DuplexCap == SK_LMODE_STAT_HALF)) &&
-		(pAC->ChipsetType)) {
-		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
-					"    Using Full Duplex.\n");
-				DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_SENS && DupSet) {
-		printk("sk98lin, Port B: DuplexCapabilities"
-			" ignored using Sense mode\n");
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
-		printk("sk98lin: Port B: Illegal combination"
-			" of values AutoNeg. and DuplexCap.\n    Using "
-			"Full Duplex\n");
-		DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
-		DuplexCap = DC_FULL;
-	}
-	
-	if (!AutoSet && DupSet) {
-		printk("sk98lin: Port B: Duplex setting not"
-			" possible in\n    default AutoNegotiation mode"
-			" (Sense).\n    Using AutoNegotiation On\n");
-		AutoNeg = AN_ON;
-	}
-
-	/* 
-	** set the desired mode 
-	*/
-	if (AutoSet || DupSet) {
-	    pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
-	}
-
-	/*
-	** c) Any FlowCtrl parameter set?
-	*/
-	if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		FlowCtrl_B[pAC->Index] != NULL) {
-		if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
-		    IsFlowCtrlDefined = SK_FALSE;
-		} else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
-		    FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
-		} else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
-		    FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
-		} else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
-		    FlowCtrl = SK_FLOW_MODE_LOC_SEND;
-		} else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
-		    FlowCtrl = SK_FLOW_MODE_NONE;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n",
-			FlowCtrl_B[pAC->Index]);
-		    IsFlowCtrlDefined = SK_FALSE;
-		}
-	} else {
-		IsFlowCtrlDefined = SK_FALSE;
-	}
-
-	if (IsFlowCtrlDefined) {
-	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
-		printk("sk98lin: Port B: FlowControl"
-			" impossible without AutoNegotiation,"
-			" disabled\n");
-		FlowCtrl = SK_FLOW_MODE_NONE;
-	    }
-	    pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
-	}
-
-	/*
-	** d) What is the RoleParameter?
-	*/
-	if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		Role_B[pAC->Index] != NULL) {
-		if (strcmp(Role_B[pAC->Index],"")==0) {
-		    IsRoleDefined = SK_FALSE;
-		} else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
-		    MSMode = SK_MS_MODE_AUTO;
-		} else if (strcmp(Role_B[pAC->Index],"Master")==0) {
-		    MSMode = SK_MS_MODE_MASTER;
-		} else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
-		    MSMode = SK_MS_MODE_SLAVE;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for Role_B\n",
-			Role_B[pAC->Index]);
-		    IsRoleDefined = SK_FALSE;
-		}
-	} else {
-	    IsRoleDefined = SK_FALSE;
-	}
-
-	if (IsRoleDefined) {
-	    pAC->GIni.GP[1].PMSMode = MSMode;
-	}
-	
-	/*
-	** Evaluate settings for both ports
-	*/
-	pAC->ActivePort = 0;
-	if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		PrefPort[pAC->Index] != NULL) {
-		if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
-			pAC->ActivePort             =  0;
-			pAC->Rlmt.Net[0].Preference = -1; /* auto */
-			pAC->Rlmt.Net[0].PrefPort   =  0;
-		} else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
-			/*
-			** do not set ActivePort here, thus a port
-			** switch is issued after net up.
-			*/
-			Port                        = 0;
-			pAC->Rlmt.Net[0].Preference = Port;
-			pAC->Rlmt.Net[0].PrefPort   = Port;
-		} else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
-			/*
-			** do not set ActivePort here, thus a port
-			** switch is issued after net up.
-			*/
-			if (pAC->GIni.GIMacsFound == 1) {
-				printk("sk98lin: Illegal value \"B\" for PrefPort.\n"
-					"      Port B not available on single port adapters.\n");
-
-				pAC->ActivePort             =  0;
-				pAC->Rlmt.Net[0].Preference = -1; /* auto */
-				pAC->Rlmt.Net[0].PrefPort   =  0;
-			} else {
-				Port                        = 1;
-				pAC->Rlmt.Net[0].Preference = Port;
-				pAC->Rlmt.Net[0].PrefPort   = Port;
-			}
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for PrefPort\n",
-			PrefPort[pAC->Index]);
-		}
-	}
-
-	pAC->RlmtNets = 1;
-
-	if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		RlmtMode[pAC->Index] != NULL) {
-		if (strcmp(RlmtMode[pAC->Index], "") == 0) {
-			pAC->RlmtMode = 0;
-		} else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
-			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
-		} else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
-			pAC->RlmtMode = SK_RLMT_CHECK_LINK |
-					SK_RLMT_CHECK_LOC_LINK;
-		} else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
-			pAC->RlmtMode = SK_RLMT_CHECK_LINK     |
-					SK_RLMT_CHECK_LOC_LINK |
-					SK_RLMT_CHECK_SEG;
-		} else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
-			(pAC->GIni.GIMacsFound == 2)) {
-			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
-			pAC->RlmtNets = 2;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for"
-			" RlmtMode, using default\n", 
-			RlmtMode[pAC->Index]);
-			pAC->RlmtMode = 0;
-		}
-	} else {
-		pAC->RlmtMode = 0;
-	}
-	
-	/*
-	** Check the interrupt moderation parameters
-	*/
-	if (Moderation[pAC->Index] != NULL) {
-		if (strcmp(Moderation[pAC->Index], "") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-		} else if (strcmp(Moderation[pAC->Index], "Static") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
-		} else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
-		} else if (strcmp(Moderation[pAC->Index], "None") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-		} else {
-	   		printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
-				"      Disable interrupt moderation.\n",
-				Moderation[pAC->Index]);
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-		}
-	} else {
-		pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-	}
-
-	if (Stats[pAC->Index] != NULL) {
-		if (strcmp(Stats[pAC->Index], "Yes") == 0) {
-			pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
-		} else {
-			pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
-		}
-	} else {
-		pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
-	}
-
-	if (ModerationMask[pAC->Index] != NULL) {
-		if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
-		} else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
-		} else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
-		} else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
-		} else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
-		} else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
-		} else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
-		} else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
-		} else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
-		} else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else { /* some rubbish */
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
-		}
-	} else {  /* operator has stated nothing */
-		pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
-	}
-
-	if (AutoSizing[pAC->Index] != NULL) {
-		if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
-			pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
-		} else {
-			pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
-		}
-	} else {  /* operator has stated nothing */
-		pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
-	}
-
-	if (IntsPerSec[pAC->Index] != 0) {
-		if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) || 
-			(IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
-	   		printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n"
-				"      Using default value of %i.\n", 
-				IntsPerSec[pAC->Index],
-				C_INT_MOD_IPS_LOWER_RANGE,
-				C_INT_MOD_IPS_UPPER_RANGE,
-				C_INTS_PER_SEC_DEFAULT);
-			pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
-		} else {
-			pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
-		}
-	} else {
-		pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
-	}
-
-	/*
-	** Evaluate upper and lower moderation threshold
-	*/
-	pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
-		pAC->DynIrqModInfo.MaxModIntsPerSec +
-		(pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
-
-	pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
-		pAC->DynIrqModInfo.MaxModIntsPerSec -
-		(pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
-
-	pAC->DynIrqModInfo.PrevTimeVal = jiffies;  /* initial value */
-
-
-} /* GetConfiguration */
-
-
-/*****************************************************************************
- *
- * 	ProductStr - return a adapter identification string from vpd
- *
- * Description:
- *	This function reads the product name string from the vpd area
- *	and puts it the field pAC->DeviceString.
- *
- * Returns: N/A
- */
-static inline int ProductStr(
-	SK_AC	*pAC,		/* pointer to adapter context */
-	char    *DeviceStr,	/* result string */
-	int      StrLen		/* length of the string */
-)
-{
-char	Keyword[] = VPD_NAME;	/* vpd productname identifier */
-int	ReturnCode;		/* return code from vpd_read */
-unsigned long Flags;
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	return ReturnCode;
-} /* ProductStr */
-
-/*****************************************************************************
- *
- *      StartDrvCleanupTimer - Start timer to check for descriptors which
- *                             might be placed in descriptor ring, but
- *                             havent been handled up to now
- *
- * Description:
- *      This function requests a HW-timer fo the Yukon card. The actions to
- *      perform when this timer expires, are located in the SkDrvEvent().
- *
- * Returns: N/A
- */
-static void
-StartDrvCleanupTimer(SK_AC *pAC) {
-    SK_EVPARA    EventParam;   /* Event struct for timer event */
-
-    SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
-    EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
-    SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
-                 SK_DRV_RX_CLEANUP_TIMER_LENGTH,
-                 SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*****************************************************************************
- *
- *      StopDrvCleanupTimer - Stop timer to check for descriptors
- *
- * Description:
- *      This function requests a HW-timer fo the Yukon card. The actions to
- *      perform when this timer expires, are located in the SkDrvEvent().
- *
- * Returns: N/A
- */
-static void
-StopDrvCleanupTimer(SK_AC *pAC) {
-    SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
-    SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
-}
-
-/****************************************************************************/
-/* functions for common modules *********************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- *	SkDrvAllocRlmtMbuf - allocate an RLMT mbuf
- *
- * Description:
- *	This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure
- *	is embedded into a socket buff data area.
- *
- * Context:
- *	runtime
- *
- * Returns:
- *	NULL or pointer to Mbuf.
- */
-SK_MBUF *SkDrvAllocRlmtMbuf(
-SK_AC		*pAC,		/* pointer to adapter context */
-SK_IOC		IoC,		/* the IO-context */
-unsigned	BufferSize)	/* size of the requested buffer */
-{
-SK_MBUF		*pRlmtMbuf;	/* pointer to a new rlmt-mbuf structure */
-struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
-
-	pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);
-	if (pMsgBlock == NULL) {
-		return (NULL);
-	}
-	pRlmtMbuf = (SK_MBUF*) pMsgBlock->data;
-	skb_reserve(pMsgBlock, sizeof(SK_MBUF));
-	pRlmtMbuf->pNext = NULL;
-	pRlmtMbuf->pOs = pMsgBlock;
-	pRlmtMbuf->pData = pMsgBlock->data;	/* Data buffer. */
-	pRlmtMbuf->Size = BufferSize;		/* Data buffer size. */
-	pRlmtMbuf->Length = 0;		/* Length of packet (<= Size). */
-	return (pRlmtMbuf);
-
-} /* SkDrvAllocRlmtMbuf */
-
-
-/*****************************************************************************
- *
- *	SkDrvFreeRlmtMbuf - free an RLMT mbuf
- *
- * Description:
- *	This routine frees one or more RLMT mbuf(s).
- *
- * Context:
- *	runtime
- *
- * Returns:
- *	Nothing
- */
-void  SkDrvFreeRlmtMbuf(
-SK_AC		*pAC,		/* pointer to adapter context */
-SK_IOC		IoC,		/* the IO-context */
-SK_MBUF		*pMbuf)		/* size of the requested buffer */
-{
-SK_MBUF		*pFreeMbuf;
-SK_MBUF		*pNextMbuf;
-
-	pFreeMbuf = pMbuf;
-	do {
-		pNextMbuf = pFreeMbuf->pNext;
-		DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
-		pFreeMbuf = pNextMbuf;
-	} while ( pFreeMbuf != NULL );
-} /* SkDrvFreeRlmtMbuf */
-
-
-/*****************************************************************************
- *
- *	SkOsGetTime - provide a time value
- *
- * Description:
- *	This routine provides a time value. The unit is 1/HZ (defined by Linux).
- *	It is not used for absolute time, but only for time differences.
- *
- *
- * Returns:
- *	Time value
- */
-SK_U64 SkOsGetTime(SK_AC *pAC)
-{
-	SK_U64	PrivateJiffies;
-	SkOsGetTimeCurrent(pAC, &PrivateJiffies);
-	return PrivateJiffies;
-} /* SkOsGetTime */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgDWord - read a 32 bit value from pci config space
- *
- * Description:
- *	This routine reads a 32 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgDWord(
-SK_AC *pAC,		/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U32 *pVal)		/* pointer to store the read value */
-{
-	pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
-	return(0);
-} /* SkPciReadCfgDWord */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgWord - read a 16 bit value from pci config space
- *
- * Description:
- *	This routine reads a 16 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgWord(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U16 *pVal)		/* pointer to store the read value */
-{
-	pci_read_config_word(pAC->PciDev, PciAddr, pVal);
-	return(0);
-} /* SkPciReadCfgWord */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgByte - read a 8 bit value from pci config space
- *
- * Description:
- *	This routine reads a 8 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgByte(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U8 *pVal)		/* pointer to store the read value */
-{
-	pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
-	return(0);
-} /* SkPciReadCfgByte */
-
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgWord - write a 16 bit value to pci config space
- *
- * Description:
- *	This routine writes a 16 bit value to the pci configuration
- *	space. The flag PciConfigUp indicates whether the config space
- *	is accesible or must be set up first.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciWriteCfgWord(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U16 Val)		/* pointer to store the read value */
-{
-	pci_write_config_word(pAC->PciDev, PciAddr, Val);
-	return(0);
-} /* SkPciWriteCfgWord */
-
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgWord - write a 8 bit value to pci config space
- *
- * Description:
- *	This routine writes a 8 bit value to the pci configuration
- *	space. The flag PciConfigUp indicates whether the config space
- *	is accesible or must be set up first.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciWriteCfgByte(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U8 Val)		/* pointer to store the read value */
-{
-	pci_write_config_byte(pAC->PciDev, PciAddr, Val);
-	return(0);
-} /* SkPciWriteCfgByte */
-
-
-/*****************************************************************************
- *
- *	SkDrvEvent - handle driver events
- *
- * Description:
- *	This function handles events from all modules directed to the driver
- *
- * Context:
- *	Is called under protection of slow path lock.
- *
- * Returns:
- *	0 if everything ok
- *	< 0  on error
- *	
- */
-int SkDrvEvent(
-SK_AC *pAC,		/* pointer to adapter context */
-SK_IOC IoC,		/* io-context */
-SK_U32 Event,		/* event-id */
-SK_EVPARA Param)	/* event-parameter */
-{
-SK_MBUF		*pRlmtMbuf;	/* pointer to a rlmt-mbuf structure */
-struct sk_buff	*pMsg;		/* pointer to a message block */
-int		FromPort;	/* the port from which we switch away */
-int		ToPort;		/* the port we switch to */
-SK_EVPARA	NewPara;	/* parameter for further events */
-int		Stat;
-unsigned long	Flags;
-SK_BOOL		DualNet;
-
-	switch (Event) {
-	case SK_DRV_ADAP_FAIL:
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("ADAPTER FAIL EVENT\n"));
-		printk("%s: Adapter failed.\n", pAC->dev[0]->name);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		/* cgoos */
-		break;
-	case SK_DRV_PORT_FAIL:
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT FAIL EVENT, Port: %d\n", FromPort));
-		if (FromPort == 0) {
-			printk("%s: Port A failed.\n", pAC->dev[0]->name);
-		} else {
-			printk("%s: Port B failed.\n", pAC->dev[1]->name);
-		}
-		/* cgoos */
-		break;
-	case SK_DRV_PORT_RESET:	 /* SK_U32 PortIdx */
-		/* action list 4 */
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT RESET EVENT, Port: %d ", FromPort));
-		NewPara.Para64 = FromPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-
-		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
-		netif_carrier_off(pAC->dev[Param.Para32[0]]);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		
-		/* clear rx ring from received frames */
-		ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
-		
-		ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		
-		/* tschilling: Handling of return value inserted. */
-		if (SkGeInitPort(pAC, IoC, FromPort)) {
-			if (FromPort == 0) {
-				printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
-			} else {
-				printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
-			}
-		}
-		SkAddrMcUpdate(pAC,IoC, FromPort);
-		PortReInitBmu(pAC, FromPort);
-		SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
-		ClearAndStartRx(pAC, FromPort);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		break;
-	case SK_DRV_NET_UP:	 /* SK_U32 PortIdx */
-	{	struct net_device *dev = pAC->dev[Param.Para32[0]];
-		/* action list 5 */
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("NET UP EVENT, Port: %d ", Param.Para32[0]));
-		/* Mac update */
-		SkAddrMcUpdate(pAC,IoC, FromPort);
-
-		if (DoPrintInterfaceChange) {
-		printk("%s: network connection up using"
-			" port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
-
-		/* tschilling: Values changed according to LinkSpeedUsed. */
-		Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
-		if (Stat == SK_LSPEED_STAT_10MBPS) {
-			printk("    speed:           10\n");
-		} else if (Stat == SK_LSPEED_STAT_100MBPS) {
-			printk("    speed:           100\n");
-		} else if (Stat == SK_LSPEED_STAT_1000MBPS) {
-			printk("    speed:           1000\n");
-		} else {
-			printk("    speed:           unknown\n");
-		}
-
-
-		Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
-		if (Stat == SK_LMODE_STAT_AUTOHALF ||
-			Stat == SK_LMODE_STAT_AUTOFULL) {
-			printk("    autonegotiation: yes\n");
-		}
-		else {
-			printk("    autonegotiation: no\n");
-		}
-		if (Stat == SK_LMODE_STAT_AUTOHALF ||
-			Stat == SK_LMODE_STAT_HALF) {
-			printk("    duplex mode:     half\n");
-		}
-		else {
-			printk("    duplex mode:     full\n");
-		}
-		Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
-		if (Stat == SK_FLOW_STAT_REM_SEND ) {
-			printk("    flowctrl:        remote send\n");
-		}
-		else if (Stat == SK_FLOW_STAT_LOC_SEND ){
-			printk("    flowctrl:        local send\n");
-		}
-		else if (Stat == SK_FLOW_STAT_SYMMETRIC ){
-			printk("    flowctrl:        symmetric\n");
-		}
-		else {
-			printk("    flowctrl:        none\n");
-		}
-		
-		/* tschilling: Check against CopperType now. */
-		if ((pAC->GIni.GICopperType == SK_TRUE) &&
-			(pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
-			SK_LSPEED_STAT_1000MBPS)) {
-			Stat = pAC->GIni.GP[FromPort].PMSStatus;
-			if (Stat == SK_MS_STAT_MASTER ) {
-				printk("    role:            master\n");
-			}
-			else if (Stat == SK_MS_STAT_SLAVE ) {
-				printk("    role:            slave\n");
-			}
-			else {
-				printk("    role:            ???\n");
-			}
-		}
-
-		/* 
-		   Display dim (dynamic interrupt moderation) 
-		   informations
-		 */
-		if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC)
-			printk("    irq moderation:  static (%d ints/sec)\n",
-					pAC->DynIrqModInfo.MaxModIntsPerSec);
-		else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC)
-			printk("    irq moderation:  dynamic (%d ints/sec)\n",
-					pAC->DynIrqModInfo.MaxModIntsPerSec);
-		else
-			printk("    irq moderation:  disabled\n");
-
-
-		printk("    scatter-gather:  %s\n",
-		       (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
-		printk("    tx-checksum:     %s\n",
-		       (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
-		printk("    rx-checksum:     %s\n",
-		       pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
-
-		} else {
-                        DoPrintInterfaceChange = SK_TRUE;
-                }
-	
-		if ((Param.Para32[0] != pAC->ActivePort) &&
-			(pAC->RlmtNets == 1)) {
-			NewPara.Para32[0] = pAC->ActivePort;
-			NewPara.Para32[1] = Param.Para32[0];
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
-				NewPara);
-		}
-
-		/* Inform the world that link protocol is up. */
-		netif_carrier_on(dev);
-		break;
-	}
-	case SK_DRV_NET_DOWN:	 /* SK_U32 Reason */
-		/* action list 7 */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("NET DOWN EVENT "));
-		if (DoPrintInterfaceChange) {
-			printk("%s: network connection down\n", 
-				pAC->dev[Param.Para32[1]]->name);
-		} else {
-			DoPrintInterfaceChange = SK_TRUE;
-		}
-		netif_carrier_off(pAC->dev[Param.Para32[1]]);
-		break;
-	case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT SWITCH HARD "));
-	case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-	/* action list 6 */
-		printk("%s: switching to port %c\n", pAC->dev[0]->name,
-			'A'+Param.Para32[1]);
-	case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-		FromPort = Param.Para32[0];
-		ToPort = Param.Para32[1];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT SWITCH EVENT, From: %d  To: %d (Pref %d) ",
-			FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
-		NewPara.Para64 = FromPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		NewPara.Para64 = ToPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
-		SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
-		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-
-		ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
-		ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
-		
-		ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
-		ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		pAC->ActivePort = ToPort;
-#if 0
-		SetQueueSizes(pAC);
-#else
-		/* tschilling: New common function with minimum size check. */
-		DualNet = SK_FALSE;
-		if (pAC->RlmtNets == 2) {
-			DualNet = SK_TRUE;
-		}
-		
-		if (SkGeInitAssignRamToQueues(
-			pAC,
-			pAC->ActivePort,
-			DualNet)) {
-			spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-			spin_unlock_irqrestore(
-				&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-				Flags);
-			printk("SkGeInitAssignRamToQueues failed.\n");
-			break;
-		}
-#endif
-		/* tschilling: Handling of return values inserted. */
-		if (SkGeInitPort(pAC, IoC, FromPort) ||
-			SkGeInitPort(pAC, IoC, ToPort)) {
-			printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
-		}
-		if (Event == SK_DRV_SWITCH_SOFT) {
-			SkMacRxTxEnable(pAC, IoC, FromPort);
-		}
-		SkMacRxTxEnable(pAC, IoC, ToPort);
-		SkAddrSwap(pAC, IoC, FromPort, ToPort);
-		SkAddrMcUpdate(pAC, IoC, FromPort);
-		SkAddrMcUpdate(pAC, IoC, ToPort);
-		PortReInitBmu(pAC, FromPort);
-		PortReInitBmu(pAC, ToPort);
-		SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
-		SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
-		ClearAndStartRx(pAC, FromPort);
-		ClearAndStartRx(pAC, ToPort);
-		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		break;
-	case SK_DRV_RLMT_SEND:	 /* SK_MBUF *pMb */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("RLS "));
-		pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
-		pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
-		skb_put(pMsg, pRlmtMbuf->Length);
-		if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
-			pMsg) < 0)
-
-			DEV_KFREE_SKB_ANY(pMsg);
-		break;
-	case SK_DRV_TIMER:
-		if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
-			/*
-			** expiration of the moderation timer implies that
-			** dynamic moderation is to be applied
-			*/
-			SkDimStartModerationTimer(pAC);
-			SkDimModerate(pAC);
-                        if (pAC->DynIrqModInfo.DisplayStats) {
-			    SkDimDisplayModerationSettings(pAC);
-                        }
-                } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
-			/*
-			** check if we need to check for descriptors which
-			** haven't been handled the last millisecs
-			*/
-			StartDrvCleanupTimer(pAC);
-			if (pAC->GIni.GIMacsFound == 2) {
-				ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
-			}
-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
-		} else {
-			printk("Expiration of unknown timer\n");
-		}
-		break;
-	default:
-		break;
-	}
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-		("END EVENT "));
-	
-	return (0);
-} /* SkDrvEvent */
-
-
-/*****************************************************************************
- *
- *	SkErrorLog - log errors
- *
- * Description:
- *	This function logs errors to the system buffer and to the console
- *
- * Returns:
- *	0 if everything ok
- *	< 0  on error
- *	
- */
-void SkErrorLog(
-SK_AC	*pAC,
-int	ErrClass,
-int	ErrNum,
-char	*pErrorMsg)
-{
-char	ClassStr[80];
-
-	switch (ErrClass) {
-	case SK_ERRCL_OTHER:
-		strcpy(ClassStr, "Other error");
-		break;
-	case SK_ERRCL_CONFIG:
-		strcpy(ClassStr, "Configuration error");
-		break;
-	case SK_ERRCL_INIT:
-		strcpy(ClassStr, "Initialization error");
-		break;
-	case SK_ERRCL_NORES:
-		strcpy(ClassStr, "Out of resources error");
-		break;
-	case SK_ERRCL_SW:
-		strcpy(ClassStr, "internal Software error");
-		break;
-	case SK_ERRCL_HW:
-		strcpy(ClassStr, "Hardware failure");
-		break;
-	case SK_ERRCL_COMM:
-		strcpy(ClassStr, "Communication error");
-		break;
-	}
-	printk(KERN_INFO "%s: -- ERROR --\n        Class:  %s\n"
-		"        Nr:  0x%x\n        Msg:  %s\n", pAC->dev[0]->name,
-		ClassStr, ErrNum, pErrorMsg);
-
-} /* SkErrorLog */
-
-#ifdef SK_DIAG_SUPPORT
-
-/*****************************************************************************
- *
- *	SkDrvEnterDiagMode - handles DIAG attach request
- *
- * Description:
- *	Notify the kernel to NOT access the card any longer due to DIAG
- *	Deinitialize the Card
- *
- * Returns:
- *	int
- */
-int SkDrvEnterDiagMode(
-SK_AC   *pAc)   /* pointer to adapter context */
-{
-	DEV_NET *pNet = netdev_priv(pAc->dev[0]);
-	SK_AC   *pAC  = pNet->pAC;
-
-	SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-
-	pAC->DiagModeActive = DIAG_ACTIVE;
-	if (pAC->BoardLevel > SK_INIT_DATA) {
-		if (netif_running(pAC->dev[0])) {
-			pAC->WasIfUp[0] = SK_TRUE;
-			pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose      */
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
-		} else {
-			pAC->WasIfUp[0] = SK_FALSE;
-		}
-		if (pNet != netdev_priv(pAC->dev[1])) {
-			pNet = netdev_priv(pAC->dev[1]);
-			if (netif_running(pAC->dev[1])) {
-				pAC->WasIfUp[1] = SK_TRUE;
-				pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-				DoPrintInterfaceChange = SK_FALSE;
-				SkDrvDeInitAdapter(pAC, 1);  /* do SkGeClose  */
-			} else {
-				pAC->WasIfUp[1] = SK_FALSE;
-			}
-		}
-		pAC->BoardLevel = SK_INIT_DATA;
-	}
-	return(0);
-}
-
-/*****************************************************************************
- *
- *	SkDrvLeaveDiagMode - handles DIAG detach request
- *
- * Description:
- *	Notify the kernel to may access the card again after use by DIAG
- *	Initialize the Card
- *
- * Returns:
- * 	int
- */
-int SkDrvLeaveDiagMode(
-SK_AC   *pAc)   /* pointer to adapter control context */
-{ 
-	SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-	pAc->DiagModeActive    = DIAG_NOTACTIVE;
-	pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
-        if (pAc->WasIfUp[0] == SK_TRUE) {
-                pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-		DoPrintInterfaceChange = SK_FALSE;
-                SkDrvInitAdapter(pAc, 0);    /* first device  */
-        }
-        if (pAc->WasIfUp[1] == SK_TRUE) {
-                pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-		DoPrintInterfaceChange = SK_FALSE;
-                SkDrvInitAdapter(pAc, 1);    /* second device */
-        }
-	return(0);
-}
-
-/*****************************************************************************
- *
- *	ParseDeviceNbrFromSlotName - Evaluate PCI device number
- *
- * Description:
- * 	This function parses the PCI slot name information string and will
- *	retrieve the devcie number out of it. The slot_name maintianed by
- *	linux is in the form of '02:0a.0', whereas the first two characters 
- *	represent the bus number in hex (in the sample above this is 
- *	pci bus 0x02) and the next two characters the device number (0x0a).
- *
- * Returns:
- *	SK_U32: The device number from the PCI slot name
- */ 
-
-static SK_U32 ParseDeviceNbrFromSlotName(
-const char *SlotName)   /* pointer to pci slot name eg. '02:0a.0' */
-{
-	char	*CurrCharPos	= (char *) SlotName;
-	int	FirstNibble	= -1;
-	int	SecondNibble	= -1;
-	SK_U32	Result		=  0;
-
-	while (*CurrCharPos != '\0') {
-		if (*CurrCharPos == ':') { 
-			while (*CurrCharPos != '.') {
-				CurrCharPos++;  
-				if (	(*CurrCharPos >= '0') && 
-					(*CurrCharPos <= '9')) {
-					if (FirstNibble == -1) {
-						/* dec. value for '0' */
-						FirstNibble = *CurrCharPos - 48;
-					} else {
-						SecondNibble = *CurrCharPos - 48;
-					}  
-				} else if (	(*CurrCharPos >= 'a') && 
-						(*CurrCharPos <= 'f')  ) {
-					if (FirstNibble == -1) {
-						FirstNibble = *CurrCharPos - 87; 
-					} else {
-						SecondNibble = *CurrCharPos - 87; 
-					}
-				} else {
-					Result = 0;
-				}
-			}
-
-			Result = FirstNibble;
-			Result = Result << 4; /* first nibble is higher one */
-			Result = Result | SecondNibble;
-		}
-		CurrCharPos++;   /* next character */
-	}
-	return (Result);
-}
-
-/****************************************************************************
- *
- *	SkDrvDeInitAdapter - deinitialize adapter (this function is only 
- *				called if Diag attaches to that card)
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkDrvDeInitAdapter(
-SK_AC   *pAC,		/* pointer to adapter context   */
-int      devNbr)	/* what device is to be handled */
-{
-	struct SK_NET_DEVICE *dev;
-
-	dev = pAC->dev[devNbr];
-
-	/* On Linux 2.6 the network driver does NOT mess with reference
-	** counts.  The driver MUST be able to be unloaded at any time
-	** due to the possibility of hotplug.
-	*/
-	if (SkGeClose(dev) != 0) {
-		return (-1);
-	}
-	return (0);
-
-} /* SkDrvDeInitAdapter() */
-
-/****************************************************************************
- *
- *	SkDrvInitAdapter - Initialize adapter (this function is only 
- *				called if Diag deattaches from that card)
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkDrvInitAdapter(
-SK_AC   *pAC,		/* pointer to adapter context   */
-int      devNbr)	/* what device is to be handled */
-{
-	struct SK_NET_DEVICE *dev;
-
-	dev = pAC->dev[devNbr];
-
-	if (SkGeOpen(dev) != 0) {
-		return (-1);
-	}
-
-	/*
-	** Use correct MTU size and indicate to kernel TX queue can be started
-	*/ 
-	if (SkGeChangeMtu(dev, dev->mtu) != 0) {
-		return (-1);
-	} 
-	return (0);
-
-} /* SkDrvInitAdapter */
-
-#endif
-
-#ifdef DEBUG
-/****************************************************************************/
-/* "debug only" section *****************************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- *	DumpMsg - print a frame
- *
- * Description:
- *	This function prints frames to the system logfile/to the console.
- *
- * Returns: N/A
- *	
- */
-static void DumpMsg(struct sk_buff *skb, char *str)
-{
-	int	msglen;
-
-	if (skb == NULL) {
-		printk("DumpMsg(): NULL-Message\n");
-		return;
-	}
-
-	if (skb->data == NULL) {
-		printk("DumpMsg(): Message empty\n");
-		return;
-	}
-
-	msglen = skb->len;
-	if (msglen > 64)
-		msglen = 64;
-
-	printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len);
-
-	DumpData((char *)skb->data, msglen);
-
-	printk("------- End of message ---------\n");
-} /* DumpMsg */
-
-
-
-/*****************************************************************************
- *
- *	DumpData - print a data area
- *
- * Description:
- *	This function prints a area of data to the system logfile/to the
- *	console.
- *
- * Returns: N/A
- *	
- */
-static void DumpData(char *p, int size)
-{
-register int    i;
-int	haddr, addr;
-char	hex_buffer[180];
-char	asc_buffer[180];
-char	HEXCHAR[] = "0123456789ABCDEF";
-
-	addr = 0;
-	haddr = 0;
-	hex_buffer[0] = 0;
-	asc_buffer[0] = 0;
-	for (i=0; i < size; ) {
-		if (*p >= '0' && *p <='z')
-			asc_buffer[addr] = *p;
-		else
-			asc_buffer[addr] = '.';
-		addr++;
-		asc_buffer[addr] = 0;
-		hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[*p & 0x0f];
-		haddr++;
-		hex_buffer[haddr] = ' ';
-		haddr++;
-		hex_buffer[haddr] = 0;
-		p++;
-		i++;
-		if (i%16 == 0) {
-			printk("%s  %s\n", hex_buffer, asc_buffer);
-			addr = 0;
-			haddr = 0;
-		}
-	}
-} /* DumpData */
-
-
-/*****************************************************************************
- *
- *	DumpLong - print a data area as long values
- *
- * Description:
- *	This function prints a area of data to the system logfile/to the
- *	console.
- *
- * Returns: N/A
- *	
- */
-static void DumpLong(char *pc, int size)
-{
-register int    i;
-int	haddr, addr;
-char	hex_buffer[180];
-char	asc_buffer[180];
-char	HEXCHAR[] = "0123456789ABCDEF";
-long	*p;
-int	l;
-
-	addr = 0;
-	haddr = 0;
-	hex_buffer[0] = 0;
-	asc_buffer[0] = 0;
-	p = (long*) pc;
-	for (i=0; i < size; ) {
-		l = (long) *p;
-		hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[l & 0x0f];
-		haddr++;
-		hex_buffer[haddr] = ' ';
-		haddr++;
-		hex_buffer[haddr] = 0;
-		p++;
-		i++;
-		if (i%8 == 0) {
-			printk("%4x %s\n", (i-8)*4, hex_buffer);
-			haddr = 0;
-		}
-	}
-	printk("------------------------\n");
-} /* DumpLong */
-
-#endif
-
-static int __devinit skge_probe_one(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	SK_AC			*pAC;
-	DEV_NET			*pNet = NULL;
-	struct net_device	*dev = NULL;
-	static int boards_found = 0;
-	int error = -ENODEV;
-	int using_dac = 0;
-	char DeviceStr[80];
-
-	if (pci_enable_device(pdev))
-		goto out;
- 
-	/* Configure DMA attributes. */
-	if (sizeof(dma_addr_t) > sizeof(u32) &&
-	    !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
-		using_dac = 1;
-		error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-		if (error < 0) {
-			printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
-			       "for consistent allocations\n", pci_name(pdev));
-			goto out_disable_device;
-		}
-	} else {
-		error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-		if (error) {
-			printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
-			       pci_name(pdev));
-			goto out_disable_device;
-		}
-	}
-
- 	error = -ENOMEM;
- 	dev = alloc_etherdev(sizeof(DEV_NET));
- 	if (!dev) {
-		printk(KERN_ERR "sk98lin: unable to allocate etherdev "
-		       "structure!\n");
-		goto out_disable_device;
-	}
-
-	pNet = netdev_priv(dev);
-	pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
-	if (!pNet->pAC) {
-		printk(KERN_ERR "sk98lin: unable to allocate adapter "
-		       "structure!\n");
-		goto out_free_netdev;
-	}
-
-	pAC = pNet->pAC;
-	pAC->PciDev = pdev;
-
-	pAC->dev[0] = dev;
-	pAC->dev[1] = dev;
-	pAC->CheckQueue = SK_FALSE;
-
-	dev->irq = pdev->irq;
-
-	error = SkGeInitPCI(pAC);
-	if (error) {
-		printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
-		goto out_free_netdev;
-	}
-
-	SET_MODULE_OWNER(dev);
-	dev->open =		&SkGeOpen;
-	dev->stop =		&SkGeClose;
-	dev->hard_start_xmit =	&SkGeXmit;
-	dev->get_stats =	&SkGeStats;
-	dev->set_multicast_list = &SkGeSetRxMode;
-	dev->set_mac_address =	&SkGeSetMacAddr;
-	dev->do_ioctl =		&SkGeIoctl;
-	dev->change_mtu =	&SkGeChangeMtu;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller =	&SkGePollController;
-#endif
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
-	/* Use only if yukon hardware */
-	if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
-		dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
-		dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
-		pAC->RxPort[0].RxCsum = 1;
-#endif
-	}
-
-	if (using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
-
-	pAC->Index = boards_found++;
-
-	error = SkGeBoardInit(dev, pAC);
-	if (error)
-		goto out_free_netdev;
-
-	/* Read Adapter name from VPD */
-	if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
-		error = -EIO;
-		printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
-		goto out_free_resources;
-	}
-
-	/* Register net device */
-	error = register_netdev(dev);
-	if (error) {
-		printk(KERN_ERR "sk98lin: Could not register device.\n");
-		goto out_free_resources;
-	}
-
-	/* Print adapter specific string from vpd */
-	printk("%s: %s\n", dev->name, DeviceStr);
-
-	/* Print configuration settings */
-	printk("      PrefPort:%c  RlmtMode:%s\n",
-		'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
-		(pAC->RlmtMode==0)  ? "Check Link State" :
-		((pAC->RlmtMode==1) ? "Check Link State" :
-		((pAC->RlmtMode==3) ? "Check Local Port" :
-		((pAC->RlmtMode==7) ? "Check Segmentation" :
-		((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
-	SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-	memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
-	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-	pNet->PortNr = 0;
-	pNet->NetNr  = 0;
-
-	boards_found++;
-
-	pci_set_drvdata(pdev, dev);
-
-	/* More then one port found */
-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		dev = alloc_etherdev(sizeof(DEV_NET));
-		if (!dev) {
-			printk(KERN_ERR "sk98lin: unable to allocate etherdev "
-				"structure!\n");
-			goto single_port;
-		}
-
-		pNet          = netdev_priv(dev);
-		pNet->PortNr  = 1;
-		pNet->NetNr   = 1;
-		pNet->pAC     = pAC;
-
-		dev->open               = &SkGeOpen;
-		dev->stop               = &SkGeClose;
-		dev->hard_start_xmit    = &SkGeXmit;
-		dev->get_stats          = &SkGeStats;
-		dev->set_multicast_list = &SkGeSetRxMode;
-		dev->set_mac_address    = &SkGeSetMacAddr;
-		dev->do_ioctl           = &SkGeIoctl;
-		dev->change_mtu         = &SkGeChangeMtu;
-		SET_NETDEV_DEV(dev, &pdev->dev);
-		SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
-		if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
-			dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
-			dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
-			pAC->RxPort[1].RxCsum = 1;
-#endif
-		}
-
-		if (using_dac)
-			dev->features |= NETIF_F_HIGHDMA;
-
-		error = register_netdev(dev);
-		if (error) {
-			printk(KERN_ERR "sk98lin: Could not register device"
-			       " for second port. (%d)\n", error);
-			free_netdev(dev);
-			goto single_port;
-		}
-
-		pAC->dev[1]   = dev;
-		memcpy(&dev->dev_addr,
-		       &pAC->Addr.Net[1].CurrentMacAddress, 6);
-		memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-		printk("%s: %s\n", dev->name, DeviceStr);
-		printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
-	}
-
-single_port:
-
-	/* Save the hardware revision */
-	pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
-		(pAC->GIni.GIPciHwRev & 0x0F);
-
-	/* Set driver globals */
-	pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
-	pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
-
-	memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
-	memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
-
-	return 0;
-
- out_free_resources:
-	FreeResources(dev);
- out_free_netdev:
-	free_netdev(dev);
- out_disable_device:
-	pci_disable_device(pdev);
- out:
-	return error;
-}
-
-static void __devexit skge_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-
-	unregister_netdev(dev);
-
-	SkGeYellowLED(pAC, pAC->IoBase, 0);
-
-	if (pAC->BoardLevel == SK_INIT_RUN) {
-		SK_EVPARA EvPara;
-		unsigned long Flags;
-
-		/* board is still alive */
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		EvPara.Para32[0] = 0;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		EvPara.Para32[0] = 1;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		SkGeDeInit(pAC, pAC->IoBase);
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		pAC->BoardLevel = SK_INIT_DATA;
-		/* We do NOT check here, if IRQ was pending, of course*/
-	}
-
-	if (pAC->BoardLevel == SK_INIT_IO) {
-		/* board is still alive */
-		SkGeDeInit(pAC, pAC->IoBase);
-		pAC->BoardLevel = SK_INIT_DATA;
-	}
-
-	FreeResources(dev);
-	free_netdev(dev);
-	if (otherdev != dev)
-		free_netdev(otherdev);
-	kfree(pAC);
-}
-
-#ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-
-	if (netif_running(dev)) {
-		netif_carrier_off(dev);
-		DoPrintInterfaceChange = SK_FALSE;
-		SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
-		netif_device_detach(dev);
-	}
-	if (otherdev != dev) {
-		if (netif_running(otherdev)) {
-			netif_carrier_off(otherdev);
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvDeInitAdapter(pAC, 1);  /* performs SkGeClose */
-			netif_device_detach(otherdev);
-		}
-	}
-
-	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-	if (pAC->AllocFlag & SK_ALLOC_IRQ) {
-		free_irq(dev->irq, dev);
-	}
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-static int skge_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-	int ret;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		printk(KERN_WARNING "sk98lin: unable to enable device %s "
-				"in resume\n", dev->name);
-		goto err_out;
-	}
-	pci_set_master(pdev);
-	if (pAC->GIni.GIMacsFound == 2)
-		ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
-	else
-		ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev);
-	if (ret) {
-		printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
-		ret = -EBUSY;
-		goto err_out_disable_pdev;
-	}
-
-	netif_device_attach(dev);
-	if (netif_running(dev)) {
-		DoPrintInterfaceChange = SK_FALSE;
-		SkDrvInitAdapter(pAC, 0);    /* first device  */
-	}
-	if (otherdev != dev) {
-		netif_device_attach(otherdev);
-		if (netif_running(otherdev)) {
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvInitAdapter(pAC, 1);    /* second device  */
-		}
-	}
-
-	return 0;
-
-err_out_disable_pdev:
-	pci_disable_device(pdev);
-err_out:
-	pAC->AllocFlag &= ~SK_ALLOC_IRQ;
-	dev->irq = 0;
-	return ret;
-}
-#else
-#define skge_suspend NULL
-#define skge_resume NULL
-#endif
-
-static struct pci_device_id skge_pci_tbl[] = {
-	{ PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-/* DLink card does not have valid VPD so this driver gags
- *	{ PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- */
-	{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
-	{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
-
-static struct pci_driver skge_driver = {
-	.name		= "sk98lin",
-	.id_table	= skge_pci_tbl,
-	.probe		= skge_probe_one,
-	.remove		= __devexit_p(skge_remove_one),
-	.suspend	= skge_suspend,
-	.resume		= skge_resume,
-};
-
-static int __init skge_init(void)
-{
-	printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
-	       " and is scheduled for removal\n");
-
-	return pci_register_driver(&skge_driver);
-}
-
-static void __exit skge_exit(void)
-{
-	pci_unregister_driver(&skge_driver);
-}
-
-module_init(skge_init);
-module_exit(skge_exit);
diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
deleted file mode 100644
index db67099..0000000
--- a/drivers/net/sk98lin/skgehwt.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgehwt.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.15 $
- * Date:	$Date: 2003/09/16 13:41:23 $
- * Purpose:	Hardware Timer
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- *   Hardware Timer function queue management.
- */
-intro()
-{}
-#endif
-
-/*
- * Prototypes of local functions.
- */
-#define	SK_HWT_MAX	(65000)
-
-/* correction factor */
-#define	SK_HWT_FAC	(1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100)
-
-/*
- * Initialize hardware timer.
- *
- * Must be called during init level 1.
- */
-void	SkHwtInit(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	pAC->Hwt.TStart = 0 ;
-	pAC->Hwt.TStop	= 0 ;
-	pAC->Hwt.TActive = SK_FALSE;
-
-	SkHwtStop(pAC, Ioc);
-}
-
-/*
- *
- * Start hardware timer (clock ticks are 16us).
- *
- */
-void	SkHwtStart(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc,	/* IoContext */
-SK_U32	Time)	/* Time in units of 16us to load the timer with. */
-{
-	SK_U32	Cnt;
-
-	if (Time > SK_HWT_MAX)
-		Time = SK_HWT_MAX;
-
-	pAC->Hwt.TStart = Time;
-	pAC->Hwt.TStop = 0L;
-
-	Cnt = Time;
-
-	/*
-	 * if time < 16 us
-	 *	time = 16 us
-	 */
-	if (!Cnt) {
-		Cnt++;
-	}
-
-	SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC);
-	
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_START);	/* Start timer. */
-
-	pAC->Hwt.TActive = SK_TRUE;
-}
-
-/*
- * Stop hardware timer.
- * and clear the timer IRQ
- */
-void	SkHwtStop(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
-	
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
-
-	pAC->Hwt.TActive = SK_FALSE;
-}
-
-
-/*
- *	Stop hardware timer and read time elapsed since last start.
- *
- * returns
- *	The elapsed time since last start in units of 16us.
- *
- */
-SK_U32	SkHwtRead(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SK_U32	TRead;
-	SK_U32	IStatus;
-
-	if (pAC->Hwt.TActive) {
-		
-		SkHwtStop(pAC, Ioc);
-
-		SK_IN32(Ioc, B2_TI_VAL, &TRead);
-		TRead /= SK_HWT_FAC;
-
-		SK_IN32(Ioc, B0_ISRC, &IStatus);
-
-		/* Check if timer expired (or wraped around) */
-		if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) {
-			
-			SkHwtStop(pAC, Ioc);
-			
-			pAC->Hwt.TStop = pAC->Hwt.TStart;
-		}
-		else {
-			
-			pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
-		}
-	}
-	return(pAC->Hwt.TStop);
-}
-
-/*
- * interrupt source= timer
- */
-void	SkHwtIsr(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SkHwtStop(pAC, Ioc);
-	
-	pAC->Hwt.TStop = pAC->Hwt.TStart;
-	
-	SkTimerDone(pAC, Ioc);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
deleted file mode 100644
index 67f1d6a..0000000
--- a/drivers/net/sk98lin/skgeinit.c
+++ /dev/null
@@ -1,2005 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgeinit.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.97 $
- * Date:	$Date: 2003/10/02 16:45:31 $
- * Purpose:	Contains functions to initialize the adapter
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* global variables ***********************************************************/
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell.";
-#endif
-
-struct s_QOffTab {
-	int	RxQOff;		/* Receive Queue Address Offset */
-	int	XsQOff;		/* Sync Tx Queue Address Offset */
-	int	XaQOff;		/* Async Tx Queue Address Offset */
-};
-static struct s_QOffTab QOffTab[] = {
-	{Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2}
-};
-
-struct s_Config {
-	char	ScanString[8];
-	SK_U32	Value;
-};
-
-static struct s_Config OemConfig = {
-	{'O','E','M','_','C','o','n','f'},
-#ifdef SK_OEM_CONFIG
-	OEM_CONFIG_VALUE,
-#else
-	0,
-#endif
-};
-
-/******************************************************************************
- *
- *	SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
- *
- * Description:
- *	Enable or disable the descriptor polling of the transmit descriptor
- *	ring(s) (TxD) for port 'Port'.
- *	The new configuration is *not* saved over any SkGeStopPort() and
- *	SkGeInitPort() calls.
- *
- * Returns:
- *	nothing
- */
-void SkGePollTxD(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL PollTxD)	/* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
-{
-	SK_GEPORT *pPrt;
-	SK_U32	DWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL);
-
-	if (pPrt->PXSQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
-	}
-	
-	if (pPrt->PXAQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
-	}
-}	/* SkGePollTxD */
-
-
-/******************************************************************************
- *
- *	SkGeYellowLED() - Switch the yellow LED on or off.
- *
- * Description:
- *	Switch the yellow LED on or off.
- *
- * Note:
- *	This function may be called any time after SkGeInit(Level 1).
- *
- * Returns:
- *	nothing
- */
-void SkGeYellowLED(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		State)		/* yellow LED state, 0 = OFF, 0 != ON */
-{
-	if (State == 0) {
-		/* Switch yellow LED OFF */
-		SK_OUT8(IoC, B0_LED, LED_STAT_OFF);
-	}
-	else {
-		/* Switch yellow LED ON */
-		SK_OUT8(IoC, B0_LED, LED_STAT_ON);
-	}
-}	/* SkGeYellowLED */
-
-
-#if (!defined(SK_SLIM) || defined(GENESIS))
-/******************************************************************************
- *
- *	SkGeXmitLED() - Modify the Operational Mode of a transmission LED.
- *
- * Description:
- *	The Rx or Tx LED which is specified by 'Led' will be
- *	enabled, disabled or switched on in test mode.
- *
- * Note:
- *	'Led' must contain the address offset of the LEDs INI register.
- *
- * Usage:
- *	SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
- *
- * Returns:
- *	nothing
- */
-void SkGeXmitLED(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Led,		/* offset to the LED Init Value register */
-int		Mode)		/* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
-{
-	SK_U32	LedIni;
-
-	switch (Mode) {
-	case SK_LED_ENA:
-		LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-		SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni);
-		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
-		break;
-	case SK_LED_TST:
-		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON);
-		SK_OUT32(IoC, Led + XMIT_LED_CNT, 100);
-		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
-		break;
-	case SK_LED_DIS:
-	default:
-		/*
-		 * Do NOT stop the LED Timer here. The LED might be
-		 * in on state. But it needs to go off.
-		 */
-		SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
-		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
-		break;
-	}
-			
-	/*
-	 * 1000BT: The Transmit LED is driven by the PHY.
-	 * But the default LED configuration is used for
-	 * Level One and Broadcom PHYs.
-	 * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.)
-	 * (In this case it has to be added here. But we will see. XXX)
-	 */
-}	/* SkGeXmitLED */
-#endif	/* !SK_SLIM || GENESIS */
-
-
-/******************************************************************************
- *
- *	DoCalcAddr() - Calculates the start and the end address of a queue.
- *
- * Description:
- *	This function calculates the start and the end address of a queue.
- *  Afterwards the 'StartVal' is incremented to the next start position.
- *	If the port is already initialized the calculated values
- *	will be checked against the configured values and an
- *	error will be returned, if they are not equal.
- *	If the port is not initialized the values will be written to
- *	*StartAdr and *EndAddr.
- *
- * Returns:
- *	0:	success
- *	1:	configuration error
- */
-static int DoCalcAddr(
-SK_AC		*pAC, 				/* adapter context */
-SK_GEPORT	SK_FAR *pPrt,		/* port index */
-int			QuSize,				/* size of the queue to configure in kB */
-SK_U32		SK_FAR *StartVal,	/* start value for address calculation */
-SK_U32		SK_FAR *QuStartAddr,/* start addr to calculate */
-SK_U32		SK_FAR *QuEndAddr)	/* end address to calculate */
-{
-	SK_U32	EndVal;
-	SK_U32	NextStart;
-	int		Rtv;
-
-	Rtv = 0;
-	if (QuSize == 0) {
-		EndVal = *StartVal;
-		NextStart = EndVal;
-	}
-	else {
-		EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1;
-		NextStart = EndVal + 1;
-	}
-
-	if (pPrt->PState >= SK_PRT_INIT) {
-		if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) {
-			Rtv = 1;
-		}
-	}
-	else {
-		*QuStartAddr = *StartVal;
-		*QuEndAddr = EndVal;
-	}
-
-	*StartVal = NextStart;
-	return(Rtv);
-}	/* DoCalcAddr */
-
-/******************************************************************************
- *
- *	SkGeInitAssignRamToQueues() - allocate default queue sizes
- *
- * Description:
- *	This function assigns the memory to the different queues and ports.
- *	When DualNet is set to SK_TRUE all ports get the same amount of memory.
- *  Otherwise the first port gets most of the memory and all the
- *	other ports just the required minimum.
- *	This function can only be called when pAC->GIni.GIRamSize and
- *	pAC->GIni.GIMacsFound have been initialized, usually this happens
- *	at init level 1
- *
- * Returns:
- *	0 - ok
- *	1 - invalid input values
- *	2 - not enough memory
- */
-
-int SkGeInitAssignRamToQueues(
-SK_AC	*pAC,			/* Adapter context */
-int		ActivePort,		/* Active Port in RLMT mode */
-SK_BOOL	DualNet)		/* adapter context */
-{
-	int	i;
-	int	UsedKilobytes;			/* memory already assigned */
-	int	ActivePortKilobytes;	/* memory available for active port */
-	SK_GEPORT *pGePort;
-
-	UsedKilobytes = 0;
-
-	if (ActivePort >= pAC->GIni.GIMacsFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
-			ActivePort));
-		return(1);
-	}
-	if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) +
-		((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
-			 pAC->GIni.GIRamSize));
-		return(2);
-	}
-
-	if (DualNet) {
-		/* every port gets the same amount of memory */
-		ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound;
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
-			pGePort = &pAC->GIni.GP[i];
-			
-			/* take away the minimum memory for active queues */
-			ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
-
-			/* receive queue gets the minimum + 80% of the rest */
-			pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((
-				ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100))
-				+ SK_MIN_RXQ_SIZE;
-
-			ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
-			/* synchronous transmit queue */
-			pGePort->PXSQSize = 0;
-
-			/* asynchronous transmit queue */
-			pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes +
-				SK_MIN_TXQ_SIZE);
-		}
-	}
-	else {	
-		/* Rlmt Mode or single link adapter */
-
-		/* Set standby queue size defaults for all standby ports */
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
-			if (i != ActivePort) {
-				pGePort = &pAC->GIni.GP[i];
-
-				pGePort->PRxQSize = SK_MIN_RXQ_SIZE;
-				pGePort->PXAQSize = SK_MIN_TXQ_SIZE;
-				pGePort->PXSQSize = 0;
-
-				/* Count used RAM */
-				UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize;
-			}
-		}
-		/* what's left? */
-		ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes;
-
-		/* assign it to the active port */
-		/* first take away the minimum memory */
-		ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
-		pGePort = &pAC->GIni.GP[ActivePort];
-
-		/* receive queue get's the minimum + 80% of the rest */
-		pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes *
-			(unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE;
-
-		ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
-		/* synchronous transmit queue */
-		pGePort->PXSQSize = 0;
-
-		/* asynchronous transmit queue */
-		pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) +
-			SK_MIN_TXQ_SIZE;
-	}
-#ifdef VCPU
-	VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n",
-		pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize);
-#endif /* VCPU */
-
-	return(0);
-}	/* SkGeInitAssignRamToQueues */
-
-/******************************************************************************
- *
- *	SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
- *
- * Description:
- *	This function verifies the Queue Size Configuration specified
- *	in the variables PRxQSize, PXSQSize, and PXAQSize of all
- *	used ports.
- *	This requirements must be fullfilled to have a valid configuration:
- *		- The size of all queues must not exceed GIRamSize.
- *		- The queue sizes must be specified in units of 8 kB.
- *		- The size of Rx queues of available ports must not be
- *		  smaller than 16 kB.
- *		- The size of at least one Tx queue (synch. or asynch.)
- *        of available ports must not be smaller than 16 kB
- *        when Jumbo Frames are used.
- *		- The RAM start and end addresses must not be changed
- *		  for ports which are already initialized.
- *	Furthermore SkGeCheckQSize() defines the Start and End Addresses
- *  of all ports and stores them into the HWAC port	structure.
- *
- * Returns:
- *	0:	Queue Size Configuration valid
- *	1:	Queue Size Configuration invalid
- */
-static int SkGeCheckQSize(
-SK_AC	 *pAC,		/* adapter context */
-int		 Port)		/* port index */
-{
-	SK_GEPORT *pPrt;
-	int	i;
-	int	Rtv;
-	int	Rtv2;
-	SK_U32	StartAddr;
-#ifndef SK_SLIM
-	int	UsedMem;	/* total memory used (max. found ports) */
-#endif	
-
-	Rtv = 0;
-	
-#ifndef SK_SLIM
-
-	UsedMem = 0;
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		if ((pPrt->PRxQSize & QZ_UNITS) != 0 ||
-			(pPrt->PXSQSize & QZ_UNITS) != 0 ||
-			(pPrt->PXAQSize & QZ_UNITS) != 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
-			return(1);
-		}
-
-		if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
-			return(1);
-		}
-		
-		/*
-		 * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
-		 * if Jumbo Frames are used, this size has to be >= 16 kB.
-		 */
-		if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
-			(pAC->GIni.GIPortUsage == SK_JUMBO_LINK &&
-            ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
-			 (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
-				return(1);
-		}
-		
-		UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
-	}
-	
-	if (UsedMem > pAC->GIni.GIRamSize) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
-		return(1);
-	}
-#endif	/* !SK_SLIM */
-
-	/* Now start address calculation */
-	StartAddr = pAC->GIni.GIRamOffs;
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		/* Calculate/Check values for the receive queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
-			&pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
-		Rtv |= Rtv2;
-
-		/* Calculate/Check values for the synchronous Tx queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr,
-			&pPrt->PXsQRamStart, &pPrt->PXsQRamEnd);
-		Rtv |= Rtv2;
-
-		/* Calculate/Check values for the asynchronous Tx queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr,
-			&pPrt->PXaQRamStart, &pPrt->PXaQRamEnd);
-		Rtv |= Rtv2;
-
-		if (Rtv) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG);
-			return(1);
-		}
-	}
-
-	return(0);
-}	/* SkGeCheckQSize */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkGeInitMacArb() - Initialize the MAC Arbiter
- *
- * Description:
- *	This function initializes the MAC Arbiter.
- *	It must not be called if there is still an
- *	initialized or active port.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitMacArb(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53);
-
-	SK_OUT8(IoC, B3_MA_RCINI_RX1, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_RX2, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_TX1, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_TX2, 0);
-
-	/* recovery values are needed for XMAC II Rev. B2 only */
-	/* Fast Output Enable Mode was intended to use with Rev. B2, but now? */
-
-	/*
-	 * There is no start or enable button to push, therefore
-	 * the MAC arbiter is configured and enabled now.
-	 */
-}	/* SkGeInitMacArb */
-
-
-/******************************************************************************
- *
- *	SkGeInitPktArb() - Initialize the Packet Arbiter
- *
- * Description:
- *	This function initializes the Packet Arbiter.
- *	It must not be called if there is still an
- *	initialized or active port.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitPktArb(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
-
-	/*
-	 * enable timeout timers if jumbo frames not used
-	 * NOTE: the packet arbiter timeout interrupt is needed for
-	 * half duplex hangup workaround
-	 */
-	if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) {
-		if (pAC->GIni.GIMacsFound == 1) {
-			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
-		}
-		else {
-			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2);
-		}
-	}
-}	/* SkGeInitPktArb */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkGeInitMacFifo() - Initialize the MAC FIFOs
- *
- * Description:
- *	Initialize all MAC FIFOs of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitMacFifo(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Word;
-#ifdef VCPU
-	SK_U32	DWord;
-#endif /* VCPU */
-	/*
-	 * For each FIFO:
-	 *	- release local reset
-	 *	- use default value for MAC FIFO size
-	 *	- setup defaults for the control register
-	 *	- enable the FIFO
-	 */
-	
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* Configure Rx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
-		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
-	
-		/* Configure Tx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
-		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
-	
-		/* Enable frame flushing if jumbo frames used */
-		if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-			SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* set Rx GMAC FIFO Flush Mask */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK);
-		
-		Word = (SK_U16)GMF_RX_CTRL_DEF;
-
-		/* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
-		if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-
-			Word &= ~GMF_RX_F_FL_ON;
-		}
-		
-		/* Configure Rx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
-		
-		/* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
-		
-		/* Configure Tx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
-		
-#ifdef VCPU
-		SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord);
-		SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord);
-#endif /* VCPU */
-		
-		/* set Tx GMAC FIFO Almost Empty Threshold */
-/*		SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */
-	}
-#endif /* YUKON */
-
-}	/* SkGeInitMacFifo */
-
-#ifdef	SK_LNK_SYNC_CNT
-/******************************************************************************
- *
- *	SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
- *
- * Description:
- *	This function starts the Link Sync Counter of the specified
- *	port and enables the generation of an Link Sync IRQ.
- *	The Link Sync Counter may be used to detect an active link,
- *	if autonegotiation is not used.
- *
- * Note:
- *	o To ensure receiving the Link Sync Event the LinkSyncCounter
- *	  should be initialized BEFORE clearing the XMAC's reset!
- *	o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this
- *	  function.
- *
- * Returns:
- *	nothing
- */
-void SkGeLoadLnkSyncCnt(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U32	CntVal)		/* Counter value */
-{
-	SK_U32	OrgIMsk;
-	SK_U32	NewIMsk;
-	SK_U32	ISrc;
-	SK_BOOL	IrqPend;
-
-	/* stop counter */
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP);
-
-	/*
-	 * ASIC problem:
-	 * Each time starting the Link Sync Counter an IRQ is generated
-	 * by the adapter. See problem report entry from 21.07.98
-	 *
-	 * Workaround:	Disable Link Sync IRQ and clear the unexpeced IRQ
-	 *		if no IRQ is already pending.
-	 */
-	IrqPend = SK_FALSE;
-	SK_IN32(IoC, B0_ISRC, &ISrc);
-	SK_IN32(IoC, B0_IMSK, &OrgIMsk);
-	if (Port == MAC_1) {
-		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
-		if ((ISrc & IS_LNK_SYNC_M1) != 0) {
-			IrqPend = SK_TRUE;
-		}
-	}
-	else {
-		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2;
-		if ((ISrc & IS_LNK_SYNC_M2) != 0) {
-			IrqPend = SK_TRUE;
-		}
-	}
-	if (!IrqPend) {
-		SK_OUT32(IoC, B0_IMSK, NewIMsk);
-	}
-
-	/* load counter */
-	SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
-
-	/* start counter */
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START);
-
-	if (!IrqPend) {
-		/* clear the unexpected IRQ, and restore the interrupt mask */
-		SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ);
-		SK_OUT32(IoC, B0_IMSK, OrgIMsk);
-	}
-}	/* SkGeLoadLnkSyncCnt*/
-#endif	/* SK_LNK_SYNC_CNT */
-
-#if defined(SK_DIAG) || defined(SK_CFG_SYNC)
-/******************************************************************************
- *
- *	SkGeCfgSync() - Configure synchronous bandwidth for this port.
- *
- * Description:
- *	This function may be used to configure synchronous bandwidth
- *	to the specified port. This may be done any time after
- *	initializing the port. The configuration values are NOT saved
- *	in the HWAC port structure and will be overwritten any
- *	time when stopping and starting the port.
- *	Any values for the synchronous configuration will be ignored
- *	if the size of the synchronous queue is zero!
- *
- *	The default configuration for the synchronous service is
- *	TXA_ENA_FSYNC. This means if the size of
- *	the synchronous queue is unequal zero but no specific
- *	synchronous bandwidth is configured, the synchronous queue
- *	will always have the 'unlimited' transmit priority!
- *
- *	This mode will be restored if the synchronous bandwidth is
- *	deallocated ('IntTime' = 0 and 'LimCount' = 0).
- *
- * Returns:
- *	0:	success
- *	1:	parameter configuration error
- *	2:	try to configure quality of service although no
- *		synchronous queue is configured
- */
-int SkGeCfgSync(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U32	IntTime,	/* Interval Timer Value in units of 8ns */
-SK_U32	LimCount,	/* Number of bytes to transfer during IntTime */
-int		SyncMode)	/* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */
-{
-	int Rtv;
-
-	Rtv = 0;
-
-	/* check the parameters */
-	if (LimCount > IntTime ||
-		(LimCount == 0 && IntTime != 0) ||
-		(LimCount != 0 && IntTime == 0)) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
-		return(1);
-	}
-	
-	if (pAC->GIni.GP[Port].PXSQSize == 0) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
-		return(2);
-	}
-	
-	/* calculate register values */
-	IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
-	LimCount = LimCount / 8;
-	
-	if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
-		return(1);
-	}
-
-	/*
-	 * - Enable 'Force Sync' to ensure the synchronous queue
-	 *   has the priority while configuring the new values.
-	 * - Also 'disable alloc' to ensure the settings complies
-	 *   to the SyncMode parameter.
-	 * - Disable 'Rate Control' to configure the new values.
-	 * - write IntTime and LimCount
-	 * - start 'Rate Control' and disable 'Force Sync'
-	 *   if Interval Timer or Limit Counter not zero.
-	 */
-	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-		TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-	
-	SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
-	SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
-	
-	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-		(SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
-	
-	if (IntTime != 0 || LimCount != 0) {
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
-	}
-
-	return(0);
-}	/* SkGeCfgSync */
-#endif /* SK_DIAG || SK_CFG_SYNC*/
-
-
-/******************************************************************************
- *
- *	DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue
- *
- * Desccription:
- *	If the queue is used, enable and initialize it.
- *	Make sure the queue is still reset, if it is not used.
- *
- * Returns:
- *	nothing
- */
-static void DoInitRamQueue(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-int		QuIoOffs,		/* Queue IO Address Offset */
-SK_U32	QuStartAddr,	/* Queue Start Address */
-SK_U32	QuEndAddr,		/* Queue End Address */
-int		QuType)			/* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
-{
-	SK_U32	RxUpThresVal;
-	SK_U32	RxLoThresVal;
-
-	if (QuStartAddr != QuEndAddr) {
-		/* calculate thresholds, assume we have a big Rx queue */
-		RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8;
-		RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8;
-
-		/* build HW address format */
-		QuStartAddr = QuStartAddr / 8;
-		QuEndAddr = QuEndAddr / 8;
-
-		/* release local reset */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR);
-
-		/* configure addresses */
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr);
-
-		switch (QuType) {
-		case SK_RX_SRAM_Q:
-			/* configure threshold for small Rx Queue */
-			RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8;
-
-			/* continue with SK_RX_BRAM_Q */
-		case SK_RX_BRAM_Q:
-			/* write threshold for Rx Queue */
-
-			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
-			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
-
-			/* the high priority threshold not used */
-			break;
-		case SK_TX_RAM_Q:
-			/*
-			 * Do NOT use Store & Forward under normal operation due to
-			 * performance optimization (GENESIS only).
-			 * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB)
-			 * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
-			 * we NEED Store & Forward of the RAM buffer.
-			 */
-			if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK ||
-				pAC->GIni.GIYukon) {
-				/* enable Store & Forward Mode for the Tx Side */
-				SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
-			}
-			break;
-		}
-
-		/* set queue operational */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD);
-	}
-	else {
-		/* ensure the queue is still disabled */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET);
-	}
-}	/* DoInitRamQueue */
-
-
-/******************************************************************************
- *
- *	SkGeInitRamBufs() - Initialize the RAM Buffer Queues
- *
- * Description:
- *	Initialize all RAM Buffer Queues of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitRamBufs(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT *pPrt;
-	int RxQType;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) {
-		RxQType = SK_RX_SRAM_Q; 	/* small Rx Queue */
-	}
-	else {
-		RxQType = SK_RX_BRAM_Q;		/* big Rx Queue */
-	}
-
-	DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
-		pPrt->PRxQRamEnd, RxQType);
-	
-	DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
-		pPrt->PXsQRamEnd, SK_TX_RAM_Q);
-	
-	DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
-		pPrt->PXaQRamEnd, SK_TX_RAM_Q);
-
-}	/* SkGeInitRamBufs */
-
-
-/******************************************************************************
- *
- *	SkGeInitRamIface() - Initialize the RAM Interface
- *
- * Description:
- *	This function initializes the Adapters RAM Interface.
- *
- * Note:
- *	This function is used in the diagnostics.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitRamIface(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53);
-
-}	/* SkGeInitRamIface */
-
-
-/******************************************************************************
- *
- *	SkGeInitBmu() - Initialize the BMU state machines
- *
- * Description:
- *	Initialize all BMU state machines of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitBmu(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U32		RxWm;
-	SK_U32		TxWm;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	RxWm = SK_BMU_RX_WM;
-	TxWm = SK_BMU_TX_WM;
-	
-	if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
-		/* for better performance */
-		RxWm /= 2;
-		TxWm /= 2;
-	}
-
-	/* Rx Queue: Release all local resets and set the watermark */
-	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
-	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
-
-	/*
-	 * Tx Queue: Release all local resets if the queue is used !
-	 * 		set watermark
-	 */
-	if (pPrt->PXSQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
-	}
-	
-	if (pPrt->PXAQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
-	}
-	/*
-	 * Do NOT enable the descriptor poll timers here, because
-	 * the descriptor addresses are not specified yet.
-	 */
-}	/* SkGeInitBmu */
-
-
-/******************************************************************************
- *
- *	TestStopBit() -	Test the stop bit of the queue
- *
- * Description:
- *	Stopping a queue is not as simple as it seems to be.
- *	If descriptor polling is enabled, it may happen
- *	that RX/TX stop is done and SV idle is NOT set.
- *	In this case we have to issue another stop command.
- *
- * Returns:
- *	The queues control status register
- */
-static SK_U32 TestStopBit(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		QuIoOffs)	/* Queue IO Address Offset */
-{
-	SK_U32	QuCsr;	/* CSR contents */
-
-	SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
-	
-	if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
-		/* Stop Descriptor overridden by start command */
-		SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
-
-		SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
-	}
-	
-	return(QuCsr);
-}	/* TestStopBit */
-
-
-/******************************************************************************
- *
- *	SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'.
- *
- * Description:
- *	After calling this function the descriptor rings and Rx and Tx
- *	queues of this port may be reconfigured.
- *
- *	It is possible to stop the receive and transmit path separate or
- *	both together.
- *
- *	Dir =	SK_STOP_TX 	Stops the transmit path only and resets the MAC.
- *				The receive queue is still active and
- *				the pending Rx frames may be still transferred
- *				into the RxD.
- *		SK_STOP_RX	Stop the receive path. The tansmit path
- *				has to be stopped once before.
- *		SK_STOP_ALL	SK_STOP_TX + SK_STOP_RX
- *
- *	RstMode = SK_SOFT_RST	Resets the MAC. The PHY is still alive.
- *			SK_HARD_RST	Resets the MAC and the PHY.
- *
- * Example:
- *	1) A Link Down event was signaled for a port. Therefore the activity
- *	of this port should be stopped and a hardware reset should be issued
- *	to enable the workaround of XMAC Errata #2. But the received frames
- *	should not be discarded.
- *		...
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST);
- *		(transfer all pending Rx frames)
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST);
- *		...
- *
- *	2) An event was issued which request the driver to switch
- *	the 'virtual active' link to an other already active port
- *	as soon as possible. The frames in the receive queue of this
- *	port may be lost. But the PHY must not be reset during this
- *	event.
- *		...
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST);
- *		...
- *
- * Extended Description:
- *	If SK_STOP_TX is set,
- *		o disable the MAC's receive and transmitter to prevent
- *		  from sending incomplete frames
- *		o stop the port's transmit queues before terminating the
- *		  BMUs to prevent from performing incomplete PCI cycles
- *		  on the PCI bus
- *		- The network Rx and Tx activity and PCI Tx transfer is
- *		  disabled now.
- *		o reset the MAC depending on the RstMode
- *		o Stop Interval Timer and Limit Counter of Tx Arbiter,
- *		  also disable Force Sync bit and Enable Alloc bit.
- *		o perform a local reset of the port's Tx path
- *			- reset the PCI FIFO of the async Tx queue
- *			- reset the PCI FIFO of the sync Tx queue
- *			- reset the RAM Buffer async Tx queue
- *			- reset the RAM Buffer sync Tx queue
- *			- reset the MAC Tx FIFO
- *		o switch Link and Tx LED off, stop the LED counters
- *
- *	If SK_STOP_RX is set,
- *		o stop the port's receive queue
- *		- The path data transfer activity is fully stopped now.
- *		o perform a local reset of the port's Rx path
- *			- reset the PCI FIFO of the Rx queue
- *			- reset the RAM Buffer receive queue
- *			- reset the MAC Rx FIFO
- *		o switch Rx LED off, stop the LED counter
- *
- *	If all ports are stopped,
- *		o reset the RAM Interface.
- *
- * Notes:
- *	o This function may be called during the driver states RESET_PORT and
- *	  SWITCH_PORT.
- */
-void SkGeStopPort(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* I/O context */
-int		Port,	/* port to stop (MAC_1 + n) */
-int		Dir,	/* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
-int		RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
-{
-#ifndef SK_DIAG
-	SK_EVPARA Para;
-#endif /* !SK_DIAG */
-	SK_GEPORT *pPrt;
-	SK_U32	DWord;
-	SK_U32	XsCsr;
-	SK_U32	XaCsr;
-	SK_U64	ToutStart;
-	int		i;
-	int		ToutCnt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((Dir & SK_STOP_TX) != 0) {
-		/* disable receiver and transmitter */
-		SkMacRxTxDisable(pAC, IoC, Port);
-		
-		/* stop both transmit queues */
-		/*
-		 * If the BMU is in the reset state CSR_STOP will terminate
-		 * immediately.
-		 */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP);
-
-		ToutStart = SkOsGetTime(pAC);
-		ToutCnt = 0;
-		do {
-			/*
-			 * Clear packet arbiter timeout to make sure
-			 * this loop will terminate.
-			 */
-			SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
-				PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
-
-			/*
-			 * If the transfer stucks at the MAC the STOP command will not
-			 * terminate if we don't flush the XMAC's transmit FIFO !
-			 */
-			SkMacFlushTxFifo(pAC, IoC, Port);
-
-			XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
-			XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
-
-			if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
-				/*
-				 * Timeout of 1/18 second reached.
-				 * This needs to be checked at 1/18 sec only.
-				 */
-				ToutCnt++;
-				if (ToutCnt > 1) {
-					/* Might be a problem when the driver event handler
-					 * calls StopPort again. XXX.
-					 */
-
-					/* Fatal Error, Loop aborted */
-					SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018,
-						SKERR_HWI_E018MSG);
-#ifndef SK_DIAG
-					Para.Para64 = Port;
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-#endif /* !SK_DIAG */
-					return;
-				}
-				/*
-				 * Cache incoherency workaround: Assume a start command
-				 * has been lost while sending the frame.
-				 */
-				ToutStart = SkOsGetTime(pAC);
-
-				if ((XsCsr & CSR_STOP) != 0) {
-					SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START);
-				}
-				if ((XaCsr & CSR_STOP) != 0) {
-					SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START);
-				}
-			}
-
-			/*
-			 * Because of the ASIC problem report entry from 21.08.1998 it is
-			 * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
-			 */
-		} while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE ||
-				 (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
-		/* Reset the MAC depending on the RstMode */
-		if (RstMode == SK_SOFT_RST) {
-			SkMacSoftRst(pAC, IoC, Port);
-		}
-		else {
-			SkMacHardRst(pAC, IoC, Port);
-		}
- 		
-		/* Disable Force Sync bit and Enable Alloc bit */
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-			TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-		
-		/* Stop Interval Timer and Limit Counter of Tx Arbiter */
-		SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
-		SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
-
-		/* Perform a local reset of the port's Tx path */
-
-		/* Reset the PCI FIFO of the async Tx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the PCI FIFO of the sync Tx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the RAM Buffer async Tx queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
-		/* Reset the RAM Buffer sync Tx queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
-		
-		/* Reset Tx MAC FIFO */
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/* Note: MFF_RST_SET does NOT reset the XMAC ! */
-			SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET);
-
-			/* switch Link and Tx LED off, stop the LED counters */
-			/* Link LED is switched off by the RLMT and the Diag itself */
-			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			/* Reset TX MAC FIFO */
-			SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
-		}
-#endif /* YUKON */
-	}
-
-	if ((Dir & SK_STOP_RX) != 0) {
-		/*
-		 * The RX Stop Command will not terminate if no buffers
-		 * are queued in the RxD ring. But it will always reach
-		 * the Idle state. Therefore we can use this feature to
-		 * stop the transfer of received packets.
-		 */
-		/* stop the port's receive queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP);
-		
-		i = 100;
-		do {
-			/*
-			 * Clear packet arbiter timeout to make sure
-			 * this loop will terminate
-			 */
-			SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
-				PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
-
-			DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff);
-
-			/* timeout if i==0 (bug fix for #10748) */
-			if (--i == 0) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
-					SKERR_HWI_E024MSG);
-				break;
-			}
-			/*
-			 * because of the ASIC problem report entry from 21.08.98
-			 * it is required to wait until CSR_STOP is reset and
-			 * CSR_SV_IDLE is set.
-			 */
-		} while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
-		/* The path data transfer activity is fully stopped now */
-
-		/* Perform a local reset of the port's Rx path */
-
-		 /*	Reset the PCI FIFO of the Rx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the RAM Buffer receive queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
-
-		/* Reset Rx MAC FIFO */
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			
-			SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
-
-			/* switch Rx LED off, stop the LED counter */
-			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			/* Reset Rx MAC FIFO */
-			SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
-		}
-#endif /* YUKON */
-	}
-}	/* SkGeStopPort */
-
-
-/******************************************************************************
- *
- *	SkGeInit0() - Level 0 Initialization
- *
- * Description:
- *	- Initialize the BMU address offsets
- *
- * Returns:
- *	nothing
- */
-static void SkGeInit0(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	int i;
-	SK_GEPORT *pPrt;
-
-	for (i = 0; i < SK_MAX_MACS; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		pPrt->PState = SK_PRT_RESET;
-		pPrt->PRxQOff = QOffTab[i].RxQOff;
-		pPrt->PXsQOff = QOffTab[i].XsQOff;
-		pPrt->PXaQOff = QOffTab[i].XaQOff;
-		pPrt->PCheckPar = SK_FALSE;
-		pPrt->PIsave = 0;
-		pPrt->PPrevShorts = 0;
-		pPrt->PLinkResCt = 0;
-		pPrt->PAutoNegTOCt = 0;
-		pPrt->PPrevRx = 0;
-		pPrt->PPrevFcs = 0;
-		pPrt->PRxLim = SK_DEF_RX_WA_LIM;
-		pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
-		pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS;
-		pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS;
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN;
-		pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE;
-		pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
-		pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL |
-			SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL);
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-		pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
-		pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-		pPrt->PMSCap = 0;
-		pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO;
-		pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET;
-		pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
-		pPrt->PAutoNegFail = SK_FALSE;
-		pPrt->PHWLinkUp = SK_FALSE;
-		pPrt->PLinkBroken = SK_TRUE; /* See WA code */
-		pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
-		pPrt->PMacColThres = TX_COL_DEF;
-		pPrt->PMacJamLen = TX_JAM_LEN_DEF;
-		pPrt->PMacJamIpgVal	= TX_JAM_IPG_DEF;
-		pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
-		pPrt->PMacIpgData = IPG_DATA_DEF;
-		pPrt->PMacLimit4 = SK_FALSE;
-	}
-
-	pAC->GIni.GIPortUsage = SK_RED_LINK;
-	pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
-	pAC->GIni.GIValIrqMask = IS_ALL_MSK;
-
-}	/* SkGeInit0*/
-
-
-/******************************************************************************
- *
- *	SkGeInit1() - Level 1 Initialization
- *
- * Description:
- *	o Do a software reset.
- *	o Clear all reset bits.
- *	o Verify that the detected hardware is present.
- *	  Return an error if not.
- *	o Get the hardware configuration
- *		+ Read the number of MACs/Ports.
- *		+ Read the RAM size.
- *		+ Read the PCI Revision Id.
- *		+ Find out the adapters host clock speed
- *		+ Read and check the PHY type
- *
- * Returns:
- *	0:	success
- *	5:	Unexpected PHY type detected
- *	6:	HW self test failed
- */
-static int SkGeInit1(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	SK_U8	Byte;
-	SK_U16	Word;
-	SK_U16	CtrlStat;
-	SK_U32	DWord;
-	int	RetVal;
-	int	i;
-
-	RetVal = 0;
-
-	/* save CLK_RUN bits (YUKON-Lite) */
-	SK_IN16(IoC, B0_CTST, &CtrlStat);
-
-	/* do the SW-reset */
-	SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-
-	/* release the SW-reset */
-	SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
-
-	/* reset all error bits in the PCI STATUS register */
-	/*
-	 * Note: PCI Cfg cycles cannot be used, because they are not
-	 *		 available on some platforms after 'boot time'.
-	 */
-	SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-	
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-	SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-	/* release Master Reset */
-	SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
-
-#ifdef CLK_RUN
-	CtrlStat |= CS_CLK_RUN_ENA;
-#endif /* CLK_RUN */
-
-	/* restore CLK_RUN bits */
-	SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
-		(CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
-
-	/* read Chip Identification Number */
-	SK_IN8(IoC, B2_CHIP_ID, &Byte);
-	pAC->GIni.GIChipId = Byte;
-	
-	/* read number of MACs */
-	SK_IN8(IoC, B2_MAC_CFG, &Byte);
-	pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
-	
-	/* get Chip Revision Number */
-	pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
-
-	/* get diff. PCI parameters */
-	SK_IN16(IoC, B0_CTST, &CtrlStat);
-	
-	/* read the adapters RAM size */
-	SK_IN8(IoC, B2_E_0, &Byte);
-	
-	pAC->GIni.GIGenesis = SK_FALSE;
-	pAC->GIni.GIYukon = SK_FALSE;
-	pAC->GIni.GIYukonLite = SK_FALSE;
-
-#ifdef GENESIS
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-
-		pAC->GIni.GIGenesis = SK_TRUE;
-
-		if (Byte == (SK_U8)3) {						
-			/* special case: 4 x 64k x 36, offset = 0x80000 */
-			pAC->GIni.GIRamSize = 1024;
-			pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
-		}
-		else {
-			pAC->GIni.GIRamSize = (int)Byte * 512;
-			pAC->GIni.GIRamOffs = 0;
-		}
-		/* all GE adapters work with 53.125 MHz host clock */
-		pAC->GIni.GIHstClkFact = SK_FACT_53;
-		
-		/* set Descr. Poll Timer Init Value to 250 ms */
-		pAC->GIni.GIPollTimerVal =
-			SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
-		
-		pAC->GIni.GIYukon = SK_TRUE;
-		
-		pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
-		
-		pAC->GIni.GIRamOffs = 0;
-		
-		/* WA for chip Rev. A */
-		pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
-			pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
-		
-		/* get PM Capabilities of PCI config space */
-		SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word);
-
-		/* check if VAUX is available */
-		if (((CtrlStat & CS_VAUX_AVAIL) != 0) &&
-			/* check also if PME from D3cold is set */
-			((Word & PCI_PME_D3C_SUP) != 0)) {
-			/* set entry in GE init struct */
-			pAC->GIni.GIVauxAvail = SK_TRUE;
-		}
-		
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
-			/* this is Rev. A1 */
-			pAC->GIni.GIYukonLite = SK_TRUE;
-		}
-		else {
-			/* save Flash-Address Register */
-			SK_IN32(IoC, B2_FAR, &DWord);
-
-			/* test Flash-Address Register */
-			SK_OUT8(IoC, B2_FAR + 3, 0xff);
-			SK_IN8(IoC, B2_FAR + 3, &Byte);
-
-			if (Byte != 0) {
-				/* this is Rev. A0 */
-				pAC->GIni.GIYukonLite = SK_TRUE;
-
-				/* restore Flash-Address Register */
-				SK_OUT32(IoC, B2_FAR, DWord);
-			}
-		}
-
-		/* switch power to VCC (WA for VAUX problem) */
-		SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
-			PC_VAUX_OFF | PC_VCC_ON));
-
-		/* read the Interrupt source */
-		SK_IN32(IoC, B0_ISRC, &DWord);
-		
-		if ((DWord & IS_HW_ERR) != 0) {
-			/* read the HW Error Interrupt source */
-			SK_IN32(IoC, B0_HWE_ISRC, &DWord);
-			
-			if ((DWord & IS_IRQ_SENSOR) != 0) {
-				/* disable HW Error IRQ */
-				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
-			}
-		}
-		
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-			/* set GMAC Link Control reset */
-			SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET);
-
-			/* clear GMAC Link Control reset */
-			SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
-		}
-		/* all YU chips work with 78.125 MHz host clock */
-		pAC->GIni.GIHstClkFact = SK_FACT_78;
-		
-		pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;	/* 215 ms */
-	}
-#endif /* YUKON */
-
-	/* check if 64-bit PCI Slot is present */
-	pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
-	
-	/* check if 66 MHz PCI Clock is active */
-	pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
-
-	/* read PCI HW Revision Id. */
-	SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte);
-	pAC->GIni.GIPciHwRev = Byte;
-
-	/* read the PMD type */
-	SK_IN8(IoC, B2_PMD_TYP, &Byte);
-	pAC->GIni.GICopperType = (SK_U8)(Byte == 'T');
-
-	/* read the PHY type */
-	SK_IN8(IoC, B2_E_1, &Byte);
-
-	Byte &= 0x0f;	/* the PHY type is stored in the lower nibble */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			switch (Byte) {
-			case SK_PHY_XMAC:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC;
-				break;
-			case SK_PHY_BCOM:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM;
-				pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
-					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
-				break;
-#ifdef OTHER_PHY
-			case SK_PHY_LONE:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE;
-				break;
-			case SK_PHY_NAT:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT;
-				break;
-#endif /* OTHER_PHY */
-			default:
-				/* ERROR: unexpected PHY type detected */
-				RetVal = 5;
-				break;
-			}
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			
-			if (Byte < (SK_U8)SK_PHY_MARV_COPPER) {
-				/* if this field is not initialized */
-				Byte = (SK_U8)SK_PHY_MARV_COPPER;
-				
-				pAC->GIni.GICopperType = SK_TRUE;
-			}
-			
-			pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV;
-			
-			if (pAC->GIni.GICopperType) {
-
-				pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO |
-					SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS |
-					SK_LSPEED_CAP_1000MBPS);
-				
-				pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
-				
-				pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
-					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
-			}
-			else {
-				Byte = (SK_U8)SK_PHY_MARV_FIBER;
-			}
-		}
-#endif /* YUKON */
-		
-		pAC->GIni.GP[i].PhyType = (int)Byte;
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("PHY type: %d  PHY addr: %04x\n", Byte,
-			pAC->GIni.GP[i].PhyAddr));
-	}
-	
-	/* get MAC Type & set function pointers dependent on */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		pAC->GIni.GIMacType = SK_MAC_XMAC;
-
-		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkXmUpdateStats;
-		pAC->GIni.GIFunc.pFnMacStatistic	= SkXmMacStatistic;
-		pAC->GIni.GIFunc.pFnMacResetCounter	= SkXmResetCounter;
-		pAC->GIni.GIFunc.pFnMacOverflow		= SkXmOverflowStatus;
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		pAC->GIni.GIMacType = SK_MAC_GMAC;
-
-		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkGmUpdateStats;
-		pAC->GIni.GIFunc.pFnMacStatistic	= SkGmMacStatistic;
-		pAC->GIni.GIFunc.pFnMacResetCounter	= SkGmResetCounter;
-		pAC->GIni.GIFunc.pFnMacOverflow		= SkGmOverflowStatus;
-
-#ifdef SPECIAL_HANDLING
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-			/* check HW self test result */
-			SK_IN8(IoC, B2_E_3, &Byte);
-			if (Byte & B2_E3_RES_MASK) {
-				RetVal = 6;
-			}
-		}
-#endif
-	}
-#endif /* YUKON */
-	
-	return(RetVal);
-}	/* SkGeInit1 */
-
-
-/******************************************************************************
- *
- *	SkGeInit2() - Level 2 Initialization
- *
- * Description:
- *	- start the Blink Source Counter
- *	- start the Descriptor Poll Timer
- *	- configure the MAC-Arbiter
- *	- configure the Packet-Arbiter
- *	- enable the Tx Arbiters
- *	- enable the RAM Interface Arbiter
- *
- * Returns:
- *	nothing
- */
-static void SkGeInit2(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-#ifdef GENESIS
-	SK_U32	DWord;
-#endif /* GENESIS */
-	int		i;
-
-	/* start the Descriptor Poll Timer */
-	if (pAC->GIni.GIPollTimerVal != 0) {
-		if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) {
-			pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG);
-		}
-		SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal);
-		SK_OUT8(IoC, B28_DPT_CTRL, DPT_START);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* start the Blink Source Counter */
-		DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-
-		SK_OUT32(IoC, B2_BSC_INI, DWord);
-		SK_OUT8(IoC, B2_BSC_CTRL, BSC_START);
-
-		/*
-		 * Configure the MAC Arbiter and the Packet Arbiter.
-		 * They will be started once and never be stopped.
-		 */
-		SkGeInitMacArb(pAC, IoC);
-
-		SkGeInitPktArb(pAC, IoC);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* start Time Stamp Timer */
-		SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
-	}
-#endif /* YUKON */
-
-	/* enable the Tx Arbiters */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB);
-	}
-
-	/* enable the RAM Interface Arbiter */
-	SkGeInitRamIface(pAC, IoC);
-
-}	/* SkGeInit2 */
-
-/******************************************************************************
- *
- *	SkGeInit() - Initialize the GE Adapter with the specified level.
- *
- * Description:
- *	Level	0:	Initialize the Module structures.
- *	Level	1:	Generic Hardware Initialization. The IOP/MemBase pointer has
- *				to be set before calling this level.
- *
- *			o Do a software reset.
- *			o Clear all reset bits.
- *			o Verify that the detected hardware is present.
- *			  Return an error if not.
- *			o Get the hardware configuration
- *				+ Set GIMacsFound with the number of MACs.
- *				+ Store the RAM size in GIRamSize.
- *				+ Save the PCI Revision ID in GIPciHwRev.
- *			o return an error
- *				if Number of MACs > SK_MAX_MACS
- *
- *			After returning from Level 0 the adapter
- *			may be accessed with IO operations.
- *
- *	Level	2:	start the Blink Source Counter
- *
- * Returns:
- *	0:	success
- *	1:	Number of MACs exceeds SK_MAX_MACS	(after level 1)
- *	2:	Adapter not present or not accessible
- *	3:	Illegal initialization level
- *	4:	Initialization Level 1 Call missing
- *	5:	Unexpected PHY type detected
- *	6:	HW self test failed
- */
-int	SkGeInit(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Level)		/* initialization level */
-{
-	int		RetVal;		/* return value */
-	SK_U32	DWord;
-
-	RetVal = 0;
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-		("SkGeInit(Level %d)\n", Level));
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		/* Initialization Level 0 */
-		SkGeInit0(pAC, IoC);
-		pAC->GIni.GILevel = SK_INIT_DATA;
-		break;
-	
-	case SK_INIT_IO:
-		/* Initialization Level 1 */
-		RetVal = SkGeInit1(pAC, IoC);
-		if (RetVal != 0) {
-			break;
-		}
-
-		/* check if the adapter seems to be accessible */
-		SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
-		SK_IN32(IoC, B2_IRQM_INI, &DWord);
-		SK_OUT32(IoC, B2_IRQM_INI, 0L);
-		
-		if (DWord != SK_TEST_VAL) {
-			RetVal = 2;
-			break;
-		}
-
-		/* check if the number of GIMacsFound matches SK_MAX_MACS */
-		if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
-			RetVal = 1;
-			break;
-		}
-
-		/* Level 1 successfully passed */
-		pAC->GIni.GILevel = SK_INIT_IO;
-		break;
-	
-	case SK_INIT_RUN:
-		/* Initialization Level 2 */
-		if (pAC->GIni.GILevel != SK_INIT_IO) {
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG);
-#endif /* !SK_DIAG */
-			RetVal = 4;
-			break;
-		}
-		SkGeInit2(pAC, IoC);
-
-		/* Level 2 successfully passed */
-		pAC->GIni.GILevel = SK_INIT_RUN;
-		break;
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
-		RetVal = 3;
-		break;
-	}
-
-	return(RetVal);
-}	/* SkGeInit */
-
-
-/******************************************************************************
- *
- *	SkGeDeInit() - Deinitialize the adapter
- *
- * Description:
- *	All ports of the adapter will be stopped if not already done.
- *	Do a software reset and switch off all LEDs.
- *
- * Returns:
- *	nothing
- */
-void SkGeDeInit(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	int	i;
-	SK_U16	Word;
-
-#if (!defined(SK_SLIM) && !defined(VCPU))
-	/* ensure I2C is ready */
-	SkI2cWaitIrq(pAC, IoC);
-#endif	
-
-	/* stop all current transfer activity */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
-			pAC->GIni.GP[i].PState != SK_PRT_RESET) {
-
-			SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
-		}
-	}
-
-	/* Reset all bits in the PCI STATUS register */
-	/*
-	 * Note: PCI Cfg cycles cannot be used, because they are not
-	 *	 available on some platforms after 'boot time'.
-	 */
-	SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-	
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-	SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-	/* do the reset, all LEDs are switched off now */
-	SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-	
-	pAC->GIni.GILevel = SK_INIT_DATA;
-}	/* SkGeDeInit */
-
-
-/******************************************************************************
- *
- *	SkGeInitPort()	Initialize the specified port.
- *
- * Description:
- *	PRxQSize, PXSQSize, and PXAQSize has to be
- *	configured for the specified port before calling this function.
- *  The descriptor rings has to be initialized too.
- *
- *	o (Re)configure queues of the specified port.
- *	o configure the MAC of the specified port.
- *	o put ASIC and MAC(s) in operational mode.
- *	o initialize Rx/Tx and Sync LED
- *	o initialize RAM Buffers and MAC FIFOs
- *
- *	The port is ready to connect when returning.
- *
- * Note:
- *	The MAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	0:	success
- *	1:	Queue size initialization error. The configured values
- *		for PRxQSize, PXSQSize, or PXAQSize are invalid for one
- *		or more queues. The specified port was NOT initialized.
- *		An error log entry was generated.
- *	2:	The port has to be stopped before it can be initialized again.
- */
-int SkGeInitPort(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port to configure */
-{
-	SK_GEPORT *pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (SkGeCheckQSize(pAC, Port) != 0) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
-		return(1);
-	}
-	
-	if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
-		return(2);
-	}
-
-	/* configuration ok, initialize the Port now */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* initialize Rx, Tx and Link LED */
-		/*
-		 * If 1000BT Phy needs LED initialization than swap
-		 * LED and XMAC initialization order
-		 */
-		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
-		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
-		/* The Link LED is initialized by RLMT or Diagnostics itself */
-		
-		SkXmInitMac(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-
-		SkGmInitMac(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-	
-	/* do NOT initialize the Link Sync Counter */
-
-	SkGeInitMacFifo(pAC, IoC, Port);
-	
-	SkGeInitRamBufs(pAC, IoC, Port);
-	
-	if (pPrt->PXSQSize != 0) {
-		/* enable Force Sync bit if synchronous queue available */
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
-	}
-	
-	SkGeInitBmu(pAC, IoC, Port);
-
-	/* mark port as initialized */
-	pPrt->PState = SK_PRT_INIT;
-
-	return(0);
-}	/* SkGeInitPort */
diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
deleted file mode 100644
index 0a6f67a..0000000
--- a/drivers/net/sk98lin/skgemib.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgemib.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/09/15 13:38:12 $
- * Purpose:	Private Network Management Interface Management Database
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * PRIVATE OID handler function prototypes
- */
-PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action,
-	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
-	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int* pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-
-#ifdef SK_POWER_MGMT
-PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_DIAG_SUPPORT */
-
-
-/* defines *******************************************************************/
-#define ID_TABLE_SIZE (sizeof(IdTable)/sizeof(IdTable[0]))
-
-
-/* global variables **********************************************************/
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
-	{OID_GEN_XMIT_OK,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
-	{OID_GEN_RCV_OK,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
-	{OID_GEN_XMIT_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_RCV_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_RCV_NO_BUFFER,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_DIRECTED_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
-	{OID_GEN_MULTICAST_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
-	{OID_GEN_BROADCAST_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
-	{OID_GEN_DIRECTED_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
-	{OID_GEN_MULTICAST_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
-	{OID_GEN_BROADCAST_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
-	{OID_GEN_RCV_CRC_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
-	{OID_GEN_TRANSMIT_QUEUE_LENGTH,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_802_3_PERMANENT_ADDRESS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, 0},
-	{OID_802_3_CURRENT_ADDRESS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, 0},
-	{OID_802_3_RCV_ERROR_ALIGNMENT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
-	{OID_802_3_XMIT_ONE_COLLISION,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
-	{OID_802_3_XMIT_MORE_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
-	{OID_802_3_XMIT_DEFERRED,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
-	{OID_802_3_XMIT_MAX_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
-	{OID_802_3_RCV_OVERRUN,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
-	{OID_802_3_XMIT_UNDERRUN,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
-	{OID_802_3_XMIT_TIMES_CRS_LOST,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
-	{OID_802_3_XMIT_LATE_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
-#ifdef SK_POWER_MGMT
-	{OID_PNP_CAPABILITIES,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, PowerManagement, 0},
-	{OID_PNP_SET_POWER,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_QUERY_POWER,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, PowerManagement, 0},
-	{OID_PNP_ADD_WAKE_UP_PATTERN,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_REMOVE_WAKE_UP_PATTERN,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_ENABLE_WAKE_UP,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, PowerManagement, 0},
-#endif /* SK_POWER_MGMT */
-#ifdef SK_DIAG_SUPPORT
-	{OID_SKGE_DIAG_MODE,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, DiagActions, 0},
-#endif /* SK_DIAG_SUPPORT */
-	{OID_SKGE_MDB_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(MgmtDBVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SUPPORTED_LIST,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ALL_DATA,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, OidStruct, 0},
-	{OID_SKGE_VPD_FREE_BYTES,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdFreeBytes),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ENTRIES_LIST,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdEntriesList),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ENTRIES_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdEntriesNumber),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_KEY,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_VALUE,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ACCESS,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ACTION,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
-		SK_PNMI_RW, Vpd, 0},
-	{OID_SKGE_PORT_NUMBER,		
-		1,
-		0,
-		SK_PNMI_MAI_OFF(PortNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DEVICE_TYPE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DeviceType),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_DESCR,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverDescr),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_RELDATE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverReleaseDate),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_FILENAME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverFileName),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_HW_DESCR,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(HwDescr),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_HW_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(HwVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHIPSET,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Chipset),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHIPID,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ChipId),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RAMSIZE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RamSize),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_VAUXAVAIL,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VauxAvail),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ACTION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Action),
-		SK_PNMI_RW, Perform, 0},
-	{OID_SKGE_RESULT,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TestResult),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_TYPE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusType),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_SPEED,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusSpeed),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_WIDTH,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusWidth),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_SW_QUEUE_LEN,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxSwQueueLen),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_SW_QUEUE_MAX,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxSwQueueMax),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_RETRY,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxRetryCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_INTR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxIntrCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_INTR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxIntrCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_NO_BUF_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxNoBufCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_NO_BUF_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxNoBufCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_USED_DESCR_NO,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxUsedDescrNo),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_DELIVERED_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxDeliveredCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_OCTETS_DELIV_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_HW_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxHwErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_HW_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxHwErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_IN_ERRORS_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(InErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_OUT_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(OutErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ERR_RECOVERY_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ErrRecoveryCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SYSUPTIME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(SysUpTime),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SENSOR_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(SensorNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SENSOR_INDEX,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_DESCR,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_TYPE,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_VALUE,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_THRES_LOW,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_THRES_UPP,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_THRES_LOW,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_THRES_UPP,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_STATUS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_CTS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_CTS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_TIME,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_TIME,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_CHKSM_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ChecksumNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHKSM_RX_OK_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_RX_UNABLE_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_RX_ERR_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_TX_OK_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_TX_UNABLE_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_STAT_TX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
-	{OID_SKGE_STAT_TX_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
-	{OID_SKGE_STAT_TX_BROADCAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
-	{OID_SKGE_STAT_TX_MULTICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
-	{OID_SKGE_STAT_TX_UNICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
-	{OID_SKGE_STAT_TX_LONGFRAMES,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
-	{OID_SKGE_STAT_TX_BURST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
-	{OID_SKGE_STAT_TX_PFLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
-	{OID_SKGE_STAT_TX_FLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
-	{OID_SKGE_STAT_TX_SINGLE_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
-	{OID_SKGE_STAT_TX_MULTI_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
-	{OID_SKGE_STAT_TX_EXCESS_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
-	{OID_SKGE_STAT_TX_LATE_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
-	{OID_SKGE_STAT_TX_DEFFERAL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
-	{OID_SKGE_STAT_TX_EXCESS_DEF,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
-	{OID_SKGE_STAT_TX_UNDERRUN,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
-	{OID_SKGE_STAT_TX_CARRIER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
-/*	{OID_SKGE_STAT_TX_UTIL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
-		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
-	{OID_SKGE_STAT_TX_64,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
-	{OID_SKGE_STAT_TX_127,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
-	{OID_SKGE_STAT_TX_255,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
-	{OID_SKGE_STAT_TX_511,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
-	{OID_SKGE_STAT_TX_1023,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
-	{OID_SKGE_STAT_TX_MAX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
-	{OID_SKGE_STAT_TX_SYNC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
-	{OID_SKGE_STAT_TX_SYNC_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
-	{OID_SKGE_STAT_RX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
-	{OID_SKGE_STAT_RX_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
-	{OID_SKGE_STAT_RX_BROADCAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
-	{OID_SKGE_STAT_RX_MULTICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
-	{OID_SKGE_STAT_RX_UNICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
-	{OID_SKGE_STAT_RX_LONGFRAMES,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
-	{OID_SKGE_STAT_RX_PFLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
-	{OID_SKGE_STAT_RX_FLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
-	{OID_SKGE_STAT_RX_PFLOWC_ERR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
-	{OID_SKGE_STAT_RX_FLOWC_UNKWN,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
-	{OID_SKGE_STAT_RX_BURST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
-	{OID_SKGE_STAT_RX_MISSED,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
-	{OID_SKGE_STAT_RX_FRAMING,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
-	{OID_SKGE_STAT_RX_OVERFLOW,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
-	{OID_SKGE_STAT_RX_JABBER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
-	{OID_SKGE_STAT_RX_CARRIER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
-	{OID_SKGE_STAT_RX_IR_LENGTH,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
-	{OID_SKGE_STAT_RX_SYMBOL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
-	{OID_SKGE_STAT_RX_SHORTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
-	{OID_SKGE_STAT_RX_RUNT,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
-	{OID_SKGE_STAT_RX_CEXT,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
-	{OID_SKGE_STAT_RX_TOO_LONG,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
-	{OID_SKGE_STAT_RX_FCS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
-/*	{OID_SKGE_STAT_RX_UTIL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
-		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
-	{OID_SKGE_STAT_RX_64,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
-	{OID_SKGE_STAT_RX_127,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
-	{OID_SKGE_STAT_RX_255,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
-	{OID_SKGE_STAT_RX_511,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
-	{OID_SKGE_STAT_RX_1023,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
-	{OID_SKGE_STAT_RX_MAX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
-	{OID_SKGE_PHYS_CUR_ADDR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
-		SK_PNMI_RW, Addr, 0},
-	{OID_SKGE_PHYS_FAC_ADDR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
-		SK_PNMI_RO, Addr, 0},
-	{OID_SKGE_PMD,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_CONNECTOR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_TYPE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_LINK_MODE_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_TRAP,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Trap),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TRAP_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TrapNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RLMT_MODE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtMode),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortNumber),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_ACTIVE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortActive),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_PREFERRED,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortPreferred),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeCts),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_TIME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeTime),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_ESTIM,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeEstimate),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_THRES,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeThreshold),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_INDEX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_TX_HELLO_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_RX_HELLO_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_TX_SP_REQ_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_RX_SP_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_MONITOR_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtMonitorNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RLMT_MONITOR_INDEX,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ADDR,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ERRS,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_TIMESTAMP,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ADMIN,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
-		SK_PNMI_RW, Monitor, 0},
-	{OID_SKGE_MTU,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(MtuSize),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_VCT_GET,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Vct, 0},
-	{OID_SKGE_VCT_SET,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, Vct, 0},
-	{OID_SKGE_VCT_STATUS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Vct, 0},
-	{OID_SKGE_BOARDLEVEL,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-};
-
diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
deleted file mode 100644
index b36dd9a..0000000
--- a/drivers/net/sk98lin/skgepnmi.c
+++ /dev/null
@@ -1,8210 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnmi.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.111 $
- * Date:	$Date: 2003/09/15 13:35:35 $
- * Purpose:	Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-#ifndef _lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
-#endif /* !_lint */
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/xmac_ii.h"
-#include "h/skdebug.h"
-#include "h/skqueue.h"
-#include "h/skgepnmi.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skdrv2nd.h"
-#include "h/skgepnm2.h"
-#ifdef SK_POWER_MGMT
-#include "h/skgepmgt.h"
-#endif
-/* defines *******************************************************************/
-
-#ifndef DEBUG
-#define PNMI_STATIC	static
-#else	/* DEBUG */
-#define PNMI_STATIC
-#endif /* DEBUG */
-
-/*
- * Public Function prototypes
- */
-int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
-int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
-	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
-int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
-	unsigned int * pLen, SK_U32 NetIndex);
-
-
-/*
- * Private Function prototypes
- */
-
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
-	PhysPortIndex);
-PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
-	PhysPortIndex);
-PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
-PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
-PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
-	unsigned int PhysPortIndex, unsigned int StatIndex);
-PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
-	unsigned int StatIndex, SK_U32 NetIndex);
-PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
-PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
-	unsigned int *pEntries);
-PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
-	unsigned int KeyArrLen, unsigned int *pKeyNo);
-PNMI_STATIC int LookupId(SK_U32 Id);
-PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
-	unsigned int LastMac);
-PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
-PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
-	unsigned int PortIndex);
-PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
-	unsigned int SensorIndex);
-PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
-PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
-PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
-	unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-#include "skgemib.c"
-
-/* global variables **********************************************************/
-
-/*
- * Overflow status register bit table and corresponding counter
- * dependent on MAC type - the number relates to the size of overflow
- * mask returned by the pFnMacOverflow function
- */
-PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
-/* Bit0  */	{ SK_PNMI_HTX, 				SK_PNMI_HTX_UNICAST},
-/* Bit1  */	{ SK_PNMI_HTX_OCTETHIGH, 	SK_PNMI_HTX_BROADCAST},
-/* Bit2  */	{ SK_PNMI_HTX_OCTETLOW, 	SK_PNMI_HTX_PMACC},
-/* Bit3  */	{ SK_PNMI_HTX_BROADCAST, 	SK_PNMI_HTX_MULTICAST},
-/* Bit4  */	{ SK_PNMI_HTX_MULTICAST, 	SK_PNMI_HTX_OCTETLOW},
-/* Bit5  */	{ SK_PNMI_HTX_UNICAST, 		SK_PNMI_HTX_OCTETHIGH},
-/* Bit6  */	{ SK_PNMI_HTX_LONGFRAMES, 	SK_PNMI_HTX_64},
-/* Bit7  */	{ SK_PNMI_HTX_BURST, 		SK_PNMI_HTX_127},
-/* Bit8  */	{ SK_PNMI_HTX_PMACC, 		SK_PNMI_HTX_255},
-/* Bit9  */	{ SK_PNMI_HTX_MACC, 		SK_PNMI_HTX_511},
-/* Bit10 */	{ SK_PNMI_HTX_SINGLE_COL, 	SK_PNMI_HTX_1023},
-/* Bit11 */	{ SK_PNMI_HTX_MULTI_COL, 	SK_PNMI_HTX_MAX},
-/* Bit12 */	{ SK_PNMI_HTX_EXCESS_COL, 	SK_PNMI_HTX_LONGFRAMES},
-/* Bit13 */	{ SK_PNMI_HTX_LATE_COL, 	SK_PNMI_HTX_RESERVED},
-/* Bit14 */	{ SK_PNMI_HTX_DEFFERAL, 	SK_PNMI_HTX_COL},
-/* Bit15 */	{ SK_PNMI_HTX_EXCESS_DEF, 	SK_PNMI_HTX_LATE_COL},
-/* Bit16 */	{ SK_PNMI_HTX_UNDERRUN, 	SK_PNMI_HTX_EXCESS_COL},
-/* Bit17 */	{ SK_PNMI_HTX_CARRIER, 		SK_PNMI_HTX_MULTI_COL},
-/* Bit18 */	{ SK_PNMI_HTX_UTILUNDER, 	SK_PNMI_HTX_SINGLE_COL},
-/* Bit19 */	{ SK_PNMI_HTX_UTILOVER, 	SK_PNMI_HTX_UNDERRUN},
-/* Bit20 */	{ SK_PNMI_HTX_64, 			SK_PNMI_HTX_RESERVED},
-/* Bit21 */	{ SK_PNMI_HTX_127, 			SK_PNMI_HTX_RESERVED},
-/* Bit22 */	{ SK_PNMI_HTX_255, 			SK_PNMI_HTX_RESERVED},
-/* Bit23 */	{ SK_PNMI_HTX_511, 			SK_PNMI_HTX_RESERVED},
-/* Bit24 */	{ SK_PNMI_HTX_1023, 		SK_PNMI_HTX_RESERVED},
-/* Bit25 */	{ SK_PNMI_HTX_MAX, 			SK_PNMI_HTX_RESERVED},
-/* Bit26 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit27 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit28 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit29 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit30 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit31 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit32 */	{ SK_PNMI_HRX, 				SK_PNMI_HRX_UNICAST},
-/* Bit33 */	{ SK_PNMI_HRX_OCTETHIGH, 	SK_PNMI_HRX_BROADCAST},
-/* Bit34 */	{ SK_PNMI_HRX_OCTETLOW, 	SK_PNMI_HRX_PMACC},
-/* Bit35 */	{ SK_PNMI_HRX_BROADCAST, 	SK_PNMI_HRX_MULTICAST},
-/* Bit36 */	{ SK_PNMI_HRX_MULTICAST, 	SK_PNMI_HRX_FCS},
-/* Bit37 */	{ SK_PNMI_HRX_UNICAST, 		SK_PNMI_HRX_RESERVED},
-/* Bit38 */	{ SK_PNMI_HRX_PMACC, 		SK_PNMI_HRX_OCTETLOW},
-/* Bit39 */	{ SK_PNMI_HRX_MACC, 		SK_PNMI_HRX_OCTETHIGH},
-/* Bit40 */	{ SK_PNMI_HRX_PMACC_ERR, 	SK_PNMI_HRX_BADOCTETLOW},
-/* Bit41 */	{ SK_PNMI_HRX_MACC_UNKWN,	SK_PNMI_HRX_BADOCTETHIGH},
-/* Bit42 */	{ SK_PNMI_HRX_BURST, 		SK_PNMI_HRX_UNDERSIZE},
-/* Bit43 */	{ SK_PNMI_HRX_MISSED, 		SK_PNMI_HRX_RUNT},
-/* Bit44 */	{ SK_PNMI_HRX_FRAMING, 		SK_PNMI_HRX_64},
-/* Bit45 */	{ SK_PNMI_HRX_OVERFLOW, 	SK_PNMI_HRX_127},
-/* Bit46 */	{ SK_PNMI_HRX_JABBER, 		SK_PNMI_HRX_255},
-/* Bit47 */	{ SK_PNMI_HRX_CARRIER, 		SK_PNMI_HRX_511},
-/* Bit48 */	{ SK_PNMI_HRX_IRLENGTH, 	SK_PNMI_HRX_1023},
-/* Bit49 */	{ SK_PNMI_HRX_SYMBOL, 		SK_PNMI_HRX_MAX},
-/* Bit50 */	{ SK_PNMI_HRX_SHORTS, 		SK_PNMI_HRX_LONGFRAMES},
-/* Bit51 */	{ SK_PNMI_HRX_RUNT, 		SK_PNMI_HRX_TOO_LONG},
-/* Bit52 */	{ SK_PNMI_HRX_TOO_LONG, 	SK_PNMI_HRX_JABBER},
-/* Bit53 */	{ SK_PNMI_HRX_FCS, 			SK_PNMI_HRX_RESERVED},
-/* Bit54 */	{ SK_PNMI_HRX_RESERVED, 	SK_PNMI_HRX_OVERFLOW},
-/* Bit55 */	{ SK_PNMI_HRX_CEXT, 		SK_PNMI_HRX_RESERVED},
-/* Bit56 */	{ SK_PNMI_HRX_UTILUNDER, 	SK_PNMI_HRX_RESERVED},
-/* Bit57 */	{ SK_PNMI_HRX_UTILOVER, 	SK_PNMI_HRX_RESERVED},
-/* Bit58 */	{ SK_PNMI_HRX_64, 			SK_PNMI_HRX_RESERVED},
-/* Bit59 */	{ SK_PNMI_HRX_127, 			SK_PNMI_HRX_RESERVED},
-/* Bit60 */	{ SK_PNMI_HRX_255, 			SK_PNMI_HRX_RESERVED},
-/* Bit61 */	{ SK_PNMI_HRX_511, 			SK_PNMI_HRX_RESERVED},
-/* Bit62 */	{ SK_PNMI_HRX_1023, 		SK_PNMI_HRX_RESERVED},
-/* Bit63 */	{ SK_PNMI_HRX_MAX, 			SK_PNMI_HRX_RESERVED}
-};
-
-/*
- * Table for hardware register saving on resets and port switches
- */
-PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
-	/* SK_PNMI_HTX */
-	{{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_OCTETHIGH */
-	{{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
-	/* SK_PNMI_HTX_OCTETLOW */
-	{{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
-	/* SK_PNMI_HTX_BROADCAST */
-	{{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_MULTICAST */
-	{{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_UNICAST */
-	{{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_BURST */
-	{{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_PMACC */
-	{{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
-	/* SK_PNMI_HTX_MACC */
-	{{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_COL */
-	{{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_SINGLE_COL */
-	{{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_MULTI_COL */
-	{{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_EXCESS_COL */
-	{{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_LATE_COL */
-	{{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_DEFFERAL */
-	{{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_EXCESS_DEF */
-	{{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UNDERRUN */
-	{{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
-	/* SK_PNMI_HTX_CARRIER */
-	{{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UTILUNDER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UTILOVER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_64 */
-	{{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
-	/* SK_PNMI_HTX_127 */
-	{{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
-	/* SK_PNMI_HTX_255 */
-	{{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
-	/* SK_PNMI_HTX_511 */
-	{{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
-	/* SK_PNMI_HTX_1023 */
-	{{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
-	/* SK_PNMI_HTX_MAX */
-	{{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
-	/* SK_PNMI_HTX_LONGFRAMES  */
-	{{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
-	/* SK_PNMI_HTX_SYNC */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_SYNC_OCTET */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_RESERVED */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX */
-	{{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_OCTETHIGH */
-	{{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
-	/* SK_PNMI_HRX_OCTETLOW */
-	{{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
-	/* SK_PNMI_HRX_BADOCTETHIGH */
-	{{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
-	/* SK_PNMI_HRX_BADOCTETLOW */
-	{{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
-	/* SK_PNMI_HRX_BROADCAST */
-	{{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_MULTICAST */
-	{{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_UNICAST */
-	{{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_PMACC */
-	{{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
-	/* SK_PNMI_HRX_MACC */
-	{{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_PMACC_ERR */
-	{{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_MACC_UNKWN */
-	{{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_BURST */
-	{{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_MISSED */
-	{{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_FRAMING */
-	{{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UNDERSIZE */
-	{{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
-	/* SK_PNMI_HRX_OVERFLOW */
-	{{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
-	/* SK_PNMI_HRX_JABBER */
-	{{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
-	/* SK_PNMI_HRX_CARRIER */
-	{{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_IRLENGTH */
-	{{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_SYMBOL */
-	{{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_SHORTS */
-	{{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_RUNT */
-	{{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
-	/* SK_PNMI_HRX_TOO_LONG */
-	{{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
-	/* SK_PNMI_HRX_FCS */
-	{{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
-	/* SK_PNMI_HRX_CEXT */
-	{{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UTILUNDER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UTILOVER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_64 */
-	{{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
-	/* SK_PNMI_HRX_127 */
-	{{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
-	/* SK_PNMI_HRX_255 */
-	{{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
-	/* SK_PNMI_HRX_511 */
-	{{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
-	/* SK_PNMI_HRX_1023 */
-	{{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
-	/* SK_PNMI_HRX_MAX */
-	{{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
-	/* SK_PNMI_HRX_LONGFRAMES */
-	{{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
-	/* SK_PNMI_HRX_RESERVED */
-	{{0, SK_FALSE}, {0, SK_FALSE}}
-};
-
-
-/*****************************************************************************
- *
- * Public functions
- *
- */
-
-/*****************************************************************************
- *
- * SkPnmiInit - Init function of PNMI
- *
- * Description:
- *	SK_INIT_DATA: Initialises the data structures
- *	SK_INIT_IO:   Resets the XMAC statistics, determines the device and
- *	              connector type.
- *	SK_INIT_RUN:  Starts a timer event for port switch per hour
- *	              calculation.
- *
- * Returns:
- *	Always 0
- */
-int SkPnmiInit(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Level)		/* Initialization level */
-{
-	unsigned int	PortMax;	/* Number of ports */
-	unsigned int	PortIndex;	/* Current port index in loop */
-	SK_U16		Val16;		/* Multiple purpose 16 bit variable */
-	SK_U8		Val8;		/* Mulitple purpose 8 bit variable */
-	SK_EVPARA	EventParam;	/* Event struct for timer event */
-	SK_PNMI_VCT	*pVctBackupData;
-
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiInit: Called, level=%d\n", Level));
-
-	switch (Level) {
-
-	case SK_INIT_DATA:
-		SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
-		pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
-		pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-		pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
-		for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
-
-			pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
-			pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
-		}
-
-#ifdef SK_PNMI_CHECK
-		if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
-			
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
-					   ("CounterOffset struct size (%d) differs from"
-						"SK_PNMI_MAX_IDX (%d)\n",
-						SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
-		}
-
-		if (SK_PNMI_MAX_IDX !=
-			(sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) {
-			
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG);
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
-					   ("StatAddr table size (%d) differs from "
-						"SK_PNMI_MAX_IDX (%d)\n",
-						(sizeof(StatAddr) /
-						 (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)),
-						 SK_PNMI_MAX_IDX));
-		}
-#endif /* SK_PNMI_CHECK */
-		break;
-
-	case SK_INIT_IO:
-		/*
-		 * Reset MAC counters
-		 */
-		PortMax = pAC->GIni.GIMacsFound;
-
-		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
-
-			pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
-		}
-		
-		/* Initialize DSP variables for Vct() to 0xff => Never written! */		
-		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
-			pAC->GIni.GP[PortIndex].PCableLen = 0xff;
-			pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
-			pVctBackupData->PCableLen = 0xff;
-		}
-		
-		/*
-		 * Get pci bus speed
-		 */
-		SK_IN16(IoC, B0_CTST, &Val16);
-		if ((Val16 & CS_BUS_CLOCK) == 0) {
-
-			pAC->Pnmi.PciBusSpeed = 33;
-		}
-		else {
-			pAC->Pnmi.PciBusSpeed = 66;
-		}
-
-		/*
-		 * Get pci bus width
-		 */
-		SK_IN16(IoC, B0_CTST, &Val16);
-		if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
-
-			pAC->Pnmi.PciBusWidth = 32;
-		}
-		else {
-			pAC->Pnmi.PciBusWidth = 64;
-		}
-
-		/*
-		 * Get chipset
-		 */
-		switch (pAC->GIni.GIChipId) {
-		case CHIP_ID_GENESIS:
-			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
-			break;
-
-		case CHIP_ID_YUKON:
-			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
-			break;
-
-		default:
-			break;
-		}
-
-		/*
-		 * Get PMD and DeviceType
-		 */
-		SK_IN8(IoC, B2_PMD_TYP, &Val8);
-		switch (Val8) {
-		case 'S':
-			pAC->Pnmi.PMD = 3;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020002;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020001;
-			}
-			break;
-
-		case 'L':
-			pAC->Pnmi.PMD = 2;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020004;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020003;
-			}
-			break;
-
-		case 'C':
-			pAC->Pnmi.PMD = 4;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020006;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020005;
-			}
-			break;
-
-		case 'T':
-			pAC->Pnmi.PMD = 5;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020008;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020007;
-			}
-			break;
-
-		default :
-			pAC->Pnmi.PMD = 1;
-			pAC->Pnmi.DeviceType = 0;
-			break;
-		}
-
-		/*
-		 * Get connector
-		 */
-		SK_IN8(IoC, B2_CONN_TYP, &Val8);
-		switch (Val8) {
-		case 'C':
-			pAC->Pnmi.Connector = 2;
-			break;
-
-		case 'D':
-			pAC->Pnmi.Connector = 3;
-			break;
-
-		case 'F':
-			pAC->Pnmi.Connector = 4;
-			break;
-
-		case 'J':
-			pAC->Pnmi.Connector = 5;
-			break;
-
-		case 'V':
-			pAC->Pnmi.Connector = 6;
-			break;
-
-		default:
-			pAC->Pnmi.Connector = 1;
-			break;
-		}
-		break;
-
-	case SK_INIT_RUN:
-		/*
-		 * Start timer for RLMT change counter
-		 */
-		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
-			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
-			EventParam);
-		break;
-
-	default:
-		break; /* Nothing todo */
-	}
-
-	return (0);
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetVar - Retrieves the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. If the instance
- *	-1 is passed, the values of all instances are returned in an
- *	array of values.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-static int SkPnmiGetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetVar - Presets the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	If the instance -1 is passed, an array of values is supposed and
- *	all instances of the OID will be set.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-static int SkPnmiPreSetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* Total length of management data */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetVar - Sets the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	If the instance -1 is passed, an array of values is supposed and
- *	all instances of the OID will be set.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-int SkPnmiSetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* Total length of management data */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Runs through the IdTable, queries the single OIDs and stores the
- *	returned data into the management database structure
- *	SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
- *	is stored in the IdTable. The return value of the function will also
- *	be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- *	minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-int SkPnmiGetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer to which the management data will be copied. */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	TableIndex;
-	unsigned int	DstOffset;
-	unsigned int	InstanceNo;
-	unsigned int	InstanceCnt;
-	SK_U32		Instance;
-	unsigned int	TmpLen;
-	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
-
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
-		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
-			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
-				(SK_U32)(-1));
-		}
-
-		*pLen = SK_PNMI_STRUCT_SIZE;
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-    /*
-     * Check NetIndex
-     */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-
-	/* Update statistic */
-	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
-
-	if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
-		SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	/*
-	 * Increment semaphores to indicate that an update was
-	 * already done
-	 */
-	pAC->Pnmi.MacUpdatedFlag ++;
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-	pAC->Pnmi.SirqUpdatedFlag ++;
-
-	/* Get vpd keys for instance calculation */
-	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
-	if (Ret != SK_PNMI_ERR_OK) {
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		pAC->Pnmi.RlmtUpdatedFlag --;
-		pAC->Pnmi.SirqUpdatedFlag --;
-
-		SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/* Retrieve values */
-	SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
-	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
-		InstanceNo = IdTable[TableIndex].InstanceNo;
-		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
-			InstanceCnt ++) {
-
-			DstOffset = IdTable[TableIndex].Offset +
-				(InstanceCnt - 1) *
-				IdTable[TableIndex].StructSize;
-
-			/*
-			 * For the VPD the instance is not an index number
-			 * but the key itself. Determin with the instance
-			 * counter the VPD key to be used.
-			 */
-			if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
-
-				SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
-			}
-			else {
-				Instance = (SK_U32)InstanceCnt;
-			}
-
-			TmpLen = *pLen - DstOffset;
-			Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
-				IdTable[TableIndex].Id, (char *)pBuf +
-				DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
-
-			/*
-			 * An unknown instance error means that we reached
-			 * the last instance of that variable. Proceed with
-			 * the next OID in the table and ignore the return
-			 * code.
-			 */
-			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
-                break;
-			}
-
-			if (Ret != SK_PNMI_ERR_OK) {
-
-				pAC->Pnmi.MacUpdatedFlag --;
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-				SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (Ret);
-			}
-		}
-	}
-
-	pAC->Pnmi.MacUpdatedFlag --;
-	pAC->Pnmi.RlmtUpdatedFlag --;
-	pAC->Pnmi.SirqUpdatedFlag --;
-
-	*pLen = SK_PNMI_STRUCT_SIZE;
-	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Calls a general sub-function for all this set stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	The sub-function runs through the IdTable, checks which OIDs are able
- *	to set, and calls the handler function of the OID to perform the
- *	preset. The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- */
-int SkPnmiPreSetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer which contains the data to be set */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
-    					pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Calls a general sub-function for all this set stuff. The return value
- *	of the function will also be stored in SK_PNMI_STRUCT_DATA if the
- *	passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- *	The sub-function runs through the IdTable, checks which OIDs are able
- *	to set, and calls the handler function of the OID to perform the
- *	set. The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- */
-int SkPnmiSetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer which contains the data to be set */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
-    					pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiEvent - Event handler
- *
- * Description:
- *	Handles the following events:
- *	SK_PNMI_EVT_SIRQ_OVERFLOW     When a hardware counter overflows an
- *	                              interrupt will be generated which is
- *	                              first handled by SIRQ which generates a
- *	                              this event. The event increments the
- *	                              upper 32 bit of the 64 bit counter.
- *	SK_PNMI_EVT_SEN_XXX           The event is generated by the I2C module
- *	                              when a sensor reports a warning or
- *	                              error. The event will store a trap
- *	                              message in the trap buffer.
- *	SK_PNMI_EVT_CHG_EST_TIMER     The timer event was initiated by this
- *	                              module and is used to calculate the
- *	                              port switches per hour.
- *	SK_PNMI_EVT_CLEAR_COUNTER     The event clears all counters and
- *	                              timestamps.
- *	SK_PNMI_EVT_XMAC_RESET        The event is generated by the driver
- *	                              before a hard reset of the XMAC is
- *	                              performed. All counters will be saved
- *	                              and added to the hardware counter
- *	                              values after reset to grant continuous
- *	                              counter values.
- *	SK_PNMI_EVT_RLMT_PORT_UP      Generated by RLMT to notify that a port
- *	                              went logically up. A trap message will
- *	                              be stored to the trap buffer.
- *	SK_PNMI_EVT_RLMT_PORT_DOWN    Generated by RLMT to notify that a port
- *	                              went logically down. A trap message will
- *	                              be stored to the trap buffer.
- *	SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
- *	                              spanning tree root bridges were
- *	                              detected. A trap message will be stored
- *	                              to the trap buffer.
- *	SK_PNMI_EVT_RLMT_ACTIVE_DOWN  Notifies PNMI that an active port went
- *	                              down. PNMI will not further add the
- *	                              statistic values to the virtual port.
- *	SK_PNMI_EVT_RLMT_ACTIVE_UP    Notifies PNMI that a port went up and
- *	                              is now an active port. PNMI will now
- *	                              add the statistic data of this port to
- *	                              the virtual port.
- *	SK_PNMI_EVT_RLMT_SET_NETS     Notifies PNMI about the net mode. The first parameter
- *	                              contains the number of nets. 1 means single net, 2 means
- *	                              dual net. The second parameter is -1
- *
- * Returns:
- *	Always 0
- */
-int SkPnmiEvent(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Event,		/* Event-Id */
-SK_EVPARA Param)	/* Event dependent parameter */
-{
-	unsigned int	PhysPortIndex;
-    unsigned int	MaxNetNumber;
-	int			CounterIndex;
-	int			Ret;
-	SK_U16		MacStatus;
-	SK_U64		OverflowStatus;
-	SK_U64		Mask;
-	int			MacType;
-	SK_U64		Value;
-	SK_U32		Val32;
-	SK_U16		Register;
-	SK_EVPARA	EventParam;
-	SK_U64		NewestValue;
-	SK_U64		OldestValue;
-	SK_U64		Delta;
-	SK_PNMI_ESTIMATE *pEst;
-	SK_U32		NetIndex;
-	SK_GEPORT	*pPrt;
-	SK_PNMI_VCT	*pVctBackupData;
-	SK_U32		RetCode;
-	int		i;
-	SK_U32		CableLength;
-
-
-#ifdef DEBUG
-	if (Event != SK_PNMI_EVT_XMAC_RESET) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-			("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
-			(unsigned int)Event, (unsigned int)Param.Para64));
-	}
-#endif /* DEBUG */
-	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
-
-	MacType = pAC->GIni.GIMacType;
-	
-	switch (Event) {
-
-	case SK_PNMI_EVT_SIRQ_OVERFLOW:
-		PhysPortIndex = (int)Param.Para32[0];
-		MacStatus = (SK_U16)Param.Para32[1];
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
-				 " wrong, PhysPortIndex=0x%x\n",
-				PhysPortIndex));
-			return (0);
-		}
-#endif /* DEBUG */
-		OverflowStatus = 0;
-
-		/*
-		 * Check which source caused an overflow interrupt.
-		 */
-		if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
-				MacStatus, &OverflowStatus) != 0) ||
-			(OverflowStatus == 0)) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-
-		/*
-		 * Check the overflow status register and increment
-		 * the upper dword of corresponding counter.
-		 */
-		for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
-			CounterIndex ++) {
-
-			Mask = (SK_U64)1 << CounterIndex;
-			if ((OverflowStatus & Mask) == 0) {
-
-				continue;
-			}
-
-			switch (StatOvrflwBit[CounterIndex][MacType]) {
-
-			case SK_PNMI_HTX_UTILUNDER:
-			case SK_PNMI_HTX_UTILOVER:
-				if (MacType == SK_MAC_XMAC) {
-					XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
-					Register |= XM_TX_SAM_LINE;
-					XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
-				}
-				break;
-
-			case SK_PNMI_HRX_UTILUNDER:
-			case SK_PNMI_HRX_UTILOVER:
-				if (MacType == SK_MAC_XMAC) {
-					XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
-					Register |= XM_RX_SAM_LINE;
-					XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
-				}
-				break;
-
-			case SK_PNMI_HTX_OCTETHIGH:
-			case SK_PNMI_HTX_OCTETLOW:
-			case SK_PNMI_HTX_RESERVED:
-			case SK_PNMI_HRX_OCTETHIGH:
-			case SK_PNMI_HRX_OCTETLOW:
-			case SK_PNMI_HRX_IRLENGTH:
-			case SK_PNMI_HRX_RESERVED:
-			
-			/*
-			 * the following counters aren't be handled (id > 63)
-			 */
-			case SK_PNMI_HTX_SYNC:
-			case SK_PNMI_HTX_SYNC_OCTET:
-				break;
-
-			case SK_PNMI_HRX_LONGFRAMES:
-				if (MacType == SK_MAC_GMAC) {
-					pAC->Pnmi.Port[PhysPortIndex].
-						CounterHigh[CounterIndex] ++;
-				}
-				break;
-
-			default:
-				pAC->Pnmi.Port[PhysPortIndex].
-					CounterHigh[CounterIndex] ++;
-			}
-		}
-		break;
-
-	case SK_PNMI_EVT_SEN_WAR_LOW:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_SEN_WAR_UPP:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_SEN_ERR_LOW:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-	
-	case SK_PNMI_EVT_SEN_ERR_UPP:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_CHG_EST_TIMER:
-		/*
-		 * Calculate port switch average on a per hour basis
-		 *   Time interval for check       : 28125 ms
-		 *   Number of values for average  : 8
-		 *
-		 * Be careful in changing these values, on change check
-		 *   - typedef of SK_PNMI_ESTIMATE (Size of EstValue
-		 *     array one less than value number)
-		 *   - Timer initialization SkTimerStart() in SkPnmiInit
-		 *   - Delta value below must be multiplicated with
-		 *     power of 2
-		 *
-		 */
-		pEst = &pAC->Pnmi.RlmtChangeEstimate;
-		CounterIndex = pEst->EstValueIndex + 1;
-		if (CounterIndex == 7) {
-
-			CounterIndex = 0;
-		}
-		pEst->EstValueIndex = CounterIndex;
-
-		NewestValue = pAC->Pnmi.RlmtChangeCts;
-		OldestValue = pEst->EstValue[CounterIndex];
-		pEst->EstValue[CounterIndex] = NewestValue;
-
-		/*
-		 * Calculate average. Delta stores the number of
-		 * port switches per 28125 * 8 = 225000 ms
-		 */
-		if (NewestValue >= OldestValue) {
-
-			Delta = NewestValue - OldestValue;
-		}
-		else {
-			/* Overflow situation */
-			Delta = (SK_U64)(0 - OldestValue) + NewestValue;
-		}
-
-		/*
-		 * Extrapolate delta to port switches per hour.
-		 *     Estimate = Delta * (3600000 / 225000)
-		 *              = Delta * 16
-		 *              = Delta << 4
-		 */
-		pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
-
-		/*
-		 * Check if threshold is exceeded. If the threshold is
-		 * permanently exceeded every 28125 ms an event will be
-		 * generated to remind the user of this condition.
-		 */
-		if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
-			(pAC->Pnmi.RlmtChangeEstimate.Estimate >=
-			pAC->Pnmi.RlmtChangeThreshold)) {
-
-			QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
-			(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		}
-
-		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
-			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
-			EventParam);
-		break;
-
-	case SK_PNMI_EVT_CLEAR_COUNTER:
-		/*
-		 *  Param.Para32[0] contains the NetIndex (0 ..1).
-		 *  Param.Para32[1] is reserved, contains -1.
-		 */
-		NetIndex = (SK_U32)Param.Para32[0];
-
-#ifdef DEBUG
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
-				NetIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Set all counters and timestamps to zero.
-		 * The according NetIndex is required as a
-		 * parameter of the event.
-		 */
-		ResetCounter(pAC, IoC, NetIndex);
-		break;
-
-	case SK_PNMI_EVT_XMAC_RESET:
-		/*
-		 * To grant continuous counter values store the current
-		 * XMAC statistic values to the entries 1..n of the
-		 * CounterOffset array. XMAC Errata #2
-		 */
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif
-		PhysPortIndex = (unsigned int)Param.Para64;
-
-		/*
-		 * Update XMAC statistic to get fresh values
-		 */
-		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-		if (Ret != SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		/*
-		 * Increment semaphore to indicate that an update was
-		 * already done
-		 */
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
-				GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-			
-			pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
-		}
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_PORT_UP:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
-                 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/* Bugfix for XMAC errata (#10620)*/
-		if (MacType == SK_MAC_XMAC) {
-			/* Add incremental difference to offset (#10620)*/
-			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
-				XM_RXE_SHT_ERR, &Val32);
-			
-			Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
-				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
-			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
-				Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
-		}
-		
-		/* Tell VctStatus() that a link was up meanwhile. */
-		pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;		
-		break;
-
-    case SK_PNMI_EVT_RLMT_PORT_DOWN:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
-                 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/* Bugfix #10620 - get zero level for incremental difference */
-		if (MacType == SK_MAC_XMAC) {
-
-			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
-				XM_RXE_SHT_ERR, &Val32);
-			
-			pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
-				(((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
-				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
-		}
-		break;
-
-	case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-		NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
-				PhysPortIndex));
-		}
-
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
-				NetIndex));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * For now, ignore event if NetIndex != 0.
-		 */
-		if (Param.Para32[1] != 0) {
-
-			return (0);
-		}
-
-		/*
-		 * Nothing to do if port is already inactive
-		 */
-		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			return (0);
-		}
-
-		/*
-		 * Update statistic counters to calculate new offset for the virtual
-		 * port and increment semaphore to indicate that an update was already
-		 * done.
-		 */
-		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
-			SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Calculate new counter offset for virtual port to grant continous
-		 * counting on port switches. The virtual port consists of all currently
-		 * active ports. The port down event indicates that a port is removed
-		 * from the virtual port. Therefore add the counter value of the removed
-		 * port to the CounterOffset for the virtual port to grant the same
-		 * counter value.
-		 */
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
-			pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
-		}
-
-		/*
-		 * Set port to inactive
-		 */
-		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_ACTIVE_UP:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-		NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
-				PhysPortIndex));
-		}
-
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
-				NetIndex));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * For now, ignore event if NetIndex != 0.
-		 */
-		if (Param.Para32[1] != 0) {
-
-			return (0);
-		}
-
-		/*
-		 * Nothing to do if port is already active
-		 */
-		if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			return (0);
-		}
-
-		/*
-		 * Statistic maintenance
-		 */
-		pAC->Pnmi.RlmtChangeCts ++;
-		pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtNewMacTrap(pAC, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/*
-		 * Update statistic counters to calculate new offset for the virtual
-		 * port and increment semaphore to indicate that an update was
-		 * already done.
-		 */
-		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
-			SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Calculate new counter offset for virtual port to grant continous
-		 * counting on port switches. A new port is added to the virtual port.
-		 * Therefore substract the counter value of the new port from the
-		 * CounterOffset for the virtual port to grant the same value.
-		 */
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
-			pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
-		}
-
-		/* Set port to active */
-		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_SEGMENTATION:
-		/*
-		 * Para.Para32[0] contains the NetIndex.
-		 */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-    case SK_PNMI_EVT_RLMT_SET_NETS:
-		/*
-		 *  Param.Para32[0] contains the number of Nets.
-		 *  Param.Para32[1] is reserved, contains -1.
-		 */
-	    /*
-    	 * Check number of nets
-		 */
-		MaxNetNumber = pAC->GIni.GIMacsFound;
-		if (((unsigned int)Param.Para32[0] < 1)
-			|| ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
-			return (SK_PNMI_ERR_UNKNOWN_NET);
-		}
-
-        if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
-        	pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
-        }
-        else { /* dual net mode */
-        	pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
-        }
-        break;
-
-    case SK_PNMI_EVT_VCT_RESET:
-		PhysPortIndex = Param.Para32[0];
-		pPrt = &pAC->GIni.GP[PhysPortIndex];
-		pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-		
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
-			RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
-			if (RetCode == 2) {
-				/*
-				 * VCT test is still running.
-				 * Start VCT timer counter again.
-				 */
-				SK_MEMSET((char *) &Param, 0, sizeof(Param));
-				Param.Para32[0] = PhysPortIndex;
-				Param.Para32[1] = -1;
-				SkTimerStart(pAC, IoC,
-					&pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
-				4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
-				break;
-			}
-			pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
-			pAC->Pnmi.VctStatus[PhysPortIndex] |=
-				(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-			
-			/* Copy results for later use to PNMI struct. */
-			for (i = 0; i < 4; i++)  {
-				if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
-					if ((pPrt->PMdiPairLen[i] > 35) &&
-						(pPrt->PMdiPairLen[i] < 0xff)) {
-						pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
-					}
-				}
-				if ((pPrt->PMdiPairLen[i] > 35) &&
-					(pPrt->PMdiPairLen[i] != 0xff)) {
-					CableLength = 1000 *
-						(((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
-				}
-				else {
-					CableLength = 0;
-				}
-				pVctBackupData->PMdiPairLen[i] = CableLength;
-				pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
-			}
-			
-			Param.Para32[0] = PhysPortIndex;
-			Param.Para32[1] = -1;
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
-			SkEventDispatcher(pAC, IoC);
-		}
-		
-		break;
-
-	default:
-		break;
-	}
-
-	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-	return (0);
-}
-
-
-/******************************************************************************
- *
- * Private functions
- *
- */
-
-/*****************************************************************************
- *
- * PnmiVar - Gets, presets, and sets single OIDs
- *
- * Description:
- *	Looks up the requested OID, calls the corresponding handler
- *	function, and passes the parameters with the get, preset, or
- *	set command. The function is called by SkGePnmiGetVar,
- *	SkGePnmiPreSetVar, or SkGePnmiSetVar.
- *
- * Returns:
- *	SK_PNMI_ERR_XXX. For details have a look at the description of the
- *	calling functions.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* Total length of pBuf management data  */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	TableIndex;
-	int		Ret;
-
-
-	if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_OID);
-	}
-	
-    /* Check NetIndex */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-
-	SK_PNMI_CHECKFLAGS("PnmiVar: On call");
-
-	Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
-		Instance, TableIndex, NetIndex);
-
-	SK_PNMI_CHECKFLAGS("PnmiVar: On return");
-
-	return (Ret);
-}
-
-/*****************************************************************************
- *
- * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
- *	checks which OIDs are able to set, and calls the handler function of
- *	the OID to perform the set. The return value of the function will
- *	also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- *	minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
- *	by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
- *
- * Returns:
- *	SK_PNMI_ERR_XXX. The codes are described in the calling functions.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int  Action,	/* PRESET/SET action to be performed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* Length of pBuf management data buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	TableIndex;
-	unsigned int	DstOffset;
-	unsigned int	Len;
-	unsigned int	InstanceNo;
-	unsigned int	InstanceCnt;
-	SK_U32		Instance;
-	SK_U32		Id;
-
-
-	/* Check if the passed buffer has the right size */
-	if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
-		/* Check if we can return the error within the buffer */
-		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
-			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
-				(SK_U32)(-1));
-		}
-
-		*pLen = SK_PNMI_STRUCT_SIZE;
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-	
-    /* Check NetIndex */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-	
-	SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
-
-	/*
-	 * Update the values of RLMT and SIRQ and increment semaphores to
-	 * indicate that an update was already done.
-	 */
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-	pAC->Pnmi.SirqUpdatedFlag ++;
-
-	/* Preset/Set values */
-	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
-		if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
-			(IdTable[TableIndex].Access != SK_PNMI_WO)) {
-
-			continue;
-		}
-
-		InstanceNo = IdTable[TableIndex].InstanceNo;
-		Id = IdTable[TableIndex].Id;
-
-		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
-			InstanceCnt ++) {
-
-			DstOffset = IdTable[TableIndex].Offset +
-				(InstanceCnt - 1) *
-				IdTable[TableIndex].StructSize;
-
-			/*
-			 * Because VPD multiple instance variables are
-			 * not setable we do not need to evaluate VPD
-			 * instances. Have a look to VPD instance
-			 * calculation in SkPnmiGetStruct().
-			 */
-			Instance = (SK_U32)InstanceCnt;
-
-			/*
-			 * Evaluate needed buffer length
-			 */
-			Len = 0;
-			Ret = IdTable[TableIndex].Func(pAC, IoC,
-				SK_PNMI_GET, IdTable[TableIndex].Id,
-				NULL, &Len, Instance, TableIndex, NetIndex);
-
-			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
-				break;
-			}
-			if (Ret != SK_PNMI_ERR_TOO_SHORT) {
-
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-				SK_PNMI_SET_STAT(pBuf,
-					SK_PNMI_ERR_GENERAL, DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			if (Id == OID_SKGE_VPD_ACTION) {
-
-				switch (*(pBuf + DstOffset)) {
-
-				case SK_PNMI_VPD_CREATE:
-					Len = 3 + *(pBuf + DstOffset + 3);
-					break;
-
-				case SK_PNMI_VPD_DELETE:
-					Len = 3;
-					break;
-
-				default:
-					Len = 1;
-					break;
-				}
-			}
-
-			/* Call the OID handler function */
-			Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
-				IdTable[TableIndex].Id, pBuf + DstOffset,
-				&Len, Instance, TableIndex, NetIndex);
-
-			if (Ret != SK_PNMI_ERR_OK) {
-
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-				SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
-					DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-		}
-	}
-
-	pAC->Pnmi.RlmtUpdatedFlag --;
-	pAC->Pnmi.SirqUpdatedFlag --;
-
-	SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * LookupId - Lookup an OID in the IdTable
- *
- * Description:
- *	Scans the IdTable to find the table entry of an OID.
- *
- * Returns:
- *	The table index or -1 if not found.
- */
-PNMI_STATIC int LookupId(
-SK_U32 Id)		/* Object identifier to be searched */
-{
-	int i;
-
-	for (i = 0; i < ID_TABLE_SIZE; i++) {
-
-		if (IdTable[i].Id == Id) {
-
-			return i;
-		}
-	}
-
-	return (-1);
-}
-
-/*****************************************************************************
- *
- * OidStruct - Handler of OID_SKGE_ALL_DATA
- *
- * Description:
- *	This OID performs a Get/Preset/SetStruct call and returns all data
- *	in a SK_PNMI_STRUCT_DATA structure.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int OidStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	if (Id != OID_SKGE_ALL_DATA) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
-			SK_PNMI_ERR003MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	switch (Action) {
-
-	case SK_PNMI_GET:
-		return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
-	case SK_PNMI_PRESET:
-		return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
-	case SK_PNMI_SET:
-		return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-	}
-
-	SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
-
-	*pLen = 0;
-	return (SK_PNMI_ERR_GENERAL);
-}
-
-/*****************************************************************************
- *
- * Perform - OID handler of OID_SKGE_ACTION
- *
- * Description:
- *	None.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Perform(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int	Ret;
-	SK_U32	ActionOp;
-
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	if (*pLen < sizeof(SK_U32)) {
-
-		*pLen = sizeof(SK_U32);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/* Check if a get should be performed */
-	if (Action == SK_PNMI_GET) {
-
-		/* A get is easy. We always return the same value */
-		ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
-		SK_PNMI_STORE_U32(pBuf, ActionOp);
-		*pLen = sizeof(SK_U32);
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Continue with PRESET/SET action */
-	if (*pLen > sizeof(SK_U32)) {
-
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	/* Check if the command is a known one */
-	SK_PNMI_READ_U32(pBuf, ActionOp);
-	if (*pLen > sizeof(SK_U32) ||
-		(ActionOp != SK_PNMI_ACT_IDLE &&
-		ActionOp != SK_PNMI_ACT_RESET &&
-		ActionOp != SK_PNMI_ACT_SELFTEST &&
-		ActionOp != SK_PNMI_ACT_RESETCNT)) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	/* A preset ends here */
-	if (Action == SK_PNMI_PRESET) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	switch (ActionOp) {
-
-	case SK_PNMI_ACT_IDLE:
-		/* Nothing to do */
-		break;
-
-	case SK_PNMI_ACT_RESET:
-		/*
-		 * Perform a driver reset or something that comes near
-		 * to this.
-		 */
-		Ret = SK_DRIVER_RESET(pAC, IoC);
-		if (Ret != 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
-				SK_PNMI_ERR005MSG);
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		break;
-
-	case SK_PNMI_ACT_SELFTEST:
-		/*
-		 * Perform a driver selftest or something similar to this.
-		 * Currently this feature is not used and will probably
-		 * implemented in another way.
-		 */
-		Ret = SK_DRIVER_SELFTEST(pAC, IoC);
-		pAC->Pnmi.TestResult = Ret;
-		break;
-
-	case SK_PNMI_ACT_RESETCNT:
-		/* Set all counters and timestamps to zero */
-		ResetCounter(pAC, IoC, NetIndex);
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
-			SK_PNMI_ERR006MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
- *
- * Description:
- *	Retrieves the statistic values of the virtual port (logical
- *	index 0). Only special OIDs of NDIS are handled which consist
- *	of a 32 bit instead of a 64 bit value. The OIDs are public
- *	because perhaps some other platform can use them too.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Mac8023Stat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex,	/* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int     Ret;
-	SK_U64  StatVal;
-	SK_U32  StatVal32;
-	SK_BOOL Is64BitReq = SK_FALSE;
-
-	/*
-	 * Only the active Mac is returned
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check action type
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	switch (Id) {
-
-	case OID_802_3_PERMANENT_ADDRESS:
-	case OID_802_3_CURRENT_ADDRESS:
-		if (*pLen < sizeof(SK_MAC_ADDR)) {
-
-			*pLen = sizeof(SK_MAC_ADDR);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-#ifndef SK_NDIS_64BIT_CTR
-		if (*pLen < sizeof(SK_U32)) {
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-#else /* SK_NDIS_64BIT_CTR */
-
-		/* for compatibility, at least 32bit are required for OID */
-		if (*pLen < sizeof(SK_U32)) {
-			/*
-			* but indicate handling for 64bit values,
-			* if insufficient space is provided
-			*/
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
-		break;
-	}
-
-	/*
-	 * Update all statistics, because we retrieve virtual MAC, which
-	 * consists of multiple physical statistics and increment semaphore
-	 * to indicate that an update was already done.
-	 */
-	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-	if ( Ret != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.MacUpdatedFlag ++;
-
-	/*
-	 * Get value (MAC Index 0 identifies the virtual MAC)
-	 */
-	switch (Id) {
-
-	case OID_802_3_PERMANENT_ADDRESS:
-		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
-		*pLen = sizeof(SK_MAC_ADDR);
-		break;
-
-	case OID_802_3_CURRENT_ADDRESS:
-		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
-		*pLen = sizeof(SK_MAC_ADDR);
-		break;
-
-	default:
-		StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
-
-		/* by default 32bit values are evaluated */
-		if (!Is64BitReq) {
-			StatVal32 = (SK_U32)StatVal;
-			SK_PNMI_STORE_U32(pBuf, StatVal32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, StatVal);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-	}
-
-	pAC->Pnmi.MacUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
- *
- * Description:
- *	Retrieves the MAC statistic data.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int MacPrivateStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	LogPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	PhysPortMax;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	int				MacType;
-	int				Ret;
-	SK_U64			StatVal;
-	
-	
-
-	/* Calculate instance if wished. MAC index 0 is the virtual MAC */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-	
-	MacType = pAC->GIni.GIMacType;
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/* Check action */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
-
-		*pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/*
-	 * Update MAC statistic and increment semaphore to indicate that
-	 * an update was already done.
-	 */
-	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-	if (Ret != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.MacUpdatedFlag ++;
-
-	/* Get value */
-	Offset = 0;
-	for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-		switch (Id) {
-
-/* XXX not yet implemented due to XMAC problems
-		case OID_SKGE_STAT_TX_UTIL:
-			return (SK_PNMI_ERR_GENERAL);
-*/
-/* XXX not yet implemented due to XMAC problems
-		case OID_SKGE_STAT_RX_UTIL:
-			return (SK_PNMI_ERR_GENERAL);
-*/
-		case OID_SKGE_STAT_RX:
-			if (MacType == SK_MAC_GMAC) {
-				StatVal =
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_BROADCAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_MULTICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_UNICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_UNDERSIZE, NetIndex);
-			}
-			else {
-				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-					IdTable[TableIndex].Param, NetIndex);
-			}
-			break;
-
-		case OID_SKGE_STAT_TX:
-			if (MacType == SK_MAC_GMAC) {
-				StatVal =
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_BROADCAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_MULTICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_UNICAST, NetIndex);
-			}
-			else {
-				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-					IdTable[TableIndex].Param, NetIndex);
-			}
-			break;
-
-		default:
-			StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-				IdTable[TableIndex].Param, NetIndex);
-		}
-		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
-
-		Offset += sizeof(SK_U64);
-	}
-	*pLen = Offset;
-
-	pAC->Pnmi.MacUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
- *
- * Description:
- *	Get/Presets/Sets the current and factory MAC address. The MAC
- *	address of the virtual port, which is reported to the OS, may
- *	not be changed, but the physical ones. A set to the virtual port
- *	will be ignored. No error should be reported because otherwise
- *	a multiple instance set (-1) would always fail.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Addr(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	LogPortMax;
-	unsigned int	PhysPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	PhysPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset = 0;
-
-	/*
-	 * Calculate instance if wished. MAC index 0 is the virtual
-	 * MAC.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/*
-	 * Perform Action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/* Check length */
-		if (*pLen < (Limit - LogPortIndex) * 6) {
-
-			*pLen = (Limit - LogPortIndex) * 6;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		/*
-		 * Get value
-		 */
-		for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-			switch (Id) {
-
-			case OID_SKGE_PHYS_CUR_ADDR:
-				if (LogPortIndex == 0) {
-					CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
-				}
-				else {
-					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
-				}
-				Offset += 6;
-				break;
-
-			case OID_SKGE_PHYS_FAC_ADDR:
-				if (LogPortIndex == 0) {
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Net[NetIndex].PermanentMacAddress);
-				}
-				else {
-					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-						pAC, LogPortIndex);
-
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
-				}
-				Offset += 6;
-				break;
-
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
-					SK_PNMI_ERR008MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-
-		*pLen = Offset;
-	}
-	else {
-		/*
-		 * The logical MAC address may not be changed only
-		 * the physical ones
-		 */
-		if (Id == OID_SKGE_PHYS_FAC_ADDR) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-
-		/*
-		 * Only the current address may be changed
-		 */
-		if (Id != OID_SKGE_PHYS_CUR_ADDR) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
-				SK_PNMI_ERR009MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/* Check length */
-		if (*pLen < (Limit - LogPortIndex) * 6) {
-
-			*pLen = (Limit - LogPortIndex) * 6;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen > (Limit - LogPortIndex) * 6) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-
-		/*
-		 * Check Action
-		 */
-		if (Action == SK_PNMI_PRESET) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_OK);
-		}
-
-		/*
-		 * Set OID_SKGE_MAC_CUR_ADDR
-		 */
-		for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
-
-			/*
-			 * A set to virtual port and set of broadcast
-			 * address will be ignored
-			 */
-			if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
-				"\xff\xff\xff\xff\xff\xff", 6) == 0) {
-
-				continue;
-			}
-
-			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
-				LogPortIndex);
-
-			Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
-				(SK_MAC_ADDR *)(pBuf + Offset),
-				(LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
-				SK_ADDR_PHYSICAL_ADDRESS));
-			if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
-
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
- *
- * Description:
- *	Retrieves the statistic values of the CSUM module. The CSUM data
- *	structure must be available in the SK_AC even if the CSUM module
- *	is not included, because PNMI reads the statistic data from the
- *	CSUM part of SK_AC directly.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int CsumStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset = 0;
-	SK_U64		StatVal;
-
-
-	/*
-	 * Calculate instance if wished
-	 */
-	if (Instance != (SK_U32)(-1)) {
-
-		if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		Index = (unsigned int)Instance - 1;
-		Limit = Index + 1;
-	}
-	else {
-		Index = 0;
-		Limit = SKCS_NUM_PROTOCOLS;
-	}
-
-	/*
-	 * Check action
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
-		*pLen = (Limit - Index) * sizeof(SK_U64);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/*
-	 * Get value
-	 */
-	for (; Index < Limit; Index ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_CHKSM_RX_OK_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
-			break;
-
-		case OID_SKGE_CHKSM_RX_UNABLE_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
-			break;
-
-		case OID_SKGE_CHKSM_RX_ERR_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
-			break;
-
-		case OID_SKGE_CHKSM_TX_OK_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
-			break;
-
-		case OID_SKGE_CHKSM_TX_UNABLE_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
-				SK_PNMI_ERR010MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
-		Offset += sizeof(SK_U64);
-	}
-
-	/*
-	 * Store used buffer space
-	 */
-	*pLen = Offset;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
- *
- * Description:
- *	Retrieves the statistic values of the I2C module, which handles
- *	the temperature and voltage sensors.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int SensorStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	i;
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	unsigned int	Len;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-
-	/*
-	 * Calculate instance if wished
-	 */
-	if ((Instance != (SK_U32)(-1))) {
-
-		if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		Index = (unsigned int)Instance -1;
-		Limit = (unsigned int)Instance;
-	}
-	else {
-		Index = 0;
-		Limit = (unsigned int) pAC->I2c.MaxSens;
-	}
-
-	/*
-	 * Check action
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	switch (Id) {
-
-	case OID_SKGE_SENSOR_VALUE:
-	case OID_SKGE_SENSOR_WAR_THRES_LOW:
-	case OID_SKGE_SENSOR_WAR_THRES_UPP:
-	case OID_SKGE_SENSOR_ERR_THRES_LOW:
-	case OID_SKGE_SENSOR_ERR_THRES_UPP:
-		if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
-
-			*pLen = (Limit - Index) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_DESCR:
-		for (Offset = 0, i = Index; i < Limit; i ++) {
-
-			Len = (unsigned int)
-				SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
-			if (Len >= SK_PNMI_STRINGLEN2) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
-					SK_PNMI_ERR011MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			Offset += Len;
-		}
-		if (*pLen < Offset) {
-
-			*pLen = Offset;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_INDEX:
-	case OID_SKGE_SENSOR_TYPE:
-	case OID_SKGE_SENSOR_STATUS:
-		if (*pLen < Limit - Index) {
-
-			*pLen = Limit - Index;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_WAR_CTS:
-	case OID_SKGE_SENSOR_WAR_TIME:
-	case OID_SKGE_SENSOR_ERR_CTS:
-	case OID_SKGE_SENSOR_ERR_TIME:
-		if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
-			*pLen = (Limit - Index) * sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
-			SK_PNMI_ERR012MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-
-	}
-
-	/*
-	 * Get value
-	 */
-	for (Offset = 0; Index < Limit; Index ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_SENSOR_INDEX:
-			*(pBuf + Offset) = (char)Index;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_DESCR:
-			Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
-			SK_MEMCPY(pBuf + Offset + 1,
-				pAC->I2c.SenTable[Index].SenDesc, Len);
-			*(pBuf + Offset) = (char)Len;
-			Offset += Len + 1;
-			break;
-
-		case OID_SKGE_SENSOR_TYPE:
-			*(pBuf + Offset) =
-				(char)pAC->I2c.SenTable[Index].SenType;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_VALUE:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_THRES_LOW:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreWarnLow;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_THRES_UPP:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreWarnHigh;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_THRES_LOW:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreErrLow;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_THRES_UPP:
-			Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_STATUS:
-			*(pBuf + Offset) =
-				(char)pAC->I2c.SenTable[Index].SenErrFlag;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_CTS:
-			Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_CTS:
-			Val64 = pAC->I2c.SenTable[Index].SenErrCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_TIME:
-			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
-				SenBegWarnTS);
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_TIME:
-			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
-				SenBegErrTS);
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("SensorStat: Unknown OID should be handled before"));
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	/*
-	 * Store used buffer space
-	 */
-	*pLen = Offset;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Vpd - OID handler function of OID_SKGE_VPD_XXX
- *
- * Description:
- *	Get/preset/set of VPD data. As instance the name of a VPD key
- *	can be passed. The Instance parameter is a SK_U32 and can be
- *	used as a string buffer for the VPD key, because their maximum
- *	length is 4 byte.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Vpd(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_VPD_STATUS	*pVpdStatus;
-	unsigned int	BufLen;
-	char		Buf[256];
-	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
-	char		KeyStr[SK_PNMI_VPD_KEY_SIZE];
-	unsigned int	KeyNo;
-	unsigned int	Offset;
-	unsigned int	Index;
-	unsigned int	FirstIndex;
-	unsigned int	LastIndex;
-	unsigned int	Len;
-	int		Ret;
-	SK_U32		Val32;
-
-	/*
-	 * Get array of all currently stored VPD keys
-	 */
-	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
-	if (Ret != SK_PNMI_ERR_OK) {
-		*pLen = 0;
-		return (Ret);
-	}
-
-	/*
-	 * If instance is not -1, try to find the requested VPD key for
-	 * the multiple instance variables. The other OIDs as for example
-	 * OID VPD_ACTION are single instance variables and must be
-	 * handled separatly.
-	 */
-	FirstIndex = 0;
-	LastIndex = KeyNo;
-
-	if ((Instance != (SK_U32)(-1))) {
-
-		if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
-			Id == OID_SKGE_VPD_ACCESS) {
-
-			SK_STRNCPY(KeyStr, (char *)&Instance, 4);
-			KeyStr[4] = 0;
-
-			for (Index = 0; Index < KeyNo; Index ++) {
-
-				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
-					FirstIndex = Index;
-					LastIndex = Index+1;
-					break;
-				}
-			}
-			if (Index == KeyNo) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_UNKNOWN_INST);
-			}
-		}
-		else if (Instance != 1) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-	}
-
-	/*
-	 * Get value, if a query should be performed
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		switch (Id) {
-
-		case OID_SKGE_VPD_FREE_BYTES:
-			/* Check length of buffer */
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Get number of free bytes */
-			pVpdStatus = VpdStat(pAC, IoC);
-			if (pVpdStatus == NULL) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
-					SK_PNMI_ERR017MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
-					SK_PNMI_ERR018MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			
-			Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_VPD_ENTRIES_LIST:
-			/* Check length */
-			for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
-
-				Len += SK_STRLEN(KeyArr[Index]) + 1;
-			}
-			if (*pLen < Len) {
-
-				*pLen = Len;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/* Get value */
-			*(pBuf) = (char)Len - 1;
-			for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
-
-				Len = SK_STRLEN(KeyArr[Index]);
-				SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
-
-				Offset += Len;
-
-				if (Index < KeyNo - 1) {
-
-					*(pBuf + Offset) = ' ';
-					Offset ++;
-				}
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ENTRIES_NUMBER:
-			/* Check length */
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			Val32 = (SK_U32)KeyNo;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_VPD_KEY:
-			/* Check buffer length, if it is large enough */
-			for (Len = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				Len += SK_STRLEN(KeyArr[Index]) + 1;
-			}
-			if (*pLen < Len) {
-
-				*pLen = Len;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/*
-			 * Get the key to an intermediate buffer, because
-			 * we have to prepend a length byte.
-			 */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				Len = SK_STRLEN(KeyArr[Index]);
-
-				*(pBuf + Offset) = (char)Len;
-				SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
-					Len);
-				Offset += Len + 1;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_VALUE:
-			/* Check the buffer length if it is large enough */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				BufLen = 256;
-				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
-					(int *)&BufLen) > 0 ||
-					BufLen >= SK_PNMI_VPD_DATALEN) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR021,
-						SK_PNMI_ERR021MSG);
-
-					return (SK_PNMI_ERR_GENERAL);
-				}
-				Offset += BufLen + 1;
-			}
-			if (*pLen < Offset) {
-
-				*pLen = Offset;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/*
-			 * Get the value to an intermediate buffer, because
-			 * we have to prepend a length byte.
-			 */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				BufLen = 256;
-				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
-					(int *)&BufLen) > 0 ||
-					BufLen >= SK_PNMI_VPD_DATALEN) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR022,
-						SK_PNMI_ERR022MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-
-				*(pBuf + Offset) = (char)BufLen;
-				SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
-				Offset += BufLen + 1;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ACCESS:
-			if (*pLen < LastIndex - FirstIndex) {
-
-				*pLen = LastIndex - FirstIndex;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				if (VpdMayWrite(KeyArr[Index])) {
-
-					*(pBuf + Offset) = SK_PNMI_VPD_RW;
-				}
-				else {
-					*(pBuf + Offset) = SK_PNMI_VPD_RO;
-				}
-				Offset ++;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ACTION:
-			Offset = LastIndex - FirstIndex;
-			if (*pLen < Offset) {
-
-				*pLen = Offset;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			SK_MEMSET(pBuf, 0, Offset);
-			*pLen = Offset;
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
-				SK_PNMI_ERR023MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-	else {
-		/* The only OID which can be set is VPD_ACTION */
-		if (Id != OID_SKGE_VPD_ACTION) {
-
-			if (Id == OID_SKGE_VPD_FREE_BYTES ||
-				Id == OID_SKGE_VPD_ENTRIES_LIST ||
-				Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
-				Id == OID_SKGE_VPD_KEY ||
-				Id == OID_SKGE_VPD_VALUE ||
-				Id == OID_SKGE_VPD_ACCESS) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_READ_ONLY);
-			}
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
-				SK_PNMI_ERR024MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * From this point we handle VPD_ACTION. Check the buffer
-		 * length. It should at least have the size of one byte.
-		 */
-		if (*pLen < 1) {
-
-			*pLen = 1;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		/*
-		 * The first byte contains the VPD action type we should
-		 * perform.
-		 */
-		switch (*pBuf) {
-
-		case SK_PNMI_VPD_IGNORE:
-			/* Nothing to do */
-			break;
-
-		case SK_PNMI_VPD_CREATE:
-			/*
-			 * We have to create a new VPD entry or we modify
-			 * an existing one. Check first the buffer length.
-			 */
-			if (*pLen < 4) {
-
-				*pLen = 4;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			KeyStr[0] = pBuf[1];
-			KeyStr[1] = pBuf[2];
-			KeyStr[2] = 0;
-
-			/*
-			 * Is the entry writable or does it belong to the
-			 * read-only area?
-			 */
-			if (!VpdMayWrite(KeyStr)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			Offset = (int)pBuf[3] & 0xFF;
-
-			SK_MEMCPY(Buf, pBuf + 4, Offset);
-			Buf[Offset] = 0;
-
-			/* A preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/* Write the new entry or modify an existing one */
-			Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
-			if (Ret == SK_PNMI_VPD_NOWRITE ) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			else if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
-					SK_PNMI_ERR025MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			/*
-			 * Perform an update of the VPD data. This is
-			 * not mandantory, but just to be sure.
-			 */
-			Ret = VpdUpdate(pAC, IoC);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
-					SK_PNMI_ERR026MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case SK_PNMI_VPD_DELETE:
-			/* Check if the buffer size is plausible */
-			if (*pLen < 3) {
-
-				*pLen = 3;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			if (*pLen > 3) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			KeyStr[0] = pBuf[1];
-			KeyStr[1] = pBuf[2];
-			KeyStr[2] = 0;
-
-			/* Find the passed key in the array */
-			for (Index = 0; Index < KeyNo; Index ++) {
-
-				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
-
-					break;
-				}
-			}
-			/*
-			 * If we cannot find the key it is wrong, so we
-			 * return an appropriate error value.
-			 */
-			if (Index == KeyNo) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/* Ok, you wanted it and you will get it */
-			Ret = VpdDelete(pAC, IoC, KeyStr);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
-					SK_PNMI_ERR027MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			/*
-			 * Perform an update of the VPD data. This is
-			 * not mandantory, but just to be sure.
-			 */
-			Ret = VpdUpdate(pAC, IoC);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
-					SK_PNMI_ERR028MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * General - OID handler function of various single instance OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int General(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	Index;
-	unsigned int	Len;
-	unsigned int	Offset;
-	unsigned int	Val;
-	SK_U8		Val8;
-	SK_U16		Val16;
-	SK_U32		Val32;
-	SK_U64		Val64;
-	SK_U64		Val64RxHwErrs = 0;
-	SK_U64		Val64TxHwErrs = 0;
-	SK_BOOL		Is64BitReq = SK_FALSE;
-	char		Buf[256];
-	int			MacType;
-
-	/*
-	 * Check instance. We only handle single instance variables.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check action. We only allow get requests.
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-	
-	MacType = pAC->GIni.GIMacType;
-	
-	/*
-	 * Check length for the various supported OIDs
-	 */
-	switch (Id) {
-
-	case OID_GEN_XMIT_ERROR:
-	case OID_GEN_RCV_ERROR:
-	case OID_GEN_RCV_NO_BUFFER:
-#ifndef SK_NDIS_64BIT_CTR
-		if (*pLen < sizeof(SK_U32)) {
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-#else /* SK_NDIS_64BIT_CTR */
-
-		/*
-		 * for compatibility, at least 32bit are required for oid
-		 */
-		if (*pLen < sizeof(SK_U32)) {
-			/*
-			* but indicate handling for 64bit values,
-			* if insufficient space is provided
-			*/
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
-		break;
-
-	case OID_SKGE_PORT_NUMBER:
-	case OID_SKGE_DEVICE_TYPE:
-	case OID_SKGE_RESULT:
-	case OID_SKGE_RLMT_MONITOR_NUMBER:
-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-	case OID_SKGE_TRAP_NUMBER:
-	case OID_SKGE_MDB_VERSION:
-	case OID_SKGE_BOARDLEVEL:
-	case OID_SKGE_CHIPID:
-	case OID_SKGE_RAMSIZE:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_CHIPSET:
-		if (*pLen < sizeof(SK_U16)) {
-
-			*pLen = sizeof(SK_U16);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_BUS_TYPE:
-	case OID_SKGE_BUS_SPEED:
-	case OID_SKGE_BUS_WIDTH:
-	case OID_SKGE_SENSOR_NUMBER:
-	case OID_SKGE_CHKSM_NUMBER:
-	case OID_SKGE_VAUXAVAIL:
-		if (*pLen < sizeof(SK_U8)) {
-
-			*pLen = sizeof(SK_U8);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_TX_SW_QUEUE_LEN:
-	case OID_SKGE_TX_SW_QUEUE_MAX:
-	case OID_SKGE_TX_RETRY:
-	case OID_SKGE_RX_INTR_CTS:
-	case OID_SKGE_TX_INTR_CTS:
-	case OID_SKGE_RX_NO_BUF_CTS:
-	case OID_SKGE_TX_NO_BUF_CTS:
-	case OID_SKGE_TX_USED_DESCR_NO:
-	case OID_SKGE_RX_DELIVERED_CTS:
-	case OID_SKGE_RX_OCTETS_DELIV_CTS:
-	case OID_SKGE_RX_HW_ERROR_CTS:
-	case OID_SKGE_TX_HW_ERROR_CTS:
-	case OID_SKGE_IN_ERRORS_CTS:
-	case OID_SKGE_OUT_ERROR_CTS:
-	case OID_SKGE_ERR_RECOVERY_CTS:
-	case OID_SKGE_SYSUPTIME:
-		if (*pLen < sizeof(SK_U64)) {
-
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		/* Checked later */
-		break;
-	}
-
-	/* Update statistic */
-	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
-		Id == OID_SKGE_TX_HW_ERROR_CTS ||
-		Id == OID_SKGE_IN_ERRORS_CTS ||
-		Id == OID_SKGE_OUT_ERROR_CTS ||
-		Id == OID_GEN_XMIT_ERROR ||
-		Id == OID_GEN_RCV_ERROR) {
-
-		/* Force the XMAC to update its statistic counters and
-		 * Increment semaphore to indicate that an update was
-		 * already done.
-		 */
-		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-		if (Ret != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Some OIDs consist of multiple hardware counters. Those
-		 * values which are contained in all of them will be added
-		 * now.
-		 */
-		switch (Id) {
-
-		case OID_SKGE_RX_HW_ERROR_CTS:
-		case OID_SKGE_IN_ERRORS_CTS:
-		case OID_GEN_RCV_ERROR:
-			Val64RxHwErrs =
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
-	        break;
-
-		case OID_SKGE_TX_HW_ERROR_CTS:
-		case OID_SKGE_OUT_ERROR_CTS:
-		case OID_GEN_XMIT_ERROR:
-			Val64TxHwErrs =
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
-			break;
-		}
-	}
-
-	/*
-	 * Retrieve value
-	 */
-	switch (Id) {
-
-	case OID_SKGE_SUPPORTED_LIST:
-		Len = ID_TABLE_SIZE * sizeof(SK_U32);
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		for (Offset = 0, Index = 0; Offset < Len;
-			Offset += sizeof(SK_U32), Index ++) {
-
-			Val32 = (SK_U32)IdTable[Index].Id;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-		}
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_BOARDLEVEL:
-		Val32 = (SK_U32)pAC->GIni.GILevel;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_PORT_NUMBER:
-		Val32 = (SK_U32)pAC->GIni.GIMacsFound;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_DEVICE_TYPE:
-		Val32 = (SK_U32)pAC->Pnmi.DeviceType;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_DRIVER_DESCR:
-		if (pAC->Pnmi.pDriverDescription == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
-				SK_PNMI_ERR007MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
-				SK_PNMI_ERR029MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_VERSION:
-		if (pAC->Pnmi.pDriverVersion == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR030MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR031MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_RELDATE:
-		if (pAC->Pnmi.pDriverReleaseDate == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR053MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR054MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_FILENAME:
-		if (pAC->Pnmi.pDriverFileName == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR055MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR056MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_HW_DESCR:
-		/*
-		 * The hardware description is located in the VPD. This
-		 * query may move to the initialisation routine. But
-		 * the VPD data is cached and therefore a call here
-		 * will not make much difference.
-		 */
-		Len = 256;
-		if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
-				SK_PNMI_ERR032MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		Len ++;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
-				SK_PNMI_ERR033MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, Buf, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_HW_VERSION:
-		/* Oh, I love to do some string manipulation */
-		if (*pLen < 5) {
-
-			*pLen = 5;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
-		pBuf[0] = 4;
-		pBuf[1] = 'v';
-		pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
-		pBuf[3] = '.';
-		pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
-		*pLen = 5;
-		break;
-
-	case OID_SKGE_CHIPSET:
-		Val16 = pAC->Pnmi.Chipset;
-		SK_PNMI_STORE_U16(pBuf, Val16);
-		*pLen = sizeof(SK_U16);
-		break;
-
-	case OID_SKGE_CHIPID:
-		Val32 = pAC->GIni.GIChipId;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_RAMSIZE:
-		Val32 = pAC->GIni.GIRamSize;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_VAUXAVAIL:
-		*pBuf = (char) pAC->GIni.GIVauxAvail;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_TYPE:
-		*pBuf = (char) SK_PNMI_BUS_PCI;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_SPEED:
-		*pBuf = pAC->Pnmi.PciBusSpeed;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_WIDTH:
-		*pBuf = pAC->Pnmi.PciBusWidth;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_RESULT:
-		Val32 = pAC->Pnmi.TestResult;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_SENSOR_NUMBER:
-		*pBuf = (char)pAC->I2c.MaxSens;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_CHKSM_NUMBER:
-		*pBuf = SKCS_NUM_PROTOCOLS;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_TRAP_NUMBER:
-		GetTrapQueueLen(pAC, &Len, &Val);
-		Val32 = (SK_U32)Val;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_TRAP:
-		GetTrapQueueLen(pAC, &Len, &Val);
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		CopyTrapQueue(pAC, pBuf);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_RLMT_MONITOR_NUMBER:
-/* XXX Not yet implemented by RLMT therefore we return zero elements */
-		Val32 = 0;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_TX_SW_QUEUE_LEN:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
-					pAC->Pnmi.BufPort[1].TxSwQueueLen;
-			}			
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
-					pAC->Pnmi.Port[1].TxSwQueueLen;
-			}			
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-
-	case OID_SKGE_TX_SW_QUEUE_MAX:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
-					pAC->Pnmi.BufPort[1].TxSwQueueMax;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
-					pAC->Pnmi.Port[1].TxSwQueueMax;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_RETRY:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
-					pAC->Pnmi.BufPort[1].TxRetryCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxRetryCts +
-					pAC->Pnmi.Port[1].TxRetryCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_INTR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
-					pAC->Pnmi.BufPort[1].RxIntrCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxIntrCts +
-					pAC->Pnmi.Port[1].RxIntrCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_INTR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
-					pAC->Pnmi.BufPort[1].TxIntrCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxIntrCts +
-					pAC->Pnmi.Port[1].TxIntrCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_NO_BUF_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
-					pAC->Pnmi.BufPort[1].RxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
-					pAC->Pnmi.Port[1].RxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_NO_BUF_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
-					pAC->Pnmi.BufPort[1].TxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
-					pAC->Pnmi.Port[1].TxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_USED_DESCR_NO:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
-					pAC->Pnmi.BufPort[1].TxUsedDescrNo;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
-					pAC->Pnmi.Port[1].TxUsedDescrNo;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_DELIVERED_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
-					pAC->Pnmi.BufPort[1].RxDeliveredCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
-					pAC->Pnmi.Port[1].RxDeliveredCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_OCTETS_DELIV_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
-					pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
-					pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_HW_ERROR_CTS:
-		SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_HW_ERROR_CTS:
-		SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_IN_ERRORS_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64RxHwErrs +
-					pAC->Pnmi.BufPort[0].RxNoBufCts +
-					pAC->Pnmi.BufPort[1].RxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64RxHwErrs +
-					pAC->Pnmi.Port[0].RxNoBufCts +
-					pAC->Pnmi.Port[1].RxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_OUT_ERROR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64TxHwErrs +
-					pAC->Pnmi.BufPort[0].TxNoBufCts +
-					pAC->Pnmi.BufPort[1].TxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64TxHwErrs +
-					pAC->Pnmi.Port[0].TxNoBufCts +
-					pAC->Pnmi.Port[1].TxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_ERR_RECOVERY_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
-					pAC->Pnmi.BufPort[1].ErrRecoveryCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
-					pAC->Pnmi.Port[1].ErrRecoveryCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_SYSUPTIME:
-		Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-		Val64 -= pAC->Pnmi.StartUpTime;
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_MDB_VERSION:
-		Val32 = SK_PNMI_MDB_VERSION;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_GEN_RCV_ERROR:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-		}
-		else {
-			Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_XMIT_ERROR:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-		}
-		else {
-			Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_RCV_NO_BUFFER:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-		}
-		else {
-			Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-		Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
-			SK_PNMI_ERR034MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
-		Id == OID_SKGE_TX_HW_ERROR_CTS ||
-		Id == OID_SKGE_IN_ERRORS_CTS ||
-		Id == OID_SKGE_OUT_ERROR_CTS ||
-		Id == OID_GEN_XMIT_ERROR ||
-		Id == OID_GEN_RCV_ERROR) {
-
-		pAC->Pnmi.MacUpdatedFlag --;
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
- *
- * Description:
- *	Get/Presets/Sets the RLMT OIDs.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Rlmt(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	PhysPortIndex;
-	unsigned int	PhysPortMax;
-	SK_EVPARA	EventParam;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-
-	/*
-	 * Check instance. Only single instance OIDs are allowed here.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Perform the requested action.
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/*
-		 * Check if the buffer length is large enough.
-		 */
-
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-		case OID_SKGE_RLMT_PORT_ACTIVE:
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			if (*pLen < sizeof(SK_U8)) {
-
-				*pLen = sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		case OID_SKGE_RLMT_PORT_NUMBER:
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_CTS:
-		case OID_SKGE_RLMT_CHANGE_TIME:
-		case OID_SKGE_RLMT_CHANGE_ESTIM:
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			if (*pLen < sizeof(SK_U64)) {
-
-				*pLen = sizeof(SK_U64);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
-				SK_PNMI_ERR035MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * Update RLMT statistic and increment semaphores to indicate
-		 * that an update was already done. Maybe RLMT will hold its
-		 * statistic always up to date some time. Then we can
-		 * remove this type of call.
-		 */
-		if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.RlmtUpdatedFlag ++;
-
-		/*
-		 * Retrieve Value
-		*/
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-			*pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_PORT_NUMBER:
-			Val32 = (SK_U32)pAC->GIni.GIMacsFound;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_PORT_ACTIVE:
-			*pBuf = 0;
-			/*
-			 * If multiple ports may become active this OID
-			 * doesn't make sense any more. A new variable in
-			 * the port structure should be created. However,
-			 * for this variable the first active port is
-			 * returned.
-			 */
-			PhysPortMax = pAC->GIni.GIMacsFound;
-
-			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-				PhysPortIndex ++) {
-
-				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-					*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
-					break;
-				}
-			}
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_CTS:
-			Val64 = pAC->Pnmi.RlmtChangeCts;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_TIME:
-			Val64 = pAC->Pnmi.RlmtChangeTime;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_ESTIM:
-			Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			Val64 = pAC->Pnmi.RlmtChangeThreshold;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("Rlmt: Unknown OID should be handled before"));
-
-			pAC->Pnmi.RlmtUpdatedFlag --;
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		pAC->Pnmi.RlmtUpdatedFlag --;
-	}
-	else {
-		/* Perform a preset or set */
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(char)) {
-
-				*pLen = sizeof(char);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Check if the value range is correct */
-			if (*pLen != sizeof(char) ||
-				(*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
-				*(SK_U8 *)pBuf > 15) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-			/* Send an event to RLMT to change the mode */
-			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-			EventParam.Para32[0] |= (SK_U32)(*pBuf);
-			EventParam.Para32[1] = 0;
-			if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
-				EventParam) > 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
-					SK_PNMI_ERR037MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(char)) {
-
-				*pLen = sizeof(char);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Check if the value range is correct */
-			if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
-				(SK_U8)pAC->GIni.GIMacsFound) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/*
-			 * Send an event to RLMT change the preferred port.
-			 * A param of -1 means automatic mode. RLMT will
-			 * make the decision which is the preferred port.
-			 */
-			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-			EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
-			EventParam.Para32[1] = NetIndex;
-			if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
-				EventParam) > 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
-					SK_PNMI_ERR038MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(SK_U64)) {
-
-				*pLen = sizeof(SK_U64);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/*
-			 * There are not many restrictions to the
-			 * value range.
-			 */
-			if (*pLen != sizeof(SK_U64)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* A preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-			/*
-			 * Store the new threshold, which will be taken
-			 * on the next timer event.
-			 */
-			SK_PNMI_READ_U64(pBuf, Val64);
-			pAC->Pnmi.RlmtChangeThreshold = Val64;
-			break;
-
-		default:
-			/* The other OIDs are not be able for set */
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
- *
- * Description:
- *	Performs get requests on multiple instance variables.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int RlmtStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	int		Ret;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-	/*
-	 * Calculate the port indexes from the instance.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-
-	if ((Instance != (SK_U32)(-1))) {
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > PhysPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		/* Single net mode */
-		PhysPortIndex = Instance - 1;
-
-		/* Dual net mode */
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-		}
-
-		/* Both net modes */
-		Limit = PhysPortIndex + 1;
-	}
-	else {
-		/* Single net mode */
-		PhysPortIndex = 0;
-		Limit = PhysPortMax;
-
-		/* Dual net mode */
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-			Limit = PhysPortIndex + 1;
-		}
-	}
-
-	/*
-	 * Currently only get requests are allowed.
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/*
-	 * Check if the buffer length is large enough.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_RLMT_PORT_INDEX:
-	case OID_SKGE_RLMT_STATUS:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
-
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_RLMT_TX_HELLO_CTS:
-	case OID_SKGE_RLMT_RX_HELLO_CTS:
-	case OID_SKGE_RLMT_TX_SP_REQ_CTS:
-	case OID_SKGE_RLMT_RX_SP_CTS:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
-
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
-			SK_PNMI_ERR039MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-
-	}
-
-	/*
-	 * Update statistic and increment semaphores to indicate that
-	 * an update was already done.
-	 */
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-
-	/*
-	 * Get value
-	 */
-	Offset = 0;
-	for (; PhysPortIndex < Limit; PhysPortIndex ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_RLMT_PORT_INDEX:
-			Val32 = PhysPortIndex;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_STATUS:
-			if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
-				SK_RLMT_PS_INIT ||
-				pAC->Rlmt.Port[PhysPortIndex].PortState ==
-				SK_RLMT_PS_DOWN) {
-
-				Val32 = SK_PNMI_RLMT_STATUS_ERROR;
-			}
-			else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-				Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
-			}
-			else {
-				Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
-			}
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_TX_HELLO_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_RX_HELLO_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_TX_SP_REQ_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_RX_SP_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("RlmtStat: Unknown OID should be errored before"));
-
-			pAC->Pnmi.RlmtUpdatedFlag --;
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-	*pLen = Offset;
-
-	pAC->Pnmi.RlmtUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateConf - OID handler function of OIDs concerning the configuration
- *
- * Description:
- *	Get/Presets/Sets the OIDs concerning the configuration.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int MacPrivateConf(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	unsigned int	LogPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	char		Val8;
-	char 		*pBufPtr;
-	int			Ret;
-	SK_EVPARA	EventParam;
-	SK_U32		Val32;
-
-	/*
-	 * Calculate instance if wished. MAC index 0 is the virtual MAC.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/*
-	 * Perform action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/* Check length */
-		switch (Id) {
-
-		case OID_SKGE_PMD:
-		case OID_SKGE_CONNECTOR:
-		case OID_SKGE_LINK_CAP:
-		case OID_SKGE_LINK_MODE:
-		case OID_SKGE_LINK_MODE_STATUS:
-		case OID_SKGE_LINK_STATUS:
-		case OID_SKGE_FLOWCTRL_CAP:
-		case OID_SKGE_FLOWCTRL_MODE:
-		case OID_SKGE_FLOWCTRL_STATUS:
-		case OID_SKGE_PHY_OPERATION_CAP:
-		case OID_SKGE_PHY_OPERATION_MODE:
-		case OID_SKGE_PHY_OPERATION_STATUS:
-		case OID_SKGE_SPEED_CAP:
-		case OID_SKGE_SPEED_MODE:
-		case OID_SKGE_SPEED_STATUS:
-			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
-
-				*pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-        case OID_SKGE_MTU:
-        case OID_SKGE_PHY_TYPE:
-			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
-
-				*pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
-				SK_PNMI_ERR041MSG);
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * Update statistic and increment semaphore to indicate
-		 * that an update was already done.
-		 */
-		if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.SirqUpdatedFlag ++;
-
-		/*
-		 * Get value
-		 */
-		Offset = 0;
-		for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-			pBufPtr = pBuf + Offset;
-			
-			switch (Id) {
-
-			case OID_SKGE_PMD:
-				*pBufPtr = pAC->Pnmi.PMD;
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_CONNECTOR:
-				*pBufPtr = pAC->Pnmi.Connector;
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_TYPE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						continue;
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-						Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
-						SK_PNMI_STORE_U32(pBufPtr, Val32);
-					}
-				}
-				else { /* DualNetMode */
-					
-					Val32 = pAC->GIni.GP[NetIndex].PhyType;
-					SK_PNMI_STORE_U32(pBufPtr, Val32);
-				}
-				Offset += sizeof(SK_U32);
-				break;
-
-			case OID_SKGE_LINK_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
-					}
-				}
-				else { /* DualNetMode */
-					
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_MODE_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr =
-							CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
-					}
-				}
-				else { /* DualNetMode */
-					
-					*pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
-					}
-				}
-				else {
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
-				}
-				Offset += sizeof(char);
-				break;
-			
-			case OID_SKGE_MTU:
-				Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
-				SK_PNMI_STORE_U32(pBufPtr, Val32);
-				Offset += sizeof(SK_U32);
-				break;
-
-			default:
-				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-					("MacPrivateConf: Unknown OID should be handled before"));
-
-				pAC->Pnmi.SirqUpdatedFlag --;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-		pAC->Pnmi.SirqUpdatedFlag --;
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/*
-	 * From here SET or PRESET action. Check if the passed
-	 * buffer length is plausible.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_LINK_MODE:
-	case OID_SKGE_FLOWCTRL_MODE:
-	case OID_SKGE_PHY_OPERATION_MODE:
-	case OID_SKGE_SPEED_MODE:
-		if (*pLen < Limit - LogPortIndex) {
-
-			*pLen = Limit - LogPortIndex;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen != Limit - LogPortIndex) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-		break;
-
-	case OID_SKGE_MTU:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen != sizeof(SK_U32)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-		break;
-
-    default:
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/*
-	 * Perform preset or set
-	 */
-	Offset = 0;
-	for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_LINK_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_LMODE_HALF ||
-				(LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
-				(LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new link mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_LMODE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR043,
-							SK_PNMI_ERR043MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new link mode to
-				 * the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
-					EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR043,
-						SK_PNMI_ERR043MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_FLOWCTRL_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_FLOW_MODE_NONE ||
-				(LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
-				(LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new flow control mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_FLOWMODE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR044,
-							SK_PNMI_ERR044MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new flow control
-				 * mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_FLOWMODE, EventParam)
-					> 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR044,
-						SK_PNMI_ERR044MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE :
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-				/* mode of this port remains unchanged */
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_MS_MODE_AUTO ||
-				(LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
-				(LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with new master/slave (role) mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_ROLE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR042,
-							SK_PNMI_ERR042MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new master/slave
-				 * (role) mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_ROLE, EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR042,
-						SK_PNMI_ERR042MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SPEED_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < (SK_LSPEED_AUTO) ||
-				(LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
-				(LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new flow control mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_SPEED,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR045,
-							SK_PNMI_ERR045MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new flow control
-				 * mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_SPEED,
-					EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR045,
-						SK_PNMI_ERR045MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_MTU :
-			/* Check the value range */
-			Val32 = *(SK_U32*)(pBuf + Offset);
-			if (Val32 == 0) {
-				/* mtu of this port remains unchanged */
-				Offset += sizeof(SK_U32);
-				break;
-			}
-			if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			Offset += sizeof(SK_U32);
-			break;
-		
-		default:
-            SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-                ("MacPrivateConf: Unknown OID should be handled before set"));
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Monitor - OID handler function for RLMT_MONITOR_XXX
- *
- * Description:
- *	Because RLMT currently does not support the monitoring of
- *	remote adapter cards, we return always an empty table.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Monitor(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	unsigned int	Entries;
-
-	
-	/*
-	 * Calculate instance if wished.
-	 */
-	/* XXX Not yet implemented. Return always an empty table. */
-	Entries = 0;
-
-	if ((Instance != (SK_U32)(-1))) {
-
-		if ((Instance < 1) || (Instance > Entries)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		Index = (unsigned int)Instance - 1;
-		Limit = (unsigned int)Instance;
-	}
-	else {
-		Index = 0;
-		Limit = Entries;
-	}
-
-	/*
-	 * Get/Set value
-	*/
-	if (Action == SK_PNMI_GET) {
-
-		for (Offset=0; Index < Limit; Index ++) {
-
-			switch (Id) {
-
-			case OID_SKGE_RLMT_MONITOR_INDEX:
-			case OID_SKGE_RLMT_MONITOR_ADDR:
-			case OID_SKGE_RLMT_MONITOR_ERRS:
-			case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
-			case OID_SKGE_RLMT_MONITOR_ADMIN:
-				break;
-
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
-					SK_PNMI_ERR046MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-	}
-	else {
-		/* Only MONITOR_ADMIN can be set */
-		if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-
-		/* Check if the length is plausible */
-		if (*pLen < (Limit - Index)) {
-
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		/* Okay, we have a wide value range */
-		if (*pLen != (Limit - Index)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-/*
-		for (Offset=0; Index < Limit; Index ++) {
-		}
-*/
-/*
- * XXX Not yet implemented. Return always BAD_VALUE, because the table
- * is empty.
- */
-		*pLen = 0;
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * VirtualConf - Calculates the values of configuration OIDs for virtual port
- *
- * Description:
- *	We handle here the get of the configuration group OIDs, which are
- *	a little bit complicated. The virtual port consists of all currently
- *	active physical ports. If multiple ports are active and configured
- *	differently we get in some trouble to return a single value. So we
- *	get the value of the first active port and compare it with that of
- *	the other active ports. If they are not the same, we return a value
- *	that indicates that the state is indeterminated.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void VirtualConf(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf)		/* Buffer used for the management data transfer */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	SK_U8		Val8;
-	SK_U32		Val32;
-	SK_BOOL		PortActiveFlag;
-	SK_GEPORT	*pPrt;
-
-	*pBuf = 0;
-	PortActiveFlag = SK_FALSE;
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	
-	for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-		PhysPortIndex ++) {
-
-		pPrt = &pAC->GIni.GP[PhysPortIndex];
-
-		/* Check if the physical port is active */
-		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			continue;
-		}
-
-		PortActiveFlag = SK_TRUE;
-
-		switch (Id) {
-
-		case OID_SKGE_PHY_TYPE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-				Val32 = pPrt->PhyType;
-				SK_PNMI_STORE_U32(pBuf, Val32);
-				continue;
-			}
-
-		case OID_SKGE_LINK_CAP:
-
-			/*
-			 * Different capabilities should not happen, but
-			 * in the case of the cases OR them all together.
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PLinkCap;
-			break;
-
-		case OID_SKGE_LINK_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkModeConf;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * mode than the first one we return a value that
-			 * indicates that the link mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkModeConf) {
-
-				*pBuf = SK_LMODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_LINK_MODE_STATUS:
-			/* Get the link mode of the physical port */
-			Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
-
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = Val8;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * mode status than the first one we return a value
-			 * that indicates that the link mode status is
-			 * indeterminated.
-			 */
-			if (*pBuf != Val8) {
-
-				*pBuf = SK_LMODE_STAT_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_LINK_STATUS:
-			/* Get the link status of the physical port */
-			Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
-
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = Val8;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * status than the first one, we return a value
-			 * that indicates that the link status is
-			 * indeterminated.
-			 */
-			if (*pBuf != Val8) {
-
-				*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_FLOWCTRL_CAP:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlCap;
-				continue;
-			}
-
-			/*
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PFlowCtrlCap;
-			break;
-
-		case OID_SKGE_FLOWCTRL_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlMode;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PFlowCtrlMode) {
-
-				*pBuf = SK_FLOW_MODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_FLOWCTRL_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlStatus;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PFlowCtrlStatus) {
-
-				*pBuf = SK_FLOW_STAT_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_PHY_OPERATION_CAP:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSCap;
-				continue;
-			}
-
-			/*
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PMSCap;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSMode;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different master/
-			 * slave mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PMSMode) {
-
-				*pBuf = SK_MS_MODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_PHY_OPERATION_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSStatus;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different master/
-			 * slave status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PMSStatus) {
-
-				*pBuf = SK_MS_STAT_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_SPEED_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkSpeed;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkSpeed) {
-
-				*pBuf = SK_LSPEED_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_SPEED_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkSpeedUsed;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkSpeedUsed) {
-
-				*pBuf = SK_LSPEED_STAT_INDETERMINATED;
-			}
-			break;
-		}
-	}
-
-	/*
-	 * If no port is active return an indeterminated answer
-	 */
-	if (!PortActiveFlag) {
-
-		switch (Id) {
-
-		case OID_SKGE_LINK_CAP:
-			*pBuf = SK_LMODE_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_MODE:
-			*pBuf = SK_LMODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_MODE_STATUS:
-			*pBuf = SK_LMODE_STAT_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_STATUS:
-			*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
-			break;
-
-		case OID_SKGE_FLOWCTRL_CAP:
-		case OID_SKGE_FLOWCTRL_MODE:
-			*pBuf = SK_FLOW_MODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_FLOWCTRL_STATUS:
-			*pBuf = SK_FLOW_STAT_INDETERMINATED;
-			break;
-			
-		case OID_SKGE_PHY_OPERATION_CAP:
-			*pBuf = SK_MS_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE:
-			*pBuf = SK_MS_MODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_STATUS:
-			*pBuf = SK_MS_STAT_INDETERMINATED;
-			break;
-		case OID_SKGE_SPEED_CAP:
-			*pBuf = SK_LSPEED_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_SPEED_MODE:
-			*pBuf = SK_LSPEED_INDETERMINATED;
-			break;
-
-		case OID_SKGE_SPEED_STATUS:
-			*pBuf = SK_LSPEED_STAT_INDETERMINATED;
-			break;
-		}
-	}
-}
-
-/*****************************************************************************
- *
- * CalculateLinkStatus - Determins the link status of a physical port
- *
- * Description:
- *	Determins the link status the following way:
- *	  LSTAT_PHY_DOWN:  Link is down
- *	  LSTAT_AUTONEG:   Auto-negotiation failed
- *	  LSTAT_LOG_DOWN:  Link is up but RLMT did not yet put the port
- *	                   logically up.
- *	  LSTAT_LOG_UP:    RLMT marked the port as up
- *
- * Returns:
- *	Link status of physical port
- */
-PNMI_STATIC SK_U8 CalculateLinkStatus(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_IOC IoC,			/* IO context handle */
-unsigned int PhysPortIndex)	/* Physical port index */
-{
-	SK_U8	Result;
-
-	if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
-
-		Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
-	}
-	else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
-
-		Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
-				}
-	else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
-
-		Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
-	}
-	else {
-		Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
-	}
-
-	return (Result);
-}
-
-/*****************************************************************************
- *
- * CalculateLinkModeStatus - Determins the link mode status of a phys. port
- *
- * Description:
- *	The COMMON module only tells us if the mode is half or full duplex.
- *	But in the decade of auto sensing it is useful for the user to
- *	know if the mode was negotiated or forced. Therefore we have a
- *	look to the mode, which was last used by the negotiation process.
- *
- * Returns:
- *	The link mode status
- */
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_IOC IoC,			/* IO context handle */
-unsigned int PhysPortIndex)	/* Physical port index */
-{
-	SK_U8	Result;
-
-	/* Get the current mode, which can be full or half duplex */
-	Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
-
-	/* Check if no valid mode could be found (link is down) */
-	if (Result < SK_LMODE_STAT_HALF) {
-
-		Result = SK_LMODE_STAT_UNKNOWN;
-	}
-	else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
-
-		/*
-		 * Auto-negotiation was used to bring up the link. Change
-		 * the already found duplex status that it indicates
-		 * auto-negotiation was involved.
-		 */
-		if (Result == SK_LMODE_STAT_HALF) {
-
-			Result = SK_LMODE_STAT_AUTOHALF;
-		}
-		else if (Result == SK_LMODE_STAT_FULL) {
-
-			Result = SK_LMODE_STAT_AUTOFULL;
-		}
-	}
-
-	return (Result);
-}
-
-/*****************************************************************************
- *
- * GetVpdKeyArr - Obtain an array of VPD keys
- *
- * Description:
- *	Read the VPD keys and build an array of VPD keys, which are
- *	easy to access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int GetVpdKeyArr(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-char *pKeyArr,		/* Ptr KeyArray */
-unsigned int KeyArrLen,	/* Length of array in bytes */
-unsigned int *pKeyNo)	/* Number of keys */
-{
-	unsigned int		BufKeysLen = SK_PNMI_VPD_BUFSIZE;
-	char			BufKeys[SK_PNMI_VPD_BUFSIZE];
-	unsigned int		StartOffset;
-	unsigned int		Offset;
-	int			Index;
-	int			Ret;
-
-
-	SK_MEMSET(pKeyArr, 0, KeyArrLen);
-
-	/*
-	 * Get VPD key list
-	 */
-	Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
-		(int *)pKeyNo);
-	if (Ret > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
-			SK_PNMI_ERR014MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	/* If no keys are available return now */
-	if (*pKeyNo == 0 || BufKeysLen == 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-	/*
-	 * If the key list is too long for us trunc it and give a
-	 * errorlog notification. This case should not happen because
-	 * the maximum number of keys is limited due to RAM limitations
-	 */
-	if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
-			SK_PNMI_ERR015MSG);
-
-		*pKeyNo = SK_PNMI_VPD_ENTRIES;
-	}
-
-	/*
-	 * Now build an array of fixed string length size and copy
-	 * the keys together.
-	 */
-	for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
-		Offset ++) {
-
-		if (BufKeys[Offset] != 0) {
-
-			continue;
-		}
-
-		if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
-				SK_PNMI_ERR016MSG);
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
-			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
-
-		Index ++;
-		StartOffset = Offset + 1;
-	}
-
-	/* Last key not zero terminated? Get it anyway */
-	if (StartOffset < Offset) {
-
-		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
-			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SirqUpdate - Let the SIRQ update its internal values
- *
- * Description:
- *	Just to be sure that the SIRQ module holds its internal data
- *	structures up to date, we send an update event before we make
- *	any access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int SirqUpdate(
-SK_AC *pAC,	/* Pointer to adapter context */
-SK_IOC IoC)	/* IO context handle */
-{
-	SK_EVPARA	EventParam;
-
-
-	/* Was the module already updated during the current PNMI call? */
-	if (pAC->Pnmi.SirqUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an synchronuous update event to the module */
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-	if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
-			SK_PNMI_ERR047MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtUpdate - Let the RLMT update its internal values
- *
- * Description:
- *	Just to be sure that the RLMT module holds its internal data
- *	structures up to date, we send an update event before we make
- *	any access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int RlmtUpdate(
-SK_AC *pAC,	/* Pointer to adapter context */
-SK_IOC IoC,	/* IO context handle */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	SK_EVPARA	EventParam;
-
-
-	/* Was the module already updated during the current PNMI call? */
-	if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an synchronuous update event to the module */
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
-			SK_PNMI_ERR048MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacUpdate - Force the XMAC to output the current statistic
- *
- * Description:
- *	The XMAC holds its statistic internally. To obtain the current
- *	values we must send a command so that the statistic data will
- *	be written to a predefined memory area on the adapter.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int MacUpdate(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-unsigned int FirstMac,	/* Index of the first Mac to be updated */
-unsigned int LastMac)	/* Index of the last Mac to be updated */
-{
-	unsigned int	MacIndex;
-
-	/*
-	 * Were the statistics already updated during the
-	 * current PNMI call?
-	 */
-	if (pAC->Pnmi.MacUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an update command to all MACs specified */
-	for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
-
-		/*
-		 * 2002-09-13 pweber:	Freeze the current SW counters.
-		 *                      (That should be done as close as
-		 *                      possible to the update of the
-		 *                      HW counters)
-		 */
-		if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
-			pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
-		}
-			
-		/* 2002-09-13 pweber:  Update the HW counter  */
-		if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * GetStatVal - Retrieve an XMAC statistic counter
- *
- * Description:
- *	Retrieves the statistic counter of a virtual or physical port. The
- *	virtual port is identified by the index 0. It consists of all
- *	currently active ports. To obtain the counter value for this port
- *	we must add the statistic counter of all active ports. To grant
- *	continuous counter values for the virtual port even when port
- *	switches occur we must additionally add a delta value, which was
- *	calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
- *
- * Returns:
- *	Requested statistic value
- */
-PNMI_STATIC SK_U64 GetStatVal(
-SK_AC *pAC,					/* Pointer to adapter context */
-SK_IOC IoC,					/* IO context handle */
-unsigned int LogPortIndex,	/* Index of the logical Port to be processed */
-unsigned int StatIndex,		/* Index to statistic value */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	unsigned int	PhysPortIndex;
-	unsigned int	PhysPortMax;
-	SK_U64			Val = 0;
-
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {	/* Dual net mode */
-
-		PhysPortIndex = NetIndex;
-		
-		Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-	}
-	else {	/* Single Net mode */
-
-		if (LogPortIndex == 0) {
-
-			PhysPortMax = pAC->GIni.GIMacsFound;
-
-			/* Add counter of all active ports */
-			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-				PhysPortIndex ++) {
-
-				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-					Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-				}
-			}
-
-			/* Correct value because of port switches */
-			Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
-		}
-		else {
-			/* Get counter value of physical port */
-			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-			
-			Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-		}
-	}
-	return (Val);
-}
-
-/*****************************************************************************
- *
- * GetPhysStatVal - Get counter value for physical port
- *
- * Description:
- *	Builds a 64bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	in software by monitoring counter overflow interrupts in the
- *	event handler. To grant continous counter values during XMAC
- *	resets (caused by a workaround) we must add a delta value.
- *	The delta was calculated in the event handler when a
- *	SK_PNMI_EVT_XMAC_RESET was received.
- *
- * Returns:
- *	Counter value
- */
-PNMI_STATIC SK_U64 GetPhysStatVal(
-SK_AC *pAC,					/* Pointer to adapter context */
-SK_IOC IoC,					/* IO context handle */
-unsigned int PhysPortIndex,	/* Index of the logical Port to be processed */
-unsigned int StatIndex)		/* Index to statistic value */
-{
-	SK_U64	Val = 0;
-	SK_U32	LowVal = 0;
-	SK_U32	HighVal = 0;
-	SK_U16	Word;
-	int		MacType;
-	unsigned int HelpIndex;
-	SK_GEPORT	*pPrt;
-	
-	SK_PNMI_PORT	*pPnmiPrt;
-	SK_GEMACFUNC	*pFnMac;
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	
-	MacType = pAC->GIni.GIMacType;
-	
-	/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-	if (MacType == SK_MAC_XMAC) {
-		pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
-	}
-	else {
-		pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
-	}
-	
-	pFnMac   = &pAC->GIni.GIFunc;
-
-	switch (StatIndex) {
-	case SK_PNMI_HTX:
-		if (MacType == SK_MAC_GMAC) {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
-							&LowVal);
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-		}
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-	
-	case SK_PNMI_HRX:
-		if (MacType == SK_MAC_GMAC) {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
-							&LowVal);
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-		}
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_OCTET:
-	case SK_PNMI_HRX_OCTET:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &HighVal);
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex + 1][MacType].Reg,
-									  &LowVal);
-		break;
-
-	case SK_PNMI_HTX_BURST:
-	case SK_PNMI_HTX_EXCESS_DEF:
-	case SK_PNMI_HTX_CARRIER:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_MACC:
-		/* GMAC only supports PAUSE MAC control frames */
-		if (MacType == SK_MAC_GMAC) {
-			HelpIndex = SK_PNMI_HTX_PMACC;
-		}
-		else {
-			HelpIndex = StatIndex;
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-								StatAddr[HelpIndex][MacType].Reg,
-								&LowVal);
-
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_COL:
-	case SK_PNMI_HRX_UNDERSIZE:
-		/* Not supported by XMAC */
-		if (MacType == SK_MAC_XMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_DEFFERAL:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-		
-		/*
-		 * XMAC counts frames with deferred transmission
-		 * even in full-duplex mode.
-		 *
-		 * In full-duplex mode the counter remains constant!
-		 */
-		if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
-			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
-
-			LowVal = 0;
-			HighVal = 0;
-		}
-		else {
-			/* Otherwise get contents of hardware register */
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		break;
-
-	case SK_PNMI_HRX_BADOCTET:
-		/* Not supported by XMAC */
-		if (MacType == SK_MAC_XMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &HighVal);
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex + 1][MacType].Reg,
-                                      &LowVal);
-		break;
-
-	case SK_PNMI_HTX_OCTETLOW:
-	case SK_PNMI_HRX_OCTETLOW:
-	case SK_PNMI_HRX_BADOCTETLOW:
-		return (Val);
-
-	case SK_PNMI_HRX_LONGFRAMES:
-		/* For XMAC the SW counter is managed by PNMI */
-		if (MacType == SK_MAC_XMAC) {
-			return (pPnmiPrt->StatRxLongFrameCts);
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-		
-	case SK_PNMI_HRX_TOO_LONG:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-								StatAddr[StatIndex][MacType].Reg,
-								&LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		
-		Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
-		if (MacType == SK_MAC_GMAC) {
-			/* For GMAC the SW counter is additionally managed by PNMI */
-			Val += pPnmiPrt->StatRxFrameTooLongCts;
-		}
-		else {
-			/*
-			 * Frames longer than IEEE 802.3 frame max size are counted
-			 * by XMAC in frame_too_long counter even reception of long
-			 * frames was enabled and the frame was correct.
-			 * So correct the value by subtracting RxLongFrame counter.
-			 */
-			Val -= pPnmiPrt->StatRxLongFrameCts;
-		}
-
-		LowVal = (SK_U32)Val;
-		HighVal = (SK_U32)(Val >> 32);
-		break;
-		
-	case SK_PNMI_HRX_SHORTS:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			/* GM_RXE_FRAG?? */
-			return (Val);
-		}
-		
-		/*
-		 * XMAC counts short frame errors even if link down (#10620)
-		 *
-		 * If link-down the counter remains constant
-		 */
-		if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
-
-			/* Otherwise get incremental difference */
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-
-			Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-			Val -= pPnmiPrt->RxShortZeroMark;
-
-			LowVal = (SK_U32)Val;
-			HighVal = (SK_U32)(Val >> 32);
-		}
-		break;
-
-	case SK_PNMI_HRX_MACC:
-	case SK_PNMI_HRX_MACC_UNKWN:
-	case SK_PNMI_HRX_BURST:
-	case SK_PNMI_HRX_MISSED:
-	case SK_PNMI_HRX_FRAMING:
-	case SK_PNMI_HRX_CARRIER:
-	case SK_PNMI_HRX_IRLENGTH:
-	case SK_PNMI_HRX_SYMBOL:
-	case SK_PNMI_HRX_CEXT:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HRX_PMACC_ERR:
-		/* For GMAC the SW counter is managed by PNMI */
-		if (MacType == SK_MAC_GMAC) {
-			return (pPnmiPrt->StatRxPMaccErr);
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	/* SW counter managed by PNMI */
-	case SK_PNMI_HTX_SYNC:
-		LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
-		HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
-		break;
-
-	/* SW counter managed by PNMI */
-	case SK_PNMI_HTX_SYNC_OCTET:
-		LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
-		HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
-		break;
-
-	case SK_PNMI_HRX_FCS:
-		/*
-		 * Broadcom filters FCS errors and counts it in
-		 * Receive Error Counter register
-		 */
-		if (pPrt->PhyType == SK_PHY_BCOM) {
-			/* do not read while not initialized (PHY_READ hangs!)*/
-			if (pPrt->PState != SK_PRT_RESET) {
-				SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
-				
-				LowVal = Word;
-			}
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		break;
-
-	default:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-	}
-
-	Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
-	/* Correct value because of possible XMAC reset. XMAC Errata #2 */
-	Val += pPnmiPrt->CounterOffset[StatIndex];
-
-	return (Val);
-}
-
-/*****************************************************************************
- *
- * ResetCounter - Set all counters and timestamps to zero
- *
- * Description:
- *	Notifies other common modules which store statistic data to
- *	reset their counters and finally reset our own counters.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void ResetCounter(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 NetIndex)
-{
-	unsigned int	PhysPortIndex;
-	SK_EVPARA	EventParam;
-
-
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-
-	/* Notify sensor module */
-	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
-
-	/* Notify RLMT module */
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
-	EventParam.Para32[1] = 0;
-
-	/* Notify SIRQ module */
-	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
-
-	/* Notify CSUM module */
-#ifdef SK_USE_CSUM
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
-		EventParam);
-#endif /* SK_USE_CSUM */
-	
-	/* Clear XMAC statistic */
-	for (PhysPortIndex = 0; PhysPortIndex <
-		(unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
-
-		(void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
-
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
-			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			CounterOffset, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].CounterOffset));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
-			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatSyncOctetsCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxLongFrameCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-				  StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxFrameTooLongCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-				  StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxPMaccErr));
-	}
-
-	/*
-	 * Clear local statistics
-	 */
-	SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
-		  sizeof(pAC->Pnmi.VirtualCounterOffset));
-	pAC->Pnmi.RlmtChangeCts = 0;
-	pAC->Pnmi.RlmtChangeTime = 0;
-	SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
-		sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
-	pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
-	pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
-	pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
-	pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
-	pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
-	pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
-}
-
-/*****************************************************************************
- *
- * GetTrapEntry - Get an entry in the trap buffer
- *
- * Description:
- *	The trap buffer stores various events. A user application somehow
- *	gets notified that an event occured and retrieves the trap buffer
- *	contens (or simply polls the buffer). The buffer is organized as
- *	a ring which stores the newest traps at the beginning. The oldest
- *	traps are overwritten by the newest ones. Each trap entry has a
- *	unique number, so that applications may detect new trap entries.
- *
- * Returns:
- *	A pointer to the trap entry
- */
-PNMI_STATIC char* GetTrapEntry(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId,		/* SNMP ID of the trap */
-unsigned int Size)	/* Space needed for trap entry */
-{
-	unsigned int		BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int		BufFree = pAC->Pnmi.TrapBufFree;
-	unsigned int		Beg = pAC->Pnmi.TrapQueueBeg;
-	unsigned int		End = pAC->Pnmi.TrapQueueEnd;
-	char			*pBuf = &pAC->Pnmi.TrapBuf[0];
-	int			Wrap;
-	unsigned int		NeededSpace;
-	unsigned int		EntrySize;
-	SK_U32			Val32;
-	SK_U64			Val64;
-
-
-	/* Last byte of entry will get a copy of the entry length */
-	Size ++;
-
-	/*
-	 * Calculate needed buffer space */
-	if (Beg >= Size) {
-
-		NeededSpace = Size;
-		Wrap = SK_FALSE;
-	}
-	else {
-		NeededSpace = Beg + Size;
-		Wrap = SK_TRUE;
-	}
-
-	/*
-	 * Check if enough buffer space is provided. Otherwise
-	 * free some entries. Leave one byte space between begin
-	 * and end of buffer to make it possible to detect whether
-	 * the buffer is full or empty
-	 */
-	while (BufFree < NeededSpace + 1) {
-
-		if (End == 0) {
-
-			End = SK_PNMI_TRAP_QUEUE_LEN;
-		}
-
-		EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
-		BufFree += EntrySize;
-		End -= EntrySize;
-#ifdef DEBUG
-		SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
-#endif /* DEBUG */
-		if (End == BufPad) {
-#ifdef DEBUG
-			SK_MEMSET(pBuf, (char)(-1), End);
-#endif /* DEBUG */
-			BufFree += End;
-			End = 0;
-			BufPad = 0;
-		}
-	}
-
-	/*
-	 * Insert new entry as first entry. Newest entries are
-	 * stored at the beginning of the queue.
-	 */
-	if (Wrap) {
-
-		BufPad = Beg;
-		Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
-	}
-	else {
-		Beg = Beg - Size;
-	}
-	BufFree -= NeededSpace;
-
-	/* Save the current offsets */
-	pAC->Pnmi.TrapQueueBeg = Beg;
-	pAC->Pnmi.TrapQueueEnd = End;
-	pAC->Pnmi.TrapBufPad = BufPad;
-	pAC->Pnmi.TrapBufFree = BufFree;
-
-	/* Initialize the trap entry */
-	*(pBuf + Beg + Size - 1) = (char)Size;
-	*(pBuf + Beg) = (char)Size;
-	Val32 = (pAC->Pnmi.TrapUnique) ++;
-	SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
-	SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
-	Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-	SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
-
-	return (pBuf + Beg);
-}
-
-/*****************************************************************************
- *
- * CopyTrapQueue - Copies the trap buffer for the TRAP OID
- *
- * Description:
- *	On a query of the TRAP OID the trap buffer contents will be
- *	copied continuously to the request buffer, which must be large
- *	enough. No length check is performed.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void CopyTrapQueue(
-SK_AC *pAC,		/* Pointer to adapter context */
-char *pDstBuf)		/* Buffer to which the queued traps will be copied */
-{
-	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
-	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
-	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
-	unsigned int	Len;
-	unsigned int	DstOff = 0;
-
-
-	while (Trap != End) {
-
-		Len = (unsigned int)*(pBuf + Trap);
-
-		/*
-		 * Last byte containing a copy of the length will
-		 * not be copied.
-		 */
-		*(pDstBuf + DstOff) = (char)(Len - 1);
-		SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
-		DstOff += Len - 1;
-
-		Trap += Len;
-		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
-			Trap = BufPad;
-		}
-	}
-}
-
-/*****************************************************************************
- *
- * GetTrapQueueLen - Get the length of the trap buffer
- *
- * Description:
- *	Evaluates the number of currently stored traps and the needed
- *	buffer size to retrieve them.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void GetTrapQueueLen(
-SK_AC *pAC,		/* Pointer to adapter context */
-unsigned int *pLen,	/* Length in Bytes of all queued traps */
-unsigned int *pEntries)	/* Returns number of trapes stored in queue */
-{
-	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
-	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
-	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
-	unsigned int	Len;
-	unsigned int	Entries = 0;
-	unsigned int	TotalLen = 0;
-
-
-	while (Trap != End) {
-
-		Len = (unsigned int)*(pBuf + Trap);
-		TotalLen += Len - 1;
-		Entries ++;
-
-		Trap += Len;
-		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
-			Trap = BufPad;
-		}
-	}
-
-	*pEntries = Entries;
-	*pLen = TotalLen;
-}
-
-/*****************************************************************************
- *
- * QueueSimpleTrap - Store a simple trap to the trap buffer
- *
- * Description:
- *	A simple trap is a trap with now additional data. It consists
- *	simply of a trap code.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueSimpleTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId)		/* Type of sensor trap */
-{
-	GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
-}
-
-/*****************************************************************************
- *
- * QueueSensorTrap - Stores a sensor trap in the trap buffer
- *
- * Description:
- *	Gets an entry in the trap buffer and fills it with sensor related
- *	data.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueSensorTrap(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_U32 TrapId,			/* Type of sensor trap */
-unsigned int SensorIndex)	/* Index of sensor which caused the trap */
-{
-	char		*pBuf;
-	unsigned int	Offset;
-	unsigned int	DescrLen;
-	SK_U32		Val32;
-
-
-	/* Get trap buffer entry */
-	DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
-	pBuf = GetTrapEntry(pAC, TrapId,
-		SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
-	Offset = SK_PNMI_TRAP_SIMPLE_LEN;
-
-	/* Store additionally sensor trap related data */
-	Val32 = OID_SKGE_SENSOR_INDEX;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 4;
-	Val32 = (SK_U32)SensorIndex;
-	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
-	Offset += 9;
-	
-	Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = (char)DescrLen;
-	SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
-		DescrLen);
-	Offset += DescrLen + 5;
-
-	Val32 = OID_SKGE_SENSOR_TYPE;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 1;
-	*(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
-	Offset += 6;
-
-	Val32 = OID_SKGE_SENSOR_VALUE;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 4;
-	Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
-	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
-}
-
-/*****************************************************************************
- *
- * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueRlmtNewMacTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-unsigned int ActiveMac)	/* Index (0..n) of the currently active port */
-{
-	char	*pBuf;
-	SK_U32	Val32;
-
-
-	pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
-		SK_PNMI_TRAP_RLMT_CHANGE_LEN);
-
-	Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
-	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
-}
-
-/*****************************************************************************
- *
- * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueRlmtPortTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId,		/* Type of RLMT port trap */
-unsigned int PortIndex)	/* Index of the port, which changed its state */
-{
-	char	*pBuf;
-	SK_U32	Val32;
-
-
-	pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
-
-	Val32 = OID_SKGE_RLMT_PORT_INDEX;
-	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
-}
-
-/*****************************************************************************
- *
- * CopyMac - Copies a MAC address
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void CopyMac(
-char *pDst,		/* Pointer to destination buffer */
-SK_MAC_ADDR *pMac)	/* Pointer of Source */
-{
-	int	i;
-
-
-	for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
-
-		*(pDst + i) = pMac->a[i];
-	}
-}
-
-#ifdef SK_POWER_MGMT
-/*****************************************************************************
- *
- * PowerManagement - OID handler function of PowerManagement OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                               exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-
-PNMI_STATIC int PowerManagement(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* Get/PreSet/Set action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	
-	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-	
-    
-    /* Check length */
-    switch (Id) {
-
-    case OID_PNP_CAPABILITIES:
-        if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
-
-            *pLen = sizeof(SK_PNP_CAPABILITIES);
-            return (SK_PNMI_ERR_TOO_SHORT);
-        }
-        break;
-
-	case OID_PNP_SET_POWER:
-    case OID_PNP_QUERY_POWER:
-    	if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
-    	{
-    		*pLen = sizeof(SK_DEVICE_POWER_STATE);
-    		return (SK_PNMI_ERR_TOO_SHORT);
-    	}
-        break;
-
-    case OID_PNP_ADD_WAKE_UP_PATTERN:
-    case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-		if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
-
-			*pLen = sizeof(SK_PM_PACKET_PATTERN);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-    case OID_PNP_ENABLE_WAKE_UP:
-        if (*pLen < sizeof(SK_U32)) {
-
-            *pLen = sizeof(SK_U32);
-            return (SK_PNMI_ERR_TOO_SHORT);
-        }
-        break;
-    }
-	
-    /*
-	 * Perform action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/*
-		 * Get value
-		 */
-		switch (Id) {
-
-		case OID_PNP_CAPABILITIES:
-			RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
-			break;
-
-		case OID_PNP_QUERY_POWER:
-			/* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
-			 the miniport to indicate whether it can transition its NIC
-			 to the low-power state.
-			 A miniport driver must always return NDIS_STATUS_SUCCESS
-			 to a query of OID_PNP_QUERY_POWER. */
-			*pLen = sizeof(SK_DEVICE_POWER_STATE);
-            RetCode = SK_PNMI_ERR_OK;
-			break;
-
-			/* NDIS handles these OIDs as write-only.
-			 * So in case of get action the buffer with written length = 0
-			 * is returned
-			 */
-		case OID_PNP_SET_POWER:
-		case OID_PNP_ADD_WAKE_UP_PATTERN:
-		case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-			*pLen = 0;	
-            RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
-			break;
-
-		case OID_PNP_ENABLE_WAKE_UP:
-			RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
-			break;
-
-		default:
-			RetCode = SK_PNMI_ERR_GENERAL;
-			break;
-		}
-
-		return (RetCode);
-	}
-	
-
-	/*
-	 * Perform preset or set
-	 */
-	
-	/* POWER module does not support PRESET action */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK);
-	}
-
-	switch (Id) {
-	case OID_PNP_SET_POWER:
-		RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);	
-		break;
-
-	case OID_PNP_ADD_WAKE_UP_PATTERN:
-		RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);	
-		break;
-		
-	case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-		RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);	
-		break;
-		
-	case OID_PNP_ENABLE_WAKE_UP:
-		RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
-		break;
-		
-	default:
-		RetCode = SK_PNMI_ERR_READ_ONLY;
-	}
-	
-	return (RetCode);
-}
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-/*****************************************************************************
- *
- * DiagActions - OID handler function of Diagnostic driver 
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-
-PNMI_STATIC int DiagActions(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-
-	SK_U32	DiagStatus;
-	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
-
-	/*
-	 * Check instance. We only handle single instance variables.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check length.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_DIAG_MODE:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/* Perform action. */
-
-	/* GET value. */
-	if (Action == SK_PNMI_GET) {
-
-		switch (Id) {
-
-		case OID_SKGE_DIAG_MODE:
-			DiagStatus = pAC->Pnmi.DiagAttached;
-			SK_PNMI_STORE_U32(pBuf, DiagStatus);
-			*pLen = sizeof(SK_U32);	
-			RetCode = SK_PNMI_ERR_OK;
-			break;
-
-		default:
-			*pLen = 0;	
-			RetCode = SK_PNMI_ERR_GENERAL;
-			break;
-		}
-		return (RetCode); 
-	}
-
-	/* From here SET or PRESET value. */
-	
-	/* PRESET value is not supported. */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK); 
-	}
-
-	/* SET value. */
-	switch (Id) {
-		case OID_SKGE_DIAG_MODE:
-
-			/* Handle the SET. */
-			switch (*pBuf) {
-
-				/* Attach the DIAG to this adapter. */
-				case SK_DIAG_ATTACHED:
-					/* Check if we come from running */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
-						RetCode = SkDrvLeaveDiagMode(pAC);
-
-					}
-					else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
-
-						RetCode = SK_PNMI_ERR_OK;
-					}	
-					
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-
-					}
-					
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
-					}
-					break;
-
-				/* Enter the DIAG mode in the driver. */
-				case SK_DIAG_RUNNING:
-					RetCode = SK_PNMI_ERR_OK;
-					
-					/*
-					 * If DiagAttached is set, we can tell the driver
-					 * to enter the DIAG mode.
-					 */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
-						/* If DiagMode is not active, we can enter it. */
-						if (!pAC->DiagModeActive) {
-
-							RetCode = SkDrvEnterDiagMode(pAC); 
-						}
-						else {
-
-							RetCode = SK_PNMI_ERR_GENERAL;
-						}
-					}
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-					}
-					
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
-					}
-					break;
-
-				case SK_DIAG_IDLE:
-					/* Check if we come from running */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
-						RetCode = SkDrvLeaveDiagMode(pAC);
-
-					}
-					else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
-
-						RetCode = SK_PNMI_ERR_OK;
-					}	
-					
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-
-					}
-
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
-					}
-					break;
-
-				default:
-					RetCode = SK_PNMI_ERR_BAD_VALUE;
-					break;
-			}
-			break;
-
-		default:
-			RetCode = SK_PNMI_ERR_GENERAL;
-	}
-
-	if (RetCode == SK_PNMI_ERR_OK) {
-		*pLen = sizeof(SK_U32);
-	}
-	else {
-
-		*pLen = 0;
-	}
-	return (RetCode);
-}
-#endif /* SK_DIAG_SUPPORT */
-
-/*****************************************************************************
- *
- * Vct - OID handler function of  OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was performed successfully.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter).
- *	SK_PNMI_ERR_READ_ONLY	 Only the Get action is allowed.
- *
- */
-
-PNMI_STATIC int Vct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (-1,2..n) that is to be queried */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_GEPORT	*pPrt;
-	SK_PNMI_VCT	*pVctBackupData;
-	SK_U32		LogPortMax;
-	SK_U32		PhysPortMax;
-	SK_U32		PhysPortIndex;
-	SK_U32		Limit;
-	SK_U32		Offset;
-	SK_BOOL		Link;
-	SK_U32		RetCode = SK_PNMI_ERR_GENERAL;
-	int		i;
-	SK_EVPARA	Para;
-	SK_U32		CableLength;
-	
-	/*
-	 * Calculate the port indexes from the instance.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-	
-	/* Dual net mode? */
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-		LogPortMax--;
-	}
-	
-	if ((Instance != (SK_U32) (-1))) {
-		/* Check instance range. */
-		if ((Instance < 2) || (Instance > LogPortMax)) {
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-		}
-		else {
-			PhysPortIndex = Instance - 2;
-		}
-		Limit = PhysPortIndex + 1;
-	}
-	else {
-		/*
-		 * Instance == (SK_U32) (-1), get all Instances of that OID.
-		 *
-		 * Not implemented yet. May be used in future releases.
-		 */
-		PhysPortIndex = 0;
-		Limit = PhysPortMax;
-	}
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	if (pPrt->PHWLinkUp) {
-		Link = SK_TRUE;
-	}
-	else {
-		Link = SK_FALSE;
-	}
-	
-	/* Check MAC type */
-	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	
-	/* Initialize backup data pointer. */
-	pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-	
-	/* Check action type */
-	if (Action == SK_PNMI_GET) {
-		/* Check length */
-		switch (Id) {
-		
-		case OID_SKGE_VCT_GET:
-			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
-				*pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-		
-		case OID_SKGE_VCT_STATUS:
-			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
-				*pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-		
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}	
-		
-		/* Get value */
-		Offset = 0;
-		for (; PhysPortIndex < Limit; PhysPortIndex++) {
-			switch (Id) {
-			
-			case OID_SKGE_VCT_GET:
-				if ((Link == SK_FALSE) &&
-					(pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
-					RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
-					if (RetCode == 0) {
-						pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
-						pAC->Pnmi.VctStatus[PhysPortIndex] |=
-							(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-						
-						/* Copy results for later use to PNMI struct. */
-						for (i = 0; i < 4; i++)  {
-							if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
-								if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
-									pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
-								}
-							}
-							if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
-								CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
-							}
-							else {
-								CableLength = 0;
-							}
-							pVctBackupData->PMdiPairLen[i] = CableLength;
-							pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
-						}
-
-						Para.Para32[0] = PhysPortIndex;
-						Para.Para32[1] = -1;
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-						SkEventDispatcher(pAC, IoC);
-					}
-					else {
-						; /* VCT test is running. */
-					}
-				}
-				
-				/* Get all results. */
-				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
-				Offset += sizeof(SK_U8);
-				*(pBuf + Offset) = pPrt->PCableLen;
-				Offset += sizeof(SK_U8);
-				for (i = 0; i < 4; i++)  {
-					SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
-					Offset += sizeof(SK_U32);
-				}
-				for (i = 0; i < 4; i++)  {
-					*(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
-					Offset += sizeof(SK_U8);
-				}
-				
-				RetCode = SK_PNMI_ERR_OK;
-				break;
-		
-			case OID_SKGE_VCT_STATUS:
-				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
-				Offset += sizeof(SK_U8);
-				RetCode = SK_PNMI_ERR_OK;
-				break;
-			
-			default:
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		} /* for */
-		*pLen = Offset;
-		return (RetCode);
-	
-	} /* if SK_PNMI_GET */
-	
-	/*
-	 * From here SET or PRESET action. Check if the passed
-	 * buffer length is plausible.
-	 */
-	
-	/* Check length */
-	switch (Id) {
-	case OID_SKGE_VCT_SET:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-	
-	default:
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	
-	/*
-	 * Perform preset or set.
-	 */
-	
-	/* VCT does not support PRESET action. */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK);
-	}
-	
-	Offset = 0;
-	for (; PhysPortIndex < Limit; PhysPortIndex++) {
-		switch (Id) {
-		case OID_SKGE_VCT_SET: /* Start VCT test. */
-			if (Link == SK_FALSE) {
-				SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
-				
-				RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
-				if (RetCode == 0) { /* RetCode: 0 => Start! */
-					pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
-					pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
-					pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
-					
-					/*
-					 * Start VCT timer counter.
-					 */
-					SK_MEMSET((char *) &Para, 0, sizeof(Para));
-					Para.Para32[0] = PhysPortIndex;
-					Para.Para32[1] = -1;
-					SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
-						4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
-					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-					RetCode = SK_PNMI_ERR_OK;
-				}
-				else { /* RetCode: 2 => Running! */
-					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-					RetCode = SK_PNMI_ERR_OK;
-				}
-			}
-			else { /* RetCode: 4 => Link! */
-				RetCode = 4;
-				SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-				RetCode = SK_PNMI_ERR_OK;
-			}
-			Offset += sizeof(SK_U32);
-			break;
-	
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	} /* for */
-	*pLen = Offset;
-	return (RetCode);
-
-} /* Vct */
-
-
-PNMI_STATIC void CheckVctStatus(
-SK_AC		*pAC,
-SK_IOC		IoC,
-char		*pBuf,
-SK_U32		Offset,
-SK_U32		PhysPortIndex)
-{
-	SK_GEPORT 	*pPrt;
-	SK_PNMI_VCT	*pVctData;
-	SK_U32		RetCode;
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	
-	pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
-	pVctData->VctStatus = SK_PNMI_VCT_NONE;
-	
-	if (!pPrt->PHWLinkUp) {
-		
-		/* Was a VCT test ever made before? */
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
-			if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
-				pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
-			}
-			else {
-				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
-			}
-		}
-		
-		/* Check VCT test status. */
-		RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
-		if (RetCode == 2) { /* VCT test is running. */
-			pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
-		}
-		else { /* VCT data was copied to pAC here. Check PENDING state. */
-			if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
-				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
-			}
-		}
-		
-		if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
-			pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
-		}
-	}
-	else {
-		
-		/* Was a VCT test ever made before? */
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
-			pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
-			pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
-		}
-		
-		/* DSP only valid in 100/1000 modes. */
-		if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
-			SK_LSPEED_STAT_10MBPS) {	
-			pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
-		}
-	}
-} /* CheckVctStatus */
-
-
-/*****************************************************************************
- *
- *      SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
- *                       PNMI function depending on the subcommand and
- *                       returns all data belonging to the complete database
- *                       or OID request.
- *
- * Description:
- *	Looks up the requested subcommand, calls the corresponding handler
- *	function and passes all required parameters to it.
- *	The function is called by the driver. It is needed to handle the new
- *  generic PNMI IOCTL. This IOCTL is given to the driver and contains both
- *  the OID and a subcommand to decide what kind of request has to be done.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-int SkPnmiGenIoctl(
-SK_AC		*pAC,		/* Pointer to adapter context struct */
-SK_IOC		IoC,		/* I/O context */
-void		*pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,		/* Length of buffer */
-SK_U32		NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-SK_I32	Mode;			/* Store value of subcommand. */
-SK_U32	Oid;			/* Store value of OID. */
-int		ReturnCode;		/* Store return value to show status of PNMI action. */
-int 	HeaderLength;	/* Length of desired action plus OID. */
-
-	ReturnCode = SK_PNMI_ERR_GENERAL;
-	
-	SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
-	SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
-	HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
-	*pLen = *pLen - HeaderLength;
-	SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
-	
-	switch(Mode) {
-	case SK_GET_SINGLE_VAR:
-		ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_PRESET_SINGLE_VAR:
-		ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_SET_SINGLE_VAR:
-		ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_GET_FULL_MIB:
-		ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	case SK_PRESET_FULL_MIB:
-		ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	case SK_SET_FULL_MIB:
-		ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	default:
-		break;
-	}
-	
-	return (ReturnCode);
-
-} /* SkGeIocGen */
diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
deleted file mode 100644
index 3e7aa49..0000000
--- a/drivers/net/sk98lin/skgesirq.c
+++ /dev/null
@@ -1,2229 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgesirq.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.92 $
- * Date:	$Date: 2003/09/16 14:37:07 $
- * Purpose:	Special IRQ module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	Special Interrupt handler
- *
- *	The following abstract should show how this module is included
- *	in the driver path:
- *
- *	In the ISR of the driver the bits for frame transmission complete and
- *	for receive complete are checked and handled by the driver itself.
- *	The bits of the slow path mask are checked after that and then the
- *	entry into the so-called "slow path" is prepared. It is an implementors
- *	decision whether this is executed directly or just scheduled by
- *	disabling the mask. In the interrupt service routine some events may be
- *	generated, so it would be a good idea to call the EventDispatcher
- *	right after this ISR.
- *
- *	The Interrupt source register of the adapter is NOT read by this module.
- *  SO if the drivers implementor needs a while loop around the
- *	slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
- *	each loop entered.
- *
- *	However, the MAC Interrupt status registers are read in a while loop.
- *
- */
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#ifndef SK_SLIM
-#include "h/skgepnmi.h"		/* PNMI Definitions */
-#include "h/skrlmt.h"		/* RLMT Definitions */
-#endif
-#include "h/skdrv2nd.h"		/* Adapter Control and Driver specific Def. */
-
-/* local function prototypes */
-#ifdef GENESIS
-static int	SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* GENESIS */
-#ifdef YUKON
-static int	SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static int	SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* OTHER_PHY */
-
-#ifdef GENESIS
-/*
- * array of Rx counter from XMAC which are checked
- * in AutoSense mode to check whether a link is not able to auto-negotiate.
- */
-static const SK_U16 SkGeRxRegs[]= {
-	XM_RXF_64B,
-	XM_RXF_127B,
-	XM_RXF_255B,
-	XM_RXF_511B,
-	XM_RXF_1023B,
-	XM_RXF_MAX_SZ
-} ;
-#endif /* GENESIS */
-
-#ifdef __C2MAN__
-/*
- *	Special IRQ function
- *
- *	General Description:
- *
- */
-intro()
-{}
-#endif
-
-/******************************************************************************
- *
- *	SkHWInitDefSense() - Default Autosensing mode initialization
- *
- * Description: sets the PLinkMode for HWInit
- *
- * Returns: N/A
- */
-static void SkHWInitDefSense(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-	if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
-		pPrt->PLinkMode = pPrt->PLinkModeConf;
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("AutoSensing: First mode %d on Port %d\n",
-		(int)SK_LMODE_AUTOFULL, Port));
-
-	pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
-
-	return;
-}	/* SkHWInitDefSense */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkHWSenseGetNext() - Get Next Autosensing Mode
- *
- * Description: gets the appropriate next mode
- *
- * Note:
- *
- */
-static SK_U8 SkHWSenseGetNext(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
-		/* Leave all as configured */
-		return(pPrt->PLinkModeConf);
-	}
-
-    if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
-		/* Return next mode AUTOBOTH */
-        return ((SK_U8)SK_LMODE_AUTOBOTH);
-	}
-
-	/* Return default autofull */
-    return ((SK_U8)SK_LMODE_AUTOFULL);
-}	/* SkHWSenseGetNext */
-
-
-/******************************************************************************
- *
- *	SkHWSenseSetNext() - Autosensing Set next mode
- *
- * Description:	sets the appropriate next mode
- *
- * Returns: N/A
- */
-static void SkHWSenseSetNext(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U8	NewMode)	/* New Mode to be written in sense mode */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("AutoSensing: next mode %d on Port %d\n",
-		(int)NewMode, Port));
-
-	pPrt->PLinkMode = NewMode;
-
-	return;
-}	/* SkHWSenseSetNext */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkHWLinkDown() - Link Down handling
- *
- * Description: handles the hardware link down signal
- *
- * Returns: N/A
- */
-void SkHWLinkDown(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Disable all MAC interrupts */
-	SkMacIrqDisable(pAC, IoC, Port);
-
-	/* Disable Receiver and Transmitter */
-	SkMacRxTxDisable(pAC, IoC, Port);
-	
-	/* Init default sense mode */
-	SkHWInitDefSense(pAC, IoC, Port);
-
-	if (pPrt->PHWLinkUp == SK_FALSE) {
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("Link down Port %d\n", Port));
-
-	/* Set Link to DOWN */
-	pPrt->PHWLinkUp = SK_FALSE;
-
-	/* Reset Port stati */
-    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-    pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
-
-	/* Re-init Phy especially when the AutoSense default is set now */
-	SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
-	/* GP0: used for workaround of Rev. C Errata 2 */
-
-	/* Do NOT signal to RLMT */
-
-	/* Do NOT start the timer here */
-}	/* SkHWLinkDown */
-
-
-/******************************************************************************
- *
- *	SkHWLinkUp() - Link Up handling
- *
- * Description: handles the hardware link up signal
- *
- * Returns: N/A
- */
-static void SkHWLinkUp(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		/* We do NOT need to proceed on active link */
-		return;
-	}
-
-	pPrt->PHWLinkUp = SK_TRUE;
-	pPrt->PAutoNegFail = SK_FALSE;
-    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-
-    if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
-        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
-        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
-		/* Link is up and no Auto-negotiation should be done */
-
-		/* Link speed should be the configured one */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-			/* default is 1000 Mbps */
-		case SK_LSPEED_1000MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-			break;
-		case SK_LSPEED_100MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
-			break;
-		case SK_LSPEED_10MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
-			break;
-		}
-
-		/* Set Link Mode Status */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
-		}
-		else {
-            pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
-		}
-
-		/* No flow control without auto-negotiation */
-        pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-
-		/* enable Rx/Tx */
-        (void)SkMacRxTxEnable(pAC, IoC, Port);
-	}
-}	/* SkHWLinkUp */
-
-
-/******************************************************************************
- *
- *	SkMacParity() - MAC parity workaround
- *
- * Description: handles MAC parity errors correctly
- *
- * Returns: N/A
- */
-static void SkMacParity(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index of the port failed */
-{
-	SK_EVPARA	Para;
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U32		TxMax;		/* Tx Max Size Counter */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Clear IRQ Tx Parity Error */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
-			(SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
-			pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
-	}
-#endif /* YUKON */
-	
-	if (pPrt->PCheckPar) {
-
-		if (Port == MAC_1) {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
-		}
-		Para.Para64 = Port;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = Port;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		return;
-	}
-
-	/* Check whether frames with a size of 1k were sent */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* Snap statistic counters */
-		(void)SkXmUpdateStats(pAC, IoC, Port);
-		
-		(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-
-		(void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
-	}
-#endif /* YUKON */
-	
-	if (TxMax > 0) {
-		/* From now on check the parity */
-		pPrt->PCheckPar = SK_TRUE;
-	}
-}	/* SkMacParity */
-
-
-/******************************************************************************
- *
- *	SkGeHwErr() - Hardware Error service routine
- *
- * Description: handles all HW Error interrupts
- *
- * Returns: N/A
- */
-static void SkGeHwErr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-SK_U32	HwStatus)	/* Interrupt status word */
-{
-	SK_EVPARA	Para;
-	SK_U16		Word;
-
-	if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
-		/* PCI Errors occured */
-		if ((HwStatus & IS_IRQ_STAT) != 0) {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
-		}
-
-		/* Reset all bits in the PCI STATUS register */
-		SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-		
-		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-        SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		if ((HwStatus & IS_NO_STAT_M1) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
-		}
-
-		if ((HwStatus & IS_NO_STAT_M2) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
-		}
-
-		if ((HwStatus & IS_NO_TIST_M1) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
-		}
-
-		if ((HwStatus & IS_NO_TIST_M2) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* This is necessary only for Rx timing measurements */
-		if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
-			/* increment Time Stamp Timer counter (high) */
-			pAC->GIni.GITimeStampCnt++;
-
-			/* Clear Time Stamp Timer IRQ */
-			SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
-		}
-
-		if ((HwStatus & IS_IRQ_SENSOR) != 0) {
-			/* no sensors on 32-bit Yukon */
-			if (pAC->GIni.GIYukon32Bit) {
-				/* disable HW Error IRQ */
-				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
-			}
-		}
-	}
-#endif /* YUKON */
-
-	if ((HwStatus & IS_RAM_RD_PAR) != 0) {
-		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-	if ((HwStatus & IS_RAM_WR_PAR) != 0) {
-		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-	if ((HwStatus & IS_M1_PAR_ERR) != 0) {
-		SkMacParity(pAC, IoC, MAC_1);
-	}
-
-	if ((HwStatus & IS_M2_PAR_ERR) != 0) {
-		SkMacParity(pAC, IoC, MAC_2);
-	}
-
-	if ((HwStatus & IS_R1_PAR_ERR) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
-
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((HwStatus & IS_R2_PAR_ERR) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
-
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-}	/* SkGeHwErr */
-
-
-/******************************************************************************
- *
- *	SkGeSirqIsr() - Special Interrupt Service Routine
- *
- * Description: handles all non data transfer specific interrupts (slow path)
- *
- * Returns: N/A
- */
-void SkGeSirqIsr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-SK_U32	Istatus)	/* Interrupt status word */
-{
-	SK_EVPARA	Para;
-	SK_U32		RegVal32;	/* Read register value */
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U16 		PhyInt;
-	int			i;
-
-	if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
-		/* read the HW Error Interrupt source */
-		SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-		
-		SkGeHwErr(pAC, IoC, RegVal32);
-	}
-
-	/*
-	 * Packet Timeout interrupts
-	 */
-	/* Check whether MACs are correctly initialized */
-	if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
-		pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
-		/* MAC 1 was not initialized but Packet timeout occured */
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
-			SKERR_SIRQ_E004MSG);
-	}
-
-	if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
-	    pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
-		/* MAC 2 was not initialized but Packet timeout occured */
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
-			SKERR_SIRQ_E005MSG);
-	}
-
-	if ((Istatus & IS_PA_TO_RX1) != 0) {
-		/* Means network is filling us up */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
-			SKERR_SIRQ_E002MSG);
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
-	}
-
-	if ((Istatus & IS_PA_TO_RX2) != 0) {
-		/* Means network is filling us up */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
-			SKERR_SIRQ_E003MSG);
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
-	}
-
-	if ((Istatus & IS_PA_TO_TX1) != 0) {
-		
-		pPrt = &pAC->GIni.GP[0];
-
-		/* May be a normal situation in a server with a slow network */
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
-
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/*
-			 * workaround: if in half duplex mode, check for Tx hangup.
-			 * Read number of TX'ed bytes, wait for 10 ms, then compare
-			 * the number with current value. If nothing changed, we assume
-			 * that Tx is hanging and do a FIFO flush (see event routine).
-			 */
-			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
-				!pPrt->HalfDupTimerActive) {
-				/*
-				 * many more pack. arb. timeouts may come in between,
-				 * we ignore those
-				 */
-				pPrt->HalfDupTimerActive = SK_TRUE;
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, 0);
-
-				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
-
-				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
-
-				pPrt->LastOctets += RegVal32;
-				
-				Para.Para32[0] = 0;
-				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
-					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
-			}
-		}
-#endif /* GENESIS */
-	}
-
-	if ((Istatus & IS_PA_TO_TX2) != 0) {
-		
-		pPrt = &pAC->GIni.GP[1];
-
-		/* May be a normal situation in a server with a slow network */
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
-
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/* workaround: see above */
-			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
-				!pPrt->HalfDupTimerActive) {
-				pPrt->HalfDupTimerActive = SK_TRUE;
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, 1);
-
-				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
-
-				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
-
-				pPrt->LastOctets += RegVal32;
-				
-				Para.Para32[0] = 1;
-				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
-					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
-			}
-		}
-#endif /* GENESIS */
-	}
-
-	/* Check interrupts of the particular queues */
-	if ((Istatus & IS_R1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
-			SKERR_SIRQ_E006MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_R2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
-			SKERR_SIRQ_E007MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XS1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
-			SKERR_SIRQ_E008MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XA1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
-			SKERR_SIRQ_E009MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XS2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
-			SKERR_SIRQ_E010MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XA2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
-			SKERR_SIRQ_E011MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	/* External reg interrupt */
-	if ((Istatus & IS_EXT_REG) != 0) {
-		/* Test IRQs from PHY */
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-			
-			pPrt = &pAC->GIni.GP[i];
-			
-			if (pPrt->PState == SK_PRT_RESET) {
-				continue;
-			}
-			
-#ifdef GENESIS
-			if (pAC->GIni.GIGenesis) {
-				
-				switch (pPrt->PhyType) {
-				
-				case SK_PHY_XMAC:
-					break;
-				
-				case SK_PHY_BCOM:
-					SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
-	
-					if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
-						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-							("Port %d Bcom Int: 0x%04X\n",
-							i, PhyInt));
-						SkPhyIsrBcom(pAC, IoC, i, PhyInt);
-					}
-					break;
-#ifdef OTHER_PHY
-				case SK_PHY_LONE:
-					SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
-					
-					if ((PhyInt & PHY_L_DEF_MSK) != 0) {
-						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-							("Port %d Lone Int: %x\n",
-							i, PhyInt));
-						SkPhyIsrLone(pAC, IoC, i, PhyInt);
-					}
-					break;
-#endif /* OTHER_PHY */
-				}
-			}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-			if (pAC->GIni.GIYukon) {
-				/* Read PHY Interrupt Status */
-				SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
-
-				if ((PhyInt & PHY_M_DEF_MSK) != 0) {
-					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-						("Port %d Marv Int: 0x%04X\n",
-						i, PhyInt));
-					SkPhyIsrGmac(pAC, IoC, i, PhyInt);
-				}
-			}
-#endif /* YUKON */
-		}
-	}
-
-	/* I2C Ready interrupt */
-	if ((Istatus & IS_I2C_READY) != 0) {
-#ifdef SK_SLIM
-        SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-#else		
-		SkI2cIsr(pAC, IoC);
-#endif		
-	}
-
-	/* SW forced interrupt */
-	if ((Istatus & IS_IRQ_SW) != 0) {
-		/* clear the software IRQ */
-		SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
-	}
-
-	if ((Istatus & IS_LNK_SYNC_M1) != 0) {
-		/*
-		 * We do NOT need the Link Sync interrupt, because it shows
-		 * us only a link going down.
-		 */
-		/* clear interrupt */
-		SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
-	}
-
-	/* Check MAC after link sync counter */
-	if ((Istatus & IS_MAC1) != 0) {
-		/* IRQ from MAC 1 */
-		SkMacIrq(pAC, IoC, MAC_1);
-	}
-
-	if ((Istatus & IS_LNK_SYNC_M2) != 0) {
-		/*
-		 * We do NOT need the Link Sync interrupt, because it shows
-		 * us only a link going down.
-		 */
-		/* clear interrupt */
-		SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
-	}
-
-	/* Check MAC after link sync counter */
-	if ((Istatus & IS_MAC2) != 0) {
-		/* IRQ from MAC 2 */
-		SkMacIrq(pAC, IoC, MAC_2);
-	}
-
-	/* Timer interrupt (served last) */
-	if ((Istatus & IS_TIMINT) != 0) {
-		/* check for HW Errors */
-		if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
-			/* read the HW Error Interrupt source */
-			SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-
-			SkGeHwErr(pAC, IoC, RegVal32);
-		}
-
-		SkHwtIsr(pAC, IoC);
-	}
-
-}	/* SkGeSirqIsr */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- */
-static int SkGePortCheckShorts(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port)		/* Which port should be checked */
-{
-	SK_U32		Shorts;			/* Short Event Counter */
-	SK_U32		CheckShorts;	/* Check value for Short Event Counter */
-	SK_U64		RxCts;			/* Rx Counter (packets on network) */
-	SK_U32		RxTmp;			/* Rx temp. Counter */
-	SK_U32		FcsErrCts;		/* FCS Error Counter */
-	SK_GEPORT	*pPrt;			/* GIni Port struct pointer */
-	int			Rtv;			/* Return value */
-	int			i;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Default: no action */
-	Rtv = SK_HW_PS_NONE;
-
-	(void)SkXmUpdateStats(pAC, IoC, Port);
-
-	/* Extra precaution: check for short Event counter */
-	(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
-
-	/*
-	 * Read Rx counters (packets seen on the network and not necessarily
-	 * really received.
-	 */
-	RxCts = 0;
-
-	for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
-		
-		(void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
-		
-		RxCts += (SK_U64)RxTmp;
-	}
-
-	/* On default: check shorts against zero */
-	CheckShorts = 0;
-
-	/* Extra precaution on active links */
-	if (pPrt->PHWLinkUp) {
-		/* Reset Link Restart counter */
-		pPrt->PLinkResCt = 0;
-		pPrt->PAutoNegTOCt = 0;
-
-		/* If link is up check for 2 */
-		CheckShorts = 2;
-
-		(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
-		
-		if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-		    pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
-		    (pPrt->PLinkMode == SK_LMODE_HALF ||
-			 pPrt->PLinkMode == SK_LMODE_FULL)) {
-			/*
-			 * This is autosensing and we are in the fallback
-			 * manual full/half duplex mode.
-			 */
-			if (RxCts == pPrt->PPrevRx) {
-				/* Nothing received, restart link */
-				pPrt->PPrevFcs = FcsErrCts;
-				pPrt->PPrevShorts = Shorts;
-				
-				return(SK_HW_PS_RESTART);
-			}
-			else {
-				pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
-			}
-		}
-
-		if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
-		    (!(FcsErrCts - pPrt->PPrevFcs))) {
-			/*
-			 * Note: The compare with zero above has to be done the way shown,
-			 * otherwise the Linux driver will have a problem.
-			 */
-			/*
-			 * We received a bunch of frames or no CRC error occured on the
-			 * network -> ok.
-			 */
-			pPrt->PPrevRx = RxCts;
-			pPrt->PPrevFcs = FcsErrCts;
-			pPrt->PPrevShorts = Shorts;
-
-			return(SK_HW_PS_NONE);
-		}
-
-		pPrt->PPrevFcs = FcsErrCts;
-	}
-
-
-	if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Short Event Count Restart Port %d \n", Port));
-		Rtv = SK_HW_PS_RESTART;
-	}
-
-	pPrt->PPrevShorts = Shorts;
-	pPrt->PPrevRx = RxCts;
-
-	return(Rtv);
-}	/* SkGePortCheckShorts */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUp() - Check if the link is up
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUp(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port)		/* Which port should be checked */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_BOOL		AutoNeg;	/* Is Auto-negotiation used ? */
-	int			Rtv;		/* Return value */
-
-	Rtv = SK_HW_PS_NONE;
-	
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		AutoNeg = SK_FALSE;
-	}
-	else {
-		AutoNeg = SK_TRUE;
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		switch (pPrt->PhyType) {
-		
-		case SK_PHY_XMAC:
-			Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
-			break;
-		case SK_PHY_BCOM:
-			Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
-			break;
-		case SK_PHY_NAT:
-			Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
-			break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
-	}
-#endif /* YUKON */
-
-	return(Rtv);	
-}	/* SkGePortCheckUp */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpXmac(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_U32		Shorts;		/* Short Event Counter */
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U32		GpReg;		/* General Purpose register value */
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		IsrcSum;	/* Interrupt source register sum */
-	SK_U16		LpAb;		/* Link Partner Ability */
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		ExtStat;	/* Extended Status Register */
-	SK_U8		NextMode;	/* Next AutoSensing Mode */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			return(SK_HW_PS_NONE);
-		}
-		else {
-			return(SkGePortCheckShorts(pAC, IoC, Port));
-		}
-	}
-
-	IsrcSum = pPrt->PIsave;
-	pPrt->PIsave = 0;
-
-	/* Now wait for each port's link */
-	if (pPrt->PLinkBroken) {
-		/* Link was broken */
-		XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
-
-		if ((GpReg & XM_GP_INP_ASS) == 0) {
-			/* The Link is in sync */
-			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-			IsrcSum |= Isrc;
-			SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-			
-			if ((Isrc & XM_IS_INP_ASS) == 0) {
-				/* It has been in sync since last time */
-				/* Restart the PORT */
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Link in sync Restart Port %d\n", Port));
-
-				(void)SkXmUpdateStats(pAC, IoC, Port);
-
-				/* We now need to reinitialize the PrevShorts counter */
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
-				pPrt->PPrevShorts = Shorts;
-
-				pPrt->PLinkBroken = SK_FALSE;
-
-				/*
-				 * Link Restart Workaround:
-				 *  it may be possible that the other Link side
-				 *  restarts its link as well an we detect
-				 *  another LinkBroken. To prevent this
-				 *  happening we check for a maximum number
-				 *  of consecutive restart. If those happens,
-				 *  we do NOT restart the active link and
-				 *  check whether the link is now o.k.
-				 */
-				pPrt->PLinkResCt++;
-				
-				pPrt->PAutoNegTimeOut = 0;
-
-				if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
-					return(SK_HW_PS_RESTART);
-				}
-
-				pPrt->PLinkResCt = 0;
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
-			}
-			else {
-				pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
-
-				/* Do nothing more if link is broken */
-				return(SK_HW_PS_NONE);
-			}
-		}
-		else {
-			/* Do nothing more if link is broken */
-			return(SK_HW_PS_NONE);
-		}
-
-	}
-	else {
-		/* Link was not broken, check if it is */
-		XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-		IsrcSum |= Isrc;
-		if ((Isrc & XM_IS_INP_ASS) != 0) {
-			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-			IsrcSum |= Isrc;
-			if ((Isrc & XM_IS_INP_ASS) != 0) {
-				XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-				IsrcSum |= Isrc;
-				if ((Isrc & XM_IS_INP_ASS) != 0) {
-					pPrt->PLinkBroken = SK_TRUE;
-					/* Re-Init Link partner Autoneg flag */
-					pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
-					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-						("Link broken Port %d\n", Port));
-
-					/* Cable removed-> reinit sense mode */
-					SkHWInitDefSense(pAC, IoC, Port);
-
-					return(SK_HW_PS_RESTART);
-				}
-			}
-		}
-		else {
-			SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
-			
-			if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
-				return(SK_HW_PS_RESTART);
-			}
-		}
-	}
-
-	/*
-	 * here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-	XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
-	XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-	IsrcSum |= Isrc;
-
-	SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-	
-	if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
-		if ((GpReg & XM_GP_INP_ASS) == 0) {
-			/* Save Auto-negotiation Done interrupt only if link is in sync */
-			pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
-		}
-#ifdef DEBUG
-		if ((pPrt->PIsave & XM_IS_AND) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("AutoNeg done rescheduled Port %d\n", Port));
-		}
-#endif /* DEBUG */
-		return(SK_HW_PS_NONE);
-	}
-
-	if (AutoNeg) {
-		if ((IsrcSum & XM_IS_AND) != 0) {
-			SkHWLinkUp(pAC, IoC, Port);
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			if (Done != SK_AND_OK) {
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
-					 Port, LpAb, ResAb));
-					
-				/* Try next possible mode */
-				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
-				SkHWLinkDown(pAC, IoC, Port);
-				if (Done == SK_AND_DUP_CAP) {
-					/* GoTo next mode */
-					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
-				}
-
-				return(SK_HW_PS_RESTART);
-			}
-			/*
-			 * Dummy Read extended status to prevent extra link down/ups
-			 * (clear Page Received bit if set)
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
-			
-			return(SK_HW_PS_LINK);
-		}
-		
-		/* AutoNeg not done, but HW link is up. Check for timeouts */
-		pPrt->PAutoNegTimeOut++;
-		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
-			/* Increase the Timeout counter */
-			pPrt->PAutoNegTOCt++;
-
-			/* Timeout occured */
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-				("AutoNeg timeout Port %d\n", Port));
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
-				/* Set Link manually up */
-				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Set manual full duplex Port %d\n", Port));
-			}
-
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
-				pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
-				/*
-				 * This is rather complicated.
-				 * we need to check here whether the LIPA_AUTO
-				 * we saw before is false alert. We saw at one
-				 * switch ( SR8800) that on boot time it sends
-				 * just one auto-neg packet and does no further
-				 * auto-negotiation.
-				 * Solution: we restart the autosensing after
-				 * a few timeouts.
-				 */
-				pPrt->PAutoNegTOCt = 0;
-				pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
-				SkHWInitDefSense(pAC, IoC, Port);
-			}
-
-			/* Do the restart */
-			return(SK_HW_PS_RESTART);
-		}
-	}
-	else {
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		/*
-		 * Link sync (GP) and so assume a good connection. But if not received
-		 * a bunch of frames received in a time slot (maybe broken tx cable)
-		 * the port is restart.
-		 */
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpXmac */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpBcom(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		PhyStat;	/* Phy Status Register */
-	SK_U16		ResAb;		/* Master/Slave resolution */
-	SK_U16		Ctrl;		/* Broadcom control flags */
-#ifdef DEBUG
-	SK_U16		LpAb;
-	SK_U16		ExtStat;
-#endif /* DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Check for No HCD Link events (#10523) */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
-
-#ifdef xDEBUG
-	if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) ==
-		(PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
-
-		SK_U32	Stat1, Stat2, Stat3;
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"CheckUp1 - Stat: %x, Mask: %x",
-			(void *)Isrc,
-			(void *)Stat1);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"Ctrl/Stat: %x, AN Adv/LP: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-	}
-#endif /* DEBUG */
-
-	if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
-		/*
-		 * Workaround BCom Errata:
-		 *	enable and disable loopback mode if "NO HCD" occurs.
-		 */
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
-			(SK_U16)(Ctrl | PHY_CT_LOOP));
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
-			(SK_U16)(Ctrl & ~PHY_CT_LOOP));
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("No HCD Link event, Port %d\n", Port));
-#ifdef xDEBUG
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"No HCD link event, port %d.",
-			(void *)Port,
-			(void *)NULL);
-#endif /* DEBUG */
-	}
-
-	/* Not obsolete: link status bit is latched to 0 and autoclearing! */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-#ifdef xDEBUG
-	{
-		SK_U32	Stat1, Stat2, Stat3;
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"CheckUp1a - Stat: %x, Mask: %x",
-			(void *)Isrc,
-			(void *)Stat1);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-		Stat1 = Stat1 << 16 | PhyStat;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"Ctrl/Stat: %x, AN Adv/LP: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-		Stat2 = Stat2 << 16 | ResAb;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-	}
-#endif /* DEBUG */
-
-	/*
-	 * Here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault port %d\n", Port));
-		
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		
-		return(SK_HW_PS_RESTART);
-	}
-
-	if ((PhyStat & PHY_ST_LSYNC) == 0) {
-		return(SK_HW_PS_NONE);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Port %d, ResAb: 0x%04X\n", Port, ResAb));
-
-	if (AutoNeg) {
-		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-			
-			SkHWLinkUp(pAC, IoC, Port);
-			
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			
-			if (Done != SK_AND_OK) {
-#ifdef DEBUG
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
-					Port, LpAb, ExtStat));
-#endif /* DEBUG */
-				return(SK_HW_PS_RESTART);
-			}
-			else {
-#ifdef xDEBUG
-				/* Dummy read ISR to prevent extra link downs/ups */
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
-				if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
-					CMSMPrintString(
-						pAC->pConfigTable,
-						MSG_TYPE_RUNTIME_INFO,
-						"CheckUp2 - Stat: %x",
-						(void *)ExtStat,
-						(void *)NULL);
-				}
-#endif /* DEBUG */
-				return(SK_HW_PS_LINK);
-			}
-		}
-	}
-	else {	/* !AutoNeg */
-		/* Link is up and we don't need more. */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-#ifdef xDEBUG
-		/* Dummy read ISR to prevent extra link downs/ups */
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
-		if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
-			CMSMPrintString(
-				pAC->pConfigTable,
-				MSG_TYPE_RUNTIME_INFO,
-				"CheckUp3 - Stat: %x",
-				(void *)ExtStat,
-				(void *)NULL);
-		}
-#endif /* DEBUG */
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpGmac(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		PhyIsrc;	/* PHY Interrupt source */
-	SK_U16		PhyStat;	/* PPY Status */
-	SK_U16		PhySpecStat;/* PHY Specific Status */
-	SK_U16		ResAb;		/* Master/Slave resolution */
-	SK_EVPARA	Para;
-#ifdef DEBUG
-	SK_U16		Word;		/* I/O helper */
-#endif /* DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-	/* Read PHY Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
-	/* Read PHY Interrupt Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
-
-	if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault port %d\n", Port));
-		
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		
-		return(SK_HW_PS_RESTART);
-	}
-
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
-
-#ifdef DEBUG
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
-
-	if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
-		(PhySpecStat & PHY_M_PS_PAGE_REC) != 0)  {
-		/* Read PHY Next Page Link Partner */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Page Received, NextPage: 0x%04X\n", Word));
-	}
-#endif /* DEBUG */
-
-	if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
-		return(SK_HW_PS_NONE);
-	}
-	
-	if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
-		(PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
-		/* Downshift detected */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
-		
-		Para.Para64 = Port;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-	
-	pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
-	
-	if (AutoNeg) {
-		/* Auto-Negotiation Over ? */
-		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-			
-			SkHWLinkUp(pAC, IoC, Port);
-			
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			
-			if (Done != SK_AND_OK) {
-				return(SK_HW_PS_RESTART);
-			}
-			
-			return(SK_HW_PS_LINK);
-		}
-	}
-	else {	/* !AutoNeg */
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync, Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpLone(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		LpAb;		/* Link Partner Ability */
-	SK_U16		ExtStat;	/* Extended Status Register */
-	SK_U16		PhyStat;	/* Phy Status Register */
-	SK_U16		StatSum;
-	SK_U8		NextMode;	/* Next AutoSensing Mode */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-	StatSum = pPrt->PIsave;
-	pPrt->PIsave = 0;
-
-	/*
-	 * here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
-	StatSum |= PhyStat;
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	if ((PhyStat & PHY_ST_LSYNC) == 0) {
-		/* Save Auto-negotiation Done bit */
-		pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
-#ifdef DEBUG
-		if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("AutoNeg done rescheduled Port %d\n", Port));
-		}
-#endif /* DEBUG */
-		return(SK_HW_PS_NONE);
-	}
-
-	if (AutoNeg) {
-		if ((StatSum & PHY_ST_AN_OVER) != 0) {
-			SkHWLinkUp(pAC, IoC, Port);
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			if (Done != SK_AND_OK) {
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
-					 Port, LpAb, ExtStat));
-					
-				/* Try next possible mode */
-				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
-				SkHWLinkDown(pAC, IoC, Port);
-				if (Done == SK_AND_DUP_CAP) {
-					/* GoTo next mode */
-					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
-				}
-
-				return(SK_HW_PS_RESTART);
-
-			}
-			else {
-				/*
-				 * Dummy Read interrupt status to prevent
-				 * extra link down/ups
-				 */
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
-				return(SK_HW_PS_LINK);
-			}
-		}
-		
-		/* AutoNeg not done, but HW link is up. Check for timeouts */
-		pPrt->PAutoNegTimeOut++;
-		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
-			/* Timeout occured */
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-				("AutoNeg timeout Port %d\n", Port));
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
-				/* Set Link manually up */
-				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Set manual full duplex Port %d\n", Port));
-			}
-
-			/* Do the restart */
-			return(SK_HW_PS_RESTART);
-		}
-	}
-	else {
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Dummy Read interrupt status to prevent
-		 * extra link down/ups
-		 */
-		SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpLone */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpNat() - Check if the link is up on National PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpNat(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	/* todo: National */
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkGeSirqEvent() - Event Service Routine
- *
- * Description:
- *
- * Notes:
- */
-int	SkGeSirqEvent(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-SK_U32		Event,		/* Module specific Event */
-SK_EVPARA	Para)		/* Event specific Parameter */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U32		Port;
-	SK_U32		Val32;
-	int			PortStat;
-	SK_U8		Val8;
-#ifdef GENESIS
-	SK_U64		Octets;
-#endif /* GENESIS */
-
-	Port = Para.Para32[0];
-	pPrt = &pAC->GIni.GP[Port];
-
-	switch (Event) {
-	case SK_HWEV_WATIM:
-		if (pPrt->PState == SK_PRT_RESET) {
-		
-			PortStat = SK_HW_PS_NONE;
-		}
-		else {
-			/* Check whether port came up */
-			PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
-		}
-
-		switch (PortStat) {
-		case SK_HW_PS_RESTART:
-			if (pPrt->PHWLinkUp) {
-				/* Set Link to down */
-				SkHWLinkDown(pAC, IoC, (int)Port);
-
-				/*
-				 * Signal directly to RLMT to ensure correct
-				 * sequence of SWITCH and RESET event.
-				 */
-				SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-			}
-
-			/* Restart needed */
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-			break;
-
-		case SK_HW_PS_LINK:
-			/* Signal to RLMT */
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
-			break;
-		}
-		
-		/* Start again the check Timer */
-		if (pPrt->PHWLinkUp) {
-			Val32 = SK_WA_ACT_TIME;
-		}
-		else {
-			Val32 = SK_WA_INA_TIME;
-		}
-
-		/* Todo: still needed for non-XMAC PHYs??? */
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-		break;
-
-	case SK_HWEV_PORT_START:
-		if (pPrt->PHWLinkUp) {
-			/*
-			 * Signal directly to RLMT to ensure correct
-			 * sequence of SWITCH and RESET event.
-			 */
-			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-		}
-
-		SkHWLinkDown(pAC, IoC, (int)Port);
-
-		/* Schedule Port RESET */
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-		break;
-
-	case SK_HWEV_PORT_STOP:
-		if (pPrt->PHWLinkUp) {
-			/*
-			 * Signal directly to RLMT to ensure correct
-			 * sequence of SWITCH and RESET event.
-			 */
-			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-		}
-
-		/* Stop Workaround Timer */
-		SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
-
-		SkHWLinkDown(pAC, IoC, (int)Port);
-		break;
-
-	case SK_HWEV_UPDATE_STAT:
-		/* We do NOT need to update any statistics */
-		break;
-
-	case SK_HWEV_CLEAR_STAT:
-		/* We do NOT need to clear any statistics */
-		for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
-			pPrt->PPrevRx = 0;
-			pPrt->PPrevFcs = 0;
-			pPrt->PPrevShorts = 0;
-		}
-		break;
-
-	case SK_HWEV_SET_LMODE:
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PLinkModeConf != Val8) {
-			/* Set New link mode */
-			pPrt->PLinkModeConf = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_FLOWMODE:
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PFlowCtrlMode != Val8) {
-			/* Set New Flow Control mode */
-			pPrt->PFlowCtrlMode = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_ROLE:
-		/* not possible for fiber */
-		if (!pAC->GIni.GICopperType) {
-			break;
-		}
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PMSMode != Val8) {
-			/* Set New Role (Master/Slave) mode */
-			pPrt->PMSMode = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_SPEED:
-		if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-			break;
-		}
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PLinkSpeed != Val8) {
-			/* Set New Speed parameter */
-			pPrt->PLinkSpeed = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-#ifdef GENESIS
-	case SK_HWEV_HALFDUP_CHK:
-		if (pAC->GIni.GIGenesis) {
-			/*
-			 * half duplex hangup workaround.
-			 * See packet arbiter timeout interrupt for description
-			 */
-			pPrt->HalfDupTimerActive = SK_FALSE;
-			if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, Port);
-
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
-
-				Octets = (SK_U64)Val32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
-
-				Octets += Val32;
-				
-				if (pPrt->LastOctets == Octets) {
-					/* Tx hanging, a FIFO flush restarts it */
-					SkMacFlushTxFifo(pAC, IoC, Port);
-				}
-			}
-		}
-		break;
-#endif /* GENESIS */
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
-		break;
-	}
-
-	return(0);
-}	/* SkGeSirqEvent */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkPhyIsrBcom() - PHY interrupt service routine
- *
- * Description: handles all interrupts from BCom PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrBcom(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-int			Port,		/* Port Num = PHY Num */
-SK_U16		IStatus)	/* Interrupt Status */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_EVPARA	Para;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((IStatus & PHY_B_IS_PSE) != 0) {
-		/* Incorrectable pair swap error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
-			SKERR_SIRQ_E022MSG);
-	}
-	
-	if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
-
-		SkHWLinkDown(pAC, IoC, Port);
-
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-	}
-
-}	/* SkPhyIsrBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkPhyIsrGmac() - PHY interrupt service routine
- *
- * Description: handles all interrupts from Marvell PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrGmac(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-int			Port,		/* Port Num = PHY Num */
-SK_U16		IStatus)	/* Interrupt Status */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_EVPARA	Para;
-	SK_U16		Word;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
-
-		SkHWLinkDown(pAC, IoC, Port);
-
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNeg.Adv: 0x%04X\n", Word));
-		
-		/* Set Auto-negotiation advertisement */
-		if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
-			/* restore Asymmetric Pause bit */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
-				(SK_U16)(Word | PHY_M_AN_ASP));
-		}
-		
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-	
-	if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
-		/* Auto-Negotiation Error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
-	}
-	
-	if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
-		/* FIFO Overflow/Underrun Error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
-	}
-	
-}	/* SkPhyIsrGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkPhyIsrLone() - PHY interrupt service routine
- *
- * Description: handles all interrupts from LONE PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrLone(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* Io Context */
-int		Port,		/* Port Num = PHY Num */
-SK_U16	IStatus)	/* Interrupt Status */
-{
-	SK_EVPARA	Para;
-
-	if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
-		
-		SkHWLinkDown(pAC, IoC, Port);
-
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-}	/* SkPhyIsrLone */
-#endif /* OTHER_PHY */
-
-/* End of File */
diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c
deleted file mode 100644
index 79bf57c..0000000
--- a/drivers/net/sk98lin/ski2c.c
+++ /dev/null
@@ -1,1296 +0,0 @@
-/******************************************************************************
- *
- * Name:	ski2c.c
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.59 $
- * Date:	$Date: 2003/10/20 09:07:25 $
- * Purpose:	Functions to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	I2C Protocol
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	I2C protocol implementation.
-
-	General Description:
-
-	The I2C protocol is used for the temperature sensors and for
-	the serial EEPROM which hold the configuration.
-
-	This file covers functions that allow to read write and do
-	some bulk requests a specified I2C address.
-
-	The Genesis has 2 I2C buses. One for the EEPROM which holds
-	the VPD Data and one for temperature and voltage sensor.
-	The following picture shows the I2C buses, I2C devices and
-	their control registers.
-
-	Note: The VPD functions are in skvpd.c
-.
-.	PCI Config I2C Bus for VPD Data:
-.
-.		      +------------+
-.		      | VPD EEPROM |
-.		      +------------+
-.			     |
-.			     | <-- I2C
-.			     |
-.		 +-----------+-----------+
-.		 |			 |
-.	+-----------------+	+-----------------+
-.	| PCI_VPD_ADR_REG |	| PCI_VPD_DAT_REG |
-.	+-----------------+	+-----------------+
-.
-.
-.	I2C Bus for LM80 sensor:
-.
-.			+-----------------+
-.			| Temperature and |
-.			| Voltage Sensor  |
-.			| 	LM80	  |
-.			+-----------------+
-.				|
-.				|
-.			I2C --> |
-.				|
-.			     +----+
-.	     +-------------->| OR |<--+
-.	     |		     +----+   |
-.     +------+------+		      |
-.     |		    |		      |
-. +--------+	+--------+	+----------+
-. | B2_I2C |	| B2_I2C |	|  B2_I2C  |
-. | _CTRL  |	| _DATA  |	|   _SW    |
-. +--------+	+--------+	+----------+
-.
-	The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
-	and B2_I2C_DATA registers.
-	For driver software it is recommended to use the I2C control and
-	data register, because I2C bus timing is done by the ASIC and
-	an interrupt may be received when the I2C request is completed.
-
-	Clock Rate Timing:			MIN	MAX	generated by
-		VPD EEPROM:			50 kHz	100 kHz		HW
-		LM80 over I2C Ctrl/Data reg.	50 kHz	100 kHz		HW
-		LM80 over B2_I2C_SW register	0	400 kHz		SW
-
-	Note:	The clock generated by the hardware is dependend on the
-		PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
-		clock is 50 kHz.
- */
-intro()
-{}
-#endif
-
-#ifdef SK_DIAG
-/*
- * I2C Fast Mode timing values used by the LM80.
- * If new devices are added to the I2C bus the timing values have to be checked.
- */
-#ifndef I2C_SLOW_TIMING
-#define	T_CLK_LOW			1300L	/* clock low time in ns */
-#define	T_CLK_HIGH		 	 600L	/* clock high time in ns */
-#define T_DATA_IN_SETUP		 100L	/* data in Set-up Time */
-#define T_START_HOLD		 600L	/* start condition hold time */
-#define T_START_SETUP		 600L	/* start condition Set-up time */
-#define	T_STOP_SETUP		 600L	/* stop condition Set-up time */
-#define T_BUS_IDLE			1300L	/* time the bus must free after Tx */
-#define	T_CLK_2_DATA_OUT	 900L	/* max. clock low to data output valid */
-#else	/* I2C_SLOW_TIMING */
-/* I2C Standard Mode Timing */
-#define	T_CLK_LOW			4700L	/* clock low time in ns */
-#define	T_CLK_HIGH			4000L	/* clock high time in ns */
-#define T_DATA_IN_SETUP		 250L	/* data in Set-up Time */
-#define T_START_HOLD		4000L	/* start condition hold time */
-#define T_START_SETUP		4700L	/* start condition Set-up time */
-#define	T_STOP_SETUP		4000L	/* stop condition Set-up time */
-#define T_BUS_IDLE			4700L	/* time the bus must free after Tx */
-#endif	/* !I2C_SLOW_TIMING */
-
-#define NS2BCLK(x)	(((x)*125)/10000)
-
-/*
- * I2C Wire Operations
- *
- * About I2C_CLK_LOW():
- *
- * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
- * clock to low, to prevent the ASIC and the I2C data client from driving the
- * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
- * send an 'ACK'). See also Concentrator Bugreport No. 10192.
- */
-#define I2C_DATA_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA)
-#define	I2C_DATA_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA)
-#define	I2C_DATA_OUT(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
-#define	I2C_DATA_IN(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
-#define	I2C_CLK_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_CLK)
-#define	I2C_CLK_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
-#define	I2C_START_COND(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK)
-
-#define NS2CLKT(x)	((x*125L)/10000)
-
-/*--------------- I2C Interface Register Functions --------------- */
-
-/*
- * sending one bit
- */
-void SkI2cSndBit(
-SK_IOC	IoC,	/* I/O Context */
-SK_U8	Bit)	/* Bit to send */
-{
-	I2C_DATA_OUT(IoC);
-	if (Bit) {
-		I2C_DATA_HIGH(IoC);
-	}
-	else {
-		I2C_DATA_LOW(IoC);
-	}
-	SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
-	I2C_CLK_HIGH(IoC);
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
-	I2C_CLK_LOW(IoC);
-}	/* SkI2cSndBit*/
-
-
-/*
- * Signal a start to the I2C Bus.
- *
- * A start is signaled when data goes to low in a high clock cycle.
- *
- * Ends with Clock Low.
- *
- * Status: not tested
- */
-void SkI2cStart(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/* Init data and Clock to output lines */
-	/* Set Data high */
-	I2C_DATA_OUT(IoC);
-	I2C_DATA_HIGH(IoC);
-	/* Set Clock high */
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
-
-	/* Set Data Low */
-	I2C_DATA_LOW(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
-
-	/* Clock low without Data to Input */
-	I2C_START_COND(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
-}	/* SkI2cStart */
-
-
-void SkI2cStop(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/* Init data and Clock to output lines */
-	/* Set Data low */
-	I2C_DATA_OUT(IoC);
-	I2C_DATA_LOW(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
-	/* Set Clock high */
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
-
-	/*
-	 * Set Data High:	Do it by setting the Data Line to Input.
-	 *			Because of a pull up resistor the Data Line
-	 *			floods to high.
-	 */
-	I2C_DATA_IN(IoC);
-
-	/*
-	 *	When I2C activity is stopped
-	 *	 o	DATA should be set to input and
-	 *	 o	CLOCK should be set to high!
-	 */
-	SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
-}	/* SkI2cStop */
-
-
-/*
- * Receive just one bit via the I2C bus.
- *
- * Note:	Clock must be set to LOW before calling this function.
- *
- * Returns The received bit.
- */
-int SkI2cRcvBit(
-SK_IOC	IoC)	/* I/O Context */
-{
-	int	Bit;
-	SK_U8	I2cSwCtrl;
-
-	/* Init data as input line */
-	I2C_DATA_IN(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
-
-	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-	
-	Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
-
-	I2C_CLK_LOW(IoC);
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
-
-	return(Bit);
-}	/* SkI2cRcvBit */
-
-
-/*
- * Receive an ACK.
- *
- * returns	0 If acknowledged
- *		1 in case of an error
- */
-int SkI2cRcvAck(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	return(SkI2cRcvBit(IoC) != 0);
-}	/* SkI2cRcvAck */
-
-
-/*
- * Send an NACK.
- */
-void SkI2cSndNAck(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	SkI2cSndBit(IoC, 1);
-}	/* SkI2cSndNAck */
-
-
-/*
- * Send an ACK.
- */
-void SkI2cSndAck(
-SK_IOC IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	SkI2cSndBit(IoC, 0);
-}	/* SkI2cSndAck */
-
-
-/*
- * Send one byte to the I2C device and wait for ACK.
- *
- * Return acknowleged status.
- */
-int SkI2cSndByte(
-SK_IOC	IoC,	/* I/O Context */
-int		Byte)	/* byte to send */
-{
-	int	i;
-
-	for (i = 0; i < 8; i++) {
-		if (Byte & (1<<(7-i))) {
-			SkI2cSndBit(IoC, 1);
-		}
-		else {
-			SkI2cSndBit(IoC, 0);
-		}
-	}
-
-	return(SkI2cRcvAck(IoC));
-}	/* SkI2cSndByte */
-
-
-/*
- * Receive one byte and ack it.
- *
- * Return byte.
- */
-int SkI2cRcvByte(
-SK_IOC	IoC,	/* I/O Context */
-int		Last)	/* Last Byte Flag */
-{
-	int	i;
-	int	Byte = 0;
-
-	for (i = 0; i < 8; i++) {
-		Byte <<= 1;
-		Byte |= SkI2cRcvBit(IoC);
-	}
-
-	if (Last) {
-		SkI2cSndNAck(IoC);
-	}
-	else {
-		SkI2cSndAck(IoC);
-	}
-
-	return(Byte);
-}	/* SkI2cRcvByte */
-
-
-/*
- * Start dialog and send device address
- *
- * Return 0 if acknowleged, 1 in case of an error
- */
-int	SkI2cSndDev(
-SK_IOC	IoC,	/* I/O Context */
-int		Addr,	/* Device Address */
-int		Rw)		/* Read / Write Flag */
-{
-	SkI2cStart(IoC);
-	Rw = ~Rw;
-	Rw &= I2C_WRITE;
-	return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
-}	/* SkI2cSndDev */
-
-#endif /* SK_DIAG */
-
-/*----------------- I2C CTRL Register Functions ----------*/
-
-/*
- * waits for a completion of an I2C transfer
- *
- * returns	0:	success, transfer completes
- *			1:	error,	 transfer does not complete, I2C transfer
- *						 killed, wait loop terminated.
- */
-static int	SkI2cWait(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-int		Event)	/* complete event to wait for (I2C_READ or I2C_WRITE) */
-{
-	SK_U64	StartTime;
-	SK_U64	CurrentTime;
-	SK_U32	I2cCtrl;
-
-	StartTime = SkOsGetTime(pAC);
-	
-	do {
-		CurrentTime = SkOsGetTime(pAC);
-
-		if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
-			
-			SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
-#endif /* !SK_DIAG */
-			return(1);
-		}
-		
-		SK_I2C_GET_CTL(IoC, &I2cCtrl);
-
-#ifdef xYUKON_DBG
-		printf("StartTime=%lu, CurrentTime=%lu\n",
-			StartTime, CurrentTime);
-		if (kbhit()) {
-			return(1);
-		}
-#endif /* YUKON_DBG */
-	
-	} while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
-
-	return(0);
-}	/* SkI2cWait */
-
-
-/*
- * waits for a completion of an I2C transfer
- *
- * Returns
- *	Nothing
- */
-void SkI2cWaitIrq(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	SK_SENSOR	*pSen;
-	SK_U64		StartTime;
-	SK_U32		IrqSrc;
-
-	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-
-	if (pSen->SenState == SK_SEN_IDLE) {
-		return;
-	}
-
-	StartTime = SkOsGetTime(pAC);
-	
-	do {
-		if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
-			
-			SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
-#endif /* !SK_DIAG */
-			return;
-		}
-		
-		SK_IN32(IoC, B0_ISRC, &IrqSrc);
-
-	} while ((IrqSrc & IS_I2C_READY) == 0);
-
-	pSen->SenState = SK_SEN_IDLE;
-	return;
-}	/* SkI2cWaitIrq */
-
-/*
- * writes a single byte or 4 bytes into the I2C device
- *
- * returns	0:	success
- *			1:	error
- */
-static int SkI2cWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	I2cData,	/* I2C Data to write */
-int		I2cDev,		/* I2C Device Address */
-int		I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int		I2cReg,		/* I2C Device Register Address */
-int		I2cBurst)	/* I2C Burst Flag */
-{
-	SK_OUT32(IoC, B2_I2C_DATA, I2cData);
-	
-	SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-	
-	return(SkI2cWait(pAC, IoC, I2C_WRITE));
-}	/* SkI2cWrite*/
-
-
-#ifdef	SK_DIAG
-/*
- * reads a single byte or 4 bytes from the I2C device
- *
- * returns	the word read
- */
-SK_U32 SkI2cRead(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		I2cDev,		/* I2C Device Address */
-int		I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int		I2cReg,		/* I2C Device Register Address */
-int		I2cBurst)	/* I2C Burst Flag */
-{
-	SK_U32	Data;
-
-	SK_OUT32(IoC, B2_I2C_DATA, 0);
-	SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-	
-	if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
-		w_print("%s\n", SKERR_I2C_E002MSG);
-	}
-	
-	SK_IN32(IoC, B2_I2C_DATA, &Data);
-	
-	return(Data);
-}	/* SkI2cRead */
-#endif /* SK_DIAG */
-
-
-/*
- * read a sensor's value
- *
- * This function reads a sensor's value from the I2C sensor chip. The sensor
- * is defined by its index into the sensors database in the struct pAC points
- * to.
- * Returns
- *		1 if the read is completed
- *		0 if the read must be continued (I2C Bus still allocated)
- */
-static int	SkI2cReadSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_SENSOR	*pSen)	/* Sensor to be read */
-{
-    if (pSen->SenRead != NULL) {
-        return((*pSen->SenRead)(pAC, IoC, pSen));
-    }
-	else {
-        return(0); /* no success */
-	}
-}	/* SkI2cReadSensor */
-
-/*
- * Do the Init state 0 initialization
- */
-static int SkI2cInit0(
-SK_AC	*pAC)	/* Adapter Context */
-{
-	int	i;
-
-	/* Begin with first sensor */
-	pAC->I2c.CurrSens = 0;
-	
-	/* Begin with timeout control for state machine */
-	pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-	
-	/* Set sensor number to zero */
-	pAC->I2c.MaxSens = 0;
-
-#ifndef SK_DIAG
-	/* Initialize Number of Dummy Reads */
-	pAC->I2c.DummyReads = SK_MAX_SENSORS;
-#endif
-
-	for (i = 0; i < SK_MAX_SENSORS; i++) {
-		pAC->I2c.SenTable[i].SenDesc = "unknown";
-		pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
-		pAC->I2c.SenTable[i].SenThreErrHigh = 0;
-		pAC->I2c.SenTable[i].SenThreErrLow = 0;
-		pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
-		pAC->I2c.SenTable[i].SenThreWarnLow = 0;
-		pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
-		pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
-		pAC->I2c.SenTable[i].SenValue = 0;
-		pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
-		pAC->I2c.SenTable[i].SenErrCts = 0;
-		pAC->I2c.SenTable[i].SenBegErrTS = 0;
-		pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
-		pAC->I2c.SenTable[i].SenRead = NULL;
-		pAC->I2c.SenTable[i].SenDev = 0;
-	}
-
-	/* Now we are "INIT data"ed */
-	pAC->I2c.InitLevel = SK_INIT_DATA;
-	return(0);
-}	/* SkI2cInit0*/
-
-
-/*
- * Do the init state 1 initialization
- *
- * initialize the following register of the LM80:
- * Configuration register:
- * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
- *
- * Interrupt Mask Register 1:
- * - all interrupts are Disabled (0xff)
- *
- * Interrupt Mask Register 2:
- * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
- *
- * Fan Divisor/RST_OUT register:
- * - Divisors set to 1 (bits 00), all others 0s.
- *
- * OS# Configuration/Temperature resolution Register:
- * - all 0s
- *
- */
-static int SkI2cInit1(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-    int i;
-    SK_U8 I2cSwCtrl;
-	SK_GEPORT *pPrt;	/* GIni Port struct pointer */
-
-	if (pAC->I2c.InitLevel != SK_INIT_DATA) {
-		/* ReInit not needed in I2C module */
-		return(0);
-	}
-
-    /* Set the Direction of I2C-Data Pin to IN */
-    SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
-    /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
-	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-
-	if ((I2cSwCtrl & I2C_DATA) == 0) {
-		/* this is a 32-Bit board */
-		pAC->GIni.GIYukon32Bit = SK_TRUE;
-        return(0);
-    }
-
-	/* Check for 64 Bit Yukon without sensors */
-	if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
-        return(0);
-    }
-
-	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
-		LM80_CFG, 0);
-	
-	/*
-	 * MaxSens has to be updated here, because PhyType is not
-	 * set when performing Init Level 0
-	 */
-    pAC->I2c.MaxSens = 5;
-	
-	pPrt = &pAC->GIni.GP[0];
-	
-	if (pAC->GIni.GIGenesis) {
-		if (pPrt->PhyType == SK_PHY_BCOM) {
-			if (pAC->GIni.GIMacsFound == 1) {
-				pAC->I2c.MaxSens += 1;
-			}
-			else {
-				pAC->I2c.MaxSens += 3;
-			}
-		}
-	}
-	else {
-		pAC->I2c.MaxSens += 3;
-	}
-	
-	for (i = 0; i < pAC->I2c.MaxSens; i++) {
-		switch (i) {
-		case 0:
-			pAC->I2c.SenTable[i].SenDesc = "Temperature";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
-			break;
-		case 1:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
-			break;
-		case 2:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
-			pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
-			break;
-		case 3:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
-			break;
-		case 4:
-			if (pAC->GIni.GIGenesis) {
-				if (pPrt->PhyType == SK_PHY_BCOM) {
-					pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
-					pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-				}
-				else {
-					pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
-					pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-				}
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
-				if (pAC->GIni.GIVauxAvail) {
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
-				}
-				else {
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
-				}
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
-			break;
-		case 5:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
-			break;
-		case 6:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
-			break;
-		case 7:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
-				pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
-				pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
-				pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
-				pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
-			}
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
-				SKERR_I2C_E001, SKERR_I2C_E001MSG);
-			break;
-		}
-
-		pAC->I2c.SenTable[i].SenValue = 0;
-		pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
-		pAC->I2c.SenTable[i].SenErrCts = 0;
-		pAC->I2c.SenTable[i].SenBegErrTS = 0;
-		pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
-		pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
-		pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
-	}
-
-#ifndef SK_DIAG
-	pAC->I2c.DummyReads = pAC->I2c.MaxSens;
-#endif /* !SK_DIAG */
-	
-	/* Clear I2C IRQ */
-	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-	
-	/* Now we are I/O initialized */
-	pAC->I2c.InitLevel = SK_INIT_IO;
-	return(0);
-}	/* SkI2cInit1 */
-
-
-/*
- * Init level 2: Start first sensor read.
- */
-static int SkI2cInit2(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	int		ReadComplete;
-	SK_SENSOR	*pSen;
-
-	if (pAC->I2c.InitLevel != SK_INIT_IO) {
-		/* ReInit not needed in I2C module */
-		/* Init0 and Init2 not permitted */
-		return(0);
-	}
-
-	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-	ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-	if (ReadComplete) {
-		SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
-	}
-
-	/* Now we are correctly initialized */
-	pAC->I2c.InitLevel = SK_INIT_RUN;
-
-	return(0);
-}	/* SkI2cInit2*/
-
-
-/*
- * Initialize I2C devices
- *
- * Get the first voltage value and discard it.
- * Go into temperature read mode. A default pointer is not set.
- *
- * The things to be done depend on the init level in the parameter list:
- * Level 0:
- *	Initialize only the data structures. Do NOT access hardware.
- * Level 1:
- *	Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
- * Level 2:
- *	Everything is possible. Interrupts may be used from now on.
- *
- * return:
- *	0 = success
- *	other = error.
- */
-int	SkI2cInit(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context needed in levels 1 and 2 */
-int		Level)	/* Init Level */
-{
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		return(SkI2cInit0(pAC));
-	case SK_INIT_IO:
-		return(SkI2cInit1(pAC, IoC));
-	case SK_INIT_RUN:
-		return(SkI2cInit2(pAC, IoC));
-	default:
-		break;
-	}
-
-	return(0);
-}	/* SkI2cInit */
-
-
-#ifndef SK_DIAG
-
-/*
- * Interrupt service function for the I2C Interface
- *
- * Clears the Interrupt source
- *
- * Reads the register and check it for sending a trap.
- *
- * Starts the timer if necessary.
- */
-void SkI2cIsr(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	SK_EVPARA	Para;
-
-	/* Clear I2C IRQ */
-	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-
-	Para.Para64 = 0;
-	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
-}	/* SkI2cIsr */
-
-
-/*
- * Check this sensors Value against the threshold and send events.
- */
-static void SkI2cCheckSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_SENSOR	*pSen)
-{
-	SK_EVPARA	ParaLocal;
-	SK_BOOL		TooHigh;	/* Is sensor too high? */
-	SK_BOOL		TooLow;		/* Is sensor too low? */
-	SK_U64		CurrTime;	/* Current Time */
-	SK_BOOL		DoTrapSend;	/* We need to send a trap */
-	SK_BOOL		DoErrLog;	/* We need to log the error */
-	SK_BOOL		IsError;	/* We need to log the error */
-
-	/* Check Dummy Reads first */
-	if (pAC->I2c.DummyReads > 0) {
-		pAC->I2c.DummyReads--;
-		return;
-	}
-
-	/* Get the current time */
-	CurrTime = SkOsGetTime(pAC);
-
-	/* Set para to the most useful setting: The current sensor. */
-	ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
-
-	/* Check the Value against the thresholds. First: Error Thresholds */
-	TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
-	TooLow = (pSen->SenValue < pSen->SenThreErrLow);
-		
-	IsError = SK_FALSE;
-	if (TooHigh || TooLow) {
-		/* Error condition is satisfied */
-		DoTrapSend = SK_TRUE;
-		DoErrLog = SK_TRUE;
-
-		/* Now error condition is satisfied */
-		IsError = SK_TRUE;
-
-		if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
-			/* This state is the former one */
-
-			/* So check first whether we have to send a trap */
-			if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
-			    CurrTime) {
-				/*
-				 * Do NOT send the Trap. The hold back time
-				 * has to run out first.
-				 */
-				DoTrapSend = SK_FALSE;
-			}
-
-			/* Check now whether we have to log an Error */
-			if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
-			    CurrTime) {
-				/*
-				 * Do NOT log the error. The hold back time
-				 * has to run out first.
-				 */
-				DoErrLog = SK_FALSE;
-			}
-		}
-		else {
-			/* We came from a different state -> Set Begin Time Stamp */
-			pSen->SenBegErrTS = CurrTime;
-			pSen->SenErrFlag = SK_SEN_ERR_ERR;
-		}
-
-		if (DoTrapSend) {
-			/* Set current Time */
-			pSen->SenLastErrTrapTS = CurrTime;
-			pSen->SenErrCts++;
-
-			/* Queue PNMI Event */
-			SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
-				SK_PNMI_EVT_SEN_ERR_UPP :
-				SK_PNMI_EVT_SEN_ERR_LOW),
-				ParaLocal);
-		}
-
-		if (DoErrLog) {
-			/* Set current Time */
-			pSen->SenLastErrLogTS = CurrTime;
-
-			if (pSen->SenType == SK_SEN_TEMP) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
-			}
-			else if (pSen->SenType == SK_SEN_VOLT) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
-			}
-			else {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
-			}
-		}
-	}
-
-	/* Check the Value against the thresholds */
-	/* 2nd: Warning thresholds */
-	TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
-	TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
-		
-	if (!IsError && (TooHigh || TooLow)) {
-		/* Error condition is satisfied */
-		DoTrapSend = SK_TRUE;
-		DoErrLog = SK_TRUE;
-
-		if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
-			/* This state is the former one */
-
-			/* So check first whether we have to send a trap */
-			if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
-				/*
-				 * Do NOT send the Trap. The hold back time
-				 * has to run out first.
-				 */
-				DoTrapSend = SK_FALSE;
-			}
-
-			/* Check now whether we have to log an Error */
-			if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
-				/*
-				 * Do NOT log the error. The hold back time
-				 * has to run out first.
-				 */
-				DoErrLog = SK_FALSE;
-			}
-		}
-		else {
-			/* We came from a different state -> Set Begin Time Stamp */
-			pSen->SenBegWarnTS = CurrTime;
-			pSen->SenErrFlag = SK_SEN_ERR_WARN;
-		}
-
-		if (DoTrapSend) {
-			/* Set current Time */
-			pSen->SenLastWarnTrapTS = CurrTime;
-			pSen->SenWarnCts++;
-
-			/* Queue PNMI Event */
-			SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
-				SK_PNMI_EVT_SEN_WAR_UPP :
-				SK_PNMI_EVT_SEN_WAR_LOW),
-				ParaLocal);
-		}
-
-		if (DoErrLog) {
-			/* Set current Time */
-			pSen->SenLastWarnLogTS = CurrTime;
-
-			if (pSen->SenType == SK_SEN_TEMP) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
-			}
-			else if (pSen->SenType == SK_SEN_VOLT) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
-			}
-			else {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
-			}
-		}
-	}
-
-	/* Check for NO error at all */
-	if (!IsError && !TooHigh && !TooLow) {
-		/* Set o.k. Status if no error and no warning condition */
-		pSen->SenErrFlag = SK_SEN_ERR_OK;
-	}
-
-	/* End of check against the thresholds */
-
-	/* Bug fix AF: 16.Aug.2001: Correct the init base
-	 * of LM80 sensor.
-	 */
-	if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
-
-        pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
-		if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
-			/* 5V PCI-IO Voltage */
-			pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
-			pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
-		}
-		else {
-			/* 3.3V PCI-IO Voltage */
-			pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
-			pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
-		}
-	}
-	
-#ifdef TEST_ONLY
-    /* Dynamic thresholds also for VAUX of LM80 sensor */
-	if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
-
-        pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
-		/* 3.3V VAUX Voltage */
-		if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
-			pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
-			pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
-		}
-		/* 0V VAUX Voltage */
-		else {
-			pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
-			pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
-		}
-	}
-
-	/*
-	 * Check initialization state:
-	 * The VIO Thresholds need adaption
-	 */
-	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
-	     pSen->SenValue > SK_SEN_WARNLOW2C &&
-	     pSen->SenValue < SK_SEN_WARNHIGH2) {
-		pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
-		pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
-		pSen->SenInit = SK_TRUE;
-	}
-
-	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
-	     pSen->SenValue > SK_SEN_WARNLOW2 &&
-	     pSen->SenValue < SK_SEN_WARNHIGH2C) {
-		pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
-		pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
-		pSen->SenInit = SK_TRUE;
-	}
-#endif
-
-	if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
-	}
-}	/* SkI2cCheckSensor */
-
-
-/*
- * The only Event to be served is the timeout event
- *
- */
-int	SkI2cEvent(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Module specific Event */
-SK_EVPARA	Para)	/* Event specific Parameter */
-{
-	int			ReadComplete;
-	SK_SENSOR	*pSen;
-	SK_U32		Time;
-	SK_EVPARA	ParaLocal;
-	int			i;
-
-	/* New case: no sensors */
-	if (pAC->I2c.MaxSens == 0) {
-		return(0);
-	}
-
-	switch (Event) {
-	case SK_I2CEV_IRQ:
-		pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-		ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-		if (ReadComplete) {
-			/* Check sensor against defined thresholds */
-			SkI2cCheckSensor(pAC, pSen);
-
-			/* Increment Current sensor and set appropriate Timeout */
-			pAC->I2c.CurrSens++;
-			if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
-				pAC->I2c.CurrSens = 0;
-				Time = SK_I2C_TIM_LONG;
-			}
-			else {
-				Time = SK_I2C_TIM_SHORT;
-			}
-
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-			
-			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-        else {
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-
-            SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-		break;
-	case SK_I2CEV_TIM:
-		if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
-
-			ParaLocal.Para64 = (SK_U64)0;
-			SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
-
-			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-			ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-			if (ReadComplete) {
-				/* Check sensor against defined thresholds */
-				SkI2cCheckSensor(pAC, pSen);
-
-				/* Increment Current sensor and set appropriate Timeout */
-				pAC->I2c.CurrSens++;
-				if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
-					pAC->I2c.CurrSens = 0;
-					Time = SK_I2C_TIM_LONG;
-				}
-				else {
-					Time = SK_I2C_TIM_SHORT;
-				}
-
-				/* Start Timer */
-				ParaLocal.Para64 = (SK_U64)0;
-
-				pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
-				SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-					SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-			}
-		}
-		else {
-			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-			pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
-			SK_I2C_STOP(IoC);
-
-			/* Increment Current sensor and set appropriate Timeout */
-			pAC->I2c.CurrSens++;
-			if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
-				pAC->I2c.CurrSens = 0;
-				Time = SK_I2C_TIM_LONG;
-			}
-			else {
-				Time = SK_I2C_TIM_SHORT;
-			}
-
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
-			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-		break;
-	case SK_I2CEV_CLEAR:
-		for (i = 0; i < SK_MAX_SENSORS; i++) {
-			pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
-			pAC->I2c.SenTable[i].SenErrCts = 0;
-			pAC->I2c.SenTable[i].SenWarnCts = 0;
-			pAC->I2c.SenTable[i].SenBegErrTS = 0;
-			pAC->I2c.SenTable[i].SenBegWarnTS = 0;
-			pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
-		}
-		break;
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
-	}
-
-	return(0);
-}	/* SkI2cEvent*/
-
-#endif /* !SK_DIAG */
diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
deleted file mode 100644
index a204f5b..0000000
--- a/drivers/net/sk98lin/sklm80.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/******************************************************************************
- *
- * Name:	sklm80.c
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.22 $
- * Date:	$Date: 2003/10/20 09:08:21 $
- * Purpose:	Functions to access Voltage and Temperature Sensor (LM80)
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-	LM80 functions
-*/
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#define	BREAK_OR_WAIT(pAC,IoC,Event)	break
-
-/*
- * read a sensors value (LM80 specific)
- *
- * This function reads a sensors value from the I2C sensor chip LM80.
- * The sensor is defined by its index into the sensors database in the struct
- * pAC points to.
- *
- * Returns	1 if the read is completed
- *		0 if the read must be continued (I2C Bus still allocated)
- */
-int SkLm80ReadSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context needed in level 1 and 2 */
-SK_SENSOR	*pSen)	/* Sensor to be read */
-{
-	SK_I32		Value;
-
-	switch (pSen->SenState) {
-	case SK_SEN_IDLE:
-		/* Send address to ADDR register */
-		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0);
-
-		pSen->SenState = SK_SEN_VALUE ;
-		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-	
-	case SK_SEN_VALUE:
-		/* Read value from data register */
-		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
-		
-		Value &= 0xff; /* only least significant byte is valid */
-
-		/* Do NOT check the Value against the thresholds */
-		/* Checking is done in the calling instance */
-
-		if (pSen->SenType == SK_SEN_VOLT) {
-			/* Voltage sensor */
-			pSen->SenValue = Value * SK_LM80_VT_LSB;
-			pSen->SenState = SK_SEN_IDLE ;
-			return(1);
-		}
-
-		if (pSen->SenType == SK_SEN_FAN) {
-			if (Value != 0 && Value != 0xff) {
-				/* Fan speed counter */
-				pSen->SenValue = SK_LM80_FAN_FAKTOR/Value;
-			}
-			else {
-				/* Indicate Fan error */
-				pSen->SenValue = 0;
-			}
-			pSen->SenState = SK_SEN_IDLE ;
-			return(1);
-		}
-
-		/* First: correct the value: it might be negative */
-		if ((Value & 0x80) != 0) {
-			/* Value is negative */
-			Value = Value - 256;
-		}
-
-		/* We have a temperature sensor and need to get the signed extension.
-		 * For now we get the extension from the last reading, so in the normal
-		 * case we won't see flickering temperatures.
-		 */
-		pSen->SenValue = (Value * SK_LM80_TEMP_LSB) +
-			(pSen->SenValue % SK_LM80_TEMP_LSB);
-
-		/* Send address to ADDR register */
-		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-
-		pSen->SenState = SK_SEN_VALEXT ;
-		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-	
-	case SK_SEN_VALEXT:
-		/* Read value from data register */
-		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
-		Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */
-
-		/* cut the LSB bit */
-		pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) *
-			SK_LM80_TEMP_LSB);
-
-		if (pSen->SenValue < 0) {
-			/* Value negative: The bit value must be subtracted */
-			pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
-		}
-		else {
-			/* Value positive: The bit value must be added */
-			pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
-		}
-
-		pSen->SenState = SK_SEN_IDLE ;
-		return(1);
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG);
-		return(1);
-	}
-
-	/* Not completed */
-	return(0);
-}
-
diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
deleted file mode 100644
index 0275b4f..0000000
--- a/drivers/net/sk98lin/skqueue.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name:	skqueue.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.20 $
- * Date:	$Date: 2003/09/16 13:44:00 $
- * Purpose:	Management of an event queue.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skqueue.h"		/* Queue Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	Event queue management.
-
-	General Description:
-
- */
-intro()
-{}
-#endif
-
-#define PRINTF(a,b,c)
-
-/*
- * init event queue management
- *
- * Must be called during init level 0.
- */
-void	SkEventInit(
-SK_AC	*pAC,	/* Adapter context */
-SK_IOC	Ioc,	/* IO context */
-int		Level)	/* Init level */
-{
-	switch (Level) {
-	case SK_INIT_DATA:
-		pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue;
-		break;
-	default:
-		break;
-	}
-}
-
-/*
- * add event to queue
- */
-void	SkEventQueue(
-SK_AC		*pAC,	/* Adapters context */
-SK_U32		Class,	/* Event Class */
-SK_U32		Event,	/* Event to be queued */
-SK_EVPARA	Para)	/* Event parameter */
-{
-	pAC->Event.EvPut->Class = Class;
-	pAC->Event.EvPut->Event = Event;
-	pAC->Event.EvPut->Para = Para;
-	
-	if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
-		pAC->Event.EvPut = pAC->Event.EvQueue;
-
-	if (pAC->Event.EvPut == pAC->Event.EvGet) {
-		SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
-	}
-}
-
-/*
- * event dispatcher
- *	while event queue is not empty
- *		get event from queue
- *		send command to state machine
- *	end
- *	return error reported by individual Event function
- *		0 if no error occured.
- */
-int	SkEventDispatcher(
-SK_AC	*pAC,	/* Adapters Context */
-SK_IOC	Ioc)	/* Io context */
-{
-	SK_EVENTELEM	*pEv;	/* pointer into queue */
-	SK_U32			Class;
-	int			Rtv;
-
-	pEv = pAC->Event.EvGet;
-	
-	PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
-	
-	while (pEv != pAC->Event.EvPut) {
-		PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event);
-
-		switch (Class = pEv->Class) {
-#ifndef SK_USE_LAC_EV
-#ifndef SK_SLIM
-		case SKGE_RLMT:		/* RLMT Event */
-			Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_I2C:		/* I2C Event */
-			Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_PNMI:		/* PNMI Event */
-			Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif	/* not SK_SLIM */
-#endif	/* not SK_USE_LAC_EV */
-		case SKGE_DRV:		/* Driver Event */
-			Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#ifndef SK_USE_SW_TIMER
-		case SKGE_HWAC:
-			Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#else /* !SK_USE_SW_TIMER */
-        case SKGE_SWT :
-			Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif /* !SK_USE_SW_TIMER */
-#ifdef SK_USE_LAC_EV
-		case SKGE_LACP :
-			Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_RSF :
-			Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_MARKER :
-			Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_FD :
-			Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif /* SK_USE_LAC_EV */
-#ifdef	SK_USE_CSUM
-		case SKGE_CSUM :
-			Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif	/* SK_USE_CSUM */
-		default :
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG);
-			Rtv = 0;
-		}
-
-		if (Rtv != 0) {
-			return(Rtv);
-		}
-
-		if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT])
-			pEv = pAC->Event.EvQueue;
-
-		/* Renew get: it is used in queue_events to detect overruns */
-		pAC->Event.EvGet = pEv;
-	}
-
-	return(0);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
deleted file mode 100644
index be8d1cc..0000000
--- a/drivers/net/sk98lin/skrlmt.c
+++ /dev/null
@@ -1,3257 +0,0 @@
-/******************************************************************************
- *
- * Name:	skrlmt.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.69 $
- * Date:	$Date: 2003/04/15 09:39:22 $
- * Purpose:	Manage links on SK-NET Adapters, esp. redundant ones.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
- * It is mainly intended for adapters with more than one link.
- * For such adapters, this module realizes Redundant Link ManagemenT (RLMT).
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef	lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell.";
-#endif	/* !defined(lint) */
-
-#define __SKRLMT_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-#ifndef SK_HWAC_LINK_LED
-#define SK_HWAC_LINK_LED(a,b,c,d)
-#endif	/* !defined(SK_HWAC_LINK_LED) */
-
-#ifndef DEBUG
-#define RLMT_STATIC	static
-#else	/* DEBUG */
-#define RLMT_STATIC
-
-#ifndef SK_LITTLE_ENDIAN
-/* First 32 bits */
-#define OFFS_LO32	1
-
-/* Second 32 bits */
-#define OFFS_HI32	0
-#else	/* SK_LITTLE_ENDIAN */
-/* First 32 bits */
-#define OFFS_LO32	0
-
-/* Second 32 bits */
-#define OFFS_HI32	1
-#endif	/* SK_LITTLE_ENDIAN */
-
-#endif	/* DEBUG */
-
-/* ----- Private timeout values ----- */
-
-#define SK_RLMT_MIN_TO_VAL			   125000	/* 1/8 sec. */
-#define SK_RLMT_DEF_TO_VAL			  1000000	/* 1 sec. */
-#define SK_RLMT_PORTDOWN_TIM_VAL	   900000	/* another 0.9 sec. */
-#define SK_RLMT_PORTSTART_TIM_VAL	   100000	/* 0.1 sec. */
-#define SK_RLMT_PORTUP_TIM_VAL		  2500000	/* 2.5 sec. */
-#define SK_RLMT_SEG_TO_VAL			900000000	/* 15 min. */
-
-/* Assume tick counter increment is 1 - may be set OS-dependent. */
-#ifndef SK_TICK_INCR
-#define SK_TICK_INCR	SK_CONSTU64(1)
-#endif	/* !defined(SK_TICK_INCR) */
-
-/*
- * Amount that a time stamp must be later to be recognized as "substantially
- * later". This is about 1/128 sec, but above 1 tick counter increment.
- */
-#define SK_RLMT_BC_DELTA		(1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
-									(SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
-
-/* ----- Private RLMT defaults ----- */
-
-#define SK_RLMT_DEF_PREF_PORT	0					/* "Lower" port. */
-#define SK_RLMT_DEF_MODE 		SK_RLMT_CHECK_LINK	/* Default RLMT Mode. */
-
-/* ----- Private RLMT checking states ----- */
-
-#define SK_RLMT_RCS_SEG			1		/* RLMT Check State: check seg. */
-#define SK_RLMT_RCS_START_SEG	2		/* RLMT Check State: start check seg. */
-#define SK_RLMT_RCS_SEND_SEG	4		/* RLMT Check State: send BPDU packet */
-#define SK_RLMT_RCS_REPORT_SEG	8		/* RLMT Check State: report seg. */
-
-/* ----- Private PORT checking states ----- */
-
-#define SK_RLMT_PCS_TX			1		/* Port Check State: check tx. */
-#define SK_RLMT_PCS_RX			2		/* Port Check State: check rx. */
-
-/* ----- Private PORT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_PORTSTART_TIM	1100	/* Port start timeout. */
-#define SK_RLMT_PORTUP_TIM		1101	/* Port can now go up. */
-#define SK_RLMT_PORTDOWN_RX_TIM	1102	/* Port did not receive once ... */
-#define SK_RLMT_PORTDOWN		1103	/* Port went down. */
-#define SK_RLMT_PORTDOWN_TX_TIM	1104	/* Partner did not receive ... */
-
-/* ----- Private RLMT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_TIM				2100	/* RLMT timeout. */
-#define SK_RLMT_SEG_TIM			2101	/* RLMT segmentation check timeout. */
-
-#define TO_SHORTEN(tim)	((tim) / 2)
-
-/* Error numbers and messages. */
-#define SKERR_RLMT_E001		(SK_ERRBASE_RLMT + 0)
-#define SKERR_RLMT_E001_MSG	"No Packet."
-#define SKERR_RLMT_E002		(SKERR_RLMT_E001 + 1)
-#define SKERR_RLMT_E002_MSG	"Short Packet."
-#define SKERR_RLMT_E003		(SKERR_RLMT_E002 + 1)
-#define SKERR_RLMT_E003_MSG	"Unknown RLMT event."
-#define SKERR_RLMT_E004		(SKERR_RLMT_E003 + 1)
-#define SKERR_RLMT_E004_MSG	"PortsUp incorrect."
-#define SKERR_RLMT_E005		(SKERR_RLMT_E004 + 1)
-#define SKERR_RLMT_E005_MSG	\
- "Net seems to be segmented (different root bridges are reported on the ports)."
-#define SKERR_RLMT_E006		(SKERR_RLMT_E005 + 1)
-#define SKERR_RLMT_E006_MSG	"Duplicate MAC Address detected."
-#define SKERR_RLMT_E007		(SKERR_RLMT_E006 + 1)
-#define SKERR_RLMT_E007_MSG	"LinksUp incorrect."
-#define SKERR_RLMT_E008		(SKERR_RLMT_E007 + 1)
-#define SKERR_RLMT_E008_MSG	"Port not started but link came up."
-#define SKERR_RLMT_E009		(SKERR_RLMT_E008 + 1)
-#define SKERR_RLMT_E009_MSG	"Corrected illegal setting of Preferred Port."
-#define SKERR_RLMT_E010		(SKERR_RLMT_E009 + 1)
-#define SKERR_RLMT_E010_MSG	"Ignored illegal Preferred Port."
-
-/* LLC field values. */
-#define LLC_COMMAND_RESPONSE_BIT		1
-#define LLC_TEST_COMMAND				0xE3
-#define LLC_UI							0x03
-
-/* RLMT Packet fields. */
-#define	SK_RLMT_DSAP					0
-#define	SK_RLMT_SSAP					0
-#define SK_RLMT_CTRL					(LLC_TEST_COMMAND)
-#define SK_RLMT_INDICATOR0				0x53	/* S */
-#define SK_RLMT_INDICATOR1				0x4B	/* K */
-#define SK_RLMT_INDICATOR2				0x2D	/* - */
-#define SK_RLMT_INDICATOR3				0x52	/* R */
-#define SK_RLMT_INDICATOR4				0x4C	/* L */
-#define SK_RLMT_INDICATOR5				0x4D	/* M */
-#define SK_RLMT_INDICATOR6				0x54	/* T */
-#define SK_RLMT_PACKET_VERSION			0
-
-/* RLMT SPT Flag values. */
-#define	SK_RLMT_SPT_FLAG_CHANGE			0x01
-#define	SK_RLMT_SPT_FLAG_CHANGE_ACK		0x80
-
-/* RLMT SPT Packet fields. */
-#define	SK_RLMT_SPT_DSAP				0x42
-#define	SK_RLMT_SPT_SSAP				0x42
-#define SK_RLMT_SPT_CTRL				(LLC_UI)
-#define	SK_RLMT_SPT_PROTOCOL_ID0		0x00
-#define	SK_RLMT_SPT_PROTOCOL_ID1		0x00
-#define	SK_RLMT_SPT_PROTOCOL_VERSION_ID	0x00
-#define	SK_RLMT_SPT_BPDU_TYPE			0x00
-#define	SK_RLMT_SPT_FLAGS				0x00	/* ?? */
-#define	SK_RLMT_SPT_ROOT_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_ROOT_ID1			0xFF	/* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define	SK_RLMT_SPT_ROOT_PATH_COST0		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST1		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST2		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST3		0x00
-#define	SK_RLMT_SPT_BRIDGE_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_BRIDGE_ID1			0xFF	/* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define	SK_RLMT_SPT_PORT_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_PORT_ID1			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_MSG_AGE0			0x00
-#define	SK_RLMT_SPT_MSG_AGE1			0x00
-#define	SK_RLMT_SPT_MAX_AGE0			0x00
-#define	SK_RLMT_SPT_MAX_AGE1			0xFF
-#define	SK_RLMT_SPT_HELLO_TIME0			0x00
-#define	SK_RLMT_SPT_HELLO_TIME1			0xFF
-#define	SK_RLMT_SPT_FWD_DELAY0			0x00
-#define	SK_RLMT_SPT_FWD_DELAY1			0x40
-
-/* Size defines. */
-#define SK_RLMT_MIN_PACKET_SIZE			34
-#define SK_RLMT_MAX_PACKET_SIZE			(SK_RLMT_MAX_TX_BUF_SIZE)
-#define SK_PACKET_DATA_LEN				(SK_RLMT_MAX_PACKET_SIZE - \
-										SK_RLMT_MIN_PACKET_SIZE)
-
-/* ----- RLMT packet types ----- */
-#define SK_PACKET_ANNOUNCE				1	/* Port announcement. */
-#define SK_PACKET_ALIVE					2	/* Alive packet to port. */
-#define SK_PACKET_ADDR_CHANGED			3	/* Port address changed. */
-#define SK_PACKET_CHECK_TX				4	/* Check your tx line. */
-
-#ifdef SK_LITTLE_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \
-	SK_U8	*_Addr = (SK_U8*)(Addr); \
-	SK_U16	_Val = (SK_U16)(Val); \
-	*_Addr++ = (SK_U8)(_Val >> 8); \
-	*_Addr = (SK_U8)(_Val & 0xFF); \
-}
-#endif	/* SK_LITTLE_ENDIAN */
-
-#ifdef SK_BIG_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
-#endif	/* SK_BIG_ENDIAN */
-
-#define AUTONEG_FAILED	SK_FALSE
-#define AUTONEG_SUCCESS	SK_TRUE
-
-
-/* typedefs *******************************************************************/
-
-/* RLMT packet.  Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */
-typedef struct s_RlmtPacket {
-	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
-	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
-	SK_U8	TypeLen[2];
-	SK_U8	DSap;
-	SK_U8	SSap;
-	SK_U8	Ctrl;
-	SK_U8	Indicator[7];
-	SK_U8	RlmtPacketType[2];
-	SK_U8	Align1[2];
-	SK_U8	Random[4];				/* Random value of requesting(!) station. */
-	SK_U8	RlmtPacketVersion[2];	/* RLMT Packet version. */
-	SK_U8	Data[SK_PACKET_DATA_LEN];
-} SK_RLMT_PACKET;
-
-typedef struct s_SpTreeRlmtPacket {
-	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
-	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
-	SK_U8	TypeLen[2];
-	SK_U8	DSap;
-	SK_U8	SSap;
-	SK_U8	Ctrl;
-	SK_U8	ProtocolId[2];
-	SK_U8	ProtocolVersionId;
-	SK_U8	BpduType;
-	SK_U8	Flags;
-	SK_U8	RootId[8];
-	SK_U8	RootPathCost[4];
-	SK_U8	BridgeId[8];
-	SK_U8	PortId[2];
-	SK_U8	MessageAge[2];
-	SK_U8	MaxAge[2];
-	SK_U8	HelloTime[2];
-	SK_U8	ForwardDelay[2];
-} SK_SPTREE_PACKET;
-
-/* global variables ***********************************************************/
-
-SK_MAC_ADDR	SkRlmtMcAddr =	{{0x01,  0x00,  0x5A,  0x52,  0x4C,  0x4D}};
-SK_MAC_ADDR	BridgeMcAddr =	{{0x01,  0x80,  0xC2,  0x00,  0x00,  0x00}};
-
-/* local variables ************************************************************/
-
-/* None. */
-
-/* functions ******************************************************************/
-
-RLMT_STATIC void	SkRlmtCheckSwitch(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	NetIdx);
-RLMT_STATIC void	SkRlmtCheckSeg(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	NetIdx);
-RLMT_STATIC void	SkRlmtEvtSetNets(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_EVPARA	Para);
-
-/******************************************************************************
- *
- *	SkRlmtInit - initialize data, set state to init
- *
- * Description:
- *
- *	SK_INIT_DATA
- *	============
- *
- *	This routine initializes all RLMT-related variables to a known state.
- *	The initial state is SK_RLMT_RS_INIT.
- *	All ports are initialized to SK_RLMT_PS_INIT.
- *
- *
- *	SK_INIT_IO
- *	==========
- *
- *	Nothing.
- *
- *
- *	SK_INIT_RUN
- *	===========
- *
- *	Determine the adapter's random value.
- *	Set the hw registers, the "logical MAC address", the
- *	RLMT multicast address, and eventually the BPDU multicast address.
- *
- * Context:
- *	init, pageable
- *
- * Returns:
- *	Nothing.
- */
-void	SkRlmtInit(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-int		Level)	/* Initialization Level */
-{
-	SK_U32		i, j;
-	SK_U64		Random;
-	SK_EVPARA	Para;
-    SK_MAC_ADDR		VirtualMacAddress;
-    SK_MAC_ADDR		PhysicalAMacAddress;
-    SK_BOOL		VirtualMacAddressSet;
-    SK_BOOL		PhysicalAMacAddressSet;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
-		("RLMT Init level %d.\n", Level))
-
-	switch (Level) {
-	case SK_INIT_DATA:	/* Initialize data structures. */
-		SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT));
-
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT;
-			pAC->Rlmt.Port[i].LinkDown = SK_TRUE;
-			pAC->Rlmt.Port[i].PortDown = SK_TRUE;
-			pAC->Rlmt.Port[i].PortStarted = SK_FALSE;
-			pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;
-			pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Port[i].PortNumber = i;
-			pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0];
-			pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i];
-		}
-
-		pAC->Rlmt.NumNets = 1;
-		for (i = 0; i < SK_MAX_NETS; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* Automatic. */
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0];
-		pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];
-#if SK_MAX_NETS > 1
-		pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];
-#endif	/* SK_MAX_NETS > 1 */
-		break;
-
-	case SK_INIT_IO:	/* GIMacsFound first available here. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
-			("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound))
-
-		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
-		/* Initialize HW registers? */
-		if (pAC->GIni.GIMacsFound == 1) {
-			Para.Para32[0] = SK_RLMT_MODE_CLS;
-			Para.Para32[1] = 0;
-			(void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);
-		}
-		break;
-
-	case SK_INIT_RUN:
-		/* Ensure RLMT is set to one net. */
-		if (pAC->Rlmt.NumNets > 1) {
-			Para.Para32[0] = 1;
-			Para.Para32[1] = -1;
-			SkRlmtEvtSetNets(pAC, IoC, Para);
-		}
-
-		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-			Random = SkOsGetTime(pAC);
-			*(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;
-
-			for (j = 0; j < 4; j++) {
-				pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort->
-					CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j];
-			}
-
-			(void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-			
-			/* Add RLMT MC address. */
-			(void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
-			if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) {
-				/* Add BPDU MC address. */
-				(void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT);
-			}
-
-			(void)SkAddrMcUpdate(pAC, IoC, i);
-		}
-
-    	VirtualMacAddressSet = SK_FALSE;
-		/* Read virtual MAC address from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			
-            SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]);
-            VirtualMacAddressSet |= VirtualMacAddress.a[j];
-		}
-    	
-        PhysicalAMacAddressSet = SK_FALSE;
-		/* Read physical MAC address for MAC A from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			
-            SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]);
-            PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j];
-		}
-
-        /* check if the two mac addresses contain reasonable values */
-        if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) {
-
-            pAC->Rlmt.RlmtOff = SK_TRUE;
-        }
-
-        /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
-           and the RLMT_LOOKAHEAD macros */
-        else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) {
-
-            pAC->Rlmt.RlmtOff = SK_TRUE;
-        }
-		else {
-			pAC->Rlmt.RlmtOff = SK_FALSE;
-		}
-		break;
-
-	default:	/* error */
-		break;
-	}
-	return;
-}	/* SkRlmtInit */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildCheckChain - build the check chain
- *
- * Description:
- *	This routine builds the local check chain:
- *	- Each port that is up checks the next port.
- *	- The last port that is up checks the first port that is up.
- *
- * Notes:
- *	- Currently only local ports are considered when building the chain.
- *	- Currently the SuspectState is just reset;
- *	  it would be better to save it ...
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtBuildCheckChain(
-SK_AC	*pAC,	/* Adapter Context */
-SK_U32	NetIdx)	/* Net Number */
-{
-	SK_U32			i;
-	SK_U32			NumMacsUp;
-	SK_RLMT_PORT *	FirstMacUp;
-	SK_RLMT_PORT *	PrevMacUp;
-
-	FirstMacUp	= NULL;
-	PrevMacUp	= NULL;
-	
-	if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
-		for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) {
-			pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
-		}
-		return;	/* Done. */
-	}
-			
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SkRlmtBuildCheckChain.\n"))
-
-	NumMacsUp = 0;
-
-	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-		pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
-		pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0;
-		pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &=
-			~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);
-
-		/*
-		 * If more than two links are detected we should consider
-		 * checking at least two other ports:
-		 * 1. the next port that is not LinkDown and
-		 * 2. the next port that is not PortDown.
-		 */
-		if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
-			if (NumMacsUp == 0) {
-				FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
-			}
-			else {
-				PrevMacUp->PortCheck[
-					pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr =
-					pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress;
-				PrevMacUp->PortCheck[
-					PrevMacUp->PortsChecked].SuspectTx = SK_FALSE;
-				PrevMacUp->PortsChecked++;
-			}
-			PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
-			NumMacsUp++;
-		}
-	}
-
-	if (NumMacsUp > 1) {
-		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr =
-			FirstMacUp->AddrPort->CurrentMacAddress;
-		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx =
-			SK_FALSE;
-		PrevMacUp->PortsChecked++;
-	}
-
-#ifdef DEBUG
-	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Port %d checks %d other ports: %2X.\n", i,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]))
-	}
-#endif	/* DEBUG */
-
-	return;
-}	/* SkRlmtBuildCheckChain */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildPacket - build an RLMT packet
- *
- * Description:
- *	This routine sets up an RLMT packet.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF	*SkRlmtBuildPacket(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* I/O Context */
-SK_U32		PortNumber,	/* Sending port */
-SK_U16		PacketType,	/* RLMT packet type */
-SK_MAC_ADDR	*SrcAddr,	/* Source address */
-SK_MAC_ADDR	*DestAddr)	/* Destination address */
-{
-	int		i;
-	SK_U16		Length;
-	SK_MBUF		*pMb;
-	SK_RLMT_PACKET	*pPacket;
-
-#ifdef DEBUG
-	SK_U8	CheckSrc  = 0;
-	SK_U8	CheckDest = 0;
-	
-	for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {
-		CheckSrc  |= SrcAddr->a[i];
-		CheckDest |= DestAddr->a[i];
-	}
-
-	if ((CheckSrc == 0) || (CheckDest == 0)) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
-			("SkRlmtBuildPacket: Invalid %s%saddr.\n",
-			 (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")))
-	}
-#endif
-
-	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) {
-		pPacket = (SK_RLMT_PACKET*)pMb->pData;
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pPacket->DstAddr[i] = DestAddr->a[i];
-			pPacket->SrcAddr[i] = SrcAddr->a[i];
-		}
-		pPacket->DSap = SK_RLMT_DSAP;
-		pPacket->SSap = SK_RLMT_SSAP;
-		pPacket->Ctrl = SK_RLMT_CTRL;
-		pPacket->Indicator[0] = SK_RLMT_INDICATOR0;
-		pPacket->Indicator[1] = SK_RLMT_INDICATOR1;
-		pPacket->Indicator[2] = SK_RLMT_INDICATOR2;
-		pPacket->Indicator[3] = SK_RLMT_INDICATOR3;
-		pPacket->Indicator[4] = SK_RLMT_INDICATOR4;
-		pPacket->Indicator[5] = SK_RLMT_INDICATOR5;
-		pPacket->Indicator[6] = SK_RLMT_INDICATOR6;
-
-		SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]);
-
-		for (i = 0; i < 4; i++) {
-			pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i];
-		}
-		
-		SK_U16_TO_NETWORK_ORDER(
-			SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]);
-
-		for (i = 0; i < SK_PACKET_DATA_LEN; i++) {
-			pPacket->Data[i] = 0x00;
-		}
-
-		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
-		pMb->Length = Length;
-		pMb->PortIdx = PortNumber;
-		Length -= 14;
-		SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);
-
-		if (PacketType == SK_PACKET_ALIVE) {
-			pAC->Rlmt.Port[PortNumber].TxHelloCts++;
-		}
-	}
-
-	return (pMb);
-}	/* SkRlmtBuildPacket */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildSpanningTreePacket - build spanning tree check packet
- *
- * Description:
- *	This routine sets up a BPDU packet for spanning tree check.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF	*SkRlmtBuildSpanningTreePacket(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Sending port */
-{
-	unsigned			i;
-	SK_U16				Length;
-	SK_MBUF				*pMb;
-	SK_SPTREE_PACKET	*pSPacket;
-
-	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=
-		NULL) {
-		pSPacket = (SK_SPTREE_PACKET*)pMb->pData;
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pSPacket->DstAddr[i] = BridgeMcAddr.a[i];
-			pSPacket->SrcAddr[i] =
-				pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
-		}
-		pSPacket->DSap = SK_RLMT_SPT_DSAP;
-		pSPacket->SSap = SK_RLMT_SPT_SSAP;
-		pSPacket->Ctrl = SK_RLMT_SPT_CTRL;
-
-		pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;
-		pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;
-		pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;
-		pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;
-		pSPacket->Flags = SK_RLMT_SPT_FLAGS;
-		pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;
-		pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;
-		pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;
-		pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;
-		pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;
-		pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;
-		pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;
-		pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;
-
-		/*
-		 * Use logical MAC address as bridge ID and filter these packets
-		 * on receive.
-		 */
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =
-				pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber].
-					CurrentMacAddress.a[i];
-		}
-		pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;
-		pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;
-		pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;
-		pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;
-		pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;
-		pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;
-		pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;
-		pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;
-		pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;
-		pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;
-
-		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
-		pMb->Length = Length;
-		pMb->PortIdx = PortNumber;
-		Length -= 14;
-		SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);
-
-		pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++;
-	}
-
-	return (pMb);
-}	/* SkRlmtBuildSpanningTreePacket */
-
-
-/******************************************************************************
- *
- *	SkRlmtSend - build and send check packets
- *
- * Description:
- *	Depending on the RLMT state and the checking state, several packets
- *	are sent through the indicated port.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtSend(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Sending port */
-{
-	unsigned	j;
-	SK_EVPARA	Para;
-	SK_RLMT_PORT	*pRPort;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-	if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
-		if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {
-			/* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
-			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-				&SkRlmtMcAddr)) != NULL) {
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-		}
-		else {
-			/*
-			 * Send a directed RLMT packet to all ports that are
-			 * checked by the indicated port.
-			 */
-			for (j = 0; j < pRPort->PortsChecked; j++) {
-				if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-					SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-					&pRPort->PortCheck[j].CheckAddr)) != NULL) {
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-				}
-			}
-		}
-	}
-
-	if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
-		(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) {
-		/*
-		 * Send a BPDU packet to make a connected switch tell us
-		 * the correct root bridge.
-		 */
-		if ((Para.pParaPtr =
-			SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) {
-			pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG;
-			pRPort->RootIdSet = SK_FALSE;
-
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
-				("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber))
-		}
-	}
-	return;
-}	/* SkRlmtSend */
-
-
-/******************************************************************************
- *
- *	SkRlmtPortReceives - check if port is (going) down and bring it up
- *
- * Description:
- *	This routine checks if a port who received a non-BPDU packet
- *	needs to go up or needs to be stopped going down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtPortReceives(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	PortNumber)		/* Port to check */
-{
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-	pRPort->PortNoRx = SK_FALSE;
-
-	if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
-		!(pRPort->CheckingState & SK_RLMT_PCS_TX)) {
-		/*
-		 * Port is marked down (rx), but received a non-BPDU packet.
-		 * Bring it up.
-		 */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Received on PortDown.\n"))
-
-		pRPort->PortState = SK_RLMT_PS_GOING_UP;
-		pRPort->GuTimeStamp = SkOsGetTime(pAC);
-		Para.Para32[0] = PortNumber;
-		Para.Para32[1] = (SK_U32)-1;
-		SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
-			SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para);
-		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
-		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
-		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-	}	/* PortDown && !SuspectTx */
-	else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Stop bringing port down.\n"))
-		SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
-		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
-		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-	}	/* PortGoingDown */
-
-	return;
-}	/* SkRlmtPortReceives */
-
-
-/******************************************************************************
- *
- *	SkRlmtPacketReceive - receive a packet for closer examination
- *
- * Description:
- *	This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtPacketReceive(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_MBUF	*pMb)	/* Received packet */
-{
-#ifdef xDEBUG
-	extern	void DumpData(char *p, int size);
-#endif	/* DEBUG */
-	int					i;
-	unsigned			j;
-	SK_U16				PacketType;
-	SK_U32				PortNumber;
-	SK_ADDR_PORT		*pAPort;
-	SK_RLMT_PORT		*pRPort;
-	SK_RLMT_PACKET		*pRPacket;
-	SK_SPTREE_PACKET	*pSPacket;
-	SK_EVPARA			Para;
-
-	PortNumber	= pMb->PortIdx;
-	pAPort = &pAC->Addr.Port[PortNumber];
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-		("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber))
-
-	pRPacket = (SK_RLMT_PACKET*)pMb->pData;
-	pSPacket = (SK_SPTREE_PACKET*)pRPacket;
-
-#ifdef xDEBUG
-	DumpData((char *)pRPacket, 32);
-#endif	/* DEBUG */
-
-	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) {
-		SkRlmtPortReceives(pAC, IoC, PortNumber);
-	}
-	
-	/* Check destination address. */
-
-	if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) &&
-		!SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) &&
-		!SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) {
-
-		/* Not sent to current MAC or registered MC address => Trash it. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Not for me.\n"))
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		return;
-	}
-	else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) {
-
-		/*
-		 * Was sent by same port (may happen during port switching
-		 * or in case of duplicate MAC addresses).
-		 */
-
-		/*
-		 * Check for duplicate address here:
-		 * If Packet.Random != My.Random => DupAddr.
-		 */
-		for (i = 3; i >= 0; i--) {
-			if (pRPort->Random[i] != pRPacket->Random[i]) {
-				break;
-			}
-		}
-
-		/*
-		 * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
-		 * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
-		 * pRPacket->SSap).
-		 */
-		if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP &&
-			pRPacket->Ctrl == SK_RLMT_CTRL &&
-			pRPacket->SSap == SK_RLMT_SSAP &&
-			pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
-			pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
-			pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
-			pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
-			pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
-			pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
-			pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
-
-			/* Error Log entry. */
-			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
-		}
-		else {
-			/* Simply trash it. */
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Sent by me.\n"))
-		}
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		return;
-	}
-
-	/* Check SuspectTx entries. */
-	if (pRPort->PortsSuspect > 0) {
-		for (j = 0; j < pRPort->PortsChecked; j++) {
-			if (pRPort->PortCheck[j].SuspectTx &&
-				SK_ADDR_EQUAL(
-					pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) {
-				pRPort->PortCheck[j].SuspectTx = SK_FALSE;
-				pRPort->PortsSuspect--;
-				break;
-			}
-		}
-	}
-
-	/* Determine type of packet. */
-	if (pRPacket->DSap == SK_RLMT_DSAP &&
-		pRPacket->Ctrl == SK_RLMT_CTRL &&
-		(pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP &&
-		pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
-		pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
-		pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
-		pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
-		pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
-		pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
-		pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
-
-		/* It's an RLMT packet. */
-		PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) |
-			pRPacket->RlmtPacketType[1]);
-
-		switch (PacketType) {
-		case SK_PACKET_ANNOUNCE:	/* Not yet used. */
-#if 0
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC);
-#endif	/* 0 */
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Announce.\n"))
-
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			break;
-
-		case SK_PACKET_ALIVE:
-			if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-					("SkRlmtPacketReceive: Alive Reply.\n"))
-
-				if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
-					SK_ADDR_EQUAL(
-						pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) {
-					/* Obviously we could send something. */
-					if (pRPort->CheckingState & SK_RLMT_PCS_TX) {
-						pRPort->CheckingState &=  ~SK_RLMT_PCS_TX;
-						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-					}
-
-					if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
-						!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
-						pRPort->PortState = SK_RLMT_PS_GOING_UP;
-						pRPort->GuTimeStamp = SkOsGetTime(pAC);
-
-						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-						Para.Para32[0] = PortNumber;
-						Para.Para32[1] = (SK_U32)-1;
-						SkTimerStart(pAC, IoC, &pRPort->UpTimer,
-							SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT,
-							SK_RLMT_PORTUP_TIM, Para);
-					}
-				}
-
-				/* Mark sending port as alive? */
-				SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			}
-			else {	/* Alive Request Packet. */
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-					("SkRlmtPacketReceive: Alive Request.\n"))
-
-				pRPort->RxHelloCts++;
-
-				/* Answer. */
-				for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-					pRPacket->DstAddr[i] = pRPacket->SrcAddr[i];
-					pRPacket->SrcAddr[i] =
-						pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
-				}
-				pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT;
-
-				Para.pParaPtr = pMb;
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-			break;
-
-		case SK_PACKET_CHECK_TX:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Check your tx line.\n"))
-
-			/* A port checking us requests us to check our tx line. */
-			pRPort->CheckingState |= SK_RLMT_PCS_TX;
-
-			/* Start PortDownTx timer. */
-			Para.Para32[0] = PortNumber;
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pRPort->DownTxTimer,
-				SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
-				SK_RLMT_PORTDOWN_TX_TIM, Para);
-
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-
-			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-				&SkRlmtMcAddr)) != NULL) {
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-			break;
-
-		case SK_PACKET_ADDR_CHANGED:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Address Change.\n"))
-
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
-
-			/* RA;:;: ??? */
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		}
-	}
-	else if (pSPacket->DSap == SK_RLMT_SPT_DSAP &&
-		pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
-		(pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: BPDU Packet.\n"))
-
-		/* Spanning Tree packet. */
-		pRPort->RxSpHelloCts++;
-
-		if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt.
-			Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) {
-			/*
-			 * Check segmentation if a new root bridge is set and
-			 * the segmentation check is not currently running.
-			 */
-			if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) &&
-				(pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
-				(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG)
-				!= 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState &
-				SK_RLMT_RCS_SEG) == 0) {
-				pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
-					SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
-			}
-
-			/* Store tree view of this port. */
-			for (i = 0; i < 8; i++) {
-				pRPort->Root.Id[i] = pSPacket->RootId[i];
-			}
-			pRPort->RootIdSet = SK_TRUE;
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
-				("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
-					PortNumber,
-					pRPort->Root.Id[0], pRPort->Root.Id[1],
-					pRPort->Root.Id[2], pRPort->Root.Id[3],
-					pRPort->Root.Id[4], pRPort->Root.Id[5],
-					pRPort->Root.Id[6], pRPort->Root.Id[7]))
-		}
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState &
-			SK_RLMT_RCS_REPORT_SEG) != 0) {
-			SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber);
-		}
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Unknown Packet Type.\n"))
-
-		/* Unknown packet. */
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-	}
-	return;
-}	/* SkRlmtPacketReceive */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckPort - check if a port works
- *
- * Description:
- *	This routine checks if a port whose link is up received something
- *	and if it seems to transmit successfully.
- *
- *	# PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
- *	# PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
- *	# RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
- *
- *	if (Rx - RxBpdu == 0) {	# No rx.
- *		if (state == PsUp) {
- *			PortCheckingState |= ChkRx
- *		}
- *		if (ModeCheckSeg && (Timeout ==
- *			TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
- *			RlmtCheckingState |= ChkSeg)
- *			PortCheckingState |= ChkSeg
- *		}
- *		NewTimeout = TO_SHORTEN(Timeout)
- *		if (NewTimeout < RLMT_MIN_TIMEOUT) {
- *			NewTimeout = RLMT_MIN_TIMEOUT
- *			PortState = PsDown
- *			...
- *		}
- *	}
- *	else {	# something was received
- *		# Set counter to 0 at LinkDown?
- *		#   No - rx may be reported after LinkDown ???
- *		PortCheckingState &= ~ChkRx
- *		NewTimeout = RLMT_DEFAULT_TIMEOUT
- *		if (RxAck == 0) {
- *			possible reasons:
- *			is my tx line bad? --
- *				send RLMT multicast and report
- *				back internally? (only possible
- *				between ports on same adapter)
- *		}
- *		if (RxChk == 0) {
- *			possible reasons:
- *			- tx line of port set to check me
- *			  maybe bad
- *			- no other port/adapter available or set
- *			  to check me
- *			- adapter checking me has a longer
- *			  timeout
- *			??? anything that can be done here?
- *		}
- *	}
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	New timeout value.
- */
-RLMT_STATIC SK_U32	SkRlmtCheckPort(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Port to check */
-{
-	unsigned		i;
-	SK_U32			NewTimeout;
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-
-	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
-				PortNumber, pRPort->PacketsPerTimeSlot))
-
-		/*
-		 * Check segmentation if there was no receive at least twice
-		 * in a row (PortNoRx is already set) and the segmentation
-		 * check is not currently running.
-		 */
-
-		if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
-			(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
-			!(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) {
-			pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
-				SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
-		}
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
-				pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX))
-
-		if (pRPort->PortState != SK_RLMT_PS_DOWN) {
-			NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
-			if (NewTimeout < SK_RLMT_MIN_TO_VAL) {
-				NewTimeout = SK_RLMT_MIN_TO_VAL;
-			}
-
-			if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
-				Para.Para32[0] = PortNumber;
-				pRPort->CheckingState |= SK_RLMT_PCS_RX;
-
-				/*
-				 * What shall we do if the port checked by this one receives
-				 * our request frames?  What's bad - our rx line or his tx line?
-				 */
-				Para.Para32[1] = (SK_U32)-1;
-				SkTimerStart(pAC, IoC, &pRPort->DownRxTimer,
-					SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
-					SK_RLMT_PORTDOWN_RX_TIM, Para);
-
-				for (i = 0; i < pRPort->PortsChecked; i++) {
-					if (pRPort->PortCheck[i].SuspectTx) {
-						continue;
-					}
-					pRPort->PortCheck[i].SuspectTx = SK_TRUE;
-					pRPort->PortsSuspect++;
-					if ((Para.pParaPtr =
-						SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX,
-							&pAC->Addr.Port[PortNumber].CurrentMacAddress,
-							&pRPort->PortCheck[i].CheckAddr)) != NULL) {
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-					}
-				}
-			}
-		}
-		else {	/* PortDown -- or all partners suspect. */
-			NewTimeout = SK_RLMT_DEF_TO_VAL;
-		}
-		pRPort->PortNoRx = SK_TRUE;
-	}
-	else {	/* A non-BPDU packet was received. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
-				PortNumber,
-				pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
-				pRPort->PacketsPerTimeSlot))
-		
-		SkRlmtPortReceives(pAC, IoC, PortNumber);
-		if (pAC->Rlmt.CheckSwitch) {
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-
-		NewTimeout = SK_RLMT_DEF_TO_VAL;
-	}
-
-	return (NewTimeout);
-}	/* SkRlmtCheckPort */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
- *
- * Description:
- *	This routine selects the port that received a broadcast frame
- *	substantially later than all other ports.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectBcRx(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	Active,		/* Active port */
-SK_U32	PrefPort,	/* Preferred port */
-SK_U32	*pSelect)	/* New active port */
-{
-	SK_U64		BcTimeStamp;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	BcTimeStamp = 0;	/* Not totally necessary, but feeling better. */
-	PortFound = SK_FALSE;
-	
-	/* Select port with the latest TimeStamp. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
-				i,
-   				pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
-				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
-				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)))
-
-		if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
-			if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
-				BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp;
-				*pSelect = i;
-				PortFound = SK_TRUE;
-			}
-		}
-	}
-
-	if (PortFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Port %d received the last broadcast.\n", *pSelect))
-
-		/* Look if another port's time stamp is similar. */
-		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-			if (i == *pSelect) {
-				continue;
-			}
-			if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx &&
-				(pAC->Rlmt.Port[i].BcTimeStamp >
-				 BcTimeStamp - SK_RLMT_BC_DELTA ||
-				pAC->Rlmt.Port[i].BcTimeStamp +
-				 SK_RLMT_BC_DELTA > BcTimeStamp)) {
-				PortFound = SK_FALSE;
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-					("Port %d received a broadcast at a similar time.\n", i))
-				break;
-			}
-		}
-	}
-
-#ifdef DEBUG
-	if (PortFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
-			 "latest broadcast (%u).\n",
-				*pSelect,
-				BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp))
-	}
-#endif	/* DEBUG */
-
-	return (PortFound);
-}	/* SkRlmtSelectBcRx */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
- *
- * Description:
- *	This routine selects a good port (it is PortUp && !SuspectRx).
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectNotSuspect(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	Active,		/* Active port */
-SK_U32	PrefPort,	/* Preferred port */
-SK_U32	*pSelect)	/* New active port */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortUp && !SuspectRx. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (!pAC->Rlmt.Port[i].PortDown &&
-			!(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) {
-			*pSelect = i;
-			if (!pAC->Rlmt.Port[Active].PortDown &&
-				!(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) {
-				*pSelect = Active;
-			}
-			if (!pAC->Rlmt.Port[PrefPort].PortDown &&
-				!(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
-					*pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectNotSuspect */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
- *
- * Description:
- *	This routine selects a port that is up.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectUp(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortUp. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			*pSelect = i;
-			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP &&
-				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
-				*pSelect = Active;
-			}
-			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP &&
-				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
- *
- * Description:
- *	This routine selects the port that is going up for the longest time.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectGoingUp(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U64		GuTimeStamp;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	GuTimeStamp = 0;
-	PortFound = SK_FALSE;
-
-	/* Select port that is PortGoingUp for the longest time. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
-			*pSelect = i;
-			PortFound = SK_TRUE;
-			break;
-		}
-	}
-
-	if (!PortFound) {
-		return (SK_FALSE);
-	}
-
-	for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
-			pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
-			*pSelect = i;
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect))
-	return (SK_TRUE);
-}	/* SkRlmtSelectGoingUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
- *
- * Description:
- *	This routine selects a port that is down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectDown(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortDown. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			*pSelect = i;
-			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN &&
-				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
-				*pSelect = Active;
-			}
-			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN &&
-				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectDown */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckSwitch - select new active port and switch to it
- *
- * Description:
- *	This routine decides which port should be the active one and queues
- *	port switching if necessary.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtCheckSwitch(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_U32	NetIdx)	/* Net index */
-{
-	SK_EVPARA	Para;
-	SK_U32		Active;
-	SK_U32		PrefPort;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	Active = pAC->Rlmt.Net[NetIdx].ActivePort;	/* Index of active port. */
-	PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort;	/* Index of preferred port. */
-	PortFound = SK_FALSE;
-	pAC->Rlmt.CheckSwitch = SK_FALSE;
-
-#if 0	/* RW 2001/10/18 - active port becomes always prefered one */
-	if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */
-		/* disable auto-fail back */
-		PrefPort = Active;
-	}
-#endif
-
-	if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) {
-		/* Last link went down - shut down the net. */
-		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN;
-		Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP;
-		Para.Para32[1] = NetIdx;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para);
-
-		Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-			Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
-		Para.Para32[1] = NetIdx;
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
-		return;
-	}	/* pAC->Rlmt.LinksUp == 0 */
-	else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 &&
-		pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) {
-		/* First link came up - get the net up. */
-		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP;
-
-		/*
-		 * If pAC->Rlmt.ActivePort != Para.Para32[0],
-		 * the DRV switches to the port that came up.
-		 */
-		for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-			if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
-				if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) {
-					i = Active;
-				}
-				if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) {
-					i = PrefPort;
-				}
-				PortFound = SK_TRUE;
-				break;
-			}
-		}
-
-		if (PortFound) {
-			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
-			Para.Para32[1] = NetIdx;
-			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
-
-			pAC->Rlmt.Net[NetIdx].ActivePort = i;
-			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
-			Para.Para32[1] = NetIdx;
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
-
-			if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-				(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
-				SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
-				CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
-				/*
-				 * Send announce packet to RLMT multicast address to force
-				 * switches to learn the new location of the logical MAC address.
-				 */
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG);
-		}
-
-		return;
-	}	/* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
-	else {	/* Cannot be reached in dual-net mode. */
-		Para.Para32[0] = Active;
-
-		/*
-		 * Preselection:
-		 *	If RLMT Mode != CheckLinkState
-		 *		select port that received a broadcast frame substantially later
-		 *		than all other ports
-		 *	else select first port that is not SuspectRx
-		 *	else select first port that is PortUp
-		 *	else select port that is PortGoingUp for the longest time
-		 *	else select first port that is PortDown
-		 *	else stop.
-		 *
-		 * For the preselected port:
-		 *	If ActivePort is equal in quality, select ActivePort.
-		 *
-		 *	If PrefPort is equal in quality, select PrefPort.
-		 *
-		 *	If ActivePort != SelectedPort,
-		 *		If old ActivePort is LinkDown,
-		 *			SwitchHard
-		 *		else
-		 *			SwitchSoft
-		 */
-		/* check of ChgBcPrio flag added */
-		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
-			(!pAC->Rlmt.Net[0].ChgBcPrio)) {
-			
-			if (!PortFound) {
-				PortFound = SkRlmtSelectBcRx(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectNotSuspect(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		/* with changed priority for last broadcast received */
-		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
-			(pAC->Rlmt.Net[0].ChgBcPrio)) {
-			if (!PortFound) {
-				PortFound = SkRlmtSelectNotSuspect(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectBcRx(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectGoingUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectGoingUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-		}
-
-		if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) {
-			if (!PortFound) {
-				PortFound = SkRlmtSelectDown(pAC, IoC,
-					Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectDown(pAC, IoC,
-					Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		if (PortFound) {
-
-			if (Para.Para32[1] != Active) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-					("Active: %d, Para1: %d.\n", Active, Para.Para32[1]))
-				pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
-				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-					Port[Para.Para32[0]]->PortNumber;
-				Para.Para32[1] = pAC->Rlmt.Net[NetIdx].
-					Port[Para.Para32[1]]->PortNumber;
-				SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE);
-				if (pAC->Rlmt.Port[Active].LinkDown) {
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para);
-				}
-				else {
-					SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para);
-				}
-				Para.Para32[1] = NetIdx;
-				Para.Para32[0] =
-					pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber;
-				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
-				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-					Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
-				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
-				if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-					(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0],
-					SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress,
-					&SkRlmtMcAddr)) != NULL) {
-					/*
-					 * Send announce packet to RLMT multicast address to force
-					 * switches to learn the new location of the logical
-					 * MAC address.
-					 */
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-				}	/* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
-			}	/* Para.Para32[1] != Active */
-		}	/* PortFound */
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG);
-		}
-	}	/* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
-	return;
-}	/* SkRlmtCheckSwitch */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckSeg - Report if segmentation is detected
- *
- * Description:
- *	This routine checks if the ports see different root bridges and reports
- *	segmentation in such a case.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtCheckSeg(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_U32	NetIdx)	/* Net number */
-{
-	SK_EVPARA	Para;
-	SK_RLMT_NET	*pNet;
-	SK_U32		i, j;
-	SK_BOOL		Equal;
-
-	pNet = &pAC->Rlmt.Net[NetIdx];
-	pNet->RootIdSet = SK_FALSE;
-	Equal = SK_TRUE;
-
-	for (i = 0; i < pNet->NumPorts; i++) {
-		if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) {
-			continue;
-		}
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
-			("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i,
-				pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
-				pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
-				pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
-				pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]))
-
-		if (!pNet->RootIdSet) {
-			pNet->Root = pNet->Port[i]->Root;
-			pNet->RootIdSet = SK_TRUE;
-			continue;
-		}
-
-		for (j = 0; j < 8; j ++) {
-			Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j];
-			if (!Equal) {
-				break;
-			}
-		}
-		
-		if (!Equal) {
-			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);
-			Para.Para32[0] = NetIdx;
-			Para.Para32[1] = (SK_U32)-1;
-			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para);
-
-			pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG;
-
-			/* 2000-03-06 RA: New. */
-			Para.Para32[0] = NetIdx;
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL,
-				SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-			break;
-		}
-	}	/* for (i = 0; i < pNet->NumPorts; i++) */
-
-	/* 2000-03-06 RA: Moved here. */
-	/* Segmentation check not running anymore. */
-	pNet->CheckingState &= ~SK_RLMT_RCS_SEG;
-
-}	/* SkRlmtCheckSeg */
-
-
-/******************************************************************************
- *
- *	SkRlmtPortStart - initialize port variables and start port
- *
- * Description:
- *	This routine initializes a port's variables and issues a PORT_START
- *	to the HWAC module.  This handles retries if the start fails or the
- *	link eventually goes down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtPortStart(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Port number */
-{
-	SK_EVPARA	Para;
-
-	pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN;
-	pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].CheckingState = 0;
-	pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
-	Para.Para32[0] = PortNumber;
-	Para.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-}	/* SkRlmtPortStart */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortStartTim - PORT_START_TIM
- *
- * Description:
- *	This routine handles PORT_START_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortStartTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_U32			i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]))
-
-		if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
-		return;
-	}
-
-	/*
-	 * Used to start non-preferred ports if the preferred one
-	 * does not come up.
-	 * This timeout needs only be set when starting the first
-	 * (preferred) port.
-	 */
-	if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
-		/* PORT_START failed. */
-		for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) {
-			if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) {
-				SkRlmtPortStart(pAC, IoC,
-					pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber);
-			}
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
-}	/* SkRlmtEvtPortStartTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtLinkUp - LINK_UP
- *
- * Description:
- *	This routine handles LLINK_UP events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtLinkUp(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
-{
-	SK_U32			i;
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (!pRPort->PortStarted) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_LINK_UP Event EMPTY.\n"))
-		return;
-	}
-
-	if (!pRPort->LinkDown) {
-		/* RA;:;: Any better solution? */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_LINK_UP Event EMPTY.\n"))
-		return;
-	}
-
-	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-	/* Do something if timer already fired? */
-
-	pRPort->LinkDown = SK_FALSE;
-	pRPort->PortState = SK_RLMT_PS_GOING_UP;
-	pRPort->GuTimeStamp = SkOsGetTime(pAC);
-	pRPort->BcTimeStamp = 0;
-	pRPort->Net->LinksUp++;
-	if (pRPort->Net->LinksUp == 1) {
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE);
-	}
-	else {
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
-	}
-
-	for (i = 0; i < pRPort->Net->NumPorts; i++) {
-		if (!pRPort->Net->Port[i]->PortStarted) {
-			SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber);
-		}
-	}
-
-	SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-
-	if (pRPort->Net->LinksUp >= 2) {
-		if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-		}
-	}
-
-	/* If the first link comes up, start the periodical RLMT timeout. */
-	if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 &&
-		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) {
-		Para2.Para32[0] = pRPort->Net->NetNumber;
-		Para2.Para32[1] = (SK_U32)-1;
-		SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer,
-			pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2);
-	}
-
-	Para2 = Para;
-	Para2.Para32[1] = (SK_U32)-1;
-	SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
-		SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
-	
-	/* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
-	if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
-		(Para2.pParaPtr =
-			SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
-			&pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
-		) != NULL) {
-		/* Send "new" packet to RLMT multicast address. */
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-	}
-
-	if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
-		if ((Para2.pParaPtr =
-			SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) {
-			pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE;
-			pRPort->Net->CheckingState |=
-				SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
-
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer,
-				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_UP Event END.\n"))
-}	/* SkRlmtEvtLinkUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortUpTim - PORT_UP_TIM
- *
- * Description:
- *	This routine handles PORT_UP_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortUpTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
-		return;
-	}
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]))
-		return;
-	}
-
-	pRPort->PortDown = SK_FALSE;
-	pRPort->PortState = SK_RLMT_PS_UP;
-	pRPort->Net->PortsUp++;
-	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
-		if (pAC->Rlmt.NumNets <= 1) {
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTUP_TIM Event END.\n"))
-}	/* SkRlmtEvtPortUpTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortDownTim - PORT_DOWN_*
- *
- * Description:
- *	This routine handles PORT_DOWN_* events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortDownX(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Event code */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
-			Para.Para32[0], Event))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
-		return;
-	}
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
-		!(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event))
-		return;
-	}
-	
-	/* Stop port's timers. */
-	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-	if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) {
-		pRPort->PortState = SK_RLMT_PS_DOWN;
-	}
-
-	if (!pRPort->PortDown) {
-		pRPort->Net->PortsUp--;
-		pRPort->PortDown = SK_TRUE;
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para);
-	}
-
-	pRPort->PacketsPerTimeSlot = 0;
-	/* pRPort->DataPacketsPerTimeSlot = 0; */
-	pRPort->BpduPacketsPerTimeSlot = 0;
-	pRPort->BcTimeStamp = 0;
-
-	/*
-	 * RA;:;: To be checked:
-	 * - actions at RLMT_STOP: We should not switch anymore.
-	 */
-	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
-		if (Para.Para32[0] ==
-			pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) {
-			/* Active Port went down. */
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event))
-}	/* SkRlmtEvtPortDownX */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtLinkDown - LINK_DOWN
- *
- * Description:
- *	This routine handles LINK_DOWN events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtLinkDown(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
-		pRPort->Net->LinksUp--;
-		pRPort->LinkDown = SK_TRUE;
-		pRPort->PortState = SK_RLMT_PS_LINK_DOWN;
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF);
-
-		if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) {
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-		}
-
-		/* Ensure that port is marked down. */
-		Para.Para32[1] = -1;
-		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_DOWN Event END.\n"))
-}	/* SkRlmtEvtLinkDown */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortAddr - PORT_ADDR
- *
- * Description:
- *	This routine handles PORT_ADDR events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortAddr(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_U32			i, j;
-	SK_RLMT_PORT	*pRPort;
-	SK_MAC_ADDR		*pOldMacAddr;
-	SK_MAC_ADDR		*pNewMacAddr;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
-		return;
-	}
-
-	/* Port's physical MAC address changed. */
-	pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress;
-	pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress;
-
-	/*
-	 * NOTE: This is not scalable for solutions where ports are
-	 *	 checked remotely.  There, we need to send an RLMT
-	 *	 address change packet - and how do we ensure delivery?
-	 */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		pRPort = &pAC->Rlmt.Port[i];
-		for (j = 0; j < pRPort->PortsChecked; j++) {
-			if (SK_ADDR_EQUAL(
-				pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) {
-				pRPort->PortCheck[j].CheckAddr = *pNewMacAddr;
-			}
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORT_ADDR Event END.\n"))
-}	/* SkRlmtEvtPortAddr */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStart - START
- *
- * Description:
- *	This routine handles START events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStart(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_EVPARA	Para2;
-	SK_U32		PortIdx;
-	SK_U32		PortNumber;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("All nets should have been started.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >=
-		pAC->Rlmt.Net[Para.Para32[0]].NumPorts) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG);
-
-		/* Change PrefPort to internal default. */
-		Para2.Para32[0] = 0xFFFFFFFF;
-		Para2.Para32[1] = Para.Para32[0];
-		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2);
-	}
-
-	PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort;
-	PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber;
-
-	pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN;
-
-	/* Start preferred port. */
-	SkRlmtPortStart(pAC, IoC, PortNumber);
-
-	/* Start Timer (for first port only). */
-	Para2.Para32[0] = PortNumber;
-	Para2.Para32[1] = (SK_U32)-1;
-	SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer,
-		SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2);
-
-	pAC->Rlmt.NetsStarted++;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event END.\n"))
-}	/* SkRlmtEvtStart */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStop - STOP
- *
- * Description:
- *	This routine handles STOP events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStop(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_EVPARA	Para2;
-	SK_U32		PortNumber;
-	SK_U32		i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.NetsStarted == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("All nets are stopped.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	/* Stop RLMT timers. */
-	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer);
-	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer);
-
-	/* Stop net. */
-	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT;
-	pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE;
-	Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
-	Para2.Para32[1] = Para.Para32[0];			/* Net# */
-	SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
-
-	/* Stop ports. */
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
-		if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) {
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer);
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer);
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer);
-
-			pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT;
-			pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE;
-			Para2.Para32[0] = PortNumber;
-			Para2.Para32[1] = (SK_U32)-1;
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2);
-		}
-	}
-
-	pAC->Rlmt.NetsStarted--;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STOP Event END.\n"))
-}	/* SkRlmtEvtStop */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtTim - TIM
- *
- * Description:
- *	This routine handles TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-	SK_U32			Timeout;
-	SK_U32			NewTimeout;
-	SK_U32			PortNumber;
-	SK_U32			i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_TIM Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_TIM Event EMPTY.\n"))
-		return;
-	}
-
-	if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 ||
-		pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) {
-		/* Mode changed or all links down: No more link checking. */
-		return;
-	}
-
-#if 0
-	pAC->Rlmt.SwitchCheckCounter--;
-	if (pAC->Rlmt.SwitchCheckCounter == 0) {
-		pAC->Rlmt.SwitchCheckCounter;
-	}
-#endif	/* 0 */
-
-	NewTimeout = SK_RLMT_DEF_TO_VAL;
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
-		pRPort = &pAC->Rlmt.Port[PortNumber];
-		if (!pRPort->LinkDown) {
-			Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber);
-			if (Timeout < NewTimeout) {
-				NewTimeout = Timeout;
-			}
-
-			/*
-			 * These counters should be set to 0 for all ports before the
-			 * first frame is sent in the next loop.
-			 */
-			pRPort->PacketsPerTimeSlot = 0;
-			/* pRPort->DataPacketsPerTimeSlot = 0; */
-			pRPort->BpduPacketsPerTimeSlot = 0;
-		}
-	}
-	pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout;
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) {
-		/*
-		 * If checking remote ports, also send packets if
-		 *   (LinksUp == 1) &&
-		 *   this port checks at least one (remote) port.
-		 */
-
-		/*
-		 * Must be new loop, as SkRlmtCheckPort can request to
-		 * check segmentation when e.g. checking the last port.
-		 */
-		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-			if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) {
-				SkRlmtSend(pAC, IoC,
-					pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber);
-			}
-		}
-	}
-
-	SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer,
-		pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM,
-		Para);
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 &&
-		(pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) &&
-		(pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) {
-		SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer,
-			SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-		pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG;
-		pAC->Rlmt.Net[Para.Para32[0]].CheckingState |=
-			SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_TIM Event END.\n"))
-}	/* SkRlmtEvtTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtSegTim - SEG_TIM
- *
- * Description:
- *	This routine handles SEG_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtSegTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-#ifdef xDEBUG
-	int j;
-#endif	/* DEBUG */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SEG_TIM Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SEG_TIM Event EMPTY.\n"))
-		return;
-	}
-
-#ifdef xDEBUG
-	for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) {
-		SK_ADDR_PORT	*pAPort;
-		SK_U32			k;
-		SK_U16			*InAddr;
-		SK_U8			InAddr8[6];
-
-		InAddr = (SK_U16 *)&InAddr8[0];
-		pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort;
-		for (k = 0; k < pAPort->NextExactMatchRlmt; k++) {
-			/* Get exact match address k from port j. */
-			XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
-				XM_EXM(k), InAddr);
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x --  %02x %02x %02x %02x %02x %02x.\n",
-					k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
-					InAddr8[0], InAddr8[1], InAddr8[2],
-					InAddr8[3], InAddr8[4], InAddr8[5],
-					pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
-					pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
-					pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]))
-		}
-	}
-#endif	/* xDEBUG */
-				
-	SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SEG_TIM Event END.\n"))
-}	/* SkRlmtEvtSegTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPacketRx - PACKET_RECEIVED
- *
- * Description:
- *	This routine handles PACKET_RECEIVED events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPacketRx(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_MBUF *pMb */
-{
-	SK_MBUF	*pMb;
-	SK_MBUF	*pNextMb;
-	SK_U32	NetNumber;
-
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
-
-	/* Should we ignore frames during port switching? */
-
-#ifdef DEBUG
-	pMb = Para.pParaPtr;
-	if (pMb == NULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"))
-	}
-	else if (pMb->pNext != NULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("More than one mbuf or pMb->pNext not set.\n"))
-	}
-#endif	/* DEBUG */
-
-	for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) {
-		pNextMb = pMb->pNext;
-		pMb->pNext = NULL;
-
-		NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber;
-		if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) {
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		}
-		else {
-			SkRlmtPacketReceive(pAC, IoC, pMb);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PACKET_RECEIVED Event END.\n"))
-}	/* SkRlmtEvtPacketRx */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStatsClear - STATS_CLEAR
- *
- * Description:
- *	This routine handles STATS_CLEAR events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStatsClear(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_U32			i;
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
-		return;
-	}
-
-	/* Clear statistics for logical and physical ports. */
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		pRPort =
-			&pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber];
-		pRPort->TxHelloCts = 0;
-		pRPort->RxHelloCts = 0;
-		pRPort->TxSpHelloReqCts = 0;
-		pRPort->RxSpHelloCts = 0;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_CLEAR Event END.\n"))
-}	/* SkRlmtEvtStatsClear */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStatsUpdate - STATS_UPDATE
- *
- * Description:
- *	This routine handles STATS_UPDATE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStatsUpdate(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
-		return;
-	}
-
-	/* Update statistics - currently always up-to-date. */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_UPDATE Event END.\n"))
-}	/* SkRlmtEvtStatsUpdate */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPrefportChange - PREFPORT_CHANGE
- *
- * Description:
- *	This routine handles PREFPORT_CHANGE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPrefportChange(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortIndex; SK_U32 NetNumber */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[1]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	/* 0xFFFFFFFF == auto-mode. */
-	if (Para.Para32[0] == 0xFFFFFFFF) {
-		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT;
-	}
-	else {
-		if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
-			return;
-		}
-
-		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0];
-	}
-
-	pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0];
-
-	if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
-		SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
-}	/* SkRlmtEvtPrefportChange */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtSetNets - SET_NETS
- *
- * Description:
- *	This routine handles SET_NETS events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtSetNets(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NumNets; SK_U32 -1 */
-{
-	int i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SET_NETS Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
-		Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad number of nets: %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == pAC->Rlmt.NumNets) {	/* No change. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	/* Entering and leaving dual mode only allowed while nets are stopped. */
-	if (pAC->Rlmt.NetsStarted > 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Changing dual mode only allowed while all nets are stopped.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == 1) {
-		if (pAC->Rlmt.NumNets > 1) {
-			/* Clear logical MAC addr from second net's active port. */
-			(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
-				Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL);
-			pAC->Rlmt.Net[1].NumPorts = 0;
-		}
-
-		pAC->Rlmt.NumNets = Para.Para32[0];
-		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0];
-		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("RLMT: Changed to one net with two ports.\n"))
-	}
-	else if (Para.Para32[0] == 2) {
-		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
-		pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
-		pAC->Rlmt.Net[0].NumPorts =
-			pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts;
-		
-		pAC->Rlmt.NumNets = Para.Para32[0];
-		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		/* Set logical MAC addr on second net's active port. */
-		(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
-			Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL);
-
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("RLMT: Changed to two nets with one port each.\n"))
-	}
-	else {
-		/* Not implemented for more than two nets. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SetNets not implemented for more than two nets.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SET_NETS Event END.\n"))
-}	/* SkRlmtSetNets */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtModeChange - MODE_CHANGE
- *
- * Description:
- *	This routine handles MODE_CHANGE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtModeChange(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NewMode; SK_U32 NetNumber */
-{
-	SK_EVPARA	Para2;
-	SK_U32		i;
-	SK_U32		PrevRlmtMode;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
-
-	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[1]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	Para.Para32[0] |= SK_RLMT_CHECK_LINK;
-
-	if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) &&
-		Para.Para32[0] != SK_RLMT_MODE_CLS) {
-		pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Forced RLMT mode to CLS on single port net.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	/* Update RLMT mode. */
-	PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode;
-	pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0];
-
-	if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) !=
-		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
-		/* SK_RLMT_CHECK_LOC_LINK bit changed. */
-		if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 &&
-			pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 &&
-			pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) {
-			/* 20001207 RA: Was "PortsUp == 1". */
-			Para2.Para32[0] = Para.Para32[1];
-			Para2.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer,
-				pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue,
-				SKGE_RLMT, SK_RLMT_TIM, Para2);
-		}
-	}
-
-	if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) !=
-		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) {
-		/* SK_RLMT_CHECK_SEG bit changed. */
-		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) {
-			(void)SkAddrMcClear(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-				SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-
-			/* Add RLMT MC address. */
-			(void)SkAddrMcAdd(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-				&SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
-			if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode &
-				SK_RLMT_CHECK_SEG) != 0) {
-				/* Add BPDU MC address. */
-				(void)SkAddrMcAdd(pAC, IoC,
-					pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-					&BridgeMcAddr, SK_ADDR_PERMANENT);
-
-				if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
-					if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown &&
-						(Para2.pParaPtr = SkRlmtBuildSpanningTreePacket(
-						pAC, IoC, i)) != NULL) {
-						pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet =
-							SK_FALSE;
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-					}
-				}
-			}
-			(void)SkAddrMcUpdate(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber);
-		}	/* for ... */
-
-		if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) {
-			Para2.Para32[0] = Para.Para32[1];
-			Para2.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer,
-				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2);
-		}
-	}	/* SK_RLMT_CHECK_SEG bit changed. */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event END.\n"))
-}	/* SkRlmtEvtModeChange */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvent - a PORT- or an RLMT-specific event happened
- *
- * Description:
- *	This routine calls subroutines to handle PORT- and RLMT-specific events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	0
- */
-int	SkRlmtEvent(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Event code */
-SK_EVPARA	Para)	/* Event-specific parameter */
-{
-	switch (Event) {
-	
-	/* ----- PORT events ----- */
-
-	case SK_RLMT_PORTSTART_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortStartTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_LINK_UP:		/* From SIRQ. */
-		SkRlmtEvtLinkUp(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORTUP_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortUpTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORTDOWN:			/* From RLMT. */
-	case SK_RLMT_PORTDOWN_RX_TIM:	/* From RLMT via TIME. */
-	case SK_RLMT_PORTDOWN_TX_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortDownX(pAC, IoC, Event, Para);
-		break;
-	case SK_RLMT_LINK_DOWN:		/* From SIRQ. */
-		SkRlmtEvtLinkDown(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORT_ADDR:		/* From ADDR. */
-		SkRlmtEvtPortAddr(pAC, IoC, Para);
-		break;
-
-	/* ----- RLMT events ----- */
-
-	case SK_RLMT_START:		/* From DRV. */
-		SkRlmtEvtStart(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STOP:		/* From DRV. */
-		SkRlmtEvtStop(pAC, IoC, Para);
-		break;
-	case SK_RLMT_TIM:		/* From RLMT via TIME. */
-		SkRlmtEvtTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_SEG_TIM:
-		SkRlmtEvtSegTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PACKET_RECEIVED:	/* From DRV. */
-		SkRlmtEvtPacketRx(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STATS_CLEAR:	/* From PNMI. */
-		SkRlmtEvtStatsClear(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STATS_UPDATE:	/* From PNMI. */
-		SkRlmtEvtStatsUpdate(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PREFPORT_CHANGE:	/* From PNMI. */
-		SkRlmtEvtPrefportChange(pAC, IoC, Para);
-		break;
-	case SK_RLMT_MODE_CHANGE:	/* From PNMI. */
-		SkRlmtEvtModeChange(pAC, IoC, Para);
-		break;
-	case SK_RLMT_SET_NETS:	/* From DRV. */
-		SkRlmtEvtSetNets(pAC, IoC, Para);
-		break;
-
-	/* ----- Unknown events ----- */
-
-	default:	/* Create error log entry. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Unknown RLMT Event %d.\n", Event))
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
-		break;
-	}	/* switch() */
-
-	return (0);
-}	/* SkRlmtEvent */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
deleted file mode 100644
index 4e46295..0000000
--- a/drivers/net/sk98lin/sktimer.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktimer.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.14 $
- * Date:	$Date: 2003/09/16 13:46:51 $
- * Purpose:	High level timer functions.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	Event queue management.
-
-	General Description:
-
- */
-intro()
-{}
-#endif
-
-
-/* Forward declaration */
-static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
-
-
-/*
- * Inits the software timer
- *
- * needs to be called during Init level 1.
- */
-void	SkTimerInit(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc,		/* IoContext */
-int		Level)		/* Init Level */
-{
-	switch (Level) {
-	case SK_INIT_DATA:
-		pAC->Tim.StQueue = NULL;
-		break;
-	case SK_INIT_IO:
-		SkHwtInit(pAC, Ioc);
-		SkTimerDone(pAC, Ioc);
-		break;
-	default:
-		break;
-	}
-}
-
-/*
- * Stops a high level timer
- * - If a timer is not in the queue the function returns normally, too.
- */
-void	SkTimerStop(
-SK_AC		*pAC,		/* Adapters context */
-SK_IOC		Ioc,		/* IoContext */
-SK_TIMER	*pTimer)	/* Timer Pointer to be started */
-{
-	SK_TIMER	**ppTimPrev;
-	SK_TIMER	*pTm;
-
-	/*
-	 * remove timer from queue
-	 */
-	pTimer->TmActive = SK_FALSE;
-	
-	if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
-		SkHwtStop(pAC, Ioc);
-	}
-	
-	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
-		ppTimPrev = &pTm->TmNext ) {
-		
-		if (pTm == pTimer) {
-			/*
-			 * Timer found in queue
-			 * - dequeue it and
-			 * - correct delta of the next timer
-			 */
-			*ppTimPrev = pTm->TmNext;
-
-			if (pTm->TmNext) {
-				/* correct delta of next timer in queue */
-				pTm->TmNext->TmDelta += pTm->TmDelta;
-			}
-			return;
-		}
-	}
-}
-
-/*
- * Start a high level software timer
- */
-void	SkTimerStart(
-SK_AC		*pAC,		/* Adapters context */
-SK_IOC		Ioc,		/* IoContext */
-SK_TIMER	*pTimer,	/* Timer Pointer to be started */
-SK_U32		Time,		/* Time value */
-SK_U32		Class,		/* Event Class for this timer */
-SK_U32		Event,		/* Event Value for this timer */
-SK_EVPARA	Para)		/* Event Parameter for this timer */
-{
-	SK_TIMER	**ppTimPrev;
-	SK_TIMER	*pTm;
-	SK_U32		Delta;
-
-	Time /= 16;		/* input is uS, clock ticks are 16uS */
-	
-	if (!Time)
-		Time = 1;
-
-	SkTimerStop(pAC, Ioc, pTimer);
-
-	pTimer->TmClass = Class;
-	pTimer->TmEvent = Event;
-	pTimer->TmPara = Para;
-	pTimer->TmActive = SK_TRUE;
-
-	if (!pAC->Tim.StQueue) {
-		/* First Timer to be started */
-		pAC->Tim.StQueue = pTimer;
-		pTimer->TmNext = NULL;
-		pTimer->TmDelta = Time;
-		
-		SkHwtStart(pAC, Ioc, Time);
-		
-		return;
-	}
-
-	/*
-	 * timer correction
-	 */
-	timer_done(pAC, Ioc, 0);
-
-	/*
-	 * find position in queue
-	 */
-	Delta = 0;
-	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
-		ppTimPrev = &pTm->TmNext ) {
-		
-		if (Delta + pTm->TmDelta > Time) {
-			/* Position found */
-			/* Here the timer needs to be inserted. */
-			break;
-		}
-		Delta += pTm->TmDelta;
-	}
-
-	/* insert in queue */
-	*ppTimPrev = pTimer;
-	pTimer->TmNext = pTm;
-	pTimer->TmDelta = Time - Delta;
-
-	if (pTm) {
-		/* There is a next timer
-		 * -> correct its Delta value.
-		 */
-		pTm->TmDelta -= pTimer->TmDelta;
-	}
-
-	/* restart with first */
-	SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
-}
-
-
-void	SkTimerDone(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc)		/* IoContext */
-{
-	timer_done(pAC, Ioc, 1);
-}
-
-
-static void	timer_done(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc,		/* IoContext */
-int		Restart)	/* Do we need to restart the Hardware timer ? */
-{
-	SK_U32		Delta;
-	SK_TIMER	*pTm;
-	SK_TIMER	*pTComp;	/* Timer completed now now */
-	SK_TIMER	**ppLast;	/* Next field of Last timer to be deq */
-	int		Done = 0;
-
-	Delta = SkHwtRead(pAC, Ioc);
-	
-	ppLast = &pAC->Tim.StQueue;
-	pTm = pAC->Tim.StQueue;
-	while (pTm && !Done) {
-		if (Delta >= pTm->TmDelta) {
-			/* Timer ran out */
-			pTm->TmActive = SK_FALSE;
-			Delta -= pTm->TmDelta;
-			ppLast = &pTm->TmNext;
-			pTm = pTm->TmNext;
-		}
-		else {
-			/* We found the first timer that did not run out */
-			pTm->TmDelta -= Delta;
-			Delta = 0;
-			Done = 1;
-		}
-	}
-	*ppLast = NULL;
-	/*
-	 * pTm points to the first Timer that did not run out.
-	 * StQueue points to the first Timer that run out.
-	 */
-
-	for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
-		SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
-	}
-
-	/* Set head of timer queue to the first timer that did not run out */
-	pAC->Tim.StQueue = pTm;
-
-	if (Restart && pAC->Tim.StQueue) {
-		/* Restart HW timer */
-		SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
-	}
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
deleted file mode 100644
index 1e662aa..0000000
--- a/drivers/net/sk98lin/skvpd.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/******************************************************************************
- *
- * Name:	skvpd.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.37 $
- * Date:	$Date: 2003/01/13 10:42:45 $
- * Purpose:	Shared software to read and write VPD data
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2003 SysKonnect GmbH.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-	Please refer skvpd.txt for information how to include this module
- */
-static const char SysKonnectFileId[] =
-	"@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/skdebug.h"
-#include "h/skdrv2nd.h"
-
-/*
- * Static functions
- */
-#ifndef SK_KR_PROTO
-static SK_VPD_PARA	*vpd_find_para(
-	SK_AC	*pAC,
-	const char	*key,
-	SK_VPD_PARA *p);
-#else	/* SK_KR_PROTO */
-static SK_VPD_PARA	*vpd_find_para();
-#endif	/* SK_KR_PROTO */
-
-/*
- * waits for a completion of a VPD transfer
- * The VPD transfer must complete within SK_TICKS_PER_SEC/16
- *
- * returns	0:	success, transfer completes
- *		error	exit(9) with a error message
- */
-static int VpdWait(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-int		event)	/* event to wait for (VPD_READ / VPD_write) completion*/
-{
-	SK_U64	start_time;
-	SK_U16	state;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD wait for %s\n", event?"Write":"Read"));
-	start_time = SkOsGetTime(pAC);
-	do {
-		if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
-
-			/* Bug fix AF: Thu Mar 28 2002
-			 * Do not call: VPD_STOP(pAC, IoC);
-			 * A pending VPD read cycle can not be aborted by writing
-			 * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
-			 * Although the write threshold in the OUR-register protects
-			 * VPD read only space from being overwritten this does not
-			 * protect a VPD read from being `converted` into a VPD write
-			 * operation (on the fly). As a consequence the VPD_STOP would
-			 * delete VPD read only data. In case of any problems with the
-			 * I2C bus we exit the loop here. The I2C read operation can
-			 * not be aborted except by a reset (->LR).
-			 */
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
-				("ERROR:VPD wait timeout\n"));
-			return(1);
-		}
-		
-		VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("state = %x, event %x\n",state,event));
-	} while((int)(state & PCI_VPD_FLAG) == event);
-
-	return(0);
-}
-
-#ifdef SKDIAG
-
-/*
- * Read the dword at address 'addr' from the VPD EEPROM.
- *
- * Needed Time:	MIN 1,3 ms	MAX 2,6 ms
- *
- * Note: The DWord is returned in the endianess of the machine the routine
- *       is running on.
- *
- * Returns the data read.
- */
-SK_U32 VpdReadDWord(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-int		addr)	/* VPD address */
-{
-	SK_U32	Rtv;
-
-	/* start VPD read */
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD read dword at 0x%x\n",addr));
-	addr &= ~VPD_WRITE;		/* ensure the R/W bit is set to read */
-
-	VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
-
-	/* ignore return code here */
-	(void)VpdWait(pAC, IoC, VPD_READ);
-
-	/* Don't swap here, it's a data stream of bytes */
-	Rtv = 0;
-
-	VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD read dword data = 0x%x\n",Rtv));
-	return(Rtv);
-}
-
-#endif	/* SKDIAG */
-
-/*
- *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdWriteStream(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		Addr,	/* VPD start address */
-int		Len)	/* number of bytes to read / to write */
-{
-	int		i;
-	int		j;
-	SK_U16	AdrReg;
-	int		Rtv;
-	SK_U8	* pComp;	/* Compare pointer */
-	SK_U8	Data;		/* Input Data for Compare */
-
-	/* Init Compare Pointer */
-	pComp = (SK_U8 *) buf;
-
-	for (i = 0; i < Len; i++, buf++) {
-		if ((i%sizeof(SK_U32)) == 0) {
-			/*
-			 * At the begin of each cycle read the Data Reg
-			 * So it is initialized even if only a few bytes
-			 * are written.
-			 */
-			AdrReg = (SK_U16) Addr;
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				return(i);
-			}
-		}
-
-		/* Write current Byte */
-		VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
-				*(SK_U8*)buf);
-
-		if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
-			/* New Address needs to be written to VPD_ADDR reg */
-			AdrReg = (SK_U16) Addr;
-			Addr += sizeof(SK_U32);
-			AdrReg |= VPD_WRITE;	/* WRITE operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_WRITE);
-			if (Rtv != 0) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-					("Write Timed Out\n"));
-				return(i - (i%sizeof(SK_U32)));
-			}
-
-			/*
-			 * Now re-read to verify
-			 */
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-					("Verify Timed Out\n"));
-				return(i - (i%sizeof(SK_U32)));
-			}
-
-			for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
-				
-				VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
-				
-				if (Data != *pComp) {
-					/* Verify Error */
-					SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-						("WriteStream Verify Error\n"));
-					return(i - (i%sizeof(SK_U32)) + j);
-				}
-			}
-		}
-	}
-
-	return(Len);
-}
-	
-
-/*
- *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdReadStream(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		Addr,	/* VPD start address */
-int		Len)	/* number of bytes to read / to write */
-{
-	int		i;
-	SK_U16	AdrReg;
-	int		Rtv;
-
-	for (i = 0; i < Len; i++, buf++) {
-		if ((i%sizeof(SK_U32)) == 0) {
-			/* New Address needs to be written to VPD_ADDR reg */
-			AdrReg = (SK_U16) Addr;
-			Addr += sizeof(SK_U32);
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				return(i);
-			}
-		}
-		VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
-			(SK_U8 *)buf);
-	}
-
-	return(Len);
-}
-
-/*
- *	Read ore writes 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdTransferBlock(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		addr,	/* VPD start address */
-int		len,	/* number of bytes to read / to write */
-int		dir)	/* transfer direction may be VPD_READ or VPD_WRITE */
-{
-	int		Rtv;	/* Return value */
-	int		vpd_rom_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD %s block, addr = 0x%x, len = %d\n",
-		dir ? "write" : "read", addr, len));
-
-	if (len == 0)
-		return(0);
-
-	vpd_rom_size = pAC->vpd.rom_size;
-	
-	if (addr > vpd_rom_size - 4) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Address error: 0x%x, exp. < 0x%x\n",
-			addr, vpd_rom_size - 4));
-		return(0);
-	}
-	
-	if (addr + len > vpd_rom_size) {
-		len = vpd_rom_size - addr;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("Warning: len was cut to %d\n", len));
-	}
-
-	if (dir == VPD_READ) {
-		Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
-	}
-	else {
-		Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
-	}
-
-	return(Rtv);
-}
-
-#ifdef SKDIAG
-
-/*
- *	Read 'len' bytes of VPD data, starting at 'addr'.
- *
- * Returns number of bytes read.
- */
-int VpdReadBlock(
-SK_AC	*pAC,	/* pAC pointer */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* buffer were the data should be stored */
-int		addr,	/* start reading at the VPD address */
-int		len)	/* number of bytes to read */
-{
-	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
-}
-
-/*
- *	Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
- *
- * Returns number of bytes writes.
- */
-int VpdWriteBlock(
-SK_AC	*pAC,	/* pAC pointer */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* buffer, holds the data to write */
-int		addr,	/* start writing at the VPD address */
-int		len)	/* number of bytes to write */
-{
-	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
-}
-#endif	/* SKDIAG */
-
-/*
- * (re)initialize the VPD buffer
- *
- * Reads the VPD data from the EEPROM into the VPD buffer.
- * Get the remaining read only and read / write space.
- *
- * return	0:	success
- *		1:	fatal VPD error
- */
-static int VpdInit(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	SK_VPD_PARA *r, rp;	/* RW or RV */
-	int		i;
-	unsigned char	x;
-	int		vpd_size;
-	SK_U16	dev_id;
-	SK_U32	our_reg2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
-	
-	VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
-	
-	VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
-	
-	pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
-	
-	/*
-	 * this function might get used before the hardware is initialized
-	 * therefore we cannot always trust in GIChipId
-	 */
-	if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
-		dev_id != VPD_DEV_ID_GENESIS) ||
-		((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
-		!pAC->GIni.GIGenesis)) {
-
-		/* for Yukon the VPD size is always 256 */
-		vpd_size = VPD_SIZE_YUKON;
-	}
-	else {
-		/* Genesis uses the maximum ROM size up to 512 for VPD */
-		if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
-			vpd_size = VPD_SIZE_GENESIS;
-		}
-		else {
-			vpd_size = pAC->vpd.rom_size;
-		}
-	}
-
-	/* read the VPD data into the VPD buffer */
-	if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
-		!= vpd_size) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("Block Read Error\n"));
-		return(1);
-	}
-	
-	pAC->vpd.vpd_size = vpd_size;
-
-	/* Asus K8V Se Deluxe bugfix. Correct VPD content */
-	/* MBo April 2004 */
-	if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
-	    ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
-	    ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
-		printk("sk98lin: Asus mainboard with buggy VPD? "
-				"Correcting data.\n");
-		pAC->vpd.vpd_buf[0x40] = 0x38;
-	}
-
-
-	/* find the end tag of the RO area */
-	if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: RV Tag not found\n"));
-		return(1);
-	}
-	
-	if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: Invalid VPD struct size\n"));
-		return(1);
-	}
-	pAC->vpd.v.vpd_free_ro = r->p_len - 1;
-
-	/* test the checksum */
-	for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
-		x += pAC->vpd.vpd_buf[i];
-	}
-	
-	if (x != 0) {
-		/* checksum error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("VPD Checksum Error\n"));
-		return(1);
-	}
-
-	/* find and check the end tag of the RW area */
-	if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: RV Tag not found\n"));
-		return(1);
-	}
-	
-	if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: Invalid VPD struct size\n"));
-		return(1);
-	}
-	pAC->vpd.v.vpd_free_rw = r->p_len;
-
-	/* everything seems to be ok */
-	if (pAC->GIni.GIChipId != 0) {
-		pAC->vpd.v.vpd_status |= VPD_VALID;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
-		("done. Free RO = %d, Free RW = %d\n",
-		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
-	return(0);
-}
-
-/*
- *	find the Keyword 'key' in the VPD buffer and fills the
- *	parameter struct 'p' with it's values
- *
- * returns	*p	success
- *		0:	parameter was not found or VPD encoding error
- */
-static SK_VPD_PARA *vpd_find_para(
-SK_AC		*pAC,	/* common data base */
-const char	*key,	/* keyword to find (e.g. "MN") */
-SK_VPD_PARA *p)		/* parameter description struct */
-{
-	char *v	;	/* points to VPD buffer */
-	int max;	/* Maximum Number of Iterations */
-
-	v = pAC->vpd.vpd_buf;
-	max = 128;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD find para %s .. ",key));
-
-	/* check mandatory resource type ID string (Product Name) */
-	if (*v != (char)RES_ID) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Error: 0x%x missing\n", RES_ID));
-		return NULL;
-	}
-
-	if (strcmp(key, VPD_NAME) == 0) {
-		p->p_len = VPD_GET_RES_LEN(v);
-		p->p_val = VPD_GET_VAL(v);
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("found, len = %d\n", p->p_len));
-		return(p);
-	}
-
-	v += 3 + VPD_GET_RES_LEN(v) + 3;
-	for (;; ) {
-		if (SK_MEMCMP(key,v,2) == 0) {
-			p->p_len = VPD_GET_VPD_LEN(v);
-			p->p_val = VPD_GET_VAL(v);
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("found, len = %d\n",p->p_len));
-			return(p);
-		}
-
-		/* exit when reaching the "RW" Tag or the maximum of itera. */
-		max--;
-		if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
-			break;
-		}
-
-		if (SK_MEMCMP(VPD_RV,v,2) == 0) {
-			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
-		}
-		else {
-			v += 3 + VPD_GET_VPD_LEN(v);
-		}
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
-	}
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
-	if (max == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Key/Len Encoding error\n"));
-	}
-#endif /* DEBUG */
-	return NULL;
-}
-
-/*
- *	Move 'n' bytes. Begin with the last byte if 'n' is > 0,
- *	Start with the last byte if n is < 0.
- *
- * returns nothing
- */
-static void vpd_move_para(
-char	*start,		/* start of memory block */
-char	*end,		/* end of memory block to move */
-int		n)			/* number of bytes the memory block has to be moved */
-{
-	char *p;
-	int i;		/* number of byte copied */
-
-	if (n == 0)
-		return;
-
-	i = (int) (end - start + 1);
-	if (n < 0) {
-		p = start + n;
-		while (i != 0) {
-			*p++ = *start++;
-			i--;
-		}
-	}
-	else {
-		p = end + n;
-		while (i != 0) {
-			*p-- = *end--;
-			i--;
-		}
-	}
-}
-
-/*
- *	setup the VPD keyword 'key' at 'ip'.
- *
- * returns nothing
- */
-static void vpd_insert_key(
-const char	*key,	/* keyword to insert */
-const char	*buf,	/* buffer with the keyword value */
-int		len,		/* length of the value string */
-char	*ip)		/* inseration point */
-{
-	SK_VPD_KEY *p;
-
-	p = (SK_VPD_KEY *) ip;
-	p->p_key[0] = key[0];
-	p->p_key[1] = key[1];
-	p->p_len = (unsigned char) len;
-	SK_MEMCPY(&p->p_val,buf,len);
-}
-
-/*
- *	Setup the VPD end tag "RV" / "RW".
- *	Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
- *
- * returns	0:	success
- *		1:	encoding error
- */
-static int vpd_mod_endtag(
-SK_AC	*pAC,		/* common data base */
-char	*etp)		/* end pointer input position */
-{
-	SK_VPD_KEY *p;
-	unsigned char	x;
-	int	i;
-	int	vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	p = (SK_VPD_KEY *) etp;
-
-	if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
-		/* something wrong here, encoding error */
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: invalid end tag\n"));
-		return(1);
-	}
-	if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
-		/* create "RW" tag */
-		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
-		pAC->vpd.v.vpd_free_rw = (int) p->p_len;
-		i = pAC->vpd.v.vpd_free_rw;
-		etp += 3;
-	}
-	else {
-		/* create "RV" tag */
-		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
-		pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
-
-		/* setup checksum */
-		for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
-			x += pAC->vpd.vpd_buf[i];
-		}
-		p->p_val = (char) 0 - x;
-		i = pAC->vpd.v.vpd_free_ro;
-		etp += 4;
-	}
-	while (i) {
-		*etp++ = 0x00;
-		i--;
-	}
-
-	return(0);
-}
-
-/*
- *	Insert a VPD keyword into the VPD buffer.
- *
- *	The keyword 'key' is inserted at the position 'ip' in the
- *	VPD buffer.
- *	The keywords behind the input position will
- *	be moved. The VPD end tag "RV" or "RW" is generated again.
- *
- * returns	0:	success
- *		2:	value string was cut
- *		4:	VPD full, keyword was not written
- *		6:	fatal VPD error
- *
- */
-static int	VpdSetupPara(
-SK_AC	*pAC,		/* common data base */
-const char	*key,	/* keyword to insert */
-const char	*buf,	/* buffer with the keyword value */
-int		len,		/* length of the keyword value */
-int		type,		/* VPD_RO_KEY or VPD_RW_KEY */
-int		op)			/* operation to do: ADD_KEY or OWR_KEY */
-{
-	SK_VPD_PARA vp;
-	char	*etp;		/* end tag position */
-	int	free;		/* remaining space in selected area */
-	char	*ip;		/* input position inside the VPD buffer */
-	int	rtv;		/* return code */
-	int	head;		/* additional haeder bytes to move */
-	int	found;		/* additinoal bytes if the keyword was found */
-	int vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD setup para key = %s, val = %s\n",key,buf));
-	
-	vpd_size = pAC->vpd.vpd_size;
-
-	rtv = 0;
-	ip = NULL;
-	if (type == VPD_RW_KEY) {
-		/* end tag is "RW" */
-		free = pAC->vpd.v.vpd_free_rw;
-		etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
-	}
-	else {
-		/* end tag is "RV" */
-		free = pAC->vpd.v.vpd_free_ro;
-		etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
-	}
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("Free RO = %d, Free RW = %d\n",
-		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
-	head = 0;
-	found = 0;
-	if (op == OWR_KEY) {
-		if (vpd_find_para(pAC, key, &vp)) {
-			found = 3;
-			ip = vp.p_val - 3;
-			free += vp.p_len + 3;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("Overwrite Key\n"));
-		}
-		else {
-			op = ADD_KEY;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("Add Key\n"));
-		}
-	}
-	if (op == ADD_KEY) {
-		ip = etp;
-		vp.p_len = 0;
-		head = 3;
-	}
-
-	if (len + 3 > free) {
-		if (free < 7) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD Buffer Overflow, keyword not written\n"));
-			return(4);
-		}
-		/* cut it again */
-		len = free - 3;
-		rtv = 2;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD Buffer Full, Keyword was cut\n"));
-	}
-
-	vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
-	vpd_insert_key(key, buf, len, ip);
-	if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
-		pAC->vpd.v.vpd_status &= ~VPD_VALID;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD Encoding Error\n"));
-		return(6);
-	}
-
-	return(rtv);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done.
- *
- * return:	A pointer to the vpd_status structure. The structure contains
- *		this fields.
- */
-SK_VPD_STATUS *VpdStat(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		(void)VpdInit(pAC, IoC);
-	}
-	return(&pAC->vpd.v);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the VPD
- *	buffer if not already done.
- *	Scan the VPD buffer for VPD keywords and create the VPD
- *	keyword list by copying the keywords to 'buf', all after
- *	each other and terminated with a '\0'.
- *
- * Exceptions:	o The Resource Type ID String (product name) is called "Name"
- *		o The VPD end tags 'RV' and 'RW' are not listed
- *
- *	The number of copied keywords is counted in 'elements'.
- *
- * returns	0:	success
- *		2:	buffer overfull, one or more keywords are missing
- *		6:	fatal VPD error
- *
- *	example values after returning:
- *
- *		buf =	"Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
- *		*len =		30
- *		*elements =	 9
- */
-int VpdKeys(
-SK_AC	*pAC,		/* common data base */
-SK_IOC	IoC,		/* IO Context */
-char	*buf,		/* buffer where to copy the keywords */
-int		*len,		/* buffer length */
-int		*elements)	/* number of keywords returned */
-{
-	char *v;
-	int n;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
-	*elements = 0;
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			*len = 0;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD Init Error, terminated\n"));
-			return(6);
-		}
-	}
-
-	if ((signed)strlen(VPD_NAME) + 1 <= *len) {
-		v = pAC->vpd.vpd_buf;
-		strcpy(buf,VPD_NAME);
-		n = strlen(VPD_NAME) + 1;
-		buf += n;
-		*elements = 1;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-			("'%c%c' ",v[0],v[1]));
-	}
-	else {
-		*len = 0;
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
-			("buffer overflow\n"));
-		return(2);
-	}
-
-	v += 3 + VPD_GET_RES_LEN(v) + 3;
-	for (;; ) {
-		/* exit when reaching the "RW" Tag */
-		if (SK_MEMCMP(VPD_RW,v,2) == 0) {
-			break;
-		}
-
-		if (SK_MEMCMP(VPD_RV,v,2) == 0) {
-			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
-			continue;
-		}
-
-		if (n+3 <= *len) {
-			SK_MEMCPY(buf,v,2);
-			buf += 2;
-			*buf++ = '\0';
-			n += 3;
-			v += 3 + VPD_GET_VPD_LEN(v);
-			*elements += 1;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-				("'%c%c' ",v[0],v[1]));
-		}
-		else {
-			*len = n;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("buffer overflow\n"));
-			return(2);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
-	*len = n;
-	return(0);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done. Search for the VPD keyword
- *	'key' and copy its value to 'buf'. Add a terminating '\0'.
- *	If the value does not fit into the buffer cut it after
- *	'len' - 1 bytes.
- *
- * returns	0:	success
- *		1:	keyword not found
- *		2:	value string was cut
- *		3:	VPD transfer timeout
- *		6:	fatal VPD error
- */
-int VpdRead(
-SK_AC		*pAC,	/* common data base */
-SK_IOC		IoC,	/* IO Context */
-const char	*key,	/* keyword to read (e.g. "MN") */
-char		*buf,	/* buffer where to copy the keyword value */
-int			*len)	/* buffer length */
-{
-	SK_VPD_PARA *p, vp;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			*len = 0;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
-		if (p->p_len > (*(unsigned *)len)-1) {
-			p->p_len = *len - 1;
-		}
-		SK_MEMCPY(buf, p->p_val, p->p_len);
-		buf[p->p_len] = '\0';
-		*len = p->p_len;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-			("%c%c%c%c.., len = %d\n",
-			buf[0],buf[1],buf[2],buf[3],*len));
-	}
-	else {
-		*len = 0;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
-		return(1);
-	}
-	return(0);
-}
-
-
-/*
- *	Check whether a given key may be written
- *
- * returns
- *	SK_TRUE		Yes it may be written
- *	SK_FALSE	No it may be written
- */
-SK_BOOL VpdMayWrite(
-char	*key)	/* keyword to write (allowed values "Yx", "Vx") */
-{
-	if ((*key != 'Y' && *key != 'V') ||
-		key[1] < '0' || key[1] > 'Z' ||
-		(key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
-		return(SK_FALSE);
-	}
-	return(SK_TRUE);
-}
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the VPD
- *	buffer if not already done. Insert/overwrite the keyword 'key'
- *	in the VPD buffer. Cut the keyword value if it does not fit
- *	into the VPD read / write area.
- *
- * returns	0:	success
- *		2:	value string was cut
- *		3:	VPD transfer timeout
- *		4:	VPD full, keyword was not written
- *		5:	keyword cannot be written
- *		6:	fatal VPD error
- */
-int VpdWrite(
-SK_AC		*pAC,	/* common data base */
-SK_IOC		IoC,	/* IO Context */
-const char	*key,	/* keyword to write (allowed values "Yx", "Vx") */
-const char	*buf)	/* buffer where the keyword value can be read from */
-{
-	int len;		/* length of the keyword to write */
-	int rtv;		/* return code */
-	int rtv2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
-		("VPD write %s = %s\n",key,buf));
-
-	if ((*key != 'Y' && *key != 'V') ||
-		key[1] < '0' || key[1] > 'Z' ||
-		(key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("illegal key tag, keyword not written\n"));
-		return(5);
-	}
-
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	rtv = 0;
-	len = strlen(buf);
-	if (len > VPD_MAX_LEN) {
-		/* cut it */
-		len = VPD_MAX_LEN;
-		rtv = 2;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
-	}
-	if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD write error\n"));
-		return(rtv2);
-	}
-
-	return(rtv);
-}
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done. Remove the VPD keyword
- *	'key' from the VPD buffer.
- *	Only the keywords in the read/write area can be deleted.
- *	Keywords in the read only area cannot be deleted.
- *
- * returns	0:	success, keyword was removed
- *		1:	keyword not found
- *		5:	keyword cannot be deleted
- *		6:	fatal VPD error
- */
-int VpdDelete(
-SK_AC	*pAC,	/* common data base */
-SK_IOC	IoC,	/* IO Context */
-char	*key)	/* keyword to read (e.g. "MN") */
-{
-	SK_VPD_PARA *p, vp;
-	char *etp;
-	int	vpd_size;
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
-		if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
-			/* try to delete read only keyword */
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("cannot delete RO keyword\n"));
-			return(5);
-		}
-
-		etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
-
-		vpd_move_para(vp.p_val+vp.p_len, etp+2,
-			- ((int)(vp.p_len + 3)));
-		if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
-			pAC->vpd.v.vpd_status &= ~VPD_VALID;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD encoding error\n"));
-			return(6);
-		}
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("keyword not found\n"));
-		return(1);
-	}
-
-	return(0);
-}
-
-/*
- *	If the VPD buffer contains valid data write the VPD
- *	read/write area back to the VPD EEPROM.
- *
- * returns	0:	success
- *		3:	VPD transfer timeout
- */
-int VpdUpdate(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	int vpd_size;
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
-		if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
-			vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("transfer timed out\n"));
-			return(3);
-		}
-	}
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
-	return(0);
-}
-
diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
deleted file mode 100644
index b4e7502..0000000
--- a/drivers/net/sk98lin/skxmac2.c
+++ /dev/null
@@ -1,4160 +0,0 @@
-/******************************************************************************
- *
- * Name:	skxmac2.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.102 $
- * Date:	$Date: 2003/10/02 16:53:58 $
- * Purpose:	Contains functions to initialize the MACs and PHYs
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* typedefs *******************************************************************/
-
-/* BCOM PHY magic pattern list */
-typedef struct s_PhyHack {
-	int		PhyReg;		/* Phy register */
-	SK_U16	PhyVal;		/* Value to write */
-} BCOM_HACK;
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#ifdef GENESIS
-static BCOM_HACK BcomRegA1Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
- { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
- { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-static BCOM_HACK BcomRegC0Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
- { 0x15, 0x0A04 }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-#endif
-
-/* function prototypes ********************************************************/
-#ifdef GENESIS
-static void	SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
-static int	SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
-#endif /* GENESIS */
-#ifdef YUKON
-static void	SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static void	SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
-static int	SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
-#endif /* OTHER_PHY */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmPhyRead() - Read from XMAC PHY register
- *
- * Description:	reads a 16-bit word from XMAC PHY or ext. PHY
- *
- * Returns:
- *	nothing
- */
-void SkXmPhyRead(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-int		Port,			/* Port Index (MAC_1 + n) */
-int		PhyReg,			/* Register Address (Offset) */
-SK_U16	SK_FAR *pVal)	/* Pointer to Value */
-{
-	SK_U16		Mmu;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* write the PHY register's address */
-	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-	
-	/* get the PHY register's value */
-	XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Ready' is set */
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);
-
-		/* get the PHY register's value */
-		XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
-	}
-}	/* SkXmPhyRead */
-
-
-/******************************************************************************
- *
- *	SkXmPhyWrite() - Write to XMAC PHY register
- *
- * Description:	writes a 16-bit word to XMAC PHY or ext. PHY
- *
- * Returns:
- *	nothing
- */
-void SkXmPhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	SK_U16		Mmu;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Busy' is cleared */
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
-	}
-	
-	/* write the PHY register's address */
-	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-	
-	/* write the PHY register's value */
-	XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Busy' is cleared */
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
-	}
-}	/* SkXmPhyWrite */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmPhyRead() - Read from GPHY register
- *
- * Description:	reads a 16-bit word from GPHY through MDIO
- *
- * Returns:
- *	nothing
- */
-void SkGmPhyRead(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-int		Port,			/* Port Index (MAC_1 + n) */
-int		PhyReg,			/* Register Address (Offset) */
-SK_U16	SK_FAR *pVal)	/* Pointer to Value */
-{
-	SK_U16	Ctrl;
-	SK_GEPORT	*pPrt;
-#ifdef VCPU
-	u_long SimCyle;
-	u_long SimLowTime;
-	
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
-		PhyReg, SimCyle, SimLowTime);
-#endif /* VCPU */
-	
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* set PHY-Register offset and 'Read' OpCode (= 1) */
-	*pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
-		GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
-
-	GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
-
-	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-	
-	/* additional check for MDC/MDIO activity */
-	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
-		*pVal = 0;
-		return;
-	}
-
-	*pVal |= GM_SMI_CT_BUSY;
-	
-	do {
-#ifdef VCPU
-		VCPUwaitTime(1000);
-#endif /* VCPU */
-
-		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
-	/* wait until 'ReadValid' is set */
-	} while (Ctrl == *pVal);
-	
-	/* get the PHY register's value */
-	GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
-
-#ifdef VCPU
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
-		SimCyle, SimLowTime);
-#endif /* VCPU */
-
-}	/* SkGmPhyRead */
-
-
-/******************************************************************************
- *
- *	SkGmPhyWrite() - Write to GPHY register
- *
- * Description:	writes a 16-bit word to GPHY through MDIO
- *
- * Returns:
- *	nothing
- */
-void SkGmPhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	SK_U16	Ctrl;
-	SK_GEPORT	*pPrt;
-#ifdef VCPU
-	SK_U32	DWord;
-	u_long	SimCyle;
-	u_long	SimLowTime;
-	
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
-		PhyReg, Val, SimCyle, SimLowTime);
-#endif /* VCPU */
-	
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* write the PHY register's value */
-	GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
-	
-	/* set PHY-Register offset and 'Write' OpCode (= 0) */
-	Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
-
-	GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
-
-	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-	
-	/* additional check for MDC/MDIO activity */
-	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
-		return;
-	}
-	
-	Val |= GM_SMI_CT_BUSY;
-
-	do {
-#ifdef VCPU
-		/* read Timer value */
-		SK_IN32(IoC, B2_TI_VAL, &DWord);
-
-		VCPUwaitTime(1000);
-#endif /* VCPU */
-
-		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
-	/* wait until 'Busy' is cleared */
-	} while (Ctrl == Val);
-	
-#ifdef VCPU
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
-		SimCyle, SimLowTime);
-#endif /* VCPU */
-
-}	/* SkGmPhyWrite */
-#endif /* YUKON */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkGePhyRead() - Read from PHY register
- *
- * Description:	calls a read PHY routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkGePhyRead(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	*pVal)		/* Pointer to Value */
-{
-	void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
-
-	if (pAC->GIni.GIGenesis) {
-		r_func = SkXmPhyRead;
-	}
-	else {
-		r_func = SkGmPhyRead;
-	}
-	
-	r_func(pAC, IoC, Port, PhyReg, pVal);
-}	/* SkGePhyRead */
-
-
-/******************************************************************************
- *
- *	SkGePhyWrite() - Write to PHY register
- *
- * Description:	calls a write PHY routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkGePhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
-
-	if (pAC->GIni.GIGenesis) {
-		w_func = SkXmPhyWrite;
-	}
-	else {
-		w_func = SkGmPhyWrite;
-	}
-	
-	w_func(pAC, IoC, Port, PhyReg, Val);
-}	/* SkGePhyWrite */
-#endif /* SK_DIAG */
-
-
-/******************************************************************************
- *
- *	SkMacPromiscMode() - Enable / Disable Promiscuous Mode
- *
- * Description:
- *   enables / disables promiscuous mode by setting Mode Register (XMAC) or
- *   Receive Control Register (GMAC) dep. on board type   	
- *
- * Returns:
- *	nothing
- */
-void SkMacPromiscMode(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-#ifdef YUKON
-	SK_U16	RcReg;
-#endif
-#ifdef GENESIS
-	SK_U32	MdReg;
-#endif	
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-		/* enable or disable promiscuous mode */
-		if (Enable) {
-			MdReg |= XM_MD_ENA_PROM;
-		}
-		else {
-			MdReg &= ~XM_MD_ENA_PROM;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-		
-		/* enable or disable unicast and multicast filtering */
-		if (Enable) {
-			RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
-		}
-		else {
-			RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
-		}
-		/* setup Receive Control Register */
-		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
-	}
-#endif /* YUKON */
-
-}	/* SkMacPromiscMode*/
-
-
-/******************************************************************************
- *
- *	SkMacHashing() - Enable / Disable Hashing
- *
- * Description:
- *   enables / disables hashing by setting Mode Register (XMAC) or
- *   Receive Control Register (GMAC) dep. on board type		
- *
- * Returns:
- *	nothing
- */
-void SkMacHashing(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-#ifdef YUKON
-	SK_U16	RcReg;
-#endif	
-#ifdef GENESIS
-	SK_U32	MdReg;
-#endif
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-		/* enable or disable hashing */
-		if (Enable) {
-			MdReg |= XM_MD_ENA_HASH;
-		}
-		else {
-			MdReg &= ~XM_MD_ENA_HASH;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-		
-		/* enable or disable multicast filtering */
-		if (Enable) {
-			RcReg |= GM_RXCR_MCF_ENA;
-		}
-		else {
-			RcReg &= ~GM_RXCR_MCF_ENA;
-		}
-		/* setup Receive Control Register */
-		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
-	}
-#endif /* YUKON */
-
-}	/* SkMacHashing*/
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
- *
- * Description:
- *	The features
- *	 - FCS stripping,					SK_STRIP_FCS_ON/OFF
- *	 - pad byte stripping,				SK_STRIP_PAD_ON/OFF
- *	 - don't set XMR_FS_ERR in status	SK_LENERR_OK_ON/OFF
- *	   for inrange length error frames
- *	 - don't set XMR_FS_ERR in status	SK_BIG_PK_OK_ON/OFF
- *	   for frames > 1514 bytes
- *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
- *
- *	for incoming packets may be enabled/disabled by this function.
- *	Additional modes may be added later.
- *	Multiple modes can be enabled/disabled at the same time.
- *	The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- *	nothing
- */
-static void SkXmSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
-					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
-	SK_U16	OldRxCmd;
-	SK_U16	RxCmd;
-
-	XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
-
-	RxCmd = OldRxCmd;
-	
-	switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
-	case SK_STRIP_FCS_ON:
-		RxCmd |= XM_RX_STRIP_FCS;
-		break;
-	case SK_STRIP_FCS_OFF:
-		RxCmd &= ~XM_RX_STRIP_FCS;
-		break;
-	}
-
-	switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
-	case SK_STRIP_PAD_ON:
-		RxCmd |= XM_RX_STRIP_PAD;
-		break;
-	case SK_STRIP_PAD_OFF:
-		RxCmd &= ~XM_RX_STRIP_PAD;
-		break;
-	}
-
-	switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
-	case SK_LENERR_OK_ON:
-		RxCmd |= XM_RX_LENERR_OK;
-		break;
-	case SK_LENERR_OK_OFF:
-		RxCmd &= ~XM_RX_LENERR_OK;
-		break;
-	}
-
-	switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
-	case SK_BIG_PK_OK_ON:
-		RxCmd |= XM_RX_BIG_PK_OK;
-		break;
-	case SK_BIG_PK_OK_OFF:
-		RxCmd &= ~XM_RX_BIG_PK_OK;
-		break;
-	}
-
-	switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
-	case SK_SELF_RX_ON:
-		RxCmd |= XM_RX_SELF_RX;
-		break;
-	case SK_SELF_RX_OFF:
-		RxCmd &= ~XM_RX_SELF_RX;
-		break;
-	}
-
-	/* Write the new mode to the Rx command register if required */
-	if (OldRxCmd != RxCmd) {
-		XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
-	}
-}	/* SkXmSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
- *
- * Description:
- *	The features
- *	 - FCS (CRC) stripping,				SK_STRIP_FCS_ON/OFF
- *	 - don't set GMR_FS_LONG_ERR		SK_BIG_PK_OK_ON/OFF
- *	   for frames > 1514 bytes
- *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
- *
- *	for incoming packets may be enabled/disabled by this function.
- *	Additional modes may be added later.
- *	Multiple modes can be enabled/disabled at the same time.
- *	The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- *	nothing
- */
-static void SkGmSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
-					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
-	SK_U16	OldRxCmd;
-	SK_U16	RxCmd;
-
-	if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
-
-		RxCmd = OldRxCmd;
-
-		if ((Mode & SK_STRIP_FCS_ON) != 0) {
-			RxCmd |= GM_RXCR_CRC_DIS;
-		}
-		else {
-			RxCmd &= ~GM_RXCR_CRC_DIS;
-		}
-		/* Write the new mode to the Rx control register if required */
-		if (OldRxCmd != RxCmd) {
-			GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
-		}
-	}
-
-	if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
-		
-		GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
-
-		RxCmd = OldRxCmd;
-
-		if ((Mode & SK_BIG_PK_OK_ON) != 0) {
-			RxCmd |= GM_SMOD_JUMBO_ENA;
-		}
-		else {
-			RxCmd &= ~GM_SMOD_JUMBO_ENA;
-		}
-		/* Write the new mode to the Rx control register if required */
-		if (OldRxCmd != RxCmd) {
-			GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
-		}
-	}
-}	/* SkGmSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
- *
- * Description:	modifies the MAC's Rx Control reg. dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Rx Mode */
-{
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmSetRxCmd(pAC, IoC, Port, Mode);
-	}
-	else {
-		
-		SkGmSetRxCmd(pAC, IoC, Port, Mode);
-	}
-
-}	/* SkMacSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkMacCrcGener() - Enable / Disable CRC Generation
- *
- * Description:	enables / disables CRC generation dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacCrcGener(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U16	Word;
-
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN16(IoC, Port, XM_TX_CMD, &Word);
-
-		if (Enable) {
-			Word &= ~XM_TX_NO_CRC;
-		}
-		else {
-			Word |= XM_TX_NO_CRC;
-		}
-		/* setup Tx Command Register */
-		XM_OUT16(IoC, Port, XM_TX_CMD, Word);
-	}
-	else {
-		
-		GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
-		
-		if (Enable) {
-			Word &= ~GM_TXCR_CRC_DIS;
-		}
-		else {
-			Word |= GM_TXCR_CRC_DIS;
-		}
-		/* setup Tx Control Register */
-		GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
-	}
-
-}	/* SkMacCrcGener*/
-
-#endif /* SK_DIAG */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmClrExactAddr() - Clear Exact Match Address Registers
- *
- * Description:
- *	All Exact Match Address registers of the XMAC 'Port' will be
- *	cleared starting with 'StartNum' up to (and including) the
- *	Exact Match address number of 'StopNum'.
- *
- * Returns:
- *	nothing
- */
-void SkXmClrExactAddr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		StartNum,	/* Begin with this Address Register Index (0..15) */
-int		StopNum)	/* Stop after finished with this Register Idx (0..15) */
-{
-	int		i;
-	SK_U16	ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
-
-	if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
-		StartNum > StopNum) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
-		return;
-	}
-
-	for (i = StartNum; i <= StopNum; i++) {
-		XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
-	}
-}	/* SkXmClrExactAddr */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
- *
- * Description:
- *	Flush the transmit FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- *	nothing
- */
-void SkMacFlushTxFifo(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	SK_U32	MdReg;
-
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* no way to flush the FIFO we have to issue a reset */
-		/* TBD */
-	}
-#endif /* YUKON */
-
-}	/* SkMacFlushTxFifo */
-
-
-/******************************************************************************
- *
- *	SkMacFlushRxFifo() - Flush the MAC's receive FIFO
- *
- * Description:
- *	Flush the receive FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- *	nothing
- */
-static void SkMacFlushRxFifo(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	SK_U32	MdReg;
-
-	if (pAC->GIni.GIGenesis) {
-
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* no way to flush the FIFO we have to issue a reset */
-		/* TBD */
-	}
-#endif /* YUKON */
-
-}	/* SkMacFlushRxFifo */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmSoftRst() - Do a XMAC software reset
- *
- * Description:
- *	The PHY registers should not be destroyed during this
- *	kind of software reset. Therefore the XMAC Software Reset
- *	(XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
- *
- *	The software reset is done by
- *		- disabling the Rx and Tx state machine,
- *		- resetting the statistics module,
- *		- clear all other significant XMAC Mode,
- *		  Command, and Control Registers
- *		- clearing the Hash Register and the
- *		  Exact Match Address registers, and
- *		- flushing the XMAC's Rx and Tx FIFOs.
- *
- * Note:
- *	Another requirement when stopping the XMAC is to
- *	avoid sending corrupted frames on the network.
- *	Disabling the Tx state machine will NOT interrupt
- *	the currently transmitted frame. But we must take care
- *	that the Tx FIFO is cleared AFTER the current frame
- *	is complete sent to the network.
- *
- *	It takes about 12ns to send a frame with 1538 bytes.
- *	One PCI clock goes at least 15ns (66MHz). Therefore
- *	after reading XM_GP_PORT back, we are sure that the
- *	transmitter is disabled AND idle. And this means
- *	we may flush the transmit FIFO now.
- *
- * Returns:
- *	nothing
- */
-static void SkXmSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
-	
-	/* reset the statistics module */
-	XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
-
-	/* disable all XMAC IRQs */
-	XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
-	
-	XM_OUT32(IoC, Port, XM_MODE, 0);		/* clear Mode Reg */
-	
-	XM_OUT16(IoC, Port, XM_TX_CMD, 0);		/* reset TX CMD Reg */
-	XM_OUT16(IoC, Port, XM_RX_CMD, 0);		/* reset RX CMD Reg */
-	
-	/* disable all PHY IRQs */
-	switch (pAC->GIni.GP[Port].PhyType) {
-	case SK_PHY_BCOM:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
-			break;
-		case SK_PHY_NAT:
-			/* todo: National
-			 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
-			break;
-#endif /* OTHER_PHY */
-	}
-
-	/* clear the Hash Register */
-	XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
-
-	/* clear the Exact Match Address registers */
-	SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
-	
-	/* clear the Source Check Address registers */
-	XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
-
-}	/* SkXmSoftRst */
-
-
-/******************************************************************************
- *
- *	SkXmHardRst() - Do a XMAC hardware reset
- *
- * Description:
- *	The XMAC of the specified 'Port' and all connected devices
- *	(PHY and SERDES) will receive a reset signal on its *Reset pins.
- *	External PHYs must be reset by clearing a bit in the GPIO register
- *  (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
- *
- * ATTENTION:
- * 	It is absolutely necessary to reset the SW_RST Bit first
- *	before calling this function.
- *
- * Returns:
- *	nothing
- */
-static void SkXmHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	Reg;
-	int		i;
-	int		TOut;
-	SK_U16	Word;
-
-	for (i = 0; i < 4; i++) {
-		/* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
-		TOut = 0;
-		do {
-			if (TOut++ > 10000) {
-				/*
-				 * Adapter seems to be in RESET state.
-				 * Registers cannot be written.
-				 */
-				return;
-			}
-
-			SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
-			
-			SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
-		
-		} while ((Word & MFF_SET_MAC_RST) == 0);
-	}
-
-	/* For external PHYs there must be special handling */
-	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-		
-		SK_IN32(IoC, B2_GP_IO, &Reg);
-		
-		if (Port == 0) {
-			Reg |= GP_DIR_0; 	/* set to output */
-			Reg &= ~GP_IO_0;	/* set PHY reset (active low) */
-		}
-		else {
-			Reg |= GP_DIR_2;	/* set to output */
-			Reg &= ~GP_IO_2;	/* set PHY reset (active low) */
-		}
-		/* reset external PHY */
-		SK_OUT32(IoC, B2_GP_IO, Reg);
-
-		/* short delay */
-		SK_IN32(IoC, B2_GP_IO, &Reg);
-	}
-}	/* SkXmHardRst */
-
-
-/******************************************************************************
- *
- *	SkXmClearRst() - Release the PHY & XMAC reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkXmClearRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-	/* clear HW reset */
-	SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
-	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		if (Port == 0) {
-			DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
-		}
-		else {
-			DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
-		}
-		/* Clear PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-
-		/* Enable GMII interface */
-		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
-	}
-}	/* SkXmClearRst */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmSoftRst() - Do a GMAC software reset
- *
- * Description:
- *	The GPHY registers should not be destroyed during this
- *	kind of software reset.
- *
- * Returns:
- *	nothing
- */
-static void SkGmSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
-	SK_U16  RxCtrl;
-
-	/* reset the statistics module */
-
-	/* disable all GMAC IRQs */
-	SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-	
-	/* disable all PHY IRQs */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-	
-	/* clear the Hash Register */
-	GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
-
-	/* Enable Unicast and Multicast filtering */
-	GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
-	
-	GM_OUT16(IoC, Port, GM_RX_CTRL,
-		(SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
-
-}	/* SkGmSoftRst */
-
-
-/******************************************************************************
- *
- *	SkGmHardRst() - Do a GMAC hardware reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkGmHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-	/* WA code for COMA mode */
-	if (pAC->GIni.GIYukonLite &&
-		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-		
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		DWord |= (GP_DIR_9 | GP_IO_9);
-
-		/* set PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-	}
-
-	/* set GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
-
-	/* set GMAC Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-
-}	/* SkGmHardRst */
-
-
-/******************************************************************************
- *
- *	SkGmClearRst() - Release the GPHY & GMAC reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkGmClearRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-#ifdef XXX
-		/* clear GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
-
-		/* set GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-#endif /* XXX */
-
-	/* WA code for COMA mode */
-	if (pAC->GIni.GIYukonLite &&
-		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-		
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		DWord |= GP_DIR_9;		/* set to output */
-		DWord &= ~GP_IO_9;		/* clear PHY reset (active high) */
-
-		/* clear PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-	}
-
-	/* set HWCFG_MODE */
-	DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
-		GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
-		(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
-		GPC_HWCFG_GMII_FIB);
-
-	/* set GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
-
-	/* release GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
-
-#ifdef VCPU
-	VCpuWait(9000);
-#endif /* VCPU */
-
-	/* clear GMAC Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
-
-#ifdef VCPU
-	VCpuWait(2000);
-	
-	SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
-			
-	SK_IN32(IoC, B0_ISRC, &DWord);
-#endif /* VCPU */
-
-}	/* SkGmClearRst */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- *	SkMacSoftRst() - Do a MAC software reset
- *
- * Description:	calls a MAC software reset routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* disable receiver and transmitter */
-	SkMacRxTxDisable(pAC, IoC, Port);
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmSoftRst(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmSoftRst(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-	/* flush the MAC's Rx and Tx FIFOs */
-	SkMacFlushTxFifo(pAC, IoC, Port);
-	
-	SkMacFlushRxFifo(pAC, IoC, Port);
-
-	pPrt->PState = SK_PRT_STOP;
-
-}	/* SkMacSoftRst */
-
-
-/******************************************************************************
- *
- *	SkMacHardRst() - Do a MAC hardware reset
- *
- * Description:	calls a MAC hardware reset routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmHardRst(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmHardRst(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-	pAC->GIni.GP[Port].PState = SK_PRT_RESET;
-
-}	/* SkMacHardRst */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmInitMac() - Initialize the XMAC II
- *
- * Description:
- *	Initialize the XMAC of the specified port.
- *	The XMAC must be reset or stopped before calling this function.
- *
- * Note:
- *	The XMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	nothing
- */
-void SkXmInitMac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int			i;
-	SK_U16		SWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PState == SK_PRT_STOP) {
-		/* Port State: SK_PRT_STOP */
-		/* Verify that the reset bit is cleared */
-		SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
-
-		if ((SWord & MFF_SET_MAC_RST) != 0) {
-			/* PState does not match HW state */
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
-			/* Correct it */
-			pPrt->PState = SK_PRT_RESET;
-		}
-	}
-
-	if (pPrt->PState == SK_PRT_RESET) {
-
-		SkXmClearRst(pAC, IoC, Port);
-
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			/* read Id from external PHY (all have the same address) */
-			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
-
-			/*
-			 * Optimize MDIO transfer by suppressing preamble.
-			 * Must be done AFTER first access to BCOM chip.
-			 */
-			XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
-			
-			XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
-
-			if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
-				/*
-				 * Workaround BCOM Errata for the C0 type.
-				 * Write magic patterns to reserved registers.
-				 */
-				i = 0;
-				while (BcomRegC0Hack[i].PhyReg != 0) {
-					SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
-						BcomRegC0Hack[i].PhyVal);
-					i++;
-				}
-			}
-			else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
-				/*
-				 * Workaround BCOM Errata for the A1 type.
-				 * Write magic patterns to reserved registers.
-				 */
-				i = 0;
-				while (BcomRegA1Hack[i].PhyReg != 0) {
-					SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
-						BcomRegA1Hack[i].PhyVal);
-					i++;
-				}
-			}
-
-			/*
-			 * Workaround BCOM Errata (#10523) for all BCom PHYs.
-			 * Disable Power Management after reset.
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
-			
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-				(SK_U16)(SWord | PHY_B_AC_DIS_PM));
-
-			/* PHY LED initialization is done in SkGeXmitLED() */
-		}
-
-		/* Dummy read the Interrupt source register */
-		XM_IN16(IoC, Port, XM_ISRC, &SWord);
-		
-		/*
-		 * The auto-negotiation process starts immediately after
-		 * clearing the reset. The auto-negotiation process should be
-		 * started by the SIRQ, therefore stop it here immediately.
-		 */
-		SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
-#ifdef TEST_ONLY
-		/* temp. code: enable signal detect */
-		/* WARNING: do not override GMII setting above */
-		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
-#endif
-	}
-
-	/*
-	 * configure the XMACs Station Address
-	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
-	 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
-	 */
-	for (i = 0; i < 3; i++) {
-		/*
-		 * The following 2 statements are together endianess
-		 * independent. Remember this when changing.
-		 */
-		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-		
-		XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
-	}
-
-	/* Tx Inter Packet Gap (XM_TX_IPG):	use default */
-	/* Tx High Water Mark (XM_TX_HI_WM):	use default */
-	/* Tx Low Water Mark (XM_TX_LO_WM):	use default */
-	/* Host Request Threshold (XM_HT_THR):	use default */
-	/* Rx Request Threshold (XM_RX_THR):	use default */
-	/* Rx Low Water Mark (XM_RX_LO_WM):	use default */
-
-	/* configure Rx High Water Mark (XM_RX_HI_WM) */
-	XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
-
-	/* Configure Tx Request Threshold */
-	SWord = SK_XM_THR_SL;				/* for single port */
-
-	if (pAC->GIni.GIMacsFound > 1) {
-		switch (pAC->GIni.GIPortUsage) {
-		case SK_RED_LINK:
-			SWord = SK_XM_THR_REDL;		/* redundant link */
-			break;
-		case SK_MUL_LINK:
-			SWord = SK_XM_THR_MULL;		/* load balancing */
-			break;
-		case SK_JUMBO_LINK:
-			SWord = SK_XM_THR_JUMBO;	/* jumbo frames */
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
-			break;
-		}
-	}
-	XM_OUT16(IoC, Port, XM_TX_THR, SWord);
-
-	/* setup register defaults for the Tx Command Register */
-	XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
-
-	/* setup register defaults for the Rx Command Register */
-	SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		SWord |= XM_RX_BIG_PK_OK;
-	}
-
-	if (pPrt->PLinkMode == SK_LMODE_HALF) {
-		/*
-		 * If in manual half duplex mode the other side might be in
-		 * full duplex mode, so ignore if a carrier extension is not seen
-		 * on frames received
-		 */
-		SWord |= XM_RX_DIS_CEXT;
-	}
-	
-	XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
-
-	/*
-	 * setup register defaults for the Mode Register
-	 *	- Don't strip error frames to avoid Store & Forward
-	 *	  on the Rx side.
-	 *	- Enable 'Check Station Address' bit
-	 *	- Enable 'Check Address Array' bit
-	 */
-	XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
-
-	/*
-	 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
-	 *	- Enable all bits excepting 'Octets Rx OK Low CntOv'
-	 *	  and 'Octets Rx OK Hi Cnt Ov'.
-	 */
-	XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
-
-	/*
-	 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
-	 *	- Enable all bits excepting 'Octets Tx OK Low CntOv'
-	 *	  and 'Octets Tx OK Hi Cnt Ov'.
-	 */
-	XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
-
-	/*
-	 * Do NOT init XMAC interrupt mask here.
-	 * All interrupts remain disable until link comes up!
-	 */
-
-	/*
-	 * Any additional configuration changes may be done now.
-	 * The last action is to enable the Rx and Tx state machine.
-	 * This should be done after the auto-negotiation process
-	 * has been completed successfully.
-	 */
-}	/* SkXmInitMac */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmInitMac() - Initialize the GMAC
- *
- * Description:
- *	Initialize the GMAC of the specified port.
- *	The GMAC must be reset or stopped before calling this function.
- *
- * Note:
- *	The GMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	nothing
- */
-void SkGmInitMac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int			i;
-	SK_U16		SWord;
-	SK_U32		DWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PState == SK_PRT_STOP) {
-		/* Port State: SK_PRT_STOP */
-		/* Verify that the reset bit is cleared */
-		SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
-		
-		if ((DWord & GMC_RST_SET) != 0) {
-			/* PState does not match HW state */
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
-			/* Correct it */
-			pPrt->PState = SK_PRT_RESET;
-		}
-	}
-
-	if (pPrt->PState == SK_PRT_RESET) {
-		
-		SkGmHardRst(pAC, IoC, Port);
-
-		SkGmClearRst(pAC, IoC, Port);
-		
-		/* Auto-negotiation ? */
-		if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-			/* Auto-negotiation disabled */
-
-			/* get General Purpose Control */
-			GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
-
-			/* disable auto-update for speed, duplex and flow-control */
-			SWord |= GM_GPCR_AU_ALL_DIS;
-			
-			/* setup General Purpose Control Register */
-			GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-			
-			SWord = GM_GPCR_AU_ALL_DIS;
-		}
-		else {
-			SWord = 0;
-		}
-
-		/* speed settings */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-		case SK_LSPEED_1000MBPS:
-			SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
-			break;
-		case SK_LSPEED_100MBPS:
-			SWord |= GM_GPCR_SPEED_100;
-			break;
-		case SK_LSPEED_10MBPS:
-			break;
-		}
-
-		/* duplex settings */
-		if (pPrt->PLinkMode != SK_LMODE_HALF) {
-			/* set full duplex */
-			SWord |= GM_GPCR_DUP_FULL;
-		}
-
-		/* flow-control settings */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			/* set Pause Off */
-			SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
-			/* disable Tx & Rx flow-control */
-			SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			/* disable Rx flow-control */
-			SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-		case SK_FLOW_MODE_SYM_OR_REM:
-			/* enable Tx & Rx flow-control */
-			break;
-		}
-
-		/* setup General Purpose Control Register */
-		GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-
-		/* dummy read the Interrupt Source Register */
-		SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
-		
-#ifndef VCPU
-		/* read Id from PHY */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
-		
-		SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
-#endif /* VCPU */
-	}
-
-	(void)SkGmResetCounter(pAC, IoC, Port);
-
-	/* setup Transmit Control Register */
-	GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
-
-	/* setup Receive Control Register */
-	GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
-		GM_RXCR_CRC_DIS);
-
-	/* setup Transmit Flow Control Register */
-	GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
-
-	/* setup Transmit Parameter Register */
-#ifdef VCPU
-	GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
-#endif /* VCPU */
-
-    SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
-			TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
-			TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
-	
-	GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
-
-	/* configure the Serial Mode Register */
-#ifdef VCPU
-	GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
-#endif /* VCPU */
-	
-	SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
-
-	if (pPrt->PMacLimit4) {
-		/* reset of collision counter after 4 consecutive collisions */
-		SWord |= GM_SMOD_LIMIT_4;
-	}
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		/* enable jumbo mode (Max. Frame Length = 9018) */
-		SWord |= GM_SMOD_JUMBO_ENA;
-	}
-	
-	GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
-	
-	/*
-	 * configure the GMACs Station Addresses
-	 * in PROM you can find our addresses at:
-	 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
-	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
-	 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
-	 */
-
-	for (i = 0; i < 3; i++) {
-		/*
-		 * The following 2 statements are together endianess
-		 * independent. Remember this when changing.
-		 */
-		/* physical address: will be used for pause frames */
-		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-
-#ifdef WA_DEV_16
-		/* WA for deviation #16 */
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
-			/* swap the address bytes */
-			SWord = ((SWord & 0xff00) >> 8)	| ((SWord & 0x00ff) << 8);
-
-			/* write to register in reversed order */
-			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
-		}
-		else {
-			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
-		}
-#else		
-		GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
-#endif /* WA_DEV_16 */
-		
-		/* virtual address: will be used for data */
-		SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
-
-		GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
-		
-		/* reset Multicast filtering Hash registers 1-3 */
-		GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
-	}
-
-	/* reset Multicast filtering Hash register 4 */
-	GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
-
-	/* enable interrupt mask for counter overflows */
-	GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
-	GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
-	GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
-
-#if defined(SK_DIAG) || defined(DEBUG)
-	/* read General Purpose Status */
-	GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("MAC Stat Reg.=0x%04X\n", SWord));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
-	c_print("MAC Stat Reg=0x%04X\n", SWord);
-#endif /* SK_DIAG */
-
-}	/* SkGmInitMac */
-#endif /* YUKON */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmInitDupMd() - Initialize the XMACs Duplex Mode
- *
- * Description:
- *	This function initializes the XMACs Duplex Mode.
- *	It should be called after successfully finishing
- *	the Auto-negotiation Process
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitDupMd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	switch (pAC->GIni.GP[Port].PLinkModeStatus) {
-	case SK_LMODE_STAT_AUTOHALF:
-	case SK_LMODE_STAT_HALF:
-		/* Configuration Actions for Half Duplex Mode */
-		/*
-		 * XM_BURST = default value. We are probable not quick
-		 * 	enough at the 'XMAC' bus to burst 8kB.
-		 *	The XMAC stops bursting if no transmit frames
-		 *	are available or the burst limit is exceeded.
-		 */
-		/* XM_TX_RT_LIM = default value (15) */
-		/* XM_TX_STIME = default value (0xff = 4096 bit times) */
-		break;
-	case SK_LMODE_STAT_AUTOFULL:
-	case SK_LMODE_STAT_FULL:
-		/* Configuration Actions for Full Duplex Mode */
-		/*
-		 * The duplex mode is configured by the PHY,
-		 * therefore it seems to be that there is nothing
-		 * to do here.
-		 */
-		break;
-	case SK_LMODE_STAT_UNKNOWN:
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
-		break;
-	}
-}	/* SkXmInitDupMd */
-
-
-/******************************************************************************
- *
- *	SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
- *
- * Description:
- *	This function initializes the Pause Mode which should
- *	be used for this port.
- *	It should be called after successfully finishing
- *	the Auto-negotiation Process
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPauseMd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U32		DWord;
-	SK_U16		Word;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-	
-	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
-		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
-		/* Disable Pause Frame Reception */
-		Word |= XM_MMU_IGN_PF;
-	}
-	else {
-		/*
-		 * enabling pause frame reception is required for 1000BT
-		 * because the XMAC is not reset if the link is going down
-		 */
-		/* Enable Pause Frame Reception */
-		Word &= ~XM_MMU_IGN_PF;
-	}	
-	
-	XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
-
-	XM_IN32(IoC, Port, XM_MODE, &DWord);
-
-	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
-		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
-		/*
-		 * Configure Pause Frame Generation
-		 * Use internal and external Pause Frame Generation.
-		 * Sending pause frames is edge triggered.
-		 * Send a Pause frame with the maximum pause time if
-		 * internal oder external FIFO full condition occurs.
-		 * Send a zero pause time frame to re-start transmission.
-		 */
-
-		/* XM_PAUSE_DA = '010000C28001' (default) */
-
-		/* XM_MAC_PTIME = 0xffff (maximum) */
-		/* remember this value is defined in big endian (!) */
-		XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
-
-		/* Set Pause Mode in Mode Register */
-		DWord |= XM_PAUSE_MODE;
-
-		/* Set Pause Mode in MAC Rx FIFO */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
-	}
-	else {
-		/*
-		 * disable pause frame generation is required for 1000BT
-		 * because the XMAC is not reset if the link is going down
-		 */
-		/* Disable Pause Mode in Mode Register */
-		DWord &= ~XM_PAUSE_MODE;
-
-		/* Disable Pause Mode in MAC Rx FIFO */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
-	}
-	
-	XM_OUT32(IoC, Port, XM_MODE, DWord);
-}	/* SkXmInitPauseMd*/
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyXmac() - Initialize the XMAC Phy registers
- *
- * Description:	initializes all the XMACs Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl;
-
-	pPrt = &pAC->GIni.GP[Port];
-	Ctrl = 0;
-	
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyXmac: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl |= PHY_CT_DUP_MD;
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLEs are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyXmac: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl |= PHY_X_AN_HD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl |= PHY_X_AN_FD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl |= PHY_X_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl |= PHY_X_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl |= PHY_X_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl |= PHY_X_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Write AutoNeg Advertisement Register */
-		SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
-
-		/* Restart Auto-negotiation */
-		Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl |= PHY_CT_LOOP;
-	}
-
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
-}	/* SkXmInitPhyXmac */
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
- *
- * Description:	initializes all the Broadcom Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyBcom(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl1;
-	SK_U16		Ctrl2;
-	SK_U16		Ctrl3;
-	SK_U16		Ctrl4;
-	SK_U16		Ctrl5;
-
-	Ctrl1 = PHY_CT_SP1000;
-	Ctrl2 = 0;
-	Ctrl3 = PHY_SEL_TYPE;
-	Ctrl4 = PHY_B_PEC_EN_LTR;
-	Ctrl5 = PHY_B_AC_TX_TST;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		Ctrl2 |= PHY_B_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			Ctrl2 |= PHY_B_1000C_MSC;
-		}
-	}
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyBcom: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl1 |= PHY_CT_DUP_MD;
-		}
-
-		/* Determine Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			Ctrl2 |= PHY_B_1000C_MSE;	/* set it to Slave */
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLES are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyBcom: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/*
-		 * Workaround BCOM Errata #1 for the C5 type.
-		 * 1000Base-T Link Acquisition Failure in Slave Mode
-		 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
-		 */
-		Ctrl2 |= PHY_B_1000C_RD;
-		
-		 /* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl2 |= PHY_B_1000C_AHD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl2 |= PHY_B_1000C_AFD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl3 |= PHY_B_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl3 |= PHY_B_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl3 |= PHY_B_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl3 |= PHY_B_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Restart Auto-negotiation */
-		Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-	
-	/* Initialize LED register here? */
-	/* No. Please do it in SkDgXmitLed() (if required) and swap
-	   init order of LEDs and XMAC. (MAl) */
-	
-	/* Write 1000Base-T Control Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-	
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl1 |= PHY_CT_LOOP;
-	}
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		/* configure FIFO to high latency for transmission of ext. packets */
-		Ctrl4 |= PHY_B_PEC_HIGH_LA;
-
-		/* configure reception of extended packets */
-		Ctrl5 |= PHY_B_AC_LONG_PACK;
-
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
-	}
-
-	/* Configure LED Traffic Mode and Jumbo Frame usage if specified */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
-	
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Control Reg=0x%04X\n", Ctrl1));
-}	/* SkXmInitPhyBcom */
-#endif /* GENESIS */
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmInitPhyMarv() - Initialize the Marvell Phy registers
- *
- * Description:	initializes all the Marvell Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkGmInitPhyMarv(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		PhyCtrl;
-	SK_U16		C1000BaseT;
-	SK_U16		AutoNegAdv;
-	SK_U16		ExtPhyCtrl;
-	SK_U16		LedCtrl;
-	SK_BOOL		AutoNeg;
-#if defined(SK_DIAG) || defined(DEBUG)
-	SK_U16		PhyStat;
-	SK_U16		PhyStat1;
-	SK_U16		PhySpecStat;
-#endif /* SK_DIAG || DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		AutoNeg = SK_FALSE;
-	}
-	else {
-		AutoNeg = SK_TRUE;
-	}
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("InitPhyMarv: Port %d, auto-negotiation %s\n",
-		 Port, AutoNeg ? "ON" : "OFF"));
-
-#ifdef VCPU
-	VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
-		Port, DoLoop);
-#else /* VCPU */
-	if (DoLoop) {
-		/* Set 'MAC Power up'-bit, set Manual MDI configuration */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
-			PHY_M_PC_MAC_POW_UP);
-	}
-	else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
-		/* Read Ext. PHY Specific Control */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
-		
-		ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
-			PHY_M_EC_MAC_S_MSK);
-		
-		ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
-			PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
-	
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
-	}
-
-	/* Read PHY Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
-
-	if (!AutoNeg) {
-		/* Disable Auto-negotiation */
-		PhyCtrl &= ~PHY_CT_ANE;
-	}
-
-	PhyCtrl |= PHY_CT_RESET;
-	/* Assert software reset */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-#endif /* VCPU */
-
-	PhyCtrl = 0 /* PHY_CT_COL_TST */;
-	C1000BaseT = 0;
-	AutoNegAdv = PHY_SEL_TYPE;
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		/* enable Manual Master/Slave */
-		C1000BaseT |= PHY_M_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			C1000BaseT |= PHY_M_1000C_MSC;	/* set it to Master */
-		}
-	}
-	
-	/* Auto-negotiation ? */
-	if (!AutoNeg) {
-		
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			/* Set Full Duplex Mode */
-			PhyCtrl |= PHY_CT_DUP_MD;
-		}
-
-		/* Set Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			C1000BaseT |= PHY_M_1000C_MSE;	/* set it to Slave */
-		}
-
-		/* Set Speed */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-		case SK_LSPEED_1000MBPS:
-			PhyCtrl |= PHY_CT_SP1000;
-			break;
-		case SK_LSPEED_100MBPS:
-			PhyCtrl |= PHY_CT_SP100;
-			break;
-		case SK_LSPEED_10MBPS:
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
-				SKERR_HWI_E019MSG);
-		}
-
-		if (!DoLoop) {
-			PhyCtrl |= PHY_CT_RESET;
-		}
-	}
-	else {
-		/* Set Auto-negotiation advertisement */
-		
-		if (pAC->GIni.GICopperType) {
-			/* Set Speed capabilities */
-			switch (pPrt->PLinkSpeed) {
-			case SK_LSPEED_AUTO:
-				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
-				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
-					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			case SK_LSPEED_1000MBPS:
-				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
-				break;
-			case SK_LSPEED_100MBPS:
-				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
-					/* advertise 10Base-T also */
-					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			case SK_LSPEED_10MBPS:
-				AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
-					SKERR_HWI_E019MSG);
-			}
-
-			/* Set Full/half duplex capabilities */
-			switch (pPrt->PLinkMode) {
-			case SK_LMODE_AUTOHALF:
-				C1000BaseT &= ~PHY_M_1000C_AFD;
-				AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
-				break;
-			case SK_LMODE_AUTOFULL:
-				C1000BaseT &= ~PHY_M_1000C_AHD;
-				AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
-				break;
-			case SK_LMODE_AUTOBOTH:
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-					SKERR_HWI_E015MSG);
-			}
-			
-			/* Set Flow-control capabilities */
-			switch (pPrt->PFlowCtrlMode) {
-			case SK_FLOW_MODE_NONE:
-				AutoNegAdv |= PHY_B_P_NO_PAUSE;
-				break;
-			case SK_FLOW_MODE_LOC_SEND:
-				AutoNegAdv |= PHY_B_P_ASYM_MD;
-				break;
-			case SK_FLOW_MODE_SYMMETRIC:
-				AutoNegAdv |= PHY_B_P_SYM_MD;
-				break;
-			case SK_FLOW_MODE_SYM_OR_REM:
-				AutoNegAdv |= PHY_B_P_BOTH_MD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-					SKERR_HWI_E016MSG);
-			}
-		}
-		else {	/* special defines for FIBER (88E1011S only) */
-			
-			/* Set Full/half duplex capabilities */
-			switch (pPrt->PLinkMode) {
-			case SK_LMODE_AUTOHALF:
-				AutoNegAdv |= PHY_M_AN_1000X_AHD;
-				break;
-			case SK_LMODE_AUTOFULL:
-				AutoNegAdv |= PHY_M_AN_1000X_AFD;
-				break;
-			case SK_LMODE_AUTOBOTH:
-				AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-					SKERR_HWI_E015MSG);
-			}
-			
-			/* Set Flow-control capabilities */
-			switch (pPrt->PFlowCtrlMode) {
-			case SK_FLOW_MODE_NONE:
-				AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
-				break;
-			case SK_FLOW_MODE_LOC_SEND:
-				AutoNegAdv |= PHY_M_P_ASYM_MD_X;
-				break;
-			case SK_FLOW_MODE_SYMMETRIC:
-				AutoNegAdv |= PHY_M_P_SYM_MD_X;
-				break;
-			case SK_FLOW_MODE_SYM_OR_REM:
-				AutoNegAdv |= PHY_M_P_BOTH_MD_X;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-					SKERR_HWI_E016MSG);
-			}
-		}
-
-		if (!DoLoop) {
-			/* Restart Auto-negotiation */
-			PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
-		}
-	}
-	
-#ifdef VCPU
-	/*
-	 * E-mail from Gu Lin (08-03-2002):
-	 */
-	
-	/* Program PHY register 30 as 16'h0708 for simulation speed up */
-	SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
-	
-	VCpuWait(2000);
-
-#else /* VCPU */
-	
-	/* Write 1000Base-T Control Register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-#endif /* VCPU */
-	
-	if (DoLoop) {
-		/* Set the PHY Loopback bit */
-		PhyCtrl |= PHY_CT_LOOP;
-
-#ifdef XXX
-		/* Program PHY register 16 as 16'h0400 to force link good */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
-#endif /* XXX */
-
-#ifndef VCPU
-		if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
-			/* Write Ext. PHY Specific Control */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
-				(SK_U16)((pPrt->PLinkSpeed + 2) << 4));
-		}
-#endif /* VCPU */
-	}
-#ifdef TEST_ONLY
-	else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
-			/* Write PHY Specific Control */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
-				PHY_M_PC_EN_DET_MSK);
-	}
-#endif
-
-	/* Write to the PHY Control register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-
-#ifdef VCPU
-	VCpuWait(2000);
-#else
-
-	LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
-		LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
-	}
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
-		LedCtrl |= PHY_M_LEDC_DP_CTRL;
-	}
-	
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
-		/* only in forced 100 Mbps mode */
-		if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
-
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
-				PHY_M_LED_MO_100(MO_LED_ON));
-		}
-	}
-
-#ifdef SK_DIAG
-	c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
-	c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
-	c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
-	c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
-#endif /* SK_DIAG */
-
-#if defined(SK_DIAG) || defined(DEBUG)
-	/* Read PHY Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-	
-	/* Read 1000Base-T Control Register */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("1000B-T Ctrl =0x%04X\n", C1000BaseT));
-	
-	/* Read AutoNeg Advertisement Register */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-	
-	/* Read Ext. PHY Specific Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
-	
-	/* Read PHY Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Stat Reg.=0x%04X\n", PhyStat));
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Stat Reg.=0x%04X\n", PhyStat1));
-	
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Spec Stat=0x%04X\n", PhySpecStat));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
-	c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
-	c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
-	c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
-	c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
-	c_print("PHY Stat Reg=0x%04X\n", PhyStat);
-	c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
-	c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
-#endif /* SK_DIAG */
-
-#endif /* VCPU */
-
-}	/* SkGmInitPhyMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkXmInitPhyLone() - Initialize the Level One Phy registers
- *
- * Description:	initializes all the Level One Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyLone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl1;
-	SK_U16		Ctrl2;
-	SK_U16		Ctrl3;
-
-	Ctrl1 = PHY_CT_SP1000;
-	Ctrl2 = 0;
-	Ctrl3 = PHY_SEL_TYPE;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		Ctrl2 |= PHY_L_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			Ctrl2 |= PHY_L_1000C_MSC;
-		}
-	}
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		/*
-		 * level one spec say: "1000 Mbps: manual mode not allowed"
-		 * but lets see what happens...
-		 */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyLone: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl1 |= PHY_CT_DUP_MD;
-		}
-
-		/* Determine Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			Ctrl2 |= PHY_L_1000C_MSE;	/* set it to Slave */
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLES are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyLone: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl2 |= PHY_L_1000C_AHD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl2 |= PHY_L_1000C_AFD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl3 |= PHY_L_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl3 |= PHY_L_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl3 |= PHY_L_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl3 |= PHY_L_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Restart Auto-negotiation */
-		Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-	
-	/* Write 1000Base-T Control Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl1 |= PHY_CT_LOOP;
-	}
-
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Control Reg=0x%04X\n", Ctrl1));
-}	/* SkXmInitPhyLone */
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyNat() - Initialize the National Phy registers
- *
- * Description:	initializes all the National Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyNat(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-/* todo: National */
-}	/* SkXmInitPhyNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkMacInitPhy() - Initialize the PHY registers
- *
- * Description:	calls the Init PHY routines dep. on board type
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-void SkMacInitPhy(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		switch (pPrt->PhyType) {
-		case SK_PHY_XMAC:
-			SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
-			break;
-		case SK_PHY_BCOM:
-			SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
-			break;
-		case SK_PHY_NAT:
-			SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
-			break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
-	}
-#endif /* YUKON */
-
-}	/* SkMacInitPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmAutoNegDoneXmac() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		LPAb;		/* Link Partner Ability */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneXmac, Port %d\n", Port));
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
-
-	if ((LPAb & PHY_X_AN_RFB) != 0) {
-		/* At least one of the remote fault bit is set */
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	else {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_DUP_CAP);
-	}
-
-	/* Check PAUSE mismatch */
-	/* We are NOT using chapter 4.23 of the Xaqti manual */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
-	     pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
-	    (LPAb & PHY_X_P_SYM_MD) != 0) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
-		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
-		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneXmac */
-
-
-/******************************************************************************
- *
- *	SkXmAutoNegDoneBcom() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneBcom(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		AuxStat;	/* Auxiliary Status */
-
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	SK_U16		ResAb;		/* Resolved Ability */
-#endif	/* 0 */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneBcom, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-#endif	/* 0 */
-	
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
-
-	if ((LPAb & PHY_B_AN_RF) != 0) {
-		/* Remote fault bit is set: Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	else {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_DUP_CAP);
-	}
-	
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-#endif	/* 0 */
-
-	/* Check PAUSE mismatch ??? */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmAutoNegDoneMarv() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkGmAutoNegDoneMarv(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		AuxStat;	/* Auxiliary Status */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneMarv, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Link P.Abil.=0x%04X\n", LPAb));
-	
-	if ((LPAb & PHY_M_AN_RF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-	
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		(SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
-	
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
-	
-	/* Check Speed & Duplex resolved */
-	if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-		return(SK_AND_DUP_CAP);
-	}
-	
-	if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	
-	/* Check PAUSE mismatch ??? */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	
-	/* set used link speed */
-	switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
-	case (unsigned)PHY_M_PS_SPEED_1000:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-		break;
-	case PHY_M_PS_SPEED_100:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
-		break;
-	default:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
-	}
-
-	return(SK_AND_OK);
-}	/* SkGmAutoNegDoneMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkXmAutoNegDoneLone() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneLone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		QuickStat;	/* Auxiliary Status */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneLone, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
-
-	if ((LPAb & PHY_L_AN_RF) != 0) {
-		/* Remote fault bit is set */
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_L_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	else if (ResAb & PHY_L_1000S_MSR) {
-		pPrt->PMSStatus = SK_MS_STAT_MASTER;
-	}
-	else {
-		pPrt->PMSStatus = SK_MS_STAT_SLAVE;
-	}
-
-	/* Check PAUSE mismatch */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	/* we must manually resolve the abilities here */
-	pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	
-	switch (pPrt->PFlowCtrlMode) {
-	case SK_FLOW_MODE_NONE:
-		/* default */
-		break;
-	case SK_FLOW_MODE_LOC_SEND:
-		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
-			(PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
-			/* Disable PAUSE receive, enable PAUSE transmit */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-		}
-		break;
-	case SK_FLOW_MODE_SYMMETRIC:
-		if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
-			/* Symmetric PAUSE */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-		}
-		break;
-	case SK_FLOW_MODE_SYM_OR_REM:
-		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
-			PHY_L_QS_AS_PAUSE) {
-			/* Enable PAUSE receive, disable PAUSE transmit */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-		}
-		else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
-			/* Symmetric PAUSE */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-		}
-		break;
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-			SKERR_HWI_E016MSG);
-	}
-	
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneLone */
-
-
-/******************************************************************************
- *
- *	SkXmAutoNegDoneNat() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneNat(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-/* todo: National */
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkMacAutoNegDone() - Auto-negotiation handling
- *
- * Description:	calls the auto-negotiation done routines dep. on board type
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-int	SkMacAutoNegDone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int	Rtv;
-
-	Rtv = SK_AND_OK;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		switch (pPrt->PhyType) {
-		
-		case SK_PHY_XMAC:
-			Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
-			break;
-		case SK_PHY_BCOM:
-			Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
-			break;
-		case SK_PHY_NAT:
-			Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
-			break;
-#endif /* OTHER_PHY */
-		default:
-			return(SK_AND_OTHER);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-	
-	if (Rtv != SK_AND_OK) {
-		return(Rtv);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNeg done Port %d\n", Port));
-	
-	/* We checked everything and may now enable the link */
-	pPrt->PAutoNegFail = SK_FALSE;
-
-	SkMacRxTxEnable(pAC, IoC, Port);
-	
-	return(SK_AND_OK);
-}	/* SkMacAutoNegDone */
-
-
-/******************************************************************************
- *
- *	SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
- *
- * Description:	enables Rx/Tx dep. on board type
- *
- * Returns:
- *	0	o.k.
- *	!= 0	Error happened
- */
-int SkMacRxTxEnable(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Reg;		/* 16-bit register value */
-	SK_U16		IntMask;	/* MAC interrupt mask */
-#ifdef GENESIS
-	SK_U16		SWord;
-#endif
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (!pPrt->PHWLinkUp) {
-		/* The Hardware link is NOT up */
-		return(0);
-	}
-
-	if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
-	     pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
-	     pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
-	     pPrt->PAutoNegFail) {
-		/* Auto-negotiation is not done or failed */
-		return(0);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* set Duplex Mode and Pause Mode */
-		SkXmInitDupMd(pAC, IoC, Port);
-		
-		SkXmInitPauseMd(pAC, IoC, Port);
-	
-		/*
-		 * Initialize the Interrupt Mask Register. Default IRQs are...
-		 *	- Link Asynchronous Event
-		 *	- Link Partner requests config
-		 *	- Auto Negotiation Done
-		 *	- Rx Counter Event Overflow
-		 *	- Tx Counter Event Overflow
-		 *	- Transmit FIFO Underrun
-		 */
-		IntMask = XM_DEF_MSK;
-
-#ifdef DEBUG
-		/* add IRQ for Receive FIFO Overflow */
-		IntMask &= ~XM_IS_RXF_OV;
-#endif /* DEBUG */
-		
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			/* disable GP0 interrupt bit */
-			IntMask |= XM_IS_INP_ASS;
-		}
-		XM_OUT16(IoC, Port, XM_IMSK, IntMask);
-	
-		/* get MMU Command Reg. */
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
-		
-		if (pPrt->PhyType != SK_PHY_XMAC &&
-			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
-			 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
-			/* set to Full Duplex */
-			Reg |= XM_MMU_GMII_FD;
-		}
-		
-		switch (pPrt->PhyType) {
-		case SK_PHY_BCOM:
-			/*
-			 * Workaround BCOM Errata (#10523) for all BCom Phys
-			 * Enable Power Management after link up
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-				(SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
-            SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
-				(SK_U16)PHY_B_DEF_MSK);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
-			break;
-		case SK_PHY_NAT:
-			/* todo National:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
-			/* no interrupts possible from National ??? */
-			break;
-#endif /* OTHER_PHY */
-		}
-		
-		/* enable Rx/Tx */
-		XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/*
-		 * Initialize the Interrupt Mask Register. Default IRQs are...
-		 *	- Rx Counter Event Overflow
-		 *	- Tx Counter Event Overflow
-		 *	- Transmit FIFO Underrun
-		 */
-		IntMask = GMAC_DEF_MSK;
-
-#ifdef DEBUG
-		/* add IRQ for Receive FIFO Overrun */
-		IntMask |= GM_IS_RX_FF_OR;
-#endif /* DEBUG */
-		
-		SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
-		
-		/* get General Purpose Control */
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
-		
-		if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
-			pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
-			/* set to Full Duplex */
-			Reg |= GM_GPCR_DUP_FULL;
-		}
-		
-		/* enable Rx/Tx */
-        GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
-			GM_GPCR_TX_ENA));
-
-#ifndef VCPU
-		/* Enable all PHY interrupts */
-        SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
-			(SK_U16)PHY_M_DEF_MSK);
-#endif /* VCPU */
-	}
-#endif /* YUKON */
-					
-	return(0);
-
-}	/* SkMacRxTxEnable */
-
-
-/******************************************************************************
- *
- *	SkMacRxTxDisable() - Disable Receiver and Transmitter
- *
- * Description:	disables Rx/Tx dep. on board type
- *
- * Returns: N/A
- */
-void SkMacRxTxDisable(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Word;
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-		
-		XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
-	
-		/* dummy read to ensure writing */
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
-
-        GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
-			GM_GPCR_TX_ENA)));
-
-		/* dummy read to ensure writing */
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
-	}
-#endif /* YUKON */
-
-}	/* SkMacRxTxDisable */
-
-
-/******************************************************************************
- *
- *	SkMacIrqDisable() - Disable IRQ from MAC
- *
- * Description:	sets the IRQ-mask to disable IRQ dep. on board type
- *
- * Returns: N/A
- */
-void SkMacIrqDisable(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-#ifdef GENESIS
-	SK_U16		Word;
-#endif
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		/* disable all XMAC IRQs */
-		XM_OUT16(IoC, Port, XM_IMSK, 0xffff);	
-		
-		/* Disable all PHY interrupts */
-		switch (pPrt->PhyType) {
-			case SK_PHY_BCOM:
-				/* Make sure that PHY is initialized */
-				if (pPrt->PState != SK_PRT_RESET) {
-					/* NOT allowed if BCOM is in RESET state */
-					/* Workaround BCOM Errata (#10523) all BCom */
-					/* Disable Power Management if link is down */
-					SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
-					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-						(SK_U16)(Word | PHY_B_AC_DIS_PM));
-					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
-				}
-				break;
-#ifdef OTHER_PHY
-			case SK_PHY_LONE:
-				SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
-				break;
-			case SK_PHY_NAT:
-				/* todo: National
-				SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
-				break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* disable all GMAC IRQs */
-		SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-		
-#ifndef VCPU
-		/* Disable all PHY interrupts */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-#endif /* VCPU */
-	}
-#endif /* YUKON */
-
-}	/* SkMacIrqDisable */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkXmSendCont() - Enable / Disable Send Continuous Mode
- *
- * Description:	enable / disable Send Continuous Mode on XMAC
- *
- * Returns:
- *	nothing
- */
-void SkXmSendCont(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U32	MdReg;
-
-	XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-	if (Enable) {
-		MdReg |= XM_MD_TX_CONT;
-	}
-	else {
-		MdReg &= ~XM_MD_TX_CONT;
-	}
-	/* setup Mode Register */
-	XM_OUT32(IoC, Port, XM_MODE, MdReg);
-
-}	/* SkXmSendCont */
-
-
-/******************************************************************************
- *
- *	SkMacTimeStamp() - Enable / Disable Time Stamp
- *
- * Description:	enable / disable Time Stamp generation for Rx packets
- *
- * Returns:
- *	nothing
- */
-void SkMacTimeStamp(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U32	MdReg;
-	SK_U8	TimeCtrl;
-
-	if (pAC->GIni.GIGenesis) {
-
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		if (Enable) {
-			MdReg |= XM_MD_ATS;
-		}
-		else {
-			MdReg &= ~XM_MD_ATS;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-	else {
-		if (Enable) {
-			TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
-		}
-		else {
-			TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
-		}
-		/* Start/Stop Time Stamp Timer */
-		SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
-	}
-
-}	/* SkMacTimeStamp*/
-
-#else /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
- *
- *	This function analyses the Interrupt status word. If any of the
- *	Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
- *	is set true.
- */
-void SkXmAutoNegLipaXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U16	IStatus)	/* Interrupt Status word to analyse */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
-		(IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
-			Port, IStatus));
-		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
-	}
-}	/* SkXmAutoNegLipaXmac */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
- *
- *	This function analyses the PHY status word.
- *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
- *	is set true.
- */
-void SkMacAutoNegLipaPhy(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U16	PhyStat)	/* PHY Status word to analyse */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
-		(PhyStat & PHY_ST_AN_OVER) != 0) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
-			Port, PhyStat));
-		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
-	}
-}	/* SkMacAutoNegLipaPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmIrq() - Interrupt Service Routine
- *
- * Description:	services an Interrupt Request of the XMAC
- *
- * Note:
- *	With an external PHY, some interrupt bits are not meaningfull any more:
- *	- LinkAsyncEvent (bit #14)              XM_IS_LNK_AE
- *	- LinkPartnerReqConfig (bit #10)	XM_IS_LIPA_RC
- *	- Page Received (bit #9)		XM_IS_RX_PAGE
- *	- NextPageLoadedForXmt (bit #8)		XM_IS_TX_PAGE
- *	- AutoNegDone (bit #7)			XM_IS_AND
- *	Also probably not valid any more is the GP0 input bit:
- *	- GPRegisterBit0set			XM_IS_INP_ASS
- *
- * Returns:
- *	nothing
- */
-static void SkXmIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_EVPARA	Para;
-	SK_U16		IStatus;	/* Interrupt status read from the XMAC */
-	SK_U16		IStatus2;
-#ifdef SK_SLIM
-    SK_U64      OverflowStatus;
-#endif	
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	XM_IN16(IoC, Port, XM_ISRC, &IStatus);
-	
-	/* LinkPartner Auto-negable? */
-	if (pPrt->PhyType == SK_PHY_XMAC) {
-		SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
-	}
-	else {
-		/* mask bits that are not used with ext. PHY */
-		IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
-			XM_IS_RX_PAGE | XM_IS_TX_PAGE |
-			XM_IS_AND | XM_IS_INP_ASS);
-	}
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
-	if (!pPrt->PHWLinkUp) {
-		/* Spurious XMAC interrupt */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: spurious interrupt on Port %d\n", Port));
-		return;
-	}
-
-	if ((IStatus & XM_IS_INP_ASS) != 0) {
-		/* Reread ISR Register if link is not in sync */
-		XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
-			 Port, IStatus, IStatus2));
-		IStatus &= ~XM_IS_INP_ASS;
-		IStatus |= IStatus2;
-	}
-
-	if ((IStatus & XM_IS_LNK_AE) != 0) {
-		/* not used, GP0 is used instead */
-	}
-
-	if ((IStatus & XM_IS_TX_ABORT) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_FRC_INT) != 0) {
-		/* not used, use ASIC IRQ instead if needed */
-	}
-
-	if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
-		SkHWLinkDown(pAC, IoC, Port);
-
-		/* Signal to RLMT */
-		Para.Para32[0] = (SK_U32)Port;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-	}
-
-	if ((IStatus & XM_IS_RX_PAGE) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_TX_PAGE) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_AND) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: AND on link that is up Port %d\n", Port));
-	}
-
-	if ((IStatus & XM_IS_TSC_OV) != 0) {
-		/* not used */
-	}
-
-	/* Combined Tx & Rx Counter Overflow SIRQ Event */
-	if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
-#ifdef SK_SLIM
-		SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
-		Para.Para32[0] = (SK_U32)Port;
-		Para.Para32[1] = (SK_U32)IStatus;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif /* SK_SLIM */
-	}
-
-	if ((IStatus & XM_IS_RXF_OV) != 0) {
-		/* normal situation -> no effect */
-#ifdef DEBUG
-		pPrt->PRxOverCnt++;
-#endif /* DEBUG */
-	}
-
-	if ((IStatus & XM_IS_TXF_UR) != 0) {
-		/* may NOT happen -> error log */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
-	}
-
-	if ((IStatus & XM_IS_TX_COMP) != 0) {
-		/* not served here */
-	}
-
-	if ((IStatus & XM_IS_RX_COMP) != 0) {
-		/* not served here */
-	}
-}	/* SkXmIrq */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmIrq() - Interrupt Service Routine
- *
- * Description:	services an Interrupt Request of the GMAC
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkGmIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U8		IStatus;	/* Interrupt status */
-#ifdef SK_SLIM
-    SK_U64      OverflowStatus;
-#else
-	SK_EVPARA	Para;
-#endif	
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
-	
-#ifdef XXX
-	/* LinkPartner Auto-negable? */
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
-#endif /* XXX */
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
-	/* Combined Tx & Rx Counter Overflow SIRQ Event */
-	if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
-		/* these IRQs will be cleared by reading GMACs register */
-#ifdef SK_SLIM
-        SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
-		Para.Para32[0] = (SK_U32)Port;
-		Para.Para32[1] = (SK_U32)IStatus;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif		
-	}
-
-	if (IStatus & GM_IS_RX_FF_OR) {
-		/* clear GMAC Rx FIFO Overrun IRQ */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
-#ifdef DEBUG
-		pPrt->PRxOverCnt++;
-#endif /* DEBUG */
-	}
-
-	if (IStatus & GM_IS_TX_FF_UR) {
-		/* clear GMAC Tx FIFO Underrun IRQ */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
-		/* may NOT happen -> error log */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
-	}
-
-	if (IStatus & GM_IS_TX_COMPL) {
-		/* not served here */
-	}
-
-	if (IStatus & GM_IS_RX_COMPL) {
-		/* not served here */
-	}
-}	/* SkGmIrq */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- *	SkMacIrq() - Interrupt Service Routine for MAC
- *
- * Description:	calls the Interrupt Service Routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* IRQ from XMAC */
-		SkXmIrq(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* IRQ from GMAC */
-		SkGmIrq(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-}	/* SkMacIrq */
-
-#endif /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmUpdateStats() - Force the XMAC to output the current statistic
- *
- * Description:
- *	The XMAC holds its statistic internally. To obtain the current
- *	values a command must be sent so that the statistic data will
- *	be written to a predefined memory area on the adapter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmUpdateStats(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		StatReg;
-	int			WaitIndex;
-
-	pPrt = &pAC->GIni.GP[Port];
-	WaitIndex = 0;
-
-	/* Send an update command to XMAC specified */
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
-
-	/*
-	 * It is an auto-clearing register. If the command bits
-	 * went to zero again, the statistics are transferred.
-	 * Normally the command should be executed immediately.
-	 * But just to be sure we execute a loop.
-	 */
-	do {
-
-		XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
-		
-		if (++WaitIndex > 10) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
-
-			return(1);
-		}
-	} while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
-	
-	return(0);
-}	/* SkXmUpdateStats */
-
-
-/******************************************************************************
- *
- *	SkXmMacStatistic() - Get XMAC counter value
- *
- * Description:
- *	Gets the 32bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmMacStatistic(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-unsigned int Port,		/* Port Index (MAC_1 + n) */
-SK_U16	StatAddr,		/* MIB counter base address */
-SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
-{
-	if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
-		
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-		
-		return(1);
-	}
-	
-	XM_IN32(IoC, Port, StatAddr, pVal);
-
-	return(0);
-}	/* SkXmMacStatistic */
-
-
-/******************************************************************************
- *
- *	SkXmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- *	Force the XMAC to clear its statistic counter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmResetCounter(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-	/* Clear two times according to Errata #3 */
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-
-	return(0);
-}	/* SkXmResetCounter */
-
-
-/******************************************************************************
- *
- *	SkXmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- *	Checks the source causing an counter overflow interrupt. On success the
- *	resulting counter overflow status is written to <pStatus>, whereas the
- *	upper dword stores the XMAC ReceiveCounterEvent register and the lower
- *	dword the XMAC TransmitCounterEvent register.
- *
- * Note:
- *	For XMAC the interrupt source is a self-clearing register, so the source
- *	must be checked only once. SIRQ module does another check to be sure
- *	that no interrupt get lost during process time.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmOverflowStatus(
-SK_AC	*pAC,				/* adapter context */
-SK_IOC	IoC,				/* IO context */
-unsigned int Port,			/* Port Index (MAC_1 + n) */
-SK_U16	IStatus,			/* Interupt Status from MAC */
-SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
-{
-	SK_U64	Status;	/* Overflow status */
-	SK_U32	RegVal;
-
-	Status = 0;
-
-	if ((IStatus & XM_IS_RXC_OV) != 0) {
-
-		XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
-		Status |= (SK_U64)RegVal << 32;
-	}
-	
-	if ((IStatus & XM_IS_TXC_OV) != 0) {
-
-		XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
-		Status |= (SK_U64)RegVal;
-	}
-
-	*pStatus = Status;
-
-	return(0);
-}	/* SkXmOverflowStatus */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmUpdateStats() - Force the GMAC to output the current statistic
- *
- * Description:
- *	Empty function for GMAC. Statistic data is accessible in direct way.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmUpdateStats(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	return(0);
-}
-
-
-/******************************************************************************
- *
- *	SkGmMacStatistic() - Get GMAC counter value
- *
- * Description:
- *	Gets the 32bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmMacStatistic(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-unsigned int Port,		/* Port Index (MAC_1 + n) */
-SK_U16	StatAddr,		/* MIB counter base address */
-SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
-{
-
-	if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
-		
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
-		return(1);
-	}
-		
-	GM_IN32(IoC, Port, StatAddr, pVal);
-
-	return(0);
-}	/* SkGmMacStatistic */
-
-
-/******************************************************************************
- *
- *	SkGmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- *	Force GMAC to clear its statistic counter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmResetCounter(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Reg;	/* Phy Address Register */
-	SK_U16	Word;
-	int		i;
-
-	GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
-
-	/* set MIB Clear Counter Mode */
-	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
-	
-	/* read all MIB Counters with Clear Mode set */
-	for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
-		/* the reset is performed only when the lower 16 bits are read */
-		GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
-	}
-	
-	/* clear MIB Clear Counter Mode */
-	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
-	
-	return(0);
-}	/* SkGmResetCounter */
-
-
-/******************************************************************************
- *
- *	SkGmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- *	Checks the source causing an counter overflow interrupt. On success the
- *	resulting counter overflow status is written to <pStatus>, whereas the
- *	the following bit coding is used:
- *	63:56 - unused
- *	55:48 - TxRx interrupt register bit7:0
- *	32:47 - Rx interrupt register
- *	31:24 - unused
- *	23:16 - TxRx interrupt register bit15:8
- *	15:0  - Tx interrupt register
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmOverflowStatus(
-SK_AC	*pAC,				/* adapter context */
-SK_IOC	IoC,				/* IO context */
-unsigned int Port,			/* Port Index (MAC_1 + n) */
-SK_U16	IStatus,			/* Interupt Status from MAC */
-SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
-{
-	SK_U64	Status;		/* Overflow status */
-	SK_U16	RegVal;
-
-	Status = 0;
-
-	if ((IStatus & GM_IS_RX_CO_OV) != 0) {
-		/* this register is self-clearing after read */
-		GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
-		Status |= (SK_U64)RegVal << 32;
-	}
-	
-	if ((IStatus & GM_IS_TX_CO_OV) != 0) {
-		/* this register is self-clearing after read */
-		GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
-		Status |= (SK_U64)RegVal;
-	}
-	
-	/* this register is self-clearing after read */
-	GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
-	/* Rx overflow interrupt register bits (LoByte)*/
-	Status |= (SK_U64)((SK_U8)RegVal) << 48;
-	/* Tx overflow interrupt register bits (HiByte)*/
-	Status |= (SK_U64)(RegVal >> 8) << 16;
-
-	*pStatus = Status;
-
-	return(0);
-}	/* SkGmOverflowStatus */
-
-
-#ifndef SK_SLIM
-/******************************************************************************
- *
- *	SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
- *
- * Description:
- *  starts the cable diagnostic test if 'StartTest' is true
- *  gets the results if 'StartTest' is true
- *
- * NOTE:	this test is meaningful only when link is down
- *	
- * Returns:
- *	0:  success
- *	1:	no YUKON copper
- *	2:	test in progress
- */
-int SkGmCableDiagStatus(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,   		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	StartTest)	/* flag for start / get result */
-{
-	int		i;
-	SK_U16	RegVal;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-		
-		return(1);
-	}
-
-	if (StartTest) {
-		/* only start the cable test */
-		if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
-			/* apply TDR workaround from Marvell */
-			SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
-			
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
-		}
-
-		/* set address to 0 for MDI[0] */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
-
-		/* Read Cable Diagnostic Reg */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-		/* start Cable Diagnostic Test */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
-			(SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
-	
-		return(0);
-	}
-	
-	/* Read Cable Diagnostic Reg */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Cable Diag.=0x%04X\n", RegVal));
-
-	if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
-		/* test is running */
-		return(2);
-	}
-
-	/* get the test results */
-	for (i = 0; i < 4; i++)  {
-		/* set address to i for MDI[i] */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
-
-		/* get Cable Diagnostic values */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-		pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
-
-		pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
-	}
-
-	return(0);
-}	/* SkGmCableDiagStatus */
-#endif /* !SK_SLIM */
-#endif /* YUKON */
-
-/* End of file */
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
index fe84780..75afc1f 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/skfp/smt.c
@@ -1748,7 +1748,7 @@
 #endif
 
 #ifdef	AM29K
-smt_ifconfig(int argc, char *argv[])
+int smt_ifconfig(int argc, char *argv[])
 {
 	if (argc >= 2 && !strcmp(argv[0],"opt_bypass") &&
 	    !strcmp(argv[1],"yes")) {
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 832fd69..a2f3215 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -39,6 +39,7 @@
 #include <linux/workqueue.h>
 #include <linux/if_vlan.h>
 #include <linux/prefetch.h>
+#include <linux/debugfs.h>
 #include <linux/mii.h>
 
 #include <asm/irq.h>
@@ -50,7 +51,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.14"
+#define DRV_VERSION		"1.16"
 #define PFX			DRV_NAME " "
 
 /*
@@ -64,7 +65,6 @@
 #define RX_MAX_PENDING		(RX_LE_SIZE/6 - 2)
 #define RX_DEF_PENDING		RX_MAX_PENDING
 #define RX_SKB_ALIGN		8
-#define RX_BUF_WRITE		16
 
 #define TX_RING_SIZE		512
 #define TX_DEF_PENDING		(TX_RING_SIZE - 1)
@@ -77,6 +77,9 @@
 #define NAPI_WEIGHT		64
 #define PHY_RETRIES		1000
 
+#define SKY2_EEPROM_MAGIC	0x9955aabb
+
+
 #define RING_NEXT(x,s)	(((x)+1) & ((s)-1))
 
 static const u32 default_msg =
@@ -96,7 +99,7 @@
 module_param(disable_msi, int, 0);
 MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
 
-static int idle_timeout = 0;
+static int idle_timeout = 100;
 module_param(idle_timeout, int, 0);
 MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
 
@@ -130,7 +133,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
-//	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
 	{ 0 }
 };
 
@@ -217,13 +220,24 @@
 		sky2_write8(hw, B2_Y2_CLK_GATE, 0);
 
 	if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
-		u32 reg1;
+		u32 reg;
 
-		sky2_pci_write32(hw, PCI_DEV_REG3, 0);
-		reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
-		reg1 &= P_ASPM_CONTROL_MSK;
-		sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
-		sky2_pci_write32(hw, PCI_DEV_REG5, 0);
+		reg = sky2_pci_read32(hw, PCI_DEV_REG4);
+		/* set all bits to 0 except bits 15..12 and 8 */
+		reg &= P_ASPM_CONTROL_MSK;
+		sky2_pci_write32(hw, PCI_DEV_REG4, reg);
+
+		reg = sky2_pci_read32(hw, PCI_DEV_REG5);
+		/* set all bits to 0 except bits 28 & 27 */
+		reg &= P_CTL_TIM_VMAIN_AV_MSK;
+		sky2_pci_write32(hw, PCI_DEV_REG5, reg);
+
+		sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
+
+		/* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
+		reg = sky2_read32(hw, B2_GP_IO);
+		reg |= GLB_GPIO_STAT_RACE_DIS;
+		sky2_write32(hw, B2_GP_IO, reg);
 	}
 }
 
@@ -364,7 +378,7 @@
 			/* for SFP-module set SIGDET polarity to low */
 			ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
 			ctrl |= PHY_M_FIB_SIGD_POL;
-			gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+			gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
 		}
 
 		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
@@ -650,6 +664,30 @@
 
 }
 
+static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
+{
+	if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+			     TX_STFW_ENA |
+			     (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
+	} else {
+		if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+			/* set Tx GMAC FIFO Almost Empty Threshold */
+			sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+				     (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+
+			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+				     TX_JUMBO_ENA | TX_STFW_DIS);
+
+			/* Can't do offload because of lack of store/forward */
+			hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
+						     | NETIF_F_ALL_CSUM);
+		} else
+			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+				     TX_JUMBO_DIS | TX_STFW_ENA);
+	}
+}
+
 static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 {
 	struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -658,7 +696,7 @@
 	const u8 *addr = hw->dev[port]->dev_addr;
 
 	sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
-	sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR|GPC_ENA_PAUSE);
+	sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR);
 
 	sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
 
@@ -730,8 +768,11 @@
 
 	/* Configure Rx MAC FIFO */
 	sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
-	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
-		     GMF_OPER_ON | GMF_RX_F_FL_ON);
+	reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+	if (hw->chip_id == CHIP_ID_YUKON_EX)
+		reg |= GMF_RX_OVER_ON;
+
+	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
 
 	/* Flush Rx MAC FIFO on any flow control or error */
 	sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
@@ -747,16 +788,7 @@
 		sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
 		sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
 
-		/* set Tx GMAC FIFO Almost Empty Threshold */
-		sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
-			     (ECU_JUMBO_WM << 16) | ECU_AE_THR);
-
-		if (hw->dev[port]->mtu > ETH_DATA_LEN)
-			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-				     TX_JUMBO_ENA | TX_STFW_DIS);
-		else
-			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-				     TX_JUMBO_DIS | TX_STFW_ENA);
+		sky2_set_tx_stfwd(hw, port);
 	}
 
 }
@@ -861,24 +893,18 @@
 	return le;
 }
 
-/* Return high part of DMA address (could be 32 or 64 bit) */
-static inline u32 high32(dma_addr_t a)
-{
-	return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
-}
-
 /* Build description to hardware for one receive segment */
 static void sky2_rx_add(struct sky2_port *sky2,  u8 op,
 			dma_addr_t map, unsigned len)
 {
 	struct sky2_rx_le *le;
-	u32 hi = high32(map);
+	u32 hi = upper_32_bits(map);
 
 	if (sky2->rx_addr64 != hi) {
 		le = sky2_next_rx(sky2);
 		le->addr = cpu_to_le32(hi);
 		le->opcode = OP_ADDR64 | HW_OWNER;
-		sky2->rx_addr64 = high32(map + len);
+		sky2->rx_addr64 = upper_32_bits(map + len);
 	}
 
 	le = sky2_next_rx(sky2);
@@ -939,14 +965,16 @@
 {
 	struct sky2_rx_le *le;
 
-	le = sky2_next_rx(sky2);
-	le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
-	le->ctrl = 0;
-	le->opcode = OP_TCPSTART | HW_OWNER;
+	if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
+		le = sky2_next_rx(sky2);
+		le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+		le->ctrl = 0;
+		le->opcode = OP_TCPSTART | HW_OWNER;
 
-	sky2_write32(sky2->hw,
-		     Q_ADDR(rxqaddr[sky2->port], Q_CSR),
-		     sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+		sky2_write32(sky2->hw,
+			     Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+			     sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+	}
 
 }
 
@@ -1049,26 +1077,22 @@
 	u16 port = sky2->port;
 
 	netif_tx_lock_bh(dev);
+	netif_poll_disable(sky2->hw->dev[0]);
 
-	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON);
-	sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON);
 	sky2->vlgrp = grp;
+	if (grp) {
+		sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+			     RX_VLAN_STRIP_ON);
+		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+			     TX_VLAN_TAG_ON);
+	} else {
+		sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+			     RX_VLAN_STRIP_OFF);
+		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+			     TX_VLAN_TAG_OFF);
+	}
 
-	netif_tx_unlock_bh(dev);
-}
-
-static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct sky2_port *sky2 = netdev_priv(dev);
-	struct sky2_hw *hw = sky2->hw;
-	u16 port = sky2->port;
-
-	netif_tx_lock_bh(dev);
-
-	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF);
-	sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF);
-	vlan_group_set_device(sky2->vlgrp, vid, NULL);
-
+	netif_poll_enable(sky2->hw->dev[0]);
 	netif_tx_unlock_bh(dev);
 }
 #endif
@@ -1110,6 +1134,11 @@
 	return NULL;
 }
 
+static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
+{
+	sky2_put_idx(sky2->hw, rxq, sky2->rx_put);
+}
+
 /*
  * Allocate and setup receiver buffer pool.
  * Normal case this ends up creating one list element for skb
@@ -1138,15 +1167,14 @@
 	if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
 	    (hw->chip_rev == CHIP_REV_YU_EC_U_A1
 	     || hw->chip_rev == CHIP_REV_YU_EC_U_B0))
-		sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
+		sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS);
 
 	sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
 
 	rx_set_checksum(sky2);
 
 	/* Space needed for frame data + headers rounded up */
-	size = ALIGN(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8)
-		+ 8;
+	size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
 
 	/* Stopping point for hardware truncation */
 	thresh = (size - 8) / sizeof(u32);
@@ -1201,7 +1229,7 @@
 	}
 
 	/* Tell chip about available buffers */
-	sky2_put_idx(hw, rxq, sky2->rx_put);
+	sky2_rx_update(sky2, rxq);
 	return 0;
 nomem:
 	sky2_rx_clean(sky2);
@@ -1238,6 +1266,8 @@
 	if (netif_msg_ifup(sky2))
 		printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
 
+	netif_carrier_off(dev);
+
 	/* must be power of 2 */
 	sky2->tx_le = pci_alloc_consistent(hw->pdev,
 					   TX_RING_SIZE *
@@ -1289,6 +1319,10 @@
 
 	sky2_qset(hw, txqaddr[port]);
 
+	/* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */
+	if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0)
+		sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF);
+
 	/* Set almost empty threshold */
 	if (hw->chip_id == CHIP_ID_YUKON_EC_U
 	    && hw->chip_rev == CHIP_REV_YU_EC_U_A0)
@@ -1384,27 +1418,30 @@
 
 	len = skb_headlen(skb);
 	mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
-	addr64 = high32(mapping);
+	addr64 = upper_32_bits(mapping);
 
 	/* Send high bits if changed or crosses boundary */
-	if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) {
+	if (addr64 != sky2->tx_addr64 ||
+	    upper_32_bits(mapping + len) != sky2->tx_addr64) {
 		le = get_tx_le(sky2);
 		le->addr = cpu_to_le32(addr64);
 		le->opcode = OP_ADDR64 | HW_OWNER;
-		sky2->tx_addr64 = high32(mapping + len);
+		sky2->tx_addr64 = upper_32_bits(mapping + len);
 	}
 
 	/* Check for TCP Segmentation Offload */
 	mss = skb_shinfo(skb)->gso_size;
 	if (mss != 0) {
-		mss += tcp_optlen(skb); /* TCP options */
-		mss += ip_hdrlen(skb) + sizeof(struct tcphdr);
-		mss += ETH_HLEN;
+		if (hw->chip_id != CHIP_ID_YUKON_EX)
+			mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
 
-		if (mss != sky2->tx_last_mss) {
-			le = get_tx_le(sky2);
-			le->addr = cpu_to_le32(mss);
-			le->opcode = OP_LRGLEN | HW_OWNER;
+  		if (mss != sky2->tx_last_mss) {
+  			le = get_tx_le(sky2);
+  			le->addr = cpu_to_le32(mss);
+ 			if (hw->chip_id == CHIP_ID_YUKON_EX)
+				le->opcode = OP_MSS | HW_OWNER;
+			else
+				le->opcode = OP_LRGLEN | HW_OWNER;
 			sky2->tx_last_mss = mss;
 		}
 	}
@@ -1426,24 +1463,30 @@
 
 	/* Handle TCP checksum offload */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const unsigned offset = skb_transport_offset(skb);
-		u32 tcpsum;
+		/* On Yukon EX (some versions) encoding change. */
+ 		if (hw->chip_id == CHIP_ID_YUKON_EX
+		    && hw->chip_rev != CHIP_REV_YU_EX_B0)
+ 			ctrl |= CALSUM;	/* auto checksum */
+		else {
+			const unsigned offset = skb_transport_offset(skb);
+			u32 tcpsum;
 
-		tcpsum = offset << 16;		/* sum start */
-		tcpsum |= offset + skb->csum_offset;	/* sum write */
+			tcpsum = offset << 16;			/* sum start */
+			tcpsum |= offset + skb->csum_offset;	/* sum write */
 
-		ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
-		if (ip_hdr(skb)->protocol == IPPROTO_UDP)
-			ctrl |= UDPTCP;
+			ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+			if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+				ctrl |= UDPTCP;
 
-		if (tcpsum != sky2->tx_tcpsum) {
-			sky2->tx_tcpsum = tcpsum;
+			if (tcpsum != sky2->tx_tcpsum) {
+				sky2->tx_tcpsum = tcpsum;
 
-			le = get_tx_le(sky2);
-			le->addr = cpu_to_le32(tcpsum);
-			le->length = 0;	/* initial checksum value */
-			le->ctrl = 1;	/* one packet */
-			le->opcode = OP_TCPLISW | HW_OWNER;
+				le = get_tx_le(sky2);
+				le->addr = cpu_to_le32(tcpsum);
+				le->length = 0;	/* initial checksum value */
+				le->ctrl = 1;	/* one packet */
+				le->opcode = OP_TCPLISW | HW_OWNER;
+			}
 		}
 	}
 
@@ -1463,7 +1506,7 @@
 
 		mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
 				       frag->size, PCI_DMA_TODEVICE);
-		addr64 = high32(mapping);
+		addr64 = upper_32_bits(mapping);
 		if (addr64 != sky2->tx_addr64) {
 			le = get_tx_le(sky2);
 			le->addr = cpu_to_le32(addr64);
@@ -1533,13 +1576,13 @@
 			if (unlikely(netif_msg_tx_done(sky2)))
 				printk(KERN_DEBUG "%s: tx done %u\n",
 				       dev->name, idx);
+
 			sky2->net_stats.tx_packets++;
 			sky2->net_stats.tx_bytes += re->skb->len;
 
 			dev_kfree_skb_any(re->skb);
+			sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE);
 		}
-
-		le->opcode = 0;	/* paranoia */
 	}
 
 	sky2->tx_cons = idx;
@@ -1577,7 +1620,6 @@
 
 	/* Stop more packets from being queued */
 	netif_stop_queue(dev);
-	netif_carrier_off(dev);
 
 	/* Disable port IRQ */
 	imask = sky2_read32(hw, B0_IMSK);
@@ -1629,6 +1671,8 @@
 
 	sky2_phy_power(hw, port, 0);
 
+	netif_carrier_off(dev);
+
 	/* turn off LED's */
 	sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
 
@@ -1693,7 +1737,6 @@
 	gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
 
 	netif_carrier_on(sky2->netdev);
-	netif_wake_queue(sky2->netdev);
 
 	/* Turn on link LED */
 	sky2_write8(hw, SK_REG(port, LNK_LED_REG),
@@ -1745,7 +1788,6 @@
 	gma_write16(hw, port, GM_GP_CTRL, reg);
 
 	netif_carrier_off(sky2->netdev);
-	netif_stop_queue(sky2->netdev);
 
 	/* Turn on link LED */
 	sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
@@ -1917,15 +1959,8 @@
 
 	synchronize_irq(hw->pdev->irq);
 
-	if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
-		if (new_mtu > ETH_DATA_LEN) {
-			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-				     TX_JUMBO_ENA | TX_STFW_DIS);
-			dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
-		} else
-			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-				     TX_JUMBO_DIS | TX_STFW_ENA);
-	}
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+		sky2_set_tx_stfwd(hw, port);
 
 	ctl = gma_read16(hw, port, GM_GP_CTRL);
 	gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
@@ -2023,8 +2058,6 @@
 	struct sk_buff *skb, *nskb;
 	unsigned hdr_space = sky2->rx_data_size;
 
-	pr_debug(PFX "receive new length=%d\n", length);
-
 	/* Don't be tricky about reusing pages (yet) */
 	nskb = sky2_rx_alloc(sky2);
 	if (unlikely(!nskb))
@@ -2068,6 +2101,9 @@
 	if (!(status & GMR_FS_RX_OK))
 		goto resubmit;
 
+	if (status >> 16 != length)
+		goto len_mismatch;
+
 	if (length < copybreak)
 		skb = receive_copy(sky2, re, length);
 	else
@@ -2077,6 +2113,11 @@
 
 	return skb;
 
+len_mismatch:
+	/* Truncation of overlength packets
+	   causes PHY length to not match MAC length */
+	++sky2->net_stats.rx_length_errors;
+
 error:
 	++sky2->net_stats.rx_errors;
 	if (status & GMR_FS_RX_FF_OV) {
@@ -2113,15 +2154,16 @@
 /* Process status response ring */
 static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 {
-	struct sky2_port *sky2;
 	int work_done = 0;
-	unsigned buf_write[2] = { 0, 0 };
+	unsigned rx[2] = { 0, 0 };
 	u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
 
 	rmb();
 
 	while (hw->st_idx != hwidx) {
+		struct sky2_port *sky2;
 		struct sky2_status_le *le  = hw->st_le + hw->st_idx;
+		unsigned port = le->css & CSS_LINK_BIT;
 		struct net_device *dev;
 		struct sk_buff *skb;
 		u32 status;
@@ -2129,19 +2171,28 @@
 
 		hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
 
-		BUG_ON(le->link >= 2);
-		dev = hw->dev[le->link];
-
+		dev = hw->dev[port];
 		sky2 = netdev_priv(dev);
 		length = le16_to_cpu(le->length);
 		status = le32_to_cpu(le->status);
 
 		switch (le->opcode & ~HW_OWNER) {
 		case OP_RXSTAT:
+			++rx[port];
 			skb = sky2_receive(dev, length, status);
 			if (unlikely(!skb)) {
 				sky2->net_stats.rx_dropped++;
-				goto force_update;
+				break;
+			}
+
+			/* This chip reports checksum status differently */
+			if (hw->chip_id == CHIP_ID_YUKON_EX) {
+				if (sky2->rx_csum &&
+				    (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
+				    (le->css & CSS_TCPUDPCSOK))
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
+				else
+					skb->ip_summed = CHECKSUM_NONE;
 			}
 
 			skb->protocol = eth_type_trans(skb, dev);
@@ -2158,13 +2209,6 @@
 #endif
 				netif_receive_skb(skb);
 
-			/* Update receiver after 16 frames */
-			if (++buf_write[le->link] == RX_BUF_WRITE) {
-force_update:
-				sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put);
-				buf_write[le->link] = 0;
-			}
-
 			/* Stop after net poll weight */
 			if (++work_done >= to_do)
 				goto exit_loop;
@@ -2183,6 +2227,9 @@
 			if (!sky2->rx_csum)
 				break;
 
+			if (hw->chip_id == CHIP_ID_YUKON_EX)
+				break;
+
 			/* Both checksum counters are programmed to start at
 			 * the same offset, so unless there is a problem they
 			 * should match. This failure is an early indication that
@@ -2198,7 +2245,7 @@
 				       dev->name, status);
 				sky2->rx_csum = 0;
 				sky2_write32(sky2->hw,
-					     Q_ADDR(rxqaddr[le->link], Q_CSR),
+					     Q_ADDR(rxqaddr[port], Q_CSR),
 					     BMU_DIS_RX_CHKSUM);
 			}
 			break;
@@ -2217,24 +2264,18 @@
 			if (net_ratelimit())
 				printk(KERN_WARNING PFX
 				       "unknown status opcode 0x%x\n", le->opcode);
-			goto exit_loop;
 		}
 	}
 
 	/* Fully processed status ring so clear irq */
 	sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-	mmiowb();
 
 exit_loop:
-	if (buf_write[0]) {
-		sky2 = netdev_priv(hw->dev[0]);
-		sky2_put_idx(hw, Q_R1, sky2->rx_put);
-	}
+	if (rx[0])
+		sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1);
 
-	if (buf_write[1]) {
-		sky2 = netdev_priv(hw->dev[1]);
-		sky2_put_idx(hw, Q_R2, sky2->rx_put);
-	}
+	if (rx[1])
+		sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2);
 
 	return work_done;
 }
@@ -2431,8 +2472,7 @@
 static int sky2_poll(struct net_device *dev0, int *budget)
 {
 	struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
-	int work_limit = min(dev0->quota, *budget);
-	int work_done = 0;
+	int work_done;
 	u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
 
 	if (unlikely(status & Y2_IS_ERROR))
@@ -2444,18 +2484,25 @@
 	if (status & Y2_IS_IRQ_PHY2)
 		sky2_phy_intr(hw, 1);
 
-	work_done = sky2_status_intr(hw, work_limit);
-	if (work_done < work_limit) {
-		netif_rx_complete(dev0);
+	work_done = sky2_status_intr(hw, min(dev0->quota, *budget));
+	*budget -= work_done;
+	dev0->quota -= work_done;
 
-		/* end of interrupt, re-enables also acts as I/O synchronization */
-		sky2_read32(hw, B0_Y2_SP_LISR);
-		return 0;
-	} else {
-		*budget -= work_done;
-		dev0->quota -= work_done;
+	/* More work? */
+ 	if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX))
 		return 1;
+
+	/* Bug/Errata workaround?
+	 * Need to kick the TX irq moderation timer.
+	 */
+	if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+		sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+		sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
 	}
+	netif_rx_complete(dev0);
+
+	sky2_read32(hw, B0_Y2_SP_LISR);
+	return 0;
 }
 
 static irqreturn_t sky2_intr(int irq, void *dev_id)
@@ -2517,6 +2564,9 @@
 {
 	u8 t8;
 
+	/* Enable all clocks */
+	sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
 	sky2_write8(hw, B0_CTST, CS_RST_CLR);
 
 	hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
@@ -2526,14 +2576,6 @@
 		return -EOPNOTSUPP;
 	}
 
-	if (hw->chip_id == CHIP_ID_YUKON_EX)
-		dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n"
-			 "Please report success or failure to <netdev@vger.kernel.org>\n");
-
-	/* Make sure and enable all clocks */
-	if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
-		sky2_pci_write32(hw, PCI_DEV_REG3, 0);
-
 	hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
 
 	/* This rev is really old, and requires untested workarounds */
@@ -2593,6 +2635,11 @@
 	for (i = 0; i < hw->ports; i++) {
 		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
 		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+
+		if (hw->chip_id == CHIP_ID_YUKON_EX)
+			sky2_write16(hw, SK_REG(i, GMAC_CTRL),
+				     GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
+				     | GMC_BYP_RETR_ON);
 	}
 
 	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
@@ -2679,8 +2726,6 @@
 	struct net_device *dev;
 	int i, err;
 
-	dev_dbg(&hw->pdev->dev, "restarting\n");
-
 	del_timer_sync(&hw->idle_timer);
 
 	rtnl_lock();
@@ -2739,7 +2784,7 @@
 
 	sky2->wol = wol->wolopts;
 
-	if (hw->chip_id == CHIP_ID_YUKON_EC_U)
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
 		sky2_write32(hw, B0_CTST, sky2->wol
 			     ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
 
@@ -3334,7 +3379,7 @@
 
 /*
  * Returns copy of control register region
- * Note: access to the RAM address register set will cause timeouts.
+ * Note: ethtool_get_regs always provides full size (16k) buffer
  */
 static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 			  void *p)
@@ -3342,15 +3387,19 @@
 	const struct sky2_port *sky2 = netdev_priv(dev);
 	const void __iomem *io = sky2->hw->regs;
 
-	BUG_ON(regs->len < B3_RI_WTO_R1);
 	regs->version = 1;
 	memset(p, 0, regs->len);
 
 	memcpy_fromio(p, io, B3_RAM_ADDR);
 
-	memcpy_fromio(p + B3_RI_WTO_R1,
-		      io + B3_RI_WTO_R1,
-		      regs->len - B3_RI_WTO_R1);
+	/* skip diagnostic ram region */
+	memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1);
+
+	/* copy GMAC registers */
+	memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000);
+	if (sky2->hw->ports > 1)
+		memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000);
+
 }
 
 /* In order to do Jumbo packets on these chips, need to turn off the
@@ -3361,9 +3410,7 @@
 	const struct sky2_port *sky2 = netdev_priv(dev);
 	const struct sky2_hw *hw = sky2->hw;
 
-	return dev->mtu > ETH_DATA_LEN &&
-		(hw->chip_id == CHIP_ID_YUKON_EX
-		 || hw->chip_id == CHIP_ID_YUKON_EC_U);
+	return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U;
 }
 
 static int sky2_set_tx_csum(struct net_device *dev, u32 data)
@@ -3383,39 +3430,315 @@
 	return ethtool_op_set_tso(dev, data);
 }
 
+static int sky2_get_eeprom_len(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	u16 reg2;
+
+	reg2 = sky2_pci_read32(sky2->hw, PCI_DEV_REG2);
+	return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+}
+
+static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset)
+{
+	sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
+
+	while (!(sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F))
+			cpu_relax();
+	return sky2_pci_read32(hw, cap + PCI_VPD_DATA);
+}
+
+static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val)
+{
+	sky2_pci_write32(hw, cap + PCI_VPD_DATA, val);
+	sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
+	do {
+		cpu_relax();
+	} while (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F);
+}
+
+static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+			   u8 *data)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+	int length = eeprom->len;
+	u16 offset = eeprom->offset;
+
+	if (!cap)
+		return -EINVAL;
+
+	eeprom->magic = SKY2_EEPROM_MAGIC;
+
+	while (length > 0) {
+		u32 val = sky2_vpd_read(sky2->hw, cap, offset);
+		int n = min_t(int, length, sizeof(val));
+
+		memcpy(data, &val, n);
+		length -= n;
+		data += n;
+		offset += n;
+	}
+	return 0;
+}
+
+static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+			   u8 *data)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+	int length = eeprom->len;
+	u16 offset = eeprom->offset;
+
+	if (!cap)
+		return -EINVAL;
+
+	if (eeprom->magic != SKY2_EEPROM_MAGIC)
+		return -EINVAL;
+
+	while (length > 0) {
+		u32 val;
+		int n = min_t(int, length, sizeof(val));
+
+		if (n < sizeof(val))
+			val = sky2_vpd_read(sky2->hw, cap, offset);
+		memcpy(&val, data, n);
+
+		sky2_vpd_write(sky2->hw, cap, offset, val);
+
+		length -= n;
+		data += n;
+		offset += n;
+	}
+	return 0;
+}
+
+
 static const struct ethtool_ops sky2_ethtool_ops = {
-	.get_settings = sky2_get_settings,
-	.set_settings = sky2_set_settings,
-	.get_drvinfo  = sky2_get_drvinfo,
-	.get_wol      = sky2_get_wol,
-	.set_wol      = sky2_set_wol,
-	.get_msglevel = sky2_get_msglevel,
-	.set_msglevel = sky2_set_msglevel,
-	.nway_reset   = sky2_nway_reset,
-	.get_regs_len = sky2_get_regs_len,
-	.get_regs = sky2_get_regs,
-	.get_link = ethtool_op_get_link,
-	.get_sg = ethtool_op_get_sg,
-	.set_sg = ethtool_op_set_sg,
-	.get_tx_csum = ethtool_op_get_tx_csum,
-	.set_tx_csum = sky2_set_tx_csum,
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = sky2_set_tso,
-	.get_rx_csum = sky2_get_rx_csum,
-	.set_rx_csum = sky2_set_rx_csum,
-	.get_strings = sky2_get_strings,
-	.get_coalesce = sky2_get_coalesce,
-	.set_coalesce = sky2_set_coalesce,
-	.get_ringparam = sky2_get_ringparam,
-	.set_ringparam = sky2_set_ringparam,
+	.get_settings	= sky2_get_settings,
+	.set_settings	= sky2_set_settings,
+	.get_drvinfo	= sky2_get_drvinfo,
+	.get_wol	= sky2_get_wol,
+	.set_wol	= sky2_set_wol,
+	.get_msglevel	= sky2_get_msglevel,
+	.set_msglevel	= sky2_set_msglevel,
+	.nway_reset	= sky2_nway_reset,
+	.get_regs_len	= sky2_get_regs_len,
+	.get_regs	= sky2_get_regs,
+	.get_link	= ethtool_op_get_link,
+	.get_eeprom_len	= sky2_get_eeprom_len,
+	.get_eeprom	= sky2_get_eeprom,
+	.set_eeprom	= sky2_set_eeprom,
+	.get_sg 	= ethtool_op_get_sg,
+	.set_sg 	= ethtool_op_set_sg,
+	.get_tx_csum	= ethtool_op_get_tx_csum,
+	.set_tx_csum	= sky2_set_tx_csum,
+	.get_tso	= ethtool_op_get_tso,
+	.set_tso	= sky2_set_tso,
+	.get_rx_csum	= sky2_get_rx_csum,
+	.set_rx_csum	= sky2_set_rx_csum,
+	.get_strings	= sky2_get_strings,
+	.get_coalesce	= sky2_get_coalesce,
+	.set_coalesce	= sky2_set_coalesce,
+	.get_ringparam	= sky2_get_ringparam,
+	.set_ringparam	= sky2_set_ringparam,
 	.get_pauseparam = sky2_get_pauseparam,
 	.set_pauseparam = sky2_set_pauseparam,
-	.phys_id = sky2_phys_id,
+	.phys_id	= sky2_phys_id,
 	.get_stats_count = sky2_get_stats_count,
 	.get_ethtool_stats = sky2_get_ethtool_stats,
 	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
+#ifdef CONFIG_SKY2_DEBUG
+
+static struct dentry *sky2_debug;
+
+static int sky2_debug_show(struct seq_file *seq, void *v)
+{
+	struct net_device *dev = seq->private;
+	const struct sky2_port *sky2 = netdev_priv(dev);
+	const struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	unsigned idx, last;
+	int sop;
+
+	if (!netif_running(dev))
+		return -ENETDOWN;
+
+	seq_printf(seq, "IRQ src=%x mask=%x control=%x\n",
+		   sky2_read32(hw, B0_ISRC),
+		   sky2_read32(hw, B0_IMSK),
+		   sky2_read32(hw, B0_Y2_SP_ICR));
+
+	netif_poll_disable(hw->dev[0]);
+	last = sky2_read16(hw, STAT_PUT_IDX);
+
+	if (hw->st_idx == last)
+		seq_puts(seq, "Status ring (empty)\n");
+	else {
+		seq_puts(seq, "Status ring\n");
+		for (idx = hw->st_idx; idx != last && idx < STATUS_RING_SIZE;
+		     idx = RING_NEXT(idx, STATUS_RING_SIZE)) {
+			const struct sky2_status_le *le = hw->st_le + idx;
+			seq_printf(seq, "[%d] %#x %d %#x\n",
+				   idx, le->opcode, le->length, le->status);
+		}
+		seq_puts(seq, "\n");
+	}
+
+	seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n",
+		   sky2->tx_cons, sky2->tx_prod,
+		   sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
+		   sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE)));
+
+	/* Dump contents of tx ring */
+	sop = 1;
+	for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < TX_RING_SIZE;
+	     idx = RING_NEXT(idx, TX_RING_SIZE)) {
+		const struct sky2_tx_le *le = sky2->tx_le + idx;
+		u32 a = le32_to_cpu(le->addr);
+
+		if (sop)
+			seq_printf(seq, "%u:", idx);
+		sop = 0;
+
+		switch(le->opcode & ~HW_OWNER) {
+		case OP_ADDR64:
+			seq_printf(seq, " %#x:", a);
+			break;
+		case OP_LRGLEN:
+			seq_printf(seq, " mtu=%d", a);
+			break;
+		case OP_VLAN:
+			seq_printf(seq, " vlan=%d", be16_to_cpu(le->length));
+			break;
+		case OP_TCPLISW:
+			seq_printf(seq, " csum=%#x", a);
+			break;
+		case OP_LARGESEND:
+			seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length));
+			break;
+		case OP_PACKET:
+			seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length));
+			break;
+		case OP_BUFFER:
+			seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length));
+			break;
+		default:
+			seq_printf(seq, " op=%#x,%#x(%d)", le->opcode,
+				   a, le16_to_cpu(le->length));
+		}
+
+		if (le->ctrl & EOP) {
+			seq_putc(seq, '\n');
+			sop = 1;
+		}
+	}
+
+	seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n",
+		   sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)),
+		   last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
+		   sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
+
+	netif_poll_enable(hw->dev[0]);
+	return 0;
+}
+
+static int sky2_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sky2_debug_show, inode->i_private);
+}
+
+static const struct file_operations sky2_debug_fops = {
+	.owner		= THIS_MODULE,
+	.open		= sky2_debug_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/*
+ * Use network device events to create/remove/rename
+ * debugfs file entries
+ */
+static int sky2_device_event(struct notifier_block *unused,
+			     unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+
+	if (dev->open == sky2_up) {
+		struct sky2_port *sky2 = netdev_priv(dev);
+
+		switch(event) {
+		case NETDEV_CHANGENAME:
+			if (!netif_running(dev))
+				break;
+			/* fallthrough */
+		case NETDEV_DOWN:
+		case NETDEV_GOING_DOWN:
+			if (sky2->debugfs) {
+				printk(KERN_DEBUG PFX "%s: remove debugfs\n",
+				       dev->name);
+				debugfs_remove(sky2->debugfs);
+				sky2->debugfs = NULL;
+			}
+
+			if (event != NETDEV_CHANGENAME)
+				break;
+			/* fallthrough for changename */
+		case NETDEV_UP:
+			if (sky2_debug) {
+				struct dentry *d;
+				d = debugfs_create_file(dev->name, S_IRUGO,
+							sky2_debug, dev,
+							&sky2_debug_fops);
+				if (d == NULL || IS_ERR(d))
+					printk(KERN_INFO PFX
+					       "%s: debugfs create failed\n",
+					       dev->name);
+				else
+					sky2->debugfs = d;
+			}
+			break;
+		}
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block sky2_notifier = {
+	.notifier_call = sky2_device_event,
+};
+
+
+static __init void sky2_debug_init(void)
+{
+	struct dentry *ent;
+
+	ent = debugfs_create_dir("sky2", NULL);
+	if (!ent || IS_ERR(ent))
+		return;
+
+	sky2_debug = ent;
+	register_netdevice_notifier(&sky2_notifier);
+}
+
+static __exit void sky2_debug_cleanup(void)
+{
+	if (sky2_debug) {
+		unregister_netdevice_notifier(&sky2_notifier);
+		debugfs_remove(sky2_debug);
+		sky2_debug = NULL;
+	}
+}
+
+#else
+#define sky2_debug_init()
+#define sky2_debug_cleanup()
+#endif
+
+
 /* Initialize network device */
 static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
 						     unsigned port,
@@ -3484,17 +3807,12 @@
 #ifdef SKY2_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = sky2_vlan_rx_register;
-	dev->vlan_rx_kill_vid = sky2_vlan_rx_kill_vid;
 #endif
 
 	/* read the mac address */
 	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-	/* device is off until link detection */
-	netif_carrier_off(dev);
-	netif_stop_queue(dev);
-
 	return dev;
 }
 
@@ -3911,12 +4229,14 @@
 
 static int __init sky2_init_module(void)
 {
+	sky2_debug_init();
 	return pci_register_driver(&sky2_driver);
 }
 
 static void __exit sky2_cleanup_module(void)
 {
 	pci_unregister_driver(&sky2_driver);
+	sky2_debug_cleanup();
 }
 
 module_init(sky2_init_module);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 5efb5af..dce4d27 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -14,6 +14,8 @@
 	PCI_DEV_REG3	= 0x80,
 	PCI_DEV_REG4	= 0x84,
 	PCI_DEV_REG5    = 0x88,
+	PCI_CFG_REG_0	= 0x90,
+	PCI_CFG_REG_1	= 0x94,
 };
 
 enum {
@@ -28,6 +30,7 @@
 enum pci_dev_reg_1 {
 	PCI_Y2_PIG_ENA	 = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
 	PCI_Y2_DLL_DIS	 = 1<<30, /* Disable PCI DLL (YUKON-2) */
+	PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */
 	PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
 	PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
 	PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
@@ -67,6 +70,80 @@
 				  | P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
 };
 
+/*	PCI_OUR_REG_5		32 bit	Our Register 5 (Yukon-ECU only) */
+enum pci_dev_reg_5 {
+					/* Bit 31..27:	for A3 & later */
+	P_CTL_DIV_CORE_CLK_ENA	= 1<<31, /* Divide Core Clock Enable */
+	P_CTL_SRESET_VMAIN_AV	= 1<<30, /* Soft Reset for Vmain_av De-Glitch */
+	P_CTL_BYPASS_VMAIN_AV	= 1<<29, /* Bypass En. for Vmain_av De-Glitch */
+	P_CTL_TIM_VMAIN_AV_MSK	= 3<<27, /* Bit 28..27: Timer Vmain_av Mask */
+					 /* Bit 26..16: Release Clock on Event */
+	P_REL_PCIE_RST_DE_ASS	= 1<<26, /* PCIe Reset De-Asserted */
+	P_REL_GPHY_REC_PACKET	= 1<<25, /* GPHY Received Packet */
+	P_REL_INT_FIFO_N_EMPTY	= 1<<24, /* Internal FIFO Not Empty */
+	P_REL_MAIN_PWR_AVAIL	= 1<<23, /* Main Power Available */
+	P_REL_CLKRUN_REQ_REL	= 1<<22, /* CLKRUN Request Release */
+	P_REL_PCIE_RESET_ASS	= 1<<21, /* PCIe Reset Asserted */
+	P_REL_PME_ASSERTED	= 1<<20, /* PME Asserted */
+	P_REL_PCIE_EXIT_L1_ST	= 1<<19, /* PCIe Exit L1 State */
+	P_REL_LOADER_NOT_FIN	= 1<<18, /* EPROM Loader Not Finished */
+	P_REL_PCIE_RX_EX_IDLE	= 1<<17, /* PCIe Rx Exit Electrical Idle State */
+	P_REL_GPHY_LINK_UP	= 1<<16, /* GPHY Link Up */
+
+					/* Bit 10.. 0: Mask for Gate Clock */
+	P_GAT_PCIE_RST_ASSERTED	= 1<<10,/* PCIe Reset Asserted */
+	P_GAT_GPHY_N_REC_PACKET	= 1<<9, /* GPHY Not Received Packet */
+	P_GAT_INT_FIFO_EMPTY	= 1<<8, /* Internal FIFO Empty */
+	P_GAT_MAIN_PWR_N_AVAIL	= 1<<7, /* Main Power Not Available */
+	P_GAT_CLKRUN_REQ_REL	= 1<<6, /* CLKRUN Not Requested */
+	P_GAT_PCIE_RESET_ASS	= 1<<5, /* PCIe Reset Asserted */
+	P_GAT_PME_DE_ASSERTED	= 1<<4, /* PME De-Asserted */
+	P_GAT_PCIE_ENTER_L1_ST	= 1<<3, /* PCIe Enter L1 State */
+	P_GAT_LOADER_FINISHED	= 1<<2, /* EPROM Loader Finished */
+	P_GAT_PCIE_RX_EL_IDLE	= 1<<1, /* PCIe Rx Electrical Idle State */
+	P_GAT_GPHY_LINK_DOWN	= 1<<0,	/* GPHY Link Down */
+
+	PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET |
+				     P_REL_INT_FIFO_N_EMPTY |
+				     P_REL_PCIE_EXIT_L1_ST |
+				     P_REL_PCIE_RX_EX_IDLE |
+				     P_GAT_GPHY_N_REC_PACKET |
+				     P_GAT_INT_FIFO_EMPTY |
+				     P_GAT_PCIE_ENTER_L1_ST |
+				     P_GAT_PCIE_RX_EL_IDLE,
+};
+
+#/*	PCI_CFG_REG_1			32 bit	Config Register 1 (Yukon-Ext only) */
+enum pci_cfg_reg1 {
+	P_CF1_DIS_REL_EVT_RST	= 1<<24, /* Dis. Rel. Event during PCIE reset */
+										/* Bit 23..21: Release Clock on Event */
+	P_CF1_REL_LDR_NOT_FIN	= 1<<23, /* EEPROM Loader Not Finished */
+	P_CF1_REL_VMAIN_AVLBL	= 1<<22, /* Vmain available */
+	P_CF1_REL_PCIE_RESET	= 1<<21, /* PCI-E reset */
+										/* Bit 20..18: Gate Clock on Event */
+	P_CF1_GAT_LDR_NOT_FIN	= 1<<20, /* EEPROM Loader Finished */
+	P_CF1_GAT_PCIE_RX_IDLE	= 1<<19, /* PCI-E Rx Electrical idle */
+	P_CF1_GAT_PCIE_RESET	= 1<<18, /* PCI-E Reset */
+	P_CF1_PRST_PHY_CLKREQ	= 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */
+	P_CF1_PCIE_RST_CLKREQ	= 1<<16, /* Enable PCI-E rst generate CLKREQ */
+
+	P_CF1_ENA_CFG_LDR_DONE	= 1<<8, /* Enable core level Config loader done */
+
+	P_CF1_ENA_TXBMU_RD_IDLE	= 1<<1, /* Enable TX BMU Read  IDLE for ASPM */
+	P_CF1_ENA_TXBMU_WR_IDLE	= 1<<0, /* Enable TX BMU Write IDLE for ASPM */
+
+	PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST |
+					P_CF1_REL_LDR_NOT_FIN |
+					P_CF1_REL_VMAIN_AVLBL |
+					P_CF1_REL_PCIE_RESET |
+					P_CF1_GAT_LDR_NOT_FIN |
+					P_CF1_GAT_PCIE_RESET |
+					P_CF1_PRST_PHY_CLKREQ |
+					P_CF1_ENA_CFG_LDR_DONE |
+					P_CF1_ENA_TXBMU_RD_IDLE |
+					P_CF1_ENA_TXBMU_WR_IDLE,
+};
+
 
 #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
 			       PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -364,6 +441,20 @@
 	TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
 };
 
+/* 	B2_GPIO */
+enum {
+	GLB_GPIO_CLK_DEB_ENA = 1<<31,	/* Clock Debug Enable */
+	GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */
+
+	GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */
+	GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */
+	GLB_GPIO_STAT_RACE_DIS	= 1<<13, /* Status Race Disable */
+	GLB_GPIO_TEST_SEL_MSK	= 3<<11, /* Testmode Select */
+	GLB_GPIO_TEST_SEL_BASE	= 1<<11,
+	GLB_GPIO_RAND_ENA	= 1<<10, /* Random Enable */
+	GLB_GPIO_RAND_BIT_1	= 1<<9,  /* Random Bit 1 */
+};
+
 /*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
 enum {
 	CFG_CHIP_R_MSK	  = 0xf<<4,	/* Bit 7.. 4: Chip Revision */
@@ -392,6 +483,11 @@
 	CHIP_REV_YU_FE_A2    = 2,
 
 };
+enum yukon_ex_rev {
+	CHIP_REV_YU_EX_A0    = 1,
+	CHIP_REV_YU_EX_B0    = 2,
+};
+
 
 /*	B2_Y2_CLK_GATE	 8 bit	Clock Gating (Yukon-2 only) */
 enum {
@@ -515,23 +611,15 @@
 enum {
 	B8_Q_REGS = 0x0400, /* base of Queue registers */
 	Q_D	= 0x00,	/* 8*32	bit	Current Descriptor */
-	Q_DA_L	= 0x20,	/* 32 bit	Current Descriptor Address Low dWord */
-	Q_DA_H	= 0x24,	/* 32 bit	Current Descriptor Address High dWord */
+	Q_VLAN  = 0x20, /* 16 bit	Current VLAN Tag */
+	Q_DONE	= 0x24,	/* 16 bit	Done Index */
 	Q_AC_L	= 0x28,	/* 32 bit	Current Address Counter Low dWord */
 	Q_AC_H	= 0x2c,	/* 32 bit	Current Address Counter High dWord */
 	Q_BC	= 0x30,	/* 32 bit	Current Byte Counter */
 	Q_CSR	= 0x34,	/* 32 bit	BMU Control/Status Register */
-	Q_F	= 0x38,	/* 32 bit	Flag Register */
-	Q_T1	= 0x3c,	/* 32 bit	Test Register 1 */
-	Q_T1_TR	= 0x3c,	/*  8 bit	Test Register 1 Transfer SM */
-	Q_T1_WR	= 0x3d,	/*  8 bit	Test Register 1 Write Descriptor SM */
-	Q_T1_RD	= 0x3e,	/*  8 bit	Test Register 1 Read Descriptor SM */
-	Q_T1_SV	= 0x3f,	/*  8 bit	Test Register 1 Supervisor SM */
-	Q_T2	= 0x40,	/* 32 bit	Test Register 2	*/
-	Q_T3	= 0x44,	/* 32 bit	Test Register 3	*/
+	Q_TEST	= 0x38,	/* 32 bit	Test/Control Register */
 
 /* Yukon-2 */
-	Q_DONE	= 0x24,	/* 16 bit	Done Index 		(Yukon-2 only) */
 	Q_WM	= 0x40,	/* 16 bit	FIFO Watermark */
 	Q_AL	= 0x42,	/*  8 bit	FIFO Alignment */
 	Q_RSP	= 0x44,	/* 16 bit	FIFO Read Shadow Pointer */
@@ -545,15 +633,16 @@
 };
 #define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
 
-/*	Q_F				32 bit	Flag Register */
+/*	Q_TEST				32 bit	Test Register */
 enum {
-	F_ALM_FULL	= 1<<27, /* Rx FIFO: almost full */
-	F_EMPTY		= 1<<27, /* Tx FIFO: empty flag */
-	F_FIFO_EOF	= 1<<26, /* Tag (EOF Flag) bit in FIFO */
-	F_WM_REACHED	= 1<<25, /* Watermark reached */
+	/* Transmit */
+	F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */
+	F_TX_CHK_AUTO_ON  = 1<<30, /* Tx checksum auto calc off (Yukon EX) */
+
+	/* Receive */
 	F_M_RX_RAM_DIS	= 1<<24, /* MAC Rx RAM Read Port disable */
-	F_FIFO_LEVEL	= 0x1fL<<16, /* Bit 23..16:	# of Qwords in FIFO */
-	F_WATER_MARK	= 0x0007ffL, /* Bit 10.. 0:	Watermark */
+
+	/* Hardware testbits not used */
 };
 
 /* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
@@ -1149,7 +1238,7 @@
 	PHY_M_IS_JABBER		= 1<<0, /* Jabber */
 
 	PHY_M_DEF_MSK		= PHY_M_IS_LSP_CHANGE | PHY_M_IS_LST_CHANGE
-				 | PHY_M_IS_FIFO_ERROR,
+				 | PHY_M_IS_DUP_CHANGE,
 	PHY_M_AN_MSK	       = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL,
 };
 
@@ -1608,6 +1697,16 @@
 	RX_VLAN_STRIP_ON = 1<<25,	/* enable  VLAN stripping */
 	RX_VLAN_STRIP_OFF = 1<<24,	/* disable VLAN stripping */
 
+	RX_MACSEC_FLUSH_ON  = 1<<23,
+	RX_MACSEC_FLUSH_OFF = 1<<22,
+	RX_MACSEC_ASF_FLUSH_ON = 1<<21,
+	RX_MACSEC_ASF_FLUSH_OFF = 1<<20,
+
+	GMF_RX_OVER_ON      = 1<<19,	/* enable flushing on receive overrun */
+	GMF_RX_OVER_OFF     = 1<<18,	/* disable flushing on receive overrun */
+	GMF_ASF_RX_OVER_ON  = 1<<17,	/* enable flushing of ASF when overrun */
+	GMF_ASF_RX_OVER_OFF = 1<<16,	/* disable flushing of ASF when overrun */
+
 	GMF_WP_TST_ON	= 1<<14,	/* Write Pointer Test On */
 	GMF_WP_TST_OFF	= 1<<13,	/* Write Pointer Test Off */
 	GMF_WP_STEP	= 1<<12,	/* Write Pointer Step/Increment */
@@ -1720,6 +1819,15 @@
 
 /*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
 enum {
+	GMC_SET_RST	    = 1<<15,/* MAC SEC RST */
+	GMC_SEC_RST_OFF     = 1<<14,/* MAC SEC RSt OFF */
+	GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */
+	GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */
+	GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */
+	GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX  off*/
+	GMC_BYP_RETR_ON	= 1<<9, /* Bypass retransmit FIFO On */
+	GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */
+
 	GMC_H_BURST_ON	= 1<<7,	/* Half Duplex Burst Mode On */
 	GMC_H_BURST_OFF	= 1<<6,	/* Half Duplex Burst Mode Off */
 	GMC_F_LOOPB_ON	= 1<<5,	/* FIFO Loopback On */
@@ -1732,28 +1840,6 @@
 
 /*	GPHY_CTRL		32 bit	GPHY Control Reg (YUKON only) */
 enum {
-	GPC_SEL_BDT	= 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */
-	GPC_INT_POL_HI	= 1<<27, /* IRQ Polarity is Active HIGH */
-	GPC_75_OHM	= 1<<26, /* Use 75 Ohm Termination instead of 50 */
-	GPC_DIS_FC	= 1<<25, /* Disable Automatic Fiber/Copper Detection */
-	GPC_DIS_SLEEP	= 1<<24, /* Disable Energy Detect */
-	GPC_HWCFG_M_3	= 1<<23, /* HWCFG_MODE[3] */
-	GPC_HWCFG_M_2	= 1<<22, /* HWCFG_MODE[2] */
-	GPC_HWCFG_M_1	= 1<<21, /* HWCFG_MODE[1] */
-	GPC_HWCFG_M_0	= 1<<20, /* HWCFG_MODE[0] */
-	GPC_ANEG_0	= 1<<19, /* ANEG[0] */
-	GPC_ENA_XC	= 1<<18, /* Enable MDI crossover */
-	GPC_DIS_125	= 1<<17, /* Disable 125 MHz clock */
-	GPC_ANEG_3	= 1<<16, /* ANEG[3] */
-	GPC_ANEG_2	= 1<<15, /* ANEG[2] */
-	GPC_ANEG_1	= 1<<14, /* ANEG[1] */
-	GPC_ENA_PAUSE	= 1<<13, /* Enable Pause (SYM_OR_REM) */
-	GPC_PHYADDR_4	= 1<<12, /* Bit 4 of Phy Addr */
-	GPC_PHYADDR_3	= 1<<11, /* Bit 3 of Phy Addr */
-	GPC_PHYADDR_2	= 1<<10, /* Bit 2 of Phy Addr */
-	GPC_PHYADDR_1	= 1<<9,	 /* Bit 1 of Phy Addr */
-	GPC_PHYADDR_0	= 1<<8,	 /* Bit 0 of Phy Addr */
-						/* Bits  7..2:	reserved */
 	GPC_RST_CLR	= 1<<1,	/* Clear GPHY Reset */
 	GPC_RST_SET	= 1<<0,	/* Set   GPHY Reset */
 };
@@ -1827,9 +1913,13 @@
 	OP_ADDR64VLAN	= OP_ADDR64 | OP_VLAN,
 	OP_LRGLEN	= 0x24,
 	OP_LRGLENVLAN	= OP_LRGLEN | OP_VLAN,
+	OP_MSS		= 0x28,
+	OP_MSSVLAN	= OP_MSS | OP_VLAN,
+
 	OP_BUFFER	= 0x40,
 	OP_PACKET	= 0x41,
 	OP_LARGESEND	= 0x43,
+	OP_LSOV2	= 0x45,
 
 /* YUKON-2 STATUS opcodes defines */
 	OP_RXSTAT	= 0x60,
@@ -1840,6 +1930,19 @@
 	OP_RXTIMEVLAN	= OP_RXTIMESTAMP | OP_RXVLAN,
 	OP_RSS_HASH	= 0x65,
 	OP_TXINDEXLE	= 0x68,
+	OP_MACSEC	= 0x6c,
+	OP_PUTIDX	= 0x70,
+};
+
+enum status_css {
+	CSS_TCPUDPCSOK	= 1<<7,	/* TCP / UDP checksum is ok */
+	CSS_ISUDP	= 1<<6, /* packet is a UDP packet */
+	CSS_ISTCP	= 1<<5, /* packet is a TCP packet */
+	CSS_ISIPFRAG	= 1<<4, /* packet is a TCP/UDP frag, CS calc not done */
+	CSS_ISIPV6	= 1<<3, /* packet is a IPv6 packet */
+	CSS_IPV4CSUMOK	= 1<<2, /* IP v4: TCP header checksum is ok */
+	CSS_ISIPV4	= 1<<1, /* packet is a IPv4 packet */
+	CSS_LINK_BIT	= 1<<0, /* port number (legacy) */
 };
 
 /* Yukon 2 hardware interface */
@@ -1860,7 +1963,7 @@
 struct sky2_status_le {
 	__le32	status;	/* also checksum */
 	__le16	length;	/* also vlan tag */
-	u8	link;
+	u8	css;
 	u8	opcode;
 } __attribute((packed));
 
@@ -1895,6 +1998,7 @@
 	struct sky2_tx_le    *tx_le;
 	u16		     tx_cons;		/* next le to check */
 	u16		     tx_prod;		/* next le to use */
+	u16		     tx_next;		/* debug only */
 	u32		     tx_addr64;
 	u16		     tx_pending;
 	u16		     tx_last_mss;
@@ -1925,6 +2029,9 @@
  	enum flow_control    flow_mode;
  	enum flow_control    flow_status;
 
+#ifdef CONFIG_SKY2_DEBUG
+	struct dentry	     *debugfs;
+#endif
 	struct net_device_stats net_stats;
 
 };
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 111f23d..f842944 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -58,6 +58,8 @@
 #elif defined(CONFIG_BFIN)
 
 #define SMC_IRQ_FLAGS		IRQF_TRIGGER_HIGH
+#define RPC_LSA_DEFAULT		RPC_LED_100_10
+#define RPC_LSB_DEFAULT		RPC_LED_TX_RX
 
 # if defined (CONFIG_BFIN561_EZKIT)
 #define SMC_CAN_USE_8BIT	0
@@ -281,17 +283,14 @@
 
 #elif   defined(CONFIG_SUPERH)
 
-#if defined(CONFIG_SH_7780_SOLUTION_ENGINE) || defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+#ifdef CONFIG_SOLUTION_ENGINE
 #define SMC_CAN_USE_8BIT       0
 #define SMC_CAN_USE_16BIT      1
 #define SMC_CAN_USE_32BIT      0
 #define SMC_IO_SHIFT           0
 #define SMC_NOWAIT             1
 
-#define SMC_inb(a, r)          (inw((a) + ((r)&~1)) >> (8*(r%2)))&0xff
 #define SMC_inw(a, r)          inw((a) + (r))
-#define SMC_outb(v, a, r)      outw(((inw((a)+((r)&~1))*(0xff<<8*(r%2)))) | ((v)<<(8*(r&2)))), (a) + ((r)&~1))
-
 #define SMC_outw(v, a, r)      outw(v, (a) + (r))
 #define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c
new file mode 100644
index 0000000..2cf6794
--- /dev/null
+++ b/drivers/net/sni_82596.c
@@ -0,0 +1,185 @@
+/*
+ * sni_82596.c -- driver for intel 82596 ethernet controller, as
+ *  		  used in older SNI RM machines
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#define SNI_82596_DRIVER_VERSION "SNI RM 82596 driver - Revision: 0.01"
+
+static const char sni_82596_string[] = "snirm_82596";
+
+#define DMA_ALLOC                      dma_alloc_coherent
+#define DMA_FREE                       dma_free_coherent
+#define DMA_WBACK(priv, addr, len)     do { } while (0)
+#define DMA_INV(priv, addr, len)       do { } while (0)
+#define DMA_WBACK_INV(priv, addr, len) do { } while (0)
+
+#define SYSBUS      0x00004400
+
+/* big endian CPU, 82596 little endian */
+#define SWAP32(x)   cpu_to_le32((u32)(x))
+#define SWAP16(x)   cpu_to_le16((u16)(x))
+
+#define OPT_MPU_16BIT    0x01
+
+#include "lib82596.c"
+
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("i82596 driver");
+MODULE_LICENSE("GPL");
+module_param(i596_debug, int, 0);
+MODULE_PARM_DESC(i596_debug, "82596 debug mask");
+
+static inline void ca(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+
+	writel(0, lp->ca);
+}
+
+
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
+{
+	struct i596_private *lp = netdev_priv(dev);
+
+	u32 v = (u32) (c) | (u32) (x);
+
+	if (lp->options & OPT_MPU_16BIT) {
+		writew(v & 0xffff, lp->mpu_port);
+		wmb();  /* order writes to MPU port */
+		udelay(1);
+		writew(v >> 16, lp->mpu_port);
+	} else {
+		writel(v, lp->mpu_port);
+		wmb();  /* order writes to MPU port */
+		udelay(1);
+		writel(v, lp->mpu_port);
+	}
+}
+
+
+static int __devinit sni_82596_probe(struct platform_device *dev)
+{
+	struct	net_device *netdevice;
+	struct i596_private *lp;
+	struct  resource *res, *ca, *idprom, *options;
+	int	retval = -ENOMEM;
+	void __iomem *mpu_addr;
+	void __iomem *ca_addr;
+	u8 __iomem *eth_addr;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	ca = platform_get_resource(dev, IORESOURCE_MEM, 1);
+	options = platform_get_resource(dev, 0, 0);
+	idprom = platform_get_resource(dev, IORESOURCE_MEM, 2);
+	if (!res || !ca || !options || !idprom)
+		return -ENODEV;
+	mpu_addr = ioremap_nocache(res->start, 4);
+	if (!mpu_addr)
+		return -ENOMEM;
+	ca_addr = ioremap_nocache(ca->start, 4);
+	if (!ca_addr)
+		goto probe_failed_free_mpu;
+
+	printk(KERN_INFO "Found i82596 at 0x%x\n", res->start);
+
+	netdevice = alloc_etherdev(sizeof(struct i596_private));
+	if (!netdevice)
+		goto probe_failed_free_ca;
+
+	SET_NETDEV_DEV(netdevice, &dev->dev);
+	platform_set_drvdata (dev, netdevice);
+
+	netdevice->base_addr = res->start;
+	netdevice->irq = platform_get_irq(dev, 0);
+
+	eth_addr = ioremap_nocache(idprom->start, 0x10);
+	if (!eth_addr)
+		goto probe_failed;
+
+	/* someone seems to like messed up stuff */
+	netdevice->dev_addr[0] = readb(eth_addr + 0x0b);
+	netdevice->dev_addr[1] = readb(eth_addr + 0x0a);
+	netdevice->dev_addr[2] = readb(eth_addr + 0x09);
+	netdevice->dev_addr[3] = readb(eth_addr + 0x08);
+	netdevice->dev_addr[4] = readb(eth_addr + 0x07);
+	netdevice->dev_addr[5] = readb(eth_addr + 0x06);
+	iounmap(eth_addr);
+
+	if (!netdevice->irq) {
+		printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
+			__FILE__, netdevice->base_addr);
+		goto probe_failed;
+	}
+
+	lp = netdev_priv(netdevice);
+	lp->options = options->flags & IORESOURCE_BITS;
+	lp->ca = ca_addr;
+	lp->mpu_port = mpu_addr;
+
+	retval = i82596_probe(netdevice);
+	if (retval == 0)
+		return 0;
+
+probe_failed:
+	free_netdev(netdevice);
+probe_failed_free_ca:
+	iounmap(ca_addr);
+probe_failed_free_mpu:
+	iounmap(mpu_addr);
+	return retval;
+}
+
+static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct i596_private *lp = netdev_priv(dev);
+
+	unregister_netdev(dev);
+	DMA_FREE(dev->dev.parent, sizeof(struct i596_private),
+		 lp->dma, lp->dma_addr);
+	iounmap(lp->ca);
+	iounmap(lp->mpu_port);
+	free_netdev (dev);
+	return 0;
+}
+
+static struct platform_driver sni_82596_driver = {
+	.probe	= sni_82596_probe,
+	.remove	= __devexit_p(sni_82596_driver_remove),
+	.driver	= {
+		.name	= sni_82596_string,
+	},
+};
+
+static int __devinit sni_82596_init(void)
+{
+	printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
+	return platform_driver_register(&sni_82596_driver);
+}
+
+
+static void __exit sni_82596_exit(void)
+{
+	platform_driver_unregister(&sni_82596_driver);
+}
+
+module_init(sni_82596_init);
+module_exit(sni_82596_exit);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index c3964c3..590b12c 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -434,7 +434,8 @@
 				      bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
 	if (!descr->skb) {
 		if (netif_msg_rx_err(card) && net_ratelimit())
-			pr_err("Not enough memory to allocate rx buffer\n");
+			dev_err(&card->netdev->dev,
+			        "Not enough memory to allocate rx buffer\n");
 		card->spider_stats.alloc_rx_skb_error++;
 		return -ENOMEM;
 	}
@@ -455,18 +456,14 @@
 		dev_kfree_skb_any(descr->skb);
 		descr->skb = NULL;
 		if (netif_msg_rx_err(card) && net_ratelimit())
-			pr_err("Could not iommu-map rx buffer\n");
+			dev_err(&card->netdev->dev, "Could not iommu-map rx buffer\n");
 		card->spider_stats.rx_iommu_map_error++;
 		hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
 	} else {
 		hwdescr->buf_addr = buf;
-		hwdescr->next_descr_addr = 0;
 		wmb();
 		hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
 					 SPIDER_NET_DMAC_NOINTR_COMPLETE;
-
-		wmb();
-		descr->prev->hwdescr->next_descr_addr = descr->bus_addr;
 	}
 
 	return 0;
@@ -504,6 +501,20 @@
 }
 
 /**
+ * spider_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_disable_rxdmac terminates processing on the DMA controller
+ * by turing off the DMA controller, with the force-end flag set.
+ */
+static inline void
+spider_net_disable_rxdmac(struct spider_net_card *card)
+{
+	spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+			     SPIDER_NET_DMA_RX_FEND_VALUE);
+}
+
+/**
  * spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
  * @card: card structure
  *
@@ -541,12 +552,16 @@
 static int
 spider_net_alloc_rx_skbs(struct spider_net_card *card)
 {
-	int result;
-	struct spider_net_descr_chain *chain;
+	struct spider_net_descr_chain *chain = &card->rx_chain;
+	struct spider_net_descr *start = chain->tail;
+	struct spider_net_descr *descr = start;
 
-	result = -ENOMEM;
+	/* Link up the hardware chain pointers */
+	do {
+		descr->prev->hwdescr->next_descr_addr = descr->bus_addr;
+		descr = descr->next;
+	} while (descr != start);
 
-	chain = &card->rx_chain;
 	/* Put at least one buffer into the chain. if this fails,
 	 * we've got a problem. If not, spider_net_refill_rx_chain
 	 * will do the rest at the end of this function. */
@@ -563,7 +578,7 @@
 
 error:
 	spider_net_free_rx_chain_contents(card);
-	return result;
+	return -ENOMEM;
 }
 
 /**
@@ -655,20 +670,6 @@
 }
 
 /**
- * spider_net_disable_rxdmac - disables the receive DMA controller
- * @card: card structure
- *
- * spider_net_disable_rxdmac terminates processing on the DMA controller by
- * turing off DMA and issueing a force end
- */
-static void
-spider_net_disable_rxdmac(struct spider_net_card *card)
-{
-	spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
-			     SPIDER_NET_DMA_RX_FEND_VALUE);
-}
-
-/**
  * spider_net_prepare_tx_descr - fill tx descriptor with skb data
  * @card: card structure
  * @descr: descriptor structure to fill out
@@ -692,7 +693,7 @@
 	buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
 	if (pci_dma_mapping_error(buf)) {
 		if (netif_msg_tx_err(card) && net_ratelimit())
-			pr_err("could not iommu-map packet (%p, %i). "
+			dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). "
 				  "Dropping packet\n", skb->data, skb->len);
 		card->spider_stats.tx_iommu_map_error++;
 		return -ENOMEM;
@@ -715,10 +716,10 @@
 	hwdescr->data_status = 0;
 
 	hwdescr->dmac_cmd_status =
-			SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+			SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_TXFRMTL;
 	spin_unlock_irqrestore(&chain->lock, flags);
 
-	if (skb->protocol == htons(ETH_P_IP) && skb->ip_summed == CHECKSUM_PARTIAL)
+	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		switch (ip_hdr(skb)->protocol) {
 		case IPPROTO_TCP:
 			hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
@@ -832,9 +833,8 @@
 		case SPIDER_NET_DESCR_PROTECTION_ERROR:
 		case SPIDER_NET_DESCR_FORCE_END:
 			if (netif_msg_tx_err(card))
-				pr_err("%s: forcing end of tx descriptor "
-				       "with status x%02x\n",
-				       card->netdev->name, status);
+				dev_err(&card->netdev->dev, "forcing end of tx descriptor "
+				       "with status x%02x\n", status);
 			card->netdev_stats.tx_errors++;
 			break;
 
@@ -1014,42 +1014,162 @@
 		 */
 	}
 
-	/* pass skb up to stack */
-	netif_receive_skb(skb);
-
 	/* update netdevice statistics */
 	card->netdev_stats.rx_packets++;
 	card->netdev_stats.rx_bytes += skb->len;
+
+	/* pass skb up to stack */
+	netif_receive_skb(skb);
 }
 
-#ifdef DEBUG
 static void show_rx_chain(struct spider_net_card *card)
 {
 	struct spider_net_descr_chain *chain = &card->rx_chain;
 	struct spider_net_descr *start= chain->tail;
 	struct spider_net_descr *descr= start;
+	struct spider_net_hw_descr *hwd = start->hwdescr;
+	struct device *dev = &card->netdev->dev;
+	u32 curr_desc, next_desc;
 	int status;
 
+	int tot = 0;
 	int cnt = 0;
-	int cstat = spider_net_get_descr_status(descr);
-	printk(KERN_INFO "RX chain tail at descr=%ld\n",
-	     (start - card->descr) - card->tx_chain.num_desc);
+	int off = start - chain->ring;
+	int cstat = hwd->dmac_cmd_status;
+
+	dev_info(dev, "Total number of descrs=%d\n",
+		chain->num_desc);
+	dev_info(dev, "Chain tail located at descr=%d, status=0x%x\n",
+		off, cstat);
+
+	curr_desc = spider_net_read_reg(card, SPIDER_NET_GDACTDPA);
+	next_desc = spider_net_read_reg(card, SPIDER_NET_GDACNEXTDA);
+
 	status = cstat;
 	do
 	{
-		status = spider_net_get_descr_status(descr);
+		hwd = descr->hwdescr;
+		off = descr - chain->ring;
+		status = hwd->dmac_cmd_status;
+
+		if (descr == chain->head)
+			dev_info(dev, "Chain head is at %d, head status=0x%x\n",
+			         off, status);
+
+		if (curr_desc == descr->bus_addr)
+			dev_info(dev, "HW curr desc (GDACTDPA) is at %d, status=0x%x\n",
+			         off, status);
+
+		if (next_desc == descr->bus_addr)
+			dev_info(dev, "HW next desc (GDACNEXTDA) is at %d, status=0x%x\n",
+			         off, status);
+
+		if (hwd->next_descr_addr == 0)
+			dev_info(dev, "chain is cut at %d\n", off);
+
 		if (cstat != status) {
-			printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat);
+			int from = (chain->num_desc + off - cnt) % chain->num_desc;
+			int to = (chain->num_desc + off - 1) % chain->num_desc;
+			dev_info(dev, "Have %d (from %d to %d) descrs "
+			         "with stat=0x%08x\n", cnt, from, to, cstat);
 			cstat = status;
 			cnt = 0;
 		}
+
 		cnt ++;
+		tot ++;
 		descr = descr->next;
 	} while (descr != start);
-	printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat);
-}
+
+	dev_info(dev, "Last %d descrs with stat=0x%08x "
+	         "for a total of %d descrs\n", cnt, cstat, tot);
+
+#ifdef DEBUG
+	/* Now dump the whole ring */
+	descr = start;
+	do
+	{
+		struct spider_net_hw_descr *hwd = descr->hwdescr;
+		status = spider_net_get_descr_status(hwd);
+		cnt = descr - chain->ring;
+		dev_info(dev, "Descr %d stat=0x%08x skb=%p\n",
+		         cnt, status, descr->skb);
+		dev_info(dev, "bus addr=%08x buf addr=%08x sz=%d\n",
+		         descr->bus_addr, hwd->buf_addr, hwd->buf_size);
+		dev_info(dev, "next=%08x result sz=%d valid sz=%d\n",
+		         hwd->next_descr_addr, hwd->result_size,
+		         hwd->valid_size);
+		dev_info(dev, "dmac=%08x data stat=%08x data err=%08x\n",
+		         hwd->dmac_cmd_status, hwd->data_status,
+		         hwd->data_error);
+		dev_info(dev, "\n");
+
+		descr = descr->next;
+	} while (descr != start);
 #endif
 
+}
+
+/**
+ * spider_net_resync_head_ptr - Advance head ptr past empty descrs
+ *
+ * If the driver fails to keep up and empty the queue, then the
+ * hardware wil run out of room to put incoming packets. This
+ * will cause the hardware to skip descrs that are full (instead
+ * of halting/retrying). Thus, once the driver runs, it wil need
+ * to "catch up" to where the hardware chain pointer is at.
+ */
+static void spider_net_resync_head_ptr(struct spider_net_card *card)
+{
+	unsigned long flags;
+	struct spider_net_descr_chain *chain = &card->rx_chain;
+	struct spider_net_descr *descr;
+	int i, status;
+
+	/* Advance head pointer past any empty descrs */
+	descr = chain->head;
+	status = spider_net_get_descr_status(descr->hwdescr);
+
+	if (status == SPIDER_NET_DESCR_NOT_IN_USE)
+		return;
+
+	spin_lock_irqsave(&chain->lock, flags);
+
+	descr = chain->head;
+	status = spider_net_get_descr_status(descr->hwdescr);
+	for (i=0; i<chain->num_desc; i++) {
+		if (status != SPIDER_NET_DESCR_CARDOWNED) break;
+		descr = descr->next;
+		status = spider_net_get_descr_status(descr->hwdescr);
+	}
+	chain->head = descr;
+
+	spin_unlock_irqrestore(&chain->lock, flags);
+}
+
+static int spider_net_resync_tail_ptr(struct spider_net_card *card)
+{
+	struct spider_net_descr_chain *chain = &card->rx_chain;
+	struct spider_net_descr *descr;
+	int i, status;
+
+	/* Advance tail pointer past any empty and reaped descrs */
+	descr = chain->tail;
+	status = spider_net_get_descr_status(descr->hwdescr);
+
+	for (i=0; i<chain->num_desc; i++) {
+		if ((status != SPIDER_NET_DESCR_CARDOWNED) &&
+		    (status != SPIDER_NET_DESCR_NOT_IN_USE)) break;
+		descr = descr->next;
+		status = spider_net_get_descr_status(descr->hwdescr);
+	}
+	chain->tail = descr;
+
+	if ((i == chain->num_desc) || (i == 0))
+		return 1;
+	return 0;
+}
+
 /**
  * spider_net_decode_one_descr - processes an RX descriptor
  * @card: card structure
@@ -1067,6 +1187,7 @@
 	struct spider_net_descr_chain *chain = &card->rx_chain;
 	struct spider_net_descr *descr = chain->tail;
 	struct spider_net_hw_descr *hwdescr = descr->hwdescr;
+	u32 hw_buf_addr;
 	int status;
 
 	status = spider_net_get_descr_status(hwdescr);
@@ -1080,15 +1201,17 @@
 	chain->tail = descr->next;
 
 	/* unmap descriptor */
-	pci_unmap_single(card->pdev, hwdescr->buf_addr,
+	hw_buf_addr = hwdescr->buf_addr;
+	hwdescr->buf_addr = 0xffffffff;
+	pci_unmap_single(card->pdev, hw_buf_addr,
 			SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
 
 	if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
 	     (status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
 	     (status == SPIDER_NET_DESCR_FORCE_END) ) {
 		if (netif_msg_rx_err(card))
-			pr_err("%s: dropping RX descriptor with state %d\n",
-			       card->netdev->name, status);
+			dev_err(&card->netdev->dev,
+			       "dropping RX descriptor with state %d\n", status);
 		card->netdev_stats.rx_dropped++;
 		goto bad_desc;
 	}
@@ -1096,8 +1219,8 @@
 	if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
 	     (status != SPIDER_NET_DESCR_FRAME_END) ) {
 		if (netif_msg_rx_err(card))
-			pr_err("%s: RX descriptor with unknown state %d\n",
-			       card->netdev->name, status);
+			dev_err(&card->netdev->dev,
+			       "RX descriptor with unknown state %d\n", status);
 		card->spider_stats.rx_desc_unk_state++;
 		goto bad_desc;
 	}
@@ -1105,18 +1228,17 @@
 	/* The cases we'll throw away the packet immediately */
 	if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
 		if (netif_msg_rx_err(card))
-			pr_err("%s: error in received descriptor found, "
+			dev_err(&card->netdev->dev,
+			       "error in received descriptor found, "
 			       "data_status=x%08x, data_error=x%08x\n",
-			       card->netdev->name,
 			       hwdescr->data_status, hwdescr->data_error);
 		goto bad_desc;
 	}
 
-	if (hwdescr->dmac_cmd_status & 0xfefe) {
-		pr_err("%s: bad status, cmd_status=x%08x\n",
-			       card->netdev->name,
+	if (hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_BAD_STATUS) {
+		dev_err(&card->netdev->dev, "bad status, cmd_status=x%08x\n",
 			       hwdescr->dmac_cmd_status);
-		pr_err("buf_addr=x%08x\n", hwdescr->buf_addr);
+		pr_err("buf_addr=x%08x\n", hw_buf_addr);
 		pr_err("buf_size=x%08x\n", hwdescr->buf_size);
 		pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr);
 		pr_err("result_size=x%08x\n", hwdescr->result_size);
@@ -1131,10 +1253,13 @@
 
 	/* Ok, we've got a packet in descr */
 	spider_net_pass_skb_up(descr, card);
+	descr->skb = NULL;
 	hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
 	return 1;
 
 bad_desc:
+	if (netif_msg_rx_err(card))
+		show_rx_chain(card);
 	dev_kfree_skb_irq(descr->skb);
 	descr->skb = NULL;
 	hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
@@ -1160,7 +1285,6 @@
 	int packets_to_do, packets_done = 0;
 	int no_more_packets = 0;
 
-	spider_net_cleanup_tx_ring(card);
 	packets_to_do = min(*budget, netdev->quota);
 
 	while (packets_to_do) {
@@ -1174,16 +1298,25 @@
 		}
 	}
 
+	if ((packets_done == 0) && (card->num_rx_ints != 0)) {
+		no_more_packets = spider_net_resync_tail_ptr(card);
+		spider_net_resync_head_ptr(card);
+	}
+	card->num_rx_ints = 0;
+
 	netdev->quota -= packets_done;
 	*budget -= packets_done;
 	spider_net_refill_rx_chain(card);
 	spider_net_enable_rxdmac(card);
 
+	spider_net_cleanup_tx_ring(card);
+
 	/* if all packets are in the stack, enable interrupts and return 0 */
 	/* if not, return 1 */
 	if (no_more_packets) {
 		netif_rx_complete(netdev);
 		spider_net_rx_irq_on(card);
+		card->ignore_rx_ramfull = 0;
 		return 0;
 	}
 
@@ -1191,43 +1324,6 @@
 }
 
 /**
- * spider_net_vlan_rx_reg - initializes VLAN structures in the driver and card
- * @netdev: interface device structure
- * @grp: vlan_group structure that is registered (NULL on destroying interface)
- */
-static void
-spider_net_vlan_rx_reg(struct net_device *netdev, struct vlan_group *grp)
-{
-	/* further enhancement... yet to do */
-	return;
-}
-
-/**
- * spider_net_vlan_rx_add - adds VLAN id to the card filter
- * @netdev: interface device structure
- * @vid: VLAN id to add
- */
-static void
-spider_net_vlan_rx_add(struct net_device *netdev, uint16_t vid)
-{
-	/* further enhancement... yet to do */
-	/* add vid to card's VLAN filter table */
-	return;
-}
-
-/**
- * spider_net_vlan_rx_kill - removes VLAN id to the card filter
- * @netdev: interface device structure
- * @vid: VLAN id to remove
- */
-static void
-spider_net_vlan_rx_kill(struct net_device *netdev, uint16_t vid)
-{
-	/* further enhancement... yet to do */
-	/* remove vid from card's VLAN filter table */
-}
-
-/**
  * spider_net_get_stats - get interface statistics
  * @netdev: interface device structure
  *
@@ -1345,11 +1441,17 @@
 spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
 {
 	u32 error_reg1, error_reg2;
+	u32 mask_reg1, mask_reg2;
 	u32 i;
 	int show_error = 1;
 
 	error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
 	error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+	mask_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1MSK);
+	mask_reg2 = spider_net_read_reg(card,SPIDER_NET_GHIINT2MSK);
+
+	error_reg1 &= mask_reg1;
+	error_reg2 &= mask_reg2;
 
 	/* check GHIINT0STS ************************************/
 	if (status_reg)
@@ -1384,7 +1486,7 @@
 	case SPIDER_NET_GPWFFINT:
 		/* PHY command queue full */
 		if (netif_msg_intr(card))
-			pr_err("PHY write queue full\n");
+			dev_err(&card->netdev->dev, "PHY write queue full\n");
 		show_error = 0;
 		break;
 
@@ -1454,11 +1556,15 @@
 	case SPIDER_NET_GRFBFLLINT: /* fallthrough */
 	case SPIDER_NET_GRFAFLLINT: /* fallthrough */
 	case SPIDER_NET_GRMFLLINT:
-		if (netif_msg_intr(card) && net_ratelimit())
-			pr_err("Spider RX RAM full, incoming packets "
-			       "might be discarded!\n");
-		spider_net_rx_irq_off(card);
-		netif_rx_schedule(card->netdev);
+		/* Could happen when rx chain is full */
+		if (card->ignore_rx_ramfull == 0) {
+			card->ignore_rx_ramfull = 1;
+			spider_net_resync_head_ptr(card);
+			spider_net_refill_rx_chain(card);
+			spider_net_enable_rxdmac(card);
+			card->num_rx_ints ++;
+			netif_rx_schedule(card->netdev);
+		}
 		show_error = 0;
 		break;
 
@@ -1473,12 +1579,11 @@
 	case SPIDER_NET_GDCDCEINT: /* fallthrough */
 	case SPIDER_NET_GDBDCEINT: /* fallthrough */
 	case SPIDER_NET_GDADCEINT:
-		if (netif_msg_intr(card) && net_ratelimit())
-			pr_err("got descriptor chain end interrupt, "
-			       "restarting DMAC %c.\n",
-			       'D'-(i-SPIDER_NET_GDDDCEINT)/3);
+		spider_net_resync_head_ptr(card);
 		spider_net_refill_rx_chain(card);
 		spider_net_enable_rxdmac(card);
+		card->num_rx_ints ++;
+		netif_rx_schedule(card->netdev);
 		show_error = 0;
 		break;
 
@@ -1487,9 +1592,12 @@
 	case SPIDER_NET_GDCINVDINT: /* fallthrough */
 	case SPIDER_NET_GDBINVDINT: /* fallthrough */
 	case SPIDER_NET_GDAINVDINT:
-		/* could happen when rx chain is full */
+		/* Could happen when rx chain is full */
+		spider_net_resync_head_ptr(card);
 		spider_net_refill_rx_chain(card);
 		spider_net_enable_rxdmac(card);
+		card->num_rx_ints ++;
+		netif_rx_schedule(card->netdev);
 		show_error = 0;
 		break;
 
@@ -1545,9 +1653,8 @@
 	}
 
 	if ((show_error) && (netif_msg_intr(card)) && net_ratelimit())
-		pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, "
+		dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, "
 		       "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
-		       card->netdev->name,
 		       status_reg, error_reg1, error_reg2);
 
 	/* clear interrupt sources */
@@ -1572,9 +1679,11 @@
 {
 	struct net_device *netdev = ptr;
 	struct spider_net_card *card = netdev_priv(netdev);
-	u32 status_reg;
+	u32 status_reg, mask_reg;
 
 	status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
+	mask_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+	status_reg &= mask_reg;
 
 	if (!status_reg)
 		return IRQ_NONE;
@@ -1582,6 +1691,7 @@
 	if (status_reg & SPIDER_NET_RXINT ) {
 		spider_net_rx_irq_off(card);
 		netif_rx_schedule(netdev);
+		card->num_rx_ints ++;
 	}
 	if (status_reg & SPIDER_NET_TXINT)
 		netif_rx_schedule(netdev);
@@ -1615,6 +1725,38 @@
 #endif /* CONFIG_NET_POLL_CONTROLLER */
 
 /**
+ * spider_net_enable_interrupts - enable interrupts
+ * @card: card structure
+ *
+ * spider_net_enable_interrupt enables several interrupts
+ */
+static void 
+spider_net_enable_interrupts(struct spider_net_card *card)
+{
+	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
+			     SPIDER_NET_INT0_MASK_VALUE);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
+			     SPIDER_NET_INT1_MASK_VALUE);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
+			     SPIDER_NET_INT2_MASK_VALUE);
+}
+
+/**
+ * spider_net_disable_interrupts - disable interrupts
+ * @card: card structure
+ *
+ * spider_net_disable_interrupts disables all the interrupts
+ */
+static void 
+spider_net_disable_interrupts(struct spider_net_card *card)
+{
+	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+	spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+}
+
+/**
  * spider_net_init_card - initializes the card
  * @card: card structure
  *
@@ -1634,6 +1776,7 @@
 	spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
 		spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4);
 
+	spider_net_disable_interrupts(card);
 }
 
 /**
@@ -1721,14 +1864,6 @@
 	spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
 			     SPIDER_NET_OPMODE_VALUE);
 
-	/* set interrupt mask registers */
-	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
-			     SPIDER_NET_INT0_MASK_VALUE);
-	spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
-			     SPIDER_NET_INT1_MASK_VALUE);
-	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
-			     SPIDER_NET_INT2_MASK_VALUE);
-
 	spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
 			     SPIDER_NET_GDTBSTA);
 }
@@ -1811,7 +1946,8 @@
 			     SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
 		if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
 		     netif_msg_probe(card) ) {
-			pr_err("Incorrect size of spidernet firmware in " \
+			dev_err(&card->netdev->dev,
+			       "Incorrect size of spidernet firmware in " \
 			       "filesystem. Looking in host firmware...\n");
 			goto try_host_fw;
 		}
@@ -1835,8 +1971,8 @@
 
 	if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
 	     netif_msg_probe(card) ) {
-		pr_err("Incorrect size of spidernet firmware in " \
-		       "host firmware\n");
+		dev_err(&card->netdev->dev,
+		       "Incorrect size of spidernet firmware in host firmware\n");
 		goto done;
 	}
 
@@ -1846,7 +1982,8 @@
 	return err;
 out_err:
 	if (netif_msg_probe(card))
-		pr_err("Couldn't find spidernet firmware in filesystem " \
+		dev_err(&card->netdev->dev,
+		       "Couldn't find spidernet firmware in filesystem " \
 		       "or host firmware\n");
 	return err;
 }
@@ -1903,6 +2040,8 @@
 	netif_carrier_on(netdev);
 	netif_poll_enable(netdev);
 
+	spider_net_enable_interrupts(card);
+
 	return 0;
 
 register_int_failed:
@@ -2075,11 +2214,7 @@
 	del_timer_sync(&card->tx_timer);
 	del_timer_sync(&card->aneg_timer);
 
-	/* disable/mask all interrupts */
-	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
-	spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
-	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
-	spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+	spider_net_disable_interrupts(card);
 
 	free_irq(netdev->irq, netdev);
 
@@ -2177,9 +2312,6 @@
 	netdev->poll = &spider_net_poll;
 	netdev->weight = SPIDER_NET_NAPI_WEIGHT;
 	/* HW VLAN */
-	netdev->vlan_rx_register = &spider_net_vlan_rx_reg;
-	netdev->vlan_rx_add_vid = &spider_net_vlan_rx_add;
-	netdev->vlan_rx_kill_vid = &spider_net_vlan_rx_kill;
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	/* poll controller */
 	netdev->poll_controller = &spider_net_poll_controller;
@@ -2225,11 +2357,13 @@
 
 	spider_net_setup_netdev_ops(netdev);
 
-	netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
+	netdev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX;
 	/* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
 	 *		NETIF_F_HW_VLAN_FILTER */
 
 	netdev->irq = card->pdev->irq;
+	card->num_rx_ints = 0;
+	card->ignore_rx_ramfull = 0;
 
 	dn = pci_device_to_OF_node(card->pdev);
 	if (!dn)
@@ -2242,13 +2376,14 @@
 
 	result = spider_net_set_mac(netdev, &addr);
 	if ((result) && (netif_msg_probe(card)))
-		pr_err("Failed to set MAC address: %i\n", result);
+		dev_err(&card->netdev->dev,
+		        "Failed to set MAC address: %i\n", result);
 
 	result = register_netdev(netdev);
 	if (result) {
 		if (netif_msg_probe(card))
-			pr_err("Couldn't register net_device: %i\n",
-				  result);
+			dev_err(&card->netdev->dev,
+			        "Couldn't register net_device: %i\n", result);
 		return result;
 	}
 
@@ -2326,17 +2461,19 @@
 	unsigned long mmio_start, mmio_len;
 
 	if (pci_enable_device(pdev)) {
-		pr_err("Couldn't enable PCI device\n");
+		dev_err(&pdev->dev, "Couldn't enable PCI device\n");
 		return NULL;
 	}
 
 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		pr_err("Couldn't find proper PCI device base address.\n");
+		dev_err(&pdev->dev,
+		        "Couldn't find proper PCI device base address.\n");
 		goto out_disable_dev;
 	}
 
 	if (pci_request_regions(pdev, spider_net_driver_name)) {
-		pr_err("Couldn't obtain PCI resources, aborting.\n");
+		dev_err(&pdev->dev,
+		        "Couldn't obtain PCI resources, aborting.\n");
 		goto out_disable_dev;
 	}
 
@@ -2344,8 +2481,8 @@
 
 	card = spider_net_alloc_card();
 	if (!card) {
-		pr_err("Couldn't allocate net_device structure, "
-			  "aborting.\n");
+		dev_err(&pdev->dev,
+		        "Couldn't allocate net_device structure, aborting.\n");
 		goto out_release_regions;
 	}
 	card->pdev = pdev;
@@ -2359,7 +2496,8 @@
 	card->regs = ioremap(mmio_start, mmio_len);
 
 	if (!card->regs) {
-		pr_err("Couldn't obtain PCI resources, aborting.\n");
+		dev_err(&pdev->dev,
+		        "Couldn't obtain PCI resources, aborting.\n");
 		goto out_release_regions;
 	}
 
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 4a1e0d2..dbbdb8c 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -25,7 +25,7 @@
 #ifndef _SPIDER_NET_H
 #define _SPIDER_NET_H
 
-#define VERSION "2.0 A"
+#define VERSION "2.0 B"
 
 #include "sungem_phy.h"
 
@@ -222,6 +222,7 @@
 #define SPIDER_NET_GDTBSTA             0x00000300
 #define SPIDER_NET_GDTDCEIDIS          0x00000002
 #define SPIDER_NET_DMA_TX_VALUE        SPIDER_NET_TX_DMA_EN | \
+                                       SPIDER_NET_GDTDCEIDIS | \
                                        SPIDER_NET_GDTBSTA
 
 #define SPIDER_NET_DMA_TX_FEND_VALUE	0x00030003
@@ -332,8 +333,7 @@
 	SPIDER_NET_GRISPDNGINT
 };
 
-#define SPIDER_NET_TXINT	( (1 << SPIDER_NET_GDTFDCINT) | \
-                             (1 << SPIDER_NET_GDTDCEINT) )
+#define SPIDER_NET_TXINT	(1 << SPIDER_NET_GDTFDCINT)
 
 /* We rely on flagged descriptor interrupts */
 #define SPIDER_NET_RXINT	( (1 << SPIDER_NET_GDAFDCINT) )
@@ -349,11 +349,23 @@
 #define SPIDER_NET_GPRDAT_MASK			0x0000ffff
 
 #define SPIDER_NET_DMAC_NOINTR_COMPLETE		0x00800000
-#define SPIDER_NET_DMAC_NOCS			0x00040000
+#define SPIDER_NET_DMAC_TXFRMTL		0x00040000
 #define SPIDER_NET_DMAC_TCP			0x00020000
 #define SPIDER_NET_DMAC_UDP			0x00030000
 #define SPIDER_NET_TXDCEST			0x08000000
 
+#define SPIDER_NET_DESCR_RXFDIS        0x00000001
+#define SPIDER_NET_DESCR_RXDCEIS       0x00000002
+#define SPIDER_NET_DESCR_RXDEN0IS      0x00000004
+#define SPIDER_NET_DESCR_RXINVDIS      0x00000008
+#define SPIDER_NET_DESCR_RXRERRIS      0x00000010
+#define SPIDER_NET_DESCR_RXFDCIMS      0x00000100
+#define SPIDER_NET_DESCR_RXDCEIMS      0x00000200
+#define SPIDER_NET_DESCR_RXDEN0IMS     0x00000400
+#define SPIDER_NET_DESCR_RXINVDIMS     0x00000800
+#define SPIDER_NET_DESCR_RXRERRMIS     0x00001000
+#define SPIDER_NET_DESCR_UNUSED        0x077fe0e0
+
 #define SPIDER_NET_DESCR_IND_PROC_MASK		0xF0000000
 #define SPIDER_NET_DESCR_COMPLETE		0x00000000 /* used in rx and tx */
 #define SPIDER_NET_DESCR_RESPONSE_ERROR		0x10000000 /* used in rx and tx */
@@ -364,6 +376,13 @@
 #define SPIDER_NET_DESCR_NOT_IN_USE		0xF0000000
 #define SPIDER_NET_DESCR_TXDESFLG		0x00800000
 
+#define SPIDER_NET_DESCR_BAD_STATUS   (SPIDER_NET_DESCR_RXDEN0IS | \
+                                       SPIDER_NET_DESCR_RXRERRIS | \
+                                       SPIDER_NET_DESCR_RXDEN0IMS | \
+                                       SPIDER_NET_DESCR_RXINVDIMS | \
+                                       SPIDER_NET_DESCR_RXRERRMIS | \
+                                       SPIDER_NET_DESCR_UNUSED)
+
 /* Descriptor, as defined by the hardware */
 struct spider_net_hw_descr {
 	u32 buf_addr;
@@ -461,6 +480,8 @@
 	struct work_struct tx_timeout_task;
 	atomic_t tx_timeout_task_counter;
 	wait_queue_head_t waitq;
+	int num_rx_ints;
+	int ignore_rx_ramfull;
 
 	/* for ethtool */
 	int msg_enable;
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index 6bcf03f..d940474 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -134,22 +134,6 @@
 	return 0;
 }
 
-static uint32_t
-spider_net_ethtool_get_tx_csum(struct net_device *netdev)
-{
-        return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int
-spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data)
-{
-        if (data)
-                netdev->features |= NETIF_F_HW_CSUM;
-        else
-                netdev->features &= ~NETIF_F_HW_CSUM;
-
-        return 0;
-}
 
 static void
 spider_net_ethtool_get_ringparam(struct net_device *netdev,
@@ -200,11 +184,12 @@
 	.get_wol		= spider_net_ethtool_get_wol,
 	.get_msglevel		= spider_net_ethtool_get_msglevel,
 	.set_msglevel		= spider_net_ethtool_set_msglevel,
+	.get_link		= ethtool_op_get_link,
 	.nway_reset		= spider_net_ethtool_nway_reset,
 	.get_rx_csum		= spider_net_ethtool_get_rx_csum,
 	.set_rx_csum		= spider_net_ethtool_set_rx_csum,
-	.get_tx_csum		= spider_net_ethtool_get_tx_csum,
-	.set_tx_csum		= spider_net_ethtool_set_tx_csum,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.set_tx_csum		= ethtool_op_set_tx_csum,
 	.get_ringparam          = spider_net_ethtool_get_ringparam,
 	.get_strings		= spider_net_get_strings,
 	.get_stats_count	= spider_net_get_stats_count,
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 9d6e454..8b64786 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -152,7 +152,7 @@
  * This SUCKS.
  * We need a much better method to determine if dma_addr_t is 64-bit.
  */
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
 /* 64-bit dma_addr_t */
 #define ADDR_64BITS	/* This chip uses 64 bit addresses. */
 #define netdrv_addr_t u64
@@ -740,7 +740,7 @@
 	pci_set_master(pdev);
 
 	/* enable MWI -- it vastly improves Rx performance on sparc64 */
-	pci_set_mwi(pdev);
+	pci_try_set_mwi(pdev);
 
 #ifdef ZEROCOPY
 	/* Starfire can do TCP/UDP checksumming */
@@ -1456,7 +1456,7 @@
 			pci_dma_sync_single_for_cpu(np->pci_dev,
 						    np->rx_info[entry].mapping,
 						    pkt_len, PCI_DMA_FROMDEVICE);
-			eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0);
+			skb_copy_to_linear_data(skb, np->rx_info[entry].skb->data, pkt_len);
 			pci_dma_sync_single_for_device(np->pci_dev,
 						       np->rx_info[entry].mapping,
 						       pkt_len, PCI_DMA_FROMDEVICE);
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
index a123ea8..b77ab6e 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/sun3_82586.c
@@ -777,7 +777,7 @@
 					{
 						skb_reserve(skb,2);
 						skb_put(skb,totlen);
-						eth_copy_and_sum(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen,0);
+						skb_copy_to_linear_data(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen);
 						skb->protocol=eth_type_trans(skb,dev);
 						netif_rx(skb);
 						p->stats.rx_packets++;
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 791e081..f1548c0 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -853,10 +853,9 @@
 
 				skb_reserve( skb, 2 );	/* 16 byte align */
 				skb_put( skb, pkt_len );	/* Make room */
-//			        skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), pkt_len);
-				eth_copy_and_sum(skb,
+				skb_copy_to_linear_data(skb,
 						 PKTBUF_ADDR(head),
-						 pkt_len, 0);
+						 pkt_len);
 
 				skb->protocol = eth_type_trans( skb, dev );
 				netif_rx( skb );
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 2ad8d58..b3e0158 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -860,7 +860,7 @@
 			sbus_dma_sync_single_for_cpu(bp->bigmac_sdev,
 						     this->rx_addr, len,
 						     SBUS_DMA_FROMDEVICE);
-			eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0);
+			skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len);
 			sbus_dma_sync_single_for_device(bp->bigmac_sdev,
 							this->rx_addr, len,
 							SBUS_DMA_FROMDEVICE);
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index e1f912d..af0c983 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -397,7 +397,6 @@
 	unsigned char phys[MII_CNT];		/* MII device addresses, only first one used. */
 	struct pci_dev *pci_dev;
 	void __iomem *base;
-	unsigned char pci_rev_id;
 };
 
 /* The station address location in the EEPROM. */
@@ -544,8 +543,6 @@
 	dev->change_mtu = &change_mtu;
 	pci_set_drvdata(pdev, dev);
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id);
-
 	i = register_netdev(dev);
 	if (i)
 		goto err_out_unmap_rx;
@@ -828,7 +825,7 @@
 	iowrite8(100, ioaddr + RxDMAPollPeriod);
 	iowrite8(127, ioaddr + TxDMAPollPeriod);
 	/* Fix DFE-580TX packet drop issue */
-	if (np->pci_rev_id >= 0x14)
+	if (np->pci_dev->revision >= 0x14)
 		iowrite8(0x01, ioaddr + DebugCtrl1);
 	netif_start_queue(dev);
 
@@ -1194,7 +1191,7 @@
 			hw_frame_id = ioread8(ioaddr + TxFrameId);
 		}
 
-		if (np->pci_rev_id >= 0x14) {
+		if (np->pci_dev->revision >= 0x14) {
 			spin_lock(&np->lock);
 			for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
 				int entry = np->dirty_tx % TX_RING_SIZE;
@@ -1313,7 +1310,7 @@
 							    np->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
 
-				eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
 				pci_dma_sync_single_for_device(np->pci_dev,
 							       desc->frag[0].addr,
 							       np->rx_buf_sz,
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 51c3fe2..8b35f13 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2625,7 +2625,7 @@
 #endif /* CONFIG_SBUS */
 
 #ifdef CONFIG_PCI
-static struct quattro * __init quattro_pci_find(struct pci_dev *pdev)
+static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
 {
 	struct pci_dev *bdev = pdev->bus->self;
 	struct quattro *qp;
@@ -3095,12 +3095,8 @@
 
 #ifdef CONFIG_SPARC
 	hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff);
-	if (hp->hm_revision == 0xff) {
-		unsigned char prev;
-
-		pci_read_config_byte(pdev, PCI_REVISION_ID, &prev);
-		hp->hm_revision = 0xc0 | (prev & 0x0f);
-	}
+	if (hp->hm_revision == 0xff)
+		hp->hm_revision = 0xc0 | (pdev->revision & 0x0f);
 #else
 	/* works with this on non-sparc hosts */
 	hp->hm_revision = 0x20;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 4272253..053b7cb 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -549,9 +549,9 @@
 
 			skb_reserve(skb, 2);		/* 16 byte align */
 			skb_put(skb, len);		/* make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 					 (unsigned char *)&(ib->rx_buf [entry][0]),
-					 len, 0);
+					 len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
 			dev->last_rx = jiffies;
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index fa70e0b..1b65ae8 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -439,8 +439,8 @@
 			} else {
 				skb_reserve(skb, 2);
 				skb_put(skb, len);
-				eth_copy_and_sum(skb, (unsigned char *) this_qbuf,
-						 len, 0);
+				skb_copy_to_linear_data(skb, (unsigned char *) this_qbuf,
+						 len);
 				skb->protocol = eth_type_trans(skb, qep->dev);
 				netif_rx(skb);
 				qep->dev->last_rx = jiffies;
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
new file mode 100644
index 0000000..8a667c1
--- /dev/null
+++ b/drivers/net/sunvnet.c
@@ -0,0 +1,1164 @@
+/* sunvnet.c: Sun LDOM Virtual Network Driver.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+
+#include <asm/vio.h>
+#include <asm/ldc.h>
+
+#include "sunvnet.h"
+
+#define DRV_MODULE_NAME		"sunvnet"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"June 25, 2007"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM virtual network driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+/* Ordered from largest major to lowest */
+static struct vio_version vnet_versions[] = {
+	{ .major = 1, .minor = 0 },
+};
+
+static inline u32 vnet_tx_dring_avail(struct vio_dring_state *dr)
+{
+	return vio_dring_avail(dr, VNET_TX_RING_SIZE);
+}
+
+static int vnet_handle_unknown(struct vnet_port *port, void *arg)
+{
+	struct vio_msg_tag *pkt = arg;
+
+	printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+	       pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+	printk(KERN_ERR PFX "Resetting connection.\n");
+
+	ldc_disconnect(port->vio.lp);
+
+	return -ECONNRESET;
+}
+
+static int vnet_send_attr(struct vio_driver_state *vio)
+{
+	struct vnet_port *port = to_vnet_port(vio);
+	struct net_device *dev = port->vp->dev;
+	struct vio_net_attr_info pkt;
+	int i;
+
+	memset(&pkt, 0, sizeof(pkt));
+	pkt.tag.type = VIO_TYPE_CTRL;
+	pkt.tag.stype = VIO_SUBTYPE_INFO;
+	pkt.tag.stype_env = VIO_ATTR_INFO;
+	pkt.tag.sid = vio_send_sid(vio);
+	pkt.xfer_mode = VIO_DRING_MODE;
+	pkt.addr_type = VNET_ADDR_ETHERMAC;
+	pkt.ack_freq = 0;
+	for (i = 0; i < 6; i++)
+		pkt.addr |= (u64)dev->dev_addr[i] << ((5 - i) * 8);
+	pkt.mtu = ETH_FRAME_LEN;
+
+	viodbg(HS, "SEND NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] "
+	       "ackfreq[%u] mtu[%llu]\n",
+	       pkt.xfer_mode, pkt.addr_type,
+	       (unsigned long long) pkt.addr,
+	       pkt.ack_freq,
+	       (unsigned long long) pkt.mtu);
+
+	return vio_ldc_send(vio, &pkt, sizeof(pkt));
+}
+
+static int handle_attr_info(struct vio_driver_state *vio,
+			    struct vio_net_attr_info *pkt)
+{
+	viodbg(HS, "GOT NET ATTR INFO xmode[0x%x] atype[0x%x] addr[%llx] "
+	       "ackfreq[%u] mtu[%llu]\n",
+	       pkt->xfer_mode, pkt->addr_type,
+	       (unsigned long long) pkt->addr,
+	       pkt->ack_freq,
+	       (unsigned long long) pkt->mtu);
+
+	pkt->tag.sid = vio_send_sid(vio);
+
+	if (pkt->xfer_mode != VIO_DRING_MODE ||
+	    pkt->addr_type != VNET_ADDR_ETHERMAC ||
+	    pkt->mtu != ETH_FRAME_LEN) {
+		viodbg(HS, "SEND NET ATTR NACK\n");
+
+		pkt->tag.stype = VIO_SUBTYPE_NACK;
+
+		(void) vio_ldc_send(vio, pkt, sizeof(*pkt));
+
+		return -ECONNRESET;
+	} else {
+		viodbg(HS, "SEND NET ATTR ACK\n");
+
+		pkt->tag.stype = VIO_SUBTYPE_ACK;
+
+		return vio_ldc_send(vio, pkt, sizeof(*pkt));
+	}
+
+}
+
+static int handle_attr_ack(struct vio_driver_state *vio,
+			   struct vio_net_attr_info *pkt)
+{
+	viodbg(HS, "GOT NET ATTR ACK\n");
+
+	return 0;
+}
+
+static int handle_attr_nack(struct vio_driver_state *vio,
+			    struct vio_net_attr_info *pkt)
+{
+	viodbg(HS, "GOT NET ATTR NACK\n");
+
+	return -ECONNRESET;
+}
+
+static int vnet_handle_attr(struct vio_driver_state *vio, void *arg)
+{
+	struct vio_net_attr_info *pkt = arg;
+
+	switch (pkt->tag.stype) {
+	case VIO_SUBTYPE_INFO:
+		return handle_attr_info(vio, pkt);
+
+	case VIO_SUBTYPE_ACK:
+		return handle_attr_ack(vio, pkt);
+
+	case VIO_SUBTYPE_NACK:
+		return handle_attr_nack(vio, pkt);
+
+	default:
+		return -ECONNRESET;
+	}
+}
+
+static void vnet_handshake_complete(struct vio_driver_state *vio)
+{
+	struct vio_dring_state *dr;
+
+	dr = &vio->drings[VIO_DRIVER_RX_RING];
+	dr->snd_nxt = dr->rcv_nxt = 1;
+
+	dr = &vio->drings[VIO_DRIVER_TX_RING];
+	dr->snd_nxt = dr->rcv_nxt = 1;
+}
+
+/* The hypervisor interface that implements copying to/from imported
+ * memory from another domain requires that copies are done to 8-byte
+ * aligned buffers, and that the lengths of such copies are also 8-byte
+ * multiples.
+ *
+ * So we align skb->data to an 8-byte multiple and pad-out the data
+ * area so we can round the copy length up to the next multiple of
+ * 8 for the copy.
+ *
+ * The transmitter puts the actual start of the packet 6 bytes into
+ * the buffer it sends over, so that the IP headers after the ethernet
+ * header are aligned properly.  These 6 bytes are not in the descriptor
+ * length, they are simply implied.  This offset is represented using
+ * the VNET_PACKET_SKIP macro.
+ */
+static struct sk_buff *alloc_and_align_skb(struct net_device *dev,
+					   unsigned int len)
+{
+	struct sk_buff *skb = netdev_alloc_skb(dev, len+VNET_PACKET_SKIP+8+8);
+	unsigned long addr, off;
+
+	if (unlikely(!skb))
+		return NULL;
+
+	addr = (unsigned long) skb->data;
+	off = ((addr + 7UL) & ~7UL) - addr;
+	if (off)
+		skb_reserve(skb, off);
+
+	return skb;
+}
+
+static int vnet_rx_one(struct vnet_port *port, unsigned int len,
+		       struct ldc_trans_cookie *cookies, int ncookies)
+{
+	struct net_device *dev = port->vp->dev;
+	unsigned int copy_len;
+	struct sk_buff *skb;
+	int err;
+
+	err = -EMSGSIZE;
+	if (unlikely(len < ETH_ZLEN || len > ETH_FRAME_LEN)) {
+		dev->stats.rx_length_errors++;
+		goto out_dropped;
+	}
+
+	skb = alloc_and_align_skb(dev, len);
+	err = -ENOMEM;
+	if (unlikely(!skb)) {
+		dev->stats.rx_missed_errors++;
+		goto out_dropped;
+	}
+
+	copy_len = (len + VNET_PACKET_SKIP + 7U) & ~7U;
+	skb_put(skb, copy_len);
+	err = ldc_copy(port->vio.lp, LDC_COPY_IN,
+		       skb->data, copy_len, 0,
+		       cookies, ncookies);
+	if (unlikely(err < 0)) {
+		dev->stats.rx_frame_errors++;
+		goto out_free_skb;
+	}
+
+	skb_pull(skb, VNET_PACKET_SKIP);
+	skb_trim(skb, len);
+	skb->protocol = eth_type_trans(skb, dev);
+
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += len;
+
+	netif_rx(skb);
+
+	return 0;
+
+out_free_skb:
+	kfree_skb(skb);
+
+out_dropped:
+	dev->stats.rx_dropped++;
+	return err;
+}
+
+static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
+			 u32 start, u32 end, u8 vio_dring_state)
+{
+	struct vio_dring_data hdr = {
+		.tag = {
+			.type		= VIO_TYPE_DATA,
+			.stype		= VIO_SUBTYPE_ACK,
+			.stype_env	= VIO_DRING_DATA,
+			.sid		= vio_send_sid(&port->vio),
+		},
+		.dring_ident		= dr->ident,
+		.start_idx		= start,
+		.end_idx		= end,
+		.state			= vio_dring_state,
+	};
+	int err, delay;
+
+	hdr.seq = dr->snd_nxt;
+	delay = 1;
+	do {
+		err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+		if (err > 0) {
+			dr->snd_nxt++;
+			break;
+		}
+		udelay(delay);
+		if ((delay <<= 1) > 128)
+			delay = 128;
+	} while (err == -EAGAIN);
+
+	return err;
+}
+
+static u32 next_idx(u32 idx, struct vio_dring_state *dr)
+{
+	if (++idx == dr->num_entries)
+		idx = 0;
+	return idx;
+}
+
+static u32 prev_idx(u32 idx, struct vio_dring_state *dr)
+{
+	if (idx == 0)
+		idx = dr->num_entries - 1;
+	else
+		idx--;
+
+	return idx;
+}
+
+static struct vio_net_desc *get_rx_desc(struct vnet_port *port,
+					struct vio_dring_state *dr,
+					u32 index)
+{
+	struct vio_net_desc *desc = port->vio.desc_buf;
+	int err;
+
+	err = ldc_get_dring_entry(port->vio.lp, desc, dr->entry_size,
+				  (index * dr->entry_size),
+				  dr->cookies, dr->ncookies);
+	if (err < 0)
+		return ERR_PTR(err);
+
+	return desc;
+}
+
+static int put_rx_desc(struct vnet_port *port,
+		       struct vio_dring_state *dr,
+		       struct vio_net_desc *desc,
+		       u32 index)
+{
+	int err;
+
+	err = ldc_put_dring_entry(port->vio.lp, desc, dr->entry_size,
+				  (index * dr->entry_size),
+				  dr->cookies, dr->ncookies);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int vnet_walk_rx_one(struct vnet_port *port,
+			    struct vio_dring_state *dr,
+			    u32 index, int *needs_ack)
+{
+	struct vio_net_desc *desc = get_rx_desc(port, dr, index);
+	struct vio_driver_state *vio = &port->vio;
+	int err;
+
+	if (IS_ERR(desc))
+		return PTR_ERR(desc);
+
+	viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%lx:%lx]\n",
+	       desc->hdr.state, desc->hdr.ack,
+	       desc->size, desc->ncookies,
+	       desc->cookies[0].cookie_addr,
+	       desc->cookies[0].cookie_size);
+
+	if (desc->hdr.state != VIO_DESC_READY)
+		return 1;
+	err = vnet_rx_one(port, desc->size, desc->cookies, desc->ncookies);
+	if (err == -ECONNRESET)
+		return err;
+	desc->hdr.state = VIO_DESC_DONE;
+	err = put_rx_desc(port, dr, desc, index);
+	if (err < 0)
+		return err;
+	*needs_ack = desc->hdr.ack;
+	return 0;
+}
+
+static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr,
+			u32 start, u32 end)
+{
+	struct vio_driver_state *vio = &port->vio;
+	int ack_start = -1, ack_end = -1;
+
+	end = (end == (u32) -1) ? prev_idx(start, dr) : next_idx(end, dr);
+
+	viodbg(DATA, "vnet_walk_rx start[%08x] end[%08x]\n", start, end);
+
+	while (start != end) {
+		int ack = 0, err = vnet_walk_rx_one(port, dr, start, &ack);
+		if (err == -ECONNRESET)
+			return err;
+		if (err != 0)
+			break;
+		if (ack_start == -1)
+			ack_start = start;
+		ack_end = start;
+		start = next_idx(start, dr);
+		if (ack && start != end) {
+			err = vnet_send_ack(port, dr, ack_start, ack_end,
+					    VIO_DRING_ACTIVE);
+			if (err == -ECONNRESET)
+				return err;
+			ack_start = -1;
+		}
+	}
+	if (unlikely(ack_start == -1))
+		ack_start = ack_end = prev_idx(start, dr);
+	return vnet_send_ack(port, dr, ack_start, ack_end, VIO_DRING_STOPPED);
+}
+
+static int vnet_rx(struct vnet_port *port, void *msgbuf)
+{
+	struct vio_dring_data *pkt = msgbuf;
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_RX_RING];
+	struct vio_driver_state *vio = &port->vio;
+
+	viodbg(DATA, "vnet_rx stype_env[%04x] seq[%016lx] rcv_nxt[%016lx]\n",
+	       pkt->tag.stype_env, pkt->seq, dr->rcv_nxt);
+
+	if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
+		return 0;
+	if (unlikely(pkt->seq != dr->rcv_nxt)) {
+		printk(KERN_ERR PFX "RX out of sequence seq[0x%lx] "
+		       "rcv_nxt[0x%lx]\n", pkt->seq, dr->rcv_nxt);
+		return 0;
+	}
+
+	dr->rcv_nxt++;
+
+	/* XXX Validate pkt->start_idx and pkt->end_idx XXX */
+
+	return vnet_walk_rx(port, dr, pkt->start_idx, pkt->end_idx);
+}
+
+static int idx_is_pending(struct vio_dring_state *dr, u32 end)
+{
+	u32 idx = dr->cons;
+	int found = 0;
+
+	while (idx != dr->prod) {
+		if (idx == end) {
+			found = 1;
+			break;
+		}
+		idx = next_idx(idx, dr);
+	}
+	return found;
+}
+
+static int vnet_ack(struct vnet_port *port, void *msgbuf)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct vio_dring_data *pkt = msgbuf;
+	struct net_device *dev;
+	struct vnet *vp;
+	u32 end;
+
+	if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
+		return 0;
+
+	end = pkt->end_idx;
+	if (unlikely(!idx_is_pending(dr, end)))
+		return 0;
+
+	dr->cons = next_idx(end, dr);
+
+	vp = port->vp;
+	dev = vp->dev;
+	if (unlikely(netif_queue_stopped(dev) &&
+		     vnet_tx_dring_avail(dr) >= VNET_TX_WAKEUP_THRESH(dr)))
+		return 1;
+
+	return 0;
+}
+
+static int vnet_nack(struct vnet_port *port, void *msgbuf)
+{
+	/* XXX just reset or similar XXX */
+	return 0;
+}
+
+static void maybe_tx_wakeup(struct vnet *vp)
+{
+	struct net_device *dev = vp->dev;
+
+	netif_tx_lock(dev);
+	if (likely(netif_queue_stopped(dev))) {
+		struct vnet_port *port;
+		int wake = 1;
+
+		list_for_each_entry(port, &vp->port_list, list) {
+			struct vio_dring_state *dr;
+
+			dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+			if (vnet_tx_dring_avail(dr) <
+			    VNET_TX_WAKEUP_THRESH(dr)) {
+				wake = 0;
+				break;
+			}
+		}
+		if (wake)
+			netif_wake_queue(dev);
+	}
+	netif_tx_unlock(dev);
+}
+
+static void vnet_event(void *arg, int event)
+{
+	struct vnet_port *port = arg;
+	struct vio_driver_state *vio = &port->vio;
+	unsigned long flags;
+	int tx_wakeup, err;
+
+	spin_lock_irqsave(&vio->lock, flags);
+
+	if (unlikely(event == LDC_EVENT_RESET ||
+		     event == LDC_EVENT_UP)) {
+		vio_link_state_change(vio, event);
+		spin_unlock_irqrestore(&vio->lock, flags);
+
+		return;
+	}
+
+	if (unlikely(event != LDC_EVENT_DATA_READY)) {
+		printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+		spin_unlock_irqrestore(&vio->lock, flags);
+		return;
+	}
+
+	tx_wakeup = err = 0;
+	while (1) {
+		union {
+			struct vio_msg_tag tag;
+			u64 raw[8];
+		} msgbuf;
+
+		err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
+		if (unlikely(err < 0)) {
+			if (err == -ECONNRESET)
+				vio_conn_reset(vio);
+			break;
+		}
+		if (err == 0)
+			break;
+		viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
+		       msgbuf.tag.type,
+		       msgbuf.tag.stype,
+		       msgbuf.tag.stype_env,
+		       msgbuf.tag.sid);
+		err = vio_validate_sid(vio, &msgbuf.tag);
+		if (err < 0)
+			break;
+
+		if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
+			if (msgbuf.tag.stype == VIO_SUBTYPE_INFO) {
+				err = vnet_rx(port, &msgbuf);
+			} else if (msgbuf.tag.stype == VIO_SUBTYPE_ACK) {
+				err = vnet_ack(port, &msgbuf);
+				if (err > 0)
+					tx_wakeup |= err;
+			} else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK) {
+				err = vnet_nack(port, &msgbuf);
+			}
+		} else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
+			err = vio_control_pkt_engine(vio, &msgbuf);
+			if (err)
+				break;
+		} else {
+			err = vnet_handle_unknown(port, &msgbuf);
+		}
+		if (err == -ECONNRESET)
+			break;
+	}
+	spin_unlock(&vio->lock);
+	if (unlikely(tx_wakeup && err != -ECONNRESET))
+		maybe_tx_wakeup(port->vp);
+	local_irq_restore(flags);
+}
+
+static int __vnet_tx_trigger(struct vnet_port *port)
+{
+	struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	struct vio_dring_data hdr = {
+		.tag = {
+			.type		= VIO_TYPE_DATA,
+			.stype		= VIO_SUBTYPE_INFO,
+			.stype_env	= VIO_DRING_DATA,
+			.sid		= vio_send_sid(&port->vio),
+		},
+		.dring_ident		= dr->ident,
+		.start_idx		= dr->prod,
+		.end_idx		= (u32) -1,
+	};
+	int err, delay;
+
+	hdr.seq = dr->snd_nxt;
+	delay = 1;
+	do {
+		err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+		if (err > 0) {
+			dr->snd_nxt++;
+			break;
+		}
+		udelay(delay);
+		if ((delay <<= 1) > 128)
+			delay = 128;
+	} while (err == -EAGAIN);
+
+	return err;
+}
+
+struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb)
+{
+	unsigned int hash = vnet_hashfn(skb->data);
+	struct hlist_head *hp = &vp->port_hash[hash];
+	struct hlist_node *n;
+	struct vnet_port *port;
+
+	hlist_for_each_entry(port, n, hp, hash) {
+		if (!compare_ether_addr(port->raddr, skb->data))
+			return port;
+	}
+	port = NULL;
+	if (!list_empty(&vp->port_list))
+		port = list_entry(vp->port_list.next, struct vnet_port, list);
+
+	return port;
+}
+
+struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb)
+{
+	struct vnet_port *ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vp->lock, flags);
+	ret = __tx_port_find(vp, skb);
+	spin_unlock_irqrestore(&vp->lock, flags);
+
+	return ret;
+}
+
+static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct vnet *vp = netdev_priv(dev);
+	struct vnet_port *port = tx_port_find(vp, skb);
+	struct vio_dring_state *dr;
+	struct vio_net_desc *d;
+	unsigned long flags;
+	unsigned int len;
+	void *tx_buf;
+	int i, err;
+
+	if (unlikely(!port))
+		goto out_dropped;
+
+	spin_lock_irqsave(&port->vio.lock, flags);
+
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+		if (!netif_queue_stopped(dev)) {
+			netif_stop_queue(dev);
+
+			/* This is a hard error, log it. */
+			printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
+			       "queue awake!\n", dev->name);
+			dev->stats.tx_errors++;
+		}
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+
+	d = vio_dring_cur(dr);
+
+	tx_buf = port->tx_bufs[dr->prod].buf;
+	skb_copy_from_linear_data(skb, tx_buf + VNET_PACKET_SKIP, skb->len);
+
+	len = skb->len;
+	if (len < ETH_ZLEN) {
+		len = ETH_ZLEN;
+		memset(tx_buf+VNET_PACKET_SKIP+skb->len, 0, len - skb->len);
+	}
+
+	d->hdr.ack = VIO_ACK_ENABLE;
+	d->size = len;
+	d->ncookies = port->tx_bufs[dr->prod].ncookies;
+	for (i = 0; i < d->ncookies; i++)
+		d->cookies[i] = port->tx_bufs[dr->prod].cookies[i];
+
+	/* This has to be a non-SMP write barrier because we are writing
+	 * to memory which is shared with the peer LDOM.
+	 */
+	wmb();
+
+	d->hdr.state = VIO_DESC_READY;
+
+	err = __vnet_tx_trigger(port);
+	if (unlikely(err < 0)) {
+		printk(KERN_INFO PFX "%s: TX trigger error %d\n",
+		       dev->name, err);
+		d->hdr.state = VIO_DESC_FREE;
+		dev->stats.tx_carrier_errors++;
+		goto out_dropped_unlock;
+	}
+
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
+	if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+		netif_stop_queue(dev);
+		if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
+			netif_wake_queue(dev);
+	}
+
+	spin_unlock_irqrestore(&port->vio.lock, flags);
+
+	dev_kfree_skb(skb);
+
+	dev->trans_start = jiffies;
+	return NETDEV_TX_OK;
+
+out_dropped_unlock:
+	spin_unlock_irqrestore(&port->vio.lock, flags);
+
+out_dropped:
+	dev_kfree_skb(skb);
+	dev->stats.tx_dropped++;
+	return NETDEV_TX_OK;
+}
+
+static void vnet_tx_timeout(struct net_device *dev)
+{
+	/* XXX Implement me XXX */
+}
+
+static int vnet_open(struct net_device *dev)
+{
+	netif_carrier_on(dev);
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int vnet_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	return 0;
+}
+
+static void vnet_set_rx_mode(struct net_device *dev)
+{
+	/* XXX Implement multicast support XXX */
+}
+
+static int vnet_change_mtu(struct net_device *dev, int new_mtu)
+{
+	if (new_mtu != ETH_DATA_LEN)
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+static int vnet_set_mac_addr(struct net_device *dev, void *p)
+{
+	return -EINVAL;
+}
+
+static void vnet_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_MODULE_NAME);
+	strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static u32 vnet_get_msglevel(struct net_device *dev)
+{
+	struct vnet *vp = netdev_priv(dev);
+	return vp->msg_enable;
+}
+
+static void vnet_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct vnet *vp = netdev_priv(dev);
+	vp->msg_enable = value;
+}
+
+static const struct ethtool_ops vnet_ethtool_ops = {
+	.get_drvinfo		= vnet_get_drvinfo,
+	.get_msglevel		= vnet_get_msglevel,
+	.set_msglevel		= vnet_set_msglevel,
+	.get_link		= ethtool_op_get_link,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
+};
+
+static void vnet_port_free_tx_bufs(struct vnet_port *port)
+{
+	struct vio_dring_state *dr;
+	int i;
+
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+	if (dr->base) {
+		ldc_free_exp_dring(port->vio.lp, dr->base,
+				   (dr->entry_size * dr->num_entries),
+				   dr->cookies, dr->ncookies);
+		dr->base = NULL;
+		dr->entry_size = 0;
+		dr->num_entries = 0;
+		dr->pending = 0;
+		dr->ncookies = 0;
+	}
+
+	for (i = 0; i < VNET_TX_RING_SIZE; i++) {
+		void *buf = port->tx_bufs[i].buf;
+
+		if (!buf)
+			continue;
+
+		ldc_unmap(port->vio.lp,
+			  port->tx_bufs[i].cookies,
+			  port->tx_bufs[i].ncookies);
+
+		kfree(buf);
+		port->tx_bufs[i].buf = NULL;
+	}
+}
+
+static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
+{
+	struct vio_dring_state *dr;
+	unsigned long len;
+	int i, err, ncookies;
+	void *dring;
+
+	for (i = 0; i < VNET_TX_RING_SIZE; i++) {
+		void *buf = kzalloc(ETH_FRAME_LEN + 8, GFP_KERNEL);
+		int map_len = (ETH_FRAME_LEN + 7) & ~7;
+
+		err = -ENOMEM;
+		if (!buf) {
+			printk(KERN_ERR "TX buffer allocation failure\n");
+			goto err_out;
+		}
+		err = -EFAULT;
+		if ((unsigned long)buf & (8UL - 1)) {
+			printk(KERN_ERR "TX buffer misaligned\n");
+			kfree(buf);
+			goto err_out;
+		}
+
+		err = ldc_map_single(port->vio.lp, buf, map_len,
+				     port->tx_bufs[i].cookies, 2,
+				     (LDC_MAP_SHADOW |
+				      LDC_MAP_DIRECT |
+				      LDC_MAP_RW));
+		if (err < 0) {
+			kfree(buf);
+			goto err_out;
+		}
+		port->tx_bufs[i].buf = buf;
+		port->tx_bufs[i].ncookies = err;
+	}
+
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+	len = (VNET_TX_RING_SIZE *
+	       (sizeof(struct vio_net_desc) +
+		(sizeof(struct ldc_trans_cookie) * 2)));
+
+	ncookies = VIO_MAX_RING_COOKIES;
+	dring = ldc_alloc_exp_dring(port->vio.lp, len,
+				    dr->cookies, &ncookies,
+				    (LDC_MAP_SHADOW |
+				     LDC_MAP_DIRECT |
+				     LDC_MAP_RW));
+	if (IS_ERR(dring)) {
+		err = PTR_ERR(dring);
+		goto err_out;
+	}
+
+	dr->base = dring;
+	dr->entry_size = (sizeof(struct vio_net_desc) +
+			  (sizeof(struct ldc_trans_cookie) * 2));
+	dr->num_entries = VNET_TX_RING_SIZE;
+	dr->prod = dr->cons = 0;
+	dr->pending = VNET_TX_RING_SIZE;
+	dr->ncookies = ncookies;
+
+	return 0;
+
+err_out:
+	vnet_port_free_tx_bufs(port);
+
+	return err;
+}
+
+static struct ldc_channel_config vnet_ldc_cfg = {
+	.event		= vnet_event,
+	.mtu		= 64,
+	.mode		= LDC_MODE_UNRELIABLE,
+};
+
+static struct vio_driver_ops vnet_vio_ops = {
+	.send_attr		= vnet_send_attr,
+	.handle_attr		= vnet_handle_attr,
+	.handshake_complete	= vnet_handshake_complete,
+};
+
+const char *remote_macaddr_prop = "remote-mac-address";
+
+static int __devinit vnet_port_probe(struct vio_dev *vdev,
+				     const struct vio_device_id *id)
+{
+	struct mdesc_handle *hp;
+	struct vnet_port *port;
+	unsigned long flags;
+	struct vnet *vp;
+	const u64 *rmac;
+	int len, i, err, switch_port;
+
+	vp = dev_get_drvdata(vdev->dev.parent);
+	if (!vp) {
+		printk(KERN_ERR PFX "Cannot find port parent vnet.\n");
+		return -ENODEV;
+	}
+
+	hp = mdesc_grab();
+
+	rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
+	err = -ENODEV;
+	if (!rmac) {
+		printk(KERN_ERR PFX "Port lacks %s property.\n",
+		       remote_macaddr_prop);
+		goto err_out_put_mdesc;
+	}
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!port) {
+		printk(KERN_ERR PFX "Cannot allocate vnet_port.\n");
+		goto err_out_put_mdesc;
+	}
+
+	for (i = 0; i < ETH_ALEN; i++)
+		port->raddr[i] = (*rmac >> (5 - i) * 8) & 0xff;
+
+	port->vp = vp;
+
+	err = vio_driver_init(&port->vio, vdev, VDEV_NETWORK,
+			      vnet_versions, ARRAY_SIZE(vnet_versions),
+			      &vnet_vio_ops, vp->dev->name);
+	if (err)
+		goto err_out_free_port;
+
+	err = vio_ldc_alloc(&port->vio, &vnet_ldc_cfg, port);
+	if (err)
+		goto err_out_free_port;
+
+	err = vnet_port_alloc_tx_bufs(port);
+	if (err)
+		goto err_out_free_ldc;
+
+	INIT_HLIST_NODE(&port->hash);
+	INIT_LIST_HEAD(&port->list);
+
+	switch_port = 0;
+	if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL)
+		switch_port = 1;
+
+	spin_lock_irqsave(&vp->lock, flags);
+	if (switch_port)
+		list_add(&port->list, &vp->port_list);
+	else
+		list_add_tail(&port->list, &vp->port_list);
+	hlist_add_head(&port->hash, &vp->port_hash[vnet_hashfn(port->raddr)]);
+	spin_unlock_irqrestore(&vp->lock, flags);
+
+	dev_set_drvdata(&vdev->dev, port);
+
+	printk(KERN_INFO "%s: PORT ( remote-mac ", vp->dev->name);
+	for (i = 0; i < 6; i++)
+		printk("%2.2x%c", port->raddr[i], i == 5 ? ' ' : ':');
+	if (switch_port)
+		printk("switch-port ");
+	printk(")\n");
+
+	vio_port_up(&port->vio);
+
+	mdesc_release(hp);
+
+	return 0;
+
+err_out_free_ldc:
+	vio_ldc_free(&port->vio);
+
+err_out_free_port:
+	kfree(port);
+
+err_out_put_mdesc:
+	mdesc_release(hp);
+	return err;
+}
+
+static int vnet_port_remove(struct vio_dev *vdev)
+{
+	struct vnet_port *port = dev_get_drvdata(&vdev->dev);
+
+	if (port) {
+		struct vnet *vp = port->vp;
+		unsigned long flags;
+
+		del_timer_sync(&port->vio.timer);
+
+		spin_lock_irqsave(&vp->lock, flags);
+		list_del(&port->list);
+		hlist_del(&port->hash);
+		spin_unlock_irqrestore(&vp->lock, flags);
+
+		vnet_port_free_tx_bufs(port);
+		vio_ldc_free(&port->vio);
+
+		dev_set_drvdata(&vdev->dev, NULL);
+
+		kfree(port);
+	}
+	return 0;
+}
+
+static struct vio_device_id vnet_port_match[] = {
+	{
+		.type = "vnet-port",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(vio, vnet_match);
+
+static struct vio_driver vnet_port_driver = {
+	.id_table	= vnet_port_match,
+	.probe		= vnet_port_probe,
+	.remove		= vnet_port_remove,
+	.driver		= {
+		.name	= "vnet_port",
+		.owner	= THIS_MODULE,
+	}
+};
+
+const char *local_mac_prop = "local-mac-address";
+
+static int __devinit vnet_probe(struct vio_dev *vdev,
+				const struct vio_device_id *id)
+{
+	static int vnet_version_printed;
+	struct mdesc_handle *hp;
+	struct net_device *dev;
+	struct vnet *vp;
+	const u64 *mac;
+	int err, i, len;
+
+	if (vnet_version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	hp = mdesc_grab();
+
+	mac = mdesc_get_property(hp, vdev->mp, local_mac_prop, &len);
+	if (!mac) {
+		printk(KERN_ERR PFX "vnet lacks %s property.\n",
+		       local_mac_prop);
+		err = -ENODEV;
+		goto err_out;
+	}
+
+	dev = alloc_etherdev(sizeof(*vp));
+	if (!dev) {
+		printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	for (i = 0; i < ETH_ALEN; i++)
+		dev->dev_addr[i] = (*mac >> (5 - i) * 8) & 0xff;
+
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+	SET_NETDEV_DEV(dev, &vdev->dev);
+
+	vp = netdev_priv(dev);
+
+	spin_lock_init(&vp->lock);
+	vp->dev = dev;
+	vp->vdev = vdev;
+
+	INIT_LIST_HEAD(&vp->port_list);
+	for (i = 0; i < VNET_PORT_HASH_SIZE; i++)
+		INIT_HLIST_HEAD(&vp->port_hash[i]);
+
+	dev->open = vnet_open;
+	dev->stop = vnet_close;
+	dev->set_multicast_list = vnet_set_rx_mode;
+	dev->set_mac_address = vnet_set_mac_addr;
+	dev->tx_timeout = vnet_tx_timeout;
+	dev->ethtool_ops = &vnet_ethtool_ops;
+	dev->watchdog_timeo = VNET_TX_TIMEOUT;
+	dev->change_mtu = vnet_change_mtu;
+	dev->hard_start_xmit = vnet_start_xmit;
+
+	err = register_netdev(dev);
+	if (err) {
+		printk(KERN_ERR PFX "Cannot register net device, "
+		       "aborting.\n");
+		goto err_out_free_dev;
+	}
+
+	printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name);
+
+	for (i = 0; i < 6; i++)
+		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
+
+	dev_set_drvdata(&vdev->dev, vp);
+
+	mdesc_release(hp);
+
+	return 0;
+
+err_out_free_dev:
+	free_netdev(dev);
+
+err_out:
+	mdesc_release(hp);
+	return err;
+}
+
+static int vnet_remove(struct vio_dev *vdev)
+{
+
+	struct vnet *vp = dev_get_drvdata(&vdev->dev);
+
+	if (vp) {
+		/* XXX unregister port, or at least check XXX */
+		unregister_netdevice(vp->dev);
+		dev_set_drvdata(&vdev->dev, NULL);
+	}
+	return 0;
+}
+
+static struct vio_device_id vnet_match[] = {
+	{
+		.type = "network",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(vio, vnet_match);
+
+static struct vio_driver vnet_driver = {
+	.id_table	= vnet_match,
+	.probe		= vnet_probe,
+	.remove		= vnet_remove,
+	.driver		= {
+		.name	= "vnet",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init vnet_init(void)
+{
+	int err = vio_register_driver(&vnet_driver);
+
+	if (!err) {
+		err = vio_register_driver(&vnet_port_driver);
+		if (err)
+			vio_unregister_driver(&vnet_driver);
+	}
+
+	return err;
+}
+
+static void __exit vnet_exit(void)
+{
+	vio_unregister_driver(&vnet_port_driver);
+	vio_unregister_driver(&vnet_driver);
+}
+
+module_init(vnet_init);
+module_exit(vnet_exit);
diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h
new file mode 100644
index 0000000..1c88730
--- /dev/null
+++ b/drivers/net/sunvnet.h
@@ -0,0 +1,70 @@
+#ifndef _SUNVNET_H
+#define _SUNVNET_H
+
+#define DESC_NCOOKIES(entry_size)	\
+	((entry_size) - sizeof(struct vio_net_desc))
+
+/* length of time before we decide the hardware is borked,
+ * and dev->tx_timeout() should be called to fix the problem
+ */
+#define VNET_TX_TIMEOUT			(5 * HZ)
+
+#define VNET_TX_RING_SIZE		512
+#define VNET_TX_WAKEUP_THRESH(dr)	((dr)->pending / 4)
+
+/* VNET packets are sent in buffers with the first 6 bytes skipped
+ * so that after the ethernet header the IPv4/IPv6 headers are aligned
+ * properly.
+ */
+#define VNET_PACKET_SKIP		6
+
+struct vnet_tx_entry {
+	void			*buf;
+	unsigned int		ncookies;
+	struct ldc_trans_cookie	cookies[2];
+};
+
+struct vnet;
+struct vnet_port {
+	struct vio_driver_state	vio;
+
+	struct hlist_node	hash;
+	u8			raddr[ETH_ALEN];
+
+	struct vnet		*vp;
+
+	struct vnet_tx_entry	tx_bufs[VNET_TX_RING_SIZE];
+
+	struct list_head	list;
+};
+
+static inline struct vnet_port *to_vnet_port(struct vio_driver_state *vio)
+{
+	return container_of(vio, struct vnet_port, vio);
+}
+
+#define VNET_PORT_HASH_SIZE	16
+#define VNET_PORT_HASH_MASK	(VNET_PORT_HASH_SIZE - 1)
+
+static inline unsigned int vnet_hashfn(u8 *mac)
+{
+	unsigned int val = mac[4] ^ mac[5];
+
+	return val & (VNET_PORT_HASH_MASK);
+}
+
+struct vnet {
+	/* Protects port_list and port_hash.  */
+	spinlock_t		lock;
+
+	struct net_device	*dev;
+
+	u32			msg_enable;
+	struct vio_dev		*vdev;
+
+	struct list_head	port_list;
+
+	struct hlist_head	port_hash[VNET_PORT_HASH_SIZE];
+};
+
+#endif /* _SUNVNET_H */
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 463d600..75655ad 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -23,9 +23,9 @@
  */
 
 #ifdef TC35815_NAPI
-#define DRV_VERSION	"1.35-NAPI"
+#define DRV_VERSION	"1.36-NAPI"
 #else
-#define DRV_VERSION	"1.35"
+#define DRV_VERSION	"1.36"
 #endif
 static const char *version = "tc35815.c:v" DRV_VERSION "\n";
 #define MODNAME			"tc35815"
@@ -49,6 +49,7 @@
 #include <linux/pci.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -597,13 +598,46 @@
 static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
 			  int val);
 
-static void __devinit tc35815_init_dev_addr (struct net_device *dev)
+#ifdef CONFIG_CPU_TX49XX
+/*
+ * Find a platform_device providing a MAC address.  The platform code
+ * should provide a "tc35815-mac" device with a MAC address in its
+ * platform_data.
+ */
+static int __devinit tc35815_mac_match(struct device *dev, void *data)
+{
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct pci_dev *pci_dev = data;
+	unsigned int id = (pci_dev->bus->number << 8) | pci_dev->devfn;
+	return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
+}
+
+static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+{
+	struct tc35815_local *lp = dev->priv;
+	struct device *pd = bus_find_device(&platform_bus_type, NULL,
+					    lp->pci_dev, tc35815_mac_match);
+	if (pd) {
+		if (pd->platform_data)
+			memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN);
+		put_device(pd);
+		return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV;
+	}
+	return -ENODEV;
+}
+#else
+static int __devinit tc35815_read_plat_dev_addr(struct device *dev)
+{
+	return -ENODEV;
+}
+#endif
+
+static int __devinit tc35815_init_dev_addr (struct net_device *dev)
 {
 	struct tc35815_regs __iomem *tr =
 		(struct tc35815_regs __iomem *)dev->base_addr;
 	int i;
 
-	/* dev_addr will be overwritten on NETDEV_REGISTER event */
 	while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)
 		;
 	for (i = 0; i < 6; i += 2) {
@@ -615,6 +649,9 @@
 		dev->dev_addr[i] = data & 0xff;
 		dev->dev_addr[i+1] = data >> 8;
 	}
+	if (!is_valid_ether_addr(dev->dev_addr))
+		return tc35815_read_plat_dev_addr(dev);
+	return 0;
 }
 
 static int __devinit tc35815_init_one (struct pci_dev *pdev,
@@ -724,7 +761,10 @@
 	tc35815_chip_reset(dev);
 
 	/* Retrieve the ethernet address. */
-	tc35815_init_dev_addr(dev);
+	if (tc35815_init_dev_addr(dev)) {
+		dev_warn(&pdev->dev, "not valid ether addr\n");
+		random_ether_addr(dev->dev_addr);
+	}
 
 	rc = register_netdev (dev);
 	if (rc)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 923b9c7..5ee1476 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.76"
-#define DRV_MODULE_RELDATE	"May 5, 2007"
+#define DRV_MODULE_VERSION	"3.78"
+#define DRV_MODULE_RELDATE	"July 11, 2007"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -721,6 +721,44 @@
 	return ret;
 }
 
+static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+{
+	u32 phy;
+
+	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+	    (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
+		return;
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		u32 ephy;
+
+		if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) {
+			tg3_writephy(tp, MII_TG3_EPHY_TEST,
+				     ephy | MII_TG3_EPHY_SHADOW_EN);
+			if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) {
+				if (enable)
+					phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX;
+				else
+					phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX;
+				tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy);
+			}
+			tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy);
+		}
+	} else {
+		phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC |
+		      MII_TG3_AUXCTL_SHDWSEL_MISC;
+		if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) &&
+		    !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) {
+			if (enable)
+				phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+			else
+				phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+			phy |= MII_TG3_AUXCTL_MISC_WREN;
+			tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
+		}
+	}
+}
+
 static void tg3_phy_set_wirespeed(struct tg3 *tp)
 {
 	u32 val;
@@ -1045,23 +1083,11 @@
 	}
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-		u32 phy_reg;
-
 		/* adjust output voltage */
 		tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12);
-
-		if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) {
-			u32 phy_reg2;
-
-			tg3_writephy(tp, MII_TG3_EPHY_TEST,
-				     phy_reg | MII_TG3_EPHY_SHADOW_EN);
-			/* Enable auto-MDIX */
-			if (!tg3_readphy(tp, 0x10, &phy_reg2))
-				tg3_writephy(tp, 0x10, phy_reg2 | 0x4000);
-			tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg);
-		}
 	}
 
+	tg3_phy_toggle_automdix(tp, 1);
 	tg3_phy_set_wirespeed(tp);
 	return 0;
 }
@@ -1162,6 +1188,19 @@
 	}
 }
 
+static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
+{
+	if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
+		return 1;
+	else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) {
+		if (speed != SPEED_10)
+			return 1;
+	} else if (speed == SPEED_10)
+		return 1;
+
+	return 0;
+}
+
 static int tg3_setup_phy(struct tg3 *, int);
 
 #define RESET_KIND_SHUTDOWN	0
@@ -1320,9 +1359,17 @@
 			else
 				mac_mode = MAC_MODE_PORT_MODE_MII;
 
-			if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 ||
-			    !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB))
-				mac_mode |= MAC_MODE_LINK_POLARITY;
+			mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY;
+			if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+			    ASIC_REV_5700) {
+				u32 speed = (tp->tg3_flags &
+					     TG3_FLAG_WOL_SPEED_100MB) ?
+					     SPEED_100 : SPEED_10;
+				if (tg3_5700_link_polarity(tp, speed))
+					mac_mode |= MAC_MODE_LINK_POLARITY;
+				else
+					mac_mode &= ~MAC_MODE_LINK_POLARITY;
+			}
 		} else {
 			mac_mode = MAC_MODE_PORT_MODE_TBI;
 		}
@@ -1990,15 +2037,12 @@
 	if (tp->link_config.active_duplex == DUPLEX_HALF)
 		tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
 
-	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
-		if ((tp->led_ctrl == LED_CTRL_MODE_PHY_2) ||
-		    (current_link_up == 1 &&
-		     tp->link_config.active_speed == SPEED_10))
+		if (current_link_up == 1 &&
+		    tg3_5700_link_polarity(tp, tp->link_config.active_speed))
 			tp->mac_mode |= MAC_MODE_LINK_POLARITY;
-	} else {
-		if (current_link_up == 1)
-			tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+		else
+			tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
 	}
 
 	/* ??? Without this setting Netgear GA302T PHY does not
@@ -2639,6 +2683,9 @@
 
 		tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
 		udelay(40);
+
+		tw32_f(MAC_MODE, tp->mac_mode);
+		udelay(40);
 	}
 
 out:
@@ -2698,10 +2745,6 @@
 	else
 		current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
 
-	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
-	tw32_f(MAC_MODE, tp->mac_mode);
-	udelay(40);
-
 	tp->hw_status->status =
 		(SD_STATUS_UPDATED |
 		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
@@ -3512,9 +3555,9 @@
  */
 static inline void tg3_full_lock(struct tg3 *tp, int irq_sync)
 {
+	spin_lock_bh(&tp->lock);
 	if (irq_sync)
 		tg3_irq_quiesce(tp);
-	spin_lock_bh(&tp->lock);
 }
 
 static inline void tg3_full_unlock(struct tg3 *tp)
@@ -6444,6 +6487,10 @@
 
 	tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
 		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
+	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+	    !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+		tp->mac_mode |= MAC_MODE_LINK_POLARITY;
 	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
 	udelay(40);
 
@@ -8271,7 +8318,7 @@
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
-		ethtool_op_set_tx_hw_csum(dev, data);
+		ethtool_op_set_tx_ipv6_csum(dev, data);
 	else
 		ethtool_op_set_tx_csum(dev, data);
 
@@ -8805,7 +8852,9 @@
 			return 0;
 
 		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-			   MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY;
+			   MAC_MODE_PORT_INT_LPBACK;
+		if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+			mac_mode |= MAC_MODE_LINK_POLARITY;
 		if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
 			mac_mode |= MAC_MODE_PORT_MODE_MII;
 		else
@@ -8824,19 +8873,18 @@
 					     phytest | MII_TG3_EPHY_SHADOW_EN);
 				if (!tg3_readphy(tp, 0x1b, &phy))
 					tg3_writephy(tp, 0x1b, phy & ~0x20);
-				if (!tg3_readphy(tp, 0x10, &phy))
-					tg3_writephy(tp, 0x10, phy & ~0x4000);
 				tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
 			}
 			val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
 		} else
 			val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
 
+		tg3_phy_toggle_automdix(tp, 0);
+
 		tg3_writephy(tp, MII_BMCR, val);
 		udelay(40);
 
-		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-			   MAC_MODE_LINK_POLARITY;
+		mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 			tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
 			mac_mode |= MAC_MODE_PORT_MODE_MII;
@@ -8849,8 +8897,11 @@
 			udelay(10);
 			tw32_f(MAC_RX_MODE, tp->rx_mode);
 		}
-		if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
-			mac_mode &= ~MAC_MODE_LINK_POLARITY;
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+			if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+				mac_mode &= ~MAC_MODE_LINK_POLARITY;
+			else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411)
+				mac_mode |= MAC_MODE_LINK_POLARITY;
 			tg3_writephy(tp, MII_TG3_EXT_CTRL,
 				     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
 		}
@@ -9116,25 +9167,10 @@
 	/* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
 	__tg3_set_rx_mode(dev);
 
-	tg3_full_unlock(tp);
-
 	if (netif_running(dev))
 		tg3_netif_start(tp);
-}
 
-static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct tg3 *tp = netdev_priv(dev);
-
-	if (netif_running(dev))
-		tg3_netif_stop(tp);
-
-	tg3_full_lock(tp, 0);
-	vlan_group_set_device(tp->vlgrp, vid, NULL);
 	tg3_full_unlock(tp);
-
-	if (netif_running(dev))
-		tg3_netif_start(tp);
 }
 #endif
 
@@ -9425,11 +9461,13 @@
 		case FLASH_5755VENDOR_ATMEL_FLASH_1:
 		case FLASH_5755VENDOR_ATMEL_FLASH_2:
 		case FLASH_5755VENDOR_ATMEL_FLASH_3:
+		case FLASH_5755VENDOR_ATMEL_FLASH_5:
 			tp->nvram_jedecnum = JEDEC_ATMEL;
 			tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
 			tp->tg3_flags2 |= TG3_FLG2_FLASH;
 			tp->nvram_pagesize = 264;
-			if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1)
+			if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 ||
+			    nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5)
 				tp->nvram_size = (protect ? 0x3e200 : 0x80000);
 			else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
 				tp->nvram_size = (protect ? 0x1f200 : 0x40000);
@@ -10513,11 +10551,7 @@
 				continue;
 			}
 			if (pci_id->rev != PCI_ANY_ID) {
-				u8 rev;
-
-				pci_read_config_byte(bridge, PCI_REVISION_ID,
-						     &rev);
-				if (rev > pci_id->rev)
+				if (bridge->revision > pci_id->rev)
 					continue;
 			}
 			if (bridge->subordinate &&
@@ -10976,6 +11010,7 @@
 	 * upon subsystem IDs.
 	 */
 	if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
 	    !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
 				  TG3_FLAG_USE_LINKCHG_REG);
@@ -11778,7 +11813,6 @@
 #if TG3_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = tg3_vlan_rx_register;
-	dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid;
 #endif
 
 	tp = netdev_priv(dev);
@@ -11959,12 +11993,11 @@
 	 * checksumming.
 	 */
 	if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
+		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
-			dev->features |= NETIF_F_HW_CSUM;
-		else
-			dev->features |= NETIF_F_IP_CSUM;
-		dev->features |= NETIF_F_SG;
+			dev->features |= NETIF_F_IPV6_CSUM;
+
 		tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
 	} else
 		tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index bd9f4f4..d84e75e 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1467,6 +1467,7 @@
 #define  FLASH_5755VENDOR_ATMEL_FLASH_2	 0x03400002
 #define  FLASH_5755VENDOR_ATMEL_FLASH_3	 0x03400000
 #define  FLASH_5755VENDOR_ATMEL_FLASH_4	 0x00000003
+#define  FLASH_5755VENDOR_ATMEL_FLASH_5	 0x02000003
 #define  FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ	 0x03c00003
 #define  FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ	 0x03c00002
 #define  FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ	 0x03000003
@@ -1642,6 +1643,11 @@
 
 #define MII_TG3_AUX_CTRL		0x18 /* auxilliary control register */
 
+#define MII_TG3_AUXCTL_MISC_WREN	0x8000
+#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX	0x0200
+#define MII_TG3_AUXCTL_MISC_RDSEL_MISC	0x7000
+#define MII_TG3_AUXCTL_SHDWSEL_MISC		0x0007
+
 #define MII_TG3_AUX_STAT		0x19 /* auxilliary status register */
 #define MII_TG3_AUX_STAT_LPASS		0x0004
 #define MII_TG3_AUX_STAT_SPDMASK	0x0700
@@ -1667,6 +1673,9 @@
 #define MII_TG3_EPHY_TEST		0x1f /* 5906 PHY register */
 #define MII_TG3_EPHY_SHADOW_EN		0x80
 
+#define MII_TG3_EPHYTST_MISCCTRL	0x10 /* 5906 EPHY misc ctrl shadow register */
+#define MII_TG3_EPHYTST_MISCCTRL_MDIX	0x4000
+
 #define MII_TG3_TEST1			0x1e
 #define MII_TG3_TEST1_TRIM_EN		0x0010
 #define MII_TG3_TEST1_CRC_EN		0x8000
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 106dc1e..74eb121 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -533,7 +533,6 @@
 
 	struct net_device  *dev;
 	TLanPrivateInfo    *priv;
-	u8		   pci_rev;
 	u16		   device_id;
 	int		   reg, rc = -ENODEV;
 
@@ -577,8 +576,6 @@
 			goto err_out_free_dev;
 		}
 
-		pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev);
-
 		for ( reg= 0; reg <= 5; reg ++ ) {
 			if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) {
 				pci_io_base = pci_resource_start(pdev, reg);
@@ -595,7 +592,7 @@
 
 		dev->base_addr = pci_io_base;
 		dev->irq = pdev->irq;
-		priv->adapterRev = pci_rev;
+		priv->adapterRev = pdev->revision;
 		pci_set_master(pdev);
 		pci_set_drvdata(pdev, dev);
 
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index e22a3f5..9f1b6ab 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -363,7 +363,7 @@
 }
 
 
-static int __init xl_init(struct net_device *dev) 
+static int __devinit xl_init(struct net_device *dev) 
 {
     	struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
 
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index 99c4c19..e6b2e06 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -2,12 +2,10 @@
 # Token Ring driver configuration
 #
 
-menu "Token Ring devices"
-	depends on NETDEVICES && !UML
-
 # So far, we only have PCI, ISA, and MCA token ring devices
-config TR
+menuconfig TR
 	bool "Token Ring driver support"
+	depends on NETDEVICES && !UML
 	depends on (PCI || ISA || MCA || CCW)
 	select LLC
 	help
@@ -20,9 +18,11 @@
 	  from <http://www.tldp.org/docs.html#howto>. Most people can
 	  say N here.
 
+if TR
+
 config IBMTR
 	tristate "IBM Tropic chipset based adapter support"
-	depends on TR && (ISA || MCA)
+	depends on ISA || MCA
 	---help---
 	  This is support for all IBM Token Ring cards that don't use DMA. If
 	  you have such a beast, say Y and read the Token-Ring mini-HOWTO,
@@ -36,7 +36,7 @@
 
 config IBMOL
 	tristate "IBM Olympic chipset PCI adapter support"
-	depends on TR && PCI
+	depends on PCI
 	---help---
 	  This is support for all non-Lanstreamer IBM PCI Token Ring Cards.
 	  Specifically this is all IBM PCI, PCI Wake On Lan, PCI II, PCI II
@@ -54,7 +54,7 @@
 
 config IBMLS
 	tristate "IBM Lanstreamer chipset PCI adapter support"
-	depends on TR && PCI && !64BIT
+	depends on PCI && !64BIT
 	help
 	  This is support for IBM Lanstreamer PCI Token Ring Cards.
 
@@ -66,7 +66,7 @@
 
 config 3C359
 	tristate "3Com 3C359 Token Link Velocity XL adapter support"
-	depends on TR && PCI
+	depends on PCI
 	---help---
 	  This is support for the 3Com PCI Velocity XL cards, specifically
 	  the 3Com 3C359, please note this is not for the 3C339 cards, you
@@ -84,7 +84,7 @@
 
 config TMS380TR
 	tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
-	depends on TR && (PCI || ISA && ISA_DMA_API || MCA)
+	depends on PCI || ISA && ISA_DMA_API || MCA
 	select FW_LOADER
 	---help---
 	  This driver provides generic support for token ring adapters
@@ -108,7 +108,7 @@
 
 config TMSPCI
 	tristate "Generic TMS380 PCI support"
-	depends on TR && TMS380TR && PCI
+	depends on TMS380TR && PCI
 	---help---
 	  This tms380 module supports generic TMS380-based PCI cards.
 
@@ -123,7 +123,7 @@
 
 config SKISA
 	tristate "SysKonnect TR4/16 ISA support"
-	depends on TR && TMS380TR && ISA
+	depends on TMS380TR && ISA
 	help
 	  This tms380 module supports SysKonnect TR4/16 ISA cards.
 
@@ -135,7 +135,7 @@
 
 config PROTEON
 	tristate "Proteon ISA support"
-	depends on TR && TMS380TR && ISA
+	depends on TMS380TR && ISA
 	help
 	  This tms380 module supports Proteon ISA cards.
 
@@ -148,7 +148,7 @@
 
 config ABYSS
 	tristate "Madge Smart 16/4 PCI Mk2 support"
-	depends on TR && TMS380TR && PCI
+	depends on TMS380TR && PCI
 	help
 	  This tms380 module supports the Madge Smart 16/4 PCI Mk2
 	  cards (51-02).
@@ -158,7 +158,7 @@
 
 config MADGEMC
 	tristate "Madge Smart 16/4 Ringnode MicroChannel"
-	depends on TR && TMS380TR && MCA
+	depends on TMS380TR && MCA
 	help
 	  This tms380 module supports the Madge Smart 16/4 MC16 and MC32
 	  MicroChannel adapters.
@@ -168,7 +168,7 @@
 
 config SMCTR
 	tristate "SMC ISA/MCA adapter support"
-	depends on TR && (ISA || MCA_LEGACY) && (BROKEN || !64BIT)
+	depends on (ISA || MCA_LEGACY) && (BROKEN || !64BIT)
 	---help---
 	  This is support for the ISA and MCA SMC Token Ring cards,
 	  specifically SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A
@@ -182,5 +182,4 @@
 	  To compile this driver as a module, choose M here: the module will be
 	  called smctr.
 
-endmenu
-
+endif # TR
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 58d7e5d..f83bb5c 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -3692,7 +3692,6 @@
         __u16 rcode, correlator;
         int err = 0;
         __u8 xframe = 1;
-        __u16 tx_fstatus;
 
         rmf->vl = SWAP_BYTES(rmf->vl);
         if(rx_status & FCB_RX_STATUS_DA_MATCHED)
@@ -3783,7 +3782,9 @@
                                 }
                                 break;
 
-                        case TX_FORWARD:
+                        case TX_FORWARD: {
+        			__u16 uninitialized_var(tx_fstatus);
+
                                 if((rcode = smctr_rcv_tx_forward(dev, rmf))
                                         != POSITIVE_ACK)
                                 {
@@ -3811,6 +3812,7 @@
                                         }
                                 }
                                 break;
+			}
 
                         /* Received MAC Frames Processed by CRS/REM/RPS. */
                         case RSP:
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 8c9634a..1c537d5 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -2,17 +2,17 @@
 # Tulip family network device configuration
 #
 
-menu "Tulip family network device support"
-	depends on NET_ETHERNET && (PCI || EISA || CARDBUS)
-
-config NET_TULIP
+menuconfig NET_TULIP
 	bool "\"Tulip\" family network device support"
+	depends on PCI || EISA || CARDBUS
 	help
 	  This selects the "Tulip" family of EISA/PCI network cards.
 
+if NET_TULIP
+
 config DE2104X
 	tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)"
-	depends on NET_TULIP && PCI && EXPERIMENTAL
+	depends on PCI && EXPERIMENTAL
 	select CRC32
 	---help---
 	  This driver is developed for the SMC EtherPower series Ethernet
@@ -30,7 +30,7 @@
 
 config TULIP
 	tristate "DECchip Tulip (dc2114x) PCI support"
-	depends on NET_TULIP && PCI
+	depends on PCI
 	select CRC32
 	---help---
 	  This driver is developed for the SMC EtherPower series Ethernet
@@ -95,7 +95,7 @@
 
 config DE4X5
 	tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
-	depends on NET_TULIP && (PCI || EISA)
+	depends on PCI || EISA
 	select CRC32
 	---help---
 	  This is support for the DIGITAL series of PCI/EISA Ethernet cards.
@@ -112,7 +112,7 @@
 
 config WINBOND_840
 	tristate "Winbond W89c840 Ethernet support"
-	depends on NET_TULIP && PCI
+	depends on PCI
 	select CRC32
 	select MII
 	help
@@ -123,7 +123,7 @@
 
 config DM9102
 	tristate "Davicom DM910x/DM980x support"
-	depends on NET_TULIP && PCI
+	depends on PCI
 	select CRC32
 	---help---
 	  This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
@@ -137,7 +137,7 @@
 
 config ULI526X
 	tristate "ULi M526x controller support"
-	depends on NET_TULIP && PCI
+	depends on PCI
 	select CRC32
 	---help---
 	  This driver is for ULi M5261/M5263 10/100M Ethernet Controller
@@ -149,7 +149,7 @@
 	  
 config PCMCIA_XIRCOM
 	tristate "Xircom CardBus support (new driver)"
-	depends on NET_TULIP && CARDBUS
+	depends on CARDBUS
 	---help---
 	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
 	  It should work with most DEC 21*4*-based chips/ethercards, as well
@@ -162,7 +162,7 @@
 
 config PCMCIA_XIRTULIP
 	tristate "Xircom Tulip-like CardBus support (old driver)"
-	depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP
+	depends on CARDBUS && BROKEN_ON_SMP
 	select CRC32
 	---help---
 	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
@@ -174,5 +174,4 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module will
 	  be called xircom_tulip_cb.  If unsure, say N.
 
-endmenu
-
+endif # NET_TULIP
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 8617298..d380e0b 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -785,7 +785,6 @@
 
 	de->tx_head = NEXT_TX(entry);
 
-	BUG_ON(TX_BUFFS_AVAIL(de) < 0);
 	if (TX_BUFFS_AVAIL(de) == 0)
 		netif_stop_queue(dev);
 
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 62143f9..0990289 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -597,7 +597,7 @@
 #endif
 
 struct parameters {
-    int fdx;
+    bool fdx;
     int autosense;
 };
 
@@ -809,10 +809,10 @@
     s32  irq_en;                            /* Summary interrupt bits       */
     int  media;                             /* Media (eg TP), mode (eg 100B)*/
     int  c_media;                           /* Remember the last media conn */
-    int  fdx;                               /* media full duplex flag       */
+    bool fdx;                               /* media full duplex flag       */
     int  linkOK;                            /* Link is OK                   */
     int  autosense;                         /* Allow/disallow autosensing   */
-    int  tx_enable;                         /* Enable descriptor polling    */
+    bool tx_enable;                         /* Enable descriptor polling    */
     int  setup_f;                           /* Setup frame filtering type   */
     int  local_state;                       /* State within a 'media' state */
     struct mii_phy phy[DE4X5_MAX_PHY];      /* List of attached PHY devices */
@@ -838,8 +838,8 @@
     struct de4x5_srom srom;                 /* A copy of the SROM           */
     int cfrv;				    /* Card CFRV copy */
     int rx_ovf;                             /* Check for 'RX overflow' tag  */
-    int useSROM;                            /* For non-DEC card use SROM    */
-    int useMII;                             /* Infoblock using the MII      */
+    bool useSROM;                           /* For non-DEC card use SROM    */
+    bool useMII;                            /* Infoblock using the MII      */
     int asBitValid;                         /* Autosense bits in GEP?       */
     int asPolarity;                         /* 0 => asserted high           */
     int asBit;                              /* Autosense bit number in GEP  */
@@ -928,7 +928,7 @@
 static int     test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
 static int     test_for_100Mb(struct net_device *dev, int msec);
 static int     wait_for_link(struct net_device *dev);
-static int     test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec);
+static int     test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec);
 static int     is_spd_100(struct net_device *dev);
 static int     is_100_up(struct net_device *dev);
 static int     is_10_up(struct net_device *dev);
@@ -1109,7 +1109,7 @@
     /*
     ** Now find out what kind of DC21040/DC21041/DC21140 board we have.
     */
-    lp->useSROM = FALSE;
+    lp->useSROM = false;
     if (lp->bus == PCI) {
 	PCI_signature(name, lp);
     } else {
@@ -1137,7 +1137,7 @@
 	lp->cache.gepc = GEP_INIT;
 	lp->asBit = GEP_SLNK;
 	lp->asPolarity = GEP_SLNK;
-	lp->asBitValid = TRUE;
+	lp->asBitValid = ~0;
 	lp->timeout = -1;
 	lp->gendev = gendev;
 	spin_lock_init(&lp->lock);
@@ -1463,7 +1463,7 @@
     u_long flags = 0;
 
     netif_stop_queue(dev);
-    if (lp->tx_enable == NO) {                   /* Cannot send for now */
+    if (!lp->tx_enable) {                   /* Cannot send for now */
 	return -1;
     }
 
@@ -2134,7 +2134,7 @@
     u_short vendor, status;
     u_int irq = 0, device;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
-    int i, j, cfrv;
+    int i, j;
     struct de4x5_private *lp = netdev_priv(dev);
     struct list_head *walk;
 
@@ -2150,7 +2150,6 @@
 
 	/* Get the chip configuration revision register */
 	pb = this_dev->bus->number;
-	pci_read_config_dword(this_dev, PCI_REVISION_ID, &cfrv);
 
 	/* Set the device number information */
 	lp->device = PCI_SLOT(this_dev->devfn);
@@ -2158,7 +2157,8 @@
 
 	/* Set the chipset information */
 	if (is_DC2114x) {
-	    device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+	    device = ((this_dev->revision & CFRV_RN) < DC2114x_BRK
+		      ? DC21142 : DC21143);
 	}
 	lp->chipset = device;
 
@@ -2254,7 +2254,7 @@
 	}
 
 	/* Get the chip configuration revision register */
-	pci_read_config_dword(pdev, PCI_REVISION_ID, &lp->cfrv);
+	lp->cfrv = pdev->revision;
 
 	/* Set the device number information */
 	lp->device = dev_num;
@@ -2424,7 +2424,7 @@
     switch (lp->media) {
     case INIT:
 	DISABLE_IRQs;
-	lp->tx_enable = NO;
+	lp->tx_enable = false;
 	lp->timeout = -1;
 	de4x5_save_skbs(dev);
 	if ((lp->autosense == AUTO) || (lp->autosense == TP)) {
@@ -2477,7 +2477,7 @@
 	    lp->c_media = lp->media;
 	}
 	lp->media = INIT;
-	lp->tx_enable = NO;
+	lp->tx_enable = false;
 	break;
     }
 
@@ -2578,7 +2578,7 @@
     switch (lp->media) {
     case INIT:
 	DISABLE_IRQs;
-	lp->tx_enable = NO;
+	lp->tx_enable = false;
 	lp->timeout = -1;
 	de4x5_save_skbs(dev);          /* Save non transmitted skb's */
 	if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) {
@@ -2757,7 +2757,7 @@
 	    lp->c_media = lp->media;
 	}
 	lp->media = INIT;
-	lp->tx_enable = NO;
+	lp->tx_enable = false;
 	break;
     }
 
@@ -2781,7 +2781,7 @@
     case INIT:
         if (lp->timeout < 0) {
 	    DISABLE_IRQs;
-	    lp->tx_enable = FALSE;
+	    lp->tx_enable = false;
 	    lp->linkOK = 0;
 	    de4x5_save_skbs(dev);          /* Save non transmitted skb's */
 	}
@@ -2830,7 +2830,7 @@
 	    if (lp->timeout < 0) {
 		mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
 	    }
-	    cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+	    cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
 	    if (cr < 0) {
 		next_tick = cr & ~TIMER_CB;
 	    } else {
@@ -2845,7 +2845,7 @@
 	    break;
 
 	case 1:
-	    if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+	    if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) {
 		next_tick = sr & ~TIMER_CB;
 	    } else {
 		lp->media = SPD_DET;
@@ -2857,10 +2857,10 @@
 		    if (!(anlpa & MII_ANLPA_RF) &&
 			 (cap = anlpa & MII_ANLPA_TAF & ana)) {
 			if (cap & MII_ANA_100M) {
-			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+			    lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
 			    lp->media = _100Mb;
 			} else if (cap & MII_ANA_10M) {
-			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+			    lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
 
 			    lp->media = _10Mb;
 			}
@@ -2932,7 +2932,7 @@
 	    lp->c_media = lp->media;
 	}
 	lp->media = INIT;
-	lp->tx_enable = FALSE;
+	lp->tx_enable = false;
 	break;
     }
 
@@ -2965,7 +2965,7 @@
     case INIT:
         if (lp->timeout < 0) {
 	    DISABLE_IRQs;
-	    lp->tx_enable = FALSE;
+	    lp->tx_enable = false;
 	    lp->linkOK = 0;
             lp->timeout = -1;
 	    de4x5_save_skbs(dev);            /* Save non transmitted skb's */
@@ -3013,7 +3013,7 @@
 	    if (lp->timeout < 0) {
 		mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
 	    }
-	    cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+	    cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
 	    if (cr < 0) {
 		next_tick = cr & ~TIMER_CB;
 	    } else {
@@ -3028,7 +3028,8 @@
 	    break;
 
 	case 1:
-	    if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+	    sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000);
+	    if (sr < 0) {
 		next_tick = sr & ~TIMER_CB;
 	    } else {
 		lp->media = SPD_DET;
@@ -3040,10 +3041,10 @@
 		    if (!(anlpa & MII_ANLPA_RF) &&
 			 (cap = anlpa & MII_ANLPA_TAF & ana)) {
 			if (cap & MII_ANA_100M) {
-			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+			    lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
 			    lp->media = _100Mb;
 			} else if (cap & MII_ANA_10M) {
-			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+			    lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
 			    lp->media = _10Mb;
 			}
 		    }
@@ -3222,14 +3223,14 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
 
-    lp->fdx = 0;
+    lp->fdx = false;
     if (lp->infoblock_media == lp->media)
       return 0;
 
     switch(lp->infoblock_media) {
       case SROM_10BASETF:
 	if (!lp->params.fdx) return -1;
-	lp->fdx = TRUE;
+	lp->fdx = true;
       case SROM_10BASET:
 	if (lp->params.fdx && !lp->fdx) return -1;
 	if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) {
@@ -3249,7 +3250,7 @@
 
       case SROM_100BASETF:
         if (!lp->params.fdx) return -1;
-	lp->fdx = TRUE;
+	lp->fdx = true;
       case SROM_100BASET:
 	if (lp->params.fdx && !lp->fdx) return -1;
 	lp->media = _100Mb;
@@ -3261,7 +3262,7 @@
 
       case SROM_100BASEFF:
 	if (!lp->params.fdx) return -1;
-	lp->fdx = TRUE;
+	lp->fdx = true;
       case SROM_100BASEF:
 	if (lp->params.fdx && !lp->fdx) return -1;
 	lp->media = _100Mb;
@@ -3297,7 +3298,7 @@
     spin_lock_irqsave(&lp->lock, flags);
     de4x5_rst_desc_ring(dev);
     de4x5_setup_intr(dev);
-    lp->tx_enable = YES;
+    lp->tx_enable = true;
     spin_unlock_irqrestore(&lp->lock, flags);
     outl(POLL_DEMAND, DE4X5_TPD);
 
@@ -3336,7 +3337,7 @@
             }
         }
 	if (lp->useMII) {
-	    next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500);
+	    next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500);
 	}
     } else if (lp->chipset == DC21140) {
 	PHY_HARD_RESET;
@@ -3466,7 +3467,7 @@
 **
 */
 static int
-test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
+test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     int test;
@@ -3476,9 +3477,8 @@
 	lp->timeout = msec/100;
     }
 
-    if (pol) pol = ~0;
     reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
-    test = (reg ^ pol) & mask;
+    test = (reg ^ (pol ? ~0 : 0)) & mask;
 
     if (test && --lp->timeout) {
 	reg = 100 | TIMER_CB;
@@ -3992,10 +3992,10 @@
 			     )))))));
 	}
 	if (lp->chipset != DC21041) {
-	    lp->useSROM = TRUE;             /* card is not recognisably DEC */
+	    lp->useSROM = true;             /* card is not recognisably DEC */
 	}
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
-	lp->useSROM = TRUE;
+	lp->useSROM = true;
     }
 
     return status;
@@ -4216,7 +4216,7 @@
 	memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom));
 	memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN);
 	memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100);
-	lp->useSROM = TRUE;
+	lp->useSROM = true;
 	break;
     }
 
@@ -4392,7 +4392,7 @@
 	if (lp->chipset == infoleaf_array[i].chipset) break;
     }
     if (i == INFOLEAF_SIZE) {
-	lp->useSROM = FALSE;
+	lp->useSROM = false;
 	printk("%s: Cannot find correct chipset for SROM decoding!\n",
 	                                                          dev->name);
 	return -ENXIO;
@@ -4409,7 +4409,7 @@
 	    if (lp->device == *p) break;
 	}
 	if (i == 0) {
-	    lp->useSROM = FALSE;
+	    lp->useSROM = false;
 	    printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
 	                                               dev->name, lp->device);
 	    return -ENXIO;
@@ -4542,7 +4542,7 @@
 	}
 	lp->media = INIT;
 	lp->tcount = 0;
-	lp->tx_enable = FALSE;
+	lp->tx_enable = false;
     }
 
     return next_tick & ~TIMER_CB;
@@ -4577,7 +4577,7 @@
 	}
 	lp->media = INIT;
 	lp->tcount = 0;
-	lp->tx_enable = FALSE;
+	lp->tx_enable = false;
     }
 
     return next_tick & ~TIMER_CB;
@@ -4611,7 +4611,7 @@
 	}
 	lp->media = INIT;
 	lp->tcount = 0;
-	lp->tx_enable = FALSE;
+	lp->tx_enable = false;
     }
 
     return next_tick & ~TIMER_CB;
@@ -4650,7 +4650,7 @@
 	lp->asBit = 1 << ((csr6 >> 1) & 0x07);
 	lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
 	lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
-	lp->useMII = FALSE;
+	lp->useMII = false;
 
 	de4x5_switch_mac_port(dev);
     }
@@ -4691,7 +4691,7 @@
 	lp->asBit = 1 << ((csr6 >> 1) & 0x07);
 	lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
 	lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
-	lp->useMII = FALSE;
+	lp->useMII = false;
 
 	de4x5_switch_mac_port(dev);
     }
@@ -4731,7 +4731,7 @@
         lp->ibn = 1;
         lp->active = *p;
 	lp->infoblock_csr6 = OMR_MII_100;
-	lp->useMII = TRUE;
+	lp->useMII = true;
 	lp->infoblock_media = ANS;
 
 	de4x5_switch_mac_port(dev);
@@ -4773,7 +4773,7 @@
         lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
         lp->cache.gep  = ((s32)(TWIDDLE(p)) << 16);
 	lp->infoblock_csr6 = OMR_SIA;
-	lp->useMII = FALSE;
+	lp->useMII = false;
 
 	de4x5_switch_mac_port(dev);
     }
@@ -4814,7 +4814,7 @@
 	lp->active = *p;
 	if (MOTO_SROM_BUG) lp->active = 0;
 	lp->infoblock_csr6 = OMR_MII_100;
-	lp->useMII = TRUE;
+	lp->useMII = true;
 	lp->infoblock_media = ANS;
 
 	de4x5_switch_mac_port(dev);
@@ -4856,7 +4856,7 @@
 	lp->asBit = 1 << ((csr6 >> 1) & 0x07);
 	lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
 	lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
-	lp->useMII = FALSE;
+	lp->useMII = false;
 
 	de4x5_switch_mac_port(dev);
     }
@@ -5077,7 +5077,7 @@
     int id;
 
     lp->active = 0;
-    lp->useMII = TRUE;
+    lp->useMII = true;
 
     /* Search the MII address space for possible PHY devices */
     for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
@@ -5127,7 +5127,7 @@
 	    de4x5_dbg_mii(dev, k);
 	}
     }
-    if (!lp->mii_cnt) lp->useMII = FALSE;
+    if (!lp->mii_cnt) lp->useMII = false;
 
     return lp->mii_cnt;
 }
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index 57226e5..12af0cc 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -893,15 +893,6 @@
 #define PHYS_ADDR_ONLY       1     /* Update the physical address only */
 
 /*
-** Booleans
-*/
-#define NO                   0
-#define FALSE                0
-
-#define YES                  ~0
-#define TRUE                 ~0
-
-/*
 ** Adapter state
 */
 #define INITIALISED          0     /* After h/w initialised and mem alloc'd */
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 4ed67ff..dab74fe 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -181,11 +181,12 @@
 	udelay(5);
 
 #define __CHK_IO_SIZE(pci_id, dev_rev) \
- (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? \
+ (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x30) ) ? \
 	DM9102A_IO_SIZE: DM9102_IO_SIZE)
 
-#define CHK_IO_SIZE(pci_dev, dev_rev) \
-	(__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev))
+#define CHK_IO_SIZE(pci_dev) \
+	(__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, \
+	(pci_dev)->revision))
 
 /* Sten Check */
 #define DEVICE net_device
@@ -205,7 +206,7 @@
 
 struct dmfe_board_info {
 	u32 chip_id;			/* Chip vendor/Device ID */
-	u32 chip_revision;		/* Chip revision */
+	u8 chip_revision;		/* Chip revision */
 	struct DEVICE *next_dev;	/* next device */
 	struct pci_dev *pdev;		/* PCI device */
 	spinlock_t lock;
@@ -359,7 +360,7 @@
 {
 	struct dmfe_board_info *db;	/* board information structure */
 	struct net_device *dev;
-	u32 dev_rev, pci_pmr;
+	u32 pci_pmr;
 	int i, err;
 
 	DMFE_DBUG(0, "dmfe_init_one()", 0);
@@ -392,10 +393,7 @@
 		goto err_out_disable;
 	}
 
-	/* Read Chip revision */
-	pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
-
-	if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev, dev_rev)) ) {
+	if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev)) ) {
 		printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n");
 		err = -ENODEV;
 		goto err_out_disable;
@@ -433,7 +431,7 @@
 
 	db->chip_id = ent->driver_data;
 	db->ioaddr = pci_resource_start(pdev, 0);
-	db->chip_revision = dev_rev;
+	db->chip_revision = pdev->revision;
 	db->wol_mode = 0;
 
 	db->pdev = pdev;
@@ -455,7 +453,7 @@
 
 	pci_read_config_dword(pdev, 0x50, &pci_pmr);
 	pci_pmr &= 0x70000;
-	if ( (pci_pmr == 0x10000) && (dev_rev == 0x02000031) )
+	if ( (pci_pmr == 0x10000) && (db->chip_revision == 0x31) )
 		db->chip_type = 1;	/* DM9102A E3 */
 	else
 		db->chip_type = 0;
@@ -553,7 +551,7 @@
 
 	/* CR6 operation mode decision */
 	if ( !chkmode || (db->chip_id == PCI_DM9132_ID) ||
-		(db->chip_revision >= 0x02000030) ) {
+		(db->chip_revision >= 0x30) ) {
     		db->cr6_data |= DMFE_TXTH_256;
 		db->cr0_data = CR0_DEFAULT;
 		db->dm910x_chk_mode=4;		/* Enter the normal mode */
@@ -1199,9 +1197,9 @@
 		tmp_cr12 = inb(db->ioaddr + DCR12);	/* DM9102/DM9102A */
 
 	if ( ((db->chip_id == PCI_DM9102_ID) &&
-		(db->chip_revision == 0x02000030)) ||
+		(db->chip_revision == 0x30)) ||
 		((db->chip_id == PCI_DM9132_ID) &&
-		(db->chip_revision == 0x02000010)) ) {
+		(db->chip_revision == 0x10)) ) {
 		/* DM9102A Chip */
 		if (tmp_cr12 & 2)
 			link_ok = 0;
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index ea89677..53efd66 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -197,8 +197,8 @@
 								   tp->rx_buffers[entry].mapping,
 								   pkt_len, PCI_DMA_FROMDEVICE);
 #if ! defined(__alpha__)
-                                       eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
-                                                        pkt_len, 0);
+                                       skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+                                                        pkt_len);
                                        skb_put(skb, pkt_len);
 #else
                                        memcpy(skb_put(skb, pkt_len),
@@ -420,8 +420,8 @@
 							    tp->rx_buffers[entry].mapping,
 							    pkt_len, PCI_DMA_FROMDEVICE);
 #if ! defined(__alpha__)
-				eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
-						 pkt_len, 0);
+				skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+						 pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 041af63..f87d769 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1155,7 +1155,7 @@
 	/* set or disable MWI in the standard PCI command bit.
 	 * Check for the case where  mwi is desired but not available
 	 */
-	if (csr0 & MWI)	pci_set_mwi(pdev);
+	if (csr0 & MWI)	pci_try_set_mwi(pdev);
 	else		pci_clear_mwi(pdev);
 
 	/* read result from hardware (in case bit refused to enable) */
@@ -1238,7 +1238,6 @@
 	};
 	static int last_irq;
 	static int multiport_cnt;	/* For four-port boards w/one EEPROM */
-	u8 chip_rev;
 	int i, irq;
 	unsigned short sum;
 	unsigned char *ee_data;
@@ -1274,10 +1273,8 @@
 
 	if (pdev->vendor == 0x1282 && pdev->device == 0x9100)
 	{
-		u32 dev_rev;
 		/* Read Chip revision */
-		pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
-		if(dev_rev < 0x02000030)
+		if (pdev->revision < 0x30)
 		{
 			printk(KERN_ERR PFX "skipping early DM9100 with Crc bug (use dmfe)\n");
 			return -ENODEV;
@@ -1360,8 +1357,6 @@
 	if (!ioaddr)
 		goto err_out_free_res;
 
-	pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev);
-
 	/*
 	 * initialize private data structure 'tp'
 	 * it is zeroed and aligned in alloc_etherdev
@@ -1382,7 +1377,7 @@
 	tp->flags = tulip_tbl[chip_idx].flags;
 	tp->pdev = pdev;
 	tp->base_addr = ioaddr;
-	tp->revision = chip_rev;
+	tp->revision = pdev->revision;
 	tp->csr0 = csr0;
 	spin_lock_init(&tp->lock);
 	spin_lock_init(&tp->mii_lock);
@@ -1399,7 +1394,7 @@
 		tulip_mwi_config (pdev, dev);
 #else
 	/* MWI is broken for DC21143 rev 65... */
-	if (chip_idx == DC21143 && chip_rev == 65)
+	if (chip_idx == DC21143 && pdev->revision == 65)
 		tp->csr0 &= ~MWI;
 #endif
 
@@ -1640,7 +1635,7 @@
 #else
 		"Port"
 #endif
-		" %#llx,", dev->name, chip_name, chip_rev,
+		" %#llx,", dev->name, chip_name, pdev->revision,
 		(unsigned long long) pci_resource_start(pdev, TULIP_BAR));
 	pci_set_drvdata(pdev, dev);
 
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 38f3b99..5824f6a 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -1232,7 +1232,7 @@
 				pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry],
 							    np->rx_skbuff[entry]->len,
 							    PCI_DMA_FROMDEVICE);
-				eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry],
 							       np->rx_skbuff[entry]->len,
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 2470b1e..16a54e6 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -205,7 +205,6 @@
 {
 	struct net_device *dev = NULL;
 	struct xircom_private *private;
-	unsigned char chip_rev;
 	unsigned long flags;
 	unsigned short tmp16;
 	enter("xircom_probe");
@@ -224,8 +223,6 @@
 	pci_read_config_word (pdev,PCI_STATUS, &tmp16);
 	pci_write_config_word (pdev, PCI_STATUS,tmp16);
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
-
 	if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) {
 		printk(KERN_ERR "xircom_probe: failed to allocate io-region\n");
 		return -ENODEV;
@@ -286,7 +283,7 @@
 		goto reg_fail;
 	}
 
-	printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq);
+	printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, pdev->revision, pdev->irq);
 	/* start the transmitter to get a heartbeat */
 	/* TODO: send 2 dummy packets here */
 	transceiver_voodoo(private);
@@ -1208,7 +1205,7 @@
 				goto out;
 			}
 			skb_reserve(skb, 2);
-			eth_copy_and_sum(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len, 0);
+			skb_copy_to_linear_data(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len);
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
index f641729..fc439f3 100644
--- a/drivers/net/tulip/xircom_tulip_cb.c
+++ b/drivers/net/tulip/xircom_tulip_cb.c
@@ -524,7 +524,6 @@
 	int chip_idx = id->driver_data;
 	long ioaddr;
 	int i;
-	u8 chip_rev;
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -620,9 +619,8 @@
 	if (register_netdev(dev))
 		goto err_out_cleardev;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
 	printk(KERN_INFO "%s: %s rev %d at %#3lx,",
-	       dev->name, xircom_tbl[chip_idx].chip_name, chip_rev, ioaddr);
+	       dev->name, xircom_tbl[chip_idx].chip_name, pdev->revision, ioaddr);
 	for (i = 0; i < 6; i++)
 		printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
 	printk(", IRQ %d.\n", dev->irq);
@@ -1242,8 +1240,8 @@
 				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
 #if ! defined(__alpha__)
-				eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
-								 pkt_len, 0);
+				skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
+								 pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a2c6caa..62b2b30 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -432,6 +432,7 @@
 	init_waitqueue_head(&tun->read_wait);
 
 	tun->owner = -1;
+	tun->group = -1;
 
 	SET_MODULE_OWNER(dev);
 	dev->open = tun_net_open;
@@ -467,8 +468,11 @@
 			return -EBUSY;
 
 		/* Check permissions */
-		if (tun->owner != -1 &&
-		    current->euid != tun->owner && !capable(CAP_NET_ADMIN))
+		if (((tun->owner != -1 &&
+		      current->euid != tun->owner) ||
+		     (tun->group != -1 &&
+		      current->egid != tun->group)) &&
+		     !capable(CAP_NET_ADMIN))
 			return -EPERM;
 	}
 	else if (__dev_get_by_name(ifr->ifr_name))
@@ -610,6 +614,13 @@
 		DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
 		break;
 
+	case TUNSETGROUP:
+		/* Set group of the device */
+		tun->group= (gid_t) arg;
+
+		DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
+		break;
+
 	case TUNSETLINK:
 		/* Only allow setting the type when the interface is down */
 		if (tun->dev->flags & IFF_UP) {
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index f725735..0358720 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -741,15 +741,6 @@
 	spin_unlock_bh(&tp->state_lock);
 }
 
-static void
-typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct typhoon *tp = netdev_priv(dev);
-	spin_lock_bh(&tp->state_lock);
-	vlan_group_set_device(tp->vlgrp, vid, NULL);
-	spin_unlock_bh(&tp->state_lock);
-}
-
 static inline void
 typhoon_tso_fill(struct sk_buff *skb, struct transmit_ring *txRing,
 			u32 ring_dma)
@@ -1712,7 +1703,7 @@
 			pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
 						    PKT_BUF_SZ,
 						    PCI_DMA_FROMDEVICE);
-			eth_copy_and_sum(new_skb, skb->data, pkt_len, 0);
+			skb_copy_to_linear_data(new_skb, skb->data, pkt_len);
 			pci_dma_sync_single_for_device(tp->pdev, dma_addr,
 						       PKT_BUF_SZ,
 						       PCI_DMA_FROMDEVICE);
@@ -2276,12 +2267,6 @@
 	typhoon_resume(pdev);
 	return -EBUSY;
 }
-
-static int
-typhoon_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable)
-{
-	return pci_enable_wake(pdev, state, enable);
-}
 #endif
 
 static int __devinit
@@ -2542,7 +2527,7 @@
 	dev->get_stats		= typhoon_get_stats;
 	dev->set_mac_address	= typhoon_set_mac_address;
 	dev->vlan_rx_register	= typhoon_vlan_rx_register;
-	dev->vlan_rx_kill_vid	= typhoon_vlan_rx_kill_vid;
+
 	SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
 
 	/* We can handle scatter gather, up to 16 entries, and
@@ -2645,7 +2630,6 @@
 #ifdef CONFIG_PM
 	.suspend	= typhoon_suspend,
 	.resume		= typhoon_resume,
-	.enable_wake	= typhoon_enable_wake,
 #endif
 };
 
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index c2ccbd0..e4736a3 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -23,11 +23,8 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/fsl_devices.h>
-#include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/workqueue.h>
@@ -2279,7 +2276,7 @@
 	phy_stop(phydev);
 
 	/* Mask all interrupts */
-	out_be32(ugeth->uccf->p_ucce, 0x00000000);
+	out_be32(ugeth->uccf->p_uccm, 0x00000000);
 
 	/* Clear all interrupts */
 	out_be32(ugeth->uccf->p_ucce, 0xffffffff);
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index f96966d..7bcb82f 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -260,8 +260,6 @@
 	{},
 };
 
-MODULE_DEVICE_TABLE(of, uec_mdio_match);
-
 static struct of_platform_driver uec_mdio_driver = {
 	.name	= DRV_NAME,
 	.probe	= uec_mdio_probe,
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 3de564b..8dc09a3 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -313,8 +313,8 @@
 	boolean "KT Technology KC2190 based cables (InstaNet)"
 	depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
 	help
-	  Choose this option if you're using a host-to-host cable
-	  with one of these chips.
+	  Choose this option if you're using a host-to-host cable
+	  with one of these chips.
 
 config USB_NET_ZAURUS
 	tristate "Sharp Zaurus (stock ROMs) and compatible"
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index d5ef97b..6d95cac 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -1458,6 +1458,10 @@
 	// IO-DATA ETG-US2
 	USB_DEVICE (0x04bb, 0x0930),
 	.driver_info = (unsigned long) &ax88178_info,
+}, {
+	// Belkin F5D5055
+	USB_DEVICE(0x050d, 0x5055),
+	.driver_info = (unsigned long) &ax88178_info,
 },
 	{ },		// END
 };
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 86e90c5..76752d84 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -255,7 +255,7 @@
 		if (!(skb = dev_alloc_skb(pkt_len)))
 			return;
 
-		eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
+		skb_copy_to_linear_data(skb, pkt_start + pkt_offset, pkt_len);
 		skb_put(skb, pkt_len);
 
 		skb->protocol = eth_type_trans(skb, catc->netdev);
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 5a21f06..a42acc3 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -91,6 +91,22 @@
 				"CDC descriptors on config\n");
 	}
 
+	/* Maybe CDC descriptors are after the endpoint?  This bug has
+	 * been seen on some 2Wire Inc RNDIS-ish products.
+	 */
+	if (len == 0) {
+		struct usb_host_endpoint	*hep;
+
+		hep = intf->cur_altsetting->endpoint;
+		if (hep) {
+			buf = hep->extra;
+			len = hep->extralen;
+		}
+		if (len)
+			dev_dbg(&intf->dev,
+				"CDC descriptors on endpoint\n");
+	}
+
 	/* this assumes that if there's a non-RNDIS vendor variant
 	 * of cdc-acm, it'll fail RNDIS requests cleanly.
 	 */
@@ -128,14 +144,14 @@
 			 * modem interface from an RNDIS non-modem.
 			 */
 			if (rndis) {
-				struct usb_cdc_acm_descriptor *d;
+				struct usb_cdc_acm_descriptor *acm;
 
-				d = (void *) buf;
-				if (d->bmCapabilities) {
+				acm = (void *) buf;
+				if (acm->bmCapabilities) {
 					dev_dbg(&intf->dev,
 						"ACM capabilities %02x, "
 						"not really RNDIS?\n",
-						d->bmCapabilities);
+						acm->bmCapabilities);
 					goto bad_desc;
 				}
 			}
diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c
index bc62b01..943988e 100644
--- a/drivers/net/usb/cdc_subset.c
+++ b/drivers/net/usb/cdc_subset.c
@@ -305,6 +305,9 @@
 	USB_DEVICE (0x8086, 0x07d3),	// "blob" bootloader
 	.driver_info =	(unsigned long) &blob_info,
 }, {
+	USB_DEVICE (0x1286, 0x8001),    // "blob" bootloader
+	.driver_info =  (unsigned long) &blob_info,
+}, {
 	// Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config
 	// e.g. Gumstix, current OpenZaurus, ...
 	USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index a6763860..16c7a0e 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -414,18 +414,16 @@
 	dev->mii.reg_num_mask = 0x1f;
 
 	/* reset */
-	ret = dm_write_reg(dev, DM_NET_CTRL, 1);
+	dm_write_reg(dev, DM_NET_CTRL, 1);
 	udelay(20);
 
 	/* read MAC */
-	ret = dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
-	if (ret < 0) {
+	if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr) < 0) {
 		printk(KERN_ERR "Error reading MAC address\n");
 		ret = -ENODEV;
 		goto out;
 	}
 
-
 	/* power up phy */
 	dm_write_reg(dev, DM_GPR_CTRL, 1);
 	dm_write_reg(dev, DM_GPR_DATA, 0);
@@ -489,6 +487,8 @@
 	   b3..n: packet data
 	*/
 
+	len = skb->len;
+
 	if (skb_headroom(skb) < DM_TX_OVERHEAD) {
 		struct sk_buff *skb2;
 
@@ -501,10 +501,9 @@
 
 	__skb_push(skb, DM_TX_OVERHEAD);
 
-	len = skb->len;
 	/* usbnet adds padding if length is a multiple of packet size
 	   if so, adjust length value in header */
-	if ((len % dev->maxpacket) == 0)
+	if ((skb->len % dev->maxpacket) == 0)
 		len++;
 
 	skb->data[0] = len;
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 60d2944..524dc5f 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -635,7 +635,7 @@
 
 		skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
 
-		eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
+		skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len);
 
 		skb_put(skb, pkt_len);
 
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 980e4aa..cd991a0 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -515,6 +515,7 @@
 		dev_err(&intf->dev,
 			"dev can't take %u byte packets (max %u)\n",
 			dev->hard_mtu, tmp);
+		retval = -EINVAL;
 		goto fail_and_release;
 	}
 
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index f9cd42d..37bf4f2 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -192,7 +192,7 @@
 				usb_pipeendpoint(pipe), maxp, period);
 		}
 	}
-	return  0;
+	return 0;
 }
 
 /* Passes this packet up the stack, updating its accounting.
@@ -326,7 +326,7 @@
 	if (netif_running (dev->net)
 			&& netif_device_present (dev->net)
 			&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
-		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
+		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
 		case -EPIPE:
 			usbnet_defer_kevent (dev, EVENT_RX_HALT);
 			break;
@@ -393,8 +393,8 @@
 	entry->urb = NULL;
 
 	switch (urb_status) {
-	    // success
-	    case 0:
+	/* success */
+	case 0:
 		if (skb->len < dev->net->hard_header_len) {
 			entry->state = rx_cleanup;
 			dev->stats.rx_errors++;
@@ -404,28 +404,30 @@
 		}
 		break;
 
-	    // stalls need manual reset. this is rare ... except that
-	    // when going through USB 2.0 TTs, unplug appears this way.
-	    // we avoid the highspeed version of the ETIMEOUT/EILSEQ
-	    // storm, recovering as needed.
-	    case -EPIPE:
+	/* stalls need manual reset. this is rare ... except that
+	 * when going through USB 2.0 TTs, unplug appears this way.
+	 * we avoid the highspeed version of the ETIMEOUT/EILSEQ
+	 * storm, recovering as needed.
+	 */
+	case -EPIPE:
 		dev->stats.rx_errors++;
 		usbnet_defer_kevent (dev, EVENT_RX_HALT);
 		// FALLTHROUGH
 
-	    // software-driven interface shutdown
-	    case -ECONNRESET:		// async unlink
-	    case -ESHUTDOWN:		// hardware gone
+	/* software-driven interface shutdown */
+	case -ECONNRESET:		/* async unlink */
+	case -ESHUTDOWN:		/* hardware gone */
 		if (netif_msg_ifdown (dev))
 			devdbg (dev, "rx shutdown, code %d", urb_status);
 		goto block;
 
-	    // we get controller i/o faults during khubd disconnect() delays.
-	    // throttle down resubmits, to avoid log floods; just temporarily,
-	    // so we still recover when the fault isn't a khubd delay.
-	    case -EPROTO:
-	    case -ETIME:
-	    case -EILSEQ:
+	/* we get controller i/o faults during khubd disconnect() delays.
+	 * throttle down resubmits, to avoid log floods; just temporarily,
+	 * so we still recover when the fault isn't a khubd delay.
+	 */
+	case -EPROTO:
+	case -ETIME:
+	case -EILSEQ:
 		dev->stats.rx_errors++;
 		if (!timer_pending (&dev->delay)) {
 			mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@@ -438,12 +440,12 @@
 		urb = NULL;
 		break;
 
-	    // data overrun ... flush fifo?
-	    case -EOVERFLOW:
+	/* data overrun ... flush fifo? */
+	case -EOVERFLOW:
 		dev->stats.rx_over_errors++;
 		// FALLTHROUGH
 
-	    default:
+	default:
 		entry->state = rx_cleanup;
 		dev->stats.rx_errors++;
 		if (netif_msg_rx_err (dev))
@@ -471,22 +473,22 @@
 	int		status = urb->status;
 
 	switch (status) {
-	    /* success */
-	    case 0:
+	/* success */
+	case 0:
 		dev->driver_info->status(dev, urb);
 		break;
 
-	    /* software-driven interface shutdown */
-	    case -ENOENT:		// urb killed
-	    case -ESHUTDOWN:		// hardware gone
+	/* software-driven interface shutdown */
+	case -ENOENT:		/* urb killed */
+	case -ESHUTDOWN:	/* hardware gone */
 		if (netif_msg_ifdown (dev))
 			devdbg (dev, "intr shutdown, code %d", status);
 		return;
 
-	    /* NOTE:  not throttling like RX/TX, since this endpoint
-	     * already polls infrequently
-	     */
-	    default:
+	/* NOTE:  not throttling like RX/TX, since this endpoint
+	 * already polls infrequently
+	 */
+	default:
 		devdbg (dev, "intr status %d", status);
 		break;
 	}
@@ -569,9 +571,9 @@
 	temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
 
 	// maybe wait for deletions to finish.
-	while (!skb_queue_empty(&dev->rxq) &&
-	       !skb_queue_empty(&dev->txq) &&
-	       !skb_queue_empty(&dev->done)) {
+	while (!skb_queue_empty(&dev->rxq)
+			&& !skb_queue_empty(&dev->txq)
+			&& !skb_queue_empty(&dev->done)) {
 		msleep(UNLINK_TIMEOUT_MS);
 		if (netif_msg_ifdown (dev))
 			devdbg (dev, "waited for %d urb completions", temp);
@@ -953,11 +955,14 @@
 	/* don't assume the hardware handles USB_ZERO_PACKET
 	 * NOTE:  strictly conforming cdc-ether devices should expect
 	 * the ZLP here, but ignore the one-byte packet.
-	 *
-	 * FIXME zero that byte, if it doesn't require a new skb.
 	 */
-	if ((length % dev->maxpacket) == 0)
+	if ((length % dev->maxpacket) == 0) {
 		urb->transfer_buffer_length++;
+		if (skb_tailroom(skb)) {
+			skb->data[skb->len] = 0;
+			__skb_put(skb, 1);
+		}
+	}
 
 	spin_lock_irqsave (&dev->txq.lock, flags);
 
@@ -1008,16 +1013,16 @@
 	while ((skb = skb_dequeue (&dev->done))) {
 		entry = (struct skb_data *) skb->cb;
 		switch (entry->state) {
-		    case rx_done:
+		case rx_done:
 			entry->state = rx_cleanup;
 			rx_process (dev, skb);
 			continue;
-		    case tx_done:
-		    case rx_cleanup:
+		case tx_done:
+		case rx_cleanup:
 			usb_free_urb (entry->urb);
 			dev_kfree_skb (skb);
 			continue;
-		    default:
+		default:
 			devdbg (dev, "bogus skb state %d", entry->state);
 		}
 	}
@@ -1208,7 +1213,7 @@
 			status = 0;
 
 	}
-	if (status == 0 && dev->status)
+	if (status >= 0 && dev->status)
 		status = init_status (dev, udev);
 	if (status < 0)
 		goto out3;
@@ -1252,20 +1257,23 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* FIXME these suspend/resume methods assume non-CDC style
- * devices, with only one interface.
+/*
+ * suspend the whole driver as soon as the first interface is suspended
+ * resume only when the last interface is resumed
  */
 
 int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
 {
 	struct usbnet		*dev = usb_get_intfdata(intf);
 
-	/* accelerate emptying of the rx and queues, to avoid
-	 * having everything error out.
-	 */
-	netif_device_detach (dev->net);
-	(void) unlink_urbs (dev, &dev->rxq);
-	(void) unlink_urbs (dev, &dev->txq);
+	if (!dev->suspend_count++) {
+		/* accelerate emptying of the rx and queues, to avoid
+		 * having everything error out.
+		 */
+		netif_device_detach (dev->net);
+		(void) unlink_urbs (dev, &dev->rxq);
+		(void) unlink_urbs (dev, &dev->txq);
+	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_suspend);
@@ -1274,8 +1282,10 @@
 {
 	struct usbnet		*dev = usb_get_intfdata(intf);
 
-	netif_device_attach (dev->net);
-	tasklet_schedule (&dev->bh);
+	if (!--dev->suspend_count) {
+		netif_device_attach (dev->net);
+		tasklet_schedule (&dev->bh);
+	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_resume);
diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h
index 82db5a8..a6c5820 100644
--- a/drivers/net/usb/usbnet.h
+++ b/drivers/net/usb/usbnet.h
@@ -32,6 +32,7 @@
 	const char		*driver_name;
 	wait_queue_head_t	*wait;
 	struct mutex		phy_mutex;
+	unsigned char		suspend_count;
 
 	/* i/o info: pipes etc */
 	unsigned		in, out;
@@ -46,7 +47,7 @@
 	unsigned long		data [5];
 	u32			xid;
 	u32			hard_mtu;	/* count any extra framing */
-	size_t		        rx_urb_size;    /* size for rx urbs  */
+	size_t			rx_urb_size;	/* size for rx urbs */
 	struct mii_if_info	mii;
 
 	/* various kinds of pending driver work */
@@ -84,7 +85,7 @@
 #define FLAG_NO_SETINT	0x0010		/* device can't set_interface() */
 #define FLAG_ETHER	0x0020		/* maybe use "eth%d" names */
 
-#define FLAG_FRAMING_AX 0x0040          /* AX88772/178 packets */
+#define FLAG_FRAMING_AX 0x0040		/* AX88772/178 packets */
 
 	/* init device ... can sleep, or cause probe() failure */
 	int	(*bind)(struct usbnet *, struct usb_interface *);
@@ -145,9 +146,9 @@
 
 /* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
 #define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
- 			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
- 			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
- 			|USB_CDC_PACKET_TYPE_DIRECTED)
+			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
+			|USB_CDC_PACKET_TYPE_DIRECTED)
 
 
 /* we record the state for each of our queued skbs */
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index adea290a9..f51c2c1 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -622,7 +622,6 @@
 	struct net_device *dev;
 	struct rhine_private *rp;
 	int i, rc;
-	u8 pci_rev;
 	u32 quirks;
 	long pioaddr;
 	long memaddr;
@@ -642,27 +641,25 @@
 		printk(version);
 #endif
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
 	io_size = 256;
 	phy_id = 0;
 	quirks = 0;
 	name = "Rhine";
-	if (pci_rev < VTunknown0) {
+	if (pdev->revision < VTunknown0) {
 		quirks = rqRhineI;
 		io_size = 128;
 	}
-	else if (pci_rev >= VT6102) {
+	else if (pdev->revision >= VT6102) {
 		quirks = rqWOL | rqForceReset;
-		if (pci_rev < VT6105) {
+		if (pdev->revision < VT6105) {
 			name = "Rhine II";
 			quirks |= rqStatusWBRace;	/* Rhine-II exclusive */
 		}
 		else {
 			phy_id = 1;	/* Integrated PHY, phy_id fixed to 1 */
-			if (pci_rev >= VT6105_B0)
+			if (pdev->revision >= VT6105_B0)
 				quirks |= rq6patterns;
-			if (pci_rev < VT6105M)
+			if (pdev->revision < VT6105M)
 				name = "Rhine III";
 			else
 				name = "Rhine III (Management Adapter)";
@@ -1492,9 +1489,9 @@
 							    rp->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
 
-				eth_copy_and_sum(skb,
+				skb_copy_to_linear_data(skb,
 						 rp->rx_skbuff[entry]->data,
-						 pkt_len, 0);
+						 pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(rp->pdev,
 							       rp->rx_skbuff_dma[entry],
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 25b75b6..f331843 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -890,8 +890,7 @@
 
 static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
 {
-	if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0)
-		return -EIO;
+	vptr->rev_id = pdev->revision;
 
 	pci_set_master(pdev);
 
@@ -1562,7 +1561,7 @@
 	if (vptr->mii_status & VELOCITY_LINK_FAIL) {
 		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
 	} else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
-		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link autonegation", vptr->dev->name);
+		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name);
 
 		if (vptr->mii_status & VELOCITY_SPEED_1000)
 			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 4fc8681..a3df09e 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -61,7 +61,7 @@
 #
 config LANMEDIA
 	tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards"
-	depends on PCI
+	depends on PCI && VIRT_TO_BUS
 	---help---
 	  Driver for the following Lan Media family of serial boards:
 
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 999bf71..5d8c78e 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -2833,6 +2833,8 @@
 	int br, tc;
 	int br_pwr, error;
 
+	*br_io = 0;
+
 	if (rate == 0)
 		return (0);
 
@@ -3439,7 +3441,6 @@
 cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int first_time = 1;
-	ucchar cpc_rev_id;
 	int err, eeprom_outdated = 0;
 	ucshort device_id;
 	pc300_t *card;
@@ -3480,7 +3481,6 @@
 	card->hw.falcsize = pci_resource_len(pdev, 4);
 	card->hw.plxphys = pci_resource_start(pdev, 5);
 	card->hw.plxsize = pci_resource_len(pdev, 5);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &cpc_rev_id);
 
 	switch (device_id) {
 		case PCI_DEVICE_ID_PC300_RX_1:
@@ -3498,7 +3498,7 @@
 	}
 #ifdef PC300_DEBUG_PCI
 	printk("cpc (bus=0x0%x,pci_id=0x%x,", pdev->bus->number, pdev->devfn);
-	printk("rev_id=%d) IRQ%d\n", cpc_rev_id, card->hw.irq);
+	printk("rev_id=%d) IRQ%d\n", pdev->revision, card->hw.irq);
 	printk("cpc:found  ramaddr=0x%08lx plxaddr=0x%08lx "
 	       "ctladdr=0x%08lx falcaddr=0x%08lx\n",
 	       card->hw.ramphys, card->hw.plxphys, card->hw.scaphys,
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index aff05db..dfbd3b0 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -311,7 +311,6 @@
 					const struct pci_device_id *ent)
 {
 	card_t *card;
-	u8 rev_id;
 	u32 __iomem *p;
 	int i;
 	u32 ramsize;
@@ -366,7 +365,6 @@
 			return -ENOMEM;
 		}
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
 	if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE ||
 	    pci_resource_len(pdev, 2) != PC300_SCA_SIZE ||
 	    pci_resource_len(pdev, 3) < 16384) {
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index ca06a00..7f720de 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -289,7 +289,6 @@
 					 const struct pci_device_id *ent)
 {
 	card_t *card;
-	u8 rev_id;
 	u32 __iomem *p;
 	int i;
 	u32 ramsize;
@@ -330,7 +329,6 @@
 		return -ENOMEM;
 	}
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
 	if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
 	    pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE ||
 	    pci_resource_len(pdev, 3) < 16384) {
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 35eded7..1cc18e7 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -595,8 +595,8 @@
 
 	u32  crc = CRC32_INITIAL;
 
-	unsigned  framelen, frameno, ack;
-	unsigned  is_first, frame_ok;
+	unsigned  framelen = 0, frameno, ack;
+	unsigned  is_first, frame_ok = 0;
 
 	if( check_fhdr( ioaddr, &framelen, &frameno, &ack, &is_first, &crc ) ) {
 		frame_ok = framelen > 4
@@ -604,8 +604,7 @@
 			:  skip_tail( ioaddr, framelen, crc );
 		if( frame_ok )
 			interpret_ack( dev, ack );
-	} else
-		frame_ok = 0;
+	}
 
 	outb( inb( ioaddr + CSR0 ) ^ CT_ZER, ioaddr + CSR0 );
 	if( frame_ok ) {
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index e3f5bb0..ae27af0 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -266,16 +266,23 @@
 
 	  If you are not sure, say N here.
 
-config LIBERTAS_USB
-	tristate "Marvell Libertas 8388 802.11a/b/g cards"
-	depends on USB && WLAN_80211
+config LIBERTAS
+	tristate "Marvell 8xxx Libertas WLAN driver support"
+	depends on WLAN_80211
+	select IEEE80211
 	select FW_LOADER
 	---help---
+	  A library for Marvell Libertas 8xxx devices.
+
+config LIBERTAS_USB
+	tristate "Marvell Libertas 8388 USB 802.11b/g cards"
+	depends on LIBERTAS && USB
+	---help---
 	  A driver for Marvell Libertas 8388 USB devices.
 
-config LIBERTAS_USB_DEBUG
-	bool "Enable full debugging output in the Libertas USB module."
-	depends on LIBERTAS_USB
+config LIBERTAS_DEBUG
+	bool "Enable full debugging output in the Libertas module."
+	depends on LIBERTAS
 	---help---
 	  Debugging support.
 
@@ -539,6 +546,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called zd1201.
 
+config RTL8187
+	tristate "Realtek 8187 USB support"
+	depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
+	select EEPROM_93CX6
+	---help---
+	  This is a driver for RTL8187 based cards.
+	  These are USB based chips found in cards such as:
+
+	  Netgear WG111v2
+
+	  Thanks to Realtek for their support!
+
 source "drivers/net/wireless/hostap/Kconfig"
 source "drivers/net/wireless/bcm43xx/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index d212460..ef35bc6 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -44,3 +44,6 @@
 
 obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
 obj-$(CONFIG_LIBERTAS_USB)     += libertas/
+
+rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o
+obj-$(CONFIG_RTL8187)	+= rtl8187.o
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 2d3a180..ee1cc14 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -52,6 +52,8 @@
 
 #include "airo.h"
 
+#define DRV_NAME "airo"
+
 #ifdef CONFIG_PCI
 static struct pci_device_id card_ids[] = {
 	{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
@@ -71,7 +73,7 @@
 static int airo_pci_resume(struct pci_dev *pdev);
 
 static struct pci_driver airo_driver = {
-	.name     = "airo",
+	.name     = DRV_NAME,
 	.id_table = card_ids,
 	.probe    = airo_pci_probe,
 	.remove   = __devexit_p(airo_pci_remove),
@@ -1092,7 +1094,7 @@
 static void OUT4500( struct airo_info *, u16 register, u16 value );
 static unsigned short IN4500( struct airo_info *, u16 register );
 static u16 setup_card(struct airo_info*, u8 *mac, int lock);
-static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock );
+static int enable_MAC(struct airo_info *ai, int lock);
 static void disable_MAC(struct airo_info *ai, int lock);
 static void enable_interrupts(struct airo_info*);
 static void disable_interrupts(struct airo_info*);
@@ -1250,7 +1252,7 @@
 static int flashrestart(struct airo_info *ai,struct net_device *dev);
 
 #define airo_print(type, name, fmt, args...) \
-	{ printk(type "airo(%s): " fmt "\n", name, ##args); }
+	printk(type DRV_NAME "(%s): " fmt "\n", name, ##args)
 
 #define airo_print_info(name, fmt, args...) \
 	airo_print(KERN_INFO, name, fmt, ##args)
@@ -1926,28 +1928,54 @@
 	return rc;
 }
 
-static int airo_open(struct net_device *dev) {
-	struct airo_info *info = dev->priv;
-	Resp rsp;
+static void try_auto_wep(struct airo_info *ai)
+{
+	if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
+		ai->expires = RUN_AT(3*HZ);
+		wake_up_interruptible(&ai->thr_wait);
+	}
+}
 
-	if (test_bit(FLAG_FLASHING, &info->flags))
+static int airo_open(struct net_device *dev) {
+	struct airo_info *ai = dev->priv;
+	int rc = 0;
+
+	if (test_bit(FLAG_FLASHING, &ai->flags))
 		return -EIO;
 
 	/* Make sure the card is configured.
 	 * Wireless Extensions may postpone config changes until the card
 	 * is open (to pipeline changes and speed-up card setup). If
 	 * those changes are not yet commited, do it now - Jean II */
-	if (test_bit (FLAG_COMMIT, &info->flags)) {
-		disable_MAC(info, 1);
-		writeConfigRid(info, 1);
+	if (test_bit(FLAG_COMMIT, &ai->flags)) {
+		disable_MAC(ai, 1);
+		writeConfigRid(ai, 1);
 	}
 
-	if (info->wifidev != dev) {
+	if (ai->wifidev != dev) {
+		clear_bit(JOB_DIE, &ai->jobs);
+		ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
+		if (IS_ERR(ai->airo_thread_task))
+			return (int)PTR_ERR(ai->airo_thread_task);
+
+		rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED,
+			dev->name, dev);
+		if (rc) {
+			airo_print_err(dev->name,
+				"register interrupt %d failed, rc %d",
+				dev->irq, rc);
+			set_bit(JOB_DIE, &ai->jobs);
+			kthread_stop(ai->airo_thread_task);
+			return rc;
+		}
+
 		/* Power on the MAC controller (which may have been disabled) */
-		clear_bit(FLAG_RADIO_DOWN, &info->flags);
-		enable_interrupts(info);
+		clear_bit(FLAG_RADIO_DOWN, &ai->flags);
+		enable_interrupts(ai);
+
+		try_auto_wep(ai);
 	}
-	enable_MAC(info, &rsp, 1);
+	enable_MAC(ai, 1);
 
 	netif_start_queue(dev);
 	return 0;
@@ -2338,14 +2366,13 @@
 {
 	struct airo_info *ai = dev->priv;
 	struct sockaddr *addr = p;
-	Resp rsp;
 
 	readConfigRid(ai, 1);
 	memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len);
 	set_bit (FLAG_COMMIT, &ai->flags);
 	disable_MAC(ai, 1);
 	writeConfigRid (ai, 1);
-	enable_MAC(ai, &rsp, 1);
+	enable_MAC(ai, 1);
 	memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);
 	if (ai->wifidev)
 		memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);
@@ -2392,6 +2419,11 @@
 		disable_MAC(ai, 1);
 #endif
 		disable_interrupts( ai );
+
+		free_irq(dev->irq, dev);
+
+		set_bit(JOB_DIE, &ai->jobs);
+		kthread_stop(ai->airo_thread_task);
 	}
 	return 0;
 }
@@ -2403,7 +2435,6 @@
 	set_bit(FLAG_RADIO_DOWN, &ai->flags);
 	disable_MAC(ai, 1);
 	disable_interrupts(ai);
-	free_irq( dev->irq, dev );
 	takedown_proc_entry( dev, ai );
 	if (test_bit(FLAG_REGISTERED, &ai->flags)) {
 		unregister_netdev( dev );
@@ -2414,9 +2445,6 @@
 		}
 		clear_bit(FLAG_REGISTERED, &ai->flags);
 	}
-	set_bit(JOB_DIE, &ai->jobs);
-	kthread_stop(ai->airo_thread_task);
-
 	/*
 	 * Clean out tx queue
 	 */
@@ -2554,8 +2582,7 @@
  * 2) Map PCI memory for issueing commands.
  * 3) Allocate memory (shared) to send and receive ethernet frames.
  */
-static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
-		    const char *name)
+static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
 {
 	unsigned long mem_start, mem_len, aux_start, aux_len;
 	int rc = -1;
@@ -2569,35 +2596,35 @@
 	aux_start = pci_resource_start(pci, 2);
 	aux_len = AUXMEMSIZE;
 
-	if (!request_mem_region(mem_start, mem_len, name)) {
-		airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
-		       (int)mem_start, (int)mem_len, name);
+	if (!request_mem_region(mem_start, mem_len, DRV_NAME)) {
+		airo_print_err("", "Couldn't get region %x[%x]",
+			(int)mem_start, (int)mem_len);
 		goto out;
 	}
-	if (!request_mem_region(aux_start, aux_len, name)) {
-		airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
-		       (int)aux_start, (int)aux_len, name);
+	if (!request_mem_region(aux_start, aux_len, DRV_NAME)) {
+		airo_print_err("", "Couldn't get region %x[%x]",
+			(int)aux_start, (int)aux_len);
 		goto free_region1;
 	}
 
 	ai->pcimem = ioremap(mem_start, mem_len);
 	if (!ai->pcimem) {
-		airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
-		       (int)mem_start, (int)mem_len, name);
+		airo_print_err("", "Couldn't map region %x[%x]",
+			(int)mem_start, (int)mem_len);
 		goto free_region2;
 	}
 	ai->pciaux = ioremap(aux_start, aux_len);
 	if (!ai->pciaux) {
-		airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
-		       (int)aux_start, (int)aux_len, name);
+		airo_print_err("", "Couldn't map region %x[%x]",
+			(int)aux_start, (int)aux_len);
 		goto free_memmap;
 	}
 
 	/* Reserve PKTSIZE for each fid and 2K for the Rids */
 	ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
 	if (!ai->shared) {
-		airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d",
-		       PCI_SHARED_LEN);
+		airo_print_err("", "Couldn't alloc_consistent %d",
+			PCI_SHARED_LEN);
 		goto free_auxmap;
 	}
 
@@ -2742,7 +2769,7 @@
 	    kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
 		    GFP_KERNEL);
 	if (!ai->networks) {
-		airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
+		airo_print_warn("", "Out of memory allocating beacons");
 		return -ENOMEM;
 	}
 
@@ -2770,7 +2797,6 @@
 {
 	int status;
 	CapabilityRid cap_rid;
-	const char *name = ai->dev->name;
 
 	status = readCapabilityRid(ai, &cap_rid, 1);
 	if (status != SUCCESS) return 0;
@@ -2778,12 +2804,12 @@
 	/* Only firmware versions 5.30.17 or better can do WPA */
 	if ((cap_rid.softVer > 0x530)
 	  || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
-		airo_print_info(name, "WPA is supported.");
+		airo_print_info("", "WPA is supported.");
 		return 1;
 	}
 
 	/* No WPA support */
-	airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17"
+	airo_print_info("", "WPA unsupported (only firmware versions 5.30.17"
 		" and greater support WPA.  Detected %s)", cap_rid.prodVer);
 	return 0;
 }
@@ -2797,23 +2823,19 @@
 	int i, rc;
 
 	/* Create the network device object. */
-        dev = alloc_etherdev(sizeof(*ai));
-        if (!dev) {
+	dev = alloc_netdev(sizeof(*ai), "", ether_setup);
+	if (!dev) {
 		airo_print_err("", "Couldn't alloc_etherdev");
 		return NULL;
-        }
-	if (dev_alloc_name(dev, dev->name) < 0) {
-		airo_print_err("", "Couldn't get name!");
-		goto err_out_free;
 	}
 
 	ai = dev->priv;
 	ai->wifidev = NULL;
-	ai->flags = 0;
+	ai->flags = 1 << FLAG_RADIO_DOWN;
 	ai->jobs = 0;
 	ai->dev = dev;
 	if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
-		airo_print_dbg(dev->name, "Found an MPI350 card");
+		airo_print_dbg("", "Found an MPI350 card");
 		set_bit(FLAG_MPI, &ai->flags);
 	}
 	spin_lock_init(&ai->aux_lock);
@@ -2821,14 +2843,11 @@
 	ai->config.len = 0;
 	ai->pci = pci;
 	init_waitqueue_head (&ai->thr_wait);
-	ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
-	if (IS_ERR(ai->airo_thread_task))
-		goto err_out_free;
 	ai->tfm = NULL;
 	add_airo_dev(ai);
 
 	if (airo_networks_allocate (ai))
-		goto err_out_thr;
+		goto err_out_free;
 	airo_networks_initialize (ai);
 
 	/* The Airo-specific entries in the device structure. */
@@ -2851,27 +2870,22 @@
 	dev->base_addr = port;
 
 	SET_NETDEV_DEV(dev, dmdev);
+	SET_MODULE_OWNER(dev);
 
 	reset_card (dev, 1);
 	msleep(400);
 
-	rc = request_irq( dev->irq, airo_interrupt, IRQF_SHARED, dev->name, dev );
-	if (rc) {
-		airo_print_err(dev->name, "register interrupt %d failed, rc %d",
-				irq, rc);
-		goto err_out_nets;
-	}
 	if (!is_pcmcia) {
-		if (!request_region( dev->base_addr, 64, dev->name )) {
+		if (!request_region(dev->base_addr, 64, DRV_NAME)) {
 			rc = -EBUSY;
 			airo_print_err(dev->name, "Couldn't request region");
-			goto err_out_irq;
+			goto err_out_nets;
 		}
 	}
 
 	if (test_bit(FLAG_MPI,&ai->flags)) {
-		if (mpi_map_card(ai, pci, dev->name)) {
-			airo_print_err(dev->name, "Could not map memory");
+		if (mpi_map_card(ai, pci)) {
+			airo_print_err("", "Could not map memory");
 			goto err_out_res;
 		}
 	}
@@ -2899,6 +2913,7 @@
 		ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
 	}
 
+	strcpy(dev->name, "eth%d");
 	rc = register_netdev(dev);
 	if (rc) {
 		airo_print_err(dev->name, "Couldn't register_netdev");
@@ -2921,8 +2936,6 @@
 	if (setup_proc_entry(dev, dev->priv) < 0)
 		goto err_out_wifi;
 
-	netif_start_queue(dev);
-	SET_MODULE_OWNER(dev);
 	return dev;
 
 err_out_wifi:
@@ -2940,14 +2953,9 @@
 err_out_res:
 	if (!is_pcmcia)
 	        release_region( dev->base_addr, 64 );
-err_out_irq:
-	free_irq(dev->irq, dev);
 err_out_nets:
 	airo_networks_free(ai);
-err_out_thr:
 	del_airo_dev(ai);
-	set_bit(JOB_DIE, &ai->jobs);
-	kthread_stop(ai->airo_thread_task);
 err_out_free:
 	free_netdev(dev);
 	return NULL;
@@ -3078,7 +3086,8 @@
 	struct net_device *dev = data;
 	struct airo_info *ai = dev->priv;
 	int locked;
-	
+
+	set_freezable();
 	while(1) {
 		/* make swsusp happy with our thread */
 		try_to_freeze();
@@ -3529,9 +3538,11 @@
 	return rc;
 }
 
-static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
+static int enable_MAC(struct airo_info *ai, int lock)
+{
 	int rc;
-        Cmd cmd;
+	Cmd cmd;
+	Resp rsp;
 
 	/* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions
 	 * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down"
@@ -3547,7 +3558,7 @@
 	if (!test_bit(FLAG_ENABLED, &ai->flags)) {
 		memset(&cmd, 0, sizeof(cmd));
 		cmd.cmd = MAC_ENABLE;
-		rc = issuecommand(ai, &cmd, rsp);
+		rc = issuecommand(ai, &cmd, &rsp);
 		if (rc == SUCCESS)
 			set_bit(FLAG_ENABLED, &ai->flags);
 	} else
@@ -3557,8 +3568,12 @@
 	    up(&ai->sem);
 
 	if (rc)
-		airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d",
-			__FUNCTION__, rc);
+		airo_print_err(ai->dev->name, "Cannot enable MAC");
+	else if ((rsp.status & 0xFF00) != 0) {
+		airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, "
+			"rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2);
+		rc = ERROR;
+	}
 	return rc;
 }
 
@@ -3902,12 +3917,9 @@
 		if ( status != SUCCESS ) return ERROR;
 	}
 
-	status = enable_MAC(ai, &rsp, lock);
-	if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
-		airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x,"
-			" offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
+	status = enable_MAC(ai, lock);
+	if (status != SUCCESS)
 		return ERROR;
-	}
 
 	/* Grab the initial wep key, we gotta save it for auto_wep */
 	rc = readWepKeyRid(ai, &wkr, 1, lock);
@@ -3919,10 +3931,7 @@
 		rc = readWepKeyRid(ai, &wkr, 0, lock);
 	} while(lastindex != wkr.kindex);
 
-	if (auto_wep) {
-		ai->expires = RUN_AT(3*HZ);
-		wake_up_interruptible(&ai->thr_wait);
-	}
+	try_auto_wep(ai);
 
 	return SUCCESS;
 }
@@ -4004,7 +4013,7 @@
 		}
 		if ( !(max_tries--) ) {
 			airo_print_err(ai->dev->name,
-				"airo: BAP setup error too many retries\n");
+				"BAP setup error too many retries\n");
 			return ERROR;
 		}
 		// -- PC4500 missed it, try again
@@ -5152,7 +5161,6 @@
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = dev->priv;
 	SsidRid SSID_rid;
-	Resp rsp;
 	int i;
 	int offset = 0;
 
@@ -5177,7 +5185,7 @@
 		SSID_rid.len = sizeof(SSID_rid);
 	disable_MAC(ai, 1);
 	writeSsidRid(ai, &SSID_rid, 1);
-	enable_MAC(ai, &rsp, 1);
+	enable_MAC(ai, 1);
 }
 
 static inline u8 hexVal(char c) {
@@ -5193,7 +5201,6 @@
 	struct net_device *dev = dp->data;
 	struct airo_info *ai = dev->priv;
 	APListRid APList_rid;
-	Resp rsp;
 	int i;
 
 	if ( !data->writelen ) return;
@@ -5218,18 +5225,17 @@
 	}
 	disable_MAC(ai, 1);
 	writeAPListRid(ai, &APList_rid, 1);
-	enable_MAC(ai, &rsp, 1);
+	enable_MAC(ai, 1);
 }
 
 /* This function wraps PC4500_writerid with a MAC disable */
 static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
 			int len, int dummy ) {
 	int rc;
-	Resp rsp;
 
 	disable_MAC(ai, 1);
 	rc = PC4500_writerid(ai, rid, rid_data, len, 1);
-	enable_MAC(ai, &rsp, 1);
+	enable_MAC(ai, 1);
 	return rc;
 }
 
@@ -5260,7 +5266,6 @@
 		       const char *key, u16 keylen, int perm, int lock ) {
 	static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
 	WepKeyRid wkr;
-	Resp rsp;
 
 	memset(&wkr, 0, sizeof(wkr));
 	if (keylen == 0) {
@@ -5280,7 +5285,7 @@
 
 	if (perm) disable_MAC(ai, lock);
 	writeWepKeyRid(ai, &wkr, perm, lock);
-	if (perm) enable_MAC(ai, &rsp, lock);
+	if (perm) enable_MAC(ai, lock);
 	return 0;
 }
 
@@ -5548,7 +5553,6 @@
    changed. */
 static void timer_func( struct net_device *dev ) {
 	struct airo_info *apriv = dev->priv;
-	Resp rsp;
 
 /* We don't have a link so try changing the authtype */
 	readConfigRid(apriv, 0);
@@ -5575,7 +5579,7 @@
 	}
 	set_bit (FLAG_COMMIT, &apriv->flags);
 	writeConfigRid(apriv, 0);
-	enable_MAC(apriv, &rsp, 0);
+	enable_MAC(apriv, 0);
 	up(&apriv->sem);
 
 /* Schedule check to see if the change worked */
@@ -5597,8 +5601,10 @@
 			dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
 	else
 			dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
-	if (!dev)
+	if (!dev) {
+		pci_disable_device(pdev);
 		return -ENODEV;
+	}
 
 	pci_set_drvdata(pdev, dev);
 	return 0;
@@ -5610,6 +5616,8 @@
 
 	airo_print_info(dev->name, "Unregistering...");
 	stop_airo_card(dev, 1);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
 }
 
 static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -5646,7 +5654,6 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct airo_info *ai = dev->priv;
-	Resp rsp;
 	pci_power_t prev_state = pdev->current_state;
 
 	pci_set_power_state(pdev, PCI_D0);
@@ -5679,7 +5686,7 @@
 		ai->APList = NULL;
 	}
 	writeConfigRid(ai, 0);
-	enable_MAC(ai, &rsp, 0);
+	enable_MAC(ai, 0);
 	ai->power = PMSG_ON;
 	netif_device_attach(dev);
 	netif_wake_queue(dev);
@@ -5903,7 +5910,6 @@
 			  char *extra)
 {
 	struct airo_info *local = dev->priv;
-	Resp rsp;
 	SsidRid SSID_rid;		/* SSIDs */
 
 	/* Reload the list of current SSID */
@@ -5935,7 +5941,7 @@
 	/* Write it to the card */
 	disable_MAC(local, 1);
 	writeSsidRid(local, &SSID_rid, 1);
-	enable_MAC(local, &rsp, 1);
+	enable_MAC(local, 1);
 
 	return 0;
 }
@@ -6000,7 +6006,7 @@
 		memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
 		disable_MAC(local, 1);
 		writeAPListRid(local, &APList_rid, 1);
-		enable_MAC(local, &rsp, 1);
+		enable_MAC(local, 1);
 	}
 	return 0;
 }
@@ -7454,7 +7460,6 @@
 			      char *extra)			/* NULL */
 {
 	struct airo_info *local = dev->priv;
-	Resp rsp;
 
 	if (!test_bit (FLAG_COMMIT, &local->flags))
 		return 0;
@@ -7479,7 +7484,7 @@
 	if (down_interruptible(&local->sem))
 		return -ERESTARTSYS;
 	writeConfigRid(local, 0);
-	enable_MAC(local, &rsp, 0);
+	enable_MAC(local, 0);
 	if (test_bit (FLAG_RESET, &local->flags))
 		airo_set_promisc(local);
 	else
@@ -7746,7 +7751,6 @@
 	unsigned char *iobuf;
 	int len;
 	struct airo_info *ai = dev->priv;
-	Resp rsp;
 
 	if (test_bit(FLAG_FLASHING, &ai->flags))
 		return -EIO;
@@ -7758,7 +7762,7 @@
 		if (test_bit(FLAG_COMMIT, &ai->flags)) {
 			disable_MAC (ai, 1);
 			writeConfigRid (ai, 1);
-			enable_MAC (ai, &rsp, 1);
+			enable_MAC(ai, 1);
 		}
 		break;
 	case AIROGSLIST:    ridcode = RID_SSID;         break;
@@ -7815,7 +7819,6 @@
 	struct airo_info *ai = dev->priv;
 	int  ridcode;
         int  enabled;
-	Resp      rsp;
 	static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
 	unsigned char *iobuf;
 
@@ -7849,7 +7852,7 @@
 		 * same with MAC off
 		 */
 	case AIROPMACON:
-		if (enable_MAC(ai, &rsp, 1) != 0)
+		if (enable_MAC(ai, 1) != 0)
 			return -EIO;
 		return 0;
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index ef6b253..c5d6753 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -3741,10 +3741,8 @@
 	                          &bcm->board_type);
 	if (err)
 		goto err_iounmap;
-	err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
-	                          &bcm->board_revision);
-	if (err)
-		goto err_iounmap;
+
+	bcm->board_revision = bcm->pci_dev->revision;
 
 	err = bcm43xx_chipset_attach(bcm);
 	if (err)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b37f1e3..d779199 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1638,7 +1638,7 @@
 		return;
 	}
 
-	if (phy->analog > 1) {
+	if (phy->analog == 1) {
 		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
 		value |= (baseband_attenuation << 2) & 0x003C;
 	} else {
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 246fac0..3df3c60 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -311,7 +311,7 @@
 	local_info_t *local;
 	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
-	int hdr_len, res;
+	int prefix_len, postfix_len, hdr_len, res;
 
 	iface = netdev_priv(skb->dev);
 	local = iface->local;
@@ -337,10 +337,13 @@
 	if (skb == NULL)
 		return NULL;
 
-	if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
-	     skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
-	    pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
-			     crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
+	prefix_len = crypt->ops->extra_mpdu_prefix_len +
+		crypt->ops->extra_msdu_prefix_len;
+	postfix_len = crypt->ops->extra_mpdu_postfix_len +
+		crypt->ops->extra_msdu_postfix_len;
+	if ((skb_headroom(skb) < prefix_len ||
+	     skb_tailroom(skb) < postfix_len) &&
+	    pskb_expand_head(skb, prefix_len, postfix_len, GFP_ATOMIC)) {
 		kfree_skb(skb);
 		return NULL;
 	}
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 5b3abd5..9090052 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -326,7 +326,6 @@
 	char *p = page;
 	struct ap_data *ap = (struct ap_data *) data;
 	char *policy_txt;
-	struct list_head *ptr;
 	struct mac_entry *entry;
 
 	if (off != 0) {
@@ -352,14 +351,12 @@
 	p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
 	p += sprintf(p, "MAC list:\n");
 	spin_lock_bh(&ap->mac_restrictions.lock);
-	for (ptr = ap->mac_restrictions.mac_list.next;
-	     ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
+	list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
 		if (p - page > PAGE_SIZE - 80) {
 			p += sprintf(p, "All entries did not fit one page.\n");
 			break;
 		}
 
-		entry = list_entry(ptr, struct mac_entry, list);
 		p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
 	}
 	spin_unlock_bh(&ap->mac_restrictions.lock);
@@ -413,7 +410,6 @@
 static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
 			       u8 *mac)
 {
-	struct list_head *ptr;
 	struct mac_entry *entry;
 	int found = 0;
 
@@ -421,10 +417,7 @@
 		return 0;
 
 	spin_lock_bh(&mac_restrictions->lock);
-	for (ptr = mac_restrictions->mac_list.next;
-	     ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, list);
-
+	list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
 		if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
 			found = 1;
 			break;
@@ -519,7 +512,7 @@
 {
 	char *p = page;
 	struct ap_data *ap = (struct ap_data *) data;
-	struct list_head *ptr;
+	struct sta_info *sta;
 	int i;
 
 	if (off > PROC_LIMIT) {
@@ -529,9 +522,7 @@
 
 	p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
 	spin_lock_bh(&ap->sta_table_lock);
-	for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
-		struct sta_info *sta = (struct sta_info *) ptr;
-
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		if (!sta->ap)
 			continue;
 
@@ -861,7 +852,7 @@
 
 void hostap_free_data(struct ap_data *ap)
 {
-	struct list_head *n, *ptr;
+	struct sta_info *n, *sta;
 
 	if (ap == NULL || !ap->initialized) {
 		printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
@@ -875,8 +866,7 @@
 	ap->crypt = ap->crypt_priv = NULL;
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
-	list_for_each_safe(ptr, n, &ap->sta_list) {
-		struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+	list_for_each_entry_safe(sta, n, &ap->sta_list, list) {
 		ap_sta_hash_del(ap, sta);
 		list_del(&sta->list);
 		if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
@@ -2704,6 +2694,8 @@
 
 	if (hdr->addr1[0] & 0x01) {
 		/* broadcast/multicast frame - no AP related processing */
+		if (local->ap->num_sta <= 0)
+			ret = AP_TX_DROP;
 		goto out;
 	}
 
@@ -3198,15 +3190,14 @@
 
 void hostap_update_rates(local_info_t *local)
 {
-	struct list_head *ptr;
+	struct sta_info *sta;
 	struct ap_data *ap = local->ap;
 
 	if (!ap)
 		return;
 
 	spin_lock_bh(&ap->sta_table_lock);
-	for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
-		struct sta_info *sta = (struct sta_info *) ptr;
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		prism2_check_tx_rates(sta);
 	}
 	spin_unlock_bh(&ap->sta_table_lock);
@@ -3242,11 +3233,10 @@
 void hostap_add_wds_links(local_info_t *local)
 {
 	struct ap_data *ap = local->ap;
-	struct list_head *ptr;
+	struct sta_info *sta;
 
 	spin_lock_bh(&ap->sta_table_lock);
-	list_for_each(ptr, &ap->sta_list) {
-		struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		if (sta->ap)
 			hostap_wds_link_oper(local, sta->addr, WDS_ADD);
 	}
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index c090a5a..30acd39 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -1,8 +1,6 @@
 #ifndef HOSTAP_CONFIG_H
 #define HOSTAP_CONFIG_H
 
-#define PRISM2_VERSION "0.4.4-kernel"
-
 /* In the previous versions of Host AP driver, support for user space version
  * of IEEE 802.11 management (hostapd) used to be disabled in the default
  * configuration. From now on, support for hostapd is always included and it is
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ee1532b..30e723f 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -22,7 +22,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static dev_info_t dev_info = "hostap_cs";
 
 MODULE_AUTHOR("Jouni Malinen");
@@ -30,7 +29,6 @@
 		   "cards (PC Card).");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 static int ignore_cis_vcc;
@@ -910,14 +908,12 @@
 
 static int __init init_prism2_pccard(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
 	return pcmcia_register_driver(&hostap_driver);
 }
 
 static void __exit exit_prism2_pccard(void)
 {
 	pcmcia_unregister_driver(&hostap_driver);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index cdea7f7..8c71077 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3893,8 +3893,6 @@
 	local = iface->local;
 
 	strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
-	strncpy(info->version, PRISM2_VERSION,
-		sizeof(info->version) - 1);
 	snprintf(info->fw_version, sizeof(info->fw_version) - 1,
 		 "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
 		 (local->sta_fw_ver >> 8) & 0xff,
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 4743426..446de51 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -37,7 +37,6 @@
 MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("Host AP common routines");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 #define TX_TIMEOUT (2 * HZ)
 
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index db4899e..7da3664 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -20,7 +20,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static char *dev_info = "hostap_pci";
 
 
@@ -29,7 +28,6 @@
 		   "PCI cards.");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 /* struct local_info::hw_priv */
@@ -455,15 +453,11 @@
 	.suspend	= prism2_pci_suspend,
 	.resume		= prism2_pci_resume,
 #endif /* CONFIG_PM */
-	/* Linux 2.4.6 added save_state and enable_wake that are not used here
-	 */
 };
 
 
 static int __init init_prism2_pci(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
-
 	return pci_register_driver(&prism2_pci_drv_id);
 }
 
@@ -471,7 +465,6 @@
 static void __exit exit_prism2_pci(void)
 {
 	pci_unregister_driver(&prism2_pci_drv_id);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index f0fd5ec..040dc3e 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -23,7 +23,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static char *dev_info = "hostap_plx";
 
 
@@ -32,7 +31,6 @@
 		   "cards (PLX).");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 static int ignore_cis;
@@ -615,16 +613,11 @@
 	.id_table	= prism2_plx_id_table,
 	.probe		= prism2_plx_probe,
 	.remove		= prism2_plx_remove,
-	.suspend	= NULL,
-	.resume		= NULL,
-	.enable_wake	= NULL
 };
 
 
 static int __init init_prism2_plx(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
-
 	return pci_register_driver(&prism2_plx_drv_id);
 }
 
@@ -632,7 +625,6 @@
 static void __exit exit_prism2_plx(void)
 {
 	pci_unregister_driver(&prism2_plx_drv_id);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index d51daf8..072ede7 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -1768,7 +1768,8 @@
 
 		if (priv->stop_rf_kill) {
 			priv->stop_rf_kill = 0;
-			queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+			queue_delayed_work(priv->workqueue, &priv->rf_kill,
+					   round_jiffies(HZ));
 		}
 
 		deferred = 1;
@@ -2098,7 +2099,7 @@
 	/* Make sure the RF Kill check timer is running */
 	priv->stop_rf_kill = 0;
 	cancel_delayed_work(&priv->rf_kill);
-	queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+	queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ));
 }
 
 static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
@@ -4233,7 +4234,8 @@
 			/* Make sure the RF_KILL check timer is running */
 			priv->stop_rf_kill = 0;
 			cancel_delayed_work(&priv->rf_kill);
-			queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+			queue_delayed_work(priv->workqueue, &priv->rf_kill,
+					   round_jiffies(HZ));
 		} else
 			schedule_reset(priv);
 	}
@@ -5969,7 +5971,8 @@
 	if (rf_kill_active(priv)) {
 		IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
 		if (!priv->stop_rf_kill)
-			queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+			queue_delayed_work(priv->workqueue, &priv->rf_kill,
+					   round_jiffies(HZ));
 		goto exit_unlock;
 	}
 
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 7cb2052..aa32a97 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1751,7 +1751,7 @@
 			/* Make sure the RF_KILL check timer is running */
 			cancel_delayed_work(&priv->rf_kill);
 			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   2 * HZ);
+					   round_jiffies(2 * HZ));
 		} else
 			queue_work(priv->workqueue, &priv->up);
 	}
@@ -4690,7 +4690,8 @@
 			else if (priv->config & CFG_BACKGROUND_SCAN
 				 && priv->status & STATUS_ASSOCIATED)
 				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, HZ);
+						   &priv->request_scan,
+						   round_jiffies(HZ));
 
 			/* Send an empty event to user space.
 			 * We don't send the received data on the event because
diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c
index e0ecc4d..4cf0ff7b 100644
--- a/drivers/net/wireless/libertas/11d.c
+++ b/drivers/net/wireless/libertas/11d.c
@@ -95,7 +95,7 @@
 
 	for (i = 0; i < cfp_no; i++) {
 		if ((cfp + i)->channel == firstchan) {
-			lbs_pr_debug(1, "firstchan found\n");
+			lbs_deb_11d("firstchan found\n");
 			break;
 		}
 	}
@@ -129,12 +129,12 @@
 
 	for (i = 0; i < nr_chan; i++) {
 		if (chan == chanpwr[i].chan) {
-			lbs_pr_debug(1, "11D: Found Chan:%d\n", chan);
+			lbs_deb_11d("11D: Found Chan:%d\n", chan);
 			return 1;
 		}
 	}
 
-	lbs_pr_debug(1, "11D: Not Find Chan:%d\n", chan);
+	lbs_deb_11d("11D: Not Find Chan:%d\n", chan);
 	return 0;
 }
 
@@ -174,7 +174,7 @@
 	memcpy(domaininfo->countrycode, parsed_region_chan->countrycode,
 	       COUNTRY_CODE_LEN);
 
-	lbs_pr_debug(1, "11D:nrchan=%d\n", nr_chan);
+	lbs_deb_11d("11D:nrchan=%d\n", nr_chan);
 	lbs_dbg_hex("11D:parsed_region_chan:", (char *)parsed_region_chan,
 		sizeof(struct parsed_region_chan_11d));
 
@@ -212,7 +212,7 @@
 	}
 	domaininfo->nr_subband = nr_subband;
 
-	lbs_pr_debug(1, "nr_subband=%x\n", domaininfo->nr_subband);
+	lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
 	lbs_dbg_hex("11D:domaininfo:", (char *)domaininfo,
 		COUNTRY_CODE_LEN + 1 +
 		sizeof(struct ieeetypes_subbandset) * nr_subband);
@@ -233,13 +233,13 @@
 	struct chan_freq_power *cfp;
 
 	if (region_chan == NULL) {
-		lbs_pr_debug(1, "11D: region_chan is NULL\n");
+		lbs_deb_11d("11D: region_chan is NULL\n");
 		return;
 	}
 
 	cfp = region_chan->CFP;
 	if (cfp == NULL) {
-		lbs_pr_debug(1, "11D: cfp equal NULL \n");
+		lbs_deb_11d("11D: cfp equal NULL \n");
 		return;
 	}
 
@@ -248,19 +248,19 @@
 	memcpy(parsed_region_chan->countrycode,
 	       wlan_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
 
-	lbs_pr_debug(1, "11D: region[0x%x] band[%d]\n", parsed_region_chan->region,
+	lbs_deb_11d("11D: region[0x%x] band[%d]\n", parsed_region_chan->region,
 	       parsed_region_chan->band);
 
 	for (i = 0; i < region_chan->nrcfp; i++, cfp++) {
 		parsed_region_chan->chanpwr[i].chan = cfp->channel;
 		parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower;
-		lbs_pr_debug(1, "11D: Chan[%d] Pwr[%d]\n",
+		lbs_deb_11d("11D: Chan[%d] Pwr[%d]\n",
 		       parsed_region_chan->chanpwr[i].chan,
 		       parsed_region_chan->chanpwr[i].pwr);
 	}
 	parsed_region_chan->nr_chan = region_chan->nrcfp;
 
-	lbs_pr_debug(1, "11D: nrchan[%d]\n", parsed_region_chan->nr_chan);
+	lbs_deb_11d("11D: nrchan[%d]\n", parsed_region_chan->nr_chan);
 
 	return;
 }
@@ -277,8 +277,9 @@
 	struct chan_freq_power *cfp;
 	int cfp_no;
 	u8 idx;
+	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_11D);
 
 	cfp = libertas_get_region_cfp_table(region, band, &cfp_no);
 	if (cfp == NULL)
@@ -288,16 +289,19 @@
 		if (chan == (cfp + idx)->channel) {
 			/* If Mrvl Chip Supported? */
 			if ((cfp + idx)->unsupported) {
-				return 0;
+				ret = 0;
 			} else {
-				return 1;
+				ret = 1;
 			}
+			goto done;
 		}
 	}
 
 	/*chan is not in the region table */
-	LEAVE();
-	return 0;
+
+done:
+	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+	return ret;
 }
 
 /**
@@ -321,7 +325,7 @@
 
 	u8 j, i;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_11D);
 
 	/*validation Rules:
 	   1. valid region Code
@@ -337,15 +341,14 @@
 	if ((*(countryinfo->countrycode)) == 0
 	    || (countryinfo->len <= COUNTRY_CODE_LEN)) {
 		/* No region Info or Wrong region info: treat as No 11D info */
-		LEAVE();
-		return 0;
+		goto done;
 	}
 
 	/*Step1: check region_code */
 	parsed_region_chan->region = region =
 	    wlan_region_2_code(countryinfo->countrycode);
 
-	lbs_pr_debug(1, "regioncode=%x\n", (u8) parsed_region_chan->region);
+	lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region);
 	lbs_dbg_hex("CountryCode:", (char *)countryinfo->countrycode,
 		COUNTRY_CODE_LEN);
 
@@ -361,7 +364,7 @@
 
 		if (countryinfo->subband[j].firstchan <= lastchan) {
 			/*Step2&3. Check First Chan Num increment and no overlap */
-			lbs_pr_debug(1, "11D: Chan[%d>%d] Overlap\n",
+			lbs_deb_11d("11D: Chan[%d>%d] Overlap\n",
 			       countryinfo->subband[j].firstchan, lastchan);
 			continue;
 		}
@@ -374,7 +377,7 @@
 
 			if (!wlan_get_chan_11d(band, firstchan, i, &curchan)) {
 				/* Chan is not found in UN table */
-				lbs_pr_debug(1, "chan is not supported: %d \n", i);
+				lbs_deb_11d("chan is not supported: %d \n", i);
 				break;
 			}
 
@@ -389,7 +392,7 @@
 				idx++;
 			} else {
 				/*not supported and ignore the chan */
-				lbs_pr_debug(1,
+				lbs_deb_11d(
 				       "11D:i[%d] chan[%d] unsupported in region[%x] band[%d]\n",
 				       i, curchan, region, band);
 			}
@@ -401,11 +404,12 @@
 
 	parsed_region_chan->nr_chan = idx;
 
-	lbs_pr_debug(1, "nrchan=%x\n", parsed_region_chan->nr_chan);
+	lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan);
 	lbs_dbg_hex("11D:parsed_region_chan:", (u8 *) parsed_region_chan,
 		2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
 
-	LEAVE();
+done:
+	lbs_deb_enter(LBS_DEB_11D);
 	return 0;
 }
 
@@ -420,16 +424,16 @@
 {
 	u8 scan_type = cmd_scan_type_passive;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_11D);
 
 	if (wlan_channel_known_11d(chan, parsed_region_chan)) {
-		lbs_pr_debug(1, "11D: Found and do Active Scan\n");
+		lbs_deb_11d("11D: Found and do Active Scan\n");
 		scan_type = cmd_scan_type_active;
 	} else {
-		lbs_pr_debug(1, "11D: Not Find and do Passive Scan\n");
+		lbs_deb_11d("11D: Not Find and do Passive Scan\n");
 	}
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type);
 	return scan_type;
 
 }
@@ -456,7 +460,7 @@
 				    OID_802_11D_ENABLE,
 				    &priv->adapter->enable11d);
 	if (ret)
-		lbs_pr_debug(1, "11D: Fail to enable 11D \n");
+		lbs_deb_11d("11D: Fail to enable 11D \n");
 
 	return 0;
 }
@@ -471,7 +475,7 @@
 	int ret;
 
 	if (!priv->adapter->enable11d) {
-		lbs_pr_debug(1, "11D: dnld domain Info with 11d disabled\n");
+		lbs_deb_11d("11D: dnld domain Info with 11d disabled\n");
 		return 0;
 	}
 
@@ -479,7 +483,7 @@
 				    cmd_act_set,
 				    cmd_option_waitforrsp, 0, NULL);
 	if (ret)
-		lbs_pr_debug(1, "11D: Fail to dnld domain Info\n");
+		lbs_deb_11d("11D: Fail to dnld domain Info\n");
 
 	return ret;
 }
@@ -501,7 +505,7 @@
 
 	adapter->universal_channel[i].nrcfp =
 	    sizeof(channel_freq_power_UN_BG) / size;
-	lbs_pr_debug(1, "11D: BG-band nrcfp=%d\n",
+	lbs_deb_11d("11D: BG-band nrcfp=%d\n",
 	       adapter->universal_channel[i].nrcfp);
 
 	adapter->universal_channel[i].CFP = channel_freq_power_UN_BG;
@@ -531,9 +535,9 @@
 	wlan_adapter *adapter = priv->adapter;
 	u8 nr_subband = adapter->domainreg.nr_subband;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_11D);
 
-	lbs_pr_debug(1, "nr_subband=%x\n", nr_subband);
+	lbs_deb_11d("nr_subband=%x\n", nr_subband);
 
 	cmd->command = cpu_to_le16(cmdno);
 	pdomaininfo->action = cpu_to_le16(cmdoption);
@@ -542,8 +546,7 @@
 		    cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
 		lbs_dbg_hex("11D: 802_11D_DOMAIN_INFO:", (u8 *) cmd,
 			(int)(cmd->size));
-		LEAVE();
-		return 0;
+		goto done;
 	}
 
 	domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
@@ -567,10 +570,10 @@
 		    cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
 	}
 
-	lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, (int)(cmd->size));
+	lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, le16_to_cpu(cmd->size));
 
-	LEAVE();
-
+done:
+	lbs_deb_enter(LBS_DEB_11D);
 	return 0;
 }
 
@@ -585,17 +588,17 @@
 	int data = 0;
 	int *val;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_11D);
 	data = SUBCMD_DATA(wrq);
 
-	lbs_pr_debug(1, "enable 11D: %s\n",
+	lbs_deb_11d("enable 11D: %s\n",
 	       (data == 1) ? "enable" : "Disable");
 
 	wlan_enable_11d(priv, data);
 	val = (int *)wrq->u.name;
 	*val = priv->adapter->enable11d;
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_11D);
 	return 0;
 }
 
@@ -608,25 +611,24 @@
 int libertas_ret_802_11d_domain_info(wlan_private * priv,
 				 struct cmd_ds_command *resp)
 {
-	struct cmd_ds_802_11d_domain_info
-	*domaininfo = &resp->params.domaininforesp;
+	struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
 	struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
 	u16 action = le16_to_cpu(domaininfo->action);
 	s16 ret = 0;
 	u8 nr_subband = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_11D);
 
 	lbs_dbg_hex("11D DOMAIN Info Rsp Data:", (u8 *) resp,
 		(int)le16_to_cpu(resp->size));
 
-	nr_subband = (domain->header.len - 3) / sizeof(struct ieeetypes_subbandset);
-	/* countrycode 3 bytes */
+	nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
+		      sizeof(struct ieeetypes_subbandset);
 
-	lbs_pr_debug(1, "11D Domain Info Resp: nr_subband=%d\n", nr_subband);
+	lbs_deb_11d("11D Domain Info Resp: nr_subband=%d\n", nr_subband);
 
 	if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
-		lbs_pr_debug(1, "Invalid Numrer of Subband returned!!\n");
+		lbs_deb_11d("Invalid Numrer of Subband returned!!\n");
 		return -1;
 	}
 
@@ -637,12 +639,12 @@
 	case cmd_act_get:
 		break;
 	default:
-		lbs_pr_debug(1, "Invalid action:%d\n", domaininfo->action);
+		lbs_deb_11d("Invalid action:%d\n", domaininfo->action);
 		ret = -1;
 		break;
 	}
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
 	return ret;
 }
 
@@ -651,23 +653,22 @@
  *  @param priv    pointer to wlan_private
  *  @return 	   0; -1
  */
-int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
+int libertas_parse_dnld_countryinfo_11d(wlan_private * priv,
+                                        struct bss_descriptor * bss)
 {
 	int ret;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_11D);
 	if (priv->adapter->enable11d) {
 		memset(&adapter->parsed_region_chan, 0,
 		       sizeof(struct parsed_region_chan_11d));
-		ret = parse_domain_info_11d(&adapter->pattemptedbssdesc->
-					       countryinfo, 0,
+		ret = parse_domain_info_11d(&bss->countryinfo, 0,
 					       &adapter->parsed_region_chan);
 
 		if (ret == -1) {
-			lbs_pr_debug(1, "11D: Err Parse domain_info from AP..\n");
-			LEAVE();
-			return ret;
+			lbs_deb_11d("11D: Err Parse domain_info from AP..\n");
+			goto done;
 		}
 
 		memset(&adapter->domainreg, 0,
@@ -678,13 +679,15 @@
 		ret = set_domain_info_11d(priv);
 
 		if (ret) {
-			lbs_pr_debug(1, "11D: Err set domainInfo to FW\n");
-			LEAVE();
-			return ret;
+			lbs_deb_11d("11D: Err set domainInfo to FW\n");
+			goto done;
 		}
 	}
-	LEAVE();
-	return 0;
+	ret = 0;
+
+done:
+	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+	return ret;
 }
 
 /**
@@ -699,8 +702,8 @@
 	struct region_channel *region_chan;
 	u8 j;
 
-	ENTER();
-	lbs_pr_debug(1, "11D:curbssparams.band[%d]\n", adapter->curbssparams.band);
+	lbs_deb_enter(LBS_DEB_11D);
+	lbs_deb_11d("11D:curbssparams.band[%d]\n", adapter->curbssparams.band);
 
 	if (priv->adapter->enable11d) {
 		/* update parsed_region_chan_11; dnld domaininf to FW */
@@ -709,7 +712,7 @@
 		     sizeof(adapter->region_channel[0]); j++) {
 			region_chan = &adapter->region_channel[j];
 
-			lbs_pr_debug(1, "11D:[%d] region_chan->band[%d]\n", j,
+			lbs_deb_11d("11D:[%d] region_chan->band[%d]\n", j,
 			       region_chan->band);
 
 			if (!region_chan || !region_chan->valid
@@ -722,10 +725,10 @@
 
 		if (j >= sizeof(adapter->region_channel) /
 		    sizeof(adapter->region_channel[0])) {
-			lbs_pr_debug(1, "11D:region_chan not found. band[%d]\n",
+			lbs_deb_11d("11D:region_chan not found. band[%d]\n",
 			       adapter->curbssparams.band);
-			LEAVE();
-			return -1;
+			ret = -1;
+			goto done;
 		}
 
 		memset(&adapter->parsed_region_chan, 0,
@@ -742,13 +745,14 @@
 		ret = set_domain_info_11d(priv);
 
 		if (ret) {
-			lbs_pr_debug(1, "11D: Err set domainInfo to FW\n");
-			LEAVE();
-			return ret;
+			lbs_deb_11d("11D: Err set domainInfo to FW\n");
+			goto done;
 		}
 
 	}
+	ret = 0;
 
-	LEAVE();
-	return 0;
+done:
+	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+	return ret;
 }
diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h
index db2ebea9..73e42e7 100644
--- a/drivers/net/wireless/libertas/11d.h
+++ b/drivers/net/wireless/libertas/11d.h
@@ -47,7 +47,7 @@
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11d_domain_info {
-	u16 action;
+	__le16 action;
 	struct mrvlietypes_domainparamset domain;
 } __attribute__ ((packed));
 
@@ -98,7 +98,9 @@
 int libertas_ret_802_11d_domain_info(wlan_private * priv,
 				 struct cmd_ds_command *resp);
 
-int libertas_parse_dnld_countryinfo_11d(wlan_private * priv);
+struct bss_descriptor;
+int libertas_parse_dnld_countryinfo_11d(wlan_private * priv,
+                                        struct bss_descriptor * bss);
 
 int libertas_create_dnld_countryinfo_11d(wlan_private * priv);
 
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 56a8ea1..32ed413 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -1,12 +1,12 @@
-usb8xxx-objs := main.o fw.o wext.o \
+libertas-objs := main.o fw.o wext.o \
 		rx.o tx.o cmd.o 	  \
 		cmdresp.o scan.o	  \
 		join.o 11d.o 		  \
-		ioctl.o debugfs.o	  \
+		debugfs.o	  \
 		ethtool.o assoc.o
 
 usb8xxx-objs += if_bootcmd.o
 usb8xxx-objs += if_usb.o
 
+obj-$(CONFIG_LIBERTAS)     += libertas.o
 obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
-
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
index 3785772..0b133ce 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -1,7 +1,7 @@
 ================================================================================
 			README for USB8388
 
- (c) Copyright © 2003-2006, Marvell International Ltd.
+ (c) Copyright © 2003-2006, Marvell International Ltd.
  All Rights Reserved
 
  This software file (the "File") is distributed by Marvell International
@@ -28,293 +28,6 @@
 
 		insmod usb8388.ko [fw_name=usb8388.bin]
 
-=====================
-IWPRIV COMMAND
-=====================
-
-NAME
-	This manual describes the usage of private commands used in Marvell WLAN
-	Linux Driver. All the commands available in Wlanconfig will not be available
-	in the iwpriv.
-
-SYNOPSIS
-	iwpriv <ethX> <command> [sub-command] ...
-
-	iwpriv ethX setregioncode <n>
-	iwpriv ethX getregioncode
-
-Version 5 Command:
-	iwpriv ethX ledgpio <n>
-
-BT Commands:
-	The blinding table (BT) contains a list of mac addresses that should be
-	ignored by the firmware.  It is primarily used for debugging and
-	testing networks.  It can be edited and inspected with the following
-	commands:
-
-	iwpriv ethX bt_reset
-	iwpriv ethX bt_add <mac_address>
-	iwpriv ethX bt_del <mac_address>
-	iwpriv ethX bt_list <id>
-
-FWT Commands:
-	The forwarding table (FWT) is a feature used to manage mesh network
-	routing in the firmware.  The FWT is essentially a routing table that
-	associates a destination mac address (da) with a next hop receiver
-	address (ra).  The FWT can be inspected and edited with the following
-	iwpriv commands, which are described in greater detail below.
-	Eventually, the table will be automatically maintained by a custom
-	routing protocol.
-
-	NOTE: FWT commands replace the previous DFT commands.  What were the DFT
-	commands?, you might ask.  They were an earlier API to the firmware that
-	implemented a simple MAC-layer forwarding mechanism.  In the unlikely
-	event that you were using these commands, you must migrate to the new
-	FWT commands which can be used to achieve the same functionality.
-
-	iwpriv ethX fwt_add [parameters]
-	iwpriv ethX fwt_del [parameters]
-	iwpriv ethX fwt_lookup [parameters]
-	iwpriv ethX fwt_list [parameters]
-	iwpriv ethX fwt_list_route [parameters]
-	iwpriv ethX fwt_list_neigh [parameters]
-	iwpriv ethX fwt_reset [parameters]
-	iwpriv ethX fwt_cleanup
-	iwpriv ethX fwt_time
-
-MESH Commands:
-
-	The MESH commands are used to configure various features of the mesh
-	routing protocol.  The following commands are supported:
-
-	iwpriv ethX mesh_get_ttl
-	iwpriv ethX mesh_set_ttl ttl
-
-DESCRIPTION
-	Those commands are used to send additional commands to the Marvell WLAN
-	card via the Linux device driver.
-
-	The ethX parameter specifies the network device that is to be used to
-		perform this command on. it could be eth0, eth1 etc.
-
-setregioncode
-	This command is used to set the region code in the station.
-	where value is 'region code' for various regions like
-	USA FCC, Canada IC, Spain, France, Europe ETSI,	Japan ...
-
-	Usage:
-		iwpriv ethX setregioncode 0x10: set region code to USA (0x10).
-
-getregioncode
-	This command is used to get the region code information set in the
-	station.
-
-ledgpio
-	This command is used to set/get LEDs.
-
-	iwpriv ethX ledgpio <LEDs>
-		will set the corresponding LED for the GPIO Line.
-
-	iwpriv ethX ledgpio
-		will give u which LEDs are Enabled.
-
-	Usage:
-		iwpriv eth1 ledgpio 1 0 2 1 3 4
-			will enable
-			LED 1 -> GPIO 0
-			LED 2 -> GPIO 1
-			LED 3 -> GPIO 4
-
-		iwpriv eth1 ledgpio
-			shows LED information in the format as mentioned above.
-
-	Note: LED0 is invalid
-	Note: Maximum Number of LEDs are 16.
-
-fwt_add
-	This command is used to insert an entry into the FWT table. The list of
-	parameters must follow the following structure:
-
-	iwpriv ethX fwt_add da ra [metric dir ssn dsn hopcount ttl expiration sleepmode snr]
-
-	The parameters between brackets are optional, but they must appear in
-	the order specified.  For example, if you want to specify the metric,
-	you must also specify the dir, ssn, and dsn but you need not specify the
-	hopcount, expiration, sleepmode, or snr.  Any unspecified parameters
-	will be assigned the defaults specified below.
-
-	The different parameters are:-
-		da		-- DA MAC address in the form 00:11:22:33:44:55
-		ra		-- RA MAC address in the form 00:11:22:33:44:55
-		metric		-- route metric (cost: smaller-metric routes are
-				   preferred, default is 0)
-		dir		-- direction (1 for direct, 0 for reverse,
-				   default is 1)
-		ssn		-- Source Sequence Number (time at the RA for
-				   reverse routes.  Default is 0)
-		dsn		-- Destination Sequence Number (time at the DA
-				   for direct routes.  Default is 0)
-		hopcount	-- hop count (currently unused, default is 0)
-		ttl		-- TTL (Only used in reverse entries)
-		expiration	-- entry expiration (in ticks, where a tick is
-				   1024us, or ~ 1ms. Use 0 for an indefinite
-				   entry, default is 0)
-		sleepmode	-- RA's sleep mode (currently unused, default is
-				   0)
-		snr		-- SNR in the link to RA (currently unused,
-				   default is 0)
-
-	The command does not return anything.
-
-fwt_del
-	This command is used to remove an entry to the FWT table. The list of
-	parameters must follow the following structure:
-
-		iwpriv ethX fwt_del da ra [dir]
-
-	where the different parameters are:-
-		da		-- DA MAC address (in the form "00:11:22:33:44:55")
-		ra		-- RA MAC address (in the form "00:11:22:33:44:55")
-		dir		-- direction (1 for direct, 0 for reverse,
-				   default is 1)
-
-	The command does not return anything.
-
-fwt_lookup
-	This command is used to get the best route in the FWT table to a given
-	host. The only parameter is the MAC address of the host that is being
-	looked for.
-
-		iwpriv ethX fwt_lookup da
-
-	where:-
-		da		-- DA MAC address (in the form "00:11:22:33:44:55")
-
-	The command returns an output string identical to the one returned by
-	fwt_list described below.
-
-
-fwt_list
-	This command is used to list a route from the FWT table. The only
-	parameter is the index into the table. If you want to list all the
-	routes in a table, start with index=0, and keep listing until you get a
-	"(null)" string.  Note that the indicies may change as the fwt is
-	updated.  It is expected that most users will not use fwt_list directly,
-	but that a utility similar to the traditional route command will be used
-	to invoke fwt_list over and over.
-
-		iwpriv ethX fwt_list index
-
-	The output is a string of the following form:
-
-		da ra metric dir ssn dsn hopcount ttl expiration sleepmode snr
-
-	where the different fields are:-
-		da		-- DA MAC address (in the form "00:11:22:33:44:55")
-		ra		-- RA MAC address (in the form "00:11:22:33:44:55")
-		metric		-- route metric (cost: smaller-metric routes are preferred)
-		dir		-- direction (1 for direct, 0 for reverse)
-		ssn		-- Source Sequence Number (time at the RA for reverse routes)
-		dsn		-- Destination Sequence Number (time at the DA for direct routes)
-		hopcount	-- hop count (currently unused)
-		ttl		-- TTL (only used in reverse entries)
-		expiration	-- entry expiration (in ticks, where a tick is 1024us, or ~ 1ms. Use 0 for an indefinite entry)
-		sleepmode	-- RA's sleep mode (currently unused)
-		snr		-- SNR in the link to RA (currently unused)
-
-fwt_list_route
-	This command is used to list a route from the FWT table. The only
-	parameter is the route ID. If you want to list all the routes in a
-	table, start with rid=0, and keep incrementing rid until you get a
-	"(null)" string. This function is similar to fwt_list. The only
-	difference is the output format.  Also note that this command is meant
-	for debugging.  It is expected that users will use fwt_lookup and
-	fwt_list.  One important reason for this is that the route id may change
-	as the route table is altered.
-
-		iwpriv ethX fwt_list_route rid
-
-	The output is a string of the following form:
-
-		da metric dir nid ssn dsn hopcount ttl expiration
-
-	where the different fields are:-
-		da		-- DA MAC address (in the form "00:11:22:33:44:55")
-		metric		-- route metric (cost: smaller-metric routes are preferred)
-		dir		-- direction (1 for direct, 0 for reverse)
-		nid		-- Next-hop (neighbor) host ID (nid)
-		ssn		-- Source Sequence Number (time at the RA for reverse routes)
-		dsn		-- Destination Sequence Number (time at the DA for direct routes)
-		hopcount	-- hop count (currently unused)
-		ttl		-- TTL count (only used in reverse entries)
-		expiration	-- entry expiration (in ticks, where a tick is 1024us, or ~ 1ms. Use 0 for an indefinite entry)
-
-fwt_list_neigh
-	This command is used to list a neighbor from the FWT table. The only
-	parameter is the neighbor ID. If you want to list all the neighbors in a
-	table, start with nid=0, and keep incrementing nid until you get a
-	"(null)" string.  Note that the nid from a fwt_list_route command can be
-	used as an input to this command.  Also note that this command is meant
-	mostly for debugging.  It is expected that users will use fwt_lookup.
-	One important reason for this is that the neighbor id may change as the
-	neighbor table is altered.
-
-		iwpriv ethX fwt_list_neigh nid
-
-	The output is a string of the following form:
-
-		ra sleepmode snr references
-
-	where the different fields are:-
-		ra		-- RA MAC address (in the form "00:11:22:33:44:55")
-		sleepmode	-- RA's sleep mode (currently unused)
-		snr		-- SNR in the link to RA (currently unused)
-		references	-- RA's reference counter
-
-fwt_reset
-	This command is used to reset the FWT table, getting rid of all the
-	entries. There are no input parameters.
-
-		iwpriv ethX fwt_reset
-
-	The command does not return anything.
-
-fwt_cleanup
-	This command is used to perform user-based garbage recollection. The
-	FWT table is checked, and all the entries that are expired or invalid
-	are cleaned. Note that this is exported to the driver for debugging
-	purposes, as garbage collection is also fired by the firmware when in
-	space problems. There are no input parameters.
-
-		iwpriv ethX fwt_cleanup
-
-	The command does returns the number of invalid/expired routes deleted.
-
-fwt_time
-	This command returns a card's internal time representation.  It is this
-	time that is used to represent the expiration times of FWT entries.  The
-	number is not consistent from card to card; it is simply a timer count.
-	The fwt_time command is used to inspect the timer so that expiration
-	times reported by fwt_list can be properly interpreted.
-
-		iwpriv ethX fwt_time
-
-mesh_get_ttl
-
-	The mesh ttl is the number of hops a mesh packet can traverse before it
-	is dropped.  This parameter is used to prevent infinite loops in the
-	mesh network.  The value returned by this function is the ttl assigned
-	to all mesh packets.  Currently there is no way to control the ttl on a
-	per packet or per socket basis.
-
-	iwpriv ethX mesh_get_ttl
-
-mesh_set_ttl ttl
-
-	Set the ttl.  The argument must be between 0 and 255.
-
-	iwpriv ethX mesh_set_ttl <ttl>
-
 =========================
 ETHTOOL
 =========================
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index c260bd1..afd5617 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -2,6 +2,7 @@
 
 #include <linux/bitops.h>
 #include <net/ieee80211.h>
+#include <linux/etherdevice.h>
 
 #include "assoc.h"
 #include "join.h"
@@ -13,59 +14,88 @@
 static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
+static void print_assoc_req(const char * extra, struct assoc_request * assoc_req)
+{
+	lbs_deb_assoc(
+	       "#### Association Request: %s\n"
+	       "       flags:      0x%08lX\n"
+	       "       SSID:       '%s'\n"
+	       "       channel:    %d\n"
+	       "       band:       %d\n"
+	       "       mode:       %d\n"
+	       "       BSSID:      " MAC_FMT "\n"
+	       "       Encryption:%s%s%s\n"
+	       "       auth:       %d\n",
+	       extra, assoc_req->flags,
+	       escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+	       assoc_req->channel, assoc_req->band, assoc_req->mode,
+	       MAC_ARG(assoc_req->bssid),
+	       assoc_req->secinfo.WPAenabled ? " WPA" : "",
+	       assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
+	       assoc_req->secinfo.wep_enabled ? " WEP" : "",
+	       assoc_req->secinfo.auth_mode);
+}
+
+
 static int assoc_helper_essid(wlan_private *priv,
                               struct assoc_request * assoc_req)
 {
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
-	int i;
+	struct bss_descriptor * bss;
+	int channel = -1;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	lbs_pr_debug(1, "New SSID requested: %s\n", assoc_req->ssid.ssid);
+	/* FIXME: take channel into account when picking SSIDs if a channel
+	 * is set.
+	 */
+
+	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
+		channel = assoc_req->channel;
+
+	lbs_deb_assoc("New SSID requested: '%s'\n",
+	              escape_essid(assoc_req->ssid, assoc_req->ssid_len));
 	if (assoc_req->mode == IW_MODE_INFRA) {
 		if (adapter->prescan) {
-			libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1);
+			libertas_send_specific_ssid_scan(priv, assoc_req->ssid,
+				assoc_req->ssid_len, 0);
 		}
 
-		i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid,
-				NULL, IW_MODE_INFRA);
-		if (i >= 0) {
-			lbs_pr_debug(1,
-			       "SSID found in scan list ... associating...\n");
-
-			ret = wlan_associate(priv, &adapter->scantable[i]);
-			if (ret == 0) {
-				memcpy(&assoc_req->bssid,
-				       &adapter->scantable[i].macaddress,
-				       ETH_ALEN);
-			}
+		bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid,
+				assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
+		if (bss != NULL) {
+			lbs_deb_assoc("SSID found in scan list, associating\n");
+			memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
+			ret = wlan_associate(priv, assoc_req);
 		} else {
-			lbs_pr_debug(1, "SSID '%s' not found; cannot associate\n",
-				assoc_req->ssid.ssid);
+			lbs_deb_assoc("SSID not found; cannot associate\n");
 		}
 	} else if (assoc_req->mode == IW_MODE_ADHOC) {
 		/* Scan for the network, do not save previous results.  Stale
 		 *   scan data will cause us to join a non-existant adhoc network
 		 */
-		libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0);
+		libertas_send_specific_ssid_scan(priv, assoc_req->ssid,
+			assoc_req->ssid_len, 1);
 
 		/* Search for the requested SSID in the scan table */
-		i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL,
-				IW_MODE_ADHOC);
-		if (i >= 0) {
-			lbs_pr_debug(1, "SSID found at %d in List, so join\n", ret);
-			libertas_join_adhoc_network(priv, &adapter->scantable[i]);
+		bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid,
+				assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
+		if (bss != NULL) {
+			lbs_deb_assoc("SSID found, will join\n");
+			memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
+			libertas_join_adhoc_network(priv, assoc_req);
 		} else {
 			/* else send START command */
-			lbs_pr_debug(1, "SSID not found in list, so creating adhoc"
-				" with SSID '%s'\n", assoc_req->ssid.ssid);
-			libertas_start_adhoc_network(priv, &assoc_req->ssid);
+			lbs_deb_assoc("SSID not found, creating adhoc network\n");
+			memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
+				IW_ESSID_MAX_SIZE);
+			assoc_req->bss.ssid_len = assoc_req->ssid_len;
+			libertas_start_adhoc_network(priv, assoc_req);
 		}
-		memcpy(&assoc_req->bssid, &adapter->current_addr, ETH_ALEN);
 	}
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 	return ret;
 }
 
@@ -74,33 +104,31 @@
                               struct assoc_request * assoc_req)
 {
 	wlan_adapter *adapter = priv->adapter;
-	int i, ret = 0;
+	int ret = 0;
+	struct bss_descriptor * bss;
 
-	ENTER();
-
-	lbs_pr_debug(1, "ASSOC: WAP: BSSID = " MAC_FMT "\n",
+	lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID " MAC_FMT,
 		MAC_ARG(assoc_req->bssid));
 
 	/* Search for index position in list for requested MAC */
-	i = libertas_find_BSSID_in_list(adapter, assoc_req->bssid,
+	bss = libertas_find_bssid_in_list(adapter, assoc_req->bssid,
 			    assoc_req->mode);
-	if (i < 0) {
-		lbs_pr_debug(1, "ASSOC: WAP: BSSID " MAC_FMT " not found, "
+	if (bss == NULL) {
+		lbs_deb_assoc("ASSOC: WAP: BSSID " MAC_FMT " not found, "
 			"cannot associate.\n", MAC_ARG(assoc_req->bssid));
 		goto out;
 	}
 
+	memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
 	if (assoc_req->mode == IW_MODE_INFRA) {
-		ret = wlan_associate(priv, &adapter->scantable[i]);
-		lbs_pr_debug(1, "ASSOC: return from wlan_associate(bssd) was %d\n", ret);
+		ret = wlan_associate(priv, assoc_req);
+		lbs_deb_assoc("ASSOC: wlan_associate(bssid) returned %d\n", ret);
 	} else if (assoc_req->mode == IW_MODE_ADHOC) {
-		libertas_join_adhoc_network(priv, &adapter->scantable[i]);
+		libertas_join_adhoc_network(priv, assoc_req);
 	}
-	memcpy(&assoc_req->ssid, &adapter->scantable[i].ssid,
-		sizeof(struct WLAN_802_11_SSID));
 
 out:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 	return ret;
 }
 
@@ -113,12 +141,12 @@
 	/* If we're given and 'any' BSSID, try associating based on SSID */
 
 	if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
-		if (memcmp(bssid_any, assoc_req->bssid, ETH_ALEN)
-		    && memcmp(bssid_off, assoc_req->bssid, ETH_ALEN)) {
+		if (compare_ether_addr(bssid_any, assoc_req->bssid)
+		    && compare_ether_addr(bssid_off, assoc_req->bssid)) {
 			ret = assoc_helper_bssid(priv, assoc_req);
 			done = 1;
 			if (ret) {
-				lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret);
+				lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
 			}
 		}
 	}
@@ -126,7 +154,7 @@
 	if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
 		ret = assoc_helper_essid(priv, assoc_req);
 		if (ret) {
-			lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret);
+			lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
 		}
 	}
 
@@ -140,12 +168,10 @@
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	if (assoc_req->mode == adapter->mode) {
-		LEAVE();
-		return 0;
-	}
+	if (assoc_req->mode == adapter->mode)
+		goto done;
 
 	if (assoc_req->mode == IW_MODE_INFRA) {
 		if (adapter->psstate != PS_STATE_FULL_POWER)
@@ -158,9 +184,81 @@
 				    cmd_802_11_snmp_mib,
 				    0, cmd_option_waitforrsp,
 				    OID_802_11_INFRASTRUCTURE_MODE,
-				    (void *) (size_t) assoc_req->mode);
+		/* Shoot me now */  (void *) (size_t) assoc_req->mode);
 
-	LEAVE();
+done:
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+	return ret;
+}
+
+
+static int update_channel(wlan_private * priv)
+{
+	/* the channel in f/w could be out of sync, get the current channel */
+	return libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
+				    cmd_opt_802_11_rf_channel_get,
+				    cmd_option_waitforrsp, 0, NULL);
+}
+
+void libertas_sync_channel(struct work_struct *work)
+{
+	wlan_private *priv = container_of(work, wlan_private, sync_channel);
+
+	if (update_channel(priv) != 0)
+		lbs_pr_info("Channel synchronization failed.");
+}
+
+static int assoc_helper_channel(wlan_private *priv,
+                                struct assoc_request * assoc_req)
+{
+	wlan_adapter *adapter = priv->adapter;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_ASSOC);
+
+	ret = update_channel(priv);
+	if (ret < 0) {
+		lbs_deb_assoc("ASSOC: channel: error getting channel.");
+	}
+
+	if (assoc_req->channel == adapter->curbssparams.channel)
+		goto done;
+
+	lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
+	       adapter->curbssparams.channel, assoc_req->channel);
+
+	ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
+				cmd_opt_802_11_rf_channel_set,
+				cmd_option_waitforrsp, 0, &assoc_req->channel);
+	if (ret < 0) {
+		lbs_deb_assoc("ASSOC: channel: error setting channel.");
+	}
+
+	ret = update_channel(priv);
+	if (ret < 0) {
+		lbs_deb_assoc("ASSOC: channel: error getting channel.");
+	}
+
+	if (assoc_req->channel != adapter->curbssparams.channel) {
+		lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
+		              assoc_req->channel);
+		goto done;
+	}
+
+	if (   assoc_req->secinfo.wep_enabled
+	    &&   (assoc_req->wep_keys[0].len
+	       || assoc_req->wep_keys[1].len
+	       || assoc_req->wep_keys[2].len
+	       || assoc_req->wep_keys[3].len)) {
+		/* Make sure WEP keys are re-sent to firmware */
+		set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
+	}
+
+	/* Must restart/rejoin adhoc networks after channel change */
+	set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
+
+done:
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 	return ret;
 }
 
@@ -172,7 +270,7 @@
 	int i;
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	/* Set or remove WEP keys */
 	if (   assoc_req->wep_keys[0].len
@@ -216,7 +314,7 @@
 	mutex_unlock(&adapter->lock);
 
 out:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 	return ret;
 }
 
@@ -225,15 +323,49 @@
 {
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
+	u32 do_wpa;
+	u32 rsn = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	memcpy(&adapter->secinfo, &assoc_req->secinfo,
 		sizeof(struct wlan_802_11_security));
 
 	ret = libertas_set_mac_packet_filter(priv);
+	if (ret)
+		goto out;
 
-	LEAVE();
+	/* If RSN is already enabled, don't try to enable it again, since
+	 * ENABLE_RSN resets internal state machines and will clobber the
+	 * 4-way WPA handshake.
+	 */
+
+	/* Get RSN enabled/disabled */
+	ret = libertas_prepare_and_send_command(priv,
+				    cmd_802_11_enable_rsn,
+				    cmd_act_set,
+				    cmd_option_waitforrsp,
+				    0, &rsn);
+	if (ret) {
+		lbs_deb_assoc("Failed to get RSN status: %d", ret);
+		goto out;
+	}
+
+	/* Don't re-enable RSN if it's already enabled */
+	do_wpa = (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled);
+	if (do_wpa == rsn)
+		goto out;
+
+	/* Set RSN enabled/disabled */
+	rsn = do_wpa;
+	ret = libertas_prepare_and_send_command(priv,
+				    cmd_802_11_enable_rsn,
+				    cmd_act_set,
+				    cmd_option_waitforrsp,
+				    0, &rsn);
+
+out:
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 	return ret;
 }
 
@@ -243,16 +375,7 @@
 {
 	int ret = 0;
 
-	ENTER();
-
-	/* enable/Disable RSN */
-	ret = libertas_prepare_and_send_command(priv,
-				    cmd_802_11_enable_rsn,
-				    cmd_act_set,
-				    cmd_option_waitforrsp,
-				    0, assoc_req);
-	if (ret)
-		goto out;
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	ret = libertas_prepare_and_send_command(priv,
 				    cmd_802_11_key_material,
@@ -260,8 +383,7 @@
 				    cmd_option_waitforrsp,
 				    0, assoc_req);
 
-out:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 	return ret;
 }
 
@@ -272,7 +394,7 @@
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
 		memcpy(&adapter->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
@@ -282,7 +404,7 @@
 		adapter->wpa_ie_len = 0;
 	}
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 	return ret;
 }
 
@@ -294,25 +416,30 @@
 		return 0;
 
 	if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
-		lbs_pr_debug(1, "Deauthenticating due to new SSID in "
+		lbs_deb_assoc("Deauthenticating due to new SSID in "
 			" configuration request.\n");
 		return 1;
 	}
 
 	if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
 		if (adapter->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
-			lbs_pr_debug(1, "Deauthenticating due to updated security "
+			lbs_deb_assoc("Deauthenticating due to updated security "
 				"info in configuration request.\n");
 			return 1;
 		}
 	}
 
 	if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
-		lbs_pr_debug(1, "Deauthenticating due to new BSSID in "
+		lbs_deb_assoc("Deauthenticating due to new BSSID in "
 			" configuration request.\n");
 		return 1;
 	}
 
+	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+		lbs_deb_assoc("Deauthenticating due to channel switch.\n");
+		return 1;
+	}
+
 	/* FIXME: deal with 'auto' mode somehow */
 	if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
 		if (assoc_req->mode != IW_MODE_INFRA)
@@ -329,10 +456,9 @@
 	if (adapter->connect_status != libertas_connected)
 		return 0;
 
-	if (adapter->curbssparams.ssid.ssidlength != assoc_req->ssid.ssidlength)
-		return 1;
-	if (memcmp(adapter->curbssparams.ssid.ssid, assoc_req->ssid.ssid,
-			adapter->curbssparams.ssid.ssidlength))
+	if (libertas_ssid_cmp(adapter->curbssparams.ssid,
+	                      adapter->curbssparams.ssid_len,
+	                      assoc_req->ssid, assoc_req->ssid_len) != 0)
 		return 1;
 
 	/* FIXME: deal with 'auto' mode somehow */
@@ -341,11 +467,16 @@
 			return 1;
 	}
 
+	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+		if (assoc_req->channel != adapter->curbssparams.channel)
+			return 1;
+	}
+
 	return 0;
 }
 
 
-void wlan_association_worker(struct work_struct *work)
+void libertas_association_worker(struct work_struct *work)
 {
 	wlan_private *priv = container_of(work, wlan_private, assoc_work.work);
 	wlan_adapter *adapter = priv->adapter;
@@ -353,40 +484,38 @@
 	int ret = 0;
 	int find_any_ssid = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	mutex_lock(&adapter->lock);
-	assoc_req = adapter->assoc_req;
-	adapter->assoc_req = NULL;
+	assoc_req = adapter->pending_assoc_req;
+	adapter->pending_assoc_req = NULL;
+	adapter->in_progress_assoc_req = assoc_req;
 	mutex_unlock(&adapter->lock);
 
-	if (!assoc_req) {
-		LEAVE();
-		return;
-	}
+	if (!assoc_req)
+		goto done;
 
-	lbs_pr_debug(1, "ASSOC: starting new association request: flags = 0x%lX\n",
-		assoc_req->flags);
+	print_assoc_req(__func__, assoc_req);
 
 	/* If 'any' SSID was specified, find an SSID to associate with */
 	if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
-	    && !assoc_req->ssid.ssidlength)
+	    && !assoc_req->ssid_len)
 		find_any_ssid = 1;
 
 	/* But don't use 'any' SSID if there's a valid locked BSSID to use */
 	if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
-		if (memcmp(&assoc_req->bssid, bssid_any, ETH_ALEN)
-		    && memcmp(&assoc_req->bssid, bssid_off, ETH_ALEN))
+		if (compare_ether_addr(assoc_req->bssid, bssid_any)
+		    && compare_ether_addr(assoc_req->bssid, bssid_off))
 			find_any_ssid = 0;
 	}
 
 	if (find_any_ssid) {
 		u8 new_mode;
 
-		ret = libertas_find_best_network_SSID(priv, &assoc_req->ssid,
-				assoc_req->mode, &new_mode);
+		ret = libertas_find_best_network_ssid(priv, assoc_req->ssid,
+				&assoc_req->ssid_len, assoc_req->mode, &new_mode);
 		if (ret) {
-			lbs_pr_debug(1, "Could not find best network\n");
+			lbs_deb_assoc("Could not find best network\n");
 			ret = -ENETUNREACH;
 			goto out;
 		}
@@ -406,7 +535,7 @@
 		if (should_deauth_infrastructure(adapter, assoc_req)) {
 			ret = libertas_send_deauthentication(priv);
 			if (ret) {
-				lbs_pr_debug(1, "Deauthentication due to new "
+				lbs_deb_assoc("Deauthentication due to new "
 					"configuration request failed: %d\n",
 					ret);
 			}
@@ -415,7 +544,7 @@
 		if (should_stop_adhoc(adapter, assoc_req)) {
 			ret = libertas_stop_adhoc_network(priv);
 			if (ret) {
-				lbs_pr_debug(1, "Teardown of AdHoc network due to "
+				lbs_deb_assoc("Teardown of AdHoc network due to "
 					"new configuration request failed: %d\n",
 					ret);
 			}
@@ -427,7 +556,16 @@
 	if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
 		ret = assoc_helper_mode(priv, assoc_req);
 		if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
+			goto out;
+		}
+	}
+
+	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+		ret = assoc_helper_channel(priv, assoc_req);
+		if (ret) {
+			lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n",
+			              __LINE__, ret);
 			goto out;
 		}
 	}
@@ -436,7 +574,7 @@
 	    || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
 		ret = assoc_helper_wep_keys(priv, assoc_req);
 		if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret);
 			goto out;
 		}
 	}
@@ -444,7 +582,7 @@
 	if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
 		ret = assoc_helper_secinfo(priv, assoc_req);
 		if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret);
 			goto out;
 		}
 	}
@@ -452,7 +590,7 @@
 	if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
 		ret = assoc_helper_wpa_ie(priv, assoc_req);
 		if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret);
 			goto out;
 		}
 	}
@@ -461,7 +599,7 @@
 	    || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
 		ret = assoc_helper_wpa_keys(priv, assoc_req);
 		if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
 			goto out;
 		}
 	}
@@ -475,21 +613,23 @@
 
 		ret = assoc_helper_associate(priv, assoc_req);
 		if (ret) {
-			lbs_pr_debug(1, "ASSOC: association attempt unsuccessful: %d\n",
+			lbs_deb_assoc("ASSOC: association attempt unsuccessful: %d\n",
 				ret);
 			success = 0;
 		}
 
 		if (adapter->connect_status != libertas_connected) {
-			lbs_pr_debug(1, "ASSOC: assoication attempt unsuccessful, "
+			lbs_deb_assoc("ASSOC: assoication attempt unsuccessful, "
 				"not connected.\n");
 			success = 0;
 		}
 
 		if (success) {
-			lbs_pr_debug(1, "ASSOC: association attempt successful. "
+			lbs_deb_assoc("ASSOC: association attempt successful. "
 				"Associated to '%s' (" MAC_FMT ")\n",
-				assoc_req->ssid.ssid, MAC_ARG(assoc_req->bssid));
+				escape_essid(adapter->curbssparams.ssid,
+				             adapter->curbssparams.ssid_len),
+				MAC_ARG(adapter->curbssparams.bssid));
 			libertas_prepare_and_send_command(priv,
 				cmd_802_11_rssi,
 				0, cmd_option_waitforrsp, 0, NULL);
@@ -498,18 +638,23 @@
 				cmd_802_11_get_log,
 				0, cmd_option_waitforrsp, 0, NULL);
 		} else {
-
 			ret = -1;
 		}
 	}
 
 out:
 	if (ret) {
-		lbs_pr_debug(1, "ASSOC: reconfiguration attempt unsuccessful: %d\n",
+		lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
 			ret);
 	}
+
+	mutex_lock(&adapter->lock);
+	adapter->in_progress_assoc_req = NULL;
+	mutex_unlock(&adapter->lock);
 	kfree(assoc_req);
-	LEAVE();
+
+done:
+	lbs_deb_leave(LBS_DEB_ASSOC);
 }
 
 
@@ -520,9 +665,10 @@
 {
 	struct assoc_request * assoc_req;
 
-	if (!adapter->assoc_req) {
-		adapter->assoc_req = kzalloc(sizeof(struct assoc_request), GFP_KERNEL);
-		if (!adapter->assoc_req) {
+	if (!adapter->pending_assoc_req) {
+		adapter->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
+		                                     GFP_KERNEL);
+		if (!adapter->pending_assoc_req) {
 			lbs_pr_info("Not enough memory to allocate association"
 				" request!\n");
 			return NULL;
@@ -532,15 +678,19 @@
 	/* Copy current configuration attributes to the association request,
 	 * but don't overwrite any that are already set.
 	 */
-	assoc_req = adapter->assoc_req;
+	assoc_req = adapter->pending_assoc_req;
 	if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
-		memcpy(&assoc_req->ssid, adapter->curbssparams.ssid.ssid,
-			adapter->curbssparams.ssid.ssidlength);
+		memcpy(&assoc_req->ssid, &adapter->curbssparams.ssid,
+		       IW_ESSID_MAX_SIZE);
+		assoc_req->ssid_len = adapter->curbssparams.ssid_len;
 	}
 
 	if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
 		assoc_req->channel = adapter->curbssparams.channel;
 
+	if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
+		assoc_req->band = adapter->curbssparams.band;
+
 	if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
 		assoc_req->mode = adapter->mode;
 
@@ -581,7 +731,7 @@
 		assoc_req->wpa_ie_len = adapter->wpa_ie_len;
 	}
 
+	print_assoc_req(__func__, assoc_req);
+
 	return assoc_req;
 }
-
-
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
index 2ffd82d..5e9c31f 100644
--- a/drivers/net/wireless/libertas/assoc.h
+++ b/drivers/net/wireless/libertas/assoc.h
@@ -5,10 +5,12 @@
 
 #include "dev.h"
 
-void wlan_association_worker(struct work_struct *work);
+void libertas_association_worker(struct work_struct *work);
 
 struct assoc_request * wlan_get_association_request(wlan_adapter *adapter);
 
+void libertas_sync_channel(struct work_struct *work);
+
 #define ASSOC_DELAY (HZ / 2)
 static inline void wlan_postpone_association_work(wlan_private *priv)
 {
@@ -21,9 +23,9 @@
 static inline void wlan_cancel_association_work(wlan_private *priv)
 {
 	cancel_delayed_work(&priv->assoc_work);
-	if (priv->adapter->assoc_req) {
-		kfree(priv->adapter->assoc_req);
-		priv->adapter->assoc_req = NULL;
+	if (priv->adapter->pending_assoc_req) {
+		kfree(priv->adapter->pending_assoc_req);
+		priv->adapter->pending_assoc_req = NULL;
 	}
 }
 
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index de9cb46..4a8f5dc 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -6,7 +6,6 @@
 #include <net/iw_handler.h>
 #include "host.h"
 #include "hostcmd.h"
-#include "sbi.h"
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
@@ -26,13 +25,11 @@
  *  @param command the command ID
  *  @return 	   TRUE or FALSE
  */
-static u8 is_command_allowed_in_ps(u16 command)
+static u8 is_command_allowed_in_ps(__le16 command)
 {
-	int count = sizeof(commands_allowed_in_ps)
-	    / sizeof(commands_allowed_in_ps[0]);
 	int i;
 
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < ARRAY_SIZE(commands_allowed_in_ps); i++) {
 		if (command == cpu_to_le16(commands_allowed_in_ps[i]))
 			return 1;
 	}
@@ -44,14 +41,13 @@
 {
 	struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->command = cpu_to_le16(cmd_get_hw_spec);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
 	memcpy(hwspec->permanentaddr, priv->adapter->current_addr, ETH_ALEN);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -60,21 +56,19 @@
 				   u16 cmd_action)
 {
 	struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
-	u16 action = cmd_action;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->command = cpu_to_le16(cmd_802_11_ps_mode);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
-			     S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
+				S_DS_GEN);
 	psm->action = cpu_to_le16(cmd_action);
 	psm->multipledtim = 0;
-	switch (action) {
+	switch (cmd_action) {
 	case cmd_subcmd_enter_ps:
-		lbs_pr_debug(1, "PS command:" "SubCode- Enter PS\n");
-		lbs_pr_debug(1, "locallisteninterval = %d\n",
+		lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
+		lbs_deb_cmd("locallisteninterval = %d\n",
 		       adapter->locallisteninterval);
 
 		psm->locallisteninterval =
@@ -86,18 +80,18 @@
 		break;
 
 	case cmd_subcmd_exit_ps:
-		lbs_pr_debug(1, "PS command:" "SubCode- Exit PS\n");
+		lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
 		break;
 
 	case cmd_subcmd_sleep_confirmed:
-		lbs_pr_debug(1, "PS command: SubCode- sleep confirm\n");
+		lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
 		break;
 
 	default:
 		break;
 	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -115,8 +109,7 @@
 	cmd->params.inactivity_timeout.action = cpu_to_le16(cmd_action);
 
 	if (cmd_action)
-		cmd->params.inactivity_timeout.timeout =
-		    cpu_to_le16(*timeout);
+		cmd->params.inactivity_timeout.timeout = cpu_to_le16(*timeout);
 	else
 		cmd->params.inactivity_timeout.timeout = 0;
 
@@ -130,11 +123,10 @@
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_sleep_params *sp = &cmd->params.sleep_params;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	cmd->size =
-	    cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
-			     S_DS_GEN);
+	cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
+				S_DS_GEN);
 	cmd->command = cpu_to_le16(cmd_802_11_sleep_params);
 
 	if (cmd_action == cmd_act_get) {
@@ -151,7 +143,7 @@
 		sp->reserved = cpu_to_le16(adapter->sp.sp_reserved);
 	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -165,17 +157,16 @@
 	int ret = 0;
 	struct assoc_request * assoc_req = pdata_buf;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->command = cpu_to_le16(cmd_802_11_set_wep);
-	cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_set_wep))
-	                             + S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(*wep) + S_DS_GEN);
 
 	if (cmd_act == cmd_act_add) {
 		int i;
 
 		if (!assoc_req) {
-			lbs_pr_debug(1, "Invalid association request!");
+			lbs_deb_cmd("Invalid association request!");
 			ret = -1;
 			goto done;
 		}
@@ -183,11 +174,10 @@
 		wep->action = cpu_to_le16(cmd_act_add);
 
 		/* default tx key index */
-		wep->keyindex = cpu_to_le16((u16)
-				                 (assoc_req->wep_tx_keyidx &
-				                 (u32)cmd_WEP_KEY_INDEX_MASK));
+		wep->keyindex = cpu_to_le16((u16)(assoc_req->wep_tx_keyidx &
+						  (u32)cmd_WEP_KEY_INDEX_MASK));
 
-		lbs_pr_debug(1, "Tx key Index: %u\n", wep->keyindex);
+		lbs_deb_cmd("Tx key Index: %u\n", le16_to_cpu(wep->keyindex));
 
 		/* Copy key types and material to host command structure */
 		for (i = 0; i < 4; i++) {
@@ -195,19 +185,21 @@
 
 			switch (pkey->len) {
 			case KEY_LEN_WEP_40:
-				wep->keytype[i] = cmd_type_wep_40_bit;
+				wep->keytype[i] =
+					cpu_to_le16(cmd_type_wep_40_bit);
 				memmove(&wep->keymaterial[i], pkey->key,
 				        pkey->len);
 				break;
 			case KEY_LEN_WEP_104:
-				wep->keytype[i] = cmd_type_wep_104_bit;
+				wep->keytype[i] =
+					cpu_to_le16(cmd_type_wep_104_bit);
 				memmove(&wep->keymaterial[i], pkey->key,
 				        pkey->len);
 				break;
 			case 0:
 				break;
 			default:
-				lbs_pr_debug(1, "Invalid WEP key %d length of %d\n",
+				lbs_deb_cmd("Invalid WEP key %d length of %d\n",
 				       i, pkey->len);
 				ret = -1;
 				goto done;
@@ -219,36 +211,39 @@
 		wep->action = cpu_to_le16(cmd_act_remove);
 
 		/* default tx key index */
-		wep->keyindex = cpu_to_le16((u16)
-				                 (adapter->wep_tx_keyidx &
-				                 (u32)cmd_WEP_KEY_INDEX_MASK));
+		wep->keyindex = cpu_to_le16((u16)(adapter->wep_tx_keyidx &
+						  (u32)cmd_WEP_KEY_INDEX_MASK));
 	}
 
 	ret = 0;
 
 done:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
 static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
 				      struct cmd_ds_command *cmd,
-				      u16 cmd_action)
+				      u16 cmd_action,
+				      void * pdata_buf)
 {
 	struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn;
-	wlan_adapter *adapter = priv->adapter;
+	u32 * enable = pdata_buf;
+
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->command = cpu_to_le16(cmd_802_11_enable_rsn);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_enable_rsn) +
-			     S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN);
 	penableRSN->action = cpu_to_le16(cmd_action);
-	if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
-		penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
-	} else {
-		penableRSN->enable = cpu_to_le16(cmd_disable_rsn);
+
+	if (cmd_action == cmd_act_set) {
+		if (*enable)
+			penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
+		else
+			penableRSN->enable = cpu_to_le16(cmd_disable_rsn);
 	}
 
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -259,14 +254,12 @@
 	pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
 
 	if (pkey->flags & KEY_INFO_WPA_ENABLED) {
-		pkeyparamset->keyinfo = cpu_to_le16(KEY_INFO_WPA_ENABLED);
-	} else {
-		pkeyparamset->keyinfo = cpu_to_le16(!KEY_INFO_WPA_ENABLED);
+		pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
 	}
-
 	if (pkey->flags & KEY_INFO_WPA_UNICAST) {
 		pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
-	} else if (pkey->flags & KEY_INFO_WPA_MCAST) {
+	}
+	if (pkey->flags & KEY_INFO_WPA_MCAST) {
 		pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
 	}
 
@@ -284,46 +277,45 @@
 					u16 cmd_action,
 					u32 cmd_oid, void *pdata_buf)
 {
-	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_key_material *pkeymaterial =
 	    &cmd->params.keymaterial;
+	struct assoc_request * assoc_req = pdata_buf;
 	int ret = 0;
 	int index = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->command = cpu_to_le16(cmd_802_11_key_material);
 	pkeymaterial->action = cpu_to_le16(cmd_action);
 
 	if (cmd_action == cmd_act_get) {
-		cmd->size = cpu_to_le16(  S_DS_GEN
-		                             + sizeof (pkeymaterial->action));
+		cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
 		ret = 0;
 		goto done;
 	}
 
 	memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
 
-	if (adapter->wpa_unicast_key.len) {
+	if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
 		set_one_wpa_key(&pkeymaterial->keyParamSet[index],
-		                &adapter->wpa_unicast_key);
+		                &assoc_req->wpa_unicast_key);
 		index++;
 	}
 
-	if (adapter->wpa_mcast_key.len) {
+	if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
 		set_one_wpa_key(&pkeymaterial->keyParamSet[index],
-		                &adapter->wpa_mcast_key);
+		                &assoc_req->wpa_mcast_key);
 		index++;
 	}
 
 	cmd->size = cpu_to_le16(  S_DS_GEN
-	                             + sizeof (pkeymaterial->action)
-	                             + index * sizeof(struct MrvlIEtype_keyParamSet));
+	                        + sizeof (pkeymaterial->action)
+	                        + (index * sizeof(struct MrvlIEtype_keyParamSet)));
 
 	ret = 0;
 
 done:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
@@ -354,8 +346,7 @@
 {
 	cmd->command = cpu_to_le16(cmd_802_11_get_stat);
 	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) +
-			     S_DS_GEN);
+	    cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
 
 	return 0;
 }
@@ -369,14 +360,12 @@
 	wlan_adapter *adapter = priv->adapter;
 	u8 ucTemp;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	lbs_pr_debug(1, "SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
+	lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
 
 	cmd->command = cpu_to_le16(cmd_802_11_snmp_mib);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_snmp_mib) +
-			     S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
 
 	switch (cmd_oid) {
 	case OID_802_11_INFRASTRUCTURE_MODE:
@@ -407,7 +396,7 @@
 				pSNMPMIB->querytype = cmd_act_set;
 				pSNMPMIB->bufsize = sizeof(u16);
 				ulTemp = *(u32 *)pdata_buf;
-				*((unsigned short *)(pSNMPMIB->value)) =
+				*((__le16 *)(pSNMPMIB->value)) =
 				    cpu_to_le16((u16) ulTemp);
 			}
 			break;
@@ -420,15 +409,12 @@
 			pSNMPMIB->oid = cpu_to_le16((u16) fragthresh_i);
 
 			if (cmd_action == cmd_act_get) {
-				pSNMPMIB->querytype =
-				    cpu_to_le16(cmd_act_get);
+				pSNMPMIB->querytype = cpu_to_le16(cmd_act_get);
 			} else if (cmd_action == cmd_act_set) {
-				pSNMPMIB->querytype =
-				    cpu_to_le16(cmd_act_set);
-				pSNMPMIB->bufsize =
-				    cpu_to_le16(sizeof(u16));
+				pSNMPMIB->querytype = cpu_to_le16(cmd_act_set);
+				pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
 				ulTemp = *((u32 *) pdata_buf);
-				*((unsigned short *)(pSNMPMIB->value)) =
+				*((__le16 *)(pSNMPMIB->value)) =
 				    cpu_to_le16((u16) ulTemp);
 
 			}
@@ -443,16 +429,12 @@
 			pSNMPMIB->oid = le16_to_cpu((u16) rtsthresh_i);
 
 			if (cmd_action == cmd_act_get) {
-				pSNMPMIB->querytype =
-				    cpu_to_le16(cmd_act_get);
+				pSNMPMIB->querytype = cpu_to_le16(cmd_act_get);
 			} else if (cmd_action == cmd_act_set) {
-				pSNMPMIB->querytype =
-				    cpu_to_le16(cmd_act_set);
-				pSNMPMIB->bufsize =
-				    cpu_to_le16(sizeof(u16));
-				ulTemp = *((u32 *)
-					   pdata_buf);
-				*(unsigned short *)(pSNMPMIB->value) =
+				pSNMPMIB->querytype = cpu_to_le16(cmd_act_set);
+				pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
+				ulTemp = *((u32 *)pdata_buf);
+				*(__le16 *)(pSNMPMIB->value) =
 				    cpu_to_le16((u16) ulTemp);
 
 			}
@@ -462,13 +444,11 @@
 		pSNMPMIB->oid = cpu_to_le16((u16) short_retrylim_i);
 
 		if (cmd_action == cmd_act_get) {
-			pSNMPMIB->querytype =
-			    cpu_to_le16(cmd_act_get);
+			pSNMPMIB->querytype = cpu_to_le16(cmd_act_get);
 		} else if (cmd_action == cmd_act_set) {
-			pSNMPMIB->querytype =
-			    cpu_to_le16(cmd_act_set);
+			pSNMPMIB->querytype = cpu_to_le16(cmd_act_set);
 			pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
-			*((unsigned short *)(pSNMPMIB->value)) =
+			*((__le16 *)(pSNMPMIB->value)) =
 			    cpu_to_le16((u16) adapter->txretrycount);
 		}
 
@@ -477,16 +457,18 @@
 		break;
 	}
 
-	lbs_pr_debug(1,
+	lbs_deb_cmd(
 	       "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
-	       cmd->command, cmd->size, cmd->seqnum, cmd->result);
+	       le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
+	       le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
 
-	lbs_pr_debug(1,
+	lbs_deb_cmd(
 	       "SNMP_CMD: action=0x%x, oid=0x%x, oidsize=0x%x, value=0x%x\n",
-	       pSNMPMIB->querytype, pSNMPMIB->oid, pSNMPMIB->bufsize,
-	       *(u16 *) pSNMPMIB->value);
+	       le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
+	       le16_to_cpu(pSNMPMIB->bufsize),
+	       le16_to_cpu(*(__le16 *) pSNMPMIB->value));
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -495,10 +477,9 @@
 					 int cmd_action)
 {
 	wlan_adapter *adapter = priv->adapter;
-	struct cmd_ds_802_11_radio_control *pradiocontrol =
-	    &cmd->params.radio;
+	struct cmd_ds_802_11_radio_control *pradiocontrol = &cmd->params.radio;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->size =
 	    cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control)) +
@@ -527,7 +508,7 @@
 	else
 		pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -538,16 +519,16 @@
 
 	struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->size =
-	    cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) +
-			     S_DS_GEN);
+	    cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
 	cmd->command = cpu_to_le16(cmd_802_11_rf_tx_power);
-	prtp->action = cmd_action;
+	prtp->action = cpu_to_le16(cmd_action);
 
-	lbs_pr_debug(1, "RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n", cmd->size,
-	       cmd->command, prtp->action);
+	lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
+		    le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
+		    le16_to_cpu(prtp->action));
 
 	switch (cmd_action) {
 	case cmd_act_tx_power_opt_get:
@@ -557,14 +538,12 @@
 
 	case cmd_act_tx_power_opt_set_high:
 		prtp->action = cpu_to_le16(cmd_act_set);
-		prtp->currentlevel =
-		    cpu_to_le16(cmd_act_tx_power_index_high);
+		prtp->currentlevel = cpu_to_le16(cmd_act_tx_power_index_high);
 		break;
 
 	case cmd_act_tx_power_opt_set_mid:
 		prtp->action = cpu_to_le16(cmd_act_set);
-		prtp->currentlevel =
-		    cpu_to_le16(cmd_act_tx_power_index_mid);
+		prtp->currentlevel = cpu_to_le16(cmd_act_tx_power_index_mid);
 		break;
 
 	case cmd_act_tx_power_opt_set_low:
@@ -572,7 +551,8 @@
 		prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
 		break;
 	}
-	LEAVE();
+
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -583,15 +563,12 @@
 	struct cmd_ds_802_11_rf_antenna *rant = &cmd->params.rant;
 
 	cmd->command = cpu_to_le16(cmd_802_11_rf_antenna);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_antenna) +
-			     S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_antenna) +
+				S_DS_GEN);
 
 	rant->action = cpu_to_le16(cmd_action);
-	if ((cmd_action == cmd_act_set_rx) ||
-	    (cmd_action == cmd_act_set_tx)) {
-		rant->antennamode =
-		    cpu_to_le16((u16) (*(u32 *) pdata_buf));
+	if ((cmd_action == cmd_act_set_rx) || (cmd_action == cmd_act_set_tx)) {
+		rant->antennamode = cpu_to_le16((u16) (*(u32 *) pdata_buf));
 	}
 
 	return 0;
@@ -610,13 +587,13 @@
 			     + S_DS_GEN);
 	cmd->command = cpu_to_le16(cmd_802_11_rate_adapt_rateset);
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	rateadapt->action = cmd_action;
-	rateadapt->enablehwauto = adapter->enablehwauto;
-	rateadapt->bitmap = adapter->ratebitmap;
+	rateadapt->action = cpu_to_le16(cmd_action);
+	rateadapt->enablehwauto = cpu_to_le16(adapter->enablehwauto);
+	rateadapt->bitmap = cpu_to_le16(adapter->ratebitmap);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -626,12 +603,10 @@
 {
 	struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate;
 	wlan_adapter *adapter = priv->adapter;
-	u16 action = cmd_action;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
 			     S_DS_GEN);
 
 	cmd->command = cpu_to_le16(cmd_802_11_data_rate);
@@ -640,15 +615,15 @@
 
 	pdatarate->action = cpu_to_le16(cmd_action);
 
-	if (action == cmd_act_set_tx_fix_rate) {
+	if (cmd_action == cmd_act_set_tx_fix_rate) {
 		pdatarate->datarate[0] = libertas_data_rate_to_index(adapter->datarate);
-		lbs_pr_debug(1, "Setting FW for fixed rate 0x%02X\n",
+		lbs_deb_cmd("Setting FW for fixed rate 0x%02X\n",
 		       adapter->datarate);
-	} else if (action == cmd_act_set_tx_auto) {
-		lbs_pr_debug(1, "Setting FW for AUTO rate\n");
+	} else if (cmd_action == cmd_act_set_tx_auto) {
+		lbs_deb_cmd("Setting FW for AUTO rate\n");
 	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -659,8 +634,7 @@
 	struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
 	wlan_adapter *adapter = priv->adapter;
 
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
 			     S_DS_GEN);
 	cmd->command = cpu_to_le16(cmd_mac_multicast_adr);
 
@@ -680,8 +654,8 @@
 	struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
 
 	cmd->command = cpu_to_le16(cmd_802_11_rf_channel);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel)
-				     + S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
+				S_DS_GEN);
 
 	if (option == cmd_opt_802_11_rf_channel_set) {
 		rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
@@ -698,9 +672,8 @@
 	wlan_adapter *adapter = priv->adapter;
 
 	cmd->command = cpu_to_le16(cmd_802_11_rssi);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
-	cmd->params.rssi.N = priv->adapter->bcn_avg_factor;
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
+	cmd->params.rssi.N = cpu_to_le16(priv->adapter->bcn_avg_factor);
 
 	/* reset Beacon SNR/NF/RSSI values */
 	adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
@@ -719,7 +692,7 @@
 {
 	struct wlan_offset_value *offval;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	offval = (struct wlan_offset_value *)pdata_buf;
 
@@ -729,9 +702,8 @@
 			struct cmd_ds_mac_reg_access *macreg;
 
 			cmdptr->size =
-			    cpu_to_le16(sizeof
-					     (struct cmd_ds_mac_reg_access)
-					     + S_DS_GEN);
+			    cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
+					+ S_DS_GEN);
 			macreg =
 			    (struct cmd_ds_mac_reg_access *)&cmdptr->params.
 			    macreg;
@@ -785,7 +757,7 @@
 		break;
 	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -796,8 +768,7 @@
 	wlan_adapter *adapter = priv->adapter;
 
 	cmd->command = cpu_to_le16(cmd_802_11_mac_address);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
 			     S_DS_GEN);
 	cmd->result = 0;
 
@@ -818,12 +789,11 @@
 {
 	struct wlan_ioctl_regrdwr *ea = pdata_buf;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->command = cpu_to_le16(cmd_802_11_eeprom_access);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
-			     S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
+				S_DS_GEN);
 	cmd->result = 0;
 
 	cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
@@ -839,11 +809,10 @@
 			       u16 cmd_action, void *pdata_buf)
 {
 	struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
-	lbs_pr_debug(1, "BT CMD(%d)\n", cmd_action);
+	lbs_deb_cmd("BT CMD(%d)\n", cmd_action);
 
 	cmd->command = cpu_to_le16(cmd_bt_access);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access)
-				     + S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
 	cmd->result = 0;
 	bt_access->action = cpu_to_le16(cmd_action);
 
@@ -861,6 +830,11 @@
 		break;
 	case cmd_act_bt_access_reset:
 		break;
+	case cmd_act_bt_access_set_invert:
+		bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
+		break;
+	case cmd_act_bt_access_get_invert:
+		break;
 	default:
 		break;
 	}
@@ -872,11 +846,10 @@
 			       u16 cmd_action, void *pdata_buf)
 {
 	struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
-	lbs_pr_debug(1, "FWT CMD(%d)\n", cmd_action);
+	lbs_deb_cmd("FWT CMD(%d)\n", cmd_action);
 
 	cmd->command = cpu_to_le16(cmd_fwt_access);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access)
-				     + S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
 	cmd->result = 0;
 
 	if (pdata_buf)
@@ -894,11 +867,10 @@
 				u16 cmd_action, void *pdata_buf)
 {
 	struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh;
-	lbs_pr_debug(1, "FWT CMD(%d)\n", cmd_action);
+	lbs_deb_cmd("FWT CMD(%d)\n", cmd_action);
 
 	cmd->command = cpu_to_le16(cmd_mesh_access);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access)
-				     + S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN);
 	cmd->result = 0;
 
 	if (pdata_buf)
@@ -916,23 +888,23 @@
 	unsigned long flags;
 	struct cmd_ds_command *cmdptr;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	if (!cmdnode) {
-		lbs_pr_debug(1, "QUEUE_CMD: cmdnode is NULL\n");
+		lbs_deb_cmd("QUEUE_CMD: cmdnode is NULL\n");
 		goto done;
 	}
 
 	cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
 	if (!cmdptr) {
-		lbs_pr_debug(1, "QUEUE_CMD: cmdptr is NULL\n");
+		lbs_deb_cmd("QUEUE_CMD: cmdptr is NULL\n");
 		goto done;
 	}
 
 	/* Exit_PS command needs to be queued in the header always. */
 	if (cmdptr->command == cmd_802_11_ps_mode) {
 		struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode;
-		if (psm->action == cmd_subcmd_exit_ps) {
+		if (psm->action == cpu_to_le16(cmd_subcmd_exit_ps)) {
 			if (adapter->psstate != PS_STATE_FULL_POWER)
 				addtail = 0;
 		}
@@ -948,13 +920,12 @@
 
 	spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
-	lbs_pr_debug(1, "QUEUE_CMD: Inserted node=%p, cmd=0x%x in cmdpendingq\n",
+	lbs_deb_cmd("QUEUE_CMD: Inserted node=%p, cmd=0x%x in cmdpendingq\n",
 	       cmdnode,
-	       ((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command);
+	       le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command));
 
 done:
-	LEAVE();
-	return;
+	lbs_deb_leave(LBS_DEB_CMD);
 }
 
 /*
@@ -974,10 +945,10 @@
 	u16 cmdsize;
 	u16 command;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	if (!adapter || !cmdnode) {
-		lbs_pr_debug(1, "DNLD_CMD: adapter = %p, cmdnode = %p\n",
+		lbs_deb_cmd("DNLD_CMD: adapter = %p, cmdnode = %p\n",
 		       adapter, cmdnode);
 		if (cmdnode) {
 			spin_lock_irqsave(&adapter->driver_lock, flags);
@@ -993,7 +964,7 @@
 
 	spin_lock_irqsave(&adapter->driver_lock, flags);
 	if (!cmdptr || !cmdptr->size) {
-		lbs_pr_debug(1, "DNLD_CMD: cmdptr is Null or cmd size is Zero, "
+		lbs_deb_cmd("DNLD_CMD: cmdptr is Null or cmd size is Zero, "
 		       "Not sending\n");
 		__libertas_cleanup_and_insert_cmd(priv, cmdnode);
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
@@ -1004,8 +975,8 @@
 	adapter->cur_cmd = cmdnode;
 	adapter->cur_cmd_retcode = 0;
 	spin_unlock_irqrestore(&adapter->driver_lock, flags);
-	lbs_pr_debug(1, "DNLD_CMD:: Before download, size of cmd = %d\n",
-	       cmdptr->size);
+	lbs_deb_cmd("DNLD_CMD:: Before download, size of cmd = %d\n",
+		    le16_to_cpu(cmdptr->size));
 
 	cmdsize = cmdptr->size;
 
@@ -1014,10 +985,10 @@
 	cmdnode->cmdwaitqwoken = 0;
 	cmdsize = cpu_to_le16(cmdsize);
 
-	ret = libertas_sbi_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
+	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
 
 	if (ret != 0) {
-		lbs_pr_debug(1, "DNLD_CMD: Host to Card failed\n");
+		lbs_deb_cmd("DNLD_CMD: Host to Card failed\n");
 		spin_lock_irqsave(&adapter->driver_lock, flags);
 		__libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
 		adapter->cur_cmd = NULL;
@@ -1026,12 +997,11 @@
 		goto done;
 	}
 
-	lbs_pr_debug(1, "DNLD_CMD: Sent command 0x%x @ %lu\n", command, jiffies);
+	lbs_deb_cmd("DNLD_CMD: Sent command 0x%x @ %lu\n", command, jiffies);
 	lbs_dbg_hex("DNLD_CMD: command", cmdnode->bufvirtualaddr, cmdsize);
 
 	/* Setup the timer after transmit command */
-	if (command == cmd_802_11_scan
-	    || command == cmd_802_11_authenticate
+	if (command == cmd_802_11_scan || command == cmd_802_11_authenticate
 	    || command == cmd_802_11_associate)
 		mod_timer(&adapter->command_timer, jiffies + (10*HZ));
 	else
@@ -1039,8 +1009,8 @@
 
 	ret = 0;
 
-      done:
-	LEAVE();
+done:
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
@@ -1049,17 +1019,16 @@
 {
 	struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	cmd->command = cpu_to_le16(cmd_mac_control);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
 	mac->action = cpu_to_le16(priv->adapter->currentpacketfilter);
 
-	lbs_pr_debug(1, "wlan_cmd_mac_control(): action=0x%X size=%d\n",
-	       mac->action, cmd->size);
+	lbs_deb_cmd("wlan_cmd_mac_control(): action=0x%X size=%d\n",
+		    le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -1093,17 +1062,17 @@
 {
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	ret = libertas_prepare_and_send_command(priv,
 				    cmd_802_11_radio_control,
 				    cmd_act_set,
 				    cmd_option_waitforrsp, 0, NULL);
 
-	lbs_pr_debug(1, "RADIO_SET: on or off: 0x%X, preamble = 0x%X\n",
+	lbs_deb_cmd("RADIO_SET: on or off: 0x%X, preamble = 0x%X\n",
 	       priv->adapter->radioon, priv->adapter->preamble);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
@@ -1111,16 +1080,16 @@
 {
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	lbs_pr_debug(1, "libertas_set_mac_packet_filter value = %x\n",
+	lbs_deb_cmd("libertas_set_mac_packet_filter value = %x\n",
 	       priv->adapter->currentpacketfilter);
 
 	/* Send MAC control command to station */
 	ret = libertas_prepare_and_send_command(priv,
 				    cmd_mac_control, 0, 0, 0, NULL);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
@@ -1146,16 +1115,16 @@
 	struct cmd_ds_command *cmdptr;
 	unsigned long flags;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	if (!adapter) {
-		lbs_pr_debug(1, "PREP_CMD: adapter is Null\n");
+		lbs_deb_cmd("PREP_CMD: adapter is Null\n");
 		ret = -1;
 		goto done;
 	}
 
 	if (adapter->surpriseremoved) {
-		lbs_pr_debug(1, "PREP_CMD: Card is Removed\n");
+		lbs_deb_cmd("PREP_CMD: Card is Removed\n");
 		ret = -1;
 		goto done;
 	}
@@ -1163,7 +1132,7 @@
 	cmdnode = libertas_get_free_cmd_ctrl_node(priv);
 
 	if (cmdnode == NULL) {
-		lbs_pr_debug(1, "PREP_CMD: No free cmdnode\n");
+		lbs_deb_cmd("PREP_CMD: No free cmdnode\n");
 
 		/* Wake up main thread to execute next command */
 		wake_up_interruptible(&priv->mainthread.waitq);
@@ -1175,11 +1144,11 @@
 
 	cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
 
-	lbs_pr_debug(1, "PREP_CMD: Val of cmd ptr=%p, command=0x%X\n",
+	lbs_deb_cmd("PREP_CMD: Val of cmd ptr=%p, command=0x%X\n",
 	       cmdptr, cmd_no);
 
 	if (!cmdptr) {
-		lbs_pr_debug(1, "PREP_CMD: bufvirtualaddr of cmdnode is NULL\n");
+		lbs_deb_cmd("PREP_CMD: bufvirtualaddr of cmdnode is NULL\n");
 		libertas_cleanup_and_insert_cmd(priv, cmdnode);
 		ret = -1;
 		goto done;
@@ -1189,7 +1158,7 @@
 	adapter->seqnum++;
 	cmdptr->seqnum = cpu_to_le16(adapter->seqnum);
 
-	cmdptr->command = cmd_no;
+	cmdptr->command = cpu_to_le16(cmd_no);
 	cmdptr->result = 0;
 
 	switch (cmd_no) {
@@ -1298,13 +1267,13 @@
 		break;
 
 	case cmd_802_11_enable_rsn:
-		ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action);
+		ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
+				pdata_buf);
 		break;
 
 	case cmd_802_11_key_material:
-		ret = wlan_cmd_802_11_key_material(priv, cmdptr,
-						   cmd_action, cmd_oid,
-						   pdata_buf);
+		ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
+				cmd_oid, pdata_buf);
 		break;
 
 	case cmd_802_11_pairwise_tsc:
@@ -1325,9 +1294,8 @@
 	case cmd_802_11_get_afc:
 
 		cmdptr->command = cpu_to_le16(cmd_no);
-		cmdptr->size =
-		    cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
-				     S_DS_GEN);
+		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
+					   S_DS_GEN);
 
 		memmove(&cmdptr->params.afc,
 			pdata_buf, sizeof(struct cmd_ds_802_11_afc));
@@ -1406,29 +1374,26 @@
 
 	case cmd_get_tsf:
 		cmdptr->command = cpu_to_le16(cmd_get_tsf);
-		cmdptr->size =
-		    cpu_to_le16(sizeof(struct cmd_ds_get_tsf)
-				     + S_DS_GEN);
+		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
+					   S_DS_GEN);
 		ret = 0;
 		break;
 	case cmd_802_11_tx_rate_query:
-		cmdptr->command =
-		    cpu_to_le16(cmd_802_11_tx_rate_query);
-		cmdptr->size =
-		    cpu_to_le16(sizeof(struct cmd_tx_rate_query) +
-				     S_DS_GEN);
+		cmdptr->command = cpu_to_le16(cmd_802_11_tx_rate_query);
+		cmdptr->size = cpu_to_le16(sizeof(struct cmd_tx_rate_query) +
+					   S_DS_GEN);
 		adapter->txrate = 0;
 		ret = 0;
 		break;
 	default:
-		lbs_pr_debug(1, "PREP_CMD: unknown command- %#x\n", cmd_no);
+		lbs_deb_cmd("PREP_CMD: unknown command- %#x\n", cmd_no);
 		ret = -1;
 		break;
 	}
 
 	/* return error, since the command preparation failed */
 	if (ret != 0) {
-		lbs_pr_debug(1, "PREP_CMD: command preparation failed\n");
+		lbs_deb_cmd("PREP_CMD: command preparation failed\n");
 		libertas_cleanup_and_insert_cmd(priv, cmdnode);
 		ret = -1;
 		goto done;
@@ -1441,7 +1406,7 @@
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	if (wait_option & cmd_option_waitforrsp) {
-		lbs_pr_debug(1, "PREP_CMD: Wait for CMD response\n");
+		lbs_deb_cmd("PREP_CMD: Wait for CMD response\n");
 		might_sleep();
 		wait_event_interruptible(cmdnode->cmdwait_q,
 					 cmdnode->cmdwaitqwoken);
@@ -1449,7 +1414,7 @@
 
 	spin_lock_irqsave(&adapter->driver_lock, flags);
 	if (adapter->cur_cmd_retcode) {
-		lbs_pr_debug(1, "PREP_CMD: command failed with return code=%d\n",
+		lbs_deb_cmd("PREP_CMD: command failed with return code=%d\n",
 		       adapter->cur_cmd_retcode);
 		adapter->cur_cmd_retcode = 0;
 		ret = -1;
@@ -1457,9 +1422,10 @@
 	spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
 done:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(libertas_prepare_and_send_command);
 
 /**
  *  @brief This function allocates the command buffer and link
@@ -1477,33 +1443,29 @@
 	u8 *ptempvirtualaddr;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	/* Allocate and initialize cmdCtrlNode */
 	ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
 
-	if (!(tempcmd_array = kmalloc(ulbufsize, GFP_KERNEL))) {
-		lbs_pr_debug(1,
+	if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) {
+		lbs_deb_cmd(
 		       "ALLOC_CMD_BUF: failed to allocate tempcmd_array\n");
 		ret = -1;
 		goto done;
 	}
-
 	adapter->cmd_array = tempcmd_array;
-	memset(adapter->cmd_array, 0, ulbufsize);
 
 	/* Allocate and initialize command buffers */
 	ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
 	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
-		if (!(ptempvirtualaddr = kmalloc(ulbufsize, GFP_KERNEL))) {
-			lbs_pr_debug(1,
+		if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) {
+			lbs_deb_cmd(
 			       "ALLOC_CMD_BUF: ptempvirtualaddr: out of memory\n");
 			ret = -1;
 			goto done;
 		}
 
-		memset(ptempvirtualaddr, 0, ulbufsize);
-
 		/* Update command buffer virtual */
 		tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr;
 	}
@@ -1514,8 +1476,9 @@
 	}
 
 	ret = 0;
-      done:
-	LEAVE();
+
+done:
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
@@ -1527,16 +1490,16 @@
  */
 int libertas_free_cmd_buffer(wlan_private * priv)
 {
-	u32 ulbufsize;
+	u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */
 	unsigned int i;
 	struct cmd_ctrl_node *tempcmd_array;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	/* need to check if cmd array is allocated or not */
 	if (adapter->cmd_array == NULL) {
-		lbs_pr_debug(1, "FREE_CMD_BUF: cmd_array is Null\n");
+		lbs_deb_cmd("FREE_CMD_BUF: cmd_array is Null\n");
 		goto done;
 	}
 
@@ -1546,7 +1509,7 @@
 	ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
 	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
 		if (tempcmd_array[i].bufvirtualaddr) {
-			lbs_pr_debug(1, "Free all the array\n");
+			lbs_deb_cmd("Free all the array\n");
 			kfree(tempcmd_array[i].bufvirtualaddr);
 			tempcmd_array[i].bufvirtualaddr = NULL;
 		}
@@ -1554,13 +1517,13 @@
 
 	/* Release cmd_ctrl_node */
 	if (adapter->cmd_array) {
-		lbs_pr_debug(1, "Free cmd_array\n");
+		lbs_deb_cmd("Free cmd_array\n");
 		kfree(adapter->cmd_array);
 		adapter->cmd_array = NULL;
 	}
 
 done:
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -1586,16 +1549,18 @@
 		tempnode = (struct cmd_ctrl_node *)adapter->cmdfreeq.next;
 		list_del((struct list_head *)tempnode);
 	} else {
-		lbs_pr_debug(1, "GET_CMD_NODE: cmd_ctrl_node is not available\n");
+		lbs_deb_cmd("GET_CMD_NODE: cmd_ctrl_node is not available\n");
 		tempnode = NULL;
 	}
 
 	spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
 	if (tempnode) {
+		/*
 		lbs_pr_debug(3, "GET_CMD_NODE: cmdCtrlNode available\n");
 		lbs_pr_debug(3, "GET_CMD_NODE: cmdCtrlNode Address = %p\n",
 		       tempnode);
+		*/
 		cleanup_cmdnode(tempnode);
 	}
 
@@ -1638,7 +1603,7 @@
 		    struct cmd_ctrl_node *ptempnode,
 		    u32 cmd_oid, u16 wait_option, void *pdata_buf)
 {
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	if (!ptempnode)
 		return;
@@ -1647,7 +1612,7 @@
 	ptempnode->wait_option = wait_option;
 	ptempnode->pdata_buf = pdata_buf;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 }
 
 /**
@@ -1666,7 +1631,7 @@
 	unsigned long flags;
 	int ret = 0;
 
-	lbs_pr_debug(1, "libertas_execute_next_command\n");
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	spin_lock_irqsave(&adapter->driver_lock, flags);
 
@@ -1685,23 +1650,24 @@
 	spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
 	if (cmdnode) {
-		lbs_pr_debug(1,
+		lbs_deb_cmd(
 		       "EXEC_NEXT_CMD: Got next command from cmdpendingq\n");
 		cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
 
 		if (is_command_allowed_in_ps(cmdptr->command)) {
-			if ((adapter->psstate == PS_STATE_SLEEP)
-			    || (adapter->psstate == PS_STATE_PRE_SLEEP)
-			    ) {
-				lbs_pr_debug(1,
+			if ((adapter->psstate == PS_STATE_SLEEP) ||
+			    (adapter->psstate == PS_STATE_PRE_SLEEP)) {
+				lbs_deb_cmd(
 				       "EXEC_NEXT_CMD: Cannot send cmd 0x%x in psstate %d\n",
-				       cmdptr->command, adapter->psstate);
+				       le16_to_cpu(cmdptr->command),
+				       adapter->psstate);
 				ret = -1;
 				goto done;
 			}
-			lbs_pr_debug(1, "EXEC_NEXT_CMD: OK to send command "
+			lbs_deb_cmd("EXEC_NEXT_CMD: OK to send command "
 			       "0x%x in psstate %d\n",
-			       cmdptr->command, adapter->psstate);
+				    le16_to_cpu(cmdptr->command),
+				    adapter->psstate);
 		} else if (adapter->psstate != PS_STATE_FULL_POWER) {
 			/*
 			 * 1. Non-PS command:
@@ -1737,12 +1703,12 @@
 				struct cmd_ds_802_11_ps_mode *psm =
 				    &cmdptr->params.psmode;
 
-				lbs_pr_debug(1,
+				lbs_deb_cmd(
 				       "EXEC_NEXT_CMD: PS cmd- action=0x%x\n",
 				       psm->action);
 				if (psm->action !=
 				    cpu_to_le16(cmd_subcmd_exit_ps)) {
-					lbs_pr_debug(1,
+					lbs_deb_cmd(
 					       "EXEC_NEXT_CMD: Ignore Enter PS cmd\n");
 					list_del((struct list_head *)cmdnode);
 					libertas_cleanup_and_insert_cmd(priv, cmdnode);
@@ -1751,10 +1717,9 @@
 					goto done;
 				}
 
-				if ((adapter->psstate == PS_STATE_SLEEP)
-				    || (adapter->psstate == PS_STATE_PRE_SLEEP)
-				    ) {
-					lbs_pr_debug(1,
+				if ((adapter->psstate == PS_STATE_SLEEP) ||
+				    (adapter->psstate == PS_STATE_PRE_SLEEP)) {
+					lbs_deb_cmd(
 					       "EXEC_NEXT_CMD: Ignore ExitPS cmd in sleep\n");
 					list_del((struct list_head *)cmdnode);
 					libertas_cleanup_and_insert_cmd(priv, cmdnode);
@@ -1764,13 +1729,13 @@
 					goto done;
 				}
 
-				lbs_pr_debug(1,
+				lbs_deb_cmd(
 				       "EXEC_NEXT_CMD: Sending Exit_PS down...\n");
 			}
 		}
 		list_del((struct list_head *)cmdnode);
-		lbs_pr_debug(1, "EXEC_NEXT_CMD: Sending 0x%04X command\n",
-		       cmdptr->command);
+		lbs_deb_cmd("EXEC_NEXT_CMD: Sending 0x%04X command\n",
+			    le16_to_cpu(cmdptr->command));
 		DownloadcommandToStation(priv, cmdnode);
 	} else {
 		/*
@@ -1780,18 +1745,18 @@
 		if ((adapter->psmode != wlan802_11powermodecam) &&
 		    (adapter->psstate == PS_STATE_FULL_POWER) &&
 		    (adapter->connect_status == libertas_connected)) {
-			if (adapter->secinfo.WPAenabled
-			    || adapter->secinfo.WPA2enabled) {
+			if (adapter->secinfo.WPAenabled ||
+			    adapter->secinfo.WPA2enabled) {
 				/* check for valid WPA group keys */
-				if (adapter->wpa_mcast_key.len
-				    || adapter->wpa_unicast_key.len) {
-					lbs_pr_debug(1,
+				if (adapter->wpa_mcast_key.len ||
+				    adapter->wpa_unicast_key.len) {
+					lbs_deb_cmd(
 					       "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
 					       " go back to PS_SLEEP");
 					libertas_ps_sleep(priv, 0);
 				}
 			} else {
-				lbs_pr_debug(1,
+				lbs_deb_cmd(
 				       "EXEC_NEXT_CMD: command PendQ is empty,"
 				       " go back to PS_SLEEP");
 				libertas_ps_sleep(priv, 0);
@@ -1801,6 +1766,7 @@
 
 	ret = 0;
 done:
+	lbs_deb_leave(LBS_DEB_CMD);
 	return ret;
 }
 
@@ -1809,7 +1775,7 @@
 	union iwreq_data iwrq;
 	u8 buf[50];
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	memset(&iwrq, 0, sizeof(union iwreq_data));
 	memset(buf, 0, sizeof(buf));
@@ -1819,15 +1785,13 @@
 	iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
 
 	/* Send Event to upper layer */
-	lbs_pr_debug(1, "Event Indication string = %s\n",
-	       (char *)buf);
-	lbs_pr_debug(1, "Event Indication String length = %d\n", iwrq.data.length);
+	lbs_deb_cmd("Event Indication string = %s\n", (char *)buf);
+	lbs_deb_cmd("Event Indication String length = %d\n", iwrq.data.length);
 
-	lbs_pr_debug(1, "Sending wireless event IWEVCUSTOM for %s\n", str);
-	wireless_send_event(priv->wlan_dev.netdev, IWEVCUSTOM, &iwrq, buf);
+	lbs_deb_cmd("Sending wireless event IWEVCUSTOM for %s\n", str);
+	wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
 
-	LEAVE();
-	return;
+	lbs_deb_leave(LBS_DEB_CMD);
 }
 
 static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
@@ -1836,19 +1800,19 @@
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	lbs_pr_debug(1, "SEND_SLEEPC_CMD: Before download, size of cmd = %d\n",
+	lbs_deb_cmd("SEND_SLEEPC_CMD: Before download, size of cmd = %d\n",
 	       size);
 
 	lbs_dbg_hex("SEND_SLEEPC_CMD: Sleep confirm command", cmdptr, size);
 
-	ret = libertas_sbi_host_to_card(priv, MVMS_CMD, cmdptr, size);
-	priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+	ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
+	priv->dnld_sent = DNLD_RES_RECEIVED;
 
 	spin_lock_irqsave(&adapter->driver_lock, flags);
 	if (adapter->intcounter || adapter->currenttxskb)
-		lbs_pr_debug(1, "SEND_SLEEPC_CMD: intcounter=%d currenttxskb=%p\n",
+		lbs_deb_cmd("SEND_SLEEPC_CMD: intcounter=%d currenttxskb=%p\n",
 		       adapter->intcounter, adapter->currenttxskb);
 	spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
@@ -1860,23 +1824,22 @@
 		if (!adapter->intcounter) {
 			adapter->psstate = PS_STATE_SLEEP;
 		} else {
-			lbs_pr_debug(1, "SEND_SLEEPC_CMD: After sent,IntC=%d\n",
+			lbs_deb_cmd("SEND_SLEEPC_CMD: After sent,IntC=%d\n",
 			       adapter->intcounter);
 		}
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
-		lbs_pr_debug(1, "SEND_SLEEPC_CMD: Sent Confirm Sleep command\n");
-		lbs_pr_debug(1, "+");
+		lbs_deb_cmd("SEND_SLEEPC_CMD: Sent Confirm Sleep command\n");
+		lbs_deb_cmd("+");
 	}
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
 void libertas_ps_sleep(wlan_private * priv, int wait_option)
 {
-
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	/*
 	 * PS is currently supported only in Infrastructure mode
@@ -1886,8 +1849,7 @@
 	libertas_prepare_and_send_command(priv, cmd_802_11_ps_mode,
 			      cmd_subcmd_enter_ps, wait_option, 0, NULL);
 
-	LEAVE();
-	return;
+	lbs_deb_leave(LBS_DEB_CMD);
 }
 
 /**
@@ -1899,20 +1861,19 @@
  */
 void libertas_ps_wakeup(wlan_private * priv, int wait_option)
 {
-	enum WLAN_802_11_POWER_MODE Localpsmode;
+	__le32 Localpsmode;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	Localpsmode = wlan802_11powermodecam;
+	Localpsmode = cpu_to_le32(wlan802_11powermodecam);
 
-	lbs_pr_debug(1, "Exit_PS: Localpsmode = %d\n", Localpsmode);
+	lbs_deb_cmd("Exit_PS: Localpsmode = %d\n", wlan802_11powermodecam);
 
 	libertas_prepare_and_send_command(priv, cmd_802_11_ps_mode,
 			      cmd_subcmd_exit_ps,
 			      wait_option, 0, &Localpsmode);
 
-	LEAVE();
-	return;
+	lbs_deb_leave(LBS_DEB_CMD);
 }
 
 /**
@@ -1929,31 +1890,31 @@
 	wlan_adapter *adapter = priv->adapter;
 	u8 allowed = 1;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	if (priv->wlan_dev.dnld_sent) {
+	if (priv->dnld_sent) {
 		allowed = 0;
-		lbs_pr_debug(1, "D");
+		lbs_deb_cmd("D");
 	}
 
 	spin_lock_irqsave(&adapter->driver_lock, flags);
 	if (adapter->cur_cmd) {
 		allowed = 0;
-		lbs_pr_debug(1, "C");
+		lbs_deb_cmd("C");
 	}
 	if (adapter->intcounter > 0) {
 		allowed = 0;
-		lbs_pr_debug(1, "I%d", adapter->intcounter);
+		lbs_deb_cmd("I%d", adapter->intcounter);
 	}
 	spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
 	if (allowed) {
-		lbs_pr_debug(1, "Sending libertas_ps_confirm_sleep\n");
+		lbs_deb_cmd("Sending libertas_ps_confirm_sleep\n");
 		sendconfirmsleep(priv, (u8 *) & adapter->libertas_ps_confirm_sleep,
 				 sizeof(struct PS_CMD_ConfirmSleep));
 	} else {
-		lbs_pr_debug(1, "Sleep Confirm has been delayed\n");
+		lbs_deb_cmd("Sleep Confirm has been delayed\n");
 	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_CMD);
 }
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index c864540..6ac0d47 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -9,7 +9,6 @@
 #include <net/iw_handler.h>
 
 #include "host.h"
-#include "sbi.h"
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
@@ -32,7 +31,7 @@
 	if (adapter->connect_status != libertas_connected)
 		return;
 
-	lbs_pr_debug(1, "Handles disconnect event.\n");
+	lbs_deb_cmd("Handles disconnect event.\n");
 
 	memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -43,15 +42,15 @@
 	 */
 
 	msleep_interruptible(1000);
-	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
 
 	/* Free Tx and Rx packets */
 	kfree_skb(priv->adapter->currenttxskb);
 	priv->adapter->currenttxskb = NULL;
 
 	/* report disconnect to upper layer */
-	netif_stop_queue(priv->wlan_dev.netdev);
-	netif_carrier_off(priv->wlan_dev.netdev);
+	netif_stop_queue(priv->dev);
+	netif_carrier_off(priv->dev);
 
 	/* reset SNR/NF/RSSI values */
 	memset(adapter->SNR, 0x00, sizeof(adapter->SNR));
@@ -62,35 +61,32 @@
 	adapter->nextSNRNF = 0;
 	adapter->numSNRNF = 0;
 	adapter->rxpd_rate = 0;
-	lbs_pr_debug(1, "Current SSID=%s, ssid length=%u\n",
-	       adapter->curbssparams.ssid.ssid,
-	       adapter->curbssparams.ssid.ssidlength);
-	lbs_pr_debug(1, "Previous SSID=%s, ssid length=%u\n",
-	       adapter->previousssid.ssid, adapter->previousssid.ssidlength);
-
-	/* reset internal flags */
-	adapter->secinfo.WPAenabled = 0;
-	adapter->secinfo.WPA2enabled = 0;
-	adapter->wpa_ie_len = 0;
+	lbs_deb_cmd("Current SSID='%s', ssid length=%u\n",
+	            escape_essid(adapter->curbssparams.ssid,
+	                         adapter->curbssparams.ssid_len),
+	            adapter->curbssparams.ssid_len);
+	lbs_deb_cmd("Previous SSID='%s', ssid length=%u\n",
+	            escape_essid(adapter->prev_ssid, adapter->prev_ssid_len),
+	            adapter->prev_ssid_len);
 
 	adapter->connect_status = libertas_disconnected;
 
-	/*
-	 * memorize the previous SSID and BSSID
-	 * it could be used for re-assoc
-	 */
-	memcpy(&adapter->previousssid,
-	       &adapter->curbssparams.ssid, sizeof(struct WLAN_802_11_SSID));
-	memcpy(adapter->previousbssid,
-	       adapter->curbssparams.bssid, ETH_ALEN);
+	/* Save previous SSID and BSSID for possible reassociation */
+	memcpy(&adapter->prev_ssid, &adapter->curbssparams.ssid,
+	       IW_ESSID_MAX_SIZE);
+	adapter->prev_ssid_len = adapter->curbssparams.ssid_len;
+	memcpy(adapter->prev_bssid, adapter->curbssparams.bssid, ETH_ALEN);
 
-	/* need to erase the current SSID and BSSID info */
-	adapter->pattemptedbssdesc = NULL;
-	memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
+	/* Clear out associated SSID and BSSID since connection is
+	 * no longer valid.
+	 */
+	memset(&adapter->curbssparams.bssid, 0, ETH_ALEN);
+	memset(&adapter->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
+	adapter->curbssparams.ssid_len = 0;
 
 	if (adapter->psstate != PS_STATE_FULL_POWER) {
 		/* make firmware to exit PS mode */
-		lbs_pr_debug(1, "Disconnected, so exit PS mode.\n");
+		lbs_deb_cmd("Disconnected, so exit PS mode.\n");
 		libertas_ps_wakeup(priv, 0);
 	}
 }
@@ -122,55 +118,45 @@
 static int wlan_ret_reg_access(wlan_private * priv,
 			       u16 type, struct cmd_ds_command *resp)
 {
+	int ret = 0;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	switch (type) {
 	case cmd_ret_mac_reg_access:
 		{
-			struct cmd_ds_mac_reg_access *reg;
+			struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
 
-			reg =
-			    (struct cmd_ds_mac_reg_access *)&resp->params.
-			    macreg;
-
-			adapter->offsetvalue.offset = reg->offset;
-			adapter->offsetvalue.value = reg->value;
+			adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
+			adapter->offsetvalue.value = le32_to_cpu(reg->value);
 			break;
 		}
 
 	case cmd_ret_bbp_reg_access:
 		{
-			struct cmd_ds_bbp_reg_access *reg;
-			reg =
-			    (struct cmd_ds_bbp_reg_access *)&resp->params.
-			    bbpreg;
+			struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
 
-			adapter->offsetvalue.offset = reg->offset;
+			adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
 			adapter->offsetvalue.value = reg->value;
 			break;
 		}
 
 	case cmd_ret_rf_reg_access:
 		{
-			struct cmd_ds_rf_reg_access *reg;
-			reg =
-			    (struct cmd_ds_rf_reg_access *)&resp->params.
-			    rfreg;
+			struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
 
-			adapter->offsetvalue.offset = reg->offset;
+			adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
 			adapter->offsetvalue.value = reg->value;
 			break;
 		}
 
 	default:
-		LEAVE();
-		return -1;
+		ret = -1;
 	}
 
-	LEAVE();
-	return 0;
+	lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
 }
 
 static int wlan_ret_get_hw_spec(wlan_private * priv,
@@ -181,19 +167,20 @@
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	adapter->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
 
-	adapter->fwreleasenumber = hwspec->fwreleasenumber;
+	memcpy(adapter->fwreleasenumber, hwspec->fwreleasenumber, 4);
 
-	lbs_pr_debug(1, "GET_HW_SPEC: FWReleaseVersion- 0x%X\n",
-	       adapter->fwreleasenumber);
-	lbs_pr_debug(1, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
+	lbs_deb_cmd("GET_HW_SPEC: FWReleaseVersion- %u.%u.%u.p%u\n",
+		    adapter->fwreleasenumber[2], adapter->fwreleasenumber[1],
+		    adapter->fwreleasenumber[0], adapter->fwreleasenumber[3]);
+	lbs_deb_cmd("GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
 	       hwspec->permanentaddr[0], hwspec->permanentaddr[1],
 	       hwspec->permanentaddr[2], hwspec->permanentaddr[3],
 	       hwspec->permanentaddr[4], hwspec->permanentaddr[5]);
-	lbs_pr_debug(1, "GET_HW_SPEC: hwifversion=0x%X  version=0x%X\n",
+	lbs_deb_cmd("GET_HW_SPEC: hwifversion=0x%X  version=0x%X\n",
 	       hwspec->hwifversion, hwspec->version);
 
 	adapter->regioncode = le16_to_cpu(hwspec->regioncode);
@@ -210,17 +197,15 @@
 	if (i >= MRVDRV_MAX_REGION_CODE) {
 		adapter->regioncode = 0x10;
 		adapter->regiontableindex = 0;
-		lbs_pr_info(
-		       "unidentified region code, use the default (USA)\n");
+		lbs_pr_info("unidentified region code; using the default (USA)\n");
 	}
 
-	if (adapter->current_addr[0] == 0xff) {
-		memmove(adapter->current_addr, hwspec->permanentaddr,
-			ETH_ALEN);
-	}
+	if (adapter->current_addr[0] == 0xff)
+		memmove(adapter->current_addr, hwspec->permanentaddr, ETH_ALEN);
 
-	memcpy(priv->wlan_dev.netdev->dev_addr, adapter->current_addr, ETH_ALEN);
-	memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
+	memcpy(priv->dev->dev_addr, adapter->current_addr, ETH_ALEN);
+	if (priv->mesh_dev)
+		memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
 
 	if (libertas_set_regiontable(priv, adapter->regioncode, 0)) {
 		ret = -1;
@@ -232,8 +217,8 @@
 		goto done;
 	}
 
-      done:
-	LEAVE();
+done:
+	lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
@@ -243,19 +228,21 @@
 	struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	lbs_pr_debug(1, "error=%x offset=%x stabletime=%x calcontrol=%x\n"
-	       " extsleepclk=%x\n", sp->error, sp->offset,
-	       sp->stabletime, sp->calcontrol, sp->externalsleepclk);
+	lbs_deb_cmd("error=%x offset=%x stabletime=%x calcontrol=%x\n"
+		    " extsleepclk=%x\n", le16_to_cpu(sp->error),
+		    le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
+		    sp->calcontrol, sp->externalsleepclk);
+
 	adapter->sp.sp_error = le16_to_cpu(sp->error);
 	adapter->sp.sp_offset = le16_to_cpu(sp->offset);
 	adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
-	adapter->sp.sp_calcontrol = le16_to_cpu(sp->calcontrol);
-	adapter->sp.sp_extsleepclk = le16_to_cpu(sp->externalsleepclk);
+	adapter->sp.sp_calcontrol = sp->calcontrol;
+	adapter->sp.sp_extsleepclk = sp->externalsleepclk;
 	adapter->sp.sp_reserved = le16_to_cpu(sp->reserved);
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -281,42 +268,38 @@
 	u16 oid = le16_to_cpu(smib->oid);
 	u16 querytype = le16_to_cpu(smib->querytype);
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	lbs_pr_debug(1, "SNMP_RESP: value of the oid = %x, querytype=%x\n", oid,
+	lbs_deb_cmd("SNMP_RESP: value of the oid = %x, querytype=%x\n", oid,
 	       querytype);
-	lbs_pr_debug(1, "SNMP_RESP: Buf size  = %x\n",
-	       le16_to_cpu(smib->bufsize));
+	lbs_deb_cmd("SNMP_RESP: Buf size  = %x\n", le16_to_cpu(smib->bufsize));
 
 	if (querytype == cmd_act_get) {
 		switch (oid) {
 		case fragthresh_i:
 			priv->adapter->fragthsd =
-			    le16_to_cpu(*
-					     ((unsigned short *)(smib->value)));
-			lbs_pr_debug(1, "SNMP_RESP: fragthsd =%u\n",
-			       priv->adapter->fragthsd);
+				le16_to_cpu(*((__le16 *)(smib->value)));
+			lbs_deb_cmd("SNMP_RESP: fragthsd =%u\n",
+				    priv->adapter->fragthsd);
 			break;
 		case rtsthresh_i:
 			priv->adapter->rtsthsd =
-			    le16_to_cpu(*
-					     ((unsigned short *)(smib->value)));
-			lbs_pr_debug(1, "SNMP_RESP: rtsthsd =%u\n",
-			       priv->adapter->rtsthsd);
+				le16_to_cpu(*((__le16 *)(smib->value)));
+			lbs_deb_cmd("SNMP_RESP: rtsthsd =%u\n",
+				    priv->adapter->rtsthsd);
 			break;
 		case short_retrylim_i:
 			priv->adapter->txretrycount =
-			    le16_to_cpu(*
-					     ((unsigned short *)(smib->value)));
-			lbs_pr_debug(1, "SNMP_RESP: txretrycount =%u\n",
-			       priv->adapter->rtsthsd);
+				le16_to_cpu(*((__le16 *)(smib->value)));
+			lbs_deb_cmd("SNMP_RESP: txretrycount =%u\n",
+				    priv->adapter->rtsthsd);
 			break;
 		default:
 			break;
 		}
 	}
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -328,7 +311,7 @@
 	wlan_adapter *adapter = priv->adapter;
 	u16 action = le16_to_cpu(pkeymaterial->action);
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	/* Copy the returned key to driver private data */
 	if (action == cmd_act_get) {
@@ -371,7 +354,7 @@
 		}
 	}
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -381,11 +364,11 @@
 	struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	memcpy(adapter->current_addr, macadd->macadd, ETH_ALEN);
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -395,13 +378,13 @@
 	struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	adapter->txpowerlevel = le16_to_cpu(rtp->currentlevel);
 
-	lbs_pr_debug(1, "Current TxPower Level = %d\n", adapter->txpowerlevel);
+	lbs_deb_cmd("Current TxPower Level = %d\n", adapter->txpowerlevel);
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -413,14 +396,12 @@
 	u16 action = le16_to_cpu(pAntenna->action);
 
 	if (action == cmd_act_get_rx)
-		adapter->rxantennamode =
-		    le16_to_cpu(pAntenna->antennamode);
+		adapter->rxantennamode = le16_to_cpu(pAntenna->antennamode);
 
 	if (action == cmd_act_get_tx)
-		adapter->txantennamode =
-		    le16_to_cpu(pAntenna->antennamode);
+		adapter->txantennamode = le16_to_cpu(pAntenna->antennamode);
 
-	lbs_pr_debug(1, "RF_ANT_RESP: action = 0x%x, mode = 0x%04x\n",
+	lbs_deb_cmd("RF_ANT_RESP: action = 0x%x, mode = 0x%04x\n",
 	       action, le16_to_cpu(pAntenna->antennamode));
 
 	return 0;
@@ -429,19 +410,17 @@
 static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
 					      struct cmd_ds_command *resp)
 {
-	struct cmd_ds_802_11_rate_adapt_rateset *rates =
-	    &resp->params.rateset;
+	struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	if (rates->action == cmd_act_get) {
-		adapter->enablehwauto = rates->enablehwauto;
-		adapter->ratebitmap = rates->bitmap;
+		adapter->enablehwauto = le16_to_cpu(rates->enablehwauto);
+		adapter->ratebitmap = le16_to_cpu(rates->bitmap);
 	}
 
-	LEAVE();
-
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -452,43 +431,42 @@
 	wlan_adapter *adapter = priv->adapter;
 	u8 dot11datarate;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	lbs_dbg_hex("DATA_RATE_RESP: data_rate- ",
 		(u8 *) pdatarate, sizeof(struct cmd_ds_802_11_data_rate));
 
 	dot11datarate = pdatarate->datarate[0];
-	if (pdatarate->action == cmd_act_get_tx_rate) {
+	if (pdatarate->action == cpu_to_le16(cmd_act_get_tx_rate)) {
 		memcpy(adapter->libertas_supported_rates, pdatarate->datarate,
 		       sizeof(adapter->libertas_supported_rates));
 	}
 	adapter->datarate = libertas_index_to_data_rate(dot11datarate);
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
 static int wlan_ret_802_11_rf_channel(wlan_private * priv,
 				      struct cmd_ds_command *resp)
 {
-	struct cmd_ds_802_11_rf_channel *rfchannel =
-	    &resp->params.rfchannel;
+	struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
 	wlan_adapter *adapter = priv->adapter;
 	u16 action = le16_to_cpu(rfchannel->action);
 	u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
 	if (action == cmd_opt_802_11_rf_channel_get
 	    && adapter->curbssparams.channel != newchannel) {
-		lbs_pr_debug(1, "channel Switch: %d to %d\n",
+		lbs_deb_cmd("channel Switch: %d to %d\n",
 		       adapter->curbssparams.channel, newchannel);
 
 		/* Update the channel again */
 		adapter->curbssparams.channel = newchannel;
 	}
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -500,12 +478,10 @@
 
 	/* store the non average value */
 	adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
-	adapter->NF[TYPE_BEACON][TYPE_NOAVG] =
-	    le16_to_cpu(rssirsp->noisefloor);
+	adapter->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
 
 	adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
-	adapter->NF[TYPE_BEACON][TYPE_AVG] =
-	    le16_to_cpu(rssirsp->avgnoisefloor);
+	adapter->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
 
 	adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
 	    CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
@@ -515,7 +491,7 @@
 	    CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
 		     adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
 
-	lbs_pr_debug(1, "Beacon RSSI value = 0x%x\n",
+	lbs_deb_cmd("Beacon RSSI value = 0x%x\n",
 	       adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
 
 	return 0;
@@ -528,11 +504,11 @@
 	struct wlan_ioctl_regrdwr *pbuf;
 	pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom;
 
-	lbs_pr_debug(1, "eeprom read len=%x\n",
+	lbs_deb_cmd("eeprom read len=%x\n",
 	       le16_to_cpu(resp->params.rdeeprom.bytecount));
 	if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
 		pbuf->NOB = 0;
-		lbs_pr_debug(1, "eeprom read return length is too big\n");
+		lbs_deb_cmd("eeprom read return length is too big\n");
 		return -1;
 	}
 	pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
@@ -549,17 +525,33 @@
 static int wlan_ret_get_log(wlan_private * priv,
 			    struct cmd_ds_command *resp)
 {
-	struct cmd_ds_802_11_get_log *logmessage =
-	    (struct cmd_ds_802_11_get_log *)&resp->params.glog;
+	struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	/* TODO Convert it to Big Endian before copy */
-	memcpy(&adapter->logmsg, logmessage,
-	       sizeof(struct cmd_ds_802_11_get_log));
+	/* Stored little-endian */
+	memcpy(&adapter->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_CMD);
+	return 0;
+}
+
+static int libertas_ret_802_11_enable_rsn(wlan_private * priv,
+                                          struct cmd_ds_command *resp)
+{
+	struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
+	wlan_adapter *adapter = priv->adapter;
+	u32 * pdata_buf = adapter->cur_cmd->pdata_buf;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	if (enable_rsn->action == cpu_to_le16(cmd_act_get)) {
+		if (pdata_buf)
+			*pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
+	}
+
+	lbs_deb_enter(LBS_DEB_CMD);
 	return 0;
 }
 
@@ -620,8 +612,7 @@
 	case cmd_ret_802_11_set_afc:
 	case cmd_ret_802_11_get_afc:
 		spin_lock_irqsave(&adapter->driver_lock, flags);
-		memmove(adapter->cur_cmd->pdata_buf,
-			&resp->params.afc,
+		memmove(adapter->cur_cmd->pdata_buf, &resp->params.afc,
 			sizeof(struct cmd_ds_802_11_afc));
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
@@ -637,7 +628,10 @@
 	case cmd_ret_802_11_authenticate:
 	case cmd_ret_802_11_radio_control:
 	case cmd_ret_802_11_beacon_stop:
+		break;
+
 	case cmd_ret_802_11_enable_rsn:
+		ret = libertas_ret_802_11_enable_rsn(priv, resp);
 		break;
 
 	case cmd_ret_802_11_data_rate:
@@ -663,7 +657,7 @@
 		break;
 
 	case cmd_ret_802_11_key_material:
-		lbs_pr_debug(1, "CMD_RESP: KEY_MATERIAL command response\n");
+		lbs_deb_cmd("CMD_RESP: KEY_MATERIAL command response\n");
 		ret = wlan_ret_802_11_key_material(priv, resp);
 		break;
 
@@ -687,22 +681,19 @@
 
 	case cmd_ret_802_11_tpc_cfg:
 		spin_lock_irqsave(&adapter->driver_lock, flags);
-		memmove(adapter->cur_cmd->pdata_buf,
-			&resp->params.tpccfg,
+		memmove(adapter->cur_cmd->pdata_buf, &resp->params.tpccfg,
 			sizeof(struct cmd_ds_802_11_tpc_cfg));
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
 		break;
 	case cmd_ret_802_11_led_gpio_ctrl:
 		spin_lock_irqsave(&adapter->driver_lock, flags);
-		memmove(adapter->cur_cmd->pdata_buf,
-			&resp->params.ledgpio,
+		memmove(adapter->cur_cmd->pdata_buf, &resp->params.ledgpio,
 			sizeof(struct cmd_ds_802_11_led_ctrl));
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
 		break;
 	case cmd_ret_802_11_pwr_cfg:
 		spin_lock_irqsave(&adapter->driver_lock, flags);
-		memmove(adapter->cur_cmd->pdata_buf,
-			&resp->params.pwrcfg,
+		memmove(adapter->cur_cmd->pdata_buf, &resp->params.pwrcfg,
 			sizeof(struct cmd_ds_802_11_pwr_cfg));
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
@@ -724,23 +715,21 @@
 	case cmd_ret_fwt_access:
 		spin_lock_irqsave(&adapter->driver_lock, flags);
 		if (adapter->cur_cmd->pdata_buf)
-			memcpy(adapter->cur_cmd->pdata_buf,
-			       &resp->params.fwt,
-				sizeof(resp->params.fwt));
+			memcpy(adapter->cur_cmd->pdata_buf, &resp->params.fwt,
+			       sizeof(resp->params.fwt));
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
 		break;
 	case cmd_ret_mesh_access:
 		if (adapter->cur_cmd->pdata_buf)
-			memcpy(adapter->cur_cmd->pdata_buf,
-			       &resp->params.mesh,
+			memcpy(adapter->cur_cmd->pdata_buf, &resp->params.mesh,
 			       sizeof(resp->params.mesh));
 		break;
 	case cmd_rte_802_11_tx_rate_query:
 		priv->adapter->txrate = resp->params.txrate.txrate;
 		break;
 	default:
-		lbs_pr_debug(1, "CMD_RESP: Unknown command response %#x\n",
-		       resp->command);
+		lbs_deb_cmd("CMD_RESP: Unknown command response %#x\n",
+			    resp->command);
 		break;
 	}
 	return ret;
@@ -755,9 +744,9 @@
 	ulong flags;
 	u16 result;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	lbs_pr_debug(1, "CMD_RESP: @ %lu\n", jiffies);
+	lbs_deb_cmd("CMD_RESP: @ %lu\n", jiffies);
 
 	/* Now we got response from FW, cancel the command timer */
 	del_timer(&adapter->command_timer);
@@ -766,7 +755,7 @@
 	spin_lock_irqsave(&adapter->driver_lock, flags);
 
 	if (!adapter->cur_cmd) {
-		lbs_pr_debug(1, "CMD_RESP: NULL cur_cmd=%p\n", adapter->cur_cmd);
+		lbs_deb_cmd("CMD_RESP: NULL cur_cmd=%p\n", adapter->cur_cmd);
 		ret = -1;
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
 		goto done;
@@ -774,17 +763,17 @@
 	resp = (struct cmd_ds_command *)(adapter->cur_cmd->bufvirtualaddr);
 
 	lbs_dbg_hex("CMD_RESP:", adapter->cur_cmd->bufvirtualaddr,
-		priv->wlan_dev.upld_len);
+		    priv->upld_len);
 
 	respcmd = le16_to_cpu(resp->command);
 
 	result = le16_to_cpu(resp->result);
 
-	lbs_pr_debug(1, "CMD_RESP: %x result: %d length: %d\n", respcmd,
-	       result, priv->wlan_dev.upld_len);
+	lbs_deb_cmd("CMD_RESP: %x result: %d length: %d\n", respcmd,
+		    result, priv->upld_len);
 
 	if (!(respcmd & 0x8000)) {
-		lbs_pr_debug(1, "Invalid response to command!");
+		lbs_deb_cmd("Invalid response to command!");
 		adapter->cur_cmd_retcode = -1;
 		__libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
 		adapter->nr_cmd_pending--;
@@ -795,56 +784,52 @@
 	}
 
 	/* Store the response code to cur_cmd_retcode. */
-	adapter->cur_cmd_retcode = le16_to_cpu(resp->result);
+	adapter->cur_cmd_retcode = result;;
 
 	if (respcmd == cmd_ret_802_11_ps_mode) {
-		struct cmd_ds_802_11_ps_mode *psmode;
+		struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
+		u16 action = le16_to_cpu(psmode->action);
 
-		psmode = &resp->params.psmode;
-		lbs_pr_debug(1,
+		lbs_deb_cmd(
 		       "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
-		       resp->result, psmode->action);
-		psmode->action = cpu_to_le16(psmode->action);
+		       result, action);
 
 		if (result) {
-			lbs_pr_debug(1, "CMD_RESP: PS command failed- %#x \n",
-			       resp->result);
-			if (adapter->mode == IW_MODE_ADHOC) {
-				/*
-				 * We should not re-try enter-ps command in
-				 * ad-hoc mode. It takes place in
-				 * libertas_execute_next_command().
-				 */
-				if (psmode->action == cmd_subcmd_enter_ps)
-					adapter->psmode =
-					    wlan802_11powermodecam;
-			}
-		} else if (psmode->action == cmd_subcmd_enter_ps) {
+			lbs_deb_cmd("CMD_RESP: PS command failed- %#x \n",
+				    result);
+			/*
+			 * We should not re-try enter-ps command in
+			 * ad-hoc mode. It takes place in
+			 * libertas_execute_next_command().
+			 */
+			if (adapter->mode == IW_MODE_ADHOC &&
+			    action == cmd_subcmd_enter_ps)
+				adapter->psmode = wlan802_11powermodecam;
+		} else if (action == cmd_subcmd_enter_ps) {
 			adapter->needtowakeup = 0;
 			adapter->psstate = PS_STATE_AWAKE;
 
-			lbs_pr_debug(1, "CMD_RESP: Enter_PS command response\n");
+			lbs_deb_cmd("CMD_RESP: Enter_PS command response\n");
 			if (adapter->connect_status != libertas_connected) {
 				/*
 				 * When Deauth Event received before Enter_PS command
 				 * response, We need to wake up the firmware.
 				 */
-				lbs_pr_debug(1,
+				lbs_deb_cmd(
 				       "Disconnected, Going to invoke libertas_ps_wakeup\n");
 
-				mutex_unlock(&adapter->lock);
 				spin_unlock_irqrestore(&adapter->driver_lock, flags);
+				mutex_unlock(&adapter->lock);
 				libertas_ps_wakeup(priv, 0);
 				mutex_lock(&adapter->lock);
 				spin_lock_irqsave(&adapter->driver_lock, flags);
 			}
-		} else if (psmode->action == cmd_subcmd_exit_ps) {
+		} else if (action == cmd_subcmd_exit_ps) {
 			adapter->needtowakeup = 0;
 			adapter->psstate = PS_STATE_FULL_POWER;
-			lbs_pr_debug(1, "CMD_RESP: Exit_PS command response\n");
+			lbs_deb_cmd("CMD_RESP: Exit_PS command response\n");
 		} else {
-			lbs_pr_debug(1, "CMD_RESP: PS- action=0x%X\n",
-			       psmode->action);
+			lbs_deb_cmd("CMD_RESP: PS- action=0x%X\n", action);
 		}
 
 		__libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
@@ -865,15 +850,15 @@
 
 	/* If the command is not successful, cleanup and return failure */
 	if ((result != 0 || !(respcmd & 0x8000))) {
-		lbs_pr_debug(1, "CMD_RESP: command reply %#x result=%#x\n",
-		       resp->command, resp->result);
+		lbs_deb_cmd("CMD_RESP: command reply %#x result=%#x\n",
+		       respcmd, result);
 		/*
 		 * Handling errors here
 		 */
 		switch (respcmd) {
 		case cmd_ret_hw_spec_info:
 		case cmd_ret_802_11_reset:
-			lbs_pr_debug(1, "CMD_RESP: Reset command failed\n");
+			lbs_deb_cmd("CMD_RESP: Reset command failed\n");
 			break;
 
 		}
@@ -903,7 +888,7 @@
 
 done:
 	mutex_unlock(&adapter->lock);
-	LEAVE();
+	lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
@@ -917,37 +902,37 @@
 	eventcause = adapter->eventcause;
 	spin_unlock_irq(&adapter->driver_lock);
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	lbs_pr_debug(1, "EVENT Cause %x\n", eventcause);
+	lbs_deb_cmd("EVENT Cause %x\n", eventcause);
 
 	switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) {
 	case MACREG_INT_CODE_LINK_SENSED:
-		lbs_pr_debug(1, "EVENT: MACREG_INT_CODE_LINK_SENSED\n");
+		lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
 		break;
 
 	case MACREG_INT_CODE_DEAUTHENTICATED:
-		lbs_pr_debug(1, "EVENT: Deauthenticated\n");
+		lbs_deb_cmd("EVENT: Deauthenticated\n");
 		libertas_mac_event_disconnected(priv);
 		break;
 
 	case MACREG_INT_CODE_DISASSOCIATED:
-		lbs_pr_debug(1, "EVENT: Disassociated\n");
+		lbs_deb_cmd("EVENT: Disassociated\n");
 		libertas_mac_event_disconnected(priv);
 		break;
 
 	case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
-		lbs_pr_debug(1, "EVENT: Link lost\n");
+		lbs_deb_cmd("EVENT: Link lost\n");
 		libertas_mac_event_disconnected(priv);
 		break;
 
 	case MACREG_INT_CODE_PS_SLEEP:
-		lbs_pr_debug(1, "EVENT: SLEEP\n");
-		lbs_pr_debug(1, "_");
+		lbs_deb_cmd("EVENT: SLEEP\n");
+		lbs_deb_cmd("_");
 
 		/* handle unexpected PS SLEEP event */
 		if (adapter->psstate == PS_STATE_FULL_POWER) {
-			lbs_pr_debug(1,
+			lbs_deb_cmd(
 			       "EVENT: In FULL POWER mode - ignore PS SLEEP\n");
 			break;
 		}
@@ -958,12 +943,12 @@
 		break;
 
 	case MACREG_INT_CODE_PS_AWAKE:
-		lbs_pr_debug(1, "EVENT: AWAKE \n");
-		lbs_pr_debug(1, "|");
+		lbs_deb_cmd("EVENT: AWAKE \n");
+		lbs_deb_cmd("|");
 
 		/* handle unexpected PS AWAKE event */
 		if (adapter->psstate == PS_STATE_FULL_POWER) {
-			lbs_pr_debug(1,
+			lbs_deb_cmd(
 			       "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
 			break;
 		}
@@ -977,18 +962,18 @@
 			 * adapter->needtowakeup will be set to FALSE
 			 * in libertas_ps_wakeup()
 			 */
-			lbs_pr_debug(1, "Waking up...\n");
+			lbs_deb_cmd("Waking up...\n");
 			libertas_ps_wakeup(priv, 0);
 		}
 		break;
 
 	case MACREG_INT_CODE_MIC_ERR_UNICAST:
-		lbs_pr_debug(1, "EVENT: UNICAST MIC ERROR\n");
+		lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
 		handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
 		break;
 
 	case MACREG_INT_CODE_MIC_ERR_MULTICAST:
-		lbs_pr_debug(1, "EVENT: MULTICAST MIC ERROR\n");
+		lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
 		handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
 		break;
 	case MACREG_INT_CODE_MIB_CHANGED:
@@ -996,7 +981,7 @@
 		break;
 
 	case MACREG_INT_CODE_ADHOC_BCN_LOST:
-		lbs_pr_debug(1, "EVENT: HWAC - ADHOC BCN LOST\n");
+		lbs_deb_cmd("EVENT: HWAC - ADHOC BCN LOST\n");
 		break;
 
 	case MACREG_INT_CODE_RSSI_LOW:
@@ -1015,6 +1000,17 @@
 		lbs_pr_alert( "EVENT: SNR_HIGH\n");
 		break;
 
+	case MACREG_INT_CODE_MESH_AUTO_STARTED:
+		lbs_pr_alert( "EVENT: MESH_AUTO_STARTED\n");
+		adapter->connect_status = libertas_connected ;
+		if (priv->mesh_open == 1) {
+			netif_wake_queue(priv->mesh_dev) ;
+			netif_carrier_on(priv->mesh_dev) ;
+		}
+		adapter->mode = IW_MODE_ADHOC ;
+		schedule_work(&priv->sync_channel);
+		break;
+
 	default:
 		lbs_pr_alert( "EVENT: unknown event id: %#x\n",
 		       eventcause >> SBI_EVENT_CAUSE_SHIFT);
@@ -1024,6 +1020,7 @@
 	spin_lock_irq(&adapter->driver_lock);
 	adapter->eventcause = 0;
 	spin_unlock_irq(&adapter->driver_lock);
-	LEAVE();
+
+	lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 7d7bc5e..715cbda 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -4,6 +4,7 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <net/iw_handler.h>
+
 #include "dev.h"
 #include "decl.h"
 #include "host.h"
@@ -15,7 +16,9 @@
 	"Disconnected"
 };
 
-void libertas_debug_init(wlan_private * priv, struct net_device *dev);
+#ifdef PROC_DEBUG
+static void libertas_debug_init(wlan_private * priv, struct net_device *dev);
+#endif
 
 static int open_file_generic(struct inode *inode, struct file *file)
 {
@@ -60,43 +63,33 @@
 	int numscansdone = 0, res;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
+	struct bss_descriptor * iter_bss;
 
 	pos += snprintf(buf+pos, len-pos,
-			"---------------------------------------");
-	pos += snprintf(buf+pos, len-pos,
-			"---------------------------------------\n");
-	pos += snprintf(buf+pos, len-pos,
 		"# | ch  | ss  |       bssid       |   cap    |    TSF   | Qual | SSID \n");
-	pos += snprintf(buf+pos, len-pos,
-		"---------------------------------------");
-	pos += snprintf(buf+pos, len-pos,
-		"---------------------------------------\n");
 
-	while (numscansdone < priv->adapter->numinscantable) {
-		struct bss_descriptor *pbssinfo;
+	mutex_lock(&priv->adapter->lock);
+	list_for_each_entry (iter_bss, &priv->adapter->network_list, list) {
 		u16 cap;
 
-		pbssinfo = &priv->adapter->scantable[numscansdone];
-		memcpy(&cap, &pbssinfo->cap, sizeof(cap));
+		memcpy(&cap, &iter_bss->cap, sizeof(cap));
 		pos += snprintf(buf+pos, len-pos,
-			"%02u| %03d | %03ld | %02x:%02x:%02x:%02x:%02x:%02x |",
-			numscansdone, pbssinfo->channel, pbssinfo->rssi,
-			pbssinfo->macaddress[0], pbssinfo->macaddress[1],
-			pbssinfo->macaddress[2], pbssinfo->macaddress[3],
-			pbssinfo->macaddress[4], pbssinfo->macaddress[5]);
+			"%02u| %03d | %03ld | " MAC_FMT " |",
+			numscansdone, iter_bss->channel, iter_bss->rssi,
+			MAC_ARG(iter_bss->bssid));
 		pos += snprintf(buf+pos, len-pos, " %04x-", cap);
 		pos += snprintf(buf+pos, len-pos, "%c%c%c |",
-				pbssinfo->cap.ibss ? 'A' : 'I',
-				pbssinfo->cap.privacy ? 'P' : ' ',
-				pbssinfo->cap.spectrummgmt ? 'S' : ' ');
-		pos += snprintf(buf+pos, len-pos, " %08llx |", pbssinfo->networktsf);
-		pos += snprintf(buf+pos, len-pos, " %d |",
-			SCAN_RSSI(priv->adapter->scantable[numscansdone].rssi));
-
-		pos += snprintf(buf+pos, len-pos, " %s\n", pbssinfo->ssid.ssid);
+				iter_bss->cap.ibss ? 'A' : 'I',
+				iter_bss->cap.privacy ? 'P' : ' ',
+				iter_bss->cap.spectrummgmt ? 'S' : ' ');
+		pos += snprintf(buf+pos, len-pos, " %08llx |", iter_bss->networktsf);
+		pos += snprintf(buf+pos, len-pos, " %d |", SCAN_RSSI(iter_bss->rssi));
+		pos += snprintf(buf+pos, len-pos, " %s\n",
+		                escape_essid(iter_bss->ssid, iter_bss->ssid_len));
 
 		numscansdone++;
 	}
+	mutex_unlock(&priv->adapter->lock);
 
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 
@@ -111,7 +104,6 @@
 	wlan_private *priv = file->private_data;
 	ssize_t buf_size, res;
 	int p1, p2, p3, p4, p5, p6;
-	struct sleep_params sp;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
 
@@ -125,14 +117,12 @@
 		res = -EFAULT;
 		goto out_unlock;
 	}
-	sp.sp_error = p1;
-	sp.sp_offset = p2;
-	sp.sp_stabletime = p3;
-	sp.sp_calcontrol = p4;
-	sp.sp_extsleepclk = p5;
-	sp.sp_reserved = p6;
-
-	memcpy(&priv->adapter->sp, &sp, sizeof(struct sleep_params));
+	priv->adapter->sp.sp_error = p1;
+	priv->adapter->sp.sp_offset = p2;
+	priv->adapter->sp.sp_stabletime = p3;
+	priv->adapter->sp.sp_calcontrol = p4;
+	priv->adapter->sp.sp_extsleepclk = p5;
+	priv->adapter->sp.sp_reserved = p6;
 
         res = libertas_prepare_and_send_command(priv,
 				cmd_802_11_sleep_params,
@@ -185,7 +175,6 @@
 {
 	wlan_private *priv = file->private_data;
 	ssize_t res, buf_size;
-	struct WLAN_802_11_SSID extscan_ssid;
 	union iwreq_data wrqu;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
@@ -196,13 +185,10 @@
 		goto out_unlock;
 	}
 
-	memcpy(&extscan_ssid.ssid, buf, strlen(buf)-1);
-	extscan_ssid.ssidlength = strlen(buf)-1;
-
-	libertas_send_specific_SSID_scan(priv, &extscan_ssid, 1);
+	libertas_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
 
 	memset(&wrqu, 0, sizeof(union iwreq_data));
-	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL);
+	wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
 
 out_unlock:
 	free_page(addr);
@@ -251,16 +237,13 @@
 {
 	char *hold;
 	unsigned int mac[ETH_ALEN];
-	int i;
 
 	hold = strstr(buf, "bssid=");
 	if (!hold)
 		return;
 	hold += 6;
-	sscanf(hold, "%2x:%2x:%2x:%2x:%2x:%2x", mac, mac+1, mac+2, mac+3,
-			mac+4, mac+5);
-	for(i=0;i<ETH_ALEN;i++)
-		scan_cfg->specificBSSID[i] = mac[i];
+	sscanf(hold, MAC_FMT, mac, mac+1, mac+2, mac+3, mac+4, mac+5);
+	memcpy(scan_cfg->bssid, mac, ETH_ALEN);
 }
 
 static void libertas_parse_ssid(char *buf, size_t count,
@@ -278,28 +261,26 @@
 		end = buf + count - 1;
 
 	size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
-	strncpy(scan_cfg->specificSSID, hold, size);
+	strncpy(scan_cfg->ssid, hold, size);
 
 	return;
 }
 
-static void libertas_parse_keep(char *buf, size_t count,
-                        struct wlan_ioctl_user_scan_cfg *scan_cfg)
+static int libertas_parse_clear(char *buf, size_t count, const char *tag)
 {
 	char *hold;
 	int val;
 
-	hold = strstr(buf, "keep=");
+	hold = strstr(buf, tag);
 	if (!hold)
-		return;
-	hold += 5;
+		return 0;
+	hold += strlen(tag);
 	sscanf(hold, "%d", &val);
 
 	if (val != 0)
 		val = 1;
 
-	scan_cfg->keeppreviousscan = val;
-	return;
+	return val;
 }
 
 static int libertas_parse_dur(char *buf, size_t count,
@@ -382,17 +363,18 @@
 	dur = libertas_parse_dur(buf, count, scan_cfg);
 	libertas_parse_chan(buf, count, scan_cfg, dur);
 	libertas_parse_bssid(buf, count, scan_cfg);
+	scan_cfg->clear_bssid = libertas_parse_clear(buf, count, "clear_bssid=");
 	libertas_parse_ssid(buf, count, scan_cfg);
-	libertas_parse_keep(buf, count, scan_cfg);
+	scan_cfg->clear_ssid = libertas_parse_clear(buf, count, "clear_ssid=");
 	libertas_parse_probes(buf, count, scan_cfg);
 	libertas_parse_type(buf, count, scan_cfg);
 
-	wlan_scan_networks(priv, scan_cfg);
+	wlan_scan_networks(priv, scan_cfg, 1);
 	wait_event_interruptible(priv->adapter->cmd_pending,
 				 !priv->adapter->nr_cmd_pending);
 
 	memset(&wrqu, 0x00, sizeof(union iwreq_data));
-	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL);
+	wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
 
 out_unlock:
 	free_page(addr);
@@ -407,11 +389,11 @@
 	u16 wait_option = cmd_option_waitforrsp;
 
 	if (!(*cmdnode = libertas_get_free_cmd_ctrl_node(priv))) {
-		lbs_pr_debug(1, "failed libertas_get_free_cmd_ctrl_node\n");
+		lbs_deb_debugfs("failed libertas_get_free_cmd_ctrl_node\n");
 		return -ENOMEM;
 	}
 	if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) {
-		lbs_pr_debug(1, "failed to allocate response buffer!\n");
+		lbs_deb_debugfs("failed to allocate response buffer!\n");
 		return -ENOMEM;
 	}
 	libertas_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL);
@@ -420,8 +402,8 @@
 	(*cmdnode)->cmdflags |= CMD_F_HOSTCMD;
 	(*cmdnode)->cmdwaitqwoken = 0;
 	*cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr;
-	(*cmd)->command = cmd_802_11_subscribe_event;
-	(*cmd)->seqnum = ++priv->adapter->seqnum;
+	(*cmd)->command = cpu_to_le16(cmd_802_11_subscribe_event);
+	(*cmd)->seqnum = cpu_to_le16(++priv->adapter->seqnum);
 	(*cmd)->result = 0;
 	return 0;
 }
@@ -447,26 +429,25 @@
 	}
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_get;
-	pcmdptr->size =
-	cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+	event->action = cpu_to_le16(cmd_act_get);
+	pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -474,17 +455,17 @@
 	}
 
 	cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
-	event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
-	while (cmd_len < pcmdptr->size) {
-		struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
-		switch(header->type) {
+	event = (void *)(response_buf + S_DS_GEN);
+	while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+		struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+		switch (header->type) {
 		struct mrvlietypes_rssithreshold  *Lowrssi;
-		case TLV_TYPE_RSSI_LOW:
-		Lowrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
-		pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
-				Lowrssi->rssivalue,
-				Lowrssi->rssifreq,
-				(event->events & 0x0001)?1:0);
+		case __constant_cpu_to_le16(TLV_TYPE_RSSI_LOW):
+			Lowrssi = (void *)(response_buf + cmd_len);
+			pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+					Lowrssi->rssivalue,
+					Lowrssi->rssifreq,
+					(event->events & cpu_to_le16(0x0001))?1:0);
 		default:
 			cmd_len += sizeof(struct mrvlietypes_snrthreshold);
 			break;
@@ -512,21 +493,20 @@
 		return res;
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_get;
-	pcmdptr->size =
-	cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+	event->action = cpu_to_le16(cmd_act_get);
+	pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		return 0;
 	}
@@ -538,7 +518,7 @@
 	}
 
 	event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
-	event_bitmap = event->events;
+	event_bitmap = le16_to_cpu(event->events);
 	kfree(response_buf);
 	return event_bitmap;
 }
@@ -579,7 +559,7 @@
 		goto out_unlock;
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_set;
+	event->action = cpu_to_le16(cmd_act_set);
 	pcmdptr->size = cpu_to_le16(S_DS_GEN +
 		sizeof(struct cmd_ds_802_11_subscribe_event) +
 		sizeof(struct mrvlietypes_rssithreshold));
@@ -588,30 +568,30 @@
 	ptr = (u8*) pcmdptr+cmd_len;
 	rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
 	rssi_threshold->header.type = cpu_to_le16(0x0104);
-	rssi_threshold->header.len = 2;
-	rssi_threshold->rssivalue = cpu_to_le16(value);
-	rssi_threshold->rssifreq = cpu_to_le16(freq);
+	rssi_threshold->header.len = cpu_to_le16(2);
+	rssi_threshold->rssivalue = value;
+	rssi_threshold->rssifreq = freq;
 	event_bitmap |= subscribed ? 0x0001 : 0x0;
-	event->events = event_bitmap;
+	event->events = cpu_to_le16(event_bitmap);
 
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -645,27 +625,26 @@
 	}
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_get;
-	pcmdptr->size =
-	cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+	event->action = cpu_to_le16(cmd_act_get);
+	pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -673,17 +652,17 @@
 	}
 
 	cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
-	event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
-	while (cmd_len < pcmdptr->size) {
-		struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
-		switch(header->type) {
+	event = (void *)(response_buf + S_DS_GEN);
+	while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+		struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+		switch (header->type) {
 		struct mrvlietypes_snrthreshold *LowSnr;
-		case TLV_TYPE_SNR_LOW:
-		LowSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
-		pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
-				LowSnr->snrvalue,
-				LowSnr->snrfreq,
-				(event->events & 0x0002)?1:0);
+		case __constant_cpu_to_le16(TLV_TYPE_SNR_LOW):
+			LowSnr = (void *)(response_buf + cmd_len);
+			pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+					LowSnr->snrvalue,
+					LowSnr->snrfreq,
+					(event->events & cpu_to_le16(0x0002))?1:0);
 		default:
 			cmd_len += sizeof(struct mrvlietypes_snrthreshold);
 			break;
@@ -733,7 +712,7 @@
 		goto out_unlock;
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_set;
+	event->action = cpu_to_le16(cmd_act_set);
 	pcmdptr->size = cpu_to_le16(S_DS_GEN +
 		sizeof(struct cmd_ds_802_11_subscribe_event) +
 		sizeof(struct mrvlietypes_snrthreshold));
@@ -741,30 +720,30 @@
 	ptr = (u8*) pcmdptr+cmd_len;
 	snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
 	snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW);
-	snr_threshold->header.len = 2;
-	snr_threshold->snrvalue = cpu_to_le16(value);
-	snr_threshold->snrfreq = cpu_to_le16(freq);
+	snr_threshold->header.len = cpu_to_le16(2);
+	snr_threshold->snrvalue = value;
+	snr_threshold->snrfreq = freq;
 	event_bitmap |= subscribed ? 0x0002 : 0x0;
-	event->events = event_bitmap;
+	event->events = cpu_to_le16(event_bitmap);
 
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -799,27 +778,26 @@
 	}
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_get;
-	pcmdptr->size =
-	cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+	event->action = cpu_to_le16(cmd_act_get);
+	pcmdptr->size =	cpu_to_le16(sizeof(*event) + S_DS_GEN);
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -827,17 +805,17 @@
 	}
 
 	cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
-	event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
-	while (cmd_len < pcmdptr->size) {
-		struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
-		switch(header->type) {
+	event = (void *)(response_buf + S_DS_GEN);
+	while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+		struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+		switch (header->type) {
 		struct mrvlietypes_failurecount *failcount;
-		case TLV_TYPE_FAILCOUNT:
-		failcount = (struct mrvlietypes_failurecount *)(response_buf + cmd_len);
-		pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
-				failcount->failvalue,
-				failcount->Failfreq,
-				(event->events & 0x0004)?1:0);
+		case __constant_cpu_to_le16(TLV_TYPE_FAILCOUNT):
+			failcount = (void *)(response_buf + cmd_len);
+			pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+					failcount->failvalue,
+					failcount->Failfreq,
+					(event->events & cpu_to_le16(0x0004))?1:0);
 		default:
 			cmd_len += sizeof(struct mrvlietypes_failurecount);
 			break;
@@ -886,7 +864,7 @@
 		goto out_unlock;
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_set;
+	event->action = cpu_to_le16(cmd_act_set);
 	pcmdptr->size = cpu_to_le16(S_DS_GEN +
 		sizeof(struct cmd_ds_802_11_subscribe_event) +
 		sizeof(struct mrvlietypes_failurecount));
@@ -894,30 +872,30 @@
 	ptr = (u8*) pcmdptr+cmd_len;
 	failcount = (struct mrvlietypes_failurecount *)(ptr);
 	failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
-	failcount->header.len = 2;
-	failcount->failvalue = cpu_to_le16(value);
-	failcount->Failfreq = cpu_to_le16(freq);
+	failcount->header.len = cpu_to_le16(2);
+	failcount->failvalue = value;
+	failcount->Failfreq = freq;
 	event_bitmap |= subscribed ? 0x0004 : 0x0;
-	event->events = event_bitmap;
+	event->events = cpu_to_le16(event_bitmap);
 
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = (struct cmd_ds_command *)response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -951,27 +929,26 @@
 	}
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_get;
-	pcmdptr->size =
-	cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+	event->action = cpu_to_le16(cmd_act_get);
+	pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		free_page(addr);
 		kfree(response_buf);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		free_page(addr);
 		kfree(response_buf);
@@ -979,16 +956,16 @@
 	}
 
 	cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
-	event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
-	while (cmd_len < pcmdptr->size) {
-		struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
-		switch(header->type) {
+	event = (void *)(response_buf + S_DS_GEN);
+	while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+		struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+		switch (header->type) {
 		struct mrvlietypes_beaconsmissed *bcnmiss;
-		case TLV_TYPE_BCNMISS:
-		bcnmiss = (struct mrvlietypes_beaconsmissed *)(response_buf + cmd_len);
-		pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
-				bcnmiss->beaconmissed,
-				(event->events & 0x0008)?1:0);
+		case __constant_cpu_to_le16(TLV_TYPE_BCNMISS):
+			bcnmiss = (void *)(response_buf + cmd_len);
+			pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
+					bcnmiss->beaconmissed,
+					(event->events & cpu_to_le16(0x0008))?1:0);
 		default:
 			cmd_len += sizeof(struct mrvlietypes_beaconsmissed);
 			break;
@@ -1038,7 +1015,7 @@
 		goto out_unlock;
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_set;
+	event->action = cpu_to_le16(cmd_act_set);
 	pcmdptr->size = cpu_to_le16(S_DS_GEN +
 		sizeof(struct cmd_ds_802_11_subscribe_event) +
 		sizeof(struct mrvlietypes_beaconsmissed));
@@ -1046,29 +1023,29 @@
 	ptr = (u8*) pcmdptr+cmd_len;
 	bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr);
 	bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS);
-	bcnmiss->header.len = 2;
-	bcnmiss->beaconmissed = cpu_to_le16(value);
+	bcnmiss->header.len = cpu_to_le16(2);
+	bcnmiss->beaconmissed = value;
 	event_bitmap |= subscribed ? 0x0008 : 0x0;
-	event->events = event_bitmap;
+	event->events = cpu_to_le16(event_bitmap);
 
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		free_page(addr);
 		kfree(response_buf);
@@ -1102,27 +1079,26 @@
 	}
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_get;
-	pcmdptr->size =
-	cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+	event->action = cpu_to_le16(cmd_act_get);
+	pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -1130,17 +1106,17 @@
 	}
 
 	cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
-	event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
-	while (cmd_len < pcmdptr->size) {
-		struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
-		switch(header->type) {
+	event = (void *)(response_buf + S_DS_GEN);
+	while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+		struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+		switch (header->type) {
 		struct mrvlietypes_rssithreshold  *Highrssi;
-		case TLV_TYPE_RSSI_HIGH:
-		Highrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
-		pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
-				Highrssi->rssivalue,
-				Highrssi->rssifreq,
-				(event->events & 0x0010)?1:0);
+		case __constant_cpu_to_le16(TLV_TYPE_RSSI_HIGH):
+			Highrssi = (void *)(response_buf + cmd_len);
+			pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+					Highrssi->rssivalue,
+					Highrssi->rssifreq,
+					(event->events & cpu_to_le16(0x0010))?1:0);
 		default:
 			cmd_len += sizeof(struct mrvlietypes_snrthreshold);
 			break;
@@ -1190,7 +1166,7 @@
 		goto out_unlock;
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_set;
+	event->action = cpu_to_le16(cmd_act_set);
 	pcmdptr->size = cpu_to_le16(S_DS_GEN +
 		sizeof(struct cmd_ds_802_11_subscribe_event) +
 		sizeof(struct mrvlietypes_rssithreshold));
@@ -1198,29 +1174,29 @@
 	ptr = (u8*) pcmdptr+cmd_len;
 	rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
 	rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
-	rssi_threshold->header.len = 2;
-	rssi_threshold->rssivalue = cpu_to_le16(value);
-	rssi_threshold->rssifreq = cpu_to_le16(freq);
+	rssi_threshold->header.len = cpu_to_le16(2);
+	rssi_threshold->rssivalue = value;
+	rssi_threshold->rssifreq = freq;
 	event_bitmap |= subscribed ? 0x0010 : 0x0;
-	event->events = event_bitmap;
+	event->events = cpu_to_le16(event_bitmap);
 
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		return 0;
@@ -1253,27 +1229,26 @@
 	}
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_get;
-	pcmdptr->size =
-	cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+	event->action = cpu_to_le16(cmd_act_get);
+	pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -1281,17 +1256,17 @@
 	}
 
 	cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
-	event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
-	while (cmd_len < pcmdptr->size) {
-		struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
-		switch(header->type) {
+	event = (void *)(response_buf + S_DS_GEN);
+	while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+		struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+		switch (header->type) {
 		struct mrvlietypes_snrthreshold *HighSnr;
-		case TLV_TYPE_SNR_HIGH:
-		HighSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
-		pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
-				HighSnr->snrvalue,
-				HighSnr->snrfreq,
-				(event->events & 0x0020)?1:0);
+		case __constant_cpu_to_le16(TLV_TYPE_SNR_HIGH):
+			HighSnr = (void *)(response_buf + cmd_len);
+			pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+					HighSnr->snrvalue,
+					HighSnr->snrfreq,
+					(event->events & cpu_to_le16(0x0020))?1:0);
 		default:
 			cmd_len += sizeof(struct mrvlietypes_snrthreshold);
 			break;
@@ -1341,7 +1316,7 @@
 		goto out_unlock;
 
 	event = &pcmdptr->params.subscribe_event;
-	event->action = cmd_act_set;
+	event->action = cpu_to_le16(cmd_act_set);
 	pcmdptr->size = cpu_to_le16(S_DS_GEN +
 		sizeof(struct cmd_ds_802_11_subscribe_event) +
 		sizeof(struct mrvlietypes_snrthreshold));
@@ -1349,30 +1324,30 @@
 	ptr = (u8*) pcmdptr+cmd_len;
 	snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
 	snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH);
-	snr_threshold->header.len = 2;
-	snr_threshold->snrvalue = cpu_to_le16(value);
-	snr_threshold->snrfreq = cpu_to_le16(freq);
+	snr_threshold->header.len = cpu_to_le16(2);
+	snr_threshold->snrvalue = value;
+	snr_threshold->snrfreq = freq;
 	event_bitmap |= subscribed ? 0x0020 : 0x0;
-	event->events = event_bitmap;
+	event->events = cpu_to_le16(event_bitmap);
 
 	libertas_queue_cmd(adapter, pcmdnode, 1);
 	wake_up_interruptible(&priv->mainthread.waitq);
 
 	/* Sleep until response is generated by FW */
 	wait_event_interruptible(pcmdnode->cmdwait_q,
-				pcmdnode->cmdwaitqwoken);
+				 pcmdnode->cmdwaitqwoken);
 
 	pcmdptr = response_buf;
 
 	if (pcmdptr->result) {
-		lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
-			pcmdptr->result);
+		lbs_pr_err("%s: fail, result=%d\n", __func__,
+			   le16_to_cpu(pcmdptr->result));
 		kfree(response_buf);
 		free_page(addr);
 		return 0;
 	}
 
-	if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+	if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
 		lbs_pr_err("command response incorrect!\n");
 		kfree(response_buf);
 		free_page(addr);
@@ -1760,7 +1735,7 @@
 
 	debugfs_remove(priv->regs_dir);
 
-	for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
+	for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
 		debugfs_remove(priv->debugfs_events_files[i]);
 
 	debugfs_remove(priv->events_dir);
@@ -1769,13 +1744,19 @@
 #endif
 	for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
 		debugfs_remove(priv->debugfs_files[i]);
+	debugfs_remove(priv->debugfs_dir);
 }
 
+
+
 /* debug entry */
 
+#ifdef PROC_DEBUG
+
 #define item_size(n)	(FIELD_SIZEOF(wlan_adapter, n))
 #define item_addr(n)	(offsetof(wlan_adapter, n))
 
+
 struct debug_data {
 	char name[32];
 	u32 size;
@@ -1863,7 +1844,7 @@
 		return 0;
 
 	if (copy_from_user(pdata, buf, cnt)) {
-		lbs_pr_debug(1, "Copy from user failed\n");
+		lbs_deb_debugfs("Copy from user failed\n");
 		kfree(pdata);
 		return 0;
 	}
@@ -1913,7 +1894,7 @@
  *  @param dev     pointer net_device
  *  @return 	   N/A
  */
-void libertas_debug_init(wlan_private * priv, struct net_device *dev)
+static void libertas_debug_init(wlan_private * priv, struct net_device *dev)
 {
 	int i;
 
@@ -1927,4 +1908,5 @@
 						  priv->debugfs_dir, &items[0],
 						  &libertas_debug_fops);
 }
+#endif
 
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 606bdd0..40f56bb 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -6,6 +6,8 @@
 #ifndef _WLAN_DECL_H_
 #define _WLAN_DECL_H_
 
+#include <linux/device.h>
+
 #include "defs.h"
 
 /** Function Prototype Declaration */
@@ -46,7 +48,7 @@
 u8 libertas_data_rate_to_index(u32 rate);
 void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen);
 
-int libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb);
+void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb);
 
 /** The proc fs interface */
 int libertas_process_rx_command(wlan_private * priv);
@@ -66,18 +68,24 @@
 
 void libertas_tx_runqueue(wlan_private *priv);
 
-extern struct chan_freq_power *libertas_find_cfp_by_band_and_channel(
+struct chan_freq_power *libertas_find_cfp_by_band_and_channel(
 				wlan_adapter * adapter, u8 band, u16 channel);
 
-extern void libertas_mac_event_disconnected(wlan_private * priv);
+void libertas_mac_event_disconnected(wlan_private * priv);
 
 void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str);
 
-int reset_device(wlan_private *priv);
+/* fw.c */
+int libertas_init_fw(wlan_private * priv, char *fw_name);
+
 /* main.c */
-extern struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band,
+struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band,
 						             int *cfp_no);
-wlan_private *wlan_add_card(void *card);
-int wlan_remove_card(void *card);
+wlan_private *libertas_add_card(void *card, struct device *dmdev);
+int libertas_activate_card(wlan_private *priv, char *fw_name);
+int libertas_remove_card(wlan_private *priv);
+int libertas_add_mesh(wlan_private *priv, struct device *dev);
+void libertas_remove_mesh(wlan_private *priv);
+
 
 #endif				/* _WLAN_DECL_H_ */
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 80dd9ea..4dd43e5 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -7,14 +7,79 @@
 
 #include <linux/spinlock.h>
 
-extern unsigned int libertas_debug;
-
 #ifdef CONFIG_LIBERTAS_DEBUG
 #define DEBUG
 #define PROC_DEBUG
 #endif
 
-#define DRV_NAME		"usb8xxx"
+#ifndef DRV_NAME
+#define DRV_NAME "libertas"
+#endif
+
+
+#define LBS_DEB_ENTER	0x00000001
+#define LBS_DEB_LEAVE	0x00000002
+#define LBS_DEB_MAIN	0x00000004
+#define LBS_DEB_NET	0x00000008
+#define LBS_DEB_MESH	0x00000010
+#define LBS_DEB_WEXT	0x00000020
+#define LBS_DEB_IOCTL	0x00000040
+#define LBS_DEB_SCAN	0x00000080
+#define LBS_DEB_ASSOC	0x00000100
+#define LBS_DEB_JOIN	0x00000200
+#define LBS_DEB_11D	0x00000400
+#define LBS_DEB_DEBUGFS	0x00000800
+#define LBS_DEB_ETHTOOL	0x00001000
+#define LBS_DEB_HOST	0x00002000
+#define LBS_DEB_CMD	0x00004000
+#define LBS_DEB_RX	0x00008000
+#define LBS_DEB_TX	0x00010000
+#define LBS_DEB_USB	0x00020000
+#define LBS_DEB_CS	0x00040000
+#define LBS_DEB_FW	0x00080000
+#define LBS_DEB_THREAD	0x00100000
+#define LBS_DEB_HEX	0x00200000
+
+extern unsigned int libertas_debug;
+
+#ifdef DEBUG
+#define LBS_DEB_LL(grp, fmt, args...) \
+do { if ((libertas_debug & (grp)) == (grp)) \
+  printk(KERN_DEBUG DRV_NAME "%s: " fmt, \
+         in_interrupt() ? " (INT)" : "", ## args); } while (0)
+#else
+#define LBS_DEB_LL(grp, fmt, args...) do {} while (0)
+#endif
+
+#define lbs_deb_enter(grp) \
+  LBS_DEB_LL(grp | LBS_DEB_ENTER, "%s():%d enter\n", __FUNCTION__, __LINE__);
+#define lbs_deb_enter_args(grp, fmt, args...) \
+  LBS_DEB_LL(grp | LBS_DEB_ENTER, "%s(" fmt "):%d\n", __FUNCTION__, ## args, __LINE__);
+#define lbs_deb_leave(grp) \
+  LBS_DEB_LL(grp | LBS_DEB_LEAVE, "%s():%d leave\n", __FUNCTION__, __LINE__);
+#define lbs_deb_leave_args(grp, fmt, args...) \
+  LBS_DEB_LL(grp | LBS_DEB_LEAVE, "%s():%d leave, " fmt "\n", \
+  __FUNCTION__, __LINE__, ##args);
+#define lbs_deb_main(fmt, args...)      LBS_DEB_LL(LBS_DEB_MAIN, fmt, ##args)
+#define lbs_deb_net(fmt, args...)       LBS_DEB_LL(LBS_DEB_NET, fmt, ##args)
+#define lbs_deb_mesh(fmt, args...)      LBS_DEB_LL(LBS_DEB_MESH, fmt, ##args)
+#define lbs_deb_wext(fmt, args...)      LBS_DEB_LL(LBS_DEB_WEXT, fmt, ##args)
+#define lbs_deb_ioctl(fmt, args...)     LBS_DEB_LL(LBS_DEB_IOCTL, fmt, ##args)
+#define lbs_deb_scan(fmt, args...)      LBS_DEB_LL(LBS_DEB_SCAN, fmt, ##args)
+#define lbs_deb_assoc(fmt, args...)     LBS_DEB_LL(LBS_DEB_ASSOC, fmt, ##args)
+#define lbs_deb_join(fmt, args...)      LBS_DEB_LL(LBS_DEB_JOIN, fmt, ##args)
+#define lbs_deb_11d(fmt, args...)       LBS_DEB_LL(LBS_DEB_11D, fmt, ##args)
+#define lbs_deb_debugfs(fmt, args...)   LBS_DEB_LL(LBS_DEB_DEBUGFS, fmt, ##args)
+#define lbs_deb_ethtool(fmt, args...)   LBS_DEB_LL(LBS_DEB_ETHTOOL, fmt, ##args)
+#define lbs_deb_host(fmt, args...)      LBS_DEB_LL(LBS_DEB_HOST, fmt, ##args)
+#define lbs_deb_cmd(fmt, args...)       LBS_DEB_LL(LBS_DEB_CMD, fmt, ##args)
+#define lbs_deb_rx(fmt, args...)        LBS_DEB_LL(LBS_DEB_RX, fmt, ##args)
+#define lbs_deb_tx(fmt, args...)        LBS_DEB_LL(LBS_DEB_TX, fmt, ##args)
+#define lbs_deb_fw(fmt, args...)        LBS_DEB_LL(LBS_DEB_FW, fmt, ##args)
+#define lbs_deb_usb(fmt, args...)       LBS_DEB_LL(LBS_DEB_USB, fmt, ##args)
+#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, "%s:" fmt, (dev)->bus_id, ##args)
+#define lbs_deb_cs(fmt, args...)        LBS_DEB_LL(LBS_DEB_CS, fmt, ##args)
+#define lbs_deb_thread(fmt, args...)    LBS_DEB_LL(LBS_DEB_THREAD, fmt, ##args)
 
 #define lbs_pr_info(format, args...) \
 	printk(KERN_INFO DRV_NAME": " format, ## args)
@@ -24,37 +89,25 @@
 	printk(KERN_ALERT DRV_NAME": " format, ## args)
 
 #ifdef DEBUG
-#define lbs_pr_debug(level, format, args...) \
-	do { if (libertas_debug >= level) \
-	printk(KERN_INFO DRV_NAME": " format, ##args); } while (0)
-#define lbs_dev_dbg(level, device, format, args...) \
-        lbs_pr_debug(level, "%s: " format, \
-        (device)->bus_id , ## args)
-
 static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len)
 {
 	int i = 0;
 
-	if (!libertas_debug)
+	if (!(libertas_debug & LBS_DEB_HEX))
 		return;
 
 	printk(KERN_DEBUG "%s: ", prompt);
 	for (i = 1; i <= len; i++) {
-		printk(KERN_DEBUG "%02x ", (u8) * buf);
+		printk("%02x ", (u8) * buf);
 		buf++;
 	}
 	printk("\n");
 }
 #else
-#define lbs_pr_debug(level, format, args...)		do {} while (0)
-#define lbs_dev_dbg(level, device, format, args...)	do {} while (0)
 #define lbs_dbg_hex(x,y,z)				do {} while (0)
 #endif
 
-#define	ENTER()			lbs_pr_debug(1, "Enter: %s, %s:%i\n", \
-					__FUNCTION__, __FILE__, __LINE__)
-#define	LEAVE()			lbs_pr_debug(1, "Leave: %s, %s:%i\n", \
-					__FUNCTION__, __FILE__, __LINE__)
+
 
 /** Buffer Constants */
 
@@ -74,7 +127,6 @@
 #define MRVDRV_NUM_OF_CMD_BUFFER        10
 #define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
 #define MRVDRV_MAX_CHANNEL_SIZE		14
-#define MRVDRV_MAX_BSSID_LIST		64
 #define MRVDRV_ASSOCIATION_TIME_OUT	255
 #define MRVDRV_SNAP_HEADER_LEN          8
 
@@ -104,6 +156,13 @@
 #define MRVDRV_MAX_BEACON_INTERVAL		1000
 #define MRVDRV_BEACON_INTERVAL			100
 
+/** INT status Bit Definition*/
+#define his_cmddnldrdy			0x01
+#define his_cardevent			0x02
+#define his_cmdupldrdy			0x04
+
+#define SBI_EVENT_CAUSE_SHIFT		3
+
 /** TxPD status */
 
 /*	Station firmware use TxPD status field to report final Tx transmit
@@ -205,8 +264,6 @@
 extern const char libertas_driver_version[];
 extern u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE];
 
-extern u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES];
-
 extern u8 libertas_supported_rates[G_SUPPORTED_RATES];
 
 extern u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES];
@@ -316,6 +373,8 @@
 /* Default values for fwt commands. */
 #define FWT_DEFAULT_METRIC 0
 #define FWT_DEFAULT_DIR 1
+/* Default Rate, 11Mbps */
+#define FWT_DEFAULT_RATE 3
 #define FWT_DEFAULT_SSN 0xffffffff
 #define FWT_DEFAULT_DSN 0
 #define FWT_DEFAULT_HOPCOUNT 0
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index e8b9020..785192b 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -63,11 +63,11 @@
 
 /** Current Basic Service Set State Structure */
 struct current_bss_params {
-	struct bss_descriptor bssdescriptor;
 	/** bssid */
 	u8 bssid[ETH_ALEN];
 	/** ssid */
-	struct WLAN_802_11_SSID ssid;
+	u8 ssid[IW_ESSID_MAX_SIZE + 1];
+	u8 ssid_len;
 
 	/** band */
 	u8 band;
@@ -89,31 +89,6 @@
 	u16 sp_reserved;
 };
 
-/** Data structure for the Marvell WLAN device */
-typedef struct _wlan_dev {
-	/** device name */
-	char name[DEV_NAME_LEN];
-	/** card pointer */
-	void *card;
-	/** IO port */
-	u32 ioport;
-	/** Upload received */
-	u32 upld_rcv;
-	/** Upload type */
-	u32 upld_typ;
-	/** Upload length */
-	u32 upld_len;
-	/** netdev pointer */
-	struct net_device *netdev;
-	/* Upload buffer */
-	u8 upld_buf[WLAN_UPLD_SIZE];
-	/* Download sent:
-	   bit0 1/0=data_sent/data_tx_done,
-	   bit1 1/0=cmd_sent/cmd_tx_done,
-	   all other bits reserved 0 */
-	u8 dnld_sent;
-} wlan_dev_t, *pwlan_dev_t;
-
 /* Mesh statistics */
 struct wlan_mesh_stats {
 	u32	fwd_bcast_cnt;		/* Fwd: Broadcast counter */
@@ -123,6 +98,7 @@
 	u32	fwd_drop_noroute; 	/* Fwd: No route to Destination */
 	u32	fwd_drop_nobuf;		/* Fwd: Run out of internal buffers */
 	u32	drop_blind;		/* Rx:  Dropped by blinding table */
+	u32	tx_failed_cnt;		/* Tx:  Failed transmissions */
 };
 
 /** Private structure for the MV device */
@@ -131,8 +107,11 @@
 	int mesh_open;
 	int infra_open;
 
+	char name[DEV_NAME_LEN];
+
+	void *card;
 	wlan_adapter *adapter;
-	wlan_dev_t wlan_dev;
+	struct net_device *dev;
 
 	struct net_device_stats stats;
 	struct net_device *mesh_dev ; /* Virtual device */
@@ -153,6 +132,16 @@
 	u32 bbp_offset;
 	u32 rf_offset;
 
+	/** Upload length */
+	u32 upld_len;
+	/* Upload buffer */
+	u8 upld_buf[WLAN_UPLD_SIZE];
+	/* Download sent:
+	   bit0 1/0=data_sent/data_tx_done,
+	   bit1 1/0=cmd_sent/cmd_tx_done,
+	   all other bits reserved 0 */
+	u8 dnld_sent;
+
 	const struct firmware *firmware;
 	struct device *hotplug_device;
 
@@ -161,6 +150,15 @@
 
 	struct delayed_work assoc_work;
 	struct workqueue_struct *assoc_thread;
+	struct work_struct sync_channel;
+
+	/** Hardware access */
+	int (*hw_register_dev) (wlan_private * priv);
+	int (*hw_unregister_dev) (wlan_private *);
+	int (*hw_prog_firmware) (wlan_private *);
+	int (*hw_host_to_card) (wlan_private * priv, u8 type, u8 * payload, u16 nb);
+	int (*hw_get_int_status) (wlan_private * priv, u8 *);
+	int (*hw_read_event_cause) (wlan_private *);
 };
 
 /** Association request
@@ -171,18 +169,21 @@
 struct assoc_request {
 #define ASSOC_FLAG_SSID			1
 #define ASSOC_FLAG_CHANNEL		2
-#define ASSOC_FLAG_MODE			3
-#define ASSOC_FLAG_BSSID		4
-#define ASSOC_FLAG_WEP_KEYS		5
-#define ASSOC_FLAG_WEP_TX_KEYIDX	6
-#define ASSOC_FLAG_WPA_MCAST_KEY	7
-#define ASSOC_FLAG_WPA_UCAST_KEY	8
-#define ASSOC_FLAG_SECINFO		9
-#define ASSOC_FLAG_WPA_IE		10
+#define ASSOC_FLAG_BAND			3
+#define ASSOC_FLAG_MODE			4
+#define ASSOC_FLAG_BSSID		5
+#define ASSOC_FLAG_WEP_KEYS		6
+#define ASSOC_FLAG_WEP_TX_KEYIDX	7
+#define ASSOC_FLAG_WPA_MCAST_KEY	8
+#define ASSOC_FLAG_WPA_UCAST_KEY	9
+#define ASSOC_FLAG_SECINFO		10
+#define ASSOC_FLAG_WPA_IE		11
 	unsigned long flags;
 
-	struct WLAN_802_11_SSID ssid;
+	u8 ssid[IW_ESSID_MAX_SIZE + 1];
+	u8 ssid_len;
 	u8 channel;
+	u8 band;
 	u8 mode;
 	u8 bssid[ETH_ALEN];
 
@@ -199,12 +200,15 @@
 	/** WPA Information Elements*/
 	u8 wpa_ie[MAX_WPA_IE_LEN];
 	u8 wpa_ie_len;
+
+	/* BSS to associate with for infrastructure of Ad-Hoc join */
+	struct bss_descriptor bss;
 };
 
 /** Wlan adapter data structure*/
 struct _wlan_adapter {
 	/** STATUS variables */
-	u32 fwreleasenumber;
+	u8 fwreleasenumber[4];
 	u32 fwcapinfo;
 	/* protected with big lock */
 
@@ -255,13 +259,14 @@
 	/* IW_MODE_* */
 	u8 mode;
 
-	struct bss_descriptor *pattemptedbssdesc;
+	u8 prev_ssid[IW_ESSID_MAX_SIZE + 1];
+	u8 prev_ssid_len;
+	u8 prev_bssid[ETH_ALEN];
 
-	struct WLAN_802_11_SSID previousssid;
-	u8 previousbssid[ETH_ALEN];
-
-	struct bss_descriptor *scantable;
-	u32 numinscantable;
+	/* Scan results list */
+	struct list_head network_list;
+	struct list_head network_free_list;
+	struct bss_descriptor *networks;
 
 	u8 scantype;
 	u32 scanmode;
@@ -288,7 +293,6 @@
 	u32 txantenna;
 	u32 rxantenna;
 
-	u8 adhocchannel;
 	u32 fragthsd;
 	u32 rtsthsd;
 
@@ -324,7 +328,8 @@
 	u16 locallisteninterval;
 	u16 nullpktinterval;
 
-	struct assoc_request * assoc_req;
+	struct assoc_request * pending_assoc_req;
+	struct assoc_request * in_progress_assoc_req;
 
 	/** Encryption parameter */
 	struct wlan_802_11_security secinfo;
@@ -396,6 +401,8 @@
 	u32 radiomode;
 	u32 debugmode;
 	u8 fw_ready;
+
+	u8 last_scanned_channel;
 };
 
 #endif				/* _WLAN_DEV_H_ */
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 0064de5..96f1974 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -1,10 +1,8 @@
-
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
 #include <linux/delay.h>
 
 #include "host.h"
-#include "sbi.h"
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
@@ -17,7 +15,8 @@
 			"drop_no_buffers",
 			"fwded_unicast_cnt",
 			"fwded_bcast_cnt",
-			"drop_blind_table"
+			"drop_blind_table",
+			"tx_failed_cnt"
 };
 
 static void libertas_ethtool_get_drvinfo(struct net_device *dev,
@@ -69,7 +68,7 @@
 
 	/* +14 is for action, offset, and NOB in
 	 * response */
-	lbs_pr_debug(1, "action:%d offset: %x NOB: %02x\n",
+	lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n",
 	       regctrl.action, regctrl.offset, regctrl.NOB);
 
 	ret = libertas_prepare_and_send_command(priv,
@@ -81,8 +80,7 @@
 	if (ret) {
 		if (adapter->prdeeprom)
 			kfree(adapter->prdeeprom);
-		LEAVE();
-			return ret;
+		goto done;
 	}
 
 	mdelay(10);
@@ -101,7 +99,11 @@
 		kfree(adapter->prdeeprom);
 //	mutex_unlock(&priv->mutex);
 
-        return 0;
+	ret = 0;
+
+done:
+	lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret);
+        return ret;
 }
 
 static void libertas_ethtool_get_stats(struct net_device * dev,
@@ -109,7 +111,7 @@
 {
 	wlan_private *priv = dev->priv;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
 
 	stats->cmd = ETHTOOL_GSTATS;
 	BUG_ON(stats->n_stats != MESH_STATS_NUM);
@@ -121,8 +123,9 @@
         data[4] = priv->mstats.fwd_unicast_cnt;
         data[5] = priv->mstats.fwd_bcast_cnt;
         data[6] = priv->mstats.drop_blind;
+        data[7] = priv->mstats.tx_failed_cnt;
 
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
 }
 
 static int libertas_ethtool_get_stats_count(struct net_device * dev)
@@ -131,27 +134,32 @@
 	wlan_private *priv = dev->priv;
 	struct cmd_ds_mesh_access mesh_access;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+
 	/* Get Mesh Statistics */
 	ret = libertas_prepare_and_send_command(priv,
 			cmd_mesh_access, cmd_act_mesh_get_stats,
 			cmd_option_waitforrsp, 0, &mesh_access);
 
 	if (ret) {
-		LEAVE();
-		return 0;
+		ret = 0;
+		goto done;
 	}
 
-        priv->mstats.fwd_drop_rbt = mesh_access.data[0];
-        priv->mstats.fwd_drop_ttl = mesh_access.data[1];
-        priv->mstats.fwd_drop_noroute = mesh_access.data[2];
-        priv->mstats.fwd_drop_nobuf = mesh_access.data[3];
-        priv->mstats.fwd_unicast_cnt = mesh_access.data[4];
-        priv->mstats.fwd_bcast_cnt = mesh_access.data[5];
-        priv->mstats.drop_blind = mesh_access.data[6];
+        priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
+        priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
+        priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
+        priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
+        priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
+        priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
+        priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
+        priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
 
-	LEAVE();
-	return MESH_STATS_NUM;
+	ret = MESH_STATS_NUM;
+
+done:
+	lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret);
+	return ret;
 }
 
 static void libertas_ethtool_get_strings (struct net_device * dev,
@@ -160,7 +168,8 @@
 {
 	int i;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+
 	switch (stringset) {
         case ETH_SS_STATS:
 		for (i=0; i < MESH_STATS_NUM; i++) {
@@ -170,7 +179,7 @@
 		}
 		break;
         }
-	LEAVE();
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
 }
 
 struct ethtool_ops libertas_ethtool_ops = {
diff --git a/drivers/net/wireless/libertas/fw.c b/drivers/net/wireless/libertas/fw.c
index 441123c..2dc84ff 100644
--- a/drivers/net/wireless/libertas/fw.c
+++ b/drivers/net/wireless/libertas/fw.c
@@ -1,28 +1,15 @@
 /**
   * This file contains the initialization for FW and HW
   */
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/vmalloc.h>
 #include <linux/firmware.h>
-#include <linux/version.h>
 
 #include "host.h"
-#include "sbi.h"
 #include "defs.h"
 #include "decl.h"
 #include "dev.h"
-#include "fw.h"
 #include "wext.h"
 #include "if_usb.h"
 
-char *libertas_fw_name = NULL;
-module_param_named(fw_name, libertas_fw_name, charp, 0644);
-
-unsigned int libertas_debug = 0;
-module_param(libertas_debug, int, 0);
-
 /**
  *  @brief This function checks the validity of Boot2/FW image.
  *
@@ -32,7 +19,7 @@
  */
 static int check_fwfile_format(u8 *data, u32 totlen)
 {
-	u8  bincmd, exit;
+	u32 bincmd, exit;
 	u32 blksize, offset, len;
 	int ret;
 
@@ -40,8 +27,10 @@
 	exit = len = 0;
 
 	do {
-		bincmd = *data;
-		blksize = *(u32*)(data + offsetof(struct fwheader, datalength));
+		struct fwheader *fwh = (void *)data;
+
+		bincmd = le32_to_cpu(fwh->dnldcmd);
+		blksize = le32_to_cpu(fwh->datalength);
 		switch (bincmd) {
 		case FW_HAS_DATA_TO_RECV:
 			offset = sizeof(struct fwheader) + blksize;
@@ -61,9 +50,9 @@
 	} while (!exit);
 
 	if (ret)
-		lbs_pr_err("bin file format check FAIL...\n");
+		lbs_pr_err("firmware file format check FAIL\n");
 	else
-		lbs_pr_debug(1, "bin file format check PASS...\n");
+		lbs_deb_fw("firmware file format check PASS\n");
 
 	return ret;
 }
@@ -76,32 +65,31 @@
  *  @param priv    A pointer to wlan_private structure
  *  @return 	   0 or -1
  */
-static int wlan_setup_station_hw(wlan_private * priv)
+static int wlan_setup_station_hw(wlan_private * priv, char *fw_name)
 {
 	int ret = -1;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_FW);
 
-	if ((ret = request_firmware(&priv->firmware, libertas_fw_name,
+	if ((ret = request_firmware(&priv->firmware, fw_name,
 				    priv->hotplug_device)) < 0) {
-		lbs_pr_err("request_firmware() failed, error code = %#x\n",
-		       ret);
-		lbs_pr_err("%s not found in /lib/firmware\n", libertas_fw_name);
+		lbs_pr_err("request_firmware() failed with %#x\n", ret);
+		lbs_pr_err("firmware %s not found\n", fw_name);
 		goto done;
 	}
 
-	if(check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
+	if (check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
 		release_firmware(priv->firmware);
 		goto done;
 	}
 
-	ret = libertas_sbi_prog_firmware(priv);
+	ret = priv->hw_prog_firmware(priv);
 
 	release_firmware(priv->firmware);
 
 	if (ret) {
-		lbs_pr_debug(1, "Bootloader in invalid state!\n");
+		lbs_deb_fw("bootloader in invalid state\n");
 		ret = -1;
 		goto done;
 	}
@@ -133,28 +121,24 @@
 
 	ret = 0;
 done:
-	LEAVE();
-
-	return (ret);
+	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+	return ret;
 }
 
 static int wlan_allocate_adapter(wlan_private * priv)
 {
-	u32 ulbufsize;
+	size_t bufsize;
 	wlan_adapter *adapter = priv->adapter;
 
-	struct bss_descriptor *ptempscantable;
-
 	/* Allocate buffer to store the BSSID list */
-	ulbufsize = sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST;
-	if (!(ptempscantable = kmalloc(ulbufsize, GFP_KERNEL))) {
+	bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
+	adapter->networks = kzalloc(bufsize, GFP_KERNEL);
+	if (!adapter->networks) {
+		lbs_pr_err("Out of memory allocating beacons\n");
 		libertas_free_adapter(priv);
-		return -1;
+		return -ENOMEM;
 	}
 
-	adapter->scantable = ptempscantable;
-	memset(adapter->scantable, 0, ulbufsize);
-
 	/* Allocate the command buffers */
 	libertas_allocate_cmd_buffer(priv);
 
@@ -202,15 +186,23 @@
 	adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
 	adapter->mode = IW_MODE_INFRA;
 
-	adapter->assoc_req = NULL;
+	adapter->pending_assoc_req = NULL;
+	adapter->in_progress_assoc_req = NULL;
 
-	adapter->numinscantable = 0;
-	adapter->pattemptedbssdesc = NULL;
+	/* Initialize scan result lists */
+	INIT_LIST_HEAD(&adapter->network_free_list);
+	INIT_LIST_HEAD(&adapter->network_list);
+	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
+		list_add_tail(&adapter->networks[i].list,
+			      &adapter->network_free_list);
+	}
+
 	mutex_init(&adapter->lock);
 
 	adapter->prescan = 1;
 
 	memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
+	adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
 
 	/* PnP and power profile */
 	adapter->surpriseremoved = 0;
@@ -230,8 +222,6 @@
 	memset(&adapter->capinfo, 0, sizeof(adapter->capinfo));
 	adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED;
 
-	adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL;
-
 	adapter->psmode = wlan802_11powermodecam;
 	adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
 
@@ -259,12 +249,12 @@
 
 static void command_timer_fn(unsigned long data);
 
-int libertas_init_fw(wlan_private * priv)
+int libertas_init_fw(wlan_private * priv, char *fw_name)
 {
 	int ret = -1;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_FW);
 
 	/* Allocate adapter structure */
 	if ((ret = wlan_allocate_adapter(priv)) != 0)
@@ -278,7 +268,7 @@
 			(unsigned long)priv);
 
 	/* download fimrware etc. */
-	if ((ret = wlan_setup_station_hw(priv)) != 0) {
+	if ((ret = wlan_setup_station_hw(priv, fw_name)) != 0) {
 		del_timer_sync(&adapter->command_timer);
 		goto done;
 	}
@@ -288,7 +278,7 @@
 
 	ret = 0;
 done:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
 	return ret;
 }
 
@@ -297,25 +287,22 @@
 	wlan_adapter *adapter = priv->adapter;
 
 	if (!adapter) {
-		lbs_pr_debug(1, "Why double free adapter?:)\n");
+		lbs_deb_fw("why double free adapter?\n");
 		return;
 	}
 
-	lbs_pr_debug(1, "Free command buffer\n");
+	lbs_deb_fw("free command buffer\n");
 	libertas_free_cmd_buffer(priv);
 
-	lbs_pr_debug(1, "Free commandTimer\n");
+	lbs_deb_fw("free command_timer\n");
 	del_timer(&adapter->command_timer);
 
-	lbs_pr_debug(1, "Free scantable\n");
-	if (adapter->scantable) {
-		kfree(adapter->scantable);
-		adapter->scantable = NULL;
-	}
-
-	lbs_pr_debug(1, "Free adapter\n");
+	lbs_deb_fw("free scan results table\n");
+	kfree(adapter->networks);
+	adapter->networks = NULL;
 
 	/* Free the adapter object itself */
+	lbs_deb_fw("free adapter\n");
 	kfree(adapter);
 	priv->adapter = NULL;
 }
@@ -333,23 +320,27 @@
 	unsigned long flags;
 
 	ptempnode = adapter->cur_cmd;
-	cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr;
+	if (ptempnode == NULL) {
+		lbs_deb_fw("ptempnode empty\n");
+		return;
+	}
 
-	lbs_pr_info("command_timer_fn fired (%x)\n", cmd->command);
+	cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr;
+	if (!cmd) {
+		lbs_deb_fw("cmd is NULL\n");
+		return;
+	}
+
+	lbs_deb_fw("command_timer_fn fired, cmd %x\n", cmd->command);
 
 	if (!adapter->fw_ready)
 		return;
 
-	if (ptempnode == NULL) {
-		lbs_pr_debug(1, "PTempnode Empty\n");
-		return;
-	}
-
 	spin_lock_irqsave(&adapter->driver_lock, flags);
 	adapter->cur_cmd = NULL;
 	spin_unlock_irqrestore(&adapter->driver_lock, flags);
 
-	lbs_pr_debug(1, "Re-sending same command as it timeout...!\n");
+	lbs_deb_fw("re-sending same command because of timeout\n");
 	libertas_queue_cmd(adapter, ptempnode, 0);
 
 	wake_up_interruptible(&priv->mainthread.waitq);
diff --git a/drivers/net/wireless/libertas/fw.h b/drivers/net/wireless/libertas/fw.h
deleted file mode 100644
index 1f9ae26..0000000
--- a/drivers/net/wireless/libertas/fw.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
-  * This header file contains FW interface related definitions.
-  */
-#ifndef _WLAN_FW_H_
-#define _WLAN_FW_H_
-
-#ifndef DEV_NAME_LEN
-#define DEV_NAME_LEN            32
-#endif
-
-int libertas_init_fw(wlan_private * priv);
-
-#endif				/* _WLAN_FW_H_ */
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index c0faaec..7509cc1 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -99,11 +99,11 @@
 #define cmd_bt_access                 0x0087
 #define cmd_ret_bt_access                 0x8087
 
-#define cmd_fwt_access                0x0088
-#define cmd_ret_fwt_access                0x8088
+#define cmd_fwt_access                0x0095
+#define cmd_ret_fwt_access                0x8095
 
-#define cmd_mesh_access               0x0090
-#define cmd_ret_mesh_access               0x8090
+#define cmd_mesh_access               0x009b
+#define cmd_ret_mesh_access               0x809b
 
 /* For the IEEE Power Save */
 #define cmd_subcmd_enter_ps               0x0030
@@ -287,7 +287,9 @@
 	cmd_act_bt_access_add = 5,
 	cmd_act_bt_access_del,
 	cmd_act_bt_access_list,
-	cmd_act_bt_access_reset
+	cmd_act_bt_access_reset,
+	cmd_act_bt_access_set_invert,
+	cmd_act_bt_access_get_invert
 };
 
 /* Define action or option for cmd_fwt_access */
@@ -308,8 +310,8 @@
 	cmd_act_mesh_get_ttl = 1,
 	cmd_act_mesh_set_ttl,
 	cmd_act_mesh_get_stats,
-	cmd_act_mesh_get_mpp,
-	cmd_act_mesh_set_mpp,
+	cmd_act_mesh_get_anycast,
+	cmd_act_mesh_set_anycast,
 };
 
 /** Card Event definition */
@@ -334,5 +336,6 @@
 #define MACREG_INT_CODE_MAX_FAIL		0x0000001b
 #define MACREG_INT_CODE_RSSI_HIGH		0x0000001c
 #define MACREG_INT_CODE_SNR_HIGH		0x0000001d
+#define MACREG_INT_CODE_MESH_AUTO_STARTED	0x00000023
 
 #endif				/* _HOST_H_ */
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index f239e5d..09b898f 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -14,12 +14,12 @@
 /* TxPD descriptor */
 struct txpd {
 	/* Current Tx packet status */
-	u32 tx_status;
+	__le32 tx_status;
 	/* Tx control */
-	u32 tx_control;
-	u32 tx_packet_location;
+	__le32 tx_control;
+	__le32 tx_packet_location;
 	/* Tx packet length */
-	u16 tx_packet_length;
+	__le16 tx_packet_length;
 	/* First 2 byte of destination MAC address */
 	u8 tx_dest_addr_high[2];
 	/* Last 4 byte of destination MAC address */
@@ -37,7 +37,7 @@
 /* RxPD Descriptor */
 struct rxpd {
 	/* Current Rx packet status */
-	u16 status;
+	__le16 status;
 
 	/* SNR */
 	u8 snr;
@@ -46,7 +46,7 @@
 	u8 rx_control;
 
 	/* Pkt length */
-	u16 pkt_len;
+	__le16 pkt_len;
 
 	/* Noise Floor */
 	u8 nf;
@@ -55,10 +55,10 @@
 	u8 rx_rate;
 
 	/* Pkt addr */
-	u32 pkt_ptr;
+	__le32 pkt_ptr;
 
 	/* Next Rx RxPD addr */
-	u32 next_rxpd_ptr;
+	__le32 next_rxpd_ptr;
 
 	/* Pkt Priority */
 	u8 priority;
@@ -89,30 +89,17 @@
  * is determined from the keylength field.
  */
 struct WLAN_802_11_KEY {
-	u32 len;
-	u32 flags;  /* KEY_INFO_* from wlan_defs.h */
+	__le32 len;
+	__le32 flags;  /* KEY_INFO_* from wlan_defs.h */
 	u8 key[MRVL_MAX_KEY_WPA_KEY_LENGTH];
-	u16 type; /* KEY_TYPE_* from wlan_defs.h */
+	__le16 type; /* KEY_TYPE_* from wlan_defs.h */
 };
 
 struct IE_WPA {
 	u8 elementid;
 	u8 len;
 	u8 oui[4];
-	u16 version;
-};
-
-struct WLAN_802_11_SSID {
-	/* SSID length */
-	u32 ssidlength;
-
-	/* SSID information field */
-	u8 ssid[IW_ESSID_MAX_SIZE];
-};
-
-struct WPA_SUPPLICANT {
-	u8 wpa_ie[256];
-	u8 wpa_ie_len;
+	__le16 version;
 };
 
 /* wlan_offset_value */
@@ -122,9 +109,9 @@
 };
 
 struct WLAN_802_11_FIXED_IEs {
-	u8 timestamp[8];
-	u16 beaconinterval;
-	u16 capabilities;
+	__le64 timestamp;
+	__le16 beaconinterval;
+	u16 capabilities; /* Actually struct ieeetypes_capinfo */
 };
 
 struct WLAN_802_11_VARIABLE_IEs {
@@ -136,10 +123,10 @@
 /* Define general data structure */
 /* cmd_DS_GEN */
 struct cmd_ds_gen {
-	u16 command;
-	u16 size;
-	u16 seqnum;
-	u16 result;
+	__le16 command;
+	__le16 size;
+	__le16 seqnum;
+	__le16 result;
 };
 
 #define S_DS_GEN sizeof(struct cmd_ds_gen)
@@ -149,44 +136,44 @@
  */
 struct cmd_ds_get_hw_spec {
 	/* HW Interface version number */
-	u16 hwifversion;
+	__le16 hwifversion;
 	/* HW version number */
-	u16 version;
+	__le16 version;
 	/* Max number of TxPD FW can handle */
-	u16 nr_txpd;
+	__le16 nr_txpd;
 	/* Max no of Multicast address */
-	u16 nr_mcast_adr;
+	__le16 nr_mcast_adr;
 	/* MAC address */
 	u8 permanentaddr[6];
 
 	/* region Code */
-	u16 regioncode;
+	__le16 regioncode;
 
 	/* Number of antenna used */
-	u16 nr_antenna;
+	__le16 nr_antenna;
 
-	/* FW release number, example 0x1234=1.2.3.4 */
-	u32 fwreleasenumber;
+	/* FW release number, example 1,2,3,4 = 3.2.1p4 */
+	u8 fwreleasenumber[4];
 
 	/* Base Address of TxPD queue */
-	u32 wcb_base;
+	__le32 wcb_base;
 	/* Read Pointer of RxPd queue */
-	u32 rxpd_rdptr;
+	__le32 rxpd_rdptr;
 
 	/* Write Pointer of RxPd queue */
-	u32 rxpd_wrptr;
+	__le32 rxpd_wrptr;
 
 	/*FW/HW capability */
-	u32 fwcapinfo;
+	__le32 fwcapinfo;
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_reset {
-	u16 action;
+	__le16 action;
 };
 
 struct cmd_ds_802_11_subscribe_event {
-	u16 action;
-	u16 events;
+	__le16 action;
+	__le16 events;
 };
 
 /*
@@ -205,35 +192,35 @@
 };
 
 struct cmd_ds_802_11_scan_rsp {
-	u16 bssdescriptsize;
+	__le16 bssdescriptsize;
 	u8 nr_sets;
 	u8 bssdesc_and_tlvbuffer[1];
 };
 
 struct cmd_ds_802_11_get_log {
-	u32 mcasttxframe;
-	u32 failed;
-	u32 retry;
-	u32 multiretry;
-	u32 framedup;
-	u32 rtssuccess;
-	u32 rtsfailure;
-	u32 ackfailure;
-	u32 rxfrag;
-	u32 mcastrxframe;
-	u32 fcserror;
-	u32 txframe;
-	u32 wepundecryptable;
+	__le32 mcasttxframe;
+	__le32 failed;
+	__le32 retry;
+	__le32 multiretry;
+	__le32 framedup;
+	__le32 rtssuccess;
+	__le32 rtsfailure;
+	__le32 ackfailure;
+	__le32 rxfrag;
+	__le32 mcastrxframe;
+	__le32 fcserror;
+	__le32 txframe;
+	__le32 wepundecryptable;
 };
 
 struct cmd_ds_mac_control {
-	u16 action;
-	u16 reserved;
+	__le16 action;
+	__le16 reserved;
 };
 
 struct cmd_ds_mac_multicast_adr {
-	u16 action;
-	u16 nr_of_adrs;
+	__le16 action;
+	__le16 nr_of_adrs;
 	u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
 };
 
@@ -245,14 +232,14 @@
 
 struct cmd_ds_802_11_deauthenticate {
 	u8 macaddr[6];
-	u16 reasoncode;
+	__le16 reasoncode;
 };
 
 struct cmd_ds_802_11_associate {
 	u8 peerstaaddr[6];
 	struct ieeetypes_capinfo capinfo;
-	u16 listeninterval;
-	u16 bcnperiod;
+	__le16 listeninterval;
+	__le16 bcnperiod;
 	u8 dtimperiod;
 
 #if 0
@@ -265,7 +252,7 @@
 
 struct cmd_ds_802_11_disassociate {
 	u8 destmacaddr[6];
-	u16 reasoncode;
+	__le16 reasoncode;
 };
 
 struct cmd_ds_802_11_associate_rsp {
@@ -279,10 +266,10 @@
 
 struct cmd_ds_802_11_set_wep {
 	/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
-	u16 action;
+	__le16 action;
 
 	/* key Index selected for Tx */
-	u16 keyindex;
+	__le16 keyindex;
 
 	/* 40, 128bit or TXWEP */
 	u8 keytype[4];
@@ -290,96 +277,96 @@
 };
 
 struct cmd_ds_802_3_get_stat {
-	u32 xmitok;
-	u32 rcvok;
-	u32 xmiterror;
-	u32 rcverror;
-	u32 rcvnobuffer;
-	u32 rcvcrcerror;
+	__le32 xmitok;
+	__le32 rcvok;
+	__le32 xmiterror;
+	__le32 rcverror;
+	__le32 rcvnobuffer;
+	__le32 rcvcrcerror;
 };
 
 struct cmd_ds_802_11_get_stat {
-	u32 txfragmentcnt;
-	u32 mcasttxframecnt;
-	u32 failedcnt;
-	u32 retrycnt;
-	u32 Multipleretrycnt;
-	u32 rtssuccesscnt;
-	u32 rtsfailurecnt;
-	u32 ackfailurecnt;
-	u32 frameduplicatecnt;
-	u32 rxfragmentcnt;
-	u32 mcastrxframecnt;
-	u32 fcserrorcnt;
-	u32 bcasttxframecnt;
-	u32 bcastrxframecnt;
-	u32 txbeacon;
-	u32 rxbeacon;
-	u32 wepundecryptable;
+	__le32 txfragmentcnt;
+	__le32 mcasttxframecnt;
+	__le32 failedcnt;
+	__le32 retrycnt;
+	__le32 Multipleretrycnt;
+	__le32 rtssuccesscnt;
+	__le32 rtsfailurecnt;
+	__le32 ackfailurecnt;
+	__le32 frameduplicatecnt;
+	__le32 rxfragmentcnt;
+	__le32 mcastrxframecnt;
+	__le32 fcserrorcnt;
+	__le32 bcasttxframecnt;
+	__le32 bcastrxframecnt;
+	__le32 txbeacon;
+	__le32 rxbeacon;
+	__le32 wepundecryptable;
 };
 
 struct cmd_ds_802_11_snmp_mib {
-	u16 querytype;
-	u16 oid;
-	u16 bufsize;
+	__le16 querytype;
+	__le16 oid;
+	__le16 bufsize;
 	u8 value[128];
 };
 
 struct cmd_ds_mac_reg_map {
-	u16 buffersize;
+	__le16 buffersize;
 	u8 regmap[128];
-	u16 reserved;
+	__le16 reserved;
 };
 
 struct cmd_ds_bbp_reg_map {
-	u16 buffersize;
+	__le16 buffersize;
 	u8 regmap[128];
-	u16 reserved;
+	__le16 reserved;
 };
 
 struct cmd_ds_rf_reg_map {
-	u16 buffersize;
+	__le16 buffersize;
 	u8 regmap[64];
-	u16 reserved;
+	__le16 reserved;
 };
 
 struct cmd_ds_mac_reg_access {
-	u16 action;
-	u16 offset;
-	u32 value;
+	__le16 action;
+	__le16 offset;
+	__le32 value;
 };
 
 struct cmd_ds_bbp_reg_access {
-	u16 action;
-	u16 offset;
+	__le16 action;
+	__le16 offset;
 	u8 value;
 	u8 reserved[3];
 };
 
 struct cmd_ds_rf_reg_access {
-	u16 action;
-	u16 offset;
+	__le16 action;
+	__le16 offset;
 	u8 value;
 	u8 reserved[3];
 };
 
 struct cmd_ds_802_11_radio_control {
-	u16 action;
-	u16 control;
+	__le16 action;
+	__le16 control;
 };
 
 struct cmd_ds_802_11_sleep_params {
 	/* ACT_GET/ACT_SET */
-	u16 action;
+	__le16 action;
 
 	/* Sleep clock error in ppm */
-	u16 error;
+	__le16 error;
 
 	/* Wakeup offset in usec */
-	u16 offset;
+	__le16 offset;
 
 	/* Clock stabilization time in usec */
-	u16 stabletime;
+	__le16 stabletime;
 
 	/* control periodic calibration */
 	u8 calcontrol;
@@ -388,100 +375,100 @@
 	u8 externalsleepclk;
 
 	/* reserved field, should be set to zero */
-	u16 reserved;
+	__le16 reserved;
 };
 
 struct cmd_ds_802_11_inactivity_timeout {
 	/* ACT_GET/ACT_SET */
-	u16 action;
+	__le16 action;
 
 	/* Inactivity timeout in msec */
-	u16 timeout;
+	__le16 timeout;
 };
 
 struct cmd_ds_802_11_rf_channel {
-	u16 action;
-	u16 currentchannel;
-	u16 rftype;
-	u16 reserved;
+	__le16 action;
+	__le16 currentchannel;
+	__le16 rftype;
+	__le16 reserved;
 	u8 channellist[32];
 };
 
 struct cmd_ds_802_11_rssi {
 	/* weighting factor */
-	u16 N;
+	__le16 N;
 
-	u16 reserved_0;
-	u16 reserved_1;
-	u16 reserved_2;
+	__le16 reserved_0;
+	__le16 reserved_1;
+	__le16 reserved_2;
 };
 
 struct cmd_ds_802_11_rssi_rsp {
-	u16 SNR;
-	u16 noisefloor;
-	u16 avgSNR;
-	u16 avgnoisefloor;
+	__le16 SNR;
+	__le16 noisefloor;
+	__le16 avgSNR;
+	__le16 avgnoisefloor;
 };
 
 struct cmd_ds_802_11_mac_address {
-	u16 action;
+	__le16 action;
 	u8 macadd[ETH_ALEN];
 };
 
 struct cmd_ds_802_11_rf_tx_power {
-	u16 action;
-	u16 currentlevel;
+	__le16 action;
+	__le16 currentlevel;
 };
 
 struct cmd_ds_802_11_rf_antenna {
-	u16 action;
+	__le16 action;
 
 	/* Number of antennas or 0xffff(diversity) */
-	u16 antennamode;
+	__le16 antennamode;
 
 };
 
 struct cmd_ds_802_11_ps_mode {
-	u16 action;
-	u16 nullpktinterval;
-	u16 multipledtim;
-	u16 reserved;
-	u16 locallisteninterval;
+	__le16 action;
+	__le16 nullpktinterval;
+	__le16 multipledtim;
+	__le16 reserved;
+	__le16 locallisteninterval;
 };
 
 struct PS_CMD_ConfirmSleep {
-	u16 command;
-	u16 size;
-	u16 seqnum;
-	u16 result;
+	__le16 command;
+	__le16 size;
+	__le16 seqnum;
+	__le16 result;
 
-	u16 action;
-	u16 reserved1;
-	u16 multipledtim;
-	u16 reserved;
-	u16 locallisteninterval;
+	__le16 action;
+	__le16 reserved1;
+	__le16 multipledtim;
+	__le16 reserved;
+	__le16 locallisteninterval;
 };
 
 struct cmd_ds_802_11_data_rate {
-	u16 action;
-	u16 reserverd;
+	__le16 action;
+	__le16 reserverd;
 	u8 datarate[G_SUPPORTED_RATES];
 };
 
 struct cmd_ds_802_11_rate_adapt_rateset {
-	u16 action;
-	u16 enablehwauto;
-	u16 bitmap;
+	__le16 action;
+	__le16 enablehwauto;
+	__le16 bitmap;
 };
 
 struct cmd_ds_802_11_ad_hoc_start {
 	u8 SSID[IW_ESSID_MAX_SIZE];
 	u8 bsstype;
-	u16 beaconperiod;
+	__le16 beaconperiod;
 	u8 dtimperiod;
 	union IEEEtypes_ssparamset ssparamset;
 	union ieeetypes_phyparamset phyparamset;
-	u16 probedelay;
+	__le16 probedelay;
 	struct ieeetypes_capinfo cap;
 	u8 datarate[G_SUPPORTED_RATES];
 	u8 tlv_memory_size_pad[100];
@@ -491,10 +478,10 @@
 	u8 BSSID[6];
 	u8 SSID[32];
 	u8 bsstype;
-	u16 beaconperiod;
+	__le16 beaconperiod;
 	u8 dtimperiod;
-	u8 timestamp[8];
-	u8 localtime[8];
+	__le64 timestamp;
+	__le64 localtime;
 	union ieeetypes_phyparamset phyparamset;
 	union IEEEtypes_ssparamset ssparamset;
 	struct ieeetypes_capinfo cap;
@@ -508,52 +495,52 @@
 
 struct cmd_ds_802_11_ad_hoc_join {
 	struct adhoc_bssdesc bssdescriptor;
-	u16 failtimeout;
-	u16 probedelay;
+	__le16 failtimeout;
+	__le16 probedelay;
 
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_enable_rsn {
-	u16 action;
-	u16 enable;
-};
+	__le16 action;
+	__le16 enable;
+} __attribute__ ((packed));
 
 struct MrvlIEtype_keyParamSet {
 	/* type ID */
-	u16 type;
+	__le16 type;
 
 	/* length of Payload */
-	u16 length;
+	__le16 length;
 
 	/* type of key: WEP=0, TKIP=1, AES=2 */
-	u16 keytypeid;
+	__le16 keytypeid;
 
 	/* key control Info specific to a keytypeid */
-	u16 keyinfo;
+	__le16 keyinfo;
 
 	/* length of key */
-	u16 keylen;
+	__le16 keylen;
 
 	/* key material of size keylen */
 	u8 key[32];
 };
 
 struct cmd_ds_802_11_key_material {
-	u16 action;
+	__le16 action;
 	struct MrvlIEtype_keyParamSet keyParamSet[2];
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_eeprom_access {
-	u16 action;
+	__le16 action;
 
 	/* multiple 4 */
-	u16 offset;
-	u16 bytecount;
+	__le16 offset;
+	__le16 bytecount;
 	u8 value;
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_tpc_cfg {
-	u16 action;
+	__le16 action;
 	u8 enable;
 	s8 P0;
 	s8 P1;
@@ -562,13 +549,13 @@
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_led_ctrl {
-	u16 action;
-	u16 numled;
+	__le16 action;
+	__le16 numled;
 	u8 data[256];
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_pwr_cfg {
-	u16 action;
+	__le16 action;
 	u8 enable;
 	s8 PA_P0;
 	s8 PA_P1;
@@ -576,21 +563,21 @@
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_afc {
-	u16 afc_auto;
+	__le16 afc_auto;
 	union {
 		struct {
-			u16 threshold;
-			u16 period;
+			__le16 threshold;
+			__le16 period;
 		};
 		struct {
-			s16 timing_offset;
-			s16 carrier_offset;
+			__le16 timing_offset; /* signed */
+			__le16 carrier_offset; /* signed */
 		};
 	};
 } __attribute__ ((packed));
 
 struct cmd_tx_rate_query {
-	u16 txrate;
+	__le16 txrate;
 } __attribute__ ((packed));
 
 struct cmd_ds_get_tsf {
@@ -598,41 +585,46 @@
 } __attribute__ ((packed));
 
 struct cmd_ds_bt_access {
-	u16 action;
-	u32 id;
+	__le16 action;
+	__le32 id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 } __attribute__ ((packed));
 
 struct cmd_ds_fwt_access {
-	u16 action;
-	u32 id;
+	__le16 action;
+	__le32 id;
+	u8 valid;
 	u8 da[ETH_ALEN];
 	u8 dir;
 	u8 ra[ETH_ALEN];
-	u32 ssn;
-	u32 dsn;
-	u32 metric;
+	__le32 ssn;
+	__le32 dsn;
+	__le32 metric;
+	u8 rate;
 	u8 hopcount;
 	u8 ttl;
-	u32 expiration;
+	__le32 expiration;
 	u8 sleepmode;
-	u32 snr;
-	u32 references;
+	__le32 snr;
+	__le32 references;
+	u8 prec[ETH_ALEN];
 } __attribute__ ((packed));
 
-#define MESH_STATS_NUM 7
 struct cmd_ds_mesh_access {
-	u16 action;
-	u32 data[MESH_STATS_NUM + 1];	/* last position reserved */
+	__le16 action;
+	__le32 data[32];	/* last position reserved */
 } __attribute__ ((packed));
 
+/* Number of stats counters returned by the firmware */
+#define MESH_STATS_NUM 8
+
 struct cmd_ds_command {
 	/* command header */
-	u16 command;
-	u16 size;
-	u16 seqnum;
-	u16 result;
+	__le16 command;
+	__le16 size;
+	__le16 seqnum;
+	__le16 result;
 
 	/* command Body */
 	union {
diff --git a/drivers/net/wireless/libertas/if_bootcmd.c b/drivers/net/wireless/libertas/if_bootcmd.c
index 567000c..8bca306 100644
--- a/drivers/net/wireless/libertas/if_bootcmd.c
+++ b/drivers/net/wireless/libertas/if_bootcmd.c
@@ -8,6 +8,8 @@
 #include <linux/netdevice.h>
 #include <linux/usb.h>
 
+#define DRV_NAME "usb8xxx"
+
 #include "defs.h"
 #include "dev.h"
 #include "if_usb.h"
@@ -20,12 +22,12 @@
  */
 int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
 {
-	struct usb_card_rec	*cardp = priv->wlan_dev.card;
+	struct usb_card_rec	*cardp = priv->card;
 	struct bootcmdstr	sbootcmd;
 	int i;
 
 	/* Prepare command */
-	sbootcmd.u32magicnumber = BOOT_CMD_MAGIC_NUMBER;
+	sbootcmd.u32magicnumber = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
 	sbootcmd.u8cmd_tag = ivalue;
 	for (i=0; i<11; i++)
 		sbootcmd.au8dumy[i]=0x00;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index ae6f72a..9983175 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -2,12 +2,15 @@
   * This file contains functions used in USB interface module.
   */
 #include <linux/delay.h>
+#include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <linux/netdevice.h>
+#include <linux/list.h>
 #include <linux/usb.h>
 
+#define DRV_NAME "usb8xxx"
+
 #include "host.h"
-#include "sbi.h"
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
@@ -16,15 +19,24 @@
 #define MESSAGE_HEADER_LEN	4
 
 static const char usbdriver_name[] = "usb8xxx";
+static u8 *default_fw_name = "usb8388.bin";
+
+char *libertas_fw_name = NULL;
+module_param_named(fw_name, libertas_fw_name, charp, 0644);
+
+/*
+ * We need to send a RESET command to all USB devices before
+ * we tear down the USB connection. Otherwise we would not
+ * be able to re-init device the device if the module gets
+ * loaded again. This is a list of all initialized USB devices,
+ * for the reset code see if_usb_reset_device()
+*/
+static LIST_HEAD(usb_devices);
 
 static struct usb_device_id if_usb_table[] = {
 	/* Enter the device signature inside */
-	{
-		USB_DEVICE(USB8388_VID_1, USB8388_PID_1),
-	},
-	{
-		USB_DEVICE(USB8388_VID_2, USB8388_PID_2),
-	},
+	{ USB_DEVICE(0x1286, 0x2001) },
+	{ USB_DEVICE(0x05a3, 0x8388) },
 	{}	/* Terminating entry */
 };
 
@@ -32,6 +44,13 @@
 
 static void if_usb_receive(struct urb *urb);
 static void if_usb_receive_fwload(struct urb *urb);
+static int if_usb_reset_device(wlan_private *priv);
+static int if_usb_register_dev(wlan_private * priv);
+static int if_usb_unregister_dev(wlan_private *);
+static int if_usb_prog_firmware(wlan_private *);
+static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
+static int if_usb_get_int_status(wlan_private * priv, u8 *);
+static int if_usb_read_event_cause(wlan_private *);
 
 /**
  *  @brief  call back function to handle the status of the URB
@@ -42,23 +61,27 @@
 {
 	wlan_private *priv = (wlan_private *) (urb->context);
 	wlan_adapter *adapter = priv->adapter;
-	struct net_device *dev = priv->wlan_dev.netdev;
+	struct net_device *dev = priv->dev;
 
 	/* handle the transmission complete validations */
 
 	if (urb->status != 0) {
 		/* print the failure status number for debug */
-		lbs_pr_info("URB in failure status\n");
+		lbs_pr_info("URB in failure status: %d\n", urb->status);
 	} else {
-		lbs_dev_dbg(2, &urb->dev->dev, "URB status is successfull\n");
-		lbs_dev_dbg(2, &urb->dev->dev, "Actual length transmitted %d\n",
+		/*
+		lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n");
+		lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n",
 		       urb->actual_length);
-		priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+		*/
+		priv->dnld_sent = DNLD_RES_RECEIVED;
 		/* Wake main thread if commands are pending */
 		if (!adapter->cur_cmd)
 			wake_up_interruptible(&priv->mainthread.waitq);
-		if ((adapter->connect_status == libertas_connected))
+		if ((adapter->connect_status == libertas_connected)) {
 			netif_wake_queue(dev);
+			netif_wake_queue(priv->mesh_dev);
+		}
 	}
 
 	return;
@@ -71,7 +94,7 @@
  */
 void if_usb_free(struct usb_card_rec *cardp)
 {
-	ENTER();
+	lbs_deb_enter(LBS_DEB_USB);
 
 	/* Unlink tx & rx urb */
 	usb_kill_urb(cardp->tx_urb);
@@ -86,8 +109,7 @@
 	kfree(cardp->bulk_out_buffer);
 	cardp->bulk_out_buffer = NULL;
 
-	LEAVE();
-	return;
+	lbs_deb_leave(LBS_DEB_USB);
 }
 
 /**
@@ -102,27 +124,27 @@
 	struct usb_device *udev;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
-	wlan_private *pwlanpriv;
-	struct usb_card_rec *usb_cardp;
+	wlan_private *priv;
+	struct usb_card_rec *cardp;
 	int i;
 
 	udev = interface_to_usbdev(intf);
 
-	usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
-	if (!usb_cardp) {
+	cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+	if (!cardp) {
 		lbs_pr_err("Out of memory allocating private data.\n");
 		goto error;
 	}
 
-	usb_cardp->udev = udev;
+	cardp->udev = udev;
 	iface_desc = intf->cur_altsetting;
 
-	lbs_dev_dbg(1, &udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
+	lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
 	       " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
-	       udev->descriptor.bcdUSB,
-	       udev->descriptor.bDeviceClass,
-	       udev->descriptor.bDeviceSubClass,
-	       udev->descriptor.bDeviceProtocol);
+		     le16_to_cpu(udev->descriptor.bcdUSB),
+		     udev->descriptor.bDeviceClass,
+		     udev->descriptor.bDeviceSubClass,
+		     udev->descriptor.bDeviceProtocol);
 
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
@@ -130,23 +152,21 @@
 		    && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
 			USB_ENDPOINT_XFER_BULK)) {
 			/* we found a bulk in endpoint */
-			lbs_dev_dbg(1, &udev->dev, "Bulk in size is %d\n",
-			       endpoint->wMaxPacketSize);
-			if (!
-			    (usb_cardp->rx_urb =
-			     usb_alloc_urb(0, GFP_KERNEL))) {
-				lbs_dev_dbg(1, &udev->dev,
+			lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n",
+				     le16_to_cpu(endpoint->wMaxPacketSize));
+			if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
+				lbs_deb_usbd(&udev->dev,
 				       "Rx URB allocation failed\n");
 				goto dealloc;
 			}
-			usb_cardp->rx_urb_recall = 0;
+			cardp->rx_urb_recall = 0;
 
-			usb_cardp->bulk_in_size =
-			    endpoint->wMaxPacketSize;
-			usb_cardp->bulk_in_endpointAddr =
+			cardp->bulk_in_size =
+				le16_to_cpu(endpoint->wMaxPacketSize);
+			cardp->bulk_in_endpointAddr =
 			    (endpoint->
 			     bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-			lbs_dev_dbg(1, &udev->dev, "in_endpoint = %d\n",
+			lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n",
 			       endpoint->bEndpointAddress);
 		}
 
@@ -156,55 +176,63 @@
 		    && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
 			USB_ENDPOINT_XFER_BULK)) {
 			/* We found bulk out endpoint */
-			if (!
-			    (usb_cardp->tx_urb =
-			     usb_alloc_urb(0, GFP_KERNEL))) {
-				lbs_dev_dbg(1,&udev->dev,
+			if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
+				lbs_deb_usbd(&udev->dev,
 				       "Tx URB allocation failed\n");
 				goto dealloc;
 			}
 
-			usb_cardp->bulk_out_size =
-			    endpoint->wMaxPacketSize;
-			lbs_dev_dbg(1, &udev->dev,
-				    "Bulk out size is %d\n",
-				    endpoint->wMaxPacketSize);
-			usb_cardp->bulk_out_endpointAddr =
+			cardp->bulk_out_size =
+				le16_to_cpu(endpoint->wMaxPacketSize);
+			lbs_deb_usbd(&udev->dev,
+				     "Bulk out size is %d\n",
+				     le16_to_cpu(endpoint->wMaxPacketSize));
+			cardp->bulk_out_endpointAddr =
 			    endpoint->bEndpointAddress;
-			lbs_dev_dbg(1, &udev->dev, "out_endpoint = %d\n",
+			lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n",
 				    endpoint->bEndpointAddress);
-			usb_cardp->bulk_out_buffer =
+			cardp->bulk_out_buffer =
 			    kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
 				    GFP_KERNEL);
 
-			if (!usb_cardp->bulk_out_buffer) {
-				lbs_dev_dbg(1, &udev->dev,
+			if (!cardp->bulk_out_buffer) {
+				lbs_deb_usbd(&udev->dev,
 				       "Could not allocate buffer\n");
 				goto dealloc;
 			}
 		}
 	}
 
-
-	/* At this point wlan_add_card() will be called.  Don't worry
-	 * about keeping pwlanpriv around since it will be set on our
-	 * usb device data in -> add() -> libertas_sbi_register_dev().
-	 */
-	if (!(pwlanpriv = wlan_add_card(usb_cardp)))
+	if (!(priv = libertas_add_card(cardp, &udev->dev)))
 		goto dealloc;
 
-	usb_get_dev(udev);
-	usb_set_intfdata(intf, usb_cardp);
+	if (libertas_add_mesh(priv, &udev->dev))
+		goto err_add_mesh;
 
-	/*
-	 * return card structure, which can be got back in the
-	 * diconnect function as the ptr
-	 * argument.
-	 */
+	priv->hw_register_dev = if_usb_register_dev;
+	priv->hw_unregister_dev = if_usb_unregister_dev;
+	priv->hw_prog_firmware = if_usb_prog_firmware;
+	priv->hw_host_to_card = if_usb_host_to_card;
+	priv->hw_get_int_status = if_usb_get_int_status;
+	priv->hw_read_event_cause = if_usb_read_event_cause;
+
+	if (libertas_activate_card(priv, libertas_fw_name))
+		goto err_activate_card;
+
+	list_add_tail(&cardp->list, &usb_devices);
+
+	usb_get_dev(udev);
+	usb_set_intfdata(intf, cardp);
+
 	return 0;
 
+err_activate_card:
+	libertas_remove_mesh(priv);
+err_add_mesh:
+	free_netdev(priv->dev);
+	kfree(priv->adapter);
 dealloc:
-	if_usb_free(usb_cardp);
+	if_usb_free(cardp);
 
 error:
 	return -ENOMEM;
@@ -212,8 +240,7 @@
 
 /**
  *  @brief free resource and cleanup
- *  @param udev		pointer to usb_device
- *  @param ptr		pointer to usb_cardp
+ *  @param intf		USB interface structure
  *  @return 	   	N/A
  */
 static void if_usb_disconnect(struct usb_interface *intf)
@@ -229,9 +256,12 @@
 	 */
 	adapter->surpriseremoved = 1;
 
+	list_del(&cardp->list);
+
 	/* card is removed and we can call wlan_remove_card */
-	lbs_dev_dbg(1, &cardp->udev->dev, "call remove card\n");
-	wlan_remove_card(cardp);
+	lbs_deb_usbd(&cardp->udev->dev, "call remove card\n");
+	libertas_remove_mesh(priv);
+	libertas_remove_card(priv);
 
 	/* Unlink and free urb */
 	if_usb_free(cardp);
@@ -249,7 +279,7 @@
  */
 static int if_prog_firmware(wlan_private * priv)
 {
-	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct usb_card_rec *cardp = priv->card;
 	struct FWData *fwdata;
 	struct fwheader *fwheader;
 	u8 *firmware = priv->firmware->data;
@@ -266,8 +296,10 @@
 		cardp->fwseqnum = cardp->lastseqnum - 1;
 	}
 
-	lbs_dev_dbg(2, &cardp->udev->dev, "totalbytes = %d\n",
+	/*
+	lbs_deb_usbd(&cardp->udev->dev, "totalbytes = %d\n",
 		    cardp->totalbytes);
+	*/
 
 	memcpy(fwheader, &firmware[cardp->totalbytes],
 	       sizeof(struct fwheader));
@@ -275,40 +307,48 @@
 	cardp->fwlastblksent = cardp->totalbytes;
 	cardp->totalbytes += sizeof(struct fwheader);
 
-	lbs_dev_dbg(2, &cardp->udev->dev,"Copy Data\n");
+	/* lbs_deb_usbd(&cardp->udev->dev,"Copy Data\n"); */
 	memcpy(fwdata->data, &firmware[cardp->totalbytes],
-	       fwdata->fwheader.datalength);
+	       le32_to_cpu(fwdata->fwheader.datalength));
 
-	lbs_dev_dbg(2, &cardp->udev->dev,
-		    "Data length = %d\n", fwdata->fwheader.datalength);
+	/*
+	lbs_deb_usbd(&cardp->udev->dev,
+		    "Data length = %d\n", le32_to_cpu(fwdata->fwheader.datalength));
+	*/
 
 	cardp->fwseqnum = cardp->fwseqnum + 1;
 
-	fwdata->seqnum = cardp->fwseqnum;
-	cardp->lastseqnum = fwdata->seqnum;
-	cardp->totalbytes += fwdata->fwheader.datalength;
+	fwdata->seqnum = cpu_to_le32(cardp->fwseqnum);
+	cardp->lastseqnum = cardp->fwseqnum;
+	cardp->totalbytes += le32_to_cpu(fwdata->fwheader.datalength);
 
-	if (fwheader->dnldcmd == FW_HAS_DATA_TO_RECV) {
-		lbs_dev_dbg(2, &cardp->udev->dev, "There is data to follow\n");
-		lbs_dev_dbg(2, &cardp->udev->dev,
+	if (fwheader->dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
+		/*
+		lbs_deb_usbd(&cardp->udev->dev, "There are data to follow\n");
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "seqnum = %d totalbytes = %d\n", cardp->fwseqnum,
 			    cardp->totalbytes);
+		*/
 		memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
 		usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
 
-	} else if (fwdata->fwheader.dnldcmd == FW_HAS_LAST_BLOCK) {
-		lbs_dev_dbg(2, &cardp->udev->dev,
+	} else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
+		/*
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "Host has finished FW downloading\n");
-		lbs_dev_dbg(2, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "Donwloading FW JUMP BLOCK\n");
+		*/
 		memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
 		usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
 		cardp->fwfinalblk = 1;
 	}
 
-	lbs_dev_dbg(2, &cardp->udev->dev,
+	/*
+	lbs_deb_usbd(&cardp->udev->dev,
 		    "The firmware download is done size is %d\n",
 		    cardp->totalbytes);
+	*/
 
 	kfree(fwdata);
 
@@ -318,14 +358,19 @@
 static int libertas_do_reset(wlan_private *priv)
 {
 	int ret;
-	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct usb_card_rec *cardp = priv->card;
+
+	lbs_deb_enter(LBS_DEB_USB);
 
 	ret = usb_reset_device(cardp->udev);
 	if (!ret) {
 		msleep(10);
-		reset_device(priv);
+		if_usb_reset_device(priv);
 		msleep(10);
 	}
+
+	lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
+
 	return ret;
 }
 
@@ -339,12 +384,12 @@
 int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
 {
 	/* pointer to card structure */
-	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct usb_card_rec *cardp = priv->card;
 	int ret = -1;
 
 	/* check if device is removed */
 	if (priv->adapter->surpriseremoved) {
-		lbs_dev_dbg(1, &cardp->udev->dev, "Device removed\n");
+		lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
 		goto tx_ret;
 	}
 
@@ -357,10 +402,10 @@
 
 	if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
 		/*  transfer failed */
-		lbs_dev_dbg(1, &cardp->udev->dev, "usb_submit_urb failed\n");
+		lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed\n");
 		ret = -1;
 	} else {
-		lbs_dev_dbg(2, &cardp->udev->dev, "usb_submit_urb success\n");
+		/* lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb success\n"); */
 		ret = 0;
 	}
 
@@ -372,7 +417,7 @@
 				  void (*callbackfn)
 				  (struct urb *urb))
 {
-	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct usb_card_rec *cardp = priv->card;
 	struct sk_buff *skb;
 	struct read_cb_info *rinfo = &cardp->rinfo;
 	int ret = -1;
@@ -394,13 +439,13 @@
 
 	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
 
-	lbs_dev_dbg(2, &cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
+	/* lbs_deb_usbd(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); */
 	if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
 		/* handle failure conditions */
-		lbs_dev_dbg(1, &cardp->udev->dev, "Submit Rx URB failed\n");
+		lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed\n");
 		ret = -1;
 	} else {
-		lbs_dev_dbg(2, &cardp->udev->dev, "Submit Rx URB success\n");
+		/* lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB success\n"); */
 		ret = 0;
 	}
 
@@ -423,12 +468,12 @@
 	struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
 	wlan_private *priv = rinfo->priv;
 	struct sk_buff *skb = rinfo->skb;
-	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
 	struct fwsyncheader *syncfwheader;
 	struct bootcmdrespStr bootcmdresp;
 
 	if (urb->status) {
-		lbs_dev_dbg(1, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "URB status is failed during fw load\n");
 		kfree_skb(skb);
 		return;
@@ -437,18 +482,18 @@
 	if (cardp->bootcmdresp == 0) {
 		memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
 			sizeof(bootcmdresp));
-		if (cardp->udev->descriptor.bcdDevice < 0x3106) {
+		if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
 			kfree_skb(skb);
 			if_usb_submit_rx_urb_fwload(priv);
 			cardp->bootcmdresp = 1;
-			lbs_dev_dbg(1, &cardp->udev->dev,
+			lbs_deb_usbd(&cardp->udev->dev,
 				    "Received valid boot command response\n");
 			return;
 		}
-		if (bootcmdresp.u32magicnumber != BOOT_CMD_MAGIC_NUMBER) {
+		if (bootcmdresp.u32magicnumber != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
 			lbs_pr_info(
 				"boot cmd response wrong magic number (0x%x)\n",
-				bootcmdresp.u32magicnumber);
+				le32_to_cpu(bootcmdresp.u32magicnumber));
 		} else if (bootcmdresp.u8cmd_tag != BOOT_CMD_FW_BY_USB) {
 			lbs_pr_info(
 				"boot cmd response cmd_tag error (%d)\n",
@@ -459,7 +504,7 @@
 				bootcmdresp.u8result);
 		} else {
 			cardp->bootcmdresp = 1;
-			lbs_dev_dbg(1, &cardp->udev->dev,
+			lbs_deb_usbd(&cardp->udev->dev,
 				    "Received valid boot command response\n");
 		}
 		kfree_skb(skb);
@@ -469,7 +514,7 @@
 
 	syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
 	if (!syncfwheader) {
-		lbs_dev_dbg(1, &cardp->udev->dev, "Failure to allocate syncfwheader\n");
+		lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
 		kfree_skb(skb);
 		return;
 	}
@@ -478,14 +523,16 @@
 			sizeof(struct fwsyncheader));
 
 	if (!syncfwheader->cmd) {
-		lbs_dev_dbg(2, &cardp->udev->dev,
+		/*
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "FW received Blk with correct CRC\n");
-		lbs_dev_dbg(2, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "FW received Blk seqnum = %d\n",
 		       syncfwheader->seqnum);
+		*/
 		cardp->CRC_OK = 1;
 	} else {
-		lbs_dev_dbg(1, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "FW received Blk with CRC error\n");
 		cardp->CRC_OK = 0;
 	}
@@ -515,7 +562,7 @@
 {
 	if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE +
 	    MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) {
-		lbs_dev_dbg(1, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "Packet length is Invalid\n");
 		kfree_skb(skb);
 		return;
@@ -525,7 +572,7 @@
 	skb_put(skb, recvlength);
 	skb_pull(skb, MESSAGE_HEADER_LEN);
 	libertas_process_rxed_packet(priv, skb);
-	priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN);
+	priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
 }
 
 static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
@@ -535,7 +582,7 @@
 {
 	u8 *cmdbuf;
 	if (recvlength > MRVDRV_SIZE_OF_CMD_BUFFER) {
-		lbs_dev_dbg(1, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "The receive buffer is too large\n");
 		kfree_skb(skb);
 		return;
@@ -548,21 +595,21 @@
 	/* take care of cur_cmd = NULL case by reading the
 	 * data to clear the interrupt */
 	if (!priv->adapter->cur_cmd) {
-		cmdbuf = priv->wlan_dev.upld_buf;
+		cmdbuf = priv->upld_buf;
 		priv->adapter->hisregcpy &= ~his_cmdupldrdy;
 	} else
 		cmdbuf = priv->adapter->cur_cmd->bufvirtualaddr;
 
 	cardp->usb_int_cause |= his_cmdupldrdy;
-	priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN);
+	priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
 	memcpy(cmdbuf, recvbuff + MESSAGE_HEADER_LEN,
-	       priv->wlan_dev.upld_len);
+	       priv->upld_len);
 
 	kfree_skb(skb);
-	libertas_interrupt(priv->wlan_dev.netdev);
+	libertas_interrupt(priv->dev);
 	spin_unlock(&priv->adapter->driver_lock);
 
-	lbs_dev_dbg(1, &cardp->udev->dev,
+	lbs_deb_usbd(&cardp->udev->dev,
 		    "Wake up main thread to handle cmd response\n");
 
 	return;
@@ -580,17 +627,17 @@
 	struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
 	wlan_private *priv = rinfo->priv;
 	struct sk_buff *skb = rinfo->skb;
-	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
 
 	int recvlength = urb->actual_length;
 	u8 *recvbuff = NULL;
 	u32 recvtype;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_USB);
 
 	if (recvlength) {
 		if (urb->status) {
-			lbs_dev_dbg(1, &cardp->udev->dev,
+			lbs_deb_usbd(&cardp->udev->dev,
 				    "URB status is failed\n");
 			kfree_skb(skb);
 			goto setup_for_next;
@@ -598,12 +645,12 @@
 
 		recvbuff = skb->data + IPFIELD_ALIGN_OFFSET;
 		memcpy(&recvtype, recvbuff, sizeof(u32));
-		lbs_dev_dbg(1, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "Recv length = 0x%x\n", recvlength);
-		lbs_dev_dbg(1, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "Receive type = 0x%X\n", recvtype);
 		recvtype = le32_to_cpu(recvtype);
-		lbs_dev_dbg(1, &cardp->udev->dev,
+		lbs_deb_usbd(&cardp->udev->dev,
 			    "Receive type after = 0x%X\n", recvtype);
 	} else if (urb->status)
 		goto rx_exit;
@@ -621,18 +668,18 @@
 	case CMD_TYPE_INDICATION:
 		/* Event cause handling */
 		spin_lock(&priv->adapter->driver_lock);
-		cardp->usb_event_cause = *(u32 *) (recvbuff + MESSAGE_HEADER_LEN);
-		lbs_dev_dbg(1, &cardp->udev->dev,"**EVENT** 0x%X\n",
+		cardp->usb_event_cause = le32_to_cpu(*(__le32 *) (recvbuff + MESSAGE_HEADER_LEN));
+		lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n",
 			    cardp->usb_event_cause);
 		if (cardp->usb_event_cause & 0xffff0000) {
 			libertas_send_tx_feedback(priv);
 			spin_unlock(&priv->adapter->driver_lock);
 			break;
 		}
-		cardp->usb_event_cause = le32_to_cpu(cardp->usb_event_cause) << 3;
+		cardp->usb_event_cause <<= 3;
 		cardp->usb_int_cause |= his_cardevent;
 		kfree_skb(skb);
-		libertas_interrupt(priv->wlan_dev.netdev);
+		libertas_interrupt(priv->dev);
 		spin_unlock(&priv->adapter->driver_lock);
 		goto rx_exit;
 	default:
@@ -643,8 +690,7 @@
 setup_for_next:
 	if_usb_submit_rx_urb(priv);
 rx_exit:
-	LEAVE();
-	return;
+	lbs_deb_leave(LBS_DEB_USB);
 }
 
 /**
@@ -655,24 +701,24 @@
  *  @param len		number of bytes
  *  @return 	   	0 or -1
  */
-int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
+static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
 {
 	int ret = -1;
 	u32 tmp;
-	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
 
-	lbs_dev_dbg(1, &cardp->udev->dev,"*** type = %u\n", type);
-	lbs_dev_dbg(1, &cardp->udev->dev,"size after = %d\n", nb);
+	lbs_deb_usbd(&cardp->udev->dev,"*** type = %u\n", type);
+	lbs_deb_usbd(&cardp->udev->dev,"size after = %d\n", nb);
 
 	if (type == MVMS_CMD) {
 		tmp = cpu_to_le32(CMD_TYPE_REQUEST);
-		priv->wlan_dev.dnld_sent = DNLD_CMD_SENT;
+		priv->dnld_sent = DNLD_CMD_SENT;
 		memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
 		       MESSAGE_HEADER_LEN);
 
 	} else {
 		tmp = cpu_to_le32(CMD_TYPE_DATA);
-		priv->wlan_dev.dnld_sent = DNLD_DATA_SENT;
+		priv->dnld_sent = DNLD_DATA_SENT;
 		memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
 		       MESSAGE_HEADER_LEN);
 	}
@@ -686,39 +732,41 @@
 }
 
 /* called with adapter->driver_lock held */
-int libertas_sbi_get_int_status(wlan_private * priv, u8 * ireg)
+static int if_usb_get_int_status(wlan_private * priv, u8 * ireg)
 {
-	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct usb_card_rec *cardp = priv->card;
 
 	*ireg = cardp->usb_int_cause;
 	cardp->usb_int_cause = 0;
 
-	lbs_dev_dbg(1, &cardp->udev->dev,"Int cause is 0x%X\n", *ireg);
+	lbs_deb_usbd(&cardp->udev->dev,"Int cause is 0x%X\n", *ireg);
 
 	return 0;
 }
 
-int libertas_sbi_read_event_cause(wlan_private * priv)
+static int if_usb_read_event_cause(wlan_private * priv)
 {
-	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct usb_card_rec *cardp = priv->card;
 	priv->adapter->eventcause = cardp->usb_event_cause;
 	/* Re-submit rx urb here to avoid event lost issue */
 	if_usb_submit_rx_urb(priv);
 	return 0;
 }
 
-int reset_device(wlan_private *priv)
+static int if_usb_reset_device(wlan_private *priv)
 {
 	int ret;
 
+	lbs_deb_enter(LBS_DEB_USB);
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_reset,
 				    cmd_act_halt, 0, 0, NULL);
 	msleep_interruptible(10);
 
+	lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
 	return ret;
 }
 
-int libertas_sbi_unregister_dev(wlan_private * priv)
+static int if_usb_unregister_dev(wlan_private * priv)
 {
 	int ret = 0;
 
@@ -727,7 +775,7 @@
 	 * again.
 	 */
 	if (priv)
-		reset_device(priv);
+		if_usb_reset_device(priv);
 
 	return ret;
 }
@@ -738,42 +786,41 @@
  *  @param		priv pointer to wlan_private
  *  @return		0 or -1
  */
-int libertas_sbi_register_dev(wlan_private * priv)
+static int if_usb_register_dev(wlan_private * priv)
 {
+	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
 
-	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
-	ENTER();
+	lbs_deb_enter(LBS_DEB_USB);
 
 	cardp->priv = priv;
-	cardp->eth_dev = priv->wlan_dev.netdev;
+	cardp->eth_dev = priv->dev;
 	priv->hotplug_device = &(cardp->udev->dev);
 
-	SET_NETDEV_DEV(cardp->eth_dev, &(cardp->udev->dev));
-
-	lbs_dev_dbg(1, &cardp->udev->dev, "udev pointer is at %p\n",
+	lbs_deb_usbd(&cardp->udev->dev, "udev pointer is at %p\n",
 		    cardp->udev);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_USB);
 	return 0;
 }
 
 
 
-int libertas_sbi_prog_firmware(wlan_private * priv)
+static int if_usb_prog_firmware(wlan_private * priv)
 {
-	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct usb_card_rec *cardp = priv->card;
 	int i = 0;
 	static int reset_count = 10;
+	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_USB);
 
 	cardp->rinfo.priv = priv;
 
 restart:
 	if (if_usb_submit_rx_urb_fwload(priv) < 0) {
-		lbs_dev_dbg(1, &cardp->udev->dev, "URB submission is failed\n");
-		LEAVE();
-		return -1;
+		lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
+		ret = -1;
+		goto done;
 	}
 
 	cardp->bootcmdresp = 0;
@@ -811,7 +858,7 @@
 	if_prog_firmware(priv);
 
 	do {
-		lbs_dev_dbg(1, &cardp->udev->dev,"Wlan sched timeout\n");
+		lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n");
 		i++;
 		msleep_interruptible(100);
 		if (priv->adapter->surpriseremoved || i >= 20)
@@ -826,8 +873,8 @@
 		}
 
 		lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
-		LEAVE();
-		return -1;
+		ret = -1;
+		goto done;
 	}
 
 	if_usb_submit_rx_urb(priv);
@@ -837,45 +884,24 @@
 
 	priv->adapter->fw_ready = 1;
 
-	LEAVE();
-	return 0;
+done:
+	lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
+	return ret;
 }
 
-/**
- *  @brief Given a usb_card_rec return its wlan_private
- *  @param card		pointer to a usb_card_rec
- *  @return 	   	pointer to wlan_private
- */
-wlan_private *libertas_sbi_get_priv(void *card)
-{
-	struct usb_card_rec *cardp = card;
-	return cardp->priv;
-}
-
-#ifdef ENABLE_PM
-int libertas_sbi_suspend(wlan_private * priv)
-{
-	return 0;
-}
-
-int libertas_sbi_resume(wlan_private * priv)
-{
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_PM
 static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct usb_card_rec *cardp = usb_get_intfdata(intf);
 	wlan_private *priv = cardp->priv;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_USB);
 
 	if (priv->adapter->psstate != PS_STATE_FULL_POWER)
 		return -1;
 
 	netif_device_detach(cardp->eth_dev);
+	netif_device_detach(priv->mesh_dev);
 
 	/* Unlink tx & rx urb */
 	usb_kill_urb(cardp->tx_urb);
@@ -883,23 +909,25 @@
 
 	cardp->rx_urb_recall = 1;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_USB);
 	return 0;
 }
 
 static int if_usb_resume(struct usb_interface *intf)
 {
 	struct usb_card_rec *cardp = usb_get_intfdata(intf);
+	wlan_private *priv = cardp->priv;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_USB);
 
 	cardp->rx_urb_recall = 0;
 
 	if_usb_submit_rx_urb(cardp->priv);
 
 	netif_device_attach(cardp->eth_dev);
+	netif_device_attach(priv->mesh_dev);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_USB);
 	return 0;
 }
 #else
@@ -920,32 +948,40 @@
 	.resume = if_usb_resume,
 };
 
-/**
- *  @brief This function registers driver.
- *  @param add		pointer to add_card callback function
- *  @param remove	pointer to remove card callback function
- *  @param arg		pointer to call back function parameter
- *  @return 	   	dummy success variable
- */
-int libertas_sbi_register(void)
+static int if_usb_init_module(void)
 {
-	/*
-	 * API registers the Marvell USB driver
-	 * to the USB system
-	 */
-	usb_register(&if_usb_driver);
+	int ret = 0;
 
-	/* Return success to wlan layer */
-	return 0;
+	lbs_deb_enter(LBS_DEB_MAIN);
+
+	if (libertas_fw_name == NULL) {
+		libertas_fw_name = default_fw_name;
+	}
+
+	ret = usb_register(&if_usb_driver);
+
+	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+	return ret;
 }
 
-/**
- *  @brief This function removes usb driver.
- *  @return 	   	N/A
- */
-void libertas_sbi_unregister(void)
+static void if_usb_exit_module(void)
 {
+	struct usb_card_rec *cardp, *cardp_temp;
+
+	lbs_deb_enter(LBS_DEB_MAIN);
+
+	list_for_each_entry_safe(cardp, cardp_temp, &usb_devices, list)
+		if_usb_reset_device((wlan_private *) cardp->priv);
+
 	/* API unregisters the driver from USB subsystem */
 	usb_deregister(&if_usb_driver);
-	return;
+
+	lbs_deb_leave(LBS_DEB_MAIN);
 }
+
+module_init(if_usb_init_module);
+module_exit(if_usb_exit_module);
+
+MODULE_DESCRIPTION("8388 USB WLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index 170dfe6..156bb48 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -1,3 +1,8 @@
+#ifndef _LIBERTAS_IF_USB_H
+#define _LIBERTAS_IF_USB_H
+
+#include <linux/list.h>
+
 /**
   * This file contains definition for USB interface.
   */
@@ -7,11 +12,6 @@
 
 #define IPFIELD_ALIGN_OFFSET	2
 
-#define USB8388_VID_1	0x1286
-#define USB8388_PID_1	0x2001
-#define USB8388_VID_2	0x05a3
-#define USB8388_PID_2	0x8388
-
 #define BOOT_CMD_FW_BY_USB     0x01
 #define BOOT_CMD_FW_IN_EEPROM  0x02
 #define BOOT_CMD_UPDATE_BOOT2  0x03
@@ -20,7 +20,7 @@
 
 struct bootcmdstr
 {
-	u32 u32magicnumber;
+	__le32 u32magicnumber;
 	u8  u8cmd_tag;
 	u8  au8dumy[11];
 };
@@ -30,7 +30,7 @@
 
 struct bootcmdrespStr
 {
-	u32 u32magicnumber;
+	__le32 u32magicnumber;
 	u8  u8cmd_tag;
 	u8  u8result;
 	u8  au8dumy[2];
@@ -44,6 +44,7 @@
 
 /** USB card description structure*/
 struct usb_card_rec {
+	struct list_head list;
 	struct net_device *eth_dev;
 	struct usb_device *udev;
 	struct urb *rx_urb, *tx_urb;
@@ -75,33 +76,34 @@
 
 /** fwheader */
 struct fwheader {
-	u32 dnldcmd;
-	u32 baseaddr;
-	u32 datalength;
-	u32 CRC;
+	__le32 dnldcmd;
+	__le32 baseaddr;
+	__le32 datalength;
+	__le32 CRC;
 };
 
 #define FW_MAX_DATA_BLK_SIZE	600
 /** FWData */
 struct FWData {
 	struct fwheader fwheader;
-	u32 seqnum;
+	__le32 seqnum;
 	u8 data[FW_MAX_DATA_BLK_SIZE];
 };
 
 /** fwsyncheader */
 struct fwsyncheader {
-	u32 cmd;
-	u32 seqnum;
+	__le32 cmd;
+	__le32 seqnum;
 };
 
 #define FW_HAS_DATA_TO_RECV		0x00000001
 #define FW_HAS_LAST_BLOCK		0x00000004
 
 #define FW_DATA_XMIT_SIZE \
-	sizeof(struct fwheader) + fwdata->fwheader.datalength + sizeof(u32)
+	sizeof(struct fwheader) + le32_to_cpu(fwdata->fwheader.datalength) + sizeof(u32)
 
 int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb);
 void if_usb_free(struct usb_card_rec *cardp);
 int if_usb_issue_boot_command(wlan_private *priv, int ivalue);
 
+#endif
diff --git a/drivers/net/wireless/libertas/ioctl.c b/drivers/net/wireless/libertas/ioctl.c
deleted file mode 100644
index a8f76c3..0000000
--- a/drivers/net/wireless/libertas/ioctl.c
+++ /dev/null
@@ -1,991 +0,0 @@
-/**
-  * This file contains ioctl functions
-  */
-
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-
-#include <net/iw_handler.h>
-#include <net/ieee80211.h>
-
-#include "host.h"
-#include "radiotap.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "join.h"
-#include "wext.h"
-
-#define MAX_SCAN_CELL_SIZE      (IW_EV_ADDR_LEN + \
-				IW_ESSID_MAX_SIZE + \
-				IW_EV_UINT_LEN + IW_EV_FREQ_LEN + \
-				IW_EV_QUAL_LEN + IW_ESSID_MAX_SIZE + \
-				IW_EV_PARAM_LEN + 40)	/* 40 for WPAIE */
-
-#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ)
-
-static int wlan_set_region(wlan_private * priv, u16 region_code)
-{
-	int i;
-
-	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
-		// use the region code to search for the index
-		if (region_code == libertas_region_code_to_index[i]) {
-			priv->adapter->regiontableindex = (u16) i;
-			priv->adapter->regioncode = region_code;
-			break;
-		}
-	}
-
-	// if it's unidentified region code
-	if (i >= MRVDRV_MAX_REGION_CODE) {
-		lbs_pr_debug(1, "region Code not identified\n");
-		LEAVE();
-		return -1;
-	}
-
-	if (libertas_set_regiontable(priv, priv->adapter->regioncode, 0)) {
-		LEAVE();
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static inline int hex2int(char c)
-{
-	if (c >= '0' && c <= '9')
-		return (c - '0');
-	if (c >= 'a' && c <= 'f')
-		return (c - 'a' + 10);
-	if (c >= 'A' && c <= 'F')
-		return (c - 'A' + 10);
-	return -1;
-}
-
-/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
-   into binary format (6 bytes).
-
-   This function expects that each byte is represented with 2 characters
-   (e.g., 11:2:11:11:11:11 is invalid)
-
- */
-static char *eth_str2addr(char *ethstr, u8 * addr)
-{
-	int i, val, val2;
-	char *pos = ethstr;
-
-	/* get rid of initial blanks */
-	while (*pos == ' ' || *pos == '\t')
-		++pos;
-
-	for (i = 0; i < 6; i++) {
-		val = hex2int(*pos++);
-		if (val < 0)
-			return NULL;
-		val2 = hex2int(*pos++);
-		if (val2 < 0)
-			return NULL;
-		addr[i] = (val * 16 + val2) & 0xff;
-
-		if (i < 5 && *pos++ != ':')
-			return NULL;
-	}
-	return pos;
-}
-
-/* this writes xx:xx:xx:xx:xx:xx into ethstr
-   (ethstr must have space for 18 chars) */
-static int eth_addr2str(u8 * addr, char *ethstr)
-{
-	int i;
-	char *pos = ethstr;
-
-	for (i = 0; i < 6; i++) {
-		sprintf(pos, "%02x", addr[i] & 0xff);
-		pos += 2;
-		if (i < 5)
-			*pos++ = ':';
-	}
-	return 17;
-}
-
-/**
- *  @brief          Add an entry to the BT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	char ethaddrs_str[18];
-	char *pos;
-	u8 ethaddr[ETH_ALEN];
-
-	ENTER();
-	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
-			   sizeof(ethaddrs_str)))
-		return -EFAULT;
-
-	if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
-		lbs_pr_info("BT_ADD: Invalid MAC address\n");
-		return -EINVAL;
-	}
-
-	lbs_pr_debug(1, "BT: adding %s\n", ethaddrs_str);
-	LEAVE();
-	return (libertas_prepare_and_send_command(priv, cmd_bt_access,
-				      cmd_act_bt_access_add,
-				      cmd_option_waitforrsp, 0, ethaddr));
-}
-
-/**
- *  @brief          Delete an entry from the BT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	char ethaddrs_str[18];
-	u8 ethaddr[ETH_ALEN];
-	char *pos;
-
-	ENTER();
-	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
-			   sizeof(ethaddrs_str)))
-		return -EFAULT;
-
-	if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
-		lbs_pr_info("Invalid MAC address\n");
-		return -EINVAL;
-	}
-
-	lbs_pr_debug(1, "BT: deleting %s\n", ethaddrs_str);
-
-	return (libertas_prepare_and_send_command(priv,
-				      cmd_bt_access,
-				      cmd_act_bt_access_del,
-				      cmd_option_waitforrsp, 0, ethaddr));
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          Reset all entries from the BT table
- *  @param priv     A pointer to wlan_private structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_bt_reset_ioctl(wlan_private * priv)
-{
-	ENTER();
-
-	lbs_pr_alert( "BT: resetting\n");
-
-	return (libertas_prepare_and_send_command(priv,
-				      cmd_bt_access,
-				      cmd_act_bt_access_reset,
-				      cmd_option_waitforrsp, 0, NULL));
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          List an entry from the BT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	int pos;
-	char *addr1;
-	struct iwreq *wrq = (struct iwreq *)req;
-	/* used to pass id and store the bt entry returned by the FW */
-	union {
-		int id;
-		char addr1addr2[2 * ETH_ALEN];
-	} param;
-	static char outstr[64];
-	char *pbuf = outstr;
-	int ret;
-
-	ENTER();
-
-	if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
-		lbs_pr_debug(1, "Copy from user failed\n");
-		return -1;
-	}
-	param.id = simple_strtoul(outstr, NULL, 10);
-	pos = sprintf(pbuf, "%d: ", param.id);
-	pbuf += pos;
-
-	ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
-				    cmd_act_bt_access_list,
-				    cmd_option_waitforrsp, 0,
-				    (char *)&param);
-
-	if (ret == 0) {
-		addr1 = param.addr1addr2;
-
-		pos = sprintf(pbuf, "ignoring traffic from ");
-		pbuf += pos;
-		pos = eth_addr2str(addr1, pbuf);
-		pbuf += pos;
-	} else {
-		sprintf(pbuf, "(null)");
-		pbuf += pos;
-	}
-
-	wrq->u.data.length = strlen(outstr);
-	if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
-			 wrq->u.data.length)) {
-		lbs_pr_debug(1, "BT_LIST: Copy to user failed!\n");
-		return -EFAULT;
-	}
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          Find the next parameter in an input string
- *  @param ptr      A pointer to the input parameter string
- *  @return         A pointer to the next parameter, or 0 if no parameters left.
- */
-static char * next_param(char * ptr)
-{
-	if (!ptr) return NULL;
-	while (*ptr == ' ' || *ptr == '\t') ++ptr;
-	return (*ptr == '\0') ? NULL : ptr;
-}
-
-/**
- *  @brief          Add an entry to the FWT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	char in_str[128];
-	static struct cmd_ds_fwt_access fwt_access;
-	char *ptr;
-
-	ENTER();
-	if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
-		return -EFAULT;
-
-	if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
-		lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
-		return -EINVAL;
-	}
-
-	if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
-		lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
-		return -EINVAL;
-	}
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.metric =
-			cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-	else
-		fwt_access.metric = FWT_DEFAULT_METRIC;
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
-	else
-		fwt_access.dir = FWT_DEFAULT_DIR;
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.ssn =
-			cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-	else
-		fwt_access.ssn = FWT_DEFAULT_SSN;
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.dsn =
-			cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-	else
-		fwt_access.dsn = FWT_DEFAULT_DSN;
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
-	else
-		fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
-	else
-		fwt_access.ttl = FWT_DEFAULT_TTL;
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.expiration =
-			cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-	else
-		fwt_access.expiration = FWT_DEFAULT_EXPIRATION;
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
-	else
-		fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.snr =
-			cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-	else
-		fwt_access.snr = FWT_DEFAULT_SNR;
-
-#ifdef DEBUG
-	{
-		char ethaddr1_str[18], ethaddr2_str[18];
-		eth_addr2str(fwt_access.da, ethaddr1_str);
-		eth_addr2str(fwt_access.ra, ethaddr2_str);
-		lbs_pr_debug(1, "FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
-		       fwt_access.dir, ethaddr2_str);
-		lbs_pr_debug(1, "FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
-		       fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
-		       fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
-		       fwt_access.sleepmode, fwt_access.snr);
-	}
-#endif
-
-	LEAVE();
-	return (libertas_prepare_and_send_command(priv, cmd_fwt_access,
-						  cmd_act_fwt_access_add,
-						  cmd_option_waitforrsp, 0,
-						  (void *)&fwt_access));
-}
-
-/**
- *  @brief          Delete an entry from the FWT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	char in_str[64];
-	static struct cmd_ds_fwt_access fwt_access;
-	char *ptr;
-
-	ENTER();
-	if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
-		return -EFAULT;
-
-	if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
-		lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
-		return -EINVAL;
-	}
-
-	if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
-		lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
-		return -EINVAL;
-	}
-
-	if ((ptr = next_param(ptr)))
-		fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
-	else
-		fwt_access.dir = FWT_DEFAULT_DIR;
-
-#ifdef DEBUG
-	{
-		char ethaddr1_str[18], ethaddr2_str[18];
-		lbs_pr_debug(1, "FWT_DEL: line is %s\n", in_str);
-		eth_addr2str(fwt_access.da, ethaddr1_str);
-		eth_addr2str(fwt_access.ra, ethaddr2_str);
-		lbs_pr_debug(1, "FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
-		       ethaddr2_str, fwt_access.dir);
-	}
-#endif
-
-	LEAVE();
-	return (libertas_prepare_and_send_command(priv,
-						  cmd_fwt_access,
-						  cmd_act_fwt_access_del,
-						  cmd_option_waitforrsp, 0,
-						  (void *)&fwt_access));
-}
-
-
-/**
- *  @brief             Print route parameters
- *  @param fwt_access  struct cmd_ds_fwt_access with route info
- *  @param buf         destination buffer for route info
- */
-static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
-{
-	buf += sprintf(buf, " ");
-	buf += eth_addr2str(fwt_access.da, buf);
-	buf += sprintf(buf, " ");
-	buf += eth_addr2str(fwt_access.ra, buf);
-	buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
-	buf += sprintf(buf, " %u", fwt_access.dir);
-	buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
-	buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
-	buf += sprintf(buf, " %u", fwt_access.hopcount);
-	buf += sprintf(buf, " %u", fwt_access.ttl);
-	buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
-	buf += sprintf(buf, " %u", fwt_access.sleepmode);
-	buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.snr));
-}
-
-/**
- *  @brief          Lookup an entry in the FWT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	char in_str[64];
-	char *ptr;
-	static struct cmd_ds_fwt_access fwt_access;
-	static char out_str[128];
-	int ret;
-
-	ENTER();
-	if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
-		return -EFAULT;
-
-	if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
-		lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
-		return -EINVAL;
-	}
-
-#ifdef DEBUG
-	{
-		char ethaddr1_str[18];
-		lbs_pr_debug(1, "FWT_LOOKUP: line is %s\n", in_str);
-		eth_addr2str(fwt_access.da, ethaddr1_str);
-		lbs_pr_debug(1, "FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
-	}
-#endif
-
-	ret = libertas_prepare_and_send_command(priv,
-						cmd_fwt_access,
-						cmd_act_fwt_access_lookup,
-						cmd_option_waitforrsp, 0,
-						(void *)&fwt_access);
-
-	if (ret == 0)
-		print_route(fwt_access, out_str);
-	else
-		sprintf(out_str, "(null)");
-
-	wrq->u.data.length = strlen(out_str);
-	if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
-			 wrq->u.data.length)) {
-		lbs_pr_debug(1, "FWT_LOOKUP: Copy to user failed!\n");
-		return -EFAULT;
-	}
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          Reset all entries from the FWT table
- *  @param priv     A pointer to wlan_private structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_reset_ioctl(wlan_private * priv)
-{
-	lbs_pr_debug(1, "FWT: resetting\n");
-
-	return (libertas_prepare_and_send_command(priv,
-				      cmd_fwt_access,
-				      cmd_act_fwt_access_reset,
-				      cmd_option_waitforrsp, 0, NULL));
-}
-
-/**
- *  @brief          List an entry from the FWT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	char in_str[8];
-	static struct cmd_ds_fwt_access fwt_access;
-	char *ptr = in_str;
-	static char out_str[128];
-	char *pbuf = out_str;
-	int ret;
-
-	ENTER();
-	if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
-		return -EFAULT;
-
-	fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
-	{
-		lbs_pr_debug(1, "FWT_LIST: line is %s\n", in_str);
-		lbs_pr_debug(1, "FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
-	}
-#endif
-
-	ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
-				    cmd_act_fwt_access_list,
-				    cmd_option_waitforrsp, 0, (void *)&fwt_access);
-
-	if (ret == 0)
-		print_route(fwt_access, pbuf);
-	else
-		pbuf += sprintf(pbuf, " (null)");
-
-	wrq->u.data.length = strlen(out_str);
-	if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
-			 wrq->u.data.length)) {
-		lbs_pr_debug(1, "FWT_LIST: Copy to user failed!\n");
-		return -EFAULT;
-	}
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          List an entry from the FRT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	char in_str[64];
-	static struct cmd_ds_fwt_access fwt_access;
-	char *ptr = in_str;
-	static char out_str[128];
-	char *pbuf = out_str;
-	int ret;
-
-	ENTER();
-	if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
-		return -EFAULT;
-
-	fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
-	{
-		lbs_pr_debug(1, "FWT_LIST_ROUTE: line is %s\n", in_str);
-		lbs_pr_debug(1, "FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
-	}
-#endif
-
-	ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
-				    cmd_act_fwt_access_list_route,
-				    cmd_option_waitforrsp, 0, (void *)&fwt_access);
-
-	if (ret == 0) {
-		pbuf += sprintf(pbuf, " ");
-		pbuf += eth_addr2str(fwt_access.da, pbuf);
-		pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.metric));
-		pbuf += sprintf(pbuf, " %u", fwt_access.dir);
-		/* note that the firmware returns the nid in the id field */
-		pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.id));
-		pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.ssn));
-		pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.dsn));
-		pbuf += sprintf(pbuf, "  hop %u", fwt_access.hopcount);
-		pbuf += sprintf(pbuf, "  ttl %u", fwt_access.ttl);
-		pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.expiration));
-	} else
-		pbuf += sprintf(pbuf, " (null)");
-
-	wrq->u.data.length = strlen(out_str);
-	if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
-			 wrq->u.data.length)) {
-		lbs_pr_debug(1, "FWT_LIST_ROUTE: Copy to user failed!\n");
-		return -EFAULT;
-	}
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          List an entry from the FNT table
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	char in_str[8];
-	static struct cmd_ds_fwt_access fwt_access;
-	char *ptr = in_str;
-	static char out_str[128];
-	char *pbuf = out_str;
-	int ret;
-
-	ENTER();
-	if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
-		return -EFAULT;
-
-	memset(&fwt_access, 0, sizeof(fwt_access));
-	fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
-	{
-		lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: line is %s\n", in_str);
-		lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
-	}
-#endif
-
-	ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
-				    cmd_act_fwt_access_list_neighbor,
-				    cmd_option_waitforrsp, 0,
-				    (void *)&fwt_access);
-
-	if (ret == 0) {
-		pbuf += sprintf(pbuf, " ra ");
-		pbuf += eth_addr2str(fwt_access.ra, pbuf);
-		pbuf += sprintf(pbuf, "  slp %u", fwt_access.sleepmode);
-		pbuf += sprintf(pbuf, "  snr %u", le32_to_cpu(fwt_access.snr));
-		pbuf += sprintf(pbuf, "  ref %u", le32_to_cpu(fwt_access.references));
-	} else
-		pbuf += sprintf(pbuf, " (null)");
-
-	wrq->u.data.length = strlen(out_str);
-	if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
-			 wrq->u.data.length)) {
-		lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: Copy to user failed!\n");
-		return -EFAULT;
-	}
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          Cleans up the route (FRT) and neighbor (FNT) tables
- *                  (Garbage Collection)
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	static struct cmd_ds_fwt_access fwt_access;
-	int ret;
-
-	ENTER();
-
-	lbs_pr_debug(1, "FWT: cleaning up\n");
-
-	memset(&fwt_access, 0, sizeof(fwt_access));
-
-	ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
-				    cmd_act_fwt_access_cleanup,
-				    cmd_option_waitforrsp, 0,
-				    (void *)&fwt_access);
-
-	if (ret == 0)
-		wrq->u.param.value = le32_to_cpu(fwt_access.references);
-	else
-		return -EFAULT;
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          Gets firmware internal time (debug purposes)
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	static struct cmd_ds_fwt_access fwt_access;
-	int ret;
-
-	ENTER();
-
-	lbs_pr_debug(1, "FWT: getting time\n");
-
-	memset(&fwt_access, 0, sizeof(fwt_access));
-
-	ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
-				    cmd_act_fwt_access_time,
-				    cmd_option_waitforrsp, 0,
-				    (void *)&fwt_access);
-
-	if (ret == 0)
-		wrq->u.param.value = le32_to_cpu(fwt_access.references);
-	else
-		return -EFAULT;
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          Gets mesh ttl from firmware
- *  @param priv     A pointer to wlan_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
- */
-static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
-{
-	struct iwreq *wrq = (struct iwreq *)req;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-
-	ENTER();
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-
-	ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
-				    cmd_act_mesh_get_ttl,
-				    cmd_option_waitforrsp, 0,
-				    (void *)&mesh_access);
-
-	if (ret == 0)
-		wrq->u.param.value = le32_to_cpu(mesh_access.data[0]);
-	else
-		return -EFAULT;
-
-	LEAVE();
-	return 0;
-}
-
-/**
- *  @brief          Gets mesh ttl from firmware
- *  @param priv     A pointer to wlan_private structure
- *  @param ttl      New ttl value
- *  @return         0 --success, otherwise fail
- */
-static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
-{
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-
-	ENTER();
-
-	if( (ttl > 0xff) || (ttl < 0) )
-		return -EINVAL;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	mesh_access.data[0] = ttl;
-
-	ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
-						cmd_act_mesh_set_ttl,
-						cmd_option_waitforrsp, 0,
-						(void *)&mesh_access);
-
-	if (ret != 0)
-		ret = -EFAULT;
-
-	LEAVE();
-	return ret;
-}
-
-/**
- *  @brief ioctl function - entry point
- *
- *  @param dev		A pointer to net_device structure
- *  @param req	   	A pointer to ifreq structure
- *  @param cmd 		command
- *  @return 	   	0--success, otherwise fail
- */
-int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
-	int subcmd = 0;
-	int idata = 0;
-	int *pdata;
-	int ret = 0;
-	wlan_private *priv = dev->priv;
-	wlan_adapter *adapter = priv->adapter;
-	struct iwreq *wrq = (struct iwreq *)req;
-
-	ENTER();
-
-	lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
-	switch (cmd) {
-	case WLAN_SETNONE_GETNONE:	/* set WPA mode on/off ioctl #20 */
-		switch (wrq->u.data.flags) {
-		case WLAN_SUBCMD_BT_RESET:	/* bt_reset */
-			wlan_bt_reset_ioctl(priv);
-			break;
-		case WLAN_SUBCMD_FWT_RESET:	/* fwt_reset */
-			wlan_fwt_reset_ioctl(priv);
-			break;
-		}		/* End of switch */
-		break;
-
-	case WLAN_SETONEINT_GETNONE:
-		/* The first 4 bytes of req->ifr_data is sub-ioctl number
-		 * after 4 bytes sits the payload.
-		 */
-		subcmd = wrq->u.data.flags;
-		if (!subcmd)
-			subcmd = (int)wrq->u.param.value;
-
-		switch (subcmd) {
-		case WLANSETREGION:
-			idata = SUBCMD_DATA(wrq);
-			ret = wlan_set_region(priv, (u16) idata);
-			break;
-		case WLAN_SUBCMD_MESH_SET_TTL:
-			idata = SUBCMD_DATA(wrq);
-			ret = wlan_mesh_set_ttl_ioctl(priv, idata);
-			break;
-
-		default:
-			ret = -EOPNOTSUPP;
-			break;
-		}
-
-		break;
-
-	case WLAN_SET128CHAR_GET128CHAR:
-		switch ((int)wrq->u.data.flags) {
-		case WLAN_SUBCMD_BT_ADD:
-			ret = wlan_bt_add_ioctl(priv, req);
-			break;
-		case WLAN_SUBCMD_BT_DEL:
-			ret = wlan_bt_del_ioctl(priv, req);
-			break;
-		case WLAN_SUBCMD_BT_LIST:
-			ret = wlan_bt_list_ioctl(priv, req);
-			break;
-		case WLAN_SUBCMD_FWT_ADD:
-			ret = wlan_fwt_add_ioctl(priv, req);
-			break;
-		case WLAN_SUBCMD_FWT_DEL:
-			ret = wlan_fwt_del_ioctl(priv, req);
-			break;
-		case WLAN_SUBCMD_FWT_LOOKUP:
-			ret = wlan_fwt_lookup_ioctl(priv, req);
-			break;
-		case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
-			ret = wlan_fwt_list_neighbor_ioctl(priv, req);
-			break;
-		case WLAN_SUBCMD_FWT_LIST:
-			ret = wlan_fwt_list_ioctl(priv, req);
-			break;
-		case WLAN_SUBCMD_FWT_LIST_ROUTE:
-			ret = wlan_fwt_list_route_ioctl(priv, req);
-			break;
-		}
-		break;
-
-	case WLAN_SETNONE_GETONEINT:
-		switch (wrq->u.param.value) {
-		case WLANGETREGION:
-			pdata = (int *)wrq->u.name;
-			*pdata = (int)adapter->regioncode;
-			break;
-		case WLAN_SUBCMD_FWT_CLEANUP:	/* fwt_cleanup */
-			ret = wlan_fwt_cleanup_ioctl(priv, req);
-			break;
-
-		case WLAN_SUBCMD_FWT_TIME:	/* fwt_time */
-			ret = wlan_fwt_time_ioctl(priv, req);
-			break;
-
-		case WLAN_SUBCMD_MESH_GET_TTL:
-			ret = wlan_mesh_get_ttl_ioctl(priv, req);
-			break;
-
-		default:
-			ret = -EOPNOTSUPP;
-
-		}
-
-		break;
-
-	case WLAN_SET_GET_SIXTEEN_INT:
-		switch ((int)wrq->u.data.flags) {
-		case WLAN_LED_GPIO_CTRL:
-			{
-				int i;
-				int data[16];
-
-				struct cmd_ds_802_11_led_ctrl ctrl;
-				struct mrvlietypes_ledgpio *gpio =
-				    (struct mrvlietypes_ledgpio *) ctrl.data;
-
-				memset(&ctrl, 0, sizeof(ctrl));
-				if (wrq->u.data.length > MAX_LEDS * 2)
-					return -ENOTSUPP;
-				if ((wrq->u.data.length % 2) != 0)
-					return -ENOTSUPP;
-				if (wrq->u.data.length == 0) {
-					ctrl.action =
-					    cpu_to_le16
-					    (cmd_act_get);
-				} else {
-					if (copy_from_user
-					    (data, wrq->u.data.pointer,
-					     sizeof(int) *
-					     wrq->u.data.length)) {
-						lbs_pr_debug(1,
-						       "Copy from user failed\n");
-						return -EFAULT;
-					}
-
-					ctrl.action =
-					    cpu_to_le16
-					    (cmd_act_set);
-					ctrl.numled = cpu_to_le16(0);
-					gpio->header.type =
-					    cpu_to_le16(TLV_TYPE_LED_GPIO);
-					gpio->header.len = wrq->u.data.length;
-					for (i = 0; i < wrq->u.data.length;
-					     i += 2) {
-						gpio->ledpin[i / 2].led =
-						    data[i];
-						gpio->ledpin[i / 2].pin =
-						    data[i + 1];
-					}
-				}
-				ret =
-				    libertas_prepare_and_send_command(priv,
-							  cmd_802_11_led_gpio_ctrl,
-							  0,
-							  cmd_option_waitforrsp,
-							  0, (void *)&ctrl);
-				for (i = 0; i < gpio->header.len; i += 2) {
-					data[i] = gpio->ledpin[i / 2].led;
-					data[i + 1] = gpio->ledpin[i / 2].pin;
-				}
-				if (copy_to_user(wrq->u.data.pointer, data,
-						 sizeof(int) *
-						 gpio->header.len)) {
-					lbs_pr_debug(1, "Copy to user failed\n");
-					return -EFAULT;
-				}
-
-				wrq->u.data.length = gpio->header.len;
-			}
-			break;
-		}
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	LEAVE();
-	return ret;
-}
-
-
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
index d4926b8..78ac306 100644
--- a/drivers/net/wireless/libertas/join.c
+++ b/drivers/net/wireless/libertas/join.c
@@ -7,6 +7,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
+#include <linux/etherdevice.h>
 
 #include <net/iw_handler.h>
 
@@ -14,6 +15,7 @@
 #include "decl.h"
 #include "join.h"
 #include "dev.h"
+#include "assoc.h"
 
 #define AD_HOC_CAP_PRIVACY_ON 1
 
@@ -60,7 +62,7 @@
 	lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp));
 	lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size);
 	lbs_dbg_hex("Common rates:", ptr, rate1_size);
-	lbs_pr_debug(1, "Tx datarate is set to 0x%X\n", adapter->datarate);
+	lbs_deb_join("Tx datarate is set to 0x%X\n", adapter->datarate);
 
 	if (!adapter->is_datarate_auto) {
 		while (*ptr) {
@@ -104,24 +106,22 @@
  *
  *  @return          0-success, otherwise fail
  */
-int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
+int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req)
 {
 	wlan_adapter *adapter = priv->adapter;
 	int ret;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_JOIN);
 
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_authenticate,
 				    0, cmd_option_waitforrsp,
-				    0, pbssdesc->macaddress);
+				    0, assoc_req->bss.bssid);
 
-	if (ret) {
-		LEAVE();
-		return ret;
-	}
+	if (ret)
+		goto done;
 
 	/* set preamble to firmware */
-	if (adapter->capinfo.shortpreamble && pbssdesc->cap.shortpreamble)
+	if (adapter->capinfo.shortpreamble && assoc_req->bss.cap.shortpreamble)
 		adapter->preamble = cmd_type_short_preamble;
 	else
 		adapter->preamble = cmd_type_long_preamble;
@@ -129,9 +129,10 @@
 	libertas_set_radio_control(priv);
 
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_associate,
-				    0, cmd_option_waitforrsp, 0, pbssdesc);
+				    0, cmd_option_waitforrsp, 0, assoc_req);
 
-	LEAVE();
+done:
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
 	return ret;
 }
 
@@ -142,7 +143,7 @@
  *  @param adhocssid    The ssid of the Adhoc Network
  *  @return             0--success, -1--fail
  */
-int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *adhocssid)
+int libertas_start_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req)
 {
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
@@ -150,22 +151,20 @@
 	adapter->adhoccreate = 1;
 
 	if (!adapter->capinfo.shortpreamble) {
-		lbs_pr_debug(1, "AdhocStart: Long preamble\n");
+		lbs_deb_join("AdhocStart: Long preamble\n");
 		adapter->preamble = cmd_type_long_preamble;
 	} else {
-		lbs_pr_debug(1, "AdhocStart: Short preamble\n");
+		lbs_deb_join("AdhocStart: Short preamble\n");
 		adapter->preamble = cmd_type_short_preamble;
 	}
 
 	libertas_set_radio_control(priv);
 
-	lbs_pr_debug(1, "Adhoc channel = %d\n", adapter->adhocchannel);
-	lbs_pr_debug(1, "curbssparams.channel = %d\n",
-	       adapter->curbssparams.channel);
-	lbs_pr_debug(1, "curbssparams.band = %d\n", adapter->curbssparams.band);
+	lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
+	lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
 
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_start,
-				    0, cmd_option_waitforrsp, 0, adhocssid);
+				    0, cmd_option_waitforrsp, 0, assoc_req);
 
 	return ret;
 }
@@ -179,52 +178,53 @@
  *
  *  @return             0--success, -1--fail
  */
-int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbssdesc)
+int libertas_join_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req)
 {
 	wlan_adapter *adapter = priv->adapter;
+	struct bss_descriptor * bss = &assoc_req->bss;
 	int ret = 0;
 
-	lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid =%s\n",
-	       adapter->curbssparams.ssid.ssid);
-	lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid_len =%u\n",
-	       adapter->curbssparams.ssid.ssidlength);
-	lbs_pr_debug(1, "libertas_join_adhoc_network: ssid =%s\n", pbssdesc->ssid.ssid);
-	lbs_pr_debug(1, "libertas_join_adhoc_network: ssid len =%u\n",
-	       pbssdesc->ssid.ssidlength);
+	lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
+	             __func__,
+	             escape_essid(adapter->curbssparams.ssid,
+	                          adapter->curbssparams.ssid_len),
+	             adapter->curbssparams.ssid_len);
+	lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
+	             __func__, escape_essid(bss->ssid, bss->ssid_len),
+	             bss->ssid_len);
 
 	/* check if the requested SSID is already joined */
-	if (adapter->curbssparams.ssid.ssidlength
-	    && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid)
+	if (adapter->curbssparams.ssid_len
+	    && !libertas_ssid_cmp(adapter->curbssparams.ssid,
+	                          adapter->curbssparams.ssid_len,
+	                          bss->ssid, bss->ssid_len)
 	    && (adapter->mode == IW_MODE_ADHOC)) {
-
-        lbs_pr_debug(1,
+		lbs_deb_join(
 		       "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
 		       "not attempting to re-join");
-
 		return -1;
 	}
 
 	/*Use shortpreamble only when both creator and card supports
 	   short preamble */
-	if (!pbssdesc->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
-		lbs_pr_debug(1, "AdhocJoin: Long preamble\n");
+	if (!bss->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
+		lbs_deb_join("AdhocJoin: Long preamble\n");
 		adapter->preamble = cmd_type_long_preamble;
 	} else {
-		lbs_pr_debug(1, "AdhocJoin: Short preamble\n");
+		lbs_deb_join("AdhocJoin: Short preamble\n");
 		adapter->preamble = cmd_type_short_preamble;
 	}
 
 	libertas_set_radio_control(priv);
 
-	lbs_pr_debug(1, "curbssparams.channel = %d\n",
-	       adapter->curbssparams.channel);
-	lbs_pr_debug(1, "curbssparams.band = %c\n", adapter->curbssparams.band);
+	lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
+	lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
 
 	adapter->adhoccreate = 0;
 
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_join,
 				    0, cmd_option_waitforrsp,
-				    OID_802_11_SSID, pbssdesc);
+				    OID_802_11_SSID, assoc_req);
 
 	return ret;
 }
@@ -265,6 +265,8 @@
 	int ret = -1;
 	u8 *bssid = pdata_buf;
 
+	lbs_deb_enter(LBS_DEB_JOIN);
+
 	cmd->command = cpu_to_le16(cmd_802_11_authenticate);
 	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
 	                        + S_DS_GEN);
@@ -281,18 +283,19 @@
 		pauthenticate->authtype = 0x80;
 		break;
 	default:
-		lbs_pr_debug(1, "AUTH_CMD: invalid auth alg 0x%X\n",
+		lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
 		             adapter->secinfo.auth_mode);
 		goto out;
 	}
 
 	memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
 
-	lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n",
-	       bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+	lbs_deb_join("AUTH_CMD: BSSID is : " MAC_FMT " auth=0x%X\n",
+	             MAC_ARG(bssid), pauthenticate->authtype);
 	ret = 0;
 
 out:
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
 	return ret;
 }
 
@@ -302,22 +305,20 @@
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_JOIN);
 
 	cmd->command = cpu_to_le16(cmd_802_11_deauthenticate);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
 			     S_DS_GEN);
 
 	/* set AP MAC address */
-	memmove(dauth->macaddr, adapter->curbssparams.bssid,
-		ETH_ALEN);
+	memmove(dauth->macaddr, adapter->curbssparams.bssid, ETH_ALEN);
 
 	/* Reason code 3 = Station is leaving */
 #define REASON_CODE_STA_LEAVING 3
 	dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_JOIN);
 	return 0;
 }
 
@@ -327,20 +328,20 @@
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
 	int ret = 0;
-	struct bss_descriptor *pbssdesc;
+	struct assoc_request * assoc_req = pdata_buf;
+	struct bss_descriptor * bss = &assoc_req->bss;
 	u8 *card_rates;
 	u8 *pos;
 	int card_rates_size;
-	u16 tmpcap;
+	u16 tmpcap, tmplen;
 	struct mrvlietypes_ssidparamset *ssid;
 	struct mrvlietypes_phyparamset *phy;
 	struct mrvlietypes_ssparamset *ss;
 	struct mrvlietypes_ratesparamset *rates;
 	struct mrvlietypes_rsnparamset *rsn;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_JOIN);
 
-	pbssdesc = pdata_buf;
 	pos = (u8 *) passo;
 
 	if (!adapter) {
@@ -350,15 +351,11 @@
 
 	cmd->command = cpu_to_le16(cmd_802_11_associate);
 
-	/* Save so we know which BSS Desc to use in the response handler */
-	adapter->pattemptedbssdesc = pbssdesc;
-
-	memcpy(passo->peerstaaddr,
-	       pbssdesc->macaddress, sizeof(passo->peerstaaddr));
+	memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
 	pos += sizeof(passo->peerstaaddr);
 
 	/* set the listen interval */
-	passo->listeninterval = adapter->listeninterval;
+	passo->listeninterval = cpu_to_le16(adapter->listeninterval);
 
 	pos += sizeof(passo->capinfo);
 	pos += sizeof(passo->listeninterval);
@@ -367,30 +364,30 @@
 
 	ssid = (struct mrvlietypes_ssidparamset *) pos;
 	ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
-	ssid->header.len = pbssdesc->ssid.ssidlength;
-	memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len);
-	pos += sizeof(ssid->header) + ssid->header.len;
-	ssid->header.len = cpu_to_le16(ssid->header.len);
+	tmplen = bss->ssid_len;
+	ssid->header.len = cpu_to_le16(tmplen);
+	memcpy(ssid->ssid, bss->ssid, tmplen);
+	pos += sizeof(ssid->header) + tmplen;
 
 	phy = (struct mrvlietypes_phyparamset *) pos;
 	phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
-	phy->header.len = sizeof(phy->fh_ds.dsparamset);
+	tmplen = sizeof(phy->fh_ds.dsparamset);
+	phy->header.len = cpu_to_le16(tmplen);
 	memcpy(&phy->fh_ds.dsparamset,
-	       &pbssdesc->phyparamset.dsparamset.currentchan,
-	       sizeof(phy->fh_ds.dsparamset));
-	pos += sizeof(phy->header) + phy->header.len;
-	phy->header.len = cpu_to_le16(phy->header.len);
+	       &bss->phyparamset.dsparamset.currentchan,
+	       tmplen);
+	pos += sizeof(phy->header) + tmplen;
 
 	ss = (struct mrvlietypes_ssparamset *) pos;
 	ss->header.type = cpu_to_le16(TLV_TYPE_CF);
-	ss->header.len = sizeof(ss->cf_ibss.cfparamset);
-	pos += sizeof(ss->header) + ss->header.len;
-	ss->header.len = cpu_to_le16(ss->header.len);
+	tmplen = sizeof(ss->cf_ibss.cfparamset);
+	ss->header.len = cpu_to_le16(tmplen);
+	pos += sizeof(ss->header) + tmplen;
 
 	rates = (struct mrvlietypes_ratesparamset *) pos;
 	rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
 
-	memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
+	memcpy(&rates->rates, &bss->libertas_supported_rates, WLAN_SUPPORTED_RATES);
 
 	card_rates = libertas_supported_rates;
 	card_rates_size = sizeof(libertas_supported_rates);
@@ -401,41 +398,42 @@
 		goto done;
 	}
 
-	rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
-	adapter->curbssparams.numofrates = rates->header.len;
+	tmplen = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
+	adapter->curbssparams.numofrates = tmplen;
 
-	pos += sizeof(rates->header) + rates->header.len;
-	rates->header.len = cpu_to_le16(rates->header.len);
+	pos += sizeof(rates->header) + tmplen;
+	rates->header.len = cpu_to_le16(tmplen);
 
-	if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
+	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
 		rsn = (struct mrvlietypes_rsnparamset *) pos;
-		rsn->header.type = (u16) adapter->wpa_ie[0];	/* WPA_IE or WPA2_IE */
-		rsn->header.type = cpu_to_le16(rsn->header.type);
-		rsn->header.len = (u16) adapter->wpa_ie[1];
-		memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len);
+		/* WPA_IE or WPA2_IE */
+		rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
+		tmplen = (u16) assoc_req->wpa_ie[1];
+		rsn->header.len = cpu_to_le16(tmplen);
+		memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
 		lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn,
-			sizeof(rsn->header) + rsn->header.len);
-		pos += sizeof(rsn->header) + rsn->header.len;
-		rsn->header.len = cpu_to_le16(rsn->header.len);
+			sizeof(rsn->header) + tmplen);
+		pos += sizeof(rsn->header) + tmplen;
 	}
 
 	/* update curbssparams */
-	adapter->curbssparams.channel =
-	    (pbssdesc->phyparamset.dsparamset.currentchan);
+	adapter->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
 
 	/* Copy the infra. association rates into Current BSS state structure */
 	memcpy(&adapter->curbssparams.datarates, &rates->rates,
-	       min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len));
+	       min_t(size_t, sizeof(adapter->curbssparams.datarates),
+		     cpu_to_le16(rates->header.len)));
 
-	lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len);
+	lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n",
+		     cpu_to_le16(rates->header.len));
 
 	/* set IBSS field */
-	if (pbssdesc->mode == IW_MODE_INFRA) {
+	if (bss->mode == IW_MODE_INFRA) {
 #define CAPINFO_ESS_MODE 1
 		passo->capinfo.ess = CAPINFO_ESS_MODE;
 	}
 
-	if (libertas_parse_dnld_countryinfo_11d(priv)) {
+	if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
 		ret = -1;
 		goto done;
 	}
@@ -443,31 +441,28 @@
 	cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
 
 	/* set the capability info at last */
-	memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo));
+	memcpy(&tmpcap, &bss->cap, sizeof(passo->capinfo));
 	tmpcap &= CAPINFO_MASK;
-	lbs_pr_debug(1, "ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
-	       tmpcap, CAPINFO_MASK);
-	tmpcap = cpu_to_le16(tmpcap);
+	lbs_deb_join("ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
+		     tmpcap, CAPINFO_MASK);
 	memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo));
 
-      done:
-	LEAVE();
+done:
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
 	return ret;
 }
 
 int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
-				 struct cmd_ds_command *cmd, void *pssid)
+				 struct cmd_ds_command *cmd, void *pdata_buf)
 {
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
 	int ret = 0;
 	int cmdappendsize = 0;
 	int i;
-	u16 tmpcap;
-	struct bss_descriptor *pbssdesc;
-	struct WLAN_802_11_SSID *ssid = pssid;
+	struct assoc_request * assoc_req = pdata_buf;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_JOIN);
 
 	if (!adapter) {
 		ret = -1;
@@ -476,9 +471,6 @@
 
 	cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start);
 
-	pbssdesc = &adapter->curbssparams.bssdescriptor;
-	adapter->pattemptedbssdesc = pbssdesc;
-
 	/*
 	 * Fill in the parameters for 2 data structures:
 	 *   1. cmd_ds_802_11_ad_hoc_start command
@@ -492,20 +484,16 @@
 	 */
 
 	memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE);
+	memcpy(adhs->SSID, assoc_req->ssid, assoc_req->ssid_len);
 
-	memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength);
-
-	lbs_pr_debug(1, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
-
-	memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE);
-	memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength);
-
-	pbssdesc->ssid.ssidlength = ssid->ssidlength;
+	lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
+	             escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+	             assoc_req->ssid_len);
 
 	/* set the BSS type */
 	adhs->bsstype = cmd_bss_type_ibss;
-	pbssdesc->mode = IW_MODE_ADHOC;
-	adhs->beaconperiod = adapter->beaconperiod;
+	adapter->mode = IW_MODE_ADHOC;
+	adhs->beaconperiod = cpu_to_le16(adapter->beaconperiod);
 
 	/* set Physical param set */
 #define DS_PARA_IE_ID   3
@@ -514,18 +502,12 @@
 	adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
 	adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
 
-	WARN_ON(!adapter->adhocchannel);
+	WARN_ON(!assoc_req->channel);
 
-	lbs_pr_debug(1, "ADHOC_S_CMD: Creating ADHOC on channel %d\n",
-	       adapter->adhocchannel);
+	lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
+		     assoc_req->channel);
 
-	adapter->curbssparams.channel = adapter->adhocchannel;
-
-	pbssdesc->channel = adapter->adhocchannel;
-	adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel;
-
-	memcpy(&pbssdesc->phyparamset,
-	       &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
+	adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
 
 	/* set IBSS param set */
 #define IBSS_PARA_IE_ID   6
@@ -533,26 +515,21 @@
 
 	adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
 	adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
-	adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow;
-	memcpy(&pbssdesc->ssparamset,
-	       &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset));
+	adhs->ssparamset.ibssparamset.atimwindow = cpu_to_le16(adapter->atimwindow);
 
 	/* set capability info */
 	adhs->cap.ess = 0;
 	adhs->cap.ibss = 1;
-	pbssdesc->cap.ibss = 1;
 
 	/* probedelay */
 	adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
 
 	/* set up privacy in adapter->scantable[i] */
-	if (adapter->secinfo.wep_enabled) {
-		lbs_pr_debug(1, "ADHOC_S_CMD: WEP enabled, setting privacy on\n");
-		pbssdesc->privacy = wlan802_11privfilter8021xWEP;
+	if (assoc_req->secinfo.wep_enabled) {
+		lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
 		adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
 	} else {
-		lbs_pr_debug(1, "ADHOC_S_CMD: WEP disabled, setting privacy off\n");
-		pbssdesc->privacy = wlan802_11privfilteracceptall;
+		lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
 	}
 
 	memset(adhs->datarate, 0, sizeof(adhs->datarate));
@@ -574,29 +551,24 @@
 	memcpy(&adapter->curbssparams.datarates,
 	       &adhs->datarate, adapter->curbssparams.numofrates);
 
-	lbs_pr_debug(1, "ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
+	lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
 	       adhs->datarate[0], adhs->datarate[1],
 	       adhs->datarate[2], adhs->datarate[3]);
 
-	lbs_pr_debug(1, "ADHOC_S_CMD: AD HOC Start command is ready\n");
+	lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
 
 	if (libertas_create_dnld_countryinfo_11d(priv)) {
-		lbs_pr_debug(1, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
+		lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
 		ret = -1;
 		goto done;
 	}
 
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start)
-			     + S_DS_GEN + cmdappendsize);
-
-	memcpy(&tmpcap, &adhs->cap, sizeof(u16));
-	tmpcap = cpu_to_le16(tmpcap);
-	memcpy(&adhs->cap, &tmpcap, sizeof(u16));
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
+				S_DS_GEN + cmdappendsize);
 
 	ret = 0;
 done:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
 	return ret;
 }
 
@@ -614,7 +586,8 @@
 {
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj;
-	struct bss_descriptor *pbssdesc = pdata_buf;
+	struct assoc_request * assoc_req = pdata_buf;
+	struct bss_descriptor *bss = &assoc_req->bss;
 	int cmdappendsize = 0;
 	int ret = 0;
 	u8 *card_rates;
@@ -622,70 +595,59 @@
 	u16 tmpcap;
 	int i;
 
-	ENTER();
-
-	adapter->pattemptedbssdesc = pbssdesc;
+	lbs_deb_enter(LBS_DEB_JOIN);
 
 	cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join);
 
 	padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss;
 
-	padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod;
+	padhocjoin->bssdescriptor.beaconperiod = cpu_to_le16(bss->beaconperiod);
 
-	memcpy(&padhocjoin->bssdescriptor.BSSID,
-	       &pbssdesc->macaddress, ETH_ALEN);
-
-	memcpy(&padhocjoin->bssdescriptor.SSID,
-	       &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength);
+	memcpy(&padhocjoin->bssdescriptor.BSSID, &bss->bssid, ETH_ALEN);
+	memcpy(&padhocjoin->bssdescriptor.SSID, &bss->ssid, bss->ssid_len);
 
 	memcpy(&padhocjoin->bssdescriptor.phyparamset,
-	       &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset));
+	       &bss->phyparamset, sizeof(union ieeetypes_phyparamset));
 
 	memcpy(&padhocjoin->bssdescriptor.ssparamset,
-	       &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset));
+	       &bss->ssparamset, sizeof(union IEEEtypes_ssparamset));
 
-	memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo));
+	memcpy(&tmpcap, &bss->cap, sizeof(struct ieeetypes_capinfo));
 	tmpcap &= CAPINFO_MASK;
 
-	lbs_pr_debug(1, "ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
+	lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
 	       tmpcap, CAPINFO_MASK);
 	memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap,
 	       sizeof(struct ieeetypes_capinfo));
 
 	/* information on BSSID descriptor passed to FW */
-    lbs_pr_debug(1,
-	       "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
-	       padhocjoin->bssdescriptor.BSSID[0],
-	       padhocjoin->bssdescriptor.BSSID[1],
-	       padhocjoin->bssdescriptor.BSSID[2],
-	       padhocjoin->bssdescriptor.BSSID[3],
-	       padhocjoin->bssdescriptor.BSSID[4],
-	       padhocjoin->bssdescriptor.BSSID[5],
+	lbs_deb_join(
+	       "ADHOC_J_CMD: BSSID = " MAC_FMT ", SSID = '%s'\n",
+	       MAC_ARG(padhocjoin->bssdescriptor.BSSID),
 	       padhocjoin->bssdescriptor.SSID);
 
 	/* failtimeout */
 	padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
 
 	/* probedelay */
-	padhocjoin->probedelay =
-	    cpu_to_le16(cmd_scan_probe_delay_time);
+	padhocjoin->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
 
 	/* Copy Data rates from the rates recorded in scan response */
 	memset(padhocjoin->bssdescriptor.datarates, 0,
 	       sizeof(padhocjoin->bssdescriptor.datarates));
-	memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates,
+	memcpy(padhocjoin->bssdescriptor.datarates, bss->datarates,
 	       min(sizeof(padhocjoin->bssdescriptor.datarates),
-		   sizeof(pbssdesc->datarates)));
+		   sizeof(bss->datarates)));
 
 	card_rates = libertas_supported_rates;
 	card_rates_size = sizeof(libertas_supported_rates);
 
-	adapter->curbssparams.channel = pbssdesc->channel;
+	adapter->curbssparams.channel = bss->channel;
 
 	if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates,
 			     sizeof(padhocjoin->bssdescriptor.datarates),
 			     card_rates, card_rates_size)) {
-		lbs_pr_debug(1, "ADHOC_J_CMD: get_common_rates returns error.\n");
+		lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
 		ret = -1;
 		goto done;
 	}
@@ -704,17 +666,17 @@
 	       adapter->curbssparams.numofrates);
 
 	padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow =
-	    cpu_to_le16(pbssdesc->atimwindow);
+	    cpu_to_le16(bss->atimwindow);
 
-	if (adapter->secinfo.wep_enabled) {
+	if (assoc_req->secinfo.wep_enabled) {
 		padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
 	}
 
 	if (adapter->psmode == wlan802_11powermodemax_psp) {
 		/* wake up first */
-		enum WLAN_802_11_POWER_MODE Localpsmode;
+		__le32 Localpsmode;
 
-		Localpsmode = wlan802_11powermodecam;
+		Localpsmode = cpu_to_le32(wlan802_11powermodecam);
 		ret = libertas_prepare_and_send_command(priv,
 					    cmd_802_11_ps_mode,
 					    cmd_act_set,
@@ -726,24 +688,16 @@
 		}
 	}
 
-	if (libertas_parse_dnld_countryinfo_11d(priv)) {
+	if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
 		ret = -1;
 		goto done;
 	}
 
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join)
-			     + S_DS_GEN + cmdappendsize);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
+				S_DS_GEN + cmdappendsize);
 
-	memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap,
-	       sizeof(struct ieeetypes_capinfo));
-	tmpcap = cpu_to_le16(tmpcap);
-
-	memcpy(&padhocjoin->bssdescriptor.cap,
-	       &tmpcap, sizeof(struct ieeetypes_capinfo));
-
-      done:
-	LEAVE();
+done:
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
 	return ret;
 }
 
@@ -754,19 +708,24 @@
 	int ret = 0;
 	union iwreq_data wrqu;
 	struct ieeetypes_assocrsp *passocrsp;
-	struct bss_descriptor *pbssdesc;
+	struct bss_descriptor * bss;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_JOIN);
+
+	if (!adapter->in_progress_assoc_req) {
+		lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
+		ret = -1;
+		goto done;
+	}
+	bss = &adapter->in_progress_assoc_req->bss;
 
 	passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
 
-	if (passocrsp->statuscode) {
-
+	if (le16_to_cpu(passocrsp->statuscode)) {
 		libertas_mac_event_disconnected(priv);
 
-        lbs_pr_debug(1,
-		       "ASSOC_RESP: Association failed, status code = %d\n",
-		       passocrsp->statuscode);
+		lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
+			     le16_to_cpu(passocrsp->statuscode));
 
 		ret = -1;
 		goto done;
@@ -778,24 +737,15 @@
 	/* Send a Media Connected event, according to the Spec */
 	adapter->connect_status = libertas_connected;
 
-	/* Set the attempted BSSID Index to current */
-	pbssdesc = adapter->pattemptedbssdesc;
+	lbs_deb_join("ASSOC_RESP: assocated to '%s'\n",
+	             escape_essid(bss->ssid, bss->ssid_len));
 
-	lbs_pr_debug(1, "ASSOC_RESP: %s\n", pbssdesc->ssid.ssid);
+	/* Update current SSID and BSSID */
+	memcpy(&adapter->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+	adapter->curbssparams.ssid_len = bss->ssid_len;
+	memcpy(adapter->curbssparams.bssid, bss->bssid, ETH_ALEN);
 
-	/* Set the new SSID to current SSID */
-	memcpy(&adapter->curbssparams.ssid,
-	       &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
-
-	/* Set the new BSSID (AP's MAC address) to current BSSID */
-	memcpy(adapter->curbssparams.bssid,
-	       pbssdesc->macaddress, ETH_ALEN);
-
-	/* Make a copy of current BSSID descriptor */
-	memcpy(&adapter->curbssparams.bssdescriptor,
-	       pbssdesc, sizeof(struct bss_descriptor));
-
-	lbs_pr_debug(1, "ASSOC_RESP: currentpacketfilter is %x\n",
+	lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
 	       adapter->currentpacketfilter);
 
 	adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
@@ -806,28 +756,31 @@
 	adapter->nextSNRNF = 0;
 	adapter->numSNRNF = 0;
 
-	netif_carrier_on(priv->wlan_dev.netdev);
-	netif_wake_queue(priv->wlan_dev.netdev);
+	netif_carrier_on(priv->dev);
+	netif_wake_queue(priv->dev);
 
-	lbs_pr_debug(1, "ASSOC_RESP: Associated \n");
+	netif_carrier_on(priv->mesh_dev);
+	netif_wake_queue(priv->mesh_dev);
+
+	lbs_deb_join("ASSOC_RESP: Associated \n");
 
 	memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
 
-      done:
-	LEAVE();
+done:
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
 	return ret;
 }
 
 int libertas_ret_80211_disassociate(wlan_private * priv,
 				 struct cmd_ds_command *resp)
 {
-	ENTER();
+	lbs_deb_enter(LBS_DEB_JOIN);
 
 	libertas_mac_event_disconnected(priv);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_JOIN);
 	return 0;
 }
 
@@ -840,90 +793,85 @@
 	u16 result = le16_to_cpu(resp->result);
 	struct cmd_ds_802_11_ad_hoc_result *padhocresult;
 	union iwreq_data wrqu;
-	struct bss_descriptor *pbssdesc;
+	struct bss_descriptor *bss;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_JOIN);
 
 	padhocresult = &resp->params.result;
 
-	lbs_pr_debug(1, "ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size));
-	lbs_pr_debug(1, "ADHOC_S_RESP: command = %x\n", command);
-	lbs_pr_debug(1, "ADHOC_S_RESP: result = %x\n", result);
+	lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
+	lbs_deb_join("ADHOC_RESP: command = %x\n", command);
+	lbs_deb_join("ADHOC_RESP: result = %x\n", result);
 
-	pbssdesc = adapter->pattemptedbssdesc;
+	if (!adapter->in_progress_assoc_req) {
+		lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
+		ret = -1;
+		goto done;
+	}
+	bss = &adapter->in_progress_assoc_req->bss;
 
 	/*
 	 * Join result code 0 --> SUCCESS
 	 */
 	if (result) {
-		lbs_pr_debug(1, "ADHOC_RESP failed\n");
+		lbs_deb_join("ADHOC_RESP: failed\n");
 		if (adapter->connect_status == libertas_connected) {
 			libertas_mac_event_disconnected(priv);
 		}
-
-		memset(&adapter->curbssparams.bssdescriptor,
-		       0x00, sizeof(adapter->curbssparams.bssdescriptor));
-
-		LEAVE();
-		return -1;
+		ret = -1;
+		goto done;
 	}
 
 	/*
 	 * Now the join cmd should be successful
 	 * If BSSID has changed use SSID to compare instead of BSSID
 	 */
-	lbs_pr_debug(1, "ADHOC_J_RESP  %s\n", pbssdesc->ssid.ssid);
+	lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
+	             escape_essid(bss->ssid, bss->ssid_len));
 
 	/* Send a Media Connected event, according to the Spec */
 	adapter->connect_status = libertas_connected;
 
 	if (command == cmd_ret_802_11_ad_hoc_start) {
 		/* Update the created network descriptor with the new BSSID */
-		memcpy(pbssdesc->macaddress,
-		       padhocresult->BSSID, ETH_ALEN);
-	} else {
-
-		/* Make a copy of current BSSID descriptor, only needed for join since
-		 *   the current descriptor is already being used for adhoc start
-		 */
-		memmove(&adapter->curbssparams.bssdescriptor,
-			pbssdesc, sizeof(struct bss_descriptor));
+		memcpy(bss->bssid, padhocresult->BSSID, ETH_ALEN);
 	}
 
 	/* Set the BSSID from the joined/started descriptor */
-	memcpy(&adapter->curbssparams.bssid,
-	       pbssdesc->macaddress, ETH_ALEN);
+	memcpy(&adapter->curbssparams.bssid, bss->bssid, ETH_ALEN);
 
 	/* Set the new SSID to current SSID */
-	memcpy(&adapter->curbssparams.ssid,
-	       &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
+	memcpy(&adapter->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+	adapter->curbssparams.ssid_len = bss->ssid_len;
 
-	netif_carrier_on(priv->wlan_dev.netdev);
-	netif_wake_queue(priv->wlan_dev.netdev);
+	netif_carrier_on(priv->dev);
+	netif_wake_queue(priv->dev);
+
+	netif_carrier_on(priv->mesh_dev);
+	netif_wake_queue(priv->mesh_dev);
 
 	memset(&wrqu, 0, sizeof(wrqu));
 	memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
 
-	lbs_pr_debug(1, "ADHOC_RESP: - Joined/Started Ad Hoc\n");
-	lbs_pr_debug(1, "ADHOC_RESP: channel = %d\n", adapter->adhocchannel);
-	lbs_pr_debug(1, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       padhocresult->BSSID[0], padhocresult->BSSID[1],
-	       padhocresult->BSSID[2], padhocresult->BSSID[3],
-	       padhocresult->BSSID[4], padhocresult->BSSID[5]);
+	lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
+	lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->curbssparams.channel);
+	lbs_deb_join("ADHOC_RESP: BSSID = " MAC_FMT "\n",
+	       MAC_ARG(padhocresult->BSSID));
 
-	LEAVE();
+done:
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
 	return ret;
 }
 
 int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
 				struct cmd_ds_command *resp)
 {
-	ENTER();
+	lbs_deb_enter(LBS_DEB_JOIN);
 
 	libertas_mac_event_disconnected(priv);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_JOIN);
 	return 0;
 }
diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h
index 115f5a8..d522630 100644
--- a/drivers/net/wireless/libertas/join.h
+++ b/drivers/net/wireless/libertas/join.h
@@ -9,6 +9,7 @@
 #define _WLAN_JOIN_H
 
 #include "defs.h"
+#include "dev.h"
 
 struct cmd_ds_command;
 extern int libertas_cmd_80211_authenticate(wlan_private * priv,
@@ -21,7 +22,7 @@
 				       struct cmd_ds_command *cmd);
 extern int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
 					struct cmd_ds_command *cmd,
-					void *pssid);
+					void *pdata_buf);
 extern int libertas_cmd_80211_deauthenticate(wlan_private * priv,
 					  struct cmd_ds_command *cmd);
 extern int libertas_cmd_80211_associate(wlan_private * priv,
@@ -39,12 +40,10 @@
 
 extern int libertas_reassociation_thread(void *data);
 
-struct WLAN_802_11_SSID;
-struct bss_descriptor;
-
 extern int libertas_start_adhoc_network(wlan_private * priv,
-			     struct WLAN_802_11_SSID *adhocssid);
-extern int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor *pbssdesc);
+			     struct assoc_request * assoc_req);
+extern int libertas_join_adhoc_network(wlan_private * priv,
+				struct assoc_request * assoc_req);
 extern int libertas_stop_adhoc_network(wlan_private * priv);
 
 extern int libertas_send_deauthentication(wlan_private * priv);
@@ -52,6 +51,6 @@
 
 extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
 
-int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc);
+int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req);
 
 #endif
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index b9b25ce..9f36624 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -4,6 +4,7 @@
   * thread etc..
   */
 
+#include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
 #include <linux/etherdevice.h>
@@ -11,26 +12,28 @@
 #include <linux/if_arp.h>
 
 #include <net/iw_handler.h>
+#include <net/ieee80211.h>
 
 #include "host.h"
-#include "sbi.h"
 #include "decl.h"
 #include "dev.h"
-#include "fw.h"
 #include "wext.h"
 #include "debugfs.h"
 #include "assoc.h"
 
-#define DRIVER_RELEASE_VERSION "320.p0"
+#define DRIVER_RELEASE_VERSION "322.p0"
 const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
 #ifdef  DEBUG
     "-dbg"
 #endif
     "";
 
-#ifdef ENABLE_PM
-static struct pm_dev *wlan_pm_dev = NULL;
-#endif
+
+/* Module parameters */
+unsigned int libertas_debug = 0;
+module_param(libertas_debug, int, 0644);
+EXPORT_SYMBOL_GPL(libertas_debug);
+
 
 #define WLAN_TX_PWR_DEFAULT		20	/*100mW */
 #define WLAN_TX_PWR_US_DEFAULT		20	/*100mW */
@@ -146,14 +149,6 @@
 };
 
 /**
- * the rates supported by the card
- */
-u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] =
-    { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
-	0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
-};
-
-/**
  * the rates supported
  */
 u8 libertas_supported_rates[G_SUPPORTED_RATES] =
@@ -173,66 +168,57 @@
 u8 libertas_adhoc_rates_b[4] = { 0x82, 0x84, 0x8b, 0x96 };
 
 /**
- * the global variable of a pointer to wlan_private
- * structure variable
- */
-static wlan_private *wlanpriv = NULL;
-
-#define MAX_DEVS 5
-static struct net_device *libertas_devs[MAX_DEVS];
-static int libertas_found = 0;
-
-/**
  * the table to keep region code
  */
 u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
     { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
 
-static u8 *default_fw_name = "usb8388.bin";
-
 /**
  * Attributes exported through sysfs
  */
 
 /**
- * @brief Get function for sysfs attribute libertas_mpp
+ * @brief Get function for sysfs attribute anycast_mask
  */
-static ssize_t libertas_mpp_get(struct device * dev,
-		struct device_attribute *attr, char * buf) {
+static ssize_t libertas_anycast_get(struct device * dev,
+		struct device_attribute *attr, char * buf)
+{
 	struct cmd_ds_mesh_access mesh_access;
 
 	memset(&mesh_access, 0, sizeof(mesh_access));
 	libertas_prepare_and_send_command(to_net_dev(dev)->priv,
 			cmd_mesh_access,
-			cmd_act_mesh_get_mpp,
+			cmd_act_mesh_get_anycast,
 			cmd_option_waitforrsp, 0, (void *)&mesh_access);
 
-	return snprintf(buf, 3, "%d\n", mesh_access.data[0]);
+	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
 }
 
 /**
- * @brief Set function for sysfs attribute libertas_mpp
+ * @brief Set function for sysfs attribute anycast_mask
  */
-static ssize_t libertas_mpp_set(struct device * dev,
-		struct device_attribute *attr, const char * buf, size_t count) {
+static ssize_t libertas_anycast_set(struct device * dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
 	struct cmd_ds_mesh_access mesh_access;
-
+	uint32_t datum;
 
 	memset(&mesh_access, 0, sizeof(mesh_access));
-	sscanf(buf, "%d", &(mesh_access.data[0]));
+	sscanf(buf, "%x", &datum);
+	mesh_access.data[0] = cpu_to_le32(datum);
+
 	libertas_prepare_and_send_command((to_net_dev(dev))->priv,
 			cmd_mesh_access,
-			cmd_act_mesh_set_mpp,
+			cmd_act_mesh_set_anycast,
 			cmd_option_waitforrsp, 0, (void *)&mesh_access);
 	return strlen(buf);
 }
 
 /**
- * libertas_mpp attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/libertas-mpp)
+ * anycast_mask attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/anycast_mask)
  */
-static DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get,
-		libertas_mpp_set );
+static DEVICE_ATTR(anycast_mask, 0644, libertas_anycast_get, libertas_anycast_set);
 
 /**
  *  @brief Check if the device can be open and wait if necessary.
@@ -245,7 +231,8 @@
  * function to work around the issue.
  *
  */
-static int pre_open_check(struct net_device *dev) {
+static int pre_open_check(struct net_device *dev)
+{
 	wlan_private *priv = (wlan_private *) dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 	int i = 0;
@@ -255,8 +242,7 @@
 		msleep_interruptible(100);
 	}
 	if (!adapter->fw_ready) {
-		lbs_pr_info("FW not ready, pre_open_check() return failure\n");
-		LEAVE();
+		lbs_pr_err("firmware not ready\n");
 		return -1;
 	}
 
@@ -274,17 +260,19 @@
 	wlan_private *priv = (wlan_private *) dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
-
+	lbs_deb_enter(LBS_DEB_NET);
 
 	priv->open = 1;
 
 	if (adapter->connect_status == libertas_connected) {
-		netif_carrier_on(priv->wlan_dev.netdev);
-	} else
-		netif_carrier_off(priv->wlan_dev.netdev);
+		netif_carrier_on(priv->dev);
+		netif_carrier_on(priv->mesh_dev);
+	} else {
+		netif_carrier_off(priv->dev);
+		netif_carrier_off(priv->mesh_dev);
+	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_NET);
 	return 0;
 }
 /**
@@ -297,12 +285,12 @@
 {
 	wlan_private *priv = (wlan_private *) dev->priv ;
 
-	if(pre_open_check(dev) == -1)
+	if (pre_open_check(dev) == -1)
 		return -1;
 	priv->mesh_open = 1 ;
-	netif_start_queue(priv->mesh_dev);
+	netif_wake_queue(priv->mesh_dev);
 	if (priv->infra_open == 0)
-		return wlan_dev_open(priv->wlan_dev.netdev) ;
+		return wlan_dev_open(priv->dev) ;
 	return 0;
 }
 
@@ -319,9 +307,9 @@
 	if(pre_open_check(dev) == -1)
 		return -1;
 	priv->infra_open = 1 ;
-	netif_wake_queue(priv->wlan_dev.netdev);
+	netif_wake_queue(priv->dev);
 	if (priv->open == 0)
-		return wlan_dev_open(priv->wlan_dev.netdev) ;
+		return wlan_dev_open(priv->dev) ;
 	return 0;
 }
 
@@ -329,12 +317,12 @@
 {
 	wlan_private *priv = dev->priv;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_NET);
 
-	netif_carrier_off(priv->wlan_dev.netdev);
+	netif_carrier_off(priv->dev);
 	priv->open = 0;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_NET);
 	return 0;
 }
 
@@ -351,7 +339,7 @@
 	priv->mesh_open = 0;
 	netif_stop_queue(priv->mesh_dev);
 	if (priv->infra_open == 0)
-		return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ;
+		return wlan_dev_close(dev);
 	else
 		return 0;
 }
@@ -362,147 +350,38 @@
  *  @param dev     A pointer to net_device structure
  *  @return 	   0
  */
-static int wlan_close(struct net_device *dev) {
+static int wlan_close(struct net_device *dev)
+{
 	wlan_private *priv = (wlan_private *) dev->priv;
 
-	netif_stop_queue(priv->wlan_dev.netdev);
+	netif_stop_queue(dev);
 	priv->infra_open = 0;
 	if (priv->mesh_open == 0)
-		return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ;
+		return wlan_dev_close(dev);
 	else
 		return 0;
 }
 
 
-#ifdef ENABLE_PM
-
-/**
- *  @brief This function is a callback function. it is called by
- *  kernel to enter or exit power saving mode.
- *
- *  @param pmdev   A pointer to pm_dev
- *  @param pmreq   pm_request_t
- *  @param pmdata  A pointer to pmdata
- *  @return 	   0 or -1
- */
-static int wlan_pm_callback(struct pm_dev *pmdev, pm_request_t pmreq,
-			    void *pmdata)
-{
-	wlan_private *priv = wlanpriv;
-	wlan_adapter *adapter = priv->adapter;
-	struct net_device *dev = priv->wlan_dev.netdev;
-
-	lbs_pr_debug(1, "WPRM_PM_CALLBACK: pmreq = %d.\n", pmreq);
-
-	switch (pmreq) {
-	case PM_SUSPEND:
-		lbs_pr_debug(1, "WPRM_PM_CALLBACK: enter PM_SUSPEND.\n");
-
-		/* in associated mode */
-		if (adapter->connect_status == libertas_connected) {
-			if ((adapter->psstate != PS_STATE_SLEEP)
-			    ) {
-				lbs_pr_debug(1,
-				       "wlan_pm_callback: can't enter sleep mode\n");
-				return -1;
-			} else {
-
-				/*
-				 * Detach the network interface
-				 * if the network is running
-				 */
-				if (netif_running(dev)) {
-					netif_device_detach(dev);
-					lbs_pr_debug(1,
-					       "netif_device_detach().\n");
-				}
-				libertas_sbi_suspend(priv);
-			}
-			break;
-		}
-
-		/* in non associated mode */
-
-		/*
-		 * Detach the network interface
-		 * if the network is running
-		 */
-		if (netif_running(dev))
-			netif_device_detach(dev);
-
-		/*
-		 * Storing and restoring of the regs be taken care
-		 * at the driver rest will be done at wlan driver
-		 * this makes driver independent of the card
-		 */
-
-		libertas_sbi_suspend(priv);
-
-		break;
-
-	case PM_RESUME:
-		/* in associated mode */
-		if (adapter->connect_status == libertas_connected) {
-			{
-				/*
-				 * Bring the inteface up first
-				 * This case should not happen still ...
-				 */
-				libertas_sbi_resume(priv);
-
-				/*
-				 * Attach the network interface
-				 * if the network is running
-				 */
-				if (netif_running(dev)) {
-					netif_device_attach(dev);
-					lbs_pr_debug(1,
-					       "after netif_device_attach().\n");
-				}
-				lbs_pr_debug(1,
-				       "After netif attach, in associated mode.\n");
-			}
-			break;
-		}
-
-		/* in non associated mode */
-
-		/*
-		 * Bring the inteface up first
-		 * This case should not happen still ...
-		 */
-
-		libertas_sbi_resume(priv);
-
-		if (netif_running(dev))
-			netif_device_attach(dev);
-
-		lbs_pr_debug(1, "after netif attach, in NON associated mode.\n");
-		break;
-	}
-
-	return 0;
-}
-#endif				/* ENABLE_PM */
-
 static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	int ret = 0;
 	wlan_private *priv = dev->priv;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_NET);
 
-	if (priv->wlan_dev.dnld_sent || priv->adapter->TxLockFlag) {
+	if (priv->dnld_sent || priv->adapter->TxLockFlag) {
 		priv->stats.tx_dropped++;
 		goto done;
 	}
 
-	netif_stop_queue(priv->wlan_dev.netdev);
+	netif_stop_queue(priv->dev);
+	netif_stop_queue(priv->mesh_dev);
 
 	if (libertas_process_tx(priv, skb) == 0)
 		dev->trans_start = jiffies;
 done:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
 	return ret;
 }
 
@@ -513,33 +392,43 @@
 static int mesh_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	wlan_private *priv = dev->priv;
-	ENTER();
-	SET_MESH_FRAME(skb);
-	LEAVE();
+	int ret;
 
-	return wlan_hard_start_xmit(skb, priv->wlan_dev.netdev);
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	SET_MESH_FRAME(skb);
+
+	ret = wlan_hard_start_xmit(skb, priv->dev);
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
 }
 
 /**
  * @brief Mark non-mesh packets and handover them to wlan_hard_start_xmit
  *
  */
-static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) {
-	ENTER();
+static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int ret;
+
+	lbs_deb_enter(LBS_DEB_NET);
+
 	UNSET_MESH_FRAME(skb);
-	LEAVE();
-	return wlan_hard_start_xmit(skb, dev);
+
+	ret = wlan_hard_start_xmit(skb, dev);
+	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+	return ret;
 }
 
 static void wlan_tx_timeout(struct net_device *dev)
 {
 	wlan_private *priv = (wlan_private *) dev->priv;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_TX);
 
-	lbs_pr_err("tx watch dog timeout!\n");
+	lbs_pr_err("tx watch dog timeout\n");
 
-	priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+	priv->dnld_sent = DNLD_RES_RECEIVED;
 	dev->trans_start = jiffies;
 
 	if (priv->adapter->currenttxskb) {
@@ -550,10 +439,12 @@
 			libertas_send_tx_feedback(priv);
 		} else
 			wake_up_interruptible(&priv->mainthread.waitq);
-	} else if (priv->adapter->connect_status == libertas_connected)
-		netif_wake_queue(priv->wlan_dev.netdev);
+	} else if (priv->adapter->connect_status == libertas_connected) {
+		netif_wake_queue(priv->dev);
+		netif_wake_queue(priv->mesh_dev);
+	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_TX);
 }
 
 /**
@@ -576,7 +467,10 @@
 	wlan_adapter *adapter = priv->adapter;
 	struct sockaddr *phwaddr = addr;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_NET);
+
+	/* In case it was called from the mesh device */
+	dev = priv->dev ;
 
 	memset(adapter->current_addr, 0, ETH_ALEN);
 
@@ -591,17 +485,18 @@
 				    cmd_option_waitforrsp, 0, NULL);
 
 	if (ret) {
-		lbs_pr_debug(1, "set mac address failed.\n");
+		lbs_deb_net("set MAC address failed\n");
 		ret = -1;
 		goto done;
 	}
 
 	lbs_dbg_hex("adapter->macaddr:", adapter->current_addr, ETH_ALEN);
 	memcpy(dev->dev_addr, adapter->current_addr, ETH_ALEN);
-	memcpy(((wlan_private *) dev->priv)->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
+	if (priv->mesh_dev)
+		memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
 
 done:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
 	return ret;
 }
 
@@ -626,12 +521,12 @@
 	wlan_adapter *adapter = priv->adapter;
 	int oldpacketfilter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_NET);
 
 	oldpacketfilter = adapter->currentpacketfilter;
 
 	if (dev->flags & IFF_PROMISC) {
-		lbs_pr_debug(1, "enable Promiscuous mode\n");
+		lbs_deb_net("enable promiscuous mode\n");
 		adapter->currentpacketfilter |=
 		    cmd_act_mac_promiscuous_enable;
 		adapter->currentpacketfilter &=
@@ -644,7 +539,7 @@
 
 		if (dev->flags & IFF_ALLMULTI || dev->mc_count >
 		    MRVDRV_MAX_MULTICAST_LIST_SIZE) {
-			lbs_pr_debug(1, "Enabling All Multicast!\n");
+			lbs_deb_net( "enabling all multicast\n");
 			adapter->currentpacketfilter |=
 			    cmd_act_mac_all_multicast_enable;
 			adapter->currentpacketfilter &=
@@ -654,8 +549,8 @@
 			    ~cmd_act_mac_all_multicast_enable;
 
 			if (!dev->mc_count) {
-				lbs_pr_debug(1, "No multicast addresses - "
-				       "disabling multicast!\n");
+				lbs_deb_net("no multicast addresses, "
+				       "disabling multicast\n");
 				adapter->currentpacketfilter &=
 				    ~cmd_act_mac_multicast_enable;
 			} else {
@@ -667,12 +562,12 @@
 				adapter->nr_of_multicastmacaddr =
 				    wlan_copy_multicast_address(adapter, dev);
 
-				lbs_pr_debug(1, "Multicast addresses: %d\n",
+				lbs_deb_net("multicast addresses: %d\n",
 				       dev->mc_count);
 
 				for (i = 0; i < dev->mc_count; i++) {
-					lbs_pr_debug(1, "Multicast address %d:"
-					       "%x %x %x %x %x %x\n", i,
+					lbs_deb_net("Multicast address %d:"
+					       MAC_FMT "\n", i,
 					       adapter->multicastlist[i][0],
 					       adapter->multicastlist[i][1],
 					       adapter->multicastlist[i][2],
@@ -680,7 +575,7 @@
 					       adapter->multicastlist[i][4],
 					       adapter->multicastlist[i][5]);
 				}
-				/* set multicast addresses to firmware */
+				/* send multicast addresses to firmware */
 				libertas_prepare_and_send_command(priv,
 						      cmd_mac_multicast_adr,
 						      cmd_act_set, 0, 0,
@@ -693,13 +588,13 @@
 		libertas_set_mac_packet_filter(priv);
 	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_NET);
 }
 
 /**
- *  @brief This function hanldes the major job in WLAN driver.
- *  it handles the event generated by firmware, rx data received
- *  from firmware and tx data sent from kernel.
+ *  @brief This function handles the major jobs in the WLAN driver.
+ *  It handles all events generated by firmware, RX data received
+ *  from firmware and TX data sent from kernel.
  *
  *  @param data    A pointer to wlan_thread structure
  *  @return 	   0
@@ -712,26 +607,27 @@
 	wait_queue_t wait;
 	u8 ireg = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_THREAD);
 
 	wlan_activate_thread(thread);
 
 	init_waitqueue_entry(&wait, current);
 
+	set_freezable();
 	for (;;) {
-		lbs_pr_debug(1, "main-thread 111: intcounter=%d "
+		lbs_deb_thread( "main-thread 111: intcounter=%d "
 		       "currenttxskb=%p dnld_sent=%d\n",
 		       adapter->intcounter,
-		       adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+		       adapter->currenttxskb, priv->dnld_sent);
 
 		add_wait_queue(&thread->waitq, &wait);
 		set_current_state(TASK_INTERRUPTIBLE);
 		spin_lock_irq(&adapter->driver_lock);
 		if ((adapter->psstate == PS_STATE_SLEEP) ||
 		    (!adapter->intcounter
-		     && (priv->wlan_dev.dnld_sent || adapter->cur_cmd ||
+		     && (priv->dnld_sent || adapter->cur_cmd ||
 			 list_empty(&adapter->cmdpendingq)))) {
-			lbs_pr_debug(1,
+			lbs_deb_thread(
 			       "main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
 			       adapter->connect_status, adapter->intcounter,
 			       adapter->psmode, adapter->psstate);
@@ -741,23 +637,23 @@
 			spin_unlock_irq(&adapter->driver_lock);
 
 
-		lbs_pr_debug(1,
+		lbs_deb_thread(
 		       "main-thread 222 (waking up): intcounter=%d currenttxskb=%p "
 		       "dnld_sent=%d\n", adapter->intcounter,
-		       adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+		       adapter->currenttxskb, priv->dnld_sent);
 
 		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&thread->waitq, &wait);
 		try_to_freeze();
 
-		lbs_pr_debug(1, "main-thread 333: intcounter=%d currenttxskb=%p "
+		lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p "
 		       "dnld_sent=%d\n",
 		       adapter->intcounter,
-		       adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+		       adapter->currenttxskb, priv->dnld_sent);
 
 		if (kthread_should_stop()
 		    || adapter->surpriseremoved) {
-			lbs_pr_debug(1,
+			lbs_deb_thread(
 			       "main-thread: break from main thread: surpriseremoved=0x%x\n",
 			       adapter->surpriseremoved);
 			break;
@@ -768,10 +664,10 @@
 		if (adapter->intcounter) {
 			u8 int_status;
 			adapter->intcounter = 0;
-			int_status = libertas_sbi_get_int_status(priv, &ireg);
+			int_status = priv->hw_get_int_status(priv, &ireg);
 
 			if (int_status) {
-				lbs_pr_debug(1,
+				lbs_deb_thread(
 				       "main-thread: reading HOST_INT_STATUS_REG failed\n");
 				spin_unlock_irq(&adapter->driver_lock);
 				continue;
@@ -779,14 +675,14 @@
 			adapter->hisregcpy |= ireg;
 		}
 
-		lbs_pr_debug(1, "main-thread 444: intcounter=%d currenttxskb=%p "
+		lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p "
 		       "dnld_sent=%d\n",
 		       adapter->intcounter,
-		       adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+		       adapter->currenttxskb, priv->dnld_sent);
 
 		/* command response? */
 		if (adapter->hisregcpy & his_cmdupldrdy) {
-			lbs_pr_debug(1, "main-thread: cmd response ready.\n");
+			lbs_deb_thread("main-thread: cmd response ready\n");
 
 			adapter->hisregcpy &= ~his_cmdupldrdy;
 			spin_unlock_irq(&adapter->driver_lock);
@@ -796,13 +692,13 @@
 
 		/* Any Card Event */
 		if (adapter->hisregcpy & his_cardevent) {
-			lbs_pr_debug(1, "main-thread: Card Event Activity.\n");
+			lbs_deb_thread("main-thread: Card Event Activity\n");
 
 			adapter->hisregcpy &= ~his_cardevent;
 
-			if (libertas_sbi_read_event_cause(priv)) {
+			if (priv->hw_read_event_cause(priv)) {
 				lbs_pr_alert(
-				       "main-thread: libertas_sbi_read_event_cause failed.\n");
+				       "main-thread: hw_read_event_cause failed\n");
 				spin_unlock_irq(&adapter->driver_lock);
 				continue;
 			}
@@ -813,15 +709,15 @@
 
 		/* Check if we need to confirm Sleep Request received previously */
 		if (adapter->psstate == PS_STATE_PRE_SLEEP) {
-			if (!priv->wlan_dev.dnld_sent && !adapter->cur_cmd) {
+			if (!priv->dnld_sent && !adapter->cur_cmd) {
 				if (adapter->connect_status ==
 				    libertas_connected) {
-					lbs_pr_debug(1,
+					lbs_deb_thread(
 					       "main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p "
 					       "dnld_sent=%d cur_cmd=%p, confirm now\n",
 					       adapter->intcounter,
 					       adapter->currenttxskb,
-					       priv->wlan_dev.dnld_sent,
+					       priv->dnld_sent,
 					       adapter->cur_cmd);
 
 					libertas_ps_confirm_sleep(priv,
@@ -847,7 +743,7 @@
 			continue;
 
 		/* Execute the next command */
-		if (!priv->wlan_dev.dnld_sent && !priv->adapter->cur_cmd)
+		if (!priv->dnld_sent && !priv->adapter->cur_cmd)
 			libertas_execute_next_command(priv);
 
 		/* Wake-up command waiters which can't sleep in
@@ -864,7 +760,7 @@
 	wake_up_all(&adapter->cmd_pending);
 	wlan_deactivate_thread(thread);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_THREAD);
 	return 0;
 }
 
@@ -875,166 +771,203 @@
  *  @param card    A pointer to card
  *  @return 	   A pointer to wlan_private structure
  */
-wlan_private *wlan_add_card(void *card)
+wlan_private *libertas_add_card(void *card, struct device *dmdev)
 {
 	struct net_device *dev = NULL;
-	struct net_device *mesh_dev = NULL;
 	wlan_private *priv = NULL;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_NET);
 
 	/* Allocate an Ethernet device and register it */
 	if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
-		lbs_pr_alert( "Init ethernet device failed!\n");
+		lbs_pr_err("init ethX device failed\n");
 		return NULL;
 	}
-
 	priv = dev->priv;
 
 	/* allocate buffer for wlan_adapter */
-	if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
-		lbs_pr_alert( "Allocate buffer for wlan_adapter failed!\n");
-		goto err_kmalloc;
+	if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
+		lbs_pr_err("allocate buffer for wlan_adapter failed\n");
+		goto err_kzalloc;
 	}
 
-	/* Allocate a virtual mesh device */
-	if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
-		lbs_pr_debug(1, "Init ethernet device failed!\n");
-		return NULL;
-	}
-
-	/* Both intervaces share the priv structure */
-	mesh_dev->priv = priv;
-
-	/* init wlan_adapter */
-	memset(priv->adapter, 0, sizeof(wlan_adapter));
-
-	priv->wlan_dev.netdev = dev;
-	priv->wlan_dev.card = card;
+	priv->dev = dev;
+	priv->card = card;
 	priv->mesh_open = 0;
 	priv->infra_open = 0;
-	priv->mesh_dev = mesh_dev;
-	wlanpriv = priv;
 
 	SET_MODULE_OWNER(dev);
-	SET_MODULE_OWNER(mesh_dev);
 
 	/* Setup the OS Interface to our functions */
 	dev->open = wlan_open;
 	dev->hard_start_xmit = wlan_pre_start_xmit;
 	dev->stop = wlan_close;
-	dev->do_ioctl = libertas_do_ioctl;
 	dev->set_mac_address = wlan_set_mac_address;
-	mesh_dev->open = mesh_open;
-	mesh_dev->hard_start_xmit = mesh_pre_start_xmit;
-	mesh_dev->stop = mesh_close;
-	mesh_dev->do_ioctl = libertas_do_ioctl;
-	memcpy(mesh_dev->dev_addr, wlanpriv->wlan_dev.netdev->dev_addr,
-			sizeof(wlanpriv->wlan_dev.netdev->dev_addr));
-
-#define	WLAN_WATCHDOG_TIMEOUT	(5 * HZ)
-
 	dev->tx_timeout = wlan_tx_timeout;
 	dev->get_stats = wlan_get_stats;
-	dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT;
+	dev->watchdog_timeo = 5 * HZ;
 	dev->ethtool_ops = &libertas_ethtool_ops;
-	mesh_dev->get_stats = wlan_get_stats;
-	mesh_dev->ethtool_ops = &libertas_ethtool_ops;
-
 #ifdef	WIRELESS_EXT
 	dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
-	mesh_dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
 #endif
 #define NETIF_F_DYNALLOC 16
 	dev->features |= NETIF_F_DYNALLOC;
 	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
 	dev->set_multicast_list = wlan_set_multicast_list;
 
+	SET_NETDEV_DEV(dev, dmdev);
+
 	INIT_LIST_HEAD(&priv->adapter->cmdfreeq);
 	INIT_LIST_HEAD(&priv->adapter->cmdpendingq);
 
 	spin_lock_init(&priv->adapter->driver_lock);
 	init_waitqueue_head(&priv->adapter->cmd_pending);
 	priv->adapter->nr_cmd_pending = 0;
+	goto done;
 
-	lbs_pr_debug(1, "Starting kthread...\n");
+err_kzalloc:
+	free_netdev(dev);
+	priv = NULL;
+done:
+	lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv);
+	return priv;
+}
+EXPORT_SYMBOL_GPL(libertas_add_card);
+
+int libertas_activate_card(wlan_private *priv, char *fw_name)
+{
+	struct net_device *dev = priv->dev;
+	int ret = -1;
+
+	lbs_deb_enter(LBS_DEB_MAIN);
+
+	lbs_deb_thread("Starting kthread...\n");
 	priv->mainthread.priv = priv;
 	wlan_create_thread(wlan_service_main_thread,
 			   &priv->mainthread, "wlan_main_service");
 
 	priv->assoc_thread =
 		create_singlethread_workqueue("libertas_assoc");
-	INIT_DELAYED_WORK(&priv->assoc_work, wlan_association_worker);
+	INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
+	INIT_WORK(&priv->sync_channel, libertas_sync_channel);
 
 	/*
 	 * Register the device. Fillup the private data structure with
 	 * relevant information from the card and request for the required
 	 * IRQ.
 	 */
-	if (libertas_sbi_register_dev(priv) < 0) {
-		lbs_pr_info("failed to register wlan device!\n");
+	if (priv->hw_register_dev(priv) < 0) {
+		lbs_pr_err("failed to register WLAN device\n");
 		goto err_registerdev;
 	}
 
 	/* init FW and HW */
-	if (libertas_init_fw(priv)) {
-		lbs_pr_debug(1, "Firmware Init failed\n");
+	if (fw_name && libertas_init_fw(priv, fw_name)) {
+		lbs_pr_err("firmware init failed\n");
 		goto err_registerdev;
 	}
 
 	if (register_netdev(dev)) {
-		lbs_pr_err("Cannot register network device!\n");
+		lbs_pr_err("cannot register ethX device\n");
 		goto err_init_fw;
 	}
 
-	/* Register virtual mesh interface */
-	if (register_netdev(mesh_dev)) {
-		lbs_pr_info("Cannot register mesh virtual interface!\n");
-		goto err_init_fw;
-	}
-
-	lbs_pr_info("%s: Marvell Wlan 802.11 adapter ", dev->name);
+	lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
 
 	libertas_debugfs_init_one(priv, dev);
 
-	if (libertas_found == MAX_DEVS)
-		goto err_init_fw;
-	libertas_devs[libertas_found] = dev;
-	libertas_found++;
-#ifdef ENABLE_PM
-	if (!(wlan_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, wlan_pm_callback)))
-		lbs_pr_alert( "failed to register PM callback\n");
-#endif
-	if (device_create_file(&(mesh_dev->dev), &dev_attr_libertas_mpp))
-		goto err_create_file;
+	ret = 0;
+	goto done;
 
-	LEAVE();
-	return priv;
-
-err_create_file:
-	device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp);
 err_init_fw:
-	libertas_sbi_unregister_dev(priv);
+	priv->hw_unregister_dev(priv);
 err_registerdev:
 	destroy_workqueue(priv->assoc_thread);
 	/* Stop the thread servicing the interrupts */
 	wake_up_interruptible(&priv->mainthread.waitq);
 	wlan_terminate_thread(&priv->mainthread);
-	kfree(priv->adapter);
-err_kmalloc:
-	free_netdev(dev);
-	free_netdev(mesh_dev);
-	wlanpriv = NULL;
-
-	LEAVE();
-	return NULL;
+done:
+	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+	return ret;
 }
+EXPORT_SYMBOL_GPL(libertas_activate_card);
+
+
+/**
+ * @brief This function adds mshX interface
+ *
+ *  @param priv    A pointer to the wlan_private structure
+ *  @return 	   0 if successful, -X otherwise
+ */
+int libertas_add_mesh(wlan_private *priv, struct device *dev)
+{
+	struct net_device *mesh_dev = NULL;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	/* Allocate a virtual mesh device */
+	if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
+		lbs_deb_mesh("init mshX device failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	mesh_dev->priv = priv;
+	priv->mesh_dev = mesh_dev;
+
+	SET_MODULE_OWNER(mesh_dev);
+
+	mesh_dev->open = mesh_open;
+	mesh_dev->hard_start_xmit = mesh_pre_start_xmit;
+	mesh_dev->stop = mesh_close;
+	mesh_dev->get_stats = wlan_get_stats;
+	mesh_dev->set_mac_address = wlan_set_mac_address;
+	mesh_dev->ethtool_ops = &libertas_ethtool_ops;
+	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
+			sizeof(priv->dev->dev_addr));
+
+	SET_NETDEV_DEV(priv->mesh_dev, dev);
+
+#ifdef	WIRELESS_EXT
+	mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
+#endif
+#define NETIF_F_DYNALLOC 16
+
+	/* Register virtual mesh interface */
+	ret = register_netdev(mesh_dev);
+	if (ret) {
+		lbs_pr_err("cannot register mshX virtual interface\n");
+		goto err_free;
+	}
+
+	ret = device_create_file(&(mesh_dev->dev), &dev_attr_anycast_mask);
+	if (ret)
+		goto err_unregister;
+
+	/* Everything successful */
+	ret = 0;
+	goto done;
+
+
+err_unregister:
+	unregister_netdev(mesh_dev);
+
+err_free:
+	free_netdev(mesh_dev);
+
+done:
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(libertas_add_mesh);
 
 static void wake_pending_cmdnodes(wlan_private *priv)
 {
 	struct cmd_ctrl_node *cmdnode;
 	unsigned long flags;
 
+	lbs_deb_enter(LBS_DEB_CMD);
+
 	spin_lock_irqsave(&priv->adapter->driver_lock, flags);
 	list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {
 		cmdnode->cmdwaitqwoken = 1;
@@ -1044,40 +977,29 @@
 }
 
 
-int wlan_remove_card(void *card)
+int libertas_remove_card(wlan_private *priv)
 {
-	wlan_private *priv = libertas_sbi_get_priv(card);
 	wlan_adapter *adapter;
 	struct net_device *dev;
-	struct net_device *mesh_dev;
 	union iwreq_data wrqu;
-	int i;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_NET);
 
-	if (!priv) {
-		LEAVE();
-		return 0;
-	}
+	if (!priv)
+		goto out;
 
 	adapter = priv->adapter;
 
-	if (!adapter) {
-		LEAVE();
-		return 0;
-	}
+	if (!adapter)
+		goto out;
 
-	dev = priv->wlan_dev.netdev;
-	mesh_dev = priv->mesh_dev;
+	dev = priv->dev;
 
-	netif_stop_queue(mesh_dev);
-	netif_stop_queue(priv->wlan_dev.netdev);
-	netif_carrier_off(priv->wlan_dev.netdev);
+	netif_stop_queue(priv->dev);
+	netif_carrier_off(priv->dev);
 
 	wake_pending_cmdnodes(priv);
 
-	device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp);
-	unregister_netdev(mesh_dev);
 	unregister_netdev(dev);
 
 	cancel_delayed_work(&priv->assoc_work);
@@ -1090,11 +1012,7 @@
 
 	memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
-
-#ifdef ENABLE_PM
-	pm_unregister(wlan_pm_dev);
-#endif
+	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
 
 	adapter->surpriseremoved = 1;
 
@@ -1103,28 +1021,45 @@
 
 	libertas_debugfs_remove_one(priv);
 
-	lbs_pr_debug(1, "Free adapter\n");
+	lbs_deb_net("free adapter\n");
 	libertas_free_adapter(priv);
 
-	for (i = 0; i<libertas_found; i++) {
-		if (libertas_devs[i]==priv->wlan_dev.netdev) {
-			libertas_devs[i] = libertas_devs[--libertas_found];
-			libertas_devs[libertas_found] = NULL ;
-			break ;
-		}
-	}
+	lbs_deb_net("unregister finish\n");
 
-	lbs_pr_debug(1, "Unregister finish\n");
-
-	priv->wlan_dev.netdev = NULL;
-	priv->mesh_dev = NULL ;
-	free_netdev(mesh_dev);
+	priv->dev = NULL;
 	free_netdev(dev);
-	wlanpriv = NULL;
 
-	LEAVE();
+out:
+	lbs_deb_leave(LBS_DEB_NET);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(libertas_remove_card);
+
+
+void libertas_remove_mesh(wlan_private *priv)
+{
+	struct net_device *mesh_dev;
+
+	lbs_deb_enter(LBS_DEB_NET);
+
+	if (!priv)
+		goto out;
+
+	mesh_dev = priv->mesh_dev;
+
+	netif_stop_queue(mesh_dev);
+	netif_carrier_off(priv->mesh_dev);
+
+	device_remove_file(&(mesh_dev->dev), &dev_attr_anycast_mask);
+	unregister_netdev(mesh_dev);
+
+	priv->mesh_dev = NULL ;
+	free_netdev(mesh_dev);
+
+out:
+	lbs_deb_leave(LBS_DEB_NET);
+}
+EXPORT_SYMBOL_GPL(libertas_remove_mesh);
 
 /**
  *  @brief This function finds the CFP in
@@ -1139,33 +1074,34 @@
 {
 	int i, end;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_MAIN);
 
 	end = sizeof(region_cfp_table)/sizeof(struct region_cfp_table);
 
 	for (i = 0; i < end ; i++) {
-		lbs_pr_debug(1, "region_cfp_table[i].region=%d\n",
+		lbs_deb_main("region_cfp_table[i].region=%d\n",
 			region_cfp_table[i].region);
 		if (region_cfp_table[i].region == region) {
 			*cfp_no = region_cfp_table[i].cfp_no_BG;
-			LEAVE();
+			lbs_deb_leave(LBS_DEB_MAIN);
 			return region_cfp_table[i].cfp_BG;
 		}
 	}
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
 	return NULL;
 }
 
 int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band)
 {
 	wlan_adapter *adapter = priv->adapter;
+	int ret = 0;
 	int i = 0;
 
 	struct chan_freq_power *cfp;
 	int cfp_no;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_MAIN);
 
 	memset(adapter->region_channel, 0, sizeof(adapter->region_channel));
 
@@ -1175,17 +1111,19 @@
 			adapter->region_channel[i].nrcfp = cfp_no;
 			adapter->region_channel[i].CFP = cfp;
 		} else {
-			lbs_pr_debug(1, "wrong region code %#x in band B-G\n",
+			lbs_deb_main("wrong region code %#x in band B/G\n",
 			       region);
-			return -1;
+			ret = -1;
+			goto out;
 		}
 		adapter->region_channel[i].valid = 1;
 		adapter->region_channel[i].region = region;
 		adapter->region_channel[i].band = band;
 		i++;
 	}
-	LEAVE();
-	return 0;
+out:
+	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+	return ret;
 }
 
 /**
@@ -1200,9 +1138,9 @@
 {
 	wlan_private *priv = dev->priv;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_THREAD);
 
-	lbs_pr_debug(1, "libertas_interrupt: intcounter=%d\n",
+	lbs_deb_thread("libertas_interrupt: intcounter=%d\n",
 	       priv->adapter->intcounter);
 
 	priv->adapter->intcounter++;
@@ -1210,56 +1148,35 @@
 	if (priv->adapter->psstate == PS_STATE_SLEEP) {
 		priv->adapter->psstate = PS_STATE_AWAKE;
 		netif_wake_queue(dev);
+		netif_wake_queue(priv->mesh_dev);
 	}
 
 	wake_up_interruptible(&priv->mainthread.waitq);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_THREAD);
 }
+EXPORT_SYMBOL_GPL(libertas_interrupt);
 
-static int wlan_init_module(void)
+static int libertas_init_module(void)
 {
-	int ret = 0;
-
-	ENTER();
-
-	if (libertas_fw_name == NULL) {
-		libertas_fw_name = default_fw_name;
-	}
-
+	lbs_deb_enter(LBS_DEB_MAIN);
 	libertas_debugfs_init();
-
-	if (libertas_sbi_register()) {
-		ret = -1;
-		libertas_debugfs_remove();
-		goto done;
-	}
-
-done:
-	LEAVE();
-	return ret;
+	lbs_deb_leave(LBS_DEB_MAIN);
+	return 0;
 }
 
-static void wlan_cleanup_module(void)
+static void libertas_exit_module(void)
 {
-	int i;
+	lbs_deb_enter(LBS_DEB_MAIN);
 
-	ENTER();
-
-	for (i = 0; i<libertas_found; i++) {
-		wlan_private *priv = libertas_devs[i]->priv;
-		reset_device(priv);
-	}
-
-	libertas_sbi_unregister();
 	libertas_debugfs_remove();
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_MAIN);
 }
 
-module_init(wlan_init_module);
-module_exit(wlan_cleanup_module);
+module_init(libertas_init_module);
+module_exit(libertas_exit_module);
 
-MODULE_DESCRIPTION("M-WLAN Driver");
+MODULE_DESCRIPTION("Libertas WLAN Driver Library");
 MODULE_AUTHOR("Marvell International Ltd.");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index d17924f..769c86f 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -106,10 +106,10 @@
 {
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_RX);
 
-	lbs_pr_debug(1, "rxpd: SNR = %d, NF = %d\n", p_rx_pd->snr, p_rx_pd->nf);
-	lbs_pr_debug(1, "Before computing SNR: SNR- avg = %d, NF-avg = %d\n",
+	lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
+	lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
 	       adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
 	       adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
 
@@ -121,7 +121,7 @@
 
 	adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getavgsnr(priv) * AVG_SCALE;
 	adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getavgnf(priv) * AVG_SCALE;
-	lbs_pr_debug(1, "After computing SNR: SNR-avg = %d, NF-avg = %d\n",
+	lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
 	       adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
 	       adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
 
@@ -133,23 +133,20 @@
 	    CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
 		     adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_RX);
 }
 
-int libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
+void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
 {
-	lbs_pr_debug(1, "skb->data=%p\n", skb->data);
+	lbs_deb_rx("skb->data %p\n", skb->data);
 
-	if(IS_MESH_FRAME(skb))
-		skb->dev = priv->mesh_dev;
+	if (priv->mesh_dev && IS_MESH_FRAME(skb))
+		skb->protocol = eth_type_trans(skb, priv->mesh_dev);
 	else
-		skb->dev = priv->wlan_dev.netdev;
-	skb->protocol = eth_type_trans(skb, priv->wlan_dev.netdev);
+		skb->protocol = eth_type_trans(skb, priv->dev);
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 	netif_rx(skb);
-
-	return 0;
 }
 
 /**
@@ -173,7 +170,7 @@
 
 	const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_RX);
 
 	if (priv->adapter->debugmode & MRVDRV_DEBUG_RX_PATH)
 		lbs_dbg_hex("RX packet: ", skb->data,
@@ -193,7 +190,7 @@
 		 min_t(unsigned int, skb->len, 100));
 
 	if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
-		lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n");
+		lbs_deb_rx("rx err: frame received with bad length\n");
 		priv->stats.rx_length_errors++;
 		ret = 0;
 		goto done;
@@ -202,15 +199,15 @@
 	/*
 	 * Check rxpd status and update 802.3 stat,
 	 */
-	if (!(p_rx_pd->status & MRVDRV_RXPD_STATUS_OK)) {
-		lbs_pr_debug(1, "RX error: frame received with bad status\n");
-		lbs_pr_alert("rxpd Not OK\n");
+	if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
+		lbs_deb_rx("rx err: frame received with bad status\n");
+		lbs_pr_alert("rxpd not ok\n");
 		priv->stats.rx_errors++;
 		ret = 0;
 		goto done;
 	}
 
-	lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %zd = %zd\n",
+	lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
 	       skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
 
 	lbs_dbg_hex("RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
@@ -268,22 +265,18 @@
 
 	wlan_compute_rssi(priv, p_rx_pd);
 
-	lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len);
-	if (libertas_upload_rx_packet(priv, skb)) {
-		lbs_pr_debug(1, "RX error: libertas_upload_rx_packet"
-		       " returns failure\n");
-		ret = -1;
-		goto done;
-	}
+	lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
 	priv->stats.rx_bytes += skb->len;
 	priv->stats.rx_packets++;
 
+	libertas_upload_rx_packet(priv, skb);
+
 	ret = 0;
 done:
-	LEAVE();
-
+	lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(libertas_process_rxed_packet);
 
 /**
  *  @brief This function converts Tx/Rx rates from the Marvell WLAN format
@@ -320,7 +313,7 @@
 	case 11:		/*  54 Mbps */
 		return 108;
 	}
-	lbs_pr_alert( "Invalid Marvell WLAN rate (%i)\n", rate);
+	lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate);
 	return 0;
 }
 
@@ -342,7 +335,7 @@
 	struct rx_radiotap_hdr radiotap_hdr;
 	struct rx_radiotap_hdr *pradiotap_hdr;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_RX);
 
 	p_rx_pkt = (struct rx80211packethdr *) skb->data;
 	prxpd = &p_rx_pkt->rx_pd;
@@ -350,7 +343,7 @@
 	// lbs_dbg_hex("RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
 
 	if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
-		lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n");
+		lbs_deb_rx("rx err: frame received wit bad length\n");
 		priv->stats.rx_length_errors++;
 		ret = 0;
 		goto done;
@@ -359,12 +352,12 @@
 	/*
 	 * Check rxpd status and update 802.3 stat,
 	 */
-	if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK)) {
-		//lbs_pr_debug(1, "RX error: frame received with bad status\n");
+	if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
+		//lbs_deb_rx("rx err: frame received with bad status\n");
 		priv->stats.rx_errors++;
 	}
 
-	lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %zd = %zd\n",
+	lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
 	       skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
 
 	/* create the exported radio header */
@@ -392,7 +385,7 @@
 		/* XXX must check no carryout */
 		radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
 		radiotap_hdr.rx_flags = 0;
-		if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK))
+		if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
 			radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
 		//memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);
 
@@ -405,7 +398,7 @@
 		if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
 		    pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0,
 				     GFP_ATOMIC)) {
-			lbs_pr_alert( "%s: couldn't pskb_expand_head\n",
+			lbs_pr_alert("%s: couldn't pskb_expand_head\n",
 			       __func__);
 		}
 
@@ -420,7 +413,7 @@
 
 	default:
 		/* unknown header */
-		lbs_pr_alert( "Unknown radiomode (%i)\n",
+		lbs_pr_alert("Unknown radiomode %i\n",
 		       priv->adapter->radiomode);
 		/* don't export any header */
 		/* chop the rxpd */
@@ -437,23 +430,15 @@
 
 	wlan_compute_rssi(priv, prxpd);
 
-	lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len);
-
-	if (libertas_upload_rx_packet(priv, skb)) {
-		lbs_pr_debug(1, "RX error: libertas_upload_rx_packet "
-			"returns failure\n");
-		ret = -1;
-		goto done;
-	}
-
+	lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
 	priv->stats.rx_bytes += skb->len;
 	priv->stats.rx_packets++;
 
+	libertas_upload_rx_packet(priv, skb);
+
 	ret = 0;
+
 done:
-	LEAVE();
-
-	skb->protocol = __constant_htons(0x0019);	/* ETH_P_80211_RAW */
-
-	return (ret);
+	lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
+	return ret;
 }
diff --git a/drivers/net/wireless/libertas/sbi.h b/drivers/net/wireless/libertas/sbi.h
deleted file mode 100644
index 59d3a59c..0000000
--- a/drivers/net/wireless/libertas/sbi.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
-  * This file contains IF layer definitions.
-  */
-
-#ifndef	_SBI_H_
-#define	_SBI_H_
-
-#include <linux/interrupt.h>
-
-#include "defs.h"
-
-/** INT status Bit Definition*/
-#define his_cmddnldrdy			0x01
-#define his_cardevent			0x02
-#define his_cmdupldrdy			0x04
-
-#ifndef DEV_NAME_LEN
-#define DEV_NAME_LEN			32
-#endif
-
-#define SBI_EVENT_CAUSE_SHIFT		3
-
-/* Probe and Check if the card is present*/
-int libertas_sbi_register_dev(wlan_private * priv);
-int libertas_sbi_unregister_dev(wlan_private *);
-int libertas_sbi_get_int_status(wlan_private * priv, u8 *);
-int libertas_sbi_register(void);
-void libertas_sbi_unregister(void);
-int libertas_sbi_prog_firmware(wlan_private *);
-
-int libertas_sbi_read_event_cause(wlan_private *);
-int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
-wlan_private *libertas_sbi_get_priv(void *card);
-
-#ifdef ENABLE_PM
-int libertas_sbi_suspend(wlan_private *);
-int libertas_sbi_resume(wlan_private *);
-#endif
-
-#endif				/* _SBI_H */
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 3c0b1a2..c3043dc 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -8,6 +8,7 @@
 #include <linux/if.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
+#include <linux/etherdevice.h>
 
 #include <net/ieee80211.h>
 #include <net/iw_handler.h>
@@ -58,12 +59,82 @@
 //! Scan time specified in the channel TLV for each channel for active scans
 #define MRVDRV_ACTIVE_SCAN_CHAN_TIME   100
 
-//! Macro to enable/disable SSID checking before storing a scan table
-#ifdef DISCARD_BAD_SSID
-#define CHECK_SSID_IS_VALID(x) ssid_valid(&bssidEntry.ssid)
-#else
-#define CHECK_SSID_IS_VALID(x) 1
-#endif
+static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+static inline void clear_bss_descriptor (struct bss_descriptor * bss)
+{
+	/* Don't blow away ->list, just BSS data */
+	memset(bss, 0, offsetof(struct bss_descriptor, list));
+}
+
+static inline int match_bss_no_security(struct wlan_802_11_security * secinfo,
+			struct bss_descriptor * match_bss)
+{
+	if (   !secinfo->wep_enabled
+	    && !secinfo->WPAenabled
+	    && !secinfo->WPA2enabled
+	    && match_bss->wpa_ie[0] != WPA_IE
+	    && match_bss->rsn_ie[0] != WPA2_IE
+	    && !match_bss->privacy) {
+		return 1;
+	}
+	return 0;
+}
+
+static inline int match_bss_static_wep(struct wlan_802_11_security * secinfo,
+			struct bss_descriptor * match_bss)
+{
+	if ( secinfo->wep_enabled
+	   && !secinfo->WPAenabled
+	   && !secinfo->WPA2enabled
+	   && match_bss->privacy) {
+		return 1;
+	}
+	return 0;
+}
+
+static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
+			struct bss_descriptor * match_bss)
+{
+	if (  !secinfo->wep_enabled
+	   && secinfo->WPAenabled
+	   && (match_bss->wpa_ie[0] == WPA_IE)
+	   /* privacy bit may NOT be set in some APs like LinkSys WRT54G
+	      && bss->privacy */
+	   ) {
+		return 1;
+	}
+	return 0;
+}
+
+static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
+			struct bss_descriptor * match_bss)
+{
+	if (  !secinfo->wep_enabled
+	   && secinfo->WPA2enabled
+	   && (match_bss->rsn_ie[0] == WPA2_IE)
+	   /* privacy bit may NOT be set in some APs like LinkSys WRT54G
+	      && bss->privacy */
+	   ) {
+		return 1;
+	}
+	return 0;
+}
+
+static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,
+			struct bss_descriptor * match_bss)
+{
+	if (  !secinfo->wep_enabled
+	   && !secinfo->WPAenabled
+	   && !secinfo->WPA2enabled
+	   && (match_bss->wpa_ie[0] != WPA_IE)
+	   && (match_bss->rsn_ie[0] != WPA2_IE)
+	   && match_bss->privacy) {
+		return 1;
+	}
+	return 0;
+}
 
 /**
  *  @brief Check if a scanned network compatible with the driver settings
@@ -84,180 +155,63 @@
  *
  *  @return        Index in scantable, or error code if negative
  */
-static int is_network_compatible(wlan_adapter * adapter, int index, u8 mode)
+static int is_network_compatible(wlan_adapter * adapter,
+		struct bss_descriptor * bss, u8 mode)
 {
-	ENTER();
+	int matched = 0;
 
-	if (adapter->scantable[index].mode == mode) {
-		if (   !adapter->secinfo.wep_enabled
-		    && !adapter->secinfo.WPAenabled
-		    && !adapter->secinfo.WPA2enabled
-		    && adapter->scantable[index].wpa_ie[0] != WPA_IE
-		    && adapter->scantable[index].rsn_ie[0] != WPA2_IE
-		    && !adapter->scantable[index].privacy) {
-			/* no security */
-			LEAVE();
-			return index;
-		} else if (   adapter->secinfo.wep_enabled
-			   && !adapter->secinfo.WPAenabled
-			   && !adapter->secinfo.WPA2enabled
-			   && adapter->scantable[index].privacy) {
-			/* static WEP enabled */
-			LEAVE();
-			return index;
-		} else if (   !adapter->secinfo.wep_enabled
-			   && adapter->secinfo.WPAenabled
-			   && !adapter->secinfo.WPA2enabled
-			   && (adapter->scantable[index].wpa_ie[0] == WPA_IE)
-			   /* privacy bit may NOT be set in some APs like LinkSys WRT54G
-			      && adapter->scantable[index].privacy */
-		    ) {
-			/* WPA enabled */
-			lbs_pr_debug(1,
-			       "is_network_compatible() WPA: index=%d wpa_ie=%#x "
-			       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
-			       "privacy=%#x\n", index,
-			       adapter->scantable[index].wpa_ie[0],
-			       adapter->scantable[index].rsn_ie[0],
-			       adapter->secinfo.wep_enabled ? "e" : "d",
-			       adapter->secinfo.WPAenabled ? "e" : "d",
-			       adapter->secinfo.WPA2enabled ? "e" : "d",
-			       adapter->scantable[index].privacy);
-			LEAVE();
-			return index;
-		} else if (   !adapter->secinfo.wep_enabled
-			   && !adapter->secinfo.WPAenabled
-			   && adapter->secinfo.WPA2enabled
-			   && (adapter->scantable[index].rsn_ie[0] == WPA2_IE)
-			   /* privacy bit may NOT be set in some APs like LinkSys WRT54G
-			      && adapter->scantable[index].privacy */
-		    ) {
-			/* WPA2 enabled */
-			lbs_pr_debug(1,
-			       "is_network_compatible() WPA2: index=%d wpa_ie=%#x "
-			       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
-			       "privacy=%#x\n", index,
-			       adapter->scantable[index].wpa_ie[0],
-			       adapter->scantable[index].rsn_ie[0],
-			       adapter->secinfo.wep_enabled ? "e" : "d",
-			       adapter->secinfo.WPAenabled ? "e" : "d",
-			       adapter->secinfo.WPA2enabled ? "e" : "d",
-			       adapter->scantable[index].privacy);
-			LEAVE();
-			return index;
-		} else if (   !adapter->secinfo.wep_enabled
-			   && !adapter->secinfo.WPAenabled
-			   && !adapter->secinfo.WPA2enabled
-			   && (adapter->scantable[index].wpa_ie[0] != WPA_IE)
-			   && (adapter->scantable[index].rsn_ie[0] != WPA2_IE)
-			   && adapter->scantable[index].privacy) {
-			/* dynamic WEP enabled */
-			lbs_pr_debug(1,
-			       "is_network_compatible() dynamic WEP: index=%d "
-			       "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n",
-			       index,
-			       adapter->scantable[index].wpa_ie[0],
-			       adapter->scantable[index].rsn_ie[0],
-			       adapter->scantable[index].privacy);
-			LEAVE();
-			return index;
-		}
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
-		/* security doesn't match */
-		lbs_pr_debug(1,
-		       "is_network_compatible() FAILED: index=%d wpa_ie=%#x "
-		       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n",
-		       index,
-		       adapter->scantable[index].wpa_ie[0],
-		       adapter->scantable[index].rsn_ie[0],
+	if (bss->mode != mode)
+		goto done;
+
+	if ((matched = match_bss_no_security(&adapter->secinfo, bss))) {
+		goto done;
+	} else if ((matched = match_bss_static_wep(&adapter->secinfo, bss))) {
+		goto done;
+	} else if ((matched = match_bss_wpa(&adapter->secinfo, bss))) {
+		lbs_deb_scan(
+		       "is_network_compatible() WPA: wpa_ie=%#x "
+		       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
+		       "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0],
 		       adapter->secinfo.wep_enabled ? "e" : "d",
 		       adapter->secinfo.WPAenabled ? "e" : "d",
 		       adapter->secinfo.WPA2enabled ? "e" : "d",
-		       adapter->scantable[index].privacy);
-		LEAVE();
-		return -ECONNREFUSED;
+		       bss->privacy);
+		goto done;
+	} else if ((matched = match_bss_wpa2(&adapter->secinfo, bss))) {
+		lbs_deb_scan(
+		       "is_network_compatible() WPA2: wpa_ie=%#x "
+		       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
+		       "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0],
+		       adapter->secinfo.wep_enabled ? "e" : "d",
+		       adapter->secinfo.WPAenabled ? "e" : "d",
+		       adapter->secinfo.WPA2enabled ? "e" : "d",
+		       bss->privacy);
+		goto done;
+	} else if ((matched = match_bss_dynamic_wep(&adapter->secinfo, bss))) {
+		lbs_deb_scan(
+		       "is_network_compatible() dynamic WEP: "
+		       "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n",
+		       bss->wpa_ie[0],
+		       bss->rsn_ie[0],
+		       bss->privacy);
+		goto done;
 	}
 
-	/* mode doesn't match */
-	LEAVE();
-	return -ENETUNREACH;
-}
+	/* bss security settings don't match those configured on card */
+	lbs_deb_scan(
+	       "is_network_compatible() FAILED: wpa_ie=%#x "
+	       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n",
+	       bss->wpa_ie[0], bss->rsn_ie[0],
+	       adapter->secinfo.wep_enabled ? "e" : "d",
+	       adapter->secinfo.WPAenabled ? "e" : "d",
+	       adapter->secinfo.WPA2enabled ? "e" : "d",
+	       bss->privacy);
 
-/**
- *  @brief This function validates a SSID as being able to be printed
- *
- *  @param pssid   SSID structure to validate
- *
- *  @return        TRUE or FALSE
- */
-static u8 ssid_valid(struct WLAN_802_11_SSID *pssid)
-{
-	int ssididx;
-
-	for (ssididx = 0; ssididx < pssid->ssidlength; ssididx++) {
-		if (!isprint(pssid->ssid[ssididx])) {
-			return 0;
-		}
-	}
-
-	return 1;
-}
-
-/**
- *  @brief Post process the scan table after a new scan command has completed
- *
- *  Inspect each entry of the scan table and try to find an entry that
- *    matches our current associated/joined network from the scan.  If
- *    one is found, update the stored copy of the bssdescriptor for our
- *    current network.
- *
- *  Debug dump the current scan table contents if compiled accordingly.
- *
- *  @param priv   A pointer to wlan_private structure
- *
- *  @return       void
- */
-static void wlan_scan_process_results(wlan_private * priv)
-{
-	wlan_adapter *adapter = priv->adapter;
-	int foundcurrent;
-	int i;
-
-	foundcurrent = 0;
-
-	if (adapter->connect_status == libertas_connected) {
-		/* try to find the current BSSID in the new scan list */
-		for (i = 0; i < adapter->numinscantable; i++) {
-			if (!libertas_SSID_cmp(&adapter->scantable[i].ssid,
-				     &adapter->curbssparams.ssid) &&
-			    !memcmp(adapter->curbssparams.bssid,
-				    adapter->scantable[i].macaddress,
-				    ETH_ALEN)) {
-				foundcurrent = 1;
-			}
-		}
-
-		if (foundcurrent) {
-			/* Make a copy of current BSSID descriptor */
-			memcpy(&adapter->curbssparams.bssdescriptor,
-			       &adapter->scantable[i],
-			       sizeof(adapter->curbssparams.bssdescriptor));
-		}
-	}
-
-	for (i = 0; i < adapter->numinscantable; i++) {
-		lbs_pr_debug(1, "Scan:(%02d) %02x:%02x:%02x:%02x:%02x:%02x, "
-		       "RSSI[%03d], SSID[%s]\n",
-		       i,
-		       adapter->scantable[i].macaddress[0],
-		       adapter->scantable[i].macaddress[1],
-		       adapter->scantable[i].macaddress[2],
-		       adapter->scantable[i].macaddress[3],
-		       adapter->scantable[i].macaddress[4],
-		       adapter->scantable[i].macaddress[5],
-		       (s32) adapter->scantable[i].rssi,
-		       adapter->scantable[i].ssid.ssid);
-	}
+done:
+	lbs_deb_leave(LBS_DEB_SCAN);
+	return matched;
 }
 
 /**
@@ -338,14 +292,12 @@
 
 			if (scantype == cmd_scan_type_passive) {
 				scanchanlist[chanidx].maxscantime =
-				    cpu_to_le16
-				    (MRVDRV_PASSIVE_SCAN_CHAN_TIME);
+				    cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
 				scanchanlist[chanidx].chanscanmode.passivescan =
 				    1;
 			} else {
 				scanchanlist[chanidx].maxscantime =
-				    cpu_to_le16
-				    (MRVDRV_ACTIVE_SCAN_CHAN_TIME);
+				    cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
 				scanchanlist[chanidx].chanscanmode.passivescan =
 				    0;
 			}
@@ -408,13 +360,11 @@
 			    u8 * pscancurrentonly)
 {
 	wlan_adapter *adapter = priv->adapter;
-	const u8 zeromac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
 	struct mrvlietypes_numprobes *pnumprobestlv;
 	struct mrvlietypes_ssidparamset *pssidtlv;
 	struct wlan_scan_cmd_config * pscancfgout = NULL;
 	u8 *ptlvpos;
 	u16 numprobes;
-	u16 ssidlen;
 	int chanidx;
 	int scantype;
 	int scandur;
@@ -471,21 +421,18 @@
 		 * Set the BSSID filter to the incoming configuration,
 		 *   if non-zero.  If not set, it will remain disabled (all zeros).
 		 */
-		memcpy(pscancfgout->specificBSSID,
-		       puserscanin->specificBSSID,
-		       sizeof(pscancfgout->specificBSSID));
+		memcpy(pscancfgout->bssid, puserscanin->bssid,
+		       sizeof(pscancfgout->bssid));
 
-		ssidlen = strlen(puserscanin->specificSSID);
-
-		if (ssidlen) {
+		if (puserscanin->ssid_len) {
 			pssidtlv =
 			    (struct mrvlietypes_ssidparamset *) pscancfgout->
 			    tlvbuffer;
 			pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
-			pssidtlv->header.len = cpu_to_le16(ssidlen);
-			memcpy(pssidtlv->ssid, puserscanin->specificSSID,
-			       ssidlen);
-			ptlvpos += sizeof(pssidtlv->header) + ssidlen;
+			pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len);
+			memcpy(pssidtlv->ssid, puserscanin->ssid,
+			       puserscanin->ssid_len);
+			ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len;
 		}
 
 		/*
@@ -494,8 +441,8 @@
 		 *    scan results.  That is not an issue with an SSID or BSSID
 		 *    filter applied to the scan results in the firmware.
 		 */
-		if (ssidlen || (memcmp(pscancfgout->specificBSSID,
-				       &zeromac, sizeof(zeromac)) != 0)) {
+		if (   puserscanin->ssid_len
+		    || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) {
 			*pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN;
 			*pfilteredscan = 1;
 		}
@@ -507,16 +454,11 @@
 	/* If the input config or adapter has the number of Probes set, add tlv */
 	if (numprobes) {
 		pnumprobestlv = (struct mrvlietypes_numprobes *) ptlvpos;
-		pnumprobestlv->header.type =
-		    cpu_to_le16(TLV_TYPE_NUMPROBES);
-		pnumprobestlv->header.len = sizeof(pnumprobestlv->numprobes);
+		pnumprobestlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
+		pnumprobestlv->header.len = cpu_to_le16(2);
 		pnumprobestlv->numprobes = cpu_to_le16(numprobes);
 
-		ptlvpos +=
-		    sizeof(pnumprobestlv->header) + pnumprobestlv->header.len;
-
-		pnumprobestlv->header.len =
-		    cpu_to_le16(pnumprobestlv->header.len);
+		ptlvpos += sizeof(*pnumprobestlv);
 	}
 
 	/*
@@ -529,7 +471,7 @@
 
 	if (puserscanin && puserscanin->chanlist[0].channumber) {
 
-		lbs_pr_debug(1, "Scan: Using supplied channel list\n");
+		lbs_deb_scan("Scan: Using supplied channel list\n");
 
 		for (chanidx = 0;
 		     chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX
@@ -573,11 +515,11 @@
 				       ==
 				       priv->adapter->curbssparams.channel)) {
 			*pscancurrentonly = 1;
-			lbs_pr_debug(1, "Scan: Scanning current channel only");
+			lbs_deb_scan("Scan: Scanning current channel only");
 		}
 
 	} else {
-		lbs_pr_debug(1, "Scan: Creating full region channel list\n");
+		lbs_deb_scan("Scan: Creating full region channel list\n");
 		wlan_scan_create_channel_list(priv, pscanchanlist,
 					      *pfilteredscan);
 	}
@@ -613,7 +555,9 @@
 				  u8 filteredscan,
 				  struct wlan_scan_cmd_config * pscancfgout,
 				  struct mrvlietypes_chanlistparamset * pchantlvout,
-				  struct chanscanparamset * pscanchanlist)
+				  struct chanscanparamset * pscanchanlist,
+				  const struct wlan_ioctl_user_scan_cfg * puserscanin,
+				  int full_scan)
 {
 	struct chanscanparamset *ptmpchan;
 	struct chanscanparamset *pstartchan;
@@ -621,11 +565,13 @@
 	int doneearly;
 	int tlvidx;
 	int ret = 0;
+	int scanned = 0;
+	union iwreq_data wrqu;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	if (pscancfgout == 0 || pchantlvout == 0 || pscanchanlist == 0) {
-		lbs_pr_debug(1, "Scan: Null detect: %p, %p, %p\n",
+		lbs_deb_scan("Scan: Null detect: %p, %p, %p\n",
 		       pscancfgout, pchantlvout, pscanchanlist);
 		return -1;
 	}
@@ -635,6 +581,9 @@
 	/* Set the temp channel struct pointer to the start of the desired list */
 	ptmpchan = pscanchanlist;
 
+	if (priv->adapter->last_scanned_channel && !puserscanin)
+		ptmpchan += priv->adapter->last_scanned_channel;
+
 	/* Loop through the desired channel list, sending a new firmware scan
 	 *   commands for each maxchanperscan channels (or for 1,6,11 individually
 	 *   if configured accordingly)
@@ -654,9 +603,9 @@
 		 *    - doneearly is set (controlling individual scanning of 1,6,11)
 		 */
 		while (tlvidx < maxchanperscan && ptmpchan->channumber
-		       && !doneearly) {
+		       && !doneearly && scanned < 2) {
 
-            lbs_pr_debug(1,
+            lbs_deb_scan(
                     "Scan: Chan(%3d), Radio(%d), mode(%d,%d), Dur(%d)\n",
                 ptmpchan->channumber, ptmpchan->radiotype,
                 ptmpchan->chanscanmode.passivescan,
@@ -668,8 +617,11 @@
 			       ptmpchan, sizeof(pchantlvout->chanscanparam));
 
 			/* Increment the TLV header length by the size appended */
-			pchantlvout->header.len +=
-			    sizeof(pchantlvout->chanscanparam);
+			/* Ew, it would be _so_ nice if we could just declare the
+			   variable little-endian and let GCC handle it for us */
+			pchantlvout->header.len =
+				cpu_to_le16(le16_to_cpu(pchantlvout->header.len) +
+					    sizeof(pchantlvout->chanscanparam));
 
 			/*
 			 *  The tlv buffer length is set to the number of bytes of the
@@ -683,7 +635,7 @@
 			/*  Add the size of the channel tlv header and the data length */
 			pscancfgout->tlvbufferlen +=
 			    (sizeof(pchantlvout->header)
-			     + pchantlvout->header.len);
+			     + le16_to_cpu(pchantlvout->header.len));
 
 			/* Increment the index to the channel tlv we are constructing */
 			tlvidx++;
@@ -701,6 +653,7 @@
 
 			/* Increment the tmp pointer to the next channel to be scanned */
 			ptmpchan++;
+			scanned++;
 
 			/* Stop the loop if the *next* channel is in the 1,6,11 set.
 			 *  This will cause it to be the only channel scanned on the next
@@ -716,12 +669,71 @@
 		/* Send the scan command to the firmware with the specified cfg */
 		ret = libertas_prepare_and_send_command(priv, cmd_802_11_scan, 0,
 					    0, 0, pscancfgout);
+		if (scanned >= 2 && !full_scan) {
+			ret = 0;
+			goto done;
+		}
+		scanned = 0;
 	}
 
-	LEAVE();
+done:
+	priv->adapter->last_scanned_channel = ptmpchan->channumber;
+
+	/* Tell userspace the scan table has been updated */
+	memset(&wrqu, 0, sizeof(union iwreq_data));
+	wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+
+	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
 	return ret;
 }
 
+static void
+clear_selected_scan_list_entries(wlan_adapter * adapter,
+                                 const struct wlan_ioctl_user_scan_cfg * scan_cfg)
+{
+	struct bss_descriptor * bss;
+	struct bss_descriptor * safe;
+	u32 clear_ssid_flag = 0, clear_bssid_flag = 0;
+
+	if (!scan_cfg)
+		return;
+
+	if (scan_cfg->clear_ssid && scan_cfg->ssid_len)
+		clear_ssid_flag = 1;
+
+	if (scan_cfg->clear_bssid
+	    && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0)
+	    && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) {
+		clear_bssid_flag = 1;
+	}
+
+	if (!clear_ssid_flag && !clear_bssid_flag)
+		return;
+
+	mutex_lock(&adapter->lock);
+	list_for_each_entry_safe (bss, safe, &adapter->network_list, list) {
+		u32 clear = 0;
+
+		/* Check for an SSID match */
+		if (   clear_ssid_flag
+		    && (bss->ssid_len == scan_cfg->ssid_len)
+		    && !memcmp(bss->ssid, scan_cfg->ssid, bss->ssid_len))
+			clear = 1;
+
+		/* Check for a BSSID match */
+		if (   clear_bssid_flag
+		    && !compare_ether_addr(bss->bssid, scan_cfg->bssid))
+			clear = 1;
+
+		if (clear) {
+			list_move_tail (&bss->list, &adapter->network_free_list);
+			clear_bss_descriptor(bss);
+		}
+	}
+	mutex_unlock(&adapter->lock);
+}
+
+
 /**
  *  @brief Internal function used to start a scan based on an input config
  *
@@ -736,19 +748,23 @@
  *  @return              0 or < 0 if error
  */
 int wlan_scan_networks(wlan_private * priv,
-			      const struct wlan_ioctl_user_scan_cfg * puserscanin)
+			      const struct wlan_ioctl_user_scan_cfg * puserscanin,
+			      int full_scan)
 {
-	wlan_adapter *adapter = priv->adapter;
+	wlan_adapter * adapter = priv->adapter;
 	struct mrvlietypes_chanlistparamset *pchantlvout;
 	struct chanscanparamset * scan_chan_list = NULL;
 	struct wlan_scan_cmd_config * scan_cfg = NULL;
-	u8 keeppreviousscan;
 	u8 filteredscan;
 	u8 scancurrentchanonly;
 	int maxchanperscan;
 	int ret;
+#ifdef CONFIG_LIBERTAS_DEBUG
+	struct bss_descriptor * iter_bss;
+	int i = 0;
+#endif
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	scan_chan_list = kzalloc(sizeof(struct chanscanparamset) *
 				WLAN_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
@@ -769,22 +785,14 @@
 		goto out;
 	}
 
-	keeppreviousscan = 0;
-
-	if (puserscanin) {
-		keeppreviousscan = puserscanin->keeppreviousscan;
-	}
-
-	if (!keeppreviousscan) {
-		memset(adapter->scantable, 0x00,
-		       sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST);
-		adapter->numinscantable = 0;
-	}
+	clear_selected_scan_list_entries(adapter, puserscanin);
 
 	/* Keep the data path active if we are only scanning our current channel */
 	if (!scancurrentchanonly) {
-		netif_stop_queue(priv->wlan_dev.netdev);
-		netif_carrier_off(priv->wlan_dev.netdev);
+		netif_stop_queue(priv->dev);
+		netif_carrier_off(priv->dev);
+		netif_stop_queue(priv->mesh_dev);
+		netif_carrier_off(priv->mesh_dev);
 	}
 
 	ret = wlan_scan_channel_list(priv,
@@ -792,17 +800,26 @@
 				     filteredscan,
 				     scan_cfg,
 				     pchantlvout,
-				     scan_chan_list);
+				     scan_chan_list,
+				     puserscanin,
+				     full_scan);
 
-	/*  Process the resulting scan table:
-	 *    - Remove any bad ssids
-	 *    - Update our current BSS information from scan data
-	 */
-	wlan_scan_process_results(priv);
+#ifdef CONFIG_LIBERTAS_DEBUG
+	/* Dump the scan table */
+	mutex_lock(&adapter->lock);
+	list_for_each_entry (iter_bss, &adapter->network_list, list) {
+		lbs_deb_scan("Scan:(%02d) " MAC_FMT ", RSSI[%03d], SSID[%s]\n",
+		       i++, MAC_ARG(iter_bss->bssid), (s32) iter_bss->rssi,
+		       escape_essid(iter_bss->ssid, iter_bss->ssid_len));
+	}
+	mutex_unlock(&adapter->lock);
+#endif
 
 	if (priv->adapter->connect_status == libertas_connected) {
-		netif_carrier_on(priv->wlan_dev.netdev);
-		netif_wake_queue(priv->wlan_dev.netdev);
+		netif_carrier_on(priv->dev);
+		netif_wake_queue(priv->dev);
+		netif_carrier_on(priv->mesh_dev);
+		netif_wake_queue(priv->mesh_dev);
 	}
 
 out:
@@ -812,7 +829,7 @@
 	if (scan_chan_list)
 		kfree(scan_chan_list);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
 	return ret;
 }
 
@@ -843,7 +860,7 @@
 	tlvbufleft = tlvbufsize;
 	*ptsftlv = NULL;
 
-	lbs_pr_debug(1, "SCAN_RESP: tlvbufsize = %d\n", tlvbufsize);
+	lbs_deb_scan("SCAN_RESP: tlvbufsize = %d\n", tlvbufsize);
 	lbs_dbg_hex("SCAN_RESP: TLV Buf", (u8 *) ptlv, tlvbufsize);
 
 	while (tlvbufleft >= sizeof(struct mrvlietypesheader)) {
@@ -856,7 +873,7 @@
 			break;
 
 		default:
-			lbs_pr_debug(1, "SCAN_RESP: Unhandled TLV = %d\n",
+			lbs_deb_scan("SCAN_RESP: Unhandled TLV = %d\n",
 			       tlvtype);
 			/* Give up, this seems corrupted */
 			return;
@@ -875,12 +892,12 @@
  *   response or beacon from the scan command.  Record information as needed
  *   in the scan table struct bss_descriptor for that entry.
  *
- *  @param pBSSIDEntry  Output parameter: Pointer to the BSS Entry
+ *  @param bss  Output parameter: Pointer to the BSS Entry
  *
  *  @return             0 or -1
  */
-static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
-					 u8 ** pbeaconinfo, int *bytesleft)
+static int libertas_process_bss(struct bss_descriptor * bss,
+				u8 ** pbeaconinfo, int *bytesleft)
 {
 	enum ieeetypes_elementid elemID;
 	struct ieeetypes_fhparamset *pFH;
@@ -897,13 +914,14 @@
 	u16 beaconsize;
 	u8 founddatarateie;
 	int bytesleftforcurrentbeacon;
+	int ret;
 
 	struct IE_WPA *pIe;
 	const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 };
 
 	struct ieeetypes_countryinfoset *pcountryinfo;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	founddatarateie = 0;
 	ratesize = 0;
@@ -911,8 +929,7 @@
 
 	if (*bytesleft >= sizeof(beaconsize)) {
 		/* Extract & convert beacon size from the command buffer */
-		memcpy(&beaconsize, *pbeaconinfo, sizeof(beaconsize));
-		beaconsize = le16_to_cpu(beaconsize);
+		beaconsize = le16_to_cpup((void *)*pbeaconinfo);
 		*bytesleft -= sizeof(beaconsize);
 		*pbeaconinfo += sizeof(beaconsize);
 	}
@@ -934,17 +951,14 @@
 
 	bytesleftforcurrentbeacon = beaconsize;
 
-	memcpy(pBSSEntry->macaddress, pcurrentptr, ETH_ALEN);
-	lbs_pr_debug(1, "InterpretIE: AP MAC Addr-%x:%x:%x:%x:%x:%x\n",
-	       pBSSEntry->macaddress[0], pBSSEntry->macaddress[1],
-	       pBSSEntry->macaddress[2], pBSSEntry->macaddress[3],
-	       pBSSEntry->macaddress[4], pBSSEntry->macaddress[5]);
+	memcpy(bss->bssid, pcurrentptr, ETH_ALEN);
+	lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid));
 
 	pcurrentptr += ETH_ALEN;
 	bytesleftforcurrentbeacon -= ETH_ALEN;
 
 	if (bytesleftforcurrentbeacon < 12) {
-		lbs_pr_debug(1, "InterpretIE: Not enough bytes left\n");
+		lbs_deb_scan("process_bss: Not enough bytes left\n");
 		return -1;
 	}
 
@@ -954,51 +968,48 @@
 	 */
 
 	/* RSSI is 1 byte long */
-	pBSSEntry->rssi = le32_to_cpu((long)(*pcurrentptr));
-	lbs_pr_debug(1, "InterpretIE: RSSI=%02X\n", *pcurrentptr);
+	bss->rssi = *pcurrentptr;
+	lbs_deb_scan("process_bss: RSSI=%02X\n", *pcurrentptr);
 	pcurrentptr += 1;
 	bytesleftforcurrentbeacon -= 1;
 
 	/* time stamp is 8 bytes long */
-	memcpy(fixedie.timestamp, pcurrentptr, 8);
-	memcpy(pBSSEntry->timestamp, pcurrentptr, 8);
+	fixedie.timestamp = bss->timestamp = le64_to_cpup((void *)pcurrentptr);
 	pcurrentptr += 8;
 	bytesleftforcurrentbeacon -= 8;
 
 	/* beacon interval is 2 bytes long */
-	memcpy(&fixedie.beaconinterval, pcurrentptr, 2);
-	pBSSEntry->beaconperiod = le16_to_cpu(fixedie.beaconinterval);
+	fixedie.beaconinterval = bss->beaconperiod = le16_to_cpup((void *)pcurrentptr);
 	pcurrentptr += 2;
 	bytesleftforcurrentbeacon -= 2;
 
 	/* capability information is 2 bytes long */
-	memcpy(&fixedie.capabilities, pcurrentptr, 2);
-	lbs_pr_debug(1, "InterpretIE: fixedie.capabilities=0x%X\n",
+        memcpy(&fixedie.capabilities, pcurrentptr, 2);
+	lbs_deb_scan("process_bss: fixedie.capabilities=0x%X\n",
 	       fixedie.capabilities);
-	fixedie.capabilities = le16_to_cpu(fixedie.capabilities);
 	pcap = (struct ieeetypes_capinfo *) & fixedie.capabilities;
-	memcpy(&pBSSEntry->cap, pcap, sizeof(struct ieeetypes_capinfo));
+	memcpy(&bss->cap, pcap, sizeof(struct ieeetypes_capinfo));
 	pcurrentptr += 2;
 	bytesleftforcurrentbeacon -= 2;
 
 	/* rest of the current buffer are IE's */
-	lbs_pr_debug(1, "InterpretIE: IElength for this AP = %d\n",
+	lbs_deb_scan("process_bss: IE length for this AP = %d\n",
 	       bytesleftforcurrentbeacon);
 
-	lbs_dbg_hex("InterpretIE: IE info", (u8 *) pcurrentptr,
+	lbs_dbg_hex("process_bss: IE info", (u8 *) pcurrentptr,
 		bytesleftforcurrentbeacon);
 
 	if (pcap->privacy) {
-		lbs_pr_debug(1, "InterpretIE: AP WEP enabled\n");
-		pBSSEntry->privacy = wlan802_11privfilter8021xWEP;
+		lbs_deb_scan("process_bss: AP WEP enabled\n");
+		bss->privacy = wlan802_11privfilter8021xWEP;
 	} else {
-		pBSSEntry->privacy = wlan802_11privfilteracceptall;
+		bss->privacy = wlan802_11privfilteracceptall;
 	}
 
 	if (pcap->ibss == 1) {
-		pBSSEntry->mode = IW_MODE_ADHOC;
+		bss->mode = IW_MODE_ADHOC;
 	} else {
-		pBSSEntry->mode = IW_MODE_INFRA;
+		bss->mode = IW_MODE_INFRA;
 	}
 
 	/* process variable IE */
@@ -1007,94 +1018,83 @@
 		elemlen = *((u8 *) pcurrentptr + 1);
 
 		if (bytesleftforcurrentbeacon < elemlen) {
-			lbs_pr_debug(1, "InterpretIE: error in processing IE, "
+			lbs_deb_scan("process_bss: error in processing IE, "
 			       "bytes left < IE length\n");
 			bytesleftforcurrentbeacon = 0;
 			continue;
 		}
 
 		switch (elemID) {
-
 		case SSID:
-			pBSSEntry->ssid.ssidlength = elemlen;
-			memcpy(pBSSEntry->ssid.ssid, (pcurrentptr + 2),
-			       elemlen);
-			lbs_pr_debug(1, "ssid: %32s", pBSSEntry->ssid.ssid);
+			bss->ssid_len = elemlen;
+			memcpy(bss->ssid, (pcurrentptr + 2), elemlen);
+			lbs_deb_scan("ssid '%s', ssid length %u\n",
+			             escape_essid(bss->ssid, bss->ssid_len),
+			             bss->ssid_len);
 			break;
 
 		case SUPPORTED_RATES:
-			memcpy(pBSSEntry->datarates, (pcurrentptr + 2),
-			       elemlen);
-			memmove(pBSSEntry->libertas_supported_rates, (pcurrentptr + 2),
+			memcpy(bss->datarates, (pcurrentptr + 2), elemlen);
+			memmove(bss->libertas_supported_rates, (pcurrentptr + 2),
 				elemlen);
 			ratesize = elemlen;
 			founddatarateie = 1;
 			break;
 
 		case EXTRA_IE:
-			lbs_pr_debug(1, "InterpretIE: EXTRA_IE Found!\n");
-			pBSSEntry->extra_ie = 1;
+			lbs_deb_scan("process_bss: EXTRA_IE Found!\n");
 			break;
 
 		case FH_PARAM_SET:
 			pFH = (struct ieeetypes_fhparamset *) pcurrentptr;
-			memmove(&pBSSEntry->phyparamset.fhparamset, pFH,
+			memmove(&bss->phyparamset.fhparamset, pFH,
 				sizeof(struct ieeetypes_fhparamset));
-			pBSSEntry->phyparamset.fhparamset.dwelltime
-			    =
-			    le16_to_cpu(pBSSEntry->phyparamset.fhparamset.
-					     dwelltime);
+#if 0 /* I think we can store these LE */
+			bss->phyparamset.fhparamset.dwelltime
+			    = le16_to_cpu(bss->phyparamset.fhparamset.dwelltime);
+#endif
 			break;
 
 		case DS_PARAM_SET:
 			pDS = (struct ieeetypes_dsparamset *) pcurrentptr;
-
-			pBSSEntry->channel = pDS->currentchan;
-
-			memcpy(&pBSSEntry->phyparamset.dsparamset, pDS,
+			bss->channel = pDS->currentchan;
+			memcpy(&bss->phyparamset.dsparamset, pDS,
 			       sizeof(struct ieeetypes_dsparamset));
 			break;
 
 		case CF_PARAM_SET:
 			pCF = (struct ieeetypes_cfparamset *) pcurrentptr;
-
-			memcpy(&pBSSEntry->ssparamset.cfparamset, pCF,
+			memcpy(&bss->ssparamset.cfparamset, pCF,
 			       sizeof(struct ieeetypes_cfparamset));
 			break;
 
 		case IBSS_PARAM_SET:
 			pibss = (struct ieeetypes_ibssparamset *) pcurrentptr;
-			pBSSEntry->atimwindow =
-			    le32_to_cpu(pibss->atimwindow);
-
-			memmove(&pBSSEntry->ssparamset.ibssparamset, pibss,
+			bss->atimwindow = le32_to_cpu(pibss->atimwindow);
+			memmove(&bss->ssparamset.ibssparamset, pibss,
 				sizeof(struct ieeetypes_ibssparamset));
-
-			pBSSEntry->ssparamset.ibssparamset.atimwindow
-			    =
-			    le16_to_cpu(pBSSEntry->ssparamset.ibssparamset.
-					     atimwindow);
+#if 0
+			bss->ssparamset.ibssparamset.atimwindow
+			    = le16_to_cpu(bss->ssparamset.ibssparamset.atimwindow);
+#endif
 			break;
 
 			/* Handle Country Info IE */
 		case COUNTRY_INFO:
-			pcountryinfo =
-			    (struct ieeetypes_countryinfoset *) pcurrentptr;
-
-			if (pcountryinfo->len <
-			    sizeof(pcountryinfo->countrycode)
+			pcountryinfo = (struct ieeetypes_countryinfoset *) pcurrentptr;
+			if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
 			    || pcountryinfo->len > 254) {
-				lbs_pr_debug(1, "InterpretIE: 11D- Err "
+				lbs_deb_scan("process_bss: 11D- Err "
 				       "CountryInfo len =%d min=%zd max=254\n",
 				       pcountryinfo->len,
 				       sizeof(pcountryinfo->countrycode));
-				LEAVE();
-				return -1;
+				ret = -1;
+				goto done;
 			}
 
-			memcpy(&pBSSEntry->countryinfo,
+			memcpy(&bss->countryinfo,
 			       pcountryinfo, pcountryinfo->len + 2);
-			lbs_dbg_hex("InterpretIE: 11D- CountryInfo:",
+			lbs_dbg_hex("process_bss: 11D- CountryInfo:",
 				(u8 *) pcountryinfo,
 				(u32) (pcountryinfo->len + 2));
 			break;
@@ -1114,12 +1114,10 @@
 					bytestocopy = elemlen;
 				}
 
-				pRate = (u8 *) pBSSEntry->datarates;
+				pRate = (u8 *) bss->datarates;
 				pRate += ratesize;
 				memmove(pRate, (pcurrentptr + 2), bytestocopy);
-
-				pRate = (u8 *) pBSSEntry->libertas_supported_rates;
-
+				pRate = (u8 *) bss->libertas_supported_rates;
 				pRate += ratesize;
 				memmove(pRate, (pcurrentptr + 2), bytestocopy);
 			}
@@ -1132,24 +1130,17 @@
 			if (memcmp(pIe->oui, oui01, sizeof(oui01)))
 				break;
 
-			pBSSEntry->wpa_ie_len = min_t(size_t,
-				elemlen + IE_ID_LEN_FIELDS_BYTES,
-				sizeof(pBSSEntry->wpa_ie));
-			memcpy(pBSSEntry->wpa_ie, pcurrentptr,
-				pBSSEntry->wpa_ie_len);
-			lbs_dbg_hex("InterpretIE: Resp WPA_IE",
-				pBSSEntry->wpa_ie, elemlen);
+			bss->wpa_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES,
+				MAX_WPA_IE_LEN);
+			memcpy(bss->wpa_ie, pcurrentptr, bss->wpa_ie_len);
+			lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie, elemlen);
 			break;
 		case WPA2_IE:
 			pIe = (struct IE_WPA *)pcurrentptr;
-
-			pBSSEntry->rsn_ie_len = min_t(size_t,
-				elemlen + IE_ID_LEN_FIELDS_BYTES,
-				sizeof(pBSSEntry->rsn_ie));
-			memcpy(pBSSEntry->rsn_ie, pcurrentptr,
-				pBSSEntry->rsn_ie_len);
-			lbs_dbg_hex("InterpretIE: Resp WPA2_IE",
-				pBSSEntry->rsn_ie, elemlen);
+			bss->rsn_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES,
+				MAX_WPA_IE_LEN);
+			memcpy(bss->rsn_ie, pcurrentptr, bss->rsn_ie_len);
+			lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elemlen);
 			break;
 		case TIM:
 			break;
@@ -1165,7 +1156,14 @@
 
 	}			/* while (bytesleftforcurrentbeacon > 2) */
 
-	return 0;
+	/* Timestamp */
+	bss->last_scanned = jiffies;
+
+	ret = 0;
+
+done:
+	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+	return ret;
 }
 
 /**
@@ -1176,15 +1174,12 @@
  *
  *  @return         0--ssid is same, otherwise is different
  */
-int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, struct WLAN_802_11_SSID *ssid2)
+int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
 {
-	if (!ssid1 || !ssid2)
+	if (ssid1_len != ssid2_len)
 		return -1;
 
-	if (ssid1->ssidlength != ssid2->ssidlength)
-		return -1;
-
-	return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssidlength);
+	return memcmp(ssid1, ssid2, ssid1_len);
 }
 
 /**
@@ -1196,38 +1191,41 @@
  *
  *  @return         index in BSSID list, or error return code (< 0)
  */
-int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode)
+struct bss_descriptor * libertas_find_bssid_in_list(wlan_adapter * adapter,
+		u8 * bssid, u8 mode)
 {
-	int ret = -ENETUNREACH;
-	int i;
+	struct bss_descriptor * iter_bss;
+	struct bss_descriptor * found_bss = NULL;
 
 	if (!bssid)
-		return -EFAULT;
+		return NULL;
 
-	lbs_pr_debug(1, "FindBSSID: Num of BSSIDs = %d\n",
-	       adapter->numinscantable);
+	lbs_dbg_hex("libertas_find_BSSID_in_list: looking for ",
+		bssid, ETH_ALEN);
 
-	/* Look through the scan table for a compatible match. The ret return
-	 *   variable will be equal to the index in the scan table (greater
-	 *   than zero) if the network is compatible.  The loop will continue
-	 *   past a matched bssid that is not compatible in case there is an
-	 *   AP with multiple SSIDs assigned to the same BSSID
+	/* Look through the scan table for a compatible match.  The loop will
+	 *   continue past a matched bssid that is not compatible in case there
+	 *   is an AP with multiple SSIDs assigned to the same BSSID
 	 */
-	for (i = 0; ret < 0 && i < adapter->numinscantable; i++) {
-		if (!memcmp(adapter->scantable[i].macaddress, bssid, ETH_ALEN)) {
-			switch (mode) {
-			case IW_MODE_INFRA:
-			case IW_MODE_ADHOC:
-				ret = is_network_compatible(adapter, i, mode);
+	mutex_lock(&adapter->lock);
+	list_for_each_entry (iter_bss, &adapter->network_list, list) {
+		if (compare_ether_addr(iter_bss->bssid, bssid))
+			continue; /* bssid doesn't match */
+		switch (mode) {
+		case IW_MODE_INFRA:
+		case IW_MODE_ADHOC:
+			if (!is_network_compatible(adapter, iter_bss, mode))
 				break;
-			default:
-				ret = i;
-				break;
-			}
+			found_bss = iter_bss;
+			break;
+		default:
+			found_bss = iter_bss;
+			break;
 		}
 	}
+	mutex_unlock(&adapter->lock);
 
-	return ret;
+	return found_bss;
 }
 
 /**
@@ -1240,61 +1238,60 @@
  *
  *  @return         index in BSSID list
  */
-int libertas_find_SSID_in_list(wlan_adapter * adapter,
-		   struct WLAN_802_11_SSID *ssid, u8 * bssid, u8 mode)
+struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
+		   u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
+		   int channel)
 {
-	int net = -ENETUNREACH;
 	u8 bestrssi = 0;
-	int i;
-	int j;
+	struct bss_descriptor * iter_bss = NULL;
+	struct bss_descriptor * found_bss = NULL;
+	struct bss_descriptor * tmp_oldest = NULL;
 
-	lbs_pr_debug(1, "Num of Entries in Table = %d\n", adapter->numinscantable);
+	mutex_lock(&adapter->lock);
 
-	for (i = 0; i < adapter->numinscantable; i++) {
-		if (!libertas_SSID_cmp(&adapter->scantable[i].ssid, ssid) &&
-		    (!bssid ||
-		     !memcmp(adapter->scantable[i].
-			     macaddress, bssid, ETH_ALEN))) {
-			switch (mode) {
-			case IW_MODE_INFRA:
-			case IW_MODE_ADHOC:
-				j = is_network_compatible(adapter, i, mode);
+	list_for_each_entry (iter_bss, &adapter->network_list, list) {
+		if (   !tmp_oldest
+		    || (iter_bss->last_scanned < tmp_oldest->last_scanned))
+			tmp_oldest = iter_bss;
 
-				if (j >= 0) {
-					if (bssid) {
-						return i;
-					}
+		if (libertas_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
+		                      ssid, ssid_len) != 0)
+			continue; /* ssid doesn't match */
+		if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
+			continue; /* bssid doesn't match */
+		if ((channel > 0) && (iter_bss->channel != channel))
+			continue; /* channel doesn't match */
 
-					if (SCAN_RSSI
-					    (adapter->scantable[i].rssi)
-					    > bestrssi) {
-						bestrssi =
-						    SCAN_RSSI(adapter->
-							      scantable[i].
-							      rssi);
-						net = i;
-					}
-				} else {
-					if (net == -ENETUNREACH) {
-						net = j;
-					}
-				}
+		switch (mode) {
+		case IW_MODE_INFRA:
+		case IW_MODE_ADHOC:
+			if (!is_network_compatible(adapter, iter_bss, mode))
 				break;
-			case IW_MODE_AUTO:
-			default:
-				if (SCAN_RSSI(adapter->scantable[i].rssi)
-				    > bestrssi) {
-					bestrssi =
-					    SCAN_RSSI(adapter->scantable[i].
-						      rssi);
-					net = i;
-				}
-				break;
+
+			if (bssid) {
+				/* Found requested BSSID */
+				found_bss = iter_bss;
+				goto out;
 			}
+
+			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
+				bestrssi = SCAN_RSSI(iter_bss->rssi);
+				found_bss = iter_bss;
+			}
+			break;
+		case IW_MODE_AUTO:
+		default:
+			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
+				bestrssi = SCAN_RSSI(iter_bss->rssi);
+				found_bss = iter_bss;
+			}
+			break;
 		}
 	}
 
-	return net;
+out:
+	mutex_unlock(&adapter->lock);
+	return found_bss;
 }
 
 /**
@@ -1307,43 +1304,38 @@
  *
  *  @return         index in BSSID list
  */
-int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode)
+struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter,
+		u8 mode)
 {
-	int bestnet = -ENETUNREACH;
 	u8 bestrssi = 0;
-	int i;
+	struct bss_descriptor * iter_bss;
+	struct bss_descriptor * best_bss = NULL;
 
-	ENTER();
+	mutex_lock(&adapter->lock);
 
-	lbs_pr_debug(1, "Num of BSSIDs = %d\n", adapter->numinscantable);
-
-	for (i = 0; i < adapter->numinscantable; i++) {
+	list_for_each_entry (iter_bss, &adapter->network_list, list) {
 		switch (mode) {
 		case IW_MODE_INFRA:
 		case IW_MODE_ADHOC:
-			if (is_network_compatible(adapter, i, mode) >= 0) {
-				if (SCAN_RSSI(adapter->scantable[i].rssi) >
-				    bestrssi) {
-					bestrssi =
-					    SCAN_RSSI(adapter->scantable[i].
-						      rssi);
-					bestnet = i;
-				}
-			}
+			if (!is_network_compatible(adapter, iter_bss, mode))
+				break;
+			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
+				break;
+			bestrssi = SCAN_RSSI(iter_bss->rssi);
+			best_bss = iter_bss;
 			break;
 		case IW_MODE_AUTO:
 		default:
-			if (SCAN_RSSI(adapter->scantable[i].rssi) > bestrssi) {
-				bestrssi =
-				    SCAN_RSSI(adapter->scantable[i].rssi);
-				bestnet = i;
-			}
+			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
+				break;
+			bestrssi = SCAN_RSSI(iter_bss->rssi);
+			best_bss = iter_bss;
 			break;
 		}
 	}
 
-	LEAVE();
-	return bestnet;
+	mutex_unlock(&adapter->lock);
+	return best_bss;
 }
 
 /**
@@ -1354,41 +1346,30 @@
  *
  *  @return             0--success, otherwise--fail
  */
-int libertas_find_best_network_SSID(wlan_private * priv,
-                                    struct WLAN_802_11_SSID *pSSID,
-                                    u8 preferred_mode, u8 *out_mode)
+int libertas_find_best_network_ssid(wlan_private * priv,
+		u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode)
 {
 	wlan_adapter *adapter = priv->adapter;
-	int ret = 0;
-	struct bss_descriptor *preqbssid;
-	int i;
+	int ret = -1;
+	struct bss_descriptor * found;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	memset(pSSID, 0, sizeof(struct WLAN_802_11_SSID));
-
-	wlan_scan_networks(priv, NULL);
+	wlan_scan_networks(priv, NULL, 1);
 	if (adapter->surpriseremoved)
 		return -1;
+
 	wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);
 
-	i = libertas_find_best_SSID_in_list(adapter, preferred_mode);
-	if (i < 0) {
-		ret = -1;
-		goto out;
+	found = libertas_find_best_ssid_in_list(adapter, preferred_mode);
+	if (found && (found->ssid_len > 0)) {
+		memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
+		*out_ssid_len = found->ssid_len;
+		*out_mode = found->mode;
+		ret = 0;
 	}
 
-	preqbssid = &adapter->scantable[i];
-	memcpy(pSSID, &preqbssid->ssid,
-	       sizeof(struct WLAN_802_11_SSID));
-	*out_mode = preqbssid->mode;
-
-	if (!pSSID->ssidlength) {
-		ret = -1;
-	}
-
-out:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
 	return ret;
 }
 
@@ -1407,20 +1388,15 @@
 {
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
-	union iwreq_data wrqu;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_SCAN);
 
-	if (!wlan_scan_networks(priv, NULL)) {
-		memset(&wrqu, 0, sizeof(union iwreq_data));
-		wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu,
-				    NULL);
-	}
+	wlan_scan_networks(priv, NULL, 0);
 
 	if (adapter->surpriseremoved)
 		return -1;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_SCAN);
 	return 0;
 }
 
@@ -1433,32 +1409,31 @@
  *
  *  @return                0-success, otherwise fail
  */
-int libertas_send_specific_SSID_scan(wlan_private * priv,
-			 struct WLAN_802_11_SSID *prequestedssid,
-			 u8 keeppreviousscan)
+int libertas_send_specific_ssid_scan(wlan_private * priv,
+			u8 *ssid, u8 ssid_len, u8 clear_ssid)
 {
 	wlan_adapter *adapter = priv->adapter;
 	struct wlan_ioctl_user_scan_cfg scancfg;
+	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	if (prequestedssid == NULL) {
-		return -1;
-	}
+	if (!ssid_len)
+		goto out;
 
 	memset(&scancfg, 0x00, sizeof(scancfg));
+	memcpy(scancfg.ssid, ssid, ssid_len);
+	scancfg.ssid_len = ssid_len;
+	scancfg.clear_ssid = clear_ssid;
 
-	memcpy(scancfg.specificSSID, prequestedssid->ssid,
-	       prequestedssid->ssidlength);
-	scancfg.keeppreviousscan = keeppreviousscan;
-
-	wlan_scan_networks(priv, &scancfg);
+	wlan_scan_networks(priv, &scancfg, 1);
 	if (adapter->surpriseremoved)
 		return -1;
 	wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);
 
-	LEAVE();
-	return 0;
+out:
+	lbs_deb_leave(LBS_DEB_ASSOC);
+	return ret;
 }
 
 /**
@@ -1470,30 +1445,169 @@
  *
  *  @return          0-success, otherwise fail
  */
-int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 keeppreviousscan)
+int libertas_send_specific_bssid_scan(wlan_private * priv, u8 * bssid, u8 clear_bssid)
 {
 	struct wlan_ioctl_user_scan_cfg scancfg;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	if (bssid == NULL) {
-		return -1;
-	}
+	if (bssid == NULL)
+		goto out;
 
 	memset(&scancfg, 0x00, sizeof(scancfg));
-	memcpy(scancfg.specificBSSID, bssid, sizeof(scancfg.specificBSSID));
-	scancfg.keeppreviousscan = keeppreviousscan;
+	memcpy(scancfg.bssid, bssid, ETH_ALEN);
+	scancfg.clear_bssid = clear_bssid;
 
-	wlan_scan_networks(priv, &scancfg);
+	wlan_scan_networks(priv, &scancfg, 1);
 	if (priv->adapter->surpriseremoved)
 		return -1;
 	wait_event_interruptible(priv->adapter->cmd_pending,
 		!priv->adapter->nr_cmd_pending);
 
-	LEAVE();
+out:
+	lbs_deb_leave(LBS_DEB_ASSOC);
 	return 0;
 }
 
+static inline char *libertas_translate_scan(wlan_private *priv,
+					char *start, char *stop,
+					struct bss_descriptor *bss)
+{
+	wlan_adapter *adapter = priv->adapter;
+	struct chan_freq_power *cfp;
+	char *current_val;	/* For rates */
+	struct iw_event iwe;	/* Temporary buffer */
+	int j;
+#define PERFECT_RSSI ((u8)50)
+#define WORST_RSSI   ((u8)0)
+#define RSSI_DIFF    ((u8)(PERFECT_RSSI - WORST_RSSI))
+	u8 rssi;
+
+	cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, bss->channel);
+	if (!cfp) {
+		lbs_deb_scan("Invalid channel number %d\n", bss->channel);
+		return NULL;
+	}
+
+	/* First entry *MUST* be the AP BSSID */
+	iwe.cmd = SIOCGIWAP;
+	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+	memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
+	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
+
+	/* SSID */
+	iwe.cmd = SIOCGIWESSID;
+	iwe.u.data.flags = 1;
+	iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE);
+	start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+
+	/* Mode */
+	iwe.cmd = SIOCGIWMODE;
+	iwe.u.mode = bss->mode;
+	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
+
+	/* Frequency */
+	iwe.cmd = SIOCGIWFREQ;
+	iwe.u.freq.m = (long)cfp->freq * 100000;
+	iwe.u.freq.e = 1;
+	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
+
+	/* Add quality statistics */
+	iwe.cmd = IWEVQUAL;
+	iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
+	iwe.u.qual.level = SCAN_RSSI(bss->rssi);
+
+	rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
+	iwe.u.qual.qual =
+	    (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
+	     (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
+	    (RSSI_DIFF * RSSI_DIFF);
+	if (iwe.u.qual.qual > 100)
+		iwe.u.qual.qual = 100;
+
+	if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+		iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
+	} else {
+		iwe.u.qual.noise =
+		    CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+	}
+
+	/* Locally created ad-hoc BSSs won't have beacons if this is the
+	 * only station in the adhoc network; so get signal strength
+	 * from receive statistics.
+	 */
+	if ((adapter->mode == IW_MODE_ADHOC)
+	    && adapter->adhoccreate
+	    && !libertas_ssid_cmp(adapter->curbssparams.ssid,
+	                          adapter->curbssparams.ssid_len,
+	                          bss->ssid, bss->ssid_len)) {
+		int snr, nf;
+		snr = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+		nf = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+		iwe.u.qual.level = CAL_RSSI(snr, nf);
+	}
+	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
+
+	/* Add encryption capability */
+	iwe.cmd = SIOCGIWENCODE;
+	if (bss->privacy) {
+		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+	} else {
+		iwe.u.data.flags = IW_ENCODE_DISABLED;
+	}
+	iwe.u.data.length = 0;
+	start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+
+	current_val = start + IW_EV_LCP_LEN;
+
+	iwe.cmd = SIOCGIWRATE;
+	iwe.u.bitrate.fixed = 0;
+	iwe.u.bitrate.disabled = 0;
+	iwe.u.bitrate.value = 0;
+
+	for (j = 0; j < sizeof(bss->libertas_supported_rates); j++) {
+		u8 rate = bss->libertas_supported_rates[j];
+		if (rate == 0)
+			break; /* no more rates */
+		/* Bit rate given in 500 kb/s units (+ 0x80) */
+		iwe.u.bitrate.value = (rate & 0x7f) * 500000;
+		current_val = iwe_stream_add_value(start, current_val,
+					 stop, &iwe, IW_EV_PARAM_LEN);
+	}
+	if ((bss->mode == IW_MODE_ADHOC)
+	    && !libertas_ssid_cmp(adapter->curbssparams.ssid,
+	                          adapter->curbssparams.ssid_len,
+	                          bss->ssid, bss->ssid_len)
+	    && adapter->adhoccreate) {
+		iwe.u.bitrate.value = 22 * 500000;
+		current_val = iwe_stream_add_value(start, current_val,
+					 stop, &iwe, IW_EV_PARAM_LEN);
+	}
+	/* Check if we added any event */
+	if((current_val - start) > IW_EV_LCP_LEN)
+		start = current_val;
+
+	memset(&iwe, 0, sizeof(iwe));
+	if (bss->wpa_ie_len) {
+		char buf[MAX_WPA_IE_LEN];
+		memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
+		iwe.cmd = IWEVGENIE;
+		iwe.u.data.length = bss->wpa_ie_len;
+		start = iwe_stream_add_point(start, stop, &iwe, buf);
+	}
+
+	memset(&iwe, 0, sizeof(iwe));
+	if (bss->rsn_ie_len) {
+		char buf[MAX_WPA_IE_LEN];
+		memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
+		iwe.cmd = IWEVGENIE;
+		iwe.u.data.length = bss->rsn_ie_len;
+		start = iwe_stream_add_point(start, stop, &iwe, buf);
+	}
+
+	return start;
+}
+
 /**
  *  @brief  Retrieve the scan table entries via wireless tools IOCTL call
  *
@@ -1507,267 +1621,59 @@
 int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
 		  struct iw_point *dwrq, char *extra)
 {
+#define SCAN_ITEM_SIZE 128
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
-	int ret = 0;
-	char *current_ev = extra;
-	char *end_buf = extra + IW_SCAN_MAX_DATA;
-	struct chan_freq_power *cfp;
-	struct bss_descriptor *pscantable;
-	char *current_val;	/* For rates */
-	struct iw_event iwe;	/* Temporary buffer */
-	int i;
-	int j;
-	int rate;
-#define PERFECT_RSSI ((u8)50)
-#define WORST_RSSI   ((u8)0)
-#define RSSI_DIFF    ((u8)(PERFECT_RSSI - WORST_RSSI))
-	u8 rssi;
+	int err = 0;
+	char *ev = extra;
+	char *stop = ev + dwrq->length;
+	struct bss_descriptor * iter_bss;
+	struct bss_descriptor * safe;
 
-	u8 buf[16 + 256 * 2];
-	u8 *ptr;
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	ENTER();
+	/* If we've got an uncompleted scan, schedule the next part */
+	if (!adapter->nr_cmd_pending && adapter->last_scanned_channel)
+		wlan_scan_networks(priv, NULL, 0);
 
-	/*
-	 * if there's either commands in the queue or one being
-	 * processed return -EAGAIN for iwlist to retry later.
-	 */
-    if (adapter->nr_cmd_pending)
-		return -EAGAIN;
+	/* Update RSSI if current BSS is a locally created ad-hoc BSS */
+	if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) {
+		libertas_prepare_and_send_command(priv, cmd_802_11_rssi, 0,
+					cmd_option_waitforrsp, 0, NULL);
+	}
 
-	if (adapter->connect_status == libertas_connected)
-		lbs_pr_debug(1, "Current ssid: %32s\n",
-		       adapter->curbssparams.ssid.ssid);
+	mutex_lock(&adapter->lock);
+	list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) {
+		char * next_ev;
+		unsigned long stale_time;
 
-	lbs_pr_debug(1, "Scan: Get: numinscantable = %d\n",
-	       adapter->numinscantable);
-
-	/* The old API using SIOCGIWAPLIST had a hard limit of IW_MAX_AP.
-	 * The new API using SIOCGIWSCAN is only limited by buffer size
-	 * WE-14 -> WE-16 the buffer is limited to IW_SCAN_MAX_DATA bytes
-	 * which is 4096.
-	 */
-	for (i = 0; i < adapter->numinscantable; i++) {
-		if ((current_ev + MAX_SCAN_CELL_SIZE) >= end_buf) {
-			lbs_pr_debug(1, "i=%d break out: current_ev=%p end_buf=%p "
-			       "MAX_SCAN_CELL_SIZE=%zd\n",
-			       i, current_ev, end_buf, MAX_SCAN_CELL_SIZE);
+		if (stop - ev < SCAN_ITEM_SIZE) {
+			err = -E2BIG;
 			break;
 		}
 
-		pscantable = &adapter->scantable[i];
-
-		lbs_pr_debug(1, "i=%d  ssid: %32s\n", i, pscantable->ssid.ssid);
-
-		cfp =
-		    libertas_find_cfp_by_band_and_channel(adapter, 0,
-						 pscantable->channel);
-		if (!cfp) {
-			lbs_pr_debug(1, "Invalid channel number %d\n",
-			       pscantable->channel);
+		/* Prune old an old scan result */
+		stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
+		if (time_after(jiffies, stale_time)) {
+			list_move_tail (&iter_bss->list,
+			                &adapter->network_free_list);
+			clear_bss_descriptor(iter_bss);
 			continue;
 		}
 
-		if (!ssid_valid(&adapter->scantable[i].ssid)) {
+		/* Translate to WE format this entry */
+		next_ev = libertas_translate_scan(priv, ev, stop, iter_bss);
+		if (next_ev == NULL)
 			continue;
-		}
-
-		/* First entry *MUST* be the AP MAC address */
-		iwe.cmd = SIOCGIWAP;
-		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-		memcpy(iwe.u.ap_addr.sa_data,
-		       &adapter->scantable[i].macaddress, ETH_ALEN);
-
-		iwe.len = IW_EV_ADDR_LEN;
-		current_ev =
-		    iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
-
-		//Add the ESSID
-		iwe.u.data.length = adapter->scantable[i].ssid.ssidlength;
-
-		if (iwe.u.data.length > 32) {
-			iwe.u.data.length = 32;
-		}
-
-		iwe.cmd = SIOCGIWESSID;
-		iwe.u.data.flags = 1;
-		iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-						  adapter->scantable[i].ssid.
-						  ssid);
-
-		//Add mode
-		iwe.cmd = SIOCGIWMODE;
-		iwe.u.mode = adapter->scantable[i].mode;
-		iwe.len = IW_EV_UINT_LEN;
-		current_ev =
-		    iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
-
-		//frequency
-		iwe.cmd = SIOCGIWFREQ;
-		iwe.u.freq.m = (long)cfp->freq * 100000;
-		iwe.u.freq.e = 1;
-		iwe.len = IW_EV_FREQ_LEN;
-		current_ev =
-		    iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
-
-		/* Add quality statistics */
-		iwe.cmd = IWEVQUAL;
-		iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
-		iwe.u.qual.level = SCAN_RSSI(adapter->scantable[i].rssi);
-
-		rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
-		iwe.u.qual.qual =
-		    (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
-		     (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
-		    (RSSI_DIFF * RSSI_DIFF);
-		if (iwe.u.qual.qual > 100)
-			iwe.u.qual.qual = 100;
-		else if (iwe.u.qual.qual < 1)
-			iwe.u.qual.qual = 0;
-
-		if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
-			iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
-		} else {
-			iwe.u.qual.noise =
-			    CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
-		}
-		if ((adapter->mode == IW_MODE_ADHOC) &&
-		    !libertas_SSID_cmp(&adapter->curbssparams.ssid,
-			     &adapter->scantable[i].ssid)
-		    && adapter->adhoccreate) {
-			ret = libertas_prepare_and_send_command(priv,
-						    cmd_802_11_rssi,
-						    0,
-						    cmd_option_waitforrsp,
-						    0, NULL);
-
-			if (!ret) {
-				iwe.u.qual.level =
-				    CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] /
-					     AVG_SCALE,
-					     adapter->NF[TYPE_RXPD][TYPE_AVG] /
-					     AVG_SCALE);
-			}
-		}
-		iwe.len = IW_EV_QUAL_LEN;
-		current_ev =
-		    iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
-
-		/* Add encryption capability */
-		iwe.cmd = SIOCGIWENCODE;
-		if (adapter->scantable[i].privacy) {
-			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-		} else {
-			iwe.u.data.flags = IW_ENCODE_DISABLED;
-		}
-		iwe.u.data.length = 0;
-		iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-						  adapter->scantable->ssid.
-						  ssid);
-
-		current_val = current_ev + IW_EV_LCP_LEN;
-
-		iwe.cmd = SIOCGIWRATE;
-
-		iwe.u.bitrate.fixed = 0;
-		iwe.u.bitrate.disabled = 0;
-		iwe.u.bitrate.value = 0;
-
-		/* Bit rate given in 500 kb/s units (+ 0x80) */
-		for (j = 0; j < sizeof(adapter->scantable[i].libertas_supported_rates);
-		     j++) {
-			if (adapter->scantable[i].libertas_supported_rates[j] == 0) {
-				break;
-			}
-			rate =
-			    (adapter->scantable[i].libertas_supported_rates[j] & 0x7F) *
-			    500000;
-			if (rate > iwe.u.bitrate.value) {
-				iwe.u.bitrate.value = rate;
-			}
-
-			iwe.u.bitrate.value =
-			    (adapter->scantable[i].libertas_supported_rates[j]
-			     & 0x7f) * 500000;
-			iwe.len = IW_EV_PARAM_LEN;
-			current_ev =
-			    iwe_stream_add_value(current_ev, current_val,
-						 end_buf, &iwe, iwe.len);
-
-		}
-		if ((adapter->scantable[i].mode == IW_MODE_ADHOC)
-		    && !libertas_SSID_cmp(&adapter->curbssparams.ssid,
-				&adapter->scantable[i].ssid)
-		    && adapter->adhoccreate) {
-			iwe.u.bitrate.value = 22 * 500000;
-		}
-		iwe.len = IW_EV_PARAM_LEN;
-		current_ev =
-		    iwe_stream_add_value(current_ev, current_val, end_buf, &iwe,
-					 iwe.len);
-
-		/* Add new value to event */
-		current_val = current_ev + IW_EV_LCP_LEN;
-
-		if (adapter->scantable[i].rsn_ie[0] == WPA2_IE) {
-			memset(&iwe, 0, sizeof(iwe));
-			memset(buf, 0, sizeof(buf));
-			memcpy(buf, adapter->scantable[i].rsn_ie,
-					adapter->scantable[i].rsn_ie_len);
-			iwe.cmd = IWEVGENIE;
-			iwe.u.data.length = adapter->scantable[i].rsn_ie_len;
-			iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
-			current_ev = iwe_stream_add_point(current_ev, end_buf,
-					&iwe, buf);
-		}
-		if (adapter->scantable[i].wpa_ie[0] == WPA_IE) {
-			memset(&iwe, 0, sizeof(iwe));
-			memset(buf, 0, sizeof(buf));
-			memcpy(buf, adapter->scantable[i].wpa_ie,
-					adapter->scantable[i].wpa_ie_len);
-			iwe.cmd = IWEVGENIE;
-			iwe.u.data.length = adapter->scantable[i].wpa_ie_len;
-			iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
-			current_ev = iwe_stream_add_point(current_ev, end_buf,
-					&iwe, buf);
-		}
-
-
-		if (adapter->scantable[i].extra_ie != 0) {
-			memset(&iwe, 0, sizeof(iwe));
-			memset(buf, 0, sizeof(buf));
-			ptr = buf;
-			ptr += sprintf(ptr, "extra_ie");
-			iwe.u.data.length = strlen(buf);
-
-			lbs_pr_debug(1, "iwe.u.data.length %d\n",
-			       iwe.u.data.length);
-			lbs_pr_debug(1, "BUF: %s \n", buf);
-
-			iwe.cmd = IWEVCUSTOM;
-			iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
-			current_ev =
-			    iwe_stream_add_point(current_ev, end_buf, &iwe,
-						 buf);
-		}
-
-		current_val = current_ev + IW_EV_LCP_LEN;
-
-		/*
-		 * Check if we added any event
-		 */
-		if ((current_val - current_ev) > IW_EV_LCP_LEN)
-			current_ev = current_val;
+		ev = next_ev;
 	}
+	mutex_unlock(&adapter->lock);
 
-	dwrq->length = (current_ev - extra);
+	dwrq->length = (ev - extra);
 	dwrq->flags = 0;
 
-	LEAVE();
-	return 0;
+	lbs_deb_leave(LBS_DEB_ASSOC);
+	return err;
 }
 
 /**
@@ -1796,13 +1702,13 @@
 	struct cmd_ds_802_11_scan *pscan = &cmd->params.scan;
 	struct wlan_scan_cmd_config *pscancfg;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	pscancfg = pdata_buf;
 
 	/* Set fixed field variables in scan command */
 	pscan->bsstype = pscancfg->bsstype;
-	memcpy(pscan->BSSID, pscancfg->specificBSSID, sizeof(pscan->BSSID));
+	memcpy(pscan->BSSID, pscancfg->bssid, sizeof(pscan->BSSID));
 	memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);
 
 	cmd->command = cpu_to_le16(cmd_802_11_scan);
@@ -1812,12 +1718,26 @@
 				     + sizeof(pscan->BSSID)
 				     + pscancfg->tlvbufferlen + S_DS_GEN);
 
-	lbs_pr_debug(1, "SCAN_CMD: command=%x, size=%x, seqnum=%x\n",
-	       cmd->command, cmd->size, cmd->seqnum);
-	LEAVE();
+	lbs_deb_scan("SCAN_CMD: command=%x, size=%x, seqnum=%x\n",
+		     le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
+		     le16_to_cpu(cmd->seqnum));
+
+	lbs_deb_leave(LBS_DEB_ASSOC);
 	return 0;
 }
 
+static inline int is_same_network(struct bss_descriptor *src,
+				  struct bss_descriptor *dst)
+{
+	/* A network is only a duplicate if the channel, BSSID, and ESSID
+	 * all match.  We treat all <hidden> with the same BSSID and channel
+	 * as one network */
+	return ((src->ssid_len == dst->ssid_len) &&
+		(src->channel == dst->channel) &&
+		!compare_ether_addr(src->bssid, dst->bssid) &&
+		!memcmp(src->ssid, dst->ssid, src->ssid_len));
+}
+
 /**
  *  @brief This function handles the command response of scan
  *
@@ -1846,38 +1766,45 @@
 {
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_scan_rsp *pscan;
-	struct bss_descriptor newbssentry;
 	struct mrvlietypes_data *ptlv;
 	struct mrvlietypes_tsftimestamp *ptsftlv;
+	struct bss_descriptor * iter_bss;
+	struct bss_descriptor * safe;
 	u8 *pbssinfo;
 	u16 scanrespsize;
 	int bytesleft;
-	int numintable;
-	int bssIdx;
 	int idx;
 	int tlvbufsize;
-	u64 tsfval;
+	int ret;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_ASSOC);
+
+	/* Prune old entries from scan table */
+	list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) {
+		unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
+		if (time_before(jiffies, stale_time))
+			continue;
+		list_move_tail (&iter_bss->list, &adapter->network_free_list);
+		clear_bss_descriptor(iter_bss);
+	}
 
 	pscan = &resp->params.scanresp;
 
-	if (pscan->nr_sets > MRVDRV_MAX_BSSID_LIST) {
-        lbs_pr_debug(1,
-		       "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
-		       pscan->nr_sets);
-		LEAVE();
-		return -1;
+	if (pscan->nr_sets > MAX_NETWORK_COUNT) {
+		lbs_deb_scan(
+		       "SCAN_RESP: too many scan results (%d, max %d)!!\n",
+		       pscan->nr_sets, MAX_NETWORK_COUNT);
+		ret = -1;
+		goto done;
 	}
 
 	bytesleft = le16_to_cpu(pscan->bssdescriptsize);
-	lbs_pr_debug(1, "SCAN_RESP: bssdescriptsize %d\n", bytesleft);
+	lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
 
 	scanrespsize = le16_to_cpu(resp->size);
-	lbs_pr_debug(1, "SCAN_RESP: returned %d AP before parsing\n",
+	lbs_deb_scan("SCAN_RESP: returned %d AP before parsing\n",
 	       pscan->nr_sets);
 
-	numintable = adapter->numinscantable;
 	pbssinfo = pscan->bssdesc_and_tlvbuffer;
 
 	/* The size of the TLV buffer is equal to the entire command response
@@ -1901,105 +1828,68 @@
 	 *    or as an addition at the end of the table
 	 */
 	for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) {
-		/* Zero out the newbssentry we are about to store info in */
-		memset(&newbssentry, 0x00, sizeof(newbssentry));
+		struct bss_descriptor new;
+		struct bss_descriptor * found = NULL;
+		struct bss_descriptor * oldest = NULL;
 
 		/* Process the data fields and IEs returned for this BSS */
-		if ((InterpretBSSDescriptionWithIE(&newbssentry,
-						   &pbssinfo,
-						   &bytesleft) ==
-		     0)
-		    && CHECK_SSID_IS_VALID(&newbssentry.ssid)) {
-
-            lbs_pr_debug(1,
-			       "SCAN_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
-			       newbssentry.macaddress[0],
-			       newbssentry.macaddress[1],
-			       newbssentry.macaddress[2],
-			       newbssentry.macaddress[3],
-			       newbssentry.macaddress[4],
-			       newbssentry.macaddress[5]);
-
-			/*
-			 * Search the scan table for the same bssid
-			 */
-			for (bssIdx = 0; bssIdx < numintable; bssIdx++) {
-				if (memcmp(newbssentry.macaddress,
-					   adapter->scantable[bssIdx].
-					   macaddress,
-					   sizeof(newbssentry.macaddress)) ==
-				    0) {
-					/*
-					 * If the SSID matches as well, it is a duplicate of
-					 *   this entry.  Keep the bssIdx set to this
-					 *   entry so we replace the old contents in the table
-					 */
-					if ((newbssentry.ssid.ssidlength ==
-					     adapter->scantable[bssIdx].ssid.
-					     ssidlength)
-					    &&
-					    (memcmp
-					     (newbssentry.ssid.ssid,
-					      adapter->scantable[bssIdx].ssid.
-					      ssid,
-					      newbssentry.ssid.ssidlength) ==
-					     0)) {
-                        lbs_pr_debug(1,
-						       "SCAN_RESP: Duplicate of index: %d\n",
-						       bssIdx);
-						break;
-					}
-				}
-			}
-			/*
-			 * If the bssIdx is equal to the number of entries in the table,
-			 *   the new entry was not a duplicate; append it to the scan
-			 *   table
-			 */
-			if (bssIdx == numintable) {
-				/* Range check the bssIdx, keep it limited to the last entry */
-				if (bssIdx == MRVDRV_MAX_BSSID_LIST) {
-					bssIdx--;
-				} else {
-					numintable++;
-				}
-			}
-
-			/*
-			 * If the TSF TLV was appended to the scan results, save the
-			 *   this entries TSF value in the networktsf field.  The
-			 *   networktsf is the firmware's TSF value at the time the
-			 *   beacon or probe response was received.
-			 */
-			if (ptsftlv) {
-				memcpy(&tsfval, &ptsftlv->tsftable[idx],
-				       sizeof(tsfval));
-				tsfval = le64_to_cpu(tsfval);
-
-				memcpy(&newbssentry.networktsf,
-				       &tsfval, sizeof(newbssentry.networktsf));
-			}
-
-			/* Copy the locally created newbssentry to the scan table */
-			memcpy(&adapter->scantable[bssIdx],
-			       &newbssentry,
-			       sizeof(adapter->scantable[bssIdx]));
-
-		} else {
-
-			/* error parsing/interpreting the scan response, skipped */
-			lbs_pr_debug(1, "SCAN_RESP: "
-			       "InterpretBSSDescriptionWithIE returned ERROR\n");
+		memset(&new, 0, sizeof (struct bss_descriptor));
+		if (libertas_process_bss(&new, &pbssinfo, &bytesleft) != 0) {
+			/* error parsing the scan response, skipped */
+			lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
+			continue;
 		}
+
+		/* Try to find this bss in the scan table */
+		list_for_each_entry (iter_bss, &adapter->network_list, list) {
+			if (is_same_network(iter_bss, &new)) {
+				found = iter_bss;
+				break;
+			}
+
+			if ((oldest == NULL) ||
+			    (iter_bss->last_scanned < oldest->last_scanned))
+				oldest = iter_bss;
+		}
+
+		if (found) {
+			/* found, clear it */
+			clear_bss_descriptor(found);
+		} else if (!list_empty(&adapter->network_free_list)) {
+			/* Pull one from the free list */
+			found = list_entry(adapter->network_free_list.next,
+					   struct bss_descriptor, list);
+			list_move_tail(&found->list, &adapter->network_list);
+		} else if (oldest) {
+			/* If there are no more slots, expire the oldest */
+			found = oldest;
+			clear_bss_descriptor(found);
+			list_move_tail(&found->list, &adapter->network_list);
+		} else {
+			continue;
+		}
+
+		lbs_deb_scan("SCAN_RESP: BSSID = " MAC_FMT "\n",
+		       new.bssid[0], new.bssid[1], new.bssid[2],
+		       new.bssid[3], new.bssid[4], new.bssid[5]);
+
+		/*
+		 * If the TSF TLV was appended to the scan results, save the
+		 *   this entries TSF value in the networktsf field.  The
+		 *   networktsf is the firmware's TSF value at the time the
+		 *   beacon or probe response was received.
+		 */
+		if (ptsftlv) {
+			new.networktsf = le64_to_cpup(&ptsftlv->tsftable[idx]);
+		}
+
+		/* Copy the locally created newbssentry to the scan table */
+		memcpy(found, &new, offsetof(struct bss_descriptor, list));
 	}
 
-	lbs_pr_debug(1, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
-	       pscan->nr_sets, numintable - adapter->numinscantable,
-	       numintable);
+	ret = 0;
 
-	/* Update the total number of BSSIDs in the scan table */
-	adapter->numinscantable = numintable;
-
-	LEAVE();
-	return 0;
+done:
+	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+	return ret;
 }
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index 405f4f0..bd019e5 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -51,7 +51,7 @@
     /**
      *  @brief Specific BSSID used to filter scan results in the firmware
      */
-	u8 specificBSSID[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
 
     /**
      *  @brief length of TLVs sent in command starting at tlvBuffer
@@ -91,15 +91,6 @@
  *  @sa libertas_set_user_scan_ioctl
  */
 struct wlan_ioctl_user_scan_cfg {
-
-    /**
-     *  @brief Flag set to keep the previous scan table intact
-     *
-     *  If set, the scan results will accumulate, replacing any previous
-     *   matched entries for a BSS with the new scan data
-     */
-	u8 keeppreviousscan;	//!< Do not erase the existing scan results
-
     /**
      *  @brief BSS type to be sent in the firmware command
      *
@@ -117,15 +108,22 @@
      */
 	u8 numprobes;
 
-    /**
-     *  @brief BSSID filter sent in the firmware command to limit the results
-     */
-	u8 specificBSSID[ETH_ALEN];
+	/**
+	 *  @brief BSSID filter sent in the firmware command to limit the results
+	 */
+	u8 bssid[ETH_ALEN];
 
-    /**
-     *  @brief SSID filter sent in the firmware command to limit the results
-     */
-	char specificSSID[IW_ESSID_MAX_SIZE + 1];
+	/* Clear existing scan results matching this BSSID */
+	u8 clear_bssid;
+
+	/**
+	 *  @brief SSID filter sent in the firmware command to limit the results
+	 */
+	char ssid[IW_ESSID_MAX_SIZE];
+	u8 ssid_len;
+
+	/* Clear existing scan results matching this SSID */
+	u8 clear_ssid;
 
     /**
      *  @brief Variable number (fixed maximum) of channels to scan up
@@ -137,9 +135,10 @@
  *  @brief Structure used to store information for each beacon/probe response
  */
 struct bss_descriptor {
-	u8 macaddress[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
 
-	struct WLAN_802_11_SSID ssid;
+	u8 ssid[IW_ESSID_MAX_SIZE + 1];
+	u8 ssid_len;
 
 	/* WEP encryption requirement */
 	u32 privacy;
@@ -156,15 +155,15 @@
 	u8 mode;
 	u8 libertas_supported_rates[WLAN_SUPPORTED_RATES];
 
-	int extra_ie;
+	__le64 timestamp;	//!< TSF value included in the beacon/probe response
+	unsigned long last_scanned;
 
-	u8 timestamp[8];	//!< TSF value included in the beacon/probe response
 	union ieeetypes_phyparamset phyparamset;
 	union IEEEtypes_ssparamset ssparamset;
 	struct ieeetypes_capinfo cap;
 	u8 datarates[WLAN_SUPPORTED_RATES];
 
-	__le64 networktsf;		//!< TSF timestamp from the current firmware TSF
+	u64 networktsf;		//!< TSF timestamp from the current firmware TSF
 
 	struct ieeetypes_countryinfofullset countryinfo;
 
@@ -172,24 +171,29 @@
 	size_t wpa_ie_len;
 	u8 rsn_ie[MAX_WPA_IE_LEN];
 	size_t rsn_ie_len;
+
+	struct list_head list;
 };
 
-extern int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1,
-		   struct WLAN_802_11_SSID *ssid2);
-extern int libertas_find_SSID_in_list(wlan_adapter * adapter, struct WLAN_802_11_SSID *ssid,
-			  u8 * bssid, u8 mode);
-int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode);
-extern int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode);
+extern int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
 
-int libertas_find_best_network_SSID(wlan_private * priv,
-			struct WLAN_802_11_SSID *pSSID,
-			u8 preferred_mode, u8 *out_mode);
+struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
+			u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
+			int channel);
 
-extern int libertas_send_specific_SSID_scan(wlan_private * priv,
-				struct WLAN_802_11_SSID *prequestedssid,
-				u8 keeppreviousscan);
-extern int libertas_send_specific_BSSID_scan(wlan_private * priv,
-				 u8 * bssid, u8 keeppreviousscan);
+struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter,
+			u8 mode);
+
+extern struct bss_descriptor * libertas_find_bssid_in_list(wlan_adapter * adapter,
+			u8 * bssid, u8 mode);
+
+int libertas_find_best_network_ssid(wlan_private * priv, u8 *out_ssid,
+			u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
+
+extern int libertas_send_specific_ssid_scan(wlan_private * priv, u8 *ssid,
+				u8 ssid_len, u8 clear_ssid);
+extern int libertas_send_specific_bssid_scan(wlan_private * priv,
+				 u8 * bssid, u8 clear_bssid);
 
 extern int libertas_cmd_80211_scan(wlan_private * priv,
 				struct cmd_ds_command *cmd,
@@ -199,7 +203,8 @@
 				struct cmd_ds_command *resp);
 
 int wlan_scan_networks(wlan_private * priv,
-                const struct wlan_ioctl_user_scan_cfg * puserscanin);
+                const struct wlan_ioctl_user_scan_cfg * puserscanin,
+                int full_scan);
 
 struct ifreq;
 
diff --git a/drivers/net/wireless/libertas/thread.h b/drivers/net/wireless/libertas/thread.h
index 207b8a6..b1f34d9 100644
--- a/drivers/net/wireless/libertas/thread.h
+++ b/drivers/net/wireless/libertas/thread.h
@@ -21,11 +21,11 @@
 
 static inline void wlan_deactivate_thread(struct wlan_thread * thr)
 {
-	ENTER();
+	lbs_deb_enter(LBS_DEB_THREAD);
 
 	thr->pid = 0;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_THREAD);
 }
 
 static inline void wlan_create_thread(int (*wlanfunc) (void *),
@@ -36,7 +36,7 @@
 
 static inline int wlan_terminate_thread(struct wlan_thread * thr)
 {
-	ENTER();
+	lbs_deb_enter(LBS_DEB_THREAD);
 
 	/* Check if the thread is active or not */
 	if (!thr->pid) {
@@ -45,7 +45,7 @@
 	}
 	kthread_stop(thr->task);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_THREAD);
 	return 0;
 }
 
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index d4b1347..17c4376 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -5,7 +5,6 @@
 
 #include "hostcmd.h"
 #include "radiotap.h"
-#include "sbi.h"
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
@@ -68,7 +67,7 @@
 	u32 new_rate;
 	u8 *ptr = priv->adapter->tmptxbuf;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_TX);
 
 	if (priv->adapter->surpriseremoved)
 		return -1;
@@ -78,7 +77,7 @@
 			 min_t(unsigned int, skb->len, 100));
 
 	if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
-		lbs_pr_debug(1, "Tx error: Bad skb length %d : %zd\n",
+		lbs_deb_tx("tx err: skb length %d 0 or > %zd\n",
 		       skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
 		ret = -1;
 		goto done;
@@ -86,13 +85,13 @@
 
 	memset(plocaltxpd, 0, sizeof(struct txpd));
 
-	plocaltxpd->tx_packet_length = skb->len;
+	plocaltxpd->tx_packet_length = cpu_to_le16(skb->len);
 
 	/* offset of actual data */
-	plocaltxpd->tx_packet_location = sizeof(struct txpd);
+	plocaltxpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
 
 	/* TxCtrl set by user or default */
-	plocaltxpd->tx_control = adapter->pkttxctrl;
+	plocaltxpd->tx_control = cpu_to_le32(adapter->pkttxctrl);
 
 	p802x_hdr = skb->data;
 	if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
@@ -103,15 +102,16 @@
 		/* set txpd fields from the radiotap header */
 		new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate);
 		if (new_rate != 0) {
-			/* erase tx_control[4:0] */
-			plocaltxpd->tx_control &= ~0x1f;
-			/* write new tx_control[4:0] */
-			plocaltxpd->tx_control |= new_rate;
+			/* use new tx_control[4:0] */
+			new_rate |= (adapter->pkttxctrl & ~0x1f);
+			plocaltxpd->tx_control = cpu_to_le32(new_rate);
 		}
 
 		/* skip the radiotap header */
 		p802x_hdr += sizeof(struct tx_radiotap_hdr);
-		plocaltxpd->tx_packet_length -= sizeof(struct tx_radiotap_hdr);
+		plocaltxpd->tx_packet_length =
+			cpu_to_le16(le16_to_cpu(plocaltxpd->tx_packet_length)
+				    - sizeof(struct tx_radiotap_hdr));
 
 	}
 	/* copy destination address from 802.3 or 802.11 header */
@@ -123,28 +123,28 @@
 	lbs_dbg_hex("txpd", (u8 *) plocaltxpd, sizeof(struct txpd));
 
 	if (IS_MESH_FRAME(skb)) {
-		plocaltxpd->tx_control |= TxPD_MESH_FRAME;
+		plocaltxpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
 	}
 
 	memcpy(ptr, plocaltxpd, sizeof(struct txpd));
 
 	ptr += sizeof(struct txpd);
 
-	lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, plocaltxpd->tx_packet_length);
-	memcpy(ptr, p802x_hdr, plocaltxpd->tx_packet_length);
-	ret = libertas_sbi_host_to_card(priv, MVMS_DAT,
-			       priv->adapter->tmptxbuf,
-			       plocaltxpd->tx_packet_length +
-			       sizeof(struct txpd));
+	lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length));
+	memcpy(ptr, p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length));
+	ret = priv->hw_host_to_card(priv, MVMS_DAT,
+				    priv->adapter->tmptxbuf,
+				    le16_to_cpu(plocaltxpd->tx_packet_length) +
+				    sizeof(struct txpd));
 
 	if (ret) {
-		lbs_pr_debug(1, "Tx error: libertas_sbi_host_to_card failed: 0x%X\n", ret);
+		lbs_deb_tx("tx err: hw_host_to_card returned 0x%X\n", ret);
 		goto done;
 	}
 
-	lbs_pr_debug(1, "SendSinglePacket succeeds\n");
+	lbs_deb_tx("SendSinglePacket succeeds\n");
 
-      done:
+done:
 	if (!ret) {
 		priv->stats.tx_packets++;
 		priv->stats.tx_bytes += skb->len;
@@ -158,7 +158,8 @@
 		   received from FW */
 		skb_orphan(skb);
 		/* stop processing outgoing pkts */
-		netif_stop_queue(priv->wlan_dev.netdev);
+		netif_stop_queue(priv->dev);
+		netif_stop_queue(priv->mesh_dev);
 		/* freeze any packets already in our queues */
 		priv->adapter->TxLockFlag = 1;
 	} else {
@@ -166,7 +167,7 @@
 		priv->adapter->currenttxskb = NULL;
 	}
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
 	return ret;
 }
 
@@ -195,10 +196,13 @@
 
 	WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE);
 	adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb;
-	if (adapter->tx_queue_idx == NR_TX_QUEUE)
-		netif_stop_queue(priv->wlan_dev.netdev);
-	else
-		netif_start_queue(priv->wlan_dev.netdev);
+	if (adapter->tx_queue_idx == NR_TX_QUEUE) {
+		netif_stop_queue(priv->dev);
+		netif_stop_queue(priv->mesh_dev);
+	} else {
+		netif_start_queue(priv->dev);
+		netif_start_queue(priv->mesh_dev);
+	}
 
 	spin_unlock(&adapter->txqueue_lock);
 }
@@ -214,13 +218,12 @@
 {
 	int ret = -1;
 
-	ENTER();
-
+	lbs_deb_enter(LBS_DEB_TX);
 	lbs_dbg_hex("TX Data", skb->data, min_t(unsigned int, skb->len, 100));
 
-	if (priv->wlan_dev.dnld_sent) {
+	if (priv->dnld_sent) {
 		lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n",
-		       priv->wlan_dev.dnld_sent);
+		       priv->dnld_sent);
 		goto done;
 	}
 
@@ -234,7 +237,7 @@
 
 	ret = SendSinglePacket(priv, skb);
 done:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
 	return ret;
 }
 
@@ -280,6 +283,9 @@
 	libertas_upload_rx_packet(priv, adapter->currenttxskb);
 	adapter->currenttxskb = NULL;
 	priv->adapter->TxLockFlag = 0;
-	if (priv->adapter->connect_status == libertas_connected)
-		netif_wake_queue(priv->wlan_dev.netdev);
+	if (priv->adapter->connect_status == libertas_connected) {
+		netif_wake_queue(priv->dev);
+		netif_wake_queue(priv->mesh_dev);
+	}
 }
+EXPORT_SYMBOL_GPL(libertas_send_tx_feedback);
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index 09d62f8..028e2f3 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -5,6 +5,7 @@
 #define _WLAN_TYPES_
 
 #include <linux/if_ether.h>
+#include <asm/byteorder.h>
 
 /** IEEE type definitions  */
 enum ieeetypes_elementid {
@@ -29,9 +30,30 @@
 	EXTRA_IE = 133,
 } __attribute__ ((packed));
 
+#ifdef __BIG_ENDIAN
 #define CAPINFO_MASK	(~(0xda00))
+#else
+#define CAPINFO_MASK	(~(0x00da))
+#endif
 
 struct ieeetypes_capinfo {
+#ifdef __BIG_ENDIAN_BITFIELD
+	u8 chanagility:1;
+	u8 pbcc:1;
+	u8 shortpreamble:1;
+	u8 privacy:1;
+	u8 cfpollrqst:1;
+	u8 cfpollable:1;
+	u8 ibss:1;
+	u8 ess:1;
+	u8 rsrvd1:2;
+	u8 dsssofdm:1;
+	u8 rsvrd2:1;
+	u8 apsd:1;
+	u8 shortslottime:1;
+	u8 rsrvd3:1;
+	u8 spectrummgmt:1;
+#else
 	u8 ess:1;
 	u8 ibss:1;
 	u8 cfpollable:1;
@@ -47,6 +69,7 @@
 	u8 rsvrd2:1;
 	u8 dsssofdm:1;
 	u8 rsrvd1:2;
+#endif
 } __attribute__ ((packed));
 
 struct ieeetypes_cfparamset {
@@ -54,15 +77,15 @@
 	u8 len;
 	u8 cfpcnt;
 	u8 cfpperiod;
-	u16 cfpmaxduration;
-	u16 cfpdurationremaining;
+	__le16 cfpmaxduration;
+	__le16 cfpdurationremaining;
 } __attribute__ ((packed));
 
 
 struct ieeetypes_ibssparamset {
 	u8 elementid;
 	u8 len;
-	u16 atimwindow;
+	__le16 atimwindow;
 } __attribute__ ((packed));
 
 union IEEEtypes_ssparamset {
@@ -73,7 +96,7 @@
 struct ieeetypes_fhparamset {
 	u8 elementid;
 	u8 len;
-	u16 dwelltime;
+	__le16 dwelltime;
 	u8 hopset;
 	u8 hoppattern;
 	u8 hopindex;
@@ -92,8 +115,8 @@
 
 struct ieeetypes_assocrsp {
 	struct ieeetypes_capinfo capability;
-	u16 statuscode;
-	u16 aid;
+	__le16 statuscode;
+	__le16 aid;
 	u8 iebuffer[1];
 } __attribute__ ((packed));
 
@@ -138,8 +161,8 @@
 
 /** TLV related data structures*/
 struct mrvlietypesheader {
-	u16 type;
-	u16 len;
+	__le16 type;
+	__le16 len;
 } __attribute__ ((packed));
 
 struct mrvlietypes_data {
@@ -164,17 +187,23 @@
 } __attribute__ ((packed));
 
 struct chanscanmode {
+#ifdef __BIG_ENDIAN_BITFIELD
+	u8 reserved_2_7:6;
+	u8 disablechanfilt:1;
+	u8 passivescan:1;
+#else
 	u8 passivescan:1;
 	u8 disablechanfilt:1;
 	u8 reserved_2_7:6;
+#endif
 } __attribute__ ((packed));
 
 struct chanscanparamset {
 	u8 radiotype;
 	u8 channumber;
 	struct chanscanmode chanscanmode;
-	u16 minscantime;
-	u16 maxscantime;
+	__le16 minscantime;
+	__le16 maxscantime;
 } __attribute__ ((packed));
 
 struct mrvlietypes_chanlistparamset {
@@ -185,12 +214,12 @@
 struct cfparamset {
 	u8 cfpcnt;
 	u8 cfpperiod;
-	u16 cfpmaxduration;
-	u16 cfpdurationremaining;
+	__le16 cfpmaxduration;
+	__le16 cfpdurationremaining;
 } __attribute__ ((packed));
 
 struct ibssparamset {
-	u16 atimwindow;
+	__le16 atimwindow;
 } __attribute__ ((packed));
 
 struct mrvlietypes_ssparamset {
@@ -202,7 +231,7 @@
 } __attribute__ ((packed));
 
 struct fhparamset {
-	u16 dwelltime;
+	__le16 dwelltime;
 	u8 hopset;
 	u8 hoppattern;
 	u8 hopindex;
@@ -263,17 +292,17 @@
 
 struct mrvlietypes_numprobes {
 	struct mrvlietypesheader header;
-	u16 numprobes;
+	__le16 numprobes;
 } __attribute__ ((packed));
 
 struct mrvlietypes_bcastprobe {
 	struct mrvlietypesheader header;
-	u16 bcastprobe;
+	__le16 bcastprobe;
 } __attribute__ ((packed));
 
 struct mrvlietypes_numssidprobe {
 	struct mrvlietypesheader header;
-	u16 numssidprobe;
+	__le16 numssidprobe;
 } __attribute__ ((packed));
 
 struct led_pin {
diff --git a/drivers/net/wireless/libertas/version.h b/drivers/net/wireless/libertas/version.h
deleted file mode 100644
index 8b13789..0000000
--- a/drivers/net/wireless/libertas/version.h
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 69f52b6..2fcc3bf 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -22,6 +22,14 @@
 
 
 /**
+ * the rates supported by the card
+ */
+static u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] =
+    { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
+      0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
+};
+
+/**
  *  @brief Convert mw value to dbm value
  *
  *  @param mw	   the value of mw
@@ -102,8 +110,8 @@
 	}
 
 	if (!cfp && channel)
-		lbs_pr_debug(1, "libertas_find_cfp_by_band_and_channel(): cannot find "
-		       "cfp by band %d & channel %d\n", band, channel);
+		lbs_deb_wext("libertas_find_cfp_by_band_and_channel: can't find "
+		       "cfp by band %d / channel %d\n", band, channel);
 
 	return cfp;
 }
@@ -143,113 +151,12 @@
 	}
 
 	if (!cfp && freq)
-		lbs_pr_debug(1, "find_cfp_by_band_and_freql(): cannot find cfp by "
-		       "band %d & freq %d\n", band, freq);
+		lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by "
+		       "band %d / freq %d\n", band, freq);
 
 	return cfp;
 }
 
-static int updatecurrentchannel(wlan_private * priv)
-{
-	int ret;
-
-	/*
-	 ** the channel in f/w could be out of sync, get the current channel
-	 */
-	ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
-				    cmd_opt_802_11_rf_channel_get,
-				    cmd_option_waitforrsp, 0, NULL);
-
-	lbs_pr_debug(1, "Current channel = %d\n",
-	       priv->adapter->curbssparams.channel);
-
-	return ret;
-}
-
-static int setcurrentchannel(wlan_private * priv, int channel)
-{
-	lbs_pr_debug(1, "Set channel = %d\n", channel);
-
-	/*
-	 **  Current channel is not set to adhocchannel requested, set channel
-	 */
-	return (libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
-				      cmd_opt_802_11_rf_channel_set,
-				      cmd_option_waitforrsp, 0, &channel));
-}
-
-static int changeadhocchannel(wlan_private * priv, int channel)
-{
-	int ret = 0;
-	wlan_adapter *adapter = priv->adapter;
-
-	adapter->adhocchannel = channel;
-
-	updatecurrentchannel(priv);
-
-	if (adapter->curbssparams.channel == adapter->adhocchannel) {
-		/* adhocchannel is set to the current channel already */
-		LEAVE();
-		return 0;
-	}
-
-	lbs_pr_debug(1, "Updating channel from %d to %d\n",
-	       adapter->curbssparams.channel, adapter->adhocchannel);
-
-	setcurrentchannel(priv, adapter->adhocchannel);
-
-	updatecurrentchannel(priv);
-
-	if (adapter->curbssparams.channel != adapter->adhocchannel) {
-		lbs_pr_debug(1, "failed to updated channel to %d, channel = %d\n",
-		       adapter->adhocchannel, adapter->curbssparams.channel);
-		LEAVE();
-		return -1;
-	}
-
-	if (adapter->connect_status == libertas_connected) {
-		int i;
-		struct WLAN_802_11_SSID curadhocssid;
-
-		lbs_pr_debug(1, "channel Changed while in an IBSS\n");
-
-		/* Copy the current ssid */
-		memcpy(&curadhocssid, &adapter->curbssparams.ssid,
-		       sizeof(struct WLAN_802_11_SSID));
-
-		/* Exit Adhoc mode */
-		lbs_pr_debug(1, "In changeadhocchannel(): Sending Adhoc Stop\n");
-		ret = libertas_stop_adhoc_network(priv);
-
-		if (ret) {
-			LEAVE();
-			return ret;
-		}
-		/* Scan for the network, do not save previous results.  Stale
-		 *   scan data will cause us to join a non-existant adhoc network
-		 */
-		libertas_send_specific_SSID_scan(priv, &curadhocssid, 0);
-
-		// find out the BSSID that matches the current SSID
-		i = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
-				   IW_MODE_ADHOC);
-
-		if (i >= 0) {
-			lbs_pr_debug(1, "SSID found at %d in List,"
-			       "so join\n", i);
-			libertas_join_adhoc_network(priv, &adapter->scantable[i]);
-		} else {
-			// else send START command
-			lbs_pr_debug(1, "SSID not found in list, "
-			       "so creating adhoc with ssid = %s\n",
-			       curadhocssid.ssid);
-			libertas_start_adhoc_network(priv, &curadhocssid);
-		}		// end of else (START command)
-	}
-
-	LEAVE();
-	return 0;
-}
 
 /**
  *  @brief Set Radio On/OFF
@@ -263,10 +170,10 @@
 	int ret = 0;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (adapter->radioon != option) {
-		lbs_pr_debug(1, "Switching %s the Radio\n", option ? "On" : "Off");
+		lbs_deb_wext("switching radio %s\n", option ? "on" : "off");
 		adapter->radioon = option;
 
 		ret = libertas_prepare_and_send_command(priv,
@@ -275,7 +182,7 @@
 					    cmd_option_waitforrsp, 0, NULL);
 	}
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -312,15 +219,15 @@
 {
 	int k = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (adapter->connect_status != libertas_connected) {
 		if (adapter->mode == IW_MODE_INFRA) {
-			lbs_pr_debug(1, "Infra\n");
+			lbs_deb_wext("infra\n");
 			k = copyrates(rates, k, libertas_supported_rates,
 				      sizeof(libertas_supported_rates));
 		} else {
-			lbs_pr_debug(1, "Adhoc G\n");
+			lbs_deb_wext("Adhoc G\n");
 			k = copyrates(rates, k, libertas_adhoc_rates_g,
 				      sizeof(libertas_adhoc_rates_g));
 		}
@@ -329,8 +236,7 @@
 			      adapter->curbssparams.numofrates);
 	}
 
-	LEAVE();
-
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", k);
 	return k;
 }
 
@@ -342,7 +248,7 @@
 	char mrvl[6] = { "MRVL-" };
 	int cnt;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	strcpy(cwrq, mrvl);
 
@@ -360,8 +266,7 @@
 	}
 	*cwrq = '\0';
 
-	LEAVE();
-
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -372,14 +277,14 @@
 	wlan_adapter *adapter = priv->adapter;
 	struct chan_freq_power *cfp;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	cfp = libertas_find_cfp_by_band_and_channel(adapter, 0,
 					   adapter->curbssparams.channel);
 
 	if (!cfp) {
 		if (adapter->curbssparams.channel)
-			lbs_pr_debug(1, "Invalid channel=%d\n",
+			lbs_deb_wext("invalid channel %d\n",
 			       adapter->curbssparams.channel);
 		return -EINVAL;
 	}
@@ -387,9 +292,8 @@
 	fwrq->m = (long)cfp->freq * 100000;
 	fwrq->e = 1;
 
-	lbs_pr_debug(1, "freq=%u\n", fwrq->m);
-
-	LEAVE();
+	lbs_deb_wext("freq %u\n", fwrq->m);
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -399,7 +303,7 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (adapter->connect_status == libertas_connected) {
 		memcpy(awrq->sa_data, adapter->curbssparams.bssid, ETH_ALEN);
@@ -408,7 +312,7 @@
 	}
 	awrq->sa_family = ARPHRD_ETHER;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -418,7 +322,7 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	/*
 	 * Check the size of the string
@@ -433,7 +337,7 @@
 	memcpy(adapter->nodename, extra, dwrq->length);
 	mutex_unlock(&adapter->lock);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -443,7 +347,7 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	/*
 	 * Get the Nick Name saved
@@ -464,19 +368,43 @@
 	 */
 	dwrq->length = strlen(extra) + 1;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
+static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_point *dwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *adapter = priv->adapter;
+
+	lbs_deb_enter(LBS_DEB_WEXT);
+
+	/* Use nickname to indicate that mesh is on */
+
+	if (adapter->connect_status == libertas_connected) {
+		strncpy(extra, "Mesh", 12);
+		extra[12] = '\0';
+		dwrq->length = strlen(extra) + 1;
+	}
+
+	else {
+		extra[0] = '\0';
+		dwrq->length = 1 ;
+	}
+
+	lbs_deb_leave(LBS_DEB_WEXT);
+	return 0;
+}
 static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
 			struct iw_param *vwrq, char *extra)
 {
 	int ret = 0;
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
-	int rthr = vwrq->value;
+	u32 rthr = vwrq->value;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (vwrq->disabled) {
 		adapter->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
@@ -490,7 +418,7 @@
 				    cmd_act_set, cmd_option_waitforrsp,
 				    OID_802_11_RTS_THRESHOLD, &rthr);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -501,35 +429,34 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	adapter->rtsthsd = 0;
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib,
 				    cmd_act_get, cmd_option_waitforrsp,
 				    OID_802_11_RTS_THRESHOLD, NULL);
-	if (ret) {
-		LEAVE();
-		return ret;
-	}
+	if (ret)
+		goto out;
 
 	vwrq->value = adapter->rtsthsd;
 	vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
 			  || (vwrq->value > MRVDRV_RTS_MAX_VALUE));
 	vwrq->fixed = 1;
 
-	LEAVE();
-	return 0;
+out:
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
 			 struct iw_param *vwrq, char *extra)
 {
 	int ret = 0;
-	int fthr = vwrq->value;
+	u32 fthr = vwrq->value;
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (vwrq->disabled) {
 		adapter->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
@@ -543,7 +470,8 @@
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib,
 				    cmd_act_set, cmd_option_waitforrsp,
 				    OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
-	LEAVE();
+
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -554,24 +482,23 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	adapter->fragthsd = 0;
 	ret = libertas_prepare_and_send_command(priv,
 				    cmd_802_11_snmp_mib,
 				    cmd_act_get, cmd_option_waitforrsp,
 				    OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
-	if (ret) {
-		LEAVE();
-		return ret;
-	}
+	if (ret)
+		goto out;
 
 	vwrq->value = adapter->fragthsd;
 	vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
 			  || (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
 	vwrq->fixed = 1;
 
-	LEAVE();
+out:
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -581,11 +508,23 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	*uwrq = adapter->mode;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_WEXT);
+	return 0;
+}
+
+static int mesh_wlan_get_mode(struct net_device *dev,
+		              struct iw_request_info *info, u32 * uwrq,
+			      char *extra)
+{
+	lbs_deb_enter(LBS_DEB_WEXT);
+
+	*uwrq = IW_MODE_REPEAT ;
+
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -597,19 +536,17 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	ret = libertas_prepare_and_send_command(priv,
 				    cmd_802_11_rf_tx_power,
 				    cmd_act_tx_power_opt_get,
 				    cmd_option_waitforrsp, 0, NULL);
 
-	if (ret) {
-		LEAVE();
-		return ret;
-	}
+	if (ret)
+		goto out;
 
-	lbs_pr_debug(1, "TXPOWER GET %d dbm.\n", adapter->txpowerlevel);
+	lbs_deb_wext("tx power level %d dbm\n", adapter->txpowerlevel);
 	vwrq->value = adapter->txpowerlevel;
 	vwrq->fixed = 1;
 	if (adapter->radioon) {
@@ -619,8 +556,9 @@
 		vwrq->disabled = 1;
 	}
 
-	LEAVE();
-	return 0;
+out:
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
@@ -630,7 +568,7 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (vwrq->flags == IW_RETRY_LIMIT) {
 		/* The MAC has a 4-bit Total_Tx_Count register
@@ -648,16 +586,15 @@
 					    cmd_option_waitforrsp,
 					    OID_802_11_TX_RETRYCOUNT, NULL);
 
-		if (ret) {
-			LEAVE();
-			return ret;
-		}
+		if (ret)
+			goto out;
 	} else {
 		return -EOPNOTSUPP;
 	}
 
-	LEAVE();
-	return 0;
+out:
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
@@ -667,16 +604,16 @@
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
+
 	adapter->txretrycount = 0;
 	ret = libertas_prepare_and_send_command(priv,
 				    cmd_802_11_snmp_mib,
 				    cmd_act_get, cmd_option_waitforrsp,
 				    OID_802_11_TX_RETRYCOUNT, NULL);
-	if (ret) {
-		LEAVE();
-		return ret;
-	}
+	if (ret)
+		goto out;
+
 	vwrq->disabled = 0;
 	if (!vwrq->flags) {
 		vwrq->flags = IW_RETRY_LIMIT;
@@ -684,8 +621,9 @@
 		vwrq->value = adapter->txretrycount - 1;
 	}
 
-	LEAVE();
-	return 0;
+out:
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 static inline void sort_channels(struct iw_freq *freq, int num)
@@ -739,7 +677,7 @@
 
 	u8 flag = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	dwrq->length = sizeof(struct iw_range);
 	memset(range, 0, sizeof(struct iw_range));
@@ -755,7 +693,7 @@
 		range->bitrate[i] = (rates[i] & 0x7f) * 500000;
 	}
 	range->num_bitrates = i;
-	lbs_pr_debug(1, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES,
+	lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES,
 	       range->num_bitrates);
 
 	range->num_frequency = 0;
@@ -768,18 +706,17 @@
 		    &adapter->parsed_region_chan;
 
 		if (parsed_region_chan == NULL) {
-			lbs_pr_debug(1, "11D:parsed_region_chan is NULL\n");
-			LEAVE();
-			return 0;
+			lbs_deb_wext("11d: parsed_region_chan is NULL\n");
+			goto out;
 		}
 		band = parsed_region_chan->band;
-		lbs_pr_debug(1, "band=%d NoOfChan=%d\n", band,
+		lbs_deb_wext("band %d, nr_char %d\n", band,
 		       parsed_region_chan->nr_chan);
 
 		for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
 		     && (i < parsed_region_chan->nr_chan); i++) {
 			chan_no = parsed_region_chan->chanpwr[i].chan;
-			lbs_pr_debug(1, "chan_no=%d\n", chan_no);
+			lbs_deb_wext("chan_no %d\n", chan_no);
 			range->freq[range->num_frequency].i = (long)chan_no;
 			range->freq[range->num_frequency].m =
 			    (long)libertas_chan_2_freq(chan_no, band) * 100000;
@@ -808,7 +745,7 @@
 		}
 	}
 
-	lbs_pr_debug(1, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n",
+	lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
 	       IW_MAX_FREQUENCIES, range->num_frequency);
 
 	range->num_channels = range->num_frequency;
@@ -903,7 +840,8 @@
 		                  | IW_ENC_CAPA_CIPHER_CCMP;
 	}
 
-	LEAVE();
+out:
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -913,7 +851,7 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	/* PS is currently supported only in Infrastructure mode
 	 * Remove this check if it is to be supported in IBSS mode also
@@ -929,11 +867,11 @@
 	}
 
 	if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
-		lbs_pr_debug(1,
-		       "Setting power timeout command is not supported\n");
+		lbs_deb_wext(
+		       "setting power timeout is not supported\n");
 		return -EINVAL;
 	} else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
-		lbs_pr_debug(1, "Setting power period command is not supported\n");
+		lbs_deb_wext("setting power period not supported\n");
 		return -EINVAL;
 	}
 
@@ -947,7 +885,7 @@
 		libertas_ps_sleep(priv, cmd_option_waitforrsp);
 	}
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -958,154 +896,23 @@
 	wlan_adapter *adapter = priv->adapter;
 	int mode;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	mode = adapter->psmode;
 
 	if ((vwrq->disabled = (mode == wlan802_11powermodecam))
-	    || adapter->connect_status == libertas_disconnected) {
-		LEAVE();
-		return 0;
+	    || adapter->connect_status == libertas_disconnected)
+	{
+		goto out;
 	}
 
 	vwrq->value = 0;
 
-	LEAVE();
+out:
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
-/*
- * iwpriv settable callbacks
- */
-
-static const iw_handler wlan_private_handler[] = {
-	NULL,			/* SIOCIWFIRSTPRIV */
-};
-
-static const struct iw_priv_args wlan_private_args[] = {
-	/*
-	 * { cmd, set_args, get_args, name }
-	 */
-	/* Using iwpriv sub-command feature */
-	{
-	 WLAN_SETONEINT_GETNONE,	/* IOCTL: 24 */
-	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 IW_PRIV_TYPE_NONE,
-	 ""},
-	{
-	 WLANSETREGION,
-	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 IW_PRIV_TYPE_NONE,
-	 "setregioncode"},
-	{
-	 WLAN_SUBCMD_MESH_SET_TTL,
-	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 IW_PRIV_TYPE_NONE,
-	 "mesh_set_ttl"},
-	{
-	 WLAN_SETNONE_GETONEINT,
-	 IW_PRIV_TYPE_NONE,
-	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 ""},
-	{
-	 WLANGETREGION,
-	 IW_PRIV_TYPE_NONE,
-	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 "getregioncode"},
-	{
-	 WLAN_SUBCMD_FWT_CLEANUP,
-	 IW_PRIV_TYPE_NONE,
-	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 "fwt_cleanup"},
-	{
-	 WLAN_SUBCMD_FWT_TIME,
-	 IW_PRIV_TYPE_NONE,
-	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 "fwt_time"},
-	{
-	 WLAN_SUBCMD_MESH_GET_TTL,
-	 IW_PRIV_TYPE_NONE,
-	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 "mesh_get_ttl"},
-	{
-	 WLAN_SETNONE_GETNONE,
-	 IW_PRIV_TYPE_NONE,
-	 IW_PRIV_TYPE_NONE,
-	 ""},
-	{
-	 WLAN_SUBCMD_FWT_RESET,
-	 IW_PRIV_TYPE_NONE,
-	 IW_PRIV_TYPE_NONE,
-	 "fwt_reset"},
-	{
-	 WLAN_SUBCMD_BT_RESET,
-	 IW_PRIV_TYPE_NONE,
-	 IW_PRIV_TYPE_NONE,
-	 "bt_reset"},
-	{
-	 WLAN_SET128CHAR_GET128CHAR,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 ""},
-	/* BT Management */
-	{
-	 WLAN_SUBCMD_BT_ADD,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "bt_add"},
-	{
-	 WLAN_SUBCMD_BT_DEL,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "bt_del"},
-	{
-	 WLAN_SUBCMD_BT_LIST,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "bt_list"},
-	/* FWT Management */
-	{
-	 WLAN_SUBCMD_FWT_ADD,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "fwt_add"},
-	{
-	 WLAN_SUBCMD_FWT_DEL,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "fwt_del"},
-	{
-	 WLAN_SUBCMD_FWT_LOOKUP,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "fwt_lookup"},
-	{
-	 WLAN_SUBCMD_FWT_LIST_NEIGHBOR,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "fwt_list_neigh"},
-	{
-	 WLAN_SUBCMD_FWT_LIST,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "fwt_list"},
-	{
-	 WLAN_SUBCMD_FWT_LIST_ROUTE,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 IW_PRIV_TYPE_CHAR | 128,
-	 "fwt_list_route"},
-	{
-	 WLAN_SET_GET_SIXTEEN_INT,
-	 IW_PRIV_TYPE_INT | 16,
-	 IW_PRIV_TYPE_INT | 16,
-	 ""},
-	{
-	 WLAN_LED_GPIO_CTRL,
-	 IW_PRIV_TYPE_INT | 16,
-	 IW_PRIV_TYPE_INT | 16,
-	 "ledgpio"},
-};
-
 static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
 {
 	enum {
@@ -1125,7 +932,7 @@
 	u8 rssi;
 	u32 tx_retries;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	priv->wstats.status = adapter->mode;
 
@@ -1145,8 +952,8 @@
 		    CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
 	}
 
-	lbs_pr_debug(1, "Signal Level = %#x\n", priv->wstats.qual.level);
-	lbs_pr_debug(1, "Noise = %#x\n", priv->wstats.qual.noise);
+	lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
+	lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
 
 	rssi = priv->wstats.qual.level - priv->wstats.qual.noise;
 	if (rssi < 15)
@@ -1166,7 +973,7 @@
 	/* Quality by TX errors */
 	priv->wstats.discard.retries = priv->stats.tx_errors;
 
-	tx_retries = adapter->logmsg.retry;
+	tx_retries = le16_to_cpu(adapter->logmsg.retry);
 
 	if (tx_retries > 75)
 		tx_qual = (90 - tx_retries) * POOR / 15;
@@ -1182,10 +989,10 @@
 		    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
 	quality = min(quality, tx_qual);
 
-	priv->wstats.discard.code = adapter->logmsg.wepundecryptable;
-	priv->wstats.discard.fragment = adapter->logmsg.fcserror;
+	priv->wstats.discard.code = le16_to_cpu(adapter->logmsg.wepundecryptable);
+	priv->wstats.discard.fragment = le16_to_cpu(adapter->logmsg.rxfrag);
 	priv->wstats.discard.retries = tx_retries;
-	priv->wstats.discard.misc = adapter->logmsg.ackfailure;
+	priv->wstats.discard.misc = le16_to_cpu(adapter->logmsg.ackfailure);
 
 	/* Calculate quality */
 	priv->wstats.qual.qual = max(quality, (u32)100);
@@ -1209,7 +1016,7 @@
 		    IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
 	}
 
-	LEAVE ();
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return &priv->wstats;
 
 
@@ -1218,81 +1025,59 @@
 static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
 		  struct iw_freq *fwrq, char *extra)
 {
-	int ret = 0;
+	int ret = -EINVAL;
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
-	int rc = -EINPROGRESS;	/* Call commit handler */
 	struct chan_freq_power *cfp;
+	struct assoc_request * assoc_req;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
-	/*
-	 * If setting by frequency, convert to a channel
-	 */
+	mutex_lock(&adapter->lock);
+	assoc_req = wlan_get_association_request(adapter);
+	if (!assoc_req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* If setting by frequency, convert to a channel */
 	if (fwrq->e == 1) {
-
 		long f = fwrq->m / 100000;
-		int c = 0;
 
 		cfp = find_cfp_by_band_and_freq(adapter, 0, f);
 		if (!cfp) {
-			lbs_pr_debug(1, "Invalid freq=%ld\n", f);
-			return -EINVAL;
+			lbs_deb_wext("invalid freq %ld\n", f);
+			goto out;
 		}
 
-		c = (int)cfp->channel;
-
-		if (c < 0)
-			return -EINVAL;
-
 		fwrq->e = 0;
-		fwrq->m = c;
+		fwrq->m = (int) cfp->channel;
 	}
 
-	/*
-	 * Setting by channel number
-	 */
+	/* Setting by channel number */
 	if (fwrq->m > 1000 || fwrq->e > 0) {
-		rc = -EOPNOTSUPP;
-	} else {
-		int channel = fwrq->m;
-
-		cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, channel);
-		if (!cfp) {
-			rc = -EINVAL;
-		} else {
-			if (adapter->mode == IW_MODE_ADHOC) {
-				rc = changeadhocchannel(priv, channel);
-				/*  If station is WEP enabled, send the
-				 *  command to set WEP in firmware
-				 */
-				if (adapter->secinfo.wep_enabled) {
-					lbs_pr_debug(1, "set_freq: WEP enabled\n");
-					ret = libertas_prepare_and_send_command(priv,
-								    cmd_802_11_set_wep,
-								    cmd_act_add,
-								    cmd_option_waitforrsp,
-								    0,
-								    NULL);
-
-					if (ret) {
-						LEAVE();
-						return ret;
-					}
-
-					adapter->currentpacketfilter |=
-					    cmd_act_mac_wep_enable;
-
-					libertas_set_mac_packet_filter(priv);
-				}
-			} else {
-				rc = -EOPNOTSUPP;
-			}
-		}
+		goto out;
 	}
 
-	LEAVE();
-	return rc;
+	cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m);
+	if (!cfp) {
+		goto out;
+	}
+
+	assoc_req->channel = fwrq->m;
+	ret = 0;
+
+out:
+	if (ret == 0) {
+		set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
+		wlan_postpone_association_work(priv);
+	} else {
+		wlan_cancel_association_work(priv);
+	}
+	mutex_unlock(&adapter->lock);
+
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 /**
@@ -1338,9 +1123,9 @@
 	u8 rates[WLAN_SUPPORTED_RATES];
 	u8 *rate;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
-	lbs_pr_debug(1, "Vwrq->value = %d\n", vwrq->value);
+	lbs_deb_wext("vwrq->value %d\n", vwrq->value);
 
 	if (vwrq->value == -1) {
 		action = cmd_act_set_tx_auto;	// Auto
@@ -1357,15 +1142,15 @@
 		get_active_data_rates(adapter, rates);
 		rate = rates;
 		while (*rate) {
-			lbs_pr_debug(1, "Rate=0x%X  Wanted=0x%X\n", *rate,
+			lbs_deb_wext("rate=0x%X, wanted data_rate 0x%X\n", *rate,
 			       data_rate);
 			if ((*rate & 0x7f) == (data_rate & 0x7f))
 				break;
 			rate++;
 		}
 		if (!*rate) {
-			lbs_pr_alert( "The fixed data rate 0x%X is out "
-			       "of range.\n", data_rate);
+			lbs_pr_alert("fixed data rate 0x%X out "
+			       "of range\n", data_rate);
 			return -EINVAL;
 		}
 
@@ -1377,7 +1162,7 @@
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_data_rate,
 				    action, cmd_option_waitforrsp, 0, NULL);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -1387,7 +1172,7 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (adapter->is_datarate_auto) {
 		vwrq->fixed = 0;
@@ -1397,7 +1182,7 @@
 
 	vwrq->value = adapter->datarate * 500000;
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -1409,12 +1194,12 @@
 	wlan_adapter *adapter = priv->adapter;
 	struct assoc_request * assoc_req;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (   (*uwrq != IW_MODE_ADHOC)
 	    && (*uwrq != IW_MODE_INFRA)
 	    && (*uwrq != IW_MODE_AUTO)) {
-		lbs_pr_debug(1, "Invalid mode: 0x%x\n", *uwrq);
+		lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq);
 		ret = -EINVAL;
 		goto out;
 	}
@@ -1428,12 +1213,12 @@
 		assoc_req->mode = *uwrq;
 		set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
 		wlan_postpone_association_work(priv);
-		lbs_pr_debug(1, "Switching to mode: 0x%x\n", *uwrq);
+		lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
 	}
 	mutex_unlock(&adapter->lock);
 
 out:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -1455,9 +1240,9 @@
 	wlan_adapter *adapter = priv->adapter;
 	int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
-	lbs_pr_debug(1, "flags=0x%x index=%d length=%d wep_tx_keyidx=%d\n",
+	lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n",
 	       dwrq->flags, index, dwrq->length, adapter->wep_tx_keyidx);
 
 	dwrq->flags = 0;
@@ -1513,13 +1298,13 @@
 
 	dwrq->flags |= IW_ENCODE_NOKEY;
 
-	lbs_pr_debug(1, "key:%02x:%02x:%02x:%02x:%02x:%02x keylen=%d\n",
+	lbs_deb_wext("key: " MAC_FMT ", keylen %d\n",
 	       extra[0], extra[1], extra[2],
 	       extra[3], extra[4], extra[5], dwrq->length);
 
-	lbs_pr_debug(1, "Return flags=0x%x\n", dwrq->flags);
+	lbs_deb_wext("return flags 0x%x\n", dwrq->flags);
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -1539,20 +1324,21 @@
 			    u16 index,
 			    int set_tx_key)
 {
+	int ret = 0;
 	struct WLAN_802_11_KEY *pkey;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	/* Paranoid validation of key index */
 	if (index > 3) {
-		LEAVE();
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	/* validate max key length */
 	if (key_length > KEY_LEN_WEP_104) {
-		LEAVE();
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	pkey = &assoc_req->wep_keys[index];
@@ -1570,17 +1356,18 @@
 	if (set_tx_key) {
 		/* Ensure the chosen key is valid */
 		if (!pkey->len) {
-			lbs_pr_debug(1, "key not set, so cannot enable it\n");
-			LEAVE();
-			return -EINVAL;
+			lbs_deb_wext("key not set, so cannot enable it\n");
+			ret = -EINVAL;
+			goto out;
 		}
 		assoc_req->wep_tx_keyidx = index;
 	}
 
 	assoc_req->secinfo.wep_enabled = 1;
 
-	LEAVE();
-	return 0;
+out:
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 static int validate_key_index(u16 def_index, u16 raw_index,
@@ -1605,6 +1392,8 @@
 {
 	int i;
 
+	lbs_deb_enter(LBS_DEB_WEXT);
+
 	/* Set Open System auth mode */
 	assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
 
@@ -1615,6 +1404,27 @@
 
 	set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
 	set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
+
+	lbs_deb_leave(LBS_DEB_WEXT);
+}
+
+static void disable_wpa(struct assoc_request *assoc_req)
+{
+	lbs_deb_enter(LBS_DEB_WEXT);
+
+	memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct WLAN_802_11_KEY));
+	assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
+	set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
+
+	memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct WLAN_802_11_KEY));
+	assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
+	set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
+
+	assoc_req->secinfo.WPAenabled = 0;
+	assoc_req->secinfo.WPA2enabled = 0;
+	set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
+
+	lbs_deb_leave(LBS_DEB_WEXT);
 }
 
 /**
@@ -1636,7 +1446,7 @@
 	struct assoc_request * assoc_req;
 	u16 is_default = 0, index = 0, set_tx_key = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	mutex_lock(&adapter->lock);
 	assoc_req = wlan_get_association_request(adapter);
@@ -1647,6 +1457,7 @@
 
 	if (dwrq->flags & IW_ENCODE_DISABLED) {
 		disable_wep (assoc_req);
+		disable_wpa (assoc_req);
 		goto out;
 	}
 
@@ -1688,7 +1499,7 @@
 	}
 	mutex_unlock(&adapter->lock);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -1712,7 +1523,7 @@
 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 	int index, max_key_len;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	max_key_len = dwrq->length - sizeof(*ext);
 	if (max_key_len < 0)
@@ -1748,6 +1559,7 @@
 		if (   adapter->secinfo.wep_enabled
 		    && !adapter->secinfo.WPAenabled
 		    && !adapter->secinfo.WPA2enabled) {
+			/* WEP */
 			ext->alg = IW_ENCODE_ALG_WEP;
 			ext->key_len = adapter->wep_keys[index].len;
 			key = &adapter->wep_keys[index].key[0];
@@ -1755,8 +1567,27 @@
 		           && (adapter->secinfo.WPAenabled ||
 		               adapter->secinfo.WPA2enabled)) {
 			/* WPA */
-			ext->alg = IW_ENCODE_ALG_TKIP;
-			ext->key_len = 0;
+			struct WLAN_802_11_KEY * pkey = NULL;
+
+			if (   adapter->wpa_mcast_key.len
+			    && (adapter->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
+				pkey = &adapter->wpa_mcast_key;
+			else if (   adapter->wpa_unicast_key.len
+			         && (adapter->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
+				pkey = &adapter->wpa_unicast_key;
+
+			if (pkey) {
+				if (pkey->type == KEY_TYPE_ID_AES) {
+					ext->alg = IW_ENCODE_ALG_CCMP;
+				} else {
+					ext->alg = IW_ENCODE_ALG_TKIP;
+				}
+				ext->key_len = pkey->len;
+				key = &pkey->key[0];
+			} else {
+				ext->alg = IW_ENCODE_ALG_TKIP;
+				ext->key_len = 0;
+			}
 		} else {
 			goto out;
 		}
@@ -1775,7 +1606,7 @@
 	ret = 0;
 
 out:
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -1800,7 +1631,7 @@
 	int alg = ext->alg;
 	struct assoc_request * assoc_req;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	mutex_lock(&adapter->lock);
 	assoc_req = wlan_get_association_request(adapter);
@@ -1811,6 +1642,7 @@
 
 	if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
 		disable_wep (assoc_req);
+		disable_wpa (assoc_req);
 	} else if (alg == IW_ENCODE_ALG_WEP) {
 		u16 is_default = 0, index, set_tx_key = 0;
 
@@ -1846,7 +1678,6 @@
 			set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
 		if (set_tx_key)
 			set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
-
 	} else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
 		struct WLAN_802_11_KEY * pkey;
 
@@ -1855,36 +1686,40 @@
 			&& (ext->key_len != KEY_LEN_WPA_TKIP))
 		    || ((alg == IW_ENCODE_ALG_CCMP)
 		        && (ext->key_len != KEY_LEN_WPA_AES))) {
-				lbs_pr_debug(1, "Invalid size %d for key of alg"
-				       "type %d.\n",
+				lbs_deb_wext("invalid size %d for key of alg"
+				       "type %d\n",
 				       ext->key_len,
 				       alg);
 				ret = -EINVAL;
 				goto out;
 		}
 
-		if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+		if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
 			pkey = &assoc_req->wpa_mcast_key;
-		else
+			set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
+		} else {
 			pkey = &assoc_req->wpa_unicast_key;
+			set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
+		}
 
 		memset(pkey, 0, sizeof (struct WLAN_802_11_KEY));
 		memcpy(pkey->key, ext->key, ext->key_len);
 		pkey->len = ext->key_len;
-		pkey->flags = KEY_INFO_WPA_ENABLED;
+		if (pkey->len)
+			pkey->flags |= KEY_INFO_WPA_ENABLED;
 
+		/* Do this after zeroing key structure */
 		if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
 			pkey->flags |= KEY_INFO_WPA_MCAST;
-			set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
 		} else {
 			pkey->flags |= KEY_INFO_WPA_UNICAST;
-			set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
 		}
 
-		if (alg == IW_ENCODE_ALG_TKIP)
+		if (alg == IW_ENCODE_ALG_TKIP) {
 			pkey->type = KEY_TYPE_ID_TKIP;
-		else if (alg == IW_ENCODE_ALG_CCMP)
+		} else if (alg == IW_ENCODE_ALG_CCMP) {
 			pkey->type = KEY_TYPE_ID_AES;
+		}
 
 		/* If WPA isn't enabled yet, do that now */
 		if (   assoc_req->secinfo.WPAenabled == 0
@@ -1905,7 +1740,7 @@
 	}
 	mutex_unlock(&adapter->lock);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -1920,7 +1755,7 @@
 	int ret = 0;
 	struct assoc_request * assoc_req;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	mutex_lock(&adapter->lock);
 	assoc_req = wlan_get_association_request(adapter);
@@ -1952,7 +1787,7 @@
 	}
 	mutex_unlock(&adapter->lock);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -1961,27 +1796,28 @@
 			  struct iw_point *dwrq,
 			  char *extra)
 {
+	int ret = 0;
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (adapter->wpa_ie_len == 0) {
 		dwrq->length = 0;
-		LEAVE();
-		return 0;
+		goto out;
 	}
 
 	if (dwrq->length < adapter->wpa_ie_len) {
-		LEAVE();
-		return -E2BIG;
+		ret = -E2BIG;
+		goto out;
 	}
 
 	dwrq->length = adapter->wpa_ie_len;
 	memcpy(extra, &adapter->wpa_ie[0], adapter->wpa_ie_len);
 
-	LEAVE();
-	return 0;
+out:
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 
@@ -1996,7 +1832,7 @@
 	int ret = 0;
 	int updated = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	mutex_lock(&adapter->lock);
 	assoc_req = wlan_get_association_request(adapter);
@@ -2010,6 +1846,7 @@
 	case IW_AUTH_CIPHER_PAIRWISE:
 	case IW_AUTH_CIPHER_GROUP:
 	case IW_AUTH_KEY_MGMT:
+	case IW_AUTH_DROP_UNENCRYPTED:
 		/*
 		 * libertas does not use these parameters
 		 */
@@ -2019,6 +1856,7 @@
 		if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
 			assoc_req->secinfo.WPAenabled = 0;
 			assoc_req->secinfo.WPA2enabled = 0;
+			disable_wpa (assoc_req);
 		}
 		if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
 			assoc_req->secinfo.WPAenabled = 1;
@@ -2033,17 +1871,6 @@
 		updated = 1;
 		break;
 
-	case IW_AUTH_DROP_UNENCRYPTED:
-		if (dwrq->value) {
-			adapter->currentpacketfilter |=
-			    cmd_act_mac_strict_protection_enable;
-		} else {
-			adapter->currentpacketfilter &=
-			    ~cmd_act_mac_strict_protection_enable;
-		}
-		updated = 1;
-		break;
-
 	case IW_AUTH_80211_AUTH_ALG:
 		if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
 			assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
@@ -2069,6 +1896,7 @@
 		} else {
 			assoc_req->secinfo.WPAenabled = 0;
 			assoc_req->secinfo.WPA2enabled = 0;
+			disable_wpa (assoc_req);
 		}
 		updated = 1;
 		break;
@@ -2088,7 +1916,7 @@
 	}
 	mutex_unlock(&adapter->lock);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -2097,10 +1925,11 @@
 			 struct iw_param *dwrq,
 			 char *extra)
 {
+	int ret = 0;
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	switch (dwrq->flags & IW_AUTH_INDEX) {
 	case IW_AUTH_WPA_VERSION:
@@ -2113,13 +1942,6 @@
 			dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
 		break;
 
-	case IW_AUTH_DROP_UNENCRYPTED:
-		dwrq->value = 0;
-		if (adapter->currentpacketfilter &
-		    cmd_act_mac_strict_protection_enable)
-			dwrq->value = 1;
-		break;
-
 	case IW_AUTH_80211_AUTH_ALG:
 		dwrq->value = adapter->secinfo.auth_mode;
 		break;
@@ -2130,12 +1952,11 @@
 		break;
 
 	default:
-		LEAVE();
-		return -EOPNOTSUPP;
+		ret = -EOPNOTSUPP;
 	}
 
-	LEAVE();
-	return 0;
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 
@@ -2148,7 +1969,7 @@
 
 	u16 dbm;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (vwrq->disabled) {
 		wlan_radio_ioctl(priv, RADIO_OFF);
@@ -2169,14 +1990,14 @@
 	if (vwrq->fixed == 0)
 		dbm = 0xffff;
 
-	lbs_pr_debug(1, "<1>TXPOWER SET %d dbm.\n", dbm);
+	lbs_deb_wext("txpower set %d dbm\n", dbm);
 
 	ret = libertas_prepare_and_send_command(priv,
 				    cmd_802_11_rf_tx_power,
 				    cmd_act_tx_power_opt_set_low,
 				    cmd_option_waitforrsp, 0, (void *)&dbm);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -2186,7 +2007,8 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
+
 	/*
 	 * Note : if dwrq->flags != 0, we should get the relevant SSID from
 	 * the SSID list...
@@ -2196,12 +2018,12 @@
 	 * Get the current SSID
 	 */
 	if (adapter->connect_status == libertas_connected) {
-		memcpy(extra, adapter->curbssparams.ssid.ssid,
-		       adapter->curbssparams.ssid.ssidlength);
-		extra[adapter->curbssparams.ssid.ssidlength] = '\0';
+		memcpy(extra, adapter->curbssparams.ssid,
+		       adapter->curbssparams.ssid_len);
+		extra[adapter->curbssparams.ssid_len] = '\0';
 	} else {
 		memset(extra, 0, 32);
-		extra[adapter->curbssparams.ssid.ssidlength] = '\0';
+		extra[adapter->curbssparams.ssid_len] = '\0';
 	}
 	/*
 	 * If none, we may want to get the one that was set
@@ -2209,14 +2031,14 @@
 
 	/* To make the driver backward compatible with WPA supplicant v0.2.4 */
 	if (dwrq->length == 32)	/* check with WPA supplicant buffer size */
-		dwrq->length = min_t(size_t, adapter->curbssparams.ssid.ssidlength,
+		dwrq->length = min_t(size_t, adapter->curbssparams.ssid_len,
 				   IW_ESSID_MAX_SIZE);
 	else
-		dwrq->length = adapter->curbssparams.ssid.ssidlength + 1;
+		dwrq->length = adapter->curbssparams.ssid_len + 1;
 
 	dwrq->flags = 1;	/* active */
 
-	LEAVE();
+	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
 
@@ -2226,38 +2048,43 @@
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
-	struct WLAN_802_11_SSID ssid;
+	u8 ssid[IW_ESSID_MAX_SIZE];
+	u8 ssid_len = 0;
 	struct assoc_request * assoc_req;
-	int ssid_len = dwrq->length;
+	int in_ssid_len = dwrq->length;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	/*
 	 * WE-20 and earlier NULL pad the end of the SSID and increment
 	 * SSID length so it can be used like a string.  WE-21 and later don't,
 	 * but some userspace tools aren't able to cope with the change.
 	 */
-	if ((ssid_len > 0) && (extra[ssid_len - 1] == '\0'))
-		ssid_len--;
+	if ((in_ssid_len > 0) && (extra[in_ssid_len - 1] == '\0'))
+		in_ssid_len--;
 
 	/* Check the size of the string */
-	if (ssid_len > IW_ESSID_MAX_SIZE) {
+	if (in_ssid_len > IW_ESSID_MAX_SIZE) {
 		ret = -E2BIG;
 		goto out;
 	}
 
-	memset(&ssid, 0, sizeof(struct WLAN_802_11_SSID));
+	memset(&ssid, 0, sizeof(ssid));
 
-	if (!dwrq->flags || !ssid_len) {
+	if (!dwrq->flags || !in_ssid_len) {
 		/* "any" SSID requested; leave SSID blank */
 	} else {
 		/* Specific SSID requested */
-		memcpy(&ssid.ssid, extra, ssid_len);
-		ssid.ssidlength = ssid_len;
+		memcpy(&ssid, extra, in_ssid_len);
+		ssid_len = in_ssid_len;
 	}
 
-	lbs_pr_debug(1, "Requested new SSID = %s\n",
-	       (ssid.ssidlength > 0) ? (char *)ssid.ssid : "any");
+	if (!ssid_len) {
+		lbs_deb_wext("requested any SSID\n");
+	} else {
+		lbs_deb_wext("requested SSID '%s'\n",
+		             escape_essid(ssid, ssid_len));
+	}
 
 out:
 	mutex_lock(&adapter->lock);
@@ -2268,7 +2095,8 @@
 			ret = -ENOMEM;
 		} else {
 			/* Copy the SSID to the association request */
-			memcpy(&assoc_req->ssid, &ssid, sizeof(struct WLAN_802_11_SSID));
+			memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
+			assoc_req->ssid_len = ssid_len;
 			set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
 			wlan_postpone_association_work(priv);
 		}
@@ -2281,7 +2109,7 @@
 
 	mutex_unlock(&adapter->lock);
 
-	LEAVE();
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
 }
 
@@ -2302,12 +2130,12 @@
 	struct assoc_request * assoc_req;
 	int ret = 0;
 
-	ENTER();
+	lbs_deb_enter(LBS_DEB_WEXT);
 
 	if (awrq->sa_family != ARPHRD_ETHER)
 		return -EINVAL;
 
-	lbs_pr_debug(1, "ASSOC: WAP: sa_data: " MAC_FMT "\n", MAC_ARG(awrq->sa_data));
+	lbs_deb_wext("ASSOC: WAP: sa_data " MAC_FMT "\n", MAC_ARG(awrq->sa_data));
 
 	mutex_lock(&adapter->lock);
 
@@ -2330,22 +2158,23 @@
 
 void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen)
 {
-	union {
-		u32 l;
-		u8 c[4];
-	} ver;
 	char fwver[32];
 
 	mutex_lock(&adapter->lock);
-	ver.l = adapter->fwreleasenumber;
-	mutex_unlock(&adapter->lock);
 
-	if (ver.c[3] == 0)
-		sprintf(fwver, "%u.%u.%u", ver.c[2], ver.c[1], ver.c[0]);
+	if (adapter->fwreleasenumber[3] == 0)
+		sprintf(fwver, "%u.%u.%u",
+			adapter->fwreleasenumber[2],
+			adapter->fwreleasenumber[1],
+			adapter->fwreleasenumber[0]);
 	else
 		sprintf(fwver, "%u.%u.%u.p%u",
-			ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
+			adapter->fwreleasenumber[2],
+			adapter->fwreleasenumber[1],
+			adapter->fwreleasenumber[0],
+			adapter->fwreleasenumber[3]);
 
+	mutex_unlock(&adapter->lock);
 	snprintf(fwversion, maxlen, fwver);
 }
 
@@ -2411,13 +2240,71 @@
 	(iw_handler) NULL,		/* SIOCSIWPMKSA */
 };
 
+static const iw_handler mesh_wlan_handler[] = {
+	(iw_handler) NULL,	/* SIOCSIWCOMMIT */
+	(iw_handler) wlan_get_name,	/* SIOCGIWNAME */
+	(iw_handler) NULL,	/* SIOCSIWNWID */
+	(iw_handler) NULL,	/* SIOCGIWNWID */
+	(iw_handler) wlan_set_freq,	/* SIOCSIWFREQ */
+	(iw_handler) wlan_get_freq,	/* SIOCGIWFREQ */
+	(iw_handler) NULL,		/* SIOCSIWMODE */
+	(iw_handler) mesh_wlan_get_mode,	/* SIOCGIWMODE */
+	(iw_handler) NULL,	/* SIOCSIWSENS */
+	(iw_handler) NULL,	/* SIOCGIWSENS */
+	(iw_handler) NULL,	/* SIOCSIWRANGE */
+	(iw_handler) wlan_get_range,	/* SIOCGIWRANGE */
+	(iw_handler) NULL,	/* SIOCSIWPRIV */
+	(iw_handler) NULL,	/* SIOCGIWPRIV */
+	(iw_handler) NULL,	/* SIOCSIWSTATS */
+	(iw_handler) NULL,	/* SIOCGIWSTATS */
+	iw_handler_set_spy,	/* SIOCSIWSPY */
+	iw_handler_get_spy,	/* SIOCGIWSPY */
+	iw_handler_set_thrspy,	/* SIOCSIWTHRSPY */
+	iw_handler_get_thrspy,	/* SIOCGIWTHRSPY */
+	(iw_handler) NULL,	/* SIOCSIWAP */
+	(iw_handler) NULL,	/* SIOCGIWAP */
+	(iw_handler) NULL,	/* SIOCSIWMLME */
+	(iw_handler) NULL,	/* SIOCGIWAPLIST - deprecated */
+	(iw_handler) libertas_set_scan,	/* SIOCSIWSCAN */
+	(iw_handler) libertas_get_scan,	/* SIOCGIWSCAN */
+	(iw_handler) NULL,		/* SIOCSIWESSID */
+	(iw_handler) NULL,		/* SIOCGIWESSID */
+	(iw_handler) NULL,		/* SIOCSIWNICKN */
+	(iw_handler) mesh_get_nick,	/* SIOCGIWNICKN */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) wlan_set_rate,	/* SIOCSIWRATE */
+	(iw_handler) wlan_get_rate,	/* SIOCGIWRATE */
+	(iw_handler) wlan_set_rts,	/* SIOCSIWRTS */
+	(iw_handler) wlan_get_rts,	/* SIOCGIWRTS */
+	(iw_handler) wlan_set_frag,	/* SIOCSIWFRAG */
+	(iw_handler) wlan_get_frag,	/* SIOCGIWFRAG */
+	(iw_handler) wlan_set_txpow,	/* SIOCSIWTXPOW */
+	(iw_handler) wlan_get_txpow,	/* SIOCGIWTXPOW */
+	(iw_handler) wlan_set_retry,	/* SIOCSIWRETRY */
+	(iw_handler) wlan_get_retry,	/* SIOCGIWRETRY */
+	(iw_handler) wlan_set_encode,	/* SIOCSIWENCODE */
+	(iw_handler) wlan_get_encode,	/* SIOCGIWENCODE */
+	(iw_handler) wlan_set_power,	/* SIOCSIWPOWER */
+	(iw_handler) wlan_get_power,	/* SIOCGIWPOWER */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) wlan_set_genie,	/* SIOCSIWGENIE */
+	(iw_handler) wlan_get_genie,	/* SIOCGIWGENIE */
+	(iw_handler) wlan_set_auth,	/* SIOCSIWAUTH */
+	(iw_handler) wlan_get_auth,	/* SIOCGIWAUTH */
+	(iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */
+	(iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */
+	(iw_handler) NULL,		/* SIOCSIWPMKSA */
+};
 struct iw_handler_def libertas_handler_def = {
 	.num_standard	= sizeof(wlan_handler) / sizeof(iw_handler),
-	.num_private	= sizeof(wlan_private_handler) / sizeof(iw_handler),
-	.num_private_args = sizeof(wlan_private_args) /
-		sizeof(struct iw_priv_args),
 	.standard	= (iw_handler *) wlan_handler,
-	.private	= (iw_handler *) wlan_private_handler,
-	.private_args	= (struct iw_priv_args *)wlan_private_args,
+	.get_wireless_stats = wlan_get_wireless_stats,
+};
+
+struct iw_handler_def mesh_handler_def = {
+	.num_standard	= sizeof(mesh_wlan_handler) / sizeof(iw_handler),
+	.standard	= (iw_handler *) mesh_wlan_handler,
 	.get_wireless_stats = wlan_get_wireless_stats,
 };
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
index 15cfaaf..3d5196c 100644
--- a/drivers/net/wireless/libertas/wext.h
+++ b/drivers/net/wireless/libertas/wext.h
@@ -7,43 +7,6 @@
 #define SUBCMD_OFFSET			4
 #define SUBCMD_DATA(x)			*((int *)(x->u.name + SUBCMD_OFFSET))
 
-/** PRIVATE CMD ID */
-#define	WLANIOCTL			SIOCIWFIRSTPRIV
-
-#define WLAN_SETNONE_GETNONE	        (WLANIOCTL + 8)
-#define WLAN_SUBCMD_BT_RESET			13
-#define WLAN_SUBCMD_FWT_RESET			14
-
-#define WLAN_SETNONE_GETONEINT		(WLANIOCTL + 15)
-#define WLANGETREGION				1
-
-#define WLAN_SUBCMD_FWT_CLEANUP			15
-#define WLAN_SUBCMD_FWT_TIME			16
-#define WLAN_SUBCMD_MESH_GET_TTL		17
-
-#define WLAN_SETONEINT_GETNONE		(WLANIOCTL + 24)
-#define WLANSETREGION				8
-#define WLAN_SUBCMD_MESH_SET_TTL		18
-
-#define WLAN_SET128CHAR_GET128CHAR	(WLANIOCTL + 25)
-#define WLAN_SUBCMD_BT_ADD			18
-#define WLAN_SUBCMD_BT_DEL   			19
-#define WLAN_SUBCMD_BT_LIST			20
-#define WLAN_SUBCMD_FWT_ADD				21
-#define WLAN_SUBCMD_FWT_DEL   		22
-#define WLAN_SUBCMD_FWT_LOOKUP		23
-#define WLAN_SUBCMD_FWT_LIST_NEIGHBOR			24
-#define WLAN_SUBCMD_FWT_LIST			25
-#define WLAN_SUBCMD_FWT_LIST_ROUTE			26
-
-#define WLAN_SET_GET_SIXTEEN_INT       (WLANIOCTL + 29)
-#define WLAN_LED_GPIO_CTRL			5
-
-#define WLAN_LINKMODE_802_3			0
-#define WLAN_LINKMODE_802_11			2
-#define WLAN_RADIOMODE_NONE    			0
-#define WLAN_RADIOMODE_RADIOTAP			2
-
 /** wlan_ioctl_regrdwr */
 struct wlan_ioctl_regrdwr {
 	/** Which register to access */
@@ -55,8 +18,13 @@
 	u32 value;
 };
 
+#define WLAN_LINKMODE_802_3			0
+#define WLAN_LINKMODE_802_11			2
+#define WLAN_RADIOMODE_NONE			0
+#define WLAN_RADIOMODE_RADIOTAP			2
+
 extern struct iw_handler_def libertas_handler_def;
-int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int i);
+extern struct iw_handler_def mesh_handler_def;
 int wlan_radio_ioctl(wlan_private * priv, u8 option);
 
 #endif				/* _WLAN_WEXT_H_ */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 283be4a..585f599 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -1853,7 +1853,6 @@
 	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 	struct mac_entry *entry;
-	struct list_head *ptr;
 	struct sockaddr *addr = (struct sockaddr *) extra;
 
 	if (addr->sa_family != ARPHRD_ETHER)
@@ -1861,11 +1860,9 @@
 
 	if (down_interruptible(&acl->sem))
 		return -ERESTARTSYS;
-	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, _list);
-
+	list_for_each_entry(entry, &acl->mac_list, _list) {
 		if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
-			list_del(ptr);
+			list_del(&entry->_list);
 			acl->size--;
 			kfree(entry);
 			up(&acl->sem);
@@ -1883,7 +1880,6 @@
 	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 	struct mac_entry *entry;
-	struct list_head *ptr;
 	struct sockaddr *dst = (struct sockaddr *) extra;
 
 	dwrq->length = 0;
@@ -1891,9 +1887,7 @@
 	if (down_interruptible(&acl->sem))
 		return -ERESTARTSYS;
 
-	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, _list);
-
+	list_for_each_entry(entry, &acl->mac_list, _list) {
 		memcpy(dst->sa_data, entry->addr, ETH_ALEN);
 		dst->sa_family = ARPHRD_ETHER;
 		dwrq->length++;
@@ -1960,7 +1954,6 @@
 static int
 prism54_mac_accept(struct islpci_acl *acl, char *mac)
 {
-	struct list_head *ptr;
 	struct mac_entry *entry;
 	int res = 0;
 
@@ -1972,8 +1965,7 @@
 		return 1;
 	}
 
-	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, _list);
+	list_for_each_entry(entry, &acl->mac_list, _list) {
 		if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
 			res = 1;
 			break;
@@ -2216,11 +2208,9 @@
 void
 prism54_wpa_bss_ie_clean(islpci_private *priv)
 {
-	struct list_head *ptr, *n;
+	struct islpci_bss_wpa_ie *bss, *n;
 
-	list_for_each_safe(ptr, n, &priv->bss_wpa_list) {
-		struct islpci_bss_wpa_ie *bss;
-		bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
+	list_for_each_entry_safe(bss, n, &priv->bss_wpa_list, list) {
 		kfree(bss);
 	}
 }
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index dd070cc..f49eb068 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -378,9 +378,10 @@
 	display_buffer((char *) skb->data, skb->len);
 #endif
 	/* take care of monitor mode and spy monitoring. */
-	if (unlikely(priv->iw_mode == IW_MODE_MONITOR))
+	if (unlikely(priv->iw_mode == IW_MODE_MONITOR)) {
+		skb->dev = ndev;
 		discard = islpci_monitor_rx(priv, &skb);
-	else {
+	} else {
 		if (unlikely(skb->data[2 * ETH_ALEN] == 0)) {
 			/* The packet has a rx_annex. Read it for spy monitoring, Then
 			 * remove it, while keeping the 2 leading MAC addr.
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index 3dcb13b..af2e4f2 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -87,7 +87,6 @@
 	.remove = prism54_remove,
 	.suspend = prism54_suspend,
 	.resume = prism54_resume,
-	/* .enable_wake ; we don't support this yet */
 };
 
 /******************************************************************************
@@ -167,8 +166,7 @@
 	pci_set_master(pdev);
 
 	/* enable MWI */
-	if (!pci_set_mwi(pdev))
-		printk(KERN_INFO "%s: pci_set_mwi(pdev) succeeded\n", DRV_NAME);
+	pci_try_set_mwi(pdev);
 
 	/* setup the network device interface and its structure */
 	if (!(ndev = islpci_setup(pdev))) {
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
new file mode 100644
index 0000000..6124e46
--- /dev/null
+++ b/drivers/net/wireless/rtl8187.h
@@ -0,0 +1,145 @@
+/*
+ * Definitions for RTL8187 hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL8187_H
+#define RTL8187_H
+
+#include "rtl818x.h"
+
+#define RTL8187_EEPROM_TXPWR_BASE	0x05
+#define RTL8187_EEPROM_MAC_ADDR		0x07
+#define RTL8187_EEPROM_TXPWR_CHAN_1	0x16	/* 3 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_6	0x1B	/* 2 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_4	0x3D	/* 2 channels */
+
+#define RTL8187_REQT_READ	0xC0
+#define RTL8187_REQT_WRITE	0x40
+#define RTL8187_REQ_GET_REG	0x05
+#define RTL8187_REQ_SET_REG	0x05
+
+#define RTL8187_MAX_RX		0x9C4
+
+struct rtl8187_rx_info {
+	struct urb *urb;
+	struct ieee80211_hw *dev;
+};
+
+struct rtl8187_rx_hdr {
+	__le16 len;
+	__le16 rate;
+	u8 noise;
+	u8 signal;
+	u8 agc;
+	u8 reserved;
+	__le64 mac_time;
+} __attribute__((packed));
+
+struct rtl8187_tx_info {
+	struct ieee80211_tx_control *control;
+	struct urb *urb;
+	struct ieee80211_hw *dev;
+};
+
+struct rtl8187_tx_hdr {
+	__le32 flags;
+#define RTL8187_TX_FLAG_NO_ENCRYPT	(1 << 15)
+#define RTL8187_TX_FLAG_MORE_FRAG	(1 << 17)
+#define RTL8187_TX_FLAG_CTS		(1 << 18)
+#define RTL8187_TX_FLAG_RTS		(1 << 23)
+	__le16 rts_duration;
+	__le16 len;
+	__le32 retry;
+} __attribute__((packed));
+
+struct rtl8187_priv {
+	/* common between rtl818x drivers */
+	struct rtl818x_csr *map;
+	void (*rf_init)(struct ieee80211_hw *);
+	int mode;
+
+	/* rtl8187 specific */
+	struct ieee80211_channel channels[14];
+	struct ieee80211_rate rates[12];
+	struct ieee80211_hw_mode modes[2];
+	struct usb_device *udev;
+	u8 *hwaddr;
+	u16 txpwr_base;
+	u8 asic_rev;
+	struct sk_buff_head rx_queue;
+};
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
+
+static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
+{
+	u8 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return val;
+}
+
+static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
+{
+	__le16 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return le16_to_cpu(val);
+}
+
+static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
+{
+	__le32 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return le32_to_cpu(val);
+}
+
+static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
+				    u8 *addr, u8 val)
+{
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+}
+
+static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
+				     __le16 *addr, u16 val)
+{
+	__le16 buf = cpu_to_le16(val);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
+				     __le32 *addr, u32 val)
+{
+	__le32 buf = cpu_to_le32(val);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+#endif /* RTL8187_H */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
new file mode 100644
index 0000000..cea8589
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -0,0 +1,731 @@
+/*
+ * Linux device driver for RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays and register offsets below are taken from the original
+ * r8187 driver sources.  Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/eeprom_93cx6.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
+MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
+MODULE_DESCRIPTION("RTL8187 USB wireless driver");
+MODULE_LICENSE("GPL");
+
+static struct usb_device_id rtl8187_table[] __devinitdata = {
+	/* Realtek */
+	{USB_DEVICE(0x0bda, 0x8187)},
+	/* Netgear */
+	{USB_DEVICE(0x0846, 0x6100)},
+	{USB_DEVICE(0x0846, 0x6a00)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, rtl8187_table);
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	data <<= 8;
+	data |= addr | 0x80;
+
+	rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
+
+	msleep(1);
+}
+
+static void rtl8187_tx_cb(struct urb *urb)
+{
+	struct ieee80211_tx_status status = { {0} };
+	struct sk_buff *skb = (struct sk_buff *)urb->context;
+	struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
+
+	usb_free_urb(info->urb);
+	if (info->control)
+		memcpy(&status.control, info->control, sizeof(status.control));
+	kfree(info->control);
+	skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
+	status.flags |= IEEE80211_TX_STATUS_ACK;
+	ieee80211_tx_status_irqsafe(info->dev, skb, &status);
+}
+
+static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+		      struct ieee80211_tx_control *control)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_tx_hdr *hdr;
+	struct rtl8187_tx_info *info;
+	struct urb *urb;
+	u32 tmp;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree_skb(skb);
+		return 0;
+	}
+
+	hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+	tmp = skb->len - sizeof(*hdr);
+	tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
+	tmp |= control->rts_cts_rate << 19;
+	tmp |= control->tx_rate << 24;
+	if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
+		tmp |= RTL8187_TX_FLAG_MORE_FRAG;
+	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+		tmp |= RTL8187_TX_FLAG_RTS;
+		hdr->rts_duration =
+			ieee80211_rts_duration(dev, skb->len, control);
+	}
+	if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+		tmp |= RTL8187_TX_FLAG_CTS;
+	hdr->flags = cpu_to_le32(tmp);
+	hdr->len = 0;
+	tmp = control->retry_limit << 8;
+	hdr->retry = cpu_to_le32(tmp);
+
+	info = (struct rtl8187_tx_info *)skb->cb;
+	info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
+	info->urb = urb;
+	info->dev = dev;
+	usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
+			  hdr, skb->len, rtl8187_tx_cb, skb);
+	usb_submit_urb(urb, GFP_ATOMIC);
+
+	return 0;
+}
+
+static void rtl8187_rx_cb(struct urb *urb)
+{
+	struct sk_buff *skb = (struct sk_buff *)urb->context;
+	struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
+	struct ieee80211_hw *dev = info->dev;
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_rx_hdr *hdr;
+	struct ieee80211_rx_status rx_status = { 0 };
+	int rate, signal;
+
+	spin_lock(&priv->rx_queue.lock);
+	if (skb->next)
+		__skb_unlink(skb, &priv->rx_queue);
+	else {
+		spin_unlock(&priv->rx_queue.lock);
+		return;
+	}
+	spin_unlock(&priv->rx_queue.lock);
+
+	if (unlikely(urb->status)) {
+		usb_free_urb(urb);
+		dev_kfree_skb_irq(skb);
+		return;
+	}
+
+	skb_put(skb, urb->actual_length);
+	hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
+	skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
+
+	signal = hdr->agc >> 1;
+	rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
+	if (rate > 3) {	/* OFDM rate */
+		if (signal > 90)
+			signal = 90;
+		else if (signal < 25)
+			signal = 25;
+		signal = 90 - signal;
+	} else {	/* CCK rate */
+		if (signal > 95)
+			signal = 95;
+		else if (signal < 30)
+			signal = 30;
+		signal = 95 - signal;
+	}
+
+	rx_status.antenna = (hdr->signal >> 7) & 1;
+	rx_status.signal = 64 - min(hdr->noise, (u8)64);
+	rx_status.ssi = signal;
+	rx_status.rate = rate;
+	rx_status.freq = dev->conf.freq;
+	rx_status.channel = dev->conf.channel;
+	rx_status.phymode = dev->conf.phymode;
+	rx_status.mactime = le64_to_cpu(hdr->mac_time);
+	ieee80211_rx_irqsafe(dev, skb, &rx_status);
+
+	skb = dev_alloc_skb(RTL8187_MAX_RX);
+	if (unlikely(!skb)) {
+		usb_free_urb(urb);
+		/* TODO check rx queue length and refill *somewhere* */
+		return;
+	}
+
+	info = (struct rtl8187_rx_info *)skb->cb;
+	info->urb = urb;
+	info->dev = dev;
+	urb->transfer_buffer = skb_tail_pointer(skb);
+	urb->context = skb;
+	skb_queue_tail(&priv->rx_queue, skb);
+
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl8187_init_urbs(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct urb *entry;
+	struct sk_buff *skb;
+	struct rtl8187_rx_info *info;
+
+	while (skb_queue_len(&priv->rx_queue) < 8) {
+		skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
+		if (!skb)
+			break;
+		entry = usb_alloc_urb(0, GFP_KERNEL);
+		if (!entry) {
+			kfree_skb(skb);
+			break;
+		}
+		usb_fill_bulk_urb(entry, priv->udev,
+				  usb_rcvbulkpipe(priv->udev, 1),
+				  skb_tail_pointer(skb),
+				  RTL8187_MAX_RX, rtl8187_rx_cb, skb);
+		info = (struct rtl8187_rx_info *)skb->cb;
+		info->urb = entry;
+		info->dev = dev;
+		skb_queue_tail(&priv->rx_queue, skb);
+		usb_submit_urb(entry, GFP_KERNEL);
+	}
+
+	return 0;
+}
+
+static int rtl8187_init_hw(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg;
+	int i;
+
+	/* reset */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+	msleep(200);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
+	msleep(200);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg &= (1 << 1);
+	reg |= RTL818X_CMD_RESET;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	i = 10;
+	do {
+		msleep(2);
+		if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
+		      RTL818X_CMD_RESET))
+			break;
+	} while (--i);
+
+	if (!i) {
+		printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
+		return -ETIMEDOUT;
+	}
+
+	/* reload registers from eeprom */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
+
+	i = 10;
+	do {
+		msleep(4);
+		if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
+		      RTL818X_EEPROM_CMD_CONFIG))
+			break;
+	} while (--i);
+
+	if (!i) {
+		printk(KERN_ERR "%s: eeprom reset timeout!\n",
+		       wiphy_name(dev->wiphy));
+		return -ETIMEDOUT;
+	}
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	/* setup card */
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
+	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	for (i = 0; i < ETH_ALEN; i++)
+		rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
+
+	rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
+	reg &= 0x3F;
+	reg |= 0x80;
+	rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+	rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
+	rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+
+	// TODO: set RESP_RATE and BRSR properly
+	rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+
+	/* host_usb_init */
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+	reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
+	rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
+	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
+	msleep(100);
+
+	rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+	rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
+	msleep(100);
+
+	priv->rf_init(dev);
+
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+	reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
+	rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
+	rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
+	rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+
+	return 0;
+}
+
+static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
+{
+	u32 reg;
+	struct rtl8187_priv *priv = dev->priv;
+
+	reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+	/* Enable TX loopback on MAC level to avoid TX during channel
+	 * changes, as this has be seen to causes problems and the
+	 * card will stop work until next reset
+	 */
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+			  reg | RTL818X_TX_CONF_LOOPBACK_MAC);
+	msleep(10);
+	rtl8225_rf_set_channel(dev, channel);
+	msleep(10);
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+}
+
+static int rtl8187_open(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u32 reg;
+	int ret;
+
+	ret = rtl8187_init_hw(dev);
+	if (ret)
+		return ret;
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+
+	rtl8187_init_urbs(dev);
+
+	reg = RTL818X_RX_CONF_ONLYERLPKT |
+	      RTL818X_RX_CONF_RX_AUTORESETPHY |
+	      RTL818X_RX_CONF_BSSID |
+	      RTL818X_RX_CONF_MGMT |
+	      RTL818X_RX_CONF_CTRL |
+	      RTL818X_RX_CONF_DATA |
+	      (7 << 13 /* RX FIFO threshold NONE */) |
+	      (7 << 10 /* MAX RX DMA */) |
+	      RTL818X_RX_CONF_BROADCAST |
+	      RTL818X_RX_CONF_MULTICAST |
+	      RTL818X_RX_CONF_NICMAC;
+	if (priv->mode == IEEE80211_IF_TYPE_MNTR)
+		reg |= RTL818X_RX_CONF_MONITOR;
+
+	rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
+	reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
+	reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+	rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
+	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
+	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+	reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
+	rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
+
+	reg  = RTL818X_TX_CONF_CW_MIN |
+	       (7 << 21 /* MAX TX DMA */) |
+	       RTL818X_TX_CONF_NO_ICV;
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg |= RTL818X_CMD_TX_ENABLE;
+	reg |= RTL818X_CMD_RX_ENABLE;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	return 0;
+}
+
+static int rtl8187_stop(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_rx_info *info;
+	struct sk_buff *skb;
+	u32 reg;
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg &= ~RTL818X_CMD_TX_ENABLE;
+	reg &= ~RTL818X_CMD_RX_ENABLE;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	rtl8225_rf_stop(dev);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	while ((skb = skb_dequeue(&priv->rx_queue))) {
+		info = (struct rtl8187_rx_info *)skb->cb;
+		usb_kill_urb(info->urb);
+		kfree_skb(skb);
+	}
+	return 0;
+}
+
+static int rtl8187_add_interface(struct ieee80211_hw *dev,
+				 struct ieee80211_if_init_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	/* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
+	if (priv->mode != IEEE80211_IF_TYPE_MGMT)
+		return -1;
+
+	switch (conf->type) {
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_MNTR:
+		priv->mode = conf->type;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	priv->hwaddr = conf->mac_addr;
+
+	return 0;
+}
+
+static void rtl8187_remove_interface(struct ieee80211_hw *dev,
+				     struct ieee80211_if_init_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	priv->mode = IEEE80211_IF_TYPE_MGMT;
+}
+
+static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	rtl8187_set_channel(dev, conf->channel);
+
+	rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+
+	if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+	} else {
+		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
+	rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
+	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
+	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
+	return 0;
+}
+
+static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
+				    struct ieee80211_if_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
+
+	if (is_valid_ether_addr(conf->bssid))
+		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
+	else
+		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
+
+	return 0;
+}
+
+static const struct ieee80211_ops rtl8187_ops = {
+	.tx			= rtl8187_tx,
+	.open			= rtl8187_open,
+	.stop			= rtl8187_stop,
+	.add_interface		= rtl8187_add_interface,
+	.remove_interface	= rtl8187_remove_interface,
+	.config			= rtl8187_config,
+	.config_interface	= rtl8187_config_interface,
+};
+
+static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+	struct ieee80211_hw *dev = eeprom->data;
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+
+	eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+	eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+	eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+	eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+	struct ieee80211_hw *dev = eeprom->data;
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
+
+	if (eeprom->reg_data_in)
+		reg |= RTL818X_EEPROM_CMD_WRITE;
+	if (eeprom->reg_data_out)
+		reg |= RTL818X_EEPROM_CMD_READ;
+	if (eeprom->reg_data_clock)
+		reg |= RTL818X_EEPROM_CMD_CK;
+	if (eeprom->reg_chip_select)
+		reg |= RTL818X_EEPROM_CMD_CS;
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+	udelay(10);
+}
+
+static int __devinit rtl8187_probe(struct usb_interface *intf,
+				   const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct ieee80211_hw *dev;
+	struct rtl8187_priv *priv;
+	struct eeprom_93cx6 eeprom;
+	struct ieee80211_channel *channel;
+	u16 txpwr, reg;
+	int err, i;
+
+	dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
+	if (!dev) {
+		printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
+		return -ENOMEM;
+	}
+
+	priv = dev->priv;
+
+	SET_IEEE80211_DEV(dev, &intf->dev);
+	usb_set_intfdata(intf, dev);
+	priv->udev = udev;
+
+	usb_get_dev(udev);
+
+	skb_queue_head_init(&priv->rx_queue);
+	memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+	memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+	priv->map = (struct rtl818x_csr *)0xFF00;
+	priv->modes[0].mode = MODE_IEEE80211G;
+	priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+	priv->modes[0].rates = priv->rates;
+	priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+	priv->modes[0].channels = priv->channels;
+	priv->modes[1].mode = MODE_IEEE80211B;
+	priv->modes[1].num_rates = 4;
+	priv->modes[1].rates = priv->rates;
+	priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+	priv->modes[1].channels = priv->channels;
+	priv->mode = IEEE80211_IF_TYPE_MGMT;
+	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+		     IEEE80211_HW_RX_INCLUDES_FCS |
+		     IEEE80211_HW_WEP_INCLUDE_IV |
+		     IEEE80211_HW_DATA_NULLFUNC_ACK;
+	dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
+	dev->queues = 1;
+	dev->max_rssi = 65;
+	dev->max_signal = 64;
+
+	for (i = 0; i < 2; i++)
+		if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
+			goto err_free_dev;
+
+	eeprom.data = dev;
+	eeprom.register_read = rtl8187_eeprom_register_read;
+	eeprom.register_write = rtl8187_eeprom_register_write;
+	if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
+		eeprom.width = PCI_EEPROM_WIDTH_93C66;
+	else
+		eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	udelay(10);
+
+	eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR,
+			       (__le16 __force *)dev->wiphy->perm_addr, 3);
+	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+		printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly "
+		       "generated MAC address\n");
+		random_ether_addr(dev->wiphy->perm_addr);
+	}
+
+	channel = priv->channels;
+	for (i = 0; i < 3; i++) {
+		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
+				  &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+	for (i = 0; i < 2; i++) {
+		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
+				  &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+	for (i = 0; i < 2; i++) {
+		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+				  &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+
+	eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
+			  &priv->txpwr_base);
+
+	reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
+	/* 0 means asic B-cut, we should use SW 3 wire
+	 * bit-by-bit banging for radio. 1 means we can use
+	 * USB specific request to write radio registers */
+	priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write(dev, 0, 0x1B7);
+
+	if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
+		priv->rf_init = rtl8225_rf_init;
+	else
+		priv->rf_init = rtl8225z2_rf_init;
+
+	rtl8225_write(dev, 0, 0x0B7);
+
+	err = ieee80211_register_hw(dev);
+	if (err) {
+		printk(KERN_ERR "rtl8187: Cannot register device\n");
+		goto err_free_dev;
+	}
+
+	printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
+	       wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
+	       priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
+	       "rtl8225" : "rtl8225z2");
+
+	return 0;
+
+ err_free_dev:
+	ieee80211_free_hw(dev);
+	usb_set_intfdata(intf, NULL);
+	usb_put_dev(udev);
+	return err;
+}
+
+static void __devexit rtl8187_disconnect(struct usb_interface *intf)
+{
+	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+	struct rtl8187_priv *priv;
+
+	if (!dev)
+		return;
+
+	ieee80211_unregister_hw(dev);
+
+	priv = dev->priv;
+	usb_put_dev(interface_to_usbdev(intf));
+	ieee80211_free_hw(dev);
+}
+
+static struct usb_driver rtl8187_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= rtl8187_table,
+	.probe		= rtl8187_probe,
+	.disconnect	= rtl8187_disconnect,
+};
+
+static int __init rtl8187_init(void)
+{
+	return usb_register(&rtl8187_driver);
+}
+
+static void __exit rtl8187_exit(void)
+{
+	usb_deregister(&rtl8187_driver);
+}
+
+module_init(rtl8187_init);
+module_exit(rtl8187_exit);
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
new file mode 100644
index 0000000..efc4120
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -0,0 +1,745 @@
+/*
+ * Radio tuning for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays, register offsets, and phy value tables below are
+ * taken from the original r8187 driver sources.  Thanks to Realtek
+ * for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg84, reg82;
+	u32 bangdata;
+	int i;
+
+	bangdata = (data << 4) | (addr & 0xf);
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
+
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(10);
+
+	for (i = 15; i >= 0; i--) {
+		u16 reg = reg80 | (bangdata & (1 << i)) >> i;
+
+		if (i & 1)
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+
+		if (!(i & 1))
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	msleep(2);
+}
+
+static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg82, reg84;
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+	reg80 &= ~(0x3 << 2);
+	reg84 &= ~0xF;
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(10);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			addr, 0x8225, &data, sizeof(data), HZ / 2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	msleep(2);
+}
+
+void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (priv->asic_rev)
+		rtl8225_write_8051(dev, addr, cpu_to_le16(data));
+	else
+		rtl8225_write_bitbang(dev, addr, data);
+}
+
+u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg82, reg84, out;
+	int i;
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+	reg80 &= ~0xF;
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(4);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(5);
+
+	for (i = 4; i >= 0; i--) {
+		u16 reg = reg80 | ((addr >> i) & 1);
+
+		if (!(i & 1)) {
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+			udelay(1);
+		}
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg | (1 << 1));
+		udelay(2);
+
+		if (i & 1) {
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+			udelay(1);
+		}
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3) | (1 << 1));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3));
+	udelay(2);
+
+	out = 0;
+	for (i = 11; i >= 0; i--) {
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3));
+		udelay(1);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+
+		if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
+			out |= 1 << i;
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3));
+		udelay(2);
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3) | (1 << 2));
+	udelay(2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
+
+	return out;
+}
+
+static const u16 rtl8225bcd_rxgain[] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static const u8 rtl8225_agc[] = {
+	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
+	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
+	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
+	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
+	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
+	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
+	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const u8 rtl8225_gain[] = {
+	0x23, 0x88, 0x7c, 0xa5,	/* -82dBm */
+	0x23, 0x88, 0x7c, 0xb5,	/* -82dBm */
+	0x23, 0x88, 0x7c, 0xc5,	/* -82dBm */
+	0x33, 0x80, 0x79, 0xc5,	/* -78dBm */
+	0x43, 0x78, 0x76, 0xc5,	/* -74dBm */
+	0x53, 0x60, 0x73, 0xc5,	/* -70dBm */
+	0x63, 0x58, 0x70, 0xc5,	/* -66dBm */
+};
+
+static const u8 rtl8225_threshold[] = {
+	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
+};
+
+static const u8 rtl8225_tx_gain_cck_ofdm[] = {
+	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static const u8 rtl8225_tx_power_cck[] = {
+	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static const u8 rtl8225_tx_power_cck_ch14[] = {
+	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225_tx_power_ofdm[] = {
+	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static const u32 rtl8225_chan[] = {
+	0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
+	0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
+};
+
+static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 cck_power, ofdm_power;
+	const u8 *tmp;
+	u32 reg;
+	int i;
+
+	cck_power = priv->channels[channel - 1].val & 0xF;
+	ofdm_power = priv->channels[channel - 1].val >> 4;
+
+	cck_power = min(cck_power, (u8)11);
+	ofdm_power = min(ofdm_power, (u8)35);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+			 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
+
+	if (channel == 14)
+		tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
+	else
+		tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
+
+	for (i = 0; i < 8; i++)
+		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+	msleep(1); // FIXME: optional?
+
+	/* anaparam2 on */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write_phy_ofdm(dev, 2, 0x42);
+	rtl8225_write_phy_ofdm(dev, 6, 0x00);
+	rtl8225_write_phy_ofdm(dev, 8, 0x00);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+			 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
+
+	tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
+
+	rtl8225_write_phy_ofdm(dev, 5, *tmp);
+	rtl8225_write_phy_ofdm(dev, 7, *tmp);
+
+	msleep(1);
+}
+
+void rtl8225_rf_init(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	rtl8225_write(dev, 0x0, 0x067); msleep(1);
+	rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
+	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+	rtl8225_write(dev, 0x3, 0x441); msleep(1);
+	rtl8225_write(dev, 0x4, 0x486); msleep(1);
+	rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
+	rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
+	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+	rtl8225_write(dev, 0x8, 0x01F); msleep(1);
+	rtl8225_write(dev, 0x9, 0x334); msleep(1);
+	rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
+	rtl8225_write(dev, 0xB, 0x391); msleep(1);
+	rtl8225_write(dev, 0xC, 0x050); msleep(1);
+	rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
+	rtl8225_write(dev, 0xE, 0x029); msleep(1);
+	rtl8225_write(dev, 0xF, 0x914); msleep(100);
+
+	rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
+	rtl8225_write(dev, 0x2, 0x44D); msleep(200);
+
+	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+		rtl8225_write(dev, 0x02, 0x0c4d);
+		msleep(200);
+		rtl8225_write(dev, 0x02, 0x044d);
+		msleep(100);
+		if (!(rtl8225_read(dev, 6) & (1 << 7)))
+			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+	}
+
+	rtl8225_write(dev, 0x0, 0x127);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
+		rtl8225_write(dev, 0x1, i + 1);
+		rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
+	}
+
+	rtl8225_write(dev, 0x0, 0x027);
+	rtl8225_write(dev, 0x0, 0x22F);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+		msleep(1);
+		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+		msleep(1);
+	}
+
+	msleep(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+
+	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+	rtl8225_write_phy_cck(dev, 0x19, 0x00);
+	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+	rtl8225_write_phy_cck(dev, 0x40, 0x86);
+	rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+	rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
+
+	rtl8225_rf_set_tx_power(dev, 1);
+
+	/* RX antenna default to A */
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
+
+	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
+	msleep(1);
+	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+
+	/* set sensitivity */
+	rtl8225_write(dev, 0x0c, 0x50);
+	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+	rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
+}
+
+static const u8 rtl8225z2_tx_power_cck_ch14[] = {
+	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225z2_tx_power_cck[] = {
+	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_ofdm[] = {
+	0x42, 0x00, 0x40, 0x00, 0x40
+};
+
+static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
+};
+
+static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 cck_power, ofdm_power;
+	const u8 *tmp;
+	u32 reg;
+	int i;
+
+	cck_power = priv->channels[channel - 1].val & 0xF;
+	ofdm_power = priv->channels[channel - 1].val >> 4;
+
+	cck_power = min(cck_power, (u8)15);
+	cck_power += priv->txpwr_base & 0xF;
+	cck_power = min(cck_power, (u8)35);
+
+	ofdm_power = min(ofdm_power, (u8)15);
+	ofdm_power += priv->txpwr_base >> 4;
+	ofdm_power = min(ofdm_power, (u8)35);
+
+	if (channel == 14)
+		tmp = rtl8225z2_tx_power_cck_ch14;
+	else
+		tmp = rtl8225z2_tx_power_cck;
+
+	for (i = 0; i < 8; i++)
+		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+			 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
+	msleep(1);
+
+	/* anaparam2 on */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write_phy_ofdm(dev, 2, 0x42);
+	rtl8225_write_phy_ofdm(dev, 5, 0x00);
+	rtl8225_write_phy_ofdm(dev, 6, 0x40);
+	rtl8225_write_phy_ofdm(dev, 7, 0x00);
+	rtl8225_write_phy_ofdm(dev, 8, 0x40);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+			 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
+	msleep(1);
+}
+
+static const u16 rtl8225z2_rxgain[] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static const u8 rtl8225z2_gain_bg[] = {
+	0x23, 0x15, 0xa5, /* -82-1dBm */
+	0x23, 0x15, 0xb5, /* -82-2dBm */
+	0x23, 0x15, 0xc5, /* -82-3dBm */
+	0x33, 0x15, 0xc5, /* -78dBm */
+	0x43, 0x15, 0xc5, /* -74dBm */
+	0x53, 0x15, 0xc5, /* -70dBm */
+	0x63, 0x15, 0xc5  /* -66dBm */
+};
+
+void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
+	rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
+	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+	rtl8225_write(dev, 0x3, 0x441); msleep(1);
+	rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
+	rtl8225_write(dev, 0x5, 0xC72); msleep(1);
+	rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
+	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+	rtl8225_write(dev, 0x8, 0x03F); msleep(1);
+	rtl8225_write(dev, 0x9, 0x335); msleep(1);
+	rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
+	rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
+	rtl8225_write(dev, 0xc, 0x850); msleep(1);
+	rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
+	rtl8225_write(dev, 0xe, 0x02B); msleep(1);
+	rtl8225_write(dev, 0xf, 0x114); msleep(100);
+
+	rtl8225_write(dev, 0x0, 0x1B7);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+		rtl8225_write(dev, 0x1, i + 1);
+		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
+	}
+
+	rtl8225_write(dev, 0x3, 0x080);
+	rtl8225_write(dev, 0x5, 0x004);
+	rtl8225_write(dev, 0x0, 0x0B7);
+	rtl8225_write(dev, 0x2, 0xc4D);
+
+	msleep(200);
+	rtl8225_write(dev, 0x2, 0x44D);
+	msleep(100);
+
+	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+		rtl8225_write(dev, 0x02, 0x0C4D);
+		msleep(200);
+		rtl8225_write(dev, 0x02, 0x044D);
+		msleep(100);
+		if (!(rtl8225_read(dev, 6) & (1 << 7)))
+			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+	}
+
+	msleep(200);
+
+	rtl8225_write(dev, 0x0, 0x2BF);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+		msleep(1);
+		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+		msleep(1);
+	}
+
+	msleep(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
+	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
+	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
+
+	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+	rtl8225_write_phy_cck(dev, 0x19, 0x00);
+	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+	rtl8225_write_phy_cck(dev, 0x40, 0x86);
+	rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+	rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
+
+	rtl8225z2_rf_set_tx_power(dev, 1);
+
+	/* RX antenna default to A */
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
+
+	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
+	msleep(1);
+	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+}
+
+void rtl8225_rf_stop(struct ieee80211_hw *dev)
+{
+	u8 reg;
+	struct rtl8187_priv *priv = dev->priv;
+
+	rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (priv->rf_init == rtl8225_rf_init)
+		rtl8225_rf_set_tx_power(dev, channel);
+	else
+		rtl8225z2_rf_set_tx_power(dev, channel);
+
+	rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
+	msleep(10);
+}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
new file mode 100644
index 0000000..798ba4a
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -0,0 +1,44 @@
+/*
+ * Radio tuning definitions for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL8187_RTL8225_H
+#define RTL8187_RTL8225_H
+
+#define RTL8225_ANAPARAM_ON	0xa0000a59
+#define RTL8225_ANAPARAM2_ON	0x860c7312
+#define RTL8225_ANAPARAM_OFF	0xa00beb59
+#define RTL8225_ANAPARAM2_OFF	0x840dec11
+
+void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
+u16  rtl8225_read(struct ieee80211_hw *, u8 addr);
+
+void rtl8225_rf_init(struct ieee80211_hw *);
+void rtl8225z2_rf_init(struct ieee80211_hw *);
+void rtl8225_rf_stop(struct ieee80211_hw *);
+void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
+
+
+static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
+					  u8 addr, u32 data)
+{
+	rtl8187_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
+					 u8 addr, u32 data)
+{
+	rtl8187_write_phy(dev, addr, data | 0x10000);
+}
+
+#endif /* RTL8187_RTL8225_H */
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
new file mode 100644
index 0000000..283de30
--- /dev/null
+++ b/drivers/net/wireless/rtl818x.h
@@ -0,0 +1,226 @@
+/*
+ * Definitions for RTL818x hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL818X_H
+#define RTL818X_H
+
+struct rtl818x_csr {
+	u8	MAC[6];
+	u8	reserved_0[2];
+	__le32	MAR[2];
+	u8	RX_FIFO_COUNT;
+	u8	reserved_1;
+	u8	TX_FIFO_COUNT;
+	u8	BQREQ;
+	u8	reserved_2[4];
+	__le32	TSFT[2];
+	__le32	TLPDA;
+	__le32	TNPDA;
+	__le32	THPDA;
+	__le16	BRSR;
+	u8	BSSID[6];
+	u8	RESP_RATE;
+	u8	EIFS;
+	u8	reserved_3[1];
+	u8	CMD;
+#define RTL818X_CMD_TX_ENABLE		(1 << 2)
+#define RTL818X_CMD_RX_ENABLE		(1 << 3)
+#define RTL818X_CMD_RESET		(1 << 4)
+	u8	reserved_4[4];
+	__le16	INT_MASK;
+	__le16	INT_STATUS;
+#define RTL818X_INT_RX_OK		(1 <<  0)
+#define RTL818X_INT_RX_ERR		(1 <<  1)
+#define RTL818X_INT_TXL_OK		(1 <<  2)
+#define RTL818X_INT_TXL_ERR		(1 <<  3)
+#define RTL818X_INT_RX_DU		(1 <<  4)
+#define RTL818X_INT_RX_FO		(1 <<  5)
+#define RTL818X_INT_TXN_OK		(1 <<  6)
+#define RTL818X_INT_TXN_ERR		(1 <<  7)
+#define RTL818X_INT_TXH_OK		(1 <<  8)
+#define RTL818X_INT_TXH_ERR		(1 <<  9)
+#define RTL818X_INT_TXB_OK		(1 << 10)
+#define RTL818X_INT_TXB_ERR		(1 << 11)
+#define RTL818X_INT_ATIM		(1 << 12)
+#define RTL818X_INT_BEACON		(1 << 13)
+#define RTL818X_INT_TIME_OUT		(1 << 14)
+#define RTL818X_INT_TX_FO		(1 << 15)
+	__le32	TX_CONF;
+#define RTL818X_TX_CONF_LOOPBACK_MAC	(1 << 17)
+#define RTL818X_TX_CONF_NO_ICV		(1 << 19)
+#define RTL818X_TX_CONF_DISCW		(1 << 20)
+#define RTL818X_TX_CONF_R8180_ABCD	(2 << 25)
+#define RTL818X_TX_CONF_R8180_F		(3 << 25)
+#define RTL818X_TX_CONF_R8185_ABC	(4 << 25)
+#define RTL818X_TX_CONF_R8185_D		(5 << 25)
+#define RTL818X_TX_CONF_HWVER_MASK	(7 << 25)
+#define RTL818X_TX_CONF_CW_MIN		(1 << 31)
+	__le32	RX_CONF;
+#define RTL818X_RX_CONF_MONITOR		(1 <<  0)
+#define RTL818X_RX_CONF_NICMAC		(1 <<  1)
+#define RTL818X_RX_CONF_MULTICAST	(1 <<  2)
+#define RTL818X_RX_CONF_BROADCAST	(1 <<  3)
+#define RTL818X_RX_CONF_DATA		(1 << 18)
+#define RTL818X_RX_CONF_CTRL		(1 << 19)
+#define RTL818X_RX_CONF_MGMT		(1 << 20)
+#define RTL818X_RX_CONF_BSSID		(1 << 23)
+#define RTL818X_RX_CONF_RX_AUTORESETPHY	(1 << 28)
+#define RTL818X_RX_CONF_ONLYERLPKT	(1 << 31)
+	__le32	INT_TIMEOUT;
+	__le32	TBDA;
+	u8	EEPROM_CMD;
+#define RTL818X_EEPROM_CMD_READ		(1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE	(1 << 1)
+#define RTL818X_EEPROM_CMD_CK		(1 << 2)
+#define RTL818X_EEPROM_CMD_CS		(1 << 3)
+#define RTL818X_EEPROM_CMD_NORMAL	(0 << 6)
+#define RTL818X_EEPROM_CMD_LOAD		(1 << 6)
+#define RTL818X_EEPROM_CMD_PROGRAM	(2 << 6)
+#define RTL818X_EEPROM_CMD_CONFIG	(3 << 6)
+	u8	CONFIG0;
+	u8	CONFIG1;
+	u8	CONFIG2;
+	__le32	ANAPARAM;
+	u8	MSR;
+#define RTL818X_MSR_NO_LINK		(0 << 2)
+#define RTL818X_MSR_ADHOC		(1 << 2)
+#define RTL818X_MSR_INFRA		(2 << 2)
+	u8	CONFIG3;
+#define RTL818X_CONFIG3_ANAPARAM_WRITE	(1 << 6)
+	u8	CONFIG4;
+#define RTL818X_CONFIG4_POWEROFF	(1 << 6)
+#define RTL818X_CONFIG4_VCOOFF		(1 << 7)
+	u8	TESTR;
+	u8	reserved_9[2];
+	__le16	PGSELECT;
+	__le32	ANAPARAM2;
+	u8	reserved_10[12];
+	__le16	BEACON_INTERVAL;
+	__le16	ATIM_WND;
+	__le16	BEACON_INTERVAL_TIME;
+	__le16	ATIMTR_INTERVAL;
+	u8	reserved_11[4];
+	u8	PHY[4];
+	__le16	RFPinsOutput;
+	__le16	RFPinsEnable;
+	__le16	RFPinsSelect;
+	__le16	RFPinsInput;
+	__le32	RF_PARA;
+	__le32	RF_TIMING;
+	u8	GP_ENABLE;
+	u8	GPIO;
+	u8	reserved_12[10];
+	u8	TX_AGC_CTL;
+#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT		(1 << 0)
+#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT	(1 << 1)
+#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT			(1 << 2)
+	u8	TX_GAIN_CCK;
+	u8	TX_GAIN_OFDM;
+	u8	TX_ANTENNA;
+	u8	reserved_13[16];
+	u8	WPA_CONF;
+	u8	reserved_14[3];
+	u8	SIFS;
+	u8	DIFS;
+	u8	SLOT;
+	u8	reserved_15[5];
+	u8	CW_CONF;
+#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT	(1 << 0)
+#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT	(1 << 1)
+	u8	CW_VAL;
+	u8	RATE_FALLBACK;
+	u8	reserved_16[25];
+	u8	CONFIG5;
+	u8	TX_DMA_POLLING;
+	u8	reserved_17[2];
+	__le16	CWR;
+	u8	RETRY_CTR;
+	u8	reserved_18[5];
+	__le32	RDSAR;
+	u8	reserved_19[18];
+	u16	TALLY_CNT;
+	u8	TALLY_SEL;
+} __attribute__((packed));
+
+static const struct ieee80211_rate rtl818x_rates[] = {
+	{ .rate = 10,
+	  .val = 0,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 20,
+	  .val = 1,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 55,
+	  .val = 2,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 110,
+	  .val = 3,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 60,
+	  .val = 4,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 90,
+	  .val = 5,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 120,
+	  .val = 6,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 180,
+	  .val = 7,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 240,
+	  .val = 8,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 360,
+	  .val = 9,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 480,
+	  .val = 10,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 540,
+	  .val = 11,
+	  .flags = IEEE80211_RATE_OFDM },
+};
+
+static const struct ieee80211_channel rtl818x_channels[] = {
+	{ .chan = 1,
+	  .freq = 2412},
+	{ .chan = 2,
+	  .freq = 2417},
+	{ .chan = 3,
+	  .freq = 2422},
+	{ .chan = 4,
+	  .freq = 2427},
+	{ .chan = 5,
+	  .freq = 2432},
+	{ .chan = 6,
+	  .freq = 2437},
+	{ .chan = 7,
+	  .freq = 2442},
+	{ .chan = 8,
+	  .freq = 2447},
+	{ .chan = 9,
+	  .freq = 2452},
+	{ .chan = 10,
+	  .freq = 2457},
+	{ .chan = 11,
+	  .freq = 2462},
+	{ .chan = 12,
+	  .freq = 2467},
+	{ .chan = 13,
+	  .freq = 2472},
+	{ .chan = 14,
+	  .freq = 2484}
+};
+
+#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index ce9230b..c8b5c22 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1011,7 +1011,7 @@
 	} else {
 		skb->dev = dev;
 		skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
-		eth_copy_and_sum(skb, (unsigned char *)&sig.daddr, 12, 0);
+		skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12);
 		wl3501_receive(this, skb->data, pkt_len);
 		skb_put(skb, pkt_len);
 		skb->protocol	= eth_type_trans(skb, dev);
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 6603ad5..4d50590 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,7 +3,7 @@
 zd1211rw-objs := zd_chip.o zd_ieee80211.o \
 		zd_mac.o zd_netdev.o \
 		zd_rf_al2230.o zd_rf_rf2959.o \
-		zd_rf_al7230b.o \
+		zd_rf_al7230b.o zd_rf_uw2453.o \
 		zd_rf.o zd_usb.o zd_util.o
 
 ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 95b4a2a..c39f198 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -49,8 +49,9 @@
 	ZD_MEMCLEAR(chip, sizeof(*chip));
 }
 
-static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size)
+static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size)
 {
+	u8 *addr = zd_usb_to_netdev(&chip->usb)->dev_addr;
 	return scnprintf(buffer, size, "%02x-%02x-%02x",
 		         addr[0], addr[1], addr[2]);
 }
@@ -61,10 +62,10 @@
 	int i = 0;
 
 	i = scnprintf(buffer, size, "zd1211%s chip ",
-		      chip->is_zd1211b ? "b" : "");
+		      zd_chip_is_zd1211b(chip) ? "b" : "");
 	i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i);
 	i += scnprintf(buffer+i, size-i, " ");
-	i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
+	i += scnprint_mac_oui(chip, buffer+i, size-i);
 	i += scnprintf(buffer+i, size-i, " ");
 	i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
 	i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type,
@@ -366,64 +367,9 @@
 	return r;
 }
 
-static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr,
-	                  const zd_addr_t *addr)
-{
-	int r;
-	u32 parts[2];
-
-	r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2);
-	if (r) {
-		dev_dbg_f(zd_chip_dev(chip),
-			"error: couldn't read e2p macs. Error number %d\n", r);
-		return r;
-	}
-
-	mac_addr[0] = parts[0];
-	mac_addr[1] = parts[0] >>  8;
-	mac_addr[2] = parts[0] >> 16;
-	mac_addr[3] = parts[0] >> 24;
-	mac_addr[4] = parts[1];
-	mac_addr[5] = parts[1] >>  8;
-
-	return 0;
-}
-
-static int read_e2p_mac_addr(struct zd_chip *chip)
-{
-	static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 };
-
-	ZD_ASSERT(mutex_is_locked(&chip->mutex));
-	return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr);
-}
-
 /* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and
  *              CR_MAC_ADDR_P2 must be overwritten
  */
-void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
-	mutex_lock(&chip->mutex);
-	memcpy(mac_addr, chip->e2p_mac, ETH_ALEN);
-	mutex_unlock(&chip->mutex);
-}
-
-static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
-	static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 };
-	return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr);
-}
-
-int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
-	int r;
-
-	dev_dbg_f(zd_chip_dev(chip), "\n");
-	mutex_lock(&chip->mutex);
-	r = read_mac_addr(chip, mac_addr);
-	mutex_unlock(&chip->mutex);
-	return r;
-}
-
 int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
 {
 	int r;
@@ -444,12 +390,6 @@
 
 	mutex_lock(&chip->mutex);
 	r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
-#ifdef DEBUG
-	{
-		u8 tmp[ETH_ALEN];
-		read_mac_addr(chip, tmp);
-	}
-#endif /* DEBUG */
 	mutex_unlock(&chip->mutex);
 	return r;
 }
@@ -809,7 +749,7 @@
 
 static int hw_reset_phy(struct zd_chip *chip)
 {
-	return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) :
+	return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) :
 		                  zd1211_hw_reset_phy(chip);
 }
 
@@ -874,7 +814,7 @@
 	if (r)
 		return r;
 
-	return chip->is_zd1211b ?
+	return zd_chip_is_zd1211b(chip) ?
 		zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip);
 }
 
@@ -1136,8 +1076,15 @@
 	return 0;
 }
 
+/* Read mac address using pre-firmware interface */
+int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr)
+{
+	dev_dbg_f(zd_chip_dev(chip), "\n");
+	return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr,
+		ETH_ALEN);
+}
 
-int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
+int zd_chip_init_hw(struct zd_chip *chip)
 {
 	int r;
 	u8 rf_type;
@@ -1145,7 +1092,6 @@
 	dev_dbg_f(zd_chip_dev(chip), "\n");
 
 	mutex_lock(&chip->mutex);
-	chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0;
 
 #ifdef DEBUG
 	r = test_init(chip);
@@ -1201,10 +1147,6 @@
 		goto out;
 #endif /* DEBUG */
 
-	r = read_e2p_mac_addr(chip);
-	if (r)
-		goto out;
-
 	r = read_cal_int_tables(chip);
 	if (r)
 		goto out;
@@ -1253,10 +1195,13 @@
 {
 	int r;
 
+	if (!zd_rf_should_update_pwr_int(&chip->rf))
+		return 0;
+
 	r = update_pwr_int(chip, channel);
 	if (r)
 		return r;
-	if (chip->is_zd1211b) {
+	if (zd_chip_is_zd1211b(chip)) {
 		static const struct zd_ioreq16 ioreqs[] = {
 			{ CR69, 0x28 },
 			{},
@@ -1283,7 +1228,7 @@
 	int r;
 	u32 value;
 
-	if (!chip->patch_cck_gain)
+	if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
 		return 0;
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ce0a5f6..f469857 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -608,6 +608,9 @@
 #define CR_ZD1211B_TXOP			CTL_REG(0x0b20)
 #define CR_ZD1211B_RETRY_MAX		CTL_REG(0x0b28)
 
+/* Used to detect PLL lock */
+#define UW2453_INTR_REG			((zd_addr_t)0x85c1)
+
 #define CWIN_SIZE			0x007f043f
 
 
@@ -701,7 +704,6 @@
 	struct mutex mutex;
 	/* Base address of FW_REG_ registers */
 	zd_addr_t fw_regs_base;
-	u8 e2p_mac[ETH_ALEN];
 	/* EepSetPoint in the vendor driver */
 	u8 pwr_cal_values[E2P_CHANNEL_COUNT];
 	/* integration values in the vendor driver */
@@ -712,7 +714,7 @@
 	unsigned int pa_type:4,
 		patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
 		new_phy_layout:1, al2230s_bit:1,
-		is_zd1211b:1, supports_tx_led:1;
+		supports_tx_led:1;
 };
 
 static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
@@ -731,9 +733,15 @@
 	         struct net_device *netdev,
 	         struct usb_interface *intf);
 void zd_chip_clear(struct zd_chip *chip);
-int zd_chip_init_hw(struct zd_chip *chip, u8 device_type);
+int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr);
+int zd_chip_init_hw(struct zd_chip *chip);
 int zd_chip_reset(struct zd_chip *chip);
 
+static inline int zd_chip_is_zd1211b(struct zd_chip *chip)
+{
+	return chip->usb.is_zd1211b;
+}
+
 static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
 	                              const zd_addr_t *addresses,
 				      unsigned int count)
@@ -822,8 +830,6 @@
 }
 u8  zd_chip_get_channel(struct zd_chip *chip);
 int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
-void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr);
-int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr);
 int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
 int zd_chip_switch_radio_on(struct zd_chip *chip);
 int zd_chip_switch_radio_off(struct zd_chip *chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 6753d24..f6c487a 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -86,38 +86,46 @@
 	return r;
 }
 
-int zd_mac_init_hw(struct zd_mac *mac, u8 device_type)
+int zd_mac_preinit_hw(struct zd_mac *mac)
+{
+	int r;
+	u8 addr[ETH_ALEN];
+
+	r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
+	if (r)
+		return r;
+
+	memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
+	return 0;
+}
+
+int zd_mac_init_hw(struct zd_mac *mac)
 {
 	int r;
 	struct zd_chip *chip = &mac->chip;
-	u8 addr[ETH_ALEN];
 	u8 default_regdomain;
 
 	r = zd_chip_enable_int(chip);
 	if (r)
 		goto out;
-	r = zd_chip_init_hw(chip, device_type);
+	r = zd_chip_init_hw(chip);
 	if (r)
 		goto disable_int;
 
-	zd_get_e2p_mac_addr(chip, addr);
-	r = zd_write_mac_addr(chip, addr);
-	if (r)
-		goto disable_int;
 	ZD_ASSERT(!irqs_disabled());
-	spin_lock_irq(&mac->lock);
-	memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
-	spin_unlock_irq(&mac->lock);
 
 	r = zd_read_regdomain(chip, &default_regdomain);
 	if (r)
 		goto disable_int;
 	if (!zd_regdomain_supported(default_regdomain)) {
-		dev_dbg_f(zd_mac_dev(mac),
-			  "Regulatory Domain %#04x is not supported.\n",
-		          default_regdomain);
-		r = -EINVAL;
-		goto disable_int;
+		/* The vendor driver overrides the regulatory domain and
+		 * allowed channel registers and unconditionally restricts
+		 * available channels to 1-11 everywhere. Match their
+		 * questionable behaviour only for regdomains which we don't
+		 * recognise. */
+		dev_warn(zd_mac_dev(mac),  "Unrecognised regulatory domain: "
+			"%#04x. Defaulting to FCC.\n", default_regdomain);
+		default_regdomain = ZD_REGDOMAIN_FCC;
 	}
 	spin_lock_irq(&mac->lock);
 	mac->regdomain = mac->default_regdomain = default_regdomain;
@@ -164,14 +172,25 @@
 {
 	struct zd_mac *mac = zd_netdev_mac(netdev);
 	struct zd_chip *chip = &mac->chip;
+	struct zd_usb *usb = &chip->usb;
 	int r;
 
+	if (!usb->initialized) {
+		r = zd_usb_init_hw(usb);
+		if (r)
+			goto out;
+	}
+
 	tasklet_enable(&mac->rx_tasklet);
 
 	r = zd_chip_enable_int(chip);
 	if (r < 0)
 		goto out;
 
+	r = zd_write_mac_addr(chip, netdev->dev_addr);
+	if (r)
+		goto disable_int;
+
 	r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
 	if (r < 0)
 		goto disable_int;
@@ -251,9 +270,11 @@
 	dev_dbg_f(zd_mac_dev(mac),
 		  "Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data));
 
-	r = zd_write_mac_addr(chip, addr->sa_data);
-	if (r)
-		return r;
+	if (netdev->flags & IFF_UP) {
+		r = zd_write_mac_addr(chip, addr->sa_data);
+		if (r)
+			return r;
+	}
 
 	spin_lock_irqsave(&mac->lock, flags);
 	memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -855,7 +876,7 @@
 	/* ZD1211B: Computing the length difference this way, gives us
 	 * flexibility to compute the packet length.
 	 */
-	cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ?
+	cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
 			packet_length - frag_len : packet_length);
 
 	/*
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index faf4c78..9f9344e 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -189,7 +189,8 @@
 		struct usb_interface *intf);
 void zd_mac_clear(struct zd_mac *mac);
 
-int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
+int zd_mac_preinit_hw(struct zd_mac *mac);
+int zd_mac_init_hw(struct zd_mac *mac);
 
 int zd_mac_open(struct net_device *netdev);
 int zd_mac_stop(struct net_device *netdev);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 549c23b..abe5d38 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -34,7 +34,7 @@
 	[AL2210_RF]	= "AL2210_RF",
 	[MAXIM_NEW_RF]	= "MAXIM_NEW_RF",
 	[UW2453_RF]	= "UW2453_RF",
-	[UNKNOWN_A_RF]	= "UNKNOWN_A_RF",
+	[AL2230S_RF]	= "AL2230S_RF",
 	[RALINK_RF]	= "RALINK_RF",
 	[INTERSIL_RF]	= "INTERSIL_RF",
 	[RF2959_RF]	= "RF2959_RF",
@@ -52,34 +52,39 @@
 void zd_rf_init(struct zd_rf *rf)
 {
 	memset(rf, 0, sizeof(*rf));
+
+	/* default to update channel integration, as almost all RF's do want
+	 * this */
+	rf->update_channel_int = 1;
 }
 
 void zd_rf_clear(struct zd_rf *rf)
 {
+	if (rf->clear)
+		rf->clear(rf);
 	ZD_MEMCLEAR(rf, sizeof(*rf));
 }
 
 int zd_rf_init_hw(struct zd_rf *rf, u8 type)
 {
-	int r, t;
+	int r = 0;
+	int t;
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
 	switch (type) {
 	case RF2959_RF:
 		r = zd_rf_init_rf2959(rf);
-		if (r)
-			return r;
 		break;
 	case AL2230_RF:
+	case AL2230S_RF:
 		r = zd_rf_init_al2230(rf);
-		if (r)
-			return r;
 		break;
 	case AL7230B_RF:
 		r = zd_rf_init_al7230b(rf);
-		if (r)
-			return r;
+		break;
+	case UW2453_RF:
+		r = zd_rf_init_uw2453(rf);
 		break;
 	default:
 		dev_err(zd_chip_dev(chip),
@@ -88,6 +93,9 @@
 		return -ENODEV;
 	}
 
+	if (r)
+		return r;
+
 	rf->type = type;
 
 	r = zd_chip_lock_phy_regs(chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index aa9cc10..30502f2 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -26,7 +26,7 @@
 #define AL2210_RF			0x7
 #define MAXIM_NEW_RF			0x8
 #define UW2453_RF			0x9
-#define UNKNOWN_A_RF			0xa
+#define AL2230S_RF			0xa
 #define RALINK_RF			0xb
 #define INTERSIL_RF			0xc
 #define RF2959_RF			0xd
@@ -48,12 +48,26 @@
 
 	u8 channel;
 
+	/* whether channel integration and calibration should be updated
+	 * defaults to 1 (yes) */
+	u8 update_channel_int:1;
+
+	/* whether CR47 should be patched from the EEPROM, if the appropriate
+	 * flag is set in the POD. The vendor driver suggests that this should
+	 * be done for all RF's, but a bug in their code prevents but their
+	 * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
+	u8 patch_cck_gain:1;
+
+	/* private RF driver data */
+	void *priv;
+
 	/* RF-specific functions */
 	int (*init_hw)(struct zd_rf *rf);
 	int (*set_channel)(struct zd_rf *rf, u8 channel);
 	int (*switch_radio_on)(struct zd_rf *rf);
 	int (*switch_radio_off)(struct zd_rf *rf);
 	int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
+	void (*clear)(struct zd_rf *rf);
 };
 
 const char *zd_rf_name(u8 type);
@@ -71,10 +85,24 @@
 int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
 int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
 
+static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
+{
+	return rf->update_channel_int;
+}
+
+static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
+{
+	return rf->patch_cck_gain;
+}
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+
 /* Functions for individual RF chips */
 
 int zd_rf_init_rf2959(struct zd_rf *rf);
 int zd_rf_init_al2230(struct zd_rf *rf);
 int zd_rf_init_al7230b(struct zd_rf *rf);
+int zd_rf_init_uw2453(struct zd_rf *rf);
 
 #endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 511392a..006774d 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -21,6 +21,8 @@
 #include "zd_usb.h"
 #include "zd_chip.h"
 
+#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF)
+
 static const u32 zd1211_al2230_table[][3] = {
 	RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
 	RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
@@ -176,7 +178,7 @@
 	if (r)
 		return r;
 
-	if (chip->al2230s_bit) {
+	if (IS_AL2230S(chip)) {
 		r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
 			ARRAY_SIZE(ioreqs_init_al2230s));
 		if (r)
@@ -188,7 +190,7 @@
 		return r;
 
 	/* improve band edge for AL2230S */
-	if (chip->al2230s_bit)
+	if (IS_AL2230S(chip))
 		r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS);
 	else
 		r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS);
@@ -314,7 +316,7 @@
 	if (r)
 		return r;
 
-	if (chip->al2230s_bit) {
+	if (IS_AL2230S(chip)) {
 		r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
 			ARRAY_SIZE(ioreqs_init_al2230s));
 		if (r)
@@ -328,7 +330,7 @@
 	if (r)
 		return r;
 
-	if (chip->al2230s_bit)
+	if (IS_AL2230S(chip))
 		r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS);
 	else
 		r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS);
@@ -422,7 +424,7 @@
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
 	rf->switch_radio_off = al2230_switch_radio_off;
-	if (chip->is_zd1211b) {
+	if (zd_chip_is_zd1211b(chip)) {
 		rf->init_hw = zd1211b_al2230_init_hw;
 		rf->set_channel = zd1211b_al2230_set_channel;
 		rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
@@ -432,5 +434,6 @@
 		rf->switch_radio_on = zd1211_al2230_switch_radio_on;
 	}
 	rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+	rf->patch_cck_gain = 1;
 	return 0;
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index 5e5e9dd..73d0bb2 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -473,7 +473,7 @@
 {
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
-	if (chip->is_zd1211b) {
+	if (zd_chip_is_zd1211b(chip)) {
 		rf->init_hw = zd1211b_al7230b_init_hw;
 		rf->switch_radio_on = zd1211b_al7230b_switch_radio_on;
 		rf->set_channel = zd1211b_al7230b_set_channel;
@@ -483,6 +483,7 @@
 		rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
 		rf->set_channel = zd1211_al7230b_set_channel;
 		rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+		rf->patch_cck_gain = 1;
 	}
 
 	rf->switch_radio_off = al7230b_switch_radio_off;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
index 2d736bd..cc70d40 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
@@ -265,7 +265,7 @@
 {
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
-	if (chip->is_zd1211b) {
+	if (zd_chip_is_zd1211b(chip)) {
 		dev_err(zd_chip_dev(chip),
 		       "RF2959 is currently not supported for ZD1211B"
 		       " devices\n");
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
new file mode 100644
index 0000000..857dcf3
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -0,0 +1,534 @@
+/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+/* This RF programming code is based upon the code found in v2.16.0.0 of the
+ * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
+ * for this RF on their website, so we're able to understand more than
+ * usual as to what is going on. Thumbs up for Ubec for doing that. */
+
+/* The 3-wire serial interface provides access to 8 write-only registers.
+ * The data format is a 4 bit register address followed by a 20 bit value. */
+#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
+
+/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
+ * fractional divide ratio) and 3 (VCO config).
+ *
+ * We configure the RF to produce an interrupt when the PLL is locked onto
+ * the configured frequency. During initialization, we run through a variety
+ * of different VCO configurations on channel 1 until we detect a PLL lock.
+ * When this happens, we remember which VCO configuration produced the lock
+ * and use it later. Actually, we use the configuration *after* the one that
+ * produced the lock, which seems odd, but it works.
+ *
+ * If we do not see a PLL lock on any standard VCO config, we fall back on an
+ * autocal configuration, which has a fixed (as opposed to per-channel) VCO
+ * config and different synth values from the standard set (divide ratio
+ * is still shared with the standard set). */
+
+/* The per-channel synth values for all standard VCO configurations. These get
+ * written to register 1. */
+static const u8 uw2453_std_synth[] = {
+	RF_CHANNEL( 1) = 0x47,
+	RF_CHANNEL( 2) = 0x47,
+	RF_CHANNEL( 3) = 0x67,
+	RF_CHANNEL( 4) = 0x67,
+	RF_CHANNEL( 5) = 0x67,
+	RF_CHANNEL( 6) = 0x67,
+	RF_CHANNEL( 7) = 0x57,
+	RF_CHANNEL( 8) = 0x57,
+	RF_CHANNEL( 9) = 0x57,
+	RF_CHANNEL(10) = 0x57,
+	RF_CHANNEL(11) = 0x77,
+	RF_CHANNEL(12) = 0x77,
+	RF_CHANNEL(13) = 0x77,
+	RF_CHANNEL(14) = 0x4f,
+};
+
+/* This table stores the synthesizer fractional divide ratio for *all* VCO
+ * configurations (both standard and autocal). These get written to register 2.
+ */
+static const u16 uw2453_synth_divide[] = {
+	RF_CHANNEL( 1) = 0x999,
+	RF_CHANNEL( 2) = 0x99b,
+	RF_CHANNEL( 3) = 0x998,
+	RF_CHANNEL( 4) = 0x99a,
+	RF_CHANNEL( 5) = 0x999,
+	RF_CHANNEL( 6) = 0x99b,
+	RF_CHANNEL( 7) = 0x998,
+	RF_CHANNEL( 8) = 0x99a,
+	RF_CHANNEL( 9) = 0x999,
+	RF_CHANNEL(10) = 0x99b,
+	RF_CHANNEL(11) = 0x998,
+	RF_CHANNEL(12) = 0x99a,
+	RF_CHANNEL(13) = 0x999,
+	RF_CHANNEL(14) = 0xccc,
+};
+
+/* Here is the data for all the standard VCO configurations. We shrink our
+ * table a little by observing that both channels in a consecutive pair share
+ * the same value. We also observe that the high 4 bits ([0:3] in the specs)
+ * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
+ * below. */
+#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
+#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
+static const u16 uw2453_std_vco_cfg[][7] = {
+	{ /* table 1 */
+		RF_CHANPAIR( 1,  2) = 0x664d,
+		RF_CHANPAIR( 3,  4) = 0x604d,
+		RF_CHANPAIR( 5,  6) = 0x6675,
+		RF_CHANPAIR( 7,  8) = 0x6475,
+		RF_CHANPAIR( 9, 10) = 0x6655,
+		RF_CHANPAIR(11, 12) = 0x6455,
+		RF_CHANPAIR(13, 14) = 0x6665,
+	},
+	{ /* table 2 */
+		RF_CHANPAIR( 1,  2) = 0x666d,
+		RF_CHANPAIR( 3,  4) = 0x606d,
+		RF_CHANPAIR( 5,  6) = 0x664d,
+		RF_CHANPAIR( 7,  8) = 0x644d,
+		RF_CHANPAIR( 9, 10) = 0x6675,
+		RF_CHANPAIR(11, 12) = 0x6475,
+		RF_CHANPAIR(13, 14) = 0x6655,
+	},
+	{ /* table 3 */
+		RF_CHANPAIR( 1,  2) = 0x665d,
+		RF_CHANPAIR( 3,  4) = 0x605d,
+		RF_CHANPAIR( 5,  6) = 0x666d,
+		RF_CHANPAIR( 7,  8) = 0x646d,
+		RF_CHANPAIR( 9, 10) = 0x664d,
+		RF_CHANPAIR(11, 12) = 0x644d,
+		RF_CHANPAIR(13, 14) = 0x6675,
+	},
+	{ /* table 4 */
+		RF_CHANPAIR( 1,  2) = 0x667d,
+		RF_CHANPAIR( 3,  4) = 0x607d,
+		RF_CHANPAIR( 5,  6) = 0x665d,
+		RF_CHANPAIR( 7,  8) = 0x645d,
+		RF_CHANPAIR( 9, 10) = 0x666d,
+		RF_CHANPAIR(11, 12) = 0x646d,
+		RF_CHANPAIR(13, 14) = 0x664d,
+	},
+	{ /* table 5 */
+		RF_CHANPAIR( 1,  2) = 0x6643,
+		RF_CHANPAIR( 3,  4) = 0x6043,
+		RF_CHANPAIR( 5,  6) = 0x667d,
+		RF_CHANPAIR( 7,  8) = 0x647d,
+		RF_CHANPAIR( 9, 10) = 0x665d,
+		RF_CHANPAIR(11, 12) = 0x645d,
+		RF_CHANPAIR(13, 14) = 0x666d,
+	},
+	{ /* table 6 */
+		RF_CHANPAIR( 1,  2) = 0x6663,
+		RF_CHANPAIR( 3,  4) = 0x6063,
+		RF_CHANPAIR( 5,  6) = 0x6643,
+		RF_CHANPAIR( 7,  8) = 0x6443,
+		RF_CHANPAIR( 9, 10) = 0x667d,
+		RF_CHANPAIR(11, 12) = 0x647d,
+		RF_CHANPAIR(13, 14) = 0x665d,
+	},
+	{ /* table 7 */
+		RF_CHANPAIR( 1,  2) = 0x6653,
+		RF_CHANPAIR( 3,  4) = 0x6053,
+		RF_CHANPAIR( 5,  6) = 0x6663,
+		RF_CHANPAIR( 7,  8) = 0x6463,
+		RF_CHANPAIR( 9, 10) = 0x6643,
+		RF_CHANPAIR(11, 12) = 0x6443,
+		RF_CHANPAIR(13, 14) = 0x667d,
+	},
+	{ /* table 8 */
+		RF_CHANPAIR( 1,  2) = 0x6673,
+		RF_CHANPAIR( 3,  4) = 0x6073,
+		RF_CHANPAIR( 5,  6) = 0x6653,
+		RF_CHANPAIR( 7,  8) = 0x6453,
+		RF_CHANPAIR( 9, 10) = 0x6663,
+		RF_CHANPAIR(11, 12) = 0x6463,
+		RF_CHANPAIR(13, 14) = 0x6643,
+	},
+	{ /* table 9 */
+		RF_CHANPAIR( 1,  2) = 0x664b,
+		RF_CHANPAIR( 3,  4) = 0x604b,
+		RF_CHANPAIR( 5,  6) = 0x6673,
+		RF_CHANPAIR( 7,  8) = 0x6473,
+		RF_CHANPAIR( 9, 10) = 0x6653,
+		RF_CHANPAIR(11, 12) = 0x6453,
+		RF_CHANPAIR(13, 14) = 0x6663,
+	},
+	{ /* table 10 */
+		RF_CHANPAIR( 1,  2) = 0x666b,
+		RF_CHANPAIR( 3,  4) = 0x606b,
+		RF_CHANPAIR( 5,  6) = 0x664b,
+		RF_CHANPAIR( 7,  8) = 0x644b,
+		RF_CHANPAIR( 9, 10) = 0x6673,
+		RF_CHANPAIR(11, 12) = 0x6473,
+		RF_CHANPAIR(13, 14) = 0x6653,
+	},
+	{ /* table 11 */
+		RF_CHANPAIR( 1,  2) = 0x665b,
+		RF_CHANPAIR( 3,  4) = 0x605b,
+		RF_CHANPAIR( 5,  6) = 0x666b,
+		RF_CHANPAIR( 7,  8) = 0x646b,
+		RF_CHANPAIR( 9, 10) = 0x664b,
+		RF_CHANPAIR(11, 12) = 0x644b,
+		RF_CHANPAIR(13, 14) = 0x6673,
+	},
+
+};
+
+/* The per-channel synth values for autocal. These get written to register 1. */
+static const u16 uw2453_autocal_synth[] = {
+	RF_CHANNEL( 1) = 0x6847,
+	RF_CHANNEL( 2) = 0x6847,
+	RF_CHANNEL( 3) = 0x6867,
+	RF_CHANNEL( 4) = 0x6867,
+	RF_CHANNEL( 5) = 0x6867,
+	RF_CHANNEL( 6) = 0x6867,
+	RF_CHANNEL( 7) = 0x6857,
+	RF_CHANNEL( 8) = 0x6857,
+	RF_CHANNEL( 9) = 0x6857,
+	RF_CHANNEL(10) = 0x6857,
+	RF_CHANNEL(11) = 0x6877,
+	RF_CHANNEL(12) = 0x6877,
+	RF_CHANNEL(13) = 0x6877,
+	RF_CHANNEL(14) = 0x684f,
+};
+
+/* The VCO configuration for autocal (all channels) */
+static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
+
+/* TX gain settings. The array index corresponds to the TX power integration
+ * values found in the EEPROM. The values get written to register 7. */
+static u32 uw2453_txgain[] = {
+	[0x00] = 0x0e313,
+	[0x01] = 0x0fb13,
+	[0x02] = 0x0e093,
+	[0x03] = 0x0f893,
+	[0x04] = 0x0ea93,
+	[0x05] = 0x1f093,
+	[0x06] = 0x1f493,
+	[0x07] = 0x1f693,
+	[0x08] = 0x1f393,
+	[0x09] = 0x1f35b,
+	[0x0a] = 0x1e6db,
+	[0x0b] = 0x1ff3f,
+	[0x0c] = 0x1ffff,
+	[0x0d] = 0x361d7,
+	[0x0e] = 0x37fbf,
+	[0x0f] = 0x3ff8b,
+	[0x10] = 0x3ff33,
+	[0x11] = 0x3fb3f,
+	[0x12] = 0x3ffff,
+};
+
+/* RF-specific structure */
+struct uw2453_priv {
+	/* index into synth/VCO config tables where PLL lock was found
+	 * -1 means autocal */
+	int config;
+};
+
+#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
+
+static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
+	bool autocal)
+{
+	int r;
+	int idx = channel - 1;
+	u32 val;
+
+	if (autocal)
+		val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
+	else
+		val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
+
+	r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
+	if (r)
+		return r;
+
+	return zd_rfwrite_locked(chip,
+		UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
+}
+
+static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
+{
+	/* vendor driver always sets these upper bits even though the specs say
+	 * they are reserved */
+	u32 val = 0x40000 | value;
+	return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
+}
+
+static int uw2453_init_mode(struct zd_chip *chip)
+{
+	static const u32 rv[] = {
+		UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
+		UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
+		UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
+		UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
+	};
+
+	return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
+{
+	u8 int_value = chip->pwr_int_values[channel - 1];
+
+	if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
+		dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
+			  "int value %x on channel %d\n", int_value, channel);
+		return 0;
+	}
+
+	return zd_rfwrite_locked(chip,
+		UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
+}
+
+static int uw2453_init_hw(struct zd_rf *rf)
+{
+	int i, r;
+	int found_config = -1;
+	u16 intr_status;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR10,  0x89 }, { CR15,  0x20 },
+		{ CR17,  0x28 }, /* 6112 no change */
+		{ CR23,  0x38 }, { CR24,  0x20 }, { CR26,  0x93 },
+		{ CR27,  0x15 }, { CR28,  0x3e }, { CR29,  0x00 },
+		{ CR33,  0x28 }, { CR34,  0x30 },
+		{ CR35,  0x43 }, /* 6112 3e->43 */
+		{ CR41,  0x24 }, { CR44,  0x32 },
+		{ CR46,  0x92 }, /* 6112 96->92 */
+		{ CR47,  0x1e },
+		{ CR48,  0x04 }, /* 5602 Roger */
+		{ CR49,  0xfa }, { CR79,  0x58 }, { CR80,  0x30 },
+		{ CR81,  0x30 }, { CR87,  0x0a }, { CR89,  0x04 },
+		{ CR91,  0x00 }, { CR92,  0x0a }, { CR98,  0x8d },
+		{ CR99,  0x28 }, { CR100, 0x02 },
+		{ CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
+		{ CR102, 0x27 },
+		{ CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
+		{ CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
+		{ CR109, 0x13 },
+		{ CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
+		{ CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
+		{ CR114, 0x23 }, /* 6221 27->23 */
+		{ CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
+		{ CR116, 0x24 }, /* 6220 1c->24 */
+		{ CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
+		{ CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
+		{ CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
+		{ CR120, 0x4f },
+		{ CR121, 0x1f }, /* 6220 4f->1f */
+		{ CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
+		{ CR126, 0x6c }, { CR127, 0x03 },
+		{ CR128, 0x14 }, /* 6302 12->11 */
+		{ CR129, 0x12 }, /* 6301 10->0f */
+		{ CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
+		{ CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
+		{ CR253, 0xff },
+	};
+
+	static const u32 rv[] = {
+		UW2453_REGWRITE(4, 0x2b),    /* configure reciever gain */
+		UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
+		UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
+		UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
+
+		/* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
+		 * RSSI circuit powered down, reduced RSSI range */
+		UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
+
+		/* synthesizer configuration for channel 1 */
+		UW2453_REGWRITE(1, 0x47),
+		UW2453_REGWRITE(2, 0x999),
+
+		/* disable manual VCO band selection */
+		UW2453_REGWRITE(3, 0x7602),
+
+		/* enable manual VCO band selection, configure current level */
+		UW2453_REGWRITE(3, 0x46063),
+	};
+
+	r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	if (r)
+		return r;
+
+	r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+	if (r)
+		return r;
+
+	r = uw2453_init_mode(chip);
+	if (r)
+		return r;
+
+	/* Try all standard VCO configuration settings on channel 1 */
+	for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
+		/* Configure synthesizer for channel 1 */
+		r = uw2453_synth_set_channel(chip, 1, false);
+		if (r)
+			return r;
+
+		/* Write VCO config */
+		r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
+		if (r)
+			return r;
+
+		/* ack interrupt event */
+		r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
+		if (r)
+			return r;
+
+		/* check interrupt status */
+		r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
+		if (r)
+			return r;
+
+		if (!intr_status & 0xf) {
+			dev_dbg_f(zd_chip_dev(chip),
+				"PLL locked on configuration %d\n", i);
+			found_config = i;
+			break;
+		}
+	}
+
+	if (found_config == -1) {
+		/* autocal */
+		dev_dbg_f(zd_chip_dev(chip),
+			"PLL did not lock, using autocal\n");
+
+		r = uw2453_synth_set_channel(chip, 1, true);
+		if (r)
+			return r;
+
+		r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
+		if (r)
+			return r;
+	}
+
+	/* To match the vendor driver behaviour, we use the configuration after
+	 * the one that produced a lock. */
+	UW2453_PRIV(rf)->config = found_config + 1;
+
+	return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
+{
+	int r;
+	u16 vco_cfg;
+	int config = UW2453_PRIV(rf)->config;
+	bool autocal = (config == -1);
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR80,  0x30 }, { CR81,  0x30 }, { CR79,  0x58 },
+		{ CR12,  0xf0 }, { CR77,  0x1b }, { CR78,  0x58 },
+	};
+
+	r = uw2453_synth_set_channel(chip, channel, autocal);
+	if (r)
+		return r;
+
+	if (autocal)
+		vco_cfg = UW2453_AUTOCAL_VCO_CFG;
+	else
+		vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
+
+	r = uw2453_write_vco_cfg(chip, vco_cfg);
+	if (r)
+		return r;
+
+	r = uw2453_init_mode(chip);
+	if (r)
+		return r;
+
+	r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	if (r)
+		return r;
+
+	r = uw2453_set_tx_gain_level(chip, channel);
+	if (r)
+		return r;
+
+	return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_switch_radio_on(struct zd_rf *rf)
+{
+	int r;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+	struct zd_ioreq16 ioreqs[] = {
+		{ CR11,  0x00 }, { CR251, 0x3f },
+	};
+
+	/* enter RXTX mode */
+	r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
+	if (r)
+		return r;
+
+	if (zd_chip_is_zd1211b(chip))
+		ioreqs[1].value = 0x7f;
+
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int uw2453_switch_radio_off(struct zd_rf *rf)
+{
+	int r;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR11,  0x04 }, { CR251, 0x2f },
+	};
+
+	/* enter IDLE mode */
+	/* FIXME: shouldn't we go to SLEEP? sent email to zydas */
+	r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
+	if (r)
+		return r;
+
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static void uw2453_clear(struct zd_rf *rf)
+{
+	kfree(rf->priv);
+}
+
+int zd_rf_init_uw2453(struct zd_rf *rf)
+{
+	rf->init_hw = uw2453_init_hw;
+	rf->set_channel = uw2453_set_channel;
+	rf->switch_radio_on = uw2453_switch_radio_on;
+	rf->switch_radio_off = uw2453_switch_radio_off;
+	rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+	rf->clear = uw2453_clear;
+	/* we have our own TX integration code */
+	rf->update_channel_int = 0;
+
+	rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
+	if (rf->priv == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 8459549..28d41a2 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -15,7 +15,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <asm/unaligned.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -26,6 +25,7 @@
 #include <linux/usb.h>
 #include <linux/workqueue.h>
 #include <net/ieee80211.h>
+#include <asm/unaligned.h>
 
 #include "zd_def.h"
 #include "zd_netdev.h"
@@ -54,6 +54,7 @@
 	{ USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
 	/* ZD1211B */
 	{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
@@ -70,6 +71,7 @@
 	{ USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
 	/* "Driverless" devices that need ejecting */
 	{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
 	{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
@@ -194,26 +196,27 @@
 	return le16_to_cpu(p[offset]);
 }
 
-static char *get_fw_name(char *buffer, size_t size, u8 device_type,
+static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size,
 	               const char* postfix)
 {
 	scnprintf(buffer, size, "%s%s",
-		device_type == DEVICE_ZD1211B ?
+		usb->is_zd1211b ?
 			FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX,
 		postfix);
 	return buffer;
 }
 
-static int handle_version_mismatch(struct usb_device *udev, u8 device_type,
+static int handle_version_mismatch(struct zd_usb *usb,
 	const struct firmware *ub_fw)
 {
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	const struct firmware *ur_fw = NULL;
 	int offset;
 	int r = 0;
 	char fw_name[128];
 
 	r = request_fw_file(&ur_fw,
-		get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"),
+		get_fw_name(usb, fw_name, sizeof(fw_name), "ur"),
 		&udev->dev);
 	if (r)
 		goto error;
@@ -236,11 +239,12 @@
 	return r;
 }
 
-static int upload_firmware(struct usb_device *udev, u8 device_type)
+static int upload_firmware(struct zd_usb *usb)
 {
 	int r;
 	u16 fw_bcdDevice;
 	u16 bcdDevice;
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	const struct firmware *ub_fw = NULL;
 	const struct firmware *uph_fw = NULL;
 	char fw_name[128];
@@ -248,7 +252,7 @@
 	bcdDevice = get_bcdDevice(udev);
 
 	r = request_fw_file(&ub_fw,
-		get_fw_name(fw_name, sizeof(fw_name), device_type,  "ub"),
+		get_fw_name(usb, fw_name, sizeof(fw_name), "ub"),
 		&udev->dev);
 	if (r)
 		goto error;
@@ -263,7 +267,7 @@
 			dev_warn(&udev->dev, "device has old bootcode, please "
 				"report success or failure\n");
 
-		r = handle_version_mismatch(udev, device_type, ub_fw);
+		r = handle_version_mismatch(usb, ub_fw);
 		if (r)
 			goto error;
 	} else {
@@ -274,7 +278,7 @@
 
 
 	r = request_fw_file(&uph_fw,
-		get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"),
+		get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"),
 		&udev->dev);
 	if (r)
 		goto error;
@@ -293,6 +297,30 @@
 	return r;
 }
 
+/* Read data from device address space using "firmware interface" which does
+ * not require firmware to be loaded. */
+int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
+{
+	int r;
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
+
+	r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+		USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0,
+		data, len, 5000);
+	if (r < 0) {
+		dev_err(&udev->dev,
+			"read over firmware interface failed: %d\n", r);
+		return r;
+	} else if (r != len) {
+		dev_err(&udev->dev,
+			"incomplete read over firmware interface: %d/%d\n",
+			r, len);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 #define urb_dev(urb) (&(urb)->dev->dev)
 
 static inline void handle_regs_int(struct urb *urb)
@@ -919,9 +947,42 @@
 	return 0;
 }
 
+int zd_usb_init_hw(struct zd_usb *usb)
+{
+	int r;
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	r = upload_firmware(usb);
+	if (r) {
+		dev_err(zd_usb_dev(usb),
+		       "couldn't load firmware. Error number %d\n", r);
+		return r;
+	}
+
+	r = usb_reset_configuration(zd_usb_to_usbdev(usb));
+	if (r) {
+		dev_dbg_f(zd_usb_dev(usb),
+			"couldn't reset configuration. Error number %d\n", r);
+		return r;
+	}
+
+	r = zd_mac_init_hw(mac);
+	if (r) {
+		dev_dbg_f(zd_usb_dev(usb),
+		         "couldn't initialize mac. Error number %d\n", r);
+		return r;
+	}
+
+	usb->initialized = 1;
+	return 0;
+}
+
 static int probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	int r;
+	struct zd_usb *usb;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct net_device *netdev = NULL;
 
@@ -949,26 +1010,10 @@
 		goto error;
 	}
 
-	r = upload_firmware(udev, id->driver_info);
-	if (r) {
-		dev_err(&intf->dev,
-		       "couldn't load firmware. Error number %d\n", r);
-		goto error;
-	}
+	usb = &zd_netdev_mac(netdev)->chip.usb;
+	usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;
 
-	r = usb_reset_configuration(udev);
-	if (r) {
-		dev_dbg_f(&intf->dev,
-			"couldn't reset configuration. Error number %d\n", r);
-		goto error;
-	}
-
-	/* At this point the interrupt endpoint is not generally enabled. We
-	 * save the USB bandwidth until the network device is opened. But
-	 * notify that the initialization of the MAC will require the
-	 * interrupts to be temporary enabled.
-	 */
-	r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info);
+	r = zd_mac_preinit_hw(zd_netdev_mac(netdev));
 	if (r) {
 		dev_dbg_f(&intf->dev,
 		         "couldn't initialize mac. Error number %d\n", r);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index 506ea6a..961a7a1 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -188,6 +188,7 @@
 	struct zd_usb_rx rx;
 	struct zd_usb_tx tx;
 	struct usb_interface *intf;
+	u8 is_zd1211b:1, initialized:1;
 };
 
 #define zd_usb_dev(usb) (&usb->intf->dev)
@@ -236,6 +237,8 @@
 
 int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
 
+int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len);
+
 extern struct workqueue_struct *zd_workqueue;
 
 #endif /* _ZD_USB_H */
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index f2a90a7..870c539 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1137,7 +1137,7 @@
 				if (skb == NULL)
 					break;
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
-				eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, rx_skb->data, pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(yp->pci_dev, desc->addr,
 											   yp->rx_buf_sz,
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 78c2e6e..edd6de9 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -26,6 +26,7 @@
 #include <linux/profile.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/sched.h>
  
 #include "oprofile_stats.h"
 #include "event_buffer.h"
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 894fdb9..b3c4dbf 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -32,6 +32,7 @@
 */
 
 #include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
@@ -292,7 +293,6 @@
 #define PDIR_INDEX(iovp)    ((iovp)>>IOVP_SHIFT)
 #define MKIOVP(pdir_idx)    ((long)(pdir_idx) << IOVP_SHIFT)
 #define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
-#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
 
 /*
 ** Don't worry about the 150% average search length on a miss.
@@ -668,7 +668,7 @@
 	size_t saved_byte_cnt;
 
 	/* round up to nearest page size */
-	saved_byte_cnt = byte_cnt = ROUNDUP(byte_cnt, IOVP_SIZE);
+	saved_byte_cnt = byte_cnt = ALIGN(byte_cnt, IOVP_SIZE);
 
 	while(byte_cnt > 0) {
 		/* invalidate one page at a time */
@@ -751,7 +751,7 @@
 	offset = ((unsigned long) addr) & ~IOVP_MASK;
 
 	/* round up to nearest IOVP_SIZE */
-	size = ROUNDUP(size + offset, IOVP_SIZE);
+	size = ALIGN(size + offset, IOVP_SIZE);
 	spin_lock_irqsave(&ioc->res_lock, flags);
 
 #ifdef CCIO_MAP_STATS
@@ -814,7 +814,7 @@
 
 	iova ^= offset;        /* clear offset bits */
 	size += offset;
-	size = ROUNDUP(size, IOVP_SIZE);
+	size = ALIGN(size, IOVP_SIZE);
 
 	spin_lock_irqsave(&ioc->res_lock, flags);
 
@@ -1227,7 +1227,7 @@
 #endif /* 0 */
 
 /* We *can't* support JAVA (T600). Venture there at your own risk. */
-static struct parisc_device_id ccio_tbl[] = {
+static const struct parisc_device_id ccio_tbl[] = {
 	{ HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */
 	{ HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */
 	{ 0, }
@@ -1370,7 +1370,7 @@
 	}
 }
 
-static void
+static void __init
 ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr)
 {
 	int result;
@@ -1537,7 +1537,7 @@
  * If so, initialize the chip and tell other partners in crime they
  * have work to do.
  */
-static int ccio_probe(struct parisc_device *dev)
+static int __init ccio_probe(struct parisc_device *dev)
 {
 	int i;
 	struct ioc *ioc, **ioc_p = &ioc_list;
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 309076b..771cef5 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -307,7 +307,7 @@
 
 #define is_mongoose(dev) (dev->id.sversion == 0x00076)
 
-static int __devinit eisa_probe(struct parisc_device *dev)
+static int __init eisa_probe(struct parisc_device *dev)
 {
 	int i, result;
 
@@ -387,7 +387,7 @@
 	return 0;
 }
 
-static struct parisc_device_id eisa_tbl[] = {
+static const struct parisc_device_id eisa_tbl[] = {
 	{ HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00076 }, /* Mongoose */
 	{ HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00090 }, /* Wax EISA */
 	{ 0, }
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index a68b3b3..a728a7c 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/dma-mapping.h>
 #include <linux/ioport.h>
 
 #include <asm/io.h>
diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h
index 38d9e1a..0a1f99a 100644
--- a/drivers/parisc/iommu-helpers.h
+++ b/drivers/parisc/iommu-helpers.h
@@ -138,7 +138,7 @@
 			** exceed DMA_CHUNK_SIZE if we coalesce the
 			** next entry.
 			*/   
-			if(unlikely(ROUNDUP(dma_len + dma_offset + startsg->length,
+			if(unlikely(ALIGN(dma_len + dma_offset + startsg->length,
 					    IOVP_SIZE) > DMA_CHUNK_SIZE))
 				break;
 
@@ -158,7 +158,7 @@
 		** Allocate space for DMA stream.
 		*/
 		sg_dma_len(contig_sg) = dma_len;
-		dma_len = ROUNDUP(dma_len + dma_offset, IOVP_SIZE);
+		dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
 		sg_dma_address(contig_sg) =
 			PIDE_FLAG 
 			| (iommu_alloc_range(ioc, dma_len) << IOVP_SHIFT)
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 98be288..e5d7ed9 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -195,12 +195,6 @@
 
 	cur = lbuf;
 
-	/* skip initial spaces */
-	while (*cur && isspace(*cur))
-	{
-		cur++;
-	}
-
 	switch ((long)data)
 	{
 	case LED_NOLCD:
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 815e445..fc4bde2 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -121,14 +121,14 @@
 
 #define PDCS_ATTR(_name, _mode, _show, _store) \
 struct subsys_attribute pdcs_attr_##_name = { \
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+	.attr = {.name = __stringify(_name), .mode = _mode}, \
 	.show = _show, \
 	.store = _store, \
 };
 
 #define PATHS_ATTR(_name, _mode, _show, _store) \
 struct pdcspath_attribute paths_attr_##_name = { \
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+	.attr = {.name = __stringify(_name), .mode = _mode}, \
 	.show = _show, \
 	.store = _store, \
 };
@@ -1067,7 +1067,7 @@
 			error = subsys_create_file(&stable_subsys, attr);
 	
 	/* register the paths subsys as a subsystem of stable subsys */
-	kset_set_kset_s(&paths_subsys, stable_subsys);
+	kobj_set_kset_s(&paths_subsys, stable_subsys);
 	if ((rc = subsystem_register(&paths_subsys)))
 		goto fail_subsysreg;
 
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index 6dedbde..90cca5e 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -41,6 +41,7 @@
 #include <linux/reboot.h>
 #include <linux/sched.h>
 #include <linux/kthread.h>
+#include <linux/pm.h>
 
 #include <asm/pdc.h>
 #include <asm/io.h>
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 322957a..d044c48 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -113,8 +113,6 @@
 MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART");
 #endif
 
-#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
-
 
 /************************************
 ** SBA register read and write support
@@ -352,7 +350,7 @@
 		** SBA HW features in the unmap path.
 		*/
 		unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT);
-		uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
+		uint bitshiftcnt = ALIGN(ioc->res_bitshift, o);
 		unsigned long mask;
 
 		if (bitshiftcnt >= BITS_PER_LONG) {
@@ -779,7 +777,7 @@
 	offset = iova & ~IOVP_MASK;
 	iova ^= offset;        /* clear offset bits */
 	size += offset;
-	size = ROUNDUP(size, IOVP_SIZE);
+	size = ALIGN(size, IOVP_SIZE);
 
 	spin_lock_irqsave(&ioc->res_lock, flags);
 
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 1fd97f7..a708c32 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -389,7 +389,7 @@
 	return local_irq;
 }
 
-static void __devinit superio_serial_init(void)
+static void __init superio_serial_init(void)
 {
 #ifdef CONFIG_SERIAL_8250
 	int retval;
@@ -423,7 +423,7 @@
 }
 
 
-static void __devinit superio_parport_init(void)
+static void __init superio_parport_init(void)
 {
 #ifdef CONFIG_PARPORT_PC
 	if (!parport_pc_probe_port(sio_dev.pp_base,
@@ -450,7 +450,7 @@
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci);
 
 
-static int __devinit
+static int __init
 superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct superio_device *sio = &sio_dev;
@@ -485,7 +485,7 @@
 	return -ENODEV;
 }
 
-static struct pci_device_id superio_tbl[] = {
+static const struct pci_device_id superio_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) },
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index f46c69e4..09c93ff9 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -5,11 +5,9 @@
 # Parport configuration.
 #
 
-menu "Parallel port support"
-	depends on HAS_IOMEM
-
-config PARPORT
+menuconfig PARPORT
 	tristate "Parallel port support"
+	depends on HAS_IOMEM
 	---help---
 	  If you want to use devices connected to your machine's parallel port
 	  (the connector at the computer with 25 holes), e.g. printer, ZIP
@@ -33,9 +31,11 @@
 
 	  If unsure, say Y.
 
+if PARPORT
+
 config PARPORT_PC
 	tristate "PC-style hardware"
-	depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
+	depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
 	---help---
 	  You should say Y here if you have a PC-style parallel port. All
 	  IBM PC compatible computers and some Alphas have PC-style
@@ -85,7 +85,7 @@
 
 config PARPORT_IP32
 	tristate "SGI IP32 builtin port (EXPERIMENTAL)"
-	depends on SGI_IP32 && PARPORT && EXPERIMENTAL
+	depends on SGI_IP32 && EXPERIMENTAL
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port on
@@ -94,7 +94,7 @@
 
 config PARPORT_AMIGA
 	tristate "Amiga builtin port"
-	depends on AMIGA && PARPORT
+	depends on AMIGA
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port hardware on
@@ -103,7 +103,7 @@
 
 config PARPORT_MFC3
 	tristate "Multiface III parallel port"
-	depends on ZORRO && PARPORT
+	depends on ZORRO
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need parallel port support for the MFC3 card.
@@ -112,7 +112,7 @@
 
 config PARPORT_ATARI
 	tristate "Atari hardware"
-	depends on ATARI && PARPORT
+	depends on ATARI
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port hardware on
@@ -122,12 +122,11 @@
 config PARPORT_GSC
 	tristate
 	default GSC
-	depends on PARPORT
 	select PARPORT_NOT_PC
 
 config PARPORT_SUNBPP
 	tristate "Sparc hardware (EXPERIMENTAL)"
-	depends on SBUS && PARPORT && EXPERIMENTAL
+	depends on SBUS && EXPERIMENTAL
 	select PARPORT_NOT_PC
 	help
 	  This driver provides support for the bidirectional parallel port
@@ -136,7 +135,6 @@
 
 config PARPORT_AX88796
 	tristate "AX88796 Parallel Port"
-	depends on PARPORT
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port hardware on
@@ -148,7 +146,6 @@
 
 config PARPORT_1284
 	bool "IEEE 1284 transfer modes"
-	depends on PARPORT
 	help
 	  If you have a printer that supports status readback or device ID, or
 	  want to use a device that uses enhanced parallel port transfer modes
@@ -159,5 +156,4 @@
 config PARPORT_NOT_PC
 	bool
 
-endmenu
-
+endif # PARPORT
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 17bf993..43652ba 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -350,7 +350,7 @@
 
 #define PARPORT_GSC_OFFSET 0x800
 
-static int __initdata parport_count;
+static int __devinitdata parport_count;
 
 static int __devinit parport_init_chip(struct parisc_device *dev)
 {
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 7bfbad5..5d58ad5 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2424,7 +2424,6 @@
 	u32 ite8872set;
 	u32 ite8872_lpt, ite8872_lpthi;
 	u8 ite8872_irq, type;
-	char *fake_name = "parport probe";
 	int irq;
 	int i;
 
@@ -2432,11 +2431,11 @@
 	
 	// make sure which one chip
 	for(i = 0; i < 5; i++) {
-		base_res = request_region(inta_addr[i], 0x8, fake_name);
+		base_res = request_region(inta_addr[i], 32, "it887x");
 		if (base_res) {
 			int test;
 			pci_write_config_dword (pdev, 0x60,
-						0xe7000000 | inta_addr[i]);
+						0xe5000000 | inta_addr[i]);
 			pci_write_config_dword (pdev, 0x78,
 						0x00000000 | inta_addr[i]);
 			test = inb (inta_addr[i]);
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e3beb78..006054a 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -41,9 +41,7 @@
 # Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
 
-ifndef CONFIG_X86
-obj-y += syscall.o
-endif
+obj-$(CONFIG_PCI_SYSCALL) += syscall.o
 
 ifeq ($(CONFIG_PCI_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index ddbadd95..f6cc0c5 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -211,6 +211,7 @@
 
 extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
 extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
+extern int acpiphp_eject_slot (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index fa5c019..a0ca63a 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -156,11 +156,15 @@
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
 	struct slot *slot = hotplug_slot->private;
+	int retval;
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
 	/* disable the specified slot */
-	return acpiphp_disable_slot(slot->acpi_slot);
+	retval = acpiphp_disable_slot(slot->acpi_slot);
+	if (!retval)
+		retval = acpiphp_eject_slot(slot->acpi_slot);
+	return retval;
 }
 
 
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 9ef4e98..1e125b5 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1282,7 +1282,7 @@
 /**
  * acpiphp_eject_slot - physically eject the slot
  */
-static int acpiphp_eject_slot(struct acpiphp_slot *slot)
+int acpiphp_eject_slot(struct acpiphp_slot *slot)
 {
 	acpi_status status;
 	struct acpiphp_func *func;
@@ -1368,6 +1368,9 @@
 			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
 		return;
 
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+		return;
+
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
 			bridge->hpp.t0->cache_line_size);
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER,
@@ -1502,6 +1505,37 @@
  * ACPI event handlers
  */
 
+static acpi_status
+count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	int *count = (int *)context;
+	struct acpiphp_bridge *bridge;
+
+	bridge = acpiphp_handle_to_bridge(handle);
+	if (bridge)
+		(*count)++;
+	return AE_OK ;
+}
+
+static acpi_status
+check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	struct acpiphp_bridge *bridge;
+	char objname[64];
+	struct acpi_buffer buffer = { .length = sizeof(objname),
+				      .pointer = objname };
+
+	bridge = acpiphp_handle_to_bridge(handle);
+	if (bridge) {
+		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+		dbg("%s: re-enumerating slots under %s\n",
+			__FUNCTION__, objname);
+		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+		acpiphp_check_bridge(bridge);
+	}
+	return AE_OK ;
+}
+
 /**
  * handle_hotplug_event_bridge - handle ACPI event on bridges
  *
@@ -1519,6 +1553,7 @@
 	struct acpi_buffer buffer = { .length = sizeof(objname),
 				      .pointer = objname };
 	struct acpi_device *device;
+	int num_sub_bridges = 0;
 
 	if (acpi_bus_get_device(handle, &device)) {
 		/* This bridge must have just been physically inserted */
@@ -1527,7 +1562,12 @@
 	}
 
 	bridge = acpiphp_handle_to_bridge(handle);
-	if (!bridge) {
+	if (type == ACPI_NOTIFY_BUS_CHECK) {
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
+			count_sub_bridges, &num_sub_bridges, NULL);
+	}
+
+	if (!bridge && !num_sub_bridges) {
 		err("cannot get bridge info\n");
 		return;
 	}
@@ -1538,7 +1578,14 @@
 	case ACPI_NOTIFY_BUS_CHECK:
 		/* bus re-enumerate */
 		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
-		acpiphp_check_bridge(bridge);
+		if (bridge) {
+			dbg("%s: re-enumerating slots under %s\n",
+				__FUNCTION__, objname);
+			acpiphp_check_bridge(bridge);
+		}
+		if (num_sub_bridges)
+			acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+				ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index e7322c2..70db38c 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -106,7 +106,8 @@
 static void ibm_handle_events(acpi_handle handle, u32 event, void *context);
 static int ibm_get_table_from_acpi(char **bufp);
 static ssize_t ibm_read_apci_table(struct kobject *kobj,
-		char *buffer, loff_t pos, size_t size);
+				   struct bin_attribute *bin_attr,
+				   char *buffer, loff_t pos, size_t size);
 static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
 		u32 lvl, void *context, void **rv);
 static int __init ibm_acpiphp_init(void);
@@ -117,7 +118,6 @@
 static struct bin_attribute ibm_apci_table_attr = {
 	    .attr = {
 		    .name = "apci_table",
-		    .owner = THIS_MODULE,
 		    .mode = S_IRUGO,
 	    },
 	    .read = ibm_read_apci_table,
@@ -358,7 +358,8 @@
  * our solution is to only allow reading the table in all at once
  **/
 static ssize_t ibm_read_apci_table(struct kobject *kobj,
-		char *buffer, loff_t pos, size_t size)
+				   struct bin_attribute *bin_attr,
+				   char *buffer, loff_t pos, size_t size)
 {
 	int bytes_read = -EINVAL;
 	char *table = NULL;
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index 6845515..ed4d44e 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -35,6 +35,7 @@
 #include <linux/smp_lock.h>
 #include <asm/atomic.h>
 #include <linux/delay.h>
+#include <linux/kthread.h>
 #include "cpci_hotplug.h"
 
 #define DRIVER_AUTHOR	"Scott Murray <scottm@somanetworks.com>"
@@ -59,9 +60,8 @@
 static atomic_t extracting;
 int cpci_debug;
 static struct cpci_hp_controller *controller;
-static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
-static struct semaphore thread_exit;		/* guard ensure thread has exited before calling it quits */
-static int thread_finished = 1;
+static struct task_struct *cpci_thread;
+static int thread_finished;
 
 static int enable_slot(struct hotplug_slot *slot);
 static int disable_slot(struct hotplug_slot *slot);
@@ -357,9 +357,7 @@
 	controller->ops->disable_irq();
 
 	/* Trigger processing by the event thread */
-	dbg("Signal event_semaphore");
-	up(&event_semaphore);
-	dbg("exited cpci_hp_intr");
+	wake_up_process(cpci_thread);
 	return IRQ_HANDLED;
 }
 
@@ -521,17 +519,12 @@
 {
 	int rc;
 
-	lock_kernel();
-	daemonize("cpci_hp_eventd");
-	unlock_kernel();
-
 	dbg("%s - event thread started", __FUNCTION__);
 	while (1) {
 		dbg("event thread sleeping");
-		down_interruptible(&event_semaphore);
-		dbg("event thread woken, thread_finished = %d",
-		    thread_finished);
-		if (thread_finished || signal_pending(current))
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (kthread_should_stop())
 			break;
 		do {
 			rc = check_slots();
@@ -541,18 +534,17 @@
 			} else if (rc < 0) {
 				dbg("%s - error checking slots", __FUNCTION__);
 				thread_finished = 1;
-				break;
+				goto out;
 			}
-		} while (atomic_read(&extracting) && !thread_finished);
-		if (thread_finished)
+		} while (atomic_read(&extracting) && !kthread_should_stop());
+		if (kthread_should_stop())
 			break;
 
 		/* Re-enable ENUM# interrupt */
 		dbg("%s - re-enabling irq", __FUNCTION__);
 		controller->ops->enable_irq();
 	}
-	dbg("%s - event thread signals exit", __FUNCTION__);
-	up(&thread_exit);
+ out:
 	return 0;
 }
 
@@ -562,12 +554,8 @@
 {
 	int rc;
 
-	lock_kernel();
-	daemonize("cpci_hp_polld");
-	unlock_kernel();
-
 	while (1) {
-		if (thread_finished || signal_pending(current))
+		if (kthread_should_stop() || signal_pending(current))
 			break;
 		if (controller->ops->query_enum()) {
 			do {
@@ -578,48 +566,36 @@
 				} else if (rc < 0) {
 					dbg("%s - error checking slots", __FUNCTION__);
 					thread_finished = 1;
-					break;
+					goto out;
 				}
-			} while (atomic_read(&extracting) && !thread_finished);
+			} while (atomic_read(&extracting) && !kthread_should_stop());
 		}
 		msleep(100);
 	}
-	dbg("poll thread signals exit");
-	up(&thread_exit);
+ out:
 	return 0;
 }
 
 static int
 cpci_start_thread(void)
 {
-	int pid;
-
-	/* initialize our semaphores */
-	init_MUTEX_LOCKED(&event_semaphore);
-	init_MUTEX_LOCKED(&thread_exit);
-	thread_finished = 0;
-
 	if (controller->irq)
-		pid = kernel_thread(event_thread, NULL, 0);
+		cpci_thread = kthread_run(event_thread, NULL, "cpci_hp_eventd");
 	else
-		pid = kernel_thread(poll_thread, NULL, 0);
-	if (pid < 0) {
+		cpci_thread = kthread_run(poll_thread, NULL, "cpci_hp_polld");
+	if (IS_ERR(cpci_thread)) {
 		err("Can't start up our thread");
-		return -1;
+		return PTR_ERR(cpci_thread);
 	}
-	dbg("Our thread pid = %d", pid);
+	thread_finished = 0;
 	return 0;
 }
 
 static void
 cpci_stop_thread(void)
 {
+	kthread_stop(cpci_thread);
 	thread_finished = 1;
-	dbg("thread finish command given");
-	if (controller->irq)
-		up(&event_semaphore);
-	dbg("wait for thread to exit");
-	down(&thread_exit);
 }
 
 int
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 7b1beaa..5e9be44 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -45,8 +45,6 @@
 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
 
-#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
-
 
 u8 cpci_get_attention_status(struct slot* slot)
 {
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 5617cfd..d590a99 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -796,7 +796,6 @@
 	u8 num_of_slots = 0;
 	u8 hp_slot = 0;
 	u8 device;
-	u8 rev;
 	u8 bus_cap;
 	u16 temp_word;
 	u16 vendor_id;
@@ -823,9 +822,8 @@
 	}
 	dbg("Vendor ID: %x\n", vendor_id);
 
-	rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-	dbg("revision: %d\n", rev);
-	if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
+	dbg("revision: %d\n", pdev->revision);
+	if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) {
 		err(msg_HPC_rev_error);
 		rc = -ENODEV;
 		goto err_disable_device;
@@ -836,7 +834,7 @@
 	 * For Intel, each SSID bit identifies a PHP capability.
 	 * Also Intel HPC's may have RID=0.
 	 */
-	if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
+	if ((pdev->revision > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
 		// TODO: This code can be made to support non-Compaq or Intel subsystem IDs
 		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
 		if (rc) {
@@ -870,7 +868,7 @@
 
 		switch (subsystem_vid) {
 			case PCI_VENDOR_ID_COMPAQ:
-				if (rev >= 0x13) { /* CIOBX */
+				if (pdev->revision >= 0x13) { /* CIOBX */
 					ctrl->push_flag = 1;
 					ctrl->slot_switch_type = 1;
 					ctrl->push_button = 1;
@@ -1075,7 +1073,7 @@
 	memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus));
 
 	ctrl->bus = pdev->bus->number;
-	ctrl->rev = rev;
+	ctrl->rev = pdev->revision;
 	dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
 		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
 
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
index 46abaa8..d06ccb6 100644
--- a/drivers/pci/hotplug/ibmphp_hpc.c
+++ b/drivers/pci/hotplug/ibmphp_hpc.c
@@ -34,6 +34,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
 
 #include "ibmphp.h"
 
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index ccc5762..7959c22 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -103,6 +103,7 @@
 	u8 cap_base;
 	struct timer_list poll_timer;
 	volatile int cmd_busy;
+	spinlock_t lock;
 };
 
 #define INT_BUTTON_IGNORE		0
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 7f22caa..98e541ffe 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -197,6 +197,12 @@
 			    __FUNCTION__);
 			return;
 		}
+		/*
+		 * After turning power off, we must wait for at least
+		 * 1 second before taking any action that relies on
+		 * power having been removed from the slot/adapter.
+		 */
+		msleep(1000);
 	}
 }
 
@@ -615,6 +621,12 @@
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -EINVAL;
 		}
+		/*
+		 * After turning power off, we must wait for at least
+		 * 1 second before taking any action that relies on
+		 * power having been removed from the slot/adapter.
+		 */
+		msleep(1000);
 	}
 
 	ret = remove_board(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 9aac6a8..016eea9 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -275,11 +275,19 @@
 	return retval;
 }
 
-static int pcie_write_cmd(struct slot *slot, u16 cmd)
+/**
+ * pcie_write_cmd - Issue controller command
+ * @slot: slot to which the command is issued
+ * @cmd:  command value written to slot control register
+ * @mask: bitmask of slot control register to be modified
+ */
+static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
 {
 	struct controller *ctrl = slot->ctrl;
 	int retval = 0;
 	u16 slot_status;
+	u16 slot_ctrl;
+	unsigned long flags;
 
 	DBG_ENTER_ROUTINE 
 
@@ -299,17 +307,29 @@
 		    __FUNCTION__);
 	}
 
-	ctrl->cmd_busy = 1;
-	retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE));
+	spin_lock_irqsave(&ctrl->lock, flags);
+	retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
 	if (retval) {
-		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-		goto out;
+		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+		goto out_spin_unlock;
 	}
 
+	slot_ctrl &= ~mask;
+	slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE);
+
+	ctrl->cmd_busy = 1;
+	retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
+	if (retval)
+		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+
+ out_spin_unlock:
+	spin_unlock_irqrestore(&ctrl->lock, flags);
+
 	/*
 	 * Wait for command completion.
 	 */
-	retval = pcie_wait_cmd(ctrl);
+	if (!retval)
+		retval = pcie_wait_cmd(ctrl);
  out:
 	mutex_unlock(&ctrl->ctrl_lock);
 	DBG_LEAVE_ROUTINE 
@@ -502,25 +522,20 @@
 
 static int hpc_toggle_emi(struct slot *slot)
 {
-	struct controller *ctrl = slot->ctrl;
-	u16 slot_cmd = 0;
-	u16 slot_ctrl;
-	int rc = 0;
+	u16 slot_cmd;
+	u16 cmd_mask;
+	int rc;
 
 	DBG_ENTER_ROUTINE
 
-	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-	if (rc) {
-		err("%s : hp_register_read_word SLOT_CTRL failed\n",
-			__FUNCTION__);
-		return rc;
+	slot_cmd = EMI_CTRL;
+	cmd_mask = EMI_CTRL;
+	if (!pciehp_poll_mode) {
+		slot_cmd = slot_cmd | HP_INTR_ENABLE;
+		cmd_mask = cmd_mask | HP_INTR_ENABLE;
 	}
 
-	slot_cmd = (slot_ctrl | EMI_CTRL);
-	if (!pciehp_poll_mode)
-		slot_cmd = slot_cmd | HP_INTR_ENABLE;
-
-	pcie_write_cmd(slot, slot_cmd);
+	rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
 	slot->last_emi_toggle = get_seconds();
 	DBG_LEAVE_ROUTINE
 	return rc;
@@ -529,35 +544,32 @@
 static int hpc_set_attention_status(struct slot *slot, u8 value)
 {
 	struct controller *ctrl = slot->ctrl;
-	u16 slot_cmd = 0;
-	u16 slot_ctrl;
-	int rc = 0;
+	u16 slot_cmd;
+	u16 cmd_mask;
+	int rc;
 
 	DBG_ENTER_ROUTINE
 
-	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		return rc;
-	}
-
+	cmd_mask = ATTN_LED_CTRL;
 	switch (value) {
 		case 0 :	/* turn off */
-			slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0;
+			slot_cmd = 0x00C0;
 			break;
 		case 1:		/* turn on */
-			slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040;
+			slot_cmd = 0x0040;
 			break;
 		case 2:		/* turn blink */
-			slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080;
+			slot_cmd = 0x0080;
 			break;
 		default:
 			return -1;
 	}
-	if (!pciehp_poll_mode)
-		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
+	if (!pciehp_poll_mode) {
+		slot_cmd = slot_cmd | HP_INTR_ENABLE;
+		cmd_mask = cmd_mask | HP_INTR_ENABLE;
+	}
 
-	pcie_write_cmd(slot, slot_cmd);
+	rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 	
@@ -570,21 +582,18 @@
 {
 	struct controller *ctrl = slot->ctrl;
 	u16 slot_cmd;
-	u16 slot_ctrl;
-	int rc = 0;
+	u16 cmd_mask;
        	
 	DBG_ENTER_ROUTINE
 
-	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		return;
+	slot_cmd = 0x0100;
+	cmd_mask = PWR_LED_CTRL;
+	if (!pciehp_poll_mode) {
+		slot_cmd = slot_cmd | HP_INTR_ENABLE;
+		cmd_mask = cmd_mask | HP_INTR_ENABLE;
 	}
-	slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
-	if (!pciehp_poll_mode)
-		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
 
-	pcie_write_cmd(slot, slot_cmd);
+	pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -596,22 +605,18 @@
 {
 	struct controller *ctrl = slot->ctrl;
 	u16 slot_cmd;
-	u16 slot_ctrl;
-	int rc = 0;
+	u16 cmd_mask;
 
 	DBG_ENTER_ROUTINE
 
-	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		return;
+	slot_cmd = 0x0300;
+	cmd_mask = PWR_LED_CTRL;
+	if (!pciehp_poll_mode) {
+		slot_cmd = slot_cmd | HP_INTR_ENABLE;
+		cmd_mask = cmd_mask | HP_INTR_ENABLE;
 	}
 
-	slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
-
-	if (!pciehp_poll_mode)
-		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
-	pcie_write_cmd(slot, slot_cmd);
+	pcie_write_cmd(slot, slot_cmd, cmd_mask);
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
@@ -623,22 +628,18 @@
 {
 	struct controller *ctrl = slot->ctrl;
 	u16 slot_cmd;
-	u16 slot_ctrl;
-	int rc = 0; 
+	u16 cmd_mask;
 	
 	DBG_ENTER_ROUTINE
 
-	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		return;
+	slot_cmd = 0x0200;
+	cmd_mask = PWR_LED_CTRL;
+	if (!pciehp_poll_mode) {
+		slot_cmd = slot_cmd | HP_INTR_ENABLE;
+		cmd_mask = cmd_mask | HP_INTR_ENABLE;
 	}
 
-	slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
-
-	if (!pciehp_poll_mode)
-		slot_cmd = slot_cmd | HP_INTR_ENABLE; 
-	pcie_write_cmd(slot, slot_cmd);
+	pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -669,7 +670,8 @@
 {
 	struct controller *ctrl = slot->ctrl;
 	u16 slot_cmd;
-	u16 slot_ctrl, slot_status;
+	u16 cmd_mask;
+	u16 slot_status;
 	int retval = 0;
 
 	DBG_ENTER_ROUTINE 
@@ -692,23 +694,23 @@
 		}
 	}
 
-	retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-	if (retval) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		return retval;
-	}
-
-	slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
-
+	slot_cmd = POWER_ON;
+	cmd_mask = PWR_CTRL;
 	/* Enable detection that we turned off at slot power-off time */
-	if (!pciehp_poll_mode)
+	if (!pciehp_poll_mode) {
 		slot_cmd = slot_cmd |
 		           PWR_FAULT_DETECT_ENABLE |
 		           MRL_DETECT_ENABLE |
 		           PRSN_DETECT_ENABLE |
 		           HP_INTR_ENABLE;
+		cmd_mask = cmd_mask |
+		           PWR_FAULT_DETECT_ENABLE |
+		           MRL_DETECT_ENABLE |
+		           PRSN_DETECT_ENABLE |
+		           HP_INTR_ENABLE;
+	}
 
-	retval = pcie_write_cmd(slot, slot_cmd);
+	retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
 
 	if (retval) {
 		err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
@@ -726,21 +728,15 @@
 {
 	struct controller *ctrl = slot->ctrl;
 	u16 slot_cmd;
-	u16 slot_ctrl;
+	u16 cmd_mask;
 	int retval = 0;
 
 	DBG_ENTER_ROUTINE 
 
 	dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
 
-	retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-	if (retval) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		return retval;
-	}
-
-	slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
-
+	slot_cmd = POWER_OFF;
+	cmd_mask = PWR_CTRL;
 	/*
 	 * If we get MRL or presence detect interrupts now, the isr
 	 * will notice the sticky power-fault bit too and issue power
@@ -748,14 +744,19 @@
 	 * of command completions, since the power-fault bit remains on
 	 * till the slot is powered on again.
 	 */
-	if (!pciehp_poll_mode)
+	if (!pciehp_poll_mode) {
 		slot_cmd = (slot_cmd &
 		            ~PWR_FAULT_DETECT_ENABLE &
 		            ~MRL_DETECT_ENABLE &
 		            ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
+		cmd_mask = cmd_mask |
+			   PWR_FAULT_DETECT_ENABLE |
+			   MRL_DETECT_ENABLE |
+			   PRSN_DETECT_ENABLE |
+			   HP_INTR_ENABLE;
+	}
 
-	retval = pcie_write_cmd(slot, slot_cmd);
-
+	retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
 	if (retval) {
 		err("%s: Write command failed!\n", __FUNCTION__);
 		return -1;
@@ -775,6 +776,7 @@
 	u16 temp_word;
 	int hp_slot = 0;	/* only 1 slot per PCI Express port */
 	int rc = 0;
+	unsigned long flags;
 
 	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
 	if (rc) {
@@ -794,10 +796,12 @@
 	dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
 	/* Mask Hot-plug Interrupt Enable */
 	if (!pciehp_poll_mode) {
+		spin_lock_irqsave(&ctrl->lock, flags);
 		rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
 		if (rc) {
 			err("%s: Cannot read SLOT_CTRL register\n",
 			    __FUNCTION__);
+			spin_unlock_irqrestore(&ctrl->lock, flags);
 			return IRQ_NONE;
 		}
 
@@ -808,8 +812,10 @@
 		if (rc) {
 			err("%s: Cannot write to SLOTCTRL register\n",
 			    __FUNCTION__);
+			spin_unlock_irqrestore(&ctrl->lock, flags);
 			return IRQ_NONE;
 		}
+		spin_unlock_irqrestore(&ctrl->lock, flags);
 
 		rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
 		if (rc) {
@@ -859,10 +865,12 @@
 	}
 	/* Unmask Hot-plug Interrupt Enable */
 	if (!pciehp_poll_mode) {
+		spin_lock_irqsave(&ctrl->lock, flags);
 		rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
 		if (rc) {
 			err("%s: Cannot read SLOTCTRL register\n",
 			    __FUNCTION__);
+			spin_unlock_irqrestore(&ctrl->lock, flags);
 			return IRQ_NONE;
 		}
 
@@ -873,8 +881,10 @@
 		if (rc) {
 			err("%s: Cannot write to SLOTCTRL register\n",
 			    __FUNCTION__);
+			spin_unlock_irqrestore(&ctrl->lock, flags);
 			return IRQ_NONE;
 		}
+		spin_unlock_irqrestore(&ctrl->lock, flags);
 
 		rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
 		if (rc) {
@@ -1237,6 +1247,7 @@
 
 	mutex_init(&ctrl->crit_sect);
 	mutex_init(&ctrl->ctrl_lock);
+	spin_lock_init(&ctrl->lock);
 
 	/* setup wait queue */
 	init_waitqueue_head(&ctrl->queue);
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index bb3c101..deb6b5e 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -159,8 +159,8 @@
 	/* Claim new bus resources */
 	pcibios_claim_one_bus(dev->bus);
 
-	/* ioremap() for child bus, which may or may not succeed */
-	remap_bus_range(dev->subordinate);
+	/* Map IO space for child bus, which may or may not succeed */
+	pcibios_map_io_space(dev->subordinate);
 
 	/* Add new devices to global lists.  Register in proc, sysfs. */
 	pci_bus_add_devices(phb->bus);
@@ -390,7 +390,7 @@
 	} else
 		pcibios_remove_pci_devices(bus);
 
-	if (unmap_bus_range(bus)) {
+	if (pcibios_unmap_io_space(bus)) {
 		printk(KERN_ERR "%s: failed to unmap bus range\n",
 			__FUNCTION__);
 		return -ERANGE;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d9cbd58..be1df85 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -15,10 +15,10 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/msi.h>
+#include <linux/smp.h>
 
 #include <asm/errno.h>
 #include <asm/io.h>
-#include <asm/smp.h>
 
 #include "pci.h"
 #include "msi.h"
@@ -333,7 +333,7 @@
 			msi_mask_bits_reg(pos, is_64bit_address(control)),
 			maskbits);
 	}
-	list_add(&entry->list, &dev->msi_list);
+	list_add_tail(&entry->list, &dev->msi_list);
 
 	/* Configure MSI capability structure */
 	ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI);
@@ -404,7 +404,7 @@
 		entry->dev = dev;
 		entry->mask_base = base;
 
-		list_add(&entry->list, &dev->msi_list);
+		list_add_tail(&entry->list, &dev->msi_list);
 	}
 
 	ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
@@ -558,12 +558,12 @@
 
 	list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
 		if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) {
-			if (list_is_last(&entry->list, &dev->msi_list))
-				iounmap(entry->mask_base);
-
 			writel(1, entry->mask_base + entry->msi_attrib.entry_nr
 				  * PCI_MSIX_ENTRY_SIZE
 				  + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+
+			if (list_is_last(&entry->list, &dev->msi_list))
+				iounmap(entry->mask_base);
 		}
 		list_del(&entry->list);
 		kfree(entry);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index b5ac810..c806249 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -55,8 +55,6 @@
 
 	status = acpi_evaluate_object(handle, "_OSC", &input, &output);
 	if (ACPI_FAILURE (status)) {
-		printk(KERN_DEBUG  
-			"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
 		*ret_status = status;
 		return status;
 	}
@@ -124,11 +122,9 @@
 	in_params[3].buffer.pointer 	= (u8 *)context;
 
 	status = acpi_evaluate_object(handle, "_OSC", &input, &output);
-	if (ACPI_FAILURE (status)) {
-		printk(KERN_DEBUG  
-			"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
+	if (ACPI_FAILURE (status))
 		return status;
-	}
+
 	out_obj = output.pointer;
 	if (out_obj->type != ACPI_TYPE_BUFFER) {
 		printk(KERN_DEBUG  
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 284e83a..1b7b281 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -20,7 +20,7 @@
 #include <linux/stat.h>
 #include <linux/topology.h>
 #include <linux/mm.h>
-
+#include <linux/capability.h>
 #include "pci.h"
 
 static int sysfs_initialized;	/* = 0 */
@@ -213,7 +213,8 @@
 };
 
 static ssize_t
-pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+		char *buf, loff_t off, size_t count)
 {
 	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 	unsigned int size = 64;
@@ -285,7 +286,8 @@
 }
 
 static ssize_t
-pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+		 char *buf, loff_t off, size_t count)
 {
 	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 	unsigned int size = count;
@@ -352,7 +354,8 @@
  * callback routine (pci_legacy_read).
  */
 ssize_t
-pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+		   char *buf, loff_t off, size_t count)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
                                                       struct class_device,
@@ -376,7 +379,8 @@
  * callback routine (pci_legacy_write).
  */
 ssize_t
-pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+		    char *buf, loff_t off, size_t count)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
 						      struct class_device,
@@ -499,7 +503,6 @@
 			sprintf(res_attr_name, "resource%d", i);
 			res_attr->attr.name = res_attr_name;
 			res_attr->attr.mode = S_IRUSR | S_IWUSR;
-			res_attr->attr.owner = THIS_MODULE;
 			res_attr->size = pci_resource_len(pdev, i);
 			res_attr->mmap = pci_mmap_resource;
 			res_attr->private = &pdev->resource[i];
@@ -529,7 +532,8 @@
  * writing anything except 0 enables it
  */
 static ssize_t
-pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
+	      char *buf, loff_t off, size_t count)
 {
 	struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
 
@@ -552,7 +556,8 @@
  * device corresponding to @kobj.
  */
 static ssize_t
-pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
+	     char *buf, loff_t off, size_t count)
 {
 	struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
 	void __iomem *rom;
@@ -582,7 +587,6 @@
 	.attr =	{
 		.name = "config",
 		.mode = S_IRUGO | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 256,
 	.read = pci_read_config,
@@ -593,13 +597,17 @@
 	.attr =	{
 		.name = "config",
 		.mode = S_IRUGO | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 4096,
 	.read = pci_read_config,
 	.write = pci_write_config,
 };
 
+int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
+{
+	return 0;
+}
+
 int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
 	struct bin_attribute *rom_attr = NULL;
@@ -628,7 +636,6 @@
 			rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
 			rom_attr->attr.name = "rom";
 			rom_attr->attr.mode = S_IRUSR;
-			rom_attr->attr.owner = THIS_MODULE;
 			rom_attr->read = pci_read_rom;
 			rom_attr->write = pci_write_rom;
 			retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
@@ -640,10 +647,14 @@
 		}
 	}
 	/* add platform-specific attributes */
-	pcibios_add_platform_entries(pdev);
+	if (pcibios_add_platform_entries(pdev))
+		goto err_rom_file;
 
 	return 0;
 
+err_rom_file:
+	if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+		sysfs_remove_bin_file(&pdev->dev.kobj, rom_attr);
 err_rom:
 	kfree(rom_attr);
 err_resource_files:
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index fd47ac0..03fd59e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -406,6 +406,13 @@
 	if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
 		return 0;
 
+	/* find PCI PM capability in list */
+	pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+
+	/* abort if the device doesn't support PM capabilities */
+	if (!pm)
+		return -EIO;
+
 	/* Validate current state:
 	 * Can enter D0 from any state, but if we can only go deeper 
 	 * to sleep if we're already in a low power state
@@ -418,13 +425,6 @@
 		return 0;        /* we're already there */
 
 
-	/* find PCI PM capability in list */
-	pm = pci_find_capability(dev, PCI_CAP_ID_PM);
-	
-	/* abort if the device doesn't support PM capabilities */
-	if (!pm)
-		return -EIO; 
-
 	pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
 	if ((pmc & PCI_PM_CAP_VER_MASK) > 3) {
 		printk(KERN_DEBUG
@@ -1186,6 +1186,11 @@
 	return 0;
 }
 
+int pci_try_set_mwi(struct pci_dev *dev)
+{
+	return 0;
+}
+
 void pci_clear_mwi(struct pci_dev *dev)
 {
 }
@@ -1242,9 +1247,7 @@
  * pci_set_mwi - enables memory-write-invalidate PCI transaction
  * @dev: the PCI device for which MWI is enabled
  *
- * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND,
- * and then calls @pcibios_set_mwi to do the needed arch specific
- * operations or a generic mwi-prep function.
+ * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND.
  *
  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
  */
@@ -1260,7 +1263,8 @@
 
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	if (! (cmd & PCI_COMMAND_INVALIDATE)) {
-		pr_debug("PCI: Enabling Mem-Wr-Inval for device %s\n", pci_name(dev));
+		pr_debug("PCI: Enabling Mem-Wr-Inval for device %s\n",
+			pci_name(dev));
 		cmd |= PCI_COMMAND_INVALIDATE;
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 	}
@@ -1269,6 +1273,21 @@
 }
 
 /**
+ * pci_try_set_mwi - enables memory-write-invalidate PCI transaction
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND.
+ * Callers are not required to check the return value.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+int pci_try_set_mwi(struct pci_dev *dev)
+{
+	int rc = pci_set_mwi(dev);
+	return rc;
+}
+
+/**
  * pci_clear_mwi - disables Memory-Write-Invalidate for device dev
  * @dev: the PCI device to disable
  *
@@ -1375,6 +1394,164 @@
 #endif
 
 /**
+ * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
+ * @dev: PCI device to query
+ *
+ * Returns mmrbc: maximum designed memory read count in bytes
+ *    or appropriate error value.
+ */
+int pcix_get_max_mmrbc(struct pci_dev *dev)
+{
+	int err, cap;
+	u32 stat;
+
+	cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+	if (!cap)
+		return -EINVAL;
+
+	err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
+	if (err)
+		return -EINVAL;
+
+	return (stat & PCI_X_STATUS_MAX_READ) >> 12;
+}
+EXPORT_SYMBOL(pcix_get_max_mmrbc);
+
+/**
+ * pcix_get_mmrbc - get PCI-X maximum memory read byte count
+ * @dev: PCI device to query
+ *
+ * Returns mmrbc: maximum memory read count in bytes
+ *    or appropriate error value.
+ */
+int pcix_get_mmrbc(struct pci_dev *dev)
+{
+	int ret, cap;
+	u32 cmd;
+
+	cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+	if (!cap)
+		return -EINVAL;
+
+	ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
+	if (!ret)
+		ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2);
+
+	return ret;
+}
+EXPORT_SYMBOL(pcix_get_mmrbc);
+
+/**
+ * pcix_set_mmrbc - set PCI-X maximum memory read byte count
+ * @dev: PCI device to query
+ * @mmrbc: maximum memory read count in bytes
+ *    valid values are 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum memory read byte count, some bridges have erratas
+ * that prevent this.
+ */
+int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
+{
+	int cap, err = -EINVAL;
+	u32 stat, cmd, v, o;
+
+	if (mmrbc < 512 || mmrbc > 4096 || (mmrbc & (mmrbc-1)))
+		goto out;
+
+	v = ffs(mmrbc) - 10;
+
+	cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+	if (!cap)
+		goto out;
+
+	err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
+	if (err)
+		goto out;
+
+	if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21)
+		return -E2BIG;
+
+	err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
+	if (err)
+		goto out;
+
+	o = (cmd & PCI_X_CMD_MAX_READ) >> 2;
+	if (o != v) {
+		if (v > o && dev->bus &&
+		   (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC))
+			return -EIO;
+
+		cmd &= ~PCI_X_CMD_MAX_READ;
+		cmd |= v << 2;
+		err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd);
+	}
+out:
+	return err;
+}
+EXPORT_SYMBOL(pcix_set_mmrbc);
+
+/**
+ * pcie_get_readrq - get PCI Express read request size
+ * @dev: PCI device to query
+ *
+ * Returns maximum memory read request in bytes
+ *    or appropriate error value.
+ */
+int pcie_get_readrq(struct pci_dev *dev)
+{
+	int ret, cap;
+	u16 ctl;
+
+	cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (!cap)
+		return -EINVAL;
+
+	ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+	if (!ret)
+	ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
+
+	return ret;
+}
+EXPORT_SYMBOL(pcie_get_readrq);
+
+/**
+ * pcie_set_readrq - set PCI Express maximum memory read request
+ * @dev: PCI device to query
+ * @count: maximum memory read count in bytes
+ *    valid values are 128, 256, 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum read byte count
+ */
+int pcie_set_readrq(struct pci_dev *dev, int rq)
+{
+	int cap, err = -EINVAL;
+	u16 ctl, v;
+
+	if (rq < 128 || rq > 4096 || (rq & (rq-1)))
+		goto out;
+
+	v = (ffs(rq) - 8) << 12;
+
+	cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (!cap)
+		goto out;
+
+	err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+	if (err)
+		goto out;
+
+	if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) {
+		ctl &= ~PCI_EXP_DEVCTL_READRQ;
+		ctl |= v;
+		err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl);
+	}
+
+out:
+	return err;
+}
+EXPORT_SYMBOL(pcie_set_readrq);
+
+/**
  * pci_select_bars - Make BAR mask from the type of resource
  * @dev: the PCI device for which BAR mask is made
  * @flags: resource type mask to be selected
@@ -1442,6 +1619,7 @@
 EXPORT_SYMBOL(pci_request_selected_regions);
 EXPORT_SYMBOL(pci_set_master);
 EXPORT_SYMBOL(pci_set_mwi);
+EXPORT_SYMBOL(pci_try_set_mwi);
 EXPORT_SYMBOL(pci_clear_mwi);
 EXPORT_SYMBOL_GPL(pci_intx);
 EXPORT_SYMBOL(pci_set_dma_mask);
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
index 3f37a60..c3bde58 100644
--- a/drivers/pci/pcie/aer/Kconfig
+++ b/drivers/pci/pcie/aer/Kconfig
@@ -4,7 +4,7 @@
 
 config PCIEAER
 	boolean "Root Port Advanced Error Reporting support"
-	depends on PCIEPORTBUS && ACPI
+	depends on PCIEPORTBUS
 	default y
 	help
 	  This enables PCI Express Root Port Advanced Error Reporting
diff --git a/drivers/pci/pcie/aer/Makefile b/drivers/pci/pcie/aer/Makefile
index 15a4f40..8da3bd8 100644
--- a/drivers/pci/pcie/aer/Makefile
+++ b/drivers/pci/pcie/aer/Makefile
@@ -4,5 +4,6 @@
 
 obj-$(CONFIG_PCIEAER) += aerdriver.o
 
-aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o aerdrv_acpi.o
+aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o
+aerdriver-$(CONFIG_ACPI) += aerdrv_acpi.o
 
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index db6ad8e..6846fb4 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -157,7 +157,7 @@
 	 * Initialize Root lock access, e_lock, to Root Error Status Reg,
 	 * Root Error ID Reg, and Root error producer/consumer index.
 	 */
-	rpc->e_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&rpc->e_lock);
 
 	rpc->rpd = dev;
 	INIT_WORK(&rpc->dpc_handler, aer_isr);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index bf655db..c7ad68b 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -8,6 +8,7 @@
 #ifndef _AERDRV_H_
 #define _AERDRV_H_
 
+#include <linux/workqueue.h>
 #include <linux/pcieport_if.h>
 #include <linux/aer.h>
 
@@ -18,10 +19,6 @@
 #define AER_ERROR_MASK			0x001fffff
 #define AER_ERROR(d)			(d & AER_ERROR_MASK)
 
-#define OSC_METHOD_RUN_SUCCESS		0
-#define OSC_METHOD_NOT_SUPPORTED	1
-#define OSC_METHOD_RUN_FAILURE		2
-
 /* Root Error Status Register Bits */
 #define ROOT_ERR_STATUS_MASKS			0x0f
 
@@ -120,6 +117,14 @@
 extern int aer_init(struct pcie_device *dev);
 extern void aer_isr(struct work_struct *work);
 extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
-extern int aer_osc_setup(struct pci_dev *dev);
+
+#ifdef CONFIG_ACPI
+extern int aer_osc_setup(struct pcie_device *pciedev);
+#else
+static inline int aer_osc_setup(struct pcie_device *pciedev)
+{
+	return 0;
+}
+#endif
 
 #endif //_AERDRV_H_
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index fa68e89..1a1eb45 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -20,19 +20,18 @@
 
 /**
  * aer_osc_setup - run ACPI _OSC method
+ * @pciedev: pcie_device which AER is being enabled on
  *
- * Return:
- *	Zero if success. Nonzero for otherwise.
+ * @return: Zero on success. Nonzero otherwise.
  *
  * Invoked when PCIE bus loads AER service driver. To avoid conflict with
  * BIOS AER support requires BIOS to yield AER control to OS native driver.
  **/
-int aer_osc_setup(struct pci_dev *dev)
+int aer_osc_setup(struct pcie_device *pciedev)
 {
-	int retval = OSC_METHOD_RUN_SUCCESS;
-	acpi_status status;
-	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
-	struct pci_dev *pdev = dev;
+	acpi_status status = AE_NOT_FOUND;
+	struct pci_dev *pdev = pciedev->port;
+	acpi_handle handle = DEVICE_ACPI_HANDLE(&pdev->dev);
 	struct pci_bus *parent;
 
 	while (!handle) {
@@ -50,19 +49,20 @@
 		pdev = parent->self;
 	}
 
-	if (!handle)
-		return OSC_METHOD_NOT_SUPPORTED;
-
-	pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
-	status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_AER_CONTROL |
-		OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-	if (ACPI_FAILURE(status)) {
-		if (status == AE_SUPPORT)
-			retval = OSC_METHOD_NOT_SUPPORTED;
-	 	else
-			retval = OSC_METHOD_RUN_FAILURE;
+	if (handle) {
+		pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+		status = pci_osc_control_set(handle,
+					OSC_PCI_EXPRESS_AER_CONTROL |
+					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
 	}
 
-	return retval;
-}
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_DEBUG "AER service couldn't init device %s - %s\n",
+		    pciedev->device.bus_id,
+		    (status == AE_SUPPORT || status == AE_NOT_FOUND) ?
+		    "no _OSC support" : "Run ACPI _OSC fails");
+		return -1;
+	}
 
+	return 0;
+}
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 08e1303..92a8469 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -22,8 +22,6 @@
 #include <linux/errno.h>
 #include <linux/pm.h>
 #include <linux/suspend.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
 #include <linux/delay.h>
 #include "aerdrv.h"
 
@@ -119,6 +117,21 @@
 	return 0;
 }
 
+int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+{
+	int pos;
+	u32 status;
+
+	pos = pci_find_aer_capability(dev);
+	if (!pos)
+		return -EIO;
+
+	pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
+	pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
+
+	return 0;
+}
+
 static int find_device_iter(struct device *device, void *data)
 {
 	struct pci_dev *dev;
@@ -733,20 +746,8 @@
  **/
 int aer_init(struct pcie_device *dev)
 {
-	int status;
-
-	/* Run _OSC Method */
-	status = aer_osc_setup(dev->port);
-
-	if(status != OSC_METHOD_RUN_SUCCESS) {
-		printk(KERN_DEBUG "%s: AER service init fails - %s\n",
-		__FUNCTION__,
-		(status == OSC_METHOD_NOT_SUPPORTED) ?
-			"No ACPI _OSC support" : "Run ACPI _OSC fails");
-
-		if (!forceload)
-			return status;
-	}
+	if (aer_osc_setup(dev) && !forceload)
+		return -ENXIO;
 
 	return AER_SUCCESS;
 }
@@ -755,4 +756,5 @@
 EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
 EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
 EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+EXPORT_SYMBOL_GPL(pci_cleanup_aer_correct_error_status);
 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e48fcf0..34b8dae0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -22,6 +22,18 @@
 
 LIST_HEAD(pci_devices);
 
+/*
+ * Some device drivers need know if pci is initiated.
+ * Basically, we think pci is not initiated when there
+ * is no device in list of pci_devices.
+ */
+int no_pci_devices(void)
+{
+	return list_empty(&pci_devices);
+}
+
+EXPORT_SYMBOL(no_pci_devices);
+
 #ifdef HAVE_PCI_LEGACY
 /**
  * pci_create_legacy_files - create legacy I/O port and memory files
@@ -39,7 +51,6 @@
 		b->legacy_io->attr.name = "legacy_io";
 		b->legacy_io->size = 0xffff;
 		b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
-		b->legacy_io->attr.owner = THIS_MODULE;
 		b->legacy_io->read = pci_read_legacy_io;
 		b->legacy_io->write = pci_write_legacy_io;
 		class_device_create_bin_file(&b->class_dev, b->legacy_io);
@@ -49,7 +60,6 @@
 		b->legacy_mem->attr.name = "legacy_mem";
 		b->legacy_mem->size = 1024*1024;
 		b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
-		b->legacy_mem->attr.owner = THIS_MODULE;
 		b->legacy_mem->mmap = pci_mmap_legacy_mem;
 		class_device_create_bin_file(&b->class_dev, b->legacy_mem);
 	}
@@ -656,7 +666,7 @@
 			       pcibios_assign_all_busses() ? " " :
 			       " (try 'pci=assign-busses')");
 			printk(KERN_WARNING "Please report the result to "
-			       "linux-kernel to fix this permanently\n");
+			       "<bk@suse.de> to fix this permanently\n");
 		}
 		bus = bus->parent;
 	}
@@ -702,6 +712,7 @@
 		dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
 
 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+	dev->revision = class & 0xff;
 	class >>= 8;				    /* upper 3 bytes */
 	dev->class = class;
 	class >>= 8;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 0425a7b..90adc62 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-
+#include <linux/capability.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include "pci.h"
@@ -480,7 +480,6 @@
 __initcall(pci_proc_init);
 
 #ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pci_proc_attach_device);
 EXPORT_SYMBOL(pci_proc_detach_bus);
 #endif
 
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 6ccc2e9..c559085 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -587,10 +587,7 @@
  */
 static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
 {
-	u8 rev;
-
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-	if (rev >= 0x02) {
+	if (dev->revision >= 0x02) {
 		printk(KERN_WARNING "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
 		printk(KERN_WARNING "        : booting with the \"noapic\" option.\n");
 	}
@@ -610,13 +607,12 @@
 #define AMD8131_NIOAMODE_BIT 0
 static void quirk_amd_8131_ioapic(struct pci_dev *dev)
 { 
-        unsigned char revid, tmp;
+        unsigned char tmp;
         
         if (nr_ioapics == 0) 
                 return;
 
-        pci_read_config_byte(dev, PCI_REVISION_ID, &revid);
-        if (revid == AMD8131_revA0 || revid == AMD8131_revB0) {
+        if (dev->revision == AMD8131_revA0 || dev->revision == AMD8131_revB0) {
                 printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n"); 
                 pci_read_config_byte( dev, AMD8131_MISC, &tmp);
                 tmp &= ~(1 << AMD8131_NIOAMODE_BIT);
@@ -627,6 +623,22 @@
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
 #endif /* CONFIG_X86_IO_APIC */
 
+/*
+ * Some settings of MMRBC can lead to data corruption so block changes.
+ * See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide
+ */
+static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
+{
+	unsigned char revid;
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &revid);
+	if (dev->subordinate && revid <= 0x12) {
+		printk(KERN_INFO "AMD8131 rev %x detected, disabling PCI-X "
+				"MMRBC\n", revid);
+		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC;
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_mmrbc);
 
 /*
  * FIXME: it is questionable that quirk_via_acpi
@@ -843,10 +855,8 @@
 static void quirk_disable_pxb(struct pci_dev *pdev)
 {
 	u16 config;
-	u8 rev;
 	
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-	if (rev != 0x04)		/* Only C0 requires this */
+	if (pdev->revision != 0x04)		/* Only C0 requires this */
 		return;
 	pci_read_config_word(pdev, 0x40, &config);
 	if (config & (1<<6)) {
@@ -1625,18 +1635,22 @@
 			quirk_nvidia_ck804_pcie_aer_ext_cap);
 
 #ifdef CONFIG_PCI_MSI
-/* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely
- * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
- * some other busses controlled by the chipset even if Linux is not aware of it.
- * Instead of setting the flag on all busses in the machine, simply disable MSI
- * globally.
+/* Some chipsets do not support MSI. We cannot easily rely on setting
+ * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
+ * some other busses controlled by the chipset even if Linux is not
+ * aware of it.  Instead of setting the flag on all busses in the
+ * machine, simply disable MSI globally.
  */
-static void __init quirk_svw_msi(struct pci_dev *dev)
+static void __init quirk_disable_all_msi(struct pci_dev *dev)
 {
 	pci_no_msi();
 	printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n");
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
 
 /* Disable MSI on chipsets that are known to not support it */
 static void __devinit quirk_disable_msi(struct pci_dev *dev)
@@ -1649,8 +1663,6 @@
 	}
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_msi);
 
 /* Go through the list of Hypertransport capabilities and
  * return 1 if a HT MSI capability is found and enabled */
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index d087e08..dbbcc04 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -54,6 +54,49 @@
 }
 
 /**
+ * pci_get_rom_size - obtain the actual size of the ROM image
+ * @rom: kernel virtual pointer to image of ROM
+ * @size: size of PCI window
+ *  return: size of actual ROM image
+ *
+ * Determine the actual length of the ROM image.
+ * The PCI window size could be much larger than the
+ * actual image size.
+ */
+size_t pci_get_rom_size(void __iomem *rom, size_t size)
+{
+	void __iomem *image;
+	int last_image;
+
+	image = rom;
+	do {
+		void __iomem *pds;
+		/* Standard PCI ROMs start out with these bytes 55 AA */
+		if (readb(image) != 0x55)
+			break;
+		if (readb(image + 1) != 0xAA)
+			break;
+		/* get the PCI data structure and check its signature */
+		pds = image + readw(image + 24);
+		if (readb(pds) != 'P')
+			break;
+		if (readb(pds + 1) != 'C')
+			break;
+		if (readb(pds + 2) != 'I')
+			break;
+		if (readb(pds + 3) != 'R')
+			break;
+		last_image = readb(pds + 21) & 0x80;
+		/* this length is reliable */
+		image += readw(pds + 16) * 512;
+	} while (!last_image);
+
+	/* never return a size larger than the PCI resource window */
+	/* there are known ROMs that get the size wrong */
+	return min((size_t)(image - rom), size);
+}
+
+/**
  * pci_map_rom - map a PCI ROM to kernel space
  * @pdev: pointer to pci device struct
  * @size: pointer to receive size of pci window over ROM
@@ -68,8 +111,6 @@
 	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
 	loff_t start;
 	void __iomem *rom;
-	void __iomem *image;
-	int last_image;
 
 	/*
 	 * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
@@ -117,33 +158,7 @@
 	 * size is much larger than the actual size of the ROM.
 	 * True size is important if the ROM is going to be copied.
 	 */
-	image = rom;
-	do {
-		void __iomem *pds;
-		/* Standard PCI ROMs start out with these bytes 55 AA */
-		if (readb(image) != 0x55)
-			break;
-		if (readb(image + 1) != 0xAA)
-			break;
-		/* get the PCI data structure and check its signature */
-		pds = image + readw(image + 24);
-		if (readb(pds) != 'P')
-			break;
-		if (readb(pds + 1) != 'C')
-			break;
-		if (readb(pds + 2) != 'I')
-			break;
-		if (readb(pds + 3) != 'R')
-			break;
-		last_image = readb(pds + 21) & 0x80;
-		/* this length is reliable */
-		image += readw(pds + 16) * 512;
-	} while (!last_image);
-
-	/* never return a size larger than the PCI resource window */
-	/* there are known ROMs that get the size wrong */
-	*size = min((size_t)(image - rom), *size);
-
+	*size = pci_get_rom_size(rom, *size);
 	return rom;
 }
 
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index b137a27..c6e79d0 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -139,12 +139,14 @@
 }
 
 /**
- * pci_get_bus_and_slot - locate PCI device from a given PCI slot
+ * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
  * @bus: number of PCI bus on which desired PCI device resides
  * @devfn: encodes number of PCI slot in which the desired PCI
  * device resides and the logical device number within that slot
  * in case of multi-function devices.
  *
+ * Note: the bus/slot search is limited to PCI domain (segment) 0.
+ *
  * Given a PCI bus and slot/function number, the desired PCI device
  * is located in system global list of PCI devices.  If the device
  * is found, a pointer to its data structure is returned.  If no
@@ -157,7 +159,8 @@
 	struct pci_dev *dev = NULL;
 
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (dev->bus->number == bus && dev->devfn == devfn)
+		if (pci_domain_nr(dev->bus) == 0 &&
+		   (dev->bus->number == bus && dev->devfn == devfn))
 			return dev;
 	}
 	return NULL;
@@ -199,7 +202,7 @@
 	 * can cause some machines to crash.  So here we detect and flag that
 	 * situation and bail out early.
 	 */
-	if (unlikely(list_empty(&pci_devices)))
+	if (unlikely(no_pci_devices()))
 		return NULL;
 	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
@@ -274,7 +277,7 @@
 	 * can cause some machines to crash.  So here we detect and flag that
 	 * situation and bail out early.
 	 */
-	if (unlikely(list_empty(&pci_devices)))
+	if (unlikely(no_pci_devices()))
 		return NULL;
 	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
@@ -403,10 +406,11 @@
 	while (ids->vendor || ids->subvendor || ids->class_mask) {
 		list_for_each_entry(dev, &pci_devices, global_list) {
 			if ((found = pci_match_one_device(ids, dev)) != NULL)
-				break;
+				goto exit;
 		}
 		ids++;
 	}
+exit:
 	up_read(&pci_bus_sem);
 	return found;
 }
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 5ec297d..5e5191e 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -34,8 +34,6 @@
 #define DBG(x...)
 #endif
 
-#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
-
 static void pbus_assign_resources_sorted(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
@@ -310,7 +308,7 @@
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
 	size = (size & 0xff) + ((size & ~0xffUL) << 2);
 #endif
-	size = ROUND_UP(size + size1, 4096);
+	size = ALIGN(size + size1, 4096);
 	if (!size) {
 		b_res->flags = 0;
 		return;
@@ -378,11 +376,11 @@
 
 		if (!align)
 			min_align = align1;
-		else if (ROUND_UP(align + min_align, min_align) < align1)
+		else if (ALIGN(align + min_align, min_align) < align1)
 			min_align = align1 >> 1;
 		align += aligns[order];
 	}
-	size = ROUND_UP(size, min_align);
+	size = ALIGN(size, min_align);
 	if (!size) {
 		b_res->flags = 0;
 		return 1;
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 9d37fec..2ac050d 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -23,14 +23,14 @@
 	u8 byte;
 	u16 word;
 	u32 dword;
-	long err, cfg_ret;
+	long err;
+	long cfg_ret;
 
-	err = -EPERM;
 	if (!capable(CAP_SYS_ADMIN))
-		goto error;
+		return -EPERM;
 
 	err = -ENODEV;
-	dev = pci_find_slot(bus, dfn);
+	dev = pci_get_bus_and_slot(bus, dfn);
 	if (!dev)
 		goto error;
 
@@ -66,7 +66,8 @@
 	case 4:
 		err = put_user(dword, (unsigned int __user *)buf);
 		break;
-	};
+	}
+	pci_dev_put(dev);
 	return err;
 
 error:
@@ -83,7 +84,8 @@
 	case 4:
 		put_user(-1, (unsigned int __user *)buf);
 		break;
-	};
+	}
+	pci_dev_put(dev);
 	return err;
 }
 
@@ -101,7 +103,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	dev = pci_find_slot(bus, dfn);
+	dev = pci_get_bus_and_slot(bus, dfn);
 	if (!dev)
 		return -ENODEV;
 
@@ -137,8 +139,8 @@
 	default:
 		err = -EINVAL;
 		break;
-	};
+	}
 	unlock_kernel();
-
+	pci_dev_put(dev);
 	return err;
 }
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 35f8864..c0c77f8 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -180,14 +180,15 @@
 	  PCMCIA cards are plugged into. If unsure, say N.
 
 config PCMCIA_M8XX
-        tristate "MPC8xx PCMCIA support"
-        depends on PCMCIA && PPC && 8xx 
-        select PCCARD_IODYN
-        help
-        Say Y here to include support for PowerPC 8xx series PCMCIA
-        controller.
+	tristate "MPC8xx PCMCIA support"
+	depends on PCMCIA && PPC && 8xx
+	select PCCARD_IODYN
+	select PCCARD_NONSTATIC
+	help
+	  Say Y here to include support for PowerPC 8xx series PCMCIA
+	  controller.
 
-        This driver is also available as a module called m8xx_pcmcia.
+	  This driver is also available as a module called m8xx_pcmcia.
 
 config HD64465_PCMCIA
 	tristate "HD64465 host bridge support"
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 948efc7..eb6abd3 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -336,16 +336,21 @@
 		enable_irq_wake(board->det_pin);
 		if (board->irq_pin)
 			enable_irq_wake(board->irq_pin);
-	} else {
-		disable_irq_wake(board->det_pin);
-		if (board->irq_pin)
-			disable_irq_wake(board->irq_pin);
 	}
 	return 0;
 }
 
 static int at91_cf_resume(struct platform_device *pdev)
 {
+	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
+	struct at91_cf_data	*board = cf->board;
+
+	if (device_may_wakeup(&pdev->dev)) {
+		disable_irq_wake(board->det_pin);
+		if (board->irq_pin)
+			disable_irq_wake(board->irq_pin);
+	}
+
 	pcmcia_socket_dev_resume(&pdev->dev);
 	return 0;
 }
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 50cad3a..7c93a10 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -651,6 +651,7 @@
 	add_wait_queue(&skt->thread_wait, &wait);
 	complete(&skt->thread_done);
 
+	set_freezable();
 	for (;;) {
 		unsigned long flags;
 		unsigned int events;
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 9721ed7..3c45142 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -10,7 +10,7 @@
  * Further fixes, v2.6 kernel port
  *     <marcelo.tosatti@cyclades.com>
  * 
- * Some fixes, additions (C) 2005 Montavista Software, Inc. 
+ * Some fixes, additions (C) 2005-2007 Montavista Software, Inc.
  *     <vbordug@ru.mvista.com>
  *
  * "The ExCA standard specifies that socket controllers should provide
@@ -40,10 +40,6 @@
 #include <linux/fcntl.h>
 #include <linux/string.h>
 
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/system.h>
-
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -51,11 +47,18 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
 
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/irq.h>
+#include <asm/fs_pd.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -110,7 +113,7 @@
 #define CONFIG_PCMCIA_SLOT_B
 #endif
 
-#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
+#endif				/* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
 
 #if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
 
@@ -143,30 +146,20 @@
 
 /* ------------------------------------------------------------------------- */
 
-#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0   */
-#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte     */
-#define PCMCIA_IO_WIN_BASE  _IO_BASE   /* base address for io window 0       */
-
-#define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level      */
-
+#define PCMCIA_MEM_WIN_BASE 0xe0000000	/* base address for memory window 0   */
+#define PCMCIA_MEM_WIN_SIZE 0x04000000	/* each memory window is 64 MByte     */
+#define PCMCIA_IO_WIN_BASE  _IO_BASE	/* base address for io window 0       */
 /* ------------------------------------------------------------------------- */
 
-/* 2.4.x and newer has this always in HZ */
-#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq))
-
-static int pcmcia_schlvl = PCMCIA_SCHLVL;
+static int pcmcia_schlvl;
 
 static DEFINE_SPINLOCK(events_lock);
 
-
 #define PCMCIA_SOCKET_KEY_5V 1
 #define PCMCIA_SOCKET_KEY_LV 2
 
 /* look up table for pgcrx registers */
-static u32 *m8xx_pgcrx[2] = {
-	&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra,
-	&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb
-};
+static u32 *m8xx_pgcrx[2];
 
 /*
  * This structure is used to address each window in the PCMCIA controller.
@@ -176,8 +169,8 @@
  */
 
 struct pcmcia_win {
-	u32	br;
-	u32	or;
+	u32 br;
+	u32 or;
 };
 
 /*
@@ -221,22 +214,27 @@
 
 /* we keep one lookup table per socket to check flags */
 
-#define PCMCIA_EVENTS_MAX 5  /* 4 max at a time + termination */
+#define PCMCIA_EVENTS_MAX 5	/* 4 max at a time + termination */
 
 struct event_table {
 	u32 regbit;
 	u32 eventbit;
 };
 
+static const char driver_name[] = "m8xx-pcmcia";
+
 struct socket_info {
-	void	(*handler)(void *info, u32 events);
-	void	*info;
+	void (*handler) (void *info, u32 events);
+	void *info;
 
 	u32 slot;
+	pcmconf8xx_t *pcmcia;
+	u32 bus_freq;
+	int hwirq;
 
 	socket_state_t state;
 	struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
-	struct pccard_io_map  io_win[PCMCIA_IO_WIN_NO];
+	struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
 	struct event_table events[PCMCIA_EVENTS_MAX];
 	struct pcmcia_socket socket;
 };
@@ -250,8 +248,7 @@
 
 #define M8XX_SIZES_NO 32
 
-static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] =
-{
+static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = {
 	0x00000001, 0x00000002, 0x00000008, 0x00000004,
 	0x00000080, 0x00000040, 0x00000010, 0x00000020,
 	0x00008000, 0x00004000, 0x00001000, 0x00002000,
@@ -267,7 +264,7 @@
 
 static irqreturn_t m8xx_interrupt(int irq, void *dev);
 
-#define PCMCIA_BMT_LIMIT (15*4)  /* Bus Monitor Timeout value */
+#define PCMCIA_BMT_LIMIT (15*4)	/* Bus Monitor Timeout value */
 
 /* ------------------------------------------------------------------------- */
 /* board specific stuff:                                                     */
@@ -291,8 +288,9 @@
 {
 	u32 reg = 0;
 
-	switch(vcc) {
-	case 0: break;
+	switch (vcc) {
+	case 0:
+		break;
 	case 33:
 		reg |= BCSR1_PCVCTL4;
 		break;
@@ -303,11 +301,12 @@
 		return 1;
 	}
 
-	switch(vpp) {
-	case 0: break;
+	switch (vpp) {
+	case 0:
+		break;
 	case 33:
 	case 50:
-		if(vcc == vpp)
+		if (vcc == vpp)
 			reg |= BCSR1_PCVCTL6;
 		else
 			return 1;
@@ -318,25 +317,29 @@
 		return 1;
 	}
 
-	if(!((vcc == 50) || (vcc == 0)))
+	if (!((vcc == 50) || (vcc == 0)))
 		return 1;
 
 	/* first, turn off all power */
 
-	out_be32(((u32 *)RPX_CSR_ADDR), in_be32(((u32 *)RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5 | BCSR1_PCVCTL6 | BCSR1_PCVCTL7));
+	out_be32(((u32 *) RPX_CSR_ADDR),
+		 in_be32(((u32 *) RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 |
+						     BCSR1_PCVCTL5 |
+						     BCSR1_PCVCTL6 |
+						     BCSR1_PCVCTL7));
 
 	/* enable new powersettings */
 
-	out_be32(((u32 *)RPX_CSR_ADDR), in_be32(((u32 *)RPX_CSR_ADDR)) | reg);
+	out_be32(((u32 *) RPX_CSR_ADDR), in_be32(((u32 *) RPX_CSR_ADDR)) | reg);
 
 	return 0;
 }
 
 #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_)  /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
+#define hardware_enable(_slot_)	/* No hardware to enable */
+#define hardware_disable(_slot_)	/* No hardware to disable */
 
-#endif /* CONFIG_RPXCLASSIC */
+#endif				/* CONFIG_RPXCLASSIC */
 
 /* FADS Boards from Motorola                                               */
 
@@ -348,43 +351,45 @@
 {
 	u32 reg = 0;
 
-	switch(vcc) {
-		case 0:
-			break;
-		case 33:
-			reg |= BCSR1_PCCVCC0;
-			break;
-		case 50:
-			reg |= BCSR1_PCCVCC1;
-			break;
-		default:
-			return 1;
+	switch (vcc) {
+	case 0:
+		break;
+	case 33:
+		reg |= BCSR1_PCCVCC0;
+		break;
+	case 50:
+		reg |= BCSR1_PCCVCC1;
+		break;
+	default:
+		return 1;
 	}
 
-	switch(vpp) {
-		case 0:
-			break;
-		case 33:
-		case 50:
-			if(vcc == vpp)
-				reg |= BCSR1_PCCVPP1;
-			else
-				return 1;
-			break;
-		case 120:
-			if ((vcc == 33) || (vcc == 50))
-				reg |= BCSR1_PCCVPP0;
-			else
-				return 1;
-		default:
+	switch (vpp) {
+	case 0:
+		break;
+	case 33:
+	case 50:
+		if (vcc == vpp)
+			reg |= BCSR1_PCCVPP1;
+		else
 			return 1;
+		break;
+	case 120:
+		if ((vcc == 33) || (vcc == 50))
+			reg |= BCSR1_PCCVPP0;
+		else
+			return 1;
+	default:
+		return 1;
 	}
 
 	/* first, turn off all power */
-	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
+	out_be32((u32 *) BCSR1,
+		 in_be32((u32 *) BCSR1) & ~(BCSR1_PCCVCC_MASK |
+					    BCSR1_PCCVPP_MASK));
 
 	/* enable new powersettings */
-	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) | reg);
+	out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg);
 
 	return 0;
 }
@@ -393,12 +398,12 @@
 
 static void hardware_enable(int slot)
 {
-	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~BCSR1_PCCEN);
+	out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~BCSR1_PCCEN);
 }
 
 static void hardware_disable(int slot)
 {
-	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) |  BCSR1_PCCEN);
+	out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN);
 }
 
 #endif
@@ -408,78 +413,21 @@
 #if defined(CONFIG_MPC885ADS)
 
 #define PCMCIA_BOARD_MSG "MPC885ADS"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
-	u32 reg = 0;
-	unsigned *bcsr_io;
-
-	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-	switch(vcc) {
-		case 0:
-			break;
-		case 33:
-			reg |= BCSR1_PCCVCC0;
-			break;
-		case 50:
-			reg |= BCSR1_PCCVCC1;
-			break;
-		default:
-			goto out_unmap;
-	}
-
-	switch(vpp) {
-		case 0:
-			break;
-		case 33:
-		case 50:
-			if(vcc == vpp)
-				reg |= BCSR1_PCCVPP1;
-			else
-				goto out_unmap;
-			break;
-		case 120:
-			if ((vcc == 33) || (vcc == 50))
-				reg |= BCSR1_PCCVPP0;
-			else
-				goto out_unmap;
-		default:
-			goto out_unmap;
-	}
-
-	/* first, turn off all power */
-	out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
-
-	/* enable new powersettings */
-	out_be32(bcsr_io, in_be32(bcsr_io) | reg);
-
-	iounmap(bcsr_io);
-	return 0;
-
-out_unmap:
-	iounmap(bcsr_io);
-	return 1;
-}
-
 #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
 
-static void hardware_enable(int slot)
+static inline void hardware_enable(int slot)
 {
-	unsigned *bcsr_io;
-
-	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-	out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN);
-	iounmap(bcsr_io);
+	m8xx_pcmcia_ops.hw_ctrl(slot, 1);
 }
 
-static void hardware_disable(int slot)
+static inline void hardware_disable(int slot)
 {
-	unsigned *bcsr_io;
+	m8xx_pcmcia_ops.hw_ctrl(slot, 0);
+}
 
-	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-	out_be32(bcsr_io, in_be32(bcsr_io) |  BCSR1_PCCEN);
-	iounmap(bcsr_io);
+static inline int voltage_set(int slot, int vcc, int vpp)
+{
+	return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp);
 }
 
 #endif
@@ -495,52 +443,53 @@
 {
 	u8 reg = 0;
 
-	switch(vcc) {
-		case 0:
-			break;
-		case 33:
-			reg |= CSR2_VCC_33;
-			break;
-		case 50:
-			reg |= CSR2_VCC_50;
-			break;
-		default:
-			return 1;
+	switch (vcc) {
+	case 0:
+		break;
+	case 33:
+		reg |= CSR2_VCC_33;
+		break;
+	case 50:
+		reg |= CSR2_VCC_50;
+		break;
+	default:
+		return 1;
 	}
 
-	switch(vpp) {
-		case 0:
-			break;
-		case 33:
-		case 50:
-			if(vcc == vpp)
-				reg |= CSR2_VPP_VCC;
-			else
-				return 1;
-			break;
-		case 120:
-			if ((vcc == 33) || (vcc == 50))
-				reg |= CSR2_VPP_12;
-			else
-				return 1;
-		default:
+	switch (vpp) {
+	case 0:
+		break;
+	case 33:
+	case 50:
+		if (vcc == vpp)
+			reg |= CSR2_VPP_VCC;
+		else
 			return 1;
+		break;
+	case 120:
+		if ((vcc == 33) || (vcc == 50))
+			reg |= CSR2_VPP_12;
+		else
+			return 1;
+	default:
+		return 1;
 	}
 
 	/* first, turn off all power */
-	out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
+	out_8((u8 *) MBX_CSR2_ADDR,
+	      in_8((u8 *) MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
 
 	/* enable new powersettings */
-	out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) | reg);
+	out_8((u8 *) MBX_CSR2_ADDR, in_8((u8 *) MBX_CSR2_ADDR) | reg);
 
 	return 0;
 }
 
 #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_)  /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
+#define hardware_enable(_slot_)	/* No hardware to enable */
+#define hardware_disable(_slot_)	/* No hardware to disable */
 
-#endif /* CONFIG_MBX */
+#endif				/* CONFIG_MBX */
 
 #if defined(CONFIG_PRxK)
 #include <asm/cpld.h>
@@ -554,43 +503,46 @@
 	u8 regread;
 	cpld_regs *ccpld = get_cpld();
 
-	switch(vcc) {
-		case 0:
-			break;
-		case 33:
-			reg |= PCMCIA_VCC_33;
-			break;
-		case 50:
-			reg |= PCMCIA_VCC_50;
-			break;
-		default:
-			return 1;
+	switch (vcc) {
+	case 0:
+		break;
+	case 33:
+		reg |= PCMCIA_VCC_33;
+		break;
+	case 50:
+		reg |= PCMCIA_VCC_50;
+		break;
+	default:
+		return 1;
 	}
 
-	switch(vpp) {
-		case 0:
-			break;
-		case 33:
-		case 50:
-			if(vcc == vpp)
-				reg |= PCMCIA_VPP_VCC;
-			else
-				return 1;
-			break;
-		case 120:
-			if ((vcc == 33) || (vcc == 50))
-				reg |= PCMCIA_VPP_12;
-			else
-				return 1;
-		default:
+	switch (vpp) {
+	case 0:
+		break;
+	case 33:
+	case 50:
+		if (vcc == vpp)
+			reg |= PCMCIA_VPP_VCC;
+		else
 			return 1;
+		break;
+	case 120:
+		if ((vcc == 33) || (vcc == 50))
+			reg |= PCMCIA_VPP_12;
+		else
+			return 1;
+	default:
+		return 1;
 	}
 
 	reg = reg >> (slot << 2);
 	regread = in_8(&ccpld->fpga_pc_ctl);
-	if (reg != (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
+	if (reg !=
+	    (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
 		/* enable new powersettings */
-		regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2));
+		regread =
+		    regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >>
+				(slot << 2));
 		out_8(&ccpld->fpga_pc_ctl, reg | regread);
 		msleep(100);
 	}
@@ -599,52 +551,10 @@
 }
 
 #define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
-#define hardware_enable(_slot_)  /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
+#define hardware_enable(_slot_)	/* No hardware to enable */
+#define hardware_disable(_slot_)	/* No hardware to disable */
 
-#endif /* CONFIG_PRxK */
-
-static void m8xx_shutdown(void)
-{
-	u32 m, i;
-	struct pcmcia_win *w;
-
-	for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
-		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
-
-		out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i));
-		out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i));
-
-		/* turn off interrupt and disable CxOE */
-		out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
-
-		/* turn off memory windows */
-		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
-			out_be32(&w->or, 0); /* set to not valid */
-			w++;
-		}
-
-		/* turn off voltage */
-		voltage_set(i, 0, 0);
-
-		/* disable external hardware */
-		hardware_disable(i);
-	}
-
-	free_irq(pcmcia_schlvl, NULL);
-}
-
-static struct device_driver m8xx_driver = {
-        .name = "m8xx-pcmcia",
-        .bus = &platform_bus_type,
-        .suspend = pcmcia_socket_dev_suspend,
-        .resume = pcmcia_socket_dev_resume,
-};
-
-static struct platform_device m8xx_device = {
-        .name = "m8xx-pcmcia",
-        .id = 0,
-};
+#endif				/* CONFIG_PRxK */
 
 static u32 pending_events[PCMCIA_SOCKETS_NO];
 static DEFINE_SPINLOCK(pending_event_lock);
@@ -654,24 +564,25 @@
 	struct socket_info *s;
 	struct event_table *e;
 	unsigned int i, events, pscr, pipr, per;
+	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
 
 	dprintk("Interrupt!\n");
 	/* get interrupt sources */
 
-	pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr);
-	pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
-	per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per);
+	pscr = in_be32(&pcmcia->pcmc_pscr);
+	pipr = in_be32(&pcmcia->pcmc_pipr);
+	per = in_be32(&pcmcia->pcmc_per);
 
-	for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
 		s = &socket[i];
 		e = &s->events[0];
 		events = 0;
 
-		while(e->regbit) {
-			if(pscr & e->regbit)
+		while (e->regbit) {
+			if (pscr & e->regbit)
 				events |= e->eventbit;
 
-				e++;
+			e++;
 		}
 
 		/*
@@ -679,13 +590,11 @@
 		 * not too nice done,
 		 * we depend on that CD2 is the bit to the left of CD1...
 		 */
-		if(events & SS_DETECT)
-			if(((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
-				(pipr & M8XX_PCMCIA_CD1(i)))
-			{
+		if (events & SS_DETECT)
+			if (((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
+			    (pipr & M8XX_PCMCIA_CD1(i))) {
 				events &= ~SS_DETECT;
 			}
-
 #ifdef PCMCIA_GLITCHY_CD
 		/*
 		 * I've experienced CD problems with my ADS board.
@@ -693,24 +602,23 @@
 		 * real change of Card detection.
 		 */
 
-		if((events & SS_DETECT) &&
-		   ((pipr &
-		     (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
-		   (s->state.Vcc | s->state.Vpp)) {
+		if ((events & SS_DETECT) &&
+		    ((pipr &
+		      (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
+		    (s->state.Vcc | s->state.Vpp)) {
 			events &= ~SS_DETECT;
 			/*printk( "CD glitch workaround - CD = 0x%08x!\n",
-				(pipr & (M8XX_PCMCIA_CD2(i)
-					 | M8XX_PCMCIA_CD1(i))));*/
+			   (pipr & (M8XX_PCMCIA_CD2(i)
+			   | M8XX_PCMCIA_CD1(i)))); */
 		}
 #endif
 
 		/* call the handler */
 
 		dprintk("slot %u: events = 0x%02x, pscr = 0x%08x, "
-			"pipr = 0x%08x\n",
-			i, events, pscr, pipr);
+			"pipr = 0x%08x\n", i, events, pscr, pipr);
 
-		if(events) {
+		if (events) {
 			spin_lock(&pending_event_lock);
 			pending_events[i] |= events;
 			spin_unlock(&pending_event_lock);
@@ -724,7 +632,7 @@
 			per &= ~M8XX_PCMCIA_RDY_L(0);
 			per &= ~M8XX_PCMCIA_RDY_L(1);
 
-			out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per);
+			out_be32(&pcmcia->pcmc_per, per);
 
 			if (events)
 				pcmcia_parse_events(&socket[i].socket, events);
@@ -732,7 +640,7 @@
 	}
 
 	/* clear the interrupt sources */
-	out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr);
+	out_be32(&pcmcia->pcmc_pscr, pscr);
 
 	dprintk("Interrupt done.\n");
 
@@ -743,21 +651,21 @@
 {
 	u32 k;
 
-	for(k = 0; k < M8XX_SIZES_NO; k++)
-		if(m8xx_size_to_gray[k] == size)
+	for (k = 0; k < M8XX_SIZES_NO; k++)
+		if (m8xx_size_to_gray[k] == size)
 			break;
 
-	if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
+	if ((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
 		k = -1;
 
 	return k;
 }
 
-static u32 m8xx_get_speed(u32 ns, u32 is_io)
+static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq)
 {
 	u32 reg, clocks, psst, psl, psht;
 
-	if(!ns) {
+	if (!ns) {
 
 		/*
 		 * We get called with IO maps setup to 0ns
@@ -765,10 +673,10 @@
 		 * They should be 255ns.
 		 */
 
-		if(is_io)
+		if (is_io)
 			ns = 255;
 		else
-			ns = 100;  /* fast memory if 0 */
+			ns = 100;	/* fast memory if 0 */
 	}
 
 	/*
@@ -779,23 +687,23 @@
 
 /* how we want to adjust the timing - in percent */
 
-#define ADJ 180 /* 80 % longer accesstime - to be sure */
+#define ADJ 180			/* 80 % longer accesstime - to be sure */
 
-	clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
-	clocks = (clocks * ADJ) / (100*1000);
-	if(clocks >= PCMCIA_BMT_LIMIT) {
-		printk( "Max access time limit reached\n");
-		clocks = PCMCIA_BMT_LIMIT-1;
+	clocks = ((bus_freq / 1000) * ns) / 1000;
+	clocks = (clocks * ADJ) / (100 * 1000);
+	if (clocks >= PCMCIA_BMT_LIMIT) {
+		printk("Max access time limit reached\n");
+		clocks = PCMCIA_BMT_LIMIT - 1;
 	}
 
-	psst = clocks / 7;          /* setup time */
-	psht = clocks / 7;          /* hold time */
-	psl  = (clocks * 5) / 7;    /* strobe length */
+	psst = clocks / 7;	/* setup time */
+	psht = clocks / 7;	/* hold time */
+	psl = (clocks * 5) / 7;	/* strobe length */
 
 	psst += clocks - (psst + psht + psl);
 
-	reg =  psst << 12;
-	reg |= psl  << 7;
+	reg = psst << 12;
+	reg |= psl << 7;
 	reg |= psht << 16;
 
 	return reg;
@@ -806,11 +714,12 @@
 	int lsock = container_of(sock, struct socket_info, socket)->slot;
 	struct socket_info *s = &socket[lsock];
 	unsigned int pipr, reg;
+	pcmconf8xx_t *pcmcia = s->pcmcia;
 
-	pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
+	pipr = in_be32(&pcmcia->pcmc_pipr);
 
-	*value  = ((pipr & (M8XX_PCMCIA_CD1(lsock)
-			    | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
+	*value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
+			   | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
 	*value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
 
 	if (s->state.flags & SS_IOCARD)
@@ -894,16 +803,16 @@
 	/* read out VS1 and VS2 */
 
 	reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
-		>> M8XX_PCMCIA_VS_SHIFT(lsock);
+	    >> M8XX_PCMCIA_VS_SHIFT(lsock);
 
-	if(socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
-		switch(reg) {
+	if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
+		switch (reg) {
 		case 1:
 			*value |= SS_3VCARD;
-			break; /* GND, NC - 3.3V only */
+			break;	/* GND, NC - 3.3V only */
 		case 2:
 			*value |= SS_XVCARD;
-			break; /* NC. GND - x.xV only */
+			break;	/* NC. GND - x.xV only */
 		};
 	}
 
@@ -911,27 +820,29 @@
 	return 0;
 }
 
-static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state)
 {
 	int lsock = container_of(sock, struct socket_info, socket)->slot;
 	struct socket_info *s = &socket[lsock];
 	struct event_table *e;
 	unsigned int reg;
 	unsigned long flags;
+	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
 
-	dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
-	      "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
-	      state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
+	dprintk("SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
+		"io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
+		state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
 
 	/* First, set voltage - bail out if invalid */
-	if(voltage_set(lsock, state->Vcc, state->Vpp))
+	if (voltage_set(lsock, state->Vcc, state->Vpp))
 		return -EINVAL;
 
 	/* Take care of reset... */
-	if(state->flags & SS_RESET)
-		out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) |  M8XX_PGCRX_CXRESET); /* active high */
+	if (state->flags & SS_RESET)
+		out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET);	/* active high */
 	else
-		out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
+		out_be32(M8XX_PGCRX(lsock),
+			 in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
 
 	/* ... and output enable. */
 
@@ -943,10 +854,11 @@
 	   no pullups are present -> the cards act wierd.
 	   So right now the buffers are enabled if the power is on. */
 
-	if(state->Vcc || state->Vpp)
-		out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */
+	if (state->Vcc || state->Vpp)
+		out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE);	/* active low */
 	else
-		out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
+		out_be32(M8XX_PGCRX(lsock),
+			 in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
 
 	/*
 	 * We'd better turn off interrupts before
@@ -963,17 +875,17 @@
 	e = &s->events[0];
 	reg = 0;
 
-	if(state->csc_mask & SS_DETECT) {
+	if (state->csc_mask & SS_DETECT) {
 		e->eventbit = SS_DETECT;
 		reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock)
 				    | M8XX_PCMCIA_CD1(lsock));
 		e++;
 	}
-	if(state->flags & SS_IOCARD) {
+	if (state->flags & SS_IOCARD) {
 		/*
 		 * I/O card
 		 */
-		if(state->csc_mask & SS_STSCHG) {
+		if (state->csc_mask & SS_STSCHG) {
 			e->eventbit = SS_STSCHG;
 			reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
 			e++;
@@ -981,8 +893,10 @@
 		/*
 		 * If io_irq is non-zero we should enable irq.
 		 */
-		if(state->io_irq) {
-			out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24);
+		if (state->io_irq) {
+			out_be32(M8XX_PGCRX(lsock),
+				 in_be32(M8XX_PGCRX(lsock)) |
+				 mk_int_int_mask(s->hwirq) << 24);
 			/*
 			 * Strange thing here:
 			 * The manual does not tell us which interrupt
@@ -993,33 +907,32 @@
 			 * have to be cleared in PSCR in the interrupt handler.
 			 */
 			reg |= M8XX_PCMCIA_RDY_L(lsock);
-		}
-		else
-			out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
-	}
-	else {
+		} else
+			out_be32(M8XX_PGCRX(lsock),
+				 in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
+	} else {
 		/*
 		 * Memory card
 		 */
-		if(state->csc_mask & SS_BATDEAD) {
+		if (state->csc_mask & SS_BATDEAD) {
 			e->eventbit = SS_BATDEAD;
 			reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
 			e++;
 		}
-		if(state->csc_mask & SS_BATWARN) {
+		if (state->csc_mask & SS_BATWARN) {
 			e->eventbit = SS_BATWARN;
 			reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
 			e++;
 		}
 		/* What should I trigger on - low/high,raise,fall? */
-		if(state->csc_mask & SS_READY) {
+		if (state->csc_mask & SS_READY) {
 			e->eventbit = SS_READY;
-			reg |= e->regbit = 0; //??
+			reg |= e->regbit = 0;	//??
 			e++;
 		}
 	}
 
-	e->regbit = 0;  /* terminate list */
+	e->regbit = 0;		/* terminate list */
 
 	/*
 	 * Clear the status changed .
@@ -1027,7 +940,7 @@
 	 * Writing ones will clear the bits.
 	 */
 
-	out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg);
+	out_be32(&pcmcia->pcmc_pscr, reg);
 
 	/*
 	 * Write the mask.
@@ -1036,15 +949,10 @@
 	 * Ones will enable the interrupt.
 	 */
 
-	/*
-	  reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per
-	  & M8XX_PCMCIA_MASK(lsock);
-	*/
-
-	reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
-		(M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
-
-	out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg);
+	reg |=
+	    in_be32(&pcmcia->
+		    pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
+	out_be32(&pcmcia->pcmc_per, reg);
 
 	spin_unlock_irqrestore(&events_lock, flags);
 
@@ -1062,66 +970,68 @@
 	struct socket_info *s = &socket[lsock];
 	struct pcmcia_win *w;
 	unsigned int reg, winnr;
+	pcmconf8xx_t *pcmcia = s->pcmcia;
 
 #define M8XX_SIZE (io->stop - io->start + 1)
 #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
 
-	dprintk( "SetIOMap(%d, %d, %#2.2x, %d ns, "
-	      "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
-	      io->speed, io->start, io->stop);
+	dprintk("SetIOMap(%d, %d, %#2.2x, %d ns, "
+		"%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
+		io->speed, io->start, io->stop);
 
 	if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
 	    || (io->stop > 0xffff) || (io->stop < io->start))
 		return -EINVAL;
 
-	if((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
+	if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
 		return -EINVAL;
 
-	if(io->flags & MAP_ACTIVE) {
+	if (io->flags & MAP_ACTIVE) {
 
-		dprintk( "io->flags & MAP_ACTIVE\n");
+		dprintk("io->flags & MAP_ACTIVE\n");
 
 		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
-			+ (lsock * PCMCIA_IO_WIN_NO) + io->map;
+		    + (lsock * PCMCIA_IO_WIN_NO) + io->map;
 
 		/* setup registers */
 
-		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+		w = (void *)&pcmcia->pcmc_pbr0;
 		w += winnr;
 
-		out_be32(&w->or, 0); /* turn off window first */
+		out_be32(&w->or, 0);	/* turn off window first */
 		out_be32(&w->br, M8XX_BASE);
 
 		reg <<= 27;
-  		reg |= M8XX_PCMCIA_POR_IO |(lsock << 2);
+		reg |= M8XX_PCMCIA_POR_IO | (lsock << 2);
 
-		reg |= m8xx_get_speed(io->speed, 1);
+		reg |= m8xx_get_speed(io->speed, 1, s->bus_freq);
 
-		if(io->flags & MAP_WRPROT)
+		if (io->flags & MAP_WRPROT)
 			reg |= M8XX_PCMCIA_POR_WRPROT;
 
-		if(io->flags & (MAP_16BIT | MAP_AUTOSZ))
+		/*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */
+		if (io->flags & MAP_16BIT)
 			reg |= M8XX_PCMCIA_POR_16BIT;
 
-		if(io->flags & MAP_ACTIVE)
+		if (io->flags & MAP_ACTIVE)
 			reg |= M8XX_PCMCIA_POR_VALID;
 
 		out_be32(&w->or, reg);
 
 		dprintk("Socket %u: Mapped io window %u at %#8.8x, "
-		      "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
+			"OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
 	} else {
 		/* shutdown IO window */
 		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
-			+ (lsock * PCMCIA_IO_WIN_NO) + io->map;
+		    + (lsock * PCMCIA_IO_WIN_NO) + io->map;
 
 		/* setup registers */
 
-		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+		w = (void *)&pcmcia->pcmc_pbr0;
 		w += winnr;
 
-		out_be32(&w->or, 0); /* turn off window */
-		out_be32(&w->br, 0); /* turn off base address */
+		out_be32(&w->or, 0);	/* turn off window */
+		out_be32(&w->br, 0);	/* turn off base address */
 
 		dprintk("Socket %u: Unmapped io window %u at %#8.8x, "
 			"OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
@@ -1129,35 +1039,35 @@
 
 	/* copy the struct and modify the copy */
 	s->io_win[io->map] = *io;
-	s->io_win[io->map].flags &= (MAP_WRPROT
-				     | MAP_16BIT
-				     | MAP_ACTIVE);
+	s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
 	dprintk("SetIOMap exit\n");
 
 	return 0;
 }
 
-static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
+static int m8xx_set_mem_map(struct pcmcia_socket *sock,
+			    struct pccard_mem_map *mem)
 {
 	int lsock = container_of(sock, struct socket_info, socket)->slot;
 	struct socket_info *s = &socket[lsock];
 	struct pcmcia_win *w;
 	struct pccard_mem_map *old;
 	unsigned int reg, winnr;
+	pcmconf8xx_t *pcmcia = s->pcmcia;
 
-	dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, "
-	      "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
-	      mem->speed, mem->static_start, mem->card_start);
+	dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
+		"%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
+		mem->speed, mem->static_start, mem->card_start);
 
 	if ((mem->map >= PCMCIA_MEM_WIN_NO)
-//	    || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
+//          || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
 	    || (mem->card_start >= 0x04000000)
-	    || (mem->static_start & 0xfff)                /* 4KByte resolution */
-	    || (mem->card_start & 0xfff))
+	    || (mem->static_start & 0xfff)	/* 4KByte resolution */
+	    ||(mem->card_start & 0xfff))
 		return -EINVAL;
 
-	if((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
-		printk( "Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
+	if ((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
+		printk("Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
 		return -EINVAL;
 	}
 	reg <<= 27;
@@ -1166,50 +1076,47 @@
 
 	/* Setup the window in the pcmcia controller */
 
-	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+	w = (void *)&pcmcia->pcmc_pbr0;
 	w += winnr;
 
 	reg |= lsock << 2;
 
-	reg |= m8xx_get_speed(mem->speed, 0);
+	reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq);
 
-	if(mem->flags & MAP_ATTRIB)
-		reg |=  M8XX_PCMCIA_POR_ATTRMEM;
+	if (mem->flags & MAP_ATTRIB)
+		reg |= M8XX_PCMCIA_POR_ATTRMEM;
 
-	if(mem->flags & MAP_WRPROT)
+	if (mem->flags & MAP_WRPROT)
 		reg |= M8XX_PCMCIA_POR_WRPROT;
 
-	if(mem->flags & MAP_16BIT)
+	if (mem->flags & MAP_16BIT)
 		reg |= M8XX_PCMCIA_POR_16BIT;
 
-	if(mem->flags & MAP_ACTIVE)
+	if (mem->flags & MAP_ACTIVE)
 		reg |= M8XX_PCMCIA_POR_VALID;
 
 	out_be32(&w->or, reg);
 
 	dprintk("Socket %u: Mapped memory window %u at %#8.8x, "
-	      "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
+		"OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
 
-	if(mem->flags & MAP_ACTIVE) {
+	if (mem->flags & MAP_ACTIVE) {
 		/* get the new base address */
 		mem->static_start = PCMCIA_MEM_WIN_BASE +
-			(PCMCIA_MEM_WIN_SIZE * winnr)
-			+ mem->card_start;
+		    (PCMCIA_MEM_WIN_SIZE * winnr)
+		    + mem->card_start;
 	}
 
 	dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
-	      "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
-	      mem->speed, mem->static_start, mem->card_start);
+		"%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
+		mem->speed, mem->static_start, mem->card_start);
 
 	/* copy the struct and modify the copy */
 
 	old = &s->mem_win[mem->map];
 
 	*old = *mem;
-	old->flags &= (MAP_ATTRIB
-		       | MAP_WRPROT
-		       | MAP_16BIT
-		       | MAP_ACTIVE);
+	old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
 
 	return 0;
 }
@@ -1220,7 +1127,7 @@
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
 	pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
 
-	dprintk( "sock_init(%d)\n", s);
+	dprintk("sock_init(%d)\n", s);
 
 	m8xx_set_socket(sock, &dead_socket);
 	for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
@@ -1236,111 +1143,195 @@
 
 }
 
-static int m8xx_suspend(struct pcmcia_socket *sock)
+static int m8xx_sock_suspend(struct pcmcia_socket *sock)
 {
 	return m8xx_set_socket(sock, &dead_socket);
 }
 
 static struct pccard_operations m8xx_services = {
-	.init	= m8xx_sock_init,
-	.suspend = m8xx_suspend,
+	.init = m8xx_sock_init,
+	.suspend = m8xx_sock_suspend,
 	.get_status = m8xx_get_status,
 	.set_socket = m8xx_set_socket,
 	.set_io_map = m8xx_set_io_map,
 	.set_mem_map = m8xx_set_mem_map,
 };
 
-static int __init m8xx_init(void)
+static int __init m8xx_probe(struct of_device *ofdev,
+			     const struct of_device_id *match)
 {
 	struct pcmcia_win *w;
-	unsigned int i,m;
+	unsigned int i, m, hwirq;
+	pcmconf8xx_t *pcmcia;
+	int status;
+	struct device_node *np = ofdev->node;
 
 	pcmcia_info("%s\n", version);
 
-	if (driver_register(&m8xx_driver))
-		return -1;
+	pcmcia = of_iomap(np, 0);
+	if (pcmcia == NULL)
+		return -EINVAL;
+
+	pcmcia_schlvl = irq_of_parse_and_map(np, 0);
+	hwirq = irq_map[pcmcia_schlvl].hwirq;
+	if (pcmcia_schlvl < 0)
+		return -EINVAL;
+
+	m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
+	m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
 
 	pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
-		    " with IRQ %u.\n", pcmcia_schlvl);
+		    " with IRQ %u  (%d). \n", pcmcia_schlvl, hwirq);
 
 	/* Configure Status change interrupt */
 
-	if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0,
-			  "m8xx_pcmcia", NULL)) {
+	if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED,
+			driver_name, socket)) {
 		pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
 			     pcmcia_schlvl);
 		return -1;
 	}
 
-	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+	w = (void *)&pcmcia->pcmc_pbr0;
 
-	out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr,
-		M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));
+	out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
+	clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
 
-	out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per,
-		in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
-		~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)));
+	/* connect interrupt and disable CxOE */
 
-/* connect interrupt and disable CxOE */
+	out_be32(M8XX_PGCRX(0),
+		 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
+	out_be32(M8XX_PGCRX(1),
+		 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
 
-	out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
-	out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
+	/* intialize the fixed memory windows */
 
-/* intialize the fixed memory windows */
-
-	for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
-		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+		for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
 			out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
-				(PCMCIA_MEM_WIN_SIZE
-				 * (m + i * PCMCIA_MEM_WIN_NO)));
+				 (PCMCIA_MEM_WIN_SIZE
+				  * (m + i * PCMCIA_MEM_WIN_NO)));
 
-			out_be32(&w->or, 0);  /* set to not valid */
+			out_be32(&w->or, 0);	/* set to not valid */
 
 			w++;
 		}
 	}
 
-/* turn off voltage */
+	/* turn off voltage */
 	voltage_set(0, 0, 0);
 	voltage_set(1, 0, 0);
 
-/* Enable external hardware */
+	/* Enable external hardware */
 	hardware_enable(0);
 	hardware_enable(1);
 
-	platform_device_register(&m8xx_device);
-
-	for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) {
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
 		socket[i].slot = i;
 		socket[i].socket.owner = THIS_MODULE;
-		socket[i].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
+		socket[i].socket.features =
+		    SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
 		socket[i].socket.irq_mask = 0x000;
 		socket[i].socket.map_size = 0x1000;
 		socket[i].socket.io_offset = 0;
-		socket[i].socket.pci_irq = i  ? 7 : 9;
+		socket[i].socket.pci_irq = pcmcia_schlvl;
 		socket[i].socket.ops = &m8xx_services;
-		socket[i].socket.resource_ops = &pccard_iodyn_ops;
+		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
 		socket[i].socket.cb_dev = NULL;
-		socket[i].socket.dev.parent = &m8xx_device.dev;
+		socket[i].socket.dev.parent = &ofdev->dev;
+		socket[i].pcmcia = pcmcia;
+		socket[i].bus_freq = ppc_proc_freq;
+		socket[i].hwirq = hwirq;
+
 	}
 
-	for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
-		pcmcia_register_socket(&socket[i].socket);
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+		status = pcmcia_register_socket(&socket[i].socket);
+		if (status < 0)
+			pcmcia_error("Socket register failed\n");
+	}
 
 	return 0;
 }
 
-static void __exit m8xx_exit(void)
+static int m8xx_remove(struct of_device *ofdev)
 {
-	int i;
+	u32 m, i;
+	struct pcmcia_win *w;
+	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
 
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+		w = (void *)&pcmcia->pcmc_pbr0;
+
+		out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i));
+		out_be32(&pcmcia->pcmc_per,
+			 in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i));
+
+		/* turn off interrupt and disable CxOE */
+		out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
+
+		/* turn off memory windows */
+		for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+			out_be32(&w->or, 0);	/* set to not valid */
+			w++;
+		}
+
+		/* turn off voltage */
+		voltage_set(i, 0, 0);
+
+		/* disable external hardware */
+		hardware_disable(i);
+	}
 	for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
 		pcmcia_unregister_socket(&socket[i].socket);
 
-	m8xx_shutdown();
+	free_irq(pcmcia_schlvl, NULL);
 
-	platform_device_unregister(&m8xx_device);
-	driver_unregister(&m8xx_driver);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&pdev->dev, state);
+}
+
+static int m8xx_resume(struct platform_device *pdev)
+{
+	return pcmcia_socket_dev_resume(&pdev->dev);
+}
+#else
+#define m8xx_suspend NULL
+#define m8xx_resume NULL
+#endif
+
+static struct of_device_id m8xx_pcmcia_match[] = {
+	{
+	 .type = "pcmcia",
+	 .compatible = "fsl,pq-pcmcia",
+	 },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
+
+static struct of_platform_driver m8xx_pcmcia_driver = {
+	.name = (char *)driver_name,
+	.match_table = m8xx_pcmcia_match,
+	.probe = m8xx_probe,
+	.remove = m8xx_remove,
+	.suspend = m8xx_suspend,
+	.resume = m8xx_resume,
+};
+
+static int __init m8xx_init(void)
+{
+	return of_register_platform_driver(&m8xx_pcmcia_driver);
+}
+
+static void __exit m8xx_exit(void)
+{
+	of_unregister_platform_driver(&m8xx_pcmcia_driver);
 }
 
 module_init(m8xx_init);
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index a2bb465..b440900 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -283,7 +283,9 @@
 	return (ret);
 }
 
-static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t pccard_show_cis(struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t off, size_t count)
 {
 	unsigned int size = 0x200;
 
@@ -311,7 +313,9 @@
 	return (count);
 }
 
-static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t pccard_store_cis(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t off, size_t count)
 {
 	struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
 	cisdump_t *cis;
@@ -366,7 +370,7 @@
 };
 
 static struct bin_attribute pccard_cis_attr = {
-	.attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE},
+	.attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
 	.size = 0x200,
 	.read = pccard_show_cis,
 	.write = pccard_store_cis,
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 1959cef..821933f 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -2,11 +2,9 @@
 # Plug and Play configuration
 #
 
-menu "Plug and Play support"
-	depends on HAS_IOMEM
-
-config PNP
+menuconfig PNP
 	bool "Plug and Play support"
+	depends on HAS_IOMEM
 	depends on ISA || ACPI
 	---help---
 	  Plug and Play (PnP) is a standard for peripherals which allows those
@@ -22,15 +20,15 @@
 
 	  If unsure, say Y.
 
+if PNP
+
 config PNP_DEBUG
 	bool "PnP Debug Messages"
-	depends on PNP
 	help
 	  Say Y if you want the Plug and Play Layer to print debug messages.
 	  This is useful if you are developing a PnP driver or troubleshooting.
 
 comment "Protocols"
-	depends on PNP
 
 source "drivers/pnp/isapnp/Kconfig"
 
@@ -38,5 +36,4 @@
 
 source "drivers/pnp/pnpacpi/Kconfig"
 
-endmenu
-
+endif # PNP
diff --git a/drivers/pnp/isapnp/Kconfig b/drivers/pnp/isapnp/Kconfig
index 578651e..f1ef366 100644
--- a/drivers/pnp/isapnp/Kconfig
+++ b/drivers/pnp/isapnp/Kconfig
@@ -3,7 +3,7 @@
 #
 config ISAPNP
 	bool "ISA Plug and Play support"
-	depends on PNP && ISA
+	depends on ISA
 	help
 	  Say Y here if you would like support for ISA Plug and Play devices.
 	  Some information is in <file:Documentation/isapnp.txt>.
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index a0b1587..914d00c 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -370,8 +370,6 @@
 #if 0
 	printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
 #endif
-	if (type == 0)				/* wrong type */
-		return -1;
 	if (*type == 0xff && *size == 0xffff)	/* probably invalid data */
 		return -1;
 	return 0;
diff --git a/drivers/pnp/pnpbios/Kconfig b/drivers/pnp/pnpbios/Kconfig
index fab848c..b986d9f 100644
--- a/drivers/pnp/pnpbios/Kconfig
+++ b/drivers/pnp/pnpbios/Kconfig
@@ -3,7 +3,7 @@
 #
 config PNPBIOS
 	bool "Plug and Play BIOS support (EXPERIMENTAL)"
-	depends on PNP && ISA && X86 && EXPERIMENTAL
+	depends on ISA && X86 && EXPERIMENTAL
 	default n
 	---help---
 	  Linux uses the PNPBIOS as defined in "Plug and Play BIOS
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 3a201b7..03baf1c 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -160,6 +160,7 @@
 {
 	static struct pnp_docking_station_info now;
 	int docked = -1, d = 0;
+	set_freezable();
 	while (!unloading)
 	{
 		int status;
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 277df50..7c32366 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -107,31 +107,106 @@
 	return;
 }
 
+static int quirk_smc_fir_enabled(struct pnp_dev *dev)
+{
+	unsigned long firbase;
+	u8 bank, high, low, chip;
+
+	if (!pnp_port_valid(dev, 1))
+		return 0;
+
+	firbase = pnp_port_start(dev, 1);
+
+	/* Select register bank 3 */
+	bank = inb(firbase + 7);
+	bank &= 0xf0;
+	bank |= 3;
+	outb(bank, firbase + 7);
+
+	high = inb(firbase + 0);
+	low  = inb(firbase + 1);
+	chip = inb(firbase + 2);
+
+	/* This corresponds to the check in smsc_ircc_present() */
+	if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2))
+		return 1;
+
+	return 0;
+}
+
 static void quirk_smc_enable(struct pnp_dev *dev)
 {
-	unsigned int firbase;
+	struct resource fir, sir, irq;
 
-	if (!dev->active || !pnp_port_valid(dev, 1))
+	pnp_activate_dev(dev);
+	if (quirk_smc_fir_enabled(dev))
 		return;
 
 	/*
-	 * On the HP/Compaq nw8240 (and probably other similar machines),
-	 * there is an SMCF010 device with two I/O port regions:
+	 * Sometimes the BIOS claims the device is enabled, but it reports
+	 * the wrong FIR resources or doesn't properly configure ISA or LPC
+	 * bridges on the way to the device.
 	 *
-	 *	0x3e8-0x3ef SIR
-	 *	0x100-0x10f FIR
-	 *
-	 * _STA reports the device is enabled, but in fact, the BIOS
-	 * neglects to enable the FIR range.  Fortunately, it does fully
-	 * enable the device if we call _SRS.
+	 * HP nc6000 and nc8000/nw8000 laptops have known problems like
+	 * this.  Fortunately, they do fix things up if we auto-configure
+	 * the device using its _PRS and _SRS methods.
 	 */
-	firbase = pnp_port_start(dev, 1);
-	if (inb(firbase + 0x7 /* IRCC_MASTER */) == 0xff) {
-		pnp_err("%s (%s) enabled but not responding, disabling and "
-			"re-enabling", dev->dev.bus_id, pnp_dev_name(dev));
-		pnp_disable_dev(dev);
-		pnp_activate_dev(dev);
+	dev_err(&dev->dev, "%s not responding at SIR 0x%lx, FIR 0x%lx; "
+		"auto-configuring\n", dev->id->id,
+		(unsigned long) pnp_port_start(dev, 0),
+		(unsigned long) pnp_port_start(dev, 1));
+
+	pnp_disable_dev(dev);
+	pnp_init_resource_table(&dev->res);
+	pnp_auto_config_dev(dev);
+	pnp_activate_dev(dev);
+	if (quirk_smc_fir_enabled(dev)) {
+		dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n",
+			(unsigned long) pnp_port_start(dev, 0),
+			(unsigned long) pnp_port_start(dev, 1));
+		return;
 	}
+
+	/*
+	 * The Toshiba Portege 4000 _CRS reports the FIR region first,
+	 * followed by the SIR region.  The BIOS will configure the bridge,
+	 * but only if we call _SRS with SIR first, then FIR.  It also
+	 * reports the IRQ as active high, when it is really active low.
+	 */
+	dev_err(&dev->dev, "not responding at SIR 0x%lx, FIR 0x%lx; "
+		"swapping SIR/FIR and reconfiguring\n",
+		(unsigned long) pnp_port_start(dev, 0),
+		(unsigned long) pnp_port_start(dev, 1));
+
+	/*
+	 * Clear IORESOURCE_AUTO so pnp_activate_dev() doesn't reassign
+	 * these resources any more.
+	 */
+	fir = dev->res.port_resource[0];
+	sir = dev->res.port_resource[1];
+	fir.flags &= ~IORESOURCE_AUTO;
+	sir.flags &= ~IORESOURCE_AUTO;
+
+	irq = dev->res.irq_resource[0];
+	irq.flags &= ~IORESOURCE_AUTO;
+	irq.flags &= ~IORESOURCE_BITS;
+	irq.flags |= IORESOURCE_IRQ_LOWEDGE;
+
+	pnp_disable_dev(dev);
+	dev->res.port_resource[0] = sir;
+	dev->res.port_resource[1] = fir;
+	dev->res.irq_resource[0] = irq;
+	pnp_activate_dev(dev);
+
+	if (quirk_smc_fir_enabled(dev)) {
+		dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n",
+			(unsigned long) pnp_port_start(dev, 0),
+			(unsigned long) pnp_port_start(dev, 1));
+		return;
+	}
+
+	dev_err(&dev->dev, "giving up; try \"smsc-ircc2.nopnp\" and "
+		"email bjorn.helgaas@hp.com\n");
 }
 
 
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
new file mode 100644
index 0000000..3f6e176
--- /dev/null
+++ b/drivers/power/Kconfig
@@ -0,0 +1,52 @@
+menuconfig POWER_SUPPLY
+	tristate "Power supply class support"
+	help
+	  Say Y here to enable power supply class support. This allows
+	  power supply (batteries, AC, USB) monitoring by userspace
+	  via sysfs and uevent (if available) and/or APM kernel interface
+	  (if selected below).
+
+if POWER_SUPPLY
+
+config POWER_SUPPLY_DEBUG
+	bool "Power supply debug"
+	help
+	  Say Y here to enable debugging messages for power supply class
+	  and drivers.
+
+config PDA_POWER
+	tristate "Generic PDA/phone power driver"
+	depends on !S390
+	help
+	  Say Y here to enable generic power driver for PDAs and phones with
+	  one or two external power supplies (AC/USB) connected to main and
+	  backup batteries, and optional builtin charger.
+
+config APM_POWER
+	tristate "APM emulation for class batteries"
+	depends on APM_EMULATION
+	help
+	  Say Y here to enable support APM status emulation using
+	  battery class devices.
+
+config BATTERY_DS2760
+	tristate "DS2760 battery driver (HP iPAQ & others)"
+	select W1
+	select W1_SLAVE_DS2760
+	help
+	  Say Y here to enable support for batteries with ds2760 chip.
+
+config BATTERY_PMU
+	tristate "Apple PMU battery"
+	depends on ADB_PMU
+	help
+	  Say Y here to expose battery information on Apple machines
+	  through the generic battery class.
+
+config BATTERY_OLPC
+	tristate "One Laptop Per Child battery"
+	depends on X86_32 && OLPC
+	help
+	  Say Y to enable support for the battery on the OLPC laptop.
+
+endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
new file mode 100644
index 0000000..6413ded
--- /dev/null
+++ b/drivers/power/Makefile
@@ -0,0 +1,22 @@
+power_supply-objs := power_supply_core.o
+
+ifeq ($(CONFIG_SYSFS),y)
+power_supply-objs += power_supply_sysfs.o
+endif
+
+ifeq ($(CONFIG_LEDS_TRIGGERS),y)
+power_supply-objs += power_supply_leds.o
+endif
+
+ifeq ($(CONFIG_POWER_SUPPLY_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_POWER_SUPPLY)	+= power_supply.o
+
+obj-$(CONFIG_PDA_POWER)		+= pda_power.o
+obj-$(CONFIG_APM_POWER)		+= apm_power.o
+
+obj-$(CONFIG_BATTERY_DS2760)	+= ds2760_battery.o
+obj-$(CONFIG_BATTERY_PMU)	+= pmu_battery.o
+obj-$(CONFIG_BATTERY_OLPC)	+= olpc_battery.o
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
new file mode 100644
index 0000000..39a90a6
--- /dev/null
+++ b/drivers/power/apm_power.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2007 Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Author: Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ */
+
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/apm-emulation.h>
+
+#define PSY_PROP(psy, prop, val) psy->get_property(psy, \
+			 POWER_SUPPLY_PROP_##prop, val)
+
+#define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \
+							 prop, val)
+
+#define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
+
+static struct power_supply *main_battery;
+
+static void find_main_battery(void)
+{
+	struct device *dev;
+	struct power_supply *bat, *batm;
+	union power_supply_propval full;
+	int max_charge = 0;
+
+	main_battery = NULL;
+	batm = NULL;
+	list_for_each_entry(dev, &power_supply_class->devices, node) {
+		bat = dev_get_drvdata(dev);
+		/* If none of battery devices cantains 'use_for_apm' flag,
+		   choice one with maximum design charge */
+		if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full)) {
+			if (full.intval > max_charge) {
+				batm = bat;
+				max_charge = full.intval;
+			}
+		}
+
+		if (bat->use_for_apm)
+			main_battery = bat;
+	}
+	if (!main_battery)
+		main_battery = batm;
+}
+
+static int calculate_time(int status)
+{
+	union power_supply_propval charge_full, charge_empty;
+	union power_supply_propval charge, I;
+
+	if (MPSY_PROP(CHARGE_FULL, &charge_full)) {
+		/* if battery can't report this property, use design value */
+		if (MPSY_PROP(CHARGE_FULL_DESIGN, &charge_full))
+			return -1;
+	}
+
+	if (MPSY_PROP(CHARGE_EMPTY, &charge_empty)) {
+		/* if battery can't report this property, use design value */
+		if (MPSY_PROP(CHARGE_EMPTY_DESIGN, &charge_empty))
+			charge_empty.intval = 0;
+	}
+
+	if (MPSY_PROP(CHARGE_AVG, &charge)) {
+		/* if battery can't report average value, use momentary */
+		if (MPSY_PROP(CHARGE_NOW, &charge))
+			return -1;
+	}
+
+	if (MPSY_PROP(CURRENT_AVG, &I)) {
+		/* if battery can't report average value, use momentary */
+		if (MPSY_PROP(CURRENT_NOW, &I))
+			return -1;
+	}
+
+	if (status == POWER_SUPPLY_STATUS_CHARGING)
+		return ((charge.intval - charge_full.intval) * 60L) /
+		       I.intval;
+	else
+		return -((charge.intval - charge_empty.intval) * 60L) /
+			I.intval;
+}
+
+static int calculate_capacity(int using_charge)
+{
+	enum power_supply_property full_prop, empty_prop;
+	enum power_supply_property full_design_prop, empty_design_prop;
+	enum power_supply_property now_prop, avg_prop;
+	union power_supply_propval empty, full, cur;
+	int ret;
+
+	if (using_charge) {
+		full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
+		empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+		full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
+		empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
+		now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
+		avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
+	} else {
+		full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
+		empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
+		full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
+		empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
+		now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
+		avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+	}
+
+	if (_MPSY_PROP(full_prop, &full)) {
+		/* if battery can't report this property, use design value */
+		if (_MPSY_PROP(full_design_prop, &full))
+			return -1;
+	}
+
+	if (_MPSY_PROP(avg_prop, &cur)) {
+		/* if battery can't report average value, use momentary */
+		if (_MPSY_PROP(now_prop, &cur))
+			return -1;
+	}
+
+	if (_MPSY_PROP(empty_prop, &empty)) {
+		/* if battery can't report this property, use design value */
+		if (_MPSY_PROP(empty_design_prop, &empty))
+			empty.intval = 0;
+	}
+
+	if (full.intval - empty.intval)
+		ret =  ((cur.intval - empty.intval) * 100L) /
+		       (full.intval - empty.intval);
+	else
+		return -1;
+
+	if (ret > 100)
+		return 100;
+	else if (ret < 0)
+		return 0;
+
+	return ret;
+}
+
+static void apm_battery_apm_get_power_status(struct apm_power_info *info)
+{
+	union power_supply_propval status;
+	union power_supply_propval capacity, time_to_full, time_to_empty;
+
+	down(&power_supply_class->sem);
+	find_main_battery();
+	if (!main_battery) {
+		up(&power_supply_class->sem);
+		return;
+	}
+
+	/* status */
+
+	if (MPSY_PROP(STATUS, &status))
+		status.intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+	/* ac line status */
+
+	if ((status.intval == POWER_SUPPLY_STATUS_CHARGING) ||
+	    (status.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) ||
+	    (status.intval == POWER_SUPPLY_STATUS_FULL))
+		info->ac_line_status = APM_AC_ONLINE;
+	else
+		info->ac_line_status = APM_AC_OFFLINE;
+
+	/* battery life (i.e. capacity, in percents) */
+
+	if (MPSY_PROP(CAPACITY, &capacity) == 0) {
+		info->battery_life = capacity.intval;
+	} else {
+		/* try calculate using energy */
+		info->battery_life = calculate_capacity(0);
+		/* if failed try calculate using charge instead */
+		if (info->battery_life == -1)
+			info->battery_life = calculate_capacity(1);
+	}
+
+	/* charging status */
+
+	if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+		info->battery_status = APM_BATTERY_STATUS_CHARGING;
+	} else {
+		if (info->battery_life > 50)
+			info->battery_status = APM_BATTERY_STATUS_HIGH;
+		else if (info->battery_life > 5)
+			info->battery_status = APM_BATTERY_STATUS_LOW;
+		else
+			info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+	}
+	info->battery_flag = info->battery_status;
+
+	/* time */
+
+	info->units = APM_UNITS_MINS;
+
+	if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+		if (MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full)) {
+			if (MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
+				info->time = calculate_time(status.intval);
+			else
+				info->time = time_to_full.intval / 60;
+		}
+	} else {
+		if (MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty)) {
+			if (MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
+				info->time = calculate_time(status.intval);
+			else
+				info->time = time_to_empty.intval / 60;
+		}
+	}
+
+	up(&power_supply_class->sem);
+}
+
+static int __init apm_battery_init(void)
+{
+	printk(KERN_INFO "APM Battery Driver\n");
+
+	apm_get_power_status = apm_battery_apm_get_power_status;
+	return 0;
+}
+
+static void __exit apm_battery_exit(void)
+{
+	apm_get_power_status = NULL;
+}
+
+module_init(apm_battery_init);
+module_exit(apm_battery_exit);
+
+MODULE_AUTHOR("Eugeny Boger <eugenyboger@dgap.mipt.ru>");
+MODULE_DESCRIPTION("APM emulation driver for battery monitoring class");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
new file mode 100644
index 0000000..be7021e
--- /dev/null
+++ b/drivers/power/ds2760_battery.c
@@ -0,0 +1,463 @@
+/*
+ * Driver for batteries with DS2760 chips inside.
+ *
+ * Copyright © 2007 Anton Vorontsov
+ *	       2004-2007 Matt Reimer
+ *	       2004 Szabolcs Gyurko
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * Author:  Anton Vorontsov <cbou@mail.ru>
+ *	    February 2007
+ *
+ *	    Matt Reimer <mreimer@vpop.net>
+ *	    April 2004, 2005, 2007
+ *
+ *	    Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *	    September 2004
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include "../w1/w1.h"
+#include "../w1/slaves/w1_ds2760.h"
+
+struct ds2760_device_info {
+	struct device *dev;
+
+	/* DS2760 data, valid after calling ds2760_battery_read_status() */
+	unsigned long update_time;	/* jiffies when data read */
+	char raw[DS2760_DATA_SIZE];	/* raw DS2760 data */
+	int voltage_raw;		/* units of 4.88 mV */
+	int voltage_uV;			/* units of µV */
+	int current_raw;		/* units of 0.625 mA */
+	int current_uA;			/* units of µA */
+	int accum_current_raw;		/* units of 0.25 mAh */
+	int accum_current_uAh;		/* units of µAh */
+	int temp_raw;			/* units of 0.125 °C */
+	int temp_C;			/* units of 0.1 °C */
+	int rated_capacity;		/* units of µAh */
+	int rem_capacity;		/* percentage */
+	int full_active_uAh;		/* units of µAh */
+	int empty_uAh;			/* units of µAh */
+	int life_sec;			/* units of seconds */
+	int charge_status;		/* POWER_SUPPLY_STATUS_* */
+
+	int full_counter;
+	struct power_supply bat;
+	struct device *w1_dev;
+	struct workqueue_struct *monitor_wqueue;
+	struct delayed_work monitor_work;
+};
+
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+
+/* Some batteries have their rated capacity stored a N * 10 mAh, while
+ * others use an index into this table. */
+static int rated_capacities[] = {
+	0,
+	920,	/* Samsung */
+	920,	/* BYD */
+	920,	/* Lishen */
+	920,	/* NEC */
+	1440,	/* Samsung */
+	1440,	/* BYD */
+	1440,	/* Lishen */
+	1440,	/* NEC */
+	2880,	/* Samsung */
+	2880,	/* BYD */
+	2880,	/* Lishen */
+	2880	/* NEC */
+};
+
+/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C
+ * temp is in Celsius */
+static int battery_interpolate(int array[], int temp)
+{
+	int index, dt;
+
+	if (temp <= 0)
+		return array[0];
+	if (temp >= 40)
+		return array[4];
+
+	index = temp / 10;
+	dt    = temp % 10;
+
+	return array[index] + (((array[index + 1] - array[index]) * dt) / 10);
+}
+
+static int ds2760_battery_read_status(struct ds2760_device_info *di)
+{
+	int ret, i, start, count, scale[5];
+
+	if (di->update_time && time_before(jiffies, di->update_time +
+					   msecs_to_jiffies(cache_time)))
+		return 0;
+
+	/* The first time we read the entire contents of SRAM/EEPROM,
+	 * but after that we just read the interesting bits that change. */
+	if (di->update_time == 0) {
+		start = 0;
+		count = DS2760_DATA_SIZE;
+	} else {
+		start = DS2760_VOLTAGE_MSB;
+		count = DS2760_TEMP_LSB - start + 1;
+	}
+
+	ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);
+	if (ret != count) {
+		dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",
+			 di->w1_dev);
+		return 1;
+	}
+
+	di->update_time = jiffies;
+
+	/* DS2760 reports voltage in units of 4.88mV, but the battery class
+	 * reports in units of uV, so convert by multiplying by 4880. */
+	di->voltage_raw = (di->raw[DS2760_VOLTAGE_MSB] << 3) |
+			  (di->raw[DS2760_VOLTAGE_LSB] >> 5);
+	di->voltage_uV = di->voltage_raw * 4880;
+
+	/* DS2760 reports current in signed units of 0.625mA, but the battery
+	 * class reports in units of µA, so convert by multiplying by 625. */
+	di->current_raw =
+	    (((signed char)di->raw[DS2760_CURRENT_MSB]) << 5) |
+			  (di->raw[DS2760_CURRENT_LSB] >> 3);
+	di->current_uA = di->current_raw * 625;
+
+	/* DS2760 reports accumulated current in signed units of 0.25mAh. */
+	di->accum_current_raw =
+	    (((signed char)di->raw[DS2760_CURRENT_ACCUM_MSB]) << 8) |
+			   di->raw[DS2760_CURRENT_ACCUM_LSB];
+	di->accum_current_uAh = di->accum_current_raw * 250;
+
+	/* DS2760 reports temperature in signed units of 0.125°C, but the
+	 * battery class reports in units of 1/10 °C, so we convert by
+	 * multiplying by .125 * 10 = 1.25. */
+	di->temp_raw = (((signed char)di->raw[DS2760_TEMP_MSB]) << 3) |
+				     (di->raw[DS2760_TEMP_LSB] >> 5);
+	di->temp_C = di->temp_raw + (di->temp_raw / 4);
+
+	/* At least some battery monitors (e.g. HP iPAQ) store the battery's
+	 * maximum rated capacity. */
+	if (di->raw[DS2760_RATED_CAPACITY] < ARRAY_SIZE(rated_capacities))
+		di->rated_capacity = rated_capacities[
+			(unsigned int)di->raw[DS2760_RATED_CAPACITY]];
+	else
+		di->rated_capacity = di->raw[DS2760_RATED_CAPACITY] * 10;
+
+	di->rated_capacity *= 1000; /* convert to µAh */
+
+	/* Calculate the full level at the present temperature. */
+	di->full_active_uAh = di->raw[DS2760_ACTIVE_FULL] << 8 |
+			      di->raw[DS2760_ACTIVE_FULL + 1];
+
+	scale[0] = di->raw[DS2760_ACTIVE_FULL] << 8 |
+		   di->raw[DS2760_ACTIVE_FULL + 1];
+	for (i = 1; i < 5; i++)
+		scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];
+
+	di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10);
+	di->full_active_uAh *= 1000; /* convert to µAh */
+
+	/* Calculate the empty level at the present temperature. */
+	scale[4] = di->raw[DS2760_ACTIVE_EMPTY + 4];
+	for (i = 3; i >= 0; i--)
+		scale[i] = scale[i + 1] + di->raw[DS2760_ACTIVE_EMPTY + i];
+
+	di->empty_uAh = battery_interpolate(scale, di->temp_C / 10);
+	di->empty_uAh *= 1000; /* convert to µAh */
+
+	/* From Maxim Application Note 131: remaining capacity =
+	 * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */
+	di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /
+			    (di->full_active_uAh - di->empty_uAh);
+
+	if (di->rem_capacity < 0)
+		di->rem_capacity = 0;
+	if (di->rem_capacity > 100)
+		di->rem_capacity = 100;
+
+	if (di->current_uA)
+		di->life_sec = -((di->accum_current_uAh - di->empty_uAh) *
+				 3600L) / di->current_uA;
+	else
+		di->life_sec = 0;
+
+	return 0;
+}
+
+static void ds2760_battery_update_status(struct ds2760_device_info *di)
+{
+	int old_charge_status = di->charge_status;
+
+	ds2760_battery_read_status(di);
+
+	if (di->charge_status == POWER_SUPPLY_STATUS_UNKNOWN)
+		di->full_counter = 0;
+
+	if (power_supply_am_i_supplied(&di->bat)) {
+		if (di->current_uA > 10000) {
+			di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+			di->full_counter = 0;
+		} else if (di->current_uA < -5000) {
+			if (di->charge_status != POWER_SUPPLY_STATUS_NOT_CHARGING)
+				dev_notice(di->dev, "not enough power to "
+					   "charge\n");
+			di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+			di->full_counter = 0;
+		} else if (di->current_uA < 10000 &&
+			    di->charge_status != POWER_SUPPLY_STATUS_FULL) {
+
+			/* Don't consider the battery to be full unless
+			 * we've seen the current < 10 mA at least two
+			 * consecutive times. */
+
+			di->full_counter++;
+
+			if (di->full_counter < 2) {
+				di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+			} else {
+				unsigned char acr[2];
+				int acr_val;
+
+				/* acr is in units of 0.25 mAh */
+				acr_val = di->full_active_uAh * 4L / 1000;
+
+				acr[0] = acr_val >> 8;
+				acr[1] = acr_val & 0xff;
+
+				if (w1_ds2760_write(di->w1_dev, acr,
+				    DS2760_CURRENT_ACCUM_MSB, 2) < 2)
+					dev_warn(di->dev,
+						 "ACR reset failed\n");
+
+				di->charge_status = POWER_SUPPLY_STATUS_FULL;
+			}
+		}
+	} else {
+		di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
+		di->full_counter = 0;
+	}
+
+	if (di->charge_status != old_charge_status)
+		power_supply_changed(&di->bat);
+}
+
+static void ds2760_battery_work(struct work_struct *work)
+{
+	struct ds2760_device_info *di = container_of(work,
+		struct ds2760_device_info, monitor_work.work);
+	const int interval = HZ * 60;
+
+	dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+	ds2760_battery_update_status(di);
+	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
+}
+
+#define to_ds2760_device_info(x) container_of((x), struct ds2760_device_info, \
+					      bat);
+
+static void ds2760_battery_external_power_changed(struct power_supply *psy)
+{
+	struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+	dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+	cancel_delayed_work(&di->monitor_work);
+	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
+}
+
+static int ds2760_battery_get_property(struct power_supply *psy,
+				       enum power_supply_property psp,
+				       union power_supply_propval *val)
+{
+	struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		val->intval = di->charge_status;
+		return 0;
+	default:
+		break;
+	}
+
+	ds2760_battery_read_status(di);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		val->intval = di->voltage_uV;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		val->intval = di->current_uA;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		val->intval = di->rated_capacity;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = di->full_active_uAh;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_EMPTY:
+		val->intval = di->empty_uAh;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		val->intval = di->accum_current_uAh;
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		val->intval = di->temp_C;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property ds2760_battery_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_EMPTY,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_TEMP,
+};
+
+static int ds2760_battery_probe(struct platform_device *pdev)
+{
+	int retval = 0;
+	struct ds2760_device_info *di;
+	struct ds2760_platform_data *pdata;
+
+	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	if (!di) {
+		retval = -ENOMEM;
+		goto di_alloc_failed;
+	}
+
+	platform_set_drvdata(pdev, di);
+
+	pdata = pdev->dev.platform_data;
+	di->dev		= &pdev->dev;
+	di->w1_dev	     = pdev->dev.parent;
+	di->bat.name	   = pdev->dev.bus_id;
+	di->bat.type	   = POWER_SUPPLY_TYPE_BATTERY;
+	di->bat.properties     = ds2760_battery_props;
+	di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
+	di->bat.get_property   = ds2760_battery_get_property;
+	di->bat.external_power_changed =
+				  ds2760_battery_external_power_changed;
+
+	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+	retval = power_supply_register(&pdev->dev, &di->bat);
+	if (retval) {
+		dev_err(di->dev, "failed to register battery");
+		goto batt_failed;
+	}
+
+	INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
+	di->monitor_wqueue = create_singlethread_workqueue(pdev->dev.bus_id);
+	if (!di->monitor_wqueue) {
+		retval = -ESRCH;
+		goto workqueue_failed;
+	}
+	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
+
+	goto success;
+
+workqueue_failed:
+	power_supply_unregister(&di->bat);
+batt_failed:
+	kfree(di);
+di_alloc_failed:
+success:
+	return retval;
+}
+
+static int ds2760_battery_remove(struct platform_device *pdev)
+{
+	struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+	cancel_rearming_delayed_workqueue(di->monitor_wqueue,
+					  &di->monitor_work);
+	destroy_workqueue(di->monitor_wqueue);
+	power_supply_unregister(&di->bat);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ds2760_battery_suspend(struct platform_device *pdev,
+				  pm_message_t state)
+{
+	struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+	return 0;
+}
+
+static int ds2760_battery_resume(struct platform_device *pdev)
+{
+	struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+	power_supply_changed(&di->bat);
+
+	cancel_delayed_work(&di->monitor_work);
+	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
+
+	return 0;
+}
+
+#else
+
+#define ds2760_battery_suspend NULL
+#define ds2760_battery_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct platform_driver ds2760_battery_driver = {
+	.driver = {
+		.name = "ds2760-battery",
+	},
+	.probe	  = ds2760_battery_probe,
+	.remove   = ds2760_battery_remove,
+	.suspend  = ds2760_battery_suspend,
+	.resume	  = ds2760_battery_resume,
+};
+
+static int __init ds2760_battery_init(void)
+{
+	return platform_driver_register(&ds2760_battery_driver);
+}
+
+static void __exit ds2760_battery_exit(void)
+{
+	platform_driver_unregister(&ds2760_battery_driver);
+}
+
+module_init(ds2760_battery_init);
+module_exit(ds2760_battery_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
+	      "Matt Reimer <mreimer@vpop.net>, "
+	      "Anton Vorontsov <cbou@mail.ru>");
+MODULE_DESCRIPTION("ds2760 battery driver");
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
new file mode 100644
index 0000000..c998e68
--- /dev/null
+++ b/drivers/power/olpc_battery.c
@@ -0,0 +1,351 @@
+/*
+ * Battery driver for One Laptop Per Child board.
+ *
+ *	Copyright © 2006  David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <asm/olpc.h>
+
+
+#define EC_BAT_VOLTAGE	0x10	/* uint16_t,	*9.76/32,    mV   */
+#define EC_BAT_CURRENT	0x11	/* int16_t,	*15.625/120, mA   */
+#define EC_BAT_ACR	0x12
+#define EC_BAT_TEMP	0x13	/* uint16_t,	*100/256,   °C  */
+#define EC_AMB_TEMP	0x14	/* uint16_t,	*100/256,   °C  */
+#define EC_BAT_STATUS	0x15	/* uint8_t,	bitmask */
+#define EC_BAT_SOC	0x16	/* uint8_t,	percentage */
+#define EC_BAT_SERIAL	0x17	/* uint8_t[6] */
+#define EC_BAT_EEPROM	0x18	/* uint8_t adr as input, uint8_t output */
+#define EC_BAT_ERRCODE	0x1f	/* uint8_t,	bitmask */
+
+#define BAT_STAT_PRESENT	0x01
+#define BAT_STAT_FULL		0x02
+#define BAT_STAT_LOW		0x04
+#define BAT_STAT_DESTROY	0x08
+#define BAT_STAT_AC		0x10
+#define BAT_STAT_CHARGING	0x20
+#define BAT_STAT_DISCHARGING	0x40
+
+#define BAT_ERR_INFOFAIL	0x02
+#define BAT_ERR_OVERVOLTAGE	0x04
+#define BAT_ERR_OVERTEMP	0x05
+#define BAT_ERR_GAUGESTOP	0x06
+#define BAT_ERR_OUT_OF_CONTROL	0x07
+#define BAT_ERR_ID_FAIL		0x09
+#define BAT_ERR_ACR_FAIL	0x10
+
+#define BAT_ADDR_MFR_TYPE	0x5F
+
+/*********************************************************************
+ *		Power
+ *********************************************************************/
+
+static int olpc_ac_get_prop(struct power_supply *psy,
+			    enum power_supply_property psp,
+			    union power_supply_propval *val)
+{
+	int ret = 0;
+	uint8_t status;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+		if (ret)
+			return ret;
+
+		val->intval = !!(status & BAT_STAT_AC);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static enum power_supply_property olpc_ac_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply olpc_ac = {
+	.name = "olpc-ac",
+	.type = POWER_SUPPLY_TYPE_MAINS,
+	.properties = olpc_ac_props,
+	.num_properties = ARRAY_SIZE(olpc_ac_props),
+	.get_property = olpc_ac_get_prop,
+};
+
+/*********************************************************************
+ *		Battery properties
+ *********************************************************************/
+static int olpc_bat_get_property(struct power_supply *psy,
+				 enum power_supply_property psp,
+				 union power_supply_propval *val)
+{
+	int ret = 0;
+	int16_t ec_word;
+	uint8_t ec_byte;
+
+	ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1);
+	if (ret)
+		return ret;
+
+	/* Theoretically there's a race here -- the battery could be
+	   removed immediately after we check whether it's present, and
+	   then we query for some other property of the now-absent battery.
+	   It doesn't matter though -- the EC will return the last-known
+	   information, and it's as if we just ran that _little_ bit faster
+	   and managed to read it out before the battery went away. */
+	if (!(ec_byte & BAT_STAT_PRESENT) && psp != POWER_SUPPLY_PROP_PRESENT)
+		return -ENODEV;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		if (olpc_platform_info.ecver > 0x44) {
+			if (ec_byte & BAT_STAT_CHARGING)
+				val->intval = POWER_SUPPLY_STATUS_CHARGING;
+			else if (ec_byte & BAT_STAT_DISCHARGING)
+				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+			else if (ec_byte & BAT_STAT_FULL)
+				val->intval = POWER_SUPPLY_STATUS_FULL;
+			else /* er,... */
+				val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		} else {
+			/* Older EC didn't report charge/discharge bits */
+			if (!(ec_byte & BAT_STAT_AC)) /* No AC means discharging */
+				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+			else if (ec_byte & BAT_STAT_FULL)
+				val->intval = POWER_SUPPLY_STATUS_FULL;
+			else /* Not _necessarily_ true but EC doesn't tell all yet */
+				val->intval = POWER_SUPPLY_STATUS_CHARGING;
+			break;
+		}
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = !!(ec_byte & BAT_STAT_PRESENT);
+		break;
+
+	case POWER_SUPPLY_PROP_HEALTH:
+		if (ec_byte & BAT_STAT_DESTROY)
+			val->intval = POWER_SUPPLY_HEALTH_DEAD;
+		else {
+			ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1);
+			if (ret)
+				return ret;
+
+			switch (ec_byte) {
+			case 0:
+				val->intval = POWER_SUPPLY_HEALTH_GOOD;
+				break;
+
+			case BAT_ERR_OVERTEMP:
+				val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+				break;
+
+			case BAT_ERR_OVERVOLTAGE:
+				val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+				break;
+
+			case BAT_ERR_INFOFAIL:
+			case BAT_ERR_OUT_OF_CONTROL:
+			case BAT_ERR_ID_FAIL:
+			case BAT_ERR_ACR_FAIL:
+				val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+				break;
+
+			default:
+				/* Eep. We don't know this failure code */
+				return -EIO;
+			}
+		}
+		break;
+
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		ec_byte = BAT_ADDR_MFR_TYPE;
+		ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+		if (ret)
+			return ret;
+
+		switch (ec_byte >> 4) {
+		case 1:
+			val->strval = "Gold Peak";
+			break;
+		case 2:
+			val->strval = "BYD";
+			break;
+		default:
+			val->strval = "Unknown";
+			break;
+		}
+		break;
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		ec_byte = BAT_ADDR_MFR_TYPE;
+		ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+		if (ret)
+			return ret;
+
+		switch (ec_byte & 0xf) {
+		case 1:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
+			break;
+		case 2:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe;
+			break;
+		default:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+			break;
+		}
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+		ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2);
+		if (ret)
+			return ret;
+
+		ec_word = be16_to_cpu(ec_word);
+		val->intval = ec_word * 9760L / 32;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_AVG:
+		ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
+		if (ret)
+			return ret;
+
+		ec_word = be16_to_cpu(ec_word);
+		val->intval = ec_word * 15625L / 120;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
+		if (ret)
+			return ret;
+		val->intval = ec_byte;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+		if (ec_byte & BAT_STAT_FULL)
+			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+		else if (ec_byte & BAT_STAT_LOW)
+			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+		else
+			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2);
+		if (ret)
+			return ret;
+		ec_word = be16_to_cpu(ec_word);
+		val->intval = ec_word * 100 / 256;
+		break;
+	case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+		ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
+		if (ret)
+			return ret;
+
+		ec_word = be16_to_cpu(ec_word);
+		val->intval = ec_word * 100 / 256;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static enum power_supply_property olpc_bat_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TEMP_AMBIENT,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+/*********************************************************************
+ *		Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static struct power_supply olpc_bat = {
+	.properties = olpc_bat_props,
+	.num_properties = ARRAY_SIZE(olpc_bat_props),
+	.get_property = olpc_bat_get_property,
+	.use_for_apm = 1,
+};
+
+void olpc_battery_trigger_uevent(unsigned long cause)
+{
+	if (cause & EC_SCI_SRC_ACPWR)
+		kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE);
+	if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY))
+		kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE);
+}
+
+static int __init olpc_bat_init(void)
+{
+	int ret = 0;
+	uint8_t status;
+
+	if (!olpc_platform_info.ecver)
+		return -ENXIO;
+	if (olpc_platform_info.ecver < 0x43) {
+		printk(KERN_NOTICE "OLPC EC version 0x%02x too old for battery driver.\n", olpc_platform_info.ecver);
+		return -ENXIO;
+	}
+
+	ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+	if (ret)
+		return ret;
+
+	/* Ignore the status. It doesn't actually matter */
+
+	bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0);
+	if (IS_ERR(bat_pdev))
+		return PTR_ERR(bat_pdev);
+
+	ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
+	if (ret)
+		goto ac_failed;
+
+	olpc_bat.name = bat_pdev->name;
+
+	ret = power_supply_register(&bat_pdev->dev, &olpc_bat);
+	if (ret)
+		goto battery_failed;
+
+	olpc_register_battery_callback(&olpc_battery_trigger_uevent);
+	goto success;
+
+battery_failed:
+	power_supply_unregister(&olpc_ac);
+ac_failed:
+	platform_device_unregister(bat_pdev);
+success:
+	return ret;
+}
+
+static void __exit olpc_bat_exit(void)
+{
+	olpc_deregister_battery_callback();
+	power_supply_unregister(&olpc_bat);
+	power_supply_unregister(&olpc_ac);
+	platform_device_unregister(bat_pdev);
+}
+
+module_init(olpc_bat_init);
+module_exit(olpc_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Battery driver for One Laptop Per Child 'XO' machine");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
new file mode 100644
index 0000000..c058f28
--- /dev/null
+++ b/drivers/power/pda_power.c
@@ -0,0 +1,255 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/power_supply.h>
+#include <linux/pda_power.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+
+static inline unsigned int get_irq_flags(struct resource *res)
+{
+	unsigned int flags = IRQF_DISABLED | IRQF_SHARED;
+
+	flags |= res->flags & IRQF_TRIGGER_MASK;
+
+	return flags;
+}
+
+static struct device *dev;
+static struct pda_power_pdata *pdata;
+static struct resource *ac_irq, *usb_irq;
+static struct timer_list charger_timer;
+static struct timer_list supply_timer;
+
+static int pda_power_get_property(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  union power_supply_propval *val)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		if (psy->type == POWER_SUPPLY_TYPE_MAINS)
+			val->intval = pdata->is_ac_online ?
+				      pdata->is_ac_online() : 0;
+		else
+			val->intval = pdata->is_usb_online ?
+				      pdata->is_usb_online() : 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static enum power_supply_property pda_power_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static char *pda_power_supplied_to[] = {
+	"main-battery",
+	"backup-battery",
+};
+
+static struct power_supply pda_power_supplies[] = {
+	{
+		.name = "ac",
+		.type = POWER_SUPPLY_TYPE_MAINS,
+		.supplied_to = pda_power_supplied_to,
+		.num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+		.properties = pda_power_props,
+		.num_properties = ARRAY_SIZE(pda_power_props),
+		.get_property = pda_power_get_property,
+	},
+	{
+		.name = "usb",
+		.type = POWER_SUPPLY_TYPE_USB,
+		.supplied_to = pda_power_supplied_to,
+		.num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+		.properties = pda_power_props,
+		.num_properties = ARRAY_SIZE(pda_power_props),
+		.get_property = pda_power_get_property,
+	},
+};
+
+static void update_charger(void)
+{
+	if (!pdata->set_charge)
+		return;
+
+	if (pdata->is_ac_online && pdata->is_ac_online()) {
+		dev_dbg(dev, "charger on (AC)\n");
+		pdata->set_charge(PDA_POWER_CHARGE_AC);
+	} else if (pdata->is_usb_online && pdata->is_usb_online()) {
+		dev_dbg(dev, "charger on (USB)\n");
+		pdata->set_charge(PDA_POWER_CHARGE_USB);
+	} else {
+		dev_dbg(dev, "charger off\n");
+		pdata->set_charge(0);
+	}
+}
+
+static void supply_timer_func(unsigned long power_supply_ptr)
+{
+	void *power_supply = (void *)power_supply_ptr;
+
+	power_supply_changed(power_supply);
+}
+
+static void charger_timer_func(unsigned long power_supply_ptr)
+{
+	update_charger();
+
+	/* Okay, charger set. Now wait a bit before notifying supplicants,
+	 * charge power should stabilize. */
+	supply_timer.data = power_supply_ptr;
+	mod_timer(&supply_timer,
+		  jiffies + msecs_to_jiffies(pdata->wait_for_charger));
+}
+
+static irqreturn_t power_changed_isr(int irq, void *power_supply)
+{
+	/* Wait a bit before reading ac/usb line status and setting charger,
+	 * because ac/usb status readings may lag from irq. */
+	charger_timer.data = (unsigned long)power_supply;
+	mod_timer(&charger_timer,
+		  jiffies + msecs_to_jiffies(pdata->wait_for_status));
+	return IRQ_HANDLED;
+}
+
+static int pda_power_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	dev = &pdev->dev;
+
+	if (pdev->id != -1) {
+		dev_err(dev, "it's meaningless to register several "
+			"pda_powers; use id = -1\n");
+		ret = -EINVAL;
+		goto wrongid;
+	}
+
+	pdata = pdev->dev.platform_data;
+
+	update_charger();
+
+	if (!pdata->wait_for_status)
+		pdata->wait_for_status = 500;
+
+	if (!pdata->wait_for_charger)
+		pdata->wait_for_charger = 500;
+
+	setup_timer(&charger_timer, charger_timer_func, 0);
+	setup_timer(&supply_timer, supply_timer_func, 0);
+
+	ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
+	usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
+	if (!ac_irq && !usb_irq) {
+		dev_err(dev, "no ac/usb irq specified\n");
+		ret = -ENODEV;
+		goto noirqs;
+	}
+
+	if (pdata->supplied_to) {
+		pda_power_supplies[0].supplied_to = pdata->supplied_to;
+		pda_power_supplies[1].supplied_to = pdata->supplied_to;
+		pda_power_supplies[0].num_supplicants = pdata->num_supplicants;
+		pda_power_supplies[1].num_supplicants = pdata->num_supplicants;
+	}
+
+	ret = power_supply_register(&pdev->dev, &pda_power_supplies[0]);
+	if (ret) {
+		dev_err(dev, "failed to register %s power supply\n",
+			pda_power_supplies[0].name);
+		goto supply0_failed;
+	}
+
+	ret = power_supply_register(&pdev->dev, &pda_power_supplies[1]);
+	if (ret) {
+		dev_err(dev, "failed to register %s power supply\n",
+			pda_power_supplies[1].name);
+		goto supply1_failed;
+	}
+
+	if (ac_irq) {
+		ret = request_irq(ac_irq->start, power_changed_isr,
+				  get_irq_flags(ac_irq), ac_irq->name,
+				  &pda_power_supplies[0]);
+		if (ret) {
+			dev_err(dev, "request ac irq failed\n");
+			goto ac_irq_failed;
+		}
+	}
+
+	if (usb_irq) {
+		ret = request_irq(usb_irq->start, power_changed_isr,
+				  get_irq_flags(usb_irq), usb_irq->name,
+				  &pda_power_supplies[1]);
+		if (ret) {
+			dev_err(dev, "request usb irq failed\n");
+			goto usb_irq_failed;
+		}
+	}
+
+	goto success;
+
+usb_irq_failed:
+	if (ac_irq)
+		free_irq(ac_irq->start, &pda_power_supplies[0]);
+ac_irq_failed:
+	power_supply_unregister(&pda_power_supplies[1]);
+supply1_failed:
+	power_supply_unregister(&pda_power_supplies[0]);
+supply0_failed:
+noirqs:
+wrongid:
+success:
+	return ret;
+}
+
+static int pda_power_remove(struct platform_device *pdev)
+{
+	if (usb_irq)
+		free_irq(usb_irq->start, &pda_power_supplies[1]);
+	if (ac_irq)
+		free_irq(ac_irq->start, &pda_power_supplies[0]);
+	del_timer_sync(&charger_timer);
+	del_timer_sync(&supply_timer);
+	power_supply_unregister(&pda_power_supplies[1]);
+	power_supply_unregister(&pda_power_supplies[0]);
+	return 0;
+}
+
+static struct platform_driver pda_power_pdrv = {
+	.driver = {
+		.name = "pda-power",
+	},
+	.probe = pda_power_probe,
+	.remove = pda_power_remove,
+};
+
+static int __init pda_power_init(void)
+{
+	return platform_driver_register(&pda_power_pdrv);
+}
+
+static void __exit pda_power_exit(void)
+{
+	platform_driver_unregister(&pda_power_pdrv);
+}
+
+module_init(pda_power_init);
+module_exit(pda_power_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c
new file mode 100644
index 0000000..60a8cf3
--- /dev/null
+++ b/drivers/power/pmu_battery.c
@@ -0,0 +1,213 @@
+/*
+ * Battery class driver for Apple PMU
+ *
+ *	Copyright © 2006  David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+static struct pmu_battery_dev {
+	struct power_supply bat;
+	struct pmu_battery_info *pbi;
+	char name[16];
+	int propval;
+} *pbats[PMU_MAX_BATTERIES];
+
+#define to_pmu_battery_dev(x) container_of(x, struct pmu_battery_dev, bat)
+
+/*********************************************************************
+ *		Power
+ *********************************************************************/
+
+static int pmu_get_ac_prop(struct power_supply *psy,
+			   enum power_supply_property psp,
+			   union power_supply_propval *val)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = (!!(pmu_power_flags & PMU_PWR_AC_PRESENT)) ||
+			      (pmu_battery_count == 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property pmu_ac_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply pmu_ac = {
+	.name = "pmu-ac",
+	.type = POWER_SUPPLY_TYPE_MAINS,
+	.properties = pmu_ac_props,
+	.num_properties = ARRAY_SIZE(pmu_ac_props),
+	.get_property = pmu_get_ac_prop,
+};
+
+/*********************************************************************
+ *		Battery properties
+ *********************************************************************/
+
+static char *pmu_batt_types[] = {
+	"Smart", "Comet", "Hooper", "Unknown"
+};
+
+static char *pmu_bat_get_model_name(struct pmu_battery_info *pbi)
+{
+	switch (pbi->flags & PMU_BATT_TYPE_MASK) {
+	case PMU_BATT_TYPE_SMART:
+		return pmu_batt_types[0];
+	case PMU_BATT_TYPE_COMET:
+		return pmu_batt_types[1];
+	case PMU_BATT_TYPE_HOOPER:
+		return pmu_batt_types[2];
+	default: break;
+	}
+	return pmu_batt_types[3];
+}
+
+static int pmu_bat_get_property(struct power_supply *psy,
+				enum power_supply_property psp,
+				union power_supply_propval *val)
+{
+	struct pmu_battery_dev *pbat = to_pmu_battery_dev(psy);
+	struct pmu_battery_info *pbi = pbat->pbi;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		if (pbi->flags & PMU_BATT_CHARGING)
+			val->intval = POWER_SUPPLY_STATUS_CHARGING;
+		else
+			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = !!(pbi->flags & PMU_BATT_PRESENT);
+		break;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = pmu_bat_get_model_name(pbi);
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_AVG:
+		val->intval = pbi->charge     * 1000; /* mWh -> µWh */
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_FULL:
+		val->intval = pbi->max_charge * 1000; /* mWh -> µWh */
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_AVG:
+		val->intval = pbi->amperage   * 1000; /* mA -> µA */
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+		val->intval = pbi->voltage    * 1000; /* mV -> µV */
+		break;
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+		val->intval = pbi->time_remaining;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property pmu_bat_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_ENERGY_AVG,
+	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+};
+
+/*********************************************************************
+ *		Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static int __init pmu_bat_init(void)
+{
+	int ret;
+	int i;
+
+	bat_pdev = platform_device_register_simple("pmu-battery",
+						   0, NULL, 0);
+	if (IS_ERR(bat_pdev)) {
+		ret = PTR_ERR(bat_pdev);
+		goto pdev_register_failed;
+	}
+
+	ret = power_supply_register(&bat_pdev->dev, &pmu_ac);
+	if (ret)
+		goto ac_register_failed;
+
+	for (i = 0; i < pmu_battery_count; i++) {
+		struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat),
+						       GFP_KERNEL);
+		if (!pbat)
+			break;
+
+		sprintf(pbat->name, "PMU battery %d", i);
+		pbat->bat.name = pbat->name;
+		pbat->bat.properties = pmu_bat_props;
+		pbat->bat.num_properties = ARRAY_SIZE(pmu_bat_props);
+		pbat->bat.get_property = pmu_bat_get_property;
+		pbat->pbi = &pmu_batteries[i];
+
+		ret = power_supply_register(&bat_pdev->dev, &pbat->bat);
+		if (ret) {
+			kfree(pbat);
+			goto battery_register_failed;
+		}
+		pbats[i] = pbat;
+	}
+
+	goto success;
+
+battery_register_failed:
+	while (i--) {
+		if (!pbats[i])
+			continue;
+		power_supply_unregister(&pbats[i]->bat);
+		kfree(pbats[i]);
+	}
+	power_supply_unregister(&pmu_ac);
+ac_register_failed:
+	platform_device_unregister(bat_pdev);
+pdev_register_failed:
+success:
+	return ret;
+}
+
+static void __exit pmu_bat_exit(void)
+{
+	int i;
+
+	for (i = 0; i < PMU_MAX_BATTERIES; i++) {
+		if (!pbats[i])
+			continue;
+		power_supply_unregister(&pbats[i]->bat);
+		kfree(pbats[i]);
+	}
+	power_supply_unregister(&pmu_ac);
+	platform_device_unregister(bat_pdev);
+}
+
+module_init(pmu_bat_init);
+module_exit(pmu_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PMU battery driver");
diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h
new file mode 100644
index 0000000..a9880d4
--- /dev/null
+++ b/drivers/power/power_supply.h
@@ -0,0 +1,42 @@
+/*
+ *  Functions private to power supply class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#ifdef CONFIG_SYSFS
+
+extern int power_supply_create_attrs(struct power_supply *psy);
+extern void power_supply_remove_attrs(struct power_supply *psy);
+extern int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+			       char *buffer, int buffer_size);
+
+#else
+
+static inline int power_supply_create_attrs(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_attrs(struct power_supply *psy) {}
+#define power_supply_uevent NULL
+
+#endif /* CONFIG_SYSFS */
+
+#ifdef CONFIG_LEDS_TRIGGERS
+
+extern void power_supply_update_leds(struct power_supply *psy);
+extern int power_supply_create_triggers(struct power_supply *psy);
+extern void power_supply_remove_triggers(struct power_supply *psy);
+
+#else
+
+static inline void power_supply_update_leds(struct power_supply *psy) {}
+static inline int power_supply_create_triggers(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_triggers(struct power_supply *psy) {}
+
+#endif /* CONFIG_LEDS_TRIGGERS */
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
new file mode 100644
index 0000000..a63b75c
--- /dev/null
+++ b/drivers/power/power_supply_core.c
@@ -0,0 +1,162 @@
+/*
+ *  Universal power supply monitor class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include "power_supply.h"
+
+struct class *power_supply_class;
+
+static void power_supply_changed_work(struct work_struct *work)
+{
+	struct power_supply *psy = container_of(work, struct power_supply,
+						changed_work);
+	int i;
+
+	dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+	for (i = 0; i < psy->num_supplicants; i++) {
+		struct device *dev;
+
+		down(&power_supply_class->sem);
+		list_for_each_entry(dev, &power_supply_class->devices, node) {
+			struct power_supply *pst = dev_get_drvdata(dev);
+
+			if (!strcmp(psy->supplied_to[i], pst->name)) {
+				if (pst->external_power_changed)
+					pst->external_power_changed(pst);
+			}
+		}
+		up(&power_supply_class->sem);
+	}
+
+	power_supply_update_leds(psy);
+
+	kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
+}
+
+void power_supply_changed(struct power_supply *psy)
+{
+	dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+	schedule_work(&psy->changed_work);
+}
+
+int power_supply_am_i_supplied(struct power_supply *psy)
+{
+	union power_supply_propval ret = {0,};
+	struct device *dev;
+
+	down(&power_supply_class->sem);
+	list_for_each_entry(dev, &power_supply_class->devices, node) {
+		struct power_supply *epsy = dev_get_drvdata(dev);
+		int i;
+
+		for (i = 0; i < epsy->num_supplicants; i++) {
+			if (!strcmp(epsy->supplied_to[i], psy->name)) {
+				if (epsy->get_property(epsy,
+					  POWER_SUPPLY_PROP_ONLINE, &ret))
+					continue;
+				if (ret.intval)
+					goto out;
+			}
+		}
+	}
+out:
+	up(&power_supply_class->sem);
+
+	dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, ret.intval);
+
+	return ret.intval;
+}
+
+int power_supply_register(struct device *parent, struct power_supply *psy)
+{
+	int rc = 0;
+
+	psy->dev = device_create(power_supply_class, parent, 0,
+				 "%s", psy->name);
+	if (IS_ERR(psy->dev)) {
+		rc = PTR_ERR(psy->dev);
+		goto dev_create_failed;
+	}
+
+	dev_set_drvdata(psy->dev, psy);
+
+	INIT_WORK(&psy->changed_work, power_supply_changed_work);
+
+	rc = power_supply_create_attrs(psy);
+	if (rc)
+		goto create_attrs_failed;
+
+	rc = power_supply_create_triggers(psy);
+	if (rc)
+		goto create_triggers_failed;
+
+	power_supply_changed(psy);
+
+	goto success;
+
+create_triggers_failed:
+	power_supply_remove_attrs(psy);
+create_attrs_failed:
+	device_unregister(psy->dev);
+dev_create_failed:
+success:
+	return rc;
+}
+
+void power_supply_unregister(struct power_supply *psy)
+{
+	flush_scheduled_work();
+	power_supply_remove_triggers(psy);
+	power_supply_remove_attrs(psy);
+	device_unregister(psy->dev);
+}
+
+static int __init power_supply_class_init(void)
+{
+	power_supply_class = class_create(THIS_MODULE, "power_supply");
+
+	if (IS_ERR(power_supply_class))
+		return PTR_ERR(power_supply_class);
+
+	power_supply_class->dev_uevent = power_supply_uevent;
+
+	return 0;
+}
+
+static void __exit power_supply_class_exit(void)
+{
+	class_destroy(power_supply_class);
+}
+
+EXPORT_SYMBOL_GPL(power_supply_changed);
+EXPORT_SYMBOL_GPL(power_supply_am_i_supplied);
+EXPORT_SYMBOL_GPL(power_supply_register);
+EXPORT_SYMBOL_GPL(power_supply_unregister);
+
+/* exported for the APM Power driver, APM emulation */
+EXPORT_SYMBOL_GPL(power_supply_class);
+
+subsys_initcall(power_supply_class_init);
+module_exit(power_supply_class_exit);
+
+MODULE_DESCRIPTION("Universal power supply monitor class");
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, "
+	      "Szabolcs Gyurko, "
+	      "Anton Vorontsov <cbou@mail.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c
new file mode 100644
index 0000000..7f8f359
--- /dev/null
+++ b/drivers/power/power_supply_leds.c
@@ -0,0 +1,168 @@
+/*
+ *  LEDs triggers for power supply class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/power_supply.h>
+
+/* Battery specific LEDs triggers. */
+
+static void power_supply_update_bat_leds(struct power_supply *psy)
+{
+	union power_supply_propval status;
+
+	if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
+		return;
+
+	dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, status.intval);
+
+	switch (status.intval) {
+	case POWER_SUPPLY_STATUS_FULL:
+		led_trigger_event(psy->charging_full_trig, LED_FULL);
+		led_trigger_event(psy->charging_trig, LED_OFF);
+		led_trigger_event(psy->full_trig, LED_FULL);
+		break;
+	case POWER_SUPPLY_STATUS_CHARGING:
+		led_trigger_event(psy->charging_full_trig, LED_FULL);
+		led_trigger_event(psy->charging_trig, LED_FULL);
+		led_trigger_event(psy->full_trig, LED_OFF);
+		break;
+	default:
+		led_trigger_event(psy->charging_full_trig, LED_OFF);
+		led_trigger_event(psy->charging_trig, LED_OFF);
+		led_trigger_event(psy->full_trig, LED_OFF);
+		break;
+	}
+}
+
+static int power_supply_create_bat_triggers(struct power_supply *psy)
+{
+	int rc = 0;
+
+	psy->charging_full_trig_name = kmalloc(strlen(psy->name) +
+				  sizeof("-charging-or-full"), GFP_KERNEL);
+	if (!psy->charging_full_trig_name)
+		goto charging_full_failed;
+
+	psy->charging_trig_name = kmalloc(strlen(psy->name) +
+					  sizeof("-charging"), GFP_KERNEL);
+	if (!psy->charging_trig_name)
+		goto charging_failed;
+
+	psy->full_trig_name = kmalloc(strlen(psy->name) +
+				      sizeof("-full"), GFP_KERNEL);
+	if (!psy->full_trig_name)
+		goto full_failed;
+
+	strcpy(psy->charging_full_trig_name, psy->name);
+	strcat(psy->charging_full_trig_name, "-charging-or-full");
+	strcpy(psy->charging_trig_name, psy->name);
+	strcat(psy->charging_trig_name, "-charging");
+	strcpy(psy->full_trig_name, psy->name);
+	strcat(psy->full_trig_name, "-full");
+
+	led_trigger_register_simple(psy->charging_full_trig_name,
+				    &psy->charging_full_trig);
+	led_trigger_register_simple(psy->charging_trig_name,
+				    &psy->charging_trig);
+	led_trigger_register_simple(psy->full_trig_name,
+				    &psy->full_trig);
+
+	goto success;
+
+full_failed:
+	kfree(psy->charging_trig_name);
+charging_failed:
+	kfree(psy->charging_full_trig_name);
+charging_full_failed:
+	rc = -ENOMEM;
+success:
+	return rc;
+}
+
+static void power_supply_remove_bat_triggers(struct power_supply *psy)
+{
+	led_trigger_unregister_simple(psy->charging_full_trig);
+	led_trigger_unregister_simple(psy->charging_trig);
+	led_trigger_unregister_simple(psy->full_trig);
+	kfree(psy->full_trig_name);
+	kfree(psy->charging_trig_name);
+	kfree(psy->charging_full_trig_name);
+}
+
+/* Generated power specific LEDs triggers. */
+
+static void power_supply_update_gen_leds(struct power_supply *psy)
+{
+	union power_supply_propval online;
+
+	if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
+		return;
+
+	dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, online.intval);
+
+	if (online.intval)
+		led_trigger_event(psy->online_trig, LED_FULL);
+	else
+		led_trigger_event(psy->online_trig, LED_OFF);
+}
+
+static int power_supply_create_gen_triggers(struct power_supply *psy)
+{
+	int rc = 0;
+
+	psy->online_trig_name = kmalloc(strlen(psy->name) + sizeof("-online"),
+					GFP_KERNEL);
+	if (!psy->online_trig_name)
+		goto online_failed;
+
+	strcpy(psy->online_trig_name, psy->name);
+	strcat(psy->online_trig_name, "-online");
+
+	led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
+
+	goto success;
+
+online_failed:
+	rc = -ENOMEM;
+success:
+	return rc;
+}
+
+static void power_supply_remove_gen_triggers(struct power_supply *psy)
+{
+	led_trigger_unregister_simple(psy->online_trig);
+	kfree(psy->online_trig_name);
+}
+
+/* Choice what triggers to create&update. */
+
+void power_supply_update_leds(struct power_supply *psy)
+{
+	if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+		power_supply_update_bat_leds(psy);
+	else
+		power_supply_update_gen_leds(psy);
+}
+
+int power_supply_create_triggers(struct power_supply *psy)
+{
+	if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+		return power_supply_create_bat_triggers(psy);
+	return power_supply_create_gen_triggers(psy);
+}
+
+void power_supply_remove_triggers(struct power_supply *psy)
+{
+	if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+		power_supply_remove_bat_triggers(psy);
+	else
+		power_supply_remove_gen_triggers(psy);
+}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
new file mode 100644
index 0000000..c7c4574
--- /dev/null
+++ b/drivers/power/power_supply_sysfs.c
@@ -0,0 +1,297 @@
+/*
+ *  Sysfs interface for the universal power supply monitor class
+ *
+ *  Copyright © 2007  David Woodhouse <dwmw2@infradead.org>
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/ctype.h>
+#include <linux/power_supply.h>
+
+/*
+ * This is because the name "current" breaks the device attr macro.
+ * The "current" word resolves to "(get_current())" so instead of
+ * "current" "(get_current())" appears in the sysfs.
+ *
+ * The source of this definition is the device.h which calls __ATTR
+ * macro in sysfs.h which calls the __stringify macro.
+ *
+ * Only modification that the name is not tried to be resolved
+ * (as a macro let's say).
+ */
+
+#define POWER_SUPPLY_ATTR(_name)					\
+{									\
+	.attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE },	\
+	.show = power_supply_show_property,				\
+	.store = NULL,							\
+}
+
+static struct device_attribute power_supply_attrs[];
+
+static ssize_t power_supply_show_property(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf) {
+	static char *status_text[] = {
+		"Unknown", "Charging", "Discharging", "Not charging", "Full"
+	};
+	static char *health_text[] = {
+		"Unknown", "Good", "Overheat", "Dead", "Over voltage",
+		"Unspecified failure"
+	};
+	static char *technology_text[] = {
+		"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd"
+	};
+	static char *capacity_level_text[] = {
+		"Unknown", "Critical", "Low", "Normal", "High", "Full"
+	};
+	ssize_t ret;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	const ptrdiff_t off = attr - power_supply_attrs;
+	union power_supply_propval value;
+
+	ret = psy->get_property(psy, off, &value);
+
+	if (ret < 0) {
+		if (ret != -ENODEV)
+			dev_err(dev, "driver failed to report `%s' property\n",
+				attr->attr.name);
+		return ret;
+	}
+
+	if (off == POWER_SUPPLY_PROP_STATUS)
+		return sprintf(buf, "%s\n", status_text[value.intval]);
+	else if (off == POWER_SUPPLY_PROP_HEALTH)
+		return sprintf(buf, "%s\n", health_text[value.intval]);
+	else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)
+		return sprintf(buf, "%s\n", technology_text[value.intval]);
+	else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)
+		return sprintf(buf, "%s\n",
+			       capacity_level_text[value.intval]);
+	else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
+		return sprintf(buf, "%s\n", value.strval);
+
+	return sprintf(buf, "%d\n", value.intval);
+}
+
+/* Must be in the same order as POWER_SUPPLY_PROP_* */
+static struct device_attribute power_supply_attrs[] = {
+	/* Properties of type `int' */
+	POWER_SUPPLY_ATTR(status),
+	POWER_SUPPLY_ATTR(health),
+	POWER_SUPPLY_ATTR(present),
+	POWER_SUPPLY_ATTR(online),
+	POWER_SUPPLY_ATTR(technology),
+	POWER_SUPPLY_ATTR(voltage_max_design),
+	POWER_SUPPLY_ATTR(voltage_min_design),
+	POWER_SUPPLY_ATTR(voltage_now),
+	POWER_SUPPLY_ATTR(voltage_avg),
+	POWER_SUPPLY_ATTR(current_now),
+	POWER_SUPPLY_ATTR(current_avg),
+	POWER_SUPPLY_ATTR(charge_full_design),
+	POWER_SUPPLY_ATTR(charge_empty_design),
+	POWER_SUPPLY_ATTR(charge_full),
+	POWER_SUPPLY_ATTR(charge_empty),
+	POWER_SUPPLY_ATTR(charge_now),
+	POWER_SUPPLY_ATTR(charge_avg),
+	POWER_SUPPLY_ATTR(energy_full_design),
+	POWER_SUPPLY_ATTR(energy_empty_design),
+	POWER_SUPPLY_ATTR(energy_full),
+	POWER_SUPPLY_ATTR(energy_empty),
+	POWER_SUPPLY_ATTR(energy_now),
+	POWER_SUPPLY_ATTR(energy_avg),
+	POWER_SUPPLY_ATTR(capacity),
+	POWER_SUPPLY_ATTR(capacity_level),
+	POWER_SUPPLY_ATTR(temp),
+	POWER_SUPPLY_ATTR(temp_ambient),
+	POWER_SUPPLY_ATTR(time_to_empty_now),
+	POWER_SUPPLY_ATTR(time_to_empty_avg),
+	POWER_SUPPLY_ATTR(time_to_full_now),
+	POWER_SUPPLY_ATTR(time_to_full_avg),
+	/* Properties of type `const char *' */
+	POWER_SUPPLY_ATTR(model_name),
+	POWER_SUPPLY_ATTR(manufacturer),
+};
+
+static ssize_t power_supply_show_static_attrs(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf) {
+	static char *type_text[] = { "Battery", "UPS", "Mains", "USB" };
+	struct power_supply *psy = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", type_text[psy->type]);
+}
+
+static struct device_attribute power_supply_static_attrs[] = {
+	__ATTR(type, 0444, power_supply_show_static_attrs, NULL),
+};
+
+int power_supply_create_attrs(struct power_supply *psy)
+{
+	int rc = 0;
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++) {
+		rc = device_create_file(psy->dev,
+			    &power_supply_static_attrs[i]);
+		if (rc)
+			goto statics_failed;
+	}
+
+	for (j = 0; j < psy->num_properties; j++) {
+		rc = device_create_file(psy->dev,
+			    &power_supply_attrs[psy->properties[j]]);
+		if (rc)
+			goto dynamics_failed;
+	}
+
+	goto succeed;
+
+dynamics_failed:
+	while (j--)
+		device_remove_file(psy->dev,
+			   &power_supply_attrs[psy->properties[j]]);
+statics_failed:
+	while (i--)
+		device_remove_file(psy->dev,
+			   &power_supply_static_attrs[psy->properties[i]]);
+succeed:
+	return rc;
+}
+
+void power_supply_remove_attrs(struct power_supply *psy)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++)
+		device_remove_file(psy->dev,
+			    &power_supply_static_attrs[i]);
+
+	for (i = 0; i < psy->num_properties; i++)
+		device_remove_file(psy->dev,
+			    &power_supply_attrs[psy->properties[i]]);
+}
+
+static char *kstruprdup(const char *str, gfp_t gfp)
+{
+	char *ret, *ustr;
+
+	ustr = ret = kmalloc(strlen(str) + 1, gfp);
+
+	if (!ret)
+		return NULL;
+
+	while (*str)
+		*ustr++ = toupper(*str++);
+
+	*ustr = 0;
+
+	return ret;
+}
+
+int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+			char *buffer, int buffer_size)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	int i = 0, length = 0, ret = 0, j;
+	char *prop_buf;
+	char *attrname;
+
+	dev_dbg(dev, "uevent\n");
+
+	if (!psy) {
+		dev_dbg(dev, "No power supply yet\n");
+		return ret;
+	}
+
+	dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
+
+	ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+			     &length, "POWER_SUPPLY_NAME=%s", psy->name);
+	if (ret)
+		return ret;
+
+	prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
+	if (!prop_buf)
+		return -ENOMEM;
+
+	for (j = 0; j < ARRAY_SIZE(power_supply_static_attrs); j++) {
+		struct device_attribute *attr;
+		char *line;
+
+		attr = &power_supply_static_attrs[j];
+
+		ret = power_supply_show_static_attrs(dev, attr, prop_buf);
+		if (ret < 0)
+			goto out;
+
+		line = strchr(prop_buf, '\n');
+		if (line)
+			*line = 0;
+
+		attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+		if (!attrname) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
+
+		ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+				     &length, "POWER_SUPPLY_%s=%s",
+				     attrname, prop_buf);
+		kfree(attrname);
+		if (ret)
+			goto out;
+	}
+
+	dev_dbg(dev, "%zd dynamic props\n", psy->num_properties);
+
+	for (j = 0; j < psy->num_properties; j++) {
+		struct device_attribute *attr;
+		char *line;
+
+		attr = &power_supply_attrs[psy->properties[j]];
+
+		ret = power_supply_show_property(dev, attr, prop_buf);
+		if (ret == -ENODEV) {
+			/* When a battery is absent, we expect -ENODEV. Don't abort;
+			   send the uevent with at least the the PRESENT=0 property */
+			ret = 0;
+			continue;
+		}
+
+		if (ret < 0)
+			goto out;
+
+		line = strchr(prop_buf, '\n');
+		if (line)
+			*line = 0;
+
+		attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+		if (!attrname) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
+
+		ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+				     &length, "POWER_SUPPLY_%s=%s",
+				     attrname, prop_buf);
+		kfree(attrname);
+		if (ret)
+			goto out;
+	}
+
+out:
+	free_page((unsigned long)prop_buf);
+
+	return ret;
+}
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index e251d1c..746031d 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1,3 +1,6 @@
 obj-$(CONFIG_PS3_VUART) += vuart.o
-obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o
+ps3av_mod-objs		+= ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
 obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
+obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 1393e64..85e2161 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -1,32 +1,30 @@
 /*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ *  PS3 AV backend support.
  *
- * AV backend support for PS3
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/kernel.h>
 #include <linux/ioctl.h>
 
 #include <asm/firmware.h>
-#include <asm/lv1call.h>
 #include <asm/ps3av.h>
 #include <asm/ps3.h>
 
@@ -39,13 +37,12 @@
 module_param(timeout, int, 0644);
 
 static struct ps3av {
-	int available;
 	struct mutex mutex;
 	struct work_struct work;
 	struct completion done;
 	struct workqueue_struct *wq;
 	int open_count;
-	struct ps3_vuart_port_device *dev;
+	struct ps3_system_bus_device *dev;
 
 	int region;
 	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
@@ -55,11 +52,13 @@
 	u32 audio_port;
 	int ps3av_mode;
 	int ps3av_mode_old;
-} ps3av;
-
-static struct ps3_vuart_port_device ps3av_dev = {
-	.match_id = PS3_MATCH_ID_AV_SETTINGS
-};
+	union {
+		struct ps3av_reply_hdr reply_hdr;
+		u8 raw[PS3AV_BUF_SIZE];
+	} recv_buf;
+	void (*flip_ctl)(int on, void *data);
+	void *flip_data;
+} *ps3av;
 
 /* color space */
 #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
@@ -169,7 +168,7 @@
 	if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
 		table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
 		if (table)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"recv event packet cid:%08x port:0x%x size:%d\n",
 				hdr->cid, ps3av_event_get_port_id(hdr->cid),
 				hdr->size);
@@ -182,6 +181,41 @@
 	return 0;
 }
 
+
+#define POLLING_INTERVAL  25	/* in msec */
+
+static int ps3av_vuart_write(struct ps3_system_bus_device *dev,
+			     const void *buf, unsigned long size)
+{
+	int error;
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	error = ps3_vuart_write(dev, buf, size);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+	return error ? error : size;
+}
+
+static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf,
+			    unsigned long size, int timeout)
+{
+	int error;
+	int loopcnt = 0;
+
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
+	while (loopcnt++ <= timeout) {
+		error = ps3_vuart_read(dev, buf, size);
+		if (!error)
+			return size;
+		if (error != -EAGAIN) {
+			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
+			       __func__, error);
+			return error;
+		}
+		msleep(POLLING_INTERVAL);
+	}
+	return -EWOULDBLOCK;
+}
+
 static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
 			      struct ps3av_reply_hdr *recv_buf, int write_len,
 			      int read_len)
@@ -190,13 +224,13 @@
 	u32 cmd;
 	int event;
 
-	if (!ps3av.available)
+	if (!ps3av)
 		return -ENODEV;
 
 	/* send pkt */
-	res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+	res = ps3av_vuart_write(ps3av->dev, send_buf, write_len);
 	if (res < 0) {
-		dev_dbg(&ps3av_dev.core,
+		dev_dbg(&ps3av->dev->core,
 			"%s: ps3av_vuart_write() failed (result=%d)\n",
 			__func__, res);
 		return res;
@@ -206,20 +240,20 @@
 	cmd = send_buf->cid;
 	do {
 		/* read header */
-		res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+		res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE,
 				       timeout);
 		if (res != PS3AV_HDR_SIZE) {
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"%s: ps3av_vuart_read() failed (result=%d)\n",
 				__func__, res);
 			return res;
 		}
 
 		/* read body */
-		res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+		res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid,
 				       recv_buf->size, timeout);
 		if (res < 0) {
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"%s: ps3av_vuart_read() failed (result=%d)\n",
 				__func__, res);
 			return res;
@@ -230,7 +264,7 @@
 	} while (event);
 
 	if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
-		dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
+		dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n",
 			__func__, recv_buf->cid);
 		return -EINVAL;
 	}
@@ -245,7 +279,7 @@
 	int return_len;
 
 	if (recv_buf->version != PS3AV_VERSION) {
-		dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n",
+		dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n",
 			recv_buf->version);
 		return -EFAULT;
 	}
@@ -267,16 +301,11 @@
 		 struct ps3av_send_hdr *buf)
 {
 	int res = 0;
-	static union {
-		struct ps3av_reply_hdr reply_hdr;
-		u8 raw[PS3AV_BUF_SIZE];
-	} recv_buf;
-
 	u32 *table;
 
-	BUG_ON(!ps3av.available);
+	BUG_ON(!ps3av);
 
-	mutex_lock(&ps3av.mutex);
+	mutex_lock(&ps3av->mutex);
 
 	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
 	BUG_ON(!table);
@@ -288,7 +317,7 @@
 	ps3av_set_hdr(cid, send_len, buf);
 
 	/* send packet via vuart */
-	res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+	res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len,
 				 usr_buf_size);
 	if (res < 0) {
 		printk(KERN_ERR
@@ -298,7 +327,7 @@
 	}
 
 	/* process reply packet */
-	res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+	res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr,
 					 usr_buf_size);
 	if (res < 0) {
 		printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
@@ -306,11 +335,11 @@
 		goto err;
 	}
 
-	mutex_unlock(&ps3av.mutex);
+	mutex_unlock(&ps3av->mutex);
 	return 0;
 
       err:
-	mutex_unlock(&ps3av.mutex);
+	mutex_unlock(&ps3av->mutex);
 	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
 	return res;
 }
@@ -319,11 +348,11 @@
 {
 	int i, num_of_av_port, res;
 
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
 	/* video mute on */
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+		res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
@@ -335,13 +364,13 @@
 {
 	int i, num_of_hdmi_port, num_of_av_port, res;
 
-	num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
+	num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
 
 	/* tv mute */
 	for (i = 0; i < num_of_hdmi_port; i++) {
-		res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+		res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
 					   PS3AV_CMD_MUTE_ON);
 		if (res < 0)
 			return -1;
@@ -350,11 +379,11 @@
 
 	/* video mute on */
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+		res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]);
 		if (res < 0)
 			return -1;
 		if (i < num_of_hdmi_port) {
-			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+			res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
 						   PS3AV_CMD_MUTE_OFF);
 			if (res < 0)
 				return -1;
@@ -369,17 +398,17 @@
 {
 	int i, num_of_av_port, num_of_opt_port, res;
 
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
-	num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
+	num_of_opt_port = ps3av->av_hw_conf.num_of_spdif;
 
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+		res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
 	for (i = 0; i < num_of_opt_port; i++) {
-		res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+		res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
@@ -394,40 +423,40 @@
 	struct ps3av_pkt_audio_mode audio_mode;
 	u32 len = 0;
 
-	num_of_audio = ps3av.av_hw_conf.num_of_hdmi +
-		       ps3av.av_hw_conf.num_of_avmulti +
-		       ps3av.av_hw_conf.num_of_spdif;
+	num_of_audio = ps3av->av_hw_conf.num_of_hdmi +
+		       ps3av->av_hw_conf.num_of_avmulti +
+		       ps3av->av_hw_conf.num_of_spdif;
 
 	avb_param.num_of_video_pkt = 0;
 	avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO;	/* always 0 */
 	avb_param.num_of_av_video_pkt = 0;
-	avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+	avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi;
 
-	vid = video_mode_table[ps3av.ps3av_mode].vid;
+	vid = video_mode_table[ps3av->ps3av_mode].vid;
 
 	/* audio mute */
 	ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
 
 	/* audio inactive */
-	res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+	res = ps3av_cmd_audio_active(0, ps3av->audio_port);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core,
+		dev_dbg(&ps3av->dev->core,
 			"ps3av_cmd_audio_active OFF failed\n");
 
 	/* audio_pkt */
 	for (i = 0; i < num_of_audio; i++) {
-		ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
-					 word_bits, format, source);
-		if (i < ps3av.av_hw_conf.num_of_hdmi) {
+		ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch,
+					 fs, word_bits, format, source);
+		if (i < ps3av->av_hw_conf.num_of_hdmi) {
 			/* hdmi only */
 			len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
-							    ps3av.av_port[i],
+							    ps3av->av_port[i],
 							    &audio_mode, vid);
 		}
 		/* audio_mode pkt should be sent separately */
 		res = ps3av_cmd_audio_mode(&audio_mode);
 		if (res < 0)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_audio_mode failed, port:%x\n", i);
 	}
 
@@ -435,15 +464,16 @@
 	len += offsetof(struct ps3av_pkt_avb_param, buf);
 	res = ps3av_cmd_avb_param(&avb_param, len);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+		dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
 
 	/* audio mute */
 	ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
 
 	/* audio active */
-	res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+	res = ps3av_cmd_audio_active(1, ps3av->audio_port);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n");
+		dev_dbg(&ps3av->dev->core,
+			"ps3av_cmd_audio_active ON failed\n");
 
 	return 0;
 }
@@ -456,7 +486,7 @@
 	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
 
 	/* wake up ps3avd to do the actual video mode setting */
-	queue_work(ps3av.wq, &ps3av.work);
+	queue_work(ps3av->wq, &ps3av->work);
 
 	return 0;
 }
@@ -473,8 +503,8 @@
 
 	avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO;	/* num of head */
 	avb_param.num_of_audio_pkt = 0;
-	avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
-					ps3av.av_hw_conf.num_of_avmulti;
+	avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi +
+					ps3av->av_hw_conf.num_of_avmulti;
 	avb_param.num_of_av_audio_pkt = 0;
 
 	/* video signal off */
@@ -484,21 +514,21 @@
 	if (id & PS3AV_MODE_HDCP_OFF) {
 		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
 		if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
-			dev_dbg(&ps3av_dev.core, "Not supported\n");
+			dev_dbg(&ps3av->dev->core, "Not supported\n");
 		else if (res)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_av_hdmi_mode failed\n");
 	} else if (old_id & PS3AV_MODE_HDCP_OFF) {
 		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
 		if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_av_hdmi_mode failed\n");
 	}
 
 	/* video_pkt */
 	for (i = 0; i < avb_param.num_of_video_pkt; i++)
 		len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
-						ps3av.head[i], video_mode->vid,
+						ps3av->head[i], video_mode->vid,
 						video_mode->fmt, id);
 	/* av_video_pkt */
 	for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
@@ -507,12 +537,12 @@
 		else
 			av_video_cs = video_mode->cs;
 #ifndef PS3AV_HDMI_YUV
-		if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
-		    ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+		if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+		    ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
 			av_video_cs = RGB8;	/* use RGB for HDMI */
 #endif
 		len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
-						 ps3av.av_port[i],
+						 ps3av->av_port[i],
 						 video_mode->vid, av_video_cs,
 						 video_mode->aspect, id);
 	}
@@ -524,7 +554,7 @@
 		       "%s: Command failed. Please try your request again. \n",
 		       __func__);
 	else if (res)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+		dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
 
 	msleep(1500);
 	/* av video mute */
@@ -533,8 +563,8 @@
 
 static void ps3avd(struct work_struct *work)
 {
-	ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old);
-	complete(&ps3av.done);
+	ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old);
+	complete(&ps3av->done);
 }
 
 static int ps3av_vid2table_id(int vid)
@@ -601,7 +631,7 @@
 		return vid;
 	}
 
-	if (ps3av.region & PS3AV_REGION_60)
+	if (ps3av->region & PS3AV_REGION_60)
 		vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
 	else
 		vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
@@ -643,16 +673,16 @@
 		vid = PS3AV_DEFAULT_DVI_VID;
 	} else if (vid == -1) {
 		/* no HDMI interface or HDMI is off */
-		if (ps3av.region & PS3AV_REGION_60)
+		if (ps3av->region & PS3AV_REGION_60)
 			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
 		else
 			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
-		if (ps3av.region & PS3AV_REGION_RGB)
+		if (ps3av->region & PS3AV_REGION_RGB)
 			rgb = PS3AV_MODE_RGB;
 	} else if (boot) {
 		/* HDMI: using DEFAULT HDMI_VID while booting up */
 		info = &monitor_info.info;
-		if (ps3av.region & PS3AV_REGION_60) {
+		if (ps3av->region & PS3AV_REGION_60) {
 			if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
 				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
 			else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
@@ -715,14 +745,14 @@
 
 	size = ARRAY_SIZE(video_mode_table);
 	if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
-		dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id);
+		dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id);
 		return -EINVAL;
 	}
 
 	/* auto mode */
 	option = id & ~PS3AV_MODE_MASK;
 	if ((id & PS3AV_MODE_MASK) == 0) {
-		id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+		id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
 		if (id < 1) {
 			printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
 			return -EINVAL;
@@ -731,11 +761,11 @@
 	}
 
 	/* set videomode */
-	wait_for_completion(&ps3av.done);
-	ps3av.ps3av_mode_old = ps3av.ps3av_mode;
-	ps3av.ps3av_mode = id;
+	wait_for_completion(&ps3av->done);
+	ps3av->ps3av_mode_old = ps3av->ps3av_mode;
+	ps3av->ps3av_mode = id;
 	if (ps3av_set_videomode())
-		ps3av.ps3av_mode = ps3av.ps3av_mode_old;
+		ps3av->ps3av_mode = ps3av->ps3av_mode_old;
 
 	return 0;
 }
@@ -744,7 +774,7 @@
 
 int ps3av_get_auto_mode(int boot)
 {
-	return ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+	return ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
 }
 
 EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
@@ -772,7 +802,7 @@
 
 int ps3av_get_mode(void)
 {
-	return ps3av.ps3av_mode;
+	return ps3av ? ps3av->ps3av_mode : 0;
 }
 
 EXPORT_SYMBOL_GPL(ps3av_get_mode);
@@ -842,82 +872,65 @@
 
 EXPORT_SYMBOL_GPL(ps3av_audio_mute);
 
-int ps3av_dev_open(void)
+void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+			     void *flip_data)
 {
-	int status = 0;
+	mutex_lock(&ps3av->mutex);
+	ps3av->flip_ctl = flip_ctl;
+	ps3av->flip_data = flip_data;
+	mutex_unlock(&ps3av->mutex);
+}
+EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl);
 
-	mutex_lock(&ps3av.mutex);
-	if (!ps3av.open_count++) {
-		status = lv1_gpu_open(0);
-		if (status) {
-			printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
-			       __func__, status);
-			ps3av.open_count--;
-		}
-	}
-	mutex_unlock(&ps3av.mutex);
-
-	return status;
+void ps3av_flip_ctl(int on)
+{
+	mutex_lock(&ps3av->mutex);
+	if (ps3av->flip_ctl)
+		ps3av->flip_ctl(on, ps3av->flip_data);
+	mutex_unlock(&ps3av->mutex);
 }
 
-EXPORT_SYMBOL_GPL(ps3av_dev_open);
-
-int ps3av_dev_close(void)
-{
-	int status = 0;
-
-	mutex_lock(&ps3av.mutex);
-	if (ps3av.open_count <= 0) {
-		printk(KERN_ERR "%s: GPU already closed\n", __func__);
-		status = -1;
-	} else if (!--ps3av.open_count) {
-		status = lv1_gpu_close();
-		if (status)
-			printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
-			       __func__, status);
-	}
-	mutex_unlock(&ps3av.mutex);
-
-	return status;
-}
-
-EXPORT_SYMBOL_GPL(ps3av_dev_close);
-
-static int ps3av_probe(struct ps3_vuart_port_device *dev)
+static int ps3av_probe(struct ps3_system_bus_device *dev)
 {
 	int res;
 	u32 id;
 
-	dev_dbg(&ps3av_dev.core, "init ...\n");
-	dev_dbg(&ps3av_dev.core, "  timeout=%d\n", timeout);
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	dev_dbg(&dev->core, "  timeout=%d\n", timeout);
 
-	memset(&ps3av, 0, sizeof(ps3av));
+	if (ps3av) {
+		dev_err(&dev->core, "Only one ps3av device is supported\n");
+		return -EBUSY;
+	}
 
-	mutex_init(&ps3av.mutex);
-	ps3av.ps3av_mode = 0;
-	ps3av.dev = dev;
-
-	INIT_WORK(&ps3av.work, ps3avd);
-	init_completion(&ps3av.done);
-	complete(&ps3av.done);
-	ps3av.wq = create_singlethread_workqueue("ps3avd");
-	if (!ps3av.wq)
+	ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL);
+	if (!ps3av)
 		return -ENOMEM;
 
-	ps3av.available = 1;
+	mutex_init(&ps3av->mutex);
+	ps3av->ps3av_mode = 0;
+	ps3av->dev = dev;
+
+	INIT_WORK(&ps3av->work, ps3avd);
+	init_completion(&ps3av->done);
+	complete(&ps3av->done);
+	ps3av->wq = create_singlethread_workqueue("ps3avd");
+	if (!ps3av->wq)
+		goto fail;
+
 	switch (ps3_os_area_get_av_multi_out()) {
 	case PS3_PARAM_AV_MULTI_OUT_NTSC:
-		ps3av.region = PS3AV_REGION_60;
+		ps3av->region = PS3AV_REGION_60;
 		break;
 	case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
 	case PS3_PARAM_AV_MULTI_OUT_SECAM:
-		ps3av.region = PS3AV_REGION_50;
+		ps3av->region = PS3AV_REGION_50;
 		break;
 	case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
-		ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+		ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
 		break;
 	default:
-		ps3av.region = PS3AV_REGION_60;
+		ps3av->region = PS3AV_REGION_60;
 		break;
 	}
 
@@ -927,39 +940,47 @@
 		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__,
 		       res);
 
-	ps3av_get_hw_conf(&ps3av);
-	id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
-	mutex_lock(&ps3av.mutex);
-	ps3av.ps3av_mode = id;
-	mutex_unlock(&ps3av.mutex);
+	ps3av_get_hw_conf(ps3av);
+	id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1);
+	mutex_lock(&ps3av->mutex);
+	ps3av->ps3av_mode = id;
+	mutex_unlock(&ps3av->mutex);
 
-	dev_dbg(&ps3av_dev.core, "init...done\n");
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
 	return 0;
+
+fail:
+	kfree(ps3av);
+	ps3av = NULL;
+	return -ENOMEM;
 }
 
-static int ps3av_remove(struct ps3_vuart_port_device *dev)
+static int ps3av_remove(struct ps3_system_bus_device *dev)
 {
-	if (ps3av.available) {
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	if (ps3av) {
 		ps3av_cmd_fin();
-		if (ps3av.wq)
-			destroy_workqueue(ps3av.wq);
-		ps3av.available = 0;
+		if (ps3av->wq)
+			destroy_workqueue(ps3av->wq);
+		kfree(ps3av);
+		ps3av = NULL;
 	}
 
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 	return 0;
 }
 
-static void ps3av_shutdown(struct ps3_vuart_port_device *dev)
+static void ps3av_shutdown(struct ps3_system_bus_device *dev)
 {
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
 	ps3av_remove(dev);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 }
 
 static struct ps3_vuart_port_driver ps3av_driver = {
-	.match_id = PS3_MATCH_ID_AV_SETTINGS,
-	.core = {
-		.name = "ps3_av",
-	},
+	.core.match_id = PS3_MATCH_ID_AV_SETTINGS,
+	.core.core.name = "ps3_av",
 	.probe = ps3av_probe,
 	.remove = ps3av_remove,
 	.shutdown = ps3av_shutdown,
@@ -972,6 +993,8 @@
 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 		return -ENODEV;
 
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
 	error = ps3_vuart_port_driver_register(&ps3av_driver);
 	if (error) {
 		printk(KERN_ERR
@@ -980,20 +1003,21 @@
 		return error;
 	}
 
-	error = ps3_vuart_port_device_register(&ps3av_dev);
-	if (error)
-		printk(KERN_ERR
-		       "%s: ps3_vuart_port_device_register failed %d\n",
-		       __func__, error);
-
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return error;
 }
 
 static void __exit ps3av_module_exit(void)
 {
-	device_unregister(&ps3av_dev.core);
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 	ps3_vuart_port_driver_unregister(&ps3av_driver);
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 }
 
 subsys_initcall(ps3av_module_init);
 module_exit(ps3av_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 AV Settings Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS);
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
index 0145ea1..f72f5dd 100644
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -143,6 +143,14 @@
 	return PS3AV_CMD_AV_VID_480P;
 }
 
+static int ps3av_hdmi_range(void)
+{
+	if (ps3_compare_firmware_version(1, 8, 0) < 0)
+		return 0;
+	else
+		return 1; /* supported */
+}
+
 int ps3av_cmd_init(void)
 {
 	int res;
@@ -350,6 +358,10 @@
 	/* should be same as video_mode.video_cs_out */
 	av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
 	av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+	if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range())
+		av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON;
+	else /* default off */
+		av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF;
 	av_video_cs->aspect = aspect;
 	if (id & PS3AV_MODE_DITHER) {
 		av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
@@ -392,6 +404,10 @@
 	video_mode->pitch = video_mode->width * 4;	/* line_length */
 	video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
 	video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+	if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range())
+		video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT;
+	else /* default enable */
+		video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT;
 	video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
 
 	pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
@@ -852,7 +868,7 @@
 {
 	int res;
 
-	ps3fb_flip_ctl(0);	/* flip off */
+	ps3av_flip_ctl(0);	/* flip off */
 
 	/* avb packet */
 	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
@@ -866,7 +882,7 @@
 			 res);
 
       out:
-	ps3fb_flip_ctl(1);	/* flip on */
+	ps3av_flip_ctl(1);	/* flip on */
 	return res;
 }
 
@@ -987,34 +1003,3 @@
 		| PS3AV_CMD_AV_LAYOUT_176 \
 		| PS3AV_CMD_AV_LAYOUT_192)
 
-/************************* vuart ***************************/
-
-#define POLLING_INTERVAL  25	/* in msec */
-
-int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
-		      unsigned long size)
-{
-	int error = ps3_vuart_write(dev, buf, size);
-	return error ? error : size;
-}
-
-int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
-		     unsigned long size, int timeout)
-{
-	int error;
-	int loopcnt = 0;
-
-	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
-	while (loopcnt++ <= timeout) {
-		error = ps3_vuart_read(dev, buf, size);
-		if (!error)
-			return size;
-		if (error != -EAGAIN) {
-			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
-			       __func__, error);
-			return error;
-		}
-		msleep(POLLING_INTERVAL);
-	}
-	return -EWOULDBLOCK;
-}
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
new file mode 100644
index 0000000..3a9824e
--- /dev/null
+++ b/drivers/ps3/ps3stor_lib.c
@@ -0,0 +1,302 @@
+/*
+ * PS3 Storage Library
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/dma-mapping.h>
+
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+
+static int ps3stor_probe_access(struct ps3_storage_device *dev)
+{
+	int res, error;
+	unsigned int i;
+	unsigned long n;
+
+	if (dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) {
+		/* special case: CD-ROM is assumed always accessible */
+		dev->accessible_regions = 1;
+		return 0;
+	}
+
+	error = -EPERM;
+	for (i = 0; i < dev->num_regions; i++) {
+		dev_dbg(&dev->sbd.core,
+			"%s:%u: checking accessibility of region %u\n",
+			__func__, __LINE__, i);
+
+		dev->region_idx = i;
+		res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1,
+						 0);
+		if (res) {
+			dev_dbg(&dev->sbd.core, "%s:%u: read failed, "
+				"region %u is not accessible\n", __func__,
+				__LINE__, i);
+			continue;
+		}
+
+		dev_dbg(&dev->sbd.core, "%s:%u: region %u is accessible\n",
+			__func__, __LINE__, i);
+		set_bit(i, &dev->accessible_regions);
+
+		/* We can access at least one region */
+		error = 0;
+	}
+	if (error)
+		return error;
+
+	n = hweight_long(dev->accessible_regions);
+	if (n > 1)
+		dev_info(&dev->sbd.core,
+			 "%s:%u: %lu accessible regions found. Only the first "
+			 "one will be used",
+			 __func__, __LINE__, n);
+	dev->region_idx = __ffs(dev->accessible_regions);
+	dev_info(&dev->sbd.core,
+		 "First accessible region has index %u start %lu size %lu\n",
+		 dev->region_idx, dev->regions[dev->region_idx].start,
+		 dev->regions[dev->region_idx].size);
+
+	return 0;
+}
+
+
+/**
+ *	ps3stor_setup - Setup a storage device before use
+ *	@dev: Pointer to a struct ps3_storage_device
+ *	@handler: Pointer to an interrupt handler
+ *
+ *	Returns 0 for success, or an error code
+ */
+int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
+{
+	int error, res, alignment;
+	enum ps3_dma_page_size page_size;
+
+	error = ps3_open_hv_device(&dev->sbd);
+	if (error) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: ps3_open_hv_device failed %d\n", __func__,
+			__LINE__, error);
+		goto fail;
+	}
+
+	error = ps3_sb_event_receive_port_setup(&dev->sbd, PS3_BINDING_CPU_ANY,
+						&dev->irq);
+	if (error) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
+		       __func__, __LINE__, error);
+		goto fail_close_device;
+	}
+
+	error = request_irq(dev->irq, handler, IRQF_DISABLED,
+			    dev->sbd.core.driver->name, dev);
+	if (error) {
+		dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n",
+			__func__, __LINE__, error);
+		goto fail_sb_event_receive_port_destroy;
+	}
+
+	alignment = min(__ffs(dev->bounce_size),
+			__ffs((unsigned long)dev->bounce_buf));
+	if (alignment < 12) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: bounce buffer not aligned (%lx at 0x%p)\n",
+			__func__, __LINE__, dev->bounce_size, dev->bounce_buf);
+		error = -EINVAL;
+		goto fail_free_irq;
+	} else if (alignment < 16)
+		page_size = PS3_DMA_4K;
+	else
+		page_size = PS3_DMA_64K;
+	dev->sbd.d_region = &dev->dma_region;
+	ps3_dma_region_init(&dev->sbd, &dev->dma_region, page_size,
+			    PS3_DMA_OTHER, dev->bounce_buf, dev->bounce_size);
+	res = ps3_dma_region_create(&dev->dma_region);
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: cannot create DMA region\n",
+			__func__, __LINE__);
+		error = -ENOMEM;
+		goto fail_free_irq;
+	}
+
+	dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf));
+	dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf,
+					 dev->bounce_size, DMA_BIDIRECTIONAL);
+	if (!dev->bounce_dma) {
+		dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n",
+			__func__, __LINE__);
+		error = -ENODEV;
+		goto fail_free_dma;
+	}
+
+	error = ps3stor_probe_access(dev);
+	if (error) {
+		dev_err(&dev->sbd.core, "%s:%u: No accessible regions found\n",
+			__func__, __LINE__);
+		goto fail_unmap_dma;
+	}
+	return 0;
+
+fail_unmap_dma:
+	dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
+			 DMA_BIDIRECTIONAL);
+fail_free_dma:
+	ps3_dma_region_free(&dev->dma_region);
+fail_free_irq:
+	free_irq(dev->irq, dev);
+fail_sb_event_receive_port_destroy:
+	ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
+fail_close_device:
+	ps3_close_hv_device(&dev->sbd);
+fail:
+	return error;
+}
+EXPORT_SYMBOL_GPL(ps3stor_setup);
+
+
+/**
+ *	ps3stor_teardown - Tear down a storage device after use
+ *	@dev: Pointer to a struct ps3_storage_device
+ */
+void ps3stor_teardown(struct ps3_storage_device *dev)
+{
+	int error;
+
+	dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
+			 DMA_BIDIRECTIONAL);
+	ps3_dma_region_free(&dev->dma_region);
+
+	free_irq(dev->irq, dev);
+
+	error = ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
+	if (error)
+		dev_err(&dev->sbd.core,
+			"%s:%u: destroy event receive port failed %d\n",
+			__func__, __LINE__, error);
+
+	error = ps3_close_hv_device(&dev->sbd);
+	if (error)
+		dev_err(&dev->sbd.core,
+			"%s:%u: ps3_close_hv_device failed %d\n", __func__,
+			__LINE__, error);
+}
+EXPORT_SYMBOL_GPL(ps3stor_teardown);
+
+
+/**
+ *	ps3stor_read_write_sectors - read/write from/to a storage device
+ *	@dev: Pointer to a struct ps3_storage_device
+ *	@lpar: HV logical partition address
+ *	@start_sector: First sector to read/write
+ *	@sectors: Number of sectors to read/write
+ *	@write: Flag indicating write (non-zero) or read (zero)
+ *
+ *	Returns 0 for success, -1 in case of failure to submit the command, or
+ *	an LV1 status value in case of other errors
+ */
+u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+			       u64 start_sector, u64 sectors, int write)
+{
+	unsigned int region_id = dev->regions[dev->region_idx].id;
+	const char *op = write ? "write" : "read";
+	int res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
+		__func__, __LINE__, op, sectors, start_sector);
+
+	init_completion(&dev->done);
+	res = write ? lv1_storage_write(dev->sbd.dev_id, region_id,
+					start_sector, sectors, 0, lpar,
+					&dev->tag)
+		    : lv1_storage_read(dev->sbd.dev_id, region_id,
+				       start_sector, sectors, 0, lpar,
+				       &dev->tag);
+	if (res) {
+		dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
+			__LINE__, op, res);
+		return -1;
+	}
+
+	wait_for_completion(&dev->done);
+	if (dev->lv1_status) {
+		dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+			__LINE__, op, dev->lv1_status);
+		return dev->lv1_status;
+	}
+
+	dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, __LINE__,
+		op);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ps3stor_read_write_sectors);
+
+
+/**
+ *	ps3stor_send_command - send a device command to a storage device
+ *	@dev: Pointer to a struct ps3_storage_device
+ *	@cmd: Command number
+ *	@arg1: First command argument
+ *	@arg2: Second command argument
+ *	@arg3: Third command argument
+ *	@arg4: Fourth command argument
+ *
+ *	Returns 0 for success, -1 in case of failure to submit the command, or
+ *	an LV1 status value in case of other errors
+ */
+u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1,
+			 u64 arg2, u64 arg3, u64 arg4)
+{
+	int res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__,
+		__LINE__, cmd);
+
+	init_completion(&dev->done);
+
+	res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd, arg1,
+					      arg2, arg3, arg4, &dev->tag);
+	if (res) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: send_device_command 0x%lx failed %d\n",
+			__func__, __LINE__, cmd, res);
+		return -1;
+	}
+
+	wait_for_completion(&dev->done);
+	if (dev->lv1_status) {
+		dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n",
+			__func__, __LINE__, cmd, dev->lv1_status);
+		return dev->lv1_status;
+	}
+
+	dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__,
+		__LINE__, cmd);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ps3stor_send_command);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PS3 Storage Bus Library");
+MODULE_AUTHOR("Sony Corporation");
diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c
new file mode 100644
index 0000000..31648f7
--- /dev/null
+++ b/drivers/ps3/sys-manager-core.c
@@ -0,0 +1,68 @@
+/*
+ *  PS3 System Manager core.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <asm/ps3.h>
+
+/**
+ * Staticly linked routines that allow late binding of a loaded sys-manager
+ * module.
+ */
+
+static struct ps3_sys_manager_ops ps3_sys_manager_ops;
+
+/**
+ * ps3_register_sys_manager_ops - Bind ps3_sys_manager_ops to a module.
+ * @ops: struct ps3_sys_manager_ops.
+ *
+ * To be called from ps3_sys_manager_probe() and ps3_sys_manager_remove() to
+ * register call back ops for power control.  Copies data to the static
+ * variable ps3_sys_manager_ops.
+ */
+
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops)
+{
+	BUG_ON(!ops);
+	BUG_ON(!ops->dev);
+	ps3_sys_manager_ops = ops ? *ops : ps3_sys_manager_ops;
+}
+EXPORT_SYMBOL_GPL(ps3_sys_manager_register_ops);
+
+void ps3_sys_manager_power_off(void)
+{
+	if (ps3_sys_manager_ops.power_off)
+		ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1)
+		(void)0;
+}
+
+void ps3_sys_manager_restart(void)
+{
+	if (ps3_sys_manager_ops.restart)
+		ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1)
+		(void)0;
+}
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/sys-manager.c
index 3aa2b0d..8461b08 100644
--- a/drivers/ps3/sys-manager.c
+++ b/drivers/ps3/sys-manager.c
@@ -35,7 +35,7 @@
 /**
  * ps3_sys_manager - PS3 system manager driver.
  *
- * The system manager provides an asyncronous system event notification
+ * The system manager provides an asynchronous system event notification
  * mechanism for reporting events like thermal alert and button presses to
  * guests.  It also provides support to control system shutdown and startup.
  *
@@ -52,6 +52,7 @@
  * @size: Header size in bytes, curently 16.
  * @payload_size: Message payload size in bytes.
  * @service_id: Message type, one of enum ps3_sys_manager_service_id.
+ * @request_tag: Unique number to identify reply.
  */
 
 struct ps3_sys_manager_header {
@@ -61,29 +62,49 @@
 	u16 reserved_1;
 	u32 payload_size;
 	u16 service_id;
-	u16 reserved_2[3];
+	u16 reserved_2;
+	u32 request_tag;
 };
 
+#define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__)
+static void __maybe_unused _dump_sm_header(
+	const struct ps3_sys_manager_header *h, const char *func, int line)
+{
+	pr_debug("%s:%d: version:      %xh\n", func, line, h->version);
+	pr_debug("%s:%d: size:         %xh\n", func, line, h->size);
+	pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size);
+	pr_debug("%s:%d: service_id:   %xh\n", func, line, h->service_id);
+	pr_debug("%s:%d: request_tag:  %xh\n", func, line, h->request_tag);
+}
+
 /**
- * @PS3_SM_RX_MSG_LEN - System manager received message length.
+ * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length.
+ * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length.
  *
- * Currently all messages received from the system manager are the same length
- * (16 bytes header + 16 bytes payload = 32 bytes).  This knowlege is used to
- * simplify the logic.
+ * Currently all messages received from the system manager are either
+ * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header
+ * + 16 bytes payload = 32 bytes).  This knowlege is used to simplify
+ * the logic.
  */
 
 enum {
-	PS3_SM_RX_MSG_LEN = 32,
+	PS3_SM_RX_MSG_LEN_MIN = 24,
+	PS3_SM_RX_MSG_LEN_MAX = 32,
 };
 
 /**
  * enum ps3_sys_manager_service_id - Message header service_id.
- * @PS3_SM_SERVICE_ID_REQUEST:      guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_COMMAND:      guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_RESPONSE:     guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_SET_ATTR:     guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_SET_NEXT_OP:  guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST:       guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_COMMAND:       guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_RESPONSE:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_ATTR:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_EXTERN_EVENT:  guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_NEXT_OP:   guest --> sys_manager.
+ *
+ * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a
+ * a PS3_SM_SERVICE_ID_REQUEST message.  It also seems to be returned when
+ * a REQUEST message is sent at the wrong time.
  */
 
 enum ps3_sys_manager_service_id {
@@ -93,6 +114,7 @@
 	PS3_SM_SERVICE_ID_COMMAND = 3,
 	PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
 	PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
+	PS3_SM_SERVICE_ID_REQUEST_ERROR = 6,
 	PS3_SM_SERVICE_ID_SET_ATTR = 8,
 };
 
@@ -185,11 +207,21 @@
 };
 
 /**
+ * ps3_sm_force_power_off - Poweroff helper.
+ *
+ * A global variable used to force a poweroff when the power button has
+ * been pressed irrespective of how init handles the ctrl_alt_del signal.
+ *
+ */
+
+static unsigned int ps3_sm_force_power_off;
+
+/**
  * ps3_sys_manager_write - Helper to write a two part message to the vuart.
  *
  */
 
-static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_write(struct ps3_system_bus_device *dev,
 	const struct ps3_sys_manager_header *header, const void *payload)
 {
 	int result;
@@ -213,15 +245,10 @@
  *
  */
 
-static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev,
 	enum ps3_sys_manager_attr attr)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_SET_ATTR,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 reserved_1[3];
@@ -232,6 +259,12 @@
 
 	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_SET_ATTR;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 1;
 	payload.attribute = attr;
@@ -245,16 +278,11 @@
  * Tell the system manager what to do after this lpar is destroyed.
  */
 
-static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev,
 	enum ps3_sys_manager_next_op op,
 	enum ps3_sys_manager_wake_source wake_source)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 type;
@@ -268,6 +296,12 @@
 
 	dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 3;
 	payload.type = op;
@@ -286,32 +320,35 @@
  * the command is then communicated back to the system manager with a response
  * message.
  *
- * Currently, the only supported request it the 'shutdown self' request.
+ * Currently, the only supported request is the 'shutdown self' request.
  */
 
-static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_send_request_shutdown(
+	struct ps3_system_bus_device *dev)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_REQUEST,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 type;
 		u8 gos_id;
 		u8 reserved_1[13];
-	} static const payload = {
-		.version = 1,
-		.type = 1, /* shutdown */
-		.gos_id = 0, /* self */
-	};
+	} payload;
 
 	BUILD_BUG_ON(sizeof(payload) != 16);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_REQUEST;
+
+	memset(&payload, 0, sizeof(payload));
+	payload.version = 1;
+	payload.type = 1; /* shutdown */
+	payload.gos_id = 0; /* self */
+
 	return ps3_sys_manager_write(dev, &header, &payload);
 }
 
@@ -323,15 +360,10 @@
  * failure of a command sent by the system manager.
  */
 
-static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev,
 	u64 status)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_RESPONSE,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 reserved_1[3];
@@ -344,6 +376,12 @@
 	dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
 		(status ? "nak" : "ack"));
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_RESPONSE;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 1;
 	payload.status = status;
@@ -356,7 +394,7 @@
  *
  */
 
-static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct {
@@ -370,7 +408,7 @@
 	BUILD_BUG_ON(sizeof(event) != 16);
 
 	result = ps3_vuart_read(dev, &event, sizeof(event));
-	BUG_ON(result);
+	BUG_ON(result && "need to retry here");
 
 	if (event.version != 1) {
 		dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
@@ -382,11 +420,34 @@
 	case PS3_SM_EVENT_POWER_PRESSED:
 		dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
 			__func__, __LINE__);
+		ps3_sm_force_power_off = 1;
+		/*
+		 * A memory barrier is use here to sync memory since
+		 * ps3_sys_manager_final_restart() could be called on
+		 * another cpu.
+		 */
+		wmb();
+		kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
 		break;
 	case PS3_SM_EVENT_POWER_RELEASED:
 		dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
 			__func__, __LINE__, event.value);
-		kill_cad_pid(SIGINT, 1);
+		break;
+	case PS3_SM_EVENT_RESET_PRESSED:
+		dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n",
+			__func__, __LINE__);
+		ps3_sm_force_power_off = 0;
+		/*
+		 * A memory barrier is use here to sync memory since
+		 * ps3_sys_manager_final_restart() could be called on
+		 * another cpu.
+		 */
+		wmb();
+		kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
+		break;
+	case PS3_SM_EVENT_RESET_RELEASED:
+		dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
+			__func__, __LINE__, event.value);
 		break;
 	case PS3_SM_EVENT_THERMAL_ALERT:
 		dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
@@ -411,7 +472,7 @@
  * The system manager sends this in reply to a 'request' message from the guest.
  */
 
-static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct {
@@ -425,6 +486,7 @@
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
 	result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
+	BUG_ON(result && "need to retry here");
 
 	if(result)
 		return result;
@@ -448,9 +510,10 @@
 /**
  * ps3_sys_manager_handle_msg - First stage msg handler.
  *
+ * Can be called directly to manually poll vuart and pump message handler.
  */
 
-static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct ps3_sys_manager_header header;
@@ -464,12 +527,17 @@
 	if (header.version != 1) {
 		dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
 			__func__, __LINE__, header.version);
+		dump_sm_header(&header);
 		goto fail_header;
 	}
 
 	BUILD_BUG_ON(sizeof(header) != 16);
-	BUG_ON(header.size != 16);
-	BUG_ON(header.payload_size != 16);
+
+	if (header.size != 16 || (header.payload_size != 8
+		&& header.payload_size != 16)) {
+		dump_sm_header(&header);
+		BUG();
+	}
 
 	switch (header.service_id) {
 	case PS3_SM_SERVICE_ID_EXTERN_EVENT:
@@ -478,6 +546,11 @@
 	case PS3_SM_SERVICE_ID_COMMAND:
 		dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
 		return ps3_sys_manager_handle_cmd(dev);
+	case PS3_SM_SERVICE_ID_REQUEST_ERROR:
+		dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__,
+			__LINE__);
+		dump_sm_header(&header);
+		break;
 	default:
 		dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
 			__func__, __LINE__, header.service_id);
@@ -494,69 +567,19 @@
 }
 
 /**
- * ps3_sys_manager_work - Asyncronous read handler.
+ * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
  *
- * Signaled when a complete message arrives at the vuart port.
- */
-
-static void ps3_sys_manager_work(struct work_struct *work)
-{
-	struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
-
-	ps3_sys_manager_handle_msg(dev);
-	ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
-}
-
-struct {
-	struct ps3_vuart_port_device *dev;
-} static drv_priv;
-
-/**
- * ps3_sys_manager_restart - The final platform machine_restart routine.
- *
- * This routine never returns.  The routine disables asyncronous vuart reads
+ * This routine never returns.  The routine disables asynchronous vuart reads
  * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
  * the shutdown command sent from the system manager.  Soon after the
  * acknowledgement is sent the lpar is destroyed by the HV.  This routine
- * should only be called from ps3_restart().
+ * should only be called from ps3_power_off() through
+ * ps3_sys_manager_ops.power_off.
  */
 
-void ps3_sys_manager_restart(void)
+static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
 {
-	struct ps3_vuart_port_device *dev = drv_priv.dev;
-
-	BUG_ON(!drv_priv.dev);
-
-	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
-
-	ps3_vuart_cancel_async(dev);
-
-	ps3_sys_manager_send_attr(dev, 0);
-	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
-		PS3_SM_WAKE_DEFAULT);
-	ps3_sys_manager_send_request_shutdown(dev);
-
-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
-
-	while(1)
-		ps3_sys_manager_handle_msg(dev);
-}
-
-/**
- * ps3_sys_manager_power_off - The final platform machine_power_off routine.
- *
- * This routine never returns.  The routine disables asyncronous vuart reads
- * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
- * the shutdown command sent from the system manager.  Soon after the
- * acknowledgement is sent the lpar is destroyed by the HV.  This routine
- * should only be called from ps3_power_off().
- */
-
-void ps3_sys_manager_power_off(void)
-{
-	struct ps3_vuart_port_device *dev = drv_priv.dev;
-
-	BUG_ON(!drv_priv.dev);
+	BUG_ON(!dev);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
@@ -572,31 +595,97 @@
 		ps3_sys_manager_handle_msg(dev);
 }
 
-static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev)
+/**
+ * ps3_sys_manager_final_restart - The final platform machine_restart routine.
+ *
+ * This routine never returns.  The routine disables asynchronous vuart reads
+ * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
+ * the shutdown command sent from the system manager.  Soon after the
+ * acknowledgement is sent the lpar is destroyed by the HV.  This routine
+ * should only be called from ps3_restart() through ps3_sys_manager_ops.restart.
+ */
+
+static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
 {
-	int result;
+	BUG_ON(!dev);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	BUG_ON(drv_priv.dev);
-	drv_priv.dev = dev;
+	/* Check if we got here via a power button event. */
+
+	if (ps3_sm_force_power_off) {
+		dev_dbg(&dev->core, "%s:%d: forcing poweroff\n",
+			__func__, __LINE__);
+		ps3_sys_manager_final_power_off(dev);
+	}
+
+	ps3_vuart_cancel_async(dev);
+
+	ps3_sys_manager_send_attr(dev, 0);
+	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
+		PS3_SM_WAKE_DEFAULT);
+	ps3_sys_manager_send_request_shutdown(dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+
+	while(1)
+		ps3_sys_manager_handle_msg(dev);
+}
+
+/**
+ * ps3_sys_manager_work - Asynchronous read handler.
+ *
+ * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port.
+ */
+
+static void ps3_sys_manager_work(struct ps3_system_bus_device *dev)
+{
+	ps3_sys_manager_handle_msg(dev);
+	ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
+}
+
+static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
+{
+	int result;
+	struct ps3_sys_manager_ops ops;
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	ops.power_off = ps3_sys_manager_final_power_off;
+	ops.restart = ps3_sys_manager_final_restart;
+	ops.dev = dev;
+
+	/* ps3_sys_manager_register_ops copies ops. */
+
+	ps3_sys_manager_register_ops(&ops);
 
 	result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
 	BUG_ON(result);
 
-	result = ps3_vuart_read_async(dev, ps3_sys_manager_work,
-		PS3_SM_RX_MSG_LEN);
+	result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
 	BUG_ON(result);
 
 	return result;
 }
 
+static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev)
+{
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev)
+{
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+}
+
 static struct ps3_vuart_port_driver ps3_sys_manager = {
-	.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
-	.core = {
-		.name = "ps3_sys_manager",
-	},
+	.core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
+	.core.core.name = "ps3_sys_manager",
 	.probe = ps3_sys_manager_probe,
+	.remove = ps3_sys_manager_remove,
+	.shutdown = ps3_sys_manager_shutdown,
+	.work = ps3_sys_manager_work,
 };
 
 static int __init ps3_sys_manager_init(void)
@@ -608,3 +697,6 @@
 }
 
 module_init(ps3_sys_manager_init);
+/* Module remove not supported. */
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER);
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index ec2d36a..bea25a1 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -71,6 +71,34 @@
 };
 
 /**
+ * struct ps3_vuart_port_priv - private vuart device data.
+ */
+
+struct ps3_vuart_port_priv {
+	u64 interrupt_mask;
+
+	struct {
+		spinlock_t lock;
+		struct list_head head;
+	} tx_list;
+	struct {
+		struct ps3_vuart_work work;
+		unsigned long bytes_held;
+		spinlock_t lock;
+		struct list_head head;
+	} rx_list;
+	struct ps3_vuart_stats stats;
+};
+
+static struct ps3_vuart_port_priv *to_port_priv(
+	struct ps3_system_bus_device *dev)
+{
+	BUG_ON(!dev);
+	BUG_ON(!dev->driver_priv);
+	return (struct ps3_vuart_port_priv *)dev->driver_priv;
+}
+
+/**
  * struct ports_bmp - bitmap indicating ports needing service.
  *
  * A 256 bit read only bitmap indicating ports needing service.  Do not write
@@ -83,31 +111,14 @@
 } __attribute__ ((aligned (32)));
 
 #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_ports_bmp(
+static void __maybe_unused _dump_ports_bmp(
 	const struct ports_bmp* bmp, const char* func, int line)
 {
 	pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
 }
 
-static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
-	unsigned int *port_number)
-{
-	switch(match_id) {
-	case PS3_MATCH_ID_AV_SETTINGS:
-		*port_number = 0;
-		return 0;
-	case PS3_MATCH_ID_SYSTEM_MANAGER:
-		*port_number = 2;
-		return 0;
-	default:
-		WARN_ON(1);
-		*port_number = UINT_MAX;
-		return -EINVAL;
-	};
-}
-
 #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number,
+static void __maybe_unused _dump_port_params(unsigned int port_number,
 	const char* func, int line)
 {
 #if defined(DEBUG)
@@ -144,14 +155,14 @@
 	unsigned long tx;
 };
 
-int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
+int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
 	struct vuart_triggers *trig)
 {
 	int result;
 	unsigned long size;
 	unsigned long val;
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_TX_TRIGGER, &trig->tx);
 
 	if (result) {
@@ -160,7 +171,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BUF_SIZE, &size);
 
 	if (result) {
@@ -169,7 +180,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_TRIGGER, &val);
 
 	if (result) {
@@ -186,13 +197,13 @@
 	return result;
 }
 
-int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
+int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
 	unsigned int rx)
 {
 	int result;
 	unsigned long size;
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
+	result = lv1_set_virtual_uart_param(dev->port_number,
 		PARAM_TX_TRIGGER, tx);
 
 	if (result) {
@@ -201,7 +212,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BUF_SIZE, &size);
 
 	if (result) {
@@ -210,7 +221,7 @@
 		return result;
 	}
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
+	result = lv1_set_virtual_uart_param(dev->port_number,
 		PARAM_RX_TRIGGER, size - rx);
 
 	if (result) {
@@ -225,10 +236,12 @@
 	return result;
 }
 
-static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
 	u64 *bytes_waiting)
 {
-	int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	int result;
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BYTES, bytes_waiting);
 
 	if (result)
@@ -240,17 +253,24 @@
 	return result;
 }
 
-static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
+/**
+ * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables.
+ */
+
+static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev,
 	unsigned long mask)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
 	dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
 
-	dev->priv->interrupt_mask = mask;
+	priv->interrupt_mask = mask;
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
-		PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask);
+	result = lv1_set_virtual_uart_param(dev->port_number,
+		PARAM_INTERRUPT_MASK, priv->interrupt_mask);
 
 	if (result)
 		dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -259,79 +279,96 @@
 	return result;
 }
 
-static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
 	unsigned long *status)
 {
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	u64 tmp;
-	int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_INTERRUPT_STATUS, &tmp);
 
 	if (result)
 		dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	*status = tmp & dev->priv->interrupt_mask;
+	*status = tmp & priv->interrupt_mask;
 
 	dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
-		__func__, __LINE__, dev->priv->interrupt_mask, tmp, *status);
+		__func__, __LINE__, priv->interrupt_mask, tmp, *status);
 
 	return result;
 }
 
-int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_TX);
 }
 
-int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_RX);
 }
 
-int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_DISCONNECT);
 }
 
-int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_TX)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_TX) : 0;
 }
 
-int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_RX)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_RX) : 0;
 }
 
-int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_DISCONNECT) : 0;
 }
 
 /**
  * ps3_vuart_raw_write - Low level write helper.
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
  */
 
-static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
 	const void* buf, unsigned int bytes, unsigned long *bytes_written)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
-	result = lv1_write_virtual_uart(dev->priv->port_number,
+	result = lv1_write_virtual_uart(dev->port_number,
 		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
 
 	if (result) {
@@ -340,28 +377,30 @@
 		return result;
 	}
 
-	dev->priv->stats.bytes_written += *bytes_written;
+	priv->stats.bytes_written += *bytes_written;
 
 	dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
-		*bytes_written, bytes, dev->priv->stats.bytes_written);
+		*bytes_written, bytes, priv->stats.bytes_written);
 
 	return result;
 }
 
 /**
  * ps3_vuart_raw_read - Low level read helper.
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
  */
 
-static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
+static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes, unsigned long *bytes_read)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
 	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
 
-	result = lv1_read_virtual_uart(dev->priv->port_number,
+	result = lv1_read_virtual_uart(dev->port_number,
 		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
 
 	if (result) {
@@ -370,25 +409,27 @@
 		return result;
 	}
 
-	dev->priv->stats.bytes_read += *bytes_read;
+	priv->stats.bytes_read += *bytes_read;
 
 	dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
-		*bytes_read, bytes, dev->priv->stats.bytes_read);
+		*bytes_read, bytes, priv->stats.bytes_read);
 
 	return result;
 }
 
 /**
  * ps3_vuart_clear_rx_bytes - Discard bytes received.
+ * @dev: The struct ps3_system_bus_device instance.
  * @bytes: Max byte count to discard, zero = all pending.
  *
  * Used to clear pending rx interrupt source.  Will not block.
  */
 
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
 	unsigned int bytes)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	u64 bytes_waiting;
 	void* tmp;
 
@@ -418,8 +459,9 @@
 
 	/* Don't include these bytes in the stats. */
 
-	dev->priv->stats.bytes_read -= bytes_waiting;
+	priv->stats.bytes_read -= bytes_waiting;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes);
 
 /**
  * struct list_buffer - An element for a port device fifo buffer list.
@@ -435,6 +477,7 @@
 
 /**
  * ps3_vuart_write - the entry point for writing data to a port
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * If the port is idle on entry as much of the incoming data is written to
  * the port as the port will accept.  Otherwise a list buffer is created
@@ -442,25 +485,26 @@
  * then enqueued for transmision via the transmit interrupt.
  */
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
 	unsigned int bytes)
 {
 	static unsigned long dbg_number;
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb;
 
 	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
 		bytes, bytes);
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
 
-	if (list_empty(&dev->priv->tx_list.head)) {
+	if (list_empty(&priv->tx_list.head)) {
 		unsigned long bytes_written;
 
 		result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
 
-		spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+		spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 		if (result) {
 			dev_dbg(&dev->core,
@@ -478,7 +522,7 @@
 		bytes -= bytes_written;
 		buf += bytes_written;
 	} else
-		spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+		spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
 
@@ -491,29 +535,86 @@
 	lb->tail = lb->data + bytes;
 	lb->dbg_number = ++dbg_number;
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
-	list_add_tail(&lb->link, &dev->priv->tx_list.head);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
+	list_add_tail(&lb->link, &priv->tx_list.head);
 	ps3_vuart_enable_interrupt_tx(dev);
-	spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 	dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
 		__func__, __LINE__, lb->dbg_number, bytes);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_write);
 
 /**
- * ps3_vuart_read - the entry point for reading data from a port
+ * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bytes_queued: Number of bytes queued to the buffer list.
  *
- * If enough bytes to satisfy the request are held in the buffer list those
- * bytes are dequeued and copied to the caller's buffer.  Emptied list buffers
- * are retiered.  If the request cannot be statified by bytes held in the list
- * buffers -EAGAIN is returned.
+ * Must be called with priv->rx_list.lock held.
  */
 
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
+	u64 *bytes_queued)
+{
+	static unsigned long dbg_number;
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+	struct list_buffer *lb;
+	u64 bytes;
+
+	*bytes_queued = 0;
+
+	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+	BUG_ON(result);
+
+	if (result)
+		return -EIO;
+
+	if (!bytes)
+		return 0;
+
+	/* Add some extra space for recently arrived data. */
+
+	bytes += 128;
+
+	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+
+	if (!lb)
+		return -ENOMEM;
+
+	ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
+
+	lb->head = lb->data;
+	lb->tail = lb->data + bytes;
+	lb->dbg_number = ++dbg_number;
+
+	list_add_tail(&lb->link, &priv->rx_list.head);
+	priv->rx_list.bytes_held += bytes;
+
+	dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
+		__func__, __LINE__, lb->dbg_number, bytes);
+
+	*bytes_queued = bytes;
+
+	return 0;
+}
+
+/**
+ * ps3_vuart_read - The entry point for reading data from a port.
+ *
+ * Queue data waiting at the port, and if enough bytes to satisfy the request
+ * are held in the buffer list those bytes are dequeued and copied to the
+ * caller's buffer.  Emptied list buffers are retiered.  If the request cannot
+ * be statified by bytes held in the list buffers -EAGAIN is returned.
+ */
+
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes)
 {
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb, *n;
 	unsigned long bytes_read;
@@ -521,30 +622,37 @@
 	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
 		bytes, bytes);
 
-	spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
 
-	if (dev->priv->rx_list.bytes_held < bytes) {
-		spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-		dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
-			__func__, __LINE__,
-			bytes - dev->priv->rx_list.bytes_held);
-		return -EAGAIN;
+	/* Queue rx bytes here for polled reads. */
+
+	while (priv->rx_list.bytes_held < bytes) {
+		u64 tmp;
+
+		result = ps3_vuart_queue_rx_bytes(dev, &tmp);
+		if (result || !tmp) {
+			dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
+				__func__, __LINE__,
+				bytes - priv->rx_list.bytes_held);
+			spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+			return -EAGAIN;
+		}
 	}
 
-	list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) {
+	list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) {
 		bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
 
 		memcpy(buf, lb->head, bytes_read);
 		buf += bytes_read;
 		bytes -= bytes_read;
-		dev->priv->rx_list.bytes_held -= bytes_read;
+		priv->rx_list.bytes_held -= bytes_read;
 
 		if (bytes_read < lb->tail - lb->head) {
 			lb->head += bytes_read;
 			dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
 				"bytes\n", __func__, __LINE__, lb->dbg_number,
 				bytes_read);
-			spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+			spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 			return 0;
 		}
 
@@ -556,16 +664,32 @@
 		kfree(lb);
 	}
 
-	spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_read);
 
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
-	unsigned int bytes)
+/**
+ * ps3_vuart_work - Asynchronous read handler.
+ */
+
+static void ps3_vuart_work(struct work_struct *work)
 {
+	struct ps3_system_bus_device *dev =
+		ps3_vuart_work_to_system_bus_dev(work);
+	struct ps3_vuart_port_driver *drv =
+		ps3_system_bus_dev_to_vuart_drv(dev);
+
+	BUG_ON(!drv);
+	drv->work(dev);
+}
+
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
+{
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 
-	if(dev->priv->work.trigger) {
+	if (priv->rx_list.work.trigger) {
 		dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
 			__func__, __LINE__);
 		return -EAGAIN;
@@ -573,30 +697,32 @@
 
 	BUG_ON(!bytes);
 
-	PREPARE_WORK(&dev->priv->work.work, func);
+	PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
 
-	spin_lock_irqsave(&dev->priv->work.lock, flags);
-	if(dev->priv->rx_list.bytes_held >= bytes) {
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
+	if (priv->rx_list.bytes_held >= bytes) {
 		dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
 			__func__, __LINE__, bytes);
-		schedule_work(&dev->priv->work.work);
-		spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+		schedule_work(&priv->rx_list.work.work);
+		spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 		return 0;
 	}
 
-	dev->priv->work.trigger = bytes;
-	spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+	priv->rx_list.work.trigger = bytes;
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 
 	dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
 		__LINE__, bytes, bytes);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_read_async);
 
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev)
 {
-	dev->priv->work.trigger = 0;
+	to_port_priv(dev)->rx_list.work.trigger = 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async);
 
 /**
  * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
@@ -606,18 +732,19 @@
  * adjusts the final list buffer state for a partial write.
  */
 
-static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
 {
 	int result = 0;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb, *n;
 	unsigned long bytes_total = 0;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
 
-	list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) {
+	list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
 
 		unsigned long bytes_written;
 
@@ -651,7 +778,7 @@
 
 	ps3_vuart_disable_interrupt_tx(dev);
 port_full:
-	spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 	dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
 		__func__, __LINE__, bytes_total);
 	return result;
@@ -665,60 +792,37 @@
  * buffer list.  Buffer list data is dequeued via ps3_vuart_read.
  */
 
-static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	static unsigned long dbg_number;
-	int result = 0;
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
-	struct list_buffer *lb;
-	unsigned long bytes;
+	u64 bytes;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
+	result = ps3_vuart_queue_rx_bytes(dev, &bytes);
 
-	if (result)
-		return -EIO;
-
-	BUG_ON(!bytes);
-
-	/* Add some extra space for recently arrived data. */
-
-	bytes += 128;
-
-	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
-
-	if (!lb)
-		return -ENOMEM;
-
-	ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
-
-	lb->head = lb->data;
-	lb->tail = lb->data + bytes;
-	lb->dbg_number = ++dbg_number;
-
-	spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
-	list_add_tail(&lb->link, &dev->priv->rx_list.head);
-	dev->priv->rx_list.bytes_held += bytes;
-	spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-
-	dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
-		__func__, __LINE__, lb->dbg_number, bytes);
-
-	spin_lock_irqsave(&dev->priv->work.lock, flags);
-	if(dev->priv->work.trigger
-		&& dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
-		dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
-			__func__, __LINE__, dev->priv->work.trigger);
-		dev->priv->work.trigger = 0;
-		schedule_work(&dev->priv->work.work);
+	if (result) {
+		spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+		return result;
 	}
-	spin_unlock_irqrestore(&dev->priv->work.lock, flags);
-	return 0;
+
+	if (priv->rx_list.work.trigger && priv->rx_list.bytes_held
+		>= priv->rx_list.work.trigger) {
+		dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
+			__func__, __LINE__, priv->rx_list.work.trigger);
+		priv->rx_list.work.trigger = 0;
+		schedule_work(&priv->rx_list.work.work);
+	}
+
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+	return result;
 }
 
 static int ps3_vuart_handle_interrupt_disconnect(
-	struct ps3_vuart_port_device *dev)
+	struct ps3_system_bus_device *dev)
 {
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 	BUG_ON("no support");
@@ -733,9 +837,10 @@
  * stage handler after one iteration.
  */
 
-static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long status;
 
 	result = ps3_vuart_get_interrupt_status(dev, &status);
@@ -747,21 +852,21 @@
 		status);
 
 	if (status & INTERRUPT_MASK_DISCONNECT) {
-		dev->priv->stats.disconnect_interrupts++;
+		priv->stats.disconnect_interrupts++;
 		result = ps3_vuart_handle_interrupt_disconnect(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_disconnect(dev);
 	}
 
 	if (status & INTERRUPT_MASK_TX) {
-		dev->priv->stats.tx_interrupts++;
+		priv->stats.tx_interrupts++;
 		result = ps3_vuart_handle_interrupt_tx(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_tx(dev);
 	}
 
 	if (status & INTERRUPT_MASK_RX) {
-		dev->priv->stats.rx_interrupts++;
+		priv->stats.rx_interrupts++;
 		result = ps3_vuart_handle_interrupt_rx(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_rx(dev);
@@ -771,11 +876,11 @@
 }
 
 struct vuart_bus_priv {
-	const struct ports_bmp bmp;
+	struct ports_bmp *bmp;
 	unsigned int virq;
 	struct semaphore probe_mutex;
 	int use_count;
-	struct ps3_vuart_port_device *devices[PORT_COUNT];
+	struct ps3_system_bus_device *devices[PORT_COUNT];
 } static vuart_bus_priv;
 
 /**
@@ -788,17 +893,16 @@
 
 static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
 {
-	struct vuart_bus_priv *bus_priv;
+	struct vuart_bus_priv *bus_priv = _private;
 
-	BUG_ON(!_private);
-	bus_priv = (struct vuart_bus_priv *)_private;
+	BUG_ON(!bus_priv);
 
 	while (1) {
 		unsigned int port;
 
-		dump_ports_bmp(&bus_priv->bmp);
+		dump_ports_bmp(bus_priv->bmp);
 
-		port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status);
+		port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status);
 
 		if (port == BITS_PER_LONG)
 			break;
@@ -812,100 +916,144 @@
 	return IRQ_HANDLED;
 }
 
-static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
+static int ps3_vuart_bus_interrupt_get(void)
 {
 	int result;
-	struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
 
-	result = dev->match_id == drv->match_id;
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 
-	dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__,
-		__LINE__, dev->match_id, dev->core.bus_id, drv->match_id,
-		drv->core.name, (result ? "match" : "miss"));
+	vuart_bus_priv.use_count++;
 
+	BUG_ON(vuart_bus_priv.use_count > 2);
+
+	if (vuart_bus_priv.use_count != 1) {
+		return 0;
+	}
+
+	BUG_ON(vuart_bus_priv.bmp);
+
+	vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL);
+
+	if (!vuart_bus_priv.bmp) {
+		pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__);
+		result = -ENOMEM;
+		goto fail_bmp_malloc;
+	}
+
+	result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp,
+		&vuart_bus_priv.virq);
+
+	if (result) {
+		pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n",
+			__func__, __LINE__, result);
+		result = -EPERM;
+		goto fail_alloc_irq;
+	}
+
+	result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
+		IRQF_DISABLED, "vuart", &vuart_bus_priv);
+
+	if (result) {
+		pr_debug("%s:%d: request_irq failed (%d)\n",
+			__func__, __LINE__, result);
+		goto fail_request_irq;
+	}
+
+	pr_debug(" <- %s:%d: ok\n", __func__, __LINE__);
+	return result;
+
+fail_request_irq:
+	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+	vuart_bus_priv.virq = NO_IRQ;
+fail_alloc_irq:
+	kfree(vuart_bus_priv.bmp);
+	vuart_bus_priv.bmp = NULL;
+fail_bmp_malloc:
+	vuart_bus_priv.use_count--;
+	pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
 	return result;
 }
 
-static int ps3_vuart_probe(struct device *_dev)
+static int ps3_vuart_bus_interrupt_put(void)
+{
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	vuart_bus_priv.use_count--;
+
+	BUG_ON(vuart_bus_priv.use_count < 0);
+
+	if (vuart_bus_priv.use_count != 0)
+		return 0;
+
+	free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
+
+	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+	vuart_bus_priv.virq = NO_IRQ;
+
+	kfree(vuart_bus_priv.bmp);
+	vuart_bus_priv.bmp = NULL;
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
 {
 	int result;
-	unsigned int port_number;
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
+	struct ps3_vuart_port_driver *drv;
+	struct ps3_vuart_port_priv *priv = NULL;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+	dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
+		drv->core.core.name);
+
 	BUG_ON(!drv);
 
+	if (dev->port_number >= PORT_COUNT) {
+		BUG();
+		return -EINVAL;
+	}
+
 	down(&vuart_bus_priv.probe_mutex);
 
-	/* Setup vuart_bus_priv.devices[]. */
+	result = ps3_vuart_bus_interrupt_get();
 
-	result = ps3_vuart_match_id_to_port(dev->match_id,
-		&port_number);
+	if (result)
+		goto fail_setup_interrupt;
 
-	if (result) {
-		dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
-			__func__, __LINE__, dev->match_id);
-		result = -EINVAL;
-		goto fail_match;
-	}
-
-	if (vuart_bus_priv.devices[port_number]) {
+	if (vuart_bus_priv.devices[dev->port_number]) {
 		dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
-			__LINE__, port_number);
+			__LINE__, dev->port_number);
 		result = -EBUSY;
-		goto fail_match;
+		goto fail_busy;
 	}
 
-	vuart_bus_priv.devices[port_number] = dev;
+	vuart_bus_priv.devices[dev->port_number] = dev;
 
-	/* Setup dev->priv. */
+	/* Setup dev->driver_priv. */
 
-	dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL);
+	dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv),
+		GFP_KERNEL);
 
-	if (!dev->priv) {
+	if (!dev->driver_priv) {
 		result = -ENOMEM;
-		goto fail_alloc;
+		goto fail_dev_malloc;
 	}
 
-	dev->priv->port_number = port_number;
+	priv = to_port_priv(dev);
 
-	INIT_LIST_HEAD(&dev->priv->tx_list.head);
-	spin_lock_init(&dev->priv->tx_list.lock);
+	INIT_LIST_HEAD(&priv->tx_list.head);
+	spin_lock_init(&priv->tx_list.lock);
 
-	INIT_LIST_HEAD(&dev->priv->rx_list.head);
-	spin_lock_init(&dev->priv->rx_list.lock);
+	INIT_LIST_HEAD(&priv->rx_list.head);
+	spin_lock_init(&priv->rx_list.lock);
 
-	INIT_WORK(&dev->priv->work.work, NULL);
-	spin_lock_init(&dev->priv->work.lock);
-	dev->priv->work.trigger = 0;
-	dev->priv->work.dev = dev;
-
-	if (++vuart_bus_priv.use_count == 1) {
-
-		result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY,
-			(void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
-
-		if (result) {
-			dev_dbg(&dev->core,
-				"%s:%d: ps3_vuart_irq_setup failed (%d)\n",
-				__func__, __LINE__, result);
-			result = -EPERM;
-			goto fail_alloc_irq;
-		}
-
-		result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
-			IRQF_DISABLED, "vuart", &vuart_bus_priv);
-
-		if (result) {
-			dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
-				__func__, __LINE__, result);
-			goto fail_request_irq;
-		}
-	}
+	INIT_WORK(&priv->rx_list.work.work, NULL);
+	priv->rx_list.work.trigger = 0;
+	priv->rx_list.work.dev = dev;
 
 	/* clear stale pending interrupts */
 
@@ -936,152 +1084,160 @@
 
 fail_probe:
 	ps3_vuart_set_interrupt_mask(dev, 0);
-fail_request_irq:
-	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
-	vuart_bus_priv.virq = NO_IRQ;
-fail_alloc_irq:
-	--vuart_bus_priv.use_count;
-	kfree(dev->priv);
-	dev->priv = NULL;
-fail_alloc:
-	vuart_bus_priv.devices[port_number] = NULL;
-fail_match:
+	kfree(dev->driver_priv);
+	dev->driver_priv = NULL;
+fail_dev_malloc:
+	vuart_bus_priv.devices[dev->port_number] = NULL;
+fail_busy:
+	ps3_vuart_bus_interrupt_put();
+fail_setup_interrupt:
 	up(&vuart_bus_priv.probe_mutex);
-	dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
+	dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__);
 	return result;
 }
 
-static int ps3_vuart_remove(struct device *_dev)
+/**
+ * ps3_vuart_cleanup - common cleanup helper.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans interrupts and HV resources.  Must be called with
+ * vuart_bus_priv.probe_mutex held.  Used by ps3_vuart_remove and
+ * ps3_vuart_shutdown.  After this call, polled reading will still work.
+ */
+
+static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev)
 {
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	ps3_vuart_cancel_async(dev);
+	ps3_vuart_set_interrupt_mask(dev, 0);
+	ps3_vuart_bus_interrupt_put();
+	return 0;
+}
+
+/**
+ * ps3_vuart_remove - Completely clean the device instance.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans all memory, interrupts and HV resources.  After this call the
+ * device can no longer be used.
+ */
+
+static int ps3_vuart_remove(struct ps3_system_bus_device *dev)
+{
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+	struct ps3_vuart_port_driver *drv;
+
+	BUG_ON(!dev);
 
 	down(&vuart_bus_priv.probe_mutex);
 
-	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
-		dev->core.bus_id);
+	dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+		dev->match_id);
 
-	BUG_ON(vuart_bus_priv.use_count < 1);
-
-	if (drv->remove)
-		drv->remove(dev);
-	else
-		dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
-			__LINE__, dev->core.bus_id);
-
-	vuart_bus_priv.devices[dev->priv->port_number] = NULL;
-
-	if (--vuart_bus_priv.use_count == 0) {
-		BUG();
-		free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
-		ps3_vuart_irq_destroy(vuart_bus_priv.virq);
-		vuart_bus_priv.virq = NO_IRQ;
+	if (!dev->core.driver) {
+		dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+			__LINE__);
+		up(&vuart_bus_priv.probe_mutex);
+		return 0;
 	}
 
-	kfree(dev->priv);
-	dev->priv = NULL;
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+	BUG_ON(!drv);
+
+	if (drv->remove) {
+		drv->remove(dev);
+	} else {
+		dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__,
+		__LINE__);
+		BUG();
+	}
+
+	ps3_vuart_cleanup(dev);
+
+	vuart_bus_priv.devices[dev->port_number] = NULL;
+	kfree(priv);
+	priv = NULL;
+
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+	up(&vuart_bus_priv.probe_mutex);
+	return 0;
+}
+
+/**
+ * ps3_vuart_shutdown - Cleans interrupts and HV resources.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans interrupts and HV resources.  After this call the
+ * device can still be used in polling mode.  This behavior required
+ * by sys-manager to be able to complete the device power operation
+ * sequence.
+ */
+
+static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev)
+{
+	struct ps3_vuart_port_driver *drv;
+
+	BUG_ON(!dev);
+
+	down(&vuart_bus_priv.probe_mutex);
+
+	dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+		dev->match_id);
+
+	if (!dev->core.driver) {
+		dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+			__LINE__);
+		up(&vuart_bus_priv.probe_mutex);
+		return 0;
+	}
+
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+	BUG_ON(!drv);
+
+	if (drv->shutdown)
+		drv->shutdown(dev);
+	else if (drv->remove) {
+		dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n",
+			__func__, __LINE__);
+		drv->remove(dev);
+	} else {
+		dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__,
+			__LINE__);
+		BUG();
+	}
+
+	ps3_vuart_cleanup(dev);
+
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
 	up(&vuart_bus_priv.probe_mutex);
 	return 0;
 }
 
-static void ps3_vuart_shutdown(struct device *_dev)
+static int __init ps3_vuart_bus_init(void)
 {
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
-
-	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
-		dev->core.bus_id);
-
-	if (drv->shutdown)
-		drv->shutdown(dev);
-	else
-		dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
-			__LINE__, dev->core.bus_id);
-}
-
-/**
- * ps3_vuart_bus - The vuart bus instance.
- *
- * The vuart is managed as a bus that port devices connect to.
- */
-
-struct bus_type ps3_vuart_bus = {
-        .name = "ps3_vuart",
-	.match = ps3_vuart_match,
-	.probe = ps3_vuart_probe,
-	.remove = ps3_vuart_remove,
-	.shutdown = ps3_vuart_shutdown,
-};
-
-int __init ps3_vuart_bus_init(void)
-{
-	int result;
-
 	pr_debug("%s:%d:\n", __func__, __LINE__);
 
 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 		return -ENODEV;
 
 	init_MUTEX(&vuart_bus_priv.probe_mutex);
-	result = bus_register(&ps3_vuart_bus);
-	BUG_ON(result);
 
-	return result;
+	return 0;
 }
 
-void __exit ps3_vuart_bus_exit(void)
+static void __exit ps3_vuart_bus_exit(void)
 {
 	pr_debug("%s:%d:\n", __func__, __LINE__);
-	bus_unregister(&ps3_vuart_bus);
 }
 
 core_initcall(ps3_vuart_bus_init);
 module_exit(ps3_vuart_bus_exit);
 
 /**
- * ps3_vuart_port_release_device - Remove a vuart port device.
- */
-
-static void ps3_vuart_port_release_device(struct device *_dev)
-{
-#if defined(DEBUG)
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-
-	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
-
-	BUG_ON(dev->priv && "forgot to free");
-	memset(&dev->core, 0, sizeof(dev->core));
-#endif
-}
-
-/**
- * ps3_vuart_port_device_register - Add a vuart port device.
- */
-
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
-{
-	static unsigned int dev_count = 1;
-
-	BUG_ON(dev->priv && "forgot to free");
-
-	dev->core.parent = NULL;
-	dev->core.bus = &ps3_vuart_bus;
-	dev->core.release = ps3_vuart_port_release_device;
-
-	snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
-		dev_count++);
-
-	dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
-
-	return device_register(&dev->core);
-}
-
-EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
-
-/**
  * ps3_vuart_port_driver_register - Add a vuart port device driver.
  */
 
@@ -1089,12 +1245,18 @@
 {
 	int result;
 
-	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-	drv->core.bus = &ps3_vuart_bus;
-	result = driver_register(&drv->core);
+	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+
+	BUG_ON(!drv->core.match_id);
+	BUG_ON(!drv->core.core.name);
+
+	drv->core.probe = ps3_vuart_probe;
+	drv->core.remove = ps3_vuart_remove;
+	drv->core.shutdown = ps3_vuart_shutdown;
+
+	result = ps3_system_bus_driver_register(&drv->core);
 	return result;
 }
-
 EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
 
 /**
@@ -1103,8 +1265,7 @@
 
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
 {
-	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-	driver_unregister(&drv->core);
+	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+	ps3_system_bus_driver_unregister(&drv->core);
 }
-
 EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
index 1be992d..eb7f6d9 100644
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -34,29 +34,7 @@
 struct ps3_vuart_work {
 	struct work_struct work;
 	unsigned long trigger;
-	spinlock_t lock;
-	struct ps3_vuart_port_device* dev; /* to convert work to device */
-};
-
-/**
- * struct ps3_vuart_port_priv - private vuart device data.
- */
-
-struct ps3_vuart_port_priv {
-	unsigned int port_number;
-	u64 interrupt_mask;
-
-	struct {
-		spinlock_t lock;
-		struct list_head head;
-	} tx_list;
-	struct {
-		unsigned long bytes_held;
-		spinlock_t lock;
-		struct list_head head;
-	} rx_list;
-	struct ps3_vuart_stats stats;
-	struct ps3_vuart_work work;
+	struct ps3_system_bus_device *dev; /* to convert work to device */
 };
 
 /**
@@ -64,32 +42,30 @@
  */
 
 struct ps3_vuart_port_driver {
-	enum ps3_match_id match_id;
-	struct device_driver core;
-	int (*probe)(struct ps3_vuart_port_device *);
-	int (*remove)(struct ps3_vuart_port_device *);
-	void (*shutdown)(struct ps3_vuart_port_device *);
-	int (*tx_event)(struct ps3_vuart_port_device *dev);
-	int (*rx_event)(struct ps3_vuart_port_device *dev);
-	int (*disconnect_event)(struct ps3_vuart_port_device *dev);
-	/* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */
-	/* int (*resume)(struct ps3_vuart_port_device *); */
+	struct ps3_system_bus_driver core;
+	int (*probe)(struct ps3_system_bus_device *);
+	int (*remove)(struct ps3_system_bus_device *);
+	void (*shutdown)(struct ps3_system_bus_device *);
+	void (*work)(struct ps3_system_bus_device *);
+	/* int (*tx_event)(struct ps3_system_bus_device *dev); */
+	/* int (*rx_event)(struct ps3_system_bus_device *dev); */
+	/* int (*disconnect_event)(struct ps3_system_bus_device *dev); */
+	/* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
+	/* int (*resume)(struct ps3_system_bus_device *); */
 };
 
 int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
 
-static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
-	struct device_driver *_drv)
+static inline struct ps3_vuart_port_driver *
+	ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev)
 {
-	return container_of(_drv, struct ps3_vuart_port_driver, core);
+	struct ps3_system_bus_driver *sbd =
+		ps3_system_bus_dev_to_system_bus_drv(_dev);
+	BUG_ON(!sbd);
+	return container_of(sbd, struct ps3_vuart_port_driver, core);
 }
-static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
-	struct device *_dev)
-{
-	return container_of(_dev, struct ps3_vuart_port_device, core);
-}
-static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
+static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev(
 	struct work_struct *_work)
 {
 	struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
@@ -97,14 +73,13 @@
 	return vw->dev;
 }
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
 	unsigned int bytes);
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes);
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
-	unsigned int bytes);
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev);
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes);
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev);
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
 	unsigned int bytes);
 
 #endif
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index eed9143..659e311 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -67,7 +67,8 @@
 };
 
 static ssize_t
-rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+		char *buf, loff_t off, size_t count)
 {
 	struct rio_dev *dev =
 	    to_rio_dev(container_of(kobj, struct device, kobj));
@@ -137,7 +138,8 @@
 }
 
 static ssize_t
-rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+		 char *buf, loff_t off, size_t count)
 {
 	struct rio_dev *dev =
 	    to_rio_dev(container_of(kobj, struct device, kobj));
@@ -197,7 +199,6 @@
 	.attr = {
 		 .name = "config",
 		 .mode = S_IRUGO | S_IWUSR,
-		 .owner = THIS_MODULE,
 		 },
 	.size = 0x200000,
 	.read = rio_read_config,
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4e4c10a..cea401f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -10,7 +10,6 @@
 
 config RTC_CLASS
 	tristate "RTC class"
-	depends on EXPERIMENTAL
 	default n
 	select RTC_LIB
 	help
@@ -119,7 +118,7 @@
 	  will be called rtc-test.
 
 comment "I2C RTC drivers"
-	depends on RTC_CLASS
+	depends on RTC_CLASS && I2C
 
 config RTC_DRV_DS1307
 	tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00"
@@ -160,11 +159,11 @@
 	  will be called rtc-max6900.
 
 config RTC_DRV_RS5C372
-	tristate "Ricoh RS5C372A/B"
+	tristate "Ricoh RS5C372A/B, RV5C386, RV5C387A"
 	depends on RTC_CLASS && I2C
 	help
 	  If you say yes here you get support for the
-	  Ricoh RS5C372A and RS5C372B RTC chips.
+	  Ricoh RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-rs5c372.
@@ -213,12 +212,40 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf8583.
 
+config RTC_DRV_M41T80
+	tristate "ST M41T80 series RTC"
+	depends on RTC_CLASS && I2C
+	help
+	  If you say Y here you will get support for the
+	  ST M41T80 RTC chips series. Currently following chips are
+	  supported: M41T80, M41T81, M41T82, M41T83, M41ST84, M41ST85
+	  and M41ST87.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-m41t80.
+
+config RTC_DRV_M41T80_WDT
+	bool "ST M41T80 series RTC watchdog timer"
+	depends on RTC_DRV_M41T80
+	help
+	  If you say Y here you will get support for the
+	  watchdog timer in ST M41T80 RTC chips series.
+
+config RTC_DRV_TWL92330
+	boolean "TI TWL92330/Menelaus"
+	depends on RTC_CLASS && I2C && MENELAUS
+	help
+	  If you say yes here you get support for the RTC on the
+	  TWL92330 "Menelaus" power mangement chip, used with OMAP2
+	  platforms.  The support is integrated with the rest of
+	  the Menelaus driver; it's not separate module.
+
 comment "SPI RTC drivers"
-	depends on RTC_CLASS
+	depends on RTC_CLASS && SPI_MASTER
 
 config RTC_DRV_RS5C348
 	tristate "Ricoh RS5C348A/B"
-	depends on RTC_CLASS && SPI
+	depends on RTC_CLASS && SPI_MASTER
 	help
 	  If you say yes here you get support for the
 	  Ricoh RS5C348A and RS5C348B RTC chips.
@@ -228,7 +255,7 @@
 
 config RTC_DRV_MAX6902
 	tristate "Maxim 6902"
-	depends on RTC_CLASS && SPI
+	depends on RTC_CLASS && SPI_MASTER
 	help
 	  If you say yes here you will get support for the
 	  Maxim MAX6902 SPI RTC chip.
@@ -246,7 +273,7 @@
 config RTC_DRV_CMOS
 	tristate "PC-style 'CMOS'"
 	depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
-		|| M32R || ATARI || POWERPC || MIPS)
+		|| M32R || ATARI || PPC || MIPS)
 	help
 	  Say "yes" here to get direct support for the real time clock
 	  found in every PC or ACPI-based system, and some other boards.
@@ -262,6 +289,12 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-cmos.
 
+config RTC_DRV_DS1216
+	tristate "Dallas DS1216"
+	depends on RTC_CLASS && SNI_RM
+	help
+	  If you say yes here you get support for the Dallas DS1216 RTC chips.
+
 config RTC_DRV_DS1553
 	tristate "Dallas DS1553"
 	depends on RTC_CLASS
@@ -292,6 +325,16 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-m48t86.
 
+config RTC_DRV_M48T59
+	tristate "ST M48T59"
+	depends on RTC_CLASS
+	help
+	  If you say Y here you will get support for the
+	  ST M48T59 RTC chip.
+
+	  This driver can also be built as a module, if so, the module
+	  will be called "rtc-m48t59".
+
 config RTC_DRV_V3020
 	tristate "EM Microelectronic V3020"
 	depends on RTC_CLASS
@@ -379,6 +422,13 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called rtc-pl031.
 
+config RTC_DRV_AT32AP700X
+	tristate "AT32AP700X series RTC"
+	depends on RTC_CLASS && PLATFORM_AT32AP
+	help
+	  Driver for the internal RTC (Realtime Clock) on Atmel AVR32
+	  AT32AP700x family processors.
+
 config RTC_DRV_AT91RM9200
 	tristate "AT91RM9200"
 	depends on RTC_CLASS && ARCH_AT91RM9200
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index a1afbc2..3109af9 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
+obj-$(CONFIG_RTC_DRV_AT32AP700X)	+= rtc-at32ap700x.o
 obj-$(CONFIG_RTC_DRV_DS1307)	+= rtc-ds1307.o
 obj-$(CONFIG_RTC_DRV_DS1672)	+= rtc-ds1672.o
 obj-$(CONFIG_RTC_DRV_DS1742)	+= rtc-ds1742.o
@@ -28,6 +29,7 @@
 obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
 obj-$(CONFIG_RTC_DRV_S3C)	+= rtc-s3c.o
 obj-$(CONFIG_RTC_DRV_RS5C348)	+= rtc-rs5c348.o
+obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M48T86)	+= rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_DS1553)	+= rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_RS5C313)	+= rtc-rs5c313.o
@@ -41,3 +43,5 @@
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
 obj-$(CONFIG_RTC_DRV_SH)	+= rtc-sh.o
 obj-$(CONFIG_RTC_DRV_BFIN)	+= rtc-bfin.o
+obj-$(CONFIG_RTC_DRV_M48T59)	+= rtc-m48t59.o
+obj-$(CONFIG_RTC_DRV_DS1216)	+= rtc-ds1216.o
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
new file mode 100644
index 0000000..2999214
--- /dev/null
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -0,0 +1,317 @@
+/*
+ * An RTC driver for the AVR32 AT32AP700x processor series.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/io.h>
+
+/*
+ * This is a bare-bones RTC. It runs during most system sleep states, but has
+ * no battery backup and gets reset during system restart.  It must be
+ * initialized from an external clock (network, I2C, etc) before it can be of
+ * much use.
+ *
+ * The alarm functionality is limited by the hardware, not supporting
+ * periodic interrupts.
+ */
+
+#define RTC_CTRL		0x00
+#define RTC_CTRL_EN		   0
+#define RTC_CTRL_PCLR		   1
+#define RTC_CTRL_TOPEN		   2
+#define RTC_CTRL_PSEL		   8
+
+#define RTC_VAL			0x04
+
+#define RTC_TOP			0x08
+
+#define RTC_IER			0x10
+#define RTC_IER_TOPI		   0
+
+#define RTC_IDR			0x14
+#define RTC_IDR_TOPI		   0
+
+#define RTC_IMR			0x18
+#define RTC_IMR_TOPI		   0
+
+#define RTC_ISR			0x1c
+#define RTC_ISR_TOPI		   0
+
+#define RTC_ICR			0x20
+#define RTC_ICR_TOPI		   0
+
+#define RTC_BIT(name)		(1 << RTC_##name)
+#define RTC_BF(name, value)	((value) << RTC_##name)
+
+#define rtc_readl(dev, reg)				\
+	__raw_readl((dev)->regs + RTC_##reg)
+#define rtc_writel(dev, reg, value)			\
+	__raw_writel((value), (dev)->regs + RTC_##reg)
+
+struct rtc_at32ap700x {
+	struct rtc_device	*rtc;
+	void __iomem		*regs;
+	unsigned long		alarm_time;
+	unsigned long		irq;
+	/* Protect against concurrent register access. */
+	spinlock_t		lock;
+};
+
+static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+	unsigned long now;
+
+	now = rtc_readl(rtc, VAL);
+	rtc_time_to_tm(now, tm);
+
+	return 0;
+}
+
+static int at32_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+	unsigned long now;
+	int ret;
+
+	ret = rtc_tm_to_time(tm, &now);
+	if (ret == 0)
+		rtc_writel(rtc, VAL, now);
+
+	return ret;
+}
+
+static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+
+	rtc_time_to_tm(rtc->alarm_time, &alrm->time);
+	alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
+
+	return 0;
+}
+
+static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+	unsigned long rtc_unix_time;
+	unsigned long alarm_unix_time;
+	int ret;
+
+	rtc_unix_time = rtc_readl(rtc, VAL);
+
+	ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time);
+	if (ret)
+		return ret;
+
+	if (alarm_unix_time < rtc_unix_time)
+		return -EINVAL;
+
+	spin_lock_irq(&rtc->lock);
+	rtc->alarm_time = alarm_unix_time;
+	rtc_writel(rtc, TOP, rtc->alarm_time);
+	if (alrm->pending)
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				| RTC_BIT(CTRL_TOPEN));
+	else
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				& ~RTC_BIT(CTRL_TOPEN));
+	spin_unlock_irq(&rtc->lock);
+
+	return ret;
+}
+
+static int at32_rtc_ioctl(struct device *dev, unsigned int cmd,
+			unsigned long arg)
+{
+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+	int ret = 0;
+
+	spin_lock_irq(&rtc->lock);
+
+	switch (cmd) {
+	case RTC_AIE_ON:
+		if (rtc_readl(rtc, VAL) > rtc->alarm_time) {
+			ret = -EINVAL;
+			break;
+		}
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				| RTC_BIT(CTRL_TOPEN));
+		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+		rtc_writel(rtc, IER, RTC_BIT(IER_TOPI));
+		break;
+	case RTC_AIE_OFF:
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				& ~RTC_BIT(CTRL_TOPEN));
+		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+
+	spin_unlock_irq(&rtc->lock);
+
+	return ret;
+}
+
+static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id)
+{
+	struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id;
+	unsigned long isr = rtc_readl(rtc, ISR);
+	unsigned long events = 0;
+	int ret = IRQ_NONE;
+
+	spin_lock(&rtc->lock);
+
+	if (isr & RTC_BIT(ISR_TOPI)) {
+		rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+		rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+				& ~RTC_BIT(CTRL_TOPEN));
+		rtc_writel(rtc, VAL, rtc->alarm_time);
+		events = RTC_AF | RTC_IRQF;
+		rtc_update_irq(rtc->rtc, 1, events);
+		ret = IRQ_HANDLED;
+	}
+
+	spin_unlock(&rtc->lock);
+
+	return ret;
+}
+
+static struct rtc_class_ops at32_rtc_ops = {
+	.ioctl		= at32_rtc_ioctl,
+	.read_time	= at32_rtc_readtime,
+	.set_time	= at32_rtc_settime,
+	.read_alarm	= at32_rtc_readalarm,
+	.set_alarm	= at32_rtc_setalarm,
+};
+
+static int __init at32_rtc_probe(struct platform_device *pdev)
+{
+	struct resource	*regs;
+	struct rtc_at32ap700x *rtc;
+	int irq = -1;
+	int ret;
+
+	rtc = kzalloc(sizeof(struct rtc_at32ap700x), GFP_KERNEL);
+	if (!rtc) {
+		dev_dbg(&pdev->dev, "out of memory\n");
+		return -ENOMEM;
+	}
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_dbg(&pdev->dev, "no mmio resource defined\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_dbg(&pdev->dev, "could not get irq\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc);
+	if (ret) {
+		dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
+		goto out;
+	}
+
+	rtc->irq = irq;
+	rtc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!rtc->regs) {
+		ret = -ENOMEM;
+		dev_dbg(&pdev->dev, "could not map I/O memory\n");
+		goto out_free_irq;
+	}
+	spin_lock_init(&rtc->lock);
+
+	/*
+	 * Maybe init RTC: count from zero at 1 Hz, disable wrap irq.
+	 *
+	 * Do not reset VAL register, as it can hold an old time
+	 * from last JTAG reset.
+	 */
+	if (!(rtc_readl(rtc, CTRL) & RTC_BIT(CTRL_EN))) {
+		rtc_writel(rtc, CTRL, RTC_BIT(CTRL_PCLR));
+		rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+		rtc_writel(rtc, CTRL, RTC_BF(CTRL_PSEL, 0xe)
+				| RTC_BIT(CTRL_EN));
+	}
+
+	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+				&at32_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc->rtc)) {
+		dev_dbg(&pdev->dev, "could not register rtc device\n");
+		ret = PTR_ERR(rtc->rtc);
+		goto out_iounmap;
+	}
+
+	platform_set_drvdata(pdev, rtc);
+
+	dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n",
+			(unsigned long)rtc->regs, rtc->irq);
+
+	return 0;
+
+out_iounmap:
+	iounmap(rtc->regs);
+out_free_irq:
+	free_irq(irq, rtc);
+out:
+	kfree(rtc);
+	return ret;
+}
+
+static int __exit at32_rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_at32ap700x *rtc = platform_get_drvdata(pdev);
+
+	free_irq(rtc->irq, rtc);
+	iounmap(rtc->regs);
+	rtc_device_unregister(rtc->rtc);
+	kfree(rtc);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+MODULE_ALIAS("at32ap700x_rtc");
+
+static struct platform_driver at32_rtc_driver = {
+	.remove		= __exit_p(at32_rtc_remove),
+	.driver		= {
+		.name	= "at32ap700x_rtc",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at32_rtc_init(void)
+{
+	return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe);
+}
+module_init(at32_rtc_init);
+
+static void __exit at32_rtc_exit(void)
+{
+	platform_driver_unregister(&at32_rtc_driver);
+}
+module_exit(at32_rtc_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 6085261..e24ea82 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -641,9 +641,16 @@
 	 * drivers can't provide shutdown() methods to disable IRQs.
 	 * Or better yet, fix PNP to allow those methods...
 	 */
-	return cmos_do_probe(&pnp->dev,
-			&pnp->res.port_resource[0],
-			pnp->res.irq_resource[0].start);
+	if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0))
+		/* Some machines contain a PNP entry for the RTC, but
+		 * don't define the IRQ. It should always be safe to
+		 * hardcode it in these cases
+		 */
+		return cmos_do_probe(&pnp->dev, &pnp->res.port_resource[0], 8);
+	else
+		return cmos_do_probe(&pnp->dev,
+				     &pnp->res.port_resource[0],
+				     pnp->res.irq_resource[0].start);
 }
 
 static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index f4e5f00..3045359 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -341,6 +341,8 @@
 	case RTC_IRQP_READ:
 		if (ops->irq_set_freq)
 			err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
+		else
+			err = -ENOTTY;
 		break;
 
 	case RTC_IRQP_SET:
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c
new file mode 100644
index 0000000..83efb88
--- /dev/null
+++ b/drivers/rtc/rtc-ds1216.c
@@ -0,0 +1,226 @@
+/*
+ * Dallas DS1216 RTC driver
+ *
+ * Copyright (c) 2007 Thomas Bogendoerfer
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/bcd.h>
+
+#define DRV_VERSION "0.1"
+
+struct ds1216_regs {
+	u8 tsec;
+	u8 sec;
+	u8 min;
+	u8 hour;
+	u8 wday;
+	u8 mday;
+	u8 month;
+	u8 year;
+};
+
+#define DS1216_HOUR_1224	(1 << 7)
+#define DS1216_HOUR_AMPM	(1 << 5)
+
+struct ds1216_priv {
+	struct rtc_device *rtc;
+	void __iomem *ioaddr;
+	size_t size;
+	unsigned long baseaddr;
+};
+
+static const u8 magic[] = {
+	0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
+};
+
+/*
+ * Read the 64 bit we'd like to have - It a series
+ * of 64 bits showing up in the LSB of the base register.
+ *
+ */
+static void ds1216_read(u8 __iomem *ioaddr, u8 *buf)
+{
+	unsigned char c;
+	int i, j;
+
+	for (i = 0; i < 8; i++) {
+		c = 0;
+		for (j = 0; j < 8; j++)
+			c |= (readb(ioaddr) & 0x1) << j;
+		buf[i] = c;
+	}
+}
+
+static void ds1216_write(u8 __iomem *ioaddr, const u8 *buf)
+{
+	unsigned char c;
+	int i, j;
+
+	for (i = 0; i < 8; i++) {
+		c = buf[i];
+		for (j = 0; j < 8; j++) {
+			writeb(c, ioaddr);
+			c = c >> 1;
+		}
+	}
+}
+
+static void ds1216_switch_ds_to_clock(u8 __iomem *ioaddr)
+{
+	/* Reset magic pointer */
+	readb(ioaddr);
+	/* Write 64 bit magic to DS1216 */
+	ds1216_write(ioaddr, magic);
+}
+
+static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ds1216_priv *priv = platform_get_drvdata(pdev);
+	struct ds1216_regs regs;
+
+	ds1216_switch_ds_to_clock(priv->ioaddr);
+	ds1216_read(priv->ioaddr, (u8 *)&regs);
+
+	tm->tm_sec = BCD2BIN(regs.sec);
+	tm->tm_min = BCD2BIN(regs.min);
+	if (regs.hour & DS1216_HOUR_1224) {
+		/* AM/PM mode */
+		tm->tm_hour = BCD2BIN(regs.hour & 0x1f);
+		if (regs.hour & DS1216_HOUR_AMPM)
+			tm->tm_hour += 12;
+	} else
+		tm->tm_hour = BCD2BIN(regs.hour & 0x3f);
+	tm->tm_wday = (regs.wday & 7) - 1;
+	tm->tm_mday = BCD2BIN(regs.mday & 0x3f);
+	tm->tm_mon = BCD2BIN(regs.month & 0x1f);
+	tm->tm_year = BCD2BIN(regs.year);
+	if (tm->tm_year < 70)
+		tm->tm_year += 100;
+	return 0;
+}
+
+static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ds1216_priv *priv = platform_get_drvdata(pdev);
+	struct ds1216_regs regs;
+
+	ds1216_switch_ds_to_clock(priv->ioaddr);
+	ds1216_read(priv->ioaddr, (u8 *)&regs);
+
+	regs.tsec = 0; /* clear 0.1 and 0.01 seconds */
+	regs.sec = BIN2BCD(tm->tm_sec);
+	regs.min = BIN2BCD(tm->tm_min);
+	regs.hour &= DS1216_HOUR_1224;
+	if (regs.hour && tm->tm_hour > 12) {
+		regs.hour |= DS1216_HOUR_AMPM;
+		tm->tm_hour -= 12;
+	}
+	regs.hour |= BIN2BCD(tm->tm_hour);
+	regs.wday &= ~7;
+	regs.wday |= tm->tm_wday;
+	regs.mday = BIN2BCD(tm->tm_mday);
+	regs.month = BIN2BCD(tm->tm_mon);
+	regs.year = BIN2BCD(tm->tm_year % 100);
+
+	ds1216_switch_ds_to_clock(priv->ioaddr);
+	ds1216_write(priv->ioaddr, (u8 *)&regs);
+	return 0;
+}
+
+static const struct rtc_class_ops ds1216_rtc_ops = {
+	.read_time	= ds1216_rtc_read_time,
+	.set_time	= ds1216_rtc_set_time,
+};
+
+static int __devinit ds1216_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	struct resource *res;
+	struct ds1216_priv *priv;
+	int ret = 0;
+	u8 dummy[8];
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	priv = kzalloc(sizeof *priv, GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	priv->size = res->end - res->start + 1;
+	if (!request_mem_region(res->start, priv->size, pdev->name)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	priv->baseaddr = res->start;
+	priv->ioaddr = ioremap(priv->baseaddr, priv->size);
+	if (!priv->ioaddr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	rtc = rtc_device_register("ds1216", &pdev->dev,
+				  &ds1216_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		ret = PTR_ERR(rtc);
+		goto out;
+	}
+	priv->rtc = rtc;
+	platform_set_drvdata(pdev, priv);
+
+	/* dummy read to get clock into a known state */
+	ds1216_read(priv->ioaddr, dummy);
+	return 0;
+
+out:
+	if (priv->rtc)
+		rtc_device_unregister(priv->rtc);
+	if (priv->ioaddr)
+		iounmap(priv->ioaddr);
+	if (priv->baseaddr)
+		release_mem_region(priv->baseaddr, priv->size);
+	kfree(priv);
+	return ret;
+}
+
+static int __devexit ds1216_rtc_remove(struct platform_device *pdev)
+{
+	struct ds1216_priv *priv = platform_get_drvdata(pdev);
+
+	rtc_device_unregister(priv->rtc);
+	iounmap(priv->ioaddr);
+	release_mem_region(priv->baseaddr, priv->size);
+	kfree(priv);
+	return 0;
+}
+
+static struct platform_driver ds1216_rtc_platform_driver = {
+	.driver		= {
+		.name	= "rtc-ds1216",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ds1216_rtc_probe,
+	.remove		= __devexit_p(ds1216_rtc_remove),
+};
+
+static int __init ds1216_rtc_init(void)
+{
+	return platform_driver_register(&ds1216_rtc_platform_driver);
+}
+
+static void __exit ds1216_rtc_exit(void)
+{
+	platform_driver_unregister(&ds1216_rtc_platform_driver);
+}
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
+MODULE_DESCRIPTION("DS1216 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ds1216_rtc_init);
+module_exit(ds1216_rtc_exit);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 3f0f7b8..5158a62 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -24,29 +24,29 @@
  * setting the date and time), Linux can ignore the non-clock features.
  * That's a natural job for a factory or repair bench.
  *
- * If the I2C "force" mechanism is used, we assume the chip is a ds1337.
- * (Much better would be board-specific tables of I2C devices, along with
- * the platform_data drivers would use to sort such issues out.)
+ * This is currently a simple no-alarms driver.  If your board has the
+ * alarm irq wired up on a ds1337 or ds1339, and you want to use that,
+ * then look at the rtc-rs5c372 driver for code to steal...
  */
 enum ds_type {
-	unknown = 0,
-	ds_1307,		/* or ds1338, ... */
-	ds_1337,		/* or ds1339, ... */
-	ds_1340,		/* or st m41t00, ... */
+	ds_1307,
+	ds_1337,
+	ds_1338,
+	ds_1339,
+	ds_1340,
+	m41t00,
 	// rs5c372 too?  different address...
 };
 
-static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
-
 
 /* RTC registers don't differ much, except for the century flag */
 #define DS1307_REG_SECS		0x00	/* 00-59 */
 #	define DS1307_BIT_CH		0x80
+#	define DS1340_BIT_nEOSC		0x80
 #define DS1307_REG_MIN		0x01	/* 00-59 */
 #define DS1307_REG_HOUR		0x02	/* 00-23, or 1-12{am,pm} */
+#	define DS1307_BIT_12HR		0x40	/* in REG_HOUR */
+#	define DS1307_BIT_PM		0x20	/* in REG_HOUR */
 #	define DS1340_BIT_CENTURY_EN	0x80	/* in REG_HOUR */
 #	define DS1340_BIT_CENTURY	0x40	/* in REG_HOUR */
 #define DS1307_REG_WDAY		0x03	/* 01-07 */
@@ -56,11 +56,12 @@
 #define DS1307_REG_YEAR		0x06	/* 00-99 */
 
 /* Other registers (control, status, alarms, trickle charge, NVRAM, etc)
- * start at 7, and they differ a lot. Only control and status matter for RTC;
- * be careful using them.
+ * start at 7, and they differ a LOT. Only control and status matter for
+ * basic RTC date and time functionality; be careful using them.
  */
-#define DS1307_REG_CONTROL	0x07
+#define DS1307_REG_CONTROL	0x07		/* or ds1338 */
 #	define DS1307_BIT_OUT		0x80
+#	define DS1338_BIT_OSF		0x20
 #	define DS1307_BIT_SQWE		0x10
 #	define DS1307_BIT_RS1		0x02
 #	define DS1307_BIT_RS0		0x01
@@ -71,6 +72,13 @@
 #	define DS1337_BIT_INTCN		0x04
 #	define DS1337_BIT_A2IE		0x02
 #	define DS1337_BIT_A1IE		0x01
+#define DS1340_REG_CONTROL	0x07
+#	define DS1340_BIT_OUT		0x80
+#	define DS1340_BIT_FT		0x40
+#	define DS1340_BIT_CALIB_SIGN	0x20
+#	define DS1340_M_CALIBRATION	0x1f
+#define DS1340_REG_FLAG		0x09
+#	define DS1340_BIT_OSF		0x80
 #define DS1337_REG_STATUS	0x0f
 #	define DS1337_BIT_OSF		0x80
 #	define DS1337_BIT_A2I		0x02
@@ -84,21 +92,63 @@
 	u8			regs[8];
 	enum ds_type		type;
 	struct i2c_msg		msg[2];
-	struct i2c_client	client;
+	struct i2c_client	*client;
+	struct i2c_client	dev;
 	struct rtc_device	*rtc;
 };
 
+struct chip_desc {
+	char			name[9];
+	unsigned		nvram56:1;
+	unsigned		alarm:1;
+	enum ds_type		type;
+};
+
+static const struct chip_desc chips[] = { {
+	.name		= "ds1307",
+	.type		= ds_1307,
+	.nvram56	= 1,
+}, {
+	.name		= "ds1337",
+	.type		= ds_1337,
+	.alarm		= 1,
+}, {
+	.name		= "ds1338",
+	.type		= ds_1338,
+	.nvram56	= 1,
+}, {
+	.name		= "ds1339",
+	.type		= ds_1339,
+	.alarm		= 1,
+}, {
+	.name		= "ds1340",
+	.type		= ds_1340,
+}, {
+	.name		= "m41t00",
+	.type		= m41t00,
+}, };
+
+static inline const struct chip_desc *find_chip(const char *s)
+{
+	unsigned i;
+
+	for (i = 0; i < ARRAY_SIZE(chips); i++)
+		if (strnicmp(s, chips[i].name, sizeof chips[i].name) == 0)
+			return &chips[i];
+	return NULL;
+}
 
 static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 {
 	struct ds1307	*ds1307 = dev_get_drvdata(dev);
 	int		tmp;
 
-	/* read the RTC registers all at once */
+	/* read the RTC date and time registers all at once */
 	ds1307->msg[1].flags = I2C_M_RD;
 	ds1307->msg[1].len = 7;
 
-	tmp = i2c_transfer(ds1307->client.adapter, ds1307->msg, 2);
+	tmp = i2c_transfer(to_i2c_adapter(ds1307->client->dev.parent),
+			ds1307->msg, 2);
 	if (tmp != 2) {
 		dev_err(dev, "%s error %d\n", "read", tmp);
 		return -EIO;
@@ -129,7 +179,8 @@
 		t->tm_hour, t->tm_mday,
 		t->tm_mon, t->tm_year, t->tm_wday);
 
-	return 0;
+	/* initial clock setting can be undefined */
+	return rtc_valid_tm(t);
 }
 
 static int ds1307_set_time(struct device *dev, struct rtc_time *t)
@@ -157,11 +208,18 @@
 	tmp = t->tm_year - 100;
 	buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
 
-	if (ds1307->type == ds_1337)
+	switch (ds1307->type) {
+	case ds_1337:
+	case ds_1339:
 		buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
-	else if (ds1307->type == ds_1340)
+		break;
+	case ds_1340:
 		buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
 				| DS1340_BIT_CENTURY;
+		break;
+	default:
+		break;
+	}
 
 	ds1307->msg[1].flags = 0;
 	ds1307->msg[1].len = 8;
@@ -170,7 +228,8 @@
 		"write", buf[0], buf[1], buf[2], buf[3],
 		buf[4], buf[5], buf[6]);
 
-	result = i2c_transfer(ds1307->client.adapter, &ds1307->msg[1], 1);
+	result = i2c_transfer(to_i2c_adapter(ds1307->client->dev.parent),
+			&ds1307->msg[1], 1);
 	if (result != 1) {
 		dev_err(dev, "%s error %d\n", "write", tmp);
 		return -EIO;
@@ -185,25 +244,29 @@
 
 static struct i2c_driver ds1307_driver;
 
-static int __devinit
-ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
+static int __devinit ds1307_probe(struct i2c_client *client)
 {
 	struct ds1307		*ds1307;
 	int			err = -ENODEV;
-	struct i2c_client	*client;
 	int			tmp;
+	const struct chip_desc	*chip;
+	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
 
-	if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) {
-		err = -ENOMEM;
-		goto exit;
+	chip = find_chip(client->name);
+	if (!chip) {
+		dev_err(&client->dev, "unknown chip type '%s'\n",
+				client->name);
+		return -ENODEV;
 	}
 
-	client = &ds1307->client;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &ds1307_driver;
-	client->flags = 0;
+	if (!i2c_check_functionality(adapter,
+			I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EIO;
 
+	if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL)))
+		return -ENOMEM;
+
+	ds1307->client = client;
 	i2c_set_clientdata(client, ds1307);
 
 	ds1307->msg[0].addr = client->addr;
@@ -216,14 +279,16 @@
 	ds1307->msg[1].len = sizeof(ds1307->regs);
 	ds1307->msg[1].buf = ds1307->regs;
 
-	/* HACK: "force" implies "needs ds1337-style-oscillator setup" */
-	if (kind >= 0) {
-		ds1307->type = ds_1337;
+	ds1307->type = chip->type;
 
+	switch (ds1307->type) {
+	case ds_1337:
+	case ds_1339:
 		ds1307->reg_addr = DS1337_REG_CONTROL;
 		ds1307->msg[1].len = 2;
 
-		tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+		/* get registers that the "rtc" read below won't read... */
+		tmp = i2c_transfer(adapter, ds1307->msg, 2);
 		if (tmp != 2) {
 			pr_debug("read error %d\n", tmp);
 			err = -EIO;
@@ -233,19 +298,26 @@
 		ds1307->reg_addr = 0;
 		ds1307->msg[1].len = sizeof(ds1307->regs);
 
-		/* oscillator is off; need to turn it on */
-		if ((ds1307->regs[0] & DS1337_BIT_nEOSC)
-				|| (ds1307->regs[1] & DS1337_BIT_OSF)) {
-			printk(KERN_ERR "no ds1337 oscillator code\n");
-			goto exit_free;
+		/* oscillator off?  turn it on, so clock can tick. */
+		if (ds1307->regs[0] & DS1337_BIT_nEOSC)
+			i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
+				ds1307->regs[0] & ~DS1337_BIT_nEOSC);
+
+		/* oscillator fault?  clear flag, and warn */
+		if (ds1307->regs[1] & DS1337_BIT_OSF) {
+			i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
+				ds1307->regs[1] & ~DS1337_BIT_OSF);
+			dev_warn(&client->dev, "SET TIME!\n");
 		}
-	} else
-		ds1307->type = ds_1307;
+		break;
+	default:
+		break;
+	}
 
 read_rtc:
 	/* read RTC registers */
 
-	tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+	tmp = i2c_transfer(adapter, ds1307->msg, 2);
 	if (tmp != 2) {
 		pr_debug("read error %d\n", tmp);
 		err = -EIO;
@@ -257,119 +329,121 @@
 	 * still a few values that are clearly out-of-range.
 	 */
 	tmp = ds1307->regs[DS1307_REG_SECS];
-	if (tmp & DS1307_BIT_CH) {
-		if (ds1307->type && ds1307->type != ds_1307) {
-			pr_debug("not a ds1307?\n");
-			goto exit_free;
-		}
-		ds1307->type = ds_1307;
-
-		/* this partial initialization should work for ds1307,
-		 * ds1338, ds1340, st m41t00, and more.
+	switch (ds1307->type) {
+	case ds_1340:
+		/* FIXME read register with DS1340_BIT_OSF, use that to
+		 * trigger the "set time" warning (*after* restarting the
+		 * oscillator!) instead of this weaker ds1307/m41t00 test.
 		 */
-		dev_warn(&client->dev, "oscillator started; SET TIME!\n");
-		i2c_smbus_write_byte_data(client, 0, 0);
-		goto read_rtc;
+	case ds_1307:
+	case m41t00:
+		/* clock halted?  turn it on, so clock can tick. */
+		if (tmp & DS1307_BIT_CH) {
+			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+			dev_warn(&client->dev, "SET TIME!\n");
+			goto read_rtc;
+		}
+		break;
+	case ds_1338:
+		/* clock halted?  turn it on, so clock can tick. */
+		if (tmp & DS1307_BIT_CH)
+			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+
+		/* oscillator fault?  clear flag, and warn */
+		if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
+			i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL,
+					ds1307->regs[DS1337_REG_CONTROL]
+					& ~DS1338_BIT_OSF);
+			dev_warn(&client->dev, "SET TIME!\n");
+			goto read_rtc;
+		}
+		break;
+	case ds_1337:
+	case ds_1339:
+		break;
 	}
+
+	tmp = ds1307->regs[DS1307_REG_SECS];
 	tmp = BCD2BIN(tmp & 0x7f);
 	if (tmp > 60)
-		goto exit_free;
+		goto exit_bad;
 	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
 	if (tmp > 60)
-		goto exit_free;
+		goto exit_bad;
 
 	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
 	if (tmp == 0 || tmp > 31)
-		goto exit_free;
+		goto exit_bad;
 
 	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
 	if (tmp == 0 || tmp > 12)
-		goto exit_free;
+		goto exit_bad;
 
-	/* force into in 24 hour mode (most chips) or
-	 * disable century bit (ds1340)
-	 */
 	tmp = ds1307->regs[DS1307_REG_HOUR];
-	if (tmp & (1 << 6)) {
-		if (tmp & (1 << 5))
-			tmp = BCD2BIN(tmp & 0x1f) + 12;
-		else
-			tmp = BCD2BIN(tmp);
+	switch (ds1307->type) {
+	case ds_1340:
+	case m41t00:
+		/* NOTE: ignores century bits; fix before deploying
+		 * systems that will run through year 2100.
+		 */
+		break;
+	default:
+		if (!(tmp & DS1307_BIT_12HR))
+			break;
+
+		/* Be sure we're in 24 hour mode.  Multi-master systems
+		 * take note...
+		 */
+		tmp = BCD2BIN(tmp & 0x1f);
+		if (tmp == 12)
+			tmp = 0;
+		if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
+			tmp += 12;
 		i2c_smbus_write_byte_data(client,
 				DS1307_REG_HOUR,
 				BIN2BCD(tmp));
 	}
 
-	/* FIXME chips like 1337 can generate alarm irqs too; those are
-	 * worth exposing through the API (especially when the irq is
-	 * wakeup-capable).
-	 */
-
-	switch (ds1307->type) {
-	case unknown:
-		strlcpy(client->name, "unknown", I2C_NAME_SIZE);
-		break;
-	case ds_1307:
-		strlcpy(client->name, "ds1307", I2C_NAME_SIZE);
-		break;
-	case ds_1337:
-		strlcpy(client->name, "ds1337", I2C_NAME_SIZE);
-		break;
-	case ds_1340:
-		strlcpy(client->name, "ds1340", I2C_NAME_SIZE);
-		break;
-	}
-
-	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(client)))
-		goto exit_free;
-
 	ds1307->rtc = rtc_device_register(client->name, &client->dev,
 				&ds13xx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(ds1307->rtc)) {
 		err = PTR_ERR(ds1307->rtc);
 		dev_err(&client->dev,
 			"unable to register the class device\n");
-		goto exit_detach;
+		goto exit_free;
 	}
 
 	return 0;
 
-exit_detach:
-	i2c_detach_client(client);
+exit_bad:
+	dev_dbg(&client->dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+			"bogus register",
+			ds1307->regs[0], ds1307->regs[1],
+			ds1307->regs[2], ds1307->regs[3],
+			ds1307->regs[4], ds1307->regs[5],
+			ds1307->regs[6]);
+
 exit_free:
 	kfree(ds1307);
-exit:
 	return err;
 }
 
-static int __devinit
-ds1307_attach_adapter(struct i2c_adapter *adapter)
+static int __devexit ds1307_remove(struct i2c_client *client)
 {
-	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
-		return 0;
-	return i2c_probe(adapter, &addr_data, ds1307_detect);
-}
-
-static int __devexit ds1307_detach_client(struct i2c_client *client)
-{
-	int		err;
 	struct ds1307	*ds1307 = i2c_get_clientdata(client);
 
 	rtc_device_unregister(ds1307->rtc);
-	if ((err = i2c_detach_client(client)))
-		return err;
 	kfree(ds1307);
 	return 0;
 }
 
 static struct i2c_driver ds1307_driver = {
 	.driver = {
-		.name	= "ds1307",
+		.name	= "rtc-ds1307",
 		.owner	= THIS_MODULE,
 	},
-	.attach_adapter	= ds1307_attach_adapter,
-	.detach_client	= __devexit_p(ds1307_detach_client),
+	.probe		= ds1307_probe,
+	.remove		= __devexit_p(ds1307_remove),
 };
 
 static int __init ds1307_init(void)
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index afa64c7..f98a83a1 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -258,8 +258,9 @@
 	.ioctl		= ds1553_rtc_ioctl,
 };
 
-static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
-				 loff_t pos, size_t size)
+static ssize_t ds1553_nvram_read(struct kobject *kobj,
+				 struct bin_attribute *bin_attr,
+				 char *buf, loff_t pos, size_t size)
 {
 	struct platform_device *pdev =
 		to_platform_device(container_of(kobj, struct device, kobj));
@@ -272,8 +273,9 @@
 	return count;
 }
 
-static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
-				  loff_t pos, size_t size)
+static ssize_t ds1553_nvram_write(struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
+				  char *buf, loff_t pos, size_t size)
 {
 	struct platform_device *pdev =
 		to_platform_device(container_of(kobj, struct device, kobj));
@@ -290,7 +292,6 @@
 	.attr = {
 		.name = "nvram",
 		.mode = S_IRUGO | S_IWUGO,
-		.owner = THIS_MODULE,
 	},
 	.size = RTC_OFFSET,
 	.read = ds1553_nvram_read,
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index d68288b..d1778ae 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -127,8 +127,9 @@
 	.set_time	= ds1742_rtc_set_time,
 };
 
-static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
-				 loff_t pos, size_t size)
+static ssize_t ds1742_nvram_read(struct kobject *kobj,
+				 struct bin_attribute *bin_attr,
+				 char *buf, loff_t pos, size_t size)
 {
 	struct platform_device *pdev =
 		to_platform_device(container_of(kobj, struct device, kobj));
@@ -141,8 +142,9 @@
 	return count;
 }
 
-static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
-				  loff_t pos, size_t size)
+static ssize_t ds1742_nvram_write(struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
+				  char *buf, loff_t pos, size_t size)
 {
 	struct platform_device *pdev =
 		to_platform_device(container_of(kobj, struct device, kobj));
@@ -159,7 +161,6 @@
 	.attr = {
 		.name = "nvram",
 		.mode = S_IRUGO | S_IWUGO,
-		.owner = THIS_MODULE,
 	},
 	.read = ds1742_nvram_read,
 	.write = ds1742_nvram_write,
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
new file mode 100644
index 0000000..80c4a84
--- /dev/null
+++ b/drivers/rtc/rtc-m41t80.c
@@ -0,0 +1,917 @@
+/*
+ * I2C client/driver for the ST M41T80 family of i2c rtc chips.
+ *
+ * Author: Alexander Bigga <ab@mycable.de>
+ *
+ * Based on m41t00.c by Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) mycable GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#endif
+
+#define M41T80_REG_SSEC	0
+#define M41T80_REG_SEC	1
+#define M41T80_REG_MIN	2
+#define M41T80_REG_HOUR	3
+#define M41T80_REG_WDAY	4
+#define M41T80_REG_DAY	5
+#define M41T80_REG_MON	6
+#define M41T80_REG_YEAR	7
+#define M41T80_REG_ALARM_MON	0xa
+#define M41T80_REG_ALARM_DAY	0xb
+#define M41T80_REG_ALARM_HOUR	0xc
+#define M41T80_REG_ALARM_MIN	0xd
+#define M41T80_REG_ALARM_SEC	0xe
+#define M41T80_REG_FLAGS	0xf
+#define M41T80_REG_SQW	0x13
+
+#define M41T80_DATETIME_REG_SIZE	(M41T80_REG_YEAR + 1)
+#define M41T80_ALARM_REG_SIZE	\
+	(M41T80_REG_ALARM_SEC + 1 - M41T80_REG_ALARM_MON)
+
+#define M41T80_SEC_ST		(1 << 7)	/* ST: Stop Bit */
+#define M41T80_ALMON_AFE	(1 << 7)	/* AFE: AF Enable Bit */
+#define M41T80_ALMON_SQWE	(1 << 6)	/* SQWE: SQW Enable Bit */
+#define M41T80_ALHOUR_HT	(1 << 6)	/* HT: Halt Update Bit */
+#define M41T80_FLAGS_AF		(1 << 6)	/* AF: Alarm Flag Bit */
+#define M41T80_FLAGS_BATT_LOW	(1 << 4)	/* BL: Battery Low Bit */
+
+#define M41T80_FEATURE_HT	(1 << 0)
+#define M41T80_FEATURE_BL	(1 << 1)
+
+#define DRV_VERSION "0.05"
+
+struct m41t80_chip_info {
+	const char *name;
+	u8 features;
+};
+
+static const struct m41t80_chip_info m41t80_chip_info_tbl[] = {
+	{
+		.name		= "m41t80",
+		.features	= 0,
+	},
+	{
+		.name		= "m41t81",
+		.features	= M41T80_FEATURE_HT,
+	},
+	{
+		.name		= "m41t81s",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41t82",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41t83",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41st84",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41st85",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+	{
+		.name		= "m41st87",
+		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+	},
+};
+
+struct m41t80_data {
+	const struct m41t80_chip_info *chip;
+	struct rtc_device *rtc;
+};
+
+static int m41t80_get_datetime(struct i2c_client *client,
+			       struct rtc_time *tm)
+{
+	u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC };
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= dt_addr,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
+			.buf	= buf + M41T80_REG_SEC,
+		},
+	};
+
+	if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+		dev_err(&client->dev, "read error\n");
+		return -EIO;
+	}
+
+	tm->tm_sec = BCD2BIN(buf[M41T80_REG_SEC] & 0x7f);
+	tm->tm_min = BCD2BIN(buf[M41T80_REG_MIN] & 0x7f);
+	tm->tm_hour = BCD2BIN(buf[M41T80_REG_HOUR] & 0x3f);
+	tm->tm_mday = BCD2BIN(buf[M41T80_REG_DAY] & 0x3f);
+	tm->tm_wday = buf[M41T80_REG_WDAY] & 0x07;
+	tm->tm_mon = BCD2BIN(buf[M41T80_REG_MON] & 0x1f) - 1;
+
+	/* assume 20YY not 19YY, and ignore the Century Bit */
+	tm->tm_year = BCD2BIN(buf[M41T80_REG_YEAR]) + 100;
+	return 0;
+}
+
+/* Sets the given date and time to the real time clock. */
+static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+	u8 wbuf[1 + M41T80_DATETIME_REG_SIZE];
+	u8 *buf = &wbuf[1];
+	u8 dt_addr[1] = { M41T80_REG_SEC };
+	struct i2c_msg msgs_in[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= dt_addr,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
+			.buf	= buf + M41T80_REG_SEC,
+		},
+	};
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1 + M41T80_DATETIME_REG_SIZE,
+			.buf	= wbuf,
+		 },
+	};
+
+	/* Read current reg values into buf[1..7] */
+	if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
+		dev_err(&client->dev, "read error\n");
+		return -EIO;
+	}
+
+	wbuf[0] = 0; /* offset into rtc's regs */
+	/* Merge time-data and register flags into buf[0..7] */
+	buf[M41T80_REG_SSEC] = 0;
+	buf[M41T80_REG_SEC] =
+		BIN2BCD(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
+	buf[M41T80_REG_MIN] =
+		BIN2BCD(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
+	buf[M41T80_REG_HOUR] =
+		BIN2BCD(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ;
+	buf[M41T80_REG_WDAY] =
+		(tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07);
+	buf[M41T80_REG_DAY] =
+		BIN2BCD(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
+	buf[M41T80_REG_MON] =
+		BIN2BCD(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);
+	/* assume 20YY not 19YY */
+	buf[M41T80_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+
+	if (i2c_transfer(client->adapter, msgs, 1) != 1) {
+		dev_err(&client->dev, "write error\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
+static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct m41t80_data *clientdata = i2c_get_clientdata(client);
+	u8 reg;
+
+	if (clientdata->chip->features & M41T80_FEATURE_BL) {
+		reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+		seq_printf(seq, "battery\t\t: %s\n",
+			   (reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
+	}
+	return 0;
+}
+#else
+#define m41t80_rtc_proc NULL
+#endif
+
+static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	return m41t80_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	return m41t80_set_datetime(to_i2c_client(dev), tm);
+}
+
+#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
+static int
+m41t80_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int rc;
+
+	switch (cmd) {
+	case RTC_AIE_OFF:
+	case RTC_AIE_ON:
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+	if (rc < 0)
+		goto err;
+	switch (cmd) {
+	case RTC_AIE_OFF:
+		rc &= ~M41T80_ALMON_AFE;
+		break;
+	case RTC_AIE_ON:
+		rc |= M41T80_ALMON_AFE;
+		break;
+	}
+	if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, rc) < 0)
+		goto err;
+	return 0;
+err:
+	return -EIO;
+}
+#else
+#define	m41t80_rtc_ioctl NULL
+#endif
+
+static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 wbuf[1 + M41T80_ALARM_REG_SIZE];
+	u8 *buf = &wbuf[1];
+	u8 *reg = buf - M41T80_REG_ALARM_MON;
+	u8 dt_addr[1] = { M41T80_REG_ALARM_MON };
+	struct i2c_msg msgs_in[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= dt_addr,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= M41T80_ALARM_REG_SIZE,
+			.buf	= buf,
+		},
+	};
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1 + M41T80_ALARM_REG_SIZE,
+			.buf	= wbuf,
+		 },
+	};
+
+	if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
+		dev_err(&client->dev, "read error\n");
+		return -EIO;
+	}
+	reg[M41T80_REG_ALARM_MON] &= ~(0x1f | M41T80_ALMON_AFE);
+	reg[M41T80_REG_ALARM_DAY] = 0;
+	reg[M41T80_REG_ALARM_HOUR] &= ~(0x3f | 0x80);
+	reg[M41T80_REG_ALARM_MIN] = 0;
+	reg[M41T80_REG_ALARM_SEC] = 0;
+
+	wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */
+	reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ?
+		BIN2BCD(t->time.tm_sec) : 0x80;
+	reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ?
+		BIN2BCD(t->time.tm_min) : 0x80;
+	reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ?
+		BIN2BCD(t->time.tm_hour) : 0x80;
+	reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ?
+		BIN2BCD(t->time.tm_mday) : 0x80;
+	if (t->time.tm_mon >= 0)
+		reg[M41T80_REG_ALARM_MON] |= BIN2BCD(t->time.tm_mon + 1);
+	else
+		reg[M41T80_REG_ALARM_DAY] |= 0x40;
+
+	if (i2c_transfer(client->adapter, msgs, 1) != 1) {
+		dev_err(&client->dev, "write error\n");
+		return -EIO;
+	}
+
+	if (t->enabled) {
+		reg[M41T80_REG_ALARM_MON] |= M41T80_ALMON_AFE;
+		if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+					      reg[M41T80_REG_ALARM_MON]) < 0) {
+			dev_err(&client->dev, "write error\n");
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 buf[M41T80_ALARM_REG_SIZE + 1]; /* all alarm regs and flags */
+	u8 dt_addr[1] = { M41T80_REG_ALARM_MON };
+	u8 *reg = buf - M41T80_REG_ALARM_MON;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= dt_addr,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= M41T80_ALARM_REG_SIZE + 1,
+			.buf	= buf,
+		},
+	};
+
+	if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+		dev_err(&client->dev, "read error\n");
+		return -EIO;
+	}
+	t->time.tm_sec = -1;
+	t->time.tm_min = -1;
+	t->time.tm_hour = -1;
+	t->time.tm_mday = -1;
+	t->time.tm_mon = -1;
+	if (!(reg[M41T80_REG_ALARM_SEC] & 0x80))
+		t->time.tm_sec = BCD2BIN(reg[M41T80_REG_ALARM_SEC] & 0x7f);
+	if (!(reg[M41T80_REG_ALARM_MIN] & 0x80))
+		t->time.tm_min = BCD2BIN(reg[M41T80_REG_ALARM_MIN] & 0x7f);
+	if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80))
+		t->time.tm_hour = BCD2BIN(reg[M41T80_REG_ALARM_HOUR] & 0x3f);
+	if (!(reg[M41T80_REG_ALARM_DAY] & 0x80))
+		t->time.tm_mday = BCD2BIN(reg[M41T80_REG_ALARM_DAY] & 0x3f);
+	if (!(reg[M41T80_REG_ALARM_DAY] & 0x40))
+		t->time.tm_mon = BCD2BIN(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1;
+	t->time.tm_year = -1;
+	t->time.tm_wday = -1;
+	t->time.tm_yday = -1;
+	t->time.tm_isdst = -1;
+	t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE);
+	t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF);
+	return 0;
+}
+
+static struct rtc_class_ops m41t80_rtc_ops = {
+	.read_time = m41t80_rtc_read_time,
+	.set_time = m41t80_rtc_set_time,
+	.read_alarm = m41t80_rtc_read_alarm,
+	.set_alarm = m41t80_rtc_set_alarm,
+	.proc = m41t80_rtc_proc,
+	.ioctl = m41t80_rtc_ioctl,
+};
+
+#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
+static ssize_t m41t80_sysfs_show_flags(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int val;
+
+	val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+	if (val < 0)
+		return -EIO;
+	return sprintf(buf, "%#x\n", val);
+}
+static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL);
+
+static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int val;
+
+	val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW);
+	if (val < 0)
+		return -EIO;
+	val = (val >> 4) & 0xf;
+	switch (val) {
+	case 0:
+		break;
+	case 1:
+		val = 32768;
+		break;
+	default:
+		val = 32768 >> val;
+	}
+	return sprintf(buf, "%d\n", val);
+}
+static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int almon, sqw;
+	int val = simple_strtoul(buf, NULL, 0);
+
+	if (val) {
+		if (!is_power_of_2(val))
+			return -EINVAL;
+		val = ilog2(val);
+		if (val == 15)
+			val = 1;
+		else if (val < 14)
+			val = 15 - val;
+		else
+			return -EINVAL;
+	}
+	/* disable SQW, set SQW frequency & re-enable */
+	almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+	if (almon < 0)
+		return -EIO;
+	sqw = i2c_smbus_read_byte_data(client, M41T80_REG_SQW);
+	if (sqw < 0)
+		return -EIO;
+	sqw = (sqw & 0x0f) | (val << 4);
+	if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+				      almon & ~M41T80_ALMON_SQWE) < 0 ||
+	    i2c_smbus_write_byte_data(client, M41T80_REG_SQW, sqw) < 0)
+		return -EIO;
+	if (val && i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+					     almon | M41T80_ALMON_SQWE) < 0)
+		return -EIO;
+	return count;
+}
+static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR,
+		   m41t80_sysfs_show_sqwfreq, m41t80_sysfs_set_sqwfreq);
+
+static struct attribute *attrs[] = {
+	&dev_attr_flags.attr,
+	&dev_attr_sqwfreq.attr,
+	NULL,
+};
+static struct attribute_group attr_group = {
+	.attrs = attrs,
+};
+
+static int m41t80_sysfs_register(struct device *dev)
+{
+	return sysfs_create_group(&dev->kobj, &attr_group);
+}
+#else
+static int m41t80_sysfs_register(struct device *dev)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+/*
+ *****************************************************************************
+ *
+ * Watchdog Driver
+ *
+ *****************************************************************************
+ */
+static struct i2c_client *save_client;
+
+/* Default margin */
+#define WD_TIMO 60		/* 1..31 seconds */
+
+static int wdt_margin = WD_TIMO;
+module_param(wdt_margin, int, 0);
+MODULE_PARM_DESC(wdt_margin, "Watchdog timeout in seconds (default 60s)");
+
+static unsigned long wdt_is_open;
+static int boot_flag;
+
+/**
+ *	wdt_ping:
+ *
+ *	Reload counter one with the watchdog timeout. We don't bother reloading
+ *	the cascade counter.
+ */
+static void wdt_ping(void)
+{
+	unsigned char i2c_data[2];
+	struct i2c_msg msgs1[1] = {
+		{
+			.addr	= save_client->addr,
+			.flags	= 0,
+			.len	= 2,
+			.buf	= i2c_data,
+		},
+	};
+	i2c_data[0] = 0x09;		/* watchdog register */
+
+	if (wdt_margin > 31)
+		i2c_data[1] = (wdt_margin & 0xFC) | 0x83; /* resolution = 4s */
+	else
+		/*
+		 * WDS = 1 (0x80), mulitplier = WD_TIMO, resolution = 1s (0x02)
+		 */
+		i2c_data[1] = wdt_margin<<2 | 0x82;
+
+	i2c_transfer(save_client->adapter, msgs1, 1);
+}
+
+/**
+ *	wdt_disable:
+ *
+ *	disables watchdog.
+ */
+static void wdt_disable(void)
+{
+	unsigned char i2c_data[2], i2c_buf[0x10];
+	struct i2c_msg msgs0[2] = {
+		{
+			.addr	= save_client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= i2c_data,
+		},
+		{
+			.addr	= save_client->addr,
+			.flags	= I2C_M_RD,
+			.len	= 1,
+			.buf	= i2c_buf,
+		},
+	};
+	struct i2c_msg msgs1[1] = {
+		{
+			.addr	= save_client->addr,
+			.flags	= 0,
+			.len	= 2,
+			.buf	= i2c_data,
+		},
+	};
+
+	i2c_data[0] = 0x09;
+	i2c_transfer(save_client->adapter, msgs0, 2);
+
+	i2c_data[0] = 0x09;
+	i2c_data[1] = 0x00;
+	i2c_transfer(save_client->adapter, msgs1, 1);
+}
+
+/**
+ *	wdt_write:
+ *	@file: file handle to the watchdog
+ *	@buf: buffer to write (unused as data does not matter here
+ *	@count: count of bytes
+ *	@ppos: pointer to the position to write. No seeks allowed
+ *
+ *	A write to a watchdog device is defined as a keepalive signal. Any
+ *	write of data will do, as we we don't define content meaning.
+ */
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	/*  Can't seek (pwrite) on this device
+	if (ppos != &file->f_pos)
+	return -ESPIPE;
+	*/
+	if (count) {
+		wdt_ping();
+		return 1;
+	}
+	return 0;
+}
+
+static ssize_t wdt_read(struct file *file, char __user *buf,
+			size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+/**
+ *	wdt_ioctl:
+ *	@inode: inode of the device
+ *	@file: file handle to the device
+ *	@cmd: watchdog command
+ *	@arg: argument pointer
+ *
+ *	The watchdog API defines a common set of functions for all watchdogs
+ *	according to their available features. We only actually usefully support
+ *	querying capabilities and current status.
+ */
+static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg)
+{
+	int new_margin, rv;
+	static struct watchdog_info ident = {
+		.options = WDIOF_POWERUNDER | WDIOF_KEEPALIVEPING |
+			WDIOF_SETTIMEOUT,
+		.firmware_version = 1,
+		.identity = "M41T80 WTD"
+	};
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		return copy_to_user((struct watchdog_info __user *)arg, &ident,
+				    sizeof(ident)) ? -EFAULT : 0;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(boot_flag, (int __user *)arg);
+	case WDIOC_KEEPALIVE:
+		wdt_ping();
+		return 0;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, (int __user *)arg))
+			return -EFAULT;
+		/* Arbitrary, can't find the card's limits */
+		if (new_margin < 1 || new_margin > 124)
+			return -EINVAL;
+		wdt_margin = new_margin;
+		wdt_ping();
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		return put_user(wdt_margin, (int __user *)arg);
+
+	case WDIOC_SETOPTIONS:
+		if (copy_from_user(&rv, (int __user *)arg, sizeof(int)))
+			return -EFAULT;
+
+		if (rv & WDIOS_DISABLECARD) {
+			printk(KERN_INFO
+			       "rtc-m41t80: disable watchdog\n");
+			wdt_disable();
+		}
+
+		if (rv & WDIOS_ENABLECARD) {
+			printk(KERN_INFO
+			       "rtc-m41t80: enable watchdog\n");
+			wdt_ping();
+		}
+
+		return -EINVAL;
+	}
+	return -ENOTTY;
+}
+
+/**
+ *	wdt_open:
+ *	@inode: inode of device
+ *	@file: file handle to device
+ *
+ */
+static int wdt_open(struct inode *inode, struct file *file)
+{
+	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+		if (test_and_set_bit(0, &wdt_is_open))
+			return -EBUSY;
+		/*
+		 *	Activate
+		 */
+		wdt_is_open = 1;
+		return 0;
+	}
+	return -ENODEV;
+}
+
+/**
+ *	wdt_close:
+ *	@inode: inode to board
+ *	@file: file handle to board
+ *
+ */
+static int wdt_release(struct inode *inode, struct file *file)
+{
+	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR)
+		clear_bit(0, &wdt_is_open);
+	return 0;
+}
+
+/**
+ *	notify_sys:
+ *	@this: our notifier block
+ *	@code: the event being reported
+ *	@unused: unused
+ *
+ *	Our notifier is called on system shutdowns. We want to turn the card
+ *	off at reboot otherwise the machine will reboot again during memory
+ *	test or worse yet during the following fsck. This would suck, in fact
+ *	trust me - if it happens it does suck.
+ */
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+			  void *unused)
+{
+	if (code == SYS_DOWN || code == SYS_HALT)
+		/* Disable Watchdog */
+		wdt_disable();
+	return NOTIFY_DONE;
+}
+
+static const struct file_operations wdt_fops = {
+	.owner	= THIS_MODULE,
+	.read	= wdt_read,
+	.ioctl	= wdt_ioctl,
+	.write	= wdt_write,
+	.open	= wdt_open,
+	.release = wdt_release,
+};
+
+static struct miscdevice wdt_dev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &wdt_fops,
+};
+
+/*
+ *	The WDT card needs to learn about soft shutdowns in order to
+ *	turn the timebomb registers off.
+ */
+static struct notifier_block wdt_notifier = {
+	.notifier_call = wdt_notify_sys,
+};
+#endif /* CONFIG_RTC_DRV_M41T80_WDT */
+
+/*
+ *****************************************************************************
+ *
+ *	Driver Interface
+ *
+ *****************************************************************************
+ */
+static int m41t80_probe(struct i2c_client *client)
+{
+	int i, rc = 0;
+	struct rtc_device *rtc = NULL;
+	struct rtc_time tm;
+	const struct m41t80_chip_info *chip;
+	struct m41t80_data *clientdata = NULL;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
+				     | I2C_FUNC_SMBUS_BYTE_DATA)) {
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	dev_info(&client->dev,
+		 "chip found, driver version " DRV_VERSION "\n");
+
+	chip = NULL;
+	for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
+		if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
+			chip = &m41t80_chip_info_tbl[i];
+			break;
+		}
+	}
+	if (!chip) {
+		dev_err(&client->dev, "%s is not supported\n", client->name);
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL);
+	if (!clientdata) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	rtc = rtc_device_register(client->name, &client->dev,
+				  &m41t80_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		rc = PTR_ERR(rtc);
+		rtc = NULL;
+		goto exit;
+	}
+
+	clientdata->rtc = rtc;
+	clientdata->chip = chip;
+	i2c_set_clientdata(client, clientdata);
+
+	/* Make sure HT (Halt Update) bit is cleared */
+	rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);
+	if (rc < 0)
+		goto ht_err;
+
+	if (rc & M41T80_ALHOUR_HT) {
+		if (chip->features & M41T80_FEATURE_HT) {
+			m41t80_get_datetime(client, &tm);
+			dev_info(&client->dev, "HT bit was set!\n");
+			dev_info(&client->dev,
+				 "Power Down at "
+				 "%04i-%02i-%02i %02i:%02i:%02i\n",
+				 tm.tm_year + 1900,
+				 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+				 tm.tm_min, tm.tm_sec);
+		}
+		if (i2c_smbus_write_byte_data(client,
+					      M41T80_REG_ALARM_HOUR,
+					      rc & ~M41T80_ALHOUR_HT) < 0)
+			goto ht_err;
+	}
+
+	/* Make sure ST (stop) bit is cleared */
+	rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC);
+	if (rc < 0)
+		goto st_err;
+
+	if (rc & M41T80_SEC_ST) {
+		if (i2c_smbus_write_byte_data(client, M41T80_REG_SEC,
+					      rc & ~M41T80_SEC_ST) < 0)
+			goto st_err;
+	}
+
+	rc = m41t80_sysfs_register(&client->dev);
+	if (rc)
+		goto exit;
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+	if (chip->features & M41T80_FEATURE_HT) {
+		rc = misc_register(&wdt_dev);
+		if (rc)
+			goto exit;
+		rc = register_reboot_notifier(&wdt_notifier);
+		if (rc) {
+			misc_deregister(&wdt_dev);
+			goto exit;
+		}
+		save_client = client;
+	}
+#endif
+	return 0;
+
+st_err:
+	rc = -EIO;
+	dev_err(&client->dev, "Can't clear ST bit\n");
+	goto exit;
+ht_err:
+	rc = -EIO;
+	dev_err(&client->dev, "Can't clear HT bit\n");
+	goto exit;
+
+exit:
+	if (rtc)
+		rtc_device_unregister(rtc);
+	kfree(clientdata);
+	return rc;
+}
+
+static int m41t80_remove(struct i2c_client *client)
+{
+	struct m41t80_data *clientdata = i2c_get_clientdata(client);
+	struct rtc_device *rtc = clientdata->rtc;
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+	if (clientdata->chip->features & M41T80_FEATURE_HT) {
+		misc_deregister(&wdt_dev);
+		unregister_reboot_notifier(&wdt_notifier);
+	}
+#endif
+	if (rtc)
+		rtc_device_unregister(rtc);
+	kfree(clientdata);
+
+	return 0;
+}
+
+static struct i2c_driver m41t80_driver = {
+	.driver = {
+		.name = "m41t80",
+	},
+	.probe = m41t80_probe,
+	.remove = m41t80_remove,
+};
+
+static int __init m41t80_rtc_init(void)
+{
+	return i2c_add_driver(&m41t80_driver);
+}
+
+static void __exit m41t80_rtc_exit(void)
+{
+	i2c_del_driver(&m41t80_driver);
+}
+
+MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>");
+MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(m41t80_rtc_init);
+module_exit(m41t80_rtc_exit);
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
new file mode 100644
index 0000000..33b7523
--- /dev/null
+++ b/drivers/rtc/rtc-m48t59.c
@@ -0,0 +1,491 @@
+/*
+ * ST M48T59 RTC driver
+ *
+ * Copyright (c) 2007 Wind River Systems, Inc.
+ *
+ * Author: Mark Zhan <rongkai.zhan@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/rtc/m48t59.h>
+#include <linux/bcd.h>
+
+#ifndef NO_IRQ
+#define NO_IRQ	(-1)
+#endif
+
+#define M48T59_READ(reg)	pdata->read_byte(dev, reg)
+#define M48T59_WRITE(val, reg)	pdata->write_byte(dev, reg, val)
+
+#define M48T59_SET_BITS(mask, reg)	\
+	M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
+#define M48T59_CLEAR_BITS(mask, reg)	\
+	M48T59_WRITE((M48T59_READ(reg) & ~(mask)), (reg))
+
+struct m48t59_private {
+	void __iomem *ioaddr;
+	unsigned int size; /* iomem size */
+	unsigned int irq;
+	struct rtc_device *rtc;
+	spinlock_t lock; /* serialize the NVRAM and RTC access */
+};
+
+/*
+ * This is the generic access method when the chip is memory-mapped
+ */
+static void
+m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+	writeb(val, m48t59->ioaddr+ofs);
+}
+
+static u8
+m48t59_mem_readb(struct device *dev, u32 ofs)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+	return readb(m48t59->ioaddr+ofs);
+}
+
+/*
+ * NOTE: M48T59 only uses BCD mode
+ */
+static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	unsigned long flags;
+	u8 val;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	/* Issue the READ command */
+	M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+
+	tm->tm_year	= BCD2BIN(M48T59_READ(M48T59_YEAR));
+	/* tm_mon is 0-11 */
+	tm->tm_mon	= BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
+	tm->tm_mday	= BCD2BIN(M48T59_READ(M48T59_MDAY));
+
+	val = M48T59_READ(M48T59_WDAY);
+	if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
+		dev_dbg(dev, "Century bit is enabled\n");
+		tm->tm_year += 100;	/* one century */
+	}
+
+	tm->tm_wday	= BCD2BIN(val & 0x07);
+	tm->tm_hour	= BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F);
+	tm->tm_min	= BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F);
+	tm->tm_sec	= BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F);
+
+	/* Clear the READ bit */
+	M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
+		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+	return 0;
+}
+
+static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	unsigned long flags;
+	u8 val = 0;
+
+	dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n",
+		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	/* Issue the WRITE command */
+	M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+
+	M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC);
+	M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN);
+	M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR);
+	M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY);
+	/* tm_mon is 0-11 */
+	M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
+	M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
+
+	if (tm->tm_year/100)
+		val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
+	val |= (BIN2BCD(tm->tm_wday) & 0x07);
+	M48T59_WRITE(val, M48T59_WDAY);
+
+	/* Clear the WRITE bit */
+	M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+	return 0;
+}
+
+/*
+ * Read alarm time and date in RTC
+ */
+static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	struct rtc_time *tm = &alrm->time;
+	unsigned long flags;
+	u8 val;
+
+	/* If no irq, we don't support ALARM */
+	if (m48t59->irq == NO_IRQ)
+		return -EIO;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	/* Issue the READ command */
+	M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+
+	tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR));
+	/* tm_mon is 0-11 */
+	tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
+
+	val = M48T59_READ(M48T59_WDAY);
+	if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
+		tm->tm_year += 100;	/* one century */
+
+	tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE));
+	tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR));
+	tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN));
+	tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC));
+
+	/* Clear the READ bit */
+	M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
+		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+	return 0;
+}
+
+/*
+ * Set alarm time and date in RTC
+ */
+static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	struct rtc_time *tm = &alrm->time;
+	u8 mday, hour, min, sec;
+	unsigned long flags;
+
+	/* If no irq, we don't support ALARM */
+	if (m48t59->irq == NO_IRQ)
+		return -EIO;
+
+	/*
+	 * 0xff means "always match"
+	 */
+	mday = tm->tm_mday;
+	mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
+	if (mday == 0xff)
+		mday = M48T59_READ(M48T59_MDAY);
+
+	hour = tm->tm_hour;
+	hour = (hour < 24) ? BIN2BCD(hour) : 0x00;
+
+	min = tm->tm_min;
+	min = (min < 60) ? BIN2BCD(min) : 0x00;
+
+	sec = tm->tm_sec;
+	sec = (sec < 60) ? BIN2BCD(sec) : 0x00;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	/* Issue the WRITE command */
+	M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+
+	M48T59_WRITE(mday, M48T59_ALARM_DATE);
+	M48T59_WRITE(hour, M48T59_ALARM_HOUR);
+	M48T59_WRITE(min, M48T59_ALARM_MIN);
+	M48T59_WRITE(sec, M48T59_ALARM_SEC);
+
+	/* Clear the WRITE bit */
+	M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
+		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+	return 0;
+}
+
+/*
+ * Handle commands from user-space
+ */
+static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd,
+			unsigned long arg)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	switch (cmd) {
+	case RTC_AIE_OFF:	/* alarm interrupt off */
+		M48T59_WRITE(0x00, M48T59_INTR);
+		break;
+	case RTC_AIE_ON:	/* alarm interrupt on */
+		M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	return ret;
+}
+
+static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	unsigned long flags;
+	u8 val;
+
+	spin_lock_irqsave(&m48t59->lock, flags);
+	val = M48T59_READ(M48T59_FLAGS);
+	spin_unlock_irqrestore(&m48t59->lock, flags);
+
+	seq_printf(seq, "battery\t\t: %s\n",
+		 (val & M48T59_FLAGS_BF) ? "low" : "normal");
+	return 0;
+}
+
+/*
+ * IRQ handler for the RTC
+ */
+static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id)
+{
+	struct device *dev = (struct device *)dev_id;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	u8 event;
+
+	spin_lock(&m48t59->lock);
+	event = M48T59_READ(M48T59_FLAGS);
+	spin_unlock(&m48t59->lock);
+
+	if (event & M48T59_FLAGS_AF) {
+		rtc_update_irq(m48t59->rtc, 1, (RTC_AF | RTC_IRQF));
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static const struct rtc_class_ops m48t59_rtc_ops = {
+	.ioctl		= m48t59_rtc_ioctl,
+	.read_time	= m48t59_rtc_read_time,
+	.set_time	= m48t59_rtc_set_time,
+	.read_alarm	= m48t59_rtc_readalarm,
+	.set_alarm	= m48t59_rtc_setalarm,
+	.proc		= m48t59_rtc_proc,
+};
+
+static ssize_t m48t59_nvram_read(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t pos, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	ssize_t cnt = 0;
+	unsigned long flags;
+
+	for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
+		spin_lock_irqsave(&m48t59->lock, flags);
+		*buf++ = M48T59_READ(cnt);
+		spin_unlock_irqrestore(&m48t59->lock, flags);
+	}
+
+	return cnt;
+}
+
+static ssize_t m48t59_nvram_write(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t pos, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+	ssize_t cnt = 0;
+	unsigned long flags;
+
+	for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
+		spin_lock_irqsave(&m48t59->lock, flags);
+		M48T59_WRITE(*buf++, cnt);
+		spin_unlock_irqrestore(&m48t59->lock, flags);
+	}
+
+	return cnt;
+}
+
+static struct bin_attribute m48t59_nvram_attr = {
+	.attr = {
+		.name = "nvram",
+		.mode = S_IRUGO | S_IWUGO,
+		.owner = THIS_MODULE,
+	},
+	.read = m48t59_nvram_read,
+	.write = m48t59_nvram_write,
+};
+
+static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
+{
+	struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+	struct m48t59_private *m48t59 = NULL;
+	struct resource *res;
+	int ret = -ENOMEM;
+
+	/* This chip could be memory-mapped or I/O-mapped */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+		if (!res)
+			return -EINVAL;
+	}
+
+	if (res->flags & IORESOURCE_IO) {
+		/* If we are I/O-mapped, the platform should provide
+		 * the operations accessing chip registers.
+		 */
+		if (!pdata || !pdata->write_byte || !pdata->read_byte)
+			return -EINVAL;
+	} else if (res->flags & IORESOURCE_MEM) {
+		/* we are memory-mapped */
+		if (!pdata) {
+			pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+			if (!pdata)
+				return -ENOMEM;
+			/* Ensure we only kmalloc platform data once */
+			pdev->dev.platform_data = pdata;
+		}
+
+		/* Try to use the generic memory read/write ops */
+		if (!pdata->write_byte)
+			pdata->write_byte = m48t59_mem_writeb;
+		if (!pdata->read_byte)
+			pdata->read_byte = m48t59_mem_readb;
+	}
+
+	m48t59 = kzalloc(sizeof(*m48t59), GFP_KERNEL);
+	if (!m48t59)
+		return -ENOMEM;
+
+	m48t59->size = res->end - res->start + 1;
+	m48t59->ioaddr = ioremap(res->start, m48t59->size);
+	if (!m48t59->ioaddr)
+		goto out;
+
+	/* Try to get irq number. We also can work in
+	 * the mode without IRQ.
+	 */
+	m48t59->irq = platform_get_irq(pdev, 0);
+	if (m48t59->irq < 0)
+		m48t59->irq = NO_IRQ;
+
+	if (m48t59->irq != NO_IRQ) {
+		ret = request_irq(m48t59->irq, m48t59_rtc_interrupt,
+			IRQF_SHARED, "rtc-m48t59", &pdev->dev);
+		if (ret)
+			goto out;
+	}
+
+	m48t59->rtc = rtc_device_register("m48t59", &pdev->dev,
+				&m48t59_rtc_ops, THIS_MODULE);
+	if (IS_ERR(m48t59->rtc)) {
+		ret = PTR_ERR(m48t59->rtc);
+		goto out;
+	}
+
+	ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
+	if (ret)
+		goto out;
+
+	spin_lock_init(&m48t59->lock);
+	platform_set_drvdata(pdev, m48t59);
+	return 0;
+
+out:
+	if (!IS_ERR(m48t59->rtc))
+		rtc_device_unregister(m48t59->rtc);
+	if (m48t59->irq != NO_IRQ)
+		free_irq(m48t59->irq, &pdev->dev);
+	if (m48t59->ioaddr)
+		iounmap(m48t59->ioaddr);
+	if (m48t59)
+		kfree(m48t59);
+	return ret;
+}
+
+static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
+{
+	struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+	sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
+	if (!IS_ERR(m48t59->rtc))
+		rtc_device_unregister(m48t59->rtc);
+	if (m48t59->ioaddr)
+		iounmap(m48t59->ioaddr);
+	if (m48t59->irq != NO_IRQ)
+		free_irq(m48t59->irq, &pdev->dev);
+	platform_set_drvdata(pdev, NULL);
+	kfree(m48t59);
+	return 0;
+}
+
+static struct platform_driver m48t59_rtc_platdrv = {
+	.driver		= {
+		.name	= "rtc-m48t59",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= m48t59_rtc_probe,
+	.remove		= __devexit_p(m48t59_rtc_remove),
+};
+
+static int __init m48t59_rtc_init(void)
+{
+	return platform_driver_register(&m48t59_rtc_platdrv);
+}
+
+static void __exit m48t59_rtc_exit(void)
+{
+	platform_driver_unregister(&m48t59_rtc_platdrv);
+}
+
+module_init(m48t59_rtc_init);
+module_exit(m48t59_rtc_exit);
+
+MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
+MODULE_DESCRIPTION("M48T59 RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 09bbe575..6b67b50 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -13,13 +13,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 
-#define DRV_VERSION "0.4"
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD;
+#define DRV_VERSION "0.5"
 
 
 /*
@@ -88,9 +82,6 @@
 	unsigned		has_irq:1;
 	char			buf[17];
 	char			*regs;
-
-	/* on conversion to a "new style" i2c driver, this vanishes */
-	struct i2c_client	dev;
 };
 
 static int rs5c_get_regs(struct rs5c372 *rs5c)
@@ -483,25 +474,35 @@
 	return err;
 }
 
+static void rs5c_sysfs_unregister(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_trim);
+	device_remove_file(dev, &dev_attr_osc);
+}
+
 #else
 static int rs5c_sysfs_register(struct device *dev)
 {
 	return 0;
 }
+
+static void rs5c_sysfs_unregister(struct device *dev)
+{
+	/* nothing */
+}
 #endif	/* SYSFS */
 
 static struct i2c_driver rs5c372_driver;
 
-static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
+static int rs5c372_probe(struct i2c_client *client)
 {
 	int err = 0;
-	struct i2c_client *client;
 	struct rs5c372 *rs5c372;
 	struct rtc_time tm;
 
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		err = -ENODEV;
 		goto exit;
 	}
@@ -514,35 +515,22 @@
 	/* we read registers 0x0f then 0x00-0x0f; skip the first one */
 	rs5c372->regs=&rs5c372->buf[1];
 
-	/* On conversion to a "new style" i2c driver, we'll be handed
-	 * the i2c_client (we won't create it)
-	 */
-	client = &rs5c372->dev;
 	rs5c372->client = client;
-
-	/* I2C client */
-	client->addr = address;
-	client->driver = &rs5c372_driver;
-	client->adapter = adapter;
-
-	strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE);
-
 	i2c_set_clientdata(client, rs5c372);
 
-	/* Inform the i2c layer */
-	if ((err = i2c_attach_client(client)))
-		goto exit_kfree;
-
 	err = rs5c_get_regs(rs5c372);
 	if (err < 0)
-		goto exit_detach;
+		goto exit_kfree;
 
-	/* For "new style" drivers, irq is in i2c_client and chip type
-	 * info comes from i2c_client.dev.platform_data.  Meanwhile:
-	 *
-	 * STICK BOARD-SPECIFIC SETUP CODE RIGHT HERE
-	 */
-	if (rs5c372->type == rtc_undef) {
+	if (strcmp(client->name, "rs5c372a") == 0)
+		rs5c372->type = rtc_rs5c372a;
+	else if (strcmp(client->name, "rs5c372b") == 0)
+		rs5c372->type = rtc_rs5c372b;
+	else if (strcmp(client->name, "rv5c386") == 0)
+		rs5c372->type = rtc_rv5c386;
+	else if (strcmp(client->name, "rv5c387a") == 0)
+		rs5c372->type = rtc_rv5c387a;
+	else {
 		rs5c372->type = rtc_rs5c372b;
 		dev_warn(&client->dev, "assuming rs5c372b\n");
 	}
@@ -567,7 +555,7 @@
 		break;
 	default:
 		dev_err(&client->dev, "unknown RTC type\n");
-		goto exit_detach;
+		goto exit_kfree;
 	}
 
 	/* if the oscillator lost power and no other software (like
@@ -601,7 +589,7 @@
 
 		if ((i2c_master_send(client, buf, 3)) != 3) {
 			dev_err(&client->dev, "setup error\n");
-			goto exit_detach;
+			goto exit_kfree;
 		}
 		rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
 		rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
@@ -621,14 +609,14 @@
 			rs5c372->time24 ? "24hr" : "am/pm"
 			);
 
-	/* FIXME when client->irq exists, use it to register alarm irq */
+	/* REVISIT use client->irq to register alarm irq ... */
 
 	rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name,
 				&client->dev, &rs5c372_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rs5c372->rtc)) {
 		err = PTR_ERR(rs5c372->rtc);
-		goto exit_detach;
+		goto exit_kfree;
 	}
 
 	err = rs5c_sysfs_register(&client->dev);
@@ -640,9 +628,6 @@
 exit_devreg:
 	rtc_device_unregister(rs5c372->rtc);
 
-exit_detach:
-	i2c_detach_client(client);
-
 exit_kfree:
 	kfree(rs5c372);
 
@@ -650,24 +635,12 @@
 	return err;
 }
 
-static int rs5c372_attach(struct i2c_adapter *adapter)
+static int rs5c372_remove(struct i2c_client *client)
 {
-	return i2c_probe(adapter, &addr_data, rs5c372_probe);
-}
-
-static int rs5c372_detach(struct i2c_client *client)
-{
-	int err;
 	struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
 
-	if (rs5c372->rtc)
-		rtc_device_unregister(rs5c372->rtc);
-
-	/* REVISIT properly destroy the sysfs files ... */
-
-	if ((err = i2c_detach_client(client)))
-		return err;
-
+	rtc_device_unregister(rs5c372->rtc);
+	rs5c_sysfs_unregister(&client->dev);
 	kfree(rs5c372);
 	return 0;
 }
@@ -676,8 +649,8 @@
 	.driver		= {
 		.name	= "rtc-rs5c372",
 	},
-	.attach_adapter	= &rs5c372_attach,
-	.detach_client	= &rs5c372_detach,
+	.probe		= rs5c372_probe,
+	.remove		= rs5c372_remove,
 };
 
 static __init int rs5c372_init(void)
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index af7596e..ce2f78d 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -17,10 +17,11 @@
  *  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/err.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
@@ -30,25 +31,11 @@
 #include <asm/div64.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/vr41xx/irq.h>
 
 MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
 MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
 MODULE_LICENSE("GPL");
 
-#define RTC1_TYPE1_START	0x0b0000c0UL
-#define RTC1_TYPE1_END		0x0b0000dfUL
-#define RTC2_TYPE1_START	0x0b0001c0UL
-#define RTC2_TYPE1_END		0x0b0001dfUL
-
-#define RTC1_TYPE2_START	0x0f000100UL
-#define RTC1_TYPE2_END		0x0f00011fUL
-#define RTC2_TYPE2_START	0x0f000120UL
-#define RTC2_TYPE2_END		0x0f00013fUL
-
-#define RTC1_SIZE		0x20
-#define RTC2_SIZE		0x20
-
 /* RTC 1 registers */
 #define ETIMELREG		0x00
 #define ETIMEMREG		0x02
@@ -98,13 +85,8 @@
 static unsigned long periodic_frequency;
 static unsigned long periodic_count;
 static unsigned int alarm_enabled;
-
-struct resource rtc_resource[2] = {
-	{	.name	= rtc_name,
-		.flags	= IORESOURCE_MEM,	},
-	{	.name	= rtc_name,
-		.flags	= IORESOURCE_MEM,	},
-};
+static int aie_irq = -1;
+static int pie_irq = -1;
 
 static inline unsigned long read_elapsed_second(void)
 {
@@ -150,8 +132,8 @@
 
 	spin_unlock_irq(&rtc_lock);
 
-	disable_irq(ELAPSEDTIME_IRQ);
-	disable_irq(RTCLONG1_IRQ);
+	disable_irq(aie_irq);
+	disable_irq(pie_irq);
 }
 
 static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
@@ -209,14 +191,14 @@
 	spin_lock_irq(&rtc_lock);
 
 	if (alarm_enabled)
-		disable_irq(ELAPSEDTIME_IRQ);
+		disable_irq(aie_irq);
 
 	rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
 	rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
 	rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
 
 	if (wkalrm->enabled)
-		enable_irq(ELAPSEDTIME_IRQ);
+		enable_irq(aie_irq);
 
 	alarm_enabled = wkalrm->enabled;
 
@@ -234,7 +216,7 @@
 		spin_lock_irq(&rtc_lock);
 
 		if (!alarm_enabled) {
-			enable_irq(ELAPSEDTIME_IRQ);
+			enable_irq(aie_irq);
 			alarm_enabled = 1;
 		}
 
@@ -244,17 +226,17 @@
 		spin_lock_irq(&rtc_lock);
 
 		if (alarm_enabled) {
-			disable_irq(ELAPSEDTIME_IRQ);
+			disable_irq(aie_irq);
 			alarm_enabled = 0;
 		}
 
 		spin_unlock_irq(&rtc_lock);
 		break;
 	case RTC_PIE_ON:
-		enable_irq(RTCLONG1_IRQ);
+		enable_irq(pie_irq);
 		break;
 	case RTC_PIE_OFF:
-		disable_irq(RTCLONG1_IRQ);
+		disable_irq(pie_irq);
 		break;
 	case RTC_IRQP_READ:
 		return put_user(periodic_frequency, (unsigned long __user *)arg);
@@ -331,31 +313,37 @@
 
 static int __devinit rtc_probe(struct platform_device *pdev)
 {
+	struct resource *res;
 	struct rtc_device *rtc;
-	unsigned int irq;
 	int retval;
 
-	if (pdev->num_resources != 2)
+	if (pdev->num_resources != 4)
 		return -EBUSY;
 
-	rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE);
-	if (rtc1_base == NULL)
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
 		return -EBUSY;
 
-	rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE);
-	if (rtc2_base == NULL) {
-		iounmap(rtc1_base);
-		rtc1_base = NULL;
+	rtc1_base = ioremap(res->start, res->end - res->start + 1);
+	if (!rtc1_base)
 		return -EBUSY;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		retval = -EBUSY;
+		goto err_rtc1_iounmap;
+	}
+
+	rtc2_base = ioremap(res->start, res->end - res->start + 1);
+	if (!rtc2_base) {
+		retval = -EBUSY;
+		goto err_rtc1_iounmap;
 	}
 
 	rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
-		iounmap(rtc1_base);
-		iounmap(rtc2_base);
-		rtc1_base = NULL;
-		rtc2_base = NULL;
-		return PTR_ERR(rtc);
+		retval = PTR_ERR(rtc);
+		goto err_iounmap_all;
 	}
 
 	spin_lock_irq(&rtc_lock);
@@ -368,35 +356,50 @@
 
 	spin_unlock_irq(&rtc_lock);
 
-	irq = ELAPSEDTIME_IRQ;
-	retval = request_irq(irq, elapsedtime_interrupt, IRQF_DISABLED,
-	                     "elapsed_time", pdev);
-	if (retval == 0) {
-		irq = RTCLONG1_IRQ;
-		retval = request_irq(irq, rtclong1_interrupt, IRQF_DISABLED,
-		                     "rtclong1", pdev);
+	aie_irq = platform_get_irq(pdev, 0);
+	if (aie_irq < 0 || aie_irq >= NR_IRQS) {
+		retval = -EBUSY;
+		goto err_device_unregister;
 	}
 
-	if (retval < 0) {
-		printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
-		rtc_device_unregister(rtc);
-		if (irq == RTCLONG1_IRQ)
-			free_irq(ELAPSEDTIME_IRQ, NULL);
-		iounmap(rtc1_base);
-		iounmap(rtc2_base);
-		rtc1_base = NULL;
-		rtc2_base = NULL;
-		return retval;
-	}
+	retval = request_irq(aie_irq, elapsedtime_interrupt, IRQF_DISABLED,
+	                     "elapsed_time", pdev);
+	if (retval < 0)
+		goto err_device_unregister;
+
+	pie_irq = platform_get_irq(pdev, 1);
+	if (pie_irq < 0 || pie_irq >= NR_IRQS)
+		goto err_free_irq;
+
+	retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
+		             "rtclong1", pdev);
+	if (retval < 0)
+		goto err_free_irq;
 
 	platform_set_drvdata(pdev, rtc);
 
-	disable_irq(ELAPSEDTIME_IRQ);
-	disable_irq(RTCLONG1_IRQ);
+	disable_irq(aie_irq);
+	disable_irq(pie_irq);
 
 	printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
 
 	return 0;
+
+err_free_irq:
+	free_irq(aie_irq, pdev);
+
+err_device_unregister:
+	rtc_device_unregister(rtc);
+
+err_iounmap_all:
+	iounmap(rtc2_base);
+	rtc2_base = NULL;
+
+err_rtc1_iounmap:
+	iounmap(rtc1_base);
+	rtc1_base = NULL;
+
+	return retval;
 }
 
 static int __devexit rtc_remove(struct platform_device *pdev)
@@ -404,23 +407,21 @@
 	struct rtc_device *rtc;
 
 	rtc = platform_get_drvdata(pdev);
-	if (rtc != NULL)
+	if (rtc)
 		rtc_device_unregister(rtc);
 
 	platform_set_drvdata(pdev, NULL);
 
-	free_irq(ELAPSEDTIME_IRQ, NULL);
-	free_irq(RTCLONG1_IRQ, NULL);
-	if (rtc1_base != NULL)
+	free_irq(aie_irq, pdev);
+	free_irq(pie_irq, pdev);
+	if (rtc1_base)
 		iounmap(rtc1_base);
-	if (rtc2_base != NULL)
+	if (rtc2_base)
 		iounmap(rtc2_base);
 
 	return 0;
 }
 
-static struct platform_device *rtc_platform_device;
-
 static struct platform_driver rtc_platform_driver = {
 	.probe		= rtc_probe,
 	.remove		= __devexit_p(rtc_remove),
@@ -432,55 +433,12 @@
 
 static int __init vr41xx_rtc_init(void)
 {
-	int retval;
-
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		rtc_resource[0].start = RTC1_TYPE1_START;
-		rtc_resource[0].end = RTC1_TYPE1_END;
-		rtc_resource[1].start = RTC2_TYPE1_START;
-		rtc_resource[1].end = RTC2_TYPE1_END;
-		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-	case CPU_VR4133:
-		rtc_resource[0].start = RTC1_TYPE2_START;
-		rtc_resource[0].end = RTC1_TYPE2_END;
-		rtc_resource[1].start = RTC2_TYPE2_START;
-		rtc_resource[1].end = RTC2_TYPE2_END;
-		break;
-	default:
-		return -ENODEV;
-		break;
-	}
-
-	rtc_platform_device = platform_device_alloc("RTC", -1);
-	if (rtc_platform_device == NULL)
-		return -ENOMEM;
-
-	retval = platform_device_add_resources(rtc_platform_device,
-				rtc_resource, ARRAY_SIZE(rtc_resource));
-
-	if (retval == 0)
-		retval = platform_device_add(rtc_platform_device);
-
-	if (retval < 0) {
-		platform_device_put(rtc_platform_device);
-		return retval;
-	}
-
-	retval = platform_driver_register(&rtc_platform_driver);
-	if (retval < 0)
-		platform_device_unregister(rtc_platform_device);
-
-	return retval;
+	return platform_driver_register(&rtc_platform_driver);
 }
 
 static void __exit vr41xx_rtc_exit(void)
 {
 	platform_driver_unregister(&rtc_platform_driver);
-	platform_device_unregister(rtc_platform_device);
 }
 
 module_init(vr41xx_rtc_init);
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 513d1a6..b3fae35 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -9,6 +9,9 @@
  *
  * based on a lot of other RTC drivers.
  *
+ * Information and datasheet:
+ * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
+ *
  * 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.
@@ -26,7 +29,7 @@
  * Two bytes need to be written to read a single register,
  * while most other chips just require one and take the second
  * one as the data to be written. To prevent corrupting
- * unknown chips, the user must explicitely set the probe parameter.
+ * unknown chips, the user must explicitly set the probe parameter.
  */
 
 static unsigned short normal_i2c[] = { I2C_CLIENT_END };
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index a1dc8c4..0c081a6 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -14,9 +14,9 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/poll.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
-#include <asm/semaphore.h>
 #include <asm/atomic.h>
 #include <asm/ebcdic.h>
 
@@ -514,7 +514,7 @@
  * to transfer in a readbuffer, which is protected by the readbuffer_mutex.
  */
 static char readbuffer[PAGE_SIZE];
-static DECLARE_MUTEX(readbuffer_mutex);
+static DEFINE_MUTEX(readbuffer_mutex);
 
 static int dasd_eer_open(struct inode *inp, struct file *filp)
 {
@@ -579,7 +579,7 @@
 	struct eerbuffer *eerb;
 
 	eerb = (struct eerbuffer *) filp->private_data;
-	if (down_interruptible(&readbuffer_mutex))
+	if (mutex_lock_interruptible(&readbuffer_mutex))
 		return -ERESTARTSYS;
 
 	spin_lock_irqsave(&bufferlock, flags);
@@ -588,7 +588,7 @@
 		                  /* has been deleted             */
 		eerb->residual = 0;
 		spin_unlock_irqrestore(&bufferlock, flags);
-		up(&readbuffer_mutex);
+		mutex_unlock(&readbuffer_mutex);
 		return -EIO;
 	} else if (eerb->residual > 0) {
 		/* OK we still have a second half of a record to deliver */
@@ -602,7 +602,7 @@
 			if (!tc) {
 				/* no data available */
 				spin_unlock_irqrestore(&bufferlock, flags);
-				up(&readbuffer_mutex);
+				mutex_unlock(&readbuffer_mutex);
 				if (filp->f_flags & O_NONBLOCK)
 					return -EAGAIN;
 				rc = wait_event_interruptible(
@@ -610,7 +610,7 @@
 					eerb->head != eerb->tail);
 				if (rc)
 					return rc;
-				if (down_interruptible(&readbuffer_mutex))
+				if (mutex_lock_interruptible(&readbuffer_mutex))
 					return -ERESTARTSYS;
 				spin_lock_irqsave(&bufferlock, flags);
 			}
@@ -626,11 +626,11 @@
 	spin_unlock_irqrestore(&bufferlock, flags);
 
 	if (copy_to_user(buf, readbuffer, effective_count)) {
-		up(&readbuffer_mutex);
+		mutex_unlock(&readbuffer_mutex);
 		return -EFAULT;
 	}
 
-	up(&readbuffer_mutex);
+	mutex_unlock(&readbuffer_mutex);
 	return effective_count;
 }
 
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 8b3b0f4..ac7e8ef 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -28,6 +28,7 @@
 static struct proc_dir_entry *dasd_devices_entry = NULL;
 static struct proc_dir_entry *dasd_statistics_entry = NULL;
 
+#ifdef CONFIG_DASD_PROFILE
 static char *
 dasd_get_user_string(const char __user *user_buf, size_t user_len)
 {
@@ -47,6 +48,7 @@
 		buffer[user_len] = 0;
 	return buffer;
 }
+#endif /* CONFIG_DASD_PROFILE */
 
 static int
 dasd_devices_show(struct seq_file *m, void *v)
@@ -167,6 +169,7 @@
 	return len;
 }
 
+#ifdef CONFIG_DASD_PROFILE
 static char *
 dasd_statistics_array(char *str, unsigned int *array, int shift)
 {
@@ -180,6 +183,7 @@
 	str += sprintf(str,"\n");
 	return str;
 }
+#endif /* CONFIG_DASD_PROFILE */
 
 static int
 dasd_statistics_read(char *page, char **start, off_t off,
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 1340451..35765f6 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -747,14 +747,9 @@
 static void __exit
 dcssblk_exit(void)
 {
-	int rc;
-
 	PRINT_DEBUG("DCSSBLOCK EXIT...\n");
 	s390_root_dev_unregister(dcssblk_root_dev);
-	rc = unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
-	if (rc) {
-		PRINT_ERR("unregister_blkdev() failed!\n");
-	}
+	unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
 	PRINT_DEBUG("...finished!\n");
 }
 
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index f6ef90e..743944a 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -487,7 +487,7 @@
 } __attribute__ ((packed));
 
 static struct diag210 raw3270_init_diag210;
-static DECLARE_MUTEX(raw3270_init_sem);
+static DEFINE_MUTEX(raw3270_init_mutex);
 
 static int
 raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
@@ -713,7 +713,7 @@
 {
 	int rc;
 
-	down(&raw3270_init_sem);
+	mutex_lock(&raw3270_init_mutex);
 	rp->view = &raw3270_init_view;
 	raw3270_init_view.dev = rp;
 	if (MACHINE_IS_VM)
@@ -722,7 +722,7 @@
 		rc = __raw3270_size_device(rp);
 	raw3270_init_view.dev = NULL;
 	rp->view = NULL;
-	up(&raw3270_init_sem);
+	mutex_unlock(&raw3270_init_mutex);
 	if (rc == 0) {	/* Found something. */
 		/* Try to find a model. */
 		rp->model = 0;
@@ -749,7 +749,7 @@
 {
 	int rc;
 
-	down(&raw3270_init_sem);
+	mutex_lock(&raw3270_init_mutex);
 	memset(&rp->init_request, 0, sizeof(rp->init_request));
 	memset(&rp->init_data, 0, sizeof(rp->init_data));
 	/* Store reset data stream to init_data/init_request */
@@ -764,7 +764,7 @@
 	rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request);
 	raw3270_init_view.dev = NULL;
 	rp->view = NULL;
-	up(&raw3270_init_sem);
+	mutex_unlock(&raw3270_init_mutex);
 	return rc;
 }
 
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index dbb99d1..c7318a1 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -72,6 +72,18 @@
 
 typedef u32 sccb_mask_t;	/* ATTENTION: assumes 32bit mask !!! */
 
+struct sccb_header {
+	u16	length;
+	u8	function_code;
+	u8	control_mask[3];
+	u16	response_code;
+} __attribute__((packed));
+
+extern u64 sclp_facilities;
+
+#define SCLP_HAS_CHP_INFO	(sclp_facilities & 0x8000000000000000ULL)
+#define SCLP_HAS_CHP_RECONFIG	(sclp_facilities & 0x2000000000000000ULL)
+
 struct gds_subvector {
 	u8	length;
 	u8	key;
diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c
index a66b914..c68f5e7 100644
--- a/drivers/s390/char/sclp_chp.c
+++ b/drivers/s390/char/sclp_chp.c
@@ -55,6 +55,8 @@
 	struct chp_cfg_data *data;
 	int rc;
 
+	if (!SCLP_HAS_CHP_RECONFIG)
+		return -EOPNOTSUPP;
 	/* Prepare sccb. */
 	data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!data)
@@ -152,6 +154,8 @@
 	struct chp_info_data *data;
 	int rc;
 
+	if (!SCLP_HAS_CHP_INFO)
+		return -EOPNOTSUPP;
 	/* Prepare sccb. */
 	data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!data)
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
index 7bcbe64..a1136e0 100644
--- a/drivers/s390/char/sclp_info.c
+++ b/drivers/s390/char/sclp_info.c
@@ -11,47 +11,106 @@
 #include <asm/sclp.h>
 #include "sclp.h"
 
-struct sclp_readinfo_sccb s390_readinfo_sccb;
+struct sclp_readinfo_sccb {
+	struct	sccb_header header;	/* 0-7 */
+	u16	rnmax;			/* 8-9 */
+	u8	rnsize;			/* 10 */
+	u8	_reserved0[24 - 11];	/* 11-23 */
+	u8	loadparm[8];		/* 24-31 */
+	u8	_reserved1[48 - 32];	/* 32-47 */
+	u64	facilities;		/* 48-55 */
+	u8	_reserved2[91 - 56];	/* 56-90 */
+	u8	flags;			/* 91 */
+	u8	_reserved3[100 - 92];	/* 92-99 */
+	u32	rnsize2;		/* 100-103 */
+	u64	rnmax2;			/* 104-111 */
+	u8	_reserved4[4096 - 112];	/* 112-4095 */
+} __attribute__((packed, aligned(4096)));
+
+static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
+static int __initdata early_readinfo_sccb_valid;
+
+u64 sclp_facilities;
 
 void __init sclp_readinfo_early(void)
 {
-	sclp_cmdw_t command;
-	struct sccb_header *sccb;
 	int ret;
+	int i;
+	struct sclp_readinfo_sccb *sccb;
+	sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
+				  SCLP_CMDW_READ_SCP_INFO};
 
-	__ctl_set_bit(0, 9); /* enable service signal subclass mask */
+	/* Enable service signal subclass mask. */
+	__ctl_set_bit(0, 9);
+	sccb = &early_readinfo_sccb;
+	for (i = 0; i < ARRAY_SIZE(commands); i++) {
+		do {
+			memset(sccb, 0, sizeof(*sccb));
+			sccb->header.length = sizeof(*sccb);
+			sccb->header.control_mask[2] = 0x80;
+			ret = sclp_service_call(commands[i], sccb);
+		} while (ret == -EBUSY);
 
-	sccb = &s390_readinfo_sccb.header;
-	command = SCLP_CMDW_READ_SCP_INFO_FORCED;
-	while (1) {
-		u16 response;
-
-		memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
-		sccb->length = sizeof(s390_readinfo_sccb);
-		sccb->control_mask[2] = 0x80;
-
-		ret = sclp_service_call(command, &s390_readinfo_sccb);
-
-		if (ret == -EIO)
-			goto out;
-		if (ret == -EBUSY)
-			continue;
-
+		if (ret)
+			break;
 		__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
 				PSW_MASK_WAIT | PSW_DEFAULT_KEY);
 		local_irq_disable();
+		/*
+		 * Contents of the sccb might have changed
+		 * therefore a barrier is needed.
+		 */
 		barrier();
-
-		response = sccb->response_code;
-
-		if (response == 0x10)
+		if (sccb->header.response_code == 0x10) {
+			early_readinfo_sccb_valid = 1;
 			break;
-
-		if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
+		}
+		if (sccb->header.response_code != 0x1f0)
 			break;
-
-		command = SCLP_CMDW_READ_SCP_INFO;
 	}
-out:
-	__ctl_clear_bit(0, 9); /* disable service signal subclass mask */
+	/* Disable service signal subclass mask again. */
+	__ctl_clear_bit(0, 9);
+}
+
+void __init sclp_facilities_detect(void)
+{
+	if (!early_readinfo_sccb_valid)
+		return;
+	sclp_facilities = early_readinfo_sccb.facilities;
+}
+
+unsigned long long __init sclp_memory_detect(void)
+{
+	unsigned long long memsize;
+	struct sclp_readinfo_sccb *sccb;
+
+	if (!early_readinfo_sccb_valid)
+		return 0;
+	sccb = &early_readinfo_sccb;
+	if (sccb->rnsize)
+		memsize = sccb->rnsize << 20;
+	else
+		memsize = sccb->rnsize2 << 20;
+	if (sccb->rnmax)
+		memsize *= sccb->rnmax;
+	else
+		memsize *= sccb->rnmax2;
+	return memsize;
+}
+
+/*
+ * This function will be called after sclp_memory_detect(), which gets called
+ * early from early.c code. Therefore the sccb should have valid contents.
+ */
+void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
+{
+	struct sclp_readinfo_sccb *sccb;
+
+	if (!early_readinfo_sccb_valid)
+		return;
+	sccb = &early_readinfo_sccb;
+	info->is_valid = 1;
+	if (sccb->flags & 0x2)
+		info->has_dump = 1;
+	memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
 }
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index fce3dac..82e6a6b 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -175,13 +175,12 @@
 
 static const struct file_operations vmcp_fops = {
 	.owner		= THIS_MODULE,
-	.open		= &vmcp_open,
-	.release	= &vmcp_release,
-	.read		= &vmcp_read,
-	.llseek		= &no_llseek,
-	.write		= &vmcp_write,
-	.unlocked_ioctl	= &vmcp_ioctl,
-	.compat_ioctl	= &vmcp_ioctl
+	.open		= vmcp_open,
+	.release	= vmcp_release,
+	.read		= vmcp_read,
+	.write		= vmcp_write,
+	.unlocked_ioctl	= vmcp_ioctl,
+	.compat_ioctl	= vmcp_ioctl
 };
 
 static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index a5a00e9..12f7a4c 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -835,7 +835,7 @@
 }
 
 
-static int vmlogrdr_init(void)
+static int __init vmlogrdr_init(void)
 {
 	int rc;
 	int i;
@@ -885,7 +885,7 @@
 }
 
 
-static void vmlogrdr_exit(void)
+static void __exit vmlogrdr_exit(void)
 {
 	vmlogrdr_cleanup();
 	printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 66eb068..3712ede 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -156,7 +156,7 @@
 	return rc;
 }
 
-static int memcpy_real_user(__user void *dest, unsigned long src, size_t count)
+static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
 {
 	static char buf[4096];
 	int offs = 0, size;
@@ -267,7 +267,9 @@
 	u64 tod;
 	cpuid_t cpu_id;
 	u32 arch_id;
+	u32 volnr;
 	u32 build_arch;
+	u64 rmem_size;
 	char pad2[4016];
 } __attribute__((packed,__aligned__(16)));
 
@@ -559,6 +561,7 @@
 	else
 		hdr->arch_id = DUMP_ARCH_S390;
 	hdr->mem_size = sys_info.mem_size;
+	hdr->rmem_size = sys_info.mem_size;
 	hdr->mem_end = sys_info.mem_size;
 	hdr->num_pages = sys_info.mem_size / PAGE_SIZE;
 	hdr->tod = get_clock();
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index ac289e6..b57d93d 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -141,8 +141,9 @@
 /*
  * Channel measurement related functions
  */
-static ssize_t chp_measurement_chars_read(struct kobject *kobj, char *buf,
-					  loff_t off, size_t count)
+static ssize_t chp_measurement_chars_read(struct kobject *kobj,
+					  struct bin_attribute *bin_attr,
+					  char *buf, loff_t off, size_t count)
 {
 	struct channel_path *chp;
 	unsigned int size;
@@ -165,7 +166,6 @@
 	.attr = {
 		.name = "measurement_chars",
 		.mode = S_IRUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = sizeof(struct cmg_chars),
 	.read = chp_measurement_chars_read,
@@ -193,8 +193,9 @@
 	} while (reference_buf.values[0] != buf->values[0]);
 }
 
-static ssize_t chp_measurement_read(struct kobject *kobj, char *buf,
-				    loff_t off, size_t count)
+static ssize_t chp_measurement_read(struct kobject *kobj,
+				    struct bin_attribute *bin_attr,
+				    char *buf, loff_t off, size_t count)
 {
 	struct channel_path *chp;
 	struct channel_subsystem *css;
@@ -217,7 +218,6 @@
 	.attr = {
 		.name = "measurement",
 		.mode = S_IRUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = sizeof(struct cmg_entry),
 	.read = chp_measurement_read,
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index a8b373f..6b264bd 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -296,25 +296,19 @@
 		device_del(&cdev->dev);
 }
 
-static void
-ccw_device_remove_disconnected(struct ccw_device *cdev)
+static void ccw_device_remove_orphan_cb(struct device *dev)
+{
+	struct ccw_device *cdev = to_ccwdev(dev);
+
+	ccw_device_unregister(cdev);
+	put_device(&cdev->dev);
+}
+
+static void ccw_device_remove_sch_cb(struct device *dev)
 {
 	struct subchannel *sch;
-	unsigned long flags;
-	/*
-	 * Forced offline in disconnected state means
-	 * 'throw away device'.
-	 */
-	if (ccw_device_is_orphan(cdev)) {
-		/* Deregister ccw device. */
-		spin_lock_irqsave(cdev->ccwlock, flags);
-		cdev->private->state = DEV_STATE_NOT_OPER;
-		spin_unlock_irqrestore(cdev->ccwlock, flags);
-		ccw_device_unregister(cdev);
-		put_device(&cdev->dev);
-		return ;
-	}
-	sch = to_subchannel(cdev->dev.parent);
+
+	sch = to_subchannel(dev);
 	css_sch_device_unregister(sch);
 	/* Reset intparm to zeroes. */
 	sch->schib.pmcw.intparm = 0;
@@ -322,6 +316,39 @@
 	put_device(&sch->dev);
 }
 
+static void
+ccw_device_remove_disconnected(struct ccw_device *cdev)
+{
+	unsigned long flags;
+	int rc;
+
+	/*
+	 * Forced offline in disconnected state means
+	 * 'throw away device'.
+	 */
+	if (ccw_device_is_orphan(cdev)) {
+		/*
+		 * Deregister ccw device.
+		 * Unfortunately, we cannot do this directly from the
+		 * attribute method.
+		 */
+		spin_lock_irqsave(cdev->ccwlock, flags);
+		cdev->private->state = DEV_STATE_NOT_OPER;
+		spin_unlock_irqrestore(cdev->ccwlock, flags);
+		rc = device_schedule_callback(&cdev->dev,
+					      ccw_device_remove_orphan_cb);
+		if (rc)
+			dev_info(&cdev->dev, "Couldn't unregister orphan\n");
+		return;
+	}
+	/* Deregister subchannel, which will kill the ccw device. */
+	rc = device_schedule_callback(cdev->dev.parent,
+				      ccw_device_remove_sch_cb);
+	if (rc)
+		dev_info(&cdev->dev,
+			 "Couldn't unregister disconnected device\n");
+}
+
 int
 ccw_device_set_offline(struct ccw_device *cdev)
 {
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 898ec3b..6bba809 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -688,6 +688,12 @@
 		ccw_device_done(cdev, DEV_STATE_BOXED);
 		break;
 	default:
+		cdev->private->flags.donotify = 0;
+		if (get_device(&cdev->dev)) {
+			PREPARE_WORK(&cdev->private->kick_work,
+				     ccw_device_call_sch_unregister);
+			queue_work(ccw_device_work, &cdev->private->kick_work);
+		}
 		ccw_device_done(cdev, DEV_STATE_NOT_OPER);
 		break;
 	}
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 997f468..60b9347 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -27,7 +27,6 @@
 /*
  * diag210 is used under VM to get information about a virtual device
  */
-#ifdef CONFIG_64BIT
 int
 diag210(struct diag210 * addr)
 {
@@ -43,6 +42,7 @@
 	spin_lock_irqsave(&diag210_lock, flags);
 	diag210_tmp = *addr;
 
+#ifdef CONFIG_64BIT
 	asm volatile(
 		"	lhi	%0,-1\n"
 		"	sam31\n"
@@ -51,19 +51,8 @@
 		"	srl	%0,28\n"
 		"1:	sam64\n"
 		EX_TABLE(0b,1b)
-		: "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory");
-
-	*addr = diag210_tmp;
-	spin_unlock_irqrestore(&diag210_lock, flags);
-
-	return ccode;
-}
+		: "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
 #else
-int
-diag210(struct diag210 * addr)
-{
-	int ccode;
-
 	asm volatile(
 		"	lhi	%0,-1\n"
 		"	diag	%1,0,0x210\n"
@@ -71,11 +60,14 @@
 		"	srl	%0,28\n"
 		"1:\n"
 		EX_TABLE(0b,1b)
-		: "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory");
+		: "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#endif
+
+	*addr = diag210_tmp;
+	spin_unlock_irqrestore(&diag210_lock, flags);
 
 	return ccode;
 }
-#endif
 
 /*
  * Input :
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 5aac0ec..90bd220 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -43,6 +43,7 @@
 static void ap_poll_timeout(unsigned long);
 static int ap_poll_thread_start(void);
 static void ap_poll_thread_stop(void);
+static void ap_request_timeout(unsigned long);
 
 /**
  * Module description.
@@ -189,6 +190,7 @@
 	case AP_RESPONSE_NORMAL:
 		return 0;
 	case AP_RESPONSE_Q_FULL:
+	case AP_RESPONSE_RESET_IN_PROGRESS:
 		return -EBUSY;
 	default:	/* Device is gone. */
 		return -ENODEV;
@@ -252,6 +254,8 @@
 		if (status.queue_empty)
 			return -ENOENT;
 		return -EBUSY;
+	case AP_RESPONSE_RESET_IN_PROGRESS:
+		return -EBUSY;
 	default:
 		return -ENODEV;
 	}
@@ -326,11 +330,12 @@
 			i = AP_MAX_RESET;	/* return with -ENODEV */
 			break;
 		case AP_RESPONSE_RESET_IN_PROGRESS:
+			rc = -EBUSY;
 		case AP_RESPONSE_BUSY:
 		default:
 			break;
 		}
-		if (rc != -ENODEV)
+		if (rc != -ENODEV && rc != -EBUSY)
 			break;
 		if (i < AP_MAX_RESET - 1) {
 			udelay(5);
@@ -341,6 +346,40 @@
 }
 
 /**
+ * Arm request timeout if a AP device was idle and a new request is submitted.
+ */
+static void ap_increase_queue_count(struct ap_device *ap_dev)
+{
+	int timeout = ap_dev->drv->request_timeout;
+
+	ap_dev->queue_count++;
+	if (ap_dev->queue_count == 1) {
+		mod_timer(&ap_dev->timeout, jiffies + timeout);
+		ap_dev->reset = AP_RESET_ARMED;
+	}
+}
+
+/**
+ * AP device is still alive, re-schedule request timeout if there are still
+ * pending requests.
+ */
+static void ap_decrease_queue_count(struct ap_device *ap_dev)
+{
+	int timeout = ap_dev->drv->request_timeout;
+
+	ap_dev->queue_count--;
+	if (ap_dev->queue_count > 0)
+		mod_timer(&ap_dev->timeout, jiffies + timeout);
+	else
+		/**
+		 * The timeout timer should to be disabled now - since
+		 * del_timer_sync() is very expensive, we just tell via the
+		 * reset flag to ignore the pending timeout timer.
+		 */
+		ap_dev->reset = AP_RESET_IGNORE;
+}
+
+/**
  * AP device related attributes.
  */
 static ssize_t ap_hwtype_show(struct device *dev,
@@ -498,6 +537,7 @@
 	struct ap_driver *ap_drv = ap_dev->drv;
 
 	ap_flush_queue(ap_dev);
+	del_timer_sync(&ap_dev->timeout);
 	if (ap_drv->remove)
 		ap_drv->remove(ap_dev);
 	spin_lock_bh(&ap_device_lock);
@@ -759,17 +799,21 @@
 				      __ap_scan_bus);
 		rc = ap_query_queue(qid, &queue_depth, &device_type);
 		if (dev) {
+			if (rc == -EBUSY) {
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(AP_RESET_TIMEOUT);
+				rc = ap_query_queue(qid, &queue_depth,
+						    &device_type);
+			}
 			ap_dev = to_ap_dev(dev);
 			spin_lock_bh(&ap_dev->lock);
 			if (rc || ap_dev->unregistered) {
 				spin_unlock_bh(&ap_dev->lock);
-				put_device(dev);
 				device_unregister(dev);
+				put_device(dev);
 				continue;
-			} else
-				spin_unlock_bh(&ap_dev->lock);
-		}
-		if (dev) {
+			}
+			spin_unlock_bh(&ap_dev->lock);
 			put_device(dev);
 			continue;
 		}
@@ -788,6 +832,8 @@
 		INIT_LIST_HEAD(&ap_dev->pendingq);
 		INIT_LIST_HEAD(&ap_dev->requestq);
 		INIT_LIST_HEAD(&ap_dev->list);
+		setup_timer(&ap_dev->timeout, ap_request_timeout,
+			    (unsigned long) ap_dev);
 		if (device_type == 0)
 			ap_probe_device_type(ap_dev);
 		else
@@ -853,7 +899,7 @@
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
 		atomic_dec(&ap_poll_requests);
-		ap_dev->queue_count--;
+		ap_decrease_queue_count(ap_dev);
 		list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
 			if (ap_msg->psmid != ap_dev->reply->psmid)
 				continue;
@@ -904,7 +950,7 @@
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
 		atomic_inc(&ap_poll_requests);
-		ap_dev->queue_count++;
+		ap_increase_queue_count(ap_dev);
 		list_move_tail(&ap_msg->list, &ap_dev->pendingq);
 		ap_dev->requestq_count--;
 		ap_dev->pendingq_count++;
@@ -914,6 +960,7 @@
 		*flags |= 2;
 		break;
 	case AP_RESPONSE_Q_FULL:
+	case AP_RESPONSE_RESET_IN_PROGRESS:
 		*flags |= 2;
 		break;
 	case AP_RESPONSE_MESSAGE_TOO_BIG:
@@ -960,10 +1007,11 @@
 			list_add_tail(&ap_msg->list, &ap_dev->pendingq);
 			atomic_inc(&ap_poll_requests);
 			ap_dev->pendingq_count++;
-			ap_dev->queue_count++;
+			ap_increase_queue_count(ap_dev);
 			ap_dev->total_request_count++;
 			break;
 		case AP_RESPONSE_Q_FULL:
+		case AP_RESPONSE_RESET_IN_PROGRESS:
 			list_add_tail(&ap_msg->list, &ap_dev->requestq);
 			ap_dev->requestq_count++;
 			ap_dev->total_request_count++;
@@ -1046,6 +1094,25 @@
 }
 
 /**
+ * Reset a not responding AP device and move all requests from the
+ * pending queue to the request queue.
+ */
+static void ap_reset(struct ap_device *ap_dev)
+{
+	int rc;
+
+	ap_dev->reset = AP_RESET_IGNORE;
+	atomic_sub(ap_dev->queue_count, &ap_poll_requests);
+	ap_dev->queue_count = 0;
+	list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
+	ap_dev->requestq_count += ap_dev->pendingq_count;
+	ap_dev->pendingq_count = 0;
+	rc = ap_init_queue(ap_dev->qid);
+	if (rc == -ENODEV)
+		ap_dev->unregistered = 1;
+}
+
+/**
  * Poll all AP devices on the bus in a round robin fashion. Continue
  * polling until bit 2^0 of the control flags is not set. If bit 2^1
  * of the control flags has been set arm the poll timer.
@@ -1056,6 +1123,8 @@
 	if (!ap_dev->unregistered) {
 		if (ap_poll_queue(ap_dev, flags))
 			ap_dev->unregistered = 1;
+		if (ap_dev->reset == AP_RESET_DO)
+			ap_reset(ap_dev);
 	}
 	spin_unlock(&ap_dev->lock);
 	return 0;
@@ -1147,6 +1216,17 @@
 	mutex_unlock(&ap_poll_thread_mutex);
 }
 
+/**
+ * Handling of request timeouts
+ */
+static void ap_request_timeout(unsigned long data)
+{
+	struct ap_device *ap_dev = (struct ap_device *) data;
+
+	if (ap_dev->reset == AP_RESET_ARMED)
+		ap_dev->reset = AP_RESET_DO;
+}
+
 static void ap_reset_domain(void)
 {
 	int i;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 008559e..87c2d64 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -33,6 +33,7 @@
 #define AP_DEVICES 64		/* Number of AP devices. */
 #define AP_DOMAINS 16		/* Number of AP domains. */
 #define AP_MAX_RESET 90		/* Maximum number of resets. */
+#define AP_RESET_TIMEOUT (HZ/2)	/* Time in ticks for reset timeouts. */
 #define AP_CONFIG_TIME 30	/* Time in seconds between AP bus rescans. */
 #define AP_POLL_TIME 1		/* Time in ticks between receive polls. */
 
@@ -83,6 +84,13 @@
 #define AP_DEVICE_TYPE_CEX2A	6
 #define AP_DEVICE_TYPE_CEX2C	7
 
+/**
+ * AP reset flag states
+ */
+#define AP_RESET_IGNORE	0	/* request timeout will be ignored */
+#define AP_RESET_ARMED	1	/* request timeout timer is active */
+#define AP_RESET_DO	2	/* AP reset required */
+
 struct ap_device;
 struct ap_message;
 
@@ -95,6 +103,7 @@
 	/* receive is called from tasklet context */
 	void (*receive)(struct ap_device *, struct ap_message *,
 			struct ap_message *);
+	int request_timeout;		/* request timeout in jiffies */
 };
 
 #define to_ap_drv(x) container_of((x), struct ap_driver, driver)
@@ -112,6 +121,8 @@
 	int queue_depth;		/* AP queue depth.*/
 	int device_type;		/* AP device type. */
 	int unregistered;		/* marks AP device as unregistered */
+	struct timer_list timeout;	/* Timer for request timeouts. */
+	int reset;			/* Reset required after req. timeout. */
 
 	int queue_count;		/* # messages currently on AP queue. */
 
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 5bb13a9..08657f6 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -70,6 +70,7 @@
 	.remove = zcrypt_cex2a_remove,
 	.receive = zcrypt_cex2a_receive,
 	.ids = zcrypt_cex2a_ids,
+	.request_timeout = CEX2A_CLEANUP_TIME,
 };
 
 /**
@@ -306,18 +307,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, CEX2A_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, mex->outputdata,
 				      mex->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	kfree(ap_msg.message);
 	return rc;
@@ -348,18 +344,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, CEX2A_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, crt->outputdata,
 				      crt->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	kfree(ap_msg.message);
 	return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 818ffe0..6e93b47 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -70,6 +70,7 @@
 	.remove = zcrypt_pcica_remove,
 	.receive = zcrypt_pcica_receive,
 	.ids = zcrypt_pcica_ids,
+	.request_timeout = PCICA_CLEANUP_TIME,
 };
 
 /**
@@ -290,18 +291,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, PCICA_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, mex->outputdata,
 				      mex->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	kfree(ap_msg.message);
 	return rc;
@@ -332,18 +328,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, PCICA_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, crt->outputdata,
 				      crt->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	kfree(ap_msg.message);
 	return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index f295a40..d6d59bf 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -82,6 +82,7 @@
 	.remove = zcrypt_pcicc_remove,
 	.receive = zcrypt_pcicc_receive,
 	.ids = zcrypt_pcicc_ids,
+	.request_timeout = PCICC_CLEANUP_TIME,
 };
 
 /**
@@ -501,18 +502,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, PCICC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, mex->outputdata,
 				      mex->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	free_page((unsigned long) ap_msg.message);
 	return rc;
@@ -544,18 +540,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, PCICC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, crt->outputdata,
 				      crt->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	free_page((unsigned long) ap_msg.message);
 	return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 252443b..6494878 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -93,6 +93,7 @@
 	.remove = zcrypt_pcixcc_remove,
 	.receive = zcrypt_pcixcc_receive,
 	.ids = zcrypt_pcixcc_ids,
+	.request_timeout = PCIXCC_CLEANUP_TIME,
 };
 
 /**
@@ -641,18 +642,13 @@
 		goto out_free;
 	init_completion(&resp_type.work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&resp_type.work, PCIXCC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&resp_type.work);
+	if (rc == 0)
 		rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
 					  mex->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	free_page((unsigned long) ap_msg.message);
 	return rc;
@@ -685,18 +681,13 @@
 		goto out_free;
 	init_completion(&resp_type.work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&resp_type.work, PCIXCC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&resp_type.work);
+	if (rc == 0)
 		rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
 					  crt->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	free_page((unsigned long) ap_msg.message);
 	return rc;
@@ -729,17 +720,12 @@
 		goto out_free;
 	init_completion(&resp_type.work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&resp_type.work, PCIXCC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&resp_type.work);
+	if (rc == 0)
 		rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	memset(ap_msg.message, 0x0, ap_msg.length);
 	kfree(ap_msg.message);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 6dd64d0..348bb7b 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -3912,6 +3912,7 @@
 add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
 {
 	struct chbk *p_ch;
+	struct ccw_dev_id dev_id;
 
 #ifdef FUNCTRACE
         printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__FUNCTION__);
@@ -3921,7 +3922,8 @@
 	p_ch = &privptr->channel[i];
 	p_ch->cdev = cdev;
 	snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", cdev->dev.bus_id);
-	sscanf(cdev->dev.bus_id+4,"%x",&p_ch->devno);
+	ccw_device_get_id(cdev, &dev_id);
+	p_ch->devno = dev_id.devno;
 	if ((p_ch->irb = kmalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
 		printk(KERN_WARNING "%s Out of memory in %s for irb\n",
 			p_ch->id,__FUNCTION__);
@@ -3955,6 +3957,7 @@
 	struct claw_env *p_env;
 	struct net_device *dev;
 	int ret;
+	struct ccw_dev_id dev_id;
 
 	pr_debug("%s() called\n", __FUNCTION__);
 	printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
@@ -3965,10 +3968,10 @@
 	if (!privptr)
 		return -ENODEV;
 	p_env = privptr->p_env;
-	sscanf(cgdev->cdev[READ]->dev.bus_id+4,"%x",
-		&p_env->devno[READ]);
-        sscanf(cgdev->cdev[WRITE]->dev.bus_id+4,"%x",
-		&p_env->devno[WRITE]);
+	ccw_device_get_id(cgdev->cdev[READ], &dev_id);
+	p_env->devno[READ] = dev_id.devno;
+	ccw_device_get_id(cgdev->cdev[WRITE], &dev_id);
+	p_env->devno[WRITE] = dev_id.devno;
 	ret = add_channel(cgdev->cdev[0],0,privptr);
 	if (ret == 0)
 		ret = add_channel(cgdev->cdev[1],1,privptr);
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index c358764..3d28e1a 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -134,18 +134,6 @@
 		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
 		   *(((char*)ptr)+30),*(((char*)ptr)+31));
 
-static inline void iucv_hex_dump(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; i++) {
-		if (i && !(i % 16))
-			printk("\n");
-		printk("%02x ", *(buf + i));
-	}
-	printk("\n");
-}
-
 #define PRINTK_HEADER " iucv: "       /* for debugging */
 
 static struct device_driver netiucv_driver = {
@@ -212,7 +200,7 @@
  */
 static struct list_head iucv_connection_list =
 	LIST_HEAD_INIT(iucv_connection_list);
-static rwlock_t iucv_connection_rwlock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(iucv_connection_rwlock);
 
 /**
  * Representation of event-data for the
@@ -280,7 +268,7 @@
  *
  * @returns The printable string (static data!!)
  */
-static inline char *netiucv_printname(char *name)
+static char *netiucv_printname(char *name)
 {
 	static char tmp[9];
 	char *p = tmp;
@@ -1315,7 +1303,8 @@
 	 * and throw away packet.
 	 */
 	if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
-		fsm_event(privptr->fsm, DEV_EVENT_START, dev);
+		if (!in_atomic())
+			fsm_event(privptr->fsm, DEV_EVENT_START, dev);
 		dev_kfree_skb(skb);
 		privptr->stats.tx_dropped++;
 		privptr->stats.tx_errors++;
@@ -1729,7 +1718,7 @@
 	.attrs = netiucv_stat_attrs,
 };
 
-static inline int netiucv_add_files(struct device *dev)
+static int netiucv_add_files(struct device *dev)
 {
 	int ret;
 
@@ -1743,7 +1732,7 @@
 	return ret;
 }
 
-static inline void netiucv_remove_files(struct device *dev)
+static void netiucv_remove_files(struct device *dev)
 {
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 	sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index b34eb82..ec18bae 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -211,6 +211,10 @@
 	/* initial values when measuring starts */
 	unsigned long initial_rx_packets;
 	unsigned long initial_tx_packets;
+	/* inbound scatter gather data */
+	unsigned int sg_skbs_rx;
+	unsigned int sg_frags_rx;
+	unsigned int sg_alloc_page_rx;
 };
 
 /* Routing stuff */
@@ -341,6 +345,9 @@
 
 #define QETH_IP_HEADER_SIZE 40
 
+/* large receive scatter gather copy break */
+#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+
 struct qeth_hdr_layer3 {
 	__u8  id;
 	__u8  flags;
@@ -771,6 +778,7 @@
 	int layer2;
 	enum qeth_large_send_types large_send;
 	int performance_stats;
+	int rx_sg_cb;
 };
 
 /*
@@ -828,6 +836,7 @@
 	int (*orig_hard_header)(struct sk_buff *,struct net_device *,
 				unsigned short,void *,void *,unsigned);
 	struct qeth_osn_info osn_info;
+	atomic_t force_alloc_skb;
 };
 
 struct qeth_card_list_struct {
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 4640f32..70108fb 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -424,8 +424,7 @@
 		/* prepare qdio hdr */
 		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
 			eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN +
-						     eddp->nhl + eddp->thl -
-						     sizeof(struct qeth_hdr);
+						     eddp->nhl + eddp->thl;
 #ifdef CONFIG_QETH_VLAN
 			if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
 				eddp->qh.hdr.l2.pkt_length += VLAN_HLEN;
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 0b96d49..57f6943 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -986,15 +986,15 @@
 	card->use_hard_stop = 1;
 	__qeth_set_offline(card->gdev,1);
 	rc = __qeth_set_online(card->gdev,1);
+	/* don't run another scheduled recovery */
+	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
 	if (!rc)
 		PRINT_INFO("Device %s successfully recovered!\n",
 			   CARD_BUS_ID(card));
 	else
 		PRINT_INFO("Device %s could not be recovered!\n",
 			   CARD_BUS_ID(card));
-	/* don't run another scheduled recovery */
-	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
-	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
 	return 0;
 }
 
@@ -1054,6 +1054,7 @@
 	else
 		card->options.layer2 = 0;
 	card->options.performance_stats = 0;
+	card->options.rx_sg_cb = QETH_RX_SG_CB;
 }
 
 /**
@@ -1934,6 +1935,7 @@
 			atomic_inc(&reply->received);
 			wake_up(&reply->wait_q);
 		}
+		cpu_relax();
 	};
 	rc = reply->rc;
 	qeth_put_reply(reply);
@@ -2176,13 +2178,6 @@
 
 }
 
-static inline __u16
-__raw_devno_from_bus_id(char *id)
-{
-	id += (strlen(id) - 4);
-	return (__u16) simple_strtoul(id, &id, 16);
-}
-
 static int
 qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
 		  unsigned long data)
@@ -2205,6 +2200,7 @@
 	int rc;
 	__u16 temp;
 	struct qeth_cmd_buffer *iob;
+	struct ccw_dev_id dev_id;
 
 	QETH_DBF_TEXT(setup,2,"ulpsetup");
 
@@ -2218,8 +2214,8 @@
 	memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
 	       &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
 
-	temp = __raw_devno_from_bus_id(CARD_DDEV_ID(card));
-	memcpy(QETH_ULP_SETUP_CUA(iob->data), &temp, 2);
+	ccw_device_get_id(CARD_DDEV(card), &dev_id);
+	memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
 	temp = (card->info.cula << 8) + card->info.unit_addr2;
 	memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
 	rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
@@ -2264,6 +2260,89 @@
 	return skb;
 }
 
+static inline int
+qeth_create_skb_frag(struct qdio_buffer_element *element,
+		     struct sk_buff **pskb,
+		     int offset, int *pfrag, int data_len)
+{
+	struct page *page = virt_to_page(element->addr);
+	if (*pfrag == 0) {
+		/* the upper protocol layers assume that there is data in the
+		 * skb itself. Copy a small amount (64 bytes) to make them
+		 * happy. */
+		*pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH);
+		if (!(*pskb))
+			return -ENOMEM;
+		skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH);
+		if (data_len <= 64) {
+			memcpy(skb_put(*pskb, data_len), element->addr + offset,
+				data_len);
+		} else {
+			get_page(page);
+			memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
+			skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
+				data_len - 64);
+			(*pskb)->data_len += data_len - 64;
+			(*pskb)->len	  += data_len - 64;
+			(*pskb)->truesize += data_len - 64;
+		}
+	} else {
+		get_page(page);
+		skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
+		(*pskb)->data_len += data_len;
+		(*pskb)->len	  += data_len;
+		(*pskb)->truesize += data_len;
+	}
+	(*pfrag)++;
+	return 0;
+}
+
+static inline struct qeth_buffer_pool_entry *
+qeth_find_free_buffer_pool_entry(struct qeth_card *card)
+{
+	struct list_head *plh;
+	struct qeth_buffer_pool_entry *entry;
+	int i, free;
+	struct page *page;
+
+	if (list_empty(&card->qdio.in_buf_pool.entry_list))
+		return NULL;
+
+	list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
+		entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
+		free = 1;
+		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+			if (page_count(virt_to_page(entry->elements[i])) > 1) {
+				free = 0;
+				break;
+			}
+		}
+		if (free) {
+			list_del_init(&entry->list);
+			return entry;
+		}
+	}
+
+	/* no free buffer in pool so take first one and swap pages */
+	entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
+			struct qeth_buffer_pool_entry, list);
+	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+		if (page_count(virt_to_page(entry->elements[i])) > 1) {
+			page = alloc_page(GFP_ATOMIC|GFP_DMA);
+			if (!page) {
+				return NULL;
+			} else {
+				free_page((unsigned long)entry->elements[i]);
+				entry->elements[i] = page_address(page);
+				if (card->options.performance_stats)
+					card->perf_stats.sg_alloc_page_rx++;
+			}
+		}
+	}
+	list_del_init(&entry->list);
+	return entry;
+}
+
 static struct sk_buff *
 qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
 		  struct qdio_buffer_element **__element, int *__offset,
@@ -2275,6 +2354,8 @@
 	int skb_len;
 	void *data_ptr;
 	int data_len;
+	int use_rx_sg = 0;
+	int frag = 0;
 
 	QETH_DBF_TEXT(trace,6,"nextskb");
 	/* qeth_hdr must not cross element boundaries */
@@ -2299,23 +2380,43 @@
 
 	if (!skb_len)
 		return NULL;
-	if (card->options.fake_ll){
-		if(card->dev->type == ARPHRD_IEEE802_TR){
-			if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr)))
-				goto no_mem;
-			skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
+	if ((skb_len >= card->options.rx_sg_cb) &&
+	    (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+	    (!atomic_read(&card->force_alloc_skb))) {
+		use_rx_sg = 1;
+	} else {
+		if (card->options.fake_ll) {
+			if (card->dev->type == ARPHRD_IEEE802_TR) {
+				if (!(skb = qeth_get_skb(skb_len +
+						QETH_FAKE_LL_LEN_TR, *hdr)))
+					goto no_mem;
+				skb_reserve(skb, QETH_FAKE_LL_LEN_TR);
+			} else {
+				if (!(skb = qeth_get_skb(skb_len +
+						QETH_FAKE_LL_LEN_ETH, *hdr)))
+					goto no_mem;
+				skb_reserve(skb, QETH_FAKE_LL_LEN_ETH);
+			}
 		} else {
-			if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
+			skb = qeth_get_skb(skb_len, *hdr);
+			if (!skb)
 				goto no_mem;
-			skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
 		}
-	} else if (!(skb = qeth_get_skb(skb_len, *hdr)))
-		goto no_mem;
+	}
+
 	data_ptr = element->addr + offset;
 	while (skb_len) {
 		data_len = min(skb_len, (int)(element->length - offset));
-		if (data_len)
-			memcpy(skb_put(skb, data_len), data_ptr, data_len);
+		if (data_len) {
+			if (use_rx_sg) {
+				if (qeth_create_skb_frag(element, &skb, offset,
+				    &frag, data_len))
+					goto no_mem;
+			} else {
+				memcpy(skb_put(skb, data_len), data_ptr,
+					data_len);
+			}
+		}
 		skb_len -= data_len;
 		if (skb_len){
 			if (qeth_is_last_sbale(element)){
@@ -2337,6 +2438,10 @@
 	}
 	*__element = element;
 	*__offset = offset;
+	if (use_rx_sg && card->options.performance_stats) {
+		card->perf_stats.sg_skbs_rx++;
+		card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
+	}
 	return skb;
 no_mem:
 	if (net_ratelimit()){
@@ -2614,28 +2719,15 @@
 	}
 }
 
-static struct qeth_buffer_pool_entry *
-qeth_get_buffer_pool_entry(struct qeth_card *card)
-{
-	struct qeth_buffer_pool_entry *entry;
-
-	QETH_DBF_TEXT(trace, 6, "gtbfplen");
-	if (!list_empty(&card->qdio.in_buf_pool.entry_list)) {
-		entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
-				struct qeth_buffer_pool_entry, list);
-		list_del_init(&entry->list);
-		return entry;
-	}
-	return NULL;
-}
-
-static void
+static int
 qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
 {
 	struct qeth_buffer_pool_entry *pool_entry;
 	int i;
- 
-	pool_entry = qeth_get_buffer_pool_entry(card);
+
+	pool_entry = qeth_find_free_buffer_pool_entry(card);
+	if (!pool_entry)
+		return 1;
 	/*
 	 * since the buffer is accessed only from the input_tasklet
 	 * there shouldn't be a need to synchronize; also, since we use
@@ -2654,6 +2746,7 @@
 			buf->buffer->element[i].flags = 0;
 	}
 	buf->state = QETH_QDIO_BUF_EMPTY;
+	return 0;
 }
 
 static void
@@ -2688,6 +2781,7 @@
 	int count;
 	int i;
 	int rc;
+	int newcount = 0;
 
 	QETH_DBF_TEXT(trace,6,"queinbuf");
 	count = (index < queue->next_buf_to_init)?
@@ -2698,9 +2792,27 @@
 	/* only requeue at a certain threshold to avoid SIGAs */
 	if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){
 		for (i = queue->next_buf_to_init;
-		     i < queue->next_buf_to_init + count; ++i)
-			qeth_init_input_buffer(card,
-				&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]);
+		     i < queue->next_buf_to_init + count; ++i) {
+			if (qeth_init_input_buffer(card,
+				&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
+				break;
+			} else {
+				newcount++;
+			}
+		}
+
+		if (newcount < count) {
+			/* we are in memory shortage so we switch back to
+			   traditional skb allocation and drop packages */
+			if (atomic_cmpxchg(&card->force_alloc_skb, 0, 1))
+				printk(KERN_WARNING
+					"qeth: switch to alloc skb\n");
+			count = newcount;
+		} else {
+			if (atomic_cmpxchg(&card->force_alloc_skb, 1, 0))
+				printk(KERN_WARNING "qeth: switch to sg\n");
+		}
+
 		/*
 		 * according to old code it should be avoided to requeue all
 		 * 128 buffers in order to benefit from PCI avoidance.
@@ -5850,9 +5962,9 @@
 		in_dev = in6_dev_get(netdev);
 		if (!in_dev)
 			continue;
-		read_lock(&in_dev->lock);
+		read_lock_bh(&in_dev->lock);
 		qeth_add_mc6(card,in_dev);
-		read_unlock(&in_dev->lock);
+		read_unlock_bh(&in_dev->lock);
 		in6_dev_put(in_dev);
 	}
 #endif /* CONFIG_QETH_VLAN */
@@ -5869,10 +5981,10 @@
 	in6_dev = in6_dev_get(card->dev);
 	if (in6_dev == NULL)
 		return;
-	read_lock(&in6_dev->lock);
+	read_lock_bh(&in6_dev->lock);
 	qeth_add_mc6(card, in6_dev);
 	qeth_add_vlan_mc6(card);
-	read_unlock(&in6_dev->lock);
+	read_unlock_bh(&in6_dev->lock);
 	in6_dev_put(in6_dev);
 }
 #endif /* CONFIG_QETH_IPV6 */
@@ -6500,6 +6612,7 @@
 
 	QETH_DBF_TEXT(setup, 2, "hrdsetup");
 
+	atomic_set(&card->force_alloc_skb, 0);
 retry:
 	if (retries < 3){
 		PRINT_WARN("Retrying to do IDX activates.\n");
@@ -7476,11 +7589,11 @@
 		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
 		if (rc == 0xe080){
 			PRINT_WARN("LAN on card %s if offline! "
-				   "Continuing softsetup.\n",
+				   "Waiting for STARTLAN from card.\n",
 				   CARD_BUS_ID(card));
 			card->lan_online = 0;
-		} else
-			return rc;
+		}
+		return rc;
 	} else
 		card->lan_online = 1;
 	if (card->info.type==QETH_CARD_TYPE_OSN)
@@ -7797,15 +7910,17 @@
 		}
 		/* fallthrough */
 	case QETH_CARD_TYPE_IQD:
-		card->info.mcl_level[0] = (char) _ebcasc[(__u8)
-			card->info.mcl_level[0]];
-		card->info.mcl_level[1] = (char) _ebcasc[(__u8)
-			card->info.mcl_level[1]];
-		card->info.mcl_level[2] = (char) _ebcasc[(__u8)
-			card->info.mcl_level[2]];
-		card->info.mcl_level[3] = (char) _ebcasc[(__u8)
-			card->info.mcl_level[3]];
-		card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+		if (card->info.guestlan) {
+			card->info.mcl_level[0] = (char) _ebcasc[(__u8)
+				card->info.mcl_level[0]];
+			card->info.mcl_level[1] = (char) _ebcasc[(__u8)
+				card->info.mcl_level[1]];
+			card->info.mcl_level[2] = (char) _ebcasc[(__u8)
+				card->info.mcl_level[2]];
+			card->info.mcl_level[3] = (char) _ebcasc[(__u8)
+				card->info.mcl_level[3]];
+			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+		}
 		break;
 	default:
 		memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 89d56c8..f1ff165 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -212,6 +212,12 @@
 		      "  Skb fragments sent in SG mode          : %u\n\n",
 		      card->perf_stats.sg_skbs_sent,
 		      card->perf_stats.sg_frags_sent);
+	seq_printf(s, "  Skbs received in SG mode               : %u\n"
+		      "  Skb fragments received in SG mode      : %u\n"
+		      "  Page allocations for rx SG mode        : %u\n\n",
+		      card->perf_stats.sg_skbs_rx,
+		      card->perf_stats.sg_frags_rx,
+		      card->perf_stats.sg_alloc_page_rx);
 	seq_printf(s, "  large_send tx (in Kbytes)              : %u\n"
 		      "  large_send count                       : %u\n\n",
 		      card->perf_stats.large_send_bytes >> 10,
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 65ffc21..bb0287a 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -991,7 +991,7 @@
 
 #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)			     \
 struct device_attribute dev_attr_##_id = {				     \
-	.attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\
+	.attr = {.name=__stringify(_name), .mode=_mode, },\
 	.show	= _show,						     \
 	.store	= _store,						     \
 };
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index ddff40c..a1db959 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -815,9 +815,7 @@
 struct zfcp_unit *
 zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
 {
-	struct zfcp_unit *unit, *tmp_unit;
-	unsigned int scsi_lun;
-	int found;
+	struct zfcp_unit *unit;
 
 	/*
 	 * check that there is no unit with this FCP_LUN already in list
@@ -863,22 +861,10 @@
 	}
 
 	zfcp_unit_get(unit);
+	unit->scsi_lun = scsilun_to_int((struct scsi_lun *)&unit->fcp_lun);
 
-	scsi_lun = 0;
-	found = 0;
 	write_lock_irq(&zfcp_data.config_lock);
-	list_for_each_entry(tmp_unit, &port->unit_list_head, list) {
-		if (tmp_unit->scsi_lun != scsi_lun) {
-			found = 1;
-			break;
-		}
-		scsi_lun++;
-	}
-	unit->scsi_lun = scsi_lun;
-	if (found)
-		list_add_tail(&unit->list, &tmp_unit->list);
-	else
-		list_add_tail(&unit->list, &port->unit_list_head);
+	list_add_tail(&unit->list, &port->unit_list_head);
 	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
 	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
 	write_unlock_irq(&zfcp_data.config_lock);
@@ -1127,6 +1113,7 @@
 	int retval = 0;
 	unsigned long flags;
 
+	zfcp_adapter_scsi_unregister(adapter);
 	device_unregister(&adapter->generic_services);
 	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
 	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 81680ef..1c8f71a 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -189,9 +189,7 @@
  * @ccw_device: pointer to belonging ccw device
  *
  * This function gets called by the common i/o layer and sets an adapter
- * into state offline. Setting an fcp device offline means that it will be
- * unregistered from the SCSI stack and that the adapter will be shut down
- * asynchronously.
+ * into state offline.
  */
 static int
 zfcp_ccw_set_offline(struct ccw_device *ccw_device)
@@ -202,7 +200,6 @@
 	adapter = dev_get_drvdata(&ccw_device->dev);
 	zfcp_erp_adapter_shutdown(adapter, 0);
 	zfcp_erp_wait(adapter);
-	zfcp_adapter_scsi_unregister(adapter);
 	zfcp_erp_thread_kill(adapter);
 	zfcp_adapter_debug_unregister(adapter);
 	up(&zfcp_data.config_sema);
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index aef66bc..4e7cb6d 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1986,6 +1986,10 @@
  failed_openfcp:
 	zfcp_close_fsf(erp_action->adapter);
  failed_qdio:
+	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
+			  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
+			  ZFCP_STATUS_ADAPTER_XPORT_OK,
+			  &erp_action->adapter->status);
  out:
 	return retval;
 }
@@ -2167,6 +2171,9 @@
 		sleep *= 2;
 	}
 
+	atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
+			  &adapter->status);
+
 	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
 			      &adapter->status)) {
 		ZFCP_LOG_INFO("error: exchange of configuration data for "
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index a8b0254..0eb31e1 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -156,44 +156,30 @@
 	kfree(fsf_req);
 }
 
-/**
- * zfcp_fsf_req_dismiss - dismiss a single fsf request
- */
-static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter,
-				 struct zfcp_fsf_req *fsf_req,
-				 unsigned int counter)
-{
-	u64 dbg_tmp[2];
-
-	dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active);
-	dbg_tmp[1] = (u64) counter;
-	debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
-	list_del(&fsf_req->list);
-	fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
-	zfcp_fsf_req_complete(fsf_req);
-}
-
-/**
- * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests
+/*
+ * Never ever call this without shutting down the adapter first.
+ * Otherwise the adapter would continue using and corrupting s390 storage.
+ * Included BUG_ON() call to ensure this is done.
+ * ERP is supposed to be the only user of this function.
  */
 void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
 {
-	struct zfcp_fsf_req *request, *tmp;
+	struct zfcp_fsf_req *fsf_req, *tmp;
 	unsigned long flags;
 	LIST_HEAD(remove_queue);
-	unsigned int i, counter;
+	unsigned int i;
 
+	BUG_ON(atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status));
 	spin_lock_irqsave(&adapter->req_list_lock, flags);
 	atomic_set(&adapter->reqs_active, 0);
-	for (i=0; i<REQUEST_LIST_SIZE; i++)
+	for (i = 0; i < REQUEST_LIST_SIZE; i++)
 		list_splice_init(&adapter->req_list[i], &remove_queue);
-
 	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
-	counter = 0;
-	list_for_each_entry_safe(request, tmp, &remove_queue, list) {
-		zfcp_fsf_req_dismiss(adapter, request, counter);
-		counter++;
+	list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) {
+		list_del(&fsf_req->list);
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
+		zfcp_fsf_req_complete(fsf_req);
 	}
 }
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 16e2d64..0acf6db 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -569,6 +569,9 @@
 	int retval = 0;
 	static unsigned int unique_id = 0;
 
+	if (adapter->scsi_host)
+		goto out;
+
 	/* register adapter as SCSI host with mid layer of SCSI stack */
 	adapter->scsi_host = scsi_host_alloc(&zfcp_data.scsi_host_template,
 					     sizeof (struct zfcp_adapter *));
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index 022e869..7b5773d 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -24,6 +24,7 @@
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/smp_lock.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/ebus.h>
 #include <asm/oplib.h>
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 262f01e..44e0398 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
+#include <linux/mm.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 512857a..5157a2a 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -619,8 +619,7 @@
 	jsf0.busy = 0;
 
 	misc_deregister(&jsf_dev);
-	if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0)
-		printk("jsfd: cleanup_module failed\n");
+	unregister_blkdev(JSFD_MAJOR, "jsfd");
 	blk_cleanup_queue(jsf_queue);
 }
 
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index eb766c3..76c0909 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1306,22 +1306,26 @@
 					wake_up(&tw_dev->ioctl_wqueue);
 				}
 			} else {
+				struct scsi_cmnd *cmd;
+
+				cmd = tw_dev->srb[request_id];
+
 				twa_scsiop_execute_scsi_complete(tw_dev, request_id);
 				/* If no error command was a success */
 				if (error == 0) {
-					tw_dev->srb[request_id]->result = (DID_OK << 16);
+					cmd->result = (DID_OK << 16);
 				}
 
 				/* If error, command failed */
 				if (error == 1) {
 					/* Ask for a host reset */
-					tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+					cmd->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
 				}
 
 				/* Report residual bytes for single sgl */
-				if ((tw_dev->srb[request_id]->use_sg <= 1) && (full_command_packet->command.newcommand.status == 0)) {
-					if (full_command_packet->command.newcommand.sg_list[0].length < tw_dev->srb[request_id]->request_bufflen)
-						tw_dev->srb[request_id]->resid = tw_dev->srb[request_id]->request_bufflen - full_command_packet->command.newcommand.sg_list[0].length;
+				if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) {
+					if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id]))
+						scsi_set_resid(cmd, scsi_bufflen(cmd) - full_command_packet->command.newcommand.sg_list[0].length);
 				}
 
 				/* Now complete the io */
@@ -1384,53 +1388,21 @@
 {
 	int use_sg;
 	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-	struct pci_dev *pdev = tw_dev->tw_pci_dev;
-	int retval = 0;
 
-	if (cmd->use_sg == 0)
-		goto out;
-
-	use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
-
-	if (use_sg == 0) {
+	use_sg = scsi_dma_map(cmd);
+	if (!use_sg)
+		return 0;
+	else if (use_sg < 0) {
 		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
-		goto out;
+		return 0;
 	}
 
 	cmd->SCp.phase = TW_PHASE_SGLIST;
 	cmd->SCp.have_data_in = use_sg;
-	retval = use_sg;
-out:
-	return retval;
+
+	return use_sg;
 } /* End twa_map_scsi_sg_data() */
 
-/* This function will perform a pci-dma map for a single buffer */
-static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int request_id)
-{
-	dma_addr_t mapping;
-	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-	struct pci_dev *pdev = tw_dev->tw_pci_dev;
-	dma_addr_t retval = 0;
-
-	if (cmd->request_bufflen == 0) {
-		retval = 0;
-		goto out;
-	}
-
-	mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, DMA_BIDIRECTIONAL);
-
-	if (mapping == 0) {
-		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Failed to map page");
-		goto out;
-	}
-
-	cmd->SCp.phase = TW_PHASE_SINGLE;
-	cmd->SCp.have_data_in = mapping;
-	retval = mapping;
-out:
-	return retval;
-} /* End twa_map_scsi_single_data() */
-
 /* This function will poll for a response interrupt of a request */
 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
 {
@@ -1815,15 +1787,13 @@
 	u32 num_sectors = 0x0;
 	int i, sg_count;
 	struct scsi_cmnd *srb = NULL;
-	struct scatterlist *sglist = NULL;
-	dma_addr_t buffaddr = 0x0;
+	struct scatterlist *sglist = NULL, *sg;
 	int retval = 1;
 
 	if (tw_dev->srb[request_id]) {
-		if (tw_dev->srb[request_id]->request_buffer) {
-			sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
-		}
 		srb = tw_dev->srb[request_id];
+		if (scsi_sglist(srb))
+			sglist = scsi_sglist(srb);
 	}
 
 	/* Initialize command packet */
@@ -1856,32 +1826,12 @@
 
 	if (!sglistarg) {
 		/* Map sglist from scsi layer to cmd packet */
-		if (tw_dev->srb[request_id]->use_sg == 0) {
-			if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
-				command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
-				command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
-				if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
-					memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
-			} else {
-				buffaddr = twa_map_scsi_single_data(tw_dev, request_id);
-				if (buffaddr == 0)
-					goto out;
 
-				command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr);
-				command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen);
-			}
-			command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1));
-
-			if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
-				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
-				goto out;
-			}
-		}
-
-		if (tw_dev->srb[request_id]->use_sg > 0) {
-			if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
-				if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) {
-					struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+		if (scsi_sg_count(srb)) {
+			if ((scsi_sg_count(srb) == 1) &&
+			    (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+				if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) {
+					struct scatterlist *sg = scsi_sglist(srb);
 					char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
 					memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
 					kunmap_atomic(buf - sg->offset, KM_IRQ0);
@@ -1893,16 +1843,16 @@
 				if (sg_count == 0)
 					goto out;
 
-				for (i = 0; i < sg_count; i++) {
-					command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
-					command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i]));
+				scsi_for_each_sg(srb, sg, sg_count, i) {
+					command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg));
+					command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(sg));
 					if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
 						TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
 						goto out;
 					}
 				}
 			}
-			command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg));
+			command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id])));
 		}
 	} else {
 		/* Internal cdb post */
@@ -1932,7 +1882,7 @@
 
 	/* Update SG statistics */
 	if (srb) {
-		tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
+		tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
 		if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
 			tw_dev->max_sgl_entries = tw_dev->sgl_entries;
 	}
@@ -1951,16 +1901,13 @@
 /* This function completes an execute scsi operation */
 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
 {
-	if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH &&
-	    (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE ||
-	     tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) {
-		if (tw_dev->srb[request_id]->use_sg == 0) {
-			memcpy(tw_dev->srb[request_id]->request_buffer,
-			       tw_dev->generic_buffer_virt[request_id],
-			       tw_dev->srb[request_id]->request_bufflen);
-		}
-		if (tw_dev->srb[request_id]->use_sg == 1) {
-			struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+
+	if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH &&
+	    (cmd->sc_data_direction == DMA_FROM_DEVICE ||
+	     cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
+		if (scsi_sg_count(cmd) == 1) {
+			struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]);
 			char *buf;
 			unsigned long flags = 0;
 			local_irq_save(flags);
@@ -2017,16 +1964,8 @@
 static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
 {
 	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-	struct pci_dev *pdev = tw_dev->tw_pci_dev;
 
-	switch(cmd->SCp.phase) {
-	case TW_PHASE_SINGLE:
-		pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
-		break;
-	case TW_PHASE_SGLIST:
-		pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
-		break;
-	}
+	scsi_dma_unmap(cmd);
 } /* End twa_unmap_scsi_data() */
 
 /* scsi_host_template initializer */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 656bdb1..c7995fc 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1273,57 +1273,24 @@
 	int use_sg;
 
 	dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
-	
-	if (cmd->use_sg == 0)
-		return 0;
 
-	use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
-	
-	if (use_sg == 0) {
+	use_sg = scsi_dma_map(cmd);
+	if (use_sg < 0) {
 		printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
 		return 0;
 	}
 
 	cmd->SCp.phase = TW_PHASE_SGLIST;
 	cmd->SCp.have_data_in = use_sg;
-	
+
 	return use_sg;
 } /* End tw_map_scsi_sg_data() */
 
-static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-	dma_addr_t mapping;
-
-	dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n");
-
-	if (cmd->request_bufflen == 0)
-		return 0;
-
-	mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL);
-
-	if (mapping == 0) {
-		printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
-		return 0;
-	}
-
-	cmd->SCp.phase = TW_PHASE_SINGLE;
-	cmd->SCp.have_data_in = mapping;
-
-	return mapping;
-} /* End tw_map_scsi_single_data() */
-
 static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
 {
 	dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
 
-	switch(cmd->SCp.phase) {
-		case TW_PHASE_SINGLE:
-			pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
-			break;
-		case TW_PHASE_SGLIST:
-			pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
-			break;
-	}
+	scsi_dma_unmap(cmd);
 } /* End tw_unmap_scsi_data() */
 
 /* This function will reset a device extension */
@@ -1499,27 +1466,16 @@
 	void *buf;
 	unsigned int transfer_len;
 	unsigned long flags = 0;
+	struct scatterlist *sg = scsi_sglist(cmd);
 
-	if (cmd->use_sg) {
-		struct scatterlist *sg =
-			(struct scatterlist *)cmd->request_buffer;
-		local_irq_save(flags);
-		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-		transfer_len = min(sg->length, len);
-	} else {
-		buf = cmd->request_buffer;
-		transfer_len = min(cmd->request_bufflen, len);
-	}
+	local_irq_save(flags);
+	buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+	transfer_len = min(sg->length, len);
 
 	memcpy(buf, data, transfer_len);
-	
-	if (cmd->use_sg) {
-		struct scatterlist *sg;
 
-		sg = (struct scatterlist *)cmd->request_buffer;
-		kunmap_atomic(buf - sg->offset, KM_IRQ0);
-		local_irq_restore(flags);
-	}
+	kunmap_atomic(buf - sg->offset, KM_IRQ0);
+	local_irq_restore(flags);
 }
 
 /* This function is called by the isr to complete an inquiry command */
@@ -1764,19 +1720,20 @@
 {
 	TW_Command *command_packet;
 	unsigned long command_que_value;
-	u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0;
+	u32 lba = 0x0, num_sectors = 0x0;
 	int i, use_sg;
 	struct scsi_cmnd *srb;
-	struct scatterlist *sglist;
+	struct scatterlist *sglist, *sg;
 
 	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
 
-	if (tw_dev->srb[request_id]->request_buffer == NULL) {
+	srb = tw_dev->srb[request_id];
+
+	sglist = scsi_sglist(srb);
+	if (!sglist) {
 		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
 		return 1;
 	}
-	sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
-	srb = tw_dev->srb[request_id];
 
 	/* Initialize command packet */
 	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
@@ -1819,33 +1776,18 @@
 	command_packet->byte8.io.lba = lba;
 	command_packet->byte6.block_count = num_sectors;
 
-	/* Do this if there are no sg list entries */
-	if (tw_dev->srb[request_id]->use_sg == 0) {    
-		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
-		buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
-		if (buffaddr == 0)
-			return 1;
+	use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
+	if (!use_sg)
+		return 1;
 
-		command_packet->byte8.io.sgl[0].address = buffaddr;
-		command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
+	scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
+		command_packet->byte8.io.sgl[i].address = sg_dma_address(sg);
+		command_packet->byte8.io.sgl[i].length = sg_dma_len(sg);
 		command_packet->size+=2;
 	}
 
-	/* Do this if we have multiple sg list entries */
-	if (tw_dev->srb[request_id]->use_sg > 0) {
-		use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
-		if (use_sg == 0)
-			return 1;
-
-		for (i=0;i<use_sg; i++) {
-			command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]);
-			command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
-			command_packet->size+=2;
-		}
-	}
-
 	/* Update SG statistics */
-	tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
+	tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
 	if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
 		tw_dev->max_sgl_entries = tw_dev->sgl_entries;
 
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index cb02656..71ff3fb 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -267,8 +267,6 @@
 		offset = max_offset;
 	}
 	if(XFERP < min_xferp) {
-		printk(KERN_WARNING "53c700: XFERP %d is less than minium, setting to %d\n",
-		       XFERP,  min_xferp);
 		XFERP =  min_xferp;
 	}
 	return (offset & 0x0f) | (XFERP & 0x07)<<4;
@@ -585,16 +583,8 @@
 	      struct NCR_700_command_slot *slot)
 {
 	if(SCp->sc_data_direction != DMA_NONE &&
-	   SCp->sc_data_direction != DMA_BIDIRECTIONAL) {
-		if(SCp->use_sg) {
-			dma_unmap_sg(hostdata->dev, SCp->request_buffer,
-				     SCp->use_sg, SCp->sc_data_direction);
-		} else {
-			dma_unmap_single(hostdata->dev, slot->dma_handle,
-					 SCp->request_bufflen,
-					 SCp->sc_data_direction);
-		}
-	}
+	   SCp->sc_data_direction != DMA_BIDIRECTIONAL)
+		scsi_dma_unmap(SCp);
 }
 
 STATIC inline void
@@ -661,7 +651,6 @@
 {
 	struct NCR_700_Host_Parameters *hostdata = 
 		(struct NCR_700_Host_Parameters *)host->hostdata[0];
-	__u32 dcntl_extra = 0;
 	__u8 min_period;
 	__u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);
 
@@ -686,13 +675,14 @@
 			        burst_disable = BURST_DISABLE;
 			        break;
 		}
-		dcntl_extra = COMPAT_700_MODE;
+		hostdata->dcntl_extra |= COMPAT_700_MODE;
 
-		NCR_700_writeb(dcntl_extra, host, DCNTL_REG);
+		NCR_700_writeb(hostdata->dcntl_extra, host, DCNTL_REG);
 		NCR_700_writeb(burst_length | hostdata->dmode_extra,
 			       host, DMODE_710_REG);
-		NCR_700_writeb(burst_disable | (hostdata->differential ? 
-						DIFF : 0), host, CTEST7_REG);
+		NCR_700_writeb(burst_disable | hostdata->ctest7_extra |
+			       (hostdata->differential ? DIFF : 0),
+			       host, CTEST7_REG);
 		NCR_700_writeb(BTB_TIMER_DISABLE, host, CTEST0_REG);
 		NCR_700_writeb(FULL_ARBITRATION | ENABLE_PARITY | PARITY
 			       | AUTO_ATN, host, SCNTL0_REG);
@@ -727,13 +717,13 @@
 		 * of spec: sync divider 2, async divider 3 */
 		DEBUG(("53c700: sync 2 async 3\n"));
 		NCR_700_writeb(SYNC_DIV_2_0, host, SBCL_REG);
-		NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
+		NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
 		hostdata->sync_clock = hostdata->clock/2;
 	} else	if(hostdata->clock > 50  && hostdata->clock <= 75) {
 		/* sync divider 1.5, async divider 3 */
 		DEBUG(("53c700: sync 1.5 async 3\n"));
 		NCR_700_writeb(SYNC_DIV_1_5, host, SBCL_REG);
-		NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
+		NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
 		hostdata->sync_clock = hostdata->clock*2;
 		hostdata->sync_clock /= 3;
 		
@@ -741,18 +731,18 @@
 		/* sync divider 1, async divider 2 */
 		DEBUG(("53c700: sync 1 async 2\n"));
 		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
-		NCR_700_writeb(ASYNC_DIV_2_0 | dcntl_extra, host, DCNTL_REG);
+		NCR_700_writeb(ASYNC_DIV_2_0 | hostdata->dcntl_extra, host, DCNTL_REG);
 		hostdata->sync_clock = hostdata->clock;
 	} else if(hostdata->clock > 25 && hostdata->clock <=37) {
 		/* sync divider 1, async divider 1.5 */
 		DEBUG(("53c700: sync 1 async 1.5\n"));
 		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
-		NCR_700_writeb(ASYNC_DIV_1_5 | dcntl_extra, host, DCNTL_REG);
+		NCR_700_writeb(ASYNC_DIV_1_5 | hostdata->dcntl_extra, host, DCNTL_REG);
 		hostdata->sync_clock = hostdata->clock;
 	} else {
 		DEBUG(("53c700: sync 1 async 1\n"));
 		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
-		NCR_700_writeb(ASYNC_DIV_1_0 | dcntl_extra, host, DCNTL_REG);
+		NCR_700_writeb(ASYNC_DIV_1_0 | hostdata->dcntl_extra, host, DCNTL_REG);
 		/* sync divider 1, async divider 1 */
 		hostdata->sync_clock = hostdata->clock;
 	}
@@ -1263,14 +1253,13 @@
 		       host->host_no, pun, lun, NCR_700_condition[i],
 		       NCR_700_phase[j], dsp - hostdata->pScript);
 		if(SCp != NULL) {
-			scsi_print_command(SCp);
+			struct scatterlist *sg;
 
-			if(SCp->use_sg) {
-				for(i = 0; i < SCp->use_sg + 1; i++) {
-					printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
-				}
+			scsi_print_command(SCp);
+			scsi_for_each_sg(SCp, sg, scsi_sg_count(SCp) + 1, i) {
+				printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, sg->length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
 			}
-		}	       
+		}
 		NCR_700_internal_bus_reset(host);
 	} else if((dsps & 0xfffff000) == A_DEBUG_INTERRUPT) {
 		printk(KERN_NOTICE "scsi%d (%d:%d) DEBUG INTERRUPT %d AT %08x[%04x], continuing\n",
@@ -1844,8 +1833,8 @@
 	}
 	/* sanity check: some of the commands generated by the mid-layer
 	 * have an eccentric idea of their sc_data_direction */
-	if(!SCp->use_sg && !SCp->request_bufflen 
-	   && SCp->sc_data_direction != DMA_NONE) {
+	if(!scsi_sg_count(SCp) && !scsi_bufflen(SCp) &&
+	   SCp->sc_data_direction != DMA_NONE) {
 #ifdef NCR_700_DEBUG
 		printk("53c700: Command");
 		scsi_print_command(SCp);
@@ -1887,31 +1876,15 @@
 		int i;
 		int sg_count;
 		dma_addr_t vPtr = 0;
+		struct scatterlist *sg;
 		__u32 count = 0;
 
-		if(SCp->use_sg) {
-			sg_count = dma_map_sg(hostdata->dev,
-					      SCp->request_buffer, SCp->use_sg,
-					      direction);
-		} else {
-			vPtr = dma_map_single(hostdata->dev,
-					      SCp->request_buffer, 
-					      SCp->request_bufflen,
-					      direction);
-			count = SCp->request_bufflen;
-			slot->dma_handle = vPtr;
-			sg_count = 1;
-		}
-			
+		sg_count = scsi_dma_map(SCp);
+		BUG_ON(sg_count < 0);
 
-		for(i = 0; i < sg_count; i++) {
-
-			if(SCp->use_sg) {
-				struct scatterlist *sg = SCp->request_buffer;
-
-				vPtr = sg_dma_address(&sg[i]);
-				count = sg_dma_len(&sg[i]);
-			}
+		scsi_for_each_sg(SCp, sg, sg_count, i) {
+			vPtr = sg_dma_address(sg);
+			count = sg_dma_len(sg);
 
 			slot->SG[i].ins = bS_to_host(move_ins | count);
 			DEBUG((" scatter block %d: move %d[%08x] from 0x%lx\n",
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index 841e1bb..e06bdfe 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -177,6 +177,7 @@
 	__u8	state;
 	#define NCR_700_FLAG_AUTOSENSE	0x01
 	__u8	flags;
+	__u8	pad1[2];	/* Needed for m68k where min alignment is 2 bytes */
 	int	tag;
 	__u32	resume_offset;
 	struct scsi_cmnd *cmnd;
@@ -196,6 +197,8 @@
 	void __iomem	*base;		/* the base for the port (copied to host) */
 	struct device	*dev;
 	__u32	dmode_extra;	/* adjustable bus settings */
+	__u32	dcntl_extra;	/* adjustable bus settings */
+	__u32	ctest7_extra;	/* adjustable bus settings */
 	__u32	differential:1;	/* if we are differential */
 #ifdef CONFIG_53C700_LE_ON_BE
 	/* This option is for HP only.  Set it if your chip is wired for
@@ -352,6 +355,7 @@
 #define		SEL_TIMEOUT_DISABLE	0x10 /* 710 only */
 #define         DFP                     0x08
 #define         EVP                     0x04
+#define         CTEST7_TT1              0x02
 #define		DIFF			0x01
 #define CTEST6_REG                      0x1A
 #define	TEMP_REG			0x1C
@@ -385,6 +389,7 @@
 #define		SOFTWARE_RESET		0x01
 #define		COMPAT_700_MODE		0x01
 #define 	SCRPTS_16BITS		0x20
+#define		EA_710			0x20
 #define		ASYNC_DIV_2_0		0x00
 #define		ASYNC_DIV_1_5		0x40
 #define		ASYNC_DIV_1_0		0x80
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
deleted file mode 100644
index 93b41f4..0000000
--- a/drivers/scsi/53c7xx.c
+++ /dev/null
@@ -1,6102 +0,0 @@
-/*
- * 53c710 driver.  Modified from Drew Eckhardts driver
- * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
- * Check out PERM_OPTIONS and EXPECTED_CLOCK, which may be defined in the
- * relevant machine specific file (eg. mvme16x.[ch], amiga7xx.[ch]).
- * There are also currently some defines at the top of 53c7xx.scr.
- * The chip type is #defined in script_asm.pl, as well as the Makefile.
- * Host scsi ID expected to be 7 - see NCR53c7x0_init().
- *
- * I have removed the PCI code and some of the 53c8xx specific code - 
- * simply to make this file smaller and easier to manage.
- *
- * MVME16x issues:
- *   Problems trying to read any chip registers in NCR53c7x0_init(), as they
- *   may never have been set by 16xBug (eg. If kernel has come in over tftp).
- */
-
-/*
- * Adapted for Linux/m68k Amiga platforms for the A4000T/A4091 and
- * WarpEngine SCSI controllers.
- * By Alan Hourihane <alanh@fairlite.demon.co.uk>
- * Thanks to Richard Hirst for making it possible with the MVME additions
- */
-
-/*
- * 53c710 rev 0 doesn't support add with carry.  Rev 1 and 2 does.  To
- * overcome this problem you can define FORCE_DSA_ALIGNMENT, which ensures
- * that the DSA address is always xxxxxx00.  If disconnection is not allowed,
- * then the script only ever tries to add small (< 256) positive offsets to
- * DSA, so lack of carry isn't a problem.  FORCE_DSA_ALIGNMENT can, of course,
- * be defined for all chip revisions at a small cost in memory usage.
- */
-
-#define FORCE_DSA_ALIGNMENT
-
-/*
- * Selection timer does not always work on the 53c710, depending on the
- * timing at the last disconnect, if this is a problem for you, try
- * using validids as detailed below.
- *
- * Options for the NCR7xx driver
- *
- * noasync:0		-	disables sync and asynchronous negotiation
- * nosync:0		-	disables synchronous negotiation (does async)
- * nodisconnect:0	-	disables disconnection
- * validids:0x??	-	Bitmask field that disallows certain ID's.
- *			-	e.g.	0x03	allows ID 0,1
- *			-		0x1F	allows ID 0,1,2,3,4
- * opthi:n		-	replace top word of options with 'n'
- * optlo:n		-	replace bottom word of options with 'n'
- *			-	ALWAYS SPECIFY opthi THEN optlo <<<<<<<<<<
- */
-
-/*
- * PERM_OPTIONS are driver options which will be enabled for all NCR boards
- * in the system at driver initialization time.
- *
- * Don't THINK about touching these in PERM_OPTIONS : 
- *   OPTION_MEMORY_MAPPED 
- * 	680x0 doesn't have an IO map!
- *
- *   OPTION_DEBUG_TEST1
- *	Test 1 does bus mastering and interrupt tests, which will help weed 
- *	out brain damaged main boards.
- *
- * Other PERM_OPTIONS settings are listed below.  Note the actual options
- * required are set in the relevant file (mvme16x.c, amiga7xx.c, etc):
- *
- *   OPTION_NO_ASYNC
- *	Don't negotiate for asynchronous transfers on the first command 
- *	when OPTION_ALWAYS_SYNCHRONOUS is set.  Useful for dain bramaged
- *	devices which do something bad rather than sending a MESSAGE 
- *	REJECT back to us like they should if they can't cope.
- *
- *   OPTION_SYNCHRONOUS
- *	Enable support for synchronous transfers.  Target negotiated 
- *	synchronous transfers will be responded to.  To initiate 
- *	a synchronous transfer request,  call 
- *
- *	    request_synchronous (hostno, target) 
- *
- *	from within KGDB.
- *
- *   OPTION_ALWAYS_SYNCHRONOUS
- *	Negotiate for synchronous transfers with every target after
- *	driver initialization or a SCSI bus reset.  This is a bit dangerous, 
- *	since there are some dain bramaged SCSI devices which will accept
- *	SDTR messages but keep talking asynchronously.
- *
- *   OPTION_DISCONNECT
- *	Enable support for disconnect/reconnect.  To change the 
- *	default setting on a given host adapter, call
- *
- *	    request_disconnect (hostno, allow)
- *
- *	where allow is non-zero to allow, 0 to disallow.
- * 
- *  If you really want to run 10MHz FAST SCSI-II transfers, you should 
- *  know that the NCR driver currently ignores parity information.  Most
- *  systems do 5MHz SCSI fine.  I've seen a lot that have problems faster
- *  than 8MHz.  To play it safe, we only request 5MHz transfers.
- *
- *  If you'd rather get 10MHz transfers, edit sdtr_message and change 
- *  the fourth byte from 50 to 25.
- */
-
-/*
- * Sponsored by 
- *	iX Multiuser Multitasking Magazine
- *	Hannover, Germany
- *	hm@ix.de
- *
- * Copyright 1993, 1994, 1995 Drew Eckhardt
- *      Visionary Computing 
- *      (Unix and Linux consulting and custom programming)
- *      drew@PoohSticks.ORG
- *	+1 (303) 786-7975
- *
- * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
- * 
- * For more information, please consult 
- *
- * NCR53C810 
- * SCSI I/O Processor
- * Programmer's Guide
- *
- * NCR 53C810
- * PCI-SCSI I/O Processor
- * Data Manual
- *
- * NCR 53C810/53C820
- * PCI-SCSI I/O Processor Design In Guide
- *
- * For literature on Symbios Logic Inc. formerly NCR, SCSI, 
- * and Communication products please call (800) 334-5454 or
- * (719) 536-3300. 
- * 
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
- *
- * PCI Special Interest Group
- * M/S HF3-15A
- * 5200 N.E. Elam Young Parkway
- * Hillsboro, Oregon 97124-6497
- * +1 (503) 696-2000 
- * +1 (800) 433-5177
- */
-
-/*
- * Design issues : 
- * The cumulative latency needed to propagate a read/write request 
- * through the file system, buffer cache, driver stacks, SCSI host, and 
- * SCSI device is ultimately the limiting factor in throughput once we 
- * have a sufficiently fast host adapter.
- *  
- * So, to maximize performance we want to keep the ratio of latency to data 
- * transfer time to a minimum by
- * 1.  Minimizing the total number of commands sent (typical command latency
- *	including drive and bus mastering host overhead is as high as 4.5ms)
- *	to transfer a given amount of data.  
- *
- *      This is accomplished by placing no arbitrary limit on the number
- *	of scatter/gather buffers supported, since we can transfer 1K
- *	per scatter/gather buffer without Eric's cluster patches, 
- *	4K with.  
- *
- * 2.  Minimizing the number of fatal interrupts serviced, since
- * 	fatal interrupts halt the SCSI I/O processor.  Basically,
- *	this means offloading the practical maximum amount of processing 
- *	to the SCSI chip.
- * 
- *	On the NCR53c810/820/720,  this is accomplished by using 
- *		interrupt-on-the-fly signals when commands complete, 
- *		and only handling fatal errors and SDTR / WDTR 	messages 
- *		in the host code.
- *
- *	On the NCR53c710, interrupts are generated as on the NCR53c8x0,
- *		only the lack of a interrupt-on-the-fly facility complicates
- *		things.   Also, SCSI ID registers and commands are 
- *		bit fielded rather than binary encoded.
- *		
- * 	On the NCR53c700 and NCR53c700-66, operations that are done via 
- *		indirect, table mode on the more advanced chips must be
- *	        replaced by calls through a jump table which 
- *		acts as a surrogate for the DSA.  Unfortunately, this 
- * 		will mean that we must service an interrupt for each 
- *		disconnect/reconnect.
- * 
- * 3.  Eliminating latency by pipelining operations at the different levels.
- * 	
- *	This driver allows a configurable number of commands to be enqueued
- *	for each target/lun combination (experimentally, I have discovered
- *	that two seems to work best) and will ultimately allow for 
- *	SCSI-II tagged queuing.
- * 	
- *
- * Architecture : 
- * This driver is built around a Linux queue of commands waiting to 
- * be executed, and a shared Linux/NCR array of commands to start.  Commands
- * are transferred to the array  by the run_process_issue_queue() function 
- * which is called whenever a command completes.
- *
- * As commands are completed, the interrupt routine is triggered,
- * looks for commands in the linked list of completed commands with
- * valid status, removes these commands from a list of running commands, 
- * calls the done routine, and flags their target/luns as not busy.
- *
- * Due to limitations in the intelligence of the NCR chips, certain
- * concessions are made.  In many cases, it is easier to dynamically 
- * generate/fix-up code rather than calculate on the NCR at run time.  
- * So, code is generated or fixed up for
- *
- * - Handling data transfers, using a variable number of MOVE instructions
- *	interspersed with CALL MSG_IN, WHEN MSGIN instructions.
- *
- * 	The DATAIN and DATAOUT routines	are separate, so that an incorrect
- *	direction can be trapped, and space isn't wasted. 
- *
- *	It may turn out that we're better off using some sort 
- *	of table indirect instruction in a loop with a variable
- *	sized table on the NCR53c710 and newer chips.
- *
- * - Checking for reselection (NCR53c710 and better)
- *
- * - Handling the details of SCSI context switches (NCR53c710 and better),
- *	such as reprogramming appropriate synchronous parameters, 
- *	removing the dsa structure from the NCR's queue of outstanding
- *	commands, etc.
- *
- */
-
-#include <linux/module.h>
-
-
-#include <linux/types.h>
-#include <asm/setup.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/time.h>
-#include <linux/blkdev.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <asm/pgtable.h>
-
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/irq.h>
-
-#define BIG_ENDIAN
-#define NO_IO_SPACE
-#endif
-
-#ifdef CONFIG_MVME16x
-#include <asm/mvme16xhw.h>
-
-#define BIG_ENDIAN
-#define NO_IO_SPACE
-#define VALID_IDS
-#endif
-
-#ifdef CONFIG_BVME6000
-#include <asm/bvme6000hw.h>
-
-#define BIG_ENDIAN
-#define NO_IO_SPACE
-#define VALID_IDS
-#endif
-
-#include "scsi.h"
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_transport_spi.h>
-#include "53c7xx.h"
-#include <linux/stat.h>
-#include <linux/stddef.h>
-
-#ifdef NO_IO_SPACE
-/*
- * The following make the definitions in 53c7xx.h (write8, etc) smaller,
- * we don't have separate i/o space anyway.
- */
-#undef inb
-#undef outb
-#undef inw
-#undef outw
-#undef inl
-#undef outl
-#define inb(x)          1
-#define inw(x)          1
-#define inl(x)          1
-#define outb(x,y)       1
-#define outw(x,y)       1
-#define outl(x,y)       1
-#endif
-
-static int check_address (unsigned long addr, int size);
-static void dump_events (struct Scsi_Host *host, int count);
-static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, 
-    int free, int issue);
-static void hard_reset (struct Scsi_Host *host);
-static void ncr_scsi_reset (struct Scsi_Host *host);
-static void print_lots (struct Scsi_Host *host);
-static void set_synchronous (struct Scsi_Host *host, int target, int sxfer, 
-    int scntl3, int now_connected);
-static int datapath_residual (struct Scsi_Host *host);
-static const char * sbcl_to_phase (int sbcl);
-static void print_progress (Scsi_Cmnd *cmd);
-static void print_queues (struct Scsi_Host *host);
-static void process_issue_queue (unsigned long flags);
-static int shutdown (struct Scsi_Host *host);
-static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);
-static int disable (struct Scsi_Host *host);
-static int NCR53c7xx_run_tests (struct Scsi_Host *host);
-static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id);
-static void NCR53c7x0_intfly (struct Scsi_Host *host);
-static int ncr_halt (struct Scsi_Host *host);
-static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
-    *cmd);
-static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
-static void print_dsa (struct Scsi_Host *host, u32 *dsa,
-    const char *prefix);
-static int print_insn (struct Scsi_Host *host, const u32 *insn,
-    const char *prefix, int kernel);
-
-static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd);
-static void NCR53c7x0_init_fixup (struct Scsi_Host *host);
-static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct 
-    NCR53c7x0_cmd *cmd);
-static void NCR53c7x0_soft_reset (struct Scsi_Host *host);
-
-/* Size of event list (per host adapter) */
-static int track_events = 0;
-static struct Scsi_Host *first_host = NULL;	/* Head of list of NCR boards */
-static struct scsi_host_template *the_template = NULL;
-
-/* NCR53c710 script handling code */
-
-#include "53c7xx_d.h"
-#ifdef A_int_debug_sync
-#define DEBUG_SYNC_INTR A_int_debug_sync
-#endif
-int NCR53c7xx_script_len = sizeof (SCRIPT);
-int NCR53c7xx_dsa_len = A_dsa_end + Ent_dsa_zero - Ent_dsa_code_template;
-#ifdef FORCE_DSA_ALIGNMENT
-int CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff;
-#endif
-
-static char *setup_strings[] =
-	{"","","","","","","",""};
-
-#define MAX_SETUP_STRINGS ARRAY_SIZE(setup_strings)
-#define SETUP_BUFFER_SIZE 200
-static char setup_buffer[SETUP_BUFFER_SIZE];
-static char setup_used[MAX_SETUP_STRINGS];
-
-void ncr53c7xx_setup (char *str, int *ints)
-{
-   int i;
-   char *p1, *p2;
-
-   p1 = setup_buffer;
-   *p1 = '\0';
-   if (str)
-      strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
-   setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
-   p1 = setup_buffer;
-   i = 0;
-   while (*p1 && (i < MAX_SETUP_STRINGS)) {
-      p2 = strchr(p1, ',');
-      if (p2) {
-         *p2 = '\0';
-         if (p1 != p2)
-            setup_strings[i] = p1;
-         p1 = p2 + 1;
-         i++;
-         }
-      else {
-         setup_strings[i] = p1;
-         break;
-         }
-      }
-   for (i=0; i<MAX_SETUP_STRINGS; i++)
-      setup_used[i] = 0;
-}
-
-
-/* check_setup_strings() returns index if key found, 0 if not
- */
-
-static int check_setup_strings(char *key, int *flags, int *val, char *buf)
-{
-int x;
-char *cp;
-
-   for  (x=0; x<MAX_SETUP_STRINGS; x++) {
-      if (setup_used[x])
-         continue;
-      if (!strncmp(setup_strings[x], key, strlen(key)))
-         break;
-      if (!strncmp(setup_strings[x], "next", strlen("next")))
-         return 0;
-      }
-   if (x == MAX_SETUP_STRINGS)
-      return 0;
-   setup_used[x] = 1;
-   cp = setup_strings[x] + strlen(key);
-   *val = -1;
-   if (*cp != ':')
-      return ++x;
-   cp++;
-   if ((*cp >= '0') && (*cp <= '9')) {
-      *val = simple_strtoul(cp,NULL,0);
-      }
-   return ++x;
-}
-
-
-
-/*
- * KNOWN BUGS :
- * - There is some sort of conflict when the PPP driver is compiled with 
- * 	support for 16 channels?
- * 
- * - On systems which predate the 1.3.x initialization order change,
- *      the NCR driver will cause Cannot get free page messages to appear.  
- *      These are harmless, but I don't know of an easy way to avoid them.
- *
- * - With OPTION_DISCONNECT, on two systems under unknown circumstances,
- *	we get a PHASE MISMATCH with DSA set to zero (suggests that we 
- *	are occurring somewhere in the reselection code) where 
- *	DSP=some value DCMD|DBC=same value.  
- * 	
- *	Closer inspection suggests that we may be trying to execute
- *	some portion of the DSA?
- * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO)
- * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO)
- * scsi0 : no current command : unexpected phase MSGIN.
- *         DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0
- *         DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80
- * scsi0 : DSP->
- * 001c46cc : 0x001c46cc 0x00000000
- * 001c46d4 : 0x001c5ea0 0x000011f8
- *
- *	Changed the print code in the phase_mismatch handler so
- *	that we call print_lots to try to diagnose this.
- *
- */
-
-/* 
- * Possible future direction of architecture for max performance :
- *
- * We're using a single start array for the NCR chip.  This is 
- * sub-optimal, because we cannot add a command which would conflict with 
- * an executing command to this start queue, and therefore must insert the 
- * next command for a given I/T/L combination after the first has completed;
- * incurring our interrupt latency between SCSI commands.
- *
- * To allow further pipelining of the NCR and host CPU operation, we want 
- * to set things up so that immediately on termination of a command destined 
- * for a given LUN, we get that LUN busy again.  
- * 
- * To do this, we need to add a 32 bit pointer to which is jumped to 
- * on completion of a command.  If no new command is available, this 
- * would point to the usual DSA issue queue select routine.
- *
- * If one were, it would point to a per-NCR53c7x0_cmd select routine 
- * which starts execution immediately, inserting the command at the head 
- * of the start queue if the NCR chip is selected or reselected.
- *
- * We would change so that we keep a list of outstanding commands 
- * for each unit, rather than a single running_list.  We'd insert 
- * a new command into the right running list; if the NCR didn't 
- * have something running for that yet, we'd put it in the 
- * start queue as well.  Some magic needs to happen to handle the 
- * race condition between the first command terminating before the 
- * new one is written.
- *
- * Potential for profiling : 
- * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution.
- */
-
-
-/*
- * TODO : 
- * 1.  To support WIDE transfers, not much needs to happen.  We
- *	should do CHMOVE instructions instead of MOVEs when
- *	we have scatter/gather segments of uneven length.  When
- * 	we do this, we need to handle the case where we disconnect
- *	between segments.
- * 
- * 2.  Currently, when Icky things happen we do a FATAL().  Instead,
- *     we want to do an integrity check on the parts of the NCR hostdata
- *     structure which were initialized at boot time; FATAL() if that 
- *     fails, and otherwise try to recover.  Keep track of how many
- *     times this has happened within a single SCSI command; if it 
- *     gets excessive, then FATAL().
- *
- * 3.  Parity checking is currently disabled, and a few things should 
- *     happen here now that we support synchronous SCSI transfers :
- *     1.  On soft-reset, we shoould set the EPC (Enable Parity Checking)
- *	   and AAP (Assert SATN/ on parity error) bits in SCNTL0.
- *	
- *     2.  We should enable the parity interrupt in the SIEN0 register.
- * 
- *     3.  intr_phase_mismatch() needs to believe that message out is 
- *	   always an "acceptable" phase to have a mismatch in.  If 
- *	   the old phase was MSG_IN, we should send a MESSAGE PARITY 
- *	   error.  If the old phase was something else, we should send
- *	   a INITIATOR_DETECTED_ERROR message.  Note that this could
- *	   cause a RESTORE POINTERS message; so we should handle that 
- *	   correctly first.  Instead, we should probably do an 
- *	   initiator_abort.
- *
- * 4.  MPEE bit of CTEST4 should be set so we get interrupted if 
- *     we detect an error.
- *
- *  
- * 5.  The initial code has been tested on the NCR53c810.  I don't 
- *     have access to NCR53c700, 700-66 (Forex boards), NCR53c710
- *     (NCR Pentium systems), NCR53c720, NCR53c820, or NCR53c825 boards to 
- *     finish development on those platforms.
- *
- *     NCR53c820/825/720 - need to add wide transfer support, including WDTR 
- *     		negotiation, programming of wide transfer capabilities
- *		on reselection and table indirect selection.
- *
- *     NCR53c710 - need to add fatal interrupt or GEN code for 
- *		command completion signaling.   Need to modify all 
- *		SDID, SCID, etc. registers, and table indirect select code 
- *		since these use bit fielded (ie 1<<target) instead of 
- *		binary encoded target ids.  Need to accommodate
- *		different register mappings, probably scan through
- *		the SCRIPT code and change the non SFBR register operand
- *		of all MOVE instructions.
- *
- *		It is rather worse than this actually, the 710 corrupts
- *		both TEMP and DSA when you do a MOVE MEMORY.  This
- *		screws you up all over the place.  MOVE MEMORY 4 with a
- *		destination of DSA seems to work OK, which helps some.
- *		Richard Hirst  richard@sleepie.demon.co.uk
- * 
- *     NCR53c700/700-66 - need to add code to refix addresses on 
- *		every nexus change, eliminate all table indirect code,
- *		very messy.
- *
- * 6.  The NCR53c7x0 series is very popular on other platforms that 
- *     could be running Linux - ie, some high performance AMIGA SCSI 
- *     boards use it.  
- *	
- *     So, I should include #ifdef'd code so that it is 
- *     compatible with these systems.
- *	
- *     Specifically, the little Endian assumptions I made in my 
- *     bit fields need to change, and if the NCR doesn't see memory
- *     the right way, we need to provide options to reverse words
- *     when the scripts are relocated.
- *
- * 7.  Use vremap() to access memory mapped boards.  
- */
-
-/* 
- * Allow for simultaneous existence of multiple SCSI scripts so we 
- * can have a single driver binary for all of the family.
- *
- * - one for NCR53c700 and NCR53c700-66 chips	(not yet supported)
- * - one for rest (only the NCR53c810, 815, 820, and 825 are currently 
- *	supported)
- * 
- * So that we only need two SCSI scripts, we need to modify things so
- * that we fixup register accesses in READ/WRITE instructions, and 
- * we'll also have to accommodate the bit vs. binary encoding of IDs
- * with the 7xx chips.
- */
-
-#define ROUNDUP(adr,type)	\
-  ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1)))
-
-
-/*
- * Function: issue_to_cmd
- *
- * Purpose: convert jump instruction in issue array to NCR53c7x0_cmd
- *	structure pointer.  
- *
- * Inputs; issue - pointer to start of NOP or JUMP instruction
- *	in issue array.
- *
- * Returns: pointer to command on success; 0 if opcode is NOP.
- */
-
-static inline struct NCR53c7x0_cmd *
-issue_to_cmd (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
-    u32 *issue)
-{
-    return (issue[0] != hostdata->NOP_insn) ? 
-    /* 
-     * If the IF TRUE bit is set, it's a JUMP instruction.  The
-     * operand is a bus pointer to the dsa_begin routine for this DSA.  The
-     * dsa field of the NCR53c7x0_cmd structure starts with the 
-     * DSA code template.  By converting to a virtual address,
-     * subtracting the code template size, and offset of the 
-     * dsa field, we end up with a pointer to the start of the 
-     * structure (alternatively, we could use the 
-     * dsa_cmnd field, an anachronism from when we weren't
-     * sure what the relationship between the NCR structures
-     * and host structures were going to be.
-     */
-	(struct NCR53c7x0_cmd *) ((char *) bus_to_virt (issue[1]) - 
-	    (hostdata->E_dsa_code_begin - hostdata->E_dsa_code_template) -
-	    offsetof(struct NCR53c7x0_cmd, dsa)) 
-    /* If the IF TRUE bit is not set, it's a NOP */
-	: NULL;
-}
-
-
-/* 
- * FIXME: we should junk these, in favor of synchronous_want and 
- * wide_want in the NCR53c7x0_hostdata structure.
- */
-
-/* Template for "preferred" synchronous transfer parameters. */
-
-static const unsigned char sdtr_message[] = {
-#ifdef CONFIG_SCSI_NCR53C7xx_FAST
-    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 25 /* *4ns */, 8 /* off */
-#else
-    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 50 /* *4ns */, 8 /* off */ 
-#endif
-};
-
-/* Template to request asynchronous transfers */
-
-static const unsigned char async_message[] = {
-    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */
-};
-
-/* Template for "preferred" WIDE transfer parameters */
-
-static const unsigned char wdtr_message[] = {
-    EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */
-};
-
-#if 0
-/*
- * Function : struct Scsi_Host *find_host (int host)
- * 
- * Purpose : KGDB support function which translates a host number 
- * 	to a host structure. 
- *
- * Inputs : host - number of SCSI host
- *
- * Returns : NULL on failure, pointer to host structure on success.
- */
-
-static struct Scsi_Host *
-find_host (int host) {
-    struct Scsi_Host *h;
-    for (h = first_host; h && h->host_no != host; h = h->next);
-    if (!h) {
-	printk (KERN_ALERT "scsi%d not found\n", host);
-	return NULL;
-    } else if (h->hostt != the_template) {
-	printk (KERN_ALERT "scsi%d is not a NCR board\n", host);
-	return NULL;
-    }
-    return h;
-}
-
-#if 0
-/*
- * Function : request_synchronous (int host, int target)
- * 
- * Purpose : KGDB interface which will allow us to negotiate for 
- * 	synchronous transfers.  This ill be replaced with a more 
- * 	integrated function; perhaps a new entry in the scsi_host 
- *	structure, accessible via an ioctl() or perhaps /proc/scsi.
- *
- * Inputs : host - number of SCSI host; target - number of target.
- *
- * Returns : 0 when negotiation has been setup for next SCSI command,
- *	-1 on failure.
- */
-
-static int
-request_synchronous (int host, int target) {
-    struct Scsi_Host *h;
-    struct NCR53c7x0_hostdata *hostdata;
-    unsigned long flags;
-    if (target < 0) {
-	printk (KERN_ALERT "target %d is bogus\n", target);
-	return -1;
-    }
-    if (!(h = find_host (host)))
-	return -1;
-    else if (h->this_id == target) {
-	printk (KERN_ALERT "target %d is host ID\n", target);
-	return -1;
-    } 
-    else if (target >= h->max_id) {
-	printk (KERN_ALERT "target %d exceeds maximum of %d\n", target,
-	    h->max_id);
-	return -1;
-    }
-    hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0];
-
-    local_irq_save(flags);
-    if (hostdata->initiate_sdtr & (1 << target)) {
-	local_irq_restore(flags);
-	printk (KERN_ALERT "target %d already doing SDTR\n", target);
-	return -1;
-    } 
-    hostdata->initiate_sdtr |= (1 << target);
-    local_irq_restore(flags);
-    return 0;
-}
-#endif
-
-/*
- * Function : request_disconnect (int host, int on_or_off)
- * 
- * Purpose : KGDB support function, tells us to allow or disallow 
- *	disconnections.
- *
- * Inputs : host - number of SCSI host; on_or_off - non-zero to allow,
- *	zero to disallow.
- *
- * Returns : 0 on success, *	-1 on failure.
- */
-
-static int 
-request_disconnect (int host, int on_or_off) {
-    struct Scsi_Host *h;
-    struct NCR53c7x0_hostdata *hostdata;
-    if (!(h = find_host (host)))
-	return -1;
-    hostdata = (struct NCR53c7x0_hostdata *) h->hostdata[0];
-    if (on_or_off) 
-	hostdata->options |= OPTION_DISCONNECT;
-    else
-	hostdata->options &= ~OPTION_DISCONNECT;
-    return 0;
-}
-#endif
-
-/*
- * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host)
- *
- * Purpose : Initialize internal structures, as required on startup, or 
- *	after a SCSI bus reset.
- * 
- * Inputs : host - pointer to this host adapter's structure
- */
-
-static void 
-NCR53c7x0_driver_init (struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    int i, j;
-    u32 *ncrcurrent;
-
-    for (i = 0; i < 16; ++i) {
-	hostdata->request_sense[i] = 0;
-    	for (j = 0; j < 8; ++j) 
-	    hostdata->busy[i][j] = 0;
-	set_synchronous (host, i, /* sxfer */ 0, hostdata->saved_scntl3, 0);
-    }
-    hostdata->issue_queue = NULL;
-    hostdata->running_list = hostdata->finished_queue = 
-	hostdata->ncrcurrent = NULL;
-    for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 
-	i < host->can_queue; ++i, ncrcurrent += 2) {
-	ncrcurrent[0] = hostdata->NOP_insn;
-	ncrcurrent[1] = 0xdeadbeef;
-    }
-    ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE;
-    ncrcurrent[1] = (u32) virt_to_bus (hostdata->script) +
-	hostdata->E_wait_reselect;
-    hostdata->reconnect_dsa_head = 0;
-    hostdata->addr_reconnect_dsa_head = (u32) 
-	virt_to_bus((void *) &(hostdata->reconnect_dsa_head));
-    hostdata->expecting_iid = 0;
-    hostdata->expecting_sto = 0;
-    if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS) 
-	hostdata->initiate_sdtr = 0xffff; 
-    else
-    	hostdata->initiate_sdtr = 0;
-    hostdata->talked_to = 0;
-    hostdata->idle = 1;
-}
-
-/* 
- * Function : static int clock_to_ccf_710 (int clock)
- *
- * Purpose :  Return the clock conversion factor for a given SCSI clock.
- *
- * Inputs : clock - SCSI clock expressed in Hz.
- *
- * Returns : ccf on success, -1 on failure.
- */
-
-static int 
-clock_to_ccf_710 (int clock) {
-    if (clock <= 16666666)
-	return -1;
-    if (clock <= 25000000)
-	return 2; 	/* Divide by 1.0 */
-    else if (clock <= 37500000)
-	return 1; 	/* Divide by 1.5 */
-    else if (clock <= 50000000)
-	return 0;	/* Divide by 2.0 */
-    else if (clock <= 66000000)
-	return 3;	/* Divide by 3.0 */
-    else 
-	return -1;
-}
-    
-/* 
- * Function : static int NCR53c7x0_init (struct Scsi_Host *host)
- *
- * Purpose :  initialize the internal structures for a given SCSI host
- *
- * Inputs : host - pointer to this host adapter's structure
- *
- * Preconditions : when this function is called, the chip_type 
- * 	field of the hostdata structure MUST have been set.
- *
- * Returns : 0 on success, -1 on failure.
- */
-
-int 
-NCR53c7x0_init (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    int i, ccf;
-    unsigned char revision;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    /* 
-     * There are some things which we need to know about in order to provide
-     * a semblance of support.  Print 'em if they aren't what we expect, 
-     * otherwise don't add to the noise.
-     * 
-     * -1 means we don't know what to expect.
-     */
-    int val, flags;
-    char buf[32];
-    int expected_id = -1;
-    int expected_clock = -1;
-    int uninitialized = 0;
-#ifdef NO_IO_SPACE
-    int expected_mapping = OPTION_MEMORY_MAPPED;
-#else
-    int expected_mapping = OPTION_IO_MAPPED;
-#endif
-    for (i=0;i<7;i++)
-	hostdata->valid_ids[i] = 1;	/* Default all ID's to scan */
-
-    /* Parse commandline flags */
-    if (check_setup_strings("noasync",&flags,&val,buf))
-    {
-	hostdata->options |= OPTION_NO_ASYNC;
-	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
-    }
-
-    if (check_setup_strings("nosync",&flags,&val,buf))
-    {
-	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
-    }
-
-    if (check_setup_strings("nodisconnect",&flags,&val,buf))
-	hostdata->options &= ~OPTION_DISCONNECT;
-
-    if (check_setup_strings("validids",&flags,&val,buf))
-    {
-	for (i=0;i<7;i++) 
-		hostdata->valid_ids[i] = val & (1<<i);
-    }
- 
-    if  ((i = check_setup_strings("next",&flags,&val,buf)))
-    {
-	while (i)
-		setup_used[--i] = 1;
-    }
-
-    if (check_setup_strings("opthi",&flags,&val,buf))
-	hostdata->options = (long long)val << 32;
-    if (check_setup_strings("optlo",&flags,&val,buf))
-	hostdata->options |= val;
-
-    NCR53c7x0_local_setup(host);
-    switch (hostdata->chip) {
-    case 710:
-    case 770:
-    	hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr;
-    	hostdata->init_save_regs = NULL;
-    	hostdata->dsa_fixup = NCR53c7xx_dsa_fixup;
-    	hostdata->init_fixup = NCR53c7x0_init_fixup;
-    	hostdata->soft_reset = NCR53c7x0_soft_reset;
-	hostdata->run_tests = NCR53c7xx_run_tests;
-	expected_clock = hostdata->scsi_clock;
-	expected_id = 7;
-    	break;
-    default:
-	printk ("scsi%d : chip type of %d is not supported yet, detaching.\n",
-	    host->host_no, hostdata->chip);
-	scsi_unregister (host);
-	return -1;
-    }
-
-    /* Assign constants accessed by NCR */
-    hostdata->NCR53c7xx_zero = 0;			
-    hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT;
-    hostdata->NCR53c7xx_msg_abort = ABORT;
-    hostdata->NCR53c7xx_msg_nop = NOP;
-    hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24;
-    if (expected_mapping == -1 || 
-	(hostdata->options & (OPTION_MEMORY_MAPPED)) != 
-	(expected_mapping & OPTION_MEMORY_MAPPED))
-	printk ("scsi%d : using %s mapped access\n", host->host_no, 
-	    (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" : 
-	    "io");
-
-    hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ? 
-	DMODE_REG_00 : DMODE_REG_10;
-    hostdata->istat = ((hostdata->chip / 100) == 8) ? 
-    	ISTAT_REG_800 : ISTAT_REG_700;
-
-/* We have to assume that this may be the first access to the chip, so
- * we must set EA in DCNTL. */
-
-    NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM);
-
-
-/* Only the ISTAT register is readable when the NCR is running, so make 
-   sure it's halted. */
-    ncr_halt(host);
-
-/* 
- * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc,
- *	as does the 710 with one bit per SCSI ID.  Conversely, the NCR
- * 	uses a normal, 3 bit binary representation of these values.
- *
- * Get the rest of the NCR documentation, and FIND OUT where the change
- * was.
- */
-
-#if 0
-	/* May not be able to do this - chip my not have been set up yet */
-	tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG);
-	for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id);
-#else
-	host->this_id = 7;
-#endif
-
-/*
- * Note : we should never encounter a board setup for ID0.  So,
- * 	if we see ID0, assume that it was uninitialized and set it
- * 	to the industry standard 7.
- */
-    if (!host->this_id) {
-	printk("scsi%d : initiator ID was %d, changing to 7\n",
-	    host->host_no, host->this_id);
-	host->this_id = 7;
-	hostdata->this_id_mask = 1 << 7;
-	uninitialized = 1;
-    };
-
-    if (expected_id == -1 || host->this_id != expected_id)
-    	printk("scsi%d : using initiator ID %d\n", host->host_no,
-    	    host->this_id);
-
-    /*
-     * Save important registers to allow a soft reset.
-     */
-
-    /*
-     * CTEST7 controls cache snooping, burst mode, and support for 
-     * external differential drivers.  This isn't currently used - the
-     * default value may not be optimal anyway.
-     * Even worse, it may never have been set up since reset.
-     */
-    hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE;
-    revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4;
-    switch (revision) {
-	case 1: revision = 0;    break;
-	case 2: revision = 1;    break;
-	case 4: revision = 2;    break;
-	case 8: revision = 3;    break;
-	default: revision = 255; break;
-    }
-    printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
-
-    if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS)))
-    {
-	printk ("scsi%d: Disabling sync working and disconnect/reselect\n",
-							host->host_no);
-	hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS);
-    }
-
-    /*
-     * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor,
-     * on 800 series chips, it allows for a totem-pole IRQ driver.
-     * NOTE saved_dcntl currently overwritten in init function.
-     * The value read here may be garbage anyway, MVME16x board at least
-     * does not initialise chip if kernel arrived via tftp.
-     */
-
-    hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG);
-
-    /*
-     * DMODE controls DMA burst length, and on 700 series chips,
-     * 286 mode and bus width  
-     * NOTE:  On MVME16x, chip may have been reset, so this could be a
-     * power-on/reset default value.
-     */
-    hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode);
-
-    /* 
-     * Now that burst length and enabled/disabled status is known, 
-     * clue the user in on it.  
-     */
-   
-    ccf = clock_to_ccf_710 (expected_clock);
-
-    for (i = 0; i < 16; ++i) 
-	hostdata->cmd_allocated[i] = 0;
-
-    if (hostdata->init_save_regs)
-    	hostdata->init_save_regs (host);
-    if (hostdata->init_fixup)
-    	hostdata->init_fixup (host);
-
-    if (!the_template) {
-	the_template = host->hostt;
-	first_host = host;
-    }
-
-    /* 
-     * Linux SCSI drivers have always been plagued with initialization 
-     * problems - some didn't work with the BIOS disabled since they expected
-     * initialization from it, some didn't work when the networking code
-     * was enabled and registers got scrambled, etc.
-     *
-     * To avoid problems like this, in the future, we will do a soft 
-     * reset on the SCSI chip, taking it back to a sane state.
-     */
-
-    hostdata->soft_reset (host);
-
-#if 1
-    hostdata->debug_count_limit = -1;
-#else
-    hostdata->debug_count_limit = 1;
-#endif
-    hostdata->intrs = -1;
-    hostdata->resets = -1;
-    memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message, 
-	sizeof (hostdata->synchronous_want));
-
-    NCR53c7x0_driver_init (host);
-
-    if (request_irq(host->irq, NCR53c7x0_intr, IRQF_SHARED, "53c7xx", host))
-    {
-	printk("scsi%d : IRQ%d not free, detaching\n",
-		host->host_no, host->irq);
-	goto err_unregister;
-    } 
-
-    if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
-        (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
-    	/* XXX Should disable interrupts, etc. here */
-	goto err_free_irq;
-    } else {
-	if (host->io_port)  {
-	    host->n_io_port = 128;
-	    if (!request_region (host->io_port, host->n_io_port, "ncr53c7xx"))
-		goto err_free_irq;
-	}
-    }
-    
-    if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) {
-	printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no);
-	hard_reset (host);
-    }
-    return 0;
-
- err_free_irq:
-    free_irq(host->irq,  NCR53c7x0_intr);
- err_unregister:
-    scsi_unregister(host);
-    return -1;
-}
-
-/* 
- * Function : int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
- *	unsigned long base, int io_port, int irq, int dma, long long options,
- *	int clock);
- *
- * Purpose : initializes a NCR53c7,8x0 based on base addresses,
- *	IRQ, and DMA channel.	
- *	
- * Inputs : tpnt - Template for this SCSI adapter, board - board level
- *	product, chip - 710
- * 
- * Returns : 0 on success, -1 on failure.
- *
- */
-
-int 
-ncr53c7xx_init (struct scsi_host_template *tpnt, int board, int chip,
-    unsigned long base, int io_port, int irq, int dma, 
-    long long options, int clock)
-{
-    struct Scsi_Host *instance;
-    struct NCR53c7x0_hostdata *hostdata;
-    char chip_str[80];
-    int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0,
-	schedule_size = 0, ok = 0;
-    void *tmp;
-    unsigned long page;
-
-    switch (chip) {
-    case 710:
-    case 770:
-	schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */;
-	script_len = NCR53c7xx_script_len;
-    	dsa_len = NCR53c7xx_dsa_len;
-    	options |= OPTION_INTFLY;
-    	sprintf (chip_str, "NCR53c%d", chip);
-    	break;
-    default:
-    	printk("scsi-ncr53c7xx : unsupported SCSI chip %d\n", chip);
-    	return -1;
-    }
-
-    printk("scsi-ncr53c7xx : %s at memory 0x%lx, io 0x%x, irq %d",
-    	chip_str, base, io_port, irq);
-    if (dma == DMA_NONE)
-    	printk("\n");
-    else 
-    	printk(", dma %d\n", dma);
-
-    if (options & OPTION_DEBUG_PROBE_ONLY) {
-    	printk ("scsi-ncr53c7xx : probe only enabled, aborting initialization\n");
-    	return -1;
-    }
-
-    max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len +
-    	/* Size of dynamic part of command structure : */
-	2 * /* Worst case : we don't know if we need DATA IN or DATA out */
-		( 2 * /* Current instructions per scatter/gather segment */ 
-        	  tpnt->sg_tablesize + 
-                  3 /* Current startup / termination required per phase */
-		) *
-	8 /* Each instruction is eight bytes */;
-
-    /* Allocate fixed part of hostdata, dynamic part to hold appropriate
-       SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure.
-
-       We need a NCR53c7x0_cmd structure for scan_scsis() when we are 
-       not loaded as a module, and when we're loaded as a module, we 
-       can't use a non-dynamically allocated structure because modules
-       are vmalloc()'d, which can allow structures to cross page 
-       boundaries and breaks our physical/virtual address assumptions
-       for DMA.
-
-       So, we stick it past the end of our hostdata structure.
-
-       ASSUMPTION : 
-       	 Regardless of how many simultaneous SCSI commands we allow,
-	 the probe code only executes a _single_ instruction at a time,
-	 so we only need one here, and don't need to allocate NCR53c7x0_cmd
-	 structures for each target until we are no longer in scan_scsis
-	 and kmalloc() has become functional (memory_init() happens 
-	 after all device driver initialization).
-    */
-
-    size = sizeof(struct NCR53c7x0_hostdata) + script_len + 
-    /* Note that alignment will be guaranteed, since we put the command
-       allocated at probe time after the fixed-up SCSI script, which 
-       consists of 32 bit words, aligned on a 32 bit boundary.  But
-       on a 64bit machine we need 8 byte alignment for hostdata->free, so
-       we add in another 4 bytes to take care of potential misalignment
-       */
-	(sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size;
-
-    page = __get_free_pages(GFP_ATOMIC,1);
-    if(page==0)
-    {
-    	printk(KERN_ERR "53c7xx: out of memory.\n");
-    	return -ENOMEM;
-    }
-#ifdef FORCE_DSA_ALIGNMENT
-    /*
-     * 53c710 rev.0 doesn't have an add-with-carry instruction.
-     * Ensure we allocate enough memory to force DSA alignment.
-    */
-    size += 256;
-#endif
-    /* Size should be < 8K, so we can fit it in two pages. */
-    if (size > 8192) {
-      printk(KERN_ERR "53c7xx: hostdata > 8K\n");
-      return -1;
-    }
-
-    instance = scsi_register (tpnt, 4);
-    if (!instance)
-    {
-        free_page(page);
-	return -1;
-    }
-    instance->hostdata[0] = page;
-    memset((void *)instance->hostdata[0], 0, 8192);
-    cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192);
-    cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192);
-    kernel_set_cachemode((void *)instance->hostdata[0], 8192, IOMAP_NOCACHE_SER);
-
-    /* FIXME : if we ever support an ISA NCR53c7xx based board, we
-       need to check if the chip is running in a 16 bit mode, and if so 
-       unregister it if it is past the 16M (0x1000000) mark */
-
-    hostdata = (struct NCR53c7x0_hostdata *)instance->hostdata[0];
-    hostdata->size = size;
-    hostdata->script_count = script_len / sizeof(u32);
-    hostdata->board = board;
-    hostdata->chip = chip;
-
-    /*
-     * Being memory mapped is more desirable, since 
-     *
-     * - Memory accesses may be faster.
-     *
-     * - The destination and source address spaces are the same for 
-     *	 all instructions, meaning we don't have to twiddle dmode or 
-     *	 any other registers.
-     *
-     * So, we try for memory mapped, and if we don't get it,
-     * we go for port mapped, and that failing we tell the user
-     * it can't work.
-     */
-
-    if (base) {
-	instance->base = base;
-	/* Check for forced I/O mapping */
-    	if (!(options & OPTION_IO_MAPPED)) {
-	    options |= OPTION_MEMORY_MAPPED;
-	    ok = 1;
-	}
-    } else {
-	options &= ~OPTION_MEMORY_MAPPED;
-    }
-
-    if (io_port) {
-	instance->io_port = io_port;
-	options |= OPTION_IO_MAPPED;
-	ok = 1;
-    } else {
-	options &= ~OPTION_IO_MAPPED;
-    }
-
-    if (!ok) {
-	printk ("scsi%d : not initializing, no I/O or memory mapping known \n",
-	    instance->host_no);
-	scsi_unregister (instance);
-	return -1;
-    }
-    instance->irq = irq;
-    instance->dma_channel = dma;
-
-    hostdata->options = options;
-    hostdata->dsa_len = dsa_len;
-    hostdata->max_cmd_size = max_cmd_size;
-    hostdata->num_cmds = 1;
-    hostdata->scsi_clock = clock;
-    /* Initialize single command */
-    tmp = (hostdata->script + hostdata->script_count);
-#ifdef FORCE_DSA_ALIGNMENT
-    {
-	void *t = ROUNDUP(tmp, void *);
-	if (((u32)t & 0xff) > CmdPageStart)
-	    t = (void *)((u32)t + 255);
-	t = (void *)(((u32)t & ~0xff) + CmdPageStart);
-        hostdata->free = t;
-#if 0
-	printk ("scsi: Registered size increased by 256 to %d\n", size);
-	printk ("scsi: CmdPageStart = 0x%02x\n", CmdPageStart);
-	printk ("scsi: tmp = 0x%08x, hostdata->free set to 0x%08x\n",
-			(u32)tmp, (u32)t);
-#endif
-    }
-#else
-    hostdata->free = ROUNDUP(tmp, void *);
-#endif
-    hostdata->free->real = tmp;
-    hostdata->free->size = max_cmd_size;
-    hostdata->free->free = NULL;
-    hostdata->free->next = NULL;
-    hostdata->extra_allocate = 0;
-
-    /* Allocate command start code space */
-    hostdata->schedule = (chip == 700 || chip == 70066) ?
-	NULL : (u32 *) ((char *)hostdata->free + max_cmd_size);
-
-/* 
- * For diagnostic purposes, we don't really care how fast things blaze.
- * For profiling, we want to access the 800ns resolution system clock,
- * using a 'C' call on the host processor.
- *
- * Therefore, there's no need for the NCR chip to directly manipulate
- * this data, and we should put it wherever is most convenient for 
- * Linux.
- */
-    if (track_events) 
-	hostdata->events = (struct NCR53c7x0_event *) (track_events ? 
-	    vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL);
-    else
-	hostdata->events = NULL;
-
-    if (hostdata->events) {
-	memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) *
-	    track_events);	
-	hostdata->event_size = track_events;
-	hostdata->event_index = 0;
-    } else 
-	hostdata->event_size = 0;
-
-    return NCR53c7x0_init(instance);
-}
-
-
-/* 
- * Function : static void NCR53c7x0_init_fixup (struct Scsi_Host *host)
- *
- * Purpose :  copy and fixup the SCSI SCRIPTS(tm) code for this device.
- *
- * Inputs : host - pointer to this host adapter's structure
- *
- */
-
-static void 
-NCR53c7x0_init_fixup (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned char tmp;
-    int i, ncr_to_memory, memory_to_ncr;
-    u32 base;
-    NCR53c7x0_local_setup(host);
-
-
-    /* XXX - NOTE : this code MUST be made endian aware */
-    /*  Copy code into buffer that was allocated at detection time.  */
-    memcpy ((void *) hostdata->script, (void *) SCRIPT, 
-	sizeof(SCRIPT));
-    /* Fixup labels */
-    for (i = 0; i < PATCHES; ++i) 
-	hostdata->script[LABELPATCHES[i]] += 
-    	    virt_to_bus(hostdata->script);
-    /* Fixup addresses of constants that used to be EXTERNAL */
-
-    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_abort, 
-    	virt_to_bus(&(hostdata->NCR53c7xx_msg_abort)));
-    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_reject, 
-    	virt_to_bus(&(hostdata->NCR53c7xx_msg_reject)));
-    patch_abs_32 (hostdata->script, 0, NCR53c7xx_zero, 
-    	virt_to_bus(&(hostdata->NCR53c7xx_zero)));
-    patch_abs_32 (hostdata->script, 0, NCR53c7xx_sink, 
-    	virt_to_bus(&(hostdata->NCR53c7xx_sink)));
-    patch_abs_32 (hostdata->script, 0, NOP_insn,
-	virt_to_bus(&(hostdata->NOP_insn)));
-    patch_abs_32 (hostdata->script, 0, schedule,
-	virt_to_bus((void *) hostdata->schedule));
-
-    /* Fixup references to external variables: */
-    for (i = 0; i < EXTERNAL_PATCHES_LEN; ++i)
-       hostdata->script[EXTERNAL_PATCHES[i].offset] +=
-         virt_to_bus(EXTERNAL_PATCHES[i].address);
-
-    /* 
-     * Fixup absolutes set at boot-time.
-     * 
-     * All non-code absolute variables suffixed with "dsa_" and "int_"
-     * are constants, and need no fixup provided the assembler has done 
-     * it for us (I don't know what the "real" NCR assembler does in 
-     * this case, my assembler does the right magic).
-     */
-
-    patch_abs_rwri_data (hostdata->script, 0, dsa_save_data_pointer, 
-    	Ent_dsa_code_save_data_pointer - Ent_dsa_zero);
-    patch_abs_rwri_data (hostdata->script, 0, dsa_restore_pointers,
-    	Ent_dsa_code_restore_pointers - Ent_dsa_zero);
-    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect,
-    	Ent_dsa_code_check_reselect - Ent_dsa_zero);
-
-    /*
-     * Just for the hell of it, preserve the settings of 
-     * Burst Length and Enable Read Line bits from the DMODE 
-     * register.  Make sure SCRIPTS start automagically.
-     */
-
-#if defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
-    /* We know better what we want than 16xBug does! */
-    tmp = DMODE_10_BL_8 | DMODE_10_FC2;
-#else
-    tmp = NCR53c7x0_read8(DMODE_REG_10);
-    tmp &= (DMODE_BL_MASK | DMODE_10_FC2 | DMODE_10_FC1 | DMODE_710_PD |
-								DMODE_710_UO);
-#endif
-
-    if (!(hostdata->options & OPTION_MEMORY_MAPPED)) {
-    	base = (u32) host->io_port;
-    	memory_to_ncr = tmp|DMODE_800_DIOM;
-    	ncr_to_memory = tmp|DMODE_800_SIOM;
-    } else {
-    	base = virt_to_bus((void *)host->base);
-	memory_to_ncr = ncr_to_memory = tmp;
-    }
-
-    /* SCRATCHB_REG_10 == SCRATCHA_REG_800, as it happens */
-    patch_abs_32 (hostdata->script, 0, addr_scratch, base + SCRATCHA_REG_800);
-    patch_abs_32 (hostdata->script, 0, addr_temp, base + TEMP_REG);
-    patch_abs_32 (hostdata->script, 0, addr_dsa, base + DSA_REG);
-
-    /*
-     * I needed some variables in the script to be accessible to 
-     * both the NCR chip and the host processor. For these variables,
-     * I made the arbitrary decision to store them directly in the 
-     * hostdata structure rather than in the RELATIVE area of the 
-     * SCRIPTS.
-     */
-    
-
-    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp);
-    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr);
-    patch_abs_rwri_data (hostdata->script, 0, dmode_ncr_to_memory, ncr_to_memory);
-
-    patch_abs_32 (hostdata->script, 0, msg_buf, 
-	virt_to_bus((void *)&(hostdata->msg_buf)));
-    patch_abs_32 (hostdata->script, 0, reconnect_dsa_head, 
-    	virt_to_bus((void *)&(hostdata->reconnect_dsa_head)));
-    patch_abs_32 (hostdata->script, 0, addr_reconnect_dsa_head, 
-	virt_to_bus((void *)&(hostdata->addr_reconnect_dsa_head)));
-    patch_abs_32 (hostdata->script, 0, reselected_identify, 
-    	virt_to_bus((void *)&(hostdata->reselected_identify)));
-/* reselected_tag is currently unused */
-#if 0
-    patch_abs_32 (hostdata->script, 0, reselected_tag, 
-    	virt_to_bus((void *)&(hostdata->reselected_tag)));
-#endif
-
-    patch_abs_32 (hostdata->script, 0, test_dest, 
-	virt_to_bus((void*)&hostdata->test_dest));
-    patch_abs_32 (hostdata->script, 0, test_src, 
-	virt_to_bus(&hostdata->test_source));
-    patch_abs_32 (hostdata->script, 0, saved_dsa,
-	virt_to_bus((void *)&hostdata->saved2_dsa));
-    patch_abs_32 (hostdata->script, 0, emulfly,
-	virt_to_bus((void *)&hostdata->emulated_intfly));
-
-    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, 
-	(unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero));
-
-/* These are for event logging; the ncr_event enum contains the 
-   actual interrupt numbers. */
-#ifdef A_int_EVENT_SELECT
-   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT, (u32) EVENT_SELECT);
-#endif
-#ifdef A_int_EVENT_DISCONNECT
-   patch_abs_32 (hostdata->script, 0, int_EVENT_DISCONNECT, (u32) EVENT_DISCONNECT);
-#endif
-#ifdef A_int_EVENT_RESELECT
-   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT, (u32) EVENT_RESELECT);
-#endif
-#ifdef A_int_EVENT_COMPLETE
-   patch_abs_32 (hostdata->script, 0, int_EVENT_COMPLETE, (u32) EVENT_COMPLETE);
-#endif
-#ifdef A_int_EVENT_IDLE
-   patch_abs_32 (hostdata->script, 0, int_EVENT_IDLE, (u32) EVENT_IDLE);
-#endif
-#ifdef A_int_EVENT_SELECT_FAILED
-   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT_FAILED, 
-	(u32) EVENT_SELECT_FAILED);
-#endif
-#ifdef A_int_EVENT_BEFORE_SELECT
-   patch_abs_32 (hostdata->script, 0, int_EVENT_BEFORE_SELECT,
-	(u32) EVENT_BEFORE_SELECT);
-#endif
-#ifdef A_int_EVENT_RESELECT_FAILED
-   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT_FAILED, 
-	(u32) EVENT_RESELECT_FAILED);
-#endif
-
-    /*
-     * Make sure the NCR and Linux code agree on the location of 
-     * certain fields.
-     */
-
-    hostdata->E_accept_message = Ent_accept_message;
-    hostdata->E_command_complete = Ent_command_complete;		
-    hostdata->E_cmdout_cmdout = Ent_cmdout_cmdout;
-    hostdata->E_data_transfer = Ent_data_transfer;
-    hostdata->E_debug_break = Ent_debug_break;	
-    hostdata->E_dsa_code_template = Ent_dsa_code_template;
-    hostdata->E_dsa_code_template_end = Ent_dsa_code_template_end;
-    hostdata->E_end_data_transfer = Ent_end_data_transfer;
-    hostdata->E_initiator_abort = Ent_initiator_abort;
-    hostdata->E_msg_in = Ent_msg_in;
-    hostdata->E_other_transfer = Ent_other_transfer;
-    hostdata->E_other_in = Ent_other_in;
-    hostdata->E_other_out = Ent_other_out;
-    hostdata->E_reject_message = Ent_reject_message;
-    hostdata->E_respond_message = Ent_respond_message;
-    hostdata->E_select = Ent_select;
-    hostdata->E_select_msgout = Ent_select_msgout;
-    hostdata->E_target_abort = Ent_target_abort;
-#ifdef Ent_test_0
-    hostdata->E_test_0 = Ent_test_0;
-#endif
-    hostdata->E_test_1 = Ent_test_1;
-    hostdata->E_test_2 = Ent_test_2;
-#ifdef Ent_test_3
-    hostdata->E_test_3 = Ent_test_3;
-#endif
-    hostdata->E_wait_reselect = Ent_wait_reselect;
-    hostdata->E_dsa_code_begin = Ent_dsa_code_begin;
-
-    hostdata->dsa_cmdout = A_dsa_cmdout;
-    hostdata->dsa_cmnd = A_dsa_cmnd;
-    hostdata->dsa_datain = A_dsa_datain;
-    hostdata->dsa_dataout = A_dsa_dataout;
-    hostdata->dsa_end = A_dsa_end;			
-    hostdata->dsa_msgin = A_dsa_msgin;
-    hostdata->dsa_msgout = A_dsa_msgout;
-    hostdata->dsa_msgout_other = A_dsa_msgout_other;
-    hostdata->dsa_next = A_dsa_next;
-    hostdata->dsa_select = A_dsa_select;
-    hostdata->dsa_start = Ent_dsa_code_template - Ent_dsa_zero;
-    hostdata->dsa_status = A_dsa_status;
-    hostdata->dsa_jump_dest = Ent_dsa_code_fix_jump - Ent_dsa_zero + 
-	8 /* destination operand */;
-
-    /* sanity check */
-    if (A_dsa_fields_start != Ent_dsa_code_template_end - 
-    	Ent_dsa_zero) 
-    	printk("scsi%d : NCR dsa_fields start is %d not %d\n",
-    	    host->host_no, A_dsa_fields_start, Ent_dsa_code_template_end - 
-    	    Ent_dsa_zero);
-
-    printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no,
-	virt_to_bus(hostdata->script), hostdata->script);
-}
-
-/*
- * Function : static int NCR53c7xx_run_tests (struct Scsi_Host *host)
- *
- * Purpose : run various verification tests on the NCR chip, 
- *	including interrupt generation, and proper bus mastering
- * 	operation.
- * 
- * Inputs : host - a properly initialized Scsi_Host structure
- *
- * Preconditions : the NCR chip must be in a halted state.
- *
- * Returns : 0 if all tests were successful, -1 on error.
- * 
- */
-
-static int 
-NCR53c7xx_run_tests (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned long timeout;
-    u32 start;
-    int failed, i;
-    unsigned long flags;
-    NCR53c7x0_local_setup(host);
-
-    /* The NCR chip _must_ be idle to run the test scripts */
-
-    local_irq_save(flags);
-    if (!hostdata->idle) {
-	printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
-	local_irq_restore(flags);
-	return -1;
-    }
-
-    /* 
-     * Check for functional interrupts, this could work as an
-     * autoprobe routine.
-     */
-
-    if ((hostdata->options & OPTION_DEBUG_TEST1) && 
-	    hostdata->state != STATE_DISABLED) {
-	hostdata->idle = 0;
-	hostdata->test_running = 1;
-	hostdata->test_completed = -1;
-	hostdata->test_dest = 0;
-	hostdata->test_source = 0xdeadbeef;
-	start = virt_to_bus (hostdata->script) + hostdata->E_test_1;
-    	hostdata->state = STATE_RUNNING;
-	printk ("scsi%d : test 1", host->host_no);
-	NCR53c7x0_write32 (DSP_REG, start);
-	if (hostdata->options & OPTION_DEBUG_TRACE)
-	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM |
-						DCNTL_STD);
-	printk (" started\n");
-	local_irq_restore(flags);
-
-	/* 
-	 * This is currently a .5 second timeout, since (in theory) no slow 
-	 * board will take that long.  In practice, we've seen one 
-	 * pentium which occassionally fails with this, but works with 
-	 * 10 times as much?
-	 */
-
-	timeout = jiffies + 5 * HZ / 10;
-	while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
-		barrier();
-
-	failed = 1;
-	if (hostdata->test_completed == -1)
-	    printk ("scsi%d : driver test 1 timed out%s\n",host->host_no ,
-		(hostdata->test_dest == 0xdeadbeef) ? 
-		    " due to lost interrupt.\n"
-		    "         Please verify that the correct IRQ is being used for your board,\n"
-		    : "");
-	else if (hostdata->test_completed != 1) 
-	    printk ("scsi%d : test 1 bad interrupt value (%d)\n", 
-		host->host_no, hostdata->test_completed);
-	else 
-	    failed = (hostdata->test_dest != 0xdeadbeef);
-
-	if (hostdata->test_dest != 0xdeadbeef) {
-	    printk ("scsi%d : driver test 1 read 0x%x instead of 0xdeadbeef indicating a\n"
-                    "         probable cache invalidation problem.  Please configure caching\n"
-		    "         as write-through or disabled\n",
-		host->host_no, hostdata->test_dest);
-	}
-
-	if (failed) {
-	    printk ("scsi%d : DSP = 0x%p (script at 0x%p, start at 0x%x)\n",
-		host->host_no, bus_to_virt(NCR53c7x0_read32(DSP_REG)),
-		hostdata->script, start);
-	    printk ("scsi%d : DSPS = 0x%x\n", host->host_no,
-		NCR53c7x0_read32(DSPS_REG));
-	    local_irq_restore(flags);
-	    return -1;
-	}
-    	hostdata->test_running = 0;
-    }
-
-    if ((hostdata->options & OPTION_DEBUG_TEST2) && 
-	hostdata->state != STATE_DISABLED) {
-	u32 dsa[48];
-    	unsigned char identify = IDENTIFY(0, 0);
-	unsigned char cmd[6];
-	unsigned char data[36];
-    	unsigned char status = 0xff;
-    	unsigned char msg = 0xff;
-
-    	cmd[0] = INQUIRY;
-    	cmd[1] = cmd[2] = cmd[3] = cmd[5] = 0;
-    	cmd[4] = sizeof(data); 
-
-    	dsa[2] = 1;
-    	dsa[3] = virt_to_bus(&identify);
-    	dsa[4] = 6;
-    	dsa[5] = virt_to_bus(&cmd);
-    	dsa[6] = sizeof(data);
-    	dsa[7] = virt_to_bus(&data);
-    	dsa[8] = 1;
-    	dsa[9] = virt_to_bus(&status);
-    	dsa[10] = 1;
-    	dsa[11] = virt_to_bus(&msg);
-
-	for (i = 0; i < 6; ++i) {
-#ifdef VALID_IDS
-	    if (!hostdata->valid_ids[i])
-		continue;
-#endif
-	    local_irq_disable();
-	    if (!hostdata->idle) {
-		printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
-		local_irq_restore(flags);
-		return -1;
-	    }
-
-	    /* 710: bit mapped scsi ID, async   */
-            dsa[0] = (1 << i) << 16;
-	    hostdata->idle = 0;
-	    hostdata->test_running = 2;
-	    hostdata->test_completed = -1;
-	    start = virt_to_bus(hostdata->script) + hostdata->E_test_2;
-	    hostdata->state = STATE_RUNNING;
-	    NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa));
-	    NCR53c7x0_write32 (DSP_REG, start);
-	    if (hostdata->options & OPTION_DEBUG_TRACE)
-	        NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
-				DCNTL_SSM | DCNTL_STD);
-	    local_irq_restore(flags);
-
-	    timeout = jiffies + 5 * HZ;	/* arbitrary */
-	    while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
-	    	barrier();
-
-	    NCR53c7x0_write32 (DSA_REG, 0);
-
-	    if (hostdata->test_completed == 2) {
-		data[35] = 0;
-		printk ("scsi%d : test 2 INQUIRY to target %d, lun 0 : %s\n",
-		    host->host_no, i, data + 8);
-		printk ("scsi%d : status ", host->host_no);
-		scsi_print_status (status);
-		printk ("\nscsi%d : message ", host->host_no);
-		spi_print_msg(&msg);
-		printk ("\n");
-	    } else if (hostdata->test_completed == 3) {
-		printk("scsi%d : test 2 no connection with target %d\n",
-		    host->host_no, i);
-		if (!hostdata->idle) {
-		    printk("scsi%d : not idle\n", host->host_no);
-		    local_irq_restore(flags);
-		    return -1;
-		}
-	    } else if (hostdata->test_completed == -1) {
-		printk ("scsi%d : test 2 timed out\n", host->host_no);
-		local_irq_restore(flags);
-		return -1;
-	    } 
-	    hostdata->test_running = 0;
-	}
-    }
-
-    local_irq_restore(flags);
-    return 0;
-}
-
-/*
- * Function : static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : copy the NCR53c8xx dsa structure into cmd's dsa buffer,
- * 	performing all necessary relocation.
- *
- * Inputs : cmd, a NCR53c7x0_cmd structure with a dsa area large
- *	enough to hold the NCR53c8xx dsa.
- */
-
-static void 
-NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) {
-    Scsi_Cmnd *c = cmd->cmd;
-    struct Scsi_Host *host = c->device->host;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata[0];
-    int i;
-
-    memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4),
-    	hostdata->E_dsa_code_template_end - hostdata->E_dsa_code_template);
-
-    /* 
-     * Note : within the NCR 'C' code, dsa points to the _start_
-     * of the DSA structure, and _not_ the offset of dsa_zero within
-     * that structure used to facilitate shorter signed offsets
-     * for the 8 bit ALU.
-     * 
-     * The implications of this are that 
-     * 
-     * - 32 bit A_dsa_* absolute values require an additional 
-     * 	 dsa_zero added to their value to be correct, since they are 
-     *   relative to dsa_zero which is in essentially a separate
-     *   space from the code symbols.
-     *
-     * - All other symbols require no special treatment.
-     */
-
-    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_lun, c->device->lun);
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-	dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr));
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero -
-	Ent_dsa_code_template + A_dsa_next);
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), 
-    	dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->device->id].script));
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), 
-    	dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->device->id].sscf_710));
-    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	    dsa_temp_target, 1 << c->device->id);
-    /* XXX - new pointer stuff */
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer));
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_addr_saved_residual, virt_to_bus(&cmd->saved_residual));
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_addr_residual, virt_to_bus(&cmd->residual));
-
-    /*  XXX - new start stuff */
-
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-	dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr));
-}
-
-/* 
- * Function : run_process_issue_queue (void)
- * 
- * Purpose : insure that the coroutine is running and will process our 
- * 	request.  process_issue_queue_running is checked/set here (in an 
- *	inline function) rather than in process_issue_queue itself to reduce 
- * 	the chances of stack overflow.
- *
- */
-
-static volatile int process_issue_queue_running = 0;
-
-static __inline__ void 
-run_process_issue_queue(void) {
-    unsigned long flags;
-    local_irq_save(flags);
-    if (!process_issue_queue_running) {
-	process_issue_queue_running = 1;
-        process_issue_queue(flags);
-	/* 
-         * process_issue_queue_running is cleared in process_issue_queue 
-	 * once it can't do more work, and process_issue_queue exits with 
-	 * interrupts disabled.
-	 */
-    }
-    local_irq_restore(flags);
-}
-
-/*
- * Function : static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int
- *	result)
- *
- * Purpose : mark SCSI command as finished, OR'ing the host portion 
- *	of the result word into the result field of the corresponding
- *	Scsi_Cmnd structure, and removing it from the internal queues.
- *
- * Inputs : cmd - command, result - entire result field
- *
- * Preconditions : the 	NCR chip should be in a halted state when 
- *	abnormal_finished is run, since it modifies structures which
- *	the NCR expects to have exclusive access to.
- */
-
-static void 
-abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
-    Scsi_Cmnd *c = cmd->cmd;
-    struct Scsi_Host *host = c->device->host;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata[0];
-    unsigned long flags;
-    int left, found;
-    volatile struct NCR53c7x0_cmd * linux_search;
-    volatile struct NCR53c7x0_cmd * volatile *linux_prev;
-    volatile u32 *ncr_prev, *ncrcurrent, ncr_search;
-
-#if 0
-    printk ("scsi%d: abnormal finished\n", host->host_no);
-#endif
-
-    local_irq_save(flags);
-    found = 0;
-    /* 
-     * Traverse the NCR issue array until we find a match or run out 
-     * of instructions.  Instructions in the NCR issue array are 
-     * either JUMP or NOP instructions, which are 2 words in length.
-     */
-
-
-    for (found = 0, left = host->can_queue, ncrcurrent = hostdata->schedule; 
-	left > 0; --left, ncrcurrent += 2)
-    {
-	if (issue_to_cmd (host, hostdata, (u32 *) ncrcurrent) == cmd) 
-	{
-	    ncrcurrent[0] = hostdata->NOP_insn;
-	    ncrcurrent[1] = 0xdeadbeef;
-	    ++found;
-	    break;
-	}
-    }
-	
-    /* 
-     * Traverse the NCR reconnect list of DSA structures until we find 
-     * a pointer to this dsa or have found too many command structures.  
-     * We let prev point at the next field of the previous element or 
-     * head of the list, so we don't do anything different for removing 
-     * the head element.  
-     */
-
-    for (left = host->can_queue,
-	    ncr_search = hostdata->reconnect_dsa_head, 
-	    ncr_prev = &hostdata->reconnect_dsa_head;
-	left >= 0 && ncr_search && 
-	    ((char*)bus_to_virt(ncr_search) + hostdata->dsa_start) 
-		!= (char *) cmd->dsa;
-	ncr_prev = (u32*) ((char*)bus_to_virt(ncr_search) + 
-	    hostdata->dsa_next), ncr_search = *ncr_prev, --left);
-
-    if (left < 0) 
-	printk("scsi%d: loop detected in ncr reconncect list\n",
-	    host->host_no);
-    else if (ncr_search) {
-	if (found)
-	    printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n",
-		host->host_no, c->pid);
-	else {
-	    volatile u32 * next = (u32 *) 
-	    	((char *)bus_to_virt(ncr_search) + hostdata->dsa_next);
-	    *ncr_prev = *next;
-/* If we're at the tail end of the issue queue, update that pointer too. */
-	    found = 1;
-	}
-    }
-
-    /*
-     * Traverse the host running list until we find this command or discover
-     * we have too many elements, pointing linux_prev at the next field of the 
-     * linux_previous element or head of the list, search at this element.
-     */
-
-    for (left = host->can_queue, linux_search = hostdata->running_list, 
-	    linux_prev = &hostdata->running_list;
-	left >= 0 && linux_search && linux_search != cmd;
-	linux_prev = &(linux_search->next), 
-	    linux_search = linux_search->next, --left);
-    
-    if (left < 0) 
-	printk ("scsi%d: loop detected in host running list for scsi pid %ld\n",
-	    host->host_no, c->pid);
-    else if (linux_search) {
-	*linux_prev = linux_search->next;
-	--hostdata->busy[c->device->id][c->device->lun];
-    }
-
-    /* Return the NCR command structure to the free list */
-    cmd->next = hostdata->free;
-    hostdata->free = cmd;
-    c->host_scribble = NULL;
-
-    /* And return */
-    c->result = result;
-    c->scsi_done(c);
-
-    local_irq_restore(flags);
-    run_process_issue_queue();
-}
-
-/* 
- * Function : static void intr_break (struct Scsi_Host *host,
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose :  Handler for breakpoint interrupts from a SCSI script
- *
- * Inputs : host - pointer to this host adapter's structure,
- * 	cmd - pointer to the command (if any) dsa was pointing 
- * 	to.
- *
- */
-
-static void 
-intr_break (struct Scsi_Host *host, struct 
-    NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_break *bp;
-#if 0
-    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
-#endif
-    u32 *dsp;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];		
-    unsigned long flags;
-    NCR53c7x0_local_setup(host);
-
-    /*
-     * Find the break point corresponding to this address, and 
-     * dump the appropriate debugging information to standard 
-     * output.  
-     */
-    local_irq_save(flags);
-    dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
-    for (bp = hostdata->breakpoints; bp && bp->address != dsp; 
-    	bp = bp->next);
-    if (!bp) 
-    	panic("scsi%d : break point interrupt from %p with no breakpoint!",
-    	    host->host_no, dsp);
-
-    /*
-     * Configure the NCR chip for manual start mode, so that we can 
-     * point the DSP register at the instruction that follows the 
-     * INT int_debug_break instruction.
-     */
-
-    NCR53c7x0_write8 (hostdata->dmode, 
-	NCR53c7x0_read8(hostdata->dmode)|DMODE_MAN);
-
-    /*
-     * And update the DSP register, using the size of the old 
-     * instruction in bytes.
-     */
-
-    local_irq_restore(flags);
-}
-/*
- * Function : static void print_synchronous (const char *prefix, 
- *	const unsigned char *msg)
- * 
- * Purpose : print a pretty, user and machine parsable representation
- *	of a SDTR message, including the "real" parameters, data
- *	clock so we can tell transfer rate at a glance.
- *
- * Inputs ; prefix - text to prepend, msg - SDTR message (5 bytes)
- */
-
-static void
-print_synchronous (const char *prefix, const unsigned char *msg) {
-    if (msg[4]) {
-	int Hz = 1000000000 / (msg[3] * 4);
-	int integer = Hz / 1000000;
-	int fraction = (Hz - (integer * 1000000)) / 10000;
-	printk ("%speriod %dns offset %d %d.%02dMHz %s SCSI%s\n",
-	    prefix, (int) msg[3] * 4, (int) msg[4], integer, fraction,
-	    (((msg[3] * 4) < 200) ? "FAST" : "synchronous"),
-	    (((msg[3] * 4) < 200) ? "-II" : ""));
-    } else 
-	printk ("%sasynchronous SCSI\n", prefix);
-}
-
-/*
- * Function : static void set_synchronous (struct Scsi_Host *host, 
- *	 	int target, int sxfer, int scntl3, int now_connected)
- *
- * Purpose : reprogram transfers between the selected SCSI initiator and 
- *	target with the given register values; in the indirect
- *	select operand, reselection script, and chip registers.
- *
- * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id,
- *	sxfer and scntl3 - NCR registers. now_connected - if non-zero, 
- *	we should reprogram the registers now too.
- *
- *      NOTE:  For 53c710, scntl3 is actually used for SCF bits from
- *	SBCL, as we don't have a SCNTL3.
- */
-
-static void
-set_synchronous (struct Scsi_Host *host, int target, int sxfer, int scntl3,
-    int now_connected) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) 
-	host->hostdata[0];
-    u32 *script;
-    NCR53c7x0_local_setup(host);
-
-    /* These are eight bit registers */
-    sxfer &= 0xff;
-    scntl3 &= 0xff;
-
-    hostdata->sync[target].sxfer_sanity = sxfer;
-    hostdata->sync[target].scntl3_sanity = scntl3;
-
-/* 
- * HARD CODED : synchronous script is EIGHT words long.  This 
- * must agree with 53c7.8xx.h
- */
-
-    if ((hostdata->chip != 700) && (hostdata->chip != 70066)) {
-	hostdata->sync[target].select_indirect = (1 << target) << 16 |
-		(sxfer << 8);
-	hostdata->sync[target].sscf_710 = scntl3;
-
-	script = (u32 *) hostdata->sync[target].script;
-
-	/* XXX - add NCR53c7x0 code to reprogram SCF bits if we want to */
-	script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY |
-		DCMD_RWRI_OP_MOVE) << 24) |
-		(SBCL_REG << 16) | (scntl3 << 8);
-	script[1] = 0;
-	script += 2;
-
-	script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY |
-	    DCMD_RWRI_OP_MOVE) << 24) |
-		(SXFER_REG << 16) | (sxfer << 8);
-	script[1] = 0;
-	script += 2;
-
-#ifdef DEBUG_SYNC_INTR
-	if (hostdata->options & OPTION_DEBUG_DISCONNECT) {
-	    script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_INT) << 24) | DBC_TCI_TRUE;
-	    script[1] = DEBUG_SYNC_INTR;
-	    script += 2;
-	}
-#endif
-
-	script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_RETURN) << 24) | DBC_TCI_TRUE;
-	script[1] = 0;
-	script += 2;
-    }
-
-    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) 
-	printk ("scsi%d : target %d sync parameters are sxfer=0x%x, scntl3=0x%x\n",
-	host->host_no, target, sxfer, scntl3);
-
-    if (now_connected) {
-	NCR53c7x0_write8(SBCL_REG, scntl3);
-	NCR53c7x0_write8(SXFER_REG, sxfer);
-    }
-}
-
-
-/*
- * Function : static int asynchronous (struct Scsi_Host *host, int target)
- *
- * Purpose : reprogram between the selected SCSI Host adapter and target 
- *      (assumed to be currently connected) for asynchronous transfers.
- *
- * Inputs : host - SCSI host structure, target - numeric target ID.
- *
- * Preconditions : the NCR chip should be in one of the halted states
- */
-    
-static void
-asynchronous (struct Scsi_Host *host, int target) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-    set_synchronous (host, target, /* no offset */ 0, hostdata->saved_scntl3,
-	1);
-    printk ("scsi%d : setting target %d to asynchronous SCSI\n",
-	host->host_no, target);
-}
-
-/* 
- * XXX - do we want to go out of our way (ie, add extra code to selection
- * 	in the NCR53c710/NCR53c720 script) to reprogram the synchronous
- * 	conversion bits, or can we be content in just setting the 
- * 	sxfer bits?  I chose to do so [richard@sleepie.demon.co.uk]
- */
-
-/* Table for NCR53c8xx synchronous values */
-
-/* This table is also correct for 710, allowing that scf=4 is equivalent
- * of SSCF=0 (ie use DCNTL, divide by 3) for a 50.01-66.00MHz clock.
- * For any other clock values, we cannot use entries with SCF values of
- * 4.  I guess that for a 66MHz clock, the slowest it will set is 2MHz,
- * and for a 50MHz clock, the slowest will be 2.27Mhz.  Should check
- * that a device doesn't try and negotiate sync below these limits!
- */
- 
-static const struct {
-    int div;		/* Total clock divisor * 10 */
-    unsigned char scf;	/* */
-    unsigned char tp;	/* 4 + tp = xferp divisor */
-} syncs[] = {
-/*	div	scf	tp	div	scf	tp	div	scf	tp */
-    {	40,	1,	0}, {	50,	1,	1}, {	60,	1,	2}, 
-    {	70,	1,	3}, {	75,	2,	1}, {	80,	1,	4},
-    {	90,	1,	5}, {	100,	1,	6}, {	105,	2,	3},
-    {	110,	1,	7}, {	120,	2,	4}, {	135,	2,	5},
-    {	140,	3,	3}, {	150,	2,	6}, {	160,	3,	4},
-    {	165,	2,	7}, {	180,	3,	5}, {	200,	3,	6},
-    {	210,	4,	3}, {	220,	3,	7}, {	240,	4,	4},
-    {	270,	4,	5}, {	300,	4,	6}, {	330,	4,	7}
-};
-
-/*
- * Function : static void synchronous (struct Scsi_Host *host, int target, 
- *	char *msg)
- *
- * Purpose : reprogram transfers between the selected SCSI initiator and 
- *	target for synchronous SCSI transfers such that the synchronous 
- *	offset is less than that requested and period at least as long 
- *	as that requested.  Also modify *msg such that it contains 
- *	an appropriate response. 
- *
- * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id,
- *	msg - synchronous transfer request.
- */
-
-
-static void
-synchronous (struct Scsi_Host *host, int target, char *msg) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    int desire, divisor, i, limit;
-    unsigned char scntl3, sxfer;
-/* The diagnostic message fits on one line, even with max. width integers */
-    char buf[80];
-
-/* Desired transfer clock in Hz */
-    desire = 1000000000L / (msg[3] * 4);
-/* Scale the available SCSI clock by 10 so we get tenths */
-    divisor = (hostdata->scsi_clock * 10) / desire;
-
-/* NCR chips can handle at most an offset of 8 */
-    if (msg[4] > 8)
-	msg[4] = 8;
-
-    if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk("scsi%d : optimal synchronous divisor of %d.%01d\n",
-	    host->host_no, divisor / 10, divisor % 10);
-
-    limit = ARRAY_SIZE(syncs) - 1;
-    for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i);
-
-    if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk("scsi%d : selected synchronous divisor of %d.%01d\n",
-	    host->host_no, syncs[i].div / 10, syncs[i].div % 10);
-
-    msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4);
-
-    if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk("scsi%d : selected synchronous period of %dns\n", host->host_no,
-	    msg[3] * 4);
-
-    scntl3 = syncs[i].scf;
-    sxfer = (msg[4] << SXFER_MO_SHIFT) | (syncs[i].tp << 4);
-    if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk ("scsi%d : sxfer=0x%x scntl3=0x%x\n", 
-	    host->host_no, (int) sxfer, (int) scntl3);
-    set_synchronous (host, target, sxfer, scntl3, 1);
-    sprintf (buf, "scsi%d : setting target %d to ", host->host_no, target);
-    print_synchronous (buf, msg);
-}
-
-/* 
- * Function : static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host,
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose :  Handler for INT generated instructions for the 
- * 	NCR53c810/820 SCSI SCRIPT
- *
- * Inputs : host - pointer to this host adapter's structure,
- * 	cmd - pointer to the command (if any) dsa was pointing 
- * 	to.
- *
- */
-
-static int 
-NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct 
-    NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    int print;
-    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];		
-    u32 dsps,*dsp;	/* Argument of the INT instruction */
-
-    NCR53c7x0_local_setup(host);
-    dsps = NCR53c7x0_read32(DSPS_REG);
-    dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
-
-    /* RGH 150597:  Frig.  Commands which fail with Check Condition are
-     * Flagged as successful - hack dsps to indicate check condition */
-#if 0
-    /* RGH 200597:  Need to disable for BVME6000, as it gets Check Conditions
-     * and then dies.  Seems to handle Check Condition at startup, but
-     * not mid kernel build. */
-    if (dsps == A_int_norm_emulateintfly && cmd && cmd->result == 2)
-        dsps = A_int_err_check_condition;
-#endif
-
-    if (hostdata->options & OPTION_DEBUG_INTR) 
-	printk ("scsi%d : DSPS = 0x%x\n", host->host_no, dsps);
-
-    switch (dsps) {
-    case A_int_msg_1:
-	print = 1;
-	switch (hostdata->msg_buf[0]) {
-	/* 
-	 * Unless we've initiated synchronous negotiation, I don't
-	 * think that this should happen.
-	 */
-	case MESSAGE_REJECT:
-	    hostdata->dsp = hostdata->script + hostdata->E_accept_message /
-		sizeof(u32);
-	    hostdata->dsp_changed = 1;
-	    if (cmd && (cmd->flags & CMD_FLAG_SDTR)) {
-		printk ("scsi%d : target %d rejected SDTR\n", host->host_no, 
-		    c->device->id);
-		cmd->flags &= ~CMD_FLAG_SDTR;
-		asynchronous (host, c->device->id);
-		print = 0;
-	    } 
-	    break;
-	case INITIATE_RECOVERY:
-	    printk ("scsi%d : extended contingent allegiance not supported yet, rejecting\n",
-		host->host_no);
-	    /* Fall through to default */
-	    hostdata->dsp = hostdata->script + hostdata->E_reject_message /
-		sizeof(u32);
-	    hostdata->dsp_changed = 1;
-	    break;
-	default:
-	    printk ("scsi%d : unsupported message, rejecting\n",
-		host->host_no);
-	    hostdata->dsp = hostdata->script + hostdata->E_reject_message /
-		sizeof(u32);
-	    hostdata->dsp_changed = 1;
-	}
-	if (print) {
-	    printk ("scsi%d : received message", host->host_no);
-	    if (c) 
-	    	printk (" from target %d lun %d ", c->device->id, c->device->lun);
-	    spi_print_msg((unsigned char *) hostdata->msg_buf);
-	    printk("\n");
-	}
-	
-	return SPECIFIC_INT_NOTHING;
-
-
-    case A_int_msg_sdtr:
-/*
- * At this point, hostdata->msg_buf contains
- * 0 EXTENDED MESSAGE
- * 1 length 
- * 2 SDTR
- * 3 period * 4ns
- * 4 offset
- */
-
-	if (cmd) {
-	    char buf[80];
-	    sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->device->id,
-		(cmd->flags & CMD_FLAG_SDTR) ? "accepting" : "requesting");
-	    print_synchronous (buf, (unsigned char *) hostdata->msg_buf);
-
-	/* 
-	 * Initiator initiated, won't happen unless synchronous 
-	 * 	transfers are enabled.  If we get a SDTR message in
-	 * 	response to our SDTR, we should program our parameters
-	 * 	such that 
-	 *		offset <= requested offset
-	 *		period >= requested period		 	
-   	 */
-	    if (cmd->flags & CMD_FLAG_SDTR) {
-		cmd->flags &= ~CMD_FLAG_SDTR; 
-		if (hostdata->msg_buf[4]) 
-		    synchronous (host, c->device->id, (unsigned char *) 
-		    	hostdata->msg_buf);
-		else 
-		    asynchronous (host, c->device->id);
-		hostdata->dsp = hostdata->script + hostdata->E_accept_message /
-		    sizeof(u32);
-		hostdata->dsp_changed = 1;
-		return SPECIFIC_INT_NOTHING;
-	    } else {
-		if (hostdata->options & OPTION_SYNCHRONOUS)  {
-		    cmd->flags |= CMD_FLAG_DID_SDTR;
-		    synchronous (host, c->device->id, (unsigned char *) 
-			hostdata->msg_buf);
-		} else {
-		    hostdata->msg_buf[4] = 0;		/* 0 offset = async */
-		    asynchronous (host, c->device->id);
-		}
-		patch_dsa_32 (cmd->dsa, dsa_msgout_other, 0, 5);
-		patch_dsa_32 (cmd->dsa, dsa_msgout_other, 1, (u32) 
-		    virt_to_bus ((void *)&hostdata->msg_buf));
-		hostdata->dsp = hostdata->script + 
-		    hostdata->E_respond_message / sizeof(u32);
-		hostdata->dsp_changed = 1;
-	    }
-	    return SPECIFIC_INT_NOTHING;
-	}
-	/* Fall through to abort if we couldn't find a cmd, and 
-	   therefore a dsa structure to twiddle */
-    case A_int_msg_wdtr:
-	hostdata->dsp = hostdata->script + hostdata->E_reject_message /
-	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-	return SPECIFIC_INT_NOTHING;
-    case A_int_err_unexpected_phase:
-	if (hostdata->options & OPTION_DEBUG_INTR) 
-	    printk ("scsi%d : unexpected phase\n", host->host_no);
-	return SPECIFIC_INT_ABORT;
-    case A_int_err_selected:
-	if ((hostdata->chip / 100) == 8)
-	    printk ("scsi%d : selected by target %d\n", host->host_no,
-	        (int) NCR53c7x0_read8(SDID_REG_800) &7);
-	else
-            printk ("scsi%d : selected by target LCRC=0x%02x\n", host->host_no,
-                (int) NCR53c7x0_read8(LCRC_REG_10));
-	hostdata->dsp = hostdata->script + hostdata->E_target_abort / 
-    	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-	return SPECIFIC_INT_NOTHING;
-    case A_int_err_unexpected_reselect:
-	if ((hostdata->chip / 100) == 8)
-	    printk ("scsi%d : unexpected reselect by target %d lun %d\n", 
-	        host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & 7,
-	        hostdata->reselected_identify & 7);
-	else
-            printk ("scsi%d : unexpected reselect LCRC=0x%02x\n", host->host_no,
-                (int) NCR53c7x0_read8(LCRC_REG_10));
-	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
-    	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-	return SPECIFIC_INT_NOTHING;
-/*
- * Since contingent allegiance conditions are cleared by the next 
- * command issued to a target, we must issue a REQUEST SENSE 
- * command after receiving a CHECK CONDITION status, before
- * another command is issued.
- * 
- * Since this NCR53c7x0_cmd will be freed after use, we don't 
- * care if we step on the various fields, so modify a few things.
- */
-    case A_int_err_check_condition: 
-#if 0
-	if (hostdata->options & OPTION_DEBUG_INTR) 
-#endif
-	    printk ("scsi%d : CHECK CONDITION\n", host->host_no);
-	if (!c) {
-	    printk("scsi%d : CHECK CONDITION with no SCSI command\n",
-		host->host_no);
-	    return SPECIFIC_INT_PANIC;
-	}
-
-	/* 
-	 * FIXME : this uses the normal one-byte selection message.
-	 * 	We may want to renegotiate for synchronous & WIDE transfers
-	 * 	since these could be the crux of our problem.
-	 *
-	 hostdata->NOP_insn* FIXME : once SCSI-II tagged queuing is implemented, we'll
-	 * 	have to set this up so that the rest of the DSA
-	 *	agrees with this being an untagged queue'd command.
-	 */
-
-    	patch_dsa_32 (cmd->dsa, dsa_msgout, 0, 1);
-
-    	/* 
-    	 * Modify the table indirect for COMMAND OUT phase, since 
-    	 * Request Sense is a six byte command.
-    	 */
-
-    	patch_dsa_32 (cmd->dsa, dsa_cmdout, 0, 6);
-
-        /*
-         * The CDB is now mirrored in our local non-cached
-         * structure, but keep the old structure up to date as well,
-         * just in case anyone looks at it.
-         */
-
-	/*
-	 * XXX Need to worry about data buffer alignment/cache state
-	 * XXX here, but currently never get A_int_err_check_condition,
-	 * XXX so ignore problem for now.
-         */
-	cmd->cmnd[0] = c->cmnd[0] = REQUEST_SENSE;
-	cmd->cmnd[0] = c->cmnd[1] &= 0xe0;	/* Zero all but LUN */
-	cmd->cmnd[0] = c->cmnd[2] = 0;
-	cmd->cmnd[0] = c->cmnd[3] = 0;
-	cmd->cmnd[0] = c->cmnd[4] = sizeof(c->sense_buffer);
-	cmd->cmnd[0] = c->cmnd[5] = 0; 
-
-	/*
-	 * Disable dataout phase, and program datain to transfer to the 
-	 * sense buffer, and add a jump to other_transfer after the 
-    	 * command so overflow/underrun conditions are detected.
-	 */
-
-    	patch_dsa_32 (cmd->dsa, dsa_dataout, 0, 
-	    virt_to_bus(hostdata->script) + hostdata->E_other_transfer);
-    	patch_dsa_32 (cmd->dsa, dsa_datain, 0, 
-	    virt_to_bus(cmd->data_transfer_start));
-    	cmd->data_transfer_start[0] = (((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | 
-    	    DCMD_BMI_IO)) << 24) | sizeof(c->sense_buffer);
-    	cmd->data_transfer_start[1] = (u32) virt_to_bus(c->sense_buffer);
-
-	cmd->data_transfer_start[2] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) 
-    	    << 24) | DBC_TCI_TRUE;
-	cmd->data_transfer_start[3] = (u32) virt_to_bus(hostdata->script) + 
-	    hostdata->E_other_transfer;
-
-    	/*
-    	 * Currently, this command is flagged as completed, ie 
-    	 * it has valid status and message data.  Reflag it as
-    	 * incomplete.  Q - need to do something so that original
-	 * status, etc are used.
-    	 */
-
-	cmd->result = cmd->cmd->result = 0xffff;		
-
-	/* 
-	 * Restart command as a REQUEST SENSE.
-	 */
-	hostdata->dsp = (u32 *) hostdata->script + hostdata->E_select /
-	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-	return SPECIFIC_INT_NOTHING;
-    case A_int_debug_break:
-	return SPECIFIC_INT_BREAK;
-    case A_int_norm_aborted:
-	hostdata->dsp = (u32 *) hostdata->schedule;
-	hostdata->dsp_changed = 1;
-	if (cmd)
-	    abnormal_finished (cmd, DID_ERROR << 16);
-	return SPECIFIC_INT_NOTHING;
-    case A_int_norm_emulateintfly:
-	NCR53c7x0_intfly(host);
-	return SPECIFIC_INT_NOTHING;
-    case A_int_test_1:
-    case A_int_test_2:
-	hostdata->idle = 1;
-	hostdata->test_completed = (dsps - A_int_test_1) / 0x00010000 + 1;
-	if (hostdata->options & OPTION_DEBUG_INTR)
-	    printk("scsi%d : test%d complete\n", host->host_no,
-		hostdata->test_completed);
-	return SPECIFIC_INT_NOTHING;
-#ifdef A_int_debug_reselected_ok
-    case A_int_debug_reselected_ok:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-    	    	OPTION_DEBUG_DISCONNECT)) {
-	    /* 
-	     * Note - this dsa is not based on location relative to 
-	     * the command structure, but to location relative to the 
-	     * DSA register 
-	     */	
-	    u32 *dsa;
-	    dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG));
-
-	    printk("scsi%d : reselected_ok (DSA = 0x%x (virt 0x%p)\n", 
-		host->host_no, NCR53c7x0_read32(DSA_REG), dsa);
-	    printk("scsi%d : resume address is 0x%x (virt 0x%p)\n",
-		    host->host_no, cmd->saved_data_pointer,
-		    bus_to_virt(cmd->saved_data_pointer));
-	    print_insn (host, hostdata->script + Ent_reselected_ok / 
-    	    	    sizeof(u32), "", 1);
-	    if ((hostdata->chip / 100) == 8)
-    	        printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n",
-		    host->host_no, NCR53c7x0_read8(SXFER_REG),
-		    NCR53c7x0_read8(SCNTL3_REG_800));
-	    else
-    	        printk ("scsi%d : sxfer=0x%x, cannot read SBCL\n",
-		    host->host_no, NCR53c7x0_read8(SXFER_REG));
-	    if (c) {
-		print_insn (host, (u32 *) 
-		    hostdata->sync[c->device->id].script, "", 1);
-		print_insn (host, (u32 *) 
-		    hostdata->sync[c->device->id].script + 2, "", 1);
-	    }
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_reselect_check
-    case A_int_debug_reselect_check:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    u32 *dsa;
-#if 0
-	    u32 *code;
-#endif
-	    /* 
-	     * Note - this dsa is not based on location relative to 
-	     * the command structure, but to location relative to the 
-	     * DSA register 
-	     */	
-	    dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG));
-	    printk("scsi%d : reselected_check_next (DSA = 0x%lx (virt 0x%p))\n",
-		host->host_no, virt_to_bus(dsa), dsa);
-	    if (dsa) {
-		printk("scsi%d : resume address is 0x%x (virt 0x%p)\n",
-		    host->host_no, cmd->saved_data_pointer,
-		    bus_to_virt (cmd->saved_data_pointer));
-#if 0
-		printk("scsi%d : template code :\n", host->host_no);
-		for (code = dsa + (Ent_dsa_code_check_reselect - Ent_dsa_zero) 
-		    / sizeof(u32); code < (dsa + Ent_dsa_zero / sizeof(u32)); 
-		    code += print_insn (host, code, "", 1));
-#endif
-	    }
-	    print_insn (host, hostdata->script + Ent_reselected_ok / 
-    	    	    sizeof(u32), "", 1);
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_dsa_schedule
-    case A_int_debug_dsa_schedule:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    u32 *dsa;
-	    /* 
-	     * Note - this dsa is not based on location relative to 
-	     * the command structure, but to location relative to the 
-	     * DSA register 
-	     */	
-	    dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG));
-	    printk("scsi%d : dsa_schedule (old DSA = 0x%lx (virt 0x%p))\n", 
-		host->host_no, virt_to_bus(dsa), dsa);
-	    if (dsa) 
-		printk("scsi%d : resume address is 0x%x (virt 0x%p)\n"
-		       "         (temp was 0x%x (virt 0x%p))\n",
-		    host->host_no, cmd->saved_data_pointer,
-		    bus_to_virt (cmd->saved_data_pointer),
-		    NCR53c7x0_read32 (TEMP_REG),
-		    bus_to_virt (NCR53c7x0_read32(TEMP_REG)));
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_scheduled
-    case A_int_debug_scheduled:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    printk("scsi%d : new I/O 0x%x (virt 0x%p) scheduled\n", 
-		host->host_no, NCR53c7x0_read32(DSA_REG),
-	    	bus_to_virt(NCR53c7x0_read32(DSA_REG)));
-	}
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_idle
-    case A_int_debug_idle:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    printk("scsi%d : idle\n", host->host_no);
-	}
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_cmd
-    case A_int_debug_cmd:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    printk("scsi%d : command sent\n");
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_dsa_loaded
-    case A_int_debug_dsa_loaded:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    printk("scsi%d : DSA loaded with 0x%x (virt 0x%p)\n", host->host_no,
-		NCR53c7x0_read32(DSA_REG), 
-		bus_to_virt(NCR53c7x0_read32(DSA_REG)));
-	}
-	return SPECIFIC_INT_RESTART; 
-#endif
-#ifdef A_int_debug_reselected
-    case A_int_debug_reselected:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-	    OPTION_DEBUG_DISCONNECT)) {
-	    if ((hostdata->chip / 100) == 8)
-		printk("scsi%d : reselected by target %d lun %d\n",
-		    host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & ~0x80, 
-		    (int) hostdata->reselected_identify & 7);
-	    else
-		printk("scsi%d : reselected by LCRC=0x%02x lun %d\n",
-                    host->host_no, (int) NCR53c7x0_read8(LCRC_REG_10),
-                    (int) hostdata->reselected_identify & 7);
-	    print_queues(host);
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_disconnect_msg
-    case A_int_debug_disconnect_msg:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    if (c)
-		printk("scsi%d : target %d lun %d disconnecting\n", 
-		    host->host_no, c->device->id, c->device->lun);
-	    else
-		printk("scsi%d : unknown target disconnecting\n",
-		    host->host_no);
-	}
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_disconnected
-    case A_int_debug_disconnected:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-		OPTION_DEBUG_DISCONNECT)) {
-	    printk ("scsi%d : disconnected, new queues are\n", 
-		host->host_no);
-	    print_queues(host);
-#if 0
-	    /* Not valid on ncr53c710! */
-    	    printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n",
-		host->host_no, NCR53c7x0_read8(SXFER_REG),
-		NCR53c7x0_read8(SCNTL3_REG_800));
-#endif
-	    if (c) {
-		print_insn (host, (u32 *) 
-		    hostdata->sync[c->device->id].script, "", 1);
-		print_insn (host, (u32 *) 
-		    hostdata->sync[c->device->id].script + 2, "", 1);
-	    }
-	}
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_panic
-    case A_int_debug_panic:
-	printk("scsi%d : int_debug_panic received\n", host->host_no);
-	print_lots (host);
-	return SPECIFIC_INT_PANIC;
-#endif
-#ifdef A_int_debug_saved
-    case A_int_debug_saved:
-    	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-    	    OPTION_DEBUG_DISCONNECT)) {
-    	    printk ("scsi%d : saved data pointer 0x%x (virt 0x%p)\n",
-    	    	host->host_no, cmd->saved_data_pointer,
-		bus_to_virt (cmd->saved_data_pointer));
-    	    print_progress (c);
-    	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_restored
-    case A_int_debug_restored:
-    	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-    	    OPTION_DEBUG_DISCONNECT)) {
-    	    if (cmd) {
-		int size;
-    	    	printk ("scsi%d : restored data pointer 0x%x (virt 0x%p)\n",
-    	    	    host->host_no, cmd->saved_data_pointer, bus_to_virt (
-		    cmd->saved_data_pointer));
-		size = print_insn (host, (u32 *) 
-		    bus_to_virt(cmd->saved_data_pointer), "", 1);
-		size = print_insn (host, (u32 *) 
-		    bus_to_virt(cmd->saved_data_pointer) + size, "", 1);
-    	    	print_progress (c);
-	    }
-#if 0
-	    printk ("scsi%d : datapath residual %d\n",
-		host->host_no, datapath_residual (host)) ;
-#endif
-    	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_sync
-    case A_int_debug_sync:
-    	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-    	    OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) {
-	    unsigned char sxfer = NCR53c7x0_read8 (SXFER_REG), scntl3;
-	    if ((hostdata->chip / 100) == 8) {
-		scntl3 = NCR53c7x0_read8 (SCNTL3_REG_800);
-		if (c) {
-		  if (sxfer != hostdata->sync[c->device->id].sxfer_sanity ||
-		    scntl3 != hostdata->sync[c->device->id].scntl3_sanity) {
-		   	printk ("scsi%d :  sync sanity check failed sxfer=0x%x, scntl3=0x%x",
-			    host->host_no, sxfer, scntl3);
-			NCR53c7x0_write8 (SXFER_REG, sxfer);
-			NCR53c7x0_write8 (SCNTL3_REG_800, scntl3);
-		    }
-		} else 
-    	    	  printk ("scsi%d : unknown command sxfer=0x%x, scntl3=0x%x\n",
-		    host->host_no, (int) sxfer, (int) scntl3);
-	    } else {
-		if (c) {
-		  if (sxfer != hostdata->sync[c->device->id].sxfer_sanity) {
-		   	printk ("scsi%d :  sync sanity check failed sxfer=0x%x",
-			    host->host_no, sxfer);
-			NCR53c7x0_write8 (SXFER_REG, sxfer);
-			NCR53c7x0_write8 (SBCL_REG,
-				hostdata->sync[c->device->id].sscf_710);
-		    }
-		} else 
-    	    	  printk ("scsi%d : unknown command sxfer=0x%x\n",
-		    host->host_no, (int) sxfer);
-	    }
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_datain
-	case A_int_debug_datain:
-	    if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-		OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) {
-		int size;
-		if ((hostdata->chip / 100) == 8)
-		  printk ("scsi%d : In do_datain (%s) sxfer=0x%x, scntl3=0x%x\n"
-			"         datapath residual=%d\n",
-		    host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)),
-		    (int) NCR53c7x0_read8(SXFER_REG), 
-		    (int) NCR53c7x0_read8(SCNTL3_REG_800),
-		    datapath_residual (host)) ;
-		else
-		  printk ("scsi%d : In do_datain (%s) sxfer=0x%x\n"
-			"         datapath residual=%d\n",
-		    host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)),
-		    (int) NCR53c7x0_read8(SXFER_REG), 
-		    datapath_residual (host)) ;
-		print_insn (host, dsp, "", 1);
-		size = print_insn (host, (u32 *) bus_to_virt(dsp[1]), "", 1);
-		print_insn (host, (u32 *) bus_to_virt(dsp[1]) + size, "", 1);
-	   } 
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_check_dsa
-	case A_int_debug_check_dsa:
-	    if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) {
-		int sdid;
-		int tmp;
-		char *where;
-		if (hostdata->chip / 100 == 8)
-		    sdid = NCR53c7x0_read8 (SDID_REG_800) & 15;
-		else {
-		    tmp = NCR53c7x0_read8 (SDID_REG_700);
-		    if (!tmp)
-			panic ("SDID_REG_700 = 0");
-		    tmp >>= 1;
-		    sdid = 0;
-		    while (tmp) {
-			tmp >>= 1;
-			sdid++;
-		    }
-		}
-		where = dsp - NCR53c7x0_insn_size(NCR53c7x0_read8 
-			(DCMD_REG)) == hostdata->script + 
-		    	Ent_select_check_dsa / sizeof(u32) ?
-		    "selection" : "reselection";
-		if (c && sdid != c->device->id) {
-		    printk ("scsi%d : SDID target %d != DSA target %d at %s\n",
-			host->host_no, sdid, c->device->id, where);
-		    print_lots(host);
-		    dump_events (host, 20);
-		    return SPECIFIC_INT_PANIC;
-		}
-	    }
-	    return SPECIFIC_INT_RESTART;
-#endif
-    default:
-	if ((dsps & 0xff000000) == 0x03000000) {
-	     printk ("scsi%d : misc debug interrupt 0x%x\n",
-		host->host_no, dsps);
-	    return SPECIFIC_INT_RESTART;
-	} else if ((dsps & 0xff000000) == 0x05000000) {
-	    if (hostdata->events) {
-		struct NCR53c7x0_event *event;
-		++hostdata->event_index;
-		if (hostdata->event_index >= hostdata->event_size)
-		    hostdata->event_index = 0;
-		event = (struct NCR53c7x0_event *) hostdata->events + 
-		    hostdata->event_index;
-		event->event = (enum ncr_event) dsps;
-		event->dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-		if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) {
-		    if (hostdata->chip / 100 == 8)
-			event->target = NCR53c7x0_read8(SSID_REG_800);
-		    else {
-			unsigned char tmp, sdid;
-		        tmp = NCR53c7x0_read8 (SDID_REG_700);
-		        if (!tmp)
-			    panic ("SDID_REG_700 = 0");
-		        tmp >>= 1;
-		        sdid = 0;
-		        while (tmp) {
-			    tmp >>= 1;
-			    sdid++;
-		        }
-			event->target = sdid;
-		    }
-		}
-		else 
-			event->target = 255;
-
-		if (event->event == EVENT_RESELECT)
-		    event->lun = hostdata->reselected_identify & 0xf;
-		else if (c)
-		    event->lun = c->device->lun;
-		else
-		    event->lun = 255;
-		do_gettimeofday(&(event->time));
-		if (c) {
-		    event->pid = c->pid;
-		    memcpy ((void *) event->cmnd, (void *) c->cmnd, 
-			sizeof (event->cmnd));
-		} else {
-		    event->pid = -1;
-		}
-	    }
-	    return SPECIFIC_INT_RESTART;
-	}
-
-	printk ("scsi%d : unknown user interrupt 0x%x\n", 
-	    host->host_no, (unsigned) dsps);
-	return SPECIFIC_INT_PANIC;
-    }
-}
-
-/* 
- * XXX - the stock NCR assembler won't output the scriptu.h file,
- * which undefine's all #define'd CPP symbols from the script.h
- * file, which will create problems if you use multiple scripts
- * with the same  symbol names.
- *
- * If you insist on using NCR's assembler, you could generate
- * scriptu.h from script.h using something like 
- *
- * grep #define script.h | \
- * sed 's/#define[ 	][ 	]*\([_a-zA-Z][_a-zA-Z0-9]*\).*$/#undefine \1/' \
- * > scriptu.h
- */
-
-#include "53c7xx_u.h"
-
-/* XXX - add alternate script handling code here */
-
-
-/* 
- * Function : static void NCR537xx_soft_reset (struct Scsi_Host *host)
- *
- * Purpose :  perform a soft reset of the NCR53c7xx chip
- *
- * Inputs : host - pointer to this host adapter's structure
- *
- * Preconditions : NCR53c7x0_init must have been called for this 
- *      host.
- * 
- */
-
-static void 
-NCR53c7x0_soft_reset (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-
-    local_irq_save(flags);
-
-    /* Disable scsi chip and s/w level 7 ints */
-
-#ifdef CONFIG_MVME16x
-    if (MACH_IS_MVME16x)
-    {
-        volatile unsigned long v;
-
-        v = *(volatile unsigned long *)0xfff4006c;
-        v &= ~0x8000;
-        *(volatile unsigned long *)0xfff4006c = v;
-        v = *(volatile unsigned long *)0xfff4202c;
-        v &= ~0x10;
-        *(volatile unsigned long *)0xfff4202c = v;
-    }
-#endif
-    /* Anything specific for your hardware? */
-
-    /*
-     * Do a soft reset of the chip so that everything is 
-     * reinitialized to the power-on state.
-     *
-     * Basically follow the procedure outlined in the NCR53c700
-     * data manual under Chapter Six, How to Use, Steps Necessary to
-     * Start SCRIPTS, with the exception of actually starting the 
-     * script and setting up the synchronous transfer gunk.
-     */
-
-    /* Should we reset the scsi bus here??????????????????? */
-
-    NCR53c7x0_write8(ISTAT_REG_700, ISTAT_10_SRST);
-    NCR53c7x0_write8(ISTAT_REG_700, 0);
-
-    /*
-     * saved_dcntl is set up in NCR53c7x0_init() before it is overwritten
-     * here.  We should have some better way of working out the CF bit
-     * setting..
-     */
-
-    hostdata->saved_dcntl = DCNTL_10_EA|DCNTL_10_COM;
-    if (hostdata->scsi_clock > 50000000)
-	hostdata->saved_dcntl |= DCNTL_700_CF_3;
-    else
-    if (hostdata->scsi_clock > 37500000)
-        hostdata->saved_dcntl |= DCNTL_700_CF_2;
-#if 0
-    else
-	/* Any clocks less than 37.5MHz? */
-#endif
-
-    if (hostdata->options & OPTION_DEBUG_TRACE)
-    	NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM);
-    else
-    	NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl);
-    /* Following disables snooping - snooping is not required, as non-
-     * cached pages are used for shared data, and appropriate use is
-     * made of cache_push/cache_clear.  Indeed, for 68060
-     * enabling snooping causes disk corruption of ext2fs free block
-     * bitmaps and the like.  If you have a 68060 with snooping hardwared
-     * on, then you need to enable CONFIG_060_WRITETHROUGH.
-     */
-    NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD);
-    /* Actually burst of eight, according to my 53c710 databook */
-    NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2);
-    NCR53c7x0_write8(SCID_REG, 1 << host->this_id);
-    NCR53c7x0_write8(SBCL_REG, 0);
-    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_ESR_700);
-    NCR53c7x0_write8(SCNTL0_REG, ((hostdata->options & OPTION_PARITY) ? 
-            SCNTL0_EPC : 0) | SCNTL0_EPG_700 | SCNTL0_ARB1 | SCNTL0_ARB2);
-
-    /*
-     * Enable all interrupts, except parity which we only want when
-     * the user requests it.
-     */
-
-    NCR53c7x0_write8(DIEN_REG, DIEN_700_BF |
-		DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC);
-
-    NCR53c7x0_write8(SIEN_REG_700, ((hostdata->options & OPTION_PARITY) ?
-	    SIEN_PAR : 0) | SIEN_700_STO | SIEN_RST | SIEN_UDC |
-		SIEN_SGE | SIEN_MA);
-
-#ifdef CONFIG_MVME16x
-    if (MACH_IS_MVME16x)
-    {
-        volatile unsigned long v;
-
-        /* Enable scsi chip and s/w level 7 ints */
-        v = *(volatile unsigned long *)0xfff40080;
-        v = (v & ~(0xf << 28)) | (4 << 28);
-        *(volatile unsigned long *)0xfff40080 = v;
-        v = *(volatile unsigned long *)0xfff4006c;
-        v |= 0x8000;
-        *(volatile unsigned long *)0xfff4006c = v;
-        v = *(volatile unsigned long *)0xfff4202c;
-        v = (v & ~0xff) | 0x10 | 4;
-        *(volatile unsigned long *)0xfff4202c = v;
-    }
-#endif
-    /* Anything needed for your hardware? */
-    local_irq_restore(flags);
-}
-
-
-/*
- * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd)
- * 
- * Purpose : Return the first free NCR53c7x0_cmd structure (which are 
- * 	reused in a LIFO manner to minimize cache thrashing).
- *
- * Side effects : If we haven't yet scheduled allocation of NCR53c7x0_cmd
- *	structures for this device, do so.  Attempt to complete all scheduled
- *	allocations using get_zeroed_page(), putting NCR53c7x0_cmd structures on
- *	the free list.  Teach programmers not to drink and hack.
- *
- * Inputs : cmd - SCSI command
- *
- * Returns : NCR53c7x0_cmd structure allocated on behalf of cmd;
- *	NULL on failure.
- */
-
-static void
-my_free_page (void *addr, int dummy)
-{
-    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
-     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
-     */
-    kernel_set_cachemode((void *)addr, 4096, IOMAP_FULL_CACHING);
-    free_page ((u32)addr);
-}
-
-static struct NCR53c7x0_cmd *
-allocate_cmd (Scsi_Cmnd *cmd) {
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    u32 real;			/* Real address */
-    int size;			/* Size of *tmp */
-    struct NCR53c7x0_cmd *tmp;
-    unsigned long flags;
-
-    if (hostdata->options & OPTION_DEBUG_ALLOCATION)
-	printk ("scsi%d : num_cmds = %d, can_queue = %d\n"
-		"         target = %d, lun = %d, %s\n",
-	    host->host_no, hostdata->num_cmds, host->can_queue,
-	    cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] &
-		(1 << cmd->device->lun)) ? "already allocated" : "not allocated");
-
-/*
- * If we have not yet reserved commands for this I_T_L nexus, and
- * the device exists (as indicated by permanent Scsi_Cmnd structures
- * being allocated under 1.3.x, or being outside of scan_scsis in
- * 1.2.x), do so now.
- */
-    if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) &&
-				cmd->device && cmd->device->has_cmdblocks) {
-      if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue)
-          hostdata->extra_allocate += host->cmd_per_lun;
-      hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun);
-    }
-
-    for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, 
-    	++hostdata->num_cmds) {
-    /* historically, kmalloc has returned unaligned addresses; pad so we
-       have enough room to ROUNDUP */
-	size = hostdata->max_cmd_size + sizeof (void *);
-#ifdef FORCE_DSA_ALIGNMENT
-	/*
-	 * 53c710 rev.0 doesn't have an add-with-carry instruction.
-	 * Ensure we allocate enough memory to force alignment.
-	 */
-	size += 256;
-#endif
-/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
-
-        if (size > 4096) {
-            printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n");
-	    return NULL;
-	}
-        real = get_zeroed_page(GFP_ATOMIC);
-        if (real == 0)
-        	return NULL;
-        cache_push(virt_to_phys((void *)real), 4096);
-        cache_clear(virt_to_phys((void *)real), 4096);
-        kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER);
-	tmp = ROUNDUP(real, void *);
-#ifdef FORCE_DSA_ALIGNMENT
-	{
-	    if (((u32)tmp & 0xff) > CmdPageStart)
-		tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255);
-	    tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart);
-#if 0
-	    printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n",
-			size, real, (u32)tmp);
-#endif
-	}
-#endif
-	tmp->real = (void *)real;
-	tmp->size = size;			
-	tmp->free = ((void (*)(void *, int)) my_free_page);
-	local_irq_save(flags);
-	tmp->next = hostdata->free;
-	hostdata->free = tmp;
-	local_irq_restore(flags);
-    }
-    local_irq_save(flags);
-    tmp = (struct NCR53c7x0_cmd *) hostdata->free;
-    if (tmp) {
-	hostdata->free = tmp->next;
-    }
-    local_irq_restore(flags);
-    if (!tmp)
-	printk ("scsi%d : can't allocate command for target %d lun %d\n",
-	    host->host_no, cmd->device->id, cmd->device->lun);
-    return tmp;
-}
-
-/*
- * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) 
- *
- *
- * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the 
- * 	Scsi_Cmnd structure passed in cmd, including dsa and Linux field 
- * 	initialization, and dsa code relocation.
- *
- * Inputs : cmd - SCSI command
- *
- * Returns : NCR53c7x0_cmd structure corresponding to cmd,
- *	NULL on failure.
- */
-static struct NCR53c7x0_cmd *
-create_cmd (Scsi_Cmnd *cmd) {
-    NCR53c7x0_local_declare();
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-        host->hostdata[0];	
-    struct NCR53c7x0_cmd *tmp; 	/* NCR53c7x0_cmd structure for this command */
-    int datain,  		/* Number of instructions per phase */
-	dataout;
-    int data_transfer_instructions, /* Count of dynamic instructions */
-    	i;			/* Counter */
-    u32 *cmd_datain,		/* Address of datain/dataout code */
-	*cmd_dataout;		/* Incremented as we assemble */
-#ifdef notyet
-    unsigned char *msgptr;	/* Current byte in select message */
-    int msglen;			/* Length of whole select message */
-#endif
-    unsigned long flags;
-    u32 exp_select_indirect;	/* Used in sanity check */
-    NCR53c7x0_local_setup(cmd->device->host);
-
-    if (!(tmp = allocate_cmd (cmd)))
-	return NULL;
-
-    /*
-     * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd.
-     * We do this because NCR53c7x0_cmd may have a special cache mode
-     * selected to cope with lack of bus snooping, etc.
-     */
-
-    memcpy(tmp->cmnd, cmd->cmnd, 12);
-    tmp->result = cmd->result;
-
-    /*
-     * Decide whether we need to generate commands for DATA IN,
-     * DATA OUT, neither, or both based on the SCSI command 
-     */
-
-    switch (cmd->cmnd[0]) {
-    /* These commands do DATA IN */
-    case INQUIRY:
-    case MODE_SENSE:
-    case READ_6:
-    case READ_10:
-    case READ_CAPACITY:
-    case REQUEST_SENSE:
-    case READ_BLOCK_LIMITS:
-    case READ_TOC:
-	datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
-    	dataout = 0;
-	break;
-    /* These commands do DATA OUT */
-    case MODE_SELECT: 
-    case WRITE_6:
-    case WRITE_10:
-#if 0
-	printk("scsi%d : command is ", host->host_no);
-	__scsi_print_command(cmd->cmnd);
-#endif
-#if 0
-	printk ("scsi%d : %d scatter/gather segments\n", host->host_no,
-	    cmd->use_sg);
-#endif
-    	datain = 0;
-	dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
-#if 0
-	hostdata->options |= OPTION_DEBUG_INTR;
-#endif
-	break;
-    /* 
-     * These commands do no data transfer, we should force an
-     * interrupt if a data phase is attempted on them.
-     */
-    case TEST_UNIT_READY:
-    case ALLOW_MEDIUM_REMOVAL:
-    case START_STOP:
-    	datain = dataout = 0;
-	break;
-    /*
-     * We don't know about these commands, so generate code to handle
-     * both DATA IN and DATA OUT phases.  More efficient to identify them
-     * and add them to the above cases.
-     */
-    default:
-	printk("scsi%d : datain+dataout for command ", host->host_no);
-	__scsi_print_command(cmd->cmnd);
-	datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
-    }
-
-    /*
-     * New code : so that active pointers work correctly regardless
-     * 	of where the saved data pointer is at, we want to immediately
-     * 	enter the dynamic code after selection, and on a non-data
-     * 	phase perform a CALL to the non-data phase handler, with
-     * 	returns back to this address.
-     *
-     * 	If a phase mismatch is encountered in the middle of a 
-     * 	Block MOVE instruction, we want to _leave_ that instruction
-     *	unchanged as the current case is, modify a temporary buffer,
-     *	and point the active pointer (TEMP) at that.
-     *
-     * 	Furthermore, we want to implement a saved data pointer, 
-     * 	set by the SAVE_DATA_POINTERs message.
-     *
-     * 	So, the data transfer segments will change to 
-     *		CALL data_transfer, WHEN NOT data phase
-     *		MOVE x, x, WHEN data phase
-     *		( repeat )
-     *		JUMP other_transfer
-     */
-
-    data_transfer_instructions = datain + dataout;
-
-    /*
-     * When we perform a request sense, we overwrite various things,
-     * including the data transfer code.  Make sure we have enough
-     * space to do that.
-     */
-
-    if (data_transfer_instructions < 2)
-    	data_transfer_instructions = 2;
-
-
-    /*
-     * The saved data pointer is set up so that a RESTORE POINTERS message 
-     * will start the data transfer over at the beginning.
-     */
-
-    tmp->saved_data_pointer = virt_to_bus (hostdata->script) + 
-	hostdata->E_data_transfer;
-
-    /*
-     * Initialize Linux specific fields.
-     */
-
-    tmp->cmd = cmd;
-    tmp->next = NULL;
-    tmp->flags = 0;
-    tmp->dsa_next_addr = virt_to_bus(tmp->dsa) + hostdata->dsa_next - 
-	hostdata->dsa_start;
-    tmp->dsa_addr = virt_to_bus(tmp->dsa) - hostdata->dsa_start;
-
-    /* 
-     * Calculate addresses of dynamic code to fill in DSA
-     */
-
-    tmp->data_transfer_start = tmp->dsa + (hostdata->dsa_end - 
-    	hostdata->dsa_start) / sizeof(u32);
-    tmp->data_transfer_end = tmp->data_transfer_start + 
-    	2 * data_transfer_instructions;
-
-    cmd_datain = datain ? tmp->data_transfer_start : NULL;
-    cmd_dataout = dataout ? (datain ? cmd_datain + 2 * datain : tmp->
-    	data_transfer_start) : NULL;
-
-    /*
-     * Fill in the NCR53c7x0_cmd structure as follows
-     * dsa, with fixed up DSA code
-     * datain code
-     * dataout code
-     */
-
-    /* Copy template code into dsa and perform all necessary fixups */
-    if (hostdata->dsa_fixup)
-    	hostdata->dsa_fixup(tmp);
-
-    patch_dsa_32(tmp->dsa, dsa_next, 0, 0);
-    /*
-     * XXX is this giving 53c710 access to the Scsi_Cmnd in some way?
-     * Do we need to change it for caching reasons?
-     */
-    patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd));
-
-    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) {
-
-	exp_select_indirect = ((1 << cmd->device->id) << 16) |
-			(hostdata->sync[cmd->device->id].sxfer_sanity << 8);
-
-	if (hostdata->sync[cmd->device->id].select_indirect !=
-				exp_select_indirect) {
-	    printk ("scsi%d :  sanity check failed select_indirect=0x%x\n",
-		host->host_no, hostdata->sync[cmd->device->id].select_indirect);
-	    FATAL(host);
-
-	}
-    }
-
-    patch_dsa_32(tmp->dsa, dsa_select, 0,
-		hostdata->sync[cmd->device->id].select_indirect);
-
-    /*
-     * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on
-     * different commands; although it should be trivial to do them
-     * both at the same time.
-     */
-    if (hostdata->initiate_wdtr & (1 << cmd->device->id)) {
-	memcpy ((void *) (tmp->select + 1), (void *) wdtr_message,
-	    sizeof(wdtr_message));
-    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message));
-	local_irq_save(flags);
-	hostdata->initiate_wdtr &= ~(1 << cmd->device->id);
-	local_irq_restore(flags);
-    } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) {
-	memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, 
-	    sizeof(sdtr_message));
-    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message));
-	tmp->flags |= CMD_FLAG_SDTR;
-	local_irq_save(flags);
-	hostdata->initiate_sdtr &= ~(1 << cmd->device->id);
-	local_irq_restore(flags);
-    
-    }
-#if 1
-    else if (!(hostdata->talked_to & (1 << cmd->device->id)) &&
-		!(hostdata->options & OPTION_NO_ASYNC)) {
-
-	memcpy ((void *) (tmp->select + 1), (void *) async_message, 
-	    sizeof(async_message));
-    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(async_message));
-	tmp->flags |= CMD_FLAG_SDTR;
-    } 
-#endif
-    else 
-    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1);
-
-    hostdata->talked_to |= (1 << cmd->device->id);
-    tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ? 
-	IDENTIFY (1, cmd->device->lun) : IDENTIFY (0, cmd->device->lun);
-    patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select));
-    patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len);
-    patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd));
-    patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? 
-    	    virt_to_bus (cmd_dataout)
-	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
-    patch_dsa_32(tmp->dsa, dsa_datain, 0, cmd_datain ? 
-    	    virt_to_bus (cmd_datain) 
-	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
-    /* 
-     * XXX - need to make endian aware, should use separate variables
-     * for both status and message bytes.
-     */
-    patch_dsa_32(tmp->dsa, dsa_msgin, 0, 1);
-/* 
- * FIXME : these only works for little endian.  We probably want to 
- * 	provide message and status fields in the NCR53c7x0_cmd 
- *	structure, and assign them to cmd->result when we're done.
- */
-#ifdef BIG_ENDIAN
-    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 2);
-    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
-    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result) + 3);
-#else
-    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 1);
-    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
-    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result));
-#endif
-    patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1);
-    patch_dsa_32(tmp->dsa, dsa_msgout_other, 1, 
-	virt_to_bus(&(hostdata->NCR53c7xx_msg_nop)));
-    
-    /*
-     * Generate code for zero or more of the DATA IN, DATA OUT phases 
-     * in the format 
-     *
-     * CALL data_transfer, WHEN NOT phase
-     * MOVE first buffer length, first buffer address, WHEN phase
-     * ...
-     * MOVE last buffer length, last buffer address, WHEN phase
-     * JUMP other_transfer
-     */
-
-/* 
- * See if we're getting to data transfer by generating an unconditional 
- * interrupt.
- */
-#if 0
-    if (datain) {
-	cmd_datain[0] = 0x98080000;
-	cmd_datain[1] = 0x03ffd00d;
-	cmd_datain += 2;
-    }
-#endif
-
-/* 
- * XXX - I'm undecided whether all of this nonsense is faster
- * in the long run, or whether I should just go and implement a loop
- * on the NCR chip using table indirect mode?
- *
- * In any case, this is how it _must_ be done for 53c700/700-66 chips,
- * so this stays even when we come up with something better.
- *
- * When we're limited to 1 simultaneous command, no overlapping processing,
- * we're seeing 630K/sec, with 7% CPU usage on a slow Syquest 45M
- * drive.
- *
- * Not bad, not good. We'll see.
- */
-
-    tmp->bounce.len = 0;	/* Assume aligned buffer */
-
-    for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, 
-	cmd_dataout += 4, ++i) {
-	u32 vbuf = cmd->use_sg
-	    ? (u32)page_address(((struct scatterlist *)cmd->request_buffer)[i].page)+
-	      ((struct scatterlist *)cmd->request_buffer)[i].offset
-	    : (u32)(cmd->request_buffer);
-	u32 bbuf = virt_to_bus((void *)vbuf);
-	u32 count = cmd->use_sg ?
-	    ((struct scatterlist *)cmd->request_buffer)[i].length :
-	    cmd->request_bufflen;
-
-	/*
-	 * If we have buffers which are not aligned with 16 byte cache
-	 * lines, then we just hope nothing accesses the other parts of
-	 * those cache lines while the transfer is in progress.  That would
-	 * fill the cache, and subsequent reads of the dma data would pick
-	 * up the wrong thing.
-	 * XXX We need a bounce buffer to handle that correctly.
-	 */
-
-	if (((bbuf & 15) || (count & 15)) && (datain || dataout))
-	{
-	    /* Bounce buffer needed */
-	    if (cmd->use_sg)
-		printk ("53c7xx: Non-aligned buffer with use_sg\n");
-	    else if (datain && dataout)
-                printk ("53c7xx: Non-aligned buffer with datain && dataout\n");
-            else if (count > 256)
-		printk ("53c7xx: Non-aligned transfer > 256 bytes\n");
-	    else
-	    {
-		    if (datain)
-		    {
-			tmp->bounce.len = count;
-			tmp->bounce.addr = vbuf;
-			bbuf = virt_to_bus(tmp->bounce.buf);
-			tmp->bounce.buf[0] = 0xff;
-			tmp->bounce.buf[1] = 0xfe;
-			tmp->bounce.buf[2] = 0xfd;
-			tmp->bounce.buf[3] = 0xfc;
-	    	    }
-	    	    if (dataout)
-	    	    {
-			memcpy ((void *)tmp->bounce.buf, (void *)vbuf, count);
-			bbuf = virt_to_bus(tmp->bounce.buf);
-		    }
-	    }
-	}
-
-	if (datain) {
-            cache_clear(virt_to_phys((void *)vbuf), count);
-	    /* CALL other_in, WHEN NOT DATA_IN */  
-	    cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | 
-		DCMD_TCI_IO) << 24) | 
-		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
-	    cmd_datain[1] = virt_to_bus (hostdata->script) + 
-		hostdata->E_other_in;
-	    /* MOVE count, buf, WHEN DATA_IN */
-	    cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO) 
-    	    	<< 24) | count;
-	    cmd_datain[3] = bbuf;
-#if 0
-	    print_insn (host, cmd_datain, "dynamic ", 1);
-	    print_insn (host, cmd_datain + 2, "dynamic ", 1);
-#endif
-	}
-	if (dataout) {
-            cache_push(virt_to_phys((void *)vbuf), count);
-	    /* CALL other_out, WHEN NOT DATA_OUT */
-	    cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) | 
-		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
-	    cmd_dataout[1] = virt_to_bus(hostdata->script) + 
-    	    	hostdata->E_other_out;
-	    /* MOVE count, buf, WHEN DATA+OUT */
-	    cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24) 
-		| count;
-	    cmd_dataout[3] = bbuf;
-#if 0
-	    print_insn (host, cmd_dataout, "dynamic ", 1);
-	    print_insn (host, cmd_dataout + 2, "dynamic ", 1);
-#endif
-	}
-    }
-
-    /*
-     * Install JUMP instructions after the data transfer routines to return
-     * control to the do_other_transfer routines.
-     */
-  
-    
-    if (datain) {
-	cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |
-    	    DBC_TCI_TRUE;
-	cmd_datain[1] = virt_to_bus(hostdata->script) + 
-    	    hostdata->E_other_transfer;
-#if 0
-	print_insn (host, cmd_datain, "dynamic jump ", 1);
-#endif
-	cmd_datain += 2; 
-    }
-#if 0
-    if (datain) {
-	cmd_datain[0] = 0x98080000;
-	cmd_datain[1] = 0x03ffdeed;
-	cmd_datain += 2;
-    }
-#endif
-    if (dataout) {
-	cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |
-    	    DBC_TCI_TRUE;
-	cmd_dataout[1] = virt_to_bus(hostdata->script) + 
-    	    hostdata->E_other_transfer;
-#if 0
-	print_insn (host, cmd_dataout, "dynamic jump ", 1);
-#endif
-	cmd_dataout += 2;
-    }
-
-    return tmp;
-}
-
-/*
- * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd,
- *      void (*done)(Scsi_Cmnd *))
- *
- * Purpose :  enqueues a SCSI command
- *
- * Inputs : cmd - SCSI command, done - function called on completion, with
- *      a pointer to the command descriptor.
- *
- * Returns : 0
- *
- * Side effects :
- *      cmd is added to the per instance driver issue_queue, with major
- *      twiddling done to the host specific fields of cmd.  If the
- *      process_issue_queue coroutine isn't running, it is restarted.
- * 
- * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to 
- *	hold our own data, and pervert the ptr field of the SCp field
- *	to create a linked list.
- */
-
-int
-NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    unsigned long flags;
-    Scsi_Cmnd *tmp;
-
-    cmd->scsi_done = done;
-    cmd->host_scribble = NULL;
-    cmd->SCp.ptr = NULL;
-    cmd->SCp.buffer = NULL;
-
-#ifdef VALID_IDS
-    /* Ignore commands on invalid IDs */
-    if (!hostdata->valid_ids[cmd->device->id]) {
-        printk("scsi%d : ignoring target %d lun %d\n", host->host_no,
-            cmd->device->id, cmd->device->lun);
-        cmd->result = (DID_BAD_TARGET << 16);
-        done(cmd);
-        return 0;
-    }
-#endif
-
-    local_irq_save(flags);
-    if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) 
-	|| ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
-	    !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun)))
-#ifdef LINUX_1_2
-	|| cmd->device->id > 7
-#else
-	|| cmd->device->id >= host->max_id
-#endif
-	|| cmd->device->id == host->this_id
-	|| hostdata->state == STATE_DISABLED) {
-	printk("scsi%d : disabled or bad target %d lun %d\n", host->host_no,
-	    cmd->device->id, cmd->device->lun);
-	cmd->result = (DID_BAD_TARGET << 16);
-	done(cmd);
-	local_irq_restore(flags);
-	return 0;
-    }
-
-    if ((hostdata->options & OPTION_DEBUG_NCOMMANDS_LIMIT) &&
-	(hostdata->debug_count_limit == 0)) {
-	printk("scsi%d : maximum commands exceeded\n", host->host_no);
-	cmd->result = (DID_BAD_TARGET << 16);
-	done(cmd);
-	local_irq_restore(flags);
-	return 0;
-    }
-
-    if (hostdata->options & OPTION_DEBUG_READ_ONLY) {
-	switch (cmd->cmnd[0]) {
-	case WRITE_6:
-	case WRITE_10:
-	    printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",
-		host->host_no);
-	    cmd->result = (DID_BAD_TARGET << 16);
-	    done(cmd);
-	    local_irq_restore(flags);
-	    return 0;
-	}
-    }
-
-    if ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
-	    hostdata->debug_count_limit != -1) 
-	--hostdata->debug_count_limit;
-
-    cmd->result = 0xffff;	/* The NCR will overwrite message
-				       and status with valid data */
-    cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd);
-
-    /*
-     * REQUEST SENSE commands are inserted at the head of the queue 
-     * so that we do not clear the contingent allegiance condition
-     * they may be looking at.
-     */
-
-    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
-	cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
-	hostdata->issue_queue = cmd;
-    } else {
-	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr; 
-		tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
-	tmp->SCp.ptr = (unsigned char *) cmd;
-    }
-    local_irq_restore(flags);
-    run_process_issue_queue();
-    return 0;
-}
-
-/*
- * Function : void to_schedule_list (struct Scsi_Host *host,
- * 	struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd)
- *
- * Purpose : takes a SCSI command which was just removed from the 
- *	issue queue, and deals with it by inserting it in the first
- *	free slot in the schedule list or by terminating it immediately.
- *
- * Inputs : 
- *	host - SCSI host adapter; hostdata - hostdata structure for 
- *	this adapter; cmd - a pointer to the command; should have 
- *	the host_scribble field initialized to point to a valid 
- *	
- * Side effects : 
- *      cmd is added to the per instance schedule list, with minor 
- *      twiddling done to the host specific fields of cmd.
- *
- */
-
-static __inline__ void
-to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
-    struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    Scsi_Cmnd *tmp = cmd->cmd;
-    unsigned long flags;
-    /* dsa start is negative, so subtraction is used */
-    volatile u32 *ncrcurrent;
-
-    int i;
-    NCR53c7x0_local_setup(host);
-#if 0
-    printk("scsi%d : new dsa is 0x%lx (virt 0x%p)\n", host->host_no, 
-	virt_to_bus(hostdata->dsa), hostdata->dsa);
-#endif
-
-    local_irq_save(flags);
-    
-    /* 
-     * Work around race condition : if an interrupt fired and we 
-     * got disabled forget about this command.
-     */
-
-    if (hostdata->state == STATE_DISABLED) {
-	printk("scsi%d : driver disabled\n", host->host_no);
-	tmp->result = (DID_BAD_TARGET << 16);
-	cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
-	hostdata->free = cmd;
-	tmp->scsi_done(tmp);
-	local_irq_restore(flags);
-	return;
-    }
-
-    for (i = host->can_queue, ncrcurrent = hostdata->schedule; 
-	i > 0  && ncrcurrent[0] != hostdata->NOP_insn;
-	--i, ncrcurrent += 2 /* JUMP instructions are two words */);
-
-    if (i > 0) {
-	++hostdata->busy[tmp->device->id][tmp->device->lun];
-	cmd->next = hostdata->running_list;
-	hostdata->running_list = cmd;
-
-	/* Restore this instruction to a NOP once the command starts */
-	cmd->dsa [(hostdata->dsa_jump_dest - hostdata->dsa_start) / 
-	    sizeof(u32)] = (u32) virt_to_bus ((void *)ncrcurrent);
-	/* Replace the current jump operand.  */
-	ncrcurrent[1] =
-	    virt_to_bus ((void *) cmd->dsa) + hostdata->E_dsa_code_begin -
-	    hostdata->E_dsa_code_template;
-	/* Replace the NOP instruction with a JUMP */
-	ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) |
-	    DBC_TCI_TRUE;
-    }  else {
-	printk ("scsi%d: no free slot\n", host->host_no);
-	disable(host);
-	tmp->result = (DID_ERROR << 16);
-	cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
-	hostdata->free = cmd;
-	tmp->scsi_done(tmp);
-	local_irq_restore(flags);
-	return;
-    }
-
-    /* 
-     * If the NCR chip is in an idle state, start it running the scheduler
-     * immediately.  Otherwise, signal the chip to jump to schedule as 
-     * soon as it is idle.
-     */
-
-    if (hostdata->idle) {
-	hostdata->idle = 0;
-	hostdata->state = STATE_RUNNING;
-	NCR53c7x0_write32 (DSP_REG,  virt_to_bus ((void *)hostdata->schedule));
-	if (hostdata->options & OPTION_DEBUG_TRACE)
-	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
-				DCNTL_SSM | DCNTL_STD);
-    } else {
-	NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP);
-    }
-
-    local_irq_restore(flags);
-}
-
-/*
- * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata 
- *	*hostdata, Scsi_Cmnd *cmd)
- *
- * Purpose : decide if we can pass the given SCSI command on to the 
- *	device in question or not.
- *  
- * Returns : non-zero when we're busy, 0 when we aren't.
- */
-
-static __inline__ int
-busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, 
-    Scsi_Cmnd *cmd) {
-    /* FIXME : in the future, this needs to accommodate SCSI-II tagged
-       queuing, and we may be able to play with fairness here a bit.
-     */
-    return hostdata->busy[cmd->device->id][cmd->device->lun];
-}
-
-/*
- * Function : process_issue_queue (void)
- *
- * Purpose : transfer commands from the issue queue to NCR start queue 
- *	of each NCR53c7/8xx in the system, avoiding kernel stack 
- *	overflows when the scsi_done() function is invoked recursively.
- * 
- * NOTE : process_issue_queue exits with interrupts *disabled*, so the 
- *	caller must reenable them if it desires.
- * 
- * NOTE : process_issue_queue should be called from both 
- *	NCR53c7x0_queue_command() and from the interrupt handler 
- *	after command completion in case NCR53c7x0_queue_command()
- * 	isn't invoked again but we've freed up resources that are
- *	needed.
- */
-
-static void 
-process_issue_queue (unsigned long flags) {
-    Scsi_Cmnd *tmp, *prev;
-    struct Scsi_Host *host;
-    struct NCR53c7x0_hostdata *hostdata;
-    int done;
-
-    /*
-     * We run (with interrupts disabled) until we're sure that none of 
-     * the host adapters have anything that can be done, at which point 
-     * we set process_issue_queue_running to 0 and exit.
-     *
-     * Interrupts are enabled before doing various other internal 
-     * instructions, after we've decided that we need to run through
-     * the loop again.
-     *
-     */
-
-    do {
-	local_irq_disable(); /* Freeze request queues */
-	done = 1;
-	for (host = first_host; host && host->hostt == the_template;
-	    host = host->next) {
-	    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
-	    local_irq_disable();
-	    if (hostdata->issue_queue) {
-	    	if (hostdata->state == STATE_DISABLED) {
-		    tmp = (Scsi_Cmnd *) hostdata->issue_queue;
-		    hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
-		    tmp->result = (DID_BAD_TARGET << 16);
-		    if (tmp->host_scribble) {
-			((struct NCR53c7x0_cmd *)tmp->host_scribble)->next = 
-			    hostdata->free;
-			hostdata->free = 
-			    (struct NCR53c7x0_cmd *)tmp->host_scribble;
-			tmp->host_scribble = NULL;
-		    }
-		    tmp->scsi_done (tmp);
-		    done = 0;
-		} else 
-		    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
-			prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) 
-			tmp->SCp.ptr) 
-			if (!tmp->host_scribble || 
-			    !busyp (host, hostdata, tmp)) {
-				if (prev)
-				    prev->SCp.ptr = tmp->SCp.ptr;
-				else
-				    hostdata->issue_queue = (Scsi_Cmnd *) 
-					tmp->SCp.ptr;
-			    tmp->SCp.ptr = NULL;
-			    if (tmp->host_scribble) {
-				if (hostdata->options & OPTION_DEBUG_QUEUES) 
-				    printk ("scsi%d : moving command for target %d lun %d to start list\n",
-					host->host_no, tmp->device->id, tmp->device->lun);
-		
-
-			    	to_schedule_list (host, hostdata, 
-				    (struct NCR53c7x0_cmd *)
-				    tmp->host_scribble);
-			    } else {
-				if (((tmp->result & 0xff) == 0xff) ||
-			    	    ((tmp->result & 0xff00) == 0xff00)) {
-				    printk ("scsi%d : danger Will Robinson!\n",
-					host->host_no);
-				    tmp->result = DID_ERROR << 16;
-				    disable (host);
-				}
-				tmp->scsi_done(tmp);
-			    }
-			    done = 0;
-			} /* if target/lun is not busy */
-	    } /* if hostdata->issue_queue */
-	    if (!done)
-		local_irq_restore(flags);
-    	} /* for host */
-    } while (!done);
-    process_issue_queue_running = 0;
-}
-
-/*
- * Function : static void intr_scsi (struct Scsi_Host *host, 
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : handle all SCSI interrupts, indicated by the setting 
- * 	of the SIP bit in the ISTAT register.
- *
- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
- * 	may be NULL.
- */
-
-static void 
-intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = 
-    	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    unsigned char sstat0_sist0, sist1, 		/* Registers */
-	    fatal; 				/* Did a fatal interrupt 
-						   occur ? */
-   
-    NCR53c7x0_local_setup(host);
-
-    fatal = 0;
-
-    sstat0_sist0 = NCR53c7x0_read8(SSTAT0_REG);
-    sist1 = 0;
-
-    if (hostdata->options & OPTION_DEBUG_INTR) 
-	printk ("scsi%d : SIST0 0x%0x, SIST1 0x%0x\n", host->host_no,
-	    sstat0_sist0, sist1);
-
-    /* 250ms selection timeout */
-    if (sstat0_sist0 & SSTAT0_700_STO) {
-	fatal = 1;
-	if (hostdata->options & OPTION_DEBUG_INTR) {
-	    printk ("scsi%d : Selection Timeout\n", host->host_no);
-    	    if (cmd) {
-    	    	printk("scsi%d : target %d, lun %d, command ",
-		    host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
-    	    	__scsi_print_command (cmd->cmd->cmnd);
-		printk("scsi%d : dsp = 0x%x (virt 0x%p)\n", host->host_no,
-		    NCR53c7x0_read32(DSP_REG),
-		    bus_to_virt(NCR53c7x0_read32(DSP_REG)));
-    	    } else {
-    	    	printk("scsi%d : no command\n", host->host_no);
-    	    }
-    	}
-/*
- * XXX - question : how do we want to handle the Illegal Instruction
- * 	interrupt, which may occur before or after the Selection Timeout
- * 	interrupt?
- */
-
-	if (1) {
-	    hostdata->idle = 1;
-	    hostdata->expecting_sto = 0;
-
-	    if (hostdata->test_running) {
-		hostdata->test_running = 0;
-		hostdata->test_completed = 3;
-	    } else if (cmd) {
-		abnormal_finished(cmd, DID_BAD_TARGET << 16);
-	    }
-#if 0	    
-	    hostdata->intrs = 0;
-#endif
-	}
-    } 
-
-/*
- * FIXME : in theory, we can also get a UDC when a STO occurs.
- */
-    if (sstat0_sist0 & SSTAT0_UDC) {
-	fatal = 1;
-	if (cmd) {
-	    printk("scsi%d : target %d lun %d unexpected disconnect\n",
-		host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
-	    print_lots (host);
-	    abnormal_finished(cmd, DID_ERROR << 16);
-	} else 
-	     printk("scsi%d : unexpected disconnect (no command)\n",
-		host->host_no);
-
-	hostdata->dsp = (u32 *) hostdata->schedule;
-	hostdata->dsp_changed = 1;
-    }
-
-    /* SCSI PARITY error */
-    if (sstat0_sist0 & SSTAT0_PAR) {
-	fatal = 1;
-	if (cmd && cmd->cmd) {
-	    printk("scsi%d : target %d lun %d parity error.\n",
-		host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
-	    abnormal_finished (cmd, DID_PARITY << 16); 
-	} else
-	    printk("scsi%d : parity error\n", host->host_no);
-	/* Should send message out, parity error */
-
-	/* XXX - Reduce synchronous transfer rate! */
-	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
-    	    sizeof(u32);
-	hostdata->dsp_changed = 1; 
-    /* SCSI GROSS error */
-    } 
-
-    if (sstat0_sist0 & SSTAT0_SGE) {
-	fatal = 1;
-	printk("scsi%d : gross error, saved2_dsa = 0x%x\n", host->host_no,
-					(unsigned int)hostdata->saved2_dsa);
-	print_lots (host);
-	
-	/* 
-         * A SCSI gross error may occur when we have 
-	 *
-	 * - A synchronous offset which causes the SCSI FIFO to be overwritten.
-	 *
-	 * - A REQ which causes the maximum synchronous offset programmed in 
-	 * 	the SXFER register to be exceeded.
-	 *
-	 * - A phase change with an outstanding synchronous offset.
-	 *
-	 * - Residual data in the synchronous data FIFO, with a transfer
-	 *	other than a synchronous receive is started.$#
-	 */
-		
-
-	/* XXX Should deduce synchronous transfer rate! */
-	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
-    	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-    /* Phase mismatch */
-    } 
-
-    if (sstat0_sist0 & SSTAT0_MA) {
-	fatal = 1;
-	if (hostdata->options & OPTION_DEBUG_INTR)
-	    printk ("scsi%d : SSTAT0_MA\n", host->host_no);
-	intr_phase_mismatch (host, cmd);
-    }
-
-#if 0
-    if (sstat0_sist0 & SIST0_800_RSL) 
-	printk ("scsi%d : Oh no Mr. Bill!\n", host->host_no);
-#endif
-    
-/*
- * If a fatal SCSI interrupt occurs, we must insure that the DMA and
- * SCSI FIFOs were flushed.
- */
-
-    if (fatal) {
-	if (!hostdata->dstat_valid) {
-	    hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-	    hostdata->dstat_valid = 1;
-	}
-
-	if (!(hostdata->dstat & DSTAT_DFE)) {
-	  printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
-	  /*
-	   * Really need to check this code for 710  RGH.
-	   * Havn't seen any problems, but maybe we should FLUSH before
-	   * clearing sometimes.
-	   */
-          NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
-          while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
-		;
-	  hostdata->dstat |= DSTAT_DFE;
-    	}
-    }
-}
-
-#ifdef CYCLIC_TRACE
-
-/*
- * The following implements a cyclic log of instructions executed, if you turn
- * TRACE on.  It will also print the log for you.  Very useful when debugging
- * 53c710 support, possibly not really needed any more.
- */
-
-u32 insn_log[4096];
-u32 insn_log_index = 0;
-
-void log1 (u32 i)
-{
-	insn_log[insn_log_index++] = i;
-	if (insn_log_index == 4096)
-		insn_log_index = 0;
-}
-
-void log_insn (u32 *ip)
-{
-	log1 ((u32)ip);
-	log1 (*ip);
-	log1 (*(ip+1));
-	if (((*ip >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)
-		log1 (*(ip+2));
-}
-
-void dump_log(void)
-{
-	int cnt = 0;
-	int i = insn_log_index;
-	int size;
-	struct Scsi_Host *host = first_host;
-
-	while (cnt < 4096) {
-		printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4);
-		if (++i == 4096)
-			i = 0;
-		cnt++;
-		if (((insn_log[i]  >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) 
-			size = 3;
-		else
-			size = 2;
-		while (size--) {
-			printk ("%08x ", insn_log[i]);
-			if (++i == 4096)
-				i = 0;
-			cnt++;
-		}
-		printk ("\n");
-	}
-}
-#endif
-
-
-/*
- * Function : static void NCR53c7x0_intfly (struct Scsi_Host *host)
- *
- * Purpose : Scan command queue for specified host, looking for completed
- *           commands.
- * 
- * Inputs : Scsi_Host pointer.
- *
- * 	This is called from the interrupt handler, when a simulated INTFLY
- * 	interrupt occurs.
- */
-
-static void
-NCR53c7x0_intfly (struct Scsi_Host *host)
-{
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
-    struct NCR53c7x0_cmd *cmd,			/* command which halted */
-	**cmd_prev_ptr;
-    unsigned long flags;				
-    char search_found = 0;			/* Got at least one ? */
-
-    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-
-    if (hostdata->options & OPTION_DEBUG_INTR)
-    printk ("scsi%d : INTFLY\n", host->host_no); 
-
-    /*
-    * Traverse our list of running commands, and look
-    * for those with valid (non-0xff ff) status and message
-    * bytes encoded in the result which signify command
-    * completion.
-    */
-
-    local_irq_save(flags);
-restart:
-    for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list),
-	cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
-	cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
-    	cmd = (struct NCR53c7x0_cmd *) cmd->next)
-    {
-	Scsi_Cmnd *tmp;
-
-	if (!cmd) {
-	    printk("scsi%d : very weird.\n", host->host_no);
-	    break;
-	}
-
-	if (!(tmp = cmd->cmd)) {
-	    printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
-		    host->host_no);
-	    continue;
-	}
-	/* Copy the result over now; may not be complete,
-	 * but subsequent tests may as well be done on
-	 * cached memory.
-	 */
-	tmp->result = cmd->result;
-
-	if (((tmp->result & 0xff) == 0xff) ||
-			    ((tmp->result & 0xff00) == 0xff00))
-	    continue;
-
-	search_found = 1;
-
-	if (cmd->bounce.len)
-	    memcpy ((void *)cmd->bounce.addr,
-				(void *)cmd->bounce.buf, cmd->bounce.len);
-
-	/* Important - remove from list _before_ done is called */
-	if (cmd_prev_ptr)
-	    *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next;
-
-	--hostdata->busy[tmp->device->id][tmp->device->lun];
-	cmd->next = hostdata->free;
-	hostdata->free = cmd;
-
-	tmp->host_scribble = NULL;
-
-	if (hostdata->options & OPTION_DEBUG_INTR) {
-	    printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", 
-		  host->host_no, tmp->pid, tmp->device->id, tmp->device->lun, tmp->result);
-	    __scsi_print_command (tmp->cmnd);
-	}
-
-	tmp->scsi_done(tmp);
-	goto restart;
-    }
-    local_irq_restore(flags);
-
-    if (!search_found)  {
-	printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
-			    host->host_no);
-    } else {
-	run_process_issue_queue();
-    }
-    return;
-}
-
-/*
- * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id)
- *
- * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
- *	the same IRQ line.  
- * 
- * Inputs : Since we're using the IRQF_DISABLED interrupt handler
- *	semantics, irq indicates the interrupt which invoked 
- *	this handler.  
- *
- * On the 710 we simualte an INTFLY with a script interrupt, and the
- * script interrupt handler will call back to this function.
- */
-
-static irqreturn_t
-NCR53c7x0_intr (int irq, void *dev_id)
-{
-    NCR53c7x0_local_declare();
-    struct Scsi_Host *host;			/* Host we are looking at */
-    unsigned char istat; 			/* Values of interrupt regs */
-    struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
-    struct NCR53c7x0_cmd *cmd;			/* command which halted */
-    u32 *dsa;					/* DSA */
-    int handled = 0;
-
-#ifdef NCR_DEBUG
-    char buf[80];				/* Debugging sprintf buffer */
-    size_t buflen;				/* Length of same */
-#endif
-
-    host     = (struct Scsi_Host *)dev_id;
-    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-
-    /*
-     * Only read istat once per loop, since reading it again will unstack
-     * interrupts
-     */
-
-    while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) {
-	handled = 1;
-	hostdata->dsp_changed = 0;
-	hostdata->dstat_valid = 0;
-    	hostdata->state = STATE_HALTED;
-
-	if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) 
-	    printk ("scsi%d : SCSI FIFO not empty\n", host->host_no);
-
-	/*
-	 * NCR53c700 and NCR53c700-66 change the current SCSI
-	 * process, hostdata->ncrcurrent, in the Linux driver so
-	 * cmd = hostdata->ncrcurrent.
-	 *
-	 * With other chips, we must look through the commands
-	 * executing and find the command structure which 
-	 * corresponds to the DSA register.
-	 */
-
-	if (hostdata->options & OPTION_700) {
-	    cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent;
-	} else {
-	    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-	    for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list;
-		cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa;
-		    cmd = (struct NCR53c7x0_cmd *)(cmd->next))
-		;
-	}
-	if (hostdata->options & OPTION_DEBUG_INTR) {
-	    if (cmd) {
-		printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", 
-		    host->host_no, cmd->cmd->pid, (int) cmd->cmd->device->id,
-		    (int) cmd->cmd->device->lun);
-		__scsi_print_command (cmd->cmd->cmnd);
-	    } else {
-		printk("scsi%d : no active command\n", host->host_no);
-	    }
-	}
-	
-	if (istat & ISTAT_SIP) {
-	    if (hostdata->options & OPTION_DEBUG_INTR) 
-		printk ("scsi%d : ISTAT_SIP\n", host->host_no);
-	    intr_scsi (host, cmd);
-	}
-	
-	if (istat & ISTAT_DIP) {
-	    if (hostdata->options & OPTION_DEBUG_INTR) 
-		printk ("scsi%d : ISTAT_DIP\n", host->host_no);
-	    intr_dma (host, cmd);
-	}
-	
-	if (!hostdata->dstat_valid) {
-	    hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-	    hostdata->dstat_valid = 1;
-	}
-	
-	if (!(hostdata->dstat & DSTAT_DFE)) {
-	    printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
-	    /* Really need to check this out for 710 RGH */
-	    NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
-	    while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
-		;
-	    hostdata->dstat |= DSTAT_DFE;
-	}
-
-	if (!hostdata->idle && hostdata->state == STATE_HALTED) {
-	    if (!hostdata->dsp_changed)
-		hostdata->dsp = (u32 *)bus_to_virt(NCR53c7x0_read32(DSP_REG));
-#if 0
-	    printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n",
-		host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp);
-#endif
-		
-	    hostdata->state = STATE_RUNNING;
-	    NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp));
-	    if (hostdata->options & OPTION_DEBUG_TRACE) {
-#ifdef CYCLIC_TRACE
-		log_insn (hostdata->dsp);
-#else
-	    	print_insn (host, hostdata->dsp, "t ", 1);
-#endif
-		NCR53c7x0_write8 (DCNTL_REG,
-			hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD);
-	    }
-	}
-    }
-    return IRQ_HANDLED;
-}
-
-
-/* 
- * Function : static int abort_connected (struct Scsi_Host *host)
- *
- * Purpose : Assuming that the NCR SCSI processor is currently 
- * 	halted, break the currently established nexus.  Clean
- *	up of the NCR53c7x0_cmd and Scsi_Cmnd structures should
- *	be done on receipt of the abort interrupt.
- *
- * Inputs : host - SCSI host
- *
- */
-
-static int 
-abort_connected (struct Scsi_Host *host) {
-#ifdef NEW_ABORT
-    NCR53c7x0_local_declare();
-#endif
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-/* FIXME : this probably should change for production kernels; at the 
-   least, counter should move to a per-host structure. */
-    static int counter = 5;
-#ifdef NEW_ABORT
-    int sstat, phase, offset;
-    u32 *script;
-    NCR53c7x0_local_setup(host);
-#endif
-
-    if (--counter <= 0) {
-	disable(host);
-	return 0;
-    }
-
-    printk ("scsi%d : DANGER : abort_connected() called \n",
-	host->host_no);
-
-#ifdef NEW_ABORT
-
-/*
- * New strategy : Rather than using a generic abort routine,
- * we'll specifically try to source or sink the appropriate
- * amount of data for the phase we're currently in (taking into 
- * account the current synchronous offset) 
- */
-
-    sstat = NCR53c8x0_read8 (SSTAT2_REG);
-    offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
-    phase = sstat & SSTAT2_PHASE_MASK;
-
-/*
- * SET ATN
- * MOVE source_or_sink, WHEN CURRENT PHASE 
- * < repeat for each outstanding byte >
- * JUMP send_abort_message
- */
-
-    script = hostdata->abort_script = kmalloc (
-	8  /* instruction size */ * (
-	    1 /* set ATN */ +
-	    (!offset ? 1 : offset) /* One transfer per outstanding byte */ +
-	    1 /* send abort message */),
-	GFP_ATOMIC);
-
-
-#else /* def NEW_ABORT */
-    hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
-	    sizeof(u32);
-#endif /* def NEW_ABORT */
-    hostdata->dsp_changed = 1;
-
-/* XXX - need to flag the command as aborted after the abort_connected
- 	 code runs 
- */
-    return 0;
-}
-
-/*
- * Function : static int datapath_residual (Scsi_Host *host)
- *
- * Purpose : return residual data count of what's in the chip.
- *
- * Inputs : host - SCSI host
- */
-
-static int
-datapath_residual (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    int count, synchronous, sstat;
-    unsigned int ddir;
-
-    NCR53c7x0_local_setup(host);
-    /* COMPAT : the 700 and 700-66 need to use DFIFO_00_BO_MASK */
-    count = ((NCR53c7x0_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) -
-	(NCR53c7x0_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK;
-    synchronous = NCR53c7x0_read8 (SXFER_REG) & SXFER_MO_MASK;
-    /* COMPAT : DDIR is elsewhere on non-'8xx chips. */
-    ddir = NCR53c7x0_read8 (CTEST0_REG_700) & CTEST0_700_DDIR;
-
-    if (ddir) {
-    /* Receive */
-	if (synchronous) 
-	    count += (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
-	else
-	    if (NCR53c7x0_read8 (SSTAT1_REG) & SSTAT1_ILF)
-		++count;
-    } else {
-    /* Send */
-	sstat = NCR53c7x0_read8 (SSTAT1_REG);
-	if (sstat & SSTAT1_OLF)
-	    ++count;
-	if (synchronous && (sstat & SSTAT1_ORF))
-	    ++count;
-    }
-    return count;
-}
-
-/* 
- * Function : static const char * sbcl_to_phase (int sbcl)_
- *
- * Purpose : Convert SBCL register to user-parsable phase representation
- *
- * Inputs : sbcl - value of sbcl register
- */
-
-
-static const char *
-sbcl_to_phase (int sbcl) {
-    switch (sbcl & SBCL_PHASE_MASK) {
-    case SBCL_PHASE_DATAIN:
-	return "DATAIN";
-    case SBCL_PHASE_DATAOUT:
-	return "DATAOUT";
-    case SBCL_PHASE_MSGIN:
-	return "MSGIN";
-    case SBCL_PHASE_MSGOUT:
-	return "MSGOUT";
-    case SBCL_PHASE_CMDOUT:
-	return "CMDOUT";
-    case SBCL_PHASE_STATIN:
-	return "STATUSIN";
-    default:
-	return "unknown";
-    }
-}
-
-/* 
- * Function : static const char * sstat2_to_phase (int sstat)_
- *
- * Purpose : Convert SSTAT2 register to user-parsable phase representation
- *
- * Inputs : sstat - value of sstat register
- */
-
-
-static const char *
-sstat2_to_phase (int sstat) {
-    switch (sstat & SSTAT2_PHASE_MASK) {
-    case SSTAT2_PHASE_DATAIN:
-	return "DATAIN";
-    case SSTAT2_PHASE_DATAOUT:
-	return "DATAOUT";
-    case SSTAT2_PHASE_MSGIN:
-	return "MSGIN";
-    case SSTAT2_PHASE_MSGOUT:
-	return "MSGOUT";
-    case SSTAT2_PHASE_CMDOUT:
-	return "CMDOUT";
-    case SSTAT2_PHASE_STATIN:
-	return "STATUSIN";
-    default:
-	return "unknown";
-    }
-}
-
-/* 
- * Function : static void intr_phase_mismatch (struct Scsi_Host *host, 
- *	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : Handle phase mismatch interrupts
- *
- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
- * 	may be NULL.
- *
- * Side effects : The abort_connected() routine is called or the NCR chip 
- *	is restarted, jumping to the command_complete entry point, or 
- *	patching the address and transfer count of the current instruction 
- *	and calling the msg_in entry point as appropriate.
- */
-
-static void 
-intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    u32 dbc_dcmd, *dsp, *dsp_next;
-    unsigned char dcmd, sbcl;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata[0];
-    int residual;
-    enum {ACTION_ABORT, ACTION_ABORT_PRINT, ACTION_CONTINUE} action = 
-	ACTION_ABORT_PRINT;
-    const char *where = NULL;
-
-    NCR53c7x0_local_setup(host);
-
-    /*
-     * Corrective action is based on where in the SCSI SCRIPT(tm) the error 
-     * occurred, as well as which SCSI phase we are currently in.
-     */
-    dsp_next = bus_to_virt(NCR53c7x0_read32(DSP_REG));
-
-    /* 
-     * Fetch the current instruction, and remove the operands for easier 
-     * interpretation.
-     */
-    dbc_dcmd = NCR53c7x0_read32(DBC_REG);
-    dcmd = (dbc_dcmd & 0xff000000) >> 24;
-    /*
-     * Like other processors, the NCR adjusts the instruction pointer before
-     * instruction decode.  Set the DSP address back to what it should
-     * be for this instruction based on its size (2 or 3 32 bit words).
-     */
-    dsp = dsp_next - NCR53c7x0_insn_size(dcmd);
-
-
-    /*
-     * Read new SCSI phase from the SBCL lines.  Since all of our code uses 
-     * a WHEN conditional instead of an IF conditional, we don't need to 
-     * wait for a new REQ.
-     */
-    sbcl = NCR53c7x0_read8(SBCL_REG) & SBCL_PHASE_MASK;
-
-    if (!cmd) {
-	action = ACTION_ABORT_PRINT;
-	where = "no current command";
-    /*
-     * The way my SCSI SCRIPTS(tm) are architected, recoverable phase
-     * mismatches should only occur where we're doing a multi-byte  
-     * BMI instruction.  Specifically, this means 
-     *
-     *  - select messages (a SCSI-I target may ignore additional messages
-     * 		after the IDENTIFY; any target may reject a SDTR or WDTR)
-     *
-     *  - command out (targets may send a message to signal an error 
-     * 		condition, or go into STATUSIN after they've decided 
-     *		they don't like the command.
-     *
-     *	- reply_message (targets may reject a multi-byte message in the 
-     *		middle)
-     *
-     * 	- data transfer routines (command completion with buffer space
-     *		left, disconnect message, or error message)
-     */
-    } else if (((dsp >= cmd->data_transfer_start && 
-	dsp < cmd->data_transfer_end)) || dsp == (cmd->residual + 2)) {
-	if ((dcmd & (DCMD_TYPE_MASK|DCMD_BMI_OP_MASK|DCMD_BMI_INDIRECT|
-		DCMD_BMI_MSG|DCMD_BMI_CD)) == (DCMD_TYPE_BMI|
-		DCMD_BMI_OP_MOVE_I)) {
-	    residual = datapath_residual (host);
-	    if (hostdata->options & OPTION_DEBUG_DISCONNECT)
-	    	printk ("scsi%d : handling residual transfer (+ %d bytes from DMA FIFO)\n", 
-		    host->host_no, residual);
-
-	    /*
-	     * The first instruction is a CALL to the alternate handler for 
-	     * this data transfer phase, so we can do calls to 
-	     * munge_msg_restart as we would if control were passed 
-	     * from normal dynamic code.
-	     */
-	    if (dsp != cmd->residual + 2) {
-		cmd->residual[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL |
-			((dcmd & DCMD_BMI_IO) ? DCMD_TCI_IO : 0)) << 24) | 
-		    DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
-		cmd->residual[1] = virt_to_bus(hostdata->script)
-		    + ((dcmd & DCMD_BMI_IO)
-		       ? hostdata->E_other_in : hostdata->E_other_out);
-	    }
-
-	    /*
-	     * The second instruction is the a data transfer block
-	     * move instruction, reflecting the pointer and count at the 
-	     * time of the phase mismatch.
-	     */
-	    cmd->residual[2] = dbc_dcmd + residual;
-	    cmd->residual[3] = NCR53c7x0_read32(DNAD_REG) - residual;
-
-	    /*
-	     * The third and final instruction is a jump to the instruction
-	     * which follows the instruction which had to be 'split'
-	     */
-	    if (dsp != cmd->residual + 2) {
-		cmd->residual[4] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) 
-		    << 24) | DBC_TCI_TRUE;
-		cmd->residual[5] = virt_to_bus(dsp_next);
-	    }
-
-	    /*
-	     * For the sake of simplicity, transfer control to the 
-	     * conditional CALL at the start of the residual buffer.
-	     */
-	    hostdata->dsp = cmd->residual;
-	    hostdata->dsp_changed = 1;
-	    action = ACTION_CONTINUE;
-	} else {
-	    where = "non-BMI dynamic DSA code";
-	    action = ACTION_ABORT_PRINT;
-	}
-    } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4 + 2)) {
-	/* RGH 290697:  Added +2 above, to compensate for the script
-	 * instruction which disables the selection timer. */
-	/* Release ATN */
-	NCR53c7x0_write8 (SOCL_REG, 0);
-	switch (sbcl) {
-    /* 
-     * Some devices (SQ555 come to mind) grab the IDENTIFY message
-     * sent on selection, and decide to go into COMMAND OUT phase
-     * rather than accepting the rest of the messages or rejecting
-     * them.  Handle these devices gracefully.
-     */
-	case SBCL_PHASE_CMDOUT:
-	    hostdata->dsp = dsp + 2 /* two _words_ */;
-	    hostdata->dsp_changed = 1;
-	    printk ("scsi%d : target %d ignored SDTR and went into COMMAND OUT\n", 
-		host->host_no, cmd->cmd->device->id);
-	    cmd->flags &= ~CMD_FLAG_SDTR;
-	    action = ACTION_CONTINUE;
-	    break;
-	case SBCL_PHASE_MSGIN:
-	    hostdata->dsp = hostdata->script + hostdata->E_msg_in / 
-		sizeof(u32);
-	    hostdata->dsp_changed = 1;
-	    action = ACTION_CONTINUE;
-	    break;
-	default:
-	    where="select message out";
-	    action = ACTION_ABORT_PRINT;
-	}
-    /*
-     * Some SCSI devices will interpret a command as they read the bytes
-     * off the SCSI bus, and may decide that the command is Bogus before 
-     * they've read the entire command off the bus.
-     */
-    } else if (dsp == hostdata->script + hostdata->E_cmdout_cmdout / sizeof 
-	(u32)) {
-	hostdata->dsp = hostdata->script + hostdata->E_data_transfer /
-	    sizeof (u32);
-	hostdata->dsp_changed = 1;
-	action = ACTION_CONTINUE;
-    /* FIXME : we need to handle message reject, etc. within msg_respond. */
-#ifdef notyet
-    } else if (dsp == hostdata->script + hostdata->E_reply_message) {
-	switch (sbcl) {
-    /* Any other phase mismatches abort the currently executing command.  */
-#endif
-    } else {
-	where = "unknown location";
-	action = ACTION_ABORT_PRINT;
-    }
-
-    /* Flush DMA FIFO */
-    if (!hostdata->dstat_valid) {
-	hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-	hostdata->dstat_valid = 1;
-    }
-    if (!(hostdata->dstat & DSTAT_DFE)) {
-      /* Really need to check this out for 710 RGH */
-      NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
-      while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF);
-      hostdata->dstat |= DSTAT_DFE;
-    }
-
-    switch (action) {
-    case ACTION_ABORT_PRINT:
-	printk("scsi%d : %s : unexpected phase %s.\n",
-	     host->host_no, where ? where : "unknown location", 
-	     sbcl_to_phase(sbcl));
-	print_lots (host);
-    /* Fall through to ACTION_ABORT */
-    case ACTION_ABORT:
-	abort_connected (host);
-	break;
-    case ACTION_CONTINUE:
-	break;
-    }
-
-#if 0
-    if (hostdata->dsp_changed) {
-	printk("scsi%d: new dsp 0x%p\n", host->host_no, hostdata->dsp);
-	print_insn (host, hostdata->dsp, "", 1);
-    }
-#endif
-}
-
-/*
- * Function : static void intr_bf (struct Scsi_Host *host, 
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : handle BUS FAULT interrupts 
- *
- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
- * 	may be NULL.
- */
-
-static void
-intr_bf (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    u32 *dsp,
-	*next_dsp,		/* Current dsp */
-    	*dsa,
-	dbc_dcmd;		/* DCMD (high eight bits) + DBC */
-    char *reason = NULL;
-    /* Default behavior is for a silent error, with a retry until we've
-       exhausted retries. */
-    enum {MAYBE, ALWAYS, NEVER} retry = MAYBE;
-    int report = 0;
-    NCR53c7x0_local_setup(host);
-
-    dbc_dcmd = NCR53c7x0_read32 (DBC_REG);
-    next_dsp = bus_to_virt (NCR53c7x0_read32(DSP_REG));
-    dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff);
-/* FIXME - check chip type  */
-    dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG));
-
-    /*
-     * Bus faults can be caused by either a Bad Address or 
-     * Target Abort. We should check the Received Target Abort
-     * bit of the PCI status register and Master Abort Bit.
-     *
-     * 	- Master Abort bit indicates that no device claimed
-     *		the address with DEVSEL within five clocks
-     *
-     *	- Target Abort bit indicates that a target claimed it,
-     *		but changed its mind once it saw the byte enables.
-     *
-     */
-
-    /* 53c710, not PCI system */
-    report = 1;
-    reason = "Unknown";
-
-#ifndef notyet
-    report = 1;
-#endif
-    if (report && reason)
-    {
-	printk(KERN_ALERT "scsi%d : BUS FAULT reason = %s\n",
-	     host->host_no, reason ? reason : "unknown");
-	print_lots (host);
-    }
-
-#ifndef notyet
-    retry = NEVER;
-#endif
-
-    /* 
-     * TODO : we should attempt to recover from any spurious bus 
-     * faults.  After X retries, we should figure that things are 
-     * sufficiently wedged, and call NCR53c7xx_reset.
-     *
-     * This code should only get executed once we've decided that we 
-     * cannot retry.
-     */
-
-    if (retry == NEVER) {
-    	printk(KERN_ALERT "          mail richard@sleepie.demon.co.uk\n");
-    	FATAL (host);
-    }
-}
-
-/*
- * Function : static void intr_dma (struct Scsi_Host *host, 
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : handle all DMA interrupts, indicated by the setting 
- * 	of the DIP bit in the ISTAT register.
- *
- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
- * 	may be NULL.
- */
-
-static void 
-intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned char dstat;	/* DSTAT */	
-    u32 *dsp,
-	*next_dsp,		/* Current dsp */
-    	*dsa,
-	dbc_dcmd;		/* DCMD (high eight bits) + DBC */
-    int tmp;
-    unsigned long flags;
-    NCR53c7x0_local_setup(host);
-
-    if (!hostdata->dstat_valid) {
-	hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-	hostdata->dstat_valid = 1;
-    }
-    
-    dstat = hostdata->dstat;
-    
-    if (hostdata->options & OPTION_DEBUG_INTR)
-	printk("scsi%d : DSTAT=0x%x\n", host->host_no, (int) dstat);
-
-    dbc_dcmd = NCR53c7x0_read32 (DBC_REG);
-    next_dsp = bus_to_virt(NCR53c7x0_read32(DSP_REG));
-    dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff);
-/* XXX - check chip type */
-    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-
-    /*
-     * DSTAT_ABRT is the aborted interrupt.  This is set whenever the 
-     * SCSI chip is aborted.  
-     * 
-     * With NCR53c700 and NCR53c700-66 style chips, we should only 
-     * get this when the chip is currently running the accept 
-     * reselect/select code and we have set the abort bit in the 
-     * ISTAT register.
-     *
-     */
-    
-    if (dstat & DSTAT_ABRT) {
-#if 0
-	/* XXX - add code here to deal with normal abort */
-	if ((hostdata->options & OPTION_700) && (hostdata->state ==
-	    STATE_ABORTING)) {
-	} else 
-#endif
-	{
-	    printk(KERN_ALERT "scsi%d : unexpected abort interrupt at\n" 
-		   "         ", host->host_no);
-	    print_insn (host, dsp, KERN_ALERT "s ", 1);
-	    FATAL (host);
-	}
-    }
-
-    /*
-     * DSTAT_SSI is the single step interrupt.  Should be generated 
-     * whenever we have single stepped or are tracing.
-     */
-
-    if (dstat & DSTAT_SSI) {
-	if (hostdata->options & OPTION_DEBUG_TRACE) {
-	    /* Don't print instr. until we write DSP at end of intr function */
-	} else if (hostdata->options & OPTION_DEBUG_SINGLE) {
-	    print_insn (host, dsp, "s ", 0);
-	    local_irq_save(flags);
-/* XXX - should we do this, or can we get away with writing dsp? */
-
-	    NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) & 
-    	    	~DCNTL_SSM) | DCNTL_STD);
-	    local_irq_restore(flags);
-	} else {
-	    printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n"
-		   "         ", host->host_no);
-	    print_insn (host, dsp, KERN_ALERT "", 1);
-	    printk(KERN_ALERT "         mail drew@PoohSticks.ORG\n");
-    	    FATAL (host);
-    	}
-    }
-
-    /*
-     * DSTAT_IID / DSTAT_OPC (same bit, same meaning, only the name 
-     * is different) is generated whenever an illegal instruction is 
-     * encountered.  
-     * 
-     * XXX - we may want to emulate INTFLY here, so we can use 
-     *    the same SCSI SCRIPT (tm) for NCR53c710 through NCR53c810  
-     *	  chips.
-     */
-
-    if (dstat & DSTAT_OPC) {
-    /* 
-     * Ascertain if this IID interrupts occurred before or after a STO 
-     * interrupt.  Since the interrupt handling code now leaves 
-     * DSP unmodified until _after_ all stacked interrupts have been
-     * processed, reading the DSP returns the original DSP register.
-     * This means that if dsp lies between the select code, and 
-     * message out following the selection code (where the IID interrupt
-     * would have to have occurred by due to the implicit wait for REQ),
-     * we have an IID interrupt resulting from a STO condition and 
-     * can ignore it.
-     */
-
-	if (((dsp >= (hostdata->script + hostdata->E_select / sizeof(u32))) &&
-	    (dsp <= (hostdata->script + hostdata->E_select_msgout / 
-    	    sizeof(u32) + 8))) || (hostdata->test_running == 2)) {
-	    if (hostdata->options & OPTION_DEBUG_INTR) 
-		printk ("scsi%d : ignoring DSTAT_IID for SSTAT_STO\n",
-		    host->host_no);
-	    if (hostdata->expecting_iid) {
-		hostdata->expecting_iid = 0;
-		hostdata->idle = 1;
-		if (hostdata->test_running == 2) {
-		    hostdata->test_running = 0;
-		    hostdata->test_completed = 3;
-		} else if (cmd) 
-			abnormal_finished (cmd, DID_BAD_TARGET << 16);
-	    } else {
-		hostdata->expecting_sto = 1;
-	    }
-    /*
-     * We can't guarantee we'll be able to execute the WAIT DISCONNECT
-     * instruction within the 3.4us of bus free and arbitration delay
-     * that a target can RESELECT in and assert REQ after we've dropped
-     * ACK.  If this happens, we'll get an illegal instruction interrupt.
-     * Doing away with the WAIT DISCONNECT instructions broke everything,
-     * so instead I'll settle for moving one WAIT DISCONNECT a few 
-     * instructions closer to the CLEAR ACK before it to minimize the
-     * chances of this happening, and handle it if it occurs anyway.
-     *
-     * Simply continue with what we were doing, and control should
-     * be transferred to the schedule routine which will ultimately
-     * pass control onto the reselection or selection (not yet)
-     * code.
-     */
-	} else if (dbc_dcmd == 0x48000000 && (NCR53c7x0_read8 (SBCL_REG) &
-	    SBCL_REQ)) {
-	    if (!(hostdata->options & OPTION_NO_PRINT_RACE))
-	    {
-		printk("scsi%d: REQ before WAIT DISCONNECT IID\n", 
-		    host->host_no);
-		hostdata->options |= OPTION_NO_PRINT_RACE;
-	    }
-	} else {
-	    printk(KERN_ALERT "scsi%d : invalid instruction\n", host->host_no);
-	    print_lots (host);
-	    printk(KERN_ALERT "         mail Richard@sleepie.demon.co.uk with ALL\n"
-		              "         boot messages and diagnostic output\n");
-    	    FATAL (host);
-	}
-    }
-
-    /* 
-     * DSTAT_BF are bus fault errors.  DSTAT_800_BF is valid for 710 also.
-     */
-    
-    if (dstat & DSTAT_800_BF) {
-	intr_bf (host, cmd);
-    }
-	
-
-    /* 
-     * DSTAT_SIR interrupts are generated by the execution of 
-     * the INT instruction.  Since the exact values available 
-     * are determined entirely by the SCSI script running, 
-     * and are local to a particular script, a unique handler
-     * is called for each script.
-     */
-
-    if (dstat & DSTAT_SIR) {
-	if (hostdata->options & OPTION_DEBUG_INTR)
-	    printk ("scsi%d : DSTAT_SIR\n", host->host_no);
-	switch ((tmp = hostdata->dstat_sir_intr (host, cmd))) {
-	case SPECIFIC_INT_NOTHING:
-	case SPECIFIC_INT_RESTART:
-	    break;
-	case SPECIFIC_INT_ABORT:
-	    abort_connected(host);
-	    break;
-	case SPECIFIC_INT_PANIC:
-	    printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
-	    print_insn (host, dsp, KERN_ALERT "", 1);
-	    printk(KERN_ALERT "          dstat_sir_intr() returned SPECIFIC_INT_PANIC\n");
-    	    FATAL (host);
-	    break;
-	case SPECIFIC_INT_BREAK:
-	    intr_break (host, cmd);
-	    break;
-	default:
-	    printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
-	    print_insn (host, dsp, KERN_ALERT "", 1);
-	    printk(KERN_ALERT"          dstat_sir_intr() returned unknown value %d\n", 
-		tmp);
-    	    FATAL (host);
-	}
-    } 
-}
-
-/*
- * Function : static int print_insn (struct Scsi_Host *host, 
- * 	u32 *insn, int kernel)
- *
- * Purpose : print numeric representation of the instruction pointed
- * 	to by insn to the debugging or kernel message buffer
- *	as appropriate.  
- *
- * 	If desired, a user level program can interpret this 
- * 	information.
- *
- * Inputs : host, insn - host, pointer to instruction, prefix - 
- *	string to prepend, kernel - use printk instead of debugging buffer.
- *
- * Returns : size, in u32s, of instruction printed.
- */
-
-/*
- * FIXME: should change kernel parameter so that it takes an ENUM
- * 	specifying severity - either KERN_ALERT or KERN_PANIC so
- *	all panic messages are output with the same severity.
- */
-
-static int 
-print_insn (struct Scsi_Host *host, const u32 *insn, 
-    const char *prefix, int kernel) {
-    char buf[160], 		/* Temporary buffer and pointer.  ICKY 
-				   arbitrary length.  */
-
-		
-	*tmp;			
-    unsigned char dcmd;		/* dcmd register for *insn */
-    int size;
-
-    /* 
-     * Check to see if the instruction pointer is not bogus before 
-     * indirecting through it; avoiding red-zone at start of 
-     * memory.
-     *
-     * FIXME: icky magic needs to happen here on non-intel boxes which
-     * don't have kernel memory mapped in like this.  Might be reasonable
-     * to use vverify()?
-     */
-
-    if (virt_to_phys((void *)insn) < PAGE_SIZE || 
-	virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) ||
-	((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) &&
-	virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) {
-	size = 0;
-	sprintf (buf, "%s%p: address out of range\n",
-	    prefix, insn);
-    } else {
-/* 
- * FIXME : (void *) cast in virt_to_bus should be unnecessary, because
- * 	it should take const void * as argument.
- */
-#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
-	sprintf(buf, "%s0x%lx (virt 0x%p) : 0x%08x 0x%08x (virt 0x%p)", 
-	    (prefix ? prefix : ""), virt_to_bus((void *) insn), insn,  
-	    insn[0], insn[1], bus_to_virt (insn[1]));
-#else
-	/* Remove virtual addresses to reduce output, as they are the same */
-	sprintf(buf, "%s0x%x (+%x) : 0x%08x 0x%08x", 
-	    (prefix ? prefix : ""), (u32)insn, ((u32)insn -
-		(u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4, 
-	    insn[0], insn[1]);
-#endif
-	tmp = buf + strlen(buf);
-	if ((dcmd & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)  {
-#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
-	    sprintf (tmp, " 0x%08x (virt 0x%p)\n", insn[2], 
-		bus_to_virt(insn[2]));
-#else
-	    /* Remove virtual addr to reduce output, as it is the same */
-	    sprintf (tmp, " 0x%08x\n", insn[2]);
-#endif
-	    size = 3;
-	} else {
-	    sprintf (tmp, "\n");
-	    size = 2;
-	}
-    }
-
-    if (kernel) 
-	printk ("%s", buf);
-#ifdef NCR_DEBUG
-    else {
-	size_t len = strlen(buf);
-	debugger_kernel_write(host, buf, len);
-    }
-#endif
-    return size;
-}
-
-/*
- * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd)
- * 
- * Purpose : Abort an errant SCSI command, doing all necessary
- *	cleanup of the issue_queue, running_list, shared Linux/NCR
- *	dsa issue and reconnect queues.
- *
- * Inputs : cmd - command to abort, code - entire result field
- *
- * Returns : 0 on success, -1 on failure.
- */
-
-int 
-NCR53c7xx_abort (Scsi_Cmnd *cmd) {
-    NCR53c7x0_local_declare();
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) 
-	host->hostdata[0] : NULL;
-    unsigned long flags;
-    struct NCR53c7x0_cmd *curr, **prev;
-    Scsi_Cmnd *me, **last;
-#if 0
-    static long cache_pid = -1;
-#endif
-
-
-    if (!host) {
-	printk ("Bogus SCSI command pid %ld; no host structure\n",
-	    cmd->pid);
-	return SCSI_ABORT_ERROR;
-    } else if (!hostdata) {
-	printk ("Bogus SCSI host %d; no hostdata\n", host->host_no);
-	return SCSI_ABORT_ERROR;
-    }
-    NCR53c7x0_local_setup(host);
-
-/*
- * CHECK : I don't think that reading ISTAT will unstack any interrupts,
- *	since we need to write the INTF bit to clear it, and SCSI/DMA
- * 	interrupts don't clear until we read SSTAT/SIST and DSTAT registers.
- *	
- *	See that this is the case.  Appears to be correct on the 710, at least.
- *
- * I suspect that several of our failures may be coming from a new fatal
- * interrupt (possibly due to a phase mismatch) happening after we've left
- * the interrupt handler, but before the PIC has had the interrupt condition
- * cleared.
- */
-
-    if (NCR53c7x0_read8(hostdata->istat) & (ISTAT_DIP|ISTAT_SIP)) {
-	printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no,
-	    cmd->pid);
-	NCR53c7x0_intr (host->irq, NULL, NULL);
-	return SCSI_ABORT_BUSY;
-    }
-	
-    local_irq_save(flags);
-#if 0
-    if (cache_pid == cmd->pid) 
-	panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid);
-    else
-	cache_pid = cmd->pid;
-#endif
-	
-
-/*
- * The command could be hiding in the issue_queue.  This would be very
- * nice, as commands can't be moved from the high level driver's issue queue 
- * into the shared queue until an interrupt routine is serviced, and this
- * moving is atomic.  
- *
- * If this is the case, we don't have to worry about anything - we simply
- * pull the command out of the old queue, and call it aborted.
- */
-
-    for (me = (Scsi_Cmnd *) hostdata->issue_queue, 
-         last = (Scsi_Cmnd **) &(hostdata->issue_queue);
-	 me && me != cmd;  last = (Scsi_Cmnd **)&(me->SCp.ptr), 
-	 me = (Scsi_Cmnd *)me->SCp.ptr);
-
-    if (me) {
-	*last = (Scsi_Cmnd *) me->SCp.ptr;
-	if (me->host_scribble) {
-	    ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free;
-	    hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble;
-	    me->host_scribble = NULL;
-	}
-	cmd->result = DID_ABORT << 16;
-	cmd->scsi_done(cmd);
-	printk ("scsi%d : found command %ld in Linux issue queue\n", 
-	    host->host_no, me->pid);
-	local_irq_restore(flags);
-    	run_process_issue_queue();
-	return SCSI_ABORT_SUCCESS;
-    }
-
-/* 
- * That failing, the command could be in our list of already executing 
- * commands.  If this is the case, drastic measures are called for.  
- */ 
-
-    for (curr = (struct NCR53c7x0_cmd *) hostdata->running_list, 
-    	 prev = (struct NCR53c7x0_cmd **) &(hostdata->running_list);
-	 curr && curr->cmd != cmd; prev = (struct NCR53c7x0_cmd **) 
-         &(curr->next), curr = (struct NCR53c7x0_cmd *) curr->next);
-
-    if (curr) {
-	if ((curr->result & 0xff) != 0xff && (curr->result & 0xff00) != 0xff00) {
-            cmd->result = curr->result;
-	    if (prev)
-		*prev = (struct NCR53c7x0_cmd *) curr->next;
-	    curr->next = (struct NCR53c7x0_cmd *) hostdata->free;
-	    cmd->host_scribble = NULL;
-	    hostdata->free = curr;
-	    cmd->scsi_done(cmd);
-	printk ("scsi%d : found finished command %ld in running list\n", 
-	    host->host_no, cmd->pid);
-	    local_irq_restore(flags);
-	    return SCSI_ABORT_NOT_RUNNING;
-	} else {
-	    printk ("scsi%d : DANGER : command running, can not abort.\n",
-		cmd->device->host->host_no);
-	    local_irq_restore(flags);
-	    return SCSI_ABORT_BUSY;
-	}
-    }
-
-/* 
- * And if we couldn't find it in any of our queues, it must have been 
- * a dropped interrupt.
- */
-
-    curr = (struct NCR53c7x0_cmd *) cmd->host_scribble;
-    if (curr) {
-	curr->next = hostdata->free;
-	hostdata->free = curr;
-	cmd->host_scribble = NULL;
-    }
-
-    if (curr == NULL || ((curr->result & 0xff00) == 0xff00) ||
-		((curr->result & 0xff) == 0xff)) {
-	printk ("scsi%d : did this command ever run?\n", host->host_no);
-	    cmd->result = DID_ABORT << 16;
-    } else {
-	printk ("scsi%d : probably lost INTFLY, normal completion\n", 
-	    host->host_no);
-        cmd->result = curr->result;
-/* 
- * FIXME : We need to add an additional flag which indicates if a 
- * command was ever counted as BUSY, so if we end up here we can
- * decrement the busy count if and only if it is necessary.
- */
-        --hostdata->busy[cmd->device->id][cmd->device->lun];
-    }
-    local_irq_restore(flags);
-    cmd->scsi_done(cmd);
-
-/* 
- * We need to run process_issue_queue since termination of this command 
- * may allow another queued command to execute first? 
- */
-    return SCSI_ABORT_NOT_RUNNING;
-}
-
-/*
- * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd) 
- * 
- * Purpose : perform a hard reset of the SCSI bus and NCR
- * 	chip.
- *
- * Inputs : cmd - command which caused the SCSI RESET
- *
- * Returns : 0 on success.
- */
- 
-int 
-NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    int found = 0;
-    struct NCR53c7x0_cmd * c;
-    Scsi_Cmnd *tmp;
-    /*
-     * When we call scsi_done(), it's going to wake up anything sleeping on the
-     * resources which were in use by the aborted commands, and we'll start to 
-     * get new commands.
-     *
-     * We can't let this happen until after we've re-initialized the driver
-     * structures, and can't reinitialize those structures until after we've 
-     * dealt with their contents.
-     *
-     * So, we need to find all of the commands which were running, stick
-     * them on a linked list of completed commands (we'll use the host_scribble
-     * pointer), do our reinitialization, and then call the done function for
-     * each command.  
-     */
-    Scsi_Cmnd *nuke_list = NULL;
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = 
-    	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-
-    NCR53c7x0_local_setup(host);
-    local_irq_save(flags);
-    ncr_halt (host);
-    print_lots (host);
-    dump_events (host, 30);
-    ncr_scsi_reset (host);
-    for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */,
-	0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer)
-	if (tmp == cmd) {
-	    found = 1;
-	    break;
-	}
-	    
-    /* 
-     * If we didn't find the command which caused this reset in our running
-     * list, then we've lost it.  See that it terminates normally anyway.
-     */
-    if (!found) {
-    	c = (struct NCR53c7x0_cmd *) cmd->host_scribble;
-    	if (c) {
-	    cmd->host_scribble = NULL;
-    	    c->next = hostdata->free;
-    	    hostdata->free = c;
-    	} else
-	    printk ("scsi%d: lost command %ld\n", host->host_no, cmd->pid);
-	cmd->SCp.buffer = (struct scatterlist *) nuke_list;
-	nuke_list = cmd;
-    }
-
-    NCR53c7x0_driver_init (host);
-    hostdata->soft_reset (host);
-    if (hostdata->resets == 0) 
-	disable(host);
-    else if (hostdata->resets != -1)
-	--hostdata->resets;
-    local_irq_restore(flags);
-    for (; nuke_list; nuke_list = tmp) {
-	tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
-    	nuke_list->result = DID_RESET << 16;
-	nuke_list->scsi_done (nuke_list);
-    }
-    local_irq_restore(flags);
-    return SCSI_RESET_SUCCESS;
-}
-
-/*
- * The NCR SDMS bios follows Annex A of the SCSI-CAM draft, and 
- * therefore shares the scsicam_bios_param function.
- */
-
-/*
- * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn)
- *
- * Purpose : convert instructions stored at NCR pointer into data 
- *	pointer offset.
- * 
- * Inputs : cmd - SCSI command; insn - pointer to instruction.  Either current
- *	DSP, or saved data pointer.
- *
- * Returns : offset on success, -1 on failure.
- */
-
-
-static int 
-insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0];
-    struct NCR53c7x0_cmd *ncmd = 
-	(struct NCR53c7x0_cmd *) cmd->host_scribble;
-    int offset = 0, buffers;
-    struct scatterlist *segment;
-    char *ptr;
-    int found = 0;
-
-/*
- * With the current code implementation, if the insn is inside dynamically 
- * generated code, the data pointer will be the instruction preceding 
- * the next transfer segment.
- */
-
-    if (!check_address ((unsigned long) ncmd, sizeof (struct NCR53c7x0_cmd)) &&
-	((insn >= ncmd->data_transfer_start &&  
-    	    insn < ncmd->data_transfer_end) ||
-    	(insn >= ncmd->residual &&
-    	    insn < (ncmd->residual + 
-    	    	sizeof(ncmd->residual))))) {
-	    ptr = bus_to_virt(insn[3]);
-
-	    if ((buffers = cmd->use_sg)) {
-    	    	for (offset = 0, 
-		     	segment = (struct scatterlist *) cmd->request_buffer;
-    	    	     buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) && 
-    	    	    	    (ptr < ((char *)page_address(segment->page)+segment->offset+segment->length)))));
-    	    	     --buffers, offset += segment->length, ++segment)
-#if 0
-		    printk("scsi%d: comparing 0x%p to 0x%p\n", 
-			cmd->device->host->host_no, saved, page_address(segment->page+segment->offset));
-#else
-		    ;
-#endif
-    	    	    offset += ptr - ((char *)page_address(segment->page)+segment->offset);
-    	    } else {
-		found = 1;
-    	    	offset = ptr - (char *) (cmd->request_buffer);
-    	    }
-    } else if ((insn >= hostdata->script + 
-		hostdata->E_data_transfer / sizeof(u32)) &&
-	       (insn <= hostdata->script +
-		hostdata->E_end_data_transfer / sizeof(u32))) {
-    	found = 1;
-	offset = 0;
-    }
-    return found ? offset : -1;
-}
-
-
-
-/*
- * Function : void print_progress (Scsi_Cmnd *cmd) 
- * 
- * Purpose : print the current location of the saved data pointer
- *
- * Inputs : cmd - command we are interested in
- *
- */
-
-static void 
-print_progress (Scsi_Cmnd *cmd) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_cmd *ncmd = 
-	(struct NCR53c7x0_cmd *) cmd->host_scribble;
-    int offset, i;
-    char *where;
-    u32 *ptr;
-    NCR53c7x0_local_setup (cmd->device->host);
-
-    if (check_address ((unsigned long) ncmd,sizeof (struct NCR53c7x0_cmd)) == 0)
-    {
-	printk("\nNCR53c7x0_cmd fields:\n");
-	printk("  bounce.len=0x%x, addr=0x%0x, buf[]=0x%02x %02x %02x %02x\n",
-	    ncmd->bounce.len, ncmd->bounce.addr, ncmd->bounce.buf[0],
-	    ncmd->bounce.buf[1], ncmd->bounce.buf[2], ncmd->bounce.buf[3]);
-	printk("  result=%04x, cdb[0]=0x%02x\n", ncmd->result, ncmd->cmnd[0]);
-    }
-
-    for (i = 0; i < 2; ++i) {
-	if (check_address ((unsigned long) ncmd, 
-	    sizeof (struct NCR53c7x0_cmd)) == -1) 
-	    continue;
-	if (!i) {
-	    where = "saved";
-	    ptr = bus_to_virt(ncmd->saved_data_pointer);
-	} else {
-	    where = "active";
-	    ptr = bus_to_virt (NCR53c7x0_read32 (DSP_REG) -
-		NCR53c7x0_insn_size (NCR53c7x0_read8 (DCMD_REG)) *
-		sizeof(u32));
-	} 
-	offset = insn_to_offset (cmd, ptr);
-
-	if (offset != -1) 
-	    printk ("scsi%d : %s data pointer at offset %d\n",
-		cmd->device->host->host_no, where, offset);
-	else {
-	    int size;
-	    printk ("scsi%d : can't determine %s data pointer offset\n",
-		cmd->device->host->host_no, where);
-	    if (ncmd) {
-		size = print_insn (cmd->device->host,
-		    bus_to_virt(ncmd->saved_data_pointer), "", 1);
-		print_insn (cmd->device->host,
-		    bus_to_virt(ncmd->saved_data_pointer) + size * sizeof(u32),
-		    "", 1);
-	    }
-	}
-    }
-}
-
-
-static void 
-print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    int i, len;
-    char *ptr;
-    Scsi_Cmnd *cmd;
-
-    if (check_address ((unsigned long) dsa, hostdata->dsa_end - 
-	hostdata->dsa_start) == -1) {
-	printk("scsi%d : bad dsa virt 0x%p\n", host->host_no, dsa);
-	return;
-    }
-    printk("%sscsi%d : dsa at phys 0x%lx (virt 0x%p)\n"
-	    "        + %d : dsa_msgout length = %u, data = 0x%x (virt 0x%p)\n" ,
-    	    prefix ? prefix : "",
-    	    host->host_no,  virt_to_bus (dsa), dsa, hostdata->dsa_msgout,
-    	    dsa[hostdata->dsa_msgout / sizeof(u32)],
-	    dsa[hostdata->dsa_msgout / sizeof(u32) + 1],
-	    bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]));
-
-    /* 
-     * Only print messages if they're sane in length so we don't
-     * blow the kernel printk buffer on something which won't buy us
-     * anything.
-     */
-
-    if (dsa[hostdata->dsa_msgout / sizeof(u32)] < 
-	    sizeof (hostdata->free->select)) 
-	for (i = dsa[hostdata->dsa_msgout / sizeof(u32)],
-	    ptr = bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]); 
-	    i > 0 && !check_address ((unsigned long) ptr, 1);
-	    ptr += len, i -= len) {
-	    printk("               ");
-	    len = spi_print_msg(ptr);
-	    printk("\n");
-	    if (!len)
-		break;
-	}
-
-    printk("        + %d : select_indirect = 0x%x\n",
-	hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]);
-    cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]);
-    printk("        + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd,
-	   (u32) virt_to_bus(cmd));
-    /* XXX Maybe we should access cmd->host_scribble->result here. RGH */
-    if (cmd) {
-	printk("               result = 0x%x, target = %d, lun = %d, cmd = ",
-	    cmd->result, cmd->device->id, cmd->device->lun);
-	__scsi_print_command(cmd->cmnd);
-    } else
-	printk("\n");
-    printk("        + %d : dsa_next = 0x%x\n", hostdata->dsa_next,
-	dsa[hostdata->dsa_next / sizeof(u32)]);
-    if (cmd) { 
-	printk("scsi%d target %d : sxfer_sanity = 0x%x, scntl3_sanity = 0x%x\n"
-	       "                   script : ",
-	    host->host_no, cmd->device->id,
-	    hostdata->sync[cmd->device->id].sxfer_sanity,
-	    hostdata->sync[cmd->device->id].scntl3_sanity);
-	for (i = 0; i < (sizeof(hostdata->sync[cmd->device->id].script) / 4); ++i)
-	    printk ("0x%x ", hostdata->sync[cmd->device->id].script[i]);
-	printk ("\n");
-    	print_progress (cmd);
-    }
-}
-/*
- * Function : void print_queues (Scsi_Host *host) 
- * 
- * Purpose : print the contents of the NCR issue and reconnect queues
- *
- * Inputs : host - SCSI host we are interested in
- *
- */
-
-static void 
-print_queues (struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    u32 *dsa, *next_dsa;
-    volatile u32 *ncrcurrent;
-    int left;
-    Scsi_Cmnd *cmd, *next_cmd;
-    unsigned long flags;
-
-    printk ("scsi%d : issue queue\n", host->host_no);
-
-    for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue; 
-	    left >= 0 && cmd; 
-	    cmd = next_cmd) {
-	next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr;
-	local_irq_save(flags);
-	if (cmd->host_scribble) {
-	    if (check_address ((unsigned long) (cmd->host_scribble), 
-		sizeof (cmd->host_scribble)) == -1)
-		printk ("scsi%d: scsi pid %ld bad pointer to NCR53c7x0_cmd\n",
-		    host->host_no, cmd->pid);
-	    /* print_dsa does sanity check on address, no need to check */
-	    else
-	    	print_dsa (host, ((struct NCR53c7x0_cmd *) cmd->host_scribble)
-		    -> dsa, "");
-	} else 
-	    printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n",
-		host->host_no, cmd->pid, cmd->device->id, cmd->device->lun);
-	local_irq_restore(flags);
-    }
-
-    if (left <= 0) {
-	printk ("scsi%d : loop detected in issue queue\n",
-	    host->host_no);
-    }
-
-    /*
-     * Traverse the NCR reconnect and start DSA structures, printing out 
-     * each element until we hit the end or detect a loop.  Currently,
-     * the reconnect structure is a linked list; and the start structure
-     * is an array.  Eventually, the reconnect structure will become a 
-     * list as well, since this simplifies the code.
-     */
-
-    printk ("scsi%d : schedule dsa array :\n", host->host_no);
-    for (left = host->can_queue, ncrcurrent = hostdata->schedule;
-	    left > 0; ncrcurrent += 2, --left)
-	if (ncrcurrent[0] != hostdata->NOP_insn) 
-/* FIXME : convert pointer to dsa_begin to pointer to dsa. */
-	    print_dsa (host, bus_to_virt (ncrcurrent[1] - 
-		(hostdata->E_dsa_code_begin - 
-		hostdata->E_dsa_code_template)), "");
-    printk ("scsi%d : end schedule dsa array\n", host->host_no);
-    
-    printk ("scsi%d : reconnect_dsa_head :\n", host->host_no);
-	    
-    for (left = host->can_queue, 
-	dsa = bus_to_virt (hostdata->reconnect_dsa_head);
-	left >= 0 && dsa; 
-	dsa = next_dsa) {
-	local_irq_save(flags);
-	if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) {
-	    printk ("scsi%d: bad DSA pointer 0x%p", host->host_no,
-		dsa);
-	    next_dsa = NULL;
-	}
-	else 
-	{
-	    next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]);
-	    print_dsa (host, dsa, "");
-	}
-	local_irq_restore(flags);
-    }
-    printk ("scsi%d : end reconnect_dsa_head\n", host->host_no);
-    if (left < 0)
-	printk("scsi%d: possible loop in ncr reconnect list\n",
-	    host->host_no);
-}
-
-static void
-print_lots (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    u32 *dsp_next, *dsp, *dsa, dbc_dcmd;
-    unsigned char dcmd, sbcl;
-    int i, size;
-    NCR53c7x0_local_setup(host);
-
-    if ((dsp_next = bus_to_virt(NCR53c7x0_read32 (DSP_REG)))) {
-    	dbc_dcmd = NCR53c7x0_read32(DBC_REG);
-    	dcmd = (dbc_dcmd & 0xff000000) >> 24;
-    	dsp = dsp_next - NCR53c7x0_insn_size(dcmd);
-	dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-	sbcl = NCR53c7x0_read8 (SBCL_REG);
-	    
-	/*
-	 * For the 53c710, the following will report value 0 for SCNTL3
-	 * and STEST0 - we don't have these registers.
-	 */
-    	printk ("scsi%d : DCMD|DBC=0x%x, DNAD=0x%x (virt 0x%p)\n"
-		"         DSA=0x%lx (virt 0x%p)\n"
-	        "         DSPS=0x%x, TEMP=0x%x (virt 0x%p), DMODE=0x%x\n"
-		"         SXFER=0x%x, SCNTL3=0x%x\n"
-		"         %s%s%sphase=%s, %d bytes in SCSI FIFO\n"
-		"         SCRATCH=0x%x, saved2_dsa=0x%0lx\n",
-	    host->host_no, dbc_dcmd, NCR53c7x0_read32(DNAD_REG),
-		bus_to_virt(NCR53c7x0_read32(DNAD_REG)),
-	    virt_to_bus(dsa), dsa,
-	    NCR53c7x0_read32(DSPS_REG), NCR53c7x0_read32(TEMP_REG), 
-	    bus_to_virt (NCR53c7x0_read32(TEMP_REG)),
-	    (int) NCR53c7x0_read8(hostdata->dmode),
-	    (int) NCR53c7x0_read8(SXFER_REG), 
-	    ((hostdata->chip / 100) == 8) ?
-		(int) NCR53c7x0_read8(SCNTL3_REG_800) : 0,
-	    (sbcl & SBCL_BSY) ? "BSY " : "",
-	    (sbcl & SBCL_SEL) ? "SEL " : "",
-	    (sbcl & SBCL_REQ) ? "REQ " : "",
-	    sstat2_to_phase(NCR53c7x0_read8 (((hostdata->chip / 100) == 8) ?
-	    	SSTAT1_REG : SSTAT2_REG)),
-	    (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? 
-		SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT,
-	    ((hostdata->chip / 100) == 8) ? NCR53c7x0_read8 (STEST0_REG_800) :
-		NCR53c7x0_read32(SCRATCHA_REG_800),
-	    hostdata->saved2_dsa);
-	printk ("scsi%d : DSP 0x%lx (virt 0x%p) ->\n", host->host_no, 
-	    virt_to_bus(dsp), dsp);
-    	for (i = 6; i > 0; --i, dsp += size)
-	    size = print_insn (host, dsp, "", 1);
-	if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON)  {
-	    if ((hostdata->chip / 100) == 8)
-	        printk ("scsi%d : connected (SDID=0x%x, SSID=0x%x)\n",
-		    host->host_no, NCR53c7x0_read8 (SDID_REG_800),
-		    NCR53c7x0_read8 (SSID_REG_800));
-	    else
-		printk ("scsi%d : connected (SDID=0x%x)\n",
-		    host->host_no, NCR53c7x0_read8 (SDID_REG_700));
-	    print_dsa (host, dsa, "");
-	}
-
-#if 1
-	print_queues (host);
-#endif
-    }
-}
-
-/*
- * Function : static int shutdown (struct Scsi_Host *host)
- * 
- * Purpose : does a clean (we hope) shutdown of the NCR SCSI 
- *	chip.  Use prior to dumping core, unloading the NCR driver,
- * 
- * Returns : 0 on success
- */
-static int 
-shutdown (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-    local_irq_save(flags);
-/* Get in a state where we can reset the SCSI bus */
-    ncr_halt (host);
-    ncr_scsi_reset (host);
-    hostdata->soft_reset(host);
-
-    disable (host);
-    local_irq_restore(flags);
-    return 0;
-}
-
-/*
- * Function : void ncr_scsi_reset (struct Scsi_Host *host)
- *
- * Purpose : reset the SCSI bus.
- */
-
-static void 
-ncr_scsi_reset (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    NCR53c7x0_local_setup(host);
-    local_irq_save(flags);
-    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
-    udelay(25);	/* Minimum amount of time to assert RST */
-    NCR53c7x0_write8(SCNTL1_REG, 0);
-    local_irq_restore(flags);
-}
-
-/* 
- * Function : void hard_reset (struct Scsi_Host *host)
- *
- */
-
-static void 
-hard_reset (struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned long flags;
-    local_irq_save(flags);
-    ncr_scsi_reset(host);
-    NCR53c7x0_driver_init (host);
-    if (hostdata->soft_reset)
-	hostdata->soft_reset (host);
-    local_irq_restore(flags);
-}
-
-
-/*
- * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host,
- *	int free, int issue)
- *
- * Purpose : return a linked list (using the SCp.buffer field as next,
- *	so we don't perturb hostdata.  We don't use a field of the 
- *	NCR53c7x0_cmd structure since we may not have allocated one 
- *	for the command causing the reset.) of Scsi_Cmnd structures that 
- *  	had propagated below the Linux issue queue level.  If free is set, 
- *	free the NCR53c7x0_cmd structures which are associated with 
- *	the Scsi_Cmnd structures, and clean up any internal 
- *	NCR lists that the commands were on.  If issue is set,
- *	also return commands in the issue queue.
- *
- * Returns : linked list of commands
- *
- * NOTE : the caller should insure that the NCR chip is halted
- *	if the free flag is set. 
- */
-
-static Scsi_Cmnd *
-return_outstanding_commands (struct Scsi_Host *host, int free, int issue) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    struct NCR53c7x0_cmd *c;
-    int i;
-    u32 *ncrcurrent;
-    Scsi_Cmnd *list = NULL, *tmp;
-    for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c; 
-    	c = (struct NCR53c7x0_cmd *) c->next)  {
-	if (c->cmd->SCp.buffer) {
-	    printk ("scsi%d : loop detected in running list!\n", host->host_no);
-	    break;
-	} else {
-	    printk ("Duh? Bad things happening in the NCR driver\n");
-	    break;
-	}
-
-	c->cmd->SCp.buffer = (struct scatterlist *) list;
-	list = c->cmd;
-	if (free) {
-    	    c->next = hostdata->free;
-    	    hostdata->free = c;
-	}
-    }
-
-    if (free) { 
-	for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 
-	    i < host->can_queue; ++i, ncrcurrent += 2) {
-	    ncrcurrent[0] = hostdata->NOP_insn;
-	    ncrcurrent[1] = 0xdeadbeef;
-	}
-	hostdata->ncrcurrent = NULL;
-    }
-
-    if (issue) {
-	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) {
-	    if (tmp->SCp.buffer) {
-		printk ("scsi%d : loop detected in issue queue!\n", 
-			host->host_no);
-		break;
-	    }
-	    tmp->SCp.buffer = (struct scatterlist *) list;
-	    list = tmp;
-	}
-	if (free)
-	    hostdata->issue_queue = NULL;
-		
-    }
-    return list;
-}
-
-/* 
- * Function : static int disable (struct Scsi_Host *host)
- *
- * Purpose : disables the given NCR host, causing all commands
- * 	to return a driver error.  Call this so we can unload the
- * 	module during development and try again.  Eventually, 
- * 	we should be able to find clean workarounds for these
- * 	problems.
- *
- * Inputs : host - hostadapter to twiddle
- *
- * Returns : 0 on success.
- */
-
-static int 
-disable (struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned long flags;
-    Scsi_Cmnd *nuke_list, *tmp;
-    local_irq_save(flags);
-    if (hostdata->state != STATE_HALTED)
-	ncr_halt (host);
-    nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */);
-    hard_reset (host);
-    hostdata->state = STATE_DISABLED;
-    local_irq_restore(flags);
-    printk ("scsi%d : nuking commands\n", host->host_no);
-    for (; nuke_list; nuke_list = tmp) {
-	    tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
-	    nuke_list->result = DID_ERROR << 16;
-	    nuke_list->scsi_done(nuke_list);
-    }
-    printk ("scsi%d : done. \n", host->host_no);
-    printk (KERN_ALERT "scsi%d : disabled.  Unload and reload\n",
-    	host->host_no);
-    return 0;
-}
-
-/*
- * Function : static int ncr_halt (struct Scsi_Host *host)
- * 
- * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip
- *
- * Inputs : host - SCSI chip to halt
- *
- * Returns : 0 on success
- */
-
-static int 
-ncr_halt (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    unsigned char istat, tmp;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    int stage;
-    NCR53c7x0_local_setup(host);
-
-    local_irq_save(flags);
-    /* Stage 0 : eat all interrupts
-       Stage 1 : set ABORT
-       Stage 2 : eat all but abort interrupts
-       Stage 3 : eat all interrupts
-     */
-    for (stage = 0;;) {
-	if (stage == 1) {
-	    NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT);
-	    ++stage;
-	}
-	istat = NCR53c7x0_read8 (hostdata->istat);
-	if (istat & ISTAT_SIP) {
-	    tmp = NCR53c7x0_read8(SSTAT0_REG);
-	} else if (istat & ISTAT_DIP) {
-	    tmp = NCR53c7x0_read8(DSTAT_REG);
-	    if (stage == 2) {
-		if (tmp & DSTAT_ABRT) {
-		    NCR53c7x0_write8(hostdata->istat, 0);
-		    ++stage;
-		} else {
-		    printk(KERN_ALERT "scsi%d : could not halt NCR chip\n", 
-			host->host_no);
-		    disable (host);
-	    	}
-    	    }
-	}
-	if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
-	    if (stage == 0)
-	    	++stage;
-	    else if (stage == 3)
-		break;
-	}
-    }
-    hostdata->state = STATE_HALTED;
-    local_irq_restore(flags);
-#if 0
-    print_lots (host);
-#endif
-    return 0;
-}
-
-/* 
- * Function: event_name (int event)
- * 
- * Purpose: map event enum into user-readable strings.
- */
-
-static const char *
-event_name (int event) {
-    switch (event) {
-    case EVENT_NONE:		return "none";
-    case EVENT_ISSUE_QUEUE:	return "to issue queue";
-    case EVENT_START_QUEUE:	return "to start queue";
-    case EVENT_SELECT:		return "selected";
-    case EVENT_DISCONNECT:	return "disconnected";
-    case EVENT_RESELECT:	return "reselected";
-    case EVENT_COMPLETE:	return "completed";
-    case EVENT_IDLE:		return "idle";
-    case EVENT_SELECT_FAILED:	return "select failed";
-    case EVENT_BEFORE_SELECT:	return "before select";
-    case EVENT_RESELECT_FAILED:	return "reselect failed";
-    default:			return "unknown";
-    }
-}
-
-/*
- * Function : void dump_events (struct Scsi_Host *host, count)
- *
- * Purpose : print last count events which have occurred.
- */ 
-static void
-dump_events (struct Scsi_Host *host, int count) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    struct NCR53c7x0_event event;
-    int i;
-    unsigned long flags;
-    if (hostdata->events) {
-	if (count > hostdata->event_size)
-	    count = hostdata->event_size;
-	for (i = hostdata->event_index; count > 0; 
-	    i = (i ? i - 1 : hostdata->event_size -1), --count) {
-/*
- * By copying the event we're currently examining with interrupts
- * disabled, we can do multiple printk(), etc. operations and 
- * still be guaranteed that they're happening on the same 
- * event structure.
- */
-	    local_irq_save(flags);
-#if 0
-	    event = hostdata->events[i];
-#else
-	    memcpy ((void *) &event, (void *) &(hostdata->events[i]),
-		sizeof(event));
-#endif
-
-	    local_irq_restore(flags);
-	    printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n",
-		host->host_no, event_name (event.event), count,
-		(long) event.time.tv_sec, (long) event.time.tv_usec,
-		event.target, event.lun);
-	    if (event.dsa) 
-		printk ("         event for dsa 0x%lx (virt 0x%p)\n", 
-		    virt_to_bus(event.dsa), event.dsa);
-	    if (event.pid != -1) {
-		printk ("         event for pid %ld ", event.pid);
-		__scsi_print_command (event.cmnd);
-	    }
-	}
-    }
-}
-
-/*
- * Function: check_address
- *
- * Purpose: Check to see if a possibly corrupt pointer will fault the 
- *	kernel.
- *
- * Inputs: addr - address; size - size of area
- *
- * Returns: 0 if area is OK, -1 on error.
- *
- * NOTES: should be implemented in terms of vverify on kernels 
- *	that have it.
- */
-
-static int 
-check_address (unsigned long addr, int size) {
-    return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ?  -1 : 0);
-}
-
-#ifdef MODULE
-int 
-NCR53c7x0_release(struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    struct NCR53c7x0_cmd *cmd, *tmp;
-    shutdown (host);
-    if (host->irq != SCSI_IRQ_NONE)
-	{
-	    int irq_count;
-	    struct Scsi_Host *tmp;
-	    for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next)
-		if (tmp->hostt == the_template && tmp->irq == host->irq)
-		    ++irq_count;
-	    if (irq_count == 1)
-		free_irq(host->irq, NULL);
-	}
-    if (host->dma_channel != DMA_NONE)
-	free_dma(host->dma_channel);
-    if (host->io_port)
-	release_region(host->io_port, host->n_io_port);
-    
-    for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp, 
-	--hostdata->num_cmds) {
-	tmp = (struct NCR53c7x0_cmd *) cmd->next;
-    /* 
-     * If we're going to loop, try to stop it to get a more accurate
-     * count of the leaked commands.
-     */
-	cmd->next = NULL;
-	if (cmd->free)
-	    cmd->free ((void *) cmd->real, cmd->size);
-    }
-    if (hostdata->num_cmds)
-	printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n",
-	    host->host_no, hostdata->num_cmds);
-
-    vfree(hostdata->events);
-
-    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
-     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
-     */
-    kernel_set_cachemode((void *)hostdata, 8192, IOMAP_FULL_CACHING);
-    free_pages ((u32)hostdata, 1);
-    return 1;
-}
-#endif /* def MODULE */
diff --git a/drivers/scsi/53c7xx.h b/drivers/scsi/53c7xx.h
deleted file mode 100644
index 218f3b9..0000000
--- a/drivers/scsi/53c7xx.h
+++ /dev/null
@@ -1,1608 +0,0 @@
-/*
- * 53c710 driver.  Modified from Drew Eckhardts driver
- * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * I have left the code for the 53c8xx family in here, because it didn't
- * seem worth removing it.  The possibility of IO_MAPPED chips rather
- * than MEMORY_MAPPED remains, in case someone wants to add support for
- * 53c710 chips on Intel PCs (some older machines have them on the
- * motherboard).
- *
- * NOTE THERE MAY BE PROBLEMS WITH CASTS IN read8 AND Co.
- */
-
-/*
- * NCR 53c{7,8}0x0 driver, header file
- *
- * Sponsored by
- *      iX Multiuser Multitasking Magazine
- *	Hannover, Germany
- *	hm@ix.de	
- *
- * Copyright 1993, 1994, 1995 Drew Eckhardt
- *      Visionary Computing 
- *      (Unix and Linux consulting and custom programming)
- *      drew@PoohSticks.ORG
- *	+1 (303) 786-7975
- *
- * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
- * 
- * PRE-ALPHA
- *
- * For more information, please consult 
- *
- * NCR 53C700/53C700-66
- * SCSI I/O Processor
- * Data Manual
- *
- * NCR 53C810
- * PCI-SCSI I/O Processor 
- * Data Manual
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * +1 (719) 578-3400
- *
- * Toll free literature number
- * +1 (800) 334-5454
- *
- */
-
-#ifndef NCR53c710_H
-#define NCR53c710_H
-
-#ifndef HOSTS_C
-
-/* SCSI control 0 rw, default = 0xc0 */ 
-#define SCNTL0_REG 		0x00	
-#define SCNTL0_ARB1		0x80	/* 0 0 = simple arbitration */
-#define SCNTL0_ARB2		0x40	/* 1 1 = full arbitration */
-#define SCNTL0_STRT		0x20	/* Start Sequence */
-#define SCNTL0_WATN		0x10	/* Select with ATN */
-#define SCNTL0_EPC		0x08	/* Enable parity checking */
-/* Bit 2 is reserved on 800 series chips */
-#define SCNTL0_EPG_700		0x04	/* Enable parity generation */
-#define SCNTL0_AAP		0x02	/*  ATN/ on parity error */
-#define SCNTL0_TRG		0x01	/* Target mode */
-
-/* SCSI control 1 rw, default = 0x00 */
-
-#define SCNTL1_REG 		0x01	
-#define SCNTL1_EXC		0x80	/* Extra Clock Cycle of Data setup */
-#define SCNTL1_ADB		0x40	/*  contents of SODL on bus */
-#define SCNTL1_ESR_700		0x20	/* Enable SIOP response to selection 
-					   and reselection */
-#define SCNTL1_DHP_800		0x20	/* Disable halt on parity error or ATN
-					   target mode only */
-#define SCNTL1_CON		0x10	/* Connected */
-#define SCNTL1_RST		0x08	/* SCSI RST/ */
-#define SCNTL1_AESP		0x04	/* Force bad parity */
-#define SCNTL1_SND_700		0x02	/* Start SCSI send */
-#define SCNTL1_IARB_800		0x02	/* Immediate Arbitration, start
-					   arbitration immediately after
-					   busfree is detected */
-#define SCNTL1_RCV_700		0x01	/* Start SCSI receive */
-#define SCNTL1_SST_800		0x01	/* Start SCSI transfer */
-
-/* SCSI control 2 rw, */
-
-#define SCNTL2_REG_800		0x02	
-#define SCNTL2_800_SDU		0x80	/* SCSI disconnect unexpected */
-
-/* SCSI control 3 rw */
-
-#define SCNTL3_REG_800 		0x03	
-#define SCNTL3_800_SCF_SHIFT	4
-#define SCNTL3_800_SCF_MASK	0x70
-#define SCNTL3_800_SCF2		0x40	/* Synchronous divisor */
-#define SCNTL3_800_SCF1		0x20	/* 0x00 = SCLK/3 */
-#define SCNTL3_800_SCF0		0x10	/* 0x10 = SCLK/1 */
-					/* 0x20 = SCLK/1.5 
-					   0x30 = SCLK/2 
-					   0x40 = SCLK/3 */
-	    
-#define SCNTL3_800_CCF_SHIFT	0
-#define SCNTL3_800_CCF_MASK	0x07
-#define SCNTL3_800_CCF2		0x04	/* 0x00 50.01 to 66 */
-#define SCNTL3_800_CCF1		0x02	/* 0x01 16.67 to 25 */
-#define SCNTL3_800_CCF0		0x01	/* 0x02	25.01 - 37.5 
-					   0x03	37.51 - 50 
-					   0x04 50.01 - 66 */
-
-/*  
- * SCSI destination ID rw - the appropriate bit is set for the selected
- * target ID.  This is written by the SCSI SCRIPTS processor.
- * default = 0x00
- */
-#define SDID_REG_700  		0x02	
-#define SDID_REG_800		0x06
-
-#define GP_REG_800		0x07	/* General purpose IO */
-#define GP_800_IO1		0x02
-#define GP_800_IO2		0x01
-
-/* SCSI interrupt enable rw, default = 0x00 */
-#define SIEN_REG_700		0x03	
-#define SIEN0_REG_800		0x40
-#define SIEN_MA			0x80	/* Phase mismatch (ini) or ATN (tgt) */
-#define SIEN_FC			0x40	/* Function complete */
-#define SIEN_700_STO		0x20	/* Selection or reselection timeout */
-#define SIEN_800_SEL		0x20	/* Selected */
-#define SIEN_700_SEL		0x10	/* Selected or reselected */
-#define SIEN_800_RESEL		0x10	/* Reselected */
-#define SIEN_SGE		0x08	/* SCSI gross error */
-#define SIEN_UDC		0x04	/* Unexpected disconnect */
-#define SIEN_RST		0x02	/* SCSI RST/ received */
-#define SIEN_PAR		0x01	/* Parity error */
-
-/* 
- * SCSI chip ID rw
- * NCR53c700 : 
- * 	When arbitrating, the highest bit is used, when reselection or selection
- * 	occurs, the chip responds to all IDs for which a bit is set.
- * 	default = 0x00 
- * NCR53c810 : 
- *	Uses bit mapping
- */
-#define SCID_REG		0x04	
-/* Bit 7 is reserved on 800 series chips */
-#define SCID_800_RRE		0x40	/* Enable response to reselection */
-#define SCID_800_SRE		0x20	/* Enable response to selection */
-/* Bits four and three are reserved on 800 series chips */
-#define SCID_800_ENC_MASK	0x07	/* Encoded SCSI ID */
-
-/* SCSI transfer rw, default = 0x00 */
-#define SXFER_REG		0x05
-#define SXFER_DHP		0x80	/* Disable halt on parity */
-
-#define SXFER_TP2		0x40	/* Transfer period msb */
-#define SXFER_TP1		0x20
-#define SXFER_TP0		0x10	/* lsb */
-#define SXFER_TP_MASK		0x70
-/* FIXME : SXFER_TP_SHIFT == 5 is right for '8xx chips */
-#define SXFER_TP_SHIFT		5
-#define SXFER_TP_4		0x00	/* Divisors */
-#define SXFER_TP_5		0x10<<1
-#define SXFER_TP_6		0x20<<1
-#define SXFER_TP_7		0x30<<1
-#define SXFER_TP_8		0x40<<1
-#define SXFER_TP_9		0x50<<1
-#define SXFER_TP_10		0x60<<1
-#define SXFER_TP_11		0x70<<1
-
-#define SXFER_MO3		0x08	/* Max offset msb */
-#define SXFER_MO2		0x04
-#define SXFER_MO1		0x02
-#define SXFER_MO0		0x01	/* lsb */
-#define SXFER_MO_MASK		0x0f
-#define SXFER_MO_SHIFT		0
-
-/* 
- * SCSI output data latch rw
- * The contents of this register are driven onto the SCSI bus when 
- * the Assert Data Bus bit of the SCNTL1 register is set and 
- * the CD, IO, and MSG bits of the SOCL register match the SCSI phase
- */
-#define SODL_REG_700		0x06	
-#define SODL_REG_800		0x54
-
-
-/* 
- * SCSI output control latch rw, default = 0 
- * Note that when the chip is being manually programmed as an initiator,
- * the MSG, CD, and IO bits must be set correctly for the phase the target
- * is driving the bus in.  Otherwise no data transfer will occur due to 
- * phase mismatch.
- */
-
-#define SOCL_REG		0x07
-#define SOCL_REQ		0x80	/*  REQ */
-#define SOCL_ACK		0x40	/*  ACK */
-#define SOCL_BSY		0x20	/*  BSY */
-#define SOCL_SEL		0x10	/*  SEL */
-#define SOCL_ATN		0x08	/*  ATN */
-#define SOCL_MSG		0x04	/*  MSG */
-#define SOCL_CD			0x02	/*  C/D */
-#define SOCL_IO			0x01	/*  I/O */
-
-/* 
- * SCSI first byte received latch ro 
- * This register contains the first byte received during a block MOVE 
- * SCSI SCRIPTS instruction, including
- * 
- * Initiator mode	Target mode
- * Message in		Command
- * Status		Message out
- * Data in		Data out
- *
- * It also contains the selecting or reselecting device's ID and our 
- * ID.
- *
- * Note that this is the register the various IF conditionals can 
- * operate on.
- */
-#define SFBR_REG		0x08	
-
-/* 
- * SCSI input data latch ro
- * In initiator mode, data is latched into this register on the rising
- * edge of REQ/. In target mode, data is latched on the rising edge of 
- * ACK/
- */
-#define SIDL_REG_700		0x09
-#define SIDL_REG_800		0x50
-
-/* 
- * SCSI bus data lines ro 
- * This register reflects the instantaneous status of the SCSI data 
- * lines.  Note that SCNTL0 must be set to disable parity checking, 
- * otherwise reading this register will latch new parity.
- */
-#define SBDL_REG_700		0x0a
-#define SBDL_REG_800		0x58
-
-#define SSID_REG_800		0x0a
-#define SSID_800_VAL		0x80	/* Exactly two bits asserted at sel */
-#define SSID_800_ENCID_MASK	0x07	/* Device which performed operation */
-
-
-/* 
- * SCSI bus control lines rw, 
- * instantaneous readout of control lines 
- */
-#define SBCL_REG		0x0b 	
-#define SBCL_REQ		0x80	/*  REQ ro */
-#define SBCL_ACK		0x40	/*  ACK ro */
-#define SBCL_BSY		0x20	/*  BSY ro */
-#define SBCL_SEL		0x10	/*  SEL ro */
-#define SBCL_ATN		0x08	/*  ATN ro */
-#define SBCL_MSG		0x04	/*  MSG ro */
-#define SBCL_CD			0x02	/*  C/D ro */
-#define SBCL_IO			0x01	/*  I/O ro */
-#define SBCL_PHASE_CMDOUT	SBCL_CD
-#define SBCL_PHASE_DATAIN	SBCL_IO
-#define SBCL_PHASE_DATAOUT	0
-#define SBCL_PHASE_MSGIN	(SBCL_CD|SBCL_IO|SBCL_MSG)
-#define SBCL_PHASE_MSGOUT	(SBCL_CD|SBCL_MSG)
-#define SBCL_PHASE_STATIN	(SBCL_CD|SBCL_IO)
-#define SBCL_PHASE_MASK		(SBCL_CD|SBCL_IO|SBCL_MSG)
-/* 
- * Synchronous SCSI Clock Control bits 
- * 0 - set by DCNTL 
- * 1 - SCLK / 1.0
- * 2 - SCLK / 1.5
- * 3 - SCLK / 2.0 
- */
-#define SBCL_SSCF1		0x02	/* wo, -66 only */
-#define SBCL_SSCF0		0x01	/* wo, -66 only */
-#define SBCL_SSCF_MASK		0x03
-
-/* 
- * XXX note : when reading the DSTAT and STAT registers to clear interrupts,
- * insure that 10 clocks elapse between the two  
- */
-/* DMA status ro */
-#define DSTAT_REG		0x0c	
-#define DSTAT_DFE		0x80	/* DMA FIFO empty */
-#define DSTAT_800_MDPE		0x40	/* Master Data Parity Error */
-#define DSTAT_800_BF		0x20	/* Bus Fault */
-#define DSTAT_ABRT		0x10	/* Aborted - set on error */
-#define DSTAT_SSI		0x08	/* SCRIPTS single step interrupt */
-#define DSTAT_SIR		0x04	/* SCRIPTS interrupt received - 
-					   set when INT instruction is 
-					   executed */
-#define DSTAT_WTD		0x02	/* Watchdog timeout detected */
-#define DSTAT_OPC		0x01	/* Illegal instruction */
-#define DSTAT_800_IID		0x01	/* Same thing, different name */
-
-
-/* NCR53c800 moves this stuff into SIST0 */
-#define SSTAT0_REG		0x0d	/* SCSI status 0 ro */
-#define SIST0_REG_800		0x42	
-#define SSTAT0_MA		0x80	/* ini : phase mismatch,
-					 * tgt : ATN/ asserted 
-					 */
-#define SSTAT0_CMP		0x40	/* function complete */
-#define SSTAT0_700_STO		0x20	/* Selection or reselection timeout */
-#define SIST0_800_SEL		0x20	/* Selected */
-#define SSTAT0_700_SEL		0x10	/* Selected or reselected */
-#define SIST0_800_RSL		0x10	/* Reselected */
-#define SSTAT0_SGE		0x08	/* SCSI gross error */
-#define SSTAT0_UDC		0x04	/* Unexpected disconnect */
-#define SSTAT0_RST		0x02	/* SCSI RST/ received */
-#define SSTAT0_PAR		0x01	/* Parity error */
-
-/* And uses SSTAT0 for what was SSTAT1 */
-
-#define SSTAT1_REG		0x0e	/* SCSI status 1 ro */
-#define SSTAT1_ILF		0x80	/* SIDL full */
-#define SSTAT1_ORF		0x40	/* SODR full */
-#define SSTAT1_OLF		0x20	/* SODL full */
-#define SSTAT1_AIP		0x10	/* Arbitration in progress */
-#define SSTAT1_LOA		0x08	/* Lost arbitration */
-#define SSTAT1_WOA		0x04	/* Won arbitration */
-#define SSTAT1_RST		0x02	/* Instant readout of RST/ */
-#define SSTAT1_SDP		0x01	/* Instant readout of SDP/ */
-
-#define SSTAT2_REG		0x0f	/* SCSI status 2 ro */
-#define SSTAT2_FF3		0x80 	/* number of bytes in synchronous */
-#define SSTAT2_FF2		0x40	/* data FIFO */
-#define SSTAT2_FF1		0x20	
-#define SSTAT2_FF0		0x10
-#define SSTAT2_FF_MASK		0xf0
-#define SSTAT2_FF_SHIFT		4
-
-/* 
- * Latched signals, latched on the leading edge of REQ/ for initiators,
- * ACK/ for targets.
- */
-#define SSTAT2_SDP		0x08	/* SDP */
-#define SSTAT2_MSG		0x04	/* MSG */
-#define SSTAT2_CD		0x02	/* C/D */
-#define SSTAT2_IO		0x01	/* I/O */
-#define SSTAT2_PHASE_CMDOUT	SSTAT2_CD
-#define SSTAT2_PHASE_DATAIN	SSTAT2_IO
-#define SSTAT2_PHASE_DATAOUT	0
-#define SSTAT2_PHASE_MSGIN	(SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG)
-#define SSTAT2_PHASE_MSGOUT	(SSTAT2_CD|SSTAT2_MSG)
-#define SSTAT2_PHASE_STATIN	(SSTAT2_CD|SSTAT2_IO)
-#define SSTAT2_PHASE_MASK	(SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG)
-
-
-/* NCR53c700-66 only */
-#define SCRATCHA_REG_00		0x10    /* through  0x13 Scratch A rw */
-/* NCR53c710 and higher */
-#define DSA_REG			0x10	/* DATA structure address */
-
-#define CTEST0_REG_700		0x14	/* Chip test 0 ro */
-#define CTEST0_REG_800		0x18	/* Chip test 0 rw, general purpose */
-/* 0x80 - 0x04 are reserved */
-#define CTEST0_700_RTRG		0x02	/* Real target mode */
-#define CTEST0_700_DDIR		0x01	/* Data direction, 1 = 
-					 * SCSI bus to host, 0  =
-					 * host to SCSI.
-					 */
-
-#define CTEST1_REG_700		0x15	/* Chip test 1 ro */
-#define CTEST1_REG_800		0x19	/* Chip test 1 ro */
-#define CTEST1_FMT3		0x80	/* Identify which byte lanes are empty */
-#define CTEST1_FMT2		0x40 	/* in the DMA FIFO */
-#define CTEST1_FMT1		0x20
-#define CTEST1_FMT0		0x10
-
-#define CTEST1_FFL3		0x08	/* Identify which bytes lanes are full */
-#define CTEST1_FFL2		0x04	/* in the DMA FIFO */
-#define CTEST1_FFL1		0x02
-#define CTEST1_FFL0		0x01
-
-#define CTEST2_REG_700		0x16	/* Chip test 2 ro */
-#define CTEST2_REG_800		0x1a	/* Chip test 2 ro */
-
-#define CTEST2_800_DDIR		0x80	/* 1 = SCSI->host */
-#define CTEST2_800_SIGP		0x40	/* A copy of SIGP in ISTAT.
-					   Reading this register clears */
-#define CTEST2_800_CIO		0x20	/* Configured as IO */.
-#define CTEST2_800_CM		0x10	/* Configured as memory */
-
-/* 0x80 - 0x40 are reserved on 700 series chips */
-#define CTEST2_700_SOFF		0x20	/* SCSI Offset Compare,
-					 * As an initiator, this bit is 
-					 * one when the synchronous offset
-					 * is zero, as a target this bit 
-					 * is one when the synchronous 
-					 * offset is at the maximum
-					 * defined in SXFER
-					 */
-#define CTEST2_700_SFP		0x10	/* SCSI FIFO parity bit,
-					 * reading CTEST3 unloads a byte
-					 * from the FIFO and sets this
-					 */
-#define CTEST2_700_DFP		0x08	/* DMA FIFO parity bit,
-					 * reading CTEST6 unloads a byte
-					 * from the FIFO and sets this
-					 */
-#define CTEST2_TEOP		0x04	/* SCSI true end of process,
-					 * indicates a totally finished
-					 * transfer
-					 */
-#define CTEST2_DREQ		0x02	/* Data request signal */
-/* 0x01 is reserved on 700 series chips */
-#define CTEST2_800_DACK		0x01	
-
-/* 
- * Chip test 3 ro 
- * Unloads the bottom byte of the eight deep SCSI synchronous FIFO,
- * check SSTAT2 FIFO full bits to determine size.  Note that a GROSS
- * error results if a read is attempted on this register.  Also note 
- * that 16 and 32 bit reads of this register will cause corruption.
- */
-#define CTEST3_REG_700		0x17	
-/*  Chip test 3 rw */
-#define CTEST3_REG_800		0x1b
-#define CTEST3_800_V3		0x80	/* Chip revision */
-#define CTEST3_800_V2		0x40
-#define CTEST3_800_V1		0x20
-#define CTEST3_800_V0		0x10
-#define CTEST3_800_FLF		0x08	/* Flush DMA FIFO */
-#define CTEST3_800_CLF		0x04	/* Clear DMA FIFO */
-#define CTEST3_800_FM		0x02	/* Fetch mode pin */
-/* bit 0 is reserved on 800 series chips */
-
-#define CTEST4_REG_700		0x18	/* Chip test 4 rw */
-#define CTEST4_REG_800		0x21	/* Chip test 4 rw */
-/* 0x80 is reserved on 700 series chips */
-#define CTEST4_800_BDIS		0x80	/* Burst mode disable */
-#define CTEST4_ZMOD		0x40	/* High impedance mode */
-#define CTEST4_SZM		0x20	/* SCSI bus high impedance */
-#define CTEST4_700_SLBE		0x10	/* SCSI loopback enabled */
-#define CTEST4_800_SRTM		0x10	/* Shadow Register Test Mode */
-#define CTEST4_700_SFWR		0x08	/* SCSI FIFO write enable, 
-					 * redirects writes from SODL
-					 * to the SCSI FIFO.
-					 */
-#define CTEST4_800_MPEE		0x08	/* Enable parity checking
-					   during master cycles on PCI
-					   bus */
-
-/* 
- * These bits send the contents of the CTEST6 register to the appropriate
- * byte lane of the 32 bit DMA FIFO.  Normal operation is zero, otherwise 
- * the high bit means the low two bits select the byte lane.
- */
-#define CTEST4_FBL2		0x04	
-#define CTEST4_FBL1		0x02
-#define CTEST4_FBL0		0x01	
-#define CTEST4_FBL_MASK		0x07
-#define CTEST4_FBL_0		0x04	/* Select DMA FIFO byte lane 0 */
-#define CTEST4_FBL_1		0x05	/* Select DMA FIFO byte lane 1 */
-#define CTEST4_FBL_2		0x06	/* Select DMA FIFO byte lane 2 */
-#define CTEST4_FBL_3		0x07	/* Select DMA FIFO byte lane 3 */
-#define CTEST4_800_SAVE		(CTEST4_800_BDIS)
-
-
-#define CTEST5_REG_700		0x19	/* Chip test 5 rw */
-#define CTEST5_REG_800		0x22	/* Chip test 5 rw */
-/* 
- * Clock Address Incrementor.  When set, it increments the 
- * DNAD register to the next bus size boundary.  It automatically 
- * resets itself when the operation is complete.
- */
-#define CTEST5_ADCK		0x80
-/*
- * Clock Byte Counter.  When set, it decrements the DBC register to
- * the next bus size boundary.
- */
-#define CTEST5_BBCK		0x40
-/*
- * Reset SCSI Offset.  Setting this bit to 1 clears the current offset
- * pointer in the SCSI synchronous offset counter (SSTAT).  This bit
- * is set to 1 if a SCSI Gross Error Condition occurs.  The offset should
- * be cleared when a synchronous transfer fails.  When written, it is 
- * automatically cleared after the SCSI synchronous offset counter is 
- * reset.
- */
-/* Bit 5 is reserved on 800 series chips */
-#define CTEST5_700_ROFF		0x20
-/* 
- * Master Control for Set or Reset pulses. When 1, causes the low 
- * four bits of register to set when set, 0 causes the low bits to
- * clear when set.
- */
-#define CTEST5_MASR 		0x10	
-#define CTEST5_DDIR		0x08	/* DMA direction */
-/*
- * Bits 2-0 are reserved on 800 series chips
- */
-#define CTEST5_700_EOP		0x04	/* End of process */
-#define CTEST5_700_DREQ		0x02	/* Data request */
-#define CTEST5_700_DACK		0x01	/* Data acknowledge */
-
-/* 
- * Chip test 6 rw - writing to this register writes to the byte 
- * lane in the DMA FIFO as determined by the FBL bits in the CTEST4
- * register.
- */
-#define CTEST6_REG_700		0x1a
-#define CTEST6_REG_800		0x23
-
-#define CTEST7_REG		0x1b	/* Chip test 7 rw */
-/* 0x80 - 0x40 are reserved on NCR53c700 and NCR53c700-66 chips */
-#define CTEST7_10_CDIS		0x80	/* Cache burst disable */
-#define CTEST7_10_SC1		0x40	/* Snoop control bits */
-#define CTEST7_10_SC0		0x20	
-#define CTEST7_10_SC_MASK	0x60
-/* 0x20 is reserved on the NCR53c700 */
-#define CTEST7_0060_FM		0x20	/* Fetch mode */
-#define CTEST7_STD		0x10	/* Selection timeout disable */
-#define CTEST7_DFP		0x08	/* DMA FIFO parity bit for CTEST6 */
-#define CTEST7_EVP		0x04	/* 1 = host bus even parity, 0 = odd */
-#define CTEST7_10_TT1		0x02	/* Transfer type */
-#define CTEST7_00_DC		0x02	/* Set to drive DC low during instruction 
-					   fetch */
-#define CTEST7_DIFF		0x01	/* Differential mode */
-
-#define CTEST7_SAVE ( CTEST7_EVP | CTEST7_DIFF )
-
-
-#define TEMP_REG		0x1c	/* through 0x1f Temporary stack rw */
-
-#define DFIFO_REG		0x20	/* DMA FIFO rw */
-/* 
- * 0x80 is reserved on the NCR53c710, the CLF and FLF bits have been
- * moved into the CTEST8 register.
- */
-#define DFIFO_00_FLF		0x80	/* Flush DMA FIFO to memory */
-#define DFIFO_00_CLF		0x40	/* Clear DMA and SCSI FIFOs */
-#define DFIFO_BO6		0x40
-#define DFIFO_BO5		0x20
-#define DFIFO_BO4		0x10
-#define DFIFO_BO3		0x08
-#define DFIFO_BO2		0x04 
-#define DFIFO_BO1		0x02
-#define DFIFO_BO0		0x01
-#define DFIFO_10_BO_MASK	0x7f	/* 7 bit counter */
-#define DFIFO_00_BO_MASK	0x3f	/* 6 bit counter */
-
-/* 
- * Interrupt status rw 
- * Note that this is the only register which can be read while SCSI
- * SCRIPTS are being executed.
- */
-#define ISTAT_REG_700		0x21
-#define ISTAT_REG_800		0x14
-#define ISTAT_ABRT		0x80	/* Software abort, write 
-					 *1 to abort, wait for interrupt. */
-/* 0x40 and 0x20 are reserved on NCR53c700 and NCR53c700-66 chips */
-#define ISTAT_10_SRST		0x40	/* software reset */
-#define ISTAT_10_SIGP		0x20	/* signal script */
-/* 0x10 is reserved on NCR53c700 series chips */
-#define ISTAT_800_SEM		0x10	/* semaphore */
-#define ISTAT_CON		0x08	/* 1 when connected */
-#define ISTAT_800_INTF		0x04	/* Interrupt on the fly */
-#define ISTAT_700_PRE		0x04	/* Pointer register empty.
-					 * Set to 1 when DSPS and DSP
-					 * registers are empty in pipeline
-					 * mode, always set otherwise.
-					 */
-#define ISTAT_SIP		0x02	/* SCSI interrupt pending from
-					 * SCSI portion of SIOP see
-					 * SSTAT0
-					 */
-#define ISTAT_DIP		0x01	/* DMA interrupt pending 
-					 * see DSTAT
-					 */
-
-/* NCR53c700-66 and NCR53c710 only */
-#define CTEST8_REG		0x22	/* Chip test 8 rw */
-#define CTEST8_0066_EAS		0x80	/* Enable alternate SCSI clock,
-					 * ie read from SCLK/ rather than CLK/
-					 */
-#define CTEST8_0066_EFM		0x40	/* Enable fetch and master outputs */
-#define CTEST8_0066_GRP		0x20	/* Generate Receive Parity for 
-					 * pass through.  This insures that 
-					 * bad parity won't reach the host 
-					 * bus.
-					 */
-#define CTEST8_0066_TE		0x10	/* TolerANT enable.  Enable 
-					 * active negation, should only
-					 * be used for slow SCSI 
-					 * non-differential.
-					 */
-#define CTEST8_0066_HSC		0x08	/* Halt SCSI clock */
-#define CTEST8_0066_SRA		0x04	/* Shorten REQ/ACK filtering,
-					 * must be set for fast SCSI-II
-					 * speeds.
-					 */
-#define CTEST8_0066_DAS		0x02	/* Disable automatic target/initiator
-					 * switching.
-					 */
-#define CTEST8_0066_LDE		0x01	/* Last disconnect enable.
-					 * The status of pending 
-					 * disconnect is maintained by
-					 * the core, eliminating
-					 * the possibility of missing a 
-					 * selection or reselection
-					 * while waiting to fetch a 
-					 * WAIT DISCONNECT opcode.
-					 */
-
-#define CTEST8_10_V3		0x80	/* Chip revision */
-#define CTEST8_10_V2		0x40
-#define CTEST8_10_V1		0x20	
-#define CTEST8_10_V0		0x10
-#define CTEST8_10_V_MASK	0xf0	
-#define CTEST8_10_FLF		0x08	/* Flush FIFOs */
-#define CTEST8_10_CLF		0x04	/* Clear FIFOs */
-#define CTEST8_10_FM		0x02	/* Fetch pin mode */
-#define CTEST8_10_SM		0x01	/* Snoop pin mode */
-
-
-/* 
- * The CTEST9 register may be used to differentiate between a
- * NCR53c700 and a NCR53c710.  
- *
- * Write 0xff to this register.
- * Read it.
- * If the contents are 0xff, it is a NCR53c700
- * If the contents are 0x00, it is a NCR53c700-66 first revision
- * If the contents are some other value, it is some other NCR53c700-66
- */
-#define CTEST9_REG_00		0x23	/* Chip test 9 ro */
-#define LCRC_REG_10		0x23	
-
-/*
- * 0x24 through 0x27 are the DMA byte counter register.  Instructions
- * write their high 8 bits into the DCMD register, the low 24 bits into
- * the DBC register.
- *
- * Function is dependent on the command type being executed.
- */
-
- 
-#define DBC_REG			0x24
-/* 
- * For Block Move Instructions, DBC is a 24 bit quantity representing 
- *     the number of bytes to transfer.
- * For Transfer Control Instructions, DBC is bit fielded as follows : 
- */
-/* Bits 20 - 23 should be clear */
-#define DBC_TCI_TRUE		(1 << 19) 	/* Jump when true */
-#define DBC_TCI_COMPARE_DATA	(1 << 18)	/* Compare data */
-#define DBC_TCI_COMPARE_PHASE	(1 << 17)	/* Compare phase with DCMD field */
-#define DBC_TCI_WAIT_FOR_VALID	(1 << 16)	/* Wait for REQ */
-/* Bits 8 - 15 are reserved on some implementations ? */
-#define DBC_TCI_MASK_MASK	0xff00 		/* Mask for data compare */
-#define DBC_TCI_MASK_SHIFT	8
-#define DBC_TCI_DATA_MASK	0xff		/* Data to be compared */ 
-#define DBC_TCI_DATA_SHIFT	0
-
-#define DBC_RWRI_IMMEDIATE_MASK	0xff00		/* Immediate data */
-#define DBC_RWRI_IMMEDIATE_SHIFT 8		/* Amount to shift */
-#define DBC_RWRI_ADDRESS_MASK	0x3f0000	/* Register address */
-#define DBC_RWRI_ADDRESS_SHIFT 	16
-
-
-/*
- * DMA command r/w
- */
-#define DCMD_REG		0x27	
-#define DCMD_TYPE_MASK		0xc0	/* Masks off type */
-#define DCMD_TYPE_BMI		0x00	/* Indicates a Block Move instruction */
-#define DCMD_BMI_IO		0x01	/* I/O, CD, and MSG bits selecting   */
-#define DCMD_BMI_CD		0x02	/* the phase for the block MOVE      */
-#define DCMD_BMI_MSG		0x04	/* instruction 			     */
-
-#define DCMD_BMI_OP_MASK	0x18	/* mask for opcode */
-#define DCMD_BMI_OP_MOVE_T	0x00	/* MOVE */
-#define DCMD_BMI_OP_MOVE_I	0x08	/* MOVE Initiator */
-
-#define DCMD_BMI_INDIRECT	0x20	/*  Indirect addressing */
-
-#define DCMD_TYPE_TCI		0x80	/* Indicates a Transfer Control 
-					   instruction */
-#define DCMD_TCI_IO		0x01	/* I/O, CD, and MSG bits selecting   */
-#define DCMD_TCI_CD		0x02	/* the phase for the block MOVE      */
-#define DCMD_TCI_MSG		0x04	/* instruction 			     */
-#define DCMD_TCI_OP_MASK	0x38	/* mask for opcode */
-#define DCMD_TCI_OP_JUMP	0x00	/* JUMP */
-#define DCMD_TCI_OP_CALL	0x08	/* CALL */
-#define DCMD_TCI_OP_RETURN	0x10	/* RETURN */
-#define DCMD_TCI_OP_INT		0x18	/* INT */
-
-#define DCMD_TYPE_RWRI		0x40	/* Indicates I/O or register Read/Write
-					   instruction */
-#define DCMD_RWRI_OPC_MASK	0x38	/* Opcode mask */
-#define DCMD_RWRI_OPC_WRITE	0x28	/* Write SFBR to register */
-#define DCMD_RWRI_OPC_READ	0x30	/* Read register to SFBR */
-#define DCMD_RWRI_OPC_MODIFY	0x38	/* Modify in place */
-
-#define DCMD_RWRI_OP_MASK	0x07
-#define DCMD_RWRI_OP_MOVE	0x00
-#define DCMD_RWRI_OP_SHL	0x01
-#define DCMD_RWRI_OP_OR		0x02
-#define DCMD_RWRI_OP_XOR	0x03
-#define DCMD_RWRI_OP_AND	0x04
-#define DCMD_RWRI_OP_SHR	0x05
-#define DCMD_RWRI_OP_ADD	0x06
-#define DCMD_RWRI_OP_ADDC	0x07
-
-#define DCMD_TYPE_MMI		0xc0	/* Indicates a Memory Move instruction 
-					   (three words) */
-
-
-#define DNAD_REG		0x28	/* through 0x2b DMA next address for 
-					   data */
-#define DSP_REG			0x2c	/* through 0x2f DMA SCRIPTS pointer rw */
-#define DSPS_REG		0x30	/* through 0x33 DMA SCRIPTS pointer 
-					   save rw */
-#define DMODE_REG_00		0x34 	/* DMA mode rw */
-#define DMODE_00_BL1	0x80	/* Burst length bits */
-#define DMODE_00_BL0	0x40
-#define DMODE_BL_MASK	0xc0
-/* Burst lengths (800) */
-#define DMODE_BL_2	0x00	/* 2 transfer */
-#define DMODE_BL_4	0x40	/* 4 transfers */
-#define DMODE_BL_8	0x80	/* 8 transfers */
-#define DMODE_BL_16	0xc0	/* 16 transfers */
-
-#define DMODE_10_BL_1	0x00	/* 1 transfer */
-#define DMODE_10_BL_2	0x40	/* 2 transfers */
-#define DMODE_10_BL_4	0x80	/* 4 transfers */
-#define DMODE_10_BL_8	0xc0	/* 8 transfers */
-#define DMODE_10_FC2	0x20	/* Driven to FC2 pin */
-#define DMODE_10_FC1	0x10	/* Driven to FC1 pin */
-#define DMODE_710_PD	0x08	/* Program/data on FC0 pin */
-#define DMODE_710_UO	0x02	/* User prog. output */
-
-#define DMODE_700_BW16	0x20	/* Host buswidth = 16 */
-#define DMODE_700_286	0x10	/* 286 mode */
-#define DMODE_700_IOM	0x08	/* Transfer to IO port */
-#define DMODE_700_FAM	0x04	/* Fixed address mode */
-#define DMODE_700_PIPE	0x02	/* Pipeline mode disables 
-					 * automatic fetch / exec 
-					 */
-#define DMODE_MAN	0x01		/* Manual start mode, 
-					 * requires a 1 to be written
-					 * to the start DMA bit in the DCNTL
-					 * register to run scripts 
-					 */
-
-#define DMODE_700_SAVE ( DMODE_00_BL_MASK | DMODE_00_BW16 | DMODE_00_286 )
-
-/* NCR53c800 series only */
-#define SCRATCHA_REG_800	0x34	/* through 0x37 Scratch A rw */
-/* NCR53c710 only */
-#define SCRATCHB_REG_10		0x34	/* through 0x37 scratch B rw */
-
-#define DMODE_REG_10    	0x38	/* DMA mode rw, NCR53c710 and newer */
-#define DMODE_800_SIOM		0x20	/* Source IO = 1 */
-#define DMODE_800_DIOM		0x10	/* Destination IO = 1 */
-#define DMODE_800_ERL		0x08	/* Enable Read Line */
-
-/* 35-38 are reserved on 700 and 700-66 series chips */
-#define DIEN_REG		0x39	/* DMA interrupt enable rw */
-/* 0x80, 0x40, and 0x20 are reserved on 700-series chips */
-#define DIEN_800_MDPE		0x40	/* Master data parity error */
-#define DIEN_800_BF		0x20	/* BUS fault */
-#define DIEN_700_BF		0x20	/* BUS fault */
-#define DIEN_ABRT		0x10	/* Enable aborted interrupt */
-#define DIEN_SSI		0x08	/* Enable single step interrupt */
-#define DIEN_SIR		0x04	/* Enable SCRIPTS INT command 
-					 * interrupt
-					 */
-/* 0x02 is reserved on 800 series chips */
-#define DIEN_700_WTD		0x02	/* Enable watchdog timeout interrupt */
-#define DIEN_700_OPC		0x01	/* Enable illegal instruction 
-					 * interrupt 
-					 */
-#define DIEN_800_IID		0x01	/*  Same meaning, different name */ 
-
-/*
- * DMA watchdog timer rw
- * set in 16 CLK input periods.
- */
-#define DWT_REG			0x3a
-
-/* DMA control rw */
-#define DCNTL_REG		0x3b
-#define DCNTL_700_CF1		0x80	/* Clock divisor bits */
-#define DCNTL_700_CF0		0x40
-#define DCNTL_700_CF_MASK	0xc0
-/* Clock divisors 			   Divisor SCLK range (MHZ) */
-#define DCNTL_700_CF_2		0x00    /* 2.0	   37.51-50.00 */
-#define DCNTL_700_CF_1_5	0x40	/* 1.5	   25.01-37.50 */
-#define DCNTL_700_CF_1		0x80	/* 1.0     16.67-25.00 */
-#define DCNTL_700_CF_3		0xc0	/* 3.0	   50.01-66.67 (53c700-66) */
-
-#define DCNTL_700_S16		0x20	/* Load scripts 16 bits at a time */
-#define DCNTL_SSM		0x10	/* Single step mode */
-#define DCNTL_700_LLM		0x08	/* Low level mode, can only be set 
-					 * after selection */
-#define DCNTL_800_IRQM		0x08	/* Totem pole IRQ pin */
-#define DCNTL_STD		0x04	/* Start DMA / SCRIPTS */
-/* 0x02 is reserved */
-#define DCNTL_00_RST		0x01	/* Software reset, resets everything
-					 * but 286 mode bit  in DMODE. On the
-					 * NCR53c710, this bit moved to CTEST8
-					 */
-#define DCNTL_10_COM		0x01	/* 700 software compatibility mode */
-#define DCNTL_10_EA		0x20	/* Enable Ack - needed for MVME16x */
-
-#define DCNTL_700_SAVE ( DCNTL_CF_MASK | DCNTL_S16)
-
-
-/* NCR53c700-66 only */
-#define SCRATCHB_REG_00		0x3c	/* through 0x3f scratch b rw */
-#define SCRATCHB_REG_800	0x5c	/* through 0x5f scratch b rw */
-/* NCR53c710 only */
-#define ADDER_REG_10		0x3c	/* Adder, NCR53c710 only */
-
-#define SIEN1_REG_800		0x41
-#define SIEN1_800_STO		0x04	/* selection/reselection timeout */
-#define SIEN1_800_GEN		0x02	/* general purpose timer */
-#define SIEN1_800_HTH		0x01	/* handshake to handshake */
-
-#define SIST1_REG_800		0x43
-#define SIST1_800_STO		0x04	/* selection/reselection timeout */
-#define SIST1_800_GEN		0x02	/* general purpose timer */
-#define SIST1_800_HTH		0x01	/* handshake to handshake */
-
-#define SLPAR_REG_800		0x44	/* Parity */
-
-#define MACNTL_REG_800		0x46	/* Memory access control */
-#define MACNTL_800_TYP3		0x80
-#define MACNTL_800_TYP2		0x40
-#define MACNTL_800_TYP1		0x20
-#define MACNTL_800_TYP0		0x10
-#define MACNTL_800_DWR		0x08
-#define MACNTL_800_DRD		0x04
-#define MACNTL_800_PSCPT	0x02
-#define MACNTL_800_SCPTS	0x01
-
-#define GPCNTL_REG_800		0x47	/* General Purpose Pin Control */
-
-/* Timeouts are expressed such that 0=off, 1=100us, doubling after that */
-#define STIME0_REG_800		0x48	/* SCSI Timer Register 0 */
-#define STIME0_800_HTH_MASK	0xf0	/* Handshake to Handshake timeout */
-#define STIME0_800_HTH_SHIFT	4
-#define STIME0_800_SEL_MASK	0x0f	/* Selection timeout */
-#define STIME0_800_SEL_SHIFT	0
-
-#define STIME1_REG_800		0x49
-#define STIME1_800_GEN_MASK	0x0f	/* General purpose timer */
-
-#define RESPID_REG_800		0x4a	/* Response ID, bit fielded.  8
-					   bits on narrow chips, 16 on WIDE */
-
-#define STEST0_REG_800		0x4c	
-#define STEST0_800_SLT		0x08	/* Selection response logic test */
-#define STEST0_800_ART		0x04	/* Arbitration priority encoder test */
-#define STEST0_800_SOZ		0x02	/* Synchronous offset zero */
-#define STEST0_800_SOM		0x01	/* Synchronous offset maximum */
-
-#define STEST1_REG_800		0x4d
-#define STEST1_800_SCLK		0x80	/* Disable SCSI clock */
-
-#define STEST2_REG_800		0x4e	
-#define STEST2_800_SCE		0x80	/* Enable SOCL/SODL */
-#define STEST2_800_ROF		0x40	/* Reset SCSI sync offset */
-#define STEST2_800_SLB		0x10	/* Enable SCSI loopback mode */
-#define STEST2_800_SZM		0x08	/* SCSI high impedance mode */
-#define STEST2_800_EXT		0x02	/* Extend REQ/ACK filter 30 to 60ns */
-#define STEST2_800_LOW		0x01	/* SCSI low level mode */
-
-#define STEST3_REG_800		0x4f	 
-#define STEST3_800_TE		0x80	/* Enable active negation */
-#define STEST3_800_STR		0x40	/* SCSI FIFO test read */
-#define STEST3_800_HSC		0x20	/* Halt SCSI clock */
-#define STEST3_800_DSI		0x10	/* Disable single initiator response */
-#define STEST3_800_TTM		0x04	/* Time test mode */
-#define STEST3_800_CSF		0x02	/* Clear SCSI FIFO */
-#define STEST3_800_STW		0x01	/* SCSI FIFO test write */
-
-#define OPTION_PARITY 		0x1	/* Enable parity checking */
-#define OPTION_TAGGED_QUEUE	0x2	/* Enable SCSI-II tagged queuing */
-#define OPTION_700		0x8	/* Always run NCR53c700 scripts */
-#define OPTION_INTFLY		0x10	/* Use INTFLY interrupts */
-#define OPTION_DEBUG_INTR	0x20	/* Debug interrupts */
-#define OPTION_DEBUG_INIT_ONLY	0x40	/* Run initialization code and 
-					   simple test code, return
-					   DID_NO_CONNECT if any SCSI
-					   commands are attempted. */
-#define OPTION_DEBUG_READ_ONLY	0x80	/* Return DID_ERROR if any 
-					   SCSI write is attempted */
-#define OPTION_DEBUG_TRACE	0x100	/* Animated trace mode, print 
-					   each address and instruction 
-					   executed to debug buffer. */
-#define OPTION_DEBUG_SINGLE	0x200	/* stop after executing one 
-					   instruction */
-#define OPTION_SYNCHRONOUS	0x400	/* Enable sync SCSI.  */
-#define OPTION_MEMORY_MAPPED	0x800	/* NCR registers have valid 
-					   memory mapping */
-#define OPTION_IO_MAPPED	0x1000  /* NCR registers have valid
-					     I/O mapping */
-#define OPTION_DEBUG_PROBE_ONLY	0x2000  /* Probe only, don't even init */
-#define OPTION_DEBUG_TESTS_ONLY	0x4000  /* Probe, init, run selected tests */
-#define OPTION_DEBUG_TEST0	0x08000 /* Run test 0 */
-#define OPTION_DEBUG_TEST1	0x10000 /* Run test 1 */
-#define OPTION_DEBUG_TEST2	0x20000 /* Run test 2 */
-#define OPTION_DEBUG_DUMP	0x40000 /* Dump commands */
-#define OPTION_DEBUG_TARGET_LIMIT 0x80000 /* Only talk to target+luns specified */
-#define OPTION_DEBUG_NCOMMANDS_LIMIT 0x100000 /* Limit the number of commands */
-#define OPTION_DEBUG_SCRIPT 0x200000 /* Print when checkpoints are passed */
-#define OPTION_DEBUG_FIXUP 0x400000 /* print fixup values */
-#define OPTION_DEBUG_DSA 0x800000
-#define OPTION_DEBUG_CORRUPTION	0x1000000	/* Detect script corruption */
-#define OPTION_DEBUG_SDTR       0x2000000	/* Debug SDTR problem */
-#define OPTION_DEBUG_MISMATCH 	0x4000000 	/* Debug phase mismatches */
-#define OPTION_DISCONNECT	0x8000000	/* Allow disconnect */
-#define OPTION_DEBUG_DISCONNECT 0x10000000	
-#define OPTION_ALWAYS_SYNCHRONOUS 0x20000000	/* Negotiate sync. transfers
-						   on power up */
-#define OPTION_DEBUG_QUEUES	0x80000000	
-#define OPTION_DEBUG_ALLOCATION 0x100000000LL
-#define OPTION_DEBUG_SYNCHRONOUS 0x200000000LL	/* Sanity check SXFER and 
-						   SCNTL3 registers */
-#define OPTION_NO_ASYNC	0x400000000LL		/* Don't automagically send
-						   SDTR for async transfers when
-						   we haven't been told to do
-						   a synchronous transfer. */
-#define OPTION_NO_PRINT_RACE 0x800000000LL	/* Don't print message when
-						   the reselect/WAIT DISCONNECT
-						   race condition hits */
-#if !defined(PERM_OPTIONS)
-#define PERM_OPTIONS 0
-#endif
-				
-/*
- * Some data which is accessed by the NCR chip must be 4-byte aligned.
- * For some hosts the default is less than that (eg. 68K uses 2-byte).
- * Alignment has only been forced where it is important; also if one
- * 32 bit structure field is aligned then it is assumed that following
- * 32 bit fields are also aligned.  Take care when adding fields
- * which are other than 32 bit.
- */
-
-struct NCR53c7x0_synchronous {
-    u32 select_indirect			/* Value used for indirect selection */
-	__attribute__ ((aligned (4)));
-    u32 sscf_710;			/* Used to set SSCF bits for 710 */
-    u32 script[8];			/* Size ?? Script used when target is 
-						reselected */
-    unsigned char synchronous_want[5];	/* Per target desired SDTR */
-/* 
- * Set_synchronous programs these, select_indirect and current settings after
- * int_debug_should show a match.
- */
-    unsigned char sxfer_sanity, scntl3_sanity;
-};
-
-#define CMD_FLAG_SDTR 		1	/* Initiating synchronous 
-					   transfer negotiation */
-#define CMD_FLAG_WDTR		2	/* Initiating wide transfer
-					   negotiation */
-#define CMD_FLAG_DID_SDTR	4	/* did SDTR */
-#define CMD_FLAG_DID_WDTR	8	/* did WDTR */
-
-struct NCR53c7x0_table_indirect {
-    u32 count;
-    void *address;
-};
-
-enum ncr_event { 
-    EVENT_NONE = 0,
-/* 
- * Order is IMPORTANT, since these must correspond to the event interrupts
- * in 53c7,8xx.scr 
- */
-
-    EVENT_ISSUE_QUEUE = 0x5000000,	/* 0 Command was added to issue queue */
-    EVENT_START_QUEUE,			/* 1 Command moved to start queue */
-    EVENT_SELECT,			/* 2 Command completed selection */
-    EVENT_DISCONNECT,			/* 3 Command disconnected */
-    EVENT_RESELECT,			/* 4 Command reselected */
-    EVENT_COMPLETE,		        /* 5 Command completed */
-    EVENT_IDLE,				/* 6 */
-    EVENT_SELECT_FAILED,		/* 7 */
-    EVENT_BEFORE_SELECT,		/* 8 */
-    EVENT_RESELECT_FAILED		/* 9 */
-};
-
-struct NCR53c7x0_event {
-    enum ncr_event event;	/* What type of event */
-    unsigned char target;
-    unsigned char lun;
-    struct timeval time;	
-    u32 *dsa;			/* What's in the DSA register now (virt) */
-/* 
- * A few things from that SCSI pid so we know what happened after 
- * the Scsi_Cmnd structure in question may have disappeared.
- */
-    unsigned long pid;		/* The SCSI PID which caused this 
-				   event */
-    unsigned char cmnd[12];
-};
-
-/*
- * Things in the NCR53c7x0_cmd structure are split into two parts :
- *
- * 1.  A fixed portion, for things which are not accessed directly by static NCR
- *	code (ie, are referenced only by the Linux side of the driver,
- *	or only by dynamically generated code).  
- *
- * 2.  The DSA portion, for things which are accessed directly by static NCR
- *	code.
- *
- * This is a little ugly, but it 
- * 1.  Avoids conflicts between the NCR code's picture of the structure, and 
- * 	Linux code's idea of what it looks like.
- *
- * 2.  Minimizes the pain in the Linux side of the code needed 
- * 	to calculate real dsa locations for things, etc.
- * 
- */
-
-struct NCR53c7x0_cmd {
-    void *real;				/* Real, unaligned address for
-					   free function */
-    void (* free)(void *, int);		/* Command to deallocate; NULL
-					   for structures allocated with
-					   scsi_register, etc. */
-    Scsi_Cmnd *cmd;			/* Associated Scsi_Cmnd 
-					   structure, Scsi_Cmnd points
-					   at NCR53c7x0_cmd using 
-					   host_scribble structure */
-
-    int size;				/* scsi_malloc'd size of this 
-					   structure */
-
-    int flags;				/* CMD_* flags */
-
-    unsigned char      cmnd[12];	/* CDB, copied from Scsi_Cmnd */
-    int                result;		/* Copy to Scsi_Cmnd when done */
-
-    struct {				/* Private non-cached bounce buffer */
-        unsigned char buf[256];
-	u32	      addr;
-        u32           len;
-    } bounce;
-
-/*
- * SDTR and WIDE messages are an either/or affair
- * in this message, since we will go into message out and send
- * _the whole mess_ without dropping out of message out to 
- * let the target go into message in after sending the first 
- * message.
- */
-
-    unsigned char select[11];		/* Select message, includes
-					   IDENTIFY
-					   (optional) QUEUE TAG
- 				 	   (optional) SDTR or WDTR
-					 */
-
-
-    volatile struct NCR53c7x0_cmd *next; /* Linux maintained lists (free,
-					    running, eventually finished */
-    					 
-
-    u32 *data_transfer_start;		/* Start of data transfer routines */
-    u32 *data_transfer_end;		/* Address after end of data transfer o
-    	    	    	    	    	   routines */
-/* 
- * The following three fields were moved from the DSA proper to here
- * since only dynamically generated NCR code refers to them, meaning
- * we don't need dsa_* absolutes, and it is simpler to let the 
- * host code refer to them directly.
- */
-
-/* 
- * HARD CODED : residual and saved_residual need to agree with the sizes
- * used in NCR53c7,8xx.scr.  
- * 
- * FIXME: we want to consider the case where we have odd-length 
- *	scatter/gather buffers and a WIDE transfer, in which case 
- *	we'll need to use the CHAIN MOVE instruction.  Ick.
- */
-    u32 residual[6] __attribute__ ((aligned (4)));
-					/* Residual data transfer which
-					   allows pointer code to work
-					   right.
-
-    	    	    	    	    	    [0-1] : Conditional call to 
-    	    	    	    	    	    	appropriate other transfer 
-    	    	    	    	    	    	routine.
-    	    	    	    	    	    [2-3] : Residual block transfer
-    	    	    	    	    	    	instruction.
-    	    	    	    	    	    [4-5] : Jump to instruction
-    	    	    	    	    	    	after splice.
-					 */
-    u32 saved_residual[6]; 		/* Copy of old residual, so we 
-					   can get another partial 
-					   transfer and still recover 
-    	    	    	    	    	 */
-    	    	
-    u32 saved_data_pointer;		/* Saved data pointer */
-
-    u32 dsa_next_addr;		        /* _Address_ of dsa_next field  
-					   in this dsa for RISCy 
-					   style constant. */
-
-    u32 dsa_addr;			/* Address of dsa; RISCy style
-					   constant */
-
-    u32 dsa[0];				/* Variable length (depending
-					   on host type, number of scatter /
-					   gather buffers, etc).  */
-};
-
-struct NCR53c7x0_break {
-    u32 *address, old_instruction[2];
-    struct NCR53c7x0_break *next;
-    unsigned char old_size;		/* Size of old instruction */
-};
-
-/* Indicates that the NCR is not executing code */
-#define STATE_HALTED	0		
-/* 
- * Indicates that the NCR is executing the wait for select / reselect 
- * script.  Only used when running NCR53c700 compatible scripts, only 
- * state during which an ABORT is _not_ considered an error condition.
- */
-#define STATE_WAITING	1		
-/* Indicates that the NCR is executing other code. */
-#define STATE_RUNNING	2		
-/* 
- * Indicates that the NCR was being aborted.
- */
-#define STATE_ABORTING	3
-/* Indicates that the NCR was successfully aborted. */
-#define STATE_ABORTED 4
-/* Indicates that the NCR has been disabled due to a fatal error */
-#define STATE_DISABLED 5
-
-/* 
- * Where knowledge of SCSI SCRIPT(tm) specified values are needed 
- * in an interrupt handler, an interrupt handler exists for each 
- * different SCSI script so we don't have name space problems.
- * 
- * Return values of these handlers are as follows : 
- */
-#define SPECIFIC_INT_NOTHING 	0	/* don't even restart */
-#define SPECIFIC_INT_RESTART	1	/* restart at the next instruction */
-#define SPECIFIC_INT_ABORT	2	/* recoverable error, abort cmd */
-#define SPECIFIC_INT_PANIC	3	/* unrecoverable error, panic */
-#define SPECIFIC_INT_DONE	4	/* normal command completion */
-#define SPECIFIC_INT_BREAK	5	/* break point encountered */
-
-struct NCR53c7x0_hostdata {
-    int size;				/* Size of entire Scsi_Host
-					   structure */
-    int board;				/* set to board type, useful if 
-					   we have host specific things,
-					   ie, a general purpose I/O 
-					   bit is being used to enable
-					   termination, etc. */
-
-    int chip;				/* set to chip type; 700-66 is
-					   700-66, rest are last three
-					   digits of part number */
-
-    char valid_ids[8];			/* Valid SCSI ID's for adapter */
-
-    u32 *dsp;				/* dsp to restart with after
-					   all stacked interrupts are
-					   handled. */
-
-    unsigned dsp_changed:1;		/* Has dsp changed within this
-					   set of stacked interrupts ? */
-
-    unsigned char dstat;		/* Most recent value of dstat */
-    unsigned dstat_valid:1;
-
-    unsigned expecting_iid:1;		/* Expect IID interrupt */
-    unsigned expecting_sto:1;		/* Expect STO interrupt */
-    
-    /* 
-     * The code stays cleaner if we use variables with function
-     * pointers and offsets that are unique for the different
-     * scripts rather than having a slew of switch(hostdata->chip) 
-     * statements.
-     * 
-     * It also means that the #defines from the SCSI SCRIPTS(tm)
-     * don't have to be visible outside of the script-specific
-     * instructions, preventing name space pollution.
-     */
-
-    void (* init_fixup)(struct Scsi_Host *host);
-    void (* init_save_regs)(struct Scsi_Host *host);
-    void (* dsa_fixup)(struct NCR53c7x0_cmd *cmd);
-    void (* soft_reset)(struct Scsi_Host *host);
-    int (* run_tests)(struct Scsi_Host *host);
-
-    /*
-     * Called when DSTAT_SIR is set, indicating an interrupt generated
-     * by the INT instruction, where values are unique for each SCSI
-     * script.  Should return one of the SPEC_* values.
-     */
-
-    int (* dstat_sir_intr)(struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
-
-    int dsa_len; /* Size of DSA structure */
-
-    /*
-     * Location of DSA fields for the SCSI SCRIPT corresponding to this 
-     * chip.  
-     */
-
-    s32 dsa_start;			
-    s32 dsa_end;			
-    s32 dsa_next;
-    s32 dsa_prev;
-    s32 dsa_cmnd;
-    s32 dsa_select;
-    s32 dsa_msgout;
-    s32 dsa_cmdout;
-    s32 dsa_dataout;
-    s32 dsa_datain;
-    s32 dsa_msgin;
-    s32 dsa_msgout_other;
-    s32 dsa_write_sync;
-    s32 dsa_write_resume;
-    s32 dsa_check_reselect;
-    s32 dsa_status;
-    s32 dsa_saved_pointer;
-    s32 dsa_jump_dest;
-
-    /* 
-     * Important entry points that generic fixup code needs
-     * to know about, fixed up.
-     */
-
-    s32 E_accept_message;
-    s32 E_command_complete;		
-    s32 E_data_transfer;
-    s32 E_dsa_code_template;
-    s32 E_dsa_code_template_end;
-    s32 E_end_data_transfer;
-    s32 E_msg_in;
-    s32 E_initiator_abort;
-    s32 E_other_transfer;
-    s32 E_other_in;
-    s32 E_other_out;
-    s32 E_target_abort;
-    s32 E_debug_break;	
-    s32 E_reject_message;
-    s32 E_respond_message;
-    s32 E_select;
-    s32 E_select_msgout;
-    s32 E_test_0;
-    s32 E_test_1;
-    s32 E_test_2;
-    s32 E_test_3;
-    s32 E_dsa_zero;
-    s32 E_cmdout_cmdout;
-    s32 E_wait_reselect;
-    s32 E_dsa_code_begin;
-
-    long long options;			/* Bitfielded set of options enabled */
-    volatile u32 test_completed;	/* Test completed */
-    int test_running;			/* Test currently running */
-    s32 test_source
-	__attribute__ ((aligned (4)));
-    volatile s32 test_dest;
-
-    volatile int state;			/* state of driver, only used for 
-					   OPTION_700 */
-
-    unsigned char  dmode;		/* 
-					 * set to the address of the DMODE 
-					 * register for this chip.
-					 */
-    unsigned char istat;		/* 
-    	    	    	    	    	 * set to the address of the ISTAT 
-    	    	    	    	    	 * register for this chip.
-    	    	    	    	    	 */
-  
-    int scsi_clock;			/* 
-					 * SCSI clock in HZ. 0 may be used 
-					 * for unknown, although this will
-					 * disable synchronous negotiation.
-					 */
-
-    volatile int intrs;			/* Number of interrupts */
-    volatile int resets;		/* Number of SCSI resets */
-    unsigned char saved_dmode;	
-    unsigned char saved_ctest4;
-    unsigned char saved_ctest7;
-    unsigned char saved_dcntl;
-    unsigned char saved_scntl3;
-
-    unsigned char this_id_mask;
-
-    /* Debugger information */
-    struct NCR53c7x0_break *breakpoints, /* Linked list of all break points */
-	*breakpoint_current;		/* Current breakpoint being stepped 
-					   through, NULL if we are running 
-					   normally. */
-#ifdef NCR_DEBUG
-    int debug_size;			/* Size of debug buffer */
-    volatile int debug_count;		/* Current data count */
-    volatile char *debug_buf;		/* Output ring buffer */
-    volatile char *debug_write;		/* Current write pointer */
-    volatile char *debug_read;		/* Current read pointer */
-#endif /* def NCR_DEBUG */
-
-    /* XXX - primitive debugging junk, remove when working ? */
-    int debug_print_limit;		/* Number of commands to print
-					   out exhaustive debugging
-					   information for if 
-					   OPTION_DEBUG_DUMP is set */ 
-
-    unsigned char debug_lun_limit[16];	/* If OPTION_DEBUG_TARGET_LIMIT
-					   set, puke if commands are sent
-					   to other target/lun combinations */
-
-    int debug_count_limit;		/* Number of commands to execute
-					   before puking to limit debugging 
-					   output */
-				    
-
-    volatile unsigned idle:1;			/* set to 1 if idle */
-
-    /* 
-     * Table of synchronous+wide transfer parameters set on a per-target
-     * basis.
-     */
-    
-    volatile struct NCR53c7x0_synchronous sync[16]
-	__attribute__ ((aligned (4)));
-
-    volatile Scsi_Cmnd *issue_queue
-	__attribute__ ((aligned (4)));
-						/* waiting to be issued by
-						   Linux driver */
-    volatile struct NCR53c7x0_cmd *running_list;	
-						/* commands running, maintained
-						   by Linux driver */
-
-    volatile struct NCR53c7x0_cmd *ncrcurrent;	/* currently connected 
-						   nexus, ONLY valid for
-						   NCR53c700/NCR53c700-66
-						 */
-
-    volatile struct NCR53c7x0_cmd *spare;	/* pointer to spare,
-    	    	    	    	    	    	   allocated at probe time,
-    	    	    	    	    	    	   which we can use for 
-						   initialization */
-    volatile struct NCR53c7x0_cmd *free;
-    int max_cmd_size;				/* Maximum size of NCR53c7x0_cmd
-					    	   based on number of 
-						   scatter/gather segments, etc.
-						   */
-    volatile int num_cmds;			/* Number of commands 
-						   allocated */
-    volatile int extra_allocate;
-    volatile unsigned char cmd_allocated[16];	/* Have we allocated commands
-						   for this target yet?  If not,
-						   do so ASAP */
-    volatile unsigned char busy[16][8];     	/* number of commands 
-						   executing on each target
-    	    	    	    	    	    	 */
-    /* 
-     * Eventually, I'll switch to a coroutine for calling 
-     * cmd->done(cmd), etc. so that we can overlap interrupt
-     * processing with this code for maximum performance.
-     */
-    
-    volatile struct NCR53c7x0_cmd *finished_queue;	
-						
-    /* Shared variables between SCRIPT and host driver */
-    volatile u32 *schedule
-	__attribute__ ((aligned (4)));		/* Array of JUMPs to dsa_begin
-						   routines of various DSAs.  
-						   When not in use, replace
-						   with jump to next slot */
-
-
-    volatile unsigned char msg_buf[16];		/* buffer for messages
-						   other than the command
-						   complete message */
-
-    /* Per-target default synchronous and WIDE messages */
-    volatile unsigned char synchronous_want[16][5];
-    volatile unsigned char wide_want[16][4];
-
-    /* Bit fielded set of targets we want to speak synchronously with */ 
-    volatile u16 initiate_sdtr;	
-    /* Bit fielded set of targets we want to speak wide with */
-    volatile u16 initiate_wdtr;
-    /* Bit fielded list of targets we've talked to. */
-    volatile u16 talked_to;
-
-    /* Array of bit-fielded lun lists that we need to request_sense */
-    volatile unsigned char request_sense[16];
-
-    u32 addr_reconnect_dsa_head
-	__attribute__ ((aligned (4)));		/* RISCy style constant,
-						   address of following */
-    volatile u32 reconnect_dsa_head;	
-    /* Data identifying nexus we are trying to match during reselection */
-    volatile unsigned char reselected_identify; /* IDENTIFY message */
-    volatile unsigned char reselected_tag;	/* second byte of queue tag 
-						   message or 0 */
-
-    /* These were static variables before we moved them */
-
-    s32 NCR53c7xx_zero
-	__attribute__ ((aligned (4)));
-    s32 NCR53c7xx_sink;
-    u32 NOP_insn;
-    char NCR53c7xx_msg_reject;
-    char NCR53c7xx_msg_abort;
-    char NCR53c7xx_msg_nop;
-
-    /*
-     * Following item introduced by RGH to support NCRc710, which is
-     * VERY brain-dead when it come to memory moves
-     */
-
-			  /* DSA save area used only by the NCR chip */
-    volatile unsigned long saved2_dsa
-	__attribute__ ((aligned (4)));
-
-    volatile unsigned long emulated_intfly
-	__attribute__ ((aligned (4)));
-
-    volatile int event_size, event_index;
-    volatile struct NCR53c7x0_event *events;
-
-    /* If we need to generate code to kill off the currently connected 
-       command, this is where we do it. Should have a BMI instruction
-       to source or sink the current data, followed by a JUMP
-       to abort_connected */
-
-    u32 *abort_script;
-
-    int script_count;				/* Size of script in words */
-    u32 script[0];				/* Relocated SCSI script */
-
-};
-
-#define SCSI_IRQ_NONE	255
-#define DMA_NONE	255
-#define IRQ_AUTO	254
-#define DMA_AUTO	254
-
-#define BOARD_GENERIC	0
-
-#define NCR53c7x0_insn_size(insn)					\
-    (((insn) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI ? 3 : 2)
-    
-
-#define NCR53c7x0_local_declare()					\
-    volatile unsigned char *NCR53c7x0_address_memory;			\
-    unsigned int NCR53c7x0_address_io;					\
-    int NCR53c7x0_memory_mapped
-
-#define NCR53c7x0_local_setup(host)					\
-    NCR53c7x0_address_memory = (void *) (host)->base;			\
-    NCR53c7x0_address_io = (unsigned int) (host)->io_port;		\
-    NCR53c7x0_memory_mapped = ((struct NCR53c7x0_hostdata *) 		\
-	host->hostdata[0])-> options & OPTION_MEMORY_MAPPED 
-
-#ifdef BIG_ENDIAN
-/* These could be more efficient, given that we are always memory mapped,
- * but they don't give the same problems as the write macros, so leave
- * them. */
-#ifdef __mc68000__
-#define NCR53c7x0_read8(address) 					\
-    ((unsigned int)raw_inb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) )
-
-#define NCR53c7x0_read16(address) 					\
-    ((unsigned int)raw_inw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)))
-#else
-#define NCR53c7x0_read8(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int)readb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) :	\
-	inb(NCR53c7x0_address_io + (address)))
-
-#define NCR53c7x0_read16(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int)readw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) :	\
-	inw(NCR53c7x0_address_io + (address)))
-#endif /* mc68000 */
-#else
-#define NCR53c7x0_read8(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int)readb((u32)NCR53c7x0_address_memory + (u32)(address)) :	\
-	inb(NCR53c7x0_address_io + (address)))
-
-#define NCR53c7x0_read16(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int)readw((u32)NCR53c7x0_address_memory + (u32)(address)) :	\
-	inw(NCR53c7x0_address_io + (address)))
-#endif
-
-#ifdef __mc68000__
-#define NCR53c7x0_read32(address) 					\
-    ((unsigned int) raw_inl((u32)NCR53c7x0_address_memory + (u32)(address)))
-#else
-#define NCR53c7x0_read32(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int) readl((u32)NCR53c7x0_address_memory + (u32)(address)) : 	\
-	inl(NCR53c7x0_address_io + (address)))
-#endif /* mc68000*/
-
-#ifdef BIG_ENDIAN
-/* If we are big-endian, then we are not Intel, so probably don't have
- * an i/o map as well as a memory map.  So, let's assume memory mapped.
- * Also, I am having terrible problems trying to persuade the compiler
- * not to lay down code which does a read after write for these macros.
- * If you remove 'volatile' from writeb() and friends it is ok....
- */
-
-#define NCR53c7x0_write8(address,value) 				\
-	*(volatile unsigned char *)					\
-		((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) = (value)
-
-#define NCR53c7x0_write16(address,value) 				\
-	*(volatile unsigned short *)					\
-		((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) = (value)
-
-#define NCR53c7x0_write32(address,value) 				\
-	*(volatile unsigned long *)					\
-		((u32)NCR53c7x0_address_memory + ((u32)(address))) = (value)
-
-#else
-
-#define NCR53c7x0_write8(address,value) 				\
-    (NCR53c7x0_memory_mapped ? 						\
-     ({writeb((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :	\
-	outb((value), NCR53c7x0_address_io + (address)))
-
-#define NCR53c7x0_write16(address,value) 				\
-    (NCR53c7x0_memory_mapped ? 						\
-     ({writew((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :	\
-	outw((value), NCR53c7x0_address_io + (address)))
-
-#define NCR53c7x0_write32(address,value) 				\
-    (NCR53c7x0_memory_mapped ? 						\
-     ({writel((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :	\
-	outl((value), NCR53c7x0_address_io + (address)))
-
-#endif
-
-/* Patch arbitrary 32 bit words in the script */
-#define patch_abs_32(script, offset, symbol, value)			\
-    	for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof 		\
-    	    (u32)); ++i) {					\
-	    (script)[A_##symbol##_used[i] - (offset)] += (value);	\
-	    if (hostdata->options & OPTION_DEBUG_FIXUP) 		\
-	      printk("scsi%d : %s reference %d at 0x%x in %s is now 0x%x\n",\
-		host->host_no, #symbol, i, A_##symbol##_used[i] - 	\
-		(int)(offset), #script, (script)[A_##symbol##_used[i] -	\
-		(offset)]);						\
-    	}
-
-/* Patch read/write instruction immediate field */
-#define patch_abs_rwri_data(script, offset, symbol, value)		\
-    	for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof 		\
-    	    (u32)); ++i)					\
-    	    (script)[A_##symbol##_used[i] - (offset)] =			\
-	    	((script)[A_##symbol##_used[i] - (offset)] & 		\
-	    	~DBC_RWRI_IMMEDIATE_MASK) | 				\
-    	    	(((value) << DBC_RWRI_IMMEDIATE_SHIFT) &		\
-		 DBC_RWRI_IMMEDIATE_MASK)
-
-/* Patch transfer control instruction data field */
-#define patch_abs_tci_data(script, offset, symbol, value)	        \
-    	for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof 		\
-    	    (u32)); ++i)					\
-    	    (script)[A_##symbol##_used[i] - (offset)] =			\
-	    	((script)[A_##symbol##_used[i] - (offset)] & 		\
-	    	~DBC_TCI_DATA_MASK) | 					\
-    	    	(((value) << DBC_TCI_DATA_SHIFT) &			\
-		 DBC_TCI_DATA_MASK)
-
-/* Patch field in dsa structure (assignment should be +=?) */
-#define patch_dsa_32(dsa, symbol, word, value)				\
-	{								\
-	(dsa)[(hostdata->##symbol - hostdata->dsa_start) / sizeof(u32)	\
-	    + (word)] = (value);					\
-	if (hostdata->options & OPTION_DEBUG_DSA)			\
-	    printk("scsi : dsa %s symbol %s(%d) word %d now 0x%x\n",	\
-		#dsa, #symbol, hostdata->##symbol, 			\
-		(word), (u32) (value));					\
-	}
-
-/* Paranoid people could use panic() here. */
-#define FATAL(host) shutdown((host));
-
-extern int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
-			  unsigned long base, int io_port, int irq, int dma,
-			  long long options, int clock);
-
-#endif /* NCR53c710_C */
-#endif /* NCR53c710_H */
diff --git a/drivers/scsi/53c7xx.scr b/drivers/scsi/53c7xx.scr
deleted file mode 100644
index 9c5694a..0000000
--- a/drivers/scsi/53c7xx.scr
+++ /dev/null
@@ -1,1591 +0,0 @@
-#undef DEBUG
-#undef EVENTS
-#undef NO_SELECTION_TIMEOUT
-#define BIG_ENDIAN
-
-; 53c710 driver.  Modified from Drew Eckhardts driver
-; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
-;
-; I have left the script for the 53c8xx family in here, as it is likely
-; to be useful to see what I changed when bug hunting.
-
-; NCR 53c810 driver, main script
-; Sponsored by 
-;	iX Multiuser Multitasking Magazine
-;	hm@ix.de
-;
-; Copyright 1993, 1994, 1995 Drew Eckhardt
-;      Visionary Computing 
-;      (Unix and Linux consulting and custom programming)
-;      drew@PoohSticks.ORG
-;      +1 (303) 786-7975
-;
-; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
-;
-; PRE-ALPHA
-;
-; For more information, please consult 
-;
-; NCR 53C810
-; PCI-SCSI I/O Processor
-; Data Manual
-;
-; NCR 53C710 
-; SCSI I/O Processor
-; Programmers Guide
-;
-; NCR Microelectronics
-; 1635 Aeroplaza Drive
-; Colorado Springs, CO 80916
-; 1+ (719) 578-3400
-;
-; Toll free literature number
-; +1 (800) 334-5454
-;
-; IMPORTANT : This code is self modifying due to the limitations of 
-;	the NCR53c7,8xx series chips.  Persons debugging this code with
-;	the remote debugger should take this into account, and NOT set
-;	breakpoints in modified instructions.
-;
-; Design:
-; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
-; microcontroller using a simple instruction set.   
-;
-; So, to minimize the effects of interrupt latency, and to maximize 
-; throughput, this driver offloads the practical maximum amount 
-; of processing to the SCSI chip while still maintaining a common
-; structure.
-;
-; Where tradeoffs were needed between efficiency on the older
-; chips and the newer NCR53c800 series, the NCR53c800 series 
-; was chosen.
-;
-; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
-; automate SCSI transfers without host processor intervention, this 
-; isn't the case with the NCR53c710 and newer chips which allow 
-;
-; - reads and writes to the internal registers from within the SCSI
-; 	scripts, allowing the SCSI SCRIPTS(tm) code to save processor
-; 	state so that multiple threads of execution are possible, and also
-; 	provide an ALU for loop control, etc.
-; 
-; - table indirect addressing for some instructions. This allows 
-;	pointers to be located relative to the DSA ((Data Structure
-;	Address) register.
-;
-; These features make it possible to implement a mailbox style interface,
-; where the same piece of code is run to handle I/O for multiple threads
-; at once minimizing our need to relocate code.  Since the NCR53c700/
-; NCR53c800 series have a unique combination of features, making a 
-; a standard ingoing/outgoing mailbox system, costly, I've modified it.
-;
-; - Mailboxes are a mixture of code and data.  This lets us greatly
-; 	simplify the NCR53c810 code and do things that would otherwise
-;	not be possible.
-;
-; The saved data pointer is now implemented as follows :
-;
-; 	Control flow has been architected such that if control reaches
-;	munge_save_data_pointer, on a restore pointers message or 
-;	reconnection, a jump to the address formerly in the TEMP register
-;	will allow the SCSI command to resume execution.
-;
-
-;
-; Note : the DSA structures must be aligned on 32 bit boundaries,
-; since the source and destination of MOVE MEMORY instructions 
-; must share the same alignment and this is the alignment of the
-; NCR registers.
-;
-
-; For some systems (MVME166, for example) dmode is always the same, so don't
-; waste time writing it
-
-#if 1
-#define DMODE_MEMORY_TO_NCR
-#define DMODE_MEMORY_TO_MEMORY
-#define DMODE_NCR_TO_MEMORY
-#else
-#define DMODE_MEMORY_TO_NCR    MOVE dmode_memory_to_ncr TO DMODE
-#define DMODE_MEMORY_TO_MEMORY MOVE dmode_memory_to_memory TO DMODE
-#define DMODE_NCR_TO_MEMORY    MOVE dmode_ncr_to_memory TO DMODE
-#endif
-
-ABSOLUTE dsa_temp_lun = 0		; Patch to lun for current dsa
-ABSOLUTE dsa_temp_next = 0		; Patch to dsa next for current dsa
-ABSOLUTE dsa_temp_addr_next = 0		; Patch to address of dsa next address 
-					; 	for current dsa
-ABSOLUTE dsa_temp_sync = 0		; Patch to address of per-target
-					;	sync routine
-ABSOLUTE dsa_sscf_710 = 0		; Patch to address of per-target
-					;	sscf value (53c710)
-ABSOLUTE dsa_temp_target = 0		; Patch to id for current dsa
-ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
-					; 	saved data pointer
-ABSOLUTE dsa_temp_addr_residual = 0	; Patch to address of per-command
-					;	current residual code
-ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
-					; saved residual code
-ABSOLUTE dsa_temp_addr_new_value = 0	; Address of value for JUMP operand
-ABSOLUTE dsa_temp_addr_array_value = 0 	; Address to copy to
-ABSOLUTE dsa_temp_addr_dsa_value = 0	; Address of this DSA value
-
-;
-; Once a device has initiated reselection, we need to compare it 
-; against the singly linked list of commands which have disconnected
-; and are pending reselection.  These commands are maintained in 
-; an unordered singly linked list of DSA structures, through the
-; DSA pointers at their 'centers' headed by the reconnect_dsa_head
-; pointer.
-; 
-; To avoid complications in removing commands from the list,
-; I minimize the amount of expensive (at eight operations per
-; addition @ 500-600ns each) pointer operations which must
-; be done in the NCR driver by precomputing them on the 
-; host processor during dsa structure generation.
-;
-; The fixed-up per DSA code knows how to recognize the nexus
-; associated with the corresponding SCSI command, and modifies
-; the source and destination pointers for the MOVE MEMORY 
-; instruction which is executed when reselected_ok is called
-; to remove the command from the list.  Similarly, DSA is 
-; loaded with the address of the next DSA structure and
-; reselected_check_next is called if a failure occurs.
-;
-; Perhaps more concisely, the net effect of the mess is 
-;
-; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
-;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
-; 	src = &dsa->next;
-; 	if (target_id == dsa->id && target_lun == dsa->lun) {
-; 		*dest = *src;
-; 		break;
-;         }	
-; }
-;
-; if (!dsa)
-;           error (int_err_unexpected_reselect);
-; else  
-;     longjmp (dsa->jump_resume, 0);
-;
-; 	
-
-#if (CHIP != 700) && (CHIP != 70066)
-; Define DSA structure used for mailboxes
-ENTRY dsa_code_template
-dsa_code_template:
-ENTRY dsa_code_begin
-dsa_code_begin:
-; RGH: Don't care about TEMP and DSA here
-	DMODE_MEMORY_TO_NCR
-	MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
-	DMODE_MEMORY_TO_MEMORY
-#if (CHIP == 710)
-	MOVE MEMORY 4, addr_scratch, saved_dsa
-	; We are about to go and select the device, so must set SSCF bits
-	MOVE MEMORY 4, dsa_sscf_710, addr_scratch
-#ifdef BIG_ENDIAN
-	MOVE SCRATCH3 TO SFBR
-#else
-	MOVE SCRATCH0 TO SFBR
-#endif
-	MOVE SFBR TO SBCL
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-#else
-	CALL scratch_to_dsa
-#endif
-	CALL select
-; Handle the phase mismatch which may have resulted from the 
-; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
-; may or may not be necessary, and we should update script_asm.pl
-; to handle multiple pieces.
-    CLEAR ATN
-    CLEAR ACK
-
-; Replace second operand with address of JUMP instruction dest operand
-; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
-ENTRY dsa_code_fix_jump
-dsa_code_fix_jump:
-	MOVE MEMORY 4, NOP_insn, 0
-	JUMP select_done
-
-; wrong_dsa loads the DSA register with the value of the dsa_next
-; field.
-;
-wrong_dsa:
-#if (CHIP == 710)
-;                NOTE DSA is corrupt when we arrive here!
-#endif
-;		Patch the MOVE MEMORY INSTRUCTION such that 
-;		the destination address is the address of the OLD 
-;		next pointer.
-;
-	MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8
-	DMODE_MEMORY_TO_NCR
-;
-; 	Move the _contents_ of the next pointer into the DSA register as 
-;	the next I_T_L or I_T_L_Q tupple to check against the established
-;	nexus.
-;
-	MOVE MEMORY 4, dsa_temp_next, addr_scratch
-	DMODE_MEMORY_TO_MEMORY
-#if (CHIP == 710)
-	MOVE MEMORY 4, addr_scratch, saved_dsa
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-#else
-	CALL scratch_to_dsa
-#endif
-	JUMP reselected_check_next
-
-ABSOLUTE dsa_save_data_pointer = 0
-ENTRY dsa_code_save_data_pointer
-dsa_code_save_data_pointer:
-#if (CHIP == 710)
-	; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt
-	; We MUST return with DSA correct
-    	MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
-        CLEAR ACK
-#ifdef DEBUG
-        INT int_debug_saved
-#endif
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-	JUMP jump_temp
-#else
-    	DMODE_NCR_TO_MEMORY
-    	MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer
-    	DMODE_MEMORY_TO_MEMORY
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
-        CLEAR ACK
-#ifdef DEBUG
-        INT int_debug_saved
-#endif
-    	RETURN
-#endif
-ABSOLUTE dsa_restore_pointers = 0
-ENTRY dsa_code_restore_pointers
-dsa_code_restore_pointers:
-#if (CHIP == 710)
-	; TEMP and DSA are corrupt when we get here, but who cares!
-    	MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
-        CLEAR ACK
-	; Restore DSA, note we don't care about TEMP
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-#ifdef DEBUG
-        INT int_debug_restored
-#endif
-	JUMP jump_temp
-#else
-    	DMODE_MEMORY_TO_NCR
-    	MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp
-    	DMODE_MEMORY_TO_MEMORY
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
-        CLEAR ACK
-#ifdef DEBUG
-        INT int_debug_restored
-#endif
-    	RETURN
-#endif
-
-ABSOLUTE dsa_check_reselect = 0
-; dsa_check_reselect determines whether or not the current target and
-; lun match the current DSA
-ENTRY dsa_code_check_reselect
-dsa_code_check_reselect:
-#if (CHIP == 710)
-	/* Arrives here with DSA correct */
-	/* Assumes we are always ID 7 */
-	MOVE LCRC TO SFBR		; LCRC has our ID and his ID bits set
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80
-#else
-	MOVE SSID TO SFBR		; SSID contains 3 bit target ID
-; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8
-#endif
-;
-; Hack - move to scratch first, since SFBR is not writeable
-; 	via the CPU and hence a MOVE MEMORY instruction.
-;
-	DMODE_MEMORY_TO_NCR
-	MOVE MEMORY 1, reselected_identify, addr_scratch
-	DMODE_MEMORY_TO_MEMORY
-#ifdef BIG_ENDIAN
-	; BIG ENDIAN ON MVME16x
-	MOVE SCRATCH3 TO SFBR
-#else
-	MOVE SCRATCH0 TO SFBR
-#endif
-; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
-; Are you sure about that?  richard@sleepie.demon.co.uk
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
-;		Patch the MOVE MEMORY INSTRUCTION such that
-;		the source address is the address of this dsa's
-;		next pointer.
-	MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4
-	CALL reselected_ok
-#if (CHIP == 710)
-;	Restore DSA following memory moves in reselected_ok
-;	dsa_temp_sync doesn't really care about DSA, but it has an
-;	optional debug INT so a valid DSA is a good idea.
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-	CALL dsa_temp_sync	
-; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
-; transfer parameters! 
-	CLEAR ACK
-; Implicitly restore pointers on reselection, so a RETURN
-; will transfer control back to the right spot.
-    	CALL REL (dsa_code_restore_pointers)
-    	RETURN
-ENTRY dsa_zero
-dsa_zero:
-ENTRY dsa_code_template_end
-dsa_code_template_end:
-
-; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
-; dsa_zero, puke.
-
-ABSOLUTE dsa_fields_start =  0	; Sanity marker
-				; 	pad 48 bytes (fix this RSN)
-ABSOLUTE dsa_next = 48		; len 4 Next DSA
- 				; del 4 Previous DSA address
-ABSOLUTE dsa_cmnd = 56		; len 4 Scsi_Cmnd * for this thread.
-ABSOLUTE dsa_select = 60	; len 4 Device ID, Period, Offset for 
-			 	;	table indirect select
-ABSOLUTE dsa_msgout = 64	; len 8 table indirect move parameter for 
-				;       select message
-ABSOLUTE dsa_cmdout = 72	; len 8 table indirect move parameter for 
-				;	command
-ABSOLUTE dsa_dataout = 80	; len 4 code pointer for dataout
-ABSOLUTE dsa_datain = 84	; len 4 code pointer for datain
-ABSOLUTE dsa_msgin = 88		; len 8 table indirect move for msgin
-ABSOLUTE dsa_status = 96 	; len 8 table indirect move for status byte
-ABSOLUTE dsa_msgout_other = 104	; len 8 table indirect for normal message out
-				; (Synchronous transfer negotiation, etc).
-ABSOLUTE dsa_end = 112
-
-ABSOLUTE schedule = 0 		; Array of JUMP dsa_begin or JUMP (next),
-				; terminated by a call to JUMP wait_reselect
-
-; Linked lists of DSA structures
-ABSOLUTE reconnect_dsa_head = 0	; Link list of DSAs which can reconnect
-ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
-				; address of reconnect_dsa_head
-
-; These select the source and destination of a MOVE MEMORY instruction
-ABSOLUTE dmode_memory_to_memory = 0x0
-ABSOLUTE dmode_memory_to_ncr = 0x0
-ABSOLUTE dmode_ncr_to_memory = 0x0
-
-ABSOLUTE addr_scratch = 0x0
-ABSOLUTE addr_temp = 0x0
-#if (CHIP == 710)
-ABSOLUTE saved_dsa = 0x0
-ABSOLUTE emulfly = 0x0
-ABSOLUTE addr_dsa = 0x0
-#endif
-#endif /* CHIP != 700 && CHIP != 70066 */
-
-; Interrupts - 
-; MSB indicates type
-; 0	handle error condition
-; 1 	handle message 
-; 2 	handle normal condition
-; 3	debugging interrupt
-; 4 	testing interrupt 
-; Next byte indicates specific error
-
-; XXX not yet implemented, I'm not sure if I want to - 
-; Next byte indicates the routine the error occurred in
-; The LSB indicates the specific place the error occurred
- 
-ABSOLUTE int_err_unexpected_phase = 0x00000000	; Unexpected phase encountered
-ABSOLUTE int_err_selected = 0x00010000		; SELECTED (nee RESELECTED)
-ABSOLUTE int_err_unexpected_reselect = 0x00020000 
-ABSOLUTE int_err_check_condition = 0x00030000	
-ABSOLUTE int_err_no_phase = 0x00040000
-ABSOLUTE int_msg_wdtr = 0x01000000		; WDTR message received
-ABSOLUTE int_msg_sdtr = 0x01010000		; SDTR received
-ABSOLUTE int_msg_1 = 0x01020000			; single byte special message
-						; received
-
-ABSOLUTE int_norm_select_complete = 0x02000000	; Select complete, reprogram
-						; registers.
-ABSOLUTE int_norm_reselect_complete = 0x02010000	; Nexus established
-ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
-ABSOLUTE int_norm_disconnected = 0x02030000	; Disconnected 
-ABSOLUTE int_norm_aborted =0x02040000		; Aborted *dsa
-ABSOLUTE int_norm_reset = 0x02050000		; Generated BUS reset.
-ABSOLUTE int_norm_emulateintfly = 0x02060000	; 53C710 Emulated intfly
-ABSOLUTE int_debug_break = 0x03000000		; Break point
-#ifdef DEBUG
-ABSOLUTE int_debug_scheduled = 0x03010000	; new I/O scheduled 
-ABSOLUTE int_debug_idle = 0x03020000		; scheduler is idle
-ABSOLUTE int_debug_dsa_loaded = 0x03030000	; dsa reloaded
-ABSOLUTE int_debug_reselected = 0x03040000	; NCR reselected
-ABSOLUTE int_debug_head = 0x03050000		; issue head overwritten
-ABSOLUTE int_debug_disconnected = 0x03060000	; disconnected
-ABSOLUTE int_debug_disconnect_msg = 0x03070000	; got message to disconnect
-ABSOLUTE int_debug_dsa_schedule = 0x03080000	; in dsa_schedule
-ABSOLUTE int_debug_reselect_check = 0x03090000  ; Check for reselection of DSA
-ABSOLUTE int_debug_reselected_ok = 0x030a0000 	; Reselection accepted
-#endif
-ABSOLUTE int_debug_panic = 0x030b0000		; Panic driver
-#ifdef DEBUG
-ABSOLUTE int_debug_saved = 0x030c0000 		; save/restore pointers
-ABSOLUTE int_debug_restored = 0x030d0000
-ABSOLUTE int_debug_sync = 0x030e0000		; Sanity check synchronous 
-						; parameters. 
-ABSOLUTE int_debug_datain = 0x030f0000		; going into data in phase 
-						; now.
-ABSOLUTE int_debug_check_dsa = 0x03100000	; Sanity check DSA against
-						; SDID.
-#endif
-
-ABSOLUTE int_test_1 = 0x04000000		; Test 1 complete
-ABSOLUTE int_test_2 = 0x04010000		; Test 2 complete
-ABSOLUTE int_test_3 = 0x04020000		; Test 3 complete
-
-
-; These should start with 0x05000000, with low bits incrementing for 
-; each one.
-
-#ifdef EVENTS
-ABSOLUTE int_EVENT_SELECT = 0
-ABSOLUTE int_EVENT_DISCONNECT = 0
-ABSOLUTE int_EVENT_RESELECT = 0
-ABSOLUTE int_EVENT_COMPLETE = 0
-ABSOLUTE int_EVENT_IDLE = 0
-ABSOLUTE int_EVENT_SELECT_FAILED = 0
-ABSOLUTE int_EVENT_BEFORE_SELECT = 0
-ABSOLUTE int_EVENT_RESELECT_FAILED = 0
-#endif
-						
-ABSOLUTE NCR53c7xx_msg_abort = 0	; Pointer to abort message
-ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
-ABSOLUTE NCR53c7xx_zero	= 0		; long with zero in it, use for source
-ABSOLUTE NCR53c7xx_sink = 0		; long to dump worthless data in
-ABSOLUTE NOP_insn = 0			; NOP instruction
-
-; Pointer to message, potentially multi-byte
-ABSOLUTE msg_buf = 0
-
-; Pointer to holding area for reselection information
-ABSOLUTE reselected_identify = 0
-ABSOLUTE reselected_tag = 0
-
-; Request sense command pointer, it's a 6 byte command, should
-; be constant for all commands since we always want 16 bytes of 
-; sense and we don't need to change any fields as we did under 
-; SCSI-I when we actually cared about the LUN field.
-;EXTERNAL NCR53c7xx_sense		; Request sense command
-
-#if (CHIP != 700) && (CHIP != 70066)
-; dsa_schedule  
-; PURPOSE : after a DISCONNECT message has been received, and pointers
-;	saved, insert the current DSA structure at the head of the 
-; 	disconnected queue and fall through to the scheduler.
-;
-; CALLS : OK
-;
-; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
-;	of disconnected commands
-;
-; MODIFIES : SCRATCH, reconnect_dsa_head
-; 
-; EXITS : always passes control to schedule
-
-ENTRY dsa_schedule
-dsa_schedule:
-#ifdef DEBUG
-    INT int_debug_dsa_schedule
-#endif
-
-;
-; Calculate the address of the next pointer within the DSA 
-; structure of the command that is currently disconnecting
-;
-#if (CHIP == 710)
-    ; Read what should be the current DSA from memory - actual DSA
-    ; register is probably corrupt
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-#else
-    CALL dsa_to_scratch
-#endif
-    MOVE SCRATCH0 + dsa_next TO SCRATCH0
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
-
-; Point the next field of this DSA structure at the current disconnected 
-; list
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
-    DMODE_MEMORY_TO_MEMORY
-dsa_schedule_insert:
-    MOVE MEMORY 4, reconnect_dsa_head, 0 
-
-; And update the head pointer.
-#if (CHIP == 710)
-    ; Read what should be the current DSA from memory - actual DSA
-    ; register is probably corrupt
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-#else
-    CALL dsa_to_scratch
-#endif
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
-    DMODE_MEMORY_TO_MEMORY
-/* Temporarily, see what happens. */
-#ifndef ORIGINAL
-#if (CHIP != 710)
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#endif
-    CLEAR ACK
-#endif
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-    WAIT DISCONNECT
-#ifdef EVENTS
-    INT int_EVENT_DISCONNECT;
-#endif
-#ifdef DEBUG
-    INT int_debug_disconnected
-#endif
-    JUMP schedule
-#endif 
-
-;
-; select
-;
-; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
-;	On success, the current DSA structure is removed from the issue 
-;	queue.  Usually, this is entered as a fall-through from schedule,
-;	although the contingent allegiance handling code will write
-;	the select entry address to the DSP to restart a command as a 
-;	REQUEST SENSE.  A message is sent (usually IDENTIFY, although
-;	additional SDTR or WDTR messages may be sent).  COMMAND OUT
-;	is handled.
-;
-; INPUTS : DSA - SCSI command, issue_dsa_head
-;
-; CALLS : NOT OK
-;
-; MODIFIES : SCRATCH, issue_dsa_head
-;
-; EXITS : on reselection or selection, go to select_failed
-;	otherwise, RETURN so control is passed back to 
-;	dsa_begin.
-;
-
-ENTRY select
-select:
-
-#ifdef EVENTS
-    INT int_EVENT_BEFORE_SELECT
-#endif
-
-#ifdef DEBUG
-    INT int_debug_scheduled
-#endif
-    CLEAR TARGET
-
-; XXX
-;
-; In effect, SELECTION operations are backgrounded, with execution
-; continuing until code which waits for REQ or a fatal interrupt is 
-; encountered.
-;
-; So, for more performance, we could overlap the code which removes 
-; the command from the NCRs issue queue with the selection, but 
-; at this point I don't want to deal with the error recovery.
-;
-
-#if (CHIP != 700) && (CHIP != 70066)
-#if (CHIP == 710)
-    ; Enable selection timer
-#ifdef NO_SELECTION_TIMEOUT
-    MOVE CTEST7 & 0xff TO CTEST7
-#else
-    MOVE CTEST7 & 0xef TO CTEST7
-#endif
-#endif
-    SELECT ATN FROM dsa_select, select_failed
-    JUMP select_msgout, WHEN MSG_OUT
-ENTRY select_msgout
-select_msgout:
-#if (CHIP == 710)
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-#endif
-    MOVE FROM dsa_msgout, WHEN MSG_OUT
-#else
-ENTRY select_msgout
-    SELECT ATN 0, select_failed
-select_msgout:
-    MOVE 0, 0, WHEN MSGOUT
-#endif
-
-#ifdef EVENTS
-   INT int_EVENT_SELECT
-#endif
-   RETURN
-
-; 
-; select_done
-; 
-; PURPOSE: continue on to normal data transfer; called as the exit 
-;	point from dsa_begin.
-;
-; INPUTS: dsa
-;
-; CALLS: OK
-;
-;
-
-select_done:
-#if (CHIP == 710)
-; NOTE DSA is corrupt when we arrive here!
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-
-#ifdef DEBUG
-ENTRY select_check_dsa
-select_check_dsa:
-    INT int_debug_check_dsa
-#endif
-
-; After a successful selection, we should get either a CMD phase or 
-; some transfer request negotiation message.
-
-    JUMP cmdout, WHEN CMD
-    INT int_err_unexpected_phase, WHEN NOT MSG_IN 
-
-select_msg_in:
-    CALL msg_in, WHEN MSG_IN
-    JUMP select_msg_in, WHEN MSG_IN
-
-cmdout:
-    INT int_err_unexpected_phase, WHEN NOT CMD
-#if (CHIP == 700)
-    INT int_norm_selected
-#endif
-ENTRY cmdout_cmdout
-cmdout_cmdout:
-#if (CHIP != 700) && (CHIP != 70066)
-    MOVE FROM dsa_cmdout, WHEN CMD
-#else
-    MOVE 0, 0, WHEN CMD
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-
-;
-; data_transfer  
-; other_out
-; other_in
-; other_transfer
-;
-; PURPOSE : handle the main data transfer for a SCSI command in 
-;	several parts.  In the first part, data_transfer, DATA_IN
-;	and DATA_OUT phases are allowed, with the user provided
-;	code (usually dynamically generated based on the scatter/gather
-;	list associated with a SCSI command) called to handle these 
-;	phases.
-;
-;	After control has passed to one of the user provided 
-;	DATA_IN or DATA_OUT routines, back calls are made to 
-;	other_transfer_in or other_transfer_out to handle non-DATA IN
-;	and DATA OUT phases respectively, with the state of the active
-;	data pointer being preserved in TEMP.
-;
-;	On completion, the user code passes control to other_transfer
-;	which causes DATA_IN and DATA_OUT to result in unexpected_phase
-;	interrupts so that data overruns may be trapped.
-;
-; INPUTS : DSA - SCSI command
-;
-; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
-;	other_transfer
-;
-; MODIFIES : SCRATCH
-;
-; EXITS : if STATUS IN is detected, signifying command completion,
-;	the NCR jumps to command_complete.  If MSG IN occurs, a 
-;	CALL is made to msg_in.  Otherwise, other_transfer runs in 
-;	an infinite loop.
-;	
-
-ENTRY data_transfer
-data_transfer:
-    JUMP cmdout_cmdout, WHEN CMD
-    CALL msg_in, WHEN MSG_IN
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-    JUMP do_dataout, WHEN DATA_OUT
-    JUMP do_datain, WHEN DATA_IN
-    JUMP command_complete, WHEN STATUS
-    JUMP data_transfer
-ENTRY end_data_transfer
-end_data_transfer:
-
-;
-; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
-; should be fixed up whenever the nexus changes so it can point to the 
-; correct routine for that command.
-;
-
-#if (CHIP != 700) && (CHIP != 70066)
-; Nasty jump to dsa->dataout
-do_dataout:
-#if (CHIP == 710)
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-#else
-    CALL dsa_to_scratch
-#endif
-    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0	
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
-    DMODE_MEMORY_TO_MEMORY
-dataout_to_jump:
-    MOVE MEMORY 4, 0, dataout_jump + 4 
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-dataout_jump:
-    JUMP 0
-
-; Nasty jump to dsa->dsain
-do_datain:
-#if (CHIP == 710)
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-#else
-    CALL dsa_to_scratch
-#endif
-    MOVE SCRATCH0 + dsa_datain TO SCRATCH0	
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
-    DMODE_MEMORY_TO_MEMORY
-ENTRY datain_to_jump
-datain_to_jump:
-    MOVE MEMORY 4, 0, datain_jump + 4
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-#ifdef DEBUG
-    INT int_debug_datain
-#endif
-datain_jump:
-    JUMP 0
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-
-
-; Note that other_out and other_in loop until a non-data phase
-; is discovered, so we only execute return statements when we
-; can go on to the next data phase block move statement.
-
-ENTRY other_out
-other_out:
-#if 0
-    INT 0x03ffdead
-#endif
-    INT int_err_unexpected_phase, WHEN CMD
-    JUMP msg_in_restart, WHEN MSG_IN 
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-    INT int_err_unexpected_phase, WHEN DATA_IN
-    JUMP command_complete, WHEN STATUS
-    JUMP other_out, WHEN NOT DATA_OUT
-#if (CHIP == 710)
-; TEMP should be OK, as we got here from a call in the user dataout code.
-#endif
-    RETURN
-
-ENTRY other_in
-other_in:
-#if 0
-    INT 0x03ffdead
-#endif
-    INT int_err_unexpected_phase, WHEN CMD
-    JUMP msg_in_restart, WHEN MSG_IN 
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-    INT int_err_unexpected_phase, WHEN DATA_OUT
-    JUMP command_complete, WHEN STATUS
-    JUMP other_in, WHEN NOT DATA_IN
-#if (CHIP == 710)
-; TEMP should be OK, as we got here from a call in the user datain code.
-#endif
-    RETURN
-
-
-ENTRY other_transfer
-other_transfer:
-    INT int_err_unexpected_phase, WHEN CMD
-    CALL msg_in, WHEN MSG_IN
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-    INT int_err_unexpected_phase, WHEN DATA_OUT
-    INT int_err_unexpected_phase, WHEN DATA_IN
-    JUMP command_complete, WHEN STATUS
-    JUMP other_transfer
-
-;
-; msg_in_restart
-; msg_in
-; munge_msg
-;
-; PURPOSE : process messages from a target.  msg_in is called when the 
-;	caller hasn't read the first byte of the message.  munge_message
-;	is called when the caller has read the first byte of the message,
-;	and left it in SFBR.  msg_in_restart is called when the caller 
-;	hasn't read the first byte of the message, and wishes RETURN
-;	to transfer control back to the address of the conditional
-;	CALL instruction rather than to the instruction after it.
-;
-;	Various int_* interrupts are generated when the host system
-;	needs to intervene, as is the case with SDTR, WDTR, and
-;	INITIATE RECOVERY messages.
-;
-;	When the host system handles one of these interrupts,
-;	it can respond by reentering at reject_message, 
-;	which rejects the message and returns control to
-;	the caller of msg_in or munge_msg, accept_message
-;	which clears ACK and returns control, or reply_message
-;	which sends the message pointed to by the DSA 
-;	msgout_other table indirect field.
-;
-;	DISCONNECT messages are handled by moving the command
-;	to the reconnect_dsa_queue.
-#if (CHIP == 710)
-; NOTE: DSA should be valid when we get here - we cannot save both it
-;	and TEMP in this routine.
-#endif
-;
-; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
-;	only)
-;
-; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
-;
-; MODIFIES : SCRATCH, DSA on DISCONNECT
-;
-; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
-;	and normal return from message handlers running under
-;	Linux, control is returned to the caller.  Receipt
-;	of DISCONNECT messages pass control to dsa_schedule.
-;
-ENTRY msg_in_restart
-msg_in_restart:
-; XXX - hackish
-;
-; Since it's easier to debug changes to the statically 
-; compiled code, rather than the dynamically generated 
-; stuff, such as
-;
-; 	MOVE x, y, WHEN data_phase
-; 	CALL other_z, WHEN NOT data_phase
-; 	MOVE x, y, WHEN data_phase
-;
-; I'd like to have certain routines (notably the message handler)
-; restart on the conditional call rather than the next instruction.
-;
-; So, subtract 8 from the return address
-
-    MOVE TEMP0 + 0xf8 TO TEMP0
-    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
-    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
-    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
-
-ENTRY msg_in
-msg_in:
-    MOVE 1, msg_buf, WHEN MSG_IN
-
-munge_msg:
-    JUMP munge_extended, IF 0x01		; EXTENDED MESSAGE
-    JUMP munge_2, IF 0x20, AND MASK 0xdf	; two byte message
-;
-; XXX - I've seen a handful of broken SCSI devices which fail to issue
-; 	a SAVE POINTERS message before disconnecting in the middle of 
-; 	a transfer, assuming that the DATA POINTER will be implicitly 
-; 	restored.  
-;
-; Historically, I've often done an implicit save when the DISCONNECT
-; message is processed.  We may want to consider having the option of 
-; doing that here. 
-;
-    JUMP munge_save_data_pointer, IF 0x02	; SAVE DATA POINTER
-    JUMP munge_restore_pointers, IF 0x03	; RESTORE POINTERS 
-    JUMP munge_disconnect, IF 0x04		; DISCONNECT
-    INT int_msg_1, IF 0x07			; MESSAGE REJECT
-    INT int_msg_1, IF 0x0f			; INITIATE RECOVERY
-#ifdef EVENTS 
-    INT int_EVENT_SELECT_FAILED 
-#endif
-    JUMP reject_message
-
-munge_2:
-    JUMP reject_message
-;
-; The SCSI standard allows targets to recover from transient 
-; error conditions by backing up the data pointer with a 
-; RESTORE POINTERS message.  
-;	
-; So, we must save and restore the _residual_ code as well as 
-; the current instruction pointer.  Because of this messiness,
-; it is simpler to put dynamic code in the dsa for this and to
-; just do a simple jump down there. 
-;
-
-munge_save_data_pointer:
-#if (CHIP == 710)
-    ; We have something in TEMP here, so first we must save that
-    MOVE TEMP0 TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE TEMP1 TO SFBR
-    MOVE SFBR TO SCRATCH1
-    MOVE TEMP2 TO SFBR
-    MOVE SFBR TO SCRATCH2
-    MOVE TEMP3 TO SFBR
-    MOVE SFBR TO SCRATCH3
-    MOVE MEMORY 4, addr_scratch, jump_temp + 4
-    ; Now restore DSA
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-    MOVE DSA0 + dsa_save_data_pointer TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE DSA1 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH1
-    MOVE DSA2 + 0xff TO SFBR WITH CARRY 
-    MOVE SFBR TO SCRATCH2
-    MOVE DSA3 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH3
-
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
-    DMODE_MEMORY_TO_MEMORY
-jump_dsa_save:
-    JUMP 0
-
-munge_restore_pointers:
-#if (CHIP == 710)
-    ; The code at dsa_restore_pointers will RETURN, but we don't care
-    ; about TEMP here, as it will overwrite it anyway.
-#endif
-    MOVE DSA0 + dsa_restore_pointers TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE DSA1 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH1
-    MOVE DSA2 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH2
-    MOVE DSA3 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH3
-
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
-    DMODE_MEMORY_TO_MEMORY
-jump_dsa_restore:
-    JUMP 0
-
-
-munge_disconnect:
-#ifdef DEBUG
-    INT int_debug_disconnect_msg
-#endif
-
-/* 
- * Before, we overlapped processing with waiting for disconnect, but
- * debugging was beginning to appear messy.  Temporarily move things
- * to just before the WAIT DISCONNECT.
- */
- 
-#ifdef ORIGINAL
-#if (CHIP == 710)
-; Following clears Unexpected Disconnect bit.  What do we do?
-#else
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#endif
-    CLEAR ACK
-#endif
-
-#if (CHIP != 700) && (CHIP != 70066)
-    JUMP dsa_schedule
-#else
-    WAIT DISCONNECT
-    INT int_norm_disconnected
-#endif
-
-munge_extended:
-    CLEAR ACK
-    INT int_err_unexpected_phase, WHEN NOT MSG_IN
-    MOVE 1, msg_buf + 1, WHEN MSG_IN
-    JUMP munge_extended_2, IF 0x02
-    JUMP munge_extended_3, IF 0x03 
-    JUMP reject_message
-
-munge_extended_2:
-    CLEAR ACK
-    MOVE 1, msg_buf + 2, WHEN MSG_IN
-    JUMP reject_message, IF NOT 0x02	; Must be WDTR
-    CLEAR ACK
-    MOVE 1, msg_buf + 3, WHEN MSG_IN
-    INT int_msg_wdtr
-
-munge_extended_3:
-    CLEAR ACK
-    MOVE 1, msg_buf + 2, WHEN MSG_IN
-    JUMP reject_message, IF NOT 0x01	; Must be SDTR
-    CLEAR ACK
-    MOVE 2, msg_buf + 3, WHEN MSG_IN
-    INT int_msg_sdtr
-
-ENTRY reject_message
-reject_message:
-    SET ATN
-    CLEAR ACK
-    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
-    RETURN
-
-ENTRY accept_message
-accept_message:
-    CLEAR ATN
-    CLEAR ACK
-    RETURN
-
-ENTRY respond_message
-respond_message:
-    SET ATN
-    CLEAR ACK
-    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
-    RETURN
-
-;
-; command_complete
-;
-; PURPOSE : handle command termination when STATUS IN is detected by reading
-;	a status byte followed by a command termination message. 
-;
-;	Normal termination results in an INTFLY instruction, and 
-;	the host system can pick out which command terminated by 
-;	examining the MESSAGE and STATUS buffers of all currently 
-;	executing commands;
-;
-;	Abnormal (CHECK_CONDITION) termination results in an
-;	int_err_check_condition interrupt so that a REQUEST SENSE
-;	command can be issued out-of-order so that no other command
-;	clears the contingent allegiance condition.
-;	
-;
-; INPUTS : DSA - command	
-;
-; CALLS : OK
-;
-; EXITS : On successful termination, control is passed to schedule.
-;	On abnormal termination, the user will usually modify the 
-;	DSA fields and corresponding buffers and return control
-;	to select.
-;
-
-ENTRY command_complete
-command_complete:
-    MOVE FROM dsa_status, WHEN STATUS
-#if (CHIP != 700) && (CHIP != 70066)
-    MOVE SFBR TO SCRATCH0		; Save status
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-ENTRY command_complete_msgin
-command_complete_msgin:
-    MOVE FROM dsa_msgin, WHEN MSG_IN
-; Indicate that we should be expecting a disconnect
-#if (CHIP != 710)
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#else
-    ; Above code cleared the Unexpected Disconnect bit, what do we do?
-#endif
-    CLEAR ACK
-#if (CHIP != 700) && (CHIP != 70066)
-    WAIT DISCONNECT
-
-;
-; The SCSI specification states that when a UNIT ATTENTION condition
-; is pending, as indicated by a CHECK CONDITION status message,
-; the target shall revert to asynchronous transfers.  Since
-; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
-; basis, and returning control to our scheduler could work on a command
-; running on another lun on that target using the old parameters, we must
-; interrupt the host processor to get them changed, or change them ourselves.
-;
-; Once SCSI-II tagged queueing is implemented, things will be even more
-; hairy, since contingent allegiance conditions exist on a per-target/lun
-; basis, and issuing a new command with a different tag would clear it.
-; In these cases, we must interrupt the host processor to get a request 
-; added to the HEAD of the queue with the request sense command, or we
-; must automatically issue the request sense command.
-
-#if 0
-    MOVE SCRATCH0 TO SFBR			
-    JUMP command_failed, IF 0x02
-#endif
-#if (CHIP == 710)
-#if defined(MVME16x_INTFLY)
-; For MVME16x (ie CHIP=710) we will force an INTFLY by triggering a software
-; interrupt (SW7).  We can use SCRATCH, as we are about to jump to
-; schedule, which corrupts it anyway.  Will probably remove this later,
-; but want to check performance effects first.
-
-#define INTFLY_ADDR     0xfff40070
-
-    MOVE 0 TO SCRATCH0
-    MOVE 0x80 TO SCRATCH1
-    MOVE 0 TO SCRATCH2
-    MOVE 0 TO SCRATCH3
-    MOVE MEMORY 4, addr_scratch, INTFLY_ADDR
-#else
-    INT int_norm_emulateintfly
-#endif
-#else
-    INTFLY
-#endif
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-#ifdef EVENTS
-    INT int_EVENT_COMPLETE
-#endif
-#if (CHIP != 700) && (CHIP != 70066)
-    JUMP schedule
-command_failed:
-    INT int_err_check_condition
-#else
-    INT int_norm_command_complete
-#endif
-
-;
-; wait_reselect
-;
-; PURPOSE : This is essentially the idle routine, where control lands
-;	when there are no new processes to schedule.  wait_reselect
-;	waits for reselection, selection, and new commands.
-;
-;	When a successful reselection occurs, with the aid 
-;	of fixed up code in each DSA, wait_reselect walks the 
-;	reconnect_dsa_queue, asking each dsa if the target ID
-;	and LUN match its.
-;
-;	If a match is found, a call is made back to reselected_ok,
-;	which through the miracles of self modifying code, extracts
-;	the found DSA from the reconnect_dsa_queue and then 
-;	returns control to the DSAs thread of execution.
-;
-; INPUTS : NONE
-;
-; CALLS : OK
-;
-; MODIFIES : DSA,
-;
-; EXITS : On successful reselection, control is returned to the 
-;	DSA which called reselected_ok.  If the WAIT RESELECT
-;	was interrupted by a new commands arrival signaled by 
-;	SIG_P, control is passed to schedule.  If the NCR is 
-;	selected, the host system is interrupted with an 
-;	int_err_selected which is usually responded to by
-;	setting DSP to the target_abort address.
-
-ENTRY wait_reselect
-wait_reselect:
-#ifdef EVENTS
-    int int_EVENT_IDLE
-#endif
-#ifdef DEBUG
-    int int_debug_idle
-#endif
-    WAIT RESELECT wait_reselect_failed
-
-reselected:
-#ifdef EVENTS
-    int int_EVENT_RESELECT
-#endif
-    CLEAR TARGET
-    DMODE_MEMORY_TO_MEMORY
-    ; Read all data needed to reestablish the nexus - 
-    MOVE 1, reselected_identify, WHEN MSG_IN
-    ; We used to CLEAR ACK here.
-#if (CHIP != 700) && (CHIP != 70066)
-#ifdef DEBUG
-    int int_debug_reselected
-#endif
-
-    ; Point DSA at the current head of the disconnected queue.
-    DMODE_MEMORY_TO_NCR
-    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
-    DMODE_MEMORY_TO_MEMORY
-#if (CHIP == 710)
-    MOVE MEMORY 4, addr_scratch, saved_dsa
-#else
-    CALL scratch_to_dsa
-#endif
-
-    ; Fix the update-next pointer so that the reconnect_dsa_head
-    ; pointer is the one that will be updated if this DSA is a hit 
-    ; and we remove it from the queue.
-
-    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-
-ENTRY reselected_check_next
-reselected_check_next:
-#ifdef DEBUG
-    INT int_debug_reselect_check
-#endif
-    ; Check for a NULL pointer.
-    MOVE DSA0 TO SFBR
-    JUMP reselected_not_end, IF NOT 0
-    MOVE DSA1 TO SFBR
-    JUMP reselected_not_end, IF NOT 0
-    MOVE DSA2 TO SFBR
-    JUMP reselected_not_end, IF NOT 0
-    MOVE DSA3 TO SFBR
-    JUMP reselected_not_end, IF NOT 0
-    INT int_err_unexpected_reselect
-
-reselected_not_end:
-    ;
-    ; XXX the ALU is only eight bits wide, and the assembler
-    ; wont do the dirt work for us.  As long as dsa_check_reselect
-    ; is negative, we need to sign extend with 1 bits to the full
-    ; 32 bit width of the address.
-    ;
-    ; A potential work around would be to have a known alignment 
-    ; of the DSA structure such that the base address plus 
-    ; dsa_check_reselect doesn't require carrying from bytes 
-    ; higher than the LSB.
-    ;
-
-    MOVE DSA0 TO SFBR
-    MOVE SFBR + dsa_check_reselect TO SCRATCH0
-    MOVE DSA1 TO SFBR
-    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
-    MOVE DSA2 TO SFBR
-    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
-    MOVE DSA3 TO SFBR
-    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
-
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, reselected_check + 4
-    DMODE_MEMORY_TO_MEMORY
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-reselected_check:
-    JUMP 0
-
-
-;
-;
-#if (CHIP == 710)
-; We have problems here - the memory move corrupts TEMP and DSA.  This
-; routine is called from DSA code, and patched from many places.  Scratch
-; is probably free when it is called.
-; We have to:
-;   copy temp to scratch, one byte at a time
-;   write scratch to patch a jump in place of the return
-;   do the move memory
-;   jump to the patched in return address
-; DSA is corrupt when we get here, and can be left corrupt
-
-ENTRY reselected_ok
-reselected_ok:
-    MOVE TEMP0 TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE TEMP1 TO SFBR
-    MOVE SFBR TO SCRATCH1
-    MOVE TEMP2 TO SFBR
-    MOVE SFBR TO SCRATCH2
-    MOVE TEMP3 TO SFBR
-    MOVE SFBR TO SCRATCH3
-    MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4
-reselected_ok_patch:
-    MOVE MEMORY 4, 0, 0
-reselected_ok_jump:
-    JUMP 0
-#else
-ENTRY reselected_ok
-reselected_ok:
-reselected_ok_patch:
-    MOVE MEMORY 4, 0, 0				; Patched : first word
-						; 	is address of 
-						;       successful dsa_next
-						; Second word is last 
-						;	unsuccessful dsa_next,
-						;	starting with 
-						;       dsa_reconnect_head
-    ; We used to CLEAR ACK here.
-#ifdef DEBUG
-    INT int_debug_reselected_ok
-#endif
-#ifdef DEBUG
-    INT int_debug_check_dsa
-#endif
-    RETURN					; Return control to where
-#endif
-#else
-    INT int_norm_reselected
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-
-selected:
-    INT int_err_selected;
-
-;
-; A select or reselect failure can be caused by one of two conditions : 
-; 1.  SIG_P was set.  This will be the case if the user has written
-;	a new value to a previously NULL head of the issue queue.
-;
-; 2.  The NCR53c810 was selected or reselected by another device.
-;
-; 3.  The bus was already busy since we were selected or reselected
-;	before starting the command.
-
-wait_reselect_failed:
-#ifdef EVENTS 
-	INT int_EVENT_RESELECT_FAILED
-#endif
-; Check selected bit.  
-#if (CHIP == 710)
-    ; Must work out how to tell if we are selected....
-#else
-    MOVE SIST0 & 0x20 TO SFBR
-    JUMP selected, IF 0x20
-#endif
-; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
-    MOVE CTEST2 & 0x40 TO SFBR	
-    JUMP schedule, IF 0x40
-; Check connected bit.  
-; FIXME: this needs to change if we support target mode
-    MOVE ISTAT & 0x08 TO SFBR
-    JUMP reselected, IF 0x08
-; FIXME : Something bogus happened, and we shouldn't fail silently.
-#if 0
-    JUMP schedule
-#else
-    INT int_debug_panic
-#endif
-
-
-select_failed:
-#if (CHIP == 710)
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-#endif
-#ifdef EVENTS
-  int int_EVENT_SELECT_FAILED
-#endif
-; Otherwise, mask the selected and reselected bits off SIST0
-#if (CHIP ==710)
-    ; Let's assume we don't get selected for now
-    MOVE SSTAT0 & 0x10 TO SFBR
-#else
-    MOVE SIST0 & 0x30 TO SFBR
-    JUMP selected, IF 0x20
-#endif
-    JUMP reselected, IF 0x10 
-; If SIGP is set, the user just gave us another command, and
-; we should restart or return to the scheduler.
-; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
-    MOVE CTEST2 & 0x40 TO SFBR	
-    JUMP select, IF 0x40
-; Check connected bit.  
-; FIXME: this needs to change if we support target mode
-; FIXME: is this really necessary? 
-    MOVE ISTAT & 0x08 TO SFBR
-    JUMP reselected, IF 0x08
-; FIXME : Something bogus happened, and we shouldn't fail silently.
-#if 0
-    JUMP schedule
-#else
-    INT int_debug_panic
-#endif
-
-;
-; test_1
-; test_2
-;
-; PURPOSE : run some verification tests on the NCR.  test_1
-;	copies test_src to test_dest and interrupts the host
-;	processor, testing for cache coherency and interrupt
-; 	problems in the processes.
-;
-;	test_2 runs a command with offsets relative to the 
-;	DSA on entry, and is useful for miscellaneous experimentation.
-;
-
-; Verify that interrupts are working correctly and that we don't 
-; have a cache invalidation problem.
-
-ABSOLUTE test_src = 0, test_dest = 0
-ENTRY test_1
-test_1:
-    MOVE MEMORY 4, test_src, test_dest
-    INT int_test_1
-
-;
-; Run arbitrary commands, with test code establishing a DSA
-;
- 
-ENTRY test_2
-test_2:
-    CLEAR TARGET
-#if (CHIP == 710)
-    ; Enable selection timer
-#ifdef NO_SELECTION_TIMEOUT
-    MOVE CTEST7 & 0xff TO CTEST7
-#else
-    MOVE CTEST7 & 0xef TO CTEST7
-#endif
-#endif
-    SELECT ATN FROM 0, test_2_fail
-    JUMP test_2_msgout, WHEN MSG_OUT
-ENTRY test_2_msgout
-test_2_msgout:
-#if (CHIP == 710)
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-#endif
-    MOVE FROM 8, WHEN MSG_OUT
-    MOVE FROM 16, WHEN CMD 
-    MOVE FROM 24, WHEN DATA_IN
-    MOVE FROM 32, WHEN STATUS
-    MOVE FROM 40, WHEN MSG_IN
-#if (CHIP != 710)
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#endif
-    CLEAR ACK
-    WAIT DISCONNECT
-test_2_fail:
-#if (CHIP == 710)
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-#endif
-    INT int_test_2
-
-ENTRY debug_break
-debug_break:
-    INT int_debug_break
-
-;
-; initiator_abort
-; target_abort
-;
-; PURPOSE : Abort the currently established nexus from with initiator
-;	or target mode.
-;
-;  
-
-ENTRY target_abort
-target_abort:
-    SET TARGET
-    DISCONNECT
-    CLEAR TARGET
-    JUMP schedule
-    
-ENTRY initiator_abort
-initiator_abort:
-    SET ATN
-;
-; The SCSI-I specification says that targets may go into MSG out at 
-; their leisure upon receipt of the ATN single.  On all versions of the 
-; specification, we can't change phases until REQ transitions true->false, 
-; so we need to sink/source one byte of data to allow the transition.
-;
-; For the sake of safety, we'll only source one byte of data in all 
-; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
-; arbitrary number of bytes.
-    JUMP spew_cmd, WHEN CMD
-    JUMP eat_msgin, WHEN MSG_IN
-    JUMP eat_datain, WHEN DATA_IN
-    JUMP eat_status, WHEN STATUS
-    JUMP spew_dataout, WHEN DATA_OUT
-    JUMP sated
-spew_cmd:
-    MOVE 1, NCR53c7xx_zero, WHEN CMD
-    JUMP sated
-eat_msgin:
-    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
-    JUMP eat_msgin, WHEN MSG_IN
-    JUMP sated
-eat_status:
-    MOVE 1, NCR53c7xx_sink, WHEN STATUS
-    JUMP eat_status, WHEN STATUS
-    JUMP sated
-eat_datain:
-    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
-    JUMP eat_datain, WHEN DATA_IN
-    JUMP sated
-spew_dataout:
-    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
-sated:
-#if (CHIP != 710)
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#endif
-    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
-    WAIT DISCONNECT
-    INT int_norm_aborted
-
-#if (CHIP != 710)
-;
-; dsa_to_scratch
-; scratch_to_dsa
-;
-; PURPOSE :
-; 	The NCR chips cannot do a move memory instruction with the DSA register 
-; 	as the source or destination.  So, we provide a couple of subroutines
-; 	that let us switch between the DSA register and scratch register.
-;
-; 	Memory moves to/from the DSPS  register also don't work, but we 
-; 	don't use them.
-;
-;
-
- 
-dsa_to_scratch:
-    MOVE DSA0 TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE DSA1 TO SFBR
-    MOVE SFBR TO SCRATCH1
-    MOVE DSA2 TO SFBR
-    MOVE SFBR TO SCRATCH2
-    MOVE DSA3 TO SFBR
-    MOVE SFBR TO SCRATCH3
-    RETURN
-
-scratch_to_dsa:
-    MOVE SCRATCH0 TO SFBR
-    MOVE SFBR TO DSA0
-    MOVE SCRATCH1 TO SFBR
-    MOVE SFBR TO DSA1
-    MOVE SCRATCH2 TO SFBR
-    MOVE SFBR TO DSA2
-    MOVE SCRATCH3 TO SFBR
-    MOVE SFBR TO DSA3
-    RETURN
-#endif
- 
-#if (CHIP == 710)
-; Little patched jump, used to overcome problems with TEMP getting
-; corrupted on memory moves.
-
-jump_temp:
-    JUMP 0
-#endif
diff --git a/drivers/scsi/53c7xx_d.h_shipped b/drivers/scsi/53c7xx_d.h_shipped
deleted file mode 100644
index 21d31b0..0000000
--- a/drivers/scsi/53c7xx_d.h_shipped
+++ /dev/null
@@ -1,2874 +0,0 @@
-/* DO NOT EDIT - Generated automatically by script_asm.pl */
-static u32 SCRIPT[] = {
-/*
-
-
-
-
-
-; 53c710 driver.  Modified from Drew Eckhardts driver
-; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
-;
-; I have left the script for the 53c8xx family in here, as it is likely
-; to be useful to see what I changed when bug hunting.
-
-; NCR 53c810 driver, main script
-; Sponsored by 
-;	iX Multiuser Multitasking Magazine
-;	hm@ix.de
-;
-; Copyright 1993, 1994, 1995 Drew Eckhardt
-;      Visionary Computing 
-;      (Unix and Linux consulting and custom programming)
-;      drew@PoohSticks.ORG
-;      +1 (303) 786-7975
-;
-; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
-;
-; PRE-ALPHA
-;
-; For more information, please consult 
-;
-; NCR 53C810
-; PCI-SCSI I/O Processor
-; Data Manual
-;
-; NCR 53C710 
-; SCSI I/O Processor
-; Programmers Guide
-;
-; NCR Microelectronics
-; 1635 Aeroplaza Drive
-; Colorado Springs, CO 80916
-; 1+ (719) 578-3400
-;
-; Toll free literature number
-; +1 (800) 334-5454
-;
-; IMPORTANT : This code is self modifying due to the limitations of 
-;	the NCR53c7,8xx series chips.  Persons debugging this code with
-;	the remote debugger should take this into account, and NOT set
-;	breakpoints in modified instructions.
-;
-; Design:
-; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
-; microcontroller using a simple instruction set.   
-;
-; So, to minimize the effects of interrupt latency, and to maximize 
-; throughput, this driver offloads the practical maximum amount 
-; of processing to the SCSI chip while still maintaining a common
-; structure.
-;
-; Where tradeoffs were needed between efficiency on the older
-; chips and the newer NCR53c800 series, the NCR53c800 series 
-; was chosen.
-;
-; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
-; automate SCSI transfers without host processor intervention, this 
-; isn't the case with the NCR53c710 and newer chips which allow 
-;
-; - reads and writes to the internal registers from within the SCSI
-; 	scripts, allowing the SCSI SCRIPTS(tm) code to save processor
-; 	state so that multiple threads of execution are possible, and also
-; 	provide an ALU for loop control, etc.
-; 
-; - table indirect addressing for some instructions. This allows 
-;	pointers to be located relative to the DSA ((Data Structure
-;	Address) register.
-;
-; These features make it possible to implement a mailbox style interface,
-; where the same piece of code is run to handle I/O for multiple threads
-; at once minimizing our need to relocate code.  Since the NCR53c700/
-; NCR53c800 series have a unique combination of features, making a 
-; a standard ingoing/outgoing mailbox system, costly, I've modified it.
-;
-; - Mailboxes are a mixture of code and data.  This lets us greatly
-; 	simplify the NCR53c810 code and do things that would otherwise
-;	not be possible.
-;
-; The saved data pointer is now implemented as follows :
-;
-; 	Control flow has been architected such that if control reaches
-;	munge_save_data_pointer, on a restore pointers message or 
-;	reconnection, a jump to the address formerly in the TEMP register
-;	will allow the SCSI command to resume execution.
-;
-
-;
-; Note : the DSA structures must be aligned on 32 bit boundaries,
-; since the source and destination of MOVE MEMORY instructions 
-; must share the same alignment and this is the alignment of the
-; NCR registers.
-;
-
-; For some systems (MVME166, for example) dmode is always the same, so don't
-; waste time writing it
-
-
-
-
-
-
-
-
-
-
-
-ABSOLUTE dsa_temp_lun = 0		; Patch to lun for current dsa
-ABSOLUTE dsa_temp_next = 0		; Patch to dsa next for current dsa
-ABSOLUTE dsa_temp_addr_next = 0		; Patch to address of dsa next address 
-					; 	for current dsa
-ABSOLUTE dsa_temp_sync = 0		; Patch to address of per-target
-					;	sync routine
-ABSOLUTE dsa_sscf_710 = 0		; Patch to address of per-target
-					;	sscf value (53c710)
-ABSOLUTE dsa_temp_target = 0		; Patch to id for current dsa
-ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
-					; 	saved data pointer
-ABSOLUTE dsa_temp_addr_residual = 0	; Patch to address of per-command
-					;	current residual code
-ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
-					; saved residual code
-ABSOLUTE dsa_temp_addr_new_value = 0	; Address of value for JUMP operand
-ABSOLUTE dsa_temp_addr_array_value = 0 	; Address to copy to
-ABSOLUTE dsa_temp_addr_dsa_value = 0	; Address of this DSA value
-
-;
-; Once a device has initiated reselection, we need to compare it 
-; against the singly linked list of commands which have disconnected
-; and are pending reselection.  These commands are maintained in 
-; an unordered singly linked list of DSA structures, through the
-; DSA pointers at their 'centers' headed by the reconnect_dsa_head
-; pointer.
-; 
-; To avoid complications in removing commands from the list,
-; I minimize the amount of expensive (at eight operations per
-; addition @ 500-600ns each) pointer operations which must
-; be done in the NCR driver by precomputing them on the 
-; host processor during dsa structure generation.
-;
-; The fixed-up per DSA code knows how to recognize the nexus
-; associated with the corresponding SCSI command, and modifies
-; the source and destination pointers for the MOVE MEMORY 
-; instruction which is executed when reselected_ok is called
-; to remove the command from the list.  Similarly, DSA is 
-; loaded with the address of the next DSA structure and
-; reselected_check_next is called if a failure occurs.
-;
-; Perhaps more concisely, the net effect of the mess is 
-;
-; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
-;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
-; 	src = &dsa->next;
-; 	if (target_id == dsa->id && target_lun == dsa->lun) {
-; 		*dest = *src;
-; 		break;
-;         }	
-; }
-;
-; if (!dsa)
-;           error (int_err_unexpected_reselect);
-; else  
-;     longjmp (dsa->jump_resume, 0);
-;
-; 	
-
-
-; Define DSA structure used for mailboxes
-ENTRY dsa_code_template
-dsa_code_template:
-ENTRY dsa_code_begin
-dsa_code_begin:
-; RGH: Don't care about TEMP and DSA here
-	
-	MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
-
-at 0x00000000 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	
-
-	MOVE MEMORY 4, addr_scratch, saved_dsa
-
-at 0x00000003 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	; We are about to go and select the device, so must set SSCF bits
-	MOVE MEMORY 4, dsa_sscf_710, addr_scratch
-
-at 0x00000006 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-	MOVE SCRATCH3 TO SFBR
-
-at 0x00000009 : */	0x72370000,0x00000000,
-/*
-
-
-
-	MOVE SFBR TO SBCL
-
-at 0x0000000b : */	0x6a0b0000,0x00000000,
-/*
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x0000000d : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-	CALL select
-
-at 0x00000010 : */	0x88080000,0x000001f8,
-/*
-; Handle the phase mismatch which may have resulted from the 
-; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
-; may or may not be necessary, and we should update script_asm.pl
-; to handle multiple pieces.
-    CLEAR ATN
-
-at 0x00000012 : */	0x60000008,0x00000000,
-/*
-    CLEAR ACK
-
-at 0x00000014 : */	0x60000040,0x00000000,
-/*
-
-; Replace second operand with address of JUMP instruction dest operand
-; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
-ENTRY dsa_code_fix_jump
-dsa_code_fix_jump:
-	MOVE MEMORY 4, NOP_insn, 0
-
-at 0x00000016 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	JUMP select_done
-
-at 0x00000019 : */	0x80080000,0x00000230,
-/*
-
-; wrong_dsa loads the DSA register with the value of the dsa_next
-; field.
-;
-wrong_dsa:
-
-;                NOTE DSA is corrupt when we arrive here!
-
-;		Patch the MOVE MEMORY INSTRUCTION such that 
-;		the destination address is the address of the OLD 
-;		next pointer.
-;
-	MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8
-
-at 0x0000001b : */	0xc0000004,0x00000000,0x000007ec,
-/*
-	
-;
-; 	Move the _contents_ of the next pointer into the DSA register as 
-;	the next I_T_L or I_T_L_Q tupple to check against the established
-;	nexus.
-;
-	MOVE MEMORY 4, dsa_temp_next, addr_scratch
-
-at 0x0000001e : */	0xc0000004,0x00000000,0x00000000,
-/*
-	
-
-	MOVE MEMORY 4, addr_scratch, saved_dsa
-
-at 0x00000021 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x00000024 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-	JUMP reselected_check_next
-
-at 0x00000027 : */	0x80080000,0x000006f0,
-/*
-
-ABSOLUTE dsa_save_data_pointer = 0
-ENTRY dsa_code_save_data_pointer
-dsa_code_save_data_pointer:
-
-	; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt
-	; We MUST return with DSA correct
-    	MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer
-
-at 0x00000029 : */	0xc0000004,0x000009c8,0x00000000,
-/*
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
-
-at 0x0000002c : */	0xc0000018,0x00000000,0x00000000,
-/*
-        CLEAR ACK
-
-at 0x0000002f : */	0x60000040,0x00000000,
-/*
-
-
-
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x00000031 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	JUMP jump_temp
-
-at 0x00000034 : */	0x80080000,0x000009c4,
-/*
-
-ABSOLUTE dsa_restore_pointers = 0
-ENTRY dsa_code_restore_pointers
-dsa_code_restore_pointers:
-
-	; TEMP and DSA are corrupt when we get here, but who cares!
-    	MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4
-
-at 0x00000036 : */	0xc0000004,0x00000000,0x000009c8,
-/*
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
-
-at 0x00000039 : */	0xc0000018,0x00000000,0x00000000,
-/*
-        CLEAR ACK
-
-at 0x0000003c : */	0x60000040,0x00000000,
-/*
-	; Restore DSA, note we don't care about TEMP
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x0000003e : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-	JUMP jump_temp
-
-at 0x00000041 : */	0x80080000,0x000009c4,
-/*
-
-
-ABSOLUTE dsa_check_reselect = 0
-; dsa_check_reselect determines whether or not the current target and
-; lun match the current DSA
-ENTRY dsa_code_check_reselect
-dsa_code_check_reselect:
-
-	
-	
-	MOVE LCRC TO SFBR		; LCRC has our ID and his ID bits set
-
-at 0x00000043 : */	0x72230000,0x00000000,
-/*
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80
-
-at 0x00000045 : */	0x80848000,0x00ffff50,
-/*
-
-
-
-
-
-;
-; Hack - move to scratch first, since SFBR is not writeable
-; 	via the CPU and hence a MOVE MEMORY instruction.
-;
-	
-	MOVE MEMORY 1, reselected_identify, addr_scratch
-
-at 0x00000047 : */	0xc0000001,0x00000000,0x00000000,
-/*
-	
-
-	; BIG ENDIAN ON MVME16x
-	MOVE SCRATCH3 TO SFBR
-
-at 0x0000004a : */	0x72370000,0x00000000,
-/*
-
-
-
-; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
-; Are you sure about that?  richard@sleepie.demon.co.uk
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
-
-at 0x0000004c : */	0x8084f800,0x00ffff34,
-/*
-;		Patch the MOVE MEMORY INSTRUCTION such that
-;		the source address is the address of this dsa's
-;		next pointer.
-	MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4
-
-at 0x0000004e : */	0xc0000004,0x00000000,0x000007e8,
-/*
-	CALL reselected_ok
-
-at 0x00000051 : */	0x88080000,0x00000798,
-/*
-
-;	Restore DSA following memory moves in reselected_ok
-;	dsa_temp_sync doesn't really care about DSA, but it has an
-;	optional debug INT so a valid DSA is a good idea.
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x00000053 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-	CALL dsa_temp_sync	
-
-at 0x00000056 : */	0x88080000,0x00000000,
-/*
-; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
-; transfer parameters! 
-	CLEAR ACK
-
-at 0x00000058 : */	0x60000040,0x00000000,
-/*
-; Implicitly restore pointers on reselection, so a RETURN
-; will transfer control back to the right spot.
-    	CALL REL (dsa_code_restore_pointers)
-
-at 0x0000005a : */	0x88880000,0x00ffff68,
-/*
-    	RETURN
-
-at 0x0000005c : */	0x90080000,0x00000000,
-/*
-ENTRY dsa_zero
-dsa_zero:
-ENTRY dsa_code_template_end
-dsa_code_template_end:
-
-; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
-; dsa_zero, puke.
-
-ABSOLUTE dsa_fields_start =  0	; Sanity marker
-				; 	pad 48 bytes (fix this RSN)
-ABSOLUTE dsa_next = 48		; len 4 Next DSA
- 				; del 4 Previous DSA address
-ABSOLUTE dsa_cmnd = 56		; len 4 Scsi_Cmnd * for this thread.
-ABSOLUTE dsa_select = 60	; len 4 Device ID, Period, Offset for 
-			 	;	table indirect select
-ABSOLUTE dsa_msgout = 64	; len 8 table indirect move parameter for 
-				;       select message
-ABSOLUTE dsa_cmdout = 72	; len 8 table indirect move parameter for 
-				;	command
-ABSOLUTE dsa_dataout = 80	; len 4 code pointer for dataout
-ABSOLUTE dsa_datain = 84	; len 4 code pointer for datain
-ABSOLUTE dsa_msgin = 88		; len 8 table indirect move for msgin
-ABSOLUTE dsa_status = 96 	; len 8 table indirect move for status byte
-ABSOLUTE dsa_msgout_other = 104	; len 8 table indirect for normal message out
-				; (Synchronous transfer negotiation, etc).
-ABSOLUTE dsa_end = 112
-
-ABSOLUTE schedule = 0 		; Array of JUMP dsa_begin or JUMP (next),
-				; terminated by a call to JUMP wait_reselect
-
-; Linked lists of DSA structures
-ABSOLUTE reconnect_dsa_head = 0	; Link list of DSAs which can reconnect
-ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
-				; address of reconnect_dsa_head
-
-; These select the source and destination of a MOVE MEMORY instruction
-ABSOLUTE dmode_memory_to_memory = 0x0
-ABSOLUTE dmode_memory_to_ncr = 0x0
-ABSOLUTE dmode_ncr_to_memory = 0x0
-
-ABSOLUTE addr_scratch = 0x0
-ABSOLUTE addr_temp = 0x0
-
-ABSOLUTE saved_dsa = 0x0
-ABSOLUTE emulfly = 0x0
-ABSOLUTE addr_dsa = 0x0
-
-
-
-; Interrupts - 
-; MSB indicates type
-; 0	handle error condition
-; 1 	handle message 
-; 2 	handle normal condition
-; 3	debugging interrupt
-; 4 	testing interrupt 
-; Next byte indicates specific error
-
-; XXX not yet implemented, I'm not sure if I want to - 
-; Next byte indicates the routine the error occurred in
-; The LSB indicates the specific place the error occurred
- 
-ABSOLUTE int_err_unexpected_phase = 0x00000000	; Unexpected phase encountered
-ABSOLUTE int_err_selected = 0x00010000		; SELECTED (nee RESELECTED)
-ABSOLUTE int_err_unexpected_reselect = 0x00020000 
-ABSOLUTE int_err_check_condition = 0x00030000	
-ABSOLUTE int_err_no_phase = 0x00040000
-ABSOLUTE int_msg_wdtr = 0x01000000		; WDTR message received
-ABSOLUTE int_msg_sdtr = 0x01010000		; SDTR received
-ABSOLUTE int_msg_1 = 0x01020000			; single byte special message
-						; received
-
-ABSOLUTE int_norm_select_complete = 0x02000000	; Select complete, reprogram
-						; registers.
-ABSOLUTE int_norm_reselect_complete = 0x02010000	; Nexus established
-ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
-ABSOLUTE int_norm_disconnected = 0x02030000	; Disconnected 
-ABSOLUTE int_norm_aborted =0x02040000		; Aborted *dsa
-ABSOLUTE int_norm_reset = 0x02050000		; Generated BUS reset.
-ABSOLUTE int_norm_emulateintfly = 0x02060000	; 53C710 Emulated intfly
-ABSOLUTE int_debug_break = 0x03000000		; Break point
-
-ABSOLUTE int_debug_panic = 0x030b0000		; Panic driver
-
-
-ABSOLUTE int_test_1 = 0x04000000		; Test 1 complete
-ABSOLUTE int_test_2 = 0x04010000		; Test 2 complete
-ABSOLUTE int_test_3 = 0x04020000		; Test 3 complete
-
-
-; These should start with 0x05000000, with low bits incrementing for 
-; each one.
-
-
-						
-ABSOLUTE NCR53c7xx_msg_abort = 0	; Pointer to abort message
-ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
-ABSOLUTE NCR53c7xx_zero	= 0		; long with zero in it, use for source
-ABSOLUTE NCR53c7xx_sink = 0		; long to dump worthless data in
-ABSOLUTE NOP_insn = 0			; NOP instruction
-
-; Pointer to message, potentially multi-byte
-ABSOLUTE msg_buf = 0
-
-; Pointer to holding area for reselection information
-ABSOLUTE reselected_identify = 0
-ABSOLUTE reselected_tag = 0
-
-; Request sense command pointer, it's a 6 byte command, should
-; be constant for all commands since we always want 16 bytes of 
-; sense and we don't need to change any fields as we did under 
-; SCSI-I when we actually cared about the LUN field.
-;EXTERNAL NCR53c7xx_sense		; Request sense command
-
-
-; dsa_schedule  
-; PURPOSE : after a DISCONNECT message has been received, and pointers
-;	saved, insert the current DSA structure at the head of the 
-; 	disconnected queue and fall through to the scheduler.
-;
-; CALLS : OK
-;
-; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
-;	of disconnected commands
-;
-; MODIFIES : SCRATCH, reconnect_dsa_head
-; 
-; EXITS : always passes control to schedule
-
-ENTRY dsa_schedule
-dsa_schedule:
-
-
-
-
-;
-; Calculate the address of the next pointer within the DSA 
-; structure of the command that is currently disconnecting
-;
-
-    ; Read what should be the current DSA from memory - actual DSA
-    ; register is probably corrupt
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-
-at 0x0000005e : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-    MOVE SCRATCH0 + dsa_next TO SCRATCH0
-
-at 0x00000061 : */	0x7e343000,0x00000000,
-/*
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
-
-at 0x00000063 : */	0x7f350000,0x00000000,
-/*
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
-
-at 0x00000065 : */	0x7f360000,0x00000000,
-/*
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
-
-at 0x00000067 : */	0x7f370000,0x00000000,
-/*
-
-; Point the next field of this DSA structure at the current disconnected 
-; list
-    
-    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
-
-at 0x00000069 : */	0xc0000004,0x00000000,0x000001b8,
-/*
-    
-dsa_schedule_insert:
-    MOVE MEMORY 4, reconnect_dsa_head, 0 
-
-at 0x0000006c : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-; And update the head pointer.
-
-    ; Read what should be the current DSA from memory - actual DSA
-    ; register is probably corrupt
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-
-at 0x0000006f : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-    
-    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
-
-at 0x00000072 : */	0xc0000004,0x00000000,0x00000000,
-/*
-    
-
-
-
-
-
-    CLEAR ACK
-
-at 0x00000075 : */	0x60000040,0x00000000,
-/*
-
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x00000077 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-    WAIT DISCONNECT
-
-at 0x0000007a : */	0x48000000,0x00000000,
-/*
-
-
-
-
-
-
-    JUMP schedule
-
-at 0x0000007c : */	0x80080000,0x00000000,
-/*
-
-
-;
-; select
-;
-; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
-;	On success, the current DSA structure is removed from the issue 
-;	queue.  Usually, this is entered as a fall-through from schedule,
-;	although the contingent allegiance handling code will write
-;	the select entry address to the DSP to restart a command as a 
-;	REQUEST SENSE.  A message is sent (usually IDENTIFY, although
-;	additional SDTR or WDTR messages may be sent).  COMMAND OUT
-;	is handled.
-;
-; INPUTS : DSA - SCSI command, issue_dsa_head
-;
-; CALLS : NOT OK
-;
-; MODIFIES : SCRATCH, issue_dsa_head
-;
-; EXITS : on reselection or selection, go to select_failed
-;	otherwise, RETURN so control is passed back to 
-;	dsa_begin.
-;
-
-ENTRY select
-select:
-
-
-
-
-
-
-
-
-    CLEAR TARGET
-
-at 0x0000007e : */	0x60000200,0x00000000,
-/*
-
-; XXX
-;
-; In effect, SELECTION operations are backgrounded, with execution
-; continuing until code which waits for REQ or a fatal interrupt is 
-; encountered.
-;
-; So, for more performance, we could overlap the code which removes 
-; the command from the NCRs issue queue with the selection, but 
-; at this point I don't want to deal with the error recovery.
-;
-
-
-
-    ; Enable selection timer
-
-
-
-    MOVE CTEST7 & 0xef TO CTEST7
-
-at 0x00000080 : */	0x7c1bef00,0x00000000,
-/*
-
-
-    SELECT ATN FROM dsa_select, select_failed
-
-at 0x00000082 : */	0x4300003c,0x00000828,
-/*
-    JUMP select_msgout, WHEN MSG_OUT
-
-at 0x00000084 : */	0x860b0000,0x00000218,
-/*
-ENTRY select_msgout
-select_msgout:
-
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-
-at 0x00000086 : */	0x7a1b1000,0x00000000,
-/*
-
-    MOVE FROM dsa_msgout, WHEN MSG_OUT
-
-at 0x00000088 : */	0x1e000000,0x00000040,
-/*
-
-
-
-
-
-
-
-
-
-
-   RETURN
-
-at 0x0000008a : */	0x90080000,0x00000000,
-/*
-
-; 
-; select_done
-; 
-; PURPOSE: continue on to normal data transfer; called as the exit 
-;	point from dsa_begin.
-;
-; INPUTS: dsa
-;
-; CALLS: OK
-;
-;
-
-select_done:
-
-; NOTE DSA is corrupt when we arrive here!
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x0000008c : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-
-
-
-
-
-; After a successful selection, we should get either a CMD phase or 
-; some transfer request negotiation message.
-
-    JUMP cmdout, WHEN CMD
-
-at 0x0000008f : */	0x820b0000,0x0000025c,
-/*
-    INT int_err_unexpected_phase, WHEN NOT MSG_IN 
-
-at 0x00000091 : */	0x9f030000,0x00000000,
-/*
-
-select_msg_in:
-    CALL msg_in, WHEN MSG_IN
-
-at 0x00000093 : */	0x8f0b0000,0x0000041c,
-/*
-    JUMP select_msg_in, WHEN MSG_IN
-
-at 0x00000095 : */	0x870b0000,0x0000024c,
-/*
-
-cmdout:
-    INT int_err_unexpected_phase, WHEN NOT CMD
-
-at 0x00000097 : */	0x9a030000,0x00000000,
-/*
-
-
-
-ENTRY cmdout_cmdout
-cmdout_cmdout:
-
-    MOVE FROM dsa_cmdout, WHEN CMD
-
-at 0x00000099 : */	0x1a000000,0x00000048,
-/*
-
-
-
-
-;
-; data_transfer  
-; other_out
-; other_in
-; other_transfer
-;
-; PURPOSE : handle the main data transfer for a SCSI command in 
-;	several parts.  In the first part, data_transfer, DATA_IN
-;	and DATA_OUT phases are allowed, with the user provided
-;	code (usually dynamically generated based on the scatter/gather
-;	list associated with a SCSI command) called to handle these 
-;	phases.
-;
-;	After control has passed to one of the user provided 
-;	DATA_IN or DATA_OUT routines, back calls are made to 
-;	other_transfer_in or other_transfer_out to handle non-DATA IN
-;	and DATA OUT phases respectively, with the state of the active
-;	data pointer being preserved in TEMP.
-;
-;	On completion, the user code passes control to other_transfer
-;	which causes DATA_IN and DATA_OUT to result in unexpected_phase
-;	interrupts so that data overruns may be trapped.
-;
-; INPUTS : DSA - SCSI command
-;
-; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
-;	other_transfer
-;
-; MODIFIES : SCRATCH
-;
-; EXITS : if STATUS IN is detected, signifying command completion,
-;	the NCR jumps to command_complete.  If MSG IN occurs, a 
-;	CALL is made to msg_in.  Otherwise, other_transfer runs in 
-;	an infinite loop.
-;	
-
-ENTRY data_transfer
-data_transfer:
-    JUMP cmdout_cmdout, WHEN CMD
-
-at 0x0000009b : */	0x820b0000,0x00000264,
-/*
-    CALL msg_in, WHEN MSG_IN
-
-at 0x0000009d : */	0x8f0b0000,0x0000041c,
-/*
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-
-at 0x0000009f : */	0x9e0b0000,0x00000000,
-/*
-    JUMP do_dataout, WHEN DATA_OUT
-
-at 0x000000a1 : */	0x800b0000,0x000002a4,
-/*
-    JUMP do_datain, WHEN DATA_IN
-
-at 0x000000a3 : */	0x810b0000,0x000002fc,
-/*
-    JUMP command_complete, WHEN STATUS
-
-at 0x000000a5 : */	0x830b0000,0x0000065c,
-/*
-    JUMP data_transfer
-
-at 0x000000a7 : */	0x80080000,0x0000026c,
-/*
-ENTRY end_data_transfer
-end_data_transfer:
-
-;
-; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
-; should be fixed up whenever the nexus changes so it can point to the 
-; correct routine for that command.
-;
-
-
-; Nasty jump to dsa->dataout
-do_dataout:
-
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-
-at 0x000000a9 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0	
-
-at 0x000000ac : */	0x7e345000,0x00000000,
-/*
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
-
-at 0x000000ae : */	0x7f350000,0x00000000,
-/*
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
-
-at 0x000000b0 : */	0x7f360000,0x00000000,
-/*
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
-
-at 0x000000b2 : */	0x7f370000,0x00000000,
-/*
-    
-    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
-
-at 0x000000b4 : */	0xc0000004,0x00000000,0x000002e0,
-/*
-    
-dataout_to_jump:
-    MOVE MEMORY 4, 0, dataout_jump + 4 
-
-at 0x000000b7 : */	0xc0000004,0x00000000,0x000002f8,
-/*
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000000ba : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-dataout_jump:
-    JUMP 0
-
-at 0x000000bd : */	0x80080000,0x00000000,
-/*
-
-; Nasty jump to dsa->dsain
-do_datain:
-
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-
-at 0x000000bf : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-    MOVE SCRATCH0 + dsa_datain TO SCRATCH0	
-
-at 0x000000c2 : */	0x7e345400,0x00000000,
-/*
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
-
-at 0x000000c4 : */	0x7f350000,0x00000000,
-/*
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
-
-at 0x000000c6 : */	0x7f360000,0x00000000,
-/*
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
-
-at 0x000000c8 : */	0x7f370000,0x00000000,
-/*
-    
-    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
-
-at 0x000000ca : */	0xc0000004,0x00000000,0x00000338,
-/*
-    
-ENTRY datain_to_jump
-datain_to_jump:
-    MOVE MEMORY 4, 0, datain_jump + 4
-
-at 0x000000cd : */	0xc0000004,0x00000000,0x00000350,
-/*
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000000d0 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-
-datain_jump:
-    JUMP 0
-
-at 0x000000d3 : */	0x80080000,0x00000000,
-/*
-
-
-
-; Note that other_out and other_in loop until a non-data phase
-; is discovered, so we only execute return statements when we
-; can go on to the next data phase block move statement.
-
-ENTRY other_out
-other_out:
-
-
-
-    INT int_err_unexpected_phase, WHEN CMD
-
-at 0x000000d5 : */	0x9a0b0000,0x00000000,
-/*
-    JUMP msg_in_restart, WHEN MSG_IN 
-
-at 0x000000d7 : */	0x870b0000,0x000003fc,
-/*
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-
-at 0x000000d9 : */	0x9e0b0000,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN DATA_IN
-
-at 0x000000db : */	0x990b0000,0x00000000,
-/*
-    JUMP command_complete, WHEN STATUS
-
-at 0x000000dd : */	0x830b0000,0x0000065c,
-/*
-    JUMP other_out, WHEN NOT DATA_OUT
-
-at 0x000000df : */	0x80030000,0x00000354,
-/*
-
-; TEMP should be OK, as we got here from a call in the user dataout code.
-
-    RETURN
-
-at 0x000000e1 : */	0x90080000,0x00000000,
-/*
-
-ENTRY other_in
-other_in:
-
-
-
-    INT int_err_unexpected_phase, WHEN CMD
-
-at 0x000000e3 : */	0x9a0b0000,0x00000000,
-/*
-    JUMP msg_in_restart, WHEN MSG_IN 
-
-at 0x000000e5 : */	0x870b0000,0x000003fc,
-/*
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-
-at 0x000000e7 : */	0x9e0b0000,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN DATA_OUT
-
-at 0x000000e9 : */	0x980b0000,0x00000000,
-/*
-    JUMP command_complete, WHEN STATUS
-
-at 0x000000eb : */	0x830b0000,0x0000065c,
-/*
-    JUMP other_in, WHEN NOT DATA_IN
-
-at 0x000000ed : */	0x81030000,0x0000038c,
-/*
-
-; TEMP should be OK, as we got here from a call in the user datain code.
-
-    RETURN
-
-at 0x000000ef : */	0x90080000,0x00000000,
-/*
-
-
-ENTRY other_transfer
-other_transfer:
-    INT int_err_unexpected_phase, WHEN CMD
-
-at 0x000000f1 : */	0x9a0b0000,0x00000000,
-/*
-    CALL msg_in, WHEN MSG_IN
-
-at 0x000000f3 : */	0x8f0b0000,0x0000041c,
-/*
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-
-at 0x000000f5 : */	0x9e0b0000,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN DATA_OUT
-
-at 0x000000f7 : */	0x980b0000,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN DATA_IN
-
-at 0x000000f9 : */	0x990b0000,0x00000000,
-/*
-    JUMP command_complete, WHEN STATUS
-
-at 0x000000fb : */	0x830b0000,0x0000065c,
-/*
-    JUMP other_transfer
-
-at 0x000000fd : */	0x80080000,0x000003c4,
-/*
-
-;
-; msg_in_restart
-; msg_in
-; munge_msg
-;
-; PURPOSE : process messages from a target.  msg_in is called when the 
-;	caller hasn't read the first byte of the message.  munge_message
-;	is called when the caller has read the first byte of the message,
-;	and left it in SFBR.  msg_in_restart is called when the caller 
-;	hasn't read the first byte of the message, and wishes RETURN
-;	to transfer control back to the address of the conditional
-;	CALL instruction rather than to the instruction after it.
-;
-;	Various int_* interrupts are generated when the host system
-;	needs to intervene, as is the case with SDTR, WDTR, and
-;	INITIATE RECOVERY messages.
-;
-;	When the host system handles one of these interrupts,
-;	it can respond by reentering at reject_message, 
-;	which rejects the message and returns control to
-;	the caller of msg_in or munge_msg, accept_message
-;	which clears ACK and returns control, or reply_message
-;	which sends the message pointed to by the DSA 
-;	msgout_other table indirect field.
-;
-;	DISCONNECT messages are handled by moving the command
-;	to the reconnect_dsa_queue.
-
-; NOTE: DSA should be valid when we get here - we cannot save both it
-;	and TEMP in this routine.
-
-;
-; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
-;	only)
-;
-; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
-;
-; MODIFIES : SCRATCH, DSA on DISCONNECT
-;
-; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
-;	and normal return from message handlers running under
-;	Linux, control is returned to the caller.  Receipt
-;	of DISCONNECT messages pass control to dsa_schedule.
-;
-ENTRY msg_in_restart
-msg_in_restart:
-; XXX - hackish
-;
-; Since it's easier to debug changes to the statically 
-; compiled code, rather than the dynamically generated 
-; stuff, such as
-;
-; 	MOVE x, y, WHEN data_phase
-; 	CALL other_z, WHEN NOT data_phase
-; 	MOVE x, y, WHEN data_phase
-;
-; I'd like to have certain routines (notably the message handler)
-; restart on the conditional call rather than the next instruction.
-;
-; So, subtract 8 from the return address
-
-    MOVE TEMP0 + 0xf8 TO TEMP0
-
-at 0x000000ff : */	0x7e1cf800,0x00000000,
-/*
-    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
-
-at 0x00000101 : */	0x7f1dff00,0x00000000,
-/*
-    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
-
-at 0x00000103 : */	0x7f1eff00,0x00000000,
-/*
-    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
-
-at 0x00000105 : */	0x7f1fff00,0x00000000,
-/*
-
-ENTRY msg_in
-msg_in:
-    MOVE 1, msg_buf, WHEN MSG_IN
-
-at 0x00000107 : */	0x0f000001,0x00000000,
-/*
-
-munge_msg:
-    JUMP munge_extended, IF 0x01		; EXTENDED MESSAGE
-
-at 0x00000109 : */	0x800c0001,0x00000574,
-/*
-    JUMP munge_2, IF 0x20, AND MASK 0xdf	; two byte message
-
-at 0x0000010b : */	0x800cdf20,0x00000464,
-/*
-;
-; XXX - I've seen a handful of broken SCSI devices which fail to issue
-; 	a SAVE POINTERS message before disconnecting in the middle of 
-; 	a transfer, assuming that the DATA POINTER will be implicitly 
-; 	restored.  
-;
-; Historically, I've often done an implicit save when the DISCONNECT
-; message is processed.  We may want to consider having the option of 
-; doing that here. 
-;
-    JUMP munge_save_data_pointer, IF 0x02	; SAVE DATA POINTER
-
-at 0x0000010d : */	0x800c0002,0x0000046c,
-/*
-    JUMP munge_restore_pointers, IF 0x03	; RESTORE POINTERS 
-
-at 0x0000010f : */	0x800c0003,0x00000518,
-/*
-    JUMP munge_disconnect, IF 0x04		; DISCONNECT
-
-at 0x00000111 : */	0x800c0004,0x0000056c,
-/*
-    INT int_msg_1, IF 0x07			; MESSAGE REJECT
-
-at 0x00000113 : */	0x980c0007,0x01020000,
-/*
-    INT int_msg_1, IF 0x0f			; INITIATE RECOVERY
-
-at 0x00000115 : */	0x980c000f,0x01020000,
-/*
-
-
-
-    JUMP reject_message
-
-at 0x00000117 : */	0x80080000,0x00000604,
-/*
-
-munge_2:
-    JUMP reject_message
-
-at 0x00000119 : */	0x80080000,0x00000604,
-/*
-;
-; The SCSI standard allows targets to recover from transient 
-; error conditions by backing up the data pointer with a 
-; RESTORE POINTERS message.  
-;	
-; So, we must save and restore the _residual_ code as well as 
-; the current instruction pointer.  Because of this messiness,
-; it is simpler to put dynamic code in the dsa for this and to
-; just do a simple jump down there. 
-;
-
-munge_save_data_pointer:
-
-    ; We have something in TEMP here, so first we must save that
-    MOVE TEMP0 TO SFBR
-
-at 0x0000011b : */	0x721c0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH0
-
-at 0x0000011d : */	0x6a340000,0x00000000,
-/*
-    MOVE TEMP1 TO SFBR
-
-at 0x0000011f : */	0x721d0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH1
-
-at 0x00000121 : */	0x6a350000,0x00000000,
-/*
-    MOVE TEMP2 TO SFBR
-
-at 0x00000123 : */	0x721e0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH2
-
-at 0x00000125 : */	0x6a360000,0x00000000,
-/*
-    MOVE TEMP3 TO SFBR
-
-at 0x00000127 : */	0x721f0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH3
-
-at 0x00000129 : */	0x6a370000,0x00000000,
-/*
-    MOVE MEMORY 4, addr_scratch, jump_temp + 4
-
-at 0x0000012b : */	0xc0000004,0x00000000,0x000009c8,
-/*
-    ; Now restore DSA
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x0000012e : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-    MOVE DSA0 + dsa_save_data_pointer TO SFBR
-
-at 0x00000131 : */	0x76100000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH0
-
-at 0x00000133 : */	0x6a340000,0x00000000,
-/*
-    MOVE DSA1 + 0xff TO SFBR WITH CARRY
-
-at 0x00000135 : */	0x7711ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH1
-
-at 0x00000137 : */	0x6a350000,0x00000000,
-/*
-    MOVE DSA2 + 0xff TO SFBR WITH CARRY 
-
-at 0x00000139 : */	0x7712ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH2
-
-at 0x0000013b : */	0x6a360000,0x00000000,
-/*
-    MOVE DSA3 + 0xff TO SFBR WITH CARRY
-
-at 0x0000013d : */	0x7713ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH3
-
-at 0x0000013f : */	0x6a370000,0x00000000,
-/*
-
-    
-    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
-
-at 0x00000141 : */	0xc0000004,0x00000000,0x00000514,
-/*
-    
-jump_dsa_save:
-    JUMP 0
-
-at 0x00000144 : */	0x80080000,0x00000000,
-/*
-
-munge_restore_pointers:
-
-    ; The code at dsa_restore_pointers will RETURN, but we don't care
-    ; about TEMP here, as it will overwrite it anyway.
-
-    MOVE DSA0 + dsa_restore_pointers TO SFBR
-
-at 0x00000146 : */	0x76100000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH0
-
-at 0x00000148 : */	0x6a340000,0x00000000,
-/*
-    MOVE DSA1 + 0xff TO SFBR WITH CARRY
-
-at 0x0000014a : */	0x7711ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH1
-
-at 0x0000014c : */	0x6a350000,0x00000000,
-/*
-    MOVE DSA2 + 0xff TO SFBR WITH CARRY
-
-at 0x0000014e : */	0x7712ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH2
-
-at 0x00000150 : */	0x6a360000,0x00000000,
-/*
-    MOVE DSA3 + 0xff TO SFBR WITH CARRY
-
-at 0x00000152 : */	0x7713ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH3
-
-at 0x00000154 : */	0x6a370000,0x00000000,
-/*
-
-    
-    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
-
-at 0x00000156 : */	0xc0000004,0x00000000,0x00000568,
-/*
-    
-jump_dsa_restore:
-    JUMP 0
-
-at 0x00000159 : */	0x80080000,0x00000000,
-/*
-
-
-munge_disconnect:
-
-
-
-
-
-
-
-
-
- 
-
-
-
-
-
-
-
-
-
-
-    JUMP dsa_schedule
-
-at 0x0000015b : */	0x80080000,0x00000178,
-/*
-
-
-
-
-
-munge_extended:
-    CLEAR ACK
-
-at 0x0000015d : */	0x60000040,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN NOT MSG_IN
-
-at 0x0000015f : */	0x9f030000,0x00000000,
-/*
-    MOVE 1, msg_buf + 1, WHEN MSG_IN
-
-at 0x00000161 : */	0x0f000001,0x00000001,
-/*
-    JUMP munge_extended_2, IF 0x02
-
-at 0x00000163 : */	0x800c0002,0x000005a4,
-/*
-    JUMP munge_extended_3, IF 0x03 
-
-at 0x00000165 : */	0x800c0003,0x000005d4,
-/*
-    JUMP reject_message
-
-at 0x00000167 : */	0x80080000,0x00000604,
-/*
-
-munge_extended_2:
-    CLEAR ACK
-
-at 0x00000169 : */	0x60000040,0x00000000,
-/*
-    MOVE 1, msg_buf + 2, WHEN MSG_IN
-
-at 0x0000016b : */	0x0f000001,0x00000002,
-/*
-    JUMP reject_message, IF NOT 0x02	; Must be WDTR
-
-at 0x0000016d : */	0x80040002,0x00000604,
-/*
-    CLEAR ACK
-
-at 0x0000016f : */	0x60000040,0x00000000,
-/*
-    MOVE 1, msg_buf + 3, WHEN MSG_IN
-
-at 0x00000171 : */	0x0f000001,0x00000003,
-/*
-    INT int_msg_wdtr
-
-at 0x00000173 : */	0x98080000,0x01000000,
-/*
-
-munge_extended_3:
-    CLEAR ACK
-
-at 0x00000175 : */	0x60000040,0x00000000,
-/*
-    MOVE 1, msg_buf + 2, WHEN MSG_IN
-
-at 0x00000177 : */	0x0f000001,0x00000002,
-/*
-    JUMP reject_message, IF NOT 0x01	; Must be SDTR
-
-at 0x00000179 : */	0x80040001,0x00000604,
-/*
-    CLEAR ACK
-
-at 0x0000017b : */	0x60000040,0x00000000,
-/*
-    MOVE 2, msg_buf + 3, WHEN MSG_IN
-
-at 0x0000017d : */	0x0f000002,0x00000003,
-/*
-    INT int_msg_sdtr
-
-at 0x0000017f : */	0x98080000,0x01010000,
-/*
-
-ENTRY reject_message
-reject_message:
-    SET ATN
-
-at 0x00000181 : */	0x58000008,0x00000000,
-/*
-    CLEAR ACK
-
-at 0x00000183 : */	0x60000040,0x00000000,
-/*
-    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
-
-at 0x00000185 : */	0x0e000001,0x00000000,
-/*
-    RETURN
-
-at 0x00000187 : */	0x90080000,0x00000000,
-/*
-
-ENTRY accept_message
-accept_message:
-    CLEAR ATN
-
-at 0x00000189 : */	0x60000008,0x00000000,
-/*
-    CLEAR ACK
-
-at 0x0000018b : */	0x60000040,0x00000000,
-/*
-    RETURN
-
-at 0x0000018d : */	0x90080000,0x00000000,
-/*
-
-ENTRY respond_message
-respond_message:
-    SET ATN
-
-at 0x0000018f : */	0x58000008,0x00000000,
-/*
-    CLEAR ACK
-
-at 0x00000191 : */	0x60000040,0x00000000,
-/*
-    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
-
-at 0x00000193 : */	0x1e000000,0x00000068,
-/*
-    RETURN
-
-at 0x00000195 : */	0x90080000,0x00000000,
-/*
-
-;
-; command_complete
-;
-; PURPOSE : handle command termination when STATUS IN is detected by reading
-;	a status byte followed by a command termination message. 
-;
-;	Normal termination results in an INTFLY instruction, and 
-;	the host system can pick out which command terminated by 
-;	examining the MESSAGE and STATUS buffers of all currently 
-;	executing commands;
-;
-;	Abnormal (CHECK_CONDITION) termination results in an
-;	int_err_check_condition interrupt so that a REQUEST SENSE
-;	command can be issued out-of-order so that no other command
-;	clears the contingent allegiance condition.
-;	
-;
-; INPUTS : DSA - command	
-;
-; CALLS : OK
-;
-; EXITS : On successful termination, control is passed to schedule.
-;	On abnormal termination, the user will usually modify the 
-;	DSA fields and corresponding buffers and return control
-;	to select.
-;
-
-ENTRY command_complete
-command_complete:
-    MOVE FROM dsa_status, WHEN STATUS
-
-at 0x00000197 : */	0x1b000000,0x00000060,
-/*
-
-    MOVE SFBR TO SCRATCH0		; Save status
-
-at 0x00000199 : */	0x6a340000,0x00000000,
-/*
-
-ENTRY command_complete_msgin
-command_complete_msgin:
-    MOVE FROM dsa_msgin, WHEN MSG_IN
-
-at 0x0000019b : */	0x1f000000,0x00000058,
-/*
-; Indicate that we should be expecting a disconnect
-
-
-
-    ; Above code cleared the Unexpected Disconnect bit, what do we do?
-
-    CLEAR ACK
-
-at 0x0000019d : */	0x60000040,0x00000000,
-/*
-
-    WAIT DISCONNECT
-
-at 0x0000019f : */	0x48000000,0x00000000,
-/*
-
-;
-; The SCSI specification states that when a UNIT ATTENTION condition
-; is pending, as indicated by a CHECK CONDITION status message,
-; the target shall revert to asynchronous transfers.  Since
-; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
-; basis, and returning control to our scheduler could work on a command
-; running on another lun on that target using the old parameters, we must
-; interrupt the host processor to get them changed, or change them ourselves.
-;
-; Once SCSI-II tagged queueing is implemented, things will be even more
-; hairy, since contingent allegiance conditions exist on a per-target/lun
-; basis, and issuing a new command with a different tag would clear it.
-; In these cases, we must interrupt the host processor to get a request 
-; added to the HEAD of the queue with the request sense command, or we
-; must automatically issue the request sense command.
-
-
-
-
-
-
-
-    INT int_norm_emulateintfly
-
-at 0x000001a1 : */	0x98080000,0x02060000,
-/*
-
-
-
-
-
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000001a3 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-
-
-    JUMP schedule
-
-at 0x000001a6 : */	0x80080000,0x00000000,
-/*
-command_failed:
-    INT int_err_check_condition
-
-at 0x000001a8 : */	0x98080000,0x00030000,
-/*
-
-
-
-
-;
-; wait_reselect
-;
-; PURPOSE : This is essentially the idle routine, where control lands
-;	when there are no new processes to schedule.  wait_reselect
-;	waits for reselection, selection, and new commands.
-;
-;	When a successful reselection occurs, with the aid 
-;	of fixed up code in each DSA, wait_reselect walks the 
-;	reconnect_dsa_queue, asking each dsa if the target ID
-;	and LUN match its.
-;
-;	If a match is found, a call is made back to reselected_ok,
-;	which through the miracles of self modifying code, extracts
-;	the found DSA from the reconnect_dsa_queue and then 
-;	returns control to the DSAs thread of execution.
-;
-; INPUTS : NONE
-;
-; CALLS : OK
-;
-; MODIFIES : DSA,
-;
-; EXITS : On successful reselection, control is returned to the 
-;	DSA which called reselected_ok.  If the WAIT RESELECT
-;	was interrupted by a new commands arrival signaled by 
-;	SIG_P, control is passed to schedule.  If the NCR is 
-;	selected, the host system is interrupted with an 
-;	int_err_selected which is usually responded to by
-;	setting DSP to the target_abort address.
-
-ENTRY wait_reselect
-wait_reselect:
-
-
-
-
-
-
-    WAIT RESELECT wait_reselect_failed
-
-at 0x000001aa : */	0x50000000,0x00000800,
-/*
-
-reselected:
-
-
-
-    CLEAR TARGET
-
-at 0x000001ac : */	0x60000200,0x00000000,
-/*
-    
-    ; Read all data needed to reestablish the nexus - 
-    MOVE 1, reselected_identify, WHEN MSG_IN
-
-at 0x000001ae : */	0x0f000001,0x00000000,
-/*
-    ; We used to CLEAR ACK here.
-
-
-
-
-
-    ; Point DSA at the current head of the disconnected queue.
-    
-    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
-
-at 0x000001b0 : */	0xc0000004,0x00000000,0x00000000,
-/*
-    
-
-    MOVE MEMORY 4, addr_scratch, saved_dsa
-
-at 0x000001b3 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-
-    ; Fix the update-next pointer so that the reconnect_dsa_head
-    ; pointer is the one that will be updated if this DSA is a hit 
-    ; and we remove it from the queue.
-
-    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8
-
-at 0x000001b6 : */	0xc0000004,0x00000000,0x000007ec,
-/*
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000001b9 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-ENTRY reselected_check_next
-reselected_check_next:
-
-
-
-    ; Check for a NULL pointer.
-    MOVE DSA0 TO SFBR
-
-at 0x000001bc : */	0x72100000,0x00000000,
-/*
-    JUMP reselected_not_end, IF NOT 0
-
-at 0x000001be : */	0x80040000,0x00000738,
-/*
-    MOVE DSA1 TO SFBR
-
-at 0x000001c0 : */	0x72110000,0x00000000,
-/*
-    JUMP reselected_not_end, IF NOT 0
-
-at 0x000001c2 : */	0x80040000,0x00000738,
-/*
-    MOVE DSA2 TO SFBR
-
-at 0x000001c4 : */	0x72120000,0x00000000,
-/*
-    JUMP reselected_not_end, IF NOT 0
-
-at 0x000001c6 : */	0x80040000,0x00000738,
-/*
-    MOVE DSA3 TO SFBR
-
-at 0x000001c8 : */	0x72130000,0x00000000,
-/*
-    JUMP reselected_not_end, IF NOT 0
-
-at 0x000001ca : */	0x80040000,0x00000738,
-/*
-    INT int_err_unexpected_reselect
-
-at 0x000001cc : */	0x98080000,0x00020000,
-/*
-
-reselected_not_end:
-    ;
-    ; XXX the ALU is only eight bits wide, and the assembler
-    ; wont do the dirt work for us.  As long as dsa_check_reselect
-    ; is negative, we need to sign extend with 1 bits to the full
-    ; 32 bit width of the address.
-    ;
-    ; A potential work around would be to have a known alignment 
-    ; of the DSA structure such that the base address plus 
-    ; dsa_check_reselect doesn't require carrying from bytes 
-    ; higher than the LSB.
-    ;
-
-    MOVE DSA0 TO SFBR
-
-at 0x000001ce : */	0x72100000,0x00000000,
-/*
-    MOVE SFBR + dsa_check_reselect TO SCRATCH0
-
-at 0x000001d0 : */	0x6e340000,0x00000000,
-/*
-    MOVE DSA1 TO SFBR
-
-at 0x000001d2 : */	0x72110000,0x00000000,
-/*
-    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
-
-at 0x000001d4 : */	0x6f35ff00,0x00000000,
-/*
-    MOVE DSA2 TO SFBR
-
-at 0x000001d6 : */	0x72120000,0x00000000,
-/*
-    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
-
-at 0x000001d8 : */	0x6f36ff00,0x00000000,
-/*
-    MOVE DSA3 TO SFBR
-
-at 0x000001da : */	0x72130000,0x00000000,
-/*
-    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
-
-at 0x000001dc : */	0x6f37ff00,0x00000000,
-/*
-
-    
-    MOVE MEMORY 4, addr_scratch, reselected_check + 4
-
-at 0x000001de : */	0xc0000004,0x00000000,0x00000794,
-/*
-    
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000001e1 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-reselected_check:
-    JUMP 0
-
-at 0x000001e4 : */	0x80080000,0x00000000,
-/*
-
-
-;
-;
-
-; We have problems here - the memory move corrupts TEMP and DSA.  This
-; routine is called from DSA code, and patched from many places.  Scratch
-; is probably free when it is called.
-; We have to:
-;   copy temp to scratch, one byte at a time
-;   write scratch to patch a jump in place of the return
-;   do the move memory
-;   jump to the patched in return address
-; DSA is corrupt when we get here, and can be left corrupt
-
-ENTRY reselected_ok
-reselected_ok:
-    MOVE TEMP0 TO SFBR
-
-at 0x000001e6 : */	0x721c0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH0
-
-at 0x000001e8 : */	0x6a340000,0x00000000,
-/*
-    MOVE TEMP1 TO SFBR
-
-at 0x000001ea : */	0x721d0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH1
-
-at 0x000001ec : */	0x6a350000,0x00000000,
-/*
-    MOVE TEMP2 TO SFBR
-
-at 0x000001ee : */	0x721e0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH2
-
-at 0x000001f0 : */	0x6a360000,0x00000000,
-/*
-    MOVE TEMP3 TO SFBR
-
-at 0x000001f2 : */	0x721f0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH3
-
-at 0x000001f4 : */	0x6a370000,0x00000000,
-/*
-    MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4
-
-at 0x000001f6 : */	0xc0000004,0x00000000,0x000007f4,
-/*
-reselected_ok_patch:
-    MOVE MEMORY 4, 0, 0
-
-at 0x000001f9 : */	0xc0000004,0x00000000,0x00000000,
-/*
-reselected_ok_jump:
-    JUMP 0
-
-at 0x000001fc : */	0x80080000,0x00000000,
-/*
-
-
-
-
-
-selected:
-    INT int_err_selected;
-
-at 0x000001fe : */	0x98080000,0x00010000,
-/*
-
-;
-; A select or reselect failure can be caused by one of two conditions : 
-; 1.  SIG_P was set.  This will be the case if the user has written
-;	a new value to a previously NULL head of the issue queue.
-;
-; 2.  The NCR53c810 was selected or reselected by another device.
-;
-; 3.  The bus was already busy since we were selected or reselected
-;	before starting the command.
-
-wait_reselect_failed:
-
-
-
-; Check selected bit.  
-
-    ; Must work out how to tell if we are selected....
-
-
-
-
-; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
-    MOVE CTEST2 & 0x40 TO SFBR	
-
-at 0x00000200 : */	0x74164000,0x00000000,
-/*
-    JUMP schedule, IF 0x40
-
-at 0x00000202 : */	0x800c0040,0x00000000,
-/*
-; Check connected bit.  
-; FIXME: this needs to change if we support target mode
-    MOVE ISTAT & 0x08 TO SFBR
-
-at 0x00000204 : */	0x74210800,0x00000000,
-/*
-    JUMP reselected, IF 0x08
-
-at 0x00000206 : */	0x800c0008,0x000006b0,
-/*
-; FIXME : Something bogus happened, and we shouldn't fail silently.
-
-
-
-    INT int_debug_panic
-
-at 0x00000208 : */	0x98080000,0x030b0000,
-/*
-
-
-
-select_failed:
-
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-
-at 0x0000020a : */	0x7a1b1000,0x00000000,
-/*
-
-
-
-
-; Otherwise, mask the selected and reselected bits off SIST0
-
-    ; Let's assume we don't get selected for now
-    MOVE SSTAT0 & 0x10 TO SFBR
-
-at 0x0000020c : */	0x740d1000,0x00000000,
-/*
-
-
-
-
-    JUMP reselected, IF 0x10 
-
-at 0x0000020e : */	0x800c0010,0x000006b0,
-/*
-; If SIGP is set, the user just gave us another command, and
-; we should restart or return to the scheduler.
-; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
-    MOVE CTEST2 & 0x40 TO SFBR	
-
-at 0x00000210 : */	0x74164000,0x00000000,
-/*
-    JUMP select, IF 0x40
-
-at 0x00000212 : */	0x800c0040,0x000001f8,
-/*
-; Check connected bit.  
-; FIXME: this needs to change if we support target mode
-; FIXME: is this really necessary? 
-    MOVE ISTAT & 0x08 TO SFBR
-
-at 0x00000214 : */	0x74210800,0x00000000,
-/*
-    JUMP reselected, IF 0x08
-
-at 0x00000216 : */	0x800c0008,0x000006b0,
-/*
-; FIXME : Something bogus happened, and we shouldn't fail silently.
-
-
-
-    INT int_debug_panic
-
-at 0x00000218 : */	0x98080000,0x030b0000,
-/*
-
-
-;
-; test_1
-; test_2
-;
-; PURPOSE : run some verification tests on the NCR.  test_1
-;	copies test_src to test_dest and interrupts the host
-;	processor, testing for cache coherency and interrupt
-; 	problems in the processes.
-;
-;	test_2 runs a command with offsets relative to the 
-;	DSA on entry, and is useful for miscellaneous experimentation.
-;
-
-; Verify that interrupts are working correctly and that we don't 
-; have a cache invalidation problem.
-
-ABSOLUTE test_src = 0, test_dest = 0
-ENTRY test_1
-test_1:
-    MOVE MEMORY 4, test_src, test_dest
-
-at 0x0000021a : */	0xc0000004,0x00000000,0x00000000,
-/*
-    INT int_test_1
-
-at 0x0000021d : */	0x98080000,0x04000000,
-/*
-
-;
-; Run arbitrary commands, with test code establishing a DSA
-;
- 
-ENTRY test_2
-test_2:
-    CLEAR TARGET
-
-at 0x0000021f : */	0x60000200,0x00000000,
-/*
-
-    ; Enable selection timer
-
-
-
-    MOVE CTEST7 & 0xef TO CTEST7
-
-at 0x00000221 : */	0x7c1bef00,0x00000000,
-/*
-
-
-    SELECT ATN FROM 0, test_2_fail
-
-at 0x00000223 : */	0x43000000,0x000008dc,
-/*
-    JUMP test_2_msgout, WHEN MSG_OUT
-
-at 0x00000225 : */	0x860b0000,0x0000089c,
-/*
-ENTRY test_2_msgout
-test_2_msgout:
-
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-
-at 0x00000227 : */	0x7a1b1000,0x00000000,
-/*
-
-    MOVE FROM 8, WHEN MSG_OUT
-
-at 0x00000229 : */	0x1e000000,0x00000008,
-/*
-    MOVE FROM 16, WHEN CMD 
-
-at 0x0000022b : */	0x1a000000,0x00000010,
-/*
-    MOVE FROM 24, WHEN DATA_IN
-
-at 0x0000022d : */	0x19000000,0x00000018,
-/*
-    MOVE FROM 32, WHEN STATUS
-
-at 0x0000022f : */	0x1b000000,0x00000020,
-/*
-    MOVE FROM 40, WHEN MSG_IN
-
-at 0x00000231 : */	0x1f000000,0x00000028,
-/*
-
-
-
-    CLEAR ACK
-
-at 0x00000233 : */	0x60000040,0x00000000,
-/*
-    WAIT DISCONNECT
-
-at 0x00000235 : */	0x48000000,0x00000000,
-/*
-test_2_fail:
-
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-
-at 0x00000237 : */	0x7a1b1000,0x00000000,
-/*
-
-    INT int_test_2
-
-at 0x00000239 : */	0x98080000,0x04010000,
-/*
-
-ENTRY debug_break
-debug_break:
-    INT int_debug_break
-
-at 0x0000023b : */	0x98080000,0x03000000,
-/*
-
-;
-; initiator_abort
-; target_abort
-;
-; PURPOSE : Abort the currently established nexus from with initiator
-;	or target mode.
-;
-;  
-
-ENTRY target_abort
-target_abort:
-    SET TARGET
-
-at 0x0000023d : */	0x58000200,0x00000000,
-/*
-    DISCONNECT
-
-at 0x0000023f : */	0x48000000,0x00000000,
-/*
-    CLEAR TARGET
-
-at 0x00000241 : */	0x60000200,0x00000000,
-/*
-    JUMP schedule
-
-at 0x00000243 : */	0x80080000,0x00000000,
-/*
-    
-ENTRY initiator_abort
-initiator_abort:
-    SET ATN
-
-at 0x00000245 : */	0x58000008,0x00000000,
-/*
-;
-; The SCSI-I specification says that targets may go into MSG out at 
-; their leisure upon receipt of the ATN single.  On all versions of the 
-; specification, we can't change phases until REQ transitions true->false, 
-; so we need to sink/source one byte of data to allow the transition.
-;
-; For the sake of safety, we'll only source one byte of data in all 
-; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
-; arbitrary number of bytes.
-    JUMP spew_cmd, WHEN CMD
-
-at 0x00000247 : */	0x820b0000,0x0000094c,
-/*
-    JUMP eat_msgin, WHEN MSG_IN
-
-at 0x00000249 : */	0x870b0000,0x0000095c,
-/*
-    JUMP eat_datain, WHEN DATA_IN
-
-at 0x0000024b : */	0x810b0000,0x0000098c,
-/*
-    JUMP eat_status, WHEN STATUS
-
-at 0x0000024d : */	0x830b0000,0x00000974,
-/*
-    JUMP spew_dataout, WHEN DATA_OUT
-
-at 0x0000024f : */	0x800b0000,0x000009a4,
-/*
-    JUMP sated
-
-at 0x00000251 : */	0x80080000,0x000009ac,
-/*
-spew_cmd:
-    MOVE 1, NCR53c7xx_zero, WHEN CMD
-
-at 0x00000253 : */	0x0a000001,0x00000000,
-/*
-    JUMP sated
-
-at 0x00000255 : */	0x80080000,0x000009ac,
-/*
-eat_msgin:
-    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
-
-at 0x00000257 : */	0x0f000001,0x00000000,
-/*
-    JUMP eat_msgin, WHEN MSG_IN
-
-at 0x00000259 : */	0x870b0000,0x0000095c,
-/*
-    JUMP sated
-
-at 0x0000025b : */	0x80080000,0x000009ac,
-/*
-eat_status:
-    MOVE 1, NCR53c7xx_sink, WHEN STATUS
-
-at 0x0000025d : */	0x0b000001,0x00000000,
-/*
-    JUMP eat_status, WHEN STATUS
-
-at 0x0000025f : */	0x830b0000,0x00000974,
-/*
-    JUMP sated
-
-at 0x00000261 : */	0x80080000,0x000009ac,
-/*
-eat_datain:
-    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
-
-at 0x00000263 : */	0x09000001,0x00000000,
-/*
-    JUMP eat_datain, WHEN DATA_IN
-
-at 0x00000265 : */	0x810b0000,0x0000098c,
-/*
-    JUMP sated
-
-at 0x00000267 : */	0x80080000,0x000009ac,
-/*
-spew_dataout:
-    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
-
-at 0x00000269 : */	0x08000001,0x00000000,
-/*
-sated:
-
-
-
-    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
-
-at 0x0000026b : */	0x0e000001,0x00000000,
-/*
-    WAIT DISCONNECT
-
-at 0x0000026d : */	0x48000000,0x00000000,
-/*
-    INT int_norm_aborted
-
-at 0x0000026f : */	0x98080000,0x02040000,
-/*
-
-
- 
-
-; Little patched jump, used to overcome problems with TEMP getting
-; corrupted on memory moves.
-
-jump_temp:
-    JUMP 0
-
-at 0x00000271 : */	0x80080000,0x00000000,
-};
-
-#define A_NCR53c7xx_msg_abort	0x00000000
-static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = {
-	0x0000026c,
-};
-
-#define A_NCR53c7xx_msg_reject	0x00000000
-static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = {
-	0x00000186,
-};
-
-#define A_NCR53c7xx_sink	0x00000000
-static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = {
-	0x00000258,
-	0x0000025e,
-	0x00000264,
-};
-
-#define A_NCR53c7xx_zero	0x00000000
-static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = {
-	0x00000254,
-	0x0000026a,
-};
-
-#define A_NOP_insn	0x00000000
-static u32 A_NOP_insn_used[] __attribute((unused)) = {
-	0x00000017,
-};
-
-#define A_addr_dsa	0x00000000
-static u32 A_addr_dsa_used[] __attribute((unused)) = {
-	0x0000000f,
-	0x00000026,
-	0x00000033,
-	0x00000040,
-	0x00000055,
-	0x00000079,
-	0x0000008e,
-	0x000000bc,
-	0x000000d2,
-	0x00000130,
-	0x000001a5,
-	0x000001bb,
-	0x000001e3,
-};
-
-#define A_addr_reconnect_dsa_head	0x00000000
-static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = {
-	0x000001b7,
-};
-
-#define A_addr_scratch	0x00000000
-static u32 A_addr_scratch_used[] __attribute((unused)) = {
-	0x00000002,
-	0x00000004,
-	0x00000008,
-	0x00000020,
-	0x00000022,
-	0x00000049,
-	0x00000060,
-	0x0000006a,
-	0x00000071,
-	0x00000073,
-	0x000000ab,
-	0x000000b5,
-	0x000000c1,
-	0x000000cb,
-	0x0000012c,
-	0x00000142,
-	0x00000157,
-	0x000001b2,
-	0x000001b4,
-	0x000001df,
-	0x000001f7,
-};
-
-#define A_addr_temp	0x00000000
-static u32 A_addr_temp_used[] __attribute((unused)) = {
-};
-
-#define A_dmode_memory_to_memory	0x00000000
-static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = {
-};
-
-#define A_dmode_memory_to_ncr	0x00000000
-static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = {
-};
-
-#define A_dmode_ncr_to_memory	0x00000000
-static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_check_reselect	0x00000000
-static u32 A_dsa_check_reselect_used[] __attribute((unused)) = {
-	0x000001d0,
-};
-
-#define A_dsa_cmdout	0x00000048
-static u32 A_dsa_cmdout_used[] __attribute((unused)) = {
-	0x0000009a,
-};
-
-#define A_dsa_cmnd	0x00000038
-static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_datain	0x00000054
-static u32 A_dsa_datain_used[] __attribute((unused)) = {
-	0x000000c2,
-};
-
-#define A_dsa_dataout	0x00000050
-static u32 A_dsa_dataout_used[] __attribute((unused)) = {
-	0x000000ac,
-};
-
-#define A_dsa_end	0x00000070
-static u32 A_dsa_end_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_fields_start	0x00000000
-static u32 A_dsa_fields_start_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_msgin	0x00000058
-static u32 A_dsa_msgin_used[] __attribute((unused)) = {
-	0x0000019c,
-};
-
-#define A_dsa_msgout	0x00000040
-static u32 A_dsa_msgout_used[] __attribute((unused)) = {
-	0x00000089,
-};
-
-#define A_dsa_msgout_other	0x00000068
-static u32 A_dsa_msgout_other_used[] __attribute((unused)) = {
-	0x00000194,
-};
-
-#define A_dsa_next	0x00000030
-static u32 A_dsa_next_used[] __attribute((unused)) = {
-	0x00000061,
-};
-
-#define A_dsa_restore_pointers	0x00000000
-static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = {
-	0x00000146,
-};
-
-#define A_dsa_save_data_pointer	0x00000000
-static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = {
-	0x00000131,
-};
-
-#define A_dsa_select	0x0000003c
-static u32 A_dsa_select_used[] __attribute((unused)) = {
-	0x00000082,
-};
-
-#define A_dsa_sscf_710	0x00000000
-static u32 A_dsa_sscf_710_used[] __attribute((unused)) = {
-	0x00000007,
-};
-
-#define A_dsa_status	0x00000060
-static u32 A_dsa_status_used[] __attribute((unused)) = {
-	0x00000198,
-};
-
-#define A_dsa_temp_addr_array_value	0x00000000
-static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_temp_addr_dsa_value	0x00000000
-static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = {
-	0x00000001,
-};
-
-#define A_dsa_temp_addr_new_value	0x00000000
-static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_temp_addr_next	0x00000000
-static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = {
-	0x0000001c,
-	0x0000004f,
-};
-
-#define A_dsa_temp_addr_residual	0x00000000
-static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = {
-	0x0000002d,
-	0x0000003b,
-};
-
-#define A_dsa_temp_addr_saved_pointer	0x00000000
-static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = {
-	0x0000002b,
-	0x00000037,
-};
-
-#define A_dsa_temp_addr_saved_residual	0x00000000
-static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = {
-	0x0000002e,
-	0x0000003a,
-};
-
-#define A_dsa_temp_lun	0x00000000
-static u32 A_dsa_temp_lun_used[] __attribute((unused)) = {
-	0x0000004c,
-};
-
-#define A_dsa_temp_next	0x00000000
-static u32 A_dsa_temp_next_used[] __attribute((unused)) = {
-	0x0000001f,
-};
-
-#define A_dsa_temp_sync	0x00000000
-static u32 A_dsa_temp_sync_used[] __attribute((unused)) = {
-	0x00000057,
-};
-
-#define A_dsa_temp_target	0x00000000
-static u32 A_dsa_temp_target_used[] __attribute((unused)) = {
-	0x00000045,
-};
-
-#define A_emulfly	0x00000000
-static u32 A_emulfly_used[] __attribute((unused)) = {
-};
-
-#define A_int_debug_break	0x03000000
-static u32 A_int_debug_break_used[] __attribute((unused)) = {
-	0x0000023c,
-};
-
-#define A_int_debug_panic	0x030b0000
-static u32 A_int_debug_panic_used[] __attribute((unused)) = {
-	0x00000209,
-	0x00000219,
-};
-
-#define A_int_err_check_condition	0x00030000
-static u32 A_int_err_check_condition_used[] __attribute((unused)) = {
-	0x000001a9,
-};
-
-#define A_int_err_no_phase	0x00040000
-static u32 A_int_err_no_phase_used[] __attribute((unused)) = {
-};
-
-#define A_int_err_selected	0x00010000
-static u32 A_int_err_selected_used[] __attribute((unused)) = {
-	0x000001ff,
-};
-
-#define A_int_err_unexpected_phase	0x00000000
-static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = {
-	0x00000092,
-	0x00000098,
-	0x000000a0,
-	0x000000d6,
-	0x000000da,
-	0x000000dc,
-	0x000000e4,
-	0x000000e8,
-	0x000000ea,
-	0x000000f2,
-	0x000000f6,
-	0x000000f8,
-	0x000000fa,
-	0x00000160,
-};
-
-#define A_int_err_unexpected_reselect	0x00020000
-static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = {
-	0x000001cd,
-};
-
-#define A_int_msg_1	0x01020000
-static u32 A_int_msg_1_used[] __attribute((unused)) = {
-	0x00000114,
-	0x00000116,
-};
-
-#define A_int_msg_sdtr	0x01010000
-static u32 A_int_msg_sdtr_used[] __attribute((unused)) = {
-	0x00000180,
-};
-
-#define A_int_msg_wdtr	0x01000000
-static u32 A_int_msg_wdtr_used[] __attribute((unused)) = {
-	0x00000174,
-};
-
-#define A_int_norm_aborted	0x02040000
-static u32 A_int_norm_aborted_used[] __attribute((unused)) = {
-	0x00000270,
-};
-
-#define A_int_norm_command_complete	0x02020000
-static u32 A_int_norm_command_complete_used[] __attribute((unused)) = {
-};
-
-#define A_int_norm_disconnected	0x02030000
-static u32 A_int_norm_disconnected_used[] __attribute((unused)) = {
-};
-
-#define A_int_norm_emulateintfly	0x02060000
-static u32 A_int_norm_emulateintfly_used[] __attribute((unused)) = {
-	0x000001a2,
-};
-
-#define A_int_norm_reselect_complete	0x02010000
-static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = {
-};
-
-#define A_int_norm_reset	0x02050000
-static u32 A_int_norm_reset_used[] __attribute((unused)) = {
-};
-
-#define A_int_norm_select_complete	0x02000000
-static u32 A_int_norm_select_complete_used[] __attribute((unused)) = {
-};
-
-#define A_int_test_1	0x04000000
-static u32 A_int_test_1_used[] __attribute((unused)) = {
-	0x0000021e,
-};
-
-#define A_int_test_2	0x04010000
-static u32 A_int_test_2_used[] __attribute((unused)) = {
-	0x0000023a,
-};
-
-#define A_int_test_3	0x04020000
-static u32 A_int_test_3_used[] __attribute((unused)) = {
-};
-
-#define A_msg_buf	0x00000000
-static u32 A_msg_buf_used[] __attribute((unused)) = {
-	0x00000108,
-	0x00000162,
-	0x0000016c,
-	0x00000172,
-	0x00000178,
-	0x0000017e,
-};
-
-#define A_reconnect_dsa_head	0x00000000
-static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = {
-	0x0000006d,
-	0x00000074,
-	0x000001b1,
-};
-
-#define A_reselected_identify	0x00000000
-static u32 A_reselected_identify_used[] __attribute((unused)) = {
-	0x00000048,
-	0x000001af,
-};
-
-#define A_reselected_tag	0x00000000
-static u32 A_reselected_tag_used[] __attribute((unused)) = {
-};
-
-#define A_saved_dsa	0x00000000
-static u32 A_saved_dsa_used[] __attribute((unused)) = {
-	0x00000005,
-	0x0000000e,
-	0x00000023,
-	0x00000025,
-	0x00000032,
-	0x0000003f,
-	0x00000054,
-	0x0000005f,
-	0x00000070,
-	0x00000078,
-	0x0000008d,
-	0x000000aa,
-	0x000000bb,
-	0x000000c0,
-	0x000000d1,
-	0x0000012f,
-	0x000001a4,
-	0x000001b5,
-	0x000001ba,
-	0x000001e2,
-};
-
-#define A_schedule	0x00000000
-static u32 A_schedule_used[] __attribute((unused)) = {
-	0x0000007d,
-	0x000001a7,
-	0x00000203,
-	0x00000244,
-};
-
-#define A_test_dest	0x00000000
-static u32 A_test_dest_used[] __attribute((unused)) = {
-	0x0000021c,
-};
-
-#define A_test_src	0x00000000
-static u32 A_test_src_used[] __attribute((unused)) = {
-	0x0000021b,
-};
-
-#define Ent_accept_message	0x00000624
-#define Ent_cmdout_cmdout	0x00000264
-#define Ent_command_complete	0x0000065c
-#define Ent_command_complete_msgin	0x0000066c
-#define Ent_data_transfer	0x0000026c
-#define Ent_datain_to_jump	0x00000334
-#define Ent_debug_break	0x000008ec
-#define Ent_dsa_code_begin	0x00000000
-#define Ent_dsa_code_check_reselect	0x0000010c
-#define Ent_dsa_code_fix_jump	0x00000058
-#define Ent_dsa_code_restore_pointers	0x000000d8
-#define Ent_dsa_code_save_data_pointer	0x000000a4
-#define Ent_dsa_code_template	0x00000000
-#define Ent_dsa_code_template_end	0x00000178
-#define Ent_dsa_schedule	0x00000178
-#define Ent_dsa_zero	0x00000178
-#define Ent_end_data_transfer	0x000002a4
-#define Ent_initiator_abort	0x00000914
-#define Ent_msg_in	0x0000041c
-#define Ent_msg_in_restart	0x000003fc
-#define Ent_other_in	0x0000038c
-#define Ent_other_out	0x00000354
-#define Ent_other_transfer	0x000003c4
-#define Ent_reject_message	0x00000604
-#define Ent_reselected_check_next	0x000006f0
-#define Ent_reselected_ok	0x00000798
-#define Ent_respond_message	0x0000063c
-#define Ent_select	0x000001f8
-#define Ent_select_msgout	0x00000218
-#define Ent_target_abort	0x000008f4
-#define Ent_test_1	0x00000868
-#define Ent_test_2	0x0000087c
-#define Ent_test_2_msgout	0x0000089c
-#define Ent_wait_reselect	0x000006a8
-static u32 LABELPATCHES[] __attribute((unused)) = {
-	0x00000011,
-	0x0000001a,
-	0x0000001d,
-	0x00000028,
-	0x0000002a,
-	0x00000035,
-	0x00000038,
-	0x00000042,
-	0x00000050,
-	0x00000052,
-	0x0000006b,
-	0x00000083,
-	0x00000085,
-	0x00000090,
-	0x00000094,
-	0x00000096,
-	0x0000009c,
-	0x0000009e,
-	0x000000a2,
-	0x000000a4,
-	0x000000a6,
-	0x000000a8,
-	0x000000b6,
-	0x000000b9,
-	0x000000cc,
-	0x000000cf,
-	0x000000d8,
-	0x000000de,
-	0x000000e0,
-	0x000000e6,
-	0x000000ec,
-	0x000000ee,
-	0x000000f4,
-	0x000000fc,
-	0x000000fe,
-	0x0000010a,
-	0x0000010c,
-	0x0000010e,
-	0x00000110,
-	0x00000112,
-	0x00000118,
-	0x0000011a,
-	0x0000012d,
-	0x00000143,
-	0x00000158,
-	0x0000015c,
-	0x00000164,
-	0x00000166,
-	0x00000168,
-	0x0000016e,
-	0x0000017a,
-	0x000001ab,
-	0x000001b8,
-	0x000001bf,
-	0x000001c3,
-	0x000001c7,
-	0x000001cb,
-	0x000001e0,
-	0x000001f8,
-	0x00000207,
-	0x0000020f,
-	0x00000213,
-	0x00000217,
-	0x00000224,
-	0x00000226,
-	0x00000248,
-	0x0000024a,
-	0x0000024c,
-	0x0000024e,
-	0x00000250,
-	0x00000252,
-	0x00000256,
-	0x0000025a,
-	0x0000025c,
-	0x00000260,
-	0x00000262,
-	0x00000266,
-	0x00000268,
-};
-
-static struct {
-	u32	offset;
-	void		*address;
-} EXTERNAL_PATCHES[] __attribute((unused)) = {
-};
-
-static u32 INSTRUCTIONS __attribute((unused))	= 290;
-static u32 PATCHES __attribute((unused))	= 78;
-static u32 EXTERNAL_PATCHES_LEN __attribute((unused))	= 0;
diff --git a/drivers/scsi/53c7xx_u.h_shipped b/drivers/scsi/53c7xx_u.h_shipped
deleted file mode 100644
index 7b33717..0000000
--- a/drivers/scsi/53c7xx_u.h_shipped
+++ /dev/null
@@ -1,102 +0,0 @@
-#undef A_NCR53c7xx_msg_abort
-#undef A_NCR53c7xx_msg_reject
-#undef A_NCR53c7xx_sink
-#undef A_NCR53c7xx_zero
-#undef A_NOP_insn
-#undef A_addr_dsa
-#undef A_addr_reconnect_dsa_head
-#undef A_addr_scratch
-#undef A_addr_temp
-#undef A_dmode_memory_to_memory
-#undef A_dmode_memory_to_ncr
-#undef A_dmode_ncr_to_memory
-#undef A_dsa_check_reselect
-#undef A_dsa_cmdout
-#undef A_dsa_cmnd
-#undef A_dsa_datain
-#undef A_dsa_dataout
-#undef A_dsa_end
-#undef A_dsa_fields_start
-#undef A_dsa_msgin
-#undef A_dsa_msgout
-#undef A_dsa_msgout_other
-#undef A_dsa_next
-#undef A_dsa_restore_pointers
-#undef A_dsa_save_data_pointer
-#undef A_dsa_select
-#undef A_dsa_sscf_710
-#undef A_dsa_status
-#undef A_dsa_temp_addr_array_value
-#undef A_dsa_temp_addr_dsa_value
-#undef A_dsa_temp_addr_new_value
-#undef A_dsa_temp_addr_next
-#undef A_dsa_temp_addr_residual
-#undef A_dsa_temp_addr_saved_pointer
-#undef A_dsa_temp_addr_saved_residual
-#undef A_dsa_temp_lun
-#undef A_dsa_temp_next
-#undef A_dsa_temp_sync
-#undef A_dsa_temp_target
-#undef A_emulfly
-#undef A_int_debug_break
-#undef A_int_debug_panic
-#undef A_int_err_check_condition
-#undef A_int_err_no_phase
-#undef A_int_err_selected
-#undef A_int_err_unexpected_phase
-#undef A_int_err_unexpected_reselect
-#undef A_int_msg_1
-#undef A_int_msg_sdtr
-#undef A_int_msg_wdtr
-#undef A_int_norm_aborted
-#undef A_int_norm_command_complete
-#undef A_int_norm_disconnected
-#undef A_int_norm_emulateintfly
-#undef A_int_norm_reselect_complete
-#undef A_int_norm_reset
-#undef A_int_norm_select_complete
-#undef A_int_test_1
-#undef A_int_test_2
-#undef A_int_test_3
-#undef A_msg_buf
-#undef A_reconnect_dsa_head
-#undef A_reselected_identify
-#undef A_reselected_tag
-#undef A_saved_dsa
-#undef A_schedule
-#undef A_test_dest
-#undef A_test_src
-#undef Ent_accept_message
-#undef Ent_cmdout_cmdout
-#undef Ent_command_complete
-#undef Ent_command_complete_msgin
-#undef Ent_data_transfer
-#undef Ent_datain_to_jump
-#undef Ent_debug_break
-#undef Ent_dsa_code_begin
-#undef Ent_dsa_code_check_reselect
-#undef Ent_dsa_code_fix_jump
-#undef Ent_dsa_code_restore_pointers
-#undef Ent_dsa_code_save_data_pointer
-#undef Ent_dsa_code_template
-#undef Ent_dsa_code_template_end
-#undef Ent_dsa_schedule
-#undef Ent_dsa_zero
-#undef Ent_end_data_transfer
-#undef Ent_initiator_abort
-#undef Ent_msg_in
-#undef Ent_msg_in_restart
-#undef Ent_other_in
-#undef Ent_other_out
-#undef Ent_other_transfer
-#undef Ent_reject_message
-#undef Ent_reselected_check_next
-#undef Ent_reselected_ok
-#undef Ent_respond_message
-#undef Ent_select
-#undef Ent_select_msgout
-#undef Ent_target_abort
-#undef Ent_test_1
-#undef Ent_test_2
-#undef Ent_test_2_msgout
-#undef Ent_wait_reselect
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 96f4cab0..9b20617 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -304,18 +304,10 @@
 static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
 {
 	struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
-	struct scsi_cmnd *cmd = CCB->Command;
 
-	if (cmd->use_sg != 0) {
-		pci_unmap_sg(HostAdapter->PCI_Device,
-				(struct scatterlist *)cmd->request_buffer,
-				cmd->use_sg, cmd->sc_data_direction);
-	} else if (cmd->request_bufflen != 0) {
-		pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer,
-				CCB->DataLength, cmd->sc_data_direction);
-	}
+	scsi_dma_unmap(CCB->Command);
 	pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
-			CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+			 CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
 
 	CCB->Command = NULL;
 	CCB->Status = BusLogic_CCB_Free;
@@ -2648,7 +2640,8 @@
 			 */
 			if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) {
 				struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID];
-				struct SCSI_Inquiry *InquiryResult = (struct SCSI_Inquiry *) Command->request_buffer;
+				struct SCSI_Inquiry *InquiryResult =
+					(struct SCSI_Inquiry *) scsi_sglist(Command);
 				TargetFlags->TargetExists = true;
 				TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
 				TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
@@ -2819,9 +2812,8 @@
 	int CDB_Length = Command->cmd_len;
 	int TargetID = Command->device->id;
 	int LogicalUnit = Command->device->lun;
-	void *BufferPointer = Command->request_buffer;
-	int BufferLength = Command->request_bufflen;
-	int SegmentCount = Command->use_sg;
+	int BufferLength = scsi_bufflen(Command);
+	int Count;
 	struct BusLogic_CCB *CCB;
 	/*
 	   SCSI REQUEST_SENSE commands will be executed automatically by the Host
@@ -2851,36 +2843,35 @@
 			return 0;
 		}
 	}
+
 	/*
 	   Initialize the fields in the BusLogic Command Control Block (CCB).
 	 */
-	if (SegmentCount == 0 && BufferLength != 0) {
-		CCB->Opcode = BusLogic_InitiatorCCB;
-		CCB->DataLength = BufferLength;
-		CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device,
-				BufferPointer, BufferLength,
-				Command->sc_data_direction);
-	} else if (SegmentCount != 0) {
-		struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer;
-		int Segment, Count;
+	Count = scsi_dma_map(Command);
+	BUG_ON(Count < 0);
+	if (Count) {
+		struct scatterlist *sg;
+		int i;
 
-		Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount,
-				Command->sc_data_direction);
 		CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
 		CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
 		if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
 			CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB);
 		else
 			CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
-		for (Segment = 0; Segment < Count; Segment++) {
-			CCB->ScatterGatherList[Segment].SegmentByteCount = sg_dma_len(ScatterList + Segment);
-			CCB->ScatterGatherList[Segment].SegmentDataPointer = sg_dma_address(ScatterList + Segment);
+
+		scsi_for_each_sg(Command, sg, Count, i) {
+			CCB->ScatterGatherList[i].SegmentByteCount =
+				sg_dma_len(sg);
+			CCB->ScatterGatherList[i].SegmentDataPointer =
+				sg_dma_address(sg);
 		}
-	} else {
+	} else if (!Count) {
 		CCB->Opcode = BusLogic_InitiatorCCB;
 		CCB->DataLength = BufferLength;
 		CCB->DataPointer = 0;
 	}
+
 	switch (CDB[0]) {
 	case READ_6:
 	case READ_10:
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index d28c14e..3727231 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -10,6 +10,7 @@
 config SCSI
 	tristate "SCSI device support"
 	depends on BLOCK
+	select SCSI_DMA if HAS_DMA
 	---help---
 	  If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
 	  any other SCSI device under Linux, say Y and make sure that you know
@@ -29,6 +30,10 @@
 	  However, do not compile this as a module if your root file system
 	  (the one containing the directory /) is located on a SCSI device.
 
+config SCSI_DMA
+	bool
+	default n
+
 config SCSI_TGT
 	tristate "SCSI target support"
 	depends on SCSI && EXPERIMENTAL
@@ -60,6 +65,7 @@
 	depends on SCSI
 	---help---
 	  If you want to use SCSI hard disks, Fibre Channel disks,
+	  Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
 	  USB storage or the SCSI or parallel port version of
 	  the IOMEGA ZIP drive, say Y and read the SCSI-HOWTO,
 	  the Disk-HOWTO and the Multi-Disk-HOWTO, available from
@@ -539,7 +545,7 @@
 
 config SCSI_BUSLOGIC
 	tristate "BusLogic SCSI support"
-	depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API
+	depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API && VIRT_TO_BUS
 	---help---
 	  This is support for BusLogic MultiMaster and FlashPoint SCSI Host
 	  Adapters. Consult the SCSI-HOWTO, available from
@@ -738,7 +744,7 @@
 
 config SCSI_IBMMCA
 	tristate "IBMMCA SCSI support"
-	depends on MCA_LEGACY && SCSI
+	depends on MCA && SCSI
 	---help---
 	  This is support for the IBM SCSI adapter found in many of the PS/2
 	  series computers.  These machines have an MCA bus, so you need to
@@ -1006,6 +1012,11 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called stex.
 
+config 53C700_BE_BUS
+	bool
+	depends on SCSI_A4000T || SCSI_ZORRO7XX || MVME16x_SCSI || BVME6000_SCSI
+	default y
+
 config SCSI_SYM53C8XX_2
 	tristate "SYM53C8XX Version 2 SCSI support"
 	depends on PCI && SCSI
@@ -1532,6 +1543,7 @@
 config JAZZ_ESP
 	bool "MIPS JAZZ FAS216 SCSI support"
 	depends on MACH_JAZZ && SCSI
+	select SCSI_SPI_ATTRS
 	help
 	  This is the driver for the onboard SCSI host adapter of MIPS Magnum
 	  4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
@@ -1609,13 +1621,25 @@
 	  If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
 	  one in the near future, say Y to this question. Otherwise, say N.
 
-config SCSI_AMIGA7XX
-	bool "Amiga NCR53c710 SCSI support (EXPERIMENTAL)"
-	depends on AMIGA && SCSI && EXPERIMENTAL && BROKEN
+config SCSI_A4000T
+	tristate "A4000T NCR53c710 SCSI support (EXPERIMENTAL)"
+	depends on AMIGA && SCSI && EXPERIMENTAL
+	select SCSI_SPI_ATTRS
 	help
-	  Support for various NCR53c710-based SCSI controllers on the Amiga.
+	  If you have an Amiga 4000T and have SCSI devices connected to the
+	  built-in SCSI controller, say Y. Otherwise, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called a4000t.
+
+config SCSI_ZORRO7XX
+	tristate "Zorro NCR53c710 SCSI support (EXPERIMENTAL)"
+	depends on ZORRO && SCSI && EXPERIMENTAL
+	select SCSI_SPI_ATTRS
+	help
+	  Support for various NCR53c710-based SCSI controllers on Zorro
+	  expansion boards for the Amiga.
 	  This includes:
-	    - the builtin SCSI controller on the Amiga 4000T,
 	    - the Amiga 4091 Zorro III SCSI-2 controller,
 	    - the MacroSystem Development's WarpEngine Amiga SCSI-2 controller
 	      (info at
@@ -1623,10 +1647,6 @@
 	    - the SCSI controller on the Phase5 Blizzard PowerUP 603e+
 	      accelerator card for the Amiga 1200,
 	    - the SCSI controller on the GVP Turbo 040/060 accelerator.
-	  Note that all of the above SCSI controllers, except for the builtin
-	  SCSI controller on the Amiga 4000T, reside on the Zorro expansion
-	  bus, so you also have to enable Zorro bus support if you want to use
-	  them.
 
 config OKTAGON_SCSI
 	tristate "BSC Oktagon SCSI support (EXPERIMENTAL)"
@@ -1710,8 +1730,8 @@
 	  single-board computer.
 
 config MVME16x_SCSI
-	bool "NCR53C710 SCSI driver for MVME16x"
-	depends on MVME16x && SCSI && BROKEN
+	tristate "NCR53C710 SCSI driver for MVME16x"
+	depends on MVME16x && SCSI
 	select SCSI_SPI_ATTRS
 	help
 	  The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
@@ -1719,22 +1739,14 @@
 	  will want to say Y to this question.
 
 config BVME6000_SCSI
-	bool "NCR53C710 SCSI driver for BVME6000"
-	depends on BVME6000 && SCSI && BROKEN
+	tristate "NCR53C710 SCSI driver for BVME6000"
+	depends on BVME6000 && SCSI
 	select SCSI_SPI_ATTRS
 	help
 	  The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
 	  SCSI controller chip.  Almost everyone using one of these boards
 	  will want to say Y to this question.
 
-config SCSI_NCR53C7xx_FAST
-	bool "allow FAST-SCSI [10MHz]"
-	depends on SCSI_AMIGA7XX || MVME16x_SCSI || BVME6000_SCSI
-	help
-	  This will enable 10MHz FAST-SCSI transfers with your host
-	  adapter. Some systems have problems with that speed, so it's safest
-	  to say N here.
-
 config SUN3_SCSI
 	tristate "Sun3 NCR5380 SCSI"
 	depends on SUN3 && SCSI
@@ -1753,23 +1765,10 @@
 	  The ESP was an on-board SCSI controller used on Sun 3/80
 	  machines.  Say Y here to compile in support for it.
 
-config SCSI_ESP_CORE
-	tristate "ESP Scsi Driver Core"
-	depends on SCSI
-	select SCSI_SPI_ATTRS
-	help
-	  This is a core driver for NCR53c9x based scsi chipsets,
-	  also known as "ESP" for Emulex Scsi Processor or
-	  Enhanced Scsi Processor.  This driver does not exist by
-	  itself, there are front-end drivers which, when enabled,
-	  select and enable this driver.  One example is SCSI_SUNESP.
-	  These front-end drivers provide probing, DMA, and register
-	  access support for the core driver.
-
 config SCSI_SUNESP
 	tristate "Sparc ESP Scsi Driver"
 	depends on SBUS && SCSI
-	select SCSI_ESP_CORE
+	select SCSI_SPI_ATTRS
 	help
 	  This is the driver for the Sun ESP SCSI host adapter. The ESP
 	  chipset is present in most SPARC SBUS-based computers.
@@ -1777,8 +1776,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called esp.
 
-#      bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI
-
 config ZFCP
 	tristate "FCP host bus adapter driver for IBM eServer zSeries"
 	depends on S390 && QDIO && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 51e884f..0f86895 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -37,7 +37,8 @@
 
 obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	iscsi_tcp.o
 obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
-obj-$(CONFIG_SCSI_AMIGA7XX)	+= amiga7xx.o	53c7xx.o
+obj-$(CONFIG_SCSI_A4000T)	+= 53c700.o	a4000t.o
+obj-$(CONFIG_SCSI_ZORRO7XX)	+= 53c700.o	zorro7xx.o
 obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
 obj-$(CONFIG_A2091_SCSI)	+= a2091.o	wd33c93.o
 obj-$(CONFIG_GVP11_SCSI)	+= gvp11.o	wd33c93.o
@@ -53,8 +54,8 @@
 obj-$(CONFIG_MAC_SCSI)		+= mac_scsi.o
 obj-$(CONFIG_SCSI_MAC_ESP)	+= mac_esp.o	NCR53C9x.o
 obj-$(CONFIG_SUN3_SCSI)		+= sun3_scsi.o  sun3_scsi_vme.o
-obj-$(CONFIG_MVME16x_SCSI)	+= mvme16x.o	53c7xx.o
-obj-$(CONFIG_BVME6000_SCSI)	+= bvme6000.o	53c7xx.o
+obj-$(CONFIG_MVME16x_SCSI)	+= 53c700.o	mvme16x_scsi.o
+obj-$(CONFIG_BVME6000_SCSI)	+= 53c700.o	bvme6000_scsi.o
 obj-$(CONFIG_SCSI_SIM710)	+= 53c700.o	sim710.o
 obj-$(CONFIG_SCSI_ADVANSYS)	+= advansys.o
 obj-$(CONFIG_SCSI_PSI240I)	+= psi240i.o
@@ -89,7 +90,6 @@
 obj-$(CONFIG_SCSI_LPFC)		+= lpfc/
 obj-$(CONFIG_SCSI_PAS16)	+= pas16.o
 obj-$(CONFIG_SCSI_SEAGATE)	+= seagate.o
-obj-$(CONFIG_SCSI_FD_8xx)	+= seagate.o
 obj-$(CONFIG_SCSI_T128)		+= t128.o
 obj-$(CONFIG_SCSI_DMX3191D)	+= dmx3191d.o
 obj-$(CONFIG_SCSI_DTC3280)	+= dtc.o
@@ -106,8 +106,7 @@
 obj-$(CONFIG_MEGARAID_NEWGEN)	+= megaraid/
 obj-$(CONFIG_MEGARAID_SAS)	+= megaraid/
 obj-$(CONFIG_SCSI_ACARD)	+= atp870u.o
-obj-$(CONFIG_SCSI_ESP_CORE)	+= esp_scsi.o
-obj-$(CONFIG_SCSI_SUNESP)	+= sun_esp.o
+obj-$(CONFIG_SCSI_SUNESP)	+= esp_scsi.o	sun_esp.o
 obj-$(CONFIG_SCSI_GDTH)		+= gdth.o
 obj-$(CONFIG_SCSI_INITIO)	+= initio.o
 obj-$(CONFIG_SCSI_INIA100)	+= a100u2w.o
@@ -121,7 +120,7 @@
 obj-$(CONFIG_SCSI_3W_9XXX)	+= 3w-9xxx.o
 obj-$(CONFIG_SCSI_PPA)		+= ppa.o
 obj-$(CONFIG_SCSI_IMM)		+= imm.o
-obj-$(CONFIG_JAZZ_ESP)		+= NCR53C9x.o	jazz_esp.o
+obj-$(CONFIG_JAZZ_ESP)		+= esp_scsi.o	jazz_esp.o
 obj-$(CONFIG_SUN3X_ESP)		+= NCR53C9x.o	sun3x_esp.o
 obj-$(CONFIG_SCSI_FCAL)		+= fcal.o
 obj-$(CONFIG_SCSI_LASI700)	+= 53c700.o lasi700.o
@@ -149,9 +148,9 @@
 obj-$(CONFIG_SCSI_WAIT_SCAN)	+= scsi_wait_scan.o
 
 scsi_mod-y			+= scsi.o hosts.o scsi_ioctl.o constants.o \
-				   scsicam.o scsi_error.o scsi_lib.o \
-				   scsi_scan.o scsi_sysfs.o \
-				   scsi_devinfo.o
+				   scsicam.o scsi_error.o scsi_lib.o
+scsi_mod-$(CONFIG_SCSI_DMA)	+= scsi_lib_dma.o
+scsi_mod-y			+= scsi_scan.o scsi_sysfs.o scsi_devinfo.o
 scsi_mod-$(CONFIG_SCSI_NETLINK)	+= scsi_netlink.o
 scsi_mod-$(CONFIG_SYSCTL)	+= scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
@@ -169,10 +168,8 @@
 oktagon_esp_mod-objs	:= oktagon_esp.o oktagon_io.o
 
 # Files generated that shall be removed upon make clean
-clean-files :=	53c7xx_d.h 53c700_d.h	\
-		53c7xx_u.h 53c700_u.h
+clean-files :=	53c700_d.h 53c700_u.h
 
-$(obj)/53c7xx.o:   $(obj)/53c7xx_d.h $(obj)/53c7xx_u.h
 $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h
 
 # If you want to play with the firmware, uncomment
@@ -180,11 +177,6 @@
 
 ifdef GENERATE_FIRMWARE
 
-$(obj)/53c7xx_d.h: $(src)/53c7xx.scr $(src)/script_asm.pl
-	$(CPP) -traditional -DCHIP=710 - < $< | grep -v '^#' | $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h)
-
-$(obj)/53c7xx_u.h: $(obj)/53c7xx_d.h
-
 $(obj)/53c700_d.h: $(src)/53c700.scr $(src)/script_asm.pl
 	$(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h) < $<
 
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index bb3cb33..f8e449a 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -347,7 +347,7 @@
 		if((r & bit) == val)
 			return 0;
 		if(!in_interrupt())
-			yield();
+			cond_resched();
 		else
 			cpu_relax();
 	}
@@ -357,7 +357,7 @@
 static struct {
 	unsigned char value;
 	const char *name;
-} phases[] = {
+} phases[] __maybe_unused = {
 	{PHASE_DATAOUT, "DATAOUT"}, 
 	{PHASE_DATAIN, "DATAIN"}, 
 	{PHASE_CMDOUT, "CMDOUT"}, 
@@ -575,7 +575,8 @@
  *	Locks: none, irqs must be enabled on entry
  */
 
-static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
+static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
+						int possible)
 {
 	NCR5380_local_declare();
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
@@ -629,7 +630,8 @@
  *	Locks: none
  */
 
-static void __init NCR5380_print_options(struct Scsi_Host *instance)
+static void __init __maybe_unused
+NCR5380_print_options(struct Scsi_Host *instance)
 {
 	printk(" generic options"
 #ifdef AUTOPROBE_IRQ
@@ -703,8 +705,8 @@
 static
 char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
 
-static
-int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset, int length, int inout)
+static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
+	char *buffer, char **start, off_t offset, int length, int inout)
 {
 	char *pos = buffer;
 	struct NCR5380_hostdata *hostdata;
@@ -2625,7 +2627,7 @@
 #ifdef REAL_DMA
 static void NCR5380_dma_complete(NCR5380_instance * instance) {
 	NCR5380_local_declare();
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata * instance->hostdata);
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	int transferred;
 	NCR5380_setup(instance);
 
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 713a108..bccf13f 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -299,7 +299,7 @@
 static irqreturn_t NCR5380_intr(int irq, void *dev_id);
 #endif
 static void NCR5380_main(struct work_struct *work);
-static void NCR5380_print_options(struct Scsi_Host *instance);
+static void __maybe_unused NCR5380_print_options(struct Scsi_Host *instance);
 #ifdef NDEBUG
 static void NCR5380_print_phase(struct Scsi_Host *instance);
 static void NCR5380_print(struct Scsi_Host *instance);
@@ -307,8 +307,8 @@
 static int NCR5380_abort(Scsi_Cmnd * cmd);
 static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
 static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
-static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
-off_t offset, int length, int inout);
+static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
+	char *buffer, char **start, off_t offset, int length, int inout);
 
 static void NCR5380_reselect(struct Scsi_Host *instance);
 static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 7c0b17f..eda8c48 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -698,7 +698,7 @@
 	int i;
 
 	VDEB(printk("NCR53c406a_queue called\n"));
-	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, SCpnt->request_bufflen));
+	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
 
 #if 0
 	VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
@@ -785,8 +785,8 @@
 	unsigned char status, int_reg;
 #if USE_PIO
 	unsigned char pio_status;
-	struct scatterlist *sglist;
-	unsigned int sgcount;
+	struct scatterlist *sg;
+        int i;
 #endif
 
 	VDEB(printk("NCR53c406a_intr called\n"));
@@ -866,22 +866,18 @@
 			current_SC->SCp.phase = data_out;
 			VDEB(printk("NCR53c406a: Data-Out phase\n"));
 			outb(FLUSH_FIFO, CMD_REG);
-			LOAD_DMA_COUNT(current_SC->request_bufflen);	/* Max transfer size */
+			LOAD_DMA_COUNT(scsi_bufflen(current_SC));	/* Max transfer size */
 #if USE_DMA			/* No s/g support for DMA */
-			NCR53c406a_dma_write(current_SC->request_buffer, current_SC->request_bufflen);
+			NCR53c406a_dma_write(scsi_sglist(current_SC),
+                                             scsdi_bufflen(current_SC));
+
 #endif				/* USE_DMA */
 			outb(TRANSFER_INFO | DMA_OP, CMD_REG);
 #if USE_PIO
-			if (!current_SC->use_sg)	/* Don't use scatter-gather */
-				NCR53c406a_pio_write(current_SC->request_buffer, current_SC->request_bufflen);
-			else {	/* use scatter-gather */
-				sgcount = current_SC->use_sg;
-				sglist = current_SC->request_buffer;
-				while (sgcount--) {
-					NCR53c406a_pio_write(page_address(sglist->page) + sglist->offset, sglist->length);
-					sglist++;
-				}
-			}
+                        scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
+                                NCR53c406a_pio_write(page_address(sg->page) + sg->offset,
+                                                     sg->length);
+                        }
 			REG0;
 #endif				/* USE_PIO */
 		}
@@ -893,22 +889,17 @@
 			current_SC->SCp.phase = data_in;
 			VDEB(printk("NCR53c406a: Data-In phase\n"));
 			outb(FLUSH_FIFO, CMD_REG);
-			LOAD_DMA_COUNT(current_SC->request_bufflen);	/* Max transfer size */
+			LOAD_DMA_COUNT(scsi_bufflen(current_SC));	/* Max transfer size */
 #if USE_DMA			/* No s/g support for DMA */
-			NCR53c406a_dma_read(current_SC->request_buffer, current_SC->request_bufflen);
+			NCR53c406a_dma_read(scsi_sglist(current_SC),
+                                            scsdi_bufflen(current_SC));
 #endif				/* USE_DMA */
 			outb(TRANSFER_INFO | DMA_OP, CMD_REG);
 #if USE_PIO
-			if (!current_SC->use_sg)	/* Don't use scatter-gather */
-				NCR53c406a_pio_read(current_SC->request_buffer, current_SC->request_bufflen);
-			else {	/* Use scatter-gather */
-				sgcount = current_SC->use_sg;
-				sglist = current_SC->request_buffer;
-				while (sgcount--) {
-					NCR53c406a_pio_read(page_address(sglist->page) + sglist->offset, sglist->length);
-					sglist++;
-				}
-			}
+                        scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
+                                NCR53c406a_pio_read(page_address(sg->page) + sg->offset,
+                                                    sg->length);
+                        }
 			REG0;
 #endif				/* USE_PIO */
 		}
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 7f4241b..f608d4a 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -19,27 +19,6 @@
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * --------------------------------------------------------------------------
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of 
- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -75,6 +54,8 @@
  * 9/28/04 Christoph Hellwig <hch@lst.de>
  *	    - merge the two source files
  *	    - remove internal queueing code
+ * 14/06/07 Alan Cox <alan@redhat.com>
+ *	 - Grand cleanup and Linuxisation
  */
 
 #include <linux/module.h>
@@ -102,14 +83,12 @@
 #include "a100u2w.h"
 
 
-#define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
-#define MS_TO_JIFFIES(j) ((j * HZ) / 1000)
+static struct orc_scb *__orc_alloc_scb(struct orc_host * host);
+static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb);
 
-static ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
-static void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
+static struct orc_nvram nvram, *nvramp = &nvram;
 
-static NVRAM nvram, *nvramp = &nvram;
-static UCHAR dftNvRam[64] =
+static u8 default_nvram[64] =
 {
 /*----------header -------------*/
 	0x01,			/* 0x00: Sub System Vendor ID 0 */
@@ -158,823 +137,882 @@
 };
 
 
-/***************************************************************************/
-static void waitForPause(unsigned amount)
-{
-	ULONG the_time = jiffies + MS_TO_JIFFIES(amount);
-	while (time_before_eq(jiffies, the_time))
-		cpu_relax();
-}
-
-/***************************************************************************/
-static UCHAR waitChipReady(ORC_HCS * hcsp)
+static u8 wait_chip_ready(struct orc_host * host)
 {
 	int i;
 
 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
-		if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP)	/* Wait HOSTSTOP set */
+		if (inb(host->base + ORC_HCTRL) & HOSTSTOP)	/* Wait HOSTSTOP set */
 			return 1;
-		waitForPause(100);	/* wait 100ms before try again  */
+		mdelay(100);
+	}
+	return 0;
+}
+
+static u8 wait_firmware_ready(struct orc_host * host)
+{
+	int i;
+
+	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
+		if (inb(host->base + ORC_HSTUS) & RREADY)		/* Wait READY set */
+			return 1;
+		mdelay(100);	/* wait 100ms before try again  */
 	}
 	return 0;
 }
 
 /***************************************************************************/
-static UCHAR waitFWReady(ORC_HCS * hcsp)
+static u8 wait_scsi_reset_done(struct orc_host * host)
 {
 	int i;
 
 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
-		if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY)		/* Wait READY set */
+		if (!(inb(host->base + ORC_HCTRL) & SCSIRST))	/* Wait SCSIRST done */
 			return 1;
-		waitForPause(100);	/* wait 100ms before try again  */
+		mdelay(100);	/* wait 100ms before try again  */
 	}
 	return 0;
 }
 
 /***************************************************************************/
-static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp)
+static u8 wait_HDO_off(struct orc_host * host)
 {
 	int i;
 
 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
-		if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST))	/* Wait SCSIRST done */
+		if (!(inb(host->base + ORC_HCTRL) & HDO))		/* Wait HDO off */
 			return 1;
-		waitForPause(100);	/* wait 100ms before try again  */
+		mdelay(100);	/* wait 100ms before try again  */
 	}
 	return 0;
 }
 
 /***************************************************************************/
-static UCHAR waitHDOoff(ORC_HCS * hcsp)
+static u8 wait_hdi_set(struct orc_host * host, u8 * data)
 {
 	int i;
 
 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
-		if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO))		/* Wait HDO off */
-			return 1;
-		waitForPause(100);	/* wait 100ms before try again  */
-	}
-	return 0;
-}
-
-/***************************************************************************/
-static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData)
-{
-	int i;
-
-	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
-		if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI)
+		if ((*data = inb(host->base + ORC_HSTUS)) & HDI)
 			return 1;	/* Wait HDI set */
-		waitForPause(100);	/* wait 100ms before try again  */
+		mdelay(100);	/* wait 100ms before try again  */
 	}
 	return 0;
 }
 
 /***************************************************************************/
-static unsigned short get_FW_version(ORC_HCS * hcsp)
+static unsigned short orc_read_fwrev(struct orc_host * host)
 {
-	UCHAR bData;
-	union {
-		unsigned short sVersion;
-		unsigned char cVersion[2];
-	} Version;
+	u16 version;
+	u8 data;
 
-	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION);
-	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
-	if (waitHDOoff(hcsp) == 0)	/* Wait HDO off   */
+	outb(ORC_CMD_VERSION, host->base + ORC_HDATA);
+	outb(HDO, host->base + ORC_HCTRL);
+	if (wait_HDO_off(host) == 0)	/* Wait HDO off   */
 		return 0;
 
-	if (waitHDIset(hcsp, &bData) == 0)	/* Wait HDI set   */
+	if (wait_hdi_set(host, &data) == 0)	/* Wait HDI set   */
 		return 0;
-	Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
-	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI            */
+	version = inb(host->base + ORC_HDATA);
+	outb(data, host->base + ORC_HSTUS);	/* Clear HDI            */
 
-	if (waitHDIset(hcsp, &bData) == 0)	/* Wait HDI set   */
+	if (wait_hdi_set(host, &data) == 0)	/* Wait HDI set   */
 		return 0;
-	Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
-	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI            */
+	version |= inb(host->base + ORC_HDATA) << 8;
+	outb(data, host->base + ORC_HSTUS);	/* Clear HDI            */
 
-	return (Version.sVersion);
+	return version;
 }
 
 /***************************************************************************/
-static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value)
+static u8 orc_nv_write(struct orc_host * host, unsigned char address, unsigned char value)
 {
-	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM);	/* Write command */
-	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
-	if (waitHDOoff(hcsp) == 0)	/* Wait HDO off   */
+	outb(ORC_CMD_SET_NVM, host->base + ORC_HDATA);	/* Write command */
+	outb(HDO, host->base + ORC_HCTRL);
+	if (wait_HDO_off(host) == 0)	/* Wait HDO off   */
 		return 0;
 
-	ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);	/* Write address */
-	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
-	if (waitHDOoff(hcsp) == 0)	/* Wait HDO off   */
+	outb(address, host->base + ORC_HDATA);	/* Write address */
+	outb(HDO, host->base + ORC_HCTRL);
+	if (wait_HDO_off(host) == 0)	/* Wait HDO off   */
 		return 0;
 
-	ORC_WR(hcsp->HCS_Base + ORC_HDATA, value);	/* Write value  */
-	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
-	if (waitHDOoff(hcsp) == 0)	/* Wait HDO off   */
+	outb(value, host->base + ORC_HDATA);	/* Write value  */
+	outb(HDO, host->base + ORC_HCTRL);
+	if (wait_HDO_off(host) == 0)	/* Wait HDO off   */
 		return 0;
 
 	return 1;
 }
 
 /***************************************************************************/
-static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
+static u8 orc_nv_read(struct orc_host * host, u8 address, u8 *ptr)
 {
-	unsigned char bData;
+	unsigned char data;
 
-	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM);	/* Write command */
-	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
-	if (waitHDOoff(hcsp) == 0)	/* Wait HDO off   */
+	outb(ORC_CMD_GET_NVM, host->base + ORC_HDATA);	/* Write command */
+	outb(HDO, host->base + ORC_HCTRL);
+	if (wait_HDO_off(host) == 0)	/* Wait HDO off   */
 		return 0;
 
-	ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);	/* Write address */
-	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
-	if (waitHDOoff(hcsp) == 0)	/* Wait HDO off   */
+	outb(address, host->base + ORC_HDATA);	/* Write address */
+	outb(HDO, host->base + ORC_HCTRL);
+	if (wait_HDO_off(host) == 0)	/* Wait HDO off   */
 		return 0;
 
-	if (waitHDIset(hcsp, &bData) == 0)	/* Wait HDI set   */
+	if (wait_hdi_set(host, &data) == 0)	/* Wait HDI set   */
 		return 0;
-	*pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
-	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI    */
+	*ptr = inb(host->base + ORC_HDATA);
+	outb(data, host->base + ORC_HSTUS);	/* Clear HDI    */
 
 	return 1;
+
 }
 
-/***************************************************************************/
-static void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
+/**
+ *	orc_exec_sb		-	Queue an SCB with the HA
+ *	@host: host adapter the SCB belongs to
+ *	@scb: SCB to queue for execution
+ */
+
+static void orc_exec_scb(struct orc_host * host, struct orc_scb * scb)
 {
-	scbp->SCB_Status = ORCSCB_POST;
-	ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
-	return;
+	scb->status = ORCSCB_POST;
+	outb(scb->scbidx, host->base + ORC_PQUEUE);
 }
 
 
-/***********************************************************************
- Read SCSI H/A configuration parameters from serial EEPROM
-************************************************************************/
-static int se2_rd_all(ORC_HCS * hcsp)
+/**
+ *	se2_rd_all	-	read SCSI parameters from EEPROM
+ *	@host: Host whose EEPROM is being loaded
+ *
+ *	Read SCSI H/A configuration parameters from serial EEPROM
+ */
+
+static int se2_rd_all(struct orc_host * host)
 {
 	int i;
-	UCHAR *np, chksum = 0;
+	u8 *np, chksum = 0;
 
-	np = (UCHAR *) nvramp;
+	np = (u8 *) nvramp;
 	for (i = 0; i < 64; i++, np++) {	/* <01> */
-		if (get_NVRAM(hcsp, (unsigned char) i, np) == 0)
+		if (orc_nv_read(host, (u8) i, np) == 0)
 			return -1;
-//      *np++ = get_NVRAM(hcsp, (unsigned char ) i);
 	}
 
-/*------ Is ckecksum ok ? ------*/
-	np = (UCHAR *) nvramp;
+	/*------ Is ckecksum ok ? ------*/
+	np = (u8 *) nvramp;
 	for (i = 0; i < 63; i++)
 		chksum += *np++;
 
-	if (nvramp->CheckSum != (UCHAR) chksum)
+	if (nvramp->CheckSum != (u8) chksum)
 		return -1;
 	return 1;
 }
 
-/************************************************************************
- Update SCSI H/A configuration parameters from serial EEPROM
-*************************************************************************/
-static void se2_update_all(ORC_HCS * hcsp)
+/**
+ *	se2_update_all		-	update the EEPROM
+ *	@host: Host whose EEPROM is being updated
+ *
+ *	Update changed bytes in the EEPROM image.
+ */
+
+static void se2_update_all(struct orc_host * host)
 {				/* setup default pattern  */
 	int i;
-	UCHAR *np, *np1, chksum = 0;
+	u8 *np, *np1, chksum = 0;
 
 	/* Calculate checksum first   */
-	np = (UCHAR *) dftNvRam;
+	np = (u8 *) default_nvram;
 	for (i = 0; i < 63; i++)
 		chksum += *np++;
 	*np = chksum;
 
-	np = (UCHAR *) dftNvRam;
-	np1 = (UCHAR *) nvramp;
+	np = (u8 *) default_nvram;
+	np1 = (u8 *) nvramp;
 	for (i = 0; i < 64; i++, np++, np1++) {
-		if (*np != *np1) {
-			set_NVRAM(hcsp, (unsigned char) i, *np);
-		}
+		if (*np != *np1)
+			orc_nv_write(host, (u8) i, *np);
 	}
-	return;
 }
 
-/*************************************************************************
- Function name  : read_eeprom
-**************************************************************************/
-static void read_eeprom(ORC_HCS * hcsp)
+/**
+ *	read_eeprom		-	load EEPROM
+ *	@host: Host EEPROM to read
+ *
+ *	Read the EEPROM for a given host. If it is invalid or fails
+ *	the restore the defaults and use them.
+ */
+
+static void read_eeprom(struct orc_host * host)
 {
-	if (se2_rd_all(hcsp) != 1) {
-		se2_update_all(hcsp);	/* setup default pattern        */
-		se2_rd_all(hcsp);	/* load again                   */
+	if (se2_rd_all(host) != 1) {
+		se2_update_all(host);	/* setup default pattern        */
+		se2_rd_all(host);	/* load again                   */
 	}
 }
 
 
-/***************************************************************************/
-static UCHAR load_FW(ORC_HCS * hcsp)
+/**
+ *	orc_load_firmware	-	initialise firmware
+ *	@host: Host to set up
+ *
+ *	Load the firmware from the EEPROM into controller SRAM. This
+ *	is basically a 4K block copy and then a 4K block read to check
+ *	correctness. The rest is convulted by the indirect interfaces
+ *	in the hardware
+ */
+
+static u8 orc_load_firmware(struct orc_host * host)
 {
-	U32 dData;
-	USHORT wBIOSAddress;
-	USHORT i;
-	UCHAR *pData, bData;
+	u32 data32;
+	u16 bios_addr;
+	u16 i;
+	u8 *data32_ptr, data;
 
 
-	bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG);
-	ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG);	/* Enable EEPROM programming */
-	ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00);
-	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00);
-	if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) {
-		ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
+	/* Set up the EEPROM for access */
+
+	data = inb(host->base + ORC_GCFG);
+	outb(data | EEPRG, host->base + ORC_GCFG);	/* Enable EEPROM programming */
+	outb(0x00, host->base + ORC_EBIOSADR2);
+	outw(0x0000, host->base + ORC_EBIOSADR0);
+	if (inb(host->base + ORC_EBIOSDATA) != 0x55) {
+		outb(data, host->base + ORC_GCFG);	/* Disable EEPROM programming */
 		return 0;
 	}
-	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01);
-	if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) {
-		ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
+	outw(0x0001, host->base + ORC_EBIOSADR0);
+	if (inb(host->base + ORC_EBIOSDATA) != 0xAA) {
+		outb(data, host->base + ORC_GCFG);	/* Disable EEPROM programming */
 		return 0;
 	}
-	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);	/* Enable SRAM programming */
-	pData = (UCHAR *) & dData;
-	dData = 0;		/* Initial FW address to 0 */
-	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10);
-	*pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);		/* Read from BIOS */
-	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11);
-	*(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
-	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12);
-	*(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
-	ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2));
-	ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData);	/* Write FW address */
 
-	wBIOSAddress = (USHORT) dData;	/* FW code locate at BIOS address + ? */
-	for (i = 0, pData = (UCHAR *) & dData;	/* Download the code    */
+	outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL);	/* Enable SRAM programming */
+	data32_ptr = (u8 *) & data32;
+	data32 = 0;		/* Initial FW address to 0 */
+	outw(0x0010, host->base + ORC_EBIOSADR0);
+	*data32_ptr = inb(host->base + ORC_EBIOSDATA);		/* Read from BIOS */
+	outw(0x0011, host->base + ORC_EBIOSADR0);
+	*(data32_ptr + 1) = inb(host->base + ORC_EBIOSDATA);	/* Read from BIOS */
+	outw(0x0012, host->base + ORC_EBIOSADR0);
+	*(data32_ptr + 2) = inb(host->base + ORC_EBIOSDATA);	/* Read from BIOS */
+	outw(*(data32_ptr + 2), host->base + ORC_EBIOSADR2);
+	outl(data32, host->base + ORC_FWBASEADR);		/* Write FW address */
+
+	/* Copy the code from the BIOS to the SRAM */
+
+	bios_addr = (u16) data32;	/* FW code locate at BIOS address + ? */
+	for (i = 0, data32_ptr = (u8 *) & data32;	/* Download the code    */
 	     i < 0x1000;	/* Firmware code size = 4K      */
-	     i++, wBIOSAddress++) {
-		ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
-		*pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
+	     i++, bios_addr++) {
+		outw(bios_addr, host->base + ORC_EBIOSADR0);
+		*data32_ptr++ = inb(host->base + ORC_EBIOSDATA);	/* Read from BIOS */
 		if ((i % 4) == 3) {
-			ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData);	/* Write every 4 bytes */
-			pData = (UCHAR *) & dData;
+			outl(data32, host->base + ORC_RISCRAM);	/* Write every 4 bytes */
+			data32_ptr = (u8 *) & data32;
 		}
 	}
 
-	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);	/* Reset program count 0 */
-	wBIOSAddress -= 0x1000;	/* Reset the BIOS adddress      */
-	for (i = 0, pData = (UCHAR *) & dData;	/* Check the code       */
+	/* Go back and check they match */
+
+	outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL);	/* Reset program count 0 */
+	bios_addr -= 0x1000;	/* Reset the BIOS adddress      */
+	for (i = 0, data32_ptr = (u8 *) & data32;	/* Check the code       */
 	     i < 0x1000;	/* Firmware code size = 4K      */
-	     i++, wBIOSAddress++) {
-		ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
-		*pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
+	     i++, bios_addr++) {
+		outw(bios_addr, host->base + ORC_EBIOSADR0);
+		*data32_ptr++ = inb(host->base + ORC_EBIOSDATA);	/* Read from BIOS */
 		if ((i % 4) == 3) {
-			if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) {
-				ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);	/* Reset program to 0 */
-				ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/*Disable EEPROM programming */
+			if (inl(host->base + ORC_RISCRAM) != data32) {
+				outb(PRGMRST, host->base + ORC_RISCCTL);	/* Reset program to 0 */
+				outb(data, host->base + ORC_GCFG);	/*Disable EEPROM programming */
 				return 0;
 			}
-			pData = (UCHAR *) & dData;
+			data32_ptr = (u8 *) & data32;
 		}
 	}
-	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);	/* Reset program to 0   */
-	ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
+
+	/* Success */
+	outb(PRGMRST, host->base + ORC_RISCCTL);	/* Reset program to 0   */
+	outb(data, host->base + ORC_GCFG);	/* Disable EEPROM programming */
 	return 1;
 }
 
 /***************************************************************************/
-static void setup_SCBs(ORC_HCS * hcsp)
+static void setup_SCBs(struct orc_host * host)
 {
-	ORC_SCB *pVirScb;
+	struct orc_scb *scb;
 	int i;
-	ESCB *pVirEscb;
-	dma_addr_t pPhysEscb;
+	struct orc_extended_scb *escb;
+	dma_addr_t escb_phys;
 
-	/* Setup SCB HCS_Base and SCB Size registers */
-	ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, ORC_MAXQUEUE);	/* Total number of SCBs */
-	/* SCB HCS_Base address 0      */
-	ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
-	/* SCB HCS_Base address 1      */
-	ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray);
+	/* Setup SCB base and SCB Size registers */
+	outb(ORC_MAXQUEUE, host->base + ORC_SCBSIZE);	/* Total number of SCBs */
+	/* SCB base address 0      */
+	outl(host->scb_phys, host->base + ORC_SCBBASE0);
+	/* SCB base address 1      */
+	outl(host->scb_phys, host->base + ORC_SCBBASE1);
 
 	/* setup scatter list address with one buffer */
-	pVirScb = hcsp->HCS_virScbArray;
-	pVirEscb = hcsp->HCS_virEscbArray;
+	scb = host->scb_virt;
+	escb = host->escb_virt;
 
 	for (i = 0; i < ORC_MAXQUEUE; i++) {
-		pPhysEscb = (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
-		pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
-		pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
-		pVirScb->SCB_EScb = pVirEscb;
-		pVirScb->SCB_ScbIdx = i;
-		pVirScb++;
-		pVirEscb++;
+		escb_phys = (host->escb_phys + (sizeof(struct orc_extended_scb) * i));
+		scb->sg_addr = (u32) escb_phys;
+		scb->sense_addr = (u32) escb_phys;
+		scb->escb = escb;
+		scb->scbidx = i;
+		scb++;
+		escb++;
 	}
-
-	return;
 }
 
-/***************************************************************************/
-static void initAFlag(ORC_HCS * hcsp)
+/**
+ *	init_alloc_map		-	initialise allocation map
+ *	@host: host map to configure
+ *
+ *	Initialise the allocation maps for this device. If the device
+ *	is not quiescent the caller must hold the allocation lock
+ */
+
+static void init_alloc_map(struct orc_host * host)
 {
-	UCHAR i, j;
+	u8 i, j;
 
 	for (i = 0; i < MAX_CHANNELS; i++) {
 		for (j = 0; j < 8; j++) {
-			hcsp->BitAllocFlag[i][j] = 0xffffffff;
+			host->allocation_map[i][j] = 0xffffffff;
 		}
 	}
 }
 
-/***************************************************************************/
-static int init_orchid(ORC_HCS * hcsp)
-{
-	UBYTE *readBytep;
-	USHORT revision;
-	UCHAR i;
+/**
+ *	init_orchid		-	initialise the host adapter
+ *	@host:host adapter to initialise
+ *
+ *	Initialise the controller and if neccessary load the firmware.
+ *
+ *	Returns -1 if the initialisation fails.
+ */
 
-	initAFlag(hcsp);
-	ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF);	/* Disable all interrupt        */
-	if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) {	/* Orchid is ready              */
-		revision = get_FW_version(hcsp);
+static int init_orchid(struct orc_host * host)
+{
+	u8 *ptr;
+	u16 revision;
+	u8 i;
+
+	init_alloc_map(host);
+	outb(0xFF, host->base + ORC_GIMSK);	/* Disable all interrupts */
+
+	if (inb(host->base + ORC_HSTUS) & RREADY) {	/* Orchid is ready */
+		revision = orc_read_fwrev(host);
 		if (revision == 0xFFFF) {
-			ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);	/* Reset Host Adapter   */
-			if (waitChipReady(hcsp) == 0)
-				return (-1);
-			load_FW(hcsp);	/* Download FW                  */
-			setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
-			ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0);	/* clear HOSTSTOP       */
-			if (waitFWReady(hcsp) == 0)
-				return (-1);
+			outb(DEVRST, host->base + ORC_HCTRL);	/* Reset Host Adapter   */
+			if (wait_chip_ready(host) == 0)
+				return -1;
+			orc_load_firmware(host);	/* Download FW                  */
+			setup_SCBs(host);	/* Setup SCB base and SCB Size registers */
+			outb(0x00, host->base + ORC_HCTRL);	/* clear HOSTSTOP       */
+			if (wait_firmware_ready(host) == 0)
+				return -1;
 			/* Wait for firmware ready     */
 		} else {
-			setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
+			setup_SCBs(host);	/* Setup SCB base and SCB Size registers */
 		}
 	} else {		/* Orchid is not Ready          */
-		ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);	/* Reset Host Adapter   */
-		if (waitChipReady(hcsp) == 0)
-			return (-1);
-		load_FW(hcsp);	/* Download FW                  */
-		setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
-		ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);	/* Do Hardware Reset &  */
+		outb(DEVRST, host->base + ORC_HCTRL);	/* Reset Host Adapter   */
+		if (wait_chip_ready(host) == 0)
+			return -1;
+		orc_load_firmware(host);	/* Download FW                  */
+		setup_SCBs(host);	/* Setup SCB base and SCB Size registers */
+		outb(HDO, host->base + ORC_HCTRL);	/* Do Hardware Reset &  */
 
 		/*     clear HOSTSTOP  */
-		if (waitFWReady(hcsp) == 0)		/* Wait for firmware ready      */
-			return (-1);
+		if (wait_firmware_ready(host) == 0)		/* Wait for firmware ready      */
+			return -1;
 	}
 
-/*------------- get serial EEProm settting -------*/
+	/* Load an EEProm copy into RAM */
+	/* Assumes single threaded at this point */
+	read_eeprom(host);
 
-	read_eeprom(hcsp);
+	if (nvramp->revision != 1)
+		return -1;
 
-	if (nvramp->Revision != 1)
-		return (-1);
-
-	hcsp->HCS_SCSI_ID = nvramp->SCSI0Id;
-	hcsp->HCS_BIOS = nvramp->BIOSConfig1;
-	hcsp->HCS_MaxTar = MAX_TARGETS;
-	readBytep = (UCHAR *) & (nvramp->Target00Config);
-	for (i = 0; i < 16; readBytep++, i++) {
-		hcsp->TargetFlag[i] = *readBytep;
-		hcsp->MaximumTags[i] = ORC_MAXTAGS;
-	}			/* for                          */
-
-	if (nvramp->SCSI0Config & NCC_BUSRESET) {	/* Reset SCSI bus               */
-		hcsp->HCS_Flags |= HCF_SCSI_RESET;
+	host->scsi_id = nvramp->scsi_id;
+	host->BIOScfg = nvramp->BIOSConfig1;
+	host->max_targets = MAX_TARGETS;
+	ptr = (u8 *) & (nvramp->Target00Config);
+	for (i = 0; i < 16; ptr++, i++) {
+		host->target_flag[i] = *ptr;
+		host->max_tags[i] = ORC_MAXTAGS;
 	}
-	ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB);	/* enable RP FIFO interrupt     */
-	return (0);
+
+	if (nvramp->SCSI0Config & NCC_BUSRESET)
+		host->flags |= HCF_SCSI_RESET;
+	outb(0xFB, host->base + ORC_GIMSK);	/* enable RP FIFO interrupt     */
+	return 0;
 }
 
-/*****************************************************************************
- Function name  : orc_reset_scsi_bus
- Description    : Reset registers, reset a hanging bus and
-                  kill active and disconnected commands for target w/o soft reset
- Input          : pHCB  -       Pointer to host adapter structure
- Output         : None.
- Return         : pSRB  -       Pointer to SCSI request block.
-*****************************************************************************/
-static int orc_reset_scsi_bus(ORC_HCS * pHCB)
+/**
+ *	orc_reset_scsi_bus		-	perform bus reset
+ *	@host: host being reset
+ *
+ *	Perform a full bus reset on the adapter.
+ */
+
+static int orc_reset_scsi_bus(struct orc_host * host)
 {				/* I need Host Control Block Information */
-	ULONG flags;
+	unsigned long flags;
 
-	spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
+	spin_lock_irqsave(&host->allocation_lock, flags);
 
-	initAFlag(pHCB);
+	init_alloc_map(host);
 	/* reset scsi bus */
-	ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
-	if (waitSCSIRSTdone(pHCB) == 0) {
-		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+	outb(SCSIRST, host->base + ORC_HCTRL);
+	/* FIXME: We can spend up to a second with the lock held and
+	   interrupts off here */
+	if (wait_scsi_reset_done(host) == 0) {
+		spin_unlock_irqrestore(&host->allocation_lock, flags);
 		return FAILED;
 	} else {
-		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+		spin_unlock_irqrestore(&host->allocation_lock, flags);
 		return SUCCESS;
 	}
 }
 
-/*****************************************************************************
- Function name  : orc_device_reset
- Description    : Reset registers, reset a hanging bus and
-                  kill active and disconnected commands for target w/o soft reset
- Input          : pHCB  -       Pointer to host adapter structure
- Output         : None.
- Return         : pSRB  -       Pointer to SCSI request block.
-*****************************************************************************/
-static int orc_device_reset(ORC_HCS * pHCB, struct scsi_cmnd *SCpnt, unsigned int target)
-{				/* I need Host Control Block Information */
-	ORC_SCB *pScb;
-	ESCB *pVirEscb;
-	ORC_SCB *pVirScb;
-	UCHAR i;
-	ULONG flags;
+/**
+ *	orc_device_reset	-	device reset handler
+ *	@host: host to reset
+ *	@cmd: command causing the reset
+ *	@target; target device
+ *
+ *	Reset registers, reset a hanging bus and kill active and disconnected
+ *	commands for target w/o soft reset
+ */
 
-	spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
-	pScb = (ORC_SCB *) NULL;
-	pVirEscb = (ESCB *) NULL;
+static int orc_device_reset(struct orc_host * host, struct scsi_cmnd *cmd, unsigned int target)
+{				/* I need Host Control Block Information */
+	struct orc_scb *scb;
+	struct orc_extended_scb *escb;
+	struct orc_scb *host_scb;
+	u8 i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&(host->allocation_lock), flags);
+	scb = (struct orc_scb *) NULL;
+	escb = (struct orc_extended_scb *) NULL;
 
 	/* setup scatter list address with one buffer */
-	pVirScb = pHCB->HCS_virScbArray;
+	host_scb = host->scb_virt;
 
-	initAFlag(pHCB);
-	/* device reset */
+	/* FIXME: is this safe if we then fail to issue the reset or race
+	   a completion ? */
+	init_alloc_map(host);
+
+	/* Find the scb corresponding to the command */
 	for (i = 0; i < ORC_MAXQUEUE; i++) {
-		pVirEscb = pVirScb->SCB_EScb;
-		if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt))
+		escb = host_scb->escb;
+		if (host_scb->status && escb->srb == cmd)
 			break;
-		pVirScb++;
+		host_scb++;
 	}
 
 	if (i == ORC_MAXQUEUE) {
-		printk("Unable to Reset - No SCB Found\n");
-		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+		printk(KERN_ERR "Unable to Reset - No SCB Found\n");
+		spin_unlock_irqrestore(&(host->allocation_lock), flags);
 		return FAILED;
 	}
-	if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
-		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-		return FAILED;
-	}
-	pScb->SCB_Opcode = ORC_BUSDEVRST;
-	pScb->SCB_Target = target;
-	pScb->SCB_HaStat = 0;
-	pScb->SCB_TaStat = 0;
-	pScb->SCB_Status = 0x0;
-	pScb->SCB_Link = 0xFF;
-	pScb->SCB_Reserved0 = 0;
-	pScb->SCB_Reserved1 = 0;
-	pScb->SCB_XferLen = 0;
-	pScb->SCB_SGLen = 0;
 
-	pVirEscb->SCB_Srb = NULL;
-	pVirEscb->SCB_Srb = SCpnt;
-	orc_exec_scb(pHCB, pScb);	/* Start execute SCB            */
-	spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+	/* Allocate a new SCB for the reset command to the firmware */
+	if ((scb = __orc_alloc_scb(host)) == NULL) {
+		/* Can't happen.. */
+		spin_unlock_irqrestore(&(host->allocation_lock), flags);
+		return FAILED;
+	}
+
+	/* Reset device is handled by the firmare, we fill in an SCB and
+	   fire it at the controller, it does the rest */
+	scb->opcode = ORC_BUSDEVRST;
+	scb->target = target;
+	scb->hastat = 0;
+	scb->tastat = 0;
+	scb->status = 0x0;
+	scb->link = 0xFF;
+	scb->reserved0 = 0;
+	scb->reserved1 = 0;
+	scb->xferlen = 0;
+	scb->sg_len = 0;
+
+	escb->srb = NULL;
+	escb->srb = cmd;
+	orc_exec_scb(host, scb);	/* Start execute SCB            */
+	spin_unlock_irqrestore(&host->allocation_lock, flags);
 	return SUCCESS;
 }
 
+/**
+ *	__orc_alloc_scb		-		allocate an SCB
+ *	@host: host to allocate from
+ *
+ *	Allocate an SCB and return a pointer to the SCB object. NULL
+ *	is returned if no SCB is free. The caller must already hold
+ *	the allocator lock at this point.
+ */
 
-/***************************************************************************/
-static ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
+
+static struct orc_scb *__orc_alloc_scb(struct orc_host * host)
 {
-	ORC_SCB *pTmpScb;
-	UCHAR Ch;
-	ULONG idx;
-	UCHAR index;
-	UCHAR i;
+	u8 channel;
+	unsigned long idx;
+	u8 index;
+	u8 i;
 
-	Ch = hcsp->HCS_Index;
+	channel = host->index;
 	for (i = 0; i < 8; i++) {
 		for (index = 0; index < 32; index++) {
-			if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) {
-				hcsp->BitAllocFlag[Ch][i] &= ~(1 << index);
+			if ((host->allocation_map[channel][i] >> index) & 0x01) {
+				host->allocation_map[channel][i] &= ~(1 << index);
 				break;
 			}
 		}
 		idx = index + 32 * i;
-		pTmpScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
-		return (pTmpScb);
+		/* Translate the index to a structure instance */
+		return (struct orc_scb *) ((unsigned long) host->scb_virt + (idx * sizeof(struct orc_scb)));
 	}
-	return (NULL);
+	return NULL;
 }
 
-static ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
-{
-	ORC_SCB *pTmpScb;
-	ULONG flags;
+/**
+ *	orc_alloc_scb		-		allocate an SCB
+ *	@host: host to allocate from
+ *
+ *	Allocate an SCB and return a pointer to the SCB object. NULL
+ *	is returned if no SCB is free.
+ */
 
-	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
-	pTmpScb = __orc_alloc_scb(hcsp);
-	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-	return (pTmpScb);
+static struct orc_scb *orc_alloc_scb(struct orc_host * host)
+{
+	struct orc_scb *scb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->allocation_lock, flags);
+	scb = __orc_alloc_scb(host);
+	spin_unlock_irqrestore(&host->allocation_lock, flags);
+	return scb;
 }
 
+/**
+ *	orc_release_scb			-	release an SCB
+ *	@host: host owning the SCB
+ *	@scb: SCB that is now free
+ *
+ *	Called to return a completed SCB to the allocation pool. Before
+ *	calling the SCB must be out of use on both the host and the HA.
+ */
 
-/***************************************************************************/
-static void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
+static void orc_release_scb(struct orc_host *host, struct orc_scb *scb)
 {
-	ULONG flags;
-	UCHAR Index;
-	UCHAR i;
-	UCHAR Ch;
+	unsigned long flags;
+	u8 index, i, channel;
 
-	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
-	Ch = hcsp->HCS_Index;
-	Index = scbp->SCB_ScbIdx;
-	i = Index / 32;
-	Index %= 32;
-	hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
-	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+	spin_lock_irqsave(&(host->allocation_lock), flags);
+	channel = host->index;	/* Channel */
+	index = scb->scbidx;
+	i = index / 32;
+	index %= 32;
+	host->allocation_map[channel][i] |= (1 << index);
+	spin_unlock_irqrestore(&(host->allocation_lock), flags);
 }
 
-/*****************************************************************************
- Function name  : abort_SCB
- Description    : Abort a queued command.
-	                 (commands that are on the bus can't be aborted easily)
- Input          : pHCB  -       Pointer to host adapter structure
- Output         : None.
- Return         : pSRB  -       Pointer to SCSI request block.
-*****************************************************************************/
-static int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
+/**
+ *	orchid_abort_scb	-	abort a command
+ *
+ *	Abort a queued command that has been passed to the firmware layer
+ *	if possible. This is all handled by the firmware. We aks the firmware
+ *	and it either aborts the command or fails
+ */
+
+static int orchid_abort_scb(struct orc_host * host, struct orc_scb * scb)
 {
-	unsigned char bData, bStatus;
+	unsigned char data, status;
 
-	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB);	/* Write command */
-	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
-	if (waitHDOoff(hcsp) == 0)	/* Wait HDO off   */
+	outb(ORC_CMD_ABORT_SCB, host->base + ORC_HDATA);	/* Write command */
+	outb(HDO, host->base + ORC_HCTRL);
+	if (wait_HDO_off(host) == 0)	/* Wait HDO off   */
 		return 0;
 
-	ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx);	/* Write address */
-	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
-	if (waitHDOoff(hcsp) == 0)	/* Wait HDO off   */
+	outb(scb->scbidx, host->base + ORC_HDATA);	/* Write address */
+	outb(HDO, host->base + ORC_HCTRL);
+	if (wait_HDO_off(host) == 0)	/* Wait HDO off   */
 		return 0;
 
-	if (waitHDIset(hcsp, &bData) == 0)	/* Wait HDI set   */
+	if (wait_hdi_set(host, &data) == 0)	/* Wait HDI set   */
 		return 0;
-	bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
-	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI    */
+	status = inb(host->base + ORC_HDATA);
+	outb(data, host->base + ORC_HSTUS);	/* Clear HDI    */
 
-	if (bStatus == 1)	/* 0 - Successfully               */
+	if (status == 1)	/* 0 - Successfully               */
 		return 0;	/* 1 - Fail                     */
 	return 1;
 }
 
-/*****************************************************************************
- Function name  : inia100_abort
- Description    : Abort a queued command.
-	                 (commands that are on the bus can't be aborted easily)
- Input          : pHCB  -       Pointer to host adapter structure
- Output         : None.
- Return         : pSRB  -       Pointer to SCSI request block.
-*****************************************************************************/
-static int orc_abort_srb(ORC_HCS * hcsp, struct scsi_cmnd *SCpnt)
+static int inia100_abort_cmd(struct orc_host * host, struct scsi_cmnd *cmd)
 {
-	ESCB *pVirEscb;
-	ORC_SCB *pVirScb;
-	UCHAR i;
-	ULONG flags;
+	struct orc_extended_scb *escb;
+	struct orc_scb *scb;
+	u8 i;
+	unsigned long flags;
 
-	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
+	spin_lock_irqsave(&(host->allocation_lock), flags);
 
-	pVirScb = hcsp->HCS_virScbArray;
+	scb = host->scb_virt;
 
-	for (i = 0; i < ORC_MAXQUEUE; i++, pVirScb++) {
-		pVirEscb = pVirScb->SCB_EScb;
-		if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) {
-			if (pVirScb->SCB_TagMsg == 0) {
-				spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-				return FAILED;
+	/* Walk the queue until we find the SCB that belongs to the command
+	   block. This isn't a performance critical path so a walk in the park
+	   here does no harm */
+
+	for (i = 0; i < ORC_MAXQUEUE; i++, scb++) {
+		escb = scb->escb;
+		if (scb->status && escb->srb == cmd) {
+			if (scb->tag_msg == 0) {
+				goto out;
 			} else {
-				if (abort_SCB(hcsp, pVirScb)) {
-					pVirEscb->SCB_Srb = NULL;
-					spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+				/* Issue an ABORT to the firmware */
+				if (orchid_abort_scb(host, scb)) {
+					escb->srb = NULL;
+					spin_unlock_irqrestore(&host->allocation_lock, flags);
 					return SUCCESS;
-				} else {
-					spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-					return FAILED;
-				}
+				} else
+					goto out;
 			}
 		}
 	}
-	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+out:
+	spin_unlock_irqrestore(&host->allocation_lock, flags);
 	return FAILED;
 }
 
-/***********************************************************************
- Routine Description:
-	  This is the interrupt service routine for the Orchid SCSI adapter.
-	  It reads the interrupt register to determine if the adapter is indeed
-	  the source of the interrupt and clears the interrupt at the device.
- Arguments:
-	  HwDeviceExtension - HBA miniport driver's adapter data storage
- Return Value:
-***********************************************************************/
-static void orc_interrupt(
-			  ORC_HCS * hcsp
-)
+/**
+ *	orc_interrupt		-	IRQ processing
+ *	@host: Host causing the interrupt
+ *
+ *	This function is called from the IRQ handler and protected
+ *	by the host lock. While the controller reports that there are
+ *	scb's for processing we pull them off the controller, turn the
+ *	index into a host address pointer to the scb and call the scb
+ *	handler.
+ *
+ *	Returns IRQ_HANDLED if any SCBs were processed, IRQ_NONE otherwise
+ */
+
+static irqreturn_t orc_interrupt(struct orc_host * host)
 {
-	BYTE bScbIdx;
-	ORC_SCB *pScb;
+	u8 scb_index;
+	struct orc_scb *scb;
 
-	if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) {
-		return;		// 0;
+	/* Check if we have an SCB queued for servicing */
+	if (inb(host->base + ORC_RQUEUECNT) == 0)
+		return IRQ_NONE;
 
-	}
 	do {
-		bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE);
+		/* Get the SCB index of the SCB to service */
+		scb_index = inb(host->base + ORC_RQUEUE);
 
-		pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx));
-		pScb->SCB_Status = 0x0;
-
-		inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb);
-	} while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT));
-	return;			//1;
-
+		/* Translate it back to a host pointer */
+		scb = (struct orc_scb *) ((unsigned long) host->scb_virt + (unsigned long) (sizeof(struct orc_scb) * scb_index));
+		scb->status = 0x0;
+		/* Process the SCB */
+		inia100_scb_handler(host, scb);
+	} while (inb(host->base + ORC_RQUEUECNT));
+	return IRQ_HANDLED;
 }				/* End of I1060Interrupt() */
 
-/*****************************************************************************
- Function name  : inia100BuildSCB
- Description    : 
- Input          : pHCB  -       Pointer to host adapter structure
- Output         : None.
- Return         : pSRB  -       Pointer to SCSI request block.
-*****************************************************************************/
-static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, struct scsi_cmnd * SCpnt)
+/**
+ *	inia100_build_scb	-	build SCB
+ *	@host: host owing the control block
+ *	@scb: control block to use
+ *	@cmd: Mid layer command
+ *
+ *	Build a host adapter control block from the SCSI mid layer command
+ */
+
+static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struct scsi_cmnd * cmd)
 {				/* Create corresponding SCB     */
-	struct scatterlist *pSrbSG;
-	ORC_SG *pSG;		/* Pointer to SG list           */
+	struct scatterlist *sg;
+	struct orc_sgent *sgent;		/* Pointer to SG list           */
 	int i, count_sg;
-	ESCB *pEScb;
+	struct orc_extended_scb *escb;
 
-	pEScb = pSCB->SCB_EScb;
-	pEScb->SCB_Srb = SCpnt;
-	pSG = NULL;
+	/* Links between the escb, scb and Linux scsi midlayer cmd */
+	escb = scb->escb;
+	escb->srb = cmd;
+	sgent = NULL;
 
-	pSCB->SCB_Opcode = ORC_EXECSCSI;
-	pSCB->SCB_Flags = SCF_NO_DCHK;	/* Clear done bit               */
-	pSCB->SCB_Target = SCpnt->device->id;
-	pSCB->SCB_Lun = SCpnt->device->lun;
-	pSCB->SCB_Reserved0 = 0;
-	pSCB->SCB_Reserved1 = 0;
-	pSCB->SCB_SGLen = 0;
+	/* Set up the SCB to do a SCSI command block */
+	scb->opcode = ORC_EXECSCSI;
+	scb->flags = SCF_NO_DCHK;	/* Clear done bit               */
+	scb->target = cmd->device->id;
+	scb->lun = cmd->device->lun;
+	scb->reserved0 = 0;
+	scb->reserved1 = 0;
+	scb->sg_len = 0;
 
-	if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) {
-		pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
-		if (SCpnt->use_sg) {
-			pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
-			count_sg = pci_map_sg(pHCB->pdev, pSrbSG, SCpnt->use_sg,
-					SCpnt->sc_data_direction);
-			pSCB->SCB_SGLen = (U32) (count_sg * 8);
-			for (i = 0; i < count_sg; i++, pSG++, pSrbSG++) {
-				pSG->SG_Ptr = (U32) sg_dma_address(pSrbSG);
-				pSG->SG_Len = (U32) sg_dma_len(pSrbSG);
-			}
-		} else if (SCpnt->request_bufflen != 0) {/* Non SG */
-			pSCB->SCB_SGLen = 0x8;
-			SCpnt->SCp.dma_handle = pci_map_single(pHCB->pdev,
-					SCpnt->request_buffer,
-					SCpnt->request_bufflen,
-					SCpnt->sc_data_direction);
-			pSG->SG_Ptr = (U32) SCpnt->SCp.dma_handle;
-			pSG->SG_Len = (U32) SCpnt->request_bufflen;
-		} else {
-			pSCB->SCB_SGLen = 0;
-			pSG->SG_Ptr = 0;
-			pSG->SG_Len = 0;
+	scb->xferlen = (u32) scsi_bufflen(cmd);
+	sgent = (struct orc_sgent *) & escb->sglist[0];
+
+	count_sg = scsi_dma_map(cmd);
+	BUG_ON(count_sg < 0);
+
+	/* Build the scatter gather lists */
+	if (count_sg) {
+		scb->sg_len = (u32) (count_sg * 8);
+		scsi_for_each_sg(cmd, sg, count_sg, i) {
+			sgent->base = (u32) sg_dma_address(sg);
+			sgent->length = (u32) sg_dma_len(sg);
+			sgent++;
 		}
-	}
-	pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr;
-	pSCB->SCB_HaStat = 0;
-	pSCB->SCB_TaStat = 0;
-	pSCB->SCB_Link = 0xFF;
-	pSCB->SCB_SenseLen = SENSE_SIZE;
-	pSCB->SCB_CDBLen = SCpnt->cmd_len;
-	if (pSCB->SCB_CDBLen >= IMAX_CDB) {
-		printk("max cdb length= %x\b", SCpnt->cmd_len);
-		pSCB->SCB_CDBLen = IMAX_CDB;
-	}
-	pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW;
-	if (SCpnt->device->tagged_supported) {	/* Tag Support                  */
-		pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */
 	} else {
-		pSCB->SCB_TagMsg = 0;	/* No tag support               */
+		scb->sg_len = 0;
+		sgent->base = 0;
+		sgent->length = 0;
 	}
-	memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, pSCB->SCB_CDBLen);
-	return;
+	scb->sg_addr = (u32) scb->sense_addr;
+	scb->hastat = 0;
+	scb->tastat = 0;
+	scb->link = 0xFF;
+	scb->sense_len = SENSE_SIZE;
+	scb->cdb_len = cmd->cmd_len;
+	if (scb->cdb_len >= IMAX_CDB) {
+		printk("max cdb length= %x\b", cmd->cmd_len);
+		scb->cdb_len = IMAX_CDB;
+	}
+	scb->ident = cmd->device->lun | DISC_ALLOW;
+	if (cmd->device->tagged_supported) {	/* Tag Support                  */
+		scb->tag_msg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */
+	} else {
+		scb->tag_msg = 0;	/* No tag support               */
+	}
+	memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
 }
 
-/*****************************************************************************
- Function name  : inia100_queue
- Description    : Queue a command and setup interrupts for a free bus.
- Input          : pHCB  -       Pointer to host adapter structure
- Output         : None.
- Return         : pSRB  -       Pointer to SCSI request block.
-*****************************************************************************/
-static int inia100_queue(struct scsi_cmnd * SCpnt, void (*done) (struct scsi_cmnd *))
-{
-	register ORC_SCB *pSCB;
-	ORC_HCS *pHCB;		/* Point to Host adapter control block */
+/**
+ *	inia100_queue		-	queue command with host
+ *	@cmd: Command block
+ *	@done: Completion function
+ *
+ *	Called by the mid layer to queue a command. Process the command
+ *	block, build the host specific scb structures and if there is room
+ *	queue the command down to the controller
+ */
 
-	pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
-	SCpnt->scsi_done = done;
+static int inia100_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
+{
+	struct orc_scb *scb;
+	struct orc_host *host;		/* Point to Host adapter control block */
+
+	host = (struct orc_host *) cmd->device->host->hostdata;
+	cmd->scsi_done = done;
 	/* Get free SCSI control block  */
-	if ((pSCB = orc_alloc_scb(pHCB)) == NULL)
+	if ((scb = orc_alloc_scb(host)) == NULL)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
-	inia100BuildSCB(pHCB, pSCB, SCpnt);
-	orc_exec_scb(pHCB, pSCB);	/* Start execute SCB            */
-
-	return (0);
+	inia100_build_scb(host, scb, cmd);
+	orc_exec_scb(host, scb);	/* Start execute SCB            */
+	return 0;
 }
 
 /*****************************************************************************
  Function name  : inia100_abort
  Description    : Abort a queued command.
 	                 (commands that are on the bus can't be aborted easily)
- Input          : pHCB  -       Pointer to host adapter structure
+ Input          : host  -       Pointer to host adapter structure
  Output         : None.
  Return         : pSRB  -       Pointer to SCSI request block.
 *****************************************************************************/
-static int inia100_abort(struct scsi_cmnd * SCpnt)
+static int inia100_abort(struct scsi_cmnd * cmd)
 {
-	ORC_HCS *hcsp;
+	struct orc_host *host;
 
-	hcsp = (ORC_HCS *) SCpnt->device->host->hostdata;
-	return orc_abort_srb(hcsp, SCpnt);
+	host = (struct orc_host *) cmd->device->host->hostdata;
+	return inia100_abort_cmd(host, cmd);
 }
 
 /*****************************************************************************
  Function name  : inia100_reset
  Description    : Reset registers, reset a hanging bus and
                   kill active and disconnected commands for target w/o soft reset
- Input          : pHCB  -       Pointer to host adapter structure
+ Input          : host  -       Pointer to host adapter structure
  Output         : None.
  Return         : pSRB  -       Pointer to SCSI request block.
 *****************************************************************************/
-static int inia100_bus_reset(struct scsi_cmnd * SCpnt)
+static int inia100_bus_reset(struct scsi_cmnd * cmd)
 {				/* I need Host Control Block Information */
-	ORC_HCS *pHCB;
-	pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
-	return orc_reset_scsi_bus(pHCB);
+	struct orc_host *host;
+	host = (struct orc_host *) cmd->device->host->hostdata;
+	return orc_reset_scsi_bus(host);
 }
 
 /*****************************************************************************
  Function name  : inia100_device_reset
  Description    : Reset the device
- Input          : pHCB  -       Pointer to host adapter structure
+ Input          : host  -       Pointer to host adapter structure
  Output         : None.
  Return         : pSRB  -       Pointer to SCSI request block.
 *****************************************************************************/
-static int inia100_device_reset(struct scsi_cmnd * SCpnt)
+static int inia100_device_reset(struct scsi_cmnd * cmd)
 {				/* I need Host Control Block Information */
-	ORC_HCS *pHCB;
-	pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
-	return orc_device_reset(pHCB, SCpnt, scmd_id(SCpnt));
+	struct orc_host *host;
+	host = (struct orc_host *) cmd->device->host->hostdata;
+	return orc_device_reset(host, cmd, scmd_id(cmd));
 
 }
 
-/*****************************************************************************
- Function name  : inia100SCBPost
- Description    : This is callback routine be called when orc finish one
-			SCSI command.
- Input          : pHCB  -       Pointer to host adapter control block.
-		  pSCB  -       Pointer to SCSI control block.
- Output         : None.
- Return         : None.
-*****************************************************************************/
-static void inia100SCBPost(BYTE * pHcb, BYTE * pScb)
-{
-	struct scsi_cmnd *pSRB;	/* Pointer to SCSI request block */
-	ORC_HCS *pHCB;
-	ORC_SCB *pSCB;
-	ESCB *pEScb;
+/**
+ *	inia100_scb_handler	-	interrupt callback
+ *	@host: Host causing the interrupt
+ *	@scb: SCB the controller returned as needing processing
+ *
+ *	Perform completion processing on a control block. Do the conversions
+ *	from host to SCSI midlayer error coding, save any sense data and
+ *	the complete with the midlayer and recycle the scb.
+ */
 
-	pHCB = (ORC_HCS *) pHcb;
-	pSCB = (ORC_SCB *) pScb;
-	pEScb = pSCB->SCB_EScb;
-	if ((pSRB = (struct scsi_cmnd *) pEScb->SCB_Srb) == 0) {
-		printk("inia100SCBPost: SRB pointer is empty\n");
-		orc_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
+static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb)
+{
+	struct scsi_cmnd *cmd;	/* Pointer to SCSI request block */
+	struct orc_extended_scb *escb;
+
+	escb = scb->escb;
+	if ((cmd = (struct scsi_cmnd *) escb->srb) == NULL) {
+		printk(KERN_ERR "inia100_scb_handler: SRB pointer is empty\n");
+		orc_release_scb(host, scb);	/* Release SCB for current channel */
 		return;
 	}
-	pEScb->SCB_Srb = NULL;
+	escb->srb = NULL;
 
-	switch (pSCB->SCB_HaStat) {
+	switch (scb->hastat) {
 	case 0x0:
 	case 0xa:		/* Linked command complete without error and linked normally */
 	case 0xb:		/* Linked command complete without error interrupt generated */
-		pSCB->SCB_HaStat = 0;
+		scb->hastat = 0;
 		break;
 
 	case 0x11:		/* Selection time out-The initiator selection or target
 				   reselection was not complete within the SCSI Time out period */
-		pSCB->SCB_HaStat = DID_TIME_OUT;
+		scb->hastat = DID_TIME_OUT;
 		break;
 
 	case 0x14:		/* Target bus phase sequence failure-An invalid bus phase or bus
 				   phase sequence was requested by the target. The host adapter
 				   will generate a SCSI Reset Condition, notifying the host with
 				   a SCRD interrupt */
-		pSCB->SCB_HaStat = DID_RESET;
+		scb->hastat = DID_RESET;
 		break;
 
 	case 0x1a:		/* SCB Aborted. 07/21/98 */
-		pSCB->SCB_HaStat = DID_ABORT;
+		scb->hastat = DID_ABORT;
 		break;
 
 	case 0x12:		/* Data overrun/underrun-The target attempted to transfer more data
@@ -984,46 +1022,41 @@
 	case 0x16:		/* Invalid CCB Operation Code-The first byte of the CCB was invalid. */
 
 	default:
-		printk("inia100: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
-		pSCB->SCB_HaStat = DID_ERROR;	/* Couldn't find any better */
+		printk(KERN_DEBUG "inia100: %x %x\n", scb->hastat, scb->tastat);
+		scb->hastat = DID_ERROR;	/* Couldn't find any better */
 		break;
 	}
 
-	if (pSCB->SCB_TaStat == 2) {	/* Check condition              */
-		memcpy((unsigned char *) &pSRB->sense_buffer[0],
-		   (unsigned char *) &pEScb->ESCB_SGList[0], SENSE_SIZE);
+	if (scb->tastat == 2) {	/* Check condition              */
+		memcpy((unsigned char *) &cmd->sense_buffer[0],
+		   (unsigned char *) &escb->sglist[0], SENSE_SIZE);
 	}
-	pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
-
-	if (pSRB->use_sg) {
-		pci_unmap_sg(pHCB->pdev,
-			     (struct scatterlist *)pSRB->request_buffer,
-			     pSRB->use_sg, pSRB->sc_data_direction);
-	} else if (pSRB->request_bufflen != 0) {
-		pci_unmap_single(pHCB->pdev, pSRB->SCp.dma_handle,
-				 pSRB->request_bufflen,
-				 pSRB->sc_data_direction);
-	}
-
-	pSRB->scsi_done(pSRB);	/* Notify system DONE           */
-
-	orc_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
+	cmd->result = scb->tastat | (scb->hastat << 16);
+	scsi_dma_unmap(cmd);
+	cmd->scsi_done(cmd);	/* Notify system DONE           */
+	orc_release_scb(host, scb);	/* Release SCB for current channel */
 }
 
-/*
- * Interrupt handler (main routine of the driver)
+/**
+ *	inia100_intr		-	interrupt handler
+ *	@irqno: Interrupt value
+ *	@devid: Host adapter
+ *
+ *	Entry point for IRQ handling. All the real work is performed
+ *	by orc_interrupt.
  */
 static irqreturn_t inia100_intr(int irqno, void *devid)
 {
-	struct Scsi_Host *host = (struct Scsi_Host *)devid;
-	ORC_HCS *pHcb = (ORC_HCS *)host->hostdata;
+	struct Scsi_Host *shost = (struct Scsi_Host *)devid;
+	struct orc_host *host = (struct orc_host *)shost->hostdata;
 	unsigned long flags;
+	irqreturn_t res;
 
-	spin_lock_irqsave(host->host_lock, flags);
-	orc_interrupt(pHcb);
-	spin_unlock_irqrestore(host->host_lock, flags);
+	spin_lock_irqsave(shost->host_lock, flags);
+	res = orc_interrupt(host);
+	spin_unlock_irqrestore(shost->host_lock, flags);
 
-	return IRQ_HANDLED;
+	return res;
 }
 
 static struct scsi_host_template inia100_template = {
@@ -1044,12 +1077,12 @@
 		const struct pci_device_id *id)
 {
 	struct Scsi_Host *shost;
-	ORC_HCS *pHCB;
+	struct orc_host *host;
 	unsigned long port, bios;
 	int error = -ENODEV;
 	u32 sz;
-	unsigned long dBiosAdr;
-	char *pbBiosAdr;
+	unsigned long biosaddr;
+	char *bios_phys;
 
 	if (pci_enable_device(pdev))
 		goto out;
@@ -1068,55 +1101,55 @@
 	}
 
 	/* <02> read from base address + 0x50 offset to get the bios value. */
-	bios = ORC_RDWORD(port, 0x50);
+	bios = inw(port + 0x50);
 
 
-	shost = scsi_host_alloc(&inia100_template, sizeof(ORC_HCS));
+	shost = scsi_host_alloc(&inia100_template, sizeof(struct orc_host));
 	if (!shost)
 		goto out_release_region;
 
-	pHCB = (ORC_HCS *)shost->hostdata;
-	pHCB->pdev = pdev;
-	pHCB->HCS_Base = port;
-	pHCB->HCS_BIOS = bios;
-	spin_lock_init(&pHCB->BitAllocFlagLock);
+	host = (struct orc_host *)shost->hostdata;
+	host->pdev = pdev;
+	host->base = port;
+	host->BIOScfg = bios;
+	spin_lock_init(&host->allocation_lock);
 
 	/* Get total memory needed for SCB */
-	sz = ORC_MAXQUEUE * sizeof(ORC_SCB);
-	pHCB->HCS_virScbArray = pci_alloc_consistent(pdev, sz,
-			&pHCB->HCS_physScbArray);
-	if (!pHCB->HCS_virScbArray) {
+	sz = ORC_MAXQUEUE * sizeof(struct orc_scb);
+	host->scb_virt = pci_alloc_consistent(pdev, sz,
+			&host->scb_phys);
+	if (!host->scb_virt) {
 		printk("inia100: SCB memory allocation error\n");
 		goto out_host_put;
 	}
-	memset(pHCB->HCS_virScbArray, 0, sz);
+	memset(host->scb_virt, 0, sz);
 
 	/* Get total memory needed for ESCB */
-	sz = ORC_MAXQUEUE * sizeof(ESCB);
-	pHCB->HCS_virEscbArray = pci_alloc_consistent(pdev, sz,
-			&pHCB->HCS_physEscbArray);
-	if (!pHCB->HCS_virEscbArray) {
+	sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb);
+	host->escb_virt = pci_alloc_consistent(pdev, sz,
+			&host->escb_phys);
+	if (!host->escb_virt) {
 		printk("inia100: ESCB memory allocation error\n");
 		goto out_free_scb_array;
 	}
-	memset(pHCB->HCS_virEscbArray, 0, sz);
+	memset(host->escb_virt, 0, sz);
 
-	dBiosAdr = pHCB->HCS_BIOS;
-	dBiosAdr = (dBiosAdr << 4);
-	pbBiosAdr = phys_to_virt(dBiosAdr);
-	if (init_orchid(pHCB)) {	/* Initialize orchid chip */
+	biosaddr = host->BIOScfg;
+	biosaddr = (biosaddr << 4);
+	bios_phys = phys_to_virt(biosaddr);
+	if (init_orchid(host)) {	/* Initialize orchid chip */
 		printk("inia100: initial orchid fail!!\n");
 		goto out_free_escb_array;
 	}
 
-	shost->io_port = pHCB->HCS_Base;
+	shost->io_port = host->base;
 	shost->n_io_port = 0xff;
 	shost->can_queue = ORC_MAXQUEUE;
 	shost->unique_id = shost->io_port;
-	shost->max_id = pHCB->HCS_MaxTar;
+	shost->max_id = host->max_targets;
 	shost->max_lun = 16;
-	shost->irq = pHCB->HCS_Intr = pdev->irq;
-	shost->this_id = pHCB->HCS_SCSI_ID;	/* Assign HCS index */
+	shost->irq = pdev->irq;
+	shost->this_id = host->scsi_id;	/* Assign HCS index */
 	shost->sg_tablesize = TOTAL_SG_ENTRY;
 
 	/* Initial orc chip           */
@@ -1137,36 +1170,36 @@
 	scsi_scan_host(shost);
 	return 0;
 
- out_free_irq:
+out_free_irq:
         free_irq(shost->irq, shost);
- out_free_escb_array:
-	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),
-			pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
- out_free_scb_array:
-	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
-			pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
- out_host_put:
+out_free_escb_array:
+	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_extended_scb),
+			host->escb_virt, host->escb_phys);
+out_free_scb_array:
+	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_scb),
+			host->scb_virt, host->scb_phys);
+out_host_put:
 	scsi_host_put(shost);
- out_release_region:
+out_release_region:
         release_region(port, 256);
- out_disable_device:
+out_disable_device:
 	pci_disable_device(pdev);
- out:
+out:
 	return error;
 }
 
 static void __devexit inia100_remove_one(struct pci_dev *pdev)
 {
 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
-	ORC_HCS *pHCB = (ORC_HCS *)shost->hostdata;
+	struct orc_host *host = (struct orc_host *)shost->hostdata;
 
 	scsi_remove_host(shost);
 
         free_irq(shost->irq, shost);
-	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),
-			pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
-	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
-			pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
+	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_extended_scb),
+			host->escb_virt, host->escb_phys);
+	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_scb),
+			host->scb_virt, host->scb_phys);
         release_region(shost->io_port, 256);
 
 	scsi_host_put(shost);
diff --git a/drivers/scsi/a100u2w.h b/drivers/scsi/a100u2w.h
index 6f542d2..d40e0c5 100644
--- a/drivers/scsi/a100u2w.h
+++ b/drivers/scsi/a100u2w.h
@@ -18,27 +18,6 @@
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * --------------------------------------------------------------------------
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of 
- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -50,30 +29,19 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- */
-
-/*
+ *
  * Revision History:
  * 06/18/98 HL, Initial production Version 1.02
  * 12/19/98 bv, Use spinlocks for 2.1.95 and up
  * 06/25/02 Doug Ledford <dledford@redhat.com>
  *	 - This and the i60uscsi.h file are almost identical,
  *	   merged them into a single header used by both .c files.
+ * 14/06/07 Alan Cox <alan@redhat.com>
+ *	 - Grand cleanup and Linuxisation
  */
 
 #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02d"
 
-#define ULONG   unsigned long
-#define USHORT  unsigned short
-#define UCHAR   unsigned char
-#define BYTE    unsigned char
-#define WORD    unsigned short
-#define DWORD   unsigned long
-#define UBYTE   unsigned char
-#define UWORD   unsigned short
-#define UDWORD  unsigned long
-#define U32     u32
-
 #if 1
 #define ORC_MAXQUEUE		245
 #define ORC_MAXTAGS		64
@@ -90,10 +58,10 @@
 /************************************************************************/
 /*              Scatter-Gather Element Structure                        */
 /************************************************************************/
-typedef struct ORC_SG_Struc {
-	U32 SG_Ptr;		/* Data Pointer */
-	U32 SG_Len;		/* Data Length */
-} ORC_SG;
+struct orc_sgent {
+	u32 base;		/* Data Pointer */
+	u32 length;		/* Data Length */
+};
 
 /* SCSI related definition                                              */
 #define DISC_NOT_ALLOW          0x80	/* Disconnect is not allowed    */
@@ -165,42 +133,45 @@
 #define	ORC_PRGMCTR1	0xE3	/* RISC program counter           */
 #define	ORC_RISCRAM	0xEC	/* RISC RAM data port 4 bytes     */
 
-typedef struct orc_extended_scb {	/* Extended SCB                 */
-	ORC_SG ESCB_SGList[TOTAL_SG_ENTRY];	/*0 Start of SG list              */
-	struct scsi_cmnd *SCB_Srb;	/*50 SRB Pointer */
-} ESCB;
+struct orc_extended_scb {	/* Extended SCB                 */
+	struct orc_sgent sglist[TOTAL_SG_ENTRY];	/*0 Start of SG list              */
+	struct scsi_cmnd *srb;	/*50 SRB Pointer */
+};
 
 /***********************************************************************
 		SCSI Control Block
-************************************************************************/
-typedef struct orc_scb {	/* Scsi_Ctrl_Blk                */
-	UBYTE SCB_Opcode;	/*00 SCB command code&residual  */
-	UBYTE SCB_Flags;	/*01 SCB Flags                  */
-	UBYTE SCB_Target;	/*02 Target Id                  */
-	UBYTE SCB_Lun;		/*03 Lun                        */
-	U32 SCB_Reserved0;	/*04 Reserved for ORCHID must 0 */
-	U32 SCB_XferLen;	/*08 Data Transfer Length       */
-	U32 SCB_Reserved1;	/*0C Reserved for ORCHID must 0 */
-	U32 SCB_SGLen;		/*10 SG list # * 8              */
-	U32 SCB_SGPAddr;	/*14 SG List Buf physical Addr  */
-	U32 SCB_SGPAddrHigh;	/*18 SG Buffer high physical Addr */
-	UBYTE SCB_HaStat;	/*1C Host Status                */
-	UBYTE SCB_TaStat;	/*1D Target Status              */
-	UBYTE SCB_Status;	/*1E SCB status                 */
-	UBYTE SCB_Link;		/*1F Link pointer, default 0xFF */
-	UBYTE SCB_SenseLen;	/*20 Sense Allocation Length    */
-	UBYTE SCB_CDBLen;	/*21 CDB Length                 */
-	UBYTE SCB_Ident;	/*22 Identify                   */
-	UBYTE SCB_TagMsg;	/*23 Tag Message                */
-	UBYTE SCB_CDB[IMAX_CDB];	/*24 SCSI CDBs                  */
-	UBYTE SCB_ScbIdx;	/*3C Index for this ORCSCB      */
-	U32 SCB_SensePAddr;	/*34 Sense Buffer physical Addr */
 
-	ESCB *SCB_EScb;		/*38 Extended SCB Pointer       */
-#ifndef ALPHA
-	UBYTE SCB_Reserved2[4];	/*3E Reserved for Driver use    */
+		0x40 bytes long, the last 8 are user bytes
+************************************************************************/
+struct orc_scb {	/* Scsi_Ctrl_Blk                */
+	u8 opcode;	/*00 SCB command code&residual  */
+	u8 flags;	/*01 SCB Flags                  */
+	u8 target;	/*02 Target Id                  */
+	u8 lun;		/*03 Lun                        */
+	u32 reserved0;	/*04 Reserved for ORCHID must 0 */
+	u32 xferlen;	/*08 Data Transfer Length       */
+	u32 reserved1;	/*0C Reserved for ORCHID must 0 */
+	u32 sg_len;		/*10 SG list # * 8              */
+	u32 sg_addr;	/*14 SG List Buf physical Addr  */
+	u32 sg_addrhigh;	/*18 SG Buffer high physical Addr */
+	u8 hastat;	/*1C Host Status                */
+	u8 tastat;	/*1D Target Status              */
+	u8 status;	/*1E SCB status                 */
+	u8 link;		/*1F Link pointer, default 0xFF */
+	u8 sense_len;	/*20 Sense Allocation Length    */
+	u8 cdb_len;	/*21 CDB Length                 */
+	u8 ident;	/*22 Identify                   */
+	u8 tag_msg;	/*23 Tag Message                */
+	u8 cdb[IMAX_CDB];	/*24 SCSI CDBs                  */
+	u8 scbidx;	/*3C Index for this ORCSCB      */
+	u32 sense_addr;	/*34 Sense Buffer physical Addr */
+
+	struct orc_extended_scb *escb; /*38 Extended SCB Pointer       */
+        /* 64bit pointer or 32bit pointer + reserved ? */
+#ifndef CONFIG_64BIT
+	u8 reserved2[4];	/*3E Reserved for Driver use    */
 #endif
-} ORC_SCB;
+};
 
 /* Opcodes of ORCSCB_Opcode */
 #define ORC_EXECSCSI	0x00	/* SCSI initiator command with residual */
@@ -239,13 +210,13 @@
 		Target Device Control Structure
 **********************************************************************/
 
-typedef struct ORC_Tar_Ctrl_Struc {
-	UBYTE TCS_DrvDASD;	/* 6 */
-	UBYTE TCS_DrvSCSI;	/* 7 */
-	UBYTE TCS_DrvHead;	/* 8 */
-	UWORD TCS_DrvFlags;	/* 4 */
-	UBYTE TCS_DrvSector;	/* 7 */
-} ORC_TCS;
+struct orc_target {
+	u8 TCS_DrvDASD;	/* 6 */
+	u8 TCS_DrvSCSI;	/* 7 */
+	u8 TCS_DrvHead;	/* 8 */
+	u16 TCS_DrvFlags;	/* 4 */
+	u8 TCS_DrvSector;	/* 7 */
+};
 
 /* Bit Definition for TCF_DrvFlags */
 #define	TCS_DF_NODASD_SUPT	0x20	/* Suppress OS/2 DASD Mgr support */
@@ -255,32 +226,23 @@
 /***********************************************************************
               Host Adapter Control Structure
 ************************************************************************/
-typedef struct ORC_Ha_Ctrl_Struc {
-	USHORT HCS_Base;	/* 00 */
-	UBYTE HCS_Index;	/* 02 */
-	UBYTE HCS_Intr;		/* 04 */
-	UBYTE HCS_SCSI_ID;	/* 06    H/A SCSI ID */
-	UBYTE HCS_BIOS;		/* 07    BIOS configuration */
-
-	UBYTE HCS_Flags;	/* 0B */
-	UBYTE HCS_HAConfig1;	/* 1B    SCSI0MAXTags */
-	UBYTE HCS_MaxTar;	/* 1B    SCSI0MAXTags */
-
-	USHORT HCS_Units;	/* Number of units this adapter  */
-	USHORT HCS_AFlags;	/* Adapter info. defined flags   */
-	ULONG HCS_Timeout;	/* Adapter timeout value   */
-	ORC_SCB *HCS_virScbArray;	/* 28 Virtual Pointer to SCB array */
-	dma_addr_t HCS_physScbArray;	/* Scb Physical address */
-	ESCB *HCS_virEscbArray;	/* Virtual pointer to ESCB Scatter list */
-	dma_addr_t HCS_physEscbArray;	/* scatter list Physical address */
-	UBYTE TargetFlag[16];	/* 30  target configuration, TCF_EN_TAG */
-	UBYTE MaximumTags[16];	/* 40  ORC_MAX_SCBS */
-	UBYTE ActiveTags[16][16];	/* 50 */
-	ORC_TCS HCS_Tcs[16];	/* 28 */
-	U32 BitAllocFlag[MAX_CHANNELS][8];	/* Max STB is 256, So 256/32 */
-	spinlock_t BitAllocFlagLock;
+struct orc_host {
+	unsigned long base;	/* Base address */
+	u8 index;		/* Index (Channel)*/
+	u8 scsi_id;		/* H/A SCSI ID */
+	u8 BIOScfg;		/*BIOS configuration */
+	u8 flags;
+	u8 max_targets;		/* SCSI0MAXTags */
+	struct orc_scb *scb_virt;	/* Virtual Pointer to SCB array */
+	dma_addr_t scb_phys;	/* Scb Physical address */
+	struct orc_extended_scb *escb_virt; /* Virtual pointer to ESCB Scatter list */
+	dma_addr_t escb_phys;	/* scatter list Physical address */
+	u8 target_flag[16];	/* target configuration, TCF_EN_TAG */
+	u8 max_tags[16];	/* ORC_MAX_SCBS */
+	u32 allocation_map[MAX_CHANNELS][8];	/* Max STB is 256, So 256/32 */
+	spinlock_t allocation_lock;
 	struct pci_dev *pdev;
-} ORC_HCS;
+};
 
 /* Bit Definition for HCS_Flags */
 
@@ -301,79 +263,79 @@
 #define	HCS_AF_DISABLE_RESET	0x10	/* Adapter disable reset  */
 #define	HCS_AF_DISABLE_ADPT	0x80	/* Adapter disable                */
 
-typedef struct _NVRAM {
+struct orc_nvram {
 /*----------header ---------------*/
-        UCHAR SubVendorID0;     /* 00 - Sub Vendor ID           */
-        UCHAR SubVendorID1;     /* 00 - Sub Vendor ID           */
-        UCHAR SubSysID0;        /* 02 - Sub System ID           */
-        UCHAR SubSysID1;        /* 02 - Sub System ID           */
-        UCHAR SubClass;         /* 04 - Sub Class               */
-        UCHAR VendorID0;        /* 05 - Vendor ID               */
-        UCHAR VendorID1;        /* 05 - Vendor ID               */
-        UCHAR DeviceID0;        /* 07 - Device ID               */
-        UCHAR DeviceID1;        /* 07 - Device ID               */
-        UCHAR Reserved0[2];     /* 09 - Reserved                */
-        UCHAR Revision;         /* 0B - Revision of data structure */
+        u8 SubVendorID0;     /* 00 - Sub Vendor ID           */
+        u8 SubVendorID1;     /* 00 - Sub Vendor ID           */
+        u8 SubSysID0;        /* 02 - Sub System ID           */
+        u8 SubSysID1;        /* 02 - Sub System ID           */
+        u8 SubClass;         /* 04 - Sub Class               */
+        u8 VendorID0;        /* 05 - Vendor ID               */
+        u8 VendorID1;        /* 05 - Vendor ID               */
+        u8 DeviceID0;        /* 07 - Device ID               */
+        u8 DeviceID1;        /* 07 - Device ID               */
+        u8 Reserved0[2];     /* 09 - Reserved                */
+        u8 revision;         /* 0B - revision of data structure */
         /* ----Host Adapter Structure ---- */
-        UCHAR NumOfCh;          /* 0C - Number of SCSI channel  */
-        UCHAR BIOSConfig1;      /* 0D - BIOS configuration 1    */
-        UCHAR BIOSConfig2;      /* 0E - BIOS boot channel&target ID */
-        UCHAR BIOSConfig3;      /* 0F - BIOS configuration 3    */
+        u8 NumOfCh;          /* 0C - Number of SCSI channel  */
+        u8 BIOSConfig1;      /* 0D - BIOS configuration 1    */
+        u8 BIOSConfig2;      /* 0E - BIOS boot channel&target ID */
+        u8 BIOSConfig3;      /* 0F - BIOS configuration 3    */
         /* ----SCSI channel Structure ---- */
         /* from "CTRL-I SCSI Host Adapter SetUp menu "  */
-        UCHAR SCSI0Id;          /* 10 - Channel 0 SCSI ID       */
-        UCHAR SCSI0Config;      /* 11 - Channel 0 SCSI configuration */
-        UCHAR SCSI0MaxTags;     /* 12 - Channel 0 Maximum tags  */
-        UCHAR SCSI0ResetTime;   /* 13 - Channel 0 Reset recovering time */
-        UCHAR ReservedforChannel0[2];   /* 14 - Reserved                */
+        u8 scsi_id;          /* 10 - Channel 0 SCSI ID       */
+        u8 SCSI0Config;      /* 11 - Channel 0 SCSI configuration */
+        u8 SCSI0MaxTags;     /* 12 - Channel 0 Maximum tags  */
+        u8 SCSI0ResetTime;   /* 13 - Channel 0 Reset recovering time */
+        u8 ReservedforChannel0[2];   /* 14 - Reserved                */
 
         /* ----SCSI target Structure ----  */
         /* from "CTRL-I SCSI device SetUp menu "                        */
-        UCHAR Target00Config;   /* 16 - Channel 0 Target 0 config */
-        UCHAR Target01Config;   /* 17 - Channel 0 Target 1 config */
-        UCHAR Target02Config;   /* 18 - Channel 0 Target 2 config */
-        UCHAR Target03Config;   /* 19 - Channel 0 Target 3 config */
-        UCHAR Target04Config;   /* 1A - Channel 0 Target 4 config */
-        UCHAR Target05Config;   /* 1B - Channel 0 Target 5 config */
-        UCHAR Target06Config;   /* 1C - Channel 0 Target 6 config */
-        UCHAR Target07Config;   /* 1D - Channel 0 Target 7 config */
-        UCHAR Target08Config;   /* 1E - Channel 0 Target 8 config */
-        UCHAR Target09Config;   /* 1F - Channel 0 Target 9 config */
-        UCHAR Target0AConfig;   /* 20 - Channel 0 Target A config */
-        UCHAR Target0BConfig;   /* 21 - Channel 0 Target B config */
-        UCHAR Target0CConfig;   /* 22 - Channel 0 Target C config */
-        UCHAR Target0DConfig;   /* 23 - Channel 0 Target D config */
-        UCHAR Target0EConfig;   /* 24 - Channel 0 Target E config */
-        UCHAR Target0FConfig;   /* 25 - Channel 0 Target F config */
+        u8 Target00Config;   /* 16 - Channel 0 Target 0 config */
+        u8 Target01Config;   /* 17 - Channel 0 Target 1 config */
+        u8 Target02Config;   /* 18 - Channel 0 Target 2 config */
+        u8 Target03Config;   /* 19 - Channel 0 Target 3 config */
+        u8 Target04Config;   /* 1A - Channel 0 Target 4 config */
+        u8 Target05Config;   /* 1B - Channel 0 Target 5 config */
+        u8 Target06Config;   /* 1C - Channel 0 Target 6 config */
+        u8 Target07Config;   /* 1D - Channel 0 Target 7 config */
+        u8 Target08Config;   /* 1E - Channel 0 Target 8 config */
+        u8 Target09Config;   /* 1F - Channel 0 Target 9 config */
+        u8 Target0AConfig;   /* 20 - Channel 0 Target A config */
+        u8 Target0BConfig;   /* 21 - Channel 0 Target B config */
+        u8 Target0CConfig;   /* 22 - Channel 0 Target C config */
+        u8 Target0DConfig;   /* 23 - Channel 0 Target D config */
+        u8 Target0EConfig;   /* 24 - Channel 0 Target E config */
+        u8 Target0FConfig;   /* 25 - Channel 0 Target F config */
 
-        UCHAR SCSI1Id;          /* 26 - Channel 1 SCSI ID       */
-        UCHAR SCSI1Config;      /* 27 - Channel 1 SCSI configuration */
-        UCHAR SCSI1MaxTags;     /* 28 - Channel 1 Maximum tags  */
-        UCHAR SCSI1ResetTime;   /* 29 - Channel 1 Reset recovering time */
-        UCHAR ReservedforChannel1[2];   /* 2A - Reserved                */
+        u8 SCSI1Id;          /* 26 - Channel 1 SCSI ID       */
+        u8 SCSI1Config;      /* 27 - Channel 1 SCSI configuration */
+        u8 SCSI1MaxTags;     /* 28 - Channel 1 Maximum tags  */
+        u8 SCSI1ResetTime;   /* 29 - Channel 1 Reset recovering time */
+        u8 ReservedforChannel1[2];   /* 2A - Reserved                */
 
         /* ----SCSI target Structure ----  */
         /* from "CTRL-I SCSI device SetUp menu "                                          */
-        UCHAR Target10Config;   /* 2C - Channel 1 Target 0 config */
-        UCHAR Target11Config;   /* 2D - Channel 1 Target 1 config */
-        UCHAR Target12Config;   /* 2E - Channel 1 Target 2 config */
-        UCHAR Target13Config;   /* 2F - Channel 1 Target 3 config */
-        UCHAR Target14Config;   /* 30 - Channel 1 Target 4 config */
-        UCHAR Target15Config;   /* 31 - Channel 1 Target 5 config */
-        UCHAR Target16Config;   /* 32 - Channel 1 Target 6 config */
-        UCHAR Target17Config;   /* 33 - Channel 1 Target 7 config */
-        UCHAR Target18Config;   /* 34 - Channel 1 Target 8 config */
-        UCHAR Target19Config;   /* 35 - Channel 1 Target 9 config */
-        UCHAR Target1AConfig;   /* 36 - Channel 1 Target A config */
-        UCHAR Target1BConfig;   /* 37 - Channel 1 Target B config */
-        UCHAR Target1CConfig;   /* 38 - Channel 1 Target C config */
-        UCHAR Target1DConfig;   /* 39 - Channel 1 Target D config */
-        UCHAR Target1EConfig;   /* 3A - Channel 1 Target E config */
-        UCHAR Target1FConfig;   /* 3B - Channel 1 Target F config */
-        UCHAR reserved[3];      /* 3C - Reserved                */
+        u8 Target10Config;   /* 2C - Channel 1 Target 0 config */
+        u8 Target11Config;   /* 2D - Channel 1 Target 1 config */
+        u8 Target12Config;   /* 2E - Channel 1 Target 2 config */
+        u8 Target13Config;   /* 2F - Channel 1 Target 3 config */
+        u8 Target14Config;   /* 30 - Channel 1 Target 4 config */
+        u8 Target15Config;   /* 31 - Channel 1 Target 5 config */
+        u8 Target16Config;   /* 32 - Channel 1 Target 6 config */
+        u8 Target17Config;   /* 33 - Channel 1 Target 7 config */
+        u8 Target18Config;   /* 34 - Channel 1 Target 8 config */
+        u8 Target19Config;   /* 35 - Channel 1 Target 9 config */
+        u8 Target1AConfig;   /* 36 - Channel 1 Target A config */
+        u8 Target1BConfig;   /* 37 - Channel 1 Target B config */
+        u8 Target1CConfig;   /* 38 - Channel 1 Target C config */
+        u8 Target1DConfig;   /* 39 - Channel 1 Target D config */
+        u8 Target1EConfig;   /* 3A - Channel 1 Target E config */
+        u8 Target1FConfig;   /* 3B - Channel 1 Target F config */
+        u8 reserved[3];      /* 3C - Reserved                */
         /* ---------- CheckSum ----------       */
-        UCHAR CheckSum;         /* 3F - Checksum of NVRam       */
-} NVRAM, *PNVRAM;
+        u8 CheckSum;         /* 3F - Checksum of NVRam       */
+};
 
 /* Bios Configuration for nvram->BIOSConfig1                            */
 #define NBC_BIOSENABLE  0x01    /* BIOS enable                    */
@@ -407,10 +369,3 @@
 #define NCC_RESET_TIME  0x0A    /* SCSI RESET recovering time     */
 #define NTC_DEFAULT     (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
 
-#define ORC_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
-#define ORC_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
-#define ORC_RDLONG(x,y)         (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
-
-#define ORC_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
-#define ORC_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
-#define ORC_WRLONG( adr,data)   outl( (ULONG)(data), (int)(adr))
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c
new file mode 100644
index 0000000..6a57846
--- /dev/null
+++ b/drivers/scsi/a4000t.c
@@ -0,0 +1,143 @@
+/*
+ * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
+ *		Amiga Technologies A4000T SCSI controller.
+ *
+ * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ * plus modifications of the 53c7xx.c driver to support the Amiga.
+ *
+ * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
+
+#include "53c700.h"
+
+MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
+MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
+MODULE_LICENSE("GPL");
+
+
+static struct scsi_host_template a4000t_scsi_driver_template = {
+	.name		= "A4000T builtin SCSI",
+	.proc_name	= "A4000t",
+	.this_id	= 7,
+	.module		= THIS_MODULE,
+};
+
+static struct platform_device *a4000t_scsi_device;
+
+#define A4000T_SCSI_ADDR 0xdd0040
+
+static int __devinit a4000t_probe(struct device *dev)
+{
+	struct Scsi_Host * host = NULL;
+	struct NCR_700_Host_Parameters *hostdata;
+
+	if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
+		goto out;
+
+	if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000,
+				"A4000T builtin SCSI"))
+		goto out;
+
+	hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+	if (hostdata == NULL) {
+		printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n");
+		goto out_release;
+	}
+	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
+
+	/* Fill in the required pieces of hostdata */
+	hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);
+	hostdata->clock = 50;
+	hostdata->chip710 = 1;
+	hostdata->dmode_extra = DMODE_FC2;
+	hostdata->dcntl_extra = EA_710;
+
+	/* and register the chip */
+	host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev);
+	if (!host) {
+		printk(KERN_ERR "a4000t-scsi: No host detected; "
+				"board configuration problem?\n");
+		goto out_free;
+	}
+
+	host->this_id = 7;
+	host->base = A4000T_SCSI_ADDR;
+	host->irq = IRQ_AMIGA_PORTS;
+
+	if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi",
+			host)) {
+		printk(KERN_ERR "a4000t-scsi: request_irq failed\n");
+		goto out_put_host;
+	}
+
+	scsi_scan_host(host);
+
+	return 0;
+
+ out_put_host:
+	scsi_host_put(host);
+ out_free:
+	kfree(hostdata);
+ out_release:
+	release_mem_region(A4000T_SCSI_ADDR, 0x1000);
+ out:
+	return -ENODEV;
+}
+
+static __devexit int a4000t_device_remove(struct device *dev)
+{
+	struct Scsi_Host *host = dev_to_shost(dev);
+	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+
+	scsi_remove_host(host);
+
+	NCR_700_release(host);
+	kfree(hostdata);
+	free_irq(host->irq, host);
+	release_mem_region(A4000T_SCSI_ADDR, 0x1000);
+
+	return 0;
+}
+
+static struct device_driver a4000t_scsi_driver = {
+	.name	= "a4000t-scsi",
+	.bus	= &platform_bus_type,
+	.probe	= a4000t_probe,
+	.remove	= __devexit_p(a4000t_device_remove),
+};
+
+static int __init a4000t_scsi_init(void)
+{
+	int err;
+
+	err = driver_register(&a4000t_scsi_driver);
+	if (err)
+		return err;
+
+	a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
+			-1, NULL, 0);
+	if (IS_ERR(a4000t_scsi_device)) {
+		driver_unregister(&a4000t_scsi_driver);
+		return PTR_ERR(a4000t_scsi_device);
+	}
+
+	return err;
+}
+
+static void __exit a4000t_scsi_exit(void)
+{
+	platform_device_unregister(a4000t_scsi_device);
+	driver_unregister(&a4000t_scsi_driver);
+}
+
+module_init(a4000t_scsi_init);
+module_exit(a4000t_scsi_exit);
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 1e82c69..0b6fd0b 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -146,7 +146,7 @@
 static int nondasd = -1;
 static int dacmode = -1;
 
-static int commit = -1;
+int aac_commit = -1;
 int startup_timeout = 180;
 int aif_timeout = 120;
 
@@ -154,7 +154,7 @@
 MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
 module_param(dacmode, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
-module_param(commit, int, S_IRUGO|S_IWUSR);
+module_param_named(commit, aac_commit, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
 module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for adapter to have it's kernel up and\nrunning. This is typically adjusted for large systems that do not have a BIOS.");
@@ -169,10 +169,25 @@
 module_param(acbsize, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
 
+int update_interval = 30 * 60;
+module_param(update_interval, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync updates issued to adapter.");
+
+int check_interval = 24 * 60 * 60;
+module_param(check_interval, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health checks.");
+
+int check_reset = 1;
+module_param(check_reset, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the adapter.");
+
 int expose_physicals = -1;
 module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
 
+int aac_reset_devices = 0;
+module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
 
 static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
 		struct fib *fibptr) {
@@ -246,7 +261,7 @@
 	aac_fib_complete(fibptr);
 	/* Send a CT_COMMIT_CONFIG to enable discovery of devices */
 	if (status >= 0) {
-		if ((commit == 1) || commit_flag) {
+		if ((aac_commit == 1) || commit_flag) {
 			struct aac_commit_config * dinfo;
 			aac_fib_init(fibptr);
 			dinfo = (struct aac_commit_config *) fib_data(fibptr);
@@ -261,7 +276,7 @@
 				    1, 1,
 				    NULL, NULL);
 			aac_fib_complete(fibptr);
-		} else if (commit == 0) {
+		} else if (aac_commit == 0) {
 			printk(KERN_WARNING
 			  "aac_get_config_status: Foreign device configurations are being ignored\n");
 		}
@@ -309,11 +324,10 @@
 
 	if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
 		maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
-	fsa_dev_ptr =  kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
+	fsa_dev_ptr = kzalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
 			GFP_KERNEL);
 	if (!fsa_dev_ptr)
 		return -ENOMEM;
-	memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
 
 	dev->fsa_dev = fsa_dev_ptr;
 	dev->maximum_num_containers = maximum_num_containers;
@@ -340,22 +354,17 @@
 static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
 {
 	void *buf;
-	unsigned int transfer_len;
-	struct scatterlist *sg = scsicmd->request_buffer;
+	int transfer_len;
+	struct scatterlist *sg = scsi_sglist(scsicmd);
 
-	if (scsicmd->use_sg) {
-		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-		transfer_len = min(sg->length, len + offset);
-	} else {
-		buf = scsicmd->request_buffer;
-		transfer_len = min(scsicmd->request_bufflen, len + offset);
-	}
+	buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+	transfer_len = min(sg->length, len + offset);
+
 	transfer_len -= offset;
-	if (buf && transfer_len)
+	if (buf && transfer_len > 0)
 		memcpy(buf + offset, data, transfer_len);
 
-	if (scsicmd->use_sg) 
-		kunmap_atomic(buf - sg->offset, KM_IRQ0);
+	kunmap_atomic(buf - sg->offset, KM_IRQ0);
 
 }
 
@@ -448,7 +457,7 @@
 {
 	struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
 
-	if (fsa_dev_ptr[scmd_id(scsicmd)].valid)
+	if ((fsa_dev_ptr[scmd_id(scsicmd)].valid & 1))
 		return aac_scsi_cmd(scsicmd);
 
 	scsicmd->result = DID_NO_CONNECT << 16;
@@ -456,18 +465,18 @@
 	return 0;
 }
 
-static int _aac_probe_container2(void * context, struct fib * fibptr)
+static void _aac_probe_container2(void * context, struct fib * fibptr)
 {
 	struct fsa_dev_info *fsa_dev_ptr;
 	int (*callback)(struct scsi_cmnd *);
 	struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
 
-	if (!aac_valid_context(scsicmd, fibptr))
-		return 0;
 
-	fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+	if (!aac_valid_context(scsicmd, fibptr))
+		return;
 
 	scsicmd->SCp.Status = 0;
+	fsa_dev_ptr = fibptr->dev->fsa_dev;
 	if (fsa_dev_ptr) {
 		struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
 		fsa_dev_ptr += scmd_id(scsicmd);
@@ -490,10 +499,11 @@
 	aac_fib_free(fibptr);
 	callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
 	scsicmd->SCp.ptr = NULL;
-	return (*callback)(scsicmd);
+	(*callback)(scsicmd);
+	return;
 }
 
-static int _aac_probe_container1(void * context, struct fib * fibptr)
+static void _aac_probe_container1(void * context, struct fib * fibptr)
 {
 	struct scsi_cmnd * scsicmd;
 	struct aac_mount * dresp;
@@ -503,13 +513,14 @@
 	dresp = (struct aac_mount *) fib_data(fibptr);
 	dresp->mnt[0].capacityhigh = 0;
 	if ((le32_to_cpu(dresp->status) != ST_OK) ||
-	    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE))
-		return _aac_probe_container2(context, fibptr);
+	    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
+		_aac_probe_container2(context, fibptr);
+		return;
+	}
 	scsicmd = (struct scsi_cmnd *) context;
-	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
 	if (!aac_valid_context(scsicmd, fibptr))
-		return 0;
+		return;
 
 	aac_fib_init(fibptr);
 
@@ -524,21 +535,18 @@
 			  sizeof(struct aac_query_mount),
 			  FsaNormal,
 			  0, 1,
-			  (fib_callback) _aac_probe_container2,
+			  _aac_probe_container2,
 			  (void *) scsicmd);
 	/*
 	 *	Check that the command queued to the controller
 	 */
-	if (status == -EINPROGRESS) {
+	if (status == -EINPROGRESS)
 		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
-		return 0;
-	}
-	if (status < 0) {
+	else if (status < 0) {
 		/* Inherit results from VM_NameServe, if any */
 		dresp->status = cpu_to_le32(ST_OK);
-		return _aac_probe_container2(context, fibptr);
+		_aac_probe_container2(context, fibptr);
 	}
-	return 0;
 }
 
 static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
@@ -563,7 +571,7 @@
 			  sizeof(struct aac_query_mount),
 			  FsaNormal,
 			  0, 1,
-			  (fib_callback) _aac_probe_container1,
+			  _aac_probe_container1,
 			  (void *) scsicmd);
 		/*
 		 *	Check that the command queued to the controller
@@ -617,7 +625,7 @@
 		return -ENOMEM;
 	}
 	scsicmd->list.next = NULL;
-	scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1;
+	scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1;
 
 	scsicmd->device = scsidev;
 	scsidev->sdev_state = 0;
@@ -822,7 +830,7 @@
 	readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
 	readcmd->count = cpu_to_le32(count<<9);
 	readcmd->cid = cpu_to_le16(scmd_id(cmd));
-	readcmd->flags = cpu_to_le16(1);
+	readcmd->flags = cpu_to_le16(IO_TYPE_READ);
 	readcmd->bpTotal = 0;
 	readcmd->bpComplete = 0;
 
@@ -901,7 +909,7 @@
 			  (void *) cmd);
 }
 
-static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
 {
 	u16 fibsize;
 	struct aac_raw_io *writecmd;
@@ -911,7 +919,9 @@
 	writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
 	writecmd->count = cpu_to_le32(count<<9);
 	writecmd->cid = cpu_to_le16(scmd_id(cmd));
-	writecmd->flags = 0;
+	writecmd->flags = fua ?
+		cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) :
+		cpu_to_le16(IO_TYPE_WRITE);
 	writecmd->bpTotal = 0;
 	writecmd->bpComplete = 0;
 
@@ -930,7 +940,7 @@
 			  (void *) cmd);
 }
 
-static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
 {
 	u16 fibsize;
 	struct aac_write64 *writecmd;
@@ -961,7 +971,7 @@
 			  (void *) cmd);
 }
 
-static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
 {
 	u16 fibsize;
 	struct aac_write *writecmd;
@@ -1038,7 +1048,7 @@
 	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
 
 	aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg);
-	srbcmd->count = cpu_to_le32(cmd->request_bufflen);
+	srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
 
 	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
 	memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
@@ -1066,7 +1076,7 @@
 	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
 
 	aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg);
-	srbcmd->count = cpu_to_le32(cmd->request_bufflen);
+	srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
 
 	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
 	memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
@@ -1169,6 +1179,7 @@
 	}
 
 	if (!dev->in_reset) {
+		char buffer[16];
 		tmp = le32_to_cpu(dev->adapter_info.kernelrev);
 		printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
 			dev->name, 
@@ -1189,16 +1200,23 @@
 			dev->name, dev->id,
 			tmp>>24,(tmp>>16)&0xff,tmp&0xff,
 			le32_to_cpu(dev->adapter_info.biosbuild));
-		if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
-			printk(KERN_INFO "%s%d: serial %x\n",
-				dev->name, dev->id,
-				le32_to_cpu(dev->adapter_info.serial[0]));
+		buffer[0] = '\0';
+		if (aac_show_serial_number(
+		  shost_to_class(dev->scsi_host_ptr), buffer))
+			printk(KERN_INFO "%s%d: serial %s",
+			  dev->name, dev->id, buffer);
 		if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) {
 			printk(KERN_INFO "%s%d: TSID %.*s\n",
 			  dev->name, dev->id,
 			  (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
 			  dev->supplement_adapter_info.VpdInfo.Tsid);
 		}
+		if (!check_reset ||
+		  (dev->supplement_adapter_info.SupportedOptions2 &
+		  le32_to_cpu(AAC_OPTION_IGNORE_RESET))) {
+			printk(KERN_INFO "%s%d: Reset Adapter Ignored\n",
+			  dev->name, dev->id);
+		}
 	}
 
 	dev->nondasd_support = 0;
@@ -1329,7 +1347,7 @@
 	if (!aac_valid_context(scsicmd, fibptr))
 		return;
 
-	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
+	dev = fibptr->dev;
 	cid = scmd_id(scsicmd);
 
 	if (nblank(dprintk(x))) {
@@ -1368,16 +1386,9 @@
 	}
 
 	BUG_ON(fibptr == NULL);
-		
-	if(scsicmd->use_sg)
-		pci_unmap_sg(dev->pdev, 
-			(struct scatterlist *)scsicmd->request_buffer,
-			scsicmd->use_sg,
-			scsicmd->sc_data_direction);
-	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
-				 scsicmd->request_bufflen,
-				 scsicmd->sc_data_direction);
+
+	scsi_dma_unmap(scsicmd);
+
 	readreply = (struct aac_read_reply *)fib_data(fibptr);
 	if (le32_to_cpu(readreply->status) == ST_OK)
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
@@ -1495,6 +1506,7 @@
 {
 	u64 lba;
 	u32 count;
+	int fua;
 	int status;
 	struct aac_dev *dev;
 	struct fib * cmd_fibcontext;
@@ -1509,6 +1521,7 @@
 		count = scsicmd->cmnd[4];
 		if (count == 0)
 			count = 256;
+		fua = 0;
 	} else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
 		dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
 
@@ -1521,6 +1534,7 @@
 			(scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
 		count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
 			(scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
+		fua = scsicmd->cmnd[1] & 0x8;
 	} else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
 		dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
 
@@ -1528,10 +1542,12 @@
 		    | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
 		count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
 		      | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+		fua = scsicmd->cmnd[1] & 0x8;
 	} else {
 		dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
 		lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
 		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
+		fua = scsicmd->cmnd[1] & 0x8;
 	}
 	dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
 	  smp_processor_id(), (unsigned long long)lba, jiffies));
@@ -1546,7 +1562,7 @@
 		return 0;
 	}
 
-	status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count);
+	status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
 
 	/*
 	 *	Check that the command queued to the controller
@@ -1589,7 +1605,7 @@
 			COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 	else {
 		struct scsi_device *sdev = cmd->device;
-		struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
+		struct aac_dev *dev = fibptr->dev;
 		u32 cid = sdev_id(sdev);
 		printk(KERN_WARNING 
 		     "synchronize_callback: synchronize failed, status = %d\n",
@@ -1696,7 +1712,7 @@
  
 int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
 {
-	u32 cid = 0;
+	u32 cid;
 	struct Scsi_Host *host = scsicmd->device->host;
 	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
 	struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
@@ -1708,15 +1724,15 @@
 	 *	Test does not apply to ID 16, the pseudo id for the controller
 	 *	itself.
 	 */
-	if (scmd_id(scsicmd) != host->this_id) {
-		if ((scmd_channel(scsicmd) == CONTAINER_CHANNEL)) {
-			if((scmd_id(scsicmd) >= dev->maximum_num_containers) ||
+	cid = scmd_id(scsicmd);
+	if (cid != host->this_id) {
+		if (scmd_channel(scsicmd) == CONTAINER_CHANNEL) {
+			if((cid >= dev->maximum_num_containers) ||
 					(scsicmd->device->lun != 0)) {
 				scsicmd->result = DID_NO_CONNECT << 16;
 				scsicmd->scsi_done(scsicmd);
 				return 0;
 			}
-			cid = scmd_id(scsicmd);
 
 			/*
 			 *	If the target container doesn't exist, it may have
@@ -1779,7 +1795,7 @@
 	{
 		struct inquiry_data inq_data;
 
-		dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scmd_id(scsicmd)));
+		dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
 		memset(&inq_data, 0, sizeof (struct inquiry_data));
 
 		inq_data.inqd_ver = 2;	/* claim compliance to SCSI-2 */
@@ -1791,7 +1807,7 @@
 		 *	Set the Vendor, Product, and Revision Level
 		 *	see: <vendor>.c i.e. aac.c
 		 */
-		if (scmd_id(scsicmd) == host->this_id) {
+		if (cid == host->this_id) {
 			setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
 			inq_data.inqd_pdt = INQD_PDT_PROC;	/* Processor device */
 			aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
@@ -1883,15 +1899,29 @@
 
 	case MODE_SENSE:
 	{
-		char mode_buf[4];
+		char mode_buf[7];
+		int mode_buf_length = 4;
 
 		dprintk((KERN_DEBUG "MODE SENSE command.\n"));
 		mode_buf[0] = 3;	/* Mode data length */
 		mode_buf[1] = 0;	/* Medium type - default */
-		mode_buf[2] = 0;	/* Device-specific param, bit 8: 0/1 = write enabled/protected */
+		mode_buf[2] = 0;	/* Device-specific param,
+					   bit 8: 0/1 = write enabled/protected
+					   bit 4: 0/1 = FUA enabled */
+		if (dev->raw_io_interface)
+			mode_buf[2] = 0x10;
 		mode_buf[3] = 0;	/* Block descriptor length */
-
-		aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
+		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
+		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
+			mode_buf[0] = 6;
+			mode_buf[4] = 8;
+			mode_buf[5] = 1;
+			mode_buf[6] = 0x04; /* WCE */
+			mode_buf_length = 7;
+			if (mode_buf_length > scsicmd->cmnd[4])
+				mode_buf_length = scsicmd->cmnd[4];
+		}
+		aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 		scsicmd->scsi_done(scsicmd);
 
@@ -1899,18 +1929,33 @@
 	}
 	case MODE_SENSE_10:
 	{
-		char mode_buf[8];
+		char mode_buf[11];
+		int mode_buf_length = 8;
 
 		dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
 		mode_buf[0] = 0;	/* Mode data length (MSB) */
 		mode_buf[1] = 6;	/* Mode data length (LSB) */
 		mode_buf[2] = 0;	/* Medium type - default */
-		mode_buf[3] = 0;	/* Device-specific param, bit 8: 0/1 = write enabled/protected */
+		mode_buf[3] = 0;	/* Device-specific param,
+					   bit 8: 0/1 = write enabled/protected
+					   bit 4: 0/1 = FUA enabled */
+		if (dev->raw_io_interface)
+			mode_buf[3] = 0x10;
 		mode_buf[4] = 0;	/* reserved */
 		mode_buf[5] = 0;	/* reserved */
 		mode_buf[6] = 0;	/* Block descriptor length (MSB) */
 		mode_buf[7] = 0;	/* Block descriptor length (LSB) */
-		aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
+		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
+		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
+			mode_buf[1] = 9;
+			mode_buf[8] = 8;
+			mode_buf[9] = 1;
+			mode_buf[10] = 0x04; /* WCE */
+			mode_buf_length = 11;
+			if (mode_buf_length > scsicmd->cmnd[8])
+				mode_buf_length = scsicmd->cmnd[8];
+		}
+		aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
 
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 		scsicmd->scsi_done(scsicmd);
@@ -2133,28 +2178,21 @@
 	if (!aac_valid_context(scsicmd, fibptr))
 		return;
 
-	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-
 	BUG_ON(fibptr == NULL);
 
+	dev = fibptr->dev;
+
 	srbreply = (struct aac_srb_reply *) fib_data(fibptr);
 
 	scsicmd->sense_buffer[0] = '\0';  /* Initialize sense valid flag to false */
 	/*
 	 *	Calculate resid for sg 
 	 */
-	 
-	scsicmd->resid = scsicmd->request_bufflen - 
-		le32_to_cpu(srbreply->data_xfer_length);
 
-	if(scsicmd->use_sg)
-		pci_unmap_sg(dev->pdev, 
-			(struct scatterlist *)scsicmd->request_buffer,
-			scsicmd->use_sg,
-			scsicmd->sc_data_direction);
-	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen,
-			scsicmd->sc_data_direction);
+	scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
+		       - le32_to_cpu(srbreply->data_xfer_length));
+
+	scsi_dma_unmap(scsicmd);
 
 	/*
 	 * First check the fib status
@@ -2230,7 +2268,7 @@
 		break;
 
 	case SRB_STATUS_BUSY:
-		scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
+		scsicmd->result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
 		break;
 
 	case SRB_STATUS_BUS_RESET:
@@ -2340,34 +2378,33 @@
 {
 	struct aac_dev *dev;
 	unsigned long byte_count = 0;
+	int nseg;
 
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 	// Get rid of old data
 	psg->count = 0;
 	psg->sg[0].addr = 0;
-	psg->sg[0].count = 0;  
-	if (scsicmd->use_sg) {
+	psg->sg[0].count = 0;
+
+	nseg = scsi_dma_map(scsicmd);
+	BUG_ON(nseg < 0);
+	if (nseg) {
 		struct scatterlist *sg;
 		int i;
-		int sg_count;
-		sg = (struct scatterlist *) scsicmd->request_buffer;
 
-		sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
-			scsicmd->sc_data_direction);
-		psg->count = cpu_to_le32(sg_count);
+		psg->count = cpu_to_le32(nseg);
 
-		for (i = 0; i < sg_count; i++) {
+		scsi_for_each_sg(scsicmd, sg, nseg, i) {
 			psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
 			psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
 			byte_count += sg_dma_len(sg);
-			sg++;
 		}
 		/* hba wants the size to be exact */
-		if(byte_count > scsicmd->request_bufflen){
-			u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
-				(byte_count - scsicmd->request_bufflen);
+		if (byte_count > scsi_bufflen(scsicmd)) {
+			u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+				(byte_count - scsi_bufflen(scsicmd));
 			psg->sg[i-1].count = cpu_to_le32(temp);
-			byte_count = scsicmd->request_bufflen;
+			byte_count = scsi_bufflen(scsicmd);
 		}
 		/* Check for command underflow */
 		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
@@ -2375,18 +2412,6 @@
 					byte_count, scsicmd->underflow);
 		}
 	}
-	else if(scsicmd->request_bufflen) {
-		u32 addr;
-		scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
-				scsicmd->request_buffer,
-				scsicmd->request_bufflen,
-				scsicmd->sc_data_direction);
-		addr = scsicmd->SCp.dma_handle;
-		psg->count = cpu_to_le32(1);
-		psg->sg[0].addr = cpu_to_le32(addr);
-		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-		byte_count = scsicmd->request_bufflen;
-	}
 	return byte_count;
 }
 
@@ -2396,6 +2421,7 @@
 	struct aac_dev *dev;
 	unsigned long byte_count = 0;
 	u64 addr;
+	int nseg;
 
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 	// Get rid of old data
@@ -2403,31 +2429,28 @@
 	psg->sg[0].addr[0] = 0;
 	psg->sg[0].addr[1] = 0;
 	psg->sg[0].count = 0;
-	if (scsicmd->use_sg) {
+
+	nseg = scsi_dma_map(scsicmd);
+	BUG_ON(nseg < 0);
+	if (nseg) {
 		struct scatterlist *sg;
 		int i;
-		int sg_count;
-		sg = (struct scatterlist *) scsicmd->request_buffer;
 
-		sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
-			scsicmd->sc_data_direction);
-
-		for (i = 0; i < sg_count; i++) {
+		scsi_for_each_sg(scsicmd, sg, nseg, i) {
 			int count = sg_dma_len(sg);
 			addr = sg_dma_address(sg);
 			psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
 			psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
 			psg->sg[i].count = cpu_to_le32(count);
 			byte_count += count;
-			sg++;
 		}
-		psg->count = cpu_to_le32(sg_count);
+		psg->count = cpu_to_le32(nseg);
 		/* hba wants the size to be exact */
-		if(byte_count > scsicmd->request_bufflen){
-			u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
-				(byte_count - scsicmd->request_bufflen);
+		if (byte_count > scsi_bufflen(scsicmd)) {
+			u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+				(byte_count - scsi_bufflen(scsicmd));
 			psg->sg[i-1].count = cpu_to_le32(temp);
-			byte_count = scsicmd->request_bufflen;
+			byte_count = scsi_bufflen(scsicmd);
 		}
 		/* Check for command underflow */
 		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
@@ -2435,26 +2458,13 @@
 					byte_count, scsicmd->underflow);
 		}
 	}
-	else if(scsicmd->request_bufflen) {
-		scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
-				scsicmd->request_buffer,
-				scsicmd->request_bufflen,
-				scsicmd->sc_data_direction);
-		addr = scsicmd->SCp.dma_handle;
-		psg->count = cpu_to_le32(1);
-		psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
-		psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
-		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-		byte_count = scsicmd->request_bufflen;
-	}
 	return byte_count;
 }
 
 static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
 {
-	struct Scsi_Host *host = scsicmd->device->host;
-	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
 	unsigned long byte_count = 0;
+	int nseg;
 
 	// Get rid of old data
 	psg->count = 0;
@@ -2464,16 +2474,14 @@
 	psg->sg[0].addr[1] = 0;
 	psg->sg[0].count = 0;
 	psg->sg[0].flags = 0;
-	if (scsicmd->use_sg) {
+
+	nseg = scsi_dma_map(scsicmd);
+	BUG_ON(nseg < 0);
+	if (nseg) {
 		struct scatterlist *sg;
 		int i;
-		int sg_count;
-		sg = (struct scatterlist *) scsicmd->request_buffer;
 
-		sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
-			scsicmd->sc_data_direction);
-
-		for (i = 0; i < sg_count; i++) {
+		scsi_for_each_sg(scsicmd, sg, nseg, i) {
 			int count = sg_dma_len(sg);
 			u64 addr = sg_dma_address(sg);
 			psg->sg[i].next = 0;
@@ -2483,15 +2491,14 @@
 			psg->sg[i].count = cpu_to_le32(count);
 			psg->sg[i].flags = 0;
 			byte_count += count;
-			sg++;
 		}
-		psg->count = cpu_to_le32(sg_count);
+		psg->count = cpu_to_le32(nseg);
 		/* hba wants the size to be exact */
-		if(byte_count > scsicmd->request_bufflen){
-			u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
-				(byte_count - scsicmd->request_bufflen);
+		if (byte_count > scsi_bufflen(scsicmd)) {
+			u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+				(byte_count - scsi_bufflen(scsicmd));
 			psg->sg[i-1].count = cpu_to_le32(temp);
-			byte_count = scsicmd->request_bufflen;
+			byte_count = scsi_bufflen(scsicmd);
 		}
 		/* Check for command underflow */
 		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
@@ -2499,24 +2506,6 @@
 					byte_count, scsicmd->underflow);
 		}
 	}
-	else if(scsicmd->request_bufflen) {
-		int count;
-		u64 addr;
-		scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
-				scsicmd->request_buffer,
-				scsicmd->request_bufflen,
-				scsicmd->sc_data_direction);
-		addr = scsicmd->SCp.dma_handle;
-		count = scsicmd->request_bufflen;
-		psg->count = cpu_to_le32(1);
-		psg->sg[0].next = 0;
-		psg->sg[0].prev = 0;
-		psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32));
-		psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
-		psg->sg[0].count = cpu_to_le32(count);
-		psg->sg[0].flags = 0;
-		byte_count = scsicmd->request_bufflen;
-	}
 	return byte_count;
 }
 
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 45ca3e8..f1d3b66 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,8 +12,8 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 2437
-# define AAC_DRIVER_BRANCH "-mh4"
+# define AAC_DRIVER_BUILD 2447
+# define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS	32
 
@@ -464,12 +464,12 @@
 	int  (*adapter_restart)(struct aac_dev *dev, int bled);
 	/* Transport operations */
 	int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
-	irqreturn_t (*adapter_intr)(int irq, void *dev_id);
+	irq_handler_t adapter_intr;
 	/* Packet operations */
 	int  (*adapter_deliver)(struct fib * fib);
 	int  (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba);
 	int  (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
-	int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
+	int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua);
 	int  (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd);
 	/* Administrative operations */
 	int  (*adapter_comm)(struct aac_dev * dev, int comm);
@@ -860,10 +860,12 @@
 	__le32	FlashFirmwareBootBuild;
 	u8	MfgPcbaSerialNo[12];
 	u8	MfgWWNName[8];
-	__le32	MoreFeatureBits;
+	__le32	SupportedOptions2;
 	__le32	ReservedGrowth[1];
 };
 #define AAC_FEATURE_FALCON	0x00000010
+#define AAC_OPTION_MU_RESET	0x00000001
+#define AAC_OPTION_IGNORE_RESET	0x00000002
 #define AAC_SIS_VERSION_V3	3
 #define AAC_SIS_SLOT_UNKNOWN	0xFF
 
@@ -1054,8 +1056,8 @@
 #define aac_adapter_read(fib,cmd,lba,count) \
 	((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count)
 
-#define aac_adapter_write(fib,cmd,lba,count) \
-	((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count)
+#define aac_adapter_write(fib,cmd,lba,count,fua) \
+	((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count,fua)
 
 #define aac_adapter_scsi(fib,cmd) \
 	((fib)->dev)->a_ops.adapter_scsi(fib,cmd)
@@ -1213,6 +1215,9 @@
 	__le32 		block;
 	__le16		pad;
 	__le16		flags;
+#define	IO_TYPE_WRITE 0x00000000
+#define	IO_TYPE_READ  0x00000001
+#define	IO_SUREWRITE  0x00000008
 	struct sgmap64	sg;	// Must be last in struct because it is variable
 };
 struct aac_write_reply
@@ -1257,6 +1262,19 @@
 	u8		data[16];
 };
 
+#define CT_PAUSE_IO    65
+#define CT_RELEASE_IO  66
+struct aac_pause {
+	__le32		command;	/* VM_ContainerConfig */
+	__le32		type;		/* CT_PAUSE_IO */
+	__le32		timeout;	/* 10ms ticks */
+	__le32		min;
+	__le32		noRescan;
+	__le32		parm3;
+	__le32		parm4;
+	__le32		count;	/* sizeof(((struct aac_pause_reply *)NULL)->data) */
+};
+
 struct aac_srb
 {
 	__le32		function;
@@ -1804,6 +1822,10 @@
 int aac_get_containers(struct aac_dev *dev);
 int aac_scsi_cmd(struct scsi_cmnd *cmd);
 int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
+#ifndef shost_to_class
+#define shost_to_class(shost) &shost->shost_classdev
+#endif
+ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf);
 int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
 int aac_rx_init(struct aac_dev *dev);
 int aac_rkt_init(struct aac_dev *dev);
@@ -1813,6 +1835,7 @@
 unsigned int aac_response_normal(struct aac_queue * q);
 unsigned int aac_command_normal(struct aac_queue * q);
 unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
+int aac_reset_adapter(struct aac_dev * dev, int forced);
 int aac_check_health(struct aac_dev * dev);
 int aac_command_thread(void *data);
 int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
@@ -1823,9 +1846,15 @@
 int aac_probe_container(struct aac_dev *dev, int cid);
 int _aac_rx_init(struct aac_dev *dev);
 int aac_rx_select_comm(struct aac_dev *dev, int comm);
+int aac_rx_deliver_producer(struct fib * fib);
 extern int numacb;
 extern int acbsize;
 extern char aac_driver_version[];
 extern int startup_timeout;
 extern int aif_timeout;
 extern int expose_physicals;
+extern int aac_reset_devices;
+extern int aac_commit;
+extern int update_interval;
+extern int check_interval;
+extern int check_reset;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 9aca57e..d510839 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1021,7 +1021,7 @@
 
 }
 
-static int _aac_reset_adapter(struct aac_dev *aac)
+static int _aac_reset_adapter(struct aac_dev *aac, int forced)
 {
 	int index, quirks;
 	int retval;
@@ -1029,25 +1029,32 @@
 	struct scsi_device *dev;
 	struct scsi_cmnd *command;
 	struct scsi_cmnd *command_list;
+	int jafo = 0;
 
 	/*
 	 * Assumptions:
-	 *	- host is locked.
+	 *	- host is locked, unless called by the aacraid thread.
+	 *	  (a matter of convenience, due to legacy issues surrounding
+	 *	  eh_host_adapter_reset).
 	 *	- in_reset is asserted, so no new i/o is getting to the
 	 *	  card.
-	 *	- The card is dead.
+	 *	- The card is dead, or will be very shortly ;-/ so no new
+	 *	  commands are completing in the interrupt service.
 	 */
 	host = aac->scsi_host_ptr;
 	scsi_block_requests(host);
 	aac_adapter_disable_int(aac);
-	spin_unlock_irq(host->host_lock);
-	kthread_stop(aac->thread);
+	if (aac->thread->pid != current->pid) {
+		spin_unlock_irq(host->host_lock);
+		kthread_stop(aac->thread);
+		jafo = 1;
+	}
 
 	/*
 	 *	If a positive health, means in a known DEAD PANIC
 	 * state and the adapter could be reset to `try again'.
 	 */
-	retval = aac_adapter_restart(aac, aac_adapter_check_health(aac));
+	retval = aac_adapter_restart(aac, forced ? 0 : aac_adapter_check_health(aac));
 
 	if (retval)
 		goto out;
@@ -1104,10 +1111,12 @@
 	if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT)
 		if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK)))
 			goto out;
-	aac->thread = kthread_run(aac_command_thread, aac, aac->name);
-	if (IS_ERR(aac->thread)) {
-		retval = PTR_ERR(aac->thread);
-		goto out;
+	if (jafo) {
+		aac->thread = kthread_run(aac_command_thread, aac, aac->name);
+		if (IS_ERR(aac->thread)) {
+			retval = PTR_ERR(aac->thread);
+			goto out;
+		}
 	}
 	(void)aac_get_adapter_info(aac);
 	quirks = aac_get_driver_ident(index)->quirks;
@@ -1150,7 +1159,98 @@
 out:
 	aac->in_reset = 0;
 	scsi_unblock_requests(host);
-	spin_lock_irq(host->host_lock);
+	if (jafo) {
+		spin_lock_irq(host->host_lock);
+	}
+	return retval;
+}
+
+int aac_reset_adapter(struct aac_dev * aac, int forced)
+{
+	unsigned long flagv = 0;
+	int retval;
+	struct Scsi_Host * host;
+
+	if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0)
+		return -EBUSY;
+
+	if (aac->in_reset) {
+		spin_unlock_irqrestore(&aac->fib_lock, flagv);
+		return -EBUSY;
+	}
+	aac->in_reset = 1;
+	spin_unlock_irqrestore(&aac->fib_lock, flagv);
+
+	/*
+	 * Wait for all commands to complete to this specific
+	 * target (block maximum 60 seconds). Although not necessary,
+	 * it does make us a good storage citizen.
+	 */
+	host = aac->scsi_host_ptr;
+	scsi_block_requests(host);
+	if (forced < 2) for (retval = 60; retval; --retval) {
+		struct scsi_device * dev;
+		struct scsi_cmnd * command;
+		int active = 0;
+
+		__shost_for_each_device(dev, host) {
+			spin_lock_irqsave(&dev->list_lock, flagv);
+			list_for_each_entry(command, &dev->cmd_list, list) {
+				if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
+					active++;
+					break;
+				}
+			}
+			spin_unlock_irqrestore(&dev->list_lock, flagv);
+			if (active)
+				break;
+
+		}
+		/*
+		 * We can exit If all the commands are complete
+		 */
+		if (active == 0)
+			break;
+		ssleep(1);
+	}
+
+	/* Quiesce build, flush cache, write through mode */
+	aac_send_shutdown(aac);
+	spin_lock_irqsave(host->host_lock, flagv);
+	retval = _aac_reset_adapter(aac, forced);
+	spin_unlock_irqrestore(host->host_lock, flagv);
+
+	if (retval == -ENODEV) {
+		/* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */
+		struct fib * fibctx = aac_fib_alloc(aac);
+		if (fibctx) {
+			struct aac_pause *cmd;
+			int status;
+
+			aac_fib_init(fibctx);
+
+			cmd = (struct aac_pause *) fib_data(fibctx);
+
+			cmd->command = cpu_to_le32(VM_ContainerConfig);
+			cmd->type = cpu_to_le32(CT_PAUSE_IO);
+			cmd->timeout = cpu_to_le32(1);
+			cmd->min = cpu_to_le32(1);
+			cmd->noRescan = cpu_to_le32(1);
+			cmd->count = cpu_to_le32(0);
+
+			status = aac_fib_send(ContainerCommand,
+			  fibctx,
+			  sizeof(struct aac_pause),
+			  FsaNormal,
+			  -2 /* Timeout silently */, 1,
+			  NULL, NULL);
+
+			if (status >= 0)
+				aac_fib_complete(fibctx);
+			aac_fib_free(fibctx);
+		}
+	}
+
 	return retval;
 }
 
@@ -1270,10 +1370,15 @@
 
 	printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED);
 
+	if (!check_reset || (aac->supplement_adapter_info.SupportedOptions2 &
+	  le32_to_cpu(AAC_OPTION_IGNORE_RESET)))
+		goto out;
 	host = aac->scsi_host_ptr;
-	spin_lock_irqsave(host->host_lock, flagv);
-	BlinkLED = _aac_reset_adapter(aac);
-	spin_unlock_irqrestore(host->host_lock, flagv);
+	if (aac->thread->pid != current->pid)
+		spin_lock_irqsave(host->host_lock, flagv);
+	BlinkLED = _aac_reset_adapter(aac, 0);
+	if (aac->thread->pid != current->pid)
+		spin_unlock_irqrestore(host->host_lock, flagv);
 	return BlinkLED;
 
 out:
@@ -1300,6 +1405,9 @@
 	struct aac_fib_context *fibctx;
 	unsigned long flags;
 	DECLARE_WAITQUEUE(wait, current);
+	unsigned long next_jiffies = jiffies + HZ;
+	unsigned long next_check_jiffies = next_jiffies;
+	long difference = HZ;
 
 	/*
 	 *	We can only have one thread per adapter for AIF's.
@@ -1368,7 +1476,7 @@
 				     cpu_to_le32(AifCmdJobProgress))) {
 					aac_handle_aif(dev, fib);
 				}
- 				
+
 				time_now = jiffies/HZ;
 
 				/*
@@ -1507,11 +1615,79 @@
 		 *	There are no more AIF's
 		 */
 		spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
-		schedule();
+
+		/*
+		 *	Background activity
+		 */
+		if ((time_before(next_check_jiffies,next_jiffies))
+		 && ((difference = next_check_jiffies - jiffies) <= 0)) {
+			next_check_jiffies = next_jiffies;
+			if (aac_check_health(dev) == 0) {
+				difference = ((long)(unsigned)check_interval)
+					   * HZ;
+				next_check_jiffies = jiffies + difference;
+			} else if (!dev->queues)
+				break;
+		}
+		if (!time_before(next_check_jiffies,next_jiffies)
+		 && ((difference = next_jiffies - jiffies) <= 0)) {
+			struct timeval now;
+			int ret;
+
+			/* Don't even try to talk to adapter if its sick */
+			ret = aac_check_health(dev);
+			if (!ret && !dev->queues)
+				break;
+			next_check_jiffies = jiffies
+					   + ((long)(unsigned)check_interval)
+					   * HZ;
+			do_gettimeofday(&now);
+
+			/* Synchronize our watches */
+			if (((1000000 - (1000000 / HZ)) > now.tv_usec)
+			 && (now.tv_usec > (1000000 / HZ)))
+				difference = (((1000000 - now.tv_usec) * HZ)
+				  + 500000) / 1000000;
+			else if (ret == 0) {
+				struct fib *fibptr;
+
+				if ((fibptr = aac_fib_alloc(dev))) {
+					u32 * info;
+
+					aac_fib_init(fibptr);
+
+					info = (u32 *) fib_data(fibptr);
+					if (now.tv_usec > 500000)
+						++now.tv_sec;
+
+					*info = cpu_to_le32(now.tv_sec);
+
+					(void)aac_fib_send(SendHostTime,
+						fibptr,
+						sizeof(*info),
+						FsaNormal,
+						1, 1,
+						NULL,
+						NULL);
+					aac_fib_complete(fibptr);
+					aac_fib_free(fibptr);
+				}
+				difference = (long)(unsigned)update_interval*HZ;
+			} else {
+				/* retry shortly */
+				difference = 10 * HZ;
+			}
+			next_jiffies = jiffies + difference;
+			if (time_before(next_check_jiffies,next_jiffies))
+				difference = next_check_jiffies - jiffies;
+		}
+		if (difference <= 0)
+			difference = 1;
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(difference);
 
 		if (kthread_should_stop())
 			break;
-		set_current_state(TASK_INTERRUPTIBLE);
 	}
 	if (dev->queues)
 		remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 350ea7f..d76e1a8 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -39,10 +39,8 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/dma-mapping.h>
 #include <linux/syscalls.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/kthread.h>
 #include <asm/semaphore.h>
 
@@ -223,12 +221,12 @@
 	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
 	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
 	{ aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
-	{ aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell PERC2/QC */
+	{ aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_34SG }, /* Dell PERC2/QC */
 	{ aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4, AAC_QUIRK_34SG }, /* HP NetRAID-4M */
 
 	{ aac_rx_init, "aacraid",  "DELL    ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */
 	{ aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Catch All */
 	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */
 	{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec NEMER/ARK Catch All */
 };
@@ -403,10 +401,6 @@
 
 static int aac_slave_configure(struct scsi_device *sdev)
 {
-	if (sdev_channel(sdev) == CONTAINER_CHANNEL) {
-		sdev->skip_ms_page_8 = 1;
-		sdev->skip_ms_page_3f = 1;
-	}
 	if ((sdev->type == TYPE_DISK) &&
 			(sdev_channel(sdev) != CONTAINER_CHANNEL)) {
 		if (expose_physicals == 0)
@@ -450,6 +444,43 @@
 	return 0;
 }
 
+/**
+ *	aac_change_queue_depth		-	alter queue depths
+ *	@sdev:	SCSI device we are considering
+ *	@depth:	desired queue depth
+ *
+ *	Alters queue depths for target device based on the host adapter's
+ *	total capacity and the queue depth supported by the target device.
+ */
+
+static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
+{
+	if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
+	    (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
+		struct scsi_device * dev;
+		struct Scsi_Host *host = sdev->host;
+		unsigned num = 0;
+
+		__shost_for_each_device(dev, host) {
+			if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
+			    (sdev_channel(dev) == CONTAINER_CHANNEL))
+				++num;
+			++num;
+		}
+		if (num >= host->can_queue)
+			num = host->can_queue - 1;
+		if (depth > (host->can_queue - num))
+			depth = host->can_queue - num;
+		if (depth > 256)
+			depth = 256;
+		else if (depth < 2)
+			depth = 2;
+		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
+	} else
+		scsi_adjust_queue_depth(sdev, 0, 1);
+	return sdev->queue_depth;
+}
+
 static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
 {
 	struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
@@ -548,6 +579,14 @@
 		ssleep(1);
 	}
 	printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
+	/*
+	 * This adapter needs a blind reset, only do so for Adapters that
+	 * support a register, instead of a commanded, reset.
+	 */
+	if ((aac->supplement_adapter_info.SupportedOptions2 &
+	  le32_to_cpu(AAC_OPTION_MU_RESET|AAC_OPTION_IGNORE_RESET)) ==
+	  le32_to_cpu(AAC_OPTION_MU_RESET))
+		aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */
 	return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
 }
 
@@ -731,15 +770,21 @@
 	return len;
 }
 
-static ssize_t aac_show_serial_number(struct class_device *class_dev,
-		char *buf)
+ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
 {
 	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
 	int len = 0;
 
 	if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
-		len = snprintf(buf, PAGE_SIZE, "%x\n",
+		len = snprintf(buf, PAGE_SIZE, "%06X\n",
 		  le32_to_cpu(dev->adapter_info.serial[0]));
+	if (len &&
+	  !memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[
+	    sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)+2-len],
+	  buf, len))
+		len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+		  (int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),
+		  dev->supplement_adapter_info.MfgPcbaSerialNo);
 	return len;
 }
 
@@ -755,6 +800,31 @@
 	  class_to_shost(class_dev)->max_id);
 }
 
+static ssize_t aac_store_reset_adapter(struct class_device *class_dev,
+		const char *buf, size_t count)
+{
+	int retval = -EACCES;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return retval;
+	retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!');
+	if (retval >= 0)
+		retval = count;
+	return retval;
+}
+
+static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+		char *buf)
+{
+	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+	int len, tmp;
+
+	tmp = aac_adapter_check_health(dev);
+	if ((tmp == 0) && dev->in_reset)
+		tmp = -EBUSY;
+	len = snprintf(buf, PAGE_SIZE, "0x%x", tmp);
+	return len;
+}
 
 static struct class_device_attribute aac_model = {
 	.attr = {
@@ -812,6 +882,14 @@
 	},
 	.show = aac_show_max_id,
 };
+static struct class_device_attribute aac_reset = {
+	.attr = {
+		.name = "reset_host",
+		.mode = S_IWUSR|S_IRUGO,
+	},
+	.store = aac_store_reset_adapter,
+	.show = aac_show_reset_adapter,
+};
 
 static struct class_device_attribute *aac_attrs[] = {
 	&aac_model,
@@ -822,6 +900,7 @@
 	&aac_serial_number,
 	&aac_max_channel,
 	&aac_max_id,
+	&aac_reset,
 	NULL
 };
 
@@ -848,6 +927,7 @@
 	.bios_param     		= aac_biosparm,	
 	.shost_attrs			= aac_attrs,
 	.slave_configure		= aac_slave_configure,
+	.change_queue_depth		= aac_change_queue_depth,
 	.eh_abort_handler		= aac_eh_abort,
 	.eh_host_reset_handler		= aac_eh_reset,
 	.can_queue      		= AAC_NUM_IO_FIB,	
@@ -863,6 +943,14 @@
 	.emulated                       = 1,
 };
 
+static void __aac_shutdown(struct aac_dev * aac)
+{
+	kthread_stop(aac->thread);
+	aac_send_shutdown(aac);
+	aac_adapter_disable_int(aac);
+	free_irq(aac->pdev->irq, aac);
+}
+
 static int __devinit aac_probe_one(struct pci_dev *pdev,
 		const struct pci_device_id *id)
 {
@@ -1015,10 +1103,7 @@
 	return 0;
 
  out_deinit:
-	kthread_stop(aac->thread);
-	aac_send_shutdown(aac);
-	aac_adapter_disable_int(aac);
-	free_irq(pdev->irq, aac);
+	__aac_shutdown(aac);
  out_unmap:
 	aac_fib_map_free(aac);
 	pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
@@ -1038,7 +1123,8 @@
 {
 	struct Scsi_Host *shost = pci_get_drvdata(dev);
 	struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
-	aac_send_shutdown(aac);
+	scsi_block_requests(shost);
+	__aac_shutdown(aac);
 }
 
 static void __devexit aac_remove_one(struct pci_dev *pdev)
@@ -1048,16 +1134,12 @@
 
 	scsi_remove_host(shost);
 
-	kthread_stop(aac->thread);
-
-	aac_send_shutdown(aac);
-	aac_adapter_disable_int(aac);
+	__aac_shutdown(aac);
 	aac_fib_map_free(aac);
 	pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
 			aac->comm_phys);
 	kfree(aac->queues);
 
-	free_irq(pdev->irq, aac);
 	aac_adapter_ioremap(aac, 0);
 	
 	kfree(aac->fibs);
@@ -1084,7 +1166,7 @@
 {
 	int error;
 	
-	printk(KERN_INFO "Adaptec %s driver (%s)\n",
+	printk(KERN_INFO "Adaptec %s driver %s\n",
 	  AAC_DRIVERNAME, aac_driver_version);
 
 	error = pci_register_driver(&aac_pci_driver);
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 291cd14..ebc65b9 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -378,7 +378,7 @@
  *
  *	Will send a fib, returning 0 if successful.
  */
-static int aac_rx_deliver_producer(struct fib * fib)
+int aac_rx_deliver_producer(struct fib * fib)
 {
 	struct aac_dev *dev = fib->dev;
 	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
@@ -464,21 +464,24 @@
 {
 	u32 var;
 
-	if (bled)
-		printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
-			dev->name, dev->id, bled);
-	else {
-		bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
-		  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
-		if (!bled && (var != 0x00000001))
-			bled = -EINVAL;
-	}
-	if (bled && (bled != -ETIMEDOUT))
-		bled = aac_adapter_sync_cmd(dev, IOP_RESET,
-		  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
+	if (!(dev->supplement_adapter_info.SupportedOptions2 &
+	  le32_to_cpu(AAC_OPTION_MU_RESET)) || (bled >= 0) || (bled == -2)) {
+		if (bled)
+			printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
+				dev->name, dev->id, bled);
+		else {
+			bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
+			  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
+			if (!bled && (var != 0x00000001))
+				bled = -EINVAL;
+		}
+		if (bled && (bled != -ETIMEDOUT))
+			bled = aac_adapter_sync_cmd(dev, IOP_RESET,
+			  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
 
-	if (bled && (bled != -ETIMEDOUT))
-		return -EINVAL;
+		if (bled && (bled != -ETIMEDOUT))
+			return -EINVAL;
+	}
 	if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */
 		rx_writel(dev, MUnit.reserved2, 3);
 		msleep(5000); /* Delay 5 seconds */
@@ -488,6 +491,8 @@
 		return -EINVAL;
 	if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
 		return -ENODEV;
+	if (startup_timeout < 300)
+		startup_timeout = 300;
 	return 0;
 }
 
@@ -542,7 +547,7 @@
 	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
 	dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
 	dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
-	if ((((status & 0x0c) != 0x0c) || reset_devices) &&
+	if ((((status & 0x0c) != 0x0c) || aac_reset_devices || reset_devices) &&
 	  !aac_rx_restart_adapter(dev, 0))
 		++restart;
 	/*
@@ -594,6 +599,8 @@
 		}
 		msleep(1);
 	}
+	if (restart && aac_commit)
+		aac_commit = 1;
 	/*
 	 *	Fill in the common function dispatch table.
 	 */
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index f4b5e97..85b91bc 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -257,6 +257,11 @@
 			NULL, NULL, NULL, NULL, NULL);
 }
 
+static int aac_sa_restart_adapter(struct aac_dev *dev, int bled)
+{
+	return -EINVAL;
+}
+
 /**
  *	aac_sa_check_health
  *	@dev: device to check if healthy
@@ -366,7 +371,9 @@
 	dev->a_ops.adapter_notify = aac_sa_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_sa_check_health;
+	dev->a_ops.adapter_restart = aac_sa_restart_adapter;
 	dev->a_ops.adapter_intr = aac_sa_intr;
+	dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
 	dev->a_ops.adapter_ioremap = aac_sa_ioremap;
 
 	/*
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 9b3303b..2b66897 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -798,7 +798,6 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
-#include "advansys.h"
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 #endif /* CONFIG_PCI */
@@ -2014,7 +2013,7 @@
 STATIC void      AscEnableIsaDma(uchar);
 #endif /* CONFIG_ISA */
 STATIC ASC_DCNT  AscGetMaxDmaCount(ushort);
-
+static const char *advansys_info(struct Scsi_Host *shp);
 
 /*
  * --- Adv Library Constants and Macros
@@ -3970,10 +3969,6 @@
     ASC_IS_PCI,
 };
 
-/*
- * Used with the LILO 'advansys' option to eliminate or
- * limit I/O port probing at boot time, cf. advansys_setup().
- */
 STATIC int asc_iopflag = ASC_FALSE;
 STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
 
@@ -4055,10 +4050,6 @@
 #endif /* ADVANSYS_DEBUG */
 
 
-/*
- * --- Linux 'struct scsi_host_template' and advansys_setup() Functions
- */
-
 #ifdef CONFIG_PROC_FS
 /*
  * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
@@ -4080,7 +4071,7 @@
  * if 'prtbuf' is too small it will not be overwritten. Instead the
  * user just won't get all the available statistics.
  */
-int
+static int
 advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
 		off_t offset, int length, int inout)
 {
@@ -4296,7 +4287,7 @@
  * it must not call SCSI mid-level functions including scsi_malloc()
  * and scsi_free().
  */
-int __init
+static int __init
 advansys_detect(struct scsi_host_template *tpnt)
 {
     static int          detect_called = ASC_FALSE;
@@ -5428,7 +5419,7 @@
  *
  * Release resources allocated for a single AdvanSys adapter.
  */
-int
+static int
 advansys_release(struct Scsi_Host *shp)
 {
     asc_board_t    *boardp;
@@ -5475,7 +5466,7 @@
  * Note: The information line should not exceed ASC_INFO_SIZE bytes,
  * otherwise the static 'info' array will be overrun.
  */
-const char *
+static const char *
 advansys_info(struct Scsi_Host *shp)
 {
     static char     info[ASC_INFO_SIZE];
@@ -5568,7 +5559,7 @@
  * This function always returns 0. Command return status is saved
  * in the 'scp' result field.
  */
-int
+static int
 advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 {
     struct Scsi_Host    *shp;
@@ -5656,7 +5647,7 @@
  * sleeping is allowed and no locking other than for host structures is
  * required. Returns SUCCESS or FAILED.
  */
-int
+static int
 advansys_reset(struct scsi_cmnd *scp)
 {
     struct Scsi_Host     *shp;
@@ -5841,7 +5832,7 @@
  * ip[1]: sectors
  * ip[2]: cylinders
  */
-int
+static int
 advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 		sector_t capacity, int ip[])
 {
@@ -5875,82 +5866,6 @@
 }
 
 /*
- * advansys_setup()
- *
- * This function is called from init/main.c at boot time.
- * It it passed LILO parameters that can be set from the
- * LILO command line or in /etc/lilo.conf.
- *
- * It is used by the AdvanSys driver to either disable I/O
- * port scanning or to limit scanning to 1 - 4 I/O ports.
- * Regardless of the option setting EISA and PCI boards
- * will still be searched for and detected. This option
- * only affects searching for ISA and VL boards.
- *
- * If ADVANSYS_DEBUG is defined the driver debug level may
- * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
- *
- * Examples:
- * 1. Eliminate I/O port scanning:
- *         boot: linux advansys=
- *       or
- *         boot: linux advansys=0x0
- * 2. Limit I/O port scanning to one I/O port:
- *        boot: linux advansys=0x110
- * 3. Limit I/O port scanning to four I/O ports:
- *        boot: linux advansys=0x110,0x210,0x230,0x330
- * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
- *    set the driver debug level to 2.
- *        boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
- *
- * ints[0] - number of arguments
- * ints[1] - first argument
- * ints[2] - second argument
- * ...
- */
-void __init
-advansys_setup(char *str, int *ints)
-{
-    int    i;
-
-    if (asc_iopflag == ASC_TRUE) {
-        printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
-        return;
-    }
-
-    asc_iopflag = ASC_TRUE;
-
-    if (ints[0] > ASC_NUM_IOPORT_PROBE) {
-#ifdef ADVANSYS_DEBUG
-        if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
-            (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
-            asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
-        } else {
-#endif /* ADVANSYS_DEBUG */
-            printk("AdvanSys SCSI: only %d I/O ports accepted\n",
-                ASC_NUM_IOPORT_PROBE);
-#ifdef ADVANSYS_DEBUG
-        }
-#endif /* ADVANSYS_DEBUG */
-    }
-
-#ifdef ADVANSYS_DEBUG
-    ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
-    for (i = 1; i < ints[0]; i++) {
-        ASC_DBG2(1, " ints[%d] 0x%x", i, ints[i]);
-    }
-    ASC_DBG(1, "\n");
-#endif /* ADVANSYS_DEBUG */
-
-    for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
-        asc_ioport[i-1] = ints[i];
-        ASC_DBG2(1, "advansys_setup: asc_ioport[%d] 0x%x\n",
-            i - 1, asc_ioport[i-1]);
-    }
-}
-
-
-/*
  * --- Loadable Driver Support
  */
 
diff --git a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h
deleted file mode 100644
index 8ee7fb1..0000000
--- a/drivers/scsi/advansys.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters
- * 
- * Copyright (c) 1995-2000 Advanced System Products, Inc.
- * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
- * changed its name to ConnectCom Solutions, Inc.
- *
- */
-
-#ifndef _ADVANSYS_H
-#define _ADVANSYS_H
-
-/*
- * struct scsi_host_template function prototypes.
- */
-int advansys_detect(struct scsi_host_template *);
-int advansys_release(struct Scsi_Host *);
-const char *advansys_info(struct Scsi_Host *);
-int advansys_queuecommand(struct scsi_cmnd *, void (* done)(struct scsi_cmnd *));
-int advansys_reset(struct scsi_cmnd *);
-int advansys_biosparam(struct scsi_device *, struct block_device *,
-		sector_t, int[]);
-static int advansys_slave_configure(struct scsi_device *);
-
-/* init/main.c setup function */
-void advansys_setup(char *, int *);
-
-#endif /* _ADVANSYS_H */
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 4b4d123..85f2394 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -240,6 +240,7 @@
 #include <linux/io.h>
 #include <linux/blkdev.h>
 #include <asm/system.h>
+#include <linux/completion.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/wait.h>
@@ -253,7 +254,6 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/list.h>
-#include <asm/semaphore.h>
 #include <scsi/scsicam.h>
 
 #include "scsi.h"
@@ -551,7 +551,7 @@
  */
 struct aha152x_scdata {
 	Scsi_Cmnd *next;	/* next sc in queue */
-	struct semaphore *sem;	/* semaphore to block on */
+	struct completion *done;/* semaphore to block on */
 	unsigned char cmd_len;
 	unsigned char cmnd[MAX_COMMAND_SIZE];
 	unsigned short use_sg;
@@ -608,7 +608,7 @@
 
 #define SCDATA(SCpnt)		((struct aha152x_scdata *) (SCpnt)->host_scribble)
 #define SCNEXT(SCpnt)		SCDATA(SCpnt)->next
-#define SCSEM(SCpnt)		SCDATA(SCpnt)->sem
+#define SCSEM(SCpnt)		SCDATA(SCpnt)->done
 
 #define SG_ADDRESS(buffer)	((char *) (page_address((buffer)->page)+(buffer)->offset))
 
@@ -969,7 +969,8 @@
 /* 
  *  Queue a command and setup interrupts for a free bus.
  */
-static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, void (*done)(Scsi_Cmnd *))
+static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
+		int phase, void (*done)(Scsi_Cmnd *))
 {
 	struct Scsi_Host *shpnt = SCpnt->device->host;
 	unsigned long flags;
@@ -1013,7 +1014,7 @@
 	}
 
 	SCNEXT(SCpnt)		= NULL;
-	SCSEM(SCpnt)		= sem;
+	SCSEM(SCpnt)		= complete;
 
 	/* setup scratch area
 	   SCp.ptr              : buffer pointer
@@ -1084,9 +1085,9 @@
 	DPRINTK(debug_eh, INFO_LEAD "reset_done called\n", CMDINFO(SCpnt));
 #endif
 	if(SCSEM(SCpnt)) {
-		up(SCSEM(SCpnt));
+		complete(SCSEM(SCpnt));
 	} else {
-		printk(KERN_ERR "aha152x: reset_done w/o semaphore\n");
+		printk(KERN_ERR "aha152x: reset_done w/o completion\n");
 	}
 }
 
@@ -1139,21 +1140,6 @@
 	return FAILED;
 }
 
-static void timer_expired(unsigned long p)
-{
-	Scsi_Cmnd	 *SCp   = (Scsi_Cmnd *)p;
-	struct semaphore *sem   = SCSEM(SCp);
-	struct Scsi_Host *shpnt = SCp->device->host;
-	unsigned long flags;
-
-	/* remove command from issue queue */
-	DO_LOCK(flags);
-	remove_SC(&ISSUE_SC, SCp);
-	DO_UNLOCK(flags);
-
-	up(sem);
-}
-
 /*
  * Reset a device
  *
@@ -1161,14 +1147,14 @@
 static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
 {
 	struct Scsi_Host *shpnt = SCpnt->device->host;
-	DECLARE_MUTEX_LOCKED(sem);
-	struct timer_list timer;
+	DECLARE_COMPLETION(done);
 	int ret, issued, disconnected;
 	unsigned char old_cmd_len = SCpnt->cmd_len;
 	unsigned short old_use_sg = SCpnt->use_sg;
 	void *old_buffer = SCpnt->request_buffer;
 	unsigned old_bufflen = SCpnt->request_bufflen;
 	unsigned long flags;
+	unsigned long timeleft;
 
 #if defined(AHA152X_DEBUG)
 	if(HOSTDATA(shpnt)->debug & debug_eh) {
@@ -1192,15 +1178,15 @@
 	SCpnt->request_buffer  = NULL;
 	SCpnt->request_bufflen = 0;
 
-	init_timer(&timer);
-	timer.data     = (unsigned long) SCpnt;
-	timer.expires  = jiffies + 100*HZ;   /* 10s */
-	timer.function = (void (*)(unsigned long)) timer_expired;
+	aha152x_internal_queue(SCpnt, &done, resetting, reset_done);
 
-	aha152x_internal_queue(SCpnt, &sem, resetting, reset_done);
-	add_timer(&timer);
-	down(&sem);
-	del_timer(&timer);
+	timeleft = wait_for_completion_timeout(&done, 100*HZ);
+	if (!timeleft) {
+		/* remove command from issue queue */
+		DO_LOCK(flags);
+		remove_SC(&ISSUE_SC, SCpnt);
+		DO_UNLOCK(flags);
+	}
 
 	SCpnt->cmd_len         = old_cmd_len;
 	SCpnt->use_sg          = old_use_sg;
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index d7af9c6..e4a4f3a 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -271,20 +271,8 @@
 				continue;
 			}
 			sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
-			if (SCtmp->use_sg) {
-				/* We used scatter-gather.
-				   Do the unmapping dance. */
-				dma_unmap_sg (&edev->dev,
-					      (struct scatterlist *) SCtmp->request_buffer,
-					      SCtmp->use_sg,
-					      SCtmp->sc_data_direction);
-			} else {
-				dma_unmap_single (&edev->dev,
-						  sgptr->buf_dma_addr,
-						  SCtmp->request_bufflen,
-						  DMA_BIDIRECTIONAL);
-			}
-	    
+			scsi_dma_unmap(SCtmp);
+
 			/* Free the sg block */
 			dma_free_coherent (&edev->dev,
 					   sizeof (struct aha1740_sg),
@@ -349,11 +337,9 @@
 	unchar target = scmd_id(SCpnt);
 	struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
 	unsigned long flags;
-	void *buff = SCpnt->request_buffer;
-	int bufflen = SCpnt->request_bufflen;
 	dma_addr_t sg_dma;
 	struct aha1740_sg *sgptr;
-	int ecbno;
+	int ecbno, nseg;
 	DEB(int i);
 
 	if(*cmd == REQUEST_SENSE) {
@@ -423,24 +409,23 @@
 	}
 	sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
 	sgptr->sg_dma_addr = sg_dma;
-    
-	if (SCpnt->use_sg) {
-		struct scatterlist * sgpnt;
+
+	nseg = scsi_dma_map(SCpnt);
+	BUG_ON(nseg < 0);
+	if (nseg) {
+		struct scatterlist *sg;
 		struct aha1740_chain * cptr;
-		int i, count;
+		int i;
 		DEB(unsigned char * ptr);
 
 		host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
 					   * w/scatter-gather*/
-		sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 		cptr = sgptr->sg_chain;
-		count = dma_map_sg (&host->edev->dev, sgpnt, SCpnt->use_sg,
-				    SCpnt->sc_data_direction);
-		for(i=0; i < count; i++) {
-			cptr[i].datalen = sg_dma_len (sgpnt + i);
-			cptr[i].dataptr = sg_dma_address (sgpnt + i);
+		scsi_for_each_sg(SCpnt, sg, nseg, i) {
+			cptr[i].datalen = sg_dma_len (sg);
+			cptr[i].dataptr = sg_dma_address (sg);
 		}
-		host->ecb[ecbno].datalen = count*sizeof(struct aha1740_chain);
+		host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
 		host->ecb[ecbno].dataptr = sg_dma;
 #ifdef DEBUG
 		printk("cptr %x: ",cptr);
@@ -448,11 +433,8 @@
 		for(i=0;i<24;i++) printk("%02x ", ptr[i]);
 #endif
 	} else {
-		host->ecb[ecbno].datalen = bufflen;
-		sgptr->buf_dma_addr =  dma_map_single (&host->edev->dev,
-						       buff, bufflen,
-						       DMA_BIDIRECTIONAL);
-		host->ecb[ecbno].dataptr = sgptr->buf_dma_addr;
+		host->ecb[ecbno].datalen = 0;
+		host->ecb[ecbno].dataptr = 0;
 	}
 	host->ecb[ecbno].lun = SCpnt->device->lun;
 	host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 9ddc6e4..05f692b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -5180,7 +5180,7 @@
 			cur_lun = lun;
 			max_lun = lun;
 		}
-		for (cur_lun <= max_lun; cur_lun++) {
+		for (;cur_lun <= max_lun; cur_lun++) {
 			struct ahd_tmode_lstate* lstate;
 
 			lstate = tstate->enabled_luns[cur_lun];
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 6054881..286ab83 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -376,21 +376,10 @@
 ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
 {
 	struct scsi_cmnd *cmd;
-	int direction;
 
 	cmd = scb->io_ctx;
-	direction = cmd->sc_data_direction;
 	ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
-	if (cmd->use_sg != 0) {
-		struct scatterlist *sg;
-
-		sg = (struct scatterlist *)cmd->request_buffer;
-		pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction);
-	} else if (cmd->request_bufflen != 0) {
-		pci_unmap_single(ahd->dev_softc,
-				 scb->platform_data->buf_busaddr,
-				 cmd->request_bufflen, direction);
-	}
+	scsi_dma_unmap(cmd);
 }
 
 /******************************** Macros **************************************/
@@ -1422,6 +1411,7 @@
 	u_int	 col_idx;
 	uint16_t mask;
 	unsigned long flags;
+	int nseg;
 
 	ahd_lock(ahd, &flags);
 
@@ -1494,18 +1484,17 @@
 	ahd_set_residual(scb, 0);
 	ahd_set_sense_residual(scb, 0);
 	scb->sg_count = 0;
-	if (cmd->use_sg != 0) {
-		void	*sg;
-		struct	 scatterlist *cur_seg;
-		u_int	 nseg;
-		int	 dir;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		dir = cmd->sc_data_direction;
-		nseg = pci_map_sg(ahd->dev_softc, cur_seg,
-				  cmd->use_sg, dir);
+	nseg = scsi_dma_map(cmd);
+	BUG_ON(nseg < 0);
+	if (nseg > 0) {
+		void *sg = scb->sg_list;
+		struct scatterlist *cur_seg;
+		int i;
+
 		scb->platform_data->xfer_len = 0;
-		for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
+
+		scsi_for_each_sg(cmd, cur_seg, nseg, i) {
 			dma_addr_t addr;
 			bus_size_t len;
 
@@ -1513,22 +1502,8 @@
 			len = sg_dma_len(cur_seg);
 			scb->platform_data->xfer_len += len;
 			sg = ahd_sg_setup(ahd, scb, sg, addr, len,
-					  /*last*/nseg == 1);
+					  i == (nseg - 1));
 		}
-	} else if (cmd->request_bufflen != 0) {
-		void *sg;
-		dma_addr_t addr;
-		int dir;
-
-		sg = scb->sg_list;
-		dir = cmd->sc_data_direction;
-		addr = pci_map_single(ahd->dev_softc,
-				      cmd->request_buffer,
-				      cmd->request_bufflen, dir);
-		scb->platform_data->xfer_len = cmd->request_bufflen;
-		scb->platform_data->buf_busaddr = addr;
-		sg = ahd_sg_setup(ahd, scb, sg, addr,
-				  cmd->request_bufflen, /*last*/TRUE);
 	}
 
 	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index ad9761b..853998b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -781,7 +781,7 @@
 static __inline
 void ahd_set_residual(struct scb *scb, u_long resid)
 {
-	scb->io_ctx->resid = resid;
+	scsi_set_resid(scb->io_ctx, resid);
 }
 
 static __inline
@@ -793,7 +793,7 @@
 static __inline
 u_long ahd_get_residual(struct scb *scb)
 {
-	return (scb->io_ctx->resid);
+	return scsi_get_resid(scb->io_ctx);
 }
 
 static __inline
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 660f26e..1803ab6 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -402,18 +402,8 @@
 
 	cmd = scb->io_ctx;
 	ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE);
-	if (cmd->use_sg != 0) {
-		struct scatterlist *sg;
 
-		sg = (struct scatterlist *)cmd->request_buffer;
-		pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg,
-			     cmd->sc_data_direction);
-	} else if (cmd->request_bufflen != 0) {
-		pci_unmap_single(ahc->dev_softc,
-				 scb->platform_data->buf_busaddr,
-				 cmd->request_bufflen,
-				 cmd->sc_data_direction);
-	}
+	scsi_dma_unmap(cmd);
 }
 
 static __inline int
@@ -1381,6 +1371,7 @@
 	struct	 ahc_tmode_tstate *tstate;
 	uint16_t mask;
 	struct scb_tailq *untagged_q = NULL;
+	int nseg;
 
 	/*
 	 * Schedule us to run later.  The only reason we are not
@@ -1472,23 +1463,21 @@
 	ahc_set_residual(scb, 0);
 	ahc_set_sense_residual(scb, 0);
 	scb->sg_count = 0;
-	if (cmd->use_sg != 0) {
+
+	nseg = scsi_dma_map(cmd);
+	BUG_ON(nseg < 0);
+	if (nseg > 0) {
 		struct	ahc_dma_seg *sg;
 		struct	scatterlist *cur_seg;
-		struct	scatterlist *end_seg;
-		int	nseg;
+		int i;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
-				  cmd->sc_data_direction);
-		end_seg = cur_seg + nseg;
 		/* Copy the segments into the SG list. */
 		sg = scb->sg_list;
 		/*
 		 * The sg_count may be larger than nseg if
 		 * a transfer crosses a 32bit page.
-		 */ 
-		while (cur_seg < end_seg) {
+		 */
+		scsi_for_each_sg(cmd, cur_seg, nseg, i) {
 			dma_addr_t addr;
 			bus_size_t len;
 			int consumed;
@@ -1499,7 +1488,6 @@
 						     sg, addr, len);
 			sg += consumed;
 			scb->sg_count += consumed;
-			cur_seg++;
 		}
 		sg--;
 		sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
@@ -1516,33 +1504,6 @@
 		 */
 		scb->hscb->dataptr = scb->sg_list->addr;
 		scb->hscb->datacnt = scb->sg_list->len;
-	} else if (cmd->request_bufflen != 0) {
-		struct	 ahc_dma_seg *sg;
-		dma_addr_t addr;
-
-		sg = scb->sg_list;
-		addr = pci_map_single(ahc->dev_softc,
-				      cmd->request_buffer,
-				      cmd->request_bufflen,
-				      cmd->sc_data_direction);
-		scb->platform_data->buf_busaddr = addr;
-		scb->sg_count = ahc_linux_map_seg(ahc, scb,
-						  sg, addr,
-						  cmd->request_bufflen);
-		sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
-
-		/*
-		 * Reset the sg list pointer.
-		 */
-		scb->hscb->sgptr =
-			ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
-
-		/*
-		 * Copy the first SG into the "current"
-		 * data pointer area.
-		 */
-		scb->hscb->dataptr = sg->addr;
-		scb->hscb->datacnt = sg->len;
 	} else {
 		scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
 		scb->hscb->dataptr = 0;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 8fee7ed..b48dab4 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -751,7 +751,7 @@
 static __inline
 void ahc_set_residual(struct scb *scb, u_long resid)
 {
-	scb->io_ctx->resid = resid;
+	scsi_set_resid(scb->io_ctx, resid);
 }
 
 static __inline
@@ -763,7 +763,7 @@
 static __inline
 u_long ahc_get_residual(struct scb *scb)
 {
-	return (scb->io_ctx->resid);
+	return scsi_get_resid(scb->io_ctx);
 }
 
 static __inline
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
index c328596..6066998 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
@@ -106,6 +106,7 @@
 static void add_conditional(symbol_t *symbol);
 static void add_version(const char *verstring);
 static int  is_download_const(expression_t *immed);
+void yyerror(const char *string);
 
 #define SRAM_SYMNAME "SRAM_BASE"
 #define SCB_SYMNAME "SCB_BASE"
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
index 439f760..ff46aa6 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
@@ -65,6 +65,7 @@
 static symbol_t *macro_symbol;
 
 static void add_macro_arg(const char *argtext, int position);
+void mmerror(const char *string);
 
 %}
 
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index a988d5a..4998bb8 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -2690,17 +2690,8 @@
 	struct aic7xxx_scb *scbp;
 	unsigned char queue_depth;
 
-  if (cmd->use_sg > 1)
-  {
-    struct scatterlist *sg;
+        scsi_dma_unmap(cmd);
 
-    sg = (struct scatterlist *)cmd->request_buffer;
-    pci_unmap_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
-  }
-  else if (cmd->request_bufflen)
-    pci_unmap_single(p->pdev, aic7xxx_mapping(cmd),
-		     cmd->request_bufflen,
-                     cmd->sc_data_direction);
   if (scb->flags & SCB_SENSE)
   {
     pci_unmap_single(p->pdev,
@@ -3869,7 +3860,7 @@
        * the mid layer didn't check residual data counts to see if the
        * command needs retried.
        */
-      cmd->resid = scb->sg_length - actual;
+      scsi_set_resid(cmd, scb->sg_length - actual);
       aic7xxx_status(cmd) = hscb->target_status;
     }
   }
@@ -6581,7 +6572,7 @@
   struct aic7xxx_host *p = (struct aic7xxx_host *)SDptr->host->hostdata;
   struct aic_dev_data *aic_dev;
 
-  aic_dev = kmalloc(sizeof(struct aic_dev_data), GFP_ATOMIC | GFP_KERNEL);
+  aic_dev = kmalloc(sizeof(struct aic_dev_data), GFP_KERNEL);
   if(!aic_dev)
     return 1;
   /*
@@ -10137,6 +10128,7 @@
   struct scsi_device *sdptr = cmd->device;
   unsigned char tindex = TARGET_INDEX(cmd);
   struct request *req = cmd->request;
+  int use_sg;
 
   mask = (0x01 << tindex);
   hscb = scb->hscb;
@@ -10209,8 +10201,10 @@
   memcpy(scb->cmnd, cmd->cmnd, cmd->cmd_len);
   hscb->SCSI_cmd_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, scb->cmnd));
 
-  if (cmd->use_sg)
-  {
+  use_sg = scsi_dma_map(cmd);
+  BUG_ON(use_sg < 0);
+
+  if (use_sg) {
     struct scatterlist *sg;  /* Must be mid-level SCSI code scatterlist */
 
     /*
@@ -10219,11 +10213,11 @@
      * differences and the kernel SG list uses virtual addresses where
      * we need physical addresses.
      */
-    int i, use_sg;
+    int i;
 
-    sg = (struct scatterlist *)cmd->request_buffer;
     scb->sg_length = 0;
-    use_sg = pci_map_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
+
+
     /*
      * Copy the segments into the SG array.  NOTE!!! - We used to
      * have the first entry both in the data_pointer area and the first
@@ -10231,10 +10225,9 @@
      * entry in both places, but now we download the address of
      * scb->sg_list[1] instead of 0 to the sg pointer in the hscb.
      */
-    for (i = 0; i < use_sg; i++)
-    {
-      unsigned int len = sg_dma_len(sg+i);
-      scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg+i));
+    scsi_for_each_sg(cmd, sg, use_sg, i) {
+      unsigned int len = sg_dma_len(sg);
+      scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg));
       scb->sg_list[i].length = cpu_to_le32(len);
       scb->sg_length += len;
     }
@@ -10244,33 +10237,13 @@
     scb->sg_count = i;
     hscb->SG_segment_count = i;
     hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[1]));
-  }
-  else
-  {
-    if (cmd->request_bufflen)
-    {
-      unsigned int address = pci_map_single(p->pdev, cmd->request_buffer,
-					    cmd->request_bufflen,
-                                            cmd->sc_data_direction);
-      aic7xxx_mapping(cmd) = address;
-      scb->sg_list[0].address = cpu_to_le32(address);
-      scb->sg_list[0].length = cpu_to_le32(cmd->request_bufflen);
-      scb->sg_count = 1;
-      scb->sg_length = cmd->request_bufflen;
-      hscb->SG_segment_count = 1;
-      hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[0]));
-      hscb->data_count = scb->sg_list[0].length;
-      hscb->data_pointer = scb->sg_list[0].address;
-    }
-    else
-    {
+  } else {
       scb->sg_count = 0;
       scb->sg_length = 0;
       hscb->SG_segment_count = 0;
       hscb->SG_list_pointer = 0;
       hscb->data_count = 0;
       hscb->data_pointer = 0;
-    }
   }
 }
 
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 27852b4..1c0d757 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -223,13 +223,8 @@
 {
 	int err, i;
 
-	err = pci_read_config_byte(asd_ha->pcidev, PCI_REVISION_ID,
-				   &asd_ha->revision_id);
-	if (err) {
-		asd_printk("couldn't read REVISION ID register of %s\n",
-			   pci_name(asd_ha->pcidev));
-		goto Err;
-	}
+	asd_ha->revision_id = asd_ha->pcidev->revision;
+
 	err = -ENODEV;
 	if (asd_ha->revision_id < AIC9410_DEV_REV_B0) {
 		asd_printk("%s is revision %s (%X), which is not supported\n",
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index 9a14a6d..c0d0b7d 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -290,6 +290,7 @@
 static inline int asd_clear_nexus(struct sas_task *task)
 {
 	int res = TMF_RESP_FUNC_FAILED;
+	int leftover;
 	struct asd_ascb *tascb = task->lldd_task;
 	unsigned long flags;
 
@@ -298,10 +299,12 @@
 		res = asd_clear_nexus_tag(task);
 	else
 		res = asd_clear_nexus_index(task);
-	wait_for_completion_timeout(&tascb->completion,
-				    AIC94XX_SCB_TIMEOUT);
+	leftover = wait_for_completion_timeout(&tascb->completion,
+					       AIC94XX_SCB_TIMEOUT);
 	ASD_DPRINTK("came back from clear nexus\n");
 	spin_lock_irqsave(&task->task_state_lock, flags);
+	if (leftover < 1)
+		res = TMF_RESP_FUNC_FAILED;
 	if (task->task_state_flags & SAS_TASK_STATE_DONE)
 		res = TMF_RESP_FUNC_COMPLETE;
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -350,6 +353,7 @@
 	unsigned long flags;
 	struct asd_ascb *ascb = NULL;
 	struct scb *scb;
+	int leftover;
 
 	spin_lock_irqsave(&task->task_state_lock, flags);
 	if (task->task_state_flags & SAS_TASK_STATE_DONE) {
@@ -455,9 +459,11 @@
 		break;
 	case TF_TMF_TASK_DONE + 0xFF00:	/* done but not reported yet */
 		res = TMF_RESP_FUNC_FAILED;
-		wait_for_completion_timeout(&tascb->completion,
-					    AIC94XX_SCB_TIMEOUT);
+		leftover = wait_for_completion_timeout(&tascb->completion,
+						       AIC94XX_SCB_TIMEOUT);
 		spin_lock_irqsave(&task->task_state_lock, flags);
+		if (leftover < 1)
+			res = TMF_RESP_FUNC_FAILED;
 		if (task->task_state_flags & SAS_TASK_STATE_DONE)
 			res = TMF_RESP_FUNC_COMPLETE;
 		spin_unlock_irqrestore(&task->task_state_lock, flags);
diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c
deleted file mode 100644
index d5d3c4d..0000000
--- a/drivers/scsi/amiga7xx.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
- *		Amiga MacroSystemUS WarpEngine SCSI controller.
- *		Amiga Technologies A4000T SCSI controller.
- *		Amiga Technologies/DKB A4091 SCSI controller.
- *
- * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
- * plus modifications of the 53c7xx.c driver to support the Amiga.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/zorro.h>
-#include <linux/stat.h>
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/dma.h>
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "53c7xx.h"
-#include "amiga7xx.h"
-
-
-static int amiga7xx_register_one(struct scsi_host_template *tpnt,
-				 unsigned long address)
-{
-    long long options;
-    int clock;
-
-    if (!request_mem_region(address, 0x1000, "ncr53c710"))
-	return 0;
-
-    address = (unsigned long)z_ioremap(address, 0x1000);
-    options = OPTION_MEMORY_MAPPED | OPTION_DEBUG_TEST1 | OPTION_INTFLY |
-	      OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS |
-	      OPTION_DISCONNECT;
-    clock = 50000000;	/* 50 MHz SCSI Clock */
-    ncr53c7xx_init(tpnt, 0, 710, address, 0, IRQ_AMIGA_PORTS, DMA_NONE,
-		   options, clock);
-    return 1;
-}
-
-
-#ifdef CONFIG_ZORRO
-
-static struct {
-    zorro_id id;
-    unsigned long offset;
-    int absolute;	/* offset is absolute address */
-} amiga7xx_table[] = {
-    { .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, .offset = 0xf40000,
-      .absolute = 1 },
-    { .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, .offset = 0x40000 },
-    { .id = ZORRO_PROD_CBM_A4091_1, .offset = 0x800000 },
-    { .id = ZORRO_PROD_CBM_A4091_2, .offset = 0x800000 },
-    { .id = ZORRO_PROD_GVP_GFORCE_040_060, .offset = 0x40000 },
-    { 0 }
-};
-
-static int __init amiga7xx_zorro_detect(struct scsi_host_template *tpnt)
-{
-    int num = 0, i;
-    struct zorro_dev *z = NULL;
-    unsigned long address;
-
-    while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-	for (i = 0; amiga7xx_table[i].id; i++)
-	    if (z->id == amiga7xx_table[i].id)
-		break;
-	if (!amiga7xx_table[i].id)
-	    continue;
-	if (amiga7xx_table[i].absolute)
-	    address = amiga7xx_table[i].offset;
-	else
-	    address = z->resource.start + amiga7xx_table[i].offset;
-	num += amiga7xx_register_one(tpnt, address);
-    }
-    return num;
-}
-
-#endif /* CONFIG_ZORRO */
-
-
-int __init amiga7xx_detect(struct scsi_host_template *tpnt)
-{
-    static unsigned char called = 0;
-    int num = 0;
-
-    if (called || !MACH_IS_AMIGA)
-	return 0;
-
-    tpnt->proc_name = "Amiga7xx";
-
-    if (AMIGAHW_PRESENT(A4000_SCSI))
-	num += amiga7xx_register_one(tpnt, 0xdd0040);
-
-#ifdef CONFIG_ZORRO
-    num += amiga7xx_zorro_detect(tpnt);
-#endif
-
-    called = 1;
-    return num;
-}
-
-static int amiga7xx_release(struct Scsi_Host *shost)
-{
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
-	return 0;
-}
-
-static struct scsi_host_template driver_template = {
-	.name			= "Amiga NCR53c710 SCSI",
-	.detect			= amiga7xx_detect,
-	.release		= amiga7xx_release,
-	.queuecommand		= NCR53c7xx_queue_command,
-	.abort			= NCR53c7xx_abort,
-	.reset			= NCR53c7xx_reset,
-	.can_queue		= 24,
-	.this_id		= 7,
-	.sg_tablesize		= 63,
-	.cmd_per_lun		= 3,
-	.use_clustering		= DISABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
diff --git a/drivers/scsi/amiga7xx.h b/drivers/scsi/amiga7xx.h
deleted file mode 100644
index 7cd63a9..0000000
--- a/drivers/scsi/amiga7xx.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef AMIGA7XX_H
-
-#include <linux/types.h>
-
-int amiga7xx_detect(struct scsi_host_template *);
-const char *NCR53c7x0_info(void);
-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int NCR53c7xx_abort(Scsi_Cmnd *);
-int NCR53c7x0_release (struct Scsi_Host *);
-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id);
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 3
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 24
-#endif
-
-#include <scsi/scsicam.h>
-
-#endif /* AMIGA7XX_H */
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index aff96db..f0b8bf4 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -48,9 +48,10 @@
 
 #define ARCMSR_MAX_OUTSTANDING_CMD 						256
 #define ARCMSR_MAX_FREECCB_NUM							288
-#define ARCMSR_DRIVER_VERSION				"Driver Version 1.20.00.13"
+#define ARCMSR_DRIVER_VERSION				"Driver Version 1.20.00.14"
 #define ARCMSR_SCSI_INITIATOR_ID						255
 #define ARCMSR_MAX_XFER_SECTORS							512
+#define ARCMSR_MAX_XFER_SECTORS_B                                              4096
 #define ARCMSR_MAX_TARGETID							 17
 #define ARCMSR_MAX_TARGETLUN							  8
 #define ARCMSR_MAX_CMD_PERLUN				 ARCMSR_MAX_OUTSTANDING_CMD
@@ -469,4 +470,3 @@
 extern struct class_device_attribute *arcmsr_host_attrs[];
 extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb);
 void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
-
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index 03bfed6..06c0dce 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -59,8 +59,9 @@
 struct class_device_attribute *arcmsr_host_attrs[];
 
 static ssize_t
-arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+arcmsr_sysfs_iop_message_read(struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t off, size_t count)
 {
 	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *host = class_to_shost(cdev);
@@ -105,8 +106,9 @@
 }
 
 static ssize_t
-arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+arcmsr_sysfs_iop_message_write(struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t off, size_t count)
 {
 	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *host = class_to_shost(cdev);
@@ -152,8 +154,9 @@
 }
 
 static ssize_t
-arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t off, size_t count)
 {
 	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *host = class_to_shost(cdev);
@@ -188,7 +191,6 @@
 	.attr = {
 		.name = "mu_read",
 		.mode = S_IRUSR ,
-		.owner = THIS_MODULE,
 	},
 	.size = 1032,
 	.read = arcmsr_sysfs_iop_message_read,
@@ -198,7 +200,6 @@
 	.attr = {
 		.name = "mu_write",
 		.mode = S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 1032,
 	.write = arcmsr_sysfs_iop_message_write,
@@ -208,7 +209,6 @@
 	.attr = {
 		.name = "mu_clear",
 		.mode = S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 1,
 	.write = arcmsr_sysfs_iop_message_clear,
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 8b46158..0ddfc21 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -57,6 +57,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/timer.h>
 #include <linux/pci.h>
+#include <linux/aer.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -71,7 +72,7 @@
 #include "arcmsr.h"
 
 MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>");
-MODULE_DESCRIPTION("ARECA (ARC11xx/12xx) SATA RAID HOST Adapter");
+MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(ARCMSR_DRIVER_VERSION);
 
@@ -93,7 +94,9 @@
 static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb);
 static const char *arcmsr_info(struct Scsi_Host *);
 static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
-
+static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
+						pci_channel_state_t state);
+static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev);
 static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth)
 {
 	if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
@@ -104,7 +107,8 @@
 
 static struct scsi_host_template arcmsr_scsi_host_template = {
 	.module			= THIS_MODULE,
-	.name			= "ARCMSR ARECA SATA RAID HOST Adapter" ARCMSR_DRIVER_VERSION,
+	.name			= "ARCMSR ARECA SATA/SAS RAID HOST Adapter"
+							ARCMSR_DRIVER_VERSION,
 	.info			= arcmsr_info,
 	.queuecommand		= arcmsr_queue_command,
 	.eh_abort_handler	= arcmsr_abort,
@@ -119,6 +123,10 @@
 	.use_clustering		= ENABLE_CLUSTERING,
 	.shost_attrs		= arcmsr_host_attrs,
 };
+static struct pci_error_handlers arcmsr_pci_error_handlers = {
+	.error_detected		= arcmsr_pci_error_detected,
+	.slot_reset		= arcmsr_pci_slot_reset,
+};
 
 static struct pci_device_id arcmsr_device_id_table[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
@@ -144,7 +152,8 @@
 	.id_table		= arcmsr_device_id_table,
 	.probe			= arcmsr_probe,
 	.remove			= arcmsr_remove,
-	.shutdown		= arcmsr_shutdown
+	.shutdown		= arcmsr_shutdown,
+	.err_handler		= &arcmsr_pci_error_handlers,
 };
 
 static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id)
@@ -328,6 +337,8 @@
 
 	arcmsr_iop_init(acb);
 	pci_set_drvdata(pdev, host);
+	if (strncmp(acb->firm_version, "V1.42", 5) >= 0)
+		host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B;
 
 	error = scsi_add_host(host, &pdev->dev);
 	if (error)
@@ -338,6 +349,7 @@
 		goto out_free_sysfs;
 
 	scsi_scan_host(host);
+	pci_enable_pcie_error_reporting(pdev);
 	return 0;
  out_free_sysfs:
  out_free_irq:
@@ -369,19 +381,9 @@
 
 static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb)
 {
-	struct AdapterControlBlock *acb = ccb->acb;
 	struct scsi_cmnd *pcmd = ccb->pcmd;
 
-	if (pcmd->use_sg != 0) {
-		struct scatterlist *sl;
-
-		sl = (struct scatterlist *)pcmd->request_buffer;
-		pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction);
-	}
-	else if (pcmd->request_bufflen != 0)
-		pci_unmap_single(acb->pdev,
-			pcmd->SCp.dma_handle,
-			pcmd->request_bufflen, pcmd->sc_data_direction);
+	scsi_dma_unmap(pcmd);
 }
 
 static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag)
@@ -498,7 +500,7 @@
 
 static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
 {
-	struct MessageUnit __iomem *reg=acb->pmu;
+	struct MessageUnit __iomem *reg = acb->pmu;
 
 	writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, &reg->inbound_msgaddr0);
 	if (arcmsr_wait_msgint_ready(acb))
@@ -551,6 +553,7 @@
 	int8_t *psge = (int8_t *)&arcmsr_cdb->u;
 	uint32_t address_lo, address_hi;
 	int arccdbsize = 0x30;
+	int nseg;
 
 	ccb->pcmd = pcmd;
 	memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB));
@@ -561,20 +564,20 @@
 	arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len;
 	arcmsr_cdb->Context = (unsigned long)arcmsr_cdb;
 	memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len);
-	if (pcmd->use_sg) {
-		int length, sgcount, i, cdb_sgcount = 0;
-		struct scatterlist *sl;
 
-		/* Get Scatter Gather List from scsiport. */
-		sl = (struct scatterlist *) pcmd->request_buffer;
-		sgcount = pci_map_sg(acb->pdev, sl, pcmd->use_sg,
-				pcmd->sc_data_direction);
+	nseg = scsi_dma_map(pcmd);
+	BUG_ON(nseg < 0);
+
+	if (nseg) {
+		int length, i, cdb_sgcount = 0;
+		struct scatterlist *sg;
+
 		/* map stor port SG list to our iop SG List. */
-		for (i = 0; i < sgcount; i++) {
+		scsi_for_each_sg(pcmd, sg, nseg, i) {
 			/* Get the physical address of the current data pointer */
-			length = cpu_to_le32(sg_dma_len(sl));
-			address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl)));
-			address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl)));
+			length = cpu_to_le32(sg_dma_len(sg));
+			address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sg)));
+			address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sg)));
 			if (address_hi == 0) {
 				struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
 
@@ -591,32 +594,12 @@
 				psge += sizeof (struct SG64ENTRY);
 				arccdbsize += sizeof (struct SG64ENTRY);
 			}
-			sl++;
 			cdb_sgcount++;
 		}
 		arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount;
-		arcmsr_cdb->DataLength = pcmd->request_bufflen;
+		arcmsr_cdb->DataLength = scsi_bufflen(pcmd);
 		if ( arccdbsize > 256)
 			arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
-	} else if (pcmd->request_bufflen) {
-		dma_addr_t dma_addr;
-		dma_addr = pci_map_single(acb->pdev, pcmd->request_buffer,
-				pcmd->request_bufflen, pcmd->sc_data_direction);
-		pcmd->SCp.dma_handle = dma_addr;
-		address_lo = cpu_to_le32(dma_addr_lo32(dma_addr));
-		address_hi = cpu_to_le32(dma_addr_hi32(dma_addr));
-		if (address_hi == 0) {
-			struct  SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
-			pdma_sg->address = address_lo;
-			pdma_sg->length = pcmd->request_bufflen;
-		} else {
-			struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge;
-			pdma_sg->addresshigh = address_hi;
-			pdma_sg->address = address_lo;
-			pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR;
-		}
-		arcmsr_cdb->sgcount = 1;
-		arcmsr_cdb->DataLength = pcmd->request_bufflen;
 	}
 	if (pcmd->sc_data_direction == DMA_TO_DEVICE ) {
 		arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
@@ -747,7 +730,7 @@
 		int id, lun;
 		/*
 		****************************************************************
-		**               areca cdb command done
+		**	      areca cdb command done
 		****************************************************************
 		*/
 		while (1) {
@@ -758,20 +741,20 @@
 				(flag_ccb << 5));
 			if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
 				if (ccb->startdone == ARCMSR_CCB_ABORTED) {
-					struct scsi_cmnd *abortcmd=ccb->pcmd;
+					struct scsi_cmnd *abortcmd = ccb->pcmd;
 					if (abortcmd) {
 					abortcmd->result |= DID_ABORT >> 16;
 					arcmsr_ccb_complete(ccb, 1);
 					printk(KERN_NOTICE
-						"arcmsr%d: ccb='0x%p' isr got aborted command \n"
+						"arcmsr%d: ccb ='0x%p' isr got aborted command \n"
 						, acb->host->host_no, ccb);
 					}
 					continue;
 				}
 				printk(KERN_NOTICE
-					"arcmsr%d: isr get an illegal ccb command done acb='0x%p'"
-					"ccb='0x%p' ccbacb='0x%p' startdone = 0x%x"
-					" ccboutstandingcount=%d \n"
+					"arcmsr%d: isr get an illegal ccb command done acb = '0x%p'"
+					"ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x"
+					" ccboutstandingcount = %d \n"
 					, acb->host->host_no
 					, acb
 					, ccb
@@ -791,7 +774,7 @@
 				switch(ccb->arcmsr_cdb.DeviceStatus) {
 				case ARCMSR_DEV_SELECT_TIMEOUT: {
 						acb->devstate[id][lun] = ARECA_RAID_GONE;
-						ccb->pcmd->result = DID_TIME_OUT << 16;
+						ccb->pcmd->result = DID_NO_CONNECT << 16;
 						arcmsr_ccb_complete(ccb, 1);
 					}
 					break;
@@ -810,8 +793,8 @@
 					break;
 				default:
 					printk(KERN_NOTICE
-						"arcmsr%d: scsi id=%d lun=%d"
-						" isr get command error done,"
+						"arcmsr%d: scsi id = %d lun = %d"
+						" isr get command error done, "
 						"but got unknown DeviceStatus = 0x%x \n"
 						, acb->host->host_no
 						, id
@@ -848,24 +831,21 @@
 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
 	int retvalue = 0, transfer_len = 0;
 	char *buffer;
+	struct scatterlist *sg;
 	uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 |
 						(uint32_t ) cmd->cmnd[6] << 16 |
 						(uint32_t ) cmd->cmnd[7] << 8  |
 						(uint32_t ) cmd->cmnd[8];
 					/* 4 bytes: Areca io control code */
-	if (cmd->use_sg) {
-		struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
 
-		buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-		if (cmd->use_sg > 1) {
-			retvalue = ARCMSR_MESSAGE_FAIL;
-			goto message_out;
-		}
-		transfer_len += sg->length;
-	} else {
-		buffer = cmd->request_buffer;
-		transfer_len = cmd->request_bufflen;
+	sg = scsi_sglist(cmd);
+	buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+	if (scsi_sg_count(cmd) > 1) {
+		retvalue = ARCMSR_MESSAGE_FAIL;
+		goto message_out;
 	}
+	transfer_len += sg->length;
+
 	if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
 		retvalue = ARCMSR_MESSAGE_FAIL;
 		goto message_out;
@@ -1057,12 +1037,9 @@
 		retvalue = ARCMSR_MESSAGE_FAIL;
 	}
  message_out:
-	if (cmd->use_sg) {
-		struct scatterlist *sg;
+	sg = scsi_sglist(cmd);
+	kunmap_atomic(buffer - sg->offset, KM_IRQ0);
 
-		sg = (struct scatterlist *) cmd->request_buffer;
-		kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-	}
 	return retvalue;
 }
 
@@ -1085,6 +1062,7 @@
 	case INQUIRY: {
 		unsigned char inqdata[36];
 		char *buffer;
+		struct scatterlist *sg;
 
 		if (cmd->device->lun) {
 			cmd->result = (DID_TIME_OUT << 16);
@@ -1096,7 +1074,7 @@
 		inqdata[1] = 0;
 		/* rem media bit & Dev Type Modifier */
 		inqdata[2] = 0;
-		/* ISO,ECMA,& ANSI versions */
+		/* ISO, ECMA, & ANSI versions */
 		inqdata[4] = 31;
 		/* length of additional data */
 		strncpy(&inqdata[8], "Areca   ", 8);
@@ -1104,21 +1082,14 @@
 		strncpy(&inqdata[16], "RAID controller ", 16);
 		/* Product Identification */
 		strncpy(&inqdata[32], "R001", 4); /* Product Revision */
-		if (cmd->use_sg) {
-			struct scatterlist *sg;
 
-			sg = (struct scatterlist *) cmd->request_buffer;
-			buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-		} else {
-			buffer = cmd->request_buffer;
-		}
+		sg = scsi_sglist(cmd);
+		buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+
 		memcpy(buffer, inqdata, sizeof(inqdata));
-		if (cmd->use_sg) {
-			struct scatterlist *sg;
+		sg = scsi_sglist(cmd);
+		kunmap_atomic(buffer - sg->offset, KM_IRQ0);
 
-			sg = (struct scatterlist *) cmd->request_buffer;
-			kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-		}
 		cmd->scsi_done(cmd);
 	}
 	break;
@@ -1153,7 +1124,7 @@
 			, acb->host->host_no);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
-	if(target == 16) {
+	if (target == 16) {
 		/* virtual device for iop message transfer */
 		arcmsr_handle_virtual_command(acb, cmd);
 		return 0;
@@ -1166,7 +1137,7 @@
 			printk(KERN_NOTICE
 				"arcmsr%d: block 'read/write'"
 				"command with gone raid volume"
-				" Cmd=%2x, TargetId=%d, Lun=%d \n"
+				" Cmd = %2x, TargetId = %d, Lun = %d \n"
 				, acb->host->host_no
 				, cmd->cmnd[0]
 				, target, lun);
@@ -1257,7 +1228,7 @@
 			if ((ccb->startdone == ARCMSR_CCB_ABORTED) ||
 				(ccb == poll_ccb)) {
 				printk(KERN_NOTICE
-					"arcmsr%d: scsi id=%d lun=%d ccb='0x%p'"
+					"arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'"
 					" poll command abort successfully \n"
 					, acb->host->host_no
 					, ccb->pcmd->device->id
@@ -1270,8 +1241,8 @@
 			}
 			printk(KERN_NOTICE
 				"arcmsr%d: polling get an illegal ccb"
-				" command done ccb='0x%p'"
-				"ccboutstandingcount=%d \n"
+				" command done ccb ='0x%p'"
+				"ccboutstandingcount = %d \n"
 				, acb->host->host_no
 				, ccb
 				, atomic_read(&acb->ccboutstandingcount));
@@ -1288,7 +1259,7 @@
 			switch(ccb->arcmsr_cdb.DeviceStatus) {
 			case ARCMSR_DEV_SELECT_TIMEOUT: {
 					acb->devstate[id][lun] = ARECA_RAID_GONE;
-					ccb->pcmd->result = DID_TIME_OUT << 16;
+					ccb->pcmd->result = DID_NO_CONNECT << 16;
 					arcmsr_ccb_complete(ccb, 1);
 				}
 				break;
@@ -1307,7 +1278,7 @@
 				break;
 			default:
 				printk(KERN_NOTICE
-					"arcmsr%d: scsi id=%d lun=%d"
+					"arcmsr%d: scsi id = %d lun = %d"
 					" polling and getting command error done"
 					"but got unknown DeviceStatus = 0x%x \n"
 					, acb->host->host_no
@@ -1322,6 +1293,94 @@
 		}
 	}
 }
+static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb)
+{
+	int i = 0, found = 0;
+	int id, lun;
+	uint32_t flag_ccb, outbound_intstatus;
+	struct MessageUnit __iomem *reg = acb->pmu;
+	struct CommandControlBlock *ccb;
+	/*clear and abort all outbound posted Q*/
+
+	while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
+(i++ < 256)){
+		ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
+(flag_ccb << 5));
+	if (ccb){
+		if ((ccb->acb != acb)||(ccb->startdone != \
+ARCMSR_CCB_START)){
+				printk(KERN_NOTICE "arcmsr%d: polling get \
+an illegal ccb" "command done ccb = '0x%p'""ccboutstandingcount = %d \n",
+					acb->host->host_no, ccb,
+					atomic_read(&acb->ccboutstandingcount));
+				continue;
+			}
+
+			id = ccb->pcmd->device->id;
+			lun = ccb->pcmd->device->lun;
+			if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)){
+				if (acb->devstate[id][lun] == ARECA_RAID_GONE)
+					acb->devstate[id][lun] = ARECA_RAID_GOOD;
+				ccb->pcmd->result = DID_OK << 16;
+				arcmsr_ccb_complete(ccb, 1);
+			}
+			else {
+				switch(ccb->arcmsr_cdb.DeviceStatus) {
+				case ARCMSR_DEV_SELECT_TIMEOUT: {
+						acb->devstate[id][lun] = ARECA_RAID_GONE;
+						ccb->pcmd->result = DID_NO_CONNECT << 16;
+						arcmsr_ccb_complete(ccb, 1);
+				}
+				break;
+
+				case ARCMSR_DEV_ABORTED:
+
+				case ARCMSR_DEV_INIT_FAIL: {
+						acb->devstate[id][lun] =
+							ARECA_RAID_GONE;
+						ccb->pcmd->result =
+							DID_BAD_TARGET << 16;
+				arcmsr_ccb_complete(ccb, 1);
+				}
+				break;
+
+				case ARCMSR_DEV_CHECK_CONDITION: {
+						acb->devstate[id][lun] =
+							ARECA_RAID_GOOD;
+						arcmsr_report_sense_info(ccb);
+						arcmsr_ccb_complete(ccb, 1);
+				}
+				break;
+
+				default:
+						printk(KERN_NOTICE
+						      "arcmsr%d: scsi id = %d \
+							lun = %d""polling and \
+							getting command error \
+							done""but got unknown \
+							DeviceStatus = 0x%x \n",
+							acb->host->host_no, id,
+					   lun, ccb->arcmsr_cdb.DeviceStatus);
+						acb->devstate[id][lun] =
+								ARECA_RAID_GONE;
+						ccb->pcmd->result =
+							DID_BAD_TARGET << 16;
+						arcmsr_ccb_complete(ccb, 1);
+				break;
+			       }
+	}
+		       found = 1;
+	       }
+	}
+	if (found){
+		outbound_intstatus = readl(&reg->outbound_intstatus) & \
+			acb->outbound_int_enable;
+		writel(outbound_intstatus, &reg->outbound_intstatus);
+		/*clear interrupt*/
+	}
+	return;
+}
+
 
 static void arcmsr_iop_init(struct AdapterControlBlock *acb)
 {
@@ -1355,7 +1414,6 @@
 
 static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
 {
-	struct MessageUnit __iomem *reg = acb->pmu;
 	struct CommandControlBlock *ccb;
 	uint32_t intmask_org;
 	int i = 0;
@@ -1368,21 +1426,17 @@
 		/* disable all outbound interrupt */
 		intmask_org = arcmsr_disable_outbound_ints(acb);
 		/* clear all outbound posted Q */
-		for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++)
-			readl(&reg->outbound_queueport);
+		arcmsr_done4_abort_postqueue(acb);
 		for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
 			ccb = acb->pccb_pool[i];
-			if ((ccb->startdone == ARCMSR_CCB_START) ||
-				(ccb->startdone == ARCMSR_CCB_ABORTED)) {
+			if (ccb->startdone == ARCMSR_CCB_START) {
 				ccb->startdone = ARCMSR_CCB_ABORTED;
-				ccb->pcmd->result = DID_ABORT << 16;
-				arcmsr_ccb_complete(ccb, 1);
 			}
 		}
 		/* enable all outbound interrupt */
 		arcmsr_enable_outbound_ints(acb, intmask_org);
 	}
-	atomic_set(&acb->ccboutstandingcount, 0);
+
 }
 
 static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
@@ -1428,10 +1482,9 @@
 	int i = 0;
 
 	printk(KERN_NOTICE
-		"arcmsr%d: abort device command of scsi id=%d lun=%d \n",
+		"arcmsr%d: abort device command of scsi id = %d lun = %d \n",
 		acb->host->host_no, cmd->device->id, cmd->device->lun);
 	acb->num_aborts++;
-
 	/*
 	************************************************
 	** the all interrupt service routine is locked
@@ -1486,10 +1539,306 @@
 		type = "X-TYPE";
 		break;
 	}
-	sprintf(buf, "Areca %s Host Adapter RAID Controller%s\n        %s",
+	sprintf(buf, "Areca %s Host Adapter RAID Controller%s\n %s",
 			type, raid6 ? "( RAID6 capable)" : "",
 			ARCMSR_DRIVER_VERSION);
 	return buf;
 }
 
+static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host;
+	struct AdapterControlBlock *acb;
+	uint8_t bus, dev_fun;
+	int error;
 
+	error = pci_enable_device(pdev);
+	if (error)
+		return PCI_ERS_RESULT_DISCONNECT;
+	pci_set_master(pdev);
+
+	host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof \
+(struct AdapterControlBlock));
+	if (!host)
+		return PCI_ERS_RESULT_DISCONNECT;
+	acb = (struct AdapterControlBlock *)host->hostdata;
+	memset(acb, 0, sizeof (struct AdapterControlBlock));
+
+	error = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+	if (error) {
+		error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		if (error) {
+			printk(KERN_WARNING
+			       "scsi%d: No suitable DMA mask available\n",
+			       host->host_no);
+			return PCI_ERS_RESULT_DISCONNECT;
+		}
+	}
+	bus = pdev->bus->number;
+	dev_fun = pdev->devfn;
+	acb = (struct AdapterControlBlock *) host->hostdata;
+	memset(acb, 0, sizeof(struct AdapterControlBlock));
+	acb->pdev = pdev;
+	acb->host = host;
+	host->max_sectors = ARCMSR_MAX_XFER_SECTORS;
+	host->max_lun = ARCMSR_MAX_TARGETLUN;
+	host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/
+	host->max_cmd_len = 16;    /*this is issue of 64bit LBA, over 2T byte*/
+	host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES;
+	host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */
+	host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN;
+	host->this_id = ARCMSR_SCSI_INITIATOR_ID;
+	host->unique_id = (bus << 8) | dev_fun;
+	host->irq = pdev->irq;
+	error = pci_request_regions(pdev, "arcmsr");
+	if (error)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	acb->pmu = ioremap(pci_resource_start(pdev, 0),
+			   pci_resource_len(pdev, 0));
+	if (!acb->pmu) {
+		printk(KERN_NOTICE "arcmsr%d: memory"
+			" mapping region fail \n", acb->host->host_no);
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
+			   ACB_F_MESSAGE_RQBUFFER_CLEARED |
+			   ACB_F_MESSAGE_WQBUFFER_READED);
+	acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
+	INIT_LIST_HEAD(&acb->ccb_free_list);
+
+	error = arcmsr_alloc_ccb_pool(acb);
+	if (error)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	error = request_irq(pdev->irq, arcmsr_do_interrupt,
+			IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb);
+	if (error)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	arcmsr_iop_init(acb);
+	if (strncmp(acb->firm_version, "V1.42", 5) >= 0)
+	      host->max_sectors = ARCMSR_MAX_XFER_SECTORS_B;
+
+	pci_set_drvdata(pdev, host);
+
+	error = scsi_add_host(host, &pdev->dev);
+	if (error)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	error = arcmsr_alloc_sysfs_attr(acb);
+	if (error)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	scsi_scan_host(host);
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+	struct MessageUnit __iomem *reg = acb->pmu;
+	struct CommandControlBlock *ccb;
+	/*clear and abort all outbound posted Q*/
+	int i = 0, found = 0;
+	int id, lun;
+	uint32_t flag_ccb, outbound_intstatus;
+
+	while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
+								(i++ < 256)){
+			ccb = (struct CommandControlBlock *)(acb->vir2phy_offset
+							 + (flag_ccb << 5));
+			if (ccb){
+				if ((ccb->acb != acb)||(ccb->startdone !=
+							ARCMSR_CCB_START)){
+					printk(KERN_NOTICE "arcmsr%d: polling \
+					get an illegal ccb"" command done ccb = '0x%p'"
+					"ccboutstandingcount = %d \n",
+					acb->host->host_no, ccb,
+					atomic_read(&acb->ccboutstandingcount));
+					continue;
+				}
+
+				id = ccb->pcmd->device->id;
+				lun = ccb->pcmd->device->lun;
+				if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) {
+					if (acb->devstate[id][lun] ==
+								ARECA_RAID_GONE)
+						acb->devstate[id][lun] =
+								ARECA_RAID_GOOD;
+					ccb->pcmd->result = DID_OK << 16;
+					arcmsr_ccb_complete(ccb, 1);
+				}
+				else {
+					switch(ccb->arcmsr_cdb.DeviceStatus) {
+					case ARCMSR_DEV_SELECT_TIMEOUT: {
+							acb->devstate[id][lun] =
+							ARECA_RAID_GONE;
+							ccb->pcmd->result =
+							DID_NO_CONNECT << 16;
+							arcmsr_ccb_complete(ccb, 1);
+					}
+					break;
+
+					case ARCMSR_DEV_ABORTED:
+
+					case ARCMSR_DEV_INIT_FAIL: {
+							acb->devstate[id][lun] =
+							 ARECA_RAID_GONE;
+							ccb->pcmd->result =
+							DID_BAD_TARGET << 16;
+							arcmsr_ccb_complete(ccb, 1);
+					}
+					break;
+
+					case ARCMSR_DEV_CHECK_CONDITION: {
+							acb->devstate[id][lun] =
+							 ARECA_RAID_GOOD;
+							arcmsr_report_sense_info(ccb);
+							arcmsr_ccb_complete(ccb, 1);
+					}
+					break;
+
+					default:
+							printk(KERN_NOTICE
+								"arcmsr%d: scsi \
+								id = %d lun = %d"
+								" polling and \
+								getting command \
+								error done"
+								"but got unknown \
+							DeviceStatus = 0x%x \n"
+							, acb->host->host_no,
+								id, lun,
+						ccb->arcmsr_cdb.DeviceStatus);
+							acb->devstate[id][lun] =
+								ARECA_RAID_GONE;
+							ccb->pcmd->result =
+							DID_BAD_TARGET << 16;
+							arcmsr_ccb_complete(ccb, 1);
+					break;
+					}
+				}
+				found = 1;
+			}
+		}
+	if (found){
+		outbound_intstatus = readl(&reg->outbound_intstatus) &
+							acb->outbound_int_enable;
+		writel(outbound_intstatus, &reg->outbound_intstatus);
+		/*clear interrupt*/
+		    }
+	return;
+}
+
+
+static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+	struct MessageUnit __iomem *reg = acb->pmu;
+	struct CommandControlBlock *ccb;
+	/*clear and abort all outbound posted Q*/
+	int i = 0, found = 0;
+	int id, lun;
+	uint32_t flag_ccb, outbound_intstatus;
+
+	while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
+								(i++ < 256)){
+			ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
+							(flag_ccb << 5));
+			if (ccb){
+				if ((ccb->acb != acb)||(ccb->startdone !=
+							ARCMSR_CCB_START)){
+					printk(KERN_NOTICE
+						"arcmsr%d: polling get an illegal ccb"
+						" command done ccb = '0x%p'"
+						"ccboutstandingcount = %d \n",
+						acb->host->host_no, ccb,
+						atomic_read(&acb->ccboutstandingcount));
+					continue;
+			}
+
+			id = ccb->pcmd->device->id;
+			lun = ccb->pcmd->device->lun;
+			if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR))	{
+				if (acb->devstate[id][lun] == ARECA_RAID_GONE)
+					acb->devstate[id][lun] = ARECA_RAID_GOOD;
+				ccb->pcmd->result = DID_OK << 16;
+				arcmsr_ccb_complete(ccb, 1);
+			}
+			else {
+				switch(ccb->arcmsr_cdb.DeviceStatus) {
+				case ARCMSR_DEV_SELECT_TIMEOUT: {
+						acb->devstate[id][lun] =
+								ARECA_RAID_GONE;
+						ccb->pcmd->result =
+							DID_NO_CONNECT << 16;
+						arcmsr_ccb_complete(ccb, 1);
+				}
+				break;
+
+				case ARCMSR_DEV_ABORTED:
+
+				case ARCMSR_DEV_INIT_FAIL: {
+						acb->devstate[id][lun] =
+								ARECA_RAID_GONE;
+						ccb->pcmd->result =
+							DID_BAD_TARGET << 16;
+						arcmsr_ccb_complete(ccb, 1);
+				}
+				break;
+
+				case ARCMSR_DEV_CHECK_CONDITION: {
+						acb->devstate[id][lun] =
+								ARECA_RAID_GOOD;
+						arcmsr_report_sense_info(ccb);
+						arcmsr_ccb_complete(ccb, 1);
+				}
+				break;
+
+				default:
+						printk(KERN_NOTICE "arcmsr%d: \
+							scsi id = %d lun = %d"
+								" polling and \
+						getting command error done"
+								"but got unknown \
+						 DeviceStatus = 0x%x \n"
+								, acb->host->host_no,
+					id, lun, ccb->arcmsr_cdb.DeviceStatus);
+							acb->devstate[id][lun] =
+								ARECA_RAID_GONE;
+							ccb->pcmd->result =
+							DID_BAD_TARGET << 16;
+							arcmsr_ccb_complete(ccb, 1);
+				break;
+				}
+			}
+			found = 1;
+		}
+	}
+	if (found){
+		outbound_intstatus = readl(&reg->outbound_intstatus) &
+						acb->outbound_int_enable;
+		writel(outbound_intstatus, &reg->outbound_intstatus);
+		/*clear interrupt*/
+	}
+	return;
+}
+
+static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
+						pci_channel_state_t state)
+{
+	switch (state) {
+	case pci_channel_io_frozen:
+			arcmsr_pci_ers_need_reset_forepart(pdev);
+			return PCI_ERS_RESULT_NEED_RESET;
+	case pci_channel_io_perm_failure:
+			arcmsr_pci_ers_disconnect_forepart(pdev);
+			return PCI_ERS_RESULT_DISCONNECT;
+			break;
+	default:
+			return PCI_ERS_RESULT_NEED_RESET;
+	}
+}
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index eff846a..03dbe60 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -894,45 +894,6 @@
 }
 
 /*
- * our own old-style timeout update
- */
-/*
- * The strategy is to cause the timer code to call scsi_times_out()
- * when the soonest timeout is pending.
- * The arguments are used when we are queueing a new command, because
- * we do not want to subtract the time used from this time, but when we
- * set the timer, we want to take this value into account.
- */
-
-int atari_scsi_update_timeout(Scsi_Cmnd * SCset, int timeout)
-{
-	int rtn;
-
-	/*
-	 * We are using the new error handling code to actually register/deregister
-	 * timers for timeout.
-	 */
-
-	if (!timer_pending(&SCset->eh_timeout))
-		rtn = 0;
-	else
-		rtn = SCset->eh_timeout.expires - jiffies;
-
-	if (timeout == 0) {
-		del_timer(&SCset->eh_timeout);
-		SCset->eh_timeout.data = (unsigned long)NULL;
-		SCset->eh_timeout.expires = 0;
-	} else {
-		if (SCset->eh_timeout.data != (unsigned long)NULL)
-			del_timer(&SCset->eh_timeout);
-		SCset->eh_timeout.data = (unsigned long)SCset;
-		SCset->eh_timeout.expires = jiffies + timeout;
-		add_timer(&SCset->eh_timeout);
-	}
-	return rtn;
-}
-
-/*
  * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
  *	void (*done)(Scsi_Cmnd *))
  *
@@ -956,7 +917,6 @@
 	Scsi_Cmnd *tmp;
 	int oldto;
 	unsigned long flags;
-	// extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
 	switch (cmd->cmnd[0]) {
@@ -1029,9 +989,9 @@
 	 * alter queues and touch the lock.
 	 */
 	if (!IS_A_TT()) {
-		oldto = atari_scsi_update_timeout(cmd, 0);
+		/* perhaps stop command timer here */
 		falcon_get_lock();
-		atari_scsi_update_timeout(cmd, oldto);
+		/* perhaps restart command timer here */
 	}
 	if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
 		LIST(cmd, hostdata->issue_queue);
diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c
deleted file mode 100644
index 599b400..0000000
--- a/drivers/scsi/bvme6000.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
- *
- * Based on work by Alan Hourihane
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/zorro.h>
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/bvme6000hw.h>
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "53c7xx.h"
-#include "bvme6000.h"
-
-#include<linux/stat.h>
-
-
-int bvme6000_scsi_detect(struct scsi_host_template *tpnt)
-{
-    static unsigned char called = 0;
-    int clock;
-    long long options;
-
-    if (called)
-	return 0;
-    if (!MACH_IS_BVME6000)
-	return 0;
-
-    tpnt->proc_name = "BVME6000";
-
-    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
-
-    clock = 40000000;	/* 66MHz SCSI Clock */
-
-    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)BVME_NCR53C710_BASE,
-			0, BVME_IRQ_SCSI, DMA_NONE,
-			options, clock);
-    called = 1;
-    return 1;
-}
-
-static int bvme6000_scsi_release(struct Scsi_Host *shost)
-{
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
-	return 0;
-}
-
-static struct scsi_host_template driver_template = {
-	.name			= "BVME6000 NCR53c710 SCSI",
-	.detect			= bvme6000_scsi_detect,
-	.release		= bvme6000_scsi_release,
-	.queuecommand		= NCR53c7xx_queue_command,
-	.abort			= NCR53c7xx_abort,
-	.reset			= NCR53c7xx_reset,
-	.can_queue		= 24,
-	.this_id		= 7,
-	.sg_tablesize		= 63,
-	.cmd_per_lun		= 3,
-	.use_clustering		= DISABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
diff --git a/drivers/scsi/bvme6000.h b/drivers/scsi/bvme6000.h
deleted file mode 100644
index ea3e4b2..0000000
--- a/drivers/scsi/bvme6000.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef BVME6000_SCSI_H
-#define BVME6000_SCSI_H
-
-#include <linux/types.h>
-
-int bvme6000_scsi_detect(struct scsi_host_template *);
-const char *NCR53c7x0_info(void);
-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int NCR53c7xx_abort(Scsi_Cmnd *);
-int NCR53c7x0_release (struct Scsi_Host *);
-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id);
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 3
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 24
-#endif
-
-#include <scsi/scsicam.h>
-
-#endif /* BVME6000_SCSI_H */
diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c
new file mode 100644
index 0000000..012cdea
--- /dev/null
+++ b/drivers/scsi/bvme6000_scsi.c
@@ -0,0 +1,135 @@
+/*
+ * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
+ *
+ * Based on work by Alan Hourihane and Kars de Jong
+ *
+ * Rewritten to use 53c700.c by Richard Hirst <richard@sleepie.demon.co.uk>
+ */
+
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/bvme6000hw.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
+
+#include "53c700.h"
+
+MODULE_AUTHOR("Richard Hirst <richard@sleepie.demon.co.uk>");
+MODULE_DESCRIPTION("BVME6000 NCR53C710 driver");
+MODULE_LICENSE("GPL");
+
+static struct scsi_host_template bvme6000_scsi_driver_template = {
+	.name			= "BVME6000 NCR53c710 SCSI",
+	.proc_name		= "BVME6000",
+	.this_id		= 7,
+	.module			= THIS_MODULE,
+};
+
+static struct platform_device *bvme6000_scsi_device;
+
+static __devinit int
+bvme6000_probe(struct device *dev)
+{
+	struct Scsi_Host * host = NULL;
+	struct NCR_700_Host_Parameters *hostdata;
+
+	if (!MACH_IS_BVME6000)
+		goto out;
+
+	hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+	if (hostdata == NULL) {
+		printk(KERN_ERR "bvme6000-scsi: "
+				"Failed to allocate host data\n");
+		goto out;
+	}
+	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
+
+	/* Fill in the required pieces of hostdata */
+	hostdata->base = (void __iomem *)BVME_NCR53C710_BASE;
+	hostdata->clock = 40;	/* XXX - depends on the CPU clock! */
+	hostdata->chip710 = 1;
+	hostdata->dmode_extra = DMODE_FC2;
+	hostdata->dcntl_extra = EA_710;
+	hostdata->ctest7_extra = CTEST7_TT1;
+
+	/* and register the chip */
+	host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, dev);
+	if (!host) {
+		printk(KERN_ERR "bvme6000-scsi: No host detected; "
+				"board configuration problem?\n");
+		goto out_free;
+	}
+	host->base = BVME_NCR53C710_BASE;
+	host->this_id = 7;
+	host->irq = BVME_IRQ_SCSI;
+	if (request_irq(BVME_IRQ_SCSI, NCR_700_intr, 0, "bvme6000-scsi",
+			host)) {
+		printk(KERN_ERR "bvme6000-scsi: request_irq failed\n");
+		goto out_put_host;
+	}
+
+	scsi_scan_host(host);
+
+	return 0;
+
+ out_put_host:
+	scsi_host_put(host);
+ out_free:
+	kfree(hostdata);
+ out:
+	return -ENODEV;
+}
+
+static __devexit int
+bvme6000_device_remove(struct device *dev)
+{
+	struct Scsi_Host *host = dev_to_shost(dev);
+	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+
+	scsi_remove_host(host);
+	NCR_700_release(host);
+	kfree(hostdata);
+	free_irq(host->irq, host);
+
+	return 0;
+}
+
+static struct device_driver bvme6000_scsi_driver = {
+	.name	= "bvme6000-scsi",
+	.bus	= &platform_bus_type,
+	.probe	= bvme6000_probe,
+	.remove	= __devexit_p(bvme6000_device_remove),
+};
+
+static int __init bvme6000_scsi_init(void)
+{
+	int err;
+
+	err = driver_register(&bvme6000_scsi_driver);
+	if (err)
+		return err;
+
+	bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi",
+							       -1, NULL, 0);
+	if (IS_ERR(bvme6000_scsi_device)) {
+		driver_unregister(&bvme6000_scsi_driver);
+		return PTR_ERR(bvme6000_scsi_device);
+	}
+
+	return 0;
+}
+
+static void __exit bvme6000_scsi_exit(void)
+{
+	platform_device_unregister(bvme6000_scsi_device);
+	driver_unregister(&bvme6000_scsi_driver);
+}
+
+module_init(bvme6000_scsi_init);
+module_exit(bvme6000_scsi_exit);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 564ea90..7b8a345 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -979,6 +979,7 @@
 static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb)
 {
+	int nseg;
 	enum dma_data_direction dir = cmd->sc_data_direction;
 	dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n",
 		cmd->pid, dcb->target_id, dcb->target_lun);
@@ -1000,27 +1001,30 @@
 	srb->scsi_phase = PH_BUS_FREE;	/* initial phase */
 	srb->end_message = 0;
 
-	if (dir == PCI_DMA_NONE || !cmd->request_buffer) {
+	nseg = scsi_dma_map(cmd);
+	BUG_ON(nseg < 0);
+
+	if (dir == PCI_DMA_NONE || !nseg) {
 		dprintkdbg(DBG_0,
 			"build_srb: [0] len=%d buf=%p use_sg=%d !MAP=%08x\n",
-			cmd->bufflen, cmd->request_buffer,
-			cmd->use_sg, srb->segment_x[0].address);
-	} else if (cmd->use_sg) {
+			   cmd->bufflen, scsi_sglist(cmd), scsi_sg_count(cmd),
+			   srb->segment_x[0].address);
+	} else {
 		int i;
-		u32 reqlen = cmd->request_bufflen;
-		struct scatterlist *sl = (struct scatterlist *)
-					 cmd->request_buffer;
+		u32 reqlen = scsi_bufflen(cmd);
+		struct scatterlist *sg;
 		struct SGentry *sgp = srb->segment_x;
-		srb->sg_count = pci_map_sg(dcb->acb->dev, sl, cmd->use_sg,
-					   dir);
-		dprintkdbg(DBG_0,
-			"build_srb: [n] len=%d buf=%p use_sg=%d segs=%d\n",
-			reqlen, cmd->request_buffer, cmd->use_sg,
-			srb->sg_count);
 
-		for (i = 0; i < srb->sg_count; i++) {
-			u32 busaddr = (u32)sg_dma_address(&sl[i]);
-			u32 seglen = (u32)sl[i].length;
+		srb->sg_count = nseg;
+
+		dprintkdbg(DBG_0,
+			   "build_srb: [n] len=%d buf=%p use_sg=%d segs=%d\n",
+			   reqlen, scsi_sglist(cmd), scsi_sg_count(cmd),
+			   srb->sg_count);
+
+		scsi_for_each_sg(cmd, sg, srb->sg_count, i) {
+			u32 busaddr = (u32)sg_dma_address(sg);
+			u32 seglen = (u32)sg->length;
 			sgp[i].address = busaddr;
 			sgp[i].length = seglen;
 			srb->total_xfer_length += seglen;
@@ -1050,23 +1054,6 @@
 
 		dprintkdbg(DBG_SG, "build_srb: [n] map sg %p->%08x(%05x)\n",
 			srb->segment_x, srb->sg_bus_addr, SEGMENTX_LEN);
-	} else {
-		srb->total_xfer_length = cmd->request_bufflen;
-		srb->sg_count = 1;
-		srb->segment_x[0].address =
-			pci_map_single(dcb->acb->dev, cmd->request_buffer,
-				       srb->total_xfer_length, dir);
-
-		/* Fixup for WIDE padding - make sure length is even */
-		if (dcb->sync_period & WIDE_SYNC && srb->total_xfer_length % 2)
-			srb->total_xfer_length++;
-
-		srb->segment_x[0].length = srb->total_xfer_length;
-
-		dprintkdbg(DBG_0,
-			"build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n",
-			srb->total_xfer_length, cmd->request_buffer,
-			cmd->use_sg, srb->segment_x[0].address);
 	}
 
 	srb->request_length = srb->total_xfer_length;
@@ -2128,7 +2115,7 @@
 		/*clear_fifo(acb, "DOP1"); */
 		/* KG: What is this supposed to be useful for? WIDE padding stuff? */
 		if (d_left_counter == 1 && dcb->sync_period & WIDE_SYNC
-		    && srb->cmd->request_bufflen % 2) {
+		    && scsi_bufflen(srb->cmd) % 2) {
 			d_left_counter = 0;
 			dprintkl(KERN_INFO,
 				"data_out_phase0: Discard 1 byte (0x%02x)\n",
@@ -2159,7 +2146,7 @@
 			sg_update_list(srb, d_left_counter);
 			/* KG: Most ugly hack! Apparently, this works around a chip bug */
 			if ((srb->segment_x[srb->sg_index].length ==
-			     diff && srb->cmd->use_sg)
+			     diff && scsi_sg_count(srb->cmd))
 			    || ((oldxferred & ~PAGE_MASK) ==
 				(PAGE_SIZE - diff))
 			    ) {
@@ -2289,19 +2276,15 @@
 				unsigned char *virt, *base = NULL;
 				unsigned long flags = 0;
 				size_t len = left_io;
+				size_t offset = srb->request_length - left_io;
 
-				if (srb->cmd->use_sg) {
-					size_t offset = srb->request_length - left_io;
-					local_irq_save(flags);
-					/* Assumption: it's inside one page as it's at most 4 bytes and
-					   I just assume it's on a 4-byte boundary */
-					base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
-								     srb->sg_count, &offset, &len);
-					virt = base + offset;
-				} else {
-					virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
-					len = left_io;
-				}
+				local_irq_save(flags);
+				/* Assumption: it's inside one page as it's at most 4 bytes and
+				   I just assume it's on a 4-byte boundary */
+				base = scsi_kmap_atomic_sg(scsi_sglist(srb->cmd),
+							   srb->sg_count, &offset, &len);
+				virt = base + offset;
+
 				left_io -= len;
 
 				while (len) {
@@ -2341,10 +2324,8 @@
 					DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
 				}
 
-				if (srb->cmd->use_sg) {
-					scsi_kunmap_atomic_sg(base);
-					local_irq_restore(flags);
-				}
+				scsi_kunmap_atomic_sg(base);
+				local_irq_restore(flags);
 			}
 			/*printk(" %08x", *(u32*)(bus_to_virt (addr))); */
 			/*srb->total_xfer_length = 0; */
@@ -2455,7 +2436,7 @@
 		 */
 		srb->state |= SRB_DATA_XFER;
 		DC395x_write32(acb, TRM_S1040_DMA_XHIGHADDR, 0);
-		if (srb->cmd->use_sg) {	/* with S/G */
+		if (scsi_sg_count(srb->cmd)) {	/* with S/G */
 			io_dir |= DMACMD_SG;
 			DC395x_write32(acb, TRM_S1040_DMA_XLOWADDR,
 				       srb->sg_bus_addr +
@@ -2513,18 +2494,14 @@
 				unsigned char *virt, *base = NULL;
 				unsigned long flags = 0;
 				size_t len = left_io;
+				size_t offset = srb->request_length - left_io;
 
-				if (srb->cmd->use_sg) {
-					size_t offset = srb->request_length - left_io;
-					local_irq_save(flags);
-					/* Again, max 4 bytes */
-					base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
-								     srb->sg_count, &offset, &len);
-					virt = base + offset;
-				} else {
-					virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
-					len = left_io;
-				}
+				local_irq_save(flags);
+				/* Again, max 4 bytes */
+				base = scsi_kmap_atomic_sg(scsi_sglist(srb->cmd),
+							   srb->sg_count, &offset, &len);
+				virt = base + offset;
+
 				left_io -= len;
 
 				while (len--) {
@@ -2536,10 +2513,8 @@
 					sg_subtract_one(srb);
 				}
 
-				if (srb->cmd->use_sg) {
-					scsi_kunmap_atomic_sg(base);
-					local_irq_restore(flags);
-				}
+				scsi_kunmap_atomic_sg(base);
+				local_irq_restore(flags);
 			}
 			if (srb->dcb->sync_period & WIDE_SYNC) {
 				if (ln % 2) {
@@ -3295,7 +3270,8 @@
 {
 	struct scsi_cmnd *cmd = srb->cmd;
 	enum dma_data_direction dir = cmd->sc_data_direction;
-	if (cmd->use_sg && dir != PCI_DMA_NONE) {
+
+	if (scsi_sg_count(cmd) && dir != PCI_DMA_NONE) {
 		/* unmap DC395x SG list */
 		dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
 			srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3303,16 +3279,9 @@
 				 SEGMENTX_LEN,
 				 PCI_DMA_TODEVICE);
 		dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
-			cmd->use_sg, cmd->request_buffer);
+			   scsi_sg_count(cmd), scsi_bufflen(cmd));
 		/* unmap the sg segments */
-		pci_unmap_sg(acb->dev,
-			     (struct scatterlist *)cmd->request_buffer,
-			     cmd->use_sg, dir);
-	} else if (cmd->request_buffer && dir != PCI_DMA_NONE) {
-		dprintkdbg(DBG_SG, "pci_unmap_srb: buffer=%08x(%05x)\n",
-			srb->segment_x[0].address, cmd->request_bufflen);
-		pci_unmap_single(acb->dev, srb->segment_x[0].address,
-				 cmd->request_bufflen, dir);
+		scsi_dma_unmap(cmd);
 	}
 }
 
@@ -3352,8 +3321,8 @@
 	dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid,
 		srb->cmd->device->id, srb->cmd->device->lun);
 	dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
-		srb, cmd->use_sg, srb->sg_index, srb->sg_count,
-		cmd->request_buffer);
+		   srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count,
+		   scsi_sgtalbe(cmd));
 	status = srb->target_status;
 	if (srb->flag & AUTO_REQSENSE) {
 		dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n");
@@ -3482,16 +3451,10 @@
 		}
 	}
 
-	if (dir != PCI_DMA_NONE) {
-		if (cmd->use_sg)
-			pci_dma_sync_sg_for_cpu(acb->dev,
-					(struct scatterlist *)cmd->
-					request_buffer, cmd->use_sg, dir);
-		else if (cmd->request_buffer)
-			pci_dma_sync_single_for_cpu(acb->dev,
-					    srb->segment_x[0].address,
-					    cmd->request_bufflen, dir);
-	}
+	if (dir != PCI_DMA_NONE && scsi_sg_count(cmd))
+		pci_dma_sync_sg_for_cpu(acb->dev, scsi_sglist(cmd),
+					scsi_sg_count(cmd), dir);
+
 	ckc_only = 0;
 /* Check Error Conditions */
       ckc_e:
@@ -3500,19 +3463,15 @@
 		unsigned char *base = NULL;
 		struct ScsiInqData *ptr;
 		unsigned long flags = 0;
+		struct scatterlist* sg = scsi_sglist(cmd);
+		size_t offset = 0, len = sizeof(struct ScsiInqData);
 
-		if (cmd->use_sg) {
-			struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
-			size_t offset = 0, len = sizeof(struct ScsiInqData);
-
-			local_irq_save(flags);
-			base = scsi_kmap_atomic_sg(sg, cmd->use_sg, &offset, &len);
-			ptr = (struct ScsiInqData *)(base + offset);
-		} else
-			ptr = (struct ScsiInqData *)(cmd->request_buffer);
+		local_irq_save(flags);
+		base = scsi_kmap_atomic_sg(sg, scsi_sg_count(cmd), &offset, &len);
+		ptr = (struct ScsiInqData *)(base + offset);
 
 		if (!ckc_only && (cmd->result & RES_DID) == 0
-		    && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8
+		    && cmd->cmnd[2] == 0 && scsi_bufflen(cmd) >= 8
 		    && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
 			dcb->inquiry7 = ptr->Flags;
 
@@ -3527,14 +3486,12 @@
 			}
 		}
 
-		if (cmd->use_sg) {
-			scsi_kunmap_atomic_sg(base);
-			local_irq_restore(flags);
-		}
+		scsi_kunmap_atomic_sg(base);
+		local_irq_restore(flags);
 	}
 
 	/* Here is the info for Doug Gilbert's sg3 ... */
-	cmd->resid = srb->total_xfer_length;
+	scsi_set_resid(cmd, srb->total_xfer_length);
 	/* This may be interpreted by sb. or not ... */
 	cmd->SCp.this_residual = srb->total_xfer_length;
 	cmd->SCp.buffers_residual = 0;
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 8c7d2bb..2e2362d 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -2078,12 +2078,13 @@
 	u32 *lenptr;
 	int direction;
 	int scsidir;
+	int nseg;
 	u32 len;
 	u32 reqlen;
 	s32 rcode;
 
 	memset(msg, 0 , sizeof(msg));
-	len = cmd->request_bufflen;
+	len = scsi_bufflen(cmd);
 	direction = 0x00000000;	
 	
 	scsidir = 0x00000000;			// DATA NO XFER
@@ -2140,21 +2141,21 @@
 	lenptr=mptr++;		/* Remember me - fill in when we know */
 	reqlen = 14;		// SINGLE SGE
 	/* Now fill in the SGList and command */
-	if(cmd->use_sg) {
-		struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
-		int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg,
-				cmd->sc_data_direction);
 
+	nseg = scsi_dma_map(cmd);
+	BUG_ON(nseg < 0);
+	if (nseg) {
+		struct scatterlist *sg;
 
 		len = 0;
-		for(i = 0 ; i < sg_count; i++) {
+		scsi_for_each_sg(cmd, sg, nseg, i) {
 			*mptr++ = direction|0x10000000|sg_dma_len(sg);
 			len+=sg_dma_len(sg);
 			*mptr++ = sg_dma_address(sg);
-			sg++;
+			/* Make this an end of list */
+			if (i == nseg - 1)
+				mptr[-2] = direction|0xD0000000|sg_dma_len(sg);
 		}
-		/* Make this an end of list */
-		mptr[-2] = direction|0xD0000000|sg_dma_len(sg-1);
 		reqlen = mptr - msg;
 		*lenptr = len;
 		
@@ -2163,16 +2164,8 @@
 				len, cmd->underflow);
 		}
 	} else {
-		*lenptr = len = cmd->request_bufflen;
-		if(len == 0) {
-			reqlen = 12;
-		} else {
-			*mptr++ = 0xD0000000|direction|cmd->request_bufflen;
-			*mptr++ = pci_map_single(pHba->pDev,
-				cmd->request_buffer,
-				cmd->request_bufflen,
-				cmd->sc_data_direction);
-		}
+		*lenptr = len = 0;
+		reqlen = 12;
 	}
 	
 	/* Stick the headers on */
@@ -2232,7 +2225,7 @@
 	hba_status = detailed_status >> 8;
 
 	// calculate resid for sg 
-	cmd->resid = cmd->request_bufflen - readl(reply+5);
+	scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5));
 
 	pHba = (adpt_hba*) cmd->device->host->hostdata[0];
 
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index 2d38025..a83e9f1 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1609,8 +1609,9 @@
 
 static void map_dma(unsigned int i, struct hostdata *ha)
 {
-	unsigned int k, count, pci_dir;
-	struct scatterlist *sgpnt;
+	unsigned int k, pci_dir;
+	int count;
+	struct scatterlist *sg;
 	struct mscp *cpp;
 	struct scsi_cmnd *SCpnt;
 
@@ -1625,38 +1626,19 @@
 
 	cpp->sense_len = sizeof SCpnt->sense_buffer;
 
-	if (!SCpnt->use_sg) {
-
-		/* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
-		if (!SCpnt->request_bufflen)
-			pci_dir = PCI_DMA_BIDIRECTIONAL;
-
-		if (SCpnt->request_buffer)
-			cpp->data_address = H2DEV(pci_map_single(ha->pdev,
-								 SCpnt->
-								 request_buffer,
-								 SCpnt->
-								 request_bufflen,
-								 pci_dir));
-
-		cpp->data_len = H2DEV(SCpnt->request_bufflen);
-		return;
-	}
-
-	sgpnt = (struct scatterlist *)SCpnt->request_buffer;
-	count = pci_map_sg(ha->pdev, sgpnt, SCpnt->use_sg, pci_dir);
-
-	for (k = 0; k < count; k++) {
-		cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
-		cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
+	count = scsi_dma_map(SCpnt);
+	BUG_ON(count < 0);
+	scsi_for_each_sg(SCpnt, sg, count, k) {
+		cpp->sglist[k].address = H2DEV(sg_dma_address(sg));
+		cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg));
 	}
 
 	cpp->sg = 1;
 	cpp->data_address = H2DEV(pci_map_single(ha->pdev, cpp->sglist,
-						 SCpnt->use_sg *
+						 scsi_sg_count(SCpnt) *
 						 sizeof(struct sg_list),
 						 pci_dir));
-	cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
+	cpp->data_len = H2DEV((scsi_sg_count(SCpnt) * sizeof(struct sg_list)));
 }
 
 static void unmap_dma(unsigned int i, struct hostdata *ha)
@@ -1673,9 +1655,7 @@
 		pci_unmap_single(ha->pdev, DEV2H(cpp->sense_addr),
 				 DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-	if (SCpnt->use_sg)
-		pci_unmap_sg(ha->pdev, SCpnt->request_buffer, SCpnt->use_sg,
-			     pci_dir);
+	scsi_dma_unmap(SCpnt);
 
 	if (!DEV2H(cpp->data_len))
 		pci_dir = PCI_DMA_BIDIRECTIONAL;
@@ -1700,9 +1680,9 @@
 					    DEV2H(cpp->sense_len),
 					    PCI_DMA_FROMDEVICE);
 
-	if (SCpnt->use_sg)
-		pci_dma_sync_sg_for_cpu(ha->pdev, SCpnt->request_buffer,
-					SCpnt->use_sg, pci_dir);
+	if (scsi_sg_count(SCpnt))
+		pci_dma_sync_sg_for_cpu(ha->pdev, scsi_sglist(SCpnt),
+					scsi_sg_count(SCpnt), pci_dir);
 
 	if (!DEV2H(cpp->data_len))
 		pci_dir = PCI_DMA_BIDIRECTIONAL;
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index ec71061..77b06a9 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -324,17 +324,14 @@
 static void esp_map_dma(struct esp *esp, struct scsi_cmnd *cmd)
 {
 	struct esp_cmd_priv *spriv = ESP_CMD_PRIV(cmd);
-	struct scatterlist *sg = cmd->request_buffer;
+	struct scatterlist *sg = scsi_sglist(cmd);
 	int dir = cmd->sc_data_direction;
 	int total, i;
 
 	if (dir == DMA_NONE)
 		return;
 
-	BUG_ON(cmd->use_sg == 0);
-
-	spriv->u.num_sg = esp->ops->map_sg(esp, sg,
-					   cmd->use_sg, dir);
+	spriv->u.num_sg = esp->ops->map_sg(esp, sg, scsi_sg_count(cmd), dir);
 	spriv->cur_residue = sg_dma_len(sg);
 	spriv->cur_sg = sg;
 
@@ -407,8 +404,7 @@
 	if (dir == DMA_NONE)
 		return;
 
-	esp->ops->unmap_sg(esp, cmd->request_buffer,
-			   spriv->u.num_sg, dir);
+	esp->ops->unmap_sg(esp, scsi_sglist(cmd), spriv->u.num_sg, dir);
 }
 
 static void esp_save_pointers(struct esp *esp, struct esp_cmd_entry *ent)
@@ -921,7 +917,7 @@
 static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	struct scsi_device *dev = cmd->device;
-	struct esp *esp = host_to_esp(dev->host);
+	struct esp *esp = shost_priv(dev->host);
 	struct esp_cmd_priv *spriv;
 	struct esp_cmd_entry *ent;
 
@@ -2033,6 +2029,7 @@
 			starget_for_each_device(tp->starget, NULL,
 						esp_clear_hold);
 	}
+	esp->flags &= ~ESP_FLAG_RESETTING;
 }
 
 /* Runs under host->lock */
@@ -2356,7 +2353,7 @@
 
 static int esp_slave_alloc(struct scsi_device *dev)
 {
-	struct esp *esp = host_to_esp(dev->host);
+	struct esp *esp = shost_priv(dev->host);
 	struct esp_target_data *tp = &esp->target[dev->id];
 	struct esp_lun_data *lp;
 
@@ -2380,7 +2377,7 @@
 
 static int esp_slave_configure(struct scsi_device *dev)
 {
-	struct esp *esp = host_to_esp(dev->host);
+	struct esp *esp = shost_priv(dev->host);
 	struct esp_target_data *tp = &esp->target[dev->id];
 	int goal_tags, queue_depth;
 
@@ -2422,7 +2419,7 @@
 
 static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
 {
-	struct esp *esp = host_to_esp(cmd->device->host);
+	struct esp *esp = shost_priv(cmd->device->host);
 	struct esp_cmd_entry *ent, *tmp;
 	struct completion eh_done;
 	unsigned long flags;
@@ -2538,7 +2535,7 @@
 
 static int esp_eh_bus_reset_handler(struct scsi_cmnd *cmd)
 {
-	struct esp *esp = host_to_esp(cmd->device->host);
+	struct esp *esp = shost_priv(cmd->device->host);
 	struct completion eh_reset;
 	unsigned long flags;
 
@@ -2574,7 +2571,7 @@
 /* All bets are off, reset the entire device.  */
 static int esp_eh_host_reset_handler(struct scsi_cmnd *cmd)
 {
-	struct esp *esp = host_to_esp(cmd->device->host);
+	struct esp *esp = shost_priv(cmd->device->host);
 	unsigned long flags;
 
 	spin_lock_irqsave(esp->host->host_lock, flags);
@@ -2614,7 +2611,7 @@
 
 static void esp_get_signalling(struct Scsi_Host *host)
 {
-	struct esp *esp = host_to_esp(host);
+	struct esp *esp = shost_priv(host);
 	enum spi_signal_type type;
 
 	if (esp->flags & ESP_FLAG_DIFFERENTIAL)
@@ -2628,7 +2625,7 @@
 static void esp_set_offset(struct scsi_target *target, int offset)
 {
 	struct Scsi_Host *host = dev_to_shost(target->dev.parent);
-	struct esp *esp = host_to_esp(host);
+	struct esp *esp = shost_priv(host);
 	struct esp_target_data *tp = &esp->target[target->id];
 
 	tp->nego_goal_offset = offset;
@@ -2638,7 +2635,7 @@
 static void esp_set_period(struct scsi_target *target, int period)
 {
 	struct Scsi_Host *host = dev_to_shost(target->dev.parent);
-	struct esp *esp = host_to_esp(host);
+	struct esp *esp = shost_priv(host);
 	struct esp_target_data *tp = &esp->target[target->id];
 
 	tp->nego_goal_period = period;
@@ -2648,7 +2645,7 @@
 static void esp_set_width(struct scsi_target *target, int width)
 {
 	struct Scsi_Host *host = dev_to_shost(target->dev.parent);
-	struct esp *esp = host_to_esp(host);
+	struct esp *esp = shost_priv(host);
 	struct esp_target_data *tp = &esp->target[target->id];
 
 	tp->nego_goal_width = (width ? 1 : 0);
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 8d4a669..d5576d5 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -517,8 +517,6 @@
 	struct sbus_dma		*dma;
 };
 
-#define host_to_esp(host)	((struct esp *)(host)->hostdata)
-
 /* A front-end driver for the ESP chip should do the following in
  * it's device probe routine:
  * 1) Allocate the host and private area using scsi_host_alloc()
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 5d4ea6f..36169d5 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -410,6 +410,8 @@
 static char * fdomain = NULL;
 module_param(fdomain, charp, 0);
 
+#ifndef PCMCIA
+
 static unsigned long addresses[] = {
    0xc8000,
    0xca000,
@@ -426,6 +428,8 @@
 
 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 
+#endif /* !PCMCIA */
+
 /*
 
   READ THIS BEFORE YOU ADD A SIGNATURE!
@@ -458,6 +462,8 @@
 
 */
 
+#ifndef PCMCIA
+
 static struct signature {
    const char *signature;
    int  sig_offset;
@@ -503,6 +509,8 @@
 
 #define SIGNATURE_COUNT ARRAY_SIZE(signatures)
 
+#endif /* !PCMCIA */
+
 static void print_banner( struct Scsi_Host *shpnt )
 {
    if (!shpnt) return;		/* This won't ever happen */
@@ -633,6 +641,8 @@
    return 0;
 }
 
+#ifndef PCMCIA
+
 /* fdomain_get_irq assumes that we have a valid MCA ID for a
    TMC-1660/TMC-1680 Future Domain board.  Now, check to be sure the
    bios_base matches these ports.  If someone was unlucky enough to have
@@ -667,7 +677,6 @@
 
 static int fdomain_isa_detect( int *irq, int *iobase )
 {
-#ifndef PCMCIA
    int i, j;
    int base = 0xdeadbeef;
    int flag = 0;
@@ -786,11 +795,22 @@
    *iobase = base;
 
    return 1;			/* success */
-#else
-   return 0;
-#endif
 }
 
+#else /* PCMCIA */
+
+static int fdomain_isa_detect( int *irq, int *iobase )
+{
+	if (irq)
+		*irq = 0;
+	if (iobase)
+		*iobase = 0;
+	return 0;
+}
+
+#endif /* !PCMCIA */
+
+
 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
    iobase) This function gets the Interrupt Level and I/O base address from
    the PCI configuration registers. */
@@ -1345,16 +1365,15 @@
 
 #if ERRORS_ONLY
       if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
-	 if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
+	      char *buf = scsi_sglist(current_SC);
+	 if ((unsigned char)(*(buf + 2)) & 0x0f) {
 	    unsigned char key;
 	    unsigned char code;
 	    unsigned char qualifier;
 
-	    key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
-		  & 0x0f;
-	    code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
-	    qualifier = (unsigned char)(*((char *)current_SC->request_buffer
-					  + 13));
+	    key = (unsigned char)(*(buf + 2)) & 0x0f;
+	    code = (unsigned char)(*(buf + 12));
+	    qualifier = (unsigned char)(*(buf + 13));
 
 	    if (key != UNIT_ATTENTION
 		&& !(key == NOT_READY
@@ -1405,8 +1424,8 @@
    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
 	   SCpnt->target,
 	   *(unsigned char *)SCpnt->cmnd,
-	   SCpnt->use_sg,
-	   SCpnt->request_bufflen );
+	   scsi_sg_count(SCpnt),
+	   scsi_bufflen(SCpnt));
 #endif
 
    fdomain_make_bus_idle();
@@ -1416,20 +1435,19 @@
 
    /* Initialize static data */
 
-   if (current_SC->use_sg) {
-      current_SC->SCp.buffer =
-	    (struct scatterlist *)current_SC->request_buffer;
-      current_SC->SCp.ptr              = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
-      current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
-      current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
+   if (scsi_sg_count(current_SC)) {
+	   current_SC->SCp.buffer = scsi_sglist(current_SC);
+	   current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page)
+		   + current_SC->SCp.buffer->offset;
+	   current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
+	   current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
    } else {
-      current_SC->SCp.ptr              = (char *)current_SC->request_buffer;
-      current_SC->SCp.this_residual    = current_SC->request_bufflen;
-      current_SC->SCp.buffer           = NULL;
-      current_SC->SCp.buffers_residual = 0;
+	   current_SC->SCp.ptr              = 0;
+	   current_SC->SCp.this_residual    = 0;
+	   current_SC->SCp.buffer           = NULL;
+	   current_SC->SCp.buffers_residual = 0;
    }
-	 
-   
+
    current_SC->SCp.Status              = 0;
    current_SC->SCp.Message             = 0;
    current_SC->SCp.have_data_in        = 0;
@@ -1472,8 +1490,8 @@
 	   SCpnt->SCp.phase,
 	   SCpnt->device->id,
 	   *(unsigned char *)SCpnt->cmnd,
-	   SCpnt->use_sg,
-	   SCpnt->request_bufflen );
+	   scsi_sg_count(SCpnt),
+	   scsi_bufflen(SCpnt));
    printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
 	   SCpnt->SCp.sent_command,
 	   SCpnt->SCp.have_data_in,
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 60446b8..d0b95ce 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -876,7 +876,7 @@
 /* Vortex only makes RAID controllers.
  * We do not really want to specify all 550 ids here, so wildcard match.
  */
-static struct pci_device_id gdthtable[] __attribute_used__ = {
+static struct pci_device_id gdthtable[] __maybe_unused = {
     {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
     {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
     {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
@@ -1955,7 +1955,7 @@
         for (j = 0; j < 12; ++j) 
             rtc[j] = CMOS_READ(j);
     } while (rtc[0] != CMOS_READ(0));
-    spin_lock_irqrestore(&rtc_lock, flags);
+    spin_unlock_irqrestore(&rtc_lock, flags);
     TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
             *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
     /* 3. send to controller firmware */
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index bec83cb..0e579ca 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -339,20 +339,8 @@
 
 	scp = hba->reqs[tag].scp;
 
-	if (HPT_SCP(scp)->mapped) {
-		if (scp->use_sg)
-			pci_unmap_sg(hba->pcidev,
-				(struct scatterlist *)scp->request_buffer,
-				scp->use_sg,
-				scp->sc_data_direction
-			);
-		else
-			pci_unmap_single(hba->pcidev,
-				HPT_SCP(scp)->dma_handle,
-				scp->request_bufflen,
-				scp->sc_data_direction
-			);
-	}
+	if (HPT_SCP(scp)->mapped)
+		scsi_dma_unmap(scp);
 
 	switch (le32_to_cpu(req->header.result)) {
 	case IOP_RESULT_SUCCESS:
@@ -448,43 +436,26 @@
 {
 	struct Scsi_Host *host = scp->device->host;
 	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
-	struct scatterlist *sglist = (struct scatterlist *)scp->request_buffer;
+	struct scatterlist *sg;
+	int idx, nseg;
 
-	/*
-	 * though we'll not get non-use_sg fields anymore,
-	 * keep use_sg checking anyway
-	 */
-	if (scp->use_sg) {
-		int idx;
+	nseg = scsi_dma_map(scp);
+	BUG_ON(nseg < 0);
+	if (!nseg)
+		return 0;
 
-		HPT_SCP(scp)->sgcnt = pci_map_sg(hba->pcidev,
-				sglist, scp->use_sg,
-				scp->sc_data_direction);
-		HPT_SCP(scp)->mapped = 1;
-		BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
+	HPT_SCP(scp)->sgcnt = nseg;
+	HPT_SCP(scp)->mapped = 1;
 
-		for (idx = 0; idx < HPT_SCP(scp)->sgcnt; idx++) {
-			psg[idx].pci_address =
-				cpu_to_le64(sg_dma_address(&sglist[idx]));
-			psg[idx].size = cpu_to_le32(sg_dma_len(&sglist[idx]));
-			psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
-				cpu_to_le32(1) : 0;
-		}
+	BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
 
-		return HPT_SCP(scp)->sgcnt;
-	} else {
-		HPT_SCP(scp)->dma_handle = pci_map_single(
-				hba->pcidev,
-				scp->request_buffer,
-				scp->request_bufflen,
-				scp->sc_data_direction
-			);
-		HPT_SCP(scp)->mapped = 1;
-		psg->pci_address = cpu_to_le64(HPT_SCP(scp)->dma_handle);
-		psg->size = cpu_to_le32(scp->request_bufflen);
-		psg->eot = cpu_to_le32(1);
-		return 1;
+	scsi_for_each_sg(scp, sg, HPT_SCP(scp)->sgcnt, idx) {
+		psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg));
+		psg[idx].size = cpu_to_le32(sg_dma_len(sg));
+		psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
+			cpu_to_le32(1) : 0;
 	}
+	return HPT_SCP(scp)->sgcnt;
 }
 
 static int hptiop_queuecommand(struct scsi_cmnd *scp,
@@ -529,9 +500,8 @@
 	req = (struct hpt_iop_request_scsi_command *)_req->req_virt;
 
 	/* build S/G table */
-	if (scp->request_bufflen)
-		sg_count = hptiop_buildsgl(scp, req->sg_list);
-	else
+	sg_count = hptiop_buildsgl(scp, req->sg_list);
+	if (!sg_count)
 		HPT_SCP(scp)->mapped = 0;
 
 	req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
@@ -540,7 +510,7 @@
 	req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
 							(u32)_req->index);
 	req->header.context_hi32 = 0;
-	req->dataxfer_length = cpu_to_le32(scp->request_bufflen);
+	req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp));
 	req->channel = scp->device->channel;
 	req->target = scp->device->id;
 	req->lun = scp->device->lun;
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 0e57fb6..4275d1b 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -31,14 +31,21 @@
 #include <linux/mca.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
-#include <linux/mca-legacy.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "ibmmca.h"
+
+/* Common forward declarations for all Linux-versions: */
+static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+static int ibmmca_abort (Scsi_Cmnd *);
+static int ibmmca_host_reset (Scsi_Cmnd *);
+static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
+static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout);
+
+
 
 /* current version of this driver-source: */
 #define IBMMCA_SCSI_DRIVER_VERSION "4.0b-ac"
@@ -65,11 +72,11 @@
 #define IM_DEBUG_CMD_DEVICE	TYPE_TAPE
 
 /* relative addresses of hardware registers on a subsystem */
-#define IM_CMD_REG(hi)	(hosts[(hi)]->io_port)	/*Command Interface, (4 bytes long) */
-#define IM_ATTN_REG(hi)	(hosts[(hi)]->io_port+4)	/*Attention (1 byte) */
-#define IM_CTR_REG(hi)	(hosts[(hi)]->io_port+5)	/*Basic Control (1 byte) */
-#define IM_INTR_REG(hi)	(hosts[(hi)]->io_port+6)	/*Interrupt Status (1 byte, r/o) */
-#define IM_STAT_REG(hi)	(hosts[(hi)]->io_port+7)	/*Basic Status (1 byte, read only) */
+#define IM_CMD_REG(h)	((h)->io_port)	/*Command Interface, (4 bytes long) */
+#define IM_ATTN_REG(h)	((h)->io_port+4)	/*Attention (1 byte) */
+#define IM_CTR_REG(h)	((h)->io_port+5)	/*Basic Control (1 byte) */
+#define IM_INTR_REG(h)	((h)->io_port+6)	/*Interrupt Status (1 byte, r/o) */
+#define IM_STAT_REG(h)	((h)->io_port+7)	/*Basic Status (1 byte, read only) */
 
 /* basic I/O-port of first adapter */
 #define IM_IO_PORT	0x3540
@@ -266,30 +273,36 @@
     if ((display_mode & LED_ACTIVITY)||(!display_mode)) \
     outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); }
 
-/*list of supported subsystems */
-struct subsys_list_struct {
-	unsigned short mca_id;
-	char *description;
-};
-
 /* types of different supported hardware that goes to hostdata special */
 #define IBM_SCSI2_FW     0
 #define IBM_7568_WCACHE  1
 #define IBM_EXP_UNIT     2
 #define IBM_SCSI_WCACHE  3
 #define IBM_SCSI         4
+#define IBM_INTEGSCSI	 5
 
 /* other special flags for hostdata structure */
 #define FORCED_DETECTION         100
 #define INTEGRATED_SCSI          101
 
 /* List of possible IBM-SCSI-adapters */
-static struct subsys_list_struct subsys_list[] = {
-	{0x8efc, "IBM SCSI-2 F/W Adapter"},	/* special = 0 */
-	{0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/Cache"},	/* special = 1 */
-	{0x8ef8, "IBM Expansion Unit SCSI Controller"},	/* special = 2 */
-	{0x8eff, "IBM SCSI Adapter w/Cache"},	/* special = 3 */
-	{0x8efe, "IBM SCSI Adapter"},	/* special = 4 */
+static short ibmmca_id_table[] = {
+	0x8efc,
+	0x8efd,
+	0x8ef8,
+	0x8eff,
+	0x8efe,
+	/* No entry for integrated SCSI, that's part of the register */
+	0
+};
+
+static const char *ibmmca_description[] = {
+	"IBM SCSI-2 F/W Adapter",	/* special = 0 */
+	"IBM 7568 Industrial Computer SCSI Adapter w/Cache",	/* special = 1 */
+	"IBM Expansion Unit SCSI Controller",	/* special = 2 */
+	"IBM SCSI Adapter w/Cache",	/* special = 3 */
+	"IBM SCSI Adapter",	/* special = 4 */
+	"IBM Integrated SCSI Controller", /* special = 5 */
 };
 
 /* Max number of logical devices (can be up from 0 to 14).  15 is the address
@@ -375,30 +388,30 @@
 };
 
 /* macros to access host data structure */
-#define subsystem_pun(hi) (hosts[(hi)]->this_id)
-#define subsystem_maxid(hi) (hosts[(hi)]->max_id)
-#define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld)
-#define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn)
-#define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi)
-#define local_checking_phase_flag(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_local_checking_phase_flag)
-#define got_interrupt(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_got_interrupt)
-#define stat_result(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_stat_result)
-#define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status)
-#define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command)
-#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
-#define last_scsi_blockcount(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_blockcount)
-#define last_scsi_logical_block(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_logical_block)
-#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
-#define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn)
-#define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS)
-#define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special)
-#define subsystem_connector_size(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_connector_size)
-#define adapter_speed(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_adapter_speed)
-#define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[2])
-#define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[3])
-#define pos4(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[4])
-#define pos5(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[5])
-#define pos6(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[6])
+#define subsystem_pun(h) ((h)->this_id)
+#define subsystem_maxid(h) ((h)->max_id)
+#define ld(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_ld)
+#define get_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_ldn)
+#define get_scsi(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_scsi)
+#define local_checking_phase_flag(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_local_checking_phase_flag)
+#define got_interrupt(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_got_interrupt)
+#define stat_result(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_stat_result)
+#define reset_status(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_reset_status)
+#define last_scsi_command(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_command)
+#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
+#define last_scsi_blockcount(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_blockcount)
+#define last_scsi_logical_block(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_logical_block)
+#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
+#define next_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_next_ldn)
+#define IBM_DS(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_IBM_DS)
+#define special(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_special)
+#define subsystem_connector_size(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_connector_size)
+#define adapter_speed(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_adapter_speed)
+#define pos2(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[2])
+#define pos3(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[3])
+#define pos4(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[4])
+#define pos5(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[5])
+#define pos6(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[6])
 
 /* Define a arbitrary number as subsystem-marker-type. This number is, as
    described in the ANSI-SCSI-standard, not occupied by other device-types. */
@@ -459,11 +472,6 @@
 /*counter of concurrent disk read/writes, to turn on/off disk led */
 static int disk_rw_in_progress = 0;
 
-/* host information */
-static int found = 0;
-static struct Scsi_Host *hosts[IM_MAX_HOSTS + 1] = {
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
 static unsigned int pos[8];	/* whole pos register-line for diagnosis */
 /* Taking into account the additions, made by ZP Gu.
  * This selects now the preset value from the configfile and
@@ -474,70 +482,68 @@
 static char ibm_ansi_order = 0;
 #endif
 
-static void issue_cmd(int, unsigned long, unsigned char);
+static void issue_cmd(struct Scsi_Host *, unsigned long, unsigned char);
 static void internal_done(Scsi_Cmnd * cmd);
-static void check_devices(int, int);
-static int immediate_assign(int, unsigned int, unsigned int, unsigned int, unsigned int);
-static int immediate_feature(int, unsigned int, unsigned int);
+static void check_devices(struct Scsi_Host *, int);
+static int immediate_assign(struct Scsi_Host *, unsigned int, unsigned int, unsigned int, unsigned int);
+static int immediate_feature(struct Scsi_Host *, unsigned int, unsigned int);
 #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
-static int immediate_reset(int, unsigned int);
+static int immediate_reset(struct Scsi_Host *, unsigned int);
 #endif
-static int device_inquiry(int, int);
-static int read_capacity(int, int);
-static int get_pos_info(int);
+static int device_inquiry(struct Scsi_Host *, int);
+static int read_capacity(struct Scsi_Host *, int);
+static int get_pos_info(struct Scsi_Host *);
 static char *ti_p(int);
 static char *ti_l(int);
 static char *ibmrate(unsigned int, int);
 static int probe_display(int);
-static int probe_bus_mode(int);
-static int device_exists(int, int, int *, int *);
-static struct Scsi_Host *ibmmca_register(struct scsi_host_template *, int, int, int, char *);
+static int probe_bus_mode(struct Scsi_Host *);
+static int device_exists(struct Scsi_Host *, int, int *, int *);
 static int option_setup(char *);
 /* local functions needed for proc_info */
-static int ldn_access_load(int, int);
-static int ldn_access_total_read_write(int);
+static int ldn_access_load(struct Scsi_Host *, int);
+static int ldn_access_total_read_write(struct Scsi_Host *);
 
 static irqreturn_t interrupt_handler(int irq, void *dev_id)
 {
-	int host_index, ihost_index;
 	unsigned int intr_reg;
 	unsigned int cmd_result;
 	unsigned int ldn;
+	unsigned long flags;
 	Scsi_Cmnd *cmd;
 	int lastSCSI;
-	struct Scsi_Host *dev = dev_id;
+	struct device *dev = dev_id;
+	struct Scsi_Host *shpnt = dev_get_drvdata(dev);
 
-	spin_lock(dev->host_lock);
-	    /* search for one adapter-response on shared interrupt */
-	    for (host_index = 0; hosts[host_index] && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST); host_index++);
-	/* return if some other device on this IRQ caused the interrupt */
-	if (!hosts[host_index]) {
-		spin_unlock(dev->host_lock);
+	spin_lock_irqsave(shpnt->host_lock, flags);
+
+	if(!(inb(IM_STAT_REG(shpnt)) & IM_INTR_REQUEST)) {
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 		return IRQ_NONE;
 	}
 
 	/* the reset-function already did all the job, even ints got
 	   renabled on the subsystem, so just return */
-	if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT)) {
-		reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS;
-		spin_unlock(dev->host_lock);
+	if ((reset_status(shpnt) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(shpnt) == IM_RESET_FINISHED_OK_NO_INT)) {
+		reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 		return IRQ_HANDLED;
 	}
 
 	/*must wait for attention reg not busy, then send EOI to subsystem */
 	while (1) {
-		if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+		if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
 			break;
 		cpu_relax();
 	}
-	ihost_index = host_index;
+
 	/*get command result and logical device */
-	intr_reg = (unsigned char) (inb(IM_INTR_REG(ihost_index)));
+	intr_reg = (unsigned char) (inb(IM_INTR_REG(shpnt)));
 	cmd_result = intr_reg & 0xf0;
 	ldn = intr_reg & 0x0f;
 	/* get the last_scsi_command here */
-	lastSCSI = last_scsi_command(ihost_index)[ldn];
-	outb(IM_EOI | ldn, IM_ATTN_REG(ihost_index));
+	lastSCSI = last_scsi_command(shpnt)[ldn];
+	outb(IM_EOI | ldn, IM_ATTN_REG(shpnt));
 	
 	/*these should never happen (hw fails, or a local programming bug) */
 	if (!global_command_error_excuse) {
@@ -547,38 +553,38 @@
 		case IM_SOFTWARE_SEQUENCING_ERROR:
 		case IM_CMD_ERROR:
 			printk(KERN_ERR "IBM MCA SCSI: Fatal Subsystem ERROR!\n");
-			printk(KERN_ERR "              Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(ihost_index)[ldn].scb.enable);
-			if (ld(ihost_index)[ldn].cmd)
-				printk("%ld/%ld,", (long) (ld(ihost_index)[ldn].cmd->request_bufflen), (long) (ld(ihost_index)[ldn].scb.sys_buf_length));
+			printk(KERN_ERR "              Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(shpnt)[ldn].scb.enable);
+			if (ld(shpnt)[ldn].cmd)
+				printk("%ld/%ld,", (long) (scsi_bufflen(ld(shpnt)[ldn].cmd)), (long) (ld(shpnt)[ldn].scb.sys_buf_length));
 			else
 				printk("none,");
-			if (ld(ihost_index)[ldn].cmd)
-				printk("Blocksize=%d", ld(ihost_index)[ldn].scb.u2.blk.length);
+			if (ld(shpnt)[ldn].cmd)
+				printk("Blocksize=%d", ld(shpnt)[ldn].scb.u2.blk.length);
 			else
 				printk("Blocksize=none");
-			printk(", host=0x%x, ldn=0x%x\n", ihost_index, ldn);
-			if (ld(ihost_index)[ldn].cmd) {
-				printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u2.blk.count);
-				printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u1.log_blk_adr);
+			printk(", host=%p, ldn=0x%x\n", shpnt, ldn);
+			if (ld(shpnt)[ldn].cmd) {
+				printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(shpnt)[ldn], ld(shpnt)[ldn].scb.u2.blk.count);
+				printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(shpnt)[ldn], ld(shpnt)[ldn].scb.u1.log_blk_adr);
 			}
 			printk(KERN_ERR "Reason given: %s\n", (cmd_result == IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : (cmd_result == IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN");
 			/* if errors appear, enter this section to give detailed info */
 			printk(KERN_ERR "IBM MCA SCSI: Subsystem Error-Status follows:\n");
-			printk(KERN_ERR "              Command Type................: %x\n", last_scsi_type(ihost_index)[ldn]);
-			printk(KERN_ERR "              Attention Register..........: %x\n", inb(IM_ATTN_REG(ihost_index)));
-			printk(KERN_ERR "              Basic Control Register......: %x\n", inb(IM_CTR_REG(ihost_index)));
+			printk(KERN_ERR "              Command Type................: %x\n", last_scsi_type(shpnt)[ldn]);
+			printk(KERN_ERR "              Attention Register..........: %x\n", inb(IM_ATTN_REG(shpnt)));
+			printk(KERN_ERR "              Basic Control Register......: %x\n", inb(IM_CTR_REG(shpnt)));
 			printk(KERN_ERR "              Interrupt Status Register...: %x\n", intr_reg);
-			printk(KERN_ERR "              Basic Status Register.......: %x\n", inb(IM_STAT_REG(ihost_index)));
-			if ((last_scsi_type(ihost_index)[ldn] == IM_SCB) || (last_scsi_type(ihost_index)[ldn] == IM_LONG_SCB)) {
-				printk(KERN_ERR "              SCB-Command.................: %x\n", ld(ihost_index)[ldn].scb.command);
-				printk(KERN_ERR "              SCB-Enable..................: %x\n", ld(ihost_index)[ldn].scb.enable);
-				printk(KERN_ERR "              SCB-logical block address...: %lx\n", ld(ihost_index)[ldn].scb.u1.log_blk_adr);
-				printk(KERN_ERR "              SCB-system buffer address...: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_adr);
-				printk(KERN_ERR "              SCB-system buffer length....: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_length);
-				printk(KERN_ERR "              SCB-tsb address.............: %lx\n", ld(ihost_index)[ldn].scb.tsb_adr);
-				printk(KERN_ERR "              SCB-Chain address...........: %lx\n", ld(ihost_index)[ldn].scb.scb_chain_adr);
-				printk(KERN_ERR "              SCB-block count.............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.count);
-				printk(KERN_ERR "              SCB-block length............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.length);
+			printk(KERN_ERR "              Basic Status Register.......: %x\n", inb(IM_STAT_REG(shpnt)));
+			if ((last_scsi_type(shpnt)[ldn] == IM_SCB) || (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB)) {
+				printk(KERN_ERR "              SCB-Command.................: %x\n", ld(shpnt)[ldn].scb.command);
+				printk(KERN_ERR "              SCB-Enable..................: %x\n", ld(shpnt)[ldn].scb.enable);
+				printk(KERN_ERR "              SCB-logical block address...: %lx\n", ld(shpnt)[ldn].scb.u1.log_blk_adr);
+				printk(KERN_ERR "              SCB-system buffer address...: %lx\n", ld(shpnt)[ldn].scb.sys_buf_adr);
+				printk(KERN_ERR "              SCB-system buffer length....: %lx\n", ld(shpnt)[ldn].scb.sys_buf_length);
+				printk(KERN_ERR "              SCB-tsb address.............: %lx\n", ld(shpnt)[ldn].scb.tsb_adr);
+				printk(KERN_ERR "              SCB-Chain address...........: %lx\n", ld(shpnt)[ldn].scb.scb_chain_adr);
+				printk(KERN_ERR "              SCB-block count.............: %x\n", ld(shpnt)[ldn].scb.u2.blk.count);
+				printk(KERN_ERR "              SCB-block length............: %x\n", ld(shpnt)[ldn].scb.u2.blk.length);
 			}
 			printk(KERN_ERR "              Send this report to the maintainer.\n");
 			panic("IBM MCA SCSI: Fatal error message from the subsystem (0x%X,0x%X)!\n", lastSCSI, cmd_result);
@@ -600,72 +606,73 @@
 		}
 	}
 	/* if no panic appeared, increase the interrupt-counter */
-	IBM_DS(ihost_index).total_interrupts++;
+	IBM_DS(shpnt).total_interrupts++;
 	/*only for local checking phase */
-	if (local_checking_phase_flag(ihost_index)) {
-		stat_result(ihost_index) = cmd_result;
-		got_interrupt(ihost_index) = 1;
-		reset_status(ihost_index) = IM_RESET_FINISHED_OK;
-		last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-		spin_unlock(dev->host_lock);
+	if (local_checking_phase_flag(shpnt)) {
+		stat_result(shpnt) = cmd_result;
+		got_interrupt(shpnt) = 1;
+		reset_status(shpnt) = IM_RESET_FINISHED_OK;
+		last_scsi_command(shpnt)[ldn] = NO_SCSI;
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 		return IRQ_HANDLED;
 	}
 	/* handling of commands coming from upper level of scsi driver */
-	if (last_scsi_type(ihost_index)[ldn] == IM_IMM_CMD) {
+	if (last_scsi_type(shpnt)[ldn] == IM_IMM_CMD) {
 		/* verify ldn, and may handle rare reset immediate command */
-		if ((reset_status(ihost_index) == IM_RESET_IN_PROGRESS) && (last_scsi_command(ihost_index)[ldn] == IM_RESET_IMM_CMD)) {
+		if ((reset_status(shpnt) == IM_RESET_IN_PROGRESS) && (last_scsi_command(shpnt)[ldn] == IM_RESET_IMM_CMD)) {
 			if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
 				disk_rw_in_progress = 0;
 				PS2_DISK_LED_OFF();
-				reset_status(ihost_index) = IM_RESET_FINISHED_FAIL;
+				reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
 			} else {
 				/*reset disk led counter, turn off disk led */
 				disk_rw_in_progress = 0;
 				PS2_DISK_LED_OFF();
-				reset_status(ihost_index) = IM_RESET_FINISHED_OK;
+				reset_status(shpnt) = IM_RESET_FINISHED_OK;
 			}
-			stat_result(ihost_index) = cmd_result;
-			last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-			last_scsi_type(ihost_index)[ldn] = 0;
-			spin_unlock(dev->host_lock);
+			stat_result(shpnt) = cmd_result;
+			last_scsi_command(shpnt)[ldn] = NO_SCSI;
+			last_scsi_type(shpnt)[ldn] = 0;
+			spin_unlock_irqrestore(shpnt->host_lock, flags);
 			return IRQ_HANDLED;
-		} else if (last_scsi_command(ihost_index)[ldn] == IM_ABORT_IMM_CMD) {
+		} else if (last_scsi_command(shpnt)[ldn] == IM_ABORT_IMM_CMD) {
 			/* react on SCSI abort command */
 #ifdef IM_DEBUG_PROBE
 			printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n");
 #endif
 			disk_rw_in_progress = 0;
 			PS2_DISK_LED_OFF();
-			cmd = ld(ihost_index)[ldn].cmd;
-			ld(ihost_index)[ldn].cmd = NULL;
+			cmd = ld(shpnt)[ldn].cmd;
+			ld(shpnt)[ldn].cmd = NULL;
 			if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
 				cmd->result = DID_NO_CONNECT << 16;
 			else
 				cmd->result = DID_ABORT << 16;
-			stat_result(ihost_index) = cmd_result;
-			last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-			last_scsi_type(ihost_index)[ldn] = 0;
+			stat_result(shpnt) = cmd_result;
+			last_scsi_command(shpnt)[ldn] = NO_SCSI;
+			last_scsi_type(shpnt)[ldn] = 0;
 			if (cmd->scsi_done)
 				(cmd->scsi_done) (cmd);	/* should be the internal_done */
-			spin_unlock(dev->host_lock);
+			spin_unlock_irqrestore(shpnt->host_lock, flags);
 			return IRQ_HANDLED;
 		} else {
 			disk_rw_in_progress = 0;
 			PS2_DISK_LED_OFF();
-			reset_status(ihost_index) = IM_RESET_FINISHED_OK;
-			stat_result(ihost_index) = cmd_result;
-			last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-			spin_unlock(dev->host_lock);
+			reset_status(shpnt) = IM_RESET_FINISHED_OK;
+			stat_result(shpnt) = cmd_result;
+			last_scsi_command(shpnt)[ldn] = NO_SCSI;
+			spin_unlock_irqrestore(shpnt->host_lock, flags);
 			return IRQ_HANDLED;
 		}
 	}
-	last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-	last_scsi_type(ihost_index)[ldn] = 0;
-	cmd = ld(ihost_index)[ldn].cmd;
-	ld(ihost_index)[ldn].cmd = NULL;
+	last_scsi_command(shpnt)[ldn] = NO_SCSI;
+	last_scsi_type(shpnt)[ldn] = 0;
+	cmd = ld(shpnt)[ldn].cmd;
+	ld(shpnt)[ldn].cmd = NULL;
 #ifdef IM_DEBUG_TIMEOUT
 	if (cmd) {
 		if ((cmd->target == TIMEOUT_PUN) && (cmd->device->lun == TIMEOUT_LUN)) {
+			spin_unlock_irqsave(shpnt->host_lock, flags);
 			printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", cmd->target, cmd->device->lun);
 			return IRQ_HANDLED;
 		}
@@ -674,15 +681,15 @@
 	/*if no command structure, just return, else clear cmd */
 	if (!cmd)
 	{
-		spin_unlock(dev->host_lock);
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 		return IRQ_HANDLED;
 	}
 
 #ifdef IM_DEBUG_INT
-	printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(ihost_index)[ldn].tsb.dev_status, ld(ihost_index)[ldn].tsb.cmd_status, ld(ihost_index)[ldn].tsb.dev_error, ld(ihost_index)[ldn].tsb.cmd_error);
+	printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(shpnt)[ldn].tsb.dev_status, ld(shpnt)[ldn].tsb.cmd_status, ld(shpnt)[ldn].tsb.dev_error, ld(shpnt)[ldn].tsb.cmd_error);
 #endif
 	/*if this is end of media read/write, may turn off PS/2 disk led */
-	if ((ld(ihost_index)[ldn].device_type != TYPE_NO_LUN) && (ld(ihost_index)[ldn].device_type != TYPE_NO_DEVICE)) {
+	if ((ld(shpnt)[ldn].device_type != TYPE_NO_LUN) && (ld(shpnt)[ldn].device_type != TYPE_NO_DEVICE)) {
 		/* only access this, if there was a valid device addressed */
 		if (--disk_rw_in_progress == 0)
 			PS2_DISK_LED_OFF();
@@ -693,8 +700,8 @@
 	 * adapters do not support CMD_TERMINATED, TASK_SET_FULL and
 	 * ACA_ACTIVE as returning statusbyte information. (ML) */
 	if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
-		cmd->result = (unsigned char) (ld(ihost_index)[ldn].tsb.dev_status & 0x1e);
-		IBM_DS(ihost_index).total_errors++;
+		cmd->result = (unsigned char) (ld(shpnt)[ldn].tsb.dev_status & 0x1e);
+		IBM_DS(shpnt).total_errors++;
 	} else
 		cmd->result = 0;
 	/* write device status into cmd->result, and call done function */
@@ -705,24 +712,25 @@
 		cmd->result |= DID_OK << 16;
 	if (cmd->scsi_done)
 		(cmd->scsi_done) (cmd);
-	spin_unlock(dev->host_lock);
+	spin_unlock_irqrestore(shpnt->host_lock, flags);
 	return IRQ_HANDLED;
 }
 
-static void issue_cmd(int host_index, unsigned long cmd_reg, unsigned char attn_reg)
+static void issue_cmd(struct Scsi_Host *shpnt, unsigned long cmd_reg,
+		      unsigned char attn_reg)
 {
 	unsigned long flags;
 	/* must wait for attention reg not busy */
 	while (1) {
-		spin_lock_irqsave(hosts[host_index]->host_lock, flags);
-		if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+		spin_lock_irqsave(shpnt->host_lock, flags);
+		if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
 			break;
-		spin_unlock_irqrestore(hosts[host_index]->host_lock, flags);
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 	}
 	/* write registers and enable system interrupts */
-	outl(cmd_reg, IM_CMD_REG(host_index));
-	outb(attn_reg, IM_ATTN_REG(host_index));
-	spin_unlock_irqrestore(hosts[host_index]->host_lock, flags);
+	outl(cmd_reg, IM_CMD_REG(shpnt));
+	outb(attn_reg, IM_ATTN_REG(shpnt));
+	spin_unlock_irqrestore(shpnt->host_lock, flags);
 }
 
 static void internal_done(Scsi_Cmnd * cmd)
@@ -732,34 +740,34 @@
 }
 
 /* SCSI-SCB-command for device_inquiry */
-static int device_inquiry(int host_index, int ldn)
+static int device_inquiry(struct Scsi_Host *shpnt, int ldn)
 {
 	int retr;
 	struct im_scb *scb;
 	struct im_tsb *tsb;
 	unsigned char *buf;
 
-	scb = &(ld(host_index)[ldn].scb);
-	tsb = &(ld(host_index)[ldn].tsb);
-	buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
-	ld(host_index)[ldn].tsb.dev_status = 0;	/* prepare statusblock */
+	scb = &(ld(shpnt)[ldn].scb);
+	tsb = &(ld(shpnt)[ldn].tsb);
+	buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
+	ld(shpnt)[ldn].tsb.dev_status = 0;	/* prepare statusblock */
 	for (retr = 0; retr < 3; retr++) {
 		/* fill scb with inquiry command */
 		scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT;
 		scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
-		last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
-		last_scsi_type(host_index)[ldn] = IM_SCB;
+		last_scsi_command(shpnt)[ldn] = IM_DEVICE_INQUIRY_CMD;
+		last_scsi_type(shpnt)[ldn] = IM_SCB;
 		scb->sys_buf_adr = isa_virt_to_bus(buf);
 		scb->sys_buf_length = 255;	/* maximum bufferlength gives max info */
 		scb->tsb_adr = isa_virt_to_bus(tsb);
 		/* issue scb to passed ldn, and busy wait for interrupt */
-		got_interrupt(host_index) = 0;
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
-		while (!got_interrupt(host_index))
+		got_interrupt(shpnt) = 0;
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+		while (!got_interrupt(shpnt))
 			barrier();
 
 		/*if command successful, break */
-		if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+		if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
 			return 1;
 	}
 	/*if all three retries failed, return "no device at this ldn" */
@@ -769,34 +777,34 @@
 		return 1;
 }
 
-static int read_capacity(int host_index, int ldn)
+static int read_capacity(struct Scsi_Host *shpnt, int ldn)
 {
 	int retr;
 	struct im_scb *scb;
 	struct im_tsb *tsb;
 	unsigned char *buf;
 
-	scb = &(ld(host_index)[ldn].scb);
-	tsb = &(ld(host_index)[ldn].tsb);
-	buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
-	ld(host_index)[ldn].tsb.dev_status = 0;
+	scb = &(ld(shpnt)[ldn].scb);
+	tsb = &(ld(shpnt)[ldn].tsb);
+	buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
+	ld(shpnt)[ldn].tsb.dev_status = 0;
 	for (retr = 0; retr < 3; retr++) {
 		/*fill scb with read capacity command */
 		scb->command = IM_READ_CAPACITY_CMD;
 		scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
-		last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
-		last_scsi_type(host_index)[ldn] = IM_SCB;
+		last_scsi_command(shpnt)[ldn] = IM_READ_CAPACITY_CMD;
+		last_scsi_type(shpnt)[ldn] = IM_SCB;
 		scb->sys_buf_adr = isa_virt_to_bus(buf);
 		scb->sys_buf_length = 8;
 		scb->tsb_adr = isa_virt_to_bus(tsb);
 		/*issue scb to passed ldn, and busy wait for interrupt */
-		got_interrupt(host_index) = 0;
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
-		while (!got_interrupt(host_index))
+		got_interrupt(shpnt) = 0;
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+		while (!got_interrupt(shpnt))
 			barrier();
 
 		/*if got capacity, get block length and return one device found */
-		if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+		if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
 			return 1;
 	}
 	/*if all three retries failed, return "no device at this ldn" */
@@ -806,39 +814,39 @@
 		return 1;
 }
 
-static int get_pos_info(int host_index)
+static int get_pos_info(struct Scsi_Host *shpnt)
 {
 	int retr;
 	struct im_scb *scb;
 	struct im_tsb *tsb;
 	unsigned char *buf;
 
-	scb = &(ld(host_index)[MAX_LOG_DEV].scb);
-	tsb = &(ld(host_index)[MAX_LOG_DEV].tsb);
-	buf = (unsigned char *) (&(ld(host_index)[MAX_LOG_DEV].buf));
-	ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0;
+	scb = &(ld(shpnt)[MAX_LOG_DEV].scb);
+	tsb = &(ld(shpnt)[MAX_LOG_DEV].tsb);
+	buf = (unsigned char *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
+	ld(shpnt)[MAX_LOG_DEV].tsb.dev_status = 0;
 	for (retr = 0; retr < 3; retr++) {
 		/*fill scb with get_pos_info command */
 		scb->command = IM_GET_POS_INFO_CMD;
 		scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
-		last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
-		last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB;
+		last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
+		last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_SCB;
 		scb->sys_buf_adr = isa_virt_to_bus(buf);
-		if (special(host_index) == IBM_SCSI2_FW)
+		if (special(shpnt) == IBM_SCSI2_FW)
 			scb->sys_buf_length = 256;	/* get all info from F/W adapter */
 		else
 			scb->sys_buf_length = 18;	/* get exactly 18 bytes for other SCSI */
 		scb->tsb_adr = isa_virt_to_bus(tsb);
 		/*issue scb to ldn=15, and busy wait for interrupt */
-		got_interrupt(host_index) = 0;
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
+		got_interrupt(shpnt) = 0;
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
 		
 		/* FIXME: timeout */
-		while (!got_interrupt(host_index))
+		while (!got_interrupt(shpnt))
 			barrier();
 
 		/*if got POS-stuff, get block length and return one device found */
-		if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+		if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
 			return 1;
 	}
 	/* if all three retries failed, return "no device at this ldn" */
@@ -851,14 +859,16 @@
 /* SCSI-immediate-command for assign. This functions maps/unmaps specific
  ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
  subsystem and for dynamical remapping od ldns. */
-static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, unsigned int ldn, unsigned int operation)
+static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
+			    unsigned int lun, unsigned int ldn,
+			    unsigned int operation)
 {
 	int retr;
 	unsigned long imm_cmd;
 
 	for (retr = 0; retr < 3; retr++) {
 		/* select mutation level of the SCSI-adapter */
-		switch (special(host_index)) {
+		switch (special(shpnt)) {
 		case IBM_SCSI2_FW:
 			imm_cmd = (unsigned long) (IM_ASSIGN_IMM_CMD);
 			imm_cmd |= (unsigned long) ((lun & 7) << 24);
@@ -867,7 +877,7 @@
 			imm_cmd |= (unsigned long) ((ldn & 15) << 16);
 			break;
 		default:
-			imm_cmd = inl(IM_CMD_REG(host_index));
+			imm_cmd = inl(IM_CMD_REG(shpnt));
 			imm_cmd &= (unsigned long) (0xF8000000);	/* keep reserved bits */
 			imm_cmd |= (unsigned long) (IM_ASSIGN_IMM_CMD);
 			imm_cmd |= (unsigned long) ((lun & 7) << 24);
@@ -876,15 +886,15 @@
 			imm_cmd |= (unsigned long) ((ldn & 15) << 16);
 			break;
 		}
-		last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
-		last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
-		got_interrupt(host_index) = 0;
-		issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
-		while (!got_interrupt(host_index))
+		last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
+		last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
+		got_interrupt(shpnt) = 0;
+		issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
+		while (!got_interrupt(shpnt))
 			barrier();
 
 		/*if command successful, break */
-		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+		if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
 	if (retr >= 3)
@@ -893,7 +903,7 @@
 		return 1;
 }
 
-static int immediate_feature(int host_index, unsigned int speed, unsigned int timeout)
+static int immediate_feature(struct Scsi_Host *shpnt, unsigned int speed, unsigned int timeout)
 {
 	int retr;
 	unsigned long imm_cmd;
@@ -903,16 +913,16 @@
 		imm_cmd = IM_FEATURE_CTR_IMM_CMD;
 		imm_cmd |= (unsigned long) ((speed & 0x7) << 29);
 		imm_cmd |= (unsigned long) ((timeout & 0x1fff) << 16);
-		last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
-		last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
-		got_interrupt(host_index) = 0;
+		last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
+		last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
+		got_interrupt(shpnt) = 0;
 		/* we need to run into command errors in order to probe for the
 		 * right speed! */
 		global_command_error_excuse = 1;
-		issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
+		issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
 		
 		/* FIXME: timeout */
-		while (!got_interrupt(host_index))
+		while (!got_interrupt(shpnt))
 			barrier();
 		if (global_command_error_excuse == CMD_FAIL) {
 			global_command_error_excuse = 0;
@@ -920,7 +930,7 @@
 		} else
 			global_command_error_excuse = 0;
 		/*if command successful, break */
-		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+		if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
 	if (retr >= 3)
@@ -930,35 +940,35 @@
 }
 
 #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
-static int immediate_reset(int host_index, unsigned int ldn)
+static int immediate_reset(struct Scsi_Host *shpnt, unsigned int ldn)
 {
 	int retries;
 	int ticks;
 	unsigned long imm_command;
 
 	for (retries = 0; retries < 3; retries++) {
-		imm_command = inl(IM_CMD_REG(host_index));
+		imm_command = inl(IM_CMD_REG(shpnt));
 		imm_command &= (unsigned long) (0xFFFF0000);	/* keep reserved bits */
 		imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
-		last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD;
-		last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
-		got_interrupt(host_index) = 0;
-		reset_status(host_index) = IM_RESET_IN_PROGRESS;
-		issue_cmd(host_index, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
+		last_scsi_command(shpnt)[ldn] = IM_RESET_IMM_CMD;
+		last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
+		got_interrupt(shpnt) = 0;
+		reset_status(shpnt) = IM_RESET_IN_PROGRESS;
+		issue_cmd(shpnt, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
 		ticks = IM_RESET_DELAY * HZ;
-		while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) {
+		while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks) {
 			udelay((1 + 999 / HZ) * 1000);
 			barrier();
 		}
 		/* if reset did not complete, just complain */
 		if (!ticks) {
 			printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
-			reset_status(host_index) = IM_RESET_FINISHED_OK;
+			reset_status(shpnt) = IM_RESET_FINISHED_OK;
 			/* did not work, finish */
 			return 1;
 		}
 		/*if command successful, break */
-		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+		if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
 	if (retries >= 3)
@@ -1060,35 +1070,35 @@
 	return 0;
 }
 
-static int probe_bus_mode(int host_index)
+static int probe_bus_mode(struct Scsi_Host *shpnt)
 {
 	struct im_pos_info *info;
 	int num_bus = 0;
 	int ldn;
 
-	info = (struct im_pos_info *) (&(ld(host_index)[MAX_LOG_DEV].buf));
-	if (get_pos_info(host_index)) {
+	info = (struct im_pos_info *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
+	if (get_pos_info(shpnt)) {
 		if (info->connector_size & 0xf000)
-			subsystem_connector_size(host_index) = 16;
+			subsystem_connector_size(shpnt) = 16;
 		else
-			subsystem_connector_size(host_index) = 32;
+			subsystem_connector_size(shpnt) = 32;
 		num_bus |= (info->pos_4b & 8) >> 3;
 		for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
-			if ((special(host_index) == IBM_SCSI_WCACHE) || (special(host_index) == IBM_7568_WCACHE)) {
+			if ((special(shpnt) == IBM_SCSI_WCACHE) || (special(shpnt) == IBM_7568_WCACHE)) {
 				if (!((info->cache_stat >> ldn) & 1))
-					ld(host_index)[ldn].cache_flag = 0;
+					ld(shpnt)[ldn].cache_flag = 0;
 			}
 			if (!((info->retry_stat >> ldn) & 1))
-				ld(host_index)[ldn].retry_flag = 0;
+				ld(shpnt)[ldn].retry_flag = 0;
 		}
 #ifdef IM_DEBUG_PROBE
 		printk("IBM MCA SCSI: SCSI-Cache bits: ");
 		for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
-			printk("%d", ld(host_index)[ldn].cache_flag);
+			printk("%d", ld(shpnt)[ldn].cache_flag);
 		}
 		printk("\nIBM MCA SCSI: SCSI-Retry bits: ");
 		for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
-			printk("%d", ld(host_index)[ldn].retry_flag);
+			printk("%d", ld(shpnt)[ldn].retry_flag);
 		}
 		printk("\n");
 #endif
@@ -1097,7 +1107,7 @@
 }
 
 /* probing scsi devices */
-static void check_devices(int host_index, int adaptertype)
+static void check_devices(struct Scsi_Host *shpnt, int adaptertype)
 {
 	int id, lun, ldn, ticks;
 	int count_devices;	/* local counter for connected device */
@@ -1108,24 +1118,24 @@
 	/* assign default values to certain variables */
 	ticks = 0;
 	count_devices = 0;
-	IBM_DS(host_index).dyn_flag = 0;	/* normally no need for dynamical ldn management */
-	IBM_DS(host_index).total_errors = 0;	/* set errorcounter to 0 */
-	next_ldn(host_index) = 7;	/* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
+	IBM_DS(shpnt).dyn_flag = 0;	/* normally no need for dynamical ldn management */
+	IBM_DS(shpnt).total_errors = 0;	/* set errorcounter to 0 */
+	next_ldn(shpnt) = 7;	/* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
 
 	/* initialize the very important driver-informational arrays/structs */
-	memset(ld(host_index), 0, sizeof(ld(host_index)));
+	memset(ld(shpnt), 0, sizeof(ld(shpnt)));
 	for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
-		last_scsi_command(host_index)[ldn] = NO_SCSI;	/* emptify last SCSI-command storage */
-		last_scsi_type(host_index)[ldn] = 0;
-		ld(host_index)[ldn].cache_flag = 1;
-		ld(host_index)[ldn].retry_flag = 1;
+		last_scsi_command(shpnt)[ldn] = NO_SCSI;	/* emptify last SCSI-command storage */
+		last_scsi_type(shpnt)[ldn] = 0;
+		ld(shpnt)[ldn].cache_flag = 1;
+		ld(shpnt)[ldn].retry_flag = 1;
 	}
-	memset(get_ldn(host_index), TYPE_NO_DEVICE, sizeof(get_ldn(host_index)));	/* this is essential ! */
-	memset(get_scsi(host_index), TYPE_NO_DEVICE, sizeof(get_scsi(host_index)));	/* this is essential ! */
+	memset(get_ldn(shpnt), TYPE_NO_DEVICE, sizeof(get_ldn(shpnt)));	/* this is essential ! */
+	memset(get_scsi(shpnt), TYPE_NO_DEVICE, sizeof(get_scsi(shpnt)));	/* this is essential ! */
 	for (lun = 0; lun < 8; lun++) {
 		/* mark the adapter at its pun on all luns */
-		get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER;
-		get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV;	/* make sure, the subsystem
+		get_scsi(shpnt)[subsystem_pun(shpnt)][lun] = TYPE_IBM_SCSI_ADAPTER;
+		get_ldn(shpnt)[subsystem_pun(shpnt)][lun] = MAX_LOG_DEV;	/* make sure, the subsystem
 											   ldn is active for all
 											   luns. */
 	}
@@ -1134,9 +1144,9 @@
 	/* monitor connected on model XX95. */
 
 	/* STEP 1: */
-	adapter_speed(host_index) = global_adapter_speed;
-	speedrun = adapter_speed(host_index);
-	while (immediate_feature(host_index, speedrun, adapter_timeout) == 2) {
+	adapter_speed(shpnt) = global_adapter_speed;
+	speedrun = adapter_speed(shpnt);
+	while (immediate_feature(shpnt, speedrun, adapter_timeout) == 2) {
 		probe_display(1);
 		if (speedrun == 7)
 			panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n");
@@ -1144,30 +1154,30 @@
 		if (speedrun > 7)
 			speedrun = 7;
 	}
-	adapter_speed(host_index) = speedrun;
+	adapter_speed(shpnt) = speedrun;
 	/* Get detailed information about the current adapter, necessary for
 	 * device operations: */
-	num_bus = probe_bus_mode(host_index);
+	num_bus = probe_bus_mode(shpnt);
 
 	/* num_bus contains only valid data for the F/W adapter! */
 	if (adaptertype == IBM_SCSI2_FW) {	/* F/W SCSI adapter: */
 		/* F/W adapter PUN-space extension evaluation: */
 		if (num_bus) {
 			printk(KERN_INFO "IBM MCA SCSI: Separate bus mode (wide-addressing enabled)\n");
-			subsystem_maxid(host_index) = 16;
+			subsystem_maxid(shpnt) = 16;
 		} else {
 			printk(KERN_INFO "IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n");
-			subsystem_maxid(host_index) = 8;
+			subsystem_maxid(shpnt) = 8;
 		}
 		printk(KERN_INFO "IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", ibmrate(speedrun, adaptertype));
 	} else			/* all other IBM SCSI adapters: */
 		printk(KERN_INFO "IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", ibmrate(speedrun, adaptertype));
 
 	/* assign correct PUN device space */
-	max_pun = subsystem_maxid(host_index);
+	max_pun = subsystem_maxid(shpnt);
 
 #ifdef IM_DEBUG_PROBE
-	printk("IBM MCA SCSI: Current SCSI-host index: %d\n", host_index);
+	printk("IBM MCA SCSI: Current SCSI-host index: %d\n", shpnt);
 	printk("IBM MCA SCSI: Removing default logical SCSI-device mapping.");
 #else
 	printk(KERN_INFO "IBM MCA SCSI: Dev. Order: %s, Mapping (takes <2min): ", (ibm_ansi_order) ? "ANSI" : "New");
@@ -1177,7 +1187,7 @@
 #ifdef IM_DEBUG_PROBE
 		printk(".");
 #endif
-		immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN);	/* remove ldn (wherever) */
+		immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN);	/* remove ldn (wherever) */
 	}
 	lun = 0;		/* default lun is 0 */
 #ifndef IM_DEBUG_PROBE
@@ -1196,18 +1206,18 @@
 #ifdef IM_DEBUG_PROBE
 			printk(".");
 #endif
-			if (id != subsystem_pun(host_index)) {
+			if (id != subsystem_pun(shpnt)) {
 				/* if pun is not the adapter: */
 				/* set ldn=0 to pun,lun */
-				immediate_assign(host_index, id, lun, PROBE_LDN, SET_LDN);
-				if (device_inquiry(host_index, PROBE_LDN)) {	/* probe device */
-					get_scsi(host_index)[id][lun] = (unsigned char) (ld(host_index)[PROBE_LDN].buf[0]);
+				immediate_assign(shpnt, id, lun, PROBE_LDN, SET_LDN);
+				if (device_inquiry(shpnt, PROBE_LDN)) {	/* probe device */
+					get_scsi(shpnt)[id][lun] = (unsigned char) (ld(shpnt)[PROBE_LDN].buf[0]);
 					/* entry, even for NO_LUN */
-					if (ld(host_index)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
+					if (ld(shpnt)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
 						count_devices++;	/* a existing device is found */
 				}
 				/* remove ldn */
-				immediate_assign(host_index, id, lun, PROBE_LDN, REMOVE_LDN);
+				immediate_assign(shpnt, id, lun, PROBE_LDN, REMOVE_LDN);
 			}
 		}
 #ifndef IM_DEBUG_PROBE
@@ -1227,16 +1237,16 @@
 #ifdef IM_DEBUG_PROBE
 			printk(".");
 #endif
-			if (id != subsystem_pun(host_index)) {
-				if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN && get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE) {
+			if (id != subsystem_pun(shpnt)) {
+				if (get_scsi(shpnt)[id][lun] != TYPE_NO_LUN && get_scsi(shpnt)[id][lun] != TYPE_NO_DEVICE) {
 					/* Only map if accepted type. Always enter for
 					   lun == 0 to get no gaps into ldn-mapping for ldn<7. */
-					immediate_assign(host_index, id, lun, ldn, SET_LDN);
-					get_ldn(host_index)[id][lun] = ldn;	/* map ldn */
-					if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {
+					immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+					get_ldn(shpnt)[id][lun] = ldn;	/* map ldn */
+					if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
 #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
 						printk("resetting device at ldn=%x ... ", ldn);
-						immediate_reset(host_index, ldn);
+						immediate_reset(shpnt, ldn);
 #endif
 						ldn++;
 					} else {
@@ -1244,15 +1254,15 @@
 						 * handle it or because it has problems */
 						if (lun > 0) {
 							/* remove mapping */
-							get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
-							immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN);
+							get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
+							immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN);
 						} else
 							ldn++;
 					}
 				} else if (lun == 0) {
 					/* map lun == 0, even if no device exists */
-					immediate_assign(host_index, id, lun, ldn, SET_LDN);
-					get_ldn(host_index)[id][lun] = ldn;	/* map ldn */
+					immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+					get_ldn(shpnt)[id][lun] = ldn;	/* map ldn */
 					ldn++;
 				}
 			}
@@ -1262,14 +1272,14 @@
 	/* map remaining ldns to non-existing devices */
 	for (lun = 1; lun < 8 && ldn < MAX_LOG_DEV; lun++)
 		for (id = 0; id < max_pun && ldn < MAX_LOG_DEV; id++) {
-			if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN || get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE) {
+			if (get_scsi(shpnt)[id][lun] == TYPE_NO_LUN || get_scsi(shpnt)[id][lun] == TYPE_NO_DEVICE) {
 				probe_display(1);
 				/* Map remaining ldns only to NON-existing pun,lun
 				   combinations to make sure an inquiry will fail.
 				   For MULTI_LUN, it is needed to avoid adapter autonome
 				   SCSI-remapping. */
-				immediate_assign(host_index, id, lun, ldn, SET_LDN);
-				get_ldn(host_index)[id][lun] = ldn;
+				immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+				get_ldn(shpnt)[id][lun] = ldn;
 				ldn++;
 			}
 		}
@@ -1292,51 +1302,51 @@
 	for (id = 0; id < max_pun; id++) {
 		printk("%2d     ", id);
 		for (lun = 0; lun < 8; lun++)
-			printk("%2s ", ti_p(get_scsi(host_index)[id][lun]));
+			printk("%2s ", ti_p(get_scsi(shpnt)[id][lun]));
 		printk("      %2d     ", id);
 		for (lun = 0; lun < 8; lun++)
-			printk("%2s ", ti_l(get_ldn(host_index)[id][lun]));
+			printk("%2s ", ti_l(get_ldn(shpnt)[id][lun]));
 		printk("\n");
 	}
 #endif
 
 	/* assign total number of found SCSI-devices to the statistics struct */
-	IBM_DS(host_index).total_scsi_devices = count_devices;
+	IBM_DS(shpnt).total_scsi_devices = count_devices;
 
 	/* decide for output in /proc-filesystem, if the configuration of
 	   SCSI-devices makes dynamical reassignment of devices necessary */
 	if (count_devices >= MAX_LOG_DEV)
-		IBM_DS(host_index).dyn_flag = 1;	/* dynamical assignment is necessary */
+		IBM_DS(shpnt).dyn_flag = 1;	/* dynamical assignment is necessary */
 	else
-		IBM_DS(host_index).dyn_flag = 0;	/* dynamical assignment is not necessary */
+		IBM_DS(shpnt).dyn_flag = 0;	/* dynamical assignment is not necessary */
 
 	/* If no SCSI-devices are assigned, return 1 in order to cause message. */
 	if (ldn == 0)
 		printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n");
 
 	/* reset the counters for statistics on the current adapter */
-	IBM_DS(host_index).scbs = 0;
-	IBM_DS(host_index).long_scbs = 0;
-	IBM_DS(host_index).total_accesses = 0;
-	IBM_DS(host_index).total_interrupts = 0;
-	IBM_DS(host_index).dynamical_assignments = 0;
-	memset(IBM_DS(host_index).ldn_access, 0x0, sizeof(IBM_DS(host_index).ldn_access));
-	memset(IBM_DS(host_index).ldn_read_access, 0x0, sizeof(IBM_DS(host_index).ldn_read_access));
-	memset(IBM_DS(host_index).ldn_write_access, 0x0, sizeof(IBM_DS(host_index).ldn_write_access));
-	memset(IBM_DS(host_index).ldn_inquiry_access, 0x0, sizeof(IBM_DS(host_index).ldn_inquiry_access));
-	memset(IBM_DS(host_index).ldn_modeselect_access, 0x0, sizeof(IBM_DS(host_index).ldn_modeselect_access));
-	memset(IBM_DS(host_index).ldn_assignments, 0x0, sizeof(IBM_DS(host_index).ldn_assignments));
+	IBM_DS(shpnt).scbs = 0;
+	IBM_DS(shpnt).long_scbs = 0;
+	IBM_DS(shpnt).total_accesses = 0;
+	IBM_DS(shpnt).total_interrupts = 0;
+	IBM_DS(shpnt).dynamical_assignments = 0;
+	memset(IBM_DS(shpnt).ldn_access, 0x0, sizeof(IBM_DS(shpnt).ldn_access));
+	memset(IBM_DS(shpnt).ldn_read_access, 0x0, sizeof(IBM_DS(shpnt).ldn_read_access));
+	memset(IBM_DS(shpnt).ldn_write_access, 0x0, sizeof(IBM_DS(shpnt).ldn_write_access));
+	memset(IBM_DS(shpnt).ldn_inquiry_access, 0x0, sizeof(IBM_DS(shpnt).ldn_inquiry_access));
+	memset(IBM_DS(shpnt).ldn_modeselect_access, 0x0, sizeof(IBM_DS(shpnt).ldn_modeselect_access));
+	memset(IBM_DS(shpnt).ldn_assignments, 0x0, sizeof(IBM_DS(shpnt).ldn_assignments));
 	probe_display(0);
 	return;
 }
 
-static int device_exists(int host_index, int ldn, int *block_length, int *device_type)
+static int device_exists(struct Scsi_Host *shpnt, int ldn, int *block_length, int *device_type)
 {
 	unsigned char *buf;
 	/* if no valid device found, return immediately with 0 */
-	if (!(device_inquiry(host_index, ldn)))
+	if (!(device_inquiry(shpnt, ldn)))
 		return 0;
-	buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
+	buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
 	if (*buf == TYPE_ROM) {
 		*device_type = TYPE_ROM;
 		*block_length = 2048;	/* (standard blocksize for yellow-/red-book) */
@@ -1349,7 +1359,7 @@
 	}
 	if (*buf == TYPE_DISK) {
 		*device_type = TYPE_DISK;
-		if (read_capacity(host_index, ldn)) {
+		if (read_capacity(shpnt, ldn)) {
 			*block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
 			return 1;
 		} else
@@ -1357,7 +1367,7 @@
 	}
 	if (*buf == TYPE_MOD) {
 		*device_type = TYPE_MOD;
-		if (read_capacity(host_index, ldn)) {
+		if (read_capacity(shpnt, ldn)) {
 			*block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
 			return 1;
 		} else
@@ -1430,6 +1440,9 @@
 	return;
 }
 
+#if 0
+ FIXME NEED TO MOVE TO SYSFS
+
 static int ibmmca_getinfo(char *buf, int slot, void *dev_id)
 {
 	struct Scsi_Host *shpnt;
@@ -1480,58 +1493,34 @@
 
 	return len;
 }
+#endif
 
-int ibmmca_detect(struct scsi_host_template * scsi_template)
+static struct scsi_host_template ibmmca_driver_template = {
+          .proc_name      = "ibmmca",
+	  .proc_info	  = ibmmca_proc_info,
+          .name           = "IBM SCSI-Subsystem",
+          .queuecommand   = ibmmca_queuecommand,
+	  .eh_abort_handler = ibmmca_abort,
+	  .eh_host_reset_handler = ibmmca_host_reset,
+          .bios_param     = ibmmca_biosparam,
+          .can_queue      = 16,
+          .this_id        = 7,
+          .sg_tablesize   = 16,
+          .cmd_per_lun    = 1,
+          .use_clustering = ENABLE_CLUSTERING,
+};
+
+static int ibmmca_probe(struct device *dev)
 {
 	struct Scsi_Host *shpnt;
-	int port, id, i, j, k, slot;
-	int devices_on_irq_11 = 0;
-	int devices_on_irq_14 = 0;
-	int IRQ14_registered = 0;
-	int IRQ11_registered = 0;
-
-	found = 0;		/* make absolutely sure, that found is set to 0 */
+	int port, id, i, j, k, irq, enabled, ret = -EINVAL;
+	struct mca_device *mca_dev = to_mca_device(dev);
+	const char *description = ibmmca_description[mca_dev->index];
 
 	/* First of all, print the version number of the driver. This is
 	 * important to allow better user bugreports in case of already
 	 * having problems with the MCA_bus probing. */
 	printk(KERN_INFO "IBM MCA SCSI: Version %s\n", IBMMCA_SCSI_DRIVER_VERSION);
-	/* if this is not MCA machine, return "nothing found" */
-	if (!MCA_bus) {
-		printk(KERN_INFO "IBM MCA SCSI:  No Microchannel-bus present --> Aborting.\n" "      	     This machine does not have any IBM MCA-bus\n" "    	     or the MCA-Kernel-support is not enabled!\n");
-		return 0;
-	}
-
-#ifdef MODULE
-	/* If the driver is run as module, read from conf.modules or cmd-line */
-	if (boot_options)
-		option_setup(boot_options);
-#endif
-
-	/* get interrupt request level */
-	if (request_irq(IM_IRQ, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) {
-		printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ);
-		return 0;
-	} else
-		IRQ14_registered++;
-
-	/* if ibmmcascsi setup option was passed to kernel, return "found" */
-	for (i = 0; i < IM_MAX_HOSTS; i++)
-		if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) {
-			printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", io_port[i], scsi_id[i]);
-			if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], FORCED_DETECTION, "forced detected SCSI Adapter"))) {
-				for (k = 2; k < 7; k++)
-					((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = 0;
-				((struct ibmmca_hostdata *) shpnt->hostdata)->_special = FORCED_DETECTION;
-				mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter");
-				mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-				mca_mark_as_used(MCA_INTEGSCSI);
-				devices_on_irq_14++;
-			}
-		}
-	if (found)
-		return found;
-
 	/* The POS2-register of all PS/2 model SCSI-subsystems has the following
 	 * interpretation of bits:
 	 *                             Bit 7 - 4 : Chip Revision ID (Release)
@@ -1558,7 +1547,14 @@
 
 	/* first look for the IBM SCSI integrated subsystem on the motherboard */
 	for (j = 0; j < 8; j++)	/* read the pos-information */
-		pos[j] = mca_read_stored_pos(MCA_INTEGSCSI, j);
+		pos[j] = mca_device_read_pos(mca_dev, j);
+	id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */
+	enabled = (pos[2] &0x01);
+	if (!enabled) {
+		printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
+		printk(KERN_WARNING "              SCSI-operations may not work.\n");
+	}
+
 	/* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but
 	 * if we ignore the settings of all surrounding pos registers, it is not
 	 * completely sufficient to only check pos2 and pos3. */
@@ -1566,232 +1562,137 @@
 	 * make sure, we see a real integrated onboard SCSI-interface and no
 	 * internal system information, which gets mapped to some pos registers
 	 * on models 95xx. */
-	if ((!pos[0] && !pos[1] && pos[2] > 0 && pos[3] > 0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || (pos[0] == 0xff && pos[1] == 0xff && pos[2] < 0xff && pos[3] < 0xff && pos[4] == 0xff && pos[5] == 0xff && pos[6] == 0xff && pos[7] == 0xff)) {
-		if ((pos[2] & 1) == 1)	/* is the subsystem chip enabled ? */
-			port = IM_IO_PORT;
-		else {		/* if disabled, no IRQs will be generated, as the chip won't
-				 * listen to the incoming commands and will do really nothing,
-				 * except for listening to the pos-register settings. If this
-				 * happens, I need to hugely think about it, as one has to
-				 * write something to the MCA-Bus pos register in order to
-				 * enable the chip. Normally, IBM-SCSI won't pass the POST,
-				 * when the chip is disabled (see IBM tech. ref.). */
-			port = IM_IO_PORT;	/* anyway, set the portnumber and warn */
-			printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" "              SCSI-operations may not work.\n");
+	if (mca_dev->slot == MCA_INTEGSCSI &&
+	    ((!pos[0] && !pos[1] && pos[2] > 0 &&
+	      pos[3] > 0 && !pos[4] && !pos[5] &&
+	      !pos[6] && !pos[7]) ||
+	     (pos[0] == 0xff && pos[1] == 0xff &&
+	      pos[2] < 0xff && pos[3] < 0xff &&
+	      pos[4] == 0xff && pos[5] == 0xff &&
+	      pos[6] == 0xff && pos[7] == 0xff))) {
+		irq = IM_IRQ;
+		port = IM_IO_PORT;
+	} else {
+		irq = IM_IRQ;
+		port = IM_IO_PORT + ((pos[2] &0x0e) << 2);
+		if ((mca_dev->index == IBM_SCSI2_FW) && (pos[6] != 0)) {
+			printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
+			printk(KERN_ERR "              Impossible to determine adapter PUN!\n");
+			printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
+			id = 7;
+		} else {
+			id = (pos[3] & 0xe0) >> 5;	/* get subsystem PUN */
+			if (mca_dev->index == IBM_SCSI2_FW) {
+				id |= (pos[3] & 0x10) >> 1;	/* get subsystem PUN high-bit
+								 * for F/W adapters */
+			}
 		}
-		id = (pos[3] & 0xe0) >> 5;	/* this is correct and represents the PUN */
-		/* give detailed information on the subsystem. This helps me
-		 * additionally during debugging and analyzing bug-reports. */
-		printk(KERN_INFO "IBM MCA SCSI: IBM Integrated SCSI Controller ffound, io=0x%x, scsi id=%d,\n", port, id);
+		if ((mca_dev->index == IBM_SCSI2_FW) &&
+		    (pos[4] & 0x01) && (pos[6] == 0)) {
+			/* IRQ11 is used by SCSI-2 F/W Adapter/A */
+			printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
+			irq = IM_IRQ_FW;
+		}
+	}
+
+
+
+	/* give detailed information on the subsystem. This helps me
+	 * additionally during debugging and analyzing bug-reports. */
+	printk(KERN_INFO "IBM MCA SCSI: %s found, io=0x%x, scsi id=%d,\n",
+	       description, port, id);
+	if (mca_dev->slot == MCA_INTEGSCSI)
 		printk(KERN_INFO "              chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled.");
+	else {
+		if ((pos[2] & 0xf0) == 0xf0)
+			printk(KERN_DEBUG "              ROM Addr.=off,");
+		else
+			printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
 
-		/* register the found integrated SCSI-subsystem */
-		if ((shpnt = ibmmca_register(scsi_template, port, id, INTEGRATED_SCSI, "IBM Integrated SCSI Controller"))) 
-		{
-			for (k = 2; k < 7; k++)
-				((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
-			((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
-			mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller");
-			mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-			mca_mark_as_used(MCA_INTEGSCSI);
-			devices_on_irq_14++;
-		}
+		printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
 	}
 
-	/* now look for other adapters in MCA slots, */
-	/* determine the number of known IBM-SCSI-subsystem types */
-	/* see the pos[2] dependence to get the adapter port-offset. */
-	for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
-		/* scan each slot for a fitting adapter id */
-		slot = 0;	/* start at slot 0 */
-		while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
-		       != MCA_NOTFOUND) {	/* scan through all slots */
-			for (j = 0; j < 8; j++)	/* read the pos-information */
-				pos[j] = mca_read_stored_pos(slot, j);
-			if ((pos[2] & 1) == 1)
-				/* is the subsystem chip enabled ? */
-				/* (explanations see above) */
-				port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
-			else {
-				/* anyway, set the portnumber and warn */
-				port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
-				printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
-				printk(KERN_WARNING "              SCSI-operations may not work.\n");
-			}
-			if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) {
-				printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
-				printk(KERN_ERR "              Impossible to determine adapter PUN!\n");
-				printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
-				id = 7;
-			} else {
-				id = (pos[3] & 0xe0) >> 5;	/* get subsystem PUN */
-				if (i == IBM_SCSI2_FW) {
-					id |= (pos[3] & 0x10) >> 1;	/* get subsystem PUN high-bit
-									 * for F/W adapters */
-				}
-			}
-			if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) {
-				/* IRQ11 is used by SCSI-2 F/W Adapter/A */
-				printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
-				/* get interrupt request level */
-				if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) {
-					printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW);
-				} else
-					IRQ11_registered++;
-			}
-			printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id);
-			if ((pos[2] & 0xf0) == 0xf0)
-				printk(KERN_DEBUG"              ROM Addr.=off,");
-			else
-				printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
-			printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
-
-			/* register the hostadapter */
-			if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) {
-				for (k = 2; k < 8; k++)
-					((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
-				((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i;
-				mca_set_adapter_name(slot, subsys_list[i].description);
-				mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-				mca_mark_as_used(slot);
-				if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0))
-					devices_on_irq_11++;
-				else
-					devices_on_irq_14++;
-			}
-			slot++;	/* advance to next slot */
-		}		/* advance to next adapter id in the list of IBM-SCSI-subsystems */
-	}
-
-	/* now check for SCSI-adapters, mapped to the integrated SCSI
-	 * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here,
-	 * as this is a known effect on some models 95xx. */
-	for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
-		/* scan each slot for a fitting adapter id */
-		slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI);
-		if (slot != MCA_NOTFOUND) {	/* scan through all slots */
-			for (j = 0; j < 8; j++)	/* read the pos-information */
-				pos[j] = mca_read_stored_pos(slot, j);
-			if ((pos[2] & 1) == 1) {	/* is the subsystem chip enabled ? */
-				/* (explanations see above) */
-				port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
-			} else {	/* anyway, set the portnumber and warn */
-				port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
-				printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
-				printk(KERN_WARNING "              SCSI-operations may not work.\n");
-			}
-			if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) {
-				printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
-				printk(KERN_ERR  "              Impossible to determine adapter PUN!\n");
-				printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
-				id = 7;
-			} else {
-				id = (pos[3] & 0xe0) >> 5;	/* get subsystem PUN */
-				if (i == IBM_SCSI2_FW)
-					id |= (pos[3] & 0x10) >> 1;	/* get subsystem PUN high-bit
-									 * for F/W adapters */
-			}
-			if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) {
-				/* IRQ11 is used by SCSI-2 F/W Adapter/A */
-				printk(KERN_DEBUG  "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
-				/* get interrupt request level */
-				if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts))
-					printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW);
-				else
-					IRQ11_registered++;
-			}
-			printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id);
-			if ((pos[2] & 0xf0) == 0xf0)
-				printk(KERN_DEBUG "              ROM Addr.=off,");
-			else
-				printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
-			printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
-
-			/* register the hostadapter */
-			if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) {
-				for (k = 2; k < 7; k++)
-					((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
-				((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i;
-				mca_set_adapter_name(slot, subsys_list[i].description);
-				mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-				mca_mark_as_used(slot);
-				if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0))
-					devices_on_irq_11++;
-				else
-					devices_on_irq_14++;
-			}
-			slot++;	/* advance to next slot */
-		}		/* advance to next adapter id in the list of IBM-SCSI-subsystems */
-	}
-	if (IRQ11_registered && !devices_on_irq_11)
-		free_irq(IM_IRQ_FW, hosts);	/* no devices on IRQ 11 */
-	if (IRQ14_registered && !devices_on_irq_14)
-		free_irq(IM_IRQ, hosts);	/* no devices on IRQ 14 */
-	if (!devices_on_irq_11 && !devices_on_irq_14)
-		printk(KERN_WARNING "IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n");
-	return found;		/* return the number of found SCSI hosts. Should be 1 or 0. */
-}
-
-static struct Scsi_Host *ibmmca_register(struct scsi_host_template * scsi_template, int port, int id, int adaptertype, char *hostname)
-{
-	struct Scsi_Host *shpnt;
-	int i, j;
-	unsigned int ctrl;
-
 	/* check I/O region */
-	if (!request_region(port, IM_N_IO_PORT, hostname)) {
+	if (!request_region(port, IM_N_IO_PORT, description)) {
 		printk(KERN_ERR "IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n", port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT);
-		return NULL;
+		goto out_fail;
 	}
 
 	/* register host */
-	shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata));
+	shpnt = scsi_host_alloc(&ibmmca_driver_template,
+				sizeof(struct ibmmca_hostdata));
 	if (!shpnt) {
 		printk(KERN_ERR "IBM MCA SCSI: Unable to register host.\n");
-		release_region(port, IM_N_IO_PORT);
-		return NULL;
+		goto out_release;
+	}
+
+	dev_set_drvdata(dev, shpnt);
+	if(request_irq(irq, interrupt_handler, IRQF_SHARED, description, dev)) {
+		printk(KERN_ERR "IBM MCA SCSI: failed to request interrupt %d\n", irq);
+		goto out_free_host;
 	}
 
 	/* request I/O region */
-	hosts[found] = shpnt;	/* add new found hostadapter to the list */
-	special(found) = adaptertype;	/* important assignment or else crash! */
-	subsystem_connector_size(found) = 0;	/* preset slot-size */
-	shpnt->irq = IM_IRQ;	/* assign necessary stuff for the adapter */
+	special(shpnt) = mca_dev->index;	/* important assignment or else crash! */
+	subsystem_connector_size(shpnt) = 0;	/* preset slot-size */
+	shpnt->irq = irq;	/* assign necessary stuff for the adapter */
 	shpnt->io_port = port;
 	shpnt->n_io_port = IM_N_IO_PORT;
 	shpnt->this_id = id;
 	shpnt->max_id = 8;	/* 8 PUNs are default */
 	/* now, the SCSI-subsystem is connected to Linux */
 
-	ctrl = (unsigned int) (inb(IM_CTR_REG(found)));	/* get control-register status */
 #ifdef IM_DEBUG_PROBE
+	ctrl = (unsigned int) (inb(IM_CTR_REG(found)));	/* get control-register status */
 	printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", ctrl, inb(IM_STAT_REG(found)));
 	printk("IBM MCA SCSI: This adapters' POS-registers: ");
 	for (i = 0; i < 8; i++)
 		printk("%x ", pos[i]);
 	printk("\n");
 #endif
-	reset_status(found) = IM_RESET_NOT_IN_PROGRESS;
+	reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
 
 	for (i = 0; i < 16; i++)	/* reset the tables */
 		for (j = 0; j < 8; j++)
-			get_ldn(found)[i][j] = MAX_LOG_DEV;
+			get_ldn(shpnt)[i][j] = MAX_LOG_DEV;
 
 	/* check which logical devices exist */
 	/* after this line, local interrupting is possible: */
-	local_checking_phase_flag(found) = 1;
-	check_devices(found, adaptertype);	/* call by value, using the global variable hosts */
-	local_checking_phase_flag(found) = 0;
-	found++;		/* now increase index to be prepared for next found subsystem */
+	local_checking_phase_flag(shpnt) = 1;
+	check_devices(shpnt, mca_dev->index);	/* call by value, using the global variable hosts */
+	local_checking_phase_flag(shpnt) = 0;
+
 	/* an ibm mca subsystem has been detected */
-	return shpnt;
+
+	for (k = 2; k < 7; k++)
+		((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
+	((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
+	mca_device_set_name(mca_dev, description);
+	/* FIXME: NEED TO REPLUMB TO SYSFS
+	   mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
+	*/
+	mca_device_set_claim(mca_dev, 1);
+	if (scsi_add_host(shpnt, dev)) {
+		dev_printk(KERN_ERR, dev, "IBM MCA SCSI: scsi_add_host failed\n");
+		goto out_free_host;
+	}
+	scsi_scan_host(shpnt);
+
+	return 0;
+ out_free_host:
+	scsi_host_put(shpnt);
+ out_release:
+	release_region(port, IM_N_IO_PORT);
+ out_fail:
+	return ret;
 }
 
-static int ibmmca_release(struct Scsi_Host *shpnt)
+static int __devexit ibmmca_remove(struct device *dev)
 {
+	struct Scsi_Host *shpnt = dev_get_drvdata(dev);
+	scsi_remove_host(shpnt);
 	release_region(shpnt->io_port, shpnt->n_io_port);
-	if (!(--found))
-		free_irq(shpnt->irq, hosts);
+	free_irq(shpnt->irq, dev);
 	return 0;
 }
 
@@ -1805,33 +1706,24 @@
 	int current_ldn;
 	int id, lun;
 	int target;
-	int host_index;
 	int max_pun;
 	int i;
-	struct scatterlist *sl;
+	struct scatterlist *sg;
 
 	shpnt = cmd->device->host;
-	/* search for the right hostadapter */
-	for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
 
-	if (!hosts[host_index]) {	/* invalid hostadapter descriptor address */
-		cmd->result = DID_NO_CONNECT << 16;
-		if (done)
-			done(cmd);
-		return 0;
-	}
-	max_pun = subsystem_maxid(host_index);
+	max_pun = subsystem_maxid(shpnt);
 	if (ibm_ansi_order) {
 		target = max_pun - 1 - cmd->device->id;
-		if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))
+		if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
 			target--;
-		else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))
+		else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
 			target++;
 	} else
 		target = cmd->device->id;
 
 	/* if (target,lun) is NO LUN or not existing at all, return error */
-	if ((get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
+	if ((get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
 		cmd->result = DID_NO_CONNECT << 16;
 		if (done)
 			done(cmd);
@@ -1839,16 +1731,16 @@
 	}
 
 	/*if (target,lun) unassigned, do further checks... */
-	ldn = get_ldn(host_index)[target][cmd->device->lun];
+	ldn = get_ldn(shpnt)[target][cmd->device->lun];
 	if (ldn >= MAX_LOG_DEV) {	/* on invalid ldn do special stuff */
 		if (ldn > MAX_LOG_DEV) {	/* dynamical remapping if ldn unassigned */
-			current_ldn = next_ldn(host_index);	/* stop-value for one circle */
-			while (ld(host_index)[next_ldn(host_index)].cmd) {	/* search for a occupied, but not in */
+			current_ldn = next_ldn(shpnt);	/* stop-value for one circle */
+			while (ld(shpnt)[next_ldn(shpnt)].cmd) {	/* search for a occupied, but not in */
 				/* command-processing ldn. */
-				next_ldn(host_index)++;
-				if (next_ldn(host_index) >= MAX_LOG_DEV)
-					next_ldn(host_index) = 7;
-				if (current_ldn == next_ldn(host_index)) {	/* One circle done ? */
+				next_ldn(shpnt)++;
+				if (next_ldn(shpnt) >= MAX_LOG_DEV)
+					next_ldn(shpnt) = 7;
+				if (current_ldn == next_ldn(shpnt)) {	/* One circle done ? */
 					/* no non-processing ldn found */
 					scmd_printk(KERN_WARNING, cmd,
 	"IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n"
@@ -1864,56 +1756,56 @@
 			/* unmap non-processing ldn */
 			for (id = 0; id < max_pun; id++)
 				for (lun = 0; lun < 8; lun++) {
-					if (get_ldn(host_index)[id][lun] == next_ldn(host_index)) {
-						get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
-						get_scsi(host_index)[id][lun] = TYPE_NO_DEVICE;
+					if (get_ldn(shpnt)[id][lun] == next_ldn(shpnt)) {
+						get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
+						get_scsi(shpnt)[id][lun] = TYPE_NO_DEVICE;
 						/* unmap entry */
 					}
 				}
 			/* set reduced interrupt_handler-mode for checking */
-			local_checking_phase_flag(host_index) = 1;
+			local_checking_phase_flag(shpnt) = 1;
 			/* map found ldn to pun,lun */
-			get_ldn(host_index)[target][cmd->device->lun] = next_ldn(host_index);
+			get_ldn(shpnt)[target][cmd->device->lun] = next_ldn(shpnt);
 			/* change ldn to the right value, that is now next_ldn */
-			ldn = next_ldn(host_index);
+			ldn = next_ldn(shpnt);
 			/* unassign all ldns (pun,lun,ldn does not matter for remove) */
-			immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);
+			immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
 			/* set only LDN for remapped device */
-			immediate_assign(host_index, target, cmd->device->lun, ldn, SET_LDN);
+			immediate_assign(shpnt, target, cmd->device->lun, ldn, SET_LDN);
 			/* get device information for ld[ldn] */
-			if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {
-				ld(host_index)[ldn].cmd = NULL;	/* To prevent panic set 0, because
+			if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
+				ld(shpnt)[ldn].cmd = NULL;	/* To prevent panic set 0, because
 								   devices that were not assigned,
 								   should have nothing in progress. */
-				get_scsi(host_index)[target][cmd->device->lun] = ld(host_index)[ldn].device_type;
+				get_scsi(shpnt)[target][cmd->device->lun] = ld(shpnt)[ldn].device_type;
 				/* increase assignment counters for statistics in /proc */
-				IBM_DS(host_index).dynamical_assignments++;
-				IBM_DS(host_index).ldn_assignments[ldn]++;
+				IBM_DS(shpnt).dynamical_assignments++;
+				IBM_DS(shpnt).ldn_assignments[ldn]++;
 			} else
 				/* panic here, because a device, found at boottime has
 				   vanished */
 				panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->device->lun);
 			/* unassign again all ldns (pun,lun,ldn does not matter for remove) */
-			immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);
+			immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
 			/* remap all ldns, as written in the pun/lun table */
 			lun = 0;
 #ifdef CONFIG_SCSI_MULTI_LUN
 			for (lun = 0; lun < 8; lun++)
 #endif
 				for (id = 0; id < max_pun; id++) {
-					if (get_ldn(host_index)[id][lun] <= MAX_LOG_DEV)
-						immediate_assign(host_index, id, lun, get_ldn(host_index)[id][lun], SET_LDN);
+					if (get_ldn(shpnt)[id][lun] <= MAX_LOG_DEV)
+						immediate_assign(shpnt, id, lun, get_ldn(shpnt)[id][lun], SET_LDN);
 				}
 			/* set back to normal interrupt_handling */
-			local_checking_phase_flag(host_index) = 0;
+			local_checking_phase_flag(shpnt) = 0;
 #ifdef IM_DEBUG_PROBE
 			/* Information on syslog terminal */
 			printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->device->lun);
 #endif
 			/* increase next_ldn for next dynamical assignment */
-			next_ldn(host_index)++;
-			if (next_ldn(host_index) >= MAX_LOG_DEV)
-				next_ldn(host_index) = 7;
+			next_ldn(shpnt)++;
+			if (next_ldn(shpnt) >= MAX_LOG_DEV)
+				next_ldn(shpnt) = 7;
 		} else {	/* wall against Linux accesses to the subsystem adapter */
 			cmd->result = DID_BAD_TARGET << 16;
 			if (done)
@@ -1923,34 +1815,32 @@
 	}
 
 	/*verify there is no command already in progress for this log dev */
-	if (ld(host_index)[ldn].cmd)
+	if (ld(shpnt)[ldn].cmd)
 		panic("IBM MCA SCSI: cmd already in progress for this ldn.\n");
 
 	/*save done in cmd, and save cmd for the interrupt handler */
 	cmd->scsi_done = done;
-	ld(host_index)[ldn].cmd = cmd;
+	ld(shpnt)[ldn].cmd = cmd;
 
 	/*fill scb information independent of the scsi command */
-	scb = &(ld(host_index)[ldn].scb);
-	ld(host_index)[ldn].tsb.dev_status = 0;
+	scb = &(ld(shpnt)[ldn].scb);
+	ld(shpnt)[ldn].tsb.dev_status = 0;
 	scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;
-	scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb));
+	scb->tsb_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].tsb));
 	scsi_cmd = cmd->cmnd[0];
 
-	if (cmd->use_sg) {
-		i = cmd->use_sg;
-		sl = (struct scatterlist *) (cmd->request_buffer);
-		if (i > 16)
-			panic("IBM MCA SCSI: scatter-gather list too long.\n");
-		while (--i >= 0) {
-			ld(host_index)[ldn].sge[i].address = (void *) (isa_page_to_bus(sl[i].page) + sl[i].offset);
-			ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
+	if (scsi_sg_count(cmd)) {
+		BUG_ON(scsi_sg_count(cmd) > 16);
+
+		scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
+			ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg->page) + sg->offset);
+			ld(shpnt)[ldn].sge[i].byte_length = sg->length;
 		}
 		scb->enable |= IM_POINTER_TO_LIST;
-		scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0]));
-		scb->sys_buf_length = cmd->use_sg * sizeof(struct im_sge);
+		scb->sys_buf_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].sge[0]));
+		scb->sys_buf_length = scsi_sg_count(cmd) * sizeof(struct im_sge);
 	} else {
-		scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer);
+ 		scb->sys_buf_adr = isa_virt_to_bus(scsi_sglist(cmd));
 		/* recent Linux midlevel SCSI places 1024 byte for inquiry
 		 * command. Far too much for old PS/2 hardware. */
 		switch (scsi_cmd) {
@@ -1961,16 +1851,16 @@
 		case REQUEST_SENSE:
 		case MODE_SENSE:
 		case MODE_SELECT:
-			if (cmd->request_bufflen > 255)
+			if (scsi_bufflen(cmd) > 255)
 				scb->sys_buf_length = 255;
 			else
-				scb->sys_buf_length = cmd->request_bufflen;
+				scb->sys_buf_length = scsi_bufflen(cmd);
 			break;
 		case TEST_UNIT_READY:
 			scb->sys_buf_length = 0;
 			break;
 		default:
-			scb->sys_buf_length = cmd->request_bufflen;
+			scb->sys_buf_length = scsi_bufflen(cmd);
 			break;
 		}
 	}
@@ -1982,16 +1872,16 @@
 
 	/* for specific device-type debugging: */
 #ifdef IM_DEBUG_CMD_SPEC_DEV
-	if (ld(host_index)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
-		printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(host_index)[ldn].device_type, scsi_cmd, ldn);
+	if (ld(shpnt)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
+		printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(shpnt)[ldn].device_type, scsi_cmd, ldn);
 #endif
 
 	/* for possible panics store current command */
-	last_scsi_command(host_index)[ldn] = scsi_cmd;
-	last_scsi_type(host_index)[ldn] = IM_SCB;
+	last_scsi_command(shpnt)[ldn] = scsi_cmd;
+	last_scsi_type(shpnt)[ldn] = IM_SCB;
 	/* update statistical info */
-	IBM_DS(host_index).total_accesses++;
-	IBM_DS(host_index).ldn_access[ldn]++;
+	IBM_DS(shpnt).total_accesses++;
+	IBM_DS(shpnt).ldn_access[ldn]++;
 
 	switch (scsi_cmd) {
 	case READ_6:
@@ -2003,17 +1893,17 @@
 		/* Distinguish between disk and other devices. Only disks (that are the
 		   most frequently accessed devices) should be supported by the
 		   IBM-SCSI-Subsystem commands. */
-		switch (ld(host_index)[ldn].device_type) {
+		switch (ld(shpnt)[ldn].device_type) {
 		case TYPE_DISK:	/* for harddisks enter here ... */
 		case TYPE_MOD:	/* ... try it also for MO-drives (send flames as */
 			/*     you like, if this won't work.) */
 			if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) {
 				/* read command preparations */
 				scb->enable |= IM_READ_CONTROL;
-				IBM_DS(host_index).ldn_read_access[ldn]++;	/* increase READ-access on ldn stat. */
+				IBM_DS(shpnt).ldn_read_access[ldn]++;	/* increase READ-access on ldn stat. */
 				scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT;
 			} else {	/* write command preparations */
-				IBM_DS(host_index).ldn_write_access[ldn]++;	/* increase write-count on ldn stat. */
+				IBM_DS(shpnt).ldn_write_access[ldn]++;	/* increase write-count on ldn stat. */
 				scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT;
 			}
 			if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) {
@@ -2023,9 +1913,9 @@
 				scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | (((unsigned) cmd->cmnd[4]) << 8) | (((unsigned) cmd->cmnd[3]) << 16) | (((unsigned) cmd->cmnd[2]) << 24);
 				scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8);
 			}
-			last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr;
-			last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count;
-			scb->u2.blk.length = ld(host_index)[ldn].block_length;
+			last_scsi_logical_block(shpnt)[ldn] = scb->u1.log_blk_adr;
+			last_scsi_blockcount(shpnt)[ldn] = scb->u2.blk.count;
+			scb->u2.blk.length = ld(shpnt)[ldn].block_length;
 			break;
 			/* for other devices, enter here. Other types are not known by
 			   Linux! TYPE_NO_LUN is forbidden as valid device. */
@@ -2046,14 +1936,14 @@
 			scb->enable |= IM_BYPASS_BUFFER;
 			scb->u1.scsi_cmd_length = cmd->cmd_len;
 			memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-			last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+			last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
 			/* Read/write on this non-disk devices is also displayworthy,
 			   so flash-up the LED/display. */
 			break;
 		}
 		break;
 	case INQUIRY:
-		IBM_DS(host_index).ldn_inquiry_access[ldn]++;
+		IBM_DS(shpnt).ldn_inquiry_access[ldn]++;
 		scb->command = IM_DEVICE_INQUIRY_CMD;
 		scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
 		scb->u1.log_blk_adr = 0;
@@ -2064,7 +1954,7 @@
 		scb->u1.log_blk_adr = 0;
 		scb->u1.scsi_cmd_length = 6;
 		memcpy(scb->u2.scsi_command, cmd->cmnd, 6);
-		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+		last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
 		break;
 	case READ_CAPACITY:
 		/* the length of system memory buffer must be exactly 8 bytes */
@@ -2081,12 +1971,12 @@
 		/* Commands that need write-only-mode (system -> device): */
 	case MODE_SELECT:
 	case MODE_SELECT_10:
-		IBM_DS(host_index).ldn_modeselect_access[ldn]++;
+		IBM_DS(shpnt).ldn_modeselect_access[ldn]++;
 		scb->command = IM_OTHER_SCSI_CMD_CMD;
 		scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;	/*Select needs WRITE-enabled */
 		scb->u1.scsi_cmd_length = cmd->cmd_len;
 		memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+		last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
 		break;
 		/* For other commands, read-only is useful. Most other commands are
 		   running without an input-data-block. */
@@ -2095,19 +1985,19 @@
 		scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
 		scb->u1.scsi_cmd_length = cmd->cmd_len;
 		memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+		last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
 		break;
 	}
 	/*issue scb command, and return */
 	if (++disk_rw_in_progress == 1)
 		PS2_DISK_LED_ON(shpnt->host_no, target);
 
-	if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) {
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
-		IBM_DS(host_index).long_scbs++;
+	if (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB) {
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
+		IBM_DS(shpnt).long_scbs++;
 	} else {
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
-		IBM_DS(host_index).scbs++;
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+		IBM_DS(shpnt).scbs++;
 	}
 	return 0;
 }
@@ -2122,7 +2012,6 @@
 	unsigned int ldn;
 	void (*saved_done) (Scsi_Cmnd *);
 	int target;
-	int host_index;
 	int max_pun;
 	unsigned long imm_command;
 
@@ -2131,35 +2020,23 @@
 #endif
 
 	shpnt = cmd->device->host;
-	/* search for the right hostadapter */
-	for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
 
-	if (!hosts[host_index]) {	/* invalid hostadapter descriptor address */
-		cmd->result = DID_NO_CONNECT << 16;
-		if (cmd->scsi_done)
-			(cmd->scsi_done) (cmd);
-		shpnt = cmd->device->host;
-#ifdef IM_DEBUG_PROBE
-		printk(KERN_DEBUG "IBM MCA SCSI: Abort adapter selection failed!\n");
-#endif
-		return SUCCESS;
-	}
-	max_pun = subsystem_maxid(host_index);
+	max_pun = subsystem_maxid(shpnt);
 	if (ibm_ansi_order) {
 		target = max_pun - 1 - cmd->device->id;
-		if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))
+		if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
 			target--;
-		else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))
+		else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
 			target++;
 	} else
 		target = cmd->device->id;
 
 	/* get logical device number, and disable system interrupts */
 	printk(KERN_WARNING "IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", target, cmd->device->lun);
-	ldn = get_ldn(host_index)[target][cmd->device->lun];
+	ldn = get_ldn(shpnt)[target][cmd->device->lun];
 
 	/*if cmd for this ldn has already finished, no need to abort */
-	if (!ld(host_index)[ldn].cmd) {
+	if (!ld(shpnt)[ldn].cmd) {
 		    return SUCCESS;
 	}
 
@@ -2170,20 +2047,20 @@
 	saved_done = cmd->scsi_done;
 	cmd->scsi_done = internal_done;
 	cmd->SCp.Status = 0;
-	last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD;
-	last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
-	imm_command = inl(IM_CMD_REG(host_index));
+	last_scsi_command(shpnt)[ldn] = IM_ABORT_IMM_CMD;
+	last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
+	imm_command = inl(IM_CMD_REG(shpnt));
 	imm_command &= (unsigned long) (0xffff0000);	/* mask reserved stuff */
 	imm_command |= (unsigned long) (IM_ABORT_IMM_CMD);
 	/* must wait for attention reg not busy */
 	/* FIXME - timeout, politeness */
 	while (1) {
-		if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+		if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
 			break;
 	}
 	/* write registers and enable system interrupts */
-	outl(imm_command, IM_CMD_REG(host_index));
-	outb(IM_IMM_CMD | ldn, IM_ATTN_REG(host_index));
+	outl(imm_command, IM_CMD_REG(shpnt));
+	outb(IM_IMM_CMD | ldn, IM_ATTN_REG(shpnt));
 #ifdef IM_DEBUG_PROBE
 	printk("IBM MCA SCSI: Abort queued to adapter...\n");
 #endif
@@ -2202,7 +2079,7 @@
 		cmd->result |= DID_ABORT << 16;
 		if (cmd->scsi_done)
 			(cmd->scsi_done) (cmd);
-		ld(host_index)[ldn].cmd = NULL;
+		ld(shpnt)[ldn].cmd = NULL;
 #ifdef IM_DEBUG_PROBE
 		printk("IBM MCA SCSI: Abort finished with success.\n");
 #endif
@@ -2211,7 +2088,7 @@
 		cmd->result |= DID_NO_CONNECT << 16;
 		if (cmd->scsi_done)
 			(cmd->scsi_done) (cmd);
-		ld(host_index)[ldn].cmd = NULL;
+		ld(shpnt)[ldn].cmd = NULL;
 #ifdef IM_DEBUG_PROBE
 		printk("IBM MCA SCSI: Abort failed.\n");
 #endif
@@ -2236,71 +2113,65 @@
 	struct Scsi_Host *shpnt;
 	Scsi_Cmnd *cmd_aid;
 	int ticks, i;
-	int host_index;
 	unsigned long imm_command;
 
 	BUG_ON(cmd == NULL);
 
 	ticks = IM_RESET_DELAY * HZ;
 	shpnt = cmd->device->host;
-	/* search for the right hostadapter */
-	for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
 
-	if (!hosts[host_index])	/* invalid hostadapter descriptor address */
-		return FAILED;
-
-	if (local_checking_phase_flag(host_index)) {
+	if (local_checking_phase_flag(shpnt)) {
 		printk(KERN_WARNING "IBM MCA SCSI: unable to reset while checking devices.\n");
 		return FAILED;
 	}
 
 	/* issue reset immediate command to subsystem, and wait for interrupt */
 	printk("IBM MCA SCSI: resetting all devices.\n");
-	reset_status(host_index) = IM_RESET_IN_PROGRESS;
-	last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD;
-	last_scsi_type(host_index)[0xf] = IM_IMM_CMD;
-	imm_command = inl(IM_CMD_REG(host_index));
+	reset_status(shpnt) = IM_RESET_IN_PROGRESS;
+	last_scsi_command(shpnt)[0xf] = IM_RESET_IMM_CMD;
+	last_scsi_type(shpnt)[0xf] = IM_IMM_CMD;
+	imm_command = inl(IM_CMD_REG(shpnt));
 	imm_command &= (unsigned long) (0xffff0000);	/* mask reserved stuff */
 	imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
 	/* must wait for attention reg not busy */
 	while (1) {
-		if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+		if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
 			break;
 		spin_unlock_irq(shpnt->host_lock);
 		yield();
 		spin_lock_irq(shpnt->host_lock);
 	}
 	/*write registers and enable system interrupts */
-	outl(imm_command, IM_CMD_REG(host_index));
-	outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index));
+	outl(imm_command, IM_CMD_REG(shpnt));
+	outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(shpnt));
 	/* wait for interrupt finished or intr_stat register to be set, as the
 	 * interrupt will not be executed, while we are in here! */
 	 
 	/* FIXME: This is really really icky we so want a sleeping version of this ! */
-	while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(host_index)) & 0x8f) != 0x8f)) {
+	while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(shpnt)) & 0x8f) != 0x8f)) {
 		udelay((1 + 999 / HZ) * 1000);
 		barrier();
 	}
 	/* if reset did not complete, just return an error */
 	if (!ticks) {
 		printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
-		reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+		reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
 		return FAILED;
 	}
 
-	if ((inb(IM_INTR_REG(host_index)) & 0x8f) == 0x8f) {
+	if ((inb(IM_INTR_REG(shpnt)) & 0x8f) == 0x8f) {
 		/* analysis done by this routine and not by the intr-routine */
-		if (inb(IM_INTR_REG(host_index)) == 0xaf)
-			reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT;
-		else if (inb(IM_INTR_REG(host_index)) == 0xcf)
-			reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+		if (inb(IM_INTR_REG(shpnt)) == 0xaf)
+			reset_status(shpnt) = IM_RESET_FINISHED_OK_NO_INT;
+		else if (inb(IM_INTR_REG(shpnt)) == 0xcf)
+			reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
 		else		/* failed, 4get it */
-			reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
-		outb(IM_EOI | 0xf, IM_ATTN_REG(host_index));
+			reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
+		outb(IM_EOI | 0xf, IM_ATTN_REG(shpnt));
 	}
 
 	/* if reset failed, just return an error */
-	if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) {
+	if (reset_status(shpnt) == IM_RESET_FINISHED_FAIL) {
 		printk(KERN_ERR "IBM MCA SCSI: reset failed.\n");
 		return FAILED;
 	}
@@ -2308,9 +2179,9 @@
 	/* so reset finished ok - call outstanding done's, and return success */
 	printk(KERN_INFO "IBM MCA SCSI: Reset successfully completed.\n");
 	for (i = 0; i < MAX_LOG_DEV; i++) {
-		cmd_aid = ld(host_index)[i].cmd;
+		cmd_aid = ld(shpnt)[i].cmd;
 		if (cmd_aid && cmd_aid->scsi_done) {
-			ld(host_index)[i].cmd = NULL;
+			ld(shpnt)[i].cmd = NULL;
 			cmd_aid->result = DID_RESET << 16;
 		}
 	}
@@ -2351,46 +2222,46 @@
 }
 
 /* calculate percentage of total accesses on a ldn */
-static int ldn_access_load(int host_index, int ldn)
+static int ldn_access_load(struct Scsi_Host *shpnt, int ldn)
 {
-	if (IBM_DS(host_index).total_accesses == 0)
+	if (IBM_DS(shpnt).total_accesses == 0)
 		return (0);
-	if (IBM_DS(host_index).ldn_access[ldn] == 0)
+	if (IBM_DS(shpnt).ldn_access[ldn] == 0)
 		return (0);
-	return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses;
+	return (IBM_DS(shpnt).ldn_access[ldn] * 100) / IBM_DS(shpnt).total_accesses;
 }
 
 /* calculate total amount of r/w-accesses */
-static int ldn_access_total_read_write(int host_index)
+static int ldn_access_total_read_write(struct Scsi_Host *shpnt)
 {
 	int a;
 	int i;
 
 	a = 0;
 	for (i = 0; i <= MAX_LOG_DEV; i++)
-		a += IBM_DS(host_index).ldn_read_access[i] + IBM_DS(host_index).ldn_write_access[i];
+		a += IBM_DS(shpnt).ldn_read_access[i] + IBM_DS(shpnt).ldn_write_access[i];
 	return (a);
 }
 
-static int ldn_access_total_inquiry(int host_index)
+static int ldn_access_total_inquiry(struct Scsi_Host *shpnt)
 {
 	int a;
 	int i;
 
 	a = 0;
 	for (i = 0; i <= MAX_LOG_DEV; i++)
-		a += IBM_DS(host_index).ldn_inquiry_access[i];
+		a += IBM_DS(shpnt).ldn_inquiry_access[i];
 	return (a);
 }
 
-static int ldn_access_total_modeselect(int host_index)
+static int ldn_access_total_modeselect(struct Scsi_Host *shpnt)
 {
 	int a;
 	int i;
 
 	a = 0;
 	for (i = 0; i <= MAX_LOG_DEV; i++)
-		a += IBM_DS(host_index).ldn_modeselect_access[i];
+		a += IBM_DS(shpnt).ldn_modeselect_access[i];
 	return (a);
 }
 
@@ -2398,19 +2269,14 @@
 static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
 {
 	int len = 0;
-	int i, id, lun, host_index;
+	int i, id, lun;
 	unsigned long flags;
 	int max_pun;
 
-	for (i = 0; hosts[i] && hosts[i] != shpnt; i++);
 	
-	spin_lock_irqsave(hosts[i]->host_lock, flags);	/* Check it */
-	host_index = i;
-	if (!shpnt) {
-		len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter");
-		return len;
-	}
-	max_pun = subsystem_maxid(host_index);
+	spin_lock_irqsave(shpnt->host_lock, flags);	/* Check it */
+
+	max_pun = subsystem_maxid(shpnt);
 
 	len += sprintf(buffer + len, "\n             IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", IBMMCA_SCSI_DRIVER_VERSION);
 	len += sprintf(buffer + len, " SCSI Access-Statistics:\n");
@@ -2421,40 +2287,40 @@
 	len += sprintf(buffer + len, "               Multiple LUN probing.....: No\n");
 #endif
 	len += sprintf(buffer + len, "               This Hostnumber..........: %d\n", shpnt->host_no);
-	len += sprintf(buffer + len, "               Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(host_index)));
+	len += sprintf(buffer + len, "               Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(shpnt)));
 	len += sprintf(buffer + len, "               (Shared) IRQ.............: %d\n", IM_IRQ);
-	len += sprintf(buffer + len, "               Total Interrupts.........: %d\n", IBM_DS(host_index).total_interrupts);
-	len += sprintf(buffer + len, "               Total SCSI Accesses......: %d\n", IBM_DS(host_index).total_accesses);
-	len += sprintf(buffer + len, "               Total short SCBs.........: %d\n", IBM_DS(host_index).scbs);
-	len += sprintf(buffer + len, "               Total long SCBs..........: %d\n", IBM_DS(host_index).long_scbs);
-	len += sprintf(buffer + len, "                 Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(host_index));
-	len += sprintf(buffer + len, "                 Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(host_index));
-	len += sprintf(buffer + len, "                 Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(host_index));
-	len += sprintf(buffer + len, "                 Total SCSI other cmds..: %d\n", IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index)
-		       - ldn_access_total_modeselect(host_index)
-		       - ldn_access_total_inquiry(host_index));
-	len += sprintf(buffer + len, "               Total SCSI command fails.: %d\n\n", IBM_DS(host_index).total_errors);
+	len += sprintf(buffer + len, "               Total Interrupts.........: %d\n", IBM_DS(shpnt).total_interrupts);
+	len += sprintf(buffer + len, "               Total SCSI Accesses......: %d\n", IBM_DS(shpnt).total_accesses);
+	len += sprintf(buffer + len, "               Total short SCBs.........: %d\n", IBM_DS(shpnt).scbs);
+	len += sprintf(buffer + len, "               Total long SCBs..........: %d\n", IBM_DS(shpnt).long_scbs);
+	len += sprintf(buffer + len, "                 Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(shpnt));
+	len += sprintf(buffer + len, "                 Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(shpnt));
+	len += sprintf(buffer + len, "                 Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(shpnt));
+	len += sprintf(buffer + len, "                 Total SCSI other cmds..: %d\n", IBM_DS(shpnt).total_accesses - ldn_access_total_read_write(shpnt)
+		       - ldn_access_total_modeselect(shpnt)
+		       - ldn_access_total_inquiry(shpnt));
+	len += sprintf(buffer + len, "               Total SCSI command fails.: %d\n\n", IBM_DS(shpnt).total_errors);
 	len += sprintf(buffer + len, " Logical-Device-Number (LDN) Access-Statistics:\n");
 	len += sprintf(buffer + len, "         LDN | Accesses [%%] |   READ    |   WRITE   | ASSIGNMENTS\n");
 	len += sprintf(buffer + len, "        -----|--------------|-----------|-----------|--------------\n");
 	for (i = 0; i <= MAX_LOG_DEV; i++)
-		len += sprintf(buffer + len, "         %2X  |    %3d       |  %8d |  %8d | %8d\n", i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i], IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]);
+		len += sprintf(buffer + len, "         %2X  |    %3d       |  %8d |  %8d | %8d\n", i, ldn_access_load(shpnt, i), IBM_DS(shpnt).ldn_read_access[i], IBM_DS(shpnt).ldn_write_access[i], IBM_DS(shpnt).ldn_assignments[i]);
 	len += sprintf(buffer + len, "        -----------------------------------------------------------\n\n");
 	len += sprintf(buffer + len, " Dynamical-LDN-Assignment-Statistics:\n");
-	len += sprintf(buffer + len, "               Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(host_index).total_scsi_devices);
-	len += sprintf(buffer + len, "               Dynamical Assignment necessary...: %s\n", IBM_DS(host_index).dyn_flag ? "Yes" : "No ");
-	len += sprintf(buffer + len, "               Next LDN to be assigned..........: 0x%x\n", next_ldn(host_index));
-	len += sprintf(buffer + len, "               Dynamical assignments done yet...: %d\n", IBM_DS(host_index).dynamical_assignments);
+	len += sprintf(buffer + len, "               Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(shpnt).total_scsi_devices);
+	len += sprintf(buffer + len, "               Dynamical Assignment necessary...: %s\n", IBM_DS(shpnt).dyn_flag ? "Yes" : "No ");
+	len += sprintf(buffer + len, "               Next LDN to be assigned..........: 0x%x\n", next_ldn(shpnt));
+	len += sprintf(buffer + len, "               Dynamical assignments done yet...: %d\n", IBM_DS(shpnt).dynamical_assignments);
 	len += sprintf(buffer + len, "\n Current SCSI-Device-Mapping:\n");
 	len += sprintf(buffer + len, "        Physical SCSI-Device Map               Logical SCSI-Device Map\n");
 	len += sprintf(buffer + len, "    ID\\LUN  0  1  2  3  4  5  6  7       ID\\LUN  0  1  2  3  4  5  6  7\n");
 	for (id = 0; id < max_pun; id++) {
 		len += sprintf(buffer + len, "    %2d     ", id);
 		for (lun = 0; lun < 8; lun++)
-			len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(host_index)[id][lun]));
+			len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(shpnt)[id][lun]));
 		len += sprintf(buffer + len, "      %2d     ", id);
 		for (lun = 0; lun < 8; lun++)
-			len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(host_index)[id][lun]));
+			len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(shpnt)[id][lun]));
 		len += sprintf(buffer + len, "\n");
 	}
 
@@ -2488,20 +2354,31 @@
 
 __setup("ibmmcascsi=", option_setup);
 
-static struct scsi_host_template driver_template = {
-          .proc_name      = "ibmmca",
-	  .proc_info	  = ibmmca_proc_info,
-          .name           = "IBM SCSI-Subsystem",
-          .detect         = ibmmca_detect,
-          .release        = ibmmca_release,
-          .queuecommand   = ibmmca_queuecommand,
-	  .eh_abort_handler = ibmmca_abort,
-	  .eh_host_reset_handler = ibmmca_host_reset,
-          .bios_param     = ibmmca_biosparam,
-          .can_queue      = 16,
-          .this_id        = 7,
-          .sg_tablesize   = 16,
-          .cmd_per_lun    = 1,
-          .use_clustering = ENABLE_CLUSTERING,
+static struct mca_driver ibmmca_driver = {
+	.id_table = ibmmca_id_table,
+	.driver = {
+		.name	= "ibmmca",
+		.bus	= &mca_bus_type,
+		.probe	= ibmmca_probe,
+		.remove	= __devexit_p(ibmmca_remove),
+	},
 };
-#include "scsi_module.c"
+
+static int __init ibmmca_init(void)
+{
+#ifdef MODULE
+	/* If the driver is run as module, read from conf.modules or cmd-line */
+	if (boot_options)
+		option_setup(boot_options);
+#endif
+
+	return mca_register_driver_integrated(&ibmmca_driver, MCA_INTEGSCSI);
+}
+
+static void __exit ibmmca_exit(void)
+{
+	mca_unregister_driver(&ibmmca_driver);
+}
+
+module_init(ibmmca_init);
+module_exit(ibmmca_exit);
diff --git a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h
deleted file mode 100644
index 017ee2f..0000000
--- a/drivers/scsi/ibmmca.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Low Level Driver for the IBM Microchannel SCSI Subsystem
- * (Headerfile, see Documentation/scsi/ibmmca.txt for description of the
- * IBM MCA SCSI-driver.
- * For use under the GNU General Public License within the Linux-kernel project.
- * This include file works only correctly with kernel 2.4.0 or higher!!! */
-
-#ifndef _IBMMCA_H
-#define _IBMMCA_H
-
-/* Common forward declarations for all Linux-versions: */
-
-/* Interfaces to the midlevel Linux SCSI driver */
-static int ibmmca_detect (struct scsi_host_template *);
-static int ibmmca_release (struct Scsi_Host *);
-static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-static int ibmmca_abort (Scsi_Cmnd *);
-static int ibmmca_host_reset (Scsi_Cmnd *);
-static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
-
-#endif /* _IBMMCA_H */
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index b10eefe..5870866 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -173,9 +173,8 @@
 		}
 	}
 	if (in_use)
-		printk(KERN_WARNING
-		       "ibmvscsi: releasing event pool with %d "
-		       "events still in use?\n", in_use);
+		dev_warn(hostdata->dev, "releasing event pool with %d "
+			 "events still in use?\n", in_use);
 	kfree(pool->events);
 	dma_free_coherent(hostdata->dev,
 			  pool->size * sizeof(*pool->iu_storage),
@@ -210,15 +209,13 @@
 				       struct srp_event_struct *evt)
 {
 	if (!valid_event_struct(pool, evt)) {
-		printk(KERN_ERR
-		       "ibmvscsi: Freeing invalid event_struct %p "
-		       "(not in pool %p)\n", evt, pool->events);
+		dev_err(evt->hostdata->dev, "Freeing invalid event_struct %p "
+			"(not in pool %p)\n", evt, pool->events);
 		return;
 	}
 	if (atomic_inc_return(&evt->free) != 1) {
-		printk(KERN_ERR
-		       "ibmvscsi: Freeing event_struct %p "
-		       "which is not in use!\n", evt);
+		dev_err(evt->hostdata->dev, "Freeing event_struct %p "
+			"which is not in use!\n", evt);
 		return;
 	}
 }
@@ -353,20 +350,19 @@
 	}
 }
 
-static int map_sg_list(int num_entries, 
-		       struct scatterlist *sg,
+static int map_sg_list(struct scsi_cmnd *cmd, int nseg,
 		       struct srp_direct_buf *md)
 {
 	int i;
+	struct scatterlist *sg;
 	u64 total_length = 0;
 
-	for (i = 0; i < num_entries; ++i) {
+	scsi_for_each_sg(cmd, sg, nseg, i) {
 		struct srp_direct_buf *descr = md + i;
-		struct scatterlist *sg_entry = &sg[i];
-		descr->va = sg_dma_address(sg_entry);
-		descr->len = sg_dma_len(sg_entry);
+		descr->va = sg_dma_address(sg);
+		descr->len = sg_dma_len(sg);
 		descr->key = 0;
-		total_length += sg_dma_len(sg_entry);
+		total_length += sg_dma_len(sg);
  	}
 	return total_length;
 }
@@ -387,40 +383,37 @@
 
 	int sg_mapped;
 	u64 total_length = 0;
-	struct scatterlist *sg = cmd->request_buffer;
 	struct srp_direct_buf *data =
 		(struct srp_direct_buf *) srp_cmd->add_data;
 	struct srp_indirect_buf *indirect =
 		(struct srp_indirect_buf *) data;
 
-	sg_mapped = dma_map_sg(dev, sg, cmd->use_sg, DMA_BIDIRECTIONAL);
-
-	if (sg_mapped == 0)
+	sg_mapped = scsi_dma_map(cmd);
+	if (!sg_mapped)
+		return 1;
+	else if (sg_mapped < 0)
 		return 0;
+	else if (sg_mapped > SG_ALL) {
+		printk(KERN_ERR
+		       "ibmvscsi: More than %d mapped sg entries, got %d\n",
+		       SG_ALL, sg_mapped);
+		return 0;
+	}
 
 	set_srp_direction(cmd, srp_cmd, sg_mapped);
 
 	/* special case; we can use a single direct descriptor */
 	if (sg_mapped == 1) {
-		data->va = sg_dma_address(&sg[0]);
-		data->len = sg_dma_len(&sg[0]);
-		data->key = 0;
+		map_sg_list(cmd, sg_mapped, data);
 		return 1;
 	}
 
-	if (sg_mapped > SG_ALL) {
-		printk(KERN_ERR
-		       "ibmvscsi: More than %d mapped sg entries, got %d\n",
-		       SG_ALL, sg_mapped);
-		return 0;
-	}
-
 	indirect->table_desc.va = 0;
 	indirect->table_desc.len = sg_mapped * sizeof(struct srp_direct_buf);
 	indirect->table_desc.key = 0;
 
 	if (sg_mapped <= MAX_INDIRECT_BUFS) {
-		total_length = map_sg_list(sg_mapped, sg,
+		total_length = map_sg_list(cmd, sg_mapped,
 					   &indirect->desc_list[0]);
 		indirect->len = total_length;
 		return 1;
@@ -429,61 +422,27 @@
 	/* get indirect table */
 	if (!evt_struct->ext_list) {
 		evt_struct->ext_list = (struct srp_direct_buf *)
-			dma_alloc_coherent(dev, 
+			dma_alloc_coherent(dev,
 					   SG_ALL * sizeof(struct srp_direct_buf),
 					   &evt_struct->ext_list_token, 0);
 		if (!evt_struct->ext_list) {
-			printk(KERN_ERR
-			       "ibmvscsi: Can't allocate memory for indirect table\n");
+			sdev_printk(KERN_ERR, cmd->device,
+				    "Can't allocate memory for indirect table\n");
 			return 0;
-			
 		}
 	}
 
-	total_length = map_sg_list(sg_mapped, sg, evt_struct->ext_list);	
+	total_length = map_sg_list(cmd, sg_mapped, evt_struct->ext_list);
 
 	indirect->len = total_length;
 	indirect->table_desc.va = evt_struct->ext_list_token;
 	indirect->table_desc.len = sg_mapped * sizeof(indirect->desc_list[0]);
 	memcpy(indirect->desc_list, evt_struct->ext_list,
 	       MAX_INDIRECT_BUFS * sizeof(struct srp_direct_buf));
-	
  	return 1;
 }
 
 /**
- * map_single_data: - Maps memory and initializes memory decriptor fields
- * @cmd:	struct scsi_cmnd with the memory to be mapped
- * @srp_cmd:	srp_cmd that contains the memory descriptor
- * @dev:	device for which to map dma memory
- *
- * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd.
- * Returns 1 on success.
-*/
-static int map_single_data(struct scsi_cmnd *cmd,
-			   struct srp_cmd *srp_cmd, struct device *dev)
-{
-	struct srp_direct_buf *data =
-		(struct srp_direct_buf *) srp_cmd->add_data;
-
-	data->va =
-		dma_map_single(dev, cmd->request_buffer,
-			       cmd->request_bufflen,
-			       DMA_BIDIRECTIONAL);
-	if (dma_mapping_error(data->va)) {
-		printk(KERN_ERR
-		       "ibmvscsi: Unable to map request_buffer for command!\n");
-		return 0;
-	}
-	data->len = cmd->request_bufflen;
-	data->key = 0;
-
-	set_srp_direction(cmd, srp_cmd, 1);
-
-	return 1;
-}
-
-/**
  * map_data_for_srp_cmd: - Calls functions to map data for srp cmds
  * @cmd:	struct scsi_cmnd with the memory to be mapped
  * @srp_cmd:	srp_cmd that contains the memory descriptor
@@ -503,23 +462,83 @@
 	case DMA_NONE:
 		return 1;
 	case DMA_BIDIRECTIONAL:
-		printk(KERN_ERR
-		       "ibmvscsi: Can't map DMA_BIDIRECTIONAL to read/write\n");
+		sdev_printk(KERN_ERR, cmd->device,
+			    "Can't map DMA_BIDIRECTIONAL to read/write\n");
 		return 0;
 	default:
-		printk(KERN_ERR
-		       "ibmvscsi: Unknown data direction 0x%02x; can't map!\n",
-		       cmd->sc_data_direction);
+		sdev_printk(KERN_ERR, cmd->device,
+			    "Unknown data direction 0x%02x; can't map!\n",
+			    cmd->sc_data_direction);
 		return 0;
 	}
 
-	if (!cmd->request_buffer)
-		return 1;
-	if (cmd->use_sg)
-		return map_sg_data(cmd, evt_struct, srp_cmd, dev);
-	return map_single_data(cmd, srp_cmd, dev);
+	return map_sg_data(cmd, evt_struct, srp_cmd, dev);
 }
 
+/**
+ * purge_requests: Our virtual adapter just shut down.  purge any sent requests
+ * @hostdata:    the adapter
+ */
+static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
+{
+	struct srp_event_struct *tmp_evt, *pos;
+	unsigned long flags;
+
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
+	list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
+		list_del(&tmp_evt->list);
+		del_timer(&tmp_evt->timer);
+		if (tmp_evt->cmnd) {
+			tmp_evt->cmnd->result = (error_code << 16);
+			unmap_cmd_data(&tmp_evt->iu.srp.cmd,
+				       tmp_evt,
+				       tmp_evt->hostdata->dev);
+			if (tmp_evt->cmnd_done)
+				tmp_evt->cmnd_done(tmp_evt->cmnd);
+		} else if (tmp_evt->done)
+			tmp_evt->done(tmp_evt);
+		free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
+	}
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+}
+
+/**
+ * ibmvscsi_reset_host - Reset the connection to the server
+ * @hostdata:	struct ibmvscsi_host_data to reset
+*/
+static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
+{
+	scsi_block_requests(hostdata->host);
+	atomic_set(&hostdata->request_limit, 0);
+
+	purge_requests(hostdata, DID_ERROR);
+	if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) ||
+	    (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0)) ||
+	    (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) {
+		atomic_set(&hostdata->request_limit, -1);
+		dev_err(hostdata->dev, "error after reset\n");
+	}
+
+	scsi_unblock_requests(hostdata->host);
+}
+
+/**
+ * ibmvscsi_timeout - Internal command timeout handler
+ * @evt_struct:	struct srp_event_struct that timed out
+ *
+ * Called when an internally generated command times out
+*/
+static void ibmvscsi_timeout(struct srp_event_struct *evt_struct)
+{
+	struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
+
+	dev_err(hostdata->dev, "Command timed out (%x). Resetting connection\n",
+		evt_struct->iu.srp.cmd.opcode);
+
+	ibmvscsi_reset_host(hostdata);
+}
+
+
 /* ------------------------------------------------------------
  * Routines for sending and receiving SRPs
  */
@@ -527,12 +546,14 @@
  * ibmvscsi_send_srp_event: - Transforms event to u64 array and calls send_crq()
  * @evt_struct:	evt_struct to be sent
  * @hostdata:	ibmvscsi_host_data of host
+ * @timeout:	timeout in seconds - 0 means do not time command
  *
  * Returns the value returned from ibmvscsi_send_crq(). (Zero for success)
  * Note that this routine assumes that host_lock is held for synchronization
 */
 static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
-				   struct ibmvscsi_host_data *hostdata)
+				   struct ibmvscsi_host_data *hostdata,
+				   unsigned long timeout)
 {
 	u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
 	int request_status;
@@ -588,12 +609,20 @@
 	 */
 	list_add_tail(&evt_struct->list, &hostdata->sent);
 
+	init_timer(&evt_struct->timer);
+	if (timeout) {
+		evt_struct->timer.data = (unsigned long) evt_struct;
+		evt_struct->timer.expires = jiffies + (timeout * HZ);
+		evt_struct->timer.function = (void (*)(unsigned long))ibmvscsi_timeout;
+		add_timer(&evt_struct->timer);
+	}
+
 	if ((rc =
 	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
 		list_del(&evt_struct->list);
+		del_timer(&evt_struct->timer);
 
-		printk(KERN_ERR "ibmvscsi: send error %d\n",
-		       rc);
+		dev_err(hostdata->dev, "send error %d\n", rc);
 		atomic_inc(&hostdata->request_limit);
 		goto send_error;
 	}
@@ -634,9 +663,8 @@
 
 	if (unlikely(rsp->opcode != SRP_RSP)) {
 		if (printk_ratelimit())
-			printk(KERN_WARNING 
-			       "ibmvscsi: bad SRP RSP type %d\n",
-			       rsp->opcode);
+			dev_warn(evt_struct->hostdata->dev,
+				 "bad SRP RSP type %d\n", rsp->opcode);
 	}
 	
 	if (cmnd) {
@@ -650,9 +678,9 @@
 			       evt_struct->hostdata->dev);
 
 		if (rsp->flags & SRP_RSP_FLAG_DOOVER)
-			cmnd->resid = rsp->data_out_res_cnt;
+			scsi_set_resid(cmnd, rsp->data_out_res_cnt);
 		else if (rsp->flags & SRP_RSP_FLAG_DIOVER)
-			cmnd->resid = rsp->data_in_res_cnt;
+			scsi_set_resid(cmnd, rsp->data_in_res_cnt);
 	}
 
 	if (evt_struct->cmnd_done)
@@ -697,7 +725,7 @@
 	srp_cmd->lun = ((u64) lun) << 48;
 
 	if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
-		printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
+		sdev_printk(KERN_ERR, cmnd->device, "couldn't convert cmd to srp_cmd\n");
 		free_event_struct(&hostdata->pool, evt_struct);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
@@ -722,7 +750,7 @@
 			offsetof(struct srp_indirect_buf, desc_list);
 	}
 
-	return ibmvscsi_send_srp_event(evt_struct, hostdata);
+	return ibmvscsi_send_srp_event(evt_struct, hostdata, 0);
 }
 
 /* ------------------------------------------------------------
@@ -744,16 +772,16 @@
 			 DMA_BIDIRECTIONAL);
 
 	if (evt_struct->xfer_iu->mad.adapter_info.common.status) {
-		printk("ibmvscsi: error %d getting adapter info\n",
-		       evt_struct->xfer_iu->mad.adapter_info.common.status);
+		dev_err(hostdata->dev, "error %d getting adapter info\n",
+			evt_struct->xfer_iu->mad.adapter_info.common.status);
 	} else {
-		printk("ibmvscsi: host srp version: %s, "
-		       "host partition %s (%d), OS %d, max io %u\n",
-		       hostdata->madapter_info.srp_version,
-		       hostdata->madapter_info.partition_name,
-		       hostdata->madapter_info.partition_number,
-		       hostdata->madapter_info.os_type,
-		       hostdata->madapter_info.port_max_txu[0]);
+		dev_info(hostdata->dev, "host srp version: %s, "
+			 "host partition %s (%d), OS %d, max io %u\n",
+			 hostdata->madapter_info.srp_version,
+			 hostdata->madapter_info.partition_name,
+			 hostdata->madapter_info.partition_number,
+			 hostdata->madapter_info.os_type,
+			 hostdata->madapter_info.port_max_txu[0]);
 		
 		if (hostdata->madapter_info.port_max_txu[0]) 
 			hostdata->host->max_sectors = 
@@ -761,11 +789,10 @@
 		
 		if (hostdata->madapter_info.os_type == 3 &&
 		    strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) {
-			printk("ibmvscsi: host (Ver. %s) doesn't support large"
-			       "transfers\n",
-			       hostdata->madapter_info.srp_version);
-			printk("ibmvscsi: limiting scatterlists to %d\n",
-			       MAX_INDIRECT_BUFS);
+			dev_err(hostdata->dev, "host (Ver. %s) doesn't support large transfers\n",
+				hostdata->madapter_info.srp_version);
+			dev_err(hostdata->dev, "limiting scatterlists to %d\n",
+				MAX_INDIRECT_BUFS);
 			hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
 		}
 	}
@@ -784,19 +811,20 @@
 {
 	struct viosrp_adapter_info *req;
 	struct srp_event_struct *evt_struct;
+	unsigned long flags;
 	dma_addr_t addr;
 
 	evt_struct = get_event_struct(&hostdata->pool);
 	if (!evt_struct) {
-		printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
-		       "for ADAPTER_INFO_REQ!\n");
+		dev_err(hostdata->dev,
+			"couldn't allocate an event for ADAPTER_INFO_REQ!\n");
 		return;
 	}
 
 	init_event_struct(evt_struct,
 			  adapter_info_rsp,
 			  VIOSRP_MAD_FORMAT,
-			  init_timeout * HZ);
+			  init_timeout);
 	
 	req = &evt_struct->iu.mad.adapter_info;
 	memset(req, 0x00, sizeof(*req));
@@ -809,20 +837,20 @@
 					    DMA_BIDIRECTIONAL);
 
 	if (dma_mapping_error(req->buffer)) {
-		printk(KERN_ERR
-		       "ibmvscsi: Unable to map request_buffer "
-		       "for adapter_info!\n");
+		dev_err(hostdata->dev, "Unable to map request_buffer for adapter_info!\n");
 		free_event_struct(&hostdata->pool, evt_struct);
 		return;
 	}
 	
-	if (ibmvscsi_send_srp_event(evt_struct, hostdata)) {
-		printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
+	if (ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2)) {
+		dev_err(hostdata->dev, "couldn't send ADAPTER_INFO_REQ!\n");
 		dma_unmap_single(hostdata->dev,
 				 addr,
 				 sizeof(hostdata->madapter_info),
 				 DMA_BIDIRECTIONAL);
 	}
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 };
 
 /**
@@ -839,24 +867,23 @@
 	case SRP_LOGIN_RSP:	/* it worked! */
 		break;
 	case SRP_LOGIN_REJ:	/* refused! */
-		printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
-		       evt_struct->xfer_iu->srp.login_rej.reason);
+		dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
+			 evt_struct->xfer_iu->srp.login_rej.reason);
 		/* Login failed.  */
 		atomic_set(&hostdata->request_limit, -1);
 		return;
 	default:
-		printk(KERN_ERR
-		       "ibmvscsi: Invalid login response typecode 0x%02x!\n",
-		       evt_struct->xfer_iu->srp.login_rsp.opcode);
+		dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
+			evt_struct->xfer_iu->srp.login_rsp.opcode);
 		/* Login failed.  */
 		atomic_set(&hostdata->request_limit, -1);
 		return;
 	}
 
-	printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
+	dev_info(hostdata->dev, "SRP_LOGIN succeeded\n");
 
 	if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0)
-		printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n");
+		dev_err(hostdata->dev, "Invalid request_limit.\n");
 
 	/* Now we know what the real request-limit is.
 	 * This value is set rather than added to request_limit because
@@ -885,15 +912,14 @@
 	struct srp_login_req *login;
 	struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool);
 	if (!evt_struct) {
-		printk(KERN_ERR
-		       "ibmvscsi: couldn't allocate an event for login req!\n");
+		dev_err(hostdata->dev, "couldn't allocate an event for login req!\n");
 		return FAILED;
 	}
 
 	init_event_struct(evt_struct,
 			  login_rsp,
 			  VIOSRP_SRP_FORMAT,
-			  init_timeout * HZ);
+			  init_timeout);
 
 	login = &evt_struct->iu.srp.login_req;
 	memset(login, 0x00, sizeof(struct srp_login_req));
@@ -907,9 +933,9 @@
 	 */
 	atomic_set(&hostdata->request_limit, 1);
 
-	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+	rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2);
 	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
-	printk("ibmvscsic: sent SRP login\n");
+	dev_info(hostdata->dev, "sent SRP login\n");
 	return rc;
 };
 
@@ -958,20 +984,20 @@
 
 	if (!found_evt) {
 		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
-		return FAILED;
+		return SUCCESS;
 	}
 
 	evt = get_event_struct(&hostdata->pool);
 	if (evt == NULL) {
 		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
-		printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
+		sdev_printk(KERN_ERR, cmd->device, "failed to allocate abort event\n");
 		return FAILED;
 	}
 	
 	init_event_struct(evt,
 			  sync_completion,
 			  VIOSRP_SRP_FORMAT,
-			  init_timeout * HZ);
+			  init_timeout);
 
 	tsk_mgmt = &evt->iu.srp.tsk_mgmt;
 	
@@ -982,15 +1008,16 @@
 	tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
 	tsk_mgmt->task_tag = (u64) found_evt;
 
-	printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
-	       tsk_mgmt->lun, tsk_mgmt->task_tag);
+	sdev_printk(KERN_INFO, cmd->device, "aborting command. lun 0x%lx, tag 0x%lx\n",
+		    tsk_mgmt->lun, tsk_mgmt->task_tag);
 
 	evt->sync_srp = &srp_rsp;
 	init_completion(&evt->comp);
-	rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+	rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
 	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 	if (rsp_rc != 0) {
-		printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
+		sdev_printk(KERN_ERR, cmd->device,
+			    "failed to send abort() event. rc=%d\n", rsp_rc);
 		return FAILED;
 	}
 
@@ -999,9 +1026,8 @@
 	/* make sure we got a good response */
 	if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
 		if (printk_ratelimit())
-			printk(KERN_WARNING 
-			       "ibmvscsi: abort bad SRP RSP type %d\n",
-			       srp_rsp.srp.rsp.opcode);
+			sdev_printk(KERN_WARNING, cmd->device, "abort bad SRP RSP type %d\n",
+				    srp_rsp.srp.rsp.opcode);
 		return FAILED;
 	}
 
@@ -1012,10 +1038,9 @@
 
 	if (rsp_rc) {
 		if (printk_ratelimit())
-			printk(KERN_WARNING 
-			       "ibmvscsi: abort code %d for task tag 0x%lx\n",
-			       rsp_rc,
-			       tsk_mgmt->task_tag);
+			sdev_printk(KERN_WARNING, cmd->device,
+				    "abort code %d for task tag 0x%lx\n",
+				    rsp_rc, tsk_mgmt->task_tag);
 		return FAILED;
 	}
 
@@ -1034,15 +1059,13 @@
 
 	if (found_evt == NULL) {
 		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
-		printk(KERN_INFO
-		       "ibmvscsi: aborted task tag 0x%lx completed\n",
-		       tsk_mgmt->task_tag);
+		sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%lx completed\n",
+			    tsk_mgmt->task_tag);
 		return SUCCESS;
 	}
 
-	printk(KERN_INFO
-	       "ibmvscsi: successfully aborted task tag 0x%lx\n",
-	       tsk_mgmt->task_tag);
+	sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%lx\n",
+		    tsk_mgmt->task_tag);
 
 	cmd->result = (DID_ABORT << 16);
 	list_del(&found_evt->list);
@@ -1076,14 +1099,14 @@
 	evt = get_event_struct(&hostdata->pool);
 	if (evt == NULL) {
 		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
-		printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
+		sdev_printk(KERN_ERR, cmd->device, "failed to allocate reset event\n");
 		return FAILED;
 	}
 	
 	init_event_struct(evt,
 			  sync_completion,
 			  VIOSRP_SRP_FORMAT,
-			  init_timeout * HZ);
+			  init_timeout);
 
 	tsk_mgmt = &evt->iu.srp.tsk_mgmt;
 
@@ -1093,15 +1116,16 @@
 	tsk_mgmt->lun = ((u64) lun) << 48;
 	tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
 
-	printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
-	       tsk_mgmt->lun);
+	sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n",
+		    tsk_mgmt->lun);
 
 	evt->sync_srp = &srp_rsp;
 	init_completion(&evt->comp);
-	rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+	rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
 	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 	if (rsp_rc != 0) {
-		printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
+		sdev_printk(KERN_ERR, cmd->device,
+			    "failed to send reset event. rc=%d\n", rsp_rc);
 		return FAILED;
 	}
 
@@ -1110,9 +1134,8 @@
 	/* make sure we got a good response */
 	if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
 		if (printk_ratelimit())
-			printk(KERN_WARNING 
-			       "ibmvscsi: reset bad SRP RSP type %d\n",
-			       srp_rsp.srp.rsp.opcode);
+			sdev_printk(KERN_WARNING, cmd->device, "reset bad SRP RSP type %d\n",
+				    srp_rsp.srp.rsp.opcode);
 		return FAILED;
 	}
 
@@ -1123,9 +1146,9 @@
 
 	if (rsp_rc) {
 		if (printk_ratelimit())
-			printk(KERN_WARNING 
-			       "ibmvscsi: reset code %d for task tag 0x%lx\n",
-			       rsp_rc, tsk_mgmt->task_tag);
+			sdev_printk(KERN_WARNING, cmd->device,
+				    "reset code %d for task tag 0x%lx\n",
+				    rsp_rc, tsk_mgmt->task_tag);
 		return FAILED;
 	}
 
@@ -1154,32 +1177,30 @@
 }
 
 /**
- * purge_requests: Our virtual adapter just shut down.  purge any sent requests
- * @hostdata:    the adapter
- */
-static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
+ * ibmvscsi_eh_host_reset_handler - Reset the connection to the server
+ * @cmd:	struct scsi_cmnd having problems
+*/
+static int ibmvscsi_eh_host_reset_handler(struct scsi_cmnd *cmd)
 {
-	struct srp_event_struct *tmp_evt, *pos;
-	unsigned long flags;
+	unsigned long wait_switch = 0;
+	struct ibmvscsi_host_data *hostdata =
+		(struct ibmvscsi_host_data *)cmd->device->host->hostdata;
 
-	spin_lock_irqsave(hostdata->host->host_lock, flags);
-	list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
-		list_del(&tmp_evt->list);
-		if (tmp_evt->cmnd) {
-			tmp_evt->cmnd->result = (error_code << 16);
-			unmap_cmd_data(&tmp_evt->iu.srp.cmd, 
-				       tmp_evt,	
-				       tmp_evt->hostdata->dev);
-			if (tmp_evt->cmnd_done)
-				tmp_evt->cmnd_done(tmp_evt->cmnd);
-		} else {
-			if (tmp_evt->done) {
-				tmp_evt->done(tmp_evt);
-			}
-		}
-		free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
+	dev_err(hostdata->dev, "Resetting connection due to error recovery\n");
+
+	ibmvscsi_reset_host(hostdata);
+
+	for (wait_switch = jiffies + (init_timeout * HZ);
+	     time_before(jiffies, wait_switch) &&
+		     atomic_read(&hostdata->request_limit) < 2;) {
+
+		msleep(10);
 	}
-	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+
+	if (atomic_read(&hostdata->request_limit) <= 0)
+		return FAILED;
+
+	return SUCCESS;
 }
 
 /**
@@ -1191,6 +1212,7 @@
 void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 			 struct ibmvscsi_host_data *hostdata)
 {
+	long rc;
 	unsigned long flags;
 	struct srp_event_struct *evt_struct =
 	    (struct srp_event_struct *)crq->IU_data_ptr;
@@ -1198,27 +1220,25 @@
 	case 0xC0:		/* initialization */
 		switch (crq->format) {
 		case 0x01:	/* Initialization message */
-			printk(KERN_INFO "ibmvscsi: partner initialized\n");
+			dev_info(hostdata->dev, "partner initialized\n");
 			/* Send back a response */
-			if (ibmvscsi_send_crq(hostdata,
-					      0xC002000000000000LL, 0) == 0) {
+			if ((rc = ibmvscsi_send_crq(hostdata,
+						    0xC002000000000000LL, 0)) == 0) {
 				/* Now login */
 				send_srp_login(hostdata);
 			} else {
-				printk(KERN_ERR
-				       "ibmvscsi: Unable to send init rsp\n");
+				dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc);
 			}
 
 			break;
 		case 0x02:	/* Initialization response */
-			printk(KERN_INFO
-			       "ibmvscsi: partner initialization complete\n");
+			dev_info(hostdata->dev, "partner initialization complete\n");
 
 			/* Now login */
 			send_srp_login(hostdata);
 			break;
 		default:
-			printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
+			dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format);
 		}
 		return;
 	case 0xFF:	/* Hypervisor telling us the connection is closed */
@@ -1226,8 +1246,7 @@
 		atomic_set(&hostdata->request_limit, 0);
 		if (crq->format == 0x06) {
 			/* We need to re-setup the interpartition connection */
-			printk(KERN_INFO
-			       "ibmvscsi: Re-enabling adapter!\n");
+			dev_info(hostdata->dev, "Re-enabling adapter!\n");
 			purge_requests(hostdata, DID_REQUEUE);
 			if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
 							hostdata)) ||
@@ -1235,14 +1254,11 @@
 					       0xC001000000000000LL, 0))) {
 					atomic_set(&hostdata->request_limit,
 						   -1);
-					printk(KERN_ERR
-					       "ibmvscsi: error after"
-					       " enable\n");
+					dev_err(hostdata->dev, "error after enable\n");
 			}
 		} else {
-			printk(KERN_INFO
-			       "ibmvscsi: Virtual adapter failed rc %d!\n",
-			       crq->format);
+			dev_err(hostdata->dev, "Virtual adapter failed rc %d!\n",
+				crq->format);
 
 			purge_requests(hostdata, DID_ERROR);
 			if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
@@ -1251,8 +1267,7 @@
 					       0xC001000000000000LL, 0))) {
 					atomic_set(&hostdata->request_limit,
 						   -1);
-					printk(KERN_ERR
-					       "ibmvscsi: error after reset\n");
+					dev_err(hostdata->dev, "error after reset\n");
 			}
 		}
 		scsi_unblock_requests(hostdata->host);
@@ -1260,9 +1275,8 @@
 	case 0x80:		/* real payload */
 		break;
 	default:
-		printk(KERN_ERR
-		       "ibmvscsi: got an invalid message type 0x%02x\n",
-		       crq->valid);
+		dev_err(hostdata->dev, "got an invalid message type 0x%02x\n",
+			crq->valid);
 		return;
 	}
 
@@ -1271,16 +1285,14 @@
 	 * actually sent
 	 */
 	if (!valid_event_struct(&hostdata->pool, evt_struct)) {
-		printk(KERN_ERR
-		       "ibmvscsi: returned correlation_token 0x%p is invalid!\n",
+		dev_err(hostdata->dev, "returned correlation_token 0x%p is invalid!\n",
 		       (void *)crq->IU_data_ptr);
 		return;
 	}
 
 	if (atomic_read(&evt_struct->free)) {
-		printk(KERN_ERR
-		       "ibmvscsi: received duplicate  correlation_token 0x%p!\n",
-		       (void *)crq->IU_data_ptr);
+		dev_err(hostdata->dev, "received duplicate correlation_token 0x%p!\n",
+			(void *)crq->IU_data_ptr);
 		return;
 	}
 
@@ -1288,11 +1300,12 @@
 		atomic_add(evt_struct->xfer_iu->srp.rsp.req_lim_delta,
 			   &hostdata->request_limit);
 
+	del_timer(&evt_struct->timer);
+
 	if (evt_struct->done)
 		evt_struct->done(evt_struct);
 	else
-		printk(KERN_ERR
-		       "ibmvscsi: returned done() is NULL; not running it!\n");
+		dev_err(hostdata->dev, "returned done() is NULL; not running it!\n");
 
 	/*
 	 * Lock the host_lock before messing with these structures, since we
@@ -1313,20 +1326,20 @@
 {
 	struct viosrp_host_config *host_config;
 	struct srp_event_struct *evt_struct;
+	unsigned long flags;
 	dma_addr_t addr;
 	int rc;
 
 	evt_struct = get_event_struct(&hostdata->pool);
 	if (!evt_struct) {
-		printk(KERN_ERR
-		       "ibmvscsi: could't allocate event for HOST_CONFIG!\n");
+		dev_err(hostdata->dev, "couldn't allocate event for HOST_CONFIG!\n");
 		return -1;
 	}
 
 	init_event_struct(evt_struct,
 			  sync_completion,
 			  VIOSRP_MAD_FORMAT,
-			  init_timeout * HZ);
+			  init_timeout);
 
 	host_config = &evt_struct->iu.mad.host_config;
 
@@ -1339,14 +1352,15 @@
 						    DMA_BIDIRECTIONAL);
 
 	if (dma_mapping_error(host_config->buffer)) {
-		printk(KERN_ERR
-		       "ibmvscsi: dma_mapping error " "getting host config\n");
+		dev_err(hostdata->dev, "dma_mapping error getting host config\n");
 		free_event_struct(&hostdata->pool, evt_struct);
 		return -1;
 	}
 
 	init_completion(&evt_struct->comp);
-	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
+	rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2);
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 	if (rc == 0)
 		wait_for_completion(&evt_struct->comp);
 	dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL);
@@ -1375,6 +1389,23 @@
 	return 0;
 }
 
+/**
+ * ibmvscsi_change_queue_depth - Change the device's queue depth
+ * @sdev:	scsi device struct
+ * @qdepth:	depth to set
+ *
+ * Return value:
+ * 	actual depth set
+ **/
+static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+	if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
+		qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
+
+	scsi_adjust_queue_depth(sdev, 0, qdepth);
+	return sdev->queue_depth;
+}
+
 /* ------------------------------------------------------------
  * sysfs attributes
  */
@@ -1520,7 +1551,9 @@
 	.queuecommand = ibmvscsi_queuecommand,
 	.eh_abort_handler = ibmvscsi_eh_abort_handler,
 	.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+	.eh_host_reset_handler = ibmvscsi_eh_host_reset_handler,
 	.slave_configure = ibmvscsi_slave_configure,
+	.change_queue_depth = ibmvscsi_change_queue_depth,
 	.cmd_per_lun = 16,
 	.can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
 	.this_id = -1,
@@ -1545,7 +1578,7 @@
 	driver_template.can_queue = max_requests;
 	host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
 	if (!host) {
-		printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
+		dev_err(&vdev->dev, "couldn't allocate host data\n");
 		goto scsi_host_alloc_failed;
 	}
 
@@ -1559,11 +1592,11 @@
 
 	rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
 	if (rc != 0 && rc != H_RESOURCE) {
-		printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
+		dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
 		goto init_crq_failed;
 	}
 	if (initialize_event_pool(&hostdata->pool, max_requests, hostdata) != 0) {
-		printk(KERN_ERR "ibmvscsi: couldn't initialize event pool\n");
+		dev_err(&vdev->dev, "couldn't initialize event pool\n");
 		goto init_pool_failed;
 	}
 
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 77cc1d4..b19c2e2 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -45,6 +45,7 @@
 #define MAX_INDIRECT_BUFS 10
 
 #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+#define IBMVSCSI_MAX_CMDS_PER_LUN 64
 
 /* ------------------------------------------------------------
  * Data Structures
@@ -69,6 +70,7 @@
 	union viosrp_iu iu;
 	void (*cmnd_done) (struct scsi_cmnd *);
 	struct completion comp;
+	struct timer_list timer;
 	union viosrp_iu *sync_srp;
 	struct srp_direct_buf *ext_list;
 	dma_addr_t ext_list_token;
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index d8700aa..9c14e78 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -177,7 +177,7 @@
 	memset(&hostdata->madapter_info, 0x00,
 			sizeof(hostdata->madapter_info));
 
-	printk(KERN_INFO "rpa_vscsi: SPR_VERSION: %s\n", SRP_VERSION);
+	dev_info(hostdata->dev, "SRP_VERSION: %s\n", SRP_VERSION);
 	strcpy(hostdata->madapter_info.srp_version, SRP_VERSION);
 
 	strncpy(hostdata->madapter_info.partition_name, partition_name,
@@ -232,25 +232,24 @@
 
 	if (rc == 2) {
 		/* Adapter is good, but other end is not ready */
-		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+		dev_warn(hostdata->dev, "Partner adapter not ready\n");
 		retrc = 0;
 	} else if (rc != 0) {
-		printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
+		dev_warn(hostdata->dev, "Error %d opening adapter\n", rc);
 		goto reg_crq_failed;
 	}
 
 	if (request_irq(vdev->irq,
 			ibmvscsi_handle_event,
 			0, "ibmvscsi", (void *)hostdata) != 0) {
-		printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
-		       vdev->irq);
+		dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
+			vdev->irq);
 		goto req_irq_failed;
 	}
 
 	rc = vio_enable_interrupts(vdev);
 	if (rc != 0) {
-		printk(KERN_ERR "ibmvscsi:  Error %d enabling interrupts!!!\n",
-		       rc);
+		dev_err(hostdata->dev, "Error %d enabling interrupts!!!\n", rc);
 		goto req_irq_failed;
 	}
 
@@ -294,7 +293,7 @@
 	} while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
 
 	if (rc)
-		printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
+		dev_err(hostdata->dev, "Error %d enabling adapter\n", rc);
 	return rc;
 }
 
@@ -327,10 +326,9 @@
 				queue->msg_token, PAGE_SIZE);
 	if (rc == 2) {
 		/* Adapter is good, but other end is not ready */
-		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+		dev_warn(hostdata->dev, "Partner adapter not ready\n");
 	} else if (rc != 0) {
-		printk(KERN_WARNING
-		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
+		dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
 	}
 	return rc;
 }
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 8263f75..bb90df8 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -463,7 +463,7 @@
 
 static int idescsi_expiry(ide_drive_t *drive)
 {
-	idescsi_scsi_t *scsi = drive->driver_data;
+	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
 	idescsi_pc_t   *pc   = scsi->pc;
 
 #if IDESCSI_DEBUG_LOG
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 7e7635c..d9dfb69 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -3,7 +3,8 @@
  *
  * Copyright (c) 1994-1998 Initio Corporation
  * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
- * All rights reserved.
+ * Copyright (c) 2004 Christoph Hellwig <hch@lst.de>
+ * Copyright (c) 2007 Red Hat <alan@redhat.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,38 +20,6 @@
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * --------------------------------------------------------------------------
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of 
- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
  *
  *************************************************************************
  *
@@ -70,14 +39,14 @@
  *		- Fix memory allocation problem
  * 03/04/98 hc	- v1.01l
  *		- Fix tape rewind which will hang the system problem
- *		- Set can_queue to tul_num_scb
+ *		- Set can_queue to initio_num_scb
  * 06/25/98 hc	- v1.01m
  *		- Get it work for kernel version >= 2.1.75
- *		- Dynamic assign SCSI bus reset holding time in init_tulip()
+ *		- Dynamic assign SCSI bus reset holding time in initio_init()
  * 07/02/98 hc	- v1.01n
  *		- Support 0002134A
  * 08/07/98 hc  - v1.01o
- *		- Change the tul_abort_srb routine to use scsi_done. <01>
+ *		- Change the initio_abort_srb routine to use scsi_done. <01>
  * 09/07/98 hl  - v1.02
  *              - Change the INI9100U define and proc_dir_entry to
  *                reflect the newer Kernel 2.1.118, but the v1.o1o
@@ -150,23 +119,13 @@
 static unsigned int i91u_debug = DEBUG_DEFAULT;
 #endif
 
-#define TUL_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
-
-typedef struct PCI_ID_Struc {
-	unsigned short vendor_id;
-	unsigned short device_id;
-} PCI_ID;
-
-static int tul_num_ch = 4;	/* Maximum 4 adapters           */
-static int tul_num_scb;
-static int tul_tag_enable = 1;
-static SCB *tul_scb;
+static int initio_tag_enable = 1;
 
 #ifdef DEBUG_i91u
 static int setup_debug = 0;
 #endif
 
-static void i91uSCBPost(BYTE * pHcb, BYTE * pScb);
+static void i91uSCBPost(u8 * pHcb, u8 * pScb);
 
 /* PCI Devices supported by this driver */
 static struct pci_device_id i91u_pci_devices[] = {
@@ -184,74 +143,66 @@
 #define DEBUG_STATE     0
 #define INT_DISC	0
 
-/*--- external functions --*/
-static void tul_se2_wait(void);
+/*--- forward references ---*/
+static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun);
+static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host);
 
-/*--- forward refrence ---*/
-static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
-static SCB *tul_find_done_scb(HCS * pCurHcb);
+static int tulip_main(struct initio_host * host);
 
-static int tulip_main(HCS * pCurHcb);
+static int initio_next_state(struct initio_host * host);
+static int initio_state_1(struct initio_host * host);
+static int initio_state_2(struct initio_host * host);
+static int initio_state_3(struct initio_host * host);
+static int initio_state_4(struct initio_host * host);
+static int initio_state_5(struct initio_host * host);
+static int initio_state_6(struct initio_host * host);
+static int initio_state_7(struct initio_host * host);
+static int initio_xfer_data_in(struct initio_host * host);
+static int initio_xfer_data_out(struct initio_host * host);
+static int initio_xpad_in(struct initio_host * host);
+static int initio_xpad_out(struct initio_host * host);
+static int initio_status_msg(struct initio_host * host);
 
-static int tul_next_state(HCS * pCurHcb);
-static int tul_state_1(HCS * pCurHcb);
-static int tul_state_2(HCS * pCurHcb);
-static int tul_state_3(HCS * pCurHcb);
-static int tul_state_4(HCS * pCurHcb);
-static int tul_state_5(HCS * pCurHcb);
-static int tul_state_6(HCS * pCurHcb);
-static int tul_state_7(HCS * pCurHcb);
-static int tul_xfer_data_in(HCS * pCurHcb);
-static int tul_xfer_data_out(HCS * pCurHcb);
-static int tul_xpad_in(HCS * pCurHcb);
-static int tul_xpad_out(HCS * pCurHcb);
-static int tul_status_msg(HCS * pCurHcb);
+static int initio_msgin(struct initio_host * host);
+static int initio_msgin_sync(struct initio_host * host);
+static int initio_msgin_accept(struct initio_host * host);
+static int initio_msgout_reject(struct initio_host * host);
+static int initio_msgin_extend(struct initio_host * host);
 
-static int tul_msgin(HCS * pCurHcb);
-static int tul_msgin_sync(HCS * pCurHcb);
-static int tul_msgin_accept(HCS * pCurHcb);
-static int tul_msgout_reject(HCS * pCurHcb);
-static int tul_msgin_extend(HCS * pCurHcb);
+static int initio_msgout_ide(struct initio_host * host);
+static int initio_msgout_abort_targ(struct initio_host * host);
+static int initio_msgout_abort_tag(struct initio_host * host);
 
-static int tul_msgout_ide(HCS * pCurHcb);
-static int tul_msgout_abort_targ(HCS * pCurHcb);
-static int tul_msgout_abort_tag(HCS * pCurHcb);
+static int initio_bus_device_reset(struct initio_host * host);
+static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb);
+static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb);
+static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb);
+static int int_initio_busfree(struct initio_host * host);
+static int int_initio_scsi_rst(struct initio_host * host);
+static int int_initio_bad_seq(struct initio_host * host);
+static int int_initio_resel(struct initio_host * host);
+static int initio_sync_done(struct initio_host * host);
+static int wdtr_done(struct initio_host * host);
+static int wait_tulip(struct initio_host * host);
+static int initio_wait_done_disc(struct initio_host * host);
+static int initio_wait_disc(struct initio_host * host);
+static void tulip_scsi(struct initio_host * host);
+static int initio_post_scsi_rst(struct initio_host * host);
 
-static int tul_bus_device_reset(HCS * pCurHcb);
-static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
-static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
-static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
-static int int_tul_busfree(HCS * pCurHcb);
-static int int_tul_scsi_rst(HCS * pCurHcb);
-static int int_tul_bad_seq(HCS * pCurHcb);
-static int int_tul_resel(HCS * pCurHcb);
-static int tul_sync_done(HCS * pCurHcb);
-static int wdtr_done(HCS * pCurHcb);
-static int wait_tulip(HCS * pCurHcb);
-static int tul_wait_done_disc(HCS * pCurHcb);
-static int tul_wait_disc(HCS * pCurHcb);
-static void tulip_scsi(HCS * pCurHcb);
-static int tul_post_scsi_rst(HCS * pCurHcb);
+static void initio_se2_ew_en(unsigned long base);
+static void initio_se2_ew_ds(unsigned long base);
+static int initio_se2_rd_all(unsigned long base);
+static void initio_se2_update_all(unsigned long base);	/* setup default pattern */
+static void initio_read_eeprom(unsigned long base);
 
-static void tul_se2_ew_en(WORD CurBase);
-static void tul_se2_ew_ds(WORD CurBase);
-static int tul_se2_rd_all(WORD CurBase);
-static void tul_se2_update_all(WORD CurBase);	/* setup default pattern */
-static void tul_read_eeprom(WORD CurBase);
+/* ---- INTERNAL VARIABLES ---- */
 
-				/* ---- INTERNAL VARIABLES ---- */
-static HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
-static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
-
-/*NVRAM nvram, *nvramp = &nvram; */
 static NVRAM i91unvram;
 static NVRAM *i91unvramp;
 
-
-
-static UCHAR i91udftNvRam[64] =
+static u8 i91udftNvRam[64] =
 {
-/*----------- header -----------*/
+	/*----------- header -----------*/
 	0x25, 0xc9,		/* Signature    */
 	0x40,			/* Size         */
 	0x01,			/* Revision     */
@@ -289,7 +240,7 @@
 	0, 0};			/*      - CheckSum -            */
 
 
-static UCHAR tul_rate_tbl[8] =	/* fast 20      */
+static u8 initio_rate_tbl[8] =	/* fast 20      */
 {
 				/* nanosecond devide by 4 */
 	12,			/* 50ns,  20M   */
@@ -302,53 +253,17 @@
 	62			/* 250ns, 4M    */
 };
 
-static void tul_do_pause(unsigned amount)
-{				/* Pause for amount jiffies */
+static void initio_do_pause(unsigned amount)
+{
+	/* Pause for amount jiffies */
 	unsigned long the_time = jiffies + amount;
 
-	while (time_before_eq(jiffies, the_time));
+	while (time_before_eq(jiffies, the_time))
+		cpu_relax();
 }
 
 /*-- forward reference --*/
 
-/*******************************************************************
-	Use memeory refresh time        ~ 15us * 2
-********************************************************************/
-void tul_se2_wait(void)
-{
-#if 1
-	udelay(30);
-#else
-	UCHAR readByte;
-
-	readByte = TUL_RD(0, 0x61);
-	if ((readByte & 0x10) == 0x10) {
-		for (;;) {
-			readByte = TUL_RD(0, 0x61);
-			if ((readByte & 0x10) == 0x10)
-				break;
-		}
-		for (;;) {
-			readByte = TUL_RD(0, 0x61);
-			if ((readByte & 0x10) != 0x10)
-				break;
-		}
-	} else {
-		for (;;) {
-			readByte = TUL_RD(0, 0x61);
-			if ((readByte & 0x10) == 0x10)
-				break;
-		}
-		for (;;) {
-			readByte = TUL_RD(0, 0x61);
-			if ((readByte & 0x10) != 0x10)
-				break;
-		}
-	}
-#endif
-}
-
-
 /******************************************************************
  Input: instruction for  Serial E2PROM
 
@@ -379,1174 +294,1019 @@
 
 
 ******************************************************************/
-static void tul_se2_instr(WORD CurBase, UCHAR instr)
+
+/**
+ *	initio_se2_instr	-	bitbang an instruction
+ *	@base: Base of InitIO controller
+ *	@instr: Instruction for serial E2PROM
+ *
+ *	Bitbang an instruction out to the serial E2Prom
+ */
+
+static void initio_se2_instr(unsigned long base, u8 instr)
 {
 	int i;
-	UCHAR b;
+	u8 b;
 
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);	/* cs+start bit */
-	tul_se2_wait();
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO);	/* +CLK */
-	tul_se2_wait();
+	outb(SE2CS | SE2DO, base + TUL_NVRAM);		/* cs+start bit */
+	udelay(30);
+	outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM);	/* +CLK */
+	udelay(30);
 
 	for (i = 0; i < 8; i++) {
 		if (instr & 0x80)
-			b = SE2CS | SE2DO;	/* -CLK+dataBit */
+			b = SE2CS | SE2DO;		/* -CLK+dataBit */
 		else
-			b = SE2CS;	/* -CLK */
-		TUL_WR(CurBase + TUL_NVRAM, b);
-		tul_se2_wait();
-		TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK);	/* +CLK */
-		tul_se2_wait();
+			b = SE2CS;			/* -CLK */
+		outb(b, base + TUL_NVRAM);
+		udelay(30);
+		outb(b | SE2CLK, base + TUL_NVRAM);	/* +CLK */
+		udelay(30);
 		instr <<= 1;
 	}
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
-	tul_se2_wait();
-	return;
+	outb(SE2CS, base + TUL_NVRAM);			/* -CLK */
+	udelay(30);
 }
 
 
-/******************************************************************
- Function name  : tul_se2_ew_en
- Description    : Enable erase/write state of serial EEPROM
-******************************************************************/
-void tul_se2_ew_en(WORD CurBase)
+/**
+ *	initio_se2_ew_en	-	Enable erase/write
+ *	@base: Base address of InitIO controller
+ *
+ *	Enable erase/write state of serial EEPROM
+ */
+void initio_se2_ew_en(unsigned long base)
 {
-	tul_se2_instr(CurBase, 0x30);	/* EWEN */
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
-	tul_se2_wait();
-	return;
+	initio_se2_instr(base, 0x30);	/* EWEN */
+	outb(0, base + TUL_NVRAM);	/* -CS  */
+	udelay(30);
 }
 
 
-/************************************************************************
- Disable erase/write state of serial EEPROM
-*************************************************************************/
-void tul_se2_ew_ds(WORD CurBase)
+/**
+ *	initio_se2_ew_ds	-	Disable erase/write
+ *	@base: Base address of InitIO controller
+ *
+ *	Disable erase/write state of serial EEPROM
+ */
+void initio_se2_ew_ds(unsigned long base)
 {
-	tul_se2_instr(CurBase, 0);	/* EWDS */
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
-	tul_se2_wait();
-	return;
+	initio_se2_instr(base, 0);	/* EWDS */
+	outb(0, base + TUL_NVRAM);	/* -CS  */
+	udelay(30);
 }
 
 
-/******************************************************************
-	Input  :address of Serial E2PROM
-	Output :value stored in  Serial E2PROM
-*******************************************************************/
-static USHORT tul_se2_rd(WORD CurBase, ULONG adr)
+/**
+ *	initio_se2_rd		-	read E2PROM word
+ *	@base: Base of InitIO controller
+ *	@addr: Address of word in E2PROM
+ *
+ *	Read a word from the NV E2PROM device
+ */
+static u16 initio_se2_rd(unsigned long base, u8 addr)
 {
-	UCHAR instr, readByte;
-	USHORT readWord;
+	u8 instr, rb;
+	u16 val = 0;
 	int i;
 
-	instr = (UCHAR) (adr | 0x80);
-	tul_se2_instr(CurBase, instr);	/* READ INSTR */
-	readWord = 0;
+	instr = (u8) (addr | 0x80);
+	initio_se2_instr(base, instr);	/* READ INSTR */
 
 	for (i = 15; i >= 0; i--) {
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
-		tul_se2_wait();
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
+		outb(SE2CS | SE2CLK, base + TUL_NVRAM);	/* +CLK */
+		udelay(30);
+		outb(SE2CS, base + TUL_NVRAM);		/* -CLK */
 
 		/* sample data after the following edge of clock  */
-		readByte = TUL_RD(CurBase, TUL_NVRAM);
-		readByte &= SE2DI;
-		readWord += (readByte << i);
-		tul_se2_wait();	/* 6/20/95 */
+		rb = inb(base + TUL_NVRAM);
+		rb &= SE2DI;
+		val += (rb << i);
+		udelay(30);	/* 6/20/95 */
 	}
 
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* no chip select */
-	tul_se2_wait();
-	return readWord;
+	outb(0, base + TUL_NVRAM);		/* no chip select */
+	udelay(30);
+	return val;
 }
 
-
-/******************************************************************
- Input: new value in  Serial E2PROM, address of Serial E2PROM
-*******************************************************************/
-static void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
+/**
+ *	initio_se2_wr		-	read E2PROM word
+ *	@base: Base of InitIO controller
+ *	@addr: Address of word in E2PROM
+ *	@val: Value to write
+ *
+ *	Write a word to the NV E2PROM device. Used when recovering from
+ *	a problem with the NV.
+ */
+static void initio_se2_wr(unsigned long base, u8 addr, u16 val)
 {
-	UCHAR readByte;
-	UCHAR instr;
+	u8 rb;
+	u8 instr;
 	int i;
 
-	instr = (UCHAR) (adr | 0x40);
-	tul_se2_instr(CurBase, instr);	/* WRITE INSTR */
+	instr = (u8) (addr | 0x40);
+	initio_se2_instr(base, instr);	/* WRITE INSTR */
 	for (i = 15; i >= 0; i--) {
-		if (writeWord & 0x8000)
-			TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);	/* -CLK+dataBit 1 */
+		if (val & 0x8000)
+			outb(SE2CS | SE2DO, base + TUL_NVRAM);	/* -CLK+dataBit 1 */
 		else
-			TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK+dataBit 0 */
-		tul_se2_wait();
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
-		tul_se2_wait();
-		writeWord <<= 1;
+			outb(SE2CS, base + TUL_NVRAM);		/* -CLK+dataBit 0 */
+		udelay(30);
+		outb(SE2CS | SE2CLK, base + TUL_NVRAM);		/* +CLK */
+		udelay(30);
+		val <<= 1;
 	}
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
-	tul_se2_wait();
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
-	tul_se2_wait();
+	outb(SE2CS, base + TUL_NVRAM);				/* -CLK */
+	udelay(30);
+	outb(0, base + TUL_NVRAM);				/* -CS  */
+	udelay(30);
 
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* +CS  */
-	tul_se2_wait();
+	outb(SE2CS, base + TUL_NVRAM);				/* +CS  */
+	udelay(30);
 
 	for (;;) {
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
-		tul_se2_wait();
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
-		tul_se2_wait();
-		if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI)
+		outb(SE2CS | SE2CLK, base + TUL_NVRAM);		/* +CLK */
+		udelay(30);
+		outb(SE2CS, base + TUL_NVRAM);			/* -CLK */
+		udelay(30);
+		if ((rb = inb(base + TUL_NVRAM)) & SE2DI)
 			break;	/* write complete */
 	}
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS */
-	return;
+	outb(0, base + TUL_NVRAM);				/* -CS */
 }
 
+/**
+ *	initio_se2_rd_all	-	read hostadapter NV configuration
+ *	@base: Base address of InitIO controller
+ *
+ *	Reads the E2PROM data into main memory. Ensures that the checksum
+ *	and header marker are valid. Returns 1 on success -1 on error.
+ */
 
-/***********************************************************************
- Read SCSI H/A configuration parameters from serial EEPROM
-************************************************************************/
-int tul_se2_rd_all(WORD CurBase)
+static int initio_se2_rd_all(unsigned long base)
 {
 	int i;
-	ULONG chksum = 0;
-	USHORT *np;
+	u16 chksum = 0;
+	u16 *np;
 
 	i91unvramp = &i91unvram;
-	np = (USHORT *) i91unvramp;
-	for (i = 0; i < 32; i++) {
-		*np++ = tul_se2_rd(CurBase, i);
-	}
+	np = (u16 *) i91unvramp;
+	for (i = 0; i < 32; i++)
+		*np++ = initio_se2_rd(base, i);
 
-/*--------------------Is signature "ini" ok ? ----------------*/
+	/* Is signature "ini" ok ? */
 	if (i91unvramp->NVM_Signature != INI_SIGNATURE)
 		return -1;
-/*---------------------- Is ckecksum ok ? ----------------------*/
-	np = (USHORT *) i91unvramp;
+	/* Is ckecksum ok ? */
+	np = (u16 *) i91unvramp;
 	for (i = 0; i < 31; i++)
 		chksum += *np++;
-	if (i91unvramp->NVM_CheckSum != (USHORT) chksum)
+	if (i91unvramp->NVM_CheckSum != chksum)
 		return -1;
 	return 1;
 }
 
-
-/***********************************************************************
- Update SCSI H/A configuration parameters from serial EEPROM
-************************************************************************/
-void tul_se2_update_all(WORD CurBase)
+/**
+ *	initio_se2_update_all		-	Update E2PROM
+ *	@base: Base of InitIO controller
+ *
+ *	Update the E2PROM by wrting any changes into the E2PROM
+ *	chip, rewriting the checksum.
+ */
+static void initio_se2_update_all(unsigned long base)
 {				/* setup default pattern */
 	int i;
-	ULONG chksum = 0;
-	USHORT *np, *np1;
+	u16 chksum = 0;
+	u16 *np, *np1;
 
 	i91unvramp = &i91unvram;
 	/* Calculate checksum first */
-	np = (USHORT *) i91udftNvRam;
+	np = (u16 *) i91udftNvRam;
 	for (i = 0; i < 31; i++)
 		chksum += *np++;
-	*np = (USHORT) chksum;
-	tul_se2_ew_en(CurBase);	/* Enable write  */
+	*np = chksum;
+	initio_se2_ew_en(base);	/* Enable write  */
 
-	np = (USHORT *) i91udftNvRam;
-	np1 = (USHORT *) i91unvramp;
+	np = (u16 *) i91udftNvRam;
+	np1 = (u16 *) i91unvramp;
 	for (i = 0; i < 32; i++, np++, np1++) {
-		if (*np != *np1) {
-			tul_se2_wr(CurBase, i, *np);
-		}
+		if (*np != *np1)
+			initio_se2_wr(base, i, *np);
 	}
-
-	tul_se2_ew_ds(CurBase);	/* Disable write   */
-	return;
+	initio_se2_ew_ds(base);	/* Disable write   */
 }
 
-/*************************************************************************
- Function name  : read_eeprom
-**************************************************************************/
-void tul_read_eeprom(WORD CurBase)
+/**
+ *	initio_read_eeprom		-	Retrieve configuration
+ *	@base: Base of InitIO Host Adapter
+ *
+ *	Retrieve the host adapter configuration data from E2Prom. If the
+ *	data is invalid then the defaults are used and are also restored
+ *	into the E2PROM. This forms the access point for the SCSI driver
+ *	into the E2PROM layer, the other functions for the E2PROM are all
+ *	internal use.
+ *
+ *	Must be called single threaded, uses a shared global area.
+ */
+
+static void initio_read_eeprom(unsigned long base)
 {
-	UCHAR gctrl;
+	u8 gctrl;
 
 	i91unvramp = &i91unvram;
-/*------Enable EEProm programming ---*/
-	gctrl = TUL_RD(CurBase, TUL_GCTRL);
-	TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT);
-	if (tul_se2_rd_all(CurBase) != 1) {
-		tul_se2_update_all(CurBase);	/* setup default pattern */
-		tul_se2_rd_all(CurBase);	/* load again  */
+	/* Enable EEProm programming */
+	gctrl = inb(base + TUL_GCTRL);
+	outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
+	if (initio_se2_rd_all(base) != 1) {
+		initio_se2_update_all(base);	/* setup default pattern */
+		initio_se2_rd_all(base);	/* load again  */
 	}
-/*------ Disable EEProm programming ---*/
-	gctrl = TUL_RD(CurBase, TUL_GCTRL);
-	TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
-}				/* read_eeprom */
-
-static int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
-				      BYTE bBus, BYTE bDevice)
-{
-	int i, j;
-
-	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
-		if (i91u_adpt[i].ADPT_BIOS < wBIOS)
-			continue;
-		if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
-			if (i91u_adpt[i].ADPT_BASE == wBASE) {
-				if (i91u_adpt[i].ADPT_Bus != 0xFF)
-					return 1;
-			} else if (i91u_adpt[i].ADPT_BASE < wBASE)
-					continue;
-		}
-		for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
-			i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE;
-			i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR;
-			i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS;
-			i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus;
-			i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device;
-		}
-		i91u_adpt[i].ADPT_BASE = wBASE;
-		i91u_adpt[i].ADPT_INTR = bInterrupt;
-		i91u_adpt[i].ADPT_BIOS = wBIOS;
-		i91u_adpt[i].ADPT_Bus = bBus;
-		i91u_adpt[i].ADPT_Device = bDevice;
-		return 0;
-	}
-	return 1;
+	/* Disable EEProm programming */
+	gctrl = inb(base + TUL_GCTRL);
+	outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
 }
 
-static void init_i91uAdapter_table(void)
-{
-	int i;
+/**
+ *	initio_stop_bm		-	stop bus master
+ *	@host: InitIO we are stopping
+ *
+ *	Stop any pending DMA operation, aborting the DMA if neccessary
+ */
 
-	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {	/* Initialize adapter structure */
-		i91u_adpt[i].ADPT_BIOS = 0xffff;
-		i91u_adpt[i].ADPT_BASE = 0xffff;
-		i91u_adpt[i].ADPT_INTR = 0xff;
-		i91u_adpt[i].ADPT_Bus = 0xff;
-		i91u_adpt[i].ADPT_Device = 0xff;
-	}
-	return;
-}
-
-static void tul_stop_bm(HCS * pCurHcb)
+static void initio_stop_bm(struct initio_host * host)
 {
 
-	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+	if (inb(host->addr + TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
+		outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
 		/* wait Abort DMA xfer done */
-		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+		while ((inb(host->addr + TUL_Int) & XABT) == 0)
+			cpu_relax();
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 }
 
-/***************************************************************************/
-static void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
-{
-	pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE;	/* Supply base address  */
-	pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS;	/* Supply BIOS address  */
-	pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR;	/* Supply interrupt line */
-	return;
-}
+/**
+ *	initio_reset_scsi		-	Reset SCSI host controller
+ *	@host: InitIO host to reset
+ *	@seconds: Recovery time
+ *
+ *	Perform a full reset of the SCSI subsystem.
+ */
 
-/***************************************************************************/
-static int tul_reset_scsi(HCS * pCurHcb, int seconds)
+static int initio_reset_scsi(struct initio_host * host, int seconds)
 {
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
+	outb(TSC_RST_BUS, host->addr + TUL_SCtrl0);
 
-	while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
+	while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT))
+		cpu_relax();
+
 	/* reset tulip chip */
-
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
+	outb(0, host->addr + TUL_SSignal);
 
 	/* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
 	/* SONY 5200 tape drive won't work if only stall for 1 sec */
-	tul_do_pause(seconds * HZ);
+	/* FIXME: this is a very long busy wait right now */
+	initio_do_pause(seconds * HZ);
 
-	TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-
-	return (SCSI_RESET_SUCCESS);
+	inb(host->addr + TUL_SInt);
+	return SCSI_RESET_SUCCESS;
 }
 
-/***************************************************************************/
-static int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb,
-		      BYTE * pbBiosAdr, int seconds)
+/**
+ *	initio_init		-	set up an InitIO host adapter
+ *	@host: InitIO host adapter
+ *	@num_scbs: Number of SCBS
+ *	@bios_addr: BIOS address
+ *
+ *	Set up the host adapter and devices according to the configuration
+ *	retrieved from the E2PROM.
+ *
+ *	Locking: Calls E2PROM layer code which is not re-enterable so must
+ *	run single threaded for now.
+ */
+
+static void initio_init(struct initio_host * host, u8 *bios_addr)
 {
 	int i;
-	BYTE *pwFlags;
-	BYTE *pbHeads;
-	SCB *pTmpScb, *pPrevScb = NULL;
+	u8 *flags;
+	u8 *heads;
 
-	pCurHcb->HCS_NumScbs = tul_num_scb;
-	pCurHcb->HCS_Semaph = 1;
-	spin_lock_init(&pCurHcb->HCS_SemaphLock);
-	pCurHcb->HCS_JSStatus0 = 0;
-	pCurHcb->HCS_Scb = scbp;
-	pCurHcb->HCS_NxtPend = scbp;
-	pCurHcb->HCS_NxtAvail = scbp;
-	for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) {
-		pTmpScb->SCB_TagId = i;
-		if (i != 0)
-			pPrevScb->SCB_NxtScb = pTmpScb;
-		pPrevScb = pTmpScb;
-	}
-	pPrevScb->SCB_NxtScb = NULL;
-	pCurHcb->HCS_ScbEnd = pTmpScb;
-	pCurHcb->HCS_FirstAvail = scbp;
-	pCurHcb->HCS_LastAvail = pPrevScb;
-	spin_lock_init(&pCurHcb->HCS_AvailLock);
-	pCurHcb->HCS_FirstPend = NULL;
-	pCurHcb->HCS_LastPend = NULL;
-	pCurHcb->HCS_FirstBusy = NULL;
-	pCurHcb->HCS_LastBusy = NULL;
-	pCurHcb->HCS_FirstDone = NULL;
-	pCurHcb->HCS_LastDone = NULL;
-	pCurHcb->HCS_ActScb = NULL;
-	pCurHcb->HCS_ActTcs = NULL;
-
-	tul_read_eeprom(pCurHcb->HCS_Base);
-/*---------- get H/A configuration -------------*/
+	/* Get E2Prom configuration */
+	initio_read_eeprom(host->addr);
 	if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
-		pCurHcb->HCS_MaxTar = 8;
+		host->max_tar = 8;
 	else
-		pCurHcb->HCS_MaxTar = 16;
+		host->max_tar = 16;
 
-	pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
+	host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
 
-	pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
-	pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);
+	host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
+	host->idmask = ~(1 << host->scsi_id);
 
 #ifdef CHK_PARITY
 	/* Enable parity error response */
-	TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);
+	outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD);
 #endif
 
 	/* Mask all the interrupt       */
-	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+	outb(0x1F, host->addr + TUL_Mask);
 
-	tul_stop_bm(pCurHcb);
+	initio_stop_bm(host);
 	/* --- Initialize the tulip --- */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP);
+	outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0);
 
 	/* program HBA's SCSI ID        */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4);
+	outb(host->scsi_id << 4, host->addr + TUL_SScsiId);
 
 	/* Enable Initiator Mode ,phase latch,alternate sync period mode,
 	   disable SCSI reset */
-	if (pCurHcb->HCS_Config & HCC_EN_PAR)
-		pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
+	if (host->config & HCC_EN_PAR)
+		host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
 	else
-		pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1);
+		host->sconf1 = (TSC_INITDEFAULT);
+	outb(host->sconf1, host->addr + TUL_SConfig);
 
-	/* Enable HW reselect           */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
+	/* Enable HW reselect */
+	outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0);
+	outb(0, host->addr + TUL_SPeriod);
 
 	/* selection time out = 250 ms */
-	TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);
+	outb(153, host->addr + TUL_STimeOut);
 
-/*--------- Enable SCSI terminator -----*/
-	TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)));
-	TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1,
-	       ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE));
+	/* Enable SCSI terminator */
+	outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)),
+		host->addr + TUL_XCtrl);
+	outb(((host->config & HCC_AUTO_TERM) >> 4) |
+		(inb(host->addr + TUL_GCTRL1) & 0xFE),
+		host->addr + TUL_GCTRL1);
 
 	for (i = 0,
-	     pwFlags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
-	     pbHeads = pbBiosAdr + 0x180;
-	     i < pCurHcb->HCS_MaxTar;
-	     i++, pwFlags++) {
-		pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-		if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255)
-			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+	     flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
+	     heads = bios_addr + 0x180;
+	     i < host->max_tar;
+	     i++, flags++) {
+		host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+		if (host->targets[i].flags & TCF_EN_255)
+			host->targets[i].drv_flags = TCF_DRV_255_63;
 		else
-			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
-		pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0;
-		pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1;
-		pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++;
-		if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255)
-			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+			host->targets[i].drv_flags = 0;
+		host->targets[i].js_period = 0;
+		host->targets[i].sconfig0 = host->sconf1;
+		host->targets[i].heads = *heads++;
+		if (host->targets[i].heads == 255)
+			host->targets[i].drv_flags = TCF_DRV_255_63;
 		else
-			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
-		pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++;
-		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
-		pCurHcb->HCS_ActTags[i] = 0;
-		pCurHcb->HCS_MaxTags[i] = 0xFF;
+			host->targets[i].drv_flags = 0;
+		host->targets[i].sectors = *heads++;
+		host->targets[i].flags &= ~TCF_BUSY;
+		host->act_tags[i] = 0;
+		host->max_tags[i] = 0xFF;
 	}			/* for                          */
 	printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
-	       pCurHcb->HCS_Base, pCurHcb->HCS_Intr,
-	       pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);
-/*------------------- reset SCSI Bus ---------------------------*/
-	if (pCurHcb->HCS_Config & HCC_SCSI_RESET) {
-		printk("i91u: Reset SCSI Bus ... \n");
-		tul_reset_scsi(pCurHcb, seconds);
+	       host->addr, host->irq,
+	       host->bios_addr, host->scsi_id);
+	/* Reset SCSI Bus */
+	if (host->config & HCC_SCSI_RESET) {
+		printk(KERN_INFO "i91u: Reset SCSI Bus ... \n");
+		initio_reset_scsi(host, 10);
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9);
-	return (0);
+	outb(0x17, host->addr + TUL_SCFG1);
+	outb(0xE9, host->addr + TUL_SIntEnable);
 }
 
-/***************************************************************************/
-static SCB *tul_alloc_scb(HCS * hcsp)
+/**
+ *	initio_alloc_scb		-	Allocate an SCB
+ *	@host: InitIO host we are allocating for
+ *
+ *	Walk the SCB list for the controller and allocate a free SCB if
+ *	one exists.
+ */
+static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host)
 {
-	SCB *pTmpScb;
-	ULONG flags;
-	spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
-	if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {
+	struct scsi_ctrl_blk *scb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->avail_lock, flags);
+	if ((scb = host->first_avail) != NULL) {
 #if DEBUG_QUEUE
-		printk("find scb at %08lx\n", (ULONG) pTmpScb);
+		printk("find scb at %p\n", scb);
 #endif
-		if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL)
-			hcsp->HCS_LastAvail = NULL;
-		pTmpScb->SCB_NxtScb = NULL;
-		pTmpScb->SCB_Status = SCB_RENT;
+		if ((host->first_avail = scb->next) == NULL)
+			host->last_avail = NULL;
+		scb->next = NULL;
+		scb->status = SCB_RENT;
 	}
-	spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
-	return (pTmpScb);
+	spin_unlock_irqrestore(&host->avail_lock, flags);
+	return scb;
 }
 
-/***************************************************************************/
-static void tul_release_scb(HCS * hcsp, SCB * scbp)
+/**
+ *	initio_release_scb		-	Release an SCB
+ *	@host: InitIO host that owns the SCB
+ *	@cmnd: SCB command block being returned
+ *
+ *	Return an allocated SCB to the host free list
+ */
+
+static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd)
 {
-	ULONG flags;
+	unsigned long flags;
 
 #if DEBUG_QUEUE
-	printk("Release SCB %lx; ", (ULONG) scbp);
+	printk("Release SCB %p; ", cmnd);
 #endif
-	spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
-	scbp->SCB_Srb = NULL;
-	scbp->SCB_Status = 0;
-	scbp->SCB_NxtScb = NULL;
-	if (hcsp->HCS_LastAvail != NULL) {
-		hcsp->HCS_LastAvail->SCB_NxtScb = scbp;
-		hcsp->HCS_LastAvail = scbp;
+	spin_lock_irqsave(&(host->avail_lock), flags);
+	cmnd->srb = NULL;
+	cmnd->status = 0;
+	cmnd->next = NULL;
+	if (host->last_avail != NULL) {
+		host->last_avail->next = cmnd;
+		host->last_avail = cmnd;
 	} else {
-		hcsp->HCS_FirstAvail = scbp;
-		hcsp->HCS_LastAvail = scbp;
+		host->first_avail = cmnd;
+		host->last_avail = cmnd;
 	}
-	spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
+	spin_unlock_irqrestore(&(host->avail_lock), flags);
 }
 
 /***************************************************************************/
-static void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
+static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
 {
 
 #if DEBUG_QUEUE
-	printk("Append pend SCB %lx; ", (ULONG) scbp);
+	printk("Append pend SCB %p; ", scbp);
 #endif
-	scbp->SCB_Status = SCB_PEND;
-	scbp->SCB_NxtScb = NULL;
-	if (pCurHcb->HCS_LastPend != NULL) {
-		pCurHcb->HCS_LastPend->SCB_NxtScb = scbp;
-		pCurHcb->HCS_LastPend = scbp;
+	scbp->status = SCB_PEND;
+	scbp->next = NULL;
+	if (host->last_pending != NULL) {
+		host->last_pending->next = scbp;
+		host->last_pending = scbp;
 	} else {
-		pCurHcb->HCS_FirstPend = scbp;
-		pCurHcb->HCS_LastPend = scbp;
+		host->first_pending = scbp;
+		host->last_pending = scbp;
 	}
 }
 
 /***************************************************************************/
-static void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
+static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
 {
 
 #if DEBUG_QUEUE
-	printk("Push pend SCB %lx; ", (ULONG) scbp);
+	printk("Push pend SCB %p; ", scbp);
 #endif
-	scbp->SCB_Status = SCB_PEND;
-	if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) {
-		pCurHcb->HCS_FirstPend = scbp;
+	scbp->status = SCB_PEND;
+	if ((scbp->next = host->first_pending) != NULL) {
+		host->first_pending = scbp;
 	} else {
-		pCurHcb->HCS_FirstPend = scbp;
-		pCurHcb->HCS_LastPend = scbp;
+		host->first_pending = scbp;
+		host->last_pending = scbp;
 	}
 }
 
-/***************************************************************************/
-static SCB *tul_find_first_pend_scb(HCS * pCurHcb)
+static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host)
 {
-	SCB *pFirstPend;
+	struct scsi_ctrl_blk *first;
 
 
-	pFirstPend = pCurHcb->HCS_FirstPend;
-	while (pFirstPend != NULL) {
-		if (pFirstPend->SCB_Opcode != ExecSCSI) {
-			return (pFirstPend);
-		}
-		if (pFirstPend->SCB_TagMsg == 0) {
-			if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) &&
-			    !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
-				return (pFirstPend);
-			}
+	first = host->first_pending;
+	while (first != NULL) {
+		if (first->opcode != ExecSCSI)
+			return first;
+		if (first->tagmsg == 0) {
+			if ((host->act_tags[first->target] == 0) &&
+			    !(host->targets[first->target].flags & TCF_BUSY))
+				return first;
 		} else {
-			if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >=
-			  pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) |
-			    (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
-				pFirstPend = pFirstPend->SCB_NxtScb;
+			if ((host->act_tags[first->target] >=
+			  host->max_tags[first->target]) |
+			    (host->targets[first->target].flags & TCF_BUSY)) {
+				first = first->next;
 				continue;
 			}
-			return (pFirstPend);
+			return first;
 		}
-		pFirstPend = pFirstPend->SCB_NxtScb;
+		first = first->next;
 	}
-
-
-	return (pFirstPend);
+	return first;
 }
-/***************************************************************************/
-static void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
+
+static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
-	SCB *pTmpScb, *pPrevScb;
+	struct scsi_ctrl_blk *tmp, *prev;
 
 #if DEBUG_QUEUE
-	printk("unlink pend SCB %lx; ", (ULONG) pCurScb);
+	printk("unlink pend SCB %p; ", scb);
 #endif
 
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
-	while (pTmpScb != NULL) {
-		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */
-			if (pTmpScb == pCurHcb->HCS_FirstPend) {
-				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
-					pCurHcb->HCS_LastPend = NULL;
+	prev = tmp = host->first_pending;
+	while (tmp != NULL) {
+		if (scb == tmp) {	/* Unlink this SCB              */
+			if (tmp == host->first_pending) {
+				if ((host->first_pending = tmp->next) == NULL)
+					host->last_pending = NULL;
 			} else {
-				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-				if (pTmpScb == pCurHcb->HCS_LastPend)
-					pCurHcb->HCS_LastPend = pPrevScb;
+				prev->next = tmp->next;
+				if (tmp == host->last_pending)
+					host->last_pending = prev;
 			}
-			pTmpScb->SCB_NxtScb = NULL;
+			tmp->next = NULL;
 			break;
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
-	return;
 }
-/***************************************************************************/
-static void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
+
+static void initio_append_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
 {
 
 #if DEBUG_QUEUE
-	printk("append busy SCB %lx; ", (ULONG) scbp);
+	printk("append busy SCB %o; ", scbp);
 #endif
-	if (scbp->SCB_TagMsg)
-		pCurHcb->HCS_ActTags[scbp->SCB_Target]++;
+	if (scbp->tagmsg)
+		host->act_tags[scbp->target]++;
 	else
-		pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY;
-	scbp->SCB_Status = SCB_BUSY;
-	scbp->SCB_NxtScb = NULL;
-	if (pCurHcb->HCS_LastBusy != NULL) {
-		pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp;
-		pCurHcb->HCS_LastBusy = scbp;
+		host->targets[scbp->target].flags |= TCF_BUSY;
+	scbp->status = SCB_BUSY;
+	scbp->next = NULL;
+	if (host->last_busy != NULL) {
+		host->last_busy->next = scbp;
+		host->last_busy = scbp;
 	} else {
-		pCurHcb->HCS_FirstBusy = scbp;
-		pCurHcb->HCS_LastBusy = scbp;
+		host->first_busy = scbp;
+		host->last_busy = scbp;
 	}
 }
 
 /***************************************************************************/
-static SCB *tul_pop_busy_scb(HCS * pCurHcb)
+static struct scsi_ctrl_blk *initio_pop_busy_scb(struct initio_host * host)
 {
-	SCB *pTmpScb;
+	struct scsi_ctrl_blk *tmp;
 
 
-	if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) {
-		if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
-			pCurHcb->HCS_LastBusy = NULL;
-		pTmpScb->SCB_NxtScb = NULL;
-		if (pTmpScb->SCB_TagMsg)
-			pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+	if ((tmp = host->first_busy) != NULL) {
+		if ((host->first_busy = tmp->next) == NULL)
+			host->last_busy = NULL;
+		tmp->next = NULL;
+		if (tmp->tagmsg)
+			host->act_tags[tmp->target]--;
 		else
-			pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+			host->targets[tmp->target].flags &= ~TCF_BUSY;
 	}
 #if DEBUG_QUEUE
-	printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);
+	printk("Pop busy SCB %p; ", tmp);
 #endif
-	return (pTmpScb);
+	return tmp;
 }
 
 /***************************************************************************/
-static void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
+static void initio_unlink_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
-	SCB *pTmpScb, *pPrevScb;
+	struct scsi_ctrl_blk *tmp, *prev;
 
 #if DEBUG_QUEUE
-	printk("unlink busy SCB %lx; ", (ULONG) pCurScb);
+	printk("unlink busy SCB %p; ", scb);
 #endif
 
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
-	while (pTmpScb != NULL) {
-		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */
-			if (pTmpScb == pCurHcb->HCS_FirstBusy) {
-				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
-					pCurHcb->HCS_LastBusy = NULL;
+	prev = tmp = host->first_busy;
+	while (tmp != NULL) {
+		if (scb == tmp) {	/* Unlink this SCB              */
+			if (tmp == host->first_busy) {
+				if ((host->first_busy = tmp->next) == NULL)
+					host->last_busy = NULL;
 			} else {
-				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-				if (pTmpScb == pCurHcb->HCS_LastBusy)
-					pCurHcb->HCS_LastBusy = pPrevScb;
+				prev->next = tmp->next;
+				if (tmp == host->last_busy)
+					host->last_busy = prev;
 			}
-			pTmpScb->SCB_NxtScb = NULL;
-			if (pTmpScb->SCB_TagMsg)
-				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+			tmp->next = NULL;
+			if (tmp->tagmsg)
+				host->act_tags[tmp->target]--;
 			else
-				pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+				host->targets[tmp->target].flags &= ~TCF_BUSY;
 			break;
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
 	return;
 }
 
-/***************************************************************************/
-SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
+struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun)
 {
-	SCB *pTmpScb, *pPrevScb;
-	WORD scbp_tarlun;
+	struct scsi_ctrl_blk *tmp, *prev;
+	u16 scbp_tarlun;
 
 
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
-	while (pTmpScb != NULL) {
-		scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);
+	prev = tmp = host->first_busy;
+	while (tmp != NULL) {
+		scbp_tarlun = (tmp->lun << 8) | (tmp->target);
 		if (scbp_tarlun == tarlun) {	/* Unlink this SCB              */
 			break;
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
 #if DEBUG_QUEUE
-	printk("find busy SCB %lx; ", (ULONG) pTmpScb);
+	printk("find busy SCB %p; ", tmp);
 #endif
-	return (pTmpScb);
+	return tmp;
 }
 
-/***************************************************************************/
-static void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
+static void initio_append_done_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
 {
-
 #if DEBUG_QUEUE
-	printk("append done SCB %lx; ", (ULONG) scbp);
+	printk("append done SCB %p; ", scbp);
 #endif
 
-	scbp->SCB_Status = SCB_DONE;
-	scbp->SCB_NxtScb = NULL;
-	if (pCurHcb->HCS_LastDone != NULL) {
-		pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;
-		pCurHcb->HCS_LastDone = scbp;
+	scbp->status = SCB_DONE;
+	scbp->next = NULL;
+	if (host->last_done != NULL) {
+		host->last_done->next = scbp;
+		host->last_done = scbp;
 	} else {
-		pCurHcb->HCS_FirstDone = scbp;
-		pCurHcb->HCS_LastDone = scbp;
+		host->first_done = scbp;
+		host->last_done = scbp;
 	}
 }
 
-/***************************************************************************/
-SCB *tul_find_done_scb(HCS * pCurHcb)
+struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host)
 {
-	SCB *pTmpScb;
+	struct scsi_ctrl_blk *tmp;
 
-
-	if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {
-		if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)
-			pCurHcb->HCS_LastDone = NULL;
-		pTmpScb->SCB_NxtScb = NULL;
+	if ((tmp = host->first_done) != NULL) {
+		if ((host->first_done = tmp->next) == NULL)
+			host->last_done = NULL;
+		tmp->next = NULL;
 	}
 #if DEBUG_QUEUE
-	printk("find done SCB %lx; ", (ULONG) pTmpScb);
+	printk("find done SCB %p; ",tmp);
 #endif
-	return (pTmpScb);
+	return tmp;
 }
 
-/***************************************************************************/
-static int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
+static int initio_abort_srb(struct initio_host * host, struct scsi_cmnd *srbp)
 {
-	ULONG flags;
-	SCB *pTmpScb, *pPrevScb;
+	unsigned long flags;
+	struct scsi_ctrl_blk *tmp, *prev;
 
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+	spin_lock_irqsave(&host->semaph_lock, flags);
 
-	if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+	if ((host->semaph == 0) && (host->active == NULL)) {
 		/* disable Jasmin SCSI Int        */
-
-                spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-		tulip_main(pCurHcb);
-
-        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-		pCurHcb->HCS_Semaph = 1;
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-
-		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
+		outb(0x1F, host->addr + TUL_Mask);
+		spin_unlock_irqrestore(&host->semaph_lock, flags);
+		/* FIXME: synchronize_irq needed ? */
+		tulip_main(host);
+		spin_lock_irqsave(&host->semaph_lock, flags);
+		host->semaph = 1;
+		outb(0x0F, host->addr + TUL_Mask);
+		spin_unlock_irqrestore(&host->semaph_lock, flags);
 		return SCSI_ABORT_SNOOZE;
 	}
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;	/* Check Pend queue */
-	while (pTmpScb != NULL) {
+	prev = tmp = host->first_pending;	/* Check Pend queue */
+	while (tmp != NULL) {
 		/* 07/27/98 */
-		if (pTmpScb->SCB_Srb == srbp) {
-			if (pTmpScb == pCurHcb->HCS_ActScb) {
-				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+		if (tmp->srb == srbp) {
+			if (tmp == host->active) {
+				spin_unlock_irqrestore(&host->semaph_lock, flags);
 				return SCSI_ABORT_BUSY;
-			} else if (pTmpScb == pCurHcb->HCS_FirstPend) {
-				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
-					pCurHcb->HCS_LastPend = NULL;
+			} else if (tmp == host->first_pending) {
+				if ((host->first_pending = tmp->next) == NULL)
+					host->last_pending = NULL;
 			} else {
-				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-				if (pTmpScb == pCurHcb->HCS_LastPend)
-					pCurHcb->HCS_LastPend = pPrevScb;
+				prev->next = tmp->next;
+				if (tmp == host->last_pending)
+					host->last_pending = prev;
 			}
-			pTmpScb->SCB_HaStat = HOST_ABORTED;
-			pTmpScb->SCB_Flags |= SCF_DONE;
-			if (pTmpScb->SCB_Flags & SCF_POST)
-				(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
-			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+			tmp->hastat = HOST_ABORTED;
+			tmp->flags |= SCF_DONE;
+			if (tmp->flags & SCF_POST)
+				(*tmp->post) ((u8 *) host, (u8 *) tmp);
+			spin_unlock_irqrestore(&host->semaph_lock, flags);
 			return SCSI_ABORT_SUCCESS;
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
 
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
-	while (pTmpScb != NULL) {
-
-		if (pTmpScb->SCB_Srb == srbp) {
-
-			if (pTmpScb == pCurHcb->HCS_ActScb) {
-				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+	prev = tmp = host->first_busy;	/* Check Busy queue */
+	while (tmp != NULL) {
+		if (tmp->srb == srbp) {
+			if (tmp == host->active) {
+				spin_unlock_irqrestore(&host->semaph_lock, flags);
 				return SCSI_ABORT_BUSY;
-			} else if (pTmpScb->SCB_TagMsg == 0) {
-				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+			} else if (tmp->tagmsg == 0) {
+				spin_unlock_irqrestore(&host->semaph_lock, flags);
 				return SCSI_ABORT_BUSY;
 			} else {
-				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
-				if (pTmpScb == pCurHcb->HCS_FirstBusy) {
-					if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
-						pCurHcb->HCS_LastBusy = NULL;
+				host->act_tags[tmp->target]--;
+				if (tmp == host->first_busy) {
+					if ((host->first_busy = tmp->next) == NULL)
+						host->last_busy = NULL;
 				} else {
-					pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-					if (pTmpScb == pCurHcb->HCS_LastBusy)
-						pCurHcb->HCS_LastBusy = pPrevScb;
+					prev->next = tmp->next;
+					if (tmp == host->last_busy)
+						host->last_busy = prev;
 				}
-				pTmpScb->SCB_NxtScb = NULL;
+				tmp->next = NULL;
 
 
-				pTmpScb->SCB_HaStat = HOST_ABORTED;
-				pTmpScb->SCB_Flags |= SCF_DONE;
-				if (pTmpScb->SCB_Flags & SCF_POST)
-					(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
-				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+				tmp->hastat = HOST_ABORTED;
+				tmp->flags |= SCF_DONE;
+				if (tmp->flags & SCF_POST)
+					(*tmp->post) ((u8 *) host, (u8 *) tmp);
+				spin_unlock_irqrestore(&host->semaph_lock, flags);
 				return SCSI_ABORT_SUCCESS;
 			}
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-	return (SCSI_ABORT_NOT_RUNNING);
+	spin_unlock_irqrestore(&host->semaph_lock, flags);
+	return SCSI_ABORT_NOT_RUNNING;
 }
 
 /***************************************************************************/
-static int tul_bad_seq(HCS * pCurHcb)
+static int initio_bad_seq(struct initio_host * host)
 {
-	SCB *pCurScb;
+	struct scsi_ctrl_blk *scb;
 
-	printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);
+	printk("initio_bad_seg c=%d\n", host->index);
 
-	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
-		tul_unlink_busy_scb(pCurHcb, pCurScb);
-		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-		pCurScb->SCB_TaStat = 0;
-		tul_append_done_scb(pCurHcb, pCurScb);
+	if ((scb = host->active) != NULL) {
+		initio_unlink_busy_scb(host, scb);
+		scb->hastat = HOST_BAD_PHAS;
+		scb->tastat = 0;
+		initio_append_done_scb(host, scb);
 	}
-	tul_stop_bm(pCurHcb);
-
-	tul_reset_scsi(pCurHcb, 8);	/* 7/29/98 */
-
-	return (tul_post_scsi_rst(pCurHcb));
+	initio_stop_bm(host);
+	initio_reset_scsi(host, 8);	/* 7/29/98 */
+	return initio_post_scsi_rst(host);
 }
 
-#if 0
 
 /************************************************************************/
-static int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
-			    unsigned int target, unsigned int ResetFlags)
+static void initio_exec_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
-	ULONG flags;
-	SCB *pScb;
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+	unsigned long flags;
 
-	if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {
+	scb->mode = 0;
 
-		if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-			/* disable Jasmin SCSI Int        */
+	scb->sgidx = 0;
+	scb->sgmax = scb->sglen;
 
-        		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+	spin_lock_irqsave(&host->semaph_lock, flags);
 
-			tulip_main(pCurHcb);
-
-        		spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-			pCurHcb->HCS_Semaph = 1;
-			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-
-			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-			return SCSI_RESET_SNOOZE;
-		}
-		pScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
-		while (pScb != NULL) {
-			if (pScb->SCB_Srb == pSrb)
-				break;
-			pScb = pScb->SCB_NxtScb;
-		}
-		if (pScb == NULL) {
-			printk("Unable to Reset - No SCB Found\n");
-
-			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-			return SCSI_RESET_NOT_RUNNING;
-		}
-	}
-	if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {
-		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-		return SCSI_RESET_NOT_RUNNING;
-	}
-	pScb->SCB_Opcode = BusDevRst;
-	pScb->SCB_Flags = SCF_POST;
-	pScb->SCB_Target = target;
-	pScb->SCB_Mode = 0;
-
-	pScb->SCB_Srb = NULL;
-	if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
-		pScb->SCB_Srb = pSrb;
-	}
-	tul_push_pend_scb(pCurHcb, pScb);	/* push this SCB to Pending queue */
-
-	if (pCurHcb->HCS_Semaph == 1) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-		/* disable Jasmin SCSI Int        */
-		pCurHcb->HCS_Semaph = 0;
-
-        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-		tulip_main(pCurHcb);
-
-                spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-		pCurHcb->HCS_Semaph = 1;
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-	}
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-	return SCSI_RESET_PENDING;
-}
-
-static int tul_reset_scsi_bus(HCS * pCurHcb)
-{
-	ULONG flags;
-
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-	pCurHcb->HCS_Semaph = 0;
-
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-	tul_stop_bm(pCurHcb);
-
-	tul_reset_scsi(pCurHcb, 2);	/* 7/29/98 */
-
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-	tul_post_scsi_rst(pCurHcb);
-
-        spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-	tulip_main(pCurHcb);
-
-        spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-	pCurHcb->HCS_Semaph = 1;
-	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-	return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
-}
-
-#endif  /*  0  */
-
-/************************************************************************/
-static void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
-{
-	ULONG flags;
-
-	pCurScb->SCB_Mode = 0;
-
-	pCurScb->SCB_SGIdx = 0;
-	pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;
-
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-	tul_append_pend_scb(pCurHcb, pCurScb);	/* Append this SCB to Pending queue */
+	initio_append_pend_scb(host, scb);	/* Append this SCB to Pending queue */
 
 /* VVVVV 07/21/98 */
-	if (pCurHcb->HCS_Semaph == 1) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-		/* disable Jasmin SCSI Int        */
-		pCurHcb->HCS_Semaph = 0;
+	if (host->semaph == 1) {
+		/* Disable Jasmin SCSI Int */
+		outb(0x1F, host->addr + TUL_Mask);
+		host->semaph = 0;
+		spin_unlock_irqrestore(&host->semaph_lock, flags);
 
-        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+		tulip_main(host);
 
-		tulip_main(pCurHcb);
-
-        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-		pCurHcb->HCS_Semaph = 1;
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+		spin_lock_irqsave(&host->semaph_lock, flags);
+		host->semaph = 1;
+		outb(0x0F, host->addr + TUL_Mask);
 	}
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+	spin_unlock_irqrestore(&host->semaph_lock, flags);
 	return;
 }
 
 /***************************************************************************/
-static int tul_isr(HCS * pCurHcb)
+static int initio_isr(struct initio_host * host)
 {
-	/* Enter critical section       */
-
-	if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {
-		if (pCurHcb->HCS_Semaph == 1) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+	if (inb(host->addr + TUL_Int) & TSS_INT_PENDING) {
+		if (host->semaph == 1) {
+			outb(0x1F, host->addr + TUL_Mask);
 			/* Disable Tulip SCSI Int */
-			pCurHcb->HCS_Semaph = 0;
+			host->semaph = 0;
 
-			tulip_main(pCurHcb);
+			tulip_main(host);
 
-			pCurHcb->HCS_Semaph = 1;
-			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-			return (1);
+			host->semaph = 1;
+			outb(0x0F, host->addr + TUL_Mask);
+			return 1;
 		}
 	}
-	return (0);
+	return 0;
 }
 
-/***************************************************************************/
-int tulip_main(HCS * pCurHcb)
+static int tulip_main(struct initio_host * host)
 {
-	SCB *pCurScb;
+	struct scsi_ctrl_blk *scb;
 
 	for (;;) {
+		tulip_scsi(host);	/* Call tulip_scsi              */
 
-		tulip_scsi(pCurHcb);	/* Call tulip_scsi              */
-
-		while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) {	/* find done entry */
-			if (pCurScb->SCB_TaStat == INI_QUEUE_FULL) {
-				pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =
-				    pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;
-				pCurScb->SCB_TaStat = 0;
-				tul_append_pend_scb(pCurHcb, pCurScb);
+		/* Walk the list of completed SCBs */
+		while ((scb = initio_find_done_scb(host)) != NULL) {	/* find done entry */
+			if (scb->tastat == INI_QUEUE_FULL) {
+				host->max_tags[scb->target] =
+				    host->act_tags[scb->target] - 1;
+				scb->tastat = 0;
+				initio_append_pend_scb(host, scb);
 				continue;
 			}
-			if (!(pCurScb->SCB_Mode & SCM_RSENS)) {		/* not in auto req. sense mode */
-				if (pCurScb->SCB_TaStat == 2) {
+			if (!(scb->mode & SCM_RSENS)) {		/* not in auto req. sense mode */
+				if (scb->tastat == 2) {
 
 					/* clr sync. nego flag */
 
-					if (pCurScb->SCB_Flags & SCF_SENSE) {
-						BYTE len;
-						len = pCurScb->SCB_SenseLen;
+					if (scb->flags & SCF_SENSE) {
+						u8 len;
+						len = scb->senselen;
 						if (len == 0)
 							len = 1;
-						pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;
-						pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;
-						pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR);	/* for xfer_data_in */
-/*                      pCurScb->SCB_Flags |= SCF_NO_DCHK;      */
-						/* so, we won't report worng direction in xfer_data_in,
+						scb->buflen = scb->senselen;
+						scb->bufptr = scb->senseptr;
+						scb->flags &= ~(SCF_SG | SCF_DIR);	/* for xfer_data_in */
+						/* so, we won't report wrong direction in xfer_data_in,
 						   and won't report HOST_DO_DU in state_6 */
-						pCurScb->SCB_Mode = SCM_RSENS;
-						pCurScb->SCB_Ident &= 0xBF;	/* Disable Disconnect */
-						pCurScb->SCB_TagMsg = 0;
-						pCurScb->SCB_TaStat = 0;
-						pCurScb->SCB_CDBLen = 6;
-						pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;
-						pCurScb->SCB_CDB[1] = 0;
-						pCurScb->SCB_CDB[2] = 0;
-						pCurScb->SCB_CDB[3] = 0;
-						pCurScb->SCB_CDB[4] = len;
-						pCurScb->SCB_CDB[5] = 0;
-						tul_push_pend_scb(pCurHcb, pCurScb);
+						scb->mode = SCM_RSENS;
+						scb->ident &= 0xBF;	/* Disable Disconnect */
+						scb->tagmsg = 0;
+						scb->tastat = 0;
+						scb->cdblen = 6;
+						scb->cdb[0] = SCSICMD_RequestSense;
+						scb->cdb[1] = 0;
+						scb->cdb[2] = 0;
+						scb->cdb[3] = 0;
+						scb->cdb[4] = len;
+						scb->cdb[5] = 0;
+						initio_push_pend_scb(host, scb);
 						break;
 					}
 				}
 			} else {	/* in request sense mode */
 
-				if (pCurScb->SCB_TaStat == 2) {		/* check contition status again after sending
+				if (scb->tastat == 2) {		/* check contition status again after sending
 									   requset sense cmd 0x3 */
-					pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+					scb->hastat = HOST_BAD_PHAS;
 				}
-				pCurScb->SCB_TaStat = 2;
+				scb->tastat = 2;
 			}
-			pCurScb->SCB_Flags |= SCF_DONE;
-			if (pCurScb->SCB_Flags & SCF_POST) {
-				(*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);
+			scb->flags |= SCF_DONE;
+			if (scb->flags & SCF_POST) {
+				/* FIXME: only one post method and lose casts */
+				(*scb->post) ((u8 *) host, (u8 *) scb);
 			}
 		}		/* while */
-
 		/* find_active: */
-		if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)
+		if (inb(host->addr + TUL_SStatus0) & TSS_INT_PENDING)
 			continue;
-
-		if (pCurHcb->HCS_ActScb) {	/* return to OS and wait for xfer_done_ISR/Selected_ISR */
+		if (host->active)	/* return to OS and wait for xfer_done_ISR/Selected_ISR */
 			return 1;	/* return to OS, enable interrupt */
-		}
 		/* Check pending SCB            */
-		if (tul_find_first_pend_scb(pCurHcb) == NULL) {
+		if (initio_find_first_pend_scb(host) == NULL)
 			return 1;	/* return to OS, enable interrupt */
-		}
 	}			/* End of for loop */
 	/* statement won't reach here */
 }
 
-
-
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/***************************************************************************/
-/***************************************************************************/
-/***************************************************************************/
-/***************************************************************************/
-
-/***************************************************************************/
-void tulip_scsi(HCS * pCurHcb)
+static void tulip_scsi(struct initio_host * host)
 {
-	SCB *pCurScb;
-	TCS *pCurTcb;
+	struct scsi_ctrl_blk *scb;
+	struct target_control *active_tc;
 
 	/* make sure to service interrupt asap */
-
-	if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) {
-
-		pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
-		pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
-		pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-		if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* SCSI bus reset detected      */
-			int_tul_scsi_rst(pCurHcb);
+	if ((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING) {
+		host->phase = host->jsstatus0 & TSS_PH_MASK;
+		host->jsstatus1 = inb(host->addr + TUL_SStatus1);
+		host->jsint = inb(host->addr + TUL_SInt);
+		if (host->jsint & TSS_SCSIRST_INT) {	/* SCSI bus reset detected      */
+			int_initio_scsi_rst(host);
 			return;
 		}
-		if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {	/* if selected/reselected interrupt */
-			if (int_tul_resel(pCurHcb) == 0)
-				tul_next_state(pCurHcb);
+		if (host->jsint & TSS_RESEL_INT) {	/* if selected/reselected interrupt */
+			if (int_initio_resel(host) == 0)
+				initio_next_state(host);
 			return;
 		}
-		if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
-			int_tul_busfree(pCurHcb);
+		if (host->jsint & TSS_SEL_TIMEOUT) {
+			int_initio_busfree(host);
 			return;
 		}
-		if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
-			int_tul_busfree(pCurHcb);	/* unexpected bus free or sel timeout */
+		if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection            */
+			int_initio_busfree(host);	/* unexpected bus free or sel timeout */
 			return;
 		}
-		if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {	/* func complete or Bus service */
-			if ((pCurScb = pCurHcb->HCS_ActScb) != NULL)
-				tul_next_state(pCurHcb);
+		if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) {	/* func complete or Bus service */
+			if ((scb = host->active) != NULL)
+				initio_next_state(host);
 			return;
 		}
 	}
-	if (pCurHcb->HCS_ActScb != NULL)
+	if (host->active != NULL)
 		return;
 
-	if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL)
+	if ((scb = initio_find_first_pend_scb(host)) == NULL)
 		return;
 
 	/* program HBA's SCSI ID & target SCSI ID */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId,
-	     (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F));
-	if (pCurScb->SCB_Opcode == ExecSCSI) {
-		pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+	outb((host->scsi_id << 4) | (scb->target & 0x0F),
+		host->addr + TUL_SScsiId);
+	if (scb->opcode == ExecSCSI) {
+		active_tc = &host->targets[scb->target];
 
-		if (pCurScb->SCB_TagMsg)
-			pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG;
+		if (scb->tagmsg)
+			active_tc->drv_flags |= TCF_DRV_EN_TAG;
 		else
-			pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG;
+			active_tc->drv_flags &= ~TCF_DRV_EN_TAG;
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
-		if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {	/* do wdtr negotiation          */
-			tul_select_atn_stop(pCurHcb, pCurScb);
+		outb(active_tc->js_period, host->addr + TUL_SPeriod);
+		if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {	/* do wdtr negotiation          */
+			initio_select_atn_stop(host, scb);
 		} else {
-			if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync negotiation          */
-				tul_select_atn_stop(pCurHcb, pCurScb);
+			if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync negotiation          */
+				initio_select_atn_stop(host, scb);
 			} else {
-				if (pCurScb->SCB_TagMsg)
-					tul_select_atn3(pCurHcb, pCurScb);
+				if (scb->tagmsg)
+					initio_select_atn3(host, scb);
 				else
-					tul_select_atn(pCurHcb, pCurScb);
+					initio_select_atn(host, scb);
 			}
 		}
-		if (pCurScb->SCB_Flags & SCF_POLL) {
-			while (wait_tulip(pCurHcb) != -1) {
-				if (tul_next_state(pCurHcb) == -1)
+		if (scb->flags & SCF_POLL) {
+			while (wait_tulip(host) != -1) {
+				if (initio_next_state(host) == -1)
 					break;
 			}
 		}
-	} else if (pCurScb->SCB_Opcode == BusDevRst) {
-		tul_select_atn_stop(pCurHcb, pCurScb);
-		pCurScb->SCB_NxtStat = 8;
-		if (pCurScb->SCB_Flags & SCF_POLL) {
-			while (wait_tulip(pCurHcb) != -1) {
-				if (tul_next_state(pCurHcb) == -1)
+	} else if (scb->opcode == BusDevRst) {
+		initio_select_atn_stop(host, scb);
+		scb->next_state = 8;
+		if (scb->flags & SCF_POLL) {
+			while (wait_tulip(host) != -1) {
+				if (initio_next_state(host) == -1)
 					break;
 			}
 		}
-	} else if (pCurScb->SCB_Opcode == AbortCmd) {
-		if (tul_abort_srb(pCurHcb, pCurScb->SCB_Srb) != 0) {
-
-
-			tul_unlink_pend_scb(pCurHcb, pCurScb);
-
-			tul_release_scb(pCurHcb, pCurScb);
+	} else if (scb->opcode == AbortCmd) {
+		if (initio_abort_srb(host, scb->srb) != 0) {
+			initio_unlink_pend_scb(host, scb);
+			initio_release_scb(host, scb);
 		} else {
-			pCurScb->SCB_Opcode = BusDevRst;
-			tul_select_atn_stop(pCurHcb, pCurScb);
-			pCurScb->SCB_NxtStat = 8;
+			scb->opcode = BusDevRst;
+			initio_select_atn_stop(host, scb);
+			scb->next_state = 8;
 		}
-
-/* 08/03/98 */
 	} else {
-		tul_unlink_pend_scb(pCurHcb, pCurScb);
-		pCurScb->SCB_HaStat = 0x16;	/* bad command */
-		tul_append_done_scb(pCurHcb, pCurScb);
+		initio_unlink_pend_scb(host, scb);
+		scb->hastat = 0x16;	/* bad command */
+		initio_append_done_scb(host, scb);
 	}
 	return;
 }
 
+/**
+ *	initio_next_state		-	Next SCSI state
+ *	@host: InitIO host we are processing
+ *
+ *	Progress the active command block along the state machine
+ *	until we hit a state which we must wait for activity to occur.
+ *
+ *	Returns zero or a negative code.
+ */
 
-/***************************************************************************/
-int tul_next_state(HCS * pCurHcb)
+static int initio_next_state(struct initio_host * host)
 {
 	int next;
 
-	next = pCurHcb->HCS_ActScb->SCB_NxtStat;
+	next = host->active->next_state;
 	for (;;) {
 		switch (next) {
 		case 1:
-			next = tul_state_1(pCurHcb);
+			next = initio_state_1(host);
 			break;
 		case 2:
-			next = tul_state_2(pCurHcb);
+			next = initio_state_2(host);
 			break;
 		case 3:
-			next = tul_state_3(pCurHcb);
+			next = initio_state_3(host);
 			break;
 		case 4:
-			next = tul_state_4(pCurHcb);
+			next = initio_state_4(host);
 			break;
 		case 5:
-			next = tul_state_5(pCurHcb);
+			next = initio_state_5(host);
 			break;
 		case 6:
-			next = tul_state_6(pCurHcb);
+			next = initio_state_6(host);
 			break;
 		case 7:
-			next = tul_state_7(pCurHcb);
+			next = initio_state_7(host);
 			break;
 		case 8:
-			return (tul_bus_device_reset(pCurHcb));
+			return initio_bus_device_reset(host);
 		default:
-			return (tul_bad_seq(pCurHcb));
+			return initio_bad_seq(host);
 		}
 		if (next <= 0)
 			return next;
@@ -1554,338 +1314,363 @@
 }
 
 
-/***************************************************************************/
-/* sTate after selection with attention & stop */
-int tul_state_1(HCS * pCurHcb)
+/**
+ *	initio_state_1		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ *	Perform SCSI state processing for Select/Attention/Stop
+ */
+
+static int initio_state_1(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 #if DEBUG_STATE
 	printk("-s1-");
 #endif
 
-	tul_unlink_pend_scb(pCurHcb, pCurScb);
-	tul_append_busy_scb(pCurHcb, pCurScb);
+	/* Move the SCB from pending to busy */
+	initio_unlink_pend_scb(host, scb);
+	initio_append_busy_scb(host, scb);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+	outb(active_tc->sconfig0, host->addr + TUL_SConfig );
 	/* ATN on */
-	if (pCurHcb->HCS_Phase == MSG_OUT) {
+	if (host->phase == MSG_OUT) {
+		outb(TSC_EN_BUS_IN | TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
+		outb(scb->ident, host->addr + TUL_SFifo);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT));
-
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
-
-		if (pCurScb->SCB_TagMsg) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
+		if (scb->tagmsg) {
+			outb(scb->tagmsg, host->addr + TUL_SFifo);
+			outb(scb->tagid, host->addr + TUL_SFifo);
 		}
-		if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
-
-			pCurTcb->TCS_Flags |= TCF_WDTR_DONE;
-
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);	/* Extended msg length */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* Sync request */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* Start from 16 bits */
-		} else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
-
-			pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
-
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* extended msg length */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* sync request */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);	/* REQ/ACK offset */
+		if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
+			active_tc->flags |= TCF_WDTR_DONE;
+			outb(MSG_EXTEND, host->addr + TUL_SFifo);
+			outb(2, host->addr + TUL_SFifo);	/* Extended msg length */
+			outb(3, host->addr + TUL_SFifo);	/* Sync request */
+			outb(1, host->addr + TUL_SFifo);	/* Start from 16 bits */
+		} else if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
+			active_tc->flags |= TCF_SYNC_DONE;
+			outb(MSG_EXTEND, host->addr + TUL_SFifo);
+			outb(3, host->addr + TUL_SFifo);	/* extended msg length */
+			outb(1, host->addr + TUL_SFifo);	/* sync request */
+			outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
+			outb(MAX_OFFSET, host->addr + TUL_SFifo);	/* REQ/ACK offset */
 		}
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		if (wait_tulip(pCurHcb) == -1)
-			return (-1);
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
-	return (3);
+	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+	outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
+	/* Into before CDB xfer */
+	return 3;
 }
 
 
-/***************************************************************************/
-/* state after selection with attention */
-/* state after selection with attention3 */
-int tul_state_2(HCS * pCurHcb)
+/**
+ *	initio_state_2		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ * state after selection with attention
+ * state after selection with attention3
+ */
+
+static int initio_state_2(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 #if DEBUG_STATE
 	printk("-s2-");
 #endif
 
-	tul_unlink_pend_scb(pCurHcb, pCurScb);
-	tul_append_busy_scb(pCurHcb, pCurScb);
+	initio_unlink_pend_scb(host, scb);
+	initio_append_busy_scb(host, scb);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+	outb(active_tc->sconfig0, host->addr + TUL_SConfig);
 
-	if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) {
-		return (4);
-	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
-	return (3);
+	if (host->jsstatus1 & TSS_CMD_PH_CMP)
+		return 4;
+
+	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+	outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
+	/* Into before CDB xfer */
+	return 3;
 }
 
-/***************************************************************************/
-/* state before CDB xfer is done */
-int tul_state_3(HCS * pCurHcb)
+/**
+ *	initio_state_3		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ * state before CDB xfer is done
+ */
+
+static int initio_state_3(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 	int i;
 
 #if DEBUG_STATE
 	printk("-s3-");
 #endif
 	for (;;) {
-		switch (pCurHcb->HCS_Phase) {
+		switch (host->phase) {
 		case CMD_OUT:	/* Command out phase            */
-			for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-			if (wait_tulip(pCurHcb) == -1)
-				return (-1);
-			if (pCurHcb->HCS_Phase == CMD_OUT) {
-				return (tul_bad_seq(pCurHcb));
-			}
-			return (4);
+			for (i = 0; i < (int) scb->cdblen; i++)
+				outb(scb->cdb[i], host->addr + TUL_SFifo);
+			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+			if (wait_tulip(host) == -1)
+				return -1;
+			if (host->phase == CMD_OUT)
+				return initio_bad_seq(host);
+			return 4;
 
 		case MSG_IN:	/* Message in phase             */
-			pCurScb->SCB_NxtStat = 3;
-			if (tul_msgin(pCurHcb) == -1)
-				return (-1);
+			scb->next_state = 3;
+			if (initio_msgin(host) == -1)
+				return -1;
 			break;
 
 		case STATUS_IN:	/* Status phase                 */
-			if (tul_status_msg(pCurHcb) == -1)
-				return (-1);
+			if (initio_status_msg(host) == -1)
+				return -1;
 			break;
 
 		case MSG_OUT:	/* Message out phase            */
-			if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
-
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-				if (wait_tulip(pCurHcb) == -1)
-					return (-1);
-
+			if (active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
+				outb(MSG_NOP, host->addr + TUL_SFifo);		/* msg nop */
+				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+				if (wait_tulip(host) == -1)
+					return -1;
 			} else {
-				pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
+				active_tc->flags |= TCF_SYNC_DONE;
 
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* ext. msg len */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* sync request */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);	/* REQ/ACK offset */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-				if (wait_tulip(pCurHcb) == -1)
-					return (-1);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7));
+				outb(MSG_EXTEND, host->addr + TUL_SFifo);
+				outb(3, host->addr + TUL_SFifo);	/* ext. msg len */
+				outb(1, host->addr + TUL_SFifo);	/* sync request */
+				outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
+				outb(MAX_OFFSET, host->addr + TUL_SFifo);	/* REQ/ACK offset */
+				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+				if (wait_tulip(host) == -1)
+					return -1;
+				outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+				outb(inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7), host->addr + TUL_SSignal);
 
 			}
 			break;
-
 		default:
-			return (tul_bad_seq(pCurHcb));
+			return initio_bad_seq(host);
 		}
 	}
 }
 
+/**
+ *	initio_state_4		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ *	SCSI state machine. State 4
+ */
 
-/***************************************************************************/
-int tul_state_4(HCS * pCurHcb)
+static int initio_state_4(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
 #if DEBUG_STATE
 	printk("-s4-");
 #endif
-	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) {
-		return (6);	/* Go to state 6                */
+	if ((scb->flags & SCF_DIR) == SCF_NO_XF) {
+		return 6;	/* Go to state 6 (After data) */
 	}
 	for (;;) {
-		if (pCurScb->SCB_BufLen == 0)
-			return (6);	/* Go to state 6                */
+		if (scb->buflen == 0)
+			return 6;
 
-		switch (pCurHcb->HCS_Phase) {
+		switch (host->phase) {
 
 		case STATUS_IN:	/* Status phase                 */
-			if ((pCurScb->SCB_Flags & SCF_DIR) != 0) {	/* if direction bit set then report data underrun */
-				pCurScb->SCB_HaStat = HOST_DO_DU;
-			}
-			if ((tul_status_msg(pCurHcb)) == -1)
-				return (-1);
+			if ((scb->flags & SCF_DIR) != 0)	/* if direction bit set then report data underrun */
+				scb->hastat = HOST_DO_DU;
+			if ((initio_status_msg(host)) == -1)
+				return -1;
 			break;
 
 		case MSG_IN:	/* Message in phase             */
-			pCurScb->SCB_NxtStat = 0x4;
-			if (tul_msgin(pCurHcb) == -1)
-				return (-1);
+			scb->next_state = 0x4;
+			if (initio_msgin(host) == -1)
+				return -1;
 			break;
 
 		case MSG_OUT:	/* Message out phase            */
-			if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
-				pCurScb->SCB_BufLen = 0;
-				pCurScb->SCB_HaStat = HOST_DO_DU;
-				if (tul_msgout_ide(pCurHcb) == -1)
-					return (-1);
-				return (6);	/* Go to state 6                */
+			if (host->jsstatus0 & TSS_PAR_ERROR) {
+				scb->buflen = 0;
+				scb->hastat = HOST_DO_DU;
+				if (initio_msgout_ide(host) == -1)
+					return -1;
+				return 6;
 			} else {
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-				if (wait_tulip(pCurHcb) == -1)
-					return (-1);
+				outb(MSG_NOP, host->addr + TUL_SFifo);		/* msg nop */
+				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+				if (wait_tulip(host) == -1)
+					return -1;
 			}
 			break;
 
 		case DATA_IN:	/* Data in phase                */
-			return (tul_xfer_data_in(pCurHcb));
+			return initio_xfer_data_in(host);
 
 		case DATA_OUT:	/* Data out phase               */
-			return (tul_xfer_data_out(pCurHcb));
+			return initio_xfer_data_out(host);
 
 		default:
-			return (tul_bad_seq(pCurHcb));
+			return initio_bad_seq(host);
 		}
 	}
 }
 
 
-/***************************************************************************/
-/* state after dma xfer done or phase change before xfer done */
-int tul_state_5(HCS * pCurHcb)
+/**
+ *	initio_state_5		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ *	State after dma xfer done or phase change before xfer done
+ */
+
+static int initio_state_5(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 	long cnt, xcnt;		/* cannot use unsigned !! code: if (xcnt < 0) */
 
 #if DEBUG_STATE
 	printk("-s5-");
 #endif
-/*------ get remaining count -------*/
+	/*------ get remaining count -------*/
+	cnt = inl(host->addr + TUL_SCnt0) & 0x0FFFFFF;
 
-	cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF;
-
-	if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) {
+	if (inb(host->addr + TUL_XCmd) & 0x20) {
 		/* ----------------------- DATA_IN ----------------------------- */
 		/* check scsi parity error */
-		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
-			pCurScb->SCB_HaStat = HOST_DO_DU;
-		}
-		if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* DMA xfer pending, Send STOP  */
+		if (host->jsstatus0 & TSS_PAR_ERROR)
+			scb->hastat = HOST_DO_DU;
+		if (inb(host->addr + TUL_XStatus) & XPEND) {	/* DMA xfer pending, Send STOP  */
 			/* tell Hardware  scsi xfer has been terminated */
-			TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80);
+			outb(inb(host->addr + TUL_XCtrl) | 0x80, host->addr + TUL_XCtrl);
 			/* wait until DMA xfer not pending */
-			while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND);
+			while (inb(host->addr + TUL_XStatus) & XPEND)
+				cpu_relax();
 		}
 	} else {
-/*-------- DATA OUT -----------*/
-		if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) {
-			if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI)
-				cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1;
+		/*-------- DATA OUT -----------*/
+		if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) {
+			if (host->active_tc->js_period & TSC_WIDE_SCSI)
+				cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F) << 1;
 			else
-				cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F);
+				cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F);
 		}
-		if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
-			TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT);
+		if (inb(host->addr + TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
+			outb(TAX_X_ABT, host->addr + TUL_XCmd);
 			/* wait Abort DMA xfer done */
-			while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+			while ((inb(host->addr + TUL_Int) & XABT) == 0)
+				cpu_relax();
 		}
-		if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-			if (wait_tulip(pCurHcb) == -1) {
-				return (-1);
-			}
+		if ((cnt == 1) && (host->phase == DATA_OUT)) {
+			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+			if (wait_tulip(host) == -1)
+				return -1;
 			cnt = 0;
 		} else {
-			if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0)
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+			if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0)
+				outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 		}
 	}
-
 	if (cnt == 0) {
-		pCurScb->SCB_BufLen = 0;
-		return (6);	/* Go to state 6                */
+		scb->buflen = 0;
+		return 6;	/* After Data */
 	}
 	/* Update active data pointer */
-	xcnt = (long) pCurScb->SCB_BufLen - cnt;	/* xcnt== bytes already xferred */
-	pCurScb->SCB_BufLen = (U32) cnt;	/* cnt == bytes left to be xferred */
-	if (pCurScb->SCB_Flags & SCF_SG) {
-		register SG *sgp;
-		ULONG i;
+	xcnt = (long) scb->buflen - cnt;	/* xcnt== bytes already xferred */
+	scb->buflen = (u32) cnt;		/* cnt == bytes left to be xferred */
+	if (scb->flags & SCF_SG) {
+		struct sg_entry *sgp;
+		unsigned long i;
 
-		sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx];
-		for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) {
-			xcnt -= (long) sgp->SG_Len;
+		sgp = &scb->sglist[scb->sgidx];
+		for (i = scb->sgidx; i < scb->sgmax; sgp++, i++) {
+			xcnt -= (long) sgp->len;
 			if (xcnt < 0) {		/* this sgp xfer half done */
-				xcnt += (long) sgp->SG_Len;	/* xcnt == bytes xferred in this sgp */
-				sgp->SG_Ptr += (U32) xcnt;	/* new ptr to be xfer */
-				sgp->SG_Len -= (U32) xcnt;	/* new len to be xfer */
-				pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);
+				xcnt += (long) sgp->len;	/* xcnt == bytes xferred in this sgp */
+				sgp->data += (u32) xcnt;	/* new ptr to be xfer */
+				sgp->len -= (u32) xcnt;	/* new len to be xfer */
+				scb->bufptr += ((u32) (i - scb->sgidx) << 3);
 				/* new SG table ptr */
-				pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);
+				scb->sglen = (u8) (scb->sgmax - i);
 				/* new SG table len */
-				pCurScb->SCB_SGIdx = (WORD) i;
+				scb->sgidx = (u16) i;
 				/* for next disc and come in this loop */
-				return (4);	/* Go to state 4                */
+				return 4;	/* Go to state 4                */
 			}
 			/* else (xcnt >= 0 , i.e. this sgp already xferred */
 		}		/* for */
-		return (6);	/* Go to state 6                */
+		return 6;	/* Go to state 6                */
 	} else {
-		pCurScb->SCB_BufPtr += (U32) xcnt;
+		scb->bufptr += (u32) xcnt;
 	}
-	return (4);		/* Go to state 4                */
+	return 4;		/* Go to state 4                */
 }
 
-/***************************************************************************/
-/* state after Data phase */
-int tul_state_6(HCS * pCurHcb)
+/**
+ *	initio_state_6		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ *	State after Data phase
+ */
+
+static int initio_state_6(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
 #if DEBUG_STATE
 	printk("-s6-");
 #endif
 	for (;;) {
-		switch (pCurHcb->HCS_Phase) {
+		switch (host->phase) {
 		case STATUS_IN:	/* Status phase                 */
-			if ((tul_status_msg(pCurHcb)) == -1)
-				return (-1);
+			if ((initio_status_msg(host)) == -1)
+				return -1;
 			break;
 
 		case MSG_IN:	/* Message in phase             */
-			pCurScb->SCB_NxtStat = 6;
-			if ((tul_msgin(pCurHcb)) == -1)
-				return (-1);
+			scb->next_state = 6;
+			if ((initio_msgin(host)) == -1)
+				return -1;
 			break;
 
 		case MSG_OUT:	/* Message out phase            */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-			if (wait_tulip(pCurHcb) == -1)
-				return (-1);
+			outb(MSG_NOP, host->addr + TUL_SFifo);		/* msg nop */
+			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+			if (wait_tulip(host) == -1)
+				return -1;
 			break;
 
 		case DATA_IN:	/* Data in phase                */
-			return (tul_xpad_in(pCurHcb));
+			return initio_xpad_in(host);
 
 		case DATA_OUT:	/* Data out phase               */
-			return (tul_xpad_out(pCurHcb));
+			return initio_xpad_out(host);
 
 		default:
-			return (tul_bad_seq(pCurHcb));
+			return initio_bad_seq(host);
 		}
 	}
 }
 
-/***************************************************************************/
-int tul_state_7(HCS * pCurHcb)
+/**
+ *	initio_state_7		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ */
+
+int initio_state_7(struct initio_host * host)
 {
 	int cnt, i;
 
@@ -1893,1139 +1678,1029 @@
 	printk("-s7-");
 #endif
 	/* flush SCSI FIFO */
-	cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;
+	cnt = inb(host->addr + TUL_SFifoCnt) & 0x1F;
 	if (cnt) {
 		for (i = 0; i < cnt; i++)
-			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+			inb(host->addr + TUL_SFifo);
 	}
-	switch (pCurHcb->HCS_Phase) {
+	switch (host->phase) {
 	case DATA_IN:		/* Data in phase                */
 	case DATA_OUT:		/* Data out phase               */
-		return (tul_bad_seq(pCurHcb));
+		return initio_bad_seq(host);
 	default:
-		return (6);	/* Go to state 6                */
+		return 6;	/* Go to state 6                */
 	}
 }
 
-/***************************************************************************/
-int tul_xfer_data_in(HCS * pCurHcb)
+/**
+ *	initio_xfer_data_in	-	Commence data input
+ *	@host: InitIO host in use
+ *
+ *	Commence a block of data transfer. The transfer itself will
+ *	be managed by the controller and we will get a completion (or
+ *	failure) interrupt.
+ */
+static int initio_xfer_data_in(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
-	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {
-		return (6);	/* wrong direction */
-	}
-	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
+	if ((scb->flags & SCF_DIR) == SCF_DOUT)
+		return 6;	/* wrong direction */
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN);	/* 7/25/95 */
+	outl(scb->buflen, host->addr + TUL_SCnt0);
+	outb(TSC_XF_DMA_IN, host->addr + TUL_SCmd);	/* 7/25/95 */
 
-	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);
+	if (scb->flags & SCF_SG) {	/* S/G xfer */
+		outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
+		outl(scb->bufptr, host->addr + TUL_XAddH);
+		outb(TAX_SG_IN, host->addr + TUL_XCmd);
 	} else {
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);
+		outl(scb->buflen, host->addr + TUL_XCntH);
+		outl(scb->bufptr, host->addr + TUL_XAddH);
+		outb(TAX_X_IN, host->addr + TUL_XCmd);
 	}
-	pCurScb->SCB_NxtStat = 0x5;
-	return (0);		/* return to OS, wait xfer done , let jas_isr come in */
+	scb->next_state = 0x5;
+	return 0;		/* return to OS, wait xfer done , let jas_isr come in */
 }
 
+/**
+ *	initio_xfer_data_out	-	Commence data output
+ *	@host: InitIO host in use
+ *
+ *	Commence a block of data transfer. The transfer itself will
+ *	be managed by the controller and we will get a completion (or
+ *	failure) interrupt.
+ */
 
-/***************************************************************************/
-int tul_xfer_data_out(HCS * pCurHcb)
+static int initio_xfer_data_out(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
-	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {
-		return (6);	/* wrong direction */
-	}
-	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);
+	if ((scb->flags & SCF_DIR) == SCF_DIN)
+		return 6;	/* wrong direction */
 
-	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);
+	outl(scb->buflen, host->addr + TUL_SCnt0);
+	outb(TSC_XF_DMA_OUT, host->addr + TUL_SCmd);
+
+	if (scb->flags & SCF_SG) {	/* S/G xfer */
+		outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
+		outl(scb->bufptr, host->addr + TUL_XAddH);
+		outb(TAX_SG_OUT, host->addr + TUL_XCmd);
 	} else {
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);
+		outl(scb->buflen, host->addr + TUL_XCntH);
+		outl(scb->bufptr, host->addr + TUL_XAddH);
+		outb(TAX_X_OUT, host->addr + TUL_XCmd);
 	}
 
-	pCurScb->SCB_NxtStat = 0x5;
-	return (0);		/* return to OS, wait xfer done , let jas_isr come in */
+	scb->next_state = 0x5;
+	return 0;		/* return to OS, wait xfer done , let jas_isr come in */
 }
 
-
-/***************************************************************************/
-int tul_xpad_in(HCS * pCurHcb)
+int initio_xpad_in(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 
-	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
-		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */
-	}
+	if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
+		scb->hastat = HOST_DO_DU;	/* over run             */
 	for (;;) {
-		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
-			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+		if (active_tc->js_period & TSC_WIDE_SCSI)
+			outl(2, host->addr + TUL_SCnt0);
 		else
-			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+			outl(1, host->addr + TUL_SCnt0);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if ((wait_tulip(pCurHcb)) == -1) {
-			return (-1);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
+		if (host->phase != DATA_IN) {
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+			return 6;
 		}
-		if (pCurHcb->HCS_Phase != DATA_IN) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-			return (6);
-		}
-		TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+		inb(host->addr + TUL_SFifo);
 	}
 }
 
-int tul_xpad_out(HCS * pCurHcb)
+int initio_xpad_out(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 
-	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
-		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */
-	}
+	if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
+		scb->hastat = HOST_DO_DU;	/* over run             */
 	for (;;) {
-		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
-			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+		if (active_tc->js_period & TSC_WIDE_SCSI)
+			outl(2, host->addr + TUL_SCnt0);
 		else
-			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+			outl(1, host->addr + TUL_SCnt0);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		if ((wait_tulip(pCurHcb)) == -1) {
-			return (-1);
-		}
-		if (pCurHcb->HCS_Phase != DATA_OUT) {	/* Disable wide CPU to allow read 16 bits */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-			return (6);
+		outb(0, host->addr + TUL_SFifo);
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		if ((wait_tulip(host)) == -1)
+			return -1;
+		if (host->phase != DATA_OUT) {	/* Disable wide CPU to allow read 16 bits */
+			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+			return 6;
 		}
 	}
 }
 
-
-/***************************************************************************/
-int tul_status_msg(HCS * pCurHcb)
+int initio_status_msg(struct initio_host * host)
 {				/* status & MSG_IN */
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	BYTE msg;
+	struct scsi_ctrl_blk *scb = host->active;
+	u8 msg;
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);
-	if ((wait_tulip(pCurHcb)) == -1) {
-		return (-1);
-	}
+	outb(TSC_CMD_COMP, host->addr + TUL_SCmd);
+	if (wait_tulip(host) == -1)
+		return -1;
+
 	/* get status */
-	pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+	scb->tastat = inb(host->addr + TUL_SFifo);
 
-	if (pCurHcb->HCS_Phase == MSG_OUT) {
-		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
-		} else {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
-		}
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		return (wait_tulip(pCurHcb));
+	if (host->phase == MSG_OUT) {
+		if (host->jsstatus0 & TSS_PAR_ERROR)
+			outb(MSG_PARITY, host->addr + TUL_SFifo);
+		else
+			outb(MSG_NOP, host->addr + TUL_SFifo);
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		return wait_tulip(host);
 	}
-	if (pCurHcb->HCS_Phase == MSG_IN) {
-		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
-		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {	/* Parity error                 */
-			if ((tul_msgin_accept(pCurHcb)) == -1)
-				return (-1);
-			if (pCurHcb->HCS_Phase != MSG_OUT)
-				return (tul_bad_seq(pCurHcb));
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-			return (wait_tulip(pCurHcb));
+	if (host->phase == MSG_IN) {
+		msg = inb(host->addr + TUL_SFifo);
+		if (host->jsstatus0 & TSS_PAR_ERROR) {	/* Parity error                 */
+			if ((initio_msgin_accept(host)) == -1)
+				return -1;
+			if (host->phase != MSG_OUT)
+				return initio_bad_seq(host);
+			outb(MSG_PARITY, host->addr + TUL_SFifo);
+			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+			return wait_tulip(host);
 		}
 		if (msg == 0) {	/* Command complete             */
 
-			if ((pCurScb->SCB_TaStat & 0x18) == 0x10) {	/* No link support              */
-				return (tul_bad_seq(pCurHcb));
-			}
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
-			return tul_wait_done_disc(pCurHcb);
+			if ((scb->tastat & 0x18) == 0x10)	/* No link support              */
+				return initio_bad_seq(host);
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+			return initio_wait_done_disc(host);
 
 		}
-		if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {
-			if ((pCurScb->SCB_TaStat & 0x18) == 0x10)
-				return (tul_msgin_accept(pCurHcb));
+		if (msg == MSG_LINK_COMP || msg == MSG_LINK_FLAG) {
+			if ((scb->tastat & 0x18) == 0x10)
+				return initio_msgin_accept(host);
 		}
 	}
-	return (tul_bad_seq(pCurHcb));
+	return initio_bad_seq(host);
 }
 
 
-/***************************************************************************/
 /* scsi bus free */
-int int_tul_busfree(HCS * pCurHcb)
+int int_initio_busfree(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
-	if (pCurScb != NULL) {
-		if (pCurScb->SCB_Status & SCB_SELECT) {		/* selection timeout */
-			tul_unlink_pend_scb(pCurHcb, pCurScb);
-			pCurScb->SCB_HaStat = HOST_SEL_TOUT;
-			tul_append_done_scb(pCurHcb, pCurScb);
+	if (scb != NULL) {
+		if (scb->status & SCB_SELECT) {		/* selection timeout */
+			initio_unlink_pend_scb(host, scb);
+			scb->hastat = HOST_SEL_TOUT;
+			initio_append_done_scb(host, scb);
 		} else {	/* Unexpected bus free          */
-			tul_unlink_busy_scb(pCurHcb, pCurScb);
-			pCurScb->SCB_HaStat = HOST_BUS_FREE;
-			tul_append_done_scb(pCurHcb, pCurScb);
+			initio_unlink_busy_scb(host, scb);
+			scb->hastat = HOST_BUS_FREE;
+			initio_append_done_scb(host, scb);
 		}
-		pCurHcb->HCS_ActScb = NULL;
-		pCurHcb->HCS_ActTcs = NULL;
+		host->active = NULL;
+		host->active_tc = NULL;
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-	return (-1);
+	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);		/* Flush SCSI FIFO  */
+	outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+	outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect       */
+	return -1;
 }
 
 
-/***************************************************************************/
-/* scsi bus reset */
-static int int_tul_scsi_rst(HCS * pCurHcb)
+/**
+ *	int_initio_scsi_rst	-	SCSI reset occurred
+ *	@host: Host seeing the reset
+ *
+ *	A SCSI bus reset has occurred. Clean up any pending transfer
+ *	the hardware is doing by DMA and then abort all active and
+ *	disconnected commands. The mid layer should sort the rest out
+ *	for us
+ */
+
+static int int_initio_scsi_rst(struct initio_host * host)
 {
-	SCB *pCurScb;
+	struct scsi_ctrl_blk *scb;
 	int i;
 
 	/* if DMA xfer is pending, abort DMA xfer */
-	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+	if (inb(host->addr + TUL_XStatus) & 0x01) {
+		outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
 		/* wait Abort DMA xfer done */
-		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+		while ((inb(host->addr + TUL_Int) & 0x04) == 0)
+			cpu_relax();
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 	}
 	/* Abort all active & disconnected scb */
-	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
-		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-		tul_append_done_scb(pCurHcb, pCurScb);
+	while ((scb = initio_pop_busy_scb(host)) != NULL) {
+		scb->hastat = HOST_BAD_PHAS;
+		initio_append_done_scb(host, scb);
 	}
-	pCurHcb->HCS_ActScb = NULL;
-	pCurHcb->HCS_ActTcs = NULL;
+	host->active = NULL;
+	host->active_tc = NULL;
 
 	/* clr sync nego. done flag */
-	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
-		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-	}
-	return (-1);
+	for (i = 0; i < host->max_tar; i++)
+		host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+	return -1;
 }
 
+/**
+ *	int_initio_scsi_resel	-	Reselection occured
+ *	@host: InitIO host adapter
+ *
+ *	A SCSI reselection event has been signalled and the interrupt
+ *	is now being processed. Work out which command block needs attention
+ *	and continue processing that command.
+ */
 
-/***************************************************************************/
-/* scsi reselection */
-int int_tul_resel(HCS * pCurHcb)
+int int_initio_resel(struct initio_host * host)
 {
-	SCB *pCurScb;
-	TCS *pCurTcb;
-	BYTE tag, msg = 0;
-	BYTE tar, lun;
+	struct scsi_ctrl_blk *scb;
+	struct target_control *active_tc;
+	u8 tag, msg = 0;
+	u8 tar, lun;
 
-	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
-		if (pCurScb->SCB_Status & SCB_SELECT) {		/* if waiting for selection complete */
-			pCurScb->SCB_Status &= ~SCB_SELECT;
-		}
-		pCurHcb->HCS_ActScb = NULL;
+	if ((scb = host->active) != NULL) {
+		/* FIXME: Why check and not just clear ? */
+		if (scb->status & SCB_SELECT)		/* if waiting for selection complete */
+			scb->status &= ~SCB_SELECT;
+		host->active = NULL;
 	}
 	/* --------- get target id---------------------- */
-	tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);
+	tar = inb(host->addr + TUL_SBusId);
 	/* ------ get LUN from Identify message----------- */
-	lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;
+	lun = inb(host->addr + TUL_SIdent) & 0x0F;
 	/* 07/22/98 from 0x1F -> 0x0F */
-	pCurTcb = &pCurHcb->HCS_Tcs[tar];
-	pCurHcb->HCS_ActTcs = pCurTcb;
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
-
+	active_tc = &host->targets[tar];
+	host->active_tc = active_tc;
+	outb(active_tc->sconfig0, host->addr + TUL_SConfig);
+	outb(active_tc->js_period, host->addr + TUL_SPeriod);
 
 	/* ------------- tag queueing ? ------------------- */
-	if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {
-		if ((tul_msgin_accept(pCurHcb)) == -1)
-			return (-1);
-		if (pCurHcb->HCS_Phase != MSG_IN)
+	if (active_tc->drv_flags & TCF_DRV_EN_TAG) {
+		if ((initio_msgin_accept(host)) == -1)
+			return -1;
+		if (host->phase != MSG_IN)
 			goto no_tag;
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if ((wait_tulip(pCurHcb)) == -1)
-			return (-1);
-		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag Message    */
+		outl(1, host->addr + TUL_SCnt0);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
+		msg = inb(host->addr + TUL_SFifo);	/* Read Tag Message    */
 
-		if ((msg < MSG_STAG) || (msg > MSG_OTAG))	/* Is simple Tag      */
+		if (msg < MSG_STAG || msg > MSG_OTAG)		/* Is simple Tag      */
 			goto no_tag;
 
-		if ((tul_msgin_accept(pCurHcb)) == -1)
-			return (-1);
+		if (initio_msgin_accept(host) == -1)
+			return -1;
 
-		if (pCurHcb->HCS_Phase != MSG_IN)
+		if (host->phase != MSG_IN)
 			goto no_tag;
 
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if ((wait_tulip(pCurHcb)) == -1)
-			return (-1);
-		tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag ID       */
-		pCurScb = pCurHcb->HCS_Scb + tag;
-		if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {
-			return tul_msgout_abort_tag(pCurHcb);
+		outl(1, host->addr + TUL_SCnt0);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
+		tag = inb(host->addr + TUL_SFifo);	/* Read Tag ID       */
+		scb = host->scb + tag;
+		if (scb->target != tar || scb->lun != lun) {
+			return initio_msgout_abort_tag(host);
 		}
-		if (pCurScb->SCB_Status != SCB_BUSY) {	/* 03/24/95             */
-			return tul_msgout_abort_tag(pCurHcb);
+		if (scb->status != SCB_BUSY) {	/* 03/24/95             */
+			return initio_msgout_abort_tag(host);
 		}
-		pCurHcb->HCS_ActScb = pCurScb;
-		if ((tul_msgin_accept(pCurHcb)) == -1)
-			return (-1);
+		host->active = scb;
+		if ((initio_msgin_accept(host)) == -1)
+			return -1;
 	} else {		/* No tag               */
 	      no_tag:
-		if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {
-			return tul_msgout_abort_targ(pCurHcb);
+		if ((scb = initio_find_busy_scb(host, tar | (lun << 8))) == NULL) {
+			return initio_msgout_abort_targ(host);
 		}
-		pCurHcb->HCS_ActScb = pCurScb;
-		if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {
-			if ((tul_msgin_accept(pCurHcb)) == -1)
-				return (-1);
+		host->active = scb;
+		if (!(active_tc->drv_flags & TCF_DRV_EN_TAG)) {
+			if ((initio_msgin_accept(host)) == -1)
+				return -1;
 		}
 	}
 	return 0;
 }
 
+/**
+ *	int_initio_bad_seq		-	out of phase
+ *	@host: InitIO host flagging event
+ *
+ *	We have ended up out of phase somehow. Reset the host controller
+ *	and throw all our toys out of the pram. Let the midlayer clean up
+ */
 
-/***************************************************************************/
-static int int_tul_bad_seq(HCS * pCurHcb)
+static int int_initio_bad_seq(struct initio_host * host)
 {				/* target wrong phase           */
-	SCB *pCurScb;
+	struct scsi_ctrl_blk *scb;
 	int i;
 
-	tul_reset_scsi(pCurHcb, 10);
+	initio_reset_scsi(host, 10);
 
-	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
-		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-		tul_append_done_scb(pCurHcb, pCurScb);
+	while ((scb = initio_pop_busy_scb(host)) != NULL) {
+		scb->hastat = HOST_BAD_PHAS;
+		initio_append_done_scb(host, scb);
 	}
-	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
-		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-	}
-	return (-1);
+	for (i = 0; i < host->max_tar; i++)
+		host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+	return -1;
 }
 
 
-/***************************************************************************/
-int tul_msgout_abort_targ(HCS * pCurHcb)
+/**
+ *	initio_msgout_abort_targ		-	abort a tag
+ *	@host: InitIO host
+ *
+ *	Abort when the target/lun does not match or when our SCB is not
+ *	busy. Used by untagged commands.
+ */
+
+static int initio_msgout_abort_targ(struct initio_host * host)
 {
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-	if (tul_msgin_accept(pCurHcb) == -1)
-		return (-1);
-	if (pCurHcb->HCS_Phase != MSG_OUT)
-		return (tul_bad_seq(pCurHcb));
+	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+	if (initio_msgin_accept(host) == -1)
+		return -1;
+	if (host->phase != MSG_OUT)
+		return initio_bad_seq(host);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+	outb(MSG_ABORT, host->addr + TUL_SFifo);
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
 
-	return tul_wait_disc(pCurHcb);
+	return initio_wait_disc(host);
 }
 
-/***************************************************************************/
-int tul_msgout_abort_tag(HCS * pCurHcb)
+/**
+ *	initio_msgout_abort_tag		-	abort a tag
+ *	@host: InitIO host
+ *
+ *	Abort when the target/lun does not match or when our SCB is not
+ *	busy. Used for tagged commands.
+ */
+
+static int initio_msgout_abort_tag(struct initio_host * host)
 {
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-	if (tul_msgin_accept(pCurHcb) == -1)
-		return (-1);
-	if (pCurHcb->HCS_Phase != MSG_OUT)
-		return (tul_bad_seq(pCurHcb));
+	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+	if (initio_msgin_accept(host) == -1)
+		return -1;
+	if (host->phase != MSG_OUT)
+		return initio_bad_seq(host);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+	outb(MSG_ABORT_TAG, host->addr + TUL_SFifo);
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
 
-	return tul_wait_disc(pCurHcb);
+	return initio_wait_disc(host);
 
 }
 
-/***************************************************************************/
-int tul_msgin(HCS * pCurHcb)
+/**
+ *	initio_msgin		-	Message in
+ *	@host: InitIO Host
+ *
+ *	Process incoming message
+ */
+static int initio_msgin(struct initio_host * host)
 {
-	TCS *pCurTcb;
+	struct target_control *active_tc;
 
 	for (;;) {
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+		outl(1, host->addr + TUL_SCnt0);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
 
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if ((wait_tulip(pCurHcb)) == -1)
-			return (-1);
-
-		switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) {
+		switch (inb(host->addr + TUL_SFifo)) {
 		case MSG_DISC:	/* Disconnect msg */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
-
-			return tul_wait_disc(pCurHcb);
-
+			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+			return initio_wait_disc(host);
 		case MSG_SDP:
 		case MSG_RESTORE:
 		case MSG_NOP:
-			tul_msgin_accept(pCurHcb);
+			initio_msgin_accept(host);
 			break;
-
 		case MSG_REJ:	/* Clear ATN first              */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SSignal,
-			       (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
-			pCurTcb = pCurHcb->HCS_ActTcs;
-			if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync nego */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-			}
-			tul_msgin_accept(pCurHcb);
+			outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)),
+				host->addr + TUL_SSignal);
+			active_tc = host->active_tc;
+			if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)	/* do sync nego */
+				outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN),
+					host->addr + TUL_SSignal);
+			initio_msgin_accept(host);
 			break;
-
 		case MSG_EXTEND:	/* extended msg */
-			tul_msgin_extend(pCurHcb);
+			initio_msgin_extend(host);
 			break;
-
 		case MSG_IGNOREWIDE:
-			tul_msgin_accept(pCurHcb);
+			initio_msgin_accept(host);
 			break;
-
-			/* get */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-			if (wait_tulip(pCurHcb) == -1)
-				return -1;
-
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);	/* put pad  */
-			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* get IGNORE field */
-			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* get pad */
-
-			tul_msgin_accept(pCurHcb);
-			break;
-
 		case MSG_COMP:
-			{
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
-				return tul_wait_done_disc(pCurHcb);
-			}
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+			return initio_wait_done_disc(host);
 		default:
-			tul_msgout_reject(pCurHcb);
+			initio_msgout_reject(host);
 			break;
 		}
-		if (pCurHcb->HCS_Phase != MSG_IN)
-			return (pCurHcb->HCS_Phase);
+		if (host->phase != MSG_IN)
+			return host->phase;
 	}
 	/* statement won't reach here */
 }
 
-
-
-
-/***************************************************************************/
-int tul_msgout_reject(HCS * pCurHcb)
+static int initio_msgout_reject(struct initio_host * host)
 {
+	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+	if (initio_msgin_accept(host) == -1)
+		return -1;
 
-	if ((tul_msgin_accept(pCurHcb)) == -1)
-		return (-1);
-
-	if (pCurHcb->HCS_Phase == MSG_OUT) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ);		/* Msg reject           */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		return (wait_tulip(pCurHcb));
+	if (host->phase == MSG_OUT) {
+		outb(MSG_REJ, host->addr + TUL_SFifo);		/* Msg reject           */
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		return wait_tulip(host);
 	}
-	return (pCurHcb->HCS_Phase);
+	return host->phase;
 }
 
-
-
-/***************************************************************************/
-int tul_msgout_ide(HCS * pCurHcb)
+static int initio_msgout_ide(struct initio_host * host)
 {
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE);		/* Initiator Detected Error */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-	return (wait_tulip(pCurHcb));
+	outb(MSG_IDE, host->addr + TUL_SFifo);		/* Initiator Detected Error */
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+	return wait_tulip(host);
 }
 
-
-/***************************************************************************/
-int tul_msgin_extend(HCS * pCurHcb)
+static int initio_msgin_extend(struct initio_host * host)
 {
-	BYTE len, idx;
+	u8 len, idx;
 
-	if (tul_msgin_accept(pCurHcb) != MSG_IN)
-		return (pCurHcb->HCS_Phase);
+	if (initio_msgin_accept(host) != MSG_IN)
+		return host->phase;
 
 	/* Get extended msg length      */
-	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-	if (wait_tulip(pCurHcb) == -1)
-		return (-1);
+	outl(1, host->addr + TUL_SCnt0);
+	outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+	if (wait_tulip(host) == -1)
+		return -1;
 
-	len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
-	pCurHcb->HCS_Msg[0] = len;
+	len = inb(host->addr + TUL_SFifo);
+	host->msg[0] = len;
 	for (idx = 1; len != 0; len--) {
 
-		if ((tul_msgin_accept(pCurHcb)) != MSG_IN)
-			return (pCurHcb->HCS_Phase);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if (wait_tulip(pCurHcb) == -1)
-			return (-1);
-		pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+		if ((initio_msgin_accept(host)) != MSG_IN)
+			return host->phase;
+		outl(1, host->addr + TUL_SCnt0);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
+		host->msg[idx++] = inb(host->addr + TUL_SFifo);
 	}
-	if (pCurHcb->HCS_Msg[1] == 1) {		/* if it's synchronous data transfer request */
-		if (pCurHcb->HCS_Msg[0] != 3)	/* if length is not right */
-			return (tul_msgout_reject(pCurHcb));
-		if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) {	/* Set OFFSET=0 to do async, nego back */
-			pCurHcb->HCS_Msg[3] = 0;
+	if (host->msg[1] == 1) {		/* if it's synchronous data transfer request */
+		u8 r;
+		if (host->msg[0] != 3)	/* if length is not right */
+			return initio_msgout_reject(host);
+		if (host->active_tc->flags & TCF_NO_SYNC_NEGO) {	/* Set OFFSET=0 to do async, nego back */
+			host->msg[3] = 0;
 		} else {
-			if ((tul_msgin_sync(pCurHcb) == 0) &&
-			    (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) {
-				tul_sync_done(pCurHcb);
-				return (tul_msgin_accept(pCurHcb));
+			if (initio_msgin_sync(host) == 0 &&
+			    (host->active_tc->flags & TCF_SYNC_DONE)) {
+				initio_sync_done(host);
+				return initio_msgin_accept(host);
 			}
 		}
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-		if ((tul_msgin_accept(pCurHcb)) != MSG_OUT)
-			return (pCurHcb->HCS_Phase);
+		r = inb(host->addr + TUL_SSignal);
+		outb((r & (TSC_SET_ACK | 7)) | TSC_SET_ATN,
+			host->addr + TUL_SSignal);
+		if (initio_msgin_accept(host) != MSG_OUT)
+			return host->phase;
 		/* sync msg out */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 
-		tul_sync_done(pCurHcb);
+		initio_sync_done(host);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]);
-
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		return (wait_tulip(pCurHcb));
+		outb(MSG_EXTEND, host->addr + TUL_SFifo);
+		outb(3, host->addr + TUL_SFifo);
+		outb(1, host->addr + TUL_SFifo);
+		outb(host->msg[2], host->addr + TUL_SFifo);
+		outb(host->msg[3], host->addr + TUL_SFifo);
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		return wait_tulip(host);
 	}
-	if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3))
-		return (tul_msgout_reject(pCurHcb));
+	if (host->msg[0] != 2 || host->msg[1] != 3)
+		return initio_msgout_reject(host);
 	/* if it's WIDE DATA XFER REQ   */
-	if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) {
-		pCurHcb->HCS_Msg[2] = 0;
+	if (host->active_tc->flags & TCF_NO_WDTR) {
+		host->msg[2] = 0;
 	} else {
-		if (pCurHcb->HCS_Msg[2] > 2)	/* > 32 bits            */
-			return (tul_msgout_reject(pCurHcb));
-		if (pCurHcb->HCS_Msg[2] == 2) {		/* == 32                */
-			pCurHcb->HCS_Msg[2] = 1;
+		if (host->msg[2] > 2)	/* > 32 bits            */
+			return initio_msgout_reject(host);
+		if (host->msg[2] == 2) {		/* == 32                */
+			host->msg[2] = 1;
 		} else {
-			if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) {
-				wdtr_done(pCurHcb);
-				if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
-					TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-				return (tul_msgin_accept(pCurHcb));
+			if ((host->active_tc->flags & TCF_NO_WDTR) == 0) {
+				wdtr_done(host);
+				if ((host->active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
+					outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+				return initio_msgin_accept(host);
 			}
 		}
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
 
-	if (tul_msgin_accept(pCurHcb) != MSG_OUT)
-		return (pCurHcb->HCS_Phase);
+	if (initio_msgin_accept(host) != MSG_OUT)
+		return host->phase;
 	/* WDTR msg out                 */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-	return (wait_tulip(pCurHcb));
+	outb(MSG_EXTEND, host->addr + TUL_SFifo);
+	outb(2, host->addr + TUL_SFifo);
+	outb(3, host->addr + TUL_SFifo);
+	outb(host->msg[2], host->addr + TUL_SFifo);
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+	return wait_tulip(host);
 }
 
-/***************************************************************************/
-int tul_msgin_sync(HCS * pCurHcb)
+static int initio_msgin_sync(struct initio_host * host)
 {
 	char default_period;
 
-	default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE];
-	if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) {
-		pCurHcb->HCS_Msg[3] = MAX_OFFSET;
-		if (pCurHcb->HCS_Msg[2] < default_period) {
-			pCurHcb->HCS_Msg[2] = default_period;
+	default_period = initio_rate_tbl[host->active_tc->flags & TCF_SCSI_RATE];
+	if (host->msg[3] > MAX_OFFSET) {
+		host->msg[3] = MAX_OFFSET;
+		if (host->msg[2] < default_period) {
+			host->msg[2] = default_period;
 			return 1;
 		}
-		if (pCurHcb->HCS_Msg[2] >= 59) {	/* Change to async              */
-			pCurHcb->HCS_Msg[3] = 0;
-		}
+		if (host->msg[2] >= 59)	/* Change to async              */
+			host->msg[3] = 0;
 		return 1;
 	}
 	/* offset requests asynchronous transfers ? */
-	if (pCurHcb->HCS_Msg[3] == 0) {
+	if (host->msg[3] == 0) {
 		return 0;
 	}
-	if (pCurHcb->HCS_Msg[2] < default_period) {
-		pCurHcb->HCS_Msg[2] = default_period;
+	if (host->msg[2] < default_period) {
+		host->msg[2] = default_period;
 		return 1;
 	}
-	if (pCurHcb->HCS_Msg[2] >= 59) {
-		pCurHcb->HCS_Msg[3] = 0;
+	if (host->msg[2] >= 59) {
+		host->msg[3] = 0;
 		return 1;
 	}
 	return 0;
 }
 
-
-/***************************************************************************/
-int wdtr_done(HCS * pCurHcb)
+static int wdtr_done(struct initio_host * host)
 {
-	pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE;
-	pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE;
+	host->active_tc->flags &= ~TCF_SYNC_DONE;
+	host->active_tc->flags |= TCF_WDTR_DONE;
 
-	pCurHcb->HCS_ActTcs->TCS_JS_Period = 0;
-	if (pCurHcb->HCS_Msg[2]) {	/* if 16 bit */
-		pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI;
-	}
-	pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD;
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+	host->active_tc->js_period = 0;
+	if (host->msg[2])	/* if 16 bit */
+		host->active_tc->js_period |= TSC_WIDE_SCSI;
+	host->active_tc->sconfig0 &= ~TSC_ALT_PERIOD;
+	outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
+	outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
 
 	return 1;
 }
 
-/***************************************************************************/
-int tul_sync_done(HCS * pCurHcb)
+static int initio_sync_done(struct initio_host * host)
 {
 	int i;
 
-	pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE;
+	host->active_tc->flags |= TCF_SYNC_DONE;
 
-	if (pCurHcb->HCS_Msg[3]) {
-		pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3];
+	if (host->msg[3]) {
+		host->active_tc->js_period |= host->msg[3];
 		for (i = 0; i < 8; i++) {
-			if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2])	/* pick the big one */
+			if (initio_rate_tbl[i] >= host->msg[2])	/* pick the big one */
 				break;
 		}
-		pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4);
-		pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD;
+		host->active_tc->js_period |= (i << 4);
+		host->active_tc->sconfig0 |= TSC_ALT_PERIOD;
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+	outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
+	outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
 
-	return (-1);
+	return -1;
 }
 
 
-int tul_post_scsi_rst(HCS * pCurHcb)
+static int initio_post_scsi_rst(struct initio_host * host)
 {
-	SCB *pCurScb;
-	TCS *pCurTcb;
+	struct scsi_ctrl_blk *scb;
+	struct target_control *active_tc;
 	int i;
 
-	pCurHcb->HCS_ActScb = NULL;
-	pCurHcb->HCS_ActTcs = NULL;
-	pCurHcb->HCS_Flags = 0;
+	host->active = NULL;
+	host->active_tc = NULL;
+	host->flags = 0;
 
-	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
-		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-		tul_append_done_scb(pCurHcb, pCurScb);
+	while ((scb = initio_pop_busy_scb(host)) != NULL) {
+		scb->hastat = HOST_BAD_PHAS;
+		initio_append_done_scb(host, scb);
 	}
 	/* clear sync done flag         */
-	pCurTcb = &pCurHcb->HCS_Tcs[0];
-	for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) {
-		pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+	active_tc = &host->targets[0];
+	for (i = 0; i < host->max_tar; active_tc++, i++) {
+		active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
 		/* Initialize the sync. xfer register values to an asyn xfer */
-		pCurTcb->TCS_JS_Period = 0;
-		pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1;
-		pCurHcb->HCS_ActTags[0] = 0;	/* 07/22/98 */
-		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;	/* 07/22/98 */
+		active_tc->js_period = 0;
+		active_tc->sconfig0 = host->sconf1;
+		host->act_tags[0] = 0;	/* 07/22/98 */
+		host->targets[i].flags &= ~TCF_BUSY;	/* 07/22/98 */
 	}			/* for */
 
-	return (-1);
+	return -1;
 }
 
-/***************************************************************************/
-void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb)
+static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
-	pCurScb->SCB_Status |= SCB_SELECT;
-	pCurScb->SCB_NxtStat = 0x1;
-	pCurHcb->HCS_ActScb = pCurScb;
-	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP);
-	return;
+	scb->status |= SCB_SELECT;
+	scb->next_state = 0x1;
+	host->active = scb;
+	host->active_tc = &host->targets[scb->target];
+	outb(TSC_SELATNSTOP, host->addr + TUL_SCmd);
 }
 
 
-/***************************************************************************/
-void tul_select_atn(HCS * pCurHcb, SCB * pCurScb)
+static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
 	int i;
 
-	pCurScb->SCB_Status |= SCB_SELECT;
-	pCurScb->SCB_NxtStat = 0x2;
+	scb->status |= SCB_SELECT;
+	scb->next_state = 0x2;
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
-	for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
-	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
-	pCurHcb->HCS_ActScb = pCurScb;
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN);
-	return;
+	outb(scb->ident, host->addr + TUL_SFifo);
+	for (i = 0; i < (int) scb->cdblen; i++)
+		outb(scb->cdb[i], host->addr + TUL_SFifo);
+	host->active_tc = &host->targets[scb->target];
+	host->active = scb;
+	outb(TSC_SEL_ATN, host->addr + TUL_SCmd);
 }
 
-/***************************************************************************/
-void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb)
+static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
 	int i;
 
-	pCurScb->SCB_Status |= SCB_SELECT;
-	pCurScb->SCB_NxtStat = 0x2;
+	scb->status |= SCB_SELECT;
+	scb->next_state = 0x2;
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
-	for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
-	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
-	pCurHcb->HCS_ActScb = pCurScb;
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3);
-	return;
+	outb(scb->ident, host->addr + TUL_SFifo);
+	outb(scb->tagmsg, host->addr + TUL_SFifo);
+	outb(scb->tagid, host->addr + TUL_SFifo);
+	for (i = 0; i < scb->cdblen; i++)
+		outb(scb->cdb[i], host->addr + TUL_SFifo);
+	host->active_tc = &host->targets[scb->target];
+	host->active = scb;
+	outb(TSC_SEL_ATN3, host->addr + TUL_SCmd);
 }
 
-/***************************************************************************/
-/* SCSI Bus Device Reset */
-int tul_bus_device_reset(HCS * pCurHcb)
+/**
+ *	initio_bus_device_reset	-	 SCSI Bus Device Reset
+ *	@host: InitIO host to reset
+ *
+ *	Perform a device reset and abort all pending SCBs for the
+ *	victim device
+ */
+int initio_bus_device_reset(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
-	SCB *pTmpScb, *pPrevScb;
-	BYTE tar;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
+	struct scsi_ctrl_blk *tmp, *prev;
+	u8 tar;
 
-	if (pCurHcb->HCS_Phase != MSG_OUT) {
-		return (int_tul_bad_seq(pCurHcb));	/* Unexpected phase             */
-	}
-	tul_unlink_pend_scb(pCurHcb, pCurScb);
-	tul_release_scb(pCurHcb, pCurScb);
+	if (host->phase != MSG_OUT)
+		return int_initio_bad_seq(host);	/* Unexpected phase */
+
+	initio_unlink_pend_scb(host, scb);
+	initio_release_scb(host, scb);
 
 
-	tar = pCurScb->SCB_Target;	/* target                       */
-	pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
+	tar = scb->target;	/* target                       */
+	active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
 	/* clr sync. nego & WDTR flags  07/22/98 */
 
 	/* abort all SCB with same target */
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
-	while (pTmpScb != NULL) {
-
-		if (pTmpScb->SCB_Target == tar) {
+	prev = tmp = host->first_busy;	/* Check Busy queue */
+	while (tmp != NULL) {
+		if (tmp->target == tar) {
 			/* unlink it */
-			if (pTmpScb == pCurHcb->HCS_FirstBusy) {
-				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
-					pCurHcb->HCS_LastBusy = NULL;
+			if (tmp == host->first_busy) {
+				if ((host->first_busy = tmp->next) == NULL)
+					host->last_busy = NULL;
 			} else {
-				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-				if (pTmpScb == pCurHcb->HCS_LastBusy)
-					pCurHcb->HCS_LastBusy = pPrevScb;
+				prev->next = tmp->next;
+				if (tmp == host->last_busy)
+					host->last_busy = prev;
 			}
-			pTmpScb->SCB_HaStat = HOST_ABORTED;
-			tul_append_done_scb(pCurHcb, pTmpScb);
+			tmp->hastat = HOST_ABORTED;
+			initio_append_done_scb(host, tmp);
 		}
 		/* Previous haven't change      */
 		else {
-			pPrevScb = pTmpScb;
+			prev = tmp;
 		}
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		tmp = tmp->next;
 	}
-
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-
-	return tul_wait_disc(pCurHcb);
+	outb(MSG_DEVRST, host->addr + TUL_SFifo);
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+	return initio_wait_disc(host);
 
 }
 
-/***************************************************************************/
-int tul_msgin_accept(HCS * pCurHcb)
+static int initio_msgin_accept(struct initio_host * host)
 {
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
-	return (wait_tulip(pCurHcb));
+	outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+	return wait_tulip(host);
 }
 
-/***************************************************************************/
-int wait_tulip(HCS * pCurHcb)
+static int wait_tulip(struct initio_host * host)
 {
 
-	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
-		 & TSS_INT_PENDING));
+	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
+		 & TSS_INT_PENDING))
+			cpu_relax();
 
-	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-	pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
-	pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
+	host->jsint = inb(host->addr + TUL_SInt);
+	host->phase = host->jsstatus0 & TSS_PH_MASK;
+	host->jsstatus1 = inb(host->addr + TUL_SStatus1);
 
-	if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {	/* if SCSI bus reset detected   */
-		return (int_tul_resel(pCurHcb));
-	}
-	if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {	/* if selected/reselected timeout interrupt */
-		return (int_tul_busfree(pCurHcb));
-	}
-	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
-		return (int_tul_scsi_rst(pCurHcb));
-	}
-	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
-		if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-			tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
-			pCurHcb->HCS_ActScb->SCB_HaStat = 0;
-			tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
-			pCurHcb->HCS_ActScb = NULL;
-			pCurHcb->HCS_ActTcs = NULL;
-			pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC;
-			TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-			return (-1);
+	if (host->jsint & TSS_RESEL_INT)	/* if SCSI bus reset detected */
+		return int_initio_resel(host);
+	if (host->jsint & TSS_SEL_TIMEOUT)	/* if selected/reselected timeout interrupt */
+		return int_initio_busfree(host);
+	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected   */
+		return int_initio_scsi_rst(host);
+
+	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection            */
+		if (host->flags & HCF_EXPECT_DONE_DISC) {
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+			initio_unlink_busy_scb(host, host->active);
+			host->active->hastat = 0;
+			initio_append_done_scb(host, host->active);
+			host->active = NULL;
+			host->active_tc = NULL;
+			host->flags &= ~HCF_EXPECT_DONE_DISC;
+			outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */
+			return -1;
 		}
-		if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-			pCurHcb->HCS_ActScb = NULL;
-			pCurHcb->HCS_ActTcs = NULL;
-			pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC;
-			TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-			return (-1);
+		if (host->flags & HCF_EXPECT_DISC) {
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+			host->active = NULL;
+			host->active_tc = NULL;
+			host->flags &= ~HCF_EXPECT_DISC;
+			outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */
+			return -1;
 		}
-		return (int_tul_busfree(pCurHcb));
+		return int_initio_busfree(host);
 	}
-	if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
-		return (pCurHcb->HCS_Phase);
-	}
-	return (pCurHcb->HCS_Phase);
+	/* The old code really does the below. Can probably be removed */
+	if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV))
+		return host->phase;
+	return host->phase;
 }
-/***************************************************************************/
-int tul_wait_disc(HCS * pCurHcb)
+
+static int initio_wait_disc(struct initio_host * host)
 {
+	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING))
+		cpu_relax();
 
-	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
-		 & TSS_INT_PENDING));
+	host->jsint = inb(host->addr + TUL_SInt);
 
-
-	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-
-	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
-		return (int_tul_scsi_rst(pCurHcb));
+	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected */
+		return int_initio_scsi_rst(host);
+	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection */
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+		outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+		outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */
+		host->active = NULL;
+		return -1;
 	}
-	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-		pCurHcb->HCS_ActScb = NULL;
-		return (-1);
-	}
-	return (tul_bad_seq(pCurHcb));
+	return initio_bad_seq(host);
 }
 
-/***************************************************************************/
-int tul_wait_done_disc(HCS * pCurHcb)
+static int initio_wait_done_disc(struct initio_host * host)
 {
+	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
+		 & TSS_INT_PENDING))
+		 cpu_relax();
 
+	host->jsint = inb(host->addr + TUL_SInt);
 
-	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
-		 & TSS_INT_PENDING));
+	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected */
+		return int_initio_scsi_rst(host);
+	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection */
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);		/* Flush SCSI FIFO */
+		outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+		outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);		/* Enable HW reselect */
+		initio_unlink_busy_scb(host, host->active);
 
-	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-
-
-	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
-		return (int_tul_scsi_rst(pCurHcb));
+		initio_append_done_scb(host, host->active);
+		host->active = NULL;
+		return -1;
 	}
-	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-		tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
-
-		tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
-		pCurHcb->HCS_ActScb = NULL;
-		return (-1);
-	}
-	return (tul_bad_seq(pCurHcb));
+	return initio_bad_seq(host);
 }
 
+/**
+ *	i91u_intr		-	IRQ handler
+ *	@irqno: IRQ number
+ *	@dev_id: IRQ identifier
+ *
+ *	Take the relevant locks and then invoke the actual isr processing
+ *	code under the lock.
+ */
+
 static irqreturn_t i91u_intr(int irqno, void *dev_id)
 {
 	struct Scsi_Host *dev = dev_id;
 	unsigned long flags;
+	int r;
 	
 	spin_lock_irqsave(dev->host_lock, flags);
-	tul_isr((HCS *)dev->base);
+	r = initio_isr((struct initio_host *)dev->hostdata);
 	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
+	if (r)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
 }
 
-static int tul_NewReturnNumberOfAdapters(void)
-{
-	struct pci_dev *pDev = NULL;	/* Start from none              */
-	int iAdapters = 0;
-	long dRegValue;
-	WORD wBIOS;
-	int i = 0;
 
-	init_i91uAdapter_table();
+/**
+ *	initio_build_scb		-	Build the mappings and SCB
+ *	@host: InitIO host taking the command
+ *	@cblk: Firmware command block
+ *	@cmnd: SCSI midlayer command block
+ *
+ *	Translate the abstract SCSI command into a firmware command block
+ *	suitable for feeding to the InitIO host controller. This also requires
+ *	we build the scatter gather lists and ensure they are mapped properly.
+ */
 
-	for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++)
-	{
-		while ((pDev = pci_find_device(i91u_pci_devices[i].vendor, i91u_pci_devices[i].device, pDev)) != NULL) {
-			if (pci_enable_device(pDev))
-				continue;
-			pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
-			wBIOS = (UWORD) (dRegValue & 0xFF);
-			if (((dRegValue & 0xFF00) >> 8) == 0xFF)
-				dRegValue = 0;
-			wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
-			if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) {
-				printk(KERN_WARNING 
-				       "i91u: Could not set 32 bit DMA mask\n");
-				continue;
-			}
-
-			if (Addi91u_into_Adapter_table(wBIOS,
-							(pDev->resource[0].start),
-						       	pDev->irq,
-						       	pDev->bus->number,
-					       		(pDev->devfn >> 3)
-		    		) == 0)
-				iAdapters++;
-		}
-	}
-
-	return (iAdapters);
-}
-
-static int i91u_detect(struct scsi_host_template * tpnt)
-{
-	HCS *pHCB;
-	struct Scsi_Host *hreg;
-	unsigned long i;	/* 01/14/98                     */
-	int ok = 0, iAdapters;
-	ULONG dBiosAdr;
-	BYTE *pbBiosAdr;
-
-	/* Get total number of adapters in the motherboard */
-	iAdapters = tul_NewReturnNumberOfAdapters();
-	if (iAdapters == 0)	/* If no tulip founded, return */
-		return (0);
-
-	tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters;
-	/* Update actually channel number */
-	if (tul_tag_enable) {	/* 1.01i                  */
-		tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE;
-	} else {
-		tul_num_scb = MAX_TARGETS + 3;	/* 1-tape, 1-CD_ROM, 1- extra */
-	}			/* Update actually SCBs per adapter */
-
-	/* Get total memory needed for HCS */
-	i = tul_num_ch * sizeof(HCS);
-	memset((unsigned char *) &tul_hcs[0], 0, i);	/* Initialize tul_hcs 0 */
-	/* Get total memory needed for SCB */
-
-	for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
-		i = tul_num_ch * tul_num_scb * sizeof(SCB);
-		if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
-			break;
-	}
-	if (tul_scb == NULL) {
-		printk("i91u: SCB memory allocation error\n");
-		return (0);
-	}
-	memset((unsigned char *) tul_scb, 0, i);
-
-	for (i = 0, pHCB = &tul_hcs[0];		/* Get pointer for control block */
-	     i < tul_num_ch;
-	     i++, pHCB++) {
-		get_tulipPCIConfig(pHCB, i);
-
-		dBiosAdr = pHCB->HCS_BIOS;
-		dBiosAdr = (dBiosAdr << 4);
-
-		pbBiosAdr = phys_to_virt(dBiosAdr);
-
-		init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10);
-		request_region(pHCB->HCS_Base, 256, "i91u"); /* Register */ 
-
-		pHCB->HCS_Index = i;	/* 7/29/98 */
-		hreg = scsi_register(tpnt, sizeof(HCS));
-		if(hreg == NULL) {
-			release_region(pHCB->HCS_Base, 256);
-			return 0;
-		}
-		hreg->io_port = pHCB->HCS_Base;
-		hreg->n_io_port = 0xff;
-		hreg->can_queue = tul_num_scb;	/* 03/05/98                      */
-		hreg->unique_id = pHCB->HCS_Base;
-		hreg->max_id = pHCB->HCS_MaxTar;
-		hreg->max_lun = 32;	/* 10/21/97                     */
-		hreg->irq = pHCB->HCS_Intr;
-		hreg->this_id = pHCB->HCS_SCSI_ID;	/* Assign HCS index           */
-		hreg->base = (unsigned long)pHCB;
-		hreg->sg_tablesize = TOTAL_SG_ENTRY;	/* Maximun support is 32 */
-
-		/* Initial tulip chip           */
-		ok = request_irq(pHCB->HCS_Intr, i91u_intr, IRQF_DISABLED | IRQF_SHARED, "i91u", hreg);
-		if (ok < 0) {
-			printk(KERN_WARNING "i91u: unable to request IRQ %d\n\n", pHCB->HCS_Intr);
-			return 0;
-		}
-	}
-
-	tpnt->this_id = -1;
-	tpnt->can_queue = 1;
-
-	return 1;
-}
-
-static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, struct scsi_cmnd * SCpnt)
+static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * cblk, struct scsi_cmnd * cmnd)
 {				/* Create corresponding SCB     */
-	struct scatterlist *pSrbSG;
-	SG *pSG;		/* Pointer to SG list           */
-	int i;
-	long TotalLen;
+	struct scatterlist *sglist;
+	struct sg_entry *sg;		/* Pointer to SG list           */
+	int i, nseg;
+	long total_len;
 	dma_addr_t dma_addr;
 
-	pSCB->SCB_Post = i91uSCBPost;	/* i91u's callback routine      */
-	pSCB->SCB_Srb = SCpnt;
-	pSCB->SCB_Opcode = ExecSCSI;
-	pSCB->SCB_Flags = SCF_POST;	/* After SCSI done, call post routine */
-	pSCB->SCB_Target = SCpnt->device->id;
-	pSCB->SCB_Lun = SCpnt->device->lun;
-	pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW;
+	/* Fill in the command headers */
+	cblk->post = i91uSCBPost;	/* i91u's callback routine      */
+	cblk->srb = cmnd;
+	cblk->opcode = ExecSCSI;
+	cblk->flags = SCF_POST;	/* After SCSI done, call post routine */
+	cblk->target = cmnd->device->id;
+	cblk->lun = cmnd->device->lun;
+	cblk->ident = cmnd->device->lun | DISC_ALLOW;
 
-	pSCB->SCB_Flags |= SCF_SENSE;	/* Turn on auto request sense   */
-	dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->sense_buffer,
+	cblk->flags |= SCF_SENSE;	/* Turn on auto request sense   */
+
+	/* Map the sense buffer into bus memory */
+	dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,
 				  SENSE_SIZE, DMA_FROM_DEVICE);
-	pSCB->SCB_SensePtr = cpu_to_le32((u32)dma_addr);
-	pSCB->SCB_SenseLen = cpu_to_le32(SENSE_SIZE);
-	SCpnt->SCp.ptr = (char *)(unsigned long)dma_addr;
+	cblk->senseptr = cpu_to_le32((u32)dma_addr);
+	cblk->senselen = cpu_to_le32(SENSE_SIZE);
+	cmnd->SCp.ptr = (char *)(unsigned long)dma_addr;
+	cblk->cdblen = cmnd->cmd_len;
 
-	pSCB->SCB_CDBLen = SCpnt->cmd_len;
-	pSCB->SCB_HaStat = 0;
-	pSCB->SCB_TaStat = 0;
-	memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len);
+	/* Clear the returned status */
+	cblk->hastat = 0;
+	cblk->tastat = 0;
+	/* Command the command */
+	memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
 
-	if (SCpnt->device->tagged_supported) {	/* Tag Support                  */
-		pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */
+	/* Set up tags */
+	if (cmnd->device->tagged_supported) {	/* Tag Support                  */
+		cblk->tagmsg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */
 	} else {
-		pSCB->SCB_TagMsg = 0;	/* No tag support               */
+		cblk->tagmsg = 0;	/* No tag support               */
 	}
+
 	/* todo handle map_sg error */
-	if (SCpnt->use_sg) {
-		dma_addr = dma_map_single(&pHCB->pci_dev->dev, &pSCB->SCB_SGList[0],
-					  sizeof(struct SG_Struc) * TOTAL_SG_ENTRY,
+	nseg = scsi_dma_map(cmnd);
+	BUG_ON(nseg < 0);
+	if (nseg) {
+		dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],
+					  sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
 					  DMA_BIDIRECTIONAL);
-		pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr);
-		SCpnt->SCp.dma_handle = dma_addr;
+		cblk->bufptr = cpu_to_le32((u32)dma_addr);
+		cmnd->SCp.dma_handle = dma_addr;
 
-		pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
-		pSCB->SCB_SGLen = dma_map_sg(&pHCB->pci_dev->dev, pSrbSG,
-					     SCpnt->use_sg, SCpnt->sc_data_direction);
 
-		pSCB->SCB_Flags |= SCF_SG;	/* Turn on SG list flag       */
-		for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];	/* 1.01g */
-		     i < pSCB->SCB_SGLen; i++, pSG++, pSrbSG++) {
-			pSG->SG_Ptr = cpu_to_le32((u32)sg_dma_address(pSrbSG));
-			TotalLen += pSG->SG_Len = cpu_to_le32((u32)sg_dma_len(pSrbSG));
+		cblk->flags |= SCF_SG;	/* Turn on SG list flag       */
+		total_len = 0;
+		sg = &cblk->sglist[0];
+		scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {
+			sg->data = cpu_to_le32((u32)sg_dma_address(sglist));
+			total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
 		}
 
-		pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ?
-		    TotalLen : SCpnt->request_bufflen;
-	} else if (SCpnt->request_bufflen) {		/* Non SG */
-		dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->request_buffer,
-					  SCpnt->request_bufflen,
-					  SCpnt->sc_data_direction);
-		SCpnt->SCp.dma_handle = dma_addr;
-		pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr);
-		pSCB->SCB_BufLen = cpu_to_le32((u32)SCpnt->request_bufflen);
-		pSCB->SCB_SGLen = 0;
-	} else {
-		pSCB->SCB_BufLen = 0;
-		pSCB->SCB_SGLen = 0;
+		cblk->buflen = (scsi_bufflen(cmnd) > total_len) ?
+			total_len : scsi_bufflen(cmnd);
+	} else {	/* No data transfer required */
+		cblk->buflen = 0;
+		cblk->sglen = 0;
 	}
 }
 
+/**
+ *	i91u_queuecommand	-	Queue a new command if possible
+ *	@cmd: SCSI command block from the mid layer
+ *	@done: Completion handler
+ *
+ *	Attempts to queue a new command with the host adapter. Will return
+ *	zero if successful or indicate a host busy condition if not (which
+ *	will cause the mid layer to call us again later with the command)
+ */
+
 static int i91u_queuecommand(struct scsi_cmnd *cmd,
 		void (*done)(struct scsi_cmnd *))
 {
-	HCS *pHCB = (HCS *) cmd->device->host->base;
-	register SCB *pSCB;
+	struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
+	struct scsi_ctrl_blk *cmnd;
 
 	cmd->scsi_done = done;
 
-	pSCB = tul_alloc_scb(pHCB);
-	if (!pSCB)
+	cmnd = initio_alloc_scb(host);
+	if (!cmnd)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
-	i91uBuildSCB(pHCB, pSCB, cmd);
-	tul_exec_scb(pHCB, pSCB);
+	initio_build_scb(host, cmnd, cmd);
+	initio_exec_scb(host, cmnd);
 	return 0;
 }
 
-#if 0 /* no new EH yet */
-/*
- *  Abort a queued command
- *  (commands that are on the bus can't be aborted easily)
+/**
+ *	i91u_bus_reset		-	reset the SCSI bus
+ *	@cmnd: Command block we want to trigger the reset for
+ *
+ *	Initiate a SCSI bus reset sequence
  */
-static int i91u_abort(struct scsi_cmnd * SCpnt)
+
+static int i91u_bus_reset(struct scsi_cmnd * cmnd)
 {
-	HCS *pHCB;
+	struct initio_host *host;
 
-	pHCB = (HCS *) SCpnt->device->host->base;
-	return tul_abort_srb(pHCB, SCpnt);
-}
+	host = (struct initio_host *) cmnd->device->host->hostdata;
 
-/*
- *  Reset registers, reset a hanging bus and
- *  kill active and disconnected commands for target w/o soft reset
- */
-static int i91u_reset(struct scsi_cmnd * SCpnt, unsigned int reset_flags)
-{				/* I need Host Control Block Information */
-	HCS *pHCB;
-
-	pHCB = (HCS *) SCpnt->device->host->base;
-
-	if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
-		return tul_reset_scsi_bus(pHCB);
-	else
-		return tul_device_reset(pHCB, SCpnt, SCpnt->device->id, reset_flags);
-}
-#endif
-
-static int i91u_bus_reset(struct scsi_cmnd * SCpnt)
-{
-	HCS *pHCB;
-
-	pHCB = (HCS *) SCpnt->device->host->base;
-
-	spin_lock_irq(SCpnt->device->host->host_lock);
-	tul_reset_scsi(pHCB, 0);
-	spin_unlock_irq(SCpnt->device->host->host_lock);
+	spin_lock_irq(cmnd->device->host->host_lock);
+	initio_reset_scsi(host, 0);
+	spin_unlock_irq(cmnd->device->host->host_lock);
 
 	return SUCCESS;
 }
 
-/*
- * Return the "logical geometry"
+/**
+ *	i91u_biospararm			-	return the "logical geometry
+ *	@sdev: SCSI device
+ *	@dev; Matching block device
+ *	@capacity: Sector size of drive
+ *	@info_array: Return space for BIOS geometry
+ *
+ *	Map the device geometry in a manner compatible with the host
+ *	controller BIOS behaviour.
+ *
+ *	FIXME: limited to 2^32 sector devices.
  */
+
 static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev,
 		sector_t capacity, int *info_array)
 {
-	HCS *pHcb;		/* Point to Host adapter control block */
-	TCS *pTcb;
+	struct initio_host *host;		/* Point to Host adapter control block */
+	struct target_control *tc;
 
-	pHcb = (HCS *) sdev->host->base;
-	pTcb = &pHcb->HCS_Tcs[sdev->id];
+	host = (struct initio_host *) sdev->host->hostdata;
+	tc = &host->targets[sdev->id];
 
-	if (pTcb->TCS_DrvHead) {
-		info_array[0] = pTcb->TCS_DrvHead;
-		info_array[1] = pTcb->TCS_DrvSector;
-		info_array[2] = (unsigned long)capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector;
+	if (tc->heads) {
+		info_array[0] = tc->heads;
+		info_array[1] = tc->sectors;
+		info_array[2] = (unsigned long)capacity / tc->heads / tc->sectors;
 	} else {
-		if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) {
+		if (tc->drv_flags & TCF_DRV_255_63) {
 			info_array[0] = 255;
 			info_array[1] = 63;
 			info_array[2] = (unsigned long)capacity / 255 / 63;
@@ -3047,7 +2722,16 @@
 	return 0;
 }
 
-static void i91u_unmap_cmnd(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
+/**
+ *	i91u_unmap_scb		-	Unmap a command
+ *	@pci_dev: PCI device the command is for
+ *	@cmnd: The command itself
+ *
+ *	Unmap any PCI mapping/IOMMU resources allocated when the command
+ *	was mapped originally as part of initio_build_scb
+ */
+
+static void i91u_unmap_scb(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
 {
 	/* auto sense buffer */
 	if (cmnd->SCp.ptr) {
@@ -3058,65 +2742,63 @@
 	}
 
 	/* request buffer */
-	if (cmnd->use_sg) {
+	if (scsi_sg_count(cmnd)) {
 		dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
-				 sizeof(struct SG_Struc) * TOTAL_SG_ENTRY,
+				 sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
 				 DMA_BIDIRECTIONAL);
 
-		dma_unmap_sg(&pci_dev->dev, cmnd->request_buffer,
-			     cmnd->use_sg,
-			     cmnd->sc_data_direction);
-	} else if (cmnd->request_bufflen) {
-		dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
-				 cmnd->request_bufflen,
-				 cmnd->sc_data_direction);
+		scsi_dma_unmap(cmnd);
 	}
 }
 
-/*****************************************************************************
- Function name  : i91uSCBPost
- Description    : This is callback routine be called when tulip finish one
-			SCSI command.
- Input          : pHCB  -       Pointer to host adapter control block.
-		  pSCB  -       Pointer to SCSI control block.
- Output         : None.
- Return         : None.
-*****************************************************************************/
-static void i91uSCBPost(BYTE * pHcb, BYTE * pScb)
+/**
+ *	i91uSCBPost		-	SCSI callback
+ *	@host: Pointer to host adapter control block.
+ *	@cmnd: Pointer to SCSI control block.
+ *
+ *	This is callback routine be called when tulip finish one
+ *	SCSI command.
+ */
+
+static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem)
 {
-	struct scsi_cmnd *pSRB;	/* Pointer to SCSI request block */
-	HCS *pHCB;
-	SCB *pSCB;
+	struct scsi_cmnd *cmnd;	/* Pointer to SCSI request block */
+	struct initio_host *host;
+	struct scsi_ctrl_blk *cblk;
 
-	pHCB = (HCS *) pHcb;
-	pSCB = (SCB *) pScb;
-	if ((pSRB = pSCB->SCB_Srb) == 0) {
-		printk("i91uSCBPost: SRB pointer is empty\n");
-
-		tul_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
+	host = (struct initio_host *) host_mem;
+	cblk = (struct scsi_ctrl_blk *) cblk_mem;
+	if ((cmnd = cblk->srb) == NULL) {
+		printk(KERN_ERR "i91uSCBPost: SRB pointer is empty\n");
+		WARN_ON(1);
+		initio_release_scb(host, cblk);	/* Release SCB for current channel */
 		return;
 	}
-	switch (pSCB->SCB_HaStat) {
+
+	/*
+	 *	Remap the firmware error status into a mid layer one
+	 */
+	switch (cblk->hastat) {
 	case 0x0:
 	case 0xa:		/* Linked command complete without error and linked normally */
 	case 0xb:		/* Linked command complete without error interrupt generated */
-		pSCB->SCB_HaStat = 0;
+		cblk->hastat = 0;
 		break;
 
 	case 0x11:		/* Selection time out-The initiator selection or target
 				   reselection was not complete within the SCSI Time out period */
-		pSCB->SCB_HaStat = DID_TIME_OUT;
+		cblk->hastat = DID_TIME_OUT;
 		break;
 
 	case 0x14:		/* Target bus phase sequence failure-An invalid bus phase or bus
 				   phase sequence was requested by the target. The host adapter
 				   will generate a SCSI Reset Condition, notifying the host with
 				   a SCRD interrupt */
-		pSCB->SCB_HaStat = DID_RESET;
+		cblk->hastat = DID_RESET;
 		break;
 
 	case 0x1a:		/* SCB Aborted. 07/21/98 */
-		pSCB->SCB_HaStat = DID_ABORT;
+		cblk->hastat = DID_ABORT;
 		break;
 
 	case 0x12:		/* Data overrun/underrun-The target attempted to transfer more data
@@ -3126,49 +2808,196 @@
 	case 0x16:		/* Invalid SCB Operation Code. */
 
 	default:
-		printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
-		pSCB->SCB_HaStat = DID_ERROR;	/* Couldn't find any better */
+		printk("ini9100u: %x %x\n", cblk->hastat, cblk->tastat);
+		cblk->hastat = DID_ERROR;	/* Couldn't find any better */
 		break;
 	}
 
-	pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
+	cmnd->result = cblk->tastat | (cblk->hastat << 16);
+	WARN_ON(cmnd == NULL);
+	i91u_unmap_scb(host->pci_dev, cmnd);
+	cmnd->scsi_done(cmnd);	/* Notify system DONE           */
+	initio_release_scb(host, cblk);	/* Release SCB for current channel */
+}
 
-	if (pSRB == NULL) {
-		printk("pSRB is NULL\n");
+static struct scsi_host_template initio_template = {
+	.proc_name		= "INI9100U",
+	.name			= "Initio INI-9X00U/UW SCSI device driver",
+	.queuecommand		= i91u_queuecommand,
+	.eh_bus_reset_handler	= i91u_bus_reset,
+	.bios_param		= i91u_biosparam,
+	.can_queue		= MAX_TARGETS * i91u_MAXQUEUE,
+	.this_id		= 1,
+	.sg_tablesize		= SG_ALL,
+	.cmd_per_lun		= 1,
+	.use_clustering		= ENABLE_CLUSTERING,
+};
+
+static int initio_probe_one(struct pci_dev *pdev,
+	const struct pci_device_id *id)
+{
+	struct Scsi_Host *shost;
+	struct initio_host *host;
+	u32 reg;
+	u16 bios_seg;
+	struct scsi_ctrl_blk *scb, *tmp, *prev = NULL /* silence gcc */;
+	int num_scb, i, error;
+
+	error = pci_enable_device(pdev);
+	if (error)
+		return error;
+
+	pci_read_config_dword(pdev, 0x44, (u32 *) & reg);
+	bios_seg = (u16) (reg & 0xFF);
+	if (((reg & 0xFF00) >> 8) == 0xFF)
+		reg = 0;
+	bios_seg = (bios_seg << 8) + ((u16) ((reg & 0xFF00) >> 8));
+
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+		printk(KERN_WARNING  "i91u: Could not set 32 bit DMA mask\n");
+		error = -ENODEV;
+		goto out_disable_device;
+	}
+	shost = scsi_host_alloc(&initio_template, sizeof(struct initio_host));
+	if (!shost) {
+		printk(KERN_WARNING "initio: Could not allocate host structure.\n");
+		error = -ENOMEM;
+		goto out_disable_device;
+	}
+	host = (struct initio_host *)shost->hostdata;
+	memset(host, 0, sizeof(struct initio_host));
+
+	if (!request_region(host->addr, 256, "i91u")) {
+		printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr);
+		error = -ENODEV;
+		goto out_host_put;
 	}
 
-	i91u_unmap_cmnd(pHCB->pci_dev, pSRB);
-	pSRB->scsi_done(pSRB);	/* Notify system DONE           */
+	if (initio_tag_enable)	/* 1.01i */
+		num_scb = MAX_TARGETS * i91u_MAXQUEUE;
+	else
+		num_scb = MAX_TARGETS + 3;	/* 1-tape, 1-CD_ROM, 1- extra */
 
-	tul_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
-}
+	for (; num_scb >= MAX_TARGETS + 3; num_scb--) {
+		i = num_scb * sizeof(struct scsi_ctrl_blk);
+		if ((scb = kzalloc(i, GFP_DMA)) != NULL)
+			break;
+	}
 
-/*
- * Release ressources
- */
-static int i91u_release(struct Scsi_Host *hreg)
-{
-	free_irq(hreg->irq, hreg);
-	release_region(hreg->io_port, 256);
+	if (!scb) {
+		printk(KERN_WARNING "initio: Cannot allocate SCB array.\n");
+		error = -ENOMEM;
+		goto out_release_region;
+	}
+
+	host->num_scbs = num_scb;
+	host->scb = scb;
+	host->next_pending = scb;
+	host->next_avail = scb;
+	for (i = 0, tmp = scb; i < num_scb; i++, tmp++) {
+		tmp->tagid = i;
+		if (i != 0)
+			prev->next = tmp;
+		prev = tmp;
+	}
+	prev->next = NULL;
+	host->scb_end = tmp;
+	host->first_avail = scb;
+	host->last_avail = prev;
+
+	initio_init(host, phys_to_virt(bios_seg << 4));
+
+	host->jsstatus0 = 0;
+
+	shost->io_port = host->addr;
+	shost->n_io_port = 0xff;
+	shost->can_queue = num_scb;		/* 03/05/98                      */
+	shost->unique_id = host->addr;
+	shost->max_id = host->max_tar;
+	shost->max_lun = 32;	/* 10/21/97                     */
+	shost->irq = pdev->irq;
+	shost->this_id = host->scsi_id;	/* Assign HCS index           */
+	shost->base = host->addr;
+	shost->sg_tablesize = TOTAL_SG_ENTRY;
+
+	error = request_irq(pdev->irq, i91u_intr, IRQF_DISABLED|IRQF_SHARED, "i91u", shost);
+	if (error < 0) {
+		printk(KERN_WARNING "initio: Unable to request IRQ %d\n", pdev->irq);
+		goto out_free_scbs;
+	}
+
+	pci_set_drvdata(pdev, shost);
+	host->pci_dev = pdev;
+
+	error = scsi_add_host(shost, &pdev->dev);
+	if (error)
+		goto out_free_irq;
+	scsi_scan_host(shost);
 	return 0;
+out_free_irq:
+	free_irq(pdev->irq, shost);
+out_free_scbs:
+	kfree(host->scb);
+out_release_region:
+	release_region(host->addr, 256);
+out_host_put:
+	scsi_host_put(shost);
+out_disable_device:
+	pci_disable_device(pdev);
+	return error;
 }
-MODULE_LICENSE("Dual BSD/GPL");
 
-static struct scsi_host_template driver_template = {
-	.proc_name	= "INI9100U",
-	.name		= i91u_REVID,
-	.detect		= i91u_detect,
-	.release	= i91u_release,
-	.queuecommand	= i91u_queuecommand,
-//	.abort		= i91u_abort,
-//	.reset		= i91u_reset,
-	.eh_bus_reset_handler = i91u_bus_reset,
-	.bios_param	= i91u_biosparam,
-	.can_queue	= 1,
-	.this_id	= 1,
-	.sg_tablesize	= SG_ALL,
-	.cmd_per_lun 	= 1,
-	.use_clustering	= ENABLE_CLUSTERING,
+/**
+ *	initio_remove_one	-	control shutdown
+ *	@pdev:	PCI device being released
+ *
+ *	Release the resources assigned to this adapter after it has
+ *	finished being used.
+ */
+
+static void initio_remove_one(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct initio_host *s = (struct initio_host *)host->hostdata;
+	scsi_remove_host(host);
+	free_irq(pdev->irq, host);
+	release_region(s->addr, 256);
+	scsi_host_put(host);
+	pci_disable_device(pdev);
+}
+
+MODULE_LICENSE("GPL");
+
+static struct pci_device_id initio_pci_tbl[] = {
+	{PCI_VENDOR_ID_INIT, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_INIT, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_INIT, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_INIT, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_DOMEX, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
 };
-#include "scsi_module.c"
+MODULE_DEVICE_TABLE(pci, initio_pci_tbl);
 
+static struct pci_driver initio_pci_driver = {
+	.name		= "initio",
+	.id_table	= initio_pci_tbl,
+	.probe		= initio_probe_one,
+	.remove		= __devexit_p(initio_remove_one),
+};
+
+static int __init initio_init_driver(void)
+{
+	return pci_register_driver(&initio_pci_driver);
+}
+
+static void __exit initio_exit_driver(void)
+{
+	pci_unregister_driver(&initio_pci_driver);
+}
+
+MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");
+MODULE_AUTHOR("Initio Corporation");
+MODULE_LICENSE("GPL");
+
+module_init(initio_init_driver);
+module_exit(initio_exit_driver);
diff --git a/drivers/scsi/initio.h b/drivers/scsi/initio.h
index acb67a4..cb48efa 100644
--- a/drivers/scsi/initio.h
+++ b/drivers/scsi/initio.h
@@ -4,6 +4,8 @@
  * Copyright (c) 1994-1998 Initio Corporation
  * All rights reserved.
  *
+ * Cleanups (c) Copyright 2007 Red Hat <alan@redhat.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -18,27 +20,6 @@
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * --------------------------------------------------------------------------
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of 
- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -56,17 +37,6 @@
 
 #include <linux/types.h>
 
-#define ULONG   unsigned long
-#define USHORT  unsigned short
-#define UCHAR   unsigned char
-#define BYTE    unsigned char
-#define WORD    unsigned short
-#define DWORD   unsigned long
-#define UBYTE   unsigned char
-#define UWORD   unsigned short
-#define UDWORD  unsigned long
-#define U32     u32
-
 #define TOTAL_SG_ENTRY		32
 #define MAX_SUPPORTED_ADAPTERS  8
 #define MAX_OFFSET		15
@@ -368,55 +338,55 @@
 /************************************************************************/
 /*              Scatter-Gather Element Structure                        */
 /************************************************************************/
-typedef struct SG_Struc {
-	U32 SG_Ptr;		/* Data Pointer */
-	U32 SG_Len;		/* Data Length */
-} SG;
+struct sg_entry {
+	u32 data;		/* Data Pointer */
+	u32 len;		/* Data Length */
+};
 
 /***********************************************************************
 		SCSI Control Block
 ************************************************************************/
-typedef struct Scsi_Ctrl_Blk {
-	struct Scsi_Ctrl_Blk *SCB_NxtScb;
-	UBYTE SCB_Status;	/*4 */
-	UBYTE SCB_NxtStat;	/*5 */
-	UBYTE SCB_Mode;		/*6 */
-	UBYTE SCB_Msgin;	/*7 SCB_Res0 */
-	UWORD SCB_SGIdx;	/*8 */
-	UWORD SCB_SGMax;	/*A */
+struct scsi_ctrl_blk {
+	struct scsi_ctrl_blk *next;
+	u8 status;	/*4 */
+	u8 next_state;	/*5 */
+	u8 mode;		/*6 */
+	u8 msgin;	/*7 SCB_Res0 */
+	u16 sgidx;	/*8 */
+	u16 sgmax;	/*A */
 #ifdef ALPHA
-	U32 SCB_Reserved[2];	/*C */
+	u32 reserved[2];	/*C */
 #else
-	U32 SCB_Reserved[3];	/*C */
+	u32 reserved[3];	/*C */
 #endif
 
-	U32 SCB_XferLen;	/*18 Current xfer len           */
-	U32 SCB_TotXLen;	/*1C Total xfer len             */
-	U32 SCB_PAddr;		/*20 SCB phy. Addr. */
+	u32 xferlen;	/*18 Current xfer len           */
+	u32 totxlen;	/*1C Total xfer len             */
+	u32 paddr;		/*20 SCB phy. Addr. */
 
-	UBYTE SCB_Opcode;	/*24 SCB command code */
-	UBYTE SCB_Flags;	/*25 SCB Flags */
-	UBYTE SCB_Target;	/*26 Target Id */
-	UBYTE SCB_Lun;		/*27 Lun */
-	U32 SCB_BufPtr;		/*28 Data Buffer Pointer */
-	U32 SCB_BufLen;		/*2C Data Allocation Length */
-	UBYTE SCB_SGLen;	/*30 SG list # */
-	UBYTE SCB_SenseLen;	/*31 Sense Allocation Length */
-	UBYTE SCB_HaStat;	/*32 */
-	UBYTE SCB_TaStat;	/*33 */
-	UBYTE SCB_CDBLen;	/*34 CDB Length */
-	UBYTE SCB_Ident;	/*35 Identify */
-	UBYTE SCB_TagMsg;	/*36 Tag Message */
-	UBYTE SCB_TagId;	/*37 Queue Tag */
-	UBYTE SCB_CDB[12];	/*38 */
-	U32 SCB_SGPAddr;	/*44 SG List/Sense Buf phy. Addr. */
-	U32 SCB_SensePtr;	/*48 Sense data pointer */
-	void (*SCB_Post) (BYTE *, BYTE *);	/*4C POST routine */
-	struct scsi_cmnd *SCB_Srb;	/*50 SRB Pointer */
-	SG SCB_SGList[TOTAL_SG_ENTRY];	/*54 Start of SG list */
-} SCB;
+	u8 opcode;	/*24 SCB command code */
+	u8 flags;	/*25 SCB Flags */
+	u8 target;	/*26 Target Id */
+	u8 lun;		/*27 Lun */
+	u32 bufptr;		/*28 Data Buffer Pointer */
+	u32 buflen;		/*2C Data Allocation Length */
+	u8 sglen;	/*30 SG list # */
+	u8 senselen;	/*31 Sense Allocation Length */
+	u8 hastat;	/*32 */
+	u8 tastat;	/*33 */
+	u8 cdblen;	/*34 CDB Length */
+	u8 ident;	/*35 Identify */
+	u8 tagmsg;	/*36 Tag Message */
+	u8 tagid;	/*37 Queue Tag */
+	u8 cdb[12];	/*38 */
+	u32 sgpaddr;	/*44 SG List/Sense Buf phy. Addr. */
+	u32 senseptr;	/*48 Sense data pointer */
+	void (*post) (u8 *, u8 *);	/*4C POST routine */
+	struct scsi_cmnd *srb;	/*50 SRB Pointer */
+	struct sg_entry sglist[TOTAL_SG_ENTRY];	/*54 Start of SG list */
+};
 
-/* Bit Definition for SCB_Status */
+/* Bit Definition for status */
 #define SCB_RENT        0x01
 #define SCB_PEND        0x02
 #define SCB_CONTIG      0x04	/* Contigent Allegiance */
@@ -425,17 +395,17 @@
 #define SCB_DONE        0x20
 
 
-/* Opcodes of SCB_Opcode */
+/* Opcodes for opcode */
 #define ExecSCSI        0x1
 #define BusDevRst       0x2
 #define AbortCmd        0x3
 
 
-/* Bit Definition for SCB_Mode */
+/* Bit Definition for mode */
 #define SCM_RSENS       0x01	/* request sense mode */
 
 
-/* Bit Definition for SCB_Flags */
+/* Bit Definition for flags */
 #define SCF_DONE        0x01
 #define SCF_POST        0x02
 #define SCF_SENSE       0x04
@@ -492,15 +462,14 @@
 		Target Device Control Structure
 **********************************************************************/
 
-typedef struct Tar_Ctrl_Struc {
-	UWORD TCS_Flags;	/* 0 */
-	UBYTE TCS_JS_Period;	/* 2 */
-	UBYTE TCS_SConfig0;	/* 3 */
-
-	UWORD TCS_DrvFlags;	/* 4 */
-	UBYTE TCS_DrvHead;	/* 6 */
-	UBYTE TCS_DrvSector;	/* 7 */
-} TCS;
+struct target_control {
+	u16 flags;
+	u8 js_period;
+	u8 sconfig0;
+	u16 drv_flags;
+	u8 heads;
+	u8 sectors;
+};
 
 /***********************************************************************
 		Target Device Control Structure
@@ -523,62 +492,53 @@
 #define TCF_DRV_EN_TAG          0x0800
 #define TCF_DRV_255_63          0x0400
 
-typedef struct I91u_Adpt_Struc {
-	UWORD ADPT_BIOS;	/* 0 */
-	UWORD ADPT_BASE;	/* 1 */
-	UBYTE ADPT_Bus;		/* 2 */
-	UBYTE ADPT_Device;	/* 3 */
-	UBYTE ADPT_INTR;	/* 4 */
-} INI_ADPT_STRUCT;
-
-
 /***********************************************************************
 	      Host Adapter Control Structure
 ************************************************************************/
-typedef struct Ha_Ctrl_Struc {
-	UWORD HCS_Base;		/* 00 */
-	UWORD HCS_BIOS;		/* 02 */
-	UBYTE HCS_Intr;		/* 04 */
-	UBYTE HCS_SCSI_ID;	/* 05 */
-	UBYTE HCS_MaxTar;	/* 06 */
-	UBYTE HCS_NumScbs;	/* 07 */
+struct initio_host {
+	u16 addr;		/* 00 */
+	u16 bios_addr;		/* 02 */
+	u8 irq;			/* 04 */
+	u8 scsi_id;		/* 05 */
+	u8 max_tar;		/* 06 */
+	u8 num_scbs;		/* 07 */
 
-	UBYTE HCS_Flags;	/* 08 */
-	UBYTE HCS_Index;	/* 09 */
-	UBYTE HCS_HaId;		/* 0A */
-	UBYTE HCS_Config;	/* 0B */
-	UWORD HCS_IdMask;	/* 0C */
-	UBYTE HCS_Semaph;	/* 0E */
-	UBYTE HCS_Phase;	/* 0F */
-	UBYTE HCS_JSStatus0;	/* 10 */
-	UBYTE HCS_JSInt;	/* 11 */
-	UBYTE HCS_JSStatus1;	/* 12 */
-	UBYTE HCS_SConf1;	/* 13 */
+	u8 flags;		/* 08 */
+	u8 index;		/* 09 */
+	u8 ha_id;		/* 0A */
+	u8 config;		/* 0B */
+	u16 idmask;		/* 0C */
+	u8 semaph;		/* 0E */
+	u8 phase;		/* 0F */
+	u8 jsstatus0;		/* 10 */
+	u8 jsint;		/* 11 */
+	u8 jsstatus1;		/* 12 */
+	u8 sconf1;		/* 13 */
 
-	UBYTE HCS_Msg[8];	/* 14 */
-	SCB *HCS_NxtAvail;	/* 1C */
-	SCB *HCS_Scb;		/* 20 */
-	SCB *HCS_ScbEnd;	/* 24 */
-	SCB *HCS_NxtPend;	/* 28 */
-	SCB *HCS_NxtContig;	/* 2C */
-	SCB *HCS_ActScb;	/* 30 */
-	TCS *HCS_ActTcs;	/* 34 */
+	u8 msg[8];		/* 14 */
+	struct scsi_ctrl_blk *next_avail;	/* 1C */
+	struct scsi_ctrl_blk *scb;		/* 20 */
+	struct scsi_ctrl_blk *scb_end;		/* 24 */ /*UNUSED*/
+	struct scsi_ctrl_blk *next_pending;	/* 28 */
+	struct scsi_ctrl_blk *next_contig;	/* 2C */ /*UNUSED*/
+	struct scsi_ctrl_blk *active;		/* 30 */
+	struct target_control *active_tc;	/* 34 */
 
-	SCB *HCS_FirstAvail;	/* 38 */
-	SCB *HCS_LastAvail;	/* 3C */
-	SCB *HCS_FirstPend;	/* 40 */
-	SCB *HCS_LastPend;	/* 44 */
-	SCB *HCS_FirstBusy;	/* 48 */
-	SCB *HCS_LastBusy;	/* 4C */
-	SCB *HCS_FirstDone;	/* 50 */
-	SCB *HCS_LastDone;	/* 54 */
-	UBYTE HCS_MaxTags[16];	/* 58 */
-	UBYTE HCS_ActTags[16];	/* 68 */
-	TCS HCS_Tcs[MAX_TARGETS];	/* 78 */
-	spinlock_t HCS_AvailLock;
-	spinlock_t HCS_SemaphLock;
+	struct scsi_ctrl_blk *first_avail;	/* 38 */
+	struct scsi_ctrl_blk *last_avail;	/* 3C */
+	struct scsi_ctrl_blk *first_pending;	/* 40 */
+	struct scsi_ctrl_blk *last_pending;	/* 44 */
+	struct scsi_ctrl_blk *first_busy;	/* 48 */
+	struct scsi_ctrl_blk *last_busy;	/* 4C */
+	struct scsi_ctrl_blk *first_done;	/* 50 */
+	struct scsi_ctrl_blk *last_done;	/* 54 */
+	u8 max_tags[16];	/* 58 */
+	u8 act_tags[16];	/* 68 */
+	struct target_control targets[MAX_TARGETS];	/* 78 */
+	spinlock_t avail_lock;
+	spinlock_t semaph_lock;
 	struct pci_dev *pci_dev;
-} HCS;
+};
 
 /* Bit Definition for HCB_Config */
 #define HCC_SCSI_RESET          0x01
@@ -599,47 +559,47 @@
 *******************************************************************/
 
 typedef struct _NVRAM_SCSI {	/* SCSI channel configuration   */
-	UCHAR NVM_ChSCSIID;	/* 0Ch -> Channel SCSI ID       */
-	UCHAR NVM_ChConfig1;	/* 0Dh -> Channel config 1      */
-	UCHAR NVM_ChConfig2;	/* 0Eh -> Channel config 2      */
-	UCHAR NVM_NumOfTarg;	/* 0Fh -> Number of SCSI target */
+	u8 NVM_ChSCSIID;	/* 0Ch -> Channel SCSI ID       */
+	u8 NVM_ChConfig1;	/* 0Dh -> Channel config 1      */
+	u8 NVM_ChConfig2;	/* 0Eh -> Channel config 2      */
+	u8 NVM_NumOfTarg;	/* 0Fh -> Number of SCSI target */
 	/* SCSI target configuration    */
-	UCHAR NVM_Targ0Config;	/* 10h -> Target 0 configuration */
-	UCHAR NVM_Targ1Config;	/* 11h -> Target 1 configuration */
-	UCHAR NVM_Targ2Config;	/* 12h -> Target 2 configuration */
-	UCHAR NVM_Targ3Config;	/* 13h -> Target 3 configuration */
-	UCHAR NVM_Targ4Config;	/* 14h -> Target 4 configuration */
-	UCHAR NVM_Targ5Config;	/* 15h -> Target 5 configuration */
-	UCHAR NVM_Targ6Config;	/* 16h -> Target 6 configuration */
-	UCHAR NVM_Targ7Config;	/* 17h -> Target 7 configuration */
-	UCHAR NVM_Targ8Config;	/* 18h -> Target 8 configuration */
-	UCHAR NVM_Targ9Config;	/* 19h -> Target 9 configuration */
-	UCHAR NVM_TargAConfig;	/* 1Ah -> Target A configuration */
-	UCHAR NVM_TargBConfig;	/* 1Bh -> Target B configuration */
-	UCHAR NVM_TargCConfig;	/* 1Ch -> Target C configuration */
-	UCHAR NVM_TargDConfig;	/* 1Dh -> Target D configuration */
-	UCHAR NVM_TargEConfig;	/* 1Eh -> Target E configuration */
-	UCHAR NVM_TargFConfig;	/* 1Fh -> Target F configuration */
+	u8 NVM_Targ0Config;	/* 10h -> Target 0 configuration */
+	u8 NVM_Targ1Config;	/* 11h -> Target 1 configuration */
+	u8 NVM_Targ2Config;	/* 12h -> Target 2 configuration */
+	u8 NVM_Targ3Config;	/* 13h -> Target 3 configuration */
+	u8 NVM_Targ4Config;	/* 14h -> Target 4 configuration */
+	u8 NVM_Targ5Config;	/* 15h -> Target 5 configuration */
+	u8 NVM_Targ6Config;	/* 16h -> Target 6 configuration */
+	u8 NVM_Targ7Config;	/* 17h -> Target 7 configuration */
+	u8 NVM_Targ8Config;	/* 18h -> Target 8 configuration */
+	u8 NVM_Targ9Config;	/* 19h -> Target 9 configuration */
+	u8 NVM_TargAConfig;	/* 1Ah -> Target A configuration */
+	u8 NVM_TargBConfig;	/* 1Bh -> Target B configuration */
+	u8 NVM_TargCConfig;	/* 1Ch -> Target C configuration */
+	u8 NVM_TargDConfig;	/* 1Dh -> Target D configuration */
+	u8 NVM_TargEConfig;	/* 1Eh -> Target E configuration */
+	u8 NVM_TargFConfig;	/* 1Fh -> Target F configuration */
 } NVRAM_SCSI;
 
 typedef struct _NVRAM {
 /*----------header ---------------*/
-	USHORT NVM_Signature;	/* 0,1: Signature */
-	UCHAR NVM_Size;		/* 2:   Size of data structure */
-	UCHAR NVM_Revision;	/* 3:   Revision of data structure */
+	u16 NVM_Signature;	/* 0,1: Signature */
+	u8 NVM_Size;		/* 2:   Size of data structure */
+	u8 NVM_Revision;	/* 3:   Revision of data structure */
 	/* ----Host Adapter Structure ---- */
-	UCHAR NVM_ModelByte0;	/* 4:   Model number (byte 0) */
-	UCHAR NVM_ModelByte1;	/* 5:   Model number (byte 1) */
-	UCHAR NVM_ModelInfo;	/* 6:   Model information         */
-	UCHAR NVM_NumOfCh;	/* 7:   Number of SCSI channel */
-	UCHAR NVM_BIOSConfig1;	/* 8:   BIOS configuration 1  */
-	UCHAR NVM_BIOSConfig2;	/* 9:   BIOS configuration 2  */
-	UCHAR NVM_HAConfig1;	/* A:   Hoat adapter configuration 1 */
-	UCHAR NVM_HAConfig2;	/* B:   Hoat adapter configuration 2 */
+	u8 NVM_ModelByte0;	/* 4:   Model number (byte 0) */
+	u8 NVM_ModelByte1;	/* 5:   Model number (byte 1) */
+	u8 NVM_ModelInfo;	/* 6:   Model information         */
+	u8 NVM_NumOfCh;	/* 7:   Number of SCSI channel */
+	u8 NVM_BIOSConfig1;	/* 8:   BIOS configuration 1  */
+	u8 NVM_BIOSConfig2;	/* 9:   BIOS configuration 2  */
+	u8 NVM_HAConfig1;	/* A:   Hoat adapter configuration 1 */
+	u8 NVM_HAConfig2;	/* B:   Hoat adapter configuration 2 */
 	NVRAM_SCSI NVM_SCSIInfo[2];
-	UCHAR NVM_reserved[10];
+	u8 NVM_reserved[10];
 	/* ---------- CheckSum ----------       */
-	USHORT NVM_CheckSum;	/* 0x3E, 0x3F: Checksum of NVRam        */
+	u16 NVM_CheckSum;	/* 0x3E, 0x3F: Checksum of NVRam        */
 } NVRAM, *PNVRAM;
 
 /* Bios Configuration for nvram->BIOSConfig1                            */
@@ -681,19 +641,6 @@
 #define DISC_ALLOW              0xC0	/* Disconnect is allowed        */
 #define SCSICMD_RequestSense    0x03
 
-typedef struct _HCSinfo {
-	ULONG base;
-	UCHAR vec;
-	UCHAR bios;		/* High byte of BIOS address */
-	USHORT BaseAndBios;	/* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */
-} HCSINFO;
-
-#define TUL_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)(x+y)) ))
-#define TUL_RDLONG(x,y)         (ULONG)(inl((int)((ULONG)(x+y)) ))
-#define TUL_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
-#define TUL_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
-#define TUL_WRLONG( adr,data)   outl( (ULONG)(data), (int)(adr))
-
 #define SCSI_ABORT_SNOOZE 0
 #define SCSI_ABORT_SUCCESS 1
 #define SCSI_ABORT_PENDING 2
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 4baa79e..f142eaf 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -540,32 +540,6 @@
 }
 
 /**
- * ipr_unmap_sglist - Unmap scatterlist if mapped
- * @ioa_cfg:	ioa config struct
- * @ipr_cmd:	ipr command struct
- *
- * Return value:
- * 	nothing
- **/
-static void ipr_unmap_sglist(struct ipr_ioa_cfg *ioa_cfg,
-			     struct ipr_cmnd *ipr_cmd)
-{
-	struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
-
-	if (ipr_cmd->dma_use_sg) {
-		if (scsi_cmd->use_sg > 0) {
-			pci_unmap_sg(ioa_cfg->pdev, scsi_cmd->request_buffer,
-				     scsi_cmd->use_sg,
-				     scsi_cmd->sc_data_direction);
-		} else {
-			pci_unmap_single(ioa_cfg->pdev, ipr_cmd->dma_handle,
-					 scsi_cmd->request_bufflen,
-					 scsi_cmd->sc_data_direction);
-		}
-	}
-}
-
-/**
  * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts
  * @ioa_cfg:	ioa config struct
  * @clr_ints:     interrupts to clear
@@ -677,7 +651,7 @@
 
 	scsi_cmd->result |= (DID_ERROR << 16);
 
-	ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+	scsi_dma_unmap(ipr_cmd->scsi_cmd);
 	scsi_cmd->scsi_done(scsi_cmd);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 }
@@ -2465,6 +2439,7 @@
 /**
  * ipr_read_trace - Dump the adapter trace
  * @kobj:		kobject struct
+ * @bin_attr:		bin_attribute struct
  * @buf:		buffer
  * @off:		offset
  * @count:		buffer size
@@ -2472,8 +2447,9 @@
  * Return value:
  *	number of bytes printed to buffer
  **/
-static ssize_t ipr_read_trace(struct kobject *kobj, char *buf,
-			      loff_t off, size_t count)
+static ssize_t ipr_read_trace(struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t off, size_t count)
 {
 	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *shost = class_to_shost(cdev);
@@ -3166,6 +3142,7 @@
 /**
  * ipr_read_dump - Dump the adapter
  * @kobj:		kobject struct
+ * @bin_attr:		bin_attribute struct
  * @buf:		buffer
  * @off:		offset
  * @count:		buffer size
@@ -3173,8 +3150,9 @@
  * Return value:
  *	number of bytes printed to buffer
  **/
-static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
-			      loff_t off, size_t count)
+static ssize_t ipr_read_dump(struct kobject *kobj,
+			     struct bin_attribute *bin_attr,
+			     char *buf, loff_t off, size_t count)
 {
 	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *shost = class_to_shost(cdev);
@@ -3327,6 +3305,7 @@
 /**
  * ipr_write_dump - Setup dump state of adapter
  * @kobj:		kobject struct
+ * @bin_attr:		bin_attribute struct
  * @buf:		buffer
  * @off:		offset
  * @count:		buffer size
@@ -3334,8 +3313,9 @@
  * Return value:
  *	number of bytes printed to buffer
  **/
-static ssize_t ipr_write_dump(struct kobject *kobj, char *buf,
-			      loff_t off, size_t count)
+static ssize_t ipr_write_dump(struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t off, size_t count)
 {
 	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *shost = class_to_shost(cdev);
@@ -3954,6 +3934,13 @@
 		spin_unlock_irq(scsi_cmd->device->host->host_lock);
 		ata_do_eh(ap, NULL, NULL, ipr_sata_reset, NULL);
 		spin_lock_irq(scsi_cmd->device->host->host_lock);
+
+		list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
+			if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) {
+				rc = -EIO;
+				break;
+			}
+		}
 	} else
 		rc = ipr_device_reset(ioa_cfg, res);
 	res->resetting_device = 0;
@@ -4285,93 +4272,55 @@
 static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
 			   struct ipr_cmnd *ipr_cmd)
 {
-	int i;
-	struct scatterlist *sglist;
+	int i, nseg;
+	struct scatterlist *sg;
 	u32 length;
 	u32 ioadl_flags = 0;
 	struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
 	struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
 	struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
 
-	length = scsi_cmd->request_bufflen;
-
-	if (length == 0)
+	length = scsi_bufflen(scsi_cmd);
+	if (!length)
 		return 0;
 
-	if (scsi_cmd->use_sg) {
-		ipr_cmd->dma_use_sg = pci_map_sg(ioa_cfg->pdev,
-						 scsi_cmd->request_buffer,
-						 scsi_cmd->use_sg,
-						 scsi_cmd->sc_data_direction);
-
-		if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
-			ioadl_flags = IPR_IOADL_FLAGS_WRITE;
-			ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
-			ioarcb->write_data_transfer_length = cpu_to_be32(length);
-			ioarcb->write_ioadl_len =
-				cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
-		} else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
-			ioadl_flags = IPR_IOADL_FLAGS_READ;
-			ioarcb->read_data_transfer_length = cpu_to_be32(length);
-			ioarcb->read_ioadl_len =
-				cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
-		}
-
-		sglist = scsi_cmd->request_buffer;
-
-		if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
-			ioadl = ioarcb->add_data.u.ioadl;
-			ioarcb->write_ioadl_addr =
-				cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
-					    offsetof(struct ipr_ioarcb, add_data));
-			ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
-		}
-
-		for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
-			ioadl[i].flags_and_data_len =
-				cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
-			ioadl[i].address =
-				cpu_to_be32(sg_dma_address(&sglist[i]));
-		}
-
-		if (likely(ipr_cmd->dma_use_sg)) {
-			ioadl[i-1].flags_and_data_len |=
-				cpu_to_be32(IPR_IOADL_FLAGS_LAST);
-			return 0;
-		} else
-			dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
-	} else {
-		if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
-			ioadl_flags = IPR_IOADL_FLAGS_WRITE;
-			ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
-			ioarcb->write_data_transfer_length = cpu_to_be32(length);
-			ioarcb->write_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
-		} else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
-			ioadl_flags = IPR_IOADL_FLAGS_READ;
-			ioarcb->read_data_transfer_length = cpu_to_be32(length);
-			ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
-		}
-
-		ipr_cmd->dma_handle = pci_map_single(ioa_cfg->pdev,
-						     scsi_cmd->request_buffer, length,
-						     scsi_cmd->sc_data_direction);
-
-		if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
-			ioadl = ioarcb->add_data.u.ioadl;
-			ioarcb->write_ioadl_addr =
-				cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
-					    offsetof(struct ipr_ioarcb, add_data));
-			ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
-			ipr_cmd->dma_use_sg = 1;
-			ioadl[0].flags_and_data_len =
-				cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
-			ioadl[0].address = cpu_to_be32(ipr_cmd->dma_handle);
-			return 0;
-		} else
-			dev_err(&ioa_cfg->pdev->dev, "pci_map_single failed!\n");
+	nseg = scsi_dma_map(scsi_cmd);
+	if (nseg < 0) {
+		dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+		return -1;
 	}
 
-	return -1;
+	ipr_cmd->dma_use_sg = nseg;
+
+	if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
+		ioadl_flags = IPR_IOADL_FLAGS_WRITE;
+		ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
+		ioarcb->write_data_transfer_length = cpu_to_be32(length);
+		ioarcb->write_ioadl_len =
+			cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+	} else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
+		ioadl_flags = IPR_IOADL_FLAGS_READ;
+		ioarcb->read_data_transfer_length = cpu_to_be32(length);
+		ioarcb->read_ioadl_len =
+			cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+	}
+
+	if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
+		ioadl = ioarcb->add_data.u.ioadl;
+		ioarcb->write_ioadl_addr =
+			cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+				    offsetof(struct ipr_ioarcb, add_data));
+		ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+	}
+
+	scsi_for_each_sg(scsi_cmd, sg, ipr_cmd->dma_use_sg, i) {
+		ioadl[i].flags_and_data_len =
+			cpu_to_be32(ioadl_flags | sg_dma_len(sg));
+		ioadl[i].address = cpu_to_be32(sg_dma_address(sg));
+	}
+
+	ioadl[i-1].flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST);
+	return 0;
 }
 
 /**
@@ -4434,7 +4383,7 @@
 			res->needs_sync_complete = 1;
 		res->in_erp = 0;
 	}
-	ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+	scsi_dma_unmap(ipr_cmd->scsi_cmd);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 	scsi_cmd->scsi_done(scsi_cmd);
 }
@@ -4812,7 +4761,7 @@
 		break;
 	}
 
-	ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+	scsi_dma_unmap(ipr_cmd->scsi_cmd);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 	scsi_cmd->scsi_done(scsi_cmd);
 }
@@ -4833,10 +4782,10 @@
 	struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
 	u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 
-	scsi_cmd->resid = be32_to_cpu(ipr_cmd->ioasa.residual_data_len);
+	scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len));
 
 	if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
-		ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+		scsi_dma_unmap(ipr_cmd->scsi_cmd);
 		list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 		scsi_cmd->scsi_done(scsi_cmd);
 	} else
@@ -5360,18 +5309,12 @@
  **/
 static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
 {
-	u8 rev_id;
 	int i;
 
-	if (ioa_cfg->type == 0x5702) {
-		if (pci_read_config_byte(ioa_cfg->pdev, PCI_REVISION_ID,
-					 &rev_id) == PCIBIOS_SUCCESSFUL) {
-			if (rev_id < 4) {
-				for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){
-					if (__is_processor(ipr_blocked_processors[i]))
-						return 1;
-				}
-			}
+	if ((ioa_cfg->type == 0x5702) && (ioa_cfg->pdev->revision < 4)) {
+		for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){
+			if (__is_processor(ipr_blocked_processors[i]))
+				return 1;
 		}
 	}
 	return 0;
@@ -7528,13 +7471,7 @@
 	else
 		ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
 
-	rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &ioa_cfg->revid);
-
-	if (rc != PCIBIOS_SUCCESSFUL) {
-		dev_err(&pdev->dev, "Failed to read PCI revision ID\n");
-		rc = -EIO;
-		goto out_scsi_host_put;
-	}
+	ioa_cfg->revid = pdev->revision;
 
 	ipr_regs_pci = pci_resource_start(pdev, 0);
 
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 8b704f7..9f8ed6b 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -211,19 +211,6 @@
 #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
 #endif
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-#include <linux/blk.h>
-#include "sd.h"
-#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
-#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
-#ifndef __devexit_p
-#define __devexit_p(x) x
-#endif
-#else
-#define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
-#define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
-#endif
-
 #define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
                          DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \
                          PCI_DMA_BIDIRECTIONAL : \
@@ -381,24 +368,13 @@
 	.eh_abort_handler	= ips_eh_abort,
 	.eh_host_reset_handler	= ips_eh_reset,
 	.proc_name		= "ips",
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
 	.proc_info		= ips_proc_info,
 	.slave_configure	= ips_slave_configure,
-#else
-	.proc_info		= ips_proc24_info,
-	.select_queue_depths	= ips_select_queue_depth,
-#endif
 	.bios_param		= ips_biosparam,
 	.this_id		= -1,
 	.sg_tablesize		= IPS_MAX_SG,
 	.cmd_per_lun		= 3,
 	.use_clustering		= ENABLE_CLUSTERING,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	.use_new_eh_code	= 1,
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)  &&  LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-    .highmem_io          = 1,   
-#endif
 };
 
 
@@ -731,7 +707,7 @@
 	/* free IRQ */
 	free_irq(ha->irq, ha);
 
-	IPS_REMOVE_HOST(sh);
+	scsi_remove_host(sh);
 	scsi_host_put(sh);
 
 	ips_released_controllers++;
@@ -813,7 +789,6 @@
 	ips_ha_t *ha;
 	ips_copp_wait_item_t *item;
 	int ret;
-	unsigned long cpu_flags;
 	struct Scsi_Host *host;
 
 	METHOD_TRACE("ips_eh_abort", 1);
@@ -830,7 +805,7 @@
 	if (!ha->active)
 		return (FAILED);
 
-	IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+	spin_lock(host->host_lock);
 
 	/* See if the command is on the copp queue */
 	item = ha->copp_waitlist.head;
@@ -851,7 +826,7 @@
 		ret = (FAILED);
 	}
 
-	IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+	spin_unlock(host->host_lock);
 	return ret;
 }
 
@@ -1129,7 +1104,7 @@
 		/* A Reset IOCTL is only sent by the boot CD in extreme cases.           */
 		/* There can never be any system activity ( network or disk ), but check */
 		/* anyway just as a good practice.                                       */
-		pt = (ips_passthru_t *) SC->request_buffer;
+		pt = (ips_passthru_t *) scsi_sglist(SC);
 		if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) &&
 		    (pt->CoppCP.cmd.reset.adapter_flag == 1)) {
 			if (ha->scb_activelist.count != 0) {
@@ -1176,18 +1151,10 @@
 /*   Set bios geometry for the controller                                   */
 /*                                                                          */
 /****************************************************************************/
-static int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ips_biosparam(Disk * disk, kdev_t dev, int geom[])
-{
-	ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata;
-	unsigned long capacity = disk->capacity;
-#else
-ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-	      sector_t capacity, int geom[])
+static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+			 sector_t capacity, int geom[])
 {
 	ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
-#endif
 	int heads;
 	int sectors;
 	int cylinders;
@@ -1225,70 +1192,6 @@
 	return (0);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
-/* ips_proc24_info is a wrapper around ips_proc_info *
- * for compatibility with the 2.4 scsi parameters    */
-static int
-ips_proc24_info(char *buffer, char **start, off_t offset, int length,
-		              int hostno, int func)
-{
-	int i;
-
-	for (i = 0; i < ips_next_controller; i++) {
-		if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
-			return ips_proc_info(ips_sh[i], buffer, start,
-					     offset, length, func);
-		}
-	}
-	return -EINVAL;	
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_select_queue_depth                                     */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Select queue depths for the devices on the contoller                   */
-/*                                                                          */
-/****************************************************************************/
-static void
-ips_select_queue_depth(struct Scsi_Host *host, struct scsi_device * scsi_devs)
-{
-	struct scsi_device *device;
-	ips_ha_t *ha;
-	int count = 0;
-	int min;
-
-	ha = IPS_HA(host);
-	min = ha->max_cmds / 4;
-
-	for (device = scsi_devs; device; device = device->next) {
-		if (device->host == host) {
-			if ((device->channel == 0) && (device->type == 0))
-				count++;
-		}
-	}
-
-	for (device = scsi_devs; device; device = device->next) {
-		if (device->host == host) {
-			if ((device->channel == 0) && (device->type == 0)) {
-				device->queue_depth =
-				    (ha->max_cmds - 1) / count;
-				if (device->queue_depth < min)
-					device->queue_depth = min;
-			} else {
-				device->queue_depth = 2;
-			}
-
-			if (device->queue_depth < 2)
-				device->queue_depth = 2;
-		}
-	}
-}
-
-#else
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_slave_configure                                        */
@@ -1316,7 +1219,6 @@
 	SDptr->skip_ms_page_3f = 1;
 	return 0;
 }
-#endif
 
 /****************************************************************************/
 /*                                                                          */
@@ -1331,7 +1233,6 @@
 do_ipsintr(int irq, void *dev_id)
 {
 	ips_ha_t *ha;
-	unsigned long cpu_flags;
 	struct Scsi_Host *host;
 	int irqstatus;
 
@@ -1347,16 +1248,16 @@
 		return IRQ_HANDLED;
 	}
 
-	IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+	spin_lock(host->host_lock);
 
 	if (!ha->active) {
-		IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+		spin_unlock(host->host_lock);
 		return IRQ_HANDLED;
 	}
 
 	irqstatus = (*ha->func.intr) (ha);
 
-	IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+	spin_unlock(host->host_lock);
 
 	/* start the next command */
 	ips_next(ha, IPS_INTR_ON);
@@ -1606,30 +1507,22 @@
 	if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
 	    (SC->device->channel == 0) &&
 	    (SC->device->id == IPS_ADAPTER_ID) &&
-	    (SC->device->lun == 0) && SC->request_buffer) {
-		if ((!SC->use_sg) && SC->request_bufflen &&
-		    (((char *) SC->request_buffer)[0] == 'C') &&
-		    (((char *) SC->request_buffer)[1] == 'O') &&
-		    (((char *) SC->request_buffer)[2] == 'P') &&
-		    (((char *) SC->request_buffer)[3] == 'P'))
-			return 1;
-		else if (SC->use_sg) {
-			struct scatterlist *sg = SC->request_buffer;
-			char  *buffer; 
+	    (SC->device->lun == 0) && scsi_sglist(SC)) {
+                struct scatterlist *sg = scsi_sglist(SC);
+                char  *buffer;
 
-			/* kmap_atomic() ensures addressability of the user buffer.*/
-			/* local_irq_save() protects the KM_IRQ0 address slot.     */
-			local_irq_save(flags);
-			buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; 
-			if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
-			    buffer[2] == 'P' && buffer[3] == 'P') {
-				kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-				local_irq_restore(flags);
-				return 1;
-			}
-			kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-			local_irq_restore(flags);
-		}
+                /* kmap_atomic() ensures addressability of the user buffer.*/
+                /* local_irq_save() protects the KM_IRQ0 address slot.     */
+                local_irq_save(flags);
+                buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+                if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
+                    buffer[2] == 'P' && buffer[3] == 'P') {
+                        kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                        local_irq_restore(flags);
+                        return 1;
+                }
+                kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                local_irq_restore(flags);
 	}
 	return 0;
 }
@@ -1680,18 +1573,14 @@
 {
 	ips_passthru_t *pt;
 	int length = 0;
-	int ret;
+	int i, ret;
+        struct scatterlist *sg = scsi_sglist(SC);
 
 	METHOD_TRACE("ips_make_passthru", 1);
 
-	if (!SC->use_sg) {
-		length = SC->request_bufflen;
-	} else {
-		struct scatterlist *sg = SC->request_buffer;
-		int i;
-		for (i = 0; i < SC->use_sg; i++)
-			length += sg[i].length;
-	}
+        scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
+                length += sg[i].length;
+
 	if (length < sizeof (ips_passthru_t)) {
 		/* wrong size */
 		DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
@@ -2115,7 +2004,7 @@
 
 	METHOD_TRACE("ips_cleanup_passthru", 1);
 
-	if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
+	if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) {
 		DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
 			  ips_name, ha->host_num);
 
@@ -2730,7 +2619,6 @@
 	struct scsi_cmnd *q;
 	ips_copp_wait_item_t *item;
 	int ret;
-	unsigned long cpu_flags = 0;
 	struct Scsi_Host *host;
 	METHOD_TRACE("ips_next", 1);
 
@@ -2742,7 +2630,7 @@
 	 * this command won't time out
 	 */
 	if (intr == IPS_INTR_ON)
-		IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+		spin_lock(host->host_lock);
 
 	if ((ha->subsys->param[3] & 0x300000)
 	    && (ha->scb_activelist.count == 0)) {
@@ -2769,14 +2657,14 @@
 		item = ips_removeq_copp_head(&ha->copp_waitlist);
 		ha->num_ioctl++;
 		if (intr == IPS_INTR_ON)
-			IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+			spin_unlock(host->host_lock);
 		scb->scsi_cmd = item->scsi_cmd;
 		kfree(item);
 
 		ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
 
 		if (intr == IPS_INTR_ON)
-			IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+			spin_lock(host->host_lock);
 		switch (ret) {
 		case IPS_FAILURE:
 			if (scb->scsi_cmd) {
@@ -2846,7 +2734,7 @@
 		SC = ips_removeq_wait(&ha->scb_waitlist, q);
 
 		if (intr == IPS_INTR_ON)
-			IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);	/* Unlock HA after command is taken off queue */
+			spin_unlock(host->host_lock);	/* Unlock HA after command is taken off queue */
 
 		SC->result = DID_OK;
 		SC->host_scribble = NULL;
@@ -2866,41 +2754,26 @@
 		/* copy in the CDB */
 		memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
 
-		/* Now handle the data buffer */
-		if (SC->use_sg) {
+                scb->sg_count = scsi_dma_map(SC);
+                BUG_ON(scb->sg_count < 0);
+		if (scb->sg_count) {
 			struct scatterlist *sg;
 			int i;
 
-			sg = SC->request_buffer;
-			scb->sg_count = pci_map_sg(ha->pcidev, sg, SC->use_sg,
-						   SC->sc_data_direction);
 			scb->flags |= IPS_SCB_MAP_SG;
-			for (i = 0; i < scb->sg_count; i++) {
+
+                        scsi_for_each_sg(SC, sg, scb->sg_count, i) {
 				if (ips_fill_scb_sg_single
-				    (ha, sg_dma_address(&sg[i]), scb, i,
-				     sg_dma_len(&sg[i])) < 0)
+				    (ha, sg_dma_address(sg), scb, i,
+				     sg_dma_len(sg)) < 0)
 					break;
 			}
 			scb->dcdb.transfer_length = scb->data_len;
 		} else {
-			if (SC->request_bufflen) {
-				scb->data_busaddr =
-				    pci_map_single(ha->pcidev,
-						   SC->request_buffer,
-						   SC->request_bufflen,
-						   SC->sc_data_direction);
-				scb->flags |= IPS_SCB_MAP_SINGLE;
-				ips_fill_scb_sg_single(ha, scb->data_busaddr,
-						       scb, 0,
-						       SC->request_bufflen);
-				scb->dcdb.transfer_length = scb->data_len;
-			} else {
-				scb->data_busaddr = 0L;
-				scb->sg_len = 0;
-				scb->data_len = 0;
-				scb->dcdb.transfer_length = 0;
-			}
-
+                        scb->data_busaddr = 0L;
+                        scb->sg_len = 0;
+                        scb->data_len = 0;
+                        scb->dcdb.transfer_length = 0;
 		}
 
 		scb->dcdb.cmd_attribute =
@@ -2919,7 +2792,7 @@
 			scb->dcdb.transfer_length = 0;
 		}
 		if (intr == IPS_INTR_ON)
-			IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+			spin_lock(host->host_lock);
 
 		ret = ips_send_cmd(ha, scb);
 
@@ -2958,7 +2831,7 @@
 	}			/* end while */
 
 	if (intr == IPS_INTR_ON)
-		IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+		spin_unlock(host->host_lock);
 }
 
 /****************************************************************************/
@@ -3377,52 +3250,32 @@
 		 * the rest of the data and continue.
 		 */
 		if ((scb->breakup) || (scb->sg_break)) {
+                        struct scatterlist *sg;
+                        int sg_dma_index, ips_sg_index = 0;
+
 			/* we had a data breakup */
 			scb->data_len = 0;
 
-			if (scb->sg_count) {
-				/* S/G request */
-				struct scatterlist *sg;
-				int ips_sg_index = 0;
-				int sg_dma_index;
+                        sg = scsi_sglist(scb->scsi_cmd);
 
-				sg = scb->scsi_cmd->request_buffer;
+                        /* Spin forward to last dma chunk */
+                        sg_dma_index = scb->breakup;
 
-				/* Spin forward to last dma chunk */
-				sg_dma_index = scb->breakup;
+			/* Take care of possible partial on last chunk */
+                        ips_fill_scb_sg_single(ha,
+                                               sg_dma_address(&sg[sg_dma_index]),
+                                               scb, ips_sg_index++,
+                                               sg_dma_len(&sg[sg_dma_index]));
 
-				/* Take care of possible partial on last chunk */
-				ips_fill_scb_sg_single(ha,
-						       sg_dma_address(&sg
-								      [sg_dma_index]),
-						       scb, ips_sg_index++,
-						       sg_dma_len(&sg
-								  [sg_dma_index]));
-
-				for (; sg_dma_index < scb->sg_count;
-				     sg_dma_index++) {
-					if (ips_fill_scb_sg_single
-					    (ha,
-					     sg_dma_address(&sg[sg_dma_index]),
-					     scb, ips_sg_index++,
-					     sg_dma_len(&sg[sg_dma_index])) < 0)
-						break;
-
-				}
-
-			} else {
-				/* Non S/G Request */
-				(void) ips_fill_scb_sg_single(ha,
-							      scb->
-							      data_busaddr +
-							      (scb->sg_break *
-							       ha->max_xfer),
-							      scb, 0,
-							      scb->scsi_cmd->
-							      request_bufflen -
-							      (scb->sg_break *
-							       ha->max_xfer));
-			}
+                        for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
+                             sg_dma_index++) {
+                                if (ips_fill_scb_sg_single
+                                    (ha,
+                                     sg_dma_address(&sg[sg_dma_index]),
+                                     scb, ips_sg_index++,
+                                     sg_dma_len(&sg[sg_dma_index])) < 0)
+                                        break;
+                        }
 
 			scb->dcdb.transfer_length = scb->data_len;
 			scb->dcdb.cmd_attribute |=
@@ -3653,32 +3506,27 @@
 static void
 ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
 {
-	if (scmd->use_sg) {
-		int i;
-		unsigned int min_cnt, xfer_cnt;
-		char *cdata = (char *) data;
-		unsigned char *buffer;
-		unsigned long flags;
-		struct scatterlist *sg = scmd->request_buffer;
-		for (i = 0, xfer_cnt = 0;
-		     (i < scmd->use_sg) && (xfer_cnt < count); i++) {
-			min_cnt = min(count - xfer_cnt, sg[i].length);
+        int i;
+        unsigned int min_cnt, xfer_cnt;
+        char *cdata = (char *) data;
+        unsigned char *buffer;
+        unsigned long flags;
+        struct scatterlist *sg = scsi_sglist(scmd);
 
-			/* kmap_atomic() ensures addressability of the data buffer.*/
-			/* local_irq_save() protects the KM_IRQ0 address slot.     */
-			local_irq_save(flags);
-			buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
-			memcpy(buffer, &cdata[xfer_cnt], min_cnt);
-			kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
-			local_irq_restore(flags);
+        for (i = 0, xfer_cnt = 0;
+             (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+                min_cnt = min(count - xfer_cnt, sg[i].length);
 
-			xfer_cnt += min_cnt;
-		}
+                /* kmap_atomic() ensures addressability of the data buffer.*/
+                /* local_irq_save() protects the KM_IRQ0 address slot.     */
+                local_irq_save(flags);
+                buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
+                memcpy(buffer, &cdata[xfer_cnt], min_cnt);
+                kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+                local_irq_restore(flags);
 
-	} else {
-		unsigned int min_cnt = min(count, scmd->request_bufflen);
-		memcpy(scmd->request_buffer, data, min_cnt);
-	}
+                xfer_cnt += min_cnt;
+        }
 }
 
 /****************************************************************************/
@@ -3691,32 +3539,27 @@
 static void
 ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
 {
-	if (scmd->use_sg) {
-		int i;
-		unsigned int min_cnt, xfer_cnt;
-		char *cdata = (char *) data;
-		unsigned char *buffer;
-		unsigned long flags;
-		struct scatterlist *sg = scmd->request_buffer;
-		for (i = 0, xfer_cnt = 0;
-		     (i < scmd->use_sg) && (xfer_cnt < count); i++) {
-			min_cnt = min(count - xfer_cnt, sg[i].length);
+        int i;
+        unsigned int min_cnt, xfer_cnt;
+        char *cdata = (char *) data;
+        unsigned char *buffer;
+        unsigned long flags;
+        struct scatterlist *sg = scsi_sglist(scmd);
 
-			/* kmap_atomic() ensures addressability of the data buffer.*/
-			/* local_irq_save() protects the KM_IRQ0 address slot.     */
-			local_irq_save(flags);
-			buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
-			memcpy(&cdata[xfer_cnt], buffer, min_cnt);
-			kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
-			local_irq_restore(flags);
+        for (i = 0, xfer_cnt = 0;
+             (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+                min_cnt = min(count - xfer_cnt, sg[i].length);
 
-			xfer_cnt += min_cnt;
-		}
+                /* kmap_atomic() ensures addressability of the data buffer.*/
+                /* local_irq_save() protects the KM_IRQ0 address slot.     */
+                local_irq_save(flags);
+                buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
+                memcpy(&cdata[xfer_cnt], buffer, min_cnt);
+                kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+                local_irq_restore(flags);
 
-	} else {
-		unsigned int min_cnt = min(count, scmd->request_bufflen);
-		memcpy(data, scmd->request_buffer, min_cnt);
-	}
+                xfer_cnt += min_cnt;
+        }
 }
 
 /****************************************************************************/
@@ -4350,7 +4193,7 @@
 
 	METHOD_TRACE("ips_rdcap", 1);
 
-	if (scb->scsi_cmd->request_bufflen < 8)
+	if (scsi_bufflen(scb->scsi_cmd) < 8)
 		return (0);
 
 	cap.lba =
@@ -4735,8 +4578,7 @@
 
 	METHOD_TRACE("ips_freescb", 1);
 	if (scb->flags & IPS_SCB_MAP_SG)
-		pci_unmap_sg(ha->pcidev, scb->scsi_cmd->request_buffer,
-			     scb->scsi_cmd->use_sg, IPS_DMA_DIR(scb));
+                scsi_dma_unmap(scb->scsi_cmd);
 	else if (scb->flags & IPS_SCB_MAP_SINGLE)
 		pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len,
 				 IPS_DMA_DIR(scb));
@@ -7004,7 +6846,6 @@
 	kfree(oldha);
 	ips_sh[index] = sh;
 	ips_ha[index] = ha;
-	IPS_SCSI_SET_DEVICE(sh, ha);
 
 	/* Store away needed values for later use */
 	sh->io_port = ha->io_addr;
@@ -7016,17 +6857,16 @@
 	sh->cmd_per_lun = sh->hostt->cmd_per_lun;
 	sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
 	sh->use_clustering = sh->hostt->use_clustering;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
 	sh->max_sectors = 128;
-#endif
 
 	sh->max_id = ha->ntargets;
 	sh->max_lun = ha->nlun;
 	sh->max_channel = ha->nbus - 1;
 	sh->can_queue = ha->max_cmds - 1;
 
-	IPS_ADD_HOST(sh, NULL);
+	scsi_add_host(sh, NULL);
+	scsi_scan_host(sh);
+
 	return 0;
 }
 
@@ -7069,7 +6909,7 @@
 		return -ENODEV;
 	ips_driver_template.module = THIS_MODULE;
 	ips_order_controllers();
-	if (IPS_REGISTER_HOSTS(&ips_driver_template)) {
+	if (!ips_detect(&ips_driver_template)) {
 		pci_unregister_driver(&ips_pci_driver);
 		return -ENODEV;
 	}
@@ -7087,7 +6927,6 @@
 static void __exit
 ips_module_exit(void)
 {
-	IPS_UNREGISTER_HOSTS(&ips_driver_template);
 	pci_unregister_driver(&ips_pci_driver);
 	unregister_reboot_notifier(&ips_notifier);
 }
@@ -7148,7 +6987,6 @@
 	uint32_t mem_addr;
 	uint32_t io_len;
 	uint32_t mem_len;
-	uint8_t revision_id;
 	uint8_t bus;
 	uint8_t func;
 	uint8_t irq;
@@ -7227,12 +7065,6 @@
 		}
 	}
 
-	/* get the revision ID */
-	if (pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id)) {
-		IPS_PRINTK(KERN_WARNING, pci_dev, "Can't get revision id.\n");
-		return -1;
-	}
-
 	subdevice_id = pci_dev->subsystem_device;
 
 	/* found a controller */
@@ -7258,7 +7090,7 @@
 	ha->mem_ptr = mem_ptr;
 	ha->ioremap_ptr = ioremap_ptr;
 	ha->host_num = (uint32_t) index;
-	ha->revision_id = revision_id;
+	ha->revision_id = pci_dev->revision;
 	ha->slot_num = PCI_SLOT(pci_dev->devfn);
 	ha->device_id = pci_dev->device;
 	ha->subdevice_id = subdevice_id;
@@ -7443,15 +7275,9 @@
 	return SUCCESS;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
 MODULE_LICENSE("GPL");
-#endif
-
 MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
-
-#ifdef MODULE_VERSION
 MODULE_VERSION(IPS_VER_STRING);
-#endif
 
 
 /*
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index b726dcc..24123d5 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -58,10 +58,6 @@
    /*
     * Some handy macros
     */
-   #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || defined CONFIG_HIGHIO
-      #define IPS_HIGHIO
-   #endif
-
    #define IPS_HA(x)                   ((ips_ha_t *) x->hostdata)
    #define IPS_COMMAND_ID(ha, scb)     (int) (scb - ha->scbs)
    #define IPS_IS_TROMBONE(ha)         (((ha->device_id == IPS_DEVICEID_COPPERHEAD) && \
@@ -84,38 +80,8 @@
     #define IPS_SGLIST_SIZE(ha)       (IPS_USE_ENH_SGLIST(ha) ? \
                                          sizeof(IPS_ENH_SG_LIST) : sizeof(IPS_STD_SG_LIST))
 
-   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
-      #define pci_set_dma_mask(dev,mask) ( mask > 0xffffffff ? 1:0 )
-      #define scsi_set_pci_device(sh,dev) (0)
-   #endif
-
-   #ifndef IRQ_NONE
-      typedef void irqreturn_t;
-      #define IRQ_NONE
-      #define IRQ_HANDLED
-      #define IRQ_RETVAL(x)
-   #endif
-   
-   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-      #define IPS_REGISTER_HOSTS(SHT)      scsi_register_module(MODULE_SCSI_HA,SHT)
-      #define IPS_UNREGISTER_HOSTS(SHT)    scsi_unregister_module(MODULE_SCSI_HA,SHT)
-      #define IPS_ADD_HOST(shost,device)
-      #define IPS_REMOVE_HOST(shost)
-      #define IPS_SCSI_SET_DEVICE(sh,ha)   scsi_set_pci_device(sh, (ha)->pcidev)
-      #define IPS_PRINTK(level, pcidev, format, arg...)                 \
-            printk(level "%s %s:" format , "ips" ,     \
-            (pcidev)->slot_name , ## arg)
-      #define scsi_host_alloc(sh,size)         scsi_register(sh,size)
-      #define scsi_host_put(sh)             scsi_unregister(sh)
-   #else
-      #define IPS_REGISTER_HOSTS(SHT)      (!ips_detect(SHT))
-      #define IPS_UNREGISTER_HOSTS(SHT)
-      #define IPS_ADD_HOST(shost,device)   do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0)
-      #define IPS_REMOVE_HOST(shost)       scsi_remove_host(shost)
-      #define IPS_SCSI_SET_DEVICE(sh,ha)   do { } while (0)
-      #define IPS_PRINTK(level, pcidev, format, arg...)                 \
+  #define IPS_PRINTK(level, pcidev, format, arg...)                 \
             dev_printk(level , &((pcidev)->dev) , format , ## arg)
-   #endif
 
    #define MDELAY(n)			\
 	do {				\
@@ -134,7 +100,7 @@
    #define pci_dma_hi32(a)         ((a >> 16) >> 16)
    #define pci_dma_lo32(a)         (a & 0xffffffff)
 
-   #if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO)
+   #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
       #define IPS_ENABLE_DMA64        (1)
    #else
       #define IPS_ENABLE_DMA64        (0)
@@ -451,16 +417,10 @@
    /*
     * Scsi_Host Template
     */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-   static int ips_proc24_info(char *, char **, off_t, int, int, int);
-   static void ips_select_queue_depth(struct Scsi_Host *, struct scsi_device *);
-   static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]);
-#else
    static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
    static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 		sector_t capacity, int geom[]);
    static int ips_slave_configure(struct scsi_device *SDptr);
-#endif
 
 /*
  * Raid Command Formats
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index c9a3abf..aebcd5f 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -29,14 +29,15 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/inet.h>
+#include <linux/file.h>
 #include <linux/blkdev.h>
 #include <linux/crypto.h>
 #include <linux/delay.h>
 #include <linux/kfifo.h>
 #include <linux/scatterlist.h>
-#include <linux/mutex.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_transport_iscsi.h>
@@ -109,7 +110,7 @@
 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 
 	crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
-	buf->sg.length = tcp_conn->hdr_size;
+	buf->sg.length += sizeof(u32);
 }
 
 static inline int
@@ -211,16 +212,14 @@
 static int
 iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
-	int rc;
 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
 	struct iscsi_session *session = conn->session;
+	struct scsi_cmnd *sc = ctask->sc;
 	int datasn = be32_to_cpu(rhdr->datasn);
 
-	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
-	if (rc)
-		return rc;
+	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
 	/*
 	 * setup Data-In byte counter (gets decremented..)
 	 */
@@ -229,31 +228,36 @@
 	if (tcp_conn->in.datalen == 0)
 		return 0;
 
-	if (ctask->datasn != datasn)
+	if (tcp_ctask->exp_datasn != datasn) {
+		debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n",
+		          __FUNCTION__, tcp_ctask->exp_datasn, datasn);
 		return ISCSI_ERR_DATASN;
+	}
 
-	ctask->datasn++;
+	tcp_ctask->exp_datasn++;
 
 	tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
-	if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length)
+	if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+		debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+		          __FUNCTION__, tcp_ctask->data_offset,
+		          tcp_conn->in.datalen, scsi_bufflen(sc));
 		return ISCSI_ERR_DATA_OFFSET;
+	}
 
 	if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
-		struct scsi_cmnd *sc = ctask->sc;
-
 		conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
 		if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
 			int res_count = be32_to_cpu(rhdr->residual_count);
 
 			if (res_count > 0 &&
-			    res_count <= sc->request_bufflen) {
-				sc->resid = res_count;
+			    res_count <= scsi_bufflen(sc)) {
+				scsi_set_resid(sc, res_count);
 				sc->result = (DID_OK << 16) | rhdr->cmd_status;
 			} else
 				sc->result = (DID_BAD_TARGET << 16) |
 					rhdr->cmd_status;
 		} else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
-			sc->resid = be32_to_cpu(rhdr->residual_count);
+			scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
 			sc->result = (DID_OK << 16) | rhdr->cmd_status;
 		} else
 			sc->result = (DID_OK << 16) | rhdr->cmd_status;
@@ -281,6 +285,8 @@
 {
 	struct iscsi_data *hdr;
 	struct scsi_cmnd *sc = ctask->sc;
+	int i, sg_count = 0;
+	struct scatterlist *sg;
 
 	hdr = &r2t->dtask.hdr;
 	memset(hdr, 0, sizeof(struct iscsi_data));
@@ -308,39 +314,30 @@
 	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
 			   sizeof(struct iscsi_hdr));
 
-	if (sc->use_sg) {
-		int i, sg_count = 0;
-		struct scatterlist *sg = sc->request_buffer;
+	sg = scsi_sglist(sc);
+	r2t->sg = NULL;
+	for (i = 0; i < scsi_sg_count(sc); i++, sg += 1) {
+		/* FIXME: prefetch ? */
+		if (sg_count + sg->length > r2t->data_offset) {
+			int page_offset;
 
-		r2t->sg = NULL;
-		for (i = 0; i < sc->use_sg; i++, sg += 1) {
-			/* FIXME: prefetch ? */
-			if (sg_count + sg->length > r2t->data_offset) {
-				int page_offset;
+			/* sg page found! */
 
-				/* sg page found! */
+			/* offset within this page */
+			page_offset = r2t->data_offset - sg_count;
 
-				/* offset within this page */
-				page_offset = r2t->data_offset - sg_count;
+			/* fill in this buffer */
+			iscsi_buf_init_sg(&r2t->sendbuf, sg);
+			r2t->sendbuf.sg.offset += page_offset;
+			r2t->sendbuf.sg.length -= page_offset;
 
-				/* fill in this buffer */
-				iscsi_buf_init_sg(&r2t->sendbuf, sg);
-				r2t->sendbuf.sg.offset += page_offset;
-				r2t->sendbuf.sg.length -= page_offset;
-
-				/* xmit logic will continue with next one */
-				r2t->sg = sg + 1;
-				break;
-			}
-			sg_count += sg->length;
+			/* xmit logic will continue with next one */
+			r2t->sg = sg + 1;
+			break;
 		}
-		BUG_ON(r2t->sg == NULL);
-	} else {
-		iscsi_buf_init_iov(&r2t->sendbuf,
-			    (char*)sc->request_buffer + r2t->data_offset,
-			    r2t->data_count);
-		r2t->sg = NULL;
+		sg_count += sg->length;
 	}
+	BUG_ON(r2t->sg == NULL);
 }
 
 /**
@@ -365,17 +362,16 @@
 		return ISCSI_ERR_DATALEN;
 	}
 
-	if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn)
+	if (tcp_ctask->exp_datasn != r2tsn){
+		debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
+		          __FUNCTION__, tcp_ctask->exp_datasn, r2tsn);
 		return ISCSI_ERR_R2TSN;
-
-	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
-	if (rc)
-		return rc;
-
-	/* FIXME: use R2TSN to detect missing R2T */
+	}
 
 	/* fill-in new R2T associated with the task */
 	spin_lock(&session->lock);
+	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+
 	if (!ctask->sc || ctask->mtask ||
 	     session->state != ISCSI_STATE_LOGGED_IN) {
 		printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
@@ -401,11 +397,11 @@
 			    r2t->data_length, session->max_burst);
 
 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
-	if (r2t->data_offset + r2t->data_length > ctask->total_length) {
+	if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
 		spin_unlock(&session->lock);
 		printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
 		       "offset %u and total length %d\n", r2t->data_length,
-		       r2t->data_offset, ctask->total_length);
+		       r2t->data_offset, scsi_bufflen(ctask->sc));
 		return ISCSI_ERR_DATALEN;
 	}
 
@@ -414,9 +410,9 @@
 
 	iscsi_solicit_data_init(conn, ctask, r2t);
 
-	tcp_ctask->exp_r2tsn = r2tsn + 1;
+	tcp_ctask->exp_datasn = r2tsn + 1;
 	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
-	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+	tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT;
 	list_move_tail(&ctask->running, &conn->xmitqueue);
 
 	scsi_queue_work(session->host, &conn->xmitwork);
@@ -600,7 +596,7 @@
 {
 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 	int buf_left = buf_size - (tcp_conn->data_copied + offset);
-	int size = min(tcp_conn->in.copy, buf_left);
+	unsigned size = min(tcp_conn->in.copy, buf_left);
 	int rc;
 
 	size = min(size, ctask->data_count);
@@ -609,7 +605,7 @@
 	       size, tcp_conn->in.offset, tcp_conn->in.copied);
 
 	BUG_ON(size <= 0);
-	BUG_ON(tcp_ctask->sent + size > ctask->total_length);
+	BUG_ON(tcp_ctask->sent + size > scsi_bufflen(ctask->sc));
 
 	rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
 			   (char*)buf + (offset + tcp_conn->data_copied), size);
@@ -707,25 +703,8 @@
 
 	BUG_ON((void*)ctask != sc->SCp.ptr);
 
-	/*
-	 * copying Data-In into the Scsi_Cmnd
-	 */
-	if (!sc->use_sg) {
-		i = ctask->data_count;
-		rc = iscsi_ctask_copy(tcp_conn, ctask, sc->request_buffer,
-				      sc->request_bufflen,
-				      tcp_ctask->data_offset);
-		if (rc == -EAGAIN)
-			return rc;
-		if (conn->datadgst_en)
-			iscsi_recv_digest_update(tcp_conn, sc->request_buffer,
-						 i);
-		rc = 0;
-		goto done;
-	}
-
 	offset = tcp_ctask->data_offset;
-	sg = sc->request_buffer;
+	sg = scsi_sglist(sc);
 
 	if (tcp_ctask->data_offset)
 		for (i = 0; i < tcp_ctask->sg_count; i++)
@@ -734,7 +713,7 @@
 	if (offset < 0)
 		offset = 0;
 
-	for (i = tcp_ctask->sg_count; i < sc->use_sg; i++) {
+	for (i = tcp_ctask->sg_count; i < scsi_sg_count(sc); i++) {
 		char *dest;
 
 		dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
@@ -779,7 +758,6 @@
 	}
 	BUG_ON(ctask->data_count);
 
-done:
 	/* check for non-exceptional status */
 	if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
 		debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n",
@@ -895,11 +873,27 @@
 		}
 	}
 
-	if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
+	if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV &&
+	    tcp_conn->in.copy) {
 		uint32_t recv_digest;
 
 		debug_tcp("extra data_recv offset %d copy %d\n",
 			  tcp_conn->in.offset, tcp_conn->in.copy);
+
+		if (!tcp_conn->data_copied) {
+			if (tcp_conn->in.padding) {
+				debug_tcp("padding -> %d\n",
+					  tcp_conn->in.padding);
+				memset(pad, 0, tcp_conn->in.padding);
+				sg_init_one(&sg, pad, tcp_conn->in.padding);
+				crypto_hash_update(&tcp_conn->rx_hash,
+						   &sg, sg.length);
+			}
+			crypto_hash_final(&tcp_conn->rx_hash,
+					  (u8 *) &tcp_conn->in.datadgst);
+			debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
+		}
+
 		rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
 		if (rc) {
 			if (rc == -EAGAIN)
@@ -924,8 +918,7 @@
 	}
 
 	if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
-	   tcp_conn->in.copy) {
-
+	    tcp_conn->in.copy) {
 		debug_tcp("data_recv offset %d copy %d\n",
 		       tcp_conn->in.offset, tcp_conn->in.copy);
 
@@ -936,24 +929,32 @@
 			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 			return 0;
 		}
-		tcp_conn->in.copy -= tcp_conn->in.padding;
-		tcp_conn->in.offset += tcp_conn->in.padding;
-		if (conn->datadgst_en) {
-			if (tcp_conn->in.padding) {
-				debug_tcp("padding -> %d\n",
-					  tcp_conn->in.padding);
-				memset(pad, 0, tcp_conn->in.padding);
-				sg_init_one(&sg, pad, tcp_conn->in.padding);
-				crypto_hash_update(&tcp_conn->rx_hash,
-						   &sg, sg.length);
-			}
-			crypto_hash_final(&tcp_conn->rx_hash,
-					  (u8 *) &tcp_conn->in.datadgst);
-			debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
+
+		if (tcp_conn->in.padding)
+			tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
+		else if (conn->datadgst_en)
 			tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
-			tcp_conn->data_copied = 0;
-		} else
+		else
 			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+		tcp_conn->data_copied = 0;
+	}
+
+	if (tcp_conn->in_progress == IN_PROGRESS_PAD_RECV &&
+	    tcp_conn->in.copy) {
+		int copylen = min(tcp_conn->in.padding - tcp_conn->data_copied,
+				  tcp_conn->in.copy);
+
+		tcp_conn->in.copy -= copylen;
+		tcp_conn->in.offset += copylen;
+		tcp_conn->data_copied += copylen;
+
+		if (tcp_conn->data_copied != tcp_conn->in.padding)
+			tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
+		else if (conn->datadgst_en)
+			tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
+		else
+			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+		tcp_conn->data_copied = 0;
 	}
 
 	debug_tcp("f, processed %d from out of %d padding %d\n",
@@ -1215,7 +1216,6 @@
 			struct iscsi_r2t_info *r2t, int left)
 {
 	struct iscsi_data *hdr;
-	struct scsi_cmnd *sc = ctask->sc;
 	int new_offset;
 
 	hdr = &r2t->dtask.hdr;
@@ -1245,15 +1245,8 @@
 	if (iscsi_buf_left(&r2t->sendbuf))
 		return;
 
-	if (sc->use_sg) {
-		iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
-		r2t->sg += 1;
-	} else {
-		iscsi_buf_init_iov(&r2t->sendbuf,
-			    (char*)sc->request_buffer + new_offset,
-			    r2t->data_count);
-		r2t->sg = NULL;
-	}
+	iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
+	r2t->sg += 1;
 }
 
 static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask,
@@ -1277,41 +1270,10 @@
 static void
 iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
 {
-	struct scsi_cmnd *sc = ctask->sc;
 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
 	BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
-
-	tcp_ctask->sent = 0;
-	tcp_ctask->sg_count = 0;
-
-	if (sc->sc_data_direction == DMA_TO_DEVICE) {
-		tcp_ctask->xmstate = XMSTATE_W_HDR;
-		tcp_ctask->exp_r2tsn = 0;
-		BUG_ON(ctask->total_length == 0);
-
-		if (sc->use_sg) {
-			struct scatterlist *sg = sc->request_buffer;
-
-			iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
-			tcp_ctask->sg = sg + 1;
-			tcp_ctask->bad_sg = sg + sc->use_sg;
-		} else {
-			iscsi_buf_init_iov(&tcp_ctask->sendbuf,
-					   sc->request_buffer,
-					   sc->request_bufflen);
-			tcp_ctask->sg = NULL;
-			tcp_ctask->bad_sg = NULL;
-		}
-		debug_scsi("cmd [itt 0x%x total %d imm_data %d "
-			   "unsol count %d, unsol offset %d]\n",
-			   ctask->itt, ctask->total_length, ctask->imm_count,
-			   ctask->unsol_count, ctask->unsol_offset);
-	} else
-		tcp_ctask->xmstate = XMSTATE_R_HDR;
-
-	iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
-			    sizeof(struct iscsi_hdr));
+	tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT;
 }
 
 /**
@@ -1324,9 +1286,11 @@
  *	call it again later, or recover. '0' return code means successful
  *	xmit.
  *
- *	Management xmit state machine consists of two states:
- *		IN_PROGRESS_IMM_HEAD - PDU Header xmit in progress
- *		IN_PROGRESS_IMM_DATA - PDU Data xmit in progress
+ *	Management xmit state machine consists of these states:
+ *		XMSTATE_IMM_HDR_INIT	- calculate digest of PDU Header
+ *		XMSTATE_IMM_HDR 	- PDU Header xmit in progress
+ *		XMSTATE_IMM_DATA 	- PDU Data xmit in progress
+ *		XMSTATE_IDLE		- management PDU is done
  **/
 static int
 iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
@@ -1337,23 +1301,34 @@
 	debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
 		conn->id, tcp_mtask->xmstate, mtask->itt);
 
-	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
-		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
-		if (mtask->data_count)
+	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) {
+		iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
+				   sizeof(struct iscsi_hdr));
+
+		if (mtask->data_count) {
 			tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
+			iscsi_buf_init_iov(&tcp_mtask->sendbuf,
+					   (char*)mtask->data,
+					   mtask->data_count);
+		}
+
 		if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
 		    conn->stop_stage != STOP_CONN_RECOVER &&
 		    conn->hdrdgst_en)
 			iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
 					(u8*)tcp_mtask->hdrext);
+
+		tcp_mtask->sent = 0;
+		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT;
+		tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
+	}
+
+	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
 		rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
 				   mtask->data_count);
-		if (rc) {
-			tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
-			if (mtask->data_count)
-				tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
+		if (rc)
 			return rc;
-		}
+		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
 	}
 
 	if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
@@ -1387,55 +1362,67 @@
 	return 0;
 }
 
-static inline int
-iscsi_send_read_hdr(struct iscsi_conn *conn,
-		    struct iscsi_tcp_cmd_task *tcp_ctask)
+static int
+iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
-	int rc;
-
-	tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
-	if (conn->hdrdgst_en)
-		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
-				 (u8*)tcp_ctask->hdrext);
-	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0);
-	if (!rc) {
-		BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
-		return 0; /* wait for Data-In */
-	}
-	tcp_ctask->xmstate |= XMSTATE_R_HDR;
-	return rc;
-}
-
-static inline int
-iscsi_send_write_hdr(struct iscsi_conn *conn,
-		     struct iscsi_cmd_task *ctask)
-{
+	struct scsi_cmnd *sc = ctask->sc;
 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-	int rc;
+	int rc = 0;
 
-	tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
-	if (conn->hdrdgst_en)
-		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
-				 (u8*)tcp_ctask->hdrext);
-	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
-	if (rc) {
-		tcp_ctask->xmstate |= XMSTATE_W_HDR;
-		return rc;
-	}
+	if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) {
+		tcp_ctask->sent = 0;
+		tcp_ctask->sg_count = 0;
+		tcp_ctask->exp_datasn = 0;
 
-	if (ctask->imm_count) {
-		tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
-		iscsi_set_padding(tcp_ctask, ctask->imm_count);
+		if (sc->sc_data_direction == DMA_TO_DEVICE) {
+			struct scatterlist *sg = scsi_sglist(sc);
 
-		if (ctask->conn->datadgst_en) {
-			iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
-			tcp_ctask->immdigest = 0;
+			iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
+			tcp_ctask->sg = sg + 1;
+			tcp_ctask->bad_sg = sg + scsi_sg_count(sc);
+
+			debug_scsi("cmd [itt 0x%x total %d imm_data %d "
+				   "unsol count %d, unsol offset %d]\n",
+				   ctask->itt, scsi_bufflen(sc),
+				   ctask->imm_count, ctask->unsol_count,
+				   ctask->unsol_offset);
 		}
+
+		iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
+				  sizeof(struct iscsi_hdr));
+
+		if (conn->hdrdgst_en)
+			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+					 (u8*)tcp_ctask->hdrext);
+		tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
+		tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
 	}
 
-	if (ctask->unsol_count)
-		tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
-	return 0;
+	if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) {
+		rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
+		if (rc)
+			return rc;
+		tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT;
+
+		if (sc->sc_data_direction != DMA_TO_DEVICE)
+			return 0;
+
+		if (ctask->imm_count) {
+			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+			iscsi_set_padding(tcp_ctask, ctask->imm_count);
+
+			if (ctask->conn->datadgst_en) {
+				iscsi_data_digest_init(ctask->conn->dd_data,
+						       tcp_ctask);
+				tcp_ctask->immdigest = 0;
+			}
+		}
+
+		if (ctask->unsol_count)
+			tcp_ctask->xmstate |=
+					XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
+	}
+	return rc;
 }
 
 static int
@@ -1624,9 +1611,7 @@
 	struct iscsi_data_task *dtask;
 	int left, rc;
 
-	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
-		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
-		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) {
 		if (!tcp_ctask->r2t) {
 			spin_lock_bh(&session->lock);
 			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
@@ -1640,12 +1625,19 @@
 		if (conn->hdrdgst_en)
 			iscsi_hdr_digest(conn, &r2t->headbuf,
 					(u8*)dtask->hdrext);
+		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT;
+		tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+	}
+
+	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
+		r2t = tcp_ctask->r2t;
+		dtask = &r2t->dtask;
+
 		rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
-		if (rc) {
-			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
-			tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+		if (rc)
 			return rc;
-		}
+		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
 
 		if (conn->datadgst_en) {
 			iscsi_data_digest_init(conn->dd_data, tcp_ctask);
@@ -1677,8 +1669,6 @@
 		left = r2t->data_length - r2t->sent;
 		if (left) {
 			iscsi_solicit_data_cont(conn, ctask, r2t, left);
-			tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
-			tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
 			goto send_hdr;
 		}
 
@@ -1693,8 +1683,6 @@
 		if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t,
 				sizeof(void*))) {
 			tcp_ctask->r2t = r2t;
-			tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
-			tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
 			spin_unlock_bh(&session->lock);
 			goto send_hdr;
 		}
@@ -1703,6 +1691,46 @@
 	return 0;
 }
 
+/**
+ * iscsi_tcp_ctask_xmit - xmit normal PDU task
+ * @conn: iscsi connection
+ * @ctask: iscsi command task
+ *
+ * Notes:
+ *	The function can return -EAGAIN in which case caller must
+ *	call it again later, or recover. '0' return code means successful
+ *	xmit.
+ *	The function is devided to logical helpers (above) for the different
+ *	xmit stages.
+ *
+ *iscsi_send_cmd_hdr()
+ *	XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate
+ *	                       Header Digest
+ *	XMSTATE_CMD_HDR_XMIT - Transmit header in progress
+ *
+ *iscsi_send_padding
+ *	XMSTATE_W_PAD        - Prepare and send pading
+ *	XMSTATE_W_RESEND_PAD - retry send pading
+ *
+ *iscsi_send_digest
+ *	XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest
+ *	XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest
+ *
+ *iscsi_send_unsol_hdr
+ *	XMSTATE_UNS_INIT     - prepare un-solicit data header and digest
+ *	XMSTATE_UNS_HDR      - send un-solicit header
+ *
+ *iscsi_send_unsol_pdu
+ *	XMSTATE_UNS_DATA     - send un-solicit data in progress
+ *
+ *iscsi_send_sol_pdu
+ *	XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize
+ *	XMSTATE_SOL_HDR      - send solicit header
+ *	XMSTATE_SOL_DATA     - send solicit data
+ *
+ *iscsi_tcp_ctask_xmit
+ *	XMSTATE_IMM_DATA     - xmit managment data (??)
+ **/
 static int
 iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
@@ -1712,20 +1740,11 @@
 	debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n",
 		conn->id, tcp_ctask->xmstate, ctask->itt);
 
-	/*
-	 * serialize with TMF AbortTask
-	 */
-	if (ctask->mtask)
+	rc = iscsi_send_cmd_hdr(conn, ctask);
+	if (rc)
 		return rc;
-
-	if (tcp_ctask->xmstate & XMSTATE_R_HDR)
-		return iscsi_send_read_hdr(conn, tcp_ctask);
-
-	if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
-		rc = iscsi_send_write_hdr(conn, ctask);
-		if (rc)
-			return rc;
-	}
+	if (ctask->sc->sc_data_direction != DMA_TO_DEVICE)
+		return 0;
 
 	if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
 		rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
@@ -1810,18 +1829,22 @@
 static void
 iscsi_tcp_release_conn(struct iscsi_conn *conn)
 {
+	struct iscsi_session *session = conn->session;
 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct socket *sock = tcp_conn->sock;
 
-	if (!tcp_conn->sock)
+	if (!sock)
 		return;
 
-	sock_hold(tcp_conn->sock->sk);
+	sock_hold(sock->sk);
 	iscsi_conn_restore_callbacks(tcp_conn);
-	sock_put(tcp_conn->sock->sk);
+	sock_put(sock->sk);
 
-	sock_release(tcp_conn->sock);
+	spin_lock_bh(&session->lock);
 	tcp_conn->sock = NULL;
 	conn->recv_lock = NULL;
+	spin_unlock_bh(&session->lock);
+	sockfd_put(sock);
 }
 
 static void
@@ -1852,6 +1875,46 @@
 	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
 }
 
+static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
+			      char *buf, int *port,
+			      int (*getname)(struct socket *, struct sockaddr *,
+					int *addrlen))
+{
+	struct sockaddr_storage *addr;
+	struct sockaddr_in6 *sin6;
+	struct sockaddr_in *sin;
+	int rc = 0, len;
+
+	addr = kmalloc(GFP_KERNEL, sizeof(*addr));
+	if (!addr)
+		return -ENOMEM;
+
+	if (getname(sock, (struct sockaddr *) addr, &len)) {
+		rc = -ENODEV;
+		goto free_addr;
+	}
+
+	switch (addr->ss_family) {
+	case AF_INET:
+		sin = (struct sockaddr_in *)addr;
+		spin_lock_bh(&conn->session->lock);
+		sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
+		*port = be16_to_cpu(sin->sin_port);
+		spin_unlock_bh(&conn->session->lock);
+		break;
+	case AF_INET6:
+		sin6 = (struct sockaddr_in6 *)addr;
+		spin_lock_bh(&conn->session->lock);
+		sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr));
+		*port = be16_to_cpu(sin6->sin6_port);
+		spin_unlock_bh(&conn->session->lock);
+		break;
+	}
+free_addr:
+	kfree(addr);
+	return rc;
+}
+
 static int
 iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
 		    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
@@ -1869,10 +1932,24 @@
 		printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
 		return -EEXIST;
 	}
+	/*
+	 * copy these values now because if we drop the session
+	 * userspace may still want to query the values since we will
+	 * be using them for the reconnect
+	 */
+	err = iscsi_tcp_get_addr(conn, sock, conn->portal_address,
+				 &conn->portal_port, kernel_getpeername);
+	if (err)
+		goto free_socket;
+
+	err = iscsi_tcp_get_addr(conn, sock, conn->local_address,
+				&conn->local_port, kernel_getsockname);
+	if (err)
+		goto free_socket;
 
 	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
 	if (err)
-		return err;
+		goto free_socket;
 
 	/* bind iSCSI connection and socket */
 	tcp_conn->sock = sock;
@@ -1896,25 +1973,19 @@
 	 * set receive state machine into initial state
 	 */
 	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
-
 	return 0;
+
+free_socket:
+	sockfd_put(sock);
+	return err;
 }
 
 /* called with host lock */
 static void
-iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
-		    char *data, uint32_t data_size)
+iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
 {
 	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
-
-	iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
-			   sizeof(struct iscsi_hdr));
-	tcp_mtask->xmstate = XMSTATE_IMM_HDR;
-	tcp_mtask->sent = 0;
-
-	if (mtask->data_count)
-		iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
-				    mtask->data_count);
+	tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT;
 }
 
 static int
@@ -2026,41 +2097,18 @@
 			 enum iscsi_param param, char *buf)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct inet_sock *inet;
-	struct ipv6_pinfo *np;
-	struct sock *sk;
 	int len;
 
 	switch(param) {
 	case ISCSI_PARAM_CONN_PORT:
-		mutex_lock(&conn->xmitmutex);
-		if (!tcp_conn->sock) {
-			mutex_unlock(&conn->xmitmutex);
-			return -EINVAL;
-		}
-
-		inet = inet_sk(tcp_conn->sock->sk);
-		len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
-		mutex_unlock(&conn->xmitmutex);
+		spin_lock_bh(&conn->session->lock);
+		len = sprintf(buf, "%hu\n", conn->portal_port);
+		spin_unlock_bh(&conn->session->lock);
 		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
-		mutex_lock(&conn->xmitmutex);
-		if (!tcp_conn->sock) {
-			mutex_unlock(&conn->xmitmutex);
-			return -EINVAL;
-		}
-
-		sk = tcp_conn->sock->sk;
-		if (sk->sk_family == PF_INET) {
-			inet = inet_sk(sk);
-			len = sprintf(buf, NIPQUAD_FMT "\n",
-				      NIPQUAD(inet->daddr));
-		} else {
-			np = inet6_sk(sk);
-			len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
-		}
-		mutex_unlock(&conn->xmitmutex);
+		spin_lock_bh(&conn->session->lock);
+		len = sprintf(buf, "%s\n", conn->portal_address);
+		spin_unlock_bh(&conn->session->lock);
 		break;
 	default:
 		return iscsi_conn_get_param(cls_conn, param, buf);
@@ -2069,6 +2117,29 @@
 	return len;
 }
 
+static int
+iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+			 char *buf)
+{
+        struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+	int len;
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_IPADDRESS:
+		spin_lock_bh(&session->lock);
+		if (!session->leadconn)
+			len = -ENODEV;
+		else
+			len = sprintf(buf, "%s\n",
+				     session->leadconn->local_address);
+		spin_unlock_bh(&session->lock);
+		break;
+	default:
+		return iscsi_host_get_param(shost, param, buf);
+	}
+	return len;
+}
+
 static void
 iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
 {
@@ -2096,6 +2167,7 @@
 static struct iscsi_cls_session *
 iscsi_tcp_session_create(struct iscsi_transport *iscsit,
 			 struct scsi_transport_template *scsit,
+			 uint16_t cmds_max, uint16_t qdepth,
 			 uint32_t initial_cmdsn, uint32_t *hostno)
 {
 	struct iscsi_cls_session *cls_session;
@@ -2103,7 +2175,7 @@
 	uint32_t hn;
 	int cmd_i;
 
-	cls_session = iscsi_session_setup(iscsit, scsit,
+	cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth,
 					 sizeof(struct iscsi_tcp_cmd_task),
 					 sizeof(struct iscsi_tcp_mgmt_task),
 					 initial_cmdsn, &hn);
@@ -2142,17 +2214,24 @@
 	iscsi_session_teardown(cls_session);
 }
 
+static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
+{
+	blk_queue_dma_alignment(sdev->request_queue, 0);
+	return 0;
+}
+
 static struct scsi_host_template iscsi_sht = {
 	.name			= "iSCSI Initiator over TCP/IP",
 	.queuecommand           = iscsi_queuecommand,
 	.change_queue_depth	= iscsi_change_queue_depth,
-	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,
 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
 	.max_sectors		= 0xFFFF,
 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
 	.eh_abort_handler       = iscsi_eh_abort,
 	.eh_host_reset_handler	= iscsi_eh_host_reset,
 	.use_clustering         = DISABLE_CLUSTERING,
+	.slave_configure        = iscsi_tcp_slave_configure,
 	.proc_name		= "iscsi_tcp",
 	.this_id		= -1,
 };
@@ -2179,8 +2258,12 @@
 				  ISCSI_EXP_STATSN |
 				  ISCSI_PERSISTENT_PORT |
 				  ISCSI_PERSISTENT_ADDRESS |
-				  ISCSI_TARGET_NAME |
-				  ISCSI_TPGT,
+				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+				  ISCSI_USERNAME | ISCSI_PASSWORD |
+				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+				  ISCSI_HOST_INITIATOR_NAME |
+				  ISCSI_HOST_NETDEV_NAME,
 	.host_template		= &iscsi_sht,
 	.conndata_size		= sizeof(struct iscsi_conn),
 	.max_conn		= 1,
@@ -2197,6 +2280,9 @@
 	.get_session_param	= iscsi_session_get_param,
 	.start_conn		= iscsi_conn_start,
 	.stop_conn		= iscsi_tcp_conn_stop,
+	/* iscsi host params */
+	.get_host_param		= iscsi_tcp_host_get_param,
+	.set_host_param		= iscsi_host_set_param,
 	/* IO */
 	.send_pdu		= iscsi_conn_send_pdu,
 	.get_stats		= iscsi_conn_get_stats,
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 3273683..7eba44d 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -29,11 +29,12 @@
 #define IN_PROGRESS_HEADER_GATHER	0x1
 #define IN_PROGRESS_DATA_RECV		0x2
 #define IN_PROGRESS_DDIGEST_RECV	0x3
+#define IN_PROGRESS_PAD_RECV		0x4
 
 /* xmit state machine */
 #define XMSTATE_IDLE			0x0
-#define XMSTATE_R_HDR			0x1
-#define XMSTATE_W_HDR			0x2
+#define XMSTATE_CMD_HDR_INIT		0x1
+#define XMSTATE_CMD_HDR_XMIT		0x2
 #define XMSTATE_IMM_HDR			0x4
 #define XMSTATE_IMM_DATA		0x8
 #define XMSTATE_UNS_INIT		0x10
@@ -44,6 +45,8 @@
 #define XMSTATE_W_PAD			0x200
 #define XMSTATE_W_RESEND_PAD		0x400
 #define XMSTATE_W_RESEND_DATA_DIGEST	0x800
+#define XMSTATE_IMM_HDR_INIT		0x1000
+#define XMSTATE_SOL_HDR_INIT		0x2000
 
 #define ISCSI_PAD_LEN			4
 #define ISCSI_SG_TABLESIZE		SG_ALL
@@ -152,7 +155,7 @@
 	struct scatterlist	*sg;			/* per-cmd SG list  */
 	struct scatterlist	*bad_sg;		/* assert statement */
 	int			sg_count;		/* SG's to process  */
-	uint32_t		exp_r2tsn;
+	uint32_t		exp_datasn;		/* expected target's R2TSN/DataSN */
 	int			data_offset;
 	struct iscsi_r2t_info	*r2t;			/* in progress R2T    */
 	struct iscsi_queue	r2tpool;
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 19dd4b9..5d23101 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -1,307 +1,244 @@
-/*
- * jazz_esp.c: Driver for SCSI chip on Mips Magnum Boards (JAZZ architecture)
+/* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
  *
- * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- *
- * jazz_esp is based on David S. Miller's ESP driver and cyber_esp
+ * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/delay.h>
 #include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/irq.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
+#include <asm/io.h>
 #include <asm/dma.h>
 
-#include <asm/pgtable.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
 
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_advance_sg (struct scsi_cmnd *sp);
-static void dma_led_off(struct NCR_ESP *);
-static void dma_led_on(struct NCR_ESP *);
+#include <scsi/scsi_host.h>
 
+#include "esp_scsi.h"
 
-static volatile unsigned char cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are trasfered to the ESP chip
-				 * via PIO.
-				 */
+#define DRV_MODULE_NAME		"jazz_esp"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_VERSION		"1.000"
+#define DRV_MODULE_RELDATE	"May 19, 2007"
 
-static int jazz_esp_release(struct Scsi_Host *shost)
+static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg)
 {
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
+	*(volatile u8 *)(esp->regs + reg) = val;
+}
+
+static u8 jazz_esp_read8(struct esp *esp, unsigned long reg)
+{
+	return *(volatile u8 *)(esp->regs + reg);
+}
+
+static dma_addr_t jazz_esp_map_single(struct esp *esp, void *buf,
+				      size_t sz, int dir)
+{
+	return dma_map_single(esp->dev, buf, sz, dir);
+}
+
+static int jazz_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+				  int num_sg, int dir)
+{
+	return dma_map_sg(esp->dev, sg, num_sg, dir);
+}
+
+static void jazz_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+				  size_t sz, int dir)
+{
+	dma_unmap_single(esp->dev, addr, sz, dir);
+}
+
+static void jazz_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+			      int num_sg, int dir)
+{
+	dma_unmap_sg(esp->dev, sg, num_sg, dir);
+}
+
+static int jazz_esp_irq_pending(struct esp *esp)
+{
+	if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
+		return 1;
 	return 0;
 }
 
-/***************************************************************** Detection */
-static int jazz_esp_detect(struct scsi_host_template *tpnt)
+static void jazz_esp_reset_dma(struct esp *esp)
 {
-    struct NCR_ESP *esp;
-    struct ConfigDev *esp_dev;
+	vdma_disable ((int)esp->dma_regs);
+}
 
-    /*
-     * first assumption it is there:-)
-     */
-    if (1) {
-	esp_dev = NULL;
-	esp = esp_allocate(tpnt, esp_dev, 0);
-	
-	/* Do command transfer with programmed I/O */
-	esp->do_pio_cmds = 1;
-	
-	/* Required functions */
-	esp->dma_bytes_sent = &dma_bytes_sent;
-	esp->dma_can_transfer = &dma_can_transfer;
-	esp->dma_dump_state = &dma_dump_state;
-	esp->dma_init_read = &dma_init_read;
-	esp->dma_init_write = &dma_init_write;
-	esp->dma_ints_off = &dma_ints_off;
-	esp->dma_ints_on = &dma_ints_on;
-	esp->dma_irq_p = &dma_irq_p;
-	esp->dma_ports_p = &dma_ports_p;
-	esp->dma_setup = &dma_setup;
+static void jazz_esp_dma_drain(struct esp *esp)
+{
+	/* nothing to do */
+}
 
-	/* Optional functions */
-	esp->dma_barrier = NULL;
-	esp->dma_drain = NULL;
-	esp->dma_invalidate = NULL;
-	esp->dma_irq_entry = NULL;
-	esp->dma_irq_exit = NULL;
-	esp->dma_poll = NULL;
-	esp->dma_reset = NULL;
-	esp->dma_led_off = &dma_led_off;
-	esp->dma_led_on = &dma_led_on;
-	
-	/* virtual DMA functions */
-	esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
-	esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
-	esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
-	esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
-	esp->dma_advance_sg = &dma_advance_sg;
+static void jazz_esp_dma_invalidate(struct esp *esp)
+{
+	vdma_disable ((int)esp->dma_regs);
+}
 
+static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+				  u32 dma_count, int write, u8 cmd)
+{
+	BUG_ON(!(cmd & ESP_CMD_DMA));
 
-	/* SCSI chip speed */
+	jazz_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+	jazz_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+	vdma_disable ((int)esp->dma_regs);
+	if (write)
+		vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ);
+	else
+		vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE);
+
+	vdma_set_addr ((int)esp->dma_regs, addr);
+	vdma_set_count ((int)esp->dma_regs, dma_count);
+	vdma_enable ((int)esp->dma_regs);
+
+	scsi_esp_cmd(esp, cmd);
+}
+
+static int jazz_esp_dma_error(struct esp *esp)
+{
+	u32 enable = vdma_get_enable((int)esp->dma_regs);
+
+	if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR))
+		return 1;
+
+	return 0;
+}
+
+static const struct esp_driver_ops jazz_esp_ops = {
+	.esp_write8	=	jazz_esp_write8,
+	.esp_read8	=	jazz_esp_read8,
+	.map_single	=	jazz_esp_map_single,
+	.map_sg		=	jazz_esp_map_sg,
+	.unmap_single	=	jazz_esp_unmap_single,
+	.unmap_sg	=	jazz_esp_unmap_sg,
+	.irq_pending	=	jazz_esp_irq_pending,
+	.reset_dma	=	jazz_esp_reset_dma,
+	.dma_drain	=	jazz_esp_dma_drain,
+	.dma_invalidate	=	jazz_esp_dma_invalidate,
+	.send_dma_cmd	=	jazz_esp_send_dma_cmd,
+	.dma_error	=	jazz_esp_dma_error,
+};
+
+static int __devinit esp_jazz_probe(struct platform_device *dev)
+{
+	struct scsi_host_template *tpnt = &scsi_esp_template;
+	struct Scsi_Host *host;
+	struct esp *esp;
+	struct resource *res;
+	int err;
+
+	host = scsi_host_alloc(tpnt, sizeof(struct esp));
+
+	err = -ENOMEM;
+	if (!host)
+		goto fail;
+
+	host->max_id = 8;
+	esp = shost_priv(host);
+
+	esp->host = host;
+	esp->dev = dev;
+	esp->ops = &jazz_esp_ops;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto fail_unlink;
+
+	esp->regs = (void __iomem *)res->start;
+	if (!esp->regs)
+		goto fail_unlink;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+	if (!res)
+		goto fail_unlink;
+
+	esp->dma_regs = (void __iomem *)res->start;
+
+	esp->command_block = dma_alloc_coherent(esp->dev, 16,
+						&esp->command_block_dma,
+						GFP_KERNEL);
+	if (!esp->command_block)
+		goto fail_unmap_regs;
+
+	host->irq = platform_get_irq(dev, 0);
+	err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
+	if (err < 0)
+		goto fail_unmap_command_block;
+
+	esp->scsi_id = 7;
+	esp->host->this_id = esp->scsi_id;
+	esp->scsi_id_mask = (1 << esp->scsi_id);
 	esp->cfreq = 40000000;
 
-	/* 
-	 * we don't give the address of DMA channel, but the number
-	 * of DMA channel, so we can use the jazz DMA functions
-	 * 
-	 */
-	esp->dregs = (void *) JAZZ_SCSI_DMA;
-	
-	/* ESP register base */
-	esp->eregs = (struct ESP_regs *)(JAZZ_SCSI_BASE);
-	
-	/* Set the command buffer */
-	esp->esp_command = (volatile unsigned char *)cmd_buffer;
-	
-	/* get virtual dma address for command buffer */
-	esp->esp_command_dvma = vdma_alloc(CPHYSADDR(cmd_buffer), sizeof (cmd_buffer));
-	
-	esp->irq = JAZZ_SCSI_IRQ;
-	request_irq(JAZZ_SCSI_IRQ, esp_intr, IRQF_DISABLED, "JAZZ SCSI",
-	            esp->ehost);
+	dev_set_drvdata(&dev->dev, esp);
 
-	/*
-	 * FIXME, look if the scsi id is available from NVRAM
-	 */
-	esp->scsi_id = 7;
-		
-	/* Check for differential SCSI-bus */
-	/* What is this stuff? */
-	esp->diff = 0;
+	err = scsi_esp_register(esp, &dev->dev);
+	if (err)
+		goto fail_free_irq;
 
-	esp_initialize(esp);
-	
-	printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
-	esps_running = esps_in_use;
-	return esps_in_use;
-    }
-    return 0;
+	return 0;
+
+fail_free_irq:
+	free_irq(host->irq, esp);
+fail_unmap_command_block:
+	dma_free_coherent(esp->dev, 16,
+			  esp->command_block,
+			  esp->command_block_dma);
+fail_unmap_regs:
+fail_unlink:
+	scsi_host_put(host);
+fail:
+	return err;
 }
 
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+static int __devexit esp_jazz_remove(struct platform_device *dev)
 {
-    return fifo_count;
+	struct esp *esp = dev_get_drvdata(&dev->dev);
+	unsigned int irq = esp->host->irq;
+
+	scsi_esp_unregister(esp);
+
+	free_irq(irq, esp);
+	dma_free_coherent(esp->dev, 16,
+			  esp->command_block,
+			  esp->command_block_dma);
+
+	scsi_host_put(esp->host);
+
+	return 0;
 }
 
-static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp)
-{
-    /*
-     * maximum DMA size is 1MB
-     */
-    unsigned long sz = sp->SCp.this_residual;
-    if(sz > 0x100000)
-	sz = 0x100000;
-    return sz;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-    
-    ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
-	    esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_residue((int)esp->dregs)));
-}
-
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
-{
-    dma_cache_wback_inv ((unsigned long)phys_to_virt(vdma_log2phys(vaddress)), length);
-    vdma_disable ((int)esp->dregs);
-    vdma_set_mode ((int)esp->dregs, DMA_MODE_READ);
-    vdma_set_addr ((int)esp->dregs, vaddress);
-    vdma_set_count ((int)esp->dregs, length);
-    vdma_enable ((int)esp->dregs);
-}
-
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
-{
-    dma_cache_wback_inv ((unsigned long)phys_to_virt(vdma_log2phys(vaddress)), length);    
-    vdma_disable ((int)esp->dregs);    
-    vdma_set_mode ((int)esp->dregs, DMA_MODE_WRITE);
-    vdma_set_addr ((int)esp->dregs, vaddress);
-    vdma_set_count ((int)esp->dregs, length);
-    vdma_enable ((int)esp->dregs);    
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-    disable_irq(esp->irq);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-    enable_irq(esp->irq);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-    return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-    int enable = vdma_get_enable((int)esp->dregs);
-    
-    return (enable & R4030_CHNL_ENABLE);
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-    /* 
-     * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
-     * so when (write) is true, it actually means READ!
-     */
-    if(write){
-	dma_init_read(esp, addr, count);
-    } else {
-	dma_init_write(esp, addr, count);
-    }
-}
-
-static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
-{
-    sp->SCp.have_data_in = vdma_alloc(CPHYSADDR(sp->SCp.buffer), sp->SCp.this_residual);
-    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in);
-}
-
-static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
-{
-    int sz = sp->SCp.buffers_residual;
-    struct scatterlist *sg = (struct scatterlist *) sp->SCp.buffer;
-    
-    while (sz >= 0) {
-	sg[sz].dma_address = vdma_alloc(CPHYSADDR(page_address(sg[sz].page) + sg[sz].offset), sg[sz].length);
-	sz--;
-    }
-    sp->SCp.ptr=(char *)(sp->SCp.buffer->dma_address);
-}    
-
-static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
-{
-    vdma_free(sp->SCp.have_data_in);
-}
-
-static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
-{
-    int sz = sp->use_sg - 1;
-    struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
-			
-    while(sz >= 0) {
-	vdma_free(sg[sz].dma_address);
-	sz--;
-    }
-}
-
-static void dma_advance_sg (struct scsi_cmnd *sp)
-{
-    sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);
-}
-
-#define JAZZ_HDC_LED   0xe000d100 /* FIXME, find correct address */
-
-static void dma_led_off(struct NCR_ESP *esp)
-{
-#if 0    
-    *(unsigned char *)JAZZ_HDC_LED = 0;
-#endif    
-}
-
-static void dma_led_on(struct NCR_ESP *esp)
-{    
-#if 0    
-    *(unsigned char *)JAZZ_HDC_LED = 1;
-#endif    
-}
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "jazz_esp",
-	.proc_info		= esp_proc_info,
-	.name			= "ESP 100/100a/200",
-	.detect			= jazz_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= jazz_esp_release,
-	.info			= esp_info,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= DISABLE_CLUSTERING,
+static struct platform_driver esp_jazz_driver = {
+	.probe		= esp_jazz_probe,
+	.remove		= __devexit_p(esp_jazz_remove),
+	.driver	= {
+		.name	= "jazz_esp",
+	},
 };
-#include "scsi_module.c"
+
+static int __init jazz_esp_init(void)
+{
+	return platform_driver_register(&esp_jazz_driver);
+}
+
+static void __exit jazz_esp_exit(void)
+{
+	platform_driver_unregister(&esp_jazz_driver);
+}
+
+MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
+MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(jazz_esp_init);
+module_exit(jazz_esp_exit);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 3f5b9b4..4d85ce1 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -22,7 +22,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 #include <linux/types.h>
-#include <linux/mutex.h>
 #include <linux/kfifo.h>
 #include <linux/delay.h>
 #include <asm/unaligned.h>
@@ -46,27 +45,53 @@
 }
 EXPORT_SYMBOL_GPL(class_to_transport_session);
 
-#define INVALID_SN_DELTA	0xffff
+/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+#define SNA32_CHECK 2147483648UL
 
-int
-iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+static int iscsi_sna_lt(u32 n1, u32 n2)
+{
+	return n1 != n2 && ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
+			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
+}
+
+/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+static int iscsi_sna_lte(u32 n1, u32 n2)
+{
+	return n1 == n2 || ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
+			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
+}
+
+void
+iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
 {
 	uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
 	uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
 
-	if (max_cmdsn < exp_cmdsn -1 &&
-	    max_cmdsn > exp_cmdsn - INVALID_SN_DELTA)
-		return ISCSI_ERR_MAX_CMDSN;
-	if (max_cmdsn > session->max_cmdsn ||
-	    max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA)
-		session->max_cmdsn = max_cmdsn;
-	if (exp_cmdsn > session->exp_cmdsn ||
-	    exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA)
+	/*
+	 * standard specifies this check for when to update expected and
+	 * max sequence numbers
+	 */
+	if (iscsi_sna_lt(max_cmdsn, exp_cmdsn - 1))
+		return;
+
+	if (exp_cmdsn != session->exp_cmdsn &&
+	    !iscsi_sna_lt(exp_cmdsn, session->exp_cmdsn))
 		session->exp_cmdsn = exp_cmdsn;
 
-	return 0;
+	if (max_cmdsn != session->max_cmdsn &&
+	    !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) {
+		session->max_cmdsn = max_cmdsn;
+		/*
+		 * if the window closed with IO queued, then kick the
+		 * xmit thread
+		 */
+		if (!list_empty(&session->leadconn->xmitqueue) ||
+		    __kfifo_len(session->leadconn->mgmtqueue))
+			scsi_queue_work(session->host,
+					&session->leadconn->xmitwork);
+	}
 }
-EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
+EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
 
 void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
 				   struct iscsi_data *hdr)
@@ -115,14 +140,17 @@
         hdr->flags = ISCSI_ATTR_SIMPLE;
         int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
         hdr->itt = build_itt(ctask->itt, conn->id, session->age);
-        hdr->data_length = cpu_to_be32(sc->request_bufflen);
+        hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
         hdr->cmdsn = cpu_to_be32(session->cmdsn);
         session->cmdsn++;
         hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
         memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
-        memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
+	if (sc->cmd_len < MAX_COMMAND_SIZE)
+		memset(&hdr->cdb[sc->cmd_len], 0,
+			MAX_COMMAND_SIZE - sc->cmd_len);
 
 	ctask->data_count = 0;
+	ctask->imm_count = 0;
 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
 		hdr->flags |= ISCSI_FLAG_CMD_WRITE;
 		/*
@@ -139,25 +167,24 @@
 		 *
 		 *      pad_count       bytes to be sent as zero-padding
 		 */
-		ctask->imm_count = 0;
 		ctask->unsol_count = 0;
 		ctask->unsol_offset = 0;
 		ctask->unsol_datasn = 0;
 
 		if (session->imm_data_en) {
-			if (ctask->total_length >= session->first_burst)
+			if (scsi_bufflen(sc) >= session->first_burst)
 				ctask->imm_count = min(session->first_burst,
 							conn->max_xmit_dlength);
 			else
-				ctask->imm_count = min(ctask->total_length,
+				ctask->imm_count = min(scsi_bufflen(sc),
 							conn->max_xmit_dlength);
 			hton24(ctask->hdr->dlength, ctask->imm_count);
 		} else
 			zero_data(ctask->hdr->dlength);
 
 		if (!session->initial_r2t_en) {
-			ctask->unsol_count = min(session->first_burst,
-				ctask->total_length) - ctask->imm_count;
+			ctask->unsol_count = min((session->first_burst),
+				(scsi_bufflen(sc))) - ctask->imm_count;
 			ctask->unsol_offset = ctask->imm_count;
 		}
 
@@ -165,7 +192,6 @@
 			/* No unsolicit Data-Out's */
 			ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
 	} else {
-		ctask->datasn = 0;
 		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
 		zero_data(hdr->dlength);
 
@@ -174,8 +200,13 @@
 	}
 
 	conn->scsicmd_pdus_cnt++;
+
+        debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
+		"cmdsn %d win %d]\n",
+                sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+		conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+                session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
 }
-EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu);
 
 /**
  * iscsi_complete_command - return command back to scsi-ml
@@ -204,26 +235,12 @@
 	atomic_inc(&ctask->refcount);
 }
 
-static void iscsi_get_ctask(struct iscsi_cmd_task *ctask)
-{
-	spin_lock_bh(&ctask->conn->session->lock);
-	__iscsi_get_ctask(ctask);
-	spin_unlock_bh(&ctask->conn->session->lock);
-}
-
 static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
 {
 	if (atomic_dec_and_test(&ctask->refcount))
 		iscsi_complete_command(ctask);
 }
 
-static void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
-{
-	spin_lock_bh(&ctask->conn->session->lock);
-	__iscsi_put_ctask(ctask);
-	spin_unlock_bh(&ctask->conn->session->lock);
-}
-
 /**
  * iscsi_cmd_rsp - SCSI Command Response processing
  * @conn: iscsi connection
@@ -235,21 +252,15 @@
  * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
  * then completes the command and task.
  **/
-static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
-			      struct iscsi_cmd_task *ctask, char *data,
-			      int datalen)
+static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+			       struct iscsi_cmd_task *ctask, char *data,
+			       int datalen)
 {
-	int rc;
 	struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr;
 	struct iscsi_session *session = conn->session;
 	struct scsi_cmnd *sc = ctask->sc;
 
-	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
-	if (rc) {
-		sc->result = DID_ERROR << 16;
-		goto out;
-	}
-
+	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
 	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
 
 	sc->result = (DID_OK << 16) | rhdr->cmd_status;
@@ -286,14 +297,14 @@
 	if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
 		int res_count = be32_to_cpu(rhdr->residual_count);
 
-		if (res_count > 0 && res_count <= sc->request_bufflen)
-			sc->resid = res_count;
+		if (res_count > 0 && res_count <= scsi_bufflen(sc))
+			scsi_set_resid(sc, res_count);
 		else
 			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
 	} else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
 		sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
 	else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
-		sc->resid = be32_to_cpu(rhdr->residual_count);
+		scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
 
 out:
 	debug_scsi("done [sc %lx res %d itt 0x%x]\n",
@@ -301,7 +312,6 @@
 	conn->scsirsp_pdus_cnt++;
 
 	__iscsi_put_ctask(ctask);
-	return rc;
 }
 
 static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
@@ -381,8 +391,8 @@
 		switch(opcode) {
 		case ISCSI_OP_SCSI_CMD_RSP:
 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
-			rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
-						datalen);
+			iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
+					   datalen);
 			break;
 		case ISCSI_OP_SCSI_DATA_IN:
 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
@@ -405,11 +415,7 @@
 		debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
 			   opcode, conn->id, mtask->itt, datalen);
 
-		rc = iscsi_check_assign_cmdsn(session,
-					      (struct iscsi_nopin*)hdr);
-		if (rc)
-			goto done;
-
+		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
 		switch(opcode) {
 		case ISCSI_OP_LOGOUT_RSP:
 			if (datalen) {
@@ -458,10 +464,7 @@
 			break;
 		}
 	} else if (itt == ~0U) {
-		rc = iscsi_check_assign_cmdsn(session,
-					     (struct iscsi_nopin*)hdr);
-		if (rc)
-			goto done;
+		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
 
 		switch(opcode) {
 		case ISCSI_OP_NOOP_IN:
@@ -491,7 +494,6 @@
 	} else
 		rc = ISCSI_ERR_BAD_ITT;
 
-done:
 	return rc;
 }
 EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
@@ -578,17 +580,47 @@
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_failure);
 
+static void iscsi_prep_mtask(struct iscsi_conn *conn,
+			     struct iscsi_mgmt_task *mtask)
+{
+	struct iscsi_session *session = conn->session;
+	struct iscsi_hdr *hdr = mtask->hdr;
+	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+
+	if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) &&
+	    hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+	/*
+	 * pre-format CmdSN for outgoing PDU.
+	 */
+	nop->cmdsn = cpu_to_be32(session->cmdsn);
+	if (hdr->itt != RESERVED_ITT) {
+		hdr->itt = build_itt(mtask->itt, conn->id, session->age);
+		if (conn->c_stage == ISCSI_CONN_STARTED &&
+		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
+			session->cmdsn++;
+	}
+
+	if (session->tt->init_mgmt_task)
+		session->tt->init_mgmt_task(conn, mtask);
+
+	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+		   hdr->opcode, hdr->itt, mtask->data_count);
+}
+
 static int iscsi_xmit_mtask(struct iscsi_conn *conn)
 {
 	struct iscsi_hdr *hdr = conn->mtask->hdr;
 	int rc, was_logout = 0;
 
+	spin_unlock_bh(&conn->session->lock);
 	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) {
 		conn->session->state = ISCSI_STATE_IN_RECOVERY;
 		iscsi_block_session(session_to_cls(conn->session));
 		was_logout = 1;
 	}
 	rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
+	spin_lock_bh(&conn->session->lock);
 	if (rc)
 		return rc;
 
@@ -602,6 +634,45 @@
 	return 0;
 }
 
+static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
+{
+	struct iscsi_session *session = conn->session;
+
+	/*
+	 * Check for iSCSI window and take care of CmdSN wrap-around
+	 */
+	if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) {
+		debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n",
+			   session->max_cmdsn, session->cmdsn);
+		return -ENOSPC;
+	}
+	return 0;
+}
+
+static int iscsi_xmit_ctask(struct iscsi_conn *conn)
+{
+	struct iscsi_cmd_task *ctask = conn->ctask;
+	int rc = 0;
+
+	/*
+	 * serialize with TMF AbortTask
+	 */
+	if (ctask->state == ISCSI_TASK_ABORTING)
+		goto done;
+
+	__iscsi_get_ctask(ctask);
+	spin_unlock_bh(&conn->session->lock);
+	rc = conn->session->tt->xmit_cmd_task(conn, ctask);
+	spin_lock_bh(&conn->session->lock);
+	__iscsi_put_ctask(ctask);
+
+done:
+	if (!rc)
+		/* done with this ctask */
+		conn->ctask = NULL;
+	return rc;
+}
+
 /**
  * iscsi_data_xmit - xmit any command into the scheduled connection
  * @conn: iscsi connection
@@ -613,106 +684,79 @@
  **/
 static int iscsi_data_xmit(struct iscsi_conn *conn)
 {
-	struct iscsi_transport *tt;
 	int rc = 0;
 
+	spin_lock_bh(&conn->session->lock);
 	if (unlikely(conn->suspend_tx)) {
 		debug_scsi("conn %d Tx suspended!\n", conn->id);
+		spin_unlock_bh(&conn->session->lock);
 		return -ENODATA;
 	}
-	tt = conn->session->tt;
-
-	/*
-	 * Transmit in the following order:
-	 *
-	 * 1) un-finished xmit (ctask or mtask)
-	 * 2) immediate control PDUs
-	 * 3) write data
-	 * 4) SCSI commands
-	 * 5) non-immediate control PDUs
-	 *
-	 * No need to lock around __kfifo_get as long as
-	 * there's one producer and one consumer.
-	 */
-
-	BUG_ON(conn->ctask && conn->mtask);
 
 	if (conn->ctask) {
-		iscsi_get_ctask(conn->ctask);
-		rc = tt->xmit_cmd_task(conn, conn->ctask);
-		iscsi_put_ctask(conn->ctask);
+		rc = iscsi_xmit_ctask(conn);
 		if (rc)
 			goto again;
-		/* done with this in-progress ctask */
-		conn->ctask = NULL;
 	}
+
 	if (conn->mtask) {
 		rc = iscsi_xmit_mtask(conn);
 	        if (rc)
 		        goto again;
 	}
 
-	/* process immediate first */
-        if (unlikely(__kfifo_len(conn->immqueue))) {
-	        while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
-			           sizeof(void*))) {
-			spin_lock_bh(&conn->session->lock);
-			list_add_tail(&conn->mtask->running,
-				      &conn->mgmt_run_list);
-			spin_unlock_bh(&conn->session->lock);
-			rc = iscsi_xmit_mtask(conn);
-		        if (rc)
-			        goto again;
-	        }
+	/*
+	 * process mgmt pdus like nops before commands since we should
+	 * only have one nop-out as a ping from us and targets should not
+	 * overflow us with nop-ins
+	 */
+check_mgmt:
+	while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
+			   sizeof(void*))) {
+		iscsi_prep_mtask(conn, conn->mtask);
+		list_add_tail(&conn->mtask->running, &conn->mgmt_run_list);
+		rc = iscsi_xmit_mtask(conn);
+		if (rc)
+			goto again;
 	}
 
 	/* process command queue */
-	spin_lock_bh(&conn->session->lock);
 	while (!list_empty(&conn->xmitqueue)) {
+		rc = iscsi_check_cmdsn_window_closed(conn);
+		if (rc) {
+			spin_unlock_bh(&conn->session->lock);
+			return rc;
+		}
 		/*
 		 * iscsi tcp may readd the task to the xmitqueue to send
 		 * write data
 		 */
 		conn->ctask = list_entry(conn->xmitqueue.next,
 					 struct iscsi_cmd_task, running);
+		if (conn->ctask->state == ISCSI_TASK_PENDING) {
+			iscsi_prep_scsi_cmd_pdu(conn->ctask);
+			conn->session->tt->init_cmd_task(conn->ctask);
+		}
 		conn->ctask->state = ISCSI_TASK_RUNNING;
 		list_move_tail(conn->xmitqueue.next, &conn->run_list);
-		__iscsi_get_ctask(conn->ctask);
-		spin_unlock_bh(&conn->session->lock);
-
-		rc = tt->xmit_cmd_task(conn, conn->ctask);
-
-		spin_lock_bh(&conn->session->lock);
-		__iscsi_put_ctask(conn->ctask);
-		if (rc) {
-			spin_unlock_bh(&conn->session->lock);
+		rc = iscsi_xmit_ctask(conn);
+		if (rc)
 			goto again;
-		}
+		/*
+		 * we could continuously get new ctask requests so
+		 * we need to check the mgmt queue for nops that need to
+		 * be sent to aviod starvation
+		 */
+		if (__kfifo_len(conn->mgmtqueue))
+			goto check_mgmt;
 	}
 	spin_unlock_bh(&conn->session->lock);
-	/* done with this ctask */
-	conn->ctask = NULL;
-
-	/* process the rest control plane PDUs, if any */
-        if (unlikely(__kfifo_len(conn->mgmtqueue))) {
-	        while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
-			           sizeof(void*))) {
-			spin_lock_bh(&conn->session->lock);
-			list_add_tail(&conn->mtask->running,
-				      &conn->mgmt_run_list);
-			spin_unlock_bh(&conn->session->lock);
-			rc = iscsi_xmit_mtask(conn);
-		        if (rc)
-			        goto again;
-	        }
-	}
-
 	return -ENODATA;
 
 again:
 	if (unlikely(conn->suspend_tx))
-		return -ENODATA;
-
+		rc = -ENODATA;
+	spin_unlock_bh(&conn->session->lock);
 	return rc;
 }
 
@@ -724,11 +768,9 @@
 	/*
 	 * serialize Xmit worker on a per-connection basis.
 	 */
-	mutex_lock(&conn->xmitmutex);
 	do {
 		rc = iscsi_data_xmit(conn);
 	} while (rc >= 0 || rc == -EAGAIN);
-	mutex_unlock(&conn->xmitmutex);
 }
 
 enum {
@@ -786,20 +828,23 @@
 		goto fault;
 	}
 
-	/*
-	 * Check for iSCSI window and take care of CmdSN wrap-around
-	 */
-	if ((int)(session->max_cmdsn - session->cmdsn) < 0) {
-		reason = FAILURE_WINDOW_CLOSED;
-		goto reject;
-	}
-
 	conn = session->leadconn;
 	if (!conn) {
 		reason = FAILURE_SESSION_FREED;
 		goto fault;
 	}
 
+	/*
+	 * We check this here and in data xmit, because if we get to the point
+	 * that this check is hitting the window then we have enough IO in
+	 * flight and enough IO waiting to be transmitted it is better
+	 * to let the scsi/block layer queue up.
+	 */
+	if (iscsi_check_cmdsn_window_closed(conn)) {
+		reason = FAILURE_WINDOW_CLOSED;
+		goto reject;
+	}
+
 	if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
 			 sizeof(void*))) {
 		reason = FAILURE_OOM;
@@ -814,18 +859,8 @@
 	ctask->conn = conn;
 	ctask->sc = sc;
 	INIT_LIST_HEAD(&ctask->running);
-	ctask->total_length = sc->request_bufflen;
-	iscsi_prep_scsi_cmd_pdu(ctask);
-
-	session->tt->init_cmd_task(ctask);
 
 	list_add_tail(&ctask->running, &conn->xmitqueue);
-	debug_scsi(
-	       "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d "
-		"win %d]\n",
-		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
-		conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen,
-		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
 	spin_unlock(&session->lock);
 
 	scsi_queue_work(host, &conn->xmitwork);
@@ -841,7 +876,7 @@
 	printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n",
 	       sc->cmnd[0], reason);
 	sc->result = (DID_NO_CONNECT << 16);
-	sc->resid = sc->request_bufflen;
+	scsi_set_resid(sc, scsi_bufflen(sc));
 	sc->scsi_done(sc);
 	return 0;
 }
@@ -856,19 +891,16 @@
 }
 EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
 
-static int
-iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
-			char *data, uint32_t data_size)
+static struct iscsi_mgmt_task *
+__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+		      char *data, uint32_t data_size)
 {
 	struct iscsi_session *session = conn->session;
-	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
 	struct iscsi_mgmt_task *mtask;
 
-	spin_lock_bh(&session->lock);
-	if (session->state == ISCSI_STATE_TERMINATE) {
-		spin_unlock_bh(&session->lock);
-		return -EPERM;
-	}
+	if (session->state == ISCSI_STATE_TERMINATE)
+		return NULL;
+
 	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
 	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
 		/*
@@ -882,27 +914,11 @@
 		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
 		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
 
-		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
 		if (!__kfifo_get(session->mgmtpool.queue,
-				 (void*)&mtask, sizeof(void*))) {
-			spin_unlock_bh(&session->lock);
-			return -ENOSPC;
-		}
+				 (void*)&mtask, sizeof(void*)))
+			return NULL;
 	}
 
-	/*
-	 * pre-format CmdSN for outgoing PDU.
-	 */
-	if (hdr->itt != RESERVED_ITT) {
-		hdr->itt = build_itt(mtask->itt, conn->id, session->age);
-		nop->cmdsn = cpu_to_be32(session->cmdsn);
-		if (conn->c_stage == ISCSI_CONN_STARTED &&
-		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
-			session->cmdsn++;
-	} else
-		/* do not advance CmdSN */
-		nop->cmdsn = cpu_to_be32(session->cmdsn);
-
 	if (data_size) {
 		memcpy(mtask->data, data, data_size);
 		mtask->data_count = data_size;
@@ -911,38 +927,23 @@
 
 	INIT_LIST_HEAD(&mtask->running);
 	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
-	if (session->tt->init_mgmt_task)
-		session->tt->init_mgmt_task(conn, mtask, data, data_size);
-	spin_unlock_bh(&session->lock);
-
-	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
-		   hdr->opcode, hdr->itt, data_size);
-
-	/*
-	 * since send_pdu() could be called at least from two contexts,
-	 * we need to serialize __kfifo_put, so we don't have to take
-	 * additional lock on fast data-path
-	 */
-        if (hdr->opcode & ISCSI_OP_IMMEDIATE)
-	        __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
-	else
-	        __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
-
-	scsi_queue_work(session->host, &conn->xmitwork);
-	return 0;
+	__kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
+	return mtask;
 }
 
 int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
 			char *data, uint32_t data_size)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
-	int rc;
+	struct iscsi_session *session = conn->session;
+	int err = 0;
 
-	mutex_lock(&conn->xmitmutex);
-	rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
-	mutex_unlock(&conn->xmitmutex);
-
-	return rc;
+	spin_lock_bh(&session->lock);
+	if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
+		err = -EPERM;
+	spin_unlock_bh(&session->lock);
+	scsi_queue_work(session->host, &conn->xmitwork);
+	return err;
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
 
@@ -1027,14 +1028,12 @@
 	spin_unlock(&session->lock);
 }
 
-/* must be called with the mutex lock */
 static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
 				 struct iscsi_cmd_task *ctask)
 {
 	struct iscsi_conn *conn = ctask->conn;
 	struct iscsi_session *session = conn->session;
 	struct iscsi_tm *hdr = &conn->tmhdr;
-	int rc;
 
 	/*
 	 * ctask timed out but session is OK requests must be serialized.
@@ -1047,32 +1046,27 @@
 	hdr->rtt = ctask->hdr->itt;
 	hdr->refcmdsn = ctask->hdr->cmdsn;
 
-	rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
-				     NULL, 0);
-	if (rc) {
+	ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
+					    NULL, 0);
+	if (!ctask->mtask) {
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-		debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt,
-		           rc);
-		return rc;
+		debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt);
+		return -EPERM;
 	}
+	ctask->state = ISCSI_TASK_ABORTING;
 
 	debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
 
-	spin_lock_bh(&session->lock);
-	ctask->mtask = (struct iscsi_mgmt_task *)
-			session->mgmt_cmds[get_itt(hdr->itt) -
-					ISCSI_MGMT_ITT_OFFSET];
-
 	if (conn->tmabort_state == TMABORT_INITIAL) {
 		conn->tmfcmd_pdus_cnt++;
-		conn->tmabort_timer.expires = 10*HZ + jiffies;
+		conn->tmabort_timer.expires = 20*HZ + jiffies;
 		conn->tmabort_timer.function = iscsi_tmabort_timedout;
 		conn->tmabort_timer.data = (unsigned long)ctask;
 		add_timer(&conn->tmabort_timer);
 		debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt);
 	}
 	spin_unlock_bh(&session->lock);
-	mutex_unlock(&conn->xmitmutex);
+	scsi_queue_work(session->host, &conn->xmitwork);
 
 	/*
 	 * block eh thread until:
@@ -1089,13 +1083,12 @@
 	if (signal_pending(current))
 		flush_signals(current);
 	del_timer_sync(&conn->tmabort_timer);
-
-	mutex_lock(&conn->xmitmutex);
+	spin_lock_bh(&session->lock);
 	return 0;
 }
 
 /*
- * xmit mutex and session lock must be held
+ * session lock must be held
  */
 static struct iscsi_mgmt_task *
 iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
@@ -1127,7 +1120,7 @@
 	if (!ctask->mtask)
 		return -EINVAL;
 
-	if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt))
+	if (!iscsi_remove_mgmt_task(conn->mgmtqueue, ctask->mtask->itt))
 		list_del(&ctask->mtask->running);
 	__kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
 		    sizeof(void*));
@@ -1136,7 +1129,7 @@
 }
 
 /*
- * session lock and xmitmutex must be held
+ * session lock must be held
  */
 static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
 			 int err)
@@ -1147,11 +1140,14 @@
 	if (!sc)
 		return;
 
-	conn->session->tt->cleanup_cmd_task(conn, ctask);
+	if (ctask->state != ISCSI_TASK_PENDING)
+		conn->session->tt->cleanup_cmd_task(conn, ctask);
 	iscsi_ctask_mtask_cleanup(ctask);
 
 	sc->result = err;
-	sc->resid = sc->request_bufflen;
+	scsi_set_resid(sc, scsi_bufflen(sc));
+	if (conn->ctask == ctask)
+		conn->ctask = NULL;
 	/* release ref from queuecommand */
 	__iscsi_put_ctask(ctask);
 }
@@ -1179,7 +1175,6 @@
 	conn->eh_abort_cnt++;
 	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
 
-	mutex_lock(&conn->xmitmutex);
 	spin_lock_bh(&session->lock);
 
 	/*
@@ -1192,9 +1187,8 @@
 
 	/* ctask completed before time out */
 	if (!ctask->sc) {
-		spin_unlock_bh(&session->lock);
 		debug_scsi("sc completed while abort in progress\n");
-		goto success_rel_mutex;
+		goto success;
 	}
 
 	/* what should we do here ? */
@@ -1204,15 +1198,13 @@
 		goto failed;
 	}
 
-	if (ctask->state == ISCSI_TASK_PENDING)
-		goto success_cleanup;
+	if (ctask->state == ISCSI_TASK_PENDING) {
+		fail_command(conn, ctask, DID_ABORT << 16);
+		goto success;
+	}
 
 	conn->tmabort_state = TMABORT_INITIAL;
-
-	spin_unlock_bh(&session->lock);
 	rc = iscsi_exec_abort_task(sc, ctask);
-	spin_lock_bh(&session->lock);
-
 	if (rc || sc->SCp.phase != session->age ||
 	    session->state != ISCSI_STATE_LOGGED_IN)
 		goto failed;
@@ -1220,45 +1212,44 @@
 
 	switch (conn->tmabort_state) {
 	case TMABORT_SUCCESS:
-		goto success_cleanup;
+		spin_unlock_bh(&session->lock);
+		/*
+		 * clean up task if aborted. grab the recv lock as a writer
+		 */
+		write_lock_bh(conn->recv_lock);
+		spin_lock(&session->lock);
+		fail_command(conn, ctask, DID_ABORT << 16);
+		spin_unlock(&session->lock);
+		write_unlock_bh(conn->recv_lock);
+		/*
+		 * make sure xmit thread is not still touching the
+		 * ctask/scsi_cmnd
+		 */
+		scsi_flush_work(session->host);
+		goto success_unlocked;
 	case TMABORT_NOT_FOUND:
 		if (!ctask->sc) {
 			/* ctask completed before tmf abort response */
-			spin_unlock_bh(&session->lock);
 			debug_scsi("sc completed while abort in progress\n");
-			goto success_rel_mutex;
+			goto success;
 		}
 		/* fall through */
 	default:
 		/* timedout or failed */
 		spin_unlock_bh(&session->lock);
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-		spin_lock_bh(&session->lock);
-		goto failed;
+		goto failed_unlocked;
 	}
 
-success_cleanup:
-	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+success:
 	spin_unlock_bh(&session->lock);
-
-	/*
-	 * clean up task if aborted. we have the xmitmutex so grab
-	 * the recv lock as a writer
-	 */
-	write_lock_bh(conn->recv_lock);
-	spin_lock(&session->lock);
-	fail_command(conn, ctask, DID_ABORT << 16);
-	spin_unlock(&session->lock);
-	write_unlock_bh(conn->recv_lock);
-
-success_rel_mutex:
-	mutex_unlock(&conn->xmitmutex);
+success_unlocked:
+	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
 	return SUCCESS;
 
 failed:
 	spin_unlock_bh(&session->lock);
-	mutex_unlock(&conn->xmitmutex);
-
+failed_unlocked:
 	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
 	return FAILED;
 }
@@ -1339,6 +1330,10 @@
  * iscsi_session_setup - create iscsi cls session and host and session
  * @scsit: scsi transport template
  * @iscsit: iscsi transport template
+ * @cmds_max: scsi host can queue
+ * @qdepth: scsi host cmds per lun
+ * @cmd_task_size: LLD ctask private data size
+ * @mgmt_task_size: LLD mtask private data size
  * @initial_cmdsn: initial CmdSN
  * @hostno: host no allocated
  *
@@ -1348,6 +1343,7 @@
 struct iscsi_cls_session *
 iscsi_session_setup(struct iscsi_transport *iscsit,
 		    struct scsi_transport_template *scsit,
+		    uint16_t cmds_max, uint16_t qdepth,
 		    int cmd_task_size, int mgmt_task_size,
 		    uint32_t initial_cmdsn, uint32_t *hostno)
 {
@@ -1356,11 +1352,32 @@
 	struct iscsi_cls_session *cls_session;
 	int cmd_i;
 
+	if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
+		if (qdepth != 0)
+			printk(KERN_ERR "iscsi: invalid queue depth of %d. "
+			      "Queue depth must be between 1 and %d.\n",
+			      qdepth, ISCSI_MAX_CMD_PER_LUN);
+		qdepth = ISCSI_DEF_CMD_PER_LUN;
+	}
+
+	if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) ||
+	    cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
+		if (cmds_max != 0)
+			printk(KERN_ERR "iscsi: invalid can_queue of %d. "
+			       "can_queue must be a power of 2 and between "
+			       "2 and %d - setting to %d.\n", cmds_max,
+			       ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX);
+		cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
+	}
+
 	shost = scsi_host_alloc(iscsit->host_template,
 				hostdata_privsize(sizeof(*session)));
 	if (!shost)
 		return NULL;
 
+	/* the iscsi layer takes one task for reserve */
+	shost->can_queue = cmds_max - 1;
+	shost->cmd_per_lun = qdepth;
 	shost->max_id = 1;
 	shost->max_channel = 0;
 	shost->max_lun = iscsit->max_lun;
@@ -1374,7 +1391,7 @@
 	session->host = shost;
 	session->state = ISCSI_STATE_FREE;
 	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
-	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
+	session->cmds_max = cmds_max;
 	session->cmdsn = initial_cmdsn;
 	session->exp_cmdsn = initial_cmdsn + 1;
 	session->max_cmdsn = initial_cmdsn + 1;
@@ -1461,7 +1478,14 @@
 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
 
+	kfree(session->password);
+	kfree(session->password_in);
+	kfree(session->username);
+	kfree(session->username_in);
 	kfree(session->targetname);
+	kfree(session->netdev);
+	kfree(session->hwaddress);
+	kfree(session->initiatorname);
 
 	iscsi_destroy_session(cls_session);
 	scsi_host_put(shost);
@@ -1499,11 +1523,6 @@
 	INIT_LIST_HEAD(&conn->xmitqueue);
 
 	/* initialize general immediate & non-immediate PDU commands queue */
-	conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
-			                GFP_KERNEL, NULL);
-	if (conn->immqueue == ERR_PTR(-ENOMEM))
-		goto immqueue_alloc_fail;
-
 	conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
 			                GFP_KERNEL, NULL);
 	if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
@@ -1527,7 +1546,6 @@
 	conn->login_mtask->data = conn->data = data;
 
 	init_timer(&conn->tmabort_timer);
-	mutex_init(&conn->xmitmutex);
 	init_waitqueue_head(&conn->ehwait);
 
 	return cls_conn;
@@ -1538,8 +1556,6 @@
 login_mtask_alloc_fail:
 	kfifo_free(conn->mgmtqueue);
 mgmtqueue_alloc_fail:
-	kfifo_free(conn->immqueue);
-immqueue_alloc_fail:
 	iscsi_destroy_conn(cls_conn);
 	return NULL;
 }
@@ -1558,10 +1574,8 @@
 	struct iscsi_session *session = conn->session;
 	unsigned long flags;
 
-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
-	mutex_lock(&conn->xmitmutex);
-
 	spin_lock_bh(&session->lock);
+	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
 	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
 	if (session->leadconn == conn) {
 		/*
@@ -1572,8 +1586,6 @@
 	}
 	spin_unlock_bh(&session->lock);
 
-	mutex_unlock(&conn->xmitmutex);
-
 	/*
 	 * Block until all in-progress commands for this connection
 	 * time out or fail.
@@ -1610,7 +1622,6 @@
 	}
 	spin_unlock_bh(&session->lock);
 
-	kfifo_free(conn->immqueue);
 	kfifo_free(conn->mgmtqueue);
 
 	iscsi_destroy_conn(cls_conn);
@@ -1671,8 +1682,7 @@
 	struct iscsi_mgmt_task *mtask, *tmp;
 
 	/* handle pending */
-	while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
-	       __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
+	while (__kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
 		if (mtask == conn->login_mtask)
 			continue;
 		debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
@@ -1742,12 +1752,12 @@
 	conn->c_stage = ISCSI_CONN_STOPPED;
 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
 	spin_unlock_bh(&session->lock);
+	scsi_flush_work(session->host);
 
 	write_lock_bh(conn->recv_lock);
 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
 	write_unlock_bh(conn->recv_lock);
 
-	mutex_lock(&conn->xmitmutex);
 	/*
 	 * for connection level recovery we should not calculate
 	 * header digest. conn->hdr_size used for optimization
@@ -1771,8 +1781,6 @@
 	fail_all_commands(conn);
 	flush_control_queues(session, conn);
 	spin_unlock_bh(&session->lock);
-
-	mutex_unlock(&conn->xmitmutex);
 }
 
 void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
@@ -1867,6 +1875,30 @@
 	case ISCSI_PARAM_EXP_STATSN:
 		sscanf(buf, "%u", &conn->exp_statsn);
 		break;
+	case ISCSI_PARAM_USERNAME:
+		kfree(session->username);
+		session->username = kstrdup(buf, GFP_KERNEL);
+		if (!session->username)
+			return -ENOMEM;
+		break;
+	case ISCSI_PARAM_USERNAME_IN:
+		kfree(session->username_in);
+		session->username_in = kstrdup(buf, GFP_KERNEL);
+		if (!session->username_in)
+			return -ENOMEM;
+		break;
+	case ISCSI_PARAM_PASSWORD:
+		kfree(session->password);
+		session->password = kstrdup(buf, GFP_KERNEL);
+		if (!session->password)
+			return -ENOMEM;
+		break;
+	case ISCSI_PARAM_PASSWORD_IN:
+		kfree(session->password_in);
+		session->password_in = kstrdup(buf, GFP_KERNEL);
+		if (!session->password_in)
+			return -ENOMEM;
+		break;
 	case ISCSI_PARAM_TARGET_NAME:
 		/* this should not change between logins */
 		if (session->targetname)
@@ -1940,6 +1972,18 @@
 	case ISCSI_PARAM_TPGT:
 		len = sprintf(buf, "%d\n", session->tpgt);
 		break;
+	case ISCSI_PARAM_USERNAME:
+		len = sprintf(buf, "%s\n", session->username);
+		break;
+	case ISCSI_PARAM_USERNAME_IN:
+		len = sprintf(buf, "%s\n", session->username_in);
+		break;
+	case ISCSI_PARAM_PASSWORD:
+		len = sprintf(buf, "%s\n", session->password);
+		break;
+	case ISCSI_PARAM_PASSWORD_IN:
+		len = sprintf(buf, "%s\n", session->password_in);
+		break;
 	default:
 		return -ENOSYS;
 	}
@@ -1990,6 +2034,66 @@
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_get_param);
 
+int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+			 char *buf)
+{
+	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+	int len;
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		if (!session->netdev)
+			len = sprintf(buf, "%s\n", "default");
+		else
+			len = sprintf(buf, "%s\n", session->netdev);
+		break;
+	case ISCSI_HOST_PARAM_HWADDRESS:
+		if (!session->hwaddress)
+			len = sprintf(buf, "%s\n", "default");
+		else
+			len = sprintf(buf, "%s\n", session->hwaddress);
+		break;
+	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+		if (!session->initiatorname)
+			len = sprintf(buf, "%s\n", "unknown");
+		else
+			len = sprintf(buf, "%s\n", session->initiatorname);
+		break;
+
+	default:
+		return -ENOSYS;
+	}
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(iscsi_host_get_param);
+
+int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+			 char *buf, int buflen)
+{
+	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		if (!session->netdev)
+			session->netdev = kstrdup(buf, GFP_KERNEL);
+		break;
+	case ISCSI_HOST_PARAM_HWADDRESS:
+		if (!session->hwaddress)
+			session->hwaddress = kstrdup(buf, GFP_KERNEL);
+		break;
+	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+		if (!session->initiatorname)
+			session->initiatorname = kstrdup(buf, GFP_KERNEL);
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_host_set_param);
+
 MODULE_AUTHOR("Mike Christie");
 MODULE_DESCRIPTION("iSCSI library functions");
 MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index e34442e..23e90c5 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -38,8 +38,10 @@
 
 #if 0
 /* FIXME: smp needs to migrate into the sas class */
-static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t);
-static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t);
+static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *,
+			       char *, loff_t, size_t);
+static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *,
+				char *, loff_t, size_t);
 #endif
 
 /* ---------- SMP task management ---------- */
@@ -1368,7 +1370,6 @@
 	memset(bin_attr, 0, sizeof(*bin_attr));
 
 	bin_attr->attr.name = SMP_BIN_ATTR_NAME;
-	bin_attr->attr.owner = THIS_MODULE;
 	bin_attr->attr.mode = 0600;
 
 	bin_attr->size = 0;
@@ -1846,8 +1847,9 @@
 #if 0
 /* ---------- SMP portal ---------- */
 
-static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
-				size_t size)
+static ssize_t smp_portal_write(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t offs, size_t size)
 {
 	struct domain_device *dev = to_dom_device(kobj);
 	struct expander_device *ex = &dev->ex_dev;
@@ -1873,8 +1875,9 @@
 	return size;
 }
 
-static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs,
-			       size_t size)
+static ssize_t smp_portal_read(struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t offs, size_t size)
 {
 	struct domain_device *dev = to_dom_device(kobj);
 	struct expander_device *ex = &dev->ex_dev;
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index b4b5269..9c5342e 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -40,6 +40,7 @@
 
 #include <linux/err.h>
 #include <linux/blkdev.h>
+#include <linux/freezer.h>
 #include <linux/scatterlist.h>
 
 /* ---------- SCSI Host glue ---------- */
@@ -76,8 +77,8 @@
 			hs = DID_NO_CONNECT;
 			break;
 		case SAS_DATA_UNDERRUN:
-			sc->resid = ts->residual;
-			if (sc->request_bufflen - sc->resid < sc->underflow)
+			scsi_set_resid(sc, ts->residual);
+			if (scsi_bufflen(sc) - scsi_get_resid(sc) < sc->underflow)
 				hs = DID_ERROR;
 			break;
 		case SAS_DATA_OVERRUN:
@@ -161,9 +162,9 @@
 	task->ssp_task.task_attr = sas_scsi_get_task_attr(cmd);
 	memcpy(task->ssp_task.cdb, cmd->cmnd, 16);
 
-	task->scatter = cmd->request_buffer;
-	task->num_scatter = cmd->use_sg;
-	task->total_xfer_len = cmd->request_bufflen;
+	task->scatter = scsi_sglist(cmd);
+	task->num_scatter = scsi_sg_count(cmd);
+	task->total_xfer_len = scsi_bufflen(cmd);
 	task->data_dir = cmd->sc_data_direction;
 
 	task->task_done = sas_scsi_task_done;
@@ -868,8 +869,6 @@
 {
 	struct sas_ha_struct *sas_ha = _sas_ha;
 
-	current->flags |= PF_NOFREEZE;
-
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c
index 5631c19..732446e 100644
--- a/drivers/scsi/libsrp.c
+++ b/drivers/scsi/libsrp.c
@@ -254,6 +254,7 @@
 
 		sg_init_one(&dummy, md, id->table_desc.len);
 		sg_dma_address(&dummy) = token;
+		sg_dma_len(&dummy) = id->table_desc.len;
 		err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
 			      id->table_desc.len);
 		if (err) {
diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile
index d1be465..1c28670 100644
--- a/drivers/scsi/lpfc/Makefile
+++ b/drivers/scsi/lpfc/Makefile
@@ -1,7 +1,7 @@
 #/*******************************************************************
 # * This file is part of the Emulex Linux Device Driver for         *
 # * Fibre Channel Host Bus Adapters.                                *
-# * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
+# * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
 # * EMULEX and SLI are trademarks of Emulex.                        *
 # * www.emulex.com                                                  *
 # *                                                                 *
@@ -27,4 +27,5 @@
 obj-$(CONFIG_SCSI_LPFC) := lpfc.o
 
 lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o	\
-	lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o
+	lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \
+	lpfc_vport.o lpfc_debugfs.o
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 82e8f90..f8f64d6 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -19,8 +19,9 @@
  * included with this package.                                     *
  *******************************************************************/
 
-struct lpfc_sli2_slim;
+#include <scsi/scsi_host.h>
 
+struct lpfc_sli2_slim;
 
 #define LPFC_MAX_TARGET		256	/* max number of targets supported */
 #define LPFC_MAX_DISC_THREADS	64	/* max outstanding discovery els
@@ -32,6 +33,20 @@
 #define LPFC_IOCB_LIST_CNT	2250	/* list of IOCBs for fast-path usage. */
 #define LPFC_Q_RAMP_UP_INTERVAL 120     /* lun q_depth ramp up interval */
 
+/*
+ * Following time intervals are used of adjusting SCSI device
+ * queue depths when there are driver resource error or Firmware
+ * resource error.
+ */
+#define QUEUE_RAMP_DOWN_INTERVAL	(1 * HZ)   /* 1 Second */
+#define QUEUE_RAMP_UP_INTERVAL		(300 * HZ) /* 5 minutes */
+
+/* Number of exchanges reserved for discovery to complete */
+#define LPFC_DISC_IOCB_BUFF_COUNT 20
+
+#define LPFC_HB_MBOX_INTERVAL   5	/* Heart beat interval in seconds. */
+#define LPFC_HB_MBOX_TIMEOUT    30 	/* Heart beat timeout  in seconds. */
+
 /* Define macros for 64 bit support */
 #define putPaddrLow(addr)    ((uint32_t) (0xffffffff & (u64)(addr)))
 #define putPaddrHigh(addr)   ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
@@ -61,6 +76,11 @@
 	uint32_t    current_count;
 };
 
+struct hbq_dmabuf {
+	struct lpfc_dmabuf dbuf;
+	uint32_t tag;
+};
+
 /* Priority bit.  Set value to exceed low water mark in lpfc_mem. */
 #define MEM_PRI		0x100
 
@@ -90,6 +110,29 @@
 		uint32_t sli2FwRev;
 		uint8_t sli2FwName[16];
 	} rev;
+	struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint32_t rsvd2  :24;  /* Reserved                             */
+		uint32_t cmv	: 1;  /* Configure Max VPIs                   */
+		uint32_t ccrp   : 1;  /* Config Command Ring Polling          */
+		uint32_t csah   : 1;  /* Configure Synchronous Abort Handling */
+		uint32_t chbs   : 1;  /* Cofigure Host Backing store          */
+		uint32_t cinb   : 1;  /* Enable Interrupt Notification Block  */
+		uint32_t cerbm	: 1;  /* Configure Enhanced Receive Buf Mgmt  */
+		uint32_t cmx	: 1;  /* Configure Max XRIs                   */
+		uint32_t cmr	: 1;  /* Configure Max RPIs                   */
+#else	/*  __LITTLE_ENDIAN */
+		uint32_t cmr	: 1;  /* Configure Max RPIs                   */
+		uint32_t cmx	: 1;  /* Configure Max XRIs                   */
+		uint32_t cerbm	: 1;  /* Configure Enhanced Receive Buf Mgmt  */
+		uint32_t cinb   : 1;  /* Enable Interrupt Notification Block  */
+		uint32_t chbs   : 1;  /* Cofigure Host Backing store          */
+		uint32_t csah   : 1;  /* Configure Synchronous Abort Handling */
+		uint32_t ccrp   : 1;  /* Config Command Ring Polling          */
+		uint32_t cmv	: 1;  /* Configure Max VPIs                   */
+		uint32_t rsvd2  :24;  /* Reserved                             */
+#endif
+	} sli3Feat;
 } lpfc_vpd_t;
 
 struct lpfc_scsi_buf;
@@ -122,6 +165,7 @@
 	uint32_t elsRcvRPS;
 	uint32_t elsRcvRPL;
 	uint32_t elsXmitFLOGI;
+	uint32_t elsXmitFDISC;
 	uint32_t elsXmitPLOGI;
 	uint32_t elsXmitPRLI;
 	uint32_t elsXmitADISC;
@@ -165,96 +209,71 @@
 	struct lpfcMboxq *    mbox;
 };
 
-struct lpfc_hba {
-	struct lpfc_sli sli;
-	struct lpfc_sli2_slim *slim2p;
-	dma_addr_t slim2p_mapping;
-	uint16_t pci_cfg_value;
+struct lpfc_hba;
 
-	int32_t hba_state;
 
-#define LPFC_STATE_UNKNOWN        0    /* HBA state is unknown */
-#define LPFC_WARM_START           1    /* HBA state after selective reset */
-#define LPFC_INIT_START           2    /* Initial state after board reset */
-#define LPFC_INIT_MBX_CMDS        3    /* Initialize HBA with mbox commands */
-#define LPFC_LINK_DOWN            4    /* HBA initialized, link is down */
-#define LPFC_LINK_UP              5    /* Link is up  - issue READ_LA */
-#define LPFC_LOCAL_CFG_LINK       6    /* local NPORT Id configured */
-#define LPFC_FLOGI                7    /* FLOGI sent to Fabric */
-#define LPFC_FABRIC_CFG_LINK      8    /* Fabric assigned NPORT Id
-					   configured */
-#define LPFC_NS_REG               9	/* Register with NameServer */
-#define LPFC_NS_QRY               10	/* Query NameServer for NPort ID list */
-#define LPFC_BUILD_DISC_LIST      11	/* Build ADISC and PLOGI lists for
-					 * device authentication / discovery */
-#define LPFC_DISC_AUTH            12	/* Processing ADISC list */
-#define LPFC_CLEAR_LA             13	/* authentication cmplt - issue
-					   CLEAR_LA */
-#define LPFC_HBA_READY            32
-#define LPFC_HBA_ERROR            -1
+enum discovery_state {
+	LPFC_VPORT_UNKNOWN     =  0,    /* vport state is unknown */
+	LPFC_VPORT_FAILED      =  1,    /* vport has failed */
+	LPFC_LOCAL_CFG_LINK    =  6,    /* local NPORT Id configured */
+	LPFC_FLOGI             =  7,    /* FLOGI sent to Fabric */
+	LPFC_FDISC             =  8,    /* FDISC sent for vport */
+	LPFC_FABRIC_CFG_LINK   =  9,    /* Fabric assigned NPORT Id
+				         * configured */
+	LPFC_NS_REG            =  10,   /* Register with NameServer */
+	LPFC_NS_QRY            =  11,   /* Query NameServer for NPort ID list */
+	LPFC_BUILD_DISC_LIST   =  12,   /* Build ADISC and PLOGI lists for
+				         * device authentication / discovery */
+	LPFC_DISC_AUTH         =  13,   /* Processing ADISC list */
+	LPFC_VPORT_READY       =  32,
+};
 
-	int32_t stopped;   /* HBA has not been restarted since last ERATT */
-	uint8_t fc_linkspeed;	/* Link speed after last READ_LA */
+enum hba_state {
+	LPFC_LINK_UNKNOWN    =   0,   /* HBA state is unknown */
+	LPFC_WARM_START      =   1,   /* HBA state after selective reset */
+	LPFC_INIT_START      =   2,   /* Initial state after board reset */
+	LPFC_INIT_MBX_CMDS   =   3,   /* Initialize HBA with mbox commands */
+	LPFC_LINK_DOWN       =   4,   /* HBA initialized, link is down */
+	LPFC_LINK_UP         =   5,   /* Link is up  - issue READ_LA */
+	LPFC_CLEAR_LA        =   6,   /* authentication cmplt - issue
+				       * CLEAR_LA */
+	LPFC_HBA_READY       =  32,
+	LPFC_HBA_ERROR       =  -1
+};
 
-	uint32_t fc_eventTag;	/* event tag for link attention */
-	uint32_t fc_prli_sent;	/* cntr for outstanding PRLIs */
+struct lpfc_vport {
+	struct list_head listentry;
+	struct lpfc_hba *phba;
+	uint8_t port_type;
+#define LPFC_PHYSICAL_PORT 1
+#define LPFC_NPIV_PORT  2
+#define LPFC_FABRIC_PORT 3
+	enum discovery_state port_state;
 
-	uint32_t num_disc_nodes;	/*in addition to hba_state */
+	uint16_t vpi;
 
-	struct timer_list fc_estabtmo;	/* link establishment timer */
-	struct timer_list fc_disctmo;	/* Discovery rescue timer */
-	struct timer_list fc_fdmitmo;	/* fdmi timer */
-	/* These fields used to be binfo */
-	struct lpfc_name fc_nodename;	/* fc nodename */
-	struct lpfc_name fc_portname;	/* fc portname */
-	uint32_t fc_pref_DID;	/* preferred D_ID */
-	uint8_t fc_pref_ALPA;	/* preferred AL_PA */
-	uint32_t fc_edtov;	/* E_D_TOV timer value */
-	uint32_t fc_arbtov;	/* ARB_TOV timer value */
-	uint32_t fc_ratov;	/* R_A_TOV timer value */
-	uint32_t fc_rttov;	/* R_T_TOV timer value */
-	uint32_t fc_altov;	/* AL_TOV timer value */
-	uint32_t fc_crtov;	/* C_R_TOV timer value */
-	uint32_t fc_citov;	/* C_I_TOV timer value */
-	uint32_t fc_myDID;	/* fibre channel S_ID */
-	uint32_t fc_prevDID;	/* previous fibre channel S_ID */
-
-	struct serv_parm fc_sparam;	/* buffer for our service parameters */
-	struct serv_parm fc_fabparam;	/* fabric service parameters buffer */
-	uint8_t alpa_map[128];	/* AL_PA map from READ_LA */
-
-	uint8_t fc_ns_retry;	/* retries for fabric nameserver */
-	uint32_t fc_nlp_cnt;	/* outstanding NODELIST requests */
-	uint32_t fc_rscn_id_cnt;	/* count of RSCNs payloads in list */
-	struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
-	uint32_t lmt;
 	uint32_t fc_flag;	/* FC flags */
-#define FC_PT2PT                0x1	/* pt2pt with no fabric */
-#define FC_PT2PT_PLOGI          0x2	/* pt2pt initiate PLOGI */
-#define FC_DISC_TMO             0x4	/* Discovery timer running */
-#define FC_PUBLIC_LOOP          0x8	/* Public loop */
-#define FC_LBIT                 0x10	/* LOGIN bit in loopinit set */
-#define FC_RSCN_MODE            0x20	/* RSCN cmd rcv'ed */
-#define FC_NLP_MORE             0x40	/* More node to process in node tbl */
-#define FC_OFFLINE_MODE         0x80	/* Interface is offline for diag */
-#define FC_FABRIC               0x100	/* We are fabric attached */
-#define FC_ESTABLISH_LINK       0x200	/* Reestablish Link */
-#define FC_RSCN_DISCOVERY       0x400	/* Authenticate all devices after RSCN*/
-#define FC_BLOCK_MGMT_IO        0x800   /* Don't allow mgmt mbx or iocb cmds */
-#define FC_LOADING		0x1000	/* HBA in process of loading drvr */
-#define FC_UNLOADING		0x2000	/* HBA in process of unloading drvr */
-#define FC_SCSI_SCAN_TMO        0x4000	/* scsi scan timer running */
-#define FC_ABORT_DISCOVERY      0x8000	/* we want to abort discovery */
-#define FC_NDISC_ACTIVE         0x10000	/* NPort discovery active */
-#define FC_BYPASSED_MODE        0x20000	/* NPort is in bypassed mode */
-#define FC_LOOPBACK_MODE        0x40000	/* NPort is in Loopback mode */
-					/* This flag is set while issuing */
-					/* INIT_LINK mailbox command */
-#define FC_IGNORE_ERATT         0x80000	/* intr handler should ignore ERATT */
-
-	uint32_t fc_topology;	/* link topology, from LINK INIT */
-
-	struct lpfc_stats fc_stat;
+/* Several of these flags are HBA centric and should be moved to
+ * phba->link_flag (e.g. FC_PTP, FC_PUBLIC_LOOP)
+ */
+#define FC_PT2PT                0x1	 /* pt2pt with no fabric */
+#define FC_PT2PT_PLOGI          0x2	 /* pt2pt initiate PLOGI */
+#define FC_DISC_TMO             0x4	 /* Discovery timer running */
+#define FC_PUBLIC_LOOP          0x8	 /* Public loop */
+#define FC_LBIT                 0x10	 /* LOGIN bit in loopinit set */
+#define FC_RSCN_MODE            0x20	 /* RSCN cmd rcv'ed */
+#define FC_NLP_MORE             0x40	 /* More node to process in node tbl */
+#define FC_OFFLINE_MODE         0x80	 /* Interface is offline for diag */
+#define FC_FABRIC               0x100	 /* We are fabric attached */
+#define FC_ESTABLISH_LINK       0x200	 /* Reestablish Link */
+#define FC_RSCN_DISCOVERY       0x400	 /* Auth all devices after RSCN */
+#define FC_SCSI_SCAN_TMO        0x4000	 /* scsi scan timer running */
+#define FC_ABORT_DISCOVERY      0x8000	 /* we want to abort discovery */
+#define FC_NDISC_ACTIVE         0x10000	 /* NPort discovery active */
+#define FC_BYPASSED_MODE        0x20000	 /* NPort is in bypassed mode */
+#define FC_RFF_NOT_SUPPORTED    0x40000	 /* RFF_ID was rejected by switch */
+#define FC_VPORT_NEEDS_REG_VPI	0x80000  /* Needs to have its vpi registered */
+#define FC_RSCN_DEFERRED	0x100000 /* A deferred RSCN being processed */
 
 	struct list_head fc_nodes;
 
@@ -267,10 +286,131 @@
 	uint16_t fc_map_cnt;
 	uint16_t fc_npr_cnt;
 	uint16_t fc_unused_cnt;
+	struct serv_parm fc_sparam;	/* buffer for our service parameters */
+
+	uint32_t fc_myDID;	/* fibre channel S_ID */
+	uint32_t fc_prevDID;	/* previous fibre channel S_ID */
+
+	int32_t stopped;   /* HBA has not been restarted since last ERATT */
+	uint8_t fc_linkspeed;	/* Link speed after last READ_LA */
+
+	uint32_t num_disc_nodes;	/*in addition to hba_state */
+
+	uint32_t fc_nlp_cnt;	/* outstanding NODELIST requests */
+	uint32_t fc_rscn_id_cnt;	/* count of RSCNs payloads in list */
+	struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
+	struct lpfc_name fc_nodename;	/* fc nodename */
+	struct lpfc_name fc_portname;	/* fc portname */
+
+	struct lpfc_work_evt disc_timeout_evt;
+
+	struct timer_list fc_disctmo;	/* Discovery rescue timer */
+	uint8_t fc_ns_retry;	/* retries for fabric nameserver */
+	uint32_t fc_prli_sent;	/* cntr for outstanding PRLIs */
+
+	spinlock_t work_port_lock;
+	uint32_t work_port_events; /* Timeout to be handled  */
+#define WORKER_DISC_TMO                0x1	/* vport: Discovery timeout */
+#define WORKER_ELS_TMO                 0x2	/* vport: ELS timeout */
+#define WORKER_FDMI_TMO                0x4	/* vport: FDMI timeout */
+
+#define WORKER_MBOX_TMO                0x100	/* hba: MBOX timeout */
+#define WORKER_HB_TMO                  0x200	/* hba: Heart beat timeout */
+#define WORKER_FABRIC_BLOCK_TMO        0x400	/* hba: fabric block timout */
+#define WORKER_RAMP_DOWN_QUEUE         0x800	/* hba: Decrease Q depth */
+#define WORKER_RAMP_UP_QUEUE           0x1000	/* hba: Increase Q depth */
+
+	struct timer_list fc_fdmitmo;
+	struct timer_list els_tmofunc;
+
+	int unreg_vpi_cmpl;
+
+	uint8_t load_flag;
+#define FC_LOADING		0x1	/* HBA in process of loading drvr */
+#define FC_UNLOADING		0x2	/* HBA in process of unloading drvr */
+	char  *vname;		        /* Application assigned name */
+	struct fc_vport *fc_vport;
+
+#ifdef CONFIG_LPFC_DEBUG_FS
+	struct dentry *debug_disc_trc;
+	struct dentry *debug_nodelist;
+	struct dentry *vport_debugfs_root;
+	struct lpfc_disc_trc *disc_trc;
+	atomic_t disc_trc_cnt;
+#endif
+};
+
+struct hbq_s {
+	uint16_t entry_count;	  /* Current number of HBQ slots */
+	uint32_t next_hbqPutIdx;  /* Index to next HBQ slot to use */
+	uint32_t hbqPutIdx;	  /* HBQ slot to use */
+	uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */
+};
+
+#define LPFC_MAX_HBQS  16
+/* this matches the possition in the lpfc_hbq_defs array */
+#define LPFC_ELS_HBQ	0
+
+struct lpfc_hba {
+	struct lpfc_sli sli;
+	uint32_t sli_rev;		/* SLI2 or SLI3 */
+	uint32_t sli3_options;		/* Mask of enabled SLI3 options */
+#define LPFC_SLI3_ENABLED 	 0x01
+#define LPFC_SLI3_HBQ_ENABLED	 0x02
+#define LPFC_SLI3_NPIV_ENABLED	 0x04
+#define LPFC_SLI3_VPORT_TEARDOWN 0x08
+	uint32_t iocb_cmd_size;
+	uint32_t iocb_rsp_size;
+
+	enum hba_state link_state;
+	uint32_t link_flag;	/* link state flags */
+#define LS_LOOPBACK_MODE      0x1 	/* NPort is in Loopback mode */
+					/* This flag is set while issuing */
+					/* INIT_LINK mailbox command */
+#define LS_NPIV_FAB_SUPPORTED 0x2	/* Fabric supports NPIV */
+#define LS_IGNORE_ERATT       0x3	/* intr handler should ignore ERATT */
+
+	struct lpfc_sli2_slim *slim2p;
+	struct lpfc_dmabuf hbqslimp;
+
+	dma_addr_t slim2p_mapping;
+
+	uint16_t pci_cfg_value;
+
+	uint8_t work_found;
+#define LPFC_MAX_WORKER_ITERATION  4
+
+	uint8_t fc_linkspeed;	/* Link speed after last READ_LA */
+
+	uint32_t fc_eventTag;	/* event tag for link attention */
+
+
+	struct timer_list fc_estabtmo;	/* link establishment timer */
+	/* These fields used to be binfo */
+	uint32_t fc_pref_DID;	/* preferred D_ID */
+	uint8_t  fc_pref_ALPA;	/* preferred AL_PA */
+	uint32_t fc_edtov;	/* E_D_TOV timer value */
+	uint32_t fc_arbtov;	/* ARB_TOV timer value */
+	uint32_t fc_ratov;	/* R_A_TOV timer value */
+	uint32_t fc_rttov;	/* R_T_TOV timer value */
+	uint32_t fc_altov;	/* AL_TOV timer value */
+	uint32_t fc_crtov;	/* C_R_TOV timer value */
+	uint32_t fc_citov;	/* C_I_TOV timer value */
+
+	struct serv_parm fc_fabparam;	/* fabric service parameters buffer */
+	uint8_t alpa_map[128];	/* AL_PA map from READ_LA */
+
+	uint32_t lmt;
+
+	uint32_t fc_topology;	/* link topology, from LINK INIT */
+
+	struct lpfc_stats fc_stat;
+
 	struct lpfc_nodelist fc_fcpnodev; /* nodelist entry for no device */
 	uint32_t nport_event_cnt;	/* timestamp for nlplist entry */
 
-	uint32_t wwnn[2];
+	uint8_t  wwnn[8];
+	uint8_t  wwpn[8];
 	uint32_t RandomData[7];
 
 	uint32_t cfg_log_verbose;
@@ -278,6 +418,9 @@
 	uint32_t cfg_nodev_tmo;
 	uint32_t cfg_devloss_tmo;
 	uint32_t cfg_hba_queue_depth;
+	uint32_t cfg_peer_port_login;
+	uint32_t cfg_vport_restrict_login;
+	uint32_t cfg_npiv_enable;
 	uint32_t cfg_fcp_class;
 	uint32_t cfg_use_adisc;
 	uint32_t cfg_ack0;
@@ -304,22 +447,20 @@
 
 	lpfc_vpd_t vpd;		/* vital product data */
 
-	struct Scsi_Host *host;
 	struct pci_dev *pcidev;
 	struct list_head      work_list;
 	uint32_t              work_ha;      /* Host Attention Bits for WT */
 	uint32_t              work_ha_mask; /* HA Bits owned by WT        */
 	uint32_t              work_hs;      /* HS stored in case of ERRAT */
 	uint32_t              work_status[2]; /* Extra status from SLIM */
-	uint32_t              work_hba_events; /* Timeout to be handled  */
-#define WORKER_DISC_TMO                0x1	/* Discovery timeout */
-#define WORKER_ELS_TMO                 0x2	/* ELS timeout */
-#define WORKER_MBOX_TMO                0x4	/* MBOX timeout */
-#define WORKER_FDMI_TMO                0x8	/* FDMI timeout */
 
 	wait_queue_head_t    *work_wait;
 	struct task_struct   *worker_thread;
 
+	struct list_head hbq_buffer_list;
+	uint32_t hbq_count;	        /* Count of configured HBQs */
+	struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies  */
+
 	unsigned long pci_bar0_map;     /* Physical address for PCI BAR0 */
 	unsigned long pci_bar2_map;     /* Physical address for PCI BAR2 */
 	void __iomem *slim_memmap_p;	/* Kernel memory mapped address for
@@ -334,6 +475,10 @@
 					   reg */
 	void __iomem *HCregaddr;	/* virtual address for host ctl reg */
 
+	struct lpfc_hgp __iomem *host_gp; /* Host side get/put pointers */
+	uint32_t __iomem  *hbq_put;     /* Address in SLIM to HBQ put ptrs */
+	uint32_t          *hbq_get;     /* Host mem address of HBQ get ptrs */
+
 	int brd_no;			/* FC board number */
 
 	char SerialNumber[32];		/* adapter Serial Number */
@@ -353,7 +498,6 @@
 	uint8_t soft_wwn_enable;
 
 	struct timer_list fcp_poll_timer;
-	struct timer_list els_tmofunc;
 
 	/*
 	 * stat  counters
@@ -370,31 +514,69 @@
 	uint32_t total_scsi_bufs;
 	struct list_head lpfc_iocb_list;
 	uint32_t total_iocbq_bufs;
+	spinlock_t hbalock;
 
 	/* pci_mem_pools */
 	struct pci_pool *lpfc_scsi_dma_buf_pool;
 	struct pci_pool *lpfc_mbuf_pool;
+	struct pci_pool *lpfc_hbq_pool;
 	struct lpfc_dma_pool lpfc_mbuf_safety_pool;
 
 	mempool_t *mbox_mem_pool;
 	mempool_t *nlp_mem_pool;
 
 	struct fc_host_statistics link_stats;
+
+	struct list_head port_list;
+	struct lpfc_vport *pport; /* physical lpfc_vport pointer */
+	uint16_t max_vpi;	/* Maximum virtual nports */
+#define LPFC_MAX_VPI 100  /* Max number of VPorts supported */
+	unsigned long *vpi_bmask; /* vpi allocation table */
+
+	/* Data structure used by fabric iocb scheduler */
+	struct list_head fabric_iocb_list;
+	atomic_t fabric_iocb_count;
+	struct timer_list fabric_block_timer;
+	unsigned long bit_flags;
+#define	FABRIC_COMANDS_BLOCKED	0
+	atomic_t num_rsrc_err;
+	atomic_t num_cmd_success;
+	unsigned long last_rsrc_error_time;
+	unsigned long last_ramp_down_time;
+	unsigned long last_ramp_up_time;
+#ifdef CONFIG_LPFC_DEBUG_FS
+	struct dentry *hba_debugfs_root;
+	atomic_t debugfs_vport_count;
+#endif
+
+	/* Fields used for heart beat. */
+	unsigned long last_completion_time;
+	struct timer_list hb_tmofunc;
+	uint8_t hb_outstanding;
 };
 
-static inline void
-lpfc_set_loopback_flag(struct lpfc_hba *phba) {
-	if (phba->cfg_topology == FLAGS_LOCAL_LB)
-		phba->fc_flag |= FC_LOOPBACK_MODE;
-	else
-		phba->fc_flag &= ~FC_LOOPBACK_MODE;
+static inline struct Scsi_Host *
+lpfc_shost_from_vport(struct lpfc_vport *vport)
+{
+	return container_of((void *) vport, struct Scsi_Host, hostdata[0]);
 }
 
-struct rnidrsp {
-	void *buf;
-	uint32_t uniqueid;
-	struct list_head list;
-	uint32_t data;
-};
+static inline void
+lpfc_set_loopback_flag(struct lpfc_hba *phba)
+{
+	if (phba->cfg_topology == FLAGS_LOCAL_LB)
+		phba->link_flag |= LS_LOOPBACK_MODE;
+	else
+		phba->link_flag &= ~LS_LOOPBACK_MODE;
+}
+
+static inline int
+lpfc_is_link_up(struct lpfc_hba *phba)
+{
+	return  phba->link_state == LPFC_LINK_UP ||
+		phba->link_state == LPFC_CLEAR_LA ||
+		phba->link_state == LPFC_HBA_READY;
+}
 
 #define FC_REG_DUMP_EVENT	0x10	/* Register for Dump events */
+
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 95fe77e..860a52c 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -39,6 +39,7 @@
 #include "lpfc_version.h"
 #include "lpfc_compat.h"
 #include "lpfc_crtn.h"
+#include "lpfc_vport.h"
 
 #define LPFC_DEF_DEVLOSS_TMO 30
 #define LPFC_MIN_DEVLOSS_TMO 1
@@ -76,116 +77,156 @@
 lpfc_info_show(struct class_device *cdev, char *buf)
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
 }
 
 static ssize_t
 lpfc_serialnum_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
 }
 
 static ssize_t
 lpfc_modeldesc_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
 }
 
 static ssize_t
 lpfc_modelname_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
 }
 
 static ssize_t
 lpfc_programtype_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
 }
 
 static ssize_t
-lpfc_portnum_show(struct class_device *cdev, char *buf)
+lpfc_vportnum_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
 }
 
 static ssize_t
 lpfc_fwrev_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	char fwrev[32];
+
 	lpfc_decode_firmware_rev(phba, fwrev, 1);
-	return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
+	return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
 }
 
 static ssize_t
 lpfc_hdw_show(struct class_device *cdev, char *buf)
 {
 	char hdw[9];
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	lpfc_vpd_t *vp = &phba->vpd;
+
 	lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
 	return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
 }
 static ssize_t
 lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
 }
 static ssize_t
 lpfc_state_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-	int len = 0;
-	switch (phba->hba_state) {
-	case LPFC_STATE_UNKNOWN:
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	int  len = 0;
+
+	switch (phba->link_state) {
+	case LPFC_LINK_UNKNOWN:
 	case LPFC_WARM_START:
 	case LPFC_INIT_START:
 	case LPFC_INIT_MBX_CMDS:
 	case LPFC_LINK_DOWN:
+	case LPFC_HBA_ERROR:
 		len += snprintf(buf + len, PAGE_SIZE-len, "Link Down\n");
 		break;
 	case LPFC_LINK_UP:
-	case LPFC_LOCAL_CFG_LINK:
-		len += snprintf(buf + len, PAGE_SIZE-len, "Link Up\n");
-		break;
-	case LPFC_FLOGI:
-	case LPFC_FABRIC_CFG_LINK:
-	case LPFC_NS_REG:
-	case LPFC_NS_QRY:
-	case LPFC_BUILD_DISC_LIST:
-	case LPFC_DISC_AUTH:
 	case LPFC_CLEAR_LA:
-		len += snprintf(buf + len, PAGE_SIZE-len,
-				"Link Up - Discovery\n");
-		break;
 	case LPFC_HBA_READY:
-		len += snprintf(buf + len, PAGE_SIZE-len,
-				"Link Up - Ready:\n");
+		len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n");
+
+		switch (vport->port_state) {
+			len += snprintf(buf + len, PAGE_SIZE-len,
+					"initializing\n");
+			break;
+		case LPFC_LOCAL_CFG_LINK:
+			len += snprintf(buf + len, PAGE_SIZE-len,
+					"Configuring Link\n");
+			break;
+		case LPFC_FDISC:
+		case LPFC_FLOGI:
+		case LPFC_FABRIC_CFG_LINK:
+		case LPFC_NS_REG:
+		case LPFC_NS_QRY:
+		case LPFC_BUILD_DISC_LIST:
+		case LPFC_DISC_AUTH:
+			len += snprintf(buf + len, PAGE_SIZE - len,
+					"Discovery\n");
+			break;
+		case LPFC_VPORT_READY:
+			len += snprintf(buf + len, PAGE_SIZE - len, "Ready\n");
+			break;
+
+		case LPFC_VPORT_FAILED:
+			len += snprintf(buf + len, PAGE_SIZE - len, "Failed\n");
+			break;
+
+		case LPFC_VPORT_UNKNOWN:
+			len += snprintf(buf + len, PAGE_SIZE - len,
+					"Unknown\n");
+			break;
+		}
+
 		if (phba->fc_topology == TOPOLOGY_LOOP) {
-			if (phba->fc_flag & FC_PUBLIC_LOOP)
+			if (vport->fc_flag & FC_PUBLIC_LOOP)
 				len += snprintf(buf + len, PAGE_SIZE-len,
 						"   Public Loop\n");
 			else
 				len += snprintf(buf + len, PAGE_SIZE-len,
 						"   Private Loop\n");
 		} else {
-			if (phba->fc_flag & FC_FABRIC)
+			if (vport->fc_flag & FC_FABRIC)
 				len += snprintf(buf + len, PAGE_SIZE-len,
 						"   Fabric\n");
 			else
@@ -193,29 +234,32 @@
 						"   Point-2-Point\n");
 		}
 	}
+
 	return len;
 }
 
 static ssize_t
 lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-	return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt +
-							phba->fc_unmap_cnt);
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			vport->fc_map_cnt + vport->fc_unmap_cnt);
 }
 
 
 static int
-lpfc_issue_lip(struct Scsi_Host *host)
+lpfc_issue_lip(struct Scsi_Host *shost)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	LPFC_MBOXQ_t *pmboxq;
 	int mbxstatus = MBXERR_ERROR;
 
-	if ((phba->fc_flag & FC_OFFLINE_MODE) ||
-	    (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
-	    (phba->hba_state != LPFC_HBA_READY))
+	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
+	    (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) ||
+	    (vport->port_state != LPFC_VPORT_READY))
 		return -EPERM;
 
 	pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
@@ -238,9 +282,7 @@
 	}
 
 	lpfc_set_loopback_flag(phba);
-	if (mbxstatus == MBX_TIMEOUT)
-		pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-	else
+	if (mbxstatus != MBX_TIMEOUT)
 		mempool_free(pmboxq, phba->mbox_mem_pool);
 
 	if (mbxstatus == MBXERR_ERROR)
@@ -320,8 +362,10 @@
 static ssize_t
 lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	int status = -EINVAL;
 
 	if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
@@ -336,23 +380,26 @@
 static ssize_t
 lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
 }
 
 static ssize_t
 lpfc_board_mode_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	char  * state;
 
-	if (phba->hba_state == LPFC_HBA_ERROR)
+	if (phba->link_state == LPFC_HBA_ERROR)
 		state = "error";
-	else if (phba->hba_state == LPFC_WARM_START)
+	else if (phba->link_state == LPFC_WARM_START)
 		state = "warm start";
-	else if (phba->hba_state == LPFC_INIT_START)
+	else if (phba->link_state == LPFC_INIT_START)
 		state = "offline";
 	else
 		state = "online";
@@ -363,8 +410,9 @@
 static ssize_t
 lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	struct completion online_compl;
 	int status=0;
 
@@ -389,11 +437,166 @@
 		return -EIO;
 }
 
+int
+lpfc_get_hba_info(struct lpfc_hba *phba,
+		  uint32_t *mxri, uint32_t *axri,
+		  uint32_t *mrpi, uint32_t *arpi,
+		  uint32_t *mvpi, uint32_t *avpi)
+{
+	struct lpfc_sli   *psli = &phba->sli;
+	LPFC_MBOXQ_t *pmboxq;
+	MAILBOX_t *pmb;
+	int rc = 0;
+
+	/*
+	 * prevent udev from issuing mailbox commands until the port is
+	 * configured.
+	 */
+	if (phba->link_state < LPFC_LINK_DOWN ||
+	    !phba->mbox_mem_pool ||
+	    (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
+		return 0;
+
+	if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
+		return 0;
+
+	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!pmboxq)
+		return 0;
+	memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
+
+	pmb = &pmboxq->mb;
+	pmb->mbxCommand = MBX_READ_CONFIG;
+	pmb->mbxOwner = OWN_HOST;
+	pmboxq->context1 = NULL;
+
+	if ((phba->pport->fc_flag & FC_OFFLINE_MODE) ||
+		(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+		rc = MBX_NOT_FINISHED;
+	else
+		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+
+	if (rc != MBX_SUCCESS) {
+		if (rc != MBX_TIMEOUT)
+			mempool_free(pmboxq, phba->mbox_mem_pool);
+		return 0;
+	}
+
+	if (mrpi)
+		*mrpi = pmb->un.varRdConfig.max_rpi;
+	if (arpi)
+		*arpi = pmb->un.varRdConfig.avail_rpi;
+	if (mxri)
+		*mxri = pmb->un.varRdConfig.max_xri;
+	if (axri)
+		*axri = pmb->un.varRdConfig.avail_xri;
+	if (mvpi)
+		*mvpi = pmb->un.varRdConfig.max_vpi;
+	if (avpi)
+		*avpi = pmb->un.varRdConfig.avail_vpi;
+
+	mempool_free(pmboxq, phba->mbox_mem_pool);
+	return 1;
+}
+
+static ssize_t
+lpfc_max_rpi_show(struct class_device *cdev, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	uint32_t cnt;
+
+	if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL))
+		return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+	return snprintf(buf, PAGE_SIZE, "Unknown\n");
+}
+
+static ssize_t
+lpfc_used_rpi_show(struct class_device *cdev, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	uint32_t cnt, acnt;
+
+	if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL))
+		return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+	return snprintf(buf, PAGE_SIZE, "Unknown\n");
+}
+
+static ssize_t
+lpfc_max_xri_show(struct class_device *cdev, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	uint32_t cnt;
+
+	if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL))
+		return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+	return snprintf(buf, PAGE_SIZE, "Unknown\n");
+}
+
+static ssize_t
+lpfc_used_xri_show(struct class_device *cdev, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	uint32_t cnt, acnt;
+
+	if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL))
+		return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+	return snprintf(buf, PAGE_SIZE, "Unknown\n");
+}
+
+static ssize_t
+lpfc_max_vpi_show(struct class_device *cdev, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	uint32_t cnt;
+
+	if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL))
+		return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+	return snprintf(buf, PAGE_SIZE, "Unknown\n");
+}
+
+static ssize_t
+lpfc_used_vpi_show(struct class_device *cdev, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	uint32_t cnt, acnt;
+
+	if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt))
+		return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+	return snprintf(buf, PAGE_SIZE, "Unknown\n");
+}
+
+static ssize_t
+lpfc_npiv_info_show(struct class_device *cdev, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
+	if (!(phba->max_vpi))
+		return snprintf(buf, PAGE_SIZE, "NPIV Not Supported\n");
+	if (vport->port_type == LPFC_PHYSICAL_PORT)
+		return snprintf(buf, PAGE_SIZE, "NPIV Physical\n");
+	return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
+}
+
 static ssize_t
 lpfc_poll_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 
 	return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
 }
@@ -402,8 +605,9 @@
 lpfc_poll_store(struct class_device *cdev, const char *buf,
 		size_t count)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	uint32_t creg_val;
 	uint32_t old_val;
 	int val=0;
@@ -417,7 +621,7 @@
 	if ((val & 0x3) != val)
 		return -EINVAL;
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 
 	old_val = phba->cfg_poll;
 
@@ -432,16 +636,16 @@
 			lpfc_poll_start_timer(phba);
 		}
 	} else if (val != 0x0) {
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 		return -EINVAL;
 	}
 
 	if (!(val & DISABLE_FCP_RING_INT) &&
 	    (old_val & DISABLE_FCP_RING_INT))
 	{
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 		del_timer(&phba->fcp_poll_timer);
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(&phba->hbalock);
 		creg_val = readl(phba->HCregaddr);
 		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
 		writel(creg_val, phba->HCregaddr);
@@ -450,7 +654,7 @@
 
 	phba->cfg_poll = val;
 
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	return strlen(buf);
 }
@@ -459,8 +663,9 @@
 static ssize_t \
 lpfc_##attr##_show(struct class_device *cdev, char *buf) \
 { \
-	struct Scsi_Host *host = class_to_shost(cdev);\
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+	struct Scsi_Host  *shost = class_to_shost(cdev);\
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+	struct lpfc_hba   *phba = vport->phba;\
 	int val = 0;\
 	val = phba->cfg_##attr;\
 	return snprintf(buf, PAGE_SIZE, "%d\n",\
@@ -471,8 +676,9 @@
 static ssize_t \
 lpfc_##attr##_show(struct class_device *cdev, char *buf) \
 { \
-	struct Scsi_Host *host = class_to_shost(cdev);\
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+	struct Scsi_Host  *shost = class_to_shost(cdev);\
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+	struct lpfc_hba   *phba = vport->phba;\
 	int val = 0;\
 	val = phba->cfg_##attr;\
 	return snprintf(buf, PAGE_SIZE, "%#x\n",\
@@ -514,8 +720,9 @@
 static ssize_t \
 lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
 { \
-	struct Scsi_Host *host = class_to_shost(cdev);\
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+	struct Scsi_Host  *shost = class_to_shost(cdev);\
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+	struct lpfc_hba   *phba = vport->phba;\
 	int val=0;\
 	if (!isdigit(buf[0]))\
 		return -EINVAL;\
@@ -576,7 +783,7 @@
 static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
 static CLASS_DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
 static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
-static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_portnum_show, NULL);
+static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
 static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
 static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
 static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
@@ -592,6 +799,13 @@
 static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
 			 lpfc_board_mode_show, lpfc_board_mode_store);
 static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
+static CLASS_DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
+static CLASS_DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
+static CLASS_DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
+static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
+static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
+static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
+static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
 
 
 static char *lpfc_soft_wwn_key = "C99G71SL8032A";
@@ -600,8 +814,9 @@
 lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
 				size_t count)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	unsigned int cnt = count;
 
 	/*
@@ -634,8 +849,10 @@
 static ssize_t
 lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
 	return snprintf(buf, PAGE_SIZE, "0x%llx\n",
 			(unsigned long long)phba->cfg_soft_wwpn);
 }
@@ -644,8 +861,9 @@
 static ssize_t
 lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	struct completion online_compl;
 	int stat1=0, stat2=0;
 	unsigned int i, j, cnt=count;
@@ -680,9 +898,9 @@
 		}
 	}
 	phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
-	fc_host_port_name(host) = phba->cfg_soft_wwpn;
+	fc_host_port_name(shost) = phba->cfg_soft_wwpn;
 	if (phba->cfg_soft_wwnn)
-		fc_host_node_name(host) = phba->cfg_soft_wwnn;
+		fc_host_node_name(shost) = phba->cfg_soft_wwnn;
 
 	dev_printk(KERN_NOTICE, &phba->pcidev->dev,
 		   "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
@@ -777,6 +995,15 @@
 static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
 			 lpfc_poll_show, lpfc_poll_store);
 
+int  lpfc_sli_mode = 0;
+module_param(lpfc_sli_mode, int, 0);
+MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
+		 " 0 - auto (SLI-3 if supported),"
+		 " 2 - select SLI-2 even on SLI-3 capable HBAs,"
+		 " 3 - select SLI-3");
+
+LPFC_ATTR_R(npiv_enable, 0, 0, 1, "Enable NPIV functionality");
+
 /*
 # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
 # until the timer expires. Value range is [0,255]. Default value is 30.
@@ -790,8 +1017,9 @@
 static ssize_t
 lpfc_nodev_tmo_show(struct class_device *cdev, char *buf)
 {
-	struct Scsi_Host *host = class_to_shost(cdev);
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	int val = 0;
 	val = phba->cfg_devloss_tmo;
 	return snprintf(buf, PAGE_SIZE, "%d\n",
@@ -832,13 +1060,19 @@
 static void
 lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
 {
+	struct lpfc_vport *vport;
+	struct Scsi_Host  *shost;
 	struct lpfc_nodelist  *ndlp;
 
-	spin_lock_irq(phba->host->host_lock);
-	list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp)
-		if (ndlp->rport)
-			ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo;
-	spin_unlock_irq(phba->host->host_lock);
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		shost = lpfc_shost_from_vport(vport);
+		spin_lock_irq(shost->host_lock);
+		list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
+			if (ndlp->rport)
+				ndlp->rport->dev_loss_tmo =
+					phba->cfg_devloss_tmo;
+		spin_unlock_irq(shost->host_lock);
+	}
 }
 
 static int
@@ -946,6 +1180,33 @@
 	    "Max number of FCP commands we can queue to a lpfc HBA");
 
 /*
+# peer_port_login:  This parameter allows/prevents logins
+# between peer ports hosted on the same physical port.
+# When this parameter is set 0 peer ports of same physical port
+# are not allowed to login to each other.
+# When this parameter is set 1 peer ports of same physical port
+# are allowed to login to each other.
+# Default value of this parameter is 0.
+*/
+LPFC_ATTR_R(peer_port_login, 0, 0, 1,
+	    "Allow peer ports on the same physical port to login to each "
+	    "other.");
+
+/*
+# vport_restrict_login:  This parameter allows/prevents logins
+# between Virtual Ports and remote initiators.
+# When this parameter is not set (0) Virtual Ports will accept PLOGIs from
+# other initiators and will attempt to PLOGI all remote ports.
+# When this parameter is set (1) Virtual Ports will reject PLOGIs from
+# remote ports and will not attempt to PLOGI to other initiators.
+# This parameter does not restrict to the physical port.
+# This parameter does not restrict logins to Fabric resident remote ports.
+# Default value of this parameter is 1.
+*/
+LPFC_ATTR_RW(vport_restrict_login, 1, 0, 1,
+	    "Restrict virtual ports login to remote initiators.");
+
+/*
 # Some disk devices have a "select ID" or "select Target" capability.
 # From a protocol standpoint "select ID" usually means select the
 # Fibre channel "ALPA".  In the FC-AL Profile there is an "informative
@@ -1088,7 +1349,8 @@
 LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible");
 
 
-struct class_device_attribute *lpfc_host_attrs[] = {
+
+struct class_device_attribute *lpfc_hba_attrs[] = {
 	&class_device_attr_info,
 	&class_device_attr_serialnum,
 	&class_device_attr_modeldesc,
@@ -1104,6 +1366,8 @@
 	&class_device_attr_lpfc_log_verbose,
 	&class_device_attr_lpfc_lun_queue_depth,
 	&class_device_attr_lpfc_hba_queue_depth,
+	&class_device_attr_lpfc_peer_port_login,
+	&class_device_attr_lpfc_vport_restrict_login,
 	&class_device_attr_lpfc_nodev_tmo,
 	&class_device_attr_lpfc_devloss_tmo,
 	&class_device_attr_lpfc_fcp_class,
@@ -1119,9 +1383,17 @@
 	&class_device_attr_lpfc_multi_ring_type,
 	&class_device_attr_lpfc_fdmi_on,
 	&class_device_attr_lpfc_max_luns,
+	&class_device_attr_lpfc_npiv_enable,
 	&class_device_attr_nport_evt_cnt,
 	&class_device_attr_management_version,
 	&class_device_attr_board_mode,
+	&class_device_attr_max_vpi,
+	&class_device_attr_used_vpi,
+	&class_device_attr_max_rpi,
+	&class_device_attr_used_rpi,
+	&class_device_attr_max_xri,
+	&class_device_attr_used_xri,
+	&class_device_attr_npiv_info,
 	&class_device_attr_issue_reset,
 	&class_device_attr_lpfc_poll,
 	&class_device_attr_lpfc_poll_tmo,
@@ -1133,12 +1405,15 @@
 };
 
 static ssize_t
-sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+		   char *buf, loff_t off, size_t count)
 {
 	size_t buf_off;
-	struct Scsi_Host *host = class_to_shost(container_of(kobj,
-					     struct class_device, kobj));
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct class_device *cdev = container_of(kobj, struct class_device,
+						 kobj);
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 
 	if ((off + count) > FF_REG_AREA_SIZE)
 		return -ERANGE;
@@ -1148,30 +1423,31 @@
 	if (off % 4 || count % 4 || (unsigned long)buf % 4)
 		return -EINVAL;
 
-	spin_lock_irq(phba->host->host_lock);
-
-	if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
-		spin_unlock_irq(phba->host->host_lock);
+	if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
 		return -EPERM;
 	}
 
+	spin_lock_irq(&phba->hbalock);
 	for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
 		writel(*((uint32_t *)(buf + buf_off)),
 		       phba->ctrl_regs_memmap_p + off + buf_off);
 
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	return count;
 }
 
 static ssize_t
-sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+		  char *buf, loff_t off, size_t count)
 {
 	size_t buf_off;
 	uint32_t * tmp_ptr;
-	struct Scsi_Host *host = class_to_shost(container_of(kobj,
-					     struct class_device, kobj));
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct class_device *cdev = container_of(kobj, struct class_device,
+						 kobj);
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 
 	if (off > FF_REG_AREA_SIZE)
 		return -ERANGE;
@@ -1184,14 +1460,14 @@
 	if (off % 4 || count % 4 || (unsigned long)buf % 4)
 		return -EINVAL;
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 
 	for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) {
 		tmp_ptr = (uint32_t *)(buf + buf_off);
 		*tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off);
 	}
 
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	return count;
 }
@@ -1200,7 +1476,6 @@
 	.attr = {
 		.name = "ctlreg",
 		.mode = S_IRUSR | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 256,
 	.read = sysfs_ctlreg_read,
@@ -1209,7 +1484,7 @@
 
 
 static void
-sysfs_mbox_idle (struct lpfc_hba * phba)
+sysfs_mbox_idle(struct lpfc_hba *phba)
 {
 	phba->sysfs_mbox.state = SMBOX_IDLE;
 	phba->sysfs_mbox.offset = 0;
@@ -1222,12 +1497,15 @@
 }
 
 static ssize_t
-sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+		 char *buf, loff_t off, size_t count)
 {
-	struct Scsi_Host * host =
-		class_to_shost(container_of(kobj, struct class_device, kobj));
-	struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata;
-	struct lpfcMboxq * mbox = NULL;
+	struct class_device *cdev = container_of(kobj, struct class_device,
+						 kobj);
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfcMboxq  *mbox = NULL;
 
 	if ((count + off) > MAILBOX_CMD_SIZE)
 		return -ERANGE;
@@ -1245,7 +1523,7 @@
 		memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
 	}
 
-	spin_lock_irq(host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 
 	if (off == 0) {
 		if (phba->sysfs_mbox.mbox)
@@ -1256,9 +1534,9 @@
 	} else {
 		if (phba->sysfs_mbox.state  != SMBOX_WRITING ||
 		    phba->sysfs_mbox.offset != off           ||
-		    phba->sysfs_mbox.mbox   == NULL ) {
+		    phba->sysfs_mbox.mbox   == NULL) {
 			sysfs_mbox_idle(phba);
-			spin_unlock_irq(host->host_lock);
+			spin_unlock_irq(&phba->hbalock);
 			return -EAGAIN;
 		}
 	}
@@ -1268,18 +1546,20 @@
 
 	phba->sysfs_mbox.offset = off + count;
 
-	spin_unlock_irq(host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	return count;
 }
 
 static ssize_t
-sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+		char *buf, loff_t off, size_t count)
 {
-	struct Scsi_Host *host =
-		class_to_shost(container_of(kobj, struct class_device,
-					    kobj));
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct class_device *cdev = container_of(kobj, struct class_device,
+						 kobj);
+	struct Scsi_Host  *shost = class_to_shost(cdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	int rc;
 
 	if (off > MAILBOX_CMD_SIZE)
@@ -1294,7 +1574,7 @@
 	if (off && count == 0)
 		return 0;
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 
 	if (off == 0 &&
 	    phba->sysfs_mbox.state  == SMBOX_WRITING &&
@@ -1317,12 +1597,12 @@
 		case MBX_SET_MASK:
 		case MBX_SET_SLIM:
 		case MBX_SET_DEBUG:
-			if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
+			if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
 				printk(KERN_WARNING "mbox_read:Command 0x%x "
 				       "is illegal in on-line state\n",
 				       phba->sysfs_mbox.mbox->mb.mbxCommand);
 				sysfs_mbox_idle(phba);
-				spin_unlock_irq(phba->host->host_lock);
+				spin_unlock_irq(&phba->hbalock);
 				return -EPERM;
 			}
 		case MBX_LOAD_SM:
@@ -1352,48 +1632,48 @@
 			printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n",
 			       phba->sysfs_mbox.mbox->mb.mbxCommand);
 			sysfs_mbox_idle(phba);
-			spin_unlock_irq(phba->host->host_lock);
+			spin_unlock_irq(&phba->hbalock);
 			return -EPERM;
 		default:
 			printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n",
 			       phba->sysfs_mbox.mbox->mb.mbxCommand);
 			sysfs_mbox_idle(phba);
-			spin_unlock_irq(phba->host->host_lock);
+			spin_unlock_irq(&phba->hbalock);
 			return -EPERM;
 		}
 
-		if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
+		phba->sysfs_mbox.mbox->vport = vport;
+
+		if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
 			sysfs_mbox_idle(phba);
-			spin_unlock_irq(host->host_lock);
+			spin_unlock_irq(&phba->hbalock);
 			return  -EAGAIN;
 		}
 
-		if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+		if ((vport->fc_flag & FC_OFFLINE_MODE) ||
 		    (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
 
-			spin_unlock_irq(phba->host->host_lock);
+			spin_unlock_irq(&phba->hbalock);
 			rc = lpfc_sli_issue_mbox (phba,
 						  phba->sysfs_mbox.mbox,
 						  MBX_POLL);
-			spin_lock_irq(phba->host->host_lock);
+			spin_lock_irq(&phba->hbalock);
 
 		} else {
-			spin_unlock_irq(phba->host->host_lock);
+			spin_unlock_irq(&phba->hbalock);
 			rc = lpfc_sli_issue_mbox_wait (phba,
 						       phba->sysfs_mbox.mbox,
 				lpfc_mbox_tmo_val(phba,
 				    phba->sysfs_mbox.mbox->mb.mbxCommand) * HZ);
-			spin_lock_irq(phba->host->host_lock);
+			spin_lock_irq(&phba->hbalock);
 		}
 
 		if (rc != MBX_SUCCESS) {
 			if (rc == MBX_TIMEOUT) {
-				phba->sysfs_mbox.mbox->mbox_cmpl =
-					lpfc_sli_def_mbox_cmpl;
 				phba->sysfs_mbox.mbox = NULL;
 			}
 			sysfs_mbox_idle(phba);
-			spin_unlock_irq(host->host_lock);
+			spin_unlock_irq(&phba->hbalock);
 			return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
 		}
 		phba->sysfs_mbox.state = SMBOX_READING;
@@ -1402,7 +1682,7 @@
 		 phba->sysfs_mbox.state  != SMBOX_READING) {
 		printk(KERN_WARNING  "mbox_read: Bad State\n");
 		sysfs_mbox_idle(phba);
-		spin_unlock_irq(host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 		return -EAGAIN;
 	}
 
@@ -1413,7 +1693,7 @@
 	if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
 		sysfs_mbox_idle(phba);
 
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	return count;
 }
@@ -1422,7 +1702,6 @@
 	.attr = {
 		.name = "mbox",
 		.mode = S_IRUSR | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = MAILBOX_CMD_SIZE,
 	.read = sysfs_mbox_read,
@@ -1430,35 +1709,35 @@
 };
 
 int
-lpfc_alloc_sysfs_attr(struct lpfc_hba *phba)
+lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
 {
-	struct Scsi_Host *host = phba->host;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	int error;
 
-	error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-							&sysfs_ctlreg_attr);
+	error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
+				      &sysfs_ctlreg_attr);
 	if (error)
 		goto out;
 
-	error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-							&sysfs_mbox_attr);
+	error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
+				      &sysfs_mbox_attr);
 	if (error)
 		goto out_remove_ctlreg_attr;
 
 	return 0;
 out_remove_ctlreg_attr:
-	sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
+	sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
 out:
 	return error;
 }
 
 void
-lpfc_free_sysfs_attr(struct lpfc_hba *phba)
+lpfc_free_sysfs_attr(struct lpfc_vport *vport)
 {
-	struct Scsi_Host *host = phba->host;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
-	sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_mbox_attr);
-	sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
+	sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_mbox_attr);
+	sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
 }
 
 
@@ -1469,26 +1748,30 @@
 static void
 lpfc_get_host_port_id(struct Scsi_Host *shost)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+
 	/* note: fc_myDID already in cpu endianness */
-	fc_host_port_id(shost) = phba->fc_myDID;
+	fc_host_port_id(shost) = vport->fc_myDID;
 }
 
 static void
 lpfc_get_host_port_type(struct Scsi_Host *shost)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 
 	spin_lock_irq(shost->host_lock);
 
-	if (phba->hba_state == LPFC_HBA_READY) {
+	if (vport->port_type == LPFC_NPIV_PORT) {
+		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
+	} else if (lpfc_is_link_up(phba)) {
 		if (phba->fc_topology == TOPOLOGY_LOOP) {
-			if (phba->fc_flag & FC_PUBLIC_LOOP)
+			if (vport->fc_flag & FC_PUBLIC_LOOP)
 				fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
 			else
 				fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
 		} else {
-			if (phba->fc_flag & FC_FABRIC)
+			if (vport->fc_flag & FC_FABRIC)
 				fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
 			else
 				fc_host_port_type(shost) = FC_PORTTYPE_PTP;
@@ -1502,29 +1785,20 @@
 static void
 lpfc_get_host_port_state(struct Scsi_Host *shost)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 
 	spin_lock_irq(shost->host_lock);
 
-	if (phba->fc_flag & FC_OFFLINE_MODE)
+	if (vport->fc_flag & FC_OFFLINE_MODE)
 		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
 	else {
-		switch (phba->hba_state) {
-		case LPFC_STATE_UNKNOWN:
-		case LPFC_WARM_START:
-		case LPFC_INIT_START:
-		case LPFC_INIT_MBX_CMDS:
+		switch (phba->link_state) {
+		case LPFC_LINK_UNKNOWN:
 		case LPFC_LINK_DOWN:
 			fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
 			break;
 		case LPFC_LINK_UP:
-		case LPFC_LOCAL_CFG_LINK:
-		case LPFC_FLOGI:
-		case LPFC_FABRIC_CFG_LINK:
-		case LPFC_NS_REG:
-		case LPFC_NS_QRY:
-		case LPFC_BUILD_DISC_LIST:
-		case LPFC_DISC_AUTH:
 		case LPFC_CLEAR_LA:
 		case LPFC_HBA_READY:
 			/* Links up, beyond this port_type reports state */
@@ -1545,11 +1819,12 @@
 static void
 lpfc_get_host_speed(struct Scsi_Host *shost)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 
 	spin_lock_irq(shost->host_lock);
 
-	if (phba->hba_state == LPFC_HBA_READY) {
+	if (lpfc_is_link_up(phba)) {
 		switch(phba->fc_linkspeed) {
 			case LA_1GHZ_LINK:
 				fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
@@ -1575,39 +1850,31 @@
 static void
 lpfc_get_host_fabric_name (struct Scsi_Host *shost)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	u64 node_name;
 
 	spin_lock_irq(shost->host_lock);
 
-	if ((phba->fc_flag & FC_FABRIC) ||
+	if ((vport->fc_flag & FC_FABRIC) ||
 	    ((phba->fc_topology == TOPOLOGY_LOOP) &&
-	     (phba->fc_flag & FC_PUBLIC_LOOP)))
+	     (vport->fc_flag & FC_PUBLIC_LOOP)))
 		node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
 	else
 		/* fabric is local port if there is no F/FL_Port */
-		node_name = wwn_to_u64(phba->fc_nodename.u.wwn);
+		node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
 
 	spin_unlock_irq(shost->host_lock);
 
 	fc_host_fabric_name(shost) = node_name;
 }
 
-static void
-lpfc_get_host_symbolic_name (struct Scsi_Host *shost)
-{
-	struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
-
-	spin_lock_irq(shost->host_lock);
-	lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
-	spin_unlock_irq(shost->host_lock);
-}
-
 static struct fc_host_statistics *
 lpfc_get_stats(struct Scsi_Host *shost)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_sli   *psli = &phba->sli;
 	struct fc_host_statistics *hs = &phba->link_stats;
 	struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
 	LPFC_MBOXQ_t *pmboxq;
@@ -1615,7 +1882,16 @@
 	unsigned long seconds;
 	int rc = 0;
 
-	if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+	/*
+	 * prevent udev from issuing mailbox commands until the port is
+	 * configured.
+	 */
+	if (phba->link_state < LPFC_LINK_DOWN ||
+	    !phba->mbox_mem_pool ||
+	    (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
+		return NULL;
+
+	if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
 		return NULL;
 
 	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -1627,17 +1903,16 @@
 	pmb->mbxCommand = MBX_READ_STATUS;
 	pmb->mbxOwner = OWN_HOST;
 	pmboxq->context1 = NULL;
+	pmboxq->vport = vport;
 
-	if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
 		(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
 	else
 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
 
 	if (rc != MBX_SUCCESS) {
-		if (rc == MBX_TIMEOUT)
-			pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		else
+		if (rc != MBX_TIMEOUT)
 			mempool_free(pmboxq, phba->mbox_mem_pool);
 		return NULL;
 	}
@@ -1653,18 +1928,17 @@
 	pmb->mbxCommand = MBX_READ_LNK_STAT;
 	pmb->mbxOwner = OWN_HOST;
 	pmboxq->context1 = NULL;
+	pmboxq->vport = vport;
 
-	if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
 	    (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
 	else
 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
 
 	if (rc != MBX_SUCCESS) {
-		if (rc == MBX_TIMEOUT)
-			pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		else
-			mempool_free( pmboxq, phba->mbox_mem_pool);
+		if (rc != MBX_TIMEOUT)
+			mempool_free(pmboxq, phba->mbox_mem_pool);
 		return NULL;
 	}
 
@@ -1711,14 +1985,15 @@
 static void
 lpfc_reset_stats(struct Scsi_Host *shost)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-	struct lpfc_sli *psli = &phba->sli;
-	struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_sli   *psli = &phba->sli;
+	struct lpfc_lnk_stat *lso = &psli->lnk_stat_offsets;
 	LPFC_MBOXQ_t *pmboxq;
 	MAILBOX_t *pmb;
 	int rc = 0;
 
-	if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+	if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
 		return;
 
 	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -1731,17 +2006,16 @@
 	pmb->mbxOwner = OWN_HOST;
 	pmb->un.varWords[0] = 0x1; /* reset request */
 	pmboxq->context1 = NULL;
+	pmboxq->vport = vport;
 
-	if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
 		(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
 	else
 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
 
 	if (rc != MBX_SUCCESS) {
-		if (rc == MBX_TIMEOUT)
-			pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		else
+		if (rc != MBX_TIMEOUT)
 			mempool_free(pmboxq, phba->mbox_mem_pool);
 		return;
 	}
@@ -1750,17 +2024,16 @@
 	pmb->mbxCommand = MBX_READ_LNK_STAT;
 	pmb->mbxOwner = OWN_HOST;
 	pmboxq->context1 = NULL;
+	pmboxq->vport = vport;
 
-	if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
 	    (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
 	else
 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
 
 	if (rc != MBX_SUCCESS) {
-		if (rc == MBX_TIMEOUT)
-			pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		else
+		if (rc != MBX_TIMEOUT)
 			mempool_free( pmboxq, phba->mbox_mem_pool);
 		return;
 	}
@@ -1789,13 +2062,13 @@
 static struct lpfc_nodelist *
 lpfc_get_node_by_target(struct scsi_target *starget)
 {
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
+	struct Scsi_Host  *shost = dev_to_shost(starget->dev.parent);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
 	struct lpfc_nodelist *ndlp;
 
 	spin_lock_irq(shost->host_lock);
 	/* Search for this, mapped, target ID */
-	list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
 		if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
 		    starget->id == ndlp->nlp_sid) {
 			spin_unlock_irq(shost->host_lock);
@@ -1885,8 +2158,66 @@
 	.get_host_fabric_name = lpfc_get_host_fabric_name,
 	.show_host_fabric_name = 1,
 
-	.get_host_symbolic_name = lpfc_get_host_symbolic_name,
-	.show_host_symbolic_name = 1,
+	/*
+	 * The LPFC driver treats linkdown handling as target loss events
+	 * so there are no sysfs handlers for link_down_tmo.
+	 */
+
+	.get_fc_host_stats = lpfc_get_stats,
+	.reset_fc_host_stats = lpfc_reset_stats,
+
+	.dd_fcrport_size = sizeof(struct lpfc_rport_data),
+	.show_rport_maxframe_size = 1,
+	.show_rport_supported_classes = 1,
+
+	.set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+
+	.get_starget_port_id  = lpfc_get_starget_port_id,
+	.show_starget_port_id = 1,
+
+	.get_starget_node_name = lpfc_get_starget_node_name,
+	.show_starget_node_name = 1,
+
+	.get_starget_port_name = lpfc_get_starget_port_name,
+	.show_starget_port_name = 1,
+
+	.issue_fc_host_lip = lpfc_issue_lip,
+	.dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
+	.terminate_rport_io = lpfc_terminate_rport_io,
+
+	.vport_create = lpfc_vport_create,
+	.vport_delete = lpfc_vport_delete,
+	.dd_fcvport_size = sizeof(struct lpfc_vport *),
+};
+
+struct fc_function_template lpfc_vport_transport_functions = {
+	/* fixed attributes the driver supports */
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+	.show_host_supported_fc4s = 1,
+	.show_host_supported_speeds = 1,
+	.show_host_maxframe_size = 1,
+
+	/* dynamic attributes the driver supports */
+	.get_host_port_id = lpfc_get_host_port_id,
+	.show_host_port_id = 1,
+
+	.get_host_port_type = lpfc_get_host_port_type,
+	.show_host_port_type = 1,
+
+	.get_host_port_state = lpfc_get_host_port_state,
+	.show_host_port_state = 1,
+
+	/* active_fc4s is shown but doesn't change (thus no get function) */
+	.show_host_active_fc4s = 1,
+
+	.get_host_speed = lpfc_get_host_speed,
+	.show_host_speed = 1,
+
+	.get_host_fabric_name = lpfc_get_host_fabric_name,
+	.show_host_fabric_name = 1,
 
 	/*
 	 * The LPFC driver treats linkdown handling as target loss events
@@ -1915,6 +2246,8 @@
 	.issue_fc_host_lip = lpfc_issue_lip,
 	.dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
 	.terminate_rport_io = lpfc_terminate_rport_io,
+
+	.vport_disable = lpfc_vport_disable,
 };
 
 void
@@ -1937,6 +2270,9 @@
 	lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
 	lpfc_max_luns_init(phba, lpfc_max_luns);
 	lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
+	lpfc_peer_port_login_init(phba, lpfc_peer_port_login);
+	lpfc_npiv_enable_init(phba, lpfc_npiv_enable);
+	lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login);
 	lpfc_use_msi_init(phba, lpfc_use_msi);
 	lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
 	lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index b8c2a88..e19d1a7 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -23,92 +23,114 @@
 struct fc_rport;
 void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
 void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
+void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
 		 struct lpfc_dmabuf *mp);
 void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
+void lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport);
 void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
-int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
+int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *, int);
 void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
-int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *,
-		   uint32_t);
-void lpfc_unreg_login(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
-void lpfc_unreg_did(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
+int lpfc_reg_login(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
+		   LPFC_MBOXQ_t *, uint32_t);
+void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
+void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
+void lpfc_reg_vpi(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
+void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
 void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
 
-
+void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove);
 int lpfc_linkdown(struct lpfc_hba *);
 void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
 
 void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
+void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
-void lpfc_dequeue_node(struct lpfc_hba *, struct lpfc_nodelist *);
-void lpfc_nlp_set_state(struct lpfc_hba *, struct lpfc_nodelist *, int);
-void lpfc_drop_node(struct lpfc_hba *, struct lpfc_nodelist *);
-void lpfc_set_disctmo(struct lpfc_hba *);
-int lpfc_can_disctmo(struct lpfc_hba *);
-int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
+void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *);
+void lpfc_nlp_set_state(struct lpfc_vport *, struct lpfc_nodelist *, int);
+void lpfc_drop_node(struct lpfc_vport *, struct lpfc_nodelist *);
+void lpfc_set_disctmo(struct lpfc_vport *);
+int  lpfc_can_disctmo(struct lpfc_vport *);
+int  lpfc_unreg_rpi(struct lpfc_vport *, struct lpfc_nodelist *);
+void lpfc_unreg_all_rpis(struct lpfc_vport *);
+void lpfc_unreg_default_rpis(struct lpfc_vport *);
+void lpfc_issue_reg_vpi(struct lpfc_hba *, struct lpfc_vport *);
+
 int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
-		    struct lpfc_iocbq *, struct lpfc_nodelist *);
-void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t);
+			struct lpfc_iocbq *, struct lpfc_nodelist *);
+void lpfc_nlp_init(struct lpfc_vport *, struct lpfc_nodelist *, uint32_t);
 struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *);
 int  lpfc_nlp_put(struct lpfc_nodelist *);
-struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t);
-void lpfc_disc_list_loopmap(struct lpfc_hba *);
-void lpfc_disc_start(struct lpfc_hba *);
-void lpfc_disc_flush_list(struct lpfc_hba *);
+struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t);
+void lpfc_disc_list_loopmap(struct lpfc_vport *);
+void lpfc_disc_start(struct lpfc_vport *);
+void lpfc_disc_flush_list(struct lpfc_vport *);
+void lpfc_cleanup_discovery_resources(struct lpfc_vport *);
 void lpfc_disc_timeout(unsigned long);
 
-struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
-struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
+struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
+struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
 
+void lpfc_worker_wake_up(struct lpfc_hba *);
 int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
 int lpfc_do_work(void *);
-int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
+int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
 			    uint32_t);
 
-int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
-		     struct serv_parm *, uint32_t);
-int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
-int lpfc_els_abort_flogi(struct lpfc_hba *);
-int lpfc_initial_flogi(struct lpfc_hba *);
-int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
-int lpfc_issue_els_prli(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
-int lpfc_issue_els_adisc(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
-int lpfc_issue_els_logo(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
-int lpfc_issue_els_scr(struct lpfc_hba *, uint32_t, uint8_t);
-int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
-int lpfc_els_rsp_acc(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
-		     struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t);
-int lpfc_els_rsp_reject(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
+void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *,
 			struct lpfc_nodelist *);
-int lpfc_els_rsp_adisc_acc(struct lpfc_hba *, struct lpfc_iocbq *,
+void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
+int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
+		     struct serv_parm *, uint32_t);
+int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
+int lpfc_els_chk_latt(struct lpfc_vport *);
+int lpfc_els_abort_flogi(struct lpfc_hba *);
+int lpfc_initial_flogi(struct lpfc_vport *);
+int lpfc_initial_fdisc(struct lpfc_vport *);
+int lpfc_issue_els_fdisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
+int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t);
+int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
+int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
+int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
+int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *);
+int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t);
+int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
+int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
+int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
+		     struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t);
+int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
+			struct lpfc_nodelist *, LPFC_MBOXQ_t *);
+int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *,
 			   struct lpfc_nodelist *);
-int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *,
+int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *,
 			  struct lpfc_nodelist *);
-void lpfc_cancel_retry_delay_tmo(struct lpfc_hba *, struct lpfc_nodelist *);
+void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *);
 void lpfc_els_retry_delay(unsigned long);
 void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
+void lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *);
 void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
 			  struct lpfc_iocbq *);
-int lpfc_els_handle_rscn(struct lpfc_hba *);
-int lpfc_els_flush_rscn(struct lpfc_hba *);
-int lpfc_rscn_payload_check(struct lpfc_hba *, uint32_t);
-void lpfc_els_flush_cmd(struct lpfc_hba *);
-int lpfc_els_disc_adisc(struct lpfc_hba *);
-int lpfc_els_disc_plogi(struct lpfc_hba *);
+int lpfc_els_handle_rscn(struct lpfc_vport *);
+void lpfc_els_flush_rscn(struct lpfc_vport *);
+int lpfc_rscn_payload_check(struct lpfc_vport *, uint32_t);
+void lpfc_els_flush_cmd(struct lpfc_vport *);
+int lpfc_els_disc_adisc(struct lpfc_vport *);
+int lpfc_els_disc_plogi(struct lpfc_vport *);
 void lpfc_els_timeout(unsigned long);
-void lpfc_els_timeout_handler(struct lpfc_hba *);
+void lpfc_els_timeout_handler(struct lpfc_vport *);
+void lpfc_hb_timeout(unsigned long);
+void lpfc_hb_timeout_handler(struct lpfc_hba *);
 
 void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
 			 struct lpfc_iocbq *);
-int lpfc_ns_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
-int lpfc_fdmi_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
+int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
+int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
 void lpfc_fdmi_tmo(unsigned long);
-void lpfc_fdmi_tmo_handler(struct lpfc_hba *);
+void lpfc_fdmi_timeout_handler(struct lpfc_vport *vport);
 
 int lpfc_config_port_prep(struct lpfc_hba *);
 int lpfc_config_port_post(struct lpfc_hba *);
@@ -136,16 +158,23 @@
 void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
 LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
+void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
 
+void lpfc_config_hbq(struct lpfc_hba *, struct lpfc_hbq_init *, uint32_t ,
+		     LPFC_MBOXQ_t *);
+struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t);
+
 int lpfc_mem_alloc(struct lpfc_hba *);
 void lpfc_mem_free(struct lpfc_hba *);
+void lpfc_stop_vport_timers(struct lpfc_vport *);
 
 void lpfc_poll_timeout(unsigned long ptr);
 void lpfc_poll_start_timer(struct lpfc_hba * phba);
 void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
 struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
 void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
+void __lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
 uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
 
 void lpfc_reset_barrier(struct lpfc_hba * phba);
@@ -154,6 +183,7 @@
 int lpfc_sli_brdreset(struct lpfc_hba *);
 int lpfc_sli_brdrestart(struct lpfc_hba *);
 int lpfc_sli_hba_setup(struct lpfc_hba *);
+int lpfc_sli_host_down(struct lpfc_vport *);
 int lpfc_sli_hba_down(struct lpfc_hba *);
 int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
 int lpfc_sli_handle_mb_event(struct lpfc_hba *);
@@ -164,27 +194,36 @@
 int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
 			struct lpfc_iocbq *, uint32_t);
 void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
-int lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
+void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
 int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
 			     struct lpfc_dmabuf *);
 struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
 					     struct lpfc_sli_ring *,
 					     dma_addr_t);
+int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t);
+int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t);
+void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *);
+struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t);
+int lpfc_sli_hbq_size(void);
 int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
 			       struct lpfc_iocbq *);
 int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
-			  uint64_t, lpfc_ctx_cmd);
+		      uint64_t, lpfc_ctx_cmd);
 int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
-			    uint64_t, uint32_t, lpfc_ctx_cmd);
+			uint64_t, uint32_t, lpfc_ctx_cmd);
 
 void lpfc_mbox_timeout(unsigned long);
 void lpfc_mbox_timeout_handler(struct lpfc_hba *);
 
-struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t);
-struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, struct lpfc_name *);
+struct lpfc_nodelist *__lpfc_find_node(struct lpfc_vport *, node_filter,
+				       void *);
+struct lpfc_nodelist *lpfc_find_node(struct lpfc_vport *, node_filter, void *);
+struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t);
+struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *,
+					 struct lpfc_name *);
 
 int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
-			 uint32_t timeout);
+			     uint32_t timeout);
 
 int lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
 			     struct lpfc_sli_ring * pring,
@@ -195,25 +234,56 @@
 			     struct lpfc_iocbq * cmdiocb,
 			     struct lpfc_iocbq * rspiocb);
 
+void *lpfc_hbq_alloc(struct lpfc_hba *, int, dma_addr_t *);
+void lpfc_hbq_free(struct lpfc_hba *, void *, dma_addr_t);
+void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *);
+
 void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
+void __lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
 void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
 
+void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *);
 /* Function prototypes. */
 const char* lpfc_info(struct Scsi_Host *);
-void lpfc_scan_start(struct Scsi_Host *);
 int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
 
 void lpfc_get_cfgparam(struct lpfc_hba *);
-int lpfc_alloc_sysfs_attr(struct lpfc_hba *);
-void lpfc_free_sysfs_attr(struct lpfc_hba *);
-extern struct class_device_attribute *lpfc_host_attrs[];
+int lpfc_alloc_sysfs_attr(struct lpfc_vport *);
+void lpfc_free_sysfs_attr(struct lpfc_vport *);
+extern struct class_device_attribute *lpfc_hba_attrs[];
 extern struct scsi_host_template lpfc_template;
 extern struct fc_function_template lpfc_transport_functions;
+extern struct fc_function_template lpfc_vport_transport_functions;
+extern int lpfc_sli_mode;
 
-void lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp);
+int  lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
 void lpfc_terminate_rport_io(struct fc_rport *);
 void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport);
 
+struct lpfc_vport *lpfc_create_port(struct lpfc_hba *, int, struct fc_vport *);
+int  lpfc_vport_disable(struct fc_vport *fc_vport, bool disable);
+void lpfc_mbx_unreg_vpi(struct lpfc_vport *);
+void destroy_port(struct lpfc_vport *);
+int lpfc_get_instance(void);
+void lpfc_host_attrib_init(struct Scsi_Host *);
+
+extern void lpfc_debugfs_initialize(struct lpfc_vport *);
+extern void lpfc_debugfs_terminate(struct lpfc_vport *);
+extern void lpfc_debugfs_disc_trc(struct lpfc_vport *, int, char *, uint32_t,
+	uint32_t, uint32_t);
+
+/* Interface exported by fabric iocb scheduler */
+int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
+void lpfc_fabric_abort_vport(struct lpfc_vport *);
+void lpfc_fabric_abort_nport(struct lpfc_nodelist *);
+void lpfc_fabric_abort_hba(struct lpfc_hba *);
+void lpfc_fabric_abort_flogi(struct lpfc_hba *);
+void lpfc_fabric_block_timeout(unsigned long);
+void lpfc_unblock_fabric_iocbs(struct lpfc_hba *);
+void lpfc_adjust_queue_depth(struct lpfc_hba *);
+void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
+void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
+
 #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
 #define HBA_EVENT_RSCN                   5
 #define HBA_EVENT_LINK_UP                2
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 34a9e3b..ae9d6f38 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -40,6 +40,8 @@
 #include "lpfc_logmsg.h"
 #include "lpfc_crtn.h"
 #include "lpfc_version.h"
+#include "lpfc_vport.h"
+#include "lpfc_debugfs.h"
 
 #define HBA_PORTSPEED_UNKNOWN               0	/* Unknown - transceiver
 						 * incapable of reporting */
@@ -58,25 +60,69 @@
 /*
  * lpfc_ct_unsol_event
  */
+static void
+lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
+		     struct lpfc_dmabuf *mp, uint32_t size)
+{
+	if (!mp) {
+		printk(KERN_ERR "%s (%d): Unsolited CT, no buffer, "
+		       "piocbq = %p, status = x%x, mp = %p, size = %d\n",
+		       __FUNCTION__, __LINE__,
+		       piocbq, piocbq->iocb.ulpStatus, mp, size);
+	}
+
+	printk(KERN_ERR "%s (%d): Ignoring unsolicted CT piocbq = %p, "
+	       "buffer = %p, size = %d, status = x%x\n",
+	       __FUNCTION__, __LINE__,
+	       piocbq, mp, size,
+	       piocbq->iocb.ulpStatus);
+
+}
+
+static void
+lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
+			  struct lpfc_dmabuf *mp, uint32_t size)
+{
+	if (!mp) {
+		printk(KERN_ERR "%s (%d): Unsolited CT, no "
+		       "HBQ buffer, piocbq = %p, status = x%x\n",
+		       __FUNCTION__, __LINE__,
+		       piocbq, piocbq->iocb.ulpStatus);
+	} else {
+		lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
+		printk(KERN_ERR "%s (%d): Ignoring unsolicted CT "
+		       "piocbq = %p, buffer = %p, size = %d, "
+		       "status = x%x\n",
+		       __FUNCTION__, __LINE__,
+		       piocbq, mp, size, piocbq->iocb.ulpStatus);
+	}
+}
+
 void
-lpfc_ct_unsol_event(struct lpfc_hba * phba,
-		    struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocbq)
+lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+		    struct lpfc_iocbq *piocbq)
 {
 
-	struct lpfc_iocbq *next_piocbq;
-	struct lpfc_dmabuf *pmbuf = NULL;
-	struct lpfc_dmabuf *matp, *next_matp;
-	uint32_t ctx = 0, size = 0, cnt = 0;
+	struct lpfc_dmabuf *mp = NULL;
 	IOCB_t *icmd = &piocbq->iocb;
-	IOCB_t *save_icmd = icmd;
-	int i, go_exit = 0;
-	struct list_head head;
+	int i;
+	struct lpfc_iocbq *iocbq;
+	dma_addr_t paddr;
+	uint32_t size;
+	struct lpfc_dmabuf *bdeBuf1 = piocbq->context2;
+	struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
 
-	if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+	piocbq->context2 = NULL;
+	piocbq->context3 = NULL;
+
+	if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) {
+		lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
+	} else if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
 		((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
 		/* Not enough posted buffers; Try posting more buffers */
 		phba->fc_stat.NoRcvBuf++;
-		lpfc_post_buffer(phba, pring, 0, 1);
+		if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
+			lpfc_post_buffer(phba, pring, 0, 1);
 		return;
 	}
 
@@ -86,66 +132,56 @@
 	if (icmd->ulpBdeCount == 0)
 		return;
 
-	INIT_LIST_HEAD(&head);
-	list_add_tail(&head, &piocbq->list);
-
-	list_for_each_entry_safe(piocbq, next_piocbq, &head, list) {
-		icmd = &piocbq->iocb;
-		if (ctx == 0)
-			ctx = (uint32_t) (icmd->ulpContext);
-		if (icmd->ulpBdeCount == 0)
-			continue;
-
-		for (i = 0; i < icmd->ulpBdeCount; i++) {
-			matp = lpfc_sli_ringpostbuf_get(phba, pring,
-							getPaddr(icmd->un.
-								 cont64[i].
-								 addrHigh,
-								 icmd->un.
-								 cont64[i].
-								 addrLow));
-			if (!matp) {
-				/* Insert lpfc log message here */
-				lpfc_post_buffer(phba, pring, cnt, 1);
-				go_exit = 1;
-				goto ct_unsol_event_exit_piocbq;
+	if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+		list_for_each_entry(iocbq, &piocbq->list, list) {
+			icmd = &iocbq->iocb;
+			if (icmd->ulpBdeCount == 0) {
+				printk(KERN_ERR "%s (%d): Unsolited CT, no "
+				       "BDE, iocbq = %p, status = x%x\n",
+				       __FUNCTION__, __LINE__,
+				       iocbq, iocbq->iocb.ulpStatus);
+				continue;
 			}
 
-			/* Typically for Unsolicited CT requests */
-			if (!pmbuf) {
-				pmbuf = matp;
-				INIT_LIST_HEAD(&pmbuf->list);
-			} else
-				list_add_tail(&matp->list, &pmbuf->list);
-
-			size += icmd->un.cont64[i].tus.f.bdeSize;
-			cnt++;
+			size  = icmd->un.cont64[0].tus.f.bdeSize;
+			lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf1, size);
+			lpfc_in_buf_free(phba, bdeBuf1);
+			if (icmd->ulpBdeCount == 2) {
+				lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf2,
+							  size);
+				lpfc_in_buf_free(phba, bdeBuf2);
+			}
 		}
+	} else {
+		struct lpfc_iocbq  *next;
 
-		icmd->ulpBdeCount = 0;
-	}
+		list_for_each_entry_safe(iocbq, next, &piocbq->list, list) {
+			icmd = &iocbq->iocb;
+			if (icmd->ulpBdeCount == 0) {
+				printk(KERN_ERR "%s (%d): Unsolited CT, no "
+				       "BDE, iocbq = %p, status = x%x\n",
+				       __FUNCTION__, __LINE__,
+				       iocbq, iocbq->iocb.ulpStatus);
+				continue;
+			}
 
-	lpfc_post_buffer(phba, pring, cnt, 1);
-	if (save_icmd->ulpStatus) {
-		go_exit = 1;
-	}
-
-ct_unsol_event_exit_piocbq:
-	list_del(&head);
-	if (pmbuf) {
-		list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) {
-			lpfc_mbuf_free(phba, matp->virt, matp->phys);
-			list_del(&matp->list);
-			kfree(matp);
+			for (i = 0; i < icmd->ulpBdeCount; i++) {
+				paddr = getPaddr(icmd->un.cont64[i].addrHigh,
+						 icmd->un.cont64[i].addrLow);
+				mp = lpfc_sli_ringpostbuf_get(phba, pring,
+							      paddr);
+				size = icmd->un.cont64[i].tus.f.bdeSize;
+				lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
+				lpfc_in_buf_free(phba, mp);
+			}
+			list_del(&iocbq->list);
+			lpfc_sli_release_iocbq(phba, iocbq);
 		}
-		lpfc_mbuf_free(phba, pmbuf->virt, pmbuf->phys);
-		kfree(pmbuf);
 	}
-	return;
 }
 
 static void
-lpfc_free_ct_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mlist)
+lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
 {
 	struct lpfc_dmabuf *mlast, *next_mlast;
 
@@ -160,7 +196,7 @@
 }
 
 static struct lpfc_dmabuf *
-lpfc_alloc_ct_rsp(struct lpfc_hba * phba, int cmdcode, struct ulp_bde64 * bpl,
+lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
 		  uint32_t size, int *entries)
 {
 	struct lpfc_dmabuf *mlist = NULL;
@@ -181,7 +217,8 @@
 
 		INIT_LIST_HEAD(&mp->list);
 
-		if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT))
+		if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) ||
+		    cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID))
 			mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
 		else
 			mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
@@ -201,8 +238,8 @@
 
 		bpl->tus.f.bdeFlags = BUFF_USE_RCV;
 		/* build buffer ptr list for IOCB */
-		bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
-		bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
+		bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
+		bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
 		bpl->tus.f.bdeSize = (uint16_t) cnt;
 		bpl->tus.w = le32_to_cpu(bpl->tus.w);
 		bpl++;
@@ -215,24 +252,49 @@
 	return mlist;
 }
 
+int
+lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb)
+{
+	struct lpfc_dmabuf *buf_ptr;
+
+	if (ctiocb->context1) {
+		buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1;
+		lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+		kfree(buf_ptr);
+		ctiocb->context1 = NULL;
+	}
+	if (ctiocb->context2) {
+		lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2);
+		ctiocb->context2 = NULL;
+	}
+
+	if (ctiocb->context3) {
+		buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3;
+		lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+		kfree(buf_ptr);
+		ctiocb->context1 = NULL;
+	}
+	lpfc_sli_release_iocbq(phba, ctiocb);
+	return 0;
+}
+
 static int
-lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
+lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
 	     struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
 	     void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
 		     struct lpfc_iocbq *),
 	     struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry,
-	     uint32_t tmo)
+	     uint32_t tmo, uint8_t retry)
 {
-
-	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_hba  *phba = vport->phba;
+	struct lpfc_sli  *psli = &phba->sli;
 	struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
 	IOCB_t *icmd;
 	struct lpfc_iocbq *geniocb;
+	int rc;
 
 	/* Allocate buffer for  command iocb */
-	spin_lock_irq(phba->host->host_lock);
 	geniocb = lpfc_sli_get_iocbq(phba);
-	spin_unlock_irq(phba->host->host_lock);
 
 	if (geniocb == NULL)
 		return 1;
@@ -272,31 +334,40 @@
 	icmd->ulpClass = CLASS3;
 	icmd->ulpContext = ndlp->nlp_rpi;
 
+	if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+		/* For GEN_REQUEST64_CR, use the RPI */
+		icmd->ulpCt_h = 0;
+		icmd->ulpCt_l = 0;
+	}
+
 	/* Issue GEN REQ IOCB for NPORT <did> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0119 Issue GEN REQ IOCB for NPORT x%x "
-			"Data: x%x x%x\n", phba->brd_no, icmd->un.ulpWord[5],
-			icmd->ulpIoTag, phba->hba_state);
+			"%d (%d):0119 Issue GEN REQ IOCB to NPORT x%x "
+			"Data: x%x x%x\n", phba->brd_no, vport->vpi,
+			ndlp->nlp_DID, icmd->ulpIoTag,
+			vport->port_state);
 	geniocb->iocb_cmpl = cmpl;
 	geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
-	spin_lock_irq(phba->host->host_lock);
-	if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) {
+	geniocb->vport = vport;
+	geniocb->retry = retry;
+	rc = lpfc_sli_issue_iocb(phba, pring, geniocb, 0);
+
+	if (rc == IOCB_ERROR) {
 		lpfc_sli_release_iocbq(phba, geniocb);
-		spin_unlock_irq(phba->host->host_lock);
 		return 1;
 	}
-	spin_unlock_irq(phba->host->host_lock);
 
 	return 0;
 }
 
 static int
-lpfc_ct_cmd(struct lpfc_hba *phba, struct lpfc_dmabuf *inmp,
+lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
 	    struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp,
 	    void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
 			  struct lpfc_iocbq *),
-	    uint32_t rsp_size)
+	    uint32_t rsp_size, uint8_t retry)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt;
 	struct lpfc_dmabuf *outmp;
 	int cnt = 0, status;
@@ -310,8 +381,8 @@
 	if (!outmp)
 		return -ENOMEM;
 
-	status = lpfc_gen_req(phba, bmp, inmp, outmp, cmpl, ndlp, 0,
-			      cnt+1, 0);
+	status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0,
+			      cnt+1, 0, retry);
 	if (status) {
 		lpfc_free_ct_rsp(phba, outmp);
 		return -ENOMEM;
@@ -319,20 +390,35 @@
 	return 0;
 }
 
+static struct lpfc_vport *
+lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) {
+
+	struct lpfc_vport *vport_curr;
+
+	list_for_each_entry(vport_curr, &phba->port_list, listentry) {
+		if ((vport_curr->fc_myDID) &&
+			(vport_curr->fc_myDID == did))
+			return vport_curr;
+	}
+
+	return NULL;
+}
+
 static int
-lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
+lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_sli_ct_request *Response =
 		(struct lpfc_sli_ct_request *) mp->virt;
 	struct lpfc_nodelist *ndlp = NULL;
 	struct lpfc_dmabuf *mlast, *next_mp;
 	uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
-	uint32_t Did;
-	uint32_t CTentry;
+	uint32_t Did, CTentry;
 	int Cnt;
 	struct list_head head;
 
-	lpfc_set_disctmo(phba);
+	lpfc_set_disctmo(vport);
+	vport->num_disc_nodes = 0;
 
 
 	list_add_tail(&head, &mp->list);
@@ -350,39 +436,96 @@
 
 		/* Loop through entire NameServer list of DIDs */
 		while (Cnt >= sizeof (uint32_t)) {
-
 			/* Get next DID from NameServer List */
 			CTentry = *ctptr++;
 			Did = ((be32_to_cpu(CTentry)) & Mask_DID);
 
 			ndlp = NULL;
-			if (Did != phba->fc_myDID) {
-				/* Check for rscn processing or not */
-				ndlp = lpfc_setup_disc_node(phba, Did);
-			}
-			/* Mark all node table entries that are in the
-			   Nameserver */
-			if (ndlp) {
-				/* NameServer Rsp */
-				lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-						"%d:0238 Process x%x NameServer"
-						" Rsp Data: x%x x%x x%x\n",
-						phba->brd_no,
-						Did, ndlp->nlp_flag,
-						phba->fc_flag,
-						phba->fc_rscn_id_cnt);
-			} else {
-				/* NameServer Rsp */
-				lpfc_printf_log(phba,
-						KERN_INFO,
-						LOG_DISCOVERY,
-						"%d:0239 Skip x%x NameServer "
-						"Rsp Data: x%x x%x x%x\n",
-						phba->brd_no,
-						Did, Size, phba->fc_flag,
-						phba->fc_rscn_id_cnt);
-			}
 
+			/*
+			 * Check for rscn processing or not
+			 * To conserve rpi's, filter out addresses for other
+			 * vports on the same physical HBAs.
+			 */
+			if ((Did != vport->fc_myDID) &&
+			    ((lpfc_find_vport_by_did(phba, Did) == NULL) ||
+			     phba->cfg_peer_port_login)) {
+				if ((vport->port_type != LPFC_NPIV_PORT) ||
+				    (vport->fc_flag & FC_RFF_NOT_SUPPORTED) ||
+				    (!phba->cfg_vport_restrict_login)) {
+					ndlp = lpfc_setup_disc_node(vport, Did);
+					if (ndlp) {
+						lpfc_debugfs_disc_trc(vport,
+						LPFC_DISC_TRC_CT,
+						"Parse GID_FTrsp: "
+						"did:x%x flg:x%x x%x",
+						Did, ndlp->nlp_flag,
+						vport->fc_flag);
+
+						lpfc_printf_log(phba, KERN_INFO,
+							LOG_DISCOVERY,
+							"%d (%d):0238 Process "
+							"x%x NameServer Rsp"
+							"Data: x%x x%x x%x\n",
+							phba->brd_no,
+							vport->vpi, Did,
+							ndlp->nlp_flag,
+							vport->fc_flag,
+							vport->fc_rscn_id_cnt);
+					} else {
+						lpfc_debugfs_disc_trc(vport,
+						LPFC_DISC_TRC_CT,
+						"Skip1 GID_FTrsp: "
+						"did:x%x flg:x%x cnt:%d",
+						Did, vport->fc_flag,
+						vport->fc_rscn_id_cnt);
+
+						lpfc_printf_log(phba, KERN_INFO,
+							LOG_DISCOVERY,
+							"%d (%d):0239 Skip x%x "
+							"NameServer Rsp Data: "
+							"x%x x%x\n",
+							phba->brd_no,
+							vport->vpi, Did,
+							vport->fc_flag,
+							vport->fc_rscn_id_cnt);
+					}
+
+				} else {
+					if (!(vport->fc_flag & FC_RSCN_MODE) ||
+					(lpfc_rscn_payload_check(vport, Did))) {
+						lpfc_debugfs_disc_trc(vport,
+						LPFC_DISC_TRC_CT,
+						"Query GID_FTrsp: "
+						"did:x%x flg:x%x cnt:%d",
+						Did, vport->fc_flag,
+						vport->fc_rscn_id_cnt);
+
+						if (lpfc_ns_cmd(vport,
+							SLI_CTNS_GFF_ID,
+							0, Did) == 0)
+							vport->num_disc_nodes++;
+					}
+					else {
+						lpfc_debugfs_disc_trc(vport,
+						LPFC_DISC_TRC_CT,
+						"Skip2 GID_FTrsp: "
+						"did:x%x flg:x%x cnt:%d",
+						Did, vport->fc_flag,
+						vport->fc_rscn_id_cnt);
+
+						lpfc_printf_log(phba, KERN_INFO,
+							LOG_DISCOVERY,
+							"%d (%d):0245 Skip x%x "
+							"NameServer Rsp Data: "
+							"x%x x%x\n",
+							phba->brd_no,
+							vport->vpi, Did,
+							vport->fc_flag,
+							vport->fc_rscn_id_cnt);
+					}
+				}
+			}
 			if (CTentry & (be32_to_cpu(SLI_CT_LAST_ENTRY)))
 				goto nsout1;
 			Cnt -= sizeof (uint32_t);
@@ -393,188 +536,367 @@
 
 nsout1:
 	list_del(&head);
-
-	/*
- 	 * The driver has cycled through all Nports in the RSCN payload.
- 	 * Complete the handling by cleaning up and marking the
- 	 * current driver state.
- 	 */
-	if (phba->hba_state == LPFC_HBA_READY) {
-		lpfc_els_flush_rscn(phba);
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */
-		spin_unlock_irq(phba->host->host_lock);
-	}
 	return 0;
 }
 
-
-
-
 static void
-lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-			struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
 {
+	struct lpfc_vport *vport = cmdiocb->vport;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
-	struct lpfc_sli *psli;
 	struct lpfc_dmabuf *bmp;
-	struct lpfc_dmabuf *inp;
 	struct lpfc_dmabuf *outp;
-	struct lpfc_nodelist *ndlp;
 	struct lpfc_sli_ct_request *CTrsp;
+	int rc;
 
-	psli = &phba->sli;
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
 	cmdiocb->context_un.rsp_iocb = rspiocb;
 
-	inp = (struct lpfc_dmabuf *) cmdiocb->context1;
 	outp = (struct lpfc_dmabuf *) cmdiocb->context2;
 	bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
-
 	irsp = &rspiocb->iocb;
-	if (irsp->ulpStatus) {
-		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-			((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
-			 (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) {
-			goto out;
-		}
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+		 "GID_FT cmpl:     status:x%x/x%x rtry:%d",
+		irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
+
+	/* Don't bother processing response if vport is being torn down. */
+	if (vport->load_flag & FC_UNLOADING)
+		goto out;
+
+
+	if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) {
+		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+				"%d (%d):0216 Link event during NS query\n",
+				phba->brd_no, vport->vpi);
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+		goto out;
+	}
+
+	if (irsp->ulpStatus) {
 		/* Check for retry */
-		if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
-			phba->fc_ns_retry++;
+		if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
+			if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
+				(irsp->un.ulpWord[4] != IOERR_NO_RESOURCES))
+				vport->fc_ns_retry++;
 			/* CT command is being retried */
-			ndlp = lpfc_findnode_did(phba, NameServer_DID);
-			if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
-				if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) ==
-				    0) {
-					goto out;
-				}
-			}
+			rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
+					 vport->fc_ns_retry, 0);
+			if (rc == 0)
+				goto out;
 		}
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n",
+			phba->brd_no, vport->vpi, irsp->ulpStatus,
+			vport->fc_ns_retry);
 	} else {
 		/* Good status, continue checking */
 		CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
 		if (CTrsp->CommandResponse.bits.CmdRsp ==
 		    be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
 			lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-					"%d:0208 NameServer Rsp "
+					"%d (%d):0208 NameServer Rsp "
 					"Data: x%x\n",
-					phba->brd_no,
-					phba->fc_flag);
-			lpfc_ns_rsp(phba, outp,
+					phba->brd_no, vport->vpi,
+					vport->fc_flag);
+			lpfc_ns_rsp(vport, outp,
 				    (uint32_t) (irsp->un.genreq64.bdl.bdeSize));
 		} else if (CTrsp->CommandResponse.bits.CmdRsp ==
 			   be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
 			/* NameServer Rsp Error */
 			lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-					"%d:0240 NameServer Rsp Error "
+					"%d (%d):0240 NameServer Rsp Error "
 					"Data: x%x x%x x%x x%x\n",
-					phba->brd_no,
+					phba->brd_no, vport->vpi,
 					CTrsp->CommandResponse.bits.CmdRsp,
 					(uint32_t) CTrsp->ReasonCode,
 					(uint32_t) CTrsp->Explanation,
-					phba->fc_flag);
+					vport->fc_flag);
+
+			lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+				"GID_FT rsp err1  cmd:x%x rsn:x%x exp:x%x",
+				(uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+				(uint32_t) CTrsp->ReasonCode,
+				(uint32_t) CTrsp->Explanation);
+
 		} else {
 			/* NameServer Rsp Error */
-			lpfc_printf_log(phba,
-					KERN_INFO,
-					LOG_DISCOVERY,
-					"%d:0241 NameServer Rsp Error "
+			lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+					"%d (%d):0241 NameServer Rsp Error "
 					"Data: x%x x%x x%x x%x\n",
-					phba->brd_no,
+					phba->brd_no, vport->vpi,
 					CTrsp->CommandResponse.bits.CmdRsp,
 					(uint32_t) CTrsp->ReasonCode,
 					(uint32_t) CTrsp->Explanation,
-					phba->fc_flag);
+					vport->fc_flag);
+
+			lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+				"GID_FT rsp err2  cmd:x%x rsn:x%x exp:x%x",
+				(uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+				(uint32_t) CTrsp->ReasonCode,
+				(uint32_t) CTrsp->Explanation);
 		}
 	}
 	/* Link up / RSCN discovery */
-	lpfc_disc_start(phba);
+	if (vport->num_disc_nodes == 0) {
+		/*
+		 * The driver has cycled through all Nports in the RSCN payload.
+		 * Complete the handling by cleaning up and marking the
+		 * current driver state.
+		 */
+		if (vport->port_state >= LPFC_DISC_AUTH) {
+			if (vport->fc_flag & FC_RSCN_MODE) {
+				lpfc_els_flush_rscn(vport);
+				spin_lock_irq(shost->host_lock);
+				vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
+				spin_unlock_irq(shost->host_lock);
+			}
+			else
+				lpfc_els_flush_rscn(vport);
+		}
+
+		lpfc_disc_start(vport);
+	}
 out:
-	lpfc_free_ct_rsp(phba, outp);
-	lpfc_mbuf_free(phba, inp->virt, inp->phys);
-	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-	kfree(inp);
-	kfree(bmp);
-	spin_lock_irq(phba->host->host_lock);
-	lpfc_sli_release_iocbq(phba, cmdiocb);
-	spin_unlock_irq(phba->host->host_lock);
+	lpfc_ct_free_iocb(phba, cmdiocb);
 	return;
 }
 
-static void
-lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-			struct lpfc_iocbq * rspiocb)
+void
+lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
 {
-	struct lpfc_sli *psli;
-	struct lpfc_dmabuf *bmp;
+	struct lpfc_vport *vport = cmdiocb->vport;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	IOCB_t *irsp = &rspiocb->iocb;
+	struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
+	struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
+	struct lpfc_sli_ct_request *CTrsp;
+	int did;
+	uint8_t fbits;
+	struct lpfc_nodelist *ndlp;
+
+	did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId;
+	did = be32_to_cpu(did);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+		"GFF_ID cmpl:     status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4], did);
+
+	if (irsp->ulpStatus == IOSTAT_SUCCESS) {
+		/* Good status, continue checking */
+		CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
+		fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET];
+
+		if (CTrsp->CommandResponse.bits.CmdRsp ==
+		    be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
+			if ((fbits & FC4_FEATURE_INIT) &&
+			    !(fbits & FC4_FEATURE_TARGET)) {
+				lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+						"%d (%d):0245 Skip x%x GFF "
+						"NameServer Rsp Data: (init) "
+						"x%x x%x\n", phba->brd_no,
+						vport->vpi, did, fbits,
+						vport->fc_rscn_id_cnt);
+				goto out;
+			}
+		}
+	}
+	else {
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+				"%d (%d):0267 NameServer GFF Rsp"
+				" x%x Error (%d %d) Data: x%x x%x\n",
+				phba->brd_no, vport->vpi, did,
+				irsp->ulpStatus, irsp->un.ulpWord[4],
+				vport->fc_flag, vport->fc_rscn_id_cnt)
+	}
+
+	/* This is a target port, unregistered port, or the GFF_ID failed */
+	ndlp = lpfc_setup_disc_node(vport, did);
+	if (ndlp) {
+		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+				"%d (%d):0242 Process x%x GFF "
+				"NameServer Rsp Data: x%x x%x x%x\n",
+				phba->brd_no, vport->vpi,
+				did, ndlp->nlp_flag, vport->fc_flag,
+				vport->fc_rscn_id_cnt);
+	} else {
+		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+				"%d (%d):0243 Skip x%x GFF "
+				"NameServer Rsp Data: x%x x%x\n",
+				phba->brd_no, vport->vpi, did,
+				vport->fc_flag,	vport->fc_rscn_id_cnt);
+	}
+out:
+	/* Link up / RSCN discovery */
+	if (vport->num_disc_nodes)
+		vport->num_disc_nodes--;
+	if (vport->num_disc_nodes == 0) {
+		/*
+		 * The driver has cycled through all Nports in the RSCN payload.
+		 * Complete the handling by cleaning up and marking the
+		 * current driver state.
+		 */
+		if (vport->port_state >= LPFC_DISC_AUTH) {
+			if (vport->fc_flag & FC_RSCN_MODE) {
+				lpfc_els_flush_rscn(vport);
+				spin_lock_irq(shost->host_lock);
+				vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
+				spin_unlock_irq(shost->host_lock);
+			}
+			else
+				lpfc_els_flush_rscn(vport);
+		}
+		lpfc_disc_start(vport);
+	}
+	lpfc_ct_free_iocb(phba, cmdiocb);
+	return;
+}
+
+
+static void
+lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
+{
+	struct lpfc_vport *vport = cmdiocb->vport;
 	struct lpfc_dmabuf *inp;
 	struct lpfc_dmabuf *outp;
 	IOCB_t *irsp;
 	struct lpfc_sli_ct_request *CTrsp;
+	int cmdcode, rc;
+	uint8_t retry;
+	uint32_t latt;
 
-	psli = &phba->sli;
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
 	cmdiocb->context_un.rsp_iocb = rspiocb;
 
 	inp = (struct lpfc_dmabuf *) cmdiocb->context1;
 	outp = (struct lpfc_dmabuf *) cmdiocb->context2;
-	bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
 	irsp = &rspiocb->iocb;
 
+	cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
+					CommandResponse.bits.CmdRsp);
 	CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
 
+	latt = lpfc_els_chk_latt(vport);
+
 	/* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d:0209 RFT request completes ulpStatus x%x "
-			"CmdRsp x%x\n", phba->brd_no, irsp->ulpStatus,
-			CTrsp->CommandResponse.bits.CmdRsp);
+			"%d (%d):0209 RFT request completes, latt %d, "
+			"ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n",
+			phba->brd_no, vport->vpi, latt, irsp->ulpStatus,
+			CTrsp->CommandResponse.bits.CmdRsp,
+			cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
 
-	lpfc_free_ct_rsp(phba, outp);
-	lpfc_mbuf_free(phba, inp->virt, inp->phys);
-	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-	kfree(inp);
-	kfree(bmp);
-	spin_lock_irq(phba->host->host_lock);
-	lpfc_sli_release_iocbq(phba, cmdiocb);
-	spin_unlock_irq(phba->host->host_lock);
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+		"CT cmd cmpl:     status:x%x/x%x cmd:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode);
+
+	if (irsp->ulpStatus) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+			"%d (%d):0268 NS cmd %x Error (%d %d)\n",
+			phba->brd_no, vport->vpi, cmdcode,
+			irsp->ulpStatus, irsp->un.ulpWord[4]);
+
+		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+			((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
+			 (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED)))
+			goto out;
+
+		retry = cmdiocb->retry;
+		if (retry >= LPFC_MAX_NS_RETRY)
+			goto out;
+
+		retry++;
+		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+				"%d (%d):0216 Retrying NS cmd %x\n",
+				phba->brd_no, vport->vpi, cmdcode);
+		rc = lpfc_ns_cmd(vport, cmdcode, retry, 0);
+		if (rc == 0)
+			goto out;
+	}
+
+out:
+	lpfc_ct_free_iocb(phba, cmdiocb);
 	return;
 }
 
 static void
-lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-			struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
 {
 	lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
 	return;
 }
 
 static void
-lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-			 struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			 struct lpfc_iocbq *rspiocb)
 {
 	lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
 	return;
 }
 
 static void
-lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-			 struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			 struct lpfc_iocbq *rspiocb)
 {
 	lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
 	return;
 }
 
-void
-lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp)
+static void
+lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
+{
+	IOCB_t *irsp = &rspiocb->iocb;
+	struct lpfc_vport *vport = cmdiocb->vport;
+
+	if (irsp->ulpStatus != IOSTAT_SUCCESS)
+	    vport->fc_flag |= FC_RFF_NOT_SUPPORTED;
+
+	lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
+	return;
+}
+
+int
+lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
+	size_t size)
+{
+	int n;
+	uint8_t *wwn = vport->phba->wwpn;
+
+	n = snprintf(symbol, size,
+		     "Emulex PPN-%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+		     wwn[0], wwn[1], wwn[2], wwn[3],
+		     wwn[4], wwn[5], wwn[6], wwn[7]);
+
+	if (vport->port_type == LPFC_PHYSICAL_PORT)
+		return n;
+
+	if (n < size)
+		n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi);
+
+	if (n < size && vport->vname)
+		n += snprintf(symbol + n, size - n, " VName-%s", vport->vname);
+	return n;
+}
+
+int
+lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
+	size_t size)
 {
 	char fwrev[16];
+	int n;
 
-	lpfc_decode_firmware_rev(phba, fwrev, 0);
+	lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
 
-	sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName,
-		fwrev, lpfc_release_version);
-	return;
+	n = snprintf(symbol, size, "Emulex %s FV%s DV%s",
+		vport->phba->ModelName, fwrev, lpfc_release_version);
+	return n;
 }
 
 /*
@@ -585,55 +907,76 @@
  *       LI_CTNS_RFT_ID
  */
 int
-lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
+lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
+	    uint8_t retry, uint32_t context)
 {
+	struct lpfc_nodelist * ndlp;
+	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_dmabuf *mp, *bmp;
 	struct lpfc_sli_ct_request *CtReq;
 	struct ulp_bde64 *bpl;
 	void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
 		      struct lpfc_iocbq *) = NULL;
 	uint32_t rsp_size = 1024;
+	size_t   size;
+	int rc = 0;
+
+	ndlp = lpfc_findnode_did(vport, NameServer_DID);
+	if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
+		rc=1;
+		goto ns_cmd_exit;
+	}
 
 	/* fill in BDEs for command */
 	/* Allocate buffer for command payload */
 	mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
-	if (!mp)
+	if (!mp) {
+		rc=2;
 		goto ns_cmd_exit;
+	}
 
 	INIT_LIST_HEAD(&mp->list);
 	mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
-	if (!mp->virt)
+	if (!mp->virt) {
+		rc=3;
 		goto ns_cmd_free_mp;
+	}
 
 	/* Allocate buffer for Buffer ptr list */
 	bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
-	if (!bmp)
+	if (!bmp) {
+		rc=4;
 		goto ns_cmd_free_mpvirt;
+	}
 
 	INIT_LIST_HEAD(&bmp->list);
 	bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
-	if (!bmp->virt)
+	if (!bmp->virt) {
+		rc=5;
 		goto ns_cmd_free_bmp;
+	}
 
 	/* NameServer Req */
-	lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_DISCOVERY,
-			"%d:0236 NameServer Req Data: x%x x%x x%x\n",
-			phba->brd_no, cmdcode, phba->fc_flag,
-			phba->fc_rscn_id_cnt);
+	lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY,
+			"%d (%d):0236 NameServer Req Data: x%x x%x x%x\n",
+			phba->brd_no, vport->vpi, cmdcode, vport->fc_flag,
+			vport->fc_rscn_id_cnt);
 
 	bpl = (struct ulp_bde64 *) bmp->virt;
 	memset(bpl, 0, sizeof(struct ulp_bde64));
-	bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
-	bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
+	bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
+	bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
 	bpl->tus.f.bdeFlags = 0;
 	if (cmdcode == SLI_CTNS_GID_FT)
 		bpl->tus.f.bdeSize = GID_REQUEST_SZ;
+	else if (cmdcode == SLI_CTNS_GFF_ID)
+		bpl->tus.f.bdeSize = GFF_REQUEST_SZ;
 	else if (cmdcode == SLI_CTNS_RFT_ID)
 		bpl->tus.f.bdeSize = RFT_REQUEST_SZ;
 	else if (cmdcode == SLI_CTNS_RNN_ID)
 		bpl->tus.f.bdeSize = RNN_REQUEST_SZ;
+	else if (cmdcode == SLI_CTNS_RSPN_ID)
+		bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
 	else if (cmdcode == SLI_CTNS_RSNN_NN)
 		bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
 	else if (cmdcode == SLI_CTNS_RFF_ID)
@@ -654,56 +997,78 @@
 		CtReq->CommandResponse.bits.CmdRsp =
 		    be16_to_cpu(SLI_CTNS_GID_FT);
 		CtReq->un.gid.Fc4Type = SLI_CTPT_FCP;
-		if (phba->hba_state < LPFC_HBA_READY)
-			phba->hba_state = LPFC_NS_QRY;
-		lpfc_set_disctmo(phba);
+		if (vport->port_state < LPFC_NS_QRY)
+			vport->port_state = LPFC_NS_QRY;
+		lpfc_set_disctmo(vport);
 		cmpl = lpfc_cmpl_ct_cmd_gid_ft;
 		rsp_size = FC_MAX_NS_RSP;
 		break;
 
+	case SLI_CTNS_GFF_ID:
+		CtReq->CommandResponse.bits.CmdRsp =
+			be16_to_cpu(SLI_CTNS_GFF_ID);
+		CtReq->un.gff.PortId = be32_to_cpu(context);
+		cmpl = lpfc_cmpl_ct_cmd_gff_id;
+		break;
+
 	case SLI_CTNS_RFT_ID:
 		CtReq->CommandResponse.bits.CmdRsp =
 		    be16_to_cpu(SLI_CTNS_RFT_ID);
-		CtReq->un.rft.PortId = be32_to_cpu(phba->fc_myDID);
+		CtReq->un.rft.PortId = be32_to_cpu(vport->fc_myDID);
 		CtReq->un.rft.fcpReg = 1;
 		cmpl = lpfc_cmpl_ct_cmd_rft_id;
 		break;
 
-	case SLI_CTNS_RFF_ID:
-		CtReq->CommandResponse.bits.CmdRsp =
-			be16_to_cpu(SLI_CTNS_RFF_ID);
-		CtReq->un.rff.PortId = be32_to_cpu(phba->fc_myDID);
-		CtReq->un.rff.feature_res = 0;
-		CtReq->un.rff.feature_tgt = 0;
-		CtReq->un.rff.type_code = FC_FCP_DATA;
-		CtReq->un.rff.feature_init = 1;
-		cmpl = lpfc_cmpl_ct_cmd_rff_id;
-		break;
-
 	case SLI_CTNS_RNN_ID:
 		CtReq->CommandResponse.bits.CmdRsp =
 		    be16_to_cpu(SLI_CTNS_RNN_ID);
-		CtReq->un.rnn.PortId = be32_to_cpu(phba->fc_myDID);
-		memcpy(CtReq->un.rnn.wwnn,  &phba->fc_nodename,
+		CtReq->un.rnn.PortId = be32_to_cpu(vport->fc_myDID);
+		memcpy(CtReq->un.rnn.wwnn,  &vport->fc_nodename,
 		       sizeof (struct lpfc_name));
 		cmpl = lpfc_cmpl_ct_cmd_rnn_id;
 		break;
 
+	case SLI_CTNS_RSPN_ID:
+		CtReq->CommandResponse.bits.CmdRsp =
+		    be16_to_cpu(SLI_CTNS_RSPN_ID);
+		CtReq->un.rspn.PortId = be32_to_cpu(vport->fc_myDID);
+		size = sizeof(CtReq->un.rspn.symbname);
+		CtReq->un.rspn.len =
+			lpfc_vport_symbolic_port_name(vport,
+			CtReq->un.rspn.symbname, size);
+		cmpl = lpfc_cmpl_ct_cmd_rspn_id;
+		break;
 	case SLI_CTNS_RSNN_NN:
 		CtReq->CommandResponse.bits.CmdRsp =
 		    be16_to_cpu(SLI_CTNS_RSNN_NN);
-		memcpy(CtReq->un.rsnn.wwnn, &phba->fc_nodename,
+		memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename,
 		       sizeof (struct lpfc_name));
-		lpfc_get_hba_sym_node_name(phba, CtReq->un.rsnn.symbname);
-		CtReq->un.rsnn.len = strlen(CtReq->un.rsnn.symbname);
+		size = sizeof(CtReq->un.rsnn.symbname);
+		CtReq->un.rsnn.len =
+			lpfc_vport_symbolic_node_name(vport,
+			CtReq->un.rsnn.symbname, size);
 		cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
 		break;
+	case SLI_CTNS_RFF_ID:
+		vport->fc_flag &= ~FC_RFF_NOT_SUPPORTED;
+		CtReq->CommandResponse.bits.CmdRsp =
+		    be16_to_cpu(SLI_CTNS_RFF_ID);
+		CtReq->un.rff.PortId = be32_to_cpu(vport->fc_myDID);;
+		CtReq->un.rff.fbits = FC4_FEATURE_INIT;
+		CtReq->un.rff.type_code = FC_FCP_DATA;
+		cmpl = lpfc_cmpl_ct_cmd_rff_id;
+		break;
 	}
 
-	if (!lpfc_ct_cmd(phba, mp, bmp, ndlp, cmpl, rsp_size))
+	if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
 		/* On success, The cmpl function will free the buffers */
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+			"Issue CT cmd:    cmd:x%x did:x%x",
+			cmdcode, ndlp->nlp_DID, 0);
 		return 0;
+	}
 
+	rc=6;
 	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
 ns_cmd_free_bmp:
 	kfree(bmp);
@@ -712,14 +1077,17 @@
 ns_cmd_free_mp:
 	kfree(mp);
 ns_cmd_exit:
+	lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+		"%d (%d):0266 Issue NameServer Req x%x err %d Data: x%x x%x\n",
+			phba->brd_no, vport->vpi, cmdcode, rc, vport->fc_flag,
+			vport->fc_rscn_id_cnt);
 	return 1;
 }
 
 static void
-lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
-		      struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		      struct lpfc_iocbq * rspiocb)
 {
-	struct lpfc_dmabuf *bmp = cmdiocb->context3;
 	struct lpfc_dmabuf *inp = cmdiocb->context1;
 	struct lpfc_dmabuf *outp = cmdiocb->context2;
 	struct lpfc_sli_ct_request *CTrsp = outp->virt;
@@ -727,48 +1095,60 @@
 	struct lpfc_nodelist *ndlp;
 	uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
 	uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
+	struct lpfc_vport *vport = cmdiocb->vport;
+	IOCB_t *irsp = &rspiocb->iocb;
+	uint32_t latt;
 
-	ndlp = lpfc_findnode_did(phba, FDMI_DID);
+	latt = lpfc_els_chk_latt(vport);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+		"FDMI cmpl:       status:x%x/x%x latt:%d",
+		irsp->ulpStatus, irsp->un.ulpWord[4], latt);
+
+	if (latt || irsp->ulpStatus) {
+		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			        "%d (%d):0229 FDMI cmd %04x failed, latt = %d "
+				"ulpStatus: x%x, rid x%x\n",
+			        phba->brd_no, vport->vpi,
+				be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus,
+				irsp->un.ulpWord[4]);
+		lpfc_ct_free_iocb(phba, cmdiocb);
+		return;
+	}
+
+	ndlp = lpfc_findnode_did(vport, FDMI_DID);
 	if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
 		/* FDMI rsp failed */
-		lpfc_printf_log(phba,
-			        KERN_INFO,
-			        LOG_DISCOVERY,
-			        "%d:0220 FDMI rsp failed Data: x%x\n",
-			        phba->brd_no,
-			       be16_to_cpu(fdmi_cmd));
+		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			        "%d (%d):0220 FDMI rsp failed Data: x%x\n",
+			        phba->brd_no, vport->vpi,
+				be16_to_cpu(fdmi_cmd));
 	}
 
 	switch (be16_to_cpu(fdmi_cmd)) {
 	case SLI_MGMT_RHBA:
-		lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_RPA);
+		lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA);
 		break;
 
 	case SLI_MGMT_RPA:
 		break;
 
 	case SLI_MGMT_DHBA:
-		lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DPRT);
+		lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT);
 		break;
 
 	case SLI_MGMT_DPRT:
-		lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_RHBA);
+		lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA);
 		break;
 	}
-
-	lpfc_free_ct_rsp(phba, outp);
-	lpfc_mbuf_free(phba, inp->virt, inp->phys);
-	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-	kfree(inp);
-	kfree(bmp);
-	spin_lock_irq(phba->host->host_lock);
-	lpfc_sli_release_iocbq(phba, cmdiocb);
-	spin_unlock_irq(phba->host->host_lock);
+	lpfc_ct_free_iocb(phba, cmdiocb);
 	return;
 }
+
 int
-lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
+lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
 {
+	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_dmabuf *mp, *bmp;
 	struct lpfc_sli_ct_request *CtReq;
 	struct ulp_bde64 *bpl;
@@ -805,12 +1185,10 @@
 	INIT_LIST_HEAD(&bmp->list);
 
 	/* FDMI request */
-	lpfc_printf_log(phba,
-		        KERN_INFO,
-		        LOG_DISCOVERY,
-		        "%d:0218 FDMI Request Data: x%x x%x x%x\n",
-		        phba->brd_no,
-		       phba->fc_flag, phba->hba_state, cmdcode);
+	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			"%d (%d):0218 FDMI Request Data: x%x x%x x%x\n",
+			phba->brd_no, vport->vpi, vport->fc_flag,
+			vport->port_state, cmdcode);
 
 	CtReq = (struct lpfc_sli_ct_request *) mp->virt;
 
@@ -833,11 +1211,11 @@
 			    be16_to_cpu(SLI_MGMT_RHBA);
 			CtReq->CommandResponse.bits.Size = 0;
 			rh = (REG_HBA *) & CtReq->un.PortID;
-			memcpy(&rh->hi.PortName, &phba->fc_sparam.portName,
+			memcpy(&rh->hi.PortName, &vport->fc_sparam.portName,
 			       sizeof (struct lpfc_name));
 			/* One entry (port) per adapter */
 			rh->rpl.EntryCnt = be32_to_cpu(1);
-			memcpy(&rh->rpl.pe, &phba->fc_sparam.portName,
+			memcpy(&rh->rpl.pe, &vport->fc_sparam.portName,
 			       sizeof (struct lpfc_name));
 
 			/* point to the HBA attribute block */
@@ -853,7 +1231,7 @@
 			ae->ad.bits.AttrType = be16_to_cpu(NODE_NAME);
 			ae->ad.bits.AttrLen =  be16_to_cpu(FOURBYTES
 						+ sizeof (struct lpfc_name));
-			memcpy(&ae->un.NodeName, &phba->fc_sparam.nodeName,
+			memcpy(&ae->un.NodeName, &vport->fc_sparam.nodeName,
 			       sizeof (struct lpfc_name));
 			ab->EntryCnt++;
 			size += FOURBYTES + sizeof (struct lpfc_name);
@@ -991,7 +1369,7 @@
 			pab = (REG_PORT_ATTRIBUTE *) & CtReq->un.PortID;
 			size = sizeof (struct lpfc_name) + FOURBYTES;
 			memcpy((uint8_t *) & pab->PortName,
-			       (uint8_t *) & phba->fc_sparam.portName,
+			       (uint8_t *) & vport->fc_sparam.portName,
 			       sizeof (struct lpfc_name));
 			pab->ab.EntryCnt = 0;
 
@@ -1053,7 +1431,7 @@
 			ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size);
 			ae->ad.bits.AttrType = be16_to_cpu(MAX_FRAME_SIZE);
 			ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
-			hsp = (struct serv_parm *) & phba->fc_sparam;
+			hsp = (struct serv_parm *) & vport->fc_sparam;
 			ae->un.MaxFrameSize =
 			    (((uint32_t) hsp->cmn.
 			      bbRcvSizeMsb) << 8) | (uint32_t) hsp->cmn.
@@ -1097,7 +1475,7 @@
 		CtReq->CommandResponse.bits.Size = 0;
 		pe = (PORT_ENTRY *) & CtReq->un.PortID;
 		memcpy((uint8_t *) & pe->PortName,
-		       (uint8_t *) & phba->fc_sparam.portName,
+		       (uint8_t *) & vport->fc_sparam.portName,
 		       sizeof (struct lpfc_name));
 		size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name);
 		break;
@@ -1107,22 +1485,22 @@
 		CtReq->CommandResponse.bits.Size = 0;
 		pe = (PORT_ENTRY *) & CtReq->un.PortID;
 		memcpy((uint8_t *) & pe->PortName,
-		       (uint8_t *) & phba->fc_sparam.portName,
+		       (uint8_t *) & vport->fc_sparam.portName,
 		       sizeof (struct lpfc_name));
 		size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name);
 		break;
 	}
 
 	bpl = (struct ulp_bde64 *) bmp->virt;
-	bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
-	bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
+	bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
+	bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
 	bpl->tus.f.bdeFlags = 0;
 	bpl->tus.f.bdeSize = size;
 	bpl->tus.w = le32_to_cpu(bpl->tus.w);
 
 	cmpl = lpfc_cmpl_ct_cmd_fdmi;
 
-	if (!lpfc_ct_cmd(phba, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP))
+	if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0))
 		return 0;
 
 	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
@@ -1134,49 +1512,50 @@
 	kfree(mp);
 fdmi_cmd_exit:
 	/* Issue FDMI request failed */
-	lpfc_printf_log(phba,
-		        KERN_INFO,
-		        LOG_DISCOVERY,
-		        "%d:0244 Issue FDMI request failed Data: x%x\n",
-		        phba->brd_no,
-			cmdcode);
+	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+		        "%d (%d):0244 Issue FDMI request failed Data: x%x\n",
+		        phba->brd_no, vport->vpi, cmdcode);
 	return 1;
 }
 
 void
 lpfc_fdmi_tmo(unsigned long ptr)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+	struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
+	struct lpfc_hba   *phba = vport->phba;
 	unsigned long iflag;
 
-	spin_lock_irqsave(phba->host->host_lock, iflag);
-	if (!(phba->work_hba_events & WORKER_FDMI_TMO)) {
-		phba->work_hba_events |= WORKER_FDMI_TMO;
+	spin_lock_irqsave(&vport->work_port_lock, iflag);
+	if (!(vport->work_port_events & WORKER_FDMI_TMO)) {
+		vport->work_port_events |= WORKER_FDMI_TMO;
+		spin_unlock_irqrestore(&vport->work_port_lock, iflag);
+
+		spin_lock_irqsave(&phba->hbalock, iflag);
 		if (phba->work_wait)
-			wake_up(phba->work_wait);
+			lpfc_worker_wake_up(phba);
+		spin_unlock_irqrestore(&phba->hbalock, iflag);
 	}
-	spin_unlock_irqrestore(phba->host->host_lock,iflag);
+	else
+		spin_unlock_irqrestore(&vport->work_port_lock, iflag);
 }
 
 void
-lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
+lpfc_fdmi_timeout_handler(struct lpfc_vport *vport)
 {
 	struct lpfc_nodelist *ndlp;
 
-	ndlp = lpfc_findnode_did(phba, FDMI_DID);
+	ndlp = lpfc_findnode_did(vport, FDMI_DID);
 	if (ndlp) {
-		if (init_utsname()->nodename[0] != '\0') {
-			lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
-		} else {
-			mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
-		}
+		if (init_utsname()->nodename[0] != '\0')
+			lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
+		else
+			mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
 	}
 	return;
 }
 
-
 void
-lpfc_decode_firmware_rev(struct lpfc_hba * phba, char *fwrevision, int flag)
+lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
 {
 	struct lpfc_sli *psli = &phba->sli;
 	lpfc_vpd_t *vp = &phba->vpd;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
new file mode 100644
index 0000000..673cfe1
--- /dev/null
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -0,0 +1,508 @@
+/*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for         *
+ * Fibre Channel Host Bus Adapters.                                *
+ * Copyright (C) 2007 Emulex.  All rights reserved.                *
+ * EMULEX and SLI are trademarks of Emulex.                        *
+ * www.emulex.com                                                  *
+ *                                                                 *
+ * This program is free software; you can redistribute it and/or   *
+ * modify it under the terms of version 2 of the GNU General       *
+ * Public License as published by the Free Software Foundation.    *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+ * more details, a copy of which can be found in the file COPYING  *
+ * included with this package.                                     *
+ *******************************************************************/
+
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "lpfc_hw.h"
+#include "lpfc_sli.h"
+#include "lpfc_disc.h"
+#include "lpfc_scsi.h"
+#include "lpfc.h"
+#include "lpfc_logmsg.h"
+#include "lpfc_crtn.h"
+#include "lpfc_vport.h"
+#include "lpfc_version.h"
+#include "lpfc_vport.h"
+#include "lpfc_debugfs.h"
+
+#ifdef CONFIG_LPFC_DEBUG_FS
+/* debugfs interface
+ *
+ * To access this interface the user should:
+ * # mkdir /debug
+ * # mount -t debugfs none /debug
+ *
+ * The lpfc debugfs directory hierachy is:
+ * lpfc/lpfcX/vportY
+ * where X is the lpfc hba unique_id
+ * where Y is the vport VPI on that hba
+ *
+ * Debugging services available per vport:
+ * discovery_trace
+ * This is an ACSII readable file that contains a trace of the last
+ * lpfc_debugfs_max_disc_trc events that happened on a specific vport.
+ * See lpfc_debugfs.h for different categories of
+ * discovery events. To enable the discovery trace, the following
+ * module parameters must be set:
+ * lpfc_debugfs_enable=1         Turns on lpfc debugfs filesystem support
+ * lpfc_debugfs_max_disc_trc=X   Where X is the event trace depth for
+ *                               EACH vport. X MUST also be a power of 2.
+ * lpfc_debugfs_mask_disc_trc=Y  Where Y is an event mask as defined in
+ *                               lpfc_debugfs.h .
+ */
+static int lpfc_debugfs_enable = 0;
+module_param(lpfc_debugfs_enable, int, 0);
+MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
+
+static int lpfc_debugfs_max_disc_trc = 0;  /* This MUST be a power of 2 */
+module_param(lpfc_debugfs_max_disc_trc, int, 0);
+MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
+	"Set debugfs discovery trace depth");
+
+static int lpfc_debugfs_mask_disc_trc = 0;
+module_param(lpfc_debugfs_mask_disc_trc, int, 0);
+MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
+	"Set debugfs discovery trace mask");
+
+#include <linux/debugfs.h>
+
+/* size of discovery_trace output line */
+#define LPFC_DISC_TRC_ENTRY_SIZE 80
+
+/* nodelist output buffer size */
+#define LPFC_NODELIST_SIZE 8192
+#define LPFC_NODELIST_ENTRY_SIZE 120
+
+struct lpfc_debug {
+	char *buffer;
+	int  len;
+};
+
+atomic_t lpfc_debugfs_disc_trc_cnt = ATOMIC_INIT(0);
+unsigned long lpfc_debugfs_start_time = 0L;
+
+static int
+lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
+{
+	int i, index, len, enable;
+	uint32_t ms;
+	struct lpfc_disc_trc *dtp;
+	char buffer[80];
+
+
+	enable = lpfc_debugfs_enable;
+	lpfc_debugfs_enable = 0;
+
+	len = 0;
+	index = (atomic_read(&vport->disc_trc_cnt) + 1) &
+		(lpfc_debugfs_max_disc_trc - 1);
+	for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
+		dtp = vport->disc_trc + i;
+		if (!dtp->fmt)
+			continue;
+		ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
+		snprintf(buffer, 80, "%010d:%010d ms:%s\n",
+			dtp->seq_cnt, ms, dtp->fmt);
+		len +=  snprintf(buf+len, size-len, buffer,
+			dtp->data1, dtp->data2, dtp->data3);
+	}
+	for (i = 0; i < index; i++) {
+		dtp = vport->disc_trc + i;
+		if (!dtp->fmt)
+			continue;
+		ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
+		snprintf(buffer, 80, "%010d:%010d ms:%s\n",
+			dtp->seq_cnt, ms, dtp->fmt);
+		len +=  snprintf(buf+len, size-len, buffer,
+			dtp->data1, dtp->data2, dtp->data3);
+	}
+
+	lpfc_debugfs_enable = enable;
+	return len;
+}
+
+static int
+lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
+{
+	int len = 0;
+	int cnt;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_nodelist *ndlp;
+	unsigned char *statep, *name;
+
+	cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
+
+	spin_lock_irq(shost->host_lock);
+	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+		if (!cnt) {
+			len +=  snprintf(buf+len, size-len,
+				"Missing Nodelist Entries\n");
+			break;
+		}
+		cnt--;
+		switch (ndlp->nlp_state) {
+		case NLP_STE_UNUSED_NODE:
+			statep = "UNUSED";
+			break;
+		case NLP_STE_PLOGI_ISSUE:
+			statep = "PLOGI ";
+			break;
+		case NLP_STE_ADISC_ISSUE:
+			statep = "ADISC ";
+			break;
+		case NLP_STE_REG_LOGIN_ISSUE:
+			statep = "REGLOG";
+			break;
+		case NLP_STE_PRLI_ISSUE:
+			statep = "PRLI  ";
+			break;
+		case NLP_STE_UNMAPPED_NODE:
+			statep = "UNMAP ";
+			break;
+		case NLP_STE_MAPPED_NODE:
+			statep = "MAPPED";
+			break;
+		case NLP_STE_NPR_NODE:
+			statep = "NPR   ";
+			break;
+		default:
+			statep = "UNKNOWN";
+		}
+		len +=  snprintf(buf+len, size-len, "%s DID:x%06x ",
+			statep, ndlp->nlp_DID);
+		name = (unsigned char *)&ndlp->nlp_portname;
+		len +=  snprintf(buf+len, size-len,
+			"WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
+			*name, *(name+1), *(name+2), *(name+3),
+			*(name+4), *(name+5), *(name+6), *(name+7));
+		name = (unsigned char *)&ndlp->nlp_nodename;
+		len +=  snprintf(buf+len, size-len,
+			"WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
+			*name, *(name+1), *(name+2), *(name+3),
+			*(name+4), *(name+5), *(name+6), *(name+7));
+		len +=  snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ",
+			ndlp->nlp_rpi, ndlp->nlp_flag);
+		if (!ndlp->nlp_type)
+			len +=  snprintf(buf+len, size-len, "UNKNOWN_TYPE");
+		if (ndlp->nlp_type & NLP_FC_NODE)
+			len +=  snprintf(buf+len, size-len, "FC_NODE ");
+		if (ndlp->nlp_type & NLP_FABRIC)
+			len +=  snprintf(buf+len, size-len, "FABRIC ");
+		if (ndlp->nlp_type & NLP_FCP_TARGET)
+			len +=  snprintf(buf+len, size-len, "FCP_TGT sid:%d ",
+				ndlp->nlp_sid);
+		if (ndlp->nlp_type & NLP_FCP_INITIATOR)
+			len +=  snprintf(buf+len, size-len, "FCP_INITIATOR");
+		len +=  snprintf(buf+len, size-len, "\n");
+	}
+	spin_unlock_irq(shost->host_lock);
+	return len;
+}
+#endif
+
+
+inline void
+lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
+	uint32_t data1, uint32_t data2, uint32_t data3)
+{
+#ifdef CONFIG_LPFC_DEBUG_FS
+	struct lpfc_disc_trc *dtp;
+	int index;
+
+	if (!(lpfc_debugfs_mask_disc_trc & mask))
+		return;
+
+	if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
+		!vport || !vport->disc_trc)
+		return;
+
+	index = atomic_inc_return(&vport->disc_trc_cnt) &
+		(lpfc_debugfs_max_disc_trc - 1);
+	dtp = vport->disc_trc + index;
+	dtp->fmt = fmt;
+	dtp->data1 = data1;
+	dtp->data2 = data2;
+	dtp->data3 = data3;
+	dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_disc_trc_cnt);
+	dtp->jif = jiffies;
+#endif
+	return;
+}
+
+#ifdef CONFIG_LPFC_DEBUG_FS
+static int
+lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
+{
+	struct lpfc_vport *vport = inode->i_private;
+	struct lpfc_debug *debug;
+	int size;
+	int rc = -ENOMEM;
+
+	if (!lpfc_debugfs_max_disc_trc) {
+		 rc = -ENOSPC;
+		goto out;
+	}
+
+	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+	if (!debug)
+		goto out;
+
+	/* Round to page boundry */
+	size =  (lpfc_debugfs_max_disc_trc * LPFC_DISC_TRC_ENTRY_SIZE);
+	size = PAGE_ALIGN(size);
+
+	debug->buffer = kmalloc(size, GFP_KERNEL);
+	if (!debug->buffer) {
+		kfree(debug);
+		goto out;
+	}
+
+	debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
+	file->private_data = debug;
+
+	rc = 0;
+out:
+	return rc;
+}
+
+static int
+lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
+{
+	struct lpfc_vport *vport = inode->i_private;
+	struct lpfc_debug *debug;
+	int rc = -ENOMEM;
+
+	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+	if (!debug)
+		goto out;
+
+	/* Round to page boundry */
+	debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
+	if (!debug->buffer) {
+		kfree(debug);
+		goto out;
+	}
+
+	debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
+		LPFC_NODELIST_SIZE);
+	file->private_data = debug;
+
+	rc = 0;
+out:
+	return rc;
+}
+
+static loff_t
+lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
+{
+	struct lpfc_debug *debug;
+	loff_t pos = -1;
+
+	debug = file->private_data;
+
+	switch (whence) {
+	case 0:
+		pos = off;
+		break;
+	case 1:
+		pos = file->f_pos + off;
+		break;
+	case 2:
+		pos = debug->len - off;
+	}
+	return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
+}
+
+static ssize_t
+lpfc_debugfs_read(struct file *file, char __user *buf,
+		  size_t nbytes, loff_t *ppos)
+{
+	struct lpfc_debug *debug = file->private_data;
+	return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
+				       debug->len);
+}
+
+static int
+lpfc_debugfs_release(struct inode *inode, struct file *file)
+{
+	struct lpfc_debug *debug = file->private_data;
+
+	kfree(debug->buffer);
+	kfree(debug);
+
+	return 0;
+}
+
+#undef lpfc_debugfs_op_disc_trc
+static struct file_operations lpfc_debugfs_op_disc_trc = {
+	.owner =        THIS_MODULE,
+	.open =         lpfc_debugfs_disc_trc_open,
+	.llseek =       lpfc_debugfs_lseek,
+	.read =         lpfc_debugfs_read,
+	.release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_nodelist
+static struct file_operations lpfc_debugfs_op_nodelist = {
+	.owner =        THIS_MODULE,
+	.open =         lpfc_debugfs_nodelist_open,
+	.llseek =       lpfc_debugfs_lseek,
+	.read =         lpfc_debugfs_read,
+	.release =      lpfc_debugfs_release,
+};
+
+static struct dentry *lpfc_debugfs_root = NULL;
+static atomic_t lpfc_debugfs_hba_count;
+#endif
+
+inline void
+lpfc_debugfs_initialize(struct lpfc_vport *vport)
+{
+#ifdef CONFIG_LPFC_DEBUG_FS
+	struct lpfc_hba   *phba = vport->phba;
+	char name[64];
+	uint32_t num, i;
+
+	if (!lpfc_debugfs_enable)
+		return;
+
+	if (lpfc_debugfs_max_disc_trc) {
+		num = lpfc_debugfs_max_disc_trc - 1;
+		if (num & lpfc_debugfs_max_disc_trc) {
+			/* Change to be a power of 2 */
+			num = lpfc_debugfs_max_disc_trc;
+			i = 0;
+			while (num > 1) {
+				num = num >> 1;
+				i++;
+			}
+			lpfc_debugfs_max_disc_trc = (1 << i);
+			printk(KERN_ERR
+				"lpfc_debugfs_max_disc_trc changed to %d\n",
+				lpfc_debugfs_max_disc_trc);
+		}
+	}
+
+	if (!lpfc_debugfs_root) {
+		lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
+		atomic_set(&lpfc_debugfs_hba_count, 0);
+		if (!lpfc_debugfs_root)
+			goto debug_failed;
+	}
+
+	snprintf(name, sizeof(name), "lpfc%d", phba->brd_no);
+	if (!phba->hba_debugfs_root) {
+		phba->hba_debugfs_root =
+			debugfs_create_dir(name, lpfc_debugfs_root);
+		if (!phba->hba_debugfs_root)
+			goto debug_failed;
+		atomic_inc(&lpfc_debugfs_hba_count);
+		atomic_set(&phba->debugfs_vport_count, 0);
+	}
+
+	snprintf(name, sizeof(name), "vport%d", vport->vpi);
+	if (!vport->vport_debugfs_root) {
+		vport->vport_debugfs_root =
+			debugfs_create_dir(name, phba->hba_debugfs_root);
+		if (!vport->vport_debugfs_root)
+			goto debug_failed;
+		atomic_inc(&phba->debugfs_vport_count);
+	}
+
+	if (!lpfc_debugfs_start_time)
+		lpfc_debugfs_start_time = jiffies;
+
+	vport->disc_trc = kmalloc(
+		(sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc),
+		GFP_KERNEL);
+
+	if (!vport->disc_trc)
+		goto debug_failed;
+	memset(vport->disc_trc, 0,
+		(sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc));
+
+	snprintf(name, sizeof(name), "discovery_trace");
+	vport->debug_disc_trc =
+		debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+				 vport->vport_debugfs_root,
+				 vport, &lpfc_debugfs_op_disc_trc);
+	if (!vport->debug_disc_trc) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+				"%d:0409 Cannot create debugfs",
+				phba->brd_no);
+		goto debug_failed;
+	}
+	snprintf(name, sizeof(name), "nodelist");
+	vport->debug_nodelist =
+		debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+				 vport->vport_debugfs_root,
+				 vport, &lpfc_debugfs_op_nodelist);
+	if (!vport->debug_nodelist) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+				"%d:0409 Cannot create debugfs",
+				phba->brd_no);
+		goto debug_failed;
+	}
+debug_failed:
+	return;
+#endif
+}
+
+
+inline void
+lpfc_debugfs_terminate(struct lpfc_vport *vport)
+{
+#ifdef CONFIG_LPFC_DEBUG_FS
+	struct lpfc_hba   *phba = vport->phba;
+
+	if (vport->disc_trc) {
+		kfree(vport->disc_trc);
+		vport->disc_trc = NULL;
+	}
+	if (vport->debug_disc_trc) {
+		debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
+		vport->debug_disc_trc = NULL;
+	}
+	if (vport->debug_nodelist) {
+		debugfs_remove(vport->debug_nodelist); /* nodelist */
+		vport->debug_nodelist = NULL;
+	}
+	if (vport->vport_debugfs_root) {
+		debugfs_remove(vport->vport_debugfs_root); /* vportX */
+		vport->vport_debugfs_root = NULL;
+		atomic_dec(&phba->debugfs_vport_count);
+	}
+	if (atomic_read(&phba->debugfs_vport_count) == 0) {
+		debugfs_remove(vport->phba->hba_debugfs_root); /* lpfcX */
+		vport->phba->hba_debugfs_root = NULL;
+		atomic_dec(&lpfc_debugfs_hba_count);
+		if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
+			debugfs_remove(lpfc_debugfs_root); /* lpfc */
+			lpfc_debugfs_root = NULL;
+		}
+	}
+#endif
+}
+
+
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
new file mode 100644
index 0000000..fffb678
--- /dev/null
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -0,0 +1,50 @@
+/*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for         *
+ * Fibre Channel Host Bus Adapters.                                *
+ * Copyright (C) 2007 Emulex.  All rights reserved.                *
+ * EMULEX and SLI are trademarks of Emulex.                        *
+ * www.emulex.com                                                  *
+ *                                                                 *
+ * This program is free software; you can redistribute it and/or   *
+ * modify it under the terms of version 2 of the GNU General       *
+ * Public License as published by the Free Software Foundation.    *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+ * more details, a copy of which can be found in the file COPYING  *
+ * included with this package.                                     *
+ *******************************************************************/
+
+#ifndef _H_LPFC_DEBUG_FS
+#define _H_LPFC_DEBUG_FS
+
+#ifdef CONFIG_LPFC_DEBUG_FS
+struct lpfc_disc_trc {
+	char *fmt;
+	uint32_t data1;
+	uint32_t data2;
+	uint32_t data3;
+	uint32_t seq_cnt;
+	unsigned long jif;
+};
+#endif
+
+/* Mask for discovery_trace */
+#define LPFC_DISC_TRC_ELS_CMD		0x1	/* Trace ELS commands */
+#define LPFC_DISC_TRC_ELS_RSP		0x2	/* Trace ELS response */
+#define LPFC_DISC_TRC_ELS_UNSOL		0x4	/* Trace ELS rcv'ed   */
+#define LPFC_DISC_TRC_ELS_ALL		0x7	/* Trace ELS */
+#define LPFC_DISC_TRC_MBOX_VPORT	0x8	/* Trace vport MBOXs */
+#define LPFC_DISC_TRC_MBOX		0x10	/* Trace other MBOXs */
+#define LPFC_DISC_TRC_MBOX_ALL		0x18	/* Trace all MBOXs */
+#define LPFC_DISC_TRC_CT		0x20	/* Trace disc CT requests */
+#define LPFC_DISC_TRC_DSM		0x40    /* Trace DSM events */
+#define LPFC_DISC_TRC_RPORT		0x80    /* Trace rport events */
+#define LPFC_DISC_TRC_NODE		0x100   /* Trace ndlp state changes */
+
+#define LPFC_DISC_TRC_DISCOVERY		0xef    /* common mask for general
+						 * discovery */
+#endif /* H_LPFC_DEBUG_FS */
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 498059f..aacac9a 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -36,21 +36,23 @@
 	LPFC_EVT_WARM_START,
 	LPFC_EVT_KILL,
 	LPFC_EVT_ELS_RETRY,
+	LPFC_EVT_DEV_LOSS_DELAY,
+	LPFC_EVT_DEV_LOSS,
 };
 
 /* structure used to queue event to the discovery tasklet */
 struct lpfc_work_evt {
 	struct list_head      evt_listp;
-	void                * evt_arg1;
-	void                * evt_arg2;
+	void                 *evt_arg1;
+	void                 *evt_arg2;
 	enum lpfc_work_type   evt;
 };
 
 
 struct lpfc_nodelist {
 	struct list_head nlp_listp;
-	struct lpfc_name nlp_portname;		/* port name */
-	struct lpfc_name nlp_nodename;		/* node name */
+	struct lpfc_name nlp_portname;
+	struct lpfc_name nlp_nodename;
 	uint32_t         nlp_flag;		/* entry  flags */
 	uint32_t         nlp_DID;		/* FC D_ID of entry */
 	uint32_t         nlp_last_elscmd;	/* Last ELS cmd sent */
@@ -75,8 +77,9 @@
 	struct timer_list   nlp_delayfunc;	/* Used for delayed ELS cmds */
 	struct fc_rport *rport;			/* Corresponding FC transport
 						   port structure */
-	struct lpfc_hba      *nlp_phba;
+	struct lpfc_vport *vport;
 	struct lpfc_work_evt els_retry_evt;
+	struct lpfc_work_evt dev_loss_evt;
 	unsigned long last_ramp_up_time;        /* jiffy of last ramp up */
 	unsigned long last_q_full_time;		/* jiffy of last queue full */
 	struct kref     kref;
@@ -98,7 +101,9 @@
 					   ACC */
 #define NLP_NPR_ADISC      0x2000000	/* Issue ADISC when dq'ed from
 					   NPR list */
+#define NLP_RM_DFLT_RPI    0x4000000	/* need to remove leftover dflt RPI */
 #define NLP_NODEV_REMOVE   0x8000000	/* Defer removal till discovery ends */
+#define NLP_TARGET_REMOVE  0x10000000   /* Target remove in process */
 
 /* There are 4 different double linked lists nodelist entries can reside on.
  * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 638b3cd..33fbc16 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -35,38 +35,38 @@
 #include "lpfc.h"
 #include "lpfc_logmsg.h"
 #include "lpfc_crtn.h"
+#include "lpfc_vport.h"
+#include "lpfc_debugfs.h"
 
 static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
 			  struct lpfc_iocbq *);
+static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *,
+			struct lpfc_iocbq *);
+
 static int lpfc_max_els_tries = 3;
 
-static int
-lpfc_els_chk_latt(struct lpfc_hba * phba)
+int
+lpfc_els_chk_latt(struct lpfc_vport *vport)
 {
-	struct lpfc_sli *psli;
-	LPFC_MBOXQ_t *mbox;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	uint32_t ha_copy;
-	int rc;
 
-	psli = &phba->sli;
-
-	if ((phba->hba_state >= LPFC_HBA_READY) ||
-	    (phba->hba_state == LPFC_LINK_DOWN))
+	if (vport->port_state >= LPFC_VPORT_READY ||
+	    phba->link_state == LPFC_LINK_DOWN)
 		return 0;
 
 	/* Read the HBA Host Attention Register */
-	spin_lock_irq(phba->host->host_lock);
 	ha_copy = readl(phba->HAregaddr);
-	spin_unlock_irq(phba->host->host_lock);
 
 	if (!(ha_copy & HA_LATT))
 		return 0;
 
 	/* Pending Link Event during Discovery */
-	lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
-			"%d:0237 Pending Link Event during "
+	lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+			"%d (%d):0237 Pending Link Event during "
 			"Discovery: State x%x\n",
-			phba->brd_no, phba->hba_state);
+			phba->brd_no, vport->vpi,  phba->pport->port_state);
 
 	/* CLEAR_LA should re-enable link attention events and
 	 * we should then imediately take a LATT event. The
@@ -74,48 +74,34 @@
 	 * will cleanup any left over in-progress discovery
 	 * events.
 	 */
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag |= FC_ABORT_DISCOVERY;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag |= FC_ABORT_DISCOVERY;
+	spin_unlock_irq(shost->host_lock);
 
-	if (phba->hba_state != LPFC_CLEAR_LA) {
-		if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
-			phba->hba_state = LPFC_CLEAR_LA;
-			lpfc_clear_la(phba, mbox);
-			mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
-			rc = lpfc_sli_issue_mbox (phba, mbox,
-						  (MBX_NOWAIT | MBX_STOP_IOCB));
-			if (rc == MBX_NOT_FINISHED) {
-				mempool_free(mbox, phba->mbox_mem_pool);
-				phba->hba_state = LPFC_HBA_ERROR;
-			}
-		}
-	}
+	if (phba->link_state != LPFC_CLEAR_LA)
+		lpfc_issue_clear_la(phba, vport);
 
 	return 1;
-
 }
 
 static struct lpfc_iocbq *
-lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
-		   uint16_t cmdSize, uint8_t retry, struct lpfc_nodelist * ndlp,
-		   uint32_t did, uint32_t elscmd)
+lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
+		   uint16_t cmdSize, uint8_t retry,
+		   struct lpfc_nodelist *ndlp, uint32_t did,
+		   uint32_t elscmd)
 {
-	struct lpfc_sli_ring *pring;
+	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_iocbq *elsiocb;
 	struct lpfc_dmabuf *pcmd, *prsp, *pbuflist;
 	struct ulp_bde64 *bpl;
 	IOCB_t *icmd;
 
-	pring = &phba->sli.ring[LPFC_ELS_RING];
 
-	if (phba->hba_state < LPFC_LINK_UP)
-		return  NULL;
+	if (!lpfc_is_link_up(phba))
+		return NULL;
 
 	/* Allocate buffer for  command iocb */
-	spin_lock_irq(phba->host->host_lock);
 	elsiocb = lpfc_sli_get_iocbq(phba);
-	spin_unlock_irq(phba->host->host_lock);
 
 	if (elsiocb == NULL)
 		return NULL;
@@ -123,14 +109,12 @@
 
 	/* fill in BDEs for command */
 	/* Allocate buffer for command payload */
-	if (((pcmd = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
+	if (((pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
 	    ((pcmd->virt = lpfc_mbuf_alloc(phba,
 					   MEM_PRI, &(pcmd->phys))) == 0)) {
 		kfree(pcmd);
 
-		spin_lock_irq(phba->host->host_lock);
 		lpfc_sli_release_iocbq(phba, elsiocb);
-		spin_unlock_irq(phba->host->host_lock);
 		return NULL;
 	}
 
@@ -138,7 +122,7 @@
 
 	/* Allocate buffer for response payload */
 	if (expectRsp) {
-		prsp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
+		prsp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
 		if (prsp)
 			prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
 						     &prsp->phys);
@@ -146,9 +130,7 @@
 			kfree(prsp);
 			lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
 			kfree(pcmd);
-			spin_lock_irq(phba->host->host_lock);
 			lpfc_sli_release_iocbq(phba, elsiocb);
-			spin_unlock_irq(phba->host->host_lock);
 			return NULL;
 		}
 		INIT_LIST_HEAD(&prsp->list);
@@ -157,14 +139,12 @@
 	}
 
 	/* Allocate buffer for Buffer ptr list */
-	pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
+	pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
 	if (pbuflist)
-	    pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
-					     &pbuflist->phys);
+		pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
+						 &pbuflist->phys);
 	if (pbuflist == 0 || pbuflist->virt == 0) {
-		spin_lock_irq(phba->host->host_lock);
 		lpfc_sli_release_iocbq(phba, elsiocb);
-		spin_unlock_irq(phba->host->host_lock);
 		lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
 		lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
 		kfree(pcmd);
@@ -178,20 +158,28 @@
 	icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
 	icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
 	icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
+	icmd->un.elsreq64.remoteID = did;	/* DID */
 	if (expectRsp) {
-		icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
-		icmd->un.elsreq64.remoteID = did;	/* DID */
+		icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
 		icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
 		icmd->ulpTimeout = phba->fc_ratov * 2;
 	} else {
-		icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64);
+		icmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64);
 		icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
 	}
-
 	icmd->ulpBdeCount = 1;
 	icmd->ulpLe = 1;
 	icmd->ulpClass = CLASS3;
 
+	if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+		icmd->un.elsreq64.myID = vport->fc_myDID;
+
+		/* For ELS_REQUEST64_CR, use the VPI by default */
+		icmd->ulpContext = vport->vpi;
+		icmd->ulpCt_h = 0;
+		icmd->ulpCt_l = 1;
+	}
+
 	bpl = (struct ulp_bde64 *) pbuflist->virt;
 	bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys));
 	bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys));
@@ -209,10 +197,12 @@
 	}
 
 	/* Save for completion so we can release these resources */
-	elsiocb->context1 = lpfc_nlp_get(ndlp);
+	if (elscmd != ELS_CMD_LS_RJT)
+		elsiocb->context1 = lpfc_nlp_get(ndlp);
 	elsiocb->context2 = pcmd;
 	elsiocb->context3 = pbuflist;
 	elsiocb->retry = retry;
+	elsiocb->vport = vport;
 	elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
 
 	if (prsp) {
@@ -222,16 +212,16 @@
 	if (expectRsp) {
 		/* Xmit ELS command <elsCmd> to remote NPORT <did> */
 		lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-				"%d:0116 Xmit ELS command x%x to remote "
-				"NPORT x%x I/O tag: x%x, HBA state: x%x\n",
-				phba->brd_no, elscmd,
-				did, elsiocb->iotag, phba->hba_state);
+				"%d (%d):0116 Xmit ELS command x%x to remote "
+				"NPORT x%x I/O tag: x%x, port state: x%x\n",
+				phba->brd_no, vport->vpi,  elscmd, did,
+				elsiocb->iotag, vport->port_state);
 	} else {
 		/* Xmit ELS response <elsCmd> to remote NPORT <did> */
 		lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-				"%d:0117 Xmit ELS response x%x to remote "
+				"%d (%d):0117 Xmit ELS response x%x to remote "
 				"NPORT x%x I/O tag: x%x, size: x%x\n",
-				phba->brd_no, elscmd,
+				phba->brd_no, vport->vpi, elscmd,
 				ndlp->nlp_DID, elsiocb->iotag, cmdSize);
 	}
 
@@ -240,16 +230,79 @@
 
 
 static int
-lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
-		struct serv_parm *sp, IOCB_t *irsp)
+lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	LPFC_MBOXQ_t *mbox;
 	struct lpfc_dmabuf *mp;
+	struct lpfc_nodelist *ndlp;
+	struct serv_parm *sp;
 	int rc;
 
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag |= FC_FABRIC;
-	spin_unlock_irq(phba->host->host_lock);
+	sp = &phba->fc_fabparam;
+	ndlp = lpfc_findnode_did(vport, Fabric_DID);
+	if (!ndlp)
+		goto fail;
+
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!mbox)
+		goto fail;
+
+	vport->port_state = LPFC_FABRIC_CFG_LINK;
+	lpfc_config_link(phba, mbox);
+	mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+	mbox->vport = vport;
+
+	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
+	if (rc == MBX_NOT_FINISHED)
+		goto fail_free_mbox;
+
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!mbox)
+		goto fail;
+	rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
+			    0);
+	if (rc)
+		goto fail_free_mbox;
+
+	mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
+	mbox->vport = vport;
+	mbox->context2 = lpfc_nlp_get(ndlp);
+
+	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
+	if (rc == MBX_NOT_FINISHED)
+		goto fail_issue_reg_login;
+
+	return 0;
+
+fail_issue_reg_login:
+	lpfc_nlp_put(ndlp);
+	mp = (struct lpfc_dmabuf *) mbox->context1;
+	lpfc_mbuf_free(phba, mp->virt, mp->phys);
+	kfree(mp);
+fail_free_mbox:
+	mempool_free(mbox, phba->mbox_mem_pool);
+
+fail:
+	lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+	lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+		"%d (%d):0249 Cannot issue Register Fabric login\n",
+		phba->brd_no, vport->vpi);
+	return -ENXIO;
+}
+
+static int
+lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   struct serv_parm *sp, IOCB_t *irsp)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+	struct lpfc_nodelist *np;
+	struct lpfc_nodelist *next_np;
+
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag |= FC_FABRIC;
+	spin_unlock_irq(shost->host_lock);
 
 	phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov);
 	if (sp->cmn.edtovResolution)	/* E_D_TOV ticks are in nanoseconds */
@@ -258,20 +311,20 @@
 	phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
 
 	if (phba->fc_topology == TOPOLOGY_LOOP) {
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag |= FC_PUBLIC_LOOP;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag |= FC_PUBLIC_LOOP;
+		spin_unlock_irq(shost->host_lock);
 	} else {
 		/*
 		 * If we are a N-port connected to a Fabric, fixup sparam's so
 		 * logins to devices on remote loops work.
 		 */
-		phba->fc_sparam.cmn.altBbCredit = 1;
+		vport->fc_sparam.cmn.altBbCredit = 1;
 	}
 
-	phba->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
+	vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
 	memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name));
-	memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
+	memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof(struct lpfc_name));
 	ndlp->nlp_class_sup = 0;
 	if (sp->cls1.classValid)
 		ndlp->nlp_class_sup |= FC_COS_CLASS1;
@@ -285,68 +338,85 @@
 				sp->cmn.bbRcvSizeLsb;
 	memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
 
-	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mbox)
-		goto fail;
+	if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+		if (sp->cmn.response_multiple_NPort) {
+			lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
+					"%d:1816 FLOGI NPIV supported, "
+					"response data 0x%x\n",
+					phba->brd_no,
+					sp->cmn.response_multiple_NPort);
+			phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
 
-	phba->hba_state = LPFC_FABRIC_CFG_LINK;
-	lpfc_config_link(phba, mbox);
-	mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		} else {
+			/* Because we asked f/w for NPIV it still expects us
+			   to call reg_vnpid atleast for the physcial host */
+			lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
+					"%d:1817 Fabric does not support NPIV "
+					"- configuring single port mode.\n",
+					phba->brd_no);
+			phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
+		}
+	}
 
-	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
-	if (rc == MBX_NOT_FINISHED)
-		goto fail_free_mbox;
+	if ((vport->fc_prevDID != vport->fc_myDID) &&
+		!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
 
-	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mbox)
-		goto fail;
+		/* If our NportID changed, we need to ensure all
+		 * remaining NPORTs get unreg_login'ed.
+		 */
+		list_for_each_entry_safe(np, next_np,
+					&vport->fc_nodes, nlp_listp) {
+			if ((np->nlp_state != NLP_STE_NPR_NODE) ||
+				   !(np->nlp_flag & NLP_NPR_ADISC))
+				continue;
+			spin_lock_irq(shost->host_lock);
+			np->nlp_flag &= ~NLP_NPR_ADISC;
+			spin_unlock_irq(shost->host_lock);
+			lpfc_unreg_rpi(vport, np);
+		}
+		if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+			lpfc_mbx_unreg_vpi(vport);
+			vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+		}
+	}
 
-	if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
-		goto fail_free_mbox;
+	ndlp->nlp_sid = irsp->un.ulpWord[4] & Mask_DID;
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
 
-	mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
-	mbox->context2 = lpfc_nlp_get(ndlp);
-
-	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
-	if (rc == MBX_NOT_FINISHED)
-		goto fail_issue_reg_login;
-
+	if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED &&
+	    vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) {
+		lpfc_register_new_vport(phba, vport, ndlp);
+		return 0;
+	}
+	lpfc_issue_fabric_reglogin(vport);
 	return 0;
-
- fail_issue_reg_login:
-	lpfc_nlp_put(ndlp);
-	mp = (struct lpfc_dmabuf *) mbox->context1;
-	lpfc_mbuf_free(phba, mp->virt, mp->phys);
-	kfree(mp);
- fail_free_mbox:
-	mempool_free(mbox, phba->mbox_mem_pool);
- fail:
-	return -ENXIO;
 }
 
 /*
  * We FLOGIed into an NPort, initiate pt2pt protocol
  */
 static int
-lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
-		struct serv_parm *sp)
+lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  struct serv_parm *sp)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	LPFC_MBOXQ_t *mbox;
 	int rc;
 
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
-	spin_unlock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+	spin_unlock_irq(shost->host_lock);
 
 	phba->fc_edtov = FF_DEF_EDTOV;
 	phba->fc_ratov = FF_DEF_RATOV;
-	rc = memcmp(&phba->fc_portname, &sp->portName,
-			sizeof(struct lpfc_name));
+	rc = memcmp(&vport->fc_portname, &sp->portName,
+		    sizeof(vport->fc_portname));
 	if (rc >= 0) {
 		/* This side will initiate the PLOGI */
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag |= FC_PT2PT_PLOGI;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag |= FC_PT2PT_PLOGI;
+		spin_unlock_irq(shost->host_lock);
 
 		/*
 		 * N_Port ID cannot be 0, set our to LocalID the other
@@ -355,7 +425,7 @@
 
 		/* not equal */
 		if (rc)
-			phba->fc_myDID = PT2PT_LocalID;
+			vport->fc_myDID = PT2PT_LocalID;
 
 		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 		if (!mbox)
@@ -364,15 +434,16 @@
 		lpfc_config_link(phba, mbox);
 
 		mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		mbox->vport = vport;
 		rc = lpfc_sli_issue_mbox(phba, mbox,
-				MBX_NOWAIT | MBX_STOP_IOCB);
+					 MBX_NOWAIT | MBX_STOP_IOCB);
 		if (rc == MBX_NOT_FINISHED) {
 			mempool_free(mbox, phba->mbox_mem_pool);
 			goto fail;
 		}
 		lpfc_nlp_put(ndlp);
 
-		ndlp = lpfc_findnode_did(phba, PT2PT_RemoteID);
+		ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID);
 		if (!ndlp) {
 			/*
 			 * Cannot find existing Fabric ndlp, so allocate a
@@ -382,28 +453,30 @@
 			if (!ndlp)
 				goto fail;
 
-			lpfc_nlp_init(phba, ndlp, PT2PT_RemoteID);
+			lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID);
 		}
 
 		memcpy(&ndlp->nlp_portname, &sp->portName,
-				sizeof(struct lpfc_name));
+		       sizeof(struct lpfc_name));
 		memcpy(&ndlp->nlp_nodename, &sp->nodeName,
-				sizeof(struct lpfc_name));
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+		       sizeof(struct lpfc_name));
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+		spin_unlock_irq(shost->host_lock);
 	} else {
 		/* This side will wait for the PLOGI */
 		lpfc_nlp_put(ndlp);
 	}
 
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag |= FC_PT2PT;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag |= FC_PT2PT;
+	spin_unlock_irq(shost->host_lock);
 
 	/* Start discovery - this should just do CLEAR_LA */
-	lpfc_disc_start(phba);
+	lpfc_disc_start(vport);
 	return 0;
- fail:
+fail:
 	return -ENXIO;
 }
 
@@ -411,6 +484,8 @@
 lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 		    struct lpfc_iocbq *rspiocb)
 {
+	struct lpfc_vport *vport = cmdiocb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp = &rspiocb->iocb;
 	struct lpfc_nodelist *ndlp = cmdiocb->context1;
 	struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
@@ -418,21 +493,25 @@
 	int rc;
 
 	/* Check to see if link went down during discovery */
-	if (lpfc_els_chk_latt(phba)) {
+	if (lpfc_els_chk_latt(vport)) {
 		lpfc_nlp_put(ndlp);
 		goto out;
 	}
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"FLOGI cmpl:      status:x%x/x%x state:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4],
+		vport->port_state);
+
 	if (irsp->ulpStatus) {
 		/* Check for retry */
-		if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
-			/* ELS command is being retried */
+		if (lpfc_els_retry(phba, cmdiocb, rspiocb))
 			goto out;
-		}
+
 		/* FLOGI failed, so there is no fabric */
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+		spin_unlock_irq(shost->host_lock);
 
 		/* If private loop, then allow max outstanding els to be
 		 * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
@@ -443,11 +522,10 @@
 		}
 
 		/* FLOGI failure */
-		lpfc_printf_log(phba,
-				KERN_INFO,
-				LOG_ELS,
-				"%d:0100 FLOGI failure Data: x%x x%x x%x\n",
-				phba->brd_no,
+		lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+				"%d (%d):0100 FLOGI failure Data: x%x x%x "
+				"x%x\n",
+				phba->brd_no, vport->vpi,
 				irsp->ulpStatus, irsp->un.ulpWord[4],
 				irsp->ulpTimeout);
 		goto flogifail;
@@ -463,21 +541,21 @@
 
 	/* FLOGI completes successfully */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0101 FLOGI completes sucessfully "
+			"%d (%d):0101 FLOGI completes sucessfully "
 			"Data: x%x x%x x%x x%x\n",
-			phba->brd_no,
+			phba->brd_no, vport->vpi,
 			irsp->un.ulpWord[4], sp->cmn.e_d_tov,
 			sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
 
-	if (phba->hba_state == LPFC_FLOGI) {
+	if (vport->port_state == LPFC_FLOGI) {
 		/*
 		 * If Common Service Parameters indicate Nport
 		 * we are point to point, if Fport we are Fabric.
 		 */
 		if (sp->cmn.fPort)
-			rc = lpfc_cmpl_els_flogi_fabric(phba, ndlp, sp, irsp);
+			rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp);
 		else
-			rc = lpfc_cmpl_els_flogi_nport(phba, ndlp, sp);
+			rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp);
 
 		if (!rc)
 			goto out;
@@ -486,14 +564,12 @@
 flogifail:
 	lpfc_nlp_put(ndlp);
 
-	if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
-	    (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
-	     irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) {
+	if (!lpfc_error_lost_link(irsp)) {
 		/* FLOGI failed, so just use loop map to make discovery list */
-		lpfc_disc_list_loopmap(phba);
+		lpfc_disc_list_loopmap(vport);
 
 		/* Start discovery */
-		lpfc_disc_start(phba);
+		lpfc_disc_start(vport);
 	}
 
 out:
@@ -501,9 +577,10 @@
 }
 
 static int
-lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		     uint8_t retry)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	struct serv_parm *sp;
 	IOCB_t *icmd;
 	struct lpfc_iocbq *elsiocb;
@@ -515,9 +592,10 @@
 
 	pring = &phba->sli.ring[LPFC_ELS_RING];
 
-	cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
-	elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-						 ndlp->nlp_DID, ELS_CMD_FLOGI);
+	cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_FLOGI);
+
 	if (!elsiocb)
 		return 1;
 
@@ -526,8 +604,8 @@
 
 	/* For FLOGI request, remainder of payload is service parameters */
 	*((uint32_t *) (pcmd)) = ELS_CMD_FLOGI;
-	pcmd += sizeof (uint32_t);
-	memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
+	pcmd += sizeof(uint32_t);
+	memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
 	sp = (struct serv_parm *) pcmd;
 
 	/* Setup CSPs accordingly for Fabric */
@@ -541,16 +619,32 @@
 	if (sp->cmn.fcphHigh < FC_PH3)
 		sp->cmn.fcphHigh = FC_PH3;
 
+	if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+		sp->cmn.request_multiple_Nport = 1;
+
+		/* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
+		icmd->ulpCt_h = 1;
+		icmd->ulpCt_l = 0;
+	}
+
+	if (phba->fc_topology != TOPOLOGY_LOOP) {
+		icmd->un.elsreq64.myID = 0;
+		icmd->un.elsreq64.fl = 1;
+	}
+
 	tmo = phba->fc_ratov;
 	phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
-	lpfc_set_disctmo(phba);
+	lpfc_set_disctmo(vport);
 	phba->fc_ratov = tmo;
 
 	phba->fc_stat.elsXmitFLOGI++;
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
-	spin_lock_irq(phba->host->host_lock);
-	rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
-	spin_unlock_irq(phba->host->host_lock);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue FLOGI:     opt:x%x",
+		phba->sli3_options, 0, 0);
+
+	rc = lpfc_issue_fabric_iocb(phba, elsiocb);
 	if (rc == IOCB_ERROR) {
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
@@ -559,7 +653,7 @@
 }
 
 int
-lpfc_els_abort_flogi(struct lpfc_hba * phba)
+lpfc_els_abort_flogi(struct lpfc_hba *phba)
 {
 	struct lpfc_sli_ring *pring;
 	struct lpfc_iocbq *iocb, *next_iocb;
@@ -577,73 +671,99 @@
 	 * Check the txcmplq for an iocb that matches the nport the driver is
 	 * searching for.
 	 */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
 		icmd = &iocb->iocb;
-		if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
+		if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
+		    icmd->un.elsreq64.bdl.ulpIoTag32) {
 			ndlp = (struct lpfc_nodelist *)(iocb->context1);
-			if (ndlp && (ndlp->nlp_DID == Fabric_DID))
+			if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
 				lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+			}
 		}
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	return 0;
 }
 
 int
-lpfc_initial_flogi(struct lpfc_hba *phba)
+lpfc_initial_flogi(struct lpfc_vport *vport)
 {
+	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_nodelist *ndlp;
 
 	/* First look for the Fabric ndlp */
-	ndlp = lpfc_findnode_did(phba, Fabric_DID);
+	ndlp = lpfc_findnode_did(vport, Fabric_DID);
 	if (!ndlp) {
 		/* Cannot find existing Fabric ndlp, so allocate a new one */
 		ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
 		if (!ndlp)
 			return 0;
-		lpfc_nlp_init(phba, ndlp, Fabric_DID);
+		lpfc_nlp_init(vport, ndlp, Fabric_DID);
 	} else {
-		lpfc_dequeue_node(phba, ndlp);
+		lpfc_dequeue_node(vport, ndlp);
 	}
-	if (lpfc_issue_els_flogi(phba, ndlp, 0)) {
+	if (lpfc_issue_els_flogi(vport, ndlp, 0)) {
 		lpfc_nlp_put(ndlp);
 	}
 	return 1;
 }
 
+int
+lpfc_initial_fdisc(struct lpfc_vport *vport)
+{
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_nodelist *ndlp;
+
+	/* First look for the Fabric ndlp */
+	ndlp = lpfc_findnode_did(vport, Fabric_DID);
+	if (!ndlp) {
+		/* Cannot find existing Fabric ndlp, so allocate a new one */
+		ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+		if (!ndlp)
+			return 0;
+		lpfc_nlp_init(vport, ndlp, Fabric_DID);
+	} else {
+		lpfc_dequeue_node(vport, ndlp);
+	}
+	if (lpfc_issue_els_fdisc(vport, ndlp, 0)) {
+		lpfc_nlp_put(ndlp);
+	}
+	return 1;
+}
 static void
-lpfc_more_plogi(struct lpfc_hba * phba)
+lpfc_more_plogi(struct lpfc_vport *vport)
 {
 	int sentplogi;
+	struct lpfc_hba *phba = vport->phba;
 
-	if (phba->num_disc_nodes)
-		phba->num_disc_nodes--;
+	if (vport->num_disc_nodes)
+		vport->num_disc_nodes--;
 
 	/* Continue discovery with <num_disc_nodes> PLOGIs to go */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d:0232 Continue discovery with %d PLOGIs to go "
+			"%d (%d):0232 Continue discovery with %d PLOGIs to go "
 			"Data: x%x x%x x%x\n",
-			phba->brd_no, phba->num_disc_nodes, phba->fc_plogi_cnt,
-			phba->fc_flag, phba->hba_state);
+			phba->brd_no, vport->vpi, vport->num_disc_nodes,
+			vport->fc_plogi_cnt, vport->fc_flag, vport->port_state);
 
 	/* Check to see if there are more PLOGIs to be sent */
-	if (phba->fc_flag & FC_NLP_MORE) {
-		/* go thru NPR list and issue any remaining ELS PLOGIs */
-		sentplogi = lpfc_els_disc_plogi(phba);
-	}
+	if (vport->fc_flag & FC_NLP_MORE)
+		/* go thru NPR nodes and issue any remaining ELS PLOGIs */
+		sentplogi = lpfc_els_disc_plogi(vport);
+
 	return;
 }
 
 static struct lpfc_nodelist *
-lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp,
+lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
 			 struct lpfc_nodelist *ndlp)
 {
+	struct lpfc_vport    *vport = ndlp->vport;
 	struct lpfc_nodelist *new_ndlp;
-	uint32_t *lp;
 	struct serv_parm *sp;
-	uint8_t name[sizeof (struct lpfc_name)];
+	uint8_t  name[sizeof(struct lpfc_name)];
 	uint32_t rc;
 
 	/* Fabric nodes can have the same WWPN so we don't bother searching
@@ -652,50 +772,51 @@
 	if (ndlp->nlp_type & NLP_FABRIC)
 		return ndlp;
 
-	lp = (uint32_t *) prsp->virt;
-	sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+	sp = (struct serv_parm *) ((uint8_t *) prsp + sizeof(uint32_t));
 	memset(name, 0, sizeof(struct lpfc_name));
 
 	/* Now we find out if the NPort we are logging into, matches the WWPN
 	 * we have for that ndlp. If not, we have some work to do.
 	 */
-	new_ndlp = lpfc_findnode_wwpn(phba, &sp->portName);
+	new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName);
 
 	if (new_ndlp == ndlp)
 		return ndlp;
 
 	if (!new_ndlp) {
-		rc =
-		   memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
+		rc = memcmp(&ndlp->nlp_portname, name,
+			    sizeof(struct lpfc_name));
 		if (!rc)
 			return ndlp;
 		new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
 		if (!new_ndlp)
 			return ndlp;
 
-		lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID);
+		lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
 	}
 
-	lpfc_unreg_rpi(phba, new_ndlp);
+	lpfc_unreg_rpi(vport, new_ndlp);
 	new_ndlp->nlp_DID = ndlp->nlp_DID;
 	new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
-	lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state);
+	lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);
 
-	/* Move this back to NPR list */
+	/* Move this back to NPR state */
 	if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
-		lpfc_drop_node(phba, ndlp);
+		lpfc_drop_node(vport, ndlp);
 	else {
-		lpfc_unreg_rpi(phba, ndlp);
+		lpfc_unreg_rpi(vport, ndlp);
 		ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 	}
 	return new_ndlp;
 }
 
 static void
-lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		    struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		    struct lpfc_iocbq *rspiocb)
 {
+	struct lpfc_vport *vport = cmdiocb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
 	struct lpfc_nodelist *ndlp;
 	struct lpfc_dmabuf *prsp;
@@ -705,32 +826,43 @@
 	cmdiocb->context_un.rsp_iocb = rspiocb;
 
 	irsp = &rspiocb->iocb;
-	ndlp = lpfc_findnode_did(phba, irsp->un.elsreq64.remoteID);
-	if (!ndlp)
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"PLOGI cmpl:      status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4],
+		irsp->un.elsreq64.remoteID);
+
+	ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
+	if (!ndlp) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0136 PLOGI completes to NPort x%x "
+			"with no ndlp. Data: x%x x%x x%x\n",
+			phba->brd_no, vport->vpi, irsp->un.elsreq64.remoteID,
+			irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpIoTag);
 		goto out;
+	}
 
 	/* Since ndlp can be freed in the disc state machine, note if this node
 	 * is being used during discovery.
 	 */
+	spin_lock_irq(shost->host_lock);
 	disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
-	spin_lock_irq(phba->host->host_lock);
 	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 	rc   = 0;
 
 	/* PLOGI completes to NPort <nlp_DID> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0102 PLOGI completes to NPort x%x "
+			"%d (%d):0102 PLOGI completes to NPort x%x "
 			"Data: x%x x%x x%x x%x x%x\n",
-			phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
-			irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
-			phba->num_disc_nodes);
+			phba->brd_no, vport->vpi, ndlp->nlp_DID,
+			irsp->ulpStatus, irsp->un.ulpWord[4],
+			irsp->ulpTimeout, disc, vport->num_disc_nodes);
 
 	/* Check to see if link went down during discovery */
-	if (lpfc_els_chk_latt(phba)) {
-		spin_lock_irq(phba->host->host_lock);
+	if (lpfc_els_chk_latt(vport)) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		goto out;
 	}
 
@@ -743,56 +875,62 @@
 		if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
 			/* ELS command is being retried */
 			if (disc) {
-				spin_lock_irq(phba->host->host_lock);
+				spin_lock_irq(shost->host_lock);
 				ndlp->nlp_flag |= NLP_NPR_2B_DISC;
-				spin_unlock_irq(phba->host->host_lock);
+				spin_unlock_irq(shost->host_lock);
 			}
 			goto out;
 		}
 
 		/* PLOGI failed */
+		if (ndlp->nlp_DID == NameServer_DID) {
+			lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+			lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+				"%d (%d):0250 Nameserver login error: "
+				"0x%x / 0x%x\n",
+				phba->brd_no, vport->vpi,
+				irsp->ulpStatus, irsp->un.ulpWord[4]);
+		}
+
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
-		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
-		   (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
-		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+		if (lpfc_error_lost_link(irsp)) {
 			rc = NLP_STE_FREED_NODE;
 		} else {
-			rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-					NLP_EVT_CMPL_PLOGI);
+			rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+						     NLP_EVT_CMPL_PLOGI);
 		}
 	} else {
 		/* Good status, call state machine */
 		prsp = list_entry(((struct lpfc_dmabuf *)
-			cmdiocb->context2)->list.next,
-			struct lpfc_dmabuf, list);
-		ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
-		rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-					NLP_EVT_CMPL_PLOGI);
+				   cmdiocb->context2)->list.next,
+				  struct lpfc_dmabuf, list);
+		ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
+		rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+					     NLP_EVT_CMPL_PLOGI);
 	}
 
-	if (disc && phba->num_disc_nodes) {
+	if (disc && vport->num_disc_nodes) {
 		/* Check to see if there are more PLOGIs to be sent */
-		lpfc_more_plogi(phba);
+		lpfc_more_plogi(vport);
 
-		if (phba->num_disc_nodes == 0) {
-			spin_lock_irq(phba->host->host_lock);
-			phba->fc_flag &= ~FC_NDISC_ACTIVE;
-			spin_unlock_irq(phba->host->host_lock);
+		if (vport->num_disc_nodes == 0) {
+			spin_lock_irq(shost->host_lock);
+			vport->fc_flag &= ~FC_NDISC_ACTIVE;
+			spin_unlock_irq(shost->host_lock);
 
-			lpfc_can_disctmo(phba);
-			if (phba->fc_flag & FC_RSCN_MODE) {
+			lpfc_can_disctmo(vport);
+			if (vport->fc_flag & FC_RSCN_MODE) {
 				/*
 				 * Check to see if more RSCNs came in while
 				 * we were processing this one.
 				 */
-				if ((phba->fc_rscn_id_cnt == 0) &&
-			    	(!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
-					spin_lock_irq(phba->host->host_lock);
-					phba->fc_flag &= ~FC_RSCN_MODE;
-					spin_unlock_irq(phba->host->host_lock);
+				if ((vport->fc_rscn_id_cnt == 0) &&
+				    (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
+					spin_lock_irq(shost->host_lock);
+					vport->fc_flag &= ~FC_RSCN_MODE;
+					spin_unlock_irq(shost->host_lock);
 				} else {
-					lpfc_els_handle_rscn(phba);
+					lpfc_els_handle_rscn(vport);
 				}
 			}
 		}
@@ -804,8 +942,9 @@
 }
 
 int
-lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry)
+lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	struct serv_parm *sp;
 	IOCB_t *icmd;
 	struct lpfc_iocbq *elsiocb;
@@ -813,13 +952,14 @@
 	struct lpfc_sli *psli;
 	uint8_t *pcmd;
 	uint16_t cmdsize;
+	int ret;
 
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
 
-	cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
-	elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did,
-								ELS_CMD_PLOGI);
+	cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, NULL, did,
+				     ELS_CMD_PLOGI);
 	if (!elsiocb)
 		return 1;
 
@@ -828,8 +968,8 @@
 
 	/* For PLOGI request, remainder of payload is service parameters */
 	*((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;
-	pcmd += sizeof (uint32_t);
-	memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
+	pcmd += sizeof(uint32_t);
+	memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
 	sp = (struct serv_parm *) pcmd;
 
 	if (sp->cmn.fcphLow < FC_PH_4_3)
@@ -838,22 +978,27 @@
 	if (sp->cmn.fcphHigh < FC_PH3)
 		sp->cmn.fcphHigh = FC_PH3;
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue PLOGI:     did:x%x",
+		did, 0, 0);
+
 	phba->fc_stat.elsXmitPLOGI++;
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
-	spin_lock_irq(phba->host->host_lock);
-	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-		spin_unlock_irq(phba->host->host_lock);
+	ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
+
+	if (ret == IOCB_ERROR) {
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
 	}
-	spin_unlock_irq(phba->host->host_lock);
 	return 0;
 }
 
 static void
-lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		   struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		   struct lpfc_iocbq *rspiocb)
 {
+	struct lpfc_vport *vport = cmdiocb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
 	struct lpfc_sli *psli;
 	struct lpfc_nodelist *ndlp;
@@ -864,21 +1009,26 @@
 
 	irsp = &(rspiocb->iocb);
 	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~NLP_PRLI_SND;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"PRLI cmpl:       status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4],
+		ndlp->nlp_DID);
 
 	/* PRLI completes to NPort <nlp_DID> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0103 PRLI completes to NPort x%x "
+			"%d (%d):0103 PRLI completes to NPort x%x "
 			"Data: x%x x%x x%x x%x\n",
-			phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
-			irsp->un.ulpWord[4], irsp->ulpTimeout,
-			phba->num_disc_nodes);
+			phba->brd_no, vport->vpi, ndlp->nlp_DID,
+			irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
+			vport->num_disc_nodes);
 
-	phba->fc_prli_sent--;
+	vport->fc_prli_sent--;
 	/* Check to see if link went down during discovery */
-	if (lpfc_els_chk_latt(phba))
+	if (lpfc_els_chk_latt(vport))
 		goto out;
 
 	if (irsp->ulpStatus) {
@@ -889,18 +1039,16 @@
 		}
 		/* PRLI failed */
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
-		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
-		   (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
-		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+		if (lpfc_error_lost_link(irsp)) {
 			goto out;
 		} else {
-			lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-					NLP_EVT_CMPL_PRLI);
+			lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+						NLP_EVT_CMPL_PRLI);
 		}
 	} else {
 		/* Good status, call state machine */
-		lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI);
+		lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+					NLP_EVT_CMPL_PRLI);
 	}
 
 out:
@@ -909,9 +1057,11 @@
 }
 
 int
-lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		    uint8_t retry)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba *phba = vport->phba;
 	PRLI *npr;
 	IOCB_t *icmd;
 	struct lpfc_iocbq *elsiocb;
@@ -923,9 +1073,9 @@
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
 
-	cmdsize = (sizeof (uint32_t) + sizeof (PRLI));
-	elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-					ndlp->nlp_DID, ELS_CMD_PRLI);
+	cmdsize = (sizeof(uint32_t) + sizeof(PRLI));
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_PRLI);
 	if (!elsiocb)
 		return 1;
 
@@ -933,9 +1083,9 @@
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
 	/* For PRLI request, remainder of payload is service parameters */
-	memset(pcmd, 0, (sizeof (PRLI) + sizeof (uint32_t)));
+	memset(pcmd, 0, (sizeof(PRLI) + sizeof(uint32_t)));
 	*((uint32_t *) (pcmd)) = ELS_CMD_PRLI;
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 
 	/* For PRLI, remainder of payload is PRLI parameter page */
 	npr = (PRLI *) pcmd;
@@ -955,81 +1105,88 @@
 	npr->prliType = PRLI_FCP_TYPE;
 	npr->initiatorFunc = 1;
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue PRLI:      did:x%x",
+		ndlp->nlp_DID, 0, 0);
+
 	phba->fc_stat.elsXmitPRLI++;
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= NLP_PRLI_SND;
+	spin_unlock_irq(shost->host_lock);
 	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_PRLI_SND;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
 	}
-	spin_unlock_irq(phba->host->host_lock);
-	phba->fc_prli_sent++;
+	vport->fc_prli_sent++;
 	return 0;
 }
 
 static void
-lpfc_more_adisc(struct lpfc_hba * phba)
+lpfc_more_adisc(struct lpfc_vport *vport)
 {
 	int sentadisc;
+	struct lpfc_hba *phba = vport->phba;
 
-	if (phba->num_disc_nodes)
-		phba->num_disc_nodes--;
+	if (vport->num_disc_nodes)
+		vport->num_disc_nodes--;
 
 	/* Continue discovery with <num_disc_nodes> ADISCs to go */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d:0210 Continue discovery with %d ADISCs to go "
+			"%d (%d):0210 Continue discovery with %d ADISCs to go "
 			"Data: x%x x%x x%x\n",
-			phba->brd_no, phba->num_disc_nodes, phba->fc_adisc_cnt,
-			phba->fc_flag, phba->hba_state);
+			phba->brd_no, vport->vpi, vport->num_disc_nodes,
+			vport->fc_adisc_cnt, vport->fc_flag, vport->port_state);
 
 	/* Check to see if there are more ADISCs to be sent */
-	if (phba->fc_flag & FC_NLP_MORE) {
-		lpfc_set_disctmo(phba);
-
-		/* go thru NPR list and issue any remaining ELS ADISCs */
-		sentadisc = lpfc_els_disc_adisc(phba);
+	if (vport->fc_flag & FC_NLP_MORE) {
+		lpfc_set_disctmo(vport);
+		/* go thru NPR nodes and issue any remaining ELS ADISCs */
+		sentadisc = lpfc_els_disc_adisc(vport);
 	}
 	return;
 }
 
 static void
-lpfc_rscn_disc(struct lpfc_hba * phba)
+lpfc_rscn_disc(struct lpfc_vport *vport)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	lpfc_can_disctmo(vport);
+
 	/* RSCN discovery */
-	/* go thru NPR list and issue ELS PLOGIs */
-	if (phba->fc_npr_cnt) {
-		if (lpfc_els_disc_plogi(phba))
+	/* go thru NPR nodes and issue ELS PLOGIs */
+	if (vport->fc_npr_cnt)
+		if (lpfc_els_disc_plogi(vport))
 			return;
-	}
-	if (phba->fc_flag & FC_RSCN_MODE) {
+
+	if (vport->fc_flag & FC_RSCN_MODE) {
 		/* Check to see if more RSCNs came in while we were
 		 * processing this one.
 		 */
-		if ((phba->fc_rscn_id_cnt == 0) &&
-		    (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
-			spin_lock_irq(phba->host->host_lock);
-			phba->fc_flag &= ~FC_RSCN_MODE;
-			spin_unlock_irq(phba->host->host_lock);
+		if ((vport->fc_rscn_id_cnt == 0) &&
+		    (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
+			spin_lock_irq(shost->host_lock);
+			vport->fc_flag &= ~FC_RSCN_MODE;
+			spin_unlock_irq(shost->host_lock);
 		} else {
-			lpfc_els_handle_rscn(phba);
+			lpfc_els_handle_rscn(vport);
 		}
 	}
 }
 
 static void
-lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		    struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		    struct lpfc_iocbq *rspiocb)
 {
+	struct lpfc_vport *vport = cmdiocb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
-	struct lpfc_sli *psli;
 	struct lpfc_nodelist *ndlp;
-	LPFC_MBOXQ_t *mbox;
-	int disc, rc;
-
-	psli = &phba->sli;
+	int  disc;
 
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
 	cmdiocb->context_un.rsp_iocb = rspiocb;
@@ -1037,27 +1194,32 @@
 	irsp = &(rspiocb->iocb);
 	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"ADISC cmpl:      status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4],
+		ndlp->nlp_DID);
+
 	/* Since ndlp can be freed in the disc state machine, note if this node
 	 * is being used during discovery.
 	 */
+	spin_lock_irq(shost->host_lock);
 	disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
-	spin_lock_irq(phba->host->host_lock);
 	ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 
 	/* ADISC completes to NPort <nlp_DID> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0104 ADISC completes to NPort x%x "
+			"%d (%d):0104 ADISC completes to NPort x%x "
 			"Data: x%x x%x x%x x%x x%x\n",
-			phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
-			irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
-			phba->num_disc_nodes);
+			phba->brd_no, vport->vpi, ndlp->nlp_DID,
+			irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
+			disc, vport->num_disc_nodes);
 
 	/* Check to see if link went down during discovery */
-	if (lpfc_els_chk_latt(phba)) {
-		spin_lock_irq(phba->host->host_lock);
+	if (lpfc_els_chk_latt(vport)) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		goto out;
 	}
 
@@ -1066,67 +1228,68 @@
 		if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
 			/* ELS command is being retried */
 			if (disc) {
-				spin_lock_irq(phba->host->host_lock);
+				spin_lock_irq(shost->host_lock);
 				ndlp->nlp_flag |= NLP_NPR_2B_DISC;
-				spin_unlock_irq(phba->host->host_lock);
-				lpfc_set_disctmo(phba);
+				spin_unlock_irq(shost->host_lock);
+				lpfc_set_disctmo(vport);
 			}
 			goto out;
 		}
 		/* ADISC failed */
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
-		if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
-		   ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
-		   (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
-		   (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
-			lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-					NLP_EVT_CMPL_ADISC);
+		if (!lpfc_error_lost_link(irsp)) {
+			lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+						NLP_EVT_CMPL_ADISC);
 		}
 	} else {
 		/* Good status, call state machine */
-		lpfc_disc_state_machine(phba, ndlp, cmdiocb,
+		lpfc_disc_state_machine(vport, ndlp, cmdiocb,
 					NLP_EVT_CMPL_ADISC);
 	}
 
-	if (disc && phba->num_disc_nodes) {
+	if (disc && vport->num_disc_nodes) {
 		/* Check to see if there are more ADISCs to be sent */
-		lpfc_more_adisc(phba);
+		lpfc_more_adisc(vport);
 
 		/* Check to see if we are done with ADISC authentication */
-		if (phba->num_disc_nodes == 0) {
-			lpfc_can_disctmo(phba);
-			/* If we get here, there is nothing left to wait for */
-			if ((phba->hba_state < LPFC_HBA_READY) &&
-			    (phba->hba_state != LPFC_CLEAR_LA)) {
-				/* Link up discovery */
-				if ((mbox = mempool_alloc(phba->mbox_mem_pool,
-							  GFP_KERNEL))) {
-					phba->hba_state = LPFC_CLEAR_LA;
-					lpfc_clear_la(phba, mbox);
-					mbox->mbox_cmpl =
-					    lpfc_mbx_cmpl_clear_la;
-					rc = lpfc_sli_issue_mbox
-						(phba, mbox,
-						 (MBX_NOWAIT | MBX_STOP_IOCB));
-					if (rc == MBX_NOT_FINISHED) {
-						mempool_free(mbox,
-						     phba->mbox_mem_pool);
-						lpfc_disc_flush_list(phba);
-						psli->ring[(psli->extra_ring)].
-						    flag &=
-						    ~LPFC_STOP_IOCB_EVENT;
-						psli->ring[(psli->fcp_ring)].
-						    flag &=
-						    ~LPFC_STOP_IOCB_EVENT;
-						psli->ring[(psli->next_ring)].
-						    flag &=
-						    ~LPFC_STOP_IOCB_EVENT;
-						phba->hba_state =
-						    LPFC_HBA_READY;
+		if (vport->num_disc_nodes == 0) {
+			/* If we get here, there is nothing left to ADISC */
+			/*
+			 * For NPIV, cmpl_reg_vpi will set port_state to READY,
+			 * and continue discovery.
+			 */
+			if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+			   !(vport->fc_flag & FC_RSCN_MODE)) {
+				lpfc_issue_reg_vpi(phba, vport);
+				goto out;
+			}
+			/*
+			 * For SLI2, we need to set port_state to READY
+			 * and continue discovery.
+			 */
+			if (vport->port_state < LPFC_VPORT_READY) {
+				/* If we get here, there is nothing to ADISC */
+				if (vport->port_type == LPFC_PHYSICAL_PORT)
+					lpfc_issue_clear_la(phba, vport);
+
+				if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
+					vport->num_disc_nodes = 0;
+					/* go thru NPR list, issue ELS PLOGIs */
+					if (vport->fc_npr_cnt)
+						lpfc_els_disc_plogi(vport);
+
+					if (!vport->num_disc_nodes) {
+						spin_lock_irq(shost->host_lock);
+						vport->fc_flag &=
+							~FC_NDISC_ACTIVE;
+						spin_unlock_irq(
+							shost->host_lock);
+						lpfc_can_disctmo(vport);
 					}
 				}
+				vport->port_state = LPFC_VPORT_READY;
 			} else {
-				lpfc_rscn_disc(phba);
+				lpfc_rscn_disc(vport);
 			}
 		}
 	}
@@ -1136,23 +1299,22 @@
 }
 
 int
-lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		     uint8_t retry)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	ADISC *ap;
 	IOCB_t *icmd;
 	struct lpfc_iocbq *elsiocb;
-	struct lpfc_sli_ring *pring;
-	struct lpfc_sli *psli;
+	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
 	uint8_t *pcmd;
 	uint16_t cmdsize;
 
-	psli = &phba->sli;
-	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
-
-	cmdsize = (sizeof (uint32_t) + sizeof (ADISC));
-	elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-						ndlp->nlp_DID, ELS_CMD_ADISC);
+	cmdsize = (sizeof(uint32_t) + sizeof(ADISC));
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_ADISC);
 	if (!elsiocb)
 		return 1;
 
@@ -1161,81 +1323,97 @@
 
 	/* For ADISC request, remainder of payload is service parameters */
 	*((uint32_t *) (pcmd)) = ELS_CMD_ADISC;
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 
 	/* Fill in ADISC payload */
 	ap = (ADISC *) pcmd;
 	ap->hardAL_PA = phba->fc_pref_ALPA;
-	memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
-	memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
-	ap->DID = be32_to_cpu(phba->fc_myDID);
+	memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
+	memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
+	ap->DID = be32_to_cpu(vport->fc_myDID);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue ADISC:     did:x%x",
+		ndlp->nlp_DID, 0, 0);
 
 	phba->fc_stat.elsXmitADISC++;
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= NLP_ADISC_SND;
+	spin_unlock_irq(shost->host_lock);
 	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_ADISC_SND;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
 	}
-	spin_unlock_irq(phba->host->host_lock);
 	return 0;
 }
 
 static void
-lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		   struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		   struct lpfc_iocbq *rspiocb)
 {
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+	struct lpfc_vport *vport = ndlp->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
 	struct lpfc_sli *psli;
-	struct lpfc_nodelist *ndlp;
 
 	psli = &phba->sli;
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
 	cmdiocb->context_un.rsp_iocb = rspiocb;
 
 	irsp = &(rspiocb->iocb);
-	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~NLP_LOGO_SND;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"LOGO cmpl:       status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4],
+		ndlp->nlp_DID);
 
 	/* LOGO completes to NPort <nlp_DID> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0105 LOGO completes to NPort x%x "
+			"%d (%d):0105 LOGO completes to NPort x%x "
 			"Data: x%x x%x x%x x%x\n",
-			phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
-			irsp->un.ulpWord[4], irsp->ulpTimeout,
-			phba->num_disc_nodes);
+			phba->brd_no, vport->vpi, ndlp->nlp_DID,
+			irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
+			vport->num_disc_nodes);
 
 	/* Check to see if link went down during discovery */
-	if (lpfc_els_chk_latt(phba))
+	if (lpfc_els_chk_latt(vport))
 		goto out;
 
+	if (ndlp->nlp_flag & NLP_TARGET_REMOVE) {
+	        /* NLP_EVT_DEVICE_RM should unregister the RPI
+		 * which should abort all outstanding IOs.
+		 */
+		lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+					NLP_EVT_DEVICE_RM);
+		goto out;
+	}
+
 	if (irsp->ulpStatus) {
 		/* Check for retry */
-		if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
+		if (lpfc_els_retry(phba, cmdiocb, rspiocb))
 			/* ELS command is being retried */
 			goto out;
-		}
 		/* LOGO failed */
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
-		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
-		   (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
-		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+		if (lpfc_error_lost_link(irsp))
 			goto out;
-		} else {
-			lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-					NLP_EVT_CMPL_LOGO);
-		}
+		else
+			lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+						NLP_EVT_CMPL_LOGO);
 	} else {
 		/* Good status, call state machine.
 		 * This will unregister the rpi if needed.
 		 */
-		lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);
+		lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+					NLP_EVT_CMPL_LOGO);
 	}
 
 out:
@@ -1244,75 +1422,91 @@
 }
 
 int
-lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		    uint8_t retry)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	IOCB_t *icmd;
 	struct lpfc_iocbq *elsiocb;
 	struct lpfc_sli_ring *pring;
 	struct lpfc_sli *psli;
 	uint8_t *pcmd;
 	uint16_t cmdsize;
+	int rc;
 
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];
 
-	cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
-	elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-						ndlp->nlp_DID, ELS_CMD_LOGO);
+	cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name);
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_LOGO);
 	if (!elsiocb)
 		return 1;
 
 	icmd = &elsiocb->iocb;
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 	*((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 
 	/* Fill in LOGO payload */
-	*((uint32_t *) (pcmd)) = be32_to_cpu(phba->fc_myDID);
-	pcmd += sizeof (uint32_t);
-	memcpy(pcmd, &phba->fc_portname, sizeof (struct lpfc_name));
+	*((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
+	pcmd += sizeof(uint32_t);
+	memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue LOGO:      did:x%x",
+		ndlp->nlp_DID, 0, 0);
 
 	phba->fc_stat.elsXmitLOGO++;
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= NLP_LOGO_SND;
-	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+	spin_unlock_irq(shost->host_lock);
+	rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
+
+	if (rc == IOCB_ERROR) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_LOGO_SND;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
 	}
-	spin_unlock_irq(phba->host->host_lock);
 	return 0;
 }
 
 static void
-lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		  struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		  struct lpfc_iocbq *rspiocb)
 {
+	struct lpfc_vport *vport = cmdiocb->vport;
 	IOCB_t *irsp;
 
 	irsp = &rspiocb->iocb;
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"ELS cmd cmpl:    status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4],
+		irsp->un.elsreq64.remoteID);
+
 	/* ELS cmd tag <ulpIoTag> completes */
-	lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_ELS,
-			"%d:0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
-			phba->brd_no,
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+			"%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x "
+			"x%x\n",
+			phba->brd_no, vport->vpi,
 			irsp->ulpIoTag, irsp->ulpStatus,
 			irsp->un.ulpWord[4], irsp->ulpTimeout);
 
 	/* Check to see if link went down during discovery */
-	lpfc_els_chk_latt(phba);
+	lpfc_els_chk_latt(vport);
 	lpfc_els_free_iocb(phba, cmdiocb);
 	return;
 }
 
 int
-lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
+lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	IOCB_t *icmd;
 	struct lpfc_iocbq *elsiocb;
 	struct lpfc_sli_ring *pring;
@@ -1323,15 +1517,16 @@
 
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
-	cmdsize = (sizeof (uint32_t) + sizeof (SCR));
+	cmdsize = (sizeof(uint32_t) + sizeof(SCR));
 	ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
 	if (!ndlp)
 		return 1;
 
-	lpfc_nlp_init(phba, ndlp, nportid);
+	lpfc_nlp_init(vport, ndlp, nportid);
 
-	elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-						ndlp->nlp_DID, ELS_CMD_SCR);
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_SCR);
+
 	if (!elsiocb) {
 		lpfc_nlp_put(ndlp);
 		return 1;
@@ -1341,29 +1536,31 @@
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
 	*((uint32_t *) (pcmd)) = ELS_CMD_SCR;
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 
 	/* For SCR, remainder of payload is SCR parameter page */
-	memset(pcmd, 0, sizeof (SCR));
+	memset(pcmd, 0, sizeof(SCR));
 	((SCR *) pcmd)->Function = SCR_FUNC_FULL;
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue SCR:       did:x%x",
+		ndlp->nlp_DID, 0, 0);
+
 	phba->fc_stat.elsXmitSCR++;
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
-	spin_lock_irq(phba->host->host_lock);
 	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-		spin_unlock_irq(phba->host->host_lock);
 		lpfc_nlp_put(ndlp);
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
 	}
-	spin_unlock_irq(phba->host->host_lock);
 	lpfc_nlp_put(ndlp);
 	return 0;
 }
 
 static int
-lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
+lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	IOCB_t *icmd;
 	struct lpfc_iocbq *elsiocb;
 	struct lpfc_sli_ring *pring;
@@ -1377,14 +1574,15 @@
 
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
-	cmdsize = (sizeof (uint32_t) + sizeof (FARP));
+	cmdsize = (sizeof(uint32_t) + sizeof(FARP));
 	ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
 	if (!ndlp)
 		return 1;
-	lpfc_nlp_init(phba, ndlp, nportid);
 
-	elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-						ndlp->nlp_DID, ELS_CMD_RNID);
+	lpfc_nlp_init(vport, ndlp, nportid);
+
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_RNID);
 	if (!elsiocb) {
 		lpfc_nlp_put(ndlp);
 		return 1;
@@ -1394,44 +1592,71 @@
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
 	*((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 
 	/* Fill in FARPR payload */
 	fp = (FARP *) (pcmd);
-	memset(fp, 0, sizeof (FARP));
+	memset(fp, 0, sizeof(FARP));
 	lp = (uint32_t *) pcmd;
 	*lp++ = be32_to_cpu(nportid);
-	*lp++ = be32_to_cpu(phba->fc_myDID);
+	*lp++ = be32_to_cpu(vport->fc_myDID);
 	fp->Rflags = 0;
 	fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);
 
-	memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name));
-	memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
-	if ((ondlp = lpfc_findnode_did(phba, nportid))) {
+	memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name));
+	memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
+	ondlp = lpfc_findnode_did(vport, nportid);
+	if (ondlp) {
 		memcpy(&fp->OportName, &ondlp->nlp_portname,
-		       sizeof (struct lpfc_name));
+		       sizeof(struct lpfc_name));
 		memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
-		       sizeof (struct lpfc_name));
+		       sizeof(struct lpfc_name));
 	}
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue FARPR:     did:x%x",
+		ndlp->nlp_DID, 0, 0);
+
 	phba->fc_stat.elsXmitFARPR++;
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
-	spin_lock_irq(phba->host->host_lock);
 	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-		spin_unlock_irq(phba->host->host_lock);
 		lpfc_nlp_put(ndlp);
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
 	}
-	spin_unlock_irq(phba->host->host_lock);
 	lpfc_nlp_put(ndlp);
 	return 0;
 }
 
-void
-lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
+static void
+lpfc_end_rscn(struct lpfc_vport *vport)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	if (vport->fc_flag & FC_RSCN_MODE) {
+		/*
+		 * Check to see if more RSCNs came in while we were
+		 * processing this one.
+		 */
+		if (vport->fc_rscn_id_cnt ||
+		    (vport->fc_flag & FC_RSCN_DISCOVERY) != 0)
+			lpfc_els_handle_rscn(vport);
+		else {
+			spin_lock_irq(shost->host_lock);
+			vport->fc_flag &= ~FC_RSCN_MODE;
+			spin_unlock_irq(shost->host_lock);
+		}
+	}
+}
+
+void
+lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	spin_lock_irq(shost->host_lock);
 	nlp->nlp_flag &= ~NLP_DELAY_TMO;
+	spin_unlock_irq(shost->host_lock);
 	del_timer_sync(&nlp->nlp_delayfunc);
 	nlp->nlp_last_elscmd = 0;
 
@@ -1439,30 +1664,21 @@
 		list_del_init(&nlp->els_retry_evt.evt_listp);
 
 	if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
+		spin_lock_irq(shost->host_lock);
 		nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
-		if (phba->num_disc_nodes) {
+		spin_unlock_irq(shost->host_lock);
+		if (vport->num_disc_nodes) {
 			/* Check to see if there are more
 			 * PLOGIs to be sent
 			 */
-			lpfc_more_plogi(phba);
+			lpfc_more_plogi(vport);
 
-			if (phba->num_disc_nodes == 0) {
-				phba->fc_flag &= ~FC_NDISC_ACTIVE;
-				lpfc_can_disctmo(phba);
-				if (phba->fc_flag & FC_RSCN_MODE) {
-					/*
-					 * Check to see if more RSCNs
-					 * came in while we were
-					 * processing this one.
-					 */
-					if((phba->fc_rscn_id_cnt==0) &&
-					 !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
-						phba->fc_flag &= ~FC_RSCN_MODE;
-					}
-					else {
-						lpfc_els_handle_rscn(phba);
-					}
-				}
+			if (vport->num_disc_nodes == 0) {
+				spin_lock_irq(shost->host_lock);
+				vport->fc_flag &= ~FC_NDISC_ACTIVE;
+				spin_unlock_irq(shost->host_lock);
+				lpfc_can_disctmo(vport);
+				lpfc_end_rscn(vport);
 			}
 		}
 	}
@@ -1472,18 +1688,19 @@
 void
 lpfc_els_retry_delay(unsigned long ptr)
 {
-	struct lpfc_nodelist *ndlp;
-	struct lpfc_hba *phba;
-	unsigned long iflag;
-	struct lpfc_work_evt  *evtp;
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr;
+	struct lpfc_vport *vport = ndlp->vport;
+	struct lpfc_hba   *phba = vport->phba;
+	unsigned long flags;
+	struct lpfc_work_evt  *evtp = &ndlp->els_retry_evt;
 
-	ndlp = (struct lpfc_nodelist *)ptr;
-	phba = ndlp->nlp_phba;
+	ndlp = (struct lpfc_nodelist *) ptr;
+	phba = ndlp->vport->phba;
 	evtp = &ndlp->els_retry_evt;
 
-	spin_lock_irqsave(phba->host->host_lock, iflag);
+	spin_lock_irqsave(&phba->hbalock, flags);
 	if (!list_empty(&evtp->evt_listp)) {
-		spin_unlock_irqrestore(phba->host->host_lock, iflag);
+		spin_unlock_irqrestore(&phba->hbalock, flags);
 		return;
 	}
 
@@ -1491,33 +1708,31 @@
 	evtp->evt       = LPFC_EVT_ELS_RETRY;
 	list_add_tail(&evtp->evt_listp, &phba->work_list);
 	if (phba->work_wait)
-		wake_up(phba->work_wait);
+		lpfc_worker_wake_up(phba);
 
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+	spin_unlock_irqrestore(&phba->hbalock, flags);
 	return;
 }
 
 void
 lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
 {
-	struct lpfc_hba *phba;
-	uint32_t cmd;
-	uint32_t did;
-	uint8_t retry;
+	struct lpfc_vport *vport = ndlp->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	uint32_t cmd, did, retry;
 
-	phba = ndlp->nlp_phba;
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	did = ndlp->nlp_DID;
 	cmd = ndlp->nlp_last_elscmd;
 	ndlp->nlp_last_elscmd = 0;
 
 	if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		return;
 	}
 
 	ndlp->nlp_flag &= ~NLP_DELAY_TMO;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 	/*
 	 * If a discovery event readded nlp_delayfunc after timer
 	 * firing and before processing the timer, cancel the
@@ -1528,57 +1743,54 @@
 
 	switch (cmd) {
 	case ELS_CMD_FLOGI:
-		lpfc_issue_els_flogi(phba, ndlp, retry);
+		lpfc_issue_els_flogi(vport, ndlp, retry);
 		break;
 	case ELS_CMD_PLOGI:
-		if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) {
+		if (!lpfc_issue_els_plogi(vport, ndlp->nlp_DID, retry)) {
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
 		}
 		break;
 	case ELS_CMD_ADISC:
-		if (!lpfc_issue_els_adisc(phba, ndlp, retry)) {
+		if (!lpfc_issue_els_adisc(vport, ndlp, retry)) {
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
 		}
 		break;
 	case ELS_CMD_PRLI:
-		if (!lpfc_issue_els_prli(phba, ndlp, retry)) {
+		if (!lpfc_issue_els_prli(vport, ndlp, retry)) {
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
 		}
 		break;
 	case ELS_CMD_LOGO:
-		if (!lpfc_issue_els_logo(phba, ndlp, retry)) {
+		if (!lpfc_issue_els_logo(vport, ndlp, retry)) {
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 		}
 		break;
+	case ELS_CMD_FDISC:
+		lpfc_issue_els_fdisc(vport, ndlp, retry);
+		break;
 	}
 	return;
 }
 
 static int
-lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-	       struct lpfc_iocbq * rspiocb)
+lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+	       struct lpfc_iocbq *rspiocb)
 {
-	IOCB_t *irsp;
-	struct lpfc_dmabuf *pcmd;
-	struct lpfc_nodelist *ndlp;
+	struct lpfc_vport *vport = cmdiocb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	IOCB_t *irsp = &rspiocb->iocb;
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+	struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
 	uint32_t *elscmd;
 	struct ls_rjt stat;
-	int retry, maxretry;
-	int delay;
-	uint32_t cmd;
+	int retry = 0, maxretry = lpfc_max_els_tries, delay = 0;
+	uint32_t cmd = 0;
 	uint32_t did;
 
-	retry = 0;
-	delay = 0;
-	maxretry = lpfc_max_els_tries;
-	irsp = &rspiocb->iocb;
-	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-	cmd = 0;
 
 	/* Note: context2 may be 0 for internal driver abort
 	 * of delays ELS command.
@@ -1594,11 +1806,15 @@
 	else {
 		/* We should only hit this case for retrying PLOGI */
 		did = irsp->un.elsreq64.remoteID;
-		ndlp = lpfc_findnode_did(phba, did);
+		ndlp = lpfc_findnode_did(vport, did);
 		if (!ndlp && (cmd != ELS_CMD_PLOGI))
 			return 1;
 	}
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Retry ELS:       wd7:x%x wd4:x%x did:x%x",
+		*(((uint32_t *) irsp) + 7), irsp->un.ulpWord[4], ndlp->nlp_DID);
+
 	switch (irsp->ulpStatus) {
 	case IOSTAT_FCP_RSP_ERROR:
 	case IOSTAT_REMOTE_STOP:
@@ -1607,25 +1823,37 @@
 	case IOSTAT_LOCAL_REJECT:
 		switch ((irsp->un.ulpWord[4] & 0xff)) {
 		case IOERR_LOOP_OPEN_FAILURE:
-			if (cmd == ELS_CMD_PLOGI) {
-				if (cmdiocb->retry == 0) {
-					delay = 1;
-				}
+			if (cmd == ELS_CMD_PLOGI && cmdiocb->retry == 0)
+				delay = 1000;
+			retry = 1;
+			break;
+
+		case IOERR_ILLEGAL_COMMAND:
+			if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) &&
+			    (cmd == ELS_CMD_FDISC)) {
+				lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+				"%d (%d):0124 FDISC failed (3/6) retrying...\n",
+					phba->brd_no, vport->vpi);
+				lpfc_mbx_unreg_vpi(vport);
+				retry = 1;
+				/* Always retry for this case */
+				cmdiocb->retry = 0;
 			}
+			break;
+
+		case IOERR_NO_RESOURCES:
+			retry = 1;
+			if (cmdiocb->retry > 100)
+				delay = 100;
+			maxretry = 250;
+			break;
+
+		case IOERR_ILLEGAL_FRAME:
+			delay = 100;
 			retry = 1;
 			break;
 
 		case IOERR_SEQUENCE_TIMEOUT:
-			retry = 1;
-			break;
-
-		case IOERR_NO_RESOURCES:
-			if (cmd == ELS_CMD_PLOGI) {
-				delay = 1;
-			}
-			retry = 1;
-			break;
-
 		case IOERR_INVALID_RPI:
 			retry = 1;
 			break;
@@ -1655,27 +1883,57 @@
 			if (stat.un.b.lsRjtRsnCodeExp ==
 			    LSEXP_CMD_IN_PROGRESS) {
 				if (cmd == ELS_CMD_PLOGI) {
-					delay = 1;
+					delay = 1000;
 					maxretry = 48;
 				}
 				retry = 1;
 				break;
 			}
 			if (cmd == ELS_CMD_PLOGI) {
-				delay = 1;
+				delay = 1000;
 				maxretry = lpfc_max_els_tries + 1;
 				retry = 1;
 				break;
 			}
+			if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+			  (cmd == ELS_CMD_FDISC) &&
+			  (stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
+				lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+				"%d (%d):0125 FDISC Failed (x%x)."
+				" Fabric out of resources\n",
+				phba->brd_no, vport->vpi, stat.un.lsRjtError);
+				lpfc_vport_set_state(vport,
+						     FC_VPORT_NO_FABRIC_RSCS);
+			}
 			break;
 
 		case LSRJT_LOGICAL_BSY:
-			if (cmd == ELS_CMD_PLOGI) {
-				delay = 1;
+			if ((cmd == ELS_CMD_PLOGI) ||
+			    (cmd == ELS_CMD_PRLI)) {
+				delay = 1000;
 				maxretry = 48;
+			} else if (cmd == ELS_CMD_FDISC) {
+				/* Always retry for this case */
+				cmdiocb->retry = 0;
 			}
 			retry = 1;
 			break;
+
+		case LSRJT_LOGICAL_ERR:
+		case LSRJT_PROTOCOL_ERR:
+			if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+			  (cmd == ELS_CMD_FDISC) &&
+			  ((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) ||
+			  (stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
+			  ) {
+				lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+				"%d (%d):0123 FDISC Failed (x%x)."
+				" Fabric Detected Bad WWN\n",
+				phba->brd_no, vport->vpi, stat.un.lsRjtError);
+				lpfc_vport_set_state(vport,
+						     FC_VPORT_FABRIC_REJ_WWN);
+			}
+			break;
 		}
 		break;
 
@@ -1695,21 +1953,27 @@
 		retry = 0;
 	}
 
+	if ((vport->load_flag & FC_UNLOADING) != 0)
+		retry = 0;
+
 	if (retry) {
 
 		/* Retry ELS command <elsCmd> to remote NPORT <did> */
 		lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-				"%d:0107 Retry ELS command x%x to remote "
+				"%d (%d):0107 Retry ELS command x%x to remote "
 				"NPORT x%x Data: x%x x%x\n",
-				phba->brd_no,
+				phba->brd_no, vport->vpi,
 				cmd, did, cmdiocb->retry, delay);
 
-		if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
+		if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) &&
+			((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
+			((irsp->un.ulpWord[4] & 0xff) != IOERR_NO_RESOURCES))) {
+			/* Don't reset timer for no resources */
+
 			/* If discovery / RSCN timer is running, reset it */
-			if (timer_pending(&phba->fc_disctmo) ||
-			      (phba->fc_flag & FC_RSCN_MODE)) {
-				lpfc_set_disctmo(phba);
-			}
+			if (timer_pending(&vport->fc_disctmo) ||
+			    (vport->fc_flag & FC_RSCN_MODE))
+				lpfc_set_disctmo(vport);
 		}
 
 		phba->fc_stat.elsXmitRetry++;
@@ -1717,50 +1981,62 @@
 			phba->fc_stat.elsDelayRetry++;
 			ndlp->nlp_retry = cmdiocb->retry;
 
-			mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+			/* delay is specified in milliseconds */
+			mod_timer(&ndlp->nlp_delayfunc,
+				jiffies + msecs_to_jiffies(delay));
+			spin_lock_irq(shost->host_lock);
 			ndlp->nlp_flag |= NLP_DELAY_TMO;
+			spin_unlock_irq(shost->host_lock);
 
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+			if (cmd == ELS_CMD_PRLI)
+				lpfc_nlp_set_state(vport, ndlp,
+					NLP_STE_REG_LOGIN_ISSUE);
+			else
+				lpfc_nlp_set_state(vport, ndlp,
+					NLP_STE_NPR_NODE);
 			ndlp->nlp_last_elscmd = cmd;
 
 			return 1;
 		}
 		switch (cmd) {
 		case ELS_CMD_FLOGI:
-			lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry);
+			lpfc_issue_els_flogi(vport, ndlp, cmdiocb->retry);
+			return 1;
+		case ELS_CMD_FDISC:
+			lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry);
 			return 1;
 		case ELS_CMD_PLOGI:
 			if (ndlp) {
 				ndlp->nlp_prev_state = ndlp->nlp_state;
-				lpfc_nlp_set_state(phba, ndlp,
+				lpfc_nlp_set_state(vport, ndlp,
 						   NLP_STE_PLOGI_ISSUE);
 			}
-			lpfc_issue_els_plogi(phba, did, cmdiocb->retry);
+			lpfc_issue_els_plogi(vport, did, cmdiocb->retry);
 			return 1;
 		case ELS_CMD_ADISC:
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
-			lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+			lpfc_issue_els_adisc(vport, ndlp, cmdiocb->retry);
 			return 1;
 		case ELS_CMD_PRLI:
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
-			lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
+			lpfc_issue_els_prli(vport, ndlp, cmdiocb->retry);
 			return 1;
 		case ELS_CMD_LOGO:
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-			lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+			lpfc_issue_els_logo(vport, ndlp, cmdiocb->retry);
 			return 1;
 		}
 	}
 
 	/* No retry ELS command <elsCmd> to remote NPORT <did> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0108 No retry ELS command x%x to remote NPORT x%x "
-			"Data: x%x\n",
-			phba->brd_no,
+			"%d (%d):0108 No retry ELS command x%x to remote "
+			"NPORT x%x Data: x%x\n",
+			phba->brd_no, vport->vpi,
 			cmd, did, cmdiocb->retry);
 
 	return 0;
@@ -1795,33 +2071,36 @@
 		lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
 		kfree(buf_ptr);
 	}
-	spin_lock_irq(phba->host->host_lock);
 	lpfc_sli_release_iocbq(phba, elsiocb);
-	spin_unlock_irq(phba->host->host_lock);
 	return 0;
 }
 
 static void
-lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		       struct lpfc_iocbq * rspiocb)
+lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		       struct lpfc_iocbq *rspiocb)
 {
-	struct lpfc_nodelist *ndlp;
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+	struct lpfc_vport *vport = cmdiocb->vport;
+	IOCB_t *irsp;
 
-	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+	irsp = &rspiocb->iocb;
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+		"ACC LOGO cmpl:   status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID);
 
 	/* ACC to LOGO completes to NPort <nlp_DID> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0109 ACC to LOGO completes to NPort x%x "
+			"%d (%d):0109 ACC to LOGO completes to NPort x%x "
 			"Data: x%x x%x x%x\n",
-			phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
-			ndlp->nlp_state, ndlp->nlp_rpi);
+			phba->brd_no, vport->vpi, ndlp->nlp_DID,
+			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
 	switch (ndlp->nlp_state) {
 	case NLP_STE_UNUSED_NODE:	/* node is just allocated */
-		lpfc_drop_node(phba, ndlp);
+		lpfc_drop_node(vport, ndlp);
 		break;
 	case NLP_STE_NPR_NODE:		/* NPort Recovery mode */
-		lpfc_unreg_rpi(phba, ndlp);
+		lpfc_unreg_rpi(vport, ndlp);
 		break;
 	default:
 		break;
@@ -1830,24 +2109,38 @@
 	return;
 }
 
+void
+lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+{
+	struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+
+	pmb->context1 = NULL;
+	lpfc_mbuf_free(phba, mp->virt, mp->phys);
+	kfree(mp);
+	mempool_free(pmb, phba->mbox_mem_pool);
+	lpfc_nlp_put(ndlp);
+	return;
+}
+
 static void
-lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 		  struct lpfc_iocbq *rspiocb)
 {
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+	struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL;
+	struct Scsi_Host  *shost = vport ? lpfc_shost_from_vport(vport) : NULL;
 	IOCB_t *irsp;
-	struct lpfc_nodelist *ndlp;
 	LPFC_MBOXQ_t *mbox = NULL;
-	struct lpfc_dmabuf *mp;
+	struct lpfc_dmabuf *mp = NULL;
 
 	irsp = &rspiocb->iocb;
 
-	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
 	if (cmdiocb->context_un.mbox)
 		mbox = cmdiocb->context_un.mbox;
 
-
 	/* Check to see if link went down during discovery */
-	if (lpfc_els_chk_latt(phba) || !ndlp) {
+	if (!ndlp || lpfc_els_chk_latt(vport)) {
 		if (mbox) {
 			mp = (struct lpfc_dmabuf *) mbox->context1;
 			if (mp) {
@@ -1859,24 +2152,37 @@
 		goto out;
 	}
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+		"ACC cmpl:        status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4],
+		irsp->un.rcvels.remoteID);
+
 	/* ELS response tag <ulpIoTag> completes */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0110 ELS response tag x%x completes "
+			"%d (%d):0110 ELS response tag x%x completes "
 			"Data: x%x x%x x%x x%x x%x x%x x%x\n",
-			phba->brd_no,
+			phba->brd_no, vport->vpi,
 			cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
 			rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
- 			ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+			ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
 			ndlp->nlp_rpi);
 
 	if (mbox) {
 		if ((rspiocb->iocb.ulpStatus == 0)
 		    && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
-			lpfc_unreg_rpi(phba, ndlp);
-			mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
+			lpfc_unreg_rpi(vport, ndlp);
 			mbox->context2 = lpfc_nlp_get(ndlp);
-			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
+			mbox->vport = vport;
+			if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) {
+				mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
+				mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
+			}
+			else {
+				mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
+				ndlp->nlp_prev_state = ndlp->nlp_state;
+				lpfc_nlp_set_state(vport, ndlp,
+					   NLP_STE_REG_LOGIN_ISSUE);
+			}
 			if (lpfc_sli_issue_mbox(phba, mbox,
 						(MBX_NOWAIT | MBX_STOP_IOCB))
 			    != MBX_NOT_FINISHED) {
@@ -1886,15 +2192,11 @@
 			/* NOTE: we should have messages for unsuccessful
 			   reglogin */
 		} else {
-			/* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
-			if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-			      ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
-			       (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
-			       (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
-				if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
-					lpfc_drop_node(phba, ndlp);
-					ndlp = NULL;
-				}
+			/* Do not drop node for lpfc_els_abort'ed ELS cmds */
+			if (!lpfc_error_lost_link(irsp) &&
+			    ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
+				lpfc_drop_node(vport, ndlp);
+				ndlp = NULL;
 			}
 		}
 		mp = (struct lpfc_dmabuf *) mbox->context1;
@@ -1906,19 +2208,21 @@
 	}
 out:
 	if (ndlp) {
-		spin_lock_irq(phba->host->host_lock);
-		ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
+		ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
+		spin_unlock_irq(shost->host_lock);
 	}
 	lpfc_els_free_iocb(phba, cmdiocb);
 	return;
 }
 
 int
-lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
-		 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp,
-		 LPFC_MBOXQ_t * mbox, uint8_t newnode)
+lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
+		 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
+		 LPFC_MBOXQ_t *mbox, uint8_t newnode)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	IOCB_t *icmd;
 	IOCB_t *oldcmd;
 	struct lpfc_iocbq *elsiocb;
@@ -1935,23 +2239,30 @@
 
 	switch (flag) {
 	case ELS_CMD_ACC:
-		cmdsize = sizeof (uint32_t);
-		elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-					ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+		cmdsize = sizeof(uint32_t);
+		elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
+					     ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
 		if (!elsiocb) {
+			spin_lock_irq(shost->host_lock);
 			ndlp->nlp_flag &= ~NLP_LOGO_ACC;
+			spin_unlock_irq(shost->host_lock);
 			return 1;
 		}
+
 		icmd = &elsiocb->iocb;
 		icmd->ulpContext = oldcmd->ulpContext;	/* Xri */
 		pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 		*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
-		pcmd += sizeof (uint32_t);
+		pcmd += sizeof(uint32_t);
+
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+			"Issue ACC:       did:x%x flg:x%x",
+			ndlp->nlp_DID, ndlp->nlp_flag, 0);
 		break;
 	case ELS_CMD_PLOGI:
-		cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t));
-		elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-					ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+		cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
+		elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
+					     ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
 		if (!elsiocb)
 			return 1;
 
@@ -1963,12 +2274,16 @@
 			elsiocb->context_un.mbox = mbox;
 
 		*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
-		pcmd += sizeof (uint32_t);
-		memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
+		pcmd += sizeof(uint32_t);
+		memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
+
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+			"Issue ACC PLOGI: did:x%x flg:x%x",
+			ndlp->nlp_DID, ndlp->nlp_flag, 0);
 		break;
 	case ELS_CMD_PRLO:
-		cmdsize = sizeof (uint32_t) + sizeof (PRLO);
-		elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
+		cmdsize = sizeof(uint32_t) + sizeof(PRLO);
+		elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
 					     ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
 		if (!elsiocb)
 			return 1;
@@ -1978,10 +2293,14 @@
 		pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
 		memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
-		       sizeof (uint32_t) + sizeof (PRLO));
+		       sizeof(uint32_t) + sizeof(PRLO));
 		*((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
 		els_pkt_ptr = (ELS_PKT *) pcmd;
 		els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
+
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+			"Issue ACC PRLO:  did:x%x flg:x%x",
+			ndlp->nlp_DID, ndlp->nlp_flag, 0);
 		break;
 	default:
 		return 1;
@@ -1994,25 +2313,23 @@
 
 	/* Xmit ELS ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
+			"%d (%d):0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
 			"DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
-			phba->brd_no, elsiocb->iotag,
+			phba->brd_no, vport->vpi, elsiocb->iotag,
 			elsiocb->iocb.ulpContext, ndlp->nlp_DID,
 			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
 	if (ndlp->nlp_flag & NLP_LOGO_ACC) {
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_LOGO_ACC;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
 	} else {
-		elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+		elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
 	}
 
 	phba->fc_stat.elsXmitACC++;
-	spin_lock_irq(phba->host->host_lock);
 	rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
-	spin_unlock_irq(phba->host->host_lock);
 	if (rc == IOCB_ERROR) {
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
@@ -2021,9 +2338,11 @@
 }
 
 int
-lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError,
-		    struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
+lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
+		    struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
+		    LPFC_MBOXQ_t *mbox)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	IOCB_t *icmd;
 	IOCB_t *oldcmd;
 	struct lpfc_iocbq *elsiocb;
@@ -2036,9 +2355,9 @@
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
 
-	cmdsize = 2 * sizeof (uint32_t);
-	elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-					ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT);
+	cmdsize = 2 * sizeof(uint32_t);
+	elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_LS_RJT);
 	if (!elsiocb)
 		return 1;
 
@@ -2048,22 +2367,30 @@
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
 	*((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 	*((uint32_t *) (pcmd)) = rejectError;
 
+	if (mbox) {
+		elsiocb->context_un.mbox = mbox;
+		elsiocb->context1 = lpfc_nlp_get(ndlp);
+	}
+
 	/* Xmit ELS RJT <err> response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0129 Xmit ELS RJT x%x response tag x%x xri x%x, "
-			"did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
-			phba->brd_no, rejectError, elsiocb->iotag,
+			"%d (%d):0129 Xmit ELS RJT x%x response tag x%x "
+			"xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+			"rpi x%x\n",
+			phba->brd_no, vport->vpi, rejectError, elsiocb->iotag,
 			elsiocb->iocb.ulpContext, ndlp->nlp_DID,
 			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+		"Issue LS_RJT:    did:x%x flg:x%x err:x%x",
+		ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
+
 	phba->fc_stat.elsXmitLSRJT++;
-	elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
-	spin_lock_irq(phba->host->host_lock);
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
 	rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
-	spin_unlock_irq(phba->host->host_lock);
 	if (rc == IOCB_ERROR) {
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
@@ -2072,25 +2399,22 @@
 }
 
 int
-lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba,
-		       struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
+lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
+		       struct lpfc_nodelist *ndlp)
 {
+	struct lpfc_hba  *phba = vport->phba;
+	struct lpfc_sli  *psli = &phba->sli;
+	struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
 	ADISC *ap;
-	IOCB_t *icmd;
-	IOCB_t *oldcmd;
+	IOCB_t *icmd, *oldcmd;
 	struct lpfc_iocbq *elsiocb;
-	struct lpfc_sli_ring *pring;
-	struct lpfc_sli *psli;
 	uint8_t *pcmd;
 	uint16_t cmdsize;
 	int rc;
 
-	psli = &phba->sli;
-	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
-
-	cmdsize = sizeof (uint32_t) + sizeof (ADISC);
-	elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-					ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+	cmdsize = sizeof(uint32_t) + sizeof(ADISC);
+	elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_ACC);
 	if (!elsiocb)
 		return 1;
 
@@ -2100,28 +2424,30 @@
 
 	/* Xmit ADISC ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0130 Xmit ADISC ACC response iotag x%x xri: "
+			"%d (%d):0130 Xmit ADISC ACC response iotag x%x xri: "
 			"x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
-			phba->brd_no, elsiocb->iotag,
+			phba->brd_no, vport->vpi, elsiocb->iotag,
 			elsiocb->iocb.ulpContext, ndlp->nlp_DID,
 			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
 	*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 
 	ap = (ADISC *) (pcmd);
 	ap->hardAL_PA = phba->fc_pref_ALPA;
-	memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
-	memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
-	ap->DID = be32_to_cpu(phba->fc_myDID);
+	memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
+	memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
+	ap->DID = be32_to_cpu(vport->fc_myDID);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+		"Issue ACC ADISC: did:x%x flg:x%x",
+		ndlp->nlp_DID, ndlp->nlp_flag, 0);
 
 	phba->fc_stat.elsXmitACC++;
-	elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
-	spin_lock_irq(phba->host->host_lock);
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
 	rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
-	spin_unlock_irq(phba->host->host_lock);
 	if (rc == IOCB_ERROR) {
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
@@ -2130,9 +2456,10 @@
 }
 
 int
-lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb,
+lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
 		      struct lpfc_nodelist *ndlp)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	PRLI *npr;
 	lpfc_vpd_t *vpd;
 	IOCB_t *icmd;
@@ -2147,8 +2474,8 @@
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
 
-	cmdsize = sizeof (uint32_t) + sizeof (PRLI);
-	elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp,
+	cmdsize = sizeof(uint32_t) + sizeof(PRLI);
+	elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
 		ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
 	if (!elsiocb)
 		return 1;
@@ -2159,19 +2486,19 @@
 
 	/* Xmit PRLI ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0131 Xmit PRLI ACC response tag x%x xri x%x, "
+			"%d (%d):0131 Xmit PRLI ACC response tag x%x xri x%x, "
 			"did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
-			phba->brd_no, elsiocb->iotag,
+			phba->brd_no, vport->vpi, elsiocb->iotag,
 			elsiocb->iocb.ulpContext, ndlp->nlp_DID,
 			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
 	*((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 
 	/* For PRLI, remainder of payload is PRLI parameter page */
-	memset(pcmd, 0, sizeof (PRLI));
+	memset(pcmd, 0, sizeof(PRLI));
 
 	npr = (PRLI *) pcmd;
 	vpd = &phba->vpd;
@@ -2193,12 +2520,14 @@
 	npr->prliType = PRLI_FCP_TYPE;
 	npr->initiatorFunc = 1;
 
-	phba->fc_stat.elsXmitACC++;
-	elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+		"Issue ACC PRLI:  did:x%x flg:x%x",
+		ndlp->nlp_DID, ndlp->nlp_flag, 0);
 
-	spin_lock_irq(phba->host->host_lock);
+	phba->fc_stat.elsXmitACC++;
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
+
 	rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
-	spin_unlock_irq(phba->host->host_lock);
 	if (rc == IOCB_ERROR) {
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
@@ -2207,12 +2536,12 @@
 }
 
 static int
-lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format,
+lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
 		      struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	RNID *rn;
-	IOCB_t *icmd;
-	IOCB_t *oldcmd;
+	IOCB_t *icmd, *oldcmd;
 	struct lpfc_iocbq *elsiocb;
 	struct lpfc_sli_ring *pring;
 	struct lpfc_sli *psli;
@@ -2223,13 +2552,13 @@
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];
 
-	cmdsize = sizeof (uint32_t) + sizeof (uint32_t)
-		+ (2 * sizeof (struct lpfc_name));
+	cmdsize = sizeof(uint32_t) + sizeof(uint32_t)
+					+ (2 * sizeof(struct lpfc_name));
 	if (format)
-		cmdsize += sizeof (RNID_TOP_DISC);
+		cmdsize += sizeof(RNID_TOP_DISC);
 
-	elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-					ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+	elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_ACC);
 	if (!elsiocb)
 		return 1;
 
@@ -2239,30 +2568,30 @@
 
 	/* Xmit RNID ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0132 Xmit RNID ACC response tag x%x "
+			"%d (%d):0132 Xmit RNID ACC response tag x%x "
 			"xri x%x\n",
-			phba->brd_no, elsiocb->iotag,
+			phba->brd_no, vport->vpi, elsiocb->iotag,
 			elsiocb->iocb.ulpContext);
 
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 
 	*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
-	pcmd += sizeof (uint32_t);
+	pcmd += sizeof(uint32_t);
 
-	memset(pcmd, 0, sizeof (RNID));
+	memset(pcmd, 0, sizeof(RNID));
 	rn = (RNID *) (pcmd);
 	rn->Format = format;
-	rn->CommonLen = (2 * sizeof (struct lpfc_name));
-	memcpy(&rn->portName, &phba->fc_portname, sizeof (struct lpfc_name));
-	memcpy(&rn->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
+	rn->CommonLen = (2 * sizeof(struct lpfc_name));
+	memcpy(&rn->portName, &vport->fc_portname, sizeof(struct lpfc_name));
+	memcpy(&rn->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
 	switch (format) {
 	case 0:
 		rn->SpecificLen = 0;
 		break;
 	case RNID_TOPOLOGY_DISC:
-		rn->SpecificLen = sizeof (RNID_TOP_DISC);
+		rn->SpecificLen = sizeof(RNID_TOP_DISC);
 		memcpy(&rn->un.topologyDisc.portName,
-		       &phba->fc_portname, sizeof (struct lpfc_name));
+		       &vport->fc_portname, sizeof(struct lpfc_name));
 		rn->un.topologyDisc.unitType = RNID_HBA;
 		rn->un.topologyDisc.physPort = 0;
 		rn->un.topologyDisc.attachedNodes = 0;
@@ -2273,15 +2602,17 @@
 		break;
 	}
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+		"Issue ACC RNID:  did:x%x flg:x%x",
+		ndlp->nlp_DID, ndlp->nlp_flag, 0);
+
 	phba->fc_stat.elsXmitACC++;
-	elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
 	lpfc_nlp_put(ndlp);
 	elsiocb->context1 = NULL;  /* Don't need ndlp for cmpl,
 				    * it could be freed */
 
-	spin_lock_irq(phba->host->host_lock);
 	rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
-	spin_unlock_irq(phba->host->host_lock);
 	if (rc == IOCB_ERROR) {
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
@@ -2290,168 +2621,153 @@
 }
 
 int
-lpfc_els_disc_adisc(struct lpfc_hba *phba)
+lpfc_els_disc_adisc(struct lpfc_vport *vport)
 {
-	int sentadisc;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_nodelist *ndlp, *next_ndlp;
+	int sentadisc = 0;
 
-	sentadisc = 0;
 	/* go thru NPR nodes and issue any remaining ELS ADISCs */
-	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
 		if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
 		    (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
 		    (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) {
-			spin_lock_irq(phba->host->host_lock);
+			spin_lock_irq(shost->host_lock);
 			ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-			spin_unlock_irq(phba->host->host_lock);
+			spin_unlock_irq(shost->host_lock);
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
-			lpfc_issue_els_adisc(phba, ndlp, 0);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+			lpfc_issue_els_adisc(vport, ndlp, 0);
 			sentadisc++;
-			phba->num_disc_nodes++;
-			if (phba->num_disc_nodes >=
-			    phba->cfg_discovery_threads) {
-				spin_lock_irq(phba->host->host_lock);
-				phba->fc_flag |= FC_NLP_MORE;
-				spin_unlock_irq(phba->host->host_lock);
+			vport->num_disc_nodes++;
+			if (vport->num_disc_nodes >=
+			    vport->phba->cfg_discovery_threads) {
+				spin_lock_irq(shost->host_lock);
+				vport->fc_flag |= FC_NLP_MORE;
+				spin_unlock_irq(shost->host_lock);
 				break;
 			}
 		}
 	}
 	if (sentadisc == 0) {
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag &= ~FC_NLP_MORE;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag &= ~FC_NLP_MORE;
+		spin_unlock_irq(shost->host_lock);
 	}
 	return sentadisc;
 }
 
 int
-lpfc_els_disc_plogi(struct lpfc_hba * phba)
+lpfc_els_disc_plogi(struct lpfc_vport *vport)
 {
-	int sentplogi;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_nodelist *ndlp, *next_ndlp;
+	int sentplogi = 0;
 
-	sentplogi = 0;
-	/* go thru NPR list and issue any remaining ELS PLOGIs */
-	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+	/* go thru NPR nodes and issue any remaining ELS PLOGIs */
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
 		if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
 		    (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
 		    (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 &&
 		    (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) {
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
-			lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+			lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
 			sentplogi++;
-			phba->num_disc_nodes++;
-			if (phba->num_disc_nodes >=
-			    phba->cfg_discovery_threads) {
-				spin_lock_irq(phba->host->host_lock);
-				phba->fc_flag |= FC_NLP_MORE;
-				spin_unlock_irq(phba->host->host_lock);
+			vport->num_disc_nodes++;
+			if (vport->num_disc_nodes >=
+			    vport->phba->cfg_discovery_threads) {
+				spin_lock_irq(shost->host_lock);
+				vport->fc_flag |= FC_NLP_MORE;
+				spin_unlock_irq(shost->host_lock);
 				break;
 			}
 		}
 	}
 	if (sentplogi == 0) {
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag &= ~FC_NLP_MORE;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag &= ~FC_NLP_MORE;
+		spin_unlock_irq(shost->host_lock);
 	}
 	return sentplogi;
 }
 
-int
-lpfc_els_flush_rscn(struct lpfc_hba * phba)
+void
+lpfc_els_flush_rscn(struct lpfc_vport *vport)
 {
-	struct lpfc_dmabuf *mp;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	int i;
 
-	for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
-		mp = phba->fc_rscn_id_list[i];
-		lpfc_mbuf_free(phba, mp->virt, mp->phys);
-		kfree(mp);
-		phba->fc_rscn_id_list[i] = NULL;
+	for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
+		lpfc_in_buf_free(phba, vport->fc_rscn_id_list[i]);
+		vport->fc_rscn_id_list[i] = NULL;
 	}
-	phba->fc_rscn_id_cnt = 0;
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
-	spin_unlock_irq(phba->host->host_lock);
-	lpfc_can_disctmo(phba);
-	return 0;
+	spin_lock_irq(shost->host_lock);
+	vport->fc_rscn_id_cnt = 0;
+	vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
+	spin_unlock_irq(shost->host_lock);
+	lpfc_can_disctmo(vport);
 }
 
 int
-lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did)
+lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
 {
 	D_ID ns_did;
 	D_ID rscn_did;
-	struct lpfc_dmabuf *mp;
 	uint32_t *lp;
-	uint32_t payload_len, cmd, i, match;
+	uint32_t payload_len, i;
+	struct lpfc_hba *phba = vport->phba;
 
 	ns_did.un.word = did;
-	match = 0;
 
 	/* Never match fabric nodes for RSCNs */
 	if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
-		return(0);
+		return 0;
 
 	/* If we are doing a FULL RSCN rediscovery, match everything */
-	if (phba->fc_flag & FC_RSCN_DISCOVERY) {
+	if (vport->fc_flag & FC_RSCN_DISCOVERY)
 		return did;
-	}
 
-	for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
-		mp = phba->fc_rscn_id_list[i];
-		lp = (uint32_t *) mp->virt;
-		cmd = *lp++;
-		payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
-		payload_len -= sizeof (uint32_t);	/* take off word 0 */
+	for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
+		lp = vport->fc_rscn_id_list[i]->virt;
+		payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
+		payload_len -= sizeof(uint32_t);	/* take off word 0 */
 		while (payload_len) {
-			rscn_did.un.word = *lp++;
-			rscn_did.un.word = be32_to_cpu(rscn_did.un.word);
-			payload_len -= sizeof (uint32_t);
+			rscn_did.un.word = be32_to_cpu(*lp++);
+			payload_len -= sizeof(uint32_t);
 			switch (rscn_did.un.b.resv) {
 			case 0:	/* Single N_Port ID effected */
-				if (ns_did.un.word == rscn_did.un.word) {
-					match = did;
-				}
+				if (ns_did.un.word == rscn_did.un.word)
+					return did;
 				break;
 			case 1:	/* Whole N_Port Area effected */
 				if ((ns_did.un.b.domain == rscn_did.un.b.domain)
 				    && (ns_did.un.b.area == rscn_did.un.b.area))
-					{
-						match = did;
-					}
+					return did;
 				break;
 			case 2:	/* Whole N_Port Domain effected */
 				if (ns_did.un.b.domain == rscn_did.un.b.domain)
-					{
-						match = did;
-					}
-				break;
-			case 3:	/* Whole Fabric effected */
-				match = did;
+					return did;
 				break;
 			default:
-				/* Unknown Identifier in RSCN list */
+				/* Unknown Identifier in RSCN node */
 				lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-						"%d:0217 Unknown Identifier in "
-						"RSCN payload Data: x%x\n",
-						phba->brd_no, rscn_did.un.word);
-				break;
-			}
-			if (match) {
-				break;
+						"%d (%d):0217 Unknown "
+						"Identifier in RSCN payload "
+						"Data: x%x\n",
+						phba->brd_no, vport->vpi,
+						rscn_did.un.word);
+			case 3:	/* Whole Fabric effected */
+				return did;
 			}
 		}
 	}
-	return match;
+	return 0;
 }
 
 static int
-lpfc_rscn_recovery_check(struct lpfc_hba *phba)
+lpfc_rscn_recovery_check(struct lpfc_vport *vport)
 {
 	struct lpfc_nodelist *ndlp = NULL;
 
@@ -2459,188 +2775,261 @@
 	 * them to NPR state.
 	 */
 
-	list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
 		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE ||
-		    lpfc_rscn_payload_check(phba, ndlp->nlp_DID) == 0)
+		    lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0)
 			continue;
 
-		lpfc_disc_state_machine(phba, ndlp, NULL,
-					NLP_EVT_DEVICE_RECOVERY);
+		lpfc_disc_state_machine(vport, ndlp, NULL,
+						NLP_EVT_DEVICE_RECOVERY);
 
 		/*
 		 * Make sure NLP_DELAY_TMO is NOT running after a device
 		 * recovery event.
 		 */
 		if (ndlp->nlp_flag & NLP_DELAY_TMO)
-			lpfc_cancel_retry_delay_tmo(phba, ndlp);
+			lpfc_cancel_retry_delay_tmo(vport, ndlp);
 	}
 
 	return 0;
 }
 
 static int
-lpfc_els_rcv_rscn(struct lpfc_hba * phba,
-		  struct lpfc_iocbq * cmdiocb,
-		  struct lpfc_nodelist * ndlp, uint8_t newnode)
+lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		  struct lpfc_nodelist *ndlp, uint8_t newnode)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_dmabuf *pcmd;
-	uint32_t *lp;
+	struct lpfc_vport *next_vport;
+	uint32_t *lp, *datap;
 	IOCB_t *icmd;
-	uint32_t payload_len, cmd;
+	uint32_t payload_len, length, nportid, *cmd;
+	int rscn_cnt = vport->fc_rscn_id_cnt;
+	int rscn_id = 0, hba_id = 0;
 	int i;
 
 	icmd = &cmdiocb->iocb;
 	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
 	lp = (uint32_t *) pcmd->virt;
 
-	cmd = *lp++;
-	payload_len = be32_to_cpu(cmd) & 0xffff;	/* payload length */
-	payload_len -= sizeof (uint32_t);	/* take off word 0 */
-	cmd &= ELS_CMD_MASK;
+	payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
+	payload_len -= sizeof(uint32_t);	/* take off word 0 */
 
 	/* RSCN received */
-	lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_DISCOVERY,
-			"%d:0214 RSCN received Data: x%x x%x x%x x%x\n",
-			phba->brd_no,
-			phba->fc_flag, payload_len, *lp, phba->fc_rscn_id_cnt);
+	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			"%d (%d):0214 RSCN received Data: x%x x%x x%x x%x\n",
+			phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
+			*lp, rscn_cnt);
 
 	for (i = 0; i < payload_len/sizeof(uint32_t); i++)
-		fc_host_post_event(phba->host, fc_get_event_number(),
+		fc_host_post_event(shost, fc_get_event_number(),
 			FCH_EVT_RSCN, lp[i]);
 
 	/* If we are about to begin discovery, just ACC the RSCN.
 	 * Discovery processing will satisfy it.
 	 */
-	if (phba->hba_state <= LPFC_NS_QRY) {
-		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
-								newnode);
+	if (vport->port_state <= LPFC_NS_QRY) {
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
+			ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
+
+		lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
+				 newnode);
 		return 0;
 	}
 
+	/* If this RSCN just contains NPortIDs for other vports on this HBA,
+	 * just ACC and ignore it.
+	 */
+	if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+		!(phba->cfg_peer_port_login)) {
+		i = payload_len;
+		datap = lp;
+		while (i > 0) {
+			nportid = *datap++;
+			nportid = ((be32_to_cpu(nportid)) & Mask_DID);
+			i -= sizeof(uint32_t);
+			rscn_id++;
+			list_for_each_entry(next_vport, &phba->port_list,
+				listentry) {
+				if (nportid == next_vport->fc_myDID) {
+					hba_id++;
+					break;
+				}
+			}
+		}
+		if (rscn_id == hba_id) {
+			/* ALL NPortIDs in RSCN are on HBA */
+			lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			  "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n",
+			  phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
+			  *lp, rscn_cnt);
+
+			lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+				"RCV RSCN vport:  did:x%x/ste:x%x flg:x%x",
+				ndlp->nlp_DID, vport->port_state,
+				ndlp->nlp_flag);
+
+			lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
+				ndlp, NULL, newnode);
+			return 0;
+		}
+	}
+
 	/* If we are already processing an RSCN, save the received
 	 * RSCN payload buffer, cmdiocb->context2 to process later.
 	 */
-	if (phba->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
-		if ((phba->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) &&
-		    !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
-			spin_lock_irq(phba->host->host_lock);
-			phba->fc_flag |= FC_RSCN_MODE;
-			spin_unlock_irq(phba->host->host_lock);
-			phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
+	if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV RSCN defer:  did:x%x/ste:x%x flg:x%x",
+			ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
 
-			/* If we zero, cmdiocb->context2, the calling
-			 * routine will not try to free it.
-			 */
-			cmdiocb->context2 = NULL;
+		vport->fc_flag |= FC_RSCN_DEFERRED;
+		if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
+		    !(vport->fc_flag & FC_RSCN_DISCOVERY)) {
+			spin_lock_irq(shost->host_lock);
+			vport->fc_flag |= FC_RSCN_MODE;
+			spin_unlock_irq(shost->host_lock);
+			if (rscn_cnt) {
+				cmd = vport->fc_rscn_id_list[rscn_cnt-1]->virt;
+				length = be32_to_cpu(*cmd & ~ELS_CMD_MASK);
+			}
+			if ((rscn_cnt) &&
+			    (payload_len + length <= LPFC_BPL_SIZE)) {
+				*cmd &= ELS_CMD_MASK;
+				*cmd |= be32_to_cpu(payload_len + length);
+				memcpy(((uint8_t *)cmd) + length, lp,
+				       payload_len);
+			} else {
+				vport->fc_rscn_id_list[rscn_cnt] = pcmd;
+				vport->fc_rscn_id_cnt++;
+				/* If we zero, cmdiocb->context2, the calling
+				 * routine will not try to free it.
+				 */
+				cmdiocb->context2 = NULL;
+			}
 
 			/* Deferred RSCN */
 			lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-					"%d:0235 Deferred RSCN "
+					"%d (%d):0235 Deferred RSCN "
 					"Data: x%x x%x x%x\n",
-					phba->brd_no, phba->fc_rscn_id_cnt,
-					phba->fc_flag, phba->hba_state);
+					phba->brd_no, vport->vpi,
+					vport->fc_rscn_id_cnt, vport->fc_flag,
+					vport->port_state);
 		} else {
-			spin_lock_irq(phba->host->host_lock);
-			phba->fc_flag |= FC_RSCN_DISCOVERY;
-			spin_unlock_irq(phba->host->host_lock);
+			spin_lock_irq(shost->host_lock);
+			vport->fc_flag |= FC_RSCN_DISCOVERY;
+			spin_unlock_irq(shost->host_lock);
 			/* ReDiscovery RSCN */
 			lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-					"%d:0234 ReDiscovery RSCN "
+					"%d (%d):0234 ReDiscovery RSCN "
 					"Data: x%x x%x x%x\n",
-					phba->brd_no, phba->fc_rscn_id_cnt,
-					phba->fc_flag, phba->hba_state);
+					phba->brd_no, vport->vpi,
+					vport->fc_rscn_id_cnt, vport->fc_flag,
+					vport->port_state);
 		}
 		/* Send back ACC */
-		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
+		lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
 								newnode);
 
 		/* send RECOVERY event for ALL nodes that match RSCN payload */
-		lpfc_rscn_recovery_check(phba);
+		lpfc_rscn_recovery_check(vport);
+		vport->fc_flag &= ~FC_RSCN_DEFERRED;
 		return 0;
 	}
 
-	phba->fc_flag |= FC_RSCN_MODE;
-	phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+		"RCV RSCN:        did:x%x/ste:x%x flg:x%x",
+		ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
+
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag |= FC_RSCN_MODE;
+	spin_unlock_irq(shost->host_lock);
+	vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd;
 	/*
 	 * If we zero, cmdiocb->context2, the calling routine will
 	 * not try to free it.
 	 */
 	cmdiocb->context2 = NULL;
 
-	lpfc_set_disctmo(phba);
+	lpfc_set_disctmo(vport);
 
 	/* Send back ACC */
-	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
+	lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
 
 	/* send RECOVERY event for ALL nodes that match RSCN payload */
-	lpfc_rscn_recovery_check(phba);
+	lpfc_rscn_recovery_check(vport);
 
-	return lpfc_els_handle_rscn(phba);
+	return lpfc_els_handle_rscn(vport);
 }
 
 int
-lpfc_els_handle_rscn(struct lpfc_hba * phba)
+lpfc_els_handle_rscn(struct lpfc_vport *vport)
 {
 	struct lpfc_nodelist *ndlp;
+	struct lpfc_hba *phba = vport->phba;
+
+	/* Ignore RSCN if the port is being torn down. */
+	if (vport->load_flag & FC_UNLOADING) {
+		lpfc_els_flush_rscn(vport);
+		return 0;
+	}
 
 	/* Start timer for RSCN processing */
-	lpfc_set_disctmo(phba);
+	lpfc_set_disctmo(vport);
 
 	/* RSCN processed */
-	lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_DISCOVERY,
-			"%d:0215 RSCN processed Data: x%x x%x x%x x%x\n",
-			phba->brd_no,
-			phba->fc_flag, 0, phba->fc_rscn_id_cnt,
-			phba->hba_state);
+	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			"%d (%d):0215 RSCN processed Data: x%x x%x x%x x%x\n",
+			phba->brd_no, vport->vpi,
+			vport->fc_flag, 0, vport->fc_rscn_id_cnt,
+			vport->port_state);
 
 	/* To process RSCN, first compare RSCN data with NameServer */
-	phba->fc_ns_retry = 0;
-	ndlp = lpfc_findnode_did(phba, NameServer_DID);
+	vport->fc_ns_retry = 0;
+	ndlp = lpfc_findnode_did(vport, NameServer_DID);
 	if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
 		/* Good ndlp, issue CT Request to NameServer */
-		if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) {
+		if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0)
 			/* Wait for NameServer query cmpl before we can
 			   continue */
 			return 1;
-		}
 	} else {
 		/* If login to NameServer does not exist, issue one */
 		/* Good status, issue PLOGI to NameServer */
-		ndlp = lpfc_findnode_did(phba, NameServer_DID);
-		if (ndlp) {
+		ndlp = lpfc_findnode_did(vport, NameServer_DID);
+		if (ndlp)
 			/* Wait for NameServer login cmpl before we can
 			   continue */
 			return 1;
-		}
+
 		ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
 		if (!ndlp) {
-			lpfc_els_flush_rscn(phba);
+			lpfc_els_flush_rscn(vport);
 			return 0;
 		} else {
-			lpfc_nlp_init(phba, ndlp, NameServer_DID);
+			lpfc_nlp_init(vport, ndlp, NameServer_DID);
 			ndlp->nlp_type |= NLP_FABRIC;
 			ndlp->nlp_prev_state = ndlp->nlp_state;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
-			lpfc_issue_els_plogi(phba, NameServer_DID, 0);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+			lpfc_issue_els_plogi(vport, NameServer_DID, 0);
 			/* Wait for NameServer login cmpl before we can
 			   continue */
 			return 1;
 		}
 	}
 
-	lpfc_els_flush_rscn(phba);
+	lpfc_els_flush_rscn(vport);
 	return 0;
 }
 
 static int
-lpfc_els_rcv_flogi(struct lpfc_hba * phba,
-		   struct lpfc_iocbq * cmdiocb,
-		   struct lpfc_nodelist * ndlp, uint8_t newnode)
+lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		   struct lpfc_nodelist *ndlp, uint8_t newnode)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
 	uint32_t *lp = (uint32_t *) pcmd->virt;
 	IOCB_t *icmd = &cmdiocb->iocb;
@@ -2655,7 +3044,7 @@
 
 	/* FLOGI received */
 
-	lpfc_set_disctmo(phba);
+	lpfc_set_disctmo(vport);
 
 	if (phba->fc_topology == TOPOLOGY_LOOP) {
 		/* We should never receive a FLOGI in loop mode, ignore it */
@@ -2664,33 +3053,34 @@
 		/* An FLOGI ELS command <elsCmd> was received from DID <did> in
 		   Loop Mode */
 		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-				"%d:0113 An FLOGI ELS command x%x was received "
-				"from DID x%x in Loop Mode\n",
-				phba->brd_no, cmd, did);
+				"%d (%d):0113 An FLOGI ELS command x%x was "
+				"received from DID x%x in Loop Mode\n",
+				phba->brd_no, vport->vpi, cmd, did);
 		return 1;
 	}
 
 	did = Fabric_DID;
 
-	if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3))) {
+	if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) {
 		/* For a FLOGI we accept, then if our portname is greater
 		 * then the remote portname we initiate Nport login.
 		 */
 
-		rc = memcmp(&phba->fc_portname, &sp->portName,
-			    sizeof (struct lpfc_name));
+		rc = memcmp(&vport->fc_portname, &sp->portName,
+			    sizeof(struct lpfc_name));
 
 		if (!rc) {
-			if ((mbox = mempool_alloc(phba->mbox_mem_pool,
-						  GFP_KERNEL)) == 0) {
+			mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+			if (!mbox)
 				return 1;
-			}
+
 			lpfc_linkdown(phba);
 			lpfc_init_link(phba, mbox,
 				       phba->cfg_topology,
 				       phba->cfg_link_speed);
 			mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
 			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			mbox->vport = vport;
 			rc = lpfc_sli_issue_mbox
 				(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
 			lpfc_set_loopback_flag(phba);
@@ -2699,31 +3089,34 @@
 			}
 			return 1;
 		} else if (rc > 0) {	/* greater than */
-			spin_lock_irq(phba->host->host_lock);
-			phba->fc_flag |= FC_PT2PT_PLOGI;
-			spin_unlock_irq(phba->host->host_lock);
+			spin_lock_irq(shost->host_lock);
+			vport->fc_flag |= FC_PT2PT_PLOGI;
+			spin_unlock_irq(shost->host_lock);
 		}
-		phba->fc_flag |= FC_PT2PT;
-		phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag |= FC_PT2PT;
+		vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+		spin_unlock_irq(shost->host_lock);
 	} else {
 		/* Reject this request because invalid parameters */
 		stat.un.b.lsRjtRsvd0 = 0;
 		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 		stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
 		stat.un.b.vendorUnique = 0;
-		lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+			NULL);
 		return 1;
 	}
 
 	/* Send back ACC */
-	lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
+	lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
 
 	return 0;
 }
 
 static int
-lpfc_els_rcv_rnid(struct lpfc_hba * phba,
-		  struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
+lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		  struct lpfc_nodelist *ndlp)
 {
 	struct lpfc_dmabuf *pcmd;
 	uint32_t *lp;
@@ -2746,7 +3139,7 @@
 	case 0:
 	case RNID_TOPOLOGY_DISC:
 		/* Send back ACC */
-		lpfc_els_rsp_rnid_acc(phba, rn->Format, cmdiocb, ndlp);
+		lpfc_els_rsp_rnid_acc(vport, rn->Format, cmdiocb, ndlp);
 		break;
 	default:
 		/* Reject this request because format not supported */
@@ -2754,14 +3147,15 @@
 		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 		stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
 		stat.un.b.vendorUnique = 0;
-		lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+			NULL);
 	}
 	return 0;
 }
 
 static int
-lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-		 struct lpfc_nodelist *ndlp)
+lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		  struct lpfc_nodelist *ndlp)
 {
 	struct ls_rjt stat;
 
@@ -2770,15 +3164,15 @@
 	stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 	stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
 	stat.un.b.vendorUnique = 0;
-	lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+	lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
 	return 0;
 }
 
 static void
 lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-	struct lpfc_sli *psli;
-	struct lpfc_sli_ring *pring;
+	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
 	MAILBOX_t *mb;
 	IOCB_t *icmd;
 	RPS_RSP *rps_rsp;
@@ -2788,8 +3182,6 @@
 	uint16_t xri, status;
 	uint32_t cmdsize;
 
-	psli = &phba->sli;
-	pring = &psli->ring[LPFC_ELS_RING];
 	mb = &pmb->mb;
 
 	ndlp = (struct lpfc_nodelist *) pmb->context2;
@@ -2804,8 +3196,9 @@
 
 	cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
 	mempool_free(pmb, phba->mbox_mem_pool);
-	elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp,
-						ndlp->nlp_DID, ELS_CMD_ACC);
+	elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
+				     lpfc_max_els_tries, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_ACC);
 	lpfc_nlp_put(ndlp);
 	if (!elsiocb)
 		return;
@@ -2815,14 +3208,14 @@
 
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 	*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
-	pcmd += sizeof (uint32_t); /* Skip past command */
+	pcmd += sizeof(uint32_t); /* Skip past command */
 	rps_rsp = (RPS_RSP *)pcmd;
 
 	if (phba->fc_topology != TOPOLOGY_LOOP)
 		status = 0x10;
 	else
 		status = 0x8;
-	if (phba->fc_flag & FC_FABRIC)
+	if (phba->pport->fc_flag & FC_FABRIC)
 		status |= 0x4;
 
 	rps_rsp->rsvd1 = 0;
@@ -2836,25 +3229,25 @@
 
 	/* Xmit ELS RPS ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
-			"did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
-			phba->brd_no, elsiocb->iotag,
+			"%d (%d):0118 Xmit ELS RPS ACC response tag x%x "
+			"xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+			"rpi x%x\n",
+			phba->brd_no, ndlp->vport->vpi, elsiocb->iotag,
 			elsiocb->iocb.ulpContext, ndlp->nlp_DID,
 			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
-	elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
 	phba->fc_stat.elsXmitACC++;
-
-	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
 		lpfc_els_free_iocb(phba, elsiocb);
-	}
 	return;
 }
 
 static int
-lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		 struct lpfc_nodelist * ndlp)
+lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		 struct lpfc_nodelist *ndlp)
 {
+	struct lpfc_hba *phba = vport->phba;
 	uint32_t *lp;
 	uint8_t flag;
 	LPFC_MBOXQ_t *mbox;
@@ -2868,7 +3261,8 @@
 		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 		stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
 		stat.un.b.vendorUnique = 0;
-		lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+			NULL);
 	}
 
 	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
@@ -2878,19 +3272,24 @@
 
 	if ((flag == 0) ||
 	    ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
-	    ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname,
-			   sizeof (struct lpfc_name)) == 0))) {
-		if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) {
+	    ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname,
+				    sizeof(struct lpfc_name)) == 0))) {
+
+		printk("Fix me....\n");
+		dump_stack();
+		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
+		if (mbox) {
 			lpfc_read_lnk_stat(phba, mbox);
 			mbox->context1 =
-			    (void *)((unsigned long)cmdiocb->iocb.ulpContext);
+			    (void *)((unsigned long) cmdiocb->iocb.ulpContext);
 			mbox->context2 = lpfc_nlp_get(ndlp);
+			mbox->vport = vport;
 			mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
 			if (lpfc_sli_issue_mbox (phba, mbox,
-			    (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) {
+			    (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED)
 				/* Mbox completion will send ELS Response */
 				return 0;
-			}
+
 			lpfc_nlp_put(ndlp);
 			mempool_free(mbox, phba->mbox_mem_pool);
 		}
@@ -2899,27 +3298,25 @@
 	stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 	stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
 	stat.un.b.vendorUnique = 0;
-	lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+	lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
 	return 0;
 }
 
 static int
-lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize,
-		 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
+lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
+		     struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
 {
-	IOCB_t *icmd;
-	IOCB_t *oldcmd;
+	struct lpfc_hba *phba = vport->phba;
+	IOCB_t *icmd, *oldcmd;
 	RPL_RSP rpl_rsp;
 	struct lpfc_iocbq *elsiocb;
-	struct lpfc_sli_ring *pring;
-	struct lpfc_sli *psli;
+	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
 	uint8_t *pcmd;
 
-	psli = &phba->sli;
-	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
+	elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_ACC);
 
-	elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-					ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
 	if (!elsiocb)
 		return 1;
 
@@ -2929,7 +3326,7 @@
 
 	pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
 	*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
-	pcmd += sizeof (uint16_t);
+	pcmd += sizeof(uint16_t);
 	*((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize);
 	pcmd += sizeof(uint16_t);
 
@@ -2937,8 +3334,8 @@
 	rpl_rsp.listLen = be32_to_cpu(1);
 	rpl_rsp.index = 0;
 	rpl_rsp.port_num_blk.portNum = 0;
-	rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID);
-	memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname,
+	rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID);
+	memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname,
 	    sizeof(struct lpfc_name));
 
 	memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
@@ -2946,13 +3343,14 @@
 
 	/* Xmit ELS RPL ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0120 Xmit ELS RPL ACC response tag x%x xri x%x, "
-			"did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
-			phba->brd_no, elsiocb->iotag,
+			"%d (%d):0120 Xmit ELS RPL ACC response tag x%x "
+			"xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+			"rpi x%x\n",
+			phba->brd_no, vport->vpi, elsiocb->iotag,
 			elsiocb->iocb.ulpContext, ndlp->nlp_DID,
 			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
-	elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
 
 	phba->fc_stat.elsXmitACC++;
 	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
@@ -2963,8 +3361,8 @@
 }
 
 static int
-lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		 struct lpfc_nodelist * ndlp)
+lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		 struct lpfc_nodelist *ndlp)
 {
 	struct lpfc_dmabuf *pcmd;
 	uint32_t *lp;
@@ -2979,7 +3377,8 @@
 		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 		stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
 		stat.un.b.vendorUnique = 0;
-		lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+			NULL);
 	}
 
 	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
@@ -2996,15 +3395,16 @@
 	} else {
 		cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t);
 	}
-	lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp);
+	lpfc_els_rsp_rpl_acc(vport, cmdsize, cmdiocb, ndlp);
 
 	return 0;
 }
 
 static int
-lpfc_els_rcv_farp(struct lpfc_hba * phba,
-		  struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
+lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		  struct lpfc_nodelist *ndlp)
 {
+	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_dmabuf *pcmd;
 	uint32_t *lp;
 	IOCB_t *icmd;
@@ -3020,11 +3420,9 @@
 	fp = (FARP *) lp;
 
 	/* FARP-REQ received from DID <did> */
-	lpfc_printf_log(phba,
-			 KERN_INFO,
-			 LOG_ELS,
-			 "%d:0601 FARP-REQ received from DID x%x\n",
-			 phba->brd_no, did);
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+			"%d (%d):0601 FARP-REQ received from DID x%x\n",
+			phba->brd_no, vport->vpi, did);
 
 	/* We will only support match on WWPN or WWNN */
 	if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
@@ -3034,15 +3432,15 @@
 	cnt = 0;
 	/* If this FARP command is searching for my portname */
 	if (fp->Mflags & FARP_MATCH_PORT) {
-		if (memcmp(&fp->RportName, &phba->fc_portname,
-			   sizeof (struct lpfc_name)) == 0)
+		if (memcmp(&fp->RportName, &vport->fc_portname,
+			   sizeof(struct lpfc_name)) == 0)
 			cnt = 1;
 	}
 
 	/* If this FARP command is searching for my nodename */
 	if (fp->Mflags & FARP_MATCH_NODE) {
-		if (memcmp(&fp->RnodeName, &phba->fc_nodename,
-			   sizeof (struct lpfc_name)) == 0)
+		if (memcmp(&fp->RnodeName, &vport->fc_nodename,
+			   sizeof(struct lpfc_name)) == 0)
 			cnt = 1;
 	}
 
@@ -3052,28 +3450,28 @@
 			/* Log back into the node before sending the FARP. */
 			if (fp->Rflags & FARP_REQUEST_PLOGI) {
 				ndlp->nlp_prev_state = ndlp->nlp_state;
-				lpfc_nlp_set_state(phba, ndlp,
+				lpfc_nlp_set_state(vport, ndlp,
 						   NLP_STE_PLOGI_ISSUE);
-				lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+				lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
 			}
 
 			/* Send a FARP response to that node */
-			if (fp->Rflags & FARP_REQUEST_FARPR) {
-				lpfc_issue_els_farpr(phba, did, 0);
-			}
+			if (fp->Rflags & FARP_REQUEST_FARPR)
+				lpfc_issue_els_farpr(vport, did, 0);
 		}
 	}
 	return 0;
 }
 
 static int
-lpfc_els_rcv_farpr(struct lpfc_hba * phba,
-		   struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
+lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		   struct lpfc_nodelist  *ndlp)
 {
 	struct lpfc_dmabuf *pcmd;
 	uint32_t *lp;
 	IOCB_t *icmd;
 	uint32_t cmd, did;
+	struct lpfc_hba *phba = vport->phba;
 
 	icmd = &cmdiocb->iocb;
 	did = icmd->un.elsreq64.remoteID;
@@ -3082,21 +3480,18 @@
 
 	cmd = *lp++;
 	/* FARP-RSP received from DID <did> */
-	lpfc_printf_log(phba,
-			 KERN_INFO,
-			 LOG_ELS,
-			 "%d:0600 FARP-RSP received from DID x%x\n",
-			 phba->brd_no, did);
-
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+			"%d (%d):0600 FARP-RSP received from DID x%x\n",
+			phba->brd_no, vport->vpi, did);
 	/* ACCEPT the Farp resp request */
-	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+	lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
 
 	return 0;
 }
 
 static int
-lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-		 struct lpfc_nodelist * fan_ndlp)
+lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+		 struct lpfc_nodelist *fan_ndlp)
 {
 	struct lpfc_dmabuf *pcmd;
 	uint32_t *lp;
@@ -3104,10 +3499,12 @@
 	uint32_t cmd, did;
 	FAN *fp;
 	struct lpfc_nodelist *ndlp, *next_ndlp;
+	struct lpfc_hba *phba = vport->phba;
 
 	/* FAN received */
-	lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n",
-								phba->brd_no);
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+			"%d (%d):0265 FAN received\n",
+			phba->brd_no, vport->vpi);
 
 	icmd = &cmdiocb->iocb;
 	did = icmd->un.elsreq64.remoteID;
@@ -3115,11 +3512,11 @@
 	lp = (uint32_t *)pcmd->virt;
 
 	cmd = *lp++;
-	fp = (FAN *)lp;
+	fp = (FAN *) lp;
 
 	/* FAN received; Fan does not have a reply sequence */
 
-	if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
+	if (phba->pport->port_state == LPFC_LOCAL_CFG_LINK) {
 		if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName,
 			sizeof(struct lpfc_name)) != 0) ||
 		    (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
@@ -3130,7 +3527,7 @@
 			 */
 
 			list_for_each_entry_safe(ndlp, next_ndlp,
-						 &phba->fc_nodes, nlp_listp) {
+						 &vport->fc_nodes, nlp_listp) {
 				if (ndlp->nlp_state != NLP_STE_NPR_NODE)
 					continue;
 				if (ndlp->nlp_type & NLP_FABRIC) {
@@ -3138,24 +3535,24 @@
 					 * Clean up old Fabric, Nameserver and
 					 * other NLP_FABRIC logins
 					 */
-					lpfc_drop_node(phba, ndlp);
+					lpfc_drop_node(vport, ndlp);
 				} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
 					/* Fail outstanding I/O now since this
 					 * device is marked for PLOGI
 					 */
-					lpfc_unreg_rpi(phba, ndlp);
+					lpfc_unreg_rpi(vport, ndlp);
 				}
 			}
 
-			phba->hba_state = LPFC_FLOGI;
-			lpfc_set_disctmo(phba);
-			lpfc_initial_flogi(phba);
+			vport->port_state = LPFC_FLOGI;
+			lpfc_set_disctmo(vport);
+			lpfc_initial_flogi(vport);
 			return 0;
 		}
 		/* Discovery not needed,
 		 * move the nodes to their original state.
 		 */
-		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+		list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
 					 nlp_listp) {
 			if (ndlp->nlp_state != NLP_STE_NPR_NODE)
 				continue;
@@ -3163,13 +3560,13 @@
 			switch (ndlp->nlp_prev_state) {
 			case NLP_STE_UNMAPPED_NODE:
 				ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-				lpfc_nlp_set_state(phba, ndlp,
+				lpfc_nlp_set_state(vport, ndlp,
 						   NLP_STE_UNMAPPED_NODE);
 				break;
 
 			case NLP_STE_MAPPED_NODE:
 				ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-				lpfc_nlp_set_state(phba, ndlp,
+				lpfc_nlp_set_state(vport, ndlp,
 						   NLP_STE_MAPPED_NODE);
 				break;
 
@@ -3179,7 +3576,7 @@
 		}
 
 		/* Start discovery - this should just do CLEAR_LA */
-		lpfc_disc_start(phba);
+		lpfc_disc_start(vport);
 	}
 	return 0;
 }
@@ -3187,42 +3584,42 @@
 void
 lpfc_els_timeout(unsigned long ptr)
 {
-	struct lpfc_hba *phba;
+	struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
+	struct lpfc_hba   *phba = vport->phba;
 	unsigned long iflag;
 
-	phba = (struct lpfc_hba *)ptr;
-	if (phba == 0)
-		return;
-	spin_lock_irqsave(phba->host->host_lock, iflag);
-	if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
-		phba->work_hba_events |= WORKER_ELS_TMO;
+	spin_lock_irqsave(&vport->work_port_lock, iflag);
+	if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
+		vport->work_port_events |= WORKER_ELS_TMO;
+		spin_unlock_irqrestore(&vport->work_port_lock, iflag);
+
+		spin_lock_irqsave(&phba->hbalock, iflag);
 		if (phba->work_wait)
-			wake_up(phba->work_wait);
+			lpfc_worker_wake_up(phba);
+		spin_unlock_irqrestore(&phba->hbalock, iflag);
 	}
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+	else
+		spin_unlock_irqrestore(&vport->work_port_lock, iflag);
 	return;
 }
 
 void
-lpfc_els_timeout_handler(struct lpfc_hba *phba)
+lpfc_els_timeout_handler(struct lpfc_vport *vport)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_sli_ring *pring;
 	struct lpfc_iocbq *tmp_iocb, *piocb;
 	IOCB_t *cmd = NULL;
 	struct lpfc_dmabuf *pcmd;
-	uint32_t *elscmd;
-	uint32_t els_command=0;
+	uint32_t els_command = 0;
 	uint32_t timeout;
-	uint32_t remote_ID;
+	uint32_t remote_ID = 0xffffffff;
 
-	if (phba == 0)
-		return;
-	spin_lock_irq(phba->host->host_lock);
 	/* If the timer is already canceled do nothing */
-	if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
-		spin_unlock_irq(phba->host->host_lock);
+	if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
 		return;
 	}
+	spin_lock_irq(&phba->hbalock);
 	timeout = (uint32_t)(phba->fc_ratov << 1);
 
 	pring = &phba->sli.ring[LPFC_ELS_RING];
@@ -3230,63 +3627,70 @@
 	list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
 		cmd = &piocb->iocb;
 
-		if ((piocb->iocb_flag & LPFC_IO_LIBDFC) ||
-			(piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) ||
-			(piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) {
+		if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
+		    piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
+		    piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
 			continue;
-		}
-		pcmd = (struct lpfc_dmabuf *) piocb->context2;
-		if (pcmd) {
-			elscmd = (uint32_t *) (pcmd->virt);
-			els_command = *elscmd;
-		}
 
-		if ((els_command == ELS_CMD_FARP)
-		    || (els_command == ELS_CMD_FARPR)) {
+		if (piocb->vport != vport)
 			continue;
-		}
+
+		pcmd = (struct lpfc_dmabuf *) piocb->context2;
+		if (pcmd)
+			els_command = *(uint32_t *) (pcmd->virt);
+
+		if (els_command == ELS_CMD_FARP ||
+		    els_command == ELS_CMD_FARPR ||
+		    els_command == ELS_CMD_FDISC)
+			continue;
+
+		if (vport != piocb->vport)
+			continue;
 
 		if (piocb->drvrTimeout > 0) {
-			if (piocb->drvrTimeout >= timeout) {
+			if (piocb->drvrTimeout >= timeout)
 				piocb->drvrTimeout -= timeout;
-			} else {
+			else
 				piocb->drvrTimeout = 0;
-			}
 			continue;
 		}
 
-		if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
-			struct lpfc_nodelist *ndlp;
-			ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext);
-			remote_ID = ndlp->nlp_DID;
-		} else {
+		remote_ID = 0xffffffff;
+		if (cmd->ulpCommand != CMD_GEN_REQUEST64_CR)
 			remote_ID = cmd->un.elsreq64.remoteID;
+		else {
+			struct lpfc_nodelist *ndlp;
+			ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
+			if (ndlp)
+				remote_ID = ndlp->nlp_DID;
 		}
 
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_ELS,
-				"%d:0127 ELS timeout Data: x%x x%x x%x x%x\n",
-				phba->brd_no, els_command,
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+				"%d (%d):0127 ELS timeout Data: x%x x%x x%x "
+				"x%x\n",
+				phba->brd_no, vport->vpi, els_command,
 				remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
 
 		lpfc_sli_issue_abort_iotag(phba, pring, piocb);
 	}
-	if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
-		mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
+	spin_unlock_irq(&phba->hbalock);
 
-	spin_unlock_irq(phba->host->host_lock);
+	if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
+		mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
 }
 
 void
-lpfc_els_flush_cmd(struct lpfc_hba *phba)
+lpfc_els_flush_cmd(struct lpfc_vport *vport)
 {
 	LIST_HEAD(completions);
+	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
 	struct lpfc_iocbq *tmp_iocb, *piocb;
 	IOCB_t *cmd = NULL;
 
-	spin_lock_irq(phba->host->host_lock);
+	lpfc_fabric_abort_vport(vport);
+
+	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
 		cmd = &piocb->iocb;
 
@@ -3301,271 +3705,1042 @@
 		    cmd->ulpCommand == CMD_ABORT_XRI_CN)
 			continue;
 
+		if (piocb->vport != vport)
+			continue;
+
 		list_move_tail(&piocb->list, &completions);
 		pring->txq_cnt--;
-
 	}
 
 	list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
-		cmd = &piocb->iocb;
-
 		if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
 			continue;
 		}
 
+		if (piocb->vport != vport)
+			continue;
+
 		lpfc_sli_issue_abort_iotag(phba, pring, piocb);
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
-	while(!list_empty(&completions)) {
+	while (!list_empty(&completions)) {
 		piocb = list_get_first(&completions, struct lpfc_iocbq, list);
 		cmd = &piocb->iocb;
-		list_del(&piocb->list);
+		list_del_init(&piocb->list);
 
-		if (piocb->iocb_cmpl) {
+		if (!piocb->iocb_cmpl)
+			lpfc_sli_release_iocbq(phba, piocb);
+		else {
 			cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
 			cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
 			(piocb->iocb_cmpl) (phba, piocb, piocb);
-		} else
-			lpfc_sli_release_iocbq(phba, piocb);
+		}
 	}
 
 	return;
 }
 
-void
-lpfc_els_unsol_event(struct lpfc_hba * phba,
-		     struct lpfc_sli_ring * pring, struct lpfc_iocbq * elsiocb)
+static void
+lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+		      struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
 {
-	struct lpfc_sli *psli;
 	struct lpfc_nodelist *ndlp;
-	struct lpfc_dmabuf *mp;
-	uint32_t *lp;
-	IOCB_t *icmd;
 	struct ls_rjt stat;
-	uint32_t cmd;
-	uint32_t did;
-	uint32_t newnode;
-	uint32_t drop_cmd = 0;	/* by default do NOT drop received cmd */
-	uint32_t rjt_err = 0;
+	uint32_t *payload;
+	uint32_t cmd, did, newnode, rjt_err = 0;
+	IOCB_t *icmd = &elsiocb->iocb;
 
-	psli = &phba->sli;
-	icmd = &elsiocb->iocb;
-
-	if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-		((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
-		/* Not enough posted buffers; Try posting more buffers */
-		phba->fc_stat.NoRcvBuf++;
-		lpfc_post_buffer(phba, pring, 0, 1);
-		return;
-	}
-
-	/* If there are no BDEs associated with this IOCB,
-	 * there is nothing to do.
-	 */
-	if (icmd->ulpBdeCount == 0)
-		return;
-
-	/* type of ELS cmd is first 32bit word in packet */
-	mp = lpfc_sli_ringpostbuf_get(phba, pring, getPaddr(icmd->un.
-							    cont64[0].
-							    addrHigh,
-							    icmd->un.
-							    cont64[0].addrLow));
-	if (mp == 0) {
-		drop_cmd = 1;
+	if (vport == NULL || elsiocb->context2 == NULL)
 		goto dropit;
-	}
 
 	newnode = 0;
-	lp = (uint32_t *) mp->virt;
-	cmd = *lp++;
-	lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], 1, 1);
+	payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt;
+	cmd = *payload;
+	if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
+		lpfc_post_buffer(phba, pring, 1, 1);
 
+	did = icmd->un.rcvels.remoteID;
 	if (icmd->ulpStatus) {
-		lpfc_mbuf_free(phba, mp->virt, mp->phys);
-		kfree(mp);
-		drop_cmd = 1;
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV Unsol ELS:  status:x%x/x%x did:x%x",
+			icmd->ulpStatus, icmd->un.ulpWord[4], did);
 		goto dropit;
 	}
 
 	/* Check to see if link went down during discovery */
-	if (lpfc_els_chk_latt(phba)) {
-		lpfc_mbuf_free(phba, mp->virt, mp->phys);
-		kfree(mp);
-		drop_cmd = 1;
+	if (lpfc_els_chk_latt(vport))
 		goto dropit;
-	}
 
-	did = icmd->un.rcvels.remoteID;
-	ndlp = lpfc_findnode_did(phba, did);
+	/* Ignore traffic recevied during vport shutdown. */
+	if (vport->load_flag & FC_UNLOADING)
+		goto dropit;
+
+	ndlp = lpfc_findnode_did(vport, did);
 	if (!ndlp) {
 		/* Cannot find existing Fabric ndlp, so allocate a new one */
 		ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-		if (!ndlp) {
-			lpfc_mbuf_free(phba, mp->virt, mp->phys);
-			kfree(mp);
-			drop_cmd = 1;
+		if (!ndlp)
 			goto dropit;
-		}
 
-		lpfc_nlp_init(phba, ndlp, did);
+		lpfc_nlp_init(vport, ndlp, did);
 		newnode = 1;
 		if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
 			ndlp->nlp_type |= NLP_FABRIC;
 		}
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
 	}
 
 	phba->fc_stat.elsRcvFrame++;
 	if (elsiocb->context1)
 		lpfc_nlp_put(elsiocb->context1);
 	elsiocb->context1 = lpfc_nlp_get(ndlp);
-	elsiocb->context2 = mp;
+	elsiocb->vport = vport;
 
 	if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
 		cmd &= ELS_CMD_MASK;
 	}
 	/* ELS command <elsCmd> received from NPORT <did> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0112 ELS command x%x received from NPORT x%x "
-			"Data: x%x\n", phba->brd_no, cmd, did, phba->hba_state);
+			"%d (%d):0112 ELS command x%x received from NPORT x%x "
+			"Data: x%x\n", phba->brd_no, vport->vpi, cmd, did,
+			vport->port_state);
 
 	switch (cmd) {
 	case ELS_CMD_PLOGI:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV PLOGI:       did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvPLOGI++;
-		if (phba->hba_state < LPFC_DISC_AUTH) {
-			rjt_err = 1;
+		ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
+
+		if (vport->port_state < LPFC_DISC_AUTH) {
+			rjt_err = LSRJT_UNABLE_TPC;
 			break;
 		}
-		ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
-		lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
+		lpfc_disc_state_machine(vport, ndlp, elsiocb,
+					NLP_EVT_RCV_PLOGI);
+
 		break;
 	case ELS_CMD_FLOGI:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV FLOGI:       did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvFLOGI++;
-		lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
+		lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode);
 		if (newnode)
-			lpfc_drop_node(phba, ndlp);
+			lpfc_drop_node(vport, ndlp);
 		break;
 	case ELS_CMD_LOGO:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV LOGO:        did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvLOGO++;
-		if (phba->hba_state < LPFC_DISC_AUTH) {
-			rjt_err = 1;
+		if (vport->port_state < LPFC_DISC_AUTH) {
+			rjt_err = LSRJT_UNABLE_TPC;
 			break;
 		}
-		lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
+		lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
 		break;
 	case ELS_CMD_PRLO:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV PRLO:        did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvPRLO++;
-		if (phba->hba_state < LPFC_DISC_AUTH) {
-			rjt_err = 1;
+		if (vport->port_state < LPFC_DISC_AUTH) {
+			rjt_err = LSRJT_UNABLE_TPC;
 			break;
 		}
-		lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
+		lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
 		break;
 	case ELS_CMD_RSCN:
 		phba->fc_stat.elsRcvRSCN++;
-		lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
+		lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode);
 		if (newnode)
-			lpfc_drop_node(phba, ndlp);
+			lpfc_drop_node(vport, ndlp);
 		break;
 	case ELS_CMD_ADISC:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV ADISC:       did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvADISC++;
-		if (phba->hba_state < LPFC_DISC_AUTH) {
-			rjt_err = 1;
+		if (vport->port_state < LPFC_DISC_AUTH) {
+			rjt_err = LSRJT_UNABLE_TPC;
 			break;
 		}
-		lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_ADISC);
+		lpfc_disc_state_machine(vport, ndlp, elsiocb,
+					NLP_EVT_RCV_ADISC);
 		break;
 	case ELS_CMD_PDISC:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV PDISC:       did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvPDISC++;
-		if (phba->hba_state < LPFC_DISC_AUTH) {
-			rjt_err = 1;
+		if (vport->port_state < LPFC_DISC_AUTH) {
+			rjt_err = LSRJT_UNABLE_TPC;
 			break;
 		}
-		lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PDISC);
+		lpfc_disc_state_machine(vport, ndlp, elsiocb,
+					NLP_EVT_RCV_PDISC);
 		break;
 	case ELS_CMD_FARPR:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV FARPR:       did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvFARPR++;
-		lpfc_els_rcv_farpr(phba, elsiocb, ndlp);
+		lpfc_els_rcv_farpr(vport, elsiocb, ndlp);
 		break;
 	case ELS_CMD_FARP:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV FARP:        did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvFARP++;
-		lpfc_els_rcv_farp(phba, elsiocb, ndlp);
+		lpfc_els_rcv_farp(vport, elsiocb, ndlp);
 		break;
 	case ELS_CMD_FAN:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV FAN:         did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvFAN++;
-		lpfc_els_rcv_fan(phba, elsiocb, ndlp);
+		lpfc_els_rcv_fan(vport, elsiocb, ndlp);
 		break;
 	case ELS_CMD_PRLI:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV PRLI:        did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvPRLI++;
-		if (phba->hba_state < LPFC_DISC_AUTH) {
-			rjt_err = 1;
+		if (vport->port_state < LPFC_DISC_AUTH) {
+			rjt_err = LSRJT_UNABLE_TPC;
 			break;
 		}
-		lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
+		lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
 		break;
 	case ELS_CMD_LIRR:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV LIRR:        did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvLIRR++;
-		lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
+		lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
 		if (newnode)
-			lpfc_drop_node(phba, ndlp);
+			lpfc_drop_node(vport, ndlp);
 		break;
 	case ELS_CMD_RPS:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV RPS:         did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvRPS++;
-		lpfc_els_rcv_rps(phba, elsiocb, ndlp);
+		lpfc_els_rcv_rps(vport, elsiocb, ndlp);
 		if (newnode)
-			lpfc_drop_node(phba, ndlp);
+			lpfc_drop_node(vport, ndlp);
 		break;
 	case ELS_CMD_RPL:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV RPL:         did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvRPL++;
-		lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
+		lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
 		if (newnode)
-			lpfc_drop_node(phba, ndlp);
+			lpfc_drop_node(vport, ndlp);
 		break;
 	case ELS_CMD_RNID:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV RNID:        did:x%x/ste:x%x flg:x%x",
+			did, vport->port_state, ndlp->nlp_flag);
+
 		phba->fc_stat.elsRcvRNID++;
-		lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
+		lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
 		if (newnode)
-			lpfc_drop_node(phba, ndlp);
+			lpfc_drop_node(vport, ndlp);
 		break;
 	default:
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+			"RCV ELS cmd:     cmd:x%x did:x%x/ste:x%x",
+			cmd, did, vport->port_state);
+
 		/* Unsupported ELS command, reject */
-		rjt_err = 1;
+		rjt_err = LSRJT_INVALID_CMD;
 
 		/* Unknown ELS command <elsCmd> received from NPORT <did> */
 		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-				"%d:0115 Unknown ELS command x%x received from "
-				"NPORT x%x\n", phba->brd_no, cmd, did);
+				"%d (%d):0115 Unknown ELS command x%x "
+				"received from NPORT x%x\n",
+				phba->brd_no, vport->vpi, cmd, did);
 		if (newnode)
-			lpfc_drop_node(phba, ndlp);
+			lpfc_drop_node(vport, ndlp);
 		break;
 	}
 
 	/* check if need to LS_RJT received ELS cmd */
 	if (rjt_err) {
-		stat.un.b.lsRjtRsvd0 = 0;
-		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+		memset(&stat, 0, sizeof(stat));
+		stat.un.b.lsRjtRsnCode = rjt_err;
 		stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
-		stat.un.b.vendorUnique = 0;
-		lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp);
+		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
+			NULL);
+		if (newnode)
+			lpfc_drop_node(vport, ndlp);
 	}
 
+	return;
+
+dropit:
+	lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0111 Dropping received ELS cmd "
+			"Data: x%x x%x x%x\n",
+			phba->brd_no, vport ? vport->vpi : 0xffff,
+			icmd->ulpStatus, icmd->un.ulpWord[4],
+			icmd->ulpTimeout);
+	phba->fc_stat.elsRcvDrop++;
+}
+
+static struct lpfc_vport *
+lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
+{
+	struct lpfc_vport *vport;
+
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		if (vport->vpi == vpi)
+			return vport;
+	}
+	return NULL;
+}
+
+void
+lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+		     struct lpfc_iocbq *elsiocb)
+{
+	struct lpfc_vport *vport = phba->pport;
+	IOCB_t *icmd = &elsiocb->iocb;
+	dma_addr_t paddr;
+	struct lpfc_dmabuf *bdeBuf1 = elsiocb->context2;
+	struct lpfc_dmabuf *bdeBuf2 = elsiocb->context3;
+
+	elsiocb->context2 = NULL;
+	elsiocb->context3 = NULL;
+
+	if (icmd->ulpStatus == IOSTAT_NEED_BUFFER) {
+		lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
+	} else if (icmd->ulpStatus == IOSTAT_LOCAL_REJECT &&
+	    (icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING) {
+		phba->fc_stat.NoRcvBuf++;
+		/* Not enough posted buffers; Try posting more buffers */
+		if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
+			lpfc_post_buffer(phba, pring, 0, 1);
+		return;
+	}
+
+	if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+	    (icmd->ulpCommand == CMD_IOCB_RCV_ELS64_CX ||
+	     icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
+		if (icmd->unsli3.rcvsli3.vpi == 0xffff)
+			vport = phba->pport;
+		else {
+			uint16_t vpi = icmd->unsli3.rcvsli3.vpi;
+			vport = lpfc_find_vport_by_vpid(phba, vpi);
+		}
+	}
+				/* If there are no BDEs associated
+				 * with this IOCB, there is nothing to do.
+				 */
+	if (icmd->ulpBdeCount == 0)
+		return;
+
+				/* type of ELS cmd is first 32bit word
+				 * in packet
+				 */
+	if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+		elsiocb->context2 = bdeBuf1;
+	} else {
+		paddr = getPaddr(icmd->un.cont64[0].addrHigh,
+				 icmd->un.cont64[0].addrLow);
+		elsiocb->context2 = lpfc_sli_ringpostbuf_get(phba, pring,
+							     paddr);
+	}
+
+	lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
+	/*
+	 * The different unsolicited event handlers would tell us
+	 * if they are done with "mp" by setting context2 to NULL.
+	 */
 	lpfc_nlp_put(elsiocb->context1);
 	elsiocb->context1 = NULL;
 	if (elsiocb->context2) {
-		lpfc_mbuf_free(phba, mp->virt, mp->phys);
-		kfree(mp);
+		lpfc_in_buf_free(phba, (struct lpfc_dmabuf *)elsiocb->context2);
+		elsiocb->context2 = NULL;
 	}
-dropit:
-	/* check if need to drop received ELS cmd */
-	if (drop_cmd == 1) {
+
+	/* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */
+	if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) &&
+	    icmd->ulpBdeCount == 2) {
+		elsiocb->context2 = bdeBuf2;
+		lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
+		/* free mp if we are done with it */
+		if (elsiocb->context2) {
+			lpfc_in_buf_free(phba, elsiocb->context2);
+			elsiocb->context2 = NULL;
+		}
+	}
+}
+
+void
+lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+{
+	struct lpfc_nodelist *ndlp, *ndlp_fdmi;
+
+	ndlp = lpfc_findnode_did(vport, NameServer_DID);
+	if (!ndlp) {
+		ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+		if (!ndlp) {
+			if (phba->fc_topology == TOPOLOGY_LOOP) {
+				lpfc_disc_start(vport);
+				return;
+			}
+			lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+			lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+				"%d (%d):0251 NameServer login: no memory\n",
+				phba->brd_no, vport->vpi);
+			return;
+		}
+		lpfc_nlp_init(vport, ndlp, NameServer_DID);
+		ndlp->nlp_type |= NLP_FABRIC;
+	}
+
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+
+	if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) {
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
 		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-				"%d:0111 Dropping received ELS cmd "
-				"Data: x%x x%x x%x\n", phba->brd_no,
-				icmd->ulpStatus, icmd->un.ulpWord[4],
-				icmd->ulpTimeout);
-		phba->fc_stat.elsRcvDrop++;
+			"%d (%d):0252 Cannot issue NameServer login\n",
+			phba->brd_no, vport->vpi);
+		return;
+	}
+
+	if (phba->cfg_fdmi_on) {
+		ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
+					  GFP_KERNEL);
+		if (ndlp_fdmi) {
+			lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
+			ndlp_fdmi->nlp_type |= NLP_FABRIC;
+			ndlp_fdmi->nlp_state =
+				NLP_STE_PLOGI_ISSUE;
+			lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
+					     0);
+		}
 	}
 	return;
 }
+
+static void
+lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+{
+	struct lpfc_vport *vport = pmb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+	MAILBOX_t *mb = &pmb->mb;
+
+	vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+	lpfc_nlp_put(ndlp);
+
+	if (mb->mbxStatus) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+				"%d (%d):0915 Register VPI failed: 0x%x\n",
+				phba->brd_no, vport->vpi, mb->mbxStatus);
+
+		switch (mb->mbxStatus) {
+		case 0x11:	/* unsupported feature */
+		case 0x9603:	/* max_vpi exceeded */
+			/* giving up on vport registration */
+			lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+			spin_lock_irq(shost->host_lock);
+			vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+			spin_unlock_irq(shost->host_lock);
+			lpfc_can_disctmo(vport);
+			break;
+		default:
+			/* Try to recover from this error */
+			lpfc_mbx_unreg_vpi(vport);
+			vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+			lpfc_initial_fdisc(vport);
+			break;
+		}
+
+	} else {
+		if (vport == phba->pport)
+			lpfc_issue_fabric_reglogin(vport);
+		else
+			lpfc_do_scr_ns_plogi(phba, vport);
+	}
+	mempool_free(pmb, phba->mbox_mem_pool);
+	return;
+}
+
+void
+lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
+			struct lpfc_nodelist *ndlp)
+{
+	LPFC_MBOXQ_t *mbox;
+
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (mbox) {
+		lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, mbox);
+		mbox->vport = vport;
+		mbox->context2 = lpfc_nlp_get(ndlp);
+		mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport;
+		if (lpfc_sli_issue_mbox(phba, mbox,
+					MBX_NOWAIT | MBX_STOP_IOCB)
+		    == MBX_NOT_FINISHED) {
+			mempool_free(mbox, phba->mbox_mem_pool);
+			vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+
+			lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+
+			lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+				"%d (%d):0253 Register VPI: Cannot send mbox\n",
+				phba->brd_no, vport->vpi);
+		}
+	} else {
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+
+		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+			"%d (%d):0254 Register VPI: no memory\n",
+			phba->brd_no, vport->vpi);
+
+		vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+		lpfc_nlp_put(ndlp);
+	}
+}
+
+static void
+lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		    struct lpfc_iocbq *rspiocb)
+{
+	struct lpfc_vport *vport = cmdiocb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+	struct lpfc_nodelist *np;
+	struct lpfc_nodelist *next_np;
+	IOCB_t *irsp = &rspiocb->iocb;
+	struct lpfc_iocbq *piocb;
+
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+		"%d (%d):0123 FDISC completes. x%x/x%x prevDID: x%x\n",
+		phba->brd_no, vport->vpi,
+		irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
+
+	/* Since all FDISCs are being single threaded, we
+	 * must reset the discovery timer for ALL vports
+	 * waiting to send FDISC when one completes.
+	 */
+	list_for_each_entry(piocb, &phba->fabric_iocb_list, list) {
+		lpfc_set_disctmo(piocb->vport);
+	}
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"FDISC cmpl:      status:x%x/x%x prevdid:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
+
+	if (irsp->ulpStatus) {
+		/* Check for retry */
+		if (lpfc_els_retry(phba, cmdiocb, rspiocb))
+			goto out;
+
+		/* FDISC failed */
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0124 FDISC failed. (%d/%d)\n",
+			phba->brd_no, vport->vpi,
+			irsp->ulpStatus, irsp->un.ulpWord[4]);
+
+		if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
+			lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+
+		lpfc_nlp_put(ndlp);
+		/* giving up on FDISC. Cancel discovery timer */
+		lpfc_can_disctmo(vport);
+	} else {
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag |= FC_FABRIC;
+		if (vport->phba->fc_topology == TOPOLOGY_LOOP)
+			vport->fc_flag |=  FC_PUBLIC_LOOP;
+		spin_unlock_irq(shost->host_lock);
+
+		vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
+		lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
+		if ((vport->fc_prevDID != vport->fc_myDID) &&
+			!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
+			/* If our NportID changed, we need to ensure all
+			 * remaining NPORTs get unreg_login'ed so we can
+			 * issue unreg_vpi.
+			 */
+			list_for_each_entry_safe(np, next_np,
+				&vport->fc_nodes, nlp_listp) {
+				if (np->nlp_state != NLP_STE_NPR_NODE
+				   || !(np->nlp_flag & NLP_NPR_ADISC))
+					continue;
+				spin_lock_irq(shost->host_lock);
+				np->nlp_flag &= ~NLP_NPR_ADISC;
+				spin_unlock_irq(shost->host_lock);
+				lpfc_unreg_rpi(vport, np);
+			}
+			lpfc_mbx_unreg_vpi(vport);
+			vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+		}
+
+		if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
+			lpfc_register_new_vport(phba, vport, ndlp);
+		else
+			lpfc_do_scr_ns_plogi(phba, vport);
+
+		lpfc_nlp_put(ndlp); /* Free Fabric ndlp for vports */
+	}
+
+out:
+	lpfc_els_free_iocb(phba, cmdiocb);
+}
+
+int
+lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+		     uint8_t retry)
+{
+	struct lpfc_hba *phba = vport->phba;
+	IOCB_t *icmd;
+	struct lpfc_iocbq *elsiocb;
+	struct serv_parm *sp;
+	uint8_t *pcmd;
+	uint16_t cmdsize;
+	int did = ndlp->nlp_DID;
+	int rc;
+
+	cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
+				     ELS_CMD_FDISC);
+	if (!elsiocb) {
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0255 Issue FDISC: no IOCB\n",
+			phba->brd_no, vport->vpi);
+		return 1;
+	}
+
+	icmd = &elsiocb->iocb;
+	icmd->un.elsreq64.myID = 0;
+	icmd->un.elsreq64.fl = 1;
+
+	/* For FDISC, Let FDISC rsp set the NPortID for this VPI */
+	icmd->ulpCt_h = 1;
+	icmd->ulpCt_l = 0;
+
+	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+	*((uint32_t *) (pcmd)) = ELS_CMD_FDISC;
+	pcmd += sizeof(uint32_t); /* CSP Word 1 */
+	memcpy(pcmd, &vport->phba->pport->fc_sparam, sizeof(struct serv_parm));
+	sp = (struct serv_parm *) pcmd;
+	/* Setup CSPs accordingly for Fabric */
+	sp->cmn.e_d_tov = 0;
+	sp->cmn.w2.r_a_tov = 0;
+	sp->cls1.classValid = 0;
+	sp->cls2.seqDelivery = 1;
+	sp->cls3.seqDelivery = 1;
+
+	pcmd += sizeof(uint32_t); /* CSP Word 2 */
+	pcmd += sizeof(uint32_t); /* CSP Word 3 */
+	pcmd += sizeof(uint32_t); /* CSP Word 4 */
+	pcmd += sizeof(uint32_t); /* Port Name */
+	memcpy(pcmd, &vport->fc_portname, 8);
+	pcmd += sizeof(uint32_t); /* Node Name */
+	pcmd += sizeof(uint32_t); /* Node Name */
+	memcpy(pcmd, &vport->fc_nodename, 8);
+
+	lpfc_set_disctmo(vport);
+
+	phba->fc_stat.elsXmitFDISC++;
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue FDISC:     did:x%x",
+		did, 0, 0);
+
+	rc = lpfc_issue_fabric_iocb(phba, elsiocb);
+	if (rc == IOCB_ERROR) {
+		lpfc_els_free_iocb(phba, elsiocb);
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0256 Issue FDISC: Cannot send IOCB\n",
+			phba->brd_no, vport->vpi);
+
+		return 1;
+	}
+	lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING);
+	vport->port_state = LPFC_FDISC;
+	return 0;
+}
+
+static void
+lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
+{
+	struct lpfc_vport *vport = cmdiocb->vport;
+	IOCB_t *irsp;
+
+	irsp = &rspiocb->iocb;
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"LOGO npiv cmpl:  status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID);
+
+	lpfc_els_free_iocb(phba, cmdiocb);
+	vport->unreg_vpi_cmpl = VPORT_ERROR;
+}
+
+int
+lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+	struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+	IOCB_t *icmd;
+	struct lpfc_iocbq *elsiocb;
+	uint8_t *pcmd;
+	uint16_t cmdsize;
+
+	cmdsize = 2 * sizeof(uint32_t) + sizeof(struct lpfc_name);
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, ndlp->nlp_DID,
+				     ELS_CMD_LOGO);
+	if (!elsiocb)
+		return 1;
+
+	icmd = &elsiocb->iocb;
+	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+	*((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
+	pcmd += sizeof(uint32_t);
+
+	/* Fill in LOGO payload */
+	*((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
+	pcmd += sizeof(uint32_t);
+	memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue LOGO npiv  did:x%x flg:x%x",
+		ndlp->nlp_DID, ndlp->nlp_flag, 0);
+
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
+	spin_lock_irq(shost->host_lock);
+	ndlp->nlp_flag |= NLP_LOGO_SND;
+	spin_unlock_irq(shost->host_lock);
+	if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+		spin_lock_irq(shost->host_lock);
+		ndlp->nlp_flag &= ~NLP_LOGO_SND;
+		spin_unlock_irq(shost->host_lock);
+		lpfc_els_free_iocb(phba, elsiocb);
+		return 1;
+	}
+	return 0;
+}
+
+void
+lpfc_fabric_block_timeout(unsigned long ptr)
+{
+	struct lpfc_hba  *phba = (struct lpfc_hba *) ptr;
+	unsigned long iflags;
+	uint32_t tmo_posted;
+	spin_lock_irqsave(&phba->pport->work_port_lock, iflags);
+	tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO;
+	if (!tmo_posted)
+		phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO;
+	spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags);
+
+	if (!tmo_posted) {
+		spin_lock_irqsave(&phba->hbalock, iflags);
+		if (phba->work_wait)
+			lpfc_worker_wake_up(phba);
+		spin_unlock_irqrestore(&phba->hbalock, iflags);
+	}
+}
+
+static void
+lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
+{
+	struct lpfc_iocbq *iocb;
+	unsigned long iflags;
+	int ret;
+	struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+	IOCB_t *cmd;
+
+repeat:
+	iocb = NULL;
+	spin_lock_irqsave(&phba->hbalock, iflags);
+				/* Post any pending iocb to the SLI layer */
+	if (atomic_read(&phba->fabric_iocb_count) == 0) {
+		list_remove_head(&phba->fabric_iocb_list, iocb, typeof(*iocb),
+				 list);
+		if (iocb)
+			atomic_inc(&phba->fabric_iocb_count);
+	}
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	if (iocb) {
+		iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
+		iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
+		iocb->iocb_flag |= LPFC_IO_FABRIC;
+
+		lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
+			"Fabric sched1:   ste:x%x",
+			iocb->vport->port_state, 0, 0);
+
+		ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
+
+		if (ret == IOCB_ERROR) {
+			iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
+			iocb->fabric_iocb_cmpl = NULL;
+			iocb->iocb_flag &= ~LPFC_IO_FABRIC;
+			cmd = &iocb->iocb;
+			cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+			cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+			iocb->iocb_cmpl(phba, iocb, iocb);
+
+			atomic_dec(&phba->fabric_iocb_count);
+			goto repeat;
+		}
+	}
+
+	return;
+}
+
+void
+lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
+{
+	clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+
+	lpfc_resume_fabric_iocbs(phba);
+	return;
+}
+
+static void
+lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
+{
+	int blocked;
+
+	blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+				/* Start a timer to unblock fabric
+				 * iocbs after 100ms
+				 */
+	if (!blocked)
+		mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 );
+
+	return;
+}
+
+static void
+lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+	struct lpfc_iocbq *rspiocb)
+{
+	struct ls_rjt stat;
+
+	if ((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC)
+		BUG();
+
+	switch (rspiocb->iocb.ulpStatus) {
+		case IOSTAT_NPORT_RJT:
+		case IOSTAT_FABRIC_RJT:
+			if (rspiocb->iocb.un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
+				lpfc_block_fabric_iocbs(phba);
+			}
+			break;
+
+		case IOSTAT_NPORT_BSY:
+		case IOSTAT_FABRIC_BSY:
+			lpfc_block_fabric_iocbs(phba);
+			break;
+
+		case IOSTAT_LS_RJT:
+			stat.un.lsRjtError =
+				be32_to_cpu(rspiocb->iocb.un.ulpWord[4]);
+			if ((stat.un.b.lsRjtRsnCode == LSRJT_UNABLE_TPC) ||
+				(stat.un.b.lsRjtRsnCode == LSRJT_LOGICAL_BSY))
+				lpfc_block_fabric_iocbs(phba);
+			break;
+	}
+
+	if (atomic_read(&phba->fabric_iocb_count) == 0)
+		BUG();
+
+	cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl;
+	cmdiocb->fabric_iocb_cmpl = NULL;
+	cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC;
+	cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb);
+
+	atomic_dec(&phba->fabric_iocb_count);
+	if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) {
+				/* Post any pending iocbs to HBA */
+		    lpfc_resume_fabric_iocbs(phba);
+	}
+}
+
+int
+lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
+{
+	unsigned long iflags;
+	struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+	int ready;
+	int ret;
+
+	if (atomic_read(&phba->fabric_iocb_count) > 1)
+		BUG();
+
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	ready = atomic_read(&phba->fabric_iocb_count) == 0 &&
+		!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	if (ready) {
+		iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
+		iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
+		iocb->iocb_flag |= LPFC_IO_FABRIC;
+
+		lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
+			"Fabric sched2:   ste:x%x",
+			iocb->vport->port_state, 0, 0);
+
+		atomic_inc(&phba->fabric_iocb_count);
+		ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
+
+		if (ret == IOCB_ERROR) {
+			iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
+			iocb->fabric_iocb_cmpl = NULL;
+			iocb->iocb_flag &= ~LPFC_IO_FABRIC;
+			atomic_dec(&phba->fabric_iocb_count);
+		}
+	} else {
+		spin_lock_irqsave(&phba->hbalock, iflags);
+		list_add_tail(&iocb->list, &phba->fabric_iocb_list);
+		spin_unlock_irqrestore(&phba->hbalock, iflags);
+		ret = IOCB_SUCCESS;
+	}
+	return ret;
+}
+
+
+void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
+{
+	LIST_HEAD(completions);
+	struct lpfc_hba  *phba = vport->phba;
+	struct lpfc_iocbq *tmp_iocb, *piocb;
+	IOCB_t *cmd;
+
+	spin_lock_irq(&phba->hbalock);
+	list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+				 list) {
+
+		if (piocb->vport != vport)
+			continue;
+
+		list_move_tail(&piocb->list, &completions);
+	}
+	spin_unlock_irq(&phba->hbalock);
+
+	while (!list_empty(&completions)) {
+		piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+		list_del_init(&piocb->list);
+
+		cmd = &piocb->iocb;
+		cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+		cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+		(piocb->iocb_cmpl) (phba, piocb, piocb);
+	}
+}
+
+void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
+{
+	LIST_HEAD(completions);
+	struct lpfc_hba  *phba = ndlp->vport->phba;
+	struct lpfc_iocbq *tmp_iocb, *piocb;
+	struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+	IOCB_t *cmd;
+
+	spin_lock_irq(&phba->hbalock);
+	list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+				 list) {
+		if ((lpfc_check_sli_ndlp(phba, pring, piocb, ndlp))) {
+
+			list_move_tail(&piocb->list, &completions);
+		}
+	}
+	spin_unlock_irq(&phba->hbalock);
+
+	while (!list_empty(&completions)) {
+		piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+		list_del_init(&piocb->list);
+
+		cmd = &piocb->iocb;
+		cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+		cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+		(piocb->iocb_cmpl) (phba, piocb, piocb);
+	}
+}
+
+void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
+{
+	LIST_HEAD(completions);
+	struct lpfc_iocbq *piocb;
+	IOCB_t *cmd;
+
+	spin_lock_irq(&phba->hbalock);
+	list_splice_init(&phba->fabric_iocb_list, &completions);
+	spin_unlock_irq(&phba->hbalock);
+
+	while (!list_empty(&completions)) {
+		piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+		list_del_init(&piocb->list);
+
+		cmd = &piocb->iocb;
+		cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+		cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+		(piocb->iocb_cmpl) (phba, piocb, piocb);
+	}
+}
+
+
+void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
+{
+	LIST_HEAD(completions);
+	struct lpfc_iocbq *tmp_iocb, *piocb;
+	IOCB_t *cmd;
+	struct lpfc_nodelist *ndlp;
+
+	spin_lock_irq(&phba->hbalock);
+	list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+				 list) {
+
+		cmd = &piocb->iocb;
+		ndlp = (struct lpfc_nodelist *) piocb->context1;
+		if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
+		    ndlp != NULL &&
+		    ndlp->nlp_DID == Fabric_DID)
+			list_move_tail(&piocb->list, &completions);
+	}
+	spin_unlock_irq(&phba->hbalock);
+
+	while (!list_empty(&completions)) {
+		piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+		list_del_init(&piocb->list);
+
+		cmd = &piocb->iocb;
+		cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+		cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+		(piocb->iocb_cmpl) (phba, piocb, piocb);
+	}
+}
+
+
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 61caa8d..f2f4639 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -36,6 +36,8 @@
 #include "lpfc.h"
 #include "lpfc_logmsg.h"
 #include "lpfc_crtn.h"
+#include "lpfc_vport.h"
+#include "lpfc_debugfs.h"
 
 /* AlpaArray for assignment of scsid for scan-down and bind_method */
 static uint8_t lpfcAlpaArray[] = {
@@ -54,7 +56,7 @@
 	0x10, 0x0F, 0x08, 0x04, 0x02, 0x01
 };
 
-static void lpfc_disc_timeout_handler(struct lpfc_hba *);
+static void lpfc_disc_timeout_handler(struct lpfc_vport *);
 
 void
 lpfc_terminate_rport_io(struct fc_rport *rport)
@@ -74,14 +76,16 @@
 		return;
 	}
 
-	phba = ndlp->nlp_phba;
+	phba  = ndlp->vport->phba;
 
-	spin_lock_irq(phba->host->host_lock);
+	lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
+		"rport terminate: sid:x%x did:x%x flg:x%x",
+		ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
+
 	if (ndlp->nlp_sid != NLP_NO_SID) {
 		lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
 			ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
 	}
-	spin_unlock_irq(phba->host->host_lock);
 
 	return;
 }
@@ -94,105 +98,213 @@
 {
 	struct lpfc_rport_data *rdata;
 	struct lpfc_nodelist * ndlp;
-	uint8_t *name;
-	int warn_on = 0;
-	struct lpfc_hba *phba;
+	struct lpfc_vport *vport;
+	struct lpfc_hba   *phba;
+	struct completion devloss_compl;
+	struct lpfc_work_evt *evtp;
 
 	rdata = rport->dd_data;
 	ndlp = rdata->pnode;
 
 	if (!ndlp) {
-		if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+		if (rport->scsi_target_id != -1) {
 			printk(KERN_ERR "Cannot find remote node"
-			" for rport in dev_loss_tmo_callbk x%x\n",
-			rport->port_id);
+				" for rport in dev_loss_tmo_callbk x%x\n",
+				rport->port_id);
+		}
 		return;
 	}
 
-	if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+	vport = ndlp->vport;
+	phba  = vport->phba;
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+		"rport devlosscb: sid:x%x did:x%x flg:x%x",
+		ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
+
+	init_completion(&devloss_compl);
+	evtp = &ndlp->dev_loss_evt;
+
+	if (!list_empty(&evtp->evt_listp))
 		return;
 
-	name = (uint8_t *)&ndlp->nlp_portname;
-	phba = ndlp->nlp_phba;
+	spin_lock_irq(&phba->hbalock);
+	evtp->evt_arg1  = ndlp;
+	evtp->evt_arg2  = &devloss_compl;
+	evtp->evt       = LPFC_EVT_DEV_LOSS;
+	list_add_tail(&evtp->evt_listp, &phba->work_list);
+	if (phba->work_wait)
+		wake_up(phba->work_wait);
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
+
+	wait_for_completion(&devloss_compl);
+
+	return;
+}
+
+/*
+ * This function is called from the worker thread when dev_loss_tmo
+ * expire.
+ */
+void
+lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
+{
+	struct lpfc_rport_data *rdata;
+	struct fc_rport   *rport;
+	struct lpfc_vport *vport;
+	struct lpfc_hba   *phba;
+	uint8_t *name;
+	int warn_on = 0;
+
+	rport = ndlp->rport;
+
+	if (!rport)
+		return;
+
+	rdata = rport->dd_data;
+	name = (uint8_t *) &ndlp->nlp_portname;
+	vport = ndlp->vport;
+	phba  = vport->phba;
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+		"rport devlosstmo:did:x%x type:x%x id:x%x",
+		ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id);
+
+	if (!(vport->load_flag & FC_UNLOADING) &&
+	    ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+		return;
+
+	if (ndlp->nlp_type & NLP_FABRIC) {
+		int  put_node;
+		int  put_rport;
+
+		/* We will clean up these Nodes in linkup */
+		put_node = rdata->pnode != NULL;
+		put_rport = ndlp->rport != NULL;
+		rdata->pnode = NULL;
+		ndlp->rport = NULL;
+		if (put_node)
+			lpfc_nlp_put(ndlp);
+		if (put_rport)
+			put_device(&rport->dev);
+		return;
+	}
 
 	if (ndlp->nlp_sid != NLP_NO_SID) {
 		warn_on = 1;
 		/* flush the target */
 		lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-			ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
+				    ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
 	}
-	if (phba->fc_flag & FC_UNLOADING)
+	if (vport->load_flag & FC_UNLOADING)
 		warn_on = 0;
 
-	spin_unlock_irq(phba->host->host_lock);
-
 	if (warn_on) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-				"%d:0203 Devloss timeout on "
+				"%d (%d):0203 Devloss timeout on "
 				"WWPN %x:%x:%x:%x:%x:%x:%x:%x "
 				"NPort x%x Data: x%x x%x x%x\n",
-				phba->brd_no,
+				phba->brd_no, vport->vpi,
 				*name, *(name+1), *(name+2), *(name+3),
 				*(name+4), *(name+5), *(name+6), *(name+7),
 				ndlp->nlp_DID, ndlp->nlp_flag,
 				ndlp->nlp_state, ndlp->nlp_rpi);
 	} else {
 		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-				"%d:0204 Devloss timeout on "
+				"%d (%d):0204 Devloss timeout on "
 				"WWPN %x:%x:%x:%x:%x:%x:%x:%x "
 				"NPort x%x Data: x%x x%x x%x\n",
-				phba->brd_no,
+				phba->brd_no, vport->vpi,
 				*name, *(name+1), *(name+2), *(name+3),
 				*(name+4), *(name+5), *(name+6), *(name+7),
 				ndlp->nlp_DID, ndlp->nlp_flag,
 				ndlp->nlp_state, ndlp->nlp_rpi);
 	}
 
-	if (!(phba->fc_flag & FC_UNLOADING) &&
+	if (!(vport->load_flag & FC_UNLOADING) &&
 	    !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
 	    !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
 	    (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
-		lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
+		lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
 	else {
+		int  put_node;
+		int  put_rport;
+
+		put_node = rdata->pnode != NULL;
+		put_rport = ndlp->rport != NULL;
 		rdata->pnode = NULL;
 		ndlp->rport = NULL;
-		lpfc_nlp_put(ndlp);
-		put_device(&rport->dev);
+		if (put_node)
+			lpfc_nlp_put(ndlp);
+		if (put_rport)
+			put_device(&rport->dev);
 	}
+}
 
+
+void
+lpfc_worker_wake_up(struct lpfc_hba *phba)
+{
+	wake_up(phba->work_wait);
 	return;
 }
 
 static void
-lpfc_work_list_done(struct lpfc_hba * phba)
+lpfc_work_list_done(struct lpfc_hba *phba)
 {
 	struct lpfc_work_evt  *evtp = NULL;
 	struct lpfc_nodelist  *ndlp;
+	struct lpfc_vport     *vport;
 	int free_evt;
 
-	spin_lock_irq(phba->host->host_lock);
-	while(!list_empty(&phba->work_list)) {
+	spin_lock_irq(&phba->hbalock);
+	while (!list_empty(&phba->work_list)) {
 		list_remove_head((&phba->work_list), evtp, typeof(*evtp),
 				 evt_listp);
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 		free_evt = 1;
 		switch (evtp->evt) {
+		case LPFC_EVT_DEV_LOSS_DELAY:
+			free_evt = 0; /* evt is part of ndlp */
+			ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
+			vport = ndlp->vport;
+			if (!vport)
+				break;
+
+			lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+				"rport devlossdly:did:x%x flg:x%x",
+				ndlp->nlp_DID, ndlp->nlp_flag, 0);
+
+			if (!(vport->load_flag & FC_UNLOADING) &&
+			    !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
+			    !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
+				lpfc_disc_state_machine(vport, ndlp, NULL,
+					NLP_EVT_DEVICE_RM);
+			}
+			break;
 		case LPFC_EVT_ELS_RETRY:
-			ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
+			ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
 			lpfc_els_retry_delay_handler(ndlp);
+			free_evt = 0; /* evt is part of ndlp */
+			break;
+		case LPFC_EVT_DEV_LOSS:
+			ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
+			lpfc_nlp_get(ndlp);
+			lpfc_dev_loss_tmo_handler(ndlp);
 			free_evt = 0;
+			complete((struct completion *)(evtp->evt_arg2));
+			lpfc_nlp_put(ndlp);
 			break;
 		case LPFC_EVT_ONLINE:
-			if (phba->hba_state < LPFC_LINK_DOWN)
-				*(int *)(evtp->evt_arg1)  = lpfc_online(phba);
+			if (phba->link_state < LPFC_LINK_DOWN)
+				*(int *) (evtp->evt_arg1) = lpfc_online(phba);
 			else
-				*(int *)(evtp->evt_arg1)  = 0;
+				*(int *) (evtp->evt_arg1) = 0;
 			complete((struct completion *)(evtp->evt_arg2));
 			break;
 		case LPFC_EVT_OFFLINE_PREP:
-			if (phba->hba_state >= LPFC_LINK_DOWN)
+			if (phba->link_state >= LPFC_LINK_DOWN)
 				lpfc_offline_prep(phba);
 			*(int *)(evtp->evt_arg1) = 0;
 			complete((struct completion *)(evtp->evt_arg2));
@@ -218,33 +330,31 @@
 		case LPFC_EVT_KILL:
 			lpfc_offline(phba);
 			*(int *)(evtp->evt_arg1)
-				= (phba->stopped) ? 0 : lpfc_sli_brdkill(phba);
+				= (phba->pport->stopped)
+				        ? 0 : lpfc_sli_brdkill(phba);
 			lpfc_unblock_mgmt_io(phba);
 			complete((struct completion *)(evtp->evt_arg2));
 			break;
 		}
 		if (free_evt)
 			kfree(evtp);
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(&phba->hbalock);
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 }
 
-static void
-lpfc_work_done(struct lpfc_hba * phba)
+void
+lpfc_work_done(struct lpfc_hba *phba)
 {
 	struct lpfc_sli_ring *pring;
-	int i;
-	uint32_t ha_copy;
-	uint32_t control;
-	uint32_t work_hba_events;
+	uint32_t ha_copy, status, control, work_port_events;
+	struct lpfc_vport *vport;
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	ha_copy = phba->work_ha;
 	phba->work_ha = 0;
-	work_hba_events=phba->work_hba_events;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	if (ha_copy & HA_ERATT)
 		lpfc_handle_eratt(phba);
@@ -255,66 +365,111 @@
 	if (ha_copy & HA_LATT)
 		lpfc_handle_latt(phba);
 
-	if (work_hba_events & WORKER_DISC_TMO)
-		lpfc_disc_timeout_handler(phba);
+	spin_lock_irq(&phba->hbalock);
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 
-	if (work_hba_events & WORKER_ELS_TMO)
-		lpfc_els_timeout_handler(phba);
+		if (!scsi_host_get(shost)) {
+			continue;
+		}
+		spin_unlock_irq(&phba->hbalock);
+		work_port_events = vport->work_port_events;
 
-	if (work_hba_events & WORKER_MBOX_TMO)
-		lpfc_mbox_timeout_handler(phba);
+		if (work_port_events & WORKER_DISC_TMO)
+			lpfc_disc_timeout_handler(vport);
 
-	if (work_hba_events & WORKER_FDMI_TMO)
-		lpfc_fdmi_tmo_handler(phba);
+		if (work_port_events & WORKER_ELS_TMO)
+			lpfc_els_timeout_handler(vport);
 
-	spin_lock_irq(phba->host->host_lock);
-	phba->work_hba_events &= ~work_hba_events;
-	spin_unlock_irq(phba->host->host_lock);
+		if (work_port_events & WORKER_HB_TMO)
+			lpfc_hb_timeout_handler(phba);
 
-	for (i = 0; i < phba->sli.num_rings; i++, ha_copy >>= 4) {
-		pring = &phba->sli.ring[i];
-		if ((ha_copy & HA_RXATT)
-		    || (pring->flag & LPFC_DEFERRED_RING_EVENT)) {
-			if (pring->flag & LPFC_STOP_IOCB_MASK) {
-				pring->flag |= LPFC_DEFERRED_RING_EVENT;
-			} else {
-				lpfc_sli_handle_slow_ring_event(phba, pring,
-								(ha_copy &
-								 HA_RXMASK));
-				pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
-			}
-			/*
-			 * Turn on Ring interrupts
-			 */
-			spin_lock_irq(phba->host->host_lock);
-			control = readl(phba->HCregaddr);
-			control |= (HC_R0INT_ENA << i);
+		if (work_port_events & WORKER_MBOX_TMO)
+			lpfc_mbox_timeout_handler(phba);
+
+		if (work_port_events & WORKER_FABRIC_BLOCK_TMO)
+			lpfc_unblock_fabric_iocbs(phba);
+
+		if (work_port_events & WORKER_FDMI_TMO)
+			lpfc_fdmi_timeout_handler(vport);
+
+		if (work_port_events & WORKER_RAMP_DOWN_QUEUE)
+			lpfc_ramp_down_queue_handler(phba);
+
+		if (work_port_events & WORKER_RAMP_UP_QUEUE)
+			lpfc_ramp_up_queue_handler(phba);
+
+		spin_lock_irq(&vport->work_port_lock);
+		vport->work_port_events &= ~work_port_events;
+		spin_unlock_irq(&vport->work_port_lock);
+		scsi_host_put(shost);
+		spin_lock_irq(&phba->hbalock);
+	}
+	spin_unlock_irq(&phba->hbalock);
+
+	pring = &phba->sli.ring[LPFC_ELS_RING];
+	status = (ha_copy & (HA_RXMASK  << (4*LPFC_ELS_RING)));
+	status >>= (4*LPFC_ELS_RING);
+	if ((status & HA_RXMASK)
+		|| (pring->flag & LPFC_DEFERRED_RING_EVENT)) {
+		if (pring->flag & LPFC_STOP_IOCB_MASK) {
+			pring->flag |= LPFC_DEFERRED_RING_EVENT;
+		} else {
+			lpfc_sli_handle_slow_ring_event(phba, pring,
+							(status &
+							 HA_RXMASK));
+			pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
+		}
+		/*
+		 * Turn on Ring interrupts
+		 */
+		spin_lock_irq(&phba->hbalock);
+		control = readl(phba->HCregaddr);
+		if (!(control & (HC_R0INT_ENA << LPFC_ELS_RING))) {
+			control |= (HC_R0INT_ENA << LPFC_ELS_RING);
 			writel(control, phba->HCregaddr);
 			readl(phba->HCregaddr); /* flush */
-			spin_unlock_irq(phba->host->host_lock);
 		}
+		spin_unlock_irq(&phba->hbalock);
 	}
-
-	lpfc_work_list_done (phba);
-
+	lpfc_work_list_done(phba);
 }
 
 static int
-check_work_wait_done(struct lpfc_hba *phba) {
+check_work_wait_done(struct lpfc_hba *phba)
+{
+	struct lpfc_vport *vport;
+	struct lpfc_sli_ring *pring;
+	int rc = 0;
 
-	spin_lock_irq(phba->host->host_lock);
-	if (phba->work_ha ||
-	    phba->work_hba_events ||
-	    (!list_empty(&phba->work_list)) ||
-	    kthread_should_stop()) {
-		spin_unlock_irq(phba->host->host_lock);
-		return 1;
-	} else {
-		spin_unlock_irq(phba->host->host_lock);
-		return 0;
+	spin_lock_irq(&phba->hbalock);
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		if (vport->work_port_events) {
+			rc = 1;
+			goto exit;
+		}
 	}
+
+	if (phba->work_ha || (!list_empty(&phba->work_list)) ||
+	    kthread_should_stop()) {
+		rc = 1;
+		goto exit;
+	}
+
+	pring = &phba->sli.ring[LPFC_ELS_RING];
+	if (pring->flag & LPFC_DEFERRED_RING_EVENT)
+		rc = 1;
+exit:
+	if (rc)
+		phba->work_found++;
+	else
+		phba->work_found = 0;
+
+	spin_unlock_irq(&phba->hbalock);
+	return rc;
 }
 
+
 int
 lpfc_do_work(void *p)
 {
@@ -324,11 +479,13 @@
 
 	set_user_nice(current, -20);
 	phba->work_wait = &work_waitq;
+	phba->work_found = 0;
 
 	while (1) {
 
 		rc = wait_event_interruptible(work_waitq,
-						check_work_wait_done(phba));
+					      check_work_wait_done(phba));
+
 		BUG_ON(rc);
 
 		if (kthread_should_stop())
@@ -336,6 +493,17 @@
 
 		lpfc_work_done(phba);
 
+		/* If there is alot of slow ring work, like during link up
+		 * check_work_wait_done() may cause this thread to not give
+		 * up the CPU for very long periods of time. This may cause
+		 * soft lockups or other problems. To avoid these situations
+		 * give up the CPU here after LPFC_MAX_WORKER_ITERATION
+		 * consecutive iterations.
+		 */
+		if (phba->work_found >= LPFC_MAX_WORKER_ITERATION) {
+			phba->work_found = 0;
+			schedule();
+		}
 	}
 	phba->work_wait = NULL;
 	return 0;
@@ -347,16 +515,17 @@
  * embedding it in the IOCB.
  */
 int
-lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
+lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2,
 		      uint32_t evt)
 {
 	struct lpfc_work_evt  *evtp;
+	unsigned long flags;
 
 	/*
 	 * All Mailbox completions and LPFC_ELS_RING rcv ring IOCB events will
 	 * be queued to worker thread for processing
 	 */
-	evtp = kmalloc(sizeof(struct lpfc_work_evt), GFP_KERNEL);
+	evtp = kmalloc(sizeof(struct lpfc_work_evt), GFP_ATOMIC);
 	if (!evtp)
 		return 0;
 
@@ -364,136 +533,210 @@
 	evtp->evt_arg2  = arg2;
 	evtp->evt       = evt;
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irqsave(&phba->hbalock, flags);
 	list_add_tail(&evtp->evt_listp, &phba->work_list);
 	if (phba->work_wait)
-		wake_up(phba->work_wait);
-	spin_unlock_irq(phba->host->host_lock);
+		lpfc_worker_wake_up(phba);
+	spin_unlock_irqrestore(&phba->hbalock, flags);
 
 	return 1;
 }
 
+void
+lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
+{
+	struct lpfc_hba  *phba = vport->phba;
+	struct lpfc_nodelist *ndlp, *next_ndlp;
+	int  rc;
+
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+			continue;
+
+		if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN)
+			lpfc_unreg_rpi(vport, ndlp);
+
+		/* Leave Fabric nodes alone on link down */
+		if (!remove && ndlp->nlp_type & NLP_FABRIC)
+			continue;
+		rc = lpfc_disc_state_machine(vport, ndlp, NULL,
+					     remove
+					     ? NLP_EVT_DEVICE_RM
+					     : NLP_EVT_DEVICE_RECOVERY);
+	}
+	if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
+		lpfc_mbx_unreg_vpi(vport);
+		vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+	}
+}
+
+static void
+lpfc_linkdown_port(struct lpfc_vport *vport)
+{
+	struct lpfc_nodelist *ndlp, *next_ndlp;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+
+	fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Link Down:       state:x%x rtry:x%x flg:x%x",
+		vport->port_state, vport->fc_ns_retry, vport->fc_flag);
+
+	/* Cleanup any outstanding RSCN activity */
+	lpfc_els_flush_rscn(vport);
+
+	/* Cleanup any outstanding ELS commands */
+	lpfc_els_flush_cmd(vport);
+
+	lpfc_cleanup_rpis(vport, 0);
+
+	/* free any ndlp's on unused list */
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
+				/* free any ndlp's in unused state */
+		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+			lpfc_drop_node(vport, ndlp);
+
+	/* Turn off discovery timer if its running */
+	lpfc_can_disctmo(vport);
+}
+
 int
 lpfc_linkdown(struct lpfc_hba *phba)
 {
-	struct lpfc_sli       *psli;
-	struct lpfc_nodelist  *ndlp, *next_ndlp;
+	struct lpfc_vport *vport = phba->pport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_vport *port_iterator;
 	LPFC_MBOXQ_t          *mb;
-	int                   rc;
 
-	psli = &phba->sli;
-	/* sysfs or selective reset may call this routine to clean up */
-	if (phba->hba_state >= LPFC_LINK_DOWN) {
-		if (phba->hba_state == LPFC_LINK_DOWN)
-			return 0;
-
-		spin_lock_irq(phba->host->host_lock);
-		phba->hba_state = LPFC_LINK_DOWN;
-		spin_unlock_irq(phba->host->host_lock);
+	if (phba->link_state == LPFC_LINK_DOWN) {
+		return 0;
 	}
+	spin_lock_irq(&phba->hbalock);
+	if (phba->link_state > LPFC_LINK_DOWN) {
+		phba->link_state = LPFC_LINK_DOWN;
+		phba->pport->fc_flag &= ~FC_LBIT;
+	}
+	spin_unlock_irq(&phba->hbalock);
 
-	fc_host_post_event(phba->host, fc_get_event_number(),
-			FCH_EVT_LINKDOWN, 0);
+	list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+
+				/* Issue a LINK DOWN event to all nodes */
+		lpfc_linkdown_port(port_iterator);
+	}
 
 	/* Clean up any firmware default rpi's */
-	if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
-		lpfc_unreg_did(phba, 0xffffffff, mb);
-		mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
+	mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (mb) {
+		lpfc_unreg_did(phba, 0xffff, 0xffffffff, mb);
+		mb->vport = vport;
+		mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 		if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
 		    == MBX_NOT_FINISHED) {
-			mempool_free( mb, phba->mbox_mem_pool);
+			mempool_free(mb, phba->mbox_mem_pool);
 		}
 	}
 
-	/* Cleanup any outstanding RSCN activity */
-	lpfc_els_flush_rscn(phba);
-
-	/* Cleanup any outstanding ELS commands */
-	lpfc_els_flush_cmd(phba);
-
-	/*
-	 * Issue a LINK DOWN event to all nodes.
-	 */
-	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
-				/* free any ndlp's on unused list */
-		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
-			lpfc_drop_node(phba, ndlp);
-		else		/* otherwise, force node recovery. */
-			rc = lpfc_disc_state_machine(phba, ndlp, NULL,
-						     NLP_EVT_DEVICE_RECOVERY);
-	}
-
 	/* Setup myDID for link up if we are in pt2pt mode */
-	if (phba->fc_flag & FC_PT2PT) {
-		phba->fc_myDID = 0;
-		if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
+	if (phba->pport->fc_flag & FC_PT2PT) {
+		phba->pport->fc_myDID = 0;
+		mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+		if (mb) {
 			lpfc_config_link(phba, mb);
-			mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
-			if (lpfc_sli_issue_mbox
-			    (phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
+			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			mb->vport = vport;
+			if (lpfc_sli_issue_mbox(phba, mb,
+						(MBX_NOWAIT | MBX_STOP_IOCB))
 			    == MBX_NOT_FINISHED) {
-				mempool_free( mb, phba->mbox_mem_pool);
+				mempool_free(mb, phba->mbox_mem_pool);
 			}
 		}
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
+		phba->pport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
+		spin_unlock_irq(shost->host_lock);
 	}
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag &= ~FC_LBIT;
-	spin_unlock_irq(phba->host->host_lock);
 
-	/* Turn off discovery timer if its running */
-	lpfc_can_disctmo(phba);
-
-	/* Must process IOCBs on all rings to handle ABORTed I/Os */
 	return 0;
 }
 
+static void
+lpfc_linkup_cleanup_nodes(struct lpfc_vport *vport)
+{
+	struct lpfc_nodelist *ndlp;
+
+	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+			continue;
+
+		if (ndlp->nlp_type & NLP_FABRIC) {
+				/* On Linkup its safe to clean up the ndlp
+				 * from Fabric connections.
+				 */
+			if (ndlp->nlp_DID != Fabric_DID)
+				lpfc_unreg_rpi(vport, ndlp);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+		} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
+				/* Fail outstanding IO now since device is
+				 * marked for PLOGI.
+				 */
+			lpfc_unreg_rpi(vport, ndlp);
+		}
+	}
+}
+
+static void
+lpfc_linkup_port(struct lpfc_vport *vport)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_nodelist *ndlp, *next_ndlp;
+	struct lpfc_hba  *phba = vport->phba;
+
+	if ((vport->load_flag & FC_UNLOADING) != 0)
+		return;
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Link Up:         top:x%x speed:x%x flg:x%x",
+		phba->fc_topology, phba->fc_linkspeed, phba->link_flag);
+
+	/* If NPIV is not enabled, only bring the physical port up */
+	if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+		(vport != phba->pport))
+		return;
+
+	fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKUP, 0);
+
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
+			    FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
+	vport->fc_flag |= FC_NDISC_ACTIVE;
+	vport->fc_ns_retry = 0;
+	spin_unlock_irq(shost->host_lock);
+
+	if (vport->fc_flag & FC_LBIT)
+		lpfc_linkup_cleanup_nodes(vport);
+
+				/* free any ndlp's in unused state */
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
+				 nlp_listp)
+		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+			lpfc_drop_node(vport, ndlp);
+}
+
 static int
 lpfc_linkup(struct lpfc_hba *phba)
 {
-	struct lpfc_nodelist *ndlp, *next_ndlp;
+	struct lpfc_vport *vport;
 
-	fc_host_post_event(phba->host, fc_get_event_number(),
-			FCH_EVT_LINKUP, 0);
+	phba->link_state = LPFC_LINK_UP;
 
-	spin_lock_irq(phba->host->host_lock);
-	phba->hba_state = LPFC_LINK_UP;
-	phba->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
-			   FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
-	phba->fc_flag |= FC_NDISC_ACTIVE;
-	phba->fc_ns_retry = 0;
-	spin_unlock_irq(phba->host->host_lock);
+	/* Unblock fabric iocbs if they are blocked */
+	clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+	del_timer_sync(&phba->fabric_block_timer);
 
-
-	if (phba->fc_flag & FC_LBIT) {
-		list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
-			if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) {
-				if (ndlp->nlp_type & NLP_FABRIC) {
-					/*
-					 * On Linkup its safe to clean up the
-					 * ndlp from Fabric connections.
-					 */
-					lpfc_nlp_set_state(phba, ndlp,
-							   NLP_STE_UNUSED_NODE);
-				} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
-					/*
-					 * Fail outstanding IO now since
-					 * device is marked for PLOGI.
-					 */
-					lpfc_unreg_rpi(phba, ndlp);
-				}
-			}
-		}
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		lpfc_linkup_port(vport);
 	}
-
-	/* free any ndlp's on unused list */
-	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
-				 nlp_listp) {
-		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
-			lpfc_drop_node(phba, ndlp);
-	}
+	if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+		lpfc_issue_clear_la(phba, phba->pport);
 
 	return 0;
 }
@@ -505,14 +748,14 @@
  * handed off to the SLI layer.
  */
 void
-lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-	struct lpfc_sli *psli;
-	MAILBOX_t *mb;
+	struct lpfc_vport *vport = pmb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_sli   *psli = &phba->sli;
+	MAILBOX_t *mb = &pmb->mb;
 	uint32_t control;
 
-	psli = &phba->sli;
-	mb = &pmb->mb;
 	/* Since we don't do discovery right now, turn these off here */
 	psli->ring[psli->extra_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
 	psli->ring[psli->fcp_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
@@ -522,69 +765,74 @@
 	if ((mb->mbxStatus) && (mb->mbxStatus != 0x1601)) {
 		/* CLEAR_LA mbox error <mbxStatus> state <hba_state> */
 		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-				"%d:0320 CLEAR_LA mbxStatus error x%x hba "
+				"%d (%d):0320 CLEAR_LA mbxStatus error x%x hba "
 				"state x%x\n",
-				phba->brd_no, mb->mbxStatus, phba->hba_state);
+				phba->brd_no, vport->vpi, mb->mbxStatus,
+				vport->port_state);
 
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		goto out;
 	}
 
-	if (phba->fc_flag & FC_ABORT_DISCOVERY)
-		goto out;
+	if (vport->port_type == LPFC_PHYSICAL_PORT)
+		phba->link_state = LPFC_HBA_READY;
 
-	phba->num_disc_nodes = 0;
-	/* go thru NPR list and issue ELS PLOGIs */
-	if (phba->fc_npr_cnt) {
-		lpfc_els_disc_plogi(phba);
-	}
-
-	if (!phba->num_disc_nodes) {
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag &= ~FC_NDISC_ACTIVE;
-		spin_unlock_irq(phba->host->host_lock);
-	}
-
-	phba->hba_state = LPFC_HBA_READY;
-
-out:
-	/* Device Discovery completes */
-	lpfc_printf_log(phba,
-			 KERN_INFO,
-			 LOG_DISCOVERY,
-			 "%d:0225 Device Discovery completes\n",
-			 phba->brd_no);
-
-	mempool_free( pmb, phba->mbox_mem_pool);
-
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag &= ~FC_ABORT_DISCOVERY;
-	if (phba->fc_flag & FC_ESTABLISH_LINK) {
-		phba->fc_flag &= ~FC_ESTABLISH_LINK;
-	}
-	spin_unlock_irq(phba->host->host_lock);
-
-	del_timer_sync(&phba->fc_estabtmo);
-
-	lpfc_can_disctmo(phba);
-
-	/* turn on Link Attention interrupts */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	psli->sli_flag |= LPFC_PROCESS_LA;
 	control = readl(phba->HCregaddr);
 	control |= HC_LAINT_ENA;
 	writel(control, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
+	return;
+
+	vport->num_disc_nodes = 0;
+	/* go thru NPR nodes and issue ELS PLOGIs */
+	if (vport->fc_npr_cnt)
+		lpfc_els_disc_plogi(vport);
+
+	if (!vport->num_disc_nodes) {
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag &= ~FC_NDISC_ACTIVE;
+		spin_unlock_irq(shost->host_lock);
+	}
+
+	vport->port_state = LPFC_VPORT_READY;
+
+out:
+	/* Device Discovery completes */
+	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			"%d (%d):0225 Device Discovery completes\n",
+			phba->brd_no, vport->vpi);
+
+	mempool_free(pmb, phba->mbox_mem_pool);
+
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK);
+	spin_unlock_irq(shost->host_lock);
+
+	del_timer_sync(&phba->fc_estabtmo);
+
+	lpfc_can_disctmo(vport);
+
+	/* turn on Link Attention interrupts */
+
+	spin_lock_irq(&phba->hbalock);
+	psli->sli_flag |= LPFC_PROCESS_LA;
+	control = readl(phba->HCregaddr);
+	control |= HC_LAINT_ENA;
+	writel(control, phba->HCregaddr);
+	readl(phba->HCregaddr); /* flush */
+	spin_unlock_irq(&phba->hbalock);
 
 	return;
 }
 
+
 static void
 lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-	struct lpfc_sli *psli = &phba->sli;
-	int rc;
+	struct lpfc_vport *vport = pmb->vport;
 
 	if (pmb->mb.mbxStatus)
 		goto out;
@@ -592,154 +840,139 @@
 	mempool_free(pmb, phba->mbox_mem_pool);
 
 	if (phba->fc_topology == TOPOLOGY_LOOP &&
-		phba->fc_flag & FC_PUBLIC_LOOP &&
-		 !(phba->fc_flag & FC_LBIT)) {
+	    vport->fc_flag & FC_PUBLIC_LOOP &&
+	    !(vport->fc_flag & FC_LBIT)) {
 			/* Need to wait for FAN - use discovery timer
-			 * for timeout.  hba_state is identically
+			 * for timeout.  port_state is identically
 			 * LPFC_LOCAL_CFG_LINK while waiting for FAN
 			 */
-			lpfc_set_disctmo(phba);
+			lpfc_set_disctmo(vport);
 			return;
-		}
+	}
 
-	/* Start discovery by sending a FLOGI. hba_state is identically
+	/* Start discovery by sending a FLOGI. port_state is identically
 	 * LPFC_FLOGI while waiting for FLOGI cmpl
 	 */
-	phba->hba_state = LPFC_FLOGI;
-	lpfc_set_disctmo(phba);
-	lpfc_initial_flogi(phba);
+	if (vport->port_state != LPFC_FLOGI) {
+		vport->port_state = LPFC_FLOGI;
+		lpfc_set_disctmo(vport);
+		lpfc_initial_flogi(vport);
+	}
 	return;
 
 out:
 	lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-			"%d:0306 CONFIG_LINK mbxStatus error x%x "
+			"%d (%d):0306 CONFIG_LINK mbxStatus error x%x "
 			"HBA state x%x\n",
-			phba->brd_no, pmb->mb.mbxStatus, phba->hba_state);
+			phba->brd_no, vport->vpi, pmb->mb.mbxStatus,
+			vport->port_state);
+
+	mempool_free(pmb, phba->mbox_mem_pool);
 
 	lpfc_linkdown(phba);
 
-	phba->hba_state = LPFC_HBA_ERROR;
-
 	lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-			"%d:0200 CONFIG_LINK bad hba state x%x\n",
-			phba->brd_no, phba->hba_state);
+			"%d (%d):0200 CONFIG_LINK bad hba state x%x\n",
+			phba->brd_no, vport->vpi, vport->port_state);
 
-	lpfc_clear_la(phba, pmb);
-	pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
-	rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
-	if (rc == MBX_NOT_FINISHED) {
-		mempool_free(pmb, phba->mbox_mem_pool);
-		lpfc_disc_flush_list(phba);
-		psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
-		psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
-		psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
-		phba->hba_state = LPFC_HBA_READY;
-	}
+	lpfc_issue_clear_la(phba, vport);
 	return;
 }
 
 static void
-lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-	struct lpfc_sli *psli = &phba->sli;
 	MAILBOX_t *mb = &pmb->mb;
 	struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
+	struct lpfc_vport  *vport = pmb->vport;
 
 
 	/* Check for error */
 	if (mb->mbxStatus) {
 		/* READ_SPARAM mbox error <mbxStatus> state <hba_state> */
 		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-				"%d:0319 READ_SPARAM mbxStatus error x%x "
+				"%d (%d):0319 READ_SPARAM mbxStatus error x%x "
 				"hba state x%x>\n",
-				phba->brd_no, mb->mbxStatus, phba->hba_state);
+				phba->brd_no, vport->vpi, mb->mbxStatus,
+				vport->port_state);
 
 		lpfc_linkdown(phba);
-		phba->hba_state = LPFC_HBA_ERROR;
 		goto out;
 	}
 
-	memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt,
+	memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt,
 	       sizeof (struct serv_parm));
 	if (phba->cfg_soft_wwnn)
-		u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
+		u64_to_wwn(phba->cfg_soft_wwnn,
+			   vport->fc_sparam.nodeName.u.wwn);
 	if (phba->cfg_soft_wwpn)
-		u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
-	memcpy((uint8_t *) & phba->fc_nodename,
-	       (uint8_t *) & phba->fc_sparam.nodeName,
-	       sizeof (struct lpfc_name));
-	memcpy((uint8_t *) & phba->fc_portname,
-	       (uint8_t *) & phba->fc_sparam.portName,
-	       sizeof (struct lpfc_name));
+		u64_to_wwn(phba->cfg_soft_wwpn,
+			   vport->fc_sparam.portName.u.wwn);
+	memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
+	       sizeof(vport->fc_nodename));
+	memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
+	       sizeof(vport->fc_portname));
+	if (vport->port_type == LPFC_PHYSICAL_PORT) {
+		memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn));
+		memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn));
+	}
+
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
-	mempool_free( pmb, phba->mbox_mem_pool);
+	mempool_free(pmb, phba->mbox_mem_pool);
 	return;
 
 out:
 	pmb->context1 = NULL;
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
-	if (phba->hba_state != LPFC_CLEAR_LA) {
-		lpfc_clear_la(phba, pmb);
-		pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
-		if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB))
-		    == MBX_NOT_FINISHED) {
-			mempool_free( pmb, phba->mbox_mem_pool);
-			lpfc_disc_flush_list(phba);
-			psli->ring[(psli->extra_ring)].flag &=
-			    ~LPFC_STOP_IOCB_EVENT;
-			psli->ring[(psli->fcp_ring)].flag &=
-			    ~LPFC_STOP_IOCB_EVENT;
-			psli->ring[(psli->next_ring)].flag &=
-			    ~LPFC_STOP_IOCB_EVENT;
-			phba->hba_state = LPFC_HBA_READY;
-		}
-	} else {
-		mempool_free( pmb, phba->mbox_mem_pool);
-	}
+	lpfc_issue_clear_la(phba, vport);
+	mempool_free(pmb, phba->mbox_mem_pool);
 	return;
 }
 
 static void
 lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
 {
-	int i;
+	struct lpfc_vport *vport = phba->pport;
 	LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox;
+	int i;
 	struct lpfc_dmabuf *mp;
 	int rc;
 
 	sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	switch (la->UlnkSpeed) {
-		case LA_1GHZ_LINK:
-			phba->fc_linkspeed = LA_1GHZ_LINK;
-			break;
-		case LA_2GHZ_LINK:
-			phba->fc_linkspeed = LA_2GHZ_LINK;
-			break;
-		case LA_4GHZ_LINK:
-			phba->fc_linkspeed = LA_4GHZ_LINK;
-			break;
-		case LA_8GHZ_LINK:
-			phba->fc_linkspeed = LA_8GHZ_LINK;
-			break;
-		default:
-			phba->fc_linkspeed = LA_UNKNW_LINK;
-			break;
+	case LA_1GHZ_LINK:
+		phba->fc_linkspeed = LA_1GHZ_LINK;
+		break;
+	case LA_2GHZ_LINK:
+		phba->fc_linkspeed = LA_2GHZ_LINK;
+		break;
+	case LA_4GHZ_LINK:
+		phba->fc_linkspeed = LA_4GHZ_LINK;
+		break;
+	case LA_8GHZ_LINK:
+		phba->fc_linkspeed = LA_8GHZ_LINK;
+		break;
+	default:
+		phba->fc_linkspeed = LA_UNKNW_LINK;
+		break;
 	}
 
 	phba->fc_topology = la->topology;
+	phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
 
 	if (phba->fc_topology == TOPOLOGY_LOOP) {
-	/* Get Loop Map information */
+		phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
 
+				/* Get Loop Map information */
 		if (la->il)
-			phba->fc_flag |= FC_LBIT;
+			vport->fc_flag |= FC_LBIT;
 
-		phba->fc_myDID = la->granted_AL_PA;
+		vport->fc_myDID = la->granted_AL_PA;
 		i = la->un.lilpBde64.tus.f.bdeSize;
 
 		if (i == 0) {
@@ -769,29 +1002,35 @@
 					}
 					/* Link Up Event ALPA map */
 					lpfc_printf_log(phba,
-						KERN_WARNING,
-						LOG_LINK_EVENT,
-						"%d:1304 Link Up Event "
-						"ALPA map Data: x%x "
-						"x%x x%x x%x\n",
-						phba->brd_no,
-						un.pa.wd1, un.pa.wd2,
-						un.pa.wd3, un.pa.wd4);
+							KERN_WARNING,
+							LOG_LINK_EVENT,
+							"%d:1304 Link Up Event "
+							"ALPA map Data: x%x "
+							"x%x x%x x%x\n",
+							phba->brd_no,
+							un.pa.wd1, un.pa.wd2,
+							un.pa.wd3, un.pa.wd4);
 				}
 			}
 		}
 	} else {
-		phba->fc_myDID = phba->fc_pref_DID;
-		phba->fc_flag |= FC_LBIT;
+		if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
+			if (phba->max_vpi && phba->cfg_npiv_enable &&
+			   (phba->sli_rev == 3))
+				phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
+		}
+		vport->fc_myDID = phba->fc_pref_DID;
+		vport->fc_flag |= FC_LBIT;
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	lpfc_linkup(phba);
 	if (sparam_mbox) {
-		lpfc_read_sparam(phba, sparam_mbox);
+		lpfc_read_sparam(phba, sparam_mbox, 0);
+		sparam_mbox->vport = vport;
 		sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
 		rc = lpfc_sli_issue_mbox(phba, sparam_mbox,
-						(MBX_NOWAIT | MBX_STOP_IOCB));
+				    (MBX_NOWAIT | MBX_STOP_IOCB));
 		if (rc == MBX_NOT_FINISHED) {
 			mp = (struct lpfc_dmabuf *) sparam_mbox->context1;
 			lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -799,36 +1038,48 @@
 			mempool_free(sparam_mbox, phba->mbox_mem_pool);
 			if (cfglink_mbox)
 				mempool_free(cfglink_mbox, phba->mbox_mem_pool);
-			return;
+			goto out;
 		}
 	}
 
 	if (cfglink_mbox) {
-		phba->hba_state = LPFC_LOCAL_CFG_LINK;
+		vport->port_state = LPFC_LOCAL_CFG_LINK;
 		lpfc_config_link(phba, cfglink_mbox);
+		cfglink_mbox->vport = vport;
 		cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
 		rc = lpfc_sli_issue_mbox(phba, cfglink_mbox,
-						(MBX_NOWAIT | MBX_STOP_IOCB));
-		if (rc == MBX_NOT_FINISHED)
-			mempool_free(cfglink_mbox, phba->mbox_mem_pool);
+				    (MBX_NOWAIT | MBX_STOP_IOCB));
+		if (rc != MBX_NOT_FINISHED)
+			return;
+		mempool_free(cfglink_mbox, phba->mbox_mem_pool);
 	}
+out:
+	lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+	lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+		"%d (%d):0263 Discovery Mailbox error: state: 0x%x : %p %p\n",
+		phba->brd_no, vport->vpi,
+		vport->port_state, sparam_mbox, cfglink_mbox);
+
+	lpfc_issue_clear_la(phba, vport);
+	return;
 }
 
 static void
-lpfc_mbx_issue_link_down(struct lpfc_hba *phba) {
+lpfc_mbx_issue_link_down(struct lpfc_hba *phba)
+{
 	uint32_t control;
 	struct lpfc_sli *psli = &phba->sli;
 
 	lpfc_linkdown(phba);
 
 	/* turn on Link Attention interrupts - no CLEAR_LA needed */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	psli->sli_flag |= LPFC_PROCESS_LA;
 	control = readl(phba->HCregaddr);
 	control |= HC_LAINT_ENA;
 	writel(control, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 }
 
 /*
@@ -838,22 +1089,21 @@
  * handed off to the SLI layer.
  */
 void
-lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
+	struct lpfc_vport *vport = pmb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	READ_LA_VAR *la;
 	MAILBOX_t *mb = &pmb->mb;
 	struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
 
 	/* Check for error */
 	if (mb->mbxStatus) {
-		lpfc_printf_log(phba,
-				KERN_INFO,
-				LOG_LINK_EVENT,
+		lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
 				"%d:1307 READ_LA mbox error x%x state x%x\n",
-				phba->brd_no,
-				mb->mbxStatus, phba->hba_state);
+				phba->brd_no, mb->mbxStatus, vport->port_state);
 		lpfc_mbx_issue_link_down(phba);
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		goto lpfc_mbx_cmpl_read_la_free_mbuf;
 	}
 
@@ -861,27 +1111,26 @@
 
 	memcpy(&phba->alpa_map[0], mp->virt, 128);
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	if (la->pb)
-		phba->fc_flag |= FC_BYPASSED_MODE;
+		vport->fc_flag |= FC_BYPASSED_MODE;
 	else
-		phba->fc_flag &= ~FC_BYPASSED_MODE;
-	spin_unlock_irq(phba->host->host_lock);
+		vport->fc_flag &= ~FC_BYPASSED_MODE;
+	spin_unlock_irq(shost->host_lock);
 
 	if (((phba->fc_eventTag + 1) < la->eventTag) ||
-	     (phba->fc_eventTag == la->eventTag)) {
+	    (phba->fc_eventTag == la->eventTag)) {
 		phba->fc_stat.LinkMultiEvent++;
-		if (la->attType == AT_LINK_UP) {
+		if (la->attType == AT_LINK_UP)
 			if (phba->fc_eventTag != 0)
 				lpfc_linkdown(phba);
-		}
 	}
 
 	phba->fc_eventTag = la->eventTag;
 
 	if (la->attType == AT_LINK_UP) {
 		phba->fc_stat.LinkUp++;
-		if (phba->fc_flag & FC_LOOPBACK_MODE) {
+		if (phba->link_flag & LS_LOOPBACK_MODE) {
 			lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
 				"%d:1306 Link Up Event in loop back mode "
 				"x%x received Data: x%x x%x x%x x%x\n",
@@ -903,7 +1152,7 @@
 				"%d:1305 Link Down Event x%x received "
 				"Data: x%x x%x x%x\n",
 				phba->brd_no, la->eventTag, phba->fc_eventTag,
-				phba->hba_state, phba->fc_flag);
+				phba->pport->port_state, vport->fc_flag);
 		lpfc_mbx_issue_link_down(phba);
 	}
 
@@ -921,31 +1170,115 @@
  * handed off to the SLI layer.
  */
 void
-lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-	struct lpfc_sli *psli;
-	MAILBOX_t *mb;
-	struct lpfc_dmabuf *mp;
-	struct lpfc_nodelist *ndlp;
-
-	psli = &phba->sli;
-	mb = &pmb->mb;
-
-	ndlp = (struct lpfc_nodelist *) pmb->context2;
-	mp = (struct lpfc_dmabuf *) (pmb->context1);
+	struct lpfc_vport  *vport = pmb->vport;
+	struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
 
 	pmb->context1 = NULL;
 
 	/* Good status, call state machine */
-	lpfc_disc_state_machine(phba, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
+	lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
-	mempool_free( pmb, phba->mbox_mem_pool);
+	mempool_free(pmb, phba->mbox_mem_pool);
 	lpfc_nlp_put(ndlp);
 
 	return;
 }
 
+static void
+lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+{
+	MAILBOX_t *mb = &pmb->mb;
+	struct lpfc_vport *vport = pmb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+
+	switch (mb->mbxStatus) {
+	case 0x0011:
+	case 0x0020:
+	case 0x9700:
+		lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+				"%d (%d):0911 cmpl_unreg_vpi, "
+				"mb status = 0x%x\n",
+				phba->brd_no, vport->vpi, mb->mbxStatus);
+		break;
+	}
+	vport->unreg_vpi_cmpl = VPORT_OK;
+	mempool_free(pmb, phba->mbox_mem_pool);
+	/*
+	 * This shost reference might have been taken at the beginning of
+	 * lpfc_vport_delete()
+	 */
+	if (vport->load_flag & FC_UNLOADING)
+		scsi_host_put(shost);
+}
+
+void
+lpfc_mbx_unreg_vpi(struct lpfc_vport *vport)
+{
+	struct lpfc_hba  *phba = vport->phba;
+	LPFC_MBOXQ_t *mbox;
+	int rc;
+
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!mbox)
+		return;
+
+	lpfc_unreg_vpi(phba, vport->vpi, mbox);
+	mbox->vport = vport;
+	mbox->mbox_cmpl = lpfc_mbx_cmpl_unreg_vpi;
+	rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+	if (rc == MBX_NOT_FINISHED) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT,
+				"%d (%d):1800 Could not issue unreg_vpi\n",
+				phba->brd_no, vport->vpi);
+		mempool_free(mbox, phba->mbox_mem_pool);
+		vport->unreg_vpi_cmpl = VPORT_ERROR;
+	}
+}
+
+static void
+lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+{
+	struct lpfc_vport *vport = pmb->vport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	MAILBOX_t *mb = &pmb->mb;
+
+	switch (mb->mbxStatus) {
+	case 0x0011:
+	case 0x9601:
+	case 0x9602:
+		lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+				"%d (%d):0912 cmpl_reg_vpi, mb status = 0x%x\n",
+				phba->brd_no, vport->vpi, mb->mbxStatus);
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+		spin_unlock_irq(shost->host_lock);
+		vport->fc_myDID = 0;
+		goto out;
+	}
+
+	vport->num_disc_nodes = 0;
+	/* go thru NPR list and issue ELS PLOGIs */
+	if (vport->fc_npr_cnt)
+		lpfc_els_disc_plogi(vport);
+
+	if (!vport->num_disc_nodes) {
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag &= ~FC_NDISC_ACTIVE;
+		spin_unlock_irq(shost->host_lock);
+		lpfc_can_disctmo(vport);
+	}
+	vport->port_state = LPFC_VPORT_READY;
+
+out:
+	mempool_free(pmb, phba->mbox_mem_pool);
+	return;
+}
+
 /*
  * This routine handles processing a Fabric REG_LOGIN mailbox
  * command upon completion. It is setup in the LPFC_MBOXQ
@@ -953,20 +1286,14 @@
  * handed off to the SLI layer.
  */
 void
-lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-	struct lpfc_sli *psli;
-	MAILBOX_t *mb;
-	struct lpfc_dmabuf *mp;
+	struct lpfc_vport *vport = pmb->vport;
+	struct lpfc_vport *next_vport;
+	MAILBOX_t *mb = &pmb->mb;
+	struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
 	struct lpfc_nodelist *ndlp;
-	struct lpfc_nodelist *ndlp_fdmi;
-
-
-	psli = &phba->sli;
-	mb = &pmb->mb;
-
 	ndlp = (struct lpfc_nodelist *) pmb->context2;
-	mp = (struct lpfc_dmabuf *) (pmb->context1);
 
 	pmb->context1 = NULL;
 	pmb->context2 = NULL;
@@ -977,60 +1304,46 @@
 		mempool_free(pmb, phba->mbox_mem_pool);
 		lpfc_nlp_put(ndlp);
 
-		/* FLOGI failed, so just use loop map to make discovery list */
-		lpfc_disc_list_loopmap(phba);
+		if (phba->fc_topology == TOPOLOGY_LOOP) {
+			/* FLOGI failed, use loop map to make discovery list */
+			lpfc_disc_list_loopmap(vport);
 
-		/* Start discovery */
-		lpfc_disc_start(phba);
+			/* Start discovery */
+			lpfc_disc_start(vport);
+			return;
+		}
+
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+			"%d (%d):0258 Register Fabric login error: 0x%x\n",
+			phba->brd_no, vport->vpi, mb->mbxStatus);
+
 		return;
 	}
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
 	ndlp->nlp_type |= NLP_FABRIC;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 
 	lpfc_nlp_put(ndlp);	/* Drop the reference from the mbox */
 
-	if (phba->hba_state == LPFC_FABRIC_CFG_LINK) {
-		/* This NPort has been assigned an NPort_ID by the fabric as a
-		 * result of the completed fabric login.  Issue a State Change
-		 * Registration (SCR) ELS request to the fabric controller
-		 * (SCR_DID) so that this NPort gets RSCN events from the
-		 * fabric.
-		 */
-		lpfc_issue_els_scr(phba, SCR_DID, 0);
+	if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
+		list_for_each_entry(next_vport, &phba->port_list, listentry) {
+			if (next_vport->port_type == LPFC_PHYSICAL_PORT)
+				continue;
 
-		ndlp = lpfc_findnode_did(phba, NameServer_DID);
-		if (!ndlp) {
-			/* Allocate a new node instance. If the pool is empty,
-			 * start the discovery process and skip the Nameserver
-			 * login process.  This is attempted again later on.
-			 * Otherwise, issue a Port Login (PLOGI) to NameServer.
-			 */
-			ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
-			if (!ndlp) {
-				lpfc_disc_start(phba);
-				lpfc_mbuf_free(phba, mp->virt, mp->phys);
-				kfree(mp);
-				mempool_free(pmb, phba->mbox_mem_pool);
-				return;
-			} else {
-				lpfc_nlp_init(phba, ndlp, NameServer_DID);
-				ndlp->nlp_type |= NLP_FABRIC;
+			if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
+				lpfc_initial_fdisc(next_vport);
+			else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+				lpfc_vport_set_state(vport,
+						     FC_VPORT_NO_FABRIC_SUPP);
+				lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+						"%d (%d):0259 No NPIV Fabric "
+						"support\n",
+						phba->brd_no, vport->vpi);
 			}
 		}
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
-		lpfc_issue_els_plogi(phba, NameServer_DID, 0);
-		if (phba->cfg_fdmi_on) {
-			ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
-								GFP_KERNEL);
-			if (ndlp_fdmi) {
-				lpfc_nlp_init(phba, ndlp_fdmi, FDMI_DID);
-				ndlp_fdmi->nlp_type |= NLP_FABRIC;
-				ndlp_fdmi->nlp_state = NLP_STE_PLOGI_ISSUE;
-				lpfc_issue_els_plogi(phba, FDMI_DID, 0);
-			}
-		}
+		lpfc_do_scr_ns_plogi(phba, vport);
 	}
 
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -1046,32 +1359,36 @@
  * handed off to the SLI layer.
  */
 void
-lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-	struct lpfc_sli *psli;
-	MAILBOX_t *mb;
-	struct lpfc_dmabuf *mp;
-	struct lpfc_nodelist *ndlp;
-
-	psli = &phba->sli;
-	mb = &pmb->mb;
-
-	ndlp = (struct lpfc_nodelist *) pmb->context2;
-	mp = (struct lpfc_dmabuf *) (pmb->context1);
+	MAILBOX_t *mb = &pmb->mb;
+	struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+	struct lpfc_vport *vport = pmb->vport;
 
 	if (mb->mbxStatus) {
+out:
 		lpfc_nlp_put(ndlp);
 		lpfc_mbuf_free(phba, mp->virt, mp->phys);
 		kfree(mp);
 		mempool_free(pmb, phba->mbox_mem_pool);
-		lpfc_drop_node(phba, ndlp);
+		lpfc_drop_node(vport, ndlp);
 
-		/* RegLogin failed, so just use loop map to make discovery
-		   list */
-		lpfc_disc_list_loopmap(phba);
+		if (phba->fc_topology == TOPOLOGY_LOOP) {
+			/*
+			 * RegLogin failed, use loop map to make discovery
+			 * list
+			 */
+			lpfc_disc_list_loopmap(vport);
 
-		/* Start discovery */
-		lpfc_disc_start(phba);
+			/* Start discovery */
+			lpfc_disc_start(vport);
+			return;
+		}
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0260 Register NameServer error: 0x%x\n",
+			phba->brd_no, vport->vpi, mb->mbxStatus);
 		return;
 	}
 
@@ -1079,37 +1396,43 @@
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
 	ndlp->nlp_type |= NLP_FABRIC;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 
-	if (phba->hba_state < LPFC_HBA_READY) {
-		/* Link up discovery requires Fabrib registration. */
-		lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID);
-		lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN);
-		lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID);
-		lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFF_ID);
+	if (vport->port_state < LPFC_VPORT_READY) {
+		/* Link up discovery requires Fabric registration. */
+		lpfc_ns_cmd(vport, SLI_CTNS_RFF_ID, 0, 0); /* Do this first! */
+		lpfc_ns_cmd(vport, SLI_CTNS_RNN_ID, 0, 0);
+		lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
+		lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
+		lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0);
+
+		/* Issue SCR just before NameServer GID_FT Query */
+		lpfc_issue_els_scr(vport, SCR_DID, 0);
 	}
 
-	phba->fc_ns_retry = 0;
+	vport->fc_ns_retry = 0;
 	/* Good status, issue CT Request to NameServer */
-	if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT)) {
+	if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0)) {
 		/* Cannot issue NameServer Query, so finish up discovery */
-		lpfc_disc_start(phba);
+		goto out;
 	}
 
 	lpfc_nlp_put(ndlp);
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
-	mempool_free( pmb, phba->mbox_mem_pool);
+	mempool_free(pmb, phba->mbox_mem_pool);
 
 	return;
 }
 
 static void
-lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
-	struct fc_rport *rport;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct fc_rport  *rport;
 	struct lpfc_rport_data *rdata;
 	struct fc_rport_identifiers rport_ids;
+	struct lpfc_hba  *phba = vport->phba;
 
 	/* Remote port has reappeared. Re-register w/ FC transport */
 	rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
@@ -1125,10 +1448,15 @@
 	 * registered the port.
 	 */
 	if (ndlp->rport && ndlp->rport->dd_data &&
-	    *(struct lpfc_rport_data **) ndlp->rport->dd_data) {
+	    ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) {
 		lpfc_nlp_put(ndlp);
 	}
-	ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+		"rport add:       did:x%x flg:x%x type x%x",
+		ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
+
+	ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
 	if (!rport || !get_device(&rport->dev)) {
 		dev_printk(KERN_WARNING, &phba->pcidev->dev,
 			   "Warning: fc_remote_port_add failed\n");
@@ -1151,25 +1479,20 @@
 		fc_remote_port_rolechg(rport, rport_ids.roles);
 
 	if ((rport->scsi_target_id != -1) &&
-		(rport->scsi_target_id < LPFC_MAX_TARGET)) {
+	    (rport->scsi_target_id < LPFC_MAX_TARGET)) {
 		ndlp->nlp_sid = rport->scsi_target_id;
 	}
-
 	return;
 }
 
 static void
-lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp)
 {
 	struct fc_rport *rport = ndlp->rport;
-	struct lpfc_rport_data *rdata = rport->dd_data;
 
-	if (rport->scsi_target_id == -1) {
-		ndlp->rport = NULL;
-		rdata->pnode = NULL;
-		lpfc_nlp_put(ndlp);
-		put_device(&rport->dev);
-	}
+	lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
+		"rport delete:    did:x%x flg:x%x type x%x",
+		ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
 
 	fc_remote_port_delete(rport);
 
@@ -1177,42 +1500,46 @@
 }
 
 static void
-lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
+lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count)
 {
-	spin_lock_irq(phba->host->host_lock);
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	spin_lock_irq(shost->host_lock);
 	switch (state) {
 	case NLP_STE_UNUSED_NODE:
-		phba->fc_unused_cnt += count;
+		vport->fc_unused_cnt += count;
 		break;
 	case NLP_STE_PLOGI_ISSUE:
-		phba->fc_plogi_cnt += count;
+		vport->fc_plogi_cnt += count;
 		break;
 	case NLP_STE_ADISC_ISSUE:
-		phba->fc_adisc_cnt += count;
+		vport->fc_adisc_cnt += count;
 		break;
 	case NLP_STE_REG_LOGIN_ISSUE:
-		phba->fc_reglogin_cnt += count;
+		vport->fc_reglogin_cnt += count;
 		break;
 	case NLP_STE_PRLI_ISSUE:
-		phba->fc_prli_cnt += count;
+		vport->fc_prli_cnt += count;
 		break;
 	case NLP_STE_UNMAPPED_NODE:
-		phba->fc_unmap_cnt += count;
+		vport->fc_unmap_cnt += count;
 		break;
 	case NLP_STE_MAPPED_NODE:
-		phba->fc_map_cnt += count;
+		vport->fc_map_cnt += count;
 		break;
 	case NLP_STE_NPR_NODE:
-		phba->fc_npr_cnt += count;
+		vport->fc_npr_cnt += count;
 		break;
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 }
 
 static void
-lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		       int old_state, int new_state)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
 	if (new_state == NLP_STE_UNMAPPED_NODE) {
 		ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
 		ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
@@ -1226,35 +1553,34 @@
 	/* Transport interface */
 	if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE ||
 			    old_state == NLP_STE_UNMAPPED_NODE)) {
-		phba->nport_event_cnt++;
-		lpfc_unregister_remote_port(phba, ndlp);
+		vport->phba->nport_event_cnt++;
+		lpfc_unregister_remote_port(ndlp);
 	}
 
 	if (new_state ==  NLP_STE_MAPPED_NODE ||
 	    new_state == NLP_STE_UNMAPPED_NODE) {
-		phba->nport_event_cnt++;
-			/*
-			 * Tell the fc transport about the port, if we haven't
-			 * already. If we have, and it's a scsi entity, be
-			 * sure to unblock any attached scsi devices
-			 */
-			lpfc_register_remote_port(phba, ndlp);
+		vport->phba->nport_event_cnt++;
+		/*
+		 * Tell the fc transport about the port, if we haven't
+		 * already. If we have, and it's a scsi entity, be
+		 * sure to unblock any attached scsi devices
+		 */
+		lpfc_register_remote_port(vport, ndlp);
 	}
-
-			/*
-			 * if we added to Mapped list, but the remote port
-			 * registration failed or assigned a target id outside
-			 * our presentable range - move the node to the
-			 * Unmapped List
-			 */
+	/*
+	 * if we added to Mapped list, but the remote port
+	 * registration failed or assigned a target id outside
+	 * our presentable range - move the node to the
+	 * Unmapped List
+	 */
 	if (new_state == NLP_STE_MAPPED_NODE &&
 	    (!ndlp->rport ||
 	     ndlp->rport->scsi_target_id == -1 ||
 	     ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) {
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_TGT_NO_SCSIID;
-		spin_unlock_irq(phba->host->host_lock);
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+		spin_unlock_irq(shost->host_lock);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 	}
 }
 
@@ -1280,61 +1606,74 @@
 }
 
 void
-lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
+lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+		   int state)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	int  old_state = ndlp->nlp_state;
 	char name1[16], name2[16];
 
-	lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-			"%d:0904 NPort state transition x%06x, %s -> %s\n",
-			phba->brd_no,
+	lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE,
+			"%d (%d):0904 NPort state transition x%06x, %s -> %s\n",
+			vport->phba->brd_no, vport->vpi,
 			ndlp->nlp_DID,
 			lpfc_nlp_state_name(name1, sizeof(name1), old_state),
 			lpfc_nlp_state_name(name2, sizeof(name2), state));
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
+		"node statechg    did:x%x old:%d ste:%d",
+		ndlp->nlp_DID, old_state, state);
+
 	if (old_state == NLP_STE_NPR_NODE &&
 	    (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
 	    state != NLP_STE_NPR_NODE)
-		lpfc_cancel_retry_delay_tmo(phba, ndlp);
+		lpfc_cancel_retry_delay_tmo(vport, ndlp);
 	if (old_state == NLP_STE_UNMAPPED_NODE) {
 		ndlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
 		ndlp->nlp_type &= ~NLP_FC_NODE;
 	}
 
 	if (list_empty(&ndlp->nlp_listp)) {
-		spin_lock_irq(phba->host->host_lock);
-		list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes);
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
+		list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes);
+		spin_unlock_irq(shost->host_lock);
 	} else if (old_state)
-		lpfc_nlp_counters(phba, old_state, -1);
+		lpfc_nlp_counters(vport, old_state, -1);
 
 	ndlp->nlp_state = state;
-	lpfc_nlp_counters(phba, state, 1);
-	lpfc_nlp_state_cleanup(phba, ndlp, old_state, state);
+	lpfc_nlp_counters(vport, state, 1);
+	lpfc_nlp_state_cleanup(vport, ndlp, old_state, state);
 }
 
 void
-lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
 	if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
-		lpfc_cancel_retry_delay_tmo(phba, ndlp);
+		lpfc_cancel_retry_delay_tmo(vport, ndlp);
 	if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
-		lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
-	spin_lock_irq(phba->host->host_lock);
+		lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
+	spin_lock_irq(shost->host_lock);
 	list_del_init(&ndlp->nlp_listp);
-	spin_unlock_irq(phba->host->host_lock);
-	lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0);
+	spin_unlock_irq(shost->host_lock);
+	lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state,
+			       NLP_STE_UNUSED_NODE);
 }
 
 void
-lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
 	if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
-		lpfc_cancel_retry_delay_tmo(phba, ndlp);
+		lpfc_cancel_retry_delay_tmo(vport, ndlp);
 	if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
-		lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
-	spin_lock_irq(phba->host->host_lock);
+		lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
+	spin_lock_irq(shost->host_lock);
 	list_del_init(&ndlp->nlp_listp);
-	spin_unlock_irq(phba->host->host_lock);
+	ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
+	spin_unlock_irq(shost->host_lock);
 	lpfc_nlp_put(ndlp);
 }
 
@@ -1342,11 +1681,13 @@
  * Start / ReStart rescue timer for Discovery / RSCN handling
  */
 void
-lpfc_set_disctmo(struct lpfc_hba * phba)
+lpfc_set_disctmo(struct lpfc_vport *vport)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	uint32_t tmo;
 
-	if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
+	if (vport->port_state == LPFC_LOCAL_CFG_LINK) {
 		/* For FAN, timeout should be greater then edtov */
 		tmo = (((phba->fc_edtov + 999) / 1000) + 1);
 	} else {
@@ -1356,18 +1697,25 @@
 		tmo = ((phba->fc_ratov * 3) + 3);
 	}
 
-	mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo);
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag |= FC_DISC_TMO;
-	spin_unlock_irq(phba->host->host_lock);
+
+	if (!timer_pending(&vport->fc_disctmo)) {
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+			"set disc timer:  tmo:x%x state:x%x flg:x%x",
+			tmo, vport->port_state, vport->fc_flag);
+	}
+
+	mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo);
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag |= FC_DISC_TMO;
+	spin_unlock_irq(shost->host_lock);
 
 	/* Start Discovery Timer state <hba_state> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d:0247 Start Discovery Timer state x%x "
+			"%d (%d):0247 Start Discovery Timer state x%x "
 			"Data: x%x x%lx x%x x%x\n",
-			phba->brd_no,
-			phba->hba_state, tmo, (unsigned long)&phba->fc_disctmo,
-			phba->fc_plogi_cnt, phba->fc_adisc_cnt);
+			phba->brd_no, vport->vpi, vport->port_state, tmo,
+			(unsigned long)&vport->fc_disctmo, vport->fc_plogi_cnt,
+			vport->fc_adisc_cnt);
 
 	return;
 }
@@ -1376,23 +1724,34 @@
  * Cancel rescue timer for Discovery / RSCN handling
  */
 int
-lpfc_can_disctmo(struct lpfc_hba * phba)
+lpfc_can_disctmo(struct lpfc_vport *vport)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+	unsigned long iflags;
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"can disc timer:  state:x%x rtry:x%x flg:x%x",
+		vport->port_state, vport->fc_ns_retry, vport->fc_flag);
+
 	/* Turn off discovery timer if its running */
-	if (phba->fc_flag & FC_DISC_TMO) {
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag &= ~FC_DISC_TMO;
-		spin_unlock_irq(phba->host->host_lock);
-		del_timer_sync(&phba->fc_disctmo);
-		phba->work_hba_events &= ~WORKER_DISC_TMO;
+	if (vport->fc_flag & FC_DISC_TMO) {
+		spin_lock_irqsave(shost->host_lock, iflags);
+		vport->fc_flag &= ~FC_DISC_TMO;
+		spin_unlock_irqrestore(shost->host_lock, iflags);
+		del_timer_sync(&vport->fc_disctmo);
+		spin_lock_irqsave(&vport->work_port_lock, iflags);
+		vport->work_port_events &= ~WORKER_DISC_TMO;
+		spin_unlock_irqrestore(&vport->work_port_lock, iflags);
 	}
 
 	/* Cancel Discovery Timer state <hba_state> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d:0248 Cancel Discovery Timer state x%x "
+			"%d (%d):0248 Cancel Discovery Timer state x%x "
 			"Data: x%x x%x x%x\n",
-			phba->brd_no, phba->hba_state, phba->fc_flag,
-			phba->fc_plogi_cnt, phba->fc_adisc_cnt);
+			phba->brd_no, vport->vpi, vport->port_state,
+			vport->fc_flag, vport->fc_plogi_cnt,
+			vport->fc_adisc_cnt);
 
 	return 0;
 }
@@ -1402,15 +1761,18 @@
  * Return true if iocb matches the specified nport
  */
 int
-lpfc_check_sli_ndlp(struct lpfc_hba * phba,
-		    struct lpfc_sli_ring * pring,
-		    struct lpfc_iocbq * iocb, struct lpfc_nodelist * ndlp)
+lpfc_check_sli_ndlp(struct lpfc_hba *phba,
+		    struct lpfc_sli_ring *pring,
+		    struct lpfc_iocbq *iocb,
+		    struct lpfc_nodelist *ndlp)
 {
-	struct lpfc_sli *psli;
-	IOCB_t *icmd;
+	struct lpfc_sli *psli = &phba->sli;
+	IOCB_t *icmd = &iocb->iocb;
+	struct lpfc_vport    *vport = ndlp->vport;
 
-	psli = &phba->sli;
-	icmd = &iocb->iocb;
+	if (iocb->vport != vport)
+		return 0;
+
 	if (pring->ringno == LPFC_ELS_RING) {
 		switch (icmd->ulpCommand) {
 		case CMD_GEN_REQUEST64_CR:
@@ -1428,7 +1790,7 @@
 	} else if (pring->ringno == psli->fcp_ring) {
 		/* Skip match check if waiting to relogin to FCP target */
 		if ((ndlp->nlp_type & NLP_FCP_TARGET) &&
-		  (ndlp->nlp_flag & NLP_DELAY_TMO)) {
+		    (ndlp->nlp_flag & NLP_DELAY_TMO)) {
 			return 0;
 		}
 		if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) {
@@ -1445,7 +1807,7 @@
  * associated with nlp_rpi in the LPFC_NODELIST entry.
  */
 static int
-lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
 	LIST_HEAD(completions);
 	struct lpfc_sli *psli;
@@ -1454,6 +1816,8 @@
 	IOCB_t *icmd;
 	uint32_t rpi, i;
 
+	lpfc_fabric_abort_nport(ndlp);
+
 	/*
 	 * Everything that matches on txcmplq will be returned
 	 * by firmware with a no rpi error.
@@ -1465,15 +1829,15 @@
 		for (i = 0; i < psli->num_rings; i++) {
 			pring = &psli->ring[i];
 
-			spin_lock_irq(phba->host->host_lock);
+			spin_lock_irq(&phba->hbalock);
 			list_for_each_entry_safe(iocb, next_iocb, &pring->txq,
-						list) {
+						 list) {
 				/*
 				 * Check to see if iocb matches the nport we are
 				 * looking for
 				 */
-				if ((lpfc_check_sli_ndlp
-				     (phba, pring, iocb, ndlp))) {
+				if ((lpfc_check_sli_ndlp(phba, pring, iocb,
+							 ndlp))) {
 					/* It matches, so deque and call compl
 					   with an error */
 					list_move_tail(&iocb->list,
@@ -1481,22 +1845,22 @@
 					pring->txq_cnt--;
 				}
 			}
-			spin_unlock_irq(phba->host->host_lock);
-
+			spin_unlock_irq(&phba->hbalock);
 		}
 	}
 
 	while (!list_empty(&completions)) {
 		iocb = list_get_first(&completions, struct lpfc_iocbq, list);
-		list_del(&iocb->list);
+		list_del_init(&iocb->list);
 
-		if (iocb->iocb_cmpl) {
+		if (!iocb->iocb_cmpl)
+			lpfc_sli_release_iocbq(phba, iocb);
+		else {
 			icmd = &iocb->iocb;
 			icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
 			icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-			(iocb->iocb_cmpl) (phba, iocb, iocb);
-		} else
-			lpfc_sli_release_iocbq(phba, iocb);
+			(iocb->iocb_cmpl)(phba, iocb, iocb);
+		}
 	}
 
 	return 0;
@@ -1512,19 +1876,22 @@
  * we are waiting to PLOGI back to the remote NPort.
  */
 int
-lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
-	LPFC_MBOXQ_t *mbox;
+	struct lpfc_hba *phba = vport->phba;
+	LPFC_MBOXQ_t    *mbox;
 	int rc;
 
 	if (ndlp->nlp_rpi) {
-		if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
-			lpfc_unreg_login(phba, ndlp->nlp_rpi, mbox);
-			mbox->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
-			rc = lpfc_sli_issue_mbox
-				    (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+		if (mbox) {
+			lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox);
+			mbox->vport = vport;
+			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			rc = lpfc_sli_issue_mbox(phba, mbox,
+						 (MBX_NOWAIT | MBX_STOP_IOCB));
 			if (rc == MBX_NOT_FINISHED)
-				mempool_free( mbox, phba->mbox_mem_pool);
+				mempool_free(mbox, phba->mbox_mem_pool);
 		}
 		lpfc_no_rpi(phba, ndlp);
 		ndlp->nlp_rpi = 0;
@@ -1533,25 +1900,70 @@
 	return 0;
 }
 
+void
+lpfc_unreg_all_rpis(struct lpfc_vport *vport)
+{
+	struct lpfc_hba  *phba  = vport->phba;
+	LPFC_MBOXQ_t     *mbox;
+	int rc;
+
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (mbox) {
+		lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox);
+		mbox->vport = vport;
+		mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		rc = lpfc_sli_issue_mbox(phba, mbox,
+					 (MBX_NOWAIT | MBX_STOP_IOCB));
+		if (rc == MBX_NOT_FINISHED) {
+			mempool_free(mbox, phba->mbox_mem_pool);
+		}
+	}
+}
+
+void
+lpfc_unreg_default_rpis(struct lpfc_vport *vport)
+{
+	struct lpfc_hba  *phba  = vport->phba;
+	LPFC_MBOXQ_t     *mbox;
+	int rc;
+
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (mbox) {
+		lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox);
+		mbox->vport = vport;
+		mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		rc = lpfc_sli_issue_mbox(phba, mbox,
+					 (MBX_NOWAIT | MBX_STOP_IOCB));
+		if (rc == MBX_NOT_FINISHED) {
+			lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT,
+					"%d (%d):1815 Could not issue "
+					"unreg_did (default rpis)\n",
+					phba->brd_no, vport->vpi);
+			mempool_free(mbox, phba->mbox_mem_pool);
+		}
+	}
+}
+
 /*
  * Free resources associated with LPFC_NODELIST entry
  * so it can be freed.
  */
 static int
-lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
-	LPFC_MBOXQ_t       *mb;
-	LPFC_MBOXQ_t       *nextmb;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+	LPFC_MBOXQ_t *mb, *nextmb;
 	struct lpfc_dmabuf *mp;
 
 	/* Cleanup node for NPort <nlp_DID> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-			"%d:0900 Cleanup node for NPort x%x "
+			"%d (%d):0900 Cleanup node for NPort x%x "
 			"Data: x%x x%x x%x\n",
-			phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
+			phba->brd_no, vport->vpi, ndlp->nlp_DID, ndlp->nlp_flag,
 			ndlp->nlp_state, ndlp->nlp_rpi);
 
-	lpfc_dequeue_node(phba, ndlp);
+	lpfc_dequeue_node(vport, ndlp);
 
 	/* cleanup any ndlp on mbox q waiting for reglogin cmpl */
 	if ((mb = phba->sli.mbox_active)) {
@@ -1562,13 +1974,13 @@
 		}
 	}
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
 		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
-		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+		    (ndlp == (struct lpfc_nodelist *) mb->context2)) {
 			mp = (struct lpfc_dmabuf *) (mb->context1);
 			if (mp) {
-				lpfc_mbuf_free(phba, mp->virt, mp->phys);
+				__lpfc_mbuf_free(phba, mp->virt, mp->phys);
 				kfree(mp);
 			}
 			list_del(&mb->list);
@@ -1576,20 +1988,27 @@
 			lpfc_nlp_put(ndlp);
 		}
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	lpfc_els_abort(phba,ndlp);
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~NLP_DELAY_TMO;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 
 	ndlp->nlp_last_elscmd = 0;
 	del_timer_sync(&ndlp->nlp_delayfunc);
 
 	if (!list_empty(&ndlp->els_retry_evt.evt_listp))
 		list_del_init(&ndlp->els_retry_evt.evt_listp);
+	if (!list_empty(&ndlp->dev_loss_evt.evt_listp))
+		list_del_init(&ndlp->dev_loss_evt.evt_listp);
 
-	lpfc_unreg_rpi(phba, ndlp);
+	if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) {
+		list_del_init(&ndlp->dev_loss_evt.evt_listp);
+		complete((struct completion *)(ndlp->dev_loss_evt.evt_arg2));
+	}
+
+	lpfc_unreg_rpi(vport, ndlp);
 
 	return 0;
 }
@@ -1600,18 +2019,22 @@
  * machine, defer the free till we reach the end of the state machine.
  */
 static void
-lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
 	struct lpfc_rport_data *rdata;
 
 	if (ndlp->nlp_flag & NLP_DELAY_TMO) {
-		lpfc_cancel_retry_delay_tmo(phba, ndlp);
+		lpfc_cancel_retry_delay_tmo(vport, ndlp);
 	}
 
-	lpfc_cleanup_node(phba, ndlp);
+	lpfc_cleanup_node(vport, ndlp);
 
-	if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
-		put_device(&ndlp->rport->dev);
+	/*
+	 * We can get here with a non-NULL ndlp->rport because when we
+	 * unregister a rport we don't break the rport/node linkage.  So if we
+	 * do, make sure we don't leaving any dangling pointers behind.
+	 */
+	if (ndlp->rport) {
 		rdata = ndlp->rport->dd_data;
 		rdata->pnode = NULL;
 		ndlp->rport = NULL;
@@ -1619,11 +2042,10 @@
 }
 
 static int
-lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
+lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+	      uint32_t did)
 {
-	D_ID mydid;
-	D_ID ndlpdid;
-	D_ID matchdid;
+	D_ID mydid, ndlpdid, matchdid;
 
 	if (did == Bcast_DID)
 		return 0;
@@ -1637,7 +2059,7 @@
 		return 1;
 
 	/* Next check for area/domain identically equals 0 match */
-	mydid.un.word = phba->fc_myDID;
+	mydid.un.word = vport->fc_myDID;
 	if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {
 		return 0;
 	}
@@ -1669,101 +2091,116 @@
 }
 
 /* Search for a nodelist entry */
-struct lpfc_nodelist *
-lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
+static struct lpfc_nodelist *
+__lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_nodelist *ndlp;
 	uint32_t data1;
 
-	spin_lock_irq(phba->host->host_lock);
-	list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
-		if (lpfc_matchdid(phba, ndlp, did)) {
+	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+		if (lpfc_matchdid(vport, ndlp, did)) {
 			data1 = (((uint32_t) ndlp->nlp_state << 24) |
 				 ((uint32_t) ndlp->nlp_xri << 16) |
 				 ((uint32_t) ndlp->nlp_type << 8) |
 				 ((uint32_t) ndlp->nlp_rpi & 0xff));
 			lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-					"%d:0929 FIND node DID "
+					"%d (%d):0929 FIND node DID "
 					" Data: x%p x%x x%x x%x\n",
-					phba->brd_no,
+					phba->brd_no, vport->vpi,
 					ndlp, ndlp->nlp_DID,
 					ndlp->nlp_flag, data1);
-			spin_unlock_irq(phba->host->host_lock);
 			return ndlp;
 		}
 	}
-	spin_unlock_irq(phba->host->host_lock);
 
 	/* FIND node did <did> NOT FOUND */
 	lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-			"%d:0932 FIND node did x%x NOT FOUND.\n",
-			phba->brd_no, did);
+			"%d (%d):0932 FIND node did x%x NOT FOUND.\n",
+			phba->brd_no, vport->vpi, did);
 	return NULL;
 }
 
 struct lpfc_nodelist *
-lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
+lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_nodelist *ndlp;
 
-	ndlp = lpfc_findnode_did(phba, did);
+	spin_lock_irq(shost->host_lock);
+	ndlp = __lpfc_findnode_did(vport, did);
+	spin_unlock_irq(shost->host_lock);
+	return ndlp;
+}
+
+struct lpfc_nodelist *
+lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_nodelist *ndlp;
+
+	ndlp = lpfc_findnode_did(vport, did);
 	if (!ndlp) {
-		if ((phba->fc_flag & FC_RSCN_MODE) &&
-		   ((lpfc_rscn_payload_check(phba, did) == 0)))
+		if ((vport->fc_flag & FC_RSCN_MODE) != 0 &&
+		    lpfc_rscn_payload_check(vport, did) == 0)
 			return NULL;
 		ndlp = (struct lpfc_nodelist *)
-		     mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+		     mempool_alloc(vport->phba->nlp_mem_pool, GFP_KERNEL);
 		if (!ndlp)
 			return NULL;
-		lpfc_nlp_init(phba, ndlp, did);
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+		lpfc_nlp_init(vport, ndlp, did);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+		spin_unlock_irq(shost->host_lock);
 		return ndlp;
 	}
-	if (phba->fc_flag & FC_RSCN_MODE) {
-		if (lpfc_rscn_payload_check(phba, did)) {
+	if (vport->fc_flag & FC_RSCN_MODE) {
+		if (lpfc_rscn_payload_check(vport, did)) {
+			spin_lock_irq(shost->host_lock);
 			ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+			spin_unlock_irq(shost->host_lock);
 
 			/* Since this node is marked for discovery,
 			 * delay timeout is not needed.
 			 */
 			if (ndlp->nlp_flag & NLP_DELAY_TMO)
-				lpfc_cancel_retry_delay_tmo(phba, ndlp);
+				lpfc_cancel_retry_delay_tmo(vport, ndlp);
 		} else
 			ndlp = NULL;
 	} else {
 		if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE ||
 		    ndlp->nlp_state == NLP_STE_PLOGI_ISSUE)
 			return NULL;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+		spin_unlock_irq(shost->host_lock);
 	}
 	return ndlp;
 }
 
 /* Build a list of nodes to discover based on the loopmap */
 void
-lpfc_disc_list_loopmap(struct lpfc_hba * phba)
+lpfc_disc_list_loopmap(struct lpfc_vport *vport)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	int j;
 	uint32_t alpa, index;
 
-	if (phba->hba_state <= LPFC_LINK_DOWN) {
+	if (!lpfc_is_link_up(phba))
 		return;
-	}
-	if (phba->fc_topology != TOPOLOGY_LOOP) {
+
+	if (phba->fc_topology != TOPOLOGY_LOOP)
 		return;
-	}
 
 	/* Check for loop map present or not */
 	if (phba->alpa_map[0]) {
 		for (j = 1; j <= phba->alpa_map[0]; j++) {
 			alpa = phba->alpa_map[j];
-
-			if (((phba->fc_myDID & 0xff) == alpa) || (alpa == 0)) {
+			if (((vport->fc_myDID & 0xff) == alpa) || (alpa == 0))
 				continue;
-			}
-			lpfc_setup_disc_node(phba, alpa);
+			lpfc_setup_disc_node(vport, alpa);
 		}
 	} else {
 		/* No alpamap, so try all alpa's */
@@ -1776,113 +2213,167 @@
 			else
 				index = FC_MAXLOOP - j - 1;
 			alpa = lpfcAlpaArray[index];
-			if ((phba->fc_myDID & 0xff) == alpa) {
+			if ((vport->fc_myDID & 0xff) == alpa)
 				continue;
-			}
-
-			lpfc_setup_disc_node(phba, alpa);
+			lpfc_setup_disc_node(vport, alpa);
 		}
 	}
 	return;
 }
 
-/* Start Link up / RSCN discovery on NPR list */
 void
-lpfc_disc_start(struct lpfc_hba * phba)
+lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport)
 {
-	struct lpfc_sli *psli;
 	LPFC_MBOXQ_t *mbox;
-	struct lpfc_nodelist *ndlp, *next_ndlp;
+	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_sli_ring *extra_ring = &psli->ring[psli->extra_ring];
+	struct lpfc_sli_ring *fcp_ring   = &psli->ring[psli->fcp_ring];
+	struct lpfc_sli_ring *next_ring  = &psli->ring[psli->next_ring];
+	int  rc;
+
+	/*
+	 * if it's not a physical port or if we already send
+	 * clear_la then don't send it.
+	 */
+	if ((phba->link_state >= LPFC_CLEAR_LA) ||
+	    (vport->port_type != LPFC_PHYSICAL_PORT))
+		return;
+
+			/* Link up discovery */
+	if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) != NULL) {
+		phba->link_state = LPFC_CLEAR_LA;
+		lpfc_clear_la(phba, mbox);
+		mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
+		mbox->vport = vport;
+		rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT |
+						      MBX_STOP_IOCB));
+		if (rc == MBX_NOT_FINISHED) {
+			mempool_free(mbox, phba->mbox_mem_pool);
+			lpfc_disc_flush_list(vport);
+			extra_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
+			fcp_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
+			next_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
+			phba->link_state = LPFC_HBA_ERROR;
+		}
+	}
+}
+
+/* Reg_vpi to tell firmware to resume normal operations */
+void
+lpfc_issue_reg_vpi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+{
+	LPFC_MBOXQ_t *regvpimbox;
+
+	regvpimbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (regvpimbox) {
+		lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, regvpimbox);
+		regvpimbox->mbox_cmpl = lpfc_mbx_cmpl_reg_vpi;
+		regvpimbox->vport = vport;
+		if (lpfc_sli_issue_mbox(phba, regvpimbox,
+					(MBX_NOWAIT | MBX_STOP_IOCB))
+					== MBX_NOT_FINISHED) {
+			mempool_free(regvpimbox, phba->mbox_mem_pool);
+		}
+	}
+}
+
+/* Start Link up / RSCN discovery on NPR nodes */
+void
+lpfc_disc_start(struct lpfc_vport *vport)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 	uint32_t num_sent;
 	uint32_t clear_la_pending;
 	int did_changed;
-	int rc;
 
-	psli = &phba->sli;
-
-	if (phba->hba_state <= LPFC_LINK_DOWN) {
+	if (!lpfc_is_link_up(phba))
 		return;
-	}
-	if (phba->hba_state == LPFC_CLEAR_LA)
+
+	if (phba->link_state == LPFC_CLEAR_LA)
 		clear_la_pending = 1;
 	else
 		clear_la_pending = 0;
 
-	if (phba->hba_state < LPFC_HBA_READY) {
-		phba->hba_state = LPFC_DISC_AUTH;
-	}
-	lpfc_set_disctmo(phba);
+	if (vport->port_state < LPFC_VPORT_READY)
+		vport->port_state = LPFC_DISC_AUTH;
 
-	if (phba->fc_prevDID == phba->fc_myDID) {
+	lpfc_set_disctmo(vport);
+
+	if (vport->fc_prevDID == vport->fc_myDID)
 		did_changed = 0;
-	} else {
+	else
 		did_changed = 1;
-	}
-	phba->fc_prevDID = phba->fc_myDID;
-	phba->num_disc_nodes = 0;
+
+	vport->fc_prevDID = vport->fc_myDID;
+	vport->num_disc_nodes = 0;
 
 	/* Start Discovery state <hba_state> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d:0202 Start Discovery hba state x%x "
+			"%d (%d):0202 Start Discovery hba state x%x "
 			"Data: x%x x%x x%x\n",
-			phba->brd_no, phba->hba_state, phba->fc_flag,
-			phba->fc_plogi_cnt, phba->fc_adisc_cnt);
-
-	/* If our did changed, we MUST do PLOGI */
-	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
-		if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
-		    (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
-		    did_changed) {
-			spin_lock_irq(phba->host->host_lock);
-			ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-			spin_unlock_irq(phba->host->host_lock);
-		}
-	}
+			phba->brd_no, vport->vpi, vport->port_state,
+			vport->fc_flag, vport->fc_plogi_cnt,
+			vport->fc_adisc_cnt);
 
 	/* First do ADISCs - if any */
-	num_sent = lpfc_els_disc_adisc(phba);
+	num_sent = lpfc_els_disc_adisc(vport);
 
 	if (num_sent)
 		return;
 
-	if ((phba->hba_state < LPFC_HBA_READY) && (!clear_la_pending)) {
+	/*
+	 * For SLI3, cmpl_reg_vpi will set port_state to READY, and
+	 * continue discovery.
+	 */
+	if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+	    !(vport->fc_flag & FC_RSCN_MODE)) {
+		lpfc_issue_reg_vpi(phba, vport);
+		return;
+	}
+
+	/*
+	 * For SLI2, we need to set port_state to READY and continue
+	 * discovery.
+	 */
+	if (vport->port_state < LPFC_VPORT_READY && !clear_la_pending) {
 		/* If we get here, there is nothing to ADISC */
-		if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
-			phba->hba_state = LPFC_CLEAR_LA;
-			lpfc_clear_la(phba, mbox);
-			mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
-			rc = lpfc_sli_issue_mbox(phba, mbox,
-						 (MBX_NOWAIT | MBX_STOP_IOCB));
-			if (rc == MBX_NOT_FINISHED) {
-				mempool_free( mbox, phba->mbox_mem_pool);
-				lpfc_disc_flush_list(phba);
-				psli->ring[(psli->extra_ring)].flag &=
-					~LPFC_STOP_IOCB_EVENT;
-				psli->ring[(psli->fcp_ring)].flag &=
-					~LPFC_STOP_IOCB_EVENT;
-				psli->ring[(psli->next_ring)].flag &=
-					~LPFC_STOP_IOCB_EVENT;
-				phba->hba_state = LPFC_HBA_READY;
+		if (vport->port_type == LPFC_PHYSICAL_PORT)
+			lpfc_issue_clear_la(phba, vport);
+
+		if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
+			vport->num_disc_nodes = 0;
+			/* go thru NPR nodes and issue ELS PLOGIs */
+			if (vport->fc_npr_cnt)
+				lpfc_els_disc_plogi(vport);
+
+			if (!vport->num_disc_nodes) {
+				spin_lock_irq(shost->host_lock);
+				vport->fc_flag &= ~FC_NDISC_ACTIVE;
+				spin_unlock_irq(shost->host_lock);
+				lpfc_can_disctmo(vport);
 			}
 		}
+		vport->port_state = LPFC_VPORT_READY;
 	} else {
 		/* Next do PLOGIs - if any */
-		num_sent = lpfc_els_disc_plogi(phba);
+		num_sent = lpfc_els_disc_plogi(vport);
 
 		if (num_sent)
 			return;
 
-		if (phba->fc_flag & FC_RSCN_MODE) {
+		if (vport->fc_flag & FC_RSCN_MODE) {
 			/* Check to see if more RSCNs came in while we
 			 * were processing this one.
 			 */
-			if ((phba->fc_rscn_id_cnt == 0) &&
-			    (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
-				spin_lock_irq(phba->host->host_lock);
-				phba->fc_flag &= ~FC_RSCN_MODE;
-				spin_unlock_irq(phba->host->host_lock);
+			if ((vport->fc_rscn_id_cnt == 0) &&
+			    (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
+				spin_lock_irq(shost->host_lock);
+				vport->fc_flag &= ~FC_RSCN_MODE;
+				spin_unlock_irq(shost->host_lock);
+				lpfc_can_disctmo(vport);
 			} else
-				lpfc_els_handle_rscn(phba);
+				lpfc_els_handle_rscn(vport);
 		}
 	}
 	return;
@@ -1893,7 +2384,7 @@
  *  ring the match the sppecified nodelist.
  */
 static void
-lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
 	LIST_HEAD(completions);
 	struct lpfc_sli *psli;
@@ -1907,7 +2398,7 @@
 	/* Error matching iocb on txq or txcmplq
 	 * First check the txq.
 	 */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
 		if (iocb->context1 != ndlp) {
 			continue;
@@ -1927,36 +2418,36 @@
 			continue;
 		}
 		icmd = &iocb->iocb;
-		if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) ||
-		    (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {
+		if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR ||
+		    icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX) {
 			lpfc_sli_issue_abort_iotag(phba, pring, iocb);
 		}
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	while (!list_empty(&completions)) {
 		iocb = list_get_first(&completions, struct lpfc_iocbq, list);
-		list_del(&iocb->list);
+		list_del_init(&iocb->list);
 
-		if (iocb->iocb_cmpl) {
+		if (!iocb->iocb_cmpl)
+			lpfc_sli_release_iocbq(phba, iocb);
+		else {
 			icmd = &iocb->iocb;
 			icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
 			icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
 			(iocb->iocb_cmpl) (phba, iocb, iocb);
-		} else
-			lpfc_sli_release_iocbq(phba, iocb);
+		}
 	}
-
-	return;
 }
 
 void
-lpfc_disc_flush_list(struct lpfc_hba * phba)
+lpfc_disc_flush_list(struct lpfc_vport *vport)
 {
 	struct lpfc_nodelist *ndlp, *next_ndlp;
+	struct lpfc_hba *phba = vport->phba;
 
-	if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) {
-		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+	if (vport->fc_plogi_cnt || vport->fc_adisc_cnt) {
+		list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
 					 nlp_listp) {
 			if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
 			    ndlp->nlp_state == NLP_STE_ADISC_ISSUE) {
@@ -1967,6 +2458,14 @@
 	}
 }
 
+void
+lpfc_cleanup_discovery_resources(struct lpfc_vport *vport)
+{
+	lpfc_els_flush_rscn(vport);
+	lpfc_els_flush_cmd(vport);
+	lpfc_disc_flush_list(vport);
+}
+
 /*****************************************************************************/
 /*
  * NAME:     lpfc_disc_timeout
@@ -1985,158 +2484,154 @@
 void
 lpfc_disc_timeout(unsigned long ptr)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+	struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
+	struct lpfc_hba   *phba = vport->phba;
 	unsigned long flags = 0;
 
 	if (unlikely(!phba))
 		return;
 
-	spin_lock_irqsave(phba->host->host_lock, flags);
-	if (!(phba->work_hba_events & WORKER_DISC_TMO)) {
-		phba->work_hba_events |= WORKER_DISC_TMO;
+	if ((vport->work_port_events & WORKER_DISC_TMO) == 0) {
+		spin_lock_irqsave(&vport->work_port_lock, flags);
+		vport->work_port_events |= WORKER_DISC_TMO;
+		spin_unlock_irqrestore(&vport->work_port_lock, flags);
+
+		spin_lock_irqsave(&phba->hbalock, flags);
 		if (phba->work_wait)
-			wake_up(phba->work_wait);
+			lpfc_worker_wake_up(phba);
+		spin_unlock_irqrestore(&phba->hbalock, flags);
 	}
-	spin_unlock_irqrestore(phba->host->host_lock, flags);
 	return;
 }
 
 static void
-lpfc_disc_timeout_handler(struct lpfc_hba *phba)
+lpfc_disc_timeout_handler(struct lpfc_vport *vport)
 {
-	struct lpfc_sli *psli;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+	struct lpfc_sli  *psli = &phba->sli;
 	struct lpfc_nodelist *ndlp, *next_ndlp;
-	LPFC_MBOXQ_t *clearlambox, *initlinkmbox;
+	LPFC_MBOXQ_t *initlinkmbox;
 	int rc, clrlaerr = 0;
 
-	if (unlikely(!phba))
+	if (!(vport->fc_flag & FC_DISC_TMO))
 		return;
 
-	if (!(phba->fc_flag & FC_DISC_TMO))
-		return;
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag &= ~FC_DISC_TMO;
+	spin_unlock_irq(shost->host_lock);
 
-	psli = &phba->sli;
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"disc timeout:    state:x%x rtry:x%x flg:x%x",
+		vport->port_state, vport->fc_ns_retry, vport->fc_flag);
 
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag &= ~FC_DISC_TMO;
-	spin_unlock_irq(phba->host->host_lock);
-
-	switch (phba->hba_state) {
+	switch (vport->port_state) {
 
 	case LPFC_LOCAL_CFG_LINK:
-	/* hba_state is identically LPFC_LOCAL_CFG_LINK while waiting for FAN */
-		/* FAN timeout */
-		lpfc_printf_log(phba,
-				 KERN_WARNING,
-				 LOG_DISCOVERY,
-				 "%d:0221 FAN timeout\n",
-				 phba->brd_no);
+	/* port_state is identically  LPFC_LOCAL_CFG_LINK while waiting for
+	 * FAN
+	 */
+				/* FAN timeout */
+		lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
+				"%d (%d):0221 FAN timeout\n",
+				phba->brd_no, vport->vpi);
 
 		/* Start discovery by sending FLOGI, clean up old rpis */
-		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+		list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
 					 nlp_listp) {
 			if (ndlp->nlp_state != NLP_STE_NPR_NODE)
 				continue;
 			if (ndlp->nlp_type & NLP_FABRIC) {
 				/* Clean up the ndlp on Fabric connections */
-				lpfc_drop_node(phba, ndlp);
+				lpfc_drop_node(vport, ndlp);
 			} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
 				/* Fail outstanding IO now since device
 				 * is marked for PLOGI.
 				 */
-				lpfc_unreg_rpi(phba, ndlp);
+				lpfc_unreg_rpi(vport, ndlp);
 			}
 		}
-		phba->hba_state = LPFC_FLOGI;
-		lpfc_set_disctmo(phba);
-		lpfc_initial_flogi(phba);
+		if (vport->port_state != LPFC_FLOGI) {
+			vport->port_state = LPFC_FLOGI;
+			lpfc_set_disctmo(vport);
+			lpfc_initial_flogi(vport);
+		}
 		break;
 
+	case LPFC_FDISC:
 	case LPFC_FLOGI:
-	/* hba_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
+	/* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
 		/* Initial FLOGI timeout */
-		lpfc_printf_log(phba,
-				 KERN_ERR,
-				 LOG_DISCOVERY,
-				 "%d:0222 Initial FLOGI timeout\n",
-				 phba->brd_no);
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+				"%d (%d):0222 Initial %s timeout\n",
+				phba->brd_no, vport->vpi,
+				vport->vpi ? "FLOGI" : "FDISC");
 
 		/* Assume no Fabric and go on with discovery.
 		 * Check for outstanding ELS FLOGI to abort.
 		 */
 
 		/* FLOGI failed, so just use loop map to make discovery list */
-		lpfc_disc_list_loopmap(phba);
+		lpfc_disc_list_loopmap(vport);
 
 		/* Start discovery */
-		lpfc_disc_start(phba);
+		lpfc_disc_start(vport);
 		break;
 
 	case LPFC_FABRIC_CFG_LINK:
 	/* hba_state is identically LPFC_FABRIC_CFG_LINK while waiting for
 	   NameServer login */
 		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-				"%d:0223 Timeout while waiting for NameServer "
-				"login\n", phba->brd_no);
+				"%d (%d):0223 Timeout while waiting for "
+				"NameServer login\n",
+				phba->brd_no, vport->vpi);
 
 		/* Next look for NameServer ndlp */
-		ndlp = lpfc_findnode_did(phba, NameServer_DID);
+		ndlp = lpfc_findnode_did(vport, NameServer_DID);
 		if (ndlp)
 			lpfc_nlp_put(ndlp);
 		/* Start discovery */
-		lpfc_disc_start(phba);
+		lpfc_disc_start(vport);
 		break;
 
 	case LPFC_NS_QRY:
 	/* Check for wait for NameServer Rsp timeout */
 		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-				"%d:0224 NameServer Query timeout "
+				"%d (%d):0224 NameServer Query timeout "
 				"Data: x%x x%x\n",
-				phba->brd_no,
-				phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
+				phba->brd_no, vport->vpi,
+				vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
 
-		ndlp = lpfc_findnode_did(phba, NameServer_DID);
-		if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
-			if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
-				/* Try it one more time */
-				rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT);
-				if (rc == 0)
-					break;
-			}
-			phba->fc_ns_retry = 0;
+		if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
+			/* Try it one more time */
+			vport->fc_ns_retry++;
+			rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
+					 vport->fc_ns_retry, 0);
+			if (rc == 0)
+				break;
 		}
+		vport->fc_ns_retry = 0;
 
-		/* Nothing to authenticate, so CLEAR_LA right now */
-		clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-		if (!clearlambox) {
-			clrlaerr = 1;
-			lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-					"%d:0226 Device Discovery "
-					"completion error\n",
-					phba->brd_no);
-			phba->hba_state = LPFC_HBA_ERROR;
-			break;
-		}
-
-		phba->hba_state = LPFC_CLEAR_LA;
-		lpfc_clear_la(phba, clearlambox);
-		clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
-		rc = lpfc_sli_issue_mbox(phba, clearlambox,
-					 (MBX_NOWAIT | MBX_STOP_IOCB));
-		if (rc == MBX_NOT_FINISHED) {
-			mempool_free(clearlambox, phba->mbox_mem_pool);
-			clrlaerr = 1;
-			break;
+		/*
+		 * Discovery is over.
+		 * set port_state to PORT_READY if SLI2.
+		 * cmpl_reg_vpi will set port_state to READY for SLI3.
+		 */
+		if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+			lpfc_issue_reg_vpi(phba, vport);
+		else  {	/* NPIV Not enabled */
+			lpfc_issue_clear_la(phba, vport);
+			vport->port_state = LPFC_VPORT_READY;
 		}
 
 		/* Setup and issue mailbox INITIALIZE LINK command */
 		initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 		if (!initlinkmbox) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-					"%d:0206 Device Discovery "
+					"%d (%d):0206 Device Discovery "
 					"completion error\n",
-					phba->brd_no);
-			phba->hba_state = LPFC_HBA_ERROR;
+					phba->brd_no, vport->vpi);
+			phba->link_state = LPFC_HBA_ERROR;
 			break;
 		}
 
@@ -2144,6 +2639,8 @@
 		lpfc_init_link(phba, initlinkmbox, phba->cfg_topology,
 			       phba->cfg_link_speed);
 		initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
+		initlinkmbox->vport = vport;
+		initlinkmbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 		rc = lpfc_sli_issue_mbox(phba, initlinkmbox,
 					 (MBX_NOWAIT | MBX_STOP_IOCB));
 		lpfc_set_loopback_flag(phba);
@@ -2154,67 +2651,81 @@
 
 	case LPFC_DISC_AUTH:
 	/* Node Authentication timeout */
-		lpfc_printf_log(phba,
-				 KERN_ERR,
-				 LOG_DISCOVERY,
-				 "%d:0227 Node Authentication timeout\n",
-				 phba->brd_no);
-		lpfc_disc_flush_list(phba);
-		clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-		if (!clearlambox) {
-			clrlaerr = 1;
-			lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-					"%d:0207 Device Discovery "
-					"completion error\n",
-					phba->brd_no);
-			phba->hba_state = LPFC_HBA_ERROR;
-			break;
-		}
-		phba->hba_state = LPFC_CLEAR_LA;
-		lpfc_clear_la(phba, clearlambox);
-		clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
-		rc = lpfc_sli_issue_mbox(phba, clearlambox,
-					 (MBX_NOWAIT | MBX_STOP_IOCB));
-		if (rc == MBX_NOT_FINISHED) {
-			mempool_free(clearlambox, phba->mbox_mem_pool);
-			clrlaerr = 1;
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+				"%d (%d):0227 Node Authentication timeout\n",
+				phba->brd_no, vport->vpi);
+		lpfc_disc_flush_list(vport);
+
+		/*
+		 * set port_state to PORT_READY if SLI2.
+		 * cmpl_reg_vpi will set port_state to READY for SLI3.
+		 */
+		if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+			lpfc_issue_reg_vpi(phba, vport);
+		else {	/* NPIV Not enabled */
+			lpfc_issue_clear_la(phba, vport);
+			vport->port_state = LPFC_VPORT_READY;
 		}
 		break;
 
+	case LPFC_VPORT_READY:
+		if (vport->fc_flag & FC_RSCN_MODE) {
+			lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+					"%d (%d):0231 RSCN timeout Data: x%x "
+					"x%x\n",
+					phba->brd_no, vport->vpi,
+					vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
+
+			/* Cleanup any outstanding ELS commands */
+			lpfc_els_flush_cmd(vport);
+
+			lpfc_els_flush_rscn(vport);
+			lpfc_disc_flush_list(vport);
+		}
+		break;
+
+	default:
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+				"%d (%d):0229 Unexpected discovery timeout, "
+				"vport State x%x\n",
+				phba->brd_no, vport->vpi, vport->port_state);
+
+		break;
+	}
+
+	switch (phba->link_state) {
 	case LPFC_CLEAR_LA:
-	/* CLEAR LA timeout */
-		lpfc_printf_log(phba,
-				 KERN_ERR,
-				 LOG_DISCOVERY,
-				 "%d:0228 CLEAR LA timeout\n",
-				 phba->brd_no);
+				/* CLEAR LA timeout */
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+				"%d (%d):0228 CLEAR LA timeout\n",
+				phba->brd_no, vport->vpi);
+		clrlaerr = 1;
+		break;
+
+	case LPFC_LINK_UNKNOWN:
+	case LPFC_WARM_START:
+	case LPFC_INIT_START:
+	case LPFC_INIT_MBX_CMDS:
+	case LPFC_LINK_DOWN:
+	case LPFC_LINK_UP:
+	case LPFC_HBA_ERROR:
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+				"%d (%d):0230 Unexpected timeout, hba link "
+				"state x%x\n",
+				phba->brd_no, vport->vpi, phba->link_state);
 		clrlaerr = 1;
 		break;
 
 	case LPFC_HBA_READY:
-		if (phba->fc_flag & FC_RSCN_MODE) {
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_DISCOVERY,
-					"%d:0231 RSCN timeout Data: x%x x%x\n",
-					phba->brd_no,
-					phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
-
-			/* Cleanup any outstanding ELS commands */
-			lpfc_els_flush_cmd(phba);
-
-			lpfc_els_flush_rscn(phba);
-			lpfc_disc_flush_list(phba);
-		}
 		break;
 	}
 
 	if (clrlaerr) {
-		lpfc_disc_flush_list(phba);
+		lpfc_disc_flush_list(vport);
 		psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
 		psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
 		psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
-		phba->hba_state = LPFC_HBA_READY;
+		vport->port_state = LPFC_VPORT_READY;
 	}
 
 	return;
@@ -2227,37 +2738,29 @@
  * handed off to the SLI layer.
  */
 void
-lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
-	struct lpfc_sli *psli;
-	MAILBOX_t *mb;
-	struct lpfc_dmabuf *mp;
-	struct lpfc_nodelist *ndlp;
-
-	psli = &phba->sli;
-	mb = &pmb->mb;
-
-	ndlp = (struct lpfc_nodelist *) pmb->context2;
-	mp = (struct lpfc_dmabuf *) (pmb->context1);
+	MAILBOX_t *mb = &pmb->mb;
+	struct lpfc_dmabuf   *mp = (struct lpfc_dmabuf *) (pmb->context1);
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+	struct lpfc_vport    *vport = pmb->vport;
 
 	pmb->context1 = NULL;
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
 	ndlp->nlp_type |= NLP_FABRIC;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 
-	/* Start issuing Fabric-Device Management Interface (FDMI)
-	 * command to 0xfffffa (FDMI well known port)
+	/*
+	 * Start issuing Fabric-Device Management Interface (FDMI) command to
+	 * 0xfffffa (FDMI well known port) or Delay issuing FDMI command if
+	 * fdmi-on=2 (supporting RPA/hostnmae)
 	 */
-	if (phba->cfg_fdmi_on == 1) {
-		lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
-	} else {
-		/*
-		 * Delay issuing FDMI command if fdmi-on=2
-		 * (supporting RPA/hostnmae)
-		 */
-		mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
-	}
+
+	if (phba->cfg_fdmi_on == 1)
+		lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
+	else
+		mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
 
 				/* Mailbox took a reference to the node */
 	lpfc_nlp_put(ndlp);
@@ -2283,16 +2786,12 @@
 		      sizeof(ndlp->nlp_portname)) == 0;
 }
 
-/*
- * Search node lists for a remote port matching filter criteria
- * Caller needs to hold host_lock before calling this routine.
- */
 struct lpfc_nodelist *
-__lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
+__lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
 {
 	struct lpfc_nodelist *ndlp;
 
-	list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
 		if (ndlp->nlp_state != NLP_STE_UNUSED_NODE &&
 		    filter(ndlp, param))
 			return ndlp;
@@ -2302,68 +2801,104 @@
 
 /*
  * Search node lists for a remote port matching filter criteria
- * This routine is used when the caller does NOT have host_lock.
+ * Caller needs to hold host_lock before calling this routine.
  */
 struct lpfc_nodelist *
-lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
+lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
 {
+	struct Scsi_Host     *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_nodelist *ndlp;
 
-	spin_lock_irq(phba->host->host_lock);
-	ndlp = __lpfc_find_node(phba, filter, param);
-	spin_unlock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
+	ndlp = __lpfc_find_node(vport, filter, param);
+	spin_unlock_irq(shost->host_lock);
 	return ndlp;
 }
 
 /*
  * This routine looks up the ndlp lists for the given RPI. If rpi found it
- * returns the node list pointer else return NULL.
+ * returns the node list element pointer else return NULL.
  */
 struct lpfc_nodelist *
-__lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi)
+__lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
 {
-	return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi);
+	return __lpfc_find_node(vport, lpfc_filter_by_rpi, &rpi);
 }
 
 struct lpfc_nodelist *
-lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
+lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_nodelist *ndlp;
 
-	spin_lock_irq(phba->host->host_lock);
-	ndlp = __lpfc_findnode_rpi(phba, rpi);
-	spin_unlock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
+	ndlp = __lpfc_findnode_rpi(vport, rpi);
+	spin_unlock_irq(shost->host_lock);
 	return ndlp;
 }
 
 /*
  * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
- * returns the node list pointer else return NULL.
+ * returns the node element list pointer else return NULL.
  */
 struct lpfc_nodelist *
-lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn)
+lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_nodelist *ndlp;
 
-	spin_lock_irq(phba->host->host_lock);
-	ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn);
-	spin_unlock_irq(phba->host->host_lock);
-	return NULL;
+	spin_lock_irq(shost->host_lock);
+	ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn);
+	spin_unlock_irq(shost->host_lock);
+	return ndlp;
 }
 
 void
-lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
+lpfc_dev_loss_delay(unsigned long ptr)
+{
+	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr;
+	struct lpfc_vport *vport = ndlp->vport;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_work_evt  *evtp = &ndlp->dev_loss_evt;
+	unsigned long flags;
+
+	evtp = &ndlp->dev_loss_evt;
+
+	spin_lock_irqsave(&phba->hbalock, flags);
+	if (!list_empty(&evtp->evt_listp)) {
+		spin_unlock_irqrestore(&phba->hbalock, flags);
+		return;
+	}
+
+	evtp->evt_arg1  = ndlp;
+	evtp->evt       = LPFC_EVT_DEV_LOSS_DELAY;
+	list_add_tail(&evtp->evt_listp, &phba->work_list);
+	if (phba->work_wait)
+		lpfc_worker_wake_up(phba);
+	spin_unlock_irqrestore(&phba->hbalock, flags);
+	return;
+}
+
+void
+lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+	      uint32_t did)
 {
 	memset(ndlp, 0, sizeof (struct lpfc_nodelist));
 	INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
+	INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
 	init_timer(&ndlp->nlp_delayfunc);
 	ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
 	ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
 	ndlp->nlp_DID = did;
-	ndlp->nlp_phba = phba;
+	ndlp->vport = vport;
 	ndlp->nlp_sid = NLP_NO_SID;
 	INIT_LIST_HEAD(&ndlp->nlp_listp);
 	kref_init(&ndlp->kref);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
+		"node init:       did:x%x",
+		ndlp->nlp_DID, 0, 0);
+
 	return;
 }
 
@@ -2372,8 +2907,13 @@
 {
 	struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
 						  kref);
-	lpfc_nlp_remove(ndlp->nlp_phba, ndlp);
-	mempool_free(ndlp, ndlp->nlp_phba->nlp_mem_pool);
+
+	lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
+		"node release:    did:x%x flg:x%x type:x%x",
+		ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
+
+	lpfc_nlp_remove(ndlp->vport, ndlp);
+	mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
 }
 
 struct lpfc_nodelist *
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 2623a9b..c2fb59f 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -59,6 +59,12 @@
 #define SLI2_IOCB_CMD_R3XTRA_ENTRIES 24
 #define SLI2_IOCB_RSP_R3XTRA_ENTRIES 32
 
+#define SLI2_IOCB_CMD_SIZE	32
+#define SLI2_IOCB_RSP_SIZE	32
+#define SLI3_IOCB_CMD_SIZE	128
+#define SLI3_IOCB_RSP_SIZE	64
+
+
 /* Common Transport structures and definitions */
 
 union CtRevisionId {
@@ -79,6 +85,9 @@
 	uint32_t word;
 };
 
+#define FC4_FEATURE_INIT 0x2
+#define FC4_FEATURE_TARGET 0x1
+
 struct lpfc_sli_ct_request {
 	/* Structure is in Big Endian format */
 	union CtRevisionId RevisionId;
@@ -121,20 +130,6 @@
 
 			uint32_t rsvd[7];
 		} rft;
-		struct rff {
-			uint32_t PortId;
-			uint8_t reserved[2];
-#ifdef __BIG_ENDIAN_BITFIELD
-			uint8_t feature_res:6;
-			uint8_t feature_init:1;
-			uint8_t feature_tgt:1;
-#else  /*  __LITTLE_ENDIAN_BITFIELD */
-			uint8_t feature_tgt:1;
-			uint8_t feature_init:1;
-			uint8_t feature_res:6;
-#endif
-			uint8_t type_code;     /* type=8 for FCP */
-		} rff;
 		struct rnn {
 			uint32_t PortId;	/* For RNN_ID requests */
 			uint8_t wwnn[8];
@@ -144,15 +139,42 @@
 			uint8_t len;
 			uint8_t symbname[255];
 		} rsnn;
+		struct rspn {	/* For RSPN_ID requests */
+			uint32_t PortId;
+			uint8_t len;
+			uint8_t symbname[255];
+		} rspn;
+		struct gff {
+			uint32_t PortId;
+		} gff;
+		struct gff_acc {
+			uint8_t fbits[128];
+		} gff_acc;
+#define FCP_TYPE_FEATURE_OFFSET 4
+		struct rff {
+			uint32_t PortId;
+			uint8_t reserved[2];
+			uint8_t fbits;
+			uint8_t type_code;     /* type=8 for FCP */
+		} rff;
 	} un;
 };
 
 #define  SLI_CT_REVISION        1
-#define  GID_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 260)
-#define  RFT_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 228)
-#define  RFF_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 235)
-#define  RNN_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 252)
-#define  RSNN_REQUEST_SZ        (sizeof(struct lpfc_sli_ct_request))
+#define  GID_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+			   sizeof(struct gid))
+#define  GFF_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+			   sizeof(struct gff))
+#define  RFT_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+			   sizeof(struct rft))
+#define  RFF_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+			   sizeof(struct rff))
+#define  RNN_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+			   sizeof(struct rnn))
+#define  RSNN_REQUEST_SZ  (offsetof(struct lpfc_sli_ct_request, un) + \
+			   sizeof(struct rsnn))
+#define  RSPN_REQUEST_SZ  (offsetof(struct lpfc_sli_ct_request, un) + \
+			   sizeof(struct rspn))
 
 /*
  * FsType Definitions
@@ -227,6 +249,7 @@
 #define  SLI_CTNS_GFT_ID      0x0117
 #define  SLI_CTNS_GSPN_ID     0x0118
 #define  SLI_CTNS_GPT_ID      0x011A
+#define  SLI_CTNS_GFF_ID      0x011F
 #define  SLI_CTNS_GID_PN      0x0121
 #define  SLI_CTNS_GID_NN      0x0131
 #define  SLI_CTNS_GIP_NN      0x0135
@@ -240,9 +263,9 @@
 #define  SLI_CTNS_RNN_ID      0x0213
 #define  SLI_CTNS_RCS_ID      0x0214
 #define  SLI_CTNS_RFT_ID      0x0217
-#define  SLI_CTNS_RFF_ID      0x021F
 #define  SLI_CTNS_RSPN_ID     0x0218
 #define  SLI_CTNS_RPT_ID      0x021A
+#define  SLI_CTNS_RFF_ID      0x021F
 #define  SLI_CTNS_RIP_NN      0x0235
 #define  SLI_CTNS_RIPA_NN     0x0236
 #define  SLI_CTNS_RSNN_NN     0x0239
@@ -311,9 +334,9 @@
 	uint8_t bbCreditlsb;	/* FC Word 0, byte 3 */
 
 #ifdef __BIG_ENDIAN_BITFIELD
-	uint16_t increasingOffset:1;	/* FC Word 1, bit 31 */
+	uint16_t request_multiple_Nport:1;	/* FC Word 1, bit 31 */
 	uint16_t randomOffset:1;	/* FC Word 1, bit 30 */
-	uint16_t word1Reserved2:1;	/* FC Word 1, bit 29 */
+	uint16_t response_multiple_NPort:1;	/* FC Word 1, bit 29 */
 	uint16_t fPort:1;	/* FC Word 1, bit 28 */
 	uint16_t altBbCredit:1;	/* FC Word 1, bit 27 */
 	uint16_t edtovResolution:1;	/* FC Word 1, bit 26 */
@@ -332,9 +355,9 @@
 	uint16_t edtovResolution:1;	/* FC Word 1, bit 26 */
 	uint16_t altBbCredit:1;	/* FC Word 1, bit 27 */
 	uint16_t fPort:1;	/* FC Word 1, bit 28 */
-	uint16_t word1Reserved2:1;	/* FC Word 1, bit 29 */
+	uint16_t response_multiple_NPort:1;	/* FC Word 1, bit 29 */
 	uint16_t randomOffset:1;	/* FC Word 1, bit 30 */
-	uint16_t increasingOffset:1;	/* FC Word 1, bit 31 */
+	uint16_t request_multiple_Nport:1;	/* FC Word 1, bit 31 */
 
 	uint16_t payloadlength:1;	/* FC Word 1, bit 16 */
 	uint16_t contIncSeqCnt:1;	/* FC Word 1, bit 17 */
@@ -1255,7 +1278,9 @@
 #define MBX_KILL_BOARD      0x24
 #define MBX_CONFIG_FARP     0x25
 #define MBX_BEACON          0x2A
+#define MBX_HEARTBEAT       0x31
 
+#define MBX_CONFIG_HBQ	    0x7C
 #define MBX_LOAD_AREA       0x81
 #define MBX_RUN_BIU_DIAG64  0x84
 #define MBX_CONFIG_PORT     0x88
@@ -1263,6 +1288,10 @@
 #define MBX_READ_RPI64      0x8F
 #define MBX_REG_LOGIN64     0x93
 #define MBX_READ_LA64       0x95
+#define MBX_REG_VPI	    0x96
+#define MBX_UNREG_VPI	    0x97
+#define MBX_REG_VNPID	    0x96
+#define MBX_UNREG_VNPID	    0x97
 
 #define MBX_FLASH_WR_ULA    0x98
 #define MBX_SET_DEBUG       0x99
@@ -1335,6 +1364,10 @@
 #define CMD_FCP_TRECEIVE64_CX   0xA1
 #define CMD_FCP_TRSP64_CX       0xA3
 
+#define CMD_IOCB_RCV_SEQ64_CX	0xB5
+#define CMD_IOCB_RCV_ELS64_CX	0xB7
+#define CMD_IOCB_RCV_CONT64_CX	0xBB
+
 #define CMD_GEN_REQUEST64_CR    0xC2
 #define CMD_GEN_REQUEST64_CX    0xC3
 
@@ -1561,6 +1594,7 @@
 #define FLAGS_TOPOLOGY_MODE_PT_PT    0x02 /* Attempt pt-pt only */
 #define FLAGS_TOPOLOGY_MODE_LOOP     0x04 /* Attempt loop only */
 #define FLAGS_TOPOLOGY_MODE_PT_LOOP  0x06 /* Attempt pt-pt then loop */
+#define	FLAGS_UNREG_LOGIN_ALL	     0x08 /* UNREG_LOGIN all on link down */
 #define FLAGS_LIRP_LILP              0x80 /* LIRP / LILP is disabled */
 
 #define FLAGS_TOPOLOGY_FAILOVER      0x0400	/* Bit 10 */
@@ -1744,8 +1778,6 @@
 #define LMT_4Gb       0x040
 #define LMT_8Gb       0x080
 #define LMT_10Gb      0x100
-
-
 	uint32_t rsvd2;
 	uint32_t rsvd3;
 	uint32_t max_xri;
@@ -1754,7 +1786,10 @@
 	uint32_t avail_xri;
 	uint32_t avail_iocb;
 	uint32_t avail_rpi;
-	uint32_t default_rpi;
+	uint32_t max_vpi;
+	uint32_t rsvd4;
+	uint32_t rsvd5;
+	uint32_t avail_vpi;
 } READ_CONFIG_VAR;
 
 /* Structure for MB Command READ_RCONFIG (12) */
@@ -1818,6 +1853,13 @@
 				      structure */
 		struct ulp_bde64 sp64;
 	} un;
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint16_t rsvd3;
+	uint16_t vpi;
+#else	/*  __LITTLE_ENDIAN_BITFIELD */
+	uint16_t vpi;
+	uint16_t rsvd3;
+#endif
 } READ_SPARM_VAR;
 
 /* Structure for MB Command READ_STATUS (14) */
@@ -1918,11 +1960,17 @@
 #ifdef __BIG_ENDIAN_BITFIELD
 	uint32_t cv:1;
 	uint32_t rr:1;
-	uint32_t rsvd1:29;
+	uint32_t rsvd2:2;
+	uint32_t v3req:1;
+	uint32_t v3rsp:1;
+	uint32_t rsvd1:25;
 	uint32_t rv:1;
 #else	/*  __LITTLE_ENDIAN_BITFIELD */
 	uint32_t rv:1;
-	uint32_t rsvd1:29;
+	uint32_t rsvd1:25;
+	uint32_t v3rsp:1;
+	uint32_t v3req:1;
+	uint32_t rsvd2:2;
 	uint32_t rr:1;
 	uint32_t cv:1;
 #endif
@@ -1972,8 +2020,8 @@
 	uint8_t sli1FwName[16];
 	uint32_t sli2FwRev;
 	uint8_t sli2FwName[16];
-	uint32_t rsvd2;
-	uint32_t RandomData[7];
+	uint32_t sli3Feat;
+	uint32_t RandomData[6];
 } READ_REV_VAR;
 
 /* Structure for MB Command READ_LINK_STAT (18) */
@@ -2013,6 +2061,14 @@
 		struct ulp_bde64 sp64;
 	} un;
 
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint16_t rsvd6;
+	uint16_t vpi;
+#else /* __LITTLE_ENDIAN_BITFIELD */
+	uint16_t vpi;
+	uint16_t rsvd6;
+#endif
+
 } REG_LOGIN_VAR;
 
 /* Word 30 contents for REG_LOGIN */
@@ -2037,16 +2093,78 @@
 #ifdef __BIG_ENDIAN_BITFIELD
 	uint16_t rsvd1;
 	uint16_t rpi;
+	uint32_t rsvd2;
+	uint32_t rsvd3;
+	uint32_t rsvd4;
+	uint32_t rsvd5;
+	uint16_t rsvd6;
+	uint16_t vpi;
 #else	/*  __LITTLE_ENDIAN_BITFIELD */
 	uint16_t rpi;
 	uint16_t rsvd1;
+	uint32_t rsvd2;
+	uint32_t rsvd3;
+	uint32_t rsvd4;
+	uint32_t rsvd5;
+	uint16_t vpi;
+	uint16_t rsvd6;
 #endif
 } UNREG_LOGIN_VAR;
 
+/* Structure for MB Command REG_VPI (0x96) */
+typedef struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t rsvd1;
+	uint32_t rsvd2:8;
+	uint32_t sid:24;
+	uint32_t rsvd3;
+	uint32_t rsvd4;
+	uint32_t rsvd5;
+	uint16_t rsvd6;
+	uint16_t vpi;
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t rsvd1;
+	uint32_t sid:24;
+	uint32_t rsvd2:8;
+	uint32_t rsvd3;
+	uint32_t rsvd4;
+	uint32_t rsvd5;
+	uint16_t vpi;
+	uint16_t rsvd6;
+#endif
+} REG_VPI_VAR;
+
+/* Structure for MB Command UNREG_VPI (0x97) */
+typedef struct {
+	uint32_t rsvd1;
+	uint32_t rsvd2;
+	uint32_t rsvd3;
+	uint32_t rsvd4;
+	uint32_t rsvd5;
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint16_t rsvd6;
+	uint16_t vpi;
+#else	/*  __LITTLE_ENDIAN */
+	uint16_t vpi;
+	uint16_t rsvd6;
+#endif
+} UNREG_VPI_VAR;
+
 /* Structure for MB Command UNREG_D_ID (0x23) */
 
 typedef struct {
 	uint32_t did;
+	uint32_t rsvd2;
+	uint32_t rsvd3;
+	uint32_t rsvd4;
+	uint32_t rsvd5;
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint16_t rsvd6;
+	uint16_t vpi;
+#else
+	uint16_t vpi;
+	uint16_t rsvd6;
+#endif
 } UNREG_D_ID_VAR;
 
 /* Structure for MB Command READ_LA (21) */
@@ -2178,13 +2296,240 @@
 #define  DMP_RSP_OFFSET          0x14   /* word 5 contains first word of rsp */
 #define  DMP_RSP_SIZE            0x6C   /* maximum of 27 words of rsp data */
 
-/* Structure for MB Command CONFIG_PORT (0x88) */
+struct hbq_mask {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint8_t tmatch;
+	uint8_t tmask;
+	uint8_t rctlmatch;
+	uint8_t rctlmask;
+#else	/*  __LITTLE_ENDIAN */
+	uint8_t rctlmask;
+	uint8_t rctlmatch;
+	uint8_t tmask;
+	uint8_t tmatch;
+#endif
+};
 
+
+/* Structure for MB Command CONFIG_HBQ (7c) */
+
+struct config_hbq_var {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t rsvd1      :7;
+	uint32_t recvNotify :1;     /* Receive Notification */
+	uint32_t numMask    :8;     /* # Mask Entries       */
+	uint32_t profile    :8;     /* Selection Profile    */
+	uint32_t rsvd2      :8;
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t rsvd2      :8;
+	uint32_t profile    :8;     /* Selection Profile    */
+	uint32_t numMask    :8;     /* # Mask Entries       */
+	uint32_t recvNotify :1;     /* Receive Notification */
+	uint32_t rsvd1      :7;
+#endif
+
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t hbqId      :16;
+	uint32_t rsvd3      :12;
+	uint32_t ringMask   :4;
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t ringMask   :4;
+	uint32_t rsvd3      :12;
+	uint32_t hbqId      :16;
+#endif
+
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t entry_count :16;
+	uint32_t rsvd4        :8;
+	uint32_t headerLen    :8;
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t headerLen    :8;
+	uint32_t rsvd4        :8;
+	uint32_t entry_count :16;
+#endif
+
+	uint32_t hbqaddrLow;
+	uint32_t hbqaddrHigh;
+
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t rsvd5      :31;
+	uint32_t logEntry   :1;
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t logEntry   :1;
+	uint32_t rsvd5      :31;
+#endif
+
+	uint32_t rsvd6;    /* w7 */
+	uint32_t rsvd7;    /* w8 */
+	uint32_t rsvd8;    /* w9 */
+
+	struct hbq_mask hbqMasks[6];
+
+
+	union {
+		uint32_t allprofiles[12];
+
+		struct {
+			#ifdef __BIG_ENDIAN_BITFIELD
+				uint32_t	seqlenoff	:16;
+				uint32_t	maxlen		:16;
+			#else	/*  __LITTLE_ENDIAN */
+				uint32_t	maxlen		:16;
+				uint32_t	seqlenoff	:16;
+			#endif
+			#ifdef __BIG_ENDIAN_BITFIELD
+				uint32_t	rsvd1		:28;
+				uint32_t	seqlenbcnt	:4;
+			#else	/*  __LITTLE_ENDIAN */
+				uint32_t	seqlenbcnt	:4;
+				uint32_t	rsvd1		:28;
+			#endif
+			uint32_t rsvd[10];
+		} profile2;
+
+		struct {
+			#ifdef __BIG_ENDIAN_BITFIELD
+				uint32_t	seqlenoff	:16;
+				uint32_t	maxlen		:16;
+			#else	/*  __LITTLE_ENDIAN */
+				uint32_t	maxlen		:16;
+				uint32_t	seqlenoff	:16;
+			#endif
+			#ifdef __BIG_ENDIAN_BITFIELD
+				uint32_t	cmdcodeoff	:28;
+				uint32_t	rsvd1		:12;
+				uint32_t	seqlenbcnt	:4;
+			#else	/*  __LITTLE_ENDIAN */
+				uint32_t	seqlenbcnt	:4;
+				uint32_t	rsvd1		:12;
+				uint32_t	cmdcodeoff	:28;
+			#endif
+			uint32_t cmdmatch[8];
+
+			uint32_t rsvd[2];
+		} profile3;
+
+		struct {
+			#ifdef __BIG_ENDIAN_BITFIELD
+				uint32_t	seqlenoff	:16;
+				uint32_t	maxlen		:16;
+			#else	/*  __LITTLE_ENDIAN */
+				uint32_t	maxlen		:16;
+				uint32_t	seqlenoff	:16;
+			#endif
+			#ifdef __BIG_ENDIAN_BITFIELD
+				uint32_t	cmdcodeoff	:28;
+				uint32_t	rsvd1		:12;
+				uint32_t	seqlenbcnt	:4;
+			#else	/*  __LITTLE_ENDIAN */
+				uint32_t	seqlenbcnt	:4;
+				uint32_t	rsvd1		:12;
+				uint32_t	cmdcodeoff	:28;
+			#endif
+			uint32_t cmdmatch[8];
+
+			uint32_t rsvd[2];
+		} profile5;
+
+	} profiles;
+
+};
+
+
+
+/* Structure for MB Command CONFIG_PORT (0x88) */
 typedef struct {
-	uint32_t pcbLen;
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t cBE       :  1;
+	uint32_t cET       :  1;
+	uint32_t cHpcb     :  1;
+	uint32_t cMA       :  1;
+	uint32_t sli_mode  :  4;
+	uint32_t pcbLen    : 24;       /* bit 23:0  of memory based port
+					* config block */
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t pcbLen    : 24;       /* bit 23:0  of memory based port
+					* config block */
+	uint32_t sli_mode  :  4;
+	uint32_t cMA       :  1;
+	uint32_t cHpcb     :  1;
+	uint32_t cET       :  1;
+	uint32_t cBE       :  1;
+#endif
+
 	uint32_t pcbLow;       /* bit 31:0  of memory based port config block */
 	uint32_t pcbHigh;      /* bit 63:32 of memory based port config block */
-	uint32_t hbainit[5];
+	uint32_t hbainit[6];
+
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t rsvd      : 24;  /* Reserved                             */
+	uint32_t cmv	   :  1;  /* Configure Max VPIs                   */
+	uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
+	uint32_t csah      :  1;  /* Configure Synchronous Abort Handling */
+	uint32_t chbs      :  1;  /* Cofigure Host Backing store          */
+	uint32_t cinb      :  1;  /* Enable Interrupt Notification Block  */
+	uint32_t cerbm	   :  1;  /* Configure Enhanced Receive Buf Mgmt  */
+	uint32_t cmx	   :  1;  /* Configure Max XRIs                   */
+	uint32_t cmr	   :  1;  /* Configure Max RPIs                   */
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t cmr	   :  1;  /* Configure Max RPIs                   */
+	uint32_t cmx	   :  1;  /* Configure Max XRIs                   */
+	uint32_t cerbm	   :  1;  /* Configure Enhanced Receive Buf Mgmt  */
+	uint32_t cinb      :  1;  /* Enable Interrupt Notification Block  */
+	uint32_t chbs      :  1;  /* Cofigure Host Backing store          */
+	uint32_t csah      :  1;  /* Configure Synchronous Abort Handling */
+	uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
+	uint32_t cmv	   :  1;  /* Configure Max VPIs                   */
+	uint32_t rsvd      : 24;  /* Reserved                             */
+#endif
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t rsvd2     : 24;  /* Reserved                             */
+	uint32_t gmv	   :  1;  /* Grant Max VPIs                       */
+	uint32_t gcrp	   :  1;  /* Grant Command Ring Polling           */
+	uint32_t gsah	   :  1;  /* Grant Synchronous Abort Handling     */
+	uint32_t ghbs	   :  1;  /* Grant Host Backing Store             */
+	uint32_t ginb	   :  1;  /* Grant Interrupt Notification Block   */
+	uint32_t gerbm	   :  1;  /* Grant ERBM Request                   */
+	uint32_t gmx	   :  1;  /* Grant Max XRIs                       */
+	uint32_t gmr	   :  1;  /* Grant Max RPIs                       */
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t gmr	   :  1;  /* Grant Max RPIs                       */
+	uint32_t gmx	   :  1;  /* Grant Max XRIs                       */
+	uint32_t gerbm	   :  1;  /* Grant ERBM Request                   */
+	uint32_t ginb	   :  1;  /* Grant Interrupt Notification Block   */
+	uint32_t ghbs	   :  1;  /* Grant Host Backing Store             */
+	uint32_t gsah	   :  1;  /* Grant Synchronous Abort Handling     */
+	uint32_t gcrp	   :  1;  /* Grant Command Ring Polling           */
+	uint32_t gmv	   :  1;  /* Grant Max VPIs                       */
+	uint32_t rsvd2     : 24;  /* Reserved                             */
+#endif
+
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t max_rpi   : 16;  /* Max RPIs Port should configure       */
+	uint32_t max_xri   : 16;  /* Max XRIs Port should configure       */
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t max_xri   : 16;  /* Max XRIs Port should configure       */
+	uint32_t max_rpi   : 16;  /* Max RPIs Port should configure       */
+#endif
+
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t max_hbq   : 16;  /* Max HBQs Host expect to configure    */
+	uint32_t rsvd3     : 16;  /* Max HBQs Host expect to configure    */
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t rsvd3     : 16;  /* Max HBQs Host expect to configure    */
+	uint32_t max_hbq   : 16;  /* Max HBQs Host expect to configure    */
+#endif
+
+	uint32_t rsvd4;           /* Reserved                             */
+
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint32_t rsvd5      : 16;  /* Reserved                             */
+	uint32_t max_vpi    : 16;  /* Max number of virt N-Ports           */
+#else	/*  __LITTLE_ENDIAN */
+	uint32_t max_vpi    : 16;  /* Max number of virt N-Ports           */
+	uint32_t rsvd5      : 16;  /* Reserved                             */
+#endif
+
 } CONFIG_PORT_VAR;
 
 /* SLI-2 Port Control Block */
@@ -2262,33 +2607,40 @@
 #define MAILBOX_CMD_SIZE	(MAILBOX_CMD_WSIZE * sizeof(uint32_t))
 
 typedef union {
-	uint32_t varWords[MAILBOX_CMD_WSIZE - 1];
-	LOAD_SM_VAR varLdSM;	/* cmd =  1 (LOAD_SM)        */
-	READ_NV_VAR varRDnvp;	/* cmd =  2 (READ_NVPARMS)   */
-	WRITE_NV_VAR varWTnvp;	/* cmd =  3 (WRITE_NVPARMS)  */
-	BIU_DIAG_VAR varBIUdiag;	/* cmd =  4 (RUN_BIU_DIAG)   */
-	INIT_LINK_VAR varInitLnk;	/* cmd =  5 (INIT_LINK)      */
+	uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; /* first word is type/
+						    * feature/max ring number
+						    */
+	LOAD_SM_VAR varLdSM;		/* cmd =  1 (LOAD_SM)        */
+	READ_NV_VAR varRDnvp;		/* cmd =  2 (READ_NVPARMS)   */
+	WRITE_NV_VAR varWTnvp;		/* cmd =  3 (WRITE_NVPARMS)  */
+	BIU_DIAG_VAR varBIUdiag; 	/* cmd =  4 (RUN_BIU_DIAG)   */
+	INIT_LINK_VAR varInitLnk; 	/* cmd =  5 (INIT_LINK)      */
 	DOWN_LINK_VAR varDwnLnk;	/* cmd =  6 (DOWN_LINK)      */
-	CONFIG_LINK varCfgLnk;	/* cmd =  7 (CONFIG_LINK)    */
-	PART_SLIM_VAR varSlim;	/* cmd =  8 (PART_SLIM)      */
+	CONFIG_LINK varCfgLnk;		/* cmd =  7 (CONFIG_LINK)    */
+	PART_SLIM_VAR varSlim;		/* cmd =  8 (PART_SLIM)      */
 	CONFIG_RING_VAR varCfgRing;	/* cmd =  9 (CONFIG_RING)    */
 	RESET_RING_VAR varRstRing;	/* cmd = 10 (RESET_RING)     */
 	READ_CONFIG_VAR varRdConfig;	/* cmd = 11 (READ_CONFIG)    */
 	READ_RCONF_VAR varRdRConfig;	/* cmd = 12 (READ_RCONFIG)   */
 	READ_SPARM_VAR varRdSparm;	/* cmd = 13 (READ_SPARM(64)) */
 	READ_STATUS_VAR varRdStatus;	/* cmd = 14 (READ_STATUS)    */
-	READ_RPI_VAR varRdRPI;	/* cmd = 15 (READ_RPI(64))   */
-	READ_XRI_VAR varRdXRI;	/* cmd = 16 (READ_XRI)       */
-	READ_REV_VAR varRdRev;	/* cmd = 17 (READ_REV)       */
-	READ_LNK_VAR varRdLnk;	/* cmd = 18 (READ_LNK_STAT)  */
+	READ_RPI_VAR varRdRPI;		/* cmd = 15 (READ_RPI(64))   */
+	READ_XRI_VAR varRdXRI;		/* cmd = 16 (READ_XRI)       */
+	READ_REV_VAR varRdRev;		/* cmd = 17 (READ_REV)       */
+	READ_LNK_VAR varRdLnk;		/* cmd = 18 (READ_LNK_STAT)  */
 	REG_LOGIN_VAR varRegLogin;	/* cmd = 19 (REG_LOGIN(64))  */
 	UNREG_LOGIN_VAR varUnregLogin;	/* cmd = 20 (UNREG_LOGIN)    */
-	READ_LA_VAR varReadLA;	/* cmd = 21 (READ_LA(64))    */
+	READ_LA_VAR varReadLA;		/* cmd = 21 (READ_LA(64))    */
 	CLEAR_LA_VAR varClearLA;	/* cmd = 22 (CLEAR_LA)       */
-	DUMP_VAR varDmp;	/* Warm Start DUMP mbx cmd   */
-	UNREG_D_ID_VAR varUnregDID; /* cmd = 0x23 (UNREG_D_ID)   */
-	CONFIG_FARP_VAR varCfgFarp; /* cmd = 0x25 (CONFIG_FARP)  NEW_FEATURE */
-	CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT)  */
+	DUMP_VAR varDmp;		/* Warm Start DUMP mbx cmd   */
+	UNREG_D_ID_VAR varUnregDID;	/* cmd = 0x23 (UNREG_D_ID)   */
+	CONFIG_FARP_VAR varCfgFarp;	/* cmd = 0x25 (CONFIG_FARP)
+					 * NEW_FEATURE
+					 */
+	struct config_hbq_var varCfgHbq;/* cmd = 0x7c (CONFIG_HBQ)  */
+	CONFIG_PORT_VAR varCfgPort;	/* cmd = 0x88 (CONFIG_PORT)  */
+	REG_VPI_VAR varRegVpi;		/* cmd = 0x96 (REG_VPI) */
+	UNREG_VPI_VAR varUnregVpi;	/* cmd = 0x97 (UNREG_VPI) */
 } MAILVARIANTS;
 
 /*
@@ -2305,14 +2657,27 @@
 	__le32 rspPutInx;
 };
 
-typedef struct _SLI2_DESC {
-	struct lpfc_hgp host[MAX_RINGS];
+struct sli2_desc {
 	uint32_t unused1[16];
+	struct lpfc_hgp host[MAX_RINGS];
 	struct lpfc_pgp port[MAX_RINGS];
-} SLI2_DESC;
+};
+
+struct sli3_desc {
+	struct lpfc_hgp host[MAX_RINGS];
+	uint32_t reserved[8];
+	uint32_t hbq_put[16];
+};
+
+struct sli3_pgp {
+	struct lpfc_pgp port[MAX_RINGS];
+	uint32_t hbq_get[16];
+};
 
 typedef union {
-	SLI2_DESC s2;
+	struct sli2_desc s2;
+	struct sli3_desc s3;
+	struct sli3_pgp  s3_pgp;
 } SLI_VAR;
 
 typedef struct {
@@ -2618,6 +2983,25 @@
 	uint32_t fcpt_Length;	/* transfer ready for IWRITE */
 } FCPT_FIELDS64;
 
+/* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7)
+   or CMD_IOCB_RCV_SEQ64_CX (0xB5) */
+
+struct rcv_sli3 {
+	uint32_t word8Rsvd;
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint16_t vpi;
+	uint16_t word9Rsvd;
+#else  /*  __LITTLE_ENDIAN */
+	uint16_t word9Rsvd;
+	uint16_t vpi;
+#endif
+	uint32_t word10Rsvd;
+	uint32_t acc_len;      /* accumulated length */
+	struct ulp_bde64 bde2;
+};
+
+
+
 typedef struct _IOCB {	/* IOCB structure */
 	union {
 		GENERIC_RSP grsp;	/* Generic response */
@@ -2632,8 +3016,8 @@
 
 		/* SLI-2 structures */
 
-		struct ulp_bde64 cont64[2];	/* up to 2 64 bit continuation
-					   bde_64s */
+		struct ulp_bde64 cont64[2];  /* up to 2 64 bit continuation
+					      * bde_64s */
 		ELS_REQUEST64 elsreq64;	/* ELS_REQUEST template */
 		GEN_REQUEST64 genreq64;	/* GEN_REQUEST template */
 		RCV_ELS_REQ64 rcvels64;	/* RCV_ELS_REQ template */
@@ -2695,9 +3079,20 @@
 	uint32_t ulpTimeout:8;
 #endif
 
+	union {
+		struct rcv_sli3 rcvsli3; /* words 8 - 15 */
+		uint32_t sli3Words[24]; /* 96 extra bytes for SLI-3 */
+	} unsli3;
+
+#define ulpCt_h ulpXS
+#define ulpCt_l ulpFCP2Rcvy
+
+#define IOCB_FCP	   1	/* IOCB is used for FCP ELS cmds-ulpRsvByte */
+#define IOCB_IP		   2	/* IOCB is used for IP ELS cmds */
 #define PARM_UNUSED        0	/* PU field (Word 4) not used */
 #define PARM_REL_OFF       1	/* PU field (Word 4) = R. O. */
 #define PARM_READ_CHECK    2	/* PU field (Word 4) = Data Transfer Length */
+#define PARM_NPIV_DID	   3
 #define CLASS1             0	/* Class 1 */
 #define CLASS2             1	/* Class 2 */
 #define CLASS3             2	/* Class 3 */
@@ -2718,39 +3113,51 @@
 #define IOSTAT_RSVD2           0xC
 #define IOSTAT_RSVD3           0xD
 #define IOSTAT_RSVD4           0xE
-#define IOSTAT_RSVD5           0xF
+#define IOSTAT_NEED_BUFFER     0xF
 #define IOSTAT_DRIVER_REJECT   0x10   /* ulpStatus  - Driver defined */
 #define IOSTAT_DEFAULT         0xF    /* Same as rsvd5 for now */
 #define IOSTAT_CNT             0x11
 
 } IOCB_t;
 
+/* Structure used for a single HBQ entry */
+struct lpfc_hbq_entry {
+	struct ulp_bde64 bde;
+	uint32_t buffer_tag;
+};
+
 
 #define SLI1_SLIM_SIZE   (4 * 1024)
 
 /* Up to 498 IOCBs will fit into 16k
  * 256 (MAILBOX_t) + 140 (PCB_t) + ( 32 (IOCB_t) * 498 ) = < 16384
  */
-#define SLI2_SLIM_SIZE   (16 * 1024)
+#define SLI2_SLIM_SIZE   (64 * 1024)
 
 /* Maximum IOCBs that will fit in SLI2 slim */
 #define MAX_SLI2_IOCB    498
+#define MAX_SLIM_IOCB_SIZE (SLI2_SLIM_SIZE - \
+			    (sizeof(MAILBOX_t) + sizeof(PCB_t)))
+
+/* HBQ entries are 4 words each = 4k */
+#define LPFC_TOTAL_HBQ_SIZE (sizeof(struct lpfc_hbq_entry) *  \
+			     lpfc_sli_hbq_count())
 
 struct lpfc_sli2_slim {
 	MAILBOX_t mbx;
 	PCB_t pcb;
-	IOCB_t IOCBs[MAX_SLI2_IOCB];
+	IOCB_t IOCBs[MAX_SLIM_IOCB_SIZE];
 };
 
-/*******************************************************************
-This macro check PCI device to allow special handling for LC HBAs.
-
-Parameters:
-device : struct pci_dev 's device field
-
-return 1 => TRUE
-       0 => FALSE
- *******************************************************************/
+/*
+ * This function checks PCI device to allow special handling for LC HBAs.
+ *
+ * Parameters:
+ * device : struct pci_dev 's device field
+ *
+ * return 1 => TRUE
+ *        0 => FALSE
+ */
 static inline int
 lpfc_is_LC_HBA(unsigned short device)
 {
@@ -2766,3 +3173,16 @@
 	else
 		return 0;
 }
+
+/*
+ * Determine if an IOCB failed because of a link event or firmware reset.
+ */
+
+static inline int
+lpfc_error_lost_link(IOCB_t *iocbp)
+{
+	return (iocbp->ulpStatus == IOSTAT_LOCAL_REJECT &&
+		(iocbp->un.ulpWord[4] == IOERR_SLI_ABORTED ||
+		 iocbp->un.ulpWord[4] == IOERR_LINK_DOWN ||
+		 iocbp->un.ulpWord[4] == IOERR_SLI_DOWN));
+}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index dcb4ba0..f81f85e 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -27,6 +27,7 @@
 #include <linux/kthread.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
+#include <linux/ctype.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -40,15 +41,20 @@
 #include "lpfc.h"
 #include "lpfc_logmsg.h"
 #include "lpfc_crtn.h"
+#include "lpfc_vport.h"
 #include "lpfc_version.h"
+#include "lpfc_vport.h"
 
 static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
 static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
 static int lpfc_post_rcv_buf(struct lpfc_hba *);
 
 static struct scsi_transport_template *lpfc_transport_template = NULL;
+static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
 static DEFINE_IDR(lpfc_hba_index);
 
+
+
 /************************************************************************/
 /*                                                                      */
 /*    lpfc_config_port_prep                                             */
@@ -61,7 +67,7 @@
 /*                                                                      */
 /************************************************************************/
 int
-lpfc_config_port_prep(struct lpfc_hba * phba)
+lpfc_config_port_prep(struct lpfc_hba *phba)
 {
 	lpfc_vpd_t *vp = &phba->vpd;
 	int i = 0, rc;
@@ -75,12 +81,12 @@
 
 	pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!pmb) {
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		return -ENOMEM;
 	}
 
 	mb = &pmb->mb;
-	phba->hba_state = LPFC_INIT_MBX_CMDS;
+	phba->link_state = LPFC_INIT_MBX_CMDS;
 
 	if (lpfc_is_LC_HBA(phba->pcidev->device)) {
 		if (init_key) {
@@ -100,9 +106,7 @@
 		rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
 
 		if (rc != MBX_SUCCESS) {
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_MBOX,
+			lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
 					"%d:0324 Config Port initialization "
 					"error, mbxCmd x%x READ_NVPARM, "
 					"mbxStatus x%x\n",
@@ -112,16 +116,18 @@
 			return -ERESTART;
 		}
 		memcpy(phba->wwnn, (char *)mb->un.varRDnvp.nodename,
-		       sizeof (mb->un.varRDnvp.nodename));
+		       sizeof(phba->wwnn));
+		memcpy(phba->wwpn, (char *)mb->un.varRDnvp.portname,
+		       sizeof(phba->wwpn));
 	}
 
+	phba->sli3_options = 0x0;
+
 	/* Setup and issue mailbox READ REV command */
 	lpfc_read_rev(phba, pmb);
 	rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
 	if (rc != MBX_SUCCESS) {
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_INIT,
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"%d:0439 Adapter failed to init, mbxCmd x%x "
 				"READ_REV, mbxStatus x%x\n",
 				phba->brd_no,
@@ -130,6 +136,7 @@
 		return -ERESTART;
 	}
 
+
 	/*
 	 * The value of rr must be 1 since the driver set the cv field to 1.
 	 * This setting requires the FW to set all revision fields.
@@ -144,8 +151,12 @@
 		return -ERESTART;
 	}
 
+	if (phba->sli_rev == 3 && !mb->un.varRdRev.v3rsp)
+		return -EINVAL;
+
 	/* Save information as VPD data */
 	vp->rev.rBit = 1;
+	memcpy(&vp->sli3Feat, &mb->un.varRdRev.sli3Feat, sizeof(uint32_t));
 	vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
 	memcpy(vp->rev.sli1FwName, (char*) mb->un.varRdRev.sli1FwName, 16);
 	vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
@@ -161,6 +172,13 @@
 	vp->rev.postKernRev = mb->un.varRdRev.postKernRev;
 	vp->rev.opFwRev = mb->un.varRdRev.opFwRev;
 
+	/* If the sli feature level is less then 9, we must
+	 * tear down all RPIs and VPIs on link down if NPIV
+	 * is enabled.
+	 */
+	if (vp->rev.feaLevelHigh < 9)
+		phba->sli3_options |= LPFC_SLI3_VPORT_TEARDOWN;
+
 	if (lpfc_is_LC_HBA(phba->pcidev->device))
 		memcpy(phba->RandomData, (char *)&mb->un.varWords[24],
 						sizeof (phba->RandomData));
@@ -188,7 +206,7 @@
 		if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
 			mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
 		lpfc_sli_pcimem_bcopy(pmb->context2, lpfc_vpd_data + offset,
-							mb->un.varDmp.word_cnt);
+				      mb->un.varDmp.word_cnt);
 		offset += mb->un.varDmp.word_cnt;
 	} while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
 	lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
@@ -212,48 +230,34 @@
 /*                                                                      */
 /************************************************************************/
 int
-lpfc_config_port_post(struct lpfc_hba * phba)
+lpfc_config_port_post(struct lpfc_hba *phba)
 {
+	struct lpfc_vport *vport = phba->pport;
 	LPFC_MBOXQ_t *pmb;
 	MAILBOX_t *mb;
 	struct lpfc_dmabuf *mp;
 	struct lpfc_sli *psli = &phba->sli;
 	uint32_t status, timeout;
-	int i, j, rc;
+	int i, j;
+	int rc;
 
 	pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!pmb) {
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		return -ENOMEM;
 	}
 	mb = &pmb->mb;
 
-	lpfc_config_link(phba, pmb);
-	rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
-	if (rc != MBX_SUCCESS) {
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_INIT,
-				"%d:0447 Adapter failed init, mbxCmd x%x "
-				"CONFIG_LINK mbxStatus x%x\n",
-				phba->brd_no,
-				mb->mbxCommand, mb->mbxStatus);
-		phba->hba_state = LPFC_HBA_ERROR;
-		mempool_free( pmb, phba->mbox_mem_pool);
-		return -EIO;
-	}
-
 	/* Get login parameters for NID.  */
-	lpfc_read_sparam(phba, pmb);
+	lpfc_read_sparam(phba, pmb, 0);
+	pmb->vport = vport;
 	if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_INIT,
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"%d:0448 Adapter failed init, mbxCmd x%x "
 				"READ_SPARM mbxStatus x%x\n",
 				phba->brd_no,
 				mb->mbxCommand, mb->mbxStatus);
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		mp = (struct lpfc_dmabuf *) pmb->context1;
 		mempool_free( pmb, phba->mbox_mem_pool);
 		lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -263,25 +267,27 @@
 
 	mp = (struct lpfc_dmabuf *) pmb->context1;
 
-	memcpy(&phba->fc_sparam, mp->virt, sizeof (struct serv_parm));
+	memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
 	pmb->context1 = NULL;
 
 	if (phba->cfg_soft_wwnn)
-		u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
+		u64_to_wwn(phba->cfg_soft_wwnn,
+			   vport->fc_sparam.nodeName.u.wwn);
 	if (phba->cfg_soft_wwpn)
-		u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
-	memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName,
+		u64_to_wwn(phba->cfg_soft_wwpn,
+			   vport->fc_sparam.portName.u.wwn);
+	memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
 	       sizeof (struct lpfc_name));
-	memcpy(&phba->fc_portname, &phba->fc_sparam.portName,
+	memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
 	       sizeof (struct lpfc_name));
 	/* If no serial number in VPD data, use low 6 bytes of WWNN */
 	/* This should be consolidated into parse_vpd ? - mr */
 	if (phba->SerialNumber[0] == 0) {
 		uint8_t *outptr;
 
-		outptr = &phba->fc_nodename.u.s.IEEE[0];
+		outptr = &vport->fc_nodename.u.s.IEEE[0];
 		for (i = 0; i < 12; i++) {
 			status = *outptr++;
 			j = ((status & 0xf0) >> 4);
@@ -303,15 +309,14 @@
 	}
 
 	lpfc_read_config(phba, pmb);
+	pmb->vport = vport;
 	if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_INIT,
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"%d:0453 Adapter failed to init, mbxCmd x%x "
 				"READ_CONFIG, mbxStatus x%x\n",
 				phba->brd_no,
 				mb->mbxCommand, mb->mbxStatus);
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		mempool_free( pmb, phba->mbox_mem_pool);
 		return -EIO;
 	}
@@ -338,9 +343,7 @@
 	    || ((phba->cfg_link_speed == LINK_SPEED_10G)
 		&& !(phba->lmt & LMT_10Gb))) {
 		/* Reset link speed to auto */
-		lpfc_printf_log(phba,
-			KERN_WARNING,
-			LOG_LINK_EVENT,
+		lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
 			"%d:1302 Invalid speed for this board: "
 			"Reset link speed to auto: x%x\n",
 			phba->brd_no,
@@ -348,7 +351,7 @@
 			phba->cfg_link_speed = LINK_SPEED_AUTO;
 	}
 
-	phba->hba_state = LPFC_LINK_DOWN;
+	phba->link_state = LPFC_LINK_DOWN;
 
 	/* Only process IOCBs on ring 0 till hba_state is READY */
 	if (psli->ring[psli->extra_ring].cmdringaddr)
@@ -359,10 +362,11 @@
 		psli->ring[psli->next_ring].flag |= LPFC_STOP_IOCB_EVENT;
 
 	/* Post receive buffers for desired rings */
-	lpfc_post_rcv_buf(phba);
+	if (phba->sli_rev != 3)
+		lpfc_post_rcv_buf(phba);
 
 	/* Enable appropriate host interrupts */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	status = readl(phba->HCregaddr);
 	status |= HC_MBINT_ENA | HC_ERINT_ENA | HC_LAINT_ENA;
 	if (psli->num_rings > 0)
@@ -380,22 +384,24 @@
 
 	writel(status, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	/*
 	 * Setup the ring 0 (els)  timeout handler
 	 */
 	timeout = phba->fc_ratov << 1;
-	mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
+	mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+	mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+	phba->hb_outstanding = 0;
+	phba->last_completion_time = jiffies;
 
 	lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
 	pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+	pmb->vport = vport;
 	rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
 	lpfc_set_loopback_flag(phba);
 	if (rc != MBX_SUCCESS) {
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_INIT,
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"%d:0454 Adapter failed to init, mbxCmd x%x "
 				"INIT_LINK, mbxStatus x%x\n",
 				phba->brd_no,
@@ -408,7 +414,7 @@
 		writel(0xffffffff, phba->HAregaddr);
 		readl(phba->HAregaddr); /* flush */
 
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		if (rc != MBX_BUSY)
 			mempool_free(pmb, phba->mbox_mem_pool);
 		return -EIO;
@@ -429,18 +435,19 @@
 /*                                                                      */
 /************************************************************************/
 int
-lpfc_hba_down_prep(struct lpfc_hba * phba)
+lpfc_hba_down_prep(struct lpfc_hba *phba)
 {
+	struct lpfc_vport *vport = phba->pport;
+
 	/* Disable interrupts */
 	writel(0, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
 
-	/* Cleanup potential discovery resources */
-	lpfc_els_flush_rscn(phba);
-	lpfc_els_flush_cmd(phba);
-	lpfc_disc_flush_list(phba);
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		lpfc_cleanup_discovery_resources(vport);
+	}
 
-	return (0);
+	return 0;
 }
 
 /************************************************************************/
@@ -453,20 +460,24 @@
 /*                                                                      */
 /************************************************************************/
 int
-lpfc_hba_down_post(struct lpfc_hba * phba)
+lpfc_hba_down_post(struct lpfc_hba *phba)
 {
 	struct lpfc_sli *psli = &phba->sli;
 	struct lpfc_sli_ring *pring;
 	struct lpfc_dmabuf *mp, *next_mp;
 	int i;
 
-	/* Cleanup preposted buffers on the ELS ring */
-	pring = &psli->ring[LPFC_ELS_RING];
-	list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
-		list_del(&mp->list);
-		pring->postbufq_cnt--;
-		lpfc_mbuf_free(phba, mp->virt, mp->phys);
-		kfree(mp);
+	if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
+		lpfc_sli_hbqbuf_free_all(phba);
+	else {
+		/* Cleanup preposted buffers on the ELS ring */
+		pring = &psli->ring[LPFC_ELS_RING];
+		list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
+			list_del(&mp->list);
+			pring->postbufq_cnt--;
+			lpfc_mbuf_free(phba, mp->virt, mp->phys);
+			kfree(mp);
+		}
 	}
 
 	for (i = 0; i < psli->num_rings; i++) {
@@ -477,6 +488,119 @@
 	return 0;
 }
 
+/* HBA heart beat timeout handler */
+void
+lpfc_hb_timeout(unsigned long ptr)
+{
+	struct lpfc_hba *phba;
+	unsigned long iflag;
+
+	phba = (struct lpfc_hba *)ptr;
+	spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
+	if (!(phba->pport->work_port_events & WORKER_HB_TMO))
+		phba->pport->work_port_events |= WORKER_HB_TMO;
+	spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+
+	if (phba->work_wait)
+		wake_up(phba->work_wait);
+	return;
+}
+
+static void
+lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
+{
+	unsigned long drvr_flag;
+
+	spin_lock_irqsave(&phba->hbalock, drvr_flag);
+	phba->hb_outstanding = 0;
+	spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+
+	mempool_free(pmboxq, phba->mbox_mem_pool);
+	if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) &&
+		!(phba->link_state == LPFC_HBA_ERROR) &&
+		!(phba->pport->fc_flag & FC_UNLOADING))
+		mod_timer(&phba->hb_tmofunc,
+			jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+	return;
+}
+
+void
+lpfc_hb_timeout_handler(struct lpfc_hba *phba)
+{
+	LPFC_MBOXQ_t *pmboxq;
+	int retval;
+	struct lpfc_sli *psli = &phba->sli;
+
+	if ((phba->link_state == LPFC_HBA_ERROR) ||
+		(phba->pport->fc_flag & FC_UNLOADING) ||
+		(phba->pport->fc_flag & FC_OFFLINE_MODE))
+		return;
+
+	spin_lock_irq(&phba->pport->work_port_lock);
+	/* If the timer is already canceled do nothing */
+	if (!(phba->pport->work_port_events & WORKER_HB_TMO)) {
+		spin_unlock_irq(&phba->pport->work_port_lock);
+		return;
+	}
+
+	if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ,
+		jiffies)) {
+		spin_unlock_irq(&phba->pport->work_port_lock);
+		if (!phba->hb_outstanding)
+			mod_timer(&phba->hb_tmofunc,
+				jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+		else
+			mod_timer(&phba->hb_tmofunc,
+				jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+		return;
+	}
+	spin_unlock_irq(&phba->pport->work_port_lock);
+
+	/* If there is no heart beat outstanding, issue a heartbeat command */
+	if (!phba->hb_outstanding) {
+		pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
+		if (!pmboxq) {
+			mod_timer(&phba->hb_tmofunc,
+				jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+			return;
+		}
+
+		lpfc_heart_beat(phba, pmboxq);
+		pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl;
+		pmboxq->vport = phba->pport;
+		retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
+
+		if (retval != MBX_BUSY && retval != MBX_SUCCESS) {
+			mempool_free(pmboxq, phba->mbox_mem_pool);
+			mod_timer(&phba->hb_tmofunc,
+				jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+			return;
+		}
+		mod_timer(&phba->hb_tmofunc,
+			jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+		phba->hb_outstanding = 1;
+		return;
+	} else {
+		/*
+		 * If heart beat timeout called with hb_outstanding set we
+		 * need to take the HBA offline.
+		 */
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+			"%d:0459 Adapter heartbeat failure, taking "
+			"this port offline.\n", phba->brd_no);
+
+		spin_lock_irq(&phba->hbalock);
+		psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+		spin_unlock_irq(&phba->hbalock);
+
+		lpfc_offline_prep(phba);
+		lpfc_offline(phba);
+		lpfc_unblock_mgmt_io(phba);
+		phba->link_state = LPFC_HBA_ERROR;
+		lpfc_hba_down_post(phba);
+	}
+}
+
 /************************************************************************/
 /*                                                                      */
 /*    lpfc_handle_eratt                                                 */
@@ -486,11 +610,15 @@
 /*                                                                      */
 /************************************************************************/
 void
-lpfc_handle_eratt(struct lpfc_hba * phba)
+lpfc_handle_eratt(struct lpfc_hba *phba)
 {
-	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_vport *vport = phba->pport;
+	struct lpfc_sli   *psli = &phba->sli;
 	struct lpfc_sli_ring  *pring;
+	struct lpfc_vport *port_iterator;
 	uint32_t event_data;
+	struct Scsi_Host  *shost;
+
 	/* If the pci channel is offline, ignore possible errors,
 	 * since we cannot communicate with the pci card anyway. */
 	if (pci_channel_offline(phba->pcidev))
@@ -504,10 +632,17 @@
 				"Data: x%x x%x x%x\n",
 				phba->brd_no, phba->work_hs,
 				phba->work_status[0], phba->work_status[1]);
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag |= FC_ESTABLISH_LINK;
+		list_for_each_entry(port_iterator, &phba->port_list,
+				    listentry) {
+			shost = lpfc_shost_from_vport(port_iterator);
+
+			spin_lock_irq(shost->host_lock);
+			port_iterator->fc_flag |= FC_ESTABLISH_LINK;
+			spin_unlock_irq(shost->host_lock);
+		}
+		spin_lock_irq(&phba->hbalock);
 		psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 
 		/*
 		* Firmware stops when it triggled erratt with HS_FFER6.
@@ -544,15 +679,18 @@
 				phba->work_status[0], phba->work_status[1]);
 
 		event_data = FC_REG_DUMP_EVENT;
-		fc_host_post_vendor_event(phba->host, fc_get_event_number(),
+		shost = lpfc_shost_from_vport(vport);
+		fc_host_post_vendor_event(shost, fc_get_event_number(),
 				sizeof(event_data), (char *) &event_data,
 				SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
 
+		spin_lock_irq(&phba->hbalock);
 		psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+		spin_unlock_irq(&phba->hbalock);
 		lpfc_offline_prep(phba);
 		lpfc_offline(phba);
 		lpfc_unblock_mgmt_io(phba);
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		lpfc_hba_down_post(phba);
 	}
 }
@@ -566,9 +704,11 @@
 /*                                                                      */
 /************************************************************************/
 void
-lpfc_handle_latt(struct lpfc_hba * phba)
+lpfc_handle_latt(struct lpfc_hba *phba)
 {
-	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_vport *vport = phba->pport;
+	struct lpfc_sli   *psli = &phba->sli;
+	struct lpfc_vport *port_iterator;
 	LPFC_MBOXQ_t *pmb;
 	volatile uint32_t control;
 	struct lpfc_dmabuf *mp;
@@ -589,20 +729,22 @@
 	rc = -EIO;
 
 	/* Cleanup any outstanding ELS commands */
-	lpfc_els_flush_cmd(phba);
+	list_for_each_entry(port_iterator, &phba->port_list, listentry)
+		lpfc_els_flush_cmd(port_iterator);
 
 	psli->slistat.link_event++;
 	lpfc_read_la(phba, pmb, mp);
 	pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
+	pmb->vport = vport;
 	rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
 	if (rc == MBX_NOT_FINISHED)
 		goto lpfc_handle_latt_free_mbuf;
 
 	/* Clear Link Attention in HA REG */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	writel(HA_LATT, phba->HAregaddr);
 	readl(phba->HAregaddr); /* flush */
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	return;
 
@@ -614,7 +756,7 @@
 	mempool_free(pmb, phba->mbox_mem_pool);
 lpfc_handle_latt_err_exit:
 	/* Enable Link attention interrupts */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	psli->sli_flag |= LPFC_PROCESS_LA;
 	control = readl(phba->HCregaddr);
 	control |= HC_LAINT_ENA;
@@ -624,15 +766,13 @@
 	/* Clear Link Attention in HA REG */
 	writel(HA_LATT, phba->HAregaddr);
 	readl(phba->HAregaddr); /* flush */
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 	lpfc_linkdown(phba);
-	phba->hba_state = LPFC_HBA_ERROR;
+	phba->link_state = LPFC_HBA_ERROR;
 
 	/* The other case is an error from issue_mbox */
 	if (rc == -ENOMEM)
-		lpfc_printf_log(phba,
-				KERN_WARNING,
-				LOG_MBOX,
+		lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
 			        "%d:0300 READ_LA: no buffers\n",
 				phba->brd_no);
 
@@ -646,7 +786,7 @@
 /*                                                                      */
 /************************************************************************/
 static int
-lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
+lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
 {
 	uint8_t lenlo, lenhi;
 	int Length;
@@ -658,9 +798,7 @@
 		return 0;
 
 	/* Vital Product */
-	lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_INIT,
+	lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
 			"%d:0455 Vital Product Data: x%x x%x x%x x%x\n",
 			phba->brd_no,
 			(uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2],
@@ -785,7 +923,7 @@
 }
 
 static void
-lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
+lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
 {
 	lpfc_vpd_t *vp;
 	uint16_t dev_id = phba->pcidev->device;
@@ -943,7 +1081,7 @@
 /*   Returns the number of buffers NOT posted.    */
 /**************************************************/
 int
-lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
+lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt,
 		 int type)
 {
 	IOCB_t *icmd;
@@ -955,9 +1093,7 @@
 	/* While there are buffers to post */
 	while (cnt > 0) {
 		/* Allocate buffer for  command iocb */
-		spin_lock_irq(phba->host->host_lock);
 		iocb = lpfc_sli_get_iocbq(phba);
-		spin_unlock_irq(phba->host->host_lock);
 		if (iocb == NULL) {
 			pring->missbufcnt = cnt;
 			return cnt;
@@ -972,9 +1108,7 @@
 						&mp1->phys);
 		if (mp1 == 0 || mp1->virt == 0) {
 			kfree(mp1);
-			spin_lock_irq(phba->host->host_lock);
 			lpfc_sli_release_iocbq(phba, iocb);
-			spin_unlock_irq(phba->host->host_lock);
 			pring->missbufcnt = cnt;
 			return cnt;
 		}
@@ -990,9 +1124,7 @@
 				kfree(mp2);
 				lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
 				kfree(mp1);
-				spin_lock_irq(phba->host->host_lock);
 				lpfc_sli_release_iocbq(phba, iocb);
-				spin_unlock_irq(phba->host->host_lock);
 				pring->missbufcnt = cnt;
 				return cnt;
 			}
@@ -1018,7 +1150,6 @@
 		icmd->ulpCommand = CMD_QUE_RING_BUF64_CN;
 		icmd->ulpLe = 1;
 
-		spin_lock_irq(phba->host->host_lock);
 		if (lpfc_sli_issue_iocb(phba, pring, iocb, 0) == IOCB_ERROR) {
 			lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
 			kfree(mp1);
@@ -1030,14 +1161,11 @@
 			}
 			lpfc_sli_release_iocbq(phba, iocb);
 			pring->missbufcnt = cnt;
-			spin_unlock_irq(phba->host->host_lock);
 			return cnt;
 		}
-		spin_unlock_irq(phba->host->host_lock);
 		lpfc_sli_ringpostbuf_put(phba, pring, mp1);
-		if (mp2) {
+		if (mp2)
 			lpfc_sli_ringpostbuf_put(phba, pring, mp2);
-		}
 	}
 	pring->missbufcnt = 0;
 	return 0;
@@ -1050,7 +1178,7 @@
 /*                                                                      */
 /************************************************************************/
 static int
-lpfc_post_rcv_buf(struct lpfc_hba * phba)
+lpfc_post_rcv_buf(struct lpfc_hba *phba)
 {
 	struct lpfc_sli *psli = &phba->sli;
 
@@ -1151,7 +1279,7 @@
 {
 	int t;
 	uint32_t *HashWorking;
-	uint32_t *pwwnn = phba->wwnn;
+	uint32_t *pwwnn = (uint32_t *) phba->wwnn;
 
 	HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL);
 	if (!HashWorking)
@@ -1170,64 +1298,76 @@
 }
 
 static void
-lpfc_cleanup(struct lpfc_hba * phba)
+lpfc_cleanup(struct lpfc_vport *vport)
 {
 	struct lpfc_nodelist *ndlp, *next_ndlp;
 
 	/* clean up phba - lpfc specific */
-	lpfc_can_disctmo(phba);
-	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
+	lpfc_can_disctmo(vport);
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
 		lpfc_nlp_put(ndlp);
-
-	INIT_LIST_HEAD(&phba->fc_nodes);
-
 	return;
 }
 
 static void
 lpfc_establish_link_tmo(unsigned long ptr)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+	struct lpfc_hba   *phba = (struct lpfc_hba *) ptr;
+	struct lpfc_vport *vport = phba->pport;
 	unsigned long iflag;
 
-
 	/* Re-establishing Link, timer expired */
 	lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
 			"%d:1300 Re-establishing Link, timer expired "
 			"Data: x%x x%x\n",
-			phba->brd_no, phba->fc_flag, phba->hba_state);
-	spin_lock_irqsave(phba->host->host_lock, iflag);
-	phba->fc_flag &= ~FC_ESTABLISH_LINK;
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+			phba->brd_no, vport->fc_flag,
+			vport->port_state);
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+		spin_lock_irqsave(shost->host_lock, iflag);
+		vport->fc_flag &= ~FC_ESTABLISH_LINK;
+		spin_unlock_irqrestore(shost->host_lock, iflag);
+	}
 }
 
-static int
-lpfc_stop_timer(struct lpfc_hba * phba)
+void
+lpfc_stop_vport_timers(struct lpfc_vport *vport)
 {
-	struct lpfc_sli *psli = &phba->sli;
+	del_timer_sync(&vport->els_tmofunc);
+	del_timer_sync(&vport->fc_fdmitmo);
+	lpfc_can_disctmo(vport);
+	return;
+}
+
+static void
+lpfc_stop_phba_timers(struct lpfc_hba *phba)
+{
+	struct lpfc_vport *vport;
 
 	del_timer_sync(&phba->fcp_poll_timer);
 	del_timer_sync(&phba->fc_estabtmo);
-	del_timer_sync(&phba->fc_disctmo);
-	del_timer_sync(&phba->fc_fdmitmo);
-	del_timer_sync(&phba->els_tmofunc);
-	psli = &phba->sli;
-	del_timer_sync(&psli->mbox_tmo);
-	return(1);
+	list_for_each_entry(vport, &phba->port_list, listentry)
+		lpfc_stop_vport_timers(vport);
+	del_timer_sync(&phba->sli.mbox_tmo);
+	del_timer_sync(&phba->fabric_block_timer);
+	phba->hb_outstanding = 0;
+	del_timer_sync(&phba->hb_tmofunc);
+	return;
 }
 
 int
-lpfc_online(struct lpfc_hba * phba)
+lpfc_online(struct lpfc_hba *phba)
 {
+	struct lpfc_vport *vport = phba->pport;
+
 	if (!phba)
 		return 0;
 
-	if (!(phba->fc_flag & FC_OFFLINE_MODE))
+	if (!(vport->fc_flag & FC_OFFLINE_MODE))
 		return 0;
 
-	lpfc_printf_log(phba,
-		       KERN_WARNING,
-		       LOG_INIT,
+	lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
 		       "%d:0458 Bring Adapter online\n",
 		       phba->brd_no);
 
@@ -1243,9 +1383,14 @@
 		return 1;
 	}
 
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag &= ~FC_OFFLINE_MODE;
-	spin_unlock_irq(phba->host->host_lock);
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag &= ~FC_OFFLINE_MODE;
+		if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+			vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+		spin_unlock_irq(shost->host_lock);
+	}
 
 	lpfc_unblock_mgmt_io(phba);
 	return 0;
@@ -1256,9 +1401,9 @@
 {
 	unsigned long iflag;
 
-	spin_lock_irqsave(phba->host->host_lock, iflag);
-	phba->fc_flag |= FC_BLOCK_MGMT_IO;
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+	spin_lock_irqsave(&phba->hbalock, iflag);
+	phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO;
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
 }
 
 void
@@ -1266,17 +1411,18 @@
 {
 	unsigned long iflag;
 
-	spin_lock_irqsave(phba->host->host_lock, iflag);
-	phba->fc_flag &= ~FC_BLOCK_MGMT_IO;
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+	spin_lock_irqsave(&phba->hbalock, iflag);
+	phba->sli.sli_flag &= ~LPFC_BLOCK_MGMT_IO;
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
 }
 
 void
 lpfc_offline_prep(struct lpfc_hba * phba)
 {
+	struct lpfc_vport *vport = phba->pport;
 	struct lpfc_nodelist  *ndlp, *next_ndlp;
 
-	if (phba->fc_flag & FC_OFFLINE_MODE)
+	if (vport->fc_flag & FC_OFFLINE_MODE)
 		return;
 
 	lpfc_block_mgmt_io(phba);
@@ -1284,39 +1430,49 @@
 	lpfc_linkdown(phba);
 
 	/* Issue an unreg_login to all nodes */
-	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
 		if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
-			lpfc_unreg_rpi(phba, ndlp);
+			lpfc_unreg_rpi(vport, ndlp);
 
 	lpfc_sli_flush_mbox_queue(phba);
 }
 
 void
-lpfc_offline(struct lpfc_hba * phba)
+lpfc_offline(struct lpfc_hba *phba)
 {
-	unsigned long iflag;
+	struct lpfc_vport *vport = phba->pport;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_vport *port_iterator;
 
-	if (phba->fc_flag & FC_OFFLINE_MODE)
+	if (vport->fc_flag & FC_OFFLINE_MODE)
 		return;
 
 	/* stop all timers associated with this hba */
-	lpfc_stop_timer(phba);
+	lpfc_stop_phba_timers(phba);
+	list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+		port_iterator->work_port_events = 0;
+	}
 
-	lpfc_printf_log(phba,
-		       KERN_WARNING,
-		       LOG_INIT,
+	lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
 		       "%d:0460 Bring Adapter offline\n",
 		       phba->brd_no);
 
 	/* Bring down the SLI Layer and cleanup.  The HBA is offline
 	   now.  */
 	lpfc_sli_hba_down(phba);
-	lpfc_cleanup(phba);
-	spin_lock_irqsave(phba->host->host_lock, iflag);
-	phba->work_hba_events = 0;
+	spin_lock_irq(&phba->hbalock);
 	phba->work_ha = 0;
-	phba->fc_flag |= FC_OFFLINE_MODE;
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+	vport->fc_flag |= FC_OFFLINE_MODE;
+	spin_unlock_irq(&phba->hbalock);
+	list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+		shost = lpfc_shost_from_vport(port_iterator);
+
+		lpfc_cleanup(port_iterator);
+		spin_lock_irq(shost->host_lock);
+		vport->work_port_events = 0;
+		vport->fc_flag |= FC_OFFLINE_MODE;
+		spin_unlock_irq(shost->host_lock);
+	}
 }
 
 /******************************************************************************
@@ -1326,17 +1482,17 @@
 *
 ******************************************************************************/
 static int
-lpfc_scsi_free(struct lpfc_hba * phba)
+lpfc_scsi_free(struct lpfc_hba *phba)
 {
 	struct lpfc_scsi_buf *sb, *sb_next;
 	struct lpfc_iocbq *io, *io_next;
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	/* Release all the lpfc_scsi_bufs maintained by this host. */
 	list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
 		list_del(&sb->list);
 		pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
-								sb->dma_handle);
+			      sb->dma_handle);
 		kfree(sb);
 		phba->total_scsi_bufs--;
 	}
@@ -1348,134 +1504,183 @@
 		phba->total_iocbq_bufs--;
 	}
 
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	return 0;
 }
 
-void lpfc_remove_device(struct lpfc_hba *phba)
+
+struct lpfc_vport *
+lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport)
 {
-	unsigned long iflag;
+	struct lpfc_vport *vport;
+	struct Scsi_Host  *shost;
+	int error = 0;
 
-	lpfc_free_sysfs_attr(phba);
+	shost = scsi_host_alloc(&lpfc_template, sizeof(struct lpfc_vport));
+	if (!shost)
+		goto out;
 
-	spin_lock_irqsave(phba->host->host_lock, iflag);
-	phba->fc_flag |= FC_UNLOADING;
+	vport = (struct lpfc_vport *) shost->hostdata;
+	vport->phba = phba;
 
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+	vport->load_flag |= FC_LOADING;
+	vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
 
-	fc_remove_host(phba->host);
-	scsi_remove_host(phba->host);
-
-	kthread_stop(phba->worker_thread);
-
+	shost->unique_id = instance;
+	shost->max_id = LPFC_MAX_TARGET;
+	shost->max_lun = phba->cfg_max_luns;
+	shost->this_id = -1;
+	shost->max_cmd_len = 16;
 	/*
-	 * Bring down the SLI Layer. This step disable all interrupts,
-	 * clears the rings, discards all mailbox commands, and resets
-	 * the HBA.
+	 * Set initial can_queue value since 0 is no longer supported and
+	 * scsi_add_host will fail. This will be adjusted later based on the
+	 * max xri value determined in hba setup.
 	 */
-	lpfc_sli_hba_down(phba);
-	lpfc_sli_brdrestart(phba);
+	shost->can_queue = phba->cfg_hba_queue_depth - 10;
+	if (fc_vport != NULL) {
+		shost->transportt = lpfc_vport_transport_template;
+		vport->port_type = LPFC_NPIV_PORT;
+	} else {
+		shost->transportt = lpfc_transport_template;
+		vport->port_type = LPFC_PHYSICAL_PORT;
+	}
 
-	/* Release the irq reservation */
-	free_irq(phba->pcidev->irq, phba);
-	pci_disable_msi(phba->pcidev);
+	/* Initialize all internally managed lists. */
+	INIT_LIST_HEAD(&vport->fc_nodes);
+	spin_lock_init(&vport->work_port_lock);
 
-	lpfc_cleanup(phba);
-	lpfc_stop_timer(phba);
-	phba->work_hba_events = 0;
+	init_timer(&vport->fc_disctmo);
+	vport->fc_disctmo.function = lpfc_disc_timeout;
+	vport->fc_disctmo.data = (unsigned long)vport;
 
-	/*
-	 * Call scsi_free before mem_free since scsi bufs are released to their
-	 * corresponding pools here.
-	 */
-	lpfc_scsi_free(phba);
-	lpfc_mem_free(phba);
+	init_timer(&vport->fc_fdmitmo);
+	vport->fc_fdmitmo.function = lpfc_fdmi_tmo;
+	vport->fc_fdmitmo.data = (unsigned long)vport;
 
-	/* Free resources associated with SLI2 interface */
-	dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
-			  phba->slim2p, phba->slim2p_mapping);
+	init_timer(&vport->els_tmofunc);
+	vport->els_tmofunc.function = lpfc_els_timeout;
+	vport->els_tmofunc.data = (unsigned long)vport;
 
-	/* unmap adapter SLIM and Control Registers */
-	iounmap(phba->ctrl_regs_memmap_p);
-	iounmap(phba->slim_memmap_p);
+	if (fc_vport != NULL) {
+		error = scsi_add_host(shost, &fc_vport->dev);
+	} else {
+		error = scsi_add_host(shost, &phba->pcidev->dev);
+	}
+	if (error)
+		goto out_put_shost;
 
-	pci_release_regions(phba->pcidev);
-	pci_disable_device(phba->pcidev);
+	list_add_tail(&vport->listentry, &phba->port_list);
+	return vport;
 
-	idr_remove(&lpfc_hba_index, phba->brd_no);
-	scsi_host_put(phba->host);
+out_put_shost:
+	scsi_host_put(shost);
+out:
+	return NULL;
 }
 
-void lpfc_scan_start(struct Scsi_Host *host)
+void
+destroy_port(struct lpfc_vport *vport)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
 
-	if (lpfc_alloc_sysfs_attr(phba))
-		goto error;
+	kfree(vport->vname);
 
-	phba->MBslimaddr = phba->slim_memmap_p;
-	phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
-	phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
-	phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
-	phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+	lpfc_debugfs_terminate(vport);
+	fc_remove_host(shost);
+	scsi_remove_host(shost);
 
-	if (lpfc_sli_hba_setup(phba))
-		goto error;
+	spin_lock_irq(&phba->hbalock);
+	list_del_init(&vport->listentry);
+	spin_unlock_irq(&phba->hbalock);
 
-	/*
-	 * hba setup may have changed the hba_queue_depth so we need to adjust
-	 * the value of can_queue.
-	 */
-	host->can_queue = phba->cfg_hba_queue_depth - 10;
+	lpfc_cleanup(vport);
 	return;
-
-error:
-	lpfc_remove_device(phba);
 }
 
+int
+lpfc_get_instance(void)
+{
+	int instance = 0;
+
+	/* Assign an unused number */
+	if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
+		return -1;
+	if (idr_get_new(&lpfc_hba_index, NULL, &instance))
+		return -1;
+	return instance;
+}
+
+/*
+ * Note: there is no scan_start function as adapter initialization
+ * will have asynchronously kicked off the link initialization.
+ */
+
 int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	int stat = 0;
 
-	if (!phba->host)
-		return 1;
-	if (time >= 30 * HZ)
+	spin_lock_irq(shost->host_lock);
+
+	if (vport->fc_flag & FC_UNLOADING) {
+		stat = 1;
 		goto finished;
-
-	if (phba->hba_state != LPFC_HBA_READY)
-		return 0;
-	if (phba->num_disc_nodes || phba->fc_prli_sent)
-		return 0;
-	if ((phba->fc_map_cnt == 0) && (time < 2 * HZ))
-		return 0;
-	if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)
-		return 0;
-	if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ))
-		return 0;
-
-finished:
-	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-		spin_lock_irq(shost->host_lock);
-		lpfc_poll_start_timer(phba);
-		spin_unlock_irq(shost->host_lock);
+	}
+	if (time >= 30 * HZ) {
+		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+				"%d:0461 Scanning longer than 30 "
+				"seconds.  Continuing initialization\n",
+				phba->brd_no);
+		stat = 1;
+		goto finished;
+	}
+	if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) {
+		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+				"%d:0465 Link down longer than 15 "
+				"seconds.  Continuing initialization\n",
+				phba->brd_no);
+		stat = 1;
+		goto finished;
 	}
 
+	if (vport->port_state != LPFC_VPORT_READY)
+		goto finished;
+	if (vport->num_disc_nodes || vport->fc_prli_sent)
+		goto finished;
+	if (vport->fc_map_cnt == 0 && time < 2 * HZ)
+		goto finished;
+	if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
+		goto finished;
+
+	stat = 1;
+
+finished:
+	spin_unlock_irq(shost->host_lock);
+	return stat;
+}
+
+void lpfc_host_attrib_init(struct Scsi_Host *shost)
+{
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	/*
-	 * set fixed host attributes
-	 * Must done after lpfc_sli_hba_setup()
+	 * Set fixed host attributes.  Must done after lpfc_sli_hba_setup().
 	 */
 
-	fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn);
-	fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn);
+	fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
+	fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
 	fc_host_supported_classes(shost) = FC_COS_CLASS3;
 
 	memset(fc_host_supported_fc4s(shost), 0,
-		sizeof(fc_host_supported_fc4s(shost)));
+	       sizeof(fc_host_supported_fc4s(shost)));
 	fc_host_supported_fc4s(shost)[2] = 1;
 	fc_host_supported_fc4s(shost)[7] = 1;
 
-	lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
+	lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost),
+				 sizeof fc_host_symbolic_name(shost));
 
 	fc_host_supported_speeds(shost) = 0;
 	if (phba->lmt & LMT_10Gb)
@@ -1488,31 +1693,31 @@
 		fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
 
 	fc_host_maxframe_size(shost) =
-		((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
-		 (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
+		(((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
+		(uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
 
 	/* This value is also unchanging */
 	memset(fc_host_active_fc4s(shost), 0,
-		sizeof(fc_host_active_fc4s(shost)));
+	       sizeof(fc_host_active_fc4s(shost)));
 	fc_host_active_fc4s(shost)[2] = 1;
 	fc_host_active_fc4s(shost)[7] = 1;
 
+	fc_host_max_npiv_vports(shost) = phba->max_vpi;
 	spin_lock_irq(shost->host_lock);
-	phba->fc_flag &= ~FC_LOADING;
+	vport->fc_flag &= ~FC_LOADING;
 	spin_unlock_irq(shost->host_lock);
-
-	return 1;
 }
 
 static int __devinit
 lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
-	struct Scsi_Host *host;
-	struct lpfc_hba  *phba;
-	struct lpfc_sli  *psli;
+	struct lpfc_vport *vport = NULL;
+	struct lpfc_hba   *phba;
+	struct lpfc_sli   *psli;
 	struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;
+	struct Scsi_Host  *shost = NULL;
 	unsigned long bar0map_len, bar2map_len;
-	int error = -ENODEV, retval;
+	int error = -ENODEV;
 	int i;
 	uint16_t iotag;
 
@@ -1521,67 +1726,49 @@
 	if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
 		goto out_disable_device;
 
-	host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
-	if (!host)
+	phba = kzalloc(sizeof (struct lpfc_hba), GFP_KERNEL);
+	if (!phba)
 		goto out_release_regions;
 
-	phba = (struct lpfc_hba*)host->hostdata;
-	memset(phba, 0, sizeof (struct lpfc_hba));
-	phba->host = host;
+	spin_lock_init(&phba->hbalock);
 
-	phba->fc_flag |= FC_LOADING;
 	phba->pcidev = pdev;
 
 	/* Assign an unused board number */
-	if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
-		goto out_put_host;
+	if ((phba->brd_no = lpfc_get_instance()) < 0)
+		goto out_free_phba;
 
-	error = idr_get_new(&lpfc_hba_index, NULL, &phba->brd_no);
-	if (error)
-		goto out_put_host;
-
-	host->unique_id = phba->brd_no;
+	INIT_LIST_HEAD(&phba->port_list);
+	INIT_LIST_HEAD(&phba->hbq_buffer_list);
+	/*
+	 * Get all the module params for configuring this host and then
+	 * establish the host.
+	 */
+	lpfc_get_cfgparam(phba);
+	phba->max_vpi = LPFC_MAX_VPI;
 
 	/* Initialize timers used by driver */
 	init_timer(&phba->fc_estabtmo);
 	phba->fc_estabtmo.function = lpfc_establish_link_tmo;
 	phba->fc_estabtmo.data = (unsigned long)phba;
-	init_timer(&phba->fc_disctmo);
-	phba->fc_disctmo.function = lpfc_disc_timeout;
-	phba->fc_disctmo.data = (unsigned long)phba;
 
-	init_timer(&phba->fc_fdmitmo);
-	phba->fc_fdmitmo.function = lpfc_fdmi_tmo;
-	phba->fc_fdmitmo.data = (unsigned long)phba;
-	init_timer(&phba->els_tmofunc);
-	phba->els_tmofunc.function = lpfc_els_timeout;
-	phba->els_tmofunc.data = (unsigned long)phba;
+	init_timer(&phba->hb_tmofunc);
+	phba->hb_tmofunc.function = lpfc_hb_timeout;
+	phba->hb_tmofunc.data = (unsigned long)phba;
+
 	psli = &phba->sli;
 	init_timer(&psli->mbox_tmo);
 	psli->mbox_tmo.function = lpfc_mbox_timeout;
-	psli->mbox_tmo.data = (unsigned long)phba;
-
+	psli->mbox_tmo.data = (unsigned long) phba;
 	init_timer(&phba->fcp_poll_timer);
 	phba->fcp_poll_timer.function = lpfc_poll_timeout;
-	phba->fcp_poll_timer.data = (unsigned long)phba;
-
-	/*
-	 * Get all the module params for configuring this host and then
-	 * establish the host parameters.
-	 */
-	lpfc_get_cfgparam(phba);
-
-	host->max_id = LPFC_MAX_TARGET;
-	host->max_lun = phba->cfg_max_luns;
-	host->this_id = -1;
-
-	INIT_LIST_HEAD(&phba->fc_nodes);
+	phba->fcp_poll_timer.data = (unsigned long) phba;
+	init_timer(&phba->fabric_block_timer);
+	phba->fabric_block_timer.function = lpfc_fabric_block_timeout;
+	phba->fabric_block_timer.data = (unsigned long) phba;
 
 	pci_set_master(pdev);
-	retval = pci_set_mwi(pdev);
-	if (retval)
-		dev_printk(KERN_WARNING, &pdev->dev,
-			   "Warning: pci_set_mwi returned %d\n", retval);
+	pci_try_set_mwi(pdev);
 
 	if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0)
 		if (pci_set_dma_mask(phba->pcidev, DMA_32BIT_MASK) != 0)
@@ -1623,13 +1810,22 @@
 
 	memset(phba->slim2p, 0, SLI2_SLIM_SIZE);
 
+	phba->hbqslimp.virt = dma_alloc_coherent(&phba->pcidev->dev,
+						 lpfc_sli_hbq_size(),
+						 &phba->hbqslimp.phys,
+						 GFP_KERNEL);
+	if (!phba->hbqslimp.virt)
+		goto out_free_slim;
+
+	memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size());
+
 	/* Initialize the SLI Layer to run with lpfc HBAs. */
 	lpfc_sli_setup(phba);
 	lpfc_sli_queue_setup(phba);
 
 	error = lpfc_mem_alloc(phba);
 	if (error)
-		goto out_free_slim;
+		goto out_free_hbqslimp;
 
 	/* Initialize and populate the iocb list per host.  */
 	INIT_LIST_HEAD(&phba->lpfc_iocb_list);
@@ -1653,10 +1849,11 @@
 			error = -ENOMEM;
 			goto out_free_iocbq;
 		}
-		spin_lock_irq(phba->host->host_lock);
+
+		spin_lock_irq(&phba->hbalock);
 		list_add(&iocbq_entry->list, &phba->lpfc_iocb_list);
 		phba->total_iocbq_bufs++;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 	}
 
 	/* Initialize HBA structure */
@@ -1677,22 +1874,22 @@
 		goto out_free_iocbq;
 	}
 
-	/*
-	 * Set initial can_queue value since 0 is no longer supported and
-	 * scsi_add_host will fail. This will be adjusted later based on the
-	 * max xri value determined in hba setup.
-	 */
-	host->can_queue = phba->cfg_hba_queue_depth - 10;
-
-	/* Tell the midlayer we support 16 byte commands */
-	host->max_cmd_len = 16;
-
 	/* Initialize the list of scsi buffers used by driver for scsi IO. */
 	spin_lock_init(&phba->scsi_buf_list_lock);
 	INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
 
-	host->transportt = lpfc_transport_template;
-	pci_set_drvdata(pdev, host);
+	/* Initialize list of fabric iocbs */
+	INIT_LIST_HEAD(&phba->fabric_iocb_list);
+
+	vport = lpfc_create_port(phba, phba->brd_no, NULL);
+	if (!vport)
+		goto out_kthread_stop;
+
+	shost = lpfc_shost_from_vport(vport);
+	phba->pport = vport;
+	lpfc_debugfs_initialize(vport);
+
+	pci_set_drvdata(pdev, shost);
 
 	if (phba->cfg_use_msi) {
 		error = pci_enable_msi(phba->pcidev);
@@ -1703,38 +1900,68 @@
 	}
 
 	error =	request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED,
-							LPFC_DRIVER_NAME, phba);
+			    LPFC_DRIVER_NAME, phba);
 	if (error) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 			"%d:0451 Enable interrupt handler failed\n",
 			phba->brd_no);
-		goto out_kthread_stop;
+		goto out_disable_msi;
 	}
 
-	error = scsi_add_host(host, &pdev->dev);
-	if (error)
+	phba->MBslimaddr = phba->slim_memmap_p;
+	phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
+	phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
+	phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
+	phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+
+	if (lpfc_alloc_sysfs_attr(vport))
 		goto out_free_irq;
 
-	scsi_scan_host(host);
+	if (lpfc_sli_hba_setup(phba))
+		goto out_remove_device;
+
+	/*
+	 * hba setup may have changed the hba_queue_depth so we need to adjust
+	 * the value of can_queue.
+	 */
+	shost->can_queue = phba->cfg_hba_queue_depth - 10;
+
+	lpfc_host_attrib_init(shost);
+
+	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+		spin_lock_irq(shost->host_lock);
+		lpfc_poll_start_timer(phba);
+		spin_unlock_irq(shost->host_lock);
+	}
+
+	scsi_scan_host(shost);
 
 	return 0;
 
+out_remove_device:
+	lpfc_free_sysfs_attr(vport);
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag |= FC_UNLOADING;
+	spin_unlock_irq(shost->host_lock);
 out_free_irq:
-	lpfc_stop_timer(phba);
-	phba->work_hba_events = 0;
+	lpfc_stop_phba_timers(phba);
+	phba->pport->work_port_events = 0;
 	free_irq(phba->pcidev->irq, phba);
+out_disable_msi:
 	pci_disable_msi(phba->pcidev);
+	destroy_port(vport);
 out_kthread_stop:
 	kthread_stop(phba->worker_thread);
 out_free_iocbq:
 	list_for_each_entry_safe(iocbq_entry, iocbq_next,
 						&phba->lpfc_iocb_list, list) {
-		spin_lock_irq(phba->host->host_lock);
 		kfree(iocbq_entry);
 		phba->total_iocbq_bufs--;
-		spin_unlock_irq(phba->host->host_lock);
 	}
 	lpfc_mem_free(phba);
+out_free_hbqslimp:
+	dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
+			  phba->hbqslimp.phys);
 out_free_slim:
 	dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, phba->slim2p,
 							phba->slim2p_mapping);
@@ -1744,27 +1971,85 @@
 	iounmap(phba->slim_memmap_p);
 out_idr_remove:
 	idr_remove(&lpfc_hba_index, phba->brd_no);
-out_put_host:
-	phba->host = NULL;
-	scsi_host_put(host);
+out_free_phba:
+	kfree(phba);
 out_release_regions:
 	pci_release_regions(pdev);
 out_disable_device:
 	pci_disable_device(pdev);
 out:
 	pci_set_drvdata(pdev, NULL);
+	if (shost)
+		scsi_host_put(shost);
 	return error;
 }
 
 static void __devexit
 lpfc_pci_remove_one(struct pci_dev *pdev)
 {
-	struct Scsi_Host   *host = pci_get_drvdata(pdev);
-	struct lpfc_hba    *phba = (struct lpfc_hba *)host->hostdata;
+	struct Scsi_Host  *shost = pci_get_drvdata(pdev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_vport *port_iterator;
+	list_for_each_entry(port_iterator, &phba->port_list, listentry)
+		port_iterator->load_flag |= FC_UNLOADING;
 
-	lpfc_remove_device(phba);
+	kfree(vport->vname);
+	lpfc_free_sysfs_attr(vport);
+
+	fc_remove_host(shost);
+	scsi_remove_host(shost);
+
+	/*
+	 * Bring down the SLI Layer. This step disable all interrupts,
+	 * clears the rings, discards all mailbox commands, and resets
+	 * the HBA.
+	 */
+	lpfc_sli_hba_down(phba);
+	lpfc_sli_brdrestart(phba);
+
+	lpfc_stop_phba_timers(phba);
+	spin_lock_irq(&phba->hbalock);
+	list_del_init(&vport->listentry);
+	spin_unlock_irq(&phba->hbalock);
+
+
+	lpfc_debugfs_terminate(vport);
+	lpfc_cleanup(vport);
+
+	kthread_stop(phba->worker_thread);
+
+	/* Release the irq reservation */
+	free_irq(phba->pcidev->irq, phba);
+	pci_disable_msi(phba->pcidev);
 
 	pci_set_drvdata(pdev, NULL);
+	scsi_host_put(shost);
+
+	/*
+	 * Call scsi_free before mem_free since scsi bufs are released to their
+	 * corresponding pools here.
+	 */
+	lpfc_scsi_free(phba);
+	lpfc_mem_free(phba);
+
+	dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
+			  phba->hbqslimp.phys);
+
+	/* Free resources associated with SLI2 interface */
+	dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
+			  phba->slim2p, phba->slim2p_mapping);
+
+	/* unmap adapter SLIM and Control Registers */
+	iounmap(phba->ctrl_regs_memmap_p);
+	iounmap(phba->slim_memmap_p);
+
+	idr_remove(&lpfc_hba_index, phba->brd_no);
+
+	kfree(phba);
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
 }
 
 /**
@@ -1822,10 +2107,13 @@
 	pci_set_master(pdev);
 
 	/* Re-establishing Link */
-	spin_lock_irq(phba->host->host_lock);
-	phba->fc_flag |= FC_ESTABLISH_LINK;
+	spin_lock_irq(host->host_lock);
+	phba->pport->fc_flag |= FC_ESTABLISH_LINK;
+	spin_unlock_irq(host->host_lock);
+
+	spin_lock_irq(&phba->hbalock);
 	psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 
 	/* Take device offline; this will perform cleanup */
@@ -1935,7 +2223,7 @@
 	.id_table	= lpfc_id_table,
 	.probe		= lpfc_pci_probe_one,
 	.remove		= __devexit_p(lpfc_pci_remove_one),
-	.err_handler = &lpfc_err_handler,
+	.err_handler    = &lpfc_err_handler,
 };
 
 static int __init
@@ -1948,11 +2236,15 @@
 
 	lpfc_transport_template =
 				fc_attach_transport(&lpfc_transport_functions);
-	if (!lpfc_transport_template)
+	lpfc_vport_transport_template =
+			fc_attach_transport(&lpfc_vport_transport_functions);
+	if (!lpfc_transport_template || !lpfc_vport_transport_template)
 		return -ENOMEM;
 	error = pci_register_driver(&lpfc_driver);
-	if (error)
+	if (error) {
 		fc_release_transport(lpfc_transport_template);
+		fc_release_transport(lpfc_vport_transport_template);
+	}
 
 	return error;
 }
@@ -1962,6 +2254,7 @@
 {
 	pci_unregister_driver(&lpfc_driver);
 	fc_release_transport(lpfc_transport_template);
+	fc_release_transport(lpfc_vport_transport_template);
 }
 
 module_init(lpfc_init);
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index 438cbcd..8a6ceff 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -30,6 +30,7 @@
 #define LOG_SLI                       0x800	/* SLI events */
 #define LOG_FCP_ERROR                 0x1000	/* log errors, not underruns */
 #define LOG_LIBDFC                    0x2000	/* Libdfc events */
+#define LOG_VPORT                     0x4000	/* NPIV events */
 #define LOG_ALL_MSG                   0xffff	/* LOG all messages */
 
 #define lpfc_printf_log(phba, level, mask, fmt, arg...) \
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 8041c3f..8f42fbf 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -82,6 +82,22 @@
 }
 
 /**********************************************/
+/*  lpfc_heart_beat  Issue a HEART_BEAT       */
+/*                mailbox command             */
+/**********************************************/
+void
+lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+{
+	MAILBOX_t *mb;
+
+	mb = &pmb->mb;
+	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+	mb->mbxCommand = MBX_HEARTBEAT;
+	mb->mbxOwner = OWN_HOST;
+	return;
+}
+
+/**********************************************/
 /*  lpfc_read_la  Issue a READ LA             */
 /*                mailbox command             */
 /**********************************************/
@@ -134,6 +150,7 @@
 void
 lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 {
+	struct lpfc_vport  *vport = phba->pport;
 	MAILBOX_t *mb = &pmb->mb;
 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
@@ -147,7 +164,7 @@
 		mb->un.varCfgLnk.cr_count = phba->cfg_cr_count;
 	}
 
-	mb->un.varCfgLnk.myId = phba->fc_myDID;
+	mb->un.varCfgLnk.myId = vport->fc_myDID;
 	mb->un.varCfgLnk.edtov = phba->fc_edtov;
 	mb->un.varCfgLnk.arbtov = phba->fc_arbtov;
 	mb->un.varCfgLnk.ratov = phba->fc_ratov;
@@ -239,7 +256,7 @@
 /*                    mailbox command         */
 /**********************************************/
 int
-lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
 {
 	struct lpfc_dmabuf *mp;
 	MAILBOX_t *mb;
@@ -270,6 +287,7 @@
 	mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
 	mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
 	mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
+	mb->un.varRdSparm.vpi = vpi;
 
 	/* save address for completion */
 	pmb->context1 = mp;
@@ -282,7 +300,8 @@
 /*                  mailbox command         */
 /********************************************/
 void
-lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
+lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
+	       LPFC_MBOXQ_t * pmb)
 {
 	MAILBOX_t *mb;
 
@@ -290,6 +309,7 @@
 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
 	mb->un.varUnregDID.did = did;
+	mb->un.varUnregDID.vpi = vpi;
 
 	mb->mbxCommand = MBX_UNREG_D_ID;
 	mb->mbxOwner = OWN_HOST;
@@ -335,19 +355,17 @@
 /*                  mailbox command         */
 /********************************************/
 int
-lpfc_reg_login(struct lpfc_hba * phba,
-	       uint32_t did, uint8_t * param, LPFC_MBOXQ_t * pmb, uint32_t flag)
+lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
+	       uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag)
 {
+	MAILBOX_t *mb = &pmb->mb;
 	uint8_t *sparam;
 	struct lpfc_dmabuf *mp;
-	MAILBOX_t *mb;
-	struct lpfc_sli *psli;
 
-	psli = &phba->sli;
-	mb = &pmb->mb;
 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
 	mb->un.varRegLogin.rpi = 0;
+	mb->un.varRegLogin.vpi = vpi;
 	mb->un.varRegLogin.did = did;
 	mb->un.varWords[30] = flag;	/* Set flag to issue action on cmpl */
 
@@ -359,12 +377,10 @@
 		kfree(mp);
 		mb->mbxCommand = MBX_REG_LOGIN64;
 		/* REG_LOGIN: no buffers */
-		lpfc_printf_log(phba,
-			       KERN_WARNING,
-			       LOG_MBOX,
-			       "%d:0302 REG_LOGIN: no buffers Data x%x x%x\n",
-			       phba->brd_no,
-			       (uint32_t) did, (uint32_t) flag);
+		lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
+				"%d (%d):0302 REG_LOGIN: no buffers, DID x%x, "
+				"flag x%x\n",
+				phba->brd_no, vpi, did, flag);
 		return (1);
 	}
 	INIT_LIST_HEAD(&mp->list);
@@ -389,7 +405,8 @@
 /*                    mailbox command         */
 /**********************************************/
 void
-lpfc_unreg_login(struct lpfc_hba * phba, uint32_t rpi, LPFC_MBOXQ_t * pmb)
+lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
+		 LPFC_MBOXQ_t * pmb)
 {
 	MAILBOX_t *mb;
 
@@ -398,12 +415,52 @@
 
 	mb->un.varUnregLogin.rpi = (uint16_t) rpi;
 	mb->un.varUnregLogin.rsvd1 = 0;
+	mb->un.varUnregLogin.vpi = vpi;
 
 	mb->mbxCommand = MBX_UNREG_LOGIN;
 	mb->mbxOwner = OWN_HOST;
 	return;
 }
 
+/**************************************************/
+/*  lpfc_reg_vpi   Issue a REG_VPI                */
+/*                    mailbox command             */
+/**************************************************/
+void
+lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
+	     LPFC_MBOXQ_t *pmb)
+{
+	MAILBOX_t *mb = &pmb->mb;
+
+	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+
+	mb->un.varRegVpi.vpi = vpi;
+	mb->un.varRegVpi.sid = sid;
+
+	mb->mbxCommand = MBX_REG_VPI;
+	mb->mbxOwner = OWN_HOST;
+	return;
+
+}
+
+/**************************************************/
+/*  lpfc_unreg_vpi   Issue a UNREG_VNPI           */
+/*                    mailbox command             */
+/**************************************************/
+void
+lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
+{
+	MAILBOX_t *mb = &pmb->mb;
+	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+
+	mb->un.varUnregVpi.vpi = vpi;
+
+	mb->mbxCommand = MBX_UNREG_VPI;
+	mb->mbxOwner = OWN_HOST;
+	return;
+
+}
+
 static void
 lpfc_config_pcb_setup(struct lpfc_hba * phba)
 {
@@ -412,14 +469,18 @@
 	PCB_t *pcbp = &phba->slim2p->pcb;
 	dma_addr_t pdma_addr;
 	uint32_t offset;
-	uint32_t iocbCnt;
+	uint32_t iocbCnt = 0;
 	int i;
 
 	pcbp->maxRing = (psli->num_rings - 1);
 
-	iocbCnt = 0;
 	for (i = 0; i < psli->num_rings; i++) {
 		pring = &psli->ring[i];
+
+		pring->sizeCiocb = phba->sli_rev == 3 ? SLI3_IOCB_CMD_SIZE:
+							SLI2_IOCB_CMD_SIZE;
+		pring->sizeRiocb = phba->sli_rev == 3 ? SLI3_IOCB_RSP_SIZE:
+							SLI2_IOCB_RSP_SIZE;
 		/* A ring MUST have both cmd and rsp entries defined to be
 		   valid */
 		if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
@@ -434,20 +495,18 @@
 			continue;
 		}
 		/* Command ring setup for ring */
-		pring->cmdringaddr =
-		    (void *)&phba->slim2p->IOCBs[iocbCnt];
+		pring->cmdringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
 		pcbp->rdsc[i].cmdEntries = pring->numCiocb;
 
-		offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
-			 (uint8_t *)phba->slim2p;
+		offset = (uint8_t *) &phba->slim2p->IOCBs[iocbCnt] -
+			 (uint8_t *) phba->slim2p;
 		pdma_addr = phba->slim2p_mapping + offset;
 		pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr);
 		pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr);
 		iocbCnt += pring->numCiocb;
 
 		/* Response ring setup for ring */
-		pring->rspringaddr =
-		    (void *)&phba->slim2p->IOCBs[iocbCnt];
+		pring->rspringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
 
 		pcbp->rdsc[i].rspEntries = pring->numRiocb;
 		offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
@@ -462,16 +521,108 @@
 void
 lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 {
-	MAILBOX_t *mb;
-
-	mb = &pmb->mb;
+	MAILBOX_t *mb = &pmb->mb;
 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 	mb->un.varRdRev.cv = 1;
+	mb->un.varRdRev.v3req = 1; /* Request SLI3 info */
 	mb->mbxCommand = MBX_READ_REV;
 	mb->mbxOwner = OWN_HOST;
 	return;
 }
 
+static void
+lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
+			struct lpfc_hbq_init  *hbq_desc)
+{
+	hbqmb->profiles.profile2.seqlenbcnt = hbq_desc->seqlenbcnt;
+	hbqmb->profiles.profile2.maxlen     = hbq_desc->maxlen;
+	hbqmb->profiles.profile2.seqlenoff  = hbq_desc->seqlenoff;
+}
+
+static void
+lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
+			struct lpfc_hbq_init  *hbq_desc)
+{
+	hbqmb->profiles.profile3.seqlenbcnt = hbq_desc->seqlenbcnt;
+	hbqmb->profiles.profile3.maxlen     = hbq_desc->maxlen;
+	hbqmb->profiles.profile3.cmdcodeoff = hbq_desc->cmdcodeoff;
+	hbqmb->profiles.profile3.seqlenoff  = hbq_desc->seqlenoff;
+	memcpy(&hbqmb->profiles.profile3.cmdmatch, hbq_desc->cmdmatch,
+	       sizeof(hbqmb->profiles.profile3.cmdmatch));
+}
+
+static void
+lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
+			struct lpfc_hbq_init  *hbq_desc)
+{
+	hbqmb->profiles.profile5.seqlenbcnt = hbq_desc->seqlenbcnt;
+	hbqmb->profiles.profile5.maxlen     = hbq_desc->maxlen;
+	hbqmb->profiles.profile5.cmdcodeoff = hbq_desc->cmdcodeoff;
+	hbqmb->profiles.profile5.seqlenoff  = hbq_desc->seqlenoff;
+	memcpy(&hbqmb->profiles.profile5.cmdmatch, hbq_desc->cmdmatch,
+	       sizeof(hbqmb->profiles.profile5.cmdmatch));
+}
+
+void
+lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc,
+		uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb)
+{
+	int i;
+	MAILBOX_t *mb = &pmb->mb;
+	struct config_hbq_var *hbqmb = &mb->un.varCfgHbq;
+
+	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+	hbqmb->entry_count = hbq_desc->entry_count;   /* # entries in HBQ */
+	hbqmb->recvNotify = hbq_desc->rn;             /* Receive
+						       * Notification */
+	hbqmb->numMask    = hbq_desc->mask_count;     /* # R_CTL/TYPE masks
+						       * # in words 0-19 */
+	hbqmb->profile    = hbq_desc->profile;	      /* Selection profile:
+						       * 0 = all,
+						       * 7 = logentry */
+	hbqmb->ringMask   = hbq_desc->ring_mask;      /* Binds HBQ to a ring
+						       * e.g. Ring0=b0001,
+						       * ring2=b0100 */
+	hbqmb->headerLen  = hbq_desc->headerLen;      /* 0 if not profile 4
+						       * or 5 */
+	hbqmb->logEntry   = hbq_desc->logEntry;       /* Set to 1 if this
+						       * HBQ will be used
+						       * for LogEntry
+						       * buffers */
+	hbqmb->hbqaddrLow = putPaddrLow(phba->hbqslimp.phys) +
+		hbq_entry_index * sizeof(struct lpfc_hbq_entry);
+	hbqmb->hbqaddrHigh = putPaddrHigh(phba->hbqslimp.phys);
+
+	mb->mbxCommand = MBX_CONFIG_HBQ;
+	mb->mbxOwner = OWN_HOST;
+
+				/* Copy info for profiles 2,3,5. Other
+				 * profiles this area is reserved
+				 */
+	if (hbq_desc->profile == 2)
+		lpfc_build_hbq_profile2(hbqmb, hbq_desc);
+	else if (hbq_desc->profile == 3)
+		lpfc_build_hbq_profile3(hbqmb, hbq_desc);
+	else if (hbq_desc->profile == 5)
+		lpfc_build_hbq_profile5(hbqmb, hbq_desc);
+
+	/* Return if no rctl / type masks for this HBQ */
+	if (!hbq_desc->mask_count)
+		return;
+
+	/* Otherwise we setup specific rctl / type masks for this HBQ */
+	for (i = 0; i < hbq_desc->mask_count; i++) {
+		hbqmb->hbqMasks[i].tmatch = hbq_desc->hbqMasks[i].tmatch;
+		hbqmb->hbqMasks[i].tmask  = hbq_desc->hbqMasks[i].tmask;
+		hbqmb->hbqMasks[i].rctlmatch = hbq_desc->hbqMasks[i].rctlmatch;
+		hbqmb->hbqMasks[i].rctlmask  = hbq_desc->hbqMasks[i].rctlmask;
+	}
+
+	return;
+}
+
+
+
 void
 lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
 {
@@ -514,15 +665,16 @@
 }
 
 void
-lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
+	MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr;
 	MAILBOX_t *mb = &pmb->mb;
 	dma_addr_t pdma_addr;
 	uint32_t bar_low, bar_high;
 	size_t offset;
 	struct lpfc_hgp hgp;
-	void __iomem *to_slim;
 	int i;
+	uint32_t pgp_offset;
 
 	memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
 	mb->mbxCommand = MBX_CONFIG_PORT;
@@ -535,12 +687,29 @@
 	mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
 	mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
 
+	/* If HBA supports SLI=3 ask for it */
+
+	if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
+		mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
+		mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */
+		if (phba->max_vpi && phba->cfg_npiv_enable &&
+		    phba->vpd.sli3Feat.cmv) {
+			mb->un.varCfgPort.max_vpi = phba->max_vpi;
+			mb->un.varCfgPort.cmv = 1;
+			phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
+		} else
+			mb->un.varCfgPort.max_vpi = phba->max_vpi = 0;
+	} else
+		phba->sli_rev = 2;
+	mb->un.varCfgPort.sli_mode = phba->sli_rev;
+
 	/* Now setup pcb */
 	phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
 	phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
 
 	/* Setup Mailbox pointers */
-	phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t);
+	phba->slim2p->pcb.mailBoxSize = offsetof(MAILBOX_t, us) +
+		sizeof(struct sli2_desc);
 	offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
 	pdma_addr = phba->slim2p_mapping + offset;
 	phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
@@ -568,29 +737,70 @@
 	pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
 	pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
 
+	/*
+	 * Set up HGP - Port Memory
+	 *
+	 * The port expects the host get/put pointers to reside in memory
+	 * following the "non-diagnostic" mode mailbox (32 words, 0x80 bytes)
+	 * area of SLIM.  In SLI-2 mode, there's an additional 16 reserved
+	 * words (0x40 bytes).  This area is not reserved if HBQs are
+	 * configured in SLI-3.
+	 *
+	 * CR0Put    - SLI2(no HBQs) = 0xc0, With HBQs = 0x80
+	 * RR0Get                      0xc4              0x84
+	 * CR1Put                      0xc8              0x88
+	 * RR1Get                      0xcc              0x8c
+	 * CR2Put                      0xd0              0x90
+	 * RR2Get                      0xd4              0x94
+	 * CR3Put                      0xd8              0x98
+	 * RR3Get                      0xdc              0x9c
+	 *
+	 * Reserved                    0xa0-0xbf
+	 *    If HBQs configured:
+	 *                         HBQ 0 Put ptr  0xc0
+	 *                         HBQ 1 Put ptr  0xc4
+	 *                         HBQ 2 Put ptr  0xc8
+	 *                         ......
+	 *                         HBQ(M-1)Put Pointer 0xc0+(M-1)*4
+	 *
+	 */
+
+	if (phba->sli_rev == 3) {
+		phba->host_gp = &mb_slim->us.s3.host[0];
+		phba->hbq_put = &mb_slim->us.s3.hbq_put[0];
+	} else {
+		phba->host_gp = &mb_slim->us.s2.host[0];
+		phba->hbq_put = NULL;
+	}
 
 	/* mask off BAR0's flag bits 0 - 3 */
 	phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
-					(SLIMOFF*sizeof(uint32_t));
+		(void __iomem *) phba->host_gp -
+		(void __iomem *)phba->MBslimaddr;
 	if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
 		phba->slim2p->pcb.hgpAddrHigh = bar_high;
 	else
 		phba->slim2p->pcb.hgpAddrHigh = 0;
 	/* write HGP data to SLIM at the required longword offset */
 	memset(&hgp, 0, sizeof(struct lpfc_hgp));
-	to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
 
 	for (i=0; i < phba->sli.num_rings; i++) {
-		lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp));
-		to_slim += sizeof (struct lpfc_hgp);
+		lpfc_memcpy_to_slim(phba->host_gp + i, &hgp,
+				    sizeof(*phba->host_gp));
 	}
 
 	/* Setup Port Group ring pointer */
-	offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
-		 (uint8_t *)phba->slim2p;
-	pdma_addr = phba->slim2p_mapping + offset;
+	if (phba->sli_rev == 3)
+		pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s3_pgp.port -
+			(uint8_t *)phba->slim2p;
+	else
+		pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
+			(uint8_t *)phba->slim2p;
+
+	pdma_addr = phba->slim2p_mapping + pgp_offset;
 	phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
 	phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
+	phba->hbq_get = &phba->slim2p->mbx.us.s3_pgp.hbq_get[0];
 
 	/* Use callback routine to setp rings in the pcb */
 	lpfc_config_pcb_setup(phba);
@@ -606,11 +816,7 @@
 
 	/* Swap PCB if needed */
 	lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
-								sizeof (PCB_t));
-
-	lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-		        "%d:0405 Service Level Interface (SLI) 2 selected\n",
-		        phba->brd_no);
+			      sizeof(PCB_t));
 }
 
 void
@@ -644,15 +850,23 @@
 	LPFC_MBOXQ_t *mbq = NULL;
 	struct lpfc_sli *psli = &phba->sli;
 
-	list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t,
-			 list);
-	if (mbq) {
+	list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t, list);
+	if (mbq)
 		psli->mboxq_cnt--;
-	}
 
 	return mbq;
 }
 
+void
+lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
+{
+	/* This function expects to be called from interupt context */
+	spin_lock(&phba->hbalock);
+	list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl);
+	spin_unlock(&phba->hbalock);
+	return;
+}
+
 int
 lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
 {
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index ec3bbbd..3594c46 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -38,10 +38,13 @@
 #define LPFC_MBUF_POOL_SIZE     64      /* max elements in MBUF safety pool */
 #define LPFC_MEM_POOL_SIZE      64      /* max elem in non-DMA safety pool */
 
+
+
 int
 lpfc_mem_alloc(struct lpfc_hba * phba)
 {
 	struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
+	int longs;
 	int i;
 
 	phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool",
@@ -80,10 +83,27 @@
 	if (!phba->nlp_mem_pool)
 		goto fail_free_mbox_pool;
 
+	phba->lpfc_hbq_pool = pci_pool_create("lpfc_hbq_pool",phba->pcidev,
+					      LPFC_BPL_SIZE, 8, 0);
+	if (!phba->lpfc_hbq_pool)
+		goto fail_free_nlp_mem_pool;
+
+	/* vpi zero is reserved for the physical port so add 1 to max */
+	longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG;
+	phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL);
+	if (!phba->vpi_bmask)
+		goto fail_free_hbq_pool;
+
 	return 0;
 
+ fail_free_hbq_pool:
+	lpfc_sli_hbqbuf_free_all(phba);
+ fail_free_nlp_mem_pool:
+	mempool_destroy(phba->nlp_mem_pool);
+	phba->nlp_mem_pool = NULL;
  fail_free_mbox_pool:
 	mempool_destroy(phba->mbox_mem_pool);
+	phba->mbox_mem_pool = NULL;
  fail_free_mbuf_pool:
 	while (i--)
 		pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
@@ -91,8 +111,10 @@
 	kfree(pool->elements);
  fail_free_lpfc_mbuf_pool:
 	pci_pool_destroy(phba->lpfc_mbuf_pool);
+	phba->lpfc_mbuf_pool = NULL;
  fail_free_dma_buf_pool:
 	pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
+	phba->lpfc_scsi_dma_buf_pool = NULL;
  fail:
 	return -ENOMEM;
 }
@@ -106,6 +128,9 @@
 	struct lpfc_dmabuf   *mp;
 	int i;
 
+	kfree(phba->vpi_bmask);
+	lpfc_sli_hbqbuf_free_all(phba);
+
 	list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
 		mp = (struct lpfc_dmabuf *) (mbox->context1);
 		if (mp) {
@@ -115,6 +140,15 @@
 		list_del(&mbox->list);
 		mempool_free(mbox, phba->mbox_mem_pool);
 	}
+	list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
+		mp = (struct lpfc_dmabuf *) (mbox->context1);
+		if (mp) {
+			lpfc_mbuf_free(phba, mp->virt, mp->phys);
+			kfree(mp);
+		}
+		list_del(&mbox->list);
+		mempool_free(mbox, phba->mbox_mem_pool);
+	}
 
 	psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
 	if (psli->mbox_active) {
@@ -132,13 +166,21 @@
 		pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
 						 pool->elements[i].phys);
 	kfree(pool->elements);
+
+	pci_pool_destroy(phba->lpfc_hbq_pool);
 	mempool_destroy(phba->nlp_mem_pool);
 	mempool_destroy(phba->mbox_mem_pool);
 
 	pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
 	pci_pool_destroy(phba->lpfc_mbuf_pool);
 
-	/* Free the iocb lookup array */
+	phba->lpfc_hbq_pool = NULL;
+	phba->nlp_mem_pool = NULL;
+	phba->mbox_mem_pool = NULL;
+	phba->lpfc_scsi_dma_buf_pool = NULL;
+	phba->lpfc_mbuf_pool = NULL;
+
+				/* Free the iocb lookup array */
 	kfree(psli->iocbq_lookup);
 	psli->iocbq_lookup = NULL;
 
@@ -148,20 +190,23 @@
 lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
 {
 	struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
+	unsigned long iflags;
 	void *ret;
 
 	ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle);
 
-	if (!ret && ( mem_flags & MEM_PRI) && pool->current_count) {
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	if (!ret && (mem_flags & MEM_PRI) && pool->current_count) {
 		pool->current_count--;
 		ret = pool->elements[pool->current_count].virt;
 		*handle = pool->elements[pool->current_count].phys;
 	}
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
 	return ret;
 }
 
 void
-lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
+__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
 {
 	struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
 
@@ -174,3 +219,51 @@
 	}
 	return;
 }
+
+void
+lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
+{
+	unsigned long iflags;
+
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	__lpfc_mbuf_free(phba, virt, dma);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	return;
+}
+
+void *
+lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
+{
+	void *ret;
+	ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle);
+	return ret;
+}
+
+void
+lpfc_hbq_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma)
+{
+	pci_pool_free(phba->lpfc_hbq_pool, virt, dma);
+	return;
+}
+
+void
+lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
+{
+	struct hbq_dmabuf *hbq_entry;
+
+	if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+		hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf);
+		if (hbq_entry->tag == -1) {
+			lpfc_hbq_free(phba, hbq_entry->dbuf.virt,
+				      hbq_entry->dbuf.phys);
+			kfree(hbq_entry);
+		} else {
+			lpfc_sli_free_hbq(phba, hbq_entry);
+		}
+	} else {
+		lpfc_mbuf_free(phba, mp->virt, mp->phys);
+		kfree(mp);
+	}
+	return;
+}
+
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index b309841..bca2f5c 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1,4 +1,4 @@
-/*******************************************************************
+ /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
  * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
@@ -35,20 +35,22 @@
 #include "lpfc.h"
 #include "lpfc_logmsg.h"
 #include "lpfc_crtn.h"
+#include "lpfc_vport.h"
+#include "lpfc_debugfs.h"
 
 
 /* Called to verify a rcv'ed ADISC was intended for us. */
 static int
-lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-		 struct lpfc_name * nn, struct lpfc_name * pn)
+lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+		 struct lpfc_name *nn, struct lpfc_name *pn)
 {
 	/* Compare the ADISC rsp WWNN / WWPN matches our internal node
 	 * table entry for that node.
 	 */
-	if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)) != 0)
+	if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)))
 		return 0;
 
-	if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)) != 0)
+	if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)))
 		return 0;
 
 	/* we match, return success */
@@ -56,11 +58,10 @@
 }
 
 int
-lpfc_check_sparm(struct lpfc_hba * phba,
-		 struct lpfc_nodelist * ndlp, struct serv_parm * sp,
-		 uint32_t class)
+lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+		 struct serv_parm * sp, uint32_t class)
 {
-	volatile struct serv_parm *hsp = &phba->fc_sparam;
+	volatile struct serv_parm *hsp = &vport->fc_sparam;
 	uint16_t hsp_value, ssp_value = 0;
 
 	/*
@@ -75,12 +76,14 @@
 				hsp->cls1.rcvDataSizeLsb;
 		ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
 				sp->cls1.rcvDataSizeLsb;
+		if (!ssp_value)
+			goto bad_service_param;
 		if (ssp_value > hsp_value) {
 			sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
 			sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
 		}
 	} else if (class == CLASS1) {
-		return 0;
+		goto bad_service_param;
 	}
 
 	if (sp->cls2.classValid) {
@@ -88,12 +91,14 @@
 				hsp->cls2.rcvDataSizeLsb;
 		ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
 				sp->cls2.rcvDataSizeLsb;
+		if (!ssp_value)
+			goto bad_service_param;
 		if (ssp_value > hsp_value) {
 			sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
 			sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
 		}
 	} else if (class == CLASS2) {
-		return 0;
+		goto bad_service_param;
 	}
 
 	if (sp->cls3.classValid) {
@@ -101,12 +106,14 @@
 				hsp->cls3.rcvDataSizeLsb;
 		ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
 				sp->cls3.rcvDataSizeLsb;
+		if (!ssp_value)
+			goto bad_service_param;
 		if (ssp_value > hsp_value) {
 			sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
 			sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
 		}
 	} else if (class == CLASS3) {
-		return 0;
+		goto bad_service_param;
 	}
 
 	/*
@@ -125,12 +132,22 @@
 	memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
 	memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
 	return 1;
+bad_service_param:
+	lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY,
+			"%d (%d):0207 Device %x "
+			"(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent "
+			"invalid service parameters.  Ignoring device.\n",
+			vport->phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID,
+			sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1],
+			sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3],
+			sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5],
+			sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]);
+	return 0;
 }
 
 static void *
-lpfc_check_elscmpl_iocb(struct lpfc_hba * phba,
-		      struct lpfc_iocbq *cmdiocb,
-		      struct lpfc_iocbq *rspiocb)
+lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
 {
 	struct lpfc_dmabuf *pcmd, *prsp;
 	uint32_t *lp;
@@ -168,32 +185,29 @@
  * routine effectively results in a "software abort".
  */
 int
-lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
 	LIST_HEAD(completions);
-	struct lpfc_sli *psli;
-	struct lpfc_sli_ring *pring;
+	struct lpfc_sli  *psli = &phba->sli;
+	struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
 	struct lpfc_iocbq *iocb, *next_iocb;
 	IOCB_t *cmd;
 
 	/* Abort outstanding I/O on NPort <nlp_DID> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d:0205 Abort outstanding I/O on NPort x%x "
+			"%d (%d):0205 Abort outstanding I/O on NPort x%x "
 			"Data: x%x x%x x%x\n",
-			phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
-			ndlp->nlp_state, ndlp->nlp_rpi);
+			phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID,
+			ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
 
-	psli = &phba->sli;
-	pring = &psli->ring[LPFC_ELS_RING];
+	lpfc_fabric_abort_nport(ndlp);
 
 	/* First check the txq */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
-		/* Check to see if iocb matches the nport we are looking
-		   for */
+		/* Check to see if iocb matches the nport we are looking for */
 		if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
-			/* It matches, so deque and call compl with an
-			   error */
+			/* It matches, so deque and call compl with anp error */
 			list_move_tail(&iocb->list, &completions);
 			pring->txq_cnt--;
 		}
@@ -201,37 +215,39 @@
 
 	/* Next check the txcmplq */
 	list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
-		/* Check to see if iocb matches the nport we are looking
-		   for */
-		if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
+		/* Check to see if iocb matches the nport we are looking for */
+		if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
 			lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+		}
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	while (!list_empty(&completions)) {
 		iocb = list_get_first(&completions, struct lpfc_iocbq, list);
 		cmd = &iocb->iocb;
-		list_del(&iocb->list);
+		list_del_init(&iocb->list);
 
-		if (iocb->iocb_cmpl) {
+		if (!iocb->iocb_cmpl)
+			lpfc_sli_release_iocbq(phba, iocb);
+		else {
 			cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
 			cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
 			(iocb->iocb_cmpl) (phba, iocb, iocb);
-		} else
-			lpfc_sli_release_iocbq(phba, iocb);
+		}
 	}
 
 	/* If we are delaying issuing an ELS command, cancel it */
 	if (ndlp->nlp_flag & NLP_DELAY_TMO)
-		lpfc_cancel_retry_delay_tmo(phba, ndlp);
+		lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
 	return 0;
 }
 
 static int
-lpfc_rcv_plogi(struct lpfc_hba * phba,
-		      struct lpfc_nodelist * ndlp,
-		      struct lpfc_iocbq *cmdiocb)
+lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+	       struct lpfc_iocbq *cmdiocb)
 {
+	struct Scsi_Host   *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba    *phba = vport->phba;
 	struct lpfc_dmabuf *pcmd;
 	uint32_t *lp;
 	IOCB_t *icmd;
@@ -241,14 +257,14 @@
 	int rc;
 
 	memset(&stat, 0, sizeof (struct ls_rjt));
-	if (phba->hba_state <= LPFC_FLOGI) {
+	if (vport->port_state <= LPFC_FLOGI) {
 		/* Before responding to PLOGI, check for pt2pt mode.
 		 * If we are pt2pt, with an outstanding FLOGI, abort
 		 * the FLOGI and resend it first.
 		 */
-		if (phba->fc_flag & FC_PT2PT) {
-			lpfc_els_abort_flogi(phba);
-		        if (!(phba->fc_flag & FC_PT2PT_PLOGI)) {
+		if (vport->fc_flag & FC_PT2PT) {
+			 lpfc_els_abort_flogi(phba);
+		        if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
 				/* If the other side is supposed to initiate
 				 * the PLOGI anyway, just ACC it now and
 				 * move on with discovery.
@@ -257,45 +273,42 @@
 				phba->fc_ratov = FF_DEF_RATOV;
 				/* Start discovery - this should just do
 				   CLEAR_LA */
-				lpfc_disc_start(phba);
-			} else {
-				lpfc_initial_flogi(phba);
-			}
+				lpfc_disc_start(vport);
+			} else
+				lpfc_initial_flogi(vport);
 		} else {
 			stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
 			stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
-			lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb,
-					    ndlp);
+			lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
+					    ndlp, NULL);
 			return 0;
 		}
 	}
 	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
 	lp = (uint32_t *) pcmd->virt;
 	sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
-	if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3) == 0)) {
+	if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) {
 		/* Reject this request because invalid parameters */
 		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 		stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
-		lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+			NULL);
 		return 0;
 	}
 	icmd = &cmdiocb->iocb;
 
 	/* PLOGI chkparm OK */
-	lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_ELS,
-			"%d:0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
-			phba->brd_no,
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+			"%d (%d):0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
+			phba->brd_no, vport->vpi,
 			ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
 			ndlp->nlp_rpi);
 
-	if ((phba->cfg_fcp_class == 2) &&
-	    (sp->cls2.classValid)) {
+	if (phba->cfg_fcp_class == 2 && sp->cls2.classValid)
 		ndlp->nlp_fcp_info |= CLASS2;
-	} else {
+	else
 		ndlp->nlp_fcp_info |= CLASS3;
-	}
+
 	ndlp->nlp_class_sup = 0;
 	if (sp->cls1.classValid)
 		ndlp->nlp_class_sup |= FC_COS_CLASS1;
@@ -317,35 +330,37 @@
 	case  NLP_STE_PRLI_ISSUE:
 	case  NLP_STE_UNMAPPED_NODE:
 	case  NLP_STE_MAPPED_NODE:
-		lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0);
+		lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0);
 		return 1;
 	}
 
-	if ((phba->fc_flag & FC_PT2PT)
-	    && !(phba->fc_flag & FC_PT2PT_PLOGI)) {
+	if ((vport->fc_flag & FC_PT2PT) &&
+	    !(vport->fc_flag & FC_PT2PT_PLOGI)) {
 		/* rcv'ed PLOGI decides what our NPortId will be */
-		phba->fc_myDID = icmd->un.rcvels.parmRo;
+		vport->fc_myDID = icmd->un.rcvels.parmRo;
 		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 		if (mbox == NULL)
 			goto out;
 		lpfc_config_link(phba, mbox);
 		mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		mbox->vport = vport;
 		rc = lpfc_sli_issue_mbox
 			(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
 		if (rc == MBX_NOT_FINISHED) {
-			mempool_free( mbox, phba->mbox_mem_pool);
+			mempool_free(mbox, phba->mbox_mem_pool);
 			goto out;
 		}
 
-		lpfc_can_disctmo(phba);
+		lpfc_can_disctmo(vport);
 	}
 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (mbox == NULL)
+	if (!mbox)
 		goto out;
 
-	if (lpfc_reg_login(phba, icmd->un.rcvels.remoteID,
-			   (uint8_t *) sp, mbox, 0)) {
-		mempool_free( mbox, phba->mbox_mem_pool);
+	rc = lpfc_reg_login(phba, vport->vpi, icmd->un.rcvels.remoteID,
+			    (uint8_t *) sp, mbox, 0);
+	if (rc) {
+		mempool_free(mbox, phba->mbox_mem_pool);
 		goto out;
 	}
 
@@ -357,7 +372,10 @@
 	 * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox
 	 * command issued in lpfc_cmpl_els_acc().
 	 */
+	mbox->vport = vport;
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
+	spin_unlock_irq(shost->host_lock);
 
 	/*
 	 * If there is an outstanding PLOGI issued, abort it before
@@ -373,24 +391,41 @@
 		lpfc_els_abort(phba, ndlp);
 	}
 
-	lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
+	if ((vport->port_type == LPFC_NPIV_PORT &&
+	      phba->cfg_vport_restrict_login)) {
+
+		/* In order to preserve RPIs, we want to cleanup
+		 * the default RPI the firmware created to rcv
+		 * this ELS request. The only way to do this is
+		 * to register, then unregister the RPI.
+		 */
+		spin_lock_irq(shost->host_lock);
+		ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
+		spin_unlock_irq(shost->host_lock);
+		stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
+		stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
+		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
+			ndlp, mbox);
+		return 1;
+	}
+	lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
 	return 1;
 
 out:
 	stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 	stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
-	lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+	lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
 	return 0;
 }
 
 static int
-lpfc_rcv_padisc(struct lpfc_hba * phba,
-		struct lpfc_nodelist * ndlp,
+lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		struct lpfc_iocbq *cmdiocb)
 {
+	struct Scsi_Host   *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_dmabuf *pcmd;
-	struct serv_parm *sp;
-	struct lpfc_name *pnn, *ppn;
+	struct serv_parm   *sp;
+	struct lpfc_name   *pnn, *ppn;
 	struct ls_rjt stat;
 	ADISC *ap;
 	IOCB_t *icmd;
@@ -412,13 +447,12 @@
 	}
 
 	icmd = &cmdiocb->iocb;
-	if ((icmd->ulpStatus == 0) &&
-	    (lpfc_check_adisc(phba, ndlp, pnn, ppn))) {
+	if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
 		if (cmd == ELS_CMD_ADISC) {
-			lpfc_els_rsp_adisc_acc(phba, cmdiocb, ndlp);
+			lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
 		} else {
-			lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp,
-				NULL, 0);
+			lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp,
+					 NULL, 0);
 		}
 		return 1;
 	}
@@ -427,55 +461,57 @@
 	stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 	stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
 	stat.un.b.vendorUnique = 0;
-	lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+	lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
 
 	/* 1 sec timeout */
 	mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= NLP_DELAY_TMO;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 	ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
 	ndlp->nlp_prev_state = ndlp->nlp_state;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 	return 0;
 }
 
 static int
-lpfc_rcv_logo(struct lpfc_hba * phba,
-		      struct lpfc_nodelist * ndlp,
-		      struct lpfc_iocbq *cmdiocb,
-		      uint32_t els_cmd)
+lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+	      struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
 {
-	/* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	/* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */
 	/* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
 	 * PLOGIs during LOGO storms from a device.
 	 */
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= NLP_LOGO_ACC;
+	spin_unlock_irq(shost->host_lock);
 	if (els_cmd == ELS_CMD_PRLO)
-		lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+		lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
 	else
-		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+		lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
 
 	if (!(ndlp->nlp_type & NLP_FABRIC) ||
-		(ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
+	    (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
 		/* Only try to re-login if this is NOT a Fabric Node */
 		mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_DELAY_TMO;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 
 		ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
 		ndlp->nlp_prev_state = ndlp->nlp_state;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 	} else {
 		ndlp->nlp_prev_state = ndlp->nlp_state;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
 	}
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 	/* The driver has to wait until the ACC completes before it continues
 	 * processing the LOGO.  The action will resume in
 	 * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an
@@ -485,9 +521,8 @@
 }
 
 static void
-lpfc_rcv_prli(struct lpfc_hba * phba,
-		      struct lpfc_nodelist * ndlp,
-		      struct lpfc_iocbq *cmdiocb)
+lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+	      struct lpfc_iocbq *cmdiocb)
 {
 	struct lpfc_dmabuf *pcmd;
 	uint32_t *lp;
@@ -501,8 +536,7 @@
 
 	ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
 	ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
-	if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
-	    (npr->prliType == PRLI_FCP_TYPE)) {
+	if (npr->prliType == PRLI_FCP_TYPE) {
 		if (npr->initiatorFunc)
 			ndlp->nlp_type |= NLP_FCP_INITIATOR;
 		if (npr->targetFunc)
@@ -517,36 +551,42 @@
 			roles |= FC_RPORT_ROLE_FCP_INITIATOR;
 		if (ndlp->nlp_type & NLP_FCP_TARGET)
 			roles |= FC_RPORT_ROLE_FCP_TARGET;
+
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+			"rport rolechg:   role:x%x did:x%x flg:x%x",
+			roles, ndlp->nlp_DID, ndlp->nlp_flag);
+
 		fc_remote_port_rolechg(rport, roles);
 	}
 }
 
 static uint32_t
-lpfc_disc_set_adisc(struct lpfc_hba * phba,
-		      struct lpfc_nodelist * ndlp)
+lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+
 	/* Check config parameter use-adisc or FCP-2 */
-	if ((phba->cfg_use_adisc == 0) &&
-		!(phba->fc_flag & FC_RSCN_MODE)) {
-		if (!(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE))
-			return 0;
+	if ((phba->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
+	    ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
+		spin_lock_irq(shost->host_lock);
+		ndlp->nlp_flag |= NLP_NPR_ADISC;
+		spin_unlock_irq(shost->host_lock);
+		return 1;
 	}
-	spin_lock_irq(phba->host->host_lock);
-	ndlp->nlp_flag |= NLP_NPR_ADISC;
-	spin_unlock_irq(phba->host->host_lock);
-	return 1;
+	ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+	lpfc_unreg_rpi(vport, ndlp);
+	return 0;
 }
 
 static uint32_t
-lpfc_disc_illegal(struct lpfc_hba * phba,
-		   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+		  void *arg, uint32_t evt)
 {
-	lpfc_printf_log(phba,
-			KERN_ERR,
-			LOG_DISCOVERY,
-			"%d:0253 Illegal State Transition: node x%x event x%x, "
-			"state x%x Data: x%x x%x\n",
-			phba->brd_no,
+	lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY,
+			"%d (%d):0253 Illegal State Transition: node x%x "
+			"event x%x, state x%x Data: x%x x%x\n",
+			vport->phba->brd_no, vport->vpi,
 			ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
 			ndlp->nlp_flag);
 	return ndlp->nlp_state;
@@ -555,151 +595,162 @@
 /* Start of Discovery State Machine routines */
 
 static uint32_t
-lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba,
-			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
+	if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
 		ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
 		return ndlp->nlp_state;
 	}
-	lpfc_drop_node(phba, ndlp);
+	lpfc_drop_node(vport, ndlp);
 	return NLP_STE_FREED_NODE;
 }
 
 static uint32_t
-lpfc_rcv_els_unused_node(struct lpfc_hba * phba,
-			 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
-	lpfc_issue_els_logo(phba, ndlp, 0);
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+	lpfc_issue_els_logo(vport, ndlp, 0);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_logo_unused_node(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq     *cmdiocb;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= NLP_LOGO_ACC;
-	spin_unlock_irq(phba->host->host_lock);
-	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+	spin_unlock_irq(shost->host_lock);
+	lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
 
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-{
-	lpfc_drop_node(phba, ndlp);
-	return NLP_STE_FREED_NODE;
-}
-
-static uint32_t
-lpfc_device_rm_unused_node(struct lpfc_hba * phba,
-			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-{
-	lpfc_drop_node(phba, ndlp);
-	return NLP_STE_FREED_NODE;
-}
-
-static uint32_t
-lpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 			   void *arg, uint32_t evt)
 {
+	lpfc_drop_node(vport, ndlp);
+	return NLP_STE_FREED_NODE;
+}
+
+static uint32_t
+lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
+{
+	lpfc_drop_node(vport, ndlp);
+	return NLP_STE_FREED_NODE;
+}
+
+static uint32_t
+lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
+{
+	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_iocbq *cmdiocb = arg;
-	struct lpfc_dmabuf *pcmd;
-	struct serv_parm *sp;
-	uint32_t *lp;
+	struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+	uint32_t *lp = (uint32_t *) pcmd->virt;
+	struct serv_parm *sp = (struct serv_parm *) (lp + 1);
 	struct ls_rjt stat;
 	int port_cmp;
 
-	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-	lp = (uint32_t *) pcmd->virt;
-	sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
-
 	memset(&stat, 0, sizeof (struct ls_rjt));
 
 	/* For a PLOGI, we only accept if our portname is less
 	 * than the remote portname.
 	 */
 	phba->fc_stat.elsLogiCol++;
-	port_cmp = memcmp(&phba->fc_portname, &sp->portName,
-			  sizeof (struct lpfc_name));
+	port_cmp = memcmp(&vport->fc_portname, &sp->portName,
+			  sizeof(struct lpfc_name));
 
 	if (port_cmp >= 0) {
 		/* Reject this request because the remote node will accept
 		   ours */
 		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 		stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
-		lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+			NULL);
 	} else {
-		lpfc_rcv_plogi(phba, ndlp, cmdiocb);
-	} /* if our portname was less */
+		lpfc_rcv_plogi(vport, ndlp, cmdiocb);
+	} /* If our portname was less */
 
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq     *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
+	struct ls_rjt     stat;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	/* software abort outstanding PLOGI */
-	lpfc_els_abort(phba, ndlp);
-
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+	memset(&stat, 0, sizeof (struct ls_rjt));
+	stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
+	stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
+	lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq     *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
+				/* software abort outstanding PLOGI */
+	lpfc_els_abort(vport->phba, ndlp);
+
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
+	return ndlp->nlp_state;
+}
+
+static uint32_t
+lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
+{
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* software abort outstanding PLOGI */
 	lpfc_els_abort(phba, ndlp);
 
 	if (evt == NLP_EVT_RCV_LOGO) {
-		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+		lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
 	} else {
-		lpfc_issue_els_logo(phba, ndlp, 0);
+		lpfc_issue_els_logo(vport, ndlp, 0);
 	}
 
-	/* Put ndlp in npr list set plogi timer for 1 sec */
+	/* Put ndlp in npr state set plogi timer for 1 sec */
 	mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= NLP_DELAY_TMO;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 	ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
 	ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
+lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
+			    struct lpfc_nodelist *ndlp,
+			    void *arg,
 			    uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb, *rspiocb;
+	struct lpfc_hba    *phba = vport->phba;
+	struct lpfc_iocbq  *cmdiocb, *rspiocb;
 	struct lpfc_dmabuf *pcmd, *prsp, *mp;
 	uint32_t *lp;
 	IOCB_t *irsp;
@@ -721,31 +772,26 @@
 
 	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
 
-	prsp = list_get_first(&pcmd->list,
-			      struct lpfc_dmabuf,
-			      list);
-	lp = (uint32_t *) prsp->virt;
+	prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
 
+	lp = (uint32_t *) prsp->virt;
 	sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
-	if (!lpfc_check_sparm(phba, ndlp, sp, CLASS3))
+	if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3))
 		goto out;
 
 	/* PLOGI chkparm OK */
-	lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_ELS,
-			"%d:0121 PLOGI chkparm OK "
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+			"%d (%d):0121 PLOGI chkparm OK "
 			"Data: x%x x%x x%x x%x\n",
-			phba->brd_no,
+			phba->brd_no, vport->vpi,
 			ndlp->nlp_DID, ndlp->nlp_state,
 			ndlp->nlp_flag, ndlp->nlp_rpi);
 
-	if ((phba->cfg_fcp_class == 2) &&
-	    (sp->cls2.classValid)) {
+	if (phba->cfg_fcp_class == 2 && (sp->cls2.classValid))
 		ndlp->nlp_fcp_info |= CLASS2;
-	} else {
+	else
 		ndlp->nlp_fcp_info |= CLASS3;
-	}
+
 	ndlp->nlp_class_sup = 0;
 	if (sp->cls1.classValid)
 		ndlp->nlp_class_sup |= FC_COS_CLASS1;
@@ -756,16 +802,23 @@
 	if (sp->cls4.classValid)
 		ndlp->nlp_class_sup |= FC_COS_CLASS4;
 	ndlp->nlp_maxframe =
-		((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
-		sp->cmn.bbRcvSizeLsb;
+		((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
 
-	if (!(mbox = mempool_alloc(phba->mbox_mem_pool,
-				   GFP_KERNEL)))
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!mbox) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0133 PLOGI: no memory for reg_login "
+			"Data: x%x x%x x%x x%x\n",
+			phba->brd_no, vport->vpi,
+			ndlp->nlp_DID, ndlp->nlp_state,
+			ndlp->nlp_flag, ndlp->nlp_rpi);
 		goto out;
+	}
 
-	lpfc_unreg_rpi(phba, ndlp);
-	if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp,
-			   mbox, 0) == 0) {
+	lpfc_unreg_rpi(vport, ndlp);
+
+	if (lpfc_reg_login(phba, vport->vpi, irsp->un.elsreq64.remoteID,
+			   (uint8_t *) sp, mbox, 0) == 0) {
 		switch (ndlp->nlp_DID) {
 		case NameServer_DID:
 			mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
@@ -777,68 +830,104 @@
 			mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
 		}
 		mbox->context2 = lpfc_nlp_get(ndlp);
+		mbox->vport = vport;
 		if (lpfc_sli_issue_mbox(phba, mbox,
 					(MBX_NOWAIT | MBX_STOP_IOCB))
 		    != MBX_NOT_FINISHED) {
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
+			lpfc_nlp_set_state(vport, ndlp,
+					   NLP_STE_REG_LOGIN_ISSUE);
 			return ndlp->nlp_state;
 		}
 		lpfc_nlp_put(ndlp);
-		mp = (struct lpfc_dmabuf *)mbox->context1;
+		mp = (struct lpfc_dmabuf *) mbox->context1;
 		lpfc_mbuf_free(phba, mp->virt, mp->phys);
 		kfree(mp);
 		mempool_free(mbox, phba->mbox_mem_pool);
+
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0134 PLOGI: cannot issue reg_login "
+			"Data: x%x x%x x%x x%x\n",
+			phba->brd_no, vport->vpi,
+			ndlp->nlp_DID, ndlp->nlp_state,
+			ndlp->nlp_flag, ndlp->nlp_rpi);
 	} else {
 		mempool_free(mbox, phba->mbox_mem_pool);
+
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0135 PLOGI: cannot format reg_login "
+			"Data: x%x x%x x%x x%x\n",
+			phba->brd_no, vport->vpi,
+			ndlp->nlp_DID, ndlp->nlp_state,
+			ndlp->nlp_flag, ndlp->nlp_rpi);
 	}
 
 
- out:
+out:
+	if (ndlp->nlp_DID == NameServer_DID) {
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+			"%d (%d):0261 Cannot Register NameServer login\n",
+			phba->brd_no, vport->vpi);
+	}
+
 	/* Free this node since the driver cannot login or has the wrong
 	   sparm */
-	lpfc_drop_node(phba, ndlp);
+	lpfc_drop_node(vport, ndlp);
 	return NLP_STE_FREED_NODE;
 }
 
 static uint32_t
-lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
-			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
 {
-	if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
-		return ndlp->nlp_state;
-	}
-	else {
-		/* software abort outstanding PLOGI */
-		lpfc_els_abort(phba, ndlp);
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
-		lpfc_drop_node(phba, ndlp);
+	if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		spin_lock_irq(shost->host_lock);
+		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		spin_unlock_irq(shost->host_lock);
+		return ndlp->nlp_state;
+	} else {
+		/* software abort outstanding PLOGI */
+		lpfc_els_abort(vport->phba, ndlp);
+
+		lpfc_drop_node(vport, ndlp);
 		return NLP_STE_FREED_NODE;
 	}
 }
 
 static uint32_t
-lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,
+			      struct lpfc_nodelist *ndlp,
+			      void *arg,
+			      uint32_t evt)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+
+	/* Don't do anything that will mess up processing of the
+	 * previous RSCN.
+	 */
+	if (vport->fc_flag & FC_RSCN_DEFERRED)
+		return ndlp->nlp_state;
+
 	/* software abort outstanding PLOGI */
 	lpfc_els_abort(phba, ndlp);
 
 	ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-	spin_lock_irq(phba->host->host_lock);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
 {
+	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_iocbq *cmdiocb;
 
 	/* software abort outstanding ADISC */
@@ -846,34 +935,31 @@
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
+	if (lpfc_rcv_plogi(vport, ndlp, cmdiocb))
 		return ndlp->nlp_state;
-	}
+
 	ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
-	lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+	lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
 
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prli_adisc_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+	lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
+	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_iocbq *cmdiocb;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
@@ -881,42 +967,43 @@
 	/* software abort outstanding ADISC */
 	lpfc_els_abort(phba, ndlp);
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_padisc_adisc_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport,
+			    struct lpfc_nodelist *ndlp,
+			    void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+	lpfc_rcv_padisc(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* Treat like rcv logo */
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
+			    struct lpfc_nodelist *ndlp,
+			    void *arg, uint32_t evt)
 {
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_iocbq *cmdiocb, *rspiocb;
 	IOCB_t *irsp;
 	ADISC *ap;
@@ -928,101 +1015,112 @@
 	irsp = &rspiocb->iocb;
 
 	if ((irsp->ulpStatus) ||
-		(!lpfc_check_adisc(phba, ndlp, &ap->nodeName, &ap->portName))) {
+	    (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
 		/* 1 sec timeout */
 		mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_DELAY_TMO;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
 
-		memset(&ndlp->nlp_nodename, 0, sizeof (struct lpfc_name));
-		memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name));
+		memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name));
+		memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name));
 
 		ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-		lpfc_unreg_rpi(phba, ndlp);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+		lpfc_unreg_rpi(vport, ndlp);
 		return ndlp->nlp_state;
 	}
 
 	if (ndlp->nlp_type & NLP_FCP_TARGET) {
 		ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
 	} else {
 		ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 	}
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
 {
-	if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
-		return ndlp->nlp_state;
-	}
-	else {
-		/* software abort outstanding ADISC */
-		lpfc_els_abort(phba, ndlp);
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
-		lpfc_drop_node(phba, ndlp);
+	if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		spin_lock_irq(shost->host_lock);
+		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		spin_unlock_irq(shost->host_lock);
+		return ndlp->nlp_state;
+	} else {
+		/* software abort outstanding ADISC */
+		lpfc_els_abort(vport->phba, ndlp);
+
+		lpfc_drop_node(vport, ndlp);
 		return NLP_STE_FREED_NODE;
 	}
 }
 
 static uint32_t
-lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,
+			      struct lpfc_nodelist *ndlp,
+			      void *arg,
+			      uint32_t evt)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+
+	/* Don't do anything that will mess up processing of the
+	 * previous RSCN.
+	 */
+	if (vport->fc_flag & FC_RSCN_DEFERRED)
+		return ndlp->nlp_state;
+
 	/* software abort outstanding ADISC */
 	lpfc_els_abort(phba, ndlp);
 
 	ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-	spin_lock_irq(phba->host->host_lock);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
-	ndlp->nlp_flag |= NLP_NPR_ADISC;
-	spin_unlock_irq(phba->host->host_lock);
-
+	spin_unlock_irq(shost->host_lock);
+	lpfc_disc_set_adisc(vport, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_plogi_reglogin_issue(struct lpfc_hba * phba,
-			      struct lpfc_nodelist * ndlp, void *arg,
+lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport,
+			      struct lpfc_nodelist *ndlp,
+			      void *arg,
 			      uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_plogi(phba, ndlp, cmdiocb);
+	lpfc_rcv_plogi(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prli_reglogin_issue(struct lpfc_hba * phba,
-			     struct lpfc_nodelist * ndlp, void *arg,
+lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport,
+			     struct lpfc_nodelist *ndlp,
+			     void *arg,
 			     uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+	lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
-			     struct lpfc_nodelist * ndlp, void *arg,
+lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
+			     struct lpfc_nodelist *ndlp,
+			     void *arg,
 			     uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 	LPFC_MBOXQ_t	  *mb;
 	LPFC_MBOXQ_t	  *nextmb;
 	struct lpfc_dmabuf *mp;
@@ -1033,12 +1131,13 @@
 	if ((mb = phba->sli.mbox_active)) {
 		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
 		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+			lpfc_nlp_put(ndlp);
 			mb->context2 = NULL;
 			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 		}
 	}
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
 		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
 		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {
@@ -1047,61 +1146,61 @@
 				lpfc_mbuf_free(phba, mp->virt, mp->phys);
 				kfree(mp);
 			}
+			lpfc_nlp_put(ndlp);
 			list_del(&mb->list);
 			mempool_free(mb, phba->mbox_mem_pool);
 		}
 	}
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_padisc_reglogin_issue(struct lpfc_hba * phba,
-			       struct lpfc_nodelist * ndlp, void *arg,
+lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport,
+			       struct lpfc_nodelist *ndlp,
+			       void *arg,
 			       uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+	lpfc_rcv_padisc(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
-			     struct lpfc_nodelist * ndlp, void *arg,
+lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,
+			     struct lpfc_nodelist *ndlp,
+			     void *arg,
 			     uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
-	lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+	lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
-				  struct lpfc_nodelist * ndlp,
-				  void *arg, uint32_t evt)
+lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
+				  struct lpfc_nodelist *ndlp,
+				  void *arg,
+				  uint32_t evt)
 {
-	LPFC_MBOXQ_t *pmb;
-	MAILBOX_t *mb;
-	uint32_t did;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+	LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
+	MAILBOX_t *mb = &pmb->mb;
+	uint32_t did  = mb->un.varWords[1];
 
-	pmb = (LPFC_MBOXQ_t *) arg;
-	mb = &pmb->mb;
-	did = mb->un.varWords[1];
 	if (mb->mbxStatus) {
 		/* RegLogin failed */
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_DISCOVERY,
-				"%d:0246 RegLogin failed Data: x%x x%x x%x\n",
-				phba->brd_no,
-				did, mb->mbxStatus, phba->hba_state);
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+				"%d (%d):0246 RegLogin failed Data: x%x x%x "
+				"x%x\n",
+				phba->brd_no, vport->vpi,
+				did, mb->mbxStatus, vport->port_state);
 
 		/*
 		 * If RegLogin failed due to lack of HBA resources do not
@@ -1109,20 +1208,20 @@
 		 */
 		if (mb->mbxStatus == MBXERR_RPI_FULL) {
 			ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
 			return ndlp->nlp_state;
 		}
 
-		/* Put ndlp in npr list set plogi timer for 1 sec */
+		/* Put ndlp in npr state set plogi timer for 1 sec */
 		mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_DELAY_TMO;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
 
-		lpfc_issue_els_logo(phba, ndlp, 0);
+		lpfc_issue_els_logo(vport, ndlp, 0);
 		ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 		return ndlp->nlp_state;
 	}
 
@@ -1131,91 +1230,99 @@
 	/* Only if we are not a fabric nport do we issue PRLI */
 	if (!(ndlp->nlp_type & NLP_FABRIC)) {
 		ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
-		lpfc_issue_els_prli(phba, ndlp, 0);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
+		lpfc_issue_els_prli(vport, ndlp, 0);
 	} else {
 		ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 	}
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
-			      struct lpfc_nodelist * ndlp, void *arg,
+lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport,
+			      struct lpfc_nodelist *ndlp,
+			      void *arg,
 			      uint32_t evt)
 {
-	if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		spin_unlock_irq(shost->host_lock);
 		return ndlp->nlp_state;
-	}
-	else {
-		lpfc_drop_node(phba, ndlp);
+	} else {
+		lpfc_drop_node(vport, ndlp);
 		return NLP_STE_FREED_NODE;
 	}
 }
 
 static uint32_t
-lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
-			       struct lpfc_nodelist * ndlp, void *arg,
-			       uint32_t evt)
+lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
+				 struct lpfc_nodelist *ndlp,
+				 void *arg,
+				 uint32_t evt)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	/* Don't do anything that will mess up processing of the
+	 * previous RSCN.
+	 */
+	if (vport->fc_flag & FC_RSCN_DEFERRED)
+		return ndlp->nlp_state;
+
 	ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-	spin_lock_irq(phba->host->host_lock);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
+	lpfc_disc_set_adisc(vport, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_plogi_prli_issue(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	lpfc_rcv_plogi(phba, ndlp, cmdiocb);
+	lpfc_rcv_plogi(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prli_prli_issue(struct lpfc_hba * phba,
-			 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+	lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
-			 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
-
-	cmdiocb = (struct lpfc_iocbq *) arg;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* Software abort outstanding PRLI before sending acc */
-	lpfc_els_abort(phba, ndlp);
+	lpfc_els_abort(vport->phba, ndlp);
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_padisc_prli_issue(struct lpfc_hba * phba,
-			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+	lpfc_rcv_padisc(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
@@ -1225,21 +1332,22 @@
  * NEXT STATE = PRLI_ISSUE
  */
 static uint32_t
-lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
-			 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-	lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+	lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_iocbq *cmdiocb, *rspiocb;
+	struct lpfc_hba   *phba = vport->phba;
 	IOCB_t *irsp;
 	PRLI *npr;
 
@@ -1249,8 +1357,12 @@
 
 	irsp = &rspiocb->iocb;
 	if (irsp->ulpStatus) {
+		if ((vport->port_type == LPFC_NPIV_PORT) &&
+			phba->cfg_vport_restrict_login) {
+			goto out;
+		}
 		ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 		return ndlp->nlp_state;
 	}
 
@@ -1266,319 +1378,329 @@
 		if (npr->Retry)
 			ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
 	}
+	if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
+	    (vport->port_type == LPFC_NPIV_PORT) &&
+	     phba->cfg_vport_restrict_login) {
+out:
+		spin_lock_irq(shost->host_lock);
+		ndlp->nlp_flag |= NLP_TARGET_REMOVE;
+		spin_unlock_irq(shost->host_lock);
+		lpfc_issue_els_logo(vport, ndlp, 0);
+
+		ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
+		return ndlp->nlp_state;
+	}
 
 	ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
+	if (ndlp->nlp_type & NLP_FCP_TARGET)
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
+	else
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 	return ndlp->nlp_state;
 }
 
 /*! lpfc_device_rm_prli_issue
-  *
-  * \pre
-  * \post
-  * \param   phba
-  * \param   ndlp
-  * \param   arg
-  * \param   evt
-  * \return  uint32_t
-  *
-  * \b Description:
-  *    This routine is envoked when we a request to remove a nport we are in the
-  *    process of PRLIing. We should software abort outstanding prli, unreg
-  *    login, send a logout. We will change node state to UNUSED_NODE, put it
-  *    on plogi list so it can be freed when LOGO completes.
-  *
-  */
-static uint32_t
-lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-{
-	if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
-		return ndlp->nlp_state;
-	}
-	else {
-		/* software abort outstanding PLOGI */
-		lpfc_els_abort(phba, ndlp);
+ *
+ * \pre
+ * \post
+ * \param   phba
+ * \param   ndlp
+ * \param   arg
+ * \param   evt
+ * \return  uint32_t
+ *
+ * \b Description:
+ *    This routine is envoked when we a request to remove a nport we are in the
+ *    process of PRLIing. We should software abort outstanding prli, unreg
+ *    login, send a logout. We will change node state to UNUSED_NODE, put it
+ *    on plogi list so it can be freed when LOGO completes.
+ *
+ */
 
-		lpfc_drop_node(phba, ndlp);
+static uint32_t
+lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		spin_lock_irq(shost->host_lock);
+		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		spin_unlock_irq(shost->host_lock);
+		return ndlp->nlp_state;
+	} else {
+		/* software abort outstanding PLOGI */
+		lpfc_els_abort(vport->phba, ndlp);
+
+		lpfc_drop_node(vport, ndlp);
 		return NLP_STE_FREED_NODE;
 	}
 }
 
 
 /*! lpfc_device_recov_prli_issue
-  *
-  * \pre
-  * \post
-  * \param   phba
-  * \param   ndlp
-  * \param   arg
-  * \param   evt
-  * \return  uint32_t
-  *
-  * \b Description:
-  *    The routine is envoked when the state of a device is unknown, like
-  *    during a link down. We should remove the nodelist entry from the
-  *    unmapped list, issue a UNREG_LOGIN, do a software abort of the
-  *    outstanding PRLI command, then free the node entry.
-  */
+ *
+ * \pre
+ * \post
+ * \param   phba
+ * \param   ndlp
+ * \param   arg
+ * \param   evt
+ * \return  uint32_t
+ *
+ * \b Description:
+ *    The routine is envoked when the state of a device is unknown, like
+ *    during a link down. We should remove the nodelist entry from the
+ *    unmapped list, issue a UNREG_LOGIN, do a software abort of the
+ *    outstanding PRLI command, then free the node entry.
+ */
 static uint32_t
-lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
-			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_device_recov_prli_issue(struct lpfc_vport *vport,
+			     struct lpfc_nodelist *ndlp,
+			     void *arg,
+			     uint32_t evt)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_hba  *phba = vport->phba;
+
+	/* Don't do anything that will mess up processing of the
+	 * previous RSCN.
+	 */
+	if (vport->fc_flag & FC_RSCN_DEFERRED)
+		return ndlp->nlp_state;
+
 	/* software abort outstanding PRLI */
 	lpfc_els_abort(phba, ndlp);
 
 	ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-	spin_lock_irq(phba->host->host_lock);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
+	lpfc_disc_set_adisc(vport, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_plogi_unmap_node(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_plogi(phba, ndlp, cmdiocb);
+	lpfc_rcv_plogi(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prli_unmap_node(struct lpfc_hba * phba,
-			 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_prli(phba, ndlp, cmdiocb);
-	lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+	lpfc_rcv_prli(vport, ndlp, cmdiocb);
+	lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
-			 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_padisc_unmap_node(struct lpfc_hba * phba,
-			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+	lpfc_rcv_padisc(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
-			 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+	lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
-			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
+			     struct lpfc_nodelist *ndlp,
+			     void *arg,
+			     uint32_t evt)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
 	ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
-	lpfc_disc_set_adisc(phba, ndlp);
+	spin_unlock_irq(shost->host_lock);
+	lpfc_disc_set_adisc(vport, ndlp);
 
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_plogi_mapped_node(struct lpfc_hba * phba,
-			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_plogi(phba, ndlp, cmdiocb);
+	lpfc_rcv_plogi(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prli_mapped_node(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+	lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_padisc_mapped_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport,
+			    struct lpfc_nodelist *ndlp,
+			    void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+	lpfc_rcv_padisc(vport, ndlp, cmdiocb);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			  void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
-
-	cmdiocb = (struct lpfc_iocbq *) arg;
+	struct lpfc_hba  *phba = vport->phba;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* flush the target */
-	spin_lock_irq(phba->host->host_lock);
 	lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-			       ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
-	spin_unlock_irq(phba->host->host_lock);
+			    ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
 
 	/* Treat like rcv logo */
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
+			      struct lpfc_nodelist *ndlp,
+			      void *arg,
+			      uint32_t evt)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
 	ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
-	lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-	spin_lock_irq(phba->host->host_lock);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
-	spin_unlock_irq(phba->host->host_lock);
-	lpfc_disc_set_adisc(phba, ndlp);
+	spin_unlock_irq(shost->host_lock);
+	lpfc_disc_set_adisc(vport, ndlp);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq *cmdiocb;
-
-	cmdiocb = (struct lpfc_iocbq *) arg;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_iocbq *cmdiocb  = (struct lpfc_iocbq *) arg;
 
 	/* Ignore PLOGI if we have an outstanding LOGO */
-	if (ndlp->nlp_flag & NLP_LOGO_SND) {
+	if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) {
 		return ndlp->nlp_state;
 	}
 
-	if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
-		spin_lock_irq(phba->host->host_lock);
+	if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		return ndlp->nlp_state;
 	}
 
 	/* send PLOGI immediately, move to PLOGI issue state */
 	if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
 		ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-		lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
-		lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+		lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
 	}
 
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prli_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+		       void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq     *cmdiocb;
-	struct ls_rjt          stat;
-
-	cmdiocb = (struct lpfc_iocbq *) arg;
+	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
+	struct ls_rjt     stat;
 
 	memset(&stat, 0, sizeof (struct ls_rjt));
 	stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 	stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
-	lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+	lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
 
 	if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
 		if (ndlp->nlp_flag & NLP_NPR_ADISC) {
-			spin_lock_irq(phba->host->host_lock);
+			spin_lock_irq(shost->host_lock);
 			ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-			spin_unlock_irq(phba->host->host_lock);
 			ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
-			lpfc_issue_els_adisc(phba, ndlp, 0);
+			spin_unlock_irq(shost->host_lock);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+			lpfc_issue_els_adisc(vport, ndlp, 0);
 		} else {
 			ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
-			lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+			lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
 		}
 	}
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_logo_npr_node(struct lpfc_vport *vport,  struct lpfc_nodelist *ndlp,
+		       void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq     *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+	lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq     *cmdiocb;
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+	lpfc_rcv_padisc(vport, ndlp, cmdiocb);
 
 	/*
 	 * Do not start discovery if discovery is about to start
@@ -1586,53 +1708,52 @@
 	 * here will affect the counting of discovery threads.
 	 */
 	if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
-		!(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
+	    !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
 		if (ndlp->nlp_flag & NLP_NPR_ADISC) {
+			ndlp->nlp_flag &= ~NLP_NPR_ADISC;
 			ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
-			lpfc_issue_els_adisc(phba, ndlp, 0);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+			lpfc_issue_els_adisc(vport, ndlp, 0);
 		} else {
 			ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
-			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
-			lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+			lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+			lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
 		}
 	}
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_rcv_prlo_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+		       void *arg, uint32_t evt)
 {
-	struct lpfc_iocbq     *cmdiocb;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
-	cmdiocb = (struct lpfc_iocbq *) arg;
-
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag |= NLP_LOGO_ACC;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 
-	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+	lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
 
-	if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
+	if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
 		mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_DELAY_TMO;
 		ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 		ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
 	} else {
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(shost->host_lock);
 	}
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb, *rspiocb;
 	IOCB_t *irsp;
@@ -1642,15 +1763,15 @@
 
 	irsp = &rspiocb->iocb;
 	if (irsp->ulpStatus) {
-		lpfc_drop_node(phba, ndlp);
+		lpfc_drop_node(vport, ndlp);
 		return NLP_STE_FREED_NODE;
 	}
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
-			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb, *rspiocb;
 	IOCB_t *irsp;
@@ -1660,25 +1781,24 @@
 
 	irsp = &rspiocb->iocb;
 	if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
-		lpfc_drop_node(phba, ndlp);
+		lpfc_drop_node(vport, ndlp);
 		return NLP_STE_FREED_NODE;
 	}
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_logo_npr_node(struct lpfc_hba * phba,
-		struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			void *arg, uint32_t evt)
 {
-	lpfc_unreg_rpi(phba, ndlp);
+	lpfc_unreg_rpi(vport, ndlp);
 	/* This routine does nothing, just return the current state */
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			 void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb, *rspiocb;
 	IOCB_t *irsp;
@@ -1688,28 +1808,25 @@
 
 	irsp = &rspiocb->iocb;
 	if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
-		lpfc_drop_node(phba, ndlp);
+		lpfc_drop_node(vport, ndlp);
 		return NLP_STE_FREED_NODE;
 	}
 	return ndlp->nlp_state;
 }
 
 static uint32_t
-lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,
+			    struct lpfc_nodelist *ndlp,
+			    void *arg, uint32_t evt)
 {
-	LPFC_MBOXQ_t *pmb;
-	MAILBOX_t *mb;
-
-	pmb = (LPFC_MBOXQ_t *) arg;
-	mb = &pmb->mb;
+	LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
+	MAILBOX_t    *mb = &pmb->mb;
 
 	if (!mb->mbxStatus)
 		ndlp->nlp_rpi = mb->un.varWords[0];
 	else {
 		if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
-			lpfc_drop_node(phba, ndlp);
+			lpfc_drop_node(vport, ndlp);
 			return NLP_STE_FREED_NODE;
 		}
 	}
@@ -1717,28 +1834,38 @@
 }
 
 static uint32_t
-lpfc_device_rm_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			void *arg, uint32_t evt)
 {
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
 	if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		spin_unlock_irq(shost->host_lock);
 		return ndlp->nlp_state;
 	}
-	lpfc_drop_node(phba, ndlp);
+	lpfc_drop_node(vport, ndlp);
 	return NLP_STE_FREED_NODE;
 }
 
 static uint32_t
-lpfc_device_recov_npr_node(struct lpfc_hba * phba,
-			    struct lpfc_nodelist * ndlp, void *arg,
-			    uint32_t evt)
+lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			   void *arg, uint32_t evt)
 {
-	spin_lock_irq(phba->host->host_lock);
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	/* Don't do anything that will mess up processing of the
+	 * previous RSCN.
+	 */
+	if (vport->fc_flag & FC_RSCN_DEFERRED)
+		return ndlp->nlp_state;
+
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(shost->host_lock);
 	if (ndlp->nlp_flag & NLP_DELAY_TMO) {
-		lpfc_cancel_retry_delay_tmo(phba, ndlp);
+		lpfc_cancel_retry_delay_tmo(vport, ndlp);
 	}
 	return ndlp->nlp_state;
 }
@@ -1801,7 +1928,7 @@
  */
 
 static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
-     (struct lpfc_hba *, struct lpfc_nodelist *, void *, uint32_t) = {
+     (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = {
 	/* Action routine                  Event       Current State  */
 	lpfc_rcv_plogi_unused_node,	/* RCV_PLOGI   UNUSED_NODE    */
 	lpfc_rcv_els_unused_node,	/* RCV_PRLI        */
@@ -1818,7 +1945,7 @@
 	lpfc_disc_illegal,		/* DEVICE_RECOVERY */
 
 	lpfc_rcv_plogi_plogi_issue,	/* RCV_PLOGI   PLOGI_ISSUE    */
-	lpfc_rcv_els_plogi_issue,	/* RCV_PRLI        */
+	lpfc_rcv_prli_plogi_issue,	/* RCV_PRLI        */
 	lpfc_rcv_logo_plogi_issue,	/* RCV_LOGO        */
 	lpfc_rcv_els_plogi_issue,	/* RCV_ADISC       */
 	lpfc_rcv_els_plogi_issue,	/* RCV_PDISC       */
@@ -1917,35 +2044,41 @@
 };
 
 int
-lpfc_disc_state_machine(struct lpfc_hba * phba,
-			struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			void *arg, uint32_t evt)
 {
+	struct lpfc_hba  *phba = vport->phba;
 	uint32_t cur_state, rc;
-	uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *,
+	uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,
 			 uint32_t);
 
 	lpfc_nlp_get(ndlp);
 	cur_state = ndlp->nlp_state;
 
 	/* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
-	lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_DISCOVERY,
-			"%d:0211 DSM in event x%x on NPort x%x in state %d "
-			"Data: x%x\n",
-			phba->brd_no,
+	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			"%d (%d):0211 DSM in event x%x on NPort x%x in "
+			"state %d Data: x%x\n",
+			phba->brd_no, vport->vpi,
 			evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
+		 "DSM in:          evt:%d ste:%d did:x%x",
+		evt, cur_state, ndlp->nlp_DID);
+
 	func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
-	rc = (func) (phba, ndlp, arg, evt);
+	rc = (func) (vport, ndlp, arg, evt);
 
 	/* DSM out state <rc> on NPort <nlp_DID> */
-	lpfc_printf_log(phba,
-		       KERN_INFO,
-		       LOG_DISCOVERY,
-		       "%d:0212 DSM out state %d on NPort x%x Data: x%x\n",
-		       phba->brd_no,
-		       rc, ndlp->nlp_DID, ndlp->nlp_flag);
+	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			"%d (%d):0212 DSM out state %d on NPort x%x "
+			"Data: x%x\n",
+			phba->brd_no, vport->vpi,
+			rc, ndlp->nlp_DID, ndlp->nlp_flag);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
+		 "DSM out:         ste:%d did:x%x flg:x%x",
+		rc, ndlp->nlp_DID, ndlp->nlp_flag);
 
 	lpfc_nlp_put(ndlp);
 
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 9a12d05..8f45bbc 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -37,10 +37,158 @@
 #include "lpfc.h"
 #include "lpfc_logmsg.h"
 #include "lpfc_crtn.h"
+#include "lpfc_vport.h"
 
 #define LPFC_RESET_WAIT  2
 #define LPFC_ABORT_WAIT  2
 
+/*
+ * This function is called with no lock held when there is a resource
+ * error in driver or in firmware.
+ */
+void
+lpfc_adjust_queue_depth(struct lpfc_hba *phba)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&phba->hbalock, flags);
+	atomic_inc(&phba->num_rsrc_err);
+	phba->last_rsrc_error_time = jiffies;
+
+	if ((phba->last_ramp_down_time + QUEUE_RAMP_DOWN_INTERVAL) > jiffies) {
+		spin_unlock_irqrestore(&phba->hbalock, flags);
+		return;
+	}
+
+	phba->last_ramp_down_time = jiffies;
+
+	spin_unlock_irqrestore(&phba->hbalock, flags);
+
+	spin_lock_irqsave(&phba->pport->work_port_lock, flags);
+	if ((phba->pport->work_port_events &
+		WORKER_RAMP_DOWN_QUEUE) == 0) {
+		phba->pport->work_port_events |= WORKER_RAMP_DOWN_QUEUE;
+	}
+	spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
+
+	spin_lock_irqsave(&phba->hbalock, flags);
+	if (phba->work_wait)
+		wake_up(phba->work_wait);
+	spin_unlock_irqrestore(&phba->hbalock, flags);
+
+	return;
+}
+
+/*
+ * This function is called with no lock held when there is a successful
+ * SCSI command completion.
+ */
+static inline void
+lpfc_rampup_queue_depth(struct lpfc_hba *phba,
+			struct scsi_device *sdev)
+{
+	unsigned long flags;
+	atomic_inc(&phba->num_cmd_success);
+
+	if (phba->cfg_lun_queue_depth <= sdev->queue_depth)
+		return;
+
+	spin_lock_irqsave(&phba->hbalock, flags);
+	if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) ||
+	 ((phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL ) > jiffies)) {
+		spin_unlock_irqrestore(&phba->hbalock, flags);
+		return;
+	}
+
+	phba->last_ramp_up_time = jiffies;
+	spin_unlock_irqrestore(&phba->hbalock, flags);
+
+	spin_lock_irqsave(&phba->pport->work_port_lock, flags);
+	if ((phba->pport->work_port_events &
+		WORKER_RAMP_UP_QUEUE) == 0) {
+		phba->pport->work_port_events |= WORKER_RAMP_UP_QUEUE;
+	}
+	spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
+
+	spin_lock_irqsave(&phba->hbalock, flags);
+	if (phba->work_wait)
+		wake_up(phba->work_wait);
+	spin_unlock_irqrestore(&phba->hbalock, flags);
+}
+
+void
+lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
+{
+	struct lpfc_vport *vport;
+	struct Scsi_Host  *host;
+	struct scsi_device *sdev;
+	unsigned long new_queue_depth;
+	unsigned long num_rsrc_err, num_cmd_success;
+
+	num_rsrc_err = atomic_read(&phba->num_rsrc_err);
+	num_cmd_success = atomic_read(&phba->num_cmd_success);
+
+	spin_lock_irq(&phba->hbalock);
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		host = lpfc_shost_from_vport(vport);
+		if (!scsi_host_get(host))
+			continue;
+
+		spin_unlock_irq(&phba->hbalock);
+
+		shost_for_each_device(sdev, host) {
+			new_queue_depth = sdev->queue_depth * num_rsrc_err /
+			(num_rsrc_err + num_cmd_success);
+			if (!new_queue_depth)
+				new_queue_depth = sdev->queue_depth - 1;
+			else
+				new_queue_depth =
+					sdev->queue_depth - new_queue_depth;
+
+			if (sdev->ordered_tags)
+				scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
+					new_queue_depth);
+			else
+				scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
+					new_queue_depth);
+		}
+		spin_lock_irq(&phba->hbalock);
+		scsi_host_put(host);
+	}
+	spin_unlock_irq(&phba->hbalock);
+	atomic_set(&phba->num_rsrc_err, 0);
+	atomic_set(&phba->num_cmd_success, 0);
+}
+
+void
+lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
+{
+	struct lpfc_vport *vport;
+	struct Scsi_Host  *host;
+	struct scsi_device *sdev;
+
+	spin_lock_irq(&phba->hbalock);
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		host = lpfc_shost_from_vport(vport);
+		if (!scsi_host_get(host))
+			continue;
+
+		spin_unlock_irq(&phba->hbalock);
+		shost_for_each_device(sdev, host) {
+			if (sdev->ordered_tags)
+				scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
+					sdev->queue_depth+1);
+			else
+				scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
+					sdev->queue_depth+1);
+		}
+		spin_lock_irq(&phba->hbalock);
+		scsi_host_put(host);
+	}
+	spin_unlock_irq(&phba->hbalock);
+	atomic_set(&phba->num_rsrc_err, 0);
+	atomic_set(&phba->num_cmd_success, 0);
+}
 
 /*
  * This routine allocates a scsi buffer, which contains all the necessary
@@ -51,8 +199,9 @@
  * and the BPL BDE is setup in the IOCB.
  */
 static struct lpfc_scsi_buf *
-lpfc_new_scsi_buf(struct lpfc_hba * phba)
+lpfc_new_scsi_buf(struct lpfc_vport *vport)
 {
+	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_scsi_buf *psb;
 	struct ulp_bde64 *bpl;
 	IOCB_t *iocb;
@@ -63,7 +212,6 @@
 	if (!psb)
 		return NULL;
 	memset(psb, 0, sizeof (struct lpfc_scsi_buf));
-	psb->scsi_hba = phba;
 
 	/*
 	 * Get memory from the pci pool to map the virt space to pci bus space
@@ -155,7 +303,7 @@
 }
 
 static void
-lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
+lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
 {
 	unsigned long iflag = 0;
 
@@ -166,7 +314,7 @@
 }
 
 static int
-lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
+lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
 {
 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
 	struct scatterlist *sgel = NULL;
@@ -175,8 +323,7 @@
 	IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
 	dma_addr_t physaddr;
 	uint32_t i, num_bde = 0;
-	int datadir = scsi_cmnd->sc_data_direction;
-	int dma_error;
+	int nseg, datadir = scsi_cmnd->sc_data_direction;
 
 	/*
 	 * There are three possibilities here - use scatter-gather segment, use
@@ -185,26 +332,26 @@
 	 * data bde entry.
 	 */
 	bpl += 2;
-	if (scsi_cmnd->use_sg) {
+	if (scsi_sg_count(scsi_cmnd)) {
 		/*
 		 * The driver stores the segment count returned from pci_map_sg
 		 * because this a count of dma-mappings used to map the use_sg
 		 * pages.  They are not guaranteed to be the same for those
 		 * architectures that implement an IOMMU.
 		 */
-		sgel = (struct scatterlist *)scsi_cmnd->request_buffer;
-		lpfc_cmd->seg_cnt = dma_map_sg(&phba->pcidev->dev, sgel,
-						scsi_cmnd->use_sg, datadir);
-		if (lpfc_cmd->seg_cnt == 0)
+
+		nseg = dma_map_sg(&phba->pcidev->dev, scsi_sglist(scsi_cmnd),
+				  scsi_sg_count(scsi_cmnd), datadir);
+		if (unlikely(!nseg))
 			return 1;
 
+		lpfc_cmd->seg_cnt = nseg;
 		if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
 			printk(KERN_ERR "%s: Too many sg segments from "
 			       "dma_map_sg.  Config %d, seg_cnt %d",
 			       __FUNCTION__, phba->cfg_sg_seg_cnt,
 			       lpfc_cmd->seg_cnt);
-			dma_unmap_sg(&phba->pcidev->dev, sgel,
-				     lpfc_cmd->seg_cnt, datadir);
+			scsi_dma_unmap(scsi_cmnd);
 			return 1;
 		}
 
@@ -214,7 +361,7 @@
 		 * single scsi command.  Just run through the seg_cnt and format
 		 * the bde's.
 		 */
-		for (i = 0; i < lpfc_cmd->seg_cnt; i++) {
+		scsi_for_each_sg(scsi_cmnd, sgel, nseg, i) {
 			physaddr = sg_dma_address(sgel);
 			bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr));
 			bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
@@ -225,34 +372,8 @@
 				bpl->tus.f.bdeFlags = BUFF_USE_RCV;
 			bpl->tus.w = le32_to_cpu(bpl->tus.w);
 			bpl++;
-			sgel++;
 			num_bde++;
 		}
-	} else if (scsi_cmnd->request_buffer && scsi_cmnd->request_bufflen) {
-		physaddr = dma_map_single(&phba->pcidev->dev,
-					  scsi_cmnd->request_buffer,
-					  scsi_cmnd->request_bufflen,
-					  datadir);
-		dma_error = dma_mapping_error(physaddr);
-		if (dma_error) {
-			lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-				"%d:0718 Unable to dma_map_single "
-				"request_buffer: x%x\n",
-				phba->brd_no, dma_error);
-			return 1;
-		}
-
-		lpfc_cmd->nonsg_phys = physaddr;
-		bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr));
-		bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
-		bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen;
-		if (datadir == DMA_TO_DEVICE)
-			bpl->tus.f.bdeFlags = 0;
-		else
-			bpl->tus.f.bdeFlags = BUFF_USE_RCV;
-		bpl->tus.w = le32_to_cpu(bpl->tus.w);
-		num_bde = 1;
-		bpl++;
 	}
 
 	/*
@@ -266,7 +387,7 @@
 		(num_bde * sizeof (struct ulp_bde64));
 	iocb_cmd->ulpBdeCount = 1;
 	iocb_cmd->ulpLe = 1;
-	fcp_cmnd->fcpDl = be32_to_cpu(scsi_cmnd->request_bufflen);
+	fcp_cmnd->fcpDl = be32_to_cpu(scsi_bufflen(scsi_cmnd));
 	return 0;
 }
 
@@ -279,26 +400,20 @@
 	 * a request buffer, but did not request use_sg.  There is a third
 	 * case, but it does not require resource deallocation.
 	 */
-	if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
-		dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
-				psb->seg_cnt, psb->pCmd->sc_data_direction);
-	} else {
-		 if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
-			dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
-						psb->pCmd->request_bufflen,
-						psb->pCmd->sc_data_direction);
-		 }
-	}
+	if (psb->seg_cnt > 0)
+		scsi_dma_unmap(psb->pCmd);
 }
 
 static void
-lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
+lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
+		    struct lpfc_iocbq *rsp_iocb)
 {
 	struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
 	struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
 	struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
-	struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
+	struct lpfc_hba *phba = vport->phba;
 	uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
+	uint32_t vpi = vport->vpi;
 	uint32_t resp_info = fcprsp->rspStatus2;
 	uint32_t scsi_status = fcprsp->rspStatus3;
 	uint32_t *lp;
@@ -331,9 +446,9 @@
 		logit = LOG_FCP;
 
 	lpfc_printf_log(phba, KERN_WARNING, logit,
-			"%d:0730 FCP command x%x failed: x%x SNS x%x x%x "
+			"%d (%d):0730 FCP command x%x failed: x%x SNS x%x x%x "
 			"Data: x%x x%x x%x x%x x%x\n",
-			phba->brd_no, cmnd->cmnd[0], scsi_status,
+			phba->brd_no, vpi, cmnd->cmnd[0], scsi_status,
 			be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info,
 			be32_to_cpu(fcprsp->rspResId),
 			be32_to_cpu(fcprsp->rspSnsLen),
@@ -349,15 +464,16 @@
 		}
 	}
 
-	cmnd->resid = 0;
+	scsi_set_resid(cmnd, 0);
 	if (resp_info & RESID_UNDER) {
-		cmnd->resid = be32_to_cpu(fcprsp->rspResId);
+		scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
 
 		lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
-				"%d:0716 FCP Read Underrun, expected %d, "
-				"residual %d Data: x%x x%x x%x\n", phba->brd_no,
-				be32_to_cpu(fcpcmd->fcpDl), cmnd->resid,
-				fcpi_parm, cmnd->cmnd[0], cmnd->underflow);
+				"%d (%d):0716 FCP Read Underrun, expected %d, "
+				"residual %d Data: x%x x%x x%x\n",
+				phba->brd_no, vpi, be32_to_cpu(fcpcmd->fcpDl),
+				scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0],
+				cmnd->underflow);
 
 		/*
 		 * If there is an under run check if under run reported by
@@ -366,15 +482,16 @@
 		 */
 		if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
 			fcpi_parm &&
-			(cmnd->resid != fcpi_parm)) {
+			(scsi_get_resid(cmnd) != fcpi_parm)) {
 			lpfc_printf_log(phba, KERN_WARNING,
-				LOG_FCP | LOG_FCP_ERROR,
-				"%d:0735 FCP Read Check Error and Underrun "
-				"Data: x%x x%x x%x x%x\n", phba->brd_no,
-				be32_to_cpu(fcpcmd->fcpDl),
-				cmnd->resid,
-				fcpi_parm, cmnd->cmnd[0]);
-			cmnd->resid = cmnd->request_bufflen;
+					LOG_FCP | LOG_FCP_ERROR,
+					"%d (%d):0735 FCP Read Check Error "
+					"and Underrun Data: x%x x%x x%x x%x\n",
+					phba->brd_no, vpi,
+					be32_to_cpu(fcpcmd->fcpDl),
+					scsi_get_resid(cmnd), fcpi_parm,
+					cmnd->cmnd[0]);
+			scsi_set_resid(cmnd, scsi_bufflen(cmnd));
 			host_status = DID_ERROR;
 		}
 		/*
@@ -385,22 +502,23 @@
 		 */
 		if (!(resp_info & SNS_LEN_VALID) &&
 		    (scsi_status == SAM_STAT_GOOD) &&
-		    (cmnd->request_bufflen - cmnd->resid) < cmnd->underflow) {
+		    (scsi_bufflen(cmnd) - scsi_get_resid(cmnd)
+		     < cmnd->underflow)) {
 			lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
-					"%d:0717 FCP command x%x residual "
+					"%d (%d):0717 FCP command x%x residual "
 					"underrun converted to error "
-					"Data: x%x x%x x%x\n", phba->brd_no,
-					cmnd->cmnd[0], cmnd->request_bufflen,
-					cmnd->resid, cmnd->underflow);
-
+					"Data: x%x x%x x%x\n",
+					phba->brd_no, vpi, cmnd->cmnd[0],
+					scsi_bufflen(cmnd),
+					scsi_get_resid(cmnd), cmnd->underflow);
 			host_status = DID_ERROR;
 		}
 	} else if (resp_info & RESID_OVER) {
 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
-				"%d:0720 FCP command x%x residual "
+				"%d (%d):0720 FCP command x%x residual "
 				"overrun error. Data: x%x x%x \n",
-				phba->brd_no, cmnd->cmnd[0],
-				cmnd->request_bufflen, cmnd->resid);
+				phba->brd_no, vpi, cmnd->cmnd[0],
+				scsi_bufflen(cmnd), scsi_get_resid(cmnd));
 		host_status = DID_ERROR;
 
 	/*
@@ -410,13 +528,14 @@
 	} else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm &&
 			(cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
-			"%d:0734 FCP Read Check Error Data: "
-			"x%x x%x x%x x%x\n", phba->brd_no,
-			be32_to_cpu(fcpcmd->fcpDl),
-			be32_to_cpu(fcprsp->rspResId),
-			fcpi_parm, cmnd->cmnd[0]);
+				"%d (%d):0734 FCP Read Check Error Data: "
+				"x%x x%x x%x x%x\n",
+				phba->brd_no, vpi,
+				be32_to_cpu(fcpcmd->fcpDl),
+				be32_to_cpu(fcprsp->rspResId),
+				fcpi_parm, cmnd->cmnd[0]);
 		host_status = DID_ERROR;
-		cmnd->resid = cmnd->request_bufflen;
+		scsi_set_resid(cmnd, scsi_bufflen(cmnd));
 	}
 
  out:
@@ -429,9 +548,13 @@
 {
 	struct lpfc_scsi_buf *lpfc_cmd =
 		(struct lpfc_scsi_buf *) pIocbIn->context1;
+	struct lpfc_vport      *vport = pIocbIn->vport;
 	struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
 	struct lpfc_nodelist *pnode = rdata->pnode;
 	struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
+	uint32_t vpi = (lpfc_cmd->cur_iocbq.vport
+			? lpfc_cmd->cur_iocbq.vport->vpi
+			: 0);
 	int result;
 	struct scsi_device *sdev, *tmp_sdev;
 	int depth = 0;
@@ -447,22 +570,31 @@
 			lpfc_cmd->status = IOSTAT_DEFAULT;
 
 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
-				"%d:0729 FCP cmd x%x failed <%d/%d> status: "
-				"x%x result: x%x Data: x%x x%x\n",
-				phba->brd_no, cmd->cmnd[0], cmd->device->id,
-				cmd->device->lun, lpfc_cmd->status,
-				lpfc_cmd->result, pIocbOut->iocb.ulpContext,
+				"%d (%d):0729 FCP cmd x%x failed <%d/%d> "
+				"status: x%x result: x%x Data: x%x x%x\n",
+				phba->brd_no, vpi, cmd->cmnd[0],
+				cmd->device ? cmd->device->id : 0xffff,
+				cmd->device ? cmd->device->lun : 0xffff,
+				lpfc_cmd->status, lpfc_cmd->result,
+				pIocbOut->iocb.ulpContext,
 				lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
 
 		switch (lpfc_cmd->status) {
 		case IOSTAT_FCP_RSP_ERROR:
 			/* Call FCP RSP handler to determine result */
-			lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
+			lpfc_handle_fcp_err(vport, lpfc_cmd, pIocbOut);
 			break;
 		case IOSTAT_NPORT_BSY:
 		case IOSTAT_FABRIC_BSY:
 			cmd->result = ScsiResult(DID_BUS_BUSY, 0);
 			break;
+		case IOSTAT_LOCAL_REJECT:
+			if (lpfc_cmd->result == RJT_UNAVAIL_PERM ||
+			    lpfc_cmd->result == IOERR_NO_RESOURCES ||
+			    lpfc_cmd->result == RJT_LOGIN_REQUIRED) {
+				cmd->result = ScsiResult(DID_REQUEUE, 0);
+			break;
+		} /* else: fall through */
 		default:
 			cmd->result = ScsiResult(DID_ERROR, 0);
 			break;
@@ -479,11 +611,12 @@
 		uint32_t *lp = (uint32_t *)cmd->sense_buffer;
 
 		lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
-				"%d:0710 Iodone <%d/%d> cmd %p, error x%x "
-				"SNS x%x x%x Data: x%x x%x\n",
-				phba->brd_no, cmd->device->id,
+				"%d (%d):0710 Iodone <%d/%d> cmd %p, error "
+				"x%x SNS x%x x%x Data: x%x x%x\n",
+				phba->brd_no, vpi, cmd->device->id,
 				cmd->device->lun, cmd, cmd->result,
-				*lp, *(lp + 3), cmd->retries, cmd->resid);
+				*lp, *(lp + 3), cmd->retries,
+				scsi_get_resid(cmd));
 	}
 
 	result = cmd->result;
@@ -496,6 +629,10 @@
 		return;
 	}
 
+
+	if (!result)
+		lpfc_rampup_queue_depth(phba, sdev);
+
 	if (!result && pnode != NULL &&
 	   ((jiffies - pnode->last_ramp_up_time) >
 		LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
@@ -534,7 +671,7 @@
 					tmp_sdev->queue_depth - 1);
 		}
 		/*
- 		 * The queue depth cannot be lowered any more.
+		 * The queue depth cannot be lowered any more.
 		 * Modify the returned error code to store
 		 * the final depth value set by
 		 * scsi_track_queue_full.
@@ -544,8 +681,9 @@
 
 		if (depth) {
 			lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
-				"%d:0711 detected queue full - lun queue depth "
-				" adjusted to %d.\n", phba->brd_no, depth);
+					"%d (%d):0711 detected queue full - "
+					"lun queue depth  adjusted to %d.\n",
+					phba->brd_no, vpi, depth);
 		}
 	}
 
@@ -553,9 +691,10 @@
 }
 
 static void
-lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
-			struct lpfc_nodelist *pnode)
+lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
+		    struct lpfc_nodelist *pnode)
 {
+	struct lpfc_hba *phba = vport->phba;
 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
 	IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
@@ -592,7 +731,7 @@
 	 * bumping the bpl beyond the fcp_cmnd and fcp_rsp regions to the first
 	 * data bde entry.
 	 */
-	if (scsi_cmnd->use_sg) {
+	if (scsi_sg_count(scsi_cmnd)) {
 		if (datadir == DMA_TO_DEVICE) {
 			iocb_cmd->ulpCommand = CMD_FCP_IWRITE64_CR;
 			iocb_cmd->un.fcpi.fcpi_parm = 0;
@@ -602,23 +741,7 @@
 		} else {
 			iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR;
 			iocb_cmd->ulpPU = PARM_READ_CHECK;
-			iocb_cmd->un.fcpi.fcpi_parm =
-				scsi_cmnd->request_bufflen;
-			fcp_cmnd->fcpCntl3 = READ_DATA;
-			phba->fc4InputRequests++;
-		}
-	} else if (scsi_cmnd->request_buffer && scsi_cmnd->request_bufflen) {
-		if (datadir == DMA_TO_DEVICE) {
-			iocb_cmd->ulpCommand = CMD_FCP_IWRITE64_CR;
-			iocb_cmd->un.fcpi.fcpi_parm = 0;
-			iocb_cmd->ulpPU = 0;
-			fcp_cmnd->fcpCntl3 = WRITE_DATA;
-			phba->fc4OutputRequests++;
-		} else {
-			iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR;
-			iocb_cmd->ulpPU = PARM_READ_CHECK;
-			iocb_cmd->un.fcpi.fcpi_parm =
-				scsi_cmnd->request_bufflen;
+			iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
 			fcp_cmnd->fcpCntl3 = READ_DATA;
 			phba->fc4InputRequests++;
 		}
@@ -642,15 +765,15 @@
 	piocbq->context1  = lpfc_cmd;
 	piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
 	piocbq->iocb.ulpTimeout = lpfc_cmd->timeout;
+	piocbq->vport = vport;
 }
 
 static int
-lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
+lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
 			     struct lpfc_scsi_buf *lpfc_cmd,
 			     unsigned int lun,
 			     uint8_t task_mgmt_cmd)
 {
-	struct lpfc_sli *psli;
 	struct lpfc_iocbq *piocbq;
 	IOCB_t *piocb;
 	struct fcp_cmnd *fcp_cmnd;
@@ -661,8 +784,9 @@
 		return 0;
 	}
 
-	psli = &phba->sli;
 	piocbq = &(lpfc_cmd->cur_iocbq);
+	piocbq->vport = vport;
+
 	piocb = &piocbq->iocb;
 
 	fcp_cmnd = lpfc_cmd->fcp_cmnd;
@@ -688,7 +812,7 @@
 		piocb->ulpTimeout = lpfc_cmd->timeout;
 	}
 
-	return (1);
+	return 1;
 }
 
 static void
@@ -704,10 +828,11 @@
 }
 
 static int
-lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
+lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
 		    unsigned  tgt_id, unsigned int lun,
 		    struct lpfc_rport_data *rdata)
 {
+	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_iocbq *iocbq;
 	struct lpfc_iocbq *iocbqrsp;
 	int ret;
@@ -716,12 +841,11 @@
 		return FAILED;
 
 	lpfc_cmd->rdata = rdata;
-	ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun,
+	ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun,
 					   FCP_TARGET_RESET);
 	if (!ret)
 		return FAILED;
 
-	lpfc_cmd->scsi_hba = phba;
 	iocbq = &lpfc_cmd->cur_iocbq;
 	iocbqrsp = lpfc_sli_get_iocbq(phba);
 
@@ -730,10 +854,10 @@
 
 	/* Issue Target Reset to TGT <num> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
-			"%d:0702 Issue Target Reset to TGT %d "
+			"%d (%d):0702 Issue Target Reset to TGT %d "
 			"Data: x%x x%x\n",
-			phba->brd_no, tgt_id, rdata->pnode->nlp_rpi,
-			rdata->pnode->nlp_flag);
+			phba->brd_no, vport->vpi, tgt_id,
+			rdata->pnode->nlp_rpi, rdata->pnode->nlp_flag);
 
 	ret = lpfc_sli_issue_iocb_wait(phba,
 				       &phba->sli.ring[phba->sli.fcp_ring],
@@ -758,7 +882,8 @@
 const char *
 lpfc_info(struct Scsi_Host *host)
 {
-	struct lpfc_hba    *phba = (struct lpfc_hba *) host->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) host->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	int len;
 	static char  lpfcinfobuf[384];
 
@@ -800,26 +925,22 @@
 
 void lpfc_poll_timeout(unsigned long ptr)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
-	unsigned long iflag;
-
-	spin_lock_irqsave(phba->host->host_lock, iflag);
+	struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
 
 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
 		lpfc_sli_poll_fcp_ring (phba);
 		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
 			lpfc_poll_rearm_timer(phba);
 	}
-
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
 }
 
 static int
 lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 {
-	struct lpfc_hba *phba =
-		(struct lpfc_hba *) cmnd->device->host->hostdata;
-	struct lpfc_sli *psli = &phba->sli;
+	struct Scsi_Host  *shost = cmnd->device->host;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_sli   *psli = &phba->sli;
 	struct lpfc_rport_data *rdata = cmnd->device->hostdata;
 	struct lpfc_nodelist *ndlp = rdata->pnode;
 	struct lpfc_scsi_buf *lpfc_cmd;
@@ -840,11 +961,14 @@
 		cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
 		goto out_fail_command;
 	}
-	lpfc_cmd = lpfc_get_scsi_buf (phba);
+	lpfc_cmd = lpfc_get_scsi_buf(phba);
 	if (lpfc_cmd == NULL) {
+		lpfc_adjust_queue_depth(phba);
+
 		lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
-				"%d:0707 driver's buffer pool is empty, "
-				"IO busied\n", phba->brd_no);
+				"%d (%d):0707 driver's buffer pool is empty, "
+				"IO busied\n",
+				phba->brd_no, vport->vpi);
 		goto out_host_busy;
 	}
 
@@ -862,10 +986,10 @@
 	if (err)
 		goto out_host_busy_free_buf;
 
-	lpfc_scsi_prep_cmnd(phba, lpfc_cmd, ndlp);
+	lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
 
 	err = lpfc_sli_issue_iocb(phba, &phba->sli.ring[psli->fcp_ring],
-				&lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
+				  &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
 	if (err)
 		goto out_host_busy_free_buf;
 
@@ -907,8 +1031,9 @@
 static int
 lpfc_abort_handler(struct scsi_cmnd *cmnd)
 {
-	struct Scsi_Host *shost = cmnd->device->host;
-	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+	struct Scsi_Host  *shost = cmnd->device->host;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
 	struct lpfc_iocbq *iocb;
 	struct lpfc_iocbq *abtsiocb;
@@ -918,8 +1043,6 @@
 	int ret = SUCCESS;
 
 	lpfc_block_error_handler(cmnd);
-	spin_lock_irq(shost->host_lock);
-
 	lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
 	BUG_ON(!lpfc_cmd);
 
@@ -956,12 +1079,13 @@
 
 	icmd->ulpLe = 1;
 	icmd->ulpClass = cmd->ulpClass;
-	if (phba->hba_state >= LPFC_LINK_UP)
+	if (lpfc_is_link_up(phba))
 		icmd->ulpCommand = CMD_ABORT_XRI_CN;
 	else
 		icmd->ulpCommand = CMD_CLOSE_XRI_CN;
 
 	abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
+	abtsiocb->vport = vport;
 	if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == IOCB_ERROR) {
 		lpfc_sli_release_iocbq(phba, abtsiocb);
 		ret = FAILED;
@@ -977,9 +1101,7 @@
 		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
 			lpfc_sli_poll_fcp_ring (phba);
 
-		spin_unlock_irq(phba->host->host_lock);
-			schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
-		spin_lock_irq(phba->host->host_lock);
+		schedule_timeout_uninterruptible(LPFC_ABORT_WAIT * HZ);
 		if (++loop_count
 		    > (2 * phba->cfg_devloss_tmo)/LPFC_ABORT_WAIT)
 			break;
@@ -988,30 +1110,30 @@
 	if (lpfc_cmd->pCmd == cmnd) {
 		ret = FAILED;
 		lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-				"%d:0748 abort handler timed out waiting for "
-				"abort to complete: ret %#x, ID %d, LUN %d, "
-				"snum %#lx\n",
-				phba->brd_no,  ret, cmnd->device->id,
-				cmnd->device->lun, cmnd->serial_number);
+				"%d (%d):0748 abort handler timed out waiting "
+				"for abort to complete: ret %#x, ID %d, "
+				"LUN %d, snum %#lx\n",
+				phba->brd_no, vport->vpi, ret,
+				cmnd->device->id, cmnd->device->lun,
+				cmnd->serial_number);
 	}
 
  out:
 	lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
-			"%d:0749 SCSI Layer I/O Abort Request "
+			"%d (%d):0749 SCSI Layer I/O Abort Request "
 			"Status x%x ID %d LUN %d snum %#lx\n",
-			phba->brd_no, ret, cmnd->device->id,
+			phba->brd_no, vport->vpi, ret, cmnd->device->id,
 			cmnd->device->lun, cmnd->serial_number);
 
-	spin_unlock_irq(shost->host_lock);
-
 	return ret;
 }
 
 static int
 lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
 {
-	struct Scsi_Host *shost = cmnd->device->host;
-	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+	struct Scsi_Host  *shost = cmnd->device->host;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_scsi_buf *lpfc_cmd;
 	struct lpfc_iocbq *iocbq, *iocbqrsp;
 	struct lpfc_rport_data *rdata = cmnd->device->hostdata;
@@ -1022,28 +1144,26 @@
 	int cnt, loopcnt;
 
 	lpfc_block_error_handler(cmnd);
-	spin_lock_irq(shost->host_lock);
 	loopcnt = 0;
 	/*
 	 * If target is not in a MAPPED state, delay the reset until
 	 * target is rediscovered or devloss timeout expires.
 	 */
-	while ( 1 ) {
+	while (1) {
 		if (!pnode)
 			goto out;
 
 		if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
-			spin_unlock_irq(phba->host->host_lock);
 			schedule_timeout_uninterruptible(msecs_to_jiffies(500));
-			spin_lock_irq(phba->host->host_lock);
 			loopcnt++;
 			rdata = cmnd->device->hostdata;
 			if (!rdata ||
 				(loopcnt > ((phba->cfg_devloss_tmo * 2) + 1))) {
 				lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-		   			"%d:0721 LUN Reset rport failure:"
-					" cnt x%x rdata x%p\n",
-		   			phba->brd_no, loopcnt, rdata);
+						"%d (%d):0721 LUN Reset rport "
+						"failure: cnt x%x rdata x%p\n",
+						phba->brd_no, vport->vpi,
+						loopcnt, rdata);
 				goto out;
 			}
 			pnode = rdata->pnode;
@@ -1054,15 +1174,14 @@
 			break;
 	}
 
-	lpfc_cmd = lpfc_get_scsi_buf (phba);
+	lpfc_cmd = lpfc_get_scsi_buf(phba);
 	if (lpfc_cmd == NULL)
 		goto out;
 
 	lpfc_cmd->timeout = 60;
-	lpfc_cmd->scsi_hba = phba;
 	lpfc_cmd->rdata = rdata;
 
-	ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
+	ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, cmnd->device->lun,
 					   FCP_TARGET_RESET);
 	if (!ret)
 		goto out_free_scsi_buf;
@@ -1075,8 +1194,9 @@
 		goto out_free_scsi_buf;
 
 	lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
-			"%d:0703 Issue target reset to TGT %d LUN %d rpi x%x "
-			"nlp_flag x%x\n", phba->brd_no, cmnd->device->id,
+			"%d (%d):0703 Issue target reset to TGT %d LUN %d "
+			"rpi x%x nlp_flag x%x\n",
+			phba->brd_no, vport->vpi, cmnd->device->id,
 			cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
 
 	iocb_status = lpfc_sli_issue_iocb_wait(phba,
@@ -1111,9 +1231,7 @@
 				    0, LPFC_CTX_LUN);
 	loopcnt = 0;
 	while(cnt) {
-		spin_unlock_irq(phba->host->host_lock);
 		schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
-		spin_lock_irq(phba->host->host_lock);
 
 		if (++loopcnt
 		    > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
@@ -1127,8 +1245,9 @@
 
 	if (cnt) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-			"%d:0719 device reset I/O flush failure: cnt x%x\n",
-			phba->brd_no, cnt);
+				"%d (%d):0719 device reset I/O flush failure: "
+				"cnt x%x\n",
+				phba->brd_no, vport->vpi, cnt);
 		ret = FAILED;
 	}
 
@@ -1137,21 +1256,21 @@
 		lpfc_release_scsi_buf(phba, lpfc_cmd);
 	}
 	lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-			"%d:0713 SCSI layer issued device reset (%d, %d) "
+			"%d (%d):0713 SCSI layer issued device reset (%d, %d) "
 			"return x%x status x%x result x%x\n",
-			phba->brd_no, cmnd->device->id, cmnd->device->lun,
-			ret, cmd_status, cmd_result);
+			phba->brd_no, vport->vpi, cmnd->device->id,
+			cmnd->device->lun, ret, cmd_status, cmd_result);
 
 out:
-	spin_unlock_irq(shost->host_lock);
 	return ret;
 }
 
 static int
 lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
 {
-	struct Scsi_Host *shost = cmnd->device->host;
-	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+	struct Scsi_Host  *shost = cmnd->device->host;
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_nodelist *ndlp = NULL;
 	int match;
 	int ret = FAILED, i, err_count = 0;
@@ -1159,7 +1278,6 @@
 	struct lpfc_scsi_buf * lpfc_cmd;
 
 	lpfc_block_error_handler(cmnd);
-	spin_lock_irq(shost->host_lock);
 
 	lpfc_cmd = lpfc_get_scsi_buf(phba);
 	if (lpfc_cmd == NULL)
@@ -1167,7 +1285,6 @@
 
 	/* The lpfc_cmd storage is reused.  Set all loop invariants. */
 	lpfc_cmd->timeout = 60;
-	lpfc_cmd->scsi_hba = phba;
 
 	/*
 	 * Since the driver manages a single bus device, reset all
@@ -1177,7 +1294,8 @@
 	for (i = 0; i < LPFC_MAX_TARGET; i++) {
 		/* Search for mapped node by target ID */
 		match = 0;
-		list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+		spin_lock_irq(shost->host_lock);
+		list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
 			if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
 			    i == ndlp->nlp_sid &&
 			    ndlp->rport) {
@@ -1185,15 +1303,18 @@
 				break;
 			}
 		}
+		spin_unlock_irq(shost->host_lock);
 		if (!match)
 			continue;
 
-		ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba, i, cmnd->device->lun,
+		ret = lpfc_scsi_tgt_reset(lpfc_cmd, vport, i,
+					  cmnd->device->lun,
 					  ndlp->rport->dd_data);
 		if (ret != SUCCESS) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-				"%d:0700 Bus Reset on target %d failed\n",
-				phba->brd_no, i);
+					"%d (%d):0700 Bus Reset on target %d "
+					"failed\n",
+					phba->brd_no, vport->vpi, i);
 			err_count++;
 			break;
 		}
@@ -1219,9 +1340,7 @@
 				    0, 0, 0, LPFC_CTX_HOST);
 	loopcnt = 0;
 	while(cnt) {
-		spin_unlock_irq(phba->host->host_lock);
 		schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
-		spin_lock_irq(phba->host->host_lock);
 
 		if (++loopcnt
 		    > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
@@ -1234,25 +1353,24 @@
 
 	if (cnt) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-		   "%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n",
-		   phba->brd_no, cnt, i);
+				"%d (%d):0715 Bus Reset I/O flush failure: "
+				"cnt x%x left x%x\n",
+				phba->brd_no, vport->vpi, cnt, i);
 		ret = FAILED;
 	}
 
-	lpfc_printf_log(phba,
-			KERN_ERR,
-			LOG_FCP,
-			"%d:0714 SCSI layer issued Bus Reset Data: x%x\n",
-			phba->brd_no, ret);
+	lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+			"%d (%d):0714 SCSI layer issued Bus Reset Data: x%x\n",
+			phba->brd_no, vport->vpi, ret);
 out:
-	spin_unlock_irq(shost->host_lock);
 	return ret;
 }
 
 static int
 lpfc_slave_alloc(struct scsi_device *sdev)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata;
+	struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_scsi_buf *scsi_buf = NULL;
 	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
 	uint32_t total = 0, i;
@@ -1273,27 +1391,35 @@
 	 */
 	total = phba->total_scsi_bufs;
 	num_to_alloc = phba->cfg_lun_queue_depth + 2;
-	if (total >= phba->cfg_hba_queue_depth) {
+
+	/* Allow some exchanges to be available always to complete discovery */
+	if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
-				"%d:0704 At limitation of %d preallocated "
-				"command buffers\n", phba->brd_no, total);
+				"%d (%d):0704 At limitation of %d "
+				"preallocated command buffers\n",
+				phba->brd_no, vport->vpi, total);
 		return 0;
-	} else if (total + num_to_alloc > phba->cfg_hba_queue_depth) {
+
+	/* Allow some exchanges to be available always to complete discovery */
+	} else if (total + num_to_alloc >
+		phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
-				"%d:0705 Allocation request of %d command "
-				"buffers will exceed max of %d.  Reducing "
-				"allocation request to %d.\n", phba->brd_no,
-				num_to_alloc, phba->cfg_hba_queue_depth,
+				"%d (%d):0705 Allocation request of %d "
+				"command buffers will exceed max of %d.  "
+				"Reducing allocation request to %d.\n",
+				phba->brd_no, vport->vpi, num_to_alloc,
+				phba->cfg_hba_queue_depth,
 				(phba->cfg_hba_queue_depth - total));
 		num_to_alloc = phba->cfg_hba_queue_depth - total;
 	}
 
 	for (i = 0; i < num_to_alloc; i++) {
-		scsi_buf = lpfc_new_scsi_buf(phba);
+		scsi_buf = lpfc_new_scsi_buf(vport);
 		if (!scsi_buf) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-					"%d:0706 Failed to allocate command "
-					"buffer\n", phba->brd_no);
+					"%d (%d):0706 Failed to allocate "
+					"command buffer\n",
+					phba->brd_no, vport->vpi);
 			break;
 		}
 
@@ -1308,8 +1434,9 @@
 static int
 lpfc_slave_configure(struct scsi_device *sdev)
 {
-	struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata;
-	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
+	struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+	struct fc_rport   *rport = starget_to_rport(sdev->sdev_target);
 
 	if (sdev->tagged_supported)
 		scsi_activate_tcq(sdev, phba->cfg_lun_queue_depth);
@@ -1340,6 +1467,7 @@
 	return;
 }
 
+
 struct scsi_host_template lpfc_template = {
 	.module			= THIS_MODULE,
 	.name			= LPFC_DRIVER_NAME,
@@ -1352,11 +1480,10 @@
 	.slave_configure	= lpfc_slave_configure,
 	.slave_destroy		= lpfc_slave_destroy,
 	.scan_finished		= lpfc_scan_finished,
-	.scan_start		= lpfc_scan_start,
 	.this_id		= -1,
 	.sg_tablesize		= LPFC_SG_SEG_CNT,
 	.cmd_per_lun		= LPFC_CMD_PER_LUN,
 	.use_clustering		= ENABLE_CLUSTERING,
-	.shost_attrs		= lpfc_host_attrs,
+	.shost_attrs		= lpfc_hba_attrs,
 	.max_sectors		= 0xFFFF,
 };
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index cdcd253..31787bb 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -110,7 +110,6 @@
 struct lpfc_scsi_buf {
 	struct list_head list;
 	struct scsi_cmnd *pCmd;
-	struct lpfc_hba *scsi_hba;
 	struct lpfc_rport_data *rdata;
 
 	uint32_t timeout;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index a1e7214..f4d5a6b 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -38,23 +38,25 @@
 #include "lpfc_crtn.h"
 #include "lpfc_logmsg.h"
 #include "lpfc_compat.h"
+#include "lpfc_debugfs.h"
 
 /*
  * Define macro to log: Mailbox command x%x cannot issue Data
  * This allows multiple uses of lpfc_msgBlk0311
  * w/o perturbing log msg utility.
  */
-#define LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag) \
+#define LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag) \
 			lpfc_printf_log(phba, \
 				KERN_INFO, \
 				LOG_MBOX | LOG_SLI, \
-				"%d:0311 Mailbox command x%x cannot issue " \
-				"Data: x%x x%x x%x\n", \
+				"%d (%d):0311 Mailbox command x%x cannot " \
+				"issue Data: x%x x%x x%x\n", \
 				phba->brd_no, \
-				mb->mbxCommand,		\
-				phba->hba_state,	\
+				pmbox->vport ? pmbox->vport->vpi : 0, \
+				pmbox->mb.mbxCommand,		\
+				phba->pport->port_state,	\
 				psli->sli_flag,	\
-				flag);
+				flag)
 
 
 /* There are only four IOCB completion types. */
@@ -65,8 +67,26 @@
 	LPFC_ABORT_IOCB
 } lpfc_iocb_type;
 
-struct lpfc_iocbq *
-lpfc_sli_get_iocbq(struct lpfc_hba * phba)
+		/* SLI-2/SLI-3 provide different sized iocbs.  Given a pointer
+		 * to the start of the ring, and the slot number of the
+		 * desired iocb entry, calc a pointer to that entry.
+		 */
+static inline IOCB_t *
+lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+{
+	return (IOCB_t *) (((char *) pring->cmdringaddr) +
+			   pring->cmdidx * phba->iocb_cmd_size);
+}
+
+static inline IOCB_t *
+lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+{
+	return (IOCB_t *) (((char *) pring->rspringaddr) +
+			   pring->rspidx * phba->iocb_rsp_size);
+}
+
+static struct lpfc_iocbq *
+__lpfc_sli_get_iocbq(struct lpfc_hba *phba)
 {
 	struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
 	struct lpfc_iocbq * iocbq = NULL;
@@ -75,10 +95,22 @@
 	return iocbq;
 }
 
-void
-lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
+struct lpfc_iocbq *
+lpfc_sli_get_iocbq(struct lpfc_hba *phba)
 {
-	size_t start_clean = (size_t)(&((struct lpfc_iocbq *)NULL)->iocb);
+	struct lpfc_iocbq * iocbq = NULL;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	iocbq = __lpfc_sli_get_iocbq(phba);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	return iocbq;
+}
+
+void
+__lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
+{
+	size_t start_clean = offsetof(struct lpfc_iocbq, iocb);
 
 	/*
 	 * Clean all volatile data fields, preserve iotag and node struct.
@@ -87,6 +119,19 @@
 	list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
 }
 
+void
+lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
+{
+	unsigned long iflags;
+
+	/*
+	 * Clean all volatile data fields, preserve iotag and node struct.
+	 */
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	__lpfc_sli_release_iocbq(phba, iocbq);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+}
+
 /*
  * Translate the iocb command to an iocb command type used to decide the final
  * disposition of each completed IOCB.
@@ -155,6 +200,9 @@
 	case CMD_RCV_ELS_REQ_CX:
 	case CMD_RCV_SEQUENCE64_CX:
 	case CMD_RCV_ELS_REQ64_CX:
+	case CMD_IOCB_RCV_SEQ64_CX:
+	case CMD_IOCB_RCV_ELS64_CX:
+	case CMD_IOCB_RCV_CONT64_CX:
 		type = LPFC_UNSOL_IOCB;
 		break;
 	default:
@@ -166,73 +214,77 @@
 }
 
 static int
-lpfc_sli_ring_map(struct lpfc_hba * phba, LPFC_MBOXQ_t *pmb)
+lpfc_sli_ring_map(struct lpfc_hba *phba)
 {
 	struct lpfc_sli *psli = &phba->sli;
-	MAILBOX_t *pmbox = &pmb->mb;
-	int i, rc;
+	LPFC_MBOXQ_t *pmb;
+	MAILBOX_t *pmbox;
+	int i, rc, ret = 0;
 
+	pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!pmb)
+		return -ENOMEM;
+	pmbox = &pmb->mb;
+	phba->link_state = LPFC_INIT_MBX_CMDS;
 	for (i = 0; i < psli->num_rings; i++) {
-		phba->hba_state = LPFC_INIT_MBX_CMDS;
 		lpfc_config_ring(phba, i, pmb);
 		rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
 		if (rc != MBX_SUCCESS) {
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_INIT,
-					"%d:0446 Adapter failed to init, "
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"%d:0446 Adapter failed to init (%d), "
 					"mbxCmd x%x CFG_RING, mbxStatus x%x, "
 					"ring %d\n",
-					phba->brd_no,
+					phba->brd_no, rc,
 					pmbox->mbxCommand,
 					pmbox->mbxStatus,
 					i);
-			phba->hba_state = LPFC_HBA_ERROR;
-			return -ENXIO;
+			phba->link_state = LPFC_HBA_ERROR;
+			ret = -ENXIO;
+			break;
 		}
 	}
-	return 0;
+	mempool_free(pmb, phba->mbox_mem_pool);
+	return ret;
 }
 
 static int
-lpfc_sli_ringtxcmpl_put(struct lpfc_hba * phba,
-			struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocb)
+lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+			struct lpfc_iocbq *piocb)
 {
 	list_add_tail(&piocb->list, &pring->txcmplq);
 	pring->txcmplq_cnt++;
-	if (unlikely(pring->ringno == LPFC_ELS_RING))
-		mod_timer(&phba->els_tmofunc,
-					jiffies + HZ * (phba->fc_ratov << 1));
+	if ((unlikely(pring->ringno == LPFC_ELS_RING)) &&
+	   (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
+	   (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
+		if (!piocb->vport)
+			BUG();
+		else
+			mod_timer(&piocb->vport->els_tmofunc,
+				  jiffies + HZ * (phba->fc_ratov << 1));
+	}
 
-	return (0);
+
+	return 0;
 }
 
 static struct lpfc_iocbq *
-lpfc_sli_ringtx_get(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
+lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
-	struct list_head *dlp;
 	struct lpfc_iocbq *cmd_iocb;
 
-	dlp = &pring->txq;
-	cmd_iocb = NULL;
-	list_remove_head((&pring->txq), cmd_iocb,
-			 struct lpfc_iocbq,
-			 list);
-	if (cmd_iocb) {
-		/* If the first ptr is not equal to the list header,
-		 * deque the IOCBQ_t and return it.
-		 */
+	list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list);
+	if (cmd_iocb != NULL)
 		pring->txq_cnt--;
-	}
-	return (cmd_iocb);
+	return cmd_iocb;
 }
 
 static IOCB_t *
 lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
-	struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+	struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+		&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+		&phba->slim2p->mbx.us.s2.port[pring->ringno];
 	uint32_t  max_cmd_idx = pring->numCiocb;
-	IOCB_t *iocb = NULL;
 
 	if ((pring->next_cmdidx == pring->cmdidx) &&
 	   (++pring->next_cmdidx >= max_cmd_idx))
@@ -249,15 +301,17 @@
 					phba->brd_no, pring->ringno,
 					pring->local_getidx, max_cmd_idx);
 
-			phba->hba_state = LPFC_HBA_ERROR;
+			phba->link_state = LPFC_HBA_ERROR;
 			/*
 			 * All error attention handlers are posted to
 			 * worker thread
 			 */
 			phba->work_ha |= HA_ERATT;
 			phba->work_hs = HS_FFER3;
+
+			/* hbalock should already be held */
 			if (phba->work_wait)
-				wake_up(phba->work_wait);
+				lpfc_worker_wake_up(phba);
 
 			return NULL;
 		}
@@ -266,39 +320,34 @@
 			return NULL;
 	}
 
-	iocb = IOCB_ENTRY(pring->cmdringaddr, pring->cmdidx);
-
-	return iocb;
+	return lpfc_cmd_iocb(phba, pring);
 }
 
 uint16_t
-lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
+lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
 {
-	struct lpfc_iocbq ** new_arr;
-	struct lpfc_iocbq ** old_arr;
+	struct lpfc_iocbq **new_arr;
+	struct lpfc_iocbq **old_arr;
 	size_t new_len;
 	struct lpfc_sli *psli = &phba->sli;
 	uint16_t iotag;
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	iotag = psli->last_iotag;
 	if(++iotag < psli->iocbq_lookup_len) {
 		psli->last_iotag = iotag;
 		psli->iocbq_lookup[iotag] = iocbq;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 		iocbq->iotag = iotag;
 		return iotag;
-	}
-	else if (psli->iocbq_lookup_len < (0xffff
+	} else if (psli->iocbq_lookup_len < (0xffff
 					   - LPFC_IOCBQ_LOOKUP_INCREMENT)) {
 		new_len = psli->iocbq_lookup_len + LPFC_IOCBQ_LOOKUP_INCREMENT;
-		spin_unlock_irq(phba->host->host_lock);
-		new_arr = kmalloc(new_len * sizeof (struct lpfc_iocbq *),
+		spin_unlock_irq(&phba->hbalock);
+		new_arr = kzalloc(new_len * sizeof (struct lpfc_iocbq *),
 				  GFP_KERNEL);
 		if (new_arr) {
-			memset((char *)new_arr, 0,
-			       new_len * sizeof (struct lpfc_iocbq *));
-			spin_lock_irq(phba->host->host_lock);
+			spin_lock_irq(&phba->hbalock);
 			old_arr = psli->iocbq_lookup;
 			if (new_len <= psli->iocbq_lookup_len) {
 				/* highly unprobable case */
@@ -307,11 +356,11 @@
 				if(++iotag < psli->iocbq_lookup_len) {
 					psli->last_iotag = iotag;
 					psli->iocbq_lookup[iotag] = iocbq;
-					spin_unlock_irq(phba->host->host_lock);
+					spin_unlock_irq(&phba->hbalock);
 					iocbq->iotag = iotag;
 					return iotag;
 				}
-				spin_unlock_irq(phba->host->host_lock);
+				spin_unlock_irq(&phba->hbalock);
 				return 0;
 			}
 			if (psli->iocbq_lookup)
@@ -322,13 +371,13 @@
 			psli->iocbq_lookup_len = new_len;
 			psli->last_iotag = iotag;
 			psli->iocbq_lookup[iotag] = iocbq;
-			spin_unlock_irq(phba->host->host_lock);
+			spin_unlock_irq(&phba->hbalock);
 			iocbq->iotag = iotag;
 			kfree(old_arr);
 			return iotag;
 		}
 	} else
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 
 	lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
 			"%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n",
@@ -349,7 +398,7 @@
 	/*
 	 * Issue iocb command to adapter
 	 */
-	lpfc_sli_pcimem_bcopy(&nextiocb->iocb, iocb, sizeof (IOCB_t));
+	lpfc_sli_pcimem_bcopy(&nextiocb->iocb, iocb, phba->iocb_cmd_size);
 	wmb();
 	pring->stats.iocb_cmd++;
 
@@ -361,20 +410,18 @@
 	if (nextiocb->iocb_cmpl)
 		lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb);
 	else
-		lpfc_sli_release_iocbq(phba, nextiocb);
+		__lpfc_sli_release_iocbq(phba, nextiocb);
 
 	/*
 	 * Let the HBA know what IOCB slot will be the next one the
 	 * driver will put a command into.
 	 */
 	pring->cmdidx = pring->next_cmdidx;
-	writel(pring->cmdidx, phba->MBslimaddr
-	       + (SLIMOFF + (pring->ringno * 2)) * 4);
+	writel(pring->cmdidx, &phba->host_gp[pring->ringno].cmdPutInx);
 }
 
 static void
-lpfc_sli_update_full_ring(struct lpfc_hba * phba,
-			  struct lpfc_sli_ring *pring)
+lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
 	int ringno = pring->ringno;
 
@@ -393,8 +440,7 @@
 }
 
 static void
-lpfc_sli_update_ring(struct lpfc_hba * phba,
-		     struct lpfc_sli_ring *pring)
+lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
 	int ringno = pring->ringno;
 
@@ -407,7 +453,7 @@
 }
 
 static void
-lpfc_sli_resume_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
+lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
 	IOCB_t *iocb;
 	struct lpfc_iocbq *nextiocb;
@@ -420,7 +466,7 @@
 	 *  (d) IOCB processing is not blocked by the outstanding mbox command.
 	 */
 	if (pring->txq_cnt &&
-	    (phba->hba_state > LPFC_LINK_DOWN) &&
+	    lpfc_is_link_up(phba) &&
 	    (pring->ringno != phba->sli.fcp_ring ||
 	     phba->sli.sli_flag & LPFC_PROCESS_LA) &&
 	    !(pring->flag & LPFC_STOP_IOCB_MBX)) {
@@ -440,11 +486,15 @@
 
 /* lpfc_sli_turn_on_ring is only called by lpfc_sli_handle_mb_event below */
 static void
-lpfc_sli_turn_on_ring(struct lpfc_hba * phba, int ringno)
+lpfc_sli_turn_on_ring(struct lpfc_hba *phba, int ringno)
 {
-	struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[ringno];
+	struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+		&phba->slim2p->mbx.us.s3_pgp.port[ringno] :
+		&phba->slim2p->mbx.us.s2.port[ringno];
+	unsigned long iflags;
 
 	/* If the ring is active, flag it */
+	spin_lock_irqsave(&phba->hbalock, iflags);
 	if (phba->sli.ring[ringno].cmdringaddr) {
 		if (phba->sli.ring[ringno].flag & LPFC_STOP_IOCB_MBX) {
 			phba->sli.ring[ringno].flag &= ~LPFC_STOP_IOCB_MBX;
@@ -453,11 +503,176 @@
 			 */
 			phba->sli.ring[ringno].local_getidx
 				= le32_to_cpu(pgp->cmdGetInx);
-			spin_lock_irq(phba->host->host_lock);
 			lpfc_sli_resume_iocb(phba, &phba->sli.ring[ringno]);
-			spin_unlock_irq(phba->host->host_lock);
 		}
 	}
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+}
+
+struct lpfc_hbq_entry *
+lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
+{
+	struct hbq_s *hbqp = &phba->hbqs[hbqno];
+
+	if (hbqp->next_hbqPutIdx == hbqp->hbqPutIdx &&
+	    ++hbqp->next_hbqPutIdx >= hbqp->entry_count)
+		hbqp->next_hbqPutIdx = 0;
+
+	if (unlikely(hbqp->local_hbqGetIdx == hbqp->next_hbqPutIdx)) {
+		uint32_t raw_index = phba->hbq_get[hbqno];
+		uint32_t getidx = le32_to_cpu(raw_index);
+
+		hbqp->local_hbqGetIdx = getidx;
+
+		if (unlikely(hbqp->local_hbqGetIdx >= hbqp->entry_count)) {
+			lpfc_printf_log(phba, KERN_ERR,
+					LOG_SLI | LOG_VPORT,
+					"%d:1802 HBQ %d: local_hbqGetIdx "
+					"%u is > than hbqp->entry_count %u\n",
+					phba->brd_no, hbqno,
+					hbqp->local_hbqGetIdx,
+					hbqp->entry_count);
+
+			phba->link_state = LPFC_HBA_ERROR;
+			return NULL;
+		}
+
+		if (hbqp->local_hbqGetIdx == hbqp->next_hbqPutIdx)
+			return NULL;
+	}
+
+	return (struct lpfc_hbq_entry *) phba->hbqslimp.virt + hbqp->hbqPutIdx;
+}
+
+void
+lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
+{
+	struct lpfc_dmabuf *dmabuf, *next_dmabuf;
+	struct hbq_dmabuf *hbq_buf;
+
+	/* Return all memory used by all HBQs */
+	list_for_each_entry_safe(dmabuf, next_dmabuf,
+				 &phba->hbq_buffer_list, list) {
+		hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf);
+		list_del(&hbq_buf->dbuf.list);
+		lpfc_hbq_free(phba, hbq_buf->dbuf.virt, hbq_buf->dbuf.phys);
+		kfree(hbq_buf);
+	}
+}
+
+static void
+lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
+			 struct hbq_dmabuf *hbq_buf)
+{
+	struct lpfc_hbq_entry *hbqe;
+	dma_addr_t physaddr = hbq_buf->dbuf.phys;
+
+	/* Get next HBQ entry slot to use */
+	hbqe = lpfc_sli_next_hbq_slot(phba, hbqno);
+	if (hbqe) {
+		struct hbq_s *hbqp = &phba->hbqs[hbqno];
+
+		hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
+		hbqe->bde.addrLow  = le32_to_cpu(putPaddrLow(physaddr));
+		hbqe->bde.tus.f.bdeSize = FCELSSIZE;
+		hbqe->bde.tus.f.bdeFlags = 0;
+		hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w);
+		hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag);
+				/* Sync SLIM */
+		hbqp->hbqPutIdx = hbqp->next_hbqPutIdx;
+		writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno);
+				/* flush */
+		readl(phba->hbq_put + hbqno);
+		list_add_tail(&hbq_buf->dbuf.list, &phba->hbq_buffer_list);
+	}
+}
+
+static struct lpfc_hbq_init lpfc_els_hbq = {
+	.rn = 1,
+	.entry_count = 200,
+	.mask_count = 0,
+	.profile = 0,
+	.ring_mask = 1 << LPFC_ELS_RING,
+	.buffer_count = 0,
+	.init_count = 20,
+	.add_count = 5,
+};
+
+static struct lpfc_hbq_init *lpfc_hbq_defs[] = {
+	&lpfc_els_hbq,
+};
+
+int
+lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
+{
+	uint32_t i, start, end;
+	struct hbq_dmabuf *hbq_buffer;
+
+	start = lpfc_hbq_defs[hbqno]->buffer_count;
+	end = count + lpfc_hbq_defs[hbqno]->buffer_count;
+	if (end > lpfc_hbq_defs[hbqno]->entry_count) {
+		end = lpfc_hbq_defs[hbqno]->entry_count;
+	}
+
+	/* Populate HBQ entries */
+	for (i = start; i < end; i++) {
+		hbq_buffer = kmalloc(sizeof(struct hbq_dmabuf),
+				     GFP_KERNEL);
+		if (!hbq_buffer)
+			return 1;
+		hbq_buffer->dbuf.virt = lpfc_hbq_alloc(phba, MEM_PRI,
+							&hbq_buffer->dbuf.phys);
+		if (hbq_buffer->dbuf.virt == NULL)
+			return 1;
+		hbq_buffer->tag = (i | (hbqno << 16));
+		lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer);
+		lpfc_hbq_defs[hbqno]->buffer_count++;
+	}
+	return 0;
+}
+
+int
+lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
+{
+	return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
+					 lpfc_hbq_defs[qno]->add_count));
+}
+
+int
+lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
+{
+	return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
+					 lpfc_hbq_defs[qno]->init_count));
+}
+
+struct hbq_dmabuf *
+lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
+{
+	struct lpfc_dmabuf *d_buf;
+	struct hbq_dmabuf *hbq_buf;
+
+	list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) {
+		hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
+		if ((hbq_buf->tag & 0xffff) == tag) {
+			return hbq_buf;
+		}
+	}
+	lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT,
+			"%d:1803 Bad hbq tag. Data: x%x x%x\n",
+			phba->brd_no, tag,
+			lpfc_hbq_defs[tag >> 16]->buffer_count);
+	return NULL;
+}
+
+void
+lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *sp)
+{
+	uint32_t hbqno;
+
+	if (sp) {
+		hbqno = sp->tag >> 16;
+		lpfc_sli_hbq_to_firmware(phba, hbqno, sp);
+	}
 }
 
 static int
@@ -511,32 +726,38 @@
 	case MBX_FLASH_WR_ULA:
 	case MBX_SET_DEBUG:
 	case MBX_LOAD_EXP_ROM:
+	case MBX_REG_VPI:
+	case MBX_UNREG_VPI:
+	case MBX_HEARTBEAT:
 		ret = mbxCommand;
 		break;
 	default:
 		ret = MBX_SHUTDOWN;
 		break;
 	}
-	return (ret);
+	return ret;
 }
 static void
-lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
+lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 {
 	wait_queue_head_t *pdone_q;
+	unsigned long drvr_flag;
 
 	/*
 	 * If pdone_q is empty, the driver thread gave up waiting and
 	 * continued running.
 	 */
 	pmboxq->mbox_flag |= LPFC_MBX_WAKE;
+	spin_lock_irqsave(&phba->hbalock, drvr_flag);
 	pdone_q = (wait_queue_head_t *) pmboxq->context1;
 	if (pdone_q)
 		wake_up_interruptible(pdone_q);
+	spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
 	return;
 }
 
 void
-lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
 	struct lpfc_dmabuf *mp;
 	uint16_t rpi;
@@ -553,79 +774,64 @@
 	 * If a REG_LOGIN succeeded  after node is destroyed or node
 	 * is in re-discovery driver need to cleanup the RPI.
 	 */
-	if (!(phba->fc_flag & FC_UNLOADING) &&
-		(pmb->mb.mbxCommand == MBX_REG_LOGIN64) &&
-		(!pmb->mb.mbxStatus)) {
+	if (!(phba->pport->load_flag & FC_UNLOADING) &&
+	    pmb->mb.mbxCommand == MBX_REG_LOGIN64 &&
+	    !pmb->mb.mbxStatus) {
 
 		rpi = pmb->mb.un.varWords[0];
-		lpfc_unreg_login(phba, rpi, pmb);
-		pmb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
+		lpfc_unreg_login(phba, pmb->mb.un.varRegLogin.vpi, rpi, pmb);
+		pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 		rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
 		if (rc != MBX_NOT_FINISHED)
 			return;
 	}
 
-	mempool_free( pmb, phba->mbox_mem_pool);
+	mempool_free(pmb, phba->mbox_mem_pool);
 	return;
 }
 
 int
-lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
+lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
 {
-	MAILBOX_t *mbox;
 	MAILBOX_t *pmbox;
 	LPFC_MBOXQ_t *pmb;
-	struct lpfc_sli *psli;
-	int i, rc;
-	uint32_t process_next;
-
-	psli = &phba->sli;
-	/* We should only get here if we are in SLI2 mode */
-	if (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE)) {
-		return (1);
-	}
+	int rc;
+	LIST_HEAD(cmplq);
 
 	phba->sli.slistat.mbox_event++;
 
+	/* Get all completed mailboxe buffers into the cmplq */
+	spin_lock_irq(&phba->hbalock);
+	list_splice_init(&phba->sli.mboxq_cmpl, &cmplq);
+	spin_unlock_irq(&phba->hbalock);
+
 	/* Get a Mailbox buffer to setup mailbox commands for callback */
-	if ((pmb = phba->sli.mbox_active)) {
+	do {
+		list_remove_head(&cmplq, pmb, LPFC_MBOXQ_t, list);
+		if (pmb == NULL)
+			break;
+
 		pmbox = &pmb->mb;
-		mbox = &phba->slim2p->mbx;
 
-		/* First check out the status word */
-		lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof (uint32_t));
-
-		/* Sanity check to ensure the host owns the mailbox */
-		if (pmbox->mbxOwner != OWN_HOST) {
-			/* Lets try for a while */
-			for (i = 0; i < 10240; i++) {
-				/* First copy command data */
-				lpfc_sli_pcimem_bcopy(mbox, pmbox,
-							sizeof (uint32_t));
-				if (pmbox->mbxOwner == OWN_HOST)
-					goto mbout;
+		if (pmbox->mbxCommand != MBX_HEARTBEAT) {
+			if (pmb->vport) {
+				lpfc_debugfs_disc_trc(pmb->vport,
+					LPFC_DISC_TRC_MBOX_VPORT,
+					"MBOX cmpl vport: cmd:x%x mb:x%x x%x",
+					(uint32_t)pmbox->mbxCommand,
+					pmbox->un.varWords[0],
+					pmbox->un.varWords[1]);
 			}
-			/* Stray Mailbox Interrupt, mbxCommand <cmd> mbxStatus
-			   <status> */
-			lpfc_printf_log(phba,
-					KERN_WARNING,
-					LOG_MBOX | LOG_SLI,
-					"%d:0304 Stray Mailbox Interrupt "
-					"mbxCommand x%x mbxStatus x%x\n",
-					phba->brd_no,
-					pmbox->mbxCommand,
-					pmbox->mbxStatus);
-
-			spin_lock_irq(phba->host->host_lock);
-			phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
-			spin_unlock_irq(phba->host->host_lock);
-			return (1);
+			else {
+				lpfc_debugfs_disc_trc(phba->pport,
+					LPFC_DISC_TRC_MBOX,
+					"MBOX cmpl:       cmd:x%x mb:x%x x%x",
+					(uint32_t)pmbox->mbxCommand,
+					pmbox->un.varWords[0],
+					pmbox->un.varWords[1]);
+			}
 		}
 
-	      mbout:
-		del_timer_sync(&phba->sli.mbox_tmo);
-		phba->work_hba_events &= ~WORKER_MBOX_TMO;
-
 		/*
 		 * It is a fatal error if unknown mbox command completion.
 		 */
@@ -633,51 +839,50 @@
 		    MBX_SHUTDOWN) {
 
 			/* Unknow mailbox command compl */
-			lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_MBOX | LOG_SLI,
-				"%d:0323 Unknown Mailbox command %x Cmpl\n",
-				phba->brd_no,
-				pmbox->mbxCommand);
-			phba->hba_state = LPFC_HBA_ERROR;
+			lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+					"%d (%d):0323 Unknown Mailbox command "
+					"%x Cmpl\n",
+					phba->brd_no,
+					pmb->vport ? pmb->vport->vpi : 0,
+					pmbox->mbxCommand);
+			phba->link_state = LPFC_HBA_ERROR;
 			phba->work_hs = HS_FFER3;
 			lpfc_handle_eratt(phba);
-			return (0);
+			continue;
 		}
 
-		phba->sli.mbox_active = NULL;
 		if (pmbox->mbxStatus) {
 			phba->sli.slistat.mbox_stat_err++;
 			if (pmbox->mbxStatus == MBXERR_NO_RESOURCES) {
 				/* Mbox cmd cmpl error - RETRYing */
-				lpfc_printf_log(phba,
-					KERN_INFO,
-					LOG_MBOX | LOG_SLI,
-					"%d:0305 Mbox cmd cmpl error - "
-					"RETRYing Data: x%x x%x x%x x%x\n",
-					phba->brd_no,
-					pmbox->mbxCommand,
-					pmbox->mbxStatus,
-					pmbox->un.varWords[0],
-					phba->hba_state);
+				lpfc_printf_log(phba, KERN_INFO,
+						LOG_MBOX | LOG_SLI,
+						"%d (%d):0305 Mbox cmd cmpl "
+						"error - RETRYing Data: x%x "
+						"x%x x%x x%x\n",
+						phba->brd_no,
+						pmb->vport ? pmb->vport->vpi :0,
+						pmbox->mbxCommand,
+						pmbox->mbxStatus,
+						pmbox->un.varWords[0],
+						pmb->vport->port_state);
 				pmbox->mbxStatus = 0;
 				pmbox->mbxOwner = OWN_HOST;
-				spin_lock_irq(phba->host->host_lock);
+				spin_lock_irq(&phba->hbalock);
 				phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-				spin_unlock_irq(phba->host->host_lock);
+				spin_unlock_irq(&phba->hbalock);
 				rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
 				if (rc == MBX_SUCCESS)
-					return (0);
+					continue;
 			}
 		}
 
 		/* Mailbox cmd <cmd> Cmpl <cmpl> */
-		lpfc_printf_log(phba,
-				KERN_INFO,
-				LOG_MBOX | LOG_SLI,
-				"%d:0307 Mailbox cmd x%x Cmpl x%p "
+		lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+				"%d (%d):0307 Mailbox cmd x%x Cmpl x%p "
 				"Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
 				phba->brd_no,
+				pmb->vport ? pmb->vport->vpi : 0,
 				pmbox->mbxCommand,
 				pmb->mbox_cmpl,
 				*((uint32_t *) pmbox),
@@ -690,39 +895,35 @@
 				pmbox->un.varWords[6],
 				pmbox->un.varWords[7]);
 
-		if (pmb->mbox_cmpl) {
-			lpfc_sli_pcimem_bcopy(mbox, pmbox, MAILBOX_CMD_SIZE);
+		if (pmb->mbox_cmpl)
 			pmb->mbox_cmpl(phba,pmb);
-		}
-	}
-
-
-	do {
-		process_next = 0;	/* by default don't loop */
-		spin_lock_irq(phba->host->host_lock);
-		phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-
-		/* Process next mailbox command if there is one */
-		if ((pmb = lpfc_mbox_get(phba))) {
-			spin_unlock_irq(phba->host->host_lock);
-			rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-			if (rc == MBX_NOT_FINISHED) {
-				pmb->mb.mbxStatus = MBX_NOT_FINISHED;
-				pmb->mbox_cmpl(phba,pmb);
-				process_next = 1;
-				continue;	/* loop back */
-			}
-		} else {
-			spin_unlock_irq(phba->host->host_lock);
-			/* Turn on IOCB processing */
-			for (i = 0; i < phba->sli.num_rings; i++)
-				lpfc_sli_turn_on_ring(phba, i);
-		}
-
-	} while (process_next);
-
-	return (0);
+	} while (1);
+	return 0;
 }
+
+static struct lpfc_dmabuf *
+lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
+{
+	struct hbq_dmabuf *hbq_entry, *new_hbq_entry;
+
+	hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
+	if (hbq_entry == NULL)
+		return NULL;
+	list_del(&hbq_entry->dbuf.list);
+	new_hbq_entry = kmalloc(sizeof(struct hbq_dmabuf), GFP_ATOMIC);
+	if (new_hbq_entry == NULL)
+		return &hbq_entry->dbuf;
+	new_hbq_entry->dbuf = hbq_entry->dbuf;
+	new_hbq_entry->tag = -1;
+	hbq_entry->dbuf.virt = lpfc_hbq_alloc(phba, 0, &hbq_entry->dbuf.phys);
+	if (hbq_entry->dbuf.virt == NULL) {
+		kfree(new_hbq_entry);
+		return &hbq_entry->dbuf;
+	}
+	lpfc_sli_free_hbq(phba, hbq_entry);
+	return &new_hbq_entry->dbuf;
+}
+
 static int
 lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 			    struct lpfc_iocbq *saveq)
@@ -735,7 +936,9 @@
 	match = 0;
 	irsp = &(saveq->iocb);
 	if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX)
-	    || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)) {
+	    || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)
+	    || (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)
+	    || (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX)) {
 		Rctl = FC_ELS_REQ;
 		Type = FC_ELS_DATA;
 	} else {
@@ -747,13 +950,24 @@
 
 		/* Firmware Workaround */
 		if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) &&
-			(irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX)) {
+			(irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX ||
+			 irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
 			Rctl = FC_ELS_REQ;
 			Type = FC_ELS_DATA;
 			w5p->hcsw.Rctl = Rctl;
 			w5p->hcsw.Type = Type;
 		}
 	}
+
+	if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+		if (irsp->ulpBdeCount != 0)
+			saveq->context2 = lpfc_sli_replace_hbqbuff(phba,
+						irsp->un.ulpWord[3]);
+		if (irsp->ulpBdeCount == 2)
+			saveq->context3 = lpfc_sli_replace_hbqbuff(phba,
+						irsp->un.ulpWord[15]);
+	}
+
 	/* unSolicited Responses */
 	if (pring->prt[0].profile) {
 		if (pring->prt[0].lpfc_sli_rcv_unsol_event)
@@ -781,23 +995,21 @@
 		/* Unexpected Rctl / Type received */
 		/* Ring <ringno> handler: unexpected
 		   Rctl <Rctl> Type <Type> received */
-		lpfc_printf_log(phba,
-				KERN_WARNING,
-				LOG_SLI,
+		lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
 				"%d:0313 Ring %d handler: unexpected Rctl x%x "
-				"Type x%x received \n",
+				"Type x%x received\n",
 				phba->brd_no,
 				pring->ringno,
 				Rctl,
 				Type);
 	}
-	return(1);
+	return 1;
 }
 
 static struct lpfc_iocbq *
-lpfc_sli_iocbq_lookup(struct lpfc_hba * phba,
-		      struct lpfc_sli_ring * pring,
-		      struct lpfc_iocbq * prspiocb)
+lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
+		      struct lpfc_sli_ring *pring,
+		      struct lpfc_iocbq *prspiocb)
 {
 	struct lpfc_iocbq *cmd_iocb = NULL;
 	uint16_t iotag;
@@ -806,7 +1018,7 @@
 
 	if (iotag != 0 && iotag <= phba->sli.last_iotag) {
 		cmd_iocb = phba->sli.iocbq_lookup[iotag];
-		list_del(&cmd_iocb->list);
+		list_del_init(&cmd_iocb->list);
 		pring->txcmplq_cnt--;
 		return cmd_iocb;
 	}
@@ -821,16 +1033,18 @@
 }
 
 static int
-lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
+lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 			  struct lpfc_iocbq *saveq)
 {
-	struct lpfc_iocbq * cmdiocbp;
+	struct lpfc_iocbq *cmdiocbp;
 	int rc = 1;
 	unsigned long iflag;
 
 	/* Based on the iotag field, get the cmd IOCB from the txcmplq */
-	spin_lock_irqsave(phba->host->host_lock, iflag);
+	spin_lock_irqsave(&phba->hbalock, iflag);
 	cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
+
 	if (cmdiocbp) {
 		if (cmdiocbp->iocb_cmpl) {
 			/*
@@ -846,17 +1060,8 @@
 					saveq->iocb.un.ulpWord[4] =
 						IOERR_SLI_ABORTED;
 				}
-				spin_unlock_irqrestore(phba->host->host_lock,
-						       iflag);
-				(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
-				spin_lock_irqsave(phba->host->host_lock, iflag);
 			}
-			else {
-				spin_unlock_irqrestore(phba->host->host_lock,
-						       iflag);
-				(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
-				spin_lock_irqsave(phba->host->host_lock, iflag);
-			}
+			(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
 		} else
 			lpfc_sli_release_iocbq(phba, cmdiocbp);
 	} else {
@@ -870,29 +1075,30 @@
 			 * Ring <ringno> handler: unexpected completion IoTag
 			 * <IoTag>
 			 */
-			lpfc_printf_log(phba,
-				KERN_WARNING,
-				LOG_SLI,
-				"%d:0322 Ring %d handler: unexpected "
-				"completion IoTag x%x Data: x%x x%x x%x x%x\n",
-				phba->brd_no,
-				pring->ringno,
-				saveq->iocb.ulpIoTag,
-				saveq->iocb.ulpStatus,
-				saveq->iocb.un.ulpWord[4],
-				saveq->iocb.ulpCommand,
-				saveq->iocb.ulpContext);
+			lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+					"%d (%d):0322 Ring %d handler: "
+					"unexpected completion IoTag x%x "
+					"Data: x%x x%x x%x x%x\n",
+					phba->brd_no,
+					cmdiocbp->vport->vpi,
+					pring->ringno,
+					saveq->iocb.ulpIoTag,
+					saveq->iocb.ulpStatus,
+					saveq->iocb.un.ulpWord[4],
+					saveq->iocb.ulpCommand,
+					saveq->iocb.ulpContext);
 		}
 	}
 
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
 	return rc;
 }
 
-static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
-					struct lpfc_sli_ring * pring)
+static void
+lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
-	struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+	struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+		&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+		&phba->slim2p->mbx.us.s2.port[pring->ringno];
 	/*
 	 * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
 	 * rsp ring <portRspMax>
@@ -904,7 +1110,7 @@
 			le32_to_cpu(pgp->rspPutInx),
 			pring->numRiocb);
 
-	phba->hba_state = LPFC_HBA_ERROR;
+	phba->link_state = LPFC_HBA_ERROR;
 
 	/*
 	 * All error attention handlers are posted to
@@ -912,16 +1118,18 @@
 	 */
 	phba->work_ha |= HA_ERATT;
 	phba->work_hs = HS_FFER3;
+
+	/* hbalock should already be held */
 	if (phba->work_wait)
-		wake_up(phba->work_wait);
+		lpfc_worker_wake_up(phba);
 
 	return;
 }
 
-void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
+void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
 {
-	struct lpfc_sli      * psli   = &phba->sli;
-	struct lpfc_sli_ring * pring = &psli->ring[LPFC_FCP_RING];
+	struct lpfc_sli      *psli  = &phba->sli;
+	struct lpfc_sli_ring *pring = &psli->ring[LPFC_FCP_RING];
 	IOCB_t *irsp = NULL;
 	IOCB_t *entry = NULL;
 	struct lpfc_iocbq *cmdiocbq = NULL;
@@ -931,13 +1139,15 @@
 	uint32_t portRspPut, portRspMax;
 	int type;
 	uint32_t rsp_cmpl = 0;
-	void __iomem *to_slim;
 	uint32_t ha_copy;
+	unsigned long iflags;
 
 	pring->stats.iocb_event++;
 
-	/* The driver assumes SLI-2 mode */
-	pgp =  &phba->slim2p->mbx.us.s2.port[pring->ringno];
+	pgp = (phba->sli_rev == 3) ?
+		&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+		&phba->slim2p->mbx.us.s2.port[pring->ringno];
+
 
 	/*
 	 * The next available response entry should never exceed the maximum
@@ -952,15 +1162,13 @@
 
 	rmb();
 	while (pring->rspidx != portRspPut) {
-
-		entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
-
+		entry = lpfc_resp_iocb(phba, pring);
 		if (++pring->rspidx >= portRspMax)
 			pring->rspidx = 0;
 
 		lpfc_sli_pcimem_bcopy((uint32_t *) entry,
 				      (uint32_t *) &rspiocbq.iocb,
-				      sizeof (IOCB_t));
+				      phba->iocb_rsp_size);
 		irsp = &rspiocbq.iocb;
 		type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK);
 		pring->stats.iocb_rsp++;
@@ -998,8 +1206,10 @@
 				break;
 			}
 
+			spin_lock_irqsave(&phba->hbalock, iflags);
 			cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
 							 &rspiocbq);
+			spin_unlock_irqrestore(&phba->hbalock, iflags);
 			if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
 				(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
 						      &rspiocbq);
@@ -1033,9 +1243,7 @@
 		 * been updated, sync the pgp->rspPutInx and fetch the new port
 		 * response put pointer.
 		 */
-		to_slim = phba->MBslimaddr +
-			(SLIMOFF + (pring->ringno * 2) + 1) * 4;
-		writeb(pring->rspidx, to_slim);
+		writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
 
 		if (pring->rspidx == portRspPut)
 			portRspPut = le32_to_cpu(pgp->rspPutInx);
@@ -1045,13 +1253,16 @@
 	ha_copy >>= (LPFC_FCP_RING * 4);
 
 	if ((rsp_cmpl > 0) && (ha_copy & HA_R0RE_REQ)) {
+		spin_lock_irqsave(&phba->hbalock, iflags);
 		pring->stats.iocb_rsp_full++;
 		status = ((CA_R0ATT | CA_R0RE_RSP) << (LPFC_FCP_RING * 4));
 		writel(status, phba->CAregaddr);
 		readl(phba->CAregaddr);
+		spin_unlock_irqrestore(&phba->hbalock, iflags);
 	}
 	if ((ha_copy & HA_R0CE_RSP) &&
 	    (pring->flag & LPFC_CALL_RING_AVAILABLE)) {
+		spin_lock_irqsave(&phba->hbalock, iflags);
 		pring->flag &= ~LPFC_CALL_RING_AVAILABLE;
 		pring->stats.iocb_cmd_empty++;
 
@@ -1062,6 +1273,7 @@
 		if ((pring->lpfc_sli_cmd_available))
 			(pring->lpfc_sli_cmd_available) (phba, pring);
 
+		spin_unlock_irqrestore(&phba->hbalock, iflags);
 	}
 
 	return;
@@ -1072,10 +1284,12 @@
  * to check it explicitly.
  */
 static int
-lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
-				struct lpfc_sli_ring * pring, uint32_t mask)
+lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
+				struct lpfc_sli_ring *pring, uint32_t mask)
 {
- 	struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+	struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+		&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+		&phba->slim2p->mbx.us.s2.port[pring->ringno];
 	IOCB_t *irsp = NULL;
 	IOCB_t *entry = NULL;
 	struct lpfc_iocbq *cmdiocbq = NULL;
@@ -1086,9 +1300,8 @@
 	lpfc_iocb_type type;
 	unsigned long iflag;
 	uint32_t rsp_cmpl = 0;
-	void __iomem  *to_slim;
 
-	spin_lock_irqsave(phba->host->host_lock, iflag);
+	spin_lock_irqsave(&phba->hbalock, iflag);
 	pring->stats.iocb_event++;
 
 	/*
@@ -1099,7 +1312,7 @@
 	portRspPut = le32_to_cpu(pgp->rspPutInx);
 	if (unlikely(portRspPut >= portRspMax)) {
 		lpfc_sli_rsp_pointers_error(phba, pring);
-		spin_unlock_irqrestore(phba->host->host_lock, iflag);
+		spin_unlock_irqrestore(&phba->hbalock, iflag);
 		return 1;
 	}
 
@@ -1110,14 +1323,15 @@
 		 * structure.  The copy involves a byte-swap since the
 		 * network byte order and pci byte orders are different.
 		 */
-		entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
+		entry = lpfc_resp_iocb(phba, pring);
+		phba->last_completion_time = jiffies;
 
 		if (++pring->rspidx >= portRspMax)
 			pring->rspidx = 0;
 
 		lpfc_sli_pcimem_bcopy((uint32_t *) entry,
 				      (uint32_t *) &rspiocbq.iocb,
-				      sizeof (IOCB_t));
+				      phba->iocb_rsp_size);
 		INIT_LIST_HEAD(&(rspiocbq.list));
 		irsp = &rspiocbq.iocb;
 
@@ -1126,16 +1340,30 @@
 		rsp_cmpl++;
 
 		if (unlikely(irsp->ulpStatus)) {
+			/*
+			 * If resource errors reported from HBA, reduce
+			 * queuedepths of the SCSI device.
+			 */
+			if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+				(irsp->un.ulpWord[4] == IOERR_NO_RESOURCES)) {
+				spin_unlock_irqrestore(&phba->hbalock, iflag);
+				lpfc_adjust_queue_depth(phba);
+				spin_lock_irqsave(&phba->hbalock, iflag);
+			}
+
 			/* Rsp ring <ringno> error: IOCB */
 			lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
-				"%d:0336 Rsp Ring %d error: IOCB Data: "
-				"x%x x%x x%x x%x x%x x%x x%x x%x\n",
-				phba->brd_no, pring->ringno,
-				irsp->un.ulpWord[0], irsp->un.ulpWord[1],
-				irsp->un.ulpWord[2], irsp->un.ulpWord[3],
-				irsp->un.ulpWord[4], irsp->un.ulpWord[5],
-				*(((uint32_t *) irsp) + 6),
-				*(((uint32_t *) irsp) + 7));
+					"%d:0336 Rsp Ring %d error: IOCB Data: "
+					"x%x x%x x%x x%x x%x x%x x%x x%x\n",
+					phba->brd_no, pring->ringno,
+					irsp->un.ulpWord[0],
+					irsp->un.ulpWord[1],
+					irsp->un.ulpWord[2],
+					irsp->un.ulpWord[3],
+					irsp->un.ulpWord[4],
+					irsp->un.ulpWord[5],
+					*(((uint32_t *) irsp) + 6),
+					*(((uint32_t *) irsp) + 7));
 		}
 
 		switch (type) {
@@ -1149,7 +1377,8 @@
 				lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
 						"%d:0333 IOCB cmd 0x%x"
 						" processed. Skipping"
-						" completion\n", phba->brd_no,
+						" completion\n",
+						phba->brd_no,
 						irsp->ulpCommand);
 				break;
 			}
@@ -1161,19 +1390,19 @@
 					(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
 							      &rspiocbq);
 				} else {
-					spin_unlock_irqrestore(
-						phba->host->host_lock, iflag);
+					spin_unlock_irqrestore(&phba->hbalock,
+							       iflag);
 					(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
 							      &rspiocbq);
-					spin_lock_irqsave(phba->host->host_lock,
+					spin_lock_irqsave(&phba->hbalock,
 							  iflag);
 				}
 			}
 			break;
 		case LPFC_UNSOL_IOCB:
-			spin_unlock_irqrestore(phba->host->host_lock, iflag);
+			spin_unlock_irqrestore(&phba->hbalock, iflag);
 			lpfc_sli_process_unsol_iocb(phba, pring, &rspiocbq);
-			spin_lock_irqsave(phba->host->host_lock, iflag);
+			spin_lock_irqsave(&phba->hbalock, iflag);
 			break;
 		default:
 			if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
@@ -1186,11 +1415,13 @@
 			} else {
 				/* Unknown IOCB command */
 				lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-					"%d:0334 Unknown IOCB command "
-					"Data: x%x, x%x x%x x%x x%x\n",
-					phba->brd_no, type, irsp->ulpCommand,
-					irsp->ulpStatus, irsp->ulpIoTag,
-					irsp->ulpContext);
+						"%d:0334 Unknown IOCB command "
+						"Data: x%x, x%x x%x x%x x%x\n",
+						phba->brd_no, type,
+						irsp->ulpCommand,
+						irsp->ulpStatus,
+						irsp->ulpIoTag,
+						irsp->ulpContext);
 			}
 			break;
 		}
@@ -1201,9 +1432,7 @@
 		 * been updated, sync the pgp->rspPutInx and fetch the new port
 		 * response put pointer.
 		 */
-		to_slim = phba->MBslimaddr +
-			(SLIMOFF + (pring->ringno * 2) + 1) * 4;
-		writel(pring->rspidx, to_slim);
+		writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
 
 		if (pring->rspidx == portRspPut)
 			portRspPut = le32_to_cpu(pgp->rspPutInx);
@@ -1228,31 +1457,31 @@
 
 	}
 
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
 	return rc;
 }
 
-
 int
-lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
-			   struct lpfc_sli_ring * pring, uint32_t mask)
+lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
+				struct lpfc_sli_ring *pring, uint32_t mask)
 {
+	struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+		&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+		&phba->slim2p->mbx.us.s2.port[pring->ringno];
 	IOCB_t *entry;
 	IOCB_t *irsp = NULL;
 	struct lpfc_iocbq *rspiocbp = NULL;
 	struct lpfc_iocbq *next_iocb;
 	struct lpfc_iocbq *cmdiocbp;
 	struct lpfc_iocbq *saveq;
-	struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
 	uint8_t iocb_cmd_type;
 	lpfc_iocb_type type;
 	uint32_t status, free_saveq;
 	uint32_t portRspPut, portRspMax;
 	int rc = 1;
 	unsigned long iflag;
-	void __iomem  *to_slim;
 
-	spin_lock_irqsave(phba->host->host_lock, iflag);
+	spin_lock_irqsave(&phba->hbalock, iflag);
 	pring->stats.iocb_event++;
 
 	/*
@@ -1266,16 +1495,14 @@
 		 * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
 		 * rsp ring <portRspMax>
 		 */
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_SLI,
+		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
 				"%d:0303 Ring %d handler: portRspPut %d "
 				"is bigger then rsp ring %d\n",
-				phba->brd_no,
-				pring->ringno, portRspPut, portRspMax);
+				phba->brd_no, pring->ringno, portRspPut,
+				portRspMax);
 
-		phba->hba_state = LPFC_HBA_ERROR;
-		spin_unlock_irqrestore(phba->host->host_lock, iflag);
+		phba->link_state = LPFC_HBA_ERROR;
+		spin_unlock_irqrestore(&phba->hbalock, iflag);
 
 		phba->work_hs = HS_FFER3;
 		lpfc_handle_eratt(phba);
@@ -1298,23 +1525,24 @@
 		 * the ulpLe field is set, the entire Command has been
 		 * received.
 		 */
-		entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
-		rspiocbp = lpfc_sli_get_iocbq(phba);
+		entry = lpfc_resp_iocb(phba, pring);
+
+		phba->last_completion_time = jiffies;
+		rspiocbp = __lpfc_sli_get_iocbq(phba);
 		if (rspiocbp == NULL) {
 			printk(KERN_ERR "%s: out of buffers! Failing "
 			       "completion.\n", __FUNCTION__);
 			break;
 		}
 
-		lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb, sizeof (IOCB_t));
+		lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb,
+				      phba->iocb_rsp_size);
 		irsp = &rspiocbp->iocb;
 
 		if (++pring->rspidx >= portRspMax)
 			pring->rspidx = 0;
 
-		to_slim = phba->MBslimaddr + (SLIMOFF + (pring->ringno * 2)
-					      + 1) * 4;
-		writel(pring->rspidx, to_slim);
+		writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
 
 		if (list_empty(&(pring->iocb_continueq))) {
 			list_add(&rspiocbp->list, &(pring->iocb_continueq));
@@ -1338,23 +1566,44 @@
 
 			pring->stats.iocb_rsp++;
 
+			/*
+			 * If resource errors reported from HBA, reduce
+			 * queuedepths of the SCSI device.
+			 */
+			if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+			     (irsp->un.ulpWord[4] == IOERR_NO_RESOURCES)) {
+				spin_unlock_irqrestore(&phba->hbalock, iflag);
+				lpfc_adjust_queue_depth(phba);
+				spin_lock_irqsave(&phba->hbalock, iflag);
+			}
+
 			if (irsp->ulpStatus) {
 				/* Rsp ring <ringno> error: IOCB */
-				lpfc_printf_log(phba,
-					KERN_WARNING,
-					LOG_SLI,
-					"%d:0328 Rsp Ring %d error: IOCB Data: "
-					"x%x x%x x%x x%x x%x x%x x%x x%x\n",
-					phba->brd_no,
-					pring->ringno,
-					irsp->un.ulpWord[0],
-					irsp->un.ulpWord[1],
-					irsp->un.ulpWord[2],
-					irsp->un.ulpWord[3],
-					irsp->un.ulpWord[4],
-					irsp->un.ulpWord[5],
-					*(((uint32_t *) irsp) + 6),
-					*(((uint32_t *) irsp) + 7));
+				lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+						"%d:0328 Rsp Ring %d error: "
+						"IOCB Data: "
+						"x%x x%x x%x x%x "
+						"x%x x%x x%x x%x "
+						"x%x x%x x%x x%x "
+						"x%x x%x x%x x%x\n",
+						phba->brd_no,
+						pring->ringno,
+						irsp->un.ulpWord[0],
+						irsp->un.ulpWord[1],
+						irsp->un.ulpWord[2],
+						irsp->un.ulpWord[3],
+						irsp->un.ulpWord[4],
+						irsp->un.ulpWord[5],
+						*(((uint32_t *) irsp) + 6),
+						*(((uint32_t *) irsp) + 7),
+						*(((uint32_t *) irsp) + 8),
+						*(((uint32_t *) irsp) + 9),
+						*(((uint32_t *) irsp) + 10),
+						*(((uint32_t *) irsp) + 11),
+						*(((uint32_t *) irsp) + 12),
+						*(((uint32_t *) irsp) + 13),
+						*(((uint32_t *) irsp) + 14),
+						*(((uint32_t *) irsp) + 15));
 			}
 
 			/*
@@ -1366,17 +1615,17 @@
 			iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK;
 			type = lpfc_sli_iocb_cmd_type(iocb_cmd_type);
 			if (type == LPFC_SOL_IOCB) {
-				spin_unlock_irqrestore(phba->host->host_lock,
+				spin_unlock_irqrestore(&phba->hbalock,
 						       iflag);
 				rc = lpfc_sli_process_sol_iocb(phba, pring,
-					saveq);
-				spin_lock_irqsave(phba->host->host_lock, iflag);
+							       saveq);
+				spin_lock_irqsave(&phba->hbalock, iflag);
 			} else if (type == LPFC_UNSOL_IOCB) {
-				spin_unlock_irqrestore(phba->host->host_lock,
+				spin_unlock_irqrestore(&phba->hbalock,
 						       iflag);
 				rc = lpfc_sli_process_unsol_iocb(phba, pring,
-					saveq);
-				spin_lock_irqsave(phba->host->host_lock, iflag);
+								 saveq);
+				spin_lock_irqsave(&phba->hbalock, iflag);
 			} else if (type == LPFC_ABORT_IOCB) {
 				if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) &&
 				    ((cmdiocbp =
@@ -1386,15 +1635,15 @@
 					   routine */
 					if (cmdiocbp->iocb_cmpl) {
 						spin_unlock_irqrestore(
-						       phba->host->host_lock,
+						       &phba->hbalock,
 						       iflag);
 						(cmdiocbp->iocb_cmpl) (phba,
 							     cmdiocbp, saveq);
 						spin_lock_irqsave(
-							  phba->host->host_lock,
+							  &phba->hbalock,
 							  iflag);
 					} else
-						lpfc_sli_release_iocbq(phba,
+						__lpfc_sli_release_iocbq(phba,
 								      cmdiocbp);
 				}
 			} else if (type == LPFC_UNKNOWN_IOCB) {
@@ -1411,32 +1660,28 @@
 						 phba->brd_no, adaptermsg);
 				} else {
 					/* Unknown IOCB command */
-					lpfc_printf_log(phba,
-						KERN_ERR,
-						LOG_SLI,
-						"%d:0335 Unknown IOCB command "
-						"Data: x%x x%x x%x x%x\n",
-						phba->brd_no,
-						irsp->ulpCommand,
-						irsp->ulpStatus,
-						irsp->ulpIoTag,
-						irsp->ulpContext);
+					lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+							"%d:0335 Unknown IOCB "
+							"command Data: x%x "
+							"x%x x%x x%x\n",
+							phba->brd_no,
+							irsp->ulpCommand,
+							irsp->ulpStatus,
+							irsp->ulpIoTag,
+							irsp->ulpContext);
 				}
 			}
 
 			if (free_saveq) {
-				if (!list_empty(&saveq->list)) {
-					list_for_each_entry_safe(rspiocbp,
-								 next_iocb,
-								 &saveq->list,
-								 list) {
-						list_del(&rspiocbp->list);
-						lpfc_sli_release_iocbq(phba,
-								     rspiocbp);
-					}
+				list_for_each_entry_safe(rspiocbp, next_iocb,
+							 &saveq->list, list) {
+					list_del(&rspiocbp->list);
+					__lpfc_sli_release_iocbq(phba,
+								 rspiocbp);
 				}
-				lpfc_sli_release_iocbq(phba, saveq);
+				__lpfc_sli_release_iocbq(phba, saveq);
 			}
+			rspiocbp = NULL;
 		}
 
 		/*
@@ -1449,7 +1694,7 @@
 		}
 	} /* while (pring->rspidx != portRspPut) */
 
-	if ((rspiocbp != 0) && (mask & HA_R0RE_REQ)) {
+	if ((rspiocbp != NULL) && (mask & HA_R0RE_REQ)) {
 		/* At least one response entry has been freed */
 		pring->stats.iocb_rsp_full++;
 		/* SET RxRE_RSP in Chip Att register */
@@ -1470,24 +1715,25 @@
 
 	}
 
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
 	return rc;
 }
 
-int
+void
 lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
 	LIST_HEAD(completions);
 	struct lpfc_iocbq *iocb, *next_iocb;
 	IOCB_t *cmd = NULL;
-	int errcnt;
 
-	errcnt = 0;
+	if (pring->ringno == LPFC_ELS_RING) {
+		lpfc_fabric_abort_hba(phba);
+	}
 
 	/* Error everything on txq and txcmplq
 	 * First do the txq.
 	 */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	list_splice_init(&pring->txq, &completions);
 	pring->txq_cnt = 0;
 
@@ -1495,26 +1741,25 @@
 	list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
 		lpfc_sli_issue_abort_iotag(phba, pring, iocb);
 
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	while (!list_empty(&completions)) {
 		iocb = list_get_first(&completions, struct lpfc_iocbq, list);
 		cmd = &iocb->iocb;
-		list_del(&iocb->list);
+		list_del_init(&iocb->list);
 
-		if (iocb->iocb_cmpl) {
+		if (!iocb->iocb_cmpl)
+			lpfc_sli_release_iocbq(phba, iocb);
+		else {
 			cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
 			cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
 			(iocb->iocb_cmpl) (phba, iocb, iocb);
-		} else
-			lpfc_sli_release_iocbq(phba, iocb);
+		}
 	}
-
-	return errcnt;
 }
 
 int
-lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
+lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
 {
 	uint32_t status;
 	int i = 0;
@@ -1541,7 +1786,8 @@
 			msleep(2500);
 
 		if (i == 15) {
-			phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
+				/* Do post */
+			phba->pport->port_state = LPFC_VPORT_UNKNOWN;
 			lpfc_sli_brdrestart(phba);
 		}
 		/* Read the HBA Host Status Register */
@@ -1550,7 +1796,7 @@
 
 	/* Check to see if any errors occurred during init */
 	if ((status & HS_FFERM) || (i >= 20)) {
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		retval = 1;
 	}
 
@@ -1559,7 +1805,7 @@
 
 #define BARRIER_TEST_PATTERN (0xdeadbeef)
 
-void lpfc_reset_barrier(struct lpfc_hba * phba)
+void lpfc_reset_barrier(struct lpfc_hba *phba)
 {
 	uint32_t __iomem *resp_buf;
 	uint32_t __iomem *mbox_buf;
@@ -1584,12 +1830,12 @@
 	hc_copy = readl(phba->HCregaddr);
 	writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
-	phba->fc_flag |= FC_IGNORE_ERATT;
+	phba->link_flag |= LS_IGNORE_ERATT;
 
 	if (readl(phba->HAregaddr) & HA_ERATT) {
 		/* Clear Chip error bit */
 		writel(HA_ERATT, phba->HAregaddr);
-		phba->stopped = 1;
+		phba->pport->stopped = 1;
 	}
 
 	mbox = 0;
@@ -1606,7 +1852,7 @@
 
 	if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
 		if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE ||
-		    phba->stopped)
+		    phba->pport->stopped)
 			goto restore_hc;
 		else
 			goto clear_errat;
@@ -1623,17 +1869,17 @@
 
 	if (readl(phba->HAregaddr) & HA_ERATT) {
 		writel(HA_ERATT, phba->HAregaddr);
-		phba->stopped = 1;
+		phba->pport->stopped = 1;
 	}
 
 restore_hc:
-	phba->fc_flag &= ~FC_IGNORE_ERATT;
+	phba->link_flag &= ~LS_IGNORE_ERATT;
 	writel(hc_copy, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
 }
 
 int
-lpfc_sli_brdkill(struct lpfc_hba * phba)
+lpfc_sli_brdkill(struct lpfc_hba *phba)
 {
 	struct lpfc_sli *psli;
 	LPFC_MBOXQ_t *pmb;
@@ -1645,26 +1891,22 @@
 	psli = &phba->sli;
 
 	/* Kill HBA */
-	lpfc_printf_log(phba,
-		KERN_INFO,
-		LOG_SLI,
-		"%d:0329 Kill HBA Data: x%x x%x\n",
-		phba->brd_no,
-		phba->hba_state,
-		psli->sli_flag);
+	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+			"%d:0329 Kill HBA Data: x%x x%x\n",
+			phba->brd_no, phba->pport->port_state, psli->sli_flag);
 
 	if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
 						  GFP_KERNEL)) == 0)
 		return 1;
 
 	/* Disable the error attention */
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	status = readl(phba->HCregaddr);
 	status &= ~HC_ERINT_ENA;
 	writel(status, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
-	phba->fc_flag |= FC_IGNORE_ERATT;
-	spin_unlock_irq(phba->host->host_lock);
+	phba->link_flag |= LS_IGNORE_ERATT;
+	spin_unlock_irq(&phba->hbalock);
 
 	lpfc_kill_board(phba, pmb);
 	pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
@@ -1673,9 +1915,9 @@
 	if (retval != MBX_SUCCESS) {
 		if (retval != MBX_BUSY)
 			mempool_free(pmb, phba->mbox_mem_pool);
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag &= ~FC_IGNORE_ERATT;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_lock_irq(&phba->hbalock);
+		phba->link_flag &= ~LS_IGNORE_ERATT;
+		spin_unlock_irq(&phba->hbalock);
 		return 1;
 	}
 
@@ -1698,22 +1940,22 @@
 	del_timer_sync(&psli->mbox_tmo);
 	if (ha_copy & HA_ERATT) {
 		writel(HA_ERATT, phba->HAregaddr);
-		phba->stopped = 1;
+		phba->pport->stopped = 1;
 	}
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-	phba->fc_flag &= ~FC_IGNORE_ERATT;
-	spin_unlock_irq(phba->host->host_lock);
+	phba->link_flag &= ~LS_IGNORE_ERATT;
+	spin_unlock_irq(&phba->hbalock);
 
 	psli->mbox_active = NULL;
 	lpfc_hba_down_post(phba);
-	phba->hba_state = LPFC_HBA_ERROR;
+	phba->link_state = LPFC_HBA_ERROR;
 
-	return (ha_copy & HA_ERATT ? 0 : 1);
+	return ha_copy & HA_ERATT ? 0 : 1;
 }
 
 int
-lpfc_sli_brdreset(struct lpfc_hba * phba)
+lpfc_sli_brdreset(struct lpfc_hba *phba)
 {
 	struct lpfc_sli *psli;
 	struct lpfc_sli_ring *pring;
@@ -1725,12 +1967,12 @@
 	/* Reset HBA */
 	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
 			"%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no,
-			phba->hba_state, psli->sli_flag);
+			phba->pport->port_state, psli->sli_flag);
 
 	/* perform board reset */
 	phba->fc_eventTag = 0;
-	phba->fc_myDID = 0;
-	phba->fc_prevDID = 0;
+	phba->pport->fc_myDID = 0;
+	phba->pport->fc_prevDID = 0;
 
 	/* Turn off parity checking and serr during the physical reset */
 	pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
@@ -1760,12 +2002,12 @@
 		pring->missbufcnt = 0;
 	}
 
-	phba->hba_state = LPFC_WARM_START;
+	phba->link_state = LPFC_WARM_START;
 	return 0;
 }
 
 int
-lpfc_sli_brdrestart(struct lpfc_hba * phba)
+lpfc_sli_brdrestart(struct lpfc_hba *phba)
 {
 	MAILBOX_t *mb;
 	struct lpfc_sli *psli;
@@ -1773,14 +2015,14 @@
 	volatile uint32_t word0;
 	void __iomem *to_slim;
 
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 
 	psli = &phba->sli;
 
 	/* Restart HBA */
 	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
 			"%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no,
-			phba->hba_state, psli->sli_flag);
+			phba->pport->port_state, psli->sli_flag);
 
 	word0 = 0;
 	mb = (MAILBOX_t *) &word0;
@@ -1794,7 +2036,7 @@
 	readl(to_slim); /* flush */
 
 	/* Only skip post after fc_ffinit is completed */
-	if (phba->hba_state) {
+	if (phba->pport->port_state) {
 		skip_post = 1;
 		word0 = 1;	/* This is really setting up word1 */
 	} else {
@@ -1806,10 +2048,10 @@
 	readl(to_slim); /* flush */
 
 	lpfc_sli_brdreset(phba);
-	phba->stopped = 0;
-	phba->hba_state = LPFC_INIT_START;
+	phba->pport->stopped = 0;
+	phba->link_state = LPFC_INIT_START;
 
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
 	psli->stats_start = get_seconds();
@@ -1843,14 +2085,11 @@
 		if (i++ >= 20) {
 			/* Adapter failed to init, timeout, status reg
 			   <status> */
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_INIT,
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 					"%d:0436 Adapter failed to init, "
 					"timeout, status reg x%x\n",
-					phba->brd_no,
-					status);
-			phba->hba_state = LPFC_HBA_ERROR;
+					phba->brd_no, status);
+			phba->link_state = LPFC_HBA_ERROR;
 			return -ETIMEDOUT;
 		}
 
@@ -1859,14 +2098,12 @@
 			/* ERROR: During chipset initialization */
 			/* Adapter failed to init, chipset, status reg
 			   <status> */
-			lpfc_printf_log(phba,
-					KERN_ERR,
-					LOG_INIT,
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 					"%d:0437 Adapter failed to init, "
 					"chipset, status reg x%x\n",
 					phba->brd_no,
 					status);
-			phba->hba_state = LPFC_HBA_ERROR;
+			phba->link_state = LPFC_HBA_ERROR;
 			return -EIO;
 		}
 
@@ -1879,7 +2116,8 @@
 		}
 
 		if (i == 15) {
-			phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
+				/* Do post */
+			phba->pport->port_state = LPFC_VPORT_UNKNOWN;
 			lpfc_sli_brdrestart(phba);
 		}
 		/* Read the HBA Host Status Register */
@@ -1890,14 +2128,12 @@
 	if (status & HS_FFERM) {
 		/* ERROR: During chipset initialization */
 		/* Adapter failed to init, chipset, status reg <status> */
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_INIT,
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"%d:0438 Adapter failed to init, chipset, "
 				"status reg x%x\n",
 				phba->brd_no,
 				status);
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		return -EIO;
 	}
 
@@ -1911,80 +2147,253 @@
 	return 0;
 }
 
+static int
+lpfc_sli_hbq_count(void)
+{
+	return ARRAY_SIZE(lpfc_hbq_defs);
+}
+
+static int
+lpfc_sli_hbq_entry_count(void)
+{
+	int  hbq_count = lpfc_sli_hbq_count();
+	int  count = 0;
+	int  i;
+
+	for (i = 0; i < hbq_count; ++i)
+		count += lpfc_hbq_defs[i]->entry_count;
+	return count;
+}
+
 int
-lpfc_sli_hba_setup(struct lpfc_hba * phba)
+lpfc_sli_hbq_size(void)
+{
+	return lpfc_sli_hbq_entry_count() * sizeof(struct lpfc_hbq_entry);
+}
+
+static int
+lpfc_sli_hbq_setup(struct lpfc_hba *phba)
+{
+	int  hbq_count = lpfc_sli_hbq_count();
+	LPFC_MBOXQ_t *pmb;
+	MAILBOX_t *pmbox;
+	uint32_t hbqno;
+	uint32_t hbq_entry_index;
+
+				/* Get a Mailbox buffer to setup mailbox
+				 * commands for HBA initialization
+				 */
+	pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+
+	if (!pmb)
+		return -ENOMEM;
+
+	pmbox = &pmb->mb;
+
+	/* Initialize the struct lpfc_sli_hbq structure for each hbq */
+	phba->link_state = LPFC_INIT_MBX_CMDS;
+
+	hbq_entry_index = 0;
+	for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
+		phba->hbqs[hbqno].next_hbqPutIdx = 0;
+		phba->hbqs[hbqno].hbqPutIdx      = 0;
+		phba->hbqs[hbqno].local_hbqGetIdx   = 0;
+		phba->hbqs[hbqno].entry_count =
+			lpfc_hbq_defs[hbqno]->entry_count;
+		lpfc_config_hbq(phba, lpfc_hbq_defs[hbqno], hbq_entry_index,
+				pmb);
+		hbq_entry_index += phba->hbqs[hbqno].entry_count;
+
+		if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
+			/* Adapter failed to init, mbxCmd <cmd> CFG_RING,
+			   mbxStatus <status>, ring <num> */
+
+			lpfc_printf_log(phba, KERN_ERR,
+					LOG_SLI | LOG_VPORT,
+					"%d:1805 Adapter failed to init. "
+					"Data: x%x x%x x%x\n",
+					phba->brd_no, pmbox->mbxCommand,
+					pmbox->mbxStatus, hbqno);
+
+			phba->link_state = LPFC_HBA_ERROR;
+			mempool_free(pmb, phba->mbox_mem_pool);
+			return ENXIO;
+		}
+	}
+	phba->hbq_count = hbq_count;
+
+	mempool_free(pmb, phba->mbox_mem_pool);
+
+	/* Initially populate or replenish the HBQs */
+	for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
+		if (lpfc_sli_hbqbuf_init_hbqs(phba, hbqno))
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+static int
+lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
 {
 	LPFC_MBOXQ_t *pmb;
 	uint32_t resetcount = 0, rc = 0, done = 0;
 
 	pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!pmb) {
-		phba->hba_state = LPFC_HBA_ERROR;
+		phba->link_state = LPFC_HBA_ERROR;
 		return -ENOMEM;
 	}
 
+	phba->sli_rev = sli_mode;
 	while (resetcount < 2 && !done) {
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(&phba->hbalock);
 		phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
-		spin_unlock_irq(phba->host->host_lock);
-		phba->hba_state = LPFC_STATE_UNKNOWN;
+		spin_unlock_irq(&phba->hbalock);
+		phba->pport->port_state = LPFC_VPORT_UNKNOWN;
 		lpfc_sli_brdrestart(phba);
 		msleep(2500);
 		rc = lpfc_sli_chipset_init(phba);
 		if (rc)
 			break;
 
-		spin_lock_irq(phba->host->host_lock);
+		spin_lock_irq(&phba->hbalock);
 		phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-		spin_unlock_irq(phba->host->host_lock);
+		spin_unlock_irq(&phba->hbalock);
 		resetcount++;
 
-	/* Call pre CONFIG_PORT mailbox command initialization.  A value of 0
-	 * means the call was successful.  Any other nonzero value is a failure,
-	 * but if ERESTART is returned, the driver may reset the HBA and try
-	 * again.
-	 */
+		/* Call pre CONFIG_PORT mailbox command initialization.  A
+		 * value of 0 means the call was successful.  Any other
+		 * nonzero value is a failure, but if ERESTART is returned,
+		 * the driver may reset the HBA and try again.
+		 */
 		rc = lpfc_config_port_prep(phba);
 		if (rc == -ERESTART) {
-			phba->hba_state = 0;
+			phba->link_state = LPFC_LINK_UNKNOWN;
 			continue;
 		} else if (rc) {
 			break;
 		}
 
-		phba->hba_state = LPFC_INIT_MBX_CMDS;
+		phba->link_state = LPFC_INIT_MBX_CMDS;
 		lpfc_config_port(phba, pmb);
 		rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
-		if (rc == MBX_SUCCESS)
-			done = 1;
-		else {
+		if (rc != MBX_SUCCESS) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"%d:0442 Adapter failed to init, mbxCmd x%x "
 				"CONFIG_PORT, mbxStatus x%x Data: x%x\n",
 				phba->brd_no, pmb->mb.mbxCommand,
 				pmb->mb.mbxStatus, 0);
+			spin_lock_irq(&phba->hbalock);
 			phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
+			spin_unlock_irq(&phba->hbalock);
+			rc = -ENXIO;
+		} else {
+			done = 1;
+			phba->max_vpi = (phba->max_vpi &&
+					 pmb->mb.un.varCfgPort.gmv) != 0
+				? pmb->mb.un.varCfgPort.max_vpi
+				: 0;
 		}
 	}
-	if (!done)
+
+	if (!done) {
+		rc = -EINVAL;
+		goto do_prep_failed;
+	}
+
+	if ((pmb->mb.un.varCfgPort.sli_mode == 3) &&
+		(!pmb->mb.un.varCfgPort.cMA)) {
+		rc = -ENXIO;
+		goto do_prep_failed;
+	}
+	return rc;
+
+do_prep_failed:
+	mempool_free(pmb, phba->mbox_mem_pool);
+	return rc;
+}
+
+int
+lpfc_sli_hba_setup(struct lpfc_hba *phba)
+{
+	uint32_t rc;
+	int  mode = 3;
+
+	switch (lpfc_sli_mode) {
+	case 2:
+		if (phba->cfg_npiv_enable) {
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+				"%d:1824 NPIV enabled: Override lpfc_sli_mode "
+				"parameter (%d) to auto (0).\n",
+				phba->brd_no, lpfc_sli_mode);
+			break;
+		}
+		mode = 2;
+		break;
+	case 0:
+	case 3:
+		break;
+	default:
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+				"%d:1819 Unrecognized lpfc_sli_mode "
+				"parameter: %d.\n",
+				phba->brd_no, lpfc_sli_mode);
+
+		break;
+	}
+
+	rc = lpfc_do_config_port(phba, mode);
+	if (rc && lpfc_sli_mode == 3)
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+				"%d:1820 Unable to select SLI-3.  "
+				"Not supported by adapter.\n",
+				phba->brd_no);
+	if (rc && mode != 2)
+		rc = lpfc_do_config_port(phba, 2);
+	if (rc)
 		goto lpfc_sli_hba_setup_error;
 
-	rc = lpfc_sli_ring_map(phba, pmb);
+	if (phba->sli_rev == 3) {
+		phba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
+		phba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
+		phba->sli3_options |= LPFC_SLI3_ENABLED;
+		phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
+
+	} else {
+		phba->iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
+		phba->iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
+		phba->sli3_options = 0;
+	}
+
+	lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+			"%d:0444 Firmware in SLI %x mode. Max_vpi %d\n",
+			phba->brd_no, phba->sli_rev, phba->max_vpi);
+	rc = lpfc_sli_ring_map(phba);
 
 	if (rc)
 		goto lpfc_sli_hba_setup_error;
 
+				/* Init HBQs */
+
+	if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+		rc = lpfc_sli_hbq_setup(phba);
+		if (rc)
+			goto lpfc_sli_hba_setup_error;
+	}
+
 	phba->sli.sli_flag |= LPFC_PROCESS_LA;
 
 	rc = lpfc_config_port_post(phba);
 	if (rc)
 		goto lpfc_sli_hba_setup_error;
 
-	goto lpfc_sli_hba_setup_exit;
+	return rc;
+
 lpfc_sli_hba_setup_error:
-	phba->hba_state = LPFC_HBA_ERROR;
-lpfc_sli_hba_setup_exit:
-	mempool_free(pmb, phba->mbox_mem_pool);
+	phba->link_state = LPFC_HBA_ERROR;
+	lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+			"%d:0445 Firmware initialization failed\n",
+			phba->brd_no);
 	return rc;
 }
 
@@ -2004,56 +2413,58 @@
 void
 lpfc_mbox_timeout(unsigned long ptr)
 {
-	struct lpfc_hba *phba;
+	struct lpfc_hba  *phba = (struct lpfc_hba *) ptr;
 	unsigned long iflag;
+	uint32_t tmo_posted;
 
-	phba = (struct lpfc_hba *)ptr;
-	spin_lock_irqsave(phba->host->host_lock, iflag);
-	if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
-		phba->work_hba_events |= WORKER_MBOX_TMO;
+	spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
+	tmo_posted = phba->pport->work_port_events & WORKER_MBOX_TMO;
+	if (!tmo_posted)
+		phba->pport->work_port_events |= WORKER_MBOX_TMO;
+	spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+
+	if (!tmo_posted) {
+		spin_lock_irqsave(&phba->hbalock, iflag);
 		if (phba->work_wait)
-			wake_up(phba->work_wait);
+			lpfc_worker_wake_up(phba);
+		spin_unlock_irqrestore(&phba->hbalock, iflag);
 	}
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
 }
 
 void
 lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
 {
-	LPFC_MBOXQ_t *pmbox;
-	MAILBOX_t *mb;
+	LPFC_MBOXQ_t *pmbox = phba->sli.mbox_active;
+	MAILBOX_t *mb = &pmbox->mb;
 	struct lpfc_sli *psli = &phba->sli;
 	struct lpfc_sli_ring *pring;
 
-	spin_lock_irq(phba->host->host_lock);
-	if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
-		spin_unlock_irq(phba->host->host_lock);
+	if (!(phba->pport->work_port_events & WORKER_MBOX_TMO)) {
 		return;
 	}
 
-	pmbox = phba->sli.mbox_active;
-	mb = &pmbox->mb;
-
 	/* Mbox cmd <mbxCommand> timeout */
-	lpfc_printf_log(phba,
-		KERN_ERR,
-		LOG_MBOX | LOG_SLI,
-		"%d:0310 Mailbox command x%x timeout Data: x%x x%x x%p\n",
-		phba->brd_no,
-		mb->mbxCommand,
-		phba->hba_state,
-		phba->sli.sli_flag,
-		phba->sli.mbox_active);
+	lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+			"%d:0310 Mailbox command x%x timeout Data: x%x x%x "
+			"x%p\n",
+			phba->brd_no,
+			mb->mbxCommand,
+			phba->pport->port_state,
+			phba->sli.sli_flag,
+			phba->sli.mbox_active);
 
 	/* Setting state unknown so lpfc_sli_abort_iocb_ring
 	 * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
 	 * it to fail all oustanding SCSI IO.
 	 */
-	phba->hba_state = LPFC_STATE_UNKNOWN;
-	phba->work_hba_events &= ~WORKER_MBOX_TMO;
-	phba->fc_flag |= FC_ESTABLISH_LINK;
+	spin_lock_irq(&phba->pport->work_port_lock);
+	phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+	spin_unlock_irq(&phba->pport->work_port_lock);
+	spin_lock_irq(&phba->hbalock);
+	phba->link_state = LPFC_LINK_UNKNOWN;
+	phba->pport->fc_flag |= FC_ESTABLISH_LINK;
 	psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-	spin_unlock_irq(phba->host->host_lock);
+	spin_unlock_irq(&phba->hbalock);
 
 	pring = &psli->ring[psli->fcp_ring];
 	lpfc_sli_abort_iocb_ring(phba, pring);
@@ -2075,10 +2486,10 @@
 }
 
 int
-lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
+lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
 {
 	MAILBOX_t *mb;
-	struct lpfc_sli *psli;
+	struct lpfc_sli *psli = &phba->sli;
 	uint32_t status, evtctr;
 	uint32_t ha_copy;
 	int i;
@@ -2086,31 +2497,44 @@
 	volatile uint32_t word0, ldata;
 	void __iomem *to_slim;
 
+	if (pmbox->mbox_cmpl && pmbox->mbox_cmpl != lpfc_sli_def_mbox_cmpl &&
+		pmbox->mbox_cmpl != lpfc_sli_wake_mbox_wait) {
+		if(!pmbox->vport) {
+			lpfc_printf_log(phba, KERN_ERR,
+					LOG_MBOX | LOG_VPORT,
+					"%d:1806 Mbox x%x failed. No vport\n",
+					phba->brd_no,
+					pmbox->mb.mbxCommand);
+			dump_stack();
+			return MBXERR_ERROR;
+		}
+	}
+
+
 	/* If the PCI channel is in offline state, do not post mbox. */
 	if (unlikely(pci_channel_offline(phba->pcidev)))
 		return MBX_NOT_FINISHED;
 
+	spin_lock_irqsave(&phba->hbalock, drvr_flag);
 	psli = &phba->sli;
 
-	spin_lock_irqsave(phba->host->host_lock, drvr_flag);
-
 
 	mb = &pmbox->mb;
 	status = MBX_SUCCESS;
 
-	if (phba->hba_state == LPFC_HBA_ERROR) {
-		spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
+	if (phba->link_state == LPFC_HBA_ERROR) {
+		spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
 
 		/* Mbox command <mbxCommand> cannot issue */
-		LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
-		return (MBX_NOT_FINISHED);
+		LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag)
+		return MBX_NOT_FINISHED;
 	}
 
 	if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
 	    !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
-		spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
-		LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
-		return (MBX_NOT_FINISHED);
+		spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+		LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag)
+		return MBX_NOT_FINISHED;
 	}
 
 	if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
@@ -2120,20 +2544,18 @@
 		 */
 
 		if (flag & MBX_POLL) {
-			spin_unlock_irqrestore(phba->host->host_lock,
-					       drvr_flag);
+			spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
 
 			/* Mbox command <mbxCommand> cannot issue */
-			LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
-			return (MBX_NOT_FINISHED);
+			LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+			return MBX_NOT_FINISHED;
 		}
 
 		if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
-			spin_unlock_irqrestore(phba->host->host_lock,
-					       drvr_flag);
+			spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
 			/* Mbox command <mbxCommand> cannot issue */
-			LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
-			return (MBX_NOT_FINISHED);
+			LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+			return MBX_NOT_FINISHED;
 		}
 
 		/* Handle STOP IOCB processing flag. This is only meaningful
@@ -2157,21 +2579,33 @@
 		lpfc_mbox_put(phba, pmbox);
 
 		/* Mbox cmd issue - BUSY */
-		lpfc_printf_log(phba,
-			KERN_INFO,
-			LOG_MBOX | LOG_SLI,
-			"%d:0308 Mbox cmd issue - BUSY Data: x%x x%x x%x x%x\n",
-			phba->brd_no,
-			mb->mbxCommand,
-			phba->hba_state,
-			psli->sli_flag,
-			flag);
+		lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+				"%d (%d):0308 Mbox cmd issue - BUSY Data: "
+				"x%x x%x x%x x%x\n",
+				phba->brd_no,
+				pmbox->vport ? pmbox->vport->vpi : 0xffffff,
+				mb->mbxCommand, phba->pport->port_state,
+				psli->sli_flag, flag);
 
 		psli->slistat.mbox_busy++;
-		spin_unlock_irqrestore(phba->host->host_lock,
-				       drvr_flag);
+		spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
 
-		return (MBX_BUSY);
+		if (pmbox->vport) {
+			lpfc_debugfs_disc_trc(pmbox->vport,
+				LPFC_DISC_TRC_MBOX_VPORT,
+				"MBOX Bsy vport:  cmd:x%x mb:x%x x%x",
+				(uint32_t)mb->mbxCommand,
+				mb->un.varWords[0], mb->un.varWords[1]);
+		}
+		else {
+			lpfc_debugfs_disc_trc(phba->pport,
+				LPFC_DISC_TRC_MBOX,
+				"MBOX Bsy:        cmd:x%x mb:x%x x%x",
+				(uint32_t)mb->mbxCommand,
+				mb->un.varWords[0], mb->un.varWords[1]);
+		}
+
+		return MBX_BUSY;
 	}
 
 	/* Handle STOP IOCB processing flag. This is only meaningful
@@ -2198,11 +2632,10 @@
 		if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) &&
 		    (mb->mbxCommand != MBX_KILL_BOARD)) {
 			psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-			spin_unlock_irqrestore(phba->host->host_lock,
-					       drvr_flag);
+			spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
 			/* Mbox command <mbxCommand> cannot issue */
-			LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag);
-			return (MBX_NOT_FINISHED);
+			LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+			return MBX_NOT_FINISHED;
 		}
 		/* timeout active mbox command */
 		mod_timer(&psli->mbox_tmo, (jiffies +
@@ -2210,15 +2643,29 @@
 	}
 
 	/* Mailbox cmd <cmd> issue */
-	lpfc_printf_log(phba,
-		KERN_INFO,
-		LOG_MBOX | LOG_SLI,
-		"%d:0309 Mailbox cmd x%x issue Data: x%x x%x x%x\n",
-		phba->brd_no,
-		mb->mbxCommand,
-		phba->hba_state,
-		psli->sli_flag,
-		flag);
+	lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+			"%d (%d):0309 Mailbox cmd x%x issue Data: x%x x%x "
+			"x%x\n",
+			phba->brd_no, pmbox->vport ? pmbox->vport->vpi : 0,
+			mb->mbxCommand, phba->pport->port_state,
+			psli->sli_flag, flag);
+
+	if (mb->mbxCommand != MBX_HEARTBEAT) {
+		if (pmbox->vport) {
+			lpfc_debugfs_disc_trc(pmbox->vport,
+				LPFC_DISC_TRC_MBOX_VPORT,
+				"MBOX Send vport: cmd:x%x mb:x%x x%x",
+				(uint32_t)mb->mbxCommand,
+				mb->un.varWords[0], mb->un.varWords[1]);
+		}
+		else {
+			lpfc_debugfs_disc_trc(phba->pport,
+				LPFC_DISC_TRC_MBOX,
+				"MBOX Send:       cmd:x%x mb:x%x x%x",
+				(uint32_t)mb->mbxCommand,
+				mb->un.varWords[0], mb->un.varWords[1]);
+		}
+	}
 
 	psli->slistat.mbox_cmd++;
 	evtctr = psli->slistat.mbox_event;
@@ -2233,7 +2680,7 @@
 		if (mb->mbxCommand == MBX_CONFIG_PORT) {
 			/* copy command data into host mbox for cmpl */
 			lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx,
-					MAILBOX_CMD_SIZE);
+					      MAILBOX_CMD_SIZE);
 		}
 
 		/* First copy mbox command data to HBA SLIM, skip past first
@@ -2285,12 +2732,12 @@
 		/* Wait for command to complete */
 		while (((word0 & OWN_CHIP) == OWN_CHIP) ||
 		       (!(ha_copy & HA_MBATT) &&
-			(phba->hba_state > LPFC_WARM_START))) {
+			(phba->link_state > LPFC_WARM_START))) {
 			if (i-- <= 0) {
 				psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-				spin_unlock_irqrestore(phba->host->host_lock,
+				spin_unlock_irqrestore(&phba->hbalock,
 						       drvr_flag);
-				return (MBX_NOT_FINISHED);
+				return MBX_NOT_FINISHED;
 			}
 
 			/* Check if we took a mbox interrupt while we were
@@ -2299,12 +2746,12 @@
 			    && (evtctr != psli->slistat.mbox_event))
 				break;
 
-			spin_unlock_irqrestore(phba->host->host_lock,
+			spin_unlock_irqrestore(&phba->hbalock,
 					       drvr_flag);
 
 			msleep(1);
 
-			spin_lock_irqsave(phba->host->host_lock, drvr_flag);
+			spin_lock_irqsave(&phba->hbalock, drvr_flag);
 
 			if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
 				/* First copy command data */
@@ -2335,7 +2782,7 @@
 		if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
 			/* copy results back to user */
 			lpfc_sli_pcimem_bcopy(&phba->slim2p->mbx, mb,
-					MAILBOX_CMD_SIZE);
+					      MAILBOX_CMD_SIZE);
 		} else {
 			/* First copy command data */
 			lpfc_memcpy_from_slim(mb, phba->MBslimaddr,
@@ -2355,23 +2802,25 @@
 		status = mb->mbxStatus;
 	}
 
-	spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
-	return (status);
+	spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+	return status;
 }
 
-static int
-lpfc_sli_ringtx_put(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
-		    struct lpfc_iocbq * piocb)
+/*
+ * Caller needs to hold lock.
+ */
+static void
+__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+		    struct lpfc_iocbq *piocb)
 {
 	/* Insert the caller's iocb in the txq tail for later processing. */
 	list_add_tail(&piocb->list, &pring->txq);
 	pring->txq_cnt++;
-	return (0);
 }
 
 static struct lpfc_iocbq *
 lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-		   struct lpfc_iocbq ** piocb)
+		   struct lpfc_iocbq **piocb)
 {
 	struct lpfc_iocbq * nextiocb;
 
@@ -2384,13 +2833,29 @@
 	return nextiocb;
 }
 
+/*
+ * Lockless version of lpfc_sli_issue_iocb.
+ */
 int
-lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+__lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 		    struct lpfc_iocbq *piocb, uint32_t flag)
 {
 	struct lpfc_iocbq *nextiocb;
 	IOCB_t *iocb;
 
+	if (piocb->iocb_cmpl && (!piocb->vport) &&
+	   (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
+	   (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
+		lpfc_printf_log(phba, KERN_ERR,
+				LOG_SLI | LOG_VPORT,
+				"%d:1807 IOCB x%x failed. No vport\n",
+				phba->brd_no,
+				piocb->iocb.ulpCommand);
+		dump_stack();
+		return IOCB_ERROR;
+	}
+
+
 	/* If the PCI channel is in offline state, do not post iocbs. */
 	if (unlikely(pci_channel_offline(phba->pcidev)))
 		return IOCB_ERROR;
@@ -2398,7 +2863,7 @@
 	/*
 	 * We should never get an IOCB if we are in a < LINK_DOWN state
 	 */
-	if (unlikely(phba->hba_state < LPFC_LINK_DOWN))
+	if (unlikely(phba->link_state < LPFC_LINK_DOWN))
 		return IOCB_ERROR;
 
 	/*
@@ -2408,7 +2873,7 @@
 	if (unlikely(pring->flag & LPFC_STOP_IOCB_MBX))
 		goto iocb_busy;
 
-	if (unlikely(phba->hba_state == LPFC_LINK_DOWN)) {
+	if (unlikely(phba->link_state == LPFC_LINK_DOWN)) {
 		/*
 		 * Only CREATE_XRI, CLOSE_XRI, and QUE_RING_BUF
 		 * can be issued if the link is not up.
@@ -2436,8 +2901,9 @@
 	 * attention events.
 	 */
 	} else if (unlikely(pring->ringno == phba->sli.fcp_ring &&
-		   !(phba->sli.sli_flag & LPFC_PROCESS_LA)))
+			    !(phba->sli.sli_flag & LPFC_PROCESS_LA))) {
 		goto iocb_busy;
+	}
 
 	while ((iocb = lpfc_sli_next_iocb_slot(phba, pring)) &&
 	       (nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb)))
@@ -2459,13 +2925,28 @@
  out_busy:
 
 	if (!(flag & SLI_IOCB_RET_IOCB)) {
-		lpfc_sli_ringtx_put(phba, pring, piocb);
+		__lpfc_sli_ringtx_put(phba, pring, piocb);
 		return IOCB_SUCCESS;
 	}
 
 	return IOCB_BUSY;
 }
 
+
+int
+lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+		    struct lpfc_iocbq *piocb, uint32_t flag)
+{
+	unsigned long iflags;
+	int rc;
+
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	rc = __lpfc_sli_issue_iocb(phba, pring, piocb, flag);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+	return rc;
+}
+
 static int
 lpfc_extra_ring_setup( struct lpfc_hba *phba)
 {
@@ -2504,7 +2985,7 @@
 int
 lpfc_sli_setup(struct lpfc_hba *phba)
 {
-	int i, totiocb = 0;
+	int i, totiocbsize = 0;
 	struct lpfc_sli *psli = &phba->sli;
 	struct lpfc_sli_ring *pring;
 
@@ -2529,6 +3010,12 @@
 			pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
 			pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
 			pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES;
+			pring->sizeCiocb = (phba->sli_rev == 3) ?
+							SLI3_IOCB_CMD_SIZE :
+							SLI2_IOCB_CMD_SIZE;
+			pring->sizeRiocb = (phba->sli_rev == 3) ?
+							SLI3_IOCB_RSP_SIZE :
+							SLI2_IOCB_RSP_SIZE;
 			pring->iotag_ctr = 0;
 			pring->iotag_max =
 			    (phba->cfg_hba_queue_depth * 2);
@@ -2539,12 +3026,25 @@
 			/* numCiocb and numRiocb are used in config_port */
 			pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES;
 			pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES;
+			pring->sizeCiocb = (phba->sli_rev == 3) ?
+							SLI3_IOCB_CMD_SIZE :
+							SLI2_IOCB_CMD_SIZE;
+			pring->sizeRiocb = (phba->sli_rev == 3) ?
+							SLI3_IOCB_RSP_SIZE :
+							SLI2_IOCB_RSP_SIZE;
+			pring->iotag_max = phba->cfg_hba_queue_depth;
 			pring->num_mask = 0;
 			break;
 		case LPFC_ELS_RING:	/* ring 2 - ELS / CT */
 			/* numCiocb and numRiocb are used in config_port */
 			pring->numCiocb = SLI2_IOCB_CMD_R2_ENTRIES;
 			pring->numRiocb = SLI2_IOCB_RSP_R2_ENTRIES;
+			pring->sizeCiocb = (phba->sli_rev == 3) ?
+							SLI3_IOCB_CMD_SIZE :
+							SLI2_IOCB_CMD_SIZE;
+			pring->sizeRiocb = (phba->sli_rev == 3) ?
+							SLI3_IOCB_RSP_SIZE :
+							SLI2_IOCB_RSP_SIZE;
 			pring->fast_iotag = 0;
 			pring->iotag_ctr = 0;
 			pring->iotag_max = 4096;
@@ -2575,14 +3075,16 @@
 			    lpfc_ct_unsol_event;
 			break;
 		}
-		totiocb += (pring->numCiocb + pring->numRiocb);
+		totiocbsize += (pring->numCiocb * pring->sizeCiocb) +
+				(pring->numRiocb * pring->sizeRiocb);
 	}
-	if (totiocb > MAX_SLI2_IOCB) {
+	if (totiocbsize > MAX_SLIM_IOCB_SIZE) {
 		/* Too many cmd / rsp ring entries in SLI2 SLIM */
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"%d:0462 Too many cmd / rsp ring entries in "
-				"SLI2 SLIM Data: x%x x%x\n",
-				phba->brd_no, totiocb, MAX_SLI2_IOCB);
+				"SLI2 SLIM Data: x%x x%lx\n",
+				phba->brd_no, totiocbsize,
+				(unsigned long) MAX_SLIM_IOCB_SIZE);
 	}
 	if (phba->cfg_multi_ring_support == 2)
 		lpfc_extra_ring_setup(phba);
@@ -2591,15 +3093,16 @@
 }
 
 int
-lpfc_sli_queue_setup(struct lpfc_hba * phba)
+lpfc_sli_queue_setup(struct lpfc_hba *phba)
 {
 	struct lpfc_sli *psli;
 	struct lpfc_sli_ring *pring;
 	int i;
 
 	psli = &phba->sli;
-	spin_lock_irq(phba->host->host_lock);
+	spin_lock_irq(&phba->hbalock);
 	INIT_LIST_HEAD(&psli->mboxq);
+	INIT_LIST_HEAD(&psli->mboxq_cmpl);
 	/* Initialize list headers for txq and txcmplq as double linked lists */
 	for (i = 0; i < psli->num_rings; i++) {
 		pring = &psli->ring[i];
@@ -2612,15 +3115,73 @@
 		INIT_LIST_HEAD(&pring->iocb_continueq);
 		INIT_LIST_HEAD(&pring->postbufq);
 	}
-	spin_unlock_irq(phba->host->host_lock);
-	return (1);
+	spin_unlock_irq(&phba->hbalock);
+	return 1;
 }
 
 int
-lpfc_sli_hba_down(struct lpfc_hba * phba)
+lpfc_sli_host_down(struct lpfc_vport *vport)
 {
 	LIST_HEAD(completions);
-	struct lpfc_sli *psli;
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_sli_ring *pring;
+	struct lpfc_iocbq *iocb, *next_iocb;
+	int i;
+	unsigned long flags = 0;
+	uint16_t prev_pring_flag;
+
+	lpfc_cleanup_discovery_resources(vport);
+
+	spin_lock_irqsave(&phba->hbalock, flags);
+	for (i = 0; i < psli->num_rings; i++) {
+		pring = &psli->ring[i];
+		prev_pring_flag = pring->flag;
+		if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
+			pring->flag |= LPFC_DEFERRED_RING_EVENT;
+		/*
+		 * Error everything on the txq since these iocbs have not been
+		 * given to the FW yet.
+		 */
+		list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
+			if (iocb->vport != vport)
+				continue;
+			list_move_tail(&iocb->list, &completions);
+			pring->txq_cnt--;
+		}
+
+		/* Next issue ABTS for everything on the txcmplq */
+		list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq,
+									list) {
+			if (iocb->vport != vport)
+				continue;
+			lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+		}
+
+		pring->flag = prev_pring_flag;
+	}
+
+	spin_unlock_irqrestore(&phba->hbalock, flags);
+
+	while (!list_empty(&completions)) {
+		list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
+
+		if (!iocb->iocb_cmpl)
+			lpfc_sli_release_iocbq(phba, iocb);
+		else {
+			iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
+			iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN;
+			(iocb->iocb_cmpl) (phba, iocb, iocb);
+		}
+	}
+	return 1;
+}
+
+int
+lpfc_sli_hba_down(struct lpfc_hba *phba)
+{
+	LIST_HEAD(completions);
+	struct lpfc_sli *psli = &phba->sli;
 	struct lpfc_sli_ring *pring;
 	LPFC_MBOXQ_t *pmb;
 	struct lpfc_iocbq *iocb;
@@ -2628,13 +3189,15 @@
 	int i;
 	unsigned long flags = 0;
 
-	psli = &phba->sli;
 	lpfc_hba_down_prep(phba);
 
-	spin_lock_irqsave(phba->host->host_lock, flags);
+	lpfc_fabric_abort_hba(phba);
+
+	spin_lock_irqsave(&phba->hbalock, flags);
 	for (i = 0; i < psli->num_rings; i++) {
 		pring = &psli->ring[i];
-		pring->flag |= LPFC_DEFERRED_RING_EVENT;
+		if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
+			pring->flag |= LPFC_DEFERRED_RING_EVENT;
 
 		/*
 		 * Error everything on the txq since these iocbs have not been
@@ -2644,51 +3207,50 @@
 		pring->txq_cnt = 0;
 
 	}
-	spin_unlock_irqrestore(phba->host->host_lock, flags);
+	spin_unlock_irqrestore(&phba->hbalock, flags);
 
 	while (!list_empty(&completions)) {
-		iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+		list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
 		cmd = &iocb->iocb;
-		list_del(&iocb->list);
 
-		if (iocb->iocb_cmpl) {
+		if (!iocb->iocb_cmpl)
+			lpfc_sli_release_iocbq(phba, iocb);
+		else {
 			cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
 			cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
 			(iocb->iocb_cmpl) (phba, iocb, iocb);
-		} else
-			lpfc_sli_release_iocbq(phba, iocb);
+		}
 	}
 
 	/* Return any active mbox cmds */
 	del_timer_sync(&psli->mbox_tmo);
-	spin_lock_irqsave(phba->host->host_lock, flags);
-	phba->work_hba_events &= ~WORKER_MBOX_TMO;
+	spin_lock_irqsave(&phba->hbalock, flags);
+
+	spin_lock(&phba->pport->work_port_lock);
+	phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+	spin_unlock(&phba->pport->work_port_lock);
+
 	if (psli->mbox_active) {
-		pmb = psli->mbox_active;
-		pmb->mb.mbxStatus = MBX_NOT_FINISHED;
-		if (pmb->mbox_cmpl) {
-			spin_unlock_irqrestore(phba->host->host_lock, flags);
-			pmb->mbox_cmpl(phba,pmb);
-			spin_lock_irqsave(phba->host->host_lock, flags);
-		}
-	}
-	psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-	psli->mbox_active = NULL;
-
-	/* Return any pending mbox cmds */
-	while ((pmb = lpfc_mbox_get(phba)) != NULL) {
-		pmb->mb.mbxStatus = MBX_NOT_FINISHED;
-		if (pmb->mbox_cmpl) {
-			spin_unlock_irqrestore(phba->host->host_lock, flags);
-			pmb->mbox_cmpl(phba,pmb);
-			spin_lock_irqsave(phba->host->host_lock, flags);
-		}
+		list_add_tail(&psli->mbox_active->list, &completions);
+		psli->mbox_active = NULL;
+		psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
 	}
 
+	/* Return any pending or completed mbox cmds */
+	list_splice_init(&phba->sli.mboxq, &completions);
+	list_splice_init(&phba->sli.mboxq_cmpl, &completions);
 	INIT_LIST_HEAD(&psli->mboxq);
+	INIT_LIST_HEAD(&psli->mboxq_cmpl);
 
-	spin_unlock_irqrestore(phba->host->host_lock, flags);
+	spin_unlock_irqrestore(&phba->hbalock, flags);
 
+	while (!list_empty(&completions)) {
+		list_remove_head(&completions, pmb, LPFC_MBOXQ_t, list);
+		pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+		if (pmb->mbox_cmpl) {
+			pmb->mbox_cmpl(phba,pmb);
+		}
+	}
 	return 1;
 }
 
@@ -2710,14 +3272,15 @@
 }
 
 int
-lpfc_sli_ringpostbuf_put(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
-			 struct lpfc_dmabuf * mp)
+lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+			 struct lpfc_dmabuf *mp)
 {
 	/* Stick struct lpfc_dmabuf at end of postbufq so driver can look it up
 	   later */
+	spin_lock_irq(&phba->hbalock);
 	list_add_tail(&mp->list, &pring->postbufq);
-
 	pring->postbufq_cnt++;
+	spin_unlock_irq(&phba->hbalock);
 	return 0;
 }
 
@@ -2730,14 +3293,17 @@
 	struct list_head *slp = &pring->postbufq;
 
 	/* Search postbufq, from the begining, looking for a match on phys */
+	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
 		if (mp->phys == phys) {
 			list_del_init(&mp->list);
 			pring->postbufq_cnt--;
+			spin_unlock_irq(&phba->hbalock);
 			return mp;
 		}
 	}
 
+	spin_unlock_irq(&phba->hbalock);
 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 			"%d:0410 Cannot find virtual addr for mapped buf on "
 			"ring %d Data x%llx x%p x%p x%x\n",
@@ -2747,92 +3313,110 @@
 }
 
 static void
-lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-			struct lpfc_iocbq * rspiocb)
+lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
 {
-	IOCB_t *irsp;
+	IOCB_t *irsp = &rspiocb->iocb;
 	uint16_t abort_iotag, abort_context;
-	struct lpfc_iocbq *abort_iocb, *rsp_ab_iocb;
+	struct lpfc_iocbq *abort_iocb;
 	struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
 
 	abort_iocb = NULL;
-	irsp = &rspiocb->iocb;
-
-	spin_lock_irq(phba->host->host_lock);
 
 	if (irsp->ulpStatus) {
 		abort_context = cmdiocb->iocb.un.acxri.abortContextTag;
 		abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag;
 
+		spin_lock_irq(&phba->hbalock);
 		if (abort_iotag != 0 && abort_iotag <= phba->sli.last_iotag)
 			abort_iocb = phba->sli.iocbq_lookup[abort_iotag];
 
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"%d:0327 Cannot abort els iocb %p"
-				" with tag %x context %x\n",
-				phba->brd_no, abort_iocb,
-				abort_iotag, abort_context);
+		lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI,
+				"%d:0327 Cannot abort els iocb %p "
+				"with tag %x context %x, abort status %x, "
+				"abort code %x\n",
+				phba->brd_no, abort_iocb, abort_iotag,
+				abort_context, irsp->ulpStatus,
+				irsp->un.ulpWord[4]);
 
 		/*
 		 * make sure we have the right iocbq before taking it
 		 * off the txcmplq and try to call completion routine.
 		 */
-		if (abort_iocb &&
-		    abort_iocb->iocb.ulpContext == abort_context &&
-		    abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
-			list_del(&abort_iocb->list);
+		if (!abort_iocb ||
+		    abort_iocb->iocb.ulpContext != abort_context ||
+		    (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0)
+			spin_unlock_irq(&phba->hbalock);
+		else {
+			list_del_init(&abort_iocb->list);
 			pring->txcmplq_cnt--;
+			spin_unlock_irq(&phba->hbalock);
 
-			rsp_ab_iocb = lpfc_sli_get_iocbq(phba);
-			if (rsp_ab_iocb == NULL)
-				lpfc_sli_release_iocbq(phba, abort_iocb);
-			else {
-				abort_iocb->iocb_flag &=
-					~LPFC_DRIVER_ABORTED;
-				rsp_ab_iocb->iocb.ulpStatus =
-					IOSTAT_LOCAL_REJECT;
-				rsp_ab_iocb->iocb.un.ulpWord[4] =
-					IOERR_SLI_ABORTED;
-				spin_unlock_irq(phba->host->host_lock);
-				(abort_iocb->iocb_cmpl)
-					(phba, abort_iocb, rsp_ab_iocb);
-				spin_lock_irq(phba->host->host_lock);
-				lpfc_sli_release_iocbq(phba, rsp_ab_iocb);
-			}
+			abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
+			abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
+			abort_iocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED;
+			(abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb);
 		}
 	}
 
 	lpfc_sli_release_iocbq(phba, cmdiocb);
-	spin_unlock_irq(phba->host->host_lock);
+	return;
+}
+
+static void
+lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		     struct lpfc_iocbq *rspiocb)
+{
+	IOCB_t *irsp = &rspiocb->iocb;
+
+	/* ELS cmd tag <ulpIoTag> completes */
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+			"%d (X):0133 Ignoring ELS cmd tag x%x completion Data: "
+			"x%x x%x x%x\n",
+			phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus,
+			irsp->un.ulpWord[4], irsp->ulpTimeout);
+	if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR)
+		lpfc_ct_free_iocb(phba, cmdiocb);
+	else
+		lpfc_els_free_iocb(phba, cmdiocb);
 	return;
 }
 
 int
-lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
-			   struct lpfc_sli_ring * pring,
-			   struct lpfc_iocbq * cmdiocb)
+lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+			   struct lpfc_iocbq *cmdiocb)
 {
+	struct lpfc_vport *vport = cmdiocb->vport;
 	struct lpfc_iocbq *abtsiocbp;
 	IOCB_t *icmd = NULL;
 	IOCB_t *iabt = NULL;
 	int retval = IOCB_ERROR;
 
-	/* There are certain command types we don't want
-	 * to abort.
+	/*
+	 * There are certain command types we don't want to abort.  And we
+	 * don't want to abort commands that are already in the process of
+	 * being aborted.
 	 */
 	icmd = &cmdiocb->iocb;
-	if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) ||
-	    (icmd->ulpCommand == CMD_CLOSE_XRI_CN))
+	if (icmd->ulpCommand == CMD_ABORT_XRI_CN ||
+	    icmd->ulpCommand == CMD_CLOSE_XRI_CN ||
+	    (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0)
 		return 0;
 
-	/* If we're unloading, interrupts are disabled so we
-	 * need to cleanup the iocb here.
+	/* If we're unloading, don't abort iocb on the ELS ring, but change the
+	 * callback so that nothing happens when it finishes.
 	 */
-	if (phba->fc_flag & FC_UNLOADING)
+	if ((vport->load_flag & FC_UNLOADING) &&
+	    (pring->ringno == LPFC_ELS_RING)) {
+		if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
+			cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
+		else
+			cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl;
 		goto abort_iotag_exit;
+	}
 
 	/* issue ABTS for this IOCB based on iotag */
-	abtsiocbp = lpfc_sli_get_iocbq(phba);
+	abtsiocbp = __lpfc_sli_get_iocbq(phba);
 	if (abtsiocbp == NULL)
 		return 0;
 
@@ -2848,7 +3432,7 @@
 	iabt->ulpLe = 1;
 	iabt->ulpClass = icmd->ulpClass;
 
-	if (phba->hba_state >= LPFC_LINK_UP)
+	if (phba->link_state >= LPFC_LINK_UP)
 		iabt->ulpCommand = CMD_ABORT_XRI_CN;
 	else
 		iabt->ulpCommand = CMD_CLOSE_XRI_CN;
@@ -2856,32 +3440,20 @@
 	abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
 
 	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-			"%d:0339 Abort xri x%x, original iotag x%x, abort "
-			"cmd iotag x%x\n",
-			phba->brd_no, iabt->un.acxri.abortContextTag,
+			"%d (%d):0339 Abort xri x%x, original iotag x%x, "
+			"abort cmd iotag x%x\n",
+			phba->brd_no, vport->vpi,
+			iabt->un.acxri.abortContextTag,
 			iabt->un.acxri.abortIoTag, abtsiocbp->iotag);
-	retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
+	retval = __lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
 
 abort_iotag_exit:
-
-	/* If we could not issue an abort dequeue the iocb and handle
-	 * the completion here.
+	/*
+	 * Caller to this routine should check for IOCB_ERROR
+	 * and handle it properly.  This routine no longer removes
+	 * iocb off txcmplq and call compl in case of IOCB_ERROR.
 	 */
-	if (retval == IOCB_ERROR) {
-		list_del(&cmdiocb->list);
-		pring->txcmplq_cnt--;
-
-		if (cmdiocb->iocb_cmpl) {
-			icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-			icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-			spin_unlock_irq(phba->host->host_lock);
-			(cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb);
-			spin_lock_irq(phba->host->host_lock);
-		} else
-			lpfc_sli_release_iocbq(phba, cmdiocb);
-	}
-
-	return 1;
+	return retval;
 }
 
 static int
@@ -2930,7 +3502,7 @@
 
 int
 lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-		uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd)
+		  uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd)
 {
 	struct lpfc_iocbq *iocbq;
 	int sum, i;
@@ -2947,14 +3519,10 @@
 }
 
 void
-lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
-			   struct lpfc_iocbq * rspiocb)
+lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+			struct lpfc_iocbq *rspiocb)
 {
-	unsigned long iflags;
-
-	spin_lock_irqsave(phba->host->host_lock, iflags);
 	lpfc_sli_release_iocbq(phba, cmdiocb);
-	spin_unlock_irqrestore(phba->host->host_lock, iflags);
 	return;
 }
 
@@ -2972,8 +3540,8 @@
 	for (i = 1; i <= phba->sli.last_iotag; i++) {
 		iocbq = phba->sli.iocbq_lookup[i];
 
-		if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id,
-						0, abort_cmd) != 0)
+		if (lpfc_sli_validate_fcp_iocb(iocbq, tgt_id, lun_id, 0,
+					       abort_cmd) != 0)
 			continue;
 
 		/* issue ABTS for this IOCB based on iotag */
@@ -2989,8 +3557,9 @@
 		abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag;
 		abtsiocb->iocb.ulpLe = 1;
 		abtsiocb->iocb.ulpClass = cmd->ulpClass;
+		abtsiocb->vport = phba->pport;
 
-		if (phba->hba_state >= LPFC_LINK_UP)
+		if (lpfc_is_link_up(phba))
 			abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN;
 		else
 			abtsiocb->iocb.ulpCommand = CMD_CLOSE_XRI_CN;
@@ -3016,16 +3585,16 @@
 	wait_queue_head_t *pdone_q;
 	unsigned long iflags;
 
-	spin_lock_irqsave(phba->host->host_lock, iflags);
+	spin_lock_irqsave(&phba->hbalock, iflags);
 	cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
 	if (cmdiocbq->context2 && rspiocbq)
 		memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
 		       &rspiocbq->iocb, sizeof(IOCB_t));
 
 	pdone_q = cmdiocbq->context_un.wait_queue;
-	spin_unlock_irqrestore(phba->host->host_lock, iflags);
 	if (pdone_q)
 		wake_up(pdone_q);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
 	return;
 }
 
@@ -3035,11 +3604,12 @@
  * lpfc_sli_issue_call since the wake routine sets a unique value and by
  * definition this is a wait function.
  */
+
 int
-lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
-			 struct lpfc_sli_ring * pring,
-			 struct lpfc_iocbq * piocb,
-			 struct lpfc_iocbq * prspiocbq,
+lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
+			 struct lpfc_sli_ring *pring,
+			 struct lpfc_iocbq *piocb,
+			 struct lpfc_iocbq *prspiocbq,
 			 uint32_t timeout)
 {
 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
@@ -3071,11 +3641,9 @@
 	retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
 	if (retval == IOCB_SUCCESS) {
 		timeout_req = timeout * HZ;
-		spin_unlock_irq(phba->host->host_lock);
 		timeleft = wait_event_timeout(done_q,
 				piocb->iocb_flag & LPFC_IO_WAKE,
 				timeout_req);
-		spin_lock_irq(phba->host->host_lock);
 
 		if (piocb->iocb_flag & LPFC_IO_WAKE) {
 			lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
@@ -3117,16 +3685,16 @@
 }
 
 int
-lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
+lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
 			 uint32_t timeout)
 {
 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
 	int retval;
+	unsigned long flag;
 
 	/* The caller must leave context1 empty. */
-	if (pmboxq->context1 != 0) {
-		return (MBX_NOT_FINISHED);
-	}
+	if (pmboxq->context1 != 0)
+		return MBX_NOT_FINISHED;
 
 	/* setup wake call as IOCB callback */
 	pmboxq->mbox_cmpl = lpfc_sli_wake_mbox_wait;
@@ -3141,6 +3709,7 @@
 				pmboxq->mbox_flag & LPFC_MBX_WAKE,
 				timeout * HZ);
 
+		spin_lock_irqsave(&phba->hbalock, flag);
 		pmboxq->context1 = NULL;
 		/*
 		 * if LPFC_MBX_WAKE flag is set the mailbox is completed
@@ -3148,8 +3717,11 @@
 		 */
 		if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
 			retval = MBX_SUCCESS;
-		else
+		else {
 			retval = MBX_TIMEOUT;
+			pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		}
+		spin_unlock_irqrestore(&phba->hbalock, flag);
 	}
 
 	return retval;
@@ -3158,14 +3730,27 @@
 int
 lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
 {
+	struct lpfc_vport *vport = phba->pport;
 	int i = 0;
+	uint32_t ha_copy;
 
-	while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !phba->stopped) {
+	while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !vport->stopped) {
 		if (i++ > LPFC_MBOX_TMO * 1000)
 			return 1;
 
-		if (lpfc_sli_handle_mb_event(phba) == 0)
-			i = 0;
+		/*
+		 * Call lpfc_sli_handle_mb_event only if a mailbox cmd
+		 * did finish. This way we won't get the misleading
+		 * "Stray Mailbox Interrupt" message.
+		 */
+		spin_lock_irq(&phba->hbalock);
+		ha_copy = phba->work_ha;
+		phba->work_ha &= ~HA_MBATT;
+		spin_unlock_irq(&phba->hbalock);
+
+		if (ha_copy & HA_MBATT)
+			if (lpfc_sli_handle_mb_event(phba) == 0)
+				i = 0;
 
 		msleep(1);
 	}
@@ -3176,13 +3761,20 @@
 irqreturn_t
 lpfc_intr_handler(int irq, void *dev_id)
 {
-	struct lpfc_hba *phba;
+	struct lpfc_hba  *phba;
 	uint32_t ha_copy;
 	uint32_t work_ha_copy;
 	unsigned long status;
 	int i;
 	uint32_t control;
 
+	MAILBOX_t *mbox, *pmbox;
+	struct lpfc_vport *vport;
+	struct lpfc_nodelist *ndlp;
+	struct lpfc_dmabuf *mp;
+	LPFC_MBOXQ_t *pmb;
+	int rc;
+
 	/*
 	 * Get the driver's phba structure from the dev_id and
 	 * assume the HBA is not interrupting.
@@ -3204,7 +3796,7 @@
 	 */
 
 	/* Ignore all interrupts during initialization. */
-	if (unlikely(phba->hba_state < LPFC_LINK_DOWN))
+	if (unlikely(phba->link_state < LPFC_LINK_DOWN))
 		return IRQ_NONE;
 
 	/*
@@ -3212,16 +3804,16 @@
 	 * Clear Attention Sources, except Error Attention (to
 	 * preserve status) and Link Attention
 	 */
-	spin_lock(phba->host->host_lock);
+	spin_lock(&phba->hbalock);
 	ha_copy = readl(phba->HAregaddr);
 	/* If somebody is waiting to handle an eratt don't process it
 	 * here.  The brdkill function will do this.
 	 */
-	if (phba->fc_flag & FC_IGNORE_ERATT)
+	if (phba->link_flag & LS_IGNORE_ERATT)
 		ha_copy &= ~HA_ERATT;
 	writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
 	readl(phba->HAregaddr); /* flush */
-	spin_unlock(phba->host->host_lock);
+	spin_unlock(&phba->hbalock);
 
 	if (unlikely(!ha_copy))
 		return IRQ_NONE;
@@ -3235,36 +3827,41 @@
 				 * Turn off Link Attention interrupts
 				 * until CLEAR_LA done
 				 */
-				spin_lock(phba->host->host_lock);
+				spin_lock(&phba->hbalock);
 				phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
 				control = readl(phba->HCregaddr);
 				control &= ~HC_LAINT_ENA;
 				writel(control, phba->HCregaddr);
 				readl(phba->HCregaddr); /* flush */
-				spin_unlock(phba->host->host_lock);
+				spin_unlock(&phba->hbalock);
 			}
 			else
 				work_ha_copy &= ~HA_LATT;
 		}
 
 		if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) {
-			for (i = 0; i < phba->sli.num_rings; i++) {
-				if (work_ha_copy & (HA_RXATT << (4*i))) {
-					/*
-					 * Turn off Slow Rings interrupts
-					 */
-					spin_lock(phba->host->host_lock);
-					control = readl(phba->HCregaddr);
-					control &= ~(HC_R0INT_ENA << i);
+			/*
+			 * Turn off Slow Rings interrupts, LPFC_ELS_RING is
+			 * the only slow ring.
+			 */
+			status = (work_ha_copy &
+				(HA_RXMASK  << (4*LPFC_ELS_RING)));
+			status >>= (4*LPFC_ELS_RING);
+			if (status & HA_RXMASK) {
+				spin_lock(&phba->hbalock);
+				control = readl(phba->HCregaddr);
+				if (control & (HC_R0INT_ENA << LPFC_ELS_RING)) {
+					control &=
+					    ~(HC_R0INT_ENA << LPFC_ELS_RING);
 					writel(control, phba->HCregaddr);
 					readl(phba->HCregaddr); /* flush */
-					spin_unlock(phba->host->host_lock);
 				}
+				spin_unlock(&phba->hbalock);
 			}
 		}
 
 		if (work_ha_copy & HA_ERATT) {
-			phba->hba_state = LPFC_HBA_ERROR;
+			phba->link_state = LPFC_HBA_ERROR;
 			/*
 			 * There was a link/board error.  Read the
 			 * status register to retrieve the error event
@@ -3279,14 +3876,108 @@
 			/* Clear Chip error bit */
 			writel(HA_ERATT, phba->HAregaddr);
 			readl(phba->HAregaddr); /* flush */
-			phba->stopped = 1;
+			phba->pport->stopped = 1;
 		}
 
-		spin_lock(phba->host->host_lock);
+		if ((work_ha_copy & HA_MBATT) &&
+		    (phba->sli.mbox_active)) {
+			pmb = phba->sli.mbox_active;
+			pmbox = &pmb->mb;
+			mbox = &phba->slim2p->mbx;
+			vport = pmb->vport;
+
+			/* First check out the status word */
+			lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
+			if (pmbox->mbxOwner != OWN_HOST) {
+				/*
+				 * Stray Mailbox Interrupt, mbxCommand <cmd>
+				 * mbxStatus <status>
+				 */
+				lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX |
+						LOG_SLI,
+						"%d (%d):0304 Stray Mailbox "
+						"Interrupt mbxCommand x%x "
+						"mbxStatus x%x\n",
+						phba->brd_no,
+						(vport
+						 ? vport->vpi : 0),
+						pmbox->mbxCommand,
+						pmbox->mbxStatus);
+			}
+			phba->last_completion_time = jiffies;
+			del_timer_sync(&phba->sli.mbox_tmo);
+
+			phba->sli.mbox_active = NULL;
+			if (pmb->mbox_cmpl) {
+				lpfc_sli_pcimem_bcopy(mbox, pmbox,
+						      MAILBOX_CMD_SIZE);
+			}
+			if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
+				pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
+
+				lpfc_debugfs_disc_trc(vport,
+					LPFC_DISC_TRC_MBOX_VPORT,
+					"MBOX dflt rpi: : status:x%x rpi:x%x",
+					(uint32_t)pmbox->mbxStatus,
+					pmbox->un.varWords[0], 0);
+
+				if ( !pmbox->mbxStatus) {
+					mp = (struct lpfc_dmabuf *)
+						(pmb->context1);
+					ndlp = (struct lpfc_nodelist *)
+						pmb->context2;
+
+					/* Reg_LOGIN of dflt RPI was successful.
+					 * new lets get rid of the RPI using the
+					 * same mbox buffer.
+					 */
+					lpfc_unreg_login(phba, vport->vpi,
+						pmbox->un.varWords[0], pmb);
+					pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
+					pmb->context1 = mp;
+					pmb->context2 = ndlp;
+					pmb->vport = vport;
+					spin_lock(&phba->hbalock);
+					phba->sli.sli_flag &=
+						~LPFC_SLI_MBOX_ACTIVE;
+					spin_unlock(&phba->hbalock);
+					goto send_current_mbox;
+				}
+			}
+			spin_lock(&phba->pport->work_port_lock);
+			phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+			spin_unlock(&phba->pport->work_port_lock);
+			lpfc_mbox_cmpl_put(phba, pmb);
+		}
+		if ((work_ha_copy & HA_MBATT) &&
+		    (phba->sli.mbox_active == NULL)) {
+send_next_mbox:
+			spin_lock(&phba->hbalock);
+			phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+			pmb = lpfc_mbox_get(phba);
+			spin_unlock(&phba->hbalock);
+send_current_mbox:
+			/* Process next mailbox command if there is one */
+			if (pmb != NULL) {
+				rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+				if (rc == MBX_NOT_FINISHED) {
+					pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+					lpfc_mbox_cmpl_put(phba, pmb);
+					goto send_next_mbox;
+				}
+			} else {
+				/* Turn on IOCB processing */
+				for (i = 0; i < phba->sli.num_rings; i++)
+					lpfc_sli_turn_on_ring(phba, i);
+			}
+
+		}
+
+		spin_lock(&phba->hbalock);
 		phba->work_ha |= work_ha_copy;
 		if (phba->work_wait)
-			wake_up(phba->work_wait);
-		spin_unlock(phba->host->host_lock);
+			lpfc_worker_wake_up(phba);
+		spin_unlock(&phba->hbalock);
 	}
 
 	ha_copy &= ~(phba->work_ha_mask);
@@ -3298,7 +3989,7 @@
 	 */
 	status = (ha_copy & (HA_RXMASK  << (4*LPFC_FCP_RING)));
 	status >>= (4*LPFC_FCP_RING);
-	if (status & HA_RXATT)
+	if (status & HA_RXMASK)
 		lpfc_sli_handle_fast_ring_event(phba,
 						&phba->sli.ring[LPFC_FCP_RING],
 						status);
@@ -3311,7 +4002,7 @@
 		 */
 		status = (ha_copy & (HA_RXMASK  << (4*LPFC_EXTRA_RING)));
 		status >>= (4*LPFC_EXTRA_RING);
-		if (status & HA_RXATT) {
+		if (status & HA_RXMASK) {
 			lpfc_sli_handle_fast_ring_event(phba,
 					&phba->sli.ring[LPFC_EXTRA_RING],
 					status);
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index 41c38d3..76058505 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -20,6 +20,7 @@
 
 /* forward declaration for LPFC_IOCB_t's use */
 struct lpfc_hba;
+struct lpfc_vport;
 
 /* Define the context types that SLI handles for abort and sums. */
 typedef enum _lpfc_ctx_cmd {
@@ -43,10 +44,12 @@
 #define LPFC_IO_WAKE		2	/* High Priority Queue signal flag */
 #define LPFC_IO_FCP		4	/* FCP command -- iocbq in scsi_buf */
 #define LPFC_DRIVER_ABORTED	8	/* driver aborted this request */
+#define LPFC_IO_FABRIC		0x10	/* Iocb send using fabric scheduler */
 
 	uint8_t abort_count;
 	uint8_t rsvd2;
 	uint32_t drvrTimeout;	/* driver timeout in seconds */
+	struct lpfc_vport *vport;/* virtual port pointer */
 	void *context1;		/* caller context information */
 	void *context2;		/* caller context information */
 	void *context3;		/* caller context information */
@@ -56,6 +59,8 @@
 		struct lpfcMboxq   *mbox;
 	} context_un;
 
+	void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
+			   struct lpfc_iocbq *);
 	void (*iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
 			   struct lpfc_iocbq *);
 
@@ -68,12 +73,14 @@
 #define IOCB_ERROR          2
 #define IOCB_TIMEDOUT       3
 
-#define LPFC_MBX_WAKE	1
+#define LPFC_MBX_WAKE		1
+#define LPFC_MBX_IMED_UNREG	2
 
 typedef struct lpfcMboxq {
 	/* MBOXQs are used in single linked lists */
 	struct list_head list;	/* ptr to next mailbox command */
 	MAILBOX_t mb;		/* Mailbox cmd */
+	struct lpfc_vport *vport;/* virutal port pointer */
 	void *context1;		/* caller context information */
 	void *context2;		/* caller context information */
 
@@ -135,6 +142,8 @@
 	uint8_t ringno;		/* ring number */
 	uint16_t numCiocb;	/* number of command iocb's per ring */
 	uint16_t numRiocb;	/* number of rsp iocb's per ring */
+	uint16_t sizeCiocb;	/* Size of command iocb's in this ring */
+	uint16_t sizeRiocb; 	/* Size of response iocb's in this ring */
 
 	uint32_t fast_iotag;	/* max fastlookup based iotag           */
 	uint32_t iotag_ctr;	/* keeps track of the next iotag to use */
@@ -165,6 +174,34 @@
 					struct lpfc_sli_ring *);
 };
 
+/* Structure used for configuring rings to a specific profile or rctl / type */
+struct lpfc_hbq_init {
+	uint32_t rn;		/* Receive buffer notification */
+	uint32_t entry_count;	/* max # of entries in HBQ */
+	uint32_t headerLen;	/* 0 if not profile 4 or 5 */
+	uint32_t logEntry;	/* Set to 1 if this HBQ used for LogEntry */
+	uint32_t profile;	/* Selection profile 0=all, 7=logentry */
+	uint32_t ring_mask;	/* Binds HBQ to a ring e.g. Ring0=b0001,
+				 * ring2=b0100 */
+	uint32_t hbq_index;	/* index of this hbq in ring .HBQs[] */
+
+	uint32_t seqlenoff;
+	uint32_t maxlen;
+	uint32_t seqlenbcnt;
+	uint32_t cmdcodeoff;
+	uint32_t cmdmatch[8];
+	uint32_t mask_count;	/* number of mask entries in prt array */
+	struct hbq_mask hbqMasks[6];
+
+	/* Non-config rings fields to keep track of buffer allocations */
+	uint32_t buffer_count;	/* number of buffers allocated */
+	uint32_t init_count;	/* number to allocate when initialized */
+	uint32_t add_count;	/* number to allocate when starved */
+} ;
+
+#define LPFC_MAX_HBQ 16
+
+
 /* Structure used to hold SLI statistical counters and info */
 struct lpfc_sli_stat {
 	uint64_t mbox_stat_err;  /* Mbox cmds completed status error */
@@ -197,6 +234,7 @@
 #define LPFC_SLI_MBOX_ACTIVE      0x100	/* HBA mailbox is currently active */
 #define LPFC_SLI2_ACTIVE          0x200	/* SLI2 overlay in firmware is active */
 #define LPFC_PROCESS_LA           0x400	/* Able to process link attention */
+#define LPFC_BLOCK_MGMT_IO        0x800	/* Don't allow mgmt mbx or iocb cmds */
 
 	struct lpfc_sli_ring ring[LPFC_MAX_RING];
 	int fcp_ring;		/* ring used for FCP initiator commands */
@@ -209,6 +247,7 @@
 	uint16_t mboxq_cnt;	/* current length of queue */
 	uint16_t mboxq_max;	/* max length */
 	LPFC_MBOXQ_t *mbox_active;	/* active mboxq information */
+	struct list_head mboxq_cmpl;
 
 	struct timer_list mbox_tmo;	/* Hold clk to timeout active mbox
 					   cmd */
@@ -221,12 +260,6 @@
 	struct lpfc_lnk_stat lnk_stat_offsets;
 };
 
-/* Given a pointer to the start of the ring, and the slot number of
- * the desired iocb entry, calc a pointer to that entry.
- * (assume iocb entry size is 32 bytes, or 8 words)
- */
-#define IOCB_ENTRY(ring,slot) ((IOCB_t *)(((char *)(ring)) + ((slot) * 32)))
-
 #define LPFC_MBOX_TMO           30	/* Sec tmo for outstanding mbox
 					   command */
 #define LPFC_MBOX_TMO_FLASH_CMD 300     /* Sec tmo for outstanding FLASH write
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 92a9107..a5bc79e 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.1.12"
+#define LPFC_DRIVER_VERSION "8.2.1"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
new file mode 100644
index 0000000..85797db
--- /dev/null
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -0,0 +1,523 @@
+/*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for         *
+ * Fibre Channel Host Bus Adapters.                                *
+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * EMULEX and SLI are trademarks of Emulex.                        *
+ * www.emulex.com                                                  *
+ * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
+ *                                                                 *
+ * This program is free software; you can redistribute it and/or   *
+ * modify it under the terms of version 2 of the GNU General       *
+ * Public License as published by the Free Software Foundation.    *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+ * more details, a copy of which can be found in the file COPYING  *
+ * included with this package.                                     *
+ *******************************************************************/
+
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
+#include "lpfc_hw.h"
+#include "lpfc_sli.h"
+#include "lpfc_disc.h"
+#include "lpfc_scsi.h"
+#include "lpfc.h"
+#include "lpfc_logmsg.h"
+#include "lpfc_crtn.h"
+#include "lpfc_version.h"
+#include "lpfc_vport.h"
+
+inline void lpfc_vport_set_state(struct lpfc_vport *vport,
+				 enum fc_vport_state new_state)
+{
+	struct fc_vport *fc_vport = vport->fc_vport;
+
+	if (fc_vport) {
+		/*
+		 * When the transport defines fc_vport_set state we will replace
+		 * this code with the following line
+		 */
+		/* fc_vport_set_state(fc_vport, new_state); */
+		if (new_state != FC_VPORT_INITIALIZING)
+			fc_vport->vport_last_state = fc_vport->vport_state;
+		fc_vport->vport_state = new_state;
+	}
+
+	/* for all the error states we will set the invternal state to FAILED */
+	switch (new_state) {
+	case FC_VPORT_NO_FABRIC_SUPP:
+	case FC_VPORT_NO_FABRIC_RSCS:
+	case FC_VPORT_FABRIC_LOGOUT:
+	case FC_VPORT_FABRIC_REJ_WWN:
+	case FC_VPORT_FAILED:
+		vport->port_state = LPFC_VPORT_FAILED;
+		break;
+	case FC_VPORT_LINKDOWN:
+		vport->port_state = LPFC_VPORT_UNKNOWN;
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+}
+
+static int
+lpfc_alloc_vpi(struct lpfc_hba *phba)
+{
+	int  vpi;
+
+	spin_lock_irq(&phba->hbalock);
+	/* Start at bit 1 because vpi zero is reserved for the physical port */
+	vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1);
+	if (vpi > phba->max_vpi)
+		vpi = 0;
+	else
+		set_bit(vpi, phba->vpi_bmask);
+	spin_unlock_irq(&phba->hbalock);
+	return vpi;
+}
+
+static void
+lpfc_free_vpi(struct lpfc_hba *phba, int vpi)
+{
+	spin_lock_irq(&phba->hbalock);
+	clear_bit(vpi, phba->vpi_bmask);
+	spin_unlock_irq(&phba->hbalock);
+}
+
+static int
+lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport)
+{
+	LPFC_MBOXQ_t *pmb;
+	MAILBOX_t *mb;
+	struct lpfc_dmabuf *mp;
+	int  rc;
+
+	pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!pmb) {
+		return -ENOMEM;
+	}
+	mb = &pmb->mb;
+
+	lpfc_read_sparam(phba, pmb, vport->vpi);
+	/*
+	 * Grab buffer pointer and clear context1 so we can use
+	 * lpfc_sli_issue_box_wait
+	 */
+	mp = (struct lpfc_dmabuf *) pmb->context1;
+	pmb->context1 = NULL;
+
+	pmb->vport = vport;
+	rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2);
+	if (rc != MBX_SUCCESS) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+				"%d (%d):1818 VPort failed init, mbxCmd x%x "
+				"READ_SPARM mbxStatus x%x, rc = x%x\n",
+				phba->brd_no, vport->vpi,
+				mb->mbxCommand, mb->mbxStatus, rc);
+		lpfc_mbuf_free(phba, mp->virt, mp->phys);
+		kfree(mp);
+		if (rc != MBX_TIMEOUT)
+			mempool_free(pmb, phba->mbox_mem_pool);
+		return -EIO;
+	}
+
+	memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
+	memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
+	       sizeof (struct lpfc_name));
+	memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
+	       sizeof (struct lpfc_name));
+
+	lpfc_mbuf_free(phba, mp->virt, mp->phys);
+	kfree(mp);
+	mempool_free(pmb, phba->mbox_mem_pool);
+
+	return 0;
+}
+
+static int
+lpfc_valid_wwn_format(struct lpfc_hba *phba, struct lpfc_name *wwn,
+		      const char *name_type)
+{
+				/* ensure that IEEE format 1 addresses
+				 * contain zeros in bits 59-48
+				 */
+	if (!((wwn->u.wwn[0] >> 4) == 1 &&
+	      ((wwn->u.wwn[0] & 0xf) != 0 || (wwn->u.wwn[1] & 0xf) != 0)))
+		return 1;
+
+	lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+			"%d:1822 Invalid %s: %02x:%02x:%02x:%02x:"
+			"%02x:%02x:%02x:%02x\n",
+			phba->brd_no, name_type,
+			wwn->u.wwn[0], wwn->u.wwn[1],
+			wwn->u.wwn[2], wwn->u.wwn[3],
+			wwn->u.wwn[4], wwn->u.wwn[5],
+			wwn->u.wwn[6], wwn->u.wwn[7]);
+	return 0;
+}
+
+static int
+lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport)
+{
+	struct lpfc_vport *vport;
+
+	list_for_each_entry(vport, &phba->port_list, listentry) {
+		if (vport == new_vport)
+			continue;
+		/* If they match, return not unique */
+		if (memcmp(&vport->fc_sparam.portName,
+			&new_vport->fc_sparam.portName,
+			sizeof(struct lpfc_name)) == 0)
+			return 0;
+	}
+	return 1;
+}
+
+int
+lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
+{
+	struct lpfc_nodelist *ndlp;
+	struct lpfc_vport *pport =
+		(struct lpfc_vport *) fc_vport->shost->hostdata;
+	struct lpfc_hba   *phba = pport->phba;
+	struct lpfc_vport *vport = NULL;
+	int instance;
+	int vpi;
+	int rc = VPORT_ERROR;
+
+	if ((phba->sli_rev < 3) ||
+		!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+				"%d:1808 Create VPORT failed: "
+				"NPIV is not enabled: SLImode:%d\n",
+				phba->brd_no, phba->sli_rev);
+		rc = VPORT_INVAL;
+		goto error_out;
+	}
+
+	vpi = lpfc_alloc_vpi(phba);
+	if (vpi == 0) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+				"%d:1809 Create VPORT failed: "
+				"Max VPORTs (%d) exceeded\n",
+				phba->brd_no, phba->max_vpi);
+		rc = VPORT_NORESOURCES;
+		goto error_out;
+	}
+
+
+	/* Assign an unused board number */
+	if ((instance = lpfc_get_instance()) < 0) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+				"%d:1810 Create VPORT failed: Cannot get "
+				"instance number\n", phba->brd_no);
+		lpfc_free_vpi(phba, vpi);
+		rc = VPORT_NORESOURCES;
+		goto error_out;
+	}
+
+	vport = lpfc_create_port(phba, instance, fc_vport);
+	if (!vport) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+				"%d:1811 Create VPORT failed: vpi x%x\n",
+				phba->brd_no, vpi);
+		lpfc_free_vpi(phba, vpi);
+		rc = VPORT_NORESOURCES;
+		goto error_out;
+	}
+
+	vport->vpi = vpi;
+	lpfc_debugfs_initialize(vport);
+
+	if (lpfc_vport_sparm(phba, vport)) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+				"%d:1813 Create VPORT failed: vpi:%d "
+				"Cannot get sparam\n",
+				phba->brd_no, vpi);
+		lpfc_free_vpi(phba, vpi);
+		destroy_port(vport);
+		rc = VPORT_NORESOURCES;
+		goto error_out;
+	}
+
+	memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8);
+	memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8);
+
+	if (fc_vport->node_name != 0)
+		u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
+	if (fc_vport->port_name != 0)
+		u64_to_wwn(fc_vport->port_name, vport->fc_portname.u.wwn);
+
+	memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8);
+	memcpy(&vport->fc_sparam.nodeName, vport->fc_nodename.u.wwn, 8);
+
+	if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") ||
+	    !lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+				"%d:1821 Create VPORT failed: vpi:%d "
+				"Invalid WWN format\n",
+				phba->brd_no, vpi);
+		lpfc_free_vpi(phba, vpi);
+		destroy_port(vport);
+		rc = VPORT_INVAL;
+		goto error_out;
+	}
+
+	if (!lpfc_unique_wwpn(phba, vport)) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+				"%d:1823 Create VPORT failed: vpi:%d "
+				"Duplicate WWN on HBA\n",
+				phba->brd_no, vpi);
+		lpfc_free_vpi(phba, vpi);
+		destroy_port(vport);
+		rc = VPORT_INVAL;
+		goto error_out;
+	}
+
+	*(struct lpfc_vport **)fc_vport->dd_data = vport;
+	vport->fc_vport = fc_vport;
+
+	if ((phba->link_state < LPFC_LINK_UP) ||
+	    (phba->fc_topology == TOPOLOGY_LOOP)) {
+		lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
+		rc = VPORT_OK;
+		goto out;
+	}
+
+	if (disable) {
+		rc = VPORT_OK;
+		goto out;
+	}
+
+	/* Use the Physical nodes Fabric NDLP to determine if the link is
+	 * up and ready to FDISC.
+	 */
+	ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+	if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
+		if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
+			lpfc_set_disctmo(vport);
+			lpfc_initial_fdisc(vport);
+		} else {
+			lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
+			lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+					"%d (%d):0262 No NPIV Fabric "
+					"support\n",
+					phba->brd_no, vport->vpi);
+		}
+	} else {
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+	}
+	rc = VPORT_OK;
+
+out:
+	lpfc_host_attrib_init(lpfc_shost_from_vport(vport));
+error_out:
+	return rc;
+}
+
+int
+disable_vport(struct fc_vport *fc_vport)
+{
+	struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
+	long timeout;
+
+	ndlp = lpfc_findnode_did(vport, Fabric_DID);
+	if (ndlp && phba->link_state >= LPFC_LINK_UP) {
+		vport->unreg_vpi_cmpl = VPORT_INVAL;
+		timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
+		if (!lpfc_issue_els_npiv_logo(vport, ndlp))
+			while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
+				timeout = schedule_timeout(timeout);
+	}
+
+	lpfc_sli_host_down(vport);
+
+	/* Mark all nodes for discovery so we can remove them by
+	 * calling lpfc_cleanup_rpis(vport, 1)
+	 */
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+			continue;
+		lpfc_disc_state_machine(vport, ndlp, NULL,
+					NLP_EVT_DEVICE_RECOVERY);
+	}
+	lpfc_cleanup_rpis(vport, 1);
+
+	lpfc_stop_vport_timers(vport);
+	lpfc_unreg_all_rpis(vport);
+	lpfc_unreg_default_rpis(vport);
+	/*
+	 * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
+	 * scsi_host_put() to release the vport.
+	 */
+	lpfc_mbx_unreg_vpi(vport);
+
+	lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
+	return VPORT_OK;
+}
+
+int
+enable_vport(struct fc_vport *fc_vport)
+{
+	struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
+	struct lpfc_hba   *phba = vport->phba;
+	struct lpfc_nodelist *ndlp = NULL;
+
+	if ((phba->link_state < LPFC_LINK_UP) ||
+	    (phba->fc_topology == TOPOLOGY_LOOP)) {
+		lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
+		return VPORT_OK;
+	}
+
+	vport->load_flag |= FC_LOADING;
+	vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+
+	/* Use the Physical nodes Fabric NDLP to determine if the link is
+	 * up and ready to FDISC.
+	 */
+	ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+	if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
+		if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
+			lpfc_set_disctmo(vport);
+			lpfc_initial_fdisc(vport);
+		} else {
+			lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
+			lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+					"%d (%d):0264 No NPIV Fabric "
+					"support\n",
+					phba->brd_no, vport->vpi);
+		}
+	} else {
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+	}
+
+	return VPORT_OK;
+}
+
+int
+lpfc_vport_disable(struct fc_vport *fc_vport, bool disable)
+{
+	if (disable)
+		return disable_vport(fc_vport);
+	else
+		return enable_vport(fc_vport);
+}
+
+
+int
+lpfc_vport_delete(struct fc_vport *fc_vport)
+{
+	struct lpfc_nodelist *ndlp = NULL;
+	struct lpfc_nodelist *next_ndlp;
+	struct Scsi_Host *shost = (struct Scsi_Host *) fc_vport->shost;
+	struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
+	struct lpfc_hba   *phba = vport->phba;
+	long timeout;
+	int rc = VPORT_ERROR;
+
+	/*
+	 * This is a bit of a mess.  We want to ensure the shost doesn't get
+	 * torn down until we're done with the embedded lpfc_vport structure.
+	 *
+	 * Beyond holding a reference for this function, we also need a
+	 * reference for outstanding I/O requests we schedule during delete
+	 * processing.  But once we scsi_remove_host() we can no longer obtain
+	 * a reference through scsi_host_get().
+	 *
+	 * So we take two references here.  We release one reference at the
+	 * bottom of the function -- after delinking the vport.  And we
+	 * release the other at the completion of the unreg_vpi that get's
+	 * initiated after we've disposed of all other resources associated
+	 * with the port.
+	 */
+	if (!scsi_host_get(shost) || !scsi_host_get(shost))
+		return VPORT_INVAL;
+
+	if (vport->port_type == LPFC_PHYSICAL_PORT) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+				"%d:1812 vport_delete failed: Cannot delete "
+				"physical host\n", phba->brd_no);
+		goto out;
+	}
+
+	vport->load_flag |= FC_UNLOADING;
+
+	kfree(vport->vname);
+	lpfc_debugfs_terminate(vport);
+	fc_remove_host(lpfc_shost_from_vport(vport));
+	scsi_remove_host(lpfc_shost_from_vport(vport));
+
+	ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+	if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
+		phba->link_state >= LPFC_LINK_UP) {
+
+		/* First look for the Fabric ndlp */
+		ndlp = lpfc_findnode_did(vport, Fabric_DID);
+		if (!ndlp) {
+			/* Cannot find existing Fabric ndlp, allocate one */
+			ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+			if (!ndlp)
+				goto skip_logo;
+			lpfc_nlp_init(vport, ndlp, Fabric_DID);
+		} else {
+			lpfc_dequeue_node(vport, ndlp);
+		}
+		vport->unreg_vpi_cmpl = VPORT_INVAL;
+		timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
+		if (!lpfc_issue_els_npiv_logo(vport, ndlp))
+			while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
+				timeout = schedule_timeout(timeout);
+	}
+
+skip_logo:
+	lpfc_sli_host_down(vport);
+
+	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+		lpfc_disc_state_machine(vport, ndlp, NULL,
+					     NLP_EVT_DEVICE_RECOVERY);
+		lpfc_disc_state_machine(vport, ndlp, NULL,
+					     NLP_EVT_DEVICE_RM);
+	}
+
+	lpfc_stop_vport_timers(vport);
+	lpfc_unreg_all_rpis(vport);
+	lpfc_unreg_default_rpis(vport);
+	/*
+	 * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
+	 * scsi_host_put() to release the vport.
+	 */
+	lpfc_mbx_unreg_vpi(vport);
+
+	lpfc_free_vpi(phba, vport->vpi);
+	vport->work_port_events = 0;
+	spin_lock_irq(&phba->hbalock);
+	list_del_init(&vport->listentry);
+	spin_unlock_irq(&phba->hbalock);
+
+	rc = VPORT_OK;
+out:
+	scsi_host_put(shost);
+	return rc;
+}
+
+
+EXPORT_SYMBOL(lpfc_vport_create);
+EXPORT_SYMBOL(lpfc_vport_delete);
diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h
new file mode 100644
index 0000000..f223550
--- /dev/null
+++ b/drivers/scsi/lpfc/lpfc_vport.h
@@ -0,0 +1,113 @@
+/*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for         *
+ * Fibre Channel Host Bus Adapters.                                *
+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+ * EMULEX and SLI are trademarks of Emulex.                        *
+ * www.emulex.com                                                  *
+ * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
+ *                                                                 *
+ * This program is free software; you can redistribute it and/or   *
+ * modify it under the terms of version 2 of the GNU General       *
+ * Public License as published by the Free Software Foundation.    *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+ * more details, a copy of which can be found in the file COPYING  *
+ * included with this package.                                     *
+ *******************************************************************/
+
+#ifndef _H_LPFC_VPORT
+#define _H_LPFC_VPORT
+
+/* API version values (each will be an individual bit) */
+#define VPORT_API_VERSION_1	0x01
+
+/* Values returned via lpfc_vport_getinfo() */
+struct vport_info {
+
+	uint32_t api_versions;
+	uint8_t linktype;
+#define  VPORT_TYPE_PHYSICAL	0
+#define  VPORT_TYPE_VIRTUAL	1
+
+	uint8_t state;
+#define  VPORT_STATE_OFFLINE	0
+#define  VPORT_STATE_ACTIVE	1
+#define  VPORT_STATE_FAILED	2
+
+	uint8_t fail_reason;
+	uint8_t prev_fail_reason;
+#define  VPORT_FAIL_UNKNOWN	0
+#define  VPORT_FAIL_LINKDOWN	1
+#define  VPORT_FAIL_FAB_UNSUPPORTED	2
+#define  VPORT_FAIL_FAB_NORESOURCES	3
+#define  VPORT_FAIL_FAB_LOGOUT	4
+#define  VPORT_FAIL_ADAP_NORESOURCES	5
+
+	uint8_t node_name[8];	/* WWNN */
+	uint8_t port_name[8];	/* WWPN */
+
+	struct Scsi_Host *shost;
+
+/* Following values are valid only on physical links */
+	uint32_t vports_max;
+	uint32_t vports_inuse;
+	uint32_t rpi_max;
+	uint32_t rpi_inuse;
+#define  VPORT_CNT_INVALID	0xFFFFFFFF
+};
+
+/* data used  in link creation */
+struct vport_data {
+	uint32_t api_version;
+
+	uint32_t options;
+#define  VPORT_OPT_AUTORETRY	0x01
+
+	uint8_t node_name[8];	/* WWNN */
+	uint8_t port_name[8];	/* WWPN */
+
+/*
+ *  Upon successful creation, vport_shost will point to the new Scsi_Host
+ *  structure for the new virtual link.
+ */
+	struct Scsi_Host *vport_shost;
+};
+
+/* API function return codes */
+#define VPORT_OK	0
+#define VPORT_ERROR	-1
+#define VPORT_INVAL	-2
+#define VPORT_NOMEM	-3
+#define VPORT_NORESOURCES	-4
+
+int lpfc_vport_create(struct fc_vport *, bool);
+int lpfc_vport_delete(struct fc_vport *);
+int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
+int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
+
+/*
+ *  queuecommand  VPORT-specific return codes. Specified in  the host byte code.
+ *  Returned when the virtual link has failed or is not active.
+ */
+#define  DID_VPORT_ERROR	0x0f
+
+#define VPORT_INFO	0x1
+#define VPORT_CREATE	0x2
+#define VPORT_DELETE	0x4
+
+struct vport_cmd_tag {
+	uint32_t cmd;
+	struct vport_data cdata;
+	struct vport_info cinfo;
+	void *vport;
+	int vport_num;
+};
+
+void lpfc_vport_set_state(struct lpfc_vport *vport,
+			  enum fc_vport_state new_state);
+
+#endif /* H_LPFC_VPORT */
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 5806ede..b12ad7c7 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -77,7 +77,7 @@
 		for (i = 0; i < cmd->cmd_len; ++i)
 			printk(" %.2x", cmd->cmnd[i]);
 		printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
-		       cmd->use_sg, cmd->request_bufflen, cmd->request_buffer);
+		       scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd));
 	}
 #endif
 
@@ -173,8 +173,7 @@
 	writeb(CMD_SELECT, &regs->command);
 	state->phase = selecting;
 
-	if (cmd->use_sg > 0 || cmd->request_bufflen != 0)
-		set_dma_cmds(state, cmd);
+	set_dma_cmds(state, cmd);
 }
 
 static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id)
@@ -262,7 +261,7 @@
 		writeb(CMD_NOP, &regs->command);
 		/* set DMA controller going if any data to transfer */
 		if ((stat & (STAT_MSG|STAT_CD)) == 0
-		    && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) {
+		    && (scsi_sg_count(cmd) > 0 || scsi_bufflen(cmd))) {
 			nb = cmd->SCp.this_residual;
 			if (nb > 0xfff0)
 				nb = 0xfff0;
@@ -310,14 +309,7 @@
 			printk(KERN_DEBUG "intr %x before data xfer complete\n", intr);
 		}
 		writel(RUN << 16, &dma->control);	/* stop dma */
-		if (cmd->use_sg != 0) {
-			pci_unmap_sg(state->pdev,
-				(struct scatterlist *)cmd->request_buffer,
-				cmd->use_sg, cmd->sc_data_direction);
-		} else {
-			pci_unmap_single(state->pdev, state->dma_addr,
-				cmd->request_bufflen, cmd->sc_data_direction);
-		}
+		scsi_dma_unmap(cmd);
 		/* should check dma status */
 		writeb(CMD_I_COMPLETE, &regs->command);
 		state->phase = completing;
@@ -365,47 +357,35 @@
  */
 static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
 {
-	int i, dma_cmd, total;
+	int i, dma_cmd, total, nseg;
 	struct scatterlist *scl;
 	struct dbdma_cmd *dcmds;
 	dma_addr_t dma_addr;
 	u32 dma_len;
 
+	nseg = scsi_dma_map(cmd);
+	BUG_ON(nseg < 0);
+	if (!nseg)
+		return;
+
 	dma_cmd = cmd->sc_data_direction == DMA_TO_DEVICE ?
 			OUTPUT_MORE : INPUT_MORE;
 	dcmds = state->dma_cmds;
-	if (cmd->use_sg > 0) {
-		int nseg;
+	total = 0;
 
-		total = 0;
-		scl = (struct scatterlist *) cmd->request_buffer;
-		nseg = pci_map_sg(state->pdev, scl, cmd->use_sg,
-				cmd->sc_data_direction);
-		for (i = 0; i < nseg; ++i) {
-			dma_addr = sg_dma_address(scl);
-			dma_len = sg_dma_len(scl);
-			if (dma_len > 0xffff)
-				panic("mac53c94: scatterlist element >= 64k");
-			total += dma_len;
-			st_le16(&dcmds->req_count, dma_len);
-			st_le16(&dcmds->command, dma_cmd);
-			st_le32(&dcmds->phy_addr, dma_addr);
-			dcmds->xfer_status = 0;
-			++scl;
-			++dcmds;
-		}
-	} else {
-		total = cmd->request_bufflen;
-		if (total > 0xffff)
-			panic("mac53c94: transfer size >= 64k");
-		dma_addr = pci_map_single(state->pdev, cmd->request_buffer,
-					  total, cmd->sc_data_direction);
-		state->dma_addr = dma_addr;
-		st_le16(&dcmds->req_count, total);
+	scsi_for_each_sg(cmd, scl, nseg, i) {
+		dma_addr = sg_dma_address(scl);
+		dma_len = sg_dma_len(scl);
+		if (dma_len > 0xffff)
+			panic("mac53c94: scatterlist element >= 64k");
+		total += dma_len;
+		st_le16(&dcmds->req_count, dma_len);
+		st_le16(&dcmds->command, dma_cmd);
 		st_le32(&dcmds->phy_addr, dma_addr);
 		dcmds->xfer_status = 0;
 		++dcmds;
 	}
+
 	dma_cmd += OUTPUT_LAST - OUTPUT_MORE;
 	st_le16(&dcmds[-1].command, dma_cmd);
 	st_le16(&dcmds->command, DBDMA_STOP);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 3cce75d..3907f67 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -523,10 +523,8 @@
 	/*
 	 * filter the internal and ioctl commands
 	 */
-	if((cmd->cmnd[0] == MEGA_INTERNAL_CMD)) {
-		return cmd->request_buffer;
-	}
-
+	if((cmd->cmnd[0] == MEGA_INTERNAL_CMD))
+		return (scb_t *)cmd->host_scribble;
 
 	/*
 	 * We know what channels our logical drives are on - mega_find_card()
@@ -657,22 +655,14 @@
 
 		case MODE_SENSE: {
 			char *buf;
+			struct scatterlist *sg;
 
-			if (cmd->use_sg) {
-				struct scatterlist *sg;
+			sg = scsi_sglist(cmd);
+			buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
 
-				sg = (struct scatterlist *)cmd->request_buffer;
-				buf = kmap_atomic(sg->page, KM_IRQ0) +
-					sg->offset;
-			} else
-				buf = cmd->request_buffer;
 			memset(buf, 0, cmd->cmnd[4]);
-			if (cmd->use_sg) {
-				struct scatterlist *sg;
+			kunmap_atomic(buf - sg->offset, KM_IRQ0);
 
-				sg = (struct scatterlist *)cmd->request_buffer;
-				kunmap_atomic(buf - sg->offset, KM_IRQ0);
-			}
 			cmd->result = (DID_OK << 16);
 			cmd->scsi_done(cmd);
 			return NULL;
@@ -1551,23 +1541,15 @@
 		islogical = adapter->logdrv_chan[cmd->device->channel];
 		if( cmd->cmnd[0] == INQUIRY && !islogical ) {
 
-			if( cmd->use_sg ) {
-				sgl = (struct scatterlist *)
-					cmd->request_buffer;
-
-				if( sgl->page ) {
-					c = *(unsigned char *)
+			sgl = scsi_sglist(cmd);
+			if( sgl->page ) {
+				c = *(unsigned char *)
 					page_address((&sgl[0])->page) +
 					(&sgl[0])->offset; 
-				}
-				else {
-					printk(KERN_WARNING
-						"megaraid: invalid sg.\n");
-					c = 0;
-				}
-			}
-			else {
-				c = *(u8 *)cmd->request_buffer;
+			} else {
+				printk(KERN_WARNING
+				       "megaraid: invalid sg.\n");
+				c = 0;
 			}
 
 			if(IS_RAID_CH(adapter, cmd->device->channel) &&
@@ -1704,30 +1686,14 @@
 static void
 mega_free_scb(adapter_t *adapter, scb_t *scb)
 {
-	unsigned long length;
-
 	switch( scb->dma_type ) {
 
 	case MEGA_DMA_TYPE_NONE:
 		break;
 
-	case MEGA_BULK_DATA:
-		if (scb->cmd->use_sg == 0)
-			length = scb->cmd->request_bufflen;
-		else {
-			struct scatterlist *sgl =
-				(struct scatterlist *)scb->cmd->request_buffer;
-			length = sgl->length;
-		}
-		pci_unmap_page(adapter->dev, scb->dma_h_bulkdata,
-			       length, scb->dma_direction);
-		break;
-
 	case MEGA_SGLIST:
-		pci_unmap_sg(adapter->dev, scb->cmd->request_buffer,
-			scb->cmd->use_sg, scb->dma_direction);
+		scsi_dma_unmap(scb->cmd);
 		break;
-
 	default:
 		break;
 	}
@@ -1767,80 +1733,33 @@
 static int
 mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
 {
-	struct scatterlist	*sgl;
-	struct page	*page;
-	unsigned long	offset;
-	unsigned int	length;
+	struct scatterlist *sg;
 	Scsi_Cmnd	*cmd;
 	int	sgcnt;
 	int	idx;
 
 	cmd = scb->cmd;
 
-	/* Scatter-gather not used */
-	if( cmd->use_sg == 0 || (cmd->use_sg == 1 && 
-				 !adapter->has_64bit_addr)) {
-
-		if (cmd->use_sg == 0) {
-			page = virt_to_page(cmd->request_buffer);
-			offset = offset_in_page(cmd->request_buffer);
-			length = cmd->request_bufflen;
-		} else {
-			sgl = (struct scatterlist *)cmd->request_buffer;
-			page = sgl->page;
-			offset = sgl->offset;
-			length = sgl->length;
-		}
-
-		scb->dma_h_bulkdata = pci_map_page(adapter->dev,
-						  page, offset,
-						  length,
-						  scb->dma_direction);
-		scb->dma_type = MEGA_BULK_DATA;
-
-		/*
-		 * We need to handle special 64-bit commands that need a
-		 * minimum of 1 SG
-		 */
-		if( adapter->has_64bit_addr ) {
-			scb->sgl64[0].address = scb->dma_h_bulkdata;
-			scb->sgl64[0].length = length;
-			*buf = (u32)scb->sgl_dma_addr;
-			*len = (u32)length;
-			return 1;
-		}
-		else {
-			*buf = (u32)scb->dma_h_bulkdata;
-			*len = (u32)length;
-		}
-		return 0;
-	}
-
-	sgl = (struct scatterlist *)cmd->request_buffer;
-
 	/*
 	 * Copy Scatter-Gather list info into controller structure.
 	 *
 	 * The number of sg elements returned must not exceed our limit
 	 */
-	sgcnt = pci_map_sg(adapter->dev, sgl, cmd->use_sg,
-			scb->dma_direction);
+	sgcnt = scsi_dma_map(cmd);
 
 	scb->dma_type = MEGA_SGLIST;
 
-	BUG_ON(sgcnt > adapter->sglen);
+	BUG_ON(sgcnt > adapter->sglen || sgcnt < 0);
 
 	*len = 0;
 
-	for( idx = 0; idx < sgcnt; idx++, sgl++ ) {
-
-		if( adapter->has_64bit_addr ) {
-			scb->sgl64[idx].address = sg_dma_address(sgl);
-			*len += scb->sgl64[idx].length = sg_dma_len(sgl);
-		}
-		else {
-			scb->sgl[idx].address = sg_dma_address(sgl);
-			*len += scb->sgl[idx].length = sg_dma_len(sgl);
+	scsi_for_each_sg(cmd, sg, sgcnt, idx) {
+		if (adapter->has_64bit_addr) {
+			scb->sgl64[idx].address = sg_dma_address(sg);
+			*len += scb->sgl64[idx].length = sg_dma_len(sg);
+		} else {
+			scb->sgl[idx].address = sg_dma_address(sg);
+			*len += scb->sgl[idx].length = sg_dma_len(sg);
 		}
 	}
 
@@ -3571,7 +3490,7 @@
 			/*
 			 * The user passthru structure
 			 */
-			upthru = (mega_passthru __user *)MBOX(uioc)->xferaddr;
+			upthru = (mega_passthru __user *)(unsigned long)MBOX(uioc)->xferaddr;
 
 			/*
 			 * Copy in the user passthru here.
@@ -3623,7 +3542,7 @@
 				/*
 				 * Get the user data
 				 */
-				if( copy_from_user(data, (char __user *)uxferaddr,
+				if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
 							pthru->dataxferlen) ) {
 					rval = (-EFAULT);
 					goto freemem_and_return;
@@ -3649,7 +3568,7 @@
 			 * Is data going up-stream
 			 */
 			if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) {
-				if( copy_to_user((char __user *)uxferaddr, data,
+				if( copy_to_user((char __user *)(unsigned long) uxferaddr, data,
 							pthru->dataxferlen) ) {
 					rval = (-EFAULT);
 				}
@@ -3702,7 +3621,7 @@
 				/*
 				 * Get the user data
 				 */
-				if( copy_from_user(data, (char __user *)uxferaddr,
+				if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
 							uioc.xferlen) ) {
 
 					pci_free_consistent(pdev,
@@ -3742,7 +3661,7 @@
 			 * Is data going up-stream
 			 */
 			if( uioc.xferlen && (uioc.flags & UIOC_RD) ) {
-				if( copy_to_user((char __user *)uxferaddr, data,
+				if( copy_to_user((char __user *)(unsigned long) uxferaddr, data,
 							uioc.xferlen) ) {
 
 					rval = (-EFAULT);
@@ -4494,7 +4413,7 @@
 	scmd->device = sdev;
 
 	scmd->device->host = adapter->host;
-	scmd->request_buffer = (void *)scb;
+	scmd->host_scribble = (void *)scb;
 	scmd->cmnd[0] = MEGA_INTERNAL_CMD;
 
 	scb->state |= SCB_ACTIVE;
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
index 26e1e6c..fef9ac9 100644
--- a/drivers/scsi/megaraid/mega_common.h
+++ b/drivers/scsi/megaraid/mega_common.h
@@ -21,6 +21,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 04d0b69..c46685a 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -1378,8 +1378,6 @@
 {
 	struct scatterlist	*sgl;
 	mbox_ccb_t		*ccb;
-	struct page		*page;
-	unsigned long		offset;
 	struct scsi_cmnd	*scp;
 	int			sgcnt;
 	int			i;
@@ -1388,48 +1386,16 @@
 	scp	= scb->scp;
 	ccb	= (mbox_ccb_t *)scb->ccb;
 
+	sgcnt = scsi_dma_map(scp);
+	BUG_ON(sgcnt < 0 || sgcnt > adapter->sglen);
+
 	// no mapping required if no data to be transferred
-	if (!scp->request_buffer || !scp->request_bufflen)
+	if (!sgcnt)
 		return 0;
 
-	if (!scp->use_sg) {	/* scatter-gather list not used */
-
-		page = virt_to_page(scp->request_buffer);
-
-		offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK);
-
-		ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset,
-						  scp->request_bufflen,
-						  scb->dma_direction);
-		scb->dma_type = MRAID_DMA_WBUF;
-
-		/*
-		 * We need to handle special 64-bit commands that need a
-		 * minimum of 1 SG
-		 */
-		sgcnt = 1;
-		ccb->sgl64[0].address	= ccb->buf_dma_h;
-		ccb->sgl64[0].length	= scp->request_bufflen;
-
-		return sgcnt;
-	}
-
-	sgl = (struct scatterlist *)scp->request_buffer;
-
-	// The number of sg elements returned must not exceed our limit
-	sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg,
-			scb->dma_direction);
-
-	if (sgcnt > adapter->sglen) {
-		con_log(CL_ANN, (KERN_CRIT
-			"megaraid critical: too many sg elements:%d\n",
-			sgcnt));
-		BUG();
-	}
-
 	scb->dma_type = MRAID_DMA_WSG;
 
-	for (i = 0; i < sgcnt; i++, sgl++) {
+	scsi_for_each_sg(scp, sgl, sgcnt, i) {
 		ccb->sgl64[i].address	= sg_dma_address(sgl);
 		ccb->sgl64[i].length	= sg_dma_len(sgl);
 	}
@@ -1489,19 +1455,11 @@
 
 	adapter->outstanding_cmds++;
 
-	if (scb->dma_direction == PCI_DMA_TODEVICE) {
-		if (!scb->scp->use_sg) {	// sg list not used
-			pci_dma_sync_single_for_device(adapter->pdev,
-					ccb->buf_dma_h,
-					scb->scp->request_bufflen,
-					PCI_DMA_TODEVICE);
-		}
-		else {
-			pci_dma_sync_sg_for_device(adapter->pdev,
-				scb->scp->request_buffer,
-				scb->scp->use_sg, PCI_DMA_TODEVICE);
-		}
-	}
+	if (scb->dma_direction == PCI_DMA_TODEVICE)
+		pci_dma_sync_sg_for_device(adapter->pdev,
+					   scsi_sglist(scb->scp),
+					   scsi_sg_count(scb->scp),
+					   PCI_DMA_TODEVICE);
 
 	mbox->busy	= 1;	// Set busy
 	mbox->poll	= 0;
@@ -1624,29 +1582,26 @@
 			return scb;
 
 		case MODE_SENSE:
-			if (scp->use_sg) {
-				struct scatterlist	*sgl;
-				caddr_t			vaddr;
+		{
+			struct scatterlist	*sgl;
+			caddr_t			vaddr;
 
-				sgl = (struct scatterlist *)scp->request_buffer;
-				if (sgl->page) {
-					vaddr = (caddr_t)
-						(page_address((&sgl[0])->page)
-						+ (&sgl[0])->offset);
+			sgl = scsi_sglist(scp);
+			if (sgl->page) {
+				vaddr = (caddr_t)
+					(page_address((&sgl[0])->page)
+					 + (&sgl[0])->offset);
 
-					memset(vaddr, 0, scp->cmnd[4]);
-				}
-				else {
-					con_log(CL_ANN, (KERN_WARNING
-					"megaraid mailbox: invalid sg:%d\n",
-					__LINE__));
-				}
+				memset(vaddr, 0, scp->cmnd[4]);
 			}
 			else {
-				memset(scp->request_buffer, 0, scp->cmnd[4]);
+				con_log(CL_ANN, (KERN_WARNING
+						 "megaraid mailbox: invalid sg:%d\n",
+						 __LINE__));
 			}
-			scp->result = (DID_OK << 16);
-			return NULL;
+		}
+		scp->result = (DID_OK << 16);
+		return NULL;
 
 		case INQUIRY:
 			/*
@@ -1716,7 +1671,7 @@
 			mbox->cmd		= MBOXCMD_PASSTHRU64;
 			scb->dma_direction	= scp->sc_data_direction;
 
-			pthru->dataxferlen	= scp->request_bufflen;
+			pthru->dataxferlen	= scsi_bufflen(scp);
 			pthru->dataxferaddr	= ccb->sgl_dma_h;
 			pthru->numsge		= megaraid_mbox_mksgl(adapter,
 							scb);
@@ -2050,8 +2005,8 @@
 
 	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
 
-	if (scp->request_bufflen) {
-		pthru->dataxferlen	= scp->request_bufflen;
+	if (scsi_bufflen(scp)) {
+		pthru->dataxferlen	= scsi_bufflen(scp);
 		pthru->dataxferaddr	= ccb->sgl_dma_h;
 		pthru->numsge		= megaraid_mbox_mksgl(adapter, scb);
 	}
@@ -2099,8 +2054,8 @@
 
 	memcpy(epthru->cdb, scp->cmnd, scp->cmd_len);
 
-	if (scp->request_bufflen) {
-		epthru->dataxferlen	= scp->request_bufflen;
+	if (scsi_bufflen(scp)) {
+		epthru->dataxferlen	= scsi_bufflen(scp);
 		epthru->dataxferaddr	= ccb->sgl_dma_h;
 		epthru->numsge		= megaraid_mbox_mksgl(adapter, scb);
 	}
@@ -2266,37 +2221,13 @@
 
 	ccb	= (mbox_ccb_t *)scb->ccb;
 
-	switch (scb->dma_type) {
-
-	case MRAID_DMA_WBUF:
-		if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
-			pci_dma_sync_single_for_cpu(adapter->pdev,
-					ccb->buf_dma_h,
-					scb->scp->request_bufflen,
+	if (scb->dma_direction == PCI_DMA_FROMDEVICE)
+		pci_dma_sync_sg_for_cpu(adapter->pdev,
+					scsi_sglist(scb->scp),
+					scsi_sg_count(scb->scp),
 					PCI_DMA_FROMDEVICE);
-		}
 
-		pci_unmap_page(adapter->pdev, ccb->buf_dma_h,
-			scb->scp->request_bufflen, scb->dma_direction);
-
-		break;
-
-	case MRAID_DMA_WSG:
-		if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
-			pci_dma_sync_sg_for_cpu(adapter->pdev,
-					scb->scp->request_buffer,
-					scb->scp->use_sg, PCI_DMA_FROMDEVICE);
-		}
-
-		pci_unmap_sg(adapter->pdev, scb->scp->request_buffer,
-			scb->scp->use_sg, scb->dma_direction);
-
-		break;
-
-	default:
-		break;
-	}
-
+	scsi_dma_unmap(scb->scp);
 	return;
 }
 
@@ -2399,24 +2330,16 @@
 		if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
 				&& IS_RAID_CH(raid_dev, scb->dev_channel)) {
 
-			if (scp->use_sg) {
-				sgl = (struct scatterlist *)
-					scp->request_buffer;
-
-				if (sgl->page) {
-					c = *(unsigned char *)
+			sgl = scsi_sglist(scp);
+			if (sgl->page) {
+				c = *(unsigned char *)
 					(page_address((&sgl[0])->page) +
-						(&sgl[0])->offset);
-				}
-				else {
-					con_log(CL_ANN, (KERN_WARNING
-					"megaraid mailbox: invalid sg:%d\n",
-					__LINE__));
-					c = 0;
-				}
-			}
-			else {
-				c = *(uint8_t *)scp->request_buffer;
+					 (&sgl[0])->offset);
+			} else {
+				con_log(CL_ANN, (KERN_WARNING
+						 "megaraid mailbox: invalid sg:%d\n",
+						 __LINE__));
+				c = 0;
 			}
 
 			if ((c & 0x1F ) == TYPE_DISK) {
@@ -3957,7 +3880,7 @@
 		megaraid_sysfs_free_resources(adapter);
 	}
 
-	sema_init(&raid_dev->sysfs_sem, 1);
+	mutex_init(&raid_dev->sysfs_mtx);
 
 	init_waitqueue_head(&raid_dev->sysfs_wait_q);
 
@@ -4058,7 +3981,7 @@
 	/*
 	 * Allow only one read at a time to go through the sysfs attributes
 	 */
-	down(&raid_dev->sysfs_sem);
+	mutex_lock(&raid_dev->sysfs_mtx);
 
 	uioc	= raid_dev->sysfs_uioc;
 	mbox64	= raid_dev->sysfs_mbox64;
@@ -4134,7 +4057,7 @@
 
 	del_timer_sync(timerp);
 
-	up(&raid_dev->sysfs_sem);
+	mutex_unlock(&raid_dev->sysfs_mtx);
 
 	return rval;
 }
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 9de803c..626459d 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -168,7 +168,7 @@
  * @hw_error			: set if FW not responding
  * @fast_load			: If set, skip physical device scanning
  * @channel_class		: channel class, RAID or SCSI
- * @sysfs_sem			: semaphore to serialize access to sysfs res.
+ * @sysfs_mtx			: mutex to serialize access to sysfs res.
  * @sysfs_uioc			: management packet to issue FW calls from sysfs
  * @sysfs_mbox64		: mailbox packet to issue FW calls from sysfs
  * @sysfs_buffer		: data buffer for FW commands issued from sysfs
@@ -208,7 +208,7 @@
 	int				hw_error;
 	int				fast_load;
 	uint8_t				channel_class;
-	struct semaphore		sysfs_sem;
+	struct mutex			sysfs_mtx;
 	uioc_t				*sysfs_uioc;
 	mbox64_t			*sysfs_mbox64;
 	caddr_t				sysfs_buffer;
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index e075a52..84d9c27 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -14,7 +14,7 @@
  *
  * Common management module
  */
-
+#include <linux/sched.h>
 #include "megaraid_mm.h"
 
 
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 7a81267..b7f2e61 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_sas.c
- * Version	: v00.00.03.10-rc1
+ * Version	: v00.00.03.10-rc5
  *
  * Authors:
  *	(email-id : megaraidlinux@lsi.com)
@@ -433,34 +433,15 @@
 	int sge_count;
 	struct scatterlist *os_sgl;
 
-	/*
-	 * Return 0 if there is no data transfer
-	 */
-	if (!scp->request_buffer || !scp->request_bufflen)
-		return 0;
+	sge_count = scsi_dma_map(scp);
+	BUG_ON(sge_count < 0);
 
-	if (!scp->use_sg) {
-		mfi_sgl->sge32[0].phys_addr = pci_map_single(instance->pdev,
-							     scp->
-							     request_buffer,
-							     scp->
-							     request_bufflen,
-							     scp->
-							     sc_data_direction);
-		mfi_sgl->sge32[0].length = scp->request_bufflen;
-
-		return 1;
+	if (sge_count) {
+		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+			mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
+			mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
+		}
 	}
-
-	os_sgl = (struct scatterlist *)scp->request_buffer;
-	sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
-			       scp->sc_data_direction);
-
-	for (i = 0; i < sge_count; i++, os_sgl++) {
-		mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
-		mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
-	}
-
 	return sge_count;
 }
 
@@ -481,35 +462,15 @@
 	int sge_count;
 	struct scatterlist *os_sgl;
 
-	/*
-	 * Return 0 if there is no data transfer
-	 */
-	if (!scp->request_buffer || !scp->request_bufflen)
-		return 0;
+	sge_count = scsi_dma_map(scp);
+	BUG_ON(sge_count < 0);
 
-	if (!scp->use_sg) {
-		mfi_sgl->sge64[0].phys_addr = pci_map_single(instance->pdev,
-							     scp->
-							     request_buffer,
-							     scp->
-							     request_bufflen,
-							     scp->
-							     sc_data_direction);
-
-		mfi_sgl->sge64[0].length = scp->request_bufflen;
-
-		return 1;
+	if (sge_count) {
+		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+			mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
+			mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
+		}
 	}
-
-	os_sgl = (struct scatterlist *)scp->request_buffer;
-	sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
-			       scp->sc_data_direction);
-
-	for (i = 0; i < sge_count; i++, os_sgl++) {
-		mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
-		mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
-	}
-
 	return sge_count;
 }
 
@@ -593,7 +554,7 @@
 	pthru->cdb_len = scp->cmd_len;
 	pthru->timeout = 0;
 	pthru->flags = flags;
-	pthru->data_xfer_len = scp->request_bufflen;
+	pthru->data_xfer_len = scsi_bufflen(scp);
 
 	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
 
@@ -886,6 +847,7 @@
 		goto out_return_cmd;
 
 	cmd->scmd = scmd;
+	scmd->SCp.ptr = (char *)cmd;
 
 	/*
 	 * Issue the command to the FW
@@ -919,7 +881,7 @@
 	 * The RAID firmware may require extended timeouts.
 	 */
 	if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
-		sdev->timeout = 90 * HZ;
+		sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
 	return 0;
 }
 
@@ -981,8 +943,8 @@
 
 	instance = (struct megasas_instance *)scmd->device->host->hostdata;
 
-	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x\n",
-	       scmd->serial_number, scmd->cmnd[0]);
+	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
+		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
 
 	if (instance->hw_crit_error) {
 		printk(KERN_ERR "megasas: cannot recover from previous reset "
@@ -1000,6 +962,39 @@
 }
 
 /**
+ * megasas_reset_timer - quiesce the adapter if required
+ * @scmd:		scsi cmnd
+ *
+ * Sets the FW busy flag and reduces the host->can_queue if the
+ * cmd has not been completed within the timeout period.
+ */
+static enum
+scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+{
+	struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
+	struct megasas_instance *instance;
+	unsigned long flags;
+
+	if (time_after(jiffies, scmd->jiffies_at_alloc +
+				(MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
+		return EH_NOT_HANDLED;
+	}
+
+	instance = cmd->instance;
+	if (!(instance->flag & MEGASAS_FW_BUSY)) {
+		/* FW is busy, throttle IO */
+		spin_lock_irqsave(instance->host->host_lock, flags);
+
+		instance->host->can_queue = 16;
+		instance->last_time = jiffies;
+		instance->flag |= MEGASAS_FW_BUSY;
+
+		spin_unlock_irqrestore(instance->host->host_lock, flags);
+	}
+	return EH_RESET_TIMER;
+}
+
+/**
  * megasas_reset_device -	Device reset handler entry point
  */
 static int megasas_reset_device(struct scsi_cmnd *scmd)
@@ -1112,6 +1107,7 @@
 	.eh_device_reset_handler = megasas_reset_device,
 	.eh_bus_reset_handler = megasas_reset_bus_host,
 	.eh_host_reset_handler = megasas_reset_bus_host,
+	.eh_timed_out = megasas_reset_timer,
 	.bios_param = megasas_bios_param,
 	.use_clustering = ENABLE_CLUSTERING,
 };
@@ -1160,45 +1156,6 @@
 }
 
 /**
- * megasas_unmap_sgbuf -	Unmap SG buffers
- * @instance:			Adapter soft state
- * @cmd:			Completed command
- */
-static void
-megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
-{
-	dma_addr_t buf_h;
-	u8 opcode;
-
-	if (cmd->scmd->use_sg) {
-		pci_unmap_sg(instance->pdev, cmd->scmd->request_buffer,
-			     cmd->scmd->use_sg, cmd->scmd->sc_data_direction);
-		return;
-	}
-
-	if (!cmd->scmd->request_bufflen)
-		return;
-
-	opcode = cmd->frame->hdr.cmd;
-
-	if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) {
-		if (IS_DMA64)
-			buf_h = cmd->frame->io.sgl.sge64[0].phys_addr;
-		else
-			buf_h = cmd->frame->io.sgl.sge32[0].phys_addr;
-	} else {
-		if (IS_DMA64)
-			buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr;
-		else
-			buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr;
-	}
-
-	pci_unmap_single(instance->pdev, buf_h, cmd->scmd->request_bufflen,
-			 cmd->scmd->sc_data_direction);
-	return;
-}
-
-/**
  * megasas_complete_cmd -	Completes a command
  * @instance:			Adapter soft state
  * @cmd:			Command to be completed
@@ -1215,9 +1172,8 @@
 	int exception = 0;
 	struct megasas_header *hdr = &cmd->frame->hdr;
 
-	if (cmd->scmd) {
-		cmd->scmd->SCp.ptr = (char *)0;
-	}
+	if (cmd->scmd)
+		cmd->scmd->SCp.ptr = NULL;
 
 	switch (hdr->cmd) {
 
@@ -1247,7 +1203,7 @@
 
 			atomic_dec(&instance->fw_outstanding);
 
-			megasas_unmap_sgbuf(instance, cmd);
+			scsi_dma_unmap(cmd->scmd);
 			cmd->scmd->scsi_done(cmd->scmd);
 			megasas_return_cmd(instance, cmd);
 
@@ -1295,7 +1251,7 @@
 
 		atomic_dec(&instance->fw_outstanding);
 
-		megasas_unmap_sgbuf(instance, cmd);
+		scsi_dma_unmap(cmd->scmd);
 		cmd->scmd->scsi_done(cmd->scmd);
 		megasas_return_cmd(instance, cmd);
 
@@ -1806,6 +1762,7 @@
 	u32 context;
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
+	unsigned long flags;
 
 	/* If we have already declared adapter dead, donot complete cmds */
 	if (instance->hw_crit_error)
@@ -1828,6 +1785,22 @@
 	}
 
 	*instance->consumer = producer;
+
+	/*
+	 * Check if we can restore can_queue
+	 */
+	if (instance->flag & MEGASAS_FW_BUSY
+		&& time_after(jiffies, instance->last_time + 5 * HZ)
+		&& atomic_read(&instance->fw_outstanding) < 17) {
+
+		spin_lock_irqsave(instance->host->host_lock, flags);
+		instance->flag &= ~MEGASAS_FW_BUSY;
+		instance->host->can_queue =
+				instance->max_fw_cmds - MEGASAS_INT_CMDS;
+
+		spin_unlock_irqrestore(instance->host->host_lock, flags);
+	}
+
 }
 
 /**
@@ -2398,6 +2371,8 @@
 	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
 
 	megasas_dbg_lvl = 0;
+	instance->flag = 0;
+	instance->last_time = 0;
 
 	/*
 	 * Initialize MFI Firmware
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index e862992..4dffc91 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -18,9 +18,9 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION				"00.00.03.10-rc1"
-#define MEGASAS_RELDATE				"Feb 14, 2007"
-#define MEGASAS_EXT_VERSION			"Wed Feb 14 10:14:25 PST 2007"
+#define MEGASAS_VERSION				"00.00.03.10-rc5"
+#define MEGASAS_RELDATE				"May 17, 2007"
+#define MEGASAS_EXT_VERSION			"Thu May 17 10:09:32 PDT 2007"
 
 /*
  * Device IDs
@@ -539,6 +539,8 @@
 
 #define MEGASAS_DBG_LVL				1
 
+#define MEGASAS_FW_BUSY				1
+
 /*
  * When SCSI mid-layer calls driver's reset routine, driver waits for
  * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
@@ -549,8 +551,8 @@
 #define MEGASAS_RESET_WAIT_TIME			180
 #define MEGASAS_INTERNAL_CMD_WAIT_TIME		180
 #define	MEGASAS_RESET_NOTICE_INTERVAL		5
-
 #define MEGASAS_IOCTL_CMD			0
+#define MEGASAS_DEFAULT_CMD_TIMEOUT		90
 
 /*
  * FW reports the maximum of number of commands that it can accept (maximum
@@ -1073,7 +1075,6 @@
 	struct megasas_register_set __iomem *reg_set;
 
 	s8 init_id;
-	u8 reserved[3];
 
 	u16 max_num_sge;
 	u16 max_fw_cmds;
@@ -1104,6 +1105,9 @@
 
 	struct megasas_instance_template *instancet;
 	struct tasklet_struct isr_tasklet;
+
+	u8 flag;
+	unsigned long last_time;
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index e64d1a1..651d09b 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -421,7 +421,7 @@
 		for (i = 0; i < cmd->cmd_len; ++i)
 			printk(" %x", cmd->cmnd[i]);
 		printk(" use_sg=%d buffer=%p bufflen=%u\n",
-		       cmd->use_sg, cmd->request_buffer, cmd->request_bufflen);
+		       scsi_sg_count(cmd), scsi_sglist(cmd), scsi_bufflen(cmd));
 	}
 #endif
 	if (ms->dma_started)
@@ -602,13 +602,16 @@
 			cmd->result += (cmd->SCp.Message << 8);
 		if (DEBUG_TARGET(cmd)) {
 			printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n",
-			       cmd->result, ms->data_ptr, cmd->request_bufflen);
+			       cmd->result, ms->data_ptr, scsi_bufflen(cmd));
+#if 0
+			/* needs to use sg? */
 			if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3)
 			    && cmd->request_buffer != 0) {
 				unsigned char *b = cmd->request_buffer;
 				printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n",
 				       b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
 			}
+#endif
 		}
 		cmd->SCp.this_residual -= ms->data_ptr;
 		mesh_completed(ms, cmd);
@@ -1265,15 +1268,18 @@
 	dcmds = ms->dma_cmds;
 	dtot = 0;
 	if (cmd) {
-		cmd->SCp.this_residual = cmd->request_bufflen;
-		if (cmd->use_sg > 0) {
-			int nseg;
+		int nseg;
+
+		cmd->SCp.this_residual = scsi_bufflen(cmd);
+
+		nseg = scsi_dma_map(cmd);
+		BUG_ON(nseg < 0);
+
+		if (nseg) {
 			total = 0;
-			scl = (struct scatterlist *) cmd->request_buffer;
 			off = ms->data_ptr;
-			nseg = pci_map_sg(ms->pdev, scl, cmd->use_sg,
-					  cmd->sc_data_direction);
-			for (i = 0; i <nseg; ++i, ++scl) {
+
+			scsi_for_each_sg(cmd, scl, nseg, i) {
 				u32 dma_addr = sg_dma_address(scl);
 				u32 dma_len = sg_dma_len(scl);
 				
@@ -1292,16 +1298,6 @@
 				dtot += dma_len - off;
 				off = 0;
 			}
-		} else if (ms->data_ptr < cmd->request_bufflen) {
-			dtot = cmd->request_bufflen - ms->data_ptr;
-			if (dtot > 0xffff)
-				panic("mesh: transfer size >= 64k");
-			st_le16(&dcmds->req_count, dtot);
-			/* XXX Use pci DMA API here ... */
-			st_le32(&dcmds->phy_addr,
-				virt_to_phys(cmd->request_buffer) + ms->data_ptr);
-			dcmds->xfer_status = 0;
-			++dcmds;
 		}
 	}
 	if (dtot == 0) {
@@ -1356,18 +1352,14 @@
 		dumplog(ms, ms->conn_tgt);
 		dumpslog(ms);
 #endif /* MESH_DBG */
-	} else if (cmd && cmd->request_bufflen != 0 &&
-		   ms->data_ptr > cmd->request_bufflen) {
+	} else if (cmd && scsi_bufflen(cmd) &&
+		   ms->data_ptr > scsi_bufflen(cmd)) {
 		printk(KERN_DEBUG "mesh: target %d overrun, "
 		       "data_ptr=%x total=%x goes_out=%d\n",
-		       ms->conn_tgt, ms->data_ptr, cmd->request_bufflen,
+		       ms->conn_tgt, ms->data_ptr, scsi_bufflen(cmd),
 		       ms->tgts[ms->conn_tgt].data_goes_out);
 	}
-	if (cmd->use_sg != 0) {
-		struct scatterlist *sg;
-		sg = (struct scatterlist *)cmd->request_buffer;
-		pci_unmap_sg(ms->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
-	}
+	scsi_dma_unmap(cmd);
 	ms->dma_started = 0;
 }
 
diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c
deleted file mode 100644
index 575fe6f..0000000
--- a/drivers/scsi/mvme16x.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
- *
- * Based on work by Alan Hourihane
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/mvme16xhw.h>
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "53c7xx.h"
-#include "mvme16x.h"
-
-#include<linux/stat.h>
-
-
-int mvme16x_scsi_detect(struct scsi_host_template *tpnt)
-{
-    static unsigned char called = 0;
-    int clock;
-    long long options;
-
-    if (!MACH_IS_MVME16x)
-		return 0;
-    if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
-	printk ("SCSI detection disabled, SCSI chip not present\n");
-	return 0;
-    }
-    if (called)
-	return 0;
-
-    tpnt->proc_name = "MVME16x";
-
-    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
-
-    clock = 66000000;	/* 66MHz SCSI Clock */
-
-    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)0xfff47000,
-			0, MVME16x_IRQ_SCSI, DMA_NONE,
-			options, clock);
-    called = 1;
-    return 1;
-}
-
-static int mvme16x_scsi_release(struct Scsi_Host *shost)
-{
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
-	return 0;
-}
-
-static struct scsi_host_template driver_template = {
-	.name			= "MVME16x NCR53c710 SCSI",
-	.detect			= mvme16x_scsi_detect,
-	.release		= mvme16x_scsi_release,
-	.queuecommand		= NCR53c7xx_queue_command,
-	.abort			= NCR53c7xx_abort,
-	.reset			= NCR53c7xx_reset,
-	.can_queue		= 24,
-	.this_id		= 7,
-	.sg_tablesize		= 63,
-	.cmd_per_lun		= 3,
-	.use_clustering		= DISABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
diff --git a/drivers/scsi/mvme16x.h b/drivers/scsi/mvme16x.h
deleted file mode 100644
index 73e33b3..0000000
--- a/drivers/scsi/mvme16x.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef MVME16x_SCSI_H
-#define MVME16x_SCSI_H
-
-#include <linux/types.h>
-
-int mvme16x_scsi_detect(struct scsi_host_template *);
-const char *NCR53c7x0_info(void);
-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int NCR53c7xx_abort(Scsi_Cmnd *);
-int NCR53c7x0_release (struct Scsi_Host *);
-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id);
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 3
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 24
-#endif
-
-#include <scsi/scsicam.h>
-
-#endif /* MVME16x_SCSI_H */
diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c
new file mode 100644
index 0000000..d6ef22a
--- /dev/null
+++ b/drivers/scsi/mvme16x_scsi.c
@@ -0,0 +1,158 @@
+/*
+ * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
+ *
+ * Based on work by Alan Hourihane
+ *
+ * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
+ */
+
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/mvme16xhw.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
+
+#include "53c700.h"
+
+MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
+MODULE_DESCRIPTION("MVME16x NCR53C710 driver");
+MODULE_LICENSE("GPL");
+
+static struct scsi_host_template mvme16x_scsi_driver_template = {
+	.name			= "MVME16x NCR53c710 SCSI",
+	.proc_name		= "MVME16x",
+	.this_id		= 7,
+	.module			= THIS_MODULE,
+};
+
+static struct platform_device *mvme16x_scsi_device;
+
+static __devinit int
+mvme16x_probe(struct device *dev)
+{
+	struct Scsi_Host * host = NULL;
+	struct NCR_700_Host_Parameters *hostdata;
+
+	if (!MACH_IS_MVME16x)
+		goto out;
+
+	if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
+		printk(KERN_INFO "mvme16x-scsi: detection disabled, "
+				 "SCSI chip not present\n");
+		goto out;
+	}
+
+	hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+	if (hostdata == NULL) {
+		printk(KERN_ERR "mvme16x-scsi: "
+				"Failed to allocate host data\n");
+		goto out;
+	}
+	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
+
+	/* Fill in the required pieces of hostdata */
+	hostdata->base = (void __iomem *)0xfff47000UL;
+	hostdata->clock = 50;	/* XXX - depends on the CPU clock! */
+	hostdata->chip710 = 1;
+	hostdata->dmode_extra = DMODE_FC2;
+	hostdata->dcntl_extra = EA_710;
+	hostdata->ctest7_extra = CTEST7_TT1;
+
+	/* and register the chip */
+	host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, dev);
+	if (!host) {
+		printk(KERN_ERR "mvme16x-scsi: No host detected; "
+				"board configuration problem?\n");
+		goto out_free;
+	}
+	host->this_id = 7;
+	host->base = 0xfff47000UL;
+	host->irq = MVME16x_IRQ_SCSI;
+	if (request_irq(host->irq, NCR_700_intr, 0, "mvme16x-scsi", host)) {
+		printk(KERN_ERR "mvme16x-scsi: request_irq failed\n");
+		goto out_put_host;
+	}
+
+	/* Enable scsi chip ints */
+	{
+		volatile unsigned long v;
+
+		/* Enable scsi interrupts at level 4 in PCCchip2 */
+		v = in_be32(0xfff4202c);
+		v = (v & ~0xff) | 0x10 | 4;
+		out_be32(0xfff4202c, v);
+	}
+
+	scsi_scan_host(host);
+
+	return 0;
+
+ out_put_host:
+	scsi_host_put(host);
+ out_free:
+	kfree(hostdata);
+ out:
+	return -ENODEV;
+}
+
+static __devexit int
+mvme16x_device_remove(struct device *dev)
+{
+	struct Scsi_Host *host = dev_to_shost(dev);
+	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+
+	/* Disable scsi chip ints */
+	{
+		volatile unsigned long v;
+
+		v = in_be32(0xfff4202c);
+		v &= ~0x10;
+		out_be32(0xfff4202c, v);
+	}
+	scsi_remove_host(host);
+	NCR_700_release(host);
+	kfree(hostdata);
+	free_irq(host->irq, host);
+
+	return 0;
+}
+
+static struct device_driver mvme16x_scsi_driver = {
+	.name	= "mvme16x-scsi",
+	.bus	= &platform_bus_type,
+	.probe	= mvme16x_probe,
+	.remove	= __devexit_p(mvme16x_device_remove),
+};
+
+static int __init mvme16x_scsi_init(void)
+{
+	int err;
+
+	err = driver_register(&mvme16x_scsi_driver);
+	if (err)
+		return err;
+
+	mvme16x_scsi_device = platform_device_register_simple("mvme16x-scsi",
+							      -1, NULL, 0);
+	if (IS_ERR(mvme16x_scsi_device)) {
+		driver_unregister(&mvme16x_scsi_driver);
+		return PTR_ERR(mvme16x_scsi_device);
+	}
+
+	return 0;
+}
+
+static void __exit mvme16x_scsi_exit(void)
+{
+	platform_device_unregister(mvme16x_scsi_device);
+	driver_unregister(&mvme16x_scsi_driver);
+}
+
+module_init(mvme16x_scsi_init);
+module_exit(mvme16x_scsi_exit);
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index bbf521c..030ba49 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -529,43 +529,20 @@
 {
 	switch(cmd->__data_mapped) {
 	case 2:
-		dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
-				cmd->sc_data_direction);
-		break;
-	case 1:
-		dma_unmap_single(dev, cmd->__data_mapping,
-				 cmd->request_bufflen,
-				 cmd->sc_data_direction);
+		scsi_dma_unmap(cmd);
 		break;
 	}
 	cmd->__data_mapped = 0;
 }
 
-static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
-{
-	dma_addr_t mapping;
-
-	if (cmd->request_bufflen == 0)
-		return 0;
-
-	mapping = dma_map_single(dev, cmd->request_buffer,
-				 cmd->request_bufflen,
-				 cmd->sc_data_direction);
-	cmd->__data_mapped = 1;
-	cmd->__data_mapping = mapping;
-
-	return mapping;
-}
-
 static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
 {
 	int use_sg;
 
-	if (cmd->use_sg == 0)
+	use_sg = scsi_dma_map(cmd);
+	if (!use_sg)
 		return 0;
 
-	use_sg = dma_map_sg(dev, cmd->request_buffer, cmd->use_sg,
-			cmd->sc_data_direction);
 	cmd->__data_mapped = 2;
 	cmd->__data_mapping = use_sg;
 
@@ -573,7 +550,6 @@
 }
 
 #define unmap_scsi_data(np, cmd)	__unmap_scsi_data(np->dev, cmd)
-#define map_scsi_single_data(np, cmd)	__map_scsi_single_data(np->dev, cmd)
 #define map_scsi_sg_data(np, cmd)	__map_scsi_sg_data(np->dev, cmd)
 
 /*==========================================================
@@ -7667,39 +7643,16 @@
 **	sizes to the data segment array.
 */
 
-static int ncr_scatter_no_sglist(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd)
-{
-	struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - 1];
-	int segment;
-
-	cp->data_len = cmd->request_bufflen;
-
-	if (cmd->request_bufflen) {
-		dma_addr_t baddr = map_scsi_single_data(np, cmd);
-		if (baddr) {
-			ncr_build_sge(np, data, baddr, cmd->request_bufflen);
-			segment = 1;
-		} else {
-			segment = -2;
-		}
-	} else {
-		segment = 0;
-	}
-
-	return segment;
-}
-
 static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd)
 {
 	int segment	= 0;
-	int use_sg	= (int) cmd->use_sg;
+	int use_sg	= scsi_sg_count(cmd);
 
 	cp->data_len	= 0;
 
-	if (!use_sg)
-		segment = ncr_scatter_no_sglist(np, cp, cmd);
-	else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) {
-		struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer;
+	use_sg = map_scsi_sg_data(np, cmd);
+	if (use_sg > 0) {
+		struct scatterlist *sg;
 		struct scr_tblmove *data;
 
 		if (use_sg > MAX_SCATTER) {
@@ -7709,16 +7662,15 @@
 
 		data = &cp->phys.data[MAX_SCATTER - use_sg];
 
-		for (segment = 0; segment < use_sg; segment++) {
-			dma_addr_t baddr = sg_dma_address(&scatter[segment]);
-			unsigned int len = sg_dma_len(&scatter[segment]);
+		scsi_for_each_sg(cmd, sg, use_sg, segment) {
+			dma_addr_t baddr = sg_dma_address(sg);
+			unsigned int len = sg_dma_len(sg);
 
 			ncr_build_sge(np, &data[segment], baddr, len);
 			cp->data_len += len;
 		}
-	} else {
+	} else
 		segment = -2;
-	}
 
 	return segment;
 }
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index f6f561d..7fed353 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -49,10 +49,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-# include <linux/blk.h>
-#endif
-
 #include "nsp32.h"
 
 
@@ -199,17 +195,9 @@
 static void __exit    exit_nsp32  (void);
 
 /* struct struct scsi_host_template */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
-#else
-static int         nsp32_proc_info   (char *, char **, off_t, int, int, int);
-#endif
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 static int         nsp32_detect      (struct pci_dev *pdev);
-#else
-static int         nsp32_detect      (struct scsi_host_template *);
-#endif
 static int         nsp32_queuecommand(struct scsi_cmnd *,
 		void (*done)(struct scsi_cmnd *));
 static const char *nsp32_info        (struct Scsi_Host *);
@@ -296,15 +284,7 @@
 	.eh_abort_handler       	= nsp32_eh_abort,
 	.eh_bus_reset_handler		= nsp32_eh_bus_reset,
 	.eh_host_reset_handler		= nsp32_eh_host_reset,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74))
-	.detect				= nsp32_detect,
-	.release			= nsp32_release,
-#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
-	.use_new_eh_code        	= 1,
-#else
 /*	.highmem_io			= 1, */
-#endif
 };
 
 #include "nsp32_io.h"
@@ -739,7 +719,7 @@
 	command = 0;
 	command |= (TRANSFER_GO | ALL_COUNTER_CLR);
 	if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
-		if (SCpnt->request_bufflen > 0) {
+		if (scsi_bufflen(SCpnt) > 0) {
 			command |= BM_START;
 		}
 	} else if (data->trans_method & NSP32_TRANSFER_MMIO) {
@@ -888,31 +868,28 @@
 static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt)
 {
 	nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
-	struct scatterlist   *sgl;
+	struct scatterlist *sg;
 	nsp32_sgtable *sgt = data->cur_lunt->sglun->sgt;
 	int num, i;
 	u32_le l;
 
-	if (SCpnt->request_bufflen == 0) {
-		return TRUE;
-	}
-
 	if (sgt == NULL) {
 		nsp32_dbg(NSP32_DEBUG_SGLIST, "SGT == null");
 		return FALSE;
 	}
 
-	if (SCpnt->use_sg) {
-		sgl = (struct scatterlist *)SCpnt->request_buffer;
-		num = pci_map_sg(data->Pci, sgl, SCpnt->use_sg,
-				 SCpnt->sc_data_direction);
-		for (i = 0; i < num; i++) {
+	num = scsi_dma_map(SCpnt);
+	if (!num)
+		return TRUE;
+	else if (num < 0)
+		return FALSE;
+	else {
+		scsi_for_each_sg(SCpnt, sg, num, i) {
 			/*
 			 * Build nsp32_sglist, substitute sg dma addresses.
 			 */
-			sgt[i].addr = cpu_to_le32(sg_dma_address(sgl));
-			sgt[i].len  = cpu_to_le32(sg_dma_len(sgl));
-			sgl++;
+			sgt[i].addr = cpu_to_le32(sg_dma_address(sg));
+			sgt[i].len  = cpu_to_le32(sg_dma_len(sg));
 
 			if (le32_to_cpu(sgt[i].len) > 0x10000) {
 				nsp32_msg(KERN_ERR,
@@ -929,23 +906,6 @@
 		/* set end mark */
 		l = le32_to_cpu(sgt[num-1].len);
 		sgt[num-1].len = cpu_to_le32(l | SGTEND);
-
-	} else {
-		SCpnt->SCp.have_data_in	= pci_map_single(data->Pci,
-			SCpnt->request_buffer, SCpnt->request_bufflen,
-			SCpnt->sc_data_direction);
-
-		sgt[0].addr = cpu_to_le32(SCpnt->SCp.have_data_in);
-		sgt[0].len  = cpu_to_le32(SCpnt->request_bufflen | SGTEND); /* set end mark */
-
-		if (SCpnt->request_bufflen > 0x10000) {
-			nsp32_msg(KERN_ERR,
-				  "can't transfer over 64KB at a time, size=0x%lx", SCpnt->request_bufflen);
-			return FALSE;
-		}
-		nsp32_dbg(NSP32_DEBUG_SGLIST, "single : addr 0x%lx len=0x%lx",
-			  le32_to_cpu(sgt[0].addr),
-			  le32_to_cpu(sgt[0].len ));
 	}
 
 	return TRUE;
@@ -962,7 +922,7 @@
 		  "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
 		  "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
 		  SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len,
-		  SCpnt->use_sg, SCpnt->request_buffer, SCpnt->request_bufflen);
+		  scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt));
 
 	if (data->CurrentSC != NULL) {
 		nsp32_msg(KERN_ERR, "Currentsc != NULL. Cancel this command request");
@@ -994,10 +954,10 @@
 	data->CurrentSC      = SCpnt;
 	SCpnt->SCp.Status    = CHECK_CONDITION;
 	SCpnt->SCp.Message   = 0;
-	SCpnt->resid         = SCpnt->request_bufflen;
+	scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
 
-	SCpnt->SCp.ptr		    = (char *) SCpnt->request_buffer;
-	SCpnt->SCp.this_residual    = SCpnt->request_bufflen;
+	SCpnt->SCp.ptr		    = (char *)scsi_sglist(SCpnt);
+	SCpnt->SCp.this_residual    = scsi_bufflen(SCpnt);
 	SCpnt->SCp.buffer	    = NULL;
 	SCpnt->SCp.buffers_residual = 0;
 
@@ -1210,13 +1170,9 @@
 	unsigned long flags;
 	int ret;
 	int handled = 0;
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 	struct Scsi_Host *host = data->Host;
+
 	spin_lock_irqsave(host->host_lock, flags);
-#else
-	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	/*
 	 * IRQ check, then enable IRQ mask
@@ -1312,7 +1268,7 @@
 		}
 
 		if ((auto_stat & DATA_IN_PHASE) &&
-		    (SCpnt->resid > 0) &&
+		    (scsi_get_resid(SCpnt) > 0) &&
 		    ((nsp32_read2(base, FIFO_REST_CNT) & FIFO_REST_MASK) != 0)) {
 			printk( "auto+fifo\n");
 			//nsp32_pio_read(SCpnt);
@@ -1333,7 +1289,7 @@
 			nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", 
 				    nsp32_read4(base, SAVED_SACK_CNT));
 
-			SCpnt->resid = 0; /* all data transfered! */
+			scsi_set_resid(SCpnt, 0); /* all data transfered! */
 		}
 
 		/*
@@ -1480,11 +1436,7 @@
 	nsp32_write2(base, IRQ_CONTROL, 0);
 
  out2:
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 	spin_unlock_irqrestore(host->host_lock, flags);
-#else
-	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 
 	nsp32_dbg(NSP32_DEBUG_INTR, "exit");
 
@@ -1499,28 +1451,15 @@
 			nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
 		} \
 	} while(0)
-static int nsp32_proc_info(
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
-	struct Scsi_Host *host,
-#endif
-	char             *buffer,
-	char            **start,
-	off_t             offset,
-	int               length,
-#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
-	int               hostno,
-#endif
-	int               inout)
+
+static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
+			   off_t offset, int length, int inout)
 {
 	char             *pos = buffer;
 	int               thislength;
 	unsigned long     flags;
 	nsp32_hw_data    *data;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
 	int               hostno;
-#else
-	struct Scsi_Host *host;
-#endif
 	unsigned int      base;
 	unsigned char     mode_reg;
 	int               id, speed;
@@ -1531,15 +1470,7 @@
 		return -EINVAL;
 	}
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
 	hostno = host->host_no;
-#else
-	/* search this HBA host */
-	host = scsi_host_hn_get(hostno);
-	if (host == NULL) {
-		return -ESRCH;
-	}
-#endif
 	data = (nsp32_hw_data *)host->hostdata;
 	base = host->io_port;
 
@@ -1626,25 +1557,8 @@
 	nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
 	unsigned int   base = SCpnt->device->host->io_port;
 
-	/*
-	 * unmap pci
-	 */
-	if (SCpnt->request_bufflen == 0) {
-		goto skip;
-	}
+	scsi_dma_unmap(SCpnt);
 
-	if (SCpnt->use_sg) {
-		pci_unmap_sg(data->Pci,
-			     (struct scatterlist *)SCpnt->request_buffer,
-			     SCpnt->use_sg, SCpnt->sc_data_direction);
-	} else {
-		pci_unmap_single(data->Pci,
-				 (u32)SCpnt->SCp.have_data_in,
-				 SCpnt->request_bufflen,
-				 SCpnt->sc_data_direction);
-	}
-
- skip:
 	/*
 	 * clear TRANSFERCONTROL_BM_START
 	 */
@@ -1800,7 +1714,7 @@
 		SCpnt->SCp.Message = 0;
 		nsp32_dbg(NSP32_DEBUG_BUSFREE, 
 			  "normal end stat=0x%x resid=0x%x\n",
-			  SCpnt->SCp.Status, SCpnt->resid);
+			  SCpnt->SCp.Status, scsi_get_resid(SCpnt));
 		SCpnt->result = (DID_OK             << 16) |
 			        (SCpnt->SCp.Message <<  8) |
 			        (SCpnt->SCp.Status  <<  0);
@@ -1844,7 +1758,7 @@
 	unsigned int          restlen, sentlen;
 	u32_le                len, addr;
 
-	nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", SCpnt->resid);
+	nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", scsi_get_resid(SCpnt));
 
 	/* adjust saved SACK count with 4 byte start address boundary */
 	s_sacklen -= le32_to_cpu(sgt[old_entry].addr) & 3;
@@ -1888,12 +1802,12 @@
 	return;
 
  last:
-	if (SCpnt->resid < sentlen) {
+	if (scsi_get_resid(SCpnt) < sentlen) {
 		nsp32_msg(KERN_ERR, "resid underflow");
 	}
 
-	SCpnt->resid -= sentlen;
-	nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", SCpnt->resid);
+	scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) - sentlen);
+	nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", scsi_get_resid(SCpnt));
 
 	/* update hostdata and lun */
 
@@ -2022,7 +1936,7 @@
 	transfer = 0;
 	transfer |= (TRANSFER_GO | ALL_COUNTER_CLR);
 	if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
-		if (SCpnt->request_bufflen > 0) {
+		if (scsi_bufflen(SCpnt) > 0) {
 			transfer |= BM_START;
 		}
 	} else if (data->trans_method & NSP32_TRANSFER_MMIO) {
@@ -2674,17 +2588,7 @@
  *	0x900-0xbff: (map same 0x800-0x8ff I/O port image repeatedly)
  *	0xc00-0xfff: CardBus status registers
  */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-#define DETECT_OK 0
-#define DETECT_NG 1
-#define PCIDEV    pdev
 static int nsp32_detect(struct pci_dev *pdev)
-#else
-#define DETECT_OK 1
-#define DETECT_NG 0
-#define PCIDEV    (data->Pci)
-static int nsp32_detect(struct scsi_host_template *sht)
-#endif
 {
 	struct Scsi_Host *host;	/* registered host structure */
 	struct resource  *res;
@@ -2697,11 +2601,7 @@
 	/*
 	 * register this HBA as SCSI device
 	 */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 	host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data));
-#else
-	host = scsi_register(sht, sizeof(nsp32_hw_data));
-#endif
 	if (host == NULL) {
 		nsp32_msg (KERN_ERR, "failed to scsi register");
 		goto err;
@@ -2719,9 +2619,6 @@
 	host->unique_id = data->BaseAddress;
 	host->n_io_port	= data->NumAddress;
 	host->base      = (unsigned long)data->MmioAddress;
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,63))
-	scsi_set_pci_device(host, PCIDEV);
-#endif
 
 	data->Host      = host;
 	spin_lock_init(&(data->Lock));
@@ -2776,7 +2673,7 @@
 	/*
 	 * setup DMA 
 	 */
-	if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) {
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
 		nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
 		goto scsi_unregister;
 	}
@@ -2784,7 +2681,7 @@
 	/*
 	 * allocate autoparam DMA resource.
 	 */
-	data->autoparam = pci_alloc_consistent(PCIDEV, sizeof(nsp32_autoparam), &(data->auto_paddr));
+	data->autoparam = pci_alloc_consistent(pdev, sizeof(nsp32_autoparam), &(data->auto_paddr));
 	if (data->autoparam == NULL) {
 		nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
 		goto scsi_unregister;
@@ -2793,7 +2690,7 @@
 	/*
 	 * allocate scatter-gather DMA resource.
 	 */
-	data->sg_list = pci_alloc_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+	data->sg_list = pci_alloc_consistent(pdev, NSP32_SG_TABLE_SIZE,
 					     &(data->sg_paddr));
 	if (data->sg_list == NULL) {
 		nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
@@ -2883,16 +2780,14 @@
 		goto free_irq;
         }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-	ret = scsi_add_host(host, &PCIDEV->dev);
+	ret = scsi_add_host(host, &pdev->dev);
 	if (ret) {
 		nsp32_msg(KERN_ERR, "failed to add scsi host");
 		goto free_region;
 	}
 	scsi_scan_host(host);
-#endif
-	pci_set_drvdata(PCIDEV, host);
-	return DETECT_OK;
+	pci_set_drvdata(pdev, host);
+	return 0;
 
  free_region:
 	release_region(host->io_port, host->n_io_port);
@@ -2901,22 +2796,19 @@
 	free_irq(host->irq, data);
 
  free_sg_list:
-	pci_free_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+	pci_free_consistent(pdev, NSP32_SG_TABLE_SIZE,
 			    data->sg_list, data->sg_paddr);
 
  free_autoparam:
-	pci_free_consistent(PCIDEV, sizeof(nsp32_autoparam),
+	pci_free_consistent(pdev, sizeof(nsp32_autoparam),
 			    data->autoparam, data->auto_paddr);
 	
  scsi_unregister:
 	scsi_host_put(host);
 
  err:
-	return DETECT_NG;
+	return 1;
 }
-#undef DETECT_OK
-#undef DETECT_NG
-#undef PCIDEV
 
 static int nsp32_release(struct Scsi_Host *host)
 {
@@ -3487,15 +3379,6 @@
 	return 0;
 }
 
-/* Enable wake event */
-static int nsp32_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable)
-{
-	struct Scsi_Host *host = pci_get_drvdata(pdev);
-
-	nsp32_msg(KERN_INFO, "pci-enable_wake: stub, pdev=0x%p, enable=%d, slot=%s, host=0x%p", pdev, enable, pci_name(pdev), host);
-
-	return 0;
-}
 #endif
 
 /************************************************************************
@@ -3525,11 +3408,7 @@
 
 	pci_set_master(pdev);
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 	ret = nsp32_detect(pdev);
-#else
-	ret = scsi_register_host(&nsp32_template);
-#endif
 
 	nsp32_msg(KERN_INFO, "irq: %i mmio: %p+0x%lx slot: %s model: %s",
 		  pdev->irq,
@@ -3544,25 +3423,17 @@
 
 static void __devexit nsp32_remove(struct pci_dev *pdev)
 {
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 	struct Scsi_Host *host = pci_get_drvdata(pdev);
-#endif
 
 	nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
         scsi_remove_host(host);
 
 	nsp32_release(host);
 
 	scsi_host_put(host);
-#else
-	scsi_unregister_host(&nsp32_template);	
-#endif
 }
 
-
-
 static struct pci_driver nsp32_driver = {
 	.name		= "nsp32",
 	.id_table	= nsp32_pci_table,
@@ -3571,7 +3442,6 @@
 #ifdef CONFIG_PM
 	.suspend	= nsp32_suspend, 
 	.resume		= nsp32_resume, 
-	.enable_wake    = nsp32_enable_wake,
 #endif
 };
 
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index ffe75c4..2695b71 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -370,8 +370,6 @@
 	DEB(unsigned char seq_reg;)
 	unsigned char status, int_reg;
 	unsigned char pio_status;
-	struct scatterlist *sglist;
-	unsigned int sgcount;
 	int port_base = dev->io_port;
 	struct sym53c500_data *data =
 	    (struct sym53c500_data *)dev->hostdata;
@@ -434,20 +432,19 @@
 	switch (status & 0x07) {	/* scsi phase */
 	case 0x00:			/* DATA-OUT */
 		if (int_reg & 0x10) {	/* Target requesting info transfer */
+			struct scatterlist *sg;
+			int i;
+
 			curSC->SCp.phase = data_out;
 			VDEB(printk("SYM53C500: Data-Out phase\n"));
 			outb(FLUSH_FIFO, port_base + CMD_REG);
-			LOAD_DMA_COUNT(port_base, curSC->request_bufflen);	/* Max transfer size */
+			LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC));	/* Max transfer size */
 			outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
-			if (!curSC->use_sg)	/* Don't use scatter-gather */
-				SYM53C500_pio_write(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
-			else {	/* use scatter-gather */
-				sgcount = curSC->use_sg;
-				sglist = curSC->request_buffer;
-				while (sgcount--) {
-					SYM53C500_pio_write(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
-					sglist++;
-				}
+
+			scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
+				SYM53C500_pio_write(fast_pio, port_base,
+						    page_address(sg->page) + sg->offset,
+						    sg->length);
 			}
 			REG0(port_base);
 		}
@@ -455,20 +452,19 @@
 
 	case 0x01:		/* DATA-IN */
 		if (int_reg & 0x10) {	/* Target requesting info transfer */
+			struct scatterlist *sg;
+			int i;
+
 			curSC->SCp.phase = data_in;
 			VDEB(printk("SYM53C500: Data-In phase\n"));
 			outb(FLUSH_FIFO, port_base + CMD_REG);
-			LOAD_DMA_COUNT(port_base, curSC->request_bufflen);	/* Max transfer size */
+			LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC));	/* Max transfer size */
 			outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
-			if (!curSC->use_sg)	/* Don't use scatter-gather */
-				SYM53C500_pio_read(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
-			else {	/* Use scatter-gather */
-				sgcount = curSC->use_sg;
-				sglist = curSC->request_buffer;
-				while (sgcount--) {
-					SYM53C500_pio_read(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
-					sglist++;
-				}
+
+			scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
+				SYM53C500_pio_read(fast_pio, port_base,
+						   page_address(sg->page) + sg->offset,
+						   sg->length);
 			}
 			REG0(port_base);
 		}
@@ -578,7 +574,7 @@
 
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
 	    SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, 
-	    SCpnt->device->lun,  SCpnt->request_bufflen));
+	    SCpnt->device->lun,  scsi_bufflen(SCpnt)));
 
 	VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
 	    printk("cmd[%d]=%02x  ", i, SCpnt->cmnd[i]));
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 3b2e1a5..d953d43 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -4,6 +4,7 @@
  *
  */
 
+#include <linux/completion.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -50,16 +51,10 @@
 } *fcs __initdata;
 static int fcscount __initdata = 0;
 static atomic_t fcss __initdata = ATOMIC_INIT(0);
-DECLARE_MUTEX_LOCKED(fc_sem);
+static DECLARE_COMPLETION(fc_detect_complete);
 
 static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
 
-static void __init pluto_detect_timeout(unsigned long data)
-{
-	PLND(("Timeout\n"))
-	up(&fc_sem);
-}
-
 static void __init pluto_detect_done(Scsi_Cmnd *SCpnt)
 {
 	/* Do nothing */
@@ -69,7 +64,7 @@
 {
 	PLND(("Detect done %08lx\n", (long)SCpnt))
 	if (atomic_dec_and_test (&fcss))
-		up(&fc_sem);
+		complete(&fc_detect_complete);
 }
 
 int pluto_slave_configure(struct scsi_device *device)
@@ -96,7 +91,6 @@
 	int i, retry, nplutos;
 	fc_channel *fc;
 	struct scsi_device dev;
-	DEFINE_TIMER(fc_timer, pluto_detect_timeout, 0, 0);
 
 	tpnt->proc_name = "pluto";
 	fcscount = 0;
@@ -187,15 +181,11 @@
 			}
 		}
 	    
-		fc_timer.expires = jiffies + 10 * HZ;
-		add_timer(&fc_timer);
-		
-		down(&fc_sem);
+		wait_for_completion_timeout(&fc_detect_complete, 10 * HZ);
 		PLND(("Woken up\n"))
 		if (!atomic_read(&fcss))
 			break; /* All fc channels have answered us */
 	}
-	del_timer_sync(&fc_timer);
 
 	PLND(("Finished search\n"))
 	for (i = 0, nplutos = 0; i < fcscount; i++) {
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 584ba4d..2f1fa1e 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -129,11 +129,11 @@
 	if ((length > 10) && (strncmp(buffer, "recon_tmo=", 10) == 0)) {
 		x = simple_strtoul(buffer + 10, NULL, 0);
 		dev->recon_tmo = x;
-		printk("ppa: recon_tmo set to %ld\n", x);
+		printk(KERN_INFO "ppa: recon_tmo set to %ld\n", x);
 		return length;
 	}
-	printk("ppa /proc: invalid variable\n");
-	return (-EINVAL);
+	printk(KERN_WARNING "ppa /proc: invalid variable\n");
+	return -EINVAL;
 }
 
 static int ppa_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
@@ -216,7 +216,7 @@
 
 	/* Counter expired - Time out occurred */
 	ppa_fail(dev, DID_TIME_OUT);
-	printk("ppa timeout in ppa_wait\n");
+	printk(KERN_WARNING "ppa timeout in ppa_wait\n");
 	return 0;		/* command timed out */
 }
 
@@ -248,7 +248,7 @@
 				return;
 			udelay(5);
 		}
-		printk("ppa: ECP sync failed as data still present in FIFO.\n");
+		printk(KERN_WARNING "ppa: ECP sync failed as data still present in FIFO.\n");
 	}
 }
 
@@ -328,7 +328,7 @@
 		break;
 
 	default:
-		printk("PPA: bug in ppa_out()\n");
+		printk(KERN_ERR "PPA: bug in ppa_out()\n");
 		r = 0;
 	}
 	return r;
@@ -381,7 +381,7 @@
 		break;
 
 	default:
-		printk("PPA: bug in ppa_ins()\n");
+		printk(KERN_ERR "PPA: bug in ppa_ins()\n");
 		r = 0;
 		break;
 	}
@@ -633,7 +633,7 @@
 	struct scsi_cmnd *cmd = dev->cur_cmd;
 
 	if (!cmd) {
-		printk("PPA: bug in ppa_interrupt\n");
+		printk(KERN_ERR "PPA: bug in ppa_interrupt\n");
 		return;
 	}
 	if (ppa_engine(dev, cmd)) {
@@ -646,31 +646,31 @@
 	case DID_OK:
 		break;
 	case DID_NO_CONNECT:
-		printk("ppa: no device at SCSI ID %i\n", cmd->device->target);
+		printk(KERN_DEBUG "ppa: no device at SCSI ID %i\n", cmd->device->target);
 		break;
 	case DID_BUS_BUSY:
-		printk("ppa: BUS BUSY - EPP timeout detected\n");
+		printk(KERN_DEBUG "ppa: BUS BUSY - EPP timeout detected\n");
 		break;
 	case DID_TIME_OUT:
-		printk("ppa: unknown timeout\n");
+		printk(KERN_DEBUG "ppa: unknown timeout\n");
 		break;
 	case DID_ABORT:
-		printk("ppa: told to abort\n");
+		printk(KERN_DEBUG "ppa: told to abort\n");
 		break;
 	case DID_PARITY:
-		printk("ppa: parity error (???)\n");
+		printk(KERN_DEBUG "ppa: parity error (???)\n");
 		break;
 	case DID_ERROR:
-		printk("ppa: internal driver error\n");
+		printk(KERN_DEBUG "ppa: internal driver error\n");
 		break;
 	case DID_RESET:
-		printk("ppa: told to reset device\n");
+		printk(KERN_DEBUG "ppa: told to reset device\n");
 		break;
 	case DID_BAD_INTR:
-		printk("ppa: bad interrupt (???)\n");
+		printk(KERN_WARNING "ppa: bad interrupt (???)\n");
 		break;
 	default:
-		printk("ppa: bad return code (%02x)\n",
+		printk(KERN_WARNING "ppa: bad return code (%02x)\n",
 		       (cmd->result >> 16) & 0xff);
 	}
 #endif
@@ -724,8 +724,7 @@
 
 			if (retv) {
 				if (time_after(jiffies, dev->jstart + (1 * HZ))) {
-					printk
-					    ("ppa: Parallel port cable is unplugged!!\n");
+					printk(KERN_ERR "ppa: Parallel port cable is unplugged.\n");
 					ppa_fail(dev, DID_BUS_BUSY);
 					return 0;
 				} else {
@@ -755,11 +754,9 @@
 	case 4:		/* Phase 4 - Setup scatter/gather buffers */
 		if (cmd->use_sg) {
 			/* if many buffers are available, start filling the first */
-			cmd->SCp.buffer =
-			    (struct scatterlist *) cmd->request_buffer;
+			cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
 			cmd->SCp.this_residual = cmd->SCp.buffer->length;
-			cmd->SCp.ptr =
-			    page_address(cmd->SCp.buffer->page) +
+			cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
 			    cmd->SCp.buffer->offset;
 		} else {
 			/* else fill the only available buffer */
@@ -800,7 +797,7 @@
 		break;
 
 	default:
-		printk("ppa: Invalid scsi phase\n");
+		printk(KERN_ERR "ppa: Invalid scsi phase\n");
 	}
 	return 0;
 }
@@ -811,7 +808,7 @@
 	ppa_struct *dev = ppa_dev(cmd->device->host);
 
 	if (dev->cur_cmd) {
-		printk("PPA: bug in ppa_queuecommand\n");
+		printk(KERN_ERR "PPA: bug in ppa_queuecommand\n");
 		return 0;
 	}
 	dev->failed = 0;
@@ -899,7 +896,7 @@
 	/* This routine looks for a device and then attempts to use EPP
 	   to send a command. If all goes as planned then EPP is available. */
 
-	static char cmd[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	static u8 cmd[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	int loop, old_mode, status, k, ppb = dev->base;
 	unsigned char l;
 
@@ -909,14 +906,14 @@
 		if ((ppb & 0x0007) == 0x0000)
 			dev->mode = PPA_EPP_32;
 
-	      second_pass:
+second_pass:
 		ppa_connect(dev, CONNECT_EPP_MAYBE);
 		/* Select SCSI device */
 		if (!ppa_select(dev, loop)) {
 			ppa_disconnect(dev);
 			continue;
 		}
-		printk("ppa: Found device at ID %i, Attempting to use %s\n",
+		printk(KERN_INFO "ppa: Found device at ID %i, Attempting to use %s\n",
 		       loop, PPA_MODE_STRING[dev->mode]);
 
 		/* Send SCSI command */
@@ -965,7 +962,7 @@
 			return -EIO;
 		}
 		ppa_disconnect(dev);
-		printk("ppa: Communication established with ID %i using %s\n",
+		printk(KERN_INFO "ppa: Communication established with ID %i using %s\n",
 		       loop, PPA_MODE_STRING[dev->mode]);
 		ppa_connect(dev, CONNECT_EPP_MAYBE);
 		ppa_reset_pulse(ppb);
@@ -1140,7 +1137,7 @@
 
 static int __init ppa_driver_init(void)
 {
-	printk("ppa: Version %s\n", PPA_VERSION);
+	printk(KERN_INFO "ppa: Version %s\n", PPA_VERSION);
 	return parport_register_driver(&ppa_driver);
 }
 
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index 411663a..71ddb5d 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,4 +1,4 @@
 qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
-		qla_dbg.o qla_sup.o qla_attr.o
+		qla_dbg.o qla_sup.o qla_attr.o qla_mid.o
 
 obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 8081b63..3eb2208 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -6,13 +6,17 @@
  */
 #include "qla_def.h"
 
+#include <linux/kthread.h>
 #include <linux/vmalloc.h>
 
+int qla24xx_vport_disable(struct fc_vport *, bool);
+
 /* SYSFS attributes --------------------------------------------------------- */
 
 static ssize_t
-qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
+			   struct bin_attribute *bin_attr,
+			   char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -31,8 +35,9 @@
 }
 
 static ssize_t
-qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
+			    struct bin_attribute *bin_attr,
+			    char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -73,7 +78,6 @@
 	.attr = {
 		.name = "fw_dump",
 		.mode = S_IRUSR | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 0,
 	.read = qla2x00_sysfs_read_fw_dump,
@@ -81,8 +85,9 @@
 };
 
 static ssize_t
-qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_nvram(struct kobject *kobj,
+			 struct bin_attribute *bin_attr,
+			 char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -101,8 +106,9 @@
 }
 
 static ssize_t
-qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_nvram(struct kobject *kobj,
+			  struct bin_attribute *bin_attr,
+			  char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -149,7 +155,6 @@
 	.attr = {
 		.name = "nvram",
 		.mode = S_IRUSR | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 512,
 	.read = qla2x00_sysfs_read_nvram,
@@ -157,8 +162,9 @@
 };
 
 static ssize_t
-qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_optrom(struct kobject *kobj,
+			  struct bin_attribute *bin_attr,
+			  char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -176,8 +182,9 @@
 }
 
 static ssize_t
-qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_optrom(struct kobject *kobj,
+			   struct bin_attribute *bin_attr,
+			   char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -198,7 +205,6 @@
 	.attr = {
 		.name = "optrom",
 		.mode = S_IRUSR | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = OPTROM_SIZE_24XX,
 	.read = qla2x00_sysfs_read_optrom,
@@ -206,8 +212,9 @@
 };
 
 static ssize_t
-qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -279,15 +286,15 @@
 	.attr = {
 		.name = "optrom_ctl",
 		.mode = S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 0,
 	.write = qla2x00_sysfs_write_optrom_ctl,
 };
 
 static ssize_t
-qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_vpd(struct kobject *kobj,
+		       struct bin_attribute *bin_attr,
+		       char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -305,8 +312,9 @@
 }
 
 static ssize_t
-qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_write_vpd(struct kobject *kobj,
+			struct bin_attribute *bin_attr,
+			char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -327,7 +335,6 @@
 	.attr = {
 		.name = "vpd",
 		.mode = S_IRUSR | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = 0,
 	.read = qla2x00_sysfs_read_vpd,
@@ -335,8 +342,9 @@
 };
 
 static ssize_t
-qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
-    size_t count)
+qla2x00_sysfs_read_sfp(struct kobject *kobj,
+		       struct bin_attribute *bin_attr,
+		       char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -375,7 +383,6 @@
 	.attr = {
 		.name = "sfp",
 		.mode = S_IRUSR | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = SFP_DEV_SIZE * 2,
 	.read = qla2x00_sysfs_read_sfp,
@@ -959,6 +966,122 @@
 		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
 }
 
+static int
+qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
+{
+	int	ret = 0;
+	scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+	scsi_qla_host_t *vha;
+
+	ret = qla24xx_vport_create_req_sanity_check(fc_vport);
+	if (ret) {
+		DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, "
+		    "status %x\n", ret));
+		return (ret);
+	}
+
+	vha = qla24xx_create_vhost(fc_vport);
+	if (vha == NULL) {
+		DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n",
+		    vha));
+		return FC_VPORT_FAILED;
+	}
+	if (disable) {
+		atomic_set(&vha->vp_state, VP_OFFLINE);
+		fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
+	} else
+		atomic_set(&vha->vp_state, VP_FAILED);
+
+	/* ready to create vport */
+	qla_printk(KERN_INFO, vha, "VP entry id %d assigned.\n", vha->vp_idx);
+
+	/* initialized vport states */
+	atomic_set(&vha->loop_state, LOOP_DOWN);
+	vha->vp_err_state=  VP_ERR_PORTDWN;
+	vha->vp_prev_err_state=  VP_ERR_UNKWN;
+	/* Check if physical ha port is Up */
+	if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
+	    atomic_read(&ha->loop_state) == LOOP_DEAD) {
+		/* Don't retry or attempt login of this virtual port */
+		DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n",
+		    vha->host_no));
+		atomic_set(&vha->loop_state, LOOP_DEAD);
+		if (!disable)
+			fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
+	}
+
+	if (scsi_add_host(vha->host, &fc_vport->dev)) {
+		DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
+			vha->host_no, vha->vp_idx));
+		goto vport_create_failed_2;
+	}
+
+	/* initialize attributes */
+	fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
+	fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
+	fc_host_supported_classes(vha->host) =
+		fc_host_supported_classes(ha->host);
+	fc_host_supported_speeds(vha->host) =
+		fc_host_supported_speeds(ha->host);
+
+	qla24xx_vport_disable(fc_vport, disable);
+
+	return 0;
+vport_create_failed_2:
+	qla24xx_disable_vp(vha);
+	qla24xx_deallocate_vp_id(vha);
+	kfree(vha->port_name);
+	kfree(vha->node_name);
+	scsi_host_put(vha->host);
+	return FC_VPORT_FAILED;
+}
+
+int
+qla24xx_vport_delete(struct fc_vport *fc_vport)
+{
+	scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+	scsi_qla_host_t *vha = fc_vport->dd_data;
+
+	qla24xx_disable_vp(vha);
+	qla24xx_deallocate_vp_id(vha);
+
+	down(&ha->vport_sem);
+	ha->cur_vport_count--;
+	clear_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map);
+	up(&ha->vport_sem);
+
+	kfree(vha->node_name);
+	kfree(vha->port_name);
+
+	if (vha->timer_active) {
+		qla2x00_vp_stop_timer(vha);
+		DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p "
+		    "has stopped\n",
+		    vha->host_no, vha->vp_idx, vha));
+        }
+
+	fc_remove_host(vha->host);
+
+	scsi_remove_host(vha->host);
+
+	scsi_host_put(vha->host);
+
+	return 0;
+}
+
+int
+qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable)
+{
+	scsi_qla_host_t *vha = fc_vport->dd_data;
+
+	if (disable)
+		qla24xx_disable_vp(vha);
+	else
+		qla24xx_enable_vp(vha);
+
+	return 0;
+}
+
 struct fc_function_template qla2xxx_transport_functions = {
 
 	.show_host_node_name = 1,
@@ -996,6 +1119,49 @@
 
 	.issue_fc_host_lip = qla2x00_issue_lip,
 	.get_fc_host_stats = qla2x00_get_fc_host_stats,
+
+	.vport_create = qla24xx_vport_create,
+	.vport_disable = qla24xx_vport_disable,
+	.vport_delete = qla24xx_vport_delete,
+};
+
+struct fc_function_template qla2xxx_transport_vport_functions = {
+
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+
+	.get_host_port_id = qla2x00_get_host_port_id,
+	.show_host_port_id = 1,
+	.get_host_speed = qla2x00_get_host_speed,
+	.show_host_speed = 1,
+	.get_host_port_type = qla2x00_get_host_port_type,
+	.show_host_port_type = 1,
+	.get_host_symbolic_name = qla2x00_get_host_symbolic_name,
+	.show_host_symbolic_name = 1,
+	.set_host_system_hostname = qla2x00_set_host_system_hostname,
+	.show_host_system_hostname = 1,
+	.get_host_fabric_name = qla2x00_get_host_fabric_name,
+	.show_host_fabric_name = 1,
+	.get_host_port_state = qla2x00_get_host_port_state,
+	.show_host_port_state = 1,
+
+	.dd_fcrport_size = sizeof(struct fc_port *),
+	.show_rport_supported_classes = 1,
+
+	.get_starget_node_name = qla2x00_get_starget_node_name,
+	.show_starget_node_name = 1,
+	.get_starget_port_name = qla2x00_get_starget_port_name,
+	.show_starget_port_name = 1,
+	.get_starget_port_id  = qla2x00_get_starget_port_id,
+	.show_starget_port_id = 1,
+
+	.get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
+	.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+
+	.issue_fc_host_lip = qla2x00_issue_lip,
+	.get_fc_host_stats = qla2x00_get_fc_host_stats,
 };
 
 void
@@ -1004,4 +1170,6 @@
 	fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
 	fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
 	fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
+	fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC;
+	fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count;
 }
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index f6ed696..996c47a 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1411,9 +1411,9 @@
 		printk("0x%02x ", cmd->cmnd[i]);
 	}
 	printk("\n  seg_cnt=%d, allowed=%d, retries=%d\n",
-	    cmd->use_sg, cmd->allowed, cmd->retries);
+	       scsi_sg_count(cmd), cmd->allowed, cmd->retries);
 	printk("  request buffer=0x%p, request buffer len=0x%x\n",
-	    cmd->request_buffer, cmd->request_bufflen);
+	       scsi_sglist(cmd), scsi_bufflen(cmd));
 	printk("  tag=%d, transfersize=0x%x\n",
 	    cmd->tag, cmd->transfersize);
 	printk("  serial_number=%lx, SP=%p\n", cmd->serial_number, sp);
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 5b12278..49dffeb 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -21,6 +21,7 @@
 /* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */
 /* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */
 /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
+/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
 /*
  *  Local Macro Definitions.
  */
@@ -30,7 +31,8 @@
     defined(QL_DEBUG_LEVEL_7)  || defined(QL_DEBUG_LEVEL_8) || \
     defined(QL_DEBUG_LEVEL_9)  || defined(QL_DEBUG_LEVEL_10) || \
     defined(QL_DEBUG_LEVEL_11) || defined(QL_DEBUG_LEVEL_12) || \
-    defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14)
+    defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14) || \
+    defined(QL_DEBUG_LEVEL_15)
     #define QL_DEBUG_ROUTINES
 #endif
 
@@ -125,6 +127,12 @@
 #define DEBUG14(x)	do {} while (0)
 #endif
 
+#if defined(QL_DEBUG_LEVEL_15)
+#define DEBUG15(x)      do {x;} while (0)
+#else
+#define DEBUG15(x)	do {} while (0)
+#endif
+
 /*
  * Firmware Dump structure definition
  */
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index e8948b6..a1ca590 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1551,6 +1551,9 @@
 
 	unsigned long last_queue_full;
 	unsigned long last_ramp_up;
+
+	struct list_head vp_fcport;
+	uint16_t vp_idx;
 } fc_port_t;
 
 /*
@@ -1999,6 +2002,36 @@
 };
 #define GID_LIST_SIZE (sizeof(struct gid_list_info) * MAX_FIBRE_DEVICES)
 
+/* NPIV */
+typedef struct vport_info {
+	uint8_t		port_name[WWN_SIZE];
+	uint8_t		node_name[WWN_SIZE];
+	int		vp_id;
+	uint16_t	loop_id;
+	unsigned long	host_no;
+	uint8_t		port_id[3];
+	int		loop_state;
+} vport_info_t;
+
+typedef struct vport_params {
+	uint8_t 	port_name[WWN_SIZE];
+	uint8_t 	node_name[WWN_SIZE];
+	uint32_t 	options;
+#define	VP_OPTS_RETRY_ENABLE	BIT_0
+#define	VP_OPTS_VP_DISABLE	BIT_1
+} vport_params_t;
+
+/* NPIV - return codes of VP create and modify */
+#define VP_RET_CODE_OK			0
+#define VP_RET_CODE_FATAL		1
+#define VP_RET_CODE_WRONG_ID		2
+#define VP_RET_CODE_WWPN		3
+#define VP_RET_CODE_RESOURCES		4
+#define VP_RET_CODE_NO_MEM		5
+#define VP_RET_CODE_NOT_FOUND		6
+
+#define to_qla_parent(x) (((x)->parent) ? (x)->parent : (x))
+
 /*
  * ISP operations
  */
@@ -2073,6 +2106,16 @@
 	uint16_t msix_entry;
 };
 
+#define	WATCH_INTERVAL		1       /* number of seconds */
+
+/* NPIV */
+#define MAX_MULTI_ID_LOOP                     126
+#define MAX_MULTI_ID_FABRIC                    64
+#define MAX_NUM_VPORT_LOOP                      (MAX_MULTI_ID_LOOP - 1)
+#define MAX_NUM_VPORT_FABRIC                    (MAX_MULTI_ID_FABRIC - 1)
+#define MAX_NUM_VHBA_LOOP                       (MAX_MULTI_ID_LOOP - 1)
+#define MAX_NUM_VHBA_FABRIC                     (MAX_MULTI_ID_FABRIC - 1)
+
 /*
  * Linux Host Adapter structure
  */
@@ -2108,6 +2151,8 @@
 		uint32_t	msix_enabled		:1;
 		uint32_t	disable_serdes		:1;
 		uint32_t	gpsc_supported		:1;
+		uint32_t        vsan_enabled            :1;
+		uint32_t	npiv_supported		:1;
 	} flags;
 
 	atomic_t	loop_state;
@@ -2147,6 +2192,7 @@
 #define BEACON_BLINK_NEEDED	25
 #define REGISTER_FDMI_NEEDED	26
 #define FCPORT_UPDATE_NEEDED	27
+#define VP_DPC_NEEDED		28	/* wake up for VP dpc handling */
 
 	uint32_t	device_flags;
 #define DFLG_LOCAL_DEVICES		BIT_0
@@ -2237,6 +2283,11 @@
 
 	/* ISP configuration data. */
 	uint16_t	loop_id;		/* Host adapter loop id */
+	uint16_t	switch_cap;
+#define FLOGI_SEQ_DEL		BIT_8
+#define FLOGI_MID_SUPPORT	BIT_10
+#define FLOGI_VSAN_SUPPORT	BIT_12
+#define FLOGI_SP_SUPPORT	BIT_13
 	uint16_t	fb_rev;
 
 	port_id_t	d_id;			/* Host adapter port id */
@@ -2344,6 +2395,7 @@
 #define MBX_UPDATE_FLASH_ACTIVE	3
 
 	struct semaphore mbx_cmd_sem;	/* Serialialize mbx access */
+	struct semaphore vport_sem;	/* Virtual port synchronization */
 	struct semaphore mbx_intr_sem;  /* Used for completion notification */
 
 	uint32_t	mbx_flags;
@@ -2428,6 +2480,37 @@
 	struct fc_host_statistics fc_host_stat;
 
 	struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES];
+
+	struct list_head	vp_list;	/* list of VP */
+	struct fc_vport	*fc_vport;	/* holds fc_vport * for each vport */
+	uint8_t		vp_idx_map[16];
+	uint16_t        num_vhosts;	/* number of vports created */
+	uint16_t        num_vsans;	/* number of vsan created */
+	uint16_t        vp_idx;		/* vport ID */
+
+	struct scsi_qla_host	*parent;	/* holds pport */
+	unsigned long		vp_flags;
+	struct list_head	vp_fcports;	/* list of fcports */
+#define VP_IDX_ACQUIRED		0	/* bit no 0 */
+#define VP_CREATE_NEEDED	1
+#define VP_BIND_NEEDED		2
+#define VP_DELETE_NEEDED	3
+#define VP_SCR_NEEDED		4	/* State Change Request registration */
+	atomic_t 		vp_state;
+#define VP_OFFLINE		0
+#define VP_ACTIVE		1
+#define VP_FAILED		2
+// #define VP_DISABLE		3
+	uint16_t 	vp_err_state;
+	uint16_t	vp_prev_err_state;
+#define VP_ERR_UNKWN		0
+#define VP_ERR_PORTDWN		1
+#define VP_ERR_FAB_UNSUPPORTED	2
+#define VP_ERR_FAB_NORESOURCES	3
+#define VP_ERR_FAB_LOGOUT	4
+#define VP_ERR_ADAP_NORESOURCES	5
+	int		max_npiv_vports;	/* 63 or 125 per topoloty */
+	int		cur_vport_count;
 } scsi_qla_host_t;
 
 
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index a0a722c..63a11fe 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -69,6 +69,16 @@
 	uint8_t reserved_3[24];
 };
 
+struct vp_database_24xx {
+	uint16_t vp_status;
+	uint8_t  options;
+	uint8_t  id;
+	uint8_t  port_name[WWN_SIZE];
+	uint8_t  node_name[WWN_SIZE];
+	uint16_t port_id_low;
+	uint16_t port_id_high;
+};
+
 struct nvram_24xx {
 	/* NVRAM header. */
 	uint8_t id[4];
@@ -962,6 +972,25 @@
 	struct mid_db_entry_24xx entries[MAX_MID_VPS];
 };
 
+ /*
+ * Virtual Fabric ID type definition.
+ */
+typedef struct vf_id {
+        uint16_t id : 12;
+        uint16_t priority : 4;
+} vf_id_t;
+
+/*
+ * Virtual Fabric HopCt type definition.
+ */
+typedef struct vf_hopct {
+        uint16_t reserved : 8;
+        uint16_t hopct : 8;
+} vf_hopct_t;
+
+/*
+ * Virtual Port Control IOCB
+ */
 #define VP_CTRL_IOCB_TYPE	0x30	/* Vitual Port Control entry. */
 struct vp_ctrl_entry_24xx {
 	uint8_t entry_type;		/* Entry type. */
@@ -974,6 +1003,7 @@
 	uint16_t vp_idx_failed;
 
 	uint16_t comp_status;		/* Completion status. */
+#define CS_VCE_IOCB_ERROR       0x01    /* Error processing IOCB */
 #define CS_VCE_ACQ_ID_ERROR	0x02	/* Error while acquireing ID. */
 #define CS_VCE_BUSY		0x05	/* Firmware not ready to accept cmd. */
 
@@ -982,24 +1012,34 @@
 #define VCE_COMMAND_DISABLE_VPS	0x08	/* Disable VPs. */
 #define VCE_COMMAND_DISABLE_VPS_REINIT	0x09 /* Disable VPs and reinit link. */
 #define VCE_COMMAND_DISABLE_VPS_LOGO	0x0a /* Disable VPs and LOGO ports. */
+#define VCE_COMMAND_DISABLE_VPS_LOGO_ALL        0x0b /* Disable VPs and LOGO ports. */
 
 	uint16_t vp_count;
 
 	uint8_t vp_idx_map[16];
-
-	uint8_t reserved_4[32];
+	uint16_t flags;
+	struct vf_id    id;
+	uint16_t reserved_4;
+	struct vf_hopct  hopct;
+	uint8_t reserved_5[8];
 };
 
+/*
+ * Modify Virtual Port Configuration IOCB
+ */
 #define VP_CONFIG_IOCB_TYPE	0x31	/* Vitual Port Config entry. */
 struct vp_config_entry_24xx {
 	uint8_t entry_type;		/* Entry type. */
 	uint8_t entry_count;		/* Entry count. */
-	uint8_t sys_define;		/* System defined. */
+	uint8_t handle_count;
 	uint8_t entry_status;		/* Entry Status. */
 
 	uint32_t handle;		/* System handle. */
 
-	uint16_t reserved_1;
+	uint16_t flags;
+#define CS_VF_BIND_VPORTS_TO_VF         BIT_0
+#define CS_VF_SET_QOS_OF_VPORTS         BIT_1
+#define CS_VF_SET_HOPS_OF_VPORTS        BIT_2
 
 	uint16_t comp_status;		/* Completion status. */
 #define CS_VCT_STS_ERROR	0x01	/* Specified VPs were not disabled. */
@@ -1009,27 +1049,29 @@
 #define CS_VCT_BUSY		0x05	/* Firmware not ready to accept cmd. */
 
 	uint8_t command;
-#define VCT_COMMAND_MOD_VPS	0x00	/* Enable VPs. */
-#define VCT_COMMAND_MOD_ENABLE_VPS 0x08	/* Disable VPs. */
+#define VCT_COMMAND_MOD_VPS     0x00    /* Modify VP configurations. */
+#define VCT_COMMAND_MOD_ENABLE_VPS 0x01 /* Modify configuration & enable VPs. */
 
 	uint8_t vp_count;
 
-	uint8_t vp_idx1;
-	uint8_t vp_idx2;
+	uint8_t vp_index1;
+	uint8_t vp_index2;
 
 	uint8_t options_idx1;
 	uint8_t hard_address_idx1;
-	uint16_t reserved_2;
+	uint16_t reserved_vp1;
 	uint8_t port_name_idx1[WWN_SIZE];
 	uint8_t node_name_idx1[WWN_SIZE];
 
 	uint8_t options_idx2;
 	uint8_t hard_address_idx2;
-	uint16_t reserved_3;
+	uint16_t reserved_vp2;
 	uint8_t port_name_idx2[WWN_SIZE];
 	uint8_t node_name_idx2[WWN_SIZE];
-
-	uint8_t reserved_4[8];
+	struct vf_id    id;
+	uint16_t reserved_4;
+	struct vf_hopct  hopct;
+	uint8_t reserved_5;
 };
 
 #define VP_RPT_ID_IOCB_TYPE	0x32	/* Report ID Acquisition entry. */
@@ -1054,5 +1096,30 @@
 	uint8_t reserved_4[32];
 };
 
+#define VF_EVFP_IOCB_TYPE       0x26    /* Exchange Virtual Fabric Parameters entry. */
+struct vf_evfp_entry_24xx {
+        uint8_t entry_type;             /* Entry type. */
+        uint8_t entry_count;            /* Entry count. */
+        uint8_t sys_define;             /* System defined. */
+        uint8_t entry_status;           /* Entry Status. */
+
+        uint32_t handle;                /* System handle. */
+        uint16_t comp_status;           /* Completion status. */
+        uint16_t timeout;               /* timeout */
+        uint16_t adim_tagging_mode;
+
+        uint16_t vfport_id;
+        uint32_t exch_addr;
+
+        uint16_t nport_handle;          /* N_PORT handle. */
+        uint16_t control_flags;
+        uint32_t io_parameter_0;
+        uint32_t io_parameter_1;
+        uint32_t tx_address[2];         /* Data segment 0 address. */
+        uint32_t tx_len;                /* Data segment 0 length. */
+        uint32_t rx_address[2];         /* Data segment 1 address. */
+        uint32_t rx_len;                /* Data segment 1 length. */
+};
+
 /* END MID Support ***********************************************************/
 #endif
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 74544ae..b44eff2 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -62,6 +62,38 @@
 extern int ql2xallocfwdump;
 extern int ql2xextended_error_logging;
 extern int ql2xqfullrampup;
+extern int num_hosts;
+
+/*
+ * Global Functions in qla_mid.c source file.
+ */
+extern struct scsi_host_template qla2x00_driver_template;
+extern struct scsi_host_template qla24xx_driver_template;
+extern struct scsi_transport_template *qla2xxx_transport_vport_template;
+extern uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
+extern void qla2x00_timer(scsi_qla_host_t *);
+extern void qla2x00_start_timer(scsi_qla_host_t *, void *, unsigned long);
+extern void qla2x00_stop_timer(scsi_qla_host_t *);
+extern uint32_t qla24xx_allocate_vp_id(scsi_qla_host_t *);
+extern void qla24xx_deallocate_vp_id(scsi_qla_host_t *);
+extern int qla24xx_disable_vp (scsi_qla_host_t *);
+extern int qla24xx_enable_vp (scsi_qla_host_t *);
+extern void qla2x00_mem_free(scsi_qla_host_t *);
+extern int qla24xx_control_vp(scsi_qla_host_t *, int );
+extern int qla24xx_modify_vp_config(scsi_qla_host_t *);
+extern int qla2x00_send_change_request(scsi_qla_host_t *, uint16_t, uint16_t);
+extern void qla2x00_vp_stop_timer(scsi_qla_host_t *);
+extern int qla24xx_configure_vhba (scsi_qla_host_t *);
+extern int qla24xx_get_vp_entry(scsi_qla_host_t *, uint16_t, int);
+extern int qla24xx_get_vp_database(scsi_qla_host_t *, uint16_t);
+extern int qla2x00_do_dpc_vp(scsi_qla_host_t *);
+extern void qla24xx_report_id_acquisition(scsi_qla_host_t *,
+    struct vp_rpt_id_entry_24xx *);
+extern scsi_qla_host_t * qla24xx_find_vhost_by_name(scsi_qla_host_t *,
+    uint8_t *);
+extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *);
+extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *);
+extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *);
 
 extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
 
@@ -77,6 +109,10 @@
 extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
 
 extern void qla2xxx_wake_dpc(scsi_qla_host_t *);
+extern void qla2x00_alert_all_vps(scsi_qla_host_t *, uint16_t *);
+extern void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);
+extern void qla2x00_vp_abort_isp(scsi_qla_host_t *);
+extern int qla24xx_vport_delete(struct fc_vport *);
 
 /*
  * Global Function Prototypes in qla_iocb.c source file.
@@ -128,7 +164,7 @@
 
 extern int
 qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
-    uint8_t *, uint16_t *);
+    uint8_t *, uint16_t *, uint16_t *);
 
 extern int
 qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *);
@@ -303,6 +339,7 @@
 extern struct class_device_attribute *qla2x00_host_attrs[];
 struct fc_function_template;
 extern struct fc_function_template qla2xxx_transport_functions;
+extern struct fc_function_template qla2xxx_transport_vport_functions;
 extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
 extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
 extern void qla2x00_init_host_attr(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index ec5b2dd..a086b3f 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -88,6 +88,7 @@
 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+	ct_pkt->vp_index = ha->vp_idx;
 
 	return (ct_pkt);
 }
@@ -1186,6 +1187,7 @@
 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+	ct_pkt->vp_index = ha->vp_idx;
 
 	return ct_pkt;
 }
@@ -1746,6 +1748,7 @@
 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+	ct_pkt->vp_index = ha->vp_idx;
 
 	return ct_pkt;
 }
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 2a45aec..cc6ebb6 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -296,7 +296,7 @@
 	d &= ~PCI_ROM_ADDRESS_ENABLE;
 	pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
 
-	pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision);
+	ha->chip_revision = ha->pdev->revision;
 
 	/* Get PCI bus information. */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -899,6 +899,10 @@
 				    &ha->fw_subminor_version,
 				    &ha->fw_attributes, &ha->fw_memory_size);
 				qla2x00_resize_request_q(ha);
+				ha->flags.npiv_supported = 0;
+				if (IS_QLA24XX(ha) &&
+				    (ha->fw_attributes & BIT_2))
+					ha->flags.npiv_supported = 1;
 
 				if (ql2xallocfwdump)
 					qla2x00_alloc_fw_dump(ha);
@@ -1101,6 +1105,8 @@
 	int	rval;
 	unsigned long flags = 0;
 	int cnt;
+	struct mid_init_cb_24xx *mid_init_cb =
+	    (struct mid_init_cb_24xx *) ha->init_cb;
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -1132,6 +1138,10 @@
 	ha->isp_ops.update_fw_options(ha);
 
 	DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));
+
+	mid_init_cb->count = MAX_NUM_VPORT_FABRIC;
+	ha->max_npiv_vports = MAX_NUM_VPORT_FABRIC;
+
 	rval = qla2x00_init_firmware(ha, ha->init_cb_size);
 	if (rval) {
 		DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",
@@ -1263,6 +1273,7 @@
 	int       rval;
 	uint16_t      loop_id;
 	uint16_t      topo;
+	uint16_t      sw_cap;
 	uint8_t       al_pa;
 	uint8_t       area;
 	uint8_t       domain;
@@ -1270,7 +1281,7 @@
 
 	/* Get host addresses. */
 	rval = qla2x00_get_adapter_id(ha,
-	    &loop_id, &al_pa, &area, &domain, &topo);
+	    &loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
 	if (rval != QLA_SUCCESS) {
 		if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) ||
 		    (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
@@ -1295,6 +1306,7 @@
 	/* initialize */
 	ha->min_external_loopid = SNS_FIRST_LOOP_ID;
 	ha->operating_mode = LOOP;
+	ha->switch_cap = 0;
 
 	switch (topo) {
 	case 0:
@@ -1307,6 +1319,7 @@
 	case 1:
 		DEBUG3(printk("scsi(%ld): HBA in FL topology.\n",
 		    ha->host_no));
+		ha->switch_cap = sw_cap;
 		ha->current_topology = ISP_CFG_FL;
 		strcpy(connect_type, "(FL_Port)");
 		break;
@@ -1322,6 +1335,7 @@
 	case 3:
 		DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n",
 		    ha->host_no));
+		ha->switch_cap = sw_cap;
 		ha->operating_mode = P2P;
 		ha->current_topology = ISP_CFG_F;
 		strcpy(connect_type, "(F_Port)");
@@ -1743,7 +1757,6 @@
 	spin_unlock_irqrestore(&fcport->rport_lock, flags);
 	if (rport)
 		fc_remote_port_delete(rport);
-
 }
 
 /**
@@ -1765,6 +1778,7 @@
 	/* Setup fcport template structure. */
 	memset(fcport, 0, sizeof (fc_port_t));
 	fcport->ha = ha;
+	fcport->vp_idx = ha->vp_idx;
 	fcport->port_type = FCT_UNKNOWN;
 	fcport->loop_id = FC_NO_LOOP_ID;
 	atomic_set(&fcport->state, FCS_UNCONFIGURED);
@@ -1911,6 +1925,7 @@
 	char		*id_iter;
 	uint16_t	loop_id;
 	uint8_t		domain, area, al_pa;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	found_devs = 0;
 	new_fcport = NULL;
@@ -1942,7 +1957,10 @@
 	/*
 	 * Mark local devices that were present with FCF_DEVICE_LOST for now.
 	 */
-	list_for_each_entry(fcport, &ha->fcports, list) {
+	list_for_each_entry(fcport, &pha->fcports, list) {
+		if (fcport->vp_idx != ha->vp_idx)
+			continue;
+
 		if (atomic_read(&fcport->state) == FCS_ONLINE &&
 		    fcport->port_type != FCT_BROADCAST &&
 		    (fcport->flags & FCF_FABRIC_DEVICE) == 0) {
@@ -1988,6 +2006,7 @@
 		new_fcport->d_id.b.area = area;
 		new_fcport->d_id.b.al_pa = al_pa;
 		new_fcport->loop_id = loop_id;
+		new_fcport->vp_idx = ha->vp_idx;
 		rval2 = qla2x00_get_port_database(ha, new_fcport, 0);
 		if (rval2 != QLA_SUCCESS) {
 			DEBUG2(printk("scsi(%ld): Failed to retrieve fcport "
@@ -2003,7 +2022,10 @@
 		/* Check for matching device in port list. */
 		found = 0;
 		fcport = NULL;
-		list_for_each_entry(fcport, &ha->fcports, list) {
+		list_for_each_entry(fcport, &pha->fcports, list) {
+			if (fcport->vp_idx != ha->vp_idx)
+				continue;
+
 			if (memcmp(new_fcport->port_name, fcport->port_name,
 			    WWN_SIZE))
 				continue;
@@ -2023,7 +2045,13 @@
 		if (!found) {
 			/* New device, add to fcports list. */
 			new_fcport->flags &= ~FCF_PERSISTENT_BOUND;
-			list_add_tail(&new_fcport->list, &ha->fcports);
+			if (ha->parent) {
+				new_fcport->ha = ha;
+				new_fcport->vp_idx = ha->vp_idx;
+				list_add_tail(&new_fcport->vp_fcport,
+				    &ha->vp_fcports);
+			}
+			list_add_tail(&new_fcport->list, &pha->fcports);
 
 			/* Allocate a new replacement fcport. */
 			fcport = new_fcport;
@@ -2199,11 +2227,13 @@
 void
 qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
 {
+	scsi_qla_host_t *pha = to_qla_parent(ha);
+
 	fcport->ha = ha;
 	fcport->login_retry = 0;
-	fcport->port_login_retry_count = ha->port_down_retry_count *
+	fcport->port_login_retry_count = pha->port_down_retry_count *
 	    PORT_RETRY_TIME;
-	atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
+	atomic_set(&fcport->port_down_timer, pha->port_down_retry_count *
 	    PORT_RETRY_TIME);
 	fcport->flags &= ~FCF_LOGIN_NEEDED;
 
@@ -2234,6 +2264,7 @@
 	uint16_t	mb[MAILBOX_REGISTER_COUNT];
 	uint16_t	loop_id;
 	LIST_HEAD(new_fcports);
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	/* If FL port exists, then SNS is present */
 	if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
@@ -2307,7 +2338,10 @@
 		 * Logout all previous fabric devices marked lost, except
 		 * tape devices.
 		 */
-		list_for_each_entry(fcport, &ha->fcports, list) {
+		list_for_each_entry(fcport, &pha->fcports, list) {
+			if (fcport->vp_idx !=ha->vp_idx)
+				continue;
+
 			if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
 				break;
 
@@ -2332,13 +2366,16 @@
 		}
 
 		/* Starting free loop ID. */
-		next_loopid = ha->min_external_loopid;
+		next_loopid = pha->min_external_loopid;
 
 		/*
 		 * Scan through our port list and login entries that need to be
 		 * logged in.
 		 */
-		list_for_each_entry(fcport, &ha->fcports, list) {
+		list_for_each_entry(fcport, &pha->fcports, list) {
+			if (fcport->vp_idx != ha->vp_idx)
+				continue;
+
 			if (atomic_read(&ha->loop_down_timer) ||
 			    test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
 				break;
@@ -2380,11 +2417,18 @@
 				break;
 			}
 
-			/* Remove device from the new list and add it to DB */
-			list_move_tail(&fcport->list, &ha->fcports);
-
 			/* Login and update database */
 			qla2x00_fabric_dev_login(ha, fcport, &next_loopid);
+
+			if (ha->parent) {
+				fcport->ha = ha;
+				fcport->vp_idx = ha->vp_idx;
+				list_add_tail(&fcport->vp_fcport,
+				    &ha->vp_fcports);
+				list_move_tail(&fcport->list,
+				    &ha->parent->fcports);
+			} else
+				list_move_tail(&fcport->list, &ha->fcports);
 		}
 	} while (0);
 
@@ -2428,6 +2472,11 @@
 	int		swl_idx;
 	int		first_dev, last_dev;
 	port_id_t	wrap, nxt_d_id;
+	int 		vp_index;
+	int		empty_vp_index;
+	int		found_vp;
+	scsi_qla_host_t *vha;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	rval = QLA_SUCCESS;
 
@@ -2461,13 +2510,13 @@
 		return (QLA_MEMORY_ALLOC_FAILED);
 	}
 	new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
-
+	new_fcport->vp_idx = ha->vp_idx;
 	/* Set start port ID scan at adapter ID. */
 	first_dev = 1;
 	last_dev = 0;
 
 	/* Starting free loop ID. */
-	loop_id = ha->min_external_loopid;
+	loop_id = pha->min_external_loopid;
 	for (; loop_id <= ha->last_loop_id; loop_id++) {
 		if (qla2x00_is_reserved_id(ha, loop_id))
 			continue;
@@ -2521,10 +2570,42 @@
 			break;
 		}
 
-		/* Bypass if host adapter. */
-		if (new_fcport->d_id.b24 == ha->d_id.b24)
+		/* Bypass if same physical adapter. */
+		if (new_fcport->d_id.b24 == pha->d_id.b24)
 			continue;
 
+		/* Bypass virtual ports of the same host. */
+		if (pha->num_vhosts) {
+			vp_index = find_next_bit(
+			    (unsigned long *)pha->vp_idx_map,
+			    MAX_MULTI_ID_FABRIC + 1, 1);
+
+			for (;vp_index <= MAX_MULTI_ID_FABRIC;
+			    vp_index = find_next_bit(
+			    (unsigned long *)pha->vp_idx_map,
+			    MAX_MULTI_ID_FABRIC + 1, vp_index + 1)) {
+				empty_vp_index = 1;
+				found_vp = 0;
+				list_for_each_entry(vha, &pha->vp_list,
+				    vp_list) {
+					if (vp_index == vha->vp_idx) {
+						empty_vp_index = 0;
+						found_vp = 1;
+						break;
+					}
+				}
+
+				if (empty_vp_index)
+					continue;
+
+				if (found_vp &&
+				    new_fcport->d_id.b24 == vha->d_id.b24)
+					break;
+			}
+			if (vp_index <= MAX_MULTI_ID_FABRIC)
+				continue;
+		}
+
 		/* Bypass if same domain and area of adapter. */
 		if (((new_fcport->d_id.b24 & 0xffff00) ==
 		    (ha->d_id.b24 & 0xffff00)) && ha->current_topology ==
@@ -2537,7 +2618,9 @@
 
 		/* Locate matching device in database. */
 		found = 0;
-		list_for_each_entry(fcport, &ha->fcports, list) {
+		list_for_each_entry(fcport, &pha->fcports, list) {
+			if (new_fcport->vp_idx != fcport->vp_idx)
+				continue;
 			if (memcmp(new_fcport->port_name, fcport->port_name,
 			    WWN_SIZE))
 				continue;
@@ -2605,6 +2688,7 @@
 		}
 		new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
 		new_fcport->d_id.b24 = nxt_d_id.b24;
+		new_fcport->vp_idx = ha->vp_idx;
 	}
 
 	kfree(swl);
@@ -2637,6 +2721,7 @@
 	int	found;
 	fc_port_t *fcport;
 	uint16_t first_loop_id;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	rval = QLA_SUCCESS;
 
@@ -2663,7 +2748,7 @@
 		/* Check for loop ID being already in use. */
 		found = 0;
 		fcport = NULL;
-		list_for_each_entry(fcport, &ha->fcports, list) {
+		list_for_each_entry(fcport, &pha->fcports, list) {
 			if (fcport->loop_id == dev->loop_id && fcport != dev) {
 				/* ID possibly in use */
 				found++;
@@ -2710,6 +2795,7 @@
 	uint8_t rscn_out_iter;
 	uint8_t format;
 	port_id_t d_id;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	rval = QLA_RSCNS_HANDLED;
 
@@ -2776,7 +2862,10 @@
 
 		rval = QLA_SUCCESS;
 
-		list_for_each_entry(fcport, &ha->fcports, list) {
+		list_for_each_entry(fcport, &pha->fcports, list) {
+			if (fcport->vp_idx != ha->vp_idx)
+				continue;
+
 			if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
 			    (fcport->d_id.b24 & mask) != d_id.b24 ||
 			    fcport->port_type == FCT_BROADCAST)
@@ -3940,3 +4029,40 @@
 		ret = qla2x00_stop_firmware(ha);
 	}
 }
+
+int
+qla24xx_configure_vhba(scsi_qla_host_t *ha)
+{
+	int rval = QLA_SUCCESS;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+
+	if (!ha->parent)
+		return -EINVAL;
+
+	rval = qla2x00_fw_ready(ha);
+	if (rval == QLA_SUCCESS) {
+		clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
+		qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
+	}
+
+	ha->flags.management_server_logged_in = 0;
+
+	/* Login to SNS first */
+	qla24xx_login_fabric(ha, NPH_SNS, 0xff, 0xff, 0xfc,
+	    mb, BIT_1);
+	if (mb[0] != MBS_COMMAND_COMPLETE) {
+		DEBUG15(qla_printk(KERN_INFO, ha,
+		    "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
+		    "mb[2]=%x mb[6]=%x mb[7]=%x\n", NPH_SNS,
+		    mb[0], mb[1], mb[2], mb[6], mb[7]));
+		return (QLA_FUNCTION_FAILED);
+	}
+
+	atomic_set(&ha->loop_down_timer, 0);
+	atomic_set(&ha->loop_state, LOOP_UP);
+	set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+	set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
+	rval = qla2x00_loop_resync(ha);
+
+	return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index c5b3c61..c71863f 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -155,6 +155,8 @@
 	uint32_t	*cur_dsd;
 	scsi_qla_host_t	*ha;
 	struct scsi_cmnd *cmd;
+	struct scatterlist *sg;
+	int i;
 
 	cmd = sp->cmd;
 
@@ -163,7 +165,7 @@
 	    __constant_cpu_to_le32(COMMAND_TYPE);
 
 	/* No data transfer */
-	if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+	if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
 		cmd_pkt->byte_count = __constant_cpu_to_le32(0);
 		return;
 	}
@@ -177,35 +179,23 @@
 	cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
 
 	/* Load data segments */
-	if (cmd->use_sg != 0) {
-		struct	scatterlist *cur_seg;
-		struct	scatterlist *end_seg;
+	scsi_for_each_sg(cmd, sg, tot_dsds, i) {
+		cont_entry_t *cont_pkt;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		end_seg = cur_seg + tot_dsds;
-		while (cur_seg < end_seg) {
-			cont_entry_t	*cont_pkt;
-
-			/* Allocate additional continuation packets? */
-			if (avail_dsds == 0) {
-				/*
-				 * Seven DSDs are available in the Continuation
-				 * Type 0 IOCB.
-				 */
-				cont_pkt = qla2x00_prep_cont_type0_iocb(ha);
-				cur_dsd = (uint32_t *)&cont_pkt->dseg_0_address;
-				avail_dsds = 7;
-			}
-
-			*cur_dsd++ = cpu_to_le32(sg_dma_address(cur_seg));
-			*cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
-			avail_dsds--;
-
-			cur_seg++;
+		/* Allocate additional continuation packets? */
+		if (avail_dsds == 0) {
+			/*
+			 * Seven DSDs are available in the Continuation
+			 * Type 0 IOCB.
+			 */
+			cont_pkt = qla2x00_prep_cont_type0_iocb(ha);
+			cur_dsd = (uint32_t *)&cont_pkt->dseg_0_address;
+			avail_dsds = 7;
 		}
-	} else {
-		*cur_dsd++ = cpu_to_le32(sp->dma_handle);
-		*cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
+
+		*cur_dsd++ = cpu_to_le32(sg_dma_address(sg));
+		*cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+		avail_dsds--;
 	}
 }
 
@@ -224,6 +214,8 @@
 	uint32_t	*cur_dsd;
 	scsi_qla_host_t	*ha;
 	struct scsi_cmnd *cmd;
+	struct scatterlist *sg;
+	int i;
 
 	cmd = sp->cmd;
 
@@ -232,7 +224,7 @@
 	    __constant_cpu_to_le32(COMMAND_A64_TYPE);
 
 	/* No data transfer */
-	if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+	if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
 		cmd_pkt->byte_count = __constant_cpu_to_le32(0);
 		return;
 	}
@@ -246,39 +238,26 @@
 	cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
 
 	/* Load data segments */
-	if (cmd->use_sg != 0) {
-		struct	scatterlist *cur_seg;
-		struct	scatterlist *end_seg;
+	scsi_for_each_sg(cmd, sg, tot_dsds, i) {
+		dma_addr_t	sle_dma;
+		cont_a64_entry_t *cont_pkt;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		end_seg = cur_seg + tot_dsds;
-		while (cur_seg < end_seg) {
-			dma_addr_t	sle_dma;
-			cont_a64_entry_t *cont_pkt;
-
-			/* Allocate additional continuation packets? */
-			if (avail_dsds == 0) {
-				/*
-				 * Five DSDs are available in the Continuation
-				 * Type 1 IOCB.
-				 */
-				cont_pkt = qla2x00_prep_cont_type1_iocb(ha);
-				cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
-				avail_dsds = 5;
-			}
-
-			sle_dma = sg_dma_address(cur_seg);
-			*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
-			*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
-			*cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
-			avail_dsds--;
-
-			cur_seg++;
+		/* Allocate additional continuation packets? */
+		if (avail_dsds == 0) {
+			/*
+			 * Five DSDs are available in the Continuation
+			 * Type 1 IOCB.
+			 */
+			cont_pkt = qla2x00_prep_cont_type1_iocb(ha);
+			cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
+			avail_dsds = 5;
 		}
-	} else {
-		*cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle));
-		*cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle));
-		*cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
+
+		sle_dma = sg_dma_address(sg);
+		*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+		*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+		*cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+		avail_dsds--;
 	}
 }
 
@@ -291,7 +270,7 @@
 int
 qla2x00_start_scsi(srb_t *sp)
 {
-	int		ret;
+	int		ret, nseg;
 	unsigned long   flags;
 	scsi_qla_host_t	*ha;
 	struct scsi_cmnd *cmd;
@@ -299,7 +278,6 @@
 	uint32_t        index;
 	uint32_t	handle;
 	cmd_entry_t	*cmd_pkt;
-	struct scatterlist *sg;
 	uint16_t	cnt;
 	uint16_t	req_cnt;
 	uint16_t	tot_dsds;
@@ -337,23 +315,15 @@
 		goto queuing_error;
 
 	/* Map the sg table so we have an accurate count of sg entries needed */
-	if (cmd->use_sg) {
-		sg = (struct scatterlist *) cmd->request_buffer;
-		tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
-		    cmd->sc_data_direction);
-		if (tot_dsds == 0)
+	if (scsi_sg_count(cmd)) {
+		nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
+		    scsi_sg_count(cmd), cmd->sc_data_direction);
+		if (unlikely(!nseg))
 			goto queuing_error;
-	} else if (cmd->request_bufflen) {
-		dma_addr_t	req_dma;
+	} else
+		nseg = 0;
 
-		req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
-		    cmd->request_bufflen, cmd->sc_data_direction);
-		if (dma_mapping_error(req_dma))
-			goto queuing_error;
-
-		sp->dma_handle = req_dma;
-		tot_dsds = 1;
-	}
+	tot_dsds = nseg;
 
 	/* Calculate the number of request entries needed. */
 	req_cnt = ha->isp_ops.calc_req_entries(tot_dsds);
@@ -391,7 +361,7 @@
 
 	/* Load SCSI command packet. */
 	memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len);
-	cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen);
+	cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
 
 	/* Build IOCB segments */
 	ha->isp_ops.build_iocbs(sp, cmd_pkt, tot_dsds);
@@ -423,14 +393,9 @@
 	return (QLA_SUCCESS);
 
 queuing_error:
-	if (cmd->use_sg && tot_dsds) {
-		sg = (struct scatterlist *) cmd->request_buffer;
-		pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
-		    cmd->sc_data_direction);
-	} else if (tot_dsds) {
-		pci_unmap_single(ha->pdev, sp->dma_handle,
-		    cmd->request_bufflen, cmd->sc_data_direction);
-	}
+	if (tot_dsds)
+		scsi_dma_unmap(cmd);
+
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	return (QLA_FUNCTION_FAILED);
@@ -453,9 +418,10 @@
 {
 	mrk_entry_t *mrk;
 	struct mrk_entry_24xx *mrk24;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	mrk24 = NULL;
-	mrk = (mrk_entry_t *)qla2x00_req_pkt(ha);
+	mrk = (mrk_entry_t *)qla2x00_req_pkt(pha);
 	if (mrk == NULL) {
 		DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n",
 		    __func__, ha->host_no));
@@ -472,6 +438,7 @@
 			mrk24->lun[1] = LSB(lun);
 			mrk24->lun[2] = MSB(lun);
 			host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
+			mrk24->vp_index = ha->vp_idx;
 		} else {
 			SET_TARGET_ID(ha, mrk->target, loop_id);
 			mrk->lun = cpu_to_le16(lun);
@@ -479,7 +446,7 @@
 	}
 	wmb();
 
-	qla2x00_isp_cmd(ha);
+	qla2x00_isp_cmd(pha);
 
 	return (QLA_SUCCESS);
 }
@@ -642,6 +609,8 @@
 	uint32_t	*cur_dsd;
 	scsi_qla_host_t	*ha;
 	struct scsi_cmnd *cmd;
+	struct scatterlist *sg;
+	int i;
 
 	cmd = sp->cmd;
 
@@ -650,7 +619,7 @@
 	    __constant_cpu_to_le32(COMMAND_TYPE_7);
 
 	/* No data transfer */
-	if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+	if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
 		cmd_pkt->byte_count = __constant_cpu_to_le32(0);
 		return;
 	}
@@ -670,39 +639,27 @@
 	cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
 
 	/* Load data segments */
-	if (cmd->use_sg != 0) {
-		struct	scatterlist *cur_seg;
-		struct	scatterlist *end_seg;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		end_seg = cur_seg + tot_dsds;
-		while (cur_seg < end_seg) {
-			dma_addr_t	sle_dma;
-			cont_a64_entry_t *cont_pkt;
+	scsi_for_each_sg(cmd, sg, tot_dsds, i) {
+		dma_addr_t	sle_dma;
+		cont_a64_entry_t *cont_pkt;
 
-			/* Allocate additional continuation packets? */
-			if (avail_dsds == 0) {
-				/*
-				 * Five DSDs are available in the Continuation
-				 * Type 1 IOCB.
-				 */
-				cont_pkt = qla2x00_prep_cont_type1_iocb(ha);
-				cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
-				avail_dsds = 5;
-			}
-
-			sle_dma = sg_dma_address(cur_seg);
-			*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
-			*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
-			*cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
-			avail_dsds--;
-
-			cur_seg++;
+		/* Allocate additional continuation packets? */
+		if (avail_dsds == 0) {
+			/*
+			 * Five DSDs are available in the Continuation
+			 * Type 1 IOCB.
+			 */
+			cont_pkt = qla2x00_prep_cont_type1_iocb(ha);
+			cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
+			avail_dsds = 5;
 		}
-	} else {
-		*cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle));
-		*cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle));
-		*cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
+
+		sle_dma = sg_dma_address(sg);
+		*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+		*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+		*cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+		avail_dsds--;
 	}
 }
 
@@ -716,7 +673,7 @@
 int
 qla24xx_start_scsi(srb_t *sp)
 {
-	int		ret;
+	int		ret, nseg;
 	unsigned long   flags;
 	scsi_qla_host_t	*ha;
 	struct scsi_cmnd *cmd;
@@ -724,7 +681,6 @@
 	uint32_t        index;
 	uint32_t	handle;
 	struct cmd_type_7 *cmd_pkt;
-	struct scatterlist *sg;
 	uint16_t	cnt;
 	uint16_t	req_cnt;
 	uint16_t	tot_dsds;
@@ -762,23 +718,15 @@
 		goto queuing_error;
 
 	/* Map the sg table so we have an accurate count of sg entries needed */
-	if (cmd->use_sg) {
-		sg = (struct scatterlist *) cmd->request_buffer;
-		tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
-		    cmd->sc_data_direction);
-		if (tot_dsds == 0)
+	if (scsi_sg_count(cmd)) {
+		nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
+		    scsi_sg_count(cmd), cmd->sc_data_direction);
+		if (unlikely(!nseg))
 			goto queuing_error;
-	} else if (cmd->request_bufflen) {
-		dma_addr_t      req_dma;
+	} else
+		nseg = 0;
 
-		req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
-		    cmd->request_bufflen, cmd->sc_data_direction);
-		if (dma_mapping_error(req_dma))
-			goto queuing_error;
-
-		sp->dma_handle = req_dma;
-		tot_dsds = 1;
-	}
+	tot_dsds = nseg;
 
 	req_cnt = qla24xx_calc_iocbs(tot_dsds);
 	if (ha->req_q_cnt < (req_cnt + 2)) {
@@ -813,6 +761,7 @@
 	cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
 	cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
 	cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
+	cmd_pkt->vp_index = sp->fcport->vp_idx;
 
 	int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
 	host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
@@ -821,7 +770,7 @@
 	memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
 	host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
 
-	cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen);
+	cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
 
 	/* Build IOCB segments */
 	qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds);
@@ -853,14 +802,9 @@
 	return QLA_SUCCESS;
 
 queuing_error:
-	if (cmd->use_sg && tot_dsds) {
-		sg = (struct scatterlist *) cmd->request_buffer;
-		pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
-		    cmd->sc_data_direction);
-	} else if (tot_dsds) {
-		pci_unmap_single(ha->pdev, sp->dma_handle,
-		    cmd->request_bufflen, cmd->sc_data_direction);
-	}
+	if (tot_dsds)
+		scsi_dma_unmap(cmd);
+
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	return QLA_FUNCTION_FAILED;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index ca46346..0ba4c8d 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -9,7 +9,6 @@
 #include <scsi/scsi_tcq.h>
 
 static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
-static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);
 static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
 static void qla2x00_status_entry(scsi_qla_host_t *, void *);
 static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
@@ -244,7 +243,7 @@
  * @ha: SCSI driver HA context
  * @mb: Mailbox registers (0 - 3)
  */
-static void
+void
 qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 {
 #define LS_UNKNOWN	2
@@ -386,6 +385,11 @@
 			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
+		if (ha->parent) {
+			atomic_set(&ha->vp_state, VP_FAILED);
+			fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+		}
+
 		set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
 
 		ha->flags.management_server_logged_in = 0;
@@ -422,6 +426,11 @@
 			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
+		if (ha->parent) {
+			atomic_set(&ha->vp_state, VP_FAILED);
+			fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+		}
+
 		ha->flags.management_server_logged_in = 0;
 		ha->link_data_rate = PORT_SPEED_UNKNOWN;
 		if (ql2xfdmienable)
@@ -440,6 +449,11 @@
 			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
+		if (ha->parent) {
+			atomic_set(&ha->vp_state, VP_FAILED);
+			fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+		}
+
 		set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
 
 		ha->operating_mode = LOOP;
@@ -465,6 +479,11 @@
 			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
+		if (ha->parent) {
+			atomic_set(&ha->vp_state, VP_FAILED);
+			fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+		}
+
 		if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) {
 			set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
 		}
@@ -491,6 +510,11 @@
 			qla2x00_mark_all_devices_lost(ha, 1);
 		}
 
+		if (ha->parent) {
+			atomic_set(&ha->vp_state, VP_FAILED);
+			fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+		}
+
 		set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
 		set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
 		break;
@@ -530,6 +554,10 @@
 		break;
 
 	case MBA_RSCN_UPDATE:		/* State Change Registration */
+		/* Check if the Vport has issued a SCR */
+		if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags))
+			break;
+
 		DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
 		    ha->host_no));
 		DEBUG(printk(KERN_INFO
@@ -589,6 +617,9 @@
 		ha->host_no, mb[1], mb[2]));
 		break;
 	}
+
+	if (!ha->parent && ha->num_vhosts)
+		qla2x00_alert_all_vps(ha, mb);
 }
 
 static void
@@ -889,19 +920,19 @@
 		}
 		if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
 			resid = resid_len;
-			cp->resid = resid;
+			scsi_set_resid(cp, resid);
 			CMD_RESID_LEN(cp) = resid;
 
 			if (!lscsi_status &&
-			    ((unsigned)(cp->request_bufflen - resid) <
+			    ((unsigned)(scsi_bufflen(cp) - resid) <
 			     cp->underflow)) {
 				qla_printk(KERN_INFO, ha,
-				    "scsi(%ld:%d:%d:%d): Mid-layer underflow "
-				    "detected (%x of %x bytes)...returning "
-				    "error status.\n", ha->host_no,
-				    cp->device->channel, cp->device->id,
-				    cp->device->lun, resid,
-				    cp->request_bufflen);
+					   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
+					   "detected (%x of %x bytes)...returning "
+					   "error status.\n", ha->host_no,
+					   cp->device->channel, cp->device->id,
+					   cp->device->lun, resid,
+					   scsi_bufflen(cp));
 
 				cp->result = DID_ERROR << 16;
 				break;
@@ -963,7 +994,7 @@
 			resid = fw_resid_len;
 
 		if (scsi_status & SS_RESIDUAL_UNDER) {
-			cp->resid = resid;
+			scsi_set_resid(cp, resid);
 			CMD_RESID_LEN(cp) = resid;
 		} else {
 			DEBUG2(printk(KERN_INFO
@@ -1042,26 +1073,26 @@
 			 */
 			if (!(scsi_status & SS_RESIDUAL_UNDER)) {
 				DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped "
-				    "frame(s) detected (%x of %x bytes)..."
-				    "retrying command.\n", ha->host_no,
-				    cp->device->channel, cp->device->id,
-				    cp->device->lun, resid,
-				    cp->request_bufflen));
+					      "frame(s) detected (%x of %x bytes)..."
+					      "retrying command.\n", ha->host_no,
+					      cp->device->channel, cp->device->id,
+					      cp->device->lun, resid,
+					      scsi_bufflen(cp)));
 
 				cp->result = DID_BUS_BUSY << 16;
 				break;
 			}
 
 			/* Handle mid-layer underflow */
-			if ((unsigned)(cp->request_bufflen - resid) <
+			if ((unsigned)(scsi_bufflen(cp) - resid) <
 			    cp->underflow) {
 				qla_printk(KERN_INFO, ha,
-				    "scsi(%ld:%d:%d:%d): Mid-layer underflow "
-				    "detected (%x of %x bytes)...returning "
-				    "error status.\n", ha->host_no,
-				    cp->device->channel, cp->device->id,
-				    cp->device->lun, resid,
-				    cp->request_bufflen);
+					   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
+					   "detected (%x of %x bytes)...returning "
+					   "error status.\n", ha->host_no,
+					   cp->device->channel, cp->device->id,
+					   cp->device->lun, resid,
+					   scsi_bufflen(cp));
 
 				cp->result = DID_ERROR << 16;
 				break;
@@ -1084,7 +1115,7 @@
 		DEBUG2(printk(KERN_INFO
 		    "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR "
 		    "status!\n",
-		    cp->serial_number, cp->request_bufflen, resid_len));
+		    cp->serial_number, scsi_bufflen(cp), resid_len));
 
 		cp->result = DID_ERROR << 16;
 		break;
@@ -1393,6 +1424,10 @@
 		case MS_IOCB_TYPE:
 			qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
 			break;
+		case VP_RPT_ID_IOCB_TYPE:
+			qla24xx_report_id_acquisition(ha,
+			    (struct vp_rpt_id_entry_24xx *)pkt);
+			break;
 		default:
 			/* Type Not Supported. */
 			DEBUG4(printk(KERN_WARNING
@@ -1633,7 +1668,7 @@
 	uint16_t entry;
 	uint16_t index;
 	const char *name;
-	irqreturn_t (*handler)(int, void *);
+	irq_handler_t handler;
 };
 
 static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 71e32a2..2cd0cff 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -42,25 +42,29 @@
  *	Kernel context.
  */
 static int
-qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
+qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
 {
 	int		rval;
 	unsigned long    flags = 0;
-	device_reg_t __iomem *reg = ha->iobase;
+	device_reg_t __iomem *reg;
 	struct timer_list	tmp_intr_timer;
 	uint8_t		abort_active;
-	uint8_t		io_lock_on = ha->flags.init_done;
+	uint8_t		io_lock_on;
 	uint16_t	command;
 	uint16_t	*iptr;
 	uint16_t __iomem *optr;
 	uint32_t	cnt;
 	uint32_t	mboxes;
 	unsigned long	wait_time;
+	scsi_qla_host_t *ha = to_qla_parent(pvha);
+
+	reg = ha->iobase;
+	io_lock_on = ha->flags.init_done;
 
 	rval = QLA_SUCCESS;
 	abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
 
-	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+	DEBUG11(printk("%s(%ld): entered.\n", __func__, pvha->host_no));
 
 	/*
 	 * Wait for active mailbox commands to finish by waiting at most tov
@@ -889,7 +893,7 @@
  */
 int
 qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
-    uint8_t *area, uint8_t *domain, uint16_t *top)
+    uint8_t *area, uint8_t *domain, uint16_t *top, uint16_t *sw_cap)
 {
 	int rval;
 	mbx_cmd_t mc;
@@ -899,8 +903,9 @@
 	    ha->host_no));
 
 	mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID;
+	mcp->mb[9] = ha->vp_idx;
 	mcp->out_mb = MBX_0;
-	mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
 	mcp->tov = 30;
 	mcp->flags = 0;
 	rval = qla2x00_mailbox_command(ha, mcp);
@@ -913,6 +918,7 @@
 	*area = MSB(mcp->mb[2]);
 	*domain	= LSB(mcp->mb[3]);
 	*top = mcp->mb[6];
+	*sw_cap = mcp->mb[7];
 
 	if (rval != QLA_SUCCESS) {
 		/*EMPTY*/
@@ -1009,7 +1015,11 @@
 	DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n",
 	    ha->host_no));
 
-	mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
+	if (ha->flags.npiv_supported)
+		mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE;
+	else
+		mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
+
 	mcp->mb[2] = MSW(ha->init_cb_dma);
 	mcp->mb[3] = LSW(ha->init_cb_dma);
 	mcp->mb[4] = 0;
@@ -1081,7 +1091,8 @@
 	mcp->mb[3] = LSW(pd_dma);
 	mcp->mb[6] = MSW(MSD(pd_dma));
 	mcp->mb[7] = LSW(MSD(pd_dma));
-	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
+	mcp->mb[9] = ha->vp_idx;
+	mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
 	mcp->in_mb = MBX_0;
 	if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
 		mcp->mb[1] = fcport->loop_id;
@@ -1259,7 +1270,8 @@
 	    ha->host_no));
 
 	mcp->mb[0] = MBC_GET_PORT_NAME;
-	mcp->out_mb = MBX_1|MBX_0;
+	mcp->mb[9] = ha->vp_idx;
+	mcp->out_mb = MBX_9|MBX_1|MBX_0;
 	if (HAS_EXTENDED_IDS(ha)) {
 		mcp->mb[1] = loop_id;
 		mcp->mb[10] = opt;
@@ -1447,6 +1459,7 @@
 	lg->port_id[0] = al_pa;
 	lg->port_id[1] = area;
 	lg->port_id[2] = domain;
+	lg->vp_index = cpu_to_le16(ha->vp_idx);
 	rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
 	if (rval != QLA_SUCCESS) {
 		DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
@@ -1701,6 +1714,7 @@
 	lg->port_id[0] = al_pa;
 	lg->port_id[1] = area;
 	lg->port_id[2] = domain;
+	lg->vp_index = cpu_to_le16(ha->vp_idx);
 	rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
 	if (rval != QLA_SUCCESS) {
 		DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
@@ -1863,7 +1877,8 @@
 		mcp->mb[6] = MSW(MSD(id_list_dma));
 		mcp->mb[7] = LSW(MSD(id_list_dma));
 		mcp->mb[8] = 0;
-		mcp->out_mb |= MBX_8|MBX_7|MBX_6|MBX_3|MBX_2;
+		mcp->mb[9] = ha->vp_idx;
+		mcp->out_mb |= MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2;
 	} else {
 		mcp->mb[1] = MSW(id_list_dma);
 		mcp->mb[2] = LSW(id_list_dma);
@@ -2212,6 +2227,7 @@
 	abt->port_id[0] = fcport->d_id.b.al_pa;
 	abt->port_id[1] = fcport->d_id.b.area;
 	abt->port_id[2] = fcport->d_id.b.domain;
+	abt->vp_index = fcport->vp_idx;
 	rval = qla2x00_issue_iocb(ha, abt, abt_dma, 0);
 	if (rval != QLA_SUCCESS) {
 		DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n",
@@ -2249,7 +2265,7 @@
 	int		rval;
 	struct tsk_mgmt_cmd *tsk;
 	dma_addr_t	tsk_dma;
-	scsi_qla_host_t *ha;
+	scsi_qla_host_t *ha, *pha;
 
 	if (fcport == NULL)
 		return 0;
@@ -2257,7 +2273,8 @@
 	DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
 
 	ha = fcport->ha;
-	tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
+	pha = to_qla_parent(ha);
+	tsk = dma_pool_alloc(pha->s_dma_pool, GFP_KERNEL, &tsk_dma);
 	if (tsk == NULL) {
 		DEBUG2_3(printk("%s(%ld): failed to allocate Task Management "
 		    "IOCB.\n", __func__, ha->host_no));
@@ -2273,6 +2290,8 @@
 	tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
 	tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
 	tsk->p.tsk.port_id[2] = fcport->d_id.b.domain;
+	tsk->p.tsk.vp_index = fcport->vp_idx;
+
 	rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0);
 	if (rval != QLA_SUCCESS) {
 		DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB "
@@ -2303,7 +2322,7 @@
 	}
 
 atarget_done:
-	dma_pool_free(ha->s_dma_pool, tsk, tsk_dma);
+	dma_pool_free(pha->s_dma_pool, tsk, tsk_dma);
 
 	return rval;
 }
@@ -2610,3 +2629,354 @@
 
 	return rval;
 }
+
+/*
+ * qla24xx_get_vp_database
+ *	Get the VP's database for all configured ports.
+ *
+ * Input:
+ *	ha = adapter block pointer.
+ *	size = size of initialization control block.
+ *
+ * Returns:
+ *	qla2x00 local function return status code.
+ *
+ * Context:
+ *	Kernel context.
+ */
+int
+qla24xx_get_vp_database(scsi_qla_host_t *ha, uint16_t size)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	DEBUG11(printk("scsi(%ld):%s - entered.\n",
+	    ha->host_no, __func__));
+
+	mcp->mb[0] = MBC_MID_GET_VP_DATABASE;
+	mcp->mb[2] = MSW(ha->init_cb_dma);
+	mcp->mb[3] = LSW(ha->init_cb_dma);
+	mcp->mb[4] = 0;
+	mcp->mb[5] = 0;
+	mcp->mb[6] = MSW(MSD(ha->init_cb_dma));
+	mcp->mb[7] = LSW(MSD(ha->init_cb_dma));
+	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
+	mcp->in_mb = MBX_1|MBX_0;
+	mcp->buf_size = size;
+	mcp->flags = MBX_DMA_OUT;
+	mcp->tov = MBX_TOV_SECONDS;
+	rval = qla2x00_mailbox_command(ha, mcp);
+
+	if (rval != QLA_SUCCESS) {
+		/*EMPTY*/
+		DEBUG2_3_11(printk("%s(%ld): failed=%x "
+		    "mb0=%x.\n",
+		    __func__, ha->host_no, rval, mcp->mb[0]));
+	} else {
+		/*EMPTY*/
+		DEBUG11(printk("%s(%ld): done.\n",
+		    __func__, ha->host_no));
+	}
+
+	return rval;
+}
+
+int
+qla24xx_get_vp_entry(scsi_qla_host_t *ha, uint16_t size, int vp_id)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+	mcp->mb[0] = MBC_MID_GET_VP_ENTRY;
+	mcp->mb[2] = MSW(ha->init_cb_dma);
+	mcp->mb[3] = LSW(ha->init_cb_dma);
+	mcp->mb[4] = 0;
+	mcp->mb[5] = 0;
+	mcp->mb[6] = MSW(MSD(ha->init_cb_dma));
+	mcp->mb[7] = LSW(MSD(ha->init_cb_dma));
+	mcp->mb[9] = vp_id;
+	mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
+	mcp->in_mb = MBX_0;
+	mcp->buf_size = size;
+	mcp->flags = MBX_DMA_OUT;
+	mcp->tov = 30;
+	rval = qla2x00_mailbox_command(ha, mcp);
+
+	if (rval != QLA_SUCCESS) {
+		/*EMPTY*/
+		DEBUG2_3_11(printk("qla24xx_get_vp_entry(%ld): failed=%x "
+		    "mb0=%x.\n",
+		    ha->host_no, rval, mcp->mb[0]));
+	} else {
+		/*EMPTY*/
+		DEBUG11(printk("qla24xx_get_vp_entry(%ld): done.\n",
+		    ha->host_no));
+	}
+
+	return rval;
+}
+
+void
+qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
+	struct vp_rpt_id_entry_24xx *rptid_entry)
+{
+	uint8_t vp_idx;
+	scsi_qla_host_t *vha;
+
+	if (rptid_entry->entry_status != 0)
+		return;
+	if (rptid_entry->entry_status != __constant_cpu_to_le16(CS_COMPLETE))
+		return;
+
+	if (rptid_entry->format == 0) {
+		DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d,"
+			" number of VPs acquired %d\n", __func__, ha->host_no,
+			MSB(rptid_entry->vp_count), LSB(rptid_entry->vp_count)));
+		DEBUG15(printk("%s primary port id %02x%02x%02x\n", __func__,
+			rptid_entry->port_id[2], rptid_entry->port_id[1],
+			rptid_entry->port_id[0]));
+	} else if (rptid_entry->format == 1) {
+		vp_idx = LSB(rptid_entry->vp_idx);
+		DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled "
+		    "- status %d - "
+		    "with port id %02x%02x%02x\n",__func__,ha->host_no,
+		    vp_idx, MSB(rptid_entry->vp_idx),
+		    rptid_entry->port_id[2], rptid_entry->port_id[1],
+		    rptid_entry->port_id[0]));
+		if (vp_idx == 0)
+			return;
+
+		if (MSB(rptid_entry->vp_idx) == 1)
+			return;
+
+		list_for_each_entry(vha, &ha->vp_list, vp_list)
+			if (vp_idx == vha->vp_idx)
+				break;
+
+		if (!vha)
+			return;
+
+		vha->d_id.b.domain = rptid_entry->port_id[2];
+		vha->d_id.b.area =  rptid_entry->port_id[1];
+		vha->d_id.b.al_pa = rptid_entry->port_id[0];
+
+		/*
+		 * Cannot configure here as we are still sitting on the
+		 * response queue. Handle it in dpc context.
+		 */
+		set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
+		set_bit(VP_DPC_NEEDED, &ha->dpc_flags);
+
+		wake_up_process(ha->dpc_thread);
+	}
+}
+
+/*
+ * qla24xx_modify_vp_config
+ *	Change VP configuration for vha
+ *
+ * Input:
+ *	vha = adapter block pointer.
+ *
+ * Returns:
+ *	qla2xxx local function return status code.
+ *
+ * Context:
+ *	Kernel context.
+ */
+int
+qla24xx_modify_vp_config(scsi_qla_host_t *vha)
+{
+	int		rval;
+	struct vp_config_entry_24xx *vpmod;
+	dma_addr_t	vpmod_dma;
+	scsi_qla_host_t *pha;
+
+	/* This can be called by the parent */
+	pha = to_qla_parent(vha);
+
+	vpmod = dma_pool_alloc(pha->s_dma_pool, GFP_KERNEL, &vpmod_dma);
+	if (!vpmod) {
+		DEBUG2_3(printk("%s(%ld): failed to allocate Modify VP "
+		    "IOCB.\n", __func__, pha->host_no));
+		return QLA_MEMORY_ALLOC_FAILED;
+	}
+
+	memset(vpmod, 0, sizeof(struct vp_config_entry_24xx));
+	vpmod->entry_type = VP_CONFIG_IOCB_TYPE;
+	vpmod->entry_count = 1;
+	vpmod->command = VCT_COMMAND_MOD_ENABLE_VPS;
+	vpmod->vp_count = 1;
+	vpmod->vp_index1 = vha->vp_idx;
+	vpmod->options_idx1 = BIT_3|BIT_4|BIT_5;
+	memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE);
+	memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE);
+	vpmod->entry_count = 1;
+
+	rval = qla2x00_issue_iocb(pha, vpmod, vpmod_dma, 0);
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk("%s(%ld): failed to issue VP config IOCB"
+			"(%x).\n", __func__, pha->host_no, rval));
+	} else if (vpmod->comp_status != 0) {
+		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+			"-- error status (%x).\n", __func__, pha->host_no,
+			vpmod->comp_status));
+		rval = QLA_FUNCTION_FAILED;
+	} else if (vpmod->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
+		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+		    "-- completion status (%x).\n", __func__, pha->host_no,
+		    le16_to_cpu(vpmod->comp_status)));
+		rval = QLA_FUNCTION_FAILED;
+	} else {
+		/* EMPTY */
+		DEBUG11(printk("%s(%ld): done.\n", __func__, pha->host_no));
+		fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING);
+	}
+	dma_pool_free(pha->s_dma_pool, vpmod, vpmod_dma);
+
+	return rval;
+}
+
+/*
+ * qla24xx_control_vp
+ *	Enable a virtual port for given host
+ *
+ * Input:
+ *	ha = adapter block pointer.
+ *	vhba = virtual adapter (unused)
+ *	index = index number for enabled VP
+ *
+ * Returns:
+ *	qla2xxx local function return status code.
+ *
+ * Context:
+ *	Kernel context.
+ */
+int
+qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
+{
+	int		rval;
+	int		map, pos;
+	struct vp_ctrl_entry_24xx   *vce;
+	dma_addr_t	vce_dma;
+	scsi_qla_host_t *ha = vha->parent;
+	int	vp_index = vha->vp_idx;
+
+	DEBUG11(printk("%s(%ld): entered. Enabling index %d\n", __func__,
+	    ha->host_no, vp_index));
+
+	if (vp_index == 0 || vp_index >= MAX_MULTI_ID_LOOP)
+		return QLA_PARAMETER_ERROR;
+
+	vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma);
+	if (!vce) {
+		DEBUG2_3(printk("%s(%ld): "
+		    "failed to allocate VP Control IOCB.\n", __func__,
+		    ha->host_no));
+		return QLA_MEMORY_ALLOC_FAILED;
+	}
+	memset(vce, 0, sizeof(struct vp_ctrl_entry_24xx));
+
+	vce->entry_type = VP_CTRL_IOCB_TYPE;
+	vce->entry_count = 1;
+	vce->command = cpu_to_le16(cmd);
+	vce->vp_count = __constant_cpu_to_le16(1);
+
+	/* index map in firmware starts with 1; decrement index
+	 * this is ok as we never use index 0
+	 */
+	map = (vp_index - 1) / 8;
+	pos = (vp_index - 1) & 7;
+	down(&ha->vport_sem);
+	vce->vp_idx_map[map] |= 1 << pos;
+	up(&ha->vport_sem);
+
+	rval = qla2x00_issue_iocb(ha, vce, vce_dma, 0);
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk("%s(%ld): failed to issue VP control IOCB"
+		    "(%x).\n", __func__, ha->host_no, rval));
+		printk("%s(%ld): failed to issue VP control IOCB"
+		    "(%x).\n", __func__, ha->host_no, rval);
+	} else if (vce->entry_status != 0) {
+		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+		    "-- error status (%x).\n", __func__, ha->host_no,
+		    vce->entry_status));
+		printk("%s(%ld): failed to complete IOCB "
+		    "-- error status (%x).\n", __func__, ha->host_no,
+		    vce->entry_status);
+		rval = QLA_FUNCTION_FAILED;
+	} else if (vce->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
+		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+		    "-- completion status (%x).\n", __func__, ha->host_no,
+		    le16_to_cpu(vce->comp_status)));
+		printk("%s(%ld): failed to complete IOCB "
+		    "-- completion status (%x).\n", __func__, ha->host_no,
+		    le16_to_cpu(vce->comp_status));
+		rval = QLA_FUNCTION_FAILED;
+	} else {
+		DEBUG2(printk("%s(%ld): done.\n", __func__, ha->host_no));
+	}
+
+	dma_pool_free(ha->s_dma_pool, vce, vce_dma);
+
+	return rval;
+}
+
+/*
+ * qla2x00_send_change_request
+ *	Receive or disable RSCN request from fabric controller
+ *
+ * Input:
+ *	ha = adapter block pointer
+ *	format = registration format:
+ *		0 - Reserved
+ *		1 - Fabric detected registration
+ *		2 - N_port detected registration
+ *		3 - Full registration
+ *		FF - clear registration
+ *	vp_idx = Virtual port index
+ *
+ * Returns:
+ *	qla2x00 local function return status code.
+ *
+ * Context:
+ *	Kernel Context
+ */
+
+int
+qla2x00_send_change_request(scsi_qla_host_t *ha, uint16_t format,
+			    uint16_t vp_idx)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	/*
+	 * This command is implicitly executed by firmware during login for the
+	 * physical hosts
+	 */
+	if (vp_idx == 0)
+		return QLA_FUNCTION_FAILED;
+
+	mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
+	mcp->mb[1] = format;
+	mcp->mb[9] = vp_idx;
+	mcp->out_mb = MBX_9|MBX_1|MBX_0;
+	mcp->in_mb = MBX_0|MBX_1;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(ha, mcp);
+
+	if (rval == QLA_SUCCESS) {
+		if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
+			rval = BIT_1;
+		}
+	} else
+		rval = BIT_1;
+
+	return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
new file mode 100644
index 0000000..54dc415
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -0,0 +1,497 @@
+/*
+ *                  QLOGIC LINUX SOFTWARE
+ *
+ * QLogic ISP2x00 device driver for Linux 2.6.x
+ * Copyright (C) 2003-2005 QLogic Corporation
+ * (www.qlogic.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ */
+#include "qla_def.h"
+
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
+#include <linux/list.h>
+
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsicam.h>
+#include <linux/delay.h>
+
+void qla2x00_vp_stop_timer(scsi_qla_host_t *);
+
+void
+qla2x00_vp_stop_timer(scsi_qla_host_t *vha)
+{
+	if (vha->parent && vha->timer_active) {
+		del_timer_sync(&vha->timer);
+		vha->timer_active = 0;
+	}
+}
+
+uint32_t
+qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
+{
+	uint32_t vp_id;
+	scsi_qla_host_t *ha = vha->parent;
+
+	/* Find an empty slot and assign an vp_id */
+	down(&ha->vport_sem);
+	vp_id = find_first_zero_bit((unsigned long *)ha->vp_idx_map,
+				MAX_MULTI_ID_FABRIC);
+	if (vp_id > MAX_MULTI_ID_FABRIC) {
+		DEBUG15(printk ("vp_id %d is bigger than MAX_MULTI_ID_FABRID\n",
+		    vp_id));
+		up(&ha->vport_sem);
+		return vp_id;
+	}
+
+	set_bit(vp_id, (unsigned long *)ha->vp_idx_map);
+	ha->num_vhosts++;
+	vha->vp_idx = vp_id;
+	list_add_tail(&vha->vp_list, &ha->vp_list);
+	up(&ha->vport_sem);
+	return vp_id;
+}
+
+void
+qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
+{
+	uint16_t vp_id;
+	scsi_qla_host_t *ha = vha->parent;
+
+	down(&ha->vport_sem);
+	vp_id = vha->vp_idx;
+	ha->num_vhosts--;
+	clear_bit(vp_id, (unsigned long *)ha->vp_idx_map);
+	list_del(&vha->vp_list);
+	up(&ha->vport_sem);
+}
+
+scsi_qla_host_t *
+qla24xx_find_vhost_by_name(scsi_qla_host_t *ha, uint8_t *port_name)
+{
+	scsi_qla_host_t *vha;
+
+	/* Locate matching device in database. */
+	list_for_each_entry(vha, &ha->vp_list, vp_list) {
+		if (!memcmp(port_name, vha->port_name, WWN_SIZE))
+			return vha;
+	}
+	return NULL;
+}
+
+/*
+ * qla2x00_mark_vp_devices_dead
+ *	Updates fcport state when device goes offline.
+ *
+ * Input:
+ *	ha = adapter block pointer.
+ *	fcport = port structure pointer.
+ *
+ * Return:
+ *	None.
+ *
+ * Context:
+ */
+void
+qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
+{
+	fc_port_t *fcport;
+	scsi_qla_host_t *pha = to_qla_parent(vha);
+
+	list_for_each_entry(fcport, &pha->fcports, list) {
+		if (fcport->vp_idx != vha->vp_idx)
+			continue;
+
+		DEBUG15(printk("scsi(%ld): Marking port dead, "
+		    "loop_id=0x%04x :%x\n",
+		    vha->host_no, fcport->loop_id, fcport->vp_idx));
+
+		atomic_set(&fcport->state, FCS_DEVICE_DEAD);
+		qla2x00_mark_device_lost(vha, fcport, 0, 0);
+	}
+}
+
+int
+qla24xx_disable_vp(scsi_qla_host_t *vha)
+{
+	int ret;
+
+	ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
+	atomic_set(&vha->loop_state, LOOP_DOWN);
+	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
+
+	/* Delete all vp's fcports from parent's list */
+	qla2x00_mark_vp_devices_dead(vha);
+	atomic_set(&vha->vp_state, VP_FAILED);
+	vha->flags.management_server_logged_in = 0;
+	if (ret == QLA_SUCCESS) {
+		fc_vport_set_state(vha->fc_vport, FC_VPORT_DISABLED);
+	} else {
+		fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
+		return -1;
+	}
+	return 0;
+}
+
+int
+qla24xx_enable_vp(scsi_qla_host_t *vha)
+{
+	int ret;
+	scsi_qla_host_t *ha = vha->parent;
+
+	/* Check if physical ha port is Up */
+	if (atomic_read(&ha->loop_state) == LOOP_DOWN  ||
+		atomic_read(&ha->loop_state) == LOOP_DEAD ) {
+		vha->vp_err_state =  VP_ERR_PORTDWN;
+		fc_vport_set_state(vha->fc_vport, FC_VPORT_LINKDOWN);
+		goto enable_failed;
+	}
+
+	/* Initialize the new vport unless it is a persistent port */
+	down(&ha->vport_sem);
+	ret = qla24xx_modify_vp_config(vha);
+	up(&ha->vport_sem);
+
+	if (ret != QLA_SUCCESS) {
+		fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
+		goto enable_failed;
+	}
+
+	DEBUG15(qla_printk(KERN_INFO, ha,
+	    "Virtual port with id: %d - Enabled\n", vha->vp_idx));
+	return 0;
+
+enable_failed:
+	DEBUG15(qla_printk(KERN_INFO, ha,
+	    "Virtual port with id: %d - Disabled\n", vha->vp_idx));
+	return 1;
+}
+
+/**
+ * qla24xx_modify_vport() -  Modifies the virtual fabric port's configuration
+ * @ha: HA context
+ * @vp: pointer to buffer of virtual port parameters.
+ * @ret_code: return error code:
+ *
+ * Returns the virtual port id, or MAX_VSAN_ID, if couldn't create.
+ */
+uint32_t
+qla24xx_modify_vhba(scsi_qla_host_t *ha, vport_params_t *vp, uint32_t *vp_id)
+{
+	scsi_qla_host_t *vha;
+
+	vha = qla24xx_find_vhost_by_name(ha, vp->port_name);
+	if (!vha) {
+		*vp_id = MAX_NUM_VPORT_LOOP;
+		return VP_RET_CODE_WWPN;
+	}
+
+	if (qla24xx_enable_vp(vha)) {
+		scsi_host_put(vha->host);
+		qla2x00_mem_free(vha);
+		*vp_id = MAX_NUM_VPORT_LOOP;
+		return VP_RET_CODE_RESOURCES;
+	}
+
+	*vp_id = vha->vp_idx;
+	return VP_RET_CODE_OK;
+}
+
+void
+qla24xx_configure_vp(scsi_qla_host_t *vha)
+{
+	struct fc_vport *fc_vport;
+	int ret;
+
+	fc_vport = vha->fc_vport;
+
+	DEBUG15(printk("scsi(%ld): %s: change request #3 for this host.\n",
+	    vha->host_no, __func__));
+	ret = qla2x00_send_change_request(vha, 0x3, vha->vp_idx);
+	if (ret != QLA_SUCCESS) {
+		DEBUG15(qla_printk(KERN_ERR, vha, "Failed to enable receiving"
+		    " of RSCN requests: 0x%x\n", ret));
+		return;
+	} else {
+		/* Corresponds to SCR enabled */
+		clear_bit(VP_SCR_NEEDED, &vha->vp_flags);
+	}
+
+	vha->flags.online = 1;
+	if (qla24xx_configure_vhba(vha))
+		return;
+
+	atomic_set(&vha->vp_state, VP_ACTIVE);
+	fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
+}
+
+void
+qla2x00_alert_all_vps(scsi_qla_host_t *ha, uint16_t *mb)
+{
+	int i, vp_idx_matched;
+	scsi_qla_host_t *vha;
+
+	if (ha->parent)
+		return;
+
+	i = find_next_bit((unsigned long *)ha->vp_idx_map,
+	    MAX_MULTI_ID_FABRIC + 1, 1);
+	for (;i <= MAX_MULTI_ID_FABRIC;
+	    i = find_next_bit((unsigned long *)ha->vp_idx_map,
+	    MAX_MULTI_ID_FABRIC + 1, i + 1)) {
+		vp_idx_matched = 0;
+
+		list_for_each_entry(vha, &ha->vp_list, vp_list) {
+			if (i == vha->vp_idx) {
+				vp_idx_matched = 1;
+				break;
+			}
+		}
+
+		if (vp_idx_matched) {
+			switch (mb[0]) {
+			case MBA_LIP_OCCURRED:
+			case MBA_LOOP_UP:
+			case MBA_LOOP_DOWN:
+			case MBA_LIP_RESET:
+			case MBA_POINT_TO_POINT:
+			case MBA_CHG_IN_CONNECTION:
+			case MBA_PORT_UPDATE:
+			case MBA_RSCN_UPDATE:
+				DEBUG15(printk("scsi(%ld)%s: Async_event for"
+				    " VP[%d], mb = 0x%x, vha=%p\n",
+				    vha->host_no, __func__,i, *mb, vha));
+				qla2x00_async_event(vha, mb);
+				break;
+			}
+		}
+	}
+}
+
+void
+qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
+{
+	/*
+	 * Physical port will do most of the abort and recovery work. We can
+	 * just treat it as a loop down
+	 */
+	if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
+		atomic_set(&vha->loop_state, LOOP_DOWN);
+		qla2x00_mark_all_devices_lost(vha, 0);
+	} else {
+		if (!atomic_read(&vha->loop_down_timer))
+			atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
+	}
+
+	DEBUG15(printk("scsi(%ld): Scheduling enable of Vport %d...\n",
+	    vha->host_no, vha->vp_idx));
+	qla24xx_enable_vp(vha);
+}
+
+int
+qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
+{
+	if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
+		/* VP acquired. complete port configuration */
+		qla24xx_configure_vp(vha);
+		return 0;
+	}
+
+	if (test_and_clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
+		qla2x00_vp_abort_isp(vha);
+
+	if (test_and_clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) &&
+	    (!(test_and_set_bit(RESET_ACTIVE, &vha->dpc_flags)))) {
+		clear_bit(RESET_ACTIVE, &vha->dpc_flags);
+	}
+
+	if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
+		if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))) {
+			qla2x00_loop_resync(vha);
+			clear_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags);
+		}
+	}
+
+	return 0;
+}
+
+void
+qla2x00_do_dpc_all_vps(scsi_qla_host_t *ha)
+{
+	int ret;
+	int i, vp_idx_matched;
+	scsi_qla_host_t *vha;
+
+	if (ha->parent)
+		return;
+	if (list_empty(&ha->vp_list))
+		return;
+
+	clear_bit(VP_DPC_NEEDED, &ha->dpc_flags);
+
+	i = find_next_bit((unsigned long *)ha->vp_idx_map,
+	    MAX_MULTI_ID_FABRIC + 1, 1);
+	for (;i <= MAX_MULTI_ID_FABRIC;
+	    i = find_next_bit((unsigned long *)ha->vp_idx_map,
+	    MAX_MULTI_ID_FABRIC + 1, i + 1)) {
+		vp_idx_matched = 0;
+
+		list_for_each_entry(vha, &ha->vp_list, vp_list) {
+			if (i == vha->vp_idx) {
+				vp_idx_matched = 1;
+				break;
+			}
+		}
+
+		if (vp_idx_matched)
+			ret = qla2x00_do_dpc_vp(vha);
+	}
+}
+
+int
+qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
+{
+	scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+	scsi_qla_host_t *vha;
+	uint8_t port_name[WWN_SIZE];
+
+	if (fc_vport->roles != FC_PORT_ROLE_FCP_INITIATOR)
+		return VPCERR_UNSUPPORTED;
+
+	/* Check up the F/W and H/W support NPIV */
+	if (!ha->flags.npiv_supported)
+		return VPCERR_UNSUPPORTED;
+
+	/* Check up whether npiv supported switch presented */
+	if (!(ha->switch_cap & FLOGI_MID_SUPPORT))
+		return VPCERR_NO_FABRIC_SUPP;
+
+	/* Check up unique WWPN */
+	u64_to_wwn(fc_vport->port_name, port_name);
+	vha = qla24xx_find_vhost_by_name(ha, port_name);
+	if (vha)
+		return VPCERR_BAD_WWN;
+
+	/* Check up max-npiv-supports */
+	if (ha->num_vhosts > ha->max_npiv_vports) {
+		DEBUG15(printk("scsi(%ld): num_vhosts %d is bigger than "
+		    "max_npv_vports %d.\n", ha->host_no,
+		    (uint16_t) ha->num_vhosts, (int) ha->max_npiv_vports));
+		return VPCERR_UNSUPPORTED;
+	}
+	return 0;
+}
+
+scsi_qla_host_t *
+qla24xx_create_vhost(struct fc_vport *fc_vport)
+{
+	scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+	scsi_qla_host_t *vha;
+	struct Scsi_Host *host;
+
+	host = scsi_host_alloc(&qla24xx_driver_template,
+	    sizeof(scsi_qla_host_t));
+	if (!host) {
+		printk(KERN_WARNING
+		    "qla2xxx: scsi_host_alloc() failed for vport\n");
+		return(NULL);
+	}
+
+	vha = (scsi_qla_host_t *)host->hostdata;
+
+	/* clone the parent hba */
+	memcpy(vha, ha, sizeof (scsi_qla_host_t));
+
+	fc_vport->dd_data = vha;
+
+	vha->node_name = kmalloc(WWN_SIZE * sizeof(char), GFP_KERNEL);
+	if (!vha->node_name)
+		goto create_vhost_failed_1;
+
+	vha->port_name = kmalloc(WWN_SIZE * sizeof(char), GFP_KERNEL);
+	if (!vha->port_name)
+		goto create_vhost_failed_2;
+
+	/* New host info */
+	u64_to_wwn(fc_vport->node_name, vha->node_name);
+	u64_to_wwn(fc_vport->port_name, vha->port_name);
+
+	vha->host = host;
+	vha->host_no = host->host_no;
+	vha->parent = ha;
+	vha->fc_vport = fc_vport;
+	vha->device_flags = 0;
+	vha->instance = num_hosts;
+	vha->vp_idx = qla24xx_allocate_vp_id(vha);
+	if (vha->vp_idx > ha->max_npiv_vports) {
+		DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n",
+			vha->host_no));
+		goto create_vhost_failed_3;
+	}
+	vha->mgmt_svr_loop_id = 10 + vha->vp_idx;
+
+	init_MUTEX(&vha->mbx_cmd_sem);
+	init_MUTEX_LOCKED(&vha->mbx_intr_sem);
+
+	INIT_LIST_HEAD(&vha->list);
+	INIT_LIST_HEAD(&vha->fcports);
+	INIT_LIST_HEAD(&vha->vp_fcports);
+
+	vha->dpc_flags = 0L;
+	set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
+	set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
+
+	/*
+	 * To fix the issue of processing a parent's RSCN for the vport before
+	 * its SCR is complete.
+	 */
+	set_bit(VP_SCR_NEEDED, &vha->vp_flags);
+	atomic_set(&vha->loop_state, LOOP_DOWN);
+	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
+
+	qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL);
+
+	host->can_queue = vha->request_q_length + 128;
+	host->this_id = 255;
+	host->cmd_per_lun = 3;
+	host->max_cmd_len = MAX_CMDSZ;
+	host->max_channel = MAX_BUSES - 1;
+	host->max_lun = MAX_LUNS;
+	host->unique_id = vha->instance;
+	host->max_id = MAX_TARGETS_2200;
+	host->transportt = qla2xxx_transport_vport_template;
+
+	DEBUG15(printk("DEBUG: detect vport hba %ld at address = %p\n",
+	    vha->host_no, vha));
+
+	vha->flags.init_done = 1;
+	num_hosts++;
+
+	down(&ha->vport_sem);
+	set_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map);
+	ha->cur_vport_count++;
+	up(&ha->vport_sem);
+
+	return vha;
+
+create_vhost_failed_3:
+	kfree(vha->port_name);
+
+create_vhost_failed_2:
+	kfree(vha->node_name);
+
+create_vhost_failed_1:
+	return NULL;
+}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index dd076da..b5a77b0 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -29,8 +29,7 @@
 /*
  * Ioctl related information.
  */
-static int num_hosts;
-
+int num_hosts;
 int ql2xlogintimeout = 20;
 module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xlogintimeout,
@@ -112,7 +111,7 @@
 static int qla2x00_change_queue_depth(struct scsi_device *, int);
 static int qla2x00_change_queue_type(struct scsi_device *, int);
 
-static struct scsi_host_template qla2x00_driver_template = {
+struct scsi_host_template qla2x00_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= QLA2XXX_DRIVER_NAME,
 	.queuecommand		= qla2x00_queuecommand,
@@ -143,7 +142,7 @@
 	.shost_attrs		= qla2x00_host_attrs,
 };
 
-static struct scsi_host_template qla24xx_driver_template = {
+struct scsi_host_template qla24xx_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= QLA2XXX_DRIVER_NAME,
 	.queuecommand		= qla24xx_queuecommand,
@@ -171,21 +170,21 @@
 };
 
 static struct scsi_transport_template *qla2xxx_transport_template = NULL;
+struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
 
 /* TODO Convert to inlines
  *
  * Timer routines
  */
-#define	WATCH_INTERVAL		1       /* number of seconds */
 
-static void qla2x00_timer(scsi_qla_host_t *);
+void qla2x00_timer(scsi_qla_host_t *);
 
-static __inline__ void qla2x00_start_timer(scsi_qla_host_t *,
+__inline__ void qla2x00_start_timer(scsi_qla_host_t *,
     void *, unsigned long);
 static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long);
-static __inline__ void qla2x00_stop_timer(scsi_qla_host_t *);
+__inline__ void qla2x00_stop_timer(scsi_qla_host_t *);
 
-static inline void
+__inline__ void
 qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval)
 {
 	init_timer(&ha->timer);
@@ -202,7 +201,7 @@
 	mod_timer(&ha->timer, jiffies + interval * HZ);
 }
 
-static __inline__ void
+__inline__ void
 qla2x00_stop_timer(scsi_qla_host_t *ha)
 {
 	del_timer_sync(&ha->timer);
@@ -213,8 +212,8 @@
 
 static void qla2x00_rst_aen(scsi_qla_host_t *);
 
-static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
-static void qla2x00_mem_free(scsi_qla_host_t *ha);
+uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
+void qla2x00_mem_free(scsi_qla_host_t *ha);
 static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
 static void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
 static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *);
@@ -438,6 +437,7 @@
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
 	srb_t *sp;
 	int rval;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	rval = fc_remote_port_chkready(rport);
 	if (rval) {
@@ -453,7 +453,7 @@
 
 	if (atomic_read(&fcport->state) != FCS_ONLINE) {
 		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
-		    atomic_read(&ha->loop_state) == LOOP_DEAD) {
+		    atomic_read(&pha->loop_state) == LOOP_DEAD) {
 			cmd->result = DID_NO_CONNECT << 16;
 			goto qc24_fail_command;
 		}
@@ -462,7 +462,7 @@
 
 	spin_unlock_irq(ha->host->host_lock);
 
-	sp = qla2x00_get_new_sp(ha, fcport, cmd, done);
+	sp = qla2x00_get_new_sp(pha, fcport, cmd, done);
 	if (!sp)
 		goto qc24_host_busy_lock;
 
@@ -475,8 +475,8 @@
 	return 0;
 
 qc24_host_busy_free_sp:
-	qla2x00_sp_free_dma(ha, sp);
-	mempool_free(sp, ha->srb_mempool);
+	qla2x00_sp_free_dma(pha, sp);
+	mempool_free(sp, pha->srb_mempool);
 
 qc24_host_busy_lock:
 	spin_lock_irq(ha->host->host_lock);
@@ -548,16 +548,17 @@
 {
 	int		return_status;
 	unsigned long	wait_online;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
-	while (((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) ||
-	    test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
-	    test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) ||
-	    ha->dpc_active) && time_before(jiffies, wait_online)) {
+	while (((test_bit(ISP_ABORT_NEEDED, &pha->dpc_flags)) ||
+	    test_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags) ||
+	    test_bit(ISP_ABORT_RETRY, &pha->dpc_flags) ||
+	    pha->dpc_active) && time_before(jiffies, wait_online)) {
 
 		msleep(1000);
 	}
-	if (ha->flags.online)
+	if (pha->flags.online)
 		return_status = QLA_SUCCESS;
 	else
 		return_status = QLA_FUNCTION_FAILED;
@@ -588,14 +589,15 @@
 {
 	int 	 return_status = QLA_SUCCESS;
 	unsigned long loop_timeout ;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	/* wait for 5 min at the max for loop to be ready */
 	loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ);
 
-	while ((!atomic_read(&ha->loop_down_timer) &&
-	    atomic_read(&ha->loop_state) == LOOP_DOWN) ||
-	    atomic_read(&ha->loop_state) != LOOP_READY) {
-		if (atomic_read(&ha->loop_state) == LOOP_DEAD) {
+	while ((!atomic_read(&pha->loop_down_timer) &&
+	    atomic_read(&pha->loop_state) == LOOP_DOWN) ||
+	    atomic_read(&pha->loop_state) != LOOP_READY) {
+		if (atomic_read(&pha->loop_state) == LOOP_DEAD) {
 			return_status = QLA_FUNCTION_FAILED;
 			break;
 		}
@@ -650,6 +652,7 @@
 	unsigned long serial;
 	unsigned long flags;
 	int wait = 0;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	qla2x00_block_error_handler(cmd);
 
@@ -663,9 +666,9 @@
 	serial = cmd->serial_number;
 
 	/* Check active list for command command. */
-	spin_lock_irqsave(&ha->hardware_lock, flags);
+	spin_lock_irqsave(&pha->hardware_lock, flags);
 	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
-		sp = ha->outstanding_cmds[i];
+		sp = pha->outstanding_cmds[i];
 
 		if (sp == NULL)
 			continue;
@@ -677,7 +680,7 @@
 		    __func__, ha->host_no, sp, serial));
 		DEBUG3(qla2x00_print_scsi_cmd(cmd));
 
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+		spin_unlock_irqrestore(&pha->hardware_lock, flags);
 		if (ha->isp_ops.abort_command(ha, sp)) {
 			DEBUG2(printk("%s(%ld): abort_command "
 			    "mbx failed.\n", __func__, ha->host_no));
@@ -686,11 +689,11 @@
 			    "mbx success.\n", __func__, ha->host_no));
 			wait = 1;
 		}
-		spin_lock_irqsave(&ha->hardware_lock, flags);
+		spin_lock_irqsave(&pha->hardware_lock, flags);
 
 		break;
 	}
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	spin_unlock_irqrestore(&pha->hardware_lock, flags);
 
 	/* Wait for the command to be returned. */
 	if (wait) {
@@ -731,6 +734,7 @@
 	srb_t		*sp;
 	struct scsi_cmnd *cmd;
 	unsigned long flags;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	status = 0;
 
@@ -739,19 +743,20 @@
 	 * array
 	 */
 	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-		spin_lock_irqsave(&ha->hardware_lock, flags);
-		sp = ha->outstanding_cmds[cnt];
+		spin_lock_irqsave(&pha->hardware_lock, flags);
+		sp = pha->outstanding_cmds[cnt];
 		if (sp) {
 			cmd = sp->cmd;
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-			if (cmd->device->id == t) {
+			spin_unlock_irqrestore(&pha->hardware_lock, flags);
+			if (cmd->device->id == t &&
+			    ha->vp_idx == sp->ha->vp_idx) {
 				if (!qla2x00_eh_wait_on_command(ha, cmd)) {
 					status = 1;
 					break;
 				}
 			}
 		} else {
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
+			spin_unlock_irqrestore(&pha->hardware_lock, flags);
 		}
 	}
 	return (status);
@@ -782,14 +787,12 @@
 {
 	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-	int ret;
+	int ret = FAILED;
 	unsigned int id, lun;
 	unsigned long serial;
 
 	qla2x00_block_error_handler(cmd);
 
-	ret = FAILED;
-
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 	serial = cmd->serial_number;
@@ -912,15 +915,14 @@
 qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
 {
 	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-	int ret;
+	int ret = FAILED;
 	unsigned int id, lun;
 	unsigned long serial;
 
 	qla2x00_block_error_handler(cmd);
 
-	ret = FAILED;
-
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 	serial = cmd->serial_number;
@@ -944,7 +946,7 @@
 		goto eh_bus_reset_done;
 
 	/* Flush outstanding commands. */
-	if (!qla2x00_eh_wait_for_pending_commands(ha))
+	if (!qla2x00_eh_wait_for_pending_commands(pha))
 		ret = FAILED;
 
 eh_bus_reset_done:
@@ -974,14 +976,13 @@
 {
 	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-	int ret;
+	int ret = FAILED;
 	unsigned int id, lun;
 	unsigned long serial;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	qla2x00_block_error_handler(cmd);
 
-	ret = FAILED;
-
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 	serial = cmd->serial_number;
@@ -1004,21 +1005,24 @@
 	 * while dpc is stuck for the mailbox to complete.
 	 */
 	qla2x00_wait_for_loop_ready(ha);
-	set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
-	if (qla2x00_abort_isp(ha)) {
-		clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
+	set_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
+	if (qla2x00_abort_isp(pha)) {
+		clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
 		/* failed. schedule dpc to try */
-		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+		set_bit(ISP_ABORT_NEEDED, &pha->dpc_flags);
 
 		if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
 			goto eh_host_reset_lock;
 	}
-	clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
+	clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
 
 	/* Waiting for our command in done_queue to be returned to OS.*/
-	if (qla2x00_eh_wait_for_pending_commands(ha))
+	if (qla2x00_eh_wait_for_pending_commands(pha))
 		ret = SUCCESS;
 
+	if (ha->parent)
+		qla2x00_vp_abort_isp(ha);
+
 eh_host_reset_lock:
 	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
 	    (ret == FAILED) ? "failed" : "succeded");
@@ -1435,6 +1439,7 @@
 	ha->host = host;
 	ha->host_no = host->host_no;
 	sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
+	ha->parent = NULL;
 
 	/* Set ISP-type information. */
 	qla2x00_set_isp_flags(ha);
@@ -1452,7 +1457,7 @@
 
 	ha->prev_topology = 0;
 	ha->init_cb_size = sizeof(init_cb_t);
-	ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
+	ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx;
 	ha->link_data_rate = PORT_SPEED_UNKNOWN;
 	ha->optrom_size = OPTROM_SIZE_2300;
 
@@ -1524,8 +1529,8 @@
 		ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
 		ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
 		ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
-		ha->init_cb_size = sizeof(struct init_cb_24xx);
-		ha->mgmt_svr_loop_id = 10;
+		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
+		ha->mgmt_svr_loop_id = 10 + ha->vp_idx;
 		ha->isp_ops.pci_config = qla24xx_pci_config;
 		ha->isp_ops.reset_chip = qla24xx_reset_chip;
 		ha->isp_ops.chip_diag = qla24xx_chip_diag;
@@ -1563,10 +1568,14 @@
 	ha->instance = num_hosts;
 
 	init_MUTEX(&ha->mbx_cmd_sem);
+	init_MUTEX(&ha->vport_sem);
 	init_MUTEX_LOCKED(&ha->mbx_intr_sem);
 
 	INIT_LIST_HEAD(&ha->list);
 	INIT_LIST_HEAD(&ha->fcports);
+	INIT_LIST_HEAD(&ha->vp_list);
+
+	set_bit(0, (unsigned long *) ha->vp_idx_map);
 
 	qla2x00_config_dma_addressing(ha);
 	if (qla2x00_mem_alloc(ha)) {
@@ -1789,7 +1798,8 @@
 void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
     int do_login, int defer)
 {
-	if (atomic_read(&fcport->state) == FCS_ONLINE)
+	if (atomic_read(&fcport->state) == FCS_ONLINE &&
+	    ha->vp_idx == fcport->vp_idx)
 		qla2x00_schedule_rport_del(ha, fcport, defer);
 
 	/*
@@ -1840,19 +1850,23 @@
 qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
 {
 	fc_port_t *fcport;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
-	list_for_each_entry(fcport, &ha->fcports, list) {
-		if (fcport->port_type != FCT_TARGET)
+	list_for_each_entry(fcport, &pha->fcports, list) {
+		if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx)
 			continue;
-
 		/*
 		 * No point in marking the device as lost, if the device is
 		 * already DEAD.
 		 */
 		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
 			continue;
-		if (atomic_read(&fcport->state) == FCS_ONLINE)
-			qla2x00_schedule_rport_del(ha, fcport, defer);
+		if (atomic_read(&fcport->state) == FCS_ONLINE) {
+			if (defer)
+				qla2x00_schedule_rport_del(ha, fcport, defer);
+			else if (ha->vp_idx == fcport->vp_idx)
+				qla2x00_schedule_rport_del(ha, fcport, defer);
+		}
 		atomic_set(&fcport->state, FCS_DEVICE_LOST);
 	}
 
@@ -1868,7 +1882,7 @@
 *      0  = success.
 *      1  = failure.
 */
-static uint8_t
+uint8_t
 qla2x00_mem_alloc(scsi_qla_host_t *ha)
 {
 	char	name[16];
@@ -1920,6 +1934,20 @@
 			continue;
 		}
 
+		/* get consistent memory allocated for init control block */
+		ha->init_cb = dma_alloc_coherent(&ha->pdev->dev,
+		    ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL);
+		if (ha->init_cb == NULL) {
+			qla_printk(KERN_WARNING, ha,
+			    "Memory Allocation failed - init_cb\n");
+
+			qla2x00_mem_free(ha);
+			msleep(100);
+
+			continue;
+		}
+		memset(ha->init_cb, 0, ha->init_cb_size);
+
 		snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME,
 		    ha->host_no);
 		ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,
@@ -1934,20 +1962,6 @@
 			continue;
 		}
 
-		/* get consistent memory allocated for init control block */
-		ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
-		    &ha->init_cb_dma);
-		if (ha->init_cb == NULL) {
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - init_cb\n");
-
-			qla2x00_mem_free(ha);
-			msleep(100);
-
-			continue;
-		}
-		memset(ha->init_cb, 0, ha->init_cb_size);
-
 		if (qla2x00_allocate_sp_pool(ha)) {
 			qla_printk(KERN_WARNING, ha,
 			    "Memory Allocation failed - "
@@ -2052,7 +2066,7 @@
 * Input:
 *      ha = adapter block pointer.
 */
-static void
+void
 qla2x00_mem_free(scsi_qla_host_t *ha)
 {
 	struct list_head	*fcpl, *fcptemp;
@@ -2088,12 +2102,13 @@
 	if (ha->ms_iocb)
 		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
 
-	if (ha->init_cb)
-		dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma);
-
 	if (ha->s_dma_pool)
 		dma_pool_destroy(ha->s_dma_pool);
 
+	if (ha->init_cb)
+		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
+		    ha->init_cb, ha->init_cb_dma);
+
 	if (ha->gid_list)
 		dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
 		    ha->gid_list_dma);
@@ -2199,6 +2214,7 @@
 static int
 qla2x00_do_dpc(void *data)
 {
+	int		rval;
 	scsi_qla_host_t *ha;
 	fc_port_t	*fcport;
 	uint8_t		status;
@@ -2347,7 +2363,7 @@
 			if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE,
 			    &ha->dpc_flags))) {
 
-				qla2x00_loop_resync(ha);
+				rval = qla2x00_loop_resync(ha);
 
 				clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
 			}
@@ -2374,6 +2390,8 @@
 		if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags))
 			ha->isp_ops.beacon_blink(ha);
 
+		qla2x00_do_dpc_all_vps(ha);
+
 		ha->dpc_active = 0;
 	} /* End of while(1) */
 
@@ -2426,13 +2444,7 @@
 	struct scsi_cmnd *cmd = sp->cmd;
 
 	if (sp->flags & SRB_DMA_VALID) {
-		if (cmd->use_sg) {
-			dma_unmap_sg(&ha->pdev->dev, cmd->request_buffer,
-			    cmd->use_sg, cmd->sc_data_direction);
-		} else if (cmd->request_bufflen) {
-			dma_unmap_single(&ha->pdev->dev, sp->dma_handle,
-			    cmd->request_bufflen, cmd->sc_data_direction);
-		}
+		scsi_dma_unmap(cmd);
 		sp->flags &= ~SRB_DMA_VALID;
 	}
 	CMD_SP(cmd) = NULL;
@@ -2458,7 +2470,7 @@
 *
 * Context: Interrupt
 ***************************************************************************/
-static void
+void
 qla2x00_timer(scsi_qla_host_t *ha)
 {
 	unsigned long	cpu_flags = 0;
@@ -2467,6 +2479,7 @@
 	int		index;
 	srb_t		*sp;
 	int		t;
+	scsi_qla_host_t *pha = to_qla_parent(ha);
 
 	/*
 	 * Ports - Port down timer.
@@ -2512,23 +2525,29 @@
 				atomic_set(&ha->loop_state, LOOP_DEAD);
 
 			/* Schedule an ISP abort to return any tape commands. */
-			spin_lock_irqsave(&ha->hardware_lock, cpu_flags);
-			for (index = 1; index < MAX_OUTSTANDING_COMMANDS;
-			    index++) {
-				fc_port_t *sfcp;
+			/* NPIV - scan physical port only */
+			if (!ha->parent) {
+				spin_lock_irqsave(&ha->hardware_lock,
+				    cpu_flags);
+				for (index = 1;
+				    index < MAX_OUTSTANDING_COMMANDS;
+				    index++) {
+					fc_port_t *sfcp;
 
-				sp = ha->outstanding_cmds[index];
-				if (!sp)
-					continue;
-				sfcp = sp->fcport;
-				if (!(sfcp->flags & FCF_TAPE_PRESENT))
-					continue;
+					sp = ha->outstanding_cmds[index];
+					if (!sp)
+						continue;
+					sfcp = sp->fcport;
+					if (!(sfcp->flags & FCF_TAPE_PRESENT))
+						continue;
 
-				set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-				break;
+					set_bit(ISP_ABORT_NEEDED,
+					    &ha->dpc_flags);
+					break;
+				}
+				spin_unlock_irqrestore(&ha->hardware_lock,
+				    cpu_flags);
 			}
-			spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags);
-
 			set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags);
 			start_dpc++;
 		}
@@ -2572,8 +2591,9 @@
 	    test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
 	    test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
 	    test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
+	    test_bit(VP_DPC_NEEDED, &ha->dpc_flags) ||
 	    test_bit(RELOGIN_NEEDED, &ha->dpc_flags)))
-		qla2xxx_wake_dpc(ha);
+		qla2xxx_wake_dpc(pha);
 
 	qla2x00_restart_timer(ha, WATCH_INTERVAL);
 }
@@ -2590,7 +2610,7 @@
 			return 0;
 		if (msleep_interruptible(step))
 			break;
-	} while (--iterations >= 0);
+	} while (--iterations > 0);
 
 	return -ETIMEDOUT;
 }
@@ -2717,14 +2737,24 @@
 
 	qla2xxx_transport_template =
 	    fc_attach_transport(&qla2xxx_transport_functions);
-	if (!qla2xxx_transport_template)
+	if (!qla2xxx_transport_template) {
+		kmem_cache_destroy(srb_cachep);
 		return -ENODEV;
+	}
+	qla2xxx_transport_vport_template =
+	    fc_attach_transport(&qla2xxx_transport_vport_functions);
+	if (!qla2xxx_transport_vport_template) {
+		kmem_cache_destroy(srb_cachep);
+		fc_release_transport(qla2xxx_transport_template);
+		return -ENODEV;
+	}
 
 	printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
 	ret = pci_register_driver(&qla2xxx_pci_driver);
 	if (ret) {
 		kmem_cache_destroy(srb_cachep);
 		fc_release_transport(qla2xxx_transport_template);
+		fc_release_transport(qla2xxx_transport_vport_template);
 	}
 	return ret;
 }
@@ -2739,6 +2769,7 @@
 	qla2x00_release_firmware();
 	kmem_cache_destroy(srb_cachep);
 	fc_release_transport(qla2xxx_transport_template);
+	fc_release_transport(qla2xxx_transport_vport_template);
 }
 
 module_init(qla2x00_module_init);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index c375a4e..fd2f10a 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.07-k7"
+#define QLA2XXX_VERSION      "8.02.00-k1"
 
 #define QLA_DRIVER_MAJOR_VER	8
-#define QLA_DRIVER_MINOR_VER	1
-#define QLA_DRIVER_PATCH_VER	7
+#define QLA_DRIVER_MINOR_VER	2
+#define QLA_DRIVER_PATCH_VER	0
 #define QLA_DRIVER_BETA_VER	0
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c
index 6437d024..fcc184c 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.c
+++ b/drivers/scsi/qla4xxx/ql4_dbg.c
@@ -6,176 +6,9 @@
  */
 
 #include "ql4_def.h"
-#include <scsi/scsi_dbg.h>
-
-#if 0
-
-static void qla4xxx_print_srb_info(struct srb * srb)
-{
-	printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags);
-	printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n",
-	       __func__, srb->cmd, (unsigned long) srb->dma_handle);
-	printk("%s: fw_ddb_index = %d, lun = %d\n",
-	       __func__, srb->fw_ddb_index, srb->cmd->device->lun);
-	printk("%s: iocb_tov = %d\n",
-	       __func__, srb->iocb_tov);
-	printk("%s: cc_stat = 0x%x, r_start = 0x%lx, u_start = 0x%lx\n\n",
-	       __func__, srb->cc_stat, srb->r_start, srb->u_start);
-}
-
-void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd)
-{
-	printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
-	printk("  b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n",
-	       cmd->device->channel, cmd->device->id, cmd->device->lun,
-	       cmd->cmd_len);
-	scsi_print_command(cmd);
-	printk("  seg_cnt = %d\n", cmd->use_sg);
-	printk("  request buffer = 0x%p, request buffer len = 0x%x\n",
-	       cmd->request_buffer, cmd->request_bufflen);
-	if (cmd->use_sg) {
-		struct scatterlist *sg;
-		sg = (struct scatterlist *)cmd->request_buffer;
-		printk("  SG buffer: \n");
-		qla4xxx_dump_buffer((caddr_t) sg,
-				    (cmd->use_sg * sizeof(*sg)));
-	}
-	printk("  tag = %d, transfersize = 0x%x \n", cmd->tag,
-	       cmd->transfersize);
-	printk("  Pid = %d, SP = 0x%p\n", (int)cmd->pid, cmd->SCp.ptr);
-	printk("  underflow size = 0x%x, direction=0x%x\n", cmd->underflow,
-	       cmd->sc_data_direction);
-	printk("  Current time (jiffies) = 0x%lx, "
-	       "timeout expires = 0x%lx\n", jiffies, cmd->eh_timeout.expires);
-	qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr);
-}
-
-void __dump_registers(struct scsi_qla_host *ha)
-{
-	uint8_t i;
-	for (i = 0; i < MBOX_REG_COUNT; i++) {
-		printk(KERN_INFO "0x%02X mailbox[%d]	  = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, mailbox[i]), i,
-		       readw(&ha->reg->mailbox[i]));
-	}
-	printk(KERN_INFO "0x%02X flash_address	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, flash_address),
-	       readw(&ha->reg->flash_address));
-	printk(KERN_INFO "0x%02X flash_data	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, flash_data),
-	       readw(&ha->reg->flash_data));
-	printk(KERN_INFO "0x%02X ctrl_status	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, ctrl_status),
-	       readw(&ha->reg->ctrl_status));
-	if (is_qla4010(ha)) {
-		printk(KERN_INFO "0x%02X nvram		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u1.isp4010.nvram),
-		       readw(&ha->reg->u1.isp4010.nvram));
-	}
-
-	else if (is_qla4022(ha) | is_qla4032(ha)) {
-		printk(KERN_INFO "0x%02X intr_mask	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u1.isp4022.intr_mask),
-		       readw(&ha->reg->u1.isp4022.intr_mask));
-		printk(KERN_INFO "0x%02X nvram		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u1.isp4022.nvram),
-		       readw(&ha->reg->u1.isp4022.nvram));
-		printk(KERN_INFO "0x%02X semaphore	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u1.isp4022.semaphore),
-		       readw(&ha->reg->u1.isp4022.semaphore));
-	}
-	printk(KERN_INFO "0x%02X req_q_in	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, req_q_in),
-	       readw(&ha->reg->req_q_in));
-	printk(KERN_INFO "0x%02X rsp_q_out	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, rsp_q_out),
-	       readw(&ha->reg->rsp_q_out));
-	if (is_qla4010(ha)) {
-		printk(KERN_INFO "0x%02X ext_hw_conf	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.ext_hw_conf),
-		       readw(&ha->reg->u2.isp4010.ext_hw_conf));
-		printk(KERN_INFO "0x%02X port_ctrl	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.port_ctrl),
-		       readw(&ha->reg->u2.isp4010.port_ctrl));
-		printk(KERN_INFO "0x%02X port_status	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.port_status),
-		       readw(&ha->reg->u2.isp4010.port_status));
-		printk(KERN_INFO "0x%02X req_q_out	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.req_q_out),
-		       readw(&ha->reg->u2.isp4010.req_q_out));
-		printk(KERN_INFO "0x%02X gp_out		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_out),
-		       readw(&ha->reg->u2.isp4010.gp_out));
-		printk(KERN_INFO "0x%02X gp_in		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_in),
-		       readw(&ha->reg->u2.isp4010.gp_in));
-		printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.port_err_status),
-		       readw(&ha->reg->u2.isp4010.port_err_status));
-	}
-
-	else if (is_qla4022(ha) | is_qla4032(ha)) {
-		printk(KERN_INFO "Page 0 Registers:\n");
-		printk(KERN_INFO "0x%02X ext_hw_conf	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.ext_hw_conf),
-		       readw(&ha->reg->u2.isp4022.p0.ext_hw_conf));
-		printk(KERN_INFO "0x%02X port_ctrl	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.port_ctrl),
-		       readw(&ha->reg->u2.isp4022.p0.port_ctrl));
-		printk(KERN_INFO "0x%02X port_status	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.port_status),
-		       readw(&ha->reg->u2.isp4022.p0.port_status));
-		printk(KERN_INFO "0x%02X gp_out		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.gp_out),
-		       readw(&ha->reg->u2.isp4022.p0.gp_out));
-		printk(KERN_INFO "0x%02X gp_in		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u2.isp4022.p0.gp_in),
-		       readw(&ha->reg->u2.isp4022.p0.gp_in));
-		printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.port_err_status),
-		       readw(&ha->reg->u2.isp4022.p0.port_err_status));
-		printk(KERN_INFO "Page 1 Registers:\n");
-		writel(HOST_MEM_CFG_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
-		       &ha->reg->ctrl_status);
-		printk(KERN_INFO "0x%02X req_q_out	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p1.req_q_out),
-		       readw(&ha->reg->u2.isp4022.p1.req_q_out));
-		writel(PORT_CTRL_STAT_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
-		       &ha->reg->ctrl_status);
-	}
-}
-
-void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha)
-{
-	unsigned long flags = 0;
-	int i = 0;
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-	for (i = 1; i < MBOX_REG_COUNT; i++)
-		printk(KERN_INFO "  Mailbox[%d] = %08x\n", i,
-		       readw(&ha->reg->mailbox[i]));
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-}
-
-void qla4xxx_dump_registers(struct scsi_qla_host *ha)
-{
-	unsigned long flags = 0;
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-	__dump_registers(ha);
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-}
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 void qla4xxx_dump_buffer(void *b, uint32_t size)
 {
@@ -198,4 +31,3 @@
 		printk(KERN_DEBUG "\n");
 }
 
-#endif  /*  0  */
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 6f4cf2d..accaf690 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -122,8 +122,7 @@
 
 #define ISCSI_IPADDR_SIZE		4	/* IP address size */
 #define ISCSI_ALIAS_SIZE		32	/* ISCSI Alais name size */
-#define ISCSI_NAME_SIZE			255	/* ISCSI Name size -
-						 * usually a string */
+#define ISCSI_NAME_SIZE			0xE0	/* ISCSI Name size */
 
 #define LSDW(x) ((u32)((u64)(x)))
 #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
@@ -187,9 +186,21 @@
 	u_long u_start;		/* Time when we handed the cmd to F/W */
 };
 
-	/*
-	 * Device Database (DDB) structure
-	 */
+/*
+ * Asynchronous Event Queue structure
+ */
+struct aen {
+        uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
+};
+
+struct ql4_aen_log {
+        int count;
+        struct aen entry[MAX_AEN_ENTRIES];
+};
+
+/*
+ * Device Database (DDB) structure
+ */
 struct ddb_entry {
 	struct list_head list;	/* ddb list */
 	struct scsi_qla_host *ha;
@@ -254,13 +265,6 @@
 #define DF_ISNS_DISCOVERED	2	/* Device was discovered via iSNS */
 #define DF_FO_MASKED		3
 
-/*
- * Asynchronous Event Queue structure
- */
-struct aen {
-	uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
-};
-
 
 #include "ql4_fw.h"
 #include "ql4_nvram.h"
@@ -270,31 +274,31 @@
  */
 struct scsi_qla_host {
 	/* Linux adapter configuration data */
-	struct Scsi_Host *host; /* pointer to host data */
-	uint32_t tot_ddbs;
 	unsigned long flags;
 
-#define AF_ONLINE		      0 /* 0x00000001 */
-#define AF_INIT_DONE		      1 /* 0x00000002 */
-#define AF_MBOX_COMMAND		      2 /* 0x00000004 */
-#define AF_MBOX_COMMAND_DONE	      3 /* 0x00000008 */
-#define AF_INTERRUPTS_ON	      6 /* 0x00000040 Not Used */
-#define AF_GET_CRASH_RECORD	      7 /* 0x00000080 */
-#define AF_LINK_UP		      8 /* 0x00000100 */
-#define AF_IRQ_ATTACHED		     10 /* 0x00000400 */
-#define AF_ISNS_CMD_IN_PROCESS	     12 /* 0x00001000 */
-#define AF_ISNS_CMD_DONE	     13 /* 0x00002000 */
+#define AF_ONLINE			0 /* 0x00000001 */
+#define AF_INIT_DONE			1 /* 0x00000002 */
+#define AF_MBOX_COMMAND			2 /* 0x00000004 */
+#define AF_MBOX_COMMAND_DONE		3 /* 0x00000008 */
+#define AF_INTERRUPTS_ON		6 /* 0x00000040 */
+#define AF_GET_CRASH_RECORD		7 /* 0x00000080 */
+#define AF_LINK_UP			8 /* 0x00000100 */
+#define AF_IRQ_ATTACHED			10 /* 0x00000400 */
+#define AF_DISABLE_ACB_COMPLETE		11 /* 0x00000800 */
 
 	unsigned long dpc_flags;
 
-#define DPC_RESET_HA		      1 /* 0x00000002 */
-#define DPC_RETRY_RESET_HA	      2 /* 0x00000004 */
-#define DPC_RELOGIN_DEVICE	      3 /* 0x00000008 */
-#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */
-#define DPC_RESET_HA_INTR	      5 /* 0x00000020 */
-#define DPC_ISNS_RESTART	      7 /* 0x00000080 */
-#define DPC_AEN			      9 /* 0x00000200 */
-#define DPC_GET_DHCP_IP_ADDR	     15 /* 0x00008000 */
+#define DPC_RESET_HA			1 /* 0x00000002 */
+#define DPC_RETRY_RESET_HA		2 /* 0x00000004 */
+#define DPC_RELOGIN_DEVICE		3 /* 0x00000008 */
+#define DPC_RESET_HA_DESTROY_DDB_LIST	4 /* 0x00000010 */
+#define DPC_RESET_HA_INTR		5 /* 0x00000020 */
+#define DPC_ISNS_RESTART		7 /* 0x00000080 */
+#define DPC_AEN				9 /* 0x00000200 */
+#define DPC_GET_DHCP_IP_ADDR		15 /* 0x00008000 */
+
+	struct Scsi_Host *host; /* pointer to host data */
+	uint32_t tot_ddbs;
 
 	uint16_t	iocb_cnt;
 	uint16_t	iocb_hiwat;
@@ -344,6 +348,7 @@
 	uint32_t firmware_version[2];
 	uint32_t patch_number;
 	uint32_t build_number;
+	uint32_t board_id;
 
 	/* --- From Init_FW --- */
 	/* init_cb_t *init_cb; */
@@ -363,7 +368,6 @@
 
 	/* --- From GetFwState --- */
 	uint32_t firmware_state;
-	uint32_t board_id;
 	uint32_t addl_fw_state;
 
 	/* Linux kernel thread */
@@ -414,6 +418,8 @@
 	uint16_t aen_out;
 	struct aen aen_q[MAX_AEN_ENTRIES];
 
+	struct ql4_aen_log aen_log;/* tracks all aens */
+
 	/* This mutex protects several threads to do mailbox commands
 	 * concurrently.
 	 */
@@ -585,10 +591,4 @@
 #define FLUSH_DDB_CHANGED_AENS	 1
 #define RELOGIN_DDB_CHANGED_AENS 2
 
-#include "ql4_version.h"
-#include "ql4_glbl.h"
-#include "ql4_dbg.h"
-#include "ql4_inline.h"
-
-
 #endif	/*_QLA4XXX_H */
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 4eea8c5..9bb3d1d 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -20,143 +20,23 @@
  *************************************************************************/
 
 struct port_ctrl_stat_regs {
-	__le32 ext_hw_conf;	/*  80 x50  R/W */
-	__le32 intChipConfiguration; /*	 84 x54 */
-	__le32 port_ctrl;	/*  88 x58 */
-	__le32 port_status;	/*  92 x5c */
-	__le32 HostPrimMACHi;	/*  96 x60 */
-	__le32 HostPrimMACLow;	/* 100 x64 */
-	__le32 HostSecMACHi;	/* 104 x68 */
-	__le32 HostSecMACLow;	/* 108 x6c */
-	__le32 EPPrimMACHi;	/* 112 x70 */
-	__le32 EPPrimMACLow;	/* 116 x74 */
-	__le32 EPSecMACHi;	/* 120 x78 */
-	__le32 EPSecMACLow;	/* 124 x7c */
-	__le32 HostPrimIPHi;	/* 128 x80 */
-	__le32 HostPrimIPMidHi; /* 132 x84 */
-	__le32 HostPrimIPMidLow;	/* 136 x88 */
-	__le32 HostPrimIPLow;	/* 140 x8c */
-	__le32 HostSecIPHi;	/* 144 x90 */
-	__le32 HostSecIPMidHi;	/* 148 x94 */
-	__le32 HostSecIPMidLow; /* 152 x98 */
-	__le32 HostSecIPLow;	/* 156 x9c */
-	__le32 EPPrimIPHi;	/* 160 xa0 */
-	__le32 EPPrimIPMidHi;	/* 164 xa4 */
-	__le32 EPPrimIPMidLow;	/* 168 xa8 */
-	__le32 EPPrimIPLow;	/* 172 xac */
-	__le32 EPSecIPHi;	/* 176 xb0 */
-	__le32 EPSecIPMidHi;	/* 180 xb4 */
-	__le32 EPSecIPMidLow;	/* 184 xb8 */
-	__le32 EPSecIPLow;	/* 188 xbc */
-	__le32 IPReassemblyTimeout; /* 192 xc0 */
-	__le32 EthMaxFramePayload; /* 196 xc4 */
-	__le32 TCPMaxWindowSize; /* 200 xc8 */
-	__le32 TCPCurrentTimestampHi; /* 204 xcc */
-	__le32 TCPCurrentTimestampLow; /* 208 xd0 */
-	__le32 LocalRAMAddress; /* 212 xd4 */
-	__le32 LocalRAMData;	/* 216 xd8 */
-	__le32 PCSReserved1;	/* 220 xdc */
-	__le32 gp_out;		/* 224 xe0 */
-	__le32 gp_in;		/* 228 xe4 */
-	__le32 ProbeMuxAddr;	/* 232 xe8 */
-	__le32 ProbeMuxData;	/* 236 xec */
-	__le32 ERMQueueBaseAddr0; /* 240 xf0 */
-	__le32 ERMQueueBaseAddr1; /* 244 xf4 */
-	__le32 MACConfiguration; /* 248 xf8 */
-	__le32 port_err_status; /* 252 xfc  COR */
+	__le32 ext_hw_conf;	/* 0x50  R/W */
+	__le32 rsrvd0;		/* 0x54 */
+	__le32 port_ctrl;	/* 0x58 */
+	__le32 port_status;	/* 0x5c */
+	__le32 rsrvd1[32];	/* 0x60-0xdf */
+	__le32 gp_out;		/* 0xe0 */
+	__le32 gp_in;		/* 0xe4 */
+	__le32 rsrvd2[5];	/* 0xe8-0xfb */
+	__le32 port_err_status; /* 0xfc */
 };
 
 struct host_mem_cfg_regs {
-	__le32 NetRequestQueueOut; /*  80 x50 */
-	__le32 NetRequestQueueOutAddrHi; /*  84 x54 */
-	__le32 NetRequestQueueOutAddrLow; /*  88 x58 */
-	__le32 NetRequestQueueBaseAddrHi; /*  92 x5c */
-	__le32 NetRequestQueueBaseAddrLow; /*  96 x60 */
-	__le32 NetRequestQueueLength; /* 100 x64 */
-	__le32 NetResponseQueueIn; /* 104 x68 */
-	__le32 NetResponseQueueInAddrHi; /* 108 x6c */
-	__le32 NetResponseQueueInAddrLow; /* 112 x70 */
-	__le32 NetResponseQueueBaseAddrHi; /* 116 x74 */
-	__le32 NetResponseQueueBaseAddrLow; /* 120 x78 */
-	__le32 NetResponseQueueLength; /* 124 x7c */
-	__le32 req_q_out;	/* 128 x80 */
-	__le32 RequestQueueOutAddrHi; /* 132 x84 */
-	__le32 RequestQueueOutAddrLow; /* 136 x88 */
-	__le32 RequestQueueBaseAddrHi; /* 140 x8c */
-	__le32 RequestQueueBaseAddrLow; /* 144 x90 */
-	__le32 RequestQueueLength; /* 148 x94 */
-	__le32 ResponseQueueIn; /* 152 x98 */
-	__le32 ResponseQueueInAddrHi; /* 156 x9c */
-	__le32 ResponseQueueInAddrLow; /* 160 xa0 */
-	__le32 ResponseQueueBaseAddrHi; /* 164 xa4 */
-	__le32 ResponseQueueBaseAddrLow; /* 168 xa8 */
-	__le32 ResponseQueueLength; /* 172 xac */
-	__le32 NetRxLargeBufferQueueOut; /* 176 xb0 */
-	__le32 NetRxLargeBufferQueueBaseAddrHi; /* 180 xb4 */
-	__le32 NetRxLargeBufferQueueBaseAddrLow; /* 184 xb8 */
-	__le32 NetRxLargeBufferQueueLength; /* 188 xbc */
-	__le32 NetRxLargeBufferLength; /* 192 xc0 */
-	__le32 NetRxSmallBufferQueueOut; /* 196 xc4 */
-	__le32 NetRxSmallBufferQueueBaseAddrHi; /* 200 xc8 */
-	__le32 NetRxSmallBufferQueueBaseAddrLow; /* 204 xcc */
-	__le32 NetRxSmallBufferQueueLength; /* 208 xd0 */
-	__le32 NetRxSmallBufferLength; /* 212 xd4 */
-	__le32 HMCReserved0[10]; /* 216 xd8 */
+	__le32 rsrvd0[12];	/* 0x50-0x79 */
+	__le32 req_q_out;	/* 0x80 */
+	__le32 rsrvd1[31];	/* 0x84-0xFF */
 };
 
-struct local_ram_cfg_regs {
-	__le32 BufletSize;	/*  80 x50 */
-	__le32 BufletMaxCount;	/*  84 x54 */
-	__le32 BufletCurrCount; /*  88 x58 */
-	__le32 BufletPauseThresholdCount; /*  92 x5c */
-	__le32 BufletTCPWinThresholdHi; /*  96 x60 */
-	__le32 BufletTCPWinThresholdLow; /* 100 x64 */
-	__le32 IPHashTableBaseAddr; /* 104 x68 */
-	__le32 IPHashTableSize; /* 108 x6c */
-	__le32 TCPHashTableBaseAddr; /* 112 x70 */
-	__le32 TCPHashTableSize; /* 116 x74 */
-	__le32 NCBAreaBaseAddr; /* 120 x78 */
-	__le32 NCBMaxCount;	/* 124 x7c */
-	__le32 NCBCurrCount;	/* 128 x80 */
-	__le32 DRBAreaBaseAddr; /* 132 x84 */
-	__le32 DRBMaxCount;	/* 136 x88 */
-	__le32 DRBCurrCount;	/* 140 x8c */
-	__le32 LRCReserved[28]; /* 144 x90 */
-};
-
-struct prot_stat_regs {
-	__le32 MACTxFrameCount; /*  80 x50   R */
-	__le32 MACTxByteCount;	/*  84 x54   R */
-	__le32 MACRxFrameCount; /*  88 x58   R */
-	__le32 MACRxByteCount;	/*  92 x5c   R */
-	__le32 MACCRCErrCount;	/*  96 x60   R */
-	__le32 MACEncErrCount;	/* 100 x64   R */
-	__le32 MACRxLengthErrCount; /* 104 x68	 R */
-	__le32 IPTxPacketCount; /* 108 x6c   R */
-	__le32 IPTxByteCount;	/* 112 x70   R */
-	__le32 IPTxFragmentCount; /* 116 x74   R */
-	__le32 IPRxPacketCount; /* 120 x78   R */
-	__le32 IPRxByteCount;	/* 124 x7c   R */
-	__le32 IPRxFragmentCount; /* 128 x80   R */
-	__le32 IPDatagramReassemblyCount; /* 132 x84   R */
-	__le32 IPV6RxPacketCount; /* 136 x88   R */
-	__le32 IPErrPacketCount; /* 140 x8c   R */
-	__le32 IPReassemblyErrCount; /* 144 x90	  R */
-	__le32 TCPTxSegmentCount; /* 148 x94   R */
-	__le32 TCPTxByteCount;	/* 152 x98   R */
-	__le32 TCPRxSegmentCount; /* 156 x9c   R */
-	__le32 TCPRxByteCount;	/* 160 xa0   R */
-	__le32 TCPTimerExpCount; /* 164 xa4   R */
-	__le32 TCPRxAckCount;	/* 168 xa8   R */
-	__le32 TCPTxAckCount;	/* 172 xac   R */
-	__le32 TCPRxErrOOOCount; /* 176 xb0   R */
-	__le32 PSReserved0;	/* 180 xb4 */
-	__le32 TCPRxWindowProbeUpdateCount; /* 184 xb8	 R */
-	__le32 ECCErrCorrectionCount; /* 188 xbc   R */
-	__le32 PSReserved1[16]; /* 192 xc0 */
-};
-
-
 /*  remote register set (access via PCI memory read/write) */
 struct isp_reg {
 #define MBOX_REG_COUNT 8
@@ -207,11 +87,7 @@
 			union {
 				struct port_ctrl_stat_regs p0;
 				struct host_mem_cfg_regs p1;
-				struct local_ram_cfg_regs p2;
-				struct prot_stat_regs p3;
-				__le32 r_union[44];
 			};
-
 		} __attribute__ ((packed)) isp4022;
 	} u2;
 };				/* 256 x100 */
@@ -296,6 +172,7 @@
 /*  ISP Semaphore definitions */
 
 /*  ISP General Purpose Output definitions */
+#define GPOR_TOPCAT_RESET			0x00000004
 
 /*  shadow registers (DMA'd from HA to system memory.  read only) */
 struct shadow_regs {
@@ -337,6 +214,7 @@
 
 /*  Mailbox command definitions */
 #define MBOX_CMD_ABOUT_FW			0x0009
+#define MBOX_CMD_PING				0x000B
 #define MBOX_CMD_LUN_RESET			0x0016
 #define MBOX_CMD_GET_MANAGEMENT_DATA		0x001E
 #define MBOX_CMD_GET_FW_STATUS			0x001F
@@ -364,6 +242,17 @@
 #define MBOX_CMD_GET_FW_STATE			0x0069
 #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A
 #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS	0x0087
+#define MBOX_CMD_SET_ACB			0x0088
+#define MBOX_CMD_GET_ACB			0x0089
+#define MBOX_CMD_DISABLE_ACB			0x008A
+#define MBOX_CMD_GET_IPV6_NEIGHBOR_CACHE	0x008B
+#define MBOX_CMD_GET_IPV6_DEST_CACHE		0x008C
+#define MBOX_CMD_GET_IPV6_DEF_ROUTER_LIST	0x008D
+#define MBOX_CMD_GET_IPV6_LCL_PREFIX_LIST	0x008E
+#define MBOX_CMD_SET_IPV6_NEIGHBOR_CACHE	0x0090
+#define MBOX_CMD_GET_IP_ADDR_STATE		0x0091
+#define MBOX_CMD_SEND_IPV6_ROUTER_SOL		0x0092
+#define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR	0x0093
 
 /* Mailbox 1 */
 #define FW_STATE_READY				0x0000
@@ -409,6 +298,16 @@
 #define MBOX_ASTS_DHCP_LEASE_EXPIRED		0x801D
 #define MBOX_ASTS_DHCP_LEASE_ACQUIRED		0x801F
 #define MBOX_ASTS_ISNS_UNSOLICITED_PDU_RECEIVED 0x8021
+#define MBOX_ASTS_DUPLICATE_IP			0x8025
+#define MBOX_ASTS_ARP_COMPLETE			0x8026
+#define MBOX_ASTS_SUBNET_STATE_CHANGE		0x8027
+#define MBOX_ASTS_RESPONSE_QUEUE_FULL		0x8028
+#define MBOX_ASTS_IP_ADDR_STATE_CHANGED		0x8029
+#define MBOX_ASTS_IPV6_PREFIX_EXPIRED		0x802B
+#define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED	0x802C
+#define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED	0x802D
+#define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD		0x802E
+
 #define ISNS_EVENT_DATA_RECEIVED		0x0000
 #define ISNS_EVENT_CONNECTION_OPENED		0x0001
 #define ISNS_EVENT_CONNECTION_FAILED		0x0002
@@ -418,137 +317,166 @@
 /*************************************************************************/
 
 /* Host Adapter Initialization Control Block (from host) */
-struct init_fw_ctrl_blk {
-	uint8_t Version;	/* 00 */
-	uint8_t Control;	/* 01 */
+struct addr_ctrl_blk {
+	uint8_t version;	/* 00 */
+	uint8_t control;	/* 01 */
 
-	uint16_t FwOptions;	/* 02-03 */
+	uint16_t fw_options;	/* 02-03 */
 #define	 FWOPT_HEARTBEAT_ENABLE		  0x1000
 #define	 FWOPT_SESSION_MODE		  0x0040
 #define	 FWOPT_INITIATOR_MODE		  0x0020
 #define	 FWOPT_TARGET_MODE		  0x0010
 
-	uint16_t ExecThrottle;	/* 04-05 */
-	uint8_t RetryCount;	/* 06 */
-	uint8_t RetryDelay;	/* 07 */
-	uint16_t MaxEthFrPayloadSize;	/* 08-09 */
-	uint16_t AddFwOptions;	/* 0A-0B */
+	uint16_t exec_throttle;	/* 04-05 */
+	uint8_t zio_count;	/* 06 */
+	uint8_t res0;	/* 07 */
+	uint16_t eth_mtu_size;	/* 08-09 */
+	uint16_t add_fw_options;	/* 0A-0B */
 
-	uint8_t HeartbeatInterval;	/* 0C */
-	uint8_t InstanceNumber; /* 0D */
-	uint16_t RES2;		/* 0E-0F */
-	uint16_t ReqQConsumerIndex;	/* 10-11 */
-	uint16_t ComplQProducerIndex;	/* 12-13 */
-	uint16_t ReqQLen;	/* 14-15 */
-	uint16_t ComplQLen;	/* 16-17 */
-	uint32_t ReqQAddrLo;	/* 18-1B */
-	uint32_t ReqQAddrHi;	/* 1C-1F */
-	uint32_t ComplQAddrLo;	/* 20-23 */
-	uint32_t ComplQAddrHi;	/* 24-27 */
-	uint32_t ShadowRegBufAddrLo;	/* 28-2B */
-	uint32_t ShadowRegBufAddrHi;	/* 2C-2F */
+	uint8_t hb_interval;	/* 0C */
+	uint8_t inst_num; /* 0D */
+	uint16_t res1;		/* 0E-0F */
+	uint16_t rqq_consumer_idx;	/* 10-11 */
+	uint16_t compq_producer_idx;	/* 12-13 */
+	uint16_t rqq_len;	/* 14-15 */
+	uint16_t compq_len;	/* 16-17 */
+	uint32_t rqq_addr_lo;	/* 18-1B */
+	uint32_t rqq_addr_hi;	/* 1C-1F */
+	uint32_t compq_addr_lo;	/* 20-23 */
+	uint32_t compq_addr_hi;	/* 24-27 */
+	uint32_t shdwreg_addr_lo;	/* 28-2B */
+	uint32_t shdwreg_addr_hi;	/* 2C-2F */
 
-	uint16_t iSCSIOptions;	/* 30-31 */
+	uint16_t iscsi_opts;	/* 30-31 */
+	uint16_t ipv4_tcp_opts;	/* 32-33 */
+	uint16_t ipv4_ip_opts;	/* 34-35 */
 
-	uint16_t TCPOptions;	/* 32-33 */
+	uint16_t iscsi_max_pdu_size;	/* 36-37 */
+	uint8_t ipv4_tos;	/* 38 */
+	uint8_t ipv4_ttl;	/* 39 */
+	uint8_t acb_version;	/* 3A */
+	uint8_t res2;	/* 3B */
+	uint16_t def_timeout;	/* 3C-3D */
+	uint16_t iscsi_fburst_len;	/* 3E-3F */
+	uint16_t iscsi_def_time2wait;	/* 40-41 */
+	uint16_t iscsi_def_time2retain;	/* 42-43 */
+	uint16_t iscsi_max_outstnd_r2t;	/* 44-45 */
+	uint16_t conn_ka_timeout;	/* 46-47 */
+	uint16_t ipv4_port;	/* 48-49 */
+	uint16_t iscsi_max_burst_len;	/* 4A-4B */
+	uint32_t res5;		/* 4C-4F */
+	uint8_t ipv4_addr[4];	/* 50-53 */
+	uint16_t ipv4_vlan_tag;	/* 54-55 */
+	uint8_t ipv4_addr_state;	/* 56 */
+	uint8_t ipv4_cacheid;	/* 57 */
+	uint8_t res6[8];	/* 58-5F */
+	uint8_t ipv4_subnet[4];	/* 60-63 */
+	uint8_t res7[12];	/* 64-6F */
+	uint8_t ipv4_gw_addr[4];	/* 70-73 */
+	uint8_t res8[0xc];	/* 74-7F */
+	uint8_t pri_dns_srvr_ip[4];/* 80-83 */
+	uint8_t sec_dns_srvr_ip[4];/* 84-87 */
+	uint16_t min_eph_port;	/* 88-89 */
+	uint16_t max_eph_port;	/* 8A-8B */
+	uint8_t res9[4];	/* 8C-8F */
+	uint8_t iscsi_alias[32];/* 90-AF */
+	uint8_t res9_1[0x16];	/* B0-C5 */
+	uint16_t tgt_portal_grp;/* C6-C7 */
+	uint8_t abort_timer;	/* C8	 */
+	uint8_t ipv4_tcp_wsf;	/* C9	 */
+	uint8_t res10[6];	/* CA-CF */
+	uint8_t ipv4_sec_ip_addr[4];	/* D0-D3 */
+	uint8_t ipv4_dhcp_vid_len;	/* D4 */
+	uint8_t ipv4_dhcp_vid[11];	/* D5-DF */
+	uint8_t res11[20];	/* E0-F3 */
+	uint8_t ipv4_dhcp_alt_cid_len;	/* F4 */
+	uint8_t ipv4_dhcp_alt_cid[11];	/* F5-FF */
+	uint8_t iscsi_name[224];	/* 100-1DF */
+	uint8_t res12[32];	/* 1E0-1FF */
+	uint32_t cookie;	/* 200-203 */
+	uint16_t ipv6_port;	/* 204-205 */
+	uint16_t ipv6_opts;	/* 206-207 */
+	uint16_t ipv6_addtl_opts;	/* 208-209 */
+	uint16_t ipv6_tcp_opts;	/* 20A-20B */
+	uint8_t ipv6_tcp_wsf;	/* 20C */
+	uint16_t ipv6_flow_lbl;	/* 20D-20F */
+	uint8_t ipv6_gw_addr[16];	/* 210-21F */
+	uint16_t ipv6_vlan_tag;	/* 220-221 */
+	uint8_t ipv6_lnk_lcl_addr_state;/* 222 */
+	uint8_t ipv6_addr0_state;	/* 223 */
+	uint8_t ipv6_addr1_state;	/* 224 */
+	uint8_t ipv6_gw_state;	/* 225 */
+	uint8_t ipv6_traffic_class;	/* 226 */
+	uint8_t ipv6_hop_limit;	/* 227 */
+	uint8_t ipv6_if_id[8];	/* 228-22F */
+	uint8_t ipv6_addr0[16];	/* 230-23F */
+	uint8_t ipv6_addr1[16];	/* 240-24F */
+	uint32_t ipv6_nd_reach_time;	/* 250-253 */
+	uint32_t ipv6_nd_rexmit_timer;	/* 254-257 */
+	uint32_t ipv6_nd_stale_timeout;	/* 258-25B */
+	uint8_t ipv6_dup_addr_detect_count;	/* 25C */
+	uint8_t ipv6_cache_id;	/* 25D */
+	uint8_t res13[18];	/* 25E-26F */
+	uint32_t ipv6_gw_advrt_mtu;	/* 270-273 */
+	uint8_t res14[140];	/* 274-2FF */
+};
 
-	uint16_t IPOptions;	/* 34-35 */
-
-	uint16_t MaxPDUSize;	/* 36-37 */
-	uint16_t RcvMarkerInt;	/* 38-39 */
-	uint16_t SndMarkerInt;	/* 3A-3B */
-	uint16_t InitMarkerlessInt;	/* 3C-3D */
-	uint16_t FirstBurstSize;	/* 3E-3F */
-	uint16_t DefaultTime2Wait;	/* 40-41 */
-	uint16_t DefaultTime2Retain;	/* 42-43 */
-	uint16_t MaxOutStndngR2T;	/* 44-45 */
-	uint16_t KeepAliveTimeout;	/* 46-47 */
-	uint16_t PortNumber;	/* 48-49 */
-	uint16_t MaxBurstSize;	/* 4A-4B */
-	uint32_t RES4;		/* 4C-4F */
-	uint8_t IPAddr[4];	/* 50-53 */
-	uint8_t RES5[12];	/* 54-5F */
-	uint8_t SubnetMask[4];	/* 60-63 */
-	uint8_t RES6[12];	/* 64-6F */
-	uint8_t GatewayIPAddr[4];	/* 70-73 */
-	uint8_t RES7[12];	/* 74-7F */
-	uint8_t PriDNSIPAddr[4];	/* 80-83 */
-	uint8_t SecDNSIPAddr[4];	/* 84-87 */
-	uint8_t RES8[8];	/* 88-8F */
-	uint8_t Alias[32];	/* 90-AF */
-	uint8_t TargAddr[8];	/* B0-B7 *//* /FIXME: Remove?? */
-	uint8_t CHAPNameSecretsTable[8];	/* B8-BF */
-	uint8_t EthernetMACAddr[6];	/* C0-C5 */
-	uint16_t TargetPortalGroup;	/* C6-C7 */
-	uint8_t SendScale;	/* C8	 */
-	uint8_t RecvScale;	/* C9	 */
-	uint8_t TypeOfService;	/* CA	 */
-	uint8_t Time2Live;	/* CB	 */
-	uint16_t VLANPriority;	/* CC-CD */
-	uint16_t Reserved8;	/* CE-CF */
-	uint8_t SecIPAddr[4];	/* D0-D3 */
-	uint8_t Reserved9[12];	/* D4-DF */
-	uint8_t iSNSIPAddr[4];	/* E0-E3 */
-	uint16_t iSNSServerPortNumber;	/* E4-E5 */
-	uint8_t Reserved10[10]; /* E6-EF */
-	uint8_t SLPDAIPAddr[4]; /* F0-F3 */
-	uint8_t Reserved11[12]; /* F4-FF */
-	uint8_t iSCSINameString[256];	/* 100-1FF */
+struct init_fw_ctrl_blk {
+	struct addr_ctrl_blk pri;
+	struct addr_ctrl_blk sec;
 };
 
 /*************************************************************************/
 
 struct dev_db_entry {
-	uint8_t options;	/* 00 */
+	uint16_t options;	/* 00-01 */
 #define DDB_OPT_DISC_SESSION  0x10
 #define DDB_OPT_TARGET	      0x02 /* device is a target */
 
-	uint8_t control;	/* 01 */
-
-	uint16_t exeThrottle;	/* 02-03 */
-	uint16_t exeCount;	/* 04-05 */
-	uint8_t retryCount;	/* 06	 */
-	uint8_t retryDelay;	/* 07	 */
-	uint16_t iSCSIOptions;	/* 08-09 */
-
-	uint16_t TCPOptions;	/* 0A-0B */
-
-	uint16_t IPOptions;	/* 0C-0D */
-
-	uint16_t maxPDUSize;	/* 0E-0F */
-	uint16_t rcvMarkerInt;	/* 10-11 */
-	uint16_t sndMarkerInt;	/* 12-13 */
-	uint16_t iSCSIMaxSndDataSegLen; /* 14-15 */
-	uint16_t firstBurstSize;	/* 16-17 */
-	uint16_t minTime2Wait;	/* 18-19 : RA :default_time2wait */
-	uint16_t maxTime2Retain;	/* 1A-1B */
-	uint16_t maxOutstndngR2T;	/* 1C-1D */
-	uint16_t keepAliveTimeout;	/* 1E-1F */
-	uint8_t ISID[6];	/* 20-25 big-endian, must be converted
+	uint16_t exec_throttle;	/* 02-03 */
+	uint16_t exec_count;	/* 04-05 */
+	uint16_t res0;	/* 06-07 */
+	uint16_t iscsi_options;	/* 08-09 */
+	uint16_t tcp_options;	/* 0A-0B */
+	uint16_t ip_options;	/* 0C-0D */
+	uint16_t iscsi_max_rcv_data_seg_len;	/* 0E-0F */
+	uint32_t res1;	/* 10-13 */
+	uint16_t iscsi_max_snd_data_seg_len;	/* 14-15 */
+	uint16_t iscsi_first_burst_len;	/* 16-17 */
+	uint16_t iscsi_def_time2wait;	/* 18-19 */
+	uint16_t iscsi_def_time2retain;	/* 1A-1B */
+	uint16_t iscsi_max_outsnd_r2t;	/* 1C-1D */
+	uint16_t ka_timeout;	/* 1E-1F */
+	uint8_t isid[6];	/* 20-25 big-endian, must be converted
 				 * to little-endian */
-	uint16_t TSID;		/* 26-27 */
-	uint16_t portNumber;	/* 28-29 */
-	uint16_t maxBurstSize;	/* 2A-2B */
-	uint16_t taskMngmntTimeout;	/* 2C-2D */
-	uint16_t reserved1;	/* 2E-2F */
-	uint8_t ipAddr[0x10];	/* 30-3F */
-	uint8_t iSCSIAlias[0x20];	/* 40-5F */
-	uint8_t targetAddr[0x20];	/* 60-7F */
-	uint8_t userID[0x20];	/* 80-9F */
-	uint8_t password[0x20]; /* A0-BF */
-	uint8_t iscsiName[0x100];	/* C0-1BF : xxzzy Make this a
+	uint16_t tsid;		/* 26-27 */
+	uint16_t port;	/* 28-29 */
+	uint16_t iscsi_max_burst_len;	/* 2A-2B */
+	uint16_t def_timeout;	/* 2C-2D */
+	uint16_t res2;	/* 2E-2F */
+	uint8_t ip_addr[0x10];	/* 30-3F */
+	uint8_t iscsi_alias[0x20];	/* 40-5F */
+	uint8_t tgt_addr[0x20];	/* 60-7F */
+	uint16_t mss;	/* 80-81 */
+	uint16_t res3;	/* 82-83 */
+	uint16_t lcl_port;	/* 84-85 */
+	uint8_t ipv4_tos;	/* 86 */
+	uint16_t ipv6_flow_lbl;	/* 87-89 */
+	uint8_t res4[0x36];	/* 8A-BF */
+	uint8_t iscsi_name[0xE0];	/* C0-19F : xxzzy Make this a
 					 * pointer to a string so we
 					 * don't have to reserve soooo
 					 * much RAM */
-	uint16_t ddbLink;	/* 1C0-1C1 */
-	uint16_t CHAPTableIndex; /* 1C2-1C3 */
-	uint16_t TargetPortalGroup; /* 1C4-1C5 */
-	uint16_t reserved2[2];	/* 1C6-1C7 */
-	uint32_t statSN;	/* 1C8-1CB */
-	uint32_t expStatSN;	/* 1CC-1CF */
-	uint16_t reserved3[0x2C]; /* 1D0-1FB */
-	uint16_t ddbValidCookie; /* 1FC-1FD */
-	uint16_t ddbValidSize;	/* 1FE-1FF */
+	uint8_t ipv6_addr[0x10];/* 1A0-1AF */
+	uint8_t res5[0x10];	/* 1B0-1BF */
+	uint16_t ddb_link;	/* 1C0-1C1 */
+	uint16_t chap_tbl_idx;	/* 1C2-1C3 */
+	uint16_t tgt_portal_grp; /* 1C4-1C5 */
+	uint8_t tcp_xmt_wsf;	/* 1C6 */
+	uint8_t tcp_rcv_wsf;	/* 1C7 */
+	uint32_t stat_sn;	/* 1C8-1CB */
+	uint32_t exp_stat_sn;	/* 1CC-1CF */
+	uint8_t res6[0x30];	/* 1D0-1FF */
 };
 
 /*************************************************************************/
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 5b00cb0..a3608e0 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -8,6 +8,9 @@
 #ifndef __QLA4x_GBL_H
 #define	__QLA4x_GBL_H
 
+struct iscsi_cls_conn;
+
+void qla4xxx_hw_reset(struct scsi_qla_host *ha);
 int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
 int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
 int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb);
@@ -58,11 +61,13 @@
 void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
 				       uint32_t intr_status);
 int qla4xxx_init_rings(struct scsi_qla_host * ha);
-struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index);
+struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
+					uint32_t index);
 void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
 int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
 int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
 				uint32_t fw_ddb_index, uint32_t state);
+void qla4xxx_dump_buffer(void *b, uint32_t size);
 
 extern int ql4xextended_error_logging;
 extern int ql4xdiscoverywait;
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 6365df2..1e29f51 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -6,6 +6,9 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
 					    uint32_t fw_ddb_index);
@@ -300,12 +303,12 @@
 	if (!qla4xxx_fw_ready(ha))
 		return status;
 
-	set_bit(AF_ONLINE, &ha->flags);
 	return qla4xxx_get_firmware_status(ha);
 }
 
 static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
-					       uint32_t fw_ddb_index)
+						uint32_t fw_ddb_index,
+						uint32_t *new_tgt)
 {
 	struct dev_db_entry *fw_ddb_entry = NULL;
 	dma_addr_t fw_ddb_entry_dma;
@@ -313,6 +316,7 @@
 	int found = 0;
 	uint32_t device_state;
 
+	*new_tgt = 0;
 	/* Make sure the dma buffer is valid */
 	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
 					  sizeof(*fw_ddb_entry),
@@ -337,7 +341,7 @@
 	DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
 		      __func__, fw_ddb_index));
 	list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
-		if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsiName,
+		if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
 			   ISCSI_NAME_SIZE) == 0) {
 			found++;
 			break;
@@ -348,6 +352,7 @@
 		DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating "
 			      "new ddb\n", ha->host_no, __func__,
 			      fw_ddb_index));
+		*new_tgt = 1;
 		ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
 	}
 
@@ -409,26 +414,26 @@
 	}
 
 	status = QLA_SUCCESS;
-	ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->TSID);
+	ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid);
 	ddb_entry->task_mgmt_timeout =
-		le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
+		le16_to_cpu(fw_ddb_entry->def_timeout);
 	ddb_entry->CmdSn = 0;
-	ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exeThrottle);
+	ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle);
 	ddb_entry->default_relogin_timeout =
-		le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
-	ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->minTime2Wait);
+		le16_to_cpu(fw_ddb_entry->def_timeout);
+	ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
 
 	/* Update index in case it changed */
 	ddb_entry->fw_ddb_index = fw_ddb_index;
 	ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
 
-	ddb_entry->port = le16_to_cpu(fw_ddb_entry->portNumber);
-	ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->TargetPortalGroup);
-	memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsiName[0],
+	ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
+	ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+	memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
 	       min(sizeof(ddb_entry->iscsi_name),
-		   sizeof(fw_ddb_entry->iscsiName)));
-	memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ipAddr[0],
-	       min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ipAddr)));
+		   sizeof(fw_ddb_entry->iscsi_name)));
+	memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0],
+	       min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr)));
 
 	DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n",
 		      ha->host_no, __func__, fw_ddb_index,
@@ -495,6 +500,7 @@
 	uint32_t ddb_state;
 	uint32_t conn_err, err_code;
 	struct ddb_entry *ddb_entry;
+	uint32_t new_tgt;
 
 	dev_info(&ha->pdev->dev, "Initializing DDBs ...\n");
 	for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
@@ -526,8 +532,19 @@
 					      "completed "
 					      "or access denied failure\n",
 					      ha->host_no, __func__));
-			} else
+			} else {
 				qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
+				if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
+					NULL, 0, NULL, &next_fw_ddb_index,
+					&ddb_state, &conn_err, NULL, NULL)
+					== QLA_ERROR) {
+					DEBUG2(printk("scsi%ld: %s:"
+						"get_ddb_entry %d failed\n",
+						ha->host_no,
+						__func__, fw_ddb_index));
+					return QLA_ERROR;
+				}
+			}
 		}
 
 		if (ddb_state != DDB_DS_SESSION_ACTIVE)
@@ -540,7 +557,7 @@
 			      ha->host_no, __func__, fw_ddb_index));
 
 		/* Add DDB to internal our ddb list. */
-		ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
+		ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
 		if (ddb_entry == NULL) {
 			DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
 				      "for device at fw_ddb_index %d\n",
@@ -865,21 +882,20 @@
 
 static void qla4x00_pci_config(struct scsi_qla_host *ha)
 {
-	uint16_t w, mwi;
+	uint16_t w;
+	int status;
 
 	dev_info(&ha->pdev->dev, "Configuring PCI space...\n");
 
 	pci_set_master(ha->pdev);
-	mwi = 0;
-	if (pci_set_mwi(ha->pdev))
-		mwi = PCI_COMMAND_INVALIDATE;
+	status = pci_set_mwi(ha->pdev);
 	/*
 	 * We want to respect framework's setting of PCI configuration space
 	 * command register and also want to make sure that all bits of
 	 * interest to us are properly set in command register.
 	 */
 	pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
-	w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+	w |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
 	w &= ~PCI_COMMAND_INTX_DISABLE;
 	pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 }
@@ -911,6 +927,9 @@
 		writel(set_rmask(NVR_WRITE_ENABLE),
 		       &ha->reg->u1.isp4022.nvram);
 
+        writel(2, &ha->reg->mailbox[6]);
+        readl(&ha->reg->mailbox[6]);
+
 	writel(set_rmask(CSR_BOOT_ENABLE), &ha->reg->ctrl_status);
 	readl(&ha->reg->ctrl_status);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -958,25 +977,25 @@
 	return status;
 }
 
-int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
+int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
 {
-#define QL4_LOCK_DRVR_WAIT	30
+#define QL4_LOCK_DRVR_WAIT	60
 #define QL4_LOCK_DRVR_SLEEP	1
 
 	int drvr_wait = QL4_LOCK_DRVR_WAIT;
 	while (drvr_wait) {
-		if (ql4xxx_lock_drvr(ha) == 0) {
+		if (ql4xxx_lock_drvr(a) == 0) {
 			ssleep(QL4_LOCK_DRVR_SLEEP);
 			if (drvr_wait) {
 				DEBUG2(printk("scsi%ld: %s: Waiting for "
-					      "Global Init Semaphore(%d)...n",
-					      ha->host_no,
+					      "Global Init Semaphore(%d)...\n",
+					      a->host_no,
 					      __func__, drvr_wait));
 			}
 			drvr_wait -= QL4_LOCK_DRVR_SLEEP;
 		} else {
 			DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
-				      "acquired.n", ha->host_no, __func__));
+				      "acquired\n", a->host_no, __func__));
 			return QLA_SUCCESS;
 		}
 	}
@@ -1125,17 +1144,17 @@
 
 	/* Initialize the Host adapter request/response queues and firmware */
 	if (qla4xxx_start_firmware(ha) == QLA_ERROR)
-		return status;
+		goto exit_init_hba;
 
 	if (qla4xxx_validate_mac_address(ha) == QLA_ERROR)
-		return status;
+		goto exit_init_hba;
 
 	if (qla4xxx_init_local_data(ha) == QLA_ERROR)
-		return status;
+		goto exit_init_hba;
 
 	status = qla4xxx_init_firmware(ha);
 	if (status == QLA_ERROR)
-		return status;
+		goto exit_init_hba;
 
 	/*
 	 * FW is waiting to get an IP address from DHCP server: Skip building
@@ -1143,12 +1162,12 @@
 	 * followed by 0x8014 aen" to trigger the tgt discovery process.
 	 */
 	if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS)
-		return status;
+		goto exit_init_online;
 
 	/* Skip device discovery if ip and subnet is zero */
 	if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
 	    memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0)
-		return status;
+		goto exit_init_online;
 
 	if (renew_ddb_list == PRESERVE_DDB_LIST) {
 		/*
@@ -1177,9 +1196,10 @@
 			      ha->host_no));
 	}
 
- exit_init_hba:
+exit_init_online:
+	set_bit(AF_ONLINE, &ha->flags);
+exit_init_hba:
 	return status;
-
 }
 
 /**
@@ -1193,9 +1213,10 @@
 					   uint32_t fw_ddb_index)
 {
 	struct ddb_entry * ddb_entry;
+	uint32_t new_tgt;
 
 	/* First allocate a device structure */
-	ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
+	ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
 	if (ddb_entry == NULL) {
 		DEBUG2(printk(KERN_WARNING
 			      "scsi%ld: Unable to allocate memory to add "
@@ -1203,6 +1224,18 @@
 		return;
 	}
 
+	if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) {
+		/* Target has been bound to a new fw_ddb_index */
+		qla4xxx_free_ddb(ha, ddb_entry);
+		ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
+		if (ddb_entry == NULL) {
+			DEBUG2(printk(KERN_WARNING
+				"scsi%ld: Unable to allocate memory"
+				" to add fw_ddb_index %d\n",
+				ha->host_no, fw_ddb_index));
+			return;
+		}
+	}
 	if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
 				    QLA_ERROR) {
 		ha->fw_ddb_index_map[fw_ddb_index] =
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index a216a17..5006ecb 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -6,6 +6,10 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
+
 
 #include <scsi/scsi_tcq.h>
 
@@ -141,11 +145,13 @@
 	uint16_t avail_dsds;
 	struct data_seg_a64 *cur_dsd;
 	struct scsi_cmnd *cmd;
+	struct scatterlist *sg;
+	int i;
 
 	cmd = srb->cmd;
 	ha = srb->ha;
 
-	if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+	if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
 		/* No data being transferred */
 		cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0);
 		return;
@@ -154,40 +160,27 @@
 	avail_dsds = COMMAND_SEG;
 	cur_dsd = (struct data_seg_a64 *) & (cmd_entry->dataseg[0]);
 
-	/* Load data segments */
-	if (cmd->use_sg) {
-		struct scatterlist *cur_seg;
-		struct scatterlist *end_seg;
+	scsi_for_each_sg(cmd, sg, tot_dsds, i) {
+		dma_addr_t sle_dma;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		end_seg = cur_seg + tot_dsds;
-		while (cur_seg < end_seg) {
-			dma_addr_t sle_dma;
+		/* Allocate additional continuation packets? */
+		if (avail_dsds == 0) {
+			struct continuation_t1_entry *cont_entry;
 
-			/* Allocate additional continuation packets? */
-			if (avail_dsds == 0) {
-				struct continuation_t1_entry *cont_entry;
-
-				cont_entry = qla4xxx_alloc_cont_entry(ha);
-				cur_dsd =
-					(struct data_seg_a64 *)
-					&cont_entry->dataseg[0];
-				avail_dsds = CONTINUE_SEG;
-			}
-
-			sle_dma = sg_dma_address(cur_seg);
-			cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma));
-			cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma));
-			cur_dsd->count = cpu_to_le32(sg_dma_len(cur_seg));
-			avail_dsds--;
-
-			cur_dsd++;
-			cur_seg++;
+			cont_entry = qla4xxx_alloc_cont_entry(ha);
+			cur_dsd =
+				(struct data_seg_a64 *)
+				&cont_entry->dataseg[0];
+			avail_dsds = CONTINUE_SEG;
 		}
-	} else {
-		cur_dsd->base.addrLow = cpu_to_le32(LSDW(srb->dma_handle));
-		cur_dsd->base.addrHigh = cpu_to_le32(MSDW(srb->dma_handle));
-		cur_dsd->count = cpu_to_le32(cmd->request_bufflen);
+
+		sle_dma = sg_dma_address(sg);
+		cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma));
+		cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma));
+		cur_dsd->count = cpu_to_le32(sg_dma_len(sg));
+		avail_dsds--;
+
+		cur_dsd++;
 	}
 }
 
@@ -204,8 +197,8 @@
 	struct scsi_cmnd *cmd = srb->cmd;
 	struct ddb_entry *ddb_entry;
 	struct command_t3_entry *cmd_entry;
-	struct scatterlist *sg = NULL;
 
+	int nseg;
 	uint16_t tot_dsds;
 	uint16_t req_cnt;
 
@@ -233,24 +226,11 @@
 	index = (uint32_t)cmd->request->tag;
 
 	/* Calculate the number of request entries needed. */
-	if (cmd->use_sg) {
-		sg = (struct scatterlist *)cmd->request_buffer;
-		tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
-				      cmd->sc_data_direction);
-		if (tot_dsds == 0)
-			goto queuing_error;
-	} else if (cmd->request_bufflen) {
-		dma_addr_t	req_dma;
+	nseg = scsi_dma_map(cmd);
+	if (nseg < 0)
+		goto queuing_error;
+	tot_dsds = nseg;
 
-		req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
-					 cmd->request_bufflen,
-					 cmd->sc_data_direction);
-		if (dma_mapping_error(req_dma))
-			goto queuing_error;
-
-		srb->dma_handle = req_dma;
-		tot_dsds = 1;
-	}
 	req_cnt = qla4xxx_calc_request_entries(tot_dsds);
 
 	if (ha->req_q_count < (req_cnt + 2)) {
@@ -279,7 +259,7 @@
 
 	int_to_scsilun(cmd->device->lun, &cmd_entry->lun);
 	cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn);
-	cmd_entry->ttlByteCnt = cpu_to_le32(cmd->request_bufflen);
+	cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd));
 	memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len);
 	cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds);
 	cmd_entry->hdr.entryCount = req_cnt;
@@ -289,13 +269,13 @@
 	 *	 transferred, as the data direction bit is sometimed filled
 	 *	 in when there is no data to be transferred */
 	cmd_entry->control_flags = CF_NO_DATA;
-	if (cmd->request_bufflen) {
+	if (scsi_bufflen(cmd)) {
 		if (cmd->sc_data_direction == DMA_TO_DEVICE)
 			cmd_entry->control_flags = CF_WRITE;
 		else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
 			cmd_entry->control_flags = CF_READ;
 
-		ha->bytes_xfered += cmd->request_bufflen;
+		ha->bytes_xfered += scsi_bufflen(cmd);
 		if (ha->bytes_xfered & ~0xFFFFF){
 			ha->total_mbytes_xferred += ha->bytes_xfered >> 20;
 			ha->bytes_xfered &= 0xFFFFF;
@@ -359,14 +339,9 @@
 	return QLA_SUCCESS;
 
 queuing_error:
+	if (tot_dsds)
+		scsi_dma_unmap(cmd);
 
-	if (cmd->use_sg && tot_dsds) {
-		sg = (struct scatterlist *) cmd->request_buffer;
-		pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
-			     cmd->sc_data_direction);
-	} else if (tot_dsds)
-		pci_unmap_single(ha->pdev, srb->dma_handle,
-				 cmd->request_bufflen, cmd->sc_data_direction);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	return QLA_ERROR;
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 35b9e36..4a154be 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -6,6 +6,9 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 /**
  * qla2x00_process_completed_request() - Process a Fast Post response.
@@ -90,9 +93,29 @@
 			break;
 		}
 
-		if (sts_entry->iscsiFlags &
-		    (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER))
-			cmd->resid = residual;
+		if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
+			cmd->result = DID_ERROR << 16;
+			break;
+		}
+
+		if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
+			scsi_set_resid(cmd, residual);
+			if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
+				cmd->underflow)) {
+
+				cmd->result = DID_ERROR << 16;
+
+				DEBUG2(printk("scsi%ld:%d:%d:%d: %s: "
+					"Mid-layer Data underrun0, "
+					"xferlen = 0x%x, "
+					"residual = 0x%x\n", ha->host_no,
+					cmd->device->channel,
+					cmd->device->id,
+					cmd->device->lun, __func__,
+					scsi_bufflen(cmd), residual));
+				break;
+			}
+		}
 
 		cmd->result = DID_OK << 16 | scsi_status;
 
@@ -161,7 +184,8 @@
 
 	case SCS_DATA_UNDERRUN:
 	case SCS_DATA_OVERRUN:
-		if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
+		if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) ||
+			(sts_entry->completionStatus == SCS_DATA_OVERRUN)) {
 			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun, "
 				      "residual = 0x%x\n", ha->host_no,
 				      cmd->device->channel, cmd->device->id,
@@ -171,21 +195,7 @@
 			break;
 		}
 
-		if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
-			/*
-			 * Firmware detected a SCSI transport underrun
-			 * condition
-			 */
-			cmd->resid = residual;
-			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status "
-				      "detected, xferlen = 0x%x, residual = "
-				      "0x%x\n",
-				      ha->host_no, cmd->device->channel,
-				      cmd->device->id,
-				      cmd->device->lun, __func__,
-				      cmd->request_bufflen,
-				      residual));
-		}
+		scsi_set_resid(cmd, residual);
 
 		/*
 		 * If there is scsi_status, it takes precedense over
@@ -227,7 +237,7 @@
 			if ((sts_entry->iscsiFlags &
 			     ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
 				cmd->result = DID_BUS_BUSY << 16;
-			} else if ((cmd->request_bufflen - residual) <
+			} else if ((scsi_bufflen(cmd) - residual) <
 				   cmd->underflow) {
 				/*
 				 * Handle mid-layer underflow???
@@ -242,13 +252,13 @@
 				 * will return DID_ERROR.
 				 */
 				DEBUG2(printk("scsi%ld:%d:%d:%d: %s: "
-					      "Mid-layer Data underrun, "
-					      "xferlen = 0x%x, "
-					      "residual = 0x%x\n", ha->host_no,
-					      cmd->device->channel,
-					      cmd->device->id,
-					      cmd->device->lun, __func__,
-					      cmd->request_bufflen, residual));
+					"Mid-layer Data underrun1, "
+					"xferlen = 0x%x, "
+					"residual = 0x%x\n", ha->host_no,
+					cmd->device->channel,
+					cmd->device->id,
+					cmd->device->lun, __func__,
+					scsi_bufflen(cmd), residual));
 
 				cmd->result = DID_ERROR << 16;
 			} else {
@@ -417,6 +427,7 @@
 				       uint32_t mbox_status)
 {
 	int i;
+	uint32_t mbox_stat2, mbox_stat3;
 
 	if ((mbox_status == MBOX_STS_BUSY) ||
 	    (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
@@ -437,6 +448,12 @@
 	} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
 		/* Immediately process the AENs that don't require much work.
 		 * Only queue the database_changed AENs */
+		if (ha->aen_log.count < MAX_AEN_ENTRIES) {
+			for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
+				ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] =
+					readl(&ha->reg->mailbox[i]);
+			ha->aen_log.count++;
+		}
 		switch (mbox_status) {
 		case MBOX_ASTS_SYSTEM_ERROR:
 			/* Log Mailbox registers */
@@ -493,6 +510,16 @@
 				      mbox_status));
 			break;
 
+		case MBOX_ASTS_IP_ADDR_STATE_CHANGED:
+			mbox_stat2 = readl(&ha->reg->mailbox[2]);
+			mbox_stat3 = readl(&ha->reg->mailbox[3]);
+
+			if ((mbox_stat3 == 5) && (mbox_stat2 == 3))
+				set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
+			else if ((mbox_stat3 == 2) && (mbox_stat2 == 5))
+				set_bit(DPC_RESET_HA, &ha->dpc_flags);
+			break;
+
 		case MBOX_ASTS_MAC_ADDRESS_CHANGED:
 		case MBOX_ASTS_DNS:
 			/* No action */
@@ -518,11 +545,6 @@
 			/* Queue AEN information and process it in the DPC
 			 * routine */
 			if (ha->aen_q_count > 0) {
-				/* advance pointer */
-				if (ha->aen_in == (MAX_AEN_ENTRIES - 1))
-					ha->aen_in = 0;
-				else
-					ha->aen_in++;
 
 				/* decrement available counter */
 				ha->aen_q_count--;
@@ -542,6 +564,10 @@
 					      ha->aen_q[ha->aen_in].mbox_sts[2],
 					      ha->aen_q[ha->aen_in].mbox_sts[3],
 					      ha->aen_q[ha->aen_in].  mbox_sts[4]));
+				/* advance pointer */
+				ha->aen_in++;
+				if (ha->aen_in == MAX_AEN_ENTRIES)
+					ha->aen_in = 0;
 
 				/* The DPC routine will process the aen */
 				set_bit(DPC_AEN, &ha->dpc_flags);
@@ -724,25 +750,24 @@
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	while (ha->aen_out != ha->aen_in) {
-		/* Advance pointers for next entry */
-		if (ha->aen_out == (MAX_AEN_ENTRIES - 1))
-			ha->aen_out = 0;
-		else
-			ha->aen_out++;
-
-		ha->aen_q_count++;
 		aen = &ha->aen_q[ha->aen_out];
-
 		/* copy aen information to local structure */
 		for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
 			mbox_sts[i] = aen->mbox_sts[i];
 
+		ha->aen_q_count++;
+		ha->aen_out++;
+
+		if (ha->aen_out == MAX_AEN_ENTRIES)
+			ha->aen_out = 0;
+
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-		DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x "
-			     "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out,
-			     mbox_sts[0], mbox_sts[2], mbox_sts[3],
-			     mbox_sts[1], mbox_sts[4]));
+		DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x"
+			" mbx3=0x%08x mbx4=0x%08x\n", ha->host_no,
+			(ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)),
+			mbox_sts[0], mbox_sts[1], mbox_sts[2],
+			mbox_sts[3], mbox_sts[4]));
 
 		switch (mbox_sts[0]) {
 		case MBOX_ASTS_DATABASE_CHANGED:
@@ -792,6 +817,5 @@
 		spin_lock_irqsave(&ha->hardware_lock, flags);
 	}
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
 }
 
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index f116ff9..35cd73c 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -6,6 +6,9 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 
 /**
@@ -169,84 +172,6 @@
 	return status;
 }
 
-
-#if 0
-
-/**
- * qla4xxx_issue_iocb - issue mailbox iocb command
- * @ha: adapter state pointer.
- * @buffer: buffer pointer.
- * @phys_addr: physical address of buffer.
- * @size: size of buffer.
- *
- * Issues iocbs via mailbox commands.
- * TARGET_QUEUE_LOCK must be released.
- * ADAPTER_STATE_LOCK must be released.
- **/
-int
-qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer,
-		   dma_addr_t phys_addr, size_t size)
-{
-	uint32_t mbox_cmd[MBOX_REG_COUNT];
-	uint32_t mbox_sts[MBOX_REG_COUNT];
-	int status;
-
-	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-	memset(&mbox_sts, 0, sizeof(mbox_sts));
-	mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64;
-	mbox_cmd[1] = 0;
-	mbox_cmd[2] = LSDW(phys_addr);
-	mbox_cmd[3] = MSDW(phys_addr);
-	status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
-	return status;
-}
-
-int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
-				   uint16_t fw_ddb_index,
-				   uint16_t connection_id,
-				   uint16_t option)
-{
-	uint32_t mbox_cmd[MBOX_REG_COUNT];
-	uint32_t mbox_sts[MBOX_REG_COUNT];
-
-	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-	memset(&mbox_sts, 0, sizeof(mbox_sts));
-	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
-	mbox_cmd[1] = fw_ddb_index;
-	mbox_cmd[2] = connection_id;
-	mbox_cmd[3] = LOGOUT_OPTION_RELOGIN;
-	if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) !=
-	    QLA_SUCCESS) {
-		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
-			      "option %04x failed sts %04X %04X",
-			      ha->host_no, __func__,
-			      option, mbox_sts[0], mbox_sts[1]));
-		if (mbox_sts[0] == 0x4005)
-			DEBUG2(printk("%s reason %04X\n", __func__,
-				      mbox_sts[1]));
-	}
-	return QLA_SUCCESS;
-}
-
-int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
-				 uint16_t fw_ddb_index)
-{
-	uint32_t mbox_cmd[MBOX_REG_COUNT];
-	uint32_t mbox_sts[MBOX_REG_COUNT];
-
-	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-	memset(&mbox_sts, 0, sizeof(mbox_sts));
-	mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
-	mbox_cmd[1] = fw_ddb_index;
-	if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) !=
-	    QLA_SUCCESS)
-		return QLA_ERROR;
-
-	return QLA_SUCCESS;
-}
-
-#endif  /*  0  */
-
 /**
  * qla4xxx_initialize_fw_cb - initializes firmware control block.
  * @ha: Pointer to host adapter structure.
@@ -272,10 +197,13 @@
 	/* Get Initialize Firmware Control Block. */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
-	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		dma_free_coherent(&ha->pdev->dev,
 				  sizeof(struct init_fw_ctrl_blk),
@@ -287,51 +215,56 @@
 	qla4xxx_init_rings(ha);
 
 	/* Fill in the request and response queue information. */
-	init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out);
-	init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in);
-	init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
-	init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
-	init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma));
-	init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma));
-	init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma));
-	init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma));
-	init_fw_cb->ShadowRegBufAddrLo =
+	init_fw_cb->pri.rqq_consumer_idx = cpu_to_le16(ha->request_out);
+	init_fw_cb->pri.compq_producer_idx = cpu_to_le16(ha->response_in);
+	init_fw_cb->pri.rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
+	init_fw_cb->pri.compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
+	init_fw_cb->pri.rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
+	init_fw_cb->pri.rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
+	init_fw_cb->pri.compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
+	init_fw_cb->pri.compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
+	init_fw_cb->pri.shdwreg_addr_lo =
 		cpu_to_le32(LSDW(ha->shadow_regs_dma));
-	init_fw_cb->ShadowRegBufAddrHi =
+	init_fw_cb->pri.shdwreg_addr_hi =
 		cpu_to_le32(MSDW(ha->shadow_regs_dma));
 
 	/* Set up required options. */
-	init_fw_cb->FwOptions |=
+	init_fw_cb->pri.fw_options |=
 		__constant_cpu_to_le16(FWOPT_SESSION_MODE |
 				       FWOPT_INITIATOR_MODE);
-	init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
+	init_fw_cb->pri.fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
 
 	/* Save some info in adapter structure. */
-	ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions);
-	ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions);
-	ha->heartbeat_interval = init_fw_cb->HeartbeatInterval;
-	memcpy(ha->ip_address, init_fw_cb->IPAddr,
-	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
-	memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
-	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
-	memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
-	       min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
-	memcpy(ha->name_string, init_fw_cb->iSCSINameString,
+	ha->firmware_options = le16_to_cpu(init_fw_cb->pri.fw_options);
+	ha->tcp_options = le16_to_cpu(init_fw_cb->pri.ipv4_tcp_opts);
+	ha->heartbeat_interval = init_fw_cb->pri.hb_interval;
+	memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr,
+	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr)));
+	memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet,
+	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet)));
+	memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr,
+	       min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr)));
+	memcpy(ha->name_string, init_fw_cb->pri.iscsi_name,
 	       min(sizeof(ha->name_string),
-		   sizeof(init_fw_cb->iSCSINameString)));
-	memcpy(ha->alias, init_fw_cb->Alias,
-	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));
+		   sizeof(init_fw_cb->pri.iscsi_name)));
+	/*memcpy(ha->alias, init_fw_cb->Alias,
+	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
 
 	/* Save Command Line Paramater info */
-	ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout);
+	ha->port_down_retry_count = le16_to_cpu(init_fw_cb->pri.conn_ka_timeout);
 	ha->discovery_wait = ql4xdiscoverywait;
 
 	/* Send Initialize Firmware Control Block. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
 	mbox_cmd[1] = 0;
 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
-	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) ==
+	mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) ==
 	    QLA_SUCCESS)
 		status = QLA_SUCCESS;
 	 else {
@@ -368,12 +301,14 @@
 	/* Get Initialize Firmware Control Block. */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
 	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
+	mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
 
-	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
 			      ha->host_no, __func__));
@@ -384,12 +319,12 @@
 	}
 
 	/* Save IP Address. */
-	memcpy(ha->ip_address, init_fw_cb->IPAddr,
-	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
-	memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
-	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
-	memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
-	       min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
+	memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr,
+	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr)));
+	memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet,
+	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet)));
+	memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr,
+	       min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr)));
 
 	dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
 			  init_fw_cb, init_fw_cb_dma);
@@ -409,8 +344,10 @@
 	/* Get firmware version */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
-	if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
 			      "status %04X\n", ha->host_no, __func__,
@@ -438,8 +375,10 @@
 	/* Get firmware version */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
-	if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
 			      "status %04X\n", ha->host_no, __func__,
@@ -491,11 +430,14 @@
 	}
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
-	if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) ==
+	mbox_cmd[4] = sizeof(struct dev_db_entry);
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
 	    QLA_ERROR) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
 			      " with status 0x%04X\n", ha->host_no, __func__,
@@ -512,11 +454,11 @@
 		dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d "
 			   "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n",
 			   fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3],
-			   mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0],
-			   fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2],
-			   fw_ddb_entry->ipAddr[3],
-			   le16_to_cpu(fw_ddb_entry->portNumber),
-			   fw_ddb_entry->iscsiName);
+			   mbox_sts[4], mbox_sts[5], fw_ddb_entry->ip_addr[0],
+			   fw_ddb_entry->ip_addr[1], fw_ddb_entry->ip_addr[2],
+			   fw_ddb_entry->ip_addr[3],
+			   le16_to_cpu(fw_ddb_entry->port),
+			   fw_ddb_entry->iscsi_name);
 	}
 	if (num_valid_ddb_entries)
 		*num_valid_ddb_entries = mbox_sts[2];
@@ -571,36 +513,11 @@
 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
-	return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
+	mbox_cmd[4] = sizeof(struct dev_db_entry);
+
+	return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
 }
 
-#if 0
-int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
-				    uint16_t fw_ddb_index)
-{
-	int status = QLA_ERROR;
-	uint32_t mbox_cmd[MBOX_REG_COUNT];
-	uint32_t mbox_sts[MBOX_REG_COUNT];
-
-	/* Do not wait for completion. The firmware will send us an
-	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
-	 */
-	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-	memset(&mbox_sts, 0, sizeof(mbox_sts));
-	mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN;
-	mbox_cmd[1] = (uint32_t) fw_ddb_index;
-	mbox_cmd[2] = 0;
-	mbox_cmd[3] = 0;
-	mbox_cmd[4] = 0;
-	status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]);
-	DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n",
-		      __func__, fw_ddb_index, status, mbox_sts[0],
-		      mbox_sts[1]);)
-
-		return status;
-}
-#endif  /*  0  */
-
 /**
  * qla4xxx_get_crash_record - retrieves crash record.
  * @ha: Pointer to host adapter structure.
@@ -614,12 +531,14 @@
 	struct crash_record *crash_record = NULL;
 	dma_addr_t crash_record_dma = 0;
 	uint32_t crash_record_size = 0;
+
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
 
 	/* Get size of crash record. */
 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
-	if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
 			      ha->host_no, __func__));
@@ -639,11 +558,15 @@
 		goto exit_get_crash_record;
 
 	/* Get Crash Record. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_cmd));
+
 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
 	mbox_cmd[2] = LSDW(crash_record_dma);
 	mbox_cmd[3] = MSDW(crash_record_dma);
 	mbox_cmd[4] = crash_record_size;
-	if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS)
 		goto exit_get_crash_record;
 
@@ -655,7 +578,6 @@
 				  crash_record, crash_record_dma);
 }
 
-#if 0
 /**
  * qla4xxx_get_conn_event_log - retrieves connection event log
  * @ha: Pointer to host adapter structure.
@@ -678,7 +600,8 @@
 
 	/* Get size of crash record. */
 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
-	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS)
 		goto exit_get_event_log;
 
@@ -693,10 +616,14 @@
 		goto exit_get_event_log;
 
 	/* Get Crash Record. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_cmd));
+
 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
 	mbox_cmd[2] = LSDW(event_log_dma);
 	mbox_cmd[3] = MSDW(event_log_dma);
-	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
 			      "log!\n", ha->host_no, __func__));
@@ -745,7 +672,6 @@
 		dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
 				  event_log_dma);
 }
-#endif  /*  0  */
 
 /**
  * qla4xxx_reset_lun - issues LUN Reset
@@ -773,11 +699,13 @@
 	 */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_LUN_RESET;
 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
 	mbox_cmd[2] = lun << 8;
 	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
-	qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]);
+
+	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
 	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
 		status = QLA_ERROR;
@@ -794,12 +722,14 @@
 
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_READ_FLASH;
 	mbox_cmd[1] = LSDW(dma_addr);
 	mbox_cmd[2] = MSDW(dma_addr);
 	mbox_cmd[3] = offset;
 	mbox_cmd[4] = len;
-	if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
 		    "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
@@ -825,8 +755,10 @@
 	/* Get firmware version. */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
-	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ "
 		    "status %04X\n", ha->host_no, __func__, mbox_sts[0]));
@@ -855,7 +787,7 @@
 	mbox_cmd[2] = LSDW(dma_addr);
 	mbox_cmd[3] = MSDW(dma_addr);
 
-	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
 		     ha->host_no, __func__, mbox_sts[0]));
@@ -875,7 +807,7 @@
 	mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
 	mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
 
-	if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) !=
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
 			*ddb_index = mbox_sts[2];
@@ -918,23 +850,23 @@
 	if (ret_val != QLA_SUCCESS)
 		goto qla4xxx_send_tgts_exit;
 
-	memset((void *)fw_ddb_entry->iSCSIAlias, 0,
-	       sizeof(fw_ddb_entry->iSCSIAlias));
+	memset(fw_ddb_entry->iscsi_alias, 0,
+	       sizeof(fw_ddb_entry->iscsi_alias));
 
-	memset((void *)fw_ddb_entry->iscsiName, 0,
-	       sizeof(fw_ddb_entry->iscsiName));
+	memset(fw_ddb_entry->iscsi_name, 0,
+	       sizeof(fw_ddb_entry->iscsi_name));
 
-	memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr));
-	memset((void *)fw_ddb_entry->targetAddr, 0,
-	       sizeof(fw_ddb_entry->targetAddr));
+	memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
+	memset(fw_ddb_entry->tgt_addr, 0,
+	       sizeof(fw_ddb_entry->tgt_addr));
 
 	fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
-	fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port));
+	fw_ddb_entry->port = cpu_to_le16(ntohs(port));
 
-	fw_ddb_entry->ipAddr[0] = *ip;
-	fw_ddb_entry->ipAddr[1] = *(ip + 1);
-	fw_ddb_entry->ipAddr[2] = *(ip + 2);
-	fw_ddb_entry->ipAddr[3] = *(ip + 3);
+	fw_ddb_entry->ip_addr[0] = *ip;
+	fw_ddb_entry->ip_addr[1] = *(ip + 1);
+	fw_ddb_entry->ip_addr[2] = *(ip + 2);
+	fw_ddb_entry->ip_addr[3] = *(ip + 3);
 
 	ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
 
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
index 58afd13..7fe0482 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.c
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -6,6 +6,9 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha)
 {
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index da21f5f..e69160a 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -10,6 +10,10 @@
 #include <scsi/scsicam.h>
 
 #include "ql4_def.h"
+#include "ql4_version.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 /*
  * Driver version
@@ -50,12 +54,15 @@
 /*
  * iSCSI template entry points
  */
-static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
-			     uint32_t enable, struct sockaddr *dst_addr);
+static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
+			     enum iscsi_tgt_dscvr type, uint32_t enable,
+			     struct sockaddr *dst_addr);
 static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
 				  enum iscsi_param param, char *buf);
 static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
 				  enum iscsi_param param, char *buf);
+static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+				  enum iscsi_host_param param, char *buf);
 static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag);
 static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
 static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
@@ -95,16 +102,20 @@
 static struct iscsi_transport qla4xxx_iscsi_transport = {
 	.owner			= THIS_MODULE,
 	.name			= DRIVER_NAME,
-	.param_mask		= ISCSI_CONN_PORT |
-				  ISCSI_CONN_ADDRESS |
-				  ISCSI_TARGET_NAME |
-				  ISCSI_TPGT,
+	.caps			= CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
+				  CAP_DATA_PATH_OFFLOAD,
+	.param_mask		= ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+				  ISCSI_TARGET_NAME | ISCSI_TPGT,
+	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+				  ISCSI_HOST_IPADDRESS |
+				  ISCSI_HOST_INITIATOR_NAME,
 	.sessiondata_size	= sizeof(struct ddb_entry),
 	.host_template		= &qla4xxx_driver_template,
 
 	.tgt_dscvr		= qla4xxx_tgt_dscvr,
 	.get_conn_param		= qla4xxx_conn_get_param,
 	.get_session_param	= qla4xxx_sess_get_param,
+	.get_host_param		= qla4xxx_host_get_param,
 	.start_conn		= qla4xxx_conn_start,
 	.stop_conn		= qla4xxx_conn_stop,
 	.session_recovery_timedout = qla4xxx_recovery_timedout,
@@ -161,6 +172,43 @@
 		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
 }
 
+static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
+{
+	int i;
+	char *cp = buf;
+
+	for (i = 0; i < len; i++)
+		cp += sprintf(cp, "%02x%c", addr[i],
+			      i == (len - 1) ? '\n' : ':');
+	return cp - buf;
+}
+
+
+static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+				  enum iscsi_host_param param, char *buf)
+{
+	struct scsi_qla_host *ha = to_qla_host(shost);
+	int len;
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_HWADDRESS:
+		len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN);
+		break;
+	case ISCSI_HOST_PARAM_IPADDRESS:
+		len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0],
+			      ha->ip_address[1], ha->ip_address[2],
+			      ha->ip_address[3]);
+		break;
+	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+		len = sprintf(buf, "%s\n", ha->name_string);
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return len;
+}
+
 static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
 				  enum iscsi_param param, char *buf)
 {
@@ -208,21 +256,15 @@
 	return len;
 }
 
-static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
-			     uint32_t enable, struct sockaddr *dst_addr)
+static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
+			     enum iscsi_tgt_dscvr type, uint32_t enable,
+			     struct sockaddr *dst_addr)
 {
 	struct scsi_qla_host *ha;
-	struct Scsi_Host *shost;
 	struct sockaddr_in *addr;
 	struct sockaddr_in6 *addr6;
 	int ret = 0;
 
-	shost = scsi_host_lookup(host_no);
-	if (IS_ERR(shost)) {
-		printk(KERN_ERR "Could not find host no %u\n", host_no);
-		return -ENODEV;
-	}
-
 	ha = (struct scsi_qla_host *) shost->hostdata;
 
 	switch (type) {
@@ -246,8 +288,6 @@
 	default:
 		ret = -ENOSYS;
 	}
-
-	scsi_host_put(shost);
 	return ret;
 }
 
@@ -369,14 +409,7 @@
 	struct scsi_cmnd *cmd = srb->cmd;
 
 	if (srb->flags & SRB_DMA_VALID) {
-		if (cmd->use_sg) {
-			pci_unmap_sg(ha->pdev, cmd->request_buffer,
-				     cmd->use_sg, cmd->sc_data_direction);
-		} else if (cmd->request_bufflen) {
-			pci_unmap_single(ha->pdev, srb->dma_handle,
-					 cmd->request_bufflen,
-					 cmd->sc_data_direction);
-		}
+		scsi_dma_unmap(cmd);
 		srb->flags &= ~SRB_DMA_VALID;
 	}
 	cmd->SCp.ptr = NULL;
@@ -711,7 +744,7 @@
 	return stat;
 }
 
-static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
+void qla4xxx_hw_reset(struct scsi_qla_host *ha)
 {
 	uint32_t ctrl_status;
 	unsigned long flags = 0;
@@ -1081,13 +1114,13 @@
 	if (ha->timer_active)
 		qla4xxx_stop_timer(ha);
 
-	/* free extra memory */
-	qla4xxx_mem_free(ha);
-
 	/* Detach interrupts */
 	if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
 		free_irq(ha->pdev->irq, ha);
 
+	/* free extra memory */
+	qla4xxx_mem_free(ha);
+
 	pci_disable_device(ha->pdev);
 
 }
@@ -1332,6 +1365,11 @@
 
 	ha = pci_get_drvdata(pdev);
 
+	qla4xxx_disable_intrs(ha);
+
+	while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
+		ssleep(1);
+
 	/* remove devs from iscsi_sessions to scsi_devices */
 	qla4xxx_free_ddb_list(ha);
 
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index e5183a69..ab984cb 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,5 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION	"5.00.07-k1"
+#define QLA4XXX_DRIVER_VERSION	"5.01.00-k8"
+
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 2e7db18..2bfbf26 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -265,8 +265,6 @@
 	unsigned int message;	/* scsi returned message */
 	unsigned int phase;	/* recorded scsi phase */
 	unsigned int reqlen;	/* total length of transfer */
-	struct scatterlist *sglist;	/* scatter-gather list pointer */
-	unsigned int sgcount;	/* sg counter */
 	char *buf;
 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
 	int qbase = priv->qbase;
@@ -301,9 +299,10 @@
 	if (inb(qbase + 7) & 0x1f)	/* if some bytes in fifo */
 		outb(1, qbase + 3);	/* clear fifo */
 	/* note that request_bufflen is the total xfer size when sg is used */
-	reqlen = cmd->request_bufflen;
+	reqlen = scsi_bufflen(cmd);
 	/* note that it won't work if transfers > 16M are requested */
 	if (reqlen && !((phase = inb(qbase + 4)) & 6)) {	/* data phase */
+		struct scatterlist *sg;
 		rtrc(2)
 		outb(reqlen, qbase);	/* low-mid xfer cnt */
 		outb(reqlen >> 8, qbase + 1);	/* low-mid xfer cnt */
@@ -311,23 +310,16 @@
 		outb(0x90, qbase + 3);	/* command do xfer */
 		/* PIO pseudo DMA to buffer or sglist */
 		REG1;
-		if (!cmd->use_sg)
-			ql_pdma(priv, phase, cmd->request_buffer,
-				cmd->request_bufflen);
-		else {
-			sgcount = cmd->use_sg;
-			sglist = cmd->request_buffer;
-			while (sgcount--) {
-				if (priv->qabort) {
-					REG0;
-					return ((priv->qabort == 1 ?
-						DID_ABORT : DID_RESET) << 16);
-				}
-				buf = page_address(sglist->page) + sglist->offset;
-				if (ql_pdma(priv, phase, buf, sglist->length))
-					break;
-				sglist++;
+
+		scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
+			if (priv->qabort) {
+				REG0;
+				return ((priv->qabort == 1 ?
+					 DID_ABORT : DID_RESET) << 16);
 			}
+			buf = page_address(sg->page) + sg->offset;
+			if (ql_pdma(priv, phase, buf, sg->length))
+				break;
 		}
 		REG0;
 		rtrc(2)
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 4c1e313..a691dda 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -368,7 +368,7 @@
 			if (level > 3) {
 				printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
 				       " done = 0x%p, queuecommand 0x%p\n",
-					cmd->request_buffer, cmd->request_bufflen,
+					scsi_sglist(cmd), scsi_bufflen(cmd),
 					cmd->done,
 					cmd->device->host->hostt->queuecommand);
 
@@ -1016,52 +1016,6 @@
 }
 EXPORT_SYMBOL(scsi_device_lookup);
 
-/**
- * scsi_device_cancel - cancel outstanding IO to this device
- * @sdev:	Pointer to struct scsi_device
- * @recovery:	Boolean instructing function to recover device or not.
- *
- **/
-int scsi_device_cancel(struct scsi_device *sdev, int recovery)
-{
-	struct scsi_cmnd *scmd;
-	LIST_HEAD(active_list);
-	struct list_head *lh, *lh_sf;
-	unsigned long flags;
-
-	scsi_device_set_state(sdev, SDEV_CANCEL);
-
-	spin_lock_irqsave(&sdev->list_lock, flags);
-	list_for_each_entry(scmd, &sdev->cmd_list, list) {
-		if (scmd->request) {
-			/*
-			 * If we are unable to remove the timer, it means
-			 * that the command has already timed out or
-			 * finished.
-			 */
-			if (!scsi_delete_timer(scmd))
-				continue;
-			list_add_tail(&scmd->eh_entry, &active_list);
-		}
-	}
-	spin_unlock_irqrestore(&sdev->list_lock, flags);
-
-	if (!list_empty(&active_list)) {
-		list_for_each_safe(lh, lh_sf, &active_list) {
-			scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
-			list_del_init(lh);
-			if (recovery &&
-			    !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) {
-				scmd->result = (DID_ABORT << 16);
-				scsi_finish_command(scmd);
-			}
-		}
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(scsi_device_cancel);
-
 MODULE_DESCRIPTION("SCSI core");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 06229f2..4cd9c58 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -2405,7 +2405,7 @@
 MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
 MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
 MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
-MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)");
+MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
 MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
 MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
 MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index ce63044..19c44f0 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -128,6 +128,7 @@
 	{"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN},
 	{"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN},
 	{"BELKIN", "USB 2 HS-CF", "1.95",  BLIST_FORCELUN | BLIST_INQUIRY_36},
+	{"BROWNIE", "1200U3P", NULL, BLIST_NOREPORTLUN},
 	{"BROWNIE", "1600U3P", NULL, BLIST_NOREPORTLUN},
 	{"CANON", "IPUBJD", NULL, BLIST_SPARSELUN},
 	{"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN | BLIST_INQUIRY_36},
@@ -209,6 +210,7 @@
 	{"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+	{"Promise", "", NULL, BLIST_SPARSELUN},
 	{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
 	{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
 	{"SEAGATE", "ST34555N", "0930", BLIST_NOTQ},	/* Chokes on tagged INQUIRY */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index e8350c5..8a525ab 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -18,12 +18,13 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/freezer.h>
 #include <linux/kthread.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/scatterlist.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -640,16 +641,8 @@
 	memcpy(scmd->cmnd, cmnd, cmnd_size);
 
 	if (copy_sense) {
-		gfp_t gfp_mask = GFP_ATOMIC;
-
-		if (shost->hostt->unchecked_isa_dma)
-			gfp_mask |= __GFP_DMA;
-
-		sgl.page = alloc_page(gfp_mask);
-		if (!sgl.page)
-			return FAILED;
-		sgl.offset = 0;
-		sgl.length = 252;
+		sg_init_one(&sgl, scmd->sense_buffer,
+			    sizeof(scmd->sense_buffer));
 
 		scmd->sc_data_direction = DMA_FROM_DEVICE;
 		scmd->request_bufflen = sgl.length;
@@ -720,18 +713,6 @@
 
 
 	/*
-	 * Last chance to have valid sense data.
-	 */
-	if (copy_sense) {
-		if (!SCSI_SENSE_VALID(scmd)) {
-			memcpy(scmd->sense_buffer, page_address(sgl.page),
-			       sizeof(scmd->sense_buffer));
-		}
-		__free_page(sgl.page);
-	}
-
-
-	/*
 	 * Restore original data
 	 */
 	scmd->request_buffer = old_buffer;
@@ -1536,8 +1517,6 @@
 {
 	struct Scsi_Host *shost = data;
 
-	current->flags |= PF_NOFREEZE;
-
 	/*
 	 * We use TASK_INTERRUPTIBLE so that the thread is not
 	 * counted against the load average as a running process.
diff --git a/drivers/scsi/scsi_lib_dma.c b/drivers/scsi/scsi_lib_dma.c
new file mode 100644
index 0000000..ac6855c
--- /dev/null
+++ b/drivers/scsi/scsi_lib_dma.c
@@ -0,0 +1,50 @@
+/*
+ * SCSI library functions depending on DMA
+ */
+
+#include <linux/blkdev.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+/**
+ * scsi_dma_map - perform DMA mapping against command's sg lists
+ * @cmd:	scsi command
+ *
+ * Returns the number of sg lists actually used, zero if the sg lists
+ * is NULL, or -ENOMEM if the mapping failed.
+ */
+int scsi_dma_map(struct scsi_cmnd *cmd)
+{
+	int nseg = 0;
+
+	if (scsi_sg_count(cmd)) {
+		struct device *dev = cmd->device->host->shost_gendev.parent;
+
+		nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
+				  cmd->sc_data_direction);
+		if (unlikely(!nseg))
+			return -ENOMEM;
+	}
+	return nseg;
+}
+EXPORT_SYMBOL(scsi_dma_map);
+
+/**
+ * scsi_dma_unmap - unmap command's sg lists mapped by scsi_dma_map
+ * @cmd:	scsi command
+ */
+void scsi_dma_unmap(struct scsi_cmnd *cmd)
+{
+	if (scsi_sg_count(cmd)) {
+		struct device *dev = cmd->device->host->shost_gendev.parent;
+
+		dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
+			     cmd->sc_data_direction);
+	}
+}
+EXPORT_SYMBOL(scsi_dma_unmap);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index a67f315..a86e62f 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -184,6 +184,15 @@
 /* Only exported for the benefit of scsi_wait_scan */
 EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
 
+#ifndef MODULE
+/*
+ * For async scanning we need to wait for all the scans to complete before
+ * trying to mount the root fs.  Otherwise non-modular drivers may not be ready
+ * yet.
+ */
+late_initcall(scsi_complete_async_scans);
+#endif
+
 /**
  * scsi_unlock_floptical - unlock device via a special MODE SENSE command
  * @sdev:	scsi device to send command to
@@ -694,16 +703,14 @@
 
 /**
  * scsi_add_lun - allocate and fully initialze a scsi_device
- * @sdevscan:	holds information to be stored in the new scsi_device
- * @sdevnew:	store the address of the newly allocated scsi_device
+ * @sdev:	holds information to be stored in the new scsi_device
  * @inq_result:	holds the result of a previous INQUIRY to the LUN
  * @bflags:	black/white list flag
+ * @async:	1 if this device is being scanned asynchronously
  *
  * Description:
- *     Allocate and initialize a scsi_device matching sdevscan. Optionally
- *     set fields based on values in *@bflags. If @sdevnew is not
- *     NULL, store the address of the new scsi_device in *@sdevnew (needed
- *     when scanning a particular LUN).
+ *     Initialize the scsi_device @sdev.  Optionally set fields based
+ *     on values in *@bflags.
  *
  * Return:
  *     SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device
@@ -743,25 +750,15 @@
 	sdev->rev = (char *) (sdev->inquiry + 32);
 
 	if (*bflags & BLIST_ISROM) {
-		/*
-		 * It would be better to modify sdev->type, and set
-		 * sdev->removable; this can now be done since
-		 * print_inquiry has gone away.
-		 */
-		inq_result[0] = TYPE_ROM;
-		inq_result[1] |= 0x80;	/* removable */
-	} else if (*bflags & BLIST_NO_ULD_ATTACH)
-		sdev->no_uld_attach = 1;
+		sdev->type = TYPE_ROM;
+		sdev->removable = 1;
+	} else {
+		sdev->type = (inq_result[0] & 0x1f);
+		sdev->removable = (inq_result[1] & 0x80) >> 7;
+	}
 
-	switch (sdev->type = (inq_result[0] & 0x1f)) {
+	switch (sdev->type) {
 	case TYPE_RBC:
-		/* RBC devices can return SCSI-3 compliance and yet
-		 * still not support REPORT LUNS, so make them act as
-		 * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
-		 * specifically set */
-		if ((*bflags & BLIST_REPORTLUN2) == 0)
-			*bflags |= BLIST_NOREPORTLUN;
-		/* fall through */
 	case TYPE_TAPE:
 	case TYPE_DISK:
 	case TYPE_PRINTER:
@@ -775,13 +772,6 @@
 		sdev->writeable = 1;
 		break;
 	case TYPE_ROM:
-		/* MMC devices can return SCSI-3 compliance and yet
-		 * still not support REPORT LUNS, so make them act as
-		 * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
-		 * specifically set */
-		if ((*bflags & BLIST_REPORTLUN2) == 0)
-			*bflags |= BLIST_NOREPORTLUN;
-		/* fall through */
 	case TYPE_WORM:
 		sdev->writeable = 0;
 		break;
@@ -789,6 +779,15 @@
 		printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type);
 	}
 
+	if (sdev->type == TYPE_RBC || sdev->type == TYPE_ROM) {
+		/* RBC and MMC devices can return SCSI-3 compliance and yet
+		 * still not support REPORT LUNS, so make them act as
+		 * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
+		 * specifically set */
+		if ((*bflags & BLIST_REPORTLUN2) == 0)
+			*bflags |= BLIST_NOREPORTLUN;
+	}
+
 	/*
 	 * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI
 	 * spec says: The device server is capable of supporting the
@@ -806,12 +805,11 @@
 	 */ 
 
 	sdev->inq_periph_qual = (inq_result[0] >> 5) & 7;
-	sdev->removable = (0x80 & inq_result[1]) >> 7;
 	sdev->lockable = sdev->removable;
 	sdev->soft_reset = (inq_result[7] & 1) && ((inq_result[3] & 7) == 2);
 
-	if (sdev->scsi_level >= SCSI_3 || (sdev->inquiry_len > 56 &&
-		inq_result[56] & 0x04))
+	if (sdev->scsi_level >= SCSI_3 ||
+			(sdev->inquiry_len > 56 && inq_result[56] & 0x04))
 		sdev->ppr = 1;
 	if (inq_result[7] & 0x60)
 		sdev->wdtr = 1;
@@ -824,13 +822,10 @@
 			sdev->inq_periph_qual, inq_result[2] & 0x07,
 			(inq_result[3] & 0x0f) == 1 ? " CCS" : "");
 
-	/*
-	 * End sysfs code.
-	 */
-
 	if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) &&
 	    !(*bflags & BLIST_NOTQ))
 		sdev->tagged_supported = 1;
+
 	/*
 	 * Some devices (Texel CD ROM drives) have handshaking problems
 	 * when used with the Seagate controllers. borken is initialized
@@ -839,6 +834,9 @@
 	if ((*bflags & BLIST_BORKEN) == 0)
 		sdev->borken = 0;
 
+	if (*bflags & BLIST_NO_ULD_ATTACH)
+		sdev->no_uld_attach = 1;
+
 	/*
 	 * Apparently some really broken devices (contrary to the SCSI
 	 * standards) need to be selected without asserting ATN
@@ -863,7 +861,6 @@
 	if (*bflags & BLIST_SINGLELUN)
 		sdev->single_lun = 1;
 
-
 	sdev->use_10_for_rw = 1;
 
 	if (*bflags & BLIST_MS_SKIP_PAGE_08)
@@ -1204,7 +1201,7 @@
  *     Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns
  *     the integer: 0x0b030a04
  **/
-static int scsilun_to_int(struct scsi_lun *scsilun)
+int scsilun_to_int(struct scsi_lun *scsilun)
 {
 	int i;
 	unsigned int lun;
@@ -1215,6 +1212,7 @@
 			      scsilun->scsi_lun[i + 1]) << (i * 8));
 	return lun;
 }
+EXPORT_SYMBOL(scsilun_to_int);
 
 /**
  * int_to_scsilun: reverts an int into a scsi_lun
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 67a38a1..ed72086 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -293,30 +293,18 @@
 {
 	struct device_driver *drv = dev->driver;
 	struct scsi_device *sdev = to_scsi_device(dev);
-	struct scsi_host_template *sht = sdev->host->hostt;
 	int err;
 
 	err = scsi_device_quiesce(sdev);
 	if (err)
 		return err;
 
-	/* call HLD suspend first */
 	if (drv && drv->suspend) {
 		err = drv->suspend(dev, state);
 		if (err)
 			return err;
 	}
 
-	/* then, call host suspend */
-	if (sht->suspend) {
-		err = sht->suspend(sdev, state);
-		if (err) {
-			if (drv && drv->resume)
-				drv->resume(dev);
-			return err;
-		}
-	}
-
 	return 0;
 }
 
@@ -324,21 +312,14 @@
 {
 	struct device_driver *drv = dev->driver;
 	struct scsi_device *sdev = to_scsi_device(dev);
-	struct scsi_host_template *sht = sdev->host->hostt;
-	int err = 0, err2 = 0;
+	int err = 0;
 
-	/* call host resume first */
-	if (sht->resume)
-		err = sht->resume(sdev);
-
-	/* then, call HLD resume */
 	if (drv && drv->resume)
-		err2 = drv->resume(dev);
+		err = drv->resume(dev);
 
 	scsi_device_resume(sdev);
 
-	/* favor LLD failure */
-	return err ? err : err2;;
+	return err;
 }
 
 struct bus_type scsi_bus_type = {
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index b4d1ece..e882570 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1,4 +1,4 @@
-/* 
+/*
  *  FiberChannel transport specific attributes exported to sysfs.
  *
  *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
@@ -19,9 +19,10 @@
  *
  *  ========
  *
- *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
+ *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
  *    Rewrite for host, target, device, and remote port attributes,
  *    statistics, and service functions...
+ *    Add vports, etc
  *
  */
 #include <linux/module.h>
@@ -37,6 +38,34 @@
 #include "scsi_priv.h"
 
 static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
+static void fc_vport_sched_delete(struct work_struct *work);
+
+/*
+ * This is a temporary carrier for creating a vport. It will eventually
+ * be replaced  by a real message definition for sgio or netlink.
+ *
+ * fc_vport_identifiers: This set of data contains all elements
+ * to uniquely identify and instantiate a FC virtual port.
+ *
+ * Notes:
+ *   symbolic_name: The driver is to append the symbolic_name string data
+ *      to the symbolic_node_name data that it generates by default.
+ *      the resulting combination should then be registered with the switch.
+ *      It is expected that things like Xen may stuff a VM title into
+ *      this field.
+ */
+struct fc_vport_identifiers {
+	u64 node_name;
+	u64 port_name;
+	u32 roles;
+	bool disable;
+	enum fc_port_type vport_type;	/* only FC_PORTTYPE_NPIV allowed */
+	char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
+};
+
+static int fc_vport_create(struct Scsi_Host *shost, int channel,
+	struct device *pdev, struct fc_vport_identifiers  *ids,
+	struct fc_vport **vport);
 
 /*
  * Redefine so that we can have same named attributes in the
@@ -90,10 +119,14 @@
 	{ FC_PORTTYPE_NLPORT,	"NLPort (fabric via loop)" },
 	{ FC_PORTTYPE_LPORT,	"LPort (private loop)" },
 	{ FC_PORTTYPE_PTP,	"Point-To-Point (direct nport connection" },
+	{ FC_PORTTYPE_NPIV,		"NPIV VPORT" },
 };
 fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
 #define FC_PORTTYPE_MAX_NAMELEN		50
 
+/* Reuse fc_port_type enum function for vport_type */
+#define get_fc_vport_type_name get_fc_port_type_name
+
 
 /* Convert fc_host_event_code values to ascii string name */
 static const struct {
@@ -139,6 +172,29 @@
 #define FC_PORTSTATE_MAX_NAMELEN	20
 
 
+/* Convert fc_vport_state values to ascii string name */
+static struct {
+	enum fc_vport_state	value;
+	char			*name;
+} fc_vport_state_names[] = {
+	{ FC_VPORT_UNKNOWN,		"Unknown" },
+	{ FC_VPORT_ACTIVE,		"Active" },
+	{ FC_VPORT_DISABLED,		"Disabled" },
+	{ FC_VPORT_LINKDOWN,		"Linkdown" },
+	{ FC_VPORT_INITIALIZING,	"Initializing" },
+	{ FC_VPORT_NO_FABRIC_SUPP,	"No Fabric Support" },
+	{ FC_VPORT_NO_FABRIC_RSCS,	"No Fabric Resources" },
+	{ FC_VPORT_FABRIC_LOGOUT,	"Fabric Logout" },
+	{ FC_VPORT_FABRIC_REJ_WWN,	"Fabric Rejected WWN" },
+	{ FC_VPORT_FAILED,		"VPort Failed" },
+};
+fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)
+#define FC_VPORTSTATE_MAX_NAMELEN	24
+
+/* Reuse fc_vport_state enum function for vport_last_state */
+#define get_fc_vport_last_state_name get_fc_vport_state_name
+
+
 /* Convert fc_tgtid_binding_type values to ascii string name */
 static const struct {
 	enum fc_tgtid_binding_type	value;
@@ -219,16 +275,16 @@
 }
 
 
-/* Convert FC_RPORT_ROLE bit values to ascii string name */
+/* Convert FC_PORT_ROLE bit values to ascii string name */
 static const struct {
 	u32 			value;
 	char			*name;
-} fc_remote_port_role_names[] = {
-	{ FC_RPORT_ROLE_FCP_TARGET,	"FCP Target" },
-	{ FC_RPORT_ROLE_FCP_INITIATOR,	"FCP Initiator" },
-	{ FC_RPORT_ROLE_IP_PORT,	"IP Port" },
+} fc_port_role_names[] = {
+	{ FC_PORT_ROLE_FCP_TARGET,	"FCP Target" },
+	{ FC_PORT_ROLE_FCP_INITIATOR,	"FCP Initiator" },
+	{ FC_PORT_ROLE_IP_PORT,		"IP Port" },
 };
-fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
+fc_bitfield_name_search(port_roles, fc_port_role_names)
 
 /*
  * Define roles that are specific to port_id. Values are relative to ROLE_MASK.
@@ -252,7 +308,8 @@
  */
 #define FC_STARGET_NUM_ATTRS 	3
 #define FC_RPORT_NUM_ATTRS	10
-#define FC_HOST_NUM_ATTRS	17
+#define FC_VPORT_NUM_ATTRS	9
+#define FC_HOST_NUM_ATTRS	21
 
 struct fc_internal {
 	struct scsi_transport_template t;
@@ -278,6 +335,10 @@
 	struct transport_container rport_attr_cont;
 	struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
 	struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
+
+	struct transport_container vport_attr_cont;
+	struct class_device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
+	struct class_device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
 };
 
 #define to_fc_internal(tmpl)	container_of(tmpl, struct fc_internal, t)
@@ -318,7 +379,7 @@
 	struct Scsi_Host *shost = dev_to_shost(dev);
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 
-	/* 
+	/*
 	 * Set default values easily detected by the midlayer as
 	 * failure cases.  The scsi lldd is responsible for initializing
 	 * all transport attributes to valid values per host.
@@ -331,6 +392,7 @@
 		sizeof(fc_host->supported_fc4s));
 	fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
 	fc_host->maxframe_size = -1;
+	fc_host->max_npiv_vports = 0;
 	memset(fc_host->serial_number, 0,
 		sizeof(fc_host->serial_number));
 
@@ -348,8 +410,11 @@
 
 	INIT_LIST_HEAD(&fc_host->rports);
 	INIT_LIST_HEAD(&fc_host->rport_bindings);
+	INIT_LIST_HEAD(&fc_host->vports);
 	fc_host->next_rport_number = 0;
 	fc_host->next_target_id = 0;
+	fc_host->next_vport_number = 0;
+	fc_host->npiv_vports_inuse = 0;
 
 	snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
 		shost->host_no);
@@ -388,6 +453,16 @@
 			       NULL);
 
 /*
+ * Setup and Remove actions for virtual ports are handled
+ * in the service functions below.
+ */
+static DECLARE_TRANSPORT_CLASS(fc_vport_class,
+			       "fc_vports",
+			       NULL,
+			       NULL,
+			       NULL);
+
+/*
  * Module Parameters
  */
 
@@ -585,6 +660,9 @@
 	error = transport_class_register(&fc_host_class);
 	if (error)
 		return error;
+	error = transport_class_register(&fc_vport_class);
+	if (error)
+		return error;
 	error = transport_class_register(&fc_rport_class);
 	if (error)
 		return error;
@@ -596,6 +674,7 @@
 	transport_class_unregister(&fc_transport_class);
 	transport_class_unregister(&fc_rport_class);
 	transport_class_unregister(&fc_host_class);
+	transport_class_unregister(&fc_vport_class);
 }
 
 /*
@@ -800,9 +879,9 @@
 			return snprintf(buf, 30, "Unknown Fabric Entity\n");
 		}
 	} else {
-		if (rport->roles == FC_RPORT_ROLE_UNKNOWN)
+		if (rport->roles == FC_PORT_ROLE_UNKNOWN)
 			return snprintf(buf, 20, "unknown\n");
-		return get_fc_remote_port_roles_names(rport->roles, buf);
+		return get_fc_port_roles_names(rport->roles, buf);
 	}
 }
 static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
@@ -857,7 +936,7 @@
 
 /*
  * Note: in the target show function we recognize when the remote
- *  port is in the hierarchy and do not allow the driver to get
+ *  port is in the heirarchy and do not allow the driver to get
  *  involved in sysfs functions. The driver only gets involved if
  *  it's the "old" style that doesn't use rports.
  */
@@ -912,6 +991,257 @@
 
 
 /*
+ * FC Virtual Port Attribute Management
+ */
+
+#define fc_vport_show_function(field, format_string, sz, cast)		\
+static ssize_t								\
+show_fc_vport_##field (struct class_device *cdev, char *buf)		\
+{									\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	struct Scsi_Host *shost = vport_to_shost(vport);		\
+	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+	if ((i->f->get_vport_##field) &&				\
+	    !(vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)))	\
+		i->f->get_vport_##field(vport);				\
+	return snprintf(buf, sz, format_string, cast vport->field); 	\
+}
+
+#define fc_vport_store_function(field)					\
+static ssize_t								\
+store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+			   size_t count)				\
+{									\
+	int val;							\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	struct Scsi_Host *shost = vport_to_shost(vport);		\
+	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+	char *cp;							\
+	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))	\
+		return -EBUSY;						\
+	val = simple_strtoul(buf, &cp, 0);				\
+	if (*cp && (*cp != '\n'))					\
+		return -EINVAL;						\
+	i->f->set_vport_##field(vport, val);				\
+	return count;							\
+}
+
+#define fc_vport_store_str_function(field, slen)			\
+static ssize_t								\
+store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+			   size_t count)				\
+{									\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	struct Scsi_Host *shost = vport_to_shost(vport);		\
+	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+	unsigned int cnt=count;						\
+									\
+	/* count may include a LF at end of string */			\
+	if (buf[cnt-1] == '\n')						\
+		cnt--;							\
+	if (cnt > ((slen) - 1))						\
+		return -EINVAL;						\
+	memcpy(vport->field, buf, cnt);					\
+	i->f->set_vport_##field(vport);					\
+	return count;							\
+}
+
+#define fc_vport_rd_attr(field, format_string, sz)			\
+	fc_vport_show_function(field, format_string, sz, )		\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
+			 show_fc_vport_##field, NULL)
+
+#define fc_vport_rd_attr_cast(field, format_string, sz, cast)		\
+	fc_vport_show_function(field, format_string, sz, (cast))	\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
+			  show_fc_vport_##field, NULL)
+
+#define fc_vport_rw_attr(field, format_string, sz)			\
+	fc_vport_show_function(field, format_string, sz, )		\
+	fc_vport_store_function(field)					\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\
+			show_fc_vport_##field,				\
+			store_fc_vport_##field)
+
+#define fc_private_vport_show_function(field, format_string, sz, cast)	\
+static ssize_t								\
+show_fc_vport_##field (struct class_device *cdev, char *buf)		\
+{									\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	return snprintf(buf, sz, format_string, cast vport->field); 	\
+}
+
+#define fc_private_vport_store_u32_function(field)			\
+static ssize_t								\
+store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+			   size_t count)				\
+{									\
+	u32 val;							\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	char *cp;							\
+	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))		\
+		return -EBUSY;						\
+	val = simple_strtoul(buf, &cp, 0);				\
+	if (*cp && (*cp != '\n'))					\
+		return -EINVAL;						\
+	vport->field = val;						\
+	return count;							\
+}
+
+
+#define fc_private_vport_rd_attr(field, format_string, sz)		\
+	fc_private_vport_show_function(field, format_string, sz, )	\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
+			 show_fc_vport_##field, NULL)
+
+#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast)	\
+	fc_private_vport_show_function(field, format_string, sz, (cast)) \
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
+			  show_fc_vport_##field, NULL)
+
+#define fc_private_vport_rw_u32_attr(field, format_string, sz)		\
+	fc_private_vport_show_function(field, format_string, sz, )	\
+	fc_private_vport_store_u32_function(field)			\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\
+			show_fc_vport_##field,				\
+			store_fc_vport_##field)
+
+
+#define fc_private_vport_rd_enum_attr(title, maxlen)			\
+static ssize_t								\
+show_fc_vport_##title (struct class_device *cdev, char *buf)		\
+{									\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	const char *name;						\
+	name = get_fc_##title##_name(vport->title);			\
+	if (!name)							\
+		return -EINVAL;						\
+	return snprintf(buf, maxlen, "%s\n", name);			\
+}									\
+static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO,			\
+			show_fc_vport_##title, NULL)
+
+
+#define SETUP_VPORT_ATTRIBUTE_RD(field)					\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	i->private_vport_attrs[count].attr.mode = S_IRUGO;		\
+	i->private_vport_attrs[count].store = NULL;			\
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	if (i->f->get_##field)						\
+		count++
+	/* NOTE: Above MACRO differs: checks function not show bit */
+
+#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field)				\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	i->private_vport_attrs[count].attr.mode = S_IRUGO;		\
+	i->private_vport_attrs[count].store = NULL;			\
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	count++
+
+#define SETUP_VPORT_ATTRIBUTE_WR(field)					\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	if (i->f->field)						\
+		count++
+	/* NOTE: Above MACRO differs: checks function */
+
+#define SETUP_VPORT_ATTRIBUTE_RW(field)					\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	if (!i->f->set_vport_##field) {					\
+		i->private_vport_attrs[count].attr.mode = S_IRUGO;	\
+		i->private_vport_attrs[count].store = NULL;		\
+	}								\
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	count++
+	/* NOTE: Above MACRO differs: does not check show bit */
+
+#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field)				\
+{									\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	count++;							\
+}
+
+
+/* The FC Transport Virtual Port Attributes: */
+
+/* Fixed Virtual Port Attributes */
+
+/* Dynamic Virtual Port Attributes */
+
+/* Private Virtual Port Attributes */
+
+fc_private_vport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN);
+fc_private_vport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN);
+fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
+fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+
+static ssize_t
+show_fc_vport_roles (struct class_device *cdev, char *buf)
+{
+	struct fc_vport *vport = transport_class_to_vport(cdev);
+
+	if (vport->roles == FC_PORT_ROLE_UNKNOWN)
+		return snprintf(buf, 20, "unknown\n");
+	return get_fc_port_roles_names(vport->roles, buf);
+}
+static FC_CLASS_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
+
+fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
+
+fc_private_vport_show_function(symbolic_name, "%s\n",
+		FC_VPORT_SYMBOLIC_NAMELEN + 1, )
+fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
+static FC_CLASS_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
+		show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);
+
+static ssize_t
+store_fc_vport_delete(struct class_device *cdev, const char *buf,
+			   size_t count)
+{
+	struct fc_vport *vport = transport_class_to_vport(cdev);
+	struct Scsi_Host *shost = vport_to_shost(vport);
+
+	fc_queue_work(shost, &vport->vport_delete_work);
+	return count;
+}
+static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
+			NULL, store_fc_vport_delete);
+
+
+/*
+ * Enable/Disable vport
+ *  Write "1" to disable, write "0" to enable
+ */
+static ssize_t
+store_fc_vport_disable(struct class_device *cdev, const char *buf,
+			   size_t count)
+{
+	struct fc_vport *vport = transport_class_to_vport(cdev);
+	struct Scsi_Host *shost = vport_to_shost(vport);
+	struct fc_internal *i = to_fc_internal(shost->transportt);
+	int stat;
+
+	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))
+		return -EBUSY;
+
+	if (*buf == '0') {
+		if (vport->vport_state != FC_VPORT_DISABLED)
+			return -EALREADY;
+	} else if (*buf == '1') {
+		if (vport->vport_state == FC_VPORT_DISABLED)
+			return -EALREADY;
+	} else
+		return -EINVAL;
+
+	stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
+	return stat ? stat : count;
+}
+static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+			NULL, store_fc_vport_disable);
+
+
+/*
  * Host Attribute Management
  */
 
@@ -1003,6 +1333,13 @@
 	if (i->f->show_host_##field)					\
 		count++
 
+#define SETUP_HOST_ATTRIBUTE_RD_NS(field)				\
+	i->private_host_attrs[count] = class_device_attr_host_##field;	\
+	i->private_host_attrs[count].attr.mode = S_IRUGO;		\
+	i->private_host_attrs[count].store = NULL;			\
+	i->host_attrs[count] = &i->private_host_attrs[count];		\
+	count++
+
 #define SETUP_HOST_ATTRIBUTE_RW(field)					\
 	i->private_host_attrs[count] = class_device_attr_host_##field;	\
 	if (!i->f->set_host_##field) {					\
@@ -1090,6 +1427,7 @@
 fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
 			     unsigned long long);
 fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
+fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20);
 fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
 
 
@@ -1210,6 +1548,9 @@
 static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
 			store_fc_private_host_issue_lip);
 
+fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+
+
 /*
  * Host Statistics Management
  */
@@ -1285,7 +1626,6 @@
 static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
 				fc_reset_statistics);
 
-
 static struct attribute *fc_statistics_attrs[] = {
 	&class_device_attr_host_seconds_since_last_reset.attr,
 	&class_device_attr_host_tx_frames.attr,
@@ -1316,6 +1656,142 @@
 	.attrs = fc_statistics_attrs,
 };
 
+
+/* Host Vport Attributes */
+
+static int
+fc_parse_wwn(const char *ns, u64 *nm)
+{
+	unsigned int i, j;
+	u8 wwn[8];
+
+	memset(wwn, 0, sizeof(wwn));
+
+	/* Validate and store the new name */
+	for (i=0, j=0; i < 16; i++) {
+		if ((*ns >= 'a') && (*ns <= 'f'))
+			j = ((j << 4) | ((*ns++ -'a') + 10));
+		else if ((*ns >= 'A') && (*ns <= 'F'))
+			j = ((j << 4) | ((*ns++ -'A') + 10));
+		else if ((*ns >= '0') && (*ns <= '9'))
+			j = ((j << 4) | (*ns++ -'0'));
+		else
+			return -EINVAL;
+		if (i % 2) {
+			wwn[i/2] = j & 0xff;
+			j = 0;
+		}
+	}
+
+	*nm = wwn_to_u64(wwn);
+
+	return 0;
+}
+
+
+/*
+ * "Short-cut" sysfs variable to create a new vport on a FC Host.
+ * Input is a string of the form "<WWPN>:<WWNN>". Other attributes
+ * will default to a NPIV-based FCP_Initiator; The WWNs are specified
+ * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
+ */
+static ssize_t
+store_fc_host_vport_create(struct class_device *cdev, const char *buf,
+			   size_t count)
+{
+	struct Scsi_Host *shost = transport_class_to_shost(cdev);
+	struct fc_vport_identifiers vid;
+	struct fc_vport *vport;
+	unsigned int cnt=count;
+	int stat;
+
+	memset(&vid, 0, sizeof(vid));
+
+	/* count may include a LF at end of string */
+	if (buf[cnt-1] == '\n')
+		cnt--;
+
+	/* validate we have enough characters for WWPN */
+	if ((cnt != (16+1+16)) || (buf[16] != ':'))
+		return -EINVAL;
+
+	stat = fc_parse_wwn(&buf[0], &vid.port_name);
+	if (stat)
+		return stat;
+
+	stat = fc_parse_wwn(&buf[17], &vid.node_name);
+	if (stat)
+		return stat;
+
+	vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
+	vid.vport_type = FC_PORTTYPE_NPIV;
+	/* vid.symbolic_name is already zero/NULL's */
+	vid.disable = false;		/* always enabled */
+
+	/* we only allow support on Channel 0 !!! */
+	stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
+	return stat ? stat : count;
+}
+static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
+			store_fc_host_vport_create);
+
+
+/*
+ * "Short-cut" sysfs variable to delete a vport on a FC Host.
+ * Vport is identified by a string containing "<WWPN>:<WWNN>".
+ * The WWNs are specified as hex characters, and may *not* contain
+ * any prefixes (e.g. 0x, x, etc)
+ */
+static ssize_t
+store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
+			   size_t count)
+{
+	struct Scsi_Host *shost = transport_class_to_shost(cdev);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_vport *vport;
+	u64 wwpn, wwnn;
+	unsigned long flags;
+	unsigned int cnt=count;
+	int stat, match;
+
+	/* count may include a LF at end of string */
+	if (buf[cnt-1] == '\n')
+		cnt--;
+
+	/* validate we have enough characters for WWPN */
+	if ((cnt != (16+1+16)) || (buf[16] != ':'))
+		return -EINVAL;
+
+	stat = fc_parse_wwn(&buf[0], &wwpn);
+	if (stat)
+		return stat;
+
+	stat = fc_parse_wwn(&buf[17], &wwnn);
+	if (stat)
+		return stat;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	match = 0;
+	/* we only allow support on Channel 0 !!! */
+	list_for_each_entry(vport, &fc_host->vports, peers) {
+		if ((vport->channel == 0) &&
+		    (vport->port_name == wwpn) && (vport->node_name == wwnn)) {
+			match = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	if (!match)
+		return -ENODEV;
+
+	stat = fc_vport_terminate(vport);
+	return stat ? stat : count;
+}
+static FC_CLASS_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
+			store_fc_host_vport_delete);
+
+
 static int fc_host_match(struct attribute_container *cont,
 			  struct device *dev)
 {
@@ -1387,6 +1863,40 @@
 }
 
 
+static void fc_vport_dev_release(struct device *dev)
+{
+	struct fc_vport *vport = dev_to_vport(dev);
+	put_device(dev->parent);		/* release kobj parent */
+	kfree(vport);
+}
+
+int scsi_is_fc_vport(const struct device *dev)
+{
+	return dev->release == fc_vport_dev_release;
+}
+EXPORT_SYMBOL(scsi_is_fc_vport);
+
+static int fc_vport_match(struct attribute_container *cont,
+			    struct device *dev)
+{
+	struct fc_vport *vport;
+	struct Scsi_Host *shost;
+	struct fc_internal *i;
+
+	if (!scsi_is_fc_vport(dev))
+		return 0;
+	vport = dev_to_vport(dev);
+
+	shost = vport_to_shost(vport);
+	if (!shost->transportt  || shost->transportt->host_attrs.ac.class
+	    != &fc_host_class.class)
+		return 0;
+
+	i = to_fc_internal(shost->transportt);
+	return &i->vport_attr_cont.ac == cont;
+}
+
+
 /**
  * fc_timed_out - FC Transport I/O timeout intercept handler
  *
@@ -1433,6 +1943,9 @@
 		if (rport->scsi_target_id == -1)
 			continue;
 
+		if (rport->port_state != FC_PORTSTATE_ONLINE)
+			continue;
+
 		if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
 		    (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
 			scsi_scan_target(&rport->dev, rport->channel,
@@ -1472,6 +1985,11 @@
 	i->rport_attr_cont.ac.match = fc_rport_match;
 	transport_container_register(&i->rport_attr_cont);
 
+	i->vport_attr_cont.ac.attrs = &i->vport_attrs[0];
+	i->vport_attr_cont.ac.class = &fc_vport_class.class;
+	i->vport_attr_cont.ac.match = fc_vport_match;
+	transport_container_register(&i->vport_attr_cont);
+
 	i->f = ft;
 
 	/* Transport uses the shost workq for scsi scanning */
@@ -1480,7 +1998,7 @@
 	i->t.eh_timed_out = fc_timed_out;
 
 	i->t.user_scan = fc_user_scan;
-	
+
 	/*
 	 * Setup SCSI Target Attributes.
 	 */
@@ -1505,6 +2023,10 @@
 	SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
 	SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
 	SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
+	if (ft->vport_create) {
+		SETUP_HOST_ATTRIBUTE_RD_NS(max_npiv_vports);
+		SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse);
+	}
 	SETUP_HOST_ATTRIBUTE_RD(serial_number);
 
 	SETUP_HOST_ATTRIBUTE_RD(port_id);
@@ -1520,6 +2042,10 @@
 	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
 	if (ft->issue_fc_host_lip)
 		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
+	if (ft->vport_create)
+		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_create);
+	if (ft->vport_delete)
+		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_delete);
 
 	BUG_ON(count > FC_HOST_NUM_ATTRS);
 
@@ -1545,6 +2071,24 @@
 
 	i->rport_attrs[count] = NULL;
 
+	/*
+	 * Setup Virtual Port Attributes.
+	 */
+	count=0;
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_state);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_last_state);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(node_name);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(port_name);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(roles);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_type);
+	SETUP_VPORT_ATTRIBUTE_RW(symbolic_name);
+	SETUP_VPORT_ATTRIBUTE_WR(vport_delete);
+	SETUP_VPORT_ATTRIBUTE_WR(vport_disable);
+
+	BUG_ON(count > FC_VPORT_NUM_ATTRS);
+
+	i->vport_attrs[count] = NULL;
+
 	return &i->t;
 }
 EXPORT_SYMBOL(fc_attach_transport);
@@ -1556,6 +2100,7 @@
 	transport_container_unregister(&i->t.target_attrs);
 	transport_container_unregister(&i->t.host_attrs);
 	transport_container_unregister(&i->rport_attr_cont);
+	transport_container_unregister(&i->vport_attr_cont);
 
 	kfree(i);
 }
@@ -1667,9 +2212,17 @@
 void
 fc_remove_host(struct Scsi_Host *shost)
 {
-	struct fc_rport *rport, *next_rport;
+	struct fc_vport *vport = NULL, *next_vport = NULL;
+	struct fc_rport *rport = NULL, *next_rport = NULL;
 	struct workqueue_struct *work_q;
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+
+	/* Remove any vports */
+	list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers)
+		fc_queue_work(shost, &vport->vport_delete_work);
 
 	/* Remove any remote ports */
 	list_for_each_entry_safe(rport, next_rport,
@@ -1686,6 +2239,8 @@
 		fc_queue_work(shost, &rport->rport_delete_work);
 	}
 
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
 	/* flush all scan work items */
 	scsi_flush_work(shost);
 
@@ -1744,7 +2299,7 @@
 	unsigned long flags;
 
 	/*
-	 * if a scan is pending, flush the SCSI Host work_q so that 
+	 * if a scan is pending, flush the SCSI Host work_q so that
 	 * that we can reclaim the rport scan work element.
 	 */
 	if (rport->flags & FC_RPORT_SCAN_PENDING)
@@ -1844,7 +2399,7 @@
 	spin_lock_irqsave(shost->host_lock, flags);
 
 	rport->number = fc_host->next_rport_number++;
-	if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+	if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
 		rport->scsi_target_id = fc_host->next_target_id++;
 	else
 		rport->scsi_target_id = -1;
@@ -1869,7 +2424,7 @@
 	transport_add_device(dev);
 	transport_configure_device(dev);
 
-	if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
+	if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
 		/* initiate a scan of the target */
 		rport->flags |= FC_RPORT_SCAN_PENDING;
 		scsi_queue_work(shost, &rport->scan_work);
@@ -2003,7 +2558,7 @@
 
 				/* was a target, not in roles */
 				if ((rport->scsi_target_id != -1) &&
-				    (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET)))
+				    (!(ids->roles & FC_PORT_ROLE_FCP_TARGET)))
 					return rport;
 
 				/*
@@ -2086,7 +2641,7 @@
 				memset(rport->dd_data, 0,
 						fci->f->dd_fcrport_size);
 
-			if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
+			if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
 				/* initiate a scan of the target */
 				rport->flags |= FC_RPORT_SCAN_PENDING;
 				scsi_queue_work(shost, &rport->scan_work);
@@ -2243,11 +2798,11 @@
 	int create = 0;
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	if (roles & FC_RPORT_ROLE_FCP_TARGET) {
+	if (roles & FC_PORT_ROLE_FCP_TARGET) {
 		if (rport->scsi_target_id == -1) {
 			rport->scsi_target_id = fc_host->next_target_id++;
 			create = 1;
-		} else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET))
+		} else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))
 			create = 1;
 	}
 
@@ -2294,7 +2849,7 @@
  * fc_timeout_deleted_rport - Timeout handler for a deleted remote port,
  * 			which we blocked, and has now failed to return
  * 			in the allotted time.
- * 
+ *
  * @work:	rport target that failed to reappear in the allotted time.
  **/
 static void
@@ -2317,7 +2872,7 @@
 	 */
 	if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
 	    (rport->scsi_target_id != -1) &&
-	    !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+	    !(rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
 		dev_printk(KERN_ERR, &rport->dev,
 			"blocked FC remote port time out: no longer"
 			" a FCP target, removing starget\n");
@@ -2367,7 +2922,7 @@
 	 */
 	rport->maxframe_size = -1;
 	rport->supported_classes = FC_COS_UNSPECIFIED;
-	rport->roles = FC_RPORT_ROLE_UNKNOWN;
+	rport->roles = FC_PORT_ROLE_UNKNOWN;
 	rport->port_state = FC_PORTSTATE_NOTPRESENT;
 
 	/* remove the identifiers that aren't used in the consisting binding */
@@ -2436,7 +2991,7 @@
 	unsigned long flags;
 
 	if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
-	    (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+	    (rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
 		scsi_scan_target(&rport->dev, rport->channel,
 			rport->scsi_target_id, SCAN_WILD_CARD, 1);
 	}
@@ -2447,7 +3002,227 @@
 }
 
 
-MODULE_AUTHOR("Martin Hicks");
+/**
+ * fc_vport_create - allocates and creates a FC virtual port.
+ * @shost:	scsi host the virtual port is connected to.
+ * @channel:	Channel on shost port connected to.
+ * @pdev:	parent device for vport
+ * @ids:	The world wide names, FC4 port roles, etc for
+ *              the virtual port.
+ * @ret_vport:	The pointer to the created vport.
+ *
+ * Allocates and creates the vport structure, calls the parent host
+ * to instantiate the vport, the completes w/ class and sysfs creation.
+ *
+ * Notes:
+ *	This routine assumes no locks are held on entry.
+ **/
+static int
+fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
+	struct fc_vport_identifiers  *ids, struct fc_vport **ret_vport)
+{
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_internal *fci = to_fc_internal(shost->transportt);
+	struct fc_vport *vport;
+	struct device *dev;
+	unsigned long flags;
+	size_t size;
+	int error;
+
+	*ret_vport = NULL;
+
+	if ( ! fci->f->vport_create)
+		return -ENOENT;
+
+	size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size);
+	vport = kzalloc(size, GFP_KERNEL);
+	if (unlikely(!vport)) {
+		printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	vport->vport_state = FC_VPORT_UNKNOWN;
+	vport->vport_last_state = FC_VPORT_UNKNOWN;
+	vport->node_name = ids->node_name;
+	vport->port_name = ids->port_name;
+	vport->roles = ids->roles;
+	vport->vport_type = ids->vport_type;
+	if (fci->f->dd_fcvport_size)
+		vport->dd_data = &vport[1];
+	vport->shost = shost;
+	vport->channel = channel;
+	vport->flags = FC_VPORT_CREATING;
+	INIT_WORK(&vport->vport_delete_work, fc_vport_sched_delete);
+
+	spin_lock_irqsave(shost->host_lock, flags);
+
+	if (fc_host->npiv_vports_inuse >= fc_host->max_npiv_vports) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		kfree(vport);
+		return -ENOSPC;
+	}
+	fc_host->npiv_vports_inuse++;
+	vport->number = fc_host->next_vport_number++;
+	list_add_tail(&vport->peers, &fc_host->vports);
+	get_device(&shost->shost_gendev);	/* for fc_host->vport list */
+
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	dev = &vport->dev;
+	device_initialize(dev);			/* takes self reference */
+	dev->parent = get_device(pdev);		/* takes parent reference */
+	dev->release = fc_vport_dev_release;
+	sprintf(dev->bus_id, "vport-%d:%d-%d",
+		shost->host_no, channel, vport->number);
+	transport_setup_device(dev);
+
+	error = device_add(dev);
+	if (error) {
+		printk(KERN_ERR "FC Virtual Port device_add failed\n");
+		goto delete_vport;
+	}
+	transport_add_device(dev);
+	transport_configure_device(dev);
+
+	error = fci->f->vport_create(vport, ids->disable);
+	if (error) {
+		printk(KERN_ERR "FC Virtual Port LLDD Create failed\n");
+		goto delete_vport_all;
+	}
+
+	/*
+	 * if the parent isn't the physical adapter's Scsi_Host, ensure
+	 * the Scsi_Host at least contains ia symlink to the vport.
+	 */
+	if (pdev != &shost->shost_gendev) {
+		error = sysfs_create_link(&shost->shost_gendev.kobj,
+				 &dev->kobj, dev->bus_id);
+		if (error)
+			printk(KERN_ERR
+				"%s: Cannot create vport symlinks for "
+				"%s, err=%d\n",
+				__FUNCTION__, dev->bus_id, error);
+	}
+	spin_lock_irqsave(shost->host_lock, flags);
+	vport->flags &= ~FC_VPORT_CREATING;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	dev_printk(KERN_NOTICE, pdev,
+			"%s created via shost%d channel %d\n", dev->bus_id,
+			shost->host_no, channel);
+
+	*ret_vport = vport;
+
+	return 0;
+
+delete_vport_all:
+	transport_remove_device(dev);
+	device_del(dev);
+delete_vport:
+	transport_destroy_device(dev);
+	spin_lock_irqsave(shost->host_lock, flags);
+	list_del(&vport->peers);
+	put_device(&shost->shost_gendev);	/* for fc_host->vport list */
+	fc_host->npiv_vports_inuse--;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	put_device(dev->parent);
+	kfree(vport);
+
+	return error;
+}
+
+
+/**
+ * fc_vport_terminate - Admin App or LLDD requests termination of a vport
+ * @vport:	fc_vport to be terminated
+ *
+ * Calls the LLDD vport_delete() function, then deallocates and removes
+ * the vport from the shost and object tree.
+ *
+ * Notes:
+ *	This routine assumes no locks are held on entry.
+ **/
+int
+fc_vport_terminate(struct fc_vport *vport)
+{
+	struct Scsi_Host *shost = vport_to_shost(vport);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_internal *i = to_fc_internal(shost->transportt);
+	struct device *dev = &vport->dev;
+	unsigned long flags;
+	int stat;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	if (vport->flags & FC_VPORT_CREATING) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		return -EBUSY;
+	}
+	if (vport->flags & (FC_VPORT_DEL)) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		return -EALREADY;
+	}
+	vport->flags |= FC_VPORT_DELETING;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	if (i->f->vport_delete)
+		stat = i->f->vport_delete(vport);
+	else
+		stat = -ENOENT;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	vport->flags &= ~FC_VPORT_DELETING;
+	if (!stat) {
+		vport->flags |= FC_VPORT_DELETED;
+		list_del(&vport->peers);
+		fc_host->npiv_vports_inuse--;
+		put_device(&shost->shost_gendev);  /* for fc_host->vport list */
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	if (stat)
+		return stat;
+
+	if (dev->parent != &shost->shost_gendev)
+		sysfs_remove_link(&shost->shost_gendev.kobj, dev->bus_id);
+	transport_remove_device(dev);
+	device_del(dev);
+	transport_destroy_device(dev);
+
+	/*
+	 * Removing our self-reference should mean our
+	 * release function gets called, which will drop the remaining
+	 * parent reference and free the data structure.
+	 */
+	put_device(dev);			/* for self-reference */
+
+	return 0; /* SUCCESS */
+}
+EXPORT_SYMBOL(fc_vport_terminate);
+
+/**
+ * fc_vport_sched_delete - workq-based delete request for a vport
+ *
+ * @work:	vport to be deleted.
+ **/
+static void
+fc_vport_sched_delete(struct work_struct *work)
+{
+	struct fc_vport *vport =
+		container_of(work, struct fc_vport, vport_delete_work);
+	int stat;
+
+	stat = fc_vport_terminate(vport);
+	if (stat)
+		dev_printk(KERN_ERR, vport->dev.parent,
+			"%s: %s could not be deleted created via "
+			"shost%d channel %d - error %d\n", __FUNCTION__,
+			vport->dev.bus_id, vport->shost->host_no,
+			vport->channel, stat);
+}
+
+
+/* Original Author:  Martin Hicks */
+MODULE_AUTHOR("James Smart");
 MODULE_DESCRIPTION("FC Transport Attributes");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index caf1836..34c1860 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -30,9 +30,9 @@
 #include <scsi/scsi_transport_iscsi.h>
 #include <scsi/iscsi_if.h>
 
-#define ISCSI_SESSION_ATTRS 11
+#define ISCSI_SESSION_ATTRS 15
 #define ISCSI_CONN_ATTRS 11
-#define ISCSI_HOST_ATTRS 0
+#define ISCSI_HOST_ATTRS 4
 #define ISCSI_TRANSPORT_VERSION "2.0-724"
 
 struct iscsi_internal {
@@ -609,12 +609,10 @@
 	int t = done ? NLMSG_DONE : type;
 
 	skb = alloc_skb(len, GFP_ATOMIC);
-	/*
-	 * FIXME:
-	 * user is supposed to react on iferror == -ENOMEM;
-	 * see iscsi_if_rx().
-	 */
-	BUG_ON(!skb);
+	if (!skb) {
+		printk(KERN_ERR "Could not allocate skb to send reply.\n");
+		return -ENOMEM;
+	}
 
 	nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
 	nlh->nlmsg_flags = flags;
@@ -816,6 +814,8 @@
 	uint32_t hostno;
 
 	session = transport->create_session(transport, &priv->t,
+					    ev->u.c_session.cmds_max,
+					    ev->u.c_session.queue_depth,
 					    ev->u.c_session.initial_cmdsn,
 					    &hostno);
 	if (!session)
@@ -947,15 +947,50 @@
 iscsi_tgt_dscvr(struct iscsi_transport *transport,
 		struct iscsi_uevent *ev)
 {
+	struct Scsi_Host *shost;
 	struct sockaddr *dst_addr;
+	int err;
 
 	if (!transport->tgt_dscvr)
 		return -EINVAL;
 
+	shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
+	if (IS_ERR(shost)) {
+		printk(KERN_ERR "target discovery could not find host no %u\n",
+		       ev->u.tgt_dscvr.host_no);
+		return -ENODEV;
+	}
+
+
 	dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
-	return transport->tgt_dscvr(ev->u.tgt_dscvr.type,
-				    ev->u.tgt_dscvr.host_no,
-				    ev->u.tgt_dscvr.enable, dst_addr);
+	err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
+				   ev->u.tgt_dscvr.enable, dst_addr);
+	scsi_host_put(shost);
+	return err;
+}
+
+static int
+iscsi_set_host_param(struct iscsi_transport *transport,
+		     struct iscsi_uevent *ev)
+{
+	char *data = (char*)ev + sizeof(*ev);
+	struct Scsi_Host *shost;
+	int err;
+
+	if (!transport->set_host_param)
+		return -ENOSYS;
+
+	shost = scsi_host_lookup(ev->u.set_host_param.host_no);
+	if (IS_ERR(shost)) {
+		printk(KERN_ERR "set_host_param could not find host no %u\n",
+		       ev->u.set_host_param.host_no);
+		return -ENODEV;
+	}
+
+	err = transport->set_host_param(shost, ev->u.set_host_param.param,
+					data, ev->u.set_host_param.len);
+	scsi_host_put(shost);
+	return err;
 }
 
 static int
@@ -1049,8 +1084,11 @@
 	case ISCSI_UEVENT_TGT_DSCVR:
 		err = iscsi_tgt_dscvr(transport, ev);
 		break;
+	case ISCSI_UEVENT_SET_HOST_PARAM:
+		err = iscsi_set_host_param(transport, ev);
+		break;
 	default:
-		err = -EINVAL;
+		err = -ENOSYS;
 		break;
 	}
 
@@ -1160,30 +1198,37 @@
 /*
  * iSCSI session attrs
  */
-#define iscsi_session_attr_show(param)					\
+#define iscsi_session_attr_show(param, perm)				\
 static ssize_t								\
 show_session_param_##param(struct class_device *cdev, char *buf)	\
 {									\
 	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
 	struct iscsi_transport *t = session->transport;			\
+									\
+	if (perm && !capable(CAP_SYS_ADMIN))				\
+		return -EACCES;						\
 	return t->get_session_param(session, param, buf);		\
 }
 
-#define iscsi_session_attr(field, param)				\
-	iscsi_session_attr_show(param)					\
+#define iscsi_session_attr(field, param, perm)				\
+	iscsi_session_attr_show(param, perm)				\
 static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
 			NULL);
 
-iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME);
-iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
-iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
-iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
-iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST);
-iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST);
-iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
-iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN);
-iscsi_session_attr(erl, ISCSI_PARAM_ERL);
-iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT);
+iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
+iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
+iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
+iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
+iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
+iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
+iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
+iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
+iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
+iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
+iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
+iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
+iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
+iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
 
 #define iscsi_priv_session_attr_show(field, format)			\
 static ssize_t								\
@@ -1199,6 +1244,28 @@
 			NULL)
 iscsi_priv_session_attr(recovery_tmo, "%d");
 
+/*
+ * iSCSI host attrs
+ */
+#define iscsi_host_attr_show(param)					\
+static ssize_t								\
+show_host_param_##param(struct class_device *cdev, char *buf)		\
+{									\
+	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
+	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
+	return priv->iscsi_transport->get_host_param(shost, param, buf); \
+}
+
+#define iscsi_host_attr(field, param)					\
+	iscsi_host_attr_show(param)					\
+static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,	\
+			NULL);
+
+iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
+iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
+iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
+iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+
 #define SETUP_PRIV_SESSION_RD_ATTR(field)				\
 do {									\
 	priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
@@ -1222,6 +1289,14 @@
 	}								\
 } while (0)
 
+#define SETUP_HOST_RD_ATTR(field, param_flag)				\
+do {									\
+	if (tt->host_param_mask & param_flag) {				\
+		priv->host_attrs[count] = &class_device_attr_host_##field; \
+		count++;						\
+	}								\
+} while (0)
+
 static int iscsi_session_match(struct attribute_container *cont,
 			   struct device *dev)
 {
@@ -1323,9 +1398,16 @@
 	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
 	priv->t.host_attrs.ac.match = iscsi_host_match;
 	priv->t.host_size = sizeof(struct iscsi_host);
-	priv->host_attrs[0] = NULL;
 	transport_container_register(&priv->t.host_attrs);
 
+	SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
+	SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
+	SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
+	SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
+	BUG_ON(count > ISCSI_HOST_ATTRS);
+	priv->host_attrs[count] = NULL;
+	count = 0;
+
 	/* connection parameters */
 	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
 	priv->conn_cont.ac.class = &iscsi_connection_class.class;
@@ -1364,6 +1446,10 @@
 	SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
 	SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
 	SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
+	SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
+	SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
+	SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
+	SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
 
 	BUG_ON(count > ISCSI_SESSION_ATTRS);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 00e4666..424d557 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -684,7 +684,7 @@
 		case SCSI_IOCTL_GET_BUS_NUMBER:
 			return scsi_ioctl(sdp, cmd, p);
 		default:
-			error = scsi_cmd_ioctl(filp, disk, cmd, p);
+			error = scsi_cmd_ioctl(filp, disk->queue, disk, cmd, p);
 			if (error != -ENOTTY)
 				return error;
 	}
@@ -1515,7 +1515,7 @@
 	if (!scsi_device_online(sdp))
 		goto out;
 
-	buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA);
+	buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL);
 	if (!buffer) {
 		sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory "
 			  "allocation failure.\n");
@@ -1789,7 +1789,7 @@
 static int sd_suspend(struct device *dev, pm_message_t mesg)
 {
 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
-	int ret;
+	int ret = 0;
 
 	if (!sdkp)
 		return 0;	/* this can happen */
@@ -1798,30 +1798,34 @@
 		sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
 		ret = sd_sync_cache(sdkp);
 		if (ret)
-			return ret;
+			goto done;
 	}
 
 	if (mesg.event == PM_EVENT_SUSPEND &&
 	    sdkp->device->manage_start_stop) {
 		sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
 		ret = sd_start_stop_device(sdkp, 0);
-		if (ret)
-			return ret;
 	}
 
-	return 0;
+done:
+	scsi_disk_put(sdkp);
+	return ret;
 }
 
 static int sd_resume(struct device *dev)
 {
 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+	int ret = 0;
 
 	if (!sdkp->device->manage_start_stop)
-		return 0;
+		goto done;
 
 	sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+	ret = sd_start_stop_device(sdkp, 1);
 
-	return sd_start_stop_device(sdkp, 1);
+done:
+	scsi_disk_put(sdkp);
+	return ret;
 }
 
 /**
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 0c691a6..85d3894 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1842,7 +1842,7 @@
 	int blk_size = buff_size;
 	struct page *p = NULL;
 
-	if ((blk_size < 0) || (!sfp))
+	if (blk_size < 0)
 		return -EFAULT;
 	if (0 == blk_size)
 		++blk_size;	/* don't know why */
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
index a7dfb65..0a6b45b 100644
--- a/drivers/scsi/sni_53c710.c
+++ b/drivers/scsi/sni_53c710.c
@@ -84,7 +84,7 @@
 
 	hostdata->dev = &dev->dev;
 	dma_set_mask(&dev->dev, DMA_32BIT_MASK);
-	hostdata->base = ioremap_nocache(CPHYSADDR(base), 0x100);
+	hostdata->base = ioremap_nocache(base, 0x100);
 	hostdata->differential = 0;
 
 	hostdata->clock = SNIRM710_CLOCK;
@@ -141,13 +141,7 @@
 
 static int __init snirm710_init(void)
 {
-	int err;
-
-	if ((err = platform_driver_register(&snirm710_driver))) {
-		printk(KERN_ERR "Driver registration failed\n");
-		return err;
-	}
-	return 0;
+	return platform_driver_register(&snirm710_driver);
 }
 
 static void __exit snirm710_exit(void)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index f9a52af..5143c89 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -885,7 +885,11 @@
 	rc = register_blkdev(SCSI_CDROM_MAJOR, "sr");
 	if (rc)
 		return rc;
-	return scsi_register_driver(&sr_template.gendrv);
+	rc = scsi_register_driver(&sr_template.gendrv);
+	if (rc)
+		unregister_blkdev(SCSI_CDROM_MAJOR, "sr");
+
+	return rc;
 }
 
 static void __exit exit_sr(void)
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 55bfecc..a4f7b84 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3549,7 +3549,8 @@
 			    !capable(CAP_SYS_RAWIO))
 				i = -EPERM;
 			else
-				i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
+				i = scsi_cmd_ioctl(file, STp->disk->queue,
+						   STp->disk, cmd_in, p);
 			if (i != -ENOTTY)
 				return i;
 			break;
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 69be132..72f6d80 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -32,11 +32,12 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
 
 #define DRV_NAME "stex"
-#define ST_DRIVER_VERSION "3.1.0.1"
+#define ST_DRIVER_VERSION "3.6.0000.1"
 #define ST_VER_MAJOR 		3
-#define ST_VER_MINOR 		1
+#define ST_VER_MINOR 		6
 #define ST_OEM 			0
 #define ST_BUILD_VER 		1
 
@@ -113,10 +114,6 @@
 	SG_CF_64B				= 0x40,	/* 64 bit item */
 	SG_CF_HOST				= 0x20,	/* sg in host memory */
 
-	ST_MAX_ARRAY_SUPPORTED			= 16,
-	ST_MAX_TARGET_NUM			= (ST_MAX_ARRAY_SUPPORTED+1),
-	ST_MAX_LUN_PER_TARGET			= 16,
-
 	st_shasta				= 0,
 	st_vsc					= 1,
 	st_vsc1					= 2,
@@ -398,53 +395,34 @@
 static int stex_map_sg(struct st_hba *hba,
 	struct req_msg *req, struct st_ccb *ccb)
 {
-	struct pci_dev *pdev = hba->pdev;
 	struct scsi_cmnd *cmd;
-	dma_addr_t dma_handle;
-	struct scatterlist *src;
+	struct scatterlist *sg;
 	struct st_sgtable *dst;
-	int i;
+	int i, nseg;
 
 	cmd = ccb->cmd;
 	dst = (struct st_sgtable *)req->variable;
 	dst->max_sg_count = cpu_to_le16(ST_MAX_SG);
-	dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen);
+	dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd));
 
-	if (cmd->use_sg) {
-		int n_elem;
+	nseg = scsi_dma_map(cmd);
+	if (nseg < 0)
+		return -EIO;
+	if (nseg) {
+		ccb->sg_count = nseg;
+		dst->sg_count = cpu_to_le16((u16)nseg);
 
-		src = (struct scatterlist *) cmd->request_buffer;
-		n_elem = pci_map_sg(pdev, src,
-			cmd->use_sg, cmd->sc_data_direction);
-		if (n_elem <= 0)
-			return -EIO;
-
-		ccb->sg_count = n_elem;
-		dst->sg_count = cpu_to_le16((u16)n_elem);
-
-		for (i = 0; i < n_elem; i++, src++) {
-			dst->table[i].count = cpu_to_le32((u32)sg_dma_len(src));
+		scsi_for_each_sg(cmd, sg, nseg, i) {
+			dst->table[i].count = cpu_to_le32((u32)sg_dma_len(sg));
 			dst->table[i].addr =
-				cpu_to_le32(sg_dma_address(src) & 0xffffffff);
+				cpu_to_le32(sg_dma_address(sg) & 0xffffffff);
 			dst->table[i].addr_hi =
-				cpu_to_le32((sg_dma_address(src) >> 16) >> 16);
+				cpu_to_le32((sg_dma_address(sg) >> 16) >> 16);
 			dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST;
 		}
 		dst->table[--i].ctrl |= SG_CF_EOT;
-		return 0;
 	}
 
-	dma_handle = pci_map_single(pdev, cmd->request_buffer,
-		cmd->request_bufflen, cmd->sc_data_direction);
-	cmd->SCp.dma_handle = dma_handle;
-
-	ccb->sg_count = 1;
-	dst->sg_count = cpu_to_le16(1);
-	dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff);
-	dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16);
-	dst->table[0].count = cpu_to_le32((u32)cmd->request_bufflen);
-	dst->table[0].ctrl = SG_CF_EOT | SG_CF_64B | SG_CF_HOST;
-
 	return 0;
 }
 
@@ -454,24 +432,24 @@
 	size_t lcount;
 	size_t len;
 	void *s, *d, *base = NULL;
-	if (*count > cmd->request_bufflen)
-		*count = cmd->request_bufflen;
+	size_t offset;
+
+	if (*count > scsi_bufflen(cmd))
+		*count = scsi_bufflen(cmd);
 	lcount = *count;
 	while (lcount) {
 		len = lcount;
 		s = (void *)src;
-		if (cmd->use_sg) {
-			size_t offset = *count - lcount;
-			s += offset;
-			base = scsi_kmap_atomic_sg(cmd->request_buffer,
-				sg_count, &offset, &len);
-			if (base == NULL) {
-				*count -= lcount;
-				return;
-			}
-			d = base + offset;
-		} else
-			d = cmd->request_buffer;
+
+		offset = *count - lcount;
+		s += offset;
+		base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
+					   sg_count, &offset, &len);
+		if (!base) {
+			*count -= lcount;
+			return;
+		}
+		d = base + offset;
 
 		if (direction == ST_TO_CMD)
 			memcpy(d, s, len);
@@ -479,30 +457,24 @@
 			memcpy(s, d, len);
 
 		lcount -= len;
-		if (cmd->use_sg)
-			scsi_kunmap_atomic_sg(base);
+		scsi_kunmap_atomic_sg(base);
 	}
 }
 
 static int stex_direct_copy(struct scsi_cmnd *cmd,
 	const void *src, size_t count)
 {
-	struct st_hba *hba = (struct st_hba *) &cmd->device->host->hostdata[0];
 	size_t cp_len = count;
 	int n_elem = 0;
 
-	if (cmd->use_sg) {
-		n_elem = pci_map_sg(hba->pdev, cmd->request_buffer,
-			cmd->use_sg, cmd->sc_data_direction);
-		if (n_elem <= 0)
-			return 0;
-	}
+	n_elem = scsi_dma_map(cmd);
+	if (n_elem < 0)
+		return 0;
 
 	stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
 
-	if (cmd->use_sg)
-		pci_unmap_sg(hba->pdev, cmd->request_buffer,
-			cmd->use_sg, cmd->sc_data_direction);
+	scsi_dma_unmap(cmd);
+
 	return cp_len == count;
 }
 
@@ -586,7 +558,7 @@
 	u16 tag;
 	host = cmd->device->host;
 	id = cmd->device->id;
-	lun = cmd->device->channel; /* firmware lun issue work around */
+	lun = cmd->device->lun;
 	hba = (struct st_hba *) &host->hostdata[0];
 
 	switch (cmd->cmnd[0]) {
@@ -605,8 +577,26 @@
 			stex_invalid_field(cmd, done);
 		return 0;
 	}
+	case REPORT_LUNS:
+		/*
+		 * The shasta firmware does not report actual luns in the
+		 * target, so fail the command to force sequential lun scan.
+		 * Also, the console device does not support this command.
+		 */
+		if (hba->cardtype == st_shasta || id == host->max_id - 1) {
+			stex_invalid_field(cmd, done);
+			return 0;
+		}
+		break;
+	case TEST_UNIT_READY:
+		if (id == host->max_id - 1) {
+			cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+			done(cmd);
+			return 0;
+		}
+		break;
 	case INQUIRY:
-		if (id != ST_MAX_ARRAY_SUPPORTED)
+		if (id != host->max_id - 1)
 			break;
 		if (lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
 			stex_direct_copy(cmd, console_inq_page,
@@ -624,7 +614,7 @@
 			ver.oem = ST_OEM;
 			ver.build = ST_BUILD_VER;
 			ver.signature[0] = PASSTHRU_SIGNATURE;
-			ver.console_id = ST_MAX_ARRAY_SUPPORTED;
+			ver.console_id = host->max_id - 1;
 			ver.host_no = hba->host->host_no;
 			cmd->result = stex_direct_copy(cmd, &ver, sizeof(ver)) ?
 				DID_OK << 16 | COMMAND_COMPLETE << 8 :
@@ -645,13 +635,8 @@
 
 	req = stex_alloc_req(hba);
 
-	if (hba->cardtype == st_yosemite) {
-		req->lun = lun * (ST_MAX_TARGET_NUM - 1) + id;
-		req->target = 0;
-	} else {
-		req->lun = lun;
-		req->target = id;
-	}
+	req->lun = lun;
+	req->target = id;
 
 	/* cdb */
 	memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH);
@@ -668,18 +653,6 @@
 	return 0;
 }
 
-static void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd)
-{
-	if (cmd->sc_data_direction != DMA_NONE) {
-		if (cmd->use_sg)
-			pci_unmap_sg(hba->pdev, cmd->request_buffer,
-				cmd->use_sg, cmd->sc_data_direction);
-		else
-			pci_unmap_single(hba->pdev, cmd->SCp.dma_handle,
-				cmd->request_bufflen, cmd->sc_data_direction);
-	}
-}
-
 static void stex_scsi_done(struct st_ccb *ccb)
 {
 	struct scsi_cmnd *cmd = ccb->cmd;
@@ -746,8 +719,8 @@
 
 	if (ccb->cmd->cmnd[0] == MGT_CMD &&
 		resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
-		ccb->cmd->request_bufflen =
-			le32_to_cpu(*(__le32 *)&resp->variable[0]);
+		scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) -
+			le32_to_cpu(*(__le32 *)&resp->variable[0]));
 		return;
 	}
 
@@ -767,18 +740,6 @@
 			ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
 		else
 			ccb->srb_status = SRB_STATUS_SUCCESS;
-	} else if (ccb->cmd->cmnd[0] == REPORT_LUNS) {
-		u8 *report_lun_data = (u8 *)hba->copy_buffer;
-
-		count = STEX_EXTRA_SIZE;
-		stex_internal_copy(ccb->cmd, report_lun_data,
-			&count, ccb->sg_count, ST_FROM_CMD);
-		if (report_lun_data[2] || report_lun_data[3]) {
-			report_lun_data[2] = 0x00;
-			report_lun_data[3] = 0x08;
-			stex_internal_copy(ccb->cmd, report_lun_data,
-				&count, ccb->sg_count, ST_TO_CMD);
-		}
 	}
 }
 
@@ -857,7 +818,7 @@
 				ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER))
 				stex_controller_info(hba, ccb);
 
-			stex_unmap_sg(hba, ccb->cmd);
+			scsi_dma_unmap(ccb->cmd);
 			stex_scsi_done(ccb);
 			hba->out_req_cnt--;
 		} else if (ccb->req_type & PASSTHRU_REQ_TYPE) {
@@ -995,6 +956,11 @@
 	u32 data;
 	int result = SUCCESS;
 	unsigned long flags;
+
+	printk(KERN_INFO DRV_NAME
+		"(%s): aborting command\n", pci_name(hba->pdev));
+	scsi_print_command(cmd);
+
 	base = hba->mmio_base;
 	spin_lock_irqsave(host->host_lock, flags);
 	if (tag < host->can_queue && hba->ccb[tag].cmd == cmd)
@@ -1025,7 +991,7 @@
 	}
 
 fail_out:
-	stex_unmap_sg(hba, cmd);
+	scsi_dma_unmap(cmd);
 	hba->wait_ccb->req = NULL; /* nullify the req's future return */
 	hba->wait_ccb = NULL;
 	result = FAILED;
@@ -1051,7 +1017,12 @@
 	pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &pci_bctl);
 	pci_bctl |= PCI_BRIDGE_CTL_BUS_RESET;
 	pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
-	msleep(1);
+
+	/*
+	 * 1 ms may be enough for 8-port controllers. But 16-port controllers
+	 * require more time to finish bus reset. Use 100 ms here for safety
+	 */
+	msleep(100);
 	pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
 	pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
 
@@ -1075,6 +1046,10 @@
 	unsigned long before;
 	hba = (struct st_hba *) &cmd->device->host->hostdata[0];
 
+	printk(KERN_INFO DRV_NAME
+		"(%s): resetting host\n", pci_name(hba->pdev));
+	scsi_print_command(cmd);
+
 	hba->mu_status = MU_STATE_RESETTING;
 
 	if (hba->cardtype == st_shasta)
@@ -1194,7 +1169,7 @@
 		goto out_scsi_host_put;
 	}
 
-	hba->mmio_base = ioremap(pci_resource_start(pdev, 0),
+	hba->mmio_base = ioremap_nocache(pci_resource_start(pdev, 0),
 		pci_resource_len(pdev, 0));
 	if ( !hba->mmio_base) {
 		printk(KERN_ERR DRV_NAME "(%s): memory map failed\n",
@@ -1229,12 +1204,18 @@
 	hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE;
 	hba->mu_status = MU_STATE_STARTING;
 
-	/* firmware uses id/lun pair for a logical drive, but lun would be
-	   always 0 if CONFIG_SCSI_MULTI_LUN not configured, so we use
-	   channel to map lun here */
-	host->max_channel = ST_MAX_LUN_PER_TARGET - 1;
-	host->max_id = ST_MAX_TARGET_NUM;
-	host->max_lun = 1;
+	if (hba->cardtype == st_shasta) {
+		host->max_lun = 8;
+		host->max_id = 16 + 1;
+	} else if (hba->cardtype == st_yosemite) {
+		host->max_lun = 128;
+		host->max_id = 1 + 1;
+	} else {
+		/* st_vsc and st_vsc1 */
+		host->max_lun = 1;
+		host->max_id = 128 + 1;
+	}
+	host->max_channel = 0;
 	host->unique_id = host->host_no;
 	host->max_cmd_len = STEX_CDB_LENGTH;
 
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c
index bbeb245..2c87db9 100644
--- a/drivers/scsi/sun_esp.c
+++ b/drivers/scsi/sun_esp.c
@@ -493,7 +493,7 @@
 		goto fail;
 
 	host->max_id = (hme ? 16 : 8);
-	esp = host_to_esp(host);
+	esp = shost_priv(host);
 
 	esp->host = host;
 	esp->dev = esp_dev;
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index 2ca9505..92bfaea 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -332,8 +332,7 @@
 	int i;
 	unsigned long flags = 0;
 	unsigned char status_reg, pio_int_reg, int_reg;
-	struct scatterlist *sglist;
-	unsigned int sgcount;
+	struct scatterlist *sg;
 	unsigned int tot_trans = 0;
 
 	/* We search the base address of the host adapter which caused the interrupt */
@@ -429,19 +428,15 @@
 			{
 				current_command->SCp.phase = data_out;
 				outb(FLUSH_FIFO, base + COMMAND_REG);
-				sym53c416_set_transfer_counter(base, current_command->request_bufflen);
+				sym53c416_set_transfer_counter(base,
+							       scsi_bufflen(current_command));
 				outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
-				if(!current_command->use_sg)
-					tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen);
-				else
-				{
-					sgcount = current_command->use_sg;
-					sglist = current_command->request_buffer;
-					while(sgcount--)
-					{
-						tot_trans += sym53c416_write(base, SG_ADDRESS(sglist), sglist->length);
-						sglist++;
-					}
+
+				scsi_for_each_sg(current_command,
+						 sg, scsi_sg_count(current_command), i) {
+					tot_trans += sym53c416_write(base,
+								     SG_ADDRESS(sg),
+								     sg->length);
 				}
 				if(tot_trans < current_command->underflow)
 					printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
@@ -455,19 +450,16 @@
 			{
 				current_command->SCp.phase = data_in;
 				outb(FLUSH_FIFO, base + COMMAND_REG);
-				sym53c416_set_transfer_counter(base, current_command->request_bufflen);
+				sym53c416_set_transfer_counter(base,
+							       scsi_bufflen(current_command));
+
 				outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
-				if(!current_command->use_sg)
-					tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen);
-				else
-				{
-					sgcount = current_command->use_sg;
-					sglist = current_command->request_buffer;
-					while(sgcount--)
-					{
-						tot_trans += sym53c416_read(base, SG_ADDRESS(sglist), sglist->length);
-						sglist++;
-					}
+
+				scsi_for_each_sg(current_command,
+						 sg, scsi_sg_count(current_command), i) {
+					tot_trans += sym53c416_read(base,
+								    SG_ADDRESS(sg),
+								    sg->length);
 				}
 				if(tot_trans < current_command->underflow)
 					printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 4d78c7e..15a5145 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -146,41 +146,17 @@
 
 static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
 {
-	int dma_dir = cmd->sc_data_direction;
+	if (SYM_UCMD_PTR(cmd)->data_mapped)
+		scsi_dma_unmap(cmd);
 
-	switch(SYM_UCMD_PTR(cmd)->data_mapped) {
-	case 2:
-		pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir);
-		break;
-	case 1:
-		pci_unmap_single(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
-				 cmd->request_bufflen, dma_dir);
-		break;
-	}
 	SYM_UCMD_PTR(cmd)->data_mapped = 0;
 }
 
-static dma_addr_t __map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-	dma_addr_t mapping;
-	int dma_dir = cmd->sc_data_direction;
-
-	mapping = pci_map_single(pdev, cmd->request_buffer,
-				 cmd->request_bufflen, dma_dir);
-	if (mapping) {
-		SYM_UCMD_PTR(cmd)->data_mapped  = 1;
-		SYM_UCMD_PTR(cmd)->data_mapping = mapping;
-	}
-
-	return mapping;
-}
-
 static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
 {
 	int use_sg;
-	int dma_dir = cmd->sc_data_direction;
 
-	use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir);
+	use_sg = scsi_dma_map(cmd);
 	if (use_sg > 0) {
 		SYM_UCMD_PTR(cmd)->data_mapped  = 2;
 		SYM_UCMD_PTR(cmd)->data_mapping = use_sg;
@@ -191,8 +167,6 @@
 
 #define unmap_scsi_data(np, cmd)	\
 		__unmap_scsi_data(np->s.device, cmd)
-#define map_scsi_single_data(np, cmd)	\
-		__map_scsi_single_data(np->s.device, cmd)
 #define map_scsi_sg_data(np, cmd)	\
 		__map_scsi_sg_data(np->s.device, cmd)
 /*
@@ -322,55 +296,20 @@
 		 */
 		cam_status = sym_xerr_cam_status(DID_ERROR, cp->xerr_status);
 	}
-	cmd->resid = resid;
+	scsi_set_resid(cmd, resid);
 	cmd->result = (drv_status << 24) + (cam_status << 16) + scsi_status;
 }
 
-
-/*
- *  Build the scatter/gather array for an I/O.
- */
-
-static int sym_scatter_no_sglist(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd *cmd)
-{
-	struct sym_tblmove *data = &cp->phys.data[SYM_CONF_MAX_SG-1];
-	int segment;
-	unsigned int len = cmd->request_bufflen;
-
-	if (len) {
-		dma_addr_t baddr = map_scsi_single_data(np, cmd);
-		if (baddr) {
-			if (len & 1) {
-				struct sym_tcb *tp = &np->target[cp->target];
-				if (tp->head.wval & EWS) {
-					len++;
-					cp->odd_byte_adjustment++;
-				}
-			}
-			cp->data_len = len;
-			sym_build_sge(np, data, baddr, len);
-			segment = 1;
-		} else {
-			segment = -2;
-		}
-	} else {
-		segment = 0;
-	}
-
-	return segment;
-}
-
 static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd *cmd)
 {
 	int segment;
-	int use_sg = (int) cmd->use_sg;
+	int use_sg;
 
 	cp->data_len = 0;
 
-	if (!use_sg)
-		segment = sym_scatter_no_sglist(np, cp, cmd);
-	else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) {
-		struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer;
+	use_sg = map_scsi_sg_data(np, cmd);
+	if (use_sg > 0) {
+		struct scatterlist *sg;
 		struct sym_tcb *tp = &np->target[cp->target];
 		struct sym_tblmove *data;
 
@@ -381,9 +320,9 @@
 
 		data = &cp->phys.data[SYM_CONF_MAX_SG - use_sg];
 
-		for (segment = 0; segment < use_sg; segment++) {
-			dma_addr_t baddr = sg_dma_address(&scatter[segment]);
-			unsigned int len = sg_dma_len(&scatter[segment]);
+		scsi_for_each_sg(cmd, sg, use_sg, segment) {
+			dma_addr_t baddr = sg_dma_address(sg);
+			unsigned int len = sg_dma_len(sg);
 
 			if ((len & 1) && (tp->head.wval & EWS)) {
 				len++;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index e022d3c..0f097ba 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -255,7 +255,7 @@
  */
 static __inline void sym_set_cam_result_ok(struct sym_ccb *cp, struct scsi_cmnd *cmd, int resid)
 {
-	cmd->resid = resid;
+	scsi_set_resid(cmd, resid);
 	cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
 }
 void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid);
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index e7b85e8..14cba1c 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -457,28 +457,21 @@
 			error = 1;
 		DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle));
 	/* Map SG list */
-	} else if (pcmd->use_sg) {
-		pSRB->pSegmentList	= (struct scatterlist *) pcmd->request_buffer;
-		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, pcmd->use_sg,
-						     pcmd->sc_data_direction);
-		/* TODO: error handling */
-		if (!pSRB->SGcount)
-			error = 1;
-		DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
-			      __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg));
-	/* Map single segment */
-	} else if (pcmd->request_buffer && pcmd->request_bufflen) {
-		pSRB->pSegmentList	= dc390_sg_build_single(&pSRB->Segmentx, pcmd->request_buffer, pcmd->request_bufflen);
-		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, 1,
-						     pcmd->sc_data_direction);
-		cmdp->saved_dma_handle	= sg_dma_address(pSRB->pSegmentList);
+	} else if (scsi_sg_count(pcmd)) {
+		int nseg;
+
+		nseg = scsi_dma_map(pcmd);
+
+		pSRB->pSegmentList	= scsi_sglist(pcmd);
+		pSRB->SGcount		= nseg;
 
 		/* TODO: error handling */
-		if (pSRB->SGcount != 1)
+		if (nseg < 0)
 			error = 1;
-		DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle));
-	/* No mapping !? */	
-    	} else
+		DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
+			      __FUNCTION__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
+	/* Map single segment */
+	} else
 		pSRB->SGcount = 0;
 
 	return error;
@@ -494,12 +487,10 @@
 	if (pSRB->SRBFlag) {
 		pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
 		DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
-	} else if (pcmd->use_sg) {
-		pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, pcmd->sc_data_direction);
-		DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", __FUNCTION__, pcmd->request_buffer, pcmd->use_sg));
-	} else if (pcmd->request_buffer && pcmd->request_bufflen) {
-		pci_unmap_sg(pdev, &pSRB->Segmentx, 1, pcmd->sc_data_direction);
-		DEBUG1(printk("%s(): Unmapped request buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
+	} else {
+		scsi_dma_unmap(pcmd);
+		DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
+			      __FUNCTION__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
 	}
 }
 
@@ -1153,9 +1144,9 @@
     struct scatterlist *psgl;
     pSRB->TotalXferredLen = 0;
     pSRB->SGIndex = 0;
-    if (pcmd->use_sg) {
+    if (scsi_sg_count(pcmd)) {
 	size_t saved;
-	pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
+	pSRB->pSegmentList = scsi_sglist(pcmd);
 	psgl = pSRB->pSegmentList;
 	//dc390_pci_sync(pSRB);
 
@@ -1179,12 +1170,6 @@
 	printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
 		pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
 
-    } else if(pcmd->request_buffer) {
-	//dc390_pci_sync(pSRB);
-
-	sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr;
-	pSRB->SGcount = 1;
-	pSRB->pSegmentList = (struct scatterlist *) &pSRB->Segmentx;
     } else {
 	 pSRB->SGcount = 0;
 	 printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
@@ -1579,7 +1564,8 @@
 	if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
 	   !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
 	{	/* Selection time out */
-		pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
+		pSRB->AdaptStatus = H_SEL_TIMEOUT;
+		pSRB->TargetStatus = 0;
 		goto  disc1;
 	}
 	else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
@@ -1612,7 +1598,7 @@
 	if( !( pACB->scan_devices ) )
 	{
 	    struct scsi_cmnd *pcmd = pSRB->pcmd;
-	    pcmd->resid = pcmd->request_bufflen;
+	    scsi_set_resid(pcmd, scsi_bufflen(pcmd));
 	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
 	    dc390_Going_remove(pDCB, pSRB);
 	    dc390_Free_insert(pACB, pSRB);
@@ -1695,7 +1681,6 @@
 			      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
 
 	pSRB->SRBFlag |= AUTO_REQSENSE;
-	pSRB->SavedSGCount = pcmd->use_sg;
 	pSRB->SavedTotXLen = pSRB->TotalXferredLen;
 	pSRB->AdaptStatus = 0;
 	pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
@@ -1728,22 +1713,21 @@
     {	/* Last command was a Request Sense */
 	pSRB->SRBFlag &= ~AUTO_REQSENSE;
 	pSRB->AdaptStatus = 0;
-	pSRB->TargetStatus = CHECK_CONDITION << 1;
+	pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
 
 	//pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
-	if (status == (CHECK_CONDITION << 1))
+	if (status == SAM_STAT_CHECK_CONDITION)
 	    pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
 	else /* Retry */
 	{
 	    if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
 	    {
 		/* Don't retry on TEST_UNIT_READY */
-		pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION);
+		pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
 		REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
 		       (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
 	    } else {
 		SET_RES_DRV(pcmd->result, DRIVER_SENSE);
-		pcmd->use_sg = pSRB->SavedSGCount;
 		//pSRB->ScsiCmdLen	 = (u8) (pSRB->Segment1[0] >> 8);
 		DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
 		pSRB->TotalXferredLen = 0;
@@ -1754,7 +1738,7 @@
     }
     if( status )
     {
-	if( status_byte(status) == CHECK_CONDITION )
+	if (status == SAM_STAT_CHECK_CONDITION)
 	{
 	    if (dc390_RequestSense(pACB, pDCB, pSRB)) {
 		SET_RES_DID(pcmd->result, DID_ERROR);
@@ -1762,22 +1746,14 @@
 	    }
 	    return;
 	}
-	else if( status_byte(status) == QUEUE_FULL )
+	else if (status == SAM_STAT_TASK_SET_FULL)
 	{
 	    scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
-	    pcmd->use_sg = pSRB->SavedSGCount;
 	    DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
 	    pSRB->TotalXferredLen = 0;
 	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
 	}
-	else if(status == SCSI_STAT_SEL_TIMEOUT)
-	{
-	    pSRB->AdaptStatus = H_SEL_TIMEOUT;
-	    pSRB->TargetStatus = 0;
-	    pcmd->result = MK_RES(0,DID_NO_CONNECT,0,0);
-	    /* Devices are removed below ... */
-	}
-	else if (status_byte(status) == BUSY && 
+	else if (status == SAM_STAT_BUSY &&
 		 (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
 		 pACB->scan_devices)
 	{
@@ -1795,12 +1771,17 @@
     else
     {	/*  Target status == 0 */
 	status = pSRB->AdaptStatus;
-	if(status & H_OVER_UNDER_RUN)
+	if (status == H_OVER_UNDER_RUN)
 	{
 	    pSRB->TargetStatus = 0;
 	    SET_RES_DID(pcmd->result,DID_OK);
 	    SET_RES_MSG(pcmd->result,pSRB->EndMessage);
 	}
+	else if (status == H_SEL_TIMEOUT)
+	{
+	    pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
+	    /* Devices are removed below ... */
+	}
 	else if( pSRB->SRBStatus & PARITY_ERROR)
 	{
 	    //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
@@ -1816,7 +1797,7 @@
     }
 
 cmd_done:
-    pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen;
+    scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
 
     dc390_Going_remove (pDCB, pSRB);
     /* Add to free list */
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
index c3d8c80..77adc54 100644
--- a/drivers/scsi/tmscsim.h
+++ b/drivers/scsi/tmscsim.h
@@ -57,7 +57,6 @@
 
 u8		MsgCnt;
 u8		EndMessage;
-u8		SavedSGCount;			
 
 u8		MsgInBuf[6];
 u8		MsgOutBuf[6];
@@ -258,13 +257,6 @@
 #define H_BAD_CCB_OR_SG  0x1A
 #define H_ABORT 	 0x0FF
 
-/*; SCSI Status byte codes*/ 
-/* The values defined in include/scsi/scsi.h, to be shifted << 1 */
-
-#define SCSI_STAT_UNEXP_BUS_F	0xFD	/*;  Unexpect Bus Free */
-#define SCSI_STAT_BUS_RST_DETECT 0xFE	/*;  Scsi Bus Reset detected */
-#define SCSI_STAT_SEL_TIMEOUT	0xFF	/*;  Selection Time out */
-
 /* cmd->result */
 #define RES_TARGET		0x000000FF	/* Target State */
 #define RES_TARGET_LNX		STATUS_MASK	/* Only official ... */
@@ -273,7 +265,7 @@
 #define RES_DRV			0xFF000000	/* DRIVER_ codes */
 
 #define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
-#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt)<<1)
+#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
 
 #define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
 #define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index 3de08a1..9e8232a 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1111,7 +1111,7 @@
 static void map_dma(unsigned int i, unsigned int j) {
    unsigned int data_len = 0;
    unsigned int k, count, pci_dir;
-   struct scatterlist *sgpnt;
+   struct scatterlist *sg;
    struct mscp *cpp;
    struct scsi_cmnd *SCpnt;
 
@@ -1124,33 +1124,28 @@
 
    cpp->sense_len = sizeof SCpnt->sense_buffer;
 
-   if (!SCpnt->use_sg) {
+   if (scsi_bufflen(SCpnt)) {
+	   count = scsi_dma_map(SCpnt);
+	   BUG_ON(count < 0);
 
-      /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
-      if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL;
+	   scsi_for_each_sg(SCpnt, sg, count, k) {
+		   cpp->sglist[k].address = H2DEV(sg_dma_address(sg));
+		   cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg));
+		   data_len += sg->length;
+	   }
 
-      if (SCpnt->request_buffer)
-         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
-                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
+	   cpp->sg = TRUE;
+	   cpp->use_sg = scsi_sg_count(SCpnt);
+	   cpp->data_address =
+		   H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
+					cpp->use_sg * sizeof(struct sg_list),
+					pci_dir));
+	   cpp->data_len = H2DEV(data_len);
 
-      cpp->data_len = H2DEV(SCpnt->request_bufflen);
-      return;
-      }
-
-   sgpnt = (struct scatterlist *) SCpnt->request_buffer;
-   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
-
-   for (k = 0; k < count; k++) {
-      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
-      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
-      data_len += sgpnt[k].length;
-      }
-
-   cpp->sg = TRUE;
-   cpp->use_sg = SCpnt->use_sg;
-   cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
-                             SCpnt->use_sg * sizeof(struct sg_list), pci_dir));
-   cpp->data_len = H2DEV(data_len);
+   } else {
+	   pci_dir = PCI_DMA_BIDIRECTIONAL;
+	   cpp->data_len = H2DEV(scsi_bufflen(SCpnt));
+   }
 }
 
 static void unmap_dma(unsigned int i, unsigned int j) {
@@ -1165,8 +1160,7 @@
       pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
                        DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-   if (SCpnt->use_sg)
-      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
+   scsi_dma_unmap(SCpnt);
 
    if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
@@ -1187,9 +1181,9 @@
       pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr),
                           DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-   if (SCpnt->use_sg)
-      pci_dma_sync_sg_for_cpu(HD(j)->pdev, SCpnt->request_buffer,
-                         SCpnt->use_sg, pci_dir);
+   if (scsi_sg_count(SCpnt))
+	   pci_dma_sync_sg_for_cpu(HD(j)->pdev, scsi_sglist(SCpnt),
+				   scsi_sg_count(SCpnt), pci_dir);
 
    if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 56906ab..c08235d 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -675,16 +675,15 @@
 
 static inline void build_sg_list(struct mscp *mscp, struct scsi_cmnd *SCpnt)
 {
-	struct scatterlist *sl;
+	struct scatterlist *sg;
 	long transfer_length = 0;
 	int i, max;
 
-	sl = (struct scatterlist *) SCpnt->request_buffer;
-	max = SCpnt->use_sg;
-	for (i = 0; i < max; i++) {
-		mscp->sglist[i].address = isa_page_to_bus(sl[i].page) + sl[i].offset;
-		mscp->sglist[i].num_bytes = sl[i].length;
-		transfer_length += sl[i].length;
+	max = scsi_sg_count(SCpnt);
+	scsi_for_each_sg(SCpnt, sg, max, i) {
+		mscp->sglist[i].address = isa_page_to_bus(sg->page) + sg->offset;
+		mscp->sglist[i].num_bytes = sg->length;
+		transfer_length += sg->length;
 	}
 	mscp->number_of_sg_list = max;
 	mscp->transfer_data = isa_virt_to_bus(mscp->sglist);
@@ -730,15 +729,15 @@
     my_mscp->target_id = SCpnt->device->id;
     my_mscp->ch_no = 0;
     my_mscp->lun = SCpnt->device->lun;
-    if (SCpnt->use_sg) {
+    if (scsi_sg_count(SCpnt)) {
 	/* Set scatter/gather flag in SCSI command packet */
 	my_mscp->sg = TRUE;
 	build_sg_list(my_mscp, SCpnt);
     } else {
 	/* Unset scatter/gather flag in SCSI command packet */
 	my_mscp->sg = FALSE;
-	my_mscp->transfer_data = isa_virt_to_bus(SCpnt->request_buffer);
-	my_mscp->transfer_data_length = SCpnt->request_bufflen;
+	my_mscp->transfer_data = isa_virt_to_bus(scsi_sglist(SCpnt));
+	my_mscp->transfer_data_length = scsi_bufflen(SCpnt);
     }
     my_mscp->command_link = 0;		/*???*/
     my_mscp->scsi_command_link_id = 0;	/*???*/
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index 30be765..d6fd425 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1091,6 +1091,7 @@
 	unchar *cdb = (unchar *) SCpnt->cmnd;
 	unchar idlun;
 	short cdblen;
+	int nseg;
 	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
 
 	cdblen = SCpnt->cmd_len;
@@ -1106,28 +1107,29 @@
 	SCpnt->host_scribble = (unchar *) scb;
 	scb->host = host;
 
-	if (SCpnt->use_sg) {
-		struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
+	nseg = scsi_sg_count(SCpnt);
+	if (nseg) {
+		struct scatterlist *sg;
 		unsigned i;
 
 		if (SCpnt->device->host->sg_tablesize == SG_NONE) {
 			panic("wd7000_queuecommand: scatter/gather not supported.\n");
 		}
-		dprintk("Using scatter/gather with %d elements.\n", SCpnt->use_sg);
+		dprintk("Using scatter/gather with %d elements.\n", nseg);
 
 		sgb = scb->sgb;
 		scb->op = 1;
 		any2scsi(scb->dataptr, (int) sgb);
-		any2scsi(scb->maxlen, SCpnt->use_sg * sizeof(Sgb));
+		any2scsi(scb->maxlen, nseg * sizeof(Sgb));
 
-		for (i = 0; i < SCpnt->use_sg; i++) {
-			any2scsi(sgb[i].ptr, isa_page_to_bus(sg[i].page) + sg[i].offset);
-			any2scsi(sgb[i].len, sg[i].length);
+		scsi_for_each_sg(SCpnt, sg, nseg, i) {
+			any2scsi(sgb[i].ptr, isa_page_to_bus(sg->page) + sg->offset);
+			any2scsi(sgb[i].len, sg->length);
 		}
 	} else {
 		scb->op = 0;
-		any2scsi(scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer));
-		any2scsi(scb->maxlen, SCpnt->request_bufflen);
+		any2scsi(scb->dataptr, isa_virt_to_bus(scsi_sglist(SCpnt)));
+		any2scsi(scb->maxlen, scsi_bufflen(SCpnt));
 	}
 
 	/* FIXME: drop lock and yield here ? */
diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c
new file mode 100644
index 0000000..5070387
--- /dev/null
+++ b/drivers/scsi/zorro7xx.c
@@ -0,0 +1,180 @@
+/*
+ * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
+ *		Amiga MacroSystemUS WarpEngine SCSI controller.
+ *		Amiga Technologies/DKB A4091 SCSI controller.
+ *
+ * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ * plus modifications of the 53c7xx.c driver to support the Amiga.
+ *
+ * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/zorro.h>
+#include <asm/amigaints.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
+
+#include "53c700.h"
+
+MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
+MODULE_DESCRIPTION("Amiga Zorro NCR53C710 driver");
+MODULE_LICENSE("GPL");
+
+
+static struct scsi_host_template zorro7xx_scsi_driver_template = {
+	.proc_name	= "zorro7xx",
+	.this_id	= 7,
+	.module		= THIS_MODULE,
+};
+
+static struct zorro_driver_data {
+	const char *name;
+	unsigned long offset;
+	int absolute;	/* offset is absolute address */
+} zorro7xx_driver_data[] __devinitdata = {
+	{ .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 },
+	{ .name = "WarpEngine 40xx", .offset = 0x40000 },
+	{ .name = "A4091", .offset = 0x800000 },
+	{ .name = "GForce 040/060", .offset = 0x40000 },
+	{ 0 }
+};
+
+static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
+	{
+		.id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS,
+		.driver_data = (unsigned long)&zorro7xx_driver_data[0],
+	},
+	{
+		.id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx,
+		.driver_data = (unsigned long)&zorro7xx_driver_data[1],
+	},
+	{
+		.id = ZORRO_PROD_CBM_A4091_1,
+		.driver_data = (unsigned long)&zorro7xx_driver_data[2],
+	},
+	{
+		.id = ZORRO_PROD_CBM_A4091_2,
+		.driver_data = (unsigned long)&zorro7xx_driver_data[2],
+	},
+	{
+		.id = ZORRO_PROD_GVP_GFORCE_040_060,
+		.driver_data = (unsigned long)&zorro7xx_driver_data[3],
+	},
+	{ 0 }
+};
+
+static int __devinit zorro7xx_init_one(struct zorro_dev *z,
+				       const struct zorro_device_id *ent)
+{
+	struct Scsi_Host * host = NULL;
+	struct NCR_700_Host_Parameters *hostdata;
+	struct zorro_driver_data *zdd;
+	unsigned long board, ioaddr;
+
+	board = zorro_resource_start(z);
+	zdd = (struct zorro_driver_data *)ent->driver_data;
+
+	if (zdd->absolute) {
+		ioaddr = zdd->offset;
+	} else {
+		ioaddr = board + zdd->offset;
+	}
+
+	if (!zorro_request_device(z, zdd->name)) {
+		printk(KERN_ERR "zorro7xx: cannot reserve region 0x%lx, abort\n",
+		       board);
+		return -EBUSY;
+	}
+
+	hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+	if (hostdata == NULL) {
+		printk(KERN_ERR "zorro7xx: Failed to allocate host data\n");
+		goto out_release;
+	}
+
+	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
+
+	/* Fill in the required pieces of hostdata */
+	if (ioaddr > 0x01000000)
+		hostdata->base = ioremap(ioaddr, zorro_resource_len(z));
+	else
+		hostdata->base = (void __iomem *)ZTWO_VADDR(ioaddr);
+
+	hostdata->clock = 50;
+	hostdata->chip710 = 1;
+
+	/* Settings for at least WarpEngine 40xx */
+	hostdata->ctest7_extra = CTEST7_TT1;
+
+	zorro7xx_scsi_driver_template.name = zdd->name;
+
+	/* and register the chip */
+	host = NCR_700_detect(&zorro7xx_scsi_driver_template, hostdata,
+			      &z->dev);
+	if (!host) {
+		printk(KERN_ERR "zorro7xx: No host detected; "
+				"board configuration problem?\n");
+		goto out_free;
+	}
+
+	host->this_id = 7;
+	host->base = ioaddr;
+	host->irq = IRQ_AMIGA_PORTS;
+
+	if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "zorro7xx-scsi",
+			host)) {
+		printk(KERN_ERR "zorro7xx: request_irq failed\n");
+		goto out_put_host;
+	}
+
+	scsi_scan_host(host);
+
+	return 0;
+
+ out_put_host:
+	scsi_host_put(host);
+ out_free:
+	if (ioaddr > 0x01000000)
+		iounmap(hostdata->base);
+	kfree(hostdata);
+ out_release:
+	zorro_release_device(z);
+
+	return -ENODEV;
+}
+
+static __devexit void zorro7xx_remove_one(struct zorro_dev *z)
+{
+	struct Scsi_Host *host = dev_to_shost(&z->dev);
+	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+
+	scsi_remove_host(host);
+
+	NCR_700_release(host);
+	kfree(hostdata);
+	free_irq(host->irq, host);
+	zorro_release_device(z);
+}
+
+static struct zorro_driver zorro7xx_driver = {
+	.name	  = "zorro7xx-scsi",
+	.id_table = zorro7xx_zorro_tbl,
+	.probe	  = zorro7xx_init_one,
+	.remove	  = __devexit_p(zorro7xx_remove_one),
+};
+
+static int __init zorro7xx_scsi_init(void)
+{
+	return zorro_register_driver(&zorro7xx_driver);
+}
+
+static void __exit zorro7xx_scsi_exit(void)
+{
+	zorro_unregister_driver(&zorro7xx_driver);
+}
+
+module_init(zorro7xx_scsi_init);
+module_exit(zorro7xx_scsi_exit);
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 68817a7..2aa6bfe 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -934,8 +934,6 @@
 	/*
 	 * Set up parity check flag
 	 */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
 	info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
 	if (I_INPCK(info->tty))
 		info->read_status_mask |= BD_SC_FR | BD_SC_PR;
@@ -1527,11 +1525,6 @@
 {
 	ser_info_t *info = (ser_info_t *)tty->driver_data;
 
-	if (   (tty->termios->c_cflag == old_termios->c_cflag)
-	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
 	change_speed(info);
 
 #ifdef modem_control
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index c84dab0..0b3ec38 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2514,12 +2514,18 @@
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
+static int __init serial8250_console_early_setup(void)
+{
+	return serial8250_find_port_for_earlycon();
+}
+
 static struct uart_driver serial8250_reg;
 static struct console serial8250_console = {
 	.name		= "ttyS",
 	.write		= serial8250_console_write,
 	.device		= uart_console_device,
 	.setup		= serial8250_console_setup,
+	.early_setup	= serial8250_console_early_setup,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
 	.data		= &serial8250_reg,
@@ -2533,7 +2539,7 @@
 }
 console_initcall(serial8250_console_init);
 
-static int __init find_port(struct uart_port *p)
+int serial8250_find_port(struct uart_port *p)
 {
 	int line;
 	struct uart_port *port;
@@ -2546,26 +2552,6 @@
 	return -ENODEV;
 }
 
-int __init serial8250_start_console(struct uart_port *port, char *options)
-{
-	int line;
-
-	line = find_port(port);
-	if (line < 0)
-		return -ENODEV;
-
-	add_preferred_console("ttyS", line, options);
-	printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",
-		line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",
-		port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :
-		    (unsigned long) port->iobase, options);
-	if (!(serial8250_console.flags & CON_ENABLED)) {
-		serial8250_console.flags &= ~CON_PRINTBUFFER;
-		register_console(&serial8250_console);
-	}
-	return line;
-}
-
 #define SERIAL8250_CONSOLE	&serial8250_console
 #else
 #define SERIAL8250_CONSOLE	NULL
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 7e51119..947c205 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -17,13 +17,11 @@
  * we locate the device directly by its MMIO or I/O port address.
  *
  * The user can specify the device directly, e.g.,
- *	console=uart,io,0x3f8,9600n8
- *	console=uart,mmio,0xff5e0000,115200n8
- * or platform code can call early_uart_console_init() to set
- * the early UART device.
- *
- * After the normal serial driver starts, we try to locate the
- * matching ttyS device and start a console there.
+ *	earlycon=uart8250,io,0x3f8,9600n8
+ *	earlycon=uart8250,mmio,0xff5e0000,115200n8
+ * or
+ *	console=uart8250,io,0x3f8,9600n8
+ *	console=uart8250,mmio,0xff5e0000,115200n8
  */
 
 #include <linux/tty.h>
@@ -32,17 +30,21 @@
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
+#include <linux/serial_8250.h>
 #include <asm/io.h>
 #include <asm/serial.h>
+#ifdef CONFIG_FIX_EARLYCON_MEM
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#endif
 
-struct early_uart_device {
+struct early_serial8250_device {
 	struct uart_port port;
 	char options[16];		/* e.g., 115200n8 */
 	unsigned int baud;
 };
 
-static struct early_uart_device early_device __initdata;
-static int early_uart_registered __initdata;
+static struct early_serial8250_device early_device;
 
 static unsigned int __init serial_in(struct uart_port *port, int offset)
 {
@@ -80,7 +82,7 @@
 	serial_out(port, UART_TX, c);
 }
 
-static void __init early_uart_write(struct console *console, const char *s, unsigned int count)
+static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count)
 {
 	struct uart_port *port = &early_device.port;
 	unsigned int ier;
@@ -111,7 +113,7 @@
 	return (port->uartclk / 16) / quot;
 }
 
-static void __init init_port(struct early_uart_device *device)
+static void __init init_port(struct early_serial8250_device *device)
 {
 	struct uart_port *port = &device->port;
 	unsigned int divisor;
@@ -130,10 +132,9 @@
 	serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 }
 
-static int __init parse_options(struct early_uart_device *device, char *options)
+static int __init parse_options(struct early_serial8250_device *device, char *options)
 {
 	struct uart_port *port = &device->port;
-	int mapsize = 64;
 	int mmio, length;
 
 	if (!options)
@@ -143,12 +144,18 @@
 	if (!strncmp(options, "mmio,", 5)) {
 		port->iotype = UPIO_MEM;
 		port->mapbase = simple_strtoul(options + 5, &options, 0);
-		port->membase = ioremap(port->mapbase, mapsize);
+#ifdef CONFIG_FIX_EARLYCON_MEM
+		set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK);
+		port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
+		port->membase += port->mapbase & ~PAGE_MASK;
+#else
+		port->membase = ioremap(port->mapbase, 64);
 		if (!port->membase) {
 			printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
 				__FUNCTION__, port->mapbase);
 			return -ENOMEM;
 		}
+#endif
 		mmio = 1;
 	} else if (!strncmp(options, "io,", 3)) {
 		port->iotype = UPIO_PORT;
@@ -175,9 +182,16 @@
 	return 0;
 }
 
-static int __init early_uart_setup(struct console *console, char *options)
+static struct console early_serial8250_console __initdata = {
+	.name	= "uart",
+	.write	= early_serial8250_write,
+	.flags	= CON_PRINTBUFFER | CON_BOOT,
+	.index	= -1,
+};
+
+static int __init early_serial8250_setup(char *options)
 {
-	struct early_uart_device *device = &early_device;
+	struct early_serial8250_device *device = &early_device;
 	int err;
 
 	if (device->port.membase || device->port.iobase)
@@ -190,61 +204,48 @@
 	return 0;
 }
 
-static struct console early_uart_console __initdata = {
-	.name	= "uart",
-	.write	= early_uart_write,
-	.setup	= early_uart_setup,
-	.flags	= CON_PRINTBUFFER,
-	.index	= -1,
-};
-
-static int __init early_uart_console_init(void)
-{
-	if (!early_uart_registered) {
-		register_console(&early_uart_console);
-		early_uart_registered = 1;
-	}
-	return 0;
-}
-console_initcall(early_uart_console_init);
-
-int __init early_serial_console_init(char *cmdline)
+int __init setup_early_serial8250_console(char *cmdline)
 {
 	char *options;
 	int err;
 
-	options = strstr(cmdline, "console=uart,");
-	if (!options)
-		return -ENODEV;
+	options = strstr(cmdline, "uart8250,");
+	if (!options) {
+		options = strstr(cmdline, "uart,");
+		if (!options)
+			return 0;
+	}
 
 	options = strchr(cmdline, ',') + 1;
-	if ((err = early_uart_setup(NULL, options)) < 0)
+	if ((err = early_serial8250_setup(options)) < 0)
 		return err;
-	return early_uart_console_init();
-}
 
-static int __init early_uart_console_switch(void)
-{
-	struct early_uart_device *device = &early_device;
-	struct uart_port *port = &device->port;
-	int mmio, line;
-
-	if (!(early_uart_console.flags & CON_ENABLED))
-		return 0;
-
-	/* Try to start the normal driver on a matching line.  */
-	mmio = (port->iotype == UPIO_MEM);
-	line = serial8250_start_console(port, device->options);
-	if (line < 0)
-		printk("No ttyS device at %s 0x%lx for console\n",
-			mmio ? "MMIO" : "I/O port",
-			mmio ? port->mapbase :
-			    (unsigned long) port->iobase);
-
-	unregister_console(&early_uart_console);
-	if (mmio)
-		iounmap(port->membase);
+	register_console(&early_serial8250_console);
 
 	return 0;
 }
-late_initcall(early_uart_console_switch);
+
+int __init serial8250_find_port_for_earlycon(void)
+{
+	struct early_serial8250_device *device = &early_device;
+	struct uart_port *port = &device->port;
+	int line;
+	int ret;
+
+	if (!device->port.membase && !device->port.iobase)
+		return -ENODEV;
+
+	line = serial8250_find_port(port);
+	if (line < 0)
+		return -ENODEV;
+
+	ret = update_console_cmdline("uart", 8250,
+			     "ttyS", line, device->options);
+	if (ret < 0)
+		ret = update_console_cmdline("uart", 0,
+				     "ttyS", line, device->options);
+
+	return ret;
+}
+
+early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 315ea99..7fa413d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -62,8 +62,22 @@
 	  kernel will automatically use the first serial line, /dev/ttyS0, as
 	  system console.
 
+	  you can set that using a kernel command line option such as
+	  "console=uart8250,io,0x3f8,9600n8"
+	  "console=uart8250,mmio,0xff5e0000,115200n8".
+	  and it will switch to normal serial console when correponding port is
+	  ready.
+	  "earlycon=uart8250,io,0x3f8,9600n8"
+	  "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+	  it will not only setup early console.
+
 	  If unsure, say N.
 
+config FIX_EARLYCON_MEM
+	bool
+	depends on X86
+	default y
+
 config SERIAL_8250_GSC
 	tristate
 	depends on SERIAL_8250 && GSC
@@ -324,6 +338,34 @@
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+config SERIAL_SB1250_DUART
+	tristate "BCM1xxx on-chip DUART serial support"
+	depends on SIBYTE_SB1xxx_SOC=y
+	select SERIAL_CORE
+	default y
+	---help---
+	  Support for the asynchronous serial interface (DUART) included in
+	  the BCM1250 and derived System-On-a-Chip (SOC) devices.  Note that
+	  the letter D in DUART stands for "dual", which is how the device
+	  is implemented.  Depending on the SOC configuration there may be
+	  one or more DUARTs available of which all are handled.
+
+	  If unsure, say Y.  To compile this driver as a module, choose M here:
+	  the module will be called sb1250-duart.
+
+config SERIAL_SB1250_DUART_CONSOLE
+	bool "Support for console on a BCM1xxx DUART serial port"
+	depends on SERIAL_SB1250_DUART=y
+	select SERIAL_CORE_CONSOLE
+	default y
+	---help---
+	  If you say Y here, it will be possible to use a serial port as the
+	  system console (the system console is the device which receives all
+	  kernel messages and warnings and which allows logins in single user
+	  mode).
+
+	  If unsure, say Y.
+
 config SERIAL_ATMEL
 	bool "AT91 / AT32 on-chip serial port support"
 	depends on (ARM && ARCH_AT91) || AVR32
@@ -556,7 +598,7 @@
 
 config SERIAL_BFIN_DMA
 	bool "DMA mode"
-	depends on DMA_UNCACHED_1M
+	depends on DMA_UNCACHED_1M && !KGDB_UART
 	help
 	  This driver works under DMA mode. If this option is selected, the
 	  blackfin simple dma driver is also enabled.
@@ -599,7 +641,7 @@
 
 config SERIAL_BFIN_UART1
 	bool "Enable UART1"
-	depends on SERIAL_BFIN && (BF534 || BF536 || BF537)
+	depends on SERIAL_BFIN && (BF534 || BF536 || BF537 || BF54x)
 	help
 	  Enable UART1
 
@@ -612,18 +654,58 @@
 
 config UART1_CTS_PIN
 	int "UART1 CTS pin"
-	depends on BFIN_UART1_CTSRTS
+	depends on BFIN_UART1_CTSRTS && (BF53x || BF561)
 	default -1
 	help
 	  Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
 
 config UART1_RTS_PIN
 	int "UART1 RTS pin"
-	depends on BFIN_UART1_CTSRTS
+	depends on BFIN_UART1_CTSRTS && (BF53x || BF561)
 	default -1
 	help
 	  Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
 
+config SERIAL_BFIN_UART2
+	bool "Enable UART2"
+	depends on SERIAL_BFIN && (BF54x)
+	help
+	  Enable UART2
+
+config BFIN_UART2_CTSRTS
+	bool "Enable UART2 hardware flow control"
+	depends on SERIAL_BFIN_UART2
+	help
+	  Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
+	  signal.
+
+config UART2_CTS_PIN
+	int "UART2 CTS pin"
+	depends on BFIN_UART2_CTSRTS
+	default -1
+	help
+	  Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config UART2_RTS_PIN
+	int "UART2 RTS pin"
+	depends on BFIN_UART2_CTSRTS
+	default -1
+	help
+	  Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config SERIAL_BFIN_UART3
+	bool "Enable UART3"
+	depends on SERIAL_BFIN && (BF54x)
+	help
+	  Enable UART3
+
+config BFIN_UART3_CTSRTS
+	bool "Enable UART3 hardware flow control"
+	depends on SERIAL_BFIN_UART3
+	help
+	  Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
+	  signal.
+
 config SERIAL_IMX
 	bool "IMX serial port support"
 	depends on ARM && ARCH_IMX
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 08ad0d9..c48cdd6 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -51,6 +51,7 @@
 obj-$(CONFIG_SERIAL_ICOM) += icom.o
 obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
 obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
+obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 1a9a24b..e88da72 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -167,8 +167,9 @@
 	ignore_char:
 		status = readb(uap->port.membase + UART01x_FR);
 	}
+	spin_unlock(&uap->port.lock);
 	tty_flip_buffer_push(tty);
-	return;
+	spin_lock(&uap->port.lock);
 }
 
 static void pl010_tx_chars(struct uart_amba_port *uap)
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 44639e7..954073c 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -153,8 +153,9 @@
 	ignore_char:
 		status = readw(uap->port.membase + UART01x_FR);
 	}
+	spin_unlock(&uap->port.lock);
 	tty_flip_buffer_push(tty);
-	return;
+	spin_lock(&uap->port.lock);
 }
 
 static void pl011_tx_chars(struct uart_amba_port *uap)
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 3320bcd..4d6b3c5 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -114,6 +114,7 @@
 	struct uart_port	uart;		/* uart */
 	struct clk		*clk;		/* uart clock */
 	unsigned short		suspended;	/* is port suspended? */
+	int			break_active;	/* break being received */
 };
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
@@ -252,6 +253,7 @@
  */
 static void atmel_rx_chars(struct uart_port *port)
 {
+	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
 	struct tty_struct *tty = port->info->tty;
 	unsigned int status, ch, flg;
 
@@ -267,13 +269,29 @@
 		 * note that the error handling code is
 		 * out of the main execution path
 		 */
-		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
+		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
+				       | ATMEL_US_OVRE | ATMEL_US_RXBRK)
+			     || atmel_port->break_active)) {
 			UART_PUT_CR(port, ATMEL_US_RSTSTA);	/* clear error */
-			if (status & ATMEL_US_RXBRK) {
+			if (status & ATMEL_US_RXBRK
+			    && !atmel_port->break_active) {
 				status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);	/* ignore side-effect */
 				port->icount.brk++;
+				atmel_port->break_active = 1;
+				UART_PUT_IER(port, ATMEL_US_RXBRK);
 				if (uart_handle_break(port))
 					goto ignore_char;
+			} else {
+				/*
+				 * This is either the end-of-break
+				 * condition or we've received at
+				 * least one character without RXBRK
+				 * being set. In both cases, the next
+				 * RXBRK will indicate start-of-break.
+				 */
+				UART_PUT_IDR(port, ATMEL_US_RXBRK);
+				status &= ~ATMEL_US_RXBRK;
+				atmel_port->break_active = 0;
 			}
 			if (status & ATMEL_US_PARE)
 				port->icount.parity++;
@@ -352,6 +370,16 @@
 		/* Interrupt receive */
 		if (pending & ATMEL_US_RXRDY)
 			atmel_rx_chars(port);
+		else if (pending & ATMEL_US_RXBRK) {
+			/*
+			 * End of break detected. If it came along
+			 * with a character, atmel_rx_chars will
+			 * handle it.
+			 */
+			UART_PUT_CR(port, ATMEL_US_RSTSTA);
+			UART_PUT_IDR(port, ATMEL_US_RXBRK);
+			atmel_port->break_active = 0;
+		}
 
 		// TODO: All reads to CSR will clear these interrupts!
 		if (pending & ATMEL_US_RIIC) port->icount.rng++;
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 408390f..66c92bc 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -6,8 +6,6 @@
  * Created:
  * Description:  Driver for blackfin 5xx serial ports
  *
- * Rev:          $Id: bfin_5xx.c,v 1.19 2006/09/24 02:33:53 aubrey Exp $
- *
  * Modified:
  *               Copyright 2006 Analog Devices Inc.
  *
@@ -43,6 +41,11 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 
+#ifdef CONFIG_KGDB_UART
+#include <linux/kgdb.h>
+#include <asm/irq_regs.h>
+#endif
+
 #include <asm/gpio.h>
 #include <asm/mach/bfin_serial_5xx.h>
 
@@ -83,15 +86,29 @@
 {
 	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
 
+#ifdef CONFIG_BF54x
+	while (!(UART_GET_LSR(uart) & TEMT))
+		continue;
+#endif
+
 #ifdef CONFIG_SERIAL_BFIN_DMA
 	disable_dma(uart->tx_dma_channel);
 #else
+#ifdef CONFIG_BF54x
+	/* Waiting for Transmission Finished */
+	while (!(UART_GET_LSR(uart) & TFI))
+		continue;
+	/* Clear TFI bit */
+	UART_PUT_LSR(uart, TFI);
+	UART_CLEAR_IER(uart, ETBEI);
+#else
 	unsigned short ier;
 
 	ier = UART_GET_IER(uart);
 	ier &= ~ETBEI;
 	UART_PUT_IER(uart, ier);
 #endif
+#endif
 }
 
 /*
@@ -104,12 +121,16 @@
 #ifdef CONFIG_SERIAL_BFIN_DMA
 	bfin_serial_dma_tx_chars(uart);
 #else
+#ifdef CONFIG_BF54x
+	UART_SET_IER(uart, ETBEI);
+#else
 	unsigned short ier;
 	ier = UART_GET_IER(uart);
 	ier |= ETBEI;
 	UART_PUT_IER(uart, ier);
 	bfin_serial_tx_chars(uart);
 #endif
+#endif
 }
 
 /*
@@ -118,11 +139,18 @@
 static void bfin_serial_stop_rx(struct uart_port *port)
 {
 	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+#ifdef CONFIG_BF54x
+	UART_CLEAR_IER(uart, ERBFI);
+#else
 	unsigned short ier;
 
 	ier = UART_GET_IER(uart);
+#ifdef	CONFIG_KGDB_UART
+	if (uart->port.line != CONFIG_KGDB_UART_PORT)
+#endif
 	ier &= ~ERBFI;
 	UART_PUT_IER(uart, ier);
+#endif
 }
 
 /*
@@ -132,6 +160,49 @@
 {
 }
 
+#ifdef CONFIG_KGDB_UART
+static int kgdb_entry_state;
+
+void kgdb_put_debug_char(int chr)
+{
+	struct bfin_serial_port *uart;
+	
+	if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+		uart = &bfin_serial_ports[0];
+	else
+		uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+	
+	while (!(UART_GET_LSR(uart) & THRE)) {
+		__builtin_bfin_ssync();
+	}
+	UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB));
+	__builtin_bfin_ssync();
+	UART_PUT_CHAR(uart, (unsigned char)chr);
+	__builtin_bfin_ssync();
+}
+
+int kgdb_get_debug_char(void)
+{
+	struct bfin_serial_port *uart;
+	unsigned char chr;
+
+	if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+		uart = &bfin_serial_ports[0];
+	else
+		uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+	
+	while(!(UART_GET_LSR(uart) & DR)) {
+		__builtin_bfin_ssync();
+	}
+	UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB));
+	__builtin_bfin_ssync();
+	chr = UART_GET_CHAR(uart);
+	__builtin_bfin_ssync();
+
+	return chr;
+}
+#endif
+
 #ifdef CONFIG_SERIAL_BFIN_PIO
 static void local_put_char(struct bfin_serial_port *uart, char ch)
 {
@@ -152,8 +223,11 @@
 
 static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
 {
-	struct tty_struct *tty = uart->port.info?uart->port.info->tty:0;
+	struct tty_struct *tty = uart->port.info->tty;
 	unsigned int status, ch, flg;
+#ifdef CONFIG_KGDB_UART
+	struct pt_regs *regs = get_irq_regs();
+#endif
 #ifdef BF533_FAMILY
 	static int in_break = 0;
 #endif
@@ -162,6 +236,27 @@
  	ch = UART_GET_CHAR(uart);
  	uart->port.icount.rx++;
 
+#ifdef CONFIG_KGDB_UART
+	if (uart->port.line == CONFIG_KGDB_UART_PORT) {
+		if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */
+			kgdb_breakkey_pressed(regs);
+			return;
+		} else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */
+			kgdb_entry_state = 1;
+		} else if (kgdb_entry_state == 1 && ch == 'q') {
+			kgdb_entry_state = 0;
+			kgdb_breakkey_pressed(regs);
+			return;
+		} else if (ch == 0x3) {/* Ctrl + C */
+			kgdb_entry_state = 0;
+			kgdb_breakkey_pressed(regs);
+			return;
+		} else {
+			kgdb_entry_state = 0;
+		}
+	}
+#endif
+ 
 #ifdef BF533_FAMILY
 	/* The BF533 family of processors have a nice misbehavior where
 	 * they continuously generate characters for a "single" break.
@@ -173,8 +268,10 @@
 		if (ch != 0) {
 			in_break = 0;
 			ch = UART_GET_CHAR(uart);
-		}
-		return;
+			if (bfin_revid() < 5)
+				return;
+		} else
+			return;
 	}
 #endif
 
@@ -185,27 +282,33 @@
 		uart->port.icount.brk++;
 		if (uart_handle_break(&uart->port))
 			goto ignore_char;
-		flg = TTY_BREAK;
-	} else if (status & PE) {
-		flg = TTY_PARITY;
+		status &= ~(PE | FE);
+	}
+	if (status & PE)
 		uart->port.icount.parity++;
-	} else if (status & OE) {
-		flg = TTY_OVERRUN;
+	if (status & OE)
 		uart->port.icount.overrun++;
-	} else if (status & FE) {
-		flg = TTY_FRAME;
+	if (status & FE)
 		uart->port.icount.frame++;
-	} else
+
+	status &= uart->port.read_status_mask;
+
+	if (status & BI)
+		flg = TTY_BREAK;
+	else if (status & PE)
+		flg = TTY_PARITY;
+	else if (status & FE)
+		flg = TTY_FRAME;
+	else
 		flg = TTY_NORMAL;
 
 	if (uart_handle_sysrq_char(&uart->port, ch))
 		goto ignore_char;
-	if (tty)
-		uart_insert_char(&uart->port, status, 2, ch, flg);
 
-ignore_char:
-	if (tty)
-		tty_flip_buffer_push(tty);
+	uart_insert_char(&uart->port, status, OE, ch, flg);
+
+ ignore_char:
+	tty_flip_buffer_push(tty);
 }
 
 static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
@@ -240,31 +343,57 @@
 		bfin_serial_stop_tx(&uart->port);
 }
 
-static irqreturn_t bfin_serial_int(int irq, void *dev_id)
+static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
 {
 	struct bfin_serial_port *uart = dev_id;
-	unsigned short status;
 
+#ifdef CONFIG_BF54x
+	unsigned short status;
 	spin_lock(&uart->port.lock);
-	status = UART_GET_IIR(uart);
-	do {
-		if ((status & IIR_STATUS) == IIR_TX_READY)
-			bfin_serial_tx_chars(uart);
-		if ((status & IIR_STATUS) == IIR_RX_READY)
-			bfin_serial_rx_chars(uart);
-		status = UART_GET_IIR(uart);
-	} while (status & (IIR_TX_READY | IIR_RX_READY));
+	status = UART_GET_LSR(uart);
+	while ((UART_GET_IER(uart) & ERBFI) && (status & DR)) {
+		bfin_serial_rx_chars(uart);
+		status = UART_GET_LSR(uart);
+	}
 	spin_unlock(&uart->port.lock);
+#else
+	spin_lock(&uart->port.lock);
+	while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY)
+		bfin_serial_rx_chars(uart);
+	spin_unlock(&uart->port.lock);
+#endif
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
+{
+	struct bfin_serial_port *uart = dev_id;
+
+#ifdef CONFIG_BF54x
+	unsigned short status;
+	spin_lock(&uart->port.lock);
+	status = UART_GET_LSR(uart);
+	while ((UART_GET_IER(uart) & ETBEI) && (status & THRE)) {
+		bfin_serial_tx_chars(uart);
+		status = UART_GET_LSR(uart);
+	}
+	spin_unlock(&uart->port.lock);
+#else
+	spin_lock(&uart->port.lock);
+	while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY)
+		bfin_serial_tx_chars(uart);
+	spin_unlock(&uart->port.lock);
+#endif
+	return IRQ_HANDLED;
+}
+
+
 static void bfin_serial_do_work(struct work_struct *work)
 {
 	struct bfin_serial_port *uart = container_of(work, struct bfin_serial_port, cts_workqueue);
 
 	bfin_serial_mctrl_check(uart);
 }
-
 #endif
 
 #ifdef CONFIG_SERIAL_BFIN_DMA
@@ -313,13 +442,17 @@
 	set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
 	set_dma_x_modify(uart->tx_dma_channel, 1);
 	enable_dma(uart->tx_dma_channel);
+#ifdef CONFIG_BF54x
+	UART_SET_IER(uart, ETBEI);
+#else
 	ier = UART_GET_IER(uart);
 	ier |= ETBEI;
 	UART_PUT_IER(uart, ier);
+#endif
 	spin_unlock_irqrestore(&uart->port.lock, flags);
 }
 
-static void bfin_serial_dma_rx_chars(struct bfin_serial_port * uart)
+static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
 {
 	struct tty_struct *tty = uart->port.info->tty;
 	int i, flg, status;
@@ -331,25 +464,33 @@
 		uart->port.icount.brk++;
 		if (uart_handle_break(&uart->port))
 			goto dma_ignore_char;
-		flg = TTY_BREAK;
-	} else if (status & PE) {
-		flg = TTY_PARITY;
+		status &= ~(PE | FE);
+	}
+	if (status & PE)
 		uart->port.icount.parity++;
-	} else if (status & OE) {
-		flg = TTY_OVERRUN;
+	if (status & OE)
 		uart->port.icount.overrun++;
-	} else if (status & FE) {
-		flg = TTY_FRAME;
+	if (status & FE)
 		uart->port.icount.frame++;
-	} else
+
+	status &= uart->port.read_status_mask;
+
+	if (status & BI)
+		flg = TTY_BREAK;
+	else if (status & PE)
+		flg = TTY_PARITY;
+	else if (status & FE)
+		flg = TTY_FRAME;
+	else
 		flg = TTY_NORMAL;
 
 	for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) {
 		if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))
 			goto dma_ignore_char;
-		uart_insert_char(&uart->port, status, 2, uart->rx_dma_buf.buf[i], flg);
+		uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg);
 	}
-dma_ignore_char:
+
+ dma_ignore_char:
 	tty_flip_buffer_push(tty);
 }
 
@@ -387,9 +528,13 @@
 	if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
 		clear_dma_irqstat(uart->tx_dma_channel);
 		disable_dma(uart->tx_dma_channel);
+#ifdef CONFIG_BF54x
+		UART_CLEAR_IER(uart, ETBEI);
+#else
 		ier = UART_GET_IER(uart);
 		ier &= ~ETBEI;
 		UART_PUT_IER(uart, ier);
+#endif
 		xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1);
 		uart->port.icount.tx+=uart->tx_count;
 
@@ -500,6 +645,14 @@
  */
 static void bfin_serial_break_ctl(struct uart_port *port, int break_state)
 {
+	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+	u16 lcr = UART_GET_LCR(uart);
+	if (break_state)
+		lcr |= SB;
+	else
+		lcr &= ~SB;
+	UART_PUT_LCR(uart, lcr);
+	SSYNC();
 }
 
 static int bfin_serial_startup(struct uart_port *port)
@@ -544,22 +697,30 @@
 	uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
 	add_timer(&(uart->rx_dma_timer));
 #else
+# ifdef	CONFIG_KGDB_UART
+	if (uart->port.line != CONFIG_KGDB_UART_PORT && request_irq
+# else
 	if (request_irq
-	    (uart->port.irq, bfin_serial_int, IRQF_DISABLED,
+# endif
+	    (uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
 	     "BFIN_UART_RX", uart)) {
 		printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
 		return -EBUSY;
 	}
 
 	if (request_irq
-	    (uart->port.irq+1, bfin_serial_int, IRQF_DISABLED,
+	    (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED,
 	     "BFIN_UART_TX", uart)) {
 		printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n");
 		free_irq(uart->port.irq, uart);
 		return -EBUSY;
 	}
 #endif
+#ifdef CONFIG_BF54x
+	UART_SET_IER(uart, ERBFI);
+#else
 	UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
+#endif
 	return 0;
 }
 
@@ -574,6 +735,9 @@
 	free_dma(uart->rx_dma_channel);
 	del_timer(&(uart->rx_dma_timer));
 #else
+#ifdef	CONFIG_KGDB_UART
+	if (uart->port.line != CONFIG_KGDB_UART_PORT)
+#endif
 	free_irq(uart->port.irq, uart);
 	free_irq(uart->port.irq+1, uart);
 #endif
@@ -608,20 +772,35 @@
 
 	if (termios->c_cflag & CSTOPB)
 		lcr |= STB;
-	if (termios->c_cflag & PARENB) {
+	if (termios->c_cflag & PARENB)
 		lcr |= PEN;
-		if (!(termios->c_cflag & PARODD))
-			lcr |= EPS;
+	if (!(termios->c_cflag & PARODD))
+		lcr |= EPS;
+	if (termios->c_cflag & CMSPAR)
+		lcr |= STP;
+
+	port->read_status_mask = OE;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= (FE | PE);
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= BI;
+
+	/*
+	 * Characters to ignore
+	 */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= FE | PE;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= BI;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= OE;
 	}
 
-	/* These controls are not implemented for this port */
-	termios->c_iflag |= INPCK | BRKINT | PARMRK;
-	termios->c_iflag &= ~(IGNPAR | IGNBRK);
-
-	/* These controls are not implemented for this port */
-	termios->c_iflag |= INPCK | BRKINT | PARMRK;
-	termios->c_iflag &= ~(IGNPAR | IGNBRK);
-
 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
 	quot = uart_get_divisor(port, baud);
 	spin_lock_irqsave(&uart->port.lock, flags);
@@ -632,29 +811,41 @@
 
 	/* Disable UART */
 	ier = UART_GET_IER(uart);
+#ifdef CONFIG_BF54x
+	UART_CLEAR_IER(uart, 0xF);
+#else
 	UART_PUT_IER(uart, 0);
+#endif
 
+#ifndef CONFIG_BF54x
 	/* Set DLAB in LCR to Access DLL and DLH */
 	val = UART_GET_LCR(uart);
 	val |= DLAB;
 	UART_PUT_LCR(uart, val);
 	SSYNC();
+#endif
 
 	UART_PUT_DLL(uart, quot & 0xFF);
 	SSYNC();
 	UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
 	SSYNC();
 
+#ifndef CONFIG_BF54x
 	/* Clear DLAB in LCR to Access THR RBR IER */
 	val = UART_GET_LCR(uart);
 	val &= ~DLAB;
 	UART_PUT_LCR(uart, val);
 	SSYNC();
+#endif
 
 	UART_PUT_LCR(uart, lcr);
 
 	/* Enable UART */
+#ifdef CONFIG_BF54x
+	UART_SET_IER(uart, ier);
+#else
 	UART_PUT_IER(uart, ier);
+#endif
 
 	val = UART_GET_GCTL(uart);
 	val |= UCEN;
@@ -766,15 +957,15 @@
 			bfin_serial_resource[i].uart_rts_pin;
 #endif
 		bfin_serial_hw_init(&bfin_serial_ports[i]);
-
 	}
+
 }
 
 #ifdef CONFIG_SERIAL_BFIN_CONSOLE
 static void bfin_serial_console_putchar(struct uart_port *port, int ch)
 {
 	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-	while (!(UART_GET_LSR(uart)))
+	while (!(UART_GET_LSR(uart) & THRE))
 		barrier();
 	UART_PUT_CHAR(uart, ch);
 	SSYNC();
@@ -826,18 +1017,22 @@
 			case 2:	*bits = 7; break;
 			case 3:	*bits = 8; break;
 		}
+#ifndef CONFIG_BF54x
 		/* Set DLAB in LCR to Access DLL and DLH */
 		val = UART_GET_LCR(uart);
 		val |= DLAB;
 		UART_PUT_LCR(uart, val);
+#endif
 
 		dll = UART_GET_DLL(uart);
 		dlh = UART_GET_DLH(uart);
 
+#ifndef CONFIG_BF54x
 		/* Clear DLAB in LCR to Access THR RBR IER */
 		val = UART_GET_LCR(uart);
 		val &= ~DLAB;
 		UART_PUT_LCR(uart, val);
+#endif
 
 		*baud = get_sclk() / (16*(dll | dlh << 8));
 	}
@@ -889,6 +1084,10 @@
 {
 	bfin_serial_init_ports();
 	register_console(&bfin_serial_console);
+#ifdef CONFIG_KGDB_UART
+	kgdb_entry_state = 0;
+	init_kgdb_uart();
+#endif
 	return 0;
 }
 console_initcall(bfin_serial_rs_console_init);
@@ -981,6 +1180,10 @@
 static int __init bfin_serial_init(void)
 {
 	int ret;
+#ifdef CONFIG_KGDB_UART
+	struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+	struct termios t;
+#endif
 
 	pr_info("Serial: Blackfin serial driver\n");
 
@@ -994,6 +1197,21 @@
 			uart_unregister_driver(&bfin_serial_reg);
 		}
 	}
+#ifdef CONFIG_KGDB_UART
+	if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) {
+		request_irq(uart->port.irq, bfin_serial_int,
+			IRQF_DISABLED, "BFIN_UART_RX", uart);
+		pr_info("Request irq for kgdb uart port\n");
+		UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
+		__builtin_bfin_ssync();
+		t.c_cflag = CS8|B57600;
+		t.c_iflag = 0;
+		t.c_oflag = 0;
+		t.c_lflag = ICANON;
+		t.c_line = CONFIG_KGDB_UART_PORT;
+		bfin_serial_set_termios(&uart->port, &t, &t);
+	}
+#endif
 	return ret;
 }
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index b63ff8d..cefde58 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -678,7 +678,7 @@
 		}
 		bdp->cbd_datlen = count;
 		bdp->cbd_sc |= BD_SC_READY;
-		__asm__("eieio");
+		eieio();
 		/* Get next BD. */
 		if (bdp->cbd_sc & BD_SC_WRAP)
 			bdp = pinfo->tx_bd_base;
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index c3abfb3..f3257f7 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -862,6 +862,7 @@
 	up->cflag = termios->c_cflag;
 
 	ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
+	uart_update_timeout(port, termios->c_cflag, baud);
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
@@ -1017,6 +1018,8 @@
 	}
 
 	con->cflag = cflag | CS8;			/* 8N1 */
+
+	uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud);
 }
 
 static int __init ip22zilog_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 81792e6..6767ee3 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -88,7 +88,7 @@
 	spin_lock_init(&brd->bd_intr_lock);
 
 	/* store which revision we have */
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+	brd->rev = pdev->revision;
 
 	brd->irq = pdev->irq;
 
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index d09f209..00924fe 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -503,7 +503,8 @@
 
 	if (pi->mirror_regs)
 		pi->shared_regs->SDMA_INTR_CAUSE_m = 0;
-	writel(0, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE);
+	writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE +
+	       pi->port.line);
 	return;
 }
 
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
index 7ffdaea..a64d858 100644
--- a/drivers/serial/of_serial.c
+++ b/drivers/serial/of_serial.c
@@ -17,6 +17,11 @@
 #include <asm/of_platform.h>
 #include <asm/prom.h>
 
+struct of_serial_info {
+	int type;
+	int line;
+};
+
 /*
  * Fill a struct uart_port for a given device node
  */
@@ -62,6 +67,7 @@
 static int __devinit of_platform_serial_probe(struct of_device *ofdev,
 						const struct of_device_id *id)
 {
+	struct of_serial_info *info;
 	struct uart_port port;
 	int port_type;
 	int ret;
@@ -69,30 +75,35 @@
 	if (of_find_property(ofdev->node, "used-by-rtas", NULL))
 		return -EBUSY;
 
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (info == NULL)
+		return -ENOMEM;
+
 	port_type = (unsigned long)id->data;
 	ret = of_platform_serial_setup(ofdev, port_type, &port);
 	if (ret)
 		goto out;
 
 	switch (port_type) {
-	case PORT_UNKNOWN:
-		dev_info(&ofdev->dev, "Unknown serial port found, "
-			"attempting to use 8250 driver\n");
-		/* fallthrough */
 	case PORT_8250 ... PORT_MAX_8250:
 		ret = serial8250_register_port(&port);
 		break;
 	default:
 		/* need to add code for these */
+	case PORT_UNKNOWN:
+		dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
 		ret = -ENODEV;
 		break;
 	}
 	if (ret < 0)
 		goto out;
 
-	ofdev->dev.driver_data = (void *)(unsigned long)ret;
+	info->type = port_type;
+	info->line = ret;
+	ofdev->dev.driver_data = info;
 	return 0;
 out:
+	kfree(info);
 	irq_dispose_mapping(port.irq);
 	return ret;
 }
@@ -102,8 +113,16 @@
  */
 static int of_platform_serial_remove(struct of_device *ofdev)
 {
-	int line = (unsigned long)ofdev->dev.driver_data;
-	serial8250_unregister_port(line);
+	struct of_serial_info *info = ofdev->dev.driver_data;
+	switch (info->type) {
+	case PORT_8250 ... PORT_MAX_8250:
+		serial8250_unregister_port(info->line);
+		break;
+	default:
+		/* need to add code for these */
+		break;
+	}
+	kfree(info);
 	return 0;
 }
 
diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c
new file mode 100644
index 0000000..1d9d728
--- /dev/null
+++ b/drivers/serial/sb1250-duart.c
@@ -0,0 +1,972 @@
+/*
+ *	drivers/serial/sb1250-duart.c
+ *
+ *	Support for the asynchronous serial interface (DUART) included
+ *	in the BCM1250 and derived System-On-a-Chip (SOC) devices.
+ *
+ *	Copyright (c) 2007  Maciej W. Rozycki
+ *
+ *	Derived from drivers/char/sb1250_duart.c for which the following
+ *	copyright applies:
+ *
+ *	Copyright (c) 2000, 2001, 2002, 2003, 2004  Broadcom Corporation
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	References:
+ *
+ *	"BCM1250/BCM1125/BCM1125H User Manual", Broadcom Corporation
+ */
+
+#if defined(CONFIG_SERIAL_SB1250_DUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/spinlock.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/war.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_uart.h>
+#include <asm/sibyte/swarm.h>
+
+
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+
+#define SBD_CHANREGS(line)	A_BCM1480_DUART_CHANREG((line), 0)
+#define SBD_CTRLREGS(line)	A_BCM1480_DUART_CTRLREG((line), 0)
+#define SBD_INT(line)		(K_BCM1480_INT_UART_0 + (line))
+
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+
+#define SBD_CHANREGS(line)	A_DUART_CHANREG((line), 0)
+#define SBD_CTRLREGS(line)	A_DUART_CTRLREG(0)
+#define SBD_INT(line)		(K_INT_UART_0 + (line))
+
+#else
+#error invalid SB1250 UART configuration
+
+#endif
+
+
+MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
+MODULE_DESCRIPTION("BCM1xxx on-chip DUART serial driver");
+MODULE_LICENSE("GPL");
+
+
+#define DUART_MAX_CHIP 2
+#define DUART_MAX_SIDE 2
+
+/*
+ * Per-port state.
+ */
+struct sbd_port {
+	struct sbd_duart	*duart;
+	struct uart_port	port;
+	unsigned char __iomem	*memctrl;
+	int			tx_stopped;
+	int			initialised;
+};
+
+/*
+ * Per-DUART state for the shared register space.
+ */
+struct sbd_duart {
+	struct sbd_port		sport[2];
+	unsigned long		mapctrl;
+	atomic_t		map_guard;
+};
+
+#define to_sport(uport) container_of(uport, struct sbd_port, port)
+
+static struct sbd_duart sbd_duarts[DUART_MAX_CHIP];
+
+#define __unused __attribute__((__unused__))
+
+
+/*
+ * Reading and writing SB1250 DUART registers.
+ *
+ * There are three register spaces: two per-channel ones and
+ * a shared one.  We have to define accessors appropriately.
+ * All registers are 64-bit and all but the Baud Rate Clock
+ * registers only define 8 least significant bits.  There is
+ * also a workaround to take into account.  Raw accessors use
+ * the full register width, but cooked ones truncate it
+ * intentionally so that the rest of the driver does not care.
+ */
+static u64 __read_sbdchn(struct sbd_port *sport, int reg)
+{
+	void __iomem *csr = sport->port.membase + reg;
+
+	return __raw_readq(csr);
+}
+
+static u64 __read_sbdshr(struct sbd_port *sport, int reg)
+{
+	void __iomem *csr = sport->memctrl + reg;
+
+	return __raw_readq(csr);
+}
+
+static void __write_sbdchn(struct sbd_port *sport, int reg, u64 value)
+{
+	void __iomem *csr = sport->port.membase + reg;
+
+	__raw_writeq(value, csr);
+}
+
+static void __write_sbdshr(struct sbd_port *sport, int reg, u64 value)
+{
+	void __iomem *csr = sport->memctrl + reg;
+
+	__raw_writeq(value, csr);
+}
+
+/*
+ * In bug 1956, we get glitches that can mess up uart registers.  This
+ * "read-mode-reg after any register access" is an accepted workaround.
+ */
+static void __war_sbd1956(struct sbd_port *sport)
+{
+	__read_sbdchn(sport, R_DUART_MODE_REG_1);
+	__read_sbdchn(sport, R_DUART_MODE_REG_2);
+}
+
+static unsigned char read_sbdchn(struct sbd_port *sport, int reg)
+{
+	unsigned char retval;
+
+	retval = __read_sbdchn(sport, reg);
+	if (SIBYTE_1956_WAR)
+		__war_sbd1956(sport);
+	return retval;
+}
+
+static unsigned char read_sbdshr(struct sbd_port *sport, int reg)
+{
+	unsigned char retval;
+
+	retval = __read_sbdshr(sport, reg);
+	if (SIBYTE_1956_WAR)
+		__war_sbd1956(sport);
+	return retval;
+}
+
+static void write_sbdchn(struct sbd_port *sport, int reg, unsigned int value)
+{
+	__write_sbdchn(sport, reg, value);
+	if (SIBYTE_1956_WAR)
+		__war_sbd1956(sport);
+}
+
+static void write_sbdshr(struct sbd_port *sport, int reg, unsigned int value)
+{
+	__write_sbdshr(sport, reg, value);
+	if (SIBYTE_1956_WAR)
+		__war_sbd1956(sport);
+}
+
+
+static int sbd_receive_ready(struct sbd_port *sport)
+{
+	return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_RX_RDY;
+}
+
+static int sbd_receive_drain(struct sbd_port *sport)
+{
+	int loops = 10000;
+
+	while (sbd_receive_ready(sport) && loops--)
+		read_sbdchn(sport, R_DUART_RX_HOLD);
+	return loops;
+}
+
+static int __unused sbd_transmit_ready(struct sbd_port *sport)
+{
+	return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_RDY;
+}
+
+static int __unused sbd_transmit_drain(struct sbd_port *sport)
+{
+	int loops = 10000;
+
+	while (!sbd_transmit_ready(sport) && loops--)
+		udelay(2);
+	return loops;
+}
+
+static int sbd_transmit_empty(struct sbd_port *sport)
+{
+	return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_EMT;
+}
+
+static int sbd_line_drain(struct sbd_port *sport)
+{
+	int loops = 10000;
+
+	while (!sbd_transmit_empty(sport) && loops--)
+		udelay(2);
+	return loops;
+}
+
+
+static unsigned int sbd_tx_empty(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	return sbd_transmit_empty(sport) ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int sbd_get_mctrl(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int mctrl, status;
+
+	status = read_sbdshr(sport, R_DUART_IN_PORT);
+	status >>= (uport->line) % 2;
+	mctrl = (!(status & M_DUART_IN_PIN0_VAL) ? TIOCM_CTS : 0) |
+		(!(status & M_DUART_IN_PIN4_VAL) ? TIOCM_CAR : 0) |
+		(!(status & M_DUART_RIN0_PIN) ? TIOCM_RNG : 0) |
+		(!(status & M_DUART_IN_PIN2_VAL) ? TIOCM_DSR : 0);
+	return mctrl;
+}
+
+static void sbd_set_mctrl(struct uart_port *uport, unsigned int mctrl)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int clr = 0, set = 0, mode2;
+
+	if (mctrl & TIOCM_DTR)
+		set |= M_DUART_SET_OPR2;
+	else
+		clr |= M_DUART_CLR_OPR2;
+	if (mctrl & TIOCM_RTS)
+		set |= M_DUART_SET_OPR0;
+	else
+		clr |= M_DUART_CLR_OPR0;
+	clr <<= (uport->line) % 2;
+	set <<= (uport->line) % 2;
+
+	mode2 = read_sbdchn(sport, R_DUART_MODE_REG_2);
+	mode2 &= ~M_DUART_CHAN_MODE;
+	if (mctrl & TIOCM_LOOP)
+		mode2 |= V_DUART_CHAN_MODE_LCL_LOOP;
+	else
+		mode2 |= V_DUART_CHAN_MODE_NORMAL;
+
+	write_sbdshr(sport, R_DUART_CLEAR_OPR, clr);
+	write_sbdshr(sport, R_DUART_SET_OPR, set);
+	write_sbdchn(sport, R_DUART_MODE_REG_2, mode2);
+}
+
+static void sbd_stop_tx(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
+	sport->tx_stopped = 1;
+};
+
+static void sbd_start_tx(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int mask;
+
+	/* Enable tx interrupts.  */
+	mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+	mask |= M_DUART_IMR_TX;
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+
+	/* Go!, go!, go!...  */
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
+	sport->tx_stopped = 0;
+};
+
+static void sbd_stop_rx(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
+};
+
+static void sbd_enable_ms(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	write_sbdchn(sport, R_DUART_AUXCTL_X,
+		     M_DUART_CIN_CHNG_ENA | M_DUART_CTS_CHNG_ENA);
+}
+
+static void sbd_break_ctl(struct uart_port *uport, int break_state)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	if (break_state == -1)
+		write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_START_BREAK);
+	else
+		write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_STOP_BREAK);
+}
+
+
+static void sbd_receive_chars(struct sbd_port *sport)
+{
+	struct uart_port *uport = &sport->port;
+	struct uart_icount *icount;
+	unsigned int status, ch, flag;
+	int count;
+
+	for (count = 16; count; count--) {
+		status = read_sbdchn(sport, R_DUART_STATUS);
+		if (!(status & M_DUART_RX_RDY))
+			break;
+
+		ch = read_sbdchn(sport, R_DUART_RX_HOLD);
+
+		flag = TTY_NORMAL;
+
+		icount = &uport->icount;
+		icount->rx++;
+
+		if (unlikely(status &
+			     (M_DUART_RCVD_BRK | M_DUART_FRM_ERR |
+			      M_DUART_PARITY_ERR | M_DUART_OVRUN_ERR))) {
+			if (status & M_DUART_RCVD_BRK) {
+				icount->brk++;
+				if (uart_handle_break(uport))
+					continue;
+			} else if (status & M_DUART_FRM_ERR)
+				icount->frame++;
+			else if (status & M_DUART_PARITY_ERR)
+				icount->parity++;
+			if (status & M_DUART_OVRUN_ERR)
+				icount->overrun++;
+
+			status &= uport->read_status_mask;
+			if (status & M_DUART_RCVD_BRK)
+				flag = TTY_BREAK;
+			else if (status & M_DUART_FRM_ERR)
+				flag = TTY_FRAME;
+			else if (status & M_DUART_PARITY_ERR)
+				flag = TTY_PARITY;
+		}
+
+		if (uart_handle_sysrq_char(uport, ch))
+			continue;
+
+		uart_insert_char(uport, status, M_DUART_OVRUN_ERR, ch, flag);
+	}
+
+	tty_flip_buffer_push(uport->info->tty);
+}
+
+static void sbd_transmit_chars(struct sbd_port *sport)
+{
+	struct uart_port *uport = &sport->port;
+	struct circ_buf *xmit = &sport->port.info->xmit;
+	unsigned int mask;
+	int stop_tx;
+
+	/* XON/XOFF chars.  */
+	if (sport->port.x_char) {
+		write_sbdchn(sport, R_DUART_TX_HOLD, sport->port.x_char);
+		sport->port.icount.tx++;
+		sport->port.x_char = 0;
+		return;
+	}
+
+	/* If nothing to do or stopped or hardware stopped.  */
+	stop_tx = (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port));
+
+	/* Send char.  */
+	if (!stop_tx) {
+		write_sbdchn(sport, R_DUART_TX_HOLD, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		sport->port.icount.tx++;
+
+		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+			uart_write_wakeup(&sport->port);
+	}
+
+	/* Are we are done?  */
+	if (stop_tx || uart_circ_empty(xmit)) {
+		/* Disable tx interrupts.  */
+		mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+		mask &= ~M_DUART_IMR_TX;
+		write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+	}
+}
+
+static void sbd_status_handle(struct sbd_port *sport)
+{
+	struct uart_port *uport = &sport->port;
+	unsigned int delta;
+
+	delta = read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
+	delta >>= (uport->line) % 2;
+
+	if (delta & (M_DUART_IN_PIN0_VAL << S_DUART_IN_PIN_CHNG))
+		uart_handle_cts_change(uport, !(delta & M_DUART_IN_PIN0_VAL));
+
+	if (delta & (M_DUART_IN_PIN2_VAL << S_DUART_IN_PIN_CHNG))
+		uport->icount.dsr++;
+
+	if (delta & ((M_DUART_IN_PIN2_VAL | M_DUART_IN_PIN0_VAL) <<
+		     S_DUART_IN_PIN_CHNG))
+		wake_up_interruptible(&uport->info->delta_msr_wait);
+}
+
+static irqreturn_t sbd_interrupt(int irq, void *dev_id)
+{
+	struct sbd_port *sport = dev_id;
+	struct uart_port *uport = &sport->port;
+	irqreturn_t status = IRQ_NONE;
+	unsigned int intstat;
+	int count;
+
+	for (count = 16; count; count--) {
+		intstat = read_sbdshr(sport,
+				      R_DUART_ISRREG((uport->line) % 2));
+		intstat &= read_sbdshr(sport,
+				       R_DUART_IMRREG((uport->line) % 2));
+		intstat &= M_DUART_ISR_ALL;
+		if (!intstat)
+			break;
+
+		if (intstat & M_DUART_ISR_RX)
+			sbd_receive_chars(sport);
+		if (intstat & M_DUART_ISR_IN)
+			sbd_status_handle(sport);
+		if (intstat & M_DUART_ISR_TX)
+			sbd_transmit_chars(sport);
+
+		status = IRQ_HANDLED;
+	}
+
+	return status;
+}
+
+
+static int sbd_startup(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int mode1;
+	int ret;
+
+	ret = request_irq(sport->port.irq, sbd_interrupt,
+			  IRQF_SHARED, "sb1250-duart", sport);
+	if (ret)
+		return ret;
+
+	/* Clear the receive FIFO.  */
+	sbd_receive_drain(sport);
+
+	/* Clear the interrupt registers.  */
+	write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT);
+	read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
+
+	/* Set rx/tx interrupt to FIFO available.  */
+	mode1 = read_sbdchn(sport, R_DUART_MODE_REG_1);
+	mode1 &= ~(M_DUART_RX_IRQ_SEL_RXFULL | M_DUART_TX_IRQ_SEL_TXEMPT);
+	write_sbdchn(sport, R_DUART_MODE_REG_1, mode1);
+
+	/* Disable tx, enable rx.  */
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_EN);
+	sport->tx_stopped = 1;
+
+	/* Enable interrupts.  */
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
+		     M_DUART_IMR_IN | M_DUART_IMR_RX);
+
+	return 0;
+}
+
+static void sbd_shutdown(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
+	sport->tx_stopped = 1;
+	free_irq(sport->port.irq, sport);
+}
+
+
+static void sbd_init_port(struct sbd_port *sport)
+{
+	struct uart_port *uport = &sport->port;
+
+	if (sport->initialised)
+		return;
+
+	/* There is no DUART reset feature, so just set some sane defaults.  */
+	write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_TX);
+	write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_RX);
+	write_sbdchn(sport, R_DUART_MODE_REG_1, V_DUART_BITS_PER_CHAR_8);
+	write_sbdchn(sport, R_DUART_MODE_REG_2, 0);
+	write_sbdchn(sport, R_DUART_FULL_CTL,
+		     V_DUART_INT_TIME(0) | V_DUART_SIG_FULL(15));
+	write_sbdchn(sport, R_DUART_OPCR_X, 0);
+	write_sbdchn(sport, R_DUART_AUXCTL_X, 0);
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
+
+	sport->initialised = 1;
+}
+
+static void sbd_set_termios(struct uart_port *uport, struct ktermios *termios,
+			    struct ktermios *old_termios)
+{
+	struct sbd_port *sport = to_sport(uport);
+	unsigned int mode1 = 0, mode2 = 0, aux = 0;
+	unsigned int mode1mask = 0, mode2mask = 0, auxmask = 0;
+	unsigned int oldmode1, oldmode2, oldaux;
+	unsigned int baud, brg;
+	unsigned int command;
+
+	mode1mask |= ~(M_DUART_PARITY_MODE | M_DUART_PARITY_TYPE_ODD |
+		       M_DUART_BITS_PER_CHAR);
+	mode2mask |= ~M_DUART_STOP_BIT_LEN_2;
+	auxmask |= ~M_DUART_CTS_CHNG_ENA;
+
+	/* Byte size.  */
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+	case CS6:
+		/* Unsupported, leave unchanged.  */
+		mode1mask |= M_DUART_PARITY_MODE;
+		break;
+	case CS7:
+		mode1 |= V_DUART_BITS_PER_CHAR_7;
+		break;
+	case CS8:
+	default:
+		mode1 |= V_DUART_BITS_PER_CHAR_8;
+		break;
+	}
+
+	/* Parity and stop bits.  */
+	if (termios->c_cflag & CSTOPB)
+		mode2 |= M_DUART_STOP_BIT_LEN_2;
+	else
+		mode2 |= M_DUART_STOP_BIT_LEN_1;
+	if (termios->c_cflag & PARENB)
+		mode1 |= V_DUART_PARITY_MODE_ADD;
+	else
+		mode1 |= V_DUART_PARITY_MODE_NONE;
+	if (termios->c_cflag & PARODD)
+		mode1 |= M_DUART_PARITY_TYPE_ODD;
+	else
+		mode1 |= M_DUART_PARITY_TYPE_EVEN;
+
+	baud = uart_get_baud_rate(uport, termios, old_termios, 1200, 5000000);
+	brg = V_DUART_BAUD_RATE(baud);
+	/* The actual lower bound is 1221bps, so compensate.  */
+	if (brg > M_DUART_CLK_COUNTER)
+		brg = M_DUART_CLK_COUNTER;
+
+	uart_update_timeout(uport, termios->c_cflag, baud);
+
+	uport->read_status_mask = M_DUART_OVRUN_ERR;
+	if (termios->c_iflag & INPCK)
+		uport->read_status_mask |= M_DUART_FRM_ERR |
+					   M_DUART_PARITY_ERR;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		uport->read_status_mask |= M_DUART_RCVD_BRK;
+
+	uport->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		uport->ignore_status_mask |= M_DUART_FRM_ERR |
+					     M_DUART_PARITY_ERR;
+	if (termios->c_iflag & IGNBRK) {
+		uport->ignore_status_mask |= M_DUART_RCVD_BRK;
+		if (termios->c_iflag & IGNPAR)
+			uport->ignore_status_mask |= M_DUART_OVRUN_ERR;
+	}
+
+	if (termios->c_cflag & CREAD)
+		command = M_DUART_RX_EN;
+	else
+		command = M_DUART_RX_DIS;
+
+	if (termios->c_cflag & CRTSCTS)
+		aux |= M_DUART_CTS_CHNG_ENA;
+	else
+		aux &= ~M_DUART_CTS_CHNG_ENA;
+
+	spin_lock(&uport->lock);
+
+	if (sport->tx_stopped)
+		command |= M_DUART_TX_DIS;
+	else
+		command |= M_DUART_TX_EN;
+
+	oldmode1 = read_sbdchn(sport, R_DUART_MODE_REG_1) & mode1mask;
+	oldmode2 = read_sbdchn(sport, R_DUART_MODE_REG_2) & mode2mask;
+	oldaux = read_sbdchn(sport, R_DUART_AUXCTL_X) & auxmask;
+
+	if (!sport->tx_stopped)
+		sbd_line_drain(sport);
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
+
+	write_sbdchn(sport, R_DUART_MODE_REG_1, mode1 | oldmode1);
+	write_sbdchn(sport, R_DUART_MODE_REG_2, mode2 | oldmode2);
+	write_sbdchn(sport, R_DUART_CLK_SEL, brg);
+	write_sbdchn(sport, R_DUART_AUXCTL_X, aux | oldaux);
+
+	write_sbdchn(sport, R_DUART_CMD, command);
+
+	spin_unlock(&uport->lock);
+}
+
+
+static const char *sbd_type(struct uart_port *uport)
+{
+	return "SB1250 DUART";
+}
+
+static void sbd_release_port(struct uart_port *uport)
+{
+	struct sbd_port *sport = to_sport(uport);
+	struct sbd_duart *duart = sport->duart;
+	int map_guard;
+
+	iounmap(sport->memctrl);
+	sport->memctrl = NULL;
+	iounmap(uport->membase);
+	uport->membase = NULL;
+
+	map_guard = atomic_add_return(-1, &duart->map_guard);
+	if (!map_guard)
+		release_mem_region(duart->mapctrl, DUART_CHANREG_SPACING);
+	release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
+}
+
+static int sbd_map_port(struct uart_port *uport)
+{
+	static const char *err = KERN_ERR "sbd: Cannot map MMIO\n";
+	struct sbd_port *sport = to_sport(uport);
+	struct sbd_duart *duart = sport->duart;
+
+	if (!uport->membase)
+		uport->membase = ioremap_nocache(uport->mapbase,
+						 DUART_CHANREG_SPACING);
+	if (!uport->membase) {
+		printk(err);
+		return -ENOMEM;
+	}
+
+	if (!sport->memctrl)
+		sport->memctrl = ioremap_nocache(duart->mapctrl,
+						 DUART_CHANREG_SPACING);
+	if (!sport->memctrl) {
+		printk(err);
+		iounmap(uport->membase);
+		uport->membase = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int sbd_request_port(struct uart_port *uport)
+{
+	static const char *err = KERN_ERR
+				 "sbd: Unable to reserve MMIO resource\n";
+	struct sbd_duart *duart = to_sport(uport)->duart;
+	int map_guard;
+	int ret = 0;
+
+	if (!request_mem_region(uport->mapbase, DUART_CHANREG_SPACING,
+				"sb1250-duart")) {
+		printk(err);
+		return -EBUSY;
+	}
+	map_guard = atomic_add_return(1, &duart->map_guard);
+	if (map_guard == 1) {
+		if (!request_mem_region(duart->mapctrl, DUART_CHANREG_SPACING,
+					"sb1250-duart")) {
+			atomic_add(-1, &duart->map_guard);
+			printk(err);
+			ret = -EBUSY;
+		}
+	}
+	if (!ret) {
+		ret = sbd_map_port(uport);
+		if (ret) {
+			map_guard = atomic_add_return(-1, &duart->map_guard);
+			if (!map_guard)
+				release_mem_region(duart->mapctrl,
+						   DUART_CHANREG_SPACING);
+		}
+	}
+	if (ret) {
+		release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
+		return ret;
+	}
+	return 0;
+}
+
+static void sbd_config_port(struct uart_port *uport, int flags)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	if (flags & UART_CONFIG_TYPE) {
+		if (sbd_request_port(uport))
+			return;
+
+		uport->type = PORT_SB1250_DUART;
+
+		sbd_init_port(sport);
+	}
+}
+
+static int sbd_verify_port(struct uart_port *uport, struct serial_struct *ser)
+{
+	int ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_SB1250_DUART)
+		ret = -EINVAL;
+	if (ser->irq != uport->irq)
+		ret = -EINVAL;
+	if (ser->baud_base != uport->uartclk / 16)
+		ret = -EINVAL;
+	return ret;
+}
+
+
+static struct uart_ops sbd_ops = {
+	.tx_empty	= sbd_tx_empty,
+	.set_mctrl	= sbd_set_mctrl,
+	.get_mctrl	= sbd_get_mctrl,
+	.stop_tx	= sbd_stop_tx,
+	.start_tx	= sbd_start_tx,
+	.stop_rx	= sbd_stop_rx,
+	.enable_ms	= sbd_enable_ms,
+	.break_ctl	= sbd_break_ctl,
+	.startup	= sbd_startup,
+	.shutdown	= sbd_shutdown,
+	.set_termios	= sbd_set_termios,
+	.type		= sbd_type,
+	.release_port	= sbd_release_port,
+	.request_port	= sbd_request_port,
+	.config_port	= sbd_config_port,
+	.verify_port	= sbd_verify_port,
+};
+
+/* Initialize SB1250 DUART port structures.  */
+static void __init sbd_probe_duarts(void)
+{
+	static int probed;
+	int chip, side;
+	int max_lines, line;
+
+	if (probed)
+		return;
+
+	/* Set the number of available units based on the SOC type.  */
+	switch (soc_type) {
+	case K_SYS_SOC_TYPE_BCM1x55:
+	case K_SYS_SOC_TYPE_BCM1x80:
+		max_lines = 4;
+		break;
+	default:
+		/* Assume at least two serial ports at the normal address.  */
+		max_lines = 2;
+		break;
+	}
+
+	probed = 1;
+
+	for (chip = 0, line = 0; chip < DUART_MAX_CHIP && line < max_lines;
+	     chip++) {
+		sbd_duarts[chip].mapctrl = SBD_CTRLREGS(line);
+
+		for (side = 0; side < DUART_MAX_SIDE && line < max_lines;
+		     side++, line++) {
+			struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+			struct uart_port *uport = &sport->port;
+
+			sport->duart	= &sbd_duarts[chip];
+
+			uport->irq	= SBD_INT(line);
+			uport->uartclk	= 100000000 / 20 * 16;
+			uport->fifosize	= 16;
+			uport->iotype	= UPIO_MEM;
+			uport->flags	= UPF_BOOT_AUTOCONF;
+			uport->ops	= &sbd_ops;
+			uport->line	= line;
+			uport->mapbase	= SBD_CHANREGS(line);
+		}
+	}
+}
+
+
+#ifdef CONFIG_SERIAL_SB1250_DUART_CONSOLE
+/*
+ * Serial console stuff.  Very basic, polling driver for doing serial
+ * console output.  The console_sem is held by the caller, so we
+ * shouldn't be interrupted for more console activity.
+ */
+static void sbd_console_putchar(struct uart_port *uport, int ch)
+{
+	struct sbd_port *sport = to_sport(uport);
+
+	sbd_transmit_drain(sport);
+	write_sbdchn(sport, R_DUART_TX_HOLD, ch);
+}
+
+static void sbd_console_write(struct console *co, const char *s,
+			      unsigned int count)
+{
+	int chip = co->index / DUART_MAX_SIDE;
+	int side = co->index % DUART_MAX_SIDE;
+	struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+	struct uart_port *uport = &sport->port;
+	unsigned long flags;
+	unsigned int mask;
+
+	/* Disable transmit interrupts and enable the transmitter. */
+	spin_lock_irqsave(&uport->lock, flags);
+	mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
+		     mask & ~M_DUART_IMR_TX);
+	write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
+	spin_unlock_irqrestore(&uport->lock, flags);
+
+	uart_console_write(&sport->port, s, count, sbd_console_putchar);
+
+	/* Restore transmit interrupts and the transmitter enable. */
+	spin_lock_irqsave(&uport->lock, flags);
+	sbd_line_drain(sport);
+	if (sport->tx_stopped)
+		write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
+	write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+	spin_unlock_irqrestore(&uport->lock, flags);
+}
+
+static int __init sbd_console_setup(struct console *co, char *options)
+{
+	int chip = co->index / DUART_MAX_SIDE;
+	int side = co->index % DUART_MAX_SIDE;
+	struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+	struct uart_port *uport = &sport->port;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+	int ret;
+
+	if (!sport->duart)
+		return -ENXIO;
+
+	ret = sbd_map_port(uport);
+	if (ret)
+		return ret;
+
+	sbd_init_port(sport);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	return uart_set_options(uport, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver sbd_reg;
+static struct console sbd_console = {
+	.name	= "duart",
+	.write	= sbd_console_write,
+	.device	= uart_console_device,
+	.setup	= sbd_console_setup,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+	.data	= &sbd_reg
+};
+
+static int __init sbd_serial_console_init(void)
+{
+	sbd_probe_duarts();
+	register_console(&sbd_console);
+
+	return 0;
+}
+
+console_initcall(sbd_serial_console_init);
+
+#define SERIAL_SB1250_DUART_CONSOLE	&sbd_console
+#else
+#define SERIAL_SB1250_DUART_CONSOLE	NULL
+#endif /* CONFIG_SERIAL_SB1250_DUART_CONSOLE */
+
+
+static struct uart_driver sbd_reg = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "serial",
+	.dev_name	= "duart",
+	.major		= TTY_MAJOR,
+	.minor		= SB1250_DUART_MINOR_BASE,
+	.nr		= DUART_MAX_CHIP * DUART_MAX_SIDE,
+	.cons		= SERIAL_SB1250_DUART_CONSOLE,
+};
+
+/* Set up the driver and register it.  */
+static int __init sbd_init(void)
+{
+	int i, ret;
+
+	sbd_probe_duarts();
+
+	ret = uart_register_driver(&sbd_reg);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < DUART_MAX_CHIP * DUART_MAX_SIDE; i++) {
+		struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
+		struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
+		struct uart_port *uport = &sport->port;
+
+		if (sport->duart)
+			uart_add_one_port(&sbd_reg, uport);
+	}
+
+	return 0;
+}
+
+/* Unload the driver.  Unregister stuff, get ready to go away.  */
+static void __exit sbd_exit(void)
+{
+	int i;
+
+	for (i = DUART_MAX_CHIP * DUART_MAX_SIDE - 1; i >= 0; i--) {
+		struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
+		struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
+		struct uart_port *uport = &sport->port;
+
+		if (sport->duart)
+			uart_remove_one_port(&sbd_reg, uport);
+	}
+
+	uart_unregister_driver(&sbd_reg);
+}
+
+module_init(sbd_init);
+module_exit(sbd_exit);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 326020f..9c57486 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1910,6 +1910,12 @@
 	if (flow == 'r')
 		termios.c_cflag |= CRTSCTS;
 
+	/*
+	 * some uarts on other side don't support no flow control.
+	 * So we set * DTR in host uart to make them happy
+	 */
+	port->mctrl |= TIOCM_DTR;
+
 	port->ops->set_termios(port, &termios, NULL);
 	co->cflag = termios.c_cflag;
 
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 6b76bab..a0ea435 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -842,12 +842,16 @@
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
+	PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+	PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
+	PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
+	PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
 	PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
 	PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
 	PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c
index c5346d6..8721afe 100644
--- a/drivers/serial/serial_ks8695.c
+++ b/drivers/serial/serial_ks8695.c
@@ -301,11 +301,11 @@
 
 	retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, IRQF_DISABLED, "UART LineStatus", port);
 	if (retval)
-		return err_ls;
+		goto err_ls;
 
 	retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, IRQF_DISABLED, "UART ModemStatus", port);
 	if (retval)
-		return err_ms;
+		goto err_ms;
 
 	return 0;
 
@@ -589,7 +589,7 @@
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver ks8695_reg;
+static struct uart_driver ks8695_reg;
 
 static struct console ks8695_console = {
 	.name		= SERIAL_KS8695_DEVNAME,
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 1f89496..672cd10 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -367,7 +367,9 @@
 	} else {
 #ifdef CONFIG_CPU_SUBTYPE_SH7343
 		/* Nothing */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+      defined(CONFIG_CPU_SUBTYPE_SHX3)
 		ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
 #else
 		ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index fb04fb5..247fb66 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -53,7 +53,12 @@
 # define SCIF_ORER 0x0001   /* overrun error bit */
 # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7091)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751R)
 # define SCSPTR1 0xffe0001c /* 8  bit SCI */
 # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
@@ -73,7 +78,7 @@
 # define SCPDR  0xA4050136        /* 16 bit SCIF */
 # define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) 
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
 # define SCSPTR0 0xA4400000	  /* 16 bit SCIF */
 # define SCI_NPORTS 2
 # define SCIF_ORER 0x0001   /* overrun error bit */
@@ -168,6 +173,14 @@
 # define SCIF_ORER 0x0001  /* overrun error bit */
 # define SCSCR_INIT(port)	0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+# define SCSPTR0 0xffc30020		/* 16 bit SCIF */
+# define SCSPTR1 0xffc40020		/* 16 bit SCIF */
+# define SCSPTR2 0xffc50020		/* 16 bit SCIF */
+# define SCSPTR3 0xffc60020		/* 16 bit SCIF */
+# define SCIF_ORER 0x0001		/* Overrun error bit */
+# define SCSCR_INIT(port)	0x38	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
 #else
 # error CPU subtype not defined
 #endif
@@ -177,10 +190,15 @@
 #define SCI_CTRL_FLAGS_RIE  0x40 /* all */
 #define SCI_CTRL_FLAGS_TE   0x20 /* all */
 #define SCI_CTRL_FLAGS_RE   0x10 /* all */
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7751) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785)
+#if defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7091)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7780)  || \
+    defined(CONFIG_CPU_SUBTYPE_SH7785)  || \
+    defined(CONFIG_CPU_SUBTYPE_SHX3)
 #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
 #else
 #define SCI_CTRL_FLAGS_REIE 0
@@ -514,8 +532,12 @@
 	}
 }
 
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7091)  || \
       defined(CONFIG_CPU_SUBTYPE_SH4_202)
 static inline int sci_rxd_in(struct uart_port *port)
 {
@@ -653,6 +675,18 @@
 		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
 	return 1;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+	if (port->mapbase == 0xffc30000)
+		return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xffc40000)
+		return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xffc50000)
+		return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+	if (port->mapbase == 0xffc60000)
+		return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+}
 #endif
 
 /*
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index a27e9e9..41fc6126 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -759,7 +759,7 @@
  */
 
 static void sn_sal_console_write(struct console *, const char *, unsigned);
-static int __init sn_sal_console_setup(struct console *, char *);
+static int sn_sal_console_setup(struct console *, char *);
 static struct uart_driver sal_console_uart;
 extern struct tty_driver *uart_console_device(struct console *, int *);
 
@@ -1006,7 +1006,7 @@
  * here so providing it is easier.
  *
  */
-static int __init sn_sal_console_setup(struct console *co, char *options)
+static int sn_sal_console_setup(struct console *co, char *options)
 {
 	return 0;
 }
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index e35d9ab..b45ba53 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -30,9 +30,9 @@
 sunserial_console_termios(struct console *con)
 {
 	char mode[16], buf[16], *s;
-	char *mode_prop = "ttyX-mode";
-	char *cd_prop = "ttyX-ignore-cd";
-	char *dtr_prop = "ttyX-rts-dtr-off";
+	char mode_prop[] = "ttyX-mode";
+	char cd_prop[]   = "ttyX-ignore-cd";
+	char dtr_prop[]  = "ttyX-rts-dtr-off";
 	char *ssp_console_modes_prop = "ssp-console-modes";
 	int baud, bits, stop, cflag;
 	char parity;
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 96557e6..d82be42 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -258,17 +258,7 @@
 /* port->lock held by caller.  */
 static void sunhv_start_tx(struct uart_port *port)
 {
-	struct circ_buf *xmit = &port->info->xmit;
-
-	while (!uart_circ_empty(xmit)) {
-		long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
-
-		if (status != HV_EOK)
-			break;
-
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		port->icount.tx++;
-	}
+	transmit_chars(port);
 }
 
 /* port->lock is not held.  */
@@ -440,8 +430,16 @@
 {
 	struct uart_port *port = sunhv_port;
 	unsigned long flags;
+	int locked = 1;
 
-	spin_lock_irqsave(&port->lock, flags);
+	local_irq_save(flags);
+	if (port->sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&port->lock);
+	} else
+		spin_lock(&port->lock);
+
 	while (n > 0) {
 		unsigned long ra = __pa(con_write_page);
 		unsigned long page_bytes;
@@ -469,7 +467,10 @@
 			ra += written;
 		}
 	}
-	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
 }
 
 static inline void sunhv_console_putchar(struct uart_port *port, char c)
@@ -488,7 +489,15 @@
 {
 	struct uart_port *port = sunhv_port;
 	unsigned long flags;
-	int i;
+	int i, locked = 1;
+
+	local_irq_save(flags);
+	if (port->sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&port->lock);
+	} else
+		spin_lock(&port->lock);
 
 	spin_lock_irqsave(&port->lock, flags);
 	for (i = 0; i < n; i++) {
@@ -496,7 +505,10 @@
 			sunhv_console_putchar(port, '\r');
 		sunhv_console_putchar(port, *s++);
 	}
-	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
 }
 
 static struct console sunhv_console = {
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index deb9ab4..8a0f9e4 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -860,22 +860,31 @@
 static void sunsab_console_putchar(struct uart_port *port, int c)
 {
 	struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
 
 	sunsab_tec_wait(up);
 	writeb(c, &up->regs->w.tic);
-
-	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static void sunsab_console_write(struct console *con, const char *s, unsigned n)
 {
 	struct uart_sunsab_port *up = &sunsab_ports[con->index];
+	unsigned long flags;
+	int locked = 1;
+
+	local_irq_save(flags);
+	if (up->port.sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&up->port.lock);
+	} else
+		spin_lock(&up->port.lock);
 
 	uart_console_write(&up->port, s, n, sunsab_console_putchar);
 	sunsab_tec_wait(up);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
 }
 
 static int sunsab_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 2a63cdb..26d720b 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1288,7 +1288,17 @@
 				unsigned int count)
 {
 	struct uart_sunsu_port *up = &sunsu_ports[co->index];
+	unsigned long flags;
 	unsigned int ier;
+	int locked = 1;
+
+	local_irq_save(flags);
+	if (up->port.sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&up->port.lock);
+	} else
+		spin_lock(&up->port.lock);
 
 	/*
 	 *	First save the UER then disable the interrupts
@@ -1304,6 +1314,10 @@
 	 */
 	wait_for_xmitr(up);
 	serial_out(up, UART_IER, ier);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
 }
 
 /*
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 0985193..0a3e10a 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -9,7 +9,7 @@
  * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
  * work there.
  *
- *  Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/module.h>
@@ -1151,11 +1151,22 @@
 {
 	struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
 	unsigned long flags;
+	int locked = 1;
 
-	spin_lock_irqsave(&up->port.lock, flags);
+	local_irq_save(flags);
+	if (up->port.sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&up->port.lock);
+	} else
+		spin_lock(&up->port.lock);
+
 	uart_console_write(&up->port, s, count, sunzilog_putchar);
 	udelay(2);
-	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
 }
 
 static int __init sunzilog_console_setup(struct console *con, char *options)
@@ -1239,7 +1250,7 @@
 #define SUNZILOG_CONSOLE()	(NULL)
 #endif
 
-static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel)
+static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel)
 {
 	int baud, brg;
 
@@ -1259,7 +1270,7 @@
 }
 
 #ifdef CONFIG_SERIO
-static void __init sunzilog_register_serio(struct uart_sunzilog_port *up)
+static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
 {
 	struct serio *serio = &up->serio;
 
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index cf0e663..85309ac 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -1,7 +1,7 @@
 /*
  *  Driver for NEC VR4100 series Serial Interface Unit.
  *
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  *
  *  Based on drivers/serial/8250.c, by Russell King.
  *
@@ -25,12 +25,12 @@
 #endif
 
 #include <linux/console.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/ioport.h>
+#include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
@@ -38,11 +38,9 @@
 #include <linux/tty_flip.h>
 
 #include <asm/io.h>
-#include <asm/vr41xx/irq.h>
 #include <asm/vr41xx/siu.h>
 #include <asm/vr41xx/vr41xx.h>
 
-#define SIU_PORTS_MAX	2
 #define SIU_BAUD_BASE	1152000
 #define SIU_MAJOR	204
 #define SIU_MINOR_BASE	82
@@ -60,32 +58,13 @@
  #define IRUSESEL	0x02
  #define SIRSEL		0x01
 
-struct siu_port {
-	unsigned int type;
-	unsigned int irq;
-	unsigned long start;
+static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = {
+	[0 ... SIU_PORTS_MAX-1] = {
+		.lock	= __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock),
+		.irq	= -1,
+	},
 };
 
-static const struct siu_port siu_type1_ports[] = {
-	{	.type		= PORT_VR41XX_SIU,
-		.irq		= SIU_IRQ,
-		.start		= 0x0c000000UL,		},
-};
-
-#define SIU_TYPE1_NR_PORTS	(sizeof(siu_type1_ports) / sizeof(struct siu_port))
-
-static const struct siu_port siu_type2_ports[] = {
-	{	.type		= PORT_VR41XX_SIU,
-		.irq		= SIU_IRQ,
-		.start		= 0x0f000800UL,		},
-	{	.type		= PORT_VR41XX_DSIU,
-		.irq		= DSIU_IRQ,
-		.start		= 0x0f000820UL,		},
-};
-
-#define SIU_TYPE2_NR_PORTS	(sizeof(siu_type2_ports) / sizeof(struct siu_port))
-
-static struct uart_port siu_uart_ports[SIU_PORTS_MAX];
 static uint8_t lsr_break_flag[SIU_PORTS_MAX];
 
 #define siu_read(port, offset)		readb((port)->membase + (offset))
@@ -110,7 +89,6 @@
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface);
 
 void vr41xx_use_irda(irda_use_t use)
@@ -132,7 +110,6 @@
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_use_irda);
 
 void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
@@ -166,7 +143,6 @@
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
-
 EXPORT_SYMBOL_GPL(vr41xx_select_irda_module);
 
 static inline void siu_clear_fifo(struct uart_port *port)
@@ -177,21 +153,6 @@
 	siu_write(port, UART_FCR, 0);
 }
 
-static inline int siu_probe_ports(void)
-{
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		return SIU_TYPE1_NR_PORTS;
-	case CPU_VR4122:
-	case CPU_VR4131:
-	case CPU_VR4133:
-		return SIU_TYPE2_NR_PORTS;
-	}
-
-	return 0;
-}
-
 static inline unsigned long siu_port_size(struct uart_port *port)
 {
 	switch (port->type) {
@@ -206,21 +167,10 @@
 
 static inline unsigned int siu_check_type(struct uart_port *port)
 {
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		if (port->line == 0)
-			return PORT_VR41XX_SIU;
-		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-	case CPU_VR4133:
-		if (port->line == 0)
-			return PORT_VR41XX_SIU;
-		else if (port->line == 1)
-			return PORT_VR41XX_DSIU;
-		break;
-	}
+	if (port->line == 0)
+		return PORT_VR41XX_SIU;
+	if (port->line == 1 && port->irq != -1)
+		return PORT_VR41XX_DSIU;
 
 	return PORT_UNKNOWN;
 }
@@ -751,44 +701,34 @@
 	.verify_port	= siu_verify_port,
 };
 
-static int siu_init_ports(void)
+static int siu_init_ports(struct platform_device *pdev)
 {
-	const struct siu_port *siu;
 	struct uart_port *port;
-	int i, num;
+	struct resource *res;
+	int *type = pdev->dev.platform_data;
+	int i;
 
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		siu = siu_type1_ports;
-		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-	case CPU_VR4133:
-		siu = siu_type2_ports;
-		break;
-	default:
+	if (!type)
 		return 0;
-	}
 
 	port = siu_uart_ports;
-	num = siu_probe_ports();
-	for (i = 0; i < num; i++) {
-		spin_lock_init(&port->lock);
-		port->irq = siu->irq;
+	for (i = 0; i < SIU_PORTS_MAX; i++) {
+		port->type = type[i];
+		if (port->type == PORT_UNKNOWN)
+			continue;
+		port->irq = platform_get_irq(pdev, i);
 		port->uartclk = SIU_BAUD_BASE * 16;
 		port->fifosize = 16;
 		port->regshift = 0;
 		port->iotype = UPIO_MEM;
 		port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-		port->type = siu->type;
 		port->line = i;
-		port->mapbase = siu->start;
-		siu++;
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		port->mapbase = res->start;
 		port++;
 	}
 
-	return num;
+	return i;
 }
 
 #ifdef CONFIG_SERIAL_VR41XX_CONSOLE
@@ -883,13 +823,9 @@
 static int __devinit siu_console_init(void)
 {
 	struct uart_port *port;
-	int num, i;
+	int i;
 
-	num = siu_init_ports();
-	if (num <= 0)
-		return -ENODEV;
-
-	for (i = 0; i < num; i++) {
+	for (i = 0; i < SIU_PORTS_MAX; i++) {
 		port = &siu_uart_ports[i];
 		port->ops = &siu_uart_ops;
 	}
@@ -920,7 +856,7 @@
 	struct uart_port *port;
 	int num, i, retval;
 
-	num = siu_init_ports();
+	num = siu_init_ports(dev);
 	if (num <= 0)
 		return -ENODEV;
 
@@ -998,8 +934,6 @@
 	return 0;
 }
 
-static struct platform_device *siu_platform_device;
-
 static struct platform_driver siu_device_driver = {
 	.probe		= siu_probe,
 	.remove		= __devexit_p(siu_remove),
@@ -1013,29 +947,12 @@
 
 static int __init vr41xx_siu_init(void)
 {
-	int retval;
-
-	siu_platform_device = platform_device_alloc("SIU", -1);
-	if (!siu_platform_device)
-		return -ENOMEM;
-
-	retval = platform_device_add(siu_platform_device);
-	if (retval < 0) {
-		platform_device_put(siu_platform_device);
-		return retval;
-	}
-
-	retval = platform_driver_register(&siu_device_driver);
-	if (retval < 0)
-		platform_device_unregister(siu_platform_device);
-
-	return retval;
+	return platform_driver_register(&siu_device_driver);
 }
 
 static void __exit vr41xx_siu_exit(void)
 {
 	platform_driver_unregister(&siu_device_driver);
-	platform_device_unregister(siu_platform_device);
 }
 
 module_init(vr41xx_siu_init);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5e3f748..b915711 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -107,6 +107,15 @@
 	  This enables using the Freescale iMX SPI controller in master
 	  mode.
 
+config SPI_LM70_LLP
+	tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
+	depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+	select SPI_BITBANG
+	help
+	  This driver supports the NS LM70 LLP Evaluation Board,
+	  which interfaces to an LM70 temperature sensor using
+	  a parallel port.
+
 config SPI_MPC52xx_PSC
 	tristate "Freescale MPC52xx PSC SPI controller"
 	depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
@@ -133,6 +142,12 @@
 	help
 	  This hooks up to the MicroWire controller on OMAP1 chips.
 
+config SPI_OMAP24XX
+	tristate "McSPI driver for OMAP24xx"
+	depends on SPI_MASTER && ARCH_OMAP24XX
+	help
+	  SPI master controller for OMAP24xx Multichannel SPI
+	  (McSPI) modules.
 
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
@@ -145,17 +160,36 @@
 config SPI_S3C24XX
 	tristate "Samsung S3C24XX series SPI"
 	depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+	select SPI_BITBANG
 	help
 	  SPI driver for Samsung S3C24XX series ARM SoCs
 
 config SPI_S3C24XX_GPIO
 	tristate "Samsung S3C24XX series SPI by GPIO"
-	depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL
+	depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+	select SPI_BITBANG
 	help
 	  SPI driver for Samsung S3C24XX series ARM SoCs using
 	  GPIO lines to provide the SPI bus. This can be used where
 	  the inbuilt hardware cannot provide the transfer mode, or
 	  where the board is using non hardware connected pins.
+
+config SPI_TXX9
+	tristate "Toshiba TXx9 SPI controller"
+	depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
+	help
+	  SPI driver for Toshiba TXx9 MIPS SoCs
+
+config SPI_XILINX
+	tristate "Xilinx SPI controller"
+	depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
+	select SPI_BITBANG
+	help
+	  This exposes the SPI controller IP from the Xilinx EDK.
+
+	  See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
+	  Product Specification document (DS464) for hardware details.
+
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
@@ -187,6 +221,15 @@
 	  Note that this application programming interface is EXPERIMENTAL
 	  and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes.
 
+config SPI_TLE62X0
+	tristate "Infineon TLE62X0 (for power switching)"
+	depends on SPI_MASTER && SYSFS
+	help
+	  SPI driver for Infineon TLE62X0 series line driver chips,
+	  such as the TLE6220, TLE6230 and TLE6240.  This provides a
+	  sysfs interface, with each line presented as a kind of GPIO
+	  exposing both switch control and diagnostic feedback.
+
 #
 # Add new SPI protocol masters in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 5788d86..41fbac4 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,17 +17,22 @@
 obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
 obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
+obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
+obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC83xx)		+= spi_mpc83xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o
+obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
+obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
 # 	... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
 obj-$(CONFIG_SPI_AT25)		+= at25.o
 obj-$(CONFIG_SPI_SPIDEV)	+= spidev.o
+obj-$(CONFIG_SPI_TLE62X0)	+= tle62x0.o
 # 	... add above this line ...
 
 # SPI slave controller drivers (upstream link)
diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c
index 8efa07e..e007833 100644
--- a/drivers/spi/at25.c
+++ b/drivers/spi/at25.c
@@ -111,7 +111,8 @@
 }
 
 static ssize_t
-at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+	      char *buf, loff_t off, size_t count)
 {
 	struct device		*dev;
 	struct at25_data	*at25;
@@ -236,7 +237,8 @@
 }
 
 static ssize_t
-at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+	       char *buf, loff_t off, size_t count)
 {
 	struct device		*dev;
 	struct at25_data	*at25;
@@ -314,7 +316,6 @@
 	 */
 	at25->bin.attr.name = "eeprom";
 	at25->bin.attr.mode = S_IRUSR;
-	at25->bin.attr.owner = THIS_MODULE;
 	at25->bin.read = at25_bin_read;
 
 	at25->bin.size = at25->chip.byte_len;
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 1d8a2f6..ad14405 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -46,6 +46,7 @@
 	struct clk		*clk;
 	struct platform_device	*pdev;
 	unsigned		new_1:1;
+	struct spi_device	*stay;
 
 	u8			stopping;
 	struct list_head	queue;
@@ -62,29 +63,62 @@
 /*
  * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
  * they assume that spi slave device state will not change on deselect, so
- * that automagic deselection is OK.  Not so!  Workaround uses nCSx pins
- * as GPIOs; or newer controllers have CSAAT and friends.
+ * that automagic deselection is OK.  ("NPCSx rises if no data is to be
+ * transmitted")  Not so!  Workaround uses nCSx pins as GPIOs; or newer
+ * controllers have CSAAT and friends.
  *
- * Since the CSAAT functionality is a bit weird on newer controllers
- * as well, we use GPIO to control nCSx pins on all controllers.
+ * Since the CSAAT functionality is a bit weird on newer controllers as
+ * well, we use GPIO to control nCSx pins on all controllers, updating
+ * MR.PCS to avoid confusing the controller.  Using GPIOs also lets us
+ * support active-high chipselects despite the controller's belief that
+ * only active-low devices/systems exists.
+ *
+ * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
+ * right when driven with GPIO.  ("Mode Fault does not allow more than one
+ * Master on Chip Select 0.")  No workaround exists for that ... so for
+ * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
+ * and (c) will trigger that first erratum in some cases.
  */
 
-static inline void cs_activate(struct spi_device *spi)
+static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 {
 	unsigned gpio = (unsigned) spi->controller_data;
 	unsigned active = spi->mode & SPI_CS_HIGH;
+	u32 mr;
 
-	dev_dbg(&spi->dev, "activate %u%s\n", gpio, active ? " (high)" : "");
-	gpio_set_value(gpio, active);
+	mr = spi_readl(as, MR);
+	mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
+
+	dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
+			gpio, active ? " (high)" : "",
+			mr);
+
+	if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
+		gpio_set_value(gpio, active);
+	spi_writel(as, MR, mr);
 }
 
-static inline void cs_deactivate(struct spi_device *spi)
+static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 {
 	unsigned gpio = (unsigned) spi->controller_data;
 	unsigned active = spi->mode & SPI_CS_HIGH;
+	u32 mr;
 
-	dev_dbg(&spi->dev, "DEactivate %u%s\n", gpio, active ? " (low)" : "");
-	gpio_set_value(gpio, !active);
+	/* only deactivate *this* device; sometimes transfers to
+	 * another device may be active when this routine is called.
+	 */
+	mr = spi_readl(as, MR);
+	if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) {
+		mr = SPI_BFINS(PCS, 0xf, mr);
+		spi_writel(as, MR, mr);
+	}
+
+	dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
+			gpio, active ? " (low)" : "",
+			mr);
+
+	if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
+		gpio_set_value(gpio, !active);
 }
 
 /*
@@ -113,16 +147,16 @@
 
 	len = as->remaining_bytes;
 
-	tx_dma = xfer->tx_dma;
-	rx_dma = xfer->rx_dma;
+	tx_dma = xfer->tx_dma + xfer->len - len;
+	rx_dma = xfer->rx_dma + xfer->len - len;
 
 	/* use scratch buffer only when rx or tx data is unspecified */
-	if (rx_dma == INVALID_DMA_ADDRESS) {
+	if (!xfer->rx_buf) {
 		rx_dma = as->buffer_dma;
 		if (len > BUFFER_SIZE)
 			len = BUFFER_SIZE;
 	}
-	if (tx_dma == INVALID_DMA_ADDRESS) {
+	if (!xfer->tx_buf) {
 		tx_dma = as->buffer_dma;
 		if (len > BUFFER_SIZE)
 			len = BUFFER_SIZE;
@@ -140,6 +174,7 @@
 
 	/* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer"
 	 * mechanism might help avoid the IRQ latency between transfers
+	 * (and improve the nCS0 errata handling on at91rm9200 chips)
 	 *
 	 * We're also waiting for ENDRX before we start the next
 	 * transfer because we need to handle some difficult timing
@@ -169,33 +204,62 @@
 {
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 	struct spi_message	*msg;
-	u32			mr;
+	struct spi_device	*spi;
 
 	BUG_ON(as->current_transfer);
 
 	msg = list_entry(as->queue.next, struct spi_message, queue);
+	spi = msg->spi;
 
-	/* Select the chip */
-	mr = spi_readl(as, MR);
-	mr = SPI_BFINS(PCS, ~(1 << msg->spi->chip_select), mr);
-	spi_writel(as, MR, mr);
-	cs_activate(msg->spi);
+	dev_dbg(master->cdev.dev, "start message %p for %s\n",
+			msg, spi->dev.bus_id);
+
+	/* select chip if it's not still active */
+	if (as->stay) {
+		if (as->stay != spi) {
+			cs_deactivate(as, as->stay);
+			cs_activate(as, spi);
+		}
+		as->stay = NULL;
+	} else
+		cs_activate(as, spi);
 
 	atmel_spi_next_xfer(master, msg);
 }
 
-static void
+/*
+ * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
+ *  - The buffer is either valid for CPU access, else NULL
+ *  - If the buffer is valid, so is its DMA addresss
+ *
+ * This driver manages the dma addresss unless message->is_dma_mapped.
+ */
+static int
 atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
 {
+	struct device	*dev = &as->pdev->dev;
+
 	xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
-	if (xfer->tx_buf)
-		xfer->tx_dma = dma_map_single(&as->pdev->dev,
+	if (xfer->tx_buf) {
+		xfer->tx_dma = dma_map_single(dev,
 				(void *) xfer->tx_buf, xfer->len,
 				DMA_TO_DEVICE);
-	if (xfer->rx_buf)
-		xfer->rx_dma = dma_map_single(&as->pdev->dev,
+		if (dma_mapping_error(xfer->tx_dma))
+			return -ENOMEM;
+	}
+	if (xfer->rx_buf) {
+		xfer->rx_dma = dma_map_single(dev,
 				xfer->rx_buf, xfer->len,
 				DMA_FROM_DEVICE);
+		if (dma_mapping_error(xfer->tx_dma)) {
+			if (xfer->tx_buf)
+				dma_unmap_single(dev,
+						xfer->tx_dma, xfer->len,
+						DMA_TO_DEVICE);
+			return -ENOMEM;
+		}
+	}
+	return 0;
 }
 
 static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
@@ -211,9 +275,13 @@
 
 static void
 atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
-		   struct spi_message *msg, int status)
+		struct spi_message *msg, int status, int stay)
 {
-	cs_deactivate(msg->spi);
+	if (!stay || status < 0)
+		cs_deactivate(as, msg->spi);
+	else
+		as->stay = msg->spi;
+
 	list_del(&msg->queue);
 	msg->status = status;
 
@@ -303,7 +371,7 @@
 		/* Clear any overrun happening while cleaning up */
 		spi_readl(as, SR);
 
-		atmel_spi_msg_done(master, as, msg, -EIO);
+		atmel_spi_msg_done(master, as, msg, -EIO, 0);
 	} else if (pending & SPI_BIT(ENDRX)) {
 		ret = IRQ_HANDLED;
 
@@ -321,12 +389,13 @@
 
 			if (msg->transfers.prev == &xfer->transfer_list) {
 				/* report completed message */
-				atmel_spi_msg_done(master, as, msg, 0);
+				atmel_spi_msg_done(master, as, msg, 0,
+						xfer->cs_change);
 			} else {
 				if (xfer->cs_change) {
-					cs_deactivate(msg->spi);
+					cs_deactivate(as, msg->spi);
 					udelay(1);
-					cs_activate(msg->spi);
+					cs_activate(as, msg->spi);
 				}
 
 				/*
@@ -350,6 +419,7 @@
 	return ret;
 }
 
+/* the spi->mode bits understood by this driver: */
 #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
 
 static int atmel_spi_setup(struct spi_device *spi)
@@ -388,6 +458,14 @@
 		return -EINVAL;
 	}
 
+	/* see notes above re chipselect */
+	if (cpu_is_at91rm9200()
+			&& spi->chip_select == 0
+			&& (spi->mode & SPI_CS_HIGH)) {
+		dev_dbg(&spi->dev, "setup: can't be active-high\n");
+		return -EINVAL;
+	}
+
 	/* speed zero convention is used by some upper layers */
 	bus_hz = clk_get_rate(as->clk);
 	if (spi->max_speed_hz) {
@@ -397,8 +475,9 @@
 		scbr = ((bus_hz + spi->max_speed_hz - 1)
 			/ spi->max_speed_hz);
 		if (scbr >= (1 << SPI_SCBR_SIZE)) {
-			dev_dbg(&spi->dev, "setup: %d Hz too slow, scbr %u\n",
-					spi->max_speed_hz, scbr);
+			dev_dbg(&spi->dev,
+				"setup: %d Hz too slow, scbr %u; min %ld Hz\n",
+				spi->max_speed_hz, scbr, bus_hz/255);
 			return -EINVAL;
 		}
 	} else
@@ -423,6 +502,14 @@
 			return ret;
 		spi->controller_state = (void *)npcs_pin;
 		gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
+	} else {
+		unsigned long		flags;
+
+		spin_lock_irqsave(&as->lock, flags);
+		if (as->stay == spi)
+			as->stay = NULL;
+		cs_deactivate(as, spi);
+		spin_unlock_irqrestore(&as->lock, flags);
 	}
 
 	dev_dbg(&spi->dev,
@@ -464,14 +551,22 @@
 			dev_dbg(&spi->dev, "no protocol options yet\n");
 			return -ENOPROTOOPT;
 		}
+
+		/*
+		 * DMA map early, for performance (empties dcache ASAP) and
+		 * better fault reporting.  This is a DMA-only driver.
+		 *
+		 * NOTE that if dma_unmap_single() ever starts to do work on
+		 * platforms supported by this driver, we would need to clean
+		 * up mappings for previously-mapped transfers.
+		 */
+		if (!msg->is_dma_mapped) {
+			if (atmel_spi_dma_map_xfer(as, xfer) < 0)
+				return -ENOMEM;
+		}
 	}
 
-	/* scrub dcache "early" */
-	if (!msg->is_dma_mapped) {
-		list_for_each_entry(xfer, &msg->transfers, transfer_list)
-			atmel_spi_dma_map_xfer(as, xfer);
-	}
-
+#ifdef VERBOSE
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		dev_dbg(controller,
 			"  xfer %p: len %u tx %p/%08x rx %p/%08x\n",
@@ -479,6 +574,7 @@
 			xfer->tx_buf, xfer->tx_dma,
 			xfer->rx_buf, xfer->rx_dma);
 	}
+#endif
 
 	msg->status = -EINPROGRESS;
 	msg->actual_length = 0;
@@ -494,8 +590,21 @@
 
 static void atmel_spi_cleanup(struct spi_device *spi)
 {
-	if (spi->controller_state)
-		gpio_free((unsigned int)spi->controller_data);
+	struct atmel_spi	*as = spi_master_get_devdata(spi->master);
+	unsigned		gpio = (unsigned) spi->controller_data;
+	unsigned long		flags;
+
+	if (!spi->controller_state)
+		return;
+
+	spin_lock_irqsave(&as->lock, flags);
+	if (as->stay == spi) {
+		as->stay = NULL;
+		cs_deactivate(as, spi);
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+
+	gpio_free(gpio);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -536,6 +645,10 @@
 
 	as = spi_master_get_devdata(master);
 
+	/*
+	 * Scratch buffer is used for throwaway rx and tx data.
+	 * It's coherent to minimize dcache pollution.
+	 */
 	as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
 					&as->buffer_dma, GFP_KERNEL);
 	if (!as->buffer)
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
index ae2b1af..c47a650 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/au1550_spi.c
@@ -280,6 +280,9 @@
 	return 0;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
 static int au1550_spi_setup(struct spi_device *spi)
 {
 	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
@@ -292,6 +295,12 @@
 		return -EINVAL;
 	}
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	if (spi->max_speed_hz == 0)
 		spi->max_speed_hz = hw->freq_max;
 	if (spi->max_speed_hz > hw->freq_max
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 052359f..d2a4b2b 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -270,6 +270,9 @@
 	spin_unlock_irq(&mps->lock);
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
 static int mpc52xx_psc_spi_setup(struct spi_device *spi)
 {
 	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
@@ -279,6 +282,12 @@
 	if (spi->bits_per_word%8)
 		return -EINVAL;
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	if (!cs) {
 		cs = kzalloc(sizeof *cs, GFP_KERNEL);
 		if (!cs)
@@ -329,8 +338,8 @@
 	int ret = 0;
 
 #if defined(CONFIG_PPC_MERGE)
-	cdm = mpc52xx_find_and_map("mpc52xx-cdm");
-	gpio = mpc52xx_find_and_map("mpc52xx-gpio");
+	cdm = mpc52xx_find_and_map("mpc5200-cdm");
+	gpio = mpc52xx_find_and_map("mpc5200-gpio");
 #else
 	cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
 	gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
@@ -445,9 +454,6 @@
 	struct spi_master *master;
 	int ret;
 
-	if (pdata == NULL)
-		return -ENODEV;
-
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
 		return -ENOMEM;
@@ -594,17 +600,17 @@
 	}
 	regaddr64 = of_translate_address(op->node, regaddr_p);
 
+	/* get PSC id (1..6, used by port_config) */
 	if (op->dev.platform_data == NULL) {
-		struct device_node *np;
-		int i = 0;
+		const u32 *psc_nump;
 
-		for_each_node_by_type(np, "spi") {
-			if (of_find_device_by_node(np) == op) {
-				id = i;
-				break;
-			}
-			i++;
+		psc_nump = of_get_property(op->node, "cell-index", NULL);
+		if (!psc_nump || *psc_nump > 5) {
+			printk(KERN_ERR "mpc52xx_psc_spi: Device node %s has invalid "
+					"cell-index property\n", op->node->full_name);
+			return -EINVAL;
 		}
+		id = *psc_nump + 1;
 	}
 
 	return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
@@ -617,7 +623,7 @@
 }
 
 static struct of_device_id mpc52xx_psc_spi_of_match[] = {
-	{ .type = "spi", .compatible = "mpc52xx-psc-spi", },
+	{ .type = "spi", .compatible = "mpc5200-psc-spi", },
 	{},
 };
 
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
new file mode 100644
index 0000000..6b357cd
--- /dev/null
+++ b/drivers/spi/omap2_mcspi.c
@@ -0,0 +1,1081 @@
+/*
+ * OMAP2 McSPI controller driver
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ * Author:	Samuel Ortiz <samuel.ortiz@nokia.com> and
+ *		Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <linux/spi/spi.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/clock.h>
+
+
+#define OMAP2_MCSPI_MAX_FREQ		48000000
+
+#define OMAP2_MCSPI_REVISION		0x00
+#define OMAP2_MCSPI_SYSCONFIG		0x10
+#define OMAP2_MCSPI_SYSSTATUS		0x14
+#define OMAP2_MCSPI_IRQSTATUS		0x18
+#define OMAP2_MCSPI_IRQENABLE		0x1c
+#define OMAP2_MCSPI_WAKEUPENABLE	0x20
+#define OMAP2_MCSPI_SYST		0x24
+#define OMAP2_MCSPI_MODULCTRL		0x28
+
+/* per-channel banks, 0x14 bytes each, first is: */
+#define OMAP2_MCSPI_CHCONF0		0x2c
+#define OMAP2_MCSPI_CHSTAT0		0x30
+#define OMAP2_MCSPI_CHCTRL0		0x34
+#define OMAP2_MCSPI_TX0			0x38
+#define OMAP2_MCSPI_RX0			0x3c
+
+/* per-register bitmasks: */
+
+#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE	(1 << 0)
+#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET	(1 << 1)
+
+#define OMAP2_MCSPI_SYSSTATUS_RESETDONE	(1 << 0)
+
+#define OMAP2_MCSPI_MODULCTRL_SINGLE	(1 << 0)
+#define OMAP2_MCSPI_MODULCTRL_MS	(1 << 2)
+#define OMAP2_MCSPI_MODULCTRL_STEST	(1 << 3)
+
+#define OMAP2_MCSPI_CHCONF_PHA		(1 << 0)
+#define OMAP2_MCSPI_CHCONF_POL		(1 << 1)
+#define OMAP2_MCSPI_CHCONF_CLKD_MASK	(0x0f << 2)
+#define OMAP2_MCSPI_CHCONF_EPOL		(1 << 6)
+#define OMAP2_MCSPI_CHCONF_WL_MASK	(0x1f << 7)
+#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY	(0x01 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY	(0x02 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_MASK	(0x03 << 12)
+#define OMAP2_MCSPI_CHCONF_DMAW		(1 << 14)
+#define OMAP2_MCSPI_CHCONF_DMAR		(1 << 15)
+#define OMAP2_MCSPI_CHCONF_DPE0		(1 << 16)
+#define OMAP2_MCSPI_CHCONF_DPE1		(1 << 17)
+#define OMAP2_MCSPI_CHCONF_IS		(1 << 18)
+#define OMAP2_MCSPI_CHCONF_TURBO	(1 << 19)
+#define OMAP2_MCSPI_CHCONF_FORCE	(1 << 20)
+
+#define OMAP2_MCSPI_CHSTAT_RXS		(1 << 0)
+#define OMAP2_MCSPI_CHSTAT_TXS		(1 << 1)
+#define OMAP2_MCSPI_CHSTAT_EOT		(1 << 2)
+
+#define OMAP2_MCSPI_CHCTRL_EN		(1 << 0)
+
+
+/* We have 2 DMA channels per CS, one for RX and one for TX */
+struct omap2_mcspi_dma {
+	int dma_tx_channel;
+	int dma_rx_channel;
+
+	int dma_tx_sync_dev;
+	int dma_rx_sync_dev;
+
+	struct completion dma_tx_completion;
+	struct completion dma_rx_completion;
+};
+
+/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
+ * cache operations; better heuristics consider wordsize and bitrate.
+ */
+#define DMA_MIN_BYTES			8
+
+
+struct omap2_mcspi {
+	struct work_struct	work;
+	/* lock protects queue and registers */
+	spinlock_t		lock;
+	struct list_head	msg_queue;
+	struct spi_master	*master;
+	struct clk		*ick;
+	struct clk		*fck;
+	/* Virtual base address of the controller */
+	void __iomem		*base;
+	/* SPI1 has 4 channels, while SPI2 has 2 */
+	struct omap2_mcspi_dma	*dma_channels;
+};
+
+struct omap2_mcspi_cs {
+	void __iomem		*base;
+	int			word_len;
+};
+
+static struct workqueue_struct *omap2_mcspi_wq;
+
+#define MOD_REG_BIT(val, mask, set) do { \
+	if (set) \
+		val |= mask; \
+	else \
+		val &= ~mask; \
+} while (0)
+
+static inline void mcspi_write_reg(struct spi_master *master,
+		int idx, u32 val)
+{
+	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+	__raw_writel(val, mcspi->base + idx);
+}
+
+static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
+{
+	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+	return __raw_readl(mcspi->base + idx);
+}
+
+static inline void mcspi_write_cs_reg(const struct spi_device *spi,
+		int idx, u32 val)
+{
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	__raw_writel(val, cs->base +  idx);
+}
+
+static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
+{
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	return __raw_readl(cs->base + idx);
+}
+
+static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
+		int is_read, int enable)
+{
+	u32 l, rw;
+
+	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+
+	if (is_read) /* 1 is read, 0 write */
+		rw = OMAP2_MCSPI_CHCONF_DMAR;
+	else
+		rw = OMAP2_MCSPI_CHCONF_DMAW;
+
+	MOD_REG_BIT(l, rw, enable);
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+}
+
+static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
+{
+	u32 l;
+
+	l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
+}
+
+static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
+{
+	u32 l;
+
+	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+	MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+}
+
+static void omap2_mcspi_set_master_mode(struct spi_master *master)
+{
+	u32 l;
+
+	/* setup when switching from (reset default) slave mode
+	 * to single-channel master mode
+	 */
+	l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+	mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
+}
+
+static unsigned
+omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+	struct omap2_mcspi_dma  *mcspi_dma;
+	unsigned int		count, c;
+	unsigned long		base, tx_reg, rx_reg;
+	int			word_len, data_type, element_count;
+	u8			* rx;
+	const u8		* tx;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+	count = xfer->len;
+	c = count;
+	word_len = cs->word_len;
+
+	base = (unsigned long) io_v2p(cs->base);
+	tx_reg = base + OMAP2_MCSPI_TX0;
+	rx_reg = base + OMAP2_MCSPI_RX0;
+	rx = xfer->rx_buf;
+	tx = xfer->tx_buf;
+
+	if (word_len <= 8) {
+		data_type = OMAP_DMA_DATA_TYPE_S8;
+		element_count = count;
+	} else if (word_len <= 16) {
+		data_type = OMAP_DMA_DATA_TYPE_S16;
+		element_count = count >> 1;
+	} else /* word_len <= 32 */ {
+		data_type = OMAP_DMA_DATA_TYPE_S32;
+		element_count = count >> 2;
+	}
+
+	if (tx != NULL) {
+		omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel,
+				data_type, element_count, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				mcspi_dma->dma_tx_sync_dev, 0);
+
+		omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				tx_reg, 0, 0);
+
+		omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0,
+				OMAP_DMA_AMODE_POST_INC,
+				xfer->tx_dma, 0, 0);
+	}
+
+	if (rx != NULL) {
+		omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
+				data_type, element_count, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				mcspi_dma->dma_rx_sync_dev, 1);
+
+		omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				rx_reg, 0, 0);
+
+		omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0,
+				OMAP_DMA_AMODE_POST_INC,
+				xfer->rx_dma, 0, 0);
+	}
+
+	if (tx != NULL) {
+		omap_start_dma(mcspi_dma->dma_tx_channel);
+		omap2_mcspi_set_dma_req(spi, 0, 1);
+	}
+
+	if (rx != NULL) {
+		omap_start_dma(mcspi_dma->dma_rx_channel);
+		omap2_mcspi_set_dma_req(spi, 1, 1);
+	}
+
+	if (tx != NULL) {
+		wait_for_completion(&mcspi_dma->dma_tx_completion);
+		dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+	}
+
+	if (rx != NULL) {
+		wait_for_completion(&mcspi_dma->dma_rx_completion);
+		dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
+	}
+	return count;
+}
+
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+	while (!(__raw_readl(reg) & bit)) {
+		if (time_after(jiffies, timeout))
+			return -1;
+		cpu_relax();
+	}
+	return 0;
+}
+
+static unsigned
+omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+	unsigned int		count, c;
+	u32			l;
+	void __iomem		*base = cs->base;
+	void __iomem		*tx_reg;
+	void __iomem		*rx_reg;
+	void __iomem		*chstat_reg;
+	int			word_len;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	count = xfer->len;
+	c = count;
+	word_len = cs->word_len;
+
+	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+	l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+
+	/* We store the pre-calculated register addresses on stack to speed
+	 * up the transfer loop. */
+	tx_reg		= base + OMAP2_MCSPI_TX0;
+	rx_reg		= base + OMAP2_MCSPI_RX0;
+	chstat_reg	= base + OMAP2_MCSPI_CHSTAT0;
+
+	if (word_len <= 8) {
+		u8		*rx;
+		const u8	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+
+		do {
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "write-%d %02x\n",
+						word_len, *tx);
+#endif
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+				/* prevent last RX_ONLY read from triggering
+				 * more word i/o: switch to rx+tx
+				 */
+				if (c == 0 && tx == NULL)
+					mcspi_write_cs_reg(spi,
+							OMAP2_MCSPI_CHCONF0, l);
+				*rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "read-%d %02x\n",
+						word_len, *(rx - 1));
+#endif
+			}
+			c -= 1;
+		} while (c);
+	} else if (word_len <= 16) {
+		u16		*rx;
+		const u16	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "write-%d %04x\n",
+						word_len, *tx);
+#endif
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+				/* prevent last RX_ONLY read from triggering
+				 * more word i/o: switch to rx+tx
+				 */
+				if (c == 0 && tx == NULL)
+					mcspi_write_cs_reg(spi,
+							OMAP2_MCSPI_CHCONF0, l);
+				*rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "read-%d %04x\n",
+						word_len, *(rx - 1));
+#endif
+			}
+			c -= 2;
+		} while (c);
+	} else if (word_len <= 32) {
+		u32		*rx;
+		const u32	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "write-%d %04x\n",
+						word_len, *tx);
+#endif
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+				/* prevent last RX_ONLY read from triggering
+				 * more word i/o: switch to rx+tx
+				 */
+				if (c == 0 && tx == NULL)
+					mcspi_write_cs_reg(spi,
+							OMAP2_MCSPI_CHCONF0, l);
+				*rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+				dev_dbg(&spi->dev, "read-%d %04x\n",
+						word_len, *(rx - 1));
+#endif
+			}
+			c -= 4;
+		} while (c);
+	}
+
+	/* for TX_ONLY mode, be sure all words have shifted out */
+	if (xfer->rx_buf == NULL) {
+		if (mcspi_wait_for_reg_bit(chstat_reg,
+				OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+			dev_err(&spi->dev, "TXS timed out\n");
+		} else if (mcspi_wait_for_reg_bit(chstat_reg,
+				OMAP2_MCSPI_CHSTAT_EOT) < 0)
+			dev_err(&spi->dev, "EOT timed out\n");
+	}
+out:
+	return count - c;
+}
+
+/* called only when no transfer is active to this device */
+static int omap2_mcspi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	struct omap2_mcspi_cs *cs = spi->controller_state;
+	struct omap2_mcspi *mcspi;
+	u32 l = 0, div = 0;
+	u8 word_len = spi->bits_per_word;
+
+	mcspi = spi_master_get_devdata(spi->master);
+
+	if (t != NULL && t->bits_per_word)
+		word_len = t->bits_per_word;
+
+	cs->word_len = word_len;
+
+	if (spi->max_speed_hz) {
+		while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div))
+					> spi->max_speed_hz)
+			div++;
+	} else
+		div = 15;
+
+	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+
+	/* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
+	 * REVISIT: this controller could support SPI_3WIRE mode.
+	 */
+	l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
+	l |= OMAP2_MCSPI_CHCONF_DPE0;
+
+	/* wordlength */
+	l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
+	l |= (word_len - 1) << 7;
+
+	/* set chipselect polarity; manage with FORCE */
+	if (!(spi->mode & SPI_CS_HIGH))
+		l |= OMAP2_MCSPI_CHCONF_EPOL;	/* active-low; normal */
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_EPOL;
+
+	/* set clock divisor */
+	l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
+	l |= div << 2;
+
+	/* set SPI mode 0..3 */
+	if (spi->mode & SPI_CPOL)
+		l |= OMAP2_MCSPI_CHCONF_POL;
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_POL;
+	if (spi->mode & SPI_CPHA)
+		l |= OMAP2_MCSPI_CHCONF_PHA;
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_PHA;
+
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+
+	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
+			OMAP2_MCSPI_MAX_FREQ / (1 << div),
+			(spi->mode & SPI_CPHA) ? "trailing" : "leading",
+			(spi->mode & SPI_CPOL) ? "inverted" : "normal");
+
+	return 0;
+}
+
+static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data)
+{
+	struct spi_device	*spi = data;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
+
+	complete(&mcspi_dma->dma_rx_completion);
+
+	/* We must disable the DMA RX request */
+	omap2_mcspi_set_dma_req(spi, 1, 0);
+}
+
+static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data)
+{
+	struct spi_device	*spi = data;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
+
+	complete(&mcspi_dma->dma_tx_completion);
+
+	/* We must disable the DMA TX request */
+	omap2_mcspi_set_dma_req(spi, 0, 0);
+}
+
+static int omap2_mcspi_request_dma(struct spi_device *spi)
+{
+	struct spi_master	*master = spi->master;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(master);
+	mcspi_dma = mcspi->dma_channels + spi->chip_select;
+
+	if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX",
+			omap2_mcspi_dma_rx_callback, spi,
+			&mcspi_dma->dma_rx_channel)) {
+		dev_err(&spi->dev, "no RX DMA channel for McSPI\n");
+		return -EAGAIN;
+	}
+
+	if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX",
+			omap2_mcspi_dma_tx_callback, spi,
+			&mcspi_dma->dma_tx_channel)) {
+		omap_free_dma(mcspi_dma->dma_rx_channel);
+		mcspi_dma->dma_rx_channel = -1;
+		dev_err(&spi->dev, "no TX DMA channel for McSPI\n");
+		return -EAGAIN;
+	}
+
+	init_completion(&mcspi_dma->dma_rx_completion);
+	init_completion(&mcspi_dma->dma_tx_completion);
+
+	return 0;
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
+static int omap2_mcspi_setup(struct spi_device *spi)
+{
+	int			ret;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
+	if (spi->bits_per_word == 0)
+		spi->bits_per_word = 8;
+	else if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
+		dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
+			spi->bits_per_word);
+		return -EINVAL;
+	}
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		cs->base = mcspi->base + spi->chip_select * 0x14;
+		spi->controller_state = cs;
+	}
+
+	if (mcspi_dma->dma_rx_channel == -1
+			|| mcspi_dma->dma_tx_channel == -1) {
+		ret = omap2_mcspi_request_dma(spi);
+		if (ret < 0)
+			return ret;
+	}
+
+	clk_enable(mcspi->ick);
+	clk_enable(mcspi->fck);
+	ret =  omap2_mcspi_setup_transfer(spi, NULL);
+	clk_disable(mcspi->fck);
+	clk_disable(mcspi->ick);
+
+	return ret;
+}
+
+static void omap2_mcspi_cleanup(struct spi_device *spi)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+	kfree(spi->controller_state);
+
+	if (mcspi_dma->dma_rx_channel != -1) {
+		omap_free_dma(mcspi_dma->dma_rx_channel);
+		mcspi_dma->dma_rx_channel = -1;
+	}
+	if (mcspi_dma->dma_tx_channel != -1) {
+		omap_free_dma(mcspi_dma->dma_tx_channel);
+		mcspi_dma->dma_tx_channel = -1;
+	}
+}
+
+static void omap2_mcspi_work(struct work_struct *work)
+{
+	struct omap2_mcspi	*mcspi;
+
+	mcspi = container_of(work, struct omap2_mcspi, work);
+	spin_lock_irq(&mcspi->lock);
+
+	clk_enable(mcspi->ick);
+	clk_enable(mcspi->fck);
+
+	/* We only enable one channel at a time -- the one whose message is
+	 * at the head of the queue -- although this controller would gladly
+	 * arbitrate among multiple channels.  This corresponds to "single
+	 * channel" master mode.  As a side effect, we need to manage the
+	 * chipselect with the FORCE bit ... CS != channel enable.
+	 */
+	while (!list_empty(&mcspi->msg_queue)) {
+		struct spi_message		*m;
+		struct spi_device		*spi;
+		struct spi_transfer		*t = NULL;
+		int				cs_active = 0;
+		struct omap2_mcspi_device_config *conf;
+		struct omap2_mcspi_cs		*cs;
+		int				par_override = 0;
+		int				status = 0;
+		u32				chconf;
+
+		m = container_of(mcspi->msg_queue.next, struct spi_message,
+				 queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mcspi->lock);
+
+		spi = m->spi;
+		conf = spi->controller_data;
+		cs = spi->controller_state;
+
+		omap2_mcspi_set_enable(spi, 1);
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+				status = -EINVAL;
+				break;
+			}
+			if (par_override || t->speed_hz || t->bits_per_word) {
+				par_override = 1;
+				status = omap2_mcspi_setup_transfer(spi, t);
+				if (status < 0)
+					break;
+				if (!t->speed_hz && !t->bits_per_word)
+					par_override = 0;
+			}
+
+			if (!cs_active) {
+				omap2_mcspi_force_cs(spi, 1);
+				cs_active = 1;
+			}
+
+			chconf = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+			chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+			if (t->tx_buf == NULL)
+				chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
+			else if (t->rx_buf == NULL)
+				chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
+			mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, chconf);
+
+			if (t->len) {
+				unsigned	count;
+
+				/* RX_ONLY mode needs dummy data in TX reg */
+				if (t->tx_buf == NULL)
+					__raw_writel(0, cs->base
+							+ OMAP2_MCSPI_TX0);
+
+				if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)
+					count = omap2_mcspi_txrx_dma(spi, t);
+				else
+					count = omap2_mcspi_txrx_pio(spi, t);
+				m->actual_length += count;
+
+				if (count != t->len) {
+					status = -EIO;
+					break;
+				}
+			}
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			/* ignore the "leave it on after last xfer" hint */
+			if (t->cs_change) {
+				omap2_mcspi_force_cs(spi, 0);
+				cs_active = 0;
+			}
+		}
+
+		/* Restore defaults if they were overriden */
+		if (par_override) {
+			par_override = 0;
+			status = omap2_mcspi_setup_transfer(spi, NULL);
+		}
+
+		if (cs_active)
+			omap2_mcspi_force_cs(spi, 0);
+
+		omap2_mcspi_set_enable(spi, 0);
+
+		m->status = status;
+		m->complete(m->context);
+
+		spin_lock_irq(&mcspi->lock);
+	}
+
+	clk_disable(mcspi->fck);
+	clk_disable(mcspi->ick);
+
+	spin_unlock_irq(&mcspi->lock);
+}
+
+static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct omap2_mcspi	*mcspi;
+	unsigned long		flags;
+	struct spi_transfer	*t;
+
+	m->actual_length = 0;
+	m->status = 0;
+
+	/* reject invalid messages and transfers */
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		const void	*tx_buf = t->tx_buf;
+		void		*rx_buf = t->rx_buf;
+		unsigned	len = t->len;
+
+		if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
+				|| (len && !(rx_buf || tx_buf))
+				|| (t->bits_per_word &&
+					(  t->bits_per_word < 4
+					|| t->bits_per_word > 32))) {
+			dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
+					t->speed_hz,
+					len,
+					tx_buf ? "tx" : "",
+					rx_buf ? "rx" : "",
+					t->bits_per_word);
+			return -EINVAL;
+		}
+		if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) {
+			dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
+					t->speed_hz,
+					OMAP2_MCSPI_MAX_FREQ/(1<<16));
+			return -EINVAL;
+		}
+
+		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
+			continue;
+
+		/* Do DMA mapping "early" for better error reporting and
+		 * dcache use.  Note that if dma_unmap_single() ever starts
+		 * to do real work on ARM, we'd need to clean up mappings
+		 * for previous transfers on *ALL* exits of this loop...
+		 */
+		if (tx_buf != NULL) {
+			t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
+					len, DMA_TO_DEVICE);
+			if (dma_mapping_error(t->tx_dma)) {
+				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
+						'T', len);
+				return -EINVAL;
+			}
+		}
+		if (rx_buf != NULL) {
+			t->rx_dma = dma_map_single(&spi->dev, rx_buf, t->len,
+					DMA_FROM_DEVICE);
+			if (dma_mapping_error(t->rx_dma)) {
+				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
+						'R', len);
+				if (tx_buf != NULL)
+					dma_unmap_single(NULL, t->tx_dma,
+							len, DMA_TO_DEVICE);
+				return -EINVAL;
+			}
+		}
+	}
+
+	mcspi = spi_master_get_devdata(spi->master);
+
+	spin_lock_irqsave(&mcspi->lock, flags);
+	list_add_tail(&m->queue, &mcspi->msg_queue);
+	queue_work(omap2_mcspi_wq, &mcspi->work);
+	spin_unlock_irqrestore(&mcspi->lock, flags);
+
+	return 0;
+}
+
+static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
+{
+	struct spi_master	*master = mcspi->master;
+	u32			tmp;
+
+	clk_enable(mcspi->ick);
+	clk_enable(mcspi->fck);
+
+	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
+			OMAP2_MCSPI_SYSCONFIG_SOFTRESET);
+	do {
+		tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS);
+	} while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
+
+	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
+			/* (3 << 8) | (2 << 3) | */
+			OMAP2_MCSPI_SYSCONFIG_AUTOIDLE);
+
+	omap2_mcspi_set_master_mode(master);
+
+	clk_disable(mcspi->fck);
+	clk_disable(mcspi->ick);
+	return 0;
+}
+
+static u8 __initdata spi1_rxdma_id [] = {
+	OMAP24XX_DMA_SPI1_RX0,
+	OMAP24XX_DMA_SPI1_RX1,
+	OMAP24XX_DMA_SPI1_RX2,
+	OMAP24XX_DMA_SPI1_RX3,
+};
+
+static u8 __initdata spi1_txdma_id [] = {
+	OMAP24XX_DMA_SPI1_TX0,
+	OMAP24XX_DMA_SPI1_TX1,
+	OMAP24XX_DMA_SPI1_TX2,
+	OMAP24XX_DMA_SPI1_TX3,
+};
+
+static u8 __initdata spi2_rxdma_id[] = {
+	OMAP24XX_DMA_SPI2_RX0,
+	OMAP24XX_DMA_SPI2_RX1,
+};
+
+static u8 __initdata spi2_txdma_id[] = {
+	OMAP24XX_DMA_SPI2_TX0,
+	OMAP24XX_DMA_SPI2_TX1,
+};
+
+static int __init omap2_mcspi_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct omap2_mcspi	*mcspi;
+	struct resource		*r;
+	int			status = 0, i;
+	const u8		*rxdma_id, *txdma_id;
+	unsigned		num_chipselect;
+
+	switch (pdev->id) {
+	case 1:
+		rxdma_id = spi1_rxdma_id;
+		txdma_id = spi1_txdma_id;
+		num_chipselect = 4;
+		break;
+	case 2:
+		rxdma_id = spi2_rxdma_id;
+		txdma_id = spi2_txdma_id;
+		num_chipselect = 2;
+		break;
+	/* REVISIT omap2430 has a third McSPI ... */
+	default:
+		return -EINVAL;
+	}
+
+	master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
+	if (master == NULL) {
+		dev_dbg(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	if (pdev->id != -1)
+		master->bus_num = pdev->id;
+
+	master->setup = omap2_mcspi_setup;
+	master->transfer = omap2_mcspi_transfer;
+	master->cleanup = omap2_mcspi_cleanup;
+	master->num_chipselect = num_chipselect;
+
+	dev_set_drvdata(&pdev->dev, master);
+
+	mcspi = spi_master_get_devdata(master);
+	mcspi->master = master;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		status = -ENODEV;
+		goto err1;
+	}
+	if (!request_mem_region(r->start, (r->end - r->start) + 1,
+			pdev->dev.bus_id)) {
+		status = -EBUSY;
+		goto err1;
+	}
+
+	mcspi->base = (void __iomem *) io_p2v(r->start);
+
+	INIT_WORK(&mcspi->work, omap2_mcspi_work);
+
+	spin_lock_init(&mcspi->lock);
+	INIT_LIST_HEAD(&mcspi->msg_queue);
+
+	mcspi->ick = clk_get(&pdev->dev, "mcspi_ick");
+	if (IS_ERR(mcspi->ick)) {
+		dev_dbg(&pdev->dev, "can't get mcspi_ick\n");
+		status = PTR_ERR(mcspi->ick);
+		goto err1a;
+	}
+	mcspi->fck = clk_get(&pdev->dev, "mcspi_fck");
+	if (IS_ERR(mcspi->fck)) {
+		dev_dbg(&pdev->dev, "can't get mcspi_fck\n");
+		status = PTR_ERR(mcspi->fck);
+		goto err2;
+	}
+
+	mcspi->dma_channels = kcalloc(master->num_chipselect,
+			sizeof(struct omap2_mcspi_dma),
+			GFP_KERNEL);
+
+	if (mcspi->dma_channels == NULL)
+		goto err3;
+
+	for (i = 0; i < num_chipselect; i++) {
+		mcspi->dma_channels[i].dma_rx_channel = -1;
+		mcspi->dma_channels[i].dma_rx_sync_dev = rxdma_id[i];
+		mcspi->dma_channels[i].dma_tx_channel = -1;
+		mcspi->dma_channels[i].dma_tx_sync_dev = txdma_id[i];
+	}
+
+	if (omap2_mcspi_reset(mcspi) < 0)
+		goto err4;
+
+	status = spi_register_master(master);
+	if (status < 0)
+		goto err4;
+
+	return status;
+
+err4:
+	kfree(mcspi->dma_channels);
+err3:
+	clk_put(mcspi->fck);
+err2:
+	clk_put(mcspi->ick);
+err1a:
+	release_mem_region(r->start, (r->end - r->start) + 1);
+err1:
+	spi_master_put(master);
+	return status;
+}
+
+static int __exit omap2_mcspi_remove(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*dma_channels;
+	struct resource		*r;
+
+	master = dev_get_drvdata(&pdev->dev);
+	mcspi = spi_master_get_devdata(master);
+	dma_channels = mcspi->dma_channels;
+
+	clk_put(mcspi->fck);
+	clk_put(mcspi->ick);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, (r->end - r->start) + 1);
+
+	spi_unregister_master(master);
+	kfree(dma_channels);
+
+	return 0;
+}
+
+static struct platform_driver omap2_mcspi_driver = {
+	.driver = {
+		.name =		"omap2_mcspi",
+		.owner =	THIS_MODULE,
+	},
+	.remove =	__exit_p(omap2_mcspi_remove),
+};
+
+
+static int __init omap2_mcspi_init(void)
+{
+	omap2_mcspi_wq = create_singlethread_workqueue(
+				omap2_mcspi_driver.driver.name);
+	if (omap2_mcspi_wq == NULL)
+		return -1;
+	return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);
+}
+subsys_initcall(omap2_mcspi_init);
+
+static void __exit omap2_mcspi_exit(void)
+{
+	platform_driver_unregister(&omap2_mcspi_driver);
+
+	destroy_workqueue(omap2_mcspi_wq);
+}
+module_exit(omap2_mcspi_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index 96f62b2..d275c61 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -358,11 +358,11 @@
 	switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
 	case SPI_MODE_0:
 	case SPI_MODE_3:
-		flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
+		flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
 		break;
 	case SPI_MODE_1:
 	case SPI_MODE_2:
-		flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
+		flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
 		break;
 	}
 
@@ -445,10 +445,19 @@
 	return status;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
 static int uwire_setup(struct spi_device *spi)
 {
 	struct uwire_state *ust = spi->controller_state;
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	if (ust == NULL) {
 		ust = kzalloc(sizeof(*ust), GFP_KERNEL);
 		if (ust == NULL)
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 9f2c887..e51311b 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1067,6 +1067,9 @@
 	return 0;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA)
+
 static int setup(struct spi_device *spi)
 {
 	struct pxa2xx_spi_chip *chip_info = NULL;
@@ -1093,6 +1096,12 @@
 		return -EINVAL;
 	}
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	/* Only alloc on first setup */
 	chip = spi_get_ctldata(spi);
 	if (!chip) {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index c3219b2..018884d 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -23,6 +23,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/cache.h>
+#include <linux/mutex.h>
 #include <linux/spi/spi.h>
 
 
@@ -185,7 +186,7 @@
 };
 
 static LIST_HEAD(board_list);
-static DECLARE_MUTEX(board_lock);
+static DEFINE_MUTEX(board_lock);
 
 
 /**
@@ -292,9 +293,9 @@
 	bi->n_board_info = n;
 	memcpy(bi->board_info, info, n * sizeof *info);
 
-	down(&board_lock);
+	mutex_lock(&board_lock);
 	list_add_tail(&bi->list, &board_list);
-	up(&board_lock);
+	mutex_unlock(&board_lock);
 	return 0;
 }
 
@@ -308,7 +309,7 @@
 	struct boardinfo	*bi;
 	struct device		*dev = master->cdev.dev;
 
-	down(&board_lock);
+	mutex_lock(&board_lock);
 	list_for_each_entry(bi, &board_list, list) {
 		struct spi_board_info	*chip = bi->board_info;
 		unsigned		n;
@@ -330,7 +331,7 @@
 			(void) spi_new_device(master, chip);
 		}
 	}
-	up(&board_lock);
+	mutex_unlock(&board_lock);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -411,7 +412,7 @@
  */
 int spi_register_master(struct spi_master *master)
 {
-	static atomic_t		dyn_bus_id = ATOMIC_INIT((1<<16) - 1);
+	static atomic_t		dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
 	struct device		*dev = master->cdev.dev;
 	int			status = -ENODEV;
 	int			dynamic = 0;
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index ce3c0ce..48587c2 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -126,7 +126,7 @@
 
 	u8 chip_select_num;
 	u8 n_bytes;
-	u32 width;		/* 0 or 1 */
+	u8 width;		/* 0 or 1 */
 	u8 enable_dma;
 	u8 bits_per_word;	/* 8 or 16 */
 	u8 cs_change_per_word;
@@ -136,7 +136,7 @@
 	void (*duplex) (struct driver_data *);
 };
 
-void bfin_spi_enable(struct driver_data *drv_data)
+static void bfin_spi_enable(struct driver_data *drv_data)
 {
 	u16 cr;
 
@@ -145,7 +145,7 @@
 	SSYNC();
 }
 
-void bfin_spi_disable(struct driver_data *drv_data)
+static void bfin_spi_disable(struct driver_data *drv_data)
 {
 	u16 cr;
 
@@ -163,9 +163,6 @@
 	if ((sclk % (2 * speed_hz)) > 0)
 		spi_baud++;
 
-	pr_debug("sclk = %ld, speed_hz = %d, spi_baud = %d\n", sclk, speed_hz,
-		 spi_baud);
-
 	return spi_baud;
 }
 
@@ -190,11 +187,12 @@
 	/* Clear status and disable clock */
 	write_STAT(BIT_STAT_CLR);
 	bfin_spi_disable(drv_data);
-	pr_debug("restoring spi ctl state\n");
+	dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
 
 #if defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537)
-	pr_debug("chip select number is %d\n", chip->chip_select_num);
-
+	dev_dbg(&drv_data->pdev->dev, 
+		"chip select number is %d\n", chip->chip_select_num);
+	
 	switch (chip->chip_select_num) {
 	case 1:
 		bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3c00);
@@ -280,7 +278,8 @@
 
 static void u8_writer(struct driver_data *drv_data)
 {
-	pr_debug("cr8-s is 0x%x\n", read_STAT());
+	dev_dbg(&drv_data->pdev->dev, 
+		"cr8-s is 0x%x\n", read_STAT());
 	while (drv_data->tx < drv_data->tx_end) {
 		write_TDBR(*(u8 *) (drv_data->tx));
 		while (read_STAT() & BIT_STAT_TXS)
@@ -318,7 +317,8 @@
 
 static void u8_reader(struct driver_data *drv_data)
 {
-	pr_debug("cr-8 is 0x%x\n", read_STAT());
+	dev_dbg(&drv_data->pdev->dev, 
+		"cr-8 is 0x%x\n", read_STAT());
 
 	/* clear TDBR buffer before read(else it will be shifted out) */
 	write_TDBR(0xFFFF);
@@ -404,7 +404,9 @@
 
 static void u16_writer(struct driver_data *drv_data)
 {
-	pr_debug("cr16 is 0x%x\n", read_STAT());
+	dev_dbg(&drv_data->pdev->dev, 
+		"cr16 is 0x%x\n", read_STAT());
+
 	while (drv_data->tx < drv_data->tx_end) {
 		write_TDBR(*(u16 *) (drv_data->tx));
 		while ((read_STAT() & BIT_STAT_TXS))
@@ -442,7 +444,8 @@
 
 static void u16_reader(struct driver_data *drv_data)
 {
-	pr_debug("cr-16 is 0x%x\n", read_STAT());
+	dev_dbg(&drv_data->pdev->dev,
+		"cr-16 is 0x%x\n", read_STAT());
 	dummy_read();
 
 	while (drv_data->rx < (drv_data->rx_end - 2)) {
@@ -571,22 +574,27 @@
 		msg->complete(msg->context);
 }
 
-static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
 	struct driver_data *drv_data = (struct driver_data *)dev_id;
 	struct spi_message *msg = drv_data->cur_msg;
 
-	pr_debug("in dma_irq_handler\n");
+	dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n");
 	clear_dma_irqstat(CH_SPI);
 
+	/* Wait for DMA to complete */
+	while (get_dma_curr_irqstat(CH_SPI) & DMA_RUN)
+		continue;
+
 	/*
-	 * wait for the last transaction shifted out.  yes, these two
-	 * while loops are supposed to be the same (see the HRM).
+	 * wait for the last transaction shifted out.  HRM states:
+	 * at this point there may still be data in the SPI DMA FIFO waiting
+	 * to be transmitted ... software needs to poll TXS in the SPI_STAT
+	 * register until it goes low for 2 successive reads
 	 */
 	if (drv_data->tx != NULL) {
-		while (bfin_read_SPI_STAT() & TXS)
-			continue;
-		while (bfin_read_SPI_STAT() & TXS)
+		while ((bfin_read_SPI_STAT() & TXS) ||
+		       (bfin_read_SPI_STAT() & TXS))
 			continue;
 	}
 
@@ -604,7 +612,9 @@
 	tasklet_schedule(&drv_data->pump_transfers);
 
 	/* free the irq handler before next transfer */
-	pr_debug("disable dma channel irq%d\n", CH_SPI);
+	dev_dbg(&drv_data->pdev->dev,
+		"disable dma channel irq%d\n",
+		CH_SPI);
 	dma_disable_irq(CH_SPI);
 
 	return IRQ_HANDLED;
@@ -617,7 +627,8 @@
 	struct spi_transfer *transfer = NULL;
 	struct spi_transfer *previous = NULL;
 	struct chip_data *chip = NULL;
-	u16 cr, width, dma_width, dma_config;
+	u8 width;
+	u16 cr, dma_width, dma_config;
 	u32 tranf_success = 1;
 
 	/* Get current state information */
@@ -662,8 +673,8 @@
 	if (transfer->tx_buf != NULL) {
 		drv_data->tx = (void *)transfer->tx_buf;
 		drv_data->tx_end = drv_data->tx + transfer->len;
-		pr_debug("tx_buf is %p, tx_end is %p\n", transfer->tx_buf,
-			 drv_data->tx_end);
+		dev_dbg(&drv_data->pdev->dev, "tx_buf is %p, tx_end is %p\n",
+			transfer->tx_buf, drv_data->tx_end);
 	} else {
 		drv_data->tx = NULL;
 	}
@@ -671,8 +682,8 @@
 	if (transfer->rx_buf != NULL) {
 		drv_data->rx = transfer->rx_buf;
 		drv_data->rx_end = drv_data->rx + transfer->len;
-		pr_debug("rx_buf is %p, rx_end is %p\n", transfer->rx_buf,
-			 drv_data->rx_end);
+		dev_dbg(&drv_data->pdev->dev, "rx_buf is %p, rx_end is %p\n",
+			transfer->rx_buf, drv_data->rx_end);
 	} else {
 		drv_data->rx = NULL;
 	}
@@ -690,9 +701,9 @@
 	drv_data->write = drv_data->tx ? chip->write : null_writer;
 	drv_data->read = drv_data->rx ? chip->read : null_reader;
 	drv_data->duplex = chip->duplex ? chip->duplex : null_writer;
-	pr_debug
-	    ("transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
-	     drv_data->write, chip->write, null_writer);
+	dev_dbg(&drv_data->pdev->dev,
+		"transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
+   		drv_data->write, chip->write, null_writer);
 
 	/* speed and width has been set on per message */
 	message->state = RUNNING_STATE;
@@ -706,8 +717,9 @@
 	}
 	write_FLAG(chip->flag);
 
-	pr_debug("now pumping a transfer: width is %d, len is %d\n", width,
-		 transfer->len);
+	dev_dbg(&drv_data->pdev->dev,
+		"now pumping a transfer: width is %d, len is %d\n",
+		width, transfer->len);
 
 	/*
 	 * Try to map dma buffer and do a dma transfer if
@@ -722,7 +734,7 @@
 		bfin_spi_disable(drv_data);
 
 		/* config dma channel */
-		pr_debug("doing dma transfer\n");
+		dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
 		if (width == CFG_SPI_WORDSIZE16) {
 			set_dma_x_count(CH_SPI, drv_data->len);
 			set_dma_x_modify(CH_SPI, 2);
@@ -738,7 +750,8 @@
 
 		/* dirty hack for autobuffer DMA mode */
 		if (drv_data->tx_dma == 0xFFFF) {
-			pr_debug("doing autobuffer DMA out.\n");
+			dev_dbg(&drv_data->pdev->dev,
+				"doing autobuffer DMA out.\n");
 
 			/* no irq in autobuffer mode */
 			dma_config =
@@ -758,7 +771,7 @@
 		/* In dma mode, rx or tx must be NULL in one transfer */
 		if (drv_data->rx != NULL) {
 			/* set transfer mode, and enable SPI */
-			pr_debug("doing DMA in.\n");
+			dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n");
 
 			/* disable SPI before write to TDBR */
 			write_CTRL(cr & ~BIT_CTL_ENABLE);
@@ -781,7 +794,7 @@
 			/* set transfer mode, and enable SPI */
 			write_CTRL(cr);
 		} else if (drv_data->tx != NULL) {
-			pr_debug("doing DMA out.\n");
+			dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
 
 			/* start dma */
 			dma_enable_irq(CH_SPI);
@@ -796,7 +809,7 @@
 		}
 	} else {
 		/* IO mode write then read */
-		pr_debug("doing IO transfer\n");
+		dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
 
 		write_STAT(BIT_STAT_CLR);
 
@@ -804,11 +817,11 @@
 			/* full duplex mode */
 			BUG_ON((drv_data->tx_end - drv_data->tx) !=
 			       (drv_data->rx_end - drv_data->rx));
-			cr = (read_CTRL() & (~BIT_CTL_TIMOD));	/* clear the TIMOD bits */
-			cr |=
-			    CFG_SPI_WRITE | (width << 8) | (CFG_SPI_ENABLE <<
-							    14);
-			pr_debug("IO duplex: cr is 0x%x\n", cr);
+			cr = (read_CTRL() & (~BIT_CTL_TIMOD));	
+			cr |= CFG_SPI_WRITE | (width << 8) |
+				(CFG_SPI_ENABLE << 14);
+			dev_dbg(&drv_data->pdev->dev,
+				"IO duplex: cr is 0x%x\n", cr);
 
 			write_CTRL(cr);
 			SSYNC();
@@ -819,11 +832,11 @@
 				tranf_success = 0;
 		} else if (drv_data->tx != NULL) {
 			/* write only half duplex */
-			cr = (read_CTRL() & (~BIT_CTL_TIMOD));	/* clear the TIMOD bits */
-			cr |=
-			    CFG_SPI_WRITE | (width << 8) | (CFG_SPI_ENABLE <<
-							    14);
-			pr_debug("IO write: cr is 0x%x\n", cr);
+			cr = (read_CTRL() & (~BIT_CTL_TIMOD));
+			cr |= CFG_SPI_WRITE | (width << 8) |
+				(CFG_SPI_ENABLE << 14);
+			dev_dbg(&drv_data->pdev->dev, 
+				"IO write: cr is 0x%x\n", cr);
 
 			write_CTRL(cr);
 			SSYNC();
@@ -834,11 +847,11 @@
 				tranf_success = 0;
 		} else if (drv_data->rx != NULL) {
 			/* read only half duplex */
-			cr = (read_CTRL() & (~BIT_CTL_TIMOD));	/* cleare the TIMOD bits */
-			cr |=
-			    CFG_SPI_READ | (width << 8) | (CFG_SPI_ENABLE <<
-							   14);
-			pr_debug("IO read: cr is 0x%x\n", cr);
+			cr = (read_CTRL() & (~BIT_CTL_TIMOD));
+			cr |= CFG_SPI_READ | (width << 8) |
+				(CFG_SPI_ENABLE << 14);
+			dev_dbg(&drv_data->pdev->dev, 
+				"IO read: cr is 0x%x\n", cr);
 
 			write_CTRL(cr);
 			SSYNC();
@@ -849,7 +862,8 @@
 		}
 
 		if (!tranf_success) {
-			pr_debug("IO write error!\n");
+			dev_dbg(&drv_data->pdev->dev, 
+				"IO write error!\n");
 			message->state = ERROR_STATE;
 		} else {
 			/* Update total byte transfered */
@@ -899,11 +913,14 @@
 	/* Setup the SSP using the per chip configuration */
 	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
 	restore_state(drv_data);
-	pr_debug
-	    ("got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
-	     drv_data->cur_chip->baud, drv_data->cur_chip->flag,
-	     drv_data->cur_chip->ctl_reg);
-	pr_debug("the first transfer len is %d\n", drv_data->cur_transfer->len);
+	dev_dbg(&drv_data->pdev->dev,
+		"got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
+   		drv_data->cur_chip->baud, drv_data->cur_chip->flag,
+   		drv_data->cur_chip->ctl_reg);
+	
+	dev_dbg(&drv_data->pdev->dev, 
+		"the first transfer len is %d\n",
+		drv_data->cur_transfer->len);
 
 	/* Mark as busy and launch transfers */
 	tasklet_schedule(&drv_data->pump_transfers);
@@ -932,7 +949,7 @@
 	msg->status = -EINPROGRESS;
 	msg->state = START_STATE;
 
-	pr_debug("adding an msg in transfer() \n");
+	dev_dbg(&spi->dev, "adding an msg in transfer() \n");
 	list_add_tail(&msg->queue, &drv_data->queue);
 
 	if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
@@ -1002,13 +1019,13 @@
 	if (chip->enable_dma && !dma_requested) {
 		/* register dma irq handler */
 		if (request_dma(CH_SPI, "BF53x_SPI_DMA") < 0) {
-			pr_debug
-			    ("Unable to request BlackFin SPI DMA channel\n");
+			dev_dbg(&spi->dev,
+				"Unable to request BlackFin SPI DMA channel\n");
 			return -ENODEV;
 		}
 		if (set_dma_callback(CH_SPI, (void *)dma_irq_handler, drv_data)
 		    < 0) {
-			pr_debug("Unable to set dma callback\n");
+			dev_dbg(&spi->dev, "Unable to set dma callback\n");
 			return -EPERM;
 		}
 		dma_disable_irq(CH_SPI);
@@ -1054,9 +1071,9 @@
 		return -ENODEV;
 	}
 
-	pr_debug("setup spi chip %s, width is %d, dma is %d,",
+	dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d,",
 			spi->modalias, chip->width, chip->enable_dma);
-	pr_debug("ctl_reg is 0x%x, flag_reg is 0x%x\n",
+	dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n",
 			chip->ctl_reg, chip->flag);
 
 	spi_set_ctldata(spi, chip);
@@ -1068,9 +1085,9 @@
  * callback for spi framework.
  * clean driver specific data
  */
-static void cleanup(const struct spi_device *spi)
+static void cleanup(struct spi_device *spi)
 {
-	struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+	struct chip_data *chip = spi_get_ctldata(spi);
 
 	kfree(chip);
 }
@@ -1207,7 +1224,7 @@
 		dev_err(&pdev->dev, "problem registering spi master\n");
 		goto out_error_queue_alloc;
 	}
-	pr_debug("controller probe successfully\n");
+	dev_dbg(&pdev->dev, "controller probe successfully\n");
 	return status;
 
       out_error_queue_alloc:
@@ -1287,27 +1304,23 @@
 #endif				/* CONFIG_PM */
 
 static struct platform_driver bfin5xx_spi_driver = {
-	.driver = {
-		   .name = "bfin-spi-master",
-		   .bus = &platform_bus_type,
-		   .owner = THIS_MODULE,
-		   },
-	.probe = bfin5xx_spi_probe,
-	.remove = __devexit_p(bfin5xx_spi_remove),
-	.suspend = bfin5xx_spi_suspend,
-	.resume = bfin5xx_spi_resume,
+	.driver 	= {
+		.name	= "bfin-spi-master",
+		.owner	= THIS_MODULE,
+	},
+	.suspend	= bfin5xx_spi_suspend,
+	.resume		= bfin5xx_spi_resume,
+	.remove		= __devexit_p(bfin5xx_spi_remove),
 };
 
 static int __init bfin5xx_spi_init(void)
 {
-	return platform_driver_register(&bfin5xx_spi_driver);
+	return platform_driver_probe(&bfin5xx_spi_driver, bfin5xx_spi_probe);
 }
-
 module_init(bfin5xx_spi_init);
 
 static void __exit bfin5xx_spi_exit(void)
 {
 	platform_driver_unregister(&bfin5xx_spi_driver);
 }
-
 module_exit(bfin5xx_spi_exit);
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 88425e1..0c85c98 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -187,12 +187,10 @@
 
 	bitbang = spi_master_get_devdata(spi->master);
 
-	/* REVISIT: some systems will want to support devices using lsb-first
-	 * bit encodings on the wire.  In pure software that would be trivial,
-	 * just bitbang_txrx_le_cphaX() routines shifting the other way, and
-	 * some hardware controllers also have this support.
+	/* Bitbangers can support SPI_CS_HIGH, SPI_3WIRE, and so on;
+	 * add those to master->flags, and provide the other support.
 	 */
-	if ((spi->mode & SPI_LSB_FIRST) != 0)
+	if ((spi->mode & ~(SPI_CPOL|SPI_CPHA|bitbang->flags)) != 0)
 		return -EINVAL;
 
 	if (!cs) {
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 51daa21..aee9ad6 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -121,7 +121,7 @@
 							32.768 KHz Clock */
 
 /* SPI DMA Register Bit Fields & Masks */
-#define SPI_DMA_RHDMA	(0xF << 4)	/* RXFIFO Half Status */
+#define SPI_DMA_RHDMA	(0x1 << 4)	/* RXFIFO Half Status */
 #define SPI_DMA_RFDMA	(0x1 << 5)      /* RXFIFO Full Status */
 #define SPI_DMA_TEDMA	(0x1 << 6)      /* TXFIFO Empty Status */
 #define SPI_DMA_THDMA	(0x1 << 7)      /* TXFIFO Half Status */
@@ -1163,6 +1163,9 @@
 	return -EINVAL;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
 /* On first setup bad values must free chip_data memory since will cause
    spi_new_device to fail. Bad value setup from protocol driver are simply not
    applied and notified to the calling driver. */
@@ -1174,6 +1177,12 @@
 	u32 tmp;
 	int status = 0;
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	/* Get controller data */
 	chip_info = spi->controller_data;
 
@@ -1245,21 +1254,6 @@
 
 	/* SPI mode */
 	tmp = spi->mode;
-	if (tmp & SPI_LSB_FIRST) {
-		status = -EINVAL;
-		if (first_setup) {
-			dev_err(&spi->dev,
-				"setup - "
-				"HW doesn't support LSB first transfer\n");
-			goto err_first_setup;
-		} else {
-			dev_err(&spi->dev,
-				"setup - "
-				"HW doesn't support LSB first transfer, "
-				"default to MSB first\n");
-			spi->mode &= ~SPI_LSB_FIRST;
-		}
-	}
 	if (tmp & SPI_CS_HIGH) {
 		u32_EDIT(chip->control,
 				SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH);
@@ -1355,6 +1349,7 @@
 		spi->bits_per_word,
 		spi_speed_hz(SPI_CONTROL_DATARATE_MIN),
 		spi->max_speed_hz);
+	return status;
 
 err_first_setup:
 	kfree(chip);
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c
new file mode 100644
index 0000000..4ea68ac
--- /dev/null
+++ b/drivers/spi/spi_lm70llp.c
@@ -0,0 +1,361 @@
+/*
+ * spi_lm70llp.c - driver for lm70llp eval board for the LM70 sensor
+ *
+ * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/parport.h>
+#include <linux/sysfs.h>
+#include <linux/workqueue.h>
+
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+
+/*
+ * The LM70 communicates with a host processor using a 3-wire variant of
+ * the SPI/Microwire bus interface. This driver specifically supports an
+ * NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel
+ * port to bitbang an SPI-parport bridge.  Accordingly, this is an SPI
+ * master controller driver.  The hwmon/lm70 driver is a "SPI protocol
+ * driver", layered on top of this one and usable without the lm70llp.
+ *
+ * The LM70 is a temperature sensor chip from National Semiconductor; its
+ * datasheet is available at http://www.national.com/pf/LM/LM70.html
+ *
+ * Also see Documentation/spi/spi-lm70llp.  The SPI<->parport code here is
+ * (heavily) based on spi-butterfly by David Brownell.
+ *
+ * The LM70 LLP connects to the PC parallel port in the following manner:
+ *
+ *   Parallel                 LM70 LLP
+ *     Port      Direction   JP2 Header
+ *  -----------  ---------  ------------
+ *      D0    2      -         -
+ *      D1    3     -->      V+   5
+ *      D2    4     -->      V+   5
+ *      D3    5     -->      V+   5
+ *      D4    6     -->      V+   5
+ *      D5    7     -->      nCS  8
+ *      D6    8     -->      SCLK 3
+ *      D7    9     -->      SI/O 5
+ *     GND   25      -       GND  7
+ *    Select 13     <--      SI/O 1
+ *
+ * Note that parport pin 13 actually gets inverted by the transistor
+ * arrangement which lets either the parport or the LM70 drive the
+ * SI/SO signal.
+ */
+
+#define DRVNAME		"spi-lm70llp"
+
+#define lm70_INIT	0xBE
+#define SIO		0x10
+#define nCS		0x20
+#define SCLK		0x40
+
+/*-------------------------------------------------------------------------*/
+
+struct spi_lm70llp {
+	struct spi_bitbang	bitbang;
+	struct parport		*port;
+	struct pardevice	*pd;
+	struct spi_device	*spidev_lm70;
+	struct spi_board_info	info;
+	struct class_device	*cdev;
+};
+
+/* REVISIT : ugly global ; provides "exclusive open" facility */
+static struct spi_lm70llp *lm70llp;
+
+
+/*-------------------------------------------------------------------*/
+
+static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi)
+{
+	return spi->controller_data;
+}
+
+/*---------------------- LM70 LLP eval board-specific inlines follow */
+
+/* NOTE:  we don't actually need to reread the output values, since they'll
+ * still be what we wrote before.  Plus, going through parport builds in
+ * a ~1ms/operation delay; these SPI transfers could easily be faster.
+ */
+
+static inline void deassertCS(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data | nCS);
+}
+
+static inline void assertCS(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data & ~nCS);
+}
+
+static inline void clkHigh(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data | SCLK);
+}
+
+static inline void clkLow(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data & ~SCLK);
+}
+
+/*------------------------- SPI-LM70-specific inlines ----------------------*/
+
+static inline void spidelay(unsigned d)
+{
+	udelay(d);
+}
+
+static inline void setsck(struct spi_device *s, int is_on)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(s);
+
+	if (is_on)
+		clkHigh(pp);
+	else
+		clkLow(pp);
+}
+
+static inline void setmosi(struct spi_device *s, int is_on)
+{
+	/* FIXME update D7 ... this way we can put the chip
+	 * into shutdown mode and read the manufacturer ID,
+	 * but we can't put it back into operational mode.
+	 */
+}
+
+/*
+ * getmiso:
+ * Why do we return 0 when the SIO line is high and vice-versa?
+ * The fact is, the lm70 eval board from NS (which this driver drives),
+ * is wired in just such a way : when the lm70's SIO goes high, a transistor
+ * switches it to low reflecting this on the parport (pin 13), and vice-versa.
+ */
+static inline int getmiso(struct spi_device *s)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(s);
+	return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1 );
+}
+/*--------------------------------------------------------------------*/
+
+#define EXPAND_BITBANG_TXRX 1
+#include <linux/spi/spi_bitbang.h>
+
+static void lm70_chipselect(struct spi_device *spi, int value)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(spi);
+
+	if (value)
+		assertCS(pp);
+	else
+		deassertCS(pp);
+}
+
+/*
+ * Our actual bitbanger routine.
+ */
+static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
+{
+	static u32 sio=0;
+	static int first_time=1;
+
+	/* First time: perform SPI bitbang and return the LSB of
+	 * the result of the SPI call.
+	 */
+	if (first_time) {
+		sio = bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
+		first_time=0;
+		return (sio & 0x00ff);
+	}
+	/* Return the MSB of the result of the SPI call */
+	else {
+		first_time=1;
+		return (sio >> 8);
+	}
+}
+
+static void spi_lm70llp_attach(struct parport *p)
+{
+	struct pardevice	*pd;
+	struct spi_lm70llp	*pp;
+	struct spi_master	*master;
+	int			status;
+
+	if (lm70llp) {
+		printk(KERN_WARNING
+			"%s: spi_lm70llp instance already loaded. Aborting.\n",
+			DRVNAME);
+		return;
+	}
+
+	/* TODO:  this just _assumes_ a lm70 is there ... no probe;
+	 * the lm70 driver could verify it, reading the manf ID.
+	 */
+
+	master = spi_alloc_master(p->physport->dev, sizeof *pp);
+	if (!master) {
+		status = -ENOMEM;
+		goto out_fail;
+	}
+	pp = spi_master_get_devdata(master);
+
+	master->bus_num = -1;	/* dynamic alloc of a bus number */
+	master->num_chipselect = 1;
+
+	/*
+	 * SPI and bitbang hookup.
+	 */
+	pp->bitbang.master = spi_master_get(master);
+	pp->bitbang.chipselect = lm70_chipselect;
+	pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
+	pp->bitbang.flags = SPI_3WIRE;
+
+	/*
+	 * Parport hookup
+	 */
+	pp->port = p;
+	pd = parport_register_device(p, DRVNAME,
+			NULL, NULL, NULL,
+			PARPORT_FLAG_EXCL, pp);
+	if (!pd) {
+		status = -ENOMEM;
+		goto out_free_master;
+	}
+	pp->pd = pd;
+
+	status = parport_claim(pd);
+	if (status < 0)
+		goto out_parport_unreg;
+
+	/*
+	 * Start SPI ...
+	 */
+	status = spi_bitbang_start(&pp->bitbang);
+	if (status < 0) {
+		printk(KERN_WARNING
+			"%s: spi_bitbang_start failed with status %d\n",
+			DRVNAME, status);
+		goto out_off_and_release;
+	}
+
+	/*
+	 * The modalias name MUST match the device_driver name
+	 * for the bus glue code to match and subsequently bind them.
+	 * We are binding to the generic drivers/hwmon/lm70.c device
+	 * driver.
+	 */
+	strcpy(pp->info.modalias, "lm70");
+	pp->info.max_speed_hz = 6 * 1000 * 1000;
+	pp->info.chip_select = 0;
+	pp->info.mode = SPI_3WIRE | SPI_MODE_0;
+
+	/* power up the chip, and let the LM70 control SI/SO */
+	parport_write_data(pp->port, lm70_INIT);
+
+	/* Enable access to our primary data structure via
+	 * the board info's (void *)controller_data.
+	 */
+	pp->info.controller_data = pp;
+	pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info);
+	if (pp->spidev_lm70)
+		dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n",
+				pp->spidev_lm70->dev.bus_id);
+	else {
+		printk(KERN_WARNING "%s: spi_new_device failed\n", DRVNAME);
+		status = -ENODEV;
+		goto out_bitbang_stop;
+	}
+	pp->spidev_lm70->bits_per_word = 16;
+
+	lm70llp = pp;
+
+	return;
+
+out_bitbang_stop:
+	spi_bitbang_stop(&pp->bitbang);
+out_off_and_release:
+	/* power down */
+	parport_write_data(pp->port, 0);
+	mdelay(10);
+	parport_release(pp->pd);
+out_parport_unreg:
+	parport_unregister_device(pd);
+out_free_master:
+	(void) spi_master_put(master);
+out_fail:
+	pr_info("%s: spi_lm70llp probe fail, status %d\n", DRVNAME, status);
+}
+
+static void spi_lm70llp_detach(struct parport *p)
+{
+	struct spi_lm70llp		*pp;
+
+	if (!lm70llp || lm70llp->port != p)
+		return;
+
+	pp = lm70llp;
+	spi_bitbang_stop(&pp->bitbang);
+
+	/* power down */
+	parport_write_data(pp->port, 0);
+	msleep(10);
+
+	parport_release(pp->pd);
+	parport_unregister_device(pp->pd);
+
+	(void) spi_master_put(pp->bitbang.master);
+
+	lm70llp = NULL;
+}
+
+
+static struct parport_driver spi_lm70llp_drv = {
+	.name =		DRVNAME,
+	.attach =	spi_lm70llp_attach,
+	.detach =	spi_lm70llp_detach,
+};
+
+static int __init init_spi_lm70llp(void)
+{
+	return parport_register_driver(&spi_lm70llp_drv);
+}
+module_init(init_spi_lm70llp);
+
+static void __exit cleanup_spi_lm70llp(void)
+{
+	parport_unregister_driver(&spi_lm70llp_drv);
+}
+module_exit(cleanup_spi_lm70llp);
+
+MODULE_AUTHOR("Kaiwan N Billimoria <kaiwan@designergraphix.com>");
+MODULE_DESCRIPTION(
+	"Parport adapter for the National Semiconductor LM70 LLP eval board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index e9798bf..3295cfc 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -47,6 +47,7 @@
 #define	SPMODE_ENABLE		(1 << 24)
 #define	SPMODE_LEN(x)		((x) << 20)
 #define	SPMODE_PM(x)		((x) << 16)
+#define	SPMODE_OP		(1 << 14)
 
 /*
  * Default for SPI Mode:
@@ -85,6 +86,11 @@
 	unsigned nsecs;		/* (clock cycle time)/2 */
 
 	u32 sysclk;
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+
+	bool qe_mode;
+
 	void (*activate_cs) (u8 cs, u8 polarity);
 	void (*deactivate_cs) (u8 cs, u8 polarity);
 };
@@ -103,7 +109,7 @@
 void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \
 {									  \
 	type * rx = mpc83xx_spi->rx;					  \
-	*rx++ = (type)data;						  \
+	*rx++ = (type)(data >> mpc83xx_spi->rx_shift);			  \
 	mpc83xx_spi->rx = rx;						  \
 }
 
@@ -114,7 +120,7 @@
 	const type * tx = mpc83xx_spi->tx;			\
 	if (!tx)						\
 		return 0;					\
-	data = *tx++;						\
+	data = *tx++ << mpc83xx_spi->tx_shift;			\
 	mpc83xx_spi->tx = tx;					\
 	return data;						\
 }
@@ -158,6 +164,12 @@
 
 		if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) {
 			u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64);
+			if (pm > 0x0f) {
+				printk(KERN_WARNING "MPC83xx SPI: SPICLK can't be less then a SYSCLK/1024!\n"
+						"Requested SPICLK is %d Hz. Will use %d Hz instead.\n",
+						spi->max_speed_hz, mpc83xx_spi->sysclk / 1024);
+				pm = 0x0f;
+			}
 			regval |= SPMODE_PM(pm) | SPMODE_DIV16;
 		} else {
 			u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4);
@@ -197,12 +209,22 @@
 	    || ((bits_per_word > 16) && (bits_per_word != 32)))
 		return -EINVAL;
 
+	mpc83xx_spi->rx_shift = 0;
+	mpc83xx_spi->tx_shift = 0;
 	if (bits_per_word <= 8) {
 		mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
 		mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
+		if (mpc83xx_spi->qe_mode) {
+			mpc83xx_spi->rx_shift = 16;
+			mpc83xx_spi->tx_shift = 24;
+		}
 	} else if (bits_per_word <= 16) {
 		mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16;
 		mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16;
+		if (mpc83xx_spi->qe_mode) {
+			mpc83xx_spi->rx_shift = 16;
+			mpc83xx_spi->tx_shift = 16;
+		}
 	} else if (bits_per_word <= 32) {
 		mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32;
 		mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32;
@@ -232,12 +254,21 @@
 	return 0;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
 static int mpc83xx_spi_setup(struct spi_device *spi)
 {
 	struct spi_bitbang *bitbang;
 	struct mpc83xx_spi *mpc83xx_spi;
 	int retval;
 
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
 	if (!spi->max_speed_hz)
 		return -EINVAL;
 
@@ -371,7 +402,6 @@
 		ret = -ENODEV;
 		goto free_master;
 	}
-
 	mpc83xx_spi = spi_master_get_devdata(master);
 	mpc83xx_spi->bitbang.master = spi_master_get(master);
 	mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect;
@@ -380,9 +410,17 @@
 	mpc83xx_spi->sysclk = pdata->sysclk;
 	mpc83xx_spi->activate_cs = pdata->activate_cs;
 	mpc83xx_spi->deactivate_cs = pdata->deactivate_cs;
+	mpc83xx_spi->qe_mode = pdata->qe_mode;
 	mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
 	mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
 
+	mpc83xx_spi->rx_shift = 0;
+	mpc83xx_spi->tx_shift = 0;
+	if (mpc83xx_spi->qe_mode) {
+		mpc83xx_spi->rx_shift = 16;
+		mpc83xx_spi->tx_shift = 24;
+	}
+
 	mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup;
 	init_completion(&mpc83xx_spi->done);
 
@@ -417,6 +455,9 @@
 
 	/* Enable SPI interface */
 	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+	if (pdata->qe_mode)
+		regval |= SPMODE_OP;
+
 	mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
 
 	ret = spi_bitbang_start(&mpc83xx_spi->bitbang);
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index d5a710f..7071ff8 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -146,6 +146,9 @@
 	return 0;
 }
 
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
 static int s3c24xx_spi_setup(struct spi_device *spi)
 {
 	int ret;
@@ -153,8 +156,11 @@
 	if (!spi->bits_per_word)
 		spi->bits_per_word = 8;
 
-	if ((spi->mode & SPI_LSB_FIRST) != 0)
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
 		return -EINVAL;
+	}
 
 	ret = s3c24xx_spi_setupxfer(spi, NULL);
 	if (ret < 0) {
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
new file mode 100644
index 0000000..08e981c
--- /dev/null
+++ b/drivers/spi/spi_txx9.c
@@ -0,0 +1,474 @@
+/*
+ * spi_txx9.c - TXx9 SPI controller driver.
+ *
+ * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ *
+ * Convert to generic SPI framework - Atsushi Nemoto (anemo@mba.ocn.ne.jp)
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <asm/gpio.h>
+
+
+#define SPI_FIFO_SIZE 4
+
+#define TXx9_SPMCR		0x00
+#define TXx9_SPCR0		0x04
+#define TXx9_SPCR1		0x08
+#define TXx9_SPFS		0x0c
+#define TXx9_SPSR		0x14
+#define TXx9_SPDR		0x18
+
+/* SPMCR : SPI Master Control */
+#define TXx9_SPMCR_OPMODE	0xc0
+#define TXx9_SPMCR_CONFIG	0x40
+#define TXx9_SPMCR_ACTIVE	0x80
+#define TXx9_SPMCR_SPSTP	0x02
+#define TXx9_SPMCR_BCLR		0x01
+
+/* SPCR0 : SPI Control 0 */
+#define TXx9_SPCR0_TXIFL_MASK	0xc000
+#define TXx9_SPCR0_RXIFL_MASK	0x3000
+#define TXx9_SPCR0_SIDIE	0x0800
+#define TXx9_SPCR0_SOEIE	0x0400
+#define TXx9_SPCR0_RBSIE	0x0200
+#define TXx9_SPCR0_TBSIE	0x0100
+#define TXx9_SPCR0_IFSPSE	0x0010
+#define TXx9_SPCR0_SBOS		0x0004
+#define TXx9_SPCR0_SPHA		0x0002
+#define TXx9_SPCR0_SPOL		0x0001
+
+/* SPSR : SPI Status */
+#define TXx9_SPSR_TBSI		0x8000
+#define TXx9_SPSR_RBSI		0x4000
+#define TXx9_SPSR_TBS_MASK	0x3800
+#define TXx9_SPSR_RBS_MASK	0x0700
+#define TXx9_SPSR_SPOE		0x0080
+#define TXx9_SPSR_IFSD		0x0008
+#define TXx9_SPSR_SIDLE		0x0004
+#define TXx9_SPSR_STRDY		0x0002
+#define TXx9_SPSR_SRRDY		0x0001
+
+
+struct txx9spi {
+	struct workqueue_struct	*workqueue;
+	struct work_struct work;
+	spinlock_t lock;	/* protect 'queue' */
+	struct list_head queue;
+	wait_queue_head_t waitq;
+	void __iomem *membase;
+	int irq;
+	int baseclk;
+	struct clk *clk;
+	u32 max_speed_hz, min_speed_hz;
+	int last_chipselect;
+	int last_chipselect_val;
+};
+
+static u32 txx9spi_rd(struct txx9spi *c, int reg)
+{
+	return __raw_readl(c->membase + reg);
+}
+static void txx9spi_wr(struct txx9spi *c, u32 val, int reg)
+{
+	__raw_writel(val, c->membase + reg);
+}
+
+static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c,
+		int on, unsigned int cs_delay)
+{
+	int val = (spi->mode & SPI_CS_HIGH) ? on : !on;
+	if (on) {
+		/* deselect the chip with cs_change hint in last transfer */
+		if (c->last_chipselect >= 0)
+			gpio_set_value(c->last_chipselect,
+					!c->last_chipselect_val);
+		c->last_chipselect = spi->chip_select;
+		c->last_chipselect_val = val;
+	} else {
+		c->last_chipselect = -1;
+		ndelay(cs_delay);	/* CS Hold Time */
+	}
+	gpio_set_value(spi->chip_select, val);
+	ndelay(cs_delay);	/* CS Setup Time / CS Recovery Time */
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS	(SPI_CS_HIGH|SPI_CPOL|SPI_CPHA)
+
+static int txx9spi_setup(struct spi_device *spi)
+{
+	struct txx9spi *c = spi_master_get_devdata(spi->master);
+	u8 bits_per_word;
+
+	if (spi->mode & ~MODEBITS)
+		return -EINVAL;
+
+	if (!spi->max_speed_hz
+			|| spi->max_speed_hz > c->max_speed_hz
+			|| spi->max_speed_hz < c->min_speed_hz)
+		return -EINVAL;
+
+	bits_per_word = spi->bits_per_word ? : 8;
+	if (bits_per_word != 8 && bits_per_word != 16)
+		return -EINVAL;
+
+	if (gpio_direction_output(spi->chip_select,
+			!(spi->mode & SPI_CS_HIGH))) {
+		dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n");
+		return -EINVAL;
+	}
+
+	/* deselect chip */
+	spin_lock(&c->lock);
+	txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz);
+	spin_unlock(&c->lock);
+
+	return 0;
+}
+
+static irqreturn_t txx9spi_interrupt(int irq, void *dev_id)
+{
+	struct txx9spi *c = dev_id;
+
+	/* disable rx intr */
+	txx9spi_wr(c, txx9spi_rd(c, TXx9_SPCR0) & ~TXx9_SPCR0_RBSIE,
+			TXx9_SPCR0);
+	wake_up(&c->waitq);
+	return IRQ_HANDLED;
+}
+
+static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
+{
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t;
+	unsigned int cs_delay;
+	unsigned int cs_change = 1;
+	int status = 0;
+	u32 mcr;
+	u32 prev_speed_hz = 0;
+	u8 prev_bits_per_word = 0;
+
+	/* CS setup/hold/recovery time in nsec */
+	cs_delay = 100 + (NSEC_PER_SEC / 2) / spi->max_speed_hz;
+
+	mcr = txx9spi_rd(c, TXx9_SPMCR);
+	if (unlikely((mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE)) {
+		dev_err(&spi->dev, "Bad mode.\n");
+		status = -EIO;
+		goto exit;
+	}
+	mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
+
+	/* enter config mode */
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+	txx9spi_wr(c, TXx9_SPCR0_SBOS
+			| ((spi->mode & SPI_CPOL) ? TXx9_SPCR0_SPOL : 0)
+			| ((spi->mode & SPI_CPHA) ? TXx9_SPCR0_SPHA : 0)
+			| 0x08,
+			TXx9_SPCR0);
+
+	list_for_each_entry (t, &m->transfers, transfer_list) {
+		const void *txbuf = t->tx_buf;
+		void *rxbuf = t->rx_buf;
+		u32 data;
+		unsigned int len = t->len;
+		unsigned int wsize;
+		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+		u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
+
+		bits_per_word = bits_per_word ? : 8;
+		wsize = bits_per_word >> 3; /* in bytes */
+
+		if (prev_speed_hz != speed_hz
+				|| prev_bits_per_word != bits_per_word) {
+			u32 n = (c->baseclk + speed_hz - 1) / speed_hz;
+			if (n < 1)
+				n = 1;
+			else if (n > 0xff)
+				n = 0xff;
+			/* enter config mode */
+			txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR,
+					TXx9_SPMCR);
+			txx9spi_wr(c, (n << 8) | bits_per_word, TXx9_SPCR1);
+			/* enter active mode */
+			txx9spi_wr(c, mcr | TXx9_SPMCR_ACTIVE, TXx9_SPMCR);
+
+			prev_speed_hz = speed_hz;
+			prev_bits_per_word = bits_per_word;
+		}
+
+		if (cs_change)
+			txx9spi_cs_func(spi, c, 1, cs_delay);
+		cs_change = t->cs_change;
+		while (len) {
+			unsigned int count = SPI_FIFO_SIZE;
+			int i;
+			u32 cr0;
+
+			if (len < count * wsize)
+				count = len / wsize;
+			/* now tx must be idle... */
+			while (!(txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_SIDLE))
+				cpu_relax();
+			cr0 = txx9spi_rd(c, TXx9_SPCR0);
+			cr0 &= ~TXx9_SPCR0_RXIFL_MASK;
+			cr0 |= (count - 1) << 12;
+			/* enable rx intr */
+			cr0 |= TXx9_SPCR0_RBSIE;
+			txx9spi_wr(c, cr0, TXx9_SPCR0);
+			/* send */
+			for (i = 0; i < count; i++) {
+				if (txbuf) {
+					data = (wsize == 1)
+						? *(const u8 *)txbuf
+						: *(const u16 *)txbuf;
+					txx9spi_wr(c, data, TXx9_SPDR);
+					txbuf += wsize;
+				} else
+					txx9spi_wr(c, 0, TXx9_SPDR);
+			}
+			/* wait all rx data */
+			wait_event(c->waitq,
+				txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_RBSI);
+			/* receive */
+			for (i = 0; i < count; i++) {
+				data = txx9spi_rd(c, TXx9_SPDR);
+				if (rxbuf) {
+					if (wsize == 1)
+						*(u8 *)rxbuf = data;
+					else
+						*(u16 *)rxbuf = data;
+					rxbuf += wsize;
+				}
+			}
+			len -= count * wsize;
+		}
+		m->actual_length += t->len;
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (!cs_change)
+			continue;
+		if (t->transfer_list.next == &m->transfers)
+			break;
+		/* sometimes a short mid-message deselect of the chip
+		 * may be needed to terminate a mode or command
+		 */
+		txx9spi_cs_func(spi, c, 0, cs_delay);
+	}
+
+exit:
+	m->status = status;
+	m->complete(m->context);
+
+	/* normally deactivate chipselect ... unless no error and
+	 * cs_change has hinted that the next message will probably
+	 * be for this chip too.
+	 */
+	if (!(status == 0 && cs_change))
+		txx9spi_cs_func(spi, c, 0, cs_delay);
+
+	/* enter config mode */
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+}
+
+static void txx9spi_work(struct work_struct *work)
+{
+	struct txx9spi *c = container_of(work, struct txx9spi, work);
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->lock, flags);
+	while (!list_empty(&c->queue)) {
+		struct spi_message *m;
+
+		m = container_of(c->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock_irqrestore(&c->lock, flags);
+
+		txx9spi_work_one(c, m);
+
+		spin_lock_irqsave(&c->lock, flags);
+	}
+	spin_unlock_irqrestore(&c->lock, flags);
+}
+
+static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct spi_master *master = spi->master;
+	struct txx9spi *c = spi_master_get_devdata(master);
+	struct spi_transfer *t;
+	unsigned long flags;
+
+	m->actual_length = 0;
+
+	/* check each transfer's parameters */
+	list_for_each_entry (t, &m->transfers, transfer_list) {
+		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+		u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
+
+		bits_per_word = bits_per_word ? : 8;
+		if (!t->tx_buf && !t->rx_buf && t->len)
+			return -EINVAL;
+		if (bits_per_word != 8 && bits_per_word != 16)
+			return -EINVAL;
+		if (t->len & ((bits_per_word >> 3) - 1))
+			return -EINVAL;
+		if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
+			return -EINVAL;
+	}
+
+	spin_lock_irqsave(&c->lock, flags);
+	list_add_tail(&m->queue, &c->queue);
+	queue_work(c->workqueue, &c->work);
+	spin_unlock_irqrestore(&c->lock, flags);
+
+	return 0;
+}
+
+static int __init txx9spi_probe(struct platform_device *dev)
+{
+	struct spi_master *master;
+	struct txx9spi *c;
+	struct resource *res;
+	int ret = -ENODEV;
+	u32 mcr;
+
+	master = spi_alloc_master(&dev->dev, sizeof(*c));
+	if (!master)
+		return ret;
+	c = spi_master_get_devdata(master);
+	c->irq = -1;
+	platform_set_drvdata(dev, master);
+
+	INIT_WORK(&c->work, txx9spi_work);
+	spin_lock_init(&c->lock);
+	INIT_LIST_HEAD(&c->queue);
+	init_waitqueue_head(&c->waitq);
+
+	c->clk = clk_get(&dev->dev, "spi-baseclk");
+	if (IS_ERR(c->clk)) {
+		ret = PTR_ERR(c->clk);
+		c->clk = NULL;
+		goto exit;
+	}
+	ret = clk_enable(c->clk);
+	if (ret) {
+		clk_put(c->clk);
+		c->clk = NULL;
+		goto exit;
+	}
+	c->baseclk = clk_get_rate(c->clk);
+	c->min_speed_hz = (c->baseclk + 0xff - 1) / 0xff;
+	c->max_speed_hz = c->baseclk;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit;
+	c->membase = ioremap(res->start, res->end - res->start + 1);
+	if (!c->membase)
+		goto exit;
+
+	/* enter config mode */
+	mcr = txx9spi_rd(c, TXx9_SPMCR);
+	mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+
+	c->irq = platform_get_irq(dev, 0);
+	if (c->irq < 0)
+		goto exit;
+	ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c);
+	if (ret) {
+		c->irq = -1;
+		goto exit;
+	}
+
+	c->workqueue = create_singlethread_workqueue(master->cdev.dev->bus_id);
+	if (!c->workqueue)
+		goto exit;
+	c->last_chipselect = -1;
+
+	dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
+		 (unsigned long long)res->start, c->irq,
+		 (c->baseclk + 500000) / 1000000);
+
+	master->bus_num = dev->id;
+	master->setup = txx9spi_setup;
+	master->transfer = txx9spi_transfer;
+	master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */
+
+	ret = spi_register_master(master);
+	if (ret)
+		goto exit;
+	return 0;
+exit:
+	if (c->workqueue)
+		destroy_workqueue(c->workqueue);
+	if (c->irq >= 0)
+		free_irq(c->irq, c);
+	if (c->membase)
+		iounmap(c->membase);
+	if (c->clk) {
+		clk_disable(c->clk);
+		clk_put(c->clk);
+	}
+	platform_set_drvdata(dev, NULL);
+	spi_master_put(master);
+	return ret;
+}
+
+static int __exit txx9spi_remove(struct platform_device *dev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
+	struct txx9spi *c = spi_master_get_devdata(master);
+
+	spi_unregister_master(master);
+	platform_set_drvdata(dev, NULL);
+	destroy_workqueue(c->workqueue);
+	free_irq(c->irq, c);
+	iounmap(c->membase);
+	clk_disable(c->clk);
+	clk_put(c->clk);
+	spi_master_put(master);
+	return 0;
+}
+
+static struct platform_driver txx9spi_driver = {
+	.remove = __exit_p(txx9spi_remove),
+	.driver = {
+		.name = "txx9spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init txx9spi_init(void)
+{
+	return platform_driver_probe(&txx9spi_driver, txx9spi_probe);
+}
+subsys_initcall(txx9spi_init);
+
+static void __exit txx9spi_exit(void)
+{
+	platform_driver_unregister(&txx9spi_driver);
+}
+module_exit(txx9spi_exit);
+
+MODULE_DESCRIPTION("TXx9 SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 225d6b2..38b60ad 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -168,6 +168,12 @@
 			n--, k_tmp++, u_tmp++) {
 		k_tmp->len = u_tmp->len;
 
+		total += k_tmp->len;
+		if (total > bufsiz) {
+			status = -EMSGSIZE;
+			goto done;
+		}
+
 		if (u_tmp->rx_buf) {
 			k_tmp->rx_buf = buf;
 			if (!access_ok(VERIFY_WRITE, u_tmp->rx_buf, u_tmp->len))
@@ -175,16 +181,11 @@
 		}
 		if (u_tmp->tx_buf) {
 			k_tmp->tx_buf = buf;
-			if (copy_from_user(buf, (const u8 __user *)u_tmp->tx_buf,
+			if (copy_from_user(buf, (const u8 __user *)
+						(ptrdiff_t) u_tmp->tx_buf,
 					u_tmp->len))
 				goto done;
 		}
-
-		total += k_tmp->len;
-		if (total > bufsiz) {
-			status = -EMSGSIZE;
-			goto done;
-		}
 		buf += k_tmp->len;
 
 		k_tmp->cs_change = !!u_tmp->cs_change;
@@ -213,7 +214,8 @@
 	buf = spidev->buffer;
 	for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
 		if (u_tmp->rx_buf) {
-			if (__copy_to_user((u8 __user *)u_tmp->rx_buf, buf,
+			if (__copy_to_user((u8 __user *)
+					(ptrdiff_t) u_tmp->rx_buf, buf,
 					u_tmp->len)) {
 				status = -EFAULT;
 				goto done;
@@ -364,6 +366,7 @@
 			break;
 		}
 		if (__copy_from_user(ioc, (void __user *)arg, tmp)) {
+			kfree(ioc);
 			retval = -EFAULT;
 			break;
 		}
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c
new file mode 100644
index 0000000..6da58ca
--- /dev/null
+++ b/drivers/spi/tle62x0.c
@@ -0,0 +1,328 @@
+/*
+ * tle62x0.c -- support Infineon TLE62x0 driver chips
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks, <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/tle62x0.h>
+
+
+#define CMD_READ	0x00
+#define CMD_SET		0xff
+
+#define DIAG_NORMAL	0x03
+#define DIAG_OVERLOAD	0x02
+#define DIAG_OPEN	0x01
+#define DIAG_SHORTGND	0x00
+
+struct tle62x0_state {
+	struct spi_device	*us;
+	struct mutex		lock;
+	unsigned int		nr_gpio;
+	unsigned int		gpio_state;
+
+	unsigned char		tx_buff[4];
+	unsigned char		rx_buff[4];
+};
+
+static int to_gpio_num(struct device_attribute *attr);
+
+static inline int tle62x0_write(struct tle62x0_state *st)
+{
+	unsigned char *buff = st->tx_buff;
+	unsigned int gpio_state = st->gpio_state;
+
+	buff[0] = CMD_SET;
+
+	if (st->nr_gpio == 16) {
+		buff[1] = gpio_state >> 8;
+		buff[2] = gpio_state;
+	} else {
+		buff[1] = gpio_state;
+	}
+
+	dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n",
+		buff[0], buff[1], buff[2]);
+
+	return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
+}
+
+static inline int tle62x0_read(struct tle62x0_state *st)
+{
+	unsigned char *txbuff = st->tx_buff;
+	struct spi_transfer xfer = {
+		.tx_buf		= txbuff,
+		.rx_buf		= st->rx_buff,
+		.len		= (st->nr_gpio * 2) / 8,
+	};
+	struct spi_message msg;
+
+	txbuff[0] = CMD_READ;
+	txbuff[1] = 0x00;
+	txbuff[2] = 0x00;
+	txbuff[3] = 0x00;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	return spi_sync(st->us, &msg);
+}
+
+static unsigned char *decode_fault(unsigned int fault_code)
+{
+	fault_code &= 3;
+
+	switch (fault_code) {
+	case DIAG_NORMAL:
+		return "N";
+	case DIAG_OVERLOAD:
+		return "V";
+	case DIAG_OPEN:
+		return "O";
+	case DIAG_SHORTGND:
+		return "G";
+	}
+
+	return "?";
+}
+
+static ssize_t tle62x0_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	char *bp = buf;
+	unsigned char *buff = st->rx_buff;
+	unsigned long fault = 0;
+	int ptr;
+	int ret;
+
+	mutex_lock(&st->lock);
+	ret = tle62x0_read(st);
+
+	dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
+
+	for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
+		fault <<= 8;
+		fault  |= ((unsigned long)buff[ptr]);
+
+		dev_dbg(dev, "byte %d is %02x\n", ptr, buff[ptr]);
+	}
+
+	for (ptr = 0; ptr < st->nr_gpio; ptr++) {
+		bp += sprintf(bp, "%s ", decode_fault(fault >> (ptr * 2)));
+	}
+
+	*bp++ = '\n';
+
+	mutex_unlock(&st->lock);
+	return bp - buf;
+}
+
+static DEVICE_ATTR(status_show, S_IRUGO, tle62x0_status_show, NULL);
+
+static ssize_t tle62x0_gpio_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	int gpio_num = to_gpio_num(attr);
+	int value;
+
+	mutex_lock(&st->lock);
+	value = (st->gpio_state >> gpio_num) & 1;
+	mutex_unlock(&st->lock);
+
+	return snprintf(buf, PAGE_SIZE, "%d", value);
+}
+
+static ssize_t tle62x0_gpio_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t len)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	int gpio_num = to_gpio_num(attr);
+	unsigned long val;
+	char *endp;
+
+	val = simple_strtoul(buf, &endp, 0);
+	if (buf == endp)
+		return -EINVAL;
+
+	dev_dbg(dev, "setting gpio %d to %ld\n", gpio_num, val);
+
+	mutex_lock(&st->lock);
+
+	if (val)
+		st->gpio_state |= 1 << gpio_num;
+	else
+		st->gpio_state &= ~(1 << gpio_num);
+
+	tle62x0_write(st);
+	mutex_unlock(&st->lock);
+
+	return len;
+}
+
+static DEVICE_ATTR(gpio1, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio2, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio3, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio4, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio5, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio6, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio7, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio8, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio9, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio10, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio11, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio12, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio13, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio14, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio15, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio16, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+
+static struct device_attribute *gpio_attrs[] = {
+	[0]		= &dev_attr_gpio1,
+	[1]		= &dev_attr_gpio2,
+	[2]		= &dev_attr_gpio3,
+	[3]		= &dev_attr_gpio4,
+	[4]		= &dev_attr_gpio5,
+	[5]		= &dev_attr_gpio6,
+	[6]		= &dev_attr_gpio7,
+	[7]		= &dev_attr_gpio8,
+	[8]		= &dev_attr_gpio9,
+	[9]		= &dev_attr_gpio10,
+	[10]		= &dev_attr_gpio11,
+	[11]		= &dev_attr_gpio12,
+	[12]		= &dev_attr_gpio13,
+	[13]		= &dev_attr_gpio14,
+	[14]		= &dev_attr_gpio15,
+	[15]		= &dev_attr_gpio16
+};
+
+static int to_gpio_num(struct device_attribute *attr)
+{
+	int ptr;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(gpio_attrs); ptr++) {
+		if (gpio_attrs[ptr] == attr)
+			return ptr;
+	}
+
+	return -1;
+}
+
+static int __devinit tle62x0_probe(struct spi_device *spi)
+{
+	struct tle62x0_state *st;
+	struct tle62x0_pdata *pdata;
+	int ptr;
+	int ret;
+
+	pdata = spi->dev.platform_data;
+	if (pdata == NULL) {
+		dev_err(&spi->dev, "no device data specified\n");
+		return -EINVAL;
+	}
+
+	st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL);
+	if (st == NULL) {
+		dev_err(&spi->dev, "no memory for device state\n");
+		return -ENOMEM;
+	}
+
+	st->us = spi;
+	st->nr_gpio = pdata->gpio_count;
+	st->gpio_state = pdata->init_state;
+
+	mutex_init(&st->lock);
+
+	ret = device_create_file(&spi->dev, &dev_attr_status_show);
+	if (ret) {
+		dev_err(&spi->dev, "cannot create status attribute\n");
+		goto err_status;
+	}
+
+	for (ptr = 0; ptr < pdata->gpio_count; ptr++) {
+		ret = device_create_file(&spi->dev, gpio_attrs[ptr]);
+		if (ret) {
+			dev_err(&spi->dev, "cannot create gpio attribute\n");
+			goto err_gpios;
+		}
+	}
+
+	/* tle62x0_write(st); */
+	spi_set_drvdata(spi, st);
+	return 0;
+
+ err_gpios:
+	for (; ptr > 0; ptr--)
+		device_remove_file(&spi->dev, gpio_attrs[ptr]);
+
+	device_remove_file(&spi->dev, &dev_attr_status_show);
+
+ err_status:
+	kfree(st);
+	return ret;
+}
+
+static int __devexit tle62x0_remove(struct spi_device *spi)
+{
+	struct tle62x0_state *st = spi_get_drvdata(spi);
+	int ptr;
+
+	for (ptr = 0; ptr < st->nr_gpio; ptr++)
+		device_remove_file(&spi->dev, gpio_attrs[ptr]);
+
+	kfree(st);
+	return 0;
+}
+
+static struct spi_driver tle62x0_driver = {
+	.driver = {
+		.name	= "tle62x0",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tle62x0_probe,
+	.remove		= __devexit_p(tle62x0_remove),
+};
+
+static __init int tle62x0_init(void)
+{
+	return spi_register_driver(&tle62x0_driver);
+}
+
+static __exit void tle62x0_exit(void)
+{
+	spi_unregister_driver(&tle62x0_driver);
+}
+
+module_init(tle62x0_init);
+module_exit(tle62x0_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("TLE62x0 SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
new file mode 100644
index 0000000..f0bf9a6
--- /dev/null
+++ b/drivers/spi/xilinx_spi.c
@@ -0,0 +1,434 @@
+/*
+ * xilinx_spi.c
+ *
+ * Xilinx SPI controller driver (master mode only)
+ *
+ * Author: MontaVista Software, Inc.
+ *	source@mvista.com
+ *
+ * 2002-2007 (c) MontaVista Software, Inc.  This file is licensed under the
+ * terms of the GNU General Public License version 2.  This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/io.h>
+
+#include <syslib/virtex_devices.h>
+
+#define XILINX_SPI_NAME "xspi"
+
+/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
+ * Product Specification", DS464
+ */
+#define XSPI_CR_OFFSET		0x62	/* 16-bit Control Register */
+
+#define XSPI_CR_ENABLE		0x02
+#define XSPI_CR_MASTER_MODE	0x04
+#define XSPI_CR_CPOL		0x08
+#define XSPI_CR_CPHA		0x10
+#define XSPI_CR_MODE_MASK	(XSPI_CR_CPHA | XSPI_CR_CPOL)
+#define XSPI_CR_TXFIFO_RESET	0x20
+#define XSPI_CR_RXFIFO_RESET	0x40
+#define XSPI_CR_MANUAL_SSELECT	0x80
+#define XSPI_CR_TRANS_INHIBIT	0x100
+
+#define XSPI_SR_OFFSET		0x67	/* 8-bit Status Register */
+
+#define XSPI_SR_RX_EMPTY_MASK	0x01	/* Receive FIFO is empty */
+#define XSPI_SR_RX_FULL_MASK	0x02	/* Receive FIFO is full */
+#define XSPI_SR_TX_EMPTY_MASK	0x04	/* Transmit FIFO is empty */
+#define XSPI_SR_TX_FULL_MASK	0x08	/* Transmit FIFO is full */
+#define XSPI_SR_MODE_FAULT_MASK	0x10	/* Mode fault error */
+
+#define XSPI_TXD_OFFSET		0x6b	/* 8-bit Data Transmit Register */
+#define XSPI_RXD_OFFSET		0x6f	/* 8-bit Data Receive Register */
+
+#define XSPI_SSR_OFFSET		0x70	/* 32-bit Slave Select Register */
+
+/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
+ * IPIF registers are 32 bit
+ */
+#define XIPIF_V123B_DGIER_OFFSET	0x1c	/* IPIF global int enable reg */
+#define XIPIF_V123B_GINTR_ENABLE	0x80000000
+
+#define XIPIF_V123B_IISR_OFFSET		0x20	/* IPIF interrupt status reg */
+#define XIPIF_V123B_IIER_OFFSET		0x28	/* IPIF interrupt enable reg */
+
+#define XSPI_INTR_MODE_FAULT		0x01	/* Mode fault error */
+#define XSPI_INTR_SLAVE_MODE_FAULT	0x02	/* Selected as slave while
+						 * disabled */
+#define XSPI_INTR_TX_EMPTY		0x04	/* TxFIFO is empty */
+#define XSPI_INTR_TX_UNDERRUN		0x08	/* TxFIFO was underrun */
+#define XSPI_INTR_RX_FULL		0x10	/* RxFIFO is full */
+#define XSPI_INTR_RX_OVERRUN		0x20	/* RxFIFO was overrun */
+
+#define XIPIF_V123B_RESETR_OFFSET	0x40	/* IPIF reset register */
+#define XIPIF_V123B_RESET_MASK		0x0a	/* the value to write */
+
+struct xilinx_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	void __iomem	*regs;	/* virt. address of the control registers */
+
+	u32		irq;
+
+	u32		speed_hz; /* SCK has a fixed frequency of speed_hz Hz */
+
+	u8 *rx_ptr;		/* pointer in the Tx buffer */
+	const u8 *tx_ptr;	/* pointer in the Rx buffer */
+	int remaining_bytes;	/* the number of bytes left to transfer */
+};
+
+static void xspi_init_hw(void __iomem *regs_base)
+{
+	/* Reset the SPI device */
+	out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET,
+		 XIPIF_V123B_RESET_MASK);
+	/* Disable all the interrupts just in case */
+	out_be32(regs_base + XIPIF_V123B_IIER_OFFSET, 0);
+	/* Enable the global IPIF interrupt */
+	out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET,
+		 XIPIF_V123B_GINTR_ENABLE);
+	/* Deselect the slave on the SPI bus */
+	out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff);
+	/* Disable the transmitter, enable Manual Slave Select Assertion,
+	 * put SPI controller into master mode, and enable it */
+	out_be16(regs_base + XSPI_CR_OFFSET,
+		 XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT
+		 | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE);
+}
+
+static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
+{
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+
+	if (is_on == BITBANG_CS_INACTIVE) {
+		/* Deselect the slave on the SPI bus */
+		out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff);
+	} else if (is_on == BITBANG_CS_ACTIVE) {
+		/* Set the SPI clock phase and polarity */
+		u16 cr = in_be16(xspi->regs + XSPI_CR_OFFSET)
+			 & ~XSPI_CR_MODE_MASK;
+		if (spi->mode & SPI_CPHA)
+			cr |= XSPI_CR_CPHA;
+		if (spi->mode & SPI_CPOL)
+			cr |= XSPI_CR_CPOL;
+		out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+
+		/* We do not check spi->max_speed_hz here as the SPI clock
+		 * frequency is not software programmable (the IP block design
+		 * parameter)
+		 */
+
+		/* Activate the chip select */
+		out_be32(xspi->regs + XSPI_SSR_OFFSET,
+			 ~(0x0001 << spi->chip_select));
+	}
+}
+
+/* spi_bitbang requires custom setup_transfer() to be defined if there is a
+ * custom txrx_bufs(). We have nothing to setup here as the SPI IP block
+ * supports just 8 bits per word, and SPI clock can't be changed in software.
+ * Check for 8 bits per word. Chip select delay calculations could be
+ * added here as soon as bitbang_work() can be made aware of the delay value.
+ */
+static int xilinx_spi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	u8 bits_per_word;
+	u32 hz;
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+
+	bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
+	hz = (t) ? t->speed_hz : spi->max_speed_hz;
+	if (bits_per_word != 8) {
+		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+			__FUNCTION__, bits_per_word);
+		return -EINVAL;
+	}
+
+	if (hz && xspi->speed_hz > hz) {
+		dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
+			__FUNCTION__, hz);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA)
+
+static int xilinx_spi_setup(struct spi_device *spi)
+{
+	struct spi_bitbang *bitbang;
+	struct xilinx_spi *xspi;
+	int retval;
+
+	xspi = spi_master_get_devdata(spi->master);
+	bitbang = &xspi->bitbang;
+
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	if (spi->mode & ~MODEBITS) {
+		dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
+			__FUNCTION__, spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
+	retval = xilinx_spi_setup_transfer(spi, NULL);
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
+		__FUNCTION__, spi->mode & MODEBITS, spi->bits_per_word, 0);
+
+	return 0;
+}
+
+static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
+{
+	u8 sr;
+
+	/* Fill the Tx FIFO with as many bytes as possible */
+	sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+	while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
+		if (xspi->tx_ptr) {
+			out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++);
+		} else {
+			out_8(xspi->regs + XSPI_TXD_OFFSET, 0);
+		}
+		xspi->remaining_bytes--;
+		sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+	}
+}
+
+static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+	u32 ipif_ier;
+	u16 cr;
+
+	/* We get here with transmitter inhibited */
+
+	xspi->tx_ptr = t->tx_buf;
+	xspi->rx_ptr = t->rx_buf;
+	xspi->remaining_bytes = t->len;
+	INIT_COMPLETION(xspi->done);
+
+	xilinx_spi_fill_tx_fifo(xspi);
+
+	/* Enable the transmit empty interrupt, which we use to determine
+	 * progress on the transmission.
+	 */
+	ipif_ier = in_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET);
+	out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET,
+		 ipif_ier | XSPI_INTR_TX_EMPTY);
+
+	/* Start the transfer by not inhibiting the transmitter any longer */
+	cr = in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT;
+	out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+
+	wait_for_completion(&xspi->done);
+
+	/* Disable the transmit empty interrupt */
+	out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, ipif_ier);
+
+	return t->len - xspi->remaining_bytes;
+}
+
+
+/* This driver supports single master mode only. Hence Tx FIFO Empty
+ * is the only interrupt we care about.
+ * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
+ * Fault are not to happen.
+ */
+static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
+{
+	struct xilinx_spi *xspi = dev_id;
+	u32 ipif_isr;
+
+	/* Get the IPIF interrupts, and clear them immediately */
+	ipif_isr = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr);
+
+	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
+		u16 cr;
+		u8 sr;
+
+		/* A transmit has just completed. Process received data and
+		 * check for more data to transmit. Always inhibit the
+		 * transmitter while the Isr refills the transmit register/FIFO,
+		 * or make sure it is stopped if we're done.
+		 */
+		cr = in_be16(xspi->regs + XSPI_CR_OFFSET);
+		out_be16(xspi->regs + XSPI_CR_OFFSET,
+			 cr | XSPI_CR_TRANS_INHIBIT);
+
+		/* Read out all the data from the Rx FIFO */
+		sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+		while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
+			u8 data;
+
+			data = in_8(xspi->regs + XSPI_RXD_OFFSET);
+			if (xspi->rx_ptr) {
+				*xspi->rx_ptr++ = data;
+			}
+			sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+		}
+
+		/* See if there is more data to send */
+		if (xspi->remaining_bytes > 0) {
+			xilinx_spi_fill_tx_fifo(xspi);
+			/* Start the transfer by not inhibiting the
+			 * transmitter any longer
+			 */
+			out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+		} else {
+			/* No more data to send.
+			 * Indicate the transfer is completed.
+			 */
+			complete(&xspi->done);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __init xilinx_spi_probe(struct platform_device *dev)
+{
+	int ret = 0;
+	struct spi_master *master;
+	struct xilinx_spi *xspi;
+	struct xspi_platform_data *pdata;
+	struct resource *r;
+
+	/* Get resources(memory, IRQ) associated with the device */
+	master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi));
+
+	if (master == NULL) {
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(dev, master);
+	pdata = dev->dev.platform_data;
+
+	if (pdata == NULL) {
+		ret = -ENODEV;
+		goto put_master;
+	}
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENODEV;
+		goto put_master;
+	}
+
+	xspi = spi_master_get_devdata(master);
+	xspi->bitbang.master = spi_master_get(master);
+	xspi->bitbang.chipselect = xilinx_spi_chipselect;
+	xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
+	xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
+	xspi->bitbang.master->setup = xilinx_spi_setup;
+	init_completion(&xspi->done);
+
+	if (!request_mem_region(r->start,
+			r->end - r->start + 1, XILINX_SPI_NAME)) {
+		ret = -ENXIO;
+		goto put_master;
+	}
+
+	xspi->regs = ioremap(r->start, r->end - r->start + 1);
+	if (xspi->regs == NULL) {
+		ret = -ENOMEM;
+		goto put_master;
+	}
+
+	xspi->irq = platform_get_irq(dev, 0);
+	if (xspi->irq < 0) {
+		ret = -ENXIO;
+		goto unmap_io;
+	}
+
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->num_chipselect;
+	xspi->speed_hz = pdata->speed_hz;
+
+	/* SPI controller initializations */
+	xspi_init_hw(xspi->regs);
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+	if (ret != 0)
+		goto unmap_io;
+
+	ret = spi_bitbang_start(&xspi->bitbang);
+	if (ret != 0) {
+		dev_err(&dev->dev, "spi_bitbang_start FAILED\n");
+		goto free_irq;
+	}
+
+	dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
+			r->start, (u32)xspi->regs, xspi->irq);
+
+	return ret;
+
+free_irq:
+	free_irq(xspi->irq, xspi);
+unmap_io:
+	iounmap(xspi->regs);
+put_master:
+	spi_master_put(master);
+	return ret;
+}
+
+static int __devexit xilinx_spi_remove(struct platform_device *dev)
+{
+	struct xilinx_spi *xspi;
+	struct spi_master *master;
+
+	master = platform_get_drvdata(dev);
+	xspi = spi_master_get_devdata(master);
+
+	spi_bitbang_stop(&xspi->bitbang);
+	free_irq(xspi->irq, xspi);
+	iounmap(xspi->regs);
+	platform_set_drvdata(dev, 0);
+	spi_master_put(xspi->bitbang.master);
+
+	return 0;
+}
+
+static struct platform_driver xilinx_spi_driver = {
+	.probe	= xilinx_spi_probe,
+	.remove	= __devexit_p(xilinx_spi_remove),
+	.driver = {
+		.name = XILINX_SPI_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init xilinx_spi_init(void)
+{
+	return platform_driver_register(&xilinx_spi_driver);
+}
+module_init(xilinx_spi_init);
+
+static void __exit xilinx_spi_exit(void)
+{
+	platform_driver_unregister(&xilinx_spi_driver);
+}
+module_exit(xilinx_spi_exit);
+
+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_DESCRIPTION("Xilinx SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 3524e3fc..ed979f1 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -136,7 +136,7 @@
 struct tty_struct zs_ttys[NUM_CHANNELS];
 
 #ifdef CONFIG_SERIAL_DEC_CONSOLE
-static struct console sercons;
+static struct console zs_console;
 #endif
 #if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
    !defined(MODULE)
@@ -383,7 +383,7 @@
 
 #if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
    !defined(MODULE)
-		if (break_pressed && info->line == sercons.index) {
+		if (break_pressed && info->line == zs_console.index) {
 			/* Ignore the null char got when BREAK is removed.  */
 			if (ch == 0)
 				continue;
@@ -446,7 +446,7 @@
 	if ((stat & BRK_ABRT) && !(info->read_reg_zero & BRK_ABRT)) {
 #if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
    !defined(MODULE)
-		if (info->line == sercons.index) {
+		if (info->line == zs_console.index) {
 			if (!break_pressed)
 				break_pressed = jiffies;
 		} else
@@ -1557,9 +1557,9 @@
 	}
 
 #ifdef CONFIG_SERIAL_DEC_CONSOLE
-	if (sercons.cflag && sercons.index == line) {
-		tty->termios->c_cflag = sercons.cflag;
-		sercons.cflag = 0;
+	if (zs_console.cflag && zs_console.index == line) {
+		tty->termios->c_cflag = zs_console.cflag;
+		zs_console.cflag = 0;
 		change_speed(info);
 	}
 #endif
@@ -2069,7 +2069,7 @@
 	return 0;
 }
 
-static struct console sercons = {
+static struct console zs_console = {
 	.name		= "ttyS",
 	.write		= serial_console_write,
 	.device		= serial_console_device,
@@ -2083,7 +2083,7 @@
  */
 void __init zs_serial_console_init(void)
 {
-	register_console(&sercons);
+	register_console(&zs_console);
 }
 #endif /* ifdef CONFIG_SERIAL_DEC_CONSOLE */
 
@@ -2182,7 +2182,7 @@
 	.init_info	= kgdbhook_init_info,
 	.rx_char	= kgdbhook_rx_char,
 	.cflags		= B38400 | CS8 | CLOCAL,
-}
+};
 
 void __init zs_kgdb_hook(int tty_num)
 {
diff --git a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig
index dd1d6a5..5f98f67 100644
--- a/drivers/telephony/Kconfig
+++ b/drivers/telephony/Kconfig
@@ -2,11 +2,9 @@
 # Telephony device configuration
 #
 
-menu "Telephony Support"
+menuconfig PHONE
+	tristate "Telephony support"
 	depends on HAS_IOMEM
-
-config PHONE
-	tristate "Linux telephony support"
 	---help---
 	  Say Y here if you have a telephony card, which for example allows
 	  you to use a regular phone for voice-over-IP applications.
@@ -17,9 +15,11 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called phonedev.
 
+if PHONE
+
 config PHONE_IXJ
 	tristate "QuickNet Internet LineJack/PhoneJack support"
-	depends on PHONE
+	depends ISA || PCI
 	---help---
 	  Say M if you have a telephony card manufactured by Quicknet
 	  Technologies, Inc.  These include the Internet PhoneJACK and
@@ -44,5 +44,4 @@
 	  cards manufactured by Quicknet Technologies, Inc.  This changes the
 	  card initialization code to work with the card manager daemon.
 
-endmenu
-
+endif # PHONE
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index c7b0a35..49cd979 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -3453,7 +3453,6 @@
 {
 	int cnt, frame_count, dly;
 	IXJ_WORD dat;
-	BYTES blankword;
 
 	frame_count = 0;
 	if(j->flags.cidplay) {
@@ -3501,6 +3500,8 @@
 		}
 		if (frame_count >= 1) {
 			if (j->ver.low == 0x12 && j->play_mode && j->flags.play_first_frame) {
+				BYTES blankword;
+
 				switch (j->play_mode) {
 				case PLAYBACK_MODE_ULAW:
 				case PLAYBACK_MODE_ALAW:
@@ -3508,6 +3509,7 @@
 					break;
 				case PLAYBACK_MODE_8LINEAR:
 				case PLAYBACK_MODE_16LINEAR:
+				default:
 					blankword.low = blankword.high = 0x00;
 					break;
 				case PLAYBACK_MODE_8LINEAR_WSS:
@@ -3531,6 +3533,8 @@
 				j->flags.play_first_frame = 0;
 			} else	if (j->play_codec == G723_63 && j->flags.play_first_frame) {
 				for (cnt = 0; cnt < 24; cnt++) {
+					BYTES blankword;
+
 					if(cnt == 12) {
 						blankword.low = 0x02;
 						blankword.high = 0x00;
@@ -4868,6 +4872,7 @@
 		bytes.high = 0xB0 + cr;
 		break;
 	case SOP_PU_PULSEDIALING:
+	default:
 		bytes.high = 0xF0 + cr;
 		break;
 	}
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 15499b7..7dd7354 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -2,8 +2,12 @@
 # USB device configuration
 #
 
-menu "USB support"
+menuconfig USB_SUPPORT
+	bool "USB support"
 	depends on HAS_IOMEM
+	default y
+
+if USB_SUPPORT
 
 # Host-side USB depends on having a host controller
 # NOTE:  dummy_hcd is always an option, but it's ignored here ...
@@ -12,6 +16,7 @@
 	boolean
 	default y if USB_ARCH_HAS_OHCI
 	default y if USB_ARCH_HAS_EHCI
+	default y if PCMCIA && !M32R			# sl811_cs
 	default y if ARM				# SL-811
 	default PCI
 
@@ -130,5 +135,4 @@
 
 source "drivers/usb/gadget/Kconfig"
 
-endmenu
-
+endif # USB_SUPPORT
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 72464b5..befff5f 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -15,7 +15,7 @@
 obj-$(CONFIG_USB_UHCI_HCD)	+= host/
 obj-$(CONFIG_USB_SL811_HCD)	+= host/
 obj-$(CONFIG_USB_U132_HCD)	+= host/
-obj-$(CONFIG_USB_OHCI_AT91)	+= host/
+obj-$(CONFIG_USB_R8A66597_HCD)	+= host/
 
 obj-$(CONFIG_USB_ACM)		+= class/
 obj-$(CONFIG_USB_PRINTER)	+= class/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 30b7bfb..1bc8840 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -171,7 +171,7 @@
 	struct delayed_work poll_work;
 	u32 card_info[CXINF_MAX];
 	struct mutex poll_state_serialize;
-	int poll_state;
+	enum cxacru_poll_state poll_state;
 
 	/* contol handles */
 	struct mutex cm_serialize;
@@ -226,58 +226,48 @@
 
 static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
 {
-	if (unlikely(value < 0)) {
-		return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
-						value / 100, -value % 100);
-	} else {
-		return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
-						value / 100, value % 100);
-	}
+	return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
+					value / 100, abs(value) % 100);
 }
 
 static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
 {
-	switch (value) {
-	case 0: return snprintf(buf, PAGE_SIZE, "no\n");
-	case 1: return snprintf(buf, PAGE_SIZE, "yes\n");
-	default: return 0;
-	}
+	static char *str[] = { "no", "yes" };
+	if (unlikely(value >= ARRAY_SIZE(str)))
+		return snprintf(buf, PAGE_SIZE, "%u\n", value);
+	return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
 {
-	switch (value) {
-	case 1: return snprintf(buf, PAGE_SIZE, "not connected\n");
-	case 2: return snprintf(buf, PAGE_SIZE, "connected\n");
-	case 3: return snprintf(buf, PAGE_SIZE, "lost\n");
-	default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
-	}
+	static char *str[] = { NULL, "not connected", "connected", "lost" };
+	if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+		return snprintf(buf, PAGE_SIZE, "%u\n", value);
+	return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
 {
-	switch (value) {
-	case 0: return snprintf(buf, PAGE_SIZE, "down\n");
-	case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n");
-	case 2: return snprintf(buf, PAGE_SIZE, "training\n");
-	case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n");
-	case 4: return snprintf(buf, PAGE_SIZE, "exchange\n");
-	case 5: return snprintf(buf, PAGE_SIZE, "up\n");
-	case 6: return snprintf(buf, PAGE_SIZE, "waiting\n");
-	case 7: return snprintf(buf, PAGE_SIZE, "initialising\n");
-	default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
-	}
+	static char *str[] = { "down", "attempting to activate",
+		"training", "channel analysis", "exchange", "up",
+		"waiting", "initialising"
+	};
+	if (unlikely(value >= ARRAY_SIZE(str)))
+		return snprintf(buf, PAGE_SIZE, "%u\n", value);
+	return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
 {
-	switch (value) {
-	case 0: return 0;
-	case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n");
-	case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n");
-	case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n");
-	default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
-	}
+	static char *str[] = {
+			NULL,
+			"ANSI T1.413",
+			"ITU-T G.992.1 (G.DMT)",
+			"ITU-T G.992.2 (G.LITE)"
+	};
+	if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+		return snprintf(buf, PAGE_SIZE, "%u\n", value);
+	return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 /*
@@ -308,11 +298,10 @@
 	struct cxacru_data *instance = usbatm_instance->driver_data;
 	u32 value = instance->card_info[CXINF_LINE_STARTABLE];
 
-	switch (value) {
-	case 0: return snprintf(buf, PAGE_SIZE, "running\n");
-	case 1: return snprintf(buf, PAGE_SIZE, "stopped\n");
-	default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
-	}
+	static char *str[] = { "running", "stopped" };
+	if (unlikely(value >= ARRAY_SIZE(str)))
+		return snprintf(buf, PAGE_SIZE, "%u\n", value);
+	return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
 
 static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
@@ -476,8 +465,6 @@
 	add_timer(&timer);
 	wait_for_completion(done);
 	status = urb->status;
-	if (status == -ECONNRESET)
-		status = -ETIMEDOUT;
 	del_timer_sync(&timer);
 
 	if (actual_length)
@@ -629,10 +616,22 @@
 	return 0;
 }
 
+static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance,
+		struct atm_dev *atm_dev)
+{
+	struct usb_interface *intf = usbatm_instance->usb_intf;
+
+	#define CXACRU_DEVICE_REMOVE_FILE(_name) \
+		device_remove_file(&intf->dev, &dev_attr_##_name);
+	CXACRU_ALL_FILES(REMOVE);
+	#undef CXACRU_DEVICE_REMOVE_FILE
+}
+
 static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
 		struct atm_dev *atm_dev)
 {
 	struct cxacru_data *instance = usbatm_instance->driver_data;
+	struct usb_interface *intf = usbatm_instance->usb_intf;
 	/*
 	struct atm_dev *atm_dev = usbatm_instance->atm_dev;
 	*/
@@ -649,14 +648,18 @@
 		return ret;
 	}
 
+	#define CXACRU_DEVICE_CREATE_FILE(_name) \
+		ret = device_create_file(&intf->dev, &dev_attr_##_name); \
+		if (unlikely(ret)) \
+			goto fail_sysfs;
+	CXACRU_ALL_FILES(CREATE);
+	#undef CXACRU_DEVICE_CREATE_FILE
+
 	/* start ADSL */
 	mutex_lock(&instance->adsl_state_serialize);
 	ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
-	if (ret < 0) {
+	if (ret < 0)
 		atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
-		mutex_unlock(&instance->adsl_state_serialize);
-		return ret;
-	}
 
 	/* Start status polling */
 	mutex_lock(&instance->poll_state_serialize);
@@ -680,6 +683,11 @@
 	if (start_polling)
 		cxacru_poll_status(&instance->poll_work.work);
 	return 0;
+
+fail_sysfs:
+	usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret);
+	cxacru_remove_device_files(usbatm_instance, atm_dev);
+	return ret;
 }
 
 static void cxacru_poll_status(struct work_struct *work)
@@ -1065,13 +1073,6 @@
 		goto fail;
 	}
 
-	#define CXACRU_DEVICE_CREATE_FILE(_name) \
-		ret = device_create_file(&intf->dev, &dev_attr_##_name); \
-		if (unlikely(ret)) \
-			goto fail_sysfs;
-	CXACRU_ALL_FILES(CREATE);
-	#undef CXACRU_DEVICE_CREATE_FILE
-
 	usb_fill_int_urb(instance->rcv_urb,
 			usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
 			instance->rcv_buf, PAGE_SIZE,
@@ -1092,14 +1093,6 @@
 
 	return 0;
 
- fail_sysfs:
-	dbg("cxacru_bind: device_create_file failed (%d)\n", ret);
-
-	#define CXACRU_DEVICE_REMOVE_FILE(_name) \
-		device_remove_file(&intf->dev, &dev_attr_##_name);
-	CXACRU_ALL_FILES(REMOVE);
-	#undef CXACRU_DEVICE_REVOVE_FILE
-
  fail:
 	free_page((unsigned long) instance->snd_buf);
 	free_page((unsigned long) instance->rcv_buf);
@@ -1146,11 +1139,6 @@
 	free_page((unsigned long) instance->snd_buf);
 	free_page((unsigned long) instance->rcv_buf);
 
-	#define CXACRU_DEVICE_REMOVE_FILE(_name) \
-		device_remove_file(&intf->dev, &dev_attr_##_name);
-	CXACRU_ALL_FILES(REMOVE);
-	#undef CXACRU_DEVICE_REVOVE_FILE
-
 	kfree(instance);
 
 	usbatm_instance->driver_data = NULL;
@@ -1231,6 +1219,7 @@
 	.heavy_init	= cxacru_heavy_init,
 	.unbind		= cxacru_unbind,
 	.atm_start	= cxacru_atm_start,
+	.atm_stop	= cxacru_remove_device_files,
 	.bulk_in	= CXACRU_EP_DATA,
 	.bulk_out	= CXACRU_EP_DATA,
 	.rx_padding	= 3,
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 4973e14..8f04665 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -1168,6 +1168,7 @@
 	struct uea_softc *sc = data;
 	int ret = -EAGAIN;
 
+	set_freezable();
 	uea_enters(INS_TO_USBDEV(sc));
 	while (!kthread_should_stop()) {
 		if (ret < 0 || sc->reset)
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 0081c1d..cd51520c 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1157,6 +1157,9 @@
 	{ USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
+	{ USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */
+	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+	},
 	{ USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 15e740e..9a14789 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -1,5 +1,5 @@
 /*
- * usblp.c  Version 0.13
+ * usblp.c
  *
  * Copyright (c) 1999 Michael Gee	<michael@linuxspecific.com>
  * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
@@ -61,11 +61,11 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.13"
 #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
 #define DRIVER_DESC "USB Printer Device Class driver"
 
 #define USBLP_BUF_SIZE		8192
+#define USBLP_BUF_SIZE_IN	1024
 #define USBLP_DEVICE_ID_SIZE	1024
 
 /* ioctls: */
@@ -127,14 +127,22 @@
  */
 #define STATUS_BUF_SIZE		8
 
+/*
+ * Locks down the locking order:
+ * ->wmut locks wstatus.
+ * ->mut locks the whole usblp, except [rw]complete, and thus, by indirection,
+ * [rw]status. We only touch status when we know the side idle.
+ * ->lock locks what interrupt accesses.
+ */
 struct usblp {
 	struct usb_device 	*dev;			/* USB device */
-	struct mutex		mut;			/* locks this struct, especially "dev" */
-	char			*writebuf;		/* write transfer_buffer */
+	struct mutex		wmut;
+	struct mutex		mut;
+	spinlock_t		lock;		/* locks rcomplete, wcomplete */
 	char			*readbuf;		/* read transfer_buffer */
 	char			*statusbuf;		/* status transfer_buffer */
-	struct urb		*readurb, *writeurb;	/* The urbs */
-	wait_queue_head_t	wait;			/* Zzzzz ... */
+	struct usb_anchor	urbs;
+	wait_queue_head_t	rwait, wwait;
 	int			readcount;		/* Counter for reads */
 	int			ifnum;			/* Interface number */
 	struct usb_interface	*intf;			/* The interface */
@@ -147,8 +155,9 @@
 	}			protocol[USBLP_MAX_PROTOCOLS];
 	int			current_protocol;
 	int			minor;			/* minor number of device */
-	int			wcomplete;		/* writing is completed */
-	int			rcomplete;		/* reading is completed */
+	int			wcomplete, rcomplete;
+	int			wstatus;	/* bytes written or error */
+	int			rstatus;	/* bytes ready or error */
 	unsigned int		quirks;			/* quirks flags */
 	unsigned char		used;			/* True if open */
 	unsigned char		present;		/* True if not disconnected */
@@ -166,9 +175,6 @@
 	dbg("dev=0x%p", usblp->dev);
 	dbg("present=%d", usblp->present);
 	dbg("readbuf=0x%p", usblp->readbuf);
-	dbg("writebuf=0x%p", usblp->writebuf);
-	dbg("readurb=0x%p", usblp->readurb);
-	dbg("writeurb=0x%p", usblp->writeurb);
 	dbg("readcount=%d", usblp->readcount);
 	dbg("ifnum=%d", usblp->ifnum);
     for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
@@ -178,8 +184,8 @@
     }
 	dbg("current_protocol=%d", usblp->current_protocol);
 	dbg("minor=%d", usblp->minor);
-	dbg("wcomplete=%d", usblp->wcomplete);
-	dbg("rcomplete=%d", usblp->rcomplete);
+	dbg("wstatus=%d", usblp->wstatus);
+	dbg("rstatus=%d", usblp->rstatus);
 	dbg("quirks=%d", usblp->quirks);
 	dbg("used=%d", usblp->used);
 	dbg("bidir=%d", usblp->bidir);
@@ -222,6 +228,11 @@
 	{ 0, 0 }
 };
 
+static int usblp_wwait(struct usblp *usblp, int nonblock);
+static int usblp_wtest(struct usblp *usblp, int nonblock);
+static int usblp_rwait_and_lock(struct usblp *usblp, int nonblock);
+static int usblp_rtest(struct usblp *usblp, int nonblock);
+static int usblp_submit_read(struct usblp *usblp);
 static int usblp_select_alts(struct usblp *usblp);
 static int usblp_set_protocol(struct usblp *usblp, int protocol);
 static int usblp_cache_device_id_string(struct usblp *usblp);
@@ -279,33 +290,47 @@
 {
 	struct usblp *usblp = urb->context;
 
-	if (unlikely(!usblp || !usblp->dev || !usblp->used))
-		return;
-
-	if (unlikely(!usblp->present))
-		goto unplug;
-	if (unlikely(urb->status))
-		warn("usblp%d: nonzero read/write bulk status received: %d",
-			usblp->minor, urb->status);
+	if (usblp->present && usblp->used) {
+		if (urb->status)
+			printk(KERN_WARNING "usblp%d: "
+			    "nonzero read bulk status received: %d\n",
+			    usblp->minor, urb->status);
+	}
+	spin_lock(&usblp->lock);
+	if (urb->status < 0)
+		usblp->rstatus = urb->status;
+	else
+		usblp->rstatus = urb->actual_length;
 	usblp->rcomplete = 1;
-unplug:
-	wake_up_interruptible(&usblp->wait);
+	wake_up(&usblp->rwait);
+	spin_unlock(&usblp->lock);
+
+	usb_free_urb(urb);
 }
 
 static void usblp_bulk_write(struct urb *urb)
 {
 	struct usblp *usblp = urb->context;
 
-	if (unlikely(!usblp || !usblp->dev || !usblp->used))
-		return;
-	if (unlikely(!usblp->present))
-		goto unplug;
-	if (unlikely(urb->status))
-		warn("usblp%d: nonzero read/write bulk status received: %d",
-			usblp->minor, urb->status);
+	if (usblp->present && usblp->used) {
+		if (urb->status)
+			printk(KERN_WARNING "usblp%d: "
+			    "nonzero write bulk status received: %d\n",
+			    usblp->minor, urb->status);
+	}
+	spin_lock(&usblp->lock);
+	if (urb->status < 0)
+		usblp->wstatus = urb->status;
+	else
+		usblp->wstatus = urb->actual_length;
 	usblp->wcomplete = 1;
-unplug:
-	wake_up_interruptible(&usblp->wait);
+	wake_up(&usblp->wwait);
+	spin_unlock(&usblp->lock);
+
+	/* XXX Use usb_setup_bulk_urb when available. Talk to Marcel. */
+	kfree(urb->transfer_buffer);
+	urb->transfer_buffer = NULL;	/* Not refcounted, so to be safe... */
+	usb_free_urb(urb);
 }
 
 /*
@@ -322,7 +347,8 @@
 	error = usblp_read_status (usblp, usblp->statusbuf);
 	if (error < 0) {
 		if (printk_ratelimit())
-			err("usblp%d: error %d reading printer status",
+			printk(KERN_ERR
+				"usblp%d: error %d reading printer status\n",
 				usblp->minor, error);
 		return 0;
 	}
@@ -336,8 +362,10 @@
 	if (~status & LP_PSELECD)
 		newerr = 2;
 
-	if (newerr != err)
-		info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
+	if (newerr != err) {
+		printk(KERN_INFO "usblp%d: %s\n",
+		   usblp->minor, usblp_messages[newerr]);
+	}
 
 	return newerr;
 }
@@ -345,14 +373,9 @@
 static int handle_bidir (struct usblp *usblp)
 {
 	if (usblp->bidir && usblp->used && !usblp->sleeping) {
-		usblp->readcount = 0;
-		usblp->readurb->dev = usblp->dev;
-		if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
-			usblp->used = 0;
+		if (usblp_submit_read(usblp) < 0)
 			return -EIO;
-		}
 	}
-
 	return 0;
 }
 
@@ -405,13 +428,12 @@
 	usblp->used = 1;
 	file->private_data = usblp;
 
-	usblp->writeurb->transfer_buffer_length = 0;
 	usblp->wcomplete = 1; /* we begin writeable */
+	usblp->wstatus = 0;
 	usblp->rcomplete = 0;
-	usblp->writeurb->status = 0;
-	usblp->readurb->status = 0;
 
 	if (handle_bidir(usblp) < 0) {
+		usblp->used = 0;
 		file->private_data = NULL;
 		retval = -EIO;
 	}
@@ -422,20 +444,17 @@
 
 static void usblp_cleanup (struct usblp *usblp)
 {
-	info("usblp%d: removed", usblp->minor);
+	printk(KERN_INFO "usblp%d: removed\n", usblp->minor);
 
+	kfree(usblp->readbuf);
 	kfree (usblp->device_id_string);
 	kfree (usblp->statusbuf);
-	usb_free_urb(usblp->writeurb);
-	usb_free_urb(usblp->readurb);
 	kfree (usblp);
 }
 
 static void usblp_unlink_urbs(struct usblp *usblp)
 {
-	usb_kill_urb(usblp->writeurb);
-	if (usblp->bidir)
-		usb_kill_urb(usblp->readurb);
+	usb_kill_anchored_urbs(&usblp->urbs);
 }
 
 static int usblp_release(struct inode *inode, struct file *file)
@@ -456,10 +475,18 @@
 /* No kernel lock - fine */
 static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
 {
+	int ret;
+	unsigned long flags;
+
 	struct usblp *usblp = file->private_data;
-	poll_wait(file, &usblp->wait, wait);
- 	return ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN  | POLLRDNORM)
+	/* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */
+	poll_wait(file, &usblp->rwait, wait);
+	poll_wait(file, &usblp->wwait, wait);
+	spin_lock_irqsave(&usblp->lock, flags);
+	ret = ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN  | POLLRDNORM)
  			       | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
+	spin_unlock_irqrestore(&usblp->lock, flags);
+	return ret;
 }
 
 static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -633,10 +660,11 @@
 		switch (cmd) {
 
 			case LPGETSTATUS:
-				if (usblp_read_status(usblp, usblp->statusbuf)) {
+				if ((retval = usblp_read_status(usblp, usblp->statusbuf))) {
 					if (printk_ratelimit())
-						err("usblp%d: failed reading printer status",
-							usblp->minor);
+						printk(KERN_ERR "usblp%d:"
+						    "failed reading printer status (%d)\n",
+						    usblp->minor, retval);
 					retval = -EIO;
 					goto done;
 				}
@@ -657,161 +685,137 @@
 static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct usblp *usblp = file->private_data;
-	int timeout, intr, rv, err = 0, transfer_length = 0;
-	size_t writecount = 0;
+	char *writebuf;
+	struct urb *writeurb;
+	int rv;
+	int transfer_length;
+	ssize_t writecount = 0;
+
+	if (mutex_lock_interruptible(&usblp->wmut)) {
+		rv = -EINTR;
+		goto raise_biglock;
+	}
+	if ((rv = usblp_wwait(usblp, !!(file->f_flags & O_NONBLOCK))) < 0)
+		goto raise_wait;
 
 	while (writecount < count) {
-		if (!usblp->wcomplete) {
-			barrier();
-			if (file->f_flags & O_NONBLOCK) {
-				writecount += transfer_length;
-				return writecount ? writecount : -EAGAIN;
-			}
-
-			timeout = USBLP_WRITE_TIMEOUT;
-
-			rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout);
-			if (rv < 0)
-				return writecount ? writecount : -EINTR;
-		}
-		intr = mutex_lock_interruptible (&usblp->mut);
-		if (intr)
-			return writecount ? writecount : -EINTR;
-		if (!usblp->present) {
-			mutex_unlock (&usblp->mut);
-			return -ENODEV;
-		}
-
-		if (usblp->sleeping) {
-			mutex_unlock (&usblp->mut);
-			return writecount ? writecount : -ENODEV;
-		}
-
-		if (usblp->writeurb->status != 0) {
-			if (usblp->quirks & USBLP_QUIRK_BIDIR) {
-				if (!usblp->wcomplete)
-					err("usblp%d: error %d writing to printer",
-						usblp->minor, usblp->writeurb->status);
-				err = usblp->writeurb->status;
-			} else
-				err = usblp_check_status(usblp, err);
-			mutex_unlock (&usblp->mut);
-
-			/* if the fault was due to disconnect, let khubd's
-			 * call to usblp_disconnect() grab usblp->mut ...
-			 */
-			schedule ();
-			continue;
-		}
-
-		/* We must increment writecount here, and not at the
-		 * end of the loop. Otherwise, the final loop iteration may
-		 * be skipped, leading to incomplete printer output.
+		/*
+		 * Step 1: Submit next block.
 		 */
-		writecount += transfer_length;
-		if (writecount == count) {
-			mutex_unlock(&usblp->mut);
-			break;
-		}
-
-		transfer_length=(count - writecount);
-		if (transfer_length > USBLP_BUF_SIZE)
+		if ((transfer_length = count - writecount) > USBLP_BUF_SIZE)
 			transfer_length = USBLP_BUF_SIZE;
 
-		usblp->writeurb->transfer_buffer_length = transfer_length;
+		rv = -ENOMEM;
+		if ((writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL)) == NULL)
+			goto raise_buf;
+		if ((writeurb = usb_alloc_urb(0, GFP_KERNEL)) == NULL)
+			goto raise_urb;
+		usb_fill_bulk_urb(writeurb, usblp->dev,
+			usb_sndbulkpipe(usblp->dev,
+			  usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress),
+			writebuf, transfer_length, usblp_bulk_write, usblp);
+		usb_anchor_urb(writeurb, &usblp->urbs);
 
-		if (copy_from_user(usblp->writeurb->transfer_buffer, 
+		if (copy_from_user(writebuf,
 				   buffer + writecount, transfer_length)) {
-			mutex_unlock(&usblp->mut);
-			return writecount ? writecount : -EFAULT;
+			rv = -EFAULT;
+			goto raise_badaddr;
 		}
 
-		usblp->writeurb->dev = usblp->dev;
+		spin_lock_irq(&usblp->lock);
 		usblp->wcomplete = 0;
-		err = usb_submit_urb(usblp->writeurb, GFP_KERNEL);
-		if (err) {
+		spin_unlock_irq(&usblp->lock);
+		if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) {
+			usblp->wstatus = 0;
+			spin_lock_irq(&usblp->lock);
 			usblp->wcomplete = 1;
-			if (err != -ENOMEM)
-				count = -EIO;
-			else
-				count = writecount ? writecount : -ENOMEM;
-			mutex_unlock (&usblp->mut);
-			break;
+			wake_up(&usblp->wwait);
+			spin_unlock_irq(&usblp->lock);
+			if (rv != -ENOMEM)
+				rv = -EIO;
+			goto raise_submit;
 		}
-		mutex_unlock (&usblp->mut);
+
+		/*
+		 * Step 2: Wait for transfer to end, collect results.
+		 */
+		rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK));
+		if (rv < 0) {
+			/*
+			 * If interrupted, we simply leave the URB to dangle,
+			 * so the ->release will call usb_kill_urb().
+			 */
+			goto collect_error;
+		}
+
+		if (usblp->wstatus < 0) {
+			usblp_check_status(usblp, 0);
+			rv = -EIO;
+			goto collect_error;
+		}
+		/*
+		 * This is critical: it must be our URB, not other writer's.
+		 * The wmut exists mainly to cover us here.
+		 */
+		writecount += usblp->wstatus;
 	}
 
-	return count;
+	mutex_unlock(&usblp->wmut);
+	return writecount;
+
+raise_submit:
+raise_badaddr:
+	usb_unanchor_urb(writeurb);
+	usb_free_urb(writeurb);
+raise_urb:
+	kfree(writebuf);
+raise_buf:
+raise_wait:
+collect_error:		/* Out of raise sequence */
+	mutex_unlock(&usblp->wmut);
+raise_biglock:
+	return writecount ? writecount : rv;
 }
 
-static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+/*
+ * Notice that we fail to restart in a few cases: on EFAULT, on restart
+ * error, etc. This is the historical behaviour. In all such cases we return
+ * EIO, and applications loop in order to get the new read going.
+ */
+static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, loff_t *ppos)
 {
 	struct usblp *usblp = file->private_data;
-	int rv, intr;
+	ssize_t count;
+	ssize_t avail;
+	int rv;
 
 	if (!usblp->bidir)
 		return -EINVAL;
 
-	intr = mutex_lock_interruptible (&usblp->mut);
-	if (intr)
-		return -EINTR;
-	if (!usblp->present) {
-		count = -ENODEV;
-		goto done;
-	}
+	rv = usblp_rwait_and_lock(usblp, !!(file->f_flags & O_NONBLOCK));
+	if (rv < 0)
+		return rv;
 
-	if (!usblp->rcomplete) {
-		barrier();
-
-		if (file->f_flags & O_NONBLOCK) {
-			count = -EAGAIN;
-			goto done;
-		}
-		mutex_unlock(&usblp->mut);
-		rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
-		mutex_lock(&usblp->mut);
-		if (rv < 0) {
-			count = -EINTR;
-			goto done;
-		}
-	}
-
-	if (!usblp->present) {
-		count = -ENODEV;
-		goto done;
-	}
-
-	if (usblp->sleeping) {
-		count = -ENODEV;
-		goto done;
-	}
-
-	if (usblp->readurb->status) {
-		err("usblp%d: error %d reading from printer",
-			usblp->minor, usblp->readurb->status);
-		usblp->readurb->dev = usblp->dev;
- 		usblp->readcount = 0;
-		usblp->rcomplete = 0;
-		if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
-			dbg("error submitting urb");
+	if ((avail = usblp->rstatus) < 0) {
+		printk(KERN_ERR "usblp%d: error %d reading from printer\n",
+		    usblp->minor, (int)avail);
+		usblp_submit_read(usblp);
 		count = -EIO;
 		goto done;
 	}
 
-	count = count < usblp->readurb->actual_length - usblp->readcount ?
-		count :	usblp->readurb->actual_length - usblp->readcount;
-
-	if (copy_to_user(buffer, usblp->readurb->transfer_buffer + usblp->readcount, count)) {
+	count = len < avail - usblp->readcount ? len : avail - usblp->readcount;
+	if (count != 0 &&
+	    copy_to_user(buffer, usblp->readbuf + usblp->readcount, count)) {
 		count = -EFAULT;
 		goto done;
 	}
 
-	if ((usblp->readcount += count) == usblp->readurb->actual_length) {
-		usblp->readcount = 0;
-		usblp->readurb->dev = usblp->dev;
-		usblp->rcomplete = 0;
-		if (usb_submit_urb(usblp->readurb, GFP_KERNEL)) {
-			count = -EIO;
+	if ((usblp->readcount += count) == avail) {
+		if (usblp_submit_read(usblp) < 0) {
+			/* We don't want to leak USB return codes into errno. */
+			if (count == 0)
+				count = -EIO;
 			goto done;
 		}
 	}
@@ -822,6 +826,165 @@
 }
 
 /*
+ * Wait for the write path to come idle.
+ * This is called under the ->wmut, so the idle path stays idle.
+ *
+ * Our write path has a peculiar property: it does not buffer like a tty,
+ * but waits for the write to succeed. This allows our ->release to bug out
+ * without waiting for writes to drain. But it obviously does not work
+ * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use
+ * select(2) or poll(2) to wait for the buffer to drain before closing.
+ * Alternatively, set blocking mode with fcntl and issue a zero-size write.
+ *
+ * Old v0.13 code had a non-functional timeout for wait_event(). Someone forgot
+ * to check the return code for timeout expiration, so it had no effect.
+ * Apparently, it was intended to check for error conditons, such as out
+ * of paper. It is going to return when we settle things with CUPS. XXX
+ */
+static int usblp_wwait(struct usblp *usblp, int nonblock)
+{
+	DECLARE_WAITQUEUE(waita, current);
+	int rc;
+
+	add_wait_queue(&usblp->wwait, &waita);
+	for (;;) {
+		if (mutex_lock_interruptible(&usblp->mut)) {
+			rc = -EINTR;
+			break;
+		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		if ((rc = usblp_wtest(usblp, nonblock)) < 0) {
+			mutex_unlock(&usblp->mut);
+			break;
+		}
+		mutex_unlock(&usblp->mut);
+		if (rc == 0)
+			break;
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&usblp->wwait, &waita);
+	return rc;
+}
+
+static int usblp_wtest(struct usblp *usblp, int nonblock)
+{
+	unsigned long flags;
+
+	if (!usblp->present)
+		return -ENODEV;
+	if (signal_pending(current))
+		return -EINTR;
+	spin_lock_irqsave(&usblp->lock, flags);
+	if (usblp->wcomplete) {
+		spin_unlock_irqrestore(&usblp->lock, flags);
+		return 0;
+	}
+	spin_unlock_irqrestore(&usblp->lock, flags);
+	if (usblp->sleeping)
+		return -ENODEV;
+	if (nonblock)
+		return -EAGAIN;
+	return 1;
+}
+
+/*
+ * Wait for read bytes to become available. This probably should have been
+ * called usblp_r_lock_and_wait(), because we lock first. But it's a traditional
+ * name for functions which lock and return.
+ *
+ * We do not use wait_event_interruptible because it makes locking iffy.
+ */
+static int usblp_rwait_and_lock(struct usblp *usblp, int nonblock)
+{
+	DECLARE_WAITQUEUE(waita, current);
+	int rc;
+
+	add_wait_queue(&usblp->rwait, &waita);
+	for (;;) {
+		if (mutex_lock_interruptible(&usblp->mut)) {
+			rc = -EINTR;
+			break;
+		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		if ((rc = usblp_rtest(usblp, nonblock)) < 0) {
+			mutex_unlock(&usblp->mut);
+			break;
+		}
+		if (rc == 0)	/* Keep it locked */
+			break;
+		mutex_unlock(&usblp->mut);
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&usblp->rwait, &waita);
+	return rc;
+}
+
+static int usblp_rtest(struct usblp *usblp, int nonblock)
+{
+	unsigned long flags;
+
+	if (!usblp->present)
+		return -ENODEV;
+	if (signal_pending(current))
+		return -EINTR;
+	spin_lock_irqsave(&usblp->lock, flags);
+	if (usblp->rcomplete) {
+		spin_unlock_irqrestore(&usblp->lock, flags);
+		return 0;
+	}
+	spin_unlock_irqrestore(&usblp->lock, flags);
+	if (usblp->sleeping)
+		return -ENODEV;
+	if (nonblock)
+		return -EAGAIN;
+	return 1;
+}
+
+/*
+ * Please check ->bidir and other such things outside for now.
+ */
+static int usblp_submit_read(struct usblp *usblp)
+{
+	struct urb *urb;
+	unsigned long flags;
+	int rc;
+
+	rc = -ENOMEM;
+	if ((urb = usb_alloc_urb(0, GFP_KERNEL)) == NULL)
+		goto raise_urb;
+
+	usb_fill_bulk_urb(urb, usblp->dev,
+		usb_rcvbulkpipe(usblp->dev,
+		  usblp->protocol[usblp->current_protocol].epread->bEndpointAddress),
+		usblp->readbuf, USBLP_BUF_SIZE_IN,
+		usblp_bulk_read, usblp);
+	usb_anchor_urb(urb, &usblp->urbs);
+
+	spin_lock_irqsave(&usblp->lock, flags);
+	usblp->readcount = 0; /* XXX Why here? */
+	usblp->rcomplete = 0;
+	spin_unlock_irqrestore(&usblp->lock, flags);
+	if ((rc = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
+		dbg("error submitting urb (%d)", rc);
+		spin_lock_irqsave(&usblp->lock, flags);
+		usblp->rstatus = rc;
+		usblp->rcomplete = 1;
+		spin_unlock_irqrestore(&usblp->lock, flags);
+		goto raise_submit;
+	}
+
+	return 0;
+
+raise_submit:
+	usb_unanchor_urb(urb);
+	usb_free_urb(urb);
+raise_urb:
+	return rc;
+}
+
+/*
  * Checks for printers that have quirks, such as requiring unidirectional
  * communication but reporting bidirectional; currently some HP printers
  * have this flaw (HP 810, 880, 895, etc.), or needing an init string
@@ -892,55 +1055,41 @@
 	/* Malloc and start initializing usblp structure so we can use it
 	 * directly. */
 	if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
-		err("out of memory for usblp");
+		retval = -ENOMEM;
 		goto abort;
 	}
 	usblp->dev = dev;
+	mutex_init(&usblp->wmut);
 	mutex_init (&usblp->mut);
-	init_waitqueue_head(&usblp->wait);
+	spin_lock_init(&usblp->lock);
+	init_waitqueue_head(&usblp->rwait);
+	init_waitqueue_head(&usblp->wwait);
+	init_usb_anchor(&usblp->urbs);
 	usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
 	usblp->intf = intf;
 
-	usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!usblp->writeurb) {
-		err("out of memory");
-		goto abort;
-	}
-	usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!usblp->readurb) {
-		err("out of memory");
-		goto abort;
-	}
-
 	/* Malloc device ID string buffer to the largest expected length,
 	 * since we can re-query it on an ioctl and a dynamic string
 	 * could change in length. */
 	if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
-		err("out of memory for device_id_string");
+		retval = -ENOMEM;
 		goto abort;
 	}
 
-	usblp->writebuf = usblp->readbuf = NULL;
-	usblp->writeurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-	usblp->readurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-	/* Malloc write & read buffers.  We somewhat wastefully
+	/*
+	 * Allocate read buffer. We somewhat wastefully
 	 * malloc both regardless of bidirectionality, because the
-	 * alternate setting can be changed later via an ioctl. */
-	if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
-				GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
-		err("out of memory for write buf");
-		goto abort;
-	}
-	if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
-				GFP_KERNEL, &usblp->readurb->transfer_dma))) {
-		err("out of memory for read buf");
+	 * alternate setting can be changed later via an ioctl.
+	 */
+	if (!(usblp->readbuf = kmalloc(USBLP_BUF_SIZE_IN, GFP_KERNEL))) {
+		retval = -ENOMEM;
 		goto abort;
 	}
 
 	/* Allocate buffer for printer status */
 	usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
 	if (!usblp->statusbuf) {
-		err("out of memory for statusbuf");
+		retval = -ENOMEM;
 		goto abort;
 	}
 
@@ -955,12 +1104,15 @@
 		dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
 			le16_to_cpu(dev->descriptor.idVendor),
 			le16_to_cpu(dev->descriptor.idProduct));
+		retval = -ENODEV;
 		goto abort;
 	}
 
 	/* Setup the selected alternate setting and endpoints. */
-	if (usblp_set_protocol(usblp, protocol) < 0)
+	if (usblp_set_protocol(usblp, protocol) < 0) {
+		retval = -ENODEV;	/* ->probe isn't ->ioctl */
 		goto abort;
+	}
 
 	/* Retrieve and store the device ID string. */
 	usblp_cache_device_id_string(usblp);
@@ -978,12 +1130,14 @@
 
 	retval = usb_register_dev(intf, &usblp_class);
 	if (retval) {
-		err("Not able to get a minor for this device.");
+		printk(KERN_ERR "usblp: Not able to get a minor"
+		    " (base %u, slice default): %d\n",
+		    USBLP_MINOR_BASE, retval);
 		goto abort_intfdata;
 	}
 	usblp->minor = intf->minor;
-	info("usblp%d: USB %sdirectional printer dev %d "
-		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+	printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d "
+		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n",
 		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
 		usblp->ifnum,
 		usblp->protocol[usblp->current_protocol].alt_setting,
@@ -998,19 +1152,12 @@
 	device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
 abort:
 	if (usblp) {
-		if (usblp->writebuf)
-			usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-				usblp->writebuf, usblp->writeurb->transfer_dma);
-		if (usblp->readbuf)
-			usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-				usblp->readbuf, usblp->writeurb->transfer_dma);
+		kfree(usblp->readbuf);
 		kfree(usblp->statusbuf);
 		kfree(usblp->device_id_string);
-		usb_free_urb(usblp->writeurb);
-		usb_free_urb(usblp->readurb);
 		kfree(usblp);
 	}
-	return -EIO;
+	return retval;
 }
 
 /*
@@ -1079,8 +1226,9 @@
 		if (ifd->desc.bInterfaceProtocol == 1) {
 			epread = NULL;
 		} else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
-			info("Disabling reads from problem bidirectional "
-				"printer on usblp%d", usblp->minor);
+			printk(KERN_INFO "usblp%d: Disabling reads from "
+			    "problematic bidirectional printer\n",
+			    usblp->minor);
 			epread = NULL;
 		}
 
@@ -1120,25 +1268,12 @@
 		return -EINVAL;
 	r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
 	if (r < 0) {
-		err("can't set desired altsetting %d on interface %d",
+		printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n",
 			alts, usblp->ifnum);
 		return r;
 	}
 
-	usb_fill_bulk_urb(usblp->writeurb, usblp->dev,
-		usb_sndbulkpipe(usblp->dev,
-		  usblp->protocol[protocol].epwrite->bEndpointAddress),
-		usblp->writebuf, 0,
-		usblp_bulk_write, usblp);
-
 	usblp->bidir = (usblp->protocol[protocol].epread != NULL);
-	if (usblp->bidir)
-		usb_fill_bulk_urb(usblp->readurb, usblp->dev,
-			usb_rcvbulkpipe(usblp->dev,
-			  usblp->protocol[protocol].epread->bEndpointAddress),
-			usblp->readbuf, USBLP_BUF_SIZE,
-			usblp_bulk_read, usblp);
-
 	usblp->current_protocol = protocol;
 	dbg("usblp%d set protocol %d", usblp->minor, protocol);
 	return 0;
@@ -1191,13 +1326,11 @@
 	mutex_lock (&usblp_mutex);
 	mutex_lock (&usblp->mut);
 	usblp->present = 0;
+	wake_up(&usblp->wwait);
+	wake_up(&usblp->rwait);
 	usb_set_intfdata (intf, NULL);
 
 	usblp_unlink_urbs(usblp);
-	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-			usblp->writebuf, usblp->writeurb->transfer_dma);
-	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-			usblp->readbuf, usblp->readurb->transfer_dma);
 	mutex_unlock (&usblp->mut);
 
 	if (!usblp->used)
@@ -1212,6 +1345,11 @@
 	/* we take no more IO */
 	usblp->sleeping = 1;
 	usblp_unlink_urbs(usblp);
+#if 0 /* XXX Do we want this? What if someone is reading, should we fail? */
+	/* not strictly necessary, but just in case */
+	wake_up(&usblp->wwait);
+	wake_up(&usblp->rwait);
+#endif
 
 	return 0;
 }
@@ -1252,12 +1390,7 @@
 
 static int __init usblp_init(void)
 {
-	int retval;
-	retval = usb_register(&usblp_driver);
-	if (!retval)
-		info(DRIVER_VERSION ": " DRIVER_DESC);
-
-	return retval;
+	return usb_register(&usblp_driver);
 }
 
 static void __exit usblp_exit(void)
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f493fb1..97b09f28 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -40,21 +40,25 @@
 config USB_DEVICE_CLASS
 	bool "USB device class-devices (DEPRECATED)"
 	depends on USB
-	default n
+	default y
 	---help---
 	  Userspace access to USB devices is granted by device-nodes exported
 	  directly from the usbdev in sysfs. Old versions of the driver
 	  core and udev needed additional class devices to export device nodes.
 
 	  These additional devices are difficult to handle in userspace, if
-	  information about USB interfaces must be available. One device contains
-	  the device node, the other device contains the interface data. Both
-	  devices are at the same level in sysfs (siblings) and one can't access
-	  the other. The device node created directly by the usbdev is the parent
-	  device of the interface and therefore easily accessible from the interface
-	  event.
+	  information about USB interfaces must be available. One device
+	  contains the device node, the other device contains the interface
+	  data. Both devices are at the same level in sysfs (siblings) and one
+	  can't access the other. The device node created directly by the
+	  usb device is the parent device of the interface and therefore
+	  easily accessible from the interface event.
 
-	  This option provides backward compatibility if needed.
+	  This option provides backward compatibility for libusb device
+	  nodes (lsusb) when usbfs is not used, and the following udev rule
+	  doesn't exist:
+	    SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \
+	    NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
 
 config USB_DYNAMIC_MINORS
 	bool "Dynamic USB minor allocation (EXPERIMENTAL)"
@@ -82,6 +86,31 @@
 
 	  If you are unsure about this, say N here.
 
+config USB_PERSIST
+	bool "USB device persistence during system suspend (DANGEROUS)"
+	depends on USB && PM && EXPERIMENTAL
+	default n
+	help
+
+	  If you say Y here and enable the "power/persist" attribute
+	  for a USB device, the device's data structures will remain
+	  persistent across system suspend, even if the USB bus loses
+	  power.  (This includes hibernation, also known as swsusp or
+	  suspend-to-disk.)  The devices will reappear as if by magic
+	  when the system wakes up, with no need to unmount USB
+	  filesystems, rmmod host-controller drivers, or do anything
+	  else.
+
+	  	WARNING: This option can be dangerous!
+
+	  If a USB device is replaced by another of the same type while
+	  the system is asleep, there's a good chance the kernel won't
+	  detect the change.  Likewise if the media in a USB storage
+	  device is replaced.  When this happens it's almost certain to
+	  cause data corruption and maybe even crash your system.
+
+	  If you are unsure, say N here.
+
 config USB_OTG
 	bool
 	depends on USB && EXPERIMENTAL
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index bfb3731..cb69aa1 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -1,4 +1,5 @@
 #include <linux/usb.h>
+#include <linux/usb/ch9.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -49,7 +50,7 @@
 	unsigned char *buffer0 = buffer;
 	struct usb_endpoint_descriptor *d;
 	struct usb_host_endpoint *endpoint;
-	int n, i;
+	int n, i, j;
 
 	d = (struct usb_endpoint_descriptor *) buffer;
 	buffer += d->bLength;
@@ -84,6 +85,66 @@
 	memcpy(&endpoint->desc, d, n);
 	INIT_LIST_HEAD(&endpoint->urb_list);
 
+	/* Fix up bInterval values outside the legal range. Use 32 ms if no
+	 * proper value can be guessed. */
+	i = 0;		/* i = min, j = max, n = default */
+	j = 255;
+	if (usb_endpoint_xfer_int(d)) {
+		i = 1;
+		switch (to_usb_device(ddev)->speed) {
+		case USB_SPEED_HIGH:
+			/* Many device manufacturers are using full-speed
+			 * bInterval values in high-speed interrupt endpoint
+			 * descriptors. Try to fix those and fall back to a
+			 * 32 ms default value otherwise. */
+			n = fls(d->bInterval*8);
+			if (n == 0)
+				n = 9;	/* 32 ms = 2^(9-1) uframes */
+			j = 16;
+			break;
+		default:		/* USB_SPEED_FULL or _LOW */
+			/* For low-speed, 10 ms is the official minimum.
+			 * But some "overclocked" devices might want faster
+			 * polling so we'll allow it. */
+			n = 32;
+			break;
+		}
+	} else if (usb_endpoint_xfer_isoc(d)) {
+		i = 1;
+		j = 16;
+		switch (to_usb_device(ddev)->speed) {
+		case USB_SPEED_HIGH:
+			n = 9;		/* 32 ms = 2^(9-1) uframes */
+			break;
+		default:		/* USB_SPEED_FULL */
+			n = 6;		/* 32 ms = 2^(6-1) frames */
+			break;
+		}
+	}
+	if (d->bInterval < i || d->bInterval > j) {
+		dev_warn(ddev, "config %d interface %d altsetting %d "
+		    "endpoint 0x%X has an invalid bInterval %d, "
+		    "changing to %d\n",
+		    cfgno, inum, asnum,
+		    d->bEndpointAddress, d->bInterval, n);
+		endpoint->desc.bInterval = n;
+	}
+
+	/* Some buggy low-speed devices have Bulk endpoints, which is
+	 * explicitly forbidden by the USB spec.  In an attempt to make
+	 * them usable, we will try treating them as Interrupt endpoints.
+	 */
+	if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
+			usb_endpoint_xfer_bulk(d)) {
+		dev_warn(ddev, "config %d interface %d altsetting %d "
+		    "endpoint 0x%X is Bulk; changing to Interrupt\n",
+		    cfgno, inum, asnum, d->bEndpointAddress);
+		endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
+		endpoint->desc.bInterval = 1;
+		if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8)
+			endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
+	}
+
 	/* Skip over any Class Specific or Vendor Specific descriptors;
 	 * find the next endpoint or interface descriptor */
 	endpoint->extra = buffer;
@@ -185,10 +246,12 @@
 		num_ep = USB_MAXENDPOINTS;
 	}
 
-	len = sizeof(struct usb_host_endpoint) * num_ep;
-	alt->endpoint = kzalloc(len, GFP_KERNEL);
-	if (!alt->endpoint)
-		return -ENOMEM;
+	if (num_ep > 0) {	/* Can't allocate 0 bytes */
+		len = sizeof(struct usb_host_endpoint) * num_ep;
+		alt->endpoint = kzalloc(len, GFP_KERNEL);
+		if (!alt->endpoint)
+			return -ENOMEM;
+	}
 
 	/* Parse all the endpoint descriptors */
 	n = 0;
@@ -232,6 +295,7 @@
 	struct usb_descriptor_header *header;
 	int len, retval;
 	u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
+	unsigned iad_num = 0;
 
 	memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
 	if (config->desc.bDescriptorType != USB_DT_CONFIG ||
@@ -309,6 +373,20 @@
 				++n;
 			}
 
+		} else if (header->bDescriptorType ==
+				USB_DT_INTERFACE_ASSOCIATION) {
+			if (iad_num == USB_MAXIADS) {
+				dev_warn(ddev, "found more Interface "
+					       "Association Descriptors "
+					       "than allocated for in "
+					       "configuration %d\n", cfgno);
+			} else {
+				config->intf_assoc[iad_num] =
+					(struct usb_interface_assoc_descriptor
+					*)header;
+				iad_num++;
+			}
+
 		} else if (header->bDescriptorType == USB_DT_DEVICE ||
 			    header->bDescriptorType == USB_DT_CONFIG)
 			dev_warn(ddev, "config %d contains an unexpected "
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 6753ca0..87c794d6 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -102,6 +102,10 @@
 /* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
   "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
   
+static const char *format_iad =
+/* A:  FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */
+  "A:  FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
+
 static const char *format_iface =
 /* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
   "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
@@ -146,6 +150,7 @@
 	{USB_CLASS_STILL_IMAGE,		"still"},
 	{USB_CLASS_CSCID,		"scard"},
 	{USB_CLASS_CONTENT_SEC,		"c-sec"},
+	{USB_CLASS_VIDEO,		"video"},
 	{-1,				"unk."}		/* leave as last */
 };
 
@@ -286,6 +291,21 @@
 	return start;
 }
 
+static char *usb_dump_iad_descriptor(char *start, char *end,
+	const struct usb_interface_assoc_descriptor *iad)
+{
+	if (start > end)
+		return start;
+	start += sprintf(start, format_iad,
+			 iad->bFirstInterface,
+			 iad->bInterfaceCount,
+			 iad->bFunctionClass,
+			 class_decode(iad->bFunctionClass),
+			 iad->bFunctionSubClass,
+			 iad->bFunctionProtocol);
+	return start;
+}
+
 /* TBD:
  * 0. TBDs
  * 1. marking active interface altsettings (code lists all, but should mark
@@ -322,6 +342,12 @@
 	if (!config)		/* getting these some in 2.3.7; none in 2.3.6 */
 		return start + sprintf(start, "(null Cfg. desc.)\n");
 	start = usb_dump_config_descriptor(start, end, &config->desc, active);
+	for (i = 0; i < USB_MAXIADS; i++) {
+		if (config->intf_assoc[i] == NULL)
+			break;
+		start = usb_dump_iad_descriptor(start, end,
+					config->intf_assoc[i]);
+	}
 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
 		intfc = config->intf_cache[i];
 		interface = config->interface[i];
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index b9f7f90..73c4936 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -24,10 +24,19 @@
 
 #include <linux/device.h>
 #include <linux/usb.h>
+#include <linux/usb/quirks.h>
 #include <linux/workqueue.h>
 #include "hcd.h"
 #include "usb.h"
 
+#define VERBOSE_DEBUG	0
+
+#if VERBOSE_DEBUG
+#define dev_vdbg	dev_dbg
+#else
+#define dev_vdbg(dev, fmt, args...)	do { } while (0)
+#endif
+
 #ifdef CONFIG_HOTPLUG
 
 /*
@@ -802,18 +811,17 @@
 			udev->state == USB_STATE_SUSPENDED)
 		goto done;
 
-	/* For devices that don't have a driver, we do a standard suspend. */
-	if (udev->dev.driver == NULL) {
+	/* For devices that don't have a driver, we do a generic suspend. */
+	if (udev->dev.driver)
+		udriver = to_usb_device_driver(udev->dev.driver);
+	else {
 		udev->do_remote_wakeup = 0;
-		status = usb_port_suspend(udev);
-		goto done;
+		udriver = &usb_generic_driver;
 	}
-
-	udriver = to_usb_device_driver(udev->dev.driver);
 	status = udriver->suspend(udev, msg);
 
-done:
-	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ done:
+	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
 	if (status == 0)
 		udev->dev.power.power_state.event = msg.event;
 	return status;
@@ -825,8 +833,9 @@
 	struct usb_device_driver	*udriver;
 	int				status = 0;
 
-	if (udev->state == USB_STATE_NOTATTACHED ||
-			udev->state != USB_STATE_SUSPENDED)
+	if (udev->state == USB_STATE_NOTATTACHED)
+		goto done;
+	if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
 		goto done;
 
 	/* Can't resume it if it doesn't have a driver. */
@@ -835,11 +844,14 @@
 		goto done;
 	}
 
+	if (udev->quirks & USB_QUIRK_RESET_RESUME)
+		udev->reset_resume = 1;
+
 	udriver = to_usb_device_driver(udev->dev.driver);
 	status = udriver->resume(udev);
 
-done:
-	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ done:
+	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
 	if (status == 0) {
 		udev->autoresume_disabled = 0;
 		udev->dev.power.power_state.event = PM_EVENT_ON;
@@ -877,15 +889,13 @@
 		mark_quiesced(intf);
 	}
 
-done:
-	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
-	if (status == 0)
-		intf->dev.power.power_state.event = msg.event;
+ done:
+	dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
 	return status;
 }
 
 /* Caller has locked intf's usb_device's pm_mutex */
-static int usb_resume_interface(struct usb_interface *intf)
+static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
 {
 	struct usb_driver	*driver;
 	int			status = 0;
@@ -905,23 +915,37 @@
 	}
 	driver = to_usb_driver(intf->dev.driver);
 
-	if (driver->resume) {
-		status = driver->resume(intf);
-		if (status)
-			dev_err(&intf->dev, "%s error %d\n",
-					"resume", status);
-		else
-			mark_active(intf);
+	if (reset_resume) {
+		if (driver->reset_resume) {
+			status = driver->reset_resume(intf);
+			if (status)
+				dev_err(&intf->dev, "%s error %d\n",
+						"reset_resume", status);
+		} else {
+			// status = -EOPNOTSUPP;
+			dev_warn(&intf->dev, "no %s for driver %s?\n",
+					"reset_resume", driver->name);
+		}
 	} else {
-		dev_warn(&intf->dev, "no resume for driver %s?\n",
-				driver->name);
-		mark_active(intf);
+		if (driver->resume) {
+			status = driver->resume(intf);
+			if (status)
+				dev_err(&intf->dev, "%s error %d\n",
+						"resume", status);
+		} else {
+			// status = -EOPNOTSUPP;
+			dev_warn(&intf->dev, "no %s for driver %s?\n",
+					"resume", driver->name);
+		}
 	}
 
 done:
-	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+	dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
 	if (status == 0)
-		intf->dev.power.power_state.event = PM_EVENT_ON;
+		mark_active(intf);
+
+	/* FIXME: Unbind the driver and reprobe if the resume failed
+	 * (not possible if auto_pm is set) */
 	return status;
 }
 
@@ -958,6 +982,18 @@
 						"for autosuspend\n");
 				return -EOPNOTSUPP;
 			}
+
+			/* Don't allow autosuspend if the device will need
+			 * a reset-resume and any of its interface drivers
+			 * doesn't include support.
+			 */
+			if (udev->quirks & USB_QUIRK_RESET_RESUME) {
+				struct usb_driver *driver;
+
+				driver = to_usb_driver(intf->dev.driver);
+				if (!driver->reset_resume)
+					return -EOPNOTSUPP;
+			}
 		}
 	}
 
@@ -974,7 +1010,7 @@
 			 * or for the past.
 			 */
 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-					suspend_time - jiffies);
+				round_jiffies_relative(suspend_time - jiffies));
 			}
 		return -EAGAIN;
 	}
@@ -983,7 +1019,10 @@
 
 #else
 
-#define autosuspend_check(udev)		0
+static inline int autosuspend_check(struct usb_device *udev)
+{
+	return 0;
+}
 
 #endif	/* CONFIG_USB_SUSPEND */
 
@@ -1041,7 +1080,6 @@
 		if (status < 0)
 			goto done;
 	}
-	cancel_delayed_work(&udev->autosuspend);
 
 	/* Suspend all the interfaces and then udev itself */
 	if (udev->actconfig) {
@@ -1052,22 +1090,36 @@
 				break;
 		}
 	}
-	if (status == 0)
+	if (status == 0) {
+
+		/* Non-root devices don't need to do anything for FREEZE
+		 * or PRETHAW. */
+		if (udev->parent && (msg.event == PM_EVENT_FREEZE ||
+				msg.event == PM_EVENT_PRETHAW))
+			goto done;
 		status = usb_suspend_device(udev, msg);
+	}
 
 	/* If the suspend failed, resume interfaces that did get suspended */
 	if (status != 0) {
 		while (--i >= 0) {
 			intf = udev->actconfig->interface[i];
-			usb_resume_interface(intf);
+			usb_resume_interface(intf, 0);
 		}
 
+		/* Try another autosuspend when the interfaces aren't busy */
+		if (udev->auto_pm)
+			autosuspend_check(udev);
+
 	/* If the suspend succeeded, propagate it up the tree */
-	} else if (parent)
-		usb_autosuspend_device(parent);
+	} else {
+		cancel_delayed_work(&udev->autosuspend);
+		if (parent)
+			usb_autosuspend_device(parent);
+	}
 
  done:
-	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
 	return status;
 }
 
@@ -1122,7 +1174,8 @@
 			status = usb_autoresume_device(parent);
 			if (status == 0) {
 				status = usb_resume_device(udev);
-				if (status) {
+				if (status || udev->state ==
+						USB_STATE_NOTATTACHED) {
 					usb_autosuspend_device(parent);
 
 					/* It's possible usb_resume_device()
@@ -1143,28 +1196,25 @@
 			/* We can't progagate beyond the USB subsystem,
 			 * so if a root hub's controller is suspended
 			 * then we're stuck. */
-			if (udev->dev.parent->power.power_state.event !=
-					PM_EVENT_ON)
-				status = -EHOSTUNREACH;
-			else
-				status = usb_resume_device(udev);
+			status = usb_resume_device(udev);
  		}
 	} else {
 
-		/* Needed only for setting udev->dev.power.power_state.event
-		 * and for possible debugging message. */
+		/* Needed for setting udev->dev.power.power_state.event,
+		 * for possible debugging message, and for reset_resume. */
 		status = usb_resume_device(udev);
 	}
 
 	if (status == 0 && udev->actconfig) {
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
-			usb_resume_interface(intf);
+			usb_resume_interface(intf, udev->reset_resume);
 		}
 	}
 
  done:
-	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+	udev->reset_resume = 0;
 	return status;
 }
 
@@ -1231,8 +1281,8 @@
 	int	status;
 
 	status = usb_autopm_do_device(udev, -1);
-	// dev_dbg(&udev->dev, "%s: cnt %d\n",
-	//		__FUNCTION__, udev->pm_usage_cnt);
+	dev_vdbg(&udev->dev, "%s: cnt %d\n",
+			__FUNCTION__, udev->pm_usage_cnt);
 }
 
 /**
@@ -1251,8 +1301,8 @@
 void usb_try_autosuspend_device(struct usb_device *udev)
 {
 	usb_autopm_do_device(udev, 0);
-	// dev_dbg(&udev->dev, "%s: cnt %d\n",
-	// 		__FUNCTION__, udev->pm_usage_cnt);
+	dev_vdbg(&udev->dev, "%s: cnt %d\n",
+			__FUNCTION__, udev->pm_usage_cnt);
 }
 
 /**
@@ -1279,8 +1329,8 @@
 	int	status;
 
 	status = usb_autopm_do_device(udev, 1);
-	// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
-	//		__FUNCTION__, status, udev->pm_usage_cnt);
+	dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
+			__FUNCTION__, status, udev->pm_usage_cnt);
 	return status;
 }
 
@@ -1352,8 +1402,8 @@
 	int	status;
 
 	status = usb_autopm_do_interface(intf, -1);
-	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
-	//		__FUNCTION__, status, intf->pm_usage_cnt);
+	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+			__FUNCTION__, status, intf->pm_usage_cnt);
 }
 EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
 
@@ -1396,8 +1446,8 @@
 	int	status;
 
 	status = usb_autopm_do_interface(intf, 1);
-	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
-	//		__FUNCTION__, status, intf->pm_usage_cnt);
+	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+			__FUNCTION__, status, intf->pm_usage_cnt);
 	return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
@@ -1418,8 +1468,8 @@
 	int	status;
 
 	status = usb_autopm_do_interface(intf, 0);
-	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
-	//		__FUNCTION__, status, intf->pm_usage_cnt);
+	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+			__FUNCTION__, status, intf->pm_usage_cnt);
 	return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
@@ -1475,6 +1525,7 @@
 	usb_pm_lock(udev);
 	udev->auto_pm = 0;
 	status = usb_resume_both(udev);
+	udev->last_busy = jiffies;
 	usb_pm_unlock(udev);
 
 	/* Now that the device is awake, we can start trying to autosuspend
@@ -1498,8 +1549,15 @@
 	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
 		return 0;
 	udev = to_usb_device(dev);
-	if (udev->autoresume_disabled)
-		return -EPERM;
+
+	/* If autoresume is disabled then we also want to prevent resume
+	 * during system wakeup.  However, a "persistent-device" reset-resume
+	 * after power loss counts as a wakeup event.  So allow a
+	 * reset-resume to occur if remote wakeup is enabled. */
+	if (udev->autoresume_disabled) {
+		if (!(udev->reset_resume && udev->do_remote_wakeup))
+			return -EPERM;
+	}
 	return usb_external_resume_device(udev);
 }
 
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 01c857a..5d860bc 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -16,15 +16,15 @@
  */
 
 #include <linux/module.h>
-#include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/rwsem.h>
 #include <linux/usb.h>
 
 #include "usb.h"
 
 #define MAX_USB_MINORS	256
 static const struct file_operations *usb_minors[MAX_USB_MINORS];
-static DEFINE_SPINLOCK(minor_lock);
+static DECLARE_RWSEM(minor_rwsem);
 
 static int usb_open(struct inode * inode, struct file * file)
 {
@@ -33,14 +33,11 @@
 	int err = -ENODEV;
 	const struct file_operations *old_fops, *new_fops = NULL;
 
-	spin_lock (&minor_lock);
+	down_read(&minor_rwsem);
 	c = usb_minors[minor];
 
-	if (!c || !(new_fops = fops_get(c))) {
-		spin_unlock(&minor_lock);
-		return err;
-	}
-	spin_unlock(&minor_lock);
+	if (!c || !(new_fops = fops_get(c)))
+		goto done;
 
 	old_fops = file->f_op;
 	file->f_op = new_fops;
@@ -52,6 +49,8 @@
 		file->f_op = fops_get(old_fops);
 	}
 	fops_put(old_fops);
+ done:
+	up_read(&minor_rwsem);
 	return err;
 }
 
@@ -166,7 +165,7 @@
 	if (class_driver->fops == NULL)
 		goto exit;
 
-	spin_lock (&minor_lock);
+	down_write(&minor_rwsem);
 	for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
 		if (usb_minors[minor])
 			continue;
@@ -176,7 +175,7 @@
 		retval = 0;
 		break;
 	}
-	spin_unlock (&minor_lock);
+	up_write(&minor_rwsem);
 
 	if (retval)
 		goto exit;
@@ -197,9 +196,9 @@
 	intf->usb_dev = device_create(usb_class->class, &intf->dev,
 				      MKDEV(USB_MAJOR, minor), "%s", temp);
 	if (IS_ERR(intf->usb_dev)) {
-		spin_lock (&minor_lock);
+		down_write(&minor_rwsem);
 		usb_minors[intf->minor] = NULL;
-		spin_unlock (&minor_lock);
+		up_write(&minor_rwsem);
 		retval = PTR_ERR(intf->usb_dev);
 	}
 exit:
@@ -236,9 +235,9 @@
 
 	dbg ("removing %d minor", intf->minor);
 
-	spin_lock (&minor_lock);
+	down_write(&minor_rwsem);
 	usb_minors[intf->minor] = NULL;
-	spin_unlock (&minor_lock);
+	up_write(&minor_rwsem);
 
 	snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
 	device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
@@ -247,5 +246,3 @@
 	destroy_usb_class();
 }
 EXPORT_SYMBOL(usb_deregister_dev);
-
-
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 9bbcb20..b2fc2b1 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -19,6 +19,7 @@
 
 #include <linux/usb.h>
 #include "usb.h"
+#include "hcd.h"
 
 static inline const char *plural(int n)
 {
@@ -193,16 +194,34 @@
 
 static int generic_suspend(struct usb_device *udev, pm_message_t msg)
 {
-	/* USB devices enter SUSPEND state through their hubs, but can be
-	 * marked for FREEZE as soon as their children are already idled.
-	 * But those semantics are useless, so we equate the two (sigh).
+	int rc;
+
+	/* Normal USB devices suspend through their upstream port.
+	 * Root hubs don't have upstream ports to suspend,
+	 * so we have to shut down their downstream HC-to-USB
+	 * interfaces manually by doing a bus (or "global") suspend.
 	 */
-	return usb_port_suspend(udev);
+	if (!udev->parent)
+		rc = hcd_bus_suspend(udev);
+	else
+		rc = usb_port_suspend(udev);
+	return rc;
 }
 
 static int generic_resume(struct usb_device *udev)
 {
-	return usb_port_resume(udev);
+	int rc;
+
+	/* Normal USB devices resume/reset through their upstream port.
+	 * Root hubs don't have upstream ports to resume or reset,
+	 * so we have to start up their downstream HC-to-USB
+	 * interfaces manually by doing a bus (or "global") resume.
+	 */
+	if (!udev->parent)
+		rc = hcd_bus_resume(udev);
+	else
+		rc = usb_port_resume(udev);
+	return rc;
 }
 
 #endif	/* CONFIG_PM */
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index edf4300..5cf6d5f 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -207,7 +207,8 @@
 	 * We must ignore the FREEZE vs SUSPEND distinction here, because
 	 * otherwise the swsusp will save (and restore) garbage state.
 	 */
-	if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON)
+	if (!(hcd->state == HC_STATE_SUSPENDED ||
+			hcd->state == HC_STATE_HALT))
 		return -EBUSY;
 
 	if (hcd->driver->suspend) {
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 40cf882..963520f 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -582,10 +582,12 @@
 	}
 
 	/* The USB 2.0 spec says 256 ms.  This is close enough and won't
-	 * exceed that limit if HZ is 100. */
+	 * exceed that limit if HZ is 100. The math is more clunky than
+	 * maybe expected, this is to make sure that all timers for USB devices
+	 * fire at the same time to give the CPU a break inbetween */
 	if (hcd->uses_new_polling ? hcd->poll_rh :
 			(length == 0 && hcd->status_urb != NULL))
-		mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250));
+		mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
 }
 EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status);
 
@@ -614,8 +616,8 @@
 		urb->hcpriv = hcd;	/* indicate it's queued */
 
 		if (!hcd->uses_new_polling)
-			mod_timer (&hcd->rh_timer, jiffies +
-					msecs_to_jiffies(250));
+			mod_timer (&hcd->rh_timer,
+				(jiffies/(HZ/4) + 1) * (HZ/4));
 
 		/* If a status change has already occurred, report it ASAP */
 		else if (hcd->poll_pending)
@@ -901,17 +903,32 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void urb_unlink (struct urb *urb)
+static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
 {
 	unsigned long		flags;
+	int at_root_hub = (urb->dev == hcd->self.root_hub);
 
 	/* clear all state linking urb to this dev (and hcd) */
-
 	spin_lock_irqsave (&hcd_data_lock, flags);
 	list_del_init (&urb->urb_list);
 	spin_unlock_irqrestore (&hcd_data_lock, flags);
-}
 
+	if (hcd->self.uses_dma && !at_root_hub) {
+		if (usb_pipecontrol (urb->pipe)
+			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+			dma_unmap_single (hcd->self.controller, urb->setup_dma,
+					sizeof (struct usb_ctrlrequest),
+					DMA_TO_DEVICE);
+		if (urb->transfer_buffer_length != 0
+			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+			dma_unmap_single (hcd->self.controller,
+					urb->transfer_dma,
+					urb->transfer_buffer_length,
+					usb_pipein (urb->pipe)
+					    ? DMA_FROM_DEVICE
+					    : DMA_TO_DEVICE);
+	}
+}
 
 /* may be called in any context with a valid urb->dev usecount
  * caller surrenders "ownership" of urb
@@ -948,19 +965,9 @@
 	else switch (hcd->state) {
 	case HC_STATE_RUNNING:
 	case HC_STATE_RESUMING:
-doit:
 		list_add_tail (&urb->urb_list, &ep->urb_list);
 		status = 0;
 		break;
-	case HC_STATE_SUSPENDED:
-		/* HC upstream links (register access, wakeup signaling) can work
-		 * even when the downstream links (and DMA etc) are quiesced; let
-		 * usbcore talk to the root hub.
-		 */
-		if (hcd->self.controller->power.power_state.event == PM_EVENT_ON
-				&& urb->dev->parent == NULL)
-			goto doit;
-		/* FALL THROUGH */
 	default:
 		status = -ESHUTDOWN;
 		break;
@@ -1014,12 +1021,12 @@
 	status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
 done:
 	if (unlikely (status)) {
-		urb_unlink (urb);
+		urb_unlink(hcd, urb);
 		atomic_dec (&urb->use_count);
 		if (urb->reject)
 			wake_up (&usb_kill_urb_queue);
-		usb_put_urb (urb);
 		usbmon_urb_submit_error(&hcd->self, urb, status);
+		usb_put_urb (urb);
 	}
 	return status;
 }
@@ -1175,10 +1182,6 @@
 	struct urb		*urb;
 
 	hcd = bus_to_hcd(udev->bus);
-
-	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
-			udev->state != USB_STATE_NOTATTACHED);
-
 	local_irq_disable ();
 
 	/* ep is already gone from udev->ep_{in,out}[]; no more submits */
@@ -1259,42 +1262,59 @@
 
 #ifdef	CONFIG_PM
 
-int hcd_bus_suspend (struct usb_bus *bus)
+int hcd_bus_suspend(struct usb_device *rhdev)
 {
-	struct usb_hcd		*hcd;
-	int			status;
+	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
+	int		status;
+	int		old_state = hcd->state;
 
-	hcd = container_of (bus, struct usb_hcd, self);
-	if (!hcd->driver->bus_suspend)
-		return -ENOENT;
-	hcd->state = HC_STATE_QUIESCING;
-	status = hcd->driver->bus_suspend (hcd);
-	if (status == 0)
+	dev_dbg(&rhdev->dev, "bus %s%s\n",
+			rhdev->auto_pm ? "auto-" : "", "suspend");
+	if (!hcd->driver->bus_suspend) {
+		status = -ENOENT;
+	} else {
+		hcd->state = HC_STATE_QUIESCING;
+		status = hcd->driver->bus_suspend(hcd);
+	}
+	if (status == 0) {
+		usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
 		hcd->state = HC_STATE_SUSPENDED;
-	else
-		dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+	} else {
+		hcd->state = old_state;
+		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
 				"suspend", status);
+	}
 	return status;
 }
 
-int hcd_bus_resume (struct usb_bus *bus)
+int hcd_bus_resume(struct usb_device *rhdev)
 {
-	struct usb_hcd		*hcd;
-	int			status;
+	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
+	int		status;
+	int		old_state = hcd->state;
 
-	hcd = container_of (bus, struct usb_hcd, self);
+	dev_dbg(&rhdev->dev, "usb %s%s\n",
+			rhdev->auto_pm ? "auto-" : "", "resume");
 	if (!hcd->driver->bus_resume)
 		return -ENOENT;
 	if (hcd->state == HC_STATE_RUNNING)
 		return 0;
+
 	hcd->state = HC_STATE_RESUMING;
-	status = hcd->driver->bus_resume (hcd);
-	if (status == 0)
+	status = hcd->driver->bus_resume(hcd);
+	if (status == 0) {
+		/* TRSMRCY = 10 msec */
+		msleep(10);
+		usb_set_device_state(rhdev, rhdev->actconfig
+				? USB_STATE_CONFIGURED
+				: USB_STATE_ADDRESS);
 		hcd->state = HC_STATE_RUNNING;
-	else {
-		dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+	} else {
+		hcd->state = old_state;
+		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
 				"resume", status);
-		usb_hc_died(hcd);
+		if (status != -ESHUTDOWN)
+			usb_hc_died(hcd);
 	}
 	return status;
 }
@@ -1388,30 +1408,10 @@
  */
 void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
 {
-	int at_root_hub;
-
-	at_root_hub = (urb->dev == hcd->self.root_hub);
-	urb_unlink (urb);
-
-	/* lower level hcd code should use *_dma exclusively if the
-	 * host controller does DMA */
-	if (hcd->self.uses_dma && !at_root_hub) {
-		if (usb_pipecontrol (urb->pipe)
-			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-			dma_unmap_single (hcd->self.controller, urb->setup_dma,
-					sizeof (struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
-		if (urb->transfer_buffer_length != 0
-			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
-			dma_unmap_single (hcd->self.controller, 
-					urb->transfer_dma,
-					urb->transfer_buffer_length,
-					usb_pipein (urb->pipe)
-					    ? DMA_FROM_DEVICE
-					    : DMA_TO_DEVICE);
-	}
-
+	urb_unlink(hcd, urb);
 	usbmon_urb_complete (&hcd->self, urb);
+	usb_unanchor_urb(urb);
+
 	/* pass ownership to the completion handler */
 	urb->complete (urb);
 	atomic_dec (&urb->use_count);
@@ -1685,7 +1685,7 @@
 	spin_unlock_irq (&hcd_root_hub_lock);
 
 #ifdef CONFIG_PM
-	flush_workqueue(ksuspend_usb_wq);
+	cancel_work_sync(&hcd->wakeup_work);
 #endif
 
 	mutex_lock(&usb_bus_list_lock);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index ef50fa4..b5ebb73 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -364,23 +364,13 @@
 #ifdef CONFIG_PM
 extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
 extern void usb_root_hub_lost_power (struct usb_device *rhdev);
-extern int hcd_bus_suspend (struct usb_bus *bus);
-extern int hcd_bus_resume (struct usb_bus *bus);
+extern int hcd_bus_suspend(struct usb_device *rhdev);
+extern int hcd_bus_resume(struct usb_device *rhdev);
 #else
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
 	return;
 }
-
-static inline int hcd_bus_suspend(struct usb_bus *bus)
-{
-	return 0;
-}
-
-static inline int hcd_bus_resume (struct usb_bus *bus)
-{
-	return 0;
-}
 #endif /* CONFIG_PM */
 
 /*
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f6b74a6..fd74c50 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -31,9 +31,16 @@
 #include "hcd.h"
 #include "hub.h"
 
+#ifdef	CONFIG_USB_PERSIST
+#define	USB_PERSIST	1
+#else
+#define	USB_PERSIST	0
+#endif
+
 struct usb_hub {
 	struct device		*intfdev;	/* the "interface" device */
 	struct usb_device	*hdev;
+	struct kref		kref;
 	struct urb		*urb;		/* for interrupt polling pipe */
 
 	/* buffer for urb ... with extra space in case of babble */
@@ -66,6 +73,7 @@
 	unsigned		limited_power:1;
 	unsigned		quiescing:1;
 	unsigned		activating:1;
+	unsigned		disconnected:1;
 
 	unsigned		has_indicators:1;
 	u8			indicator[USB_MAXCHILDREN];
@@ -321,7 +329,7 @@
 	to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
 
 	spin_lock_irqsave(&hub_event_lock, flags);
-	if (list_empty(&hub->event_list)) {
+	if (!hub->disconnected & list_empty(&hub->event_list)) {
 		list_add_tail(&hub->event_list, &hub_event_list);
 		wake_up(&khubd_wait);
 	}
@@ -330,6 +338,7 @@
 
 void usb_kick_khubd(struct usb_device *hdev)
 {
+	/* FIXME: What if hdev isn't bound to the hub driver? */
 	kick_khubd(hdev_to_hub(hdev));
 }
 
@@ -400,9 +409,10 @@
 	struct usb_hub		*hub =
 		container_of(work, struct usb_hub, tt.kevent);
 	unsigned long		flags;
+	int			limit = 100;
 
 	spin_lock_irqsave (&hub->tt.lock, flags);
-	while (!list_empty (&hub->tt.clear_list)) {
+	while (--limit && !list_empty (&hub->tt.clear_list)) {
 		struct list_head	*temp;
 		struct usb_tt_clear	*clear;
 		struct usb_device	*hdev = hub->hdev;
@@ -550,48 +560,68 @@
 static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 {
 	struct usb_device *hdev = hub->hdev;
-	int ret;
+	int ret = 0;
 
-	if (hdev->children[port1-1] && set_state) {
+	if (hdev->children[port1-1] && set_state)
 		usb_set_device_state(hdev->children[port1-1],
 				USB_STATE_NOTATTACHED);
-	}
-	ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+	if (!hub->error)
+		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
 	if (ret)
 		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
-			port1, ret);
-
+				port1, ret);
 	return ret;
 }
 
+/*
+ * Disable a port and mark a logical connnect-change event, so that some
+ * time later khubd will disconnect() any existing usb_device on the port
+ * and will re-enumerate if there actually is a device attached.
+ */
+static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+{
+	dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
+	hub_port_disable(hub, port1, 1);
+
+	/* FIXME let caller ask to power down the port:
+	 *  - some devices won't enumerate without a VBUS power cycle
+	 *  - SRP saves power that way
+	 *  - ... new call, TBD ...
+	 * That's easy if this hub can switch power per-port, and
+	 * khubd reactivates the port later (timer, SRP, etc).
+	 * Powerdown must be optional, because of reset/DFU.
+	 */
+
+	set_bit(port1, hub->change_bits);
+ 	kick_khubd(hub);
+}
 
 /* caller has locked the hub device */
-static void hub_pre_reset(struct usb_interface *intf)
+static int hub_pre_reset(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata(intf);
 	struct usb_device *hdev = hub->hdev;
-	int port1;
+	int i;
 
-	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
-		if (hdev->children[port1 - 1]) {
-			usb_disconnect(&hdev->children[port1 - 1]);
-			if (hub->error == 0)
-				hub_port_disable(hub, port1, 0);
-		}
+	/* Disconnect all the children */
+	for (i = 0; i < hdev->maxchild; ++i) {
+		if (hdev->children[i])
+			usb_disconnect(&hdev->children[i]);
 	}
 	hub_quiesce(hub);
+	return 0;
 }
 
 /* caller has locked the hub device */
-static void hub_post_reset(struct usb_interface *intf)
+static int hub_post_reset(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata(intf);
 
-	hub_activate(hub);
 	hub_power_on(hub);
+	hub_activate(hub);
+	return 0;
 }
 
-
 static int hub_configure(struct usb_hub *hub,
 	struct usb_endpoint_descriptor *endpoint)
 {
@@ -845,43 +875,42 @@
 	return ret;
 }
 
+static void hub_release(struct kref *kref)
+{
+	struct usb_hub *hub = container_of(kref, struct usb_hub, kref);
+
+	usb_put_intf(to_usb_interface(hub->intfdev));
+	kfree(hub);
+}
+
 static unsigned highspeed_hubs;
 
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
-	struct usb_device *hdev;
+
+	/* Take the hub off the event list and don't let it be added again */
+	spin_lock_irq(&hub_event_lock);
+	list_del_init(&hub->event_list);
+	hub->disconnected = 1;
+	spin_unlock_irq(&hub_event_lock);
 
 	/* Disconnect all children and quiesce the hub */
 	hub->error = 0;
 	hub_pre_reset(intf);
 
 	usb_set_intfdata (intf, NULL);
-	hdev = hub->hdev;
 
-	if (hdev->speed == USB_SPEED_HIGH)
+	if (hub->hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs--;
 
 	usb_free_urb(hub->urb);
-	hub->urb = NULL;
-
-	spin_lock_irq(&hub_event_lock);
-	list_del_init(&hub->event_list);
-	spin_unlock_irq(&hub_event_lock);
-
 	kfree(hub->descriptor);
-	hub->descriptor = NULL;
-
 	kfree(hub->status);
-	hub->status = NULL;
+	usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer,
+			hub->buffer_dma);
 
-	if (hub->buffer) {
-		usb_buffer_free(hdev, sizeof(*hub->buffer), hub->buffer,
-				hub->buffer_dma);
-		hub->buffer = NULL;
-	}
-
-	kfree(hub);
+	kref_put(&hub->kref, hub_release);
 }
 
 static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -929,10 +958,12 @@
 		return -ENOMEM;
 	}
 
+	kref_init(&hub->kref);
 	INIT_LIST_HEAD(&hub->event_list);
 	hub->intfdev = &intf->dev;
 	hub->hdev = hdev;
 	INIT_DELAYED_WORK(&hub->leds, led_work);
+	usb_get_intf(intf);
 
 	usb_set_intfdata (intf, hub);
 	intf->needs_remote_wakeup = 1;
@@ -982,49 +1013,6 @@
 }
 
 
-/* grab device/port lock, returning index of that port (zero based).
- * protects the upstream link used by this device from concurrent
- * tree operations like suspend, resume, reset, and disconnect, which
- * apply to everything downstream of a given port.
- */
-static int locktree(struct usb_device *udev)
-{
-	int			t;
-	struct usb_device	*hdev;
-
-	if (!udev)
-		return -ENODEV;
-
-	/* root hub is always the first lock in the series */
-	hdev = udev->parent;
-	if (!hdev) {
-		usb_lock_device(udev);
-		return 0;
-	}
-
-	/* on the path from root to us, lock everything from
-	 * top down, dropping parent locks when not needed
-	 */
-	t = locktree(hdev);
-	if (t < 0)
-		return t;
-
-	/* everything is fail-fast once disconnect
-	 * processing starts
-	 */
-	if (udev->state == USB_STATE_NOTATTACHED) {
-		usb_unlock_device(hdev);
-		return -ENODEV;
-	}
-
-	/* when everyone grabs locks top->bottom,
-	 * non-overlapping work may be concurrent
-	 */
-	usb_lock_device(udev);
-	usb_unlock_device(hdev);
-	return udev->portnum;
-}
-
 static void recursively_mark_NOTATTACHED(struct usb_device *udev)
 {
 	int i;
@@ -1089,46 +1077,6 @@
 	spin_unlock_irqrestore(&device_state_lock, flags);
 }
 
-
-#ifdef	CONFIG_PM
-
-/**
- * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
- * @rhdev: struct usb_device for the root hub
- *
- * The USB host controller driver calls this function when its root hub
- * is resumed and Vbus power has been interrupted or the controller
- * has been reset.  The routine marks all the children of the root hub
- * as NOTATTACHED and marks logical connect-change events on their ports.
- */
-void usb_root_hub_lost_power(struct usb_device *rhdev)
-{
-	struct usb_hub *hub;
-	int port1;
-	unsigned long flags;
-
-	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
-
-	/* Make sure no potential wakeup events get lost,
-	 * by forcing the root hub to be resumed.
-	 */
-	rhdev->dev.power.prev_state.event = PM_EVENT_ON;
-
-	spin_lock_irqsave(&device_state_lock, flags);
-	hub = hdev_to_hub(rhdev);
-	for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
-		if (rhdev->children[port1 - 1]) {
-			recursively_mark_NOTATTACHED(
-					rhdev->children[port1 - 1]);
-			set_bit(port1, hub->change_bits);
-		}
-	}
-	spin_unlock_irqrestore(&device_state_lock, flags);
-}
-EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
-
-#endif	/* CONFIG_PM */
-
 static void choose_address(struct usb_device *udev)
 {
 	int		devnum;
@@ -1158,6 +1106,30 @@
 	}
 }
 
+#ifdef	CONFIG_USB_SUSPEND
+
+static void usb_stop_pm(struct usb_device *udev)
+{
+	/* Synchronize with the ksuspend thread to prevent any more
+	 * autosuspend requests from being submitted, and decrement
+	 * the parent's count of unsuspended children.
+	 */
+	usb_pm_lock(udev);
+	if (udev->parent && !udev->discon_suspended)
+		usb_autosuspend_device(udev->parent);
+	usb_pm_unlock(udev);
+
+	/* Stop any autosuspend requests already submitted */
+	cancel_rearming_delayed_work(&udev->autosuspend);
+}
+
+#else
+
+static inline void usb_stop_pm(struct usb_device *udev)
+{ }
+
+#endif
+
 /**
  * usb_disconnect - disconnect a device (usbcore-internal)
  * @pdev: pointer to device being disconnected
@@ -1224,13 +1196,7 @@
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
 
-	/* Decrement the parent's count of unsuspended children */
-	if (udev->parent) {
-		usb_pm_lock(udev);
-		if (!udev->discon_suspended)
-			usb_autosuspend_device(udev->parent);
-		usb_pm_unlock(udev);
-	}
+	usb_stop_pm(udev);
 
 	put_device(&udev->dev);
 }
@@ -1251,7 +1217,6 @@
 
 #ifdef	CONFIG_USB_OTG
 #include "otg_whitelist.h"
-static int __usb_port_suspend(struct usb_device *, int port1);
 #endif
 
 /**
@@ -1357,11 +1322,11 @@
 		 * (Includes HNP test device.)
 		 */
 		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
-			err = __usb_port_suspend(udev, udev->bus->otg_port);
+			err = usb_port_suspend(udev);
 			if (err < 0)
 				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
 		}
-		err = -ENODEV;
+		err = -ENOTSUPP;
 		goto fail;
 	}
 #endif
@@ -1458,9 +1423,9 @@
 		if (!(portstatus & USB_PORT_STAT_CONNECTION))
 			return -ENOTCONN;
 
-		/* bomb out completely if something weird happened */
+		/* bomb out completely if the connection bounced */
 		if ((portchange & USB_PORT_STAT_C_CONNECTION))
-			return -EINVAL;
+			return -ENOTCONN;
 
 		/* if we`ve finished resetting, then break out of the loop */
 		if (!(portstatus & USB_PORT_STAT_RESET) &&
@@ -1539,34 +1504,24 @@
 	return status;
 }
 
-/*
- * Disable a port and mark a logical connnect-change event, so that some
- * time later khubd will disconnect() any existing usb_device on the port
- * and will re-enumerate if there actually is a device attached.
- */
-static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
-{
-	dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
-	hub_port_disable(hub, port1, 1);
-
-	/* FIXME let caller ask to power down the port:
-	 *  - some devices won't enumerate without a VBUS power cycle
-	 *  - SRP saves power that way
-	 *  - ... new call, TBD ...
-	 * That's easy if this hub can switch power per-port, and
-	 * khubd reactivates the port later (timer, SRP, etc).
-	 * Powerdown must be optional, because of reset/DFU.
-	 */
-
-	set_bit(port1, hub->change_bits);
- 	kick_khubd(hub);
-}
-
 #ifdef	CONFIG_PM
 
 #ifdef	CONFIG_USB_SUSPEND
 
 /*
+ * usb_port_suspend - suspend a usb device's upstream port
+ * @udev: device that's no longer in active use, not a root hub
+ * Context: must be able to sleep; device not locked; pm locks held
+ *
+ * Suspends a USB device that isn't in active use, conserving power.
+ * Devices may wake out of a suspend, if anything important happens,
+ * using the remote wakeup mechanism.  They may also be taken out of
+ * suspend by the host, using usb_port_resume().  It's also routine
+ * to disconnect devices while they are suspended.
+ *
+ * This only affects the USB hardware for a device; its interfaces
+ * (and, for hubs, child devices) must already have been suspended.
+ *
  * Selective port suspend reduces power; most suspended devices draw
  * less than 500 uA.  It's also used in OTG, along with remote wakeup.
  * All devices below the suspended port are also suspended.
@@ -1575,11 +1530,35 @@
  * also support "remote wakeup", where the device can activate the USB
  * tree above them to deliver data, such as a keypress or packet.  In
  * some cases, this wakes the USB host.
+ *
+ * Suspending OTG devices may trigger HNP, if that's been enabled
+ * between a pair of dual-role devices.  That will change roles, such
+ * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
+ *
+ * Devices on USB hub ports have only one "suspend" state, corresponding
+ * to ACPI D2, "may cause the device to lose some context".
+ * State transitions include:
+ *
+ *   - suspend, resume ... when the VBUS power link stays live
+ *   - suspend, disconnect ... VBUS lost
+ *
+ * Once VBUS drop breaks the circuit, the port it's using has to go through
+ * normal re-enumeration procedures, starting with enabling VBUS power.
+ * Other than re-initializing the hub (plug/unplug, except for root hubs),
+ * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+ * timer, no SRP, no requests through sysfs.
+ *
+ * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+ * the root hub for their bus goes into global suspend ... so we don't
+ * (falsely) update the device power state to say it suspended.
+ *
+ * Returns 0 on success, else negative errno.
  */
-static int hub_port_suspend(struct usb_hub *hub, int port1,
-		struct usb_device *udev)
+int usb_port_suspend(struct usb_device *udev)
 {
-	int	status;
+	struct usb_hub	*hub = hdev_to_hub(udev->parent);
+	int		port1 = udev->portnum;
+	int		status;
 
 	// dev_dbg(hub->intfdev, "suspend port %d\n", port1);
 
@@ -1596,17 +1575,15 @@
 				NULL, 0,
 				USB_CTRL_SET_TIMEOUT);
 		if (status)
-			dev_dbg(&udev->dev,
-				"won't remote wakeup, status %d\n",
-				status);
+			dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
+					status);
 	}
 
 	/* see 7.1.7.6 */
 	status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND);
 	if (status) {
-		dev_dbg(hub->intfdev,
-			"can't suspend port %d, status %d\n",
-			port1, status);
+		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
+				port1, status);
 		/* paranoia:  "should not happen" */
 		(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
@@ -1624,85 +1601,24 @@
 }
 
 /*
- * Devices on USB hub ports have only one "suspend" state, corresponding
- * to ACPI D2, "may cause the device to lose some context".
- * State transitions include:
- *
- *   - suspend, resume ... when the VBUS power link stays live
- *   - suspend, disconnect ... VBUS lost
- *
- * Once VBUS drop breaks the circuit, the port it's using has to go through
- * normal re-enumeration procedures, starting with enabling VBUS power.
- * Other than re-initializing the hub (plug/unplug, except for root hubs),
- * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
- * timer, no SRP, no requests through sysfs.
- *
- * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
- * the root hub for their bus goes into global suspend ... so we don't
- * (falsely) update the device power state to say it suspended.
- */
-static int __usb_port_suspend (struct usb_device *udev, int port1)
-{
-	int	status = 0;
-
-	/* caller owns the udev device lock */
-	if (port1 < 0)
-		return port1;
-
-	/* we change the device's upstream USB link,
-	 * but root hubs have no upstream USB link.
-	 */
-	if (udev->parent)
-		status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
-				udev);
-	else {
-		dev_dbg(&udev->dev, "usb %ssuspend\n",
-				udev->auto_pm ? "auto-" : "");
-		usb_set_device_state(udev, USB_STATE_SUSPENDED);
-	}
-	return status;
-}
-
-/*
- * usb_port_suspend - suspend a usb device's upstream port
- * @udev: device that's no longer in active use
- * Context: must be able to sleep; device not locked; pm locks held
- *
- * Suspends a USB device that isn't in active use, conserving power.
- * Devices may wake out of a suspend, if anything important happens,
- * using the remote wakeup mechanism.  They may also be taken out of
- * suspend by the host, using usb_port_resume().  It's also routine
- * to disconnect devices while they are suspended.
- *
- * This only affects the USB hardware for a device; its interfaces
- * (and, for hubs, child devices) must already have been suspended.
- *
- * Suspending OTG devices may trigger HNP, if that's been enabled
- * between a pair of dual-role devices.  That will change roles, such
- * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
- *
- * Returns 0 on success, else negative errno.
- */
-int usb_port_suspend(struct usb_device *udev)
-{
-	return __usb_port_suspend(udev, udev->portnum);
-}
-
-/*
  * If the USB "suspend" state is in use (rather than "global suspend"),
  * many devices will be individually taken out of suspend state using
- * special" resume" signaling.  These routines kick in shortly after
+ * special "resume" signaling.  This routine kicks in shortly after
  * hardware resume signaling is finished, either because of selective
  * resume (by host) or remote wakeup (by device) ... now see what changed
  * in the tree that's rooted at this device.
+ *
+ * If @udev->reset_resume is set then the device is reset before the
+ * status check is done.
  */
 static int finish_port_resume(struct usb_device *udev)
 {
-	int	status;
+	int	status = 0;
 	u16	devstatus;
 
 	/* caller owns the udev device lock */
-	dev_dbg(&udev->dev, "finish resume\n");
+	dev_dbg(&udev->dev, "finish %sresume\n",
+			udev->reset_resume ? "reset-" : "");
 
 	/* usb ch9 identifies four variants of SUSPENDED, based on what
 	 * state the device resumes to.  Linux currently won't see the
@@ -1713,22 +1629,30 @@
 			? USB_STATE_CONFIGURED
 			: USB_STATE_ADDRESS);
 
+	/* 10.5.4.5 says not to reset a suspended port if the attached
+	 * device is enabled for remote wakeup.  Hence the reset
+	 * operation is carried out here, after the port has been
+	 * resumed.
+	 */
+	if (udev->reset_resume)
+		status = usb_reset_device(udev);
+
  	/* 10.5.4.5 says be sure devices in the tree are still there.
  	 * For now let's assume the device didn't go crazy on resume,
 	 * and device drivers will know about any resume quirks.
 	 */
-	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
-	if (status >= 0)
-		status = (status == 2 ? 0 : -ENODEV);
+	if (status == 0) {
+		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+		if (status >= 0)
+			status = (status == 2 ? 0 : -ENODEV);
+	}
 
-	if (status)
-		dev_dbg(&udev->dev,
-			"gone after usb resume? status %d\n",
-			status);
-	else if (udev->actconfig) {
+	if (status) {
+		dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
+				status);
+	} else if (udev->actconfig) {
 		le16_to_cpus(&devstatus);
-		if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
-				&& udev->parent) {
+		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
 			status = usb_control_msg(udev,
 					usb_sndctrlpipe(udev, 0),
 					USB_REQ_CLEAR_FEATURE,
@@ -1741,19 +1665,52 @@
 					"wakeup, status %d\n", status);
 		}
 		status = 0;
-
-	} else if (udev->devnum <= 0) {
-		dev_dbg(&udev->dev, "bogus resume!\n");
-		status = -EINVAL;
 	}
 	return status;
 }
 
-static int
-hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+/*
+ * usb_port_resume - re-activate a suspended usb device's upstream port
+ * @udev: device to re-activate, not a root hub
+ * Context: must be able to sleep; device not locked; pm locks held
+ *
+ * This will re-activate the suspended device, increasing power usage
+ * while letting drivers communicate again with its endpoints.
+ * USB resume explicitly guarantees that the power session between
+ * the host and the device is the same as it was when the device
+ * suspended.
+ *
+ * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this
+ * routine won't check that the port is still enabled.  Furthermore,
+ * if @udev->reset_resume is set then finish_port_resume() above will
+ * reset @udev.  The end result is that a broken power session can be
+ * recovered and @udev will appear to persist across a loss of VBUS power.
+ *
+ * For example, if a host controller doesn't maintain VBUS suspend current
+ * during a system sleep or is reset when the system wakes up, all the USB
+ * power sessions below it will be broken.  This is especially troublesome
+ * for mass-storage devices containing mounted filesystems, since the
+ * device will appear to have disconnected and all the memory mappings
+ * to it will be lost.  Using the USB_PERSIST facility, the device can be
+ * made to appear as if it had not disconnected.
+ *
+ * This facility is inherently dangerous.  Although usb_reset_device()
+ * makes every effort to insure that the same device is present after the
+ * reset as before, it cannot provide a 100% guarantee.  Furthermore it's
+ * quite possible for a device to remain unaltered but its media to be
+ * changed.  If the user replaces a flash memory card while the system is
+ * asleep, he will have only himself to blame when the filesystem on the
+ * new card is corrupted and the system crashes.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_port_resume(struct usb_device *udev)
 {
-	int	status;
-	u16	portchange, portstatus;
+	struct usb_hub	*hub = hdev_to_hub(udev->parent);
+	int		port1 = udev->portnum;
+	int		status;
+	u16		portchange, portstatus;
+	unsigned	mask_flags, want_flags;
 
 	/* Skip the initial Clear-Suspend step for a remote wakeup */
 	status = hub_port_status(hub, port1, &portstatus, &portchange);
@@ -1768,30 +1725,31 @@
 	status = clear_port_feature(hub->hdev,
 			port1, USB_PORT_FEAT_SUSPEND);
 	if (status) {
-		dev_dbg(hub->intfdev,
-			"can't resume port %d, status %d\n",
-			port1, status);
+		dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
+				port1, status);
 	} else {
 		/* drive resume for at least 20 msec */
-		if (udev)
-			dev_dbg(&udev->dev, "usb %sresume\n",
-					udev->auto_pm ? "auto-" : "");
+		dev_dbg(&udev->dev, "usb %sresume\n",
+				udev->auto_pm ? "auto-" : "");
 		msleep(25);
 
-#define LIVE_FLAGS	( USB_PORT_STAT_POWER \
-			| USB_PORT_STAT_ENABLE \
-			| USB_PORT_STAT_CONNECTION)
-
 		/* Virtual root hubs can trigger on GET_PORT_STATUS to
 		 * stop resume signaling.  Then finish the resume
 		 * sequence.
 		 */
 		status = hub_port_status(hub, port1, &portstatus, &portchange);
-SuspendCleared:
-		if (status < 0
-				|| (portstatus & LIVE_FLAGS) != LIVE_FLAGS
-				|| (portstatus & USB_PORT_STAT_SUSPEND) != 0
-				) {
+
+ SuspendCleared:
+		if (USB_PERSIST && udev->reset_resume)
+			want_flags = USB_PORT_STAT_POWER
+					| USB_PORT_STAT_CONNECTION;
+		else
+			want_flags = USB_PORT_STAT_POWER
+					| USB_PORT_STAT_CONNECTION
+					| USB_PORT_STAT_ENABLE;
+		mask_flags = want_flags | USB_PORT_STAT_SUSPEND;
+
+		if (status < 0 || (portstatus & mask_flags) != want_flags) {
 			dev_dbg(hub->intfdev,
 				"port %d status %04x.%04x after resume, %d\n",
 				port1, portchange, portstatus, status);
@@ -1803,51 +1761,19 @@
 						USB_PORT_FEAT_C_SUSPEND);
 			/* TRSMRCY = 10 msec */
 			msleep(10);
-			if (udev)
-				status = finish_port_resume(udev);
 		}
 	}
-	if (status < 0)
-		hub_port_logical_disconnect(hub, port1);
 
 	clear_bit(port1, hub->busy_bits);
 	if (!hub->hdev->parent && !hub->busy_bits[0])
 		usb_enable_root_hub_irq(hub->hdev->bus);
 
-	return status;
-}
-
-/*
- * usb_port_resume - re-activate a suspended usb device's upstream port
- * @udev: device to re-activate
- * Context: must be able to sleep; device not locked; pm locks held
- *
- * This will re-activate the suspended device, increasing power usage
- * while letting drivers communicate again with its endpoints.
- * USB resume explicitly guarantees that the power session between
- * the host and the device is the same as it was when the device
- * suspended.
- *
- * Returns 0 on success, else negative errno.
- */
-int usb_port_resume(struct usb_device *udev)
-{
-	int	status;
-
-	/* we change the device's upstream USB link,
-	 * but root hubs have no upstream USB link.
-	 */
-	if (udev->parent) {
-		// NOTE this fails if parent is also suspended...
-		status = hub_port_resume(hdev_to_hub(udev->parent),
-				udev->portnum, udev);
-	} else {
-		dev_dbg(&udev->dev, "usb %sresume\n",
-				udev->auto_pm ? "auto-" : "");
+	if (status == 0)
 		status = finish_port_resume(udev);
-	}
-	if (status < 0)
+	if (status < 0) {
 		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+		hub_port_logical_disconnect(hub, port1);
+	}
 	return status;
 }
 
@@ -1874,21 +1800,16 @@
 	return 0;
 }
 
-static inline int
-finish_port_resume(struct usb_device *udev)
-{
-	return 0;
-}
-
-static inline int
-hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
-{
-	return 0;
-}
-
 int usb_port_resume(struct usb_device *udev)
 {
-	return 0;
+	int status = 0;
+
+	/* However we may need to do a reset-resume */
+	if (udev->reset_resume) {
+		dev_dbg(&udev->dev, "reset-resume\n");
+		status = usb_reset_device(udev);
+	}
+	return status;
 }
 
 static inline int remote_wakeup(struct usb_device *udev)
@@ -1903,7 +1824,6 @@
 	struct usb_hub		*hub = usb_get_intfdata (intf);
 	struct usb_device	*hdev = hub->hdev;
 	unsigned		port1;
-	int			status = 0;
 
 	/* fail if children aren't already suspended */
 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -1929,49 +1849,75 @@
 
 	/* stop khubd and related activity */
 	hub_quiesce(hub);
-
-	/* "global suspend" of the downstream HC-to-USB interface */
-	if (!hdev->parent) {
-		status = hcd_bus_suspend(hdev->bus);
-		if (status != 0) {
-			dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
-			hub_activate(hub);
-		}
-	}
-	return status;
+	return 0;
 }
 
 static int hub_resume(struct usb_interface *intf)
 {
 	struct usb_hub		*hub = usb_get_intfdata (intf);
-	struct usb_device	*hdev = hub->hdev;
-	int			status;
 
 	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
 
-	/* "global resume" of the downstream HC-to-USB interface */
-	if (!hdev->parent) {
-		struct usb_bus	*bus = hdev->bus;
-		if (bus) {
-			status = hcd_bus_resume (bus);
-			if (status) {
-				dev_dbg(&intf->dev, "'global' resume %d\n",
-					status);
-				return status;
-			}
-		} else
-			return -EOPNOTSUPP;
-		if (status == 0) {
-			/* TRSMRCY = 10 msec */
-			msleep(10);
-		}
-	}
-
 	/* tell khubd to look for changes on this hub */
 	hub_activate(hub);
 	return 0;
 }
 
+static int hub_reset_resume(struct usb_interface *intf)
+{
+	struct usb_hub *hub = usb_get_intfdata(intf);
+	struct usb_device *hdev = hub->hdev;
+	int port1;
+
+	hub_power_on(hub);
+
+	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+		struct usb_device *child = hdev->children[port1-1];
+
+		if (child) {
+
+			/* For "USB_PERSIST"-enabled children we must
+			 * mark the child device for reset-resume and
+			 * turn off the connect-change status to prevent
+			 * khubd from disconnecting it later.
+			 */
+			if (USB_PERSIST && child->persist_enabled) {
+				child->reset_resume = 1;
+				clear_port_feature(hdev, port1,
+						USB_PORT_FEAT_C_CONNECTION);
+
+			/* Otherwise we must disconnect the child,
+			 * but as we may not lock the child device here
+			 * we have to do a "logical" disconnect.
+			 */
+			} else {
+				hub_port_logical_disconnect(hub, port1);
+			}
+		}
+	}
+
+	hub_activate(hub);
+	return 0;
+}
+
+/**
+ * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+ * @rhdev: struct usb_device for the root hub
+ *
+ * The USB host controller driver calls this function when its root hub
+ * is resumed and Vbus power has been interrupted or the controller
+ * has been reset.  The routine marks @rhdev as having lost power.  When
+ * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
+ * is enabled then it will carry out power-session recovery, otherwise
+ * it will disconnect all the child devices.
+ */
+void usb_root_hub_lost_power(struct usb_device *rhdev)
+{
+	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+	rhdev->reset_resume = 1;
+}
+EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+
 #else	/* CONFIG_PM */
 
 static inline int remote_wakeup(struct usb_device *udev)
@@ -1979,8 +1925,9 @@
 	return 0;
 }
 
-#define hub_suspend NULL
-#define hub_resume NULL
+#define hub_suspend		NULL
+#define hub_resume		NULL
+#define hub_reset_resume	NULL
 #endif
 
 
@@ -2201,14 +2148,9 @@
 				continue;
 			}
 
-			/* Use a short timeout the first time through,
-			 * so that recalcitrant full-speed devices with
-			 * 8- or 16-byte ep0-maxpackets won't slow things
-			 * down tremendously by NAKing the unexpectedly
-			 * early status stage.  Also, retry on all errors;
-			 * some devices are flakey.
-			 * 255 is for WUSB devices, we actually need to use 512.
-			 * WUSB1.0[4.8.1].
+			/* Retry on all errors; some devices are flakey.
+			 * 255 is for WUSB devices, we actually need to use
+			 * 512 (WUSB1.0[4.8.1]).
 			 */
 			for (j = 0; j < 3; ++j) {
 				buf->bMaxPacketSize0 = 0;
@@ -2216,7 +2158,7 @@
 					USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 					USB_DT_DEVICE << 8, 0,
 					buf, GET_DESCRIPTOR_BUFSIZE,
-					(i ? USB_CTRL_GET_TIMEOUT : 1000));
+					USB_CTRL_GET_TIMEOUT);
 				switch (buf->bMaxPacketSize0) {
 				case 8: case 16: case 32: case 64: case 255:
 					if (buf->bDescriptorType ==
@@ -2426,10 +2368,10 @@
 
 	if (portchange & USB_PORT_STAT_C_CONNECTION) {
 		status = hub_port_debounce(hub, port1);
-		if (status < 0 && printk_ratelimit()) {
-			dev_err (hub_dev,
-				"connect-debounce failed, port %d disabled\n",
-				port1);
+		if (status < 0) {
+			if (printk_ratelimit())
+				dev_err (hub_dev, "connect-debounce failed, "
+						"port %d disabled\n", port1);
 			goto done;
 		}
 		portstatus = status;
@@ -2448,19 +2390,6 @@
 		return;
 	}
 
-#ifdef  CONFIG_USB_SUSPEND
-	/* If something is connected, but the port is suspended, wake it up. */
-	if (portstatus & USB_PORT_STAT_SUSPEND) {
-		status = hub_port_resume(hub, port1, NULL);
-		if (status < 0) {
-			dev_dbg(hub_dev,
-				"can't clear suspend on port %d; %d\n",
-				port1, status);
-			goto done;
-		}
-	}
-#endif
-
 	for (i = 0; i < SET_CONFIG_TRIES; i++) {
 		struct usb_device *udev;
 
@@ -2571,7 +2500,7 @@
 		ep0_reinit(udev);
 		release_address(udev);
 		usb_put_dev(udev);
-		if (status == -ENOTCONN)
+		if ((status == -ENOTCONN) || (status == -ENOTSUPP))
 			break;
 	}
  
@@ -2612,10 +2541,12 @@
 		list_del_init(tmp);
 
 		hub = list_entry(tmp, struct usb_hub, event_list);
-		hdev = hub->hdev;
-		intf = to_usb_interface(hub->intfdev);
-		hub_dev = &intf->dev;
+		kref_get(&hub->kref);
+		spin_unlock_irq(&hub_event_lock);
 
+		hdev = hub->hdev;
+		hub_dev = hub->intfdev;
+		intf = to_usb_interface(hub_dev);
 		dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
 				hdev->state, hub->descriptor
 					? hub->descriptor->bNbrPorts
@@ -2624,16 +2555,10 @@
 				(u16) hub->change_bits[0],
 				(u16) hub->event_bits[0]);
 
-		usb_get_intf(intf);
-		spin_unlock_irq(&hub_event_lock);
-
 		/* Lock the device, then check to see if we were
 		 * disconnected while waiting for the lock to succeed. */
-		if (locktree(hdev) < 0) {
-			usb_put_intf(intf);
-			continue;
-		}
-		if (hub != usb_get_intfdata(intf))
+		usb_lock_device(hdev);
+		if (unlikely(hub->disconnected))
 			goto loop;
 
 		/* If the hub has died, clean up after it */
@@ -2796,13 +2721,14 @@
 			usb_autopm_enable(intf);
 loop:
 		usb_unlock_device(hdev);
-		usb_put_intf(intf);
+		kref_put(&hub->kref, hub_release);
 
         } /* end while (1) */
 }
 
 static int hub_thread(void *__unused)
 {
+	set_freezable();
 	do {
 		hub_events();
 		wait_event_interruptible(khubd_wait,
@@ -2831,6 +2757,7 @@
 	.disconnect =	hub_disconnect,
 	.suspend =	hub_suspend,
 	.resume =	hub_resume,
+	.reset_resume =	hub_reset_resume,
 	.pre_reset =	hub_pre_reset,
 	.post_reset =	hub_post_reset,
 	.ioctl =	hub_ioctl,
@@ -2933,6 +2860,11 @@
  * this from a driver probe() routine after downloading new firmware.
  * For calls that might not occur during probe(), drivers should lock
  * the device using usb_lock_device_for_reset().
+ *
+ * Locking exception: This routine may also be called from within an
+ * autoresume handler.  Such usage won't conflict with other tasks
+ * holding the device lock because these tasks should always call
+ * usb_autopm_resume_device(), thereby preventing any unwanted autoresume.
  */
 int usb_reset_device(struct usb_device *udev)
 {
@@ -2963,7 +2895,7 @@
 		 * Other endpoints will be handled by re-enumeration. */
 		ep0_reinit(udev);
 		ret = hub_port_init(parent_hub, udev, port1, i);
-		if (ret >= 0)
+		if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
 			break;
 	}
 	clear_bit(port1, parent_hub->busy_bits);
@@ -3079,6 +3011,7 @@
 				drv = to_usb_driver(cintf->dev.driver);
 				if (drv->pre_reset)
 					(drv->pre_reset)(cintf);
+	/* FIXME: Unbind if pre_reset returns an error or isn't defined */
 			}
 		}
 	}
@@ -3097,6 +3030,7 @@
 				drv = to_usb_driver(cintf->dev.driver);
 				if (drv->post_reset)
 					(drv->post_reset)(cintf);
+	/* FIXME: Unbind if post_reset returns an error or isn't defined */
 			}
 			if (cintf != iface)
 				up(&cintf->dev.sem);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index b743478..530e854 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -221,15 +221,10 @@
 
 	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
 			USB_ENDPOINT_XFER_INT) {
-		int interval;
-
-		if (usb_dev->speed == USB_SPEED_HIGH)
-			interval = 1 << min(15, ep->desc.bInterval - 1);
-		else
-			interval = ep->desc.bInterval;
 		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
 		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
-				usb_api_blocking_completion, NULL, interval);
+				usb_api_blocking_completion, NULL,
+				ep->desc.bInterval);
 	} else
 		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
 				usb_api_blocking_completion, NULL);
@@ -409,8 +404,6 @@
 
 		io->urbs [i]->complete = sg_complete;
 		io->urbs [i]->context = io;
-		io->urbs [i]->status = -EINPROGRESS;
-		io->urbs [i]->actual_length = 0;
 
 		/*
 		 * Some systems need to revert to PIO when DMA is temporarily
@@ -504,7 +497,8 @@
 
 	/* queue the urbs.  */
 	spin_lock_irq (&io->lock);
-	for (i = 0; i < entries && !io->status; i++) {
+	i = 0;
+	while (i < entries && !io->status) {
 		int	retval;
 
 		io->urbs [i]->dev = io->dev;
@@ -521,7 +515,6 @@
 		case -ENOMEM:
 			io->urbs[i]->dev = NULL;
 			retval = 0;
-			i--;
 			yield ();
 			break;
 
@@ -532,6 +525,7 @@
 			 * URBs are queued at once; N milliseconds?
 			 */
 		case 0:
+			++i;
 			cpu_relax ();
 			break;
 
@@ -1390,6 +1384,36 @@
 	.uevent =	usb_if_uevent,
 };
 
+static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
+						       struct usb_host_config *config,
+						       u8 inum)
+{
+	struct usb_interface_assoc_descriptor *retval = NULL;
+	struct usb_interface_assoc_descriptor *intf_assoc;
+	int first_intf;
+	int last_intf;
+	int i;
+
+	for (i = 0; (i < USB_MAXIADS && config->intf_assoc[i]); i++) {
+		intf_assoc = config->intf_assoc[i];
+		if (intf_assoc->bInterfaceCount == 0)
+			continue;
+
+		first_intf = intf_assoc->bFirstInterface;
+		last_intf = first_intf + (intf_assoc->bInterfaceCount - 1);
+		if (inum >= first_intf && inum <= last_intf) {
+			if (!retval)
+				retval = intf_assoc;
+			else
+				dev_err(&dev->dev, "Interface #%d referenced"
+					" by multiple IADs\n", inum);
+		}
+	}
+
+	return retval;
+}
+
+
 /*
  * usb_set_configuration - Makes a particular device setting be current
  * @dev: the device whose configuration is being updated
@@ -1536,6 +1560,7 @@
 		intfc = cp->intf_cache[i];
 		intf->altsetting = intfc->altsetting;
 		intf->num_altsetting = intfc->num_altsetting;
+		intf->intf_assoc = find_iad(dev, cp, i);
 		kref_get(&intfc->ref);
 
 		alt = usb_altnum_to_altsetting(intf, 0);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 739f520..aa21b38 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -30,10 +30,28 @@
 static const struct usb_device_id usb_quirk_list[] = {
 	/* HP 5300/5370C scanner */
 	{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+	/* Benq S2W 3300U */
+	{ USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	/* Seiko Epson Corp. Perfection 1200 */
+	{ USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Seiko Epson Corp - Perfection 1670 */
 	{ USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	/* Samsung ML-2510 Series printer */
+	{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 	/* Elsa MicroLink 56k (V.250) */
 	{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	/* Ultima Electronics Corp.*/
+	{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	/* Umax [hex] Astra 3400U */
+	{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+
+	/* Philips PSC805 audio device */
+	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+
+	/* RIM Blackberry */
+	{ USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	{ USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+	{ USB_DEVICE(0x0fca, 0x0006), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
 
 	{ }  /* terminating entry must be last */
 };
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index e7c9823..d47ae89 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -169,6 +169,73 @@
 }
 static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
 
+
+#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
+static const char power_group[] = "power";
+#endif
+
+#ifdef	CONFIG_USB_PERSIST
+
+static ssize_t
+show_persist(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev = to_usb_device(dev);
+
+	return sprintf(buf, "%d\n", udev->persist_enabled);
+}
+
+static ssize_t
+set_persist(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct usb_device *udev = to_usb_device(dev);
+	int value;
+
+	/* Hubs are always enabled for USB_PERSIST */
+	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+		return -EPERM;
+
+	if (sscanf(buf, "%d", &value) != 1)
+		return -EINVAL;
+	usb_pm_lock(udev);
+	udev->persist_enabled = !!value;
+	usb_pm_unlock(udev);
+	return count;
+}
+
+static DEVICE_ATTR(persist, S_IRUGO | S_IWUSR, show_persist, set_persist);
+
+static int add_persist_attributes(struct device *dev)
+{
+	int rc = 0;
+
+	if (is_usb_device(dev)) {
+		struct usb_device *udev = to_usb_device(dev);
+
+		/* Hubs are automatically enabled for USB_PERSIST */
+		if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+			udev->persist_enabled = 1;
+		rc = sysfs_add_file_to_group(&dev->kobj,
+				&dev_attr_persist.attr,
+				power_group);
+	}
+	return rc;
+}
+
+static void remove_persist_attributes(struct device *dev)
+{
+	sysfs_remove_file_from_group(&dev->kobj,
+			&dev_attr_persist.attr,
+			power_group);
+}
+
+#else
+
+#define add_persist_attributes(dev)	0
+#define remove_persist_attributes(dev)	do {} while (0)
+
+#endif	/* CONFIG_USB_PERSIST */
+
 #ifdef	CONFIG_USB_SUSPEND
 
 static ssize_t
@@ -232,12 +299,15 @@
 	int len = count;
 	char *cp;
 	int rc = 0;
+	int old_autosuspend_disabled, old_autoresume_disabled;
 
 	cp = memchr(buf, '\n', count);
 	if (cp)
 		len = cp - buf;
 
 	usb_lock_device(udev);
+	old_autosuspend_disabled = udev->autosuspend_disabled;
+	old_autoresume_disabled = udev->autoresume_disabled;
 
 	/* Setting the flags without calling usb_pm_lock is a subject to
 	 * races, but who cares...
@@ -263,14 +333,16 @@
 	} else
 		rc = -EINVAL;
 
+	if (rc) {
+		udev->autosuspend_disabled = old_autosuspend_disabled;
+		udev->autoresume_disabled = old_autoresume_disabled;
+	}
 	usb_unlock_device(udev);
 	return (rc < 0 ? rc : count);
 }
 
 static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
 
-static char power_group[] = "power";
-
 static int add_power_attributes(struct device *dev)
 {
 	int rc = 0;
@@ -304,6 +376,7 @@
 
 #endif	/* CONFIG_USB_SUSPEND */
 
+
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)			\
 static ssize_t								\
@@ -377,6 +450,10 @@
 	if (retval)
 		return retval;
 
+	retval = add_persist_attributes(dev);
+	if (retval)
+		goto error;
+
 	retval = add_power_attributes(dev);
 	if (retval)
 		goto error;
@@ -414,9 +491,29 @@
 	device_remove_file(dev, &dev_attr_product);
 	device_remove_file(dev, &dev_attr_serial);
 	remove_power_attributes(dev);
+	remove_persist_attributes(dev);
 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
 }
 
+/* Interface Accociation Descriptor fields */
+#define usb_intf_assoc_attr(field, format_string)			\
+static ssize_t								\
+show_iad_##field (struct device *dev, struct device_attribute *attr,	\
+		char *buf)						\
+{									\
+	struct usb_interface *intf = to_usb_interface (dev);		\
+									\
+	return sprintf (buf, format_string,				\
+			intf->intf_assoc->field); 		\
+}									\
+static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL);
+
+usb_intf_assoc_attr (bFirstInterface, "%02x\n")
+usb_intf_assoc_attr (bInterfaceCount, "%02d\n")
+usb_intf_assoc_attr (bFunctionClass, "%02x\n")
+usb_intf_assoc_attr (bFunctionSubClass, "%02x\n")
+usb_intf_assoc_attr (bFunctionProtocol, "%02x\n")
+
 /* Interface fields */
 #define usb_intf_attr(field, format_string)				\
 static ssize_t								\
@@ -480,6 +577,18 @@
 }
 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
 
+static struct attribute *intf_assoc_attrs[] = {
+	&dev_attr_iad_bFirstInterface.attr,
+	&dev_attr_iad_bInterfaceCount.attr,
+	&dev_attr_iad_bFunctionClass.attr,
+	&dev_attr_iad_bFunctionSubClass.attr,
+	&dev_attr_iad_bFunctionProtocol.attr,
+	NULL,
+};
+static struct attribute_group intf_assoc_attr_grp = {
+	.attrs = intf_assoc_attrs,
+};
+
 static struct attribute *intf_attrs[] = {
 	&dev_attr_bInterfaceNumber.attr,
 	&dev_attr_bAlternateSetting.attr,
@@ -531,6 +640,8 @@
 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
 	if (alt->string)
 		retval = device_create_file(dev, &dev_attr_interface);
+	if (intf->intf_assoc)
+		retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
 	usb_create_intf_ep_files(intf, udev);
 	return 0;
 }
@@ -542,4 +653,5 @@
 	usb_remove_intf_ep_files(intf);
 	device_remove_file(dev, &dev_attr_interface);
 	sysfs_remove_group(&dev->kobj, &intf_attr_grp);
+	sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
 }
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 94ea972..52ec44b 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -4,6 +4,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/usb.h>
+#include <linux/wait.h>
 #include "hcd.h"
 
 #define to_urb(d) container_of(d, struct urb, kref)
@@ -11,6 +12,10 @@
 static void urb_destroy(struct kref *kref)
 {
 	struct urb *urb = to_urb(kref);
+
+	if (urb->transfer_flags & URB_FREE_BUFFER)
+		kfree(urb->transfer_buffer);
+
 	kfree(urb);
 }
 
@@ -34,6 +39,7 @@
 		memset(urb, 0, sizeof(*urb));
 		kref_init(&urb->kref);
 		spin_lock_init(&urb->lock);
+		INIT_LIST_HEAD(&urb->anchor_list);
 	}
 }
 
@@ -100,8 +106,60 @@
 		kref_get(&urb->kref);
 	return urb;
 }
-		
-		
+
+/**
+ * usb_anchor_urb - anchors an URB while it is processed
+ * @urb: pointer to the urb to anchor
+ * @anchor: pointer to the anchor
+ *
+ * This can be called to have access to URBs which are to be executed
+ * without bothering to track them
+ */
+void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&anchor->lock, flags);
+	usb_get_urb(urb);
+	list_add_tail(&urb->anchor_list, &anchor->urb_list);
+	urb->anchor = anchor;
+	spin_unlock_irqrestore(&anchor->lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_anchor_urb);
+
+/**
+ * usb_unanchor_urb - unanchors an URB
+ * @urb: pointer to the urb to anchor
+ *
+ * Call this to stop the system keeping track of this URB
+ */
+void usb_unanchor_urb(struct urb *urb)
+{
+	unsigned long flags;
+	struct usb_anchor *anchor;
+
+	if (!urb)
+		return;
+
+	anchor = urb->anchor;
+	if (!anchor)
+		return;
+
+	spin_lock_irqsave(&anchor->lock, flags);
+	if (unlikely(anchor != urb->anchor)) {
+		/* we've lost the race to another thread */
+		spin_unlock_irqrestore(&anchor->lock, flags);
+		return;
+	}
+	urb->anchor = NULL;
+	list_del(&urb->anchor_list);
+	spin_unlock_irqrestore(&anchor->lock, flags);
+	usb_put_urb(urb);
+	if (list_empty(&anchor->urb_list))
+		wake_up(&anchor->wait);
+}
+EXPORT_SYMBOL_GPL(usb_unanchor_urb);
+
 /*-------------------------------------------------------------------*/
 
 /**
@@ -478,6 +536,48 @@
 	spin_unlock_irq(&urb->lock);
 }
 
+/**
+ * usb_kill_anchored_urbs - cancel transfer requests en masse
+ * @anchor: anchor the requests are bound to
+ *
+ * this allows all outstanding URBs to be killed starting
+ * from the back of the queue
+ */
+void usb_kill_anchored_urbs(struct usb_anchor *anchor)
+{
+	struct urb *victim;
+
+	spin_lock_irq(&anchor->lock);
+	while (!list_empty(&anchor->urb_list)) {
+		victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list);
+		/* we must make sure the URB isn't freed before we kill it*/
+		usb_get_urb(victim);
+		spin_unlock_irq(&anchor->lock);
+		/* this will unanchor the URB */
+		usb_kill_urb(victim);
+		usb_put_urb(victim);
+		spin_lock_irq(&anchor->lock);
+	}
+	spin_unlock_irq(&anchor->lock);
+}
+EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+
+/**
+ * usb_wait_anchor_empty_timeout - wait for an anchor to be unused
+ * @anchor: the anchor you want to become unused
+ * @timeout: how long you are willing to wait in milliseconds
+ *
+ * Call this is you want to be sure all an anchor's
+ * URBs have finished
+ */
+int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+				  unsigned int timeout)
+{
+	return wait_event_timeout(anchor->wait, list_empty(&anchor->urb_list),
+				  msecs_to_jiffies(timeout));
+}
+EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
+
 EXPORT_SYMBOL(usb_init_urb);
 EXPORT_SYMBOL(usb_alloc_urb);
 EXPORT_SYMBOL(usb_free_urb);
@@ -485,4 +585,3 @@
 EXPORT_SYMBOL(usb_submit_urb);
 EXPORT_SYMBOL(usb_unlink_urb);
 EXPORT_SYMBOL(usb_kill_urb);
-
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 18ddc5e6..0fee5c6 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -184,10 +184,6 @@
 
 	udev = to_usb_device(dev);
 
-#ifdef	CONFIG_USB_SUSPEND
-	cancel_delayed_work(&udev->autosuspend);
-	flush_workqueue(ksuspend_usb_wq);
-#endif
 	usb_destroy_configuration(udev);
 	usb_put_hcd(bus_to_hcd(udev->bus));
 	kfree(udev->product);
@@ -205,7 +201,11 @@
 
 static int ksuspend_usb_init(void)
 {
-	ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
+	/* This workqueue is supposed to be both freezable and
+	 * singlethreaded.  Its job doesn't justify running on more
+	 * than one CPU.
+	 */
+	ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
 	if (!ksuspend_usb_wq)
 		return -ENOMEM;
 	return 0;
@@ -253,6 +253,7 @@
 	dev->dev.bus = &usb_bus_type;
 	dev->dev.type = &usb_device_type;
 	dev->dev.dma_mask = bus->controller->dma_mask;
+	set_dev_node(&dev->dev, dev_to_node(bus->controller));
 	dev->state = USB_STATE_ATTACHED;
 
 	INIT_LIST_HEAD(&dev->ep0.urb_list);
@@ -578,11 +579,12 @@
  * address (through the pointer provided).
  *
  * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags
- * to avoid behaviors like using "DMA bounce buffers", or tying down I/O
- * mapping hardware for long idle periods.  The implementation varies between
+ * to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU
+ * hardware during URB completion/resubmit.  The implementation varies between
  * platforms, depending on details of how DMA will work to this device.
- * Using these buffers also helps prevent cacheline sharing problems on
- * architectures where CPU caches are not DMA-coherent.
+ * Using these buffers also eliminates cacheline sharing problems on
+ * architectures where CPU caches are not DMA-coherent.  On systems without
+ * bus-snooping caches, these buffers are uncached.
  *
  * When the buffer is no longer used, free it with usb_buffer_free().
  */
@@ -607,7 +609,7 @@
  *
  * This reclaims an I/O buffer, letting it be reused.  The memory must have
  * been allocated using usb_buffer_alloc(), and the parameters must match
- * those provided in that allocation request. 
+ * those provided in that allocation request.
  */
 void usb_buffer_free(
 	struct usb_device *dev,
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index bf2eb0d..ad5fa03 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -52,8 +52,16 @@
 
 #else
 
-#define usb_port_suspend(dev)		0
-#define usb_port_resume(dev)		0
+static inline int usb_port_suspend(struct usb_device *udev)
+{
+	return 0;
+}
+
+static inline int usb_port_resume(struct usb_device *udev)
+{
+	return 0;
+}
+
 static inline void usb_pm_lock(struct usb_device *udev) {}
 static inline void usb_pm_unlock(struct usb_device *udev) {}
 
@@ -100,11 +108,13 @@
 static inline void mark_active(struct usb_interface *f)
 {
 	f->is_active = 1;
+	f->dev.power.power_state.event = PM_EVENT_ON;
 }
 
 static inline void mark_quiesced(struct usb_interface *f)
 {
 	f->is_active = 0;
+	f->dev.power.power_state.event = PM_EVENT_SUSPEND;
 }
 
 static inline int is_active(const struct usb_interface *f)
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index f771a7c..45e01e2 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -42,6 +42,20 @@
 	   For more information, see <http://www.linux-usb.org/gadget> and
 	   the kernel DocBook documentation for this API.
 
+config USB_GADGET_DEBUG
+	boolean "Debugging messages"
+	depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
+	help
+	   Many controller and gadget drivers will print some debugging
+	   messages if you use this option to ask for those messages.
+
+	   Avoid enabling these messages, even if you're actively
+	   debugging such a driver.  Many drivers will emit so many
+	   messages that the driver timings are affected, which will
+	   either create new failure modes or remove the one you're
+	   trying to track down.  Never enable these messages for a
+	   production build.
+
 config USB_GADGET_DEBUG_FILES
 	boolean "Debugging information files"
 	depends on USB_GADGET && PROC_FS
@@ -208,6 +222,27 @@
 
 	   Select this only if your OMAP board has a Mini-AB connector.
 
+config USB_GADGET_S3C2410
+	boolean "S3C2410 USB Device Controller"
+	depends on ARCH_S3C2410
+	help
+	  Samsung's S3C2410 is an ARM-4 processor with an integrated
+	  full speed USB 1.1 device controller.  It has 4 configurable
+	  endpoints, as well as endpoint zero (for control transfers).
+
+	  This driver has been tested on the S3C2410, S3C2412, and
+	  S3C2440 processors.
+
+config USB_S3C2410
+	tristate
+	depends on USB_GADGET_S3C2410
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
+config USB_S3C2410_DEBUG
+	boolean "S3C2410 udc debug messages"
+	depends on USB_GADGET_S3C2410
+
 config USB_GADGET_AT91
 	boolean "AT91 USB Device Port"
 	depends on ARCH_AT91 && !ARCH_AT91SAM9RL
@@ -226,6 +261,24 @@
 	depends on USB_GADGET_AT91
 	default USB_GADGET
 
+config USB_GADGET_M66592
+	boolean "M66592 driver"
+	select USB_GADGET_DUALSPEED
+	help
+	   M66592 is a USB 2.0 peripheral controller.
+
+	   It has seven configurable endpoints, and endpoint zero.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "m66592_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_M66592
+	tristate
+	depends on USB_GADGET_M66592
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
 config USB_GADGET_DUMMY_HCD
 	boolean "Dummy HCD (DEVELOPMENT)"
 	depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 5db1939..8ae76f7 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -1,14 +1,20 @@
 #
 # USB peripheral controller drivers
 #
+ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_PXA2XX)	+= pxa2xx_udc.o
 obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
 obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
 obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o
+obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
 obj-$(CONFIG_USB_AT91)		+= at91_udc.o
 obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
+obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
 
 #
 # USB gadget drivers
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index ba163f3..63d7d65 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -601,25 +601,6 @@
 	kfree(req);
 }
 
-static void *at91_ep_alloc_buffer(
-	struct usb_ep *_ep,
-	unsigned bytes,
-	dma_addr_t *dma,
-	gfp_t gfp_flags)
-{
-	*dma = ~0;
-	return kmalloc(bytes, gfp_flags);
-}
-
-static void at91_ep_free_buffer(
-	struct usb_ep *ep,
-	void *buf,
-	dma_addr_t dma,
-	unsigned bytes)
-{
-	kfree(buf);
-}
-
 static int at91_ep_queue(struct usb_ep *_ep,
 			struct usb_request *_req, gfp_t gfp_flags)
 {
@@ -788,8 +769,6 @@
 	.disable	= at91_ep_disable,
 	.alloc_request	= at91_ep_alloc_request,
 	.free_request	= at91_ep_free_request,
-	.alloc_buffer	= at91_ep_alloc_buffer,
-	.free_buffer	= at91_ep_free_buffer,
 	.queue		= at91_ep_queue,
 	.dequeue	= at91_ep_dequeue,
 	.set_halt	= at91_ep_set_halt,
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index fcb5526..f2fbdc7 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -497,38 +497,6 @@
 	kfree (req);
 }
 
-static void *
-dummy_alloc_buffer (
-	struct usb_ep *_ep,
-	unsigned bytes,
-	dma_addr_t *dma,
-	gfp_t mem_flags
-) {
-	char			*retval;
-	struct dummy_ep		*ep;
-	struct dummy		*dum;
-
-	ep = usb_ep_to_dummy_ep (_ep);
-	dum = ep_to_dummy (ep);
-
-	if (!dum->driver)
-		return NULL;
-	retval = kmalloc (bytes, mem_flags);
-	*dma = (dma_addr_t) retval;
-	return retval;
-}
-
-static void
-dummy_free_buffer (
-	struct usb_ep *_ep,
-	void *buf,
-	dma_addr_t dma,
-	unsigned bytes
-) {
-	if (bytes)
-		kfree (buf);
-}
-
 static void
 fifo_complete (struct usb_ep *ep, struct usb_request *req)
 {
@@ -659,10 +627,6 @@
 	.alloc_request	= dummy_alloc_request,
 	.free_request	= dummy_free_request,
 
-	.alloc_buffer	= dummy_alloc_buffer,
-	.free_buffer	= dummy_free_buffer,
-	/* map, unmap, ... eventually hook the "generic" dma calls */
-
 	.queue		= dummy_queue,
 	.dequeue	= dummy_dequeue,
 
@@ -1784,8 +1748,7 @@
 
 	spin_lock_irq (&dum->lock);
 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
-		dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
-		rc = -ENODEV;
+		rc = -ESHUTDOWN;
 	} else {
 		dum->rh_state = DUMMY_RH_RUNNING;
 		set_link_state (dum);
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index f28af06..6042364 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -132,7 +132,7 @@
 	 * where it's an output parameter representing the full speed limit.
 	 * the usb spec fixes high speed bulk maxpacket at 512 bytes.
 	 */
-	max = 0x7ff & le16_to_cpup (&desc->wMaxPacketSize);
+	max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
 	switch (type) {
 	case USB_ENDPOINT_XFER_INT:
 		/* INT:  limit 64 bytes full speed, 1024 high speed */
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 325bf7c..dbaf867 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -277,7 +277,7 @@
 #define DEV_CONFIG_CDC
 #endif
 
-#ifdef CONFIG_USB_GADGET_HUSB2DEV
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
 #define DEV_CONFIG_CDC
 #endif
 
@@ -292,7 +292,7 @@
 #define	DEV_CONFIG_SUBSET
 #endif
 
-#ifdef CONFIG_USB_GADGET_SH
+#ifdef CONFIG_USB_GADGET_SUPERH
 #define	DEV_CONFIG_SUBSET
 #endif
 
@@ -301,6 +301,10 @@
 #define	DEV_CONFIG_SUBSET
 #endif
 
+#ifdef CONFIG_USB_GADGET_M66592
+#define DEV_CONFIG_CDC
+#endif
+
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index c6b6479..be7a1bd 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -686,7 +686,6 @@
 	int			thread_wakeup_needed;
 	struct completion	thread_notifier;
 	struct task_struct	*thread_task;
-	sigset_t		thread_signal_mask;
 
 	int			cmnd_size;
 	u8			cmnd[MAX_COMMAND_SIZE];
@@ -3277,8 +3276,7 @@
 	/* Clear the existing signals.  Anything but SIGUSR1 is converted
 	 * into a high-priority EXIT exception. */
 	for (;;) {
-		sig = dequeue_signal_lock(current, &fsg->thread_signal_mask,
-				&info);
+		sig = dequeue_signal_lock(current, &current->blocked, &info);
 		if (!sig)
 			break;
 		if (sig != SIGUSR1) {
@@ -3431,10 +3429,13 @@
 
 	/* Allow the thread to be killed by a signal, but set the signal mask
 	 * to block everything but INT, TERM, KILL, and USR1. */
-	siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) |
-			sigmask(SIGTERM) | sigmask(SIGKILL) |
-			sigmask(SIGUSR1));
-	sigprocmask(SIG_SETMASK, &fsg->thread_signal_mask, NULL);
+	allow_signal(SIGINT);
+	allow_signal(SIGTERM);
+	allow_signal(SIGKILL);
+	allow_signal(SIGUSR1);
+
+	/* Allow the thread to be frozen */
+	set_freezable();
 
 	/* Arrange for userspace references to be interpreted as kernel
 	 * pointers.  That way we can pass a kernel pointer to a routine
@@ -3735,19 +3736,12 @@
 	}
 
 	/* Free the data buffers */
-	for (i = 0; i < NUM_BUFFERS; ++i) {
-		struct fsg_buffhd	*bh = &fsg->buffhds[i];
-
-		if (bh->buf)
-			usb_ep_free_buffer(fsg->bulk_in, bh->buf, bh->dma,
-					mod_data.buflen);
-	}
+	for (i = 0; i < NUM_BUFFERS; ++i)
+		kfree(fsg->buffhds[i].buf);
 
 	/* Free the request and buffer for endpoint 0 */
 	if (req) {
-		if (req->buf)
-			usb_ep_free_buffer(fsg->ep0, req->buf,
-					req->dma, EP0_BUFSIZE);
+		kfree(req->buf);
 		usb_ep_free_request(fsg->ep0, req);
 	}
 
@@ -3965,8 +3959,7 @@
 #endif
 
 	if (gadget->is_otg) {
-		otg_desc.bmAttributes |= USB_OTG_HNP,
-		config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		otg_desc.bmAttributes |= USB_OTG_HNP;
 	}
 
 	rc = -ENOMEM;
@@ -3975,8 +3968,7 @@
 	fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
 	if (!req)
 		goto out;
-	req->buf = usb_ep_alloc_buffer(fsg->ep0, EP0_BUFSIZE,
-			&req->dma, GFP_KERNEL);
+	req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
 	if (!req->buf)
 		goto out;
 	req->complete = ep0_complete;
@@ -3988,8 +3980,7 @@
 		/* Allocate for the bulk-in endpoint.  We assume that
 		 * the buffer will also work with the bulk-out (and
 		 * interrupt-in) endpoint. */
-		bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen,
-				&bh->dma, GFP_KERNEL);
+		bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
 		if (!bh->buf)
 			goto out;
 		bh->next = bh + 1;
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 157054e..10b2b33 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -228,13 +228,15 @@
 
 	/* Config PHY interface */
 	portctrl = fsl_readl(&dr_regs->portsc1);
-	portctrl &= ~PORTSCX_PHY_TYPE_SEL;
+	portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
 	switch (udc->phy_mode) {
 	case FSL_USB2_PHY_ULPI:
 		portctrl |= PORTSCX_PTS_ULPI;
 		break;
-	case FSL_USB2_PHY_UTMI:
 	case FSL_USB2_PHY_UTMI_WIDE:
+		portctrl |= PORTSCX_PTW_16BIT;
+		/* fall through */
+	case FSL_USB2_PHY_UTMI:
 		portctrl |= PORTSCX_PTS_UTMI;
 		break;
 	case FSL_USB2_PHY_SERIAL:
@@ -599,39 +601,6 @@
 		kfree(req);
 }
 
-/*------------------------------------------------------------------
- * Allocate an I/O buffer
-*---------------------------------------------------------------------*/
-static void *fsl_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-		dma_addr_t *dma, gfp_t gfp_flags)
-{
-	struct fsl_ep *ep;
-
-	if (!_ep)
-		return NULL;
-
-	ep = container_of(_ep, struct fsl_ep, ep);
-
-	return dma_alloc_coherent(ep->udc->gadget.dev.parent,
-			bytes, dma, gfp_flags);
-}
-
-/*------------------------------------------------------------------
- * frees an i/o buffer
-*---------------------------------------------------------------------*/
-static void fsl_free_buffer(struct usb_ep *_ep, void *buf,
-		dma_addr_t dma, unsigned bytes)
-{
-	struct fsl_ep *ep;
-
-	if (!_ep)
-		return NULL;
-
-	ep = container_of(_ep, struct fsl_ep, ep);
-
-	dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma);
-}
-
 /*-------------------------------------------------------------------------*/
 static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
 {
@@ -1045,9 +1014,6 @@
 	.alloc_request = fsl_alloc_request,
 	.free_request = fsl_free_request,
 
-	.alloc_buffer = fsl_alloc_buffer,
-	.free_buffer = fsl_free_buffer,
-
 	.queue = fsl_ep_queue,
 	.dequeue = fsl_ep_dequeue,
 
@@ -2187,27 +2153,19 @@
  * init resource for globle controller
  * Return the udc handle on success or NULL on failure
  ------------------------------------------------------------------*/
-static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
+static int __init struct_udc_setup(struct fsl_udc *udc,
+		struct platform_device *pdev)
 {
-	struct fsl_udc *udc;
 	struct fsl_usb2_platform_data *pdata;
 	size_t size;
 
-	udc = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
-	if (udc == NULL) {
-		ERR("malloc udc failed\n");
-		return NULL;
-	}
-
 	pdata = pdev->dev.platform_data;
 	udc->phy_mode = pdata->phy_mode;
-	/* max_ep_nr is bidirectional ep number, max_ep doubles the number */
-	udc->max_ep = pdata->max_ep_nr * 2;
 
 	udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
 	if (!udc->eps) {
 		ERR("malloc fsl_ep failed\n");
-		goto cleanup;
+		return -1;
 	}
 
 	/* initialized QHs, take care of alignment */
@@ -2223,7 +2181,7 @@
 	if (!udc->ep_qh) {
 		ERR("malloc QHs for udc failed\n");
 		kfree(udc->eps);
-		goto cleanup;
+		return -1;
 	}
 
 	udc->ep_qh_size = size;
@@ -2242,11 +2200,7 @@
 	udc->remote_wakeup = 0;	/* default to 0 on reset */
 	spin_lock_init(&udc->lock);
 
-	return udc;
-
-cleanup:
-	kfree(udc);
-	return NULL;
+	return 0;
 }
 
 /*----------------------------------------------------------------
@@ -2285,35 +2239,37 @@
 }
 
 /* Driver probe function
- * all intialize operations implemented here except enabling usb_intr reg
+ * all intialization operations implemented here except enabling usb_intr reg
+ * board setup should have been done in the platform code
  */
 static int __init fsl_udc_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int ret = -ENODEV;
 	unsigned int i;
+	u32 dccparams;
 
 	if (strcmp(pdev->name, driver_name)) {
 		VDBG("Wrong device\n");
 		return -ENODEV;
 	}
 
-	/* board setup should have been done in the platform code */
-
-	/* Initialize the udc structure including QH member and other member */
-	udc_controller = struct_udc_setup(pdev);
-	if (!udc_controller) {
-		VDBG("udc_controller is NULL \n");
+	udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
+	if (udc_controller == NULL) {
+		ERR("malloc udc failed\n");
 		return -ENOMEM;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
+	if (!res) {
+		kfree(udc_controller);
 		return -ENXIO;
+	}
 
 	if (!request_mem_region(res->start, res->end - res->start + 1,
 				driver_name)) {
 		ERR("request mem region for %s failed \n", pdev->name);
+		kfree(udc_controller);
 		return -EBUSY;
 	}
 
@@ -2326,13 +2282,24 @@
 	usb_sys_regs = (struct usb_sys_interface *)
 			((u32)dr_regs + USB_DR_SYS_OFFSET);
 
+	/* Read Device Controller Capability Parameters register */
+	dccparams = fsl_readl(&dr_regs->dccparams);
+	if (!(dccparams & DCCPARAMS_DC)) {
+		ERR("This SOC doesn't support device role\n");
+		ret = -ENODEV;
+		goto err2;
+	}
+	/* Get max device endpoints */
+	/* DEN is bidirectional ep number, max_ep doubles the number */
+	udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2;
+
 	udc_controller->irq = platform_get_irq(pdev, 0);
 	if (!udc_controller->irq) {
 		ret = -ENODEV;
 		goto err2;
 	}
 
-	ret = request_irq(udc_controller->irq, fsl_udc_irq, SA_SHIRQ,
+	ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED,
 			driver_name, udc_controller);
 	if (ret != 0) {
 		ERR("cannot request irq %d err %d \n",
@@ -2340,6 +2307,13 @@
 		goto err2;
 	}
 
+	/* Initialize the udc structure including QH member and other member */
+	if (struct_udc_setup(udc_controller, pdev)) {
+		ERR("Can't initialize udc data structure\n");
+		ret = -ENOMEM;
+		goto err3;
+	}
+
 	/* initialize usb hw reg except for regs for EP,
 	 * leave usbintr reg untouched */
 	dr_controller_setup(udc_controller);
@@ -2401,6 +2375,7 @@
 	iounmap(dr_regs);
 err1:
 	release_mem_region(res->start, res->end - res->start + 1);
+	kfree(udc_controller);
 	return ret;
 }
 
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index c6291e0..832ab82 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -101,6 +101,10 @@
 #define WAIT_FOR_OUT_STATUS     3
 #define DATA_STATE_RECV         4
 
+/* Device Controller Capability Parameter register */
+#define DCCPARAMS_DC				0x00000080
+#define DCCPARAMS_DEN_MASK			0x0000001f
+
 /* Frame Index Register Bit Masks */
 #define	USB_FRINDEX_MASKS			0x3fff
 /* USB CMD  Register Bit Masks */
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index d041b91..53e9139 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -8,6 +8,8 @@
  * (And avoiding all runtime comparisons in typical one-choice configs!)
  *
  * NOTE:  some of these controller drivers may not be available yet.
+ * Some are available on 2.4 kernels; several are available, but not
+ * yet pushed in the 2.6 mainline tree.
  */
 #ifdef CONFIG_USB_GADGET_NET2280
 #define	gadget_is_net2280(g)	!strcmp("net2280", (g)->name)
@@ -33,12 +35,14 @@
 #define	gadget_is_goku(g)	0
 #endif
 
+/* SH3 UDC -- not yet ported 2.4 --> 2.6 */
 #ifdef CONFIG_USB_GADGET_SUPERH
 #define	gadget_is_sh(g)		!strcmp("sh_udc", (g)->name)
 #else
 #define	gadget_is_sh(g)		0
 #endif
 
+/* not yet stable on 2.6 (would help "original Zaurus") */
 #ifdef CONFIG_USB_GADGET_SA1100
 #define	gadget_is_sa1100(g)	!strcmp("sa1100_udc", (g)->name)
 #else
@@ -51,6 +55,7 @@
 #define	gadget_is_lh7a40x(g)	0
 #endif
 
+/* handhelds.org tree (?) */
 #ifdef CONFIG_USB_GADGET_MQ11XX
 #define	gadget_is_mq11xx(g)	!strcmp("mq11xx_udc", (g)->name)
 #else
@@ -63,22 +68,24 @@
 #define	gadget_is_omap(g)	0
 #endif
 
+/* not yet ported 2.4 --> 2.6 */
 #ifdef CONFIG_USB_GADGET_N9604
 #define	gadget_is_n9604(g)	!strcmp("n9604_udc", (g)->name)
 #else
 #define	gadget_is_n9604(g)	0
 #endif
 
+/* various unstable versions available */
 #ifdef CONFIG_USB_GADGET_PXA27X
 #define	gadget_is_pxa27x(g)	!strcmp("pxa27x_udc", (g)->name)
 #else
 #define	gadget_is_pxa27x(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_HUSB2DEV
-#define gadget_is_husb2dev(g)	!strcmp("husb2_udc", (g)->name)
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+#define gadget_is_atmel_usba(g)	!strcmp("atmel_usba_udc", (g)->name)
 #else
-#define gadget_is_husb2dev(g)	0
+#define gadget_is_atmel_usba(g)	0
 #endif
 
 #ifdef CONFIG_USB_GADGET_S3C2410
@@ -93,6 +100,7 @@
 #define gadget_is_at91(g)	0
 #endif
 
+/* status unclear */
 #ifdef CONFIG_USB_GADGET_IMX
 #define gadget_is_imx(g)	!strcmp("imx_udc", (g)->name)
 #else
@@ -106,6 +114,7 @@
 #endif
 
 /* Mentor high speed function controller */
+/* from Montavista kernel (?) */
 #ifdef CONFIG_USB_GADGET_MUSBHSFC
 #define gadget_is_musbhsfc(g)	!strcmp("musbhsfc_udc", (g)->name)
 #else
@@ -119,12 +128,20 @@
 #define gadget_is_musbhdrc(g)	0
 #endif
 
+/* from Montavista kernel (?) */
 #ifdef CONFIG_USB_GADGET_MPC8272
 #define gadget_is_mpc8272(g)	!strcmp("mpc8272_udc", (g)->name)
 #else
 #define gadget_is_mpc8272(g)	0
 #endif
 
+#ifdef CONFIG_USB_GADGET_M66592
+#define	gadget_is_m66592(g)	!strcmp("m66592_udc", (g)->name)
+#else
+#define	gadget_is_m66592(g)	0
+#endif
+
+
 // CONFIG_USB_GADGET_SX2
 // CONFIG_USB_GADGET_AU1X00
 // ...
@@ -181,9 +198,11 @@
 		return 0x16;
 	else if (gadget_is_mpc8272(gadget))
 		return 0x17;
-	else if (gadget_is_husb2dev(gadget))
+	else if (gadget_is_atmel_usba(gadget))
 		return 0x18;
 	else if (gadget_is_fsl_usb2(gadget))
 		return 0x19;
+	else if (gadget_is_m66592(gadget))
+		return 0x20;
 	return -ENOENT;
 }
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index d08a8d0..1c5aa49 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -1248,17 +1248,11 @@
 	tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev);
 
 	/* preallocate control response and buffer */
-	dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+	dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ);
 	if (!dev->req) {
 		err = -ENOMEM;
 		goto fail;
 	}
-	dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ,
-				&dev->req->dma, GFP_KERNEL);
-	if (!dev->req->buf) {
-		err = -ENOMEM;
-		goto fail;
-	}
 
 	dev->req->complete = gmidi_setup_complete;
 
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index ae931af..d6c5f11 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -20,7 +20,6 @@
  *  - DMA works with ep1 (OUT transfers) and ep2 (IN transfers).
  */
 
-#undef DEBUG
 // #define	VERBOSE		/* extra debug messages (success too) */
 // #define	USB_TRACE	/* packet-level success messages */
 
@@ -296,51 +295,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* allocating buffers this way eliminates dma mapping overhead, which
- * on some platforms will mean eliminating a per-io buffer copy.  with
- * some kinds of system caches, further tweaks may still be needed.
- */
-static void *
-goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-			dma_addr_t *dma, gfp_t gfp_flags)
-{
-	void		*retval;
-	struct goku_ep	*ep;
-
-	ep = container_of(_ep, struct goku_ep, ep);
-	if (!_ep)
-		return NULL;
-	*dma = DMA_ADDR_INVALID;
-
-	if (ep->dma) {
-		/* the main problem with this call is that it wastes memory
-		 * on typical 1/N page allocations: it allocates 1-N pages.
-		 */
-#warning Using dma_alloc_coherent even with buffers smaller than a page.
-		retval = dma_alloc_coherent(&ep->dev->pdev->dev,
-				bytes, dma, gfp_flags);
-	} else
-		retval = kmalloc(bytes, gfp_flags);
-	return retval;
-}
-
-static void
-goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
-{
-	/* free memory into the right allocator */
-	if (dma != DMA_ADDR_INVALID) {
-		struct goku_ep	*ep;
-
-		ep = container_of(_ep, struct goku_ep, ep);
-		if (!_ep)
-			return;
-		dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
-	} else
-		kfree (buf);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static void
 done(struct goku_ep *ep, struct goku_request *req, int status)
 {
@@ -485,7 +439,7 @@
 			/* use ep1/ep2 double-buffering for OUT */
 			if (!(size & PACKET_ACTIVE))
 				size = readl(&regs->EPxSizeLB[ep->num]);
-			if (!(size & PACKET_ACTIVE)) 	// "can't happen"
+			if (!(size & PACKET_ACTIVE))	/* "can't happen" */
 				break;
 			size &= DATASIZE;	/* EPxSizeH == 0 */
 
@@ -1026,9 +980,6 @@
 	.alloc_request	= goku_alloc_request,
 	.free_request	= goku_free_request,
 
-	.alloc_buffer	= goku_alloc_buffer,
-	.free_buffer	= goku_free_buffer,
-
 	.queue		= goku_queue,
 	.dequeue	= goku_dequeue,
 
@@ -1140,17 +1091,17 @@
 		is_usb_connected
 			? ((tmp & PW_PULLUP) ? "full speed" : "powered")
 			: "disconnected",
-		({char *tmp;
+		({char *state;
 		switch(dev->ep0state){
-		case EP0_DISCONNECT:	tmp = "ep0_disconnect"; break;
-		case EP0_IDLE:		tmp = "ep0_idle"; break;
-		case EP0_IN:		tmp = "ep0_in"; break;
-		case EP0_OUT:		tmp = "ep0_out"; break;
-		case EP0_STATUS:	tmp = "ep0_status"; break;
-		case EP0_STALL:		tmp = "ep0_stall"; break;
-		case EP0_SUSPEND:	tmp = "ep0_suspend"; break;
-		default:		tmp = "ep0_?"; break;
-		} tmp; })
+		case EP0_DISCONNECT:	state = "ep0_disconnect"; break;
+		case EP0_IDLE:		state = "ep0_idle"; break;
+		case EP0_IN:		state = "ep0_in"; break;
+		case EP0_OUT:		state = "ep0_out"; break;
+		case EP0_STATUS:	state = "ep0_status"; break;
+		case EP0_STALL:		state = "ep0_stall"; break;
+		case EP0_SUSPEND:	state = "ep0_suspend"; break;
+		default:		state = "ep0_?"; break;
+		} state; })
 		);
 	size -= t;
 	next += t;
@@ -1195,7 +1146,6 @@
 	for (i = 0; i < 4; i++) {
 		struct goku_ep		*ep = &dev->ep [i];
 		struct goku_request	*req;
-		int			t;
 
 		if (i && !ep->desc)
 			continue;
@@ -1283,7 +1233,7 @@
 static void udc_reinit (struct goku_udc *dev)
 {
 	static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" };
-	
+
 	unsigned i;
 
 	INIT_LIST_HEAD (&dev->gadget.ep_list);
@@ -1896,9 +1846,9 @@
 
 	/* done */
 	the_controller = dev;
-	device_register(&dev->gadget.dev);
-
-	return 0;
+	retval = device_register(&dev->gadget.dev);
+	if (retval == 0)
+		return 0;
 
 done:
 	if (dev)
@@ -1910,8 +1860,8 @@
 /*-------------------------------------------------------------------------*/
 
 static struct pci_device_id pci_ids [] = { {
-	.class = 	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask = 	~0,
+	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =	~0,
 	.vendor =	0x102f,		/* Toshiba */
 	.device =	0x0107,		/* this UDC */
 	.subvendor =	PCI_ANY_ID,
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index ea8c8e5..bc4eb1e 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -41,8 +41,10 @@
 #define INT_SYSERROR		0x40000
 #define INT_PWRDETECT		0x80000
 
-#define	INT_DEVWIDE		(INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
-#define	INT_EP0 		(INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
+#define	INT_DEVWIDE \
+	(INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
+#define	INT_EP0 \
+	(INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
 
 	u32	dma_master;
 #define MST_EOPB_DIS		0x0800
@@ -231,7 +233,7 @@
 enum ep0state {
 	EP0_DISCONNECT,		/* no host */
 	EP0_IDLE,		/* between STATUS ack and SETUP report */
-	EP0_IN, EP0_OUT, 	/* data stage */
+	EP0_IN, EP0_OUT,	/* data stage */
 	EP0_STATUS,		/* status stage */
 	EP0_STALL,		/* data or status stages */
 	EP0_SUSPEND,		/* usb suspend */
@@ -242,7 +244,7 @@
 	struct usb_gadget		gadget;
 	spinlock_t			lock;
 	struct goku_ep			ep[4];
-	struct usb_gadget_driver 	*driver;
+	struct usb_gadget_driver	*driver;
 
 	enum ep0state			ep0state;
 	unsigned			got_irq:1,
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 188c74a..e60745ff 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -37,7 +37,7 @@
 #include <linux/device.h>
 #include <linux/moduleparam.h>
 
-#include <linux/usb_gadgetfs.h>
+#include <linux/usb/gadgetfs.h>
 #include <linux/usb_gadget.h>
 
 
@@ -923,7 +923,7 @@
 	struct dev_data		*dev = ep->driver_data;
 
 	if (req->buf != dev->rbuf) {
-		usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
+		kfree(req->buf);
 		req->buf = dev->rbuf;
 		req->dma = DMA_ADDR_INVALID;
 	}
@@ -963,7 +963,7 @@
 		return -EBUSY;
 	}
 	if (len > sizeof (dev->rbuf))
-		req->buf = usb_ep_alloc_buffer (ep, len, &req->dma, GFP_ATOMIC);
+		req->buf = kmalloc(len, GFP_ATOMIC);
 	if (req->buf == 0) {
 		req->buf = dev->rbuf;
 		return -ENOMEM;
@@ -1369,12 +1369,12 @@
 		hs = !hs;
 	if (hs) {
 		dev->req->buf = dev->hs_config;
-		len = le16_to_cpup (&dev->hs_config->wTotalLength);
+		len = le16_to_cpu(dev->hs_config->wTotalLength);
 	} else
 #endif
 	{
 		dev->req->buf = dev->config;
-		len = le16_to_cpup (&dev->config->wTotalLength);
+		len = le16_to_cpu(dev->config->wTotalLength);
 	}
 	((u8 *)dev->req->buf) [1] = type;
 	return len;
@@ -1505,7 +1505,7 @@
 		}
 		break;
 
-#ifndef	CONFIG_USB_GADGETFS_PXA2XX
+#ifndef	CONFIG_USB_GADGET_PXA2XX
 	/* PXA automagically handles this request too */
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != 0x80)
@@ -1885,7 +1885,7 @@
 
 	/* full or low speed config */
 	dev->config = (void *) kbuf;
-	total = le16_to_cpup (&dev->config->wTotalLength);
+	total = le16_to_cpu(dev->config->wTotalLength);
 	if (!is_valid_config (dev->config) || total >= length)
 		goto fail;
 	kbuf += total;
@@ -1894,7 +1894,7 @@
 	/* optional high speed config */
 	if (kbuf [1] == USB_DT_CONFIG) {
 		dev->hs_config = (void *) kbuf;
-		total = le16_to_cpup (&dev->hs_config->wTotalLength);
+		total = le16_to_cpu(dev->hs_config->wTotalLength);
 		if (!is_valid_config (dev->hs_config) || total >= length)
 			goto fail;
 		kbuf += total;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index a0a73c0..e78c2dd 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -75,10 +75,6 @@
 static int lh7a40x_ep_disable(struct usb_ep *ep);
 static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t);
 static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
-static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
-				  gfp_t);
-static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
-				unsigned);
 static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
 static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
 static int lh7a40x_set_halt(struct usb_ep *ep, int);
@@ -104,9 +100,6 @@
 	.alloc_request = lh7a40x_alloc_request,
 	.free_request = lh7a40x_free_request,
 
-	.alloc_buffer = lh7a40x_alloc_buffer,
-	.free_buffer = lh7a40x_free_buffer,
-
 	.queue = lh7a40x_queue,
 	.dequeue = lh7a40x_dequeue,
 
@@ -1134,26 +1127,6 @@
 	kfree(req);
 }
 
-static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
-				  dma_addr_t * dma, gfp_t gfp_flags)
-{
-	char *retval;
-
-	DEBUG("%s (%p, %d, %d)\n", __FUNCTION__, ep, bytes, gfp_flags);
-
-	retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA | __GFP_HIGHMEM));
-	if (retval)
-		*dma = virt_to_bus(retval);
-	return retval;
-}
-
-static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma,
-				unsigned bytes)
-{
-	DEBUG("%s, %p\n", __FUNCTION__, ep);
-	kfree(buf);
-}
-
 /** Queue one request
  *  Kickstart transfer if needed
  *  NOTE: Sets INDEX register
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
new file mode 100644
index 0000000..0174a32
--- /dev/null
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -0,0 +1,1634 @@
+/*
+ * M66592 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb_gadget.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "m66592-udc.h"
+
+MODULE_DESCRIPTION("M66592 USB gadget driiver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+
+#define DRIVER_VERSION	"29 May 2007"
+
+/* module parameters */
+static unsigned short clock = M66592_XTAL24;
+module_param(clock, ushort, 0644);
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=16384)");
+static unsigned short vif = M66592_LDRV;
+module_param(vif, ushort, 0644);
+MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
+static unsigned short endian = 0;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+static unsigned short irq_sense = M66592_INTL;
+module_param(irq_sense, ushort, 0644);
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0(default=2)");
+
+static const char udc_name[] = "m66592_udc";
+static const char *m66592_ep_name[] = {
+	"ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
+};
+
+static void disable_controller(struct m66592 *m66592);
+static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
+static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
+static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
+			gfp_t gfp_flags);
+
+static void transfer_complete(struct m66592_ep *ep,
+			      struct m66592_request *req,
+			      int status);
+/*-------------------------------------------------------------------------*/
+static inline u16 get_usb_speed(struct m66592 *m66592)
+{
+	return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
+}
+
+static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
+			    unsigned long reg)
+{
+	u16 tmp;
+
+	tmp = m66592_read(m66592, M66592_INTENB0);
+	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
+		    M66592_INTENB0);
+	m66592_bset(m66592, (1 << pipenum), reg);
+	m66592_write(m66592, tmp, M66592_INTENB0);
+}
+
+static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
+			     unsigned long reg)
+{
+	u16 tmp;
+
+	tmp = m66592_read(m66592, M66592_INTENB0);
+	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
+		    M66592_INTENB0);
+	m66592_bclr(m66592, (1 << pipenum), reg);
+	m66592_write(m66592, tmp, M66592_INTENB0);
+}
+
+static void m66592_usb_connect(struct m66592 *m66592)
+{
+	m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
+	m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
+		    M66592_INTENB0);
+	m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
+
+	m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
+}
+
+static void m66592_usb_disconnect(struct m66592 *m66592)
+{
+	m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
+	m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
+		    M66592_INTENB0);
+	m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
+	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+
+	m66592->gadget.speed = USB_SPEED_UNKNOWN;
+	spin_unlock(&m66592->lock);
+	m66592->driver->disconnect(&m66592->gadget);
+	spin_lock(&m66592->lock);
+
+	disable_controller(m66592);
+	INIT_LIST_HEAD(&m66592->ep[0].queue);
+}
+
+static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
+{
+	u16 pid = 0;
+	unsigned long offset;
+
+	if (pipenum == 0)
+		pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
+	else if (pipenum < M66592_MAX_NUM_PIPE) {
+		offset = get_pipectr_addr(pipenum);
+		pid = m66592_read(m66592, offset) & M66592_PID;
+	} else
+		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+
+	return pid;
+}
+
+static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
+				       u16 pid)
+{
+	unsigned long offset;
+
+	if (pipenum == 0)
+		m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
+	else if (pipenum < M66592_MAX_NUM_PIPE) {
+		offset = get_pipectr_addr(pipenum);
+		m66592_mdfy(m66592, pid, M66592_PID, offset);
+	} else
+		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+}
+
+static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
+{
+	control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
+}
+
+static inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
+{
+	control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
+}
+
+static inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
+{
+	control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
+}
+
+static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
+{
+	u16 ret = 0;
+	unsigned long offset;
+
+	if (pipenum == 0)
+		ret = m66592_read(m66592, M66592_DCPCTR);
+	else if (pipenum < M66592_MAX_NUM_PIPE) {
+		offset = get_pipectr_addr(pipenum);
+		ret = m66592_read(m66592, offset);
+	} else
+		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+
+	return ret;
+}
+
+static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
+{
+	unsigned long offset;
+
+	pipe_stop(m66592, pipenum);
+
+	if (pipenum == 0)
+		m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
+	else if (pipenum < M66592_MAX_NUM_PIPE) {
+		offset = get_pipectr_addr(pipenum);
+		m66592_bset(m66592, M66592_SQCLR, offset);
+	} else
+		printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
+}
+
+static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
+{
+	u16 tmp;
+	int size;
+
+	if (pipenum == 0) {
+		tmp = m66592_read(m66592, M66592_DCPCFG);
+		if ((tmp & M66592_CNTMD) != 0)
+			size = 256;
+		else {
+			tmp = m66592_read(m66592, M66592_DCPMAXP);
+			size = tmp & M66592_MAXP;
+		}
+	} else {
+		m66592_write(m66592, pipenum, M66592_PIPESEL);
+		tmp = m66592_read(m66592, M66592_PIPECFG);
+		if ((tmp & M66592_CNTMD) != 0) {
+			tmp = m66592_read(m66592, M66592_PIPEBUF);
+			size = ((tmp >> 10) + 1) * 64;
+		} else {
+			tmp = m66592_read(m66592, M66592_PIPEMAXP);
+			size = tmp & M66592_MXPS;
+		}
+	}
+
+	return size;
+}
+
+static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
+{
+	struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
+
+	if (ep->use_dma)
+		return;
+
+	m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
+
+	ndelay(450);
+
+	m66592_bset(m66592, M66592_MBW, ep->fifosel);
+}
+
+static int pipe_buffer_setting(struct m66592 *m66592,
+			       struct m66592_pipe_info *info)
+{
+	u16 bufnum = 0, buf_bsize = 0;
+	u16 pipecfg = 0;
+
+	if (info->pipe == 0)
+		return -EINVAL;
+
+	m66592_write(m66592, info->pipe, M66592_PIPESEL);
+
+	if (info->dir_in)
+		pipecfg |= M66592_DIR;
+	pipecfg |= info->type;
+	pipecfg |= info->epnum;
+	switch (info->type) {
+	case M66592_INT:
+		bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
+		buf_bsize = 0;
+		break;
+	case M66592_BULK:
+		bufnum = m66592->bi_bufnum +
+			 (info->pipe - M66592_BASE_PIPENUM_BULK) * 16;
+		m66592->bi_bufnum += 16;
+		buf_bsize = 7;
+		pipecfg |= M66592_DBLB;
+		if (!info->dir_in)
+			pipecfg |= M66592_SHTNAK;
+		break;
+	case M66592_ISO:
+		bufnum = m66592->bi_bufnum +
+			 (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
+		m66592->bi_bufnum += 16;
+		buf_bsize = 7;
+		break;
+	}
+	if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
+		printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n",
+		       m66592->bi_bufnum);
+		return -ENOMEM;
+	}
+
+	m66592_write(m66592, pipecfg, M66592_PIPECFG);
+	m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
+	m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
+	if (info->interval)
+		info->interval--;
+	m66592_write(m66592, info->interval, M66592_PIPEPERI);
+
+	return 0;
+}
+
+static void pipe_buffer_release(struct m66592 *m66592,
+				struct m66592_pipe_info *info)
+{
+	if (info->pipe == 0)
+		return;
+
+	switch (info->type) {
+	case M66592_BULK:
+		if (is_bulk_pipe(info->pipe))
+			m66592->bi_bufnum -= 16;
+		break;
+	case M66592_ISO:
+		if (is_isoc_pipe(info->pipe))
+			m66592->bi_bufnum -= 16;
+		break;
+	}
+
+	if (is_bulk_pipe(info->pipe)) {
+		m66592->bulk--;
+	} else if (is_interrupt_pipe(info->pipe))
+		m66592->interrupt--;
+	else if (is_isoc_pipe(info->pipe)) {
+		m66592->isochronous--;
+		if (info->type == M66592_BULK)
+			m66592->bulk--;
+	} else
+		printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
+		       info->pipe);
+}
+
+static void pipe_initialize(struct m66592_ep *ep)
+{
+	struct m66592 *m66592 = ep->m66592;
+
+	m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
+
+	m66592_write(m66592, M66592_ACLRM, ep->pipectr);
+	m66592_write(m66592, 0, ep->pipectr);
+	m66592_write(m66592, M66592_SQCLR, ep->pipectr);
+	if (ep->use_dma) {
+		m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
+
+		ndelay(450);
+
+		m66592_bset(m66592, M66592_MBW, ep->fifosel);
+	}
+}
+
+static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
+			      const struct usb_endpoint_descriptor *desc,
+			      u16 pipenum, int dma)
+{
+	if ((pipenum != 0) && dma) {
+		if (m66592->num_dma == 0) {
+			m66592->num_dma++;
+			ep->use_dma = 1;
+			ep->fifoaddr = M66592_D0FIFO;
+			ep->fifosel = M66592_D0FIFOSEL;
+			ep->fifoctr = M66592_D0FIFOCTR;
+			ep->fifotrn = M66592_D0FIFOTRN;
+		} else if (m66592->num_dma == 1) {
+			m66592->num_dma++;
+			ep->use_dma = 1;
+			ep->fifoaddr = M66592_D1FIFO;
+			ep->fifosel = M66592_D1FIFOSEL;
+			ep->fifoctr = M66592_D1FIFOCTR;
+			ep->fifotrn = M66592_D1FIFOTRN;
+		} else {
+			ep->use_dma = 0;
+			ep->fifoaddr = M66592_CFIFO;
+			ep->fifosel = M66592_CFIFOSEL;
+			ep->fifoctr = M66592_CFIFOCTR;
+			ep->fifotrn = 0;
+		}
+	} else {
+		ep->use_dma = 0;
+		ep->fifoaddr = M66592_CFIFO;
+		ep->fifosel = M66592_CFIFOSEL;
+		ep->fifoctr = M66592_CFIFOCTR;
+		ep->fifotrn = 0;
+	}
+
+	ep->pipectr = get_pipectr_addr(pipenum);
+	ep->pipenum = pipenum;
+	ep->ep.maxpacket = desc->wMaxPacketSize;
+	m66592->pipenum2ep[pipenum] = ep;
+	m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
+	INIT_LIST_HEAD(&ep->queue);
+}
+
+static void m66592_ep_release(struct m66592_ep *ep)
+{
+	struct m66592 *m66592 = ep->m66592;
+	u16 pipenum = ep->pipenum;
+
+	if (pipenum == 0)
+		return;
+
+	if (ep->use_dma)
+		m66592->num_dma--;
+	ep->pipenum = 0;
+	ep->busy = 0;
+	ep->use_dma = 0;
+}
+
+static int alloc_pipe_config(struct m66592_ep *ep,
+			     const struct usb_endpoint_descriptor *desc)
+{
+	struct m66592 *m66592 = ep->m66592;
+	struct m66592_pipe_info info;
+	int dma = 0;
+	int *counter;
+	int ret;
+
+	ep->desc = desc;
+
+	BUG_ON(ep->pipenum);
+
+	switch(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_BULK:
+		if (m66592->bulk >= M66592_MAX_NUM_BULK) {
+			if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
+				printk(KERN_ERR "bulk pipe is insufficient\n");
+				return -ENODEV;
+			} else {
+				info.pipe = M66592_BASE_PIPENUM_ISOC +
+					    m66592->isochronous;
+				counter = &m66592->isochronous;
+			}
+		} else {
+			info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
+			counter = &m66592->bulk;
+		}
+		info.type = M66592_BULK;
+		dma = 1;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		if (m66592->interrupt >= M66592_MAX_NUM_INT) {
+			printk(KERN_ERR "interrupt pipe is insufficient\n");
+			return -ENODEV;
+		}
+		info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
+		info.type = M66592_INT;
+		counter = &m66592->interrupt;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
+			printk(KERN_ERR "isochronous pipe is insufficient\n");
+			return -ENODEV;
+		}
+		info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
+		info.type = M66592_ISO;
+		counter = &m66592->isochronous;
+		break;
+	default:
+		printk(KERN_ERR "unexpect xfer type\n");
+		return -EINVAL;
+	}
+	ep->type = info.type;
+
+	info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	info.maxpacket = desc->wMaxPacketSize;
+	info.interval = desc->bInterval;
+	if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+		info.dir_in = 1;
+	else
+		info.dir_in = 0;
+
+	ret = pipe_buffer_setting(m66592, &info);
+	if (ret < 0) {
+		printk(KERN_ERR "pipe_buffer_setting fail\n");
+		return ret;
+	}
+
+	(*counter)++;
+	if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
+		m66592->bulk++;
+
+	m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
+	pipe_initialize(ep);
+
+	return 0;
+}
+
+static int free_pipe_config(struct m66592_ep *ep)
+{
+	struct m66592 *m66592 = ep->m66592;
+	struct m66592_pipe_info info;
+
+	info.pipe = ep->pipenum;
+	info.type = ep->type;
+	pipe_buffer_release(m66592, &info);
+	m66592_ep_release(ep);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
+{
+	enable_irq_ready(m66592, pipenum);
+	enable_irq_nrdy(m66592, pipenum);
+}
+
+static void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
+{
+	disable_irq_ready(m66592, pipenum);
+	disable_irq_nrdy(m66592, pipenum);
+}
+
+/* if complete is true, gadget driver complete function is not call */
+static void control_end(struct m66592 *m66592, unsigned ccpl)
+{
+	m66592->ep[0].internal_ccpl = ccpl;
+	pipe_start(m66592, 0);
+	m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
+}
+
+static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+	struct m66592 *m66592 = ep->m66592;
+
+	pipe_change(m66592, ep->pipenum);
+	m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
+		    (M66592_ISEL | M66592_CURPIPE),
+		    M66592_CFIFOSEL);
+	m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+	if (req->req.length == 0) {
+		m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+		pipe_start(m66592, 0);
+		transfer_complete(ep, req, 0);
+	} else {
+		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
+		irq_ep0_write(ep, req);
+	}
+}
+
+static void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+	struct m66592 *m66592 = ep->m66592;
+	u16 tmp;
+
+	pipe_change(m66592, ep->pipenum);
+	disable_irq_empty(m66592, ep->pipenum);
+	pipe_start(m66592, ep->pipenum);
+
+	tmp = m66592_read(m66592, ep->fifoctr);
+	if (unlikely((tmp & M66592_FRDY) == 0))
+		pipe_irq_enable(m66592, ep->pipenum);
+	else
+		irq_packet_write(ep, req);
+}
+
+static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
+{
+	struct m66592 *m66592 = ep->m66592;
+	u16 pipenum = ep->pipenum;
+
+	if (ep->pipenum == 0) {
+		m66592_mdfy(m66592, M66592_PIPE0,
+			    (M66592_ISEL | M66592_CURPIPE),
+			    M66592_CFIFOSEL);
+		m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+		pipe_start(m66592, pipenum);
+		pipe_irq_enable(m66592, pipenum);
+	} else {
+		if (ep->use_dma) {
+			m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
+			pipe_change(m66592, pipenum);
+			m66592_bset(m66592, M66592_TRENB, ep->fifosel);
+			m66592_write(m66592,
+				     (req->req.length + ep->ep.maxpacket - 1) /
+				     ep->ep.maxpacket, ep->fifotrn);
+		}
+		pipe_start(m66592, pipenum);	/* trigger once */
+		pipe_irq_enable(m66592, pipenum);
+	}
+}
+
+static void start_packet(struct m66592_ep *ep, struct m66592_request *req)
+{
+	if (ep->desc->bEndpointAddress & USB_DIR_IN)
+		start_packet_write(ep, req);
+	else
+		start_packet_read(ep, req);
+}
+
+static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
+{
+	u16 ctsq;
+
+	ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
+
+	switch (ctsq) {
+	case M66592_CS_RDDS:
+		start_ep0_write(ep, req);
+		break;
+	case M66592_CS_WRDS:
+		start_packet_read(ep, req);
+		break;
+
+	case M66592_CS_WRND:
+		control_end(ep->m66592, 0);
+		break;
+	default:
+		printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);
+		break;
+	}
+}
+
+static void init_controller(struct m66592 *m66592)
+{
+	m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
+		    M66592_PINCFG);
+	m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);		/* High spd */
+	m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);
+
+	m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+	m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+	m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+
+	msleep(3);
+
+	m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+
+	msleep(1);
+
+	m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+
+	m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
+	m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
+		     M66592_DMA0CFG);
+}
+
+static void disable_controller(struct m66592 *m66592)
+{
+	m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
+	udelay(1);
+	m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
+	udelay(1);
+	m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
+	udelay(1);
+	m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+}
+
+static void m66592_start_xclock(struct m66592 *m66592)
+{
+	u16 tmp;
+
+	tmp = m66592_read(m66592, M66592_SYSCFG);
+	if (!(tmp & M66592_XCKE))
+		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+}
+
+/*-------------------------------------------------------------------------*/
+static void transfer_complete(struct m66592_ep *ep,
+			      struct m66592_request *req,
+			      int status)
+{
+	int restart = 0;
+
+	if (unlikely(ep->pipenum == 0)) {
+		if (ep->internal_ccpl) {
+			ep->internal_ccpl = 0;
+			return;
+		}
+	}
+
+	list_del_init(&req->queue);
+	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
+		req->req.status = -ESHUTDOWN;
+	else
+		req->req.status = status;
+
+	if (!list_empty(&ep->queue))
+		restart = 1;
+
+	if (likely(req->req.complete))
+		req->req.complete(&ep->ep, &req->req);
+
+	if (restart) {
+		req = list_entry(ep->queue.next, struct m66592_request, queue);
+		if (ep->desc)
+			start_packet(ep, req);
+	}
+}
+
+static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+	int i;
+	volatile u16 tmp;
+	unsigned bufsize;
+	size_t size;
+	void *buf;
+	u16 pipenum = ep->pipenum;
+	struct m66592 *m66592 = ep->m66592;
+
+	pipe_change(m66592, pipenum);
+	m66592_bset(m66592, M66592_ISEL, ep->fifosel);
+
+	i = 0;
+	do {
+		tmp = m66592_read(m66592, ep->fifoctr);
+		if (i++ > 100000) {
+			printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus"
+				"conflict. please power off this controller.");
+			return;
+		}
+		ndelay(1);
+	} while ((tmp & M66592_FRDY) == 0);
+
+	/* prepare parameters */
+	bufsize = get_buffer_size(m66592, pipenum);
+	buf = req->req.buf + req->req.actual;
+	size = min(bufsize, req->req.length - req->req.actual);
+
+	/* write fifo */
+	if (req->req.buf) {
+		if (size > 0)
+			m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
+		if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
+			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+	}
+
+	/* update parameters */
+	req->req.actual += size;
+
+	/* check transfer finish */
+	if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+	    (size % ep->ep.maxpacket) || (size == 0)) {
+		disable_irq_ready(m66592, pipenum);
+		disable_irq_empty(m66592, pipenum);
+	} else {
+		disable_irq_ready(m66592, pipenum);
+		enable_irq_empty(m66592, pipenum);
+	}
+	pipe_start(m66592, pipenum);
+}
+
+static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+	u16 tmp;
+	unsigned bufsize;
+	size_t size;
+	void *buf;
+	u16 pipenum = ep->pipenum;
+	struct m66592 *m66592 = ep->m66592;
+
+	pipe_change(m66592, pipenum);
+	tmp = m66592_read(m66592, ep->fifoctr);
+	if (unlikely((tmp & M66592_FRDY) == 0)) {
+		pipe_stop(m66592, pipenum);
+		pipe_irq_disable(m66592, pipenum);
+		printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum);
+		return;
+	}
+
+	/* prepare parameters */
+	bufsize = get_buffer_size(m66592, pipenum);
+	buf = req->req.buf + req->req.actual;
+	size = min(bufsize, req->req.length - req->req.actual);
+
+	/* write fifo */
+	if (req->req.buf) {
+		m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
+		if ((size == 0) || ((size % ep->ep.maxpacket) != 0) ||
+		    ((bufsize != ep->ep.maxpacket) && (bufsize > size)))
+			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+	}
+
+	/* update parameters */
+	req->req.actual += size;
+	/* check transfer finish */
+	if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+	    (size % ep->ep.maxpacket) || (size == 0)) {
+		disable_irq_ready(m66592, pipenum);
+		enable_irq_empty(m66592, pipenum);
+	} else {
+		disable_irq_empty(m66592, pipenum);
+		pipe_irq_enable(m66592, pipenum);
+	}
+}
+
+static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
+{
+	u16 tmp;
+	int rcv_len, bufsize, req_len;
+	int size;
+	void *buf;
+	u16 pipenum = ep->pipenum;
+	struct m66592 *m66592 = ep->m66592;
+	int finish = 0;
+
+	pipe_change(m66592, pipenum);
+	tmp = m66592_read(m66592, ep->fifoctr);
+	if (unlikely((tmp & M66592_FRDY) == 0)) {
+		req->req.status = -EPIPE;
+		pipe_stop(m66592, pipenum);
+		pipe_irq_disable(m66592, pipenum);
+		printk(KERN_ERR "read fifo not ready");
+		return;
+	}
+
+	/* prepare parameters */
+	rcv_len = tmp & M66592_DTLN;
+	bufsize = get_buffer_size(m66592, pipenum);
+
+	buf = req->req.buf + req->req.actual;
+	req_len = req->req.length - req->req.actual;
+	if (rcv_len < bufsize)
+		size = min(rcv_len, req_len);
+	else
+		size = min(bufsize, req_len);
+
+	/* update parameters */
+	req->req.actual += size;
+
+	/* check transfer finish */
+	if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+	    (size % ep->ep.maxpacket) || (size == 0)) {
+		pipe_stop(m66592, pipenum);
+		pipe_irq_disable(m66592, pipenum);
+		finish = 1;
+	}
+
+	/* read fifo */
+	if (req->req.buf) {
+		if (size == 0)
+			m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+		else
+			m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
+	}
+
+	if ((ep->pipenum != 0) && finish)
+		transfer_complete(ep, req, 0);
+}
+
+static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
+{
+	u16 check;
+	u16 pipenum;
+	struct m66592_ep *ep;
+	struct m66592_request *req;
+
+	if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
+		m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
+		m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
+			    M66592_CFIFOSEL);
+
+		ep = &m66592->ep[0];
+		req = list_entry(ep->queue.next, struct m66592_request, queue);
+		irq_packet_read(ep, req);
+	} else {
+		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
+			check = 1 << pipenum;
+			if ((status & check) && (enb & check)) {
+				m66592_write(m66592, ~check, M66592_BRDYSTS);
+				ep = m66592->pipenum2ep[pipenum];
+				req = list_entry(ep->queue.next,
+						 struct m66592_request, queue);
+				if (ep->desc->bEndpointAddress & USB_DIR_IN)
+					irq_packet_write(ep, req);
+				else
+					irq_packet_read(ep, req);
+			}
+		}
+	}
+}
+
+static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
+{
+	u16 tmp;
+	u16 check;
+	u16 pipenum;
+	struct m66592_ep *ep;
+	struct m66592_request *req;
+
+	if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
+		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
+
+		ep = &m66592->ep[0];
+		req = list_entry(ep->queue.next, struct m66592_request, queue);
+		irq_ep0_write(ep, req);
+	} else {
+		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
+			check = 1 << pipenum;
+			if ((status & check) && (enb & check)) {
+				m66592_write(m66592, ~check, M66592_BEMPSTS);
+				tmp = control_reg_get(m66592, pipenum);
+				if ((tmp & M66592_INBUFM) == 0) {
+					disable_irq_empty(m66592, pipenum);
+					pipe_irq_disable(m66592, pipenum);
+					pipe_stop(m66592, pipenum);
+					ep = m66592->pipenum2ep[pipenum];
+					req = list_entry(ep->queue.next,
+							 struct m66592_request,
+							 queue);
+					if (!list_empty(&ep->queue))
+						transfer_complete(ep, req, 0);
+				}
+			}
+		}
+	}
+}
+
+static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+	struct m66592_ep *ep;
+	u16 pid;
+	u16 status = 0;
+
+	switch (ctrl->bRequestType & USB_RECIP_MASK) {
+	case USB_RECIP_DEVICE:
+		status = 1;	/* selfpower */
+		break;
+	case USB_RECIP_INTERFACE:
+		status = 0;
+		break;
+	case USB_RECIP_ENDPOINT:
+		ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+		pid = control_reg_get_pid(m66592, ep->pipenum);
+		if (pid == M66592_PID_STALL)
+			status = 1;
+		else
+			status = 0;
+		break;
+	default:
+		pipe_stall(m66592, 0);
+		return;		/* exit */
+	}
+
+	*m66592->ep0_buf = status;
+	m66592->ep0_req->buf = m66592->ep0_buf;
+	m66592->ep0_req->length = 2;
+	/* AV: what happens if we get called again before that gets through? */
+	m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
+}
+
+static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+	switch (ctrl->bRequestType & USB_RECIP_MASK) {
+	case USB_RECIP_DEVICE:
+		control_end(m66592, 1);
+		break;
+	case USB_RECIP_INTERFACE:
+		control_end(m66592, 1);
+		break;
+	case USB_RECIP_ENDPOINT: {
+		struct m66592_ep *ep;
+		struct m66592_request *req;
+
+		ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+		pipe_stop(m66592, ep->pipenum);
+		control_reg_sqclr(m66592, ep->pipenum);
+
+		control_end(m66592, 1);
+
+		req = list_entry(ep->queue.next,
+		struct m66592_request, queue);
+		if (ep->busy) {
+			ep->busy = 0;
+			if (list_empty(&ep->queue))
+				break;
+			start_packet(ep, req);
+		} else if (!list_empty(&ep->queue))
+			pipe_start(m66592, ep->pipenum);
+		}
+		break;
+	default:
+		pipe_stall(m66592, 0);
+		break;
+	}
+}
+
+static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+
+	switch (ctrl->bRequestType & USB_RECIP_MASK) {
+	case USB_RECIP_DEVICE:
+		control_end(m66592, 1);
+		break;
+	case USB_RECIP_INTERFACE:
+		control_end(m66592, 1);
+		break;
+	case USB_RECIP_ENDPOINT: {
+		struct m66592_ep *ep;
+
+		ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+		pipe_stall(m66592, ep->pipenum);
+
+		control_end(m66592, 1);
+		}
+		break;
+	default:
+		pipe_stall(m66592, 0);
+		break;
+	}
+}
+
+/* if return value is true, call class driver's setup() */
+static int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+	u16 *p = (u16 *)ctrl;
+	unsigned long offset = M66592_USBREQ;
+	int i, ret = 0;
+
+	/* read fifo */
+	m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
+
+	for (i = 0; i < 4; i++)
+		p[i] = m66592_read(m66592, offset + i*2);
+
+	/* check request */
+	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+		switch (ctrl->bRequest) {
+		case USB_REQ_GET_STATUS:
+			get_status(m66592, ctrl);
+			break;
+		case USB_REQ_CLEAR_FEATURE:
+			clear_feature(m66592, ctrl);
+			break;
+		case USB_REQ_SET_FEATURE:
+			set_feature(m66592, ctrl);
+			break;
+		default:
+			ret = 1;
+			break;
+		}
+	} else
+		ret = 1;
+	return ret;
+}
+
+static void m66592_update_usb_speed(struct m66592 *m66592)
+{
+	u16 speed = get_usb_speed(m66592);
+
+	switch (speed) {
+	case M66592_HSMODE:
+		m66592->gadget.speed = USB_SPEED_HIGH;
+		break;
+	case M66592_FSMODE:
+		m66592->gadget.speed = USB_SPEED_FULL;
+		break;
+	default:
+		m66592->gadget.speed = USB_SPEED_UNKNOWN;
+		printk(KERN_ERR "USB speed unknown\n");
+	}
+}
+
+static void irq_device_state(struct m66592 *m66592)
+{
+	u16 dvsq;
+
+	dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
+	m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
+
+	if (dvsq == M66592_DS_DFLT) {	/* bus reset */
+		m66592->driver->disconnect(&m66592->gadget);
+		m66592_update_usb_speed(m66592);
+	}
+	if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
+		m66592_update_usb_speed(m66592);
+	if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS) &&
+	    m66592->gadget.speed == USB_SPEED_UNKNOWN)
+		m66592_update_usb_speed(m66592);
+
+	m66592->old_dvsq = dvsq;
+}
+
+static void irq_control_stage(struct m66592 *m66592)
+{
+	struct usb_ctrlrequest ctrl;
+	u16 ctsq;
+
+	ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
+	m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
+
+	switch (ctsq) {
+	case M66592_CS_IDST: {
+		struct m66592_ep *ep;
+		struct m66592_request *req;
+		ep = &m66592->ep[0];
+		req = list_entry(ep->queue.next, struct m66592_request, queue);
+		transfer_complete(ep, req, 0);
+		}
+		break;
+
+	case M66592_CS_RDDS:
+	case M66592_CS_WRDS:
+	case M66592_CS_WRND:
+		if (setup_packet(m66592, &ctrl)) {
+			if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
+				pipe_stall(m66592, 0);
+		}
+		break;
+	case M66592_CS_RDSS:
+	case M66592_CS_WRSS:
+		control_end(m66592, 0);
+		break;
+	default:
+		printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+		break;
+	}
+}
+
+static irqreturn_t m66592_irq(int irq, void *_m66592)
+{
+	struct m66592 *m66592 = _m66592;
+	u16 intsts0;
+	u16 intenb0;
+	u16 brdysts, nrdysts, bempsts;
+	u16 brdyenb, nrdyenb, bempenb;
+	u16 savepipe;
+	u16 mask0;
+
+	intsts0 = m66592_read(m66592, M66592_INTSTS0);
+	intenb0 = m66592_read(m66592, M66592_INTENB0);
+
+	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
+
+	mask0 = intsts0 & intenb0;
+	if (mask0) {
+		brdysts = m66592_read(m66592, M66592_BRDYSTS);
+		nrdysts = m66592_read(m66592, M66592_NRDYSTS);
+		bempsts = m66592_read(m66592, M66592_BEMPSTS);
+		brdyenb = m66592_read(m66592, M66592_BRDYENB);
+		nrdyenb = m66592_read(m66592, M66592_NRDYENB);
+		bempenb = m66592_read(m66592, M66592_BEMPENB);
+
+		if (mask0 & M66592_VBINT) {
+			m66592_write(m66592, (u16)~M66592_VBINT,
+				     M66592_INTSTS0);
+			m66592_start_xclock(m66592);
+
+			/* start vbus sampling */
+			m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
+					   & M66592_VBSTS;
+			m66592->scount = M66592_MAX_SAMPLING;
+
+			mod_timer(&m66592->timer,
+				  jiffies + msecs_to_jiffies(50));
+		}
+		if (intsts0 & M66592_DVSQ)
+			irq_device_state(m66592);
+
+		if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE) &&
+		    (brdysts & brdyenb)) {
+			irq_pipe_ready(m66592, brdysts, brdyenb);
+		}
+		if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE) &&
+		    (bempsts & bempenb)) {
+			irq_pipe_empty(m66592, bempsts, bempenb);
+		}
+
+		if (intsts0 & M66592_CTRT)
+			irq_control_stage(m66592);
+	}
+
+	m66592_write(m66592, savepipe, M66592_CFIFOSEL);
+
+	return IRQ_HANDLED;
+}
+
+static void m66592_timer(unsigned long _m66592)
+{
+	struct m66592 *m66592 = (struct m66592 *)_m66592;
+	unsigned long flags;
+	u16 tmp;
+
+	spin_lock_irqsave(&m66592->lock, flags);
+	tmp = m66592_read(m66592, M66592_SYSCFG);
+	if (!(tmp & M66592_RCKE)) {
+		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+		udelay(10);
+		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+	}
+	if (m66592->scount > 0) {
+		tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
+		if (tmp == m66592->old_vbus) {
+			m66592->scount--;
+			if (m66592->scount == 0) {
+				if (tmp == M66592_VBSTS)
+					m66592_usb_connect(m66592);
+				else
+					m66592_usb_disconnect(m66592);
+			} else {
+				mod_timer(&m66592->timer,
+					  jiffies + msecs_to_jiffies(50));
+			}
+		} else {
+			m66592->scount = M66592_MAX_SAMPLING;
+			m66592->old_vbus = tmp;
+			mod_timer(&m66592->timer,
+				  jiffies + msecs_to_jiffies(50));
+		}
+	}
+	spin_unlock_irqrestore(&m66592->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+static int m66592_enable(struct usb_ep *_ep,
+			 const struct usb_endpoint_descriptor *desc)
+{
+	struct m66592_ep *ep;
+
+	ep = container_of(_ep, struct m66592_ep, ep);
+	return alloc_pipe_config(ep, desc);
+}
+
+static int m66592_disable(struct usb_ep *_ep)
+{
+	struct m66592_ep *ep;
+	struct m66592_request *req;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct m66592_ep, ep);
+	BUG_ON(!ep);
+
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct m66592_request, queue);
+		spin_lock_irqsave(&ep->m66592->lock, flags);
+		transfer_complete(ep, req, -ECONNRESET);
+		spin_unlock_irqrestore(&ep->m66592->lock, flags);
+	}
+
+	pipe_irq_disable(ep->m66592, ep->pipenum);
+	return free_pipe_config(ep);
+}
+
+static struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
+						gfp_t gfp_flags)
+{
+	struct m66592_request *req;
+
+	req = kzalloc(sizeof(struct m66592_request), gfp_flags);
+	if (!req)
+		return NULL;
+
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+static void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct m66592_request *req;
+
+	req = container_of(_req, struct m66592_request, req);
+	kfree(req);
+}
+
+static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
+			gfp_t gfp_flags)
+{
+	struct m66592_ep *ep;
+	struct m66592_request *req;
+	unsigned long flags;
+	int request = 0;
+
+	ep = container_of(_ep, struct m66592_ep, ep);
+	req = container_of(_req, struct m66592_request, req);
+
+	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	spin_lock_irqsave(&ep->m66592->lock, flags);
+
+	if (list_empty(&ep->queue))
+		request = 1;
+
+	list_add_tail(&req->queue, &ep->queue);
+	req->req.actual = 0;
+	req->req.status = -EINPROGRESS;
+
+	if (ep->desc == 0)	/* control */
+		start_ep0(ep, req);
+	else {
+		if (request && !ep->busy)
+			start_packet(ep, req);
+	}
+
+	spin_unlock_irqrestore(&ep->m66592->lock, flags);
+
+	return 0;
+}
+
+static int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct m66592_ep *ep;
+	struct m66592_request *req;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct m66592_ep, ep);
+	req = container_of(_req, struct m66592_request, req);
+
+	spin_lock_irqsave(&ep->m66592->lock, flags);
+	if (!list_empty(&ep->queue))
+		transfer_complete(ep, req, -ECONNRESET);
+	spin_unlock_irqrestore(&ep->m66592->lock, flags);
+
+	return 0;
+}
+
+static int m66592_set_halt(struct usb_ep *_ep, int value)
+{
+	struct m66592_ep *ep;
+	struct m66592_request *req;
+	unsigned long flags;
+	int ret = 0;
+
+	ep = container_of(_ep, struct m66592_ep, ep);
+	req = list_entry(ep->queue.next, struct m66592_request, queue);
+
+	spin_lock_irqsave(&ep->m66592->lock, flags);
+	if (!list_empty(&ep->queue)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+	if (value) {
+		ep->busy = 1;
+		pipe_stall(ep->m66592, ep->pipenum);
+	} else {
+		ep->busy = 0;
+		pipe_stop(ep->m66592, ep->pipenum);
+	}
+
+out:
+	spin_unlock_irqrestore(&ep->m66592->lock, flags);
+	return ret;
+}
+
+static int m66592_fifo_status(struct usb_ep *_ep)
+{
+	return -EOPNOTSUPP;
+}
+
+static void m66592_fifo_flush(struct usb_ep *_ep)
+{
+	struct m66592_ep *ep;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct m66592_ep, ep);
+	spin_lock_irqsave(&ep->m66592->lock, flags);
+	if (list_empty(&ep->queue) && !ep->busy) {
+		pipe_stop(ep->m66592, ep->pipenum);
+		m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
+	}
+	spin_unlock_irqrestore(&ep->m66592->lock, flags);
+}
+
+static struct usb_ep_ops m66592_ep_ops = {
+	.enable		= m66592_enable,
+	.disable	= m66592_disable,
+
+	.alloc_request	= m66592_alloc_request,
+	.free_request	= m66592_free_request,
+
+	.queue		= m66592_queue,
+	.dequeue	= m66592_dequeue,
+
+	.set_halt	= m66592_set_halt,
+	.fifo_status	= m66592_fifo_status,
+	.fifo_flush	= m66592_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+static struct m66592 *the_controller;
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	struct m66592 *m66592 = the_controller;
+	int retval;
+
+	if (!driver ||
+	    driver->speed != USB_SPEED_HIGH ||
+	    !driver->bind ||
+	    !driver->unbind ||
+	    !driver->setup)
+		return -EINVAL;
+	if (!m66592)
+		return -ENODEV;
+	if (m66592->driver)
+		return -EBUSY;
+
+	/* hook up the driver */
+	driver->driver.bus = NULL;
+	m66592->driver = driver;
+	m66592->gadget.dev.driver = &driver->driver;
+
+	retval = device_add(&m66592->gadget.dev);
+	if (retval) {
+		printk(KERN_ERR "device_add error (%d)\n", retval);
+		goto error;
+	}
+
+	retval = driver->bind (&m66592->gadget);
+	if (retval) {
+		printk(KERN_ERR "bind to driver error (%d)\n", retval);
+		device_del(&m66592->gadget.dev);
+		goto error;
+	}
+
+	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
+	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
+		m66592_start_xclock(m66592);
+		/* start vbus sampling */
+		m66592->old_vbus = m66592_read(m66592,
+					 M66592_INTSTS0) & M66592_VBSTS;
+		m66592->scount = M66592_MAX_SAMPLING;
+		mod_timer(&m66592->timer,
+			  jiffies + msecs_to_jiffies(50));
+	}
+
+	return 0;
+
+error:
+	m66592->driver = NULL;
+	m66592->gadget.dev.driver = NULL;
+
+	return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct m66592 *m66592 = the_controller;
+	unsigned long flags;
+
+	spin_lock_irqsave(&m66592->lock, flags);
+	if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
+		m66592_usb_disconnect(m66592);
+	spin_unlock_irqrestore(&m66592->lock, flags);
+
+	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
+
+	driver->unbind(&m66592->gadget);
+
+	init_controller(m66592);
+	disable_controller(m66592);
+
+	device_del(&m66592->gadget.dev);
+	m66592->driver = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------*/
+static int m66592_get_frame(struct usb_gadget *_gadget)
+{
+	struct m66592 *m66592 = gadget_to_m66592(_gadget);
+	return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
+}
+
+static struct usb_gadget_ops m66592_gadget_ops = {
+	.get_frame		= m66592_get_frame,
+};
+
+#if defined(CONFIG_PM)
+static int m66592_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	pdev->dev.power.power_state = state;
+	return 0;
+}
+
+static int m66592_resume(struct platform_device *pdev)
+{
+	pdev->dev.power.power_state = PMSG_ON;
+	return 0;
+}
+#else	/* if defined(CONFIG_PM) */
+#define m66592_suspend		NULL
+#define m66592_resume		NULL
+#endif
+
+static int __init_or_module m66592_remove(struct platform_device *pdev)
+{
+	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
+
+	del_timer_sync(&m66592->timer);
+	iounmap(m66592->reg);
+	free_irq(platform_get_irq(pdev, 0), m66592);
+	kfree(m66592);
+	return 0;
+}
+
+#define resource_len(r) (((r)->end - (r)->start) + 1)
+static int __init m66592_probe(struct platform_device *pdev)
+{
+	struct resource *res = NULL;
+	int irq = -1;
+	void __iomem *reg = NULL;
+	struct m66592 *m66592 = NULL;
+	int ret = 0;
+	int i;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   (char *)udc_name);
+	if (!res) {
+		ret = -ENODEV;
+		printk(KERN_ERR "platform_get_resource_byname error.\n");
+		goto clean_up;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = -ENODEV;
+		printk(KERN_ERR "platform_get_irq error.\n");
+		goto clean_up;
+	}
+
+	reg = ioremap(res->start, resource_len(res));
+	if (reg == NULL) {
+		ret = -ENOMEM;
+		printk(KERN_ERR "ioremap error.\n");
+		goto clean_up;
+	}
+
+	/* initialize ucd */
+	m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
+	if (m66592 == NULL) {
+		printk(KERN_ERR "kzalloc error\n");
+		goto clean_up;
+	}
+
+	spin_lock_init(&m66592->lock);
+	dev_set_drvdata(&pdev->dev, m66592);
+
+	m66592->gadget.ops = &m66592_gadget_ops;
+	device_initialize(&m66592->gadget.dev);
+	strcpy(m66592->gadget.dev.bus_id, "gadget");
+	m66592->gadget.is_dualspeed = 1;
+	m66592->gadget.dev.parent = &pdev->dev;
+	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
+	m66592->gadget.dev.release = pdev->dev.release;
+	m66592->gadget.name = udc_name;
+
+	init_timer(&m66592->timer);
+	m66592->timer.function = m66592_timer;
+	m66592->timer.data = (unsigned long)m66592;
+	m66592->reg = reg;
+
+	m66592->bi_bufnum = M66592_BASE_BUFNUM;
+
+	ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
+			  udc_name, m66592);
+	if (ret < 0) {
+		printk(KERN_ERR "request_irq error (%d)\n", ret);
+		goto clean_up;
+	}
+
+	INIT_LIST_HEAD(&m66592->gadget.ep_list);
+	m66592->gadget.ep0 = &m66592->ep[0].ep;
+	INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
+	for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
+		struct m66592_ep *ep = &m66592->ep[i];
+
+		if (i != 0) {
+			INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
+			list_add_tail(&m66592->ep[i].ep.ep_list,
+				      &m66592->gadget.ep_list);
+		}
+		ep->m66592 = m66592;
+		INIT_LIST_HEAD(&ep->queue);
+		ep->ep.name = m66592_ep_name[i];
+		ep->ep.ops = &m66592_ep_ops;
+		ep->ep.maxpacket = 512;
+	}
+	m66592->ep[0].ep.maxpacket = 64;
+	m66592->ep[0].pipenum = 0;
+	m66592->ep[0].fifoaddr = M66592_CFIFO;
+	m66592->ep[0].fifosel = M66592_CFIFOSEL;
+	m66592->ep[0].fifoctr = M66592_CFIFOCTR;
+	m66592->ep[0].fifotrn = 0;
+	m66592->ep[0].pipectr = get_pipectr_addr(0);
+	m66592->pipenum2ep[0] = &m66592->ep[0];
+	m66592->epaddr2ep[0] = &m66592->ep[0];
+
+	the_controller = m66592;
+
+	/* AV: leaks */
+	m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
+	if (m66592->ep0_req == NULL)
+		goto clean_up;
+	/* AV: leaks, and do we really need it separately allocated? */
+	m66592->ep0_buf = kzalloc(2, GFP_KERNEL);
+	if (m66592->ep0_buf == NULL)
+		goto clean_up;
+
+	init_controller(m66592);
+
+	printk("driver %s, %s\n", udc_name, DRIVER_VERSION);
+	return 0;
+
+clean_up:
+	if (m66592) {
+		if (m66592->ep0_req)
+			m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+		kfree(m66592);
+	}
+	if (reg)
+		iounmap(reg);
+
+	return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+static struct platform_driver m66592_driver = {
+	.probe =	m66592_probe,
+	.remove =	m66592_remove,
+	.suspend =	m66592_suspend,
+	.resume =	m66592_resume,
+	.driver		= {
+		.name =	(char *) udc_name,
+	},
+};
+
+static int __init m66592_udc_init(void)
+{
+	return platform_driver_register(&m66592_driver);
+}
+module_init(m66592_udc_init);
+
+static void __exit m66592_udc_cleanup(void)
+{
+	platform_driver_unregister(&m66592_driver);
+}
+module_exit(m66592_udc_cleanup);
+
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
new file mode 100644
index 0000000..26b54f8
--- /dev/null
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -0,0 +1,577 @@
+/*
+ * M66592 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __M66592_UDC_H__
+#define __M66592_UDC_H__
+
+#define M66592_SYSCFG		0x00
+#define	M66592_XTAL		0xC000	/* b15-14: Crystal selection */
+#define	  M66592_XTAL48		 0x8000		  /* 48MHz */
+#define   M66592_XTAL24		 0x4000		  /* 24MHz */
+#define	  M66592_XTAL12		 0x0000		  /* 12MHz */
+#define	M66592_XCKE		0x2000	/* b13: External clock enable */
+#define	M66592_RCKE		0x1000	/* b12: Register clock enable */
+#define	M66592_PLLC		0x0800	/* b11: PLL control */
+#define	M66592_SCKE		0x0400	/* b10: USB clock enable */
+#define	M66592_ATCKM		0x0100	/* b8: Automatic supply functional enable */
+#define	M66592_HSE		0x0080	/* b7: Hi-speed enable */
+#define	M66592_DCFM		0x0040	/* b6: Controller function select  */
+#define	M66592_DMRPD		0x0020	/* b5: D- pull down control */
+#define	M66592_DPRPU		0x0010	/* b4: D+ pull up control */
+#define	M66592_FSRPC		0x0004	/* b2: Full-speed receiver enable */
+#define	M66592_PCUT		0x0002	/* b1: Low power sleep enable */
+#define	M66592_USBE		0x0001	/* b0: USB module operation enable */
+
+#define M66592_SYSSTS		0x02
+#define	M66592_LNST		0x0003	/* b1-0: D+, D- line status */
+#define	  M66592_SE1		 0x0003		  /* SE1 */
+#define	  M66592_KSTS		 0x0002		  /* K State */
+#define	  M66592_JSTS		 0x0001		  /* J State */
+#define	  M66592_SE0		 0x0000		  /* SE0 */
+
+#define M66592_DVSTCTR		0x04
+#define	M66592_WKUP		0x0100	/* b8: Remote wakeup */
+#define	M66592_RWUPE		0x0080	/* b7: Remote wakeup sense */
+#define	M66592_USBRST		0x0040	/* b6: USB reset enable */
+#define	M66592_RESUME		0x0020	/* b5: Resume enable */
+#define	M66592_UACT		0x0010	/* b4: USB bus enable */
+#define	M66592_RHST		0x0003	/* b1-0: Reset handshake status */
+#define	  M66592_HSMODE		 0x0003		  /* Hi-Speed mode */
+#define	  M66592_FSMODE		 0x0002		  /* Full-Speed mode */
+#define	  M66592_HSPROC		 0x0001		  /* HS handshake is processing */
+
+#define M66592_TESTMODE		0x06
+#define	M66592_UTST		0x000F	/* b4-0: Test select */
+#define	  M66592_H_TST_PACKET	 0x000C		  /* HOST TEST Packet */
+#define	  M66592_H_TST_SE0_NAK	 0x000B		  /* HOST TEST SE0 NAK */
+#define	  M66592_H_TST_K	 0x000A		  /* HOST TEST K */
+#define	  M66592_H_TST_J	 0x0009		  /* HOST TEST J */
+#define	  M66592_H_TST_NORMAL	 0x0000		  /* HOST Normal Mode */
+#define	  M66592_P_TST_PACKET	 0x0004		  /* PERI TEST Packet */
+#define	  M66592_P_TST_SE0_NAK	 0x0003		  /* PERI TEST SE0 NAK */
+#define	  M66592_P_TST_K	 0x0002		  /* PERI TEST K */
+#define	  M66592_P_TST_J	 0x0001		  /* PERI TEST J */
+#define	  M66592_P_TST_NORMAL	 0x0000		  /* PERI Normal Mode */
+
+#define M66592_PINCFG		0x0A
+#define	M66592_LDRV		0x8000	/* b15: Drive Current Adjust */
+#define	M66592_BIGEND		0x0100	/* b8: Big endian mode */
+
+#define M66592_DMA0CFG		0x0C
+#define M66592_DMA1CFG		0x0E
+#define	M66592_DREQA		0x4000	/* b14: Dreq active select */
+#define	M66592_BURST		0x2000	/* b13: Burst mode */
+#define	M66592_DACKA		0x0400	/* b10: Dack active select */
+#define	M66592_DFORM		0x0380	/* b9-7: DMA mode select */
+#define	  M66592_CPU_ADR_RD_WR	 0x0000		  /* Address + RD/WR mode (CPU bus) */
+#define	  M66592_CPU_DACK_RD_WR	 0x0100		  /* DACK + RD/WR mode (CPU bus) */
+#define	  M66592_CPU_DACK_ONLY	 0x0180		  /* DACK only mode (CPU bus) */
+#define	  M66592_SPLIT_DACK_ONLY	 0x0200		  /* DACK only mode (SPLIT bus) */
+#define	  M66592_SPLIT_DACK_DSTB	 0x0300		  /* DACK + DSTB0 mode (SPLIT bus) */
+#define	M66592_DENDA		0x0040	/* b6: Dend active select */
+#define	M66592_PKTM		0x0020	/* b5: Packet mode */
+#define	M66592_DENDE		0x0010	/* b4: Dend enable */
+#define	M66592_OBUS		0x0004	/* b2: OUTbus mode */
+
+#define M66592_CFIFO		0x10
+#define M66592_D0FIFO		0x14
+#define M66592_D1FIFO		0x18
+
+#define M66592_CFIFOSEL		0x1E
+#define M66592_D0FIFOSEL	0x24
+#define M66592_D1FIFOSEL	0x2A
+#define	M66592_RCNT		0x8000	/* b15: Read count mode */
+#define	M66592_REW		0x4000	/* b14: Buffer rewind */
+#define	M66592_DCLRM		0x2000	/* b13: DMA buffer clear mode */
+#define	M66592_DREQE		0x1000	/* b12: DREQ output enable */
+#define	M66592_MBW		0x0400	/* b10: Maximum bit width for FIFO access */
+#define	  M66592_MBW_8		 0x0000	  /*  8bit */
+#define	  M66592_MBW_16		 0x0400		  /* 16bit */
+#define	M66592_TRENB		0x0200	/* b9: Transaction counter enable */
+#define	M66592_TRCLR		0x0100	/* b8: Transaction counter clear */
+#define	M66592_DEZPM		0x0080	/* b7: Zero-length packet additional mode */
+#define	M66592_ISEL		0x0020	/* b5: DCP FIFO port direction select */
+#define	M66592_CURPIPE		0x0007	/* b2-0: PIPE select */
+
+#define M66592_CFIFOCTR		0x20
+#define M66592_D0FIFOCTR	0x26
+#define M66592_D1FIFOCTR	0x2c
+#define	M66592_BVAL		0x8000	/* b15: Buffer valid flag */
+#define	M66592_BCLR		0x4000	/* b14: Buffer clear */
+#define	M66592_FRDY		0x2000	/* b13: FIFO ready */
+#define	M66592_DTLN		0x0FFF	/* b11-0: FIFO received data length */
+
+#define M66592_CFIFOSIE		0x22
+#define	M66592_TGL		0x8000	/* b15: Buffer toggle */
+#define	M66592_SCLR		0x4000	/* b14: Buffer clear */
+#define	M66592_SBUSY		0x2000	/* b13: SIE_FIFO busy */
+
+#define M66592_D0FIFOTRN	0x28
+#define M66592_D1FIFOTRN	0x2E
+#define	M66592_TRNCNT		0xFFFF	/* b15-0: Transaction counter */
+
+#define M66592_INTENB0	0x30
+#define	M66592_VBSE	0x8000	/* b15: VBUS interrupt */
+#define	M66592_RSME	0x4000	/* b14: Resume interrupt */
+#define	M66592_SOFE	0x2000	/* b13: Frame update interrupt */
+#define	M66592_DVSE	0x1000	/* b12: Device state transition interrupt */
+#define	M66592_CTRE	0x0800	/* b11: Control transfer stage transition interrupt */
+#define	M66592_BEMPE	0x0400	/* b10: Buffer empty interrupt */
+#define	M66592_NRDYE	0x0200	/* b9: Buffer not ready interrupt */
+#define	M66592_BRDYE	0x0100	/* b8: Buffer ready interrupt */
+#define	M66592_URST	0x0080	/* b7: USB reset detected interrupt */
+#define	M66592_SADR	0x0040	/* b6: Set address executed interrupt */
+#define	M66592_SCFG	0x0020	/* b5: Set configuration executed interrupt */
+#define	M66592_SUSP	0x0010	/* b4: Suspend detected interrupt */
+#define	M66592_WDST	0x0008	/* b3: Control write data stage completed interrupt */
+#define	M66592_RDST	0x0004	/* b2: Control read data stage completed interrupt */
+#define	M66592_CMPL	0x0002	/* b1: Control transfer complete interrupt */
+#define	M66592_SERR	0x0001	/* b0: Sequence error interrupt */
+
+#define M66592_INTENB1	0x32
+#define	M66592_BCHGE	0x4000	/* b14: USB us chenge interrupt */
+#define	M66592_DTCHE	0x1000	/* b12: Detach sense interrupt */
+#define	M66592_SIGNE	0x0020	/* b5: SETUP IGNORE interrupt */
+#define	M66592_SACKE	0x0010	/* b4: SETUP ACK interrupt */
+#define	M66592_BRDYM	0x0004	/* b2: BRDY clear timing */
+#define	M66592_INTL	0x0002	/* b1: Interrupt sense select */
+#define	M66592_PCSE	0x0001	/* b0: PCUT enable by CS assert */
+
+#define M66592_BRDYENB		0x36
+#define M66592_BRDYSTS		0x46
+#define	M66592_BRDY7		0x0080	/* b7: PIPE7 */
+#define	M66592_BRDY6		0x0040	/* b6: PIPE6 */
+#define	M66592_BRDY5		0x0020	/* b5: PIPE5 */
+#define	M66592_BRDY4		0x0010	/* b4: PIPE4 */
+#define	M66592_BRDY3		0x0008	/* b3: PIPE3 */
+#define	M66592_BRDY2		0x0004	/* b2: PIPE2 */
+#define	M66592_BRDY1		0x0002	/* b1: PIPE1 */
+#define	M66592_BRDY0		0x0001	/* b1: PIPE0 */
+
+#define M66592_NRDYENB		0x38
+#define M66592_NRDYSTS		0x48
+#define	M66592_NRDY7		0x0080	/* b7: PIPE7 */
+#define	M66592_NRDY6		0x0040	/* b6: PIPE6 */
+#define	M66592_NRDY5		0x0020	/* b5: PIPE5 */
+#define	M66592_NRDY4		0x0010	/* b4: PIPE4 */
+#define	M66592_NRDY3		0x0008	/* b3: PIPE3 */
+#define	M66592_NRDY2		0x0004	/* b2: PIPE2 */
+#define	M66592_NRDY1		0x0002	/* b1: PIPE1 */
+#define	M66592_NRDY0		0x0001	/* b1: PIPE0 */
+
+#define M66592_BEMPENB		0x3A
+#define M66592_BEMPSTS		0x4A
+#define	M66592_BEMP7		0x0080	/* b7: PIPE7 */
+#define	M66592_BEMP6		0x0040	/* b6: PIPE6 */
+#define	M66592_BEMP5		0x0020	/* b5: PIPE5 */
+#define	M66592_BEMP4		0x0010	/* b4: PIPE4 */
+#define	M66592_BEMP3		0x0008	/* b3: PIPE3 */
+#define	M66592_BEMP2		0x0004	/* b2: PIPE2 */
+#define	M66592_BEMP1		0x0002	/* b1: PIPE1 */
+#define	M66592_BEMP0		0x0001	/* b0: PIPE0 */
+
+#define M66592_SOFCFG		0x3C
+#define	M66592_SOFM		0x000C	/* b3-2: SOF palse mode */
+#define	  M66592_SOF_125US	 0x0008		  /* SOF OUT 125us uFrame Signal */
+#define	  M66592_SOF_1MS	 0x0004		  /* SOF OUT 1ms Frame Signal */
+#define	  M66592_SOF_DISABLE	 0x0000		  /* SOF OUT Disable */
+
+#define M66592_INTSTS0		0x40
+#define	M66592_VBINT		0x8000	/* b15: VBUS interrupt */
+#define	M66592_RESM		0x4000	/* b14: Resume interrupt */
+#define	M66592_SOFR		0x2000	/* b13: SOF frame update interrupt */
+#define	M66592_DVST		0x1000	/* b12: Device state transition interrupt */
+#define	M66592_CTRT		0x0800	/* b11: Control transfer stage transition interrupt */
+#define	M66592_BEMP		0x0400	/* b10: Buffer empty interrupt */
+#define	M66592_NRDY		0x0200	/* b9: Buffer not ready interrupt */
+#define	M66592_BRDY		0x0100	/* b8: Buffer ready interrupt */
+#define	M66592_VBSTS		0x0080	/* b7: VBUS input port */
+#define	M66592_DVSQ		0x0070	/* b6-4: Device state */
+#define	  M66592_DS_SPD_CNFG	 0x0070		  /* Suspend Configured */
+#define	  M66592_DS_SPD_ADDR	 0x0060		  /* Suspend Address */
+#define	  M66592_DS_SPD_DFLT	 0x0050		  /* Suspend Default */
+#define	  M66592_DS_SPD_POWR	 0x0040		  /* Suspend Powered */
+#define	  M66592_DS_SUSP	 0x0040		  /* Suspend */
+#define	  M66592_DS_CNFG	 0x0030		  /* Configured */
+#define	  M66592_DS_ADDS	 0x0020		  /* Address */
+#define	  M66592_DS_DFLT	 0x0010		  /* Default */
+#define	  M66592_DS_POWR	 0x0000		  /* Powered */
+#define	M66592_DVSQS		0x0030	/* b5-4: Device state */
+#define	M66592_VALID		0x0008	/* b3: Setup packet detected flag */
+#define	M66592_CTSQ		0x0007	/* b2-0: Control transfer stage */
+#define	  M66592_CS_SQER	 0x0006		  /* Sequence error */
+#define	  M66592_CS_WRND	 0x0005		  /* Control write nodata status stage */
+#define	  M66592_CS_WRSS	 0x0004		  /* Control write status stage */
+#define	  M66592_CS_WRDS	 0x0003		  /* Control write data stage */
+#define	  M66592_CS_RDSS	 0x0002		  /* Control read status stage */
+#define	  M66592_CS_RDDS	 0x0001		  /* Control read data stage */
+#define	  M66592_CS_IDST	 0x0000		  /* Idle or setup stage */
+
+#define M66592_INTSTS1		0x42
+#define	M66592_BCHG		0x4000	/* b14: USB bus chenge interrupt */
+#define	M66592_DTCH		0x1000	/* b12: Detach sense interrupt */
+#define	M66592_SIGN		0x0020	/* b5: SETUP IGNORE interrupt */
+#define	M66592_SACK		0x0010	/* b4: SETUP ACK interrupt */
+
+#define M66592_FRMNUM		0x4C
+#define	M66592_OVRN		0x8000	/* b15: Overrun error */
+#define	M66592_CRCE		0x4000	/* b14: Received data error */
+#define	M66592_SOFRM		0x0800	/* b11: SOF output mode */
+#define	M66592_FRNM		0x07FF	/* b10-0: Frame number */
+
+#define M66592_UFRMNUM		0x4E
+#define	M66592_UFRNM		0x0007	/* b2-0: Micro frame number */
+
+#define M66592_RECOVER		0x50
+#define	M66592_STSRECOV		0x0700	/* Status recovery */
+#define	  M66592_STSR_HI	 0x0400		  /* FULL(0) or HI(1) Speed */
+#define	  M66592_STSR_DEFAULT	 0x0100		  /* Default state */
+#define	  M66592_STSR_ADDRESS	 0x0200		  /* Address state */
+#define	  M66592_STSR_CONFIG	 0x0300		  /* Configured state */
+#define	M66592_USBADDR		0x007F	/* b6-0: USB address */
+
+#define M66592_USBREQ			0x54
+#define	M66592_bRequest			0xFF00	/* b15-8: bRequest */
+#define	  M66592_GET_STATUS		 0x0000
+#define	  M66592_CLEAR_FEATURE		 0x0100
+#define	  M66592_ReqRESERVED		 0x0200
+#define	  M66592_SET_FEATURE		 0x0300
+#define	  M66592_ReqRESERVED1		 0x0400
+#define	  M66592_SET_ADDRESS		 0x0500
+#define	  M66592_GET_DESCRIPTOR		 0x0600
+#define	  M66592_SET_DESCRIPTOR		 0x0700
+#define	  M66592_GET_CONFIGURATION	 0x0800
+#define	  M66592_SET_CONFIGURATION	 0x0900
+#define	  M66592_GET_INTERFACE		 0x0A00
+#define	  M66592_SET_INTERFACE		 0x0B00
+#define	  M66592_SYNCH_FRAME		 0x0C00
+#define	M66592_bmRequestType		0x00FF	/* b7-0: bmRequestType */
+#define	M66592_bmRequestTypeDir		0x0080	/* b7  : Data transfer direction */
+#define	  M66592_HOST_TO_DEVICE		 0x0000
+#define	  M66592_DEVICE_TO_HOST		 0x0080
+#define	M66592_bmRequestTypeType	0x0060	/* b6-5: Type */
+#define	  M66592_STANDARD		 0x0000
+#define	  M66592_CLASS			 0x0020
+#define	  M66592_VENDOR			 0x0040
+#define	M66592_bmRequestTypeRecip	0x001F	/* b4-0: Recipient */
+#define	  M66592_DEVICE			 0x0000
+#define	  M66592_INTERFACE		 0x0001
+#define	  M66592_ENDPOINT		 0x0002
+
+#define M66592_USBVAL				0x56
+#define	M66592_wValue				0xFFFF	/* b15-0: wValue */
+/* Standard Feature Selector */
+#define	  M66592_ENDPOINT_HALT			0x0000
+#define	  M66592_DEVICE_REMOTE_WAKEUP		0x0001
+#define	  M66592_TEST_MODE			0x0002
+/* Descriptor Types */
+#define	M66592_DT_TYPE				0xFF00
+#define	M66592_GET_DT_TYPE(v)			(((v) & DT_TYPE) >> 8)
+#define	  M66592_DT_DEVICE			0x01
+#define	  M66592_DT_CONFIGURATION		0x02
+#define	  M66592_DT_STRING			0x03
+#define	  M66592_DT_INTERFACE			0x04
+#define	  M66592_DT_ENDPOINT			0x05
+#define	  M66592_DT_DEVICE_QUALIFIER		0x06
+#define	  M66592_DT_OTHER_SPEED_CONFIGURATION	0x07
+#define	  M66592_DT_INTERFACE_POWER		0x08
+#define	M66592_DT_INDEX				0x00FF
+#define	M66592_CONF_NUM				0x00FF
+#define	M66592_ALT_SET				0x00FF
+
+#define M66592_USBINDEX			0x58
+#define	M66592_wIndex			0xFFFF	/* b15-0: wIndex */
+#define	M66592_TEST_SELECT		0xFF00	/* b15-b8: Test Mode Selectors */
+#define	  M66592_TEST_J			 0x0100		  /* Test_J */
+#define	  M66592_TEST_K			 0x0200		  /* Test_K */
+#define	  M66592_TEST_SE0_NAK		 0x0300		  /* Test_SE0_NAK */
+#define	  M66592_TEST_PACKET		 0x0400		  /* Test_Packet */
+#define	  M66592_TEST_FORCE_ENABLE	 0x0500		  /* Test_Force_Enable */
+#define	  M66592_TEST_STSelectors	 0x0600		  /* Standard test selectors */
+#define	  M66592_TEST_Reserved		 0x4000		  /* Reserved */
+#define	  M66592_TEST_VSTModes		 0xC000		  /* Vendor-specific test modes */
+#define	M66592_EP_DIR			0x0080	/* b7: Endpoint Direction */
+#define	  M66592_EP_DIR_IN		 0x0080
+#define	  M66592_EP_DIR_OUT		 0x0000
+
+#define M66592_USBLENG		0x5A
+#define	M66592_wLength		0xFFFF	/* b15-0: wLength */
+
+#define M66592_DCPCFG		0x5C
+#define	M66592_CNTMD		0x0100	/* b8: Continuous transfer mode select */
+#define	M66592_DIR		0x0010	/* b4: Control transfer DIR select */
+
+#define M66592_DCPMAXP		0x5E
+#define	M66592_DEVSEL		0xC000	/* b15-14: Device address select */
+#define	  M66592_DEVICE_0	 0x0000		  /* Device address 0 */
+#define	  M66592_DEVICE_1	 0x4000		  /* Device address 1 */
+#define	  M66592_DEVICE_2	 0x8000		  /* Device address 2 */
+#define	  M66592_DEVICE_3	 0xC000		  /* Device address 3 */
+#define	M66592_MAXP		0x007F	/* b6-0: Maxpacket size of default control pipe */
+
+#define M66592_DCPCTR		0x60
+#define	M66592_BSTS		0x8000	/* b15: Buffer status */
+#define	M66592_SUREQ		0x4000	/* b14: Send USB request  */
+#define	M66592_SQCLR		0x0100	/* b8: Sequence toggle bit clear */
+#define	M66592_SQSET		0x0080	/* b7: Sequence toggle bit set */
+#define	M66592_SQMON		0x0040	/* b6: Sequence toggle bit monitor */
+#define	M66592_CCPL		0x0004	/* b2: Enable control transfer complete */
+#define	M66592_PID		0x0003	/* b1-0: Response PID */
+#define	  M66592_PID_STALL	 0x0002		  /* STALL */
+#define	  M66592_PID_BUF	 0x0001		  /* BUF */
+#define	  M66592_PID_NAK	 0x0000		  /* NAK */
+
+#define M66592_PIPESEL		0x64
+#define	M66592_PIPENM		0x0007	/* b2-0: Pipe select */
+#define	  M66592_PIPE0		 0x0000		  /* PIPE 0 */
+#define	  M66592_PIPE1		 0x0001		  /* PIPE 1 */
+#define	  M66592_PIPE2		 0x0002		  /* PIPE 2 */
+#define	  M66592_PIPE3		 0x0003		  /* PIPE 3 */
+#define	  M66592_PIPE4		 0x0004		  /* PIPE 4 */
+#define	  M66592_PIPE5		 0x0005		  /* PIPE 5 */
+#define	  M66592_PIPE6		 0x0006		  /* PIPE 6 */
+#define	  M66592_PIPE7		 0x0007		  /* PIPE 7 */
+
+#define M66592_PIPECFG		0x66
+#define	M66592_TYP		0xC000	/* b15-14: Transfer type */
+#define	  M66592_ISO		 0xC000		  /* Isochronous */
+#define	  M66592_INT		 0x8000		  /* Interrupt */
+#define	  M66592_BULK		 0x4000		  /* Bulk */
+#define	M66592_BFRE		0x0400	/* b10: Buffer ready interrupt mode select */
+#define	M66592_DBLB		0x0200	/* b9: Double buffer mode select */
+#define	M66592_CNTMD		0x0100	/* b8: Continuous transfer mode select */
+#define	M66592_SHTNAK		0x0080	/* b7: Transfer end NAK */
+#define	M66592_DIR		0x0010	/* b4: Transfer direction select */
+#define	  M66592_DIR_H_OUT	 0x0010		  /* HOST OUT */
+#define	  M66592_DIR_P_IN	 0x0010		  /* PERI IN */
+#define	  M66592_DIR_H_IN	 0x0000		  /* HOST IN */
+#define	  M66592_DIR_P_OUT	 0x0000		  /* PERI OUT */
+#define	M66592_EPNUM		0x000F	/* b3-0: Eendpoint number select */
+#define	  M66592_EP1		 0x0001
+#define	  M66592_EP2		 0x0002
+#define	  M66592_EP3		 0x0003
+#define	  M66592_EP4		 0x0004
+#define	  M66592_EP5		 0x0005
+#define	  M66592_EP6		 0x0006
+#define	  M66592_EP7		 0x0007
+#define	  M66592_EP8		 0x0008
+#define	  M66592_EP9		 0x0009
+#define	  M66592_EP10		 0x000A
+#define	  M66592_EP11		 0x000B
+#define	  M66592_EP12		 0x000C
+#define	  M66592_EP13		 0x000D
+#define	  M66592_EP14		 0x000E
+#define	  M66592_EP15		 0x000F
+
+#define M66592_PIPEBUF		0x68
+#define	M66592_BUFSIZE		0x7C00	/* b14-10: Pipe buffer size */
+#define	M66592_BUF_SIZE(x)	((((x) / 64) - 1) << 10)
+#define	M66592_BUFNMB		0x00FF	/* b7-0: Pipe buffer number */
+
+#define M66592_PIPEMAXP		0x6A
+#define	M66592_MXPS		0x07FF	/* b10-0: Maxpacket size */
+
+#define M66592_PIPEPERI		0x6C
+#define	M66592_IFIS		0x1000	/* b12: Isochronous in-buffer flush mode select */
+#define	M66592_IITV		0x0007	/* b2-0: Isochronous interval */
+
+#define M66592_PIPE1CTR		0x70
+#define M66592_PIPE2CTR		0x72
+#define M66592_PIPE3CTR		0x74
+#define M66592_PIPE4CTR		0x76
+#define M66592_PIPE5CTR		0x78
+#define M66592_PIPE6CTR		0x7A
+#define M66592_PIPE7CTR		0x7C
+#define	M66592_BSTS		0x8000	/* b15: Buffer status */
+#define	M66592_INBUFM		0x4000	/* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define	M66592_ACLRM		0x0200	/* b9: Out buffer auto clear mode */
+#define	M66592_SQCLR		0x0100	/* b8: Sequence toggle bit clear */
+#define	M66592_SQSET		0x0080	/* b7: Sequence toggle bit set */
+#define	M66592_SQMON		0x0040	/* b6: Sequence toggle bit monitor */
+#define	M66592_PID		0x0003	/* b1-0: Response PID */
+
+#define M66592_INVALID_REG	0x7E
+
+
+#define __iomem
+
+#define get_pipectr_addr(pipenum)	(M66592_PIPE1CTR + (pipenum - 1) * 2)
+
+#define M66592_MAX_SAMPLING	10
+
+#define M66592_MAX_NUM_PIPE	8
+#define M66592_MAX_NUM_BULK	3
+#define M66592_MAX_NUM_ISOC	2
+#define M66592_MAX_NUM_INT	2
+
+#define M66592_BASE_PIPENUM_BULK	3
+#define M66592_BASE_PIPENUM_ISOC	1
+#define M66592_BASE_PIPENUM_INT		6
+
+#define M66592_BASE_BUFNUM	6
+#define M66592_MAX_BUFNUM	0x4F
+
+struct m66592_pipe_info {
+	u16	pipe;
+	u16	epnum;
+	u16	maxpacket;
+	u16	type;
+	u16	interval;
+	u16	dir_in;
+};
+
+struct m66592_request {
+	struct usb_request	req;
+	struct list_head	queue;
+};
+
+struct m66592_ep {
+	struct usb_ep		ep;
+	struct m66592		*m66592;
+
+	struct list_head	queue;
+	unsigned 		busy:1;
+	unsigned		internal_ccpl:1;	/* use only control */
+
+	/* this member can able to after m66592_enable */
+	unsigned		use_dma:1;
+	u16			pipenum;
+	u16			type;
+	const struct usb_endpoint_descriptor	*desc;
+	/* register address */
+	unsigned long		fifoaddr;
+	unsigned long		fifosel;
+	unsigned long		fifoctr;
+	unsigned long		fifotrn;
+	unsigned long		pipectr;
+};
+
+struct m66592 {
+	spinlock_t		lock;
+	void __iomem		*reg;
+
+	struct usb_gadget		gadget;
+	struct usb_gadget_driver	*driver;
+
+	struct m66592_ep	ep[M66592_MAX_NUM_PIPE];
+	struct m66592_ep	*pipenum2ep[M66592_MAX_NUM_PIPE];
+	struct m66592_ep	*epaddr2ep[16];
+
+	struct usb_request	*ep0_req;	/* for internal request */
+	u16			*ep0_buf;	/* for internal request */
+
+	struct timer_list	timer;
+
+	u16			old_vbus;
+	int			scount;
+
+	int			old_dvsq;
+
+	/* pipe config */
+	int bulk;
+	int interrupt;
+	int isochronous;
+	int num_dma;
+	int bi_bufnum;	/* bulk and isochronous's bufnum */
+};
+
+#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
+#define m66592_to_gadget(m66592) (&m66592->gadget)
+
+#define is_bulk_pipe(pipenum)	\
+	((pipenum >= M66592_BASE_PIPENUM_BULK) && \
+	 (pipenum < (M66592_BASE_PIPENUM_BULK + M66592_MAX_NUM_BULK)))
+#define is_interrupt_pipe(pipenum)	\
+	((pipenum >= M66592_BASE_PIPENUM_INT) && \
+	 (pipenum < (M66592_BASE_PIPENUM_INT + M66592_MAX_NUM_INT)))
+#define is_isoc_pipe(pipenum)	\
+	((pipenum >= M66592_BASE_PIPENUM_ISOC) && \
+	 (pipenum < (M66592_BASE_PIPENUM_ISOC + M66592_MAX_NUM_ISOC)))
+
+#define enable_irq_ready(m66592, pipenum)	\
+	enable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
+#define disable_irq_ready(m66592, pipenum)	\
+	disable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
+#define enable_irq_empty(m66592, pipenum)	\
+	enable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
+#define disable_irq_empty(m66592, pipenum)	\
+	disable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
+#define enable_irq_nrdy(m66592, pipenum)	\
+	enable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
+#define disable_irq_nrdy(m66592, pipenum)	\
+	disable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
+
+/*-------------------------------------------------------------------------*/
+static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
+{
+	return inw((unsigned long)m66592->reg + offset);
+}
+
+static inline void m66592_read_fifo(struct m66592 *m66592,
+				    unsigned long offset,
+				    void *buf, unsigned long len)
+{
+	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+
+	len = (len + 1) / 2;
+	insw(fifoaddr, buf, len);
+}
+
+static inline void m66592_write(struct m66592 *m66592, u16 val,
+				unsigned long offset)
+{
+	outw(val, (unsigned long)m66592->reg + offset);
+}
+
+static inline void m66592_write_fifo(struct m66592 *m66592,
+				     unsigned long offset,
+				     void *buf, unsigned long len)
+{
+	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+	unsigned long odd = len & 0x0001;
+
+	len = len / 2;
+	outsw(fifoaddr, buf, len);
+	if (odd) {
+		unsigned char *p = buf + len*2;
+		outb(*p, fifoaddr);
+	}
+}
+
+static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
+			       unsigned long offset)
+{
+	u16 tmp;
+	tmp = m66592_read(m66592, offset);
+	tmp = tmp & (~pat);
+	tmp = tmp | val;
+	m66592_write(m66592, tmp, offset);
+}
+
+#define m66592_bclr(m66592, val, offset)	\
+			m66592_mdfy(m66592, 0, val, offset)
+#define m66592_bset(m66592, val, offset)	\
+			m66592_mdfy(m66592, val, 0, offset)
+
+#endif	/* ifndef __M66592_UDC_H__ */
+
+
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 52779c5..c3d364e 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -450,100 +450,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * dma-coherent memory allocation (for dma-capable endpoints)
- *
- * NOTE: the dma_*_coherent() API calls suck.  Most implementations are
- * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
- * respect to calls with irqs disabled:  alloc is safe, free is not.
- * We currently work around (b), but not (a).
- */
-
-static void *
-net2280_alloc_buffer (
-	struct usb_ep		*_ep,
-	unsigned		bytes,
-	dma_addr_t		*dma,
-	gfp_t			gfp_flags
-)
-{
-	void			*retval;
-	struct net2280_ep	*ep;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep)
-		return NULL;
-	*dma = DMA_ADDR_INVALID;
-
-	if (ep->dma)
-		retval = dma_alloc_coherent(&ep->dev->pdev->dev,
-				bytes, dma, gfp_flags);
-	else
-		retval = kmalloc(bytes, gfp_flags);
-	return retval;
-}
-
-static DEFINE_SPINLOCK(buflock);
-static LIST_HEAD(buffers);
-
-struct free_record {
-	struct list_head	list;
-	struct device		*dev;
-	unsigned		bytes;
-	dma_addr_t		dma;
-};
-
-static void do_free(unsigned long ignored)
-{
-	spin_lock_irq(&buflock);
-	while (!list_empty(&buffers)) {
-		struct free_record	*buf;
-
-		buf = list_entry(buffers.next, struct free_record, list);
-		list_del(&buf->list);
-		spin_unlock_irq(&buflock);
-
-		dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
-
-		spin_lock_irq(&buflock);
-	}
-	spin_unlock_irq(&buflock);
-}
-
-static DECLARE_TASKLET(deferred_free, do_free, 0);
-
-static void
-net2280_free_buffer (
-	struct usb_ep *_ep,
-	void *address,
-	dma_addr_t dma,
-	unsigned bytes
-) {
-	/* free memory into the right allocator */
-	if (dma != DMA_ADDR_INVALID) {
-		struct net2280_ep	*ep;
-		struct free_record	*buf = address;
-		unsigned long		flags;
-
-		ep = container_of(_ep, struct net2280_ep, ep);
-		if (!_ep)
-			return;
-
-		ep = container_of (_ep, struct net2280_ep, ep);
-		buf->dev = &ep->dev->pdev->dev;
-		buf->bytes = bytes;
-		buf->dma = dma;
-
-		spin_lock_irqsave(&buflock, flags);
-		list_add_tail(&buf->list, &buffers);
-		tasklet_schedule(&deferred_free);
-		spin_unlock_irqrestore(&buflock, flags);
-	} else
-		kfree (address);
-}
-
-/*-------------------------------------------------------------------------*/
-
 /* load a packet into the fifo we use for usb IN transfers.
  * works for all endpoints.
  *
@@ -1392,9 +1298,6 @@
 	.alloc_request	= net2280_alloc_request,
 	.free_request	= net2280_free_request,
 
-	.alloc_buffer	= net2280_alloc_buffer,
-	.free_buffer	= net2280_free_buffer,
-
 	.queue		= net2280_queue,
 	.dequeue	= net2280_dequeue,
 
@@ -2440,9 +2343,9 @@
 
 		tmp = 0;
 
-#define	w_value		le16_to_cpup (&u.r.wValue)
-#define	w_index		le16_to_cpup (&u.r.wIndex)
-#define	w_length	le16_to_cpup (&u.r.wLength)
+#define	w_value		le16_to_cpu(u.r.wValue)
+#define	w_index		le16_to_cpu(u.r.wIndex)
+#define	w_length	le16_to_cpu(u.r.wLength)
 
 		/* ack the irq */
 		writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
@@ -2964,7 +2867,7 @@
 			, &dev->pci->pcimstctl);
 	/* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
 	pci_set_master (pdev);
-	pci_set_mwi (pdev);
+	pci_try_set_mwi (pdev);
 
 	/* ... also flushes any posted pci writes */
 	dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index b394e63..9b0f092 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -296,111 +296,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * dma-coherent memory allocation (for dma-capable endpoints)
- *
- * NOTE: the dma_*_coherent() API calls suck.  Most implementations are
- * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
- * respect to calls with irqs disabled:  alloc is safe, free is not.
- * We currently work around (b), but not (a).
- */
-
-static void *
-omap_alloc_buffer(
-	struct usb_ep	*_ep,
-	unsigned	bytes,
-	dma_addr_t	*dma,
-	gfp_t		gfp_flags
-)
-{
-	void		*retval;
-	struct omap_ep	*ep;
-
-	if (!_ep)
-		return NULL;
-
-	ep = container_of(_ep, struct omap_ep, ep);
-	if (use_dma && ep->has_dma) {
-		static int	warned;
-		if (!warned && bytes < PAGE_SIZE) {
-			dev_warn(ep->udc->gadget.dev.parent,
-				"using dma_alloc_coherent for "
-				"small allocations wastes memory\n");
-			warned++;
-		}
-		return dma_alloc_coherent(ep->udc->gadget.dev.parent,
-				bytes, dma, gfp_flags);
-	}
-
-	retval = kmalloc(bytes, gfp_flags);
-	if (retval)
-		*dma = virt_to_phys(retval);
-	return retval;
-}
-
-static DEFINE_SPINLOCK(buflock);
-static LIST_HEAD(buffers);
-
-struct free_record {
-	struct list_head	list;
-	struct device		*dev;
-	unsigned		bytes;
-	dma_addr_t		dma;
-};
-
-static void do_free(unsigned long ignored)
-{
-	spin_lock_irq(&buflock);
-	while (!list_empty(&buffers)) {
-		struct free_record	*buf;
-
-		buf = list_entry(buffers.next, struct free_record, list);
-		list_del(&buf->list);
-		spin_unlock_irq(&buflock);
-
-		dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
-
-		spin_lock_irq(&buflock);
-	}
-	spin_unlock_irq(&buflock);
-}
-
-static DECLARE_TASKLET(deferred_free, do_free, 0);
-
-static void omap_free_buffer(
-	struct usb_ep	*_ep,
-	void		*buf,
-	dma_addr_t	dma,
-	unsigned	bytes
-)
-{
-	if (!_ep) {
-		WARN_ON(1);
-		return;
-	}
-
-	/* free memory into the right allocator */
-	if (dma != DMA_ADDR_INVALID) {
-		struct omap_ep		*ep;
-		struct free_record	*rec = buf;
-		unsigned long		flags;
-
-		ep = container_of(_ep, struct omap_ep, ep);
-
-		rec->dev = ep->udc->gadget.dev.parent;
-		rec->bytes = bytes;
-		rec->dma = dma;
-
-		spin_lock_irqsave(&buflock, flags);
-		list_add_tail(&rec->list, &buffers);
-		tasklet_schedule(&deferred_free);
-		spin_unlock_irqrestore(&buflock, flags);
-	} else
-		kfree(buf);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static void
 done(struct omap_ep *ep, struct omap_req *req, int status)
 {
@@ -1271,9 +1166,6 @@
 	.alloc_request	= omap_alloc_request,
 	.free_request	= omap_free_request,
 
-	.alloc_buffer	= omap_alloc_buffer,
-	.free_buffer	= omap_free_buffer,
-
 	.queue		= omap_ep_queue,
 	.dequeue	= omap_ep_dequeue,
 
@@ -1651,9 +1543,9 @@
 			UDC_EP_NUM_REG = 0;
 		} while (UDC_IRQ_SRC_REG & UDC_SETUP);
 
-#define	w_value		le16_to_cpup (&u.r.wValue)
-#define	w_index		le16_to_cpup (&u.r.wIndex)
-#define	w_length	le16_to_cpup (&u.r.wLength)
+#define	w_value		le16_to_cpu(u.r.wValue)
+#define	w_index		le16_to_cpu(u.r.wIndex)
+#define	w_length	le16_to_cpu(u.r.wLength)
 
 		/* Delegate almost all control requests to the gadget driver,
 		 * except for a handful of ch9 status/feature requests that
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 84392e8..63b9521 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -24,9 +24,9 @@
  *
  */
 
-#undef	DEBUG
 // #define	VERBOSE	DBG_VERBOSE
 
+#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
@@ -46,19 +46,17 @@
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 #include <asm/hardware.h>
-#ifdef CONFIG_ARCH_PXA
-#include <asm/arch/pxa-regs.h>
-#endif
 
 #include <linux/usb/ch9.h>
 #include <linux/usb_gadget.h>
 
-#include <asm/arch/udc.h>
+#include <asm/mach/udc_pxa2xx.h>
 
 
 /*
@@ -76,9 +74,17 @@
  * it constrains the sorts of USB configuration change events that work.
  * The errata for these chips are misleading; some "fixed" bugs from
  * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
+ *
+ * Note that the UDC hardware supports DMA (except on IXP) but that's
+ * not used here.  IN-DMA (to host) is simple enough, when the data is
+ * suitably aligned (16 bytes) ... the network stack doesn't do that,
+ * other software can.  OUT-DMA is buggy in most chip versions, as well
+ * as poorly designed (data toggle not automatic).  So this driver won't
+ * bother using DMA.  (Mostly-working IN-DMA support was available in
+ * kernels before 2.6.23, but was never enabled or well tested.)
  */
 
-#define	DRIVER_VERSION	"4-May-2005"
+#define	DRIVER_VERSION	"30-June-2007"
 #define	DRIVER_DESC	"PXA 25x USB Device Controller driver"
 
 
@@ -87,12 +93,9 @@
 static const char ep0name [] = "ep0";
 
 
-// #define	USE_DMA
-// #define	USE_OUT_DMA
 // #define	DISABLE_TEST_MODE
 
 #ifdef CONFIG_ARCH_IXP4XX
-#undef USE_DMA
 
 /* cpu-specific register addresses are compiled in to this code */
 #ifdef CONFIG_ARCH_PXA
@@ -104,25 +107,6 @@
 #include "pxa2xx_udc.h"
 
 
-#ifdef	USE_DMA
-static int use_dma = 1;
-module_param(use_dma, bool, 0);
-MODULE_PARM_DESC (use_dma, "true to use dma");
-
-static void dma_nodesc_handler (int dmach, void *_ep);
-static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req);
-
-#ifdef USE_OUT_DMA
-#define	DMASTR " (dma support)"
-#else
-#define	DMASTR " (dma in)"
-#endif
-
-#else	/* !USE_DMA */
-#define	DMASTR " (pio only)"
-#undef	USE_OUT_DMA
-#endif
-
 #ifdef	CONFIG_USB_PXA2XX_SMALL
 #define SIZE_STR	" (small)"
 #else
@@ -155,7 +139,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_vbus)
-		return udc_gpio_get(mach->gpio_vbus);
+		return gpio_get_value(mach->gpio_vbus);
 	if (mach->udc_is_connected)
 		return mach->udc_is_connected();
 	return 1;
@@ -167,7 +151,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_pullup)
-		udc_gpio_set(mach->gpio_pullup, 0);
+		gpio_set_value(mach->gpio_pullup, 0);
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
@@ -177,7 +161,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_pullup)
-		udc_gpio_set(mach->gpio_pullup, 1);
+		gpio_set_value(mach->gpio_pullup, 1);
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
@@ -281,9 +265,8 @@
 	}
 
 	ep->desc = desc;
-	ep->dma = -1;
 	ep->stopped = 0;
-	ep->pio_irqs = ep->dma_irqs = 0;
+	ep->pio_irqs = 0;
 	ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
 
 	/* flush fifo (mostly for OUT buffers) */
@@ -291,30 +274,6 @@
 
 	/* ... reset halt state too, if we could ... */
 
-#ifdef	USE_DMA
-	/* for (some) bulk and ISO endpoints, try to get a DMA channel and
-	 * bind it to the endpoint.  otherwise use PIO.
-	 */
-	switch (ep->bmAttributes) {
-	case USB_ENDPOINT_XFER_ISOC:
-		if (le16_to_cpu(desc->wMaxPacketSize) % 32)
-			break;
-		// fall through
-	case USB_ENDPOINT_XFER_BULK:
-		if (!use_dma || !ep->reg_drcmr)
-			break;
-		ep->dma = pxa_request_dma ((char *)_ep->name,
-				(le16_to_cpu (desc->wMaxPacketSize) > 64)
-					? DMA_PRIO_MEDIUM /* some iso */
-					: DMA_PRIO_LOW,
-				dma_nodesc_handler, ep);
-		if (ep->dma >= 0) {
-			*ep->reg_drcmr = DRCMR_MAPVLD | ep->dma;
-			DMSG("%s using dma%d\n", _ep->name, ep->dma);
-		}
-	}
-#endif
-
 	DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
 	return 0;
 }
@@ -334,14 +293,6 @@
 
 	nuke (ep, -ESHUTDOWN);
 
-#ifdef	USE_DMA
-	if (ep->dma >= 0) {
-		*ep->reg_drcmr = 0;
-		pxa_free_dma (ep->dma);
-		ep->dma = -1;
-	}
-#endif
-
 	/* flush fifo (mostly for IN buffers) */
 	pxa2xx_ep_fifo_flush (_ep);
 
@@ -390,35 +341,6 @@
 	kfree(req);
 }
 
-
-/* PXA cache needs flushing with DMA I/O (it's dma-incoherent), but there's
- * no device-affinity and the heap works perfectly well for i/o buffers.
- * It wastes much less memory than dma_alloc_coherent() would, and even
- * prevents cacheline (32 bytes wide) sharing problems.
- */
-static void *
-pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-	dma_addr_t *dma, gfp_t gfp_flags)
-{
-	char			*retval;
-
-	retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
-	if (retval)
-#ifdef	USE_DMA
-		*dma = virt_to_bus (retval);
-#else
-		*dma = (dma_addr_t)~0;
-#endif
-	return retval;
-}
-
-static void
-pxa2xx_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma,
-		unsigned bytes)
-{
-	kfree (buf);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -518,18 +440,8 @@
 		/* requests complete when all IN data is in the FIFO */
 		if (is_last) {
 			done (ep, req, 0);
-			if (list_empty(&ep->queue) || unlikely(ep->dma >= 0)) {
+			if (list_empty(&ep->queue))
 				pio_irq_disable (ep->bEndpointAddress);
-#ifdef USE_DMA
-				/* unaligned data and zlps couldn't use dma */
-				if (unlikely(!list_empty(&ep->queue))) {
-					req = list_entry(ep->queue.next,
-						struct pxa2xx_request, queue);
-					kick_dma(ep,req);
-					return 0;
-				}
-#endif
-			}
 			return 1;
 		}
 
@@ -728,182 +640,6 @@
 	return 0;
 }
 
-#ifdef	USE_DMA
-
-#define	MAX_IN_DMA	((DCMD_LENGTH + 1) - BULK_FIFO_SIZE)
-
-static void
-start_dma_nodesc(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int is_in)
-{
-	u32	dcmd = req->req.length;
-	u32	buf = req->req.dma;
-	u32	fifo = io_v2p ((u32)ep->reg_uddr);
-
-	/* caller guarantees there's a packet or more remaining
-	 *  - IN may end with a short packet (TSP set separately),
-	 *  - OUT is always full length
-	 */
-	buf += req->req.actual;
-	dcmd -= req->req.actual;
-	ep->dma_fixup = 0;
-
-	/* no-descriptor mode can be simple for bulk-in, iso-in, iso-out */
-	DCSR(ep->dma) = DCSR_NODESC;
-	if (is_in) {
-		DSADR(ep->dma) = buf;
-		DTADR(ep->dma) = fifo;
-		if (dcmd > MAX_IN_DMA)
-			dcmd = MAX_IN_DMA;
-		else
-			ep->dma_fixup = (dcmd % ep->ep.maxpacket) != 0;
-		dcmd |= DCMD_BURST32 | DCMD_WIDTH1
-			| DCMD_FLOWTRG | DCMD_INCSRCADDR;
-	} else {
-#ifdef USE_OUT_DMA
-		DSADR(ep->dma) = fifo;
-		DTADR(ep->dma) = buf;
-		if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
-			dcmd = ep->ep.maxpacket;
-		dcmd |= DCMD_BURST32 | DCMD_WIDTH1
-			| DCMD_FLOWSRC | DCMD_INCTRGADDR;
-#endif
-	}
-	DCMD(ep->dma) = dcmd;
-	DCSR(ep->dma) = DCSR_RUN | DCSR_NODESC
-		| (unlikely(is_in)
-			? DCSR_STOPIRQEN	/* use dma_nodesc_handler() */
-			: 0);			/* use handle_ep() */
-}
-
-static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req)
-{
-	int	is_in = ep->bEndpointAddress & USB_DIR_IN;
-
-	if (is_in) {
-		/* unaligned tx buffers and zlps only work with PIO */
-		if ((req->req.dma & 0x0f) != 0
-				|| unlikely((req->req.length - req->req.actual)
-						== 0)) {
-			pio_irq_enable(ep->bEndpointAddress);
-			if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0)
-				(void) write_fifo(ep, req);
-		} else {
-			start_dma_nodesc(ep, req, USB_DIR_IN);
-		}
-	} else {
-		if ((req->req.length - req->req.actual) < ep->ep.maxpacket) {
-			DMSG("%s short dma read...\n", ep->ep.name);
-			/* we're always set up for pio out */
-			read_fifo (ep, req);
-		} else {
-			*ep->reg_udccs = UDCCS_BO_DME
-				| (*ep->reg_udccs & UDCCS_BO_FST);
-			start_dma_nodesc(ep, req, USB_DIR_OUT);
-		}
-	}
-}
-
-static void cancel_dma(struct pxa2xx_ep *ep)
-{
-	struct pxa2xx_request	*req;
-	u32			tmp;
-
-	if (DCSR(ep->dma) == 0 || list_empty(&ep->queue))
-		return;
-
-	DCSR(ep->dma) = 0;
-	while ((DCSR(ep->dma) & DCSR_STOPSTATE) == 0)
-		cpu_relax();
-
-	req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-	tmp = DCMD(ep->dma) & DCMD_LENGTH;
-	req->req.actual = req->req.length - (tmp & DCMD_LENGTH);
-
-	/* the last tx packet may be incomplete, so flush the fifo.
-	 * FIXME correct req.actual if we can
-	 */
-	if (ep->bEndpointAddress & USB_DIR_IN)
-		*ep->reg_udccs = UDCCS_BI_FTF;
-}
-
-/* dma channel stopped ... normal tx end (IN), or on error (IN/OUT) */
-static void dma_nodesc_handler(int dmach, void *_ep)
-{
-	struct pxa2xx_ep	*ep = _ep;
-	struct pxa2xx_request	*req;
-	u32			tmp, completed;
-
-	local_irq_disable();
-
-	req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-
-	ep->dma_irqs++;
-	ep->dev->stats.irqs++;
-	HEX_DISPLAY(ep->dev->stats.irqs);
-
-	/* ack/clear */
-	tmp = DCSR(ep->dma);
-	DCSR(ep->dma) = tmp;
-	if ((tmp & DCSR_STOPSTATE) == 0
-			|| (DDADR(ep->dma) & DDADR_STOP) != 0) {
-		DBG(DBG_VERBOSE, "%s, dcsr %08x ddadr %08x\n",
-			ep->ep.name, DCSR(ep->dma), DDADR(ep->dma));
-		goto done;
-	}
-	DCSR(ep->dma) = 0;	/* clear DCSR_STOPSTATE */
-
-	/* update transfer status */
-	completed = tmp & DCSR_BUSERR;
-	if (ep->bEndpointAddress & USB_DIR_IN)
-		tmp = DSADR(ep->dma);
-	else
-		tmp = DTADR(ep->dma);
-	req->req.actual = tmp - req->req.dma;
-
-	/* FIXME seems we sometimes see partial transfers... */
-
-	if (unlikely(completed != 0))
-		req->req.status = -EIO;
-	else if (req->req.actual) {
-		/* these registers have zeroes in low bits; they miscount
-		 * some (end-of-transfer) short packets:  tx 14 as tx 12
-		 */
-		if (ep->dma_fixup)
-			req->req.actual = min(req->req.actual + 3,
-						req->req.length);
-
-		tmp = (req->req.length - req->req.actual);
-		completed = (tmp == 0);
-		if (completed && (ep->bEndpointAddress & USB_DIR_IN)) {
-
-			/* maybe validate final short packet ... */
-			if ((req->req.actual % ep->ep.maxpacket) != 0)
-				*ep->reg_udccs = UDCCS_BI_TSP/*|UDCCS_BI_TPC*/;
-
-			/* ... or zlp, using pio fallback */
-			else if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK
-					&& req->req.zero) {
-				DMSG("%s zlp terminate ...\n", ep->ep.name);
-				completed = 0;
-			}
-		}
-	}
-
-	if (likely(completed)) {
-		done(ep, req, 0);
-
-		/* maybe re-activate after completion */
-		if (ep->stopped || list_empty(&ep->queue))
-			goto done;
-		req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-	}
-	kick_dma(ep, req);
-done:
-	local_irq_enable();
-}
-
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 static int
@@ -942,19 +678,8 @@
 						(ep->desc->wMaxPacketSize)))
 		return -EMSGSIZE;
 
-#ifdef	USE_DMA
-	// FIXME caller may already have done the dma mapping
-	if (ep->dma >= 0) {
-		_req->dma = dma_map_single(dev->dev,
-			_req->buf, _req->length,
-			((ep->bEndpointAddress & USB_DIR_IN) != 0)
-				? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
-	}
-#endif
-
 	DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
-	     _ep->name, _req, _req->length, _req->buf);
+		_ep->name, _req, _req->length, _req->buf);
 
 	local_irq_save(flags);
 
@@ -1002,11 +727,6 @@
 				local_irq_restore (flags);
 				return -EL2HLT;
 			}
-#ifdef	USE_DMA
-		/* either start dma or prime pio pump */
-		} else if (ep->dma >= 0) {
-			kick_dma(ep, req);
-#endif
 		/* can the FIFO can satisfy the request immediately? */
 		} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
 			if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
@@ -1017,7 +737,7 @@
 			req = NULL;
 		}
 
-		if (likely (req && ep->desc) && ep->dma < 0)
+		if (likely (req && ep->desc))
 			pio_irq_enable(ep->bEndpointAddress);
 	}
 
@@ -1038,10 +758,6 @@
 	struct pxa2xx_request *req;
 
 	/* called with irqs blocked */
-#ifdef	USE_DMA
-	if (ep->dma >= 0 && !ep->stopped)
-		cancel_dma(ep);
-#endif
 	while (!list_empty(&ep->queue)) {
 		req = list_entry(ep->queue.next,
 				struct pxa2xx_request,
@@ -1076,19 +792,7 @@
 		return -EINVAL;
 	}
 
-#ifdef	USE_DMA
-	if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
-		cancel_dma(ep);
-		done(ep, req, -ECONNRESET);
-		/* restart i/o */
-		if (!list_empty(&ep->queue)) {
-			req = list_entry(ep->queue.next,
-					struct pxa2xx_request, queue);
-			kick_dma(ep, req);
-		}
-	} else
-#endif
-		done(ep, req, -ECONNRESET);
+	done(ep, req, -ECONNRESET);
 
 	local_irq_restore(flags);
 	return 0;
@@ -1203,9 +907,6 @@
 	.alloc_request	= pxa2xx_ep_alloc_request,
 	.free_request	= pxa2xx_ep_free_request,
 
-	.alloc_buffer	= pxa2xx_ep_alloc_buffer,
-	.free_buffer	= pxa2xx_ep_free_buffer,
-
 	.queue		= pxa2xx_ep_queue,
 	.dequeue	= pxa2xx_ep_dequeue,
 
@@ -1325,7 +1026,7 @@
 	/* basic device status */
 	t = scnprintf(next, size, DRIVER_DESC "\n"
 		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
-		driver_name, DRIVER_VERSION SIZE_STR DMASTR,
+		driver_name, DRIVER_VERSION SIZE_STR "(pio)",
 		dev->driver ? dev->driver->driver.name : "(none)",
 		is_vbus_present() ? "full speed" : "disconnected");
 	size -= t;
@@ -1390,7 +1091,6 @@
 	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
 		struct pxa2xx_ep	*ep = &dev->ep [i];
 		struct pxa2xx_request	*req;
-		int			t;
 
 		if (i != 0) {
 			const struct usb_endpoint_descriptor	*d;
@@ -1400,10 +1100,9 @@
 				continue;
 			tmp = *dev->ep [i].reg_udccs;
 			t = scnprintf(next, size,
-				"%s max %d %s udccs %02x irqs %lu/%lu\n",
+				"%s max %d %s udccs %02x irqs %lu\n",
 				ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
-				(ep->dma >= 0) ? "dma" : "pio", tmp,
-				ep->pio_irqs, ep->dma_irqs);
+				"pio", tmp, ep->pio_irqs);
 			/* TODO translate all five groups of udccs bits! */
 
 		} else /* ep0 should only have one transfer queued */
@@ -1423,19 +1122,7 @@
 			continue;
 		}
 		list_for_each_entry(req, &ep->queue, queue) {
-#ifdef	USE_DMA
-			if (ep->dma >= 0 && req->queue.prev == &ep->queue)
-				t = scnprintf(next, size,
-					"\treq %p len %d/%d "
-					"buf %p (dma%d dcmd %08x)\n",
-					&req->req, req->req.actual,
-					req->req.length, req->req.buf,
-					ep->dma, DCMD(ep->dma)
-					// low 13 bits == bytes-to-go
-					);
-			else
-#endif
-				t = scnprintf(next, size,
+			t = scnprintf(next, size,
 					"\treq %p len %d/%d buf %p\n",
 					&req->req, req->req.actual,
 					req->req.length, req->req.buf);
@@ -1488,7 +1175,6 @@
 
 	ep0_idle (dev);
 	dev->gadget.speed = USB_SPEED_UNKNOWN;
-	LED_CONNECTED_OFF;
 }
 
 
@@ -1514,7 +1200,7 @@
 		ep->desc = NULL;
 		ep->stopped = 0;
 		INIT_LIST_HEAD (&ep->queue);
-		ep->pio_irqs = ep->dma_irqs = 0;
+		ep->pio_irqs = 0;
 	}
 
 	/* the rest was statically initialized, and is read-only */
@@ -1666,7 +1352,6 @@
 	del_timer_sync(&dev->timer);
 
 	/* report disconnect; the driver is already quiesced */
-	LED_CONNECTED_OFF;
 	if (driver)
 		driver->disconnect(&dev->gadget);
 
@@ -1715,16 +1400,13 @@
 	int			vbus;
 
 	dev->stats.irqs++;
-	HEX_DISPLAY(dev->stats.irqs);
 	switch (irq) {
 	case LUBBOCK_USB_IRQ:
-		LED_CONNECTED_ON;
 		vbus = 1;
 		disable_irq(LUBBOCK_USB_IRQ);
 		enable_irq(LUBBOCK_USB_DISC_IRQ);
 		break;
 	case LUBBOCK_USB_DISC_IRQ:
-		LED_CONNECTED_OFF;
 		vbus = 0;
 		disable_irq(LUBBOCK_USB_DISC_IRQ);
 		enable_irq(LUBBOCK_USB_IRQ);
@@ -1742,7 +1424,7 @@
 static irqreturn_t udc_vbus_irq(int irq, void *_dev)
 {
 	struct pxa2xx_udc	*dev = _dev;
-	int			vbus = udc_gpio_get(dev->mach->gpio_vbus);
+	int			vbus = gpio_get_value(dev->mach->gpio_vbus);
 
 	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
 	return IRQ_HANDLED;
@@ -2040,18 +1722,6 @@
 
 			/* fifos can hold packets, ready for reading... */
 			if (likely(req)) {
-#ifdef USE_OUT_DMA
-// TODO didn't yet debug out-dma.  this approach assumes
-// the worst about short packets and RPC; it might be better.
-
-				if (likely(ep->dma >= 0)) {
-					if (!(udccs & UDCCS_BO_RSP)) {
-						*ep->reg_udccs = UDCCS_BO_RPC;
-						ep->dma_irqs++;
-						return;
-					}
-				}
-#endif
 				completed = read_fifo(ep, req);
 			} else
 				pio_irq_disable (ep->bEndpointAddress);
@@ -2074,7 +1744,6 @@
 	int			handled;
 
 	dev->stats.irqs++;
-	HEX_DISPLAY(dev->stats.irqs);
 	do {
 		u32		udccr = UDCCR;
 
@@ -2125,7 +1794,6 @@
 			} else {
 				DBG(DBG_VERBOSE, "USB reset end\n");
 				dev->gadget.speed = USB_SPEED_FULL;
-				LED_CONNECTED_ON;
 				memset(&dev->stats, 0, sizeof dev->stats);
 				/* driver and endpoints are still reset */
 			}
@@ -2217,7 +1885,6 @@
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS1,
 		.reg_uddr	= &UDDR1,
-		drcmr (25)
 	},
 	.ep[2] = {
 		.ep = {
@@ -2232,7 +1899,6 @@
 		.reg_udccs	= &UDCCS2,
 		.reg_ubcr	= &UBCR2,
 		.reg_uddr	= &UDDR2,
-		drcmr (26)
 	},
 #ifndef CONFIG_USB_PXA2XX_SMALL
 	.ep[3] = {
@@ -2247,7 +1913,6 @@
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS3,
 		.reg_uddr	= &UDDR3,
-		drcmr (27)
 	},
 	.ep[4] = {
 		.ep = {
@@ -2262,7 +1927,6 @@
 		.reg_udccs	= &UDCCS4,
 		.reg_ubcr	= &UBCR4,
 		.reg_uddr	= &UDDR4,
-		drcmr (28)
 	},
 	.ep[5] = {
 		.ep = {
@@ -2291,7 +1955,6 @@
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS6,
 		.reg_uddr	= &UDDR6,
-		drcmr (30)
 	},
 	.ep[7] = {
 		.ep = {
@@ -2306,7 +1969,6 @@
 		.reg_udccs	= &UDCCS7,
 		.reg_ubcr	= &UBCR7,
 		.reg_uddr	= &UDDR7,
-		drcmr (31)
 	},
 	.ep[8] = {
 		.ep = {
@@ -2320,7 +1982,6 @@
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS8,
 		.reg_uddr	= &UDDR8,
-		drcmr (32)
 	},
 	.ep[9] = {
 		.ep = {
@@ -2335,7 +1996,6 @@
 		.reg_udccs	= &UDCCS9,
 		.reg_ubcr	= &UBCR9,
 		.reg_uddr	= &UDDR9,
-		drcmr (33)
 	},
 	.ep[10] = {
 		.ep = {
@@ -2364,7 +2024,6 @@
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS11,
 		.reg_uddr	= &UDDR11,
-		drcmr (35)
 	},
 	.ep[12] = {
 		.ep = {
@@ -2379,7 +2038,6 @@
 		.reg_udccs	= &UDCCS12,
 		.reg_ubcr	= &UBCR12,
 		.reg_uddr	= &UDDR12,
-		drcmr (36)
 	},
 	.ep[13] = {
 		.ep = {
@@ -2393,7 +2051,6 @@
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS13,
 		.reg_uddr	= &UDDR13,
-		drcmr (37)
 	},
 	.ep[14] = {
 		.ep = {
@@ -2408,7 +2065,6 @@
 		.reg_udccs	= &UDCCS14,
 		.reg_ubcr	= &UBCR14,
 		.reg_uddr	= &UDDR14,
-		drcmr (38)
 	},
 	.ep[15] = {
 		.ep = {
@@ -2466,7 +2122,7 @@
 static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 {
 	struct pxa2xx_udc *dev = &memory;
-	int retval, out_dma = 1, vbus_irq, irq;
+	int retval, vbus_irq, irq;
 	u32 chiprev;
 
 	/* insist on Intel/ARM/XScale */
@@ -2489,7 +2145,7 @@
 	case PXA250_B2: case PXA210_B2:
 	case PXA250_B1: case PXA210_B1:
 	case PXA250_B0: case PXA210_B0:
-		out_dma = 0;
+		/* OUT-DMA is broken ... */
 		/* fall through */
 	case PXA250_C0: case PXA210_C0:
 		break;
@@ -2498,11 +2154,9 @@
 	case IXP425_B0:
 	case IXP465_AD:
 		dev->has_cfr = 1;
-		out_dma = 0;
 		break;
 #endif
 	default:
-		out_dma = 0;
 		printk(KERN_ERR "%s: unrecognized processor: %08x\n",
 			driver_name, chiprev);
 		/* iop3xx, ixp4xx, ... */
@@ -2513,36 +2167,41 @@
 	if (irq < 0)
 		return -ENODEV;
 
-	pr_debug("%s: IRQ %d%s%s%s\n", driver_name, irq,
+	pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
 		dev->has_cfr ? "" : " (!cfr)",
-		out_dma ? "" : " (broken dma-out)",
-		SIZE_STR DMASTR
+		SIZE_STR "(pio)"
 		);
 
-#ifdef	USE_DMA
-#ifndef	USE_OUT_DMA
-	out_dma = 0;
-#endif
-	/* pxa 250 erratum 130 prevents using OUT dma (fixed C0) */
-	if (!out_dma) {
-		DMSG("disabled OUT dma\n");
-		dev->ep[ 2].reg_drcmr = dev->ep[ 4].reg_drcmr = 0;
-		dev->ep[ 7].reg_drcmr = dev->ep[ 9].reg_drcmr = 0;
-		dev->ep[12].reg_drcmr = dev->ep[14].reg_drcmr = 0;
-	}
-#endif
-
 	/* other non-static parts of init */
 	dev->dev = &pdev->dev;
 	dev->mach = pdev->dev.platform_data;
+
 	if (dev->mach->gpio_vbus) {
-		udc_gpio_init_vbus(dev->mach->gpio_vbus);
-		vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus);
+		if ((retval = gpio_request(dev->mach->gpio_vbus,
+				"pxa2xx_udc GPIO VBUS"))) {
+			dev_dbg(&pdev->dev,
+				"can't get vbus gpio %d, err: %d\n",
+				dev->mach->gpio_vbus, retval);
+			return -EBUSY;
+		}
+		gpio_direction_input(dev->mach->gpio_vbus);
+		vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
 		set_irq_type(vbus_irq, IRQT_BOTHEDGE);
 	} else
 		vbus_irq = 0;
-	if (dev->mach->gpio_pullup)
-		udc_gpio_init_pullup(dev->mach->gpio_pullup);
+
+	if (dev->mach->gpio_pullup) {
+		if ((retval = gpio_request(dev->mach->gpio_pullup,
+				"pca2xx_udc GPIO PULLUP"))) {
+			dev_dbg(&pdev->dev,
+				"can't get pullup gpio %d, err: %d\n",
+				dev->mach->gpio_pullup, retval);
+			if (dev->mach->gpio_vbus)
+				gpio_free(dev->mach->gpio_vbus);
+			return -EBUSY;
+		}
+		gpio_direction_output(dev->mach->gpio_pullup, 0);
+	}
 
 	init_timer(&dev->timer);
 	dev->timer.function = udc_watchdog;
@@ -2566,6 +2225,10 @@
 	if (retval != 0) {
 		printk(KERN_ERR "%s: can't get irq %d, err %d\n",
 			driver_name, irq, retval);
+		if (dev->mach->gpio_pullup)
+			gpio_free(dev->mach->gpio_pullup);
+		if (dev->mach->gpio_vbus)
+			gpio_free(dev->mach->gpio_vbus);
 		return -EBUSY;
 	}
 	dev->got_irq = 1;
@@ -2581,6 +2244,10 @@
 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
 lubbock_fail0:
 			free_irq(irq, dev);
+			if (dev->mach->gpio_pullup)
+				gpio_free(dev->mach->gpio_pullup);
+			if (dev->mach->gpio_vbus)
+				gpio_free(dev->mach->gpio_vbus);
 			return -EBUSY;
 		}
 		retval = request_irq(LUBBOCK_USB_IRQ,
@@ -2593,11 +2260,6 @@
 			free_irq(LUBBOCK_USB_DISC_IRQ, dev);
 			goto lubbock_fail0;
 		}
-#ifdef DEBUG
-		/* with U-Boot (but not BLOB), hex is off by default */
-		HEX_DISPLAY(dev->stats.irqs);
-		LUB_DISC_BLNK_LED &= 0xff;
-#endif
 	} else
 #endif
 	if (vbus_irq) {
@@ -2608,6 +2270,10 @@
 			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
 				driver_name, vbus_irq, retval);
 			free_irq(irq, dev);
+			if (dev->mach->gpio_pullup)
+				gpio_free(dev->mach->gpio_pullup);
+			if (dev->mach->gpio_vbus)
+				gpio_free(dev->mach->gpio_vbus);
 			return -EBUSY;
 		}
 	}
@@ -2641,8 +2307,13 @@
 		free_irq(LUBBOCK_USB_IRQ, dev);
 	}
 #endif
-	if (dev->mach->gpio_vbus)
-		free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev);
+	if (dev->mach->gpio_vbus) {
+		free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
+		gpio_free(dev->mach->gpio_vbus);
+	}
+	if (dev->mach->gpio_pullup)
+		gpio_free(dev->mach->gpio_pullup);
+
 	platform_set_drvdata(pdev, NULL);
 	the_controller = NULL;
 	return 0;
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 773e549..0e5d0e6 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -54,8 +54,6 @@
 	const struct usb_endpoint_descriptor	*desc;
 	struct list_head			queue;
 	unsigned long				pio_irqs;
-	unsigned long				dma_irqs;
-	short					dma; 
 
 	unsigned short				fifo_size;
 	u8					bEndpointAddress;
@@ -63,7 +61,7 @@
 
 	unsigned				stopped : 1;
 	unsigned				dma_fixup : 1;
-							 
+
 	/* UDCCS = UDC Control/Status for this EP
 	 * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
 	 * UDDR = UDC Endpoint Data Register (the fifo)
@@ -72,12 +70,6 @@
 	volatile u32				*reg_udccs;
 	volatile u32				*reg_ubcr;
 	volatile u32				*reg_uddr;
-#ifdef USE_DMA
-	volatile u32			*reg_drcmr;
-#define	drcmr(n)  .reg_drcmr = & DRCMR ## n ,
-#else
-#define	drcmr(n)  
-#endif
 };
 
 struct pxa2xx_request {
@@ -85,7 +77,7 @@
 	struct list_head			queue;
 };
 
-enum ep0_state { 
+enum ep0_state {
 	EP0_IDLE,
 	EP0_IN_DATA_PHASE,
 	EP0_OUT_DATA_PHASE,
@@ -108,7 +100,6 @@
 
 #ifdef CONFIG_USB_PXA2XX_SMALL
 /* when memory's tight, SMALL config saves code+data.  */
-#undef	USE_DMA
 #define	PXA_UDC_NUM_ENDPOINTS	3
 #endif
 
@@ -144,37 +135,8 @@
 #ifdef CONFIG_ARCH_LUBBOCK
 #include <asm/arch/lubbock.h>
 /* lubbock can also report usb connect/disconnect irqs */
-
-#ifdef DEBUG
-#define HEX_DISPLAY(n)	if (machine_is_lubbock()) { LUB_HEXLED = (n); }
 #endif
 
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* LEDs are only for debug */
-#ifndef HEX_DISPLAY
-#define HEX_DISPLAY(n)		do {} while(0)
-#endif
-
-#ifdef DEBUG
-#include <asm/leds.h>
-
-#define LED_CONNECTED_ON	leds_event(led_green_on)
-#define LED_CONNECTED_OFF	do { \
-					leds_event(led_green_off); \
-					HEX_DISPLAY(0); \
-				} while(0)
-#endif
-
-#ifndef LED_CONNECTED_ON
-#define LED_CONNECTED_ON	do {} while(0)
-#define LED_CONNECTED_OFF	do {} while(0)
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 static struct pxa2xx_udc *the_controller;
 
 /*-------------------------------------------------------------------------*/
@@ -204,7 +166,7 @@
 #    define UDC_DEBUG DBG_NORMAL
 #endif
 
-static void __attribute__ ((__unused__))
+static void __maybe_unused
 dump_udccr(const char *label)
 {
 	u32	udccr = UDCCR;
@@ -220,7 +182,7 @@
 		(udccr & UDCCR_UDE) ? " ude" : "");
 }
 
-static void __attribute__ ((__unused__))
+static void __maybe_unused
 dump_udccs0(const char *label)
 {
 	u32		udccs0 = UDCCS0;
@@ -237,7 +199,7 @@
 		(udccs0 & UDCCS0_OPR) ? " opr" : "");
 }
 
-static void __attribute__ ((__unused__))
+static void __maybe_unused
 dump_state(struct pxa2xx_udc *dev)
 {
 	u32		tmp;
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 6ec8cf1..db1b2bf 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -53,7 +53,7 @@
  */
 
 #if 0
-#define DEBUG(str,args...) do { \
+#define DBG(str,args...) do { \
 	if (rndis_debug) \
 		printk(KERN_DEBUG str , ## args ); \
 	} while (0)
@@ -65,7 +65,7 @@
 #else
 
 #define rndis_debug		0
-#define DEBUG(str,args...)	do{}while(0)
+#define DBG(str,args...)	do{}while(0)
 #endif
 
 #define RNDIS_MAX_CONFIGS	1
@@ -183,13 +183,17 @@
 	if (!resp) return -ENOMEM;
 
 	if (buf_len && rndis_debug > 1) {
-		DEBUG("query OID %08x value, len %d:\n", OID, buf_len);
+		DBG("query OID %08x value, len %d:\n", OID, buf_len);
 		for (i = 0; i < buf_len; i += 16) {
-			DEBUG ("%03d: %08x %08x %08x %08x\n", i,
-				le32_to_cpup((__le32 *)&buf[i]),
-				le32_to_cpup((__le32 *)&buf[i + 4]),
-				le32_to_cpup((__le32 *)&buf[i + 8]),
-				le32_to_cpup((__le32 *)&buf[i + 12]));
+			DBG("%03d: %08x %08x %08x %08x\n", i,
+				le32_to_cpu(get_unaligned((__le32 *)
+					&buf[i])),
+				le32_to_cpu(get_unaligned((__le32 *)
+					&buf[i + 4])),
+				le32_to_cpu(get_unaligned((__le32 *)
+					&buf[i + 8])),
+				le32_to_cpu(get_unaligned((__le32 *)
+					&buf[i + 12])));
 		}
 	}
 
@@ -203,7 +207,7 @@
 
 	/* mandatory */
 	case OID_GEN_SUPPORTED_LIST:
-		DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
+		DBG("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
 		length = sizeof (oid_supported_list);
 		count  = length / sizeof (u32);
 		for (i = 0; i < count; i++)
@@ -213,7 +217,7 @@
 
 	/* mandatory */
 	case OID_GEN_HARDWARE_STATUS:
-		DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
+		DBG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
 		/* Bogus question!
 		 * Hardware must be ready to receive high level protocols.
 		 * BTW:
@@ -226,14 +230,14 @@
 
 	/* mandatory */
 	case OID_GEN_MEDIA_SUPPORTED:
-		DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MEDIA_IN_USE:
-		DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
 		/* one medium, one transport... (maybe you do it better) */
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
 		retval = 0;
@@ -241,7 +245,7 @@
 
 	/* mandatory */
 	case OID_GEN_MAXIMUM_FRAME_SIZE:
-		DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -252,7 +256,7 @@
 	/* mandatory */
 	case OID_GEN_LINK_SPEED:
 		if (rndis_debug > 1)
-			DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
+			DBG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].media_state
 				== NDIS_MEDIA_STATE_DISCONNECTED)
 			*outbuf = __constant_cpu_to_le32 (0);
@@ -264,7 +268,7 @@
 
 	/* mandatory */
 	case OID_GEN_TRANSMIT_BLOCK_SIZE:
-		DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
+		DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -274,7 +278,7 @@
 
 	/* mandatory */
 	case OID_GEN_RECEIVE_BLOCK_SIZE:
-		DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
+		DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -284,7 +288,7 @@
 
 	/* mandatory */
 	case OID_GEN_VENDOR_ID:
-		DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
+		DBG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (
 			rndis_per_dev_params [configNr].vendorID);
 		retval = 0;
@@ -292,7 +296,7 @@
 
 	/* mandatory */
 	case OID_GEN_VENDOR_DESCRIPTION:
-		DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
+		DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
 		length = strlen (rndis_per_dev_params [configNr].vendorDescr);
 		memcpy (outbuf,
 			rndis_per_dev_params [configNr].vendorDescr, length);
@@ -300,7 +304,7 @@
 		break;
 
 	case OID_GEN_VENDOR_DRIVER_VERSION:
-		DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
+		DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
 		/* Created as LE */
 		*outbuf = rndis_driver_version;
 		retval = 0;
@@ -308,14 +312,14 @@
 
 	/* mandatory */
 	case OID_GEN_CURRENT_PACKET_FILTER:
-		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
+		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MAXIMUM_TOTAL_SIZE:
-		DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
 		retval = 0;
 		break;
@@ -323,14 +327,14 @@
 	/* mandatory */
 	case OID_GEN_MEDIA_CONNECT_STATUS:
 		if (rndis_debug > 1)
-			DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
+			DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 						.media_state);
 		retval = 0;
 		break;
 
 	case OID_GEN_PHYSICAL_MEDIUM:
-		DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
+		DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
@@ -340,7 +344,7 @@
 	 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
 	 */
 	case OID_GEN_MAC_OPTIONS:		/* from WinME */
-		DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32(
 			  NDIS_MAC_OPTION_RECEIVE_SERIALIZED
 			| NDIS_MAC_OPTION_FULL_DUPLEX);
@@ -352,7 +356,7 @@
 	/* mandatory */
 	case OID_GEN_XMIT_OK:
 		if (rndis_debug > 1)
-			DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
+			DBG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
 			    rndis_per_dev_params [configNr].stats->tx_packets -
@@ -365,7 +369,7 @@
 	/* mandatory */
 	case OID_GEN_RCV_OK:
 		if (rndis_debug > 1)
-			DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
+			DBG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
 			    rndis_per_dev_params [configNr].stats->rx_packets -
@@ -378,7 +382,7 @@
 	/* mandatory */
 	case OID_GEN_XMIT_ERROR:
 		if (rndis_debug > 1)
-			DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
+			DBG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->tx_errors);
@@ -389,7 +393,7 @@
 	/* mandatory */
 	case OID_GEN_RCV_ERROR:
 		if (rndis_debug > 1)
-			DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
+			DBG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_errors);
@@ -399,7 +403,7 @@
 
 	/* mandatory */
 	case OID_GEN_RCV_NO_BUFFER:
-		DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
+		DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_dropped);
@@ -409,7 +413,7 @@
 
 #ifdef	RNDIS_OPTIONAL_STATS
 	case OID_GEN_DIRECTED_BYTES_XMIT:
-		DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
+		DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
 		/*
 		 * Aunt Tilly's size of shoes
 		 * minus antarctica count of penguins
@@ -429,7 +433,7 @@
 		break;
 
 	case OID_GEN_DIRECTED_FRAMES_XMIT:
-		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
+		DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
 		/* dito */
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
@@ -445,7 +449,7 @@
 		break;
 
 	case OID_GEN_MULTICAST_BYTES_XMIT:
-		DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->multicast*1234);
@@ -454,7 +458,7 @@
 		break;
 
 	case OID_GEN_MULTICAST_FRAMES_XMIT:
-		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->multicast);
@@ -463,7 +467,7 @@
 		break;
 
 	case OID_GEN_BROADCAST_BYTES_XMIT:
-		DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
+		DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->tx_packets/42*255);
@@ -472,7 +476,7 @@
 		break;
 
 	case OID_GEN_BROADCAST_FRAMES_XMIT:
-		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
+		DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->tx_packets/42);
@@ -481,19 +485,19 @@
 		break;
 
 	case OID_GEN_DIRECTED_BYTES_RCV:
-		DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
+		DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 	case OID_GEN_DIRECTED_FRAMES_RCV:
-		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
+		DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 	case OID_GEN_MULTICAST_BYTES_RCV:
-		DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->multicast * 1111);
@@ -502,7 +506,7 @@
 		break;
 
 	case OID_GEN_MULTICAST_FRAMES_RCV:
-		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
+		DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->multicast);
@@ -511,7 +515,7 @@
 		break;
 
 	case OID_GEN_BROADCAST_BYTES_RCV:
-		DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
+		DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_packets/42*255);
@@ -520,7 +524,7 @@
 		break;
 
 	case OID_GEN_BROADCAST_FRAMES_RCV:
-		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
+		DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_packets/42);
@@ -529,7 +533,7 @@
 		break;
 
 	case OID_GEN_RCV_CRC_ERROR:
-		DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
+		DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_crc_errors);
@@ -538,7 +542,7 @@
 		break;
 
 	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-		DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
+		DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
@@ -548,7 +552,7 @@
 
 	/* mandatory */
 	case OID_802_3_PERMANENT_ADDRESS:
-		DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
+		DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = ETH_ALEN;
 			memcpy (outbuf,
@@ -560,7 +564,7 @@
 
 	/* mandatory */
 	case OID_802_3_CURRENT_ADDRESS:
-		DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
+		DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = ETH_ALEN;
 			memcpy (outbuf,
@@ -572,7 +576,7 @@
 
 	/* mandatory */
 	case OID_802_3_MULTICAST_LIST:
-		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+		DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
 		/* Multicast base address only */
 		*outbuf = __constant_cpu_to_le32 (0xE0000000);
 		retval = 0;
@@ -580,21 +584,21 @@
 
 	/* mandatory */
 	case OID_802_3_MAXIMUM_LIST_SIZE:
-		DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
+		DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
 		/* Multicast base address only */
 		*outbuf = __constant_cpu_to_le32 (1);
 		retval = 0;
 		break;
 
 	case OID_802_3_MAC_OPTIONS:
-		DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
+		DBG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
 		break;
 
 	/* ieee802.3 statistics OIDs (table 4-4) */
 
 	/* mandatory */
 	case OID_802_3_RCV_ERROR_ALIGNMENT:
-		DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
+		DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 					.stats->rx_frame_errors);
@@ -604,51 +608,51 @@
 
 	/* mandatory */
 	case OID_802_3_XMIT_ONE_COLLISION:
-		DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
+		DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_802_3_XMIT_MORE_COLLISIONS:
-		DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
+		DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 #ifdef	RNDIS_OPTIONAL_STATS
 	case OID_802_3_XMIT_DEFERRED:
-		DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
+		DBG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_MAX_COLLISIONS:
-		DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
+		DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_RCV_OVERRUN:
-		DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
+		DBG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_UNDERRUN:
-		DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
+		DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_HEARTBEAT_FAILURE:
-		DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
+		DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_TIMES_CRS_LOST:
-		DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
+		DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
 		/* TODO */
 		break;
 
 	case OID_802_3_XMIT_LATE_COLLISIONS:
-		DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
+		DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
 		/* TODO */
 		break;
 #endif	/* RNDIS_OPTIONAL_STATS */
@@ -656,7 +660,7 @@
 #ifdef	RNDIS_PM
 	/* power management OIDs (table 4-5) */
 	case OID_PNP_CAPABILITIES:
-		DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
+		DBG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
 
 		/* for now, no wakeup capabilities */
 		length = sizeof (struct NDIS_PNP_CAPABILITIES);
@@ -664,8 +668,8 @@
 		retval = 0;
 		break;
 	case OID_PNP_QUERY_POWER:
-		DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
-				le32_to_cpup((__le32 *) buf) - 1);
+		DBG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
+				le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
 		/* only suspend is a real power state, and
 		 * it can't be entered by OID_PNP_SET_POWER...
 		 */
@@ -701,13 +705,17 @@
 		return -ENOMEM;
 
 	if (buf_len && rndis_debug > 1) {
-		DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
+		DBG("set OID %08x value, len %d:\n", OID, buf_len);
 		for (i = 0; i < buf_len; i += 16) {
-			DEBUG ("%03d: %08x %08x %08x %08x\n", i,
-				le32_to_cpup((__le32 *)&buf[i]),
-				le32_to_cpup((__le32 *)&buf[i + 4]),
-				le32_to_cpup((__le32 *)&buf[i + 8]),
-				le32_to_cpup((__le32 *)&buf[i + 12]));
+			DBG("%03d: %08x %08x %08x %08x\n", i,
+				le32_to_cpu(get_unaligned((__le32 *)
+					&buf[i])),
+				le32_to_cpu(get_unaligned((__le32 *)
+					&buf[i + 4])),
+				le32_to_cpu(get_unaligned((__le32 *)
+					&buf[i + 8])),
+				le32_to_cpu(get_unaligned((__le32 *)
+					&buf[i + 12])));
 		}
 	}
 
@@ -721,8 +729,9 @@
 		 *	PROMISCUOUS, DIRECTED,
 		 *	MULTICAST, ALL_MULTICAST, BROADCAST
 		 */
-		*params->filter = (u16) le32_to_cpup((__le32 *)buf);
-		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+		*params->filter = (u16) le32_to_cpu(get_unaligned(
+				(__le32 *)buf));
+		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
 			__FUNCTION__, *params->filter);
 
 		/* this call has a significant side effect:  it's
@@ -747,7 +756,7 @@
 
 	case OID_802_3_MULTICAST_LIST:
 		/* I think we can ignore this */
-		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+		DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
 		retval = 0;
 		break;
 #if 0
@@ -755,7 +764,7 @@
 		{
 		struct rndis_config_parameter	*param;
 		param = (struct rndis_config_parameter *) buf;
-		DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
+		DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
 			__FUNCTION__,
 			min(cpu_to_le32(param->ParameterNameLength),80),
 			buf + param->ParameterNameOffset);
@@ -771,8 +780,8 @@
 		 * resuming, Windows forces a reset, and then SET_POWER D0.
 		 * FIXME ... then things go batty; Windows wedges itself.
 		 */
-		i = le32_to_cpup((__force __le32 *)buf);
-		DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
+		i = le32_to_cpu(get_unaligned((__le32 *)buf));
+		DBG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
 		switch (i) {
 		case NdisDeviceStateD0:
 			*params->filter = params->saved_filter;
@@ -849,7 +858,7 @@
 	rndis_query_cmplt_type *resp;
 	rndis_resp_t            *r;
 
-	// DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
+	// DBG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
 	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
 
 	/*
@@ -902,15 +911,15 @@
 	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
 #ifdef	VERBOSE
-	DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
-	DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
-	DEBUG("%s: InfoBuffer: ", __FUNCTION__);
+	DBG("%s: Length: %d\n", __FUNCTION__, BufLength);
+	DBG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
+	DBG("%s: InfoBuffer: ", __FUNCTION__);
 
 	for (i = 0; i < BufLength; i++) {
-		DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+		DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
 	}
 
-	DEBUG ("\n");
+	DBG("\n");
 #endif
 
 	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
@@ -1058,8 +1067,8 @@
 		return -ENOMEM;
 
 	tmp = (__le32 *) buf;
-	MsgType   = le32_to_cpup(tmp++);
-	MsgLength = le32_to_cpup(tmp++);
+	MsgType   = le32_to_cpu(get_unaligned(tmp++));
+	MsgLength = le32_to_cpu(get_unaligned(tmp++));
 
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return -ENOTSUPP;
@@ -1073,14 +1082,14 @@
 	/* For USB: responses may take up to 10 seconds */
 	switch (MsgType) {
 	case REMOTE_NDIS_INITIALIZE_MSG:
-		DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+		DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
 			__FUNCTION__ );
 		params->state = RNDIS_INITIALIZED;
 		return  rndis_init_response (configNr,
 					(rndis_init_msg_type *) buf);
 
 	case REMOTE_NDIS_HALT_MSG:
-		DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
+		DBG("%s: REMOTE_NDIS_HALT_MSG\n",
 			__FUNCTION__ );
 		params->state = RNDIS_UNINITIALIZED;
 		if (params->dev) {
@@ -1098,7 +1107,7 @@
 					(rndis_set_msg_type *) buf);
 
 	case REMOTE_NDIS_RESET_MSG:
-		DEBUG("%s: REMOTE_NDIS_RESET_MSG\n",
+		DBG("%s: REMOTE_NDIS_RESET_MSG\n",
 			__FUNCTION__ );
 		return rndis_reset_response (configNr,
 					(rndis_reset_msg_type *) buf);
@@ -1106,7 +1115,7 @@
 	case REMOTE_NDIS_KEEPALIVE_MSG:
 		/* For USB: host does this every 5 seconds */
 		if (rndis_debug > 1)
-			DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+			DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
 				__FUNCTION__ );
 		return rndis_keepalive_response (configNr,
 						 (rndis_keepalive_msg_type *)
@@ -1123,7 +1132,7 @@
 		{
 			unsigned i;
 			for (i = 0; i < MsgLength; i += 16) {
-				DEBUG ("%03d: "
+				DBG("%03d: "
 					" %02x %02x %02x %02x"
 					" %02x %02x %02x %02x"
 					" %02x %02x %02x %02x"
@@ -1154,18 +1163,18 @@
 		if (!rndis_per_dev_params [i].used) {
 			rndis_per_dev_params [i].used = 1;
 			rndis_per_dev_params [i].ack = rndis_control_ack;
-			DEBUG("%s: configNr = %d\n", __FUNCTION__, i);
+			DBG("%s: configNr = %d\n", __FUNCTION__, i);
 			return i;
 		}
 	}
-	DEBUG("failed\n");
+	DBG("failed\n");
 
 	return -1;
 }
 
 void rndis_deregister (int configNr)
 {
-	DEBUG("%s: \n", __FUNCTION__ );
+	DBG("%s: \n", __FUNCTION__ );
 
 	if (configNr >= RNDIS_MAX_CONFIGS) return;
 	rndis_per_dev_params [configNr].used = 0;
@@ -1177,7 +1186,7 @@
 			 struct net_device_stats *stats,
 			 u16 *cdc_filter)
 {
-	DEBUG("%s:\n", __FUNCTION__ );
+	DBG("%s:\n", __FUNCTION__ );
 	if (!dev || !stats) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -1190,7 +1199,7 @@
 
 int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 {
-	DEBUG("%s:\n", __FUNCTION__ );
+	DBG("%s:\n", __FUNCTION__ );
 	if (!vendorDescr) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -1202,7 +1211,7 @@
 
 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
 {
-	DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed);
+	DBG("%s: %u %u\n", __FUNCTION__, medium, speed);
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
 	rndis_per_dev_params [configNr].medium = medium;
@@ -1381,7 +1390,7 @@
 			break;
 		default:
 			if (fl_speed) p->speed = speed;
-			else DEBUG ("%c is not valid\n", c);
+			else DBG("%c is not valid\n", c);
 			break;
 		}
 
@@ -1410,12 +1419,12 @@
 		if (!(rndis_connect_state [i]
 				= create_proc_entry (name, 0660, NULL)))
 		{
-			DEBUG ("%s :remove entries", __FUNCTION__);
+			DBG("%s :remove entries", __FUNCTION__);
 			while (i) {
 				sprintf (name, NAME_TEMPLATE, --i);
 				remove_proc_entry (name, NULL);
 			}
-			DEBUG ("\n");
+			DBG("\n");
 			return -EIO;
 		}
 
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
new file mode 100644
index 0000000..0be80c6
--- /dev/null
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -0,0 +1,2045 @@
+/*
+ * linux/drivers/usb/gadget/s3c2410_udc.c
+ *
+ * Samsung S3C24xx series on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
+ *	Additional cleanups by Ben Dooks <ben-linux@fluff.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/clk.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <linux/usb.h>
+#include <linux/usb_gadget.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/arch/irqs.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-udc.h>
+#include <asm/arch/udc.h>
+
+#include <asm/mach-types.h>
+
+#include "s3c2410_udc.h"
+
+#define DRIVER_DESC	"S3C2410 USB Device Controller Gadget"
+#define DRIVER_VERSION	"29 Apr 2007"
+#define DRIVER_AUTHOR	"Herbert Pötzl <herbert@13thfloor.at>, " \
+			"Arnaud Patard <arnaud.patard@rtp-net.org>"
+
+static const char		gadget_name[] = "s3c2410_udc";
+static const char		driver_desc[] = DRIVER_DESC;
+
+static struct s3c2410_udc	*the_controller;
+static struct clk		*udc_clock;
+static struct clk		*usb_bus_clock;
+static void __iomem		*base_addr;
+static u64			rsrc_start;
+static u64			rsrc_len;
+static struct dentry		*s3c2410_udc_debugfs_root;
+
+static inline u32 udc_read(u32 reg)
+{
+	return readb(base_addr + reg);
+}
+
+static inline void udc_write(u32 value, u32 reg)
+{
+	writeb(value, base_addr + reg);
+}
+
+static inline void udc_writeb(void __iomem *base, u32 value, u32 reg)
+{
+	writeb(value, base + reg);
+}
+
+static struct s3c2410_udc_mach_info *udc_info;
+
+/*************************** DEBUG FUNCTION ***************************/
+#define DEBUG_NORMAL	1
+#define DEBUG_VERBOSE	2
+
+#ifdef CONFIG_USB_S3C2410_DEBUG
+#define USB_S3C2410_DEBUG_LEVEL 0
+
+static uint32_t s3c2410_ticks = 0;
+
+static int dprintk(int level, const char *fmt, ...)
+{
+	static char printk_buf[1024];
+	static long prevticks;
+	static int invocation;
+	va_list args;
+	int len;
+
+	if (level > USB_S3C2410_DEBUG_LEVEL)
+		return 0;
+
+	if (s3c2410_ticks != prevticks) {
+		prevticks = s3c2410_ticks;
+		invocation = 0;
+	}
+
+	len = scnprintf(printk_buf,
+			sizeof(printk_buf), "%1lu.%02d USB: ",
+			prevticks, invocation++);
+
+	va_start(args, fmt);
+	len = vscnprintf(printk_buf+len,
+			sizeof(printk_buf)-len, fmt, args);
+	va_end(args);
+
+	return printk(KERN_DEBUG "%s", printk_buf);
+}
+#else
+static int dprintk(int level, const char *fmt, ...)
+{
+	return 0;
+}
+#endif
+static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
+{
+	u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
+	u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;
+	u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2;
+	u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2;
+
+	addr_reg       = udc_read(S3C2410_UDC_FUNC_ADDR_REG);
+	pwr_reg        = udc_read(S3C2410_UDC_PWR_REG);
+	ep_int_reg     = udc_read(S3C2410_UDC_EP_INT_REG);
+	usb_int_reg    = udc_read(S3C2410_UDC_USB_INT_REG);
+	ep_int_en_reg  = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+	usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG);
+	udc_write(0, S3C2410_UDC_INDEX_REG);
+	ep0_csr        = udc_read(S3C2410_UDC_IN_CSR1_REG);
+	udc_write(1, S3C2410_UDC_INDEX_REG);
+	ep1_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+	ep1_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+	ep1_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+	ep1_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+	udc_write(2, S3C2410_UDC_INDEX_REG);
+	ep2_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+	ep2_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+	ep2_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+	ep2_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+
+	seq_printf(m, "FUNC_ADDR_REG  : 0x%04X\n"
+		 "PWR_REG        : 0x%04X\n"
+		 "EP_INT_REG     : 0x%04X\n"
+		 "USB_INT_REG    : 0x%04X\n"
+		 "EP_INT_EN_REG  : 0x%04X\n"
+		 "USB_INT_EN_REG : 0x%04X\n"
+		 "EP0_CSR        : 0x%04X\n"
+		 "EP1_I_CSR1     : 0x%04X\n"
+		 "EP1_I_CSR2     : 0x%04X\n"
+		 "EP1_O_CSR1     : 0x%04X\n"
+		 "EP1_O_CSR2     : 0x%04X\n"
+		 "EP2_I_CSR1     : 0x%04X\n"
+		 "EP2_I_CSR2     : 0x%04X\n"
+		 "EP2_O_CSR1     : 0x%04X\n"
+		 "EP2_O_CSR2     : 0x%04X\n",
+			addr_reg,pwr_reg,ep_int_reg,usb_int_reg,
+			ep_int_en_reg, usb_int_en_reg, ep0_csr,
+			ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2,
+			ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2
+		);
+
+	return 0;
+}
+
+static int s3c2410_udc_debugfs_fops_open(struct inode *inode,
+					 struct file *file)
+{
+	return single_open(file, s3c2410_udc_debugfs_seq_show, NULL);
+}
+
+static const struct file_operations s3c2410_udc_debugfs_fops = {
+	.open		= s3c2410_udc_debugfs_fops_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.owner		= THIS_MODULE,
+};
+
+/* io macros */
+
+static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base)
+{
+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY,
+			S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base)
+{
+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_clear_ep0_se(void __iomem *base)
+{
+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base)
+{
+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de(void __iomem *base)
+{
+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG);
+}
+
+inline void s3c2410_udc_set_ep0_ss(void __iomem *b)
+{
+	udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base)
+{
+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+
+	udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY
+				| S3C2410_UDC_EP0_CSR_DE),
+			S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base)
+{
+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
+				| S3C2410_UDC_EP0_CSR_SSE),
+			S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base)
+{
+	udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY
+			| S3C2410_UDC_EP0_CSR_DE),
+		S3C2410_UDC_EP0_CSR_REG);
+}
+
+/*------------------------- I/O ----------------------------------*/
+
+/*
+ *	s3c2410_udc_done
+ */
+static void s3c2410_udc_done(struct s3c2410_ep *ep,
+		struct s3c2410_request *req, int status)
+{
+	unsigned halted = ep->halted;
+
+	list_del_init(&req->queue);
+
+	if (likely (req->req.status == -EINPROGRESS))
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	ep->halted = 1;
+	req->req.complete(&ep->ep, &req->req);
+	ep->halted = halted;
+}
+
+static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
+		struct s3c2410_ep *ep, int status)
+{
+	/* Sanity check */
+	if (&ep->queue == NULL)
+		return;
+
+	while (!list_empty (&ep->queue)) {
+		struct s3c2410_request *req;
+		req = list_entry (ep->queue.next, struct s3c2410_request,
+				queue);
+		s3c2410_udc_done(ep, req, status);
+	}
+}
+
+static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev)
+{
+	unsigned i;
+
+	/* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
+	 * fifos, and pending transactions mustn't be continued in any case.
+	 */
+
+	for (i = 1; i < S3C2410_ENDPOINTS; i++)
+		s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED);
+}
+
+static inline int s3c2410_udc_fifo_count_out(void)
+{
+	int tmp;
+
+	tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;
+	tmp |= udc_read(S3C2410_UDC_OUT_FIFO_CNT1_REG);
+	return tmp;
+}
+
+/*
+ *	s3c2410_udc_write_packet
+ */
+static inline int s3c2410_udc_write_packet(int fifo,
+		struct s3c2410_request *req,
+		unsigned max)
+{
+	unsigned len = min(req->req.length - req->req.actual, max);
+	u8 *buf = req->req.buf + req->req.actual;
+
+	prefetch(buf);
+
+	dprintk(DEBUG_VERBOSE, "%s %d %d %d %d\n", __func__,
+		req->req.actual, req->req.length, len, req->req.actual + len);
+
+	req->req.actual += len;
+
+	udelay(5);
+	writesb(base_addr + fifo, buf, len);
+	return len;
+}
+
+/*
+ *	s3c2410_udc_write_fifo
+ *
+ * return:  0 = still running, 1 = completed, negative = errno
+ */
+static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep,
+		struct s3c2410_request *req)
+{
+	unsigned	count;
+	int		is_last;
+	u32		idx;
+	int		fifo_reg;
+	u32		ep_csr;
+
+	idx = ep->bEndpointAddress & 0x7F;
+	switch (idx) {
+	default:
+		idx = 0;
+	case 0:
+		fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
+		break;
+	case 1:
+		fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
+		break;
+	case 2:
+		fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
+		break;
+	case 3:
+		fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
+		break;
+	case 4:
+		fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
+		break;
+	}
+
+	count = s3c2410_udc_write_packet(fifo_reg, req, ep->ep.maxpacket);
+
+	/* last packet is often short (sometimes a zlp) */
+	if (count != ep->ep.maxpacket)
+		is_last = 1;
+	else if (req->req.length != req->req.actual || req->req.zero)
+		is_last = 0;
+	else
+		is_last = 2;
+
+	/* Only ep0 debug messages are interesting */
+	if (idx == 0)
+		dprintk(DEBUG_NORMAL,
+			"Written ep%d %d.%d of %d b [last %d,z %d]\n",
+			idx, count, req->req.actual, req->req.length,
+			is_last, req->req.zero);
+
+	if (is_last) {
+		/* The order is important. It prevents sending 2 packets
+		 * at the same time */
+
+		if (idx == 0) {
+			/* Reset signal => no need to say 'data sent' */
+			if (! (udc_read(S3C2410_UDC_USB_INT_REG)
+					& S3C2410_UDC_USBINT_RESET))
+				s3c2410_udc_set_ep0_de_in(base_addr);
+			ep->dev->ep0state=EP0_IDLE;
+		} else {
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
+					S3C2410_UDC_IN_CSR1_REG);
+		}
+
+		s3c2410_udc_done(ep, req, 0);
+		is_last = 1;
+	} else {
+		if (idx == 0) {
+			/* Reset signal => no need to say 'data sent' */
+			if (! (udc_read(S3C2410_UDC_USB_INT_REG)
+					& S3C2410_UDC_USBINT_RESET))
+				s3c2410_udc_set_ep0_ipr(base_addr);
+		} else {
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
+					S3C2410_UDC_IN_CSR1_REG);
+		}
+	}
+
+	return is_last;
+}
+
+static inline int s3c2410_udc_read_packet(int fifo, u8 *buf,
+		struct s3c2410_request *req, unsigned avail)
+{
+	unsigned len;
+
+	len = min(req->req.length - req->req.actual, avail);
+	req->req.actual += len;
+
+	readsb(fifo + base_addr, buf, len);
+	return len;
+}
+
+/*
+ * return:  0 = still running, 1 = queue empty, negative = errno
+ */
+static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
+				 struct s3c2410_request *req)
+{
+	u8		*buf;
+	u32		ep_csr;
+	unsigned	bufferspace;
+	int		is_last=1;
+	unsigned	avail;
+	int		fifo_count = 0;
+	u32		idx;
+	int		fifo_reg;
+
+	idx = ep->bEndpointAddress & 0x7F;
+
+	switch (idx) {
+	default:
+		idx = 0;
+	case 0:
+		fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
+		break;
+	case 1:
+		fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
+		break;
+	case 2:
+		fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
+		break;
+	case 3:
+		fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
+		break;
+	case 4:
+		fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
+		break;
+	}
+
+	if (!req->req.length)
+		return 1;
+
+	buf = req->req.buf + req->req.actual;
+	bufferspace = req->req.length - req->req.actual;
+	if (!bufferspace) {
+		dprintk(DEBUG_NORMAL, "%s: buffer full!\n", __func__);
+		return -1;
+	}
+
+	udc_write(idx, S3C2410_UDC_INDEX_REG);
+
+	fifo_count = s3c2410_udc_fifo_count_out();
+	dprintk(DEBUG_NORMAL, "%s fifo count : %d\n", __func__, fifo_count);
+
+	if (fifo_count > ep->ep.maxpacket)
+		avail = ep->ep.maxpacket;
+	else
+		avail = fifo_count;
+
+	fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail);
+
+	/* checking this with ep0 is not accurate as we already
+	 * read a control request
+	 **/
+	if (idx != 0 && fifo_count < ep->ep.maxpacket) {
+		is_last = 1;
+		/* overflowed this request?  flush extra data */
+		if (fifo_count != avail)
+			req->req.status = -EOVERFLOW;
+	} else {
+		is_last = (req->req.length <= req->req.actual) ? 1 : 0;
+	}
+
+	udc_write(idx, S3C2410_UDC_INDEX_REG);
+	fifo_count = s3c2410_udc_fifo_count_out();
+
+	/* Only ep0 debug messages are interesting */
+	if (idx == 0)
+		dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n",
+			__func__, fifo_count,is_last);
+
+	if (is_last) {
+		if (idx == 0) {
+			s3c2410_udc_set_ep0_de_out(base_addr);
+			ep->dev->ep0state = EP0_IDLE;
+		} else {
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
+					S3C2410_UDC_OUT_CSR1_REG);
+		}
+
+		s3c2410_udc_done(ep, req, 0);
+	} else {
+		if (idx == 0) {
+			s3c2410_udc_clear_ep0_opr(base_addr);
+		} else {
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
+					S3C2410_UDC_OUT_CSR1_REG);
+		}
+	}
+
+	return is_last;
+}
+
+static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq)
+{
+	unsigned char *outbuf = (unsigned char*)crq;
+	int bytes_read = 0;
+
+	udc_write(0, S3C2410_UDC_INDEX_REG);
+
+	bytes_read = s3c2410_udc_fifo_count_out();
+
+	dprintk(DEBUG_NORMAL, "%s: fifo_count=%d\n", __func__, bytes_read);
+
+	if (bytes_read > sizeof(struct usb_ctrlrequest))
+		bytes_read = sizeof(struct usb_ctrlrequest);
+
+	readsb(S3C2410_UDC_EP0_FIFO_REG + base_addr, outbuf, bytes_read);
+
+	dprintk(DEBUG_VERBOSE, "%s: len=%d %02x:%02x {%x,%x,%x}\n", __func__,
+		bytes_read, crq->bRequest, crq->bRequestType,
+		crq->wValue, crq->wIndex, crq->wLength);
+
+	return bytes_read;
+}
+
+static int s3c2410_udc_get_status(struct s3c2410_udc *dev,
+		struct usb_ctrlrequest *crq)
+{
+	u16 status = 0;
+	u8 ep_num = crq->wIndex & 0x7F;
+	u8 is_in = crq->wIndex & USB_DIR_IN;
+
+	switch (crq->bRequestType & USB_RECIP_MASK) {
+	case USB_RECIP_INTERFACE:
+		break;
+
+	case USB_RECIP_DEVICE:
+		status = dev->devstatus;
+		break;
+
+	case USB_RECIP_ENDPOINT:
+		if (ep_num > 4 || crq->wLength > 2)
+			return 1;
+
+		if (ep_num == 0) {
+			udc_write(0, S3C2410_UDC_INDEX_REG);
+			status = udc_read(S3C2410_UDC_IN_CSR1_REG);
+			status = status & S3C2410_UDC_EP0_CSR_SENDSTL;
+		} else {
+			udc_write(ep_num, S3C2410_UDC_INDEX_REG);
+			if (is_in) {
+				status = udc_read(S3C2410_UDC_IN_CSR1_REG);
+				status = status & S3C2410_UDC_ICSR1_SENDSTL;
+			} else {
+				status = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+				status = status & S3C2410_UDC_OCSR1_SENDSTL;
+			}
+		}
+
+		status = status ? 1 : 0;
+		break;
+
+	default:
+		return 1;
+	}
+
+	/* Seems to be needed to get it working. ouch :( */
+	udelay(5);
+	udc_write(status & 0xFF, S3C2410_UDC_EP0_FIFO_REG);
+	udc_write(status >> 8, S3C2410_UDC_EP0_FIFO_REG);
+	s3c2410_udc_set_ep0_de_in(base_addr);
+
+	return 0;
+}
+/*------------------------- usb state machine -------------------------------*/
+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value);
+
+static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
+					struct s3c2410_ep *ep,
+					struct usb_ctrlrequest *crq,
+					u32 ep0csr)
+{
+	int len, ret, tmp;
+
+	/* start control request? */
+	if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY))
+		return;
+
+	s3c2410_udc_nuke(dev, ep, -EPROTO);
+
+	len = s3c2410_udc_read_fifo_crq(crq);
+	if (len != sizeof(*crq)) {
+		dprintk(DEBUG_NORMAL, "setup begin: fifo READ ERROR"
+			" wanted %d bytes got %d. Stalling out...\n",
+			sizeof(*crq), len);
+		s3c2410_udc_set_ep0_ss(base_addr);
+		return;
+	}
+
+	dprintk(DEBUG_NORMAL, "bRequest = %d bRequestType %d wLength = %d\n",
+		crq->bRequest, crq->bRequestType, crq->wLength);
+
+	/* cope with automagic for some standard requests. */
+	dev->req_std = (crq->bRequestType & USB_TYPE_MASK)
+		== USB_TYPE_STANDARD;
+	dev->req_config = 0;
+	dev->req_pending = 1;
+
+	switch (crq->bRequest) {
+	case USB_REQ_SET_CONFIGURATION:
+		dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ... \n");
+
+		if (crq->bRequestType == USB_RECIP_DEVICE) {
+			dev->req_config = 1;
+			s3c2410_udc_set_ep0_de_out(base_addr);
+		}
+		break;
+
+	case USB_REQ_SET_INTERFACE:
+		dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ... \n");
+
+		if (crq->bRequestType == USB_RECIP_INTERFACE) {
+			dev->req_config = 1;
+			s3c2410_udc_set_ep0_de_out(base_addr);
+		}
+		break;
+
+	case USB_REQ_SET_ADDRESS:
+		dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ... \n");
+
+		if (crq->bRequestType == USB_RECIP_DEVICE) {
+			tmp = crq->wValue & 0x7F;
+			dev->address = tmp;
+			udc_write((tmp | S3C2410_UDC_FUNCADDR_UPDATE),
+					S3C2410_UDC_FUNC_ADDR_REG);
+			s3c2410_udc_set_ep0_de_out(base_addr);
+			return;
+		}
+		break;
+
+	case USB_REQ_GET_STATUS:
+		dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ... \n");
+		s3c2410_udc_clear_ep0_opr(base_addr);
+
+		if (dev->req_std) {
+			if (!s3c2410_udc_get_status(dev, crq)) {
+				return;
+			}
+		}
+		break;
+
+	case USB_REQ_CLEAR_FEATURE:
+		s3c2410_udc_clear_ep0_opr(base_addr);
+
+		if (crq->bRequestType != USB_RECIP_ENDPOINT)
+			break;
+
+		if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
+			break;
+
+		s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 0);
+		s3c2410_udc_set_ep0_de_out(base_addr);
+		return;
+
+	case USB_REQ_SET_FEATURE:
+		s3c2410_udc_clear_ep0_opr(base_addr);
+
+		if (crq->bRequestType != USB_RECIP_ENDPOINT)
+			break;
+
+		if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
+			break;
+
+		s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 1);
+		s3c2410_udc_set_ep0_de_out(base_addr);
+		return;
+
+	default:
+		s3c2410_udc_clear_ep0_opr(base_addr);
+		break;
+	}
+
+	if (crq->bRequestType & USB_DIR_IN)
+		dev->ep0state = EP0_IN_DATA_PHASE;
+	else
+		dev->ep0state = EP0_OUT_DATA_PHASE;
+
+	ret = dev->driver->setup(&dev->gadget, crq);
+	if (ret < 0) {
+		if (dev->req_config) {
+			dprintk(DEBUG_NORMAL, "config change %02x fail %d?\n",
+				crq->bRequest, ret);
+			return;
+		}
+
+		if (ret == -EOPNOTSUPP)
+			dprintk(DEBUG_NORMAL, "Operation not supported\n");
+		else
+			dprintk(DEBUG_NORMAL,
+				"dev->driver->setup failed. (%d)\n", ret);
+
+		udelay(5);
+		s3c2410_udc_set_ep0_ss(base_addr);
+		s3c2410_udc_set_ep0_de_out(base_addr);
+		dev->ep0state = EP0_IDLE;
+		/* deferred i/o == no response yet */
+	} else if (dev->req_pending) {
+		dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n");
+		dev->req_pending=0;
+	}
+
+	dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]);
+}
+
+static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev)
+{
+	u32			ep0csr;
+	struct s3c2410_ep	*ep = &dev->ep[0];
+	struct s3c2410_request	*req;
+	struct usb_ctrlrequest	crq;
+
+	if (list_empty(&ep->queue))
+		req = NULL;
+	else
+		req = list_entry(ep->queue.next, struct s3c2410_request, queue);
+
+	/* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to
+	 * S3C2410_UDC_EP0_CSR_REG when index is zero */
+
+	udc_write(0, S3C2410_UDC_INDEX_REG);
+	ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+
+	dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n",
+		ep0csr, ep0states[dev->ep0state]);
+
+	/* clear stall status */
+	if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) {
+		s3c2410_udc_nuke(dev, ep, -EPIPE);
+		dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n");
+		s3c2410_udc_clear_ep0_sst(base_addr);
+		dev->ep0state = EP0_IDLE;
+		return;
+	}
+
+	/* clear setup end */
+	if (ep0csr & S3C2410_UDC_EP0_CSR_SE) {
+		dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n");
+		s3c2410_udc_nuke(dev, ep, 0);
+		s3c2410_udc_clear_ep0_se(base_addr);
+		dev->ep0state = EP0_IDLE;
+	}
+
+	switch (dev->ep0state) {
+	case EP0_IDLE:
+		s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr);
+		break;
+
+	case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR etc */
+		dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n");
+		if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) {
+			s3c2410_udc_write_fifo(ep, req);
+		}
+		break;
+
+	case EP0_OUT_DATA_PHASE:		/* SET_DESCRIPTOR etc */
+		dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n");
+		if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) {
+			s3c2410_udc_read_fifo(ep,req);
+		}
+		break;
+
+	case EP0_END_XFER:
+		dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n");
+		dev->ep0state = EP0_IDLE;
+		break;
+
+	case EP0_STALL:
+		dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n");
+		dev->ep0state = EP0_IDLE;
+		break;
+	}
+}
+
+/*
+ *	handle_ep - Manage I/O endpoints
+ */
+
+static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
+{
+	struct s3c2410_request	*req;
+	int			is_in = ep->bEndpointAddress & USB_DIR_IN;
+	u32			ep_csr1;
+	u32			idx;
+
+	if (likely (!list_empty(&ep->queue)))
+		req = list_entry(ep->queue.next,
+				struct s3c2410_request, queue);
+	else
+		req = NULL;
+
+	idx = ep->bEndpointAddress & 0x7F;
+
+	if (is_in) {
+		udc_write(idx, S3C2410_UDC_INDEX_REG);
+		ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
+		dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n",
+			idx, ep_csr1, req ? 1 : 0);
+
+		if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
+			dprintk(DEBUG_VERBOSE, "st\n");
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL,
+					S3C2410_UDC_IN_CSR1_REG);
+			return;
+		}
+
+		if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) {
+			s3c2410_udc_write_fifo(ep,req);
+		}
+	} else {
+		udc_write(idx, S3C2410_UDC_INDEX_REG);
+		ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+		dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1);
+
+		if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
+			udc_write(idx, S3C2410_UDC_INDEX_REG);
+			udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL,
+					S3C2410_UDC_OUT_CSR1_REG);
+			return;
+		}
+
+		if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
+			s3c2410_udc_read_fifo(ep,req);
+		}
+	}
+}
+
+#include <asm/arch/regs-irq.h>
+
+/*
+ *	s3c2410_udc_irq - interrupt handler
+ */
+static irqreturn_t s3c2410_udc_irq(int irq, void *_dev)
+{
+	struct s3c2410_udc *dev = _dev;
+	int usb_status;
+	int usbd_status;
+	int pwr_reg;
+	int ep0csr;
+	int i;
+	u32 idx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* Driver connected ? */
+	if (!dev->driver) {
+		/* Clear interrupts */
+		udc_write(udc_read(S3C2410_UDC_USB_INT_REG),
+				S3C2410_UDC_USB_INT_REG);
+		udc_write(udc_read(S3C2410_UDC_EP_INT_REG),
+				S3C2410_UDC_EP_INT_REG);
+	}
+
+	/* Save index */
+	idx = udc_read(S3C2410_UDC_INDEX_REG);
+
+	/* Read status registers */
+	usb_status = udc_read(S3C2410_UDC_USB_INT_REG);
+	usbd_status = udc_read(S3C2410_UDC_EP_INT_REG);
+	pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
+
+	udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+	ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+
+	dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n",
+		usb_status, usbd_status, pwr_reg, ep0csr);
+
+	/*
+	 * Now, handle interrupts. There's two types :
+	 * - Reset, Resume, Suspend coming -> usb_int_reg
+	 * - EP -> ep_int_reg
+	 */
+
+	/* RESET */
+	if (usb_status & S3C2410_UDC_USBINT_RESET) {
+		/* two kind of reset :
+		 * - reset start -> pwr reg = 8
+		 * - reset end   -> pwr reg = 0
+		 **/
+		dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n",
+			ep0csr, pwr_reg);
+
+		dev->gadget.speed = USB_SPEED_UNKNOWN;
+		udc_write(0x00, S3C2410_UDC_INDEX_REG);
+		udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3,
+				S3C2410_UDC_MAXP_REG);
+		dev->address = 0;
+
+		dev->ep0state = EP0_IDLE;
+		dev->gadget.speed = USB_SPEED_FULL;
+
+		/* clear interrupt */
+		udc_write(S3C2410_UDC_USBINT_RESET,
+				S3C2410_UDC_USB_INT_REG);
+
+		udc_write(idx, S3C2410_UDC_INDEX_REG);
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return IRQ_HANDLED;
+	}
+
+	/* RESUME */
+	if (usb_status & S3C2410_UDC_USBINT_RESUME) {
+		dprintk(DEBUG_NORMAL, "USB resume\n");
+
+		/* clear interrupt */
+		udc_write(S3C2410_UDC_USBINT_RESUME,
+				S3C2410_UDC_USB_INT_REG);
+
+		if (dev->gadget.speed != USB_SPEED_UNKNOWN
+				&& dev->driver
+				&& dev->driver->resume)
+			dev->driver->resume(&dev->gadget);
+	}
+
+	/* SUSPEND */
+	if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
+		dprintk(DEBUG_NORMAL, "USB suspend\n");
+
+		/* clear interrupt */
+		udc_write(S3C2410_UDC_USBINT_SUSPEND,
+				S3C2410_UDC_USB_INT_REG);
+
+		if (dev->gadget.speed != USB_SPEED_UNKNOWN
+				&& dev->driver
+				&& dev->driver->suspend)
+			dev->driver->suspend(&dev->gadget);
+
+		dev->ep0state = EP0_IDLE;
+	}
+
+	/* EP */
+	/* control traffic */
+	/* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready
+	 * generate an interrupt
+	 */
+	if (usbd_status & S3C2410_UDC_INT_EP0) {
+		dprintk(DEBUG_VERBOSE, "USB ep0 irq\n");
+		/* Clear the interrupt bit by setting it to 1 */
+		udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
+		s3c2410_udc_handle_ep0(dev);
+	}
+
+	/* endpoint data transfers */
+	for (i = 1; i < S3C2410_ENDPOINTS; i++) {
+		u32 tmp = 1 << i;
+		if (usbd_status & tmp) {
+			dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i);
+
+			/* Clear the interrupt bit by setting it to 1 */
+			udc_write(tmp, S3C2410_UDC_EP_INT_REG);
+			s3c2410_udc_handle_ep(&dev->ep[i]);
+		}
+	}
+
+	dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", irq);
+
+	/* Restore old index */
+	udc_write(idx, S3C2410_UDC_INDEX_REG);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return IRQ_HANDLED;
+}
+/*------------------------- s3c2410_ep_ops ----------------------------------*/
+
+static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep)
+{
+	return container_of(ep, struct s3c2410_ep, ep);
+}
+
+static inline struct s3c2410_udc *to_s3c2410_udc(struct usb_gadget *gadget)
+{
+	return container_of(gadget, struct s3c2410_udc, gadget);
+}
+
+static inline struct s3c2410_request *to_s3c2410_req(struct usb_request *req)
+{
+	return container_of(req, struct s3c2410_request, req);
+}
+
+/*
+ *	s3c2410_udc_ep_enable
+ */
+static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
+				 const struct usb_endpoint_descriptor *desc)
+{
+	struct s3c2410_udc	*dev;
+	struct s3c2410_ep	*ep;
+	u32			max, tmp;
+	unsigned long		flags;
+	u32			csr1,csr2;
+	u32			int_en_reg;
+
+	ep = to_s3c2410_ep(_ep);
+
+	if (!_ep || !desc || ep->desc
+			|| _ep->name == ep0name
+			|| desc->bDescriptorType != USB_DT_ENDPOINT)
+		return -EINVAL;
+
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff;
+
+	local_irq_save (flags);
+	_ep->maxpacket = max & 0x7ff;
+	ep->desc = desc;
+	ep->halted = 0;
+	ep->bEndpointAddress = desc->bEndpointAddress;
+
+	/* set max packet */
+	udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+	udc_write(max >> 3, S3C2410_UDC_MAXP_REG);
+
+	/* set type, direction, address; reset fifo counters */
+	if (desc->bEndpointAddress & USB_DIR_IN) {
+		csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT;
+		csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN;
+
+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+		udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+		udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
+	} else {
+		/* don't flush in fifo or it will cause endpoint interrupt */
+		csr1 = S3C2410_UDC_ICSR1_CLRDT;
+		csr2 = S3C2410_UDC_ICSR2_DMAIEN;
+
+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+		udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+		udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
+
+		csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT;
+		csr2 = S3C2410_UDC_OCSR2_DMAIEN;
+
+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+		udc_write(csr1, S3C2410_UDC_OUT_CSR1_REG);
+		udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+		udc_write(csr2, S3C2410_UDC_OUT_CSR2_REG);
+	}
+
+	/* enable irqs */
+	int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+	udc_write(int_en_reg | (1 << ep->num), S3C2410_UDC_EP_INT_EN_REG);
+
+	/* print some debug message */
+	tmp = desc->bEndpointAddress;
+	dprintk (DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n",
+		 _ep->name,ep->num, tmp,
+		 desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max);
+
+	local_irq_restore (flags);
+	s3c2410_udc_set_halt(_ep, 0);
+
+	return 0;
+}
+
+/*
+ * s3c2410_udc_ep_disable
+ */
+static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
+{
+	struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
+	unsigned long flags;
+	u32 int_en_reg;
+
+	if (!_ep || !ep->desc) {
+		dprintk(DEBUG_NORMAL, "%s not enabled\n",
+			_ep ? ep->ep.name : NULL);
+		return -EINVAL;
+	}
+
+	local_irq_save(flags);
+
+	dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
+
+	ep->desc = NULL;
+	ep->halted = 1;
+
+	s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
+
+	/* disable irqs */
+	int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+	udc_write(int_en_reg & ~(1<<ep->num), S3C2410_UDC_EP_INT_EN_REG);
+
+	local_irq_restore(flags);
+
+	dprintk(DEBUG_NORMAL, "%s disabled\n", _ep->name);
+
+	return 0;
+}
+
+/*
+ * s3c2410_udc_alloc_request
+ */
+static struct usb_request *
+s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags)
+{
+	struct s3c2410_request *req;
+
+	dprintk(DEBUG_VERBOSE,"%s(%p,%d)\n", __func__, _ep, mem_flags);
+
+	if (!_ep)
+		return NULL;
+
+	req = kzalloc (sizeof(struct s3c2410_request), mem_flags);
+	if (!req)
+		return NULL;
+
+	INIT_LIST_HEAD (&req->queue);
+	return &req->req;
+}
+
+/*
+ * s3c2410_udc_free_request
+ */
+static void
+s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct s3c2410_ep	*ep = to_s3c2410_ep(_ep);
+	struct s3c2410_request	*req = to_s3c2410_req(_req);
+
+	dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
+
+	if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
+		return;
+
+	WARN_ON (!list_empty (&req->queue));
+	kfree(req);
+}
+
+/*
+ *	s3c2410_udc_queue
+ */
+static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
+		gfp_t gfp_flags)
+{
+	struct s3c2410_request	*req = to_s3c2410_req(_req);
+	struct s3c2410_ep	*ep = to_s3c2410_ep(_ep);
+	struct s3c2410_udc	*dev;
+	u32			ep_csr = 0;
+	int			fifo_count = 0;
+	unsigned long		flags;
+
+	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+		dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
+		return -EINVAL;
+	}
+
+	dev = ep->dev;
+	if (unlikely (!dev->driver
+			|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+		return -ESHUTDOWN;
+	}
+
+	local_irq_save (flags);
+
+	if (unlikely(!_req || !_req->complete
+			|| !_req->buf || !list_empty(&req->queue))) {
+		if (!_req)
+			dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__);
+		else {
+			dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n",
+				__func__, !_req->complete,!_req->buf,
+				!list_empty(&req->queue));
+		}
+
+		local_irq_restore(flags);
+		return -EINVAL;
+	}
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n",
+		 __func__, ep->bEndpointAddress, _req->length);
+
+	if (ep->bEndpointAddress) {
+		udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG);
+
+		ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
+				? S3C2410_UDC_IN_CSR1_REG
+				: S3C2410_UDC_OUT_CSR1_REG);
+		fifo_count = s3c2410_udc_fifo_count_out();
+	} else {
+		udc_write(0, S3C2410_UDC_INDEX_REG);
+		ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+		fifo_count = s3c2410_udc_fifo_count_out();
+	}
+
+	/* kickstart this i/o queue? */
+	if (list_empty(&ep->queue) && !ep->halted) {
+		if (ep->bEndpointAddress == 0 /* ep0 */) {
+			switch (dev->ep0state) {
+			case EP0_IN_DATA_PHASE:
+				if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY)
+						&& s3c2410_udc_write_fifo(ep,
+							req)) {
+					dev->ep0state = EP0_IDLE;
+					req = NULL;
+				}
+				break;
+
+			case EP0_OUT_DATA_PHASE:
+				if ((!_req->length)
+					|| ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
+						&& s3c2410_udc_read_fifo(ep,
+							req))) {
+					dev->ep0state = EP0_IDLE;
+					req = NULL;
+				}
+				break;
+
+			default:
+				local_irq_restore(flags);
+				return -EL2HLT;
+			}
+		} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
+				&& (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY))
+				&& s3c2410_udc_write_fifo(ep, req)) {
+			req = NULL;
+		} else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
+				&& fifo_count
+				&& s3c2410_udc_read_fifo(ep, req)) {
+			req = NULL;
+		}
+	}
+
+	/* pio or dma irq handler advances the queue. */
+	if (likely (req != 0))
+		list_add_tail(&req->queue, &ep->queue);
+
+	local_irq_restore(flags);
+
+	dprintk(DEBUG_VERBOSE, "%s ok\n", __func__);
+	return 0;
+}
+
+/*
+ *	s3c2410_udc_dequeue
+ */
+static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct s3c2410_ep	*ep = to_s3c2410_ep(_ep);
+	struct s3c2410_udc	*udc;
+	int			retval = -EINVAL;
+	unsigned long		flags;
+	struct s3c2410_request	*req = NULL;
+
+	dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
+
+	if (!the_controller->driver)
+		return -ESHUTDOWN;
+
+	if (!_ep || !_req)
+		return retval;
+
+	udc = to_s3c2410_udc(ep->gadget);
+
+	local_irq_save (flags);
+
+	list_for_each_entry (req, &ep->queue, queue) {
+		if (&req->req == _req) {
+			list_del_init (&req->queue);
+			_req->status = -ECONNRESET;
+			retval = 0;
+			break;
+		}
+	}
+
+	if (retval == 0) {
+		dprintk(DEBUG_VERBOSE,
+			"dequeued req %p from %s, len %d buf %p\n",
+			req, _ep->name, _req->length, _req->buf);
+
+		s3c2410_udc_done(ep, req, -ECONNRESET);
+	}
+
+	local_irq_restore (flags);
+	return retval;
+}
+
+/*
+ * s3c2410_udc_set_halt
+ */
+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
+{
+	struct s3c2410_ep	*ep = to_s3c2410_ep(_ep);
+	u32			ep_csr = 0;
+	unsigned long		flags;
+	u32			idx;
+
+	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+		dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__);
+		return -EINVAL;
+	}
+
+	local_irq_save (flags);
+
+	idx = ep->bEndpointAddress & 0x7F;
+
+	if (idx == 0) {
+		s3c2410_udc_set_ep0_ss(base_addr);
+		s3c2410_udc_set_ep0_de_out(base_addr);
+	} else {
+		udc_write(idx, S3C2410_UDC_INDEX_REG);
+		ep_csr = udc_read((ep->bEndpointAddress &USB_DIR_IN)
+				? S3C2410_UDC_IN_CSR1_REG
+				: S3C2410_UDC_OUT_CSR1_REG);
+
+		if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
+			if (value)
+				udc_write(ep_csr | S3C2410_UDC_ICSR1_SENDSTL,
+					S3C2410_UDC_IN_CSR1_REG);
+			else {
+				ep_csr &= ~S3C2410_UDC_ICSR1_SENDSTL;
+				udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
+				ep_csr |= S3C2410_UDC_ICSR1_CLRDT;
+				udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
+			}
+		} else {
+			if (value)
+				udc_write(ep_csr | S3C2410_UDC_OCSR1_SENDSTL,
+					S3C2410_UDC_OUT_CSR1_REG);
+			else {
+				ep_csr &= ~S3C2410_UDC_OCSR1_SENDSTL;
+				udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
+				ep_csr |= S3C2410_UDC_OCSR1_CLRDT;
+				udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
+			}
+		}
+	}
+
+	ep->halted = value ? 1 : 0;
+	local_irq_restore (flags);
+
+	return 0;
+}
+
+static const struct usb_ep_ops s3c2410_ep_ops = {
+	.enable		= s3c2410_udc_ep_enable,
+	.disable	= s3c2410_udc_ep_disable,
+
+	.alloc_request	= s3c2410_udc_alloc_request,
+	.free_request	= s3c2410_udc_free_request,
+
+	.queue		= s3c2410_udc_queue,
+	.dequeue	= s3c2410_udc_dequeue,
+
+	.set_halt	= s3c2410_udc_set_halt,
+};
+
+/*------------------------- usb_gadget_ops ----------------------------------*/
+
+/*
+ *	s3c2410_udc_get_frame
+ */
+static int s3c2410_udc_get_frame(struct usb_gadget *_gadget)
+{
+	int tmp;
+
+	dprintk(DEBUG_VERBOSE, "%s()\n", __func__);
+
+	tmp = udc_read(S3C2410_UDC_FRAME_NUM2_REG) << 8;
+	tmp |= udc_read(S3C2410_UDC_FRAME_NUM1_REG);
+	return tmp;
+}
+
+/*
+ *	s3c2410_udc_wakeup
+ */
+static int s3c2410_udc_wakeup(struct usb_gadget *_gadget)
+{
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+	return 0;
+}
+
+/*
+ *	s3c2410_udc_set_selfpowered
+ */
+static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value)
+{
+	struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+	if (value)
+		udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
+	else
+		udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+
+	return 0;
+}
+
+static void s3c2410_udc_disable(struct s3c2410_udc *dev);
+static void s3c2410_udc_enable(struct s3c2410_udc *dev);
+
+static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
+{
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+	if (udc_info && udc_info->udc_command) {
+		if (is_on)
+			s3c2410_udc_enable(udc);
+		else {
+			if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+				if (udc->driver && udc->driver->disconnect)
+					udc->driver->disconnect(&udc->gadget);
+
+			}
+			s3c2410_udc_disable(udc);
+		}
+	}
+	else
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+static int s3c2410_udc_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+	struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+	udc->vbus = (is_active != 0);
+	s3c2410_udc_set_pullup(udc, is_active);
+	return 0;
+}
+
+static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+	s3c2410_udc_set_pullup(udc, is_on ? 0 : 1);
+	return 0;
+}
+
+static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
+{
+	struct s3c2410_udc	*dev = _dev;
+	unsigned int		value;
+
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+	value = s3c2410_gpio_getpin(udc_info->vbus_pin);
+
+	if (udc_info->vbus_pin_inverted)
+		value = !value;
+
+	if (value != dev->vbus)
+		s3c2410_udc_vbus_session(&dev->gadget, value);
+
+	return IRQ_HANDLED;
+}
+
+static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
+{
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+	if (udc_info && udc_info->vbus_draw) {
+		udc_info->vbus_draw(ma);
+		return 0;
+	}
+
+	return -ENOTSUPP;
+}
+
+static const struct usb_gadget_ops s3c2410_ops = {
+	.get_frame		= s3c2410_udc_get_frame,
+	.wakeup			= s3c2410_udc_wakeup,
+	.set_selfpowered	= s3c2410_udc_set_selfpowered,
+	.pullup			= s3c2410_udc_pullup,
+	.vbus_session		= s3c2410_udc_vbus_session,
+	.vbus_draw		= s3c2410_vbus_draw,
+};
+
+/*------------------------- gadget driver handling---------------------------*/
+/*
+ * s3c2410_udc_disable
+ */
+static void s3c2410_udc_disable(struct s3c2410_udc *dev)
+{
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+	/* Disable all interrupts */
+	udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG);
+	udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG);
+
+	/* Clear the interrupt registers */
+	udc_write(S3C2410_UDC_USBINT_RESET
+				| S3C2410_UDC_USBINT_RESUME
+				| S3C2410_UDC_USBINT_SUSPEND,
+			S3C2410_UDC_USB_INT_REG);
+
+	udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
+
+	/* Good bye, cruel world */
+	if (udc_info && udc_info->udc_command)
+		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+
+	/* Set speed to unknown */
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+}
+
+/*
+ * s3c2410_udc_reinit
+ */
+static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
+{
+	u32 i;
+
+	/* device/ep0 records init */
+	INIT_LIST_HEAD (&dev->gadget.ep_list);
+	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
+	dev->ep0state = EP0_IDLE;
+
+	for (i = 0; i < S3C2410_ENDPOINTS; i++) {
+		struct s3c2410_ep *ep = &dev->ep[i];
+
+		if (i != 0)
+			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
+
+		ep->dev = dev;
+		ep->desc = NULL;
+		ep->halted = 0;
+		INIT_LIST_HEAD (&ep->queue);
+	}
+}
+
+/*
+ * s3c2410_udc_enable
+ */
+static void s3c2410_udc_enable(struct s3c2410_udc *dev)
+{
+	int i;
+
+	dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n");
+
+	/* dev->gadget.speed = USB_SPEED_UNKNOWN; */
+	dev->gadget.speed = USB_SPEED_FULL;
+
+	/* Set MAXP for all endpoints */
+	for (i = 0; i < S3C2410_ENDPOINTS; i++) {
+		udc_write(i, S3C2410_UDC_INDEX_REG);
+		udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3,
+				S3C2410_UDC_MAXP_REG);
+	}
+
+	/* Set default power state */
+	udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);
+
+	/* Enable reset and suspend interrupt interrupts */
+	udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND,
+			S3C2410_UDC_USB_INT_EN_REG);
+
+	/* Enable ep0 interrupt */
+	udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);
+
+	/* time to say "hello, world" */
+	if (udc_info && udc_info->udc_command)
+		udc_info->udc_command(S3C2410_UDC_P_ENABLE);
+}
+
+/*
+ *	usb_gadget_register_driver
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	struct s3c2410_udc *udc = the_controller;
+	int		retval;
+
+	dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",
+		driver->driver.name);
+
+	/* Sanity checks */
+	if (!udc)
+		return -ENODEV;
+
+	if (udc->driver)
+		return -EBUSY;
+
+	if (!driver->bind || !driver->setup
+			|| driver->speed != USB_SPEED_FULL) {
+		printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
+			driver->bind, driver->setup, driver->speed);
+		return -EINVAL;
+	}
+#if defined(MODULE)
+	if (!driver->unbind) {
+		printk(KERN_ERR "Invalid driver: no unbind method\n");
+		return -EINVAL;
+	}
+#endif
+
+	/* Hook the driver */
+	udc->driver = driver;
+	udc->gadget.dev.driver = &driver->driver;
+
+	/* Bind the driver */
+	if ((retval = device_add(&udc->gadget.dev)) != 0) {
+		printk(KERN_ERR "Error in device_add() : %d\n",retval);
+		goto register_error;
+	}
+
+	dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
+		driver->driver.name);
+
+	if ((retval = driver->bind (&udc->gadget)) != 0) {
+		device_del(&udc->gadget.dev);
+		goto register_error;
+	}
+
+	/* Enable udc */
+	s3c2410_udc_enable(udc);
+
+	return 0;
+
+register_error:
+	udc->driver = NULL;
+	udc->gadget.dev.driver = NULL;
+	return retval;
+}
+
+/*
+ *	usb_gadget_unregister_driver
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct s3c2410_udc *udc = the_controller;
+
+	if (!udc)
+		return -ENODEV;
+
+	if (!driver || driver != udc->driver || !driver->unbind)
+		return -EINVAL;
+
+	dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+		driver->driver.name);
+
+	if (driver->disconnect)
+		driver->disconnect(&udc->gadget);
+
+	device_del(&udc->gadget.dev);
+	udc->driver = NULL;
+
+	/* Disable udc */
+	s3c2410_udc_disable(udc);
+
+	return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+static struct s3c2410_udc memory = {
+	.gadget = {
+		.ops		= &s3c2410_ops,
+		.ep0		= &memory.ep[0].ep,
+		.name		= gadget_name,
+		.dev = {
+			.bus_id		= "gadget",
+		},
+	},
+
+	/* control endpoint */
+	.ep[0] = {
+		.num		= 0,
+		.ep = {
+			.name		= ep0name,
+			.ops		= &s3c2410_ep_ops,
+			.maxpacket	= EP0_FIFO_SIZE,
+		},
+		.dev		= &memory,
+	},
+
+	/* first group of endpoints */
+	.ep[1] = {
+		.num		= 1,
+		.ep = {
+			.name		= "ep1-bulk",
+			.ops		= &s3c2410_ep_ops,
+			.maxpacket	= EP_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= EP_FIFO_SIZE,
+		.bEndpointAddress = 1,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+	},
+	.ep[2] = {
+		.num		= 2,
+		.ep = {
+			.name		= "ep2-bulk",
+			.ops		= &s3c2410_ep_ops,
+			.maxpacket	= EP_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= EP_FIFO_SIZE,
+		.bEndpointAddress = 2,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+	},
+	.ep[3] = {
+		.num		= 3,
+		.ep = {
+			.name		= "ep3-bulk",
+			.ops		= &s3c2410_ep_ops,
+			.maxpacket	= EP_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= EP_FIFO_SIZE,
+		.bEndpointAddress = 3,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+	},
+	.ep[4] = {
+		.num		= 4,
+		.ep = {
+			.name		= "ep4-bulk",
+			.ops		= &s3c2410_ep_ops,
+			.maxpacket	= EP_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= EP_FIFO_SIZE,
+		.bEndpointAddress = 4,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+	}
+
+};
+
+/*
+ *	probe - binds to the platform device
+ */
+static int s3c2410_udc_probe(struct platform_device *pdev)
+{
+	struct s3c2410_udc *udc = &memory;
+	struct device *dev = &pdev->dev;
+	int retval;
+	unsigned int irq;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	usb_bus_clock = clk_get(NULL, "usb-bus-gadget");
+	if (IS_ERR(usb_bus_clock)) {
+		dev_err(dev, "failed to get usb bus clock source\n");
+		return PTR_ERR(usb_bus_clock);
+	}
+
+	clk_enable(usb_bus_clock);
+
+	udc_clock = clk_get(NULL, "usb-device");
+	if (IS_ERR(udc_clock)) {
+		dev_err(dev, "failed to get udc clock source\n");
+		return PTR_ERR(udc_clock);
+	}
+
+	clk_enable(udc_clock);
+
+	mdelay(10);
+
+	dev_dbg(dev, "got and enabled clocks\n");
+
+	if (strncmp(pdev->name, "s3c2440", 7) == 0) {
+		dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n");
+		memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE;
+		memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE;
+		memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE;
+		memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE;
+	}
+
+	spin_lock_init (&udc->lock);
+	udc_info = pdev->dev.platform_data;
+
+	rsrc_start = S3C2410_PA_USBDEV;
+	rsrc_len   = S3C24XX_SZ_USBDEV;
+
+	if (!request_mem_region(rsrc_start, rsrc_len, gadget_name))
+		return -EBUSY;
+
+	base_addr = ioremap(rsrc_start, rsrc_len);
+	if (!base_addr) {
+		retval = -ENOMEM;
+		goto err_mem;
+	}
+
+	device_initialize(&udc->gadget.dev);
+	udc->gadget.dev.parent = &pdev->dev;
+	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
+
+	the_controller = udc;
+	platform_set_drvdata(pdev, udc);
+
+	s3c2410_udc_disable(udc);
+	s3c2410_udc_reinit(udc);
+
+	/* irq setup after old hardware state is cleaned up */
+	retval = request_irq(IRQ_USBD, s3c2410_udc_irq,
+			IRQF_DISABLED, gadget_name, udc);
+
+	if (retval != 0) {
+		dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval);
+		retval = -EBUSY;
+		goto err_map;
+	}
+
+	dev_dbg(dev, "got irq %i\n", IRQ_USBD);
+
+	if (udc_info && udc_info->vbus_pin > 0) {
+		irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
+		retval = request_irq(irq, s3c2410_udc_vbus_irq,
+				IRQF_DISABLED | IRQF_TRIGGER_RISING
+				| IRQF_TRIGGER_FALLING,
+				gadget_name, udc);
+
+		if (retval != 0) {
+			dev_err(dev, "can't get vbus irq %i, err %d\n",
+				irq, retval);
+			retval = -EBUSY;
+			goto err_int;
+		}
+
+		dev_dbg(dev, "got irq %i\n", irq);
+	} else {
+		udc->vbus = 1;
+	}
+
+	if (s3c2410_udc_debugfs_root) {
+		udc->regs_info = debugfs_create_file("registers", S_IRUGO,
+				s3c2410_udc_debugfs_root,
+				udc, &s3c2410_udc_debugfs_fops);
+		if (IS_ERR(udc->regs_info)) {
+			dev_warn(dev, "debugfs file creation failed %ld\n",
+				 PTR_ERR(udc->regs_info));
+			udc->regs_info = NULL;
+		}
+	}
+
+	dev_dbg(dev, "probe ok\n");
+
+	return 0;
+
+err_int:
+	free_irq(IRQ_USBD, udc);
+err_map:
+	iounmap(base_addr);
+err_mem:
+	release_mem_region(rsrc_start, rsrc_len);
+
+	return retval;
+}
+
+/*
+ *	s3c2410_udc_remove
+ */
+static int s3c2410_udc_remove(struct platform_device *pdev)
+{
+	struct s3c2410_udc *udc = platform_get_drvdata(pdev);
+	unsigned int irq;
+
+	dev_dbg(&pdev->dev, "%s()\n", __func__);
+	if (udc->driver)
+		return -EBUSY;
+
+	debugfs_remove(udc->regs_info);
+
+	if (udc_info && udc_info->vbus_pin > 0) {
+		irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
+		free_irq(irq, udc);
+	}
+
+	free_irq(IRQ_USBD, udc);
+
+	iounmap(base_addr);
+	release_mem_region(rsrc_start, rsrc_len);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (!IS_ERR(udc_clock) && udc_clock != NULL) {
+		clk_disable(udc_clock);
+		clk_put(udc_clock);
+		udc_clock = NULL;
+	}
+
+	if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
+		clk_disable(usb_bus_clock);
+		clk_put(usb_bus_clock);
+		usb_bus_clock = NULL;
+	}
+
+	dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
+{
+	if (udc_info && udc_info->udc_command)
+		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+
+	return 0;
+}
+
+static int s3c2410_udc_resume(struct platform_device *pdev)
+{
+	if (udc_info && udc_info->udc_command)
+		udc_info->udc_command(S3C2410_UDC_P_ENABLE);
+
+	return 0;
+}
+#else
+#define s3c2410_udc_suspend	NULL
+#define s3c2410_udc_resume	NULL
+#endif
+
+static struct platform_driver udc_driver_2410 = {
+	.driver		= {
+		.name	= "s3c2410-usbgadget",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= s3c2410_udc_probe,
+	.remove		= s3c2410_udc_remove,
+	.suspend	= s3c2410_udc_suspend,
+	.resume		= s3c2410_udc_resume,
+};
+
+static struct platform_driver udc_driver_2440 = {
+	.driver		= {
+		.name	= "s3c2440-usbgadget",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= s3c2410_udc_probe,
+	.remove		= s3c2410_udc_remove,
+	.suspend	= s3c2410_udc_suspend,
+	.resume		= s3c2410_udc_resume,
+};
+
+static int __init udc_init(void)
+{
+	int retval;
+
+	dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
+
+	s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
+	if (IS_ERR(s3c2410_udc_debugfs_root)) {
+		printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
+			gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
+		s3c2410_udc_debugfs_root = NULL;
+	}
+
+	retval = platform_driver_register(&udc_driver_2410);
+	if (retval)
+		goto err;
+
+	retval = platform_driver_register(&udc_driver_2440);
+	if (retval)
+		goto err;
+
+	return 0;
+
+err:
+	debugfs_remove(s3c2410_udc_debugfs_root);
+	return retval;
+}
+
+static void __exit udc_exit(void)
+{
+	platform_driver_unregister(&udc_driver_2410);
+	platform_driver_unregister(&udc_driver_2440);
+	debugfs_remove(s3c2410_udc_debugfs_root);
+}
+
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+module_init(udc_init);
+module_exit(udc_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h
new file mode 100644
index 0000000..9e0bece
--- /dev/null
+++ b/drivers/usb/gadget/s3c2410_udc.h
@@ -0,0 +1,110 @@
+/*
+ * linux/drivers/usb/gadget/s3c2410_udc.h
+ * Samsung on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
+ *	Additional cleanups by Ben Dooks <ben-linux@fluff.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _S3C2410_UDC_H
+#define _S3C2410_UDC_H
+
+struct s3c2410_ep {
+	struct list_head		queue;
+	unsigned long			last_io;	/* jiffies timestamp */
+	struct usb_gadget		*gadget;
+	struct s3c2410_udc		*dev;
+	const struct usb_endpoint_descriptor *desc;
+	struct usb_ep			ep;
+	u8				num;
+
+	unsigned short			fifo_size;
+	u8				bEndpointAddress;
+	u8				bmAttributes;
+
+	unsigned			halted : 1;
+	unsigned			already_seen : 1;
+	unsigned			setup_stage : 1;
+};
+
+
+/* Warning : ep0 has a fifo of 16 bytes */
+/* Don't try to set 32 or 64            */
+/* also testusb 14 fails  wit 16 but is */
+/* fine with 8                          */
+#define EP0_FIFO_SIZE		 8
+#define EP_FIFO_SIZE		64
+#define DEFAULT_POWER_STATE	0x00
+
+#define S3C2440_EP_FIFO_SIZE	128
+
+static const char ep0name [] = "ep0";
+
+static const char *const ep_name[] = {
+	ep0name,                                /* everyone has ep0 */
+	/* s3c2410 four bidirectional bulk endpoints */
+	"ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk",
+};
+
+#define S3C2410_ENDPOINTS       ARRAY_SIZE(ep_name)
+
+struct s3c2410_request {
+	struct list_head		queue;		/* ep's requests */
+	struct usb_request		req;
+};
+
+enum ep0_state {
+        EP0_IDLE,
+        EP0_IN_DATA_PHASE,
+        EP0_OUT_DATA_PHASE,
+        EP0_END_XFER,
+        EP0_STALL,
+};
+
+static const char *ep0states[]= {
+        "EP0_IDLE",
+        "EP0_IN_DATA_PHASE",
+        "EP0_OUT_DATA_PHASE",
+        "EP0_END_XFER",
+        "EP0_STALL",
+};
+
+struct s3c2410_udc {
+	spinlock_t			lock;
+
+	struct s3c2410_ep		ep[S3C2410_ENDPOINTS];
+	int				address;
+	struct usb_gadget		gadget;
+	struct usb_gadget_driver	*driver;
+	struct s3c2410_request		fifo_req;
+	u8				fifo_buf[EP_FIFO_SIZE];
+	u16				devstatus;
+
+	u32				port_status;
+	int				ep0state;
+
+	unsigned			got_irq : 1;
+
+	unsigned			req_std : 1;
+	unsigned			req_config : 1;
+	unsigned			req_pending : 1;
+	u8				vbus;
+	struct dentry			*regs_info;
+};
+
+#endif
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index f847c34..dd33ff0 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -2215,7 +2215,7 @@
  *
  * Free the buffer and all associated memory.
  */
-void gs_buf_free(struct gs_buf *gb)
+static void gs_buf_free(struct gs_buf *gb)
 {
 	if (gb) {
 		kfree(gb->buf_buf);
@@ -2228,7 +2228,7 @@
  *
  * Clear out all data in the circular buffer.
  */
-void gs_buf_clear(struct gs_buf *gb)
+static void gs_buf_clear(struct gs_buf *gb)
 {
 	if (gb != NULL)
 		gb->buf_get = gb->buf_put;
@@ -2241,7 +2241,7 @@
  * Return the number of bytes of data available in the circular
  * buffer.
  */
-unsigned int gs_buf_data_avail(struct gs_buf *gb)
+static unsigned int gs_buf_data_avail(struct gs_buf *gb)
 {
 	if (gb != NULL)
 		return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
@@ -2255,7 +2255,7 @@
  * Return the number of bytes of space available in the circular
  * buffer.
  */
-unsigned int gs_buf_space_avail(struct gs_buf *gb)
+static unsigned int gs_buf_space_avail(struct gs_buf *gb)
 {
 	if (gb != NULL)
 		return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
@@ -2271,7 +2271,8 @@
  *
  * Return the number of bytes copied.
  */
-unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
+static unsigned int
+gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
 {
 	unsigned int len;
 
@@ -2309,7 +2310,8 @@
  *
  * Return the number of bytes copied.
  */
-unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
+static unsigned int
+gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
 {
 	unsigned int len;
 
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 7078374..a2e6e3fc 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -481,8 +481,7 @@
 	req = usb_ep_alloc_request (ep, GFP_ATOMIC);
 	if (req) {
 		req->length = length;
-		req->buf = usb_ep_alloc_buffer (ep, length,
-				&req->dma, GFP_ATOMIC);
+		req->buf = kmalloc(length, GFP_ATOMIC);
 		if (!req->buf) {
 			usb_ep_free_request (ep, req);
 			req = NULL;
@@ -493,8 +492,7 @@
 
 static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
 {
-	if (req->buf)
-		usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
+	kfree(req->buf);
 	usb_ep_free_request (ep, req);
 }
 
@@ -1199,8 +1197,7 @@
 	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
 	if (!dev->req)
 		goto enomem;
-	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
-				&dev->req->dma, GFP_KERNEL);
+	dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
 	if (!dev->req->buf)
 		goto enomem;
 
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 6271187..2f52982 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -69,8 +69,20 @@
 
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
-	depends on USB_EHCI_HCD
-	default n
+	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX)
+	default y
+
+config USB_EHCI_BIG_ENDIAN_DESC
+	bool
+	depends on USB_EHCI_HCD && 440EPX
+	default y
+
+config USB_EHCI_FSL
+	bool
+	select USB_EHCI_ROOT_HUB_TT
+	default y if MPC834x || PPC_MPC831x
+	---help---
+	  Variation of ARC USB block used in some Freescale chips.
 
 config USB_ISP116X_HCD
 	tristate "ISP116X HCD support"
@@ -224,3 +236,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called "sl811_cs".
 
+config USB_R8A66597_HCD
+	tristate "R8A66597 HCD suppoort"
+	depends on USB
+	help
+	  The R8A66597 is a USB 2.0 host and peripheral controller.
+
+	  Enable this option if your board has this chip, and you want
+	  to use it as a host controller.  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called r8a66597-hcd.
+
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 2ff396bd..bb8e9d4 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -15,3 +15,5 @@
 obj-$(CONFIG_USB_SL811_HCD)	+= sl811-hcd.o
 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 --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 43eddae..c9cc441 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -52,7 +52,7 @@
 		HCS_INDICATOR (params) ? " ind" : "",
 		HCS_N_CC (params),
 		HCS_N_PCC (params),
-	        HCS_PORTROUTED (params) ? "" : " ordered",
+		HCS_PORTROUTED (params) ? "" : " ordered",
 		HCS_PPC (params) ? "" : " !ppc",
 		HCS_N_PORTS (params)
 		);
@@ -91,20 +91,20 @@
 
 	if (HCC_ISOC_CACHE (params)) {
 		ehci_dbg (ehci,
-		     "%s hcc_params %04x caching frame %s%s%s\n",
-		     label, params,
-		     HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
-		     HCC_CANPARK (params) ? " park" : "",
-		     HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+			"%s hcc_params %04x caching frame %s%s%s\n",
+			label, params,
+			HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+			HCC_CANPARK(params) ? " park" : "",
+			HCC_64BIT_ADDR(params) ? " 64 bit addr" : "");
 	} else {
 		ehci_dbg (ehci,
-		     "%s hcc_params %04x thresh %d uframes %s%s%s\n",
-		     label,
-		     params,
-		     HCC_ISOC_THRES (params),
-		     HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
-		     HCC_CANPARK (params) ? " park" : "",
-		     HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+			"%s hcc_params %04x thresh %d uframes %s%s%s\n",
+			label,
+			params,
+			HCC_ISOC_THRES(params),
+			HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+			HCC_CANPARK(params) ? " park" : "",
+			HCC_64BIT_ADDR(params) ? " 64 bit addr" : "");
 	}
 }
 #else
@@ -115,23 +115,23 @@
 
 #ifdef	DEBUG
 
-static void __attribute__((__unused__))
+static void __maybe_unused
 dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 {
-	ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
-		le32_to_cpup (&qtd->hw_next),
-		le32_to_cpup (&qtd->hw_alt_next),
-		le32_to_cpup (&qtd->hw_token),
-		le32_to_cpup (&qtd->hw_buf [0]));
+	ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
+		hc32_to_cpup(ehci, &qtd->hw_next),
+		hc32_to_cpup(ehci, &qtd->hw_alt_next),
+		hc32_to_cpup(ehci, &qtd->hw_token),
+		hc32_to_cpup(ehci, &qtd->hw_buf [0]));
 	if (qtd->hw_buf [1])
-		ehci_dbg (ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
-			le32_to_cpup (&qtd->hw_buf [1]),
-			le32_to_cpup (&qtd->hw_buf [2]),
-			le32_to_cpup (&qtd->hw_buf [3]),
-			le32_to_cpup (&qtd->hw_buf [4]));
+		ehci_dbg(ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
+			hc32_to_cpup(ehci, &qtd->hw_buf[1]),
+			hc32_to_cpup(ehci, &qtd->hw_buf[2]),
+			hc32_to_cpup(ehci, &qtd->hw_buf[3]),
+			hc32_to_cpup(ehci, &qtd->hw_buf[4]));
 }
 
-static void __attribute__((__unused__))
+static void __maybe_unused
 dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label,
@@ -140,51 +140,53 @@
 	dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next);
 }
 
-static void __attribute__((__unused__))
+static void __maybe_unused
 dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 {
 	ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n",
-		label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb);
+		label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next),
+		itd->urb);
 	ehci_dbg (ehci,
 		"  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-		le32_to_cpu(itd->hw_transaction[0]),
-		le32_to_cpu(itd->hw_transaction[1]),
-		le32_to_cpu(itd->hw_transaction[2]),
-		le32_to_cpu(itd->hw_transaction[3]),
-		le32_to_cpu(itd->hw_transaction[4]),
-		le32_to_cpu(itd->hw_transaction[5]),
-		le32_to_cpu(itd->hw_transaction[6]),
-		le32_to_cpu(itd->hw_transaction[7]));
+		hc32_to_cpu(ehci, itd->hw_transaction[0]),
+		hc32_to_cpu(ehci, itd->hw_transaction[1]),
+		hc32_to_cpu(ehci, itd->hw_transaction[2]),
+		hc32_to_cpu(ehci, itd->hw_transaction[3]),
+		hc32_to_cpu(ehci, itd->hw_transaction[4]),
+		hc32_to_cpu(ehci, itd->hw_transaction[5]),
+		hc32_to_cpu(ehci, itd->hw_transaction[6]),
+		hc32_to_cpu(ehci, itd->hw_transaction[7]));
 	ehci_dbg (ehci,
 		"  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
-		le32_to_cpu(itd->hw_bufp[0]),
-		le32_to_cpu(itd->hw_bufp[1]),
-		le32_to_cpu(itd->hw_bufp[2]),
-		le32_to_cpu(itd->hw_bufp[3]),
-		le32_to_cpu(itd->hw_bufp[4]),
-		le32_to_cpu(itd->hw_bufp[5]),
-		le32_to_cpu(itd->hw_bufp[6]));
+		hc32_to_cpu(ehci, itd->hw_bufp[0]),
+		hc32_to_cpu(ehci, itd->hw_bufp[1]),
+		hc32_to_cpu(ehci, itd->hw_bufp[2]),
+		hc32_to_cpu(ehci, itd->hw_bufp[3]),
+		hc32_to_cpu(ehci, itd->hw_bufp[4]),
+		hc32_to_cpu(ehci, itd->hw_bufp[5]),
+		hc32_to_cpu(ehci, itd->hw_bufp[6]));
 	ehci_dbg (ehci, "  index: %d %d %d %d %d %d %d %d\n",
 		itd->index[0], itd->index[1], itd->index[2],
 		itd->index[3], itd->index[4], itd->index[5],
 		itd->index[6], itd->index[7]);
 }
 
-static void __attribute__((__unused__))
+static void __maybe_unused
 dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 {
 	ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
-		label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb);
+		label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next),
+		sitd->urb);
 	ehci_dbg (ehci,
 		"  addr %08x sched %04x result %08x buf %08x %08x\n",
-		le32_to_cpu(sitd->hw_fullspeed_ep),
-		le32_to_cpu(sitd->hw_uframe),
-		le32_to_cpu(sitd->hw_results),
-		le32_to_cpu(sitd->hw_buf [0]),
-		le32_to_cpu(sitd->hw_buf [1]));
+		hc32_to_cpu(ehci, sitd->hw_fullspeed_ep),
+		hc32_to_cpu(ehci, sitd->hw_uframe),
+		hc32_to_cpu(ehci, sitd->hw_results),
+		hc32_to_cpu(ehci, sitd->hw_buf[0]),
+		hc32_to_cpu(ehci, sitd->hw_buf[1]));
 }
 
-static int __attribute__((__unused__))
+static int __maybe_unused
 dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
 {
 	return scnprintf (buf, len,
@@ -203,7 +205,7 @@
 		);
 }
 
-static int __attribute__((__unused__))
+static int __maybe_unused
 dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
 {
 	return scnprintf (buf, len,
@@ -267,28 +269,27 @@
 		(status & PORT_PEC) ? " PEC" : "",
 		(status & PORT_PE) ? " PE" : "",
 		(status & PORT_CSC) ? " CSC" : "",
-		(status & PORT_CONNECT) ? " CONNECT" : ""
-	    );
+		(status & PORT_CONNECT) ? " CONNECT" : "");
 }
 
 #else
-static inline void __attribute__((__unused__))
+static inline void __maybe_unused
 dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
 {}
 
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
 dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
 { return 0; }
 
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
 dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
 { return 0; }
 
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
 dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
 { return 0; }
 
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
 dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
 { return 0; }
 
@@ -332,9 +333,10 @@
 		default: tmp = '?'; break; \
 		}; tmp; })
 
-static inline char token_mark (__le32 token)
+static inline char token_mark(struct ehci_hcd *ehci, __hc32 token)
 {
-	__u32 v = le32_to_cpu (token);
+	__u32 v = hc32_to_cpu(ehci, token);
+
 	if (v & QTD_STS_ACTIVE)
 		return '*';
 	if (v & QTD_STS_HALT)
@@ -360,46 +362,48 @@
 	unsigned		size = *sizep;
 	char			*next = *nextp;
 	char			mark;
+	u32			list_end = EHCI_LIST_END(ehci);
 
-	if (qh->hw_qtd_next == EHCI_LIST_END)	/* NEC does this */
+	if (qh->hw_qtd_next == list_end)	/* NEC does this */
 		mark = '@';
 	else
-		mark = token_mark (qh->hw_token);
+		mark = token_mark(ehci, qh->hw_token);
 	if (mark == '/') {	/* qh_alt_next controls qh advance? */
-		if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next)
+		if ((qh->hw_alt_next & QTD_MASK(ehci))
+				== ehci->async->hw_alt_next)
 			mark = '#';	/* blocked */
-		else if (qh->hw_alt_next == EHCI_LIST_END)
+		else if (qh->hw_alt_next == list_end)
 			mark = '.';	/* use hw_qtd_next */
 		/* else alt_next points to some other qtd */
 	}
-	scratch = le32_to_cpup (&qh->hw_info1);
-	hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0;
+	scratch = hc32_to_cpup(ehci, &qh->hw_info1);
+	hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &qh->hw_current) : 0;
 	temp = scnprintf (next, size,
 			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
 			qh, scratch & 0x007f,
 			speed_char (scratch),
 			(scratch >> 8) & 0x000f,
-			scratch, le32_to_cpup (&qh->hw_info2),
-			le32_to_cpup (&qh->hw_token), mark,
-			(__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
+			scratch, hc32_to_cpup(ehci, &qh->hw_info2),
+			hc32_to_cpup(ehci, &qh->hw_token), mark,
+			(cpu_to_hc32(ehci, QTD_TOGGLE) & qh->hw_token)
 				? "data1" : "data0",
-			(le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f);
+			(hc32_to_cpup(ehci, &qh->hw_alt_next) >> 1) & 0x0f);
 	size -= temp;
 	next += temp;
 
 	/* hc may be modifying the list as we read it ... */
 	list_for_each (entry, &qh->qtd_list) {
 		td = list_entry (entry, struct ehci_qtd, qtd_list);
-		scratch = le32_to_cpup (&td->hw_token);
+		scratch = hc32_to_cpup(ehci, &td->hw_token);
 		mark = ' ';
 		if (hw_curr == td->qtd_dma)
 			mark = '*';
-		else if (qh->hw_qtd_next == cpu_to_le32(td->qtd_dma))
+		else if (qh->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma))
 			mark = '+';
 		else if (QTD_LENGTH (scratch)) {
 			if (td->hw_alt_next == ehci->async->hw_alt_next)
 				mark = '#';
-			else if (td->hw_alt_next != EHCI_LIST_END)
+			else if (td->hw_alt_next != list_end)
 				mark = '/';
 		}
 		temp = snprintf (next, size,
@@ -490,7 +494,7 @@
 	unsigned		temp, size, seen_count;
 	char			*next;
 	unsigned		i;
-	__le32			tag;
+	__hc32			tag;
 
 	if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
 		return 0;
@@ -514,18 +518,19 @@
 		p = ehci->pshadow [i];
 		if (likely (!p.ptr))
 			continue;
-		tag = Q_NEXT_TYPE (ehci->periodic [i]);
+		tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]);
 
 		temp = scnprintf (next, size, "%4d: ", i);
 		size -= temp;
 		next += temp;
 
 		do {
-			switch (tag) {
+			switch (hc32_to_cpu(ehci, tag)) {
 			case Q_TYPE_QH:
 				temp = scnprintf (next, size, " qh%d-%04x/%p",
 						p.qh->period,
-						le32_to_cpup (&p.qh->hw_info2)
+						hc32_to_cpup(ehci,
+								&p.qh->hw_info2)
 							/* uframe masks */
 							& (QH_CMASK | QH_SMASK),
 						p.qh);
@@ -543,7 +548,7 @@
 				}
 				/* show more info the first time around */
 				if (temp == seen_count && p.ptr) {
-					u32	scratch = le32_to_cpup (
+					u32	scratch = hc32_to_cpup(ehci,
 							&p.qh->hw_info1);
 					struct ehci_qtd	*qtd;
 					char		*type = "";
@@ -554,7 +559,8 @@
 							&p.qh->qtd_list,
 							qtd_list) {
 						temp++;
-						switch (0x03 & (le32_to_cpu (
+						switch (0x03 & (hc32_to_cpu(
+							ehci,
 							qtd->hw_token) >> 8)) {
 						case 0: type = "out"; continue;
 						case 1: type = "in"; continue;
@@ -576,7 +582,7 @@
 				} else
 					temp = 0;
 				if (p.qh) {
-					tag = Q_NEXT_TYPE (p.qh->hw_next);
+					tag = Q_NEXT_TYPE(ehci, p.qh->hw_next);
 					p = p.qh->qh_next;
 				}
 				break;
@@ -584,23 +590,23 @@
 				temp = scnprintf (next, size,
 					" fstn-%8x/%p", p.fstn->hw_prev,
 					p.fstn);
-				tag = Q_NEXT_TYPE (p.fstn->hw_next);
+				tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next);
 				p = p.fstn->fstn_next;
 				break;
 			case Q_TYPE_ITD:
 				temp = scnprintf (next, size,
 					" itd/%p", p.itd);
-				tag = Q_NEXT_TYPE (p.itd->hw_next);
+				tag = Q_NEXT_TYPE(ehci, p.itd->hw_next);
 				p = p.itd->itd_next;
 				break;
 			case Q_TYPE_SITD:
 				temp = scnprintf (next, size,
 					" sitd%d-%04x/%p",
 					p.sitd->stream->interval,
-					le32_to_cpup (&p.sitd->hw_uframe)
+					hc32_to_cpup(ehci, &p.sitd->hw_uframe)
 						& 0x0000ffff,
 					p.sitd);
-				tag = Q_NEXT_TYPE (p.sitd->hw_next);
+				tag = Q_NEXT_TYPE(ehci, p.sitd->hw_next);
 				p = p.sitd->sitd_next;
 				break;
 			}
@@ -673,7 +679,8 @@
 		unsigned	count = 256/4;
 
 		pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-		offset = HCC_EXT_CAPS (ehci_readl(ehci, &ehci->caps->hcc_params));
+		offset = HCC_EXT_CAPS(ehci_readl(ehci,
+				&ehci->caps->hcc_params));
 		while (offset && count--) {
 			pci_read_config_dword (pdev, offset, &cap);
 			switch (cap & 0xff) {
@@ -740,14 +747,16 @@
 
 	for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) {
 		temp = dbg_port_buf (scratch, sizeof scratch, label, i,
-				ehci_readl(ehci, &ehci->regs->port_status [i - 1]));
+				ehci_readl(ehci,
+					&ehci->regs->port_status[i - 1]));
 		temp = scnprintf (next, size, fmt, temp, scratch);
 		size -= temp;
 		next += temp;
 		if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) {
 			temp = scnprintf (next, size,
 					"    debug control %08x\n",
-					ehci_readl(ehci, &ehci->debug->control));
+					ehci_readl(ehci,
+						&ehci->debug->control));
 			size -= temp;
 			next += temp;
 		}
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index a524805..b7b7bfb 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -67,7 +67,8 @@
 	 * in host mode.
 	 */
 	if (!((pdata->operating_mode == FSL_USB2_DR_HOST) ||
-	      (pdata->operating_mode == FSL_USB2_MPH_HOST))) {
+	      (pdata->operating_mode == FSL_USB2_MPH_HOST) ||
+	      (pdata->operating_mode == FSL_USB2_DR_OTG))) {
 		dev_err(&pdev->dev,
 			"Non Host Mode configured for %s. Wrong driver linked.\n",
 			pdev->dev.bus_id);
@@ -185,15 +186,31 @@
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct fsl_usb2_platform_data *pdata;
 	void __iomem *non_ehci = hcd->regs;
+	u32 temp;
 
 	pdata =
 	    (struct fsl_usb2_platform_data *)hcd->self.controller->
 	    platform_data;
 	/* Enable PHY interface in the control reg. */
-	out_be32(non_ehci + FSL_SOC_USB_CTRL, 0x00000004);
+	temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+	out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
 	out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
 
-	if (pdata->operating_mode == FSL_USB2_DR_HOST)
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+	/*
+	 * Turn on cache snooping hardware, since some PowerPC platforms
+	 * wholly rely on hardware to deal with cache coherent
+	 */
+
+	/* Setup Snooping for all the 4GB space */
+	/* SNOOP1 starts from 0x0, size 2G */
+	out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB);
+	/* SNOOP2 starts from 0x80000000, size 2G */
+	out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
+#endif
+
+	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
+			(pdata->operating_mode == FSL_USB2_DR_OTG))
 		mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
 
 	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index f28736a..b5e59db 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -34,4 +34,5 @@
 #define FSL_SOC_USB_PRICTRL	0x40c	/* NOTE: big-endian */
 #define FSL_SOC_USB_SICTRL	0x410	/* NOTE: big-endian */
 #define FSL_SOC_USB_CTRL	0x500	/* NOTE: big-endian */
+#define SNOOP_SIZE_2GB		0x1e
 #endif				/* _EHCI_FSL_H */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 099aff6..c4e15ed 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -41,10 +41,6 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -201,9 +197,15 @@
 	u32 __iomem	*reg_ptr;
 	u32		tmp;
 
-	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68);
+	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
 	tmp = ehci_readl(ehci, reg_ptr);
-	tmp |= 0x3;
+	tmp |= USBMODE_CM_HC;
+	/* The default byte access to MMR space is LE after
+	 * controller reset. Set the required endian mode
+	 * for transfer buffers to match the host microprocessor
+	 */
+	if (ehci_big_endian_mmio(ehci))
+		tmp |= USBMODE_BE;
 	ehci_writel(ehci, tmp, reg_ptr);
 }
 
@@ -273,6 +275,58 @@
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_CPU_FREQ
+
+#include <linux/cpufreq.h>
+
+static void ehci_cpufreq_pause (struct ehci_hcd *ehci)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave(&ehci->lock, flags);
+	if (!ehci->cpufreq_changing++)
+		qh_inactivate_split_intr_qhs(ehci);
+	spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_cpufreq_unpause (struct ehci_hcd *ehci)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave(&ehci->lock, flags);
+	if (!--ehci->cpufreq_changing)
+		qh_reactivate_split_intr_qhs(ehci);
+	spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+/*
+ * ehci_cpufreq_notifier is needed to avoid MMF errors that occur when
+ * EHCI controllers that don't cache many uframes get delayed trying to
+ * read main memory during CPU frequency transitions.  This can cause
+ * split interrupt transactions to not be completed in the required uframe.
+ * This has been observed on the Broadcom/ServerWorks HT1000 controller.
+ */
+static int ehci_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+				 void *data)
+{
+	struct ehci_hcd *ehci = container_of(nb, struct ehci_hcd,
+					     cpufreq_transition);
+
+	switch (val) {
+	case CPUFREQ_PRECHANGE:
+		ehci_cpufreq_pause(ehci);
+		break;
+	case CPUFREQ_POSTCHANGE:
+		ehci_cpufreq_unpause(ehci);
+		break;
+	}
+	return 0;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 static void ehci_watchdog (unsigned long param)
 {
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
@@ -347,6 +401,8 @@
 				is_on ? SetPortFeature : ClearPortFeature,
 				USB_PORT_FEAT_POWER,
 				port--, NULL, 0);
+	/* Flush those writes */
+	ehci_readl(ehci, &ehci->regs->command);
 	msleep(20);
 }
 
@@ -404,6 +460,10 @@
 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 	spin_unlock_irq(&ehci->lock);
 
+#ifdef CONFIG_CPU_FREQ
+	cpufreq_unregister_notifier(&ehci->cpufreq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+#endif
 	/* let companion controllers work when we aren't */
 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
 
@@ -470,12 +530,12 @@
 	 * from automatically advancing to the next td after short reads.
 	 */
 	ehci->async->qh_next.qh = NULL;
-	ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma);
-	ehci->async->hw_info1 = cpu_to_le32(QH_HEAD);
-	ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT);
-	ehci->async->hw_qtd_next = EHCI_LIST_END;
+	ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
+	ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
+	ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
+	ehci->async->hw_qtd_next = EHCI_LIST_END(ehci);
 	ehci->async->qh_state = QH_STATE_LINKED;
-	ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma);
+	ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
 
 	/* clear interrupt enables, set irq latency */
 	if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
@@ -509,6 +569,17 @@
 	}
 	ehci->command = temp;
 
+#ifdef CONFIG_CPU_FREQ
+	INIT_LIST_HEAD(&ehci->split_intr_qhs);
+	/*
+	 * If the EHCI controller caches enough uframes, this probably
+	 * isn't needed unless there are so many low/full speed devices
+	 * that the controller's can't cache it all.
+	 */
+	ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier;
+	cpufreq_register_notifier(&ehci->cpufreq_transition,
+				  CPUFREQ_TRANSITION_NOTIFIER);
+#endif
 	return 0;
 }
 
@@ -925,7 +996,7 @@
 #define	PCI_DRIVER		ehci_pci_driver
 #endif
 
-#ifdef CONFIG_MPC834x
+#ifdef CONFIG_USB_EHCI_FSL
 #include "ehci-fsl.c"
 #define	PLATFORM_DRIVER		ehci_fsl_driver
 #endif
@@ -937,7 +1008,12 @@
 
 #ifdef CONFIG_PPC_PS3
 #include "ehci-ps3.c"
-#define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_sb_driver
+#define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
+#endif
+
+#ifdef CONFIG_440EPX
+#include "ehci-ppc-soc.c"
+#define	PLATFORM_DRIVER		ehci_ppc_soc_driver
 #endif
 
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
@@ -971,18 +1047,15 @@
 #endif
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
-		retval = ps3_system_bus_driver_register(
-				&PS3_SYSTEM_BUS_DRIVER);
-		if (retval < 0) {
+	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+	if (retval < 0) {
 #ifdef PLATFORM_DRIVER
-			platform_driver_unregister(&PLATFORM_DRIVER);
+		platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PCI_DRIVER
-			pci_unregister_driver(&PCI_DRIVER);
+		pci_unregister_driver(&PCI_DRIVER);
 #endif
-			return retval;
-		}
+		return retval;
 	}
 #endif
 
@@ -999,8 +1072,7 @@
 	pci_unregister_driver(&PCI_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ehci_hcd_cleanup);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index f4d301b..0dcb416 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -28,6 +28,89 @@
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef	CONFIG_USB_PERSIST
+
+static int ehci_hub_control(
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength
+);
+
+/* After a power loss, ports that were owned by the companion must be
+ * reset so that the companion can still own them.
+ */
+static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+{
+	u32 __iomem	*reg;
+	u32		status;
+	int		port;
+	__le32		buf;
+	struct usb_hcd	*hcd = ehci_to_hcd(ehci);
+
+	if (!ehci->owned_ports)
+		return;
+
+	/* Give the connections some time to appear */
+	msleep(20);
+
+	port = HCS_N_PORTS(ehci->hcs_params);
+	while (port--) {
+		if (test_bit(port, &ehci->owned_ports)) {
+			reg = &ehci->regs->port_status[port];
+			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+
+			/* Port already owned by companion? */
+			if (status & PORT_OWNER)
+				clear_bit(port, &ehci->owned_ports);
+			else if (test_bit(port, &ehci->companion_ports))
+				ehci_writel(ehci, status & ~PORT_PE, reg);
+			else
+				ehci_hub_control(hcd, SetPortFeature,
+						USB_PORT_FEAT_RESET, port + 1,
+						NULL, 0);
+		}
+	}
+
+	if (!ehci->owned_ports)
+		return;
+	msleep(90);		/* Wait for resets to complete */
+
+	port = HCS_N_PORTS(ehci->hcs_params);
+	while (port--) {
+		if (test_bit(port, &ehci->owned_ports)) {
+			ehci_hub_control(hcd, GetPortStatus,
+					0, port + 1,
+					(char *) &buf, sizeof(buf));
+
+			/* The companion should now own the port,
+			 * but if something went wrong the port must not
+			 * remain enabled.
+			 */
+			reg = &ehci->regs->port_status[port];
+			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+			if (status & PORT_OWNER)
+				ehci_writel(ehci, status | PORT_CSC, reg);
+			else {
+				ehci_dbg(ehci, "failed handover port %d: %x\n",
+						port + 1, status);
+				ehci_writel(ehci, status & ~PORT_PE, reg);
+			}
+		}
+	}
+
+	ehci->owned_ports = 0;
+}
+
+#else	/* CONFIG_USB_PERSIST */
+
+static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+{ }
+
+#endif
+
 #ifdef	CONFIG_PM
 
 static int ehci_bus_suspend (struct usb_hcd *hcd)
@@ -60,14 +143,16 @@
 	 * then manually resume them in the bus_resume() routine.
 	 */
 	ehci->bus_suspended = 0;
+	ehci->owned_ports = 0;
 	while (port--) {
 		u32 __iomem	*reg = &ehci->regs->port_status [port];
 		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
 		u32		t2 = t1;
 
 		/* keep track of which ports we suspend */
-		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
-				!(t1 & PORT_SUSPEND)) {
+		if (t1 & PORT_OWNER)
+			set_bit(port, &ehci->owned_ports);
+		else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
 			t2 |= PORT_SUSPEND;
 			set_bit(port, &ehci->bus_suspended);
 		}
@@ -108,11 +193,16 @@
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			temp;
+	u32			power_okay;
 	int			i;
 
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
 	spin_lock_irq (&ehci->lock);
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+		spin_unlock_irq(&ehci->lock);
+		return -ESHUTDOWN;
+	}
 
 	/* Ideally and we've got a real resume here, and no port's power
 	 * was lost.  (For PCI, that means Vaux was maintained.)  But we
@@ -120,8 +210,9 @@
 	 * the last user of the controller, not reset/pm hardware keeping
 	 * state we gave to it.
 	 */
-	temp = ehci_readl(ehci, &ehci->regs->intr_enable);
-	ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
+	power_okay = ehci_readl(ehci, &ehci->regs->intr_enable);
+	ehci_dbg(ehci, "resume root hub%s\n",
+			power_okay ? "" : " after power loss");
 
 	/* at least some APM implementations will try to deliver
 	 * IRQs right away, so delay them until we're ready.
@@ -184,6 +275,9 @@
 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
 
 	spin_unlock_irq (&ehci->lock);
+
+	if (!power_okay)
+		ehci_handover_companion_ports(ehci);
 	return 0;
 }
 
@@ -448,7 +542,8 @@
 ) {
 	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
 	int		ports = HCS_N_PORTS (ehci->hcs_params);
-	u32 __iomem	*status_reg = &ehci->regs->port_status[wIndex - 1];
+	u32 __iomem	*status_reg = &ehci->regs->port_status[
+				(wIndex & 0xff) - 1];
 	u32		temp, status;
 	unsigned long	flags;
 	int		retval = 0;
@@ -556,9 +651,24 @@
 			status |= 1 << USB_PORT_FEAT_C_CONNECTION;
 		if (temp & PORT_PEC)
 			status |= 1 << USB_PORT_FEAT_C_ENABLE;
-		if ((temp & PORT_OCC) && !ignore_oc)
+
+		if ((temp & PORT_OCC) && !ignore_oc){
 			status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
 
+			/*
+			 * Hubs should disable port power on over-current.
+			 * However, not all EHCI implementations do this
+			 * automatically, even if they _do_ support per-port
+			 * power switching; they're allowed to just limit the
+			 * current.  khubd will turn the power back on.
+			 */
+			if (HCS_PPC (ehci->hcs_params)){
+				ehci_writel(ehci,
+					temp & ~(PORT_RWC_BITS | PORT_POWER),
+					status_reg);
+			}
+		}
+
 		/* whoever resumes must GetPortStatus to complete it!! */
 		if (temp & PORT_RESUME) {
 
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index a8ba2e1..8816d09 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -27,7 +27,7 @@
  *	  need to use dma_pool or dma_alloc_coherent
  *	- driver buffers, read/written by HC ... single shot DMA mapped
  *
- * There's also PCI "register" data, which is memory mapped.
+ * There's also "register" data (e.g. PCI or SOC), which is memory mapped.
  * No memory seen by this driver is pageable.
  */
 
@@ -35,13 +35,14 @@
 
 /* Allocate the key transfer structures from the previously allocated pool */
 
-static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
+static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
+				  dma_addr_t dma)
 {
 	memset (qtd, 0, sizeof *qtd);
 	qtd->qtd_dma = dma;
 	qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
-	qtd->hw_next = EHCI_LIST_END;
-	qtd->hw_alt_next = EHCI_LIST_END;
+	qtd->hw_next = EHCI_LIST_END(ehci);
+	qtd->hw_alt_next = EHCI_LIST_END(ehci);
 	INIT_LIST_HEAD (&qtd->qtd_list);
 }
 
@@ -52,7 +53,7 @@
 
 	qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
 	if (qtd != NULL) {
-		ehci_qtd_init (qtd, dma);
+		ehci_qtd_init(ehci, qtd, dma);
 	}
 	return qtd;
 }
@@ -63,9 +64,8 @@
 }
 
 
-static void qh_destroy (struct kref *kref)
+static void qh_destroy(struct ehci_qh *qh)
 {
-	struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref);
 	struct ehci_hcd *ehci = qh->ehci;
 
 	/* clean qtds first, and know this is not linked */
@@ -89,11 +89,14 @@
 		return qh;
 
 	memset (qh, 0, sizeof *qh);
-	kref_init(&qh->kref);
+	qh->refcount = 1;
 	qh->ehci = ehci;
 	qh->qh_dma = dma;
 	// INIT_LIST_HEAD (&qh->qh_list);
 	INIT_LIST_HEAD (&qh->qtd_list);
+#ifdef CONFIG_CPU_FREQ
+	INIT_LIST_HEAD (&qh->split_intr_qhs);
+#endif
 
 	/* dummy td enables safe urb queuing */
 	qh->dummy = ehci_qtd_alloc (ehci, flags);
@@ -108,13 +111,15 @@
 /* to share a qh (cpu threads, or hc) */
 static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
 {
-	kref_get(&qh->kref);
+	WARN_ON(!qh->refcount);
+	qh->refcount++;
 	return qh;
 }
 
 static inline void qh_put (struct ehci_qh *qh)
 {
-	kref_put(&qh->kref, qh_destroy);
+	if (!--qh->refcount)
+		qh_destroy(qh);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -217,7 +222,7 @@
 		goto fail;
 	}
 	for (i = 0; i < ehci->periodic_size; i++)
-		ehci->periodic [i] = EHCI_LIST_END;
+		ehci->periodic [i] = EHCI_LIST_END(ehci);
 
 	/* software shadow of hardware table */
 	ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 12edc72..a7816e3 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -149,8 +149,7 @@
 		 * fixed in newer silicon.
 		 */
 		case 0x0068:
-			pci_read_config_dword(pdev, PCI_REVISION_ID, &temp);
-			if ((temp & 0xff) < 0xa4)
+			if (pdev->revision < 0xa4)
 				ehci->no_selective_suspend = 1;
 			break;
 		}
@@ -313,13 +312,14 @@
 	ehci_work(ehci);
 	spin_unlock_irq(&ehci->lock);
 
-	/* here we "know" root ports should always stay powered */
-	ehci_port_power(ehci, 1);
-
 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
 	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
 	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
 
+	/* here we "know" root ports should always stay powered */
+	ehci_port_power(ehci, 1);
+	ehci_handover_companion_ports(ehci);
+
 	hcd->state = HC_STATE_SUSPENDED;
 	return 0;
 }
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
new file mode 100644
index 0000000..c2cedb0
--- /dev/null
+++ b/drivers/usb/host/ehci-ppc-soc.c
@@ -0,0 +1,182 @@
+/*
+ * EHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 2006-2007 Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * Bus Glue for PPC On-Chip EHCI driver
+ * Tested on AMCC 440EPx
+ *
+ * Based on "ehci-au12xx.c" by David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/platform_device.h>
+
+extern int usb_disabled(void);
+
+/**
+ * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ */
+int usb_ehci_ppc_soc_probe(const struct hc_driver *driver,
+			   struct usb_hcd **hcd_out,
+			   struct platform_device *dev)
+{
+	int retval;
+	struct usb_hcd *hcd;
+	struct ehci_hcd *ehci;
+
+	if (dev->resource[1].flags != IORESOURCE_IRQ) {
+		pr_debug("resource[1] is not IORESOURCE_IRQ");
+		retval = -ENOMEM;
+	}
+	hcd = usb_create_hcd(driver, &dev->dev, "PPC-SOC EHCI");
+	if (!hcd)
+		return -ENOMEM;
+	hcd->rsrc_start = dev->resource[0].start;
+	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_debug("request_mem_region failed");
+		retval = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
+		retval = -ENOMEM;
+		goto err2;
+	}
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->big_endian_mmio = 1;
+	ehci->big_endian_desc = 1;
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+#if defined(CONFIG_440EPX)
+	/*
+	 * 440EPx Errata USBH_3
+	 * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
+	 */
+	out_be32((void *)((ulong)(&ehci->regs->command) + 0x8c), (1 << 0));
+	ehci_dbg(ehci, "Break Memory Transfer (BMT) has beed enabled!\n");
+#endif
+
+	retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
+	if (retval == 0)
+		return retval;
+
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
+	return retval;
+}
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_ehci_hcd_ppc_soc_remove - shutdown processing for PPC-SoC-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_ehci_hcd_ppc_soc_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+void usb_ehci_ppc_soc_remove(struct usb_hcd *hcd, struct platform_device *dev)
+{
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+}
+
+static const struct hc_driver ehci_ppc_soc_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "PPC-SOC EHCI",
+	.hcd_priv_size = sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ehci_irq,
+	.flags = HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset = ehci_init,
+	.start = ehci_run,
+	.stop = ehci_stop,
+	.shutdown = ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ehci_urb_enqueue,
+	.urb_dequeue = ehci_urb_dequeue,
+	.endpoint_disable = ehci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ehci_hub_status_data,
+	.hub_control = ehci_hub_control,
+#ifdef	CONFIG_PM
+	.hub_suspend = ehci_hub_suspend,
+	.hub_resume = ehci_hub_resume,
+#endif
+};
+
+static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = NULL;
+	int ret;
+
+	pr_debug("In ehci_hcd_ppc_soc_drv_probe\n");
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev);
+	return ret;
+}
+
+static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_ehci_ppc_soc_remove(hcd, pdev);
+	return 0;
+}
+
+MODULE_ALIAS("ppc-soc-ehci");
+static struct platform_driver ehci_ppc_soc_driver = {
+	.probe = ehci_hcd_ppc_soc_drv_probe,
+	.remove = ehci_hcd_ppc_soc_drv_remove,
+	.shutdown = usb_hcd_platform_shutdown,
+	.driver = {
+		.name = "ppc-soc-ehci",
+		.bus = &platform_bus_type
+	}
+};
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 37b83ba..829fe64 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -18,6 +18,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <asm/firmware.h>
 #include <asm/ps3.h>
 
 static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
@@ -73,7 +74,7 @@
 #endif
 };
 
-static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
+static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct usb_hcd *hcd;
@@ -85,13 +86,30 @@
 		goto fail_start;
 	}
 
+	result = ps3_open_hv_device(dev);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed\n",
+			__func__, __LINE__);
+		goto fail_open;
+	}
+
+	result = ps3_dma_region_create(dev->d_region);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+			"(%d)\n", __func__, __LINE__, result);
+		BUG_ON("check region type");
+		goto fail_dma_region;
+	}
+
 	result = ps3_mmio_region_create(dev->m_region);
 
 	if (result) {
 		dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n",
 			__func__, __LINE__);
 		result = -EPERM;
-		goto fail_mmio;
+		goto fail_mmio_region;
 	}
 
 	dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
@@ -120,6 +138,11 @@
 
 	hcd->rsrc_start = dev->m_region->lpar_addr;
 	hcd->rsrc_len = dev->m_region->len;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name))
+		dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n",
+			__func__, __LINE__);
+
 	hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len);
 
 	if (!hcd->regs) {
@@ -153,34 +176,73 @@
 fail_add_hcd:
 	iounmap(hcd->regs);
 fail_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 fail_create_hcd:
 	ps3_io_irq_destroy(virq);
 fail_irq:
 	ps3_free_mmio_region(dev->m_region);
-fail_mmio:
+fail_mmio_region:
+	ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+	ps3_close_hv_device(dev);
+fail_open:
 fail_start:
 	return result;
 }
 
-static int ps3_ehci_sb_remove(struct ps3_system_bus_device *dev)
+static int ps3_ehci_remove(struct ps3_system_bus_device *dev)
 {
+	unsigned int tmp;
 	struct usb_hcd *hcd =
 		(struct usb_hcd *)ps3_system_bus_get_driver_data(dev);
 
-	usb_put_hcd(hcd);
+	BUG_ON(!hcd);
+
+	dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs);
+	dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq);
+
+	tmp = hcd->irq;
+
+	usb_remove_hcd(hcd);
+
 	ps3_system_bus_set_driver_data(dev, NULL);
 
+	BUG_ON(!hcd->regs);
+	iounmap(hcd->regs);
+
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	ps3_io_irq_destroy(tmp);
+	ps3_free_mmio_region(dev->m_region);
+
+	ps3_dma_region_free(dev->d_region);
+	ps3_close_hv_device(dev);
+
 	return 0;
 }
 
-MODULE_ALIAS("ps3-ehci");
+static int ps3_ehci_driver_register(struct ps3_system_bus_driver *drv)
+{
+	return firmware_has_feature(FW_FEATURE_PS3_LV1)
+		? ps3_system_bus_driver_register(drv)
+		: 0;
+}
 
-static struct ps3_system_bus_driver ps3_ehci_sb_driver = {
+static void ps3_ehci_driver_unregister(struct ps3_system_bus_driver *drv)
+{
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+		ps3_system_bus_driver_unregister(drv);
+}
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_EHCI);
+
+static struct ps3_system_bus_driver ps3_ehci_driver = {
+	.core.name = "ps3-ehci-driver",
+	.core.owner = THIS_MODULE,
 	.match_id = PS3_MATCH_ID_EHCI,
-	.core = {
-		.name = "ps3-ehci-driver",
-	},
-	.probe = ps3_ehci_sb_probe,
-	.remove = ps3_ehci_sb_remove,
+	.probe = ps3_ehci_probe,
+	.remove = ps3_ehci_remove,
+	.shutdown = ps3_ehci_remove,
 };
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index e7fbbd0..2284028 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -43,15 +43,15 @@
 /* fill a qtd, returning how much of the buffer we were able to queue up */
 
 static int
-qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
-		int token, int maxpacket)
+qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf,
+		  size_t len, int token, int maxpacket)
 {
 	int	i, count;
 	u64	addr = buf;
 
 	/* one buffer entry per 4K ... first might be short or unaligned */
-	qtd->hw_buf [0] = cpu_to_le32 ((u32)addr);
-	qtd->hw_buf_hi [0] = cpu_to_le32 ((u32)(addr >> 32));
+	qtd->hw_buf[0] = cpu_to_hc32(ehci, (u32)addr);
+	qtd->hw_buf_hi[0] = cpu_to_hc32(ehci, (u32)(addr >> 32));
 	count = 0x1000 - (buf & 0x0fff);	/* rest of that page */
 	if (likely (len < count))		/* ... iff needed */
 		count = len;
@@ -62,8 +62,9 @@
 		/* per-qtd limit: from 16K to 20K (best alignment) */
 		for (i = 1; count < len && i < 5; i++) {
 			addr = buf;
-			qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
-			qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
+			qtd->hw_buf[i] = cpu_to_hc32(ehci, (u32)addr);
+			qtd->hw_buf_hi[i] = cpu_to_hc32(ehci,
+					(u32)(addr >> 32));
 			buf += 0x1000;
 			if ((count + 0x1000) < len)
 				count += 0x1000;
@@ -75,7 +76,7 @@
 		if (count != len)
 			count -= (count % maxpacket);
 	}
-	qtd->hw_token = cpu_to_le32 ((count << 16) | token);
+	qtd->hw_token = cpu_to_hc32(ehci, (count << 16) | token);
 	qtd->length = count;
 
 	return count;
@@ -89,28 +90,28 @@
 	/* writes to an active overlay are unsafe */
 	BUG_ON(qh->qh_state != QH_STATE_IDLE);
 
-	qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
-	qh->hw_alt_next = EHCI_LIST_END;
+	qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
+	qh->hw_alt_next = EHCI_LIST_END(ehci);
 
 	/* Except for control endpoints, we make hardware maintain data
 	 * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
 	 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
 	 * ever clear it.
 	 */
-	if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) {
+	if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
 		unsigned	is_out, epnum;
 
-		is_out = !(qtd->hw_token & cpu_to_le32(1 << 8));
-		epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f;
+		is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
+		epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
 		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
-			qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
+			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
 			usb_settoggle (qh->dev, epnum, is_out, 1);
 		}
 	}
 
 	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
 	wmb ();
-	qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
+	qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
 }
 
 /* if it weren't for a common silicon quirk (writing the dummy into the qh
@@ -128,7 +129,7 @@
 		qtd = list_entry (qh->qtd_list.next,
 				struct ehci_qtd, qtd_list);
 		/* first qtd may already be partially processed */
-		if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current)
+		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current)
 			qtd = NULL;
 	}
 
@@ -222,7 +223,7 @@
 		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;
 
 		/* S-mask in a QH means it's an interrupt urb */
-		if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
+		if ((qh->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
 
 			/* ... update hc-wide periodic stats (for usbfs) */
 			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -277,7 +278,6 @@
  * Chases up to qh->hw_current.  Returns number of completions called,
  * indicating how much "real" work we did.
  */
-#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
 static unsigned
 qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
@@ -287,6 +287,7 @@
 	unsigned		count = 0;
 	int			do_status = 0;
 	u8			state;
+	u32			halt = HALT_BIT(ehci);
 
 	if (unlikely (list_empty (&qh->qtd_list)))
 		return count;
@@ -311,6 +312,10 @@
 		struct urb	*urb;
 		u32		token = 0;
 
+		/* ignore QHs that are currently inactive */
+		if (qh->hw_info1 & __constant_cpu_to_le32(QH_INACTIVATE))
+			break;
+
 		qtd = list_entry (entry, struct ehci_qtd, qtd_list);
 		urb = qtd->urb;
 
@@ -330,7 +335,7 @@
 
 		/* hardware copies qtd out of qh overlay */
 		rmb ();
-		token = le32_to_cpu (qtd->hw_token);
+		token = hc32_to_cpu(ehci, qtd->hw_token);
 
 		/* always clean up qtds the hc de-activated */
 		if ((token & QTD_STS_ACTIVE) == 0) {
@@ -342,7 +347,8 @@
 			 * that silicon quirk can kick in with this dummy too.
 			 */
 			} else if (IS_SHORT_READ (token)
-					&& !(qtd->hw_alt_next & EHCI_LIST_END)) {
+					&& !(qtd->hw_alt_next
+						& EHCI_LIST_END(ehci))) {
 				stopped = 1;
 				goto halt;
 			}
@@ -374,17 +380,17 @@
 
 			/* token in overlay may be most current */
 			if (state == QH_STATE_IDLE
-					&& cpu_to_le32 (qtd->qtd_dma)
+					&& cpu_to_hc32(ehci, qtd->qtd_dma)
 						== qh->hw_current)
-				token = le32_to_cpu (qh->hw_token);
+				token = hc32_to_cpu(ehci, qh->hw_token);
 
 			/* force halt for unlinked or blocked qh, so we'll
 			 * patch the qh later and so that completions can't
 			 * activate it while we "know" it's stopped.
 			 */
-			if ((HALT_BIT & qh->hw_token) == 0) {
+			if ((halt & qh->hw_token) == 0) {
 halt:
-				qh->hw_token |= HALT_BIT;
+				qh->hw_token |= halt;
 				wmb ();
 			}
 		}
@@ -419,7 +425,7 @@
 	 * it after fault cleanup, or recovering from silicon wrongly
 	 * overlaying the dummy qtd (which reduces DMA chatter).
 	 */
-	if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END) {
+	if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) {
 		switch (state) {
 		case QH_STATE_IDLE:
 			qh_refresh(ehci, qh);
@@ -428,7 +434,7 @@
 			/* should be rare for periodic transfers,
 			 * except maybe high bandwidth ...
 			 */
-			if ((__constant_cpu_to_le32 (QH_SMASK)
+			if ((cpu_to_hc32(ehci, QH_SMASK)
 					& qh->hw_info2) != 0) {
 				intr_deschedule (ehci, qh);
 				(void) qh_schedule (ehci, qh);
@@ -502,8 +508,9 @@
 	is_input = usb_pipein (urb->pipe);
 	if (usb_pipecontrol (urb->pipe)) {
 		/* SETUP pid */
-		qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
-			token | (2 /* "setup" */ << 8), 8);
+		qtd_fill(ehci, qtd, urb->setup_dma,
+				sizeof (struct usb_ctrlrequest),
+				token | (2 /* "setup" */ << 8), 8);
 
 		/* ... and always at least one more pid */
 		token ^= QTD_TOGGLE;
@@ -512,7 +519,7 @@
 		if (unlikely (!qtd))
 			goto cleanup;
 		qtd->urb = urb;
-		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+		qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
 		list_add_tail (&qtd->qtd_list, head);
 
 		/* for zero length DATA stages, STATUS is always IN */
@@ -539,7 +546,7 @@
 	for (;;) {
 		int this_qtd_len;
 
-		this_qtd_len = qtd_fill (qtd, buf, len, token, maxpacket);
+		this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
 		len -= this_qtd_len;
 		buf += this_qtd_len;
 		if (is_input)
@@ -557,7 +564,7 @@
 		if (unlikely (!qtd))
 			goto cleanup;
 		qtd->urb = urb;
-		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+		qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
 		list_add_tail (&qtd->qtd_list, head);
 	}
 
@@ -566,7 +573,7 @@
 	 */
 	if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
 				|| usb_pipecontrol (urb->pipe)))
-		qtd->hw_alt_next = EHCI_LIST_END;
+		qtd->hw_alt_next = EHCI_LIST_END(ehci);
 
 	/*
 	 * control requests may need a terminating data "status" ack;
@@ -590,17 +597,17 @@
 			if (unlikely (!qtd))
 				goto cleanup;
 			qtd->urb = urb;
-			qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+			qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
 			list_add_tail (&qtd->qtd_list, head);
 
 			/* never any data in such packets */
-			qtd_fill (qtd, 0, 0, token, 0);
+			qtd_fill(ehci, qtd, 0, 0, token, 0);
 		}
 	}
 
 	/* by default, enable interrupt on urb completion */
 	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
-		qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
+		qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC);
 	return head;
 
 cleanup:
@@ -769,8 +776,8 @@
 
 	/* init as live, toggle clear, advance to dummy */
 	qh->qh_state = QH_STATE_IDLE;
-	qh->hw_info1 = cpu_to_le32 (info1);
-	qh->hw_info2 = cpu_to_le32 (info2);
+	qh->hw_info1 = cpu_to_hc32(ehci, info1);
+	qh->hw_info2 = cpu_to_hc32(ehci, info2);
 	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
 	qh_refresh (ehci, qh);
 	return qh;
@@ -782,7 +789,7 @@
 
 static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	__le32		dma = QH_NEXT (qh->qh_dma);
+	__hc32		dma = QH_NEXT(ehci, qh->qh_dma);
 	struct ehci_qh	*head;
 
 	/* (re)start the async schedule? */
@@ -820,8 +827,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define	QH_ADDR_MASK	__constant_cpu_to_le32(0x7f)
-
 /*
  * For control/bulk/interrupt, return QH with these TDs appended.
  * Allocates and initializes the QH if necessary.
@@ -837,6 +842,7 @@
 )
 {
 	struct ehci_qh		*qh = NULL;
+	u32			qh_addr_mask = cpu_to_hc32(ehci, 0x7f);
 
 	qh = (struct ehci_qh *) *ptr;
 	if (unlikely (qh == NULL)) {
@@ -858,7 +864,7 @@
 
                         /* usb_reset_device() briefly reverts to address 0 */
                         if (usb_pipedevice (urb->pipe) == 0)
-                                qh->hw_info1 &= ~QH_ADDR_MASK;
+                                qh->hw_info1 &= ~qh_addr_mask;
 		}
 
 		/* just one way to queue requests: swap with the dummy qtd.
@@ -867,7 +873,7 @@
 		if (likely (qtd != NULL)) {
 			struct ehci_qtd		*dummy;
 			dma_addr_t		dma;
-			__le32			token;
+			__hc32			token;
 
 			/* to avoid racing the HC, use the dummy td instead of
 			 * the first td of our list (becomes new dummy).  both
@@ -875,7 +881,7 @@
 			 * HC is allowed to fetch the old dummy (4.10.2).
 			 */
 			token = qtd->hw_token;
-			qtd->hw_token = HALT_BIT;
+			qtd->hw_token = HALT_BIT(ehci);
 			wmb ();
 			dummy = qh->dummy;
 
@@ -887,14 +893,14 @@
 			list_add (&dummy->qtd_list, qtd_list);
 			__list_splice (qtd_list, qh->qtd_list.prev);
 
-			ehci_qtd_init (qtd, qtd->qtd_dma);
+			ehci_qtd_init(ehci, qtd, qtd->qtd_dma);
 			qh->dummy = qtd;
 
 			/* hc must see the new dummy at list end */
 			dma = qtd->qtd_dma;
 			qtd = list_entry (qh->qtd_list.prev,
 					struct ehci_qtd, qtd_list);
-			qtd->hw_next = QTD_NEXT (dma);
+			qtd->hw_next = QTD_NEXT(ehci, dma);
 
 			/* let the hc process these next qtds */
 			wmb ();
@@ -970,7 +976,7 @@
 
 	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
 
-	// qh->hw_next = cpu_to_le32 (qh->qh_dma);
+	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
 	qh->qh_next.qh = NULL;
 	qh_put (qh);			// refcount from reclaim
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 7b5ae71..d4a8ace 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -44,9 +44,10 @@
  * @tag: hardware tag for type of this record
  */
 static union ehci_shadow *
-periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
+periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic,
+		__hc32 tag)
 {
-	switch (tag) {
+	switch (hc32_to_cpu(ehci, tag)) {
 	case Q_TYPE_QH:
 		return &periodic->qh->qh_next;
 	case Q_TYPE_FSTN:
@@ -62,13 +63,14 @@
 /* caller must hold ehci->lock */
 static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 {
-	union ehci_shadow	*prev_p = &ehci->pshadow [frame];
-	__le32			*hw_p = &ehci->periodic [frame];
+	union ehci_shadow	*prev_p = &ehci->pshadow[frame];
+	__hc32			*hw_p = &ehci->periodic[frame];
 	union ehci_shadow	here = *prev_p;
 
 	/* find predecessor of "ptr"; hw and shadow lists are in sync */
 	while (here.ptr && here.ptr != ptr) {
-		prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
+		prev_p = periodic_next_shadow(ehci, prev_p,
+				Q_NEXT_TYPE(ehci, *hw_p));
 		hw_p = here.hw_next;
 		here = *prev_p;
 	}
@@ -79,7 +81,8 @@
 	/* update shadow and hardware lists ... the old "next" pointers
 	 * from ptr may still be in use, the caller updates them.
 	 */
-	*prev_p = *periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
+	*prev_p = *periodic_next_shadow(ehci, &here,
+			Q_NEXT_TYPE(ehci, *hw_p));
 	*hw_p = *here.hw_next;
 }
 
@@ -87,18 +90,19 @@
 static unsigned short
 periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 {
-	__le32			*hw_p = &ehci->periodic [frame];
+	__hc32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	*q = &ehci->pshadow [frame];
 	unsigned		usecs = 0;
 
 	while (q->ptr) {
-		switch (Q_NEXT_TYPE (*hw_p)) {
+		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
 		case Q_TYPE_QH:
 			/* is it in the S-mask? */
-			if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
+			if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
 				usecs += q->qh->usecs;
 			/* ... or C-mask? */
-			if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe)))
+			if (q->qh->hw_info2 & cpu_to_hc32(ehci,
+					1 << (8 + uframe)))
 				usecs += q->qh->c_usecs;
 			hw_p = &q->qh->hw_next;
 			q = &q->qh->qh_next;
@@ -108,7 +112,7 @@
 			/* for "save place" FSTNs, count the relevant INTR
 			 * bandwidth from the previous frame
 			 */
-			if (q->fstn->hw_prev != EHCI_LIST_END) {
+			if (q->fstn->hw_prev != EHCI_LIST_END(ehci)) {
 				ehci_dbg (ehci, "ignoring FSTN cost ...\n");
 			}
 			hw_p = &q->fstn->hw_next;
@@ -121,9 +125,10 @@
 			break;
 		case Q_TYPE_SITD:
 			/* is it in the S-mask?  (count SPLIT, DATA) */
-			if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
+			if (q->sitd->hw_uframe & cpu_to_hc32(ehci,
+					1 << uframe)) {
 				if (q->sitd->hw_fullspeed_ep &
-						__constant_cpu_to_le32 (1<<31))
+						cpu_to_hc32(ehci, 1<<31))
 					usecs += q->sitd->stream->usecs;
 				else	/* worst case for OUT start-split */
 					usecs += HS_USECS_ISO (188);
@@ -131,7 +136,7 @@
 
 			/* ... C-mask?  (count CSPLIT, DATA) */
 			if (q->sitd->hw_uframe &
-					cpu_to_le32 (1 << (8 + uframe))) {
+					cpu_to_hc32(ehci, 1 << (8 + uframe))) {
 				/* worst case for IN complete-split */
 				usecs += q->sitd->stream->c_usecs;
 			}
@@ -173,9 +178,9 @@
  * will cause a transfer in "B-frame" uframe 0.  "B-frames" lag
  * "H-frames" by 1 uframe.  See the EHCI spec sec 4.5 and figure 4.7.
  */
-static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask)
+static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
 {
-	unsigned char smask = QH_SMASK & le32_to_cpu(mask);
+	unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask);
 	if (!smask) {
 		ehci_err(ehci, "invalid empty smask!\n");
 		/* uframe 7 can't have bw so this will indicate failure */
@@ -217,14 +222,14 @@
 	unsigned short tt_usecs[8]
 )
 {
-	__le32			*hw_p = &ehci->periodic [frame];
+	__hc32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	*q = &ehci->pshadow [frame];
 	unsigned char		uf;
 
 	memset(tt_usecs, 0, 16);
 
 	while (q->ptr) {
-		switch (Q_NEXT_TYPE(*hw_p)) {
+		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
 		case Q_TYPE_ITD:
 			hw_p = &q->itd->hw_next;
 			q = &q->itd->itd_next;
@@ -247,8 +252,8 @@
 			continue;
 		// case Q_TYPE_FSTN:
 		default:
-			ehci_dbg(ehci,
-				  "ignoring periodic frame %d FSTN\n", frame);
+			ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n",
+					frame);
 			hw_p = &q->fstn->hw_next;
 			q = &q->fstn->fstn_next;
 		}
@@ -368,41 +373,42 @@
 	 */
 	for (; frame < ehci->periodic_size; frame += period) {
 		union ehci_shadow	here;
-		__le32			type;
+		__hc32			type;
 
 		here = ehci->pshadow [frame];
-		type = Q_NEXT_TYPE (ehci->periodic [frame]);
+		type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]);
 		while (here.ptr) {
-			switch (type) {
+			switch (hc32_to_cpu(ehci, type)) {
 			case Q_TYPE_ITD:
-				type = Q_NEXT_TYPE (here.itd->hw_next);
+				type = Q_NEXT_TYPE(ehci, here.itd->hw_next);
 				here = here.itd->itd_next;
 				continue;
 			case Q_TYPE_QH:
 				if (same_tt (dev, here.qh->dev)) {
 					u32		mask;
 
-					mask = le32_to_cpu (here.qh->hw_info2);
+					mask = hc32_to_cpu(ehci,
+							here.qh->hw_info2);
 					/* "knows" no gap is needed */
 					mask |= mask >> 8;
 					if (mask & uf_mask)
 						break;
 				}
-				type = Q_NEXT_TYPE (here.qh->hw_next);
+				type = Q_NEXT_TYPE(ehci, here.qh->hw_next);
 				here = here.qh->qh_next;
 				continue;
 			case Q_TYPE_SITD:
 				if (same_tt (dev, here.sitd->urb->dev)) {
 					u16		mask;
 
-					mask = le32_to_cpu (here.sitd
+					mask = hc32_to_cpu(ehci, here.sitd
 								->hw_uframe);
 					/* FIXME assumes no gap for IN! */
 					mask |= mask >> 8;
 					if (mask & uf_mask)
 						break;
 				}
-				type = Q_NEXT_TYPE (here.sitd->hw_next);
+				type = Q_NEXT_TYPE(ehci, here.sitd->hw_next);
 				here = here.sitd->sitd_next;
 				continue;
 			// case Q_TYPE_FSTN:
@@ -473,6 +479,109 @@
 }
 
 /*-------------------------------------------------------------------------*/
+#ifdef CONFIG_CPU_FREQ
+
+static int safe_to_modify_i (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+	int now; /* current (frame * 8) + uframe */
+	int prev_start, next_start; /* uframes from/to split start */
+	int start_uframe = ffs(le32_to_cpup (&qh->hw_info2) & QH_SMASK);
+	int end_uframe = fls((le32_to_cpup (&qh->hw_info2) & QH_CMASK) >> 8);
+	int split_duration = end_uframe - start_uframe;
+
+	now = readl(&ehci->regs->frame_index) % (ehci->periodic_size << 3);
+
+	next_start = ((1024 << 3) + (qh->start << 3) + start_uframe - now)
+			% (qh->period << 3);
+	prev_start = (qh->period << 3) - next_start;
+
+	/*
+	 * Make sure there will be at least one uframe when qh is safe.
+	 */
+	if ((qh->period << 3) <= (ehci->i_thresh + 2 + split_duration))
+		/* never safe */
+		return -EINVAL;
+
+	/*
+	 * Wait 1 uframe after transaction should have started, to make
+	 * sure controller has time to write back overlay, so we can
+	 * check QTD_STS_STS to see if transaction is in progress.
+	 */
+	if ((next_start > ehci->i_thresh) && (prev_start > 1))
+		/* safe to set "i" bit if split isn't in progress */
+		return (qh->hw_token & STATUS_BIT(ehci)) ? 0 : 1;
+	else
+		return 0;
+}
+
+/* Set inactivate bit for all the split interrupt QHs. */
+static void qh_inactivate_split_intr_qhs (struct ehci_hcd *ehci)
+{
+	struct ehci_qh	*qh;
+	int		not_done, safe;
+	u32		inactivate = INACTIVATE_BIT(ehci);
+	u32		active = ACTIVE_BIT(ehci);
+
+	do {
+		not_done = 0;
+		list_for_each_entry(qh, &ehci->split_intr_qhs,
+				split_intr_qhs) {
+			if (qh->hw_info1 & inactivate)
+				/* already off */
+				continue;
+			/*
+			 * To avoid setting "I" after the start split happens,
+			 * don't set it if the QH might be cached in the
+			 * controller.  Some HCs (Broadcom/ServerWorks HT1000)
+			 * will stop in the middle of a split transaction when
+			 * the "I" bit is set.
+			 */
+			safe = safe_to_modify_i(ehci, qh);
+			if (safe == 0) {
+				not_done = 1;
+			} else if (safe > 0) {
+				qh->was_active = qh->hw_token & active;
+				qh->hw_info1 |= inactivate;
+			}
+		}
+	} while (not_done);
+	wmb();
+}
+
+static void qh_reactivate_split_intr_qhs (struct ehci_hcd *ehci)
+{
+	struct ehci_qh	*qh;
+	u32		token;
+	int		not_done, safe;
+	u32		inactivate = INACTIVATE_BIT(ehci);
+	u32		active = ACTIVE_BIT(ehci);
+	u32		halt = HALT_BIT(ehci);
+
+	do {
+		not_done = 0;
+		list_for_each_entry(qh, &ehci->split_intr_qhs, split_intr_qhs) {
+			if (!(qh->hw_info1 & inactivate)) /* already on */
+				continue;
+			/*
+			 * Don't reactivate if cached, or controller might
+			 * overwrite overlay after we modify it!
+			 */
+			safe = safe_to_modify_i(ehci, qh);
+			if (safe == 0) {
+				not_done = 1;
+			} else if (safe > 0) {
+				/* See EHCI 1.0 section 4.15.2.4. */
+				token = qh->hw_token;
+				qh->hw_token = (token | halt) & ~active;
+				wmb();
+				qh->hw_info1 &= ~inactivate;
+				wmb();
+				qh->hw_token = (token & ~halt) | qh->was_active;
+			}
+		}
+	} while (not_done);
+}
+#endif
 
 /* periodic schedule slots have iso tds (normal or split) first, then a
  * sparse tree for active interrupt transfers.
@@ -487,25 +596,36 @@
 
 	dev_dbg (&qh->dev->dev,
 		"link qh%d-%04x/%p start %d [%d/%d us]\n",
-		period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
+		period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
 		qh, qh->start, qh->usecs, qh->c_usecs);
 
+#ifdef CONFIG_CPU_FREQ
+	/*
+	 * If low/full speed interrupt QHs are inactive (because of
+	 * cpufreq changing processor speeds), start QH with I flag set--
+	 * it will automatically be cleared when cpufreq is done.
+	 */
+	if (ehci->cpufreq_changing)
+		if (!(qh->hw_info1 & (cpu_to_le32(1 << 13))))
+			qh->hw_info1 |= INACTIVATE_BIT(ehci);
+#endif
+
 	/* high bandwidth, or otherwise every microframe */
 	if (period == 0)
 		period = 1;
 
 	for (i = qh->start; i < ehci->periodic_size; i += period) {
-		union ehci_shadow	*prev = &ehci->pshadow [i];
-		__le32			*hw_p = &ehci->periodic [i];
+		union ehci_shadow	*prev = &ehci->pshadow[i];
+		__hc32			*hw_p = &ehci->periodic[i];
 		union ehci_shadow	here = *prev;
-		__le32			type = 0;
+		__hc32			type = 0;
 
 		/* skip the iso nodes at list head */
 		while (here.ptr) {
-			type = Q_NEXT_TYPE (*hw_p);
-			if (type == Q_TYPE_QH)
+			type = Q_NEXT_TYPE(ehci, *hw_p);
+			if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
 				break;
-			prev = periodic_next_shadow (prev, type);
+			prev = periodic_next_shadow(ehci, prev, type);
 			hw_p = &here.qh->hw_next;
 			here = *prev;
 		}
@@ -527,7 +647,7 @@
 				qh->hw_next = *hw_p;
 			wmb ();
 			prev->qh = qh;
-			*hw_p = QH_NEXT (qh->qh_dma);
+			*hw_p = QH_NEXT (ehci, qh->qh_dma);
 		}
 	}
 	qh->qh_state = QH_STATE_LINKED;
@@ -538,6 +658,12 @@
 		? ((qh->usecs + qh->c_usecs) / qh->period)
 		: (qh->usecs * 8);
 
+#ifdef CONFIG_CPU_FREQ
+	/* add qh to list of low/full speed interrupt QHs, if applicable */
+	if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) {
+		list_add(&qh->split_intr_qhs, &ehci->split_intr_qhs);
+	}
+#endif
 	/* maybe enable periodic schedule processing */
 	if (!ehci->periodic_sched++)
 		return enable_periodic (ehci);
@@ -555,7 +681,14 @@
 	//   and this qh is active in the current uframe
 	//   (and overlay token SplitXstate is false?)
 	// THEN
-	//   qh->hw_info1 |= __constant_cpu_to_le32 (1 << 7 /* "ignore" */);
+	//   qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */);
+
+#ifdef CONFIG_CPU_FREQ
+	/* remove qh from list of low/full speed interrupt QHs */
+	if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) {
+		list_del_init(&qh->split_intr_qhs);
+	}
+#endif
 
 	/* high bandwidth, or otherwise part of every microframe */
 	if ((period = qh->period) == 0)
@@ -572,7 +705,7 @@
 	dev_dbg (&qh->dev->dev,
 		"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
 		qh->period,
-		le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
+		hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
 		qh, qh->start, qh->usecs, qh->c_usecs);
 
 	/* qh->qh_next still "live" to HC */
@@ -598,7 +731,7 @@
 	 * active high speed queues may need bigger delays...
 	 */
 	if (list_empty (&qh->qtd_list)
-			|| (__constant_cpu_to_le32 (QH_CMASK)
+			|| (cpu_to_hc32(ehci, QH_CMASK)
 					& qh->hw_info2) != 0)
 		wait = 2;
 	else
@@ -606,7 +739,7 @@
 
 	udelay (wait);
 	qh->qh_state = QH_STATE_IDLE;
-	qh->hw_next = EHCI_LIST_END;
+	qh->hw_next = EHCI_LIST_END(ehci);
 	wmb ();
 }
 
@@ -663,7 +796,7 @@
 	unsigned		frame,
 	unsigned		uframe,
 	const struct ehci_qh	*qh,
-	__le32			*c_maskp
+	__hc32			*c_maskp
 )
 {
 	int		retval = -ENOSPC;
@@ -695,7 +828,7 @@
 
 		retval = 0;
 
-		*c_maskp = cpu_to_le32 (mask << 8);
+		*c_maskp = cpu_to_hc32(ehci, mask << 8);
 	}
 #else
 	/* Make sure this tt's buffer is also available for CSPLITs.
@@ -706,7 +839,7 @@
 	 * one smart pass...
 	 */
 	mask = 0x03 << (uframe + qh->gap_uf);
-	*c_maskp = cpu_to_le32 (mask << 8);
+	*c_maskp = cpu_to_hc32(ehci, mask << 8);
 
 	mask |= 1 << uframe;
 	if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) {
@@ -726,20 +859,20 @@
 /* "first fit" scheduling policy used the first time through,
  * or when the previous schedule slot can't be re-used.
  */
-static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	int		status;
 	unsigned	uframe;
-	__le32		c_mask;
+	__hc32		c_mask;
 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
 
 	qh_refresh(ehci, qh);
-	qh->hw_next = EHCI_LIST_END;
+	qh->hw_next = EHCI_LIST_END(ehci);
 	frame = qh->start;
 
 	/* reuse the previous schedule slots, if we can */
 	if (frame < qh->period) {
-		uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK);
+		uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK);
 		status = check_intr_schedule (ehci, frame, --uframe,
 				qh, &c_mask);
 	} else {
@@ -775,10 +908,10 @@
 		qh->start = frame;
 
 		/* reset S-frame and (maybe) C-frame masks */
-		qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
+		qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
 		qh->hw_info2 |= qh->period
-			? cpu_to_le32 (1 << uframe)
-			: __constant_cpu_to_le32 (QH_SMASK);
+			? cpu_to_hc32(ehci, 1 << uframe)
+			: cpu_to_hc32(ehci, QH_SMASK);
 		qh->hw_info2 |= c_mask;
 	} else
 		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
@@ -808,7 +941,7 @@
 	spin_lock_irqsave (&ehci->lock, flags);
 
 	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
-			       &ehci_to_hcd(ehci)->flags))) {
+			&ehci_to_hcd(ehci)->flags))) {
 		status = -ESHUTDOWN;
 		goto done;
 	}
@@ -898,9 +1031,9 @@
 		buf1 |= maxp;
 		maxp *= multi;
 
-		stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum);
-		stream->buf1 = cpu_to_le32 (buf1);
-		stream->buf2 = cpu_to_le32 (multi);
+		stream->buf0 = cpu_to_hc32(ehci, (epnum << 8) | dev->devnum);
+		stream->buf1 = cpu_to_hc32(ehci, buf1);
+		stream->buf2 = cpu_to_hc32(ehci, multi);
 
 		/* usbfs wants to report the average usecs per frame tied up
 		 * when transfers on this endpoint are scheduled ...
@@ -943,7 +1076,7 @@
 		bandwidth /= 1 << (interval + 2);
 
 		/* stream->splits gets created from raw_mask later */
-		stream->address = cpu_to_le32 (addr);
+		stream->address = cpu_to_hc32(ehci, addr);
 	}
 	stream->bandwidth = bandwidth;
 
@@ -1077,7 +1210,8 @@
 }
 
 static inline void
-itd_sched_init (
+itd_sched_init(
+	struct ehci_hcd		*ehci,
 	struct ehci_iso_sched	*iso_sched,
 	struct ehci_iso_stream	*stream,
 	struct urb		*urb
@@ -1107,7 +1241,7 @@
 				&& !(urb->transfer_flags & URB_NO_INTERRUPT))
 			trans |= EHCI_ITD_IOC;
 		trans |= length << 16;
-		uframe->transaction = cpu_to_le32 (trans);
+		uframe->transaction = cpu_to_hc32(ehci, trans);
 
 		/* might need to cross a buffer page within a uframe */
 		uframe->bufp = (buf & ~(u64)0x0fff);
@@ -1149,7 +1283,7 @@
 	if (unlikely (sched == NULL))
 		return -ENOMEM;
 
-	itd_sched_init (sched, stream, urb);
+	itd_sched_init(ehci, sched, stream, urb);
 
 	if (urb->interval < 8)
 		num_itds = 1 + (sched->span + 7) / 8;
@@ -1167,7 +1301,7 @@
 		/* prefer previously-allocated itds */
 		if (likely (!list_empty(&stream->free_list))) {
 			itd = list_entry (stream->free_list.prev,
-					 struct ehci_itd, itd_list);
+					struct ehci_itd, itd_list);
 			list_del (&itd->itd_list);
 			itd_dma = itd->itd_dma;
 		} else
@@ -1294,7 +1428,7 @@
 		uframe += period_uframes;
 	} while (uframe < mod);
 
-	stream->splits = cpu_to_le32(stream->raw_mask << (uframe & 7));
+	stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7));
 	return 1;
 }
 
@@ -1415,12 +1549,13 @@
 /*-------------------------------------------------------------------------*/
 
 static inline void
-itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
+itd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream,
+		struct ehci_itd *itd)
 {
 	int i;
 
 	/* it's been recently zeroed */
-	itd->hw_next = EHCI_LIST_END;
+	itd->hw_next = EHCI_LIST_END(ehci);
 	itd->hw_bufp [0] = stream->buf0;
 	itd->hw_bufp [1] = stream->buf1;
 	itd->hw_bufp [2] = stream->buf2;
@@ -1432,7 +1567,8 @@
 }
 
 static inline void
-itd_patch (
+itd_patch(
+	struct ehci_hcd		*ehci,
 	struct ehci_itd		*itd,
 	struct ehci_iso_sched	*iso_sched,
 	unsigned		index,
@@ -1447,17 +1583,18 @@
 	uframe &= 0x07;
 	itd->index [uframe] = index;
 
-	itd->hw_transaction [uframe] = uf->transaction;
-	itd->hw_transaction [uframe] |= cpu_to_le32 (pg << 12);
-	itd->hw_bufp [pg] |= cpu_to_le32 (uf->bufp & ~(u32)0);
-	itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32));
+	itd->hw_transaction[uframe] = uf->transaction;
+	itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12);
+	itd->hw_bufp[pg] |= cpu_to_hc32(ehci, uf->bufp & ~(u32)0);
+	itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32));
 
 	/* iso_frame_desc[].offset must be strictly increasing */
 	if (unlikely (uf->cross)) {
 		u64	bufp = uf->bufp + 4096;
+
 		itd->pg = ++pg;
-		itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0);
-		itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(bufp >> 32));
+		itd->hw_bufp[pg] |= cpu_to_hc32(ehci, bufp & ~(u32)0);
+		itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(bufp >> 32));
 	}
 }
 
@@ -1470,7 +1607,7 @@
 	ehci->pshadow [frame].itd = itd;
 	itd->frame = frame;
 	wmb ();
-	ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
+	ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
 }
 
 /* fit urb's itds into the selected schedule slot; activate as needed */
@@ -1515,14 +1652,14 @@
 			list_move_tail (&itd->itd_list, &stream->td_list);
 			itd->stream = iso_stream_get (stream);
 			itd->urb = usb_get_urb (urb);
-			itd_init (stream, itd);
+			itd_init (ehci, stream, itd);
 		}
 
 		uframe = next_uframe & 0x07;
 		frame = next_uframe >> 3;
 
 		itd->usecs [uframe] = stream->usecs;
-		itd_patch (itd, iso_sched, packet, uframe);
+		itd_patch(ehci, itd, iso_sched, packet, uframe);
 
 		next_uframe += stream->interval;
 		stream->depth += stream->interval;
@@ -1570,7 +1707,7 @@
 		urb_index = itd->index[uframe];
 		desc = &urb->iso_frame_desc [urb_index];
 
-		t = le32_to_cpup (&itd->hw_transaction [uframe]);
+		t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]);
 		itd->hw_transaction [uframe] = 0;
 		stream->depth -= stream->interval;
 
@@ -1700,7 +1837,8 @@
  */
 
 static inline void
-sitd_sched_init (
+sitd_sched_init(
+	struct ehci_hcd		*ehci,
 	struct ehci_iso_sched	*iso_sched,
 	struct ehci_iso_stream	*stream,
 	struct urb		*urb
@@ -1729,7 +1867,7 @@
 				&& !(urb->transfer_flags & URB_NO_INTERRUPT))
 			trans |= SITD_IOC;
 		trans |= length << 16;
-		packet->transaction = cpu_to_le32 (trans);
+		packet->transaction = cpu_to_hc32(ehci, trans);
 
 		/* might need to cross a buffer page within a td */
 		packet->bufp = buf;
@@ -1765,7 +1903,7 @@
 	if (iso_sched == NULL)
 		return -ENOMEM;
 
-	sitd_sched_init (iso_sched, stream, urb);
+	sitd_sched_init(ehci, iso_sched, stream, urb);
 
 	/* allocate/init sITDs */
 	spin_lock_irqsave (&ehci->lock, flags);
@@ -1817,7 +1955,8 @@
 /*-------------------------------------------------------------------------*/
 
 static inline void
-sitd_patch (
+sitd_patch(
+	struct ehci_hcd		*ehci,
 	struct ehci_iso_stream	*stream,
 	struct ehci_sitd	*sitd,
 	struct ehci_iso_sched	*iso_sched,
@@ -1827,20 +1966,20 @@
 	struct ehci_iso_packet	*uf = &iso_sched->packet [index];
 	u64			bufp = uf->bufp;
 
-	sitd->hw_next = EHCI_LIST_END;
+	sitd->hw_next = EHCI_LIST_END(ehci);
 	sitd->hw_fullspeed_ep = stream->address;
 	sitd->hw_uframe = stream->splits;
 	sitd->hw_results = uf->transaction;
-	sitd->hw_backpointer = EHCI_LIST_END;
+	sitd->hw_backpointer = EHCI_LIST_END(ehci);
 
 	bufp = uf->bufp;
-	sitd->hw_buf [0] = cpu_to_le32 (bufp);
-	sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32);
+	sitd->hw_buf[0] = cpu_to_hc32(ehci, bufp);
+	sitd->hw_buf_hi[0] = cpu_to_hc32(ehci, bufp >> 32);
 
-	sitd->hw_buf [1] = cpu_to_le32 (uf->buf1);
+	sitd->hw_buf[1] = cpu_to_hc32(ehci, uf->buf1);
 	if (uf->cross)
 		bufp += 4096;
-	sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
+	sitd->hw_buf_hi[1] = cpu_to_hc32(ehci, bufp >> 32);
 	sitd->index = index;
 }
 
@@ -1853,7 +1992,7 @@
 	ehci->pshadow [frame].sitd = sitd;
 	sitd->frame = frame;
 	wmb ();
-	ehci->periodic [frame] = cpu_to_le32 (sitd->sitd_dma) | Q_TYPE_SITD;
+	ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD);
 }
 
 /* fit urb's sitds into the selected schedule slot; activate as needed */
@@ -1881,7 +2020,7 @@
 			urb->dev->devpath, stream->bEndpointAddress & 0x0f,
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
 			(next_uframe >> 3) % ehci->periodic_size,
-			stream->interval, le32_to_cpu (stream->splits));
+			stream->interval, hc32_to_cpu(ehci, stream->splits));
 		stream->start = jiffies;
 	}
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -1902,7 +2041,7 @@
 		sitd->stream = iso_stream_get (stream);
 		sitd->urb = usb_get_urb (urb);
 
-		sitd_patch (stream, sitd, sched, packet);
+		sitd_patch(ehci, stream, sitd, sched, packet);
 		sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
 				sitd);
 
@@ -1940,7 +2079,7 @@
 
 	urb_index = sitd->index;
 	desc = &urb->iso_frame_desc [urb_index];
-	t = le32_to_cpup (&sitd->hw_results);
+	t = hc32_to_cpup(ehci, &sitd->hw_results);
 
 	/* report transfer status */
 	if (t & SITD_ERRS) {
@@ -2095,7 +2234,7 @@
 
 	for (;;) {
 		union ehci_shadow	q, *q_p;
-		__le32			type, *hw_p;
+		__hc32			type, *hw_p;
 		unsigned		uframes;
 
 		/* don't scan past the live uframe */
@@ -2113,7 +2252,7 @@
 		q_p = &ehci->pshadow [frame];
 		hw_p = &ehci->periodic [frame];
 		q.ptr = q_p->ptr;
-		type = Q_NEXT_TYPE (*hw_p);
+		type = Q_NEXT_TYPE(ehci, *hw_p);
 		modified = 0;
 
 		while (q.ptr != NULL) {
@@ -2122,11 +2261,11 @@
 			int			live;
 
 			live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state);
-			switch (type) {
+			switch (hc32_to_cpu(ehci, type)) {
 			case Q_TYPE_QH:
 				/* handle any completions */
 				temp.qh = qh_get (q.qh);
-				type = Q_NEXT_TYPE (q.qh->hw_next);
+				type = Q_NEXT_TYPE(ehci, q.qh->hw_next);
 				q = q.qh->qh_next;
 				modified = qh_completions (ehci, temp.qh);
 				if (unlikely (list_empty (&temp.qh->qtd_list)))
@@ -2137,10 +2276,10 @@
 				/* for "save place" FSTNs, look at QH entries
 				 * in the previous frame for completions.
 				 */
-				if (q.fstn->hw_prev != EHCI_LIST_END) {
+				if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) {
 					dbg ("ignoring completions from FSTNs");
 				}
-				type = Q_NEXT_TYPE (q.fstn->hw_next);
+				type = Q_NEXT_TYPE(ehci, q.fstn->hw_next);
 				q = q.fstn->fstn_next;
 				break;
 			case Q_TYPE_ITD:
@@ -2148,11 +2287,12 @@
 				rmb ();
 				for (uf = live ? uframes : 8; uf < 8; uf++) {
 					if (0 == (q.itd->hw_transaction [uf]
-							& ITD_ACTIVE))
+							& ITD_ACTIVE(ehci)))
 						continue;
 					q_p = &q.itd->itd_next;
 					hw_p = &q.itd->hw_next;
-					type = Q_NEXT_TYPE (q.itd->hw_next);
+					type = Q_NEXT_TYPE(ehci,
+							q.itd->hw_next);
 					q = *q_p;
 					break;
 				}
@@ -2164,23 +2304,24 @@
 				 */
 				*q_p = q.itd->itd_next;
 				*hw_p = q.itd->hw_next;
-				type = Q_NEXT_TYPE (q.itd->hw_next);
+				type = Q_NEXT_TYPE(ehci, q.itd->hw_next);
 				wmb();
 				modified = itd_complete (ehci, q.itd);
 				q = *q_p;
 				break;
 			case Q_TYPE_SITD:
-				if ((q.sitd->hw_results & SITD_ACTIVE)
+				if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
 						&& live) {
 					q_p = &q.sitd->sitd_next;
 					hw_p = &q.sitd->hw_next;
-					type = Q_NEXT_TYPE (q.sitd->hw_next);
+					type = Q_NEXT_TYPE(ehci,
+							q.sitd->hw_next);
 					q = *q_p;
 					break;
 				}
 				*q_p = q.sitd->sitd_next;
 				*hw_p = q.sitd->hw_next;
-				type = Q_NEXT_TYPE (q.sitd->hw_next);
+				type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
 				wmb();
 				modified = sitd_complete (ehci, q.sitd);
 				q = *q_p;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 46fa57a..2c68a04 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -21,6 +21,22 @@
 
 /* definitions used for the EHCI driver */
 
+/*
+ * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
+ * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on
+ * the host controller implementation.
+ *
+ * To facilitate the strongest possible byte-order checking from "sparse"
+ * and so on, we use __leXX unless that's not practical.
+ */
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+typedef __u32 __bitwise __hc32;
+typedef __u16 __bitwise __hc16;
+#else
+#define __hc32	__le32
+#define __hc16	__le16
+#endif
+
 /* statistics can be kept for for tuning/monitoring */
 struct ehci_stats {
 	/* irq usage */
@@ -55,6 +71,12 @@
 	__u32			hcs_params;	/* cached register copy */
 	spinlock_t		lock;
 
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	cpufreq_transition;
+	int			cpufreq_changing;
+	struct list_head	split_intr_qhs;
+#endif
+
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
@@ -64,7 +86,7 @@
 	/* periodic schedule support */
 #define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
 	unsigned		periodic_size;
-	__le32			*periodic;	/* hw periodic table */
+	__hc32			*periodic;	/* hw periodic table */
 	dma_addr_t		periodic_dma;
 	unsigned		i_thresh;	/* uframes HC might cache */
 
@@ -74,11 +96,14 @@
 
 	/* per root hub port */
 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
+
 	/* bit vectors (one bit per port) */
 	unsigned long		bus_suspended;		/* which ports were
 			already suspended at the start of a bus suspend */
 	unsigned long		companion_ports;	/* which ports are
 			dedicated to the companion controller */
+	unsigned long		owned_ports;		/* which ports are
+			owned by the companion during a bus suspend */
 
 	/* per-HC memory pools (could be per-bus, but ...) */
 	struct dma_pool		*qh_pool;	/* qh per active urb */
@@ -97,6 +122,7 @@
 	unsigned		no_selective_suspend:1;
 	unsigned		has_fsl_port_bug:1; /* FreeScale */
 	unsigned		big_endian_mmio:1;
+	unsigned		big_endian_desc:1;
 
 	u8			sbrn;		/* packed release number */
 
@@ -276,6 +302,12 @@
 #define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
 } __attribute__ ((packed));
 
+#define USBMODE		0x68		/* USB Device mode */
+#define USBMODE_SDIS	(1<<3)		/* Stream disable */
+#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 */
+
 /* Appendix C, Debug port ... intended for use with special "debug devices"
  * that can help if there's no serial console.  (nonstandard enumeration.)
  */
@@ -303,7 +335,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define	QTD_NEXT(dma)	cpu_to_le32((u32)dma)
+#define	QTD_NEXT(ehci, dma)	cpu_to_hc32(ehci, (u32)dma)
 
 /*
  * EHCI Specification 0.95 Section 3.5
@@ -315,9 +347,9 @@
  */
 struct ehci_qtd {
 	/* first part defined by EHCI spec */
-	__le32			hw_next;	  /* see EHCI 3.5.1 */
-	__le32			hw_alt_next;      /* see EHCI 3.5.2 */
-	__le32			hw_token;         /* see EHCI 3.5.3 */
+	__hc32			hw_next;	/* see EHCI 3.5.1 */
+	__hc32			hw_alt_next;    /* see EHCI 3.5.2 */
+	__hc32			hw_token;       /* see EHCI 3.5.3 */
 #define	QTD_TOGGLE	(1 << 31)	/* data toggle */
 #define	QTD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
 #define	QTD_IOC		(1 << 15)	/* interrupt on complete */
@@ -331,8 +363,13 @@
 #define	QTD_STS_MMF	(1 << 2)	/* incomplete split transaction */
 #define	QTD_STS_STS	(1 << 1)	/* split transaction state */
 #define	QTD_STS_PING	(1 << 0)	/* issue PING? */
-	__le32			hw_buf [5];        /* see EHCI 3.5.4 */
-	__le32			hw_buf_hi [5];        /* Appendix B */
+
+#define ACTIVE_BIT(ehci)	cpu_to_hc32(ehci, QTD_STS_ACTIVE)
+#define HALT_BIT(ehci)		cpu_to_hc32(ehci, QTD_STS_HALT)
+#define STATUS_BIT(ehci)	cpu_to_hc32(ehci, QTD_STS_STS)
+
+	__hc32			hw_buf [5];        /* see EHCI 3.5.4 */
+	__hc32			hw_buf_hi [5];        /* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		qtd_dma;		/* qtd address */
@@ -342,26 +379,33 @@
 } __attribute__ ((aligned (32)));
 
 /* mask NakCnt+T in qh->hw_alt_next */
-#define QTD_MASK __constant_cpu_to_le32 (~0x1f)
+#define QTD_MASK(ehci)	cpu_to_hc32 (ehci, ~0x1f)
 
 #define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
 
 /*-------------------------------------------------------------------------*/
 
 /* type tag from {qh,itd,sitd,fstn}->hw_next */
-#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
+#define Q_NEXT_TYPE(ehci,dma)	((dma) & cpu_to_hc32(ehci, 3 << 1))
 
+/*
+ * Now the following defines are not converted using the
+ * __constant_cpu_to_le32() macro anymore, since we have to support
+ * "dynamic" switching between be and le support, so that the driver
+ * can be used on one system with SoC EHCI controller using big-endian
+ * descriptors as well as a normal little-endian PCI EHCI controller.
+ */
 /* values for that type tag */
-#define Q_TYPE_ITD	__constant_cpu_to_le32 (0 << 1)
-#define Q_TYPE_QH	__constant_cpu_to_le32 (1 << 1)
-#define Q_TYPE_SITD	__constant_cpu_to_le32 (2 << 1)
-#define Q_TYPE_FSTN	__constant_cpu_to_le32 (3 << 1)
+#define Q_TYPE_ITD	(0 << 1)
+#define Q_TYPE_QH	(1 << 1)
+#define Q_TYPE_SITD	(2 << 1)
+#define Q_TYPE_FSTN	(3 << 1)
 
 /* next async queue entry, or pointer to interrupt/periodic QH */
-#define	QH_NEXT(dma)	(cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
+#define QH_NEXT(ehci,dma)	(cpu_to_hc32(ehci, (((u32)dma)&~0x01f)|Q_TYPE_QH))
 
 /* for periodic/async schedules and qtd lists, mark end of list */
-#define	EHCI_LIST_END	__constant_cpu_to_le32(1) /* "null pointer" to hw */
+#define EHCI_LIST_END(ehci)	cpu_to_hc32(ehci, 1) /* "null pointer" to hw */
 
 /*
  * Entries in periodic shadow table are pointers to one of four kinds
@@ -376,7 +420,7 @@
 	struct ehci_itd		*itd;		/* Q_TYPE_ITD */
 	struct ehci_sitd	*sitd;		/* Q_TYPE_SITD */
 	struct ehci_fstn	*fstn;		/* Q_TYPE_FSTN */
-	__le32			*hw_next;	/* (all types) */
+	__hc32			*hw_next;	/* (all types) */
 	void			*ptr;
 };
 
@@ -392,23 +436,27 @@
 
 struct ehci_qh {
 	/* first part defined by EHCI spec */
-	__le32			hw_next;	 /* see EHCI 3.6.1 */
-	__le32			hw_info1;        /* see EHCI 3.6.2 */
+	__hc32			hw_next;	/* see EHCI 3.6.1 */
+	__hc32			hw_info1;       /* see EHCI 3.6.2 */
 #define	QH_HEAD		0x00008000
-	__le32			hw_info2;        /* see EHCI 3.6.2 */
+#define	QH_INACTIVATE	0x00000080
+
+#define INACTIVATE_BIT(ehci)	cpu_to_hc32(ehci, QH_INACTIVATE)
+
+	__hc32			hw_info2;        /* see EHCI 3.6.2 */
 #define	QH_SMASK	0x000000ff
 #define	QH_CMASK	0x0000ff00
 #define	QH_HUBADDR	0x007f0000
 #define	QH_HUBPORT	0x3f800000
 #define	QH_MULT		0xc0000000
-	__le32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
+	__hc32			hw_current;	/* qtd list - see EHCI 3.6.4 */
 
 	/* qtd overlay (hardware parts of a struct ehci_qtd) */
-	__le32			hw_qtd_next;
-	__le32			hw_alt_next;
-	__le32			hw_token;
-	__le32			hw_buf [5];
-	__le32			hw_buf_hi [5];
+	__hc32			hw_qtd_next;
+	__hc32			hw_alt_next;
+	__hc32			hw_token;
+	__hc32			hw_buf [5];
+	__hc32			hw_buf_hi [5];
 
 	/* the rest is HCD-private */
 	dma_addr_t		qh_dma;		/* address of qh */
@@ -418,7 +466,14 @@
 	struct ehci_qh		*reclaim;	/* next to reclaim */
 
 	struct ehci_hcd		*ehci;
-	struct kref		kref;
+
+	/*
+	 * Do NOT use atomic operations for QH refcounting. On some CPUs
+	 * (PPC7448 for example), atomic operations cannot be performed on
+	 * memory that is cache-inhibited (i.e. being used for DMA).
+	 * Spinlocks are used to protect all QH fields.
+	 */
+	u32			refcount;
 	unsigned		stamp;
 
 	u8			qh_state;
@@ -437,6 +492,10 @@
 	unsigned short		start;		/* where polling starts */
 #define NO_FRAME ((unsigned short)~0)			/* pick new start */
 	struct usb_device	*dev;		/* access to TT */
+#ifdef CONFIG_CPU_FREQ
+	struct list_head	split_intr_qhs; /* list of split qhs */
+	__le32			was_active;	/* active bit before "i" set */
+#endif
 } __attribute__ ((aligned (32)));
 
 /*-------------------------------------------------------------------------*/
@@ -445,7 +504,7 @@
 struct ehci_iso_packet {
 	/* These will be copied to iTD when scheduling */
 	u64			bufp;		/* itd->hw_bufp{,_hi}[pg] |= */
-	__le32			transaction;	/* itd->hw_transaction[i] |= */
+	__hc32			transaction;	/* itd->hw_transaction[i] |= */
 	u8			cross;		/* buf crosses pages */
 	/* for full speed OUT splits */
 	u32			buf1;
@@ -467,8 +526,8 @@
  */
 struct ehci_iso_stream {
 	/* first two fields match QH, but info1 == 0 */
-	__le32			hw_next;
-	__le32			hw_info1;
+	__hc32			hw_next;
+	__hc32			hw_info1;
 
 	u32			refcount;
 	u8			bEndpointAddress;
@@ -483,7 +542,7 @@
 	unsigned long		start;		/* jiffies */
 	unsigned long		rescheduled;
 	int			next_uframe;
-	__le32			splits;
+	__hc32			splits;
 
 	/* the rest is derived from the endpoint descriptor,
 	 * trusting urb->interval == f(epdesc->bInterval) and
@@ -497,12 +556,12 @@
 	unsigned		bandwidth;
 
 	/* This is used to initialize iTD's hw_bufp fields */
-	__le32			buf0;
-	__le32			buf1;
-	__le32			buf2;
+	__hc32			buf0;
+	__hc32			buf1;
+	__hc32			buf2;
 
 	/* this is used to initialize sITD's tt info */
-	__le32			address;
+	__hc32			address;
 };
 
 /*-------------------------------------------------------------------------*/
@@ -515,8 +574,8 @@
  */
 struct ehci_itd {
 	/* first part defined by EHCI spec */
-	__le32			hw_next;           /* see EHCI 3.3.1 */
-	__le32			hw_transaction [8]; /* see EHCI 3.3.2 */
+	__hc32			hw_next;           /* see EHCI 3.3.1 */
+	__hc32			hw_transaction [8]; /* see EHCI 3.3.2 */
 #define EHCI_ISOC_ACTIVE        (1<<31)        /* activate transfer this slot */
 #define EHCI_ISOC_BUF_ERR       (1<<30)        /* Data buffer error */
 #define EHCI_ISOC_BABBLE        (1<<29)        /* babble detected */
@@ -524,10 +583,10 @@
 #define	EHCI_ITD_LENGTH(tok)	(((tok)>>16) & 0x0fff)
 #define	EHCI_ITD_IOC		(1 << 15)	/* interrupt on complete */
 
-#define ITD_ACTIVE	__constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
+#define ITD_ACTIVE(ehci)	cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE)
 
-	__le32			hw_bufp [7];	/* see EHCI 3.3.3 */
-	__le32			hw_bufp_hi [7];	/* Appendix B */
+	__hc32			hw_bufp [7];	/* see EHCI 3.3.3 */
+	__hc32			hw_bufp_hi [7];	/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		itd_dma;	/* for this itd */
@@ -554,11 +613,11 @@
  */
 struct ehci_sitd {
 	/* first part defined by EHCI spec */
-	__le32			hw_next;
+	__hc32			hw_next;
 /* uses bit field macros above - see EHCI 0.95 Table 3-8 */
-	__le32			hw_fullspeed_ep;	/* EHCI table 3-9 */
-	__le32			hw_uframe;		/* EHCI table 3-10 */
-	__le32			hw_results;		/* EHCI table 3-11 */
+	__hc32			hw_fullspeed_ep;	/* EHCI table 3-9 */
+	__hc32			hw_uframe;		/* EHCI table 3-10 */
+	__hc32			hw_results;		/* EHCI table 3-11 */
 #define	SITD_IOC	(1 << 31)	/* interrupt on completion */
 #define	SITD_PAGE	(1 << 30)	/* buffer 0/1 */
 #define	SITD_LENGTH(x)	(0x3ff & ((x)>>16))
@@ -570,11 +629,11 @@
 #define	SITD_STS_MMF	(1 << 2)	/* incomplete split transaction */
 #define	SITD_STS_STS	(1 << 1)	/* split transaction state */
 
-#define SITD_ACTIVE	__constant_cpu_to_le32(SITD_STS_ACTIVE)
+#define SITD_ACTIVE(ehci)	cpu_to_hc32(ehci, SITD_STS_ACTIVE)
 
-	__le32			hw_buf [2];		/* EHCI table 3-12 */
-	__le32			hw_backpointer;		/* EHCI table 3-13 */
-	__le32			hw_buf_hi [2];		/* Appendix B */
+	__hc32			hw_buf [2];		/* EHCI table 3-12 */
+	__hc32			hw_backpointer;		/* EHCI table 3-13 */
+	__hc32			hw_buf_hi [2];		/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		sitd_dma;
@@ -599,8 +658,8 @@
  * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
  */
 struct ehci_fstn {
-	__le32			hw_next;	/* any periodic q entry */
-	__le32			hw_prev;	/* qh or EHCI_LIST_END */
+	__hc32			hw_next;	/* any periodic q entry */
+	__hc32			hw_prev;	/* qh or EHCI_LIST_END */
 
 	/* the rest is HCD-private */
 	dma_addr_t		fstn_dma;
@@ -672,8 +731,21 @@
 #define ehci_big_endian_mmio(e)		0
 #endif
 
-static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
-				       __u32 __iomem * regs)
+/*
+ * Big-endian read/write functions are arch-specific.
+ * Other arches can be added if/when they're needed.
+ *
+ * REVISIT: arch/powerpc now has readl/writel_be, so the
+ * definition below can die once the 4xx support is
+ * finally ported over.
+ */
+#if defined(CONFIG_PPC)
+#define readl_be(addr)		in_be32((__force unsigned *)addr)
+#define writel_be(val, addr)	out_be32((__force unsigned *)addr, val)
+#endif
+
+static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
+		__u32 __iomem * regs)
 {
 #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
 	return ehci_big_endian_mmio(ehci) ?
@@ -684,8 +756,8 @@
 #endif
 }
 
-static inline void ehci_writel (const struct ehci_hcd *ehci,
-				const unsigned int val, __u32 __iomem *regs)
+static inline void ehci_writel(const struct ehci_hcd *ehci,
+		const unsigned int val, __u32 __iomem *regs)
 {
 #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
 	ehci_big_endian_mmio(ehci) ?
@@ -698,6 +770,62 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * The AMCC 440EPx not only implements its EHCI registers in big-endian
+ * format, but also its DMA data structures (descriptors).
+ *
+ * EHCI controllers accessed through PCI work normally (little-endian
+ * everywhere), so we won't bother supporting a BE-only mode for now.
+ */
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+#define ehci_big_endian_desc(e)		((e)->big_endian_desc)
+
+/* cpu to ehci */
+static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x)
+{
+	return ehci_big_endian_desc(ehci)
+		? (__force __hc32)cpu_to_be32(x)
+		: (__force __hc32)cpu_to_le32(x);
+}
+
+/* ehci to cpu */
+static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x)
+{
+	return ehci_big_endian_desc(ehci)
+		? be32_to_cpu((__force __be32)x)
+		: le32_to_cpu((__force __le32)x);
+}
+
+static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+{
+	return ehci_big_endian_desc(ehci)
+		? be32_to_cpup((__force __be32 *)x)
+		: le32_to_cpup((__force __le32 *)x);
+}
+
+#else
+
+/* cpu to ehci */
+static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x)
+{
+	return cpu_to_le32(x);
+}
+
+/* ehci to cpu */
+static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x)
+{
+	return le32_to_cpu(x);
+}
+
+static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+{
+	return le32_to_cpup(x);
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 #ifndef DEBUG
 #define STUB_DEBUG_FILES
 #endif	/* DEBUG */
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 273d5dd..6f9e43e 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -23,7 +23,7 @@
 /* debug| print the main components of an URB
  * small: 0) header + data packets 1) just header
  */
-static void __attribute__((unused))
+static void __maybe_unused
 urb_print (struct urb * urb, char * str, int small)
 {
 	unsigned int pipe= urb->pipe;
@@ -338,7 +338,7 @@
 }
 
 /* caller MUST own hcd spinlock if verbose is set! */
-static void __attribute__((unused))
+static void __maybe_unused
 ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
 		const struct ed *ed, int verbose)
 {
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index a66637e..2038125 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -35,15 +35,13 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 #include <linux/reboot.h>
+#include <linux/workqueue.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
 
 #include "../core/hcd.h"
 
@@ -82,6 +80,8 @@
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
 static int ohci_init (struct ohci_hcd *ohci);
 static void ohci_stop (struct usb_hcd *hcd);
+static int ohci_restart (struct ohci_hcd *ohci);
+static void ohci_quirk_nec_worker (struct work_struct *work);
 
 #include "ohci-hub.c"
 #include "ohci-dbg.c"
@@ -510,15 +510,7 @@
 	// flush the writes
 	(void) ohci_readl (ohci, &ohci->regs->control);
 	msleep(temp);
-	temp = roothub_a (ohci);
-	if (!(temp & RH_A_NPS)) {
-		/* power down each port */
-		for (temp = 0; temp < ohci->num_ports; temp++)
-			ohci_writel (ohci, RH_PS_LSDA,
-				&ohci->regs->roothub.portstatus [temp]);
-	}
-	// flush those writes
-	(void) ohci_readl (ohci, &ohci->regs->control);
+
 	memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
 
 	/* 2msec timelimit here means no irqs/preempt */
@@ -659,9 +651,20 @@
 	}
 
 	if (ints & OHCI_INTR_UE) {
-		disable (ohci);
-		ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
 		// e.g. due to PCI Master/Target Abort
+		if (ohci->flags & OHCI_QUIRK_NEC) {
+			/* Workaround for a silicon bug in some NEC chips used
+			 * in Apple's PowerBooks. Adapted from Darwin code.
+			 */
+			ohci_err (ohci, "OHCI Unrecoverable Error, scheduling NEC chip restart\n");
+
+			ohci_writel (ohci, OHCI_INTR_UE, &regs->intrdisable);
+
+			schedule_work (&ohci->nec_work);
+		} else {
+			disable (ohci);
+			ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
+		}
 
 		ohci_dump (ohci, 1);
 		ohci_usb_reset (ohci);
@@ -763,23 +766,16 @@
 /*-------------------------------------------------------------------------*/
 
 /* must not be called from interrupt context */
-
-#ifdef	CONFIG_PM
-
 static int ohci_restart (struct ohci_hcd *ohci)
 {
 	int temp;
 	int i;
 	struct urb_priv *priv;
 
-	/* mark any devices gone, so they do nothing till khubd disconnects.
-	 * recycle any "live" eds/tds (and urbs) right away.
-	 * later, khubd disconnect processing will recycle the other state,
-	 * (either as disconnect/reconnect, or maybe someday as a reset).
-	 */
 	spin_lock_irq(&ohci->lock);
 	disable (ohci);
-	usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
+
+	/* Recycle any "live" eds/tds (and urbs). */
 	if (!list_empty (&ohci->pending))
 		ohci_dbg(ohci, "abort schedule...\n");
 	list_for_each_entry (priv, &ohci->pending, pending) {
@@ -826,20 +822,31 @@
 	if ((temp = ohci_run (ohci)) < 0) {
 		ohci_err (ohci, "can't restart, %d\n", temp);
 		return temp;
-	} else {
-		/* here we "know" root ports should always stay powered,
-		 * and that if we try to turn them back on the root hub
-		 * will respond to CSC processing.
-		 */
-		i = ohci->num_ports;
-		while (i--)
-			ohci_writel (ohci, RH_PS_PSS,
-				&ohci->regs->roothub.portstatus [i]);
-		ohci_dbg (ohci, "restart complete\n");
 	}
+	ohci_dbg(ohci, "restart complete\n");
 	return 0;
 }
-#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* NEC workaround */
+static void ohci_quirk_nec_worker(struct work_struct *work)
+{
+	struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work);
+	int status;
+
+	status = ohci_init(ohci);
+	if (status != 0) {
+		ohci_err(ohci, "Restarting NEC controller failed "
+			 "in ohci_init, %d\n", status);
+		return;
+	}
+
+	status = ohci_restart(ohci);
+	if (status != 0)
+		ohci_err(ohci, "Restarting NEC controller failed "
+			 "in ohci_restart, %d\n", status);
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -917,7 +924,7 @@
 
 #ifdef CONFIG_PPC_PS3
 #include "ohci-ps3.c"
-#define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_sb_driver
+#define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_driver
 #endif
 
 #if	!defined(PCI_DRIVER) &&		\
@@ -940,12 +947,9 @@
 		sizeof (struct ed), sizeof (struct td));
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
-		retval = ps3_system_bus_driver_register(
-				&PS3_SYSTEM_BUS_DRIVER);
-		if (retval < 0)
-			goto error_ps3;
-	}
+	retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+	if (retval < 0)
+		goto error_ps3;
 #endif
 
 #ifdef PLATFORM_DRIVER
@@ -991,8 +995,7 @@
  error_platform:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
 #endif
 	return retval;
@@ -1014,8 +1017,7 @@
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ohci_hcd_mod_exit);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 216c9c9..48e4b11 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -55,8 +55,6 @@
 static void finish_unlinks (struct ohci_hcd *, u16);
 
 #ifdef	CONFIG_PM
-static int ohci_restart(struct ohci_hcd *ohci);
-
 static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
 __releases(ohci->lock)
 __acquires(ohci->lock)
@@ -191,6 +189,9 @@
 			spin_unlock_irq (&ohci->lock);
 			(void) ohci_init (ohci);
 			status = ohci_restart (ohci);
+
+			usb_root_hub_lost_power(hcd->self.root_hub);
+
 			spin_lock_irq (&ohci->lock);
 		}
 		return status;
@@ -417,6 +418,8 @@
 	unsigned long	flags;
 
 	spin_lock_irqsave (&ohci->lock, flags);
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+		goto done;
 
 	/* undocumented erratum seen on at least rev D */
 	if ((ohci->flags & OHCI_QUIRK_AMD756)
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 2f20d3d..450c7b4 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -28,6 +28,7 @@
 	ohci->next_statechange = jiffies;
 	spin_lock_init (&ohci->lock);
 	INIT_LIST_HEAD (&ohci->pending);
+	INIT_WORK (&ohci->nec_work, ohci_quirk_nec_worker);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 7970560..a5e2eb8 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -111,6 +111,18 @@
 #endif
 }
 
+/* Check for NEC chip and apply quirk for allegedly lost interrupts.
+ */
+static int ohci_quirk_nec(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+
+	ohci->flags |= OHCI_QUIRK_NEC;
+	ohci_dbg (ohci, "enabled NEC chipset lost interrupt quirk\n");
+
+	return 0;
+}
+
 /* List of quirks for OHCI */
 static const struct pci_device_id ohci_pci_quirks[] = {
 	{
@@ -134,10 +146,14 @@
 		.driver_data = (unsigned long)ohci_quirk_toshiba_scc,
 	},
 	{
+		PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB),
+		.driver_data = (unsigned long)ohci_quirk_nec,
+	},
+	{
 		/* Toshiba portege 4000 */
 		.vendor		= PCI_VENDOR_ID_AL,
 		.device		= 0x5237,
-		.subvendor	= PCI_VENDOR_ID_TOSHIBA_2,
+		.subvendor	= PCI_VENDOR_ID_TOSHIBA,
 		.subdevice	= 0x0004,
 		.driver_data	= (unsigned long) broken_suspend,
 	},
@@ -202,6 +218,42 @@
 	return ret;
 }
 
+#if	defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
+		defined(CONFIG_USB_EHCI_HCD_MODULE))
+
+/* Following a power loss, we must prepare to regain control of the ports
+ * we used to own.  This means turning on the port power before ehci-hcd
+ * tries to switch ownership.
+ *
+ * This isn't a 100% perfect solution.  On most systems the OHCI controllers
+ * lie at lower PCI addresses than the EHCI controller, so they will be
+ * discovered (and hence resumed) first.  But there is no guarantee things
+ * will always work this way.  If the EHCI controller is resumed first and
+ * the OHCI ports are unpowered, then the handover will fail.
+ */
+static void prepare_for_handover(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	int		port;
+
+	/* Here we "know" root ports should always stay powered */
+	ohci_dbg(ohci, "powerup ports\n");
+	for (port = 0; port < ohci->num_ports; port++)
+		ohci_writel(ohci, RH_PS_PPS,
+				&ohci->regs->roothub.portstatus[port]);
+
+	/* Flush those writes */
+	ohci_readl(ohci, &ohci->regs->control);
+	msleep(20);
+}
+
+#else
+
+static inline void prepare_for_handover(struct usb_hcd *hcd)
+{ }
+
+#endif	/* CONFIG_USB_PERSIST etc. */
+
 #ifdef	CONFIG_PM
 
 static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
@@ -241,7 +293,10 @@
 static int ohci_pci_resume (struct usb_hcd *hcd)
 {
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	usb_hcd_resume_root_hub(hcd);
+
+	/* FIXME: we should try to detect loss of VBUS power here */
+	prepare_for_handover(hcd);
+
 	return 0;
 }
 
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index d601bbb..ca2a6ab 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -134,7 +134,7 @@
 {
 	struct i2c_client *c;
 
-	c = (struct i2c_client *)kzalloc(sizeof(*c), GFP_KERNEL);
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
 
 	if (!c)
 		return -ENOMEM;
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index d7cf072..01a0cae 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -18,6 +18,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <asm/firmware.h>
 #include <asm/ps3.h>
 
 static int ps3_ohci_hc_reset(struct usb_hcd *hcd)
@@ -75,7 +76,7 @@
 #endif
 };
 
-static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
+static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct usb_hcd *hcd;
@@ -87,13 +88,31 @@
 		goto fail_start;
 	}
 
+	result = ps3_open_hv_device(dev);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+		result = -EPERM;
+		goto fail_open;
+	}
+
+	result = ps3_dma_region_create(dev->d_region);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+			"(%d)\n", __func__, __LINE__, result);
+		BUG_ON("check region type");
+		goto fail_dma_region;
+	}
+
 	result = ps3_mmio_region_create(dev->m_region);
 
 	if (result) {
 		dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n",
 			__func__, __LINE__);
 		result = -EPERM;
-		goto fail_mmio;
+		goto fail_mmio_region;
 	}
 
 	dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
@@ -122,6 +141,11 @@
 
 	hcd->rsrc_start = dev->m_region->lpar_addr;
 	hcd->rsrc_len = dev->m_region->len;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name))
+		dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n",
+			__func__, __LINE__);
+
 	hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len);
 
 	if (!hcd->regs) {
@@ -155,34 +179,73 @@
 fail_add_hcd:
 	iounmap(hcd->regs);
 fail_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 fail_create_hcd:
 	ps3_io_irq_destroy(virq);
 fail_irq:
 	ps3_free_mmio_region(dev->m_region);
-fail_mmio:
+fail_mmio_region:
+	ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+	ps3_close_hv_device(dev);
+fail_open:
 fail_start:
 	return result;
 }
 
-static int ps3_ohci_sb_remove (struct ps3_system_bus_device *dev)
+static int ps3_ohci_remove (struct ps3_system_bus_device *dev)
 {
+	unsigned int tmp;
 	struct usb_hcd *hcd =
 		(struct usb_hcd *)ps3_system_bus_get_driver_data(dev);
 
-	usb_put_hcd(hcd);
+	BUG_ON(!hcd);
+
+	dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs);
+	dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq);
+
+	tmp = hcd->irq;
+
+	usb_remove_hcd(hcd);
+
 	ps3_system_bus_set_driver_data(dev, NULL);
 
+	BUG_ON(!hcd->regs);
+	iounmap(hcd->regs);
+
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	ps3_io_irq_destroy(tmp);
+	ps3_free_mmio_region(dev->m_region);
+
+	ps3_dma_region_free(dev->d_region);
+	ps3_close_hv_device(dev);
+
 	return 0;
 }
 
-MODULE_ALIAS("ps3-ohci");
+static int ps3_ohci_driver_register(struct ps3_system_bus_driver *drv)
+{
+	return firmware_has_feature(FW_FEATURE_PS3_LV1)
+		? ps3_system_bus_driver_register(drv)
+		: 0;
+}
 
-static struct ps3_system_bus_driver ps3_ohci_sb_driver = {
+static void ps3_ohci_driver_unregister(struct ps3_system_bus_driver *drv)
+{
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+		ps3_system_bus_driver_unregister(drv);
+}
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_OHCI);
+
+static struct ps3_system_bus_driver ps3_ohci_driver = {
+	.core.name = "ps3-ohci-driver",
+	.core.owner = THIS_MODULE,
 	.match_id = PS3_MATCH_ID_OHCI,
-	.core = {
-		.name = "ps3-ohci-driver",
-	},
-	.probe = ps3_ohci_sb_probe,
-	.remove = ps3_ohci_sb_remove,
+	.probe = ps3_ohci_probe,
+	.remove = ps3_ohci_remove,
+	.shutdown = ps3_ohci_remove,
 };
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index c2b5ecf..4ada43c 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -397,8 +397,10 @@
 #define	OHCI_QUIRK_BE_DESC	0x08			/* BE descriptors */
 #define	OHCI_QUIRK_BE_MMIO	0x10			/* BE registers */
 #define	OHCI_QUIRK_ZFMICRO	0x20			/* Compaq ZFMicro chipset*/
+#define	OHCI_QUIRK_NEC		0x40			/* lost interrupts */
 	// there are also chip quirks/bugs in init logic
 
+	struct work_struct	nec_work;	/* Worker for NEC quirk */
 };
 
 /* convert between an hcd pointer and the corresponding ohci_hcd */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 2086165..c225159 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -44,6 +44,7 @@
 #define EHCI_USBSTS		4		/* status register */
 #define EHCI_USBSTS_HALTED	(1 << 12)	/* HCHalted bit */
 #define EHCI_USBINTR		8		/* interrupt register */
+#define EHCI_CONFIGFLAG		0x40		/* configured flag register */
 #define EHCI_USBLEGSUP		0		/* legacy support register */
 #define EHCI_USBLEGSUP_BIOS	(1 << 16)	/* BIOS semaphore */
 #define EHCI_USBLEGSUP_OS	(1 << 24)	/* OS semaphore */
@@ -216,6 +217,7 @@
 	u32	hcc_params, val;
 	u8	offset, cap_length;
 	int	count = 256/4;
+	int	tried_handoff = 0;
 
 	if (!mmio_resource_enabled(pdev, 0))
 		return;
@@ -273,6 +275,7 @@
 			 */
 			msec = 5000;
 			while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
+				tried_handoff = 1;
 				msleep(10);
 				msec -= 10;
 				pci_read_config_dword(pdev, offset, &cap);
@@ -292,6 +295,12 @@
 			pci_write_config_dword(pdev,
 					offset + EHCI_USBLEGCTLSTS,
 					0);
+
+			/* If the BIOS ever owned the controller then we
+			 * can't expect any power sessions to remain intact.
+			 */
+			if (tried_handoff)
+				writel(0, op_reg_base + EHCI_CONFIGFLAG);
 			break;
 		case 0:			/* illegal reserved capability */
 			cap = 0;
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
new file mode 100644
index 0000000..a7a7070
--- /dev/null
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -0,0 +1,2244 @@
+/*
+ * R8A66597 HCD (Host Controller Driver)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
+ * Portions Copyright (C) 2004-2005 David Brownell
+ * Portions Copyright (C) 1999 Roman Weissgaerber
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "../core/hcd.h"
+#include "r8a66597.h"
+
+MODULE_DESCRIPTION("R8A66597 USB Host Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+
+#define DRIVER_VERSION	"29 May 2007"
+
+static const char hcd_name[] = "r8a66597_hcd";
+
+/* module parameters */
+static unsigned short clock = XTAL12;
+module_param(clock, ushort, 0644);
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=0)");
+static unsigned short vif = LDRV;
+module_param(vif, ushort, 0644);
+MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
+static unsigned short endian = 0;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+static unsigned short irq_sense = INTL;
+module_param(irq_sense, ushort, 0644);
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0(default=32)");
+
+static void packet_write(struct r8a66597 *r8a66597, u16 pipenum);
+static int r8a66597_get_frame(struct usb_hcd *hcd);
+
+/* this function must be called with interrupt disabled */
+static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+			    unsigned long reg)
+{
+	u16 tmp;
+
+	tmp = r8a66597_read(r8a66597, INTENB0);
+	r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+	r8a66597_bset(r8a66597, 1 << pipenum, reg);
+	r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+/* this function must be called with interrupt disabled */
+static void disable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+			     unsigned long reg)
+{
+	u16 tmp;
+
+	tmp = r8a66597_read(r8a66597, INTENB0);
+	r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+	r8a66597_bclr(r8a66597, 1 << pipenum, reg);
+	r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address,
+			   u16 usbspd, u8 upphub, u8 hubport, int port)
+{
+	u16 val;
+	unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
+
+	val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001);
+	r8a66597_write(r8a66597, val, devadd_reg);
+}
+
+static int enable_controller(struct r8a66597 *r8a66597)
+{
+	u16 tmp;
+	int i = 0;
+
+	do {
+		r8a66597_write(r8a66597, USBE, SYSCFG0);
+		tmp = r8a66597_read(r8a66597, SYSCFG0);
+		if (i++ > 1000) {
+			err("register access fail.");
+			return -ENXIO;
+		}
+	} while ((tmp & USBE) != USBE);
+	r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+	r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0);
+
+	i = 0;
+	r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+	do {
+		msleep(1);
+		tmp = r8a66597_read(r8a66597, SYSCFG0);
+		if (i++ > 500) {
+			err("register access fail.");
+			return -ENXIO;
+		}
+	} while ((tmp & SCKE) != SCKE);
+
+	r8a66597_bset(r8a66597, DCFM | DRPD, SYSCFG0);
+	r8a66597_bset(r8a66597, DRPD, SYSCFG1);
+
+	r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+	r8a66597_bset(r8a66597, HSE, SYSCFG0);
+	r8a66597_bset(r8a66597, HSE, SYSCFG1);
+	r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+	r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+	r8a66597_bset(r8a66597, irq_sense & INTL, SOFCFG);
+	r8a66597_bset(r8a66597, BRDY0, BRDYENB);
+	r8a66597_bset(r8a66597, BEMP0, BEMPENB);
+
+	r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA0CFG);
+	r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA1CFG);
+
+	r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
+	r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
+	r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+
+	r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
+
+	r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);
+	r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+	r8a66597_bset(r8a66597, ATTCHE, INTENB1);
+	r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+	r8a66597_bset(r8a66597, ATTCHE, INTENB2);
+
+	return 0;
+}
+
+static void disable_controller(struct r8a66597 *r8a66597)
+{
+	u16 tmp;
+
+	r8a66597_write(r8a66597, 0, INTENB0);
+	r8a66597_write(r8a66597, 0, INTENB1);
+	r8a66597_write(r8a66597, 0, INTENB2);
+	r8a66597_write(r8a66597, 0, INTSTS0);
+	r8a66597_write(r8a66597, 0, INTSTS1);
+	r8a66597_write(r8a66597, 0, INTSTS2);
+
+	r8a66597_port_power(r8a66597, 0, 0);
+	r8a66597_port_power(r8a66597, 1, 0);
+
+	do {
+		tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+		udelay(640);
+	} while (tmp == EDGESTS);
+
+	r8a66597_bclr(r8a66597, DCFM | DRPD, SYSCFG0);
+	r8a66597_bclr(r8a66597, DRPD, SYSCFG1);
+	r8a66597_bclr(r8a66597, HSE, SYSCFG0);
+	r8a66597_bclr(r8a66597, HSE, SYSCFG1);
+
+	r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+	udelay(1);
+	r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+	r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+	r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+}
+
+static int get_parent_r8a66597_address(struct r8a66597 *r8a66597,
+				       struct usb_device *udev)
+{
+	struct r8a66597_device *dev;
+
+	if (udev->parent && udev->parent->devnum != 1)
+		udev = udev->parent;
+
+	dev = dev_get_drvdata(&udev->dev);
+	if (dev)
+		return dev->address;
+	else
+		return 0;
+}
+
+static int is_child_device(char *devpath)
+{
+	return (devpath[2] ? 1 : 0);
+}
+
+static int is_hub_limit(char *devpath)
+{
+	return ((strlen(devpath) >= 4) ? 1 : 0);
+}
+
+static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port)
+{
+	if (root_port) {
+		*root_port = (devpath[0] & 0x0F) - 1;
+		if (*root_port >= R8A66597_MAX_ROOT_HUB)
+			err("illegal root port number");
+	}
+	if (hub_port)
+		*hub_port = devpath[2] & 0x0F;
+}
+
+static u16 get_r8a66597_usb_speed(enum usb_device_speed speed)
+{
+	u16 usbspd = 0;
+
+	switch (speed) {
+	case USB_SPEED_LOW:
+		usbspd = LSMODE;
+		break;
+	case USB_SPEED_FULL:
+		usbspd = FSMODE;
+		break;
+	case USB_SPEED_HIGH:
+		usbspd = HSMODE;
+		break;
+	default:
+		err("unknown speed");
+		break;
+	}
+
+	return usbspd;
+}
+
+static void set_child_connect_map(struct r8a66597 *r8a66597, int address)
+{
+	int idx;
+
+	idx = address / 32;
+	r8a66597->child_connect_map[idx] |= 1 << (address % 32);
+}
+
+static void put_child_connect_map(struct r8a66597 *r8a66597, int address)
+{
+	int idx;
+
+	idx = address / 32;
+	r8a66597->child_connect_map[idx] &= ~(1 << (address % 32));
+}
+
+static void set_pipe_reg_addr(struct r8a66597_pipe *pipe, u8 dma_ch)
+{
+	u16 pipenum = pipe->info.pipenum;
+	unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO};
+	unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL};
+	unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR};
+
+	if (dma_ch > R8A66597_PIPE_NO_DMA)	/* dma fifo not use? */
+		dma_ch = R8A66597_PIPE_NO_DMA;
+
+	pipe->fifoaddr = fifoaddr[dma_ch];
+	pipe->fifosel = fifosel[dma_ch];
+	pipe->fifoctr = fifoctr[dma_ch];
+
+	if (pipenum == 0)
+		pipe->pipectr = DCPCTR;
+	else
+		pipe->pipectr = get_pipectr_addr(pipenum);
+
+	if (check_bulk_or_isoc(pipenum)) {
+		pipe->pipetre = get_pipetre_addr(pipenum);
+		pipe->pipetrn = get_pipetrn_addr(pipenum);
+	} else {
+		pipe->pipetre = 0;
+		pipe->pipetrn = 0;
+	}
+}
+
+static struct r8a66597_device *
+get_urb_to_r8a66597_dev(struct r8a66597 *r8a66597, struct urb *urb)
+{
+	if (usb_pipedevice(urb->pipe) == 0)
+		return &r8a66597->device0;
+
+	return dev_get_drvdata(&urb->dev->dev);
+}
+
+static int make_r8a66597_device(struct r8a66597 *r8a66597,
+				struct urb *urb, u8 addr)
+{
+	struct r8a66597_device *dev;
+	int usb_address = urb->setup_packet[2];	/* urb->pipe is address 0 */
+
+	dev = kzalloc(sizeof(struct r8a66597_device), GFP_KERNEL);
+	if (dev == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&urb->dev->dev, dev);
+	dev->udev = urb->dev;
+	dev->address = addr;
+	dev->usb_address = usb_address;
+	dev->state = USB_STATE_ADDRESS;
+	dev->ep_in_toggle = 0;
+	dev->ep_out_toggle = 0;
+	INIT_LIST_HEAD(&dev->device_list);
+	list_add_tail(&dev->device_list, &r8a66597->child_device);
+
+	get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port);
+	if (!is_child_device(urb->dev->devpath))
+		r8a66597->root_hub[dev->root_port].dev = dev;
+
+	set_devadd_reg(r8a66597, dev->address,
+		       get_r8a66597_usb_speed(urb->dev->speed),
+		       get_parent_r8a66597_address(r8a66597, urb->dev),
+		       dev->hub_port, dev->root_port);
+
+	return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
+{
+	u8 addr;	/* R8A66597's address */
+	struct r8a66597_device *dev;
+
+	if (is_hub_limit(urb->dev->devpath)) {
+		err("Externel hub limit reached.");
+		return 0;
+	}
+
+	dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+	if (dev && dev->state >= USB_STATE_ADDRESS)
+		return dev->address;
+
+	for (addr = 1; addr <= R8A66597_MAX_DEVICE; addr++) {
+		if (r8a66597->address_map & (1 << addr))
+			continue;
+
+		dbg("alloc_address: r8a66597_addr=%d", addr);
+		r8a66597->address_map |= 1 << addr;
+
+		if (make_r8a66597_device(r8a66597, urb, addr) < 0)
+			return 0;
+
+		return addr;
+	}
+
+	err("cannot communicate with a USB device more than 10.(%x)",
+	    r8a66597->address_map);
+
+	return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void free_usb_address(struct r8a66597 *r8a66597,
+			     struct r8a66597_device *dev)
+{
+	int port;
+
+	if (!dev)
+		return;
+
+	dbg("free_addr: addr=%d", dev->address);
+
+	dev->state = USB_STATE_DEFAULT;
+	r8a66597->address_map &= ~(1 << dev->address);
+	dev->address = 0;
+	dev_set_drvdata(&dev->udev->dev, NULL);
+	list_del(&dev->device_list);
+	kfree(dev);
+
+	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+		if (r8a66597->root_hub[port].dev == dev) {
+			r8a66597->root_hub[port].dev = NULL;
+			break;
+		}
+	}
+}
+
+static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
+			      u16 mask, u16 loop)
+{
+	u16 tmp;
+	int i = 0;
+
+	do {
+		tmp = r8a66597_read(r8a66597, reg);
+		if (i++ > 1000000) {
+			err("register%lx, loop %x is timeout", reg, loop);
+			break;
+		}
+		ndelay(1);
+	} while ((tmp & mask) != loop);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_start(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe)
+{
+	u16 tmp;
+
+	tmp = r8a66597_read(r8a66597, pipe->pipectr) & PID;
+	if ((pipe->info.pipenum != 0) & ((tmp & PID_STALL) != 0)) /* stall? */
+		r8a66597_mdfy(r8a66597, PID_NAK, PID, pipe->pipectr);
+	r8a66597_mdfy(r8a66597, PID_BUF, PID, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_stop(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe)
+{
+	u16 tmp;
+
+	tmp = r8a66597_read(r8a66597, pipe->pipectr) & PID;
+	if ((tmp & PID_STALL11) != PID_STALL11)	/* force stall? */
+		r8a66597_mdfy(r8a66597, PID_STALL, PID, pipe->pipectr);
+	r8a66597_mdfy(r8a66597, PID_NAK, PID, pipe->pipectr);
+	r8a66597_reg_wait(r8a66597, pipe->pipectr, PBUSY, 0);
+}
+
+/* this function must be called with interrupt disabled */
+static void clear_all_buffer(struct r8a66597 *r8a66597,
+			     struct r8a66597_pipe *pipe)
+{
+	u16 tmp;
+
+	if (!pipe || pipe->info.pipenum == 0)
+		return;
+
+	pipe_stop(r8a66597, pipe);
+	r8a66597_bset(r8a66597, ACLRM, pipe->pipectr);
+	tmp = r8a66597_read(r8a66597, pipe->pipectr);
+	tmp = r8a66597_read(r8a66597, pipe->pipectr);
+	tmp = r8a66597_read(r8a66597, pipe->pipectr);
+	r8a66597_bclr(r8a66597, ACLRM, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597,
+				 struct r8a66597_pipe *pipe, int toggle)
+{
+	if (toggle)
+		r8a66597_bset(r8a66597, SQSET, pipe->pipectr);
+	else
+		r8a66597_bset(r8a66597, SQCLR, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
+{
+	r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
+	r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
+}
+
+/* this function must be called with interrupt disabled */
+static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597,
+					 struct r8a66597_pipe *pipe)
+{
+	cfifo_change(r8a66597, 0);
+	r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL);
+	r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL);
+
+	r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE,
+		      pipe->fifosel);
+	r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum);
+}
+
+static u16 r8a66597_get_pipenum(struct urb *urb, struct usb_host_endpoint *hep)
+{
+	struct r8a66597_pipe *pipe = hep->hcpriv;
+
+	if (usb_pipeendpoint(urb->pipe) == 0)
+		return 0;
+	else
+		return pipe->info.pipenum;
+}
+
+static u16 get_urb_to_r8a66597_addr(struct r8a66597 *r8a66597, struct urb *urb)
+{
+	struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+
+	return (usb_pipedevice(urb->pipe) == 0) ? 0 : dev->address;
+}
+
+static unsigned short *get_toggle_pointer(struct r8a66597_device *dev,
+					  int urb_pipe)
+{
+	if (!dev)
+		return NULL;
+
+	return usb_pipein(urb_pipe) ? &dev->ep_in_toggle : &dev->ep_out_toggle;
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_set(struct r8a66597 *r8a66597,
+			    struct r8a66597_pipe *pipe,
+			    struct urb *urb, int set)
+{
+	struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+	unsigned char endpoint = usb_pipeendpoint(urb->pipe);
+	unsigned short *toggle = get_toggle_pointer(dev, urb->pipe);
+
+	if (!toggle)
+		return;
+
+	if (set)
+		*toggle |= 1 << endpoint;
+	else
+		*toggle &= ~(1 << endpoint);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_save(struct r8a66597 *r8a66597,
+			     struct r8a66597_pipe *pipe,
+			     struct urb *urb)
+{
+	if (r8a66597_read(r8a66597, pipe->pipectr) & SQMON)
+		pipe_toggle_set(r8a66597, pipe, urb, 1);
+	else
+		pipe_toggle_set(r8a66597, pipe, urb, 0);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_restore(struct r8a66597 *r8a66597,
+				struct r8a66597_pipe *pipe,
+				struct urb *urb)
+{
+	struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+	unsigned char endpoint = usb_pipeendpoint(urb->pipe);
+	unsigned short *toggle = get_toggle_pointer(dev, urb->pipe);
+
+	if (!toggle)
+		return;
+
+	r8a66597_pipe_toggle(r8a66597, pipe, *toggle & (1 << endpoint));
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_buffer_setting(struct r8a66597 *r8a66597,
+				struct r8a66597_pipe_info *info)
+{
+	u16 val = 0;
+
+	if (info->pipenum == 0)
+		return;
+
+	r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(info->pipenum));
+	r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(info->pipenum));
+	r8a66597_write(r8a66597, info->pipenum, PIPESEL);
+	if (!info->dir_in)
+		val |= R8A66597_DIR;
+	if (info->type == R8A66597_BULK && info->dir_in)
+		val |= R8A66597_DBLB | R8A66597_SHTNAK;
+	val |= info->type | info->epnum;
+	r8a66597_write(r8a66597, val, PIPECFG);
+
+	r8a66597_write(r8a66597, (info->buf_bsize << 10) | (info->bufnum),
+		       PIPEBUF);
+	r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket,
+		       PIPEMAXP);
+	if (info->interval)
+		info->interval--;
+	r8a66597_write(r8a66597, info->interval, PIPEPERI);
+}
+
+
+
+/* this function must be called with interrupt disabled */
+static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+	struct r8a66597_pipe_info *info;
+	struct urb *urb = td->urb;
+
+	if (td->pipenum > 0) {
+		info = &td->pipe->info;
+		cfifo_change(r8a66597, 0);
+		pipe_buffer_setting(r8a66597, info);
+
+		if (!usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+				   usb_pipeout(urb->pipe)) &&
+		    !usb_pipecontrol(urb->pipe)) {
+			r8a66597_pipe_toggle(r8a66597, td->pipe, 0);
+			pipe_toggle_set(r8a66597, td->pipe, urb, 0);
+			clear_all_buffer(r8a66597, td->pipe);
+			usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+				      usb_pipeout(urb->pipe), 1);
+		}
+		pipe_toggle_restore(r8a66597, td->pipe, urb);
+	}
+}
+
+/* this function must be called with interrupt disabled */
+static u16 get_empty_pipenum(struct r8a66597 *r8a66597,
+			     struct usb_endpoint_descriptor *ep)
+{
+	u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min;
+
+	memset(array, 0, sizeof(array));
+        switch(ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+        case USB_ENDPOINT_XFER_BULK:
+		if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			array[i++] = 4;
+		else {
+			array[i++] = 3;
+			array[i++] = 5;
+		}
+                break;
+        case USB_ENDPOINT_XFER_INT:
+		if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+			array[i++] = 6;
+			array[i++] = 7;
+			array[i++] = 8;
+		} else
+			array[i++] = 9;
+                break;
+        case USB_ENDPOINT_XFER_ISOC:
+		if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			array[i++] = 2;
+		else
+			array[i++] = 1;
+                break;
+        default:
+                err("Illegal type");
+                return 0;
+        }
+
+	i = 1;
+	min = array[0];
+	while (array[i] != 0) {
+		if (r8a66597->pipe_cnt[min] > r8a66597->pipe_cnt[array[i]])
+			min = array[i];
+		i++;
+	}
+
+	return min;
+}
+
+static u16 get_r8a66597_type(__u8 type)
+{
+	u16 r8a66597_type;
+
+	switch(type) {
+	case USB_ENDPOINT_XFER_BULK:
+		r8a66597_type = R8A66597_BULK;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		r8a66597_type = R8A66597_INT;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		r8a66597_type = R8A66597_ISO;
+		break;
+	default:
+		err("Illegal type");
+		r8a66597_type = 0x0000;
+		break;
+	}
+
+	return r8a66597_type;
+}
+
+static u16 get_bufnum(u16 pipenum)
+{
+	u16 bufnum = 0;
+
+	if (pipenum == 0)
+		bufnum = 0;
+	else if (check_bulk_or_isoc(pipenum))
+		bufnum = 8 + (pipenum - 1) * R8A66597_BUF_BSIZE*2;
+	else if (check_interrupt(pipenum))
+		bufnum = 4 + (pipenum - 6);
+	else
+		err("Illegal pipenum (%d)", pipenum);
+
+	return bufnum;
+}
+
+static u16 get_buf_bsize(u16 pipenum)
+{
+	u16 buf_bsize = 0;
+
+	if (pipenum == 0)
+		buf_bsize = 3;
+	else if (check_bulk_or_isoc(pipenum))
+		buf_bsize = R8A66597_BUF_BSIZE - 1;
+	else if (check_interrupt(pipenum))
+		buf_bsize = 0;
+	else
+		err("Illegal pipenum (%d)", pipenum);
+
+	return buf_bsize;
+}
+
+/* this function must be called with interrupt disabled */
+static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
+				     struct r8a66597_device *dev,
+				     struct r8a66597_pipe *pipe,
+				     struct urb *urb)
+{
+	int i;
+	struct r8a66597_pipe_info *info = &pipe->info;
+
+	if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) {
+		for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) {
+			if ((r8a66597->dma_map & (1 << i)) != 0)
+				continue;
+
+			info("address %d, EndpointAddress 0x%02x use DMA FIFO",
+			     usb_pipedevice(urb->pipe),
+			     info->dir_in ? USB_ENDPOINT_DIR_MASK + info->epnum
+					    : info->epnum);
+
+			r8a66597->dma_map |= 1 << i;
+			dev->dma_map |= 1 << i;
+			set_pipe_reg_addr(pipe, i);
+
+			cfifo_change(r8a66597, 0);
+			r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum,
+				      MBW | CURPIPE, pipe->fifosel);
+
+			r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE,
+					  pipe->info.pipenum);
+			r8a66597_bset(r8a66597, BCLR, pipe->fifoctr);
+			break;
+		}
+	}
+}
+
+/* this function must be called with interrupt disabled */
+static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb,
+				 struct usb_host_endpoint *hep,
+				 struct r8a66597_pipe_info *info)
+{
+	struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+	struct r8a66597_pipe *pipe = hep->hcpriv;
+
+	dbg("enable_pipe:");
+
+	pipe->info = *info;
+	set_pipe_reg_addr(pipe, R8A66597_PIPE_NO_DMA);
+	r8a66597->pipe_cnt[pipe->info.pipenum]++;
+	dev->pipe_cnt[pipe->info.pipenum]++;
+
+	enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb);
+}
+
+/* this function must be called with interrupt disabled */
+static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
+{
+	struct r8a66597_td *td, *next;
+	struct urb *urb;
+	struct list_head *list = &r8a66597->pipe_queue[pipenum];
+
+	if (list_empty(list))
+		return;
+
+	list_for_each_entry_safe(td, next, list, queue) {
+		if (!td)
+			continue;
+		if (td->address != address)
+			continue;
+
+		urb = td->urb;
+		list_del(&td->queue);
+		kfree(td);
+
+		if (urb) {
+			urb->status = -ENODEV;
+			urb->hcpriv = NULL;
+			spin_unlock(&r8a66597->lock);
+			usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb);
+			spin_lock(&r8a66597->lock);
+		}
+		break;
+	}
+}
+
+/* this function must be called with interrupt disabled */
+static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
+				      struct r8a66597_device *dev)
+{
+	int check_ep0 = 0;
+	u16 pipenum;
+
+	if (!dev)
+		return;
+
+	for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+		if (!dev->pipe_cnt[pipenum])
+			continue;
+
+		if (!check_ep0) {
+			check_ep0 = 1;
+			force_dequeue(r8a66597, 0, dev->address);
+		}
+
+		r8a66597->pipe_cnt[pipenum] -= dev->pipe_cnt[pipenum];
+		dev->pipe_cnt[pipenum] = 0;
+		force_dequeue(r8a66597, pipenum, dev->address);
+	}
+
+	dbg("disable_pipe");
+
+	r8a66597->dma_map &= ~(dev->dma_map);
+	dev->dma_map = 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
+			   struct usb_host_endpoint *hep,
+			   struct usb_endpoint_descriptor *ep)
+{
+	struct r8a66597_pipe_info info;
+
+	info.pipenum = get_empty_pipenum(r8a66597, ep);
+	info.address = get_urb_to_r8a66597_addr(r8a66597, urb);
+	info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	info.maxpacket = ep->wMaxPacketSize;
+	info.type = get_r8a66597_type(ep->bmAttributes
+				      & USB_ENDPOINT_XFERTYPE_MASK);
+	info.bufnum = get_bufnum(info.pipenum);
+	info.buf_bsize = get_buf_bsize(info.pipenum);
+	info.interval = ep->bInterval;
+	if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+		info.dir_in = 1;
+	else
+		info.dir_in = 0;
+
+	enable_r8a66597_pipe(r8a66597, urb, hep, &info);
+}
+
+static void init_pipe_config(struct r8a66597 *r8a66597, struct urb *urb)
+{
+	struct r8a66597_device *dev;
+
+	dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+	dev->state = USB_STATE_CONFIGURED;
+}
+
+static void pipe_irq_enable(struct r8a66597 *r8a66597, struct urb *urb,
+			    u16 pipenum)
+{
+	if (pipenum == 0 && usb_pipeout(urb->pipe))
+		enable_irq_empty(r8a66597, pipenum);
+	else
+		enable_irq_ready(r8a66597, pipenum);
+
+	if (!usb_pipeisoc(urb->pipe))
+		enable_irq_nrdy(r8a66597, pipenum);
+}
+
+static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
+{
+	disable_irq_ready(r8a66597, pipenum);
+	disable_irq_nrdy(r8a66597, pipenum);
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port)
+{
+	r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
+					 | (1 << USB_PORT_FEAT_C_CONNECTION);
+	r8a66597_write(r8a66597, (u16)~DTCH, get_intsts_reg(port));
+	r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
+{
+	u16 speed = get_rh_usb_speed(r8a66597, port);
+	struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+	if (speed == HSMODE)
+		rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED);
+	else if (speed == LSMODE)
+		rh->port |= (1 << USB_PORT_FEAT_LOWSPEED);
+
+	rh->port &= ~(1 << USB_PORT_FEAT_RESET);
+	rh->port |= 1 << USB_PORT_FEAT_ENABLE;
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)
+{
+	struct r8a66597_device *dev = r8a66597->root_hub[port].dev;
+
+	r8a66597->root_hub[port].port &= ~(1 << USB_PORT_FEAT_CONNECTION);
+	r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_C_CONNECTION);
+
+	disable_r8a66597_pipe_all(r8a66597, dev);
+	free_usb_address(r8a66597, dev);
+
+	r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_setup_packet(struct r8a66597 *r8a66597,
+				 struct r8a66597_td *td)
+{
+	int i;
+	u16 *p = (u16 *)td->urb->setup_packet;
+	unsigned long setup_addr = USBREQ;
+
+	r8a66597_write(r8a66597, make_devsel(td->address) | td->maxpacket,
+		       DCPMAXP);
+	r8a66597_write(r8a66597, (u16)~(SIGN | SACK), INTSTS1);
+
+	for (i = 0; i < 4; i++) {
+		r8a66597_write(r8a66597, p[i], setup_addr);
+		setup_addr += 2;
+	}
+	r8a66597_write(r8a66597, SUREQ, DCPCTR);
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_packet_read(struct r8a66597 *r8a66597,
+				struct r8a66597_td *td)
+{
+	struct urb *urb = td->urb;
+
+	if (usb_pipecontrol(urb->pipe)) {
+		r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+		r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+		r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+		if (urb->actual_length == 0) {
+			r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+			r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+		}
+		pipe_irq_disable(r8a66597, td->pipenum);
+		pipe_start(r8a66597, td->pipe);
+		pipe_irq_enable(r8a66597, urb, td->pipenum);
+	} else {
+		if (urb->actual_length == 0) {
+			pipe_irq_disable(r8a66597, td->pipenum);
+			pipe_setting(r8a66597, td);
+			pipe_stop(r8a66597, td->pipe);
+			r8a66597_write(r8a66597, (u16)~(1 << td->pipenum),
+				       BRDYSTS);
+
+			if (td->pipe->pipetre) {
+				r8a66597_write(r8a66597, TRCLR,
+					        td->pipe->pipetre);
+				r8a66597_write(r8a66597,
+					       (urb->transfer_buffer_length
+					       + td->maxpacket - 1)
+					       / td->maxpacket,
+					       td->pipe->pipetrn);
+				r8a66597_bset(r8a66597, TRENB,
+					      td->pipe->pipetre);
+			}
+
+			pipe_start(r8a66597, td->pipe);
+			pipe_irq_enable(r8a66597, urb, td->pipenum);
+		}
+	}
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_packet_write(struct r8a66597 *r8a66597,
+				 struct r8a66597_td *td)
+{
+	u16 tmp;
+	struct urb *urb = td->urb;
+
+	if (usb_pipecontrol(urb->pipe)) {
+		pipe_stop(r8a66597, td->pipe);
+		r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+		r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+		r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+		if (urb->actual_length == 0) {
+			r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+			r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+		}
+	} else {
+		if (urb->actual_length == 0)
+			pipe_setting(r8a66597, td);
+		if (td->pipe->pipetre)
+			r8a66597_bclr(r8a66597, TRENB, td->pipe->pipetre);
+	}
+	r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), BRDYSTS);
+
+	fifo_change_from_pipe(r8a66597, td->pipe);
+	tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+	if (unlikely((tmp & FRDY) == 0))
+		pipe_irq_enable(r8a66597, urb, td->pipenum);
+	else
+		packet_write(r8a66597, td->pipenum);
+	pipe_start(r8a66597, td->pipe);
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_status_packet(struct r8a66597 *r8a66597,
+				  struct r8a66597_td *td)
+{
+	struct urb *urb = td->urb;
+
+	r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+
+	if (urb->setup_packet[0] & USB_ENDPOINT_DIR_MASK) {
+		r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+		r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+		r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+		r8a66597_write(r8a66597, BVAL | BCLR, CFIFOCTR);
+		r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS);
+		enable_irq_empty(r8a66597, 0);
+	} else {
+		r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+		r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+		r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+		r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+		r8a66597_write(r8a66597, (u16)~BRDY0, BRDYSTS);
+		r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS);
+		enable_irq_ready(r8a66597, 0);
+	}
+	enable_irq_nrdy(r8a66597, 0);
+	pipe_start(r8a66597, td->pipe);
+}
+
+/* this function must be called with interrupt disabled */
+static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+	BUG_ON(!td);
+
+	switch (td->type) {
+	case USB_PID_SETUP:
+		if (td->urb->setup_packet[1] == USB_REQ_SET_ADDRESS) {
+			td->set_address = 1;
+			td->urb->setup_packet[2] = alloc_usb_address(r8a66597,
+								     td->urb);
+			if (td->urb->setup_packet[2] == 0)
+				return -EPIPE;
+		}
+		prepare_setup_packet(r8a66597, td);
+		break;
+	case USB_PID_IN:
+		prepare_packet_read(r8a66597, td);
+		break;
+	case USB_PID_OUT:
+		prepare_packet_write(r8a66597, td);
+		break;
+	case USB_PID_ACK:
+		prepare_status_packet(r8a66597, td);
+		break;
+	default:
+		err("invalid type.");
+		break;
+	}
+
+	return 0;
+}
+
+static int check_transfer_finish(struct r8a66597_td *td, struct urb *urb)
+{
+	if (usb_pipeisoc(urb->pipe)) {
+		if (urb->number_of_packets == td->iso_cnt)
+			return 1;
+	}
+
+	/* control or bulk or interrupt */
+	if ((urb->transfer_buffer_length <= urb->actual_length) ||
+	    (td->short_packet) || (td->zero_packet))
+		return 1;
+
+	return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+	unsigned long time;
+
+	BUG_ON(!td);
+
+	if (!list_empty(&r8a66597->pipe_queue[td->pipenum]) &&
+	    !usb_pipecontrol(td->urb->pipe) && usb_pipein(td->urb->pipe)) {
+		r8a66597->timeout_map |= 1 << td->pipenum;
+		switch (usb_pipetype(td->urb->pipe)) {
+		case PIPE_INTERRUPT:
+		case PIPE_ISOCHRONOUS:
+			time = 30;
+			break;
+		default:
+			time = 300;
+			break;
+		}
+
+		mod_timer(&r8a66597->td_timer[td->pipenum],
+			  jiffies + msecs_to_jiffies(time));
+	}
+}
+
+/* this function must be called with interrupt disabled */
+static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+		 u16 pipenum, struct urb *urb)
+{
+	int restart = 0;
+	struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
+
+	r8a66597->timeout_map &= ~(1 << pipenum);
+
+	if (likely(td)) {
+		if (td->set_address && urb->status != 0)
+			r8a66597->address_map &= ~(1 << urb->setup_packet[2]);
+
+		pipe_toggle_save(r8a66597, td->pipe, urb);
+		list_del(&td->queue);
+		kfree(td);
+	}
+
+	if (!list_empty(&r8a66597->pipe_queue[pipenum]))
+		restart = 1;
+
+	if (likely(urb)) {
+		if (usb_pipeisoc(urb->pipe))
+			urb->start_frame = r8a66597_get_frame(hcd);
+
+		urb->hcpriv = NULL;
+		spin_unlock(&r8a66597->lock);
+		usb_hcd_giveback_urb(hcd, urb);
+		spin_lock(&r8a66597->lock);
+	}
+
+	if (restart) {
+		td = r8a66597_get_td(r8a66597, pipenum);
+		if (unlikely(!td))
+			return;
+
+		start_transfer(r8a66597, td);
+		set_td_timer(r8a66597, td);
+	}
+}
+
+/* this function must be called with interrupt disabled */
+static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+			   u16 pipenum, struct urb *urb)
+__releases(r8a66597->lock) __acquires(r8a66597->lock)
+{
+	done(r8a66597, td, pipenum, urb);
+}
+
+static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+{
+	u16 tmp;
+	int rcv_len, bufsize, urb_len, size;
+	u16 *buf;
+	struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+	struct urb *urb;
+	int finish = 0;
+
+	if (unlikely(!td))
+		return;
+	urb = td->urb;
+
+	fifo_change_from_pipe(r8a66597, td->pipe);
+	tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+	if (unlikely((tmp & FRDY) == 0)) {
+		urb->status = -EPIPE;
+		pipe_stop(r8a66597, td->pipe);
+		pipe_irq_disable(r8a66597, pipenum);
+		err("in fifo not ready (%d)", pipenum);
+		finish_request(r8a66597, td, pipenum, td->urb);
+		return;
+	}
+
+	/* prepare parameters */
+	rcv_len = tmp & DTLN;
+	bufsize = td->maxpacket;
+	if (usb_pipeisoc(urb->pipe)) {
+		buf = (u16 *)(urb->transfer_buffer +
+				urb->iso_frame_desc[td->iso_cnt].offset);
+		urb_len = urb->iso_frame_desc[td->iso_cnt].length;
+	} else {
+		buf = (void *)urb->transfer_buffer + urb->actual_length;
+		urb_len = urb->transfer_buffer_length - urb->actual_length;
+	}
+	if (rcv_len < bufsize)
+		size = min(rcv_len, urb_len);
+	else
+		size = min(bufsize, urb_len);
+
+	/* update parameters */
+	urb->actual_length += size;
+	if (rcv_len == 0)
+		td->zero_packet = 1;
+	if ((size % td->maxpacket) > 0) {
+		td->short_packet = 1;
+		if (urb->transfer_buffer_length != urb->actual_length &&
+		    urb->transfer_flags & URB_SHORT_NOT_OK)
+			td->urb->status = -EREMOTEIO;
+	}
+	if (usb_pipeisoc(urb->pipe)) {
+		urb->iso_frame_desc[td->iso_cnt].actual_length = size;
+		urb->iso_frame_desc[td->iso_cnt].status = 0;
+		td->iso_cnt++;
+	}
+
+	/* check transfer finish */
+	if (check_transfer_finish(td, urb)) {
+		pipe_stop(r8a66597, td->pipe);
+		pipe_irq_disable(r8a66597, pipenum);
+		finish = 1;
+	}
+
+	/* read fifo */
+	if (urb->transfer_buffer) {
+		if (size == 0)
+			r8a66597_write(r8a66597, BCLR, td->pipe->fifoctr);
+		else
+			r8a66597_read_fifo(r8a66597, td->pipe->fifoaddr,
+					   buf, size);
+	}
+
+	if (finish && pipenum != 0) {
+		if (td->urb->status == -EINPROGRESS)
+			td->urb->status = 0;
+		finish_request(r8a66597, td, pipenum, urb);
+	}
+}
+
+static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
+{
+	u16 tmp;
+	int bufsize, size;
+	u16 *buf;
+	struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+	struct urb *urb;
+
+	if (unlikely(!td))
+		return;
+	urb = td->urb;
+
+	fifo_change_from_pipe(r8a66597, td->pipe);
+	tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+	if (unlikely((tmp & FRDY) == 0)) {
+		urb->status = -EPIPE;
+		pipe_stop(r8a66597, td->pipe);
+		pipe_irq_disable(r8a66597, pipenum);
+		err("out write fifo not ready. (%d)", pipenum);
+		finish_request(r8a66597, td, pipenum, td->urb);
+		return;
+	}
+
+	/* prepare parameters */
+	bufsize = td->maxpacket;
+	if (usb_pipeisoc(urb->pipe)) {
+		buf = (u16 *)(urb->transfer_buffer +
+				urb->iso_frame_desc[td->iso_cnt].offset);
+		size = min(bufsize,
+			   (int)urb->iso_frame_desc[td->iso_cnt].length);
+	} else {
+		buf = (u16 *)(urb->transfer_buffer + urb->actual_length);
+		size = min((int)bufsize,
+			   urb->transfer_buffer_length - urb->actual_length);
+	}
+
+	/* write fifo */
+	if (pipenum > 0)
+		r8a66597_write(r8a66597, (u16)~(1 << pipenum), BEMPSTS);
+	if (urb->transfer_buffer) {
+		r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size);
+		if (!usb_pipebulk(urb->pipe) || td->maxpacket != size)
+			r8a66597_write(r8a66597, BVAL, td->pipe->fifoctr);
+	}
+
+	/* update parameters */
+	urb->actual_length += size;
+	if (usb_pipeisoc(urb->pipe)) {
+		urb->iso_frame_desc[td->iso_cnt].actual_length = size;
+		urb->iso_frame_desc[td->iso_cnt].status = 0;
+		td->iso_cnt++;
+	}
+
+	/* check transfer finish */
+	if (check_transfer_finish(td, urb)) {
+		disable_irq_ready(r8a66597, pipenum);
+		enable_irq_empty(r8a66597, pipenum);
+		if (!usb_pipeisoc(urb->pipe))
+			enable_irq_nrdy(r8a66597, pipenum);
+	} else
+		pipe_irq_enable(r8a66597, urb, pipenum);
+}
+
+
+static void check_next_phase(struct r8a66597 *r8a66597)
+{
+	struct r8a66597_td *td = r8a66597_get_td(r8a66597, 0);
+	struct urb *urb;
+	u8 finish = 0;
+
+	if (unlikely(!td))
+		return;
+	urb = td->urb;
+
+	switch (td->type) {
+	case USB_PID_IN:
+	case USB_PID_OUT:
+		if (urb->status != -EINPROGRESS) {
+			finish = 1;
+			break;
+		}
+		if (check_transfer_finish(td, urb))
+			td->type = USB_PID_ACK;
+		break;
+	case USB_PID_SETUP:
+		if (urb->status != -EINPROGRESS)
+			finish = 1;
+		else if (urb->transfer_buffer_length == urb->actual_length) {
+			td->type = USB_PID_ACK;
+			urb->status = 0;
+		} else if (usb_pipeout(urb->pipe))
+			td->type = USB_PID_OUT;
+		else
+			td->type = USB_PID_IN;
+		break;
+	case USB_PID_ACK:
+		finish = 1;
+		if (urb->status == -EINPROGRESS)
+			urb->status = 0;
+		break;
+	}
+
+	if (finish)
+		finish_request(r8a66597, td, 0, urb);
+	else
+		start_transfer(r8a66597, td);
+}
+
+static void set_urb_error(struct r8a66597 *r8a66597, u16 pipenum)
+{
+	struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+
+	if (td && td->urb) {
+		u16 pid = r8a66597_read(r8a66597, td->pipe->pipectr) & PID;
+
+		if (pid == PID_NAK)
+			td->urb->status = -ECONNRESET;
+		else
+			td->urb->status = -EPIPE;
+	}
+}
+
+static void irq_pipe_ready(struct r8a66597 *r8a66597)
+{
+	u16 check;
+	u16 pipenum;
+	u16 mask;
+	struct r8a66597_td *td;
+
+	mask = r8a66597_read(r8a66597, BRDYSTS)
+	       & r8a66597_read(r8a66597, BRDYENB);
+	r8a66597_write(r8a66597, (u16)~mask, BRDYSTS);
+	if (mask & BRDY0) {
+		td = r8a66597_get_td(r8a66597, 0);
+		if (td && td->type == USB_PID_IN)
+			packet_read(r8a66597, 0);
+		else
+			pipe_irq_disable(r8a66597, 0);
+		check_next_phase(r8a66597);
+	}
+
+	for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+		check = 1 << pipenum;
+		if (mask & check) {
+			td = r8a66597_get_td(r8a66597, pipenum);
+			if (unlikely(!td))
+				continue;
+
+			if (td->type == USB_PID_IN)
+				packet_read(r8a66597, pipenum);
+			else if (td->type == USB_PID_OUT)
+				packet_write(r8a66597, pipenum);
+		}
+	}
+}
+
+static void irq_pipe_empty(struct r8a66597 *r8a66597)
+{
+	u16 tmp;
+	u16 check;
+	u16 pipenum;
+	u16 mask;
+	struct r8a66597_td *td;
+
+	mask = r8a66597_read(r8a66597, BEMPSTS)
+	       & r8a66597_read(r8a66597, BEMPENB);
+	r8a66597_write(r8a66597, (u16)~mask, BEMPSTS);
+	if (mask & BEMP0) {
+		cfifo_change(r8a66597, 0);
+		td = r8a66597_get_td(r8a66597, 0);
+		if (td && td->type != USB_PID_OUT)
+			disable_irq_empty(r8a66597, 0);
+		check_next_phase(r8a66597);
+	}
+
+	for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+		check = 1 << pipenum;
+		if (mask &  check) {
+			struct r8a66597_td *td;
+			td = r8a66597_get_td(r8a66597, pipenum);
+			if (unlikely(!td))
+				continue;
+
+			tmp = r8a66597_read(r8a66597, td->pipe->pipectr);
+			if ((tmp & INBUFM) == 0) {
+				disable_irq_empty(r8a66597, pipenum);
+				pipe_irq_disable(r8a66597, pipenum);
+				if (td->urb->status == -EINPROGRESS)
+					td->urb->status = 0;
+				finish_request(r8a66597, td, pipenum, td->urb);
+			}
+		}
+	}
+}
+
+static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
+{
+	u16 check;
+	u16 pipenum;
+	u16 mask;
+
+	mask = r8a66597_read(r8a66597, NRDYSTS)
+	       & r8a66597_read(r8a66597, NRDYENB);
+	r8a66597_write(r8a66597, (u16)~mask, NRDYSTS);
+	if (mask & NRDY0) {
+		cfifo_change(r8a66597, 0);
+		set_urb_error(r8a66597, 0);
+		pipe_irq_disable(r8a66597, 0);
+		check_next_phase(r8a66597);
+	}
+
+	for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+		check = 1 << pipenum;
+		if (mask & check) {
+			struct r8a66597_td *td;
+			td = r8a66597_get_td(r8a66597, pipenum);
+			if (unlikely(!td))
+				continue;
+
+			set_urb_error(r8a66597, pipenum);
+			pipe_irq_disable(r8a66597, pipenum);
+			pipe_stop(r8a66597, td->pipe);
+			finish_request(r8a66597, td, pipenum, td->urb);
+		}
+	}
+}
+
+static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port)
+{
+	struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+	rh->old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+	rh->scount = R8A66597_MAX_SAMPLING;
+	mod_timer(&r8a66597->rh_timer, jiffies + msecs_to_jiffies(50));
+}
+
+static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	u16 intsts0, intsts1, intsts2;
+	u16 intenb0, intenb1, intenb2;
+	u16 mask0, mask1, mask2;
+
+	spin_lock(&r8a66597->lock);
+
+	intsts0 = r8a66597_read(r8a66597, INTSTS0);
+	intsts1 = r8a66597_read(r8a66597, INTSTS1);
+	intsts2 = r8a66597_read(r8a66597, INTSTS2);
+	intenb0 = r8a66597_read(r8a66597, INTENB0);
+	intenb1 = r8a66597_read(r8a66597, INTENB1);
+	intenb2 = r8a66597_read(r8a66597, INTENB2);
+
+	mask2 = intsts2 & intenb2;
+	mask1 = intsts1 & intenb1;
+	mask0 = intsts0 & intenb0 & (BEMP | NRDY | BRDY);
+	if (mask2) {
+		if (mask2 & ATTCH) {
+			r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS2);
+			r8a66597_bclr(r8a66597, ATTCHE, INTENB2);
+
+			/* start usb bus sampling */
+			start_root_hub_sampling(r8a66597, 1);
+		}
+		if (mask2 & DTCH) {
+			r8a66597_write(r8a66597, (u16)~DTCH, INTSTS2);
+			r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+			r8a66597_usb_disconnect(r8a66597, 1);
+		}
+	}
+
+	if (mask1) {
+		if (mask1 & ATTCH) {
+			r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS1);
+			r8a66597_bclr(r8a66597, ATTCHE, INTENB1);
+
+			/* start usb bus sampling */
+			start_root_hub_sampling(r8a66597, 0);
+		}
+		if (mask1 & DTCH) {
+			r8a66597_write(r8a66597, (u16)~DTCH, INTSTS1);
+			r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+			r8a66597_usb_disconnect(r8a66597, 0);
+		}
+		if (mask1 & SIGN) {
+			r8a66597_write(r8a66597, (u16)~SIGN, INTSTS1);
+			set_urb_error(r8a66597, 0);
+			check_next_phase(r8a66597);
+		}
+		if (mask1 & SACK) {
+			r8a66597_write(r8a66597, (u16)~SACK, INTSTS1);
+			check_next_phase(r8a66597);
+		}
+	}
+	if (mask0) {
+		if (mask0 & BRDY)
+			irq_pipe_ready(r8a66597);
+		if (mask0 & BEMP)
+			irq_pipe_empty(r8a66597);
+		if (mask0 & NRDY)
+			irq_pipe_nrdy(r8a66597);
+	}
+
+	spin_unlock(&r8a66597->lock);
+	return IRQ_HANDLED;
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
+{
+	u16 tmp;
+	struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+	if (rh->port & (1 << USB_PORT_FEAT_RESET)) {
+		unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+		tmp = r8a66597_read(r8a66597, dvstctr_reg);
+		if ((tmp & USBRST) == USBRST) {
+			r8a66597_mdfy(r8a66597, UACT, USBRST | UACT,
+				      dvstctr_reg);
+			mod_timer(&r8a66597->rh_timer,
+				  jiffies + msecs_to_jiffies(50));
+		} else
+			r8a66597_usb_connect(r8a66597, port);
+	}
+
+	if (rh->scount > 0) {
+		tmp = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+		if (tmp == rh->old_syssts) {
+			rh->scount--;
+			if (rh->scount == 0) {
+				if (tmp == FS_JSTS) {
+					r8a66597_bset(r8a66597, HSE,
+						      get_syscfg_reg(port));
+					r8a66597_usb_preconnect(r8a66597, port);
+				} else if (tmp == LS_JSTS) {
+					r8a66597_bclr(r8a66597, HSE,
+						      get_syscfg_reg(port));
+					r8a66597_usb_preconnect(r8a66597, port);
+				} else if (tmp == SE0)
+					r8a66597_bset(r8a66597, ATTCHE,
+						      get_intenb_reg(port));
+			} else {
+				mod_timer(&r8a66597->rh_timer,
+					  jiffies + msecs_to_jiffies(50));
+			}
+		} else {
+			rh->scount = R8A66597_MAX_SAMPLING;
+			rh->old_syssts = tmp;
+			mod_timer(&r8a66597->rh_timer,
+				  jiffies + msecs_to_jiffies(50));
+		}
+	}
+}
+
+static void r8a66597_td_timer(unsigned long _r8a66597)
+{
+	struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+	unsigned long flags;
+	u16 pipenum;
+	struct r8a66597_td *td, *new_td = NULL;
+	struct r8a66597_pipe *pipe;
+
+	spin_lock_irqsave(&r8a66597->lock, flags);
+	for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+		if (!(r8a66597->timeout_map & (1 << pipenum)))
+			continue;
+		if (timer_pending(&r8a66597->td_timer[pipenum]))
+			continue;
+
+		td = r8a66597_get_td(r8a66597, pipenum);
+		if (!td) {
+			r8a66597->timeout_map &= ~(1 << pipenum);
+			continue;
+		}
+
+		if (td->urb->actual_length) {
+			set_td_timer(r8a66597, td);
+			break;
+		}
+
+		pipe = td->pipe;
+		pipe_stop(r8a66597, pipe);
+
+		new_td = td;
+		do {
+			list_move_tail(&new_td->queue,
+				       &r8a66597->pipe_queue[pipenum]);
+			new_td = r8a66597_get_td(r8a66597, pipenum);
+			if (!new_td) {
+				new_td = td;
+				break;
+			}
+		} while (td != new_td && td->address == new_td->address);
+
+		start_transfer(r8a66597, new_td);
+
+		if (td == new_td)
+			r8a66597->timeout_map &= ~(1 << pipenum);
+		else
+			set_td_timer(r8a66597, new_td);
+		break;
+	}
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static void r8a66597_timer(unsigned long _r8a66597)
+{
+	struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+	unsigned long flags;
+
+	spin_lock_irqsave(&r8a66597->lock, flags);
+
+	r8a66597_root_hub_control(r8a66597, 0);
+	r8a66597_root_hub_control(r8a66597, 1);
+
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static int check_pipe_config(struct r8a66597 *r8a66597, struct urb *urb)
+{
+	struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+
+	if (dev && dev->address && dev->state != USB_STATE_CONFIGURED &&
+	    (urb->dev->state == USB_STATE_CONFIGURED))
+		return 1;
+	else
+		return 0;
+}
+
+static int r8a66597_start(struct usb_hcd *hcd)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	int ret;
+
+	hcd->state = HC_STATE_RUNNING;
+	if ((ret = enable_controller(r8a66597)) < 0)
+		return ret;
+
+	return 0;
+}
+
+static void r8a66597_stop(struct usb_hcd *hcd)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+
+	disable_controller(r8a66597);
+}
+
+static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb)
+{
+	unsigned int usb_address = usb_pipedevice(urb->pipe);
+	u16 root_port, hub_port;
+
+	if (usb_address == 0) {
+		get_port_number(urb->dev->devpath,
+				&root_port, &hub_port);
+		set_devadd_reg(r8a66597, 0,
+			       get_r8a66597_usb_speed(urb->dev->speed),
+			       get_parent_r8a66597_address(r8a66597, urb->dev),
+			       hub_port, root_port);
+	}
+}
+
+static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597,
+					    struct urb *urb,
+					    struct usb_host_endpoint *hep,
+					    gfp_t mem_flags)
+{
+	struct r8a66597_td *td;
+	u16 pipenum;
+
+	td = kzalloc(sizeof(struct r8a66597_td), mem_flags);
+	if (td == NULL)
+		return NULL;
+
+	pipenum = r8a66597_get_pipenum(urb, hep);
+	td->pipenum = pipenum;
+	td->pipe = hep->hcpriv;
+	td->urb = urb;
+	td->address = get_urb_to_r8a66597_addr(r8a66597, urb);
+	td->maxpacket = usb_maxpacket(urb->dev, urb->pipe,
+				      !usb_pipein(urb->pipe));
+	if (usb_pipecontrol(urb->pipe))
+		td->type = USB_PID_SETUP;
+	else if (usb_pipein(urb->pipe))
+		td->type = USB_PID_IN;
+	else
+		td->type = USB_PID_OUT;
+	INIT_LIST_HEAD(&td->queue);
+
+	return td;
+}
+
+static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
+				struct usb_host_endpoint *hep,
+				struct urb *urb,
+				gfp_t mem_flags)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	struct r8a66597_td *td = NULL;
+	int ret = 0, request = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&r8a66597->lock, flags);
+	if (!get_urb_to_r8a66597_dev(r8a66597, urb)) {
+		ret = -ENODEV;
+		goto error;
+	}
+
+	if (!hep->hcpriv) {
+		hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), mem_flags);
+		if (!hep->hcpriv) {
+			ret = -ENOMEM;
+			goto error;
+		}
+		set_pipe_reg_addr(hep->hcpriv, R8A66597_PIPE_NO_DMA);
+		if (usb_pipeendpoint(urb->pipe))
+			init_pipe_info(r8a66597, urb, hep, &hep->desc);
+	}
+
+	if (unlikely(check_pipe_config(r8a66597, urb)))
+		init_pipe_config(r8a66597, urb);
+
+	set_address_zero(r8a66597, urb);
+	td = r8a66597_make_td(r8a66597, urb, hep, mem_flags);
+	if (td == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	if (list_empty(&r8a66597->pipe_queue[td->pipenum]))
+		request = 1;
+	list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]);
+
+	spin_lock(&urb->lock);
+	if (urb->status != -EINPROGRESS) {
+		spin_unlock(&urb->lock);
+		ret = -EPIPE;
+		goto error;
+	}
+	urb->hcpriv = td;
+	spin_unlock(&urb->lock);
+
+	if (request) {
+		ret = start_transfer(r8a66597, td);
+		if (ret < 0) {
+			list_del(&td->queue);
+			kfree(td);
+		}
+	} else
+		set_td_timer(r8a66597, td);
+
+error:
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
+	return ret;
+}
+
+static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	struct r8a66597_td *td;
+	unsigned long flags;
+
+	spin_lock_irqsave(&r8a66597->lock, flags);
+	if (urb->hcpriv) {
+		td = urb->hcpriv;
+		pipe_stop(r8a66597, td->pipe);
+		pipe_irq_disable(r8a66597, td->pipenum);
+		disable_irq_empty(r8a66597, td->pipenum);
+		done(r8a66597, td, td->pipenum, urb);
+	}
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
+	return 0;
+}
+
+static void r8a66597_endpoint_disable(struct usb_hcd *hcd,
+				      struct usb_host_endpoint *hep)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	struct r8a66597_pipe *pipe = (struct r8a66597_pipe *)hep->hcpriv;
+	struct r8a66597_td *td;
+	struct urb *urb = NULL;
+	u16 pipenum;
+	unsigned long flags;
+
+	if (pipe == NULL)
+		return;
+	pipenum = pipe->info.pipenum;
+
+	if (pipenum == 0) {
+		kfree(hep->hcpriv);
+		hep->hcpriv = NULL;
+		return;
+	}
+
+	spin_lock_irqsave(&r8a66597->lock, flags);
+	pipe_stop(r8a66597, pipe);
+	pipe_irq_disable(r8a66597, pipenum);
+	disable_irq_empty(r8a66597, pipenum);
+	td = r8a66597_get_td(r8a66597, pipenum);
+	if (td)
+		urb = td->urb;
+	done(r8a66597, td, pipenum, urb);
+	kfree(hep->hcpriv);
+	hep->hcpriv = NULL;
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static int r8a66597_get_frame(struct usb_hcd *hcd)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
+}
+
+static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
+{
+	int chix;
+
+	if (udev->state == USB_STATE_CONFIGURED &&
+	    udev->parent && udev->parent->devnum > 1 &&
+	    udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
+		map[udev->devnum/32] |= (1 << (udev->devnum % 32));
+
+	for (chix = 0; chix < udev->maxchild; chix++) {
+		struct usb_device *childdev = udev->children[chix];
+
+		if (childdev)
+			collect_usb_address_map(childdev, map);
+	}
+}
+
+/* this function must be called with interrupt disabled */
+static struct r8a66597_device *get_r8a66597_device(struct r8a66597 *r8a66597,
+						   int addr)
+{
+	struct r8a66597_device *dev;
+	struct list_head *list = &r8a66597->child_device;
+
+	list_for_each_entry(dev, list, device_list) {
+		if (!dev)
+			continue;
+		if (dev->usb_address != addr)
+			continue;
+
+		return dev;
+	}
+
+	err("get_r8a66597_device fail.(%d)\n", addr);
+	return NULL;
+}
+
+static void update_usb_address_map(struct r8a66597 *r8a66597,
+				   struct usb_device *root_hub,
+				   unsigned long *map)
+{
+	int i, j, addr;
+	unsigned long diff;
+	unsigned long flags;
+
+	for (i = 0; i < 4; i++) {
+		diff = r8a66597->child_connect_map[i] ^ map[i];
+		if (!diff)
+			continue;
+
+		for (j = 0; j < 32; j++) {
+			if (!(diff & (1 << j)))
+				continue;
+
+			addr = i * 32 + j;
+			if (map[i] & (1 << j))
+				set_child_connect_map(r8a66597, addr);
+			else {
+				struct r8a66597_device *dev;
+
+				spin_lock_irqsave(&r8a66597->lock, flags);
+				dev = get_r8a66597_device(r8a66597, addr);
+				disable_r8a66597_pipe_all(r8a66597, dev);
+				free_usb_address(r8a66597, dev);
+				put_child_connect_map(r8a66597, addr);
+				spin_unlock_irqrestore(&r8a66597->lock, flags);
+			}
+		}
+	}
+}
+
+static void r8a66597_check_detect_child(struct r8a66597 *r8a66597,
+					struct usb_hcd *hcd)
+{
+	struct usb_bus *bus;
+	unsigned long now_map[4];
+
+	memset(now_map, 0, sizeof(now_map));
+
+	list_for_each_entry(bus, &usb_bus_list, bus_list) {
+		if (!bus->root_hub)
+			continue;
+
+		if (bus->busnum != hcd->self.busnum)
+			continue;
+
+		collect_usb_address_map(bus->root_hub, now_map);
+		update_usb_address_map(r8a66597, bus->root_hub, now_map);
+	}
+}
+
+static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	unsigned long flags;
+	int i;
+
+	r8a66597_check_detect_child(r8a66597, hcd);
+
+	spin_lock_irqsave(&r8a66597->lock, flags);
+
+	*buf = 0;	/* initialize (no change) */
+
+	for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) {
+		if (r8a66597->root_hub[i].port & 0xffff0000)
+			*buf |= 1 << (i + 1);
+	}
+
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
+
+	return (*buf != 0);
+}
+
+static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
+				    struct usb_hub_descriptor *desc)
+{
+	desc->bDescriptorType = 0x29;
+	desc->bHubContrCurrent = 0;
+	desc->bNbrPorts = R8A66597_MAX_ROOT_HUB;
+	desc->bDescLength = 9;
+	desc->bPwrOn2PwrGood = 0;
+	desc->wHubCharacteristics = cpu_to_le16(0x0011);
+	desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1;
+	desc->bitmap[1] = ~0;
+}
+
+static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+				u16 wIndex, char *buf, u16 wLength)
+{
+	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+	int ret;
+	int port = (wIndex & 0x00FF) - 1;
+	struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+	unsigned long flags;
+
+	ret = 0;
+
+	spin_lock_irqsave(&r8a66597->lock, flags);
+	switch (typeReq) {
+	case ClearHubFeature:
+	case SetHubFeature:
+		switch (wValue) {
+		case C_HUB_OVER_CURRENT:
+		case C_HUB_LOCAL_POWER:
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case ClearPortFeature:
+		if (wIndex > R8A66597_MAX_ROOT_HUB)
+			goto error;
+		if (wLength != 0)
+			goto error;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			rh->port &= (1 << USB_PORT_FEAT_POWER);
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+			break;
+		case USB_PORT_FEAT_POWER:
+			r8a66597_port_power(r8a66597, port, 0);
+			break;
+		case USB_PORT_FEAT_C_ENABLE:
+		case USB_PORT_FEAT_C_SUSPEND:
+		case USB_PORT_FEAT_C_CONNECTION:
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+		case USB_PORT_FEAT_C_RESET:
+			break;
+		default:
+			goto error;
+		}
+		rh->port &= ~(1 << wValue);
+		break;
+	case GetHubDescriptor:
+		r8a66597_hub_descriptor(r8a66597,
+					(struct usb_hub_descriptor *)buf);
+		break;
+	case GetHubStatus:
+		*buf = 0x00;
+		break;
+	case GetPortStatus:
+		if (wIndex > R8A66597_MAX_ROOT_HUB)
+			goto error;
+		*(u32 *)buf = rh->port;
+		break;
+	case SetPortFeature:
+		if (wIndex > R8A66597_MAX_ROOT_HUB)
+			goto error;
+		if (wLength != 0)
+			goto error;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			break;
+		case USB_PORT_FEAT_POWER:
+			r8a66597_port_power(r8a66597, port, 1);
+			rh->port |= (1 << USB_PORT_FEAT_POWER);
+			break;
+		case USB_PORT_FEAT_RESET: {
+			struct r8a66597_device *dev = rh->dev;
+
+			rh->port |= (1 << USB_PORT_FEAT_RESET);
+
+			disable_r8a66597_pipe_all(r8a66597, dev);
+			free_usb_address(r8a66597, dev);
+
+			r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,
+				      get_dvstctr_reg(port));
+			mod_timer(&r8a66597->rh_timer,
+				  jiffies + msecs_to_jiffies(50));
+			}
+			break;
+		default:
+			goto error;
+		}
+		rh->port |= 1 << wValue;
+		break;
+	default:
+error:
+		ret = -EPIPE;
+		break;
+	}
+
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
+	return ret;
+}
+
+static struct hc_driver r8a66597_hc_driver = {
+	.description =		hcd_name,
+	.hcd_priv_size =	sizeof(struct r8a66597),
+	.irq =			r8a66597_irq,
+
+	/*
+	 * generic hardware linkage
+	 */
+	.flags =		HCD_USB2,
+
+	.start =		r8a66597_start,
+	.stop =			r8a66597_stop,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		r8a66597_urb_enqueue,
+	.urb_dequeue =		r8a66597_urb_dequeue,
+	.endpoint_disable =	r8a66597_endpoint_disable,
+
+	/*
+	 * periodic schedule support
+	 */
+	.get_frame_number =	r8a66597_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	r8a66597_hub_status_data,
+	.hub_control =		r8a66597_hub_control,
+};
+
+#if defined(CONFIG_PM)
+static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	pdev->dev.power.power_state = state;
+	return 0;
+}
+
+static int r8a66597_resume(struct platform_device *pdev)
+{
+	pdev->dev.power.power_state = PMSG_ON;
+	return 0;
+}
+#else	/* if defined(CONFIG_PM) */
+#define r8a66597_suspend	NULL
+#define r8a66597_resume		NULL
+#endif
+
+static int __init_or_module r8a66597_remove(struct platform_device *pdev)
+{
+	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);
+	struct usb_hcd		*hcd = r8a66597_to_hcd(r8a66597);
+
+	del_timer_sync(&r8a66597->rh_timer);
+	iounmap((void *)r8a66597->reg);
+	usb_remove_hcd(hcd);
+	usb_put_hcd(hcd);
+	return 0;
+}
+
+#define resource_len(r) (((r)->end - (r)->start) + 1)
+static int __init r8a66597_probe(struct platform_device *pdev)
+{
+	struct resource *res = NULL;
+	int irq = -1;
+	void __iomem *reg = NULL;
+	struct usb_hcd *hcd = NULL;
+	struct r8a66597 *r8a66597;
+	int ret = 0;
+	int i;
+
+	if (pdev->dev.dma_mask) {
+		ret = -EINVAL;
+		err("dma not support");
+		goto clean_up;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   (char *)hcd_name);
+	if (!res) {
+		ret = -ENODEV;
+		err("platform_get_resource_byname error.");
+		goto clean_up;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = -ENODEV;
+		err("platform_get_irq error.");
+		goto clean_up;
+	}
+
+	reg = ioremap(res->start, resource_len(res));
+	if (reg == NULL) {
+		ret = -ENOMEM;
+		err("ioremap error.");
+		goto clean_up;
+	}
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&r8a66597_hc_driver, &pdev->dev, (char *)hcd_name);
+	if (!hcd) {
+		ret = -ENOMEM;
+		err("Failed to create hcd");
+		goto clean_up;
+	}
+	r8a66597 = hcd_to_r8a66597(hcd);
+	memset(r8a66597, 0, sizeof(struct r8a66597));
+	dev_set_drvdata(&pdev->dev, r8a66597);
+
+	spin_lock_init(&r8a66597->lock);
+	init_timer(&r8a66597->rh_timer);
+	r8a66597->rh_timer.function = r8a66597_timer;
+	r8a66597->rh_timer.data = (unsigned long)r8a66597;
+	r8a66597->reg = (unsigned long)reg;
+
+	for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) {
+		INIT_LIST_HEAD(&r8a66597->pipe_queue[i]);
+		init_timer(&r8a66597->td_timer[i]);
+		r8a66597->td_timer[i].function = r8a66597_td_timer;
+		r8a66597->td_timer[i].data = (unsigned long)r8a66597;
+	}
+	INIT_LIST_HEAD(&r8a66597->child_device);
+
+	hcd->rsrc_start = res->start;
+	ret = usb_add_hcd(hcd, irq, 0);
+	if (ret != 0) {
+		err("Failed to add hcd");
+		goto clean_up;
+	}
+
+	return 0;
+
+clean_up:
+	if (reg)
+		iounmap(reg);
+	if (res)
+		release_mem_region(res->start, 1);
+
+	return ret;
+}
+
+static struct platform_driver r8a66597_driver = {
+	.probe =	r8a66597_probe,
+	.remove =	r8a66597_remove,
+	.suspend =	r8a66597_suspend,
+	.resume =	r8a66597_resume,
+	.driver		= {
+		.name = (char *) hcd_name,
+	},
+};
+
+static int __init r8a66597_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	info("driver %s, %s", hcd_name, DRIVER_VERSION);
+	return platform_driver_register(&r8a66597_driver);
+}
+module_init(r8a66597_init);
+
+static void __exit r8a66597_cleanup(void)
+{
+	platform_driver_unregister(&r8a66597_driver);
+}
+module_exit(r8a66597_cleanup);
+
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
new file mode 100644
index 0000000..97c2a71
--- /dev/null
+++ b/drivers/usb/host/r8a66597.h
@@ -0,0 +1,634 @@
+/*
+ * R8A66597 HCD (Host Controller Driver)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
+ * Portions Copyright (C) 2004-2005 David Brownell
+ * Portions Copyright (C) 1999 Roman Weissgaerber
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __R8A66597_H__
+#define __R8A66597_H__
+
+#define SYSCFG0		0x00
+#define SYSCFG1		0x02
+#define SYSSTS0		0x04
+#define SYSSTS1		0x06
+#define DVSTCTR0	0x08
+#define DVSTCTR1	0x0A
+#define TESTMODE	0x0C
+#define PINCFG		0x0E
+#define DMA0CFG		0x10
+#define DMA1CFG		0x12
+#define CFIFO		0x14
+#define D0FIFO		0x18
+#define D1FIFO		0x1C
+#define CFIFOSEL	0x20
+#define CFIFOCTR	0x22
+#define CFIFOSIE	0x24
+#define D0FIFOSEL	0x28
+#define D0FIFOCTR	0x2A
+#define D1FIFOSEL	0x2C
+#define D1FIFOCTR	0x2E
+#define INTENB0		0x30
+#define INTENB1		0x32
+#define INTENB2		0x34
+#define BRDYENB		0x36
+#define NRDYENB		0x38
+#define BEMPENB		0x3A
+#define SOFCFG		0x3C
+#define INTSTS0		0x40
+#define INTSTS1		0x42
+#define INTSTS2		0x44
+#define BRDYSTS		0x46
+#define NRDYSTS		0x48
+#define BEMPSTS		0x4A
+#define FRMNUM		0x4C
+#define UFRMNUM		0x4E
+#define USBADDR		0x50
+#define USBREQ		0x54
+#define USBVAL		0x56
+#define USBINDX		0x58
+#define USBLENG		0x5A
+#define DCPCFG		0x5C
+#define DCPMAXP		0x5E
+#define DCPCTR		0x60
+#define PIPESEL		0x64
+#define PIPECFG		0x68
+#define PIPEBUF		0x6A
+#define PIPEMAXP	0x6C
+#define PIPEPERI	0x6E
+#define PIPE1CTR	0x70
+#define PIPE2CTR	0x72
+#define PIPE3CTR	0x74
+#define PIPE4CTR	0x76
+#define PIPE5CTR	0x78
+#define PIPE6CTR	0x7A
+#define PIPE7CTR	0x7C
+#define PIPE8CTR	0x7E
+#define PIPE9CTR	0x80
+#define PIPE1TRE	0x90
+#define PIPE1TRN	0x92
+#define PIPE2TRE	0x94
+#define PIPE2TRN	0x96
+#define PIPE3TRE	0x98
+#define PIPE3TRN	0x9A
+#define PIPE4TRE	0x9C
+#define	PIPE4TRN	0x9E
+#define	PIPE5TRE	0xA0
+#define	PIPE5TRN	0xA2
+#define DEVADD0		0xD0
+#define DEVADD1		0xD2
+#define DEVADD2		0xD4
+#define DEVADD3		0xD6
+#define DEVADD4		0xD8
+#define DEVADD5		0xDA
+#define DEVADD6		0xDC
+#define DEVADD7		0xDE
+#define DEVADD8		0xE0
+#define DEVADD9		0xE2
+#define DEVADDA		0xE4
+
+/* System Configuration Control Register */
+#define	XTAL		0xC000	/* b15-14: Crystal selection */
+#define	  XTAL48	 0x8000	  /* 48MHz */
+#define	  XTAL24	 0x4000	  /* 24MHz */
+#define	  XTAL12	 0x0000	  /* 12MHz */
+#define	XCKE		0x2000	/* b13: External clock enable */
+#define	PLLC		0x0800	/* b11: PLL control */
+#define	SCKE		0x0400	/* b10: USB clock enable */
+#define	PCSDIS		0x0200	/* b9: not CS wakeup */
+#define	LPSME		0x0100	/* b8: Low power sleep mode */
+#define	HSE		0x0080	/* b7: Hi-speed enable */
+#define	DCFM		0x0040	/* b6: Controller function select  */
+#define	DRPD		0x0020	/* b5: D+/- pull down control */
+#define	DPRPU		0x0010	/* b4: D+ pull up control */
+#define	USBE		0x0001	/* b0: USB module operation enable */
+
+/* System Configuration Status Register */
+#define	OVCBIT		0x8000	/* b15-14: Over-current bit */
+#define	OVCMON		0xC000	/* b15-14: Over-current monitor */
+#define	SOFEA		0x0020	/* b5: SOF monitor */
+#define	IDMON		0x0004	/* b3: ID-pin monitor */
+#define	LNST		0x0003	/* b1-0: D+, D- line status */
+#define	  SE1		 0x0003	  /* SE1 */
+#define	  FS_KSTS	 0x0002	  /* Full-Speed K State */
+#define	  FS_JSTS	 0x0001	  /* Full-Speed J State */
+#define	  LS_JSTS	 0x0002	  /* Low-Speed J State */
+#define	  LS_KSTS	 0x0001	  /* Low-Speed K State */
+#define	  SE0		 0x0000	  /* SE0 */
+
+/* Device State Control Register */
+#define	EXTLP0		0x0400	/* b10: External port */
+#define	VBOUT		0x0200	/* b9: VBUS output */
+#define	WKUP		0x0100	/* b8: Remote wakeup */
+#define	RWUPE		0x0080	/* b7: Remote wakeup sense */
+#define	USBRST		0x0040	/* b6: USB reset enable */
+#define	RESUME		0x0020	/* b5: Resume enable */
+#define	UACT		0x0010	/* b4: USB bus enable */
+#define	RHST		0x0007	/* b1-0: Reset handshake status */
+#define	  HSPROC	 0x0004	  /* HS handshake is processing */
+#define	  HSMODE	 0x0003	  /* Hi-Speed mode */
+#define	  FSMODE	 0x0002	  /* Full-Speed mode */
+#define	  LSMODE	 0x0001	  /* Low-Speed mode */
+#define	  UNDECID	 0x0000	  /* Undecided */
+
+/* Test Mode Register */
+#define	UTST			0x000F	/* b3-0: Test select */
+#define	  H_TST_PACKET		 0x000C	  /* HOST TEST Packet */
+#define	  H_TST_SE0_NAK		 0x000B	  /* HOST TEST SE0 NAK */
+#define	  H_TST_K		 0x000A	  /* HOST TEST K */
+#define	  H_TST_J		 0x0009	  /* HOST TEST J */
+#define	  H_TST_NORMAL		 0x0000	  /* HOST Normal Mode */
+#define	  P_TST_PACKET		 0x0004	  /* PERI TEST Packet */
+#define	  P_TST_SE0_NAK		 0x0003	  /* PERI TEST SE0 NAK */
+#define	  P_TST_K		 0x0002	  /* PERI TEST K */
+#define	  P_TST_J		 0x0001	  /* PERI TEST J */
+#define	  P_TST_NORMAL		 0x0000	  /* PERI Normal Mode */
+
+/* Data Pin Configuration Register */
+#define	LDRV			0x8000	/* b15: Drive Current Adjust */
+#define	  VIF1			  0x0000		/* VIF = 1.8V */
+#define	  VIF3			  0x8000		/* VIF = 3.3V */
+#define	INTA			0x0001	/* b1: USB INT-pin active */
+
+/* DMAx Pin Configuration Register */
+#define	DREQA			0x4000	/* b14: Dreq active select */
+#define	BURST			0x2000	/* b13: Burst mode */
+#define	DACKA			0x0400	/* b10: Dack active select */
+#define	DFORM			0x0380	/* b9-7: DMA mode select */
+#define	  CPU_ADR_RD_WR		 0x0000	  /* Address + RD/WR mode (CPU bus) */
+#define	  CPU_DACK_RD_WR	 0x0100	  /* DACK + RD/WR mode (CPU bus) */
+#define	  CPU_DACK_ONLY		 0x0180	  /* DACK only mode (CPU bus) */
+#define	  SPLIT_DACK_ONLY	 0x0200	  /* DACK only mode (SPLIT bus) */
+#define	DENDA			0x0040	/* b6: Dend active select */
+#define	PKTM			0x0020	/* b5: Packet mode */
+#define	DENDE			0x0010	/* b4: Dend enable */
+#define	OBUS			0x0004	/* b2: OUTbus mode */
+
+/* CFIFO/DxFIFO Port Select Register */
+#define	RCNT		0x8000	/* b15: Read count mode */
+#define	REW		0x4000	/* b14: Buffer rewind */
+#define	DCLRM		0x2000	/* b13: DMA buffer clear mode */
+#define	DREQE		0x1000	/* b12: DREQ output enable */
+#define	MBW		0x0400	/* b10: Maximum bit width for FIFO access */
+#define	  MBW_8		 0x0000	  /*  8bit */
+#define	  MBW_16	 0x0400	  /* 16bit */
+#define	BIGEND		0x0100	/* b8: Big endian mode */
+#define	  BYTE_LITTLE	 0x0000		/* little dendian */
+#define	  BYTE_BIG	 0x0100		/* big endifan */
+#define	ISEL		0x0020	/* b5: DCP FIFO port direction select */
+#define	CURPIPE		0x000F	/* b2-0: PIPE select */
+
+/* CFIFO/DxFIFO Port Control Register */
+#define	BVAL		0x8000	/* b15: Buffer valid flag */
+#define	BCLR		0x4000	/* b14: Buffer clear */
+#define	FRDY		0x2000	/* b13: FIFO ready */
+#define	DTLN		0x0FFF	/* b11-0: FIFO received data length */
+
+/* Interrupt Enable Register 0 */
+#define	VBSE		0x8000	/* b15: VBUS interrupt */
+#define	RSME		0x4000	/* b14: Resume interrupt */
+#define	SOFE		0x2000	/* b13: Frame update interrupt */
+#define	DVSE		0x1000	/* b12: Device state transition interrupt */
+#define	CTRE		0x0800	/* b11: Control transfer stage transition interrupt */
+#define	BEMPE		0x0400	/* b10: Buffer empty interrupt */
+#define	NRDYE		0x0200	/* b9: Buffer not ready interrupt */
+#define	BRDYE		0x0100	/* b8: Buffer ready interrupt */
+
+/* Interrupt Enable Register 1 */
+#define	OVRCRE		0x8000	/* b15: Over-current interrupt */
+#define	BCHGE		0x4000	/* b14: USB us chenge interrupt */
+#define	DTCHE		0x1000	/* b12: Detach sense interrupt */
+#define	ATTCHE		0x0800	/* b11: Attach sense interrupt */
+#define	EOFERRE		0x0040	/* b6: EOF error interrupt */
+#define	SIGNE		0x0020	/* b5: SETUP IGNORE interrupt */
+#define	SACKE		0x0010	/* b4: SETUP ACK interrupt */
+
+/* BRDY Interrupt Enable/Status Register */
+#define	BRDY9		0x0200	/* b9: PIPE9 */
+#define	BRDY8		0x0100	/* b8: PIPE8 */
+#define	BRDY7		0x0080	/* b7: PIPE7 */
+#define	BRDY6		0x0040	/* b6: PIPE6 */
+#define	BRDY5		0x0020	/* b5: PIPE5 */
+#define	BRDY4		0x0010	/* b4: PIPE4 */
+#define	BRDY3		0x0008	/* b3: PIPE3 */
+#define	BRDY2		0x0004	/* b2: PIPE2 */
+#define	BRDY1		0x0002	/* b1: PIPE1 */
+#define	BRDY0		0x0001	/* b1: PIPE0 */
+
+/* NRDY Interrupt Enable/Status Register */
+#define	NRDY9		0x0200	/* b9: PIPE9 */
+#define	NRDY8		0x0100	/* b8: PIPE8 */
+#define	NRDY7		0x0080	/* b7: PIPE7 */
+#define	NRDY6		0x0040	/* b6: PIPE6 */
+#define	NRDY5		0x0020	/* b5: PIPE5 */
+#define	NRDY4		0x0010	/* b4: PIPE4 */
+#define	NRDY3		0x0008	/* b3: PIPE3 */
+#define	NRDY2		0x0004	/* b2: PIPE2 */
+#define	NRDY1		0x0002	/* b1: PIPE1 */
+#define	NRDY0		0x0001	/* b1: PIPE0 */
+
+/* BEMP Interrupt Enable/Status Register */
+#define	BEMP9		0x0200	/* b9: PIPE9 */
+#define	BEMP8		0x0100	/* b8: PIPE8 */
+#define	BEMP7		0x0080	/* b7: PIPE7 */
+#define	BEMP6		0x0040	/* b6: PIPE6 */
+#define	BEMP5		0x0020	/* b5: PIPE5 */
+#define	BEMP4		0x0010	/* b4: PIPE4 */
+#define	BEMP3		0x0008	/* b3: PIPE3 */
+#define	BEMP2		0x0004	/* b2: PIPE2 */
+#define	BEMP1		0x0002	/* b1: PIPE1 */
+#define	BEMP0		0x0001	/* b0: PIPE0 */
+
+/* SOF Pin Configuration Register */
+#define	TRNENSEL	0x0100	/* b8: Select transaction enable period */
+#define	BRDYM		0x0040	/* b6: BRDY clear timing */
+#define	INTL		0x0020	/* b5: Interrupt sense select */
+#define	EDGESTS		0x0010	/* b4:  */
+#define	SOFMODE		0x000C	/* b3-2: SOF pin select */
+#define	  SOF_125US	 0x0008	  /* SOF OUT 125us Frame Signal */
+#define	  SOF_1MS	 0x0004	  /* SOF OUT 1ms Frame Signal */
+#define	  SOF_DISABLE	 0x0000	  /* SOF OUT Disable */
+
+/* Interrupt Status Register 0 */
+#define	VBINT		0x8000	/* b15: VBUS interrupt */
+#define	RESM		0x4000	/* b14: Resume interrupt */
+#define	SOFR		0x2000	/* b13: SOF frame update interrupt */
+#define	DVST		0x1000	/* b12: Device state transition interrupt */
+#define	CTRT		0x0800	/* b11: Control transfer stage transition interrupt */
+#define	BEMP		0x0400	/* b10: Buffer empty interrupt */
+#define	NRDY		0x0200	/* b9: Buffer not ready interrupt */
+#define	BRDY		0x0100	/* b8: Buffer ready interrupt */
+#define	VBSTS		0x0080	/* b7: VBUS input port */
+#define	DVSQ		0x0070	/* b6-4: Device state */
+#define	  DS_SPD_CNFG	 0x0070	  /* Suspend Configured */
+#define	  DS_SPD_ADDR	 0x0060	  /* Suspend Address */
+#define	  DS_SPD_DFLT	 0x0050	  /* Suspend Default */
+#define	  DS_SPD_POWR	 0x0040	  /* Suspend Powered */
+#define	  DS_SUSP	 0x0040	  /* Suspend */
+#define	  DS_CNFG	 0x0030	  /* Configured */
+#define	  DS_ADDS	 0x0020	  /* Address */
+#define	  DS_DFLT	 0x0010	  /* Default */
+#define	  DS_POWR	 0x0000	  /* Powered */
+#define	DVSQS		0x0030	/* b5-4: Device state */
+#define	VALID		0x0008	/* b3: Setup packet detected flag */
+#define	CTSQ		0x0007	/* b2-0: Control transfer stage */
+#define	  CS_SQER	 0x0006	  /* Sequence error */
+#define	  CS_WRND	 0x0005	  /* Control write nodata status stage */
+#define	  CS_WRSS	 0x0004	  /* Control write status stage */
+#define	  CS_WRDS	 0x0003	  /* Control write data stage */
+#define	  CS_RDSS	 0x0002	  /* Control read status stage */
+#define	  CS_RDDS	 0x0001	  /* Control read data stage */
+#define	  CS_IDST	 0x0000	  /* Idle or setup stage */
+
+/* Interrupt Status Register 1 */
+#define	OVRCR		0x8000	/* b15: Over-current interrupt */
+#define	BCHG		0x4000	/* b14: USB bus chenge interrupt */
+#define	DTCH		0x1000	/* b12: Detach sense interrupt */
+#define	ATTCH		0x0800	/* b11: Attach sense interrupt */
+#define	EOFERR		0x0040	/* b6: EOF-error interrupt */
+#define	SIGN		0x0020	/* b5: Setup ignore interrupt */
+#define	SACK		0x0010	/* b4: Setup acknowledge interrupt */
+
+/* Frame Number Register */
+#define	OVRN		0x8000	/* b15: Overrun error */
+#define	CRCE		0x4000	/* b14: Received data error */
+#define	FRNM		0x07FF	/* b10-0: Frame number */
+
+/* Micro Frame Number Register */
+#define	UFRNM		0x0007	/* b2-0: Micro frame number */
+
+/* USB Address / Low Power Status Recovery Register */
+//#define	USBADDR		0x007F	/* b6-0: USB address */
+
+/* Default Control Pipe Maxpacket Size Register */
+/* Pipe Maxpacket Size Register */
+#define	DEVSEL		0xF000	/* b15-14: Device address select */
+#define	MAXP		0x007F	/* b6-0: Maxpacket size of default control pipe */
+
+/* Default Control Pipe Control Register */
+#define	BSTS		0x8000	/* b15: Buffer status */
+#define	SUREQ		0x4000	/* b14: Send USB request  */
+#define	CSCLR		0x2000	/* b13: complete-split status clear */
+#define	CSSTS		0x1000	/* b12: complete-split status */
+#define	SUREQCLR	0x0800	/* b11: stop setup request */
+#define	SQCLR		0x0100	/* b8: Sequence toggle bit clear */
+#define	SQSET		0x0080	/* b7: Sequence toggle bit set */
+#define	SQMON		0x0040	/* b6: Sequence toggle bit monitor */
+#define	PBUSY		0x0020	/* b5: pipe busy */
+#define	PINGE		0x0010	/* b4: ping enable */
+#define	CCPL		0x0004	/* b2: Enable control transfer complete */
+#define	PID		0x0003	/* b1-0: Response PID */
+#define	  PID_STALL11	 0x0003	  /* STALL */
+#define	  PID_STALL	 0x0002	  /* STALL */
+#define	  PID_BUF	 0x0001	  /* BUF */
+#define	  PID_NAK	 0x0000	  /* NAK */
+
+/* Pipe Window Select Register */
+#define	PIPENM		0x0007	/* b2-0: Pipe select */
+
+/* Pipe Configuration Register */
+#define	R8A66597_TYP	0xC000	/* b15-14: Transfer type */
+#define	  R8A66597_ISO	 0xC000		  /* Isochronous */
+#define	  R8A66597_INT	 0x8000		  /* Interrupt */
+#define	  R8A66597_BULK	 0x4000		  /* Bulk */
+#define	R8A66597_BFRE	0x0400	/* b10: Buffer ready interrupt mode select */
+#define	R8A66597_DBLB	0x0200	/* b9: Double buffer mode select */
+#define	R8A66597_CNTMD	0x0100	/* b8: Continuous transfer mode select */
+#define	R8A66597_SHTNAK	0x0080	/* b7: Transfer end NAK */
+#define	R8A66597_DIR	0x0010	/* b4: Transfer direction select */
+#define	R8A66597_EPNUM	0x000F	/* b3-0: Eendpoint number select */
+
+/* Pipe Buffer Configuration Register */
+#define	BUFSIZE		0x7C00	/* b14-10: Pipe buffer size */
+#define	BUFNMB		0x007F	/* b6-0: Pipe buffer number */
+#define	PIPE0BUF	256
+#define	PIPExBUF	64
+
+/* Pipe Maxpacket Size Register */
+#define	MXPS		0x07FF	/* b10-0: Maxpacket size */
+
+/* Pipe Cycle Configuration Register */
+#define	IFIS		0x1000	/* b12: Isochronous in-buffer flush mode select */
+#define	IITV		0x0007	/* b2-0: Isochronous interval */
+
+/* Pipex Control Register */
+#define	BSTS		0x8000	/* b15: Buffer status */
+#define	INBUFM		0x4000	/* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define	CSCLR		0x2000	/* b13: complete-split status clear */
+#define	CSSTS		0x1000	/* b12: complete-split status */
+#define	ATREPM		0x0400	/* b10: Auto repeat mode */
+#define	ACLRM		0x0200	/* b9: Out buffer auto clear mode */
+#define	SQCLR		0x0100	/* b8: Sequence toggle bit clear */
+#define	SQSET		0x0080	/* b7: Sequence toggle bit set */
+#define	SQMON		0x0040	/* b6: Sequence toggle bit monitor */
+#define	PBUSY		0x0020	/* b5: pipe busy */
+#define	PID		0x0003	/* b1-0: Response PID */
+
+/* PIPExTRE */
+#define	TRENB		0x0200	/* b9: Transaction counter enable */
+#define	TRCLR		0x0100	/* b8: Transaction counter clear */
+
+/* PIPExTRN */
+#define	TRNCNT		0xFFFF	/* b15-0: Transaction counter */
+
+/* DEVADDx */
+#define	UPPHUB		0x7800
+#define	HUBPORT		0x0700
+#define	USBSPD		0x00C0
+#define	RTPORT		0x0001
+
+#define R8A66597_MAX_NUM_PIPE		10
+#define R8A66597_BUF_BSIZE		8
+#define R8A66597_MAX_DEVICE		10
+#define R8A66597_MAX_ROOT_HUB		2
+#define R8A66597_MAX_SAMPLING		10
+#define R8A66597_MAX_DMA_CHANNEL	2
+#define R8A66597_PIPE_NO_DMA		R8A66597_MAX_DMA_CHANNEL
+#define check_bulk_or_isoc(pipenum)	((pipenum >= 1 && pipenum <= 5))
+#define check_interrupt(pipenum)	((pipenum >= 6 && pipenum <= 9))
+#define make_devsel(addr)		(addr << 12)
+
+struct r8a66597_pipe_info {
+        u16 pipenum;
+        u16 address;	/* R8A66597 HCD usb addres */
+        u16 epnum;
+        u16 maxpacket;
+        u16 type;
+        u16 bufnum;
+        u16 buf_bsize;
+        u16 interval;
+        u16 dir_in;
+};
+
+struct r8a66597_pipe {
+	struct r8a66597_pipe_info info;
+
+	unsigned long fifoaddr;
+	unsigned long fifosel;
+	unsigned long fifoctr;
+	unsigned long pipectr;
+	unsigned long pipetre;
+	unsigned long pipetrn;
+};
+
+struct r8a66597_td {
+	struct r8a66597_pipe *pipe;
+	struct urb *urb;
+	struct list_head queue;
+
+	u16 type;
+	u16 pipenum;
+	int iso_cnt;
+
+	u16 address;		/* R8A66597's USB address */
+	u16 maxpacket;
+
+	unsigned zero_packet:1;
+	unsigned short_packet:1;
+	unsigned set_address:1;
+};
+
+struct r8a66597_device {
+	u16	address;	/* R8A66597's USB address */
+	u16	hub_port;
+	u16	root_port;
+
+	unsigned short ep_in_toggle;
+	unsigned short ep_out_toggle;
+	unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+	unsigned char dma_map;
+
+	enum usb_device_state state;
+
+	struct usb_device *udev;
+	int usb_address;
+	struct list_head device_list;
+};
+
+struct r8a66597_root_hub {
+	u32 port;
+	u16 old_syssts;
+	int scount;
+
+	struct r8a66597_device	*dev;
+};
+
+struct r8a66597 {
+	spinlock_t lock;
+	unsigned long reg;
+
+	struct r8a66597_device		device0;
+	struct r8a66597_root_hub	root_hub[R8A66597_MAX_ROOT_HUB];
+	struct list_head		pipe_queue[R8A66597_MAX_NUM_PIPE];
+
+	struct timer_list rh_timer;
+	struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
+
+	unsigned short address_map;
+	unsigned short timeout_map;
+	unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+	unsigned char dma_map;
+
+	struct list_head child_device;
+	unsigned long child_connect_map[4];
+};
+
+static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd)
+{
+	return (struct r8a66597 *)(hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *r8a66597_to_hcd(struct r8a66597 *r8a66597)
+{
+	return container_of((void *)r8a66597, struct usb_hcd, hcd_priv);
+}
+
+static inline struct r8a66597_td *r8a66597_get_td(struct r8a66597 *r8a66597,
+						  u16 pipenum)
+{
+	if (unlikely(list_empty(&r8a66597->pipe_queue[pipenum])))
+		return NULL;
+
+	return list_entry(r8a66597->pipe_queue[pipenum].next,
+			  struct r8a66597_td, queue);
+}
+
+static inline struct urb *r8a66597_get_urb(struct r8a66597 *r8a66597,
+					   u16 pipenum)
+{
+	struct r8a66597_td *td;
+
+	td = r8a66597_get_td(r8a66597, pipenum);
+	return (td ? td->urb : NULL);
+}
+
+static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
+{
+	return inw(r8a66597->reg + offset);
+}
+
+static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+				      unsigned long offset, u16 *buf,
+				      int len)
+{
+	len = (len + 1) / 2;
+	insw(r8a66597->reg + offset, buf, len);
+}
+
+static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+				  unsigned long offset)
+{
+	outw(val, r8a66597->reg + offset);
+}
+
+static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+				       unsigned long offset, u16 *buf,
+				       int len)
+{
+	unsigned long fifoaddr = r8a66597->reg + offset;
+	int odd = len & 0x0001;
+
+	len = len / 2;
+	outsw(fifoaddr, buf, len);
+	if (unlikely(odd)) {
+		buf = &buf[len];
+		outb((unsigned char)*buf, fifoaddr);
+	}
+}
+
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+				 u16 val, u16 pat, unsigned long offset)
+{
+	u16 tmp;
+	tmp = r8a66597_read(r8a66597, offset);
+	tmp = tmp & (~pat);
+	tmp = tmp | val;
+	r8a66597_write(r8a66597, tmp, offset);
+}
+
+#define r8a66597_bclr(r8a66597, val, offset)	\
+			r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset)	\
+			r8a66597_mdfy(r8a66597, val, 0, offset)
+
+static inline unsigned long get_syscfg_reg(int port)
+{
+	return port == 0 ? SYSCFG0 : SYSCFG1;
+}
+
+static inline unsigned long get_syssts_reg(int port)
+{
+	return port == 0 ? SYSSTS0 : SYSSTS1;
+}
+
+static inline unsigned long get_dvstctr_reg(int port)
+{
+	return port == 0 ? DVSTCTR0 : DVSTCTR1;
+}
+
+static inline unsigned long get_intenb_reg(int port)
+{
+	return port == 0 ? INTENB1 : INTENB2;
+}
+
+static inline unsigned long get_intsts_reg(int port)
+{
+	return port == 0 ? INTSTS1 : INTSTS2;
+}
+
+static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port)
+{
+	unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+	return r8a66597_read(r8a66597, dvstctr_reg) & RHST;
+}
+
+static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port,
+				       int power)
+{
+	unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+	if (power)
+		r8a66597_bset(r8a66597, VBOUT, dvstctr_reg);
+	else
+		r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg);
+}
+
+#define get_pipectr_addr(pipenum)	(PIPE1CTR + (pipenum - 1) * 2)
+#define get_pipetre_addr(pipenum)	(PIPE1TRE + (pipenum - 1) * 4)
+#define get_pipetrn_addr(pipenum)	(PIPE1TRN + (pipenum - 1) * 4)
+#define get_devadd_addr(address)	(DEVADD0 + address * 2)
+
+#define enable_irq_ready(r8a66597, pipenum)	\
+	enable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define disable_irq_ready(r8a66597, pipenum)	\
+	disable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define enable_irq_empty(r8a66597, pipenum)	\
+	enable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define disable_irq_empty(r8a66597, pipenum)	\
+	disable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define enable_irq_nrdy(r8a66597, pipenum)	\
+	enable_pipe_irq(r8a66597, pipenum, NRDYENB)
+#define disable_irq_nrdy(r8a66597, pipenum)	\
+	disable_pipe_irq(r8a66597, pipenum, NRDYENB)
+
+#endif	/* __R8A66597_H__ */
+
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index ff0dba0..e98df2e 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -57,6 +57,13 @@
 #include <asm/system.h>
 #include <asm/byteorder.h>
 #include "../core/hcd.h"
+
+	/* FIXME ohci.h is ONLY for internal use by the OHCI driver.
+	 * If you're going to try stuff like this, you need to split
+	 * out shareable stuff (register declarations?) into its own
+	 * file, maybe name <linux/usb/ohci.h>
+	 */
+
 #include "ohci.h"
 #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
 #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
@@ -173,11 +180,6 @@
         struct u132_endp *curr_endp;
         struct delayed_work scheduler;
 };
-#define OHCI_QUIRK_AMD756 0x01
-#define OHCI_QUIRK_SUPERIO 0x02
-#define OHCI_QUIRK_INITRESET 0x04
-#define OHCI_BIG_ENDIAN 0x08
-#define OHCI_QUIRK_ZFMICRO 0x10
 struct u132 {
         struct kref kref;
         struct list_head u132_list;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index d22da26..76c555a 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -730,10 +730,9 @@
 	int rc = 0;
 
 	spin_lock_irq(&uhci->lock);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
-		dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
 		rc = -ESHUTDOWN;
-	} else if (!uhci->dead)
+	else if (!uhci->dead)
 		wakeup_rh(uhci);
 	spin_unlock_irq(&uhci->lock);
 	return rc;
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 77145f9..d72c42e 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -108,8 +108,6 @@
 	struct urb*		interrupt_out_urb;
 };
 
-/* prevent races between open() and disconnect */
-static DEFINE_MUTEX(disconnect_mutex);
 static struct usb_driver adu_driver;
 
 static void adu_debug_data(int level, const char *function, int size,
@@ -256,8 +254,6 @@
 
 	subminor = iminor(inode);
 
-	mutex_lock(&disconnect_mutex);
-
 	interface = usb_find_interface(&adu_driver, subminor);
 	if (!interface) {
 		err("%s - error, can't find device for minor %d",
@@ -306,7 +302,6 @@
 	up(&dev->sem);
 
 exit_no_device:
-	mutex_unlock(&disconnect_mutex);
 	dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
 
 	return retval;
@@ -318,12 +313,6 @@
 
 	dbg(2," %s : enter", __FUNCTION__);
 
-	if (dev->udev == NULL) {
-		/* the device was unplugged before the file was released */
-		adu_delete(dev);
-		goto exit;
-	}
-
 	/* decrement our usage count for the device */
 	--dev->open_count;
 	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
@@ -332,7 +321,6 @@
 		dev->open_count = 0;
 	}
 
-exit:
 	dbg(2," %s : leave", __FUNCTION__);
 	return retval;
 }
@@ -367,8 +355,15 @@
 		goto exit;
 	}
 
-	/* do the work */
-	retval = adu_release_internal(dev);
+	if (dev->udev == NULL) {
+		/* the device was unplugged before the file was released */
+		up(&dev->sem);
+		adu_delete(dev);
+		dev = NULL;
+	} else {
+		/* do the work */
+		retval = adu_release_internal(dev);
+	}
 
 exit:
 	if (dev)
@@ -831,19 +826,17 @@
 
 	dbg(2," %s : enter", __FUNCTION__);
 
-	mutex_lock(&disconnect_mutex); /* not interruptible */
-
 	dev = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 
-	down(&dev->sem); /* not interruptible */
-
 	minor = dev->minor;
 
 	/* give back our minor */
 	usb_deregister_dev(interface, &adu_class);
 	dev->minor = 0;
 
+	down(&dev->sem); /* not interruptible */
+
 	/* if the device is not opened, then we clean up right now */
 	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
 	if (!dev->open_count) {
@@ -854,8 +847,6 @@
 		up(&dev->sem);
 	}
 
-	mutex_unlock(&disconnect_mutex);
-
 	dev_info(&interface->dev, "ADU device adutux%d now disconnected",
 		 (minor - ADU_MINOR_BASE));
 
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 88fb56d..42d4e64 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -630,7 +630,7 @@
 	} else
 		status = urb->status;
 
-	if (actual_length)
+	if (status >= 0)
 		*actual_length = urb->actual_length;
 
   	return status;
@@ -664,7 +664,7 @@
 	int ret;
 	struct usb_ctrlrequest *dr;
 	struct urb *urb;
-        int length;
+        int uninitialized_var(length);
 
         dbg ("auerchain_control_msg");
         dr = kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
@@ -1822,16 +1822,10 @@
 	pauerswald_t cp;
 	dbg("release");
 
-	/* get the mutexes */
-	if (down_interruptible (&ccp->mutex)) {
-		return -ERESTARTSYS;
-	}
+	down(&ccp->mutex);
 	cp = ccp->auerdev;
 	if (cp) {
-		if (down_interruptible (&cp->mutex)) {
-			up (&ccp->mutex);
-			return -ERESTARTSYS;
-		}
+		down(&cp->mutex);
 		/* remove an open service */
 		auerswald_removeservice (cp, &ccp->scontext);
 		/* detach from device */
@@ -2040,12 +2034,12 @@
 	if (!cp)
 		return;
 
-	down (&cp->mutex);
-	info ("device /dev/%s now disconnecting", cp->name);
-
 	/* give back our USB minor number */
 	usb_deregister_dev(intf, &auerswald_class);
 
+	down (&cp->mutex);
+	info ("device /dev/%s now disconnecting", cp->name);
+
 	/* Stop the interrupt endpoint */
 	auerswald_int_release (cp);
 
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
index b15f2fd..92c1d27 100644
--- a/drivers/usb/misc/berry_charge.c
+++ b/drivers/usb/misc/berry_charge.c
@@ -26,8 +26,11 @@
 
 #define RIM_VENDOR		0x0fca
 #define BLACKBERRY		0x0001
+#define BLACKBERRY_PEARL_DUAL   0x0004
+#define BLACKBERRY_PEARL        0x0006
 
 static int debug;
+static int pearl_dual_mode = 1;
 
 #ifdef dbg
 #undef dbg
@@ -38,6 +41,8 @@
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) },
+	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) },
 	{ },					/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -86,6 +91,30 @@
 	return retval;
 }
 
+static int magic_dual_mode(struct usb_device *udev)
+{
+	char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+	int retval;
+
+	if (!dummy_buffer)
+		return -ENOMEM;
+
+	/* send magic command so that the Blackberry Pearl device exposes
+	 * two interfaces: both the USB mass-storage one and one which can
+	 * be used for database access. */
+	dbg(&udev->dev, "Sending magic pearl command\n");
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100);
+	dbg(&udev->dev, "Magic pearl command returned %d\n", retval);
+
+	dbg(&udev->dev, "Calling set_configuration\n");
+	retval = usb_driver_set_configuration(udev, 1);
+	if (retval)
+		dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+	return retval;
+}
+
 static int berry_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
 {
@@ -105,6 +134,10 @@
 	/* turn the power on */
 	magic_charge(udev);
 
+	if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) &&
+	    (pearl_dual_mode))
+		magic_dual_mode(udev);
+
 	/* we don't really want to bind to the device, userspace programs can
 	 * handle the syncing just fine, so get outta here. */
 	return -ENODEV;
@@ -138,3 +171,5 @@
 MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
+module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode");
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index e2172e5..e0f122e 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -73,6 +73,13 @@
 #include "usb_u132.h"
 #include <asm/io.h>
 #include "../core/hcd.h"
+
+	/* FIXME ohci.h is ONLY for internal use by the OHCI driver.
+	 * If you're going to try stuff like this, you need to split
+	 * out shareable stuff (register declarations?) into its own
+	 * file, maybe name <linux/usb/ohci.h>
+	 */
+
 #include "../host/ohci.h"
 /* Define these values to match your devices*/
 #define USB_FTDI_ELAN_VENDOR_ID 0x0403
@@ -2300,10 +2307,7 @@
         offsetof(struct ohci_regs, member), 0, data);
 #define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \
         offsetof(struct ohci_regs, member), 0, data);
-#define OHCI_QUIRK_AMD756 0x01
-#define OHCI_QUIRK_SUPERIO 0x02
-#define OHCI_QUIRK_INITRESET 0x04
-#define OHCI_BIG_ENDIAN 0x08
+
 #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
 #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
         OHCI_INTR_WDH)
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 8d0e360..e6fd024 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -119,9 +119,6 @@
 	.id_table = idmouse_table,
 };
 
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
 static int idmouse_create_image(struct usb_idmouse *dev)
 {
 	int bytes_read;
@@ -211,21 +208,15 @@
 	struct usb_interface *interface;
 	int result;
 
-	/* prevent disconnects */
-	mutex_lock(&disconnect_mutex);
-
 	/* get the interface from minor number and driver information */
 	interface = usb_find_interface (&idmouse_driver, iminor (inode));
-	if (!interface) {
-		mutex_unlock(&disconnect_mutex);
+	if (!interface)
 		return -ENODEV;
-	}
+
 	/* get the device information block from the interface */
 	dev = usb_get_intfdata(interface);
-	if (!dev) {
-		mutex_unlock(&disconnect_mutex);
+	if (!dev)
 		return -ENODEV;
-	}
 
 	/* lock this device */
 	down(&dev->sem);
@@ -255,9 +246,6 @@
 
 	/* unlock this device */
 	up(&dev->sem);
-
-	/* unlock the disconnect semaphore */
-	mutex_unlock(&disconnect_mutex);
 	return result;
 }
 
@@ -265,15 +253,10 @@
 {
 	struct usb_idmouse *dev;
 
-	/* prevent a race condition with open() */
-	mutex_lock(&disconnect_mutex);
-
 	dev = file->private_data;
 
-	if (dev == NULL) {
-		mutex_unlock(&disconnect_mutex);
+	if (dev == NULL)
 		return -ENODEV;
-	}
 
 	/* lock our device */
 	down(&dev->sem);
@@ -281,7 +264,6 @@
 	/* are we really open? */
 	if (dev->open <= 0) {
 		up(&dev->sem);
-		mutex_unlock(&disconnect_mutex);
 		return -ENODEV;
 	}
 
@@ -291,12 +273,9 @@
 		/* the device was unplugged before the file was released */
 		up(&dev->sem);
 		idmouse_delete(dev);
-		mutex_unlock(&disconnect_mutex);
-		return 0;
+	} else {
+		up(&dev->sem);
 	}
-
-	up(&dev->sem);
-	mutex_unlock(&disconnect_mutex);
 	return 0;
 }
 
@@ -391,30 +370,27 @@
 {
 	struct usb_idmouse *dev;
 
-	/* prevent races with open() */
-	mutex_lock(&disconnect_mutex);
-
 	/* get device structure */
 	dev = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 
-	/* lock it */
-	down(&dev->sem);
-
 	/* give back our minor */
 	usb_deregister_dev(interface, &idmouse_class);
 
+	/* lock it */
+	down(&dev->sem);
+
 	/* prevent device read, write and ioctl */
 	dev->present = 0;
 
-	/* unlock */
-	up(&dev->sem);
-
 	/* if the device is opened, idmouse_release will clean this up */
-	if (!dev->open)
+	if (!dev->open) {
+		up(&dev->sem);
 		idmouse_delete(dev);
-
-	mutex_unlock(&disconnect_mutex);
+	} else {
+		/* unlock */
+		up(&dev->sem);
+	}
 
 	info("%s disconnected", DRIVER_DESC);
 }
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index fc51207..28548d1 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -100,8 +100,6 @@
 /*--------------*/
 /*    globals   */
 /*--------------*/
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX(disconnect_sem);
 
 /*
  *  USB spec identifies 5 second timeouts.
@@ -495,8 +493,8 @@
 
 	/* verify that the device wasn't unplugged */
 	if (!dev->present) {
-		mutex_unlock(&dev->mutex);
-		return -ENODEV;
+		retval = -ENODEV;
+		goto error_out;
 	}
 
 	dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd,
@@ -579,9 +577,10 @@
 		retval = -ENOTTY;
 		break;
 	}
-
+error_out:
 	/* unlock the device */
 	mutex_unlock(&dev->mutex);
+	kfree(buffer);
 	return retval;
 }
 
@@ -599,22 +598,18 @@
 
 	subminor = iminor(inode);
 
-	/* prevent disconnects */
-	down(&disconnect_sem);
-
 	interface = usb_find_interface(&iowarrior_driver, subminor);
 	if (!interface) {
 		err("%s - error, can't find device for minor %d", __FUNCTION__,
 		    subminor);
-		retval = -ENODEV;
-		goto out;
+		return -ENODEV;
 	}
 
 	dev = usb_get_intfdata(interface);
-	if (!dev) {
-		retval = -ENODEV;
-		goto out;
-	}
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->mutex);
 
 	/* Only one process can open each device, no sharing. */
 	if (dev->opened) {
@@ -635,7 +630,7 @@
 	retval = 0;
 
 out:
-	up(&disconnect_sem);
+	mutex_unlock(&dev->mutex);
 	return retval;
 }
 
@@ -867,19 +862,16 @@
 	struct iowarrior *dev;
 	int minor;
 
-	/* prevent races with open() */
-	down(&disconnect_sem);
-
 	dev = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 
-	mutex_lock(&dev->mutex);
-
 	minor = dev->minor;
 
 	/* give back our minor */
 	usb_deregister_dev(interface, &iowarrior_class);
 
+	mutex_lock(&dev->mutex);
+
 	/* prevent device read, write and ioctl */
 	dev->present = 0;
 
@@ -897,7 +889,6 @@
 		/* no process is using the device, cleanup now */
 		iowarrior_delete(dev);
 	}
-	up(&disconnect_sem);
 
 	dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
 		 minor - IOWARRIOR_MINOR_BASE);
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 11555bde..5e950b9 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -165,6 +165,8 @@
 	size_t			interrupt_in_endpoint_size;
 	int			interrupt_in_running;
 	int			interrupt_in_done;
+	int			buffer_overflow;
+	spinlock_t		rbsl;
 
 	char*			interrupt_out_buffer;
 	struct usb_endpoint_descriptor* interrupt_out_endpoint;
@@ -174,9 +176,6 @@
 	int			interrupt_out_busy;
 };
 
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
 static struct usb_driver ld_usb_driver;
 
 /**
@@ -230,10 +229,12 @@
 		} else {
 			dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
 				 __FUNCTION__, urb->status);
+			spin_lock(&dev->rbsl);
 			goto resubmit; /* maybe we can recover */
 		}
 	}
 
+	spin_lock(&dev->rbsl);
 	if (urb->actual_length > 0) {
 		next_ring_head = (dev->ring_head+1) % ring_buffer_size;
 		if (next_ring_head != dev->ring_tail) {
@@ -244,21 +245,25 @@
 			dev->ring_head = next_ring_head;
 			dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
 				 __FUNCTION__, urb->actual_length);
-		} else
+		} else {
 			dev_warn(&dev->intf->dev,
 				 "Ring buffer overflow, %d bytes dropped\n",
 				 urb->actual_length);
+			dev->buffer_overflow = 1;
+		}
 	}
 
 resubmit:
 	/* resubmit if we're still running */
-	if (dev->interrupt_in_running && dev->intf) {
+	if (dev->interrupt_in_running && !dev->buffer_overflow && dev->intf) {
 		retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
-		if (retval)
+		if (retval) {
 			dev_err(&dev->intf->dev,
 				"usb_submit_urb failed (%d)\n", retval);
+			dev->buffer_overflow = 1;
+		}
 	}
-
+	spin_unlock(&dev->rbsl);
 exit:
 	dev->interrupt_in_done = 1;
 	wake_up_interruptible(&dev->read_wait);
@@ -290,35 +295,28 @@
 {
 	struct ld_usb *dev;
 	int subminor;
-	int retval = 0;
+	int retval;
 	struct usb_interface *interface;
 
 	nonseekable_open(inode, file);
 	subminor = iminor(inode);
 
-	mutex_lock(&disconnect_mutex);
-
 	interface = usb_find_interface(&ld_usb_driver, subminor);
 
 	if (!interface) {
 		err("%s - error, can't find device for minor %d\n",
 		     __FUNCTION__, subminor);
-		retval = -ENODEV;
-		goto unlock_disconnect_exit;
+		return -ENODEV;
 	}
 
 	dev = usb_get_intfdata(interface);
 
-	if (!dev) {
-		retval = -ENODEV;
-		goto unlock_disconnect_exit;
-	}
+	if (!dev)
+		return -ENODEV;
 
 	/* lock this device */
-	if (down_interruptible(&dev->sem)) {
-		retval = -ERESTARTSYS;
-		goto unlock_disconnect_exit;
-	}
+	if (down_interruptible(&dev->sem))
+		return -ERESTARTSYS;
 
 	/* allow opening only once */
 	if (dev->open_count) {
@@ -330,6 +328,7 @@
 	/* initialize in direction */
 	dev->ring_head = 0;
 	dev->ring_tail = 0;
+	dev->buffer_overflow = 0;
 	usb_fill_int_urb(dev->interrupt_in_urb,
 			 interface_to_usbdev(interface),
 			 usb_rcvintpipe(interface_to_usbdev(interface),
@@ -357,9 +356,6 @@
 unlock_exit:
 	up(&dev->sem);
 
-unlock_disconnect_exit:
-	mutex_unlock(&disconnect_mutex);
-
 	return retval;
 }
 
@@ -439,6 +435,7 @@
 	size_t *actual_buffer;
 	size_t bytes_to_read;
 	int retval = 0;
+	int rv;
 
 	dev = file->private_data;
 
@@ -460,7 +457,10 @@
 	}
 
 	/* wait for data */
+	spin_lock_irq(&dev->rbsl);
 	if (dev->ring_head == dev->ring_tail) {
+		dev->interrupt_in_done = 0;
+		spin_unlock_irq(&dev->rbsl);
 		if (file->f_flags & O_NONBLOCK) {
 			retval = -EAGAIN;
 			goto unlock_exit;
@@ -468,6 +468,8 @@
 		retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
 		if (retval < 0)
 			goto unlock_exit;
+	} else {
+		spin_unlock_irq(&dev->rbsl);
 	}
 
 	/* actual_buffer contains actual_length + interrupt_in_buffer */
@@ -486,6 +488,17 @@
 
 	retval = bytes_to_read;
 
+	spin_lock_irq(&dev->rbsl);
+	if (dev->buffer_overflow) {
+		dev->buffer_overflow = 0;
+		spin_unlock_irq(&dev->rbsl);
+		rv = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+		if (rv < 0)
+			dev->buffer_overflow = 1;
+	} else {
+		spin_unlock_irq(&dev->rbsl);
+	}
+
 unlock_exit:
 	/* unlock the device */
 	up(&dev->sem);
@@ -635,6 +648,7 @@
 		goto exit;
 	}
 	init_MUTEX(&dev->sem);
+	spin_lock_init(&dev->rbsl);
 	dev->intf = intf;
 	init_waitqueue_head(&dev->read_wait);
 	init_waitqueue_head(&dev->write_wait);
@@ -739,18 +753,16 @@
 	struct ld_usb *dev;
 	int minor;
 
-	mutex_lock(&disconnect_mutex);
-
 	dev = usb_get_intfdata(intf);
 	usb_set_intfdata(intf, NULL);
 
-	down(&dev->sem);
-
 	minor = intf->minor;
 
 	/* give back our minor */
 	usb_deregister_dev(intf, &ld_usb_class);
 
+	down(&dev->sem);
+
 	/* if the device is not opened, then we clean up right now */
 	if (!dev->open_count) {
 		up(&dev->sem);
@@ -760,8 +772,6 @@
 		up(&dev->sem);
 	}
 
-	mutex_unlock(&disconnect_mutex);
-
 	dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
 		 (minor - USB_LD_MINOR_BASE));
 }
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 1713e19..2ed0dae 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -254,9 +254,6 @@
 static void tower_disconnect	(struct usb_interface *interface);
 
 
-/* prevent races between open() and disconnect */
-static DEFINE_MUTEX (disconnect_mutex);
-
 /* file operations needed when we register this driver */
 static const struct file_operations tower_fops = {
 	.owner =	THIS_MODULE,
@@ -344,28 +341,26 @@
 	nonseekable_open(inode, file);
 	subminor = iminor(inode);
 
-	mutex_lock (&disconnect_mutex);
-
 	interface = usb_find_interface (&tower_driver, subminor);
 
 	if (!interface) {
 		err ("%s - error, can't find device for minor %d",
 		     __FUNCTION__, subminor);
 		retval = -ENODEV;
-		goto unlock_disconnect_exit;
+		goto exit;
 	}
 
 	dev = usb_get_intfdata(interface);
 
 	if (!dev) {
 		retval = -ENODEV;
-		goto unlock_disconnect_exit;
+		goto exit;
 	}
 
 	/* lock this device */
 	if (down_interruptible (&dev->sem)) {
 	        retval = -ERESTARTSYS;
-		goto unlock_disconnect_exit;
+		goto exit;
 	}
 
 	/* allow opening only once */
@@ -421,9 +416,7 @@
 unlock_exit:
 	up (&dev->sem);
 
-unlock_disconnect_exit:
-	mutex_unlock (&disconnect_mutex);
-
+exit:
 	dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
 
 	return retval;
@@ -993,19 +986,16 @@
 
 	dbg(2, "%s: enter", __FUNCTION__);
 
-	mutex_lock (&disconnect_mutex);
-
 	dev = usb_get_intfdata (interface);
 	usb_set_intfdata (interface, NULL);
 
-
-	down (&dev->sem);
-
 	minor = dev->minor;
 
 	/* give back our minor */
 	usb_deregister_dev (interface, &tower_class);
 
+	down (&dev->sem);
+
 	/* if the device is not opened, then we clean up right now */
 	if (!dev->open_count) {
 		up (&dev->sem);
@@ -1015,8 +1005,6 @@
 		up (&dev->sem);
 	}
 
-	mutex_unlock (&disconnect_mutex);
-
 	info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
 
 	dbg(2, "%s: leave", __FUNCTION__);
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 6f8b134..9f37ba4 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -72,8 +72,6 @@
 
 static struct usb_driver sisusb_driver;
 
-DEFINE_MUTEX(disconnect_mutex);
-
 static void
 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
 {
@@ -2511,31 +2509,24 @@
 	struct usb_interface *interface;
 	int subminor = iminor(inode);
 
-	mutex_lock(&disconnect_mutex);
-
 	if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
 		printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
 				subminor);
-		mutex_unlock(&disconnect_mutex);
 		return -ENODEV;
 	}
 
-	if (!(sisusb = usb_get_intfdata(interface))) {
-		mutex_unlock(&disconnect_mutex);
+	if (!(sisusb = usb_get_intfdata(interface)))
 		return -ENODEV;
-	}
 
 	mutex_lock(&sisusb->lock);
 
 	if (!sisusb->present || !sisusb->ready) {
 		mutex_unlock(&sisusb->lock);
-		mutex_unlock(&disconnect_mutex);
 		return -ENODEV;
 	}
 
 	if (sisusb->isopen) {
 		mutex_unlock(&sisusb->lock);
-		mutex_unlock(&disconnect_mutex);
 		return -EBUSY;
 	}
 
@@ -2543,7 +2534,6 @@
 		if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
 			if (sisusb_init_gfxdevice(sisusb, 0)) {
 				mutex_unlock(&sisusb->lock);
-				mutex_unlock(&disconnect_mutex);
 				printk(KERN_ERR
 					"sisusbvga[%d]: Failed to initialize "
 					"device\n",
@@ -2552,7 +2542,6 @@
 			}
 		} else {
 			mutex_unlock(&sisusb->lock);
-			mutex_unlock(&disconnect_mutex);
 			printk(KERN_ERR
 				"sisusbvga[%d]: Device not attached to "
 				"USB 2.0 hub\n",
@@ -2570,8 +2559,6 @@
 
 	mutex_unlock(&sisusb->lock);
 
-	mutex_unlock(&disconnect_mutex);
-
 	return 0;
 }
 
@@ -2601,12 +2588,8 @@
 	struct sisusb_usb_data *sisusb;
 	int myminor;
 
-	mutex_lock(&disconnect_mutex);
-
-	if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
-		mutex_unlock(&disconnect_mutex);
+	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
 		return -ENODEV;
-	}
 
 	mutex_lock(&sisusb->lock);
 
@@ -2626,8 +2609,6 @@
 	/* decrement the usage count on our device */
 	kref_put(&sisusb->kref, sisusb_delete);
 
-	mutex_unlock(&disconnect_mutex);
-
 	return 0;
 }
 
@@ -3383,12 +3364,9 @@
 	sisusb_console_exit(sisusb);
 #endif
 
-	/* The above code doesn't need the disconnect
-	 * semaphore to be down; its meaning is to
-	 * protect all other routines from the disconnect
-	 * case, not the other way round.
-	 */
-	mutex_lock(&disconnect_mutex);
+	minor = sisusb->minor;
+
+	usb_deregister_dev(intf, &usb_sisusb_class);
 
 	mutex_lock(&sisusb->lock);
 
@@ -3396,12 +3374,8 @@
 	if (!sisusb_wait_all_out_complete(sisusb))
 		sisusb_kill_all_busy(sisusb);
 
-	minor = sisusb->minor;
-
 	usb_set_intfdata(intf, NULL);
 
-	usb_deregister_dev(intf, &usb_sisusb_class);
-
 #ifdef SISUSB_OLD_CONFIG_COMPAT
 	if (sisusb->ioctl32registered) {
 		int ret;
@@ -3426,8 +3400,6 @@
 	/* decrement our usage count */
 	kref_put(&sisusb->kref, sisusb_delete);
 
-	mutex_unlock(&disconnect_mutex);
-
 	printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
 }
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index 5947afb..8d0edc8 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -214,18 +214,13 @@
 	 * are set up/restored.
 	 */
 
-	mutex_lock(&disconnect_mutex);
-
-	if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
-		mutex_unlock(&disconnect_mutex);
+	if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
 		return;
-	}
 
 	mutex_lock(&sisusb->lock);
 
 	if (!sisusb_sisusb_valid(sisusb)) {
 		mutex_unlock(&sisusb->lock);
-		mutex_unlock(&disconnect_mutex);
 		return;
 	}
 
@@ -264,8 +259,6 @@
 
 	mutex_unlock(&sisusb->lock);
 
-	mutex_unlock(&disconnect_mutex);
-
 	if (init) {
 		c->vc_cols = cols;
 		c->vc_rows = rows;
@@ -284,12 +277,8 @@
 	 * and others, ie not under our control.
 	 */
 
-	mutex_lock(&disconnect_mutex);
-
-	if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
-		mutex_unlock(&disconnect_mutex);
+	if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
 		return;
-	}
 
 	mutex_lock(&sisusb->lock);
 
@@ -314,8 +303,6 @@
 
 	/* decrement the usage count on our sisusb */
 	kref_put(&sisusb->kref, sisusb_delete);
-
-	mutex_unlock(&disconnect_mutex);
 }
 
 /* interface routine */
@@ -1490,14 +1477,11 @@
 {
 	int i, ret, minor = sisusb->minor;
 
-	mutex_lock(&disconnect_mutex);
-
 	mutex_lock(&sisusb->lock);
 
 	/* Erm.. that should not happen */
 	if (sisusb->haveconsole || !sisusb->SiS_Pr) {
 		mutex_unlock(&sisusb->lock);
-		mutex_unlock(&disconnect_mutex);
 		return 1;
 	}
 
@@ -1508,14 +1492,12 @@
 	    first > MAX_NR_CONSOLES ||
 	    last > MAX_NR_CONSOLES) {
 		mutex_unlock(&sisusb->lock);
-		mutex_unlock(&disconnect_mutex);
 		return 1;
 	}
 
 	/* If gfxcore not initialized or no consoles given, quit graciously */
 	if (!sisusb->gfxinit || first < 1 || last < 1) {
 		mutex_unlock(&sisusb->lock);
-		mutex_unlock(&disconnect_mutex);
 		return 0;
 	}
 
@@ -1526,7 +1508,6 @@
 	/* Set up text mode (and upload  default font) */
 	if (sisusb_reset_text_mode(sisusb, 1)) {
 		mutex_unlock(&sisusb->lock);
-		mutex_unlock(&disconnect_mutex);
 		printk(KERN_ERR
 			"sisusbvga[%d]: Failed to set up text mode\n",
 			minor);
@@ -1550,7 +1531,6 @@
 	/* Allocate screen buffer */
 	if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
 		mutex_unlock(&sisusb->lock);
-		mutex_unlock(&disconnect_mutex);
 		printk(KERN_ERR
 			"sisusbvga[%d]: Failed to allocate screen buffer\n",
 			minor);
@@ -1558,7 +1538,6 @@
 	}
 
 	mutex_unlock(&sisusb->lock);
-	mutex_unlock(&disconnect_mutex);
 
 	/* Now grab the desired console(s) */
 	ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
index f05f832..864bc0e 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_init.h
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -808,8 +808,6 @@
 	{ 0x2b,0xc2, 35}  /* 0x71 768@576@60 */
 };
 
-extern struct mutex disconnect_mutex;
-
 int		SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 int		SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
 
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 887ef95..504f722 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -42,12 +42,16 @@
 	size_t			bulk_in_size;		/* the size of the receive buffer */
 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
 	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
-	struct kref             kref;
+	struct kref		kref;
+	struct semaphore	limit_sem;		/* to stop writes at full throttle from
+							 * using up all RAM */
+	struct usb_anchor	submitted;		/* URBs to wait for before suspend */
 };
 #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
 
+#define USB_LCD_CONCURRENT_WRITES	5
+
 static struct usb_driver lcd_driver;
-static DEFINE_MUTEX(usb_lcd_open_mutex);
 
 
 static void lcd_delete(struct kref *kref)
@@ -64,35 +68,35 @@
 {
 	struct usb_lcd *dev;
 	struct usb_interface *interface;
-	int subminor;
-	int retval = 0;
+	int subminor, r;
 
 	subminor = iminor(inode);
 
-	mutex_lock(&usb_lcd_open_mutex);
 	interface = usb_find_interface(&lcd_driver, subminor);
 	if (!interface) {
 		err ("USBLCD: %s - error, can't find device for minor %d",
 		     __FUNCTION__, subminor);
-		retval = -ENODEV;
-		goto exit;
+		return -ENODEV;
 	}
 
 	dev = usb_get_intfdata(interface);
-	if (!dev) {
-		retval = -ENODEV;
-		goto exit;
-	}
+	if (!dev)
+		return -ENODEV;
 
 	/* increment our usage count for the device */
 	kref_get(&dev->kref);
 
+	/* grab a power reference */
+	r = usb_autopm_get_interface(interface);
+	if (r < 0) {
+		kref_put(&dev->kref, lcd_delete);
+		return r;
+	}
+
 	/* save our object in the file's private structure */
 	file->private_data = dev;
 
-exit:
-	mutex_unlock(&usb_lcd_open_mutex);
-	return retval;
+	return 0;
 }
 
 static int lcd_release(struct inode *inode, struct file *file)
@@ -104,6 +108,7 @@
 		return -ENODEV;
 
 	/* decrement the count on our device */
+	usb_autopm_put_interface(dev->interface);
 	kref_put(&dev->kref, lcd_delete);
 	return 0;
 }
@@ -186,12 +191,13 @@
 	/* free up our allocated buffer */
 	usb_buffer_free(urb->dev, urb->transfer_buffer_length,
 			urb->transfer_buffer, urb->transfer_dma);
+	up(&dev->limit_sem);
 }
 
 static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos)
 {
 	struct usb_lcd *dev;
-        int retval = 0;
+        int retval = 0, r;
 	struct urb *urb = NULL;
 	char *buf = NULL;
 	
@@ -201,10 +207,16 @@
 	if (count == 0)
 		goto exit;
 
+	r = down_interruptible(&dev->limit_sem);
+	if (r < 0)
+		return -EINTR;
+
 	/* create a urb, and a buffer for it, and copy the data to the urb */
 	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb)
-		return -ENOMEM;
+	if (!urb) {
+		retval = -ENOMEM;
+		goto err_no_buf;
+	}
 	
 	buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
 	if (!buf) {
@@ -222,12 +234,14 @@
 			  usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
 			  buf, count, lcd_write_bulk_callback, dev);
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	usb_anchor_urb(urb, &dev->submitted);
 	
 	/* send the data out the bulk port */
 	retval = usb_submit_urb(urb, GFP_KERNEL);
 	if (retval) {
 		err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
-		goto error;
+		goto error_unanchor;
 	}
 	
 	/* release our reference to this urb, the USB core will eventually free it entirely */
@@ -235,10 +249,13 @@
 
 exit:
 	return count;
-
+error_unanchor:
+	usb_unanchor_urb(urb);
 error:
 	usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
 	usb_free_urb(urb);
+err_no_buf:
+	up(&dev->limit_sem);
 	return retval;
 }
 
@@ -277,6 +294,8 @@
 		goto error;
 	}
 	kref_init(&dev->kref);
+	sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES);
+	init_usb_anchor(&dev->submitted);
 
 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
@@ -344,22 +363,41 @@
 	return retval;
 }
 
+static void lcd_draw_down(struct usb_lcd *dev)
+{
+	int time;
+
+	time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+	if (!time)
+		usb_kill_anchored_urbs(&dev->submitted);
+}
+
+static int lcd_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usb_lcd *dev = usb_get_intfdata(intf);
+
+	if (!dev)
+		return 0;
+	lcd_draw_down(dev);
+	return 0;
+}
+
+static int lcd_resume (struct usb_interface *intf)
+{
+	return 0;
+}
+
 static void lcd_disconnect(struct usb_interface *interface)
 {
 	struct usb_lcd *dev;
         int minor = interface->minor;
 
-        /* prevent skel_open() from racing skel_disconnect() */
-        mutex_lock(&usb_lcd_open_mutex);
-
         dev = usb_get_intfdata(interface);
         usb_set_intfdata(interface, NULL);
 
         /* give back our minor */
         usb_deregister_dev(interface, &lcd_class);
  
-	mutex_unlock(&usb_lcd_open_mutex);
-
 	/* decrement our usage count */
 	kref_put(&dev->kref, lcd_delete);
 
@@ -370,7 +408,10 @@
 	.name =		"usblcd",
 	.probe =	lcd_probe,
 	.disconnect =	lcd_disconnect,
+	.suspend =	lcd_suspend,
+	.resume =	lcd_resume,
 	.id_table =	id_table,
+	.supports_autosuspend = 1,
 };
 
 static int __init usb_lcd_init(void)
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 7025025..1a60f9c 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -336,7 +336,7 @@
 	memcpy(priv->reg, buffer, 4);
 	/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
 	if (priv->reg[2] & priv->reg[1] & 0x10)
-		parport_generic_irq(0, pp, NULL);
+		parport_generic_irq(0, pp);
 	return 1;
 }
 #endif
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 0af11a6..c03dfd7 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -4,7 +4,7 @@
  * This is a binary format reader.
  *
  * Copyright (C) 2006 Paolo Abeni (paolo.abeni@email.it)
- * Copyright (C) 2006 Pete Zaitcev (zaitcev@redhat.com)
+ * Copyright (C) 2006,2007 Pete Zaitcev (zaitcev@redhat.com)
  */
 
 #include <linux/kernel.h>
@@ -172,6 +172,7 @@
 
 #define MON_RING_EMPTY(rp)	((rp)->b_cnt == 0)
 
+static struct class *mon_bin_class;
 static dev_t mon_bin_dev0;
 static struct cdev mon_bin_cdev;
 
@@ -1144,10 +1145,38 @@
 		free_page((unsigned long) map[n].ptr);
 }
 
+int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
+{
+	struct device *dev;
+	unsigned minor = ubus? ubus->busnum: 0;
+
+	if (minor >= MON_BIN_MAX_MINOR)
+		return 0;
+
+	dev = device_create(mon_bin_class, ubus? ubus->controller: NULL,
+			MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor);
+	if (IS_ERR(dev))
+		return 0;
+
+	mbus->classdev = dev;
+	return 1;
+}
+
+void mon_bin_del(struct mon_bus *mbus)
+{
+	device_destroy(mon_bin_class, mbus->classdev->devt);
+}
+
 int __init mon_bin_init(void)
 {
 	int rc;
 
+	mon_bin_class = class_create(THIS_MODULE, "usbmon");
+	if (IS_ERR(mon_bin_class)) {
+		rc = PTR_ERR(mon_bin_class);
+		goto err_class;
+	}
+
 	rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon");
 	if (rc < 0)
 		goto err_dev;
@@ -1164,6 +1193,8 @@
 err_add:
 	unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
 err_dev:
+	class_destroy(mon_bin_class);
+err_class:
 	return rc;
 }
 
@@ -1171,4 +1202,5 @@
 {
 	cdev_del(&mon_bin_cdev);
 	unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
+	class_destroy(mon_bin_class);
 }
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 8977ec0..ce61d8b 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -220,6 +220,8 @@
 	list_del(&mbus->bus_link);
 	if (mbus->text_inited)
 		mon_text_del(mbus);
+	if (mbus->bin_inited)
+		mon_bin_del(mbus);
 
 	mon_dissolve(mbus, ubus);
 	kref_put(&mbus->ref, mon_bus_drop);
@@ -301,8 +303,8 @@
 	mbus->u_bus = ubus;
 	ubus->mon_bus = mbus;
 
-	mbus->text_inited = mon_text_add(mbus, ubus->busnum);
-	// mon_bin_add(...)
+	mbus->text_inited = mon_text_add(mbus, ubus);
+	mbus->bin_inited = mon_bin_add(mbus, ubus);
 
 	mutex_lock(&mon_lock);
 	list_add_tail(&mbus->bus_link, &mon_buses);
@@ -321,8 +323,8 @@
 	spin_lock_init(&mbus->lock);
 	INIT_LIST_HEAD(&mbus->r_list);
 
-	mbus->text_inited = mon_text_add(mbus, 0);
-	// mbus->bin_inited = mon_bin_add(mbus, 0);
+	mbus->text_inited = mon_text_add(mbus, NULL);
+	mbus->bin_inited = mon_bin_add(mbus, NULL);
 }
 
 /*
@@ -403,6 +405,8 @@
 
 		if (mbus->text_inited)
 			mon_text_del(mbus);
+		if (mbus->bin_inited)
+			mon_bin_del(mbus);
 
 		/*
 		 * This never happens, because the open/close paths in
@@ -423,6 +427,8 @@
 	mbus = &mon_bus0;
 	if (mbus->text_inited)
 		mon_text_del(mbus);
+	if (mbus->bin_inited)
+		mon_bin_del(mbus);
 
 	mutex_unlock(&mon_lock);
 
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index ec0cc51..982b773 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -655,20 +655,24 @@
 	.release =	mon_text_release,
 };
 
-int mon_text_add(struct mon_bus *mbus, int busnum)
+int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
 {
 	struct dentry *d;
 	enum { NAMESZ = 10 };
 	char name[NAMESZ];
+	int busnum = ubus? ubus->busnum: 0;
 	int rc;
 
-	rc = snprintf(name, NAMESZ, "%dt", busnum);
-	if (rc <= 0 || rc >= NAMESZ)
-		goto err_print_t;
-	d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_t);
-	if (d == NULL)
-		goto err_create_t;
-	mbus->dent_t = d;
+	if (ubus != NULL) {
+		rc = snprintf(name, NAMESZ, "%dt", busnum);
+		if (rc <= 0 || rc >= NAMESZ)
+			goto err_print_t;
+		d = debugfs_create_file(name, 0600, mon_dir, mbus,
+							     &mon_fops_text_t);
+		if (d == NULL)
+			goto err_create_t;
+		mbus->dent_t = d;
+	}
 
 	rc = snprintf(name, NAMESZ, "%du", busnum);
 	if (rc <= 0 || rc >= NAMESZ)
@@ -694,8 +698,10 @@
 	mbus->dent_u = NULL;
 err_create_u:
 err_print_u:
-	debugfs_remove(mbus->dent_t);
-	mbus->dent_t = NULL;
+	if (ubus != NULL) {
+		debugfs_remove(mbus->dent_t);
+		mbus->dent_t = NULL;
+	}
 err_create_t:
 err_print_t:
 	return 0;
@@ -704,7 +710,8 @@
 void mon_text_del(struct mon_bus *mbus)
 {
 	debugfs_remove(mbus->dent_u);
-	debugfs_remove(mbus->dent_t);
+	if (mbus->dent_t != NULL)
+		debugfs_remove(mbus->dent_t);
 	debugfs_remove(mbus->dent_s);
 }
 
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index 13d6325..f68ad6d 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -20,9 +20,11 @@
 	struct usb_bus *u_bus;
 
 	int text_inited;
+	int bin_inited;
 	struct dentry *dent_s;		/* Debugging file */
 	struct dentry *dent_t;		/* Text interface file */
 	struct dentry *dent_u;		/* Second text interface file */
+	struct device *classdev;	/* Device in usbmon class */
 
 	/* Ref */
 	int nreaders;			/* Under mon_lock AND mbus->lock */
@@ -52,9 +54,10 @@
 
 struct mon_bus *mon_bus_lookup(unsigned int num);
 
-int /*bool*/ mon_text_add(struct mon_bus *mbus, int busnum);
+int /*bool*/ mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus);
 void mon_text_del(struct mon_bus *mbus);
-// void mon_bin_add(struct mon_bus *);
+int /*bool*/ mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus);
+void mon_bin_del(struct mon_bus *mbus);
 
 int __init mon_text_init(void);
 void mon_text_exit(void);
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 3efe670..43d6db6 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -464,6 +464,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called pl2303.
 
+config USB_SERIAL_OTI6858
+	tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller (EXPERIMENTAL)"
+	depends on USB_SERIAL
+	help
+	  Say Y here if you want to use the OTi-6858 single port USB to serial
+          converter device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called oti6858.
+
 config USB_SERIAL_HP4X
         tristate "USB HP4x Calculators support"
         depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 61166ad..07a976e 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -40,6 +40,7 @@
 obj-$(CONFIG_USB_SERIAL_NAVMAN)			+= navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)		+= omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTION)			+= option.o
+obj-$(CONFIG_USB_SERIAL_OTI6858)		+= oti6858.o
 obj-$(CONFIG_USB_SERIAL_PL2303)			+= pl2303.o
 obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
 obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)		+= sierra.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index fbc8c27..1cd29cd 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -411,12 +411,13 @@
 static void aircable_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
+	int status = urb->status;
 	int result;
 
-	dbg("%s - urb->status: %d", __FUNCTION__ , urb->status);
+	dbg("%s - urb status: %d", __FUNCTION__ , status);
 
 	/* This has been taken from cypress_m8.c cypress_write_int_callback */
-	switch (urb->status) {
+	switch (status) {
 		case 0:
 			/* success */
 			break;
@@ -425,14 +426,14 @@
 		case -ESHUTDOWN:
 			/* this urb is terminated, clean up */
 			dbg("%s - urb shutting down with status: %d",
-			    __FUNCTION__, urb->status);
+			    __FUNCTION__, status);
 			port->write_urb_busy = 0;
 			return;
 		default:
 			/* error in the urb, so we have to resubmit it */
 			dbg("%s - Overflow in write", __FUNCTION__);
 			dbg("%s - nonzero write bulk status received: %d",
-			    __FUNCTION__, urb->status);
+			    __FUNCTION__, status);
 			port->write_urb->transfer_buffer_length = 1;
 			port->write_urb->dev = port->serial->dev;
 			result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
@@ -457,16 +458,17 @@
 	unsigned long no_packages, remaining, package_length, i;
 	int result, shift = 0;
 	unsigned char *temp;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - urb status = %d", __FUNCTION__, status);
 		if (!port->open_count) {
 			dbg("%s - port is closed, exiting.", __FUNCTION__);
 			return;
 		}
-		if (urb->status == -EPROTO) {
+		if (status == -EPROTO) {
 			dbg("%s - caught -EPROTO, resubmitting the urb",
 			    __FUNCTION__);
 			usb_fill_bulk_urb(port->read_urb, port->serial->dev,
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 39a4983..cff6fd1 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -82,12 +82,13 @@
 	unsigned char *data = urb->transfer_buffer;
 	struct tty_struct *tty;
 	int result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
+	if (status) {
 		dbg("%s - nonzero read bulk status received: %d",
-		    __FUNCTION__, urb->status);
+		    __FUNCTION__, status);
 		return;
 	}
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -109,6 +110,7 @@
 {
 	struct usb_serial_port *port = urb->context;
 	struct airprime_private *priv = usb_get_serial_port_data(port);
+	int status = urb->status;
 	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -116,9 +118,9 @@
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree (urb->transfer_buffer);
 
-	if (urb->status)
+	if (status)
 		dbg("%s - nonzero write bulk status received: %d",
-		    __FUNCTION__, urb->status);
+		    __FUNCTION__, status);
 	spin_lock_irqsave(&priv->lock, flags);
 	--priv->outstanding_urbs;
 	spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index ea2175b..c9fd486 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -63,7 +63,8 @@
 				 request, requesttype, value, index,
 				 buf, 0x0000001, 1000);
 	if (result)
-		dbg("%03d < %d bytes [0x%02X]", seq, result, buf[0]);
+		dbg("%03d < %d bytes [0x%02X]", seq, result,
+		    ((unsigned char *)buf)[0]);
 	else
 		dbg("%03d < 0 bytes", seq);
 }
@@ -171,7 +172,7 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if ((!port->tty) || (!port->tty->termios)) {
+	if (!port->tty || !port->tty->termios) {
 		dbg("%s - no tty structures", __FUNCTION__);
 		return;
 	}
@@ -187,16 +188,6 @@
 
 	cflag = port->tty->termios->c_cflag;
 
-	/* check that they really want us to change something: */
-	if (old_termios) {
-		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
-		     RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg("%s - nothing to change...", __FUNCTION__);
-			return;
-		}
-	}
-
 	buf = kmalloc(1, GFP_KERNEL);
 	if (!buf) {
 		dbg("error kmalloc");
@@ -219,7 +210,7 @@
 			dbg("setting CS7");
 			break;
 		default:
-			err("CSIZE was set but not CS5-CS8, using CS8!");
+			dbg("CSIZE was set but not CS5-CS8, using CS8!");
 			/* fall through */
 		case CS8:
 			config |= 0x03;
@@ -250,38 +241,33 @@
 	}
 
 	/* set baudrate */
-	baud = 0;
-	switch (cflag & CBAUD) {
-		case B0:
-			err("can't set 0 baud, using 9600 instead");
-			break;
-		case B75:	baud = 75;	break;
-		case B150:	baud = 150;	break;
-		case B300:	baud = 300;	break;
-		case B600:	baud = 600;	break;
-		case B1200:	baud = 1200;	break;
-		case B1800:	baud = 1800;	break;
-		case B2400:	baud = 2400;	break;
-		case B4800:	baud = 4800;	break;
-		case B9600:	baud = 9600;	break;
-		case B19200:	baud = 19200;	break;
-		case B38400:	baud = 38400;	break;
-		case B57600:	baud = 57600;	break;
-		case B115200:	baud = 115200;	break;
-		case B230400:	baud = 230400;	break;
-		case B460800:	baud = 460800;	break;
-		default:
-			dbg("does not support the baudrate requested (fix it)");
-			break;
-	}
+	baud = tty_get_baud_rate(port->tty);
 
-	/* set 9600 as default (if given baudrate is invalid for example) */
-	if (baud == 0)
-		baud = 9600;
+	switch (baud) {
+		case 75:
+		case 150:
+		case 300:
+		case 600:
+		case 1200:
+		case 1800:
+		case 2400:
+		case 4800:
+		case 9600:
+		case 19200:
+		case 38400:
+		case 57600:
+		case 115200:
+		case 230400:
+		case 460800:
+			break;
+		/* set 9600 as default (if given baudrate is invalid for example) */
+		default:
+			baud = 9600;
+	}
 
 	/*
 	 * found by try'n'error, be careful, maybe there are other options
-	 * for multiplicator etc!
+	 * for multiplicator etc! (3.5 for example)
 	 */
 	if (baud == 460800)
 		/* strange, for 460800 the formula is wrong
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 3b800d2..e67ce25 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -255,9 +255,10 @@
 	struct belkin_sa_private *priv;
 	unsigned char *data = urb->transfer_buffer;
 	int retval;
+	int status = urb->status;
 	unsigned long flags;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -265,10 +266,12 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d",
+		    __FUNCTION__, status);
 		goto exit;
 	}
 
@@ -346,6 +349,7 @@
 	unsigned long flags;
 	unsigned long control_state;
 	int bad_flow_control;
+	speed_t baud;
 	
 	if ((!port->tty) || (!port->tty->termios)) {
 		dbg ("%s - no tty or termios structure", __FUNCTION__);
@@ -361,16 +365,8 @@
 	bad_flow_control = priv->bad_flow_control;
 	spin_unlock_irqrestore(&priv->lock, flags);
 	
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg("%s - nothing to change...", __FUNCTION__);
-			return;
-		}
-		old_iflag = old_termios->c_iflag;
-		old_cflag = old_termios->c_cflag;
-	}
+	old_iflag = old_termios->c_iflag;
+	old_cflag = old_termios->c_cflag;
 
 	/* Set the baud rate */
 	if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
@@ -384,38 +380,30 @@
 				if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
 					err("Set RTS error");
 		}
+	}
 
-		switch(cflag & CBAUD) {
-			case B0: /* handled below */ break;
-			case B300: urb_value = BELKIN_SA_BAUD(300); break;
-			case B600: urb_value = BELKIN_SA_BAUD(600); break;
-			case B1200: urb_value = BELKIN_SA_BAUD(1200); break;
-			case B2400: urb_value = BELKIN_SA_BAUD(2400); break;
-			case B4800: urb_value = BELKIN_SA_BAUD(4800); break;
-			case B9600: urb_value = BELKIN_SA_BAUD(9600); break;
-			case B19200: urb_value = BELKIN_SA_BAUD(19200); break;
-			case B38400: urb_value = BELKIN_SA_BAUD(38400); break;
-			case B57600: urb_value = BELKIN_SA_BAUD(57600); break;
-			case B115200: urb_value = BELKIN_SA_BAUD(115200); break;
-			case B230400: urb_value = BELKIN_SA_BAUD(230400); break;
-			default: err("BELKIN USB Serial Adapter: unsupported baudrate request, using default of 9600");
-				urb_value = BELKIN_SA_BAUD(9600); break;
-		}
-		if ((cflag & CBAUD) != B0 ) {
-			if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
-				err("Set baudrate error");
-		} else {
-			/* Disable flow control */
-			if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
-				err("Disable flowcontrol error");
+	baud = tty_get_baud_rate(port->tty);
+	urb_value = BELKIN_SA_BAUD(baud);
+	/* Clip to maximum speed */
+	if (urb_value == 0)
+		urb_value = 1;
+	/* Turn it back into a resulting real baud rate */
+	baud = BELKIN_SA_BAUD(urb_value);
+	/* FIXME: Once the tty updates are done then push this back to the tty */
 
-			/* Drop RTS and DTR */
-			control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-			if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
-				err("DTR LOW error");
-			if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
-				err("RTS LOW error");
-		}
+	if ((cflag & CBAUD) != B0 ) {
+		if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
+			err("Set baudrate error");
+	} else {
+		/* Disable flow control */
+		if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
+			err("Disable flowcontrol error");
+		/* Drop RTS and DTR */
+		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+		if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
+			err("DTR LOW error");
+		if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
+			err("RTS LOW error");
 	}
 
 	/* set the parity */
@@ -435,7 +423,7 @@
 			case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break;
 			case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break;
 			case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break;
-			default: err("CSIZE was not CS5-CS8, using default of 8");
+			default: dbg("CSIZE was not CS5-CS8, using default of 8");
 				urb_value = BELKIN_SA_DATA_BITS(8);
 				break;
 		}
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 4167753..4353df9 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -305,12 +305,13 @@
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
+	int status = urb->status;
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* the urb might have been killed. */
-	if (urb->status)
+	if (status)
 		return;
 
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -365,12 +366,14 @@
 	unsigned char *data = urb->transfer_buffer;
 	short todo;
 	int result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	
+
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -411,12 +414,14 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	port->write_urb_busy = 0;
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 57b8e27..1633863 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1275,10 +1275,11 @@
 	int bytes = 0;
 	int result;
 	int i = 0;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0: /* success */
 		break;
 	case -ECONNRESET:
@@ -1292,7 +1293,7 @@
 	default:
 		/* something ugly is going on... */
 		dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
-			__FUNCTION__,urb->status);
+			__FUNCTION__, status);
 		cypress_set_dead(port);
 		return;
 	}
@@ -1419,10 +1420,11 @@
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	int result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	
-	switch (urb->status) {
+
+	switch (status) {
 		case 0:
 			/* success */
 			break;
@@ -1430,7 +1432,8 @@
 		case -ENOENT:
 		case -ESHUTDOWN:
 			/* this urb is terminated, clean up */
-			dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+			dbg("%s - urb shutting down with status: %d",
+			    __FUNCTION__, status);
 			priv->write_urb_in_use = 0;
 			return;
 		case -EPIPE: /* no break needed; clear halt and resubmit */
@@ -1438,7 +1441,8 @@
 				break;
 			usb_clear_halt(port->serial->dev, 0x02);
 			/* error in the urb, so we have to resubmit it */
-			dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+			dbg("%s - nonzero write bulk status received: %d",
+			    __FUNCTION__, status);
 			port->interrupt_out_urb->transfer_buffer_length = 1;
 			port->interrupt_out_urb->dev = port->serial->dev;
 			result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
@@ -1450,7 +1454,7 @@
 			break;
 		default:
 			dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
-				__FUNCTION__,urb->status);
+				__FUNCTION__, status);
 			cypress_set_dead(port);
 			break;
 	}
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index d78692c..976f54e 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -416,9 +416,6 @@
 	int dp_port_num;
 	int dp_out_buf_len;
 	unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
-	int dp_in_buf_len;
-	unsigned char dp_in_buf[DIGI_IN_BUF_SIZE];
-	unsigned char dp_in_flag_buf[DIGI_IN_BUF_SIZE];
 	int dp_write_urb_in_use;
 	unsigned int dp_modem_signals;
 	wait_queue_head_t dp_modem_change_wait;
@@ -920,7 +917,6 @@
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	priv->dp_throttled = 1;
 	priv->dp_throttle_restart = 0;
-	priv->dp_in_buf_len = 0;
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
 }
@@ -930,23 +926,16 @@
 {
 
 	int ret = 0;
-	int len;
 	unsigned long flags;
 	struct digi_port *priv = usb_get_serial_port_data(port);
-	struct tty_struct *tty = port->tty;
-
 
 dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
 
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 
-	/* send any buffered chars from throttle time on to tty subsystem */
-
-	len = tty_buffer_request_room(tty, priv->dp_in_buf_len);
-	if( len > 0 ) {
-		tty_insert_flip_string_flags(tty, priv->dp_in_buf, priv->dp_in_flag_buf, len);
-		tty_flip_buffer_push( tty );
-	}
+	/* turn throttle off */
+	priv->dp_throttled = 0;
+	priv->dp_throttle_restart = 0;
 
 	/* restart read chain */
 	if( priv->dp_throttle_restart ) {
@@ -954,11 +943,6 @@
 		ret = usb_submit_urb( port->read_urb, GFP_ATOMIC );
 	}
 
-	/* turn throttle off */
-	priv->dp_throttled = 0;
-	priv->dp_in_buf_len = 0;
-	priv->dp_throttle_restart = 0;
-
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
 	if( ret ) {
@@ -1340,19 +1324,21 @@
 	struct digi_port *priv;
 	struct digi_serial *serial_priv;
 	int ret = 0;
+	int status = urb->status;
 
 
-dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
+	dbg("digi_write_bulk_callback: TOP, urb status=%d", status);
 
 	/* port and serial sanity check */
 	if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) {
-		err("%s: port or port->private is NULL, status=%d", __FUNCTION__,
-			urb->status );
+		err("%s: port or port->private is NULL, status=%d",
+		    __FUNCTION__, status);
 		return;
 	}
 	serial = port->serial;
 	if( serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL ) {
-		err("%s: serial or serial->private is NULL, status=%d", __FUNCTION__, urb->status );
+		err("%s: serial or serial->private is NULL, status=%d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -1687,7 +1673,6 @@
 		spin_lock_init( &priv->dp_port_lock );
 		priv->dp_port_num = i;
 		priv->dp_out_buf_len = 0;
-		priv->dp_in_buf_len = 0;
 		priv->dp_write_urb_in_use = 0;
 		priv->dp_modem_signals = 0;
 		init_waitqueue_head( &priv->dp_modem_change_wait );
@@ -1757,25 +1742,28 @@
 	struct digi_port *priv;
 	struct digi_serial *serial_priv;
 	int ret;
+	int status = urb->status;
 
 
 dbg( "digi_read_bulk_callback: TOP" );
 
 	/* port sanity check, do not resubmit if port is not valid */
 	if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) {
-		err("%s: port or port->private is NULL, status=%d", __FUNCTION__,
-			urb->status );
+		err("%s: port or port->private is NULL, status=%d",
+		    __FUNCTION__, status);
 		return;
 	}
 	if( port->serial == NULL
 	|| (serial_priv=usb_get_serial_data(port->serial)) == NULL ) {
-		err("%s: serial is bad or serial->private is NULL, status=%d", __FUNCTION__, urb->status );
+		err("%s: serial is bad or serial->private is NULL, status=%d",
+		    __FUNCTION__, status);
 		return;
 	}
 
 	/* do not resubmit urb if it has any status error */
-	if( urb->status ) {
-		err("%s: nonzero read bulk status: status=%d, port=%d", __FUNCTION__, urb->status, priv->dp_port_num );
+	if (status) {
+		err("%s: nonzero read bulk status: status=%d, port=%d",
+		    __FUNCTION__, status, priv->dp_port_num);
 		return;
 	}
 
@@ -1816,10 +1804,11 @@
 	struct digi_port *priv = usb_get_serial_port_data(port);
 	int opcode = ((unsigned char *)urb->transfer_buffer)[0];
 	int len = ((unsigned char *)urb->transfer_buffer)[1];
-	int status = ((unsigned char *)urb->transfer_buffer)[2];
+	int port_status = ((unsigned char *)urb->transfer_buffer)[2];
 	unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
 	int flag,throttled;
 	int i;
+	int status = urb->status;
 
 	/* do not process callbacks on closed ports */
 	/* but do continue the read chain */
@@ -1828,7 +1817,10 @@
 
 	/* short/multiple packet check */
 	if( urb->actual_length != len + 2 ) {
-     		err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", __FUNCTION__, urb->status, priv->dp_port_num, opcode, len, urb->actual_length, status );
+		err("%s: INCOMPLETE OR MULTIPLE PACKET, urb status=%d, "
+		    "port=%d, opcode=%d, len=%d, actual_length=%d, "
+		    "port_status=%d", __FUNCTION__, status, priv->dp_port_num,
+		    opcode, len, urb->actual_length, port_status);
 		return( -1 );
 	}
 
@@ -1843,52 +1835,37 @@
 	/* receive data */
 	if( opcode == DIGI_CMD_RECEIVE_DATA ) {
 
-		/* get flag from status */
+		/* get flag from port_status */
 		flag = 0;
 
 		/* overrun is special, not associated with a char */
-		if( status & DIGI_OVERRUN_ERROR ) {
+		if (port_status & DIGI_OVERRUN_ERROR) {
 			tty_insert_flip_char( tty, 0, TTY_OVERRUN );
 		}
 
 		/* break takes precedence over parity, */
 		/* which takes precedence over framing errors */
-		if( status & DIGI_BREAK_ERROR ) {
+		if (port_status & DIGI_BREAK_ERROR) {
 			flag = TTY_BREAK;
-		} else if( status & DIGI_PARITY_ERROR ) {
+		} else if (port_status & DIGI_PARITY_ERROR) {
 			flag = TTY_PARITY;
-		} else if( status & DIGI_FRAMING_ERROR ) {
+		} else if (port_status & DIGI_FRAMING_ERROR) {
 			flag = TTY_FRAME;
 		}
 
-		/* data length is len-1 (one byte of len is status) */
+		/* data length is len-1 (one byte of len is port_status) */
 		--len;
 
-		if( throttled ) {
-
-			len = min( len,
-				DIGI_IN_BUF_SIZE - priv->dp_in_buf_len );
-
-			if( len > 0 ) {
-				memcpy( priv->dp_in_buf + priv->dp_in_buf_len,
-					data, len );
-				memset( priv->dp_in_flag_buf
-					+ priv->dp_in_buf_len, flag, len );
-				priv->dp_in_buf_len += len;
+		len = tty_buffer_request_room(tty, len);
+		if( len > 0 ) {
+			/* Hot path */
+			if(flag == TTY_NORMAL)
+				tty_insert_flip_string(tty, data, len);
+			else {
+				for(i = 0; i < len; i++)
+					tty_insert_flip_char(tty, data[i], flag);
 			}
-
-		} else {
-			len = tty_buffer_request_room(tty, len);
-			if( len > 0 ) {
-				/* Hot path */
-				if(flag == TTY_NORMAL)
-					tty_insert_flip_string(tty, data, len);
-				else {
-					for(i = 0; i < len; i++)
-						tty_insert_flip_char(tty, data[i], flag);
-				}
-				tty_flip_buffer_push( tty );
-			}
+			tty_flip_buffer_push( tty );
 		}
 	}
 
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 4703c8f..050fcc9 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -326,12 +326,14 @@
 
 static void empeg_write_bulk_callback (struct urb *urb)
 {
-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct usb_serial_port *port = urb->context;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -345,11 +347,13 @@
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	int result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 95a1805..7b1673a 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -271,20 +271,58 @@
 static __u16 vendor = FTDI_VID;
 static __u16 product;
 
-/* struct ftdi_sio_quirk is used by devices requiring special attention. */
-struct ftdi_sio_quirk {
-	void (*setup)(struct usb_serial *); /* Special settings during startup. */
+struct ftdi_private {
+	ftdi_chip_type_t chip_type;
+				/* type of the device, either SIO or FT8U232AM */
+	int baud_base;		/* baud base clock for divisor setting */
+	int custom_divisor;	/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+	__u16 last_set_data_urb_value ;
+				/* the last data state set - needed for doing a break */
+        int write_offset;       /* This is the offset in the usb data block to write the serial data -
+				 * it is different between devices
+				 */
+	int flags;		/* some ASYNC_xxxx flags are supported */
+	unsigned long last_dtr_rts;	/* saved modem control outputs */
+        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
+	__u8 rx_flags;		/* receive state flags (throttling) */
+	spinlock_t rx_lock;	/* spinlock for receive state */
+	struct delayed_work rx_work;
+	struct usb_serial_port *port;
+	int rx_processed;
+	unsigned long rx_bytes;
+
+	__u16 interface;	/* FT2232C port interface (0 for FT232/245) */
+
+	int force_baud;		/* if non-zero, force the baud rate to this value */
+	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
+
+	spinlock_t tx_lock;	/* spinlock for transmit state */
+	unsigned long tx_bytes;
+	unsigned long tx_outstanding_bytes;
+	unsigned long tx_outstanding_urbs;
 };
 
-static void  ftdi_USB_UIRT_setup	(struct usb_serial *serial);
-static void  ftdi_HE_TIRA1_setup	(struct usb_serial *serial);
+/* struct ftdi_sio_quirk is used by devices requiring special attention. */
+struct ftdi_sio_quirk {
+	int (*probe)(struct usb_serial *);
+	void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
+};
+
+static int   ftdi_olimex_probe		(struct usb_serial *serial);
+static void  ftdi_USB_UIRT_setup	(struct ftdi_private *priv);
+static void  ftdi_HE_TIRA1_setup	(struct ftdi_private *priv);
+
+static struct ftdi_sio_quirk ftdi_olimex_quirk = {
+	.probe	= ftdi_olimex_probe,
+};
 
 static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
-	.setup = ftdi_USB_UIRT_setup,
+	.port_probe = ftdi_USB_UIRT_setup,
 };
 
 static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
-	.setup = ftdi_HE_TIRA1_setup,
+	.port_probe = ftdi_HE_TIRA1_setup,
 };
 
 /*
@@ -311,6 +349,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IPLUS2_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_DMX4ALL) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
@@ -319,6 +358,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
@@ -525,6 +565,9 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
 	{ USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
 	{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
+	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_olimex_quirk },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -556,38 +599,6 @@
 #define THROTTLED		0x01
 #define ACTUALLY_THROTTLED	0x02
 
-struct ftdi_private {
-	ftdi_chip_type_t chip_type;
-				/* type of the device, either SIO or FT8U232AM */
-	int baud_base;		/* baud base clock for divisor setting */
-	int custom_divisor;	/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
-	__u16 last_set_data_urb_value ;
-				/* the last data state set - needed for doing a break */
-        int write_offset;       /* This is the offset in the usb data block to write the serial data -
-				 * it is different between devices
-				 */
-	int flags;		/* some ASYNC_xxxx flags are supported */
-	unsigned long last_dtr_rts;	/* saved modem control outputs */
-        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
-	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
-	__u8 rx_flags;		/* receive state flags (throttling) */
-	spinlock_t rx_lock;	/* spinlock for receive state */
-	struct delayed_work rx_work;
-	struct usb_serial_port *port;
-	int rx_processed;
-	unsigned long rx_bytes;
-
-	__u16 interface;	/* FT2232C port interface (0 for FT232/245) */
-
-	int force_baud;		/* if non-zero, force the baud rate to this value */
-	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
-
-	spinlock_t tx_lock;	/* spinlock for transmit state */
-	unsigned long tx_bytes;
-	unsigned long tx_outstanding_bytes;
-	unsigned long tx_outstanding_urbs;
-};
-
 /* Used for TIOCMIWAIT */
 #define FTDI_STATUS_B0_MASK	(FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
 #define FTDI_STATUS_B1_MASK	(FTDI_RS_BI)
@@ -598,7 +609,6 @@
 
 /* function prototypes for a FTDI serial converter */
 static int  ftdi_sio_probe	(struct usb_serial *serial, const struct usb_device_id *id);
-static int  ftdi_sio_attach		(struct usb_serial *serial);
 static void ftdi_shutdown		(struct usb_serial *serial);
 static int  ftdi_sio_port_probe	(struct usb_serial_port *port);
 static int  ftdi_sio_port_remove	(struct usb_serial_port *port);
@@ -652,7 +662,6 @@
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
-	.attach =		ftdi_sio_attach,
 	.shutdown =		ftdi_shutdown,
 };
 
@@ -669,7 +678,7 @@
 
 /*
  * ***************************************************************************
- * Utlity functions
+ * Utility functions
  * ***************************************************************************
  */
 
@@ -1138,7 +1147,9 @@
 		dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
 		retval = device_create_file(&port->dev, &dev_attr_event_char);
 		if ((!retval) &&
-		    (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
+		    (priv->chip_type == FT232BM ||
+		     priv->chip_type == FT2232C ||
+		     priv->chip_type == FT232RL)) {
 			retval = device_create_file(&port->dev,
 						    &dev_attr_latency_timer);
 		}
@@ -1171,14 +1182,24 @@
 /* Probe function to check for special devices */
 static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id)
 {
+	struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info;
+
+	if (quirk && quirk->probe) {
+		int ret = quirk->probe(serial);
+		if (ret != 0)
+			return ret;
+	}
+
 	usb_set_serial_data(serial, (void *)id->driver_info);
 
-	return (0);
+	return 0;
 }
 
 static int ftdi_sio_port_probe(struct usb_serial_port *port)
 {
 	struct ftdi_private *priv;
+	struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
+
 
 	dbg("%s",__FUNCTION__);
 
@@ -1195,6 +1216,9 @@
 	   than queue a task to deliver them */
 	priv->flags = ASYNC_LOW_LATENCY;
 
+	if (quirk && quirk->port_probe)
+		quirk->port_probe(priv);
+
 	/* Increase the size of read buffers */
 	kfree(port->bulk_in_buffer);
 	port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
@@ -1225,29 +1249,13 @@
 	return 0;
 }
 
-/* attach subroutine */
-static int ftdi_sio_attach (struct usb_serial *serial)
-{
-	/* Check for device requiring special set up. */
-	struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
-
-	if (quirk && quirk->setup)
-		quirk->setup(serial);
-
-	return 0;
-} /* ftdi_sio_attach */
-
-
 /* Setup for the USB-UIRT device, which requires hardwired
  * baudrate (38400 gets mapped to 312500) */
 /* Called from usbserial:serial_probe */
-static void ftdi_USB_UIRT_setup (struct usb_serial *serial)
+static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
 {
-	struct ftdi_private *priv;
-
 	dbg("%s",__FUNCTION__);
 
-	priv = usb_get_serial_port_data(serial->port[0]);
 	priv->flags |= ASYNC_SPD_CUST;
 	priv->custom_divisor = 77;
 	priv->force_baud = B38400;
@@ -1255,19 +1263,34 @@
 
 /* Setup for the HE-TIRA1 device, which requires hardwired
  * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled.  */
-static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
+static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
 {
-	struct ftdi_private *priv;
-
 	dbg("%s",__FUNCTION__);
 
-	priv = usb_get_serial_port_data(serial->port[0]);
 	priv->flags |= ASYNC_SPD_CUST;
 	priv->custom_divisor = 240;
 	priv->force_baud = B38400;
 	priv->force_rtscts = 1;
 } /* ftdi_HE_TIRA1_setup */
 
+/*
+ * First port on Olimex arm-usb-ocd is reserved for JTAG interface
+ * and can be accessed from userspace using openocd.
+ */
+static int ftdi_olimex_probe(struct usb_serial *serial)
+{
+	struct usb_device *udev = serial->dev;
+	struct usb_interface *interface = serial->interface;
+
+	dbg("%s",__FUNCTION__);
+
+	if (interface == udev->actconfig->interface[0]) {
+		info("Ignoring reserved serial port on Olimex arm-usb-ocd\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
 
 /* ftdi_shutdown is called from usbserial:usb_serial_disconnect
  *   it is called when the usb device is disconnected
@@ -1537,14 +1560,15 @@
 	struct ftdi_private *priv;
 	int data_offset;       /* will be 1 for the SIO and 0 otherwise */
 	unsigned long countback;
+	int status = urb->status;
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree (urb->transfer_buffer);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("nonzero write bulk status received: %d", urb->status);
+	if (status) {
+		dbg("nonzero write bulk status received: %d", status);
 		return;
 	}
 
@@ -1620,6 +1644,7 @@
 	struct ftdi_private *priv;
 	unsigned long countread;
 	unsigned long flags;
+	int status = urb->status;
 
 	if (urb->number_of_packets > 0) {
 		err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
@@ -1648,9 +1673,10 @@
 		err("%s - Not my urb!", __FUNCTION__);
 	}
 
-	if (urb->status) {
+	if (status) {
 		/* This will happen at close every time so it is a dbg not an err */
-		dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status);
+		dbg("(this is ok on close) nonzero read bulk status received: "
+		    "%d", status);
 		return;
 	}
 
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 77ad0a0..d9e4971 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -56,10 +56,14 @@
 
 /* iPlus device */
 #define FTDI_IPLUS_PID 0xD070 /* Product Id */
+#define FTDI_IPLUS2_PID 0xD071 /* Product Id */
 
 /* DMX4ALL DMX Interfaces */
 #define FTDI_DMX4ALL 0xC850
 
+/* OpenDCC (www.opendcc.de) product id */
+#define FTDI_OPENDCC_PID	0xBFD8
+
 /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
 /* they use the ftdi chipset for the USB interface and the vendor id is the same */
 #define FTDI_XF_632_PID 0xFC08	/* 632: 16x2 Character Display */
@@ -518,6 +522,15 @@
 #define FTDI_IBS_PEDO_PID	0xff3e  /* IBS PEDO-Modem (RF modem 868.35 MHz) */
 #define FTDI_IBS_PROD_PID	0xff3f  /* future device */
 
+/*
+ *  MaxStream devices	www.maxstream.net
+ */
+#define FTDI_MAXSTREAM_PID	0xEE18	/* Xbee PKG-U Module */
+
+/* Olimex */
+#define OLIMEX_VID			0x15BA
+#define OLIMEX_ARM_USB_OCD_PID		0x0003
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 74660a3..04bd3b7 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1036,15 +1036,16 @@
 	unsigned long flags;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	int status = urb->status;
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree (urb->transfer_buffer);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
+	if (status) {
 		dbg("%s - nonzero write bulk status received: %d",
-			__FUNCTION__, urb->status);
+			__FUNCTION__, status);
 		spin_lock_irqsave(&garmin_data_p->lock, flags);
 		garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
 		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1281,7 +1282,8 @@
 	struct usb_serial *serial =  port->serial;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
-	int status;
+	int status = urb->status;
+	int retval;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -1290,9 +1292,9 @@
 		return;
 	}
 
-	if (urb->status) {
+	if (status) {
 		dbg("%s - nonzero read bulk status received: %d",
-			__FUNCTION__, urb->status);
+			__FUNCTION__, status);
 		return;
 	}
 
@@ -1306,19 +1308,19 @@
 		spin_lock_irqsave(&garmin_data_p->lock, flags);
 		garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART;
 		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
-		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-		if (status)
+		retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (retval)
 			dev_err(&port->dev,
 				"%s - failed resubmitting read urb, error %d\n",
-			        __FUNCTION__, status);
+				__FUNCTION__, retval);
 	} else if (urb->actual_length > 0) {
 		/* Continue trying to read until nothing more is received  */
 		if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
-			status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-			if (status)
+			retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+			if (retval)
 				dev_err(&port->dev,
-					"%s - failed resubmitting read urb, error %d\n",
-			        	__FUNCTION__, status);
+					"%s - failed resubmitting read urb, "
+					"error %d\n", __FUNCTION__, retval);
 		}
 	} else {
 		dbg("%s - end of bulk data", __FUNCTION__);
@@ -1333,13 +1335,14 @@
 static void garmin_read_int_callback (struct urb *urb)
 {
 	unsigned long flags;
-	int status;
+	int retval;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = port->serial;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
+	int status = urb->status;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -1348,11 +1351,11 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
-			__FUNCTION__, urb->status);
+			__FUNCTION__, status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d",
-			__FUNCTION__, urb->status);
+			__FUNCTION__, status);
 		return;
 	}
 
@@ -1374,11 +1377,11 @@
 					port->read_urb->transfer_buffer,
 					port->read_urb->transfer_buffer_length,
 					garmin_read_bulk_callback, port);
-			status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-			if (status) {
+			retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+			if (retval) {
 				dev_err(&port->dev,
 					"%s - failed submitting read urb, error %d\n",
-				__FUNCTION__, status);
+				__FUNCTION__, retval);
 			} else {
 				spin_lock_irqsave(&garmin_data_p->lock, flags);
 				garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
@@ -1422,11 +1425,11 @@
 	}
 
 	port->interrupt_in_urb->dev = port->serial->dev;
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
+	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	if (retval)
 		dev_err(&urb->dev->dev,
 			"%s - Error %d submitting interrupt urb\n",
-			__FUNCTION__, status);
+			__FUNCTION__, retval);
 }
 
 
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4f8282a..88a2c7d 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -69,6 +69,7 @@
 	.shutdown =		usb_serial_generic_shutdown,
 	.throttle =		usb_serial_generic_throttle,
 	.unthrottle =		usb_serial_generic_unthrottle,
+	.resume =		usb_serial_generic_resume,
 };
 
 static int generic_probe(struct usb_interface *interface,
@@ -169,6 +170,23 @@
 	}
 }
 
+int usb_serial_generic_resume(struct usb_serial *serial)
+{
+	struct usb_serial_port *port;
+	int i, c = 0, r;
+
+	for (i = 0; i < serial->num_ports; i++) {
+		port = serial->port[i];
+		if (port->open_count && port->read_urb) {
+			r = usb_submit_urb(port->read_urb, GFP_NOIO);
+			if (r < 0)
+				c++;
+		}
+	}
+
+	return c ? -EIO : 0;
+}
+
 void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
 {
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -263,79 +281,82 @@
 	return (chars);
 }
 
-/* Push data to tty layer and resubmit the bulk read URB */
-static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+
+static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
 {
-	struct usb_serial *serial = port->serial;
 	struct urb *urb = port->read_urb;
-	struct tty_struct *tty = port->tty;
+	struct usb_serial *serial = port->serial;
 	int result;
 
-	/* Push data to tty */
-	if (tty && urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length);
-		tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
-	  	tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
-	}
-
 	/* Continue reading from device */
-	usb_fill_bulk_urb (port->read_urb, serial->dev,
+	usb_fill_bulk_urb (urb, serial->dev,
 			   usb_rcvbulkpipe (serial->dev,
 				   	    port->bulk_in_endpointAddress),
-			   port->read_urb->transfer_buffer,
-			   port->read_urb->transfer_buffer_length,
+			   urb->transfer_buffer,
+			   urb->transfer_buffer_length,
 			   ((serial->type->read_bulk_callback) ? 
 			     serial->type->read_bulk_callback : 
 			     usb_serial_generic_read_bulk_callback), port);
-	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+	result = usb_submit_urb(urb, mem_flags);
 	if (result)
 		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
 }
 
+/* Push data to tty layer and resubmit the bulk read URB */
+static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+{
+	struct urb *urb = port->read_urb;
+	struct tty_struct *tty = port->tty;
+	int room;
+
+	/* Push data to tty */
+	if (tty && urb->actual_length) {
+		room = tty_buffer_request_room(tty, urb->actual_length);
+		if (room) {
+			tty_insert_flip_string(tty, urb->transfer_buffer, room);
+			tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
+		}
+	}
+
+	resubmit_read_urb(port, GFP_ATOMIC);
+}
+
 void usb_serial_generic_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	unsigned char *data = urb->transfer_buffer;
-	int is_throttled;
-	unsigned long flags;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (unlikely(status != 0)) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
 
 	/* Throttle the device if requested by tty */
-	if (urb->actual_length) {
-		spin_lock_irqsave(&port->lock, flags);
-		is_throttled = port->throttled = port->throttle_req;
-		spin_unlock_irqrestore(&port->lock, flags);
-		if (is_throttled) {
-			/* Let the received data linger in the read URB;
-			 * usb_serial_generic_unthrottle() will pick it
-			 * up later. */
-			dbg("%s - throttling device", __FUNCTION__);
-			return;
-		}
-	}
-
-	/* Handle data and continue reading from device */
-	flush_and_resubmit_read_urb(port);
+	spin_lock(&port->lock);
+	if (!(port->throttled = port->throttle_req))
+		/* Handle data and continue reading from device */
+		flush_and_resubmit_read_urb(port);
+	spin_unlock(&port->lock);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
 void usb_serial_generic_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	port->write_urb_busy = 0;
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -370,8 +391,8 @@
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	if (was_throttled) {
-		/* Handle pending data and resume reading from device */
-		flush_and_resubmit_read_urb(port);
+		/* Resume reading from device */
+		resubmit_read_urb(port, GFP_KERNEL);
 	}
 }
 
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 4807f96..dd42f57 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -599,10 +599,11 @@
 	int txCredits;
 	int portNumber;
 	int result;
+	int status = urb->status;
 
 	dbg("%s", __FUNCTION__);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -610,10 +611,12 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d",
+		    __FUNCTION__, status);
 		goto exit;
 	}
 
@@ -688,13 +691,15 @@
 {
 	struct edgeport_serial	*edge_serial = (struct edgeport_serial *)urb->context;
 	unsigned char		*data = urb->transfer_buffer;
-	int			status;
+	int			retval;
 	__u16			raw_data_length;
+	int status = urb->status;
 
 	dbg("%s", __FUNCTION__);
 
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		edge_serial->read_in_progress = false;
 		return;
 	}
@@ -722,9 +727,11 @@
 	if (edge_serial->rxBytesAvail > 0) {
 		dbg("%s - posting a read", __FUNCTION__);
 		edge_serial->read_urb->dev = edge_serial->serial->dev;
-		status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
-		if (status) {
-			dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status);
+		retval = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
+		if (retval) {
+			dev_err(&urb->dev->dev,
+				"%s - usb_submit_urb(read bulk) failed, "
+				"retval = %d\n", __FUNCTION__, retval);
 			edge_serial->read_in_progress = false;
 		}
 	} else {
@@ -744,11 +751,13 @@
 {
 	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
 	struct tty_struct *tty;
+	int status = urb->status;
 
 	dbg("%s", __FUNCTION__);
 
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 	}
 
 	tty = edge_port->port->tty;
@@ -1504,15 +1513,6 @@
 	}
 
 	cflag = tty->termios->c_cflag;
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if (cflag == old_termios->c_cflag &&
-		    tty->termios->c_iflag == old_termios->c_iflag) {
-			dbg("%s - nothing to change", __FUNCTION__);
-			return;
-		}
-	}
-
 	dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
 	    tty->termios->c_cflag, tty->termios->c_iflag);
 	if (old_termios) {
@@ -3046,11 +3046,11 @@
 	}
 	/* free up our endpoint stuff */
 	if (edge_serial->is_epic) {
-		usb_unlink_urb(edge_serial->interrupt_read_urb);
+		usb_kill_urb(edge_serial->interrupt_read_urb);
 		usb_free_urb(edge_serial->interrupt_read_urb);
 		kfree(edge_serial->interrupt_in_buffer);
 
-		usb_unlink_urb(edge_serial->read_urb);
+		usb_kill_urb(edge_serial->read_urb);
 		usb_free_urb(edge_serial->read_urb);
 		kfree(edge_serial->bulk_in_buffer);
 	}
diff --git a/drivers/usb/serial/io_fw_down3.h b/drivers/usb/serial/io_fw_down3.h
index 93b56d6..4496b06 100644
--- a/drivers/usb/serial/io_fw_down3.h
+++ b/drivers/usb/serial/io_fw_down3.h
@@ -5,7 +5,7 @@
 //**************************************************************
 
 
-static int IMAGE_SIZE = 12749;
+static int IMAGE_SIZE = 12938;
 
 struct EDGE_FIRMWARE_VERSION_INFO
 {
@@ -16,7 +16,7 @@
 
 static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME =
 {
-	4, 10, 0		// Major, Minor, Build
+	4, 80, 0		// Major, Minor, Build
 
 };
 
@@ -27,16 +27,16 @@
 //      WORD    Length;
 //      BYTE    CheckSum;
 //  };
-0xca, 0x31, 
-0xa8, 
+0x87, 0x32,
+0x9a,
 
-0x02, 0x26, 0xfe, 0x02, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 
+0x02, 0x27, 0xbf, 0x02, 0x21, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f, 
 0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e, 
 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75, 
 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81, 
-0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x94, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, 
+0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0xdc, 0xe6, 0xf0, 0x08, 0xa3, 0xd9,
 0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e, 
 0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86, 
 0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 
@@ -49,387 +49,398 @@
 0xc9, 0xf0, 0x69, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0, 0xca, 0xf0, 0x6a, 0x60, 0x02, 0x7e, 0x04, 
 0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 
 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 
-0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 
-0x02, 0x11, 0x94, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xaf, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 
-0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 
-0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
-0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
-0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 
-0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 
-0xb4, 0x02, 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
-0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 
-0x80, 0x03, 0x02, 0x02, 0x62, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 
-0xf1, 0x20, 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 
-0x14, 0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 
-0x7e, 0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x33, 0x12, 0x00, 0xc9, 0xee, 
-0x64, 0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 
-0x02, 0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x33, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 
-0x33, 0x7c, 0x0a, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
-0xa3, 0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 
-0x80, 0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 
-0xd2, 0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 
-0x60, 0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 
-0x60, 0x13, 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 
-0x0f, 0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 
-0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 
-0x90, 0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 
-0xec, 0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 
-0x01, 0x7f, 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 
-0xff, 0xea, 0x90, 0xfa, 0xba, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0x30, 0xe4, 0xf5, 0x4d, 0xe5, 
-0x4d, 0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0x11, 0xe4, 0x12, 0x1a, 0x38, 0x05, 0x4d, 0x04, 
-0x12, 0x1c, 0x02, 0x80, 0xea, 0x12, 0x1c, 0x30, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 
-0xc0, 0x70, 0x03, 0x02, 0x08, 0xc5, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 
-0xe0, 0xfe, 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 
-0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0x4c, 0x03, 0x56, 0x00, 0x04, 0x29, 0x01, 0x05, 0x3c, 0x03, 
-0x06, 0x03, 0x05, 0x06, 0x45, 0x06, 0x07, 0xa7, 0x08, 0x07, 0xef, 0x09, 0x08, 0x4b, 0x0a, 0x08, 
-0x8b, 0x0b, 0x00, 0x00, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
-0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x02, 0x45, 
-0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 
-0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x11, 0x74, 
-0x01, 0x12, 0x1a, 0x38, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0x11, 0x74, 0x02, 0x12, 
-0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb6, 0xe0, 
-0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 
-0x26, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
-0x60, 0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
-0x26, 0xe5, 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 
-0x38, 0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 0x38, 0x80, 0x19, 0x15, 0x4d, 
-0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x80, 0x09, 0x12, 0x1c, 
-0xb3, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x12, 0x1c, 0x11, 0x12, 0x19, 0xf2, 0x60, 0x05, 0x74, 
-0x01, 0x12, 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 
-0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x14, 0x60, 0x2d, 
-0x14, 0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x04, 
-0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 
-0x0f, 0x26, 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 
-0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb6, 
-0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 
-0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 
-0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
-0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 
-0x07, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 
-0x54, 0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 
-0x20, 0x24, 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 
-0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 
-0x1d, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x0e, 
-0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0x32, 0x15, 0x4d, 
-0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1c, 
-0xb3, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 
-0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
-0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 
-0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 
-0x60, 0x03, 0x02, 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 
-0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x07, 
-0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 
-0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 0x70, 
-0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x12, 0x31, 0x82, 
-0x40, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 
-0xe5, 0x4d, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1d, 0x64, 0x02, 0x1d, 0x2f, 0xe5, 0x35, 0x20, 
-0xe1, 0x03, 0x02, 0x0f, 0x26, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 
-0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x1c, 0xb3, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 
-0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 
-0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
-0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xbb, 
-0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 
-0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 
-0x3b, 0x70, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
-0xba, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 
-0x60, 0x03, 0x02, 0x0f, 0x26, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x30, 0x12, 0x1d, 
-0x5d, 0x7d, 0x03, 0x12, 0x0f, 0x6d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 
-0xb3, 0xe0, 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 
-0xaf, 0x3c, 0x02, 0x0f, 0xba, 0x12, 0x1c, 0x30, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 
-0x1d, 0x5d, 0x7d, 0x14, 0x12, 0x0f, 0x6d, 0x60, 0x10, 0x02, 0x0f, 0x26, 0x12, 0x1d, 0x5d, 0x7d, 
-0x04, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 0xb3, 0xe0, 
-0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 
-0x02, 0x0f, 0xba, 0x12, 0x1d, 0x5d, 0x7d, 0x05, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 
-0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x12, 0x1c, 0x78, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 
-0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb2, 0xf0, 
-0xe4, 0xf5, 0x4c, 0x90, 0xfa, 0xb2, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1c, 
-0x72, 0x12, 0x0f, 0xcc, 0xff, 0xfd, 0x90, 0xfa, 0xb4, 0xe4, 0x8d, 0xf0, 0x12, 0x1a, 0x6c, 0x90, 
-0xfa, 0xb3, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x26, 0x05, 0x4c, 
-0x80, 0xd1, 0x12, 0x1c, 0x72, 0x12, 0x0f, 0xcc, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb3, 0xf0, 0xfd, 
-0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0x7a, 0xf9, 0x79, 0x6f, 0x7b, 0x01, 0x8b, 0x36, 
-0x8a, 0x37, 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1c, 0x78, 0x12, 0x25, 
-0xd7, 0x8f, 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0x11, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x12, 
-0x1c, 0x11, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0x4a, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 
-0x95, 0x3c, 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 
-0x3a, 0x02, 0x2c, 0x07, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 
-0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 
-0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 
-0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 
-0x02, 0x0f, 0x26, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xa9, 0xe5, 
-0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 
-0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 0xe0, 0x94, 0x01, 
-0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 
-0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
-0xbb, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 
-0x53, 0x35, 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 
-0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
-0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 
-0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 
-0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x7f, 0x01, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 
-0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 
-0xe0, 0x94, 0x00, 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 
-0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 
-0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xff, 0x01, 0x12, 0x1d, 0x74, 0xef, 0x12, 0x1a, 0x38, 0x90, 
-0xfa, 0xb6, 0x12, 0x1d, 0x74, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0x4a, 0x90, 0x00, 0x02, 0xe4, 
-0x12, 0x1a, 0x4a, 0x74, 0x03, 0x12, 0x1c, 0x02, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 
-0x38, 0x82, 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 
-0x4c, 0x09, 0x4a, 0x02, 0x09, 0x6c, 0x04, 0x09, 0x8e, 0x05, 0x09, 0xba, 0x06, 0x09, 0xd8, 0x07, 
-0x09, 0xf6, 0x08, 0x0a, 0x14, 0x09, 0x0a, 0x32, 0x0b, 0x0a, 0xe7, 0x80, 0x0d, 0x6f, 0x81, 0x0d, 
-0xa0, 0x82, 0x0b, 0x2e, 0x83, 0x0b, 0x77, 0x84, 0x0b, 0x96, 0x85, 0x0b, 0xdb, 0x86, 0x0c, 0x26, 
-0x87, 0x0c, 0xb7, 0x88, 0x0d, 0x42, 0x89, 0x0a, 0x50, 0x92, 0x0a, 0x50, 0x93, 0x0e, 0x53, 0xc0, 
-0x0e, 0x7f, 0xc1, 0x0e, 0x90, 0xc2, 0x00, 0x00, 0x0f, 0x15, 0xe5, 0x35, 0x20, 0xe7, 0x05, 0x7f, 
-0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 
-0x7f, 0x07, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 0x20, 0xe7, 
-0x05, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 
-0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 
-0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1d, 0x92, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, 0x70, 
-0x05, 0x7f, 0x02, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, 0x02, 
-0x80, 0x03, 0x02, 0x31, 0x6f, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 
-0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x08, 
-0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 
-0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, 0x11, 
-0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 
-0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x16, 0x7f, 
-0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 
-0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 
-0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 
-0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 
-0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1c, 0xc9, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 
-0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 
-0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1b, 0x72, 0x12, 
-0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x05, 0x12, 0x31, 0xbd, 
-0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 
-0x72, 0x02, 0x2c, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0x18, 0x12, 0x1c, 0xc9, 0x60, 0x05, 
-0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1d, 0x92, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x30, 0xec, 0x90, 
-0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 
-0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 
-0x4c, 0x12, 0x1b, 0x72, 0x02, 0x31, 0x6f, 0x12, 0x1d, 0x9c, 0x12, 0x2a, 0x06, 0x12, 0x1c, 0x83, 
-0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x78, 0x68, 0x12, 0x1b, 
-0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a, 
-0x4a, 0x90, 0xfa, 0xb7, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, 0x8c, 
-0x83, 0x12, 0x1c, 0x8b, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 
-0xb6, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 
-0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 
-0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 0xe0, 
-0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 0xb0, 
-0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0xb4, 0x01, 
-0x0a, 0x12, 0x1c, 0x11, 0xe5, 0x90, 0x12, 0x1a, 0x38, 0x80, 0x08, 0x12, 0x1c, 0x11, 0xe5, 0xb0, 
-0x12, 0x1a, 0x38, 0x02, 0x0f, 0xa9, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0x12, 0x12, 0x1c, 0x41, 
-0x20, 0xe1, 0x33, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 
-0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1d, 0xa6, 
-0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 
-0x80, 0x04, 0x12, 0x1d, 0xad, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
-0x24, 0x12, 0x12, 0x1c, 0x41, 0x20, 0xe1, 0x39, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x1b, 
-0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
-0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
-0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 
-0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x12, 0x1c, 0xc1, 0x60, 0x4d, 0x04, 0x60, 
-0x03, 0x02, 0x0c, 0xb2, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, 0x3a, 
-0x30, 0xe1, 0x6f, 0x12, 0x1d, 0x7c, 0x02, 0x0c, 0xb2, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, 0x12, 
-0x1c, 0x3d, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1d, 0x7c, 0x80, 
-0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1d, 0x7c, 
-0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
-0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0x3a, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 
-0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0x3d, 0x30, 0xe1, 0x13, 0x30, 
-0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 
-0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 
-0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, 0x44, 
-0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 
-0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, 0x44, 
-0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 
-0x80, 0x3b, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, 0xa3, 
-0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, 0xef, 
-0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, 0xc2, 
-0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 
-0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, 0x16, 
-0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x80, 0x0a, 0x90, 0xff, 0xb6, 0xe0, 
-0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0x07, 0xe4, 
-0xff, 0x12, 0x30, 0xec, 0x12, 0x1d, 0x37, 0x7f, 0x03, 0x12, 0x12, 0x19, 0x90, 0xf9, 0x15, 0xe0, 
-0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 
-0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, 0x16, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 
-0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbc, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 
-0xb4, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 
-0xb9, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 
-0xb9, 0xf0, 0x12, 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x73, 0x12, 0x1c, 0x4a, 0x90, 0xfa, 
-0xbc, 0x12, 0x1d, 0x56, 0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 
-0xfa, 0xb9, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x12, 
-0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, 0x12, 0x1c, 0x4a, 0x80, 0xd1, 0x75, 0x4c, 0x02, 
-0x90, 0xfa, 0xbc, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb4, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 
-0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, 0xfa, 0xbd, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 
-0x00, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 
-0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 
-0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x64, 0xf0, 
-0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb7, 0xe0, 0x54, 0x0f, 0x90, 
-0xf9, 0x63, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 
-0x1d, 0x9c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x30, 0xec, 
-0x12, 0x1c, 0xd0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 
-0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 0x12, 0x1d, 0xa6, 0x12, 0x0f, 0x78, 
-0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x78, 0xff, 
-0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 0x1d, 0xa6, 0xf0, 0x90, 0xfa, 0xb7, 
-0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 
-0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1d, 0xad, 
-0x12, 0x0f, 0x98, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 
-0x0f, 0x98, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1d, 0xad, 0xf0, 
-0xe4, 0xff, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 
-0x18, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x31, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 
-0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 
-0xfa, 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 
-0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, 0xb4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 
-0xb9, 0xe0, 0xf5, 0x4a, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x22, 0xa0, 
-0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
-0xa6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x12, 0x25, 0xd7, 0x8f, 0x4c, 0x7e, 0x00, 
-0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
-0xb6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 
-0x2c, 0x07, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x02, 0x31, 0x82, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 
-0x07, 0x12, 0x22, 0xa0, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x25, 
-0xd7, 0x90, 0xfa, 0xb1, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 
-0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 
-0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 
-0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 
-0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 0x10, 0x78, 0x7f, 0x00, 0x7e, 0x00, 
-0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 
-0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 
-0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 
-0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 
-0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x12, 0x11, 0x0f, 0xd0, 0x05, 0xd0, 
-0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 
-0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x66, 
-0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 
-0x78, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 
-0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 
-0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 
-0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 
-0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 
-0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 
-0xee, 0x12, 0x11, 0x0f, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 
-0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 
-0xe8, 0x50, 0x05, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xef, 0x60, 0x31, 0x90, 0x30, 0x54, 0xe4, 0x93, 
-0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x10, 0x78, 0xd0, 0x04, 0x43, 0x07, 0x80, 
-0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 
-0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x43, 0x12, 0x11, 0x0f, 0xd0, 0x83, 0xd0, 0x82, 
-0xd0, 0xf0, 0x22, 0x02, 0x11, 0x94, 0xc0, 0x04, 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 
-0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 
-0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 
-0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 
-0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 
-0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
-0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0xd2, 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 
-0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
-0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 
-0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 
-0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 
-0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 
-0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 
-0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0x66, 0x80, 
-0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 
-0x12, 0x11, 0x66, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
-0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 
-0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 
-0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x36, 0xf5, 0x82, 
-0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 
-0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 
-0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 
-0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 
-0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x30, 0x54, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 
-0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 
-0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 
-0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 
-0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 
-0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x12, 0x41, 0xad, 0x07, 0xaf, 0x02, 
-0x12, 0x12, 0x58, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x11, 0x66, 0x80, 0xc1, 0x8f, 
-0x24, 0x12, 0x2a, 0x06, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 
-0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xed, 0xf0, 
-0x12, 0x22, 0x56, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x12, 0x22, 0x99, 0x24, 0x09, 0x12, 
-0x21, 0xf3, 0xef, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0x09, 0xc0, 
-0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 
-0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x80, 0x12, 0x22, 0x09, 
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x21, 
-0xf3, 0xef, 0xf0, 0xed, 0x12, 0x22, 0x99, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xed, 0xf0, 0x12, 0x21, 
-0xfb, 0xe0, 0xff, 0x30, 0xe7, 0x19, 0x12, 0x22, 0x6e, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x09, 0x12, 
-0x21, 0xfb, 0xef, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x12, 0x21, 0xfb, 0xef, 0x54, 0xfd, 0xf0, 0x78, 
-0x7e, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 
-0xfd, 0x12, 0x22, 0x43, 0xa3, 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 
-0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x31, 0x94, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x78, 0x80, 
-0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x06, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x03, 0x43, 0x07, 
-0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x22, 0x7a, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x42, 
-0x07, 0x43, 0x07, 0x80, 0x12, 0x22, 0x8a, 0xf5, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 
-0x22, 0x99, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 
-0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 
-0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 
-0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x69, 0x78, 0x80, 0x12, 0x22, 0x6f, 
-0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x14, 0xa6, 0x00, 0x14, 0xda, 0x01, 0x14, 0xdf, 0x03, 
-0x14, 0xda, 0x05, 0x14, 0xdf, 0x07, 0x14, 0xda, 0x09, 0x14, 0xdf, 0x0b, 0x14, 0xda, 0x0d, 0x14, 
-0xdf, 0x0f, 0x00, 0x00, 0x14, 0xe7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x21, 0x90, 0xf9, 0x15, 0xe0, 
-0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 
-0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 
-0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 
-0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x22, 0x78, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xef, 
-0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 0x54, 
-0x03, 0x70, 0x03, 0x02, 0x15, 0xd7, 0xee, 0x20, 0xe1, 0x03, 0x02, 0x15, 0xd4, 0x12, 0x22, 0x6e, 
-0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x15, 0x36, 0x00, 0x15, 0x6c, 0x01, 0x15, 0x6c, 0x03, 
-0x15, 0xa0, 0x05, 0x15, 0xa0, 0x07, 0x15, 0x86, 0x09, 0x15, 0x86, 0x0b, 0x15, 0xba, 0x0d, 0x15, 
-0xba, 0x0f, 0x00, 0x00, 0x15, 0xd7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x15, 0xe0, 
-0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, 0x07, 0x7f, 0x02, 0x15, 0xd7, 0x43, 0x07, 0x80, 0x02, 
-0x15, 0xd7, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 
-0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 
-0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 
-0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 
-0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 
-0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 
-0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 
-0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 
-0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x80, 0x12, 0x22, 0x3f, 0xe0, 0xfc, 0xa3, 0xe0, 
-0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 
-0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 
-0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 
-0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 
-0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 
-0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0x3f, 0xa3, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0x7f, 
-0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 
-0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 
-0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x12, 0x18, 0xe2, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 
-0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, 0xcc, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
-0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 
-0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe5, 
-0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 
-0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 
-0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 
-0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 
-0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, 0x41, 0x12, 0x90, 0xf9, 0x15, 0xe0, 0x44, 
-0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x15, 
-0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 
-0x05, 0xe5, 0x23, 0xb4, 0x43, 0x0c, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x80, 0xf0, 0xa3, 0xe0, 0x44, 
-0x80, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x18, 0xe2, 0x90, 0xff, 
-0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1d, 0x84, 
-0x12, 0x1c, 0x30, 0x12, 0x1d, 0x8b, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x43, 0x90, 0xf9, 0x6c, 0x12, 
-0x1b, 0x43, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 
+0xc0, 0x06, 0xc0, 0x07, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x60, 0x23, 0x74,
+0x66, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 0xf0, 0x70, 0x16, 0x74, 0xff, 0xf0, 0x74,
+0x1c, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x60, 0x04, 0x14, 0xf0, 0x70, 0x04, 0xc2, 0x90,
+0x80, 0xfc, 0x90, 0xff, 0x93, 0x74, 0x81, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 0x02, 0x11,
+0xdc, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xb2, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 0x83, 0xe0,
+0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff,
+0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 0xb4, 0x02,
+0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x28, 0x4e, 0x80,
+0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 0xa3, 0xe0,
+0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff,
+0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 0xb4, 0x02,
+0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x28, 0x4e, 0x80,
+0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x80, 0x03,
+0x02, 0x02, 0x90, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 0xf1, 0x20,
+0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x19, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 0xfc,
+0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, 0x01,
+0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x61, 0x12, 0x00, 0xc9, 0xee, 0x64, 0x04,
+0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, 0x60,
+0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x61, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x61, 0x7c,
+0x0a, 0x74, 0x19, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee,
+0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, 0x10,
+0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, 0xb1,
+0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, 0x08,
+0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 0x60, 0x13,
+0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x57, 0xd2,
+0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0,
+0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, 0xff,
+0x04, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff,
+0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, 0x7f,
+0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, 0xea,
+0x90, 0xfa, 0xbd, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0xe0, 0xe4, 0xf5, 0x4d, 0xe5, 0x4d, 0xc3,
+0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0xc1, 0xe4, 0x12, 0x1a, 0xe8, 0x05, 0x4d, 0x04, 0x12, 0x1c,
+0xb2, 0x80, 0xea, 0x12, 0x1c, 0xe0, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, 0x70,
+0x03, 0x02, 0x08, 0xf3, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xfe,
+0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, 0xff,
+0x01, 0xe0, 0x12, 0x1b, 0xfc, 0x03, 0x84, 0x00, 0x04, 0x57, 0x01, 0x05, 0x6a, 0x03, 0x06, 0x31,
+0x05, 0x06, 0x73, 0x06, 0x07, 0xd5, 0x08, 0x08, 0x1d, 0x09, 0x08, 0x79, 0x0a, 0x08, 0xb9, 0x0b,
+0x00, 0x00, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0,
+0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x64, 0x02, 0x45, 0x3b, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1c, 0xc1, 0x74, 0x01, 0x12,
+0x1a, 0xe8, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0xc1, 0x74, 0x02, 0x12, 0x1a, 0xe8,
+0x7f, 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x7f,
+0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x60, 0x07,
+0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0xfa, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0xbe, 0x12, 0x1a, 0xe8, 0x80,
+0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0xbe, 0x12, 0x1a, 0xe8, 0x80, 0x19, 0x15, 0x4d, 0x30, 0x0a,
+0x0b, 0x12, 0x1d, 0x55, 0x12, 0x1c, 0xbc, 0x12, 0x1a, 0xe8, 0x80, 0x09, 0x12, 0x1d, 0x63, 0x12,
+0x1c, 0xbc, 0x12, 0x1a, 0xe8, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xa2, 0x60, 0x05, 0x74, 0x01, 0x12,
+0x1a, 0xe8, 0x7f, 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x14, 0x60, 0x2d, 0x14, 0x60,
+0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x04, 0xa3, 0xe0,
+0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e,
+0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x06,
+0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb9, 0xe0, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb9, 0xe0, 0xd3, 0x94, 0x01,
+0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02,
+0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0xfa, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x07, 0xe5,
+0x4d, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7,
+0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 0x20, 0x24,
+0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f,
+0x03, 0x12, 0x2e, 0x79, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2e, 0x79, 0x80, 0x1d, 0x30,
+0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2e, 0x79, 0x80, 0x0e, 0xe4, 0xfd,
+0x7f, 0x04, 0x12, 0x2e, 0x79, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0xef, 0x15, 0x4d, 0x30, 0x0a,
+0x0b, 0x12, 0x1d, 0x55, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1d, 0x63, 0xf5,
+0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02,
+0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x14, 0x60,
+0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70,
+0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35,
+0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x07, 0xe5, 0x4d,
+0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 0x01, 0x40,
+0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3,
+0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x12, 0x32, 0x3f, 0x40, 0x03,
+0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x4d,
+0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1e, 0x14, 0x02, 0x1d, 0xdf, 0xe5, 0x35, 0x20, 0xe1, 0x03,
+0x02, 0x0f, 0x6e, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1d, 0x55, 0xf5, 0x83, 0xe0, 0x44, 0x08,
+0xf0, 0x80, 0x09, 0x12, 0x1d, 0x63, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 0x02, 0x32,
+0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02,
+0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbe, 0xe0, 0x90,
+0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 0xe4, 0xff,
+0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x70,
+0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0,
+0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1c, 0xe0, 0x12, 0x1e, 0x0d, 0x7d,
+0x03, 0x12, 0x0f, 0xb5, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0x72, 0x90, 0xfa, 0xb6, 0xe0,
+0xfd, 0xa3, 0x12, 0x1d, 0x2b, 0x12, 0x0f, 0xd1, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c,
+0x02, 0x10, 0x02, 0x12, 0x1c, 0xe0, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 0x1e, 0x0d,
+0x7d, 0x14, 0x12, 0x0f, 0xb5, 0x60, 0x10, 0x02, 0x0f, 0x6e, 0x12, 0x1e, 0x0d, 0x7d, 0x04, 0x12,
+0x10, 0x09, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0x72, 0x90, 0xfa, 0xb6, 0xe0, 0xfd, 0xa3,
+0x12, 0x1d, 0x2b, 0x12, 0x0f, 0xd1, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x02, 0x10,
+0x02, 0x12, 0x1e, 0x0d, 0x7d, 0x05, 0x12, 0x10, 0x09, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x7b, 0x01,
+0x7a, 0xfa, 0x79, 0xb6, 0x12, 0x1d, 0x28, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb7, 0xe4,
+0x75, 0xf0, 0x03, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xbe, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0xe4, 0xf5,
+0x4c, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1d, 0x22, 0x12,
+0x10, 0x14, 0xff, 0xfd, 0x90, 0xfa, 0xb7, 0xe4, 0x8d, 0xf0, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xb6,
+0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x6e, 0x05, 0x4c, 0x80, 0xd1,
+0x12, 0x1d, 0x22, 0x12, 0x10, 0x14, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0xfd, 0xa3, 0xe4,
+0x75, 0xf0, 0x02, 0x12, 0x1b, 0x1c, 0x7a, 0xf9, 0x79, 0x72, 0x7b, 0x01, 0x8b, 0x36, 0x8a, 0x37,
+0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1d, 0x28, 0x12, 0x26, 0x98, 0x8f,
+0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0xc1, 0xe5, 0x4c, 0x12, 0x1a, 0xe8, 0x12, 0x1c, 0xc1,
+0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0xfa, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x3c,
+0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 0x3a, 0x02,
+0x2c, 0xd8, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x64,
+0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f,
+0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d,
+0x79, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f,
+0x6e, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xf1, 0xe5, 0x35, 0x30,
+0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa,
+0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xd3, 0x90, 0xfa, 0xbe, 0xe0, 0x94, 0x01, 0x90, 0xfa,
+0xbd, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbe, 0xe0,
+0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 0x53, 0x35,
+0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0,
+0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02,
+0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1,
+0x03, 0x02, 0x0f, 0x6e, 0x7f, 0x01, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xd3, 0x90, 0xfa, 0xbe, 0xe0, 0x94,
+0x00, 0x90, 0xfa, 0xbd, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x64,
+0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff,
+0x02, 0x32, 0x6e, 0x90, 0xff, 0x01, 0x12, 0x1e, 0x24, 0xef, 0x12, 0x1a, 0xe8, 0x90, 0xfa, 0xb9,
+0x12, 0x1e, 0x24, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0xfa, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a,
+0xfa, 0x74, 0x03, 0x12, 0x1c, 0xb2, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 0x38, 0x82,
+0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0xfc, 0x09,
+0x7b, 0x02, 0x09, 0x9d, 0x04, 0x09, 0xbf, 0x05, 0x09, 0xeb, 0x06, 0x0a, 0x09, 0x07, 0x0a, 0x27,
+0x08, 0x0a, 0x45, 0x09, 0x0a, 0x63, 0x0b, 0x0b, 0x18, 0x80, 0x0d, 0xb7, 0x81, 0x0d, 0xe8, 0x82,
+0x0b, 0x5f, 0x83, 0x0b, 0xa8, 0x84, 0x0b, 0xc7, 0x85, 0x0c, 0x0c, 0x86, 0x0c, 0x57, 0x87, 0x0c,
+0xe8, 0x88, 0x0d, 0x73, 0x89, 0x0a, 0x81, 0x92, 0x0a, 0x81, 0x93, 0x0d, 0xa0, 0xb0, 0x0e, 0x9b,
+0xc0, 0x0e, 0xc7, 0xc1, 0x0e, 0xd8, 0xc2, 0x00, 0x00, 0x0f, 0x5d, 0xe5, 0x35, 0x20, 0xe7, 0x05,
+0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c,
+0x00, 0x7f, 0x07, 0x02, 0x11, 0x5e, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0xb4, 0xe5, 0x35, 0x20,
+0xe7, 0x05, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef,
+0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x5e, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0xb4, 0xe5,
+0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1e, 0x42, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b,
+0x70, 0x05, 0x7f, 0x02, 0x02, 0x31, 0xa9, 0x90, 0xfa, 0xb9, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50,
+0x02, 0x80, 0x03, 0x02, 0x32, 0x2c, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03,
+0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f,
+0x08, 0x02, 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f,
+0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02,
+0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12,
+0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x5e,
+0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71,
+0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x5e, 0x7f, 0x07,
+0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03,
+0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31,
+0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1d, 0x79, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5,
+0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05,
+0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1c, 0x22,
+0x12, 0x1e, 0x3b, 0x12, 0x25, 0xfa, 0x12, 0x1d, 0x89, 0x12, 0x1a, 0xbb, 0x60, 0x05, 0x12, 0x32,
+0x7a, 0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75,
+0x38, 0x75, 0x02, 0x2c, 0xd8, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0xb4, 0x12, 0x1d, 0x79, 0x60,
+0x05, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1e, 0x42, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x31, 0xa9,
+0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12,
+0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04,
+0xf5, 0x4c, 0x12, 0x1c, 0x22, 0x02, 0x32, 0x2c, 0x12, 0x1e, 0x4c, 0x12, 0x2a, 0xc7, 0x12, 0x1d,
+0x33, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xba, 0xf0, 0x78, 0x68, 0x12,
+0x1b, 0xd8, 0x90, 0x00, 0x02, 0x12, 0x1a, 0xbb, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12,
+0x1a, 0xfa, 0x90, 0xfa, 0xba, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6,
+0x8c, 0x83, 0x12, 0x1d, 0x3b, 0xef, 0xf0, 0x12, 0x32, 0x84, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x90,
+0xfa, 0xb9, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06,
+0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbe, 0xe0,
+0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3,
+0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbe, 0xe0, 0x42,
+0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1c, 0xe0, 0x90, 0xfa, 0xb9, 0xe0, 0xb4,
+0x01, 0x0a, 0x12, 0x1c, 0xc1, 0xe5, 0x90, 0x12, 0x1a, 0xe8, 0x80, 0x08, 0x12, 0x1c, 0xc1, 0xe5,
+0xb0, 0x12, 0x1a, 0xe8, 0x02, 0x0f, 0xf1, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x24, 0x13, 0x12, 0x1c,
+0xf1, 0x20, 0xe1, 0x33, 0x12, 0x1d, 0x80, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90,
+0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1e,
+0x56, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10,
+0xf0, 0x80, 0x04, 0x12, 0x1e, 0x5d, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x90, 0xfa, 0xb9, 0xe0,
+0xff, 0x24, 0x13, 0x12, 0x1c, 0xf1, 0x20, 0xe1, 0x39, 0x12, 0x1d, 0x80, 0xef, 0x24, 0xfc, 0x60,
+0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20,
+0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xba, 0xe0,
+0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54,
+0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x12, 0x1d, 0x71, 0x60, 0x4d, 0x04,
+0x60, 0x03, 0x02, 0x0c, 0xe3, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c,
+0xea, 0x30, 0xe1, 0x6f, 0x12, 0x1e, 0x2c, 0x02, 0x0c, 0xe3, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb,
+0x12, 0x1c, 0xed, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1e, 0x2c,
+0x80, 0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1e,
+0x2c, 0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xba, 0xe0,
+0x60, 0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0xea, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44,
+0x02, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0xed, 0x30, 0xe1, 0x13,
+0x30, 0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0,
+0x54, 0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x90, 0xfa, 0xb9, 0xe0, 0x24,
+0xfc, 0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0,
+0x44, 0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0,
+0x90, 0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0,
+0x44, 0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf,
+0xf0, 0x80, 0x3b, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0,
+0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3,
+0xef, 0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0,
+0xc2, 0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff,
+0x02, 0x31, 0xa9, 0x12, 0x1c, 0xe0, 0x90, 0xfa, 0xb9, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70,
+0x16, 0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x80, 0x0a, 0x90, 0xff, 0xb6,
+0xe0, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0xd8,
+0x90, 0xf9, 0x15, 0x74, 0x01, 0xf0, 0x90, 0xf9, 0x1c, 0x74, 0x19, 0xf0, 0x90, 0xf9, 0x66, 0x74,
+0xff, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0xe4, 0xff, 0x12, 0x31, 0xa9, 0x12, 0x1d, 0xe7, 0x7f,
+0x03, 0x12, 0x12, 0x61, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80,
+0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30,
+0xd3, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbf,
+0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb7, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54,
+0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xbc, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e,
+0x40, 0x08, 0x90, 0xfa, 0xc0, 0xe0, 0x90, 0xfa, 0xbc, 0xf0, 0x12, 0x0f, 0x98, 0xe5, 0x31, 0x45,
+0x30, 0x70, 0x73, 0x12, 0x1c, 0xfa, 0x90, 0xfa, 0xbf, 0x12, 0x1e, 0x06, 0x60, 0x27, 0xd3, 0xef,
+0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90,
+0xfa, 0xc0, 0xe0, 0x90, 0xfa, 0xbc, 0xf0, 0x12, 0x0f, 0x98, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46,
+0x12, 0x1c, 0xfa, 0x80, 0xd1, 0x75, 0x4c, 0x02, 0x90, 0xfa, 0xbf, 0xe4, 0xf0, 0xa3, 0x04, 0xf0,
+0x90, 0xfa, 0xb7, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90,
+0xfa, 0xc0, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x29, 0x60, 0x75, 0x30, 0x00, 0x8f,
+0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26,
+0x98, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x30, 0xe7,
+0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x67, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80,
+0x11, 0x90, 0xfa, 0xba, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x65, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02,
+0xc2, 0x94, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1e, 0x4c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80,
+0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x54, 0x03, 0x14, 0x60, 0x0a,
+0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91,
+0x80, 0x23, 0x12, 0x1e, 0x56, 0x12, 0x0f, 0xc0, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff,
+0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0xc0, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2,
+0x91, 0x12, 0x1e, 0x56, 0xf0, 0x90, 0xfa, 0xba, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f,
+0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80,
+0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1e, 0x5d, 0x12, 0x0f, 0xe0, 0x60, 0x04, 0xd2, 0x92, 0x80,
+0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0xe0, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92,
+0x80, 0x02, 0xd2, 0x92, 0x12, 0x1e, 0x5d, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30,
+0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0xb4, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x32,
+0x7a, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb6, 0x90, 0xfa, 0xb7, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
+0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb7, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1b,
+0x1c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa,
+0xb7, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x4a, 0x12, 0x29, 0x60, 0x75,
+0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x23, 0x61, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22,
+0xf0, 0x7f, 0x01, 0x12, 0x12, 0x61, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xbb, 0xf0, 0x54, 0xa0,
+0x22, 0x12, 0x26, 0x98, 0x8f, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22,
+0xf0, 0x7f, 0x01, 0x12, 0x12, 0x61, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xbb, 0xf0, 0x54, 0xa0,
+0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0xd8, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x02,
+0x32, 0x3f, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 0xd8, 0x12, 0x23, 0x61, 0x7e, 0x00, 0x8e, 0x30,
+0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb4, 0xe0, 0x22, 0xef, 0x90,
+0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd,
+0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70,
+0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0,
+0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c,
+0xff, 0x12, 0x10, 0xc0, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1d,
+0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff,
+0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82,
+0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83,
+0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3,
+0x80, 0xda, 0x12, 0x11, 0x57, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22,
+0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e,
+0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0xae, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02,
+0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 0xc0, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9,
+0x1d, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43,
+0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80,
+0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3,
+0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78,
+0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77,
+0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x11, 0x57, 0xd0, 0x06, 0xd0, 0x04,
+0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0,
+0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x11, 0xae, 0x80, 0xf4,
+0xef, 0x60, 0x31, 0x90, 0x31, 0x11, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff,
+0x12, 0x10, 0xc0, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1d,
+0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05,
+0x43, 0x12, 0x11, 0x57, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0xdc, 0xc0, 0x04,
+0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75,
+0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04,
+0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90,
+0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90,
+0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10,
+0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0xd2,
+0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10,
+0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04,
+0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f,
+0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f,
+0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f,
+0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8,
+0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7,
+0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0xae, 0x80, 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08,
+0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 0x12, 0x11, 0xae, 0x80, 0xee, 0xd0, 0x00, 0x22,
+0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8,
+0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83,
+0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f,
+0x75, 0xf0, 0x02, 0xa4, 0x24, 0xf3, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93,
+0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24,
+0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82,
+0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76,
+0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x31, 0x11, 0xe4,
+0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f,
+0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75,
+0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1d,
+0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6,
+0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0,
+0x07, 0x12, 0x12, 0x89, 0xad, 0x07, 0xaf, 0x02, 0x12, 0x12, 0xa0, 0xd0, 0x07, 0xa3, 0xa3, 0xa3,
+0xdf, 0xce, 0x12, 0x11, 0xae, 0x80, 0xc1, 0x8f, 0x24, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xb5, 0xa3,
+0xa3, 0xe0, 0xa3, 0x30, 0xe7, 0x28, 0x78, 0x7e, 0x12, 0x22, 0x99, 0xe0, 0x44, 0x01, 0xf0, 0x12,
+0x22, 0xfa, 0x12, 0x22, 0x9d, 0xe0, 0x20, 0xe0, 0xf6, 0x12, 0x23, 0x50, 0x74, 0x02, 0xf0, 0x12,
+0x22, 0xda, 0xe0, 0xa3, 0x30, 0xe5, 0x07, 0x12, 0x23, 0x50, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x80,
+0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0x12, 0x23,
+0x39, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x22, 0xa1, 0xed, 0xf0, 0x12, 0x23, 0x06, 0x24, 0x07, 0x12,
+0x22, 0xa1, 0xe0, 0xff, 0x12, 0x23, 0x5a, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0x90, 0xf9,
+0x16, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0xb7, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25,
+0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0,
+0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x22, 0xb5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12,
+0x23, 0x39, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0xed, 0x12, 0x23, 0x5a, 0x24,
+0x07, 0x12, 0x22, 0xa1, 0xed, 0xf0, 0x12, 0x22, 0xa9, 0xe0, 0x30, 0xe6, 0x0a, 0x12, 0x23, 0x41,
+0x24, 0x09, 0x12, 0x22, 0xa1, 0xe4, 0xf0, 0x12, 0x22, 0xa9, 0xe0, 0xff, 0x30, 0xe7, 0x1b, 0x12,
+0x23, 0x1e, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x60, 0x09, 0x12, 0x22, 0xa9, 0xef, 0x44, 0x02,
+0xf0, 0x80, 0x07, 0x12, 0x22, 0xa9, 0xef, 0x54, 0xfd, 0xf0, 0x78, 0x7e, 0x12, 0x22, 0xb7, 0xa3,
+0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x22, 0xe0, 0xa3,
+0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x22, 0xa1, 0xe0,
+0x90, 0x32, 0x51, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x23, 0x1e, 0x24, 0x06, 0x12, 0x22,
+0xa1, 0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x23, 0x29, 0x24,
+0x04, 0x12, 0x22, 0xa1, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x23, 0x39, 0xf5, 0x82, 0x8a,
+0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x5a, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0xff, 0x8d,
+0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf,
+0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07,
+0x10, 0x12, 0x22, 0xa9, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1,
+0x69, 0x12, 0x23, 0x1e, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x12, 0x1b, 0xfc, 0x15, 0x2c, 0x00,
+0x15, 0x60, 0x01, 0x15, 0x65, 0x03, 0x15, 0x60, 0x05, 0x15, 0x65, 0x07, 0x15, 0x60, 0x09, 0x15,
+0x65, 0x0b, 0x15, 0x60, 0x0d, 0x15, 0x65, 0x0f, 0x00, 0x00, 0x15, 0x6d, 0xe5, 0x24, 0x64, 0x03,
+0x70, 0x21, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80,
+0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07,
+0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d,
+0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x23, 0x27,
+0x24, 0x04, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff,
+0x12, 0x22, 0xa9, 0xe0, 0xfe, 0x54, 0x03, 0x70, 0x03, 0x02, 0x16, 0x60, 0xee, 0x20, 0xe1, 0x03,
+0x02, 0x16, 0x5d, 0x08, 0x12, 0x23, 0x20, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x12, 0x1b, 0xfc,
+0x15, 0xbf, 0x00, 0x15, 0xf5, 0x01, 0x15, 0xf5, 0x03, 0x16, 0x29, 0x05, 0x16, 0x29, 0x07, 0x16,
+0x0f, 0x09, 0x16, 0x0f, 0x0b, 0x16, 0x43, 0x0d, 0x16, 0x43, 0x0f, 0x00, 0x00, 0x16, 0x60, 0xe5,
+0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53,
+0x07, 0x7f, 0x02, 0x16, 0x60, 0x43, 0x07, 0x80, 0x02, 0x16, 0x60, 0x30, 0x94, 0x05, 0x53, 0x07,
+0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70,
+0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef,
+0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5,
+0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e,
+0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff,
+0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07,
+0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80,
+0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f,
+0x12, 0x22, 0xda, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03,
+0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec,
+0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43,
+0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03,
+0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed,
+0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0xdc,
+0xa3, 0xef, 0xf0, 0x12, 0x32, 0x84, 0x7f, 0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3,
+0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcf, 0xe4,
+0xfd, 0x12, 0x23, 0x61, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1b, 0x1c, 0x12, 0x19,
+0x92, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa,
+0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xcf,
+0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5,
+0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0xe5, 0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23,
+0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12,
+0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02,
+0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90,
+0xf9, 0x16, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4,
+0x41, 0x12, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1,
+0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x44,
+0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 0x0c, 0xe5, 0x23, 0x64, 0x43, 0x60, 0x06, 0xe5, 0x23,
+0x64, 0x44, 0x70, 0x2e, 0x90, 0xf9, 0x16, 0xe0, 0xff, 0xe5, 0x23, 0xb4, 0x44, 0x04, 0x7e, 0x40,
+0x80, 0x02, 0x7e, 0x00, 0xee, 0x24, 0x80, 0x4f, 0x90, 0xf9, 0x16, 0xf0, 0xa3, 0xe0, 0xff, 0xe5,
+0x23, 0xb4, 0x44, 0x04, 0x7e, 0x40, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x24, 0x80, 0x4f, 0x90, 0xf9,
+0x17, 0xf0, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x19, 0x92, 0x90, 0xff,
+0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1e, 0x34,
+0x12, 0x1c, 0xe0, 0x12, 0x1e, 0x3b, 0x90, 0xf9, 0x6a, 0x12, 0x1b, 0xf3, 0x90, 0xf9, 0x6f, 0x12,
+0x1b, 0xf3, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81,
 0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23, 
-0x12, 0x1c, 0xa7, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1c, 0xb5, 0xf5, 0x83, 0xe4, 0xf0, 
-0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x31, 
-0x4d, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x31, 0x5a, 0xe4, 0x93, 0xff, 
-0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1c, 0x97, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 
+0x12, 0x1d, 0x57, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1d, 0x65, 0xf5, 0x83, 0xe4, 0xf0,
+0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x32,
+0x0a, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x32, 0x17, 0xe4, 0x93, 0xff,
+0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1d, 0x47, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0,
 0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 
-0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0x28, 0xce, 0xc3, 0x13, 0xce, 
-0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1c, 0xf8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0x1e, 0xe4, 0xf5, 
-0x23, 0xe5, 0x23, 0x90, 0x31, 0x47, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0, 
-0x24, 0x4e, 0xf5, 0x82, 0xe4, 0x34, 0x31, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 
-0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0x97, 0x12, 0x1d, 0x06, 0x24, 0x47, 0xf5, 0x82, 
-0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 
-0x1c, 0xf8, 0xef, 0xf0, 0x12, 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 
-0x0b, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0x1e, 
+0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0xd8, 0xce, 0xc3, 0x13, 0xce,
+0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1d, 0xa8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0xce, 0xe4, 0xf5,
+0x23, 0xe5, 0x23, 0x90, 0x32, 0x04, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0,
+0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x34, 0x32, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7,
+0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1d, 0x47, 0x12, 0x1d, 0xb6, 0x24, 0x47, 0xf5, 0x82,
+0xe4, 0x34, 0xff, 0x12, 0x1c, 0xc8, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12,
+0x1d, 0xa8, 0xef, 0xf0, 0x12, 0x1c, 0xcf, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d,
+0xbb, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0xce,
 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 
-0xf0, 0x02, 0x18, 0xb7, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0xea, 0x12, 0x1d, 0x06, 
-0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 
-0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 
-0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x05, 0xf5, 0x82, 
+0xf0, 0x02, 0x19, 0x67, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1d, 0x9a, 0x12, 0x1d, 0xb6,
+0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0xc8, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8,
+0xf9, 0x12, 0x1d, 0xbb, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12,
+0x1c, 0xcf, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0xbb, 0x24, 0x05, 0xf5, 0x82,
 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 
 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 
 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02, 
-0x17, 0xe1, 0x90, 0x31, 0x4c, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1c, 0xe8, 0xe4, 0xf0, 
-0x90, 0x31, 0x4b, 0x93, 0xff, 0xf6, 0x12, 0x1c, 0x95, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 
-0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
-0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0xe7, 0x09, 0xf6, 0x08, 
+0x18, 0x91, 0x90, 0x32, 0x09, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1d, 0x98, 0xe4, 0xf0,
+0x90, 0x32, 0x08, 0x93, 0xff, 0xf6, 0x12, 0x1d, 0x45, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05,
+0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12,
+0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x26, 0x98, 0xe7, 0x09, 0xf6, 0x08,
 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 
 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 
 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 
@@ -445,7 +456,7 @@
 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 
 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 
 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19, 
-0x4c, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 
+0xfc, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb,
 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 
 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 
 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 
@@ -469,364 +480,365 @@
 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, 
 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 
 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 
-0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 
+0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25,
 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12, 
-0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06, 
-0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 
-0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0x38, 0x04, 0x25, 
+0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06,
+0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38,
+0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0xe8, 0x04, 0x25,
 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 
-0x38, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab, 
-0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 
-0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 
+0xe8, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab,
+0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35,
+0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8,
 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54, 
 0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 
 0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 
-0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x6f, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x12, 
-0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 
-0x00, 0xc3, 0x90, 0xfa, 0xbd, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbc, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
-0xb4, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5, 
-0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb1, 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 
+0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x72, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x13,
+0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xbc, 0xe0, 0xff, 0x7e,
+0x00, 0xc3, 0x90, 0xfa, 0xc0, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x9e, 0xf0, 0x90, 0xfa,
+0xb7, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5,
+0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb4, 0x90, 0xfa, 0xb7, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
 0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 
 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 
 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 
 0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 
-0x22, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, 
-0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9, 
-0x6c, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 
+0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22,
+0x90, 0xfa, 0xbe, 0xe0, 0x90, 0xfa, 0xba, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9,
+0x6f, 0x12, 0x1b, 0xea, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00,
 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 
 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 
-0xa4, 0x22, 0x74, 0xaf, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 
+0xa4, 0x22, 0x74, 0xb2, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0,
 0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 
 0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 
 0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 
-0x65, 0xf0, 0x22, 0x12, 0x1b, 0x1c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 
-0xfa, 0x79, 0xb4, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 
-0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x67, 0x02, 0x1b, 0x3a, 0x90, 0xff, 0xa4, 0xe0, 
+0x65, 0xf0, 0x22, 0x12, 0x1b, 0xcc, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a,
+0xfa, 0x79, 0xb7, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0,
+0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x6a, 0x02, 0x1b, 0xea, 0x90, 0xff, 0xa4, 0xe0,
 0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79, 
-0x6f, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbb, 0xe0, 
-0xff, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 
-0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0x06, 0x12, 0x22, 
-0x4a, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x0a, 
-0x12, 0x22, 0x52, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0x4a, 0x12, 
-0x22, 0x4a, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x22, 0x56, 0x24, 
-0x04, 0x12, 0x21, 0xf3, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55, 
+0x72, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbe, 0xe0,
+0xff, 0x90, 0xfa, 0xba, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4,
+0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x4b, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0xc7, 0x12, 0x22,
+0xfa, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x0a,
+0x12, 0x23, 0x02, 0x24, 0x0a, 0x12, 0x22, 0xa1, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0xfa, 0x12,
+0x22, 0xfa, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x23, 0x06, 0x24,
+0x04, 0x12, 0x22, 0xa1, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55,
 0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06, 
-0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x0c, 0xef, 
-0x12, 0x1a, 0x4a, 0x78, 0x80, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 
-0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 
-0xe5, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 
-0xe5, 0x53, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 
-0xe5, 0x53, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 
-0x80, 0xe5, 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 
-0x08, 0xe5, 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 
-0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 
-0x12, 0x1a, 0xef, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 
-0x2c, 0x90, 0x00, 0x08, 0xef, 0x12, 0x1a, 0x4a, 0x80, 0x0a, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x08, 
-0xe4, 0x12, 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x07, 0xef, 0x12, 
-0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0x4a, 0x90, 
-0x00, 0x07, 0x12, 0x1a, 0x0b, 0x70, 0x13, 0x12, 0x22, 0x2d, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 
-0xfa, 0x12, 0x19, 0xf2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0x38, 0x12, 0x22, 0x78, 0x24, 0x08, 0x12, 
-0x21, 0xf3, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 
-0xfd, 0xee, 0xed, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0xef, 0x12, 
-0x31, 0xc7, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0x90, 0xfa, 0xe3, 0xe0, 
-0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xd7, 
-0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xff, 0x7e, 0x00, 0x90, 0xfa, 
-0xd3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1a, 
-0x98, 0xff, 0x90, 0xfa, 0xd5, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 
-0x50, 0x8f, 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 
-0xd8, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd6, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 
-0xfa, 0xda, 0xf0, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0x90, 0xfa, 0xd3, 0xe0, 0x94, 0x00, 0x50, 
-0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 
-0x2d, 0x5a, 0x90, 0xfa, 0xd3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xd7, 
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xda, 
-0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd4, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 
-0xe0, 0xff, 0x22, 0x12, 0x2d, 0x5a, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 
-0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 
-0x01, 0x90, 0xfa, 0xd5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xda, 0xe0, 0xf5, 0x4a, 0x12, 
-0x28, 0x9f, 0x90, 0xfa, 0xd9, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 
-0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x20, 0xbb, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0x03, 0x78, 
-0x71, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 
-0x90, 0xfa, 0x91, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 0x22, 0x78, 
-0x72, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 
-0x90, 0xfa, 0x93, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb0, 0x74, 0x01, 0xf0, 0x22, 0x90, 
-0xfa, 0x9d, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0x03, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 
-0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 
-0xa6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 
-0xcb, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2c, 0xb4, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xcb, 0xe0, 
-0xff, 0x74, 0x34, 0x90, 0xfa, 0x95, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa7, 0xe0, 0xa3, 
-0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 
-0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xb6, 
-0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 
-0x2c, 0xb4, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x97, 0xf0, 
-0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 
-0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 
-0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc9, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 
-0x12, 0x1b, 0x4c, 0x21, 0xbb, 0x26, 0x21, 0xbb, 0x2e, 0x21, 0x5e, 0x30, 0x21, 0x5e, 0x32, 0x21, 
-0x6c, 0x38, 0x21, 0x7e, 0x3a, 0x21, 0xb0, 0x3e, 0x21, 0x9b, 0x44, 0x21, 0x90, 0x46, 0x21, 0xa6, 
-0x50, 0x21, 0xa6, 0x52, 0x21, 0xa6, 0x54, 0x21, 0xa6, 0x56, 0x00, 0x00, 0x21, 0xc0, 0x90, 0xfa, 
-0xc9, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x16, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 
-0x7f, 0x03, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 
-0x7d, 0x01, 0x7f, 0x02, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x16, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 
-0x06, 0x12, 0x11, 0x16, 0x80, 0x28, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x12, 0x20, 0x18, 0x80, 0x1e, 
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x16, 0x80, 0x13, 0x12, 0x27, 0x8d, 0x80, 0x0e, 
-0x90, 0xfa, 0xc9, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2c, 0xb4, 0xd0, 0x07, 
-0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 
-0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 
-0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x12, 0x25, 0x24, 0xf5, 
-0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 
-0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 
-0xff, 0x7a, 0x31, 0x79, 0x99, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x19, 0xcc, 0xff, 0x90, 0xf9, 0x6c, 
-0x02, 0x1b, 0x3a, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x04, 0x02, 0x1a, 0x0b, 0xe6, 
-0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6, 
-0xff, 0x22, 0xed, 0x12, 0x1a, 0x4a, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 
-0xfa, 0xcb, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x08, 0xe6, 
-0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x09, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 
-0x83, 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 
-0xfb, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, 0x22, 
-0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x02, 
-0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
-0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xce, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, 0xe0, 
-0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xce, 0xe0, 
-0xff, 0x90, 0xfa, 0xd1, 0xe4, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xd1, 
-0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xcf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xce, 0xe0, 
-0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x04, 0x12, 0x1a, 
-0x6c, 0x02, 0x22, 0xb1, 0x90, 0xfa, 0xd0, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xcf, 0xe0, 0x34, 
-0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1a, 0xd0, 0x7f, 0x00, 0x22, 0x7b, 
-0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x6c, 0x85, 
-0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0x8f, 0x62, 0x12, 0x2a, 0x06, 0x12, 0x22, 
-0x4a, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, 0x08, 
-0x12, 0x22, 0x3f, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x22, 0x56, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
-0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 
-0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, 0x24, 
-0x04, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0x74, 
-0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x21, 0xf3, 0xc0, 
-0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x96, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 
-0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 
-0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 
-0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 
-0x10, 0x03, 0x7f, 0x02, 0x12, 0x12, 0x19, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 
-0xb1, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, 0xd2, 
-0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7c, 
-0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x7a, 
-0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 
-0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe4, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 
-0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 
-0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 
-0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7a, 0xe0, 
-0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe4, 0xe0, 
-0xf5, 0xa8, 0x02, 0x10, 0x86, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 
-0xc0, 0x12, 0x1b, 0x43, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x43, 0x90, 0xfa, 
-0xc4, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x3a, 0xe9, 0x24, 
-0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 
-0x5e, 0x12, 0x2d, 0x48, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, 0xbe, 
-0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc0, 0x12, 0x2d, 0x1d, 0xff, 
-0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0x1d, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, 0xf6, 
-0x12, 0x2d, 0x1a, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0x23, 0x75, 0xf0, 0x02, 0x12, 
-0x1a, 0x6c, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0xab, 0x5c, 0xaa, 0x5d, 
-0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x0b, 0x30, 0xe4, 0x03, 0x12, 0x2d, 0x32, 0x78, 0x82, 
-0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbf, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, 0x90, 
-0xfa, 0xbf, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 
-0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x24, 0x95, 
-0x80, 0x62, 0x12, 0x2d, 0x53, 0x12, 0x1f, 0x2c, 0x90, 0xfa, 0xbf, 0xef, 0xf0, 0x80, 0x55, 0x90, 
-0xfa, 0xbf, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 
-0x12, 0x2c, 0x5f, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, 0x01, 
-0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xfd, 
-0x90, 0x00, 0x08, 0x12, 0x1a, 0x98, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 
-0x03, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 
-0xbf, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x02, 0x12, 0x1a, 
-0x4a, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, 0xe5, 
-0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2d, 0x82, 0x70, 0x16, 0x12, 0x2d, 0xa1, 0xe5, 0x2d, 
-0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x26, 0x64, 0x40, 0x0b, 0x7f, 0x00, 
-0x22, 0x12, 0x2d, 0xa1, 0x12, 0x26, 0x64, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 
-0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 
-0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0x04, 0x40, 
-0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 
-0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2d, 0x94, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, 0xe4, 
-0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0x04, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2d, 
-0x94, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0x1b, 0x12, 0x10, 0x03, 
-0x78, 0x84, 0x12, 0x22, 0x82, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x30, 0xec, 0x02, 0x26, 0xfb, 
-0x78, 0x84, 0xe6, 0xf9, 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, 0x03, 
-0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, 0x04, 
-0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x39, 
-0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x80, 
-0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, 0x54, 
-0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 
-0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x17, 0xe0, 0x04, 0xf0, 0xaf, 
-0x01, 0x12, 0x22, 0x33, 0xfd, 0x12, 0x2f, 0x49, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x75, 0xa8, 
-0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x27, 0x48, 0x02, 0x30, 0xcf, 
-0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 
-0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 
-0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 
-0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0x4c, 0xe4, 0x7e, 0x01, 0x93, 0x60, 
-0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 
-0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 
-0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 
-0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x22, 
-0x12, 0x1d, 0x12, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x2f, 0x77, 0x12, 
-0x1d, 0x12, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x22, 
-0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1d, 0x53, 0x60, 0x2c, 0x12, 0x2c, 0xb4, 
-0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 
-0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0x9d, 0x12, 0x1b, 0x1c, 0xe0, 0xa3, 0x30, 
-0xe6, 0x33, 0x12, 0x1d, 0x12, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 
-0x95, 0x12, 0x1d, 0x53, 0x60, 0x16, 0x12, 0x2c, 0xb4, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 
-0x22, 0x90, 0xfa, 0x95, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, 0x22, 
-0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 
-0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 
-0x1c, 0x11, 0x12, 0x1a, 0x38, 0x0f, 0x12, 0x1c, 0x00, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x3a, 
-0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, 0x39, 
-0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x84, 
-0x12, 0x1d, 0x76, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 
-0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0x0b, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 
-0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x16, 0x12, 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 
-0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 0x12, 0x31, 0xb1, 0x22, 0x8b, 
-0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2d, 0x82, 0x70, 0x16, 
-0x12, 0x2d, 0xa1, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x29, 
-0x14, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x29, 0x14, 0x50, 0xf8, 0xe4, 0xf5, 
-0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0x04, 0x40, 0x03, 
-0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, 0x46, 
-0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0x04, 0x40, 0x03, 0x7f, 0x18, 
-0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x19, 0xf2, 0x90, 0xff, 0xf1, 
-0xf0, 0x02, 0x31, 0x1b, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0x1b, 0x7b, 0x01, 0x7a, 
-0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x09, 0x12, 
-0x1a, 0x6c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
-0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xff, 0xf7, 0xe5, 
-0x23, 0x12, 0x29, 0x78, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 
-0x74, 0x06, 0x12, 0x29, 0x78, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 
-0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 
-0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 
-0x02, 0x25, 0xd7, 0x90, 0xff, 0x93, 0x74, 0x2a, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 
-0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, 0x15, 
-0xf0, 0xa3, 0xf0, 0x12, 0x2a, 0x78, 0x12, 0x16, 0x42, 0x12, 0x2f, 0xcd, 0x7e, 0x07, 0x7f, 0xd0, 
-0x12, 0x11, 0xe2, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0xfc, 0xe4, 0x78, 0x77, 0xf6, 0x78, 0x77, 
-0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, 0x06, 
-0x80, 0xec, 0x7f, 0x03, 0x12, 0x2e, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 0x04, 
-0x12, 0x2e, 0xb3, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 0xe0, 
-0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, 0x12, 
-0x11, 0x66, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, 0x76, 
-0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, 0xff, 
-0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, 0x9b, 
-0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x22, 0x92, 0x7b, 0x01, 0x7a, 0xff, 
-0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0x31, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, 0xa4, 
-0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x22, 0x92, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0x31, 0x78, 
-0x6d, 0xef, 0x12, 0x22, 0x92, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, 0xe0, 
-0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 
-0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7e, 0x00, 0x90, 0xfa, 0xe1, 0xee, 0xf0, 
-0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x52, 0x09, 0x90, 0xf9, 
-0x15, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe1, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 
-0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x10, 
-0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe3, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x54, 0xef, 0xf0, 
-0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x12, 0x10, 0x03, 0x78, 0x8a, 0xef, 0xf6, 0x12, 
-0x2a, 0x06, 0x12, 0x22, 0x33, 0x30, 0xe0, 0x25, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 
-0x6b, 0x12, 0x1b, 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 
-0xe4, 0x12, 0x1a, 0x4a, 0x80, 0xe9, 0x12, 0x22, 0x07, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x22, 0x33, 
-0x30, 0xe1, 0x1e, 0x12, 0x21, 0xe9, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x31, 0x5c, 0x78, 0x68, 0x12, 
-0x1b, 0x28, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0x4a, 0x12, 0x21, 0xe9, 0xe0, 0x44, 0x80, 
-0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x03, 0x68, 0x01, 0xff, 
-0x48, 0x03, 0x6b, 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x95, 0x00, 0x00, 0x00, 
-0x00, 0x44, 0xfa, 0x91, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xaf, 0x00, 0x00, 0x42, 0xfa, 0x7b, 
-0x00, 0x00, 0x42, 0xfa, 0x79, 0x00, 0x00, 0x42, 0xf9, 0x6a, 0xff, 0xff, 0x42, 0xfa, 0x77, 0x00, 
-0x00, 0x43, 0xf9, 0x18, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x65, 0x20, 0x41, 0xf9, 0x66, 0x20, 0x41, 
-0xf9, 0x63, 0x00, 0x41, 0xf9, 0x64, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 
-0x15, 0x00, 0x00, 0x41, 0xf9, 0x17, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 
-0x10, 0x03, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x30, 0x93, 0x12, 0x30, 0xec, 0x78, 0x85, 0xe6, 0xff, 
-0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 
-0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, 0x19, 
-0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
-0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x14, 0xf0, 0xe0, 
-0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0x86, 0x12, 0x1d, 0x6c, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 
-0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, 0x40, 
-0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 
-0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1d, 0x84, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, 0x1c, 
-0x11, 0x12, 0x19, 0xf2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 
-0xf0, 0x0e, 0x12, 0x1c, 0x00, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 
-0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2d, 0x48, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 
-0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xe5, 0x5b, 
-0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x43, 0xe4, 0x90, 0xfa, 
-0xbf, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, 0x50, 
-0x12, 0x12, 0x2d, 0x1a, 0xff, 0x12, 0x2d, 0x23, 0x12, 0x2d, 0x36, 0x78, 0x8b, 0x06, 0x12, 0x2d, 
-0x32, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x31, 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x74, 
-0xf6, 0x54, 0x0f, 0x12, 0x1c, 0xf8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, 0x29, 
-0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 
-0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 
-0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
-0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x90, 
-0x00, 0x03, 0x12, 0x1a, 0x0b, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x3a, 
-0x02, 0x19, 0xf2, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x3a, 0xef, 0x12, 0x1a, 0x38, 0x90, 0xfa, 0xc7, 
-0xe4, 0x22, 0x90, 0xfa, 0xc1, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1a, 0x6c, 0x90, 0x00, 0x08, 0x12, 
-0x1a, 0x98, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0x90, 0xfa, 
-0xbe, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xda, 0xe0, 0xff, 0x7e, 
-0x00, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd3, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
-0xd5, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, 0xf5, 
-0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe3, 
-0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, 0x1a, 
-0x38, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, 0xb4, 
-0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0x32, 0x7f, 0x02, 0x02, 0x31, 0x32, 0xaf, 0x64, 0x12, 0x2a, 
-0x06, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1c, 0x83, 0xe0, 
-0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, 0x31, 
-0x32, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0x32, 0x30, 0x09, 0x07, 0x12, 0x1c, 0x83, 0xe0, 0x44, 
-0x80, 0xf0, 0x12, 0x31, 0xc7, 0x22, 0x12, 0x10, 0x03, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 
-0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 
-0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 
-0xf0, 0x80, 0x0d, 0x12, 0x1d, 0x2f, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 
-0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xb0, 0x12, 0x1d, 0x37, 0x02, 0x10, 0x86, 
-0x12, 0x10, 0x03, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0x06, 0x90, 0xf9, 0x67, 0x12, 
-0x1b, 0x3a, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, 0x08, 
-0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0x25, 0x12, 0x31, 0xc7, 
-0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x3f, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x8f, 0x63, 0x12, 
-0x2a, 0x06, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 
-0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
-0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 
-0x7f, 0x00, 0x22, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 0x78, 0x7e, 0x12, 
-0x21, 0xeb, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x22, 0x4a, 0x12, 0x21, 0xef, 0xe0, 0x20, 0xe0, 0xf6, 
-0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 
-0xaf, 0x23, 0x12, 0x13, 0x3f, 0x22, 0x12, 0x10, 0x03, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x4a, 0x24, 
-0x06, 0x12, 0x21, 0xf1, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x03, 0x12, 0x22, 0x52, 0x24, 
-0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x4a, 0x12, 0x31, 0xc7, 0x7d, 0x02, 
-0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0xae, 0x05, 0x12, 0x1c, 0xde, 0xef, 0x12, 0x1a, 
-0x4a, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 
-0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 
-0x12, 0x1a, 0x4a, 0xaf, 0x06, 0x12, 0x31, 0xb1, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 
-0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 
-0x74, 0x6e, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 0x74, 0x96, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 
-0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 
-0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 
-0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 
-0x00, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
-0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 
-0x40, 0x05, 0x12, 0x28, 0x16, 0x80, 0x03, 0x12, 0x31, 0xbd, 0x02, 0x10, 0x86, 0x90, 0xff, 0xfc, 
-0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 
-0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 
-0xf0, 0x80, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 
-0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x19, 
-0x12, 0x1d, 0x46, 0x02, 0x10, 0x86, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 
-0x70, 0x02, 0x15, 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 
-0x12, 0x0f, 0xdc, 0x80, 0xe5, 0x22, 0x11, 0x94, 0x2d, 0xf6, 0x23, 0xef, 0x31, 0xa3, 0x2f, 0xf4, 
-0x2f, 0xa2, 0x30, 0xb2, 0x2e, 0xe6, 0x26, 0x6d, 0x2b, 0xaf, 0x30, 0x55, 0x30, 0x74, 0x1d, 0xb4, 
-0x2e, 0x40, 0x2a, 0xe8, 0x0e, 0x12, 0x10, 0x03, 0x78, 0x86, 0x12, 0x22, 0x82, 0x20, 0xe1, 0x07, 
-0x7f, 0x12, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x23, 0x49, 0x12, 0x30, 
-0xec, 0x02, 0x10, 0x86, 0x12, 0x10, 0x03, 0x78, 0x87, 0x12, 0x22, 0x82, 0x20, 0xe2, 0x07, 0x7f, 
-0x11, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2e, 0x7d, 0x12, 0x30, 0xec, 
-0x02, 0x10, 0x86, 0x8f, 0x61, 0x12, 0x2e, 0x7d, 0xaf, 0x61, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 
-0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 
-0x3f, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
-0x05, 0x12, 0x2c, 0x07, 0x80, 0x06, 0x12, 0x1d, 0x64, 0x12, 0x1d, 0x6c, 0x02, 0x10, 0x86, 0x12, 
-0x29, 0x93, 0x12, 0x12, 0xbb, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 
-0x58, 0x12, 0x29, 0x1d, 0x12, 0x12, 0xf7, 0x12, 0x11, 0x74, 0x80, 0xe3, 0x12, 0x1c, 0xde, 0xef, 
-0x12, 0x1a, 0x4a, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 
-0x12, 0x31, 0xb1, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 
-0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 
-0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 
-0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 0x1c, 0x95, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 
-0x1c, 0xe8, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 
-0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 
-0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 
-0x3b, 0x39, 0x85, 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 
-0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x31, 0x47, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 
-0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x12, 0x10, 0x03, 0x7f, 0x02, 0x12, 0x10, 0x92, 0x12, 0x1d, 0x46, 0x02, 0x10, 
-0x86, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0x30, 0x12, 0x2c, 0x07, 0x22, 0x12, 0x1d, 0x6c, 
-0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x64, 0x22, 0xc2, 0x08, 0x22, 
+0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x0c, 0xef,
+0x12, 0x1a, 0xfa, 0x12, 0x22, 0xb5, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0x0c,
+0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 0xe5, 0x0e,
+0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 0xe5, 0x53,
+0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 0xe5, 0x53,
+0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 0x80, 0xe5,
+0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 0x08, 0xe5,
+0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43,
+0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 0x12, 0x1b,
+0x9f, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 0xe7, 0x90,
+0x00, 0x08, 0xef, 0x12, 0x1a, 0xfa, 0x80, 0x0a, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x08, 0xe4, 0x12,
+0x1a, 0xfa, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x07, 0xef, 0x12, 0x1a, 0xfa,
+0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0xfa, 0x90, 0x00, 0x07,
+0x12, 0x1a, 0xbb, 0x70, 0x13, 0x12, 0x22, 0xe8, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 0xfa, 0x12,
+0x1a, 0xa2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0xe8, 0x12, 0x23, 0x27, 0x24, 0x08, 0x12, 0x22, 0xa1,
+0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0xee,
+0xed, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x9f, 0x12, 0x32, 0x84,
+0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0xb4, 0x02, 0x10, 0xce, 0x90, 0xfa, 0xe6, 0xe0, 0xb4, 0x03,
+0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xda, 0xee, 0xf0,
+0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, 0xff, 0x7e, 0x00, 0x90, 0xfa, 0xd6, 0xee,
+0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1b, 0x48, 0xff,
+0x90, 0xfa, 0xd8, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 0x50, 0x8f,
+0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 0xdb, 0xe0,
+0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd9, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 0xfa, 0xdd,
+0xf0, 0xc3, 0x90, 0xfa, 0xd7, 0xe0, 0x9f, 0x90, 0xfa, 0xd6, 0xe0, 0x94, 0x00, 0x50, 0x06, 0xa3,
+0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x12, 0x20, 0xa9, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2e, 0x2b,
+0x90, 0xfa, 0xd6, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xda, 0xe0, 0xfc,
+0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x80,
+0x08, 0x90, 0xfa, 0xd7, 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x12, 0x20, 0xa9, 0x60, 0x03, 0xe0, 0xff,
+0x22, 0x12, 0x2e, 0x2b, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x2d, 0xf5,
+0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 0x01, 0x90,
+0xfa, 0xd8, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xdd, 0xe0, 0xf5, 0x4a, 0x12, 0x29, 0x60,
+0x90, 0xfa, 0xdc, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 0x2e, 0x24,
+0xfe, 0x70, 0x03, 0x02, 0x21, 0x69, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0xb1, 0x78, 0x71, 0xe6,
+0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 0x90, 0xfa,
+0x94, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb2, 0x74, 0x01, 0xf0, 0x22, 0x78, 0x72, 0xe6,
+0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 0x90, 0xfa,
+0x96, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb3, 0x74, 0x01, 0xf0, 0x22, 0x90, 0xfa, 0xa0,
+0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0xb1, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0,
+0xa3, 0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xa6, 0x12,
+0x23, 0x0d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xce, 0xe0,
+0xff, 0x74, 0x34, 0xfe, 0x12, 0x2d, 0x85, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74,
+0x34, 0x90, 0xfa, 0x98, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xaa, 0xe0, 0xa3, 0x30, 0xe5,
+0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xff,
+0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x23, 0x0d, 0x90, 0xff, 0xb6, 0xe0, 0x90,
+0xfa, 0xcd, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 0x2d, 0x85,
+0xef, 0x70, 0x0e, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x9a, 0xf0, 0xef, 0xa3,
+0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0,
+0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x90,
+0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xcc, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 0x12, 0x1b,
+0xfc, 0x22, 0x69, 0x26, 0x22, 0x69, 0x2e, 0x22, 0x0c, 0x30, 0x22, 0x0c, 0x32, 0x22, 0x1a, 0x38,
+0x22, 0x2c, 0x3a, 0x22, 0x5e, 0x3e, 0x22, 0x49, 0x44, 0x22, 0x3e, 0x46, 0x22, 0x54, 0x50, 0x22,
+0x54, 0x52, 0x22, 0x54, 0x54, 0x22, 0x54, 0x56, 0x00, 0x00, 0x22, 0x6e, 0x90, 0xfa, 0xcc, 0xe0,
+0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x5e, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x03,
+0x12, 0x11, 0x5e, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 0x7d, 0x01,
+0x7f, 0x02, 0x12, 0x11, 0x5e, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 0x7c, 0x00,
+0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x5e, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x06, 0x12,
+0x11, 0x5e, 0x80, 0x28, 0x90, 0xfa, 0xcc, 0xe0, 0xff, 0x12, 0x20, 0xc6, 0x80, 0x1e, 0x7c, 0x00,
+0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x5e, 0x80, 0x13, 0x12, 0x28, 0x4e, 0x80, 0x0e, 0x90, 0xfa,
+0xcc, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2d, 0x85, 0xd0, 0x07, 0xd0, 0x06,
+0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82,
+0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 0x04, 0x8e,
+0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x13, 0x25, 0x24, 0xf5, 0x82, 0xe4,
+0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22,
+0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a,
+0x32, 0x79, 0x56, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x1a, 0x7c, 0x78, 0x80, 0xe6, 0xfc, 0x08, 0xe6,
+0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0xff, 0x90, 0xf9, 0x6f, 0x02, 0x1b, 0xea, 0x90, 0xf9,
+0x6a, 0x12, 0x1b, 0xea, 0x90, 0x00, 0x04, 0x02, 0x1a, 0xbb, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6,
+0xff, 0x22, 0xed, 0x12, 0x1a, 0xfa, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90,
+0xfa, 0xce, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x80,
+0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83,
+0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 0xfb,
+0x22, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22,
+0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82,
+0x22, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xd2, 0xe4, 0xf0, 0xa3, 0x74,
+0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xd1, 0x90, 0xfa, 0xd2, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
+0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xd1, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3,
+0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0xf0, 0x90, 0xfa, 0xd1,
+0xe0, 0xff, 0x90, 0xfa, 0xd4, 0xe4, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0x12, 0x23, 0xf0, 0x90, 0xfa,
+0xd4, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xd2, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xd1,
+0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xd2, 0xe4, 0x75, 0xf0, 0x04, 0x12,
+0x1b, 0x1c, 0x02, 0x23, 0x72, 0x90, 0xfa, 0xd3, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xd2, 0xe0,
+0x34, 0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1b, 0x80, 0x7f, 0x00, 0x22,
+0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xd1, 0x90, 0xfa, 0xd2, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1b, 0x1c,
+0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x26, 0x98, 0x8f, 0x62, 0x12, 0x2a, 0xc7, 0x12,
+0x22, 0xfa, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0,
+0x08, 0x12, 0x22, 0xdc, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x23, 0x06, 0x24, 0x0b, 0x12, 0x22,
+0xa1, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83,
+0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82,
+0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3,
+0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x22, 0xa1,
+0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x99, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5,
+0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82,
+0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x44, 0x80,
+0xf0, 0x12, 0x32, 0x84, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22,
+0x12, 0x10, 0x4b, 0x7f, 0x02, 0x12, 0x12, 0x61, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0,
+0xd2, 0xb1, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36,
+0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7e, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa,
+0x7f, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x7c, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa,
+0x7d, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74,
+0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe7, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90,
+0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43,
+0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7e, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7f,
+0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7d,
+0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x18, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe7,
+0xe0, 0xf5, 0xa8, 0x02, 0x10, 0xce, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2e, 0x0d, 0x90,
+0xfa, 0xc3, 0x12, 0x1b, 0xf3, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0xf3, 0x90,
+0xfa, 0xc7, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0xea, 0xe9,
+0x24, 0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc9, 0x12, 0x1b, 0xf3, 0xab, 0x5c, 0xaa, 0x5d,
+0xa9, 0x5e, 0x12, 0x2e, 0x19, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa,
+0xc1, 0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0xee,
+0xff, 0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc6, 0x12, 0x2d, 0xee, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83,
+0xf6, 0x12, 0x2d, 0xeb, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0xf4, 0x75, 0xf0, 0x02,
+0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xc7, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1b, 0x1c, 0xab, 0x5c, 0xaa,
+0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0xbb, 0x30, 0xe4, 0x03, 0x12, 0x2e, 0x03, 0x78,
+0x82, 0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xc2, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58,
+0x90, 0xfa, 0xc2, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xc1, 0xf0, 0x12, 0x1a, 0xa2, 0x24, 0x6e,
+0x60, 0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0xda, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x25,
+0x56, 0x80, 0x62, 0x12, 0x2e, 0x24, 0x12, 0x1f, 0xda, 0x90, 0xfa, 0xc2, 0xef, 0xf0, 0x80, 0x55,
+0x90, 0xfa, 0xc2, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0xda, 0x60, 0x09, 0x24, 0x30, 0x70,
+0x3e, 0x12, 0x2d, 0x30, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b,
+0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2e, 0x24, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb,
+0xfd, 0x90, 0x00, 0x08, 0x12, 0x1b, 0x48, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02,
+0xd0, 0x03, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xc1, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90,
+0xfa, 0xc2, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xc2, 0xe0, 0x12, 0x2e, 0x24, 0x90, 0x00, 0x02, 0x12,
+0x1a, 0xfa, 0x90, 0xfa, 0xc1, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c,
+0xe5, 0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2e, 0x53, 0x70, 0x16, 0x12, 0x2e, 0x72, 0xe5,
+0x2d, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0xd8, 0x50, 0xf2, 0x12, 0x27, 0x25, 0x40, 0x0b, 0x7f,
+0x00, 0x22, 0x12, 0x2e, 0x72, 0x12, 0x27, 0x25, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0,
+0xe5, 0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4,
+0xf0, 0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0xc1,
+0x40, 0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff,
+0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2e, 0x65, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b,
+0xe4, 0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0xc1, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12,
+0x2e, 0x65, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0xd8, 0x12, 0x10,
+0x4b, 0x78, 0x84, 0x12, 0x23, 0x31, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x31, 0xa9, 0x02, 0x27,
+0xbc, 0x78, 0x84, 0xe6, 0xf9, 0x24, 0x13, 0x12, 0x22, 0xad, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54,
+0x03, 0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44,
+0x04, 0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80,
+0x39, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0,
+0x80, 0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef,
+0x54, 0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80,
+0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x18, 0xe0, 0x04, 0xf0,
+0xaf, 0x01, 0x12, 0x22, 0xee, 0xfd, 0x12, 0x2f, 0xe5, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, 0x75,
+0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x28, 0x09, 0x02, 0x31,
+0x8c, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf,
+0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54,
+0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80,
+0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0xa9, 0xe4, 0x7e, 0x01, 0x93,
+0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60,
+0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4,
+0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3,
+0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5,
+0x22, 0x12, 0x1d, 0xc2, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x30, 0x13,
+0x12, 0x1d, 0xc2, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5,
+0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x94, 0x12, 0x1e, 0x03, 0x60, 0x2c, 0x12, 0x2d,
+0x85, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x94, 0x12, 0x1b, 0xcc, 0xe4,
+0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0xa0, 0x12, 0x1b, 0xcc, 0xe0, 0xa3,
+0x30, 0xe6, 0x33, 0x12, 0x1d, 0xc2, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90,
+0xfa, 0x98, 0x12, 0x1e, 0x03, 0x60, 0x16, 0x12, 0x2d, 0x85, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02,
+0xe5, 0x22, 0x90, 0xfa, 0x98, 0x12, 0x1b, 0xcc, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5,
+0x22, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe,
+0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0,
+0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x0f, 0x12, 0x1c, 0xb0, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5,
+0x3a, 0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5,
+0x39, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0xdf, 0x12, 0x1e,
+0x34, 0x12, 0x1e, 0x26, 0x12, 0x1a, 0xa2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e,
+0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0xbb, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f,
+0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x5e, 0x12, 0x1e, 0x3b, 0x12, 0x25, 0xfa, 0x12,
+0x1d, 0x89, 0x12, 0x1a, 0xbb, 0x60, 0x03, 0x02, 0x32, 0x7a, 0xe4, 0xff, 0x12, 0x32, 0x6e, 0x22,
+0x8b, 0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2e, 0x53, 0x70,
+0x16, 0x12, 0x2e, 0x72, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0xd8, 0x50, 0xf2, 0x12,
+0x29, 0xd5, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2e, 0x72, 0x12, 0x29, 0xd5, 0x50, 0xf8, 0xe4,
+0xf5, 0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0xc5, 0x40,
+0x03, 0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5,
+0x46, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0xc5, 0x40, 0x03, 0x7f,
+0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x1a, 0xa2, 0x90, 0xff,
+0xf1, 0xf0, 0x02, 0x31, 0xd8, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0xd8, 0x7b, 0x01,
+0x7a, 0xfa, 0x79, 0xcf, 0xe4, 0xfd, 0x12, 0x23, 0x61, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x09,
+0x12, 0x1b, 0x1c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01,
+0x12, 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xff, 0xf7,
+0xe5, 0x23, 0x12, 0x2a, 0x39, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcf, 0xe4, 0xf0,
+0xa3, 0x74, 0x06, 0x12, 0x2a, 0x39, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94,
+0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23,
+0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d,
+0x01, 0x02, 0x26, 0x98, 0x90, 0xff, 0x93, 0x74, 0x81, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06,
+0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9,
+0x16, 0xf0, 0xa3, 0xf0, 0x12, 0x2b, 0x39, 0x12, 0x16, 0xc9, 0x12, 0x30, 0x69, 0x7e, 0x07, 0x7f,
+0xd0, 0x12, 0x12, 0x2a, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x12, 0x44, 0xe4, 0x78, 0x77, 0xf6, 0x78,
+0x77, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77,
+0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x30, 0xb2, 0x90, 0xf9, 0x16, 0xe0, 0x20, 0xe4, 0x05, 0x7f,
+0x04, 0x12, 0x30, 0xb2, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8,
+0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05,
+0x12, 0x11, 0xae, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c,
+0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76,
+0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76,
+0x9e, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x23, 0x49, 0x7b, 0x01, 0x7a,
+0xff, 0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0xe1, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08,
+0xa4, 0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x23, 0x49, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0xe1,
+0x78, 0x6d, 0xef, 0x12, 0x23, 0x49, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0,
+0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe6, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcf,
+0xe4, 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x7e, 0x00, 0x90, 0xfa, 0xe4, 0xee,
+0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcf, 0xe0, 0xb4, 0x52, 0x09, 0x90,
+0xf9, 0x16, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe4, 0xe0, 0x70, 0x04, 0xa3, 0xe0,
+0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcf, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x16, 0xe0, 0x44,
+0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe6, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x54, 0xef,
+0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x03, 0x68, 0x01, 0xff, 0x48, 0x03, 0x6b,
+0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x98, 0x00, 0x00, 0x00, 0x00, 0x44, 0xfa,
+0x94, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xb2, 0x00, 0x00, 0x42, 0xfa, 0x7e, 0x00, 0x00, 0x42,
+0xfa, 0x7c, 0x00, 0x00, 0x42, 0xf9, 0x6d, 0xff, 0xff, 0x42, 0xfa, 0x7a, 0x00, 0x00, 0x41, 0xf9,
+0x66, 0xff, 0x41, 0xf9, 0x1c, 0x19, 0x41, 0xf9, 0x15, 0x00, 0x43, 0xf9, 0x19, 0x0a, 0x32, 0x02,
+0x41, 0xf9, 0x68, 0x20, 0x41, 0xf9, 0x69, 0x20, 0x41, 0xf9, 0x65, 0x00, 0x41, 0xf9, 0x67, 0x00,
+0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 0x16, 0x00, 0x00, 0x41, 0xf9, 0x18, 0x00,
+0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x10, 0x4b, 0x78, 0x8a, 0xef, 0xf6, 0x12,
+0x2a, 0xc7, 0x12, 0x22, 0xee, 0x30, 0xe0, 0x29, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x54, 0x7f,
+0xf0, 0x78, 0x6b, 0x12, 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x12, 0x1a, 0xbb, 0x30, 0xe7, 0x09, 0x90,
+0x00, 0x02, 0xe4, 0x12, 0x1a, 0xfa, 0x80, 0xe9, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x44, 0x80,
+0xf0, 0x12, 0x22, 0xee, 0x30, 0xe1, 0x1e, 0x12, 0x22, 0x97, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x32,
+0x19, 0x78, 0x68, 0x12, 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0xfa, 0x12, 0x22,
+0x97, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x32, 0x84, 0xe4, 0xff, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce,
+0x12, 0x10, 0x4b, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x31, 0x50, 0x12, 0x31, 0xa9, 0x78, 0x85, 0xe6,
+0xff, 0x24, 0x13, 0x12, 0x22, 0xad, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90,
+0xff, 0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80,
+0x19, 0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20,
+0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x18, 0xe0, 0x14, 0xf0,
+0xe0, 0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0xce, 0x12, 0x1e, 0x1c, 0xe5, 0x3a, 0x64, 0x09, 0x70,
+0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00,
+0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5,
+0x39, 0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1e, 0x34, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12,
+0x1c, 0xc1, 0x12, 0x1a, 0xa2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83,
+0xed, 0xf0, 0x0e, 0x12, 0x1c, 0xb0, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22,
+0x8b, 0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2e, 0x19, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22,
+0xab, 0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2e, 0x0d, 0x90, 0xfa, 0xc9, 0x12, 0x1b, 0xf3, 0xe5,
+0x5b, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0xf3, 0xe4, 0x90,
+0xfa, 0xc2, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xc1, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f,
+0x50, 0x12, 0x12, 0x2d, 0xeb, 0xff, 0x12, 0x2d, 0xf4, 0x12, 0x2e, 0x07, 0x78, 0x8b, 0x06, 0x12,
+0x2e, 0x03, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x32, 0x0a, 0xe4, 0x93, 0xff, 0x78,
+0x74, 0xf6, 0x54, 0x0f, 0x12, 0x1d, 0xa8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c,
+0xd9, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6,
+0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f,
+0x00, 0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed,
+0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58,
+0x90, 0x00, 0x03, 0x12, 0x1a, 0xbb, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc9, 0x12, 0x1b,
+0xea, 0x02, 0x1a, 0xa2, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0xea, 0xef, 0x12, 0x1a, 0xe8, 0x90, 0xfa,
+0xca, 0xe4, 0x22, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1b, 0x1c, 0x90, 0x00, 0x08,
+0x12, 0x1b, 0x48, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, 0x90,
+0xfa, 0xc1, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xdd, 0xe0, 0xff,
+0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd7, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd6, 0xe0, 0x9e, 0xf0, 0x90,
+0xfa, 0xd8, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50,
+0xf5, 0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa,
+0xe6, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02,
+0x1a, 0xe8, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64,
+0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0xef, 0x7f, 0x02, 0x02, 0x31, 0xef, 0xaf, 0x64, 0x12,
+0x2a, 0xc7, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1d, 0x33,
+0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12,
+0x31, 0xef, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0xef, 0x30, 0x09, 0x07, 0x12, 0x1d, 0x33, 0xe0,
+0x44, 0x80, 0xf0, 0x12, 0x32, 0x84, 0x22, 0x12, 0x10, 0x4b, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60,
+0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7,
+0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44,
+0x01, 0xf0, 0x80, 0x0d, 0x12, 0x1d, 0xdf, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe,
+0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xde, 0x12, 0x1d, 0xe7, 0x02, 0x10,
+0xce, 0x12, 0x10, 0x4b, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0xc7, 0x90, 0xf9, 0x6a,
+0x12, 0x1b, 0xea, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe,
+0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0xd3, 0x12, 0x32,
+0x84, 0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x87, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, 0x8f, 0x63,
+0x12, 0x2a, 0xc7, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04,
+0x12, 0x22, 0xa1, 0xe0, 0x54, 0x3f, 0xf0, 0x12, 0x23, 0x41, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0,
+0x54, 0xf8, 0xf0, 0x12, 0x32, 0x84, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f,
+0x00, 0x22, 0x12, 0x10, 0x4b, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xfa, 0x24, 0x06, 0x12, 0x22, 0x9f,
+0xe0, 0xfd, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x03, 0x12, 0x23, 0x02, 0x24, 0x05, 0x12, 0x22, 0xa1,
+0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0xfa, 0x12, 0x32, 0x84, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2f,
+0xb4, 0x02, 0x10, 0xce, 0xae, 0x05, 0x12, 0x1d, 0x8e, 0xef, 0x12, 0x1a, 0xfa, 0x0e, 0x0e, 0x0e,
+0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 0xd3, 0x94, 0x08, 0x74,
+0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x1a, 0xfa, 0xaf,
+0x06, 0x12, 0x32, 0x6e, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10,
+0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x6e, 0x2e, 0xf8,
+0x74, 0x02, 0x46, 0xf6, 0x74, 0x99, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0,
+0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2,
+0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0,
+0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x10,
+0x4b, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83,
+0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 0x40, 0x05, 0x12, 0x28,
+0xd7, 0x80, 0x03, 0x12, 0x32, 0x7a, 0x02, 0x10, 0xce, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f,
+0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f,
+0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22,
+0x12, 0x10, 0x4b, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f,
+0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x61, 0x12, 0x1d, 0xf6, 0x02,
+0x10, 0xce, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xc0, 0x78, 0x7e, 0x12, 0x23,
+0x42, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x32, 0x84, 0xaf, 0x23, 0x12,
+0x13, 0x87, 0x22, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 0x70, 0x02, 0x15,
+0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x10, 0x24,
+0x80, 0xe5, 0x22, 0x11, 0xdc, 0x2e, 0xc7, 0x24, 0xb0, 0x32, 0x60, 0x30, 0x90, 0x30, 0x3e, 0x31,
+0x6f, 0x2f, 0x82, 0x27, 0x2e, 0x2c, 0x80, 0x31, 0x12, 0x31, 0x31, 0x1e, 0x64, 0x2f, 0x11, 0x2c,
+0x18, 0x0e, 0x12, 0x10, 0x4b, 0x78, 0x86, 0x12, 0x23, 0x31, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12,
+0x31, 0xa9, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x24, 0x0a, 0x12, 0x31, 0xa9, 0x02, 0x10,
+0xce, 0x12, 0x10, 0x4b, 0x78, 0x87, 0x12, 0x23, 0x31, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x31,
+0xa9, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2f, 0x4e, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce,
+0x8f, 0x61, 0x12, 0x2f, 0x4e, 0xaf, 0x61, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xc0, 0x12, 0x32, 0x84,
+0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 0x87, 0x22, 0x12,
+0x10, 0x4b, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x05, 0x12, 0x2c,
+0xd8, 0x80, 0x06, 0x12, 0x1e, 0x14, 0x12, 0x1e, 0x1c, 0x02, 0x10, 0xce, 0x12, 0x2a, 0x54, 0x12,
+0x13, 0x03, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 0xa0, 0x12, 0x29,
+0xde, 0x12, 0x13, 0x3f, 0x12, 0x11, 0xbc, 0x80, 0xe3, 0x12, 0x1d, 0x8e, 0xef, 0x12, 0x1a, 0xfa,
+0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x32, 0x7a, 0xe4, 0xff, 0x12, 0x32, 0x6e,
+0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff,
+0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60,
+0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef,
+0x30, 0xe7, 0x08, 0x12, 0x1d, 0x45, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x1d, 0x98, 0xe0,
+0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40,
+0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 0xb7, 0xa3, 0xa3,
+0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x3b, 0x39, 0x85,
+0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4,
+0xfe, 0xee, 0x90, 0x32, 0x04, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3,
+0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x90, 0x0a, 0x02, 0x00, 0x00, 0x11, 0x13, 0x00,
+0x12, 0x10, 0x4b, 0x7f, 0x02, 0x12, 0x10, 0xda, 0x12, 0x1d, 0xf6, 0x02, 0x10, 0xce, 0x75, 0x39,
+0x00, 0x8f, 0x3a, 0x12, 0x1c, 0xe0, 0x12, 0x2c, 0xd8, 0x22, 0x12, 0x1e, 0x1c, 0x12, 0x1d, 0xdf,
+0x12, 0x1e, 0x14, 0x22, 0xc2, 0x08, 0x22,
 };
 
 #undef IMAGE_VERSION_NAME
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 544098d..0d39036 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -48,7 +48,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.7"
+#define DRIVER_VERSION "v0.7mode043006"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
@@ -173,8 +173,12 @@
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
-// The 4-port shows up as two 2-port devices
+	/* The 4, 8 and 16 port devices show up as multiple 2 port devices */
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
 	{ }
 };
 
@@ -209,6 +213,10 @@
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
 	{ }
 };
 
@@ -231,6 +239,7 @@
 static int low_latency = EDGE_LOW_LATENCY;
 static int closing_wait = EDGE_CLOSING_WAIT;
 static int ignore_cpu_rev = 0;
+static int default_uart_mode = 0;	/* RS232 */
 
 
 static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
@@ -241,6 +250,10 @@
 static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
 static void edge_send(struct usb_serial_port *port);
 
+/* sysfs attributes */
+static int edge_create_sysfs_attrs(struct usb_serial_port *port);
+static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
+
 /* circular buffer */
 static struct edge_buf *edge_buf_alloc(unsigned int size);
 static void edge_buf_free(struct edge_buf *eb);
@@ -1706,13 +1719,14 @@
 	int length = urb->actual_length;
 	int port_number;
 	int function;
-	int status;
+	int retval;
 	__u8 lsr;
 	__u8 msr;
+	int status = urb->status;
 
 	dbg("%s", __FUNCTION__);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -1720,10 +1734,12 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, status);
 		return;
 	default:
-		dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status);
+		dev_err(&urb->dev->dev, "%s - nonzero urb status received: "
+			"%d\n", __FUNCTION__, status);
 		goto exit;
 	}
 
@@ -1781,10 +1797,10 @@
 	}
 
 exit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
+	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	if (retval)
 		dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
-			 __FUNCTION__, status);
+			 __FUNCTION__, retval);
 }
 
 static void edge_bulk_in_callback (struct urb *urb)
@@ -1792,12 +1808,13 @@
 	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
 	unsigned char *data = urb->transfer_buffer;
 	struct tty_struct *tty;
-	int status = 0;
+	int retval = 0;
 	int port_number;
+	int status = urb->status;
 
 	dbg("%s", __FUNCTION__);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -1805,17 +1822,18 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, status);
 		return;
 	default:
 		dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
-		     __FUNCTION__, urb->status );
+		     __FUNCTION__, status);
 	}
 
-	if (urb->status == -EPIPE)
+	if (status == -EPIPE)
 		goto exit;
 
-	if (urb->status) {
+	if (status) {
 		dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
 		return;
 	}
@@ -1849,14 +1867,14 @@
 	spin_lock(&edge_port->ep_lock);
 	if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) {
 		urb->dev = edge_port->port->serial->dev;
-		status = usb_submit_urb(urb, GFP_ATOMIC);
+		retval = usb_submit_urb(urb, GFP_ATOMIC);
 	} else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) {
 		edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED;
 	}
 	spin_unlock(&edge_port->ep_lock);
-	if (status)
+	if (retval)
 		dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
-			 __FUNCTION__, status);
+			 __FUNCTION__, retval);
 }
 
 static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
@@ -1883,12 +1901,13 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+	int status = urb->status;
 
 	dbg ("%s - port %d", __FUNCTION__, port->number);
 
 	edge_port->ep_write_urb_in_use = 0;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -1896,11 +1915,12 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, status);
 		return;
 	default:
-		dev_err (&urb->dev->dev,"%s - nonzero write bulk status received: %d\n",
-		     __FUNCTION__, urb->status);
+		dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+			"received: %d\n", __FUNCTION__, status);
 	}
 
 	/* send any buffered data */
@@ -2351,7 +2371,7 @@
 		urb->complete = edge_bulk_in_callback;
 		urb->context = edge_port;
 		urb->dev = edge_port->port->serial->dev;
-		status = usb_submit_urb(urb, GFP_KERNEL);
+		status = usb_submit_urb(urb, GFP_ATOMIC);
 	}
 	edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
 	edge_port->shadow_mcr |= MCR_RTS;
@@ -2524,14 +2544,6 @@
 	}
 
 	cflag = tty->termios->c_cflag;
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if (cflag == old_termios->c_cflag &&
-		    tty->termios->c_iflag == old_termios->c_iflag) {
-			dbg ("%s - nothing to change", __FUNCTION__);
-			return;
-		}
-	}
 
 	dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
 	    tty->termios->c_cflag, tty->termios->c_iflag);
@@ -2758,7 +2770,7 @@
 		edge_port->port = serial->port[i];
 		edge_port->edge_serial = edge_serial;
 		usb_set_serial_port_data(serial->port[i], edge_port);
-		edge_port->bUartMode = 0;	/* Default is RS232 */
+		edge_port->bUartMode = default_uart_mode;
 	}
 	
 	return 0;
@@ -2784,6 +2796,7 @@
 
 	for (i=0; i < serial->num_ports; ++i) {
 		edge_port = usb_get_serial_port_data(serial->port[i]);
+		edge_remove_sysfs_attrs(edge_port->port);
 		if (edge_port) {
 			edge_buf_free(edge_port->ep_out_buf);
 			kfree(edge_port);
@@ -2795,6 +2808,48 @@
 }
 
 
+/* Sysfs Attributes */
+
+static ssize_t show_uart_mode(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct usb_serial_port *port = to_usb_serial_port(dev);
+	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+
+	return sprintf(buf, "%d\n", edge_port->bUartMode);
+}
+
+static ssize_t store_uart_mode(struct device *dev,
+	struct device_attribute *attr, const char *valbuf, size_t count)
+{
+	struct usb_serial_port *port = to_usb_serial_port(dev);
+	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+	unsigned int v = simple_strtoul(valbuf, NULL, 0);
+
+	dbg("%s: setting uart_mode = %d", __FUNCTION__, v);
+
+	if (v < 256)
+		edge_port->bUartMode = v;
+	else
+		dev_err(dev, "%s - uart_mode %d is invalid\n", __FUNCTION__, v);
+
+	return count;
+}
+
+static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode, store_uart_mode);
+
+static int edge_create_sysfs_attrs(struct usb_serial_port *port)
+{
+	return device_create_file(&port->dev, &dev_attr_uart_mode);
+}
+
+static int edge_remove_sysfs_attrs(struct usb_serial_port *port)
+{
+	device_remove_file(&port->dev, &dev_attr_uart_mode);
+	return 0;
+}
+
+
 /* Circular Buffer */
 
 /*
@@ -2991,6 +3046,7 @@
 	.unthrottle		= edge_unthrottle,
 	.attach			= edge_startup,
 	.shutdown		= edge_shutdown,
+	.port_probe		= edge_create_sysfs_attrs,
 	.ioctl			= edge_ioctl,
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
@@ -3022,6 +3078,7 @@
 	.unthrottle		= edge_unthrottle,
 	.attach			= edge_startup,
 	.shutdown		= edge_shutdown,
+	.port_probe		= edge_create_sysfs_attrs,
 	.ioctl			= edge_ioctl,
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
@@ -3085,3 +3142,6 @@
 module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device");
 
+module_param(default_uart_mode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(default_uart_mode, "Default uart_mode, 0=RS232, ...");
+
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
index e57fa11..8e1a491 100644
--- a/drivers/usb/serial/io_usbvend.h
+++ b/drivers/usb/serial/io_usbvend.h
@@ -131,7 +131,7 @@
 #define ION_DEVICE_ID_TI_EDGEPORT_2I		0x0207	// Edgeport/2i RS422/RS485
 #define ION_DEVICE_ID_TI_EDGEPORT_421		0x020C	// Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port)
 #define ION_DEVICE_ID_TI_EDGEPORT_21		0x020D	// Edgeport/21 2 RS232 + Parallel (lucent on a different hub port)
-#define ION_DEVICE_ID_TI_EDGEPORT_8		0x020F	// Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_416		0x0212  // Edgeport/416
 #define ION_DEVICE_ID_TI_EDGEPORT_1		0x0215	// Edgeport/1 RS232
 #define ION_DEVICE_ID_TI_EDGEPORT_42		0x0217	// Edgeport/42 4 hub 2 RS232
 #define ION_DEVICE_ID_TI_EDGEPORT_22I  		0x021A	// Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
@@ -143,12 +143,14 @@
 #define ION_DEVICE_ID_TI_EDGEPORT_21C		0x021E	// Edgeport/21c is a TI based Edgeport/2 with lucent chip
 
 // Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) 
-#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1	0x240	// Edgeport/1 RS232
-#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I	0x241	// Edgeport/1i- RS422 model
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1	0x0240	// Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I	0x0241	// Edgeport/1i- RS422 model
 
 // Ti based software switchable RS232/RS422/RS485 devices
-#define ION_DEVICE_ID_TI_EDGEPORT_4S		0x242	// Edgeport/4s - software switchable model
-#define ION_DEVICE_ID_IT_EDGEPORT_8S		0x243	// Edgeport/8s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_4S		0x0242	// Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_8S		0x0243	// Edgeport/8s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_8		0x0244	// Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_416B		0x0247	// Edgeport/416
 
 
 /************************************************************************
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 4df0ec7..0455c15 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -732,11 +732,13 @@
 	struct tty_struct	*tty;
 	unsigned char		*data = urb->transfer_buffer;
 	int			result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -870,11 +872,13 @@
 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
 	unsigned long		flags;
 	int			result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+
+	if (status) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 1bc5860..1b94daa 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -167,11 +167,13 @@
 	unsigned char *data = urb->transfer_buffer;
 	struct tty_struct *tty;
 	int result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -369,13 +371,15 @@
 static void ipw_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
+	int status = urb->status;
 
 	dbg("%s", __FUNCTION__);
 
 	port->write_urb_busy = 0;
 
-	if (urb->status)
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+	if (status)
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 
 	usb_serial_port_softint(port);
 }
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 9d847f6..5ab6a0c 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -21,6 +21,10 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * 2007_Jun_21  Alan Cox <alan@redhat.com>
+ *	Minimal cleanups for some of the driver problens and tty layer abuse.
+ *	Still needs fixing to allow multiple dongles.
+ *
  * 2002_Mar_07	greg kh
  *	moved some needed structures and #define values from the
  *	net/irda/irda-usb.h file into our file, as we don't want to depend on
@@ -109,6 +113,7 @@
 static void ir_read_bulk_callback (struct urb *urb);
 static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
 
+/* Not that this lot means you can only have one per system */
 static u8 ir_baud = 0;
 static u8 ir_xbof = 0;
 static u8 ir_add_bof = 0;
@@ -392,12 +397,14 @@
 static void ir_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	port->write_urb_busy = 0;
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -417,6 +424,7 @@
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	int result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -425,8 +433,7 @@
 		return;
 	}
 
-	switch (urb->status) {
-
+	switch (status) {
 		case 0: /* Successful */
 
 			/*
@@ -444,22 +451,12 @@
 				urb->actual_length,
 				data);
 
-			/*
-			 * Bypass flip-buffers, and feed the ldisc directly
-			 * due to our potentially large buffer size.  Since we
-			 * used to set low_latency, this is exactly what the
-			 * tty layer did anyway :)
-			 */
 			tty = port->tty;
 
-			/*
-			 *	FIXME: must not do this in IRQ context
-			 */
-			tty->ldisc.receive_buf(
-				tty,
-				data+1,
-				NULL,
-				urb->actual_length-1);
+			if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
+				tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
+				tty_flip_buffer_push(tty);
+			}
 
 			/*
 			 * No break here.
@@ -490,7 +487,7 @@
 		default:
 			dbg("%s - nonzero read bulk status received: %d",
 				__FUNCTION__, 
-				urb->status);
+				status);
 			break ;
 
 	}
@@ -501,8 +498,9 @@
 static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	unsigned char *transfer_buffer;
-	unsigned int cflag;
 	int result;
+	speed_t baud;
+	int ir_baud;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -511,77 +509,59 @@
 		return;
 	}
 
-	cflag = port->tty->termios->c_cflag;
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg("%s - nothing to change...", __FUNCTION__);
-			return;
-		}
+	baud = tty_get_baud_rate(port->tty);
+
+	/*
+	 * FIXME, we should compare the baud request against the
+	 * capability stated in the IR header that we got in the
+	 * startup function.
+	 */
+
+	switch (baud) {
+		case 2400:	ir_baud = SPEED_2400; break;
+		case 9600:	ir_baud = SPEED_9600; break;
+		case 19200:	ir_baud = SPEED_19200; break;
+		case 38400:	ir_baud = SPEED_38400; break;
+		case 57600:	ir_baud = SPEED_57600; break;
+		case 115200:	ir_baud = SPEED_115200; break;
+		case 576000:	ir_baud = SPEED_576000; break;
+		case 1152000:	ir_baud = SPEED_1152000; break;
+		case 4000000:	ir_baud = SPEED_4000000; break;
+			break;
+		default:
+			ir_baud = SPEED_9600;
+			baud = 9600;
+			/* And once the new tty stuff is all done we need to
+			   call back to correct the baud bits */
 	}
 
-	/* All we can change is the baud rate */
-	if (cflag & CBAUD) {
+	if (xbof == -1)
+		ir_xbof = ir_xbof_change(ir_add_bof);
+	else
+		ir_xbof = ir_xbof_change(xbof) ;
 
-		dbg ("%s - asking for baud %d",
-			__FUNCTION__,
-			tty_get_baud_rate(port->tty));
+	/* FIXME need to check to see if our write urb is busy right
+	 * now, or use a urb pool.
+	 *
+	 * send the baud change out on an "empty" data packet
+	 */
+	transfer_buffer = port->write_urb->transfer_buffer;
+	*transfer_buffer = ir_xbof | ir_baud;
 
-		/* 
-		 * FIXME, we should compare the baud request against the
-		 * capability stated in the IR header that we got in the
-		 * startup function.
-		 */
-		switch (cflag & CBAUD) {
-			case B2400:    ir_baud = SPEED_2400;    break;
-			default:
-			case B9600:    ir_baud = SPEED_9600;    break;
-			case B19200:   ir_baud = SPEED_19200;   break;
-			case B38400:   ir_baud = SPEED_38400;   break;
-			case B57600:   ir_baud = SPEED_57600;   break;
-			case B115200:  ir_baud = SPEED_115200;  break;
-			case B576000:  ir_baud = SPEED_576000;  break;
-			case B1152000: ir_baud = SPEED_1152000; break;
-#ifdef B4000000
-			case B4000000: ir_baud = SPEED_4000000; break;
-#endif
-		}
+	usb_fill_bulk_urb (
+		port->write_urb,
+		port->serial->dev,
+		usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
+		port->write_urb->transfer_buffer,
+		1,
+		ir_write_bulk_callback,
+		port);
 
-		if (xbof == -1) {
-			ir_xbof = ir_xbof_change(ir_add_bof);
-		} else {
-			ir_xbof = ir_xbof_change(xbof) ;
-		}
+	port->write_urb->transfer_flags = URB_ZERO_PACKET;
 
-		/* Notify the tty driver that the termios have changed. */
-		port->tty->ldisc.set_termios(port->tty, NULL);
-
-		/* FIXME need to check to see if our write urb is busy right
-		 * now, or use a urb pool.
-		 *
-		 * send the baud change out on an "empty" data packet
-		 */
-		transfer_buffer = port->write_urb->transfer_buffer;
-		*transfer_buffer = ir_xbof | ir_baud;
-
-		usb_fill_bulk_urb (
-			port->write_urb,
-			port->serial->dev,
-			usb_sndbulkpipe(port->serial->dev,
-				port->bulk_out_endpointAddress),
-			port->write_urb->transfer_buffer,
-			1,
-			ir_write_bulk_callback,
-			port);
-
-		port->write_urb->transfer_flags = URB_ZERO_PACKET;
-
-		result = usb_submit_urb (port->write_urb, GFP_KERNEL);
-		if (result)
-			dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
-	}
-	return;
+	result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+	if (result)
+		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
 }
 
 
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index e6966f1..f2a6fce 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -115,12 +115,13 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.1.4"
+#define DRIVER_VERSION "v1.1.5"
 #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
 #define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
 
 #define INSTAT_BUFLEN	32
 #define GLOCONT_BUFLEN	64
+#define INDAT49W_BUFLEN	512
 
 	/* Per device and per port private data */
 struct keyspan_serial_private {
@@ -129,9 +130,15 @@
 	struct urb	*instat_urb;
 	char		instat_buf[INSTAT_BUFLEN];
 
+	/* added to support 49wg, where data from all 4 ports comes in on 1 EP */
+	/* and high-speed supported */
+	struct urb	*indat_urb;
+	char		indat_buf[INDAT49W_BUFLEN];
+
 	/* XXX this one probably will need a lock */
 	struct urb	*glocont_urb;
 	char		glocont_buf[GLOCONT_BUFLEN];
+	char		ctrl_buf[8];			// for EP0 control message
 };
 
 struct keyspan_port_private {
@@ -179,12 +186,13 @@
 
 	
 /* Include Keyspan message headers.  All current Keyspan Adapters
-   make use of one of four message formats which are referred
-   to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */
+   make use of one of five message formats which are referred
+   to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */
 #include "keyspan_usa26msg.h"
 #include "keyspan_usa28msg.h"
 #include "keyspan_usa49msg.h"
 #include "keyspan_usa90msg.h"
+#include "keyspan_usa67msg.h"
 	
 
 /* Functions used by new usb-serial code. */
@@ -419,14 +427,15 @@
 	struct usb_serial_port	*port;
 	struct tty_struct	*tty;
 	unsigned char 		*data = urb->transfer_buffer;
+	int status = urb->status;
 
 	dbg ("%s", __FUNCTION__); 
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 
-	if (urb->status) {
+	if (status) {
 		dbg("%s - nonzero status: %x on endpoint %d.",
-		    __FUNCTION__, urb->status, endpoint);
+		    __FUNCTION__, status, endpoint);
 		return;
 	}
 
@@ -511,11 +520,12 @@
 	struct usb_serial_port			*port;
 	struct keyspan_port_private	 	*p_priv;
 	int old_dcd_state, err;
+	int status = urb->status;
 
 	serial = (struct usb_serial *) urb->context;
 
-	if (urb->status) {
-		dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero status: %x", __FUNCTION__, status);
 		return;
 	}
 	if (urb->actual_length != 9) {
@@ -579,6 +589,7 @@
 	struct tty_struct       *tty;
 	unsigned char           *data;
 	struct keyspan_port_private             *p_priv;
+	int status = urb->status;
 
 	dbg ("%s", __FUNCTION__);
 
@@ -590,9 +601,9 @@
 		return;
 
 	do {
-		if (urb->status) {
+		if (status) {
 			dbg("%s - nonzero status: %x on endpoint %d.",
-			    __FUNCTION__, urb->status, usb_pipeendpoint(urb->pipe));
+			    __FUNCTION__, status, usb_pipeendpoint(urb->pipe));
 			return;
 		}
 
@@ -648,11 +659,12 @@
 	struct usb_serial_port			*port;
 	struct keyspan_port_private	 	*p_priv;
 	int old_dcd_state;
+	int status = urb->status;
 
 	serial = (struct usb_serial *) urb->context;
 
-	if (urb->status) {
-		dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero status: %x", __FUNCTION__, status);
 		return;
 	}
 
@@ -739,13 +751,14 @@
 	struct usb_serial_port			*port;
 	struct keyspan_port_private	 	*p_priv;
 	int old_dcd_state;
+	int status = urb->status;
 
 	dbg ("%s", __FUNCTION__);
 
 	serial = (struct usb_serial *) urb->context;
 
-	if (urb->status) {
-		dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero status: %x", __FUNCTION__, status);
 		return;
 	}
 
@@ -805,14 +818,15 @@
 	struct usb_serial_port	*port;
 	struct tty_struct	*tty;
 	unsigned char 		*data = urb->transfer_buffer;
+	int status = urb->status;
 
 	dbg ("%s", __FUNCTION__);
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 
-	if (urb->status) {
+	if (status) {
 		dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__,
-		    urb->status, endpoint);
+		    status, endpoint);
 		return;
 	}
 
@@ -850,13 +864,90 @@
 		}
 }
 
+static void usa49wg_indat_callback(struct urb *urb)
+{
+	int			i, len, x, err;
+	struct usb_serial	*serial;
+	struct usb_serial_port	*port;
+	struct tty_struct	*tty;
+	unsigned char 		*data = urb->transfer_buffer;
+	int status = urb->status;
+
+	dbg ("%s", __FUNCTION__);
+
+	serial = urb->context;
+
+	if (status) {
+		dbg("%s - nonzero status: %x", __FUNCTION__, status);
+		return;
+	}
+
+	/* inbound data is in the form P#, len, status, data */
+	i = 0;
+	len = 0;
+
+	if (urb->actual_length) {
+		while (i < urb->actual_length) {
+
+			/* Check port number from message*/
+			if (data[i] >= serial->num_ports) {
+				dbg ("%s - Unexpected port number %d",
+					__FUNCTION__, data[i]);
+				return;
+			}
+			port = serial->port[data[i++]];
+			tty = port->tty;
+			len = data[i++];
+
+			/* 0x80 bit is error flag */
+			if ((data[i] & 0x80) == 0) {
+				/* no error on any byte */
+				i++;
+				for (x = 1; x < len ; ++x)
+					if (port->open_count)
+						tty_insert_flip_char(tty,
+								data[i++], 0);
+					else
+						i++;
+			} else {
+				/*
+				 * some bytes had errors, every byte has status
+				 */
+				for (x = 0; x + 1 < len; x += 2) {
+					int stat = data[i], flag = 0;
+					if (stat & RXERROR_OVERRUN)
+						flag |= TTY_OVERRUN;
+					if (stat & RXERROR_FRAMING)
+						flag |= TTY_FRAME;
+					if (stat & RXERROR_PARITY)
+						flag |= TTY_PARITY;
+					/* XXX should handle break (0x10) */
+					if (port->open_count)
+						tty_insert_flip_char(tty,
+							data[i+1], flag);
+					i += 2;
+				}
+			}
+			if (port->open_count)
+				tty_flip_buffer_push(tty);
+		}
+	}
+
+	/* Resubmit urb so we continue receiving */
+	urb->dev = serial->dev;
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
+		dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+}
+
 /* not used, usa-49 doesn't have per-port control endpoints */
-static void	usa49_outcont_callback(struct urb *urb)
+static void usa49_outcont_callback(struct urb *urb)
 {
 	dbg ("%s", __FUNCTION__);
 }
 
-static void	usa90_indat_callback(struct urb *urb)
+static void usa90_indat_callback(struct urb *urb)
 {
 	int			i, err;
 	int			endpoint;
@@ -864,15 +955,15 @@
 	struct keyspan_port_private	 	*p_priv;
 	struct tty_struct	*tty;
 	unsigned char 		*data = urb->transfer_buffer;
+	int status = urb->status;
 
 	dbg ("%s", __FUNCTION__); 
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 
-
-	if (urb->status) {
+	if (status) {
 		dbg("%s - nonzero status: %x on endpoint %d.",
-		    __FUNCTION__, urb->status, endpoint);
+		    __FUNCTION__, status, endpoint);
 		return;
 	}
 
@@ -938,11 +1029,12 @@
 	struct usb_serial_port			*port;
 	struct keyspan_port_private	 	*p_priv;
 	int old_dcd_state, err;
+	int status = urb->status;
 
 	serial = (struct usb_serial *) urb->context;
 
-	if (urb->status) {
-		dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero status: %x", __FUNCTION__, status);
 		return;
 	}
 	if (urb->actual_length < 14) {
@@ -995,6 +1087,88 @@
 	}
 }
 
+/* Status messages from the 28xg */
+static void	usa67_instat_callback(struct urb *urb)
+{
+	int					err;
+	unsigned char 				*data = urb->transfer_buffer;
+	struct keyspan_usa67_portStatusMessage	*msg;
+	struct usb_serial			*serial;
+	struct usb_serial_port			*port;
+	struct keyspan_port_private	 	*p_priv;
+	int old_dcd_state;
+	int status = urb->status;
+
+	dbg ("%s", __FUNCTION__);
+
+	serial = urb->context;
+
+	if (status) {
+		dbg("%s - nonzero status: %x", __FUNCTION__, status);
+		return;
+	}
+
+	if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
+		dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
+		return;
+	}
+
+
+	/* Now do something useful with the data */
+	msg = (struct keyspan_usa67_portStatusMessage *)data;
+
+	/* Check port number from message and retrieve private data */
+	if (msg->port >= serial->num_ports) {
+		dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
+		return;
+	}
+
+	port = serial->port[msg->port];
+	p_priv = usb_get_serial_port_data(port);
+
+	/* Update handshaking pin state information */
+	old_dcd_state = p_priv->dcd_state;
+	p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
+	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
+
+	if (port->tty && !C_CLOCAL(port->tty)
+	    && old_dcd_state != p_priv->dcd_state) {
+		if (old_dcd_state)
+			tty_hangup(port->tty);
+		/*  else */
+		/*	wake_up_interruptible(&p_priv->open_wait); */
+	}
+
+	/* Resubmit urb so we continue receiving */
+	urb->dev = serial->dev;
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
+		dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+}
+
+static void usa67_glocont_callback(struct urb *urb)
+{
+	struct usb_serial *serial;
+	struct usb_serial_port *port;
+	struct keyspan_port_private *p_priv;
+	int i;
+
+	dbg ("%s", __FUNCTION__);
+
+	serial = urb->context;
+	for (i = 0; i < serial->num_ports; ++i) {
+		port = serial->port[i];
+		p_priv = usb_get_serial_port_data(port);
+
+		if (p_priv->resend_cont) {
+			dbg ("%s - sending setup", __FUNCTION__);
+			keyspan_usa67_send_setup(serial, port,
+						p_priv->resend_cont - 1);
+			break;
+		}
+	}
+}
+
 static int keyspan_write_room (struct usb_serial_port *port)
 {
 	struct keyspan_port_private	*p_priv;
@@ -1311,6 +1485,11 @@
 		return NULL;
 	}
 
+	if (endpoint == 0) {
+		/* control EP filled in when used */
+		return urb;
+	}
+
 	ep_desc = find_ep(serial, endpoint);
 	if (!ep_desc) {
 		/* leak the urb, something's wrong and the callers don't care */
@@ -1380,6 +1559,14 @@
 		.outdat_callback =	usa2x_outdat_callback,
 		.inack_callback =	usa28_inack_callback,
 		.outcont_callback =	usa90_outcont_callback,
+	}, {
+		/* msg_usa67 callbacks */
+		.instat_callback =	usa67_instat_callback,
+		.glocont_callback =	usa67_glocont_callback,
+		.indat_callback =	usa26_indat_callback,
+		.outdat_callback =	usa2x_outdat_callback,
+		.inack_callback =	usa26_inack_callback,
+		.outcont_callback =	usa26_outcont_callback,
 	}
 };
 
@@ -1410,6 +1597,11 @@
 		 serial, s_priv->instat_buf, INSTAT_BUFLEN,
 		 cback->instat_callback);
 
+	s_priv->indat_urb = keyspan_setup_urb
+		(serial, d_details->indat_endpoint, USB_DIR_IN,
+		 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
+		 usa49wg_indat_callback);
+
 	s_priv->glocont_urb = keyspan_setup_urb
 		(serial, d_details->glocont_endpoint, USB_DIR_OUT,
 		 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
@@ -1685,8 +1877,8 @@
 	}
 
 	/* Save reset port val for resend.
-	Don't overwrite resend for close condition. */
-	if (p_priv->resend_cont != 3)
+	   Don't overwrite resend for open/close condition. */
+	if ((reset_port + 1) > p_priv->resend_cont)
 		p_priv->resend_cont = reset_port + 1;
 	if (this_urb->status == -EINPROGRESS) {
 		/*  dbg ("%s - already writing", __FUNCTION__); */
@@ -1836,8 +2028,8 @@
 	}
 
 	/* Save reset port val for resend.
-	   Don't overwrite resend for close condition. */
-	if (p_priv->resend_cont != 3)
+	   Don't overwrite resend for open/close condition. */
+	if ((reset_port + 1) > p_priv->resend_cont)
 		p_priv->resend_cont = reset_port + 1;
 	if (this_urb->status == -EINPROGRESS) {
 		dbg ("%s already writing", __FUNCTION__);
@@ -1940,11 +2132,11 @@
 				    struct usb_serial_port *port,
 				    int reset_port)
 {
-	struct keyspan_usa49_portControlMessage	msg;		
+	struct keyspan_usa49_portControlMessage	msg;
+	struct usb_ctrlrequest 			*dr = NULL;
 	struct keyspan_serial_private 		*s_priv;
 	struct keyspan_port_private 		*p_priv;
 	const struct keyspan_device_details	*d_details;
-	int 					glocont_urb;
 	struct urb				*this_urb;
 	int 					err, device_port;
 
@@ -1954,10 +2146,9 @@
 	p_priv = usb_get_serial_port_data(port);
 	d_details = s_priv->device_details;
 
-	glocont_urb = d_details->glocont_endpoint;
 	this_urb = s_priv->glocont_urb;
 
-		/* Work out which port within the device is being setup */
+	/* Work out which port within the device is being setup */
 	device_port = port->number - port->serial->minor;
 
 	dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
@@ -1969,9 +2160,10 @@
 	}
 
 	/* Save reset port val for resend.
-	   Don't overwrite resend for close condition. */
-	if (p_priv->resend_cont != 3)
+	   Don't overwrite resend for open/close condition. */
+	if ((reset_port + 1) > p_priv->resend_cont)
 		p_priv->resend_cont = reset_port + 1;
+
 	if (this_urb->status == -EINPROGRESS) {
 		/*  dbg ("%s - already writing", __FUNCTION__); */
 		mdelay(5);
@@ -2083,20 +2275,39 @@
 	msg.dtr = p_priv->dtr_state;
 		
 	p_priv->resend_cont = 0;
-	memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
-	
-	/* send the data out the device on control endpoint */
-	this_urb->transfer_buffer_length = sizeof(msg);
 
-	this_urb->dev = serial->dev;
+	/* if the device is a 49wg, we send control message on usb control EP 0 */
+
+	if (d_details->product_id == keyspan_usa49wg_product_id) {
+		dr = (void *)(s_priv->ctrl_buf);
+		dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
+		dr->bRequest = 0xB0;	/* 49wg control message */;
+		dr->wValue = 0;
+		dr->wIndex = 0;
+		dr->wLength = cpu_to_le16(sizeof(msg));
+
+		memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
+
+		usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			     (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
+			     usa49_glocont_callback, serial);
+
+	} else {
+		memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+	
+		/* send the data out the device on control endpoint */
+		this_urb->transfer_buffer_length = sizeof(msg);
+
+		this_urb->dev = serial->dev;
+	}
 	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
 		dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
 	}
 #if 0
 	else {
 		dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__,
-		    outcont_urb, this_urb->transfer_buffer_length,
-		    usb_pipeendpoint(this_urb->pipe));
+			   outcont_urb, this_urb->transfer_buffer_length,
+			   usb_pipeendpoint(this_urb->pipe));
 	}
 #endif
 
@@ -2241,6 +2452,154 @@
 	return (0);
 }
 
+static int keyspan_usa67_send_setup(struct usb_serial *serial,
+				    struct usb_serial_port *port,
+				    int reset_port)
+{
+	struct keyspan_usa67_portControlMessage	msg;
+	struct keyspan_serial_private 		*s_priv;
+	struct keyspan_port_private 		*p_priv;
+	const struct keyspan_device_details	*d_details;
+	struct urb				*this_urb;
+	int 					err, device_port;
+
+	dbg ("%s", __FUNCTION__);
+
+	s_priv = usb_get_serial_data(serial);
+	p_priv = usb_get_serial_port_data(port);
+	d_details = s_priv->device_details;
+
+	this_urb = s_priv->glocont_urb;
+
+	/* Work out which port within the device is being setup */
+	device_port = port->number - port->serial->minor;
+
+	/* Make sure we have an urb then send the message */
+	if (this_urb == NULL) {
+		dbg("%s - oops no urb for port %d.", __FUNCTION__,
+			port->number);
+		return -1;
+	}
+
+	/* Save reset port val for resend.
+	   Don't overwrite resend for open/close condition. */
+	if ((reset_port + 1) > p_priv->resend_cont)
+		p_priv->resend_cont = reset_port + 1;
+	if (this_urb->status == -EINPROGRESS) {
+		/*  dbg ("%s - already writing", __FUNCTION__); */
+		mdelay(5);
+		return(-1);
+	}
+
+	memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
+
+	msg.port = device_port;
+
+	/* Only set baud rate if it's changed */
+	if (p_priv->old_baud != p_priv->baud) {
+		p_priv->old_baud = p_priv->baud;
+		msg.setClocking = 0xff;
+		if (d_details->calculate_baud_rate
+		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
+		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+			dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
+			    p_priv->baud);
+			msg.baudLo = 0;
+			msg.baudHi = 125;	/* Values for 9600 baud */
+			msg.prescaler = 10;
+		}
+		msg.setPrescaler = 0xff;
+	}
+
+	msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
+	switch (p_priv->cflag & CSIZE) {
+	case CS5:
+		msg.lcr |= USA_DATABITS_5;
+		break;
+	case CS6:
+		msg.lcr |= USA_DATABITS_6;
+		break;
+	case CS7:
+		msg.lcr |= USA_DATABITS_7;
+		break;
+	case CS8:
+		msg.lcr |= USA_DATABITS_8;
+		break;
+	}
+	if (p_priv->cflag & PARENB) {
+		/* note USA_PARITY_NONE == 0 */
+		msg.lcr |= (p_priv->cflag & PARODD)?
+			USA_PARITY_ODD: USA_PARITY_EVEN;
+	}
+	msg.setLcr = 0xff;
+
+	msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
+	msg.xonFlowControl = 0;
+	msg.setFlowControl = 0xff;
+	msg.forwardingLength = 16;
+	msg.xonChar = 17;
+	msg.xoffChar = 19;
+
+	if (reset_port == 1) {
+		/* Opening port */
+		msg._txOn = 1;
+		msg._txOff = 0;
+		msg.txFlush = 0;
+		msg.txBreak = 0;
+		msg.rxOn = 1;
+		msg.rxOff = 0;
+		msg.rxFlush = 1;
+		msg.rxForward = 0;
+		msg.returnStatus = 0;
+		msg.resetDataToggle = 0xff;
+	} else if (reset_port == 2) {
+		/* Closing port */
+		msg._txOn = 0;
+		msg._txOff = 1;
+		msg.txFlush = 0;
+		msg.txBreak = 0;
+		msg.rxOn = 0;
+		msg.rxOff = 1;
+		msg.rxFlush = 1;
+		msg.rxForward = 0;
+		msg.returnStatus = 0;
+		msg.resetDataToggle = 0;
+	} else {
+		/* Sending intermediate configs */
+		msg._txOn = (! p_priv->break_on);
+		msg._txOff = 0;
+		msg.txFlush = 0;
+		msg.txBreak = (p_priv->break_on);
+		msg.rxOn = 0;
+		msg.rxOff = 0;
+		msg.rxFlush = 0;
+		msg.rxForward = 0;
+		msg.returnStatus = 0;
+		msg.resetDataToggle = 0x0;
+	}
+
+	/* Do handshaking outputs */
+	msg.setTxTriState_setRts = 0xff;
+	msg.txTriState_rts = p_priv->rts_state;
+
+	msg.setHskoa_setDtr = 0xff;
+	msg.hskoa_dtr = p_priv->dtr_state;
+
+	p_priv->resend_cont = 0;
+
+	memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
+	/* send the data out the device on control endpoint */
+	this_urb->transfer_buffer_length = sizeof(msg);
+	this_urb->dev = serial->dev;
+
+	err = usb_submit_urb(this_urb, GFP_ATOMIC);
+	if (err != 0)
+		dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__,
+				err);
+	return (0);
+}
+
 static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
 {
 	struct usb_serial *serial = port->serial;
@@ -2265,6 +2624,9 @@
 	case msg_usa90:
 		keyspan_usa90_send_setup(serial, port, reset_port);
 		break;
+	case msg_usa67:
+		keyspan_usa67_send_setup(serial, port, reset_port);
+		break;
 	}
 }
 
@@ -2313,9 +2675,19 @@
 
 	keyspan_setup_urbs(serial);
 
-	s_priv->instat_urb->dev = serial->dev;
-	if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) {
-		dbg("%s - submit instat urb failed %d", __FUNCTION__, err);
+	if (s_priv->instat_urb != NULL) {
+		s_priv->instat_urb->dev = serial->dev;
+		err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
+		if (err != 0)
+			dbg("%s - submit instat urb failed %d", __FUNCTION__,
+				err);
+	}
+	if (s_priv->indat_urb != NULL) {
+		s_priv->indat_urb->dev = serial->dev;
+		err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
+		if (err != 0)
+			dbg("%s - submit indat urb failed %d", __FUNCTION__,
+				err);
 	}
 			
 	return (0);
@@ -2335,6 +2707,7 @@
 	/* Stop reading/writing urbs */
 	stop_urb(s_priv->instat_urb);
 	stop_urb(s_priv->glocont_urb);
+	stop_urb(s_priv->indat_urb);
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		p_priv = usb_get_serial_port_data(port);
@@ -2348,6 +2721,7 @@
 
 	/* Now free them */
 	usb_free_urb(s_priv->instat_urb);
+	usb_free_urb(s_priv->indat_urb);
 	usb_free_urb(s_priv->glocont_urb);
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index c6830cb..8a0d174 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -99,6 +99,10 @@
 					 struct usb_serial_port *port,
 					 int reset_port);
 
+static int  keyspan_usa67_send_setup	(struct usb_serial *serial,
+					 struct usb_serial_port *port,
+					 int reset_port);
+
 /* Struct used for firmware - increased size of data section
    to allow Keyspan's 'C' firmware struct to be used unmodified */
 struct ezusb_hex_record {
@@ -229,15 +233,17 @@
 #define	keyspan_usa28_product_id		0x010f
 #define	keyspan_usa28x_product_id		0x0110
 #define	keyspan_usa28xa_product_id		0x0115
+#define	keyspan_usa28xb_product_id		0x0110
+#define	keyspan_usa28xg_product_id		0x0135
 #define	keyspan_usa49w_product_id		0x010a
 #define	keyspan_usa49wlc_product_id		0x012a
-
+#define	keyspan_usa49wg_product_id		0x0131
 
 struct keyspan_device_details {
 	/* product ID value */
 	int	product_id;
 
-	enum	{msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format;
+	enum	{msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} msg_format;
 
 		/* Number of physical ports */
 	int	num_ports;
@@ -264,6 +270,9 @@
 		/* Endpoint used for input status */
 	int	instat_endpoint;
 
+		/* Endpoint used for input data 49WG only */
+	int	indat_endpoint;
+
 		/* Endpoint used for global control functions */
 	int	glocont_endpoint;
 
@@ -287,6 +296,7 @@
 	.inack_endpoints	= {0x85},
 	.outcont_endpoints	= {0x05},
 	.instat_endpoint	= 0x87,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= 0x07,
 	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
 	.baudclk		= KEYSPAN_USA18X_BAUDCLK,
@@ -303,6 +313,7 @@
 	.inack_endpoints	= {0x83},
 	.outcont_endpoints	= {0x03},
 	.instat_endpoint	= 0x84,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= -1,
 	.calculate_baud_rate	= keyspan_usa19_calc_baud,
 	.baudclk		= KEYSPAN_USA19_BAUDCLK,
@@ -319,6 +330,7 @@
 	.inack_endpoints	= {0x83},
 	.outcont_endpoints	= {0x03},
 	.instat_endpoint	= 0x84,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= -1,
 	.calculate_baud_rate	= keyspan_usa28_calc_baud,
 	.baudclk		= KEYSPAN_USA19_BAUDCLK,
@@ -335,6 +347,7 @@
 	.inack_endpoints	= {0x83},
 	.outcont_endpoints	= {0x03},
 	.instat_endpoint	= 0x84,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= -1,
 	.calculate_baud_rate	= keyspan_usa28_calc_baud,
 	.baudclk		= KEYSPAN_USA19_BAUDCLK,
@@ -351,6 +364,7 @@
 	.inack_endpoints	= {0x85},
 	.outcont_endpoints	= {0x05},
 	.instat_endpoint	= 0x87,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= 0x07,
 	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
 	.baudclk		= KEYSPAN_USA19W_BAUDCLK,
@@ -367,6 +381,7 @@
 	.inack_endpoints	= {0x85},
 	.outcont_endpoints	= {0x05},
 	.instat_endpoint	= 0x87,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= 0x07,
 	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
 	.baudclk		= KEYSPAN_USA19W_BAUDCLK,
@@ -383,6 +398,7 @@
 	.inack_endpoints	= {-1},
 	.outcont_endpoints	= {0x02},
 	.instat_endpoint	= 0x82,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= -1,
 	.calculate_baud_rate	= keyspan_usa19hs_calc_baud,
 	.baudclk		= KEYSPAN_USA19HS_BAUDCLK,
@@ -399,6 +415,7 @@
 	.inack_endpoints	= {0x85, 0x86},
 	.outcont_endpoints	= {0x05, 0x06},
 	.instat_endpoint	= 0x87,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= 0x07,
 	.calculate_baud_rate	= keyspan_usa28_calc_baud,
 	.baudclk		= KEYSPAN_USA28_BAUDCLK,		
@@ -415,6 +432,7 @@
 	.inack_endpoints	= {0x85, 0x86},
 	.outcont_endpoints	= {0x05, 0x06},
 	.instat_endpoint	= 0x87,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= 0x07,
 	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
 	.baudclk		= KEYSPAN_USA28X_BAUDCLK,
@@ -431,11 +449,28 @@
 	.inack_endpoints	= {0x85, 0x86},
 	.outcont_endpoints	= {0x05, 0x06},
 	.instat_endpoint	= 0x87,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= 0x07,
 	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
 	.baudclk		= KEYSPAN_USA28X_BAUDCLK,
 };
 
+static const struct keyspan_device_details usa28xg_device_details = {
+	.product_id		= keyspan_usa28xg_product_id,
+	.msg_format		= msg_usa67,
+	.num_ports		= 2,
+	.indat_endp_flip	= 0,
+	.outdat_endp_flip	= 0,
+	.indat_endpoints	= {0x84, 0x88},
+	.outdat_endpoints	= {0x02, 0x06},
+	.inack_endpoints	= {-1, -1},
+	.outcont_endpoints	= {-1, -1},
+	.instat_endpoint	= 0x81,
+	.indat_endpoint		= -1,
+	.glocont_endpoint	= 0x01,
+	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
+	.baudclk		= KEYSPAN_USA28X_BAUDCLK,
+};
 /* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */
 
 static const struct keyspan_device_details usa49w_device_details = {
@@ -449,6 +484,7 @@
 	.inack_endpoints	= {-1, -1, -1, -1},
 	.outcont_endpoints	= {-1, -1, -1, -1},
 	.instat_endpoint	= 0x87,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= 0x07,
 	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
 	.baudclk		= KEYSPAN_USA49W_BAUDCLK,
@@ -465,11 +501,29 @@
 	.inack_endpoints	= {-1, -1, -1, -1},
 	.outcont_endpoints	= {-1, -1, -1, -1},
 	.instat_endpoint	= 0x87,
+	.indat_endpoint		= -1,
 	.glocont_endpoint	= 0x07,
 	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
 	.baudclk		= KEYSPAN_USA19W_BAUDCLK,
 };
 
+static const struct keyspan_device_details usa49wg_device_details = {
+	.product_id		= keyspan_usa49wg_product_id,
+	.msg_format		= msg_usa49,
+	.num_ports		= 4,
+	.indat_endp_flip	= 0,
+	.outdat_endp_flip	= 0,
+	.indat_endpoints	= {-1, -1, -1, -1},		/* single 'global' data in EP */
+	.outdat_endpoints	= {0x01, 0x02, 0x04, 0x06},
+	.inack_endpoints	= {-1, -1, -1, -1},
+	.outcont_endpoints	= {-1, -1, -1, -1},
+	.instat_endpoint	= 0x81,
+	.indat_endpoint		= 0x88,
+	.glocont_endpoint	= 0x00,				/* uses control EP */
+	.calculate_baud_rate	= keyspan_usa19w_calc_baud,
+	.baudclk		= KEYSPAN_USA19W_BAUDCLK,
+};
+
 static const struct keyspan_device_details *keyspan_devices[] = {
 	&usa18x_device_details,
 	&usa19_device_details,
@@ -481,9 +535,11 @@
 	&usa28_device_details,
 	&usa28x_device_details,
 	&usa28xa_device_details,
+	&usa28xg_device_details,
 	/* 28xb not required as it renumerates as a 28x */
 	&usa49w_device_details,
 	&usa49wlc_device_details,
+	&usa49wg_device_details,
 	NULL,
 };
 
@@ -510,8 +566,11 @@
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
+	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
+	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
+	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
 	{ } /* Terminating entry */
 };
 
@@ -557,12 +616,15 @@
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
+	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
+	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
 	{ } /* Terminating entry */
 };
 
 static struct usb_device_id keyspan_4port_ids[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
+	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
 	{ } /* Terminating entry */
 };
 
@@ -573,7 +635,6 @@
 		.name		= "keyspan_no_firm",
 	},
 	.description		= "Keyspan - (without firmware)",
-	.usb_driver		= &keyspan_driver,
 	.id_table		= keyspan_pre_ids,
 	.num_interrupt_in	= NUM_DONT_CARE,
 	.num_bulk_in		= NUM_DONT_CARE,
@@ -588,7 +649,6 @@
 		.name		= "keyspan_1",
 	},
 	.description		= "Keyspan 1 port adapter",
-	.usb_driver		= &keyspan_driver,
 	.id_table		= keyspan_1port_ids,
 	.num_interrupt_in	= NUM_DONT_CARE,
 	.num_bulk_in		= NUM_DONT_CARE,
@@ -616,7 +676,6 @@
 		.name		= "keyspan_2",
 	},
 	.description		= "Keyspan 2 port adapter",
-	.usb_driver		= &keyspan_driver,
 	.id_table		= keyspan_2port_ids,
 	.num_interrupt_in	= NUM_DONT_CARE,
 	.num_bulk_in		= NUM_DONT_CARE,
@@ -644,11 +703,10 @@
 		.name		= "keyspan_4",
 	},
 	.description		= "Keyspan 4 port adapter",
-	.usb_driver		= &keyspan_driver,
 	.id_table		= keyspan_4port_ids,
 	.num_interrupt_in	= NUM_DONT_CARE,
-	.num_bulk_in		= 5,
-	.num_bulk_out		= 5,
+	.num_bulk_in		= NUM_DONT_CARE,
+	.num_bulk_out		= NUM_DONT_CARE,
 	.num_ports		= 4,
 	.open			= keyspan_open,
 	.close			= keyspan_close,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index dd0b66a..be9ac20 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -218,11 +218,12 @@
        	struct tty_struct *tty = port->tty;
 	unsigned char *data = urb->transfer_buffer;
 	int i;
-	int status;
+	int retval;
+	int status = urb->status;
 	struct keyspan_pda_private *priv;
 	priv = usb_get_serial_port_data(port);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -230,10 +231,12 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d",
+		    __FUNCTION__, status);
 		goto exit;
 	}
 
@@ -268,10 +271,10 @@
 	}
 
 exit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
+	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	if (retval)
 		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, status);
+		     __FUNCTION__, retval);
 }
 
 
diff --git a/drivers/usb/serial/keyspan_usa67msg.h b/drivers/usb/serial/keyspan_usa67msg.h
new file mode 100644
index 0000000..20fa3e2
--- /dev/null
+++ b/drivers/usb/serial/keyspan_usa67msg.h
@@ -0,0 +1,254 @@
+/*
+	usa67msg.h
+
+	Copyright (c) 1998-2007 InnoSys Incorporated.  All Rights Reserved
+	This file is available under a BSD-style copyright
+
+	Keyspan USB Async Firmware to run on Anchor FX1
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are
+	met:
+
+	1. Redistributions of source code must retain this licence text
+   	without modification, this list of conditions, and the following
+   	disclaimer.  The following copyright notice must appear immediately at
+   	the beginning of all source files:
+
+        	Copyright (c) 1998-2007 InnoSys Incorporated.  All Rights Reserved
+
+        	This file is available under a BSD-style copyright
+
+	2. Redistributions in binary form must reproduce the above copyright
+   	notice, this list of conditions and the following disclaimer in the
+   	documentation and/or other materials provided with the distribution.
+
+	3. The name of InnoSys Incorprated may not be used to endorse or promote
+   	products derived from this software without specific prior written
+   	permission.
+
+	THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+	NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+	INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+	LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+	OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+	SUCH DAMAGE.
+
+	Fourth revision: This message format supports the USA28XG
+
+	Buffer formats for RX/TX data messages are not defined by
+	a structure, but are described here:
+
+	USB OUT (host -> USAxx, transmit) messages contain a
+	REQUEST_ACK indicator (set to 0xff to request an ACK at the
+	completion of transmit; 0x00 otherwise), followed by data:
+
+		RQSTACK DAT DAT DAT ...
+
+	with a total data length of up to 63.
+
+	USB IN (USAxx -> host, receive) messages begin with a status
+	byte in which the 0x80 bit is either:
+
+		(a)	0x80 bit clear
+			indicates that the bytes following it are all data
+			bytes:
+
+				STAT DATA DATA DATA DATA DATA ...
+
+			for a total of up to 63 DATA bytes,
+
+	or:
+
+		(b)	0x80 bit set
+			indiates that the bytes following alternate data and
+			status bytes:
+
+				STAT DATA STAT DATA STAT DATA STAT DATA ...
+
+			for a total of up to 32 DATA bytes.
+
+	The valid bits in the STAT bytes are:
+
+		OVERRUN	0x02
+		PARITY	0x04
+		FRAMING	0x08
+		BREAK	0x10
+
+	Notes:
+
+	(1) The OVERRUN bit can appear in either (a) or (b) format
+		messages, but the but the PARITY/FRAMING/BREAK bits
+		only appear in (b) format messages.
+	(2) For the host to determine the exact point at which the
+		overrun occurred (to identify the point in the data
+		stream at which the data was lost), it needs to count
+		128 characters, starting at the first character of the
+		message in which OVERRUN was reported; the lost character(s)
+		would have been received between the 128th and 129th
+		characters.
+	(3)	An RX data message in which the first byte has 0x80 clear
+		serves as a "break off" indicator.
+
+	revision history:
+
+	1999feb10	add reportHskiaChanges to allow us to ignore them
+	1999feb10	add txAckThreshold for fast+loose throughput enhancement
+	1999mar30	beef up support for RX error reporting
+	1999apr14	add resetDataToggle to control message
+	2000jan04	merge with usa17msg.h
+	2000jun01	add extended BSD-style copyright text
+	2001jul05	change message format to improve OVERRUN case
+	2002jun05	update copyright date, improve comments
+	2006feb06	modify for FX1 chip
+
+*/
+
+#ifndef	__USA67MSG__
+#define	__USA67MSG__
+
+
+// all things called "ControlMessage" are sent on the 'control' endpoint
+
+typedef struct keyspan_usa67_portControlMessage
+{
+	u8	port;		// 0 or 1 (selects port)
+	/*
+		there are three types of "commands" sent in the control message:
+
+		1.	configuration changes which must be requested by setting
+			the corresponding "set" flag (and should only be requested
+			when necessary, to reduce overhead on the device):
+	*/
+	u8	setClocking,	// host requests baud rate be set
+		baudLo,			// host does baud divisor calculation
+		baudHi,			// baudHi is only used for first port (gives lower rates)
+		externalClock_txClocking,
+						// 0=internal, other=external
+
+		setLcr,			// host requests lcr be set
+		lcr,			// use PARITY, STOPBITS, DATABITS below
+
+		setFlowControl,	// host requests flow control be set
+		ctsFlowControl,	// 1=use CTS flow control, 0=don't
+		xonFlowControl,	// 1=use XON/XOFF flow control, 0=don't
+		xonChar,		// specified in current character format
+		xoffChar,		// specified in current character format
+
+		setTxTriState_setRts,
+						// host requests TX tri-state be set
+		txTriState_rts,	// 1=active (normal), 0=tristate (off)
+
+		setHskoa_setDtr,
+						// host requests HSKOA output be set
+		hskoa_dtr,		// 1=on, 0=off
+
+		setPrescaler,	// host requests prescalar be set (default: 13)
+		prescaler;		// specified as N/8; values 8-ff are valid
+						// must be set any time internal baud rate is set;
+						// must not be set when external clocking is used
+
+	/*
+		3.	configuration data which is simply used as is (no overhead,
+			but must be specified correctly in every host message).
+	*/
+	u8	forwardingLength,  // forward when this number of chars available
+		reportHskiaChanges_dsrFlowControl,
+						// 1=normal; 0=ignore external clock
+						// 1=use DSR flow control, 0=don't
+		txAckThreshold,	// 0=not allowed, 1=normal, 2-255 deliver ACK faster
+		loopbackMode;	// 0=no loopback, 1=loopback enabled
+
+	/*
+		4.	commands which are flags only; these are processed in order
+			(so that, e.g., if both _txOn and _txOff flags are set, the
+			port ends in a TX_OFF state); any non-zero value is respected
+	*/
+	u8	_txOn,			// enable transmitting (and continue if there's data)
+		_txOff,			// stop transmitting
+		txFlush,		// toss outbound data
+		txBreak,		// turn on break (cleared by _txOn)
+		rxOn,			// turn on receiver
+		rxOff,			// turn off receiver
+		rxFlush,		// toss inbound data
+		rxForward,		// forward all inbound data, NOW (as if fwdLen==1)
+		returnStatus,	// return current status (even if it hasn't changed)
+		resetDataToggle;// reset data toggle state to DATA0
+
+} keyspan_usa67_portControlMessage;
+
+// defines for bits in lcr
+#define	USA_DATABITS_5		0x00
+#define	USA_DATABITS_6		0x01
+#define	USA_DATABITS_7		0x02
+#define	USA_DATABITS_8		0x03
+#define	STOPBITS_5678_1		0x00	// 1 stop bit for all byte sizes
+#define	STOPBITS_5_1p5		0x04	// 1.5 stop bits for 5-bit byte
+#define	STOPBITS_678_2		0x04	// 2 stop bits for 6/7/8-bit byte
+#define	USA_PARITY_NONE		0x00
+#define	USA_PARITY_ODD		0x08
+#define	USA_PARITY_EVEN		0x18
+#define	PARITY_1			0x28
+#define	PARITY_0			0x38
+
+// all things called "StatusMessage" are sent on the status endpoint
+
+typedef struct keyspan_usa67_portStatusMessage	// one for each port
+{
+	u8	port,			// 0=first, 1=second, other=see below
+		hskia_cts,		// reports HSKIA pin
+		gpia_dcd,		// reports GPIA pin
+		_txOff,			// port has been disabled (by host)
+		_txXoff,		// port is in XOFF state (either host or RX XOFF)
+		txAck,			// indicates a TX message acknowledgement
+		rxEnabled,		// as configured by rxOn/rxOff 1=on, 0=off
+		controlResponse;// 1=a control message has been processed
+} keyspan_usa67_portStatusMessage;
+
+// bits in RX data message when STAT byte is included
+#define	RXERROR_OVERRUN	0x02
+#define	RXERROR_PARITY	0x04
+#define	RXERROR_FRAMING	0x08
+#define	RXERROR_BREAK	0x10
+
+typedef struct keyspan_usa67_globalControlMessage
+{
+	u8	port,	 			// 3
+		sendGlobalStatus,	// 2=request for two status responses
+		resetStatusToggle,	// 1=reset global status toggle
+		resetStatusCount;	// a cycling value
+} keyspan_usa67_globalControlMessage;
+
+typedef struct keyspan_usa67_globalStatusMessage
+{
+	u8	port,				// 3
+		sendGlobalStatus,	// from request, decremented
+		resetStatusCount;	// as in request
+} keyspan_usa67_globalStatusMessage;
+
+typedef struct keyspan_usa67_globalDebugMessage
+{
+	u8	port,				// 2
+		a,
+		b,
+		c,
+		d;
+} keyspan_usa67_globalDebugMessage;
+
+// ie: the maximum length of an FX1 endpoint buffer
+#define	MAX_DATA_LEN			64
+
+// update status approx. 60 times a second (16.6666 ms)
+#define	STATUS_UPDATE_INTERVAL	16
+
+// status rationing tuning value (each port gets checked each n ms)
+#define	STATUS_RATION	10
+
+#endif
+
+
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 7b085f3..5a4127e 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -567,12 +567,13 @@
 static void klsi_105_write_bulk_callback ( struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	
-	if (urb->status) {
+
+	if (status) {
 		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		return;
 	}
 
@@ -631,16 +632,17 @@
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	int rc;
+	int status = urb->status;
 
-        dbg("%s - port %d", __FUNCTION__, port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* The urb might have been killed. */
-        if (urb->status) {
-                dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
-		    urb->status);
-                return;
-        }
-	
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
+		    status);
+		return;
+	}
+
 	/* The data received is again preceded by a length double-byte in LSB-
 	 * first order (see klsi_105_write() )
 	 */
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 0683b51..02a86db 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -358,24 +358,26 @@
 }
 
 
-static void kobil_read_int_callback( struct urb *purb)
+static void kobil_read_int_callback(struct urb *urb)
 {
 	int result;
-	struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
+	struct usb_serial_port *port = urb->context;
 	struct tty_struct *tty;
-	unsigned char *data = purb->transfer_buffer;
+	unsigned char *data = urb->transfer_buffer;
+	int status = urb->status;
 //	char *dbg_data;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (purb->status) {
-		dbg("%s - port %d Read int status not zero: %d", __FUNCTION__, port->number, purb->status);
+	if (status) {
+		dbg("%s - port %d Read int status not zero: %d",
+		    __FUNCTION__, port->number, status);
 		return;
 	}
-	
-	tty = port->tty; 
-	if (purb->actual_length) {
-		
+
+	tty = port->tty;
+	if (urb->actual_length) {
+
 		// BEGIN DEBUG
 		/*
 		  dbg_data = kzalloc((3 *  purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
@@ -390,15 +392,15 @@
 		*/
 		// END DEBUG
 
-		tty_buffer_request_room(tty, purb->actual_length);
-		tty_insert_flip_string(tty, data, purb->actual_length);
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
 
 	// someone sets the dev to 0 if the close method has been called
 	port->interrupt_in_urb->dev = port->serial->dev;
 
-	result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); 
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
 	dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
 }
 
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 3db1adc..2a3fabc 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -81,7 +81,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "z2.0"		/* Linux in-kernel version */
+#define DRIVER_VERSION "z2.1"		/* Linux in-kernel version */
 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
 
@@ -110,6 +110,10 @@
 static int  mct_u232_tiocmset		 (struct usb_serial_port *port,
 					  struct file *file, unsigned int set,
 					  unsigned int clear);
+static void mct_u232_throttle		 (struct usb_serial_port *port);
+static void mct_u232_unthrottle		 (struct usb_serial_port *port);
+
+
 /*
  * All of the device info needed for the MCT USB-RS232 converter.
  */
@@ -145,6 +149,8 @@
 	.num_ports =	     1,
 	.open =		     mct_u232_open,
 	.close =	     mct_u232_close,
+	.throttle =	     mct_u232_throttle,
+	.unthrottle =	     mct_u232_unthrottle,
 	.read_int_callback = mct_u232_read_int_callback,
 	.ioctl =	     mct_u232_ioctl,
 	.set_termios =	     mct_u232_set_termios,
@@ -162,8 +168,11 @@
 	unsigned char        last_lcr;      /* Line Control Register */
 	unsigned char	     last_lsr;      /* Line Status Register */
 	unsigned char	     last_msr;      /* Modem Status Register */
+	unsigned int	     rx_flags;      /* Throttling flags */
 };
 
+#define THROTTLED		0x01
+
 /*
  * Handle vendor specific USB requests
  */
@@ -216,11 +225,13 @@
 	}
 }
 
-static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
+static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
+				  int value)
 {
 	__le32 divisor;
         int rc;
         unsigned char zero_byte = 0;
+        unsigned char cts_enable_byte = 0;
 
 	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
 
@@ -238,10 +249,17 @@
 	   'baud rate change' message.  The actual functionality of the
 	   request codes in these messages is not fully understood but these
 	   particular codes are never seen in any operation besides a baud
-	   rate change.  Both of these messages send a single byte of data
-	   whose value is always zero.  The second of these two extra messages
-	   is required in order for data to be properly written to an RS-232
-	   device which does not assert the 'CTS' signal. */
+	   rate change.  Both of these messages send a single byte of data.
+	   In the first message, the value of this byte is always zero.
+
+	   The second message has been determined experimentally to control
+	   whether data will be transmitted to a device which is not asserting
+	   the 'CTS' signal.  If the second message's data byte is zero, data
+	   will be transmitted even if 'CTS' is not asserted (i.e. no hardware
+	   flow control).  if the second message's data byte is nonzero (a value
+	   of 1 is used by this driver), data will not be transmitted to a device
+	   which is not asserting 'CTS'.
+	*/
 
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			     MCT_U232_SET_UNKNOWN1_REQUEST, 
@@ -252,14 +270,19 @@
 		err("Sending USB device request code %d failed (error = %d)", 
 		    MCT_U232_SET_UNKNOWN1_REQUEST, rc);
 
+	if (port && C_CRTSCTS(port->tty)) {
+	   cts_enable_byte = 1;
+	}
+
+        dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			     MCT_U232_SET_UNKNOWN2_REQUEST, 
+			     MCT_U232_SET_CTS_REQUEST,
 			     MCT_U232_SET_REQUEST_TYPE,
-			     0, 0, &zero_byte, MCT_U232_SET_UNKNOWN2_SIZE, 
+			     0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
 			     WDR_TIMEOUT);
 	if (rc < 0)
-		err("Sending USB device request code %d failed (error = %d)", 
-		    MCT_U232_SET_UNKNOWN2_REQUEST, rc);
+	  err("Sending USB device request code %d failed (error = %d)",
+	      MCT_U232_SET_CTS_REQUEST, rc);
 
         return rc;
 } /* mct_u232_set_baud_rate */
@@ -458,8 +481,25 @@
 
 static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
 {
+	unsigned int c_cflag;
+	unsigned long flags;
+	unsigned int control_state;
+	struct mct_u232_private *priv = usb_get_serial_port_data(port);
 	dbg("%s port %d", __FUNCTION__, port->number);
 
+   	if (port->tty) {
+		c_cflag = port->tty->termios->c_cflag;
+		if (c_cflag & HUPCL) {
+		   /* drop DTR and RTS */
+		   spin_lock_irqsave(&priv->lock, flags);
+		   priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+		   control_state = priv->control_state;
+		   spin_unlock_irqrestore(&priv->lock, flags);
+		   mct_u232_set_modem_ctrl(port->serial, control_state);
+		}
+	}
+
+
 	if (port->serial->dev) {
 		/* shutdown our urbs */
 		usb_kill_urb(port->write_urb);
@@ -476,10 +516,11 @@
 	struct usb_serial *serial = port->serial;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
-	int status;
+	int retval;
+	int status = urb->status;
 	unsigned long flags;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -487,10 +528,12 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d",
+		    __FUNCTION__, status);
 		goto exit;
 	}
 
@@ -554,10 +597,10 @@
 #endif
 	spin_unlock_irqrestore(&priv->lock, flags);
 exit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
+	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	if (retval)
 		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, status);
+		     __FUNCTION__, retval);
 } /* mct_u232_read_int_callback */
 
 static void mct_u232_set_termios (struct usb_serial_port *port,
@@ -565,11 +608,10 @@
 {
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
-	unsigned int iflag = port->tty->termios->c_iflag;
 	unsigned int cflag = port->tty->termios->c_cflag;
 	unsigned int old_cflag = old_termios->c_cflag;
 	unsigned long flags;
-	unsigned int control_state, new_state;
+	unsigned int control_state;
 	unsigned char last_lcr;
 
 	/* get a local copy of the current port settings */
@@ -585,18 +627,14 @@
 	 * Premature optimization is the root of all evil.
 	 */
 
-        /* reassert DTR and (maybe) RTS on transition from B0 */
+        /* reassert DTR and RTS on transition from B0 */
 	if ((old_cflag & CBAUD) == B0) {
 		dbg("%s: baud was B0", __FUNCTION__);
-		control_state |= TIOCM_DTR;
-		/* don't set RTS if using hardware flow control */
-		if (!(old_cflag & CRTSCTS)) {
-			control_state |= TIOCM_RTS;
-		}
+		control_state |= TIOCM_DTR | TIOCM_RTS;
 		mct_u232_set_modem_ctrl(serial, control_state);
 	}
 
-	mct_u232_set_baud_rate(serial, cflag & CBAUD);
+	mct_u232_set_baud_rate(serial, port, cflag & CBAUD);
 
 	if ((cflag & CBAUD) == B0 ) {
 		dbg("%s: baud is B0", __FUNCTION__);
@@ -638,21 +676,6 @@
 
 	mct_u232_set_line_ctrl(serial, last_lcr);
 
-	/*
-	 * Set flow control: well, I do not really now how to handle DTR/RTS.
-	 * Just do what we have seen with SniffUSB on Win98.
-	 */
-	/* Drop DTR/RTS if no flow control otherwise assert */
-	new_state = control_state;
-	if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
-		new_state |= TIOCM_DTR | TIOCM_RTS;
-	else
-		new_state &= ~(TIOCM_DTR | TIOCM_RTS);
-	if (new_state != control_state) {
-		mct_u232_set_modem_ctrl(serial, new_state);
-		control_state = new_state;
-	}
-
 	/* save off the modified port settings */
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->control_state = control_state;
@@ -747,6 +770,50 @@
 	return 0;
 } /* mct_u232_ioctl */
 
+static void mct_u232_throttle (struct usb_serial_port *port)
+{
+	struct mct_u232_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int control_state;
+	struct tty_struct *tty;
+
+	tty = port->tty;
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->rx_flags |= THROTTLED;
+	if (C_CRTSCTS(tty)) {
+	  priv->control_state &= ~TIOCM_RTS;
+	  control_state = priv->control_state;
+	  spin_unlock_irqrestore(&priv->lock, flags);
+	  (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+	} else {
+	  spin_unlock_irqrestore(&priv->lock, flags);
+	}
+}
+
+
+static void mct_u232_unthrottle (struct usb_serial_port *port)
+{
+	struct mct_u232_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int control_state;
+	struct tty_struct *tty;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	tty = port->tty;
+	spin_lock_irqsave(&priv->lock, flags);
+	if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
+	  priv->rx_flags &= ~THROTTLED;
+	  priv->control_state |= TIOCM_RTS;
+	  control_state = priv->control_state;
+	  spin_unlock_irqrestore(&priv->lock, flags);
+	  (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+	} else {
+	  spin_unlock_irqrestore(&priv->lock, flags);
+	}
+}
 
 static int __init mct_u232_init (void)
 {
diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h
index 73dd0d9..a61bac8 100644
--- a/drivers/usb/serial/mct_u232.h
+++ b/drivers/usb/serial/mct_u232.h
@@ -63,14 +63,15 @@
 #define MCT_U232_SET_UNKNOWN1_REQUEST   11  /* Unknown functionality */
 #define MCT_U232_SET_UNKNOWN1_SIZE       1
 
-/* This USB device request code is not well understood.  It is transmitted by
-   the MCT-supplied Windows driver whenever the baud rate changes. 
+/* This USB device request code appears to control whether CTS is required
+   during transmission.
    
-   Without this USB device request, the USB/RS-232 adapter will not write to
-   RS-232 devices which do not assert the 'CTS' signal.
+   Sending a zero byte allows data transmission to a device which is not
+   asserting CTS.  Sending a '1' byte will cause transmission to be deferred
+   until the device asserts CTS.
 */
-#define MCT_U232_SET_UNKNOWN2_REQUEST   12  /* Unknown functionality */
-#define MCT_U232_SET_UNKNOWN2_SIZE       1
+#define MCT_U232_SET_CTS_REQUEST   12
+#define MCT_U232_SET_CTS_SIZE       1
 
 /*
  * Baud rate (divisor)
@@ -439,7 +440,7 @@
  * which says "U232-P9" ;-)
  * 
  * The circuit board inside the adaptor contains a Philips PDIUSBD12
- * USB endpoint chip and a Phillips P87C52UBAA microcontroller with
+ * USB endpoint chip and a Philips P87C52UBAA microcontroller with
  * embedded UART.  Exhaustive documentation for these is available at:
  *
  *   http://www.semiconductors.philips.com/pip/p87c52ubaa
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index b563e2a..231b584 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -9,9 +9,9 @@
  * the Free Software Foundation, version 2 of the License.
  *
  * Developed by:
- * 	VijayaKumar.G.N. <vijaykumar@aspirecom.net>
- *	AjayKumar <ajay@aspirecom.net>
- *	Gurudeva.N. <gurudev@aspirecom.net>
+ * 	Vijaya Kumar <vijaykumar.gn@gmail.com>
+ *	Ajay Kumar <naanuajay@yahoo.com>
+ *	Gurudeva <ngurudeva@yahoo.com>
  *
  * Cleaned up from the original by:
  *	Greg Kroah-Hartman <gregkh@suse.de>
@@ -103,6 +103,7 @@
 {
 	int result;
 	int length;
+	int status = urb->status;
 	__u8 *data;
 	__u8 sp1;
 	__u8 sp2;
@@ -114,7 +115,7 @@
 		return;
 	}
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -123,11 +124,11 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		goto exit;
 	}
 
@@ -198,14 +199,15 @@
  */
 static void mos7720_bulk_in_callback(struct urb *urb)
 {
-	int status;
+	int retval;
 	unsigned char *data ;
 	struct usb_serial_port *port;
 	struct moschip_port *mos7720_port;
 	struct tty_struct *tty;
+	int status = urb->status;
 
-	if (urb->status) {
-		dbg("nonzero read bulk status received: %d",urb->status);
+	if (status) {
+		dbg("nonzero read bulk status received: %d", status);
 		return;
 	}
 
@@ -236,10 +238,10 @@
 	if (port->read_urb->status != -EINPROGRESS) {
 		port->read_urb->dev = port->serial->dev;
 
-		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-		if (status)
-			dbg("usb_submit_urb(read bulk) failed, status = %d",
-			    status);
+		retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (retval)
+			dbg("usb_submit_urb(read bulk) failed, retval = %d",
+			    retval);
 	}
 }
 
@@ -252,9 +254,10 @@
 {
 	struct moschip_port *mos7720_port;
 	struct tty_struct *tty;
+	int status = urb->status;
 
-	if (urb->status) {
-		dbg("nonzero write bulk status received:%d", urb->status);
+	if (status) {
+		dbg("nonzero write bulk status received:%d", status);
 		return;
 	}
 
@@ -1235,16 +1238,6 @@
 		return;
 	}
 
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(tty->termios->c_iflag) ==
-		     RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg("Nothing to change");
-			return;
-		}
-	}
-
 	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
 	    tty->termios->c_cflag,
 	    RELEVANT_IFLAG(tty->termios->c_iflag));
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 2366e7b..37f41f5 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -434,6 +434,7 @@
 	struct moschip_port *mos7840_port;
 	__u8 regval = 0x0;
 	int result = 0;
+	int status = urb->status;
 
 	if (!urb) {
 		dbg("%s", "Invalid Pointer !!!!:\n");
@@ -442,7 +443,7 @@
 
 	mos7840_port = (struct moschip_port *)urb->context;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -451,11 +452,11 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		goto exit;
 	}
 
@@ -521,6 +522,7 @@
 	__u8 sp[5], st;
 	int i, rv = 0;
 	__u16 wval, wreg = 0;
+	int status = urb->status;
 
 	dbg("%s", " : Entering\n");
 	if (!urb) {
@@ -528,7 +530,7 @@
 		return;
 	}
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -537,11 +539,11 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		goto exit;
 	}
 
@@ -666,20 +668,21 @@
 
 static void mos7840_bulk_in_callback(struct urb *urb)
 {
-	int status;
+	int retval;
 	unsigned char *data;
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
 	struct moschip_port *mos7840_port;
 	struct tty_struct *tty;
+	int status = urb->status;
 
 	if (!urb) {
 		dbg("%s", "Invalid Pointer !!!!:\n");
 		return;
 	}
 
-	if (urb->status) {
-		dbg("nonzero read bulk status received: %d", urb->status);
+	if (status) {
+		dbg("nonzero read bulk status received: %d", status);
 		return;
 	}
 
@@ -729,11 +732,11 @@
 
 	mos7840_port->read_urb->dev = serial->dev;
 
-	status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+	retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
 
-	if (status) {
-		dbg(" usb_submit_urb(read bulk) failed, status = %d",
-		 status);
+	if (retval) {
+		dbg(" usb_submit_urb(read bulk) failed, retval = %d",
+		 retval);
 	}
 }
 
@@ -747,6 +750,7 @@
 {
 	struct moschip_port *mos7840_port;
 	struct tty_struct *tty;
+	int status = urb->status;
 	int i;
 
 	if (!urb) {
@@ -764,13 +768,8 @@
 	}
 	spin_unlock(&mos7840_port->pool_lock);
 
-	if (urb->status) {
-		dbg("nonzero write bulk status received:%d\n", urb->status);
-		return;
-	}
-
-	if (!mos7840_port) {
-		dbg("%s", "NULL mos7840_port pointer \n");
+	if (status) {
+		dbg("nonzero write bulk status received:%d\n", status);
 		return;
 	}
 
@@ -2190,16 +2189,6 @@
 		return;
 	}
 
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(tty->termios->c_iflag) ==
-		     RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg("%s\n", "Nothing to change");
-			return;
-		}
-	}
-
 	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
 	    tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
 
@@ -2259,30 +2248,6 @@
 }
 
 /*****************************************************************************
- * mos7840_get_bytes_avail - get number of bytes available
- *
- * Purpose: Let user call ioctl to get the count of number of bytes available.
- *****************************************************************************/
-
-static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port,
-				   unsigned int __user *value)
-{
-	unsigned int result = 0;
-	struct tty_struct *tty = mos7840_port->port->tty;
-
-	if (!tty)
-		return -ENOIOCTLCMD;
-
-	result = tty->read_cnt;
-
-	dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result);
-	if (copy_to_user(value, &result, sizeof(int)))
-		return -EFAULT;
-
-	return -ENOIOCTLCMD;
-}
-
-/*****************************************************************************
  * mos7840_set_modem_info
  *      function to set modem info
  *****************************************************************************/
@@ -2430,8 +2395,6 @@
 	struct async_icount cprev;
 	struct serial_icounter_struct icount;
 	int mosret = 0;
-	int retval;
-	struct tty_ldisc *ld;
 
 	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
 		dbg("%s", "Invalid port \n");
@@ -2450,42 +2413,6 @@
 	switch (cmd) {
 		/* return number of bytes available */
 
-	case TIOCINQ:
-		dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
-		return mos7840_get_bytes_avail(mos7840_port, argp);
-
-	case TIOCOUTQ:
-		dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number);
-		return put_user(tty->driver->chars_in_buffer ?
-				tty->driver->chars_in_buffer(tty) : 0,
-				(int __user *)arg);
-
-	case TCFLSH:
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-
-		ld = tty_ldisc_ref(tty);
-		switch (arg) {
-		case TCIFLUSH:
-			if (ld && ld->flush_buffer)
-				ld->flush_buffer(tty);
-			break;
-		case TCIOFLUSH:
-			if (ld && ld->flush_buffer)
-				ld->flush_buffer(tty);
-			/* fall through */
-		case TCOFLUSH:
-			if (tty->driver->flush_buffer)
-				tty->driver->flush_buffer(tty);
-			break;
-		default:
-			tty_ldisc_deref(ld);
-			return -EINVAL;
-		}
-		tty_ldisc_deref(ld);
-		return 0;
-
 	case TIOCSERGETLSR:
 		dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
 		return mos7840_get_lsr_info(mos7840_port, argp);
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 9070111..7f337c9 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -37,9 +37,10 @@
 	struct usb_serial_port *port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
 	struct tty_struct *tty;
+	int status = urb->status;
 	int result;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -48,11 +49,11 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
+		    __FUNCTION__, status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
+		    __FUNCTION__, status);
 		goto exit;
 	}
 
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 4adfab9..ee94d96 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -1,10 +1,9 @@
 /*
  * USB ZyXEL omni.net LCD PLUS driver
  *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
@@ -165,12 +164,10 @@
 {
 	struct usb_serial	*serial = port->serial;
 	struct usb_serial_port	*wport;
-	struct omninet_data	*od = usb_get_serial_port_data(port);
 	int			result = 0;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
 	wport = serial->port[1];
 	wport->tty = port->tty;
 
@@ -203,14 +200,15 @@
 	struct usb_serial_port 	*port 	= (struct usb_serial_port *)urb->context;
 	unsigned char 		*data 	= urb->transfer_buffer;
 	struct omninet_header 	*header = (struct omninet_header *) &data[0];
-
+	int status = urb->status;
 	int i;
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -314,12 +312,14 @@
 {
 /*	struct omninet_header	*header = (struct omninet_header  *) urb->transfer_buffer; */
 	struct usb_serial_port 	*port   = (struct usb_serial_port *) urb->context;
+	int status = urb->status;
 
 	dbg("%s - port %0x\n", __FUNCTION__, port->number);
 
 	port->write_urb_busy = 0;
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 8c3f55b..84c12b5 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -38,6 +38,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -111,7 +112,8 @@
 #define NOVATELWIRELESS_VENDOR_ID		0x1410
 
 #define ANYDATA_VENDOR_ID			0x16d5
-#define ANYDATA_PRODUCT_ID			0x6501
+#define ANYDATA_PRODUCT_ADU_E100A		0x6501
+#define ANYDATA_PRODUCT_ADU_500A		0x6502
 
 #define BANDRICH_VENDOR_ID			0x1A8D
 #define BANDRICH_PRODUCT_C100_1			0x1002
@@ -165,12 +167,12 @@
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel XU870 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
-	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
+	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
+	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
 	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
 	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) },		/* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard */
@@ -239,6 +241,7 @@
 	/* Output endpoints and buffer for this port */
 	struct urb *out_urbs[N_OUT_URB];
 	char out_buffer[N_OUT_URB][OUT_BUFLEN];
+	unsigned long out_busy;		/* Bit vector of URBs in use */
 
 	/* Settings for the port */
 	int rts_state;	/* Handshaking pins (outputs) */
@@ -369,7 +372,7 @@
 			todo = OUT_BUFLEN;
 
 		this_urb = portdata->out_urbs[i];
-		if (this_urb->status == -EINPROGRESS) {
+		if (test_and_set_bit(i, &portdata->out_busy)) {
 			if (time_before(jiffies,
 					portdata->tx_start_time[i] + 10 * HZ))
 				continue;
@@ -393,6 +396,7 @@
 			dbg("usb_submit_urb %p (write bulk) failed "
 				"(%d, has %d)", this_urb,
 				err, this_urb->status);
+			clear_bit(i, &portdata->out_busy);
 			continue;
 		}
 		portdata->tx_start_time[i] = jiffies;
@@ -412,15 +416,16 @@
 	struct usb_serial_port *port;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
+	int status = urb->status;
 
 	dbg("%s: %p", __FUNCTION__, urb);
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 	port = (struct usb_serial_port *) urb->context;
 
-	if (urb->status) {
+	if (status) {
 		dbg("%s: nonzero status: %d on endpoint %02x.",
-		    __FUNCTION__, urb->status, endpoint);
+		    __FUNCTION__, status, endpoint);
 	} else {
 		tty = port->tty;
 		if (urb->actual_length) {
@@ -432,7 +437,7 @@
 		}
 
 		/* Resubmit urb so we continue receiving */
-		if (port->open_count && urb->status != -ESHUTDOWN) {
+		if (port->open_count && status != -ESHUTDOWN) {
 			err = usb_submit_urb(urb, GFP_ATOMIC);
 			if (err)
 				printk(KERN_ERR "%s: resubmit read urb failed. "
@@ -445,17 +450,29 @@
 static void option_outdat_callback(struct urb *urb)
 {
 	struct usb_serial_port *port;
+	struct option_port_private *portdata;
+	int i;
 
 	dbg("%s", __FUNCTION__);
 
 	port = (struct usb_serial_port *) urb->context;
 
 	usb_serial_port_softint(port);
+
+	portdata = usb_get_serial_port_data(port);
+	for (i = 0; i < N_OUT_URB; ++i) {
+		if (portdata->out_urbs[i] == urb) {
+			smp_mb__before_clear_bit();
+			clear_bit(i, &portdata->out_busy);
+			break;
+		}
+	}
 }
 
 static void option_instat_callback(struct urb *urb)
 {
 	int err;
+	int status = urb->status;
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct option_port_private *portdata = usb_get_serial_port_data(port);
 	struct usb_serial *serial = port->serial;
@@ -463,7 +480,7 @@
 	dbg("%s", __FUNCTION__);
 	dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
 
-	if (urb->status == 0) {
+	if (status == 0) {
 		struct usb_ctrlrequest *req_pkt =
 				(struct usb_ctrlrequest *)urb->transfer_buffer;
 
@@ -494,10 +511,10 @@
 				req_pkt->bRequestType,req_pkt->bRequest);
 		}
 	} else
-		dbg("%s: error %d", __FUNCTION__, urb->status);
+		dbg("%s: error %d", __FUNCTION__, status);
 
 	/* Resubmit urb so we continue receiving IRQ data */
-	if (urb->status != -ESHUTDOWN) {
+	if (status != -ESHUTDOWN) {
 		urb->dev = serial->dev;
 		err = usb_submit_urb(urb, GFP_ATOMIC);
 		if (err)
@@ -517,7 +534,7 @@
 
 	for (i=0; i < N_OUT_URB; i++) {
 		this_urb = portdata->out_urbs[i];
-		if (this_urb && this_urb->status != -EINPROGRESS)
+		if (this_urb && !test_bit(i, &portdata->out_busy))
 			data_len += OUT_BUFLEN;
 	}
 
@@ -536,7 +553,7 @@
 
 	for (i=0; i < N_OUT_URB; i++) {
 		this_urb = portdata->out_urbs[i];
-		if (this_urb && this_urb->status == -EINPROGRESS)
+		if (this_urb && test_bit(i, &portdata->out_busy))
 			data_len += this_urb->transfer_buffer_length;
 	}
 	dbg("%s: %d", __FUNCTION__, data_len);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
new file mode 100644
index 0000000..d7db71e
--- /dev/null
+++ b/drivers/usb/serial/oti6858.c
@@ -0,0 +1,1342 @@
+/*
+ * Ours Technology Inc. OTi-6858 USB to serial adapter driver.
+ *
+ * Copyleft  (C) 2007 Kees Lemmens (adapted for kernel 2.6.20)
+ * Copyright (C) 2006 Tomasz Michal Lukaszewski (FIXME: add e-mail)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2003 IBM Corp.
+ *
+ * Many thanks to the authors of pl2303 driver: all functions in this file
+ * are heavily based on pl2303 code, buffering code is a 1-to-1 copy.
+ *
+ * Warning! You use this driver on your own risk! The only official
+ * description of this device I have is datasheet from manufacturer,
+ * and it doesn't contain almost any information needed to write a driver.
+ * Almost all knowlegde used while writing this driver was gathered by:
+ *  - analyzing traffic between device and the M$ Windows 2000 driver,
+ *  - trying different bit combinations and checking pin states
+ *    with a voltmeter,
+ *  - receiving malformed frames and producing buffer overflows
+ *    to learn how errors are reported,
+ * So, THIS CODE CAN DESTROY OTi-6858 AND ANY OTHER DEVICES, THAT ARE
+ * CONNECTED TO IT!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * TODO:
+ *  - implement correct flushing for ioctls and oti6858_close()
+ *  - check how errors (rx overflow, parity error, framing error) are reported
+ *  - implement oti6858_break_ctl()
+ *  - implement more ioctls
+ *  - test/implement flow control
+ *  - allow setting custom baud rates
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+#include "oti6858.h"
+
+#define OTI6858_DESCRIPTION \
+	"Ours Technology Inc. OTi-6858 USB to serial adapter driver"
+#define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>"
+#define OTI6858_VERSION "0.1"
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver oti6858_driver = {
+	.name =		"oti6858",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+	.no_dynamic_id = 	1,
+};
+
+static int debug;
+
+
+/* buffering code, copied from pl2303 driver */
+#define PL2303_BUF_SIZE		1024
+#define PL2303_TMP_BUF_SIZE	1024
+
+struct pl2303_buf {
+	unsigned int	buf_size;
+	char		*buf_buf;
+	char		*buf_get;
+	char		*buf_put;
+};
+
+/* requests */
+#define	OTI6858_REQ_GET_STATUS		(USB_DIR_IN | USB_TYPE_VENDOR | 0x00)
+#define	OTI6858_REQ_T_GET_STATUS	0x01
+
+#define	OTI6858_REQ_SET_LINE		(USB_DIR_OUT | USB_TYPE_VENDOR | 0x00)
+#define	OTI6858_REQ_T_SET_LINE		0x00
+
+#define	OTI6858_REQ_CHECK_TXBUFF	(USB_DIR_IN | USB_TYPE_VENDOR | 0x01)
+#define	OTI6858_REQ_T_CHECK_TXBUFF	0x00
+
+/* format of the control packet */
+struct oti6858_control_pkt {
+	u16	divisor;	/* baud rate = 96000000 / (16 * divisor), LE */
+#define OTI6858_MAX_BAUD_RATE	3000000
+	u8	frame_fmt;
+#define FMT_STOP_BITS_MASK	0xc0
+#define FMT_STOP_BITS_1		0x00
+#define FMT_STOP_BITS_2		0x40	/* 1.5 stop bits if FMT_DATA_BITS_5 */
+#define FMT_PARITY_MASK		0x38
+#define FMT_PARITY_NONE		0x00
+#define FMT_PARITY_ODD		0x08
+#define FMT_PARITY_EVEN		0x18
+#define FMT_PARITY_MARK		0x28
+#define FMT_PARITY_SPACE	0x38
+#define FMT_DATA_BITS_MASK	0x03
+#define FMT_DATA_BITS_5		0x00
+#define FMT_DATA_BITS_6		0x01
+#define FMT_DATA_BITS_7		0x02
+#define FMT_DATA_BITS_8		0x03
+	u8	something;	/* always equals 0x43 */
+	u8	control;	/* settings of flow control lines */
+#define CONTROL_MASK		0x0c
+#define CONTROL_DTR_HIGH	0x08
+#define CONTROL_RTS_HIGH	0x04
+	u8	tx_status;
+#define	TX_BUFFER_EMPTIED	0x09
+	u8	pin_state;
+#define PIN_MASK		0x3f
+#define PIN_RTS			0x20	/* output pin */
+#define PIN_CTS			0x10	/* input pin, active low */
+#define PIN_DSR			0x08	/* input pin, active low */
+#define PIN_DTR			0x04	/* output pin */
+#define PIN_RI			0x02	/* input pin, active low */
+#define PIN_DCD			0x01	/* input pin, active low */
+	u8	rx_bytes_avail;		/* number of bytes in rx buffer */;
+};
+
+#define OTI6858_CTRL_PKT_SIZE	sizeof(struct oti6858_control_pkt)
+#define OTI6858_CTRL_EQUALS_PENDING(a, priv) \
+	(    ((a)->divisor == (priv)->pending_setup.divisor) \
+	  && ((a)->control == (priv)->pending_setup.control) \
+	  && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) )
+
+/* function prototypes */
+static int oti6858_open(struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct usb_serial_port *port, struct file *filp);
+static void oti6858_set_termios(struct usb_serial_port *port,
+				struct ktermios *old);
+static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+			unsigned int cmd, unsigned long arg);
+static void oti6858_read_int_callback(struct urb *urb);
+static void oti6858_read_bulk_callback(struct urb *urb);
+static void oti6858_write_bulk_callback(struct urb *urb);
+static int oti6858_write(struct usb_serial_port *port,
+			const unsigned char *buf, int count);
+static int oti6858_write_room(struct usb_serial_port *port);
+static void oti6858_break_ctl(struct usb_serial_port *port, int break_state);
+static int oti6858_chars_in_buffer(struct usb_serial_port *port);
+static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file);
+static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+				unsigned int set, unsigned int clear);
+static int oti6858_startup(struct usb_serial *serial);
+static void oti6858_shutdown(struct usb_serial *serial);
+
+/* functions operating on buffers */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
+static void pl2303_buf_free(struct pl2303_buf *pb);
+static void pl2303_buf_clear(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+					unsigned int count);
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+					unsigned int count);
+
+
+/* device info */
+static struct usb_serial_driver oti6858_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"oti6858",
+	},
+	.id_table =		id_table,
+	.num_interrupt_in =	1,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.open =			oti6858_open,
+	.close =		oti6858_close,
+	.write =		oti6858_write,
+	.ioctl =		oti6858_ioctl,
+	.break_ctl =		oti6858_break_ctl,
+	.set_termios =		oti6858_set_termios,
+	.tiocmget =		oti6858_tiocmget,
+	.tiocmset =		oti6858_tiocmset,
+	.read_bulk_callback =	oti6858_read_bulk_callback,
+	.read_int_callback =	oti6858_read_int_callback,
+	.write_bulk_callback =	oti6858_write_bulk_callback,
+	.write_room =		oti6858_write_room,
+	.chars_in_buffer =	oti6858_chars_in_buffer,
+	.attach =		oti6858_startup,
+	.shutdown =		oti6858_shutdown,
+};
+
+struct oti6858_private {
+	spinlock_t lock;
+
+	struct pl2303_buf *buf;
+	struct oti6858_control_pkt status;
+
+	struct {
+		u8 read_urb_in_use;
+		u8 write_urb_in_use;
+		u8 termios_initialized;
+	} flags;
+	struct delayed_work delayed_write_work;
+
+	struct {
+		u16 divisor;
+		u8 frame_fmt;
+		u8 control;
+	} pending_setup;
+	u8 transient;
+	u8 setup_done;
+	struct delayed_work delayed_setup_work;
+
+	wait_queue_head_t intr_wait;
+        struct usb_serial_port *port;   /* USB port with which associated */
+};
+
+#undef dbg
+/* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */
+#define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg)
+
+static void setup_line(struct work_struct *work)
+{
+	struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work);
+	struct usb_serial_port *port = priv->port;
+	struct oti6858_control_pkt *new_setup;
+	unsigned long flags;
+	int result;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+		dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
+		/* we will try again */
+		schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+		return;
+	}
+
+	result = usb_control_msg(port->serial->dev,
+				usb_rcvctrlpipe(port->serial->dev, 0),
+				OTI6858_REQ_T_GET_STATUS,
+				OTI6858_REQ_GET_STATUS,
+				0, 0,
+				new_setup, OTI6858_CTRL_PKT_SIZE,
+				100);
+
+	if (result != OTI6858_CTRL_PKT_SIZE) {
+		dev_err(&port->dev, "%s(): error reading status", __FUNCTION__);
+		kfree(new_setup);
+		/* we will try again */
+		schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!OTI6858_CTRL_EQUALS_PENDING(new_setup, priv)) {
+		new_setup->divisor = priv->pending_setup.divisor;
+		new_setup->control = priv->pending_setup.control;
+		new_setup->frame_fmt = priv->pending_setup.frame_fmt;
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+		result = usb_control_msg(port->serial->dev,
+					usb_sndctrlpipe(port->serial->dev, 0),
+					OTI6858_REQ_T_SET_LINE,
+					OTI6858_REQ_SET_LINE,
+					0, 0,
+					new_setup, OTI6858_CTRL_PKT_SIZE,
+					100);
+	} else {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		result = 0;
+	}
+	kfree(new_setup);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (result != OTI6858_CTRL_PKT_SIZE)
+		priv->transient = 0;
+	priv->setup_done = 1;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	dbg("%s(): submitting interrupt urb", __FUNCTION__);
+	port->interrupt_in_urb->dev = port->serial->dev;
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+	if (result != 0) {
+		dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+				" with error %d\n", __FUNCTION__, result);
+	}
+}
+
+void send_data(struct work_struct *work)
+{
+	struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work);
+	struct usb_serial_port *port = priv->port;
+	int count = 0, result;
+	unsigned long flags;
+	unsigned char allow;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->flags.write_urb_in_use) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2));
+		return;
+	}
+	priv->flags.write_urb_in_use = 1;
+
+	count = pl2303_buf_data_avail(priv->buf);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	if (count > port->bulk_out_size)
+		count = port->bulk_out_size;
+
+	if (count != 0) {
+		result = usb_control_msg(port->serial->dev,
+				usb_rcvctrlpipe(port->serial->dev, 0),
+				OTI6858_REQ_T_CHECK_TXBUFF,
+				OTI6858_REQ_CHECK_TXBUFF,
+				count, 0, &allow, 1, 100);
+		if (result != 1 || allow != 0)
+			count = 0;
+	}
+
+	if (count == 0) {
+		priv->flags.write_urb_in_use = 0;
+
+		dbg("%s(): submitting interrupt urb", __FUNCTION__);
+		port->interrupt_in_urb->dev = port->serial->dev;
+		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+		if (result != 0) {
+			dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+				" with error %d\n", __FUNCTION__, result);
+		}
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, count);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	port->write_urb->transfer_buffer_length = count;
+	port->write_urb->dev = port->serial->dev;
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+	if (result != 0) {
+		dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+			       " with error %d\n", __FUNCTION__, result);
+		priv->flags.write_urb_in_use = 0;
+	}
+
+	usb_serial_port_softint(port);
+}
+
+static int oti6858_startup(struct usb_serial *serial)
+{
+        struct usb_serial_port *port = serial->port[0];
+        struct oti6858_private *priv;
+	int i;
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
+		if (!priv)
+			break;
+		priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
+		if (priv->buf == NULL) {
+			kfree(priv);
+			break;
+		}
+
+		spin_lock_init(&priv->lock);
+		init_waitqueue_head(&priv->intr_wait);
+//		INIT_WORK(&priv->setup_work, setup_line, serial->port[i]);
+//		INIT_WORK(&priv->write_work, send_data, serial->port[i]);
+		priv->port = port;
+		INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
+		INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
+
+		usb_set_serial_port_data(serial->port[i], priv);
+	}
+	if (i == serial->num_ports)
+		return 0;
+
+	for (--i; i >= 0; --i) {
+		priv = usb_get_serial_port_data(serial->port[i]);
+		pl2303_buf_free(priv->buf);
+		kfree(priv);
+		usb_set_serial_port_data(serial->port[i], NULL);
+	}
+	return -ENOMEM;
+}
+
+static int oti6858_write(struct usb_serial_port *port,
+			const unsigned char *buf, int count)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
+	dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count);
+
+	if (!count)
+		return count;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	count = pl2303_buf_put(priv->buf, buf, count);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return count;
+}
+
+static int oti6858_write_room(struct usb_serial_port *port)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	int room = 0;
+	unsigned long flags;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	room = pl2303_buf_space_avail(priv->buf);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return room;
+}
+
+static int oti6858_chars_in_buffer(struct usb_serial_port *port)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	int chars = 0;
+	unsigned long flags;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	chars = pl2303_buf_data_avail(priv->buf);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return chars;
+}
+
+static void oti6858_set_termios(struct usb_serial_port *port,
+				struct ktermios *old_termios)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int cflag;
+	u8 frame_fmt, control;
+	u16 divisor;
+	int br;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	if ((!port->tty) || (!port->tty->termios)) {
+		dbg("%s(): no tty structures", __FUNCTION__);
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!priv->flags.termios_initialized) {
+		*(port->tty->termios) = tty_std_termios;
+		port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+		priv->flags.termios_initialized = 1;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	cflag = port->tty->termios->c_cflag;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	divisor = priv->pending_setup.divisor;
+	frame_fmt = priv->pending_setup.frame_fmt;
+	control = priv->pending_setup.control;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	frame_fmt &= ~FMT_DATA_BITS_MASK;
+	switch (cflag & CSIZE) {
+		case CS5:
+			frame_fmt |= FMT_DATA_BITS_5;
+			break;
+		case CS6:
+			frame_fmt |= FMT_DATA_BITS_6;
+			break;
+		case CS7:
+			frame_fmt |= FMT_DATA_BITS_7;
+			break;
+		default:
+		case CS8:
+			frame_fmt |= FMT_DATA_BITS_8;
+			break;
+	}
+
+	/* manufacturer claims that this device can work with baud rates
+	 * up to 3 Mbps; I've tested it only on 115200 bps, so I can't
+	 * guarantee that any other baud rate will work (especially
+	 * the higher ones)
+	 */
+	br = tty_get_baud_rate(port->tty);
+	if (br == 0) {
+		divisor = 0;
+	} else if (br <= OTI6858_MAX_BAUD_RATE) {
+		int real_br;
+
+		divisor = (96000000 + 8 * br) / (16 * br);
+		real_br = 96000000 / (16 * divisor);
+		if ((((real_br - br) * 100 + br - 1) / br) > 2) {
+			dbg("%s(): baud rate %d is invalid", __FUNCTION__, br);
+			return;
+		}
+		divisor = cpu_to_le16(divisor);
+	} else {
+		dbg("%s(): baud rate %d is too high", __FUNCTION__, br);
+		return;
+	}
+
+	frame_fmt &= ~FMT_STOP_BITS_MASK;
+	if ((cflag & CSTOPB) != 0) {
+		frame_fmt |= FMT_STOP_BITS_2;
+	} else {
+		frame_fmt |= FMT_STOP_BITS_1;
+	}
+
+	frame_fmt &= ~FMT_PARITY_MASK;
+	if ((cflag & PARENB) != 0) {
+		if ((cflag & PARODD) != 0) {
+			frame_fmt |= FMT_PARITY_ODD;
+		} else {
+			frame_fmt |= FMT_PARITY_EVEN;
+		}
+	} else {
+		frame_fmt |= FMT_PARITY_NONE;
+	}
+
+	control &= ~CONTROL_MASK;
+	if ((cflag & CRTSCTS) != 0)
+		control |= (CONTROL_DTR_HIGH | CONTROL_RTS_HIGH);
+
+	/* change control lines if we are switching to or from B0 */
+	/* FIXME:
+	spin_lock_irqsave(&priv->lock, flags);
+	control = priv->line_control;
+	if ((cflag & CBAUD) == B0)
+		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+	else
+		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+	if (control != priv->line_control) {
+		control = priv->line_control;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		set_control_lines(serial->dev, control);
+	} else {
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+	*/
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (divisor != priv->pending_setup.divisor
+			|| control != priv->pending_setup.control
+			|| frame_fmt != priv->pending_setup.frame_fmt) {
+		priv->pending_setup.divisor = divisor;
+		priv->pending_setup.control = control;
+		priv->pending_setup.frame_fmt = frame_fmt;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	struct ktermios tmp_termios;
+	struct usb_serial *serial = port->serial;
+	struct oti6858_control_pkt *buf;
+	unsigned long flags;
+	int result;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	usb_clear_halt(serial->dev, port->write_urb->pipe);
+	usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+	if (port->open_count != 1)
+		return 0;
+
+	if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+		dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+				OTI6858_REQ_T_GET_STATUS,
+				OTI6858_REQ_GET_STATUS,
+				0, 0,
+				buf, OTI6858_CTRL_PKT_SIZE,
+				100);
+	if (result != OTI6858_CTRL_PKT_SIZE) {
+		/* assume default (after power-on reset) values */
+		buf->divisor = cpu_to_le16(0x009c);	/* 38400 bps */
+		buf->frame_fmt = 0x03;	/* 8N1 */
+		buf->something = 0x43;
+		buf->control = 0x4c;	/* DTR, RTS */
+		buf->tx_status = 0x00;
+		buf->pin_state = 0x5b;	/* RTS, CTS, DSR, DTR, RI, DCD */
+		buf->rx_bytes_avail = 0x00;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	memcpy(&priv->status, buf, OTI6858_CTRL_PKT_SIZE);
+	priv->pending_setup.divisor = buf->divisor;
+	priv->pending_setup.frame_fmt = buf->frame_fmt;
+	priv->pending_setup.control = buf->control;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	kfree(buf);
+
+	dbg("%s(): submitting interrupt urb", __FUNCTION__);
+	port->interrupt_in_urb->dev = serial->dev;
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	if (result != 0) {
+		dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+			       " with error %d\n", __FUNCTION__, result);
+		oti6858_close(port, NULL);
+		return -EPROTO;
+	}
+
+	/* setup termios */
+	if (port->tty)
+		oti6858_set_termios(port, &tmp_termios);
+
+	return 0;
+}
+
+static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	long timeout;
+	wait_queue_t wait;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	/* wait for data to drain from the buffer */
+	spin_lock_irqsave(&priv->lock, flags);
+	timeout = 30 * HZ;	/* PL2303_CLOSING_WAIT */
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&port->tty->write_wait, &wait);
+	dbg("%s(): entering wait loop", __FUNCTION__);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (pl2303_buf_data_avail(priv->buf) == 0
+		|| timeout == 0 || signal_pending(current)
+		|| !usb_get_intfdata(port->serial->interface))	/* disconnect */
+			break;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		timeout = schedule_timeout(timeout);
+		spin_lock_irqsave(&priv->lock, flags);
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->tty->write_wait, &wait);
+	dbg("%s(): after wait loop", __FUNCTION__);
+
+	/* clear out any remaining data in the buffer */
+	pl2303_buf_clear(priv->buf);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* wait for characters to drain from the device */
+	/* (this is long enough for the entire 256 byte */
+	/* pl2303 hardware buffer to drain with no flow */
+	/* control for data rates of 1200 bps or more, */
+	/* for lower rates we should really know how much */
+	/* data is in the buffer to compute a delay */
+	/* that is not unnecessarily long) */
+	/* FIXME
+	bps = tty_get_baud_rate(port->tty);
+	if (bps > 1200)
+		timeout = max((HZ*2560)/bps,HZ/10);
+	else
+	*/
+		timeout = 2*HZ;
+	schedule_timeout_interruptible(timeout);
+	dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__);
+
+	/* cancel scheduled setup */
+	cancel_delayed_work(&priv->delayed_setup_work);
+	cancel_delayed_work(&priv->delayed_write_work);
+	flush_scheduled_work();
+
+	/* shutdown our urbs */
+	dbg("%s(): shutting down urbs", __FUNCTION__);
+	usb_kill_urb(port->write_urb);
+	usb_kill_urb(port->read_urb);
+	usb_kill_urb(port->interrupt_in_urb);
+
+	/*
+	if (port->tty && (port->tty->termios->c_cflag) & HUPCL) {
+		// drop DTR and RTS
+		spin_lock_irqsave(&priv->lock, flags);
+		priv->pending_setup.control &= ~CONTROL_MASK;
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+	*/
+}
+
+static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+				unsigned int set, unsigned int clear)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	u8 control;
+
+	dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
+				__FUNCTION__, port->number, set, clear);
+
+	if (!usb_get_intfdata(port->serial->interface))
+		return -ENODEV;
+
+	/* FIXME: check if this is correct (active high/low) */
+	spin_lock_irqsave(&priv->lock, flags);
+	control = priv->pending_setup.control;
+	if ((set & TIOCM_RTS) != 0)
+		control |= CONTROL_RTS_HIGH;
+	if ((set & TIOCM_DTR) != 0)
+		control |= CONTROL_DTR_HIGH;
+	if ((clear & TIOCM_RTS) != 0)
+		control &= ~CONTROL_RTS_HIGH;
+	if ((clear & TIOCM_DTR) != 0)
+		control &= ~CONTROL_DTR_HIGH;
+
+	if (control != priv->pending_setup.control) {
+		priv->pending_setup.control = control;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned pin_state;
+	unsigned result = 0;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	if (!usb_get_intfdata(port->serial->interface))
+		return -ENODEV;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	pin_state = priv->status.pin_state & PIN_MASK;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* FIXME: check if this is correct (active high/low) */
+	if ((pin_state & PIN_RTS) != 0)
+		result |= TIOCM_RTS;
+	if ((pin_state & PIN_CTS) != 0)
+		result |= TIOCM_CTS;
+	if ((pin_state & PIN_DSR) != 0)
+		result |= TIOCM_DSR;
+	if ((pin_state & PIN_DTR) != 0)
+		result |= TIOCM_DTR;
+	if ((pin_state & PIN_RI) != 0)
+		result |= TIOCM_RI;
+	if ((pin_state & PIN_DCD) != 0)
+		result |= TIOCM_CD;
+
+	dbg("%s() = 0x%08x", __FUNCTION__, result);
+
+	return result;
+}
+
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int prev, status;
+	unsigned int changed;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	prev = priv->status.pin_state;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	while (1) {
+		wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		status = priv->status.pin_state & PIN_MASK;
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		changed = prev ^ status;
+		/* FIXME: check if this is correct (active high/low) */
+		if (	((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
+			((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
+			((arg & TIOCM_CD)  && (changed & PIN_DCD)) ||
+			((arg & TIOCM_CTS) && (changed & PIN_CTS))) {
+				return 0;
+		}
+		prev = status;
+	}
+
+	/* NOTREACHED */
+	return 0;
+}
+
+static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	void __user *user_arg = (void __user *) arg;
+	unsigned int x;
+
+	dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
+				__FUNCTION__, port->number, cmd, arg);
+
+	switch (cmd) {
+		case TCGETS:
+			if (copy_to_user(user_arg, port->tty->termios,
+						sizeof(struct ktermios))) {
+				return -EFAULT;
+			}
+			return 0;
+
+		case TCSETS:
+		case TCSETSW:	/* FIXME: this is not the same! */
+		case TCSETSF:	/* FIXME: this is not the same! */
+			if (copy_from_user(port->tty->termios, user_arg,
+						sizeof(struct ktermios))) {
+				return -EFAULT;
+			}
+			oti6858_set_termios(port, NULL);
+			return 0;
+
+		case TCFLSH:
+			/* FIXME */
+			return 0;
+
+		case TIOCMBIS:
+			if (copy_from_user(&x, user_arg, sizeof(x)))
+				return -EFAULT;
+			return oti6858_tiocmset(port, NULL, x, 0);
+
+		case TIOCMBIC:
+			if (copy_from_user(&x, user_arg, sizeof(x)))
+				return -EFAULT;
+			return oti6858_tiocmset(port, NULL, 0, x);
+
+		case TIOCGSERIAL:
+			if (copy_to_user(user_arg, port->tty->termios,
+						sizeof(struct ktermios))) {
+				return -EFAULT;
+			}
+                        return 0;
+
+		case TIOCSSERIAL:
+			if (copy_from_user(port->tty->termios, user_arg,
+						sizeof(struct ktermios))) {
+				return -EFAULT;
+			}
+			oti6858_set_termios(port, NULL);
+			return 0;
+
+		case TIOCMIWAIT:
+			dbg("%s(): TIOCMIWAIT", __FUNCTION__);
+			return wait_modem_info(port, arg);
+
+		default:
+			dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd);
+			break;
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
+{
+	int state;
+
+	dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+	state = (break_state == 0) ? 0 : 1;
+	dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");
+
+	/* FIXME */
+/*
+	result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
+				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+				  0, NULL, 0, 100);
+	if (result != 0)
+		dbg("%s(): error sending break", __FUNCTION__);
+ */
+}
+
+static void oti6858_shutdown(struct usb_serial *serial)
+{
+	struct oti6858_private *priv;
+	int i;
+
+	dbg("%s()", __FUNCTION__);
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		priv = usb_get_serial_port_data(serial->port[i]);
+		if (priv) {
+			pl2303_buf_free(priv->buf);
+			kfree(priv);
+			usb_set_serial_port_data(serial->port[i], NULL);
+		}
+	}
+}
+
+static void oti6858_read_int_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	int transient = 0, can_recv = 0, resubmit = 1;
+	int status = urb->status;
+
+	dbg("%s(port = %d, status = %d)",
+				__FUNCTION__, port->number, status);
+
+	switch (status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s(): urb shutting down with status: %d",
+					__FUNCTION__, status);
+		return;
+	default:
+		dbg("%s(): nonzero urb status received: %d",
+					__FUNCTION__, status);
+		break;
+	}
+
+	if (status == 0 && urb->actual_length == OTI6858_CTRL_PKT_SIZE) {
+		struct oti6858_control_pkt *xs = urb->transfer_buffer;
+		unsigned long flags;
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		if (!priv->transient) {
+			if (!OTI6858_CTRL_EQUALS_PENDING(xs, priv)) {
+				if (xs->rx_bytes_avail == 0) {
+					priv->transient = 4;
+					priv->setup_done = 0;
+					resubmit = 0;
+					dbg("%s(): scheduling setup_line()",
+					    __FUNCTION__);
+					schedule_delayed_work(&priv->delayed_setup_work, 0);
+				}
+			}
+		} else {
+			if (OTI6858_CTRL_EQUALS_PENDING(xs, priv)) {
+				priv->transient = 0;
+			} else if (!priv->setup_done) {
+				resubmit = 0;
+			} else if (--priv->transient == 0) {
+				if (xs->rx_bytes_avail == 0) {
+					priv->transient = 4;
+					priv->setup_done = 0;
+					resubmit = 0;
+					dbg("%s(): scheduling setup_line()",
+					    __FUNCTION__);
+					schedule_delayed_work(&priv->delayed_setup_work, 0);
+				}
+			}
+		}
+
+		if (!priv->transient) {
+			if (xs->pin_state != priv->status.pin_state)
+				wake_up_interruptible(&priv->intr_wait);
+			memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
+		}
+
+		if (!priv->transient && xs->rx_bytes_avail != 0) {
+			can_recv = xs->rx_bytes_avail;
+			priv->flags.read_urb_in_use = 1;
+		}
+
+		transient = priv->transient;
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+
+	if (can_recv) {
+		int result;
+
+		port->read_urb->dev = port->serial->dev;
+		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (result != 0) {
+			priv->flags.read_urb_in_use = 0;
+			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+					" error %d\n", __FUNCTION__, result);
+		} else {
+			resubmit = 0;
+		}
+	} else if (!transient) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		if (priv->flags.write_urb_in_use == 0
+				&& pl2303_buf_data_avail(priv->buf) != 0) {
+			schedule_delayed_work(&priv->delayed_write_work,0);
+			resubmit = 0;
+		}
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+
+	if (resubmit) {
+		int result;
+
+//		dbg("%s(): submitting interrupt urb", __FUNCTION__);
+		urb->dev = port->serial->dev;
+		result = usb_submit_urb(urb, GFP_ATOMIC);
+		if (result != 0) {
+			dev_err(&urb->dev->dev,
+					"%s(): usb_submit_urb() failed with"
+					" error %d\n", __FUNCTION__, result);
+		}
+	}
+}
+
+static void oti6858_read_bulk_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
+	unsigned char *data = urb->transfer_buffer;
+	unsigned long flags;
+	int i, result;
+	int status = urb->status;
+	char tty_flag;
+
+	dbg("%s(port = %d, status = %d)",
+				__FUNCTION__, port->number, status);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->flags.read_urb_in_use = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (status != 0) {
+		if (!port->open_count) {
+			dbg("%s(): port is closed, exiting", __FUNCTION__);
+			return;
+		}
+		/*
+		if (status == -EPROTO) {
+			// PL2303 mysteriously fails with -EPROTO reschedule the read
+			dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
+			result = usb_submit_urb(urb, GFP_ATOMIC);
+			if (result)
+				dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+			return;
+		}
+		*/
+		dbg("%s(): unable to handle the error, exiting", __FUNCTION__);
+		return;
+	}
+
+	// get tty_flag from status
+	tty_flag = TTY_NORMAL;
+
+/* FIXME: probably, errors will be signalled using interrupt pipe! */
+/*
+	// break takes precedence over parity,
+	// which takes precedence over framing errors
+	if (status & UART_BREAK_ERROR )
+		tty_flag = TTY_BREAK;
+	else if (status & UART_PARITY_ERROR)
+		tty_flag = TTY_PARITY;
+	else if (status & UART_FRAME_ERROR)
+		tty_flag = TTY_FRAME;
+	dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
+*/
+
+	tty = port->tty;
+	if (tty != NULL && urb->actual_length > 0) {
+		tty_buffer_request_room(tty, urb->actual_length);
+		for (i = 0; i < urb->actual_length; ++i)
+			tty_insert_flip_char(tty, data[i], tty_flag);
+		tty_flip_buffer_push(tty);
+	}
+
+	// schedule the interrupt urb if we are still open */
+	if (port->open_count != 0) {
+		port->interrupt_in_urb->dev = port->serial->dev;
+		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+		if (result != 0) {
+			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+					" error %d\n", __FUNCTION__, result);
+		}
+	}
+}
+
+static void oti6858_write_bulk_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+	struct oti6858_private *priv = usb_get_serial_port_data(port);
+	int status = urb->status;
+	int result;
+
+	dbg("%s(port = %d, status = %d)",
+				__FUNCTION__, port->number, status);
+
+	switch (status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s(): urb shutting down with status: %d",
+					__FUNCTION__, status);
+		priv->flags.write_urb_in_use = 0;
+		return;
+	default:
+		/* error in the urb, so we have to resubmit it */
+		dbg("%s(): nonzero write bulk status received: %d",
+					__FUNCTION__, status);
+		dbg("%s(): overflow in write", __FUNCTION__);
+
+		port->write_urb->transfer_buffer_length = 1;
+		port->write_urb->dev = port->serial->dev;
+		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (result) {
+			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+					" error %d\n", __FUNCTION__, result);
+		} else {
+			return;
+		}
+	}
+
+	priv->flags.write_urb_in_use = 0;
+
+	// schedule the interrupt urb if we are still open */
+	port->interrupt_in_urb->dev = port->serial->dev;
+	dbg("%s(): submitting interrupt urb", __FUNCTION__);
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+	if (result != 0) {
+		dev_err(&port->dev, "%s(): failed submitting int urb,"
+					" error %d\n", __FUNCTION__, result);
+	}
+}
+
+
+/*
+ * pl2303_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+{
+	struct pl2303_buf *pb;
+
+	if (size == 0)
+		return NULL;
+
+	pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+	if (pb == NULL)
+		return NULL;
+
+	pb->buf_buf = kmalloc(size, GFP_KERNEL);
+	if (pb->buf_buf == NULL) {
+		kfree(pb);
+		return NULL;
+	}
+
+	pb->buf_size = size;
+	pb->buf_get = pb->buf_put = pb->buf_buf;
+
+	return pb;
+}
+
+/*
+ * pl2303_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void pl2303_buf_free(struct pl2303_buf *pb)
+{
+	if (pb) {
+		kfree(pb->buf_buf);
+		kfree(pb);
+	}
+}
+
+/*
+ * pl2303_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void pl2303_buf_clear(struct pl2303_buf *pb)
+{
+	if (pb != NULL) {
+		/* equivalent to a get of all data available */
+		pb->buf_get = pb->buf_put;
+	}
+}
+
+/*
+ * pl2303_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
+{
+	if (pb == NULL)
+		return 0;
+	return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
+{
+	if (pb == NULL)
+		return 0;
+	return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+					unsigned int count)
+{
+	unsigned int len;
+
+	if (pb == NULL)
+		return 0;
+
+	len  = pl2303_buf_space_avail(pb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = pb->buf_buf + pb->buf_size - pb->buf_put;
+	if (count > len) {
+		memcpy(pb->buf_put, buf, len);
+		memcpy(pb->buf_buf, buf+len, count - len);
+		pb->buf_put = pb->buf_buf + count - len;
+	} else {
+		memcpy(pb->buf_put, buf, count);
+		if (count < len)
+			pb->buf_put += count;
+		else /* count == len */
+			pb->buf_put = pb->buf_buf;
+	}
+
+	return count;
+}
+
+/*
+ * pl2303_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+					unsigned int count)
+{
+	unsigned int len;
+
+	if (pb == NULL)
+		return 0;
+
+	len = pl2303_buf_data_avail(pb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = pb->buf_buf + pb->buf_size - pb->buf_get;
+	if (count > len) {
+		memcpy(buf, pb->buf_get, len);
+		memcpy(buf+len, pb->buf_buf, count - len);
+		pb->buf_get = pb->buf_buf + count - len;
+	} else {
+		memcpy(buf, pb->buf_get, count);
+		if (count < len)
+			pb->buf_get += count;
+		else /* count == len */
+			pb->buf_get = pb->buf_buf;
+	}
+
+	return count;
+}
+
+/* module description and (de)initialization */
+
+static int __init oti6858_init(void)
+{
+	int retval;
+
+	if ((retval = usb_serial_register(&oti6858_device)) == 0) {
+		if ((retval = usb_register(&oti6858_driver)) != 0)
+			usb_serial_deregister(&oti6858_device);
+		else
+			return 0;
+	}
+
+	return retval;
+}
+
+static void __exit oti6858_exit(void)
+{
+	usb_deregister(&oti6858_driver);
+	usb_serial_deregister(&oti6858_device);
+}
+
+module_init(oti6858_init);
+module_exit(oti6858_exit);
+
+MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
+MODULE_AUTHOR(OTI6858_AUTHOR);
+MODULE_VERSION(OTI6858_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "enable debug output");
+
diff --git a/drivers/usb/serial/oti6858.h b/drivers/usb/serial/oti6858.h
new file mode 100644
index 0000000..704ac3a
--- /dev/null
+++ b/drivers/usb/serial/oti6858.h
@@ -0,0 +1,15 @@
+/*
+ * Ours Technology Inc. OTi-6858 USB to serial adapter driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __LINUX_USB_SERIAL_OTI6858_H
+#define __LINUX_USB_SERIAL_OTI6858_H
+
+#define OTI6858_VENDOR_ID	0x0ea0
+#define OTI6858_PRODUCT_ID	0x6858
+
+#endif
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 83dfae9..f9f85f5 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -1,14 +1,14 @@
 /*
  * Prolific PL2303 USB to serial adaptor driver
  *
- * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2003 IBM Corp.
  *
  * Original driver for 2.2.x by anonymous
  *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License.
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
@@ -484,15 +484,6 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	cflag = port->tty->termios->c_cflag;
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
-		     RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg("%s - nothing to change...", __FUNCTION__);
-			return;
-		}
-	}
 
 	buf = kzalloc(7, GFP_KERNEL);
 	if (!buf) {
@@ -517,29 +508,7 @@
 		dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
 	}
 
-	baud = 0;
-	switch (cflag & CBAUD) {
-		case B0:	baud = 0;	break;
-		case B75:	baud = 75;	break;
-		case B150:	baud = 150;	break;
-		case B300:	baud = 300;	break;
-		case B600:	baud = 600;	break;
-		case B1200:	baud = 1200;	break;
-		case B1800:	baud = 1800;	break;
-		case B2400:	baud = 2400;	break;
-		case B4800:	baud = 4800;	break;
-		case B9600:	baud = 9600;	break;
-		case B19200:	baud = 19200;	break;
-		case B38400:	baud = 38400;	break;
-		case B57600:	baud = 57600;	break;
-		case B115200:	baud = 115200;	break;
-		case B230400:	baud = 230400;	break;
-		case B460800:	baud = 460800;	break;
-		default:
-			dev_err(&port->dev, "pl2303 driver does not support"
-				" the baudrate requested (fix it)\n");
-			break;
-	}
+	baud = tty_get_baud_rate(port->tty);;
 	dbg("%s - baud = %d", __FUNCTION__, baud);
 	if (baud) {
 		buf[0] = baud & 0xff;
@@ -617,6 +586,13 @@
 				    VENDOR_WRITE_REQUEST_TYPE,
 				    0x0, index, NULL, 0, 100);
 		dbg("0x40:0x1:0x0:0x%x  %d", index, i);
+	} else {
+		i = usb_control_msg(serial->dev,
+				    usb_sndctrlpipe(serial->dev, 0),
+				    VENDOR_WRITE_REQUEST,
+				    VENDOR_WRITE_REQUEST_TYPE,
+				    0x0, 0x0, NULL, 0, 100);
+		dbg ("0x40:0x1:0x0:0x0  %d", i);
 	}
 
 	kfree(buf);
@@ -954,11 +930,12 @@
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	unsigned char *data = urb->transfer_buffer;
 	unsigned int actual_length = urb->actual_length;
-	int status;
+	int status = urb->status;
+	int retval;
 
 	dbg("%s (%d)", __FUNCTION__, port->number);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -967,11 +944,11 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		goto exit;
 	}
 
@@ -981,11 +958,11 @@
 	pl2303_update_line_status(port, data, actual_length);
 
 exit:
-	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status)
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
 		dev_err(&urb->dev->dev,
 			"%s - usb_submit_urb failed with result %d\n",
-			__FUNCTION__, status);
+			__FUNCTION__, retval);
 }
 
 static void pl2303_read_bulk_callback(struct urb *urb)
@@ -997,23 +974,23 @@
 	unsigned long flags;
 	int i;
 	int result;
-	u8 status;
+	int status = urb->status;
+	u8 line_status;
 	char tty_flag;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - urb status = %d", __FUNCTION__, status);
 		if (!port->open_count) {
 			dbg("%s - port is closed, exiting.", __FUNCTION__);
 			return;
 		}
-		if (urb->status == -EPROTO) {
+		if (status == -EPROTO) {
 			/* PL2303 mysteriously fails with -EPROTO reschedule
 			 * the read */
 			dbg("%s - caught -EPROTO, resubmitting the urb",
 			    __FUNCTION__);
-			urb->status = 0;
 			urb->dev = port->serial->dev;
 			result = usb_submit_urb(urb, GFP_ATOMIC);
 			if (result)
@@ -1033,18 +1010,18 @@
 	tty_flag = TTY_NORMAL;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	status = priv->line_status;
+	line_status = priv->line_status;
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
 	wake_up_interruptible(&priv->delta_msr_wait);
 
 	/* break takes precedence over parity, */
 	/* which takes precedence over framing errors */
-	if (status & UART_BREAK_ERROR )
+	if (line_status & UART_BREAK_ERROR )
 		tty_flag = TTY_BREAK;
-	else if (status & UART_PARITY_ERROR)
+	else if (line_status & UART_PARITY_ERROR)
 		tty_flag = TTY_PARITY;
-	else if (status & UART_FRAME_ERROR)
+	else if (line_status & UART_FRAME_ERROR)
 		tty_flag = TTY_FRAME;
 	dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
 
@@ -1052,7 +1029,7 @@
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length + 1);
 		/* overrun is special, not associated with a char */
-		if (status & UART_OVERRUN_ERROR)
+		if (line_status & UART_OVERRUN_ERROR)
 			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 		for (i = 0; i < urb->actual_length; ++i)
 			tty_insert_flip_char(tty, data[i], tty_flag);
@@ -1076,10 +1053,11 @@
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	int result;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -1088,14 +1066,14 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		priv->write_urb_in_use = 0;
 		return;
 	default:
 		/* error in the urb, so we have to resubmit it */
 		dbg("%s - Overflow in write", __FUNCTION__);
 		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
-		    urb->status);
+		    status);
 		port->write_urb->transfer_buffer_length = 1;
 		port->write_urb->dev = port->serial->dev;
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 5a03a3f..86899d5 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -211,11 +211,13 @@
 	unsigned char length = urb->actual_length;
 	int i;
 	int result;
+	int status = urb->status;
 
 	dbg ("%s", __FUNCTION__);
 
-	if (urb->status) {
-		dbg ("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 644607d..e7db203 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -35,6 +35,7 @@
 	{ USB_DEVICE(0x1199, 0x0218) },	/* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
 	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
+	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless AirCard 595U */
 	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
 	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
 	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
@@ -60,6 +61,7 @@
 	{ USB_DEVICE(0x1199, 0x0218) },	/* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
 	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
+	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless AirCard 595U */
 	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
 	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
 	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
@@ -84,15 +86,14 @@
 #define N_IN_URB	4
 #define N_OUT_URB	4
 #define IN_BUFLEN	4096
-#define OUT_BUFLEN	128
 
 struct sierra_port_private {
+	spinlock_t lock;	/* lock the structure */
+	int outstanding_urbs;	/* number of out urbs in flight */
+
 	/* Input endpoints and buffer for this port */
 	struct urb *in_urbs[N_IN_URB];
 	char in_buffer[N_IN_URB][IN_BUFLEN];
-	/* Output endpoints and buffer for this port */
-	struct urb *out_urbs[N_OUT_URB];
-	char out_buffer[N_OUT_URB][OUT_BUFLEN];
 
 	/* Settings for the port */
 	int rts_state;	/* Handshaking pins (outputs) */
@@ -101,8 +102,6 @@
 	int dsr_state;
 	int dcd_state;
 	int ri_state;
-
-	unsigned long tx_start_time[N_OUT_URB];
 };
 
 static int sierra_send_setup(struct usb_serial_port *port)
@@ -195,61 +194,98 @@
 	return -ENOIOCTLCMD;
 }
 
+static void sierra_outdat_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+	int status = urb->status;
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* free up the transfer buffer, as usb_free_urb() does not do this */
+	kfree(urb->transfer_buffer);
+
+	if (status)
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
+
+	spin_lock_irqsave(&portdata->lock, flags);
+	--portdata->outstanding_urbs;
+	spin_unlock_irqrestore(&portdata->lock, flags);
+
+	usb_serial_port_softint(port);
+}
+
 /* Write */
 static int sierra_write(struct usb_serial_port *port,
 			const unsigned char *buf, int count)
 {
-	struct sierra_port_private *portdata;
-	int i;
-	int left, todo;
-	struct urb *this_urb = NULL; /* spurious */
-	int err;
+	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+	struct usb_serial *serial = port->serial;
+	unsigned long flags;
+	unsigned char *buffer;
+	struct urb *urb;
+	int status;
 
 	portdata = usb_get_serial_port_data(port);
 
 	dbg("%s: write (%d chars)", __FUNCTION__, count);
 
-	i = 0;
-	left = count;
-	for (i=0; left > 0 && i < N_OUT_URB; i++) {
-		todo = left;
-		if (todo > OUT_BUFLEN)
-			todo = OUT_BUFLEN;
+	spin_lock_irqsave(&portdata->lock, flags);
+	if (portdata->outstanding_urbs > N_OUT_URB) {
+		spin_unlock_irqrestore(&portdata->lock, flags);
+		dbg("%s - write limit hit\n", __FUNCTION__);
+		return 0;
+	}
+	portdata->outstanding_urbs++;
+	spin_unlock_irqrestore(&portdata->lock, flags);
 
-		this_urb = portdata->out_urbs[i];
-		if (this_urb->status == -EINPROGRESS) {
-			if (time_before(jiffies,
-					portdata->tx_start_time[i] + 10 * HZ))
-				continue;
-			usb_unlink_urb(this_urb);
-			continue;
-		}
-		if (this_urb->status != 0)
-			dbg("usb_write %p failed (err=%d)",
-				this_urb, this_urb->status);
-
-		dbg("%s: endpoint %d buf %d", __FUNCTION__,
-			usb_pipeendpoint(this_urb->pipe), i);
-
-		/* send the data */
-		memcpy (this_urb->transfer_buffer, buf, todo);
-		this_urb->transfer_buffer_length = todo;
-
-		this_urb->dev = port->serial->dev;
-		err = usb_submit_urb(this_urb, GFP_ATOMIC);
-		if (err) {
-			dbg("usb_submit_urb %p (write bulk) failed "
-				"(%d, has %d)", this_urb,
-				err, this_urb->status);
-			continue;
-		}
-		portdata->tx_start_time[i] = jiffies;
-		buf += todo;
-		left -= todo;
+	buffer = kmalloc(count, GFP_ATOMIC);
+	if (!buffer) {
+		dev_err(&port->dev, "out of memory\n");
+		count = -ENOMEM;
+		goto error_no_buffer;
 	}
 
-	count -= left;
-	dbg("%s: wrote (did %d)", __FUNCTION__, count);
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		dev_err(&port->dev, "no more free urbs\n");
+		count = -ENOMEM;
+		goto error_no_urb;
+	}
+
+	memcpy(buffer, buf, count);
+
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+
+	usb_fill_bulk_urb(urb, serial->dev,
+			  usb_sndbulkpipe(serial->dev,
+					  port->bulk_out_endpointAddress),
+			  buffer, count, sierra_outdat_callback, port);
+
+	/* send it down the pipe */
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status) {
+		dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+			"with status = %d\n", __FUNCTION__, status);
+		count = status;
+		goto error;
+	}
+
+	/* we are done with this urb, so let the host driver
+	 * really free it when it is finished with it */
+	usb_free_urb(urb);
+
+	return count;
+error:
+	usb_free_urb(urb);
+error_no_urb:
+	kfree(buffer);
+error_no_buffer:
+	spin_lock_irqsave(&portdata->lock, flags);
+	--portdata->outstanding_urbs;
+	spin_unlock_irqrestore(&portdata->lock, flags);
 	return count;
 }
 
@@ -260,15 +296,16 @@
 	struct usb_serial_port *port;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
+	int status = urb->status;
 
 	dbg("%s: %p", __FUNCTION__, urb);
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 	port = (struct usb_serial_port *) urb->context;
 
-	if (urb->status) {
+	if (status) {
 		dbg("%s: nonzero status: %d on endpoint %02x.",
-		    __FUNCTION__, urb->status, endpoint);
+		    __FUNCTION__, status, endpoint);
 	} else {
 		tty = port->tty;
 		if (urb->actual_length) {
@@ -280,30 +317,20 @@
 		}
 
 		/* Resubmit urb so we continue receiving */
-		if (port->open_count && urb->status != -ESHUTDOWN) {
+		if (port->open_count && status != -ESHUTDOWN) {
 			err = usb_submit_urb(urb, GFP_ATOMIC);
 			if (err)
-				printk(KERN_ERR "%s: resubmit read urb failed. "
-					"(%d)", __FUNCTION__, err);
+				dev_err(&port->dev, "resubmit read urb failed."
+					"(%d)", err);
 		}
 	}
 	return;
 }
 
-static void sierra_outdat_callback(struct urb *urb)
-{
-	struct usb_serial_port *port;
-
-	dbg("%s", __FUNCTION__);
-
-	port = (struct usb_serial_port *) urb->context;
-
-	usb_serial_port_softint(port);
-}
-
 static void sierra_instat_callback(struct urb *urb)
 {
 	int err;
+	int status = urb->status;
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
 	struct usb_serial *serial = port->serial;
@@ -311,7 +338,7 @@
 	dbg("%s", __FUNCTION__);
 	dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
 
-	if (urb->status == 0) {
+	if (status == 0) {
 		struct usb_ctrlrequest *req_pkt =
 				(struct usb_ctrlrequest *)urb->transfer_buffer;
 
@@ -342,10 +369,10 @@
 				req_pkt->bRequestType,req_pkt->bRequest);
 		}
 	} else
-		dbg("%s: error %d", __FUNCTION__, urb->status);
+		dbg("%s: error %d", __FUNCTION__, status);
 
 	/* Resubmit urb so we continue receiving IRQ data */
-	if (urb->status != -ESHUTDOWN) {
+	if (status != -ESHUTDOWN) {
 		urb->dev = serial->dev;
 		err = usb_submit_urb(urb, GFP_ATOMIC);
 		if (err)
@@ -356,46 +383,42 @@
 
 static int sierra_write_room(struct usb_serial_port *port)
 {
-	struct sierra_port_private *portdata;
-	int i;
-	int data_len = 0;
-	struct urb *this_urb;
+	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+	unsigned long flags;
 
-	portdata = usb_get_serial_port_data(port);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	for (i=0; i < N_OUT_URB; i++) {
-		this_urb = portdata->out_urbs[i];
-		if (this_urb && this_urb->status != -EINPROGRESS)
-			data_len += OUT_BUFLEN;
+	/* try to give a good number back based on if we have any free urbs at
+	 * this point in time */
+	spin_lock_irqsave(&portdata->lock, flags);
+	if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) {
+		spin_unlock_irqrestore(&portdata->lock, flags);
+		dbg("%s - write limit hit\n", __FUNCTION__);
+		return 0;
 	}
+	spin_unlock_irqrestore(&portdata->lock, flags);
 
-	dbg("%s: %d", __FUNCTION__, data_len);
-	return data_len;
+	return 2048;
 }
 
 static int sierra_chars_in_buffer(struct usb_serial_port *port)
 {
-	struct sierra_port_private *portdata;
-	int i;
-	int data_len = 0;
-	struct urb *this_urb;
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	portdata = usb_get_serial_port_data(port);
-
-	for (i=0; i < N_OUT_URB; i++) {
-		this_urb = portdata->out_urbs[i];
-		if (this_urb && this_urb->status == -EINPROGRESS)
-			data_len += this_urb->transfer_buffer_length;
-	}
-	dbg("%s: %d", __FUNCTION__, data_len);
-	return data_len;
+	/*
+	 * We can't really account for how much data we
+	 * have sent out, but hasn't made it through to the
+	 * device as we can't see the backend here, so just
+	 * tell the tty layer that everything is flushed.
+	 */
+	return 0;
 }
 
 static int sierra_open(struct usb_serial_port *port, struct file *filp)
 {
 	struct sierra_port_private *portdata;
 	struct usb_serial *serial = port->serial;
-	int i, err;
+	int i;
 	struct urb *urb;
 	int result;
 	__u16 set_mode_dzero = 0x0000;
@@ -411,7 +434,7 @@
 	/* Reset low level data toggle and start reading from endpoints */
 	for (i = 0; i < N_IN_URB; i++) {
 		urb = portdata->in_urbs[i];
-		if (! urb)
+		if (!urb)
 			continue;
 		if (urb->dev != serial->dev) {
 			dbg("%s: dev %p != %p", __FUNCTION__,
@@ -425,24 +448,13 @@
 		 */
 		usb_clear_halt(urb->dev, urb->pipe);
 
-		err = usb_submit_urb(urb, GFP_KERNEL);
-		if (err) {
-			dbg("%s: submit urb %d failed (%d) %d",
-				__FUNCTION__, i, err,
-				urb->transfer_buffer_length);
+		result = usb_submit_urb(urb, GFP_KERNEL);
+		if (result) {
+			dev_err(&port->dev, "submit urb %d failed (%d) %d",
+				i, result, urb->transfer_buffer_length);
 		}
 	}
 
-	/* Reset low level data toggle on out endpoints */
-	for (i = 0; i < N_OUT_URB; i++) {
-		urb = portdata->out_urbs[i];
-		if (! urb)
-			continue;
-		urb->dev = serial->dev;
-		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-				usb_pipeout(urb->pipe), 0); */
-	}
-
 	port->tty->low_latency = 1;
 
 	/* set mode to D0 */
@@ -453,7 +465,14 @@
 
 	sierra_send_setup(port);
 
-	return (0);
+	/* start up the interrupt endpoint if we have one */
+	if (port->interrupt_in_urb) {
+		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+		if (result)
+			dev_err(&port->dev, "submit irq_in urb failed %d",
+				result);
+	}
+	return 0;
 }
 
 static void sierra_close(struct usb_serial_port *port, struct file *filp)
@@ -473,71 +492,21 @@
 
 		/* Stop reading/writing urbs */
 		for (i = 0; i < N_IN_URB; i++)
-			usb_unlink_urb(portdata->in_urbs[i]);
-		for (i = 0; i < N_OUT_URB; i++)
-			usb_unlink_urb(portdata->out_urbs[i]);
+			usb_kill_urb(portdata->in_urbs[i]);
 	}
+
+	usb_kill_urb(port->interrupt_in_urb);
+
 	port->tty = NULL;
 }
 
-/* Helper functions used by sierra_setup_urbs */
-static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
-				    int dir, void *ctx, char *buf, int len,
-				    usb_complete_t callback)
-{
-	struct urb *urb;
-
-	if (endpoint == -1)
-		return NULL;		/* endpoint not needed */
-
-	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */
-	if (urb == NULL) {
-		dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
-		return NULL;
-	}
-
-		/* Fill URB using supplied data. */
-	usb_fill_bulk_urb(urb, serial->dev,
-		      usb_sndbulkpipe(serial->dev, endpoint) | dir,
-		      buf, len, callback, ctx);
-
-	return urb;
-}
-
-/* Setup urbs */
-static void sierra_setup_urbs(struct usb_serial *serial)
-{
-	int i,j;
-	struct usb_serial_port *port;
-	struct sierra_port_private *portdata;
-
-	dbg("%s", __FUNCTION__);
-
-	for (i = 0; i < serial->num_ports; i++) {
-		port = serial->port[i];
-		portdata = usb_get_serial_port_data(port);
-
-	/* Do indat endpoints first */
-		for (j = 0; j < N_IN_URB; ++j) {
-			portdata->in_urbs[j] = sierra_setup_urb (serial,
-                  	port->bulk_in_endpointAddress, USB_DIR_IN, port,
-                  	portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback);
-		}
-
-		/* outdat endpoints */
-		for (j = 0; j < N_OUT_URB; ++j) {
-			portdata->out_urbs[j] = sierra_setup_urb (serial,
-                  	port->bulk_out_endpointAddress, USB_DIR_OUT, port,
-                  	portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback);
-		}
-	}
-}
-
 static int sierra_startup(struct usb_serial *serial)
 {
-	int i, err;
 	struct usb_serial_port *port;
 	struct sierra_port_private *portdata;
+	struct urb *urb;
+	int i;
+	int j;
 
 	dbg("%s", __FUNCTION__);
 
@@ -548,22 +517,31 @@
 		if (!portdata) {
 			dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
 					__FUNCTION__, i);
-			return (1);
+			return -ENOMEM;
 		}
+		spin_lock_init(&portdata->lock);
 
 		usb_set_serial_port_data(port, portdata);
 
-		if (! port->interrupt_in_urb)
-			continue;
-		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-		if (err)
-			dbg("%s: submit irq_in urb failed %d",
-				__FUNCTION__, err);
+		/* initialize the in urbs */
+		for (j = 0; j < N_IN_URB; ++j) {
+			urb = usb_alloc_urb(0, GFP_KERNEL);
+			if (urb == NULL) {
+				dbg("%s: alloc for in port failed.",
+				    __FUNCTION__);
+				continue;
+			}
+			/* Fill URB using supplied data. */
+			usb_fill_bulk_urb(urb, serial->dev,
+					  usb_rcvbulkpipe(serial->dev,
+						port->bulk_in_endpointAddress),
+					  portdata->in_buffer[j], IN_BUFLEN,
+					  sierra_indat_callback, port);
+			portdata->in_urbs[j] = urb;
+		}
 	}
 
-	sierra_setup_urbs(serial);
-
-	return (0);
+	return 0;
 }
 
 static void sierra_shutdown(struct usb_serial *serial)
@@ -574,22 +552,6 @@
 
 	dbg("%s", __FUNCTION__);
 
-	/* Stop reading/writing urbs */
-	for (i = 0; i < serial->num_ports; ++i) {
-		port = serial->port[i];
-		if (!port)
-			continue;
-		portdata = usb_get_serial_port_data(port);
-		if (!portdata)
-			continue;
-
-		for (j = 0; j < N_IN_URB; j++)
-			usb_unlink_urb(portdata->in_urbs[j]);
-		for (j = 0; j < N_OUT_URB; j++)
-			usb_unlink_urb(portdata->out_urbs[j]);
-	}
-
-	/* Now free them */
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		if (!port)
@@ -599,25 +561,12 @@
 			continue;
 
 		for (j = 0; j < N_IN_URB; j++) {
-			if (portdata->in_urbs[j]) {
-				usb_free_urb(portdata->in_urbs[j]);
-				portdata->in_urbs[j] = NULL;
-			}
+			usb_kill_urb(portdata->in_urbs[j]);
+			usb_free_urb(portdata->in_urbs[j]);
+			portdata->in_urbs[j] = NULL;
 		}
-		for (j = 0; j < N_OUT_URB; j++) {
-			if (portdata->out_urbs[j]) {
-				usb_free_urb(portdata->out_urbs[j]);
-				portdata->out_urbs[j] = NULL;
-			}
-		}
-	}
-
-	/* Now free per port private data */
-	for (i = 0; i < serial->num_ports; i++) {
-		port = serial->port[i];
-		if (!port)
-			continue;
-		kfree(usb_get_serial_port_data(port));
+		kfree(portdata);
+		usb_set_serial_port_data(port, NULL);
 	}
 }
 
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 4203e2b..f98626a 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1112,22 +1112,24 @@
 	int length = urb->actual_length;
 	int port_number;
 	int function;
-	int status;
+	int status = urb->status;
+	int retval;
 	__u8 msr;
 
 	dbg("%s", __FUNCTION__);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		break;
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
-		dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down, %d", __FUNCTION__, status);
 		tdev->td_urb_error = 1;
 		return;
 	default:
-		dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status);
+		dev_err(dev, "%s - nonzero urb status, %d\n",
+			__FUNCTION__, status);
 		tdev->td_urb_error = 1;
 		goto exit;
 	}
@@ -1175,9 +1177,10 @@
 	}
 
 exit:
-	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status)
-		dev_err(dev, "%s - resubmit interrupt urb failed, %d\n", __FUNCTION__, status);
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		dev_err(dev, "%s - resubmit interrupt urb failed, %d\n",
+			__FUNCTION__, retval);
 }
 
 
@@ -1186,30 +1189,32 @@
 	struct ti_port *tport = (struct ti_port *)urb->context;
 	struct usb_serial_port *port = tport->tp_port;
 	struct device *dev = &urb->dev->dev;
-	int status = 0;
+	int status = urb->status;
+	int retval = 0;
 
 	dbg("%s", __FUNCTION__);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		break;
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
-		dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down, %d", __FUNCTION__, status);
 		tport->tp_tdev->td_urb_error = 1;
 		wake_up_interruptible(&tport->tp_write_wait);
 		return;
 	default:
-		dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status );
+		dev_err(dev, "%s - nonzero urb status, %d\n",
+			__FUNCTION__, status );
 		tport->tp_tdev->td_urb_error = 1;
 		wake_up_interruptible(&tport->tp_write_wait);
 	}
 
-	if (urb->status == -EPIPE)
+	if (status == -EPIPE)
 		goto exit;
 
-	if (urb->status) {
+	if (status) {
 		dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
 		return;
 	}
@@ -1234,13 +1239,14 @@
 	spin_lock(&tport->tp_lock);
 	if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) {
 		urb->dev = port->serial->dev;
-		status = usb_submit_urb(urb, GFP_ATOMIC);
+		retval = usb_submit_urb(urb, GFP_ATOMIC);
 	} else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING) {
 		tport->tp_read_urb_state = TI_READ_URB_STOPPED;
 	}
 	spin_unlock(&tport->tp_lock);
-	if (status)
-		dev_err(dev, "%s - resubmit read urb failed, %d\n", __FUNCTION__, status);
+	if (retval)
+		dev_err(dev, "%s - resubmit read urb failed, %d\n",
+			__FUNCTION__, retval);
 }
 
 
@@ -1249,23 +1255,25 @@
 	struct ti_port *tport = (struct ti_port *)urb->context;
 	struct usb_serial_port *port = tport->tp_port;
 	struct device *dev = &urb->dev->dev;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	tport->tp_write_urb_in_use = 0;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		break;
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
-		dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down, %d", __FUNCTION__, status);
 		tport->tp_tdev->td_urb_error = 1;
 		wake_up_interruptible(&tport->tp_write_wait);
 		return;
 	default:
-		dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status);
+		dev_err(dev, "%s - nonzero urb status, %d\n",
+			__FUNCTION__, status);
 		tport->tp_tdev->td_urb_error = 1;
 		wake_up_interruptible(&tport->tp_write_wait);
 	}
@@ -1555,15 +1563,17 @@
 	spin_lock_irqsave(&tport->tp_lock, flags);
 
 	if (tport->tp_read_urb_state == TI_READ_URB_STOPPED) {
+		tport->tp_read_urb_state = TI_READ_URB_RUNNING;
 		urb = tport->tp_port->read_urb;
+		spin_unlock_irqrestore(&tport->tp_lock, flags);
 		urb->complete = ti_bulk_in_callback;
 		urb->context = tport;
 		urb->dev = tport->tp_port->serial->dev;
 		status = usb_submit_urb(urb, GFP_KERNEL);
+	} else  {
+		tport->tp_read_urb_state = TI_READ_URB_RUNNING;
+		spin_unlock_irqrestore(&tport->tp_lock, flags);
 	}
-	tport->tp_read_urb_state = TI_READ_URB_RUNNING;
-
-	spin_unlock_irqrestore(&tport->tp_lock, flags);
 
 	return status;
 }
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 87f3788..a366565 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -46,6 +46,8 @@
 	.name =		"usbserial",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
+	.suspend =	usb_serial_suspend,
+	.resume =	usb_serial_resume,
 	.no_dynamic_id = 	1,
 };
 
@@ -120,11 +122,9 @@
 	if (serial == NULL)
 		return;
 
-	spin_lock(&table_lock);
 	for (i = 0; i < serial->num_ports; ++i) {
 		serial_table[serial->minor + i] = NULL;
 	}
-	spin_unlock(&table_lock);
 }
 
 static void destroy_serial(struct kref *kref)
@@ -172,7 +172,9 @@
 
 void usb_serial_put(struct usb_serial *serial)
 {
+	spin_lock(&table_lock);
 	kref_put(&serial->kref, destroy_serial);
+	spin_unlock(&table_lock);
 }
 
 /*****************************************************************************
@@ -1069,6 +1071,35 @@
 	dev_info(dev, "device disconnected\n");
 }
 
+int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usb_serial *serial = usb_get_intfdata(intf);
+	struct usb_serial_port *port;
+	int i, r = 0;
+
+	if (serial) {
+		for (i = 0; i < serial->num_ports; ++i) {
+			port = serial->port[i];
+			if (port)
+				kill_traffic(port);
+		}
+	}
+
+	if (serial->type->suspend)
+		serial->type->suspend(serial, message);
+
+	return r;
+}
+EXPORT_SYMBOL(usb_serial_suspend);
+
+int usb_serial_resume(struct usb_interface *intf)
+{
+	struct usb_serial *serial = usb_get_intfdata(intf);
+
+	return serial->type->resume(serial);
+}
+EXPORT_SYMBOL(usb_serial_resume);
+
 static const struct tty_operations serial_ops = {
 	.open =			serial_open,
 	.close =		serial_close,
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index ffbe601..7d84a76 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -5,9 +5,9 @@
  *	Copyright (C) 1999 - 2004
  *	    Greg Kroah-Hartman (greg@kroah.com)
  *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License.
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
@@ -273,7 +273,8 @@
 	int bytes_in;
 	int bytes_out;
 	int outstanding_urbs;
-	int throttled;
+	unsigned char throttled;
+	unsigned char actually_throttled;
 };
 
 /* number of outstanding urbs to prevent userspace DoS from happening */
@@ -484,16 +485,17 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct visor_private *priv = usb_get_serial_port_data(port);
+	int status = urb->status;
 	unsigned long flags;
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree (urb->transfer_buffer);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	
-	if (urb->status)
+
+	if (status)
 		dbg("%s - nonzero write bulk status received: %d",
-		    __FUNCTION__, urb->status);
+		    __FUNCTION__, status);
 
 	spin_lock_irqsave(&priv->lock, flags);
 	--priv->outstanding_urbs;
@@ -508,15 +510,16 @@
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct visor_private *priv = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
+	int status = urb->status;
 	struct tty_struct *tty;
-	unsigned long flags;
-	int throttled;
 	int result;
+	int available_room;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -524,17 +527,20 @@
 
 	tty = port->tty;
 	if (tty && urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length);
-		tty_insert_flip_string(tty, data, urb->actual_length);
-		tty_flip_buffer_push(tty);
+		available_room = tty_buffer_request_room(tty, urb->actual_length);
+		if (available_room) {
+			tty_insert_flip_string(tty, data, available_room);
+			tty_flip_buffer_push(tty);
+		}
+		spin_lock(&priv->lock);
+		priv->bytes_in += available_room;
+
+	} else {
+		spin_lock(&priv->lock);
 	}
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->bytes_in += urb->actual_length;
-	throttled = priv->throttled;
-	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* Continue trying to always read if we should */
-	if (!throttled) {
+	if (!priv->throttled) {
 		usb_fill_bulk_urb (port->read_urb, port->serial->dev,
 				   usb_rcvbulkpipe(port->serial->dev,
 						   port->bulk_in_endpointAddress),
@@ -544,16 +550,19 @@
 		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 		if (result)
 			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+	} else {
+		priv->actually_throttled = 1;
 	}
-	return;
+	spin_unlock(&priv->lock);
 }
 
 static void visor_read_int_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int status = urb->status;
 	int result;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:
 		/* success */
 		break;
@@ -562,11 +571,11 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
+		    __FUNCTION__, status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
+		    __FUNCTION__, status);
 		goto exit;
 	}
 
@@ -608,6 +617,7 @@
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->throttled = 0;
+	priv->actually_throttled = 0;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	port->read_urb->dev = port->serial->dev;
@@ -938,14 +948,6 @@
 	}
 
 	cflag = port->tty->termios->c_cflag;
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg("%s - nothing to change...", __FUNCTION__);
-			return;
-		}
-	}
 
 	/* get the byte size */
 	switch (cflag & CSIZE) {
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 27c5f8f..cc8b44c 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -74,6 +74,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/termbits.h>
 #include <linux/usb.h>
@@ -203,7 +204,7 @@
 
 
 struct whiteheat_command_private {
-	spinlock_t		lock;
+	struct mutex		mutex;
 	__u8			port_running;
 	__u8			command_finished;
 	wait_queue_head_t	wait_command;	/* for handling sleeping while waiting for a command to finish */
@@ -232,6 +233,7 @@
 	struct usb_serial_port	*port;
 	struct list_head	tx_urbs_free;
 	struct list_head	tx_urbs_submitted;
+	struct mutex		deathwarrant;
 };
 
 
@@ -425,6 +427,7 @@
 		}
 
 		spin_lock_init(&info->lock);
+		mutex_init(&info->deathwarrant);
 		info->flags = 0;
 		info->mcr = 0;
 		INIT_WORK(&info->rx_work, rx_data_softint);
@@ -495,7 +498,7 @@
 		goto no_command_private;
 	}
 
-	spin_lock_init(&command_info->lock);
+	mutex_init(&command_info->mutex);
 	command_info->port_running = 0;
 	init_waitqueue_head(&command_info->wait_command);
 	usb_set_serial_port_data(command_port, command_info);
@@ -654,7 +657,6 @@
 	struct urb *urb;
 	struct list_head *tmp;
 	struct list_head *tmp2;
-	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	
@@ -683,24 +685,32 @@
 
 	firm_close(port);
 
+printk(KERN_ERR"Before processing rx_urbs_submitted.\n");
 	/* shutdown our bulk reads and writes */
-	spin_lock_irqsave(&info->lock, flags);
+	mutex_lock(&info->deathwarrant);
+	spin_lock_irq(&info->lock);
 	list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
 		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 		urb = wrap->urb;
+		list_del(tmp);
+		spin_unlock_irq(&info->lock);
 		usb_kill_urb(urb);
-		list_move(tmp, &info->rx_urbs_free);
+		spin_lock_irq(&info->lock);
+		list_add(tmp, &info->rx_urbs_free);
 	}
 	list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
 		list_move(tmp, &info->rx_urbs_free);
-
 	list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
 		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 		urb = wrap->urb;
+		list_del(tmp);
+		spin_unlock_irq(&info->lock);
 		usb_kill_urb(urb);
-		list_move(tmp, &info->tx_urbs_free);
+		spin_lock_irq(&info->lock);
+		list_add(tmp, &info->tx_urbs_free);
 	}
-	spin_unlock_irqrestore(&info->lock, flags);
+	spin_unlock_irq(&info->lock);
+	mutex_unlock(&info->deathwarrant);
 
 	stop_command_port(port->serial);
 
@@ -872,7 +882,7 @@
 }
 
 
-static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	dbg("%s -port %d", __FUNCTION__, port->number);
 
@@ -881,15 +891,6 @@
 		goto exit;
 	}
 	
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if ((port->tty->termios->c_cflag == old_termios->c_cflag) &&
-		    (port->tty->termios->c_iflag == old_termios->c_iflag)) {
-			dbg("%s - nothing to change...", __FUNCTION__);
-			goto exit;
-		}
-	}
-
 	firm_setup_port(port);
 
 exit:
@@ -920,7 +921,7 @@
 	spin_unlock_irqrestore(&info->lock, flags);
 
 	dbg ("%s - returns %d", __FUNCTION__, chars);
-	return (chars);
+	return chars;
 }
 
 
@@ -962,54 +963,57 @@
 /*****************************************************************************
  * Connect Tech's White Heat callback routines
  *****************************************************************************/
-static void command_port_write_callback (struct urb *urb)
+static void command_port_write_callback(struct urb *urb)
 {
+	int status = urb->status;
+
 	dbg("%s", __FUNCTION__);
 
-	if (urb->status) {
-		dbg ("nonzero urb status: %d", urb->status);
+	if (status) {
+		dbg("nonzero urb status: %d", status);
 		return;
 	}
 }
 
 
-static void command_port_read_callback (struct urb *urb)
+static void command_port_read_callback(struct urb *urb)
 {
 	struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context;
 	struct whiteheat_command_private *command_info;
+	int status = urb->status;
 	unsigned char *data = urb->transfer_buffer;
 	int result;
-	unsigned long flags;
 
 	dbg("%s", __FUNCTION__);
 
-	if (urb->status) {
-		dbg("%s - nonzero urb status: %d", __FUNCTION__, urb->status);
-		return;
-	}
-
-	usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
-
 	command_info = usb_get_serial_port_data(command_port);
 	if (!command_info) {
 		dbg ("%s - command_info is NULL, exiting.", __FUNCTION__);
 		return;
 	}
-	spin_lock_irqsave(&command_info->lock, flags);
+	if (status) {
+		dbg("%s - nonzero urb status: %d", __FUNCTION__, status);
+		if (status != -ENOENT)
+			command_info->command_finished = WHITEHEAT_CMD_FAILURE;
+		wake_up(&command_info->wait_command);
+		return;
+	}
+
+	usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
 
 	if (data[0] == WHITEHEAT_CMD_COMPLETE) {
 		command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
-		wake_up_interruptible(&command_info->wait_command);
+		wake_up(&command_info->wait_command);
 	} else if (data[0] == WHITEHEAT_CMD_FAILURE) {
 		command_info->command_finished = WHITEHEAT_CMD_FAILURE;
-		wake_up_interruptible(&command_info->wait_command);
+		wake_up(&command_info->wait_command);
 	} else if (data[0] == WHITEHEAT_EVENT) {
 		/* These are unsolicited reports from the firmware, hence no waiting command to wakeup */
 		dbg("%s - event received", __FUNCTION__);
 	} else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
 		memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1);
 		command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
-		wake_up_interruptible(&command_info->wait_command);
+		wake_up(&command_info->wait_command);
 	} else {
 		dbg("%s - bad reply from firmware", __FUNCTION__);
 	}
@@ -1017,7 +1021,6 @@
 	/* Continue trying to always read */
 	command_port->read_urb->dev = command_port->serial->dev;
 	result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
-	spin_unlock_irqrestore(&command_info->lock, flags);
 	if (result)
 		dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 }
@@ -1029,6 +1032,7 @@
 	struct whiteheat_urb_wrap *wrap;
 	unsigned char *data = urb->transfer_buffer;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -1042,8 +1046,9 @@
 	list_del(&wrap->list);
 	spin_unlock(&info->lock);
 
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, status);
 		spin_lock(&info->lock);
 		list_add(&wrap->list, &info->rx_urbs_free);
 		spin_unlock(&info->lock);
@@ -1070,6 +1075,7 @@
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
 	struct whiteheat_urb_wrap *wrap;
+	int status = urb->status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -1083,8 +1089,9 @@
 	list_move(&wrap->list, &info->tx_urbs_free);
 	spin_unlock(&info->lock);
 
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+	if (status) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, status);
 		return;
 	}
 
@@ -1095,20 +1102,20 @@
 /*****************************************************************************
  * Connect Tech's White Heat firmware interface
  *****************************************************************************/
-static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
+static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
 {
 	struct usb_serial_port *command_port;
 	struct whiteheat_command_private *command_info;
 	struct whiteheat_private *info;
 	__u8 *transfer_buffer;
 	int retval = 0;
-	unsigned long flags;
+	int t;
 
 	dbg("%s - command %d", __FUNCTION__, command);
 
 	command_port = port->serial->port[COMMAND_PORT];
 	command_info = usb_get_serial_port_data(command_port);
-	spin_lock_irqsave(&command_info->lock, flags);
+	mutex_lock(&command_info->mutex);
 	command_info->command_finished = false;
 	
 	transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer;
@@ -1116,18 +1123,17 @@
 	memcpy (&transfer_buffer[1], data, datasize);
 	command_port->write_urb->transfer_buffer_length = datasize + 1;
 	command_port->write_urb->dev = port->serial->dev;
-	retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL);
+	retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
 	if (retval) {
 		dbg("%s - submit urb failed", __FUNCTION__);
 		goto exit;
 	}
-	spin_unlock_irqrestore(&command_info->lock, flags);
 
 	/* wait for the command to complete */
-	wait_event_interruptible_timeout(command_info->wait_command,
+	t = wait_event_timeout(command_info->wait_command,
 		(bool)command_info->command_finished, COMMAND_TIMEOUT);
-
-	spin_lock_irqsave(&command_info->lock, flags);
+	if (!t)
+		usb_kill_urb(command_port->write_urb);
 
 	if (command_info->command_finished == false) {
 		dbg("%s - command timed out.", __FUNCTION__);
@@ -1152,7 +1158,7 @@
 	}
 
 exit:
-	spin_unlock_irqrestore(&command_info->lock, flags);
+	mutex_unlock(&command_info->mutex);
 	return retval;
 }
 
@@ -1305,12 +1311,11 @@
 {
 	struct usb_serial_port *command_port;
 	struct whiteheat_command_private *command_info;
-	unsigned long flags;
 	int retval = 0;
 	
 	command_port = serial->port[COMMAND_PORT];
 	command_info = usb_get_serial_port_data(command_port);
-	spin_lock_irqsave(&command_info->lock, flags);
+	mutex_lock(&command_info->mutex);
 	if (!command_info->port_running) {
 		/* Work around HCD bugs */
 		usb_clear_halt(serial->dev, command_port->read_urb->pipe);
@@ -1325,7 +1330,7 @@
 	command_info->port_running++;
 
 exit:
-	spin_unlock_irqrestore(&command_info->lock, flags);
+	mutex_unlock(&command_info->mutex);
 	return retval;
 }
 
@@ -1334,15 +1339,14 @@
 {
 	struct usb_serial_port *command_port;
 	struct whiteheat_command_private *command_info;
-	unsigned long flags;
 
 	command_port = serial->port[COMMAND_PORT];
 	command_info = usb_get_serial_port_data(command_port);
-	spin_lock_irqsave(&command_info->lock, flags);
+	mutex_lock(&command_info->mutex);
 	command_info->port_running--;
 	if (!command_info->port_running)
 		usb_kill_urb(command_port->read_urb);
-	spin_unlock_irqrestore(&command_info->lock, flags);
+	mutex_unlock(&command_info->mutex);
 }
 
 
@@ -1363,17 +1367,23 @@
 		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 		urb = wrap->urb;
 		urb->dev = port->serial->dev;
+		spin_unlock_irqrestore(&info->lock, flags);
 		retval = usb_submit_urb(urb, GFP_KERNEL);
 		if (retval) {
+			spin_lock_irqsave(&info->lock, flags);
 			list_add(tmp, &info->rx_urbs_free);
 			list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
 				wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 				urb = wrap->urb;
+				list_del(tmp);
+				spin_unlock_irqrestore(&info->lock, flags);
 				usb_kill_urb(urb);
-				list_move(tmp, &info->rx_urbs_free);
+				spin_lock_irqsave(&info->lock, flags);
+				list_add(tmp, &info->rx_urbs_free);
 			}
 			break;
 		}
+		spin_lock_irqsave(&info->lock, flags);
 		list_add(tmp, &info->rx_urbs_submitted);
 	}
 
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 6d3dad3..d353693 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -84,7 +84,7 @@
 
 static int usb_onetouch_open(struct input_dev *dev)
 {
-	struct usb_onetouch *onetouch = dev->private;
+	struct usb_onetouch *onetouch = input_get_drvdata(dev);
 
 	onetouch->is_open = 1;
 	onetouch->irq->dev = onetouch->udev;
@@ -98,7 +98,7 @@
 
 static void usb_onetouch_close(struct input_dev *dev)
 {
-	struct usb_onetouch *onetouch = dev->private;
+	struct usb_onetouch *onetouch = input_get_drvdata(dev);
 
 	usb_kill_urb(onetouch->irq);
 	onetouch->is_open = 0;
@@ -185,13 +185,14 @@
 	input_dev->name = onetouch->name;
 	input_dev->phys = onetouch->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &udev->dev;
+	input_dev->dev.parent = &udev->dev;
 
 	set_bit(EV_KEY, input_dev->evbit);
 	set_bit(ONETOUCH_BUTTON, input_dev->keybit);
 	clear_bit(0, input_dev->keybit);
 
-	input_dev->private = onetouch;
+	input_set_drvdata(input_dev, onetouch);
+
 	input_dev->open = usb_onetouch_open;
 	input_dev->close = usb_onetouch_close;
 
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index e227f64..47e5607 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -285,10 +285,15 @@
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
 
-	/* lock the device pointers and do the reset */
-	mutex_lock(&(us->dev_mutex));
-	result = us->transport_reset(us);
-	mutex_unlock(&us->dev_mutex);
+	result = usb_autopm_get_interface(us->pusb_intf);
+	if (result == 0) {
+
+		/* lock the device pointers and do the reset */
+		mutex_lock(&(us->dev_mutex));
+		result = us->transport_reset(us);
+		mutex_unlock(&us->dev_mutex);
+		usb_autopm_put_interface(us->pusb_intf);
+	}
 
 	return result < 0 ? FAILED : SUCCESS;
 }
@@ -321,10 +326,14 @@
 
 /* Report a driver-initiated bus reset to the SCSI layer.
  * Calling this for a SCSI-initiated reset is unnecessary but harmless.
- * The caller must own the SCSI host lock. */
+ * The caller must not own the SCSI host lock. */
 void usb_stor_report_bus_reset(struct us_data *us)
 {
-	scsi_report_bus_reset(us_to_host(us), 0);
+	struct Scsi_Host *host = us_to_host(us);
+
+	scsi_lock(host);
+	scsi_report_bus_reset(host, 0);
+	scsi_unlock(host);
 }
 
 /***********************************************************************
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 8b3145ab..b6bf31a 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -50,10 +50,10 @@
 /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
  */
 UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
-                "ATMEL",
-                "SND1 Storage",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_IGNORE_RESIDUE),
+		"ATMEL",
+		"SND1 Storage",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE),
 
 /* modified by Tobias Lorenz <tobias.lorenz@gmx.net> */
 UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0200,
@@ -69,18 +69,18 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
-UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200,
 		"HP",
 		"CD-Writer+",
-		US_SC_8070, US_PR_CB, NULL, 0), 
+		US_SC_8070, US_PR_CB, NULL, 0),
 
 #ifdef CONFIG_USB_STORAGE_USBAT
-UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001, 
+UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001,
 		"HP",
 		"CD-Writer+ 8200e",
 		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
 
-UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001, 
+UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
 		"HP",
 		"CD-Writer+ CD-4e",
 		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
@@ -115,10 +115,10 @@
 
 /* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */
 UNUSUAL_DEV(  0x0419, 0x0100, 0x0100, 0x0100,
-                "Samsung Info. Systems America, Inc.",
-                "MP3 Player",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_IGNORE_RESIDUE ),
+		"Samsung Info. Systems America, Inc.",
+		"MP3 Player",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Orgad Shaneh <orgads@gmail.com> */
 UNUSUAL_DEV(  0x0419, 0xaace, 0x0100, 0x0100,
@@ -256,10 +256,10 @@
 * the revision to my model only
 */
 UNUSUAL_DEV(  0x0457, 0x0151, 0x0100, 0x0100,
-                "USB 2.0",
-                "Flash Disk",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_NOT_LOCKABLE ),
+		"USB 2.0",
+		"Flash Disk",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_NOT_LOCKABLE ),
 
 #ifdef CONFIG_USB_STORAGE_KARMA
 UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
@@ -408,19 +408,19 @@
 /* Most of the following entries were developed with the help of
  * Shuttle/SCM directly.
  */
-UNUSUAL_DEV(  0x04e6, 0x0001, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x0001, 0x0200, 0x0200,
 		"Matshita",
 		"LS-120",
 		US_SC_8020, US_PR_CB, NULL, 0),
 
-UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, 
-		US_FL_SCM_MULT_TARG ), 
+		US_FL_SCM_MULT_TARG ),
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999, 
+UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999,
 		"Sandisk",
 		"ImageMate SDDR09",
 		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -431,52 +431,52 @@
 		"SCM Microsystems",
 		"eUSB SmartMedia / CompactFlash Adapter",
 		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
-		0), 
+		0),
 #endif
 
 /* Reported by Markus Demleitner <msdemlei@cl.uni-heidelberg.de> */
-UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0100,
 		"SCM Microsystems Inc.",
 		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_CB, NULL, 
-		US_FL_SINGLE_LUN), 
+		US_SC_SCSI, US_PR_CB, NULL,
+		US_FL_SINGLE_LUN),
 
 /* Reported by Daniel Nouri <dpunktnpunkt@web.de> */
-UNUSUAL_DEV(  0x04e6, 0x0006, 0x0205, 0x0205, 
+UNUSUAL_DEV(  0x04e6, 0x0006, 0x0205, 0x0205,
 		"Shuttle",
 		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_DEVICE, NULL, 
-		US_FL_SINGLE_LUN), 
+		US_SC_SCSI, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN),
 
-UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200,
 		"Sony",
 		"Hifd",
-		US_SC_SCSI, US_PR_CB, NULL, 
-		US_FL_SINGLE_LUN), 
+		US_SC_SCSI, US_PR_CB, NULL,
+		US_FL_SINGLE_LUN),
 
-UNUSUAL_DEV(  0x04e6, 0x0009, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x0009, 0x0200, 0x0200,
 		"Shuttle",
 		"eUSB ATA/ATAPI Adapter",
 		US_SC_8020, US_PR_CB, NULL, 0),
 
-UNUSUAL_DEV(  0x04e6, 0x000a, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x000a, 0x0200, 0x0200,
 		"Shuttle",
 		"eUSB CompactFlash Adapter",
 		US_SC_8020, US_PR_CB, NULL, 0),
 
-UNUSUAL_DEV(  0x04e6, 0x000B, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x04e6, 0x000B, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ), 
 
-UNUSUAL_DEV(  0x04e6, 0x000C, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x04e6, 0x000C, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
-		US_FL_SCM_MULT_TARG ), 
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		US_FL_SCM_MULT_TARG ),
 
-UNUSUAL_DEV(  0x04e6, 0x0101, 0x0200, 0x0200, 
+UNUSUAL_DEV(  0x04e6, 0x0101, 0x0200, 0x0200,
 		"Shuttle",
 		"CD-RW Device",
 		US_SC_8020, US_PR_CB, NULL, 0),
@@ -556,9 +556,9 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
-UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450, 
+UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450,
 		"Sony",
-		"DSC-S30/S70/S75/505V/F505/F707/F717/P8", 
+		"DSC-S30/S70/S75/505V/F505/F707/F717/P8",
 		US_SC_SCSI, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
 
@@ -572,7 +572,7 @@
 
 
 /* Reported by wim@geeks.nl */
-UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100,
 		"Sony",
 		"Memorystick NW-MS7",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -593,21 +593,21 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
-UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100,
 		"Sony",
 		"Memorystick MSAC-US1",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Klaus Mueller <k.mueller@intershop.de> */
-UNUSUAL_DEV(  0x054c, 0x002e, 0x0106, 0x0310, 
+UNUSUAL_DEV(  0x054c, 0x002e, 0x0106, 0x0310,
 		"Sony",
 		"Handycam",
 		US_SC_SCSI, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */
-UNUSUAL_DEV(  0x054c, 0x002e, 0x0500, 0x0500, 
+UNUSUAL_DEV(  0x054c, 0x002e, 0x0500, 0x0500,
 		"Sony",
 		"Handycam HC-85",
 		US_SC_UFI, US_PR_DEVICE, NULL,
@@ -648,26 +648,26 @@
 		
 /* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */
 UNUSUAL_DEV(  0x054c, 0x0099, 0x0000, 0x9999,
-                "Sony",
-                "PEG Mass Storage",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_FIX_INQUIRY ),
+		"Sony",
+		"PEG Mass Storage",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY ),
 
 /* floppy reports multiple luns */
 UNUSUAL_DEV(  0x055d, 0x2020, 0x0000, 0x0210,
-               "SAMSUNG",
-               "SFD-321U [FW 0C]",
-               US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_SINGLE_LUN ),
+		"SAMSUNG",
+		"SFD-321U [FW 0C]",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN ),
 
 		
-UNUSUAL_DEV(  0x057b, 0x0000, 0x0000, 0x0299, 
+UNUSUAL_DEV(  0x057b, 0x0000, 0x0000, 0x0299,
 		"Y-E Data",
 		"Flashbuster-U",
 		US_SC_DEVICE,  US_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 
-UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x9999, 
+UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x9999,
 		"Y-E Data",
 		"Flashbuster-U",
 		US_SC_DEVICE,  US_PR_DEVICE, NULL,
@@ -677,7 +677,7 @@
  * This entry is needed only because the device reports
  * bInterfaceClass = 0xff (vendor-specific)
  */
-UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999, 
+UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999,
 		"Y-E Data",
 		"Silicon Media R/W",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
@@ -825,13 +825,13 @@
 		US_SC_SCSI, US_PR_BULK, NULL,
 		US_FL_FIX_INQUIRY ),
 
-UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100,
 		"TEAC",
 		"Floppy Drive",
-		US_SC_UFI, US_PR_CB, NULL, 0 ), 
+		US_SC_UFI, US_PR_CB, NULL, 0 ),
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
 		"Olympus",
 		"Camedia MAUSB-2",
 		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -867,14 +867,14 @@
 
 /* Reported by Miguel A. Fosas <amn3s1a@ono.com> */
 UNUSUAL_DEV(  0x0686, 0x4017, 0x0001, 0x0001,
-                "Minolta",
-                "DIMAGE E223",
-                US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
+		"Minolta",
+		"DIMAGE E223",
+		US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
 
 UNUSUAL_DEV(  0x0693, 0x0005, 0x0100, 0x0100,
 		"Hagiwara",
 		"Flashgate",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ), 
+		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
 
 /* Reported by David Hamilton <niftimusmaximus@lycos.com> */
 UNUSUAL_DEV(  0x069b, 0x3004, 0x0001, 0x0001,
@@ -918,7 +918,7 @@
 		US_FL_SINGLE_LUN ),
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999, 
+UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999,
 		"Sandisk",
 		"ImageMate SDDR-09",
 		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -939,17 +939,17 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
-UNUSUAL_DEV(  0x07af, 0x0004, 0x0100, 0x0133, 
+UNUSUAL_DEV(  0x07af, 0x0004, 0x0100, 0x0133,
 		"Microtech",
 		"USB-SCSI-DB25",
 		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ), 
 
-UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100, 
+UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100,
 		"Microtech",
 		"USB-SCSI-HD50",
 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
-		US_FL_SCM_MULT_TARG ), 
+		US_FL_SCM_MULT_TARG ),
 
 #ifdef CONFIG_USB_STORAGE_DPCM
 UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
@@ -1053,10 +1053,10 @@
  * as "DualSlot CompactFlash(TM) & MStick Drive USB"
  */
 UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
-                "DataFab Systems Inc.",
-                "USB CF+MS",
-                US_SC_SCSI, US_PR_DATAFAB, NULL,
-                0 ),
+		"DataFab Systems Inc.",
+		"USB CF+MS",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		0 ),
 
 #endif
 
@@ -1119,10 +1119,10 @@
  * US_FL_IGNORE_RESIDUE Needed
  */
 UNUSUAL_DEV(  0x08ca, 0x3103, 0x0100, 0x0100,
-                "AIPTEK",
-                "Aiptek USB Keychain MP3 Player",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_IGNORE_RESIDUE),
+		"AIPTEK",
+		"Aiptek USB Keychain MP3 Player",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE),
 
 /* Entry needed for flags. Moreover, all devices with this ID use
  * bulk-only transport, but _some_ falsely report Control/Bulk instead.
@@ -1166,26 +1166,40 @@
  * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
  */
 UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
-                "Pentax",
-                "Optio 2/3/400",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_FIX_INQUIRY ),
+		"Pentax",
+		"Optio 2/3/400",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY ),
 
 
 /* Submitted by Per Winkvist <per.winkvist@uk.com> */
 UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
-                "Pentax",
-                "Optio S/S4",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_FIX_INQUIRY ),
+		"Pentax",
+		"Optio S/S4",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY ),
 
-/* This is a virtual windows driver CD, which the zd1211rw driver automatically
- * converts into a WLAN device. */
+/* These are virtual windows driver CDs, which the zd1211rw driver
+ * automatically converts into WLAN devices. */
 UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
-                "ZyXEL",
-                "G-220F USB-WLAN Install",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_IGNORE_DEVICE ),
+		"ZyXEL",
+		"G-220F USB-WLAN Install",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_DEVICE ),
+
+UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101,
+		"SiteCom",
+		"WL-117 USB-WLAN Install",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_DEVICE ),
+
+/* SanDisk that has a second LUN for a driver ISO, reported by
+ * Ben Collins <bcollins@ubuntu.com> */
+UNUSUAL_DEV( 0x0781, 0x5406, 0x0000, 0xffff,
+		"SanDisk",
+		"U3 Cruzer Micro driver ISO",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN ),
 
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
@@ -1197,17 +1211,17 @@
 
 #ifdef CONFIG_USB_STORAGE_DATAFAB
 UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
-	       "Acomdata",
-	       "CF",
-	       US_SC_SCSI, US_PR_DATAFAB, NULL,
-	       US_FL_SINGLE_LUN ),
+		"Acomdata",
+		"CF",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		US_FL_SINGLE_LUN ),
 #endif
 #ifdef CONFIG_USB_STORAGE_SDDR55
 UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
-	       "Acomdata",
-	       "SM",
-	       US_SC_SCSI, US_PR_SDDR55, NULL,
-	       US_FL_SINGLE_LUN ),
+		"Acomdata",
+		"SM",
+		US_SC_SCSI, US_PR_SDDR55, NULL,
+		US_FL_SINGLE_LUN ),
 #endif
 
 /* Submitted by: Nick Sillik <n.sillik@temple.edu>
@@ -1265,6 +1279,15 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Reported by Edward Chapman (taken from linux-usb mailing list)
+   Netac OnlyDisk Mini U2CV2 512MB USB 2.0 Flash Drive */
+UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999,
+		"Netac",
+		"USB Flash Disk",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
+
+
 /* Patch by Stephan Walter <stephan.walter@epfl.ch>
  * I don't know why, but it works... */
 UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012,
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 8e898e3..28842d2 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -191,16 +191,13 @@
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
+	US_DEBUGP("%s\n", __FUNCTION__);
+
 	/* Wait until no command is running */
 	mutex_lock(&us->dev_mutex);
 
-	US_DEBUGP("%s\n", __FUNCTION__);
 	if (us->suspend_resume_hook)
 		(us->suspend_resume_hook)(us, US_SUSPEND);
-	iface->dev.power.power_state.event = message.event;
-
-	/* When runtime PM is working, we'll set a flag to indicate
-	 * whether we should autoresume when a SCSI request arrives. */
 
 	mutex_unlock(&us->dev_mutex);
 	return 0;
@@ -210,14 +207,25 @@
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
-	mutex_lock(&us->dev_mutex);
-
 	US_DEBUGP("%s\n", __FUNCTION__);
+
 	if (us->suspend_resume_hook)
 		(us->suspend_resume_hook)(us, US_RESUME);
-	iface->dev.power.power_state.event = PM_EVENT_ON;
 
-	mutex_unlock(&us->dev_mutex);
+	return 0;
+}
+
+static int storage_reset_resume(struct usb_interface *iface)
+{
+	struct us_data *us = usb_get_intfdata(iface);
+
+	US_DEBUGP("%s\n", __FUNCTION__);
+
+	/* Report the reset to the SCSI core */
+	usb_stor_report_bus_reset(us);
+
+	/* FIXME: Notify the subdrivers that they need to reinitialize
+	 * the device */
 	return 0;
 }
 
@@ -228,7 +236,7 @@
  * a USB port reset, whether from this driver or a different one.
  */
 
-static void storage_pre_reset(struct usb_interface *iface)
+static int storage_pre_reset(struct usb_interface *iface)
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
@@ -236,22 +244,23 @@
 
 	/* Make sure no command runs during the reset */
 	mutex_lock(&us->dev_mutex);
+	return 0;
 }
 
-static void storage_post_reset(struct usb_interface *iface)
+static int storage_post_reset(struct usb_interface *iface)
 {
 	struct us_data *us = usb_get_intfdata(iface);
 
 	US_DEBUGP("%s\n", __FUNCTION__);
 
 	/* Report the reset to the SCSI core */
-	scsi_lock(us_to_host(us));
 	usb_stor_report_bus_reset(us);
-	scsi_unlock(us_to_host(us));
 
 	/* FIXME: Notify the subdrivers that they need to reinitialize
 	 * the device */
+
 	mutex_unlock(&us->dev_mutex);
+	return 0;
 }
 
 /*
@@ -300,8 +309,7 @@
 {
 	struct us_data *us = (struct us_data *)__us;
 	struct Scsi_Host *host = us_to_host(us);
-
-	current->flags |= PF_NOFREEZE;
+	int autopm_rc;
 
 	for(;;) {
 		US_DEBUGP("*** thread sleeping.\n");
@@ -310,6 +318,9 @@
 			
 		US_DEBUGP("*** thread awakened.\n");
 
+		/* Autoresume the device */
+		autopm_rc = usb_autopm_get_interface(us->pusb_intf);
+
 		/* lock the device pointers */
 		mutex_lock(&(us->dev_mutex));
 
@@ -368,6 +379,12 @@
 			us->srb->result = SAM_STAT_GOOD;
 		}
 
+		/* Did the autoresume fail? */
+		else if (autopm_rc < 0) {
+			US_DEBUGP("Could not wake device\n");
+			us->srb->result = DID_ERROR << 16;
+		}
+
 		/* we've got a command, let's do it! */
 		else {
 			US_DEBUG(usb_stor_show_command(us->srb));
@@ -410,25 +427,21 @@
 
 		/* unlock the device pointers */
 		mutex_unlock(&us->dev_mutex);
+
+		/* Start an autosuspend */
+		if (autopm_rc == 0)
+			usb_autopm_put_interface(us->pusb_intf);
 	} /* for (;;) */
 
-	scsi_host_put(host);
-
-	/* notify the exit routine that we're actually exiting now 
-	 *
-	 * complete()/wait_for_completion() is similar to up()/down(),
-	 * except that complete() is safe in the case where the structure
-	 * is getting deleted in a parallel mode of execution (i.e. just
-	 * after the down() -- that's necessary for the thread-shutdown
-	 * case.
-	 *
-	 * complete_and_exit() goes even further than this -- it is safe in
-	 * the case that the thread of the caller is going away (not just
-	 * the structure) -- this is necessary for the module-remove case.
-	 * This is important in preemption kernels, which transfer the flow
-	 * of execution immediately upon a complete().
-	 */
-	complete_and_exit(&threads_gone, 0);
+	/* Wait until we are told to stop */
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (kthread_should_stop())
+			break;
+		schedule();
+	}
+	__set_current_state(TASK_RUNNING);
+	return 0;
 }	
 
 /***********************************************************************
@@ -796,19 +809,13 @@
 	}
 
 	/* Start up our control thread */
-	th = kthread_create(usb_stor_control_thread, us, "usb-storage");
+	th = kthread_run(usb_stor_control_thread, us, "usb-storage");
 	if (IS_ERR(th)) {
 		printk(KERN_WARNING USB_STORAGE 
 		       "Unable to start control thread\n");
 		return PTR_ERR(th);
 	}
-
-	/* Take a reference to the host for the control thread and
-	 * count it among all the threads we have launched.  Then
-	 * start it up. */
-	scsi_host_get(us_to_host(us));
-	atomic_inc(&total_threads);
-	wake_up_process(th);
+	us->ctl_thread = th;
 
 	return 0;
 }
@@ -825,6 +832,8 @@
 	US_DEBUGP("-- sending exit command to thread\n");
 	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
 	up(&us->sema);
+	if (us->ctl_thread)
+		kthread_stop(us->ctl_thread);
 
 	/* Call the destructor routine, if it exists */
 	if (us->extra_destructor) {
@@ -909,6 +918,7 @@
 	printk(KERN_DEBUG
 		"usb-storage: device found at %d\n", us->pusb_dev->devnum);
 
+	set_freezable();
 	/* Wait for the timeout to expire or for a disconnect */
 	if (delay_use > 0) {
 		printk(KERN_DEBUG "usb-storage: waiting for device "
@@ -938,6 +948,7 @@
 	}
 
 	scsi_host_put(us_to_host(us));
+	usb_autopm_put_interface(us->pusb_intf);
 	complete_and_exit(&threads_gone, 0);
 }
 
@@ -1027,6 +1038,7 @@
 	 * start it up. */
 	scsi_host_get(us_to_host(us));
 	atomic_inc(&total_threads);
+	usb_autopm_get_interface(intf); /* dropped in the scanning thread */
 	wake_up_process(th);
 
 	return 0;
@@ -1059,10 +1071,12 @@
 #ifdef CONFIG_PM
 	.suspend =	storage_suspend,
 	.resume =	storage_resume,
+	.reset_resume =	storage_reset_resume,
 #endif
 	.pre_reset =	storage_pre_reset,
 	.post_reset =	storage_post_reset,
 	.id_table =	storage_usb_ids,
+	.supports_autosuspend = 1,
 };
 
 static int __init usb_stor_init(void)
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 6dac1ff..6445665 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -144,6 +144,7 @@
 	unsigned char		*sensebuf;	 /* sense data buffer	 */
 	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
 	dma_addr_t		iobuf_dma;
+	struct task_struct	*ctl_thread;	 /* the control thread   */
 
 	/* mutual exclusion and synchronization structures */
 	struct semaphore	sema;		 /* to sleep thread on	    */
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 8432bf1..8de11de 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -34,9 +34,6 @@
 };
 MODULE_DEVICE_TABLE(usb, skel_table);
 
-/* to prevent a race between open and disconnect */
-static DEFINE_MUTEX(skel_open_lock);
-
 
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE	192
@@ -54,16 +51,21 @@
 	struct usb_device	*udev;			/* the usb device for this device */
 	struct usb_interface	*interface;		/* the interface for this device */
 	struct semaphore	limit_sem;		/* limiting the number of writes in progress */
+	struct usb_anchor	submitted;		/* in case we need to retract our submissions */
 	unsigned char           *bulk_in_buffer;	/* the buffer to receive data */
 	size_t			bulk_in_size;		/* the size of the receive buffer */
 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
 	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
+	int			errors;			/* the last request tanked */
+	int			open_count;		/* count the number of openers */
+	spinlock_t		err_lock;		/* lock for errors */
 	struct kref		kref;
 	struct mutex		io_mutex;		/* synchronize I/O with disconnect */
 };
 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
 static struct usb_driver skel_driver;
+static void skel_draw_down(struct usb_skel *dev);
 
 static void skel_delete(struct kref *kref)
 {
@@ -83,10 +85,8 @@
 
 	subminor = iminor(inode);
 
-	mutex_lock(&skel_open_lock);
 	interface = usb_find_interface(&skel_driver, subminor);
 	if (!interface) {
-		mutex_unlock(&skel_open_lock);
 		err ("%s - error, can't find device for minor %d",
 		     __FUNCTION__, subminor);
 		retval = -ENODEV;
@@ -95,22 +95,33 @@
 
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
-		mutex_unlock(&skel_open_lock);
 		retval = -ENODEV;
 		goto exit;
 	}
 
 	/* increment our usage count for the device */
 	kref_get(&dev->kref);
-	/* now we can drop the lock */
-	mutex_unlock(&skel_open_lock);
 
-	/* prevent the device from being autosuspended */
-	retval = usb_autopm_get_interface(interface);
-	if (retval) {
+	/* lock the device to allow correctly handling errors
+	 * in resumption */
+	mutex_lock(&dev->io_mutex);
+
+	if (!dev->open_count++) {
+		retval = usb_autopm_get_interface(interface);
+			if (retval) {
+				dev->open_count--;
+				mutex_unlock(&dev->io_mutex);
+				kref_put(&dev->kref, skel_delete);
+				goto exit;
+			}
+	} /* else { //uncomment this block if you want exclusive open
+		retval = -EBUSY;
+		dev->open_count--;
+		mutex_unlock(&dev->io_mutex);
 		kref_put(&dev->kref, skel_delete);
 		goto exit;
-	}
+	} */
+	/* prevent the device from being autosuspended */
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
@@ -129,7 +140,7 @@
 
 	/* allow the device to be autosuspended */
 	mutex_lock(&dev->io_mutex);
-	if (dev->interface)
+	if (!--dev->open_count && dev->interface)
 		usb_autopm_put_interface(dev->interface);
 	mutex_unlock(&dev->io_mutex);
 
@@ -138,6 +149,30 @@
 	return 0;
 }
 
+static int skel_flush(struct file *file, fl_owner_t id)
+{
+	struct usb_skel *dev;
+	int res;
+
+	dev = (struct usb_skel *)file->private_data;
+	if (dev == NULL)
+		return -ENODEV;
+
+	/* wait for io to stop */
+	mutex_lock(&dev->io_mutex);
+	skel_draw_down(dev);
+
+	/* read out errors, leave subsequent opens a clean slate */
+	spin_lock_irq(&dev->err_lock);
+	res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0;
+	dev->errors = 0;
+	spin_unlock_irq(&dev->err_lock);
+
+	mutex_unlock(&dev->io_mutex);
+
+	return res;
+}
+
 static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct usb_skel *dev;
@@ -179,12 +214,16 @@
 	dev = (struct usb_skel *)urb->context;
 
 	/* sync/async unlink faults aren't errors */
-	if (urb->status &&
-	    !(urb->status == -ENOENT ||
-	      urb->status == -ECONNRESET ||
-	      urb->status == -ESHUTDOWN)) {
-		err("%s - nonzero write bulk status received: %d",
-		    __FUNCTION__, urb->status);
+	if (urb->status) {
+		if(!(urb->status == -ENOENT ||
+		    urb->status == -ECONNRESET ||
+		    urb->status == -ESHUTDOWN))
+			err("%s - nonzero write bulk status received: %d",
+			    __FUNCTION__, urb->status);
+
+		spin_lock(&dev->err_lock);
+		dev->errors = urb->status;
+		spin_unlock(&dev->err_lock);
 	}
 
 	/* free up our allocated buffer */
@@ -213,6 +252,17 @@
 		goto exit;
 	}
 
+	spin_lock_irq(&dev->err_lock);
+	if ((retval = dev->errors) < 0) {
+		/* any error is reported once */
+		dev->errors = 0;
+		/* to preserve notifications about reset */
+		retval = (retval == -EPIPE) ? retval : -EIO;
+	}
+	spin_unlock_irq(&dev->err_lock);
+	if (retval < 0)
+		goto error;
+
 	/* create a urb, and a buffer for it, and copy the data to the urb */
 	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
@@ -244,13 +294,14 @@
 			  usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
 			  buf, writesize, skel_write_bulk_callback, dev);
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	usb_anchor_urb(urb, &dev->submitted);
 
 	/* send the data out the bulk port */
 	retval = usb_submit_urb(urb, GFP_KERNEL);
 	mutex_unlock(&dev->io_mutex);
 	if (retval) {
 		err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
-		goto error;
+		goto error_unanchor;
 	}
 
 	/* release our reference to this urb, the USB core will eventually free it entirely */
@@ -259,6 +310,8 @@
 
 	return writesize;
 
+error_unanchor:
+	usb_unanchor_urb(urb);
 error:
 	if (urb) {
 		usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
@@ -276,6 +329,7 @@
 	.write =	skel_write,
 	.open =		skel_open,
 	.release =	skel_release,
+	.flush =	skel_flush,
 };
 
 /*
@@ -306,6 +360,8 @@
 	kref_init(&dev->kref);
 	sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
 	mutex_init(&dev->io_mutex);
+	spin_lock_init(&dev->err_lock);
+	init_usb_anchor(&dev->submitted);
 
 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
@@ -368,22 +424,18 @@
 	struct usb_skel *dev;
 	int minor = interface->minor;
 
-	/* prevent skel_open() from racing skel_disconnect() */
-	mutex_lock(&skel_open_lock);
-
 	dev = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 
 	/* give back our minor */
 	usb_deregister_dev(interface, &skel_class);
-	mutex_unlock(&skel_open_lock);
 
 	/* prevent more I/O from starting */
 	mutex_lock(&dev->io_mutex);
 	dev->interface = NULL;
 	mutex_unlock(&dev->io_mutex);
 
-
+	usb_kill_anchored_urbs(&dev->submitted);
 
 	/* decrement our usage count */
 	kref_put(&dev->kref, skel_delete);
@@ -391,10 +443,59 @@
 	info("USB Skeleton #%d now disconnected", minor);
 }
 
+static void skel_draw_down(struct usb_skel *dev)
+{
+	int time;
+
+	time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+	if (!time)
+		usb_kill_anchored_urbs(&dev->submitted);
+}
+
+static int skel_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usb_skel *dev = usb_get_intfdata(intf);
+
+	if (!dev)
+		return 0;
+	skel_draw_down(dev);
+	return 0;
+}
+
+static int skel_resume (struct usb_interface *intf)
+{
+	return 0;
+}
+
+static int skel_pre_reset(struct usb_interface *intf)
+{
+	struct usb_skel *dev = usb_get_intfdata(intf);
+
+	mutex_lock(&dev->io_mutex);
+	skel_draw_down(dev);
+
+	return 0;
+}
+
+static int skel_post_reset(struct usb_interface *intf)
+{
+	struct usb_skel *dev = usb_get_intfdata(intf);
+
+	/* we are sure no URBs are active - no locking needed */
+	dev->errors = -EPIPE;
+	mutex_unlock(&dev->io_mutex);
+
+	return 0;
+}
+
 static struct usb_driver skel_driver = {
 	.name =		"skeleton",
 	.probe =	skel_probe,
 	.disconnect =	skel_disconnect,
+	.suspend =	skel_suspend,
+	.resume =	skel_resume,
+	.pre_reset =	skel_pre_reset,
+	.post_reset =	skel_post_reset,
 	.id_table =	skel_table,
 	.supports_autosuspend = 1,
 };
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 0dda73d..7f907fb 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -60,7 +60,7 @@
 static u_long videomemorysize;
 
 static struct fb_info fb_info;
-static u32 mc68x328fb_pseudo_palette[17];
+static u32 mc68x328fb_pseudo_palette[16];
 
 static struct fb_var_screeninfo mc68x328fb_default __initdata = {
 	.red =		{ 0, 8, 0 },
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4d7485f..0c5644bb 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -704,6 +704,91 @@
 	  This is the frame buffer device driver for the CGsix (GX, TurboGX)
 	  frame buffer.
 
+config FB_FFB
+	bool "Creator/Creator3D/Elite3D support"
+	depends on FB_SBUS && SPARC64
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Creator, Creator3D,
+	  and Elite3D graphics boards.
+
+config FB_TCX
+	bool "TCX (SS4/SS5 only) support"
+	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the TCX 24/8bit frame
+	  buffer.
+
+config FB_CG14
+	bool "CGfourteen (SX) support"
+	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the CGfourteen frame
+	  buffer on Desktop SPARCsystems with the SX graphics option.
+
+config FB_P9100
+	bool "P9100 (Sparcbook 3 only) support"
+	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the P9100 card
+	  supported on Sparcbook 3 machines.
+
+config FB_LEO
+	bool "Leo (ZX) support"
+	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the SBUS-based Sun ZX
+	  (leo) frame buffer cards.
+
+config FB_IGA
+	bool "IGA 168x display support"
+	depends on (FB = y) && SPARC32
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for the INTERGRAPHICS 1680 and
+	  successor frame buffer cards.
+
+config FB_XVR500
+	bool "Sun XVR-500 3DLABS Wildcat support"
+	depends on (FB = y) && PCI && SPARC64
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for the Sun XVR-500 and similar
+	  graphics cards based upon the 3DLABS Wildcat chipset.  The driver
+	  only works on sparc64 systems where the system firwmare has
+	  mostly initialized the card already.  It is treated as a
+	  completely dumb framebuffer device.
+
+config FB_XVR2500
+	bool "Sun XVR-2500 3DLABS Wildcat support"
+	depends on (FB = y) && PCI && SPARC64
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for the Sun XVR-2500 and similar
+	  graphics cards based upon the 3DLABS Wildcat chipset.  The driver
+	  only works on sparc64 systems where the system firwmare has
+	  mostly initialized the card already.  It is treated as a
+	  completely dumb framebuffer device.
+
 config FB_PVR2
 	tristate "NEC PowerVR 2 display support"
 	depends on FB && SH_DREAMCAST
@@ -727,7 +812,7 @@
 
 config FB_EPSON1355
 	bool "Epson 1355 framebuffer support"
-	depends on (FB = y) && (SUPERH || ARCH_CEIVA)
+	depends on (FB = y) && ARCH_CEIVA
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -1195,7 +1280,7 @@
 config FB_ATY_CT
 	bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support"
 	depends on PCI && FB_ATY
-	default y if SPARC64 && FB_PCI
+	default y if SPARC64 && PCI
 	help
 	  Say Y here to support use of ATI's 64-bit Rage boards (or other
 	  boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
@@ -1484,95 +1569,6 @@
 
 source "drivers/video/geode/Kconfig"
 
-config FB_FFB
-	bool "Creator/Creator3D/Elite3D support"
-	depends on FB_SBUS && SPARC64
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the Creator, Creator3D,
-	  and Elite3D graphics boards.
-
-config FB_TCX
-	bool "TCX (SS4/SS5 only) support"
-	depends on FB_SBUS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the TCX 24/8bit frame
-	  buffer.
-
-config FB_CG14
-	bool "CGfourteen (SX) support"
-	depends on FB_SBUS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the CGfourteen frame
-	  buffer on Desktop SPARCsystems with the SX graphics option.
-
-config FB_P9100
-	bool "P9100 (Sparcbook 3 only) support"
-	depends on FB_SBUS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the P9100 card
-	  supported on Sparcbook 3 machines.
-
-config FB_LEO
-	bool "Leo (ZX) support"
-	depends on FB_SBUS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the SBUS-based Sun ZX
-	  (leo) frame buffer cards.
-
-config FB_XVR500
-	bool "Sun XVR-500 3DLABS Wildcat support"
-	depends on (FB = y) && PCI && SPARC64
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer device for the Sun XVR-500 and similar
-	  graphics cards based upon the 3DLABS Wildcat chipset.  The driver
-	  only works on sparc64 systems where the system firwmare has
-	  mostly initialized the card already.  It is treated as a
-	  completely dumb framebuffer device.
-
-config FB_XVR2500
-	bool "Sun XVR-2500 3DLABS Wildcat support"
-	depends on (FB = y) && PCI && SPARC64
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer device for the Sun XVR-2500 and similar
-	  graphics cards based upon the 3DLABS Wildcat chipset.  The driver
-	  only works on sparc64 systems where the system firwmare has
-	  mostly initialized the card already.  It is treated as a
-	  completely dumb framebuffer device.
-
-config FB_PCI
-	bool "PCI framebuffers"
-	depends on (FB = y) && PCI && SPARC
-
-config FB_IGA
-	bool "IGA 168x display support"
-	depends on SPARC32 && FB_PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer device for the INTERGRAPHICS 1680 and
-	  successor frame buffer cards.
-
 config FB_HIT
 	tristate "HD64461 Frame Buffer support"
 	depends on FB && HD64461
@@ -1794,11 +1790,12 @@
 	  adaptor, found on some IBM System P (pSeries) machines.
 
 config FB_PS3
-	bool "PS3 GPU framebuffer driver"
-	depends on (FB = y) && PS3_PS3AV
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
+	tristate "PS3 GPU framebuffer driver"
+	depends on FB && PS3_PS3AV
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
 	---help---
 	  Include support for the virtual frame buffer in the PS3 platform.
 
@@ -1823,6 +1820,10 @@
 	  framebuffer. ML300 carries a 640*480 LCD display on the board,
 	  ML403 uses a standard DB15 VGA connector.
 
+if ARCH_OMAP
+	source "drivers/video/omap/Kconfig"
+endif
+
 config FB_VIRTUAL
 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
 	depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index bd8b052..a562f9d 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -113,6 +113,7 @@
 obj-$(CONFIG_FB_PS3)		  += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
+obj-$(CONFIG_FB_OMAP)             += omap/
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
index ba6fede..8a1b07c 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/arkfb.c
@@ -1055,9 +1055,10 @@
 static void __devexit ark_pci_remove(struct pci_dev *dev)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
-	struct arkfb_info *par = info->par;
 
 	if (info) {
+		struct arkfb_info *par = info->par;
+
 #ifdef CONFIG_MTRR
 		if (par->mtrr_reg >= 0) {
 			mtrr_del(par->mtrr_reg, 0, 0);
diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h
index 90e7df2..685a754 100644
--- a/drivers/video/aty/ati_ids.h
+++ b/drivers/video/aty/ati_ids.h
@@ -204,6 +204,7 @@
 #define PCI_CHIP_RV280_5961		0x5961
 #define PCI_CHIP_RV280_5962		0x5962
 #define PCI_CHIP_RV280_5964		0x5964
+#define PCI_CHIP_RS485_5975		0x5975
 #define PCI_CHIP_RV280_5C61		0x5C61
 #define PCI_CHIP_RV280_5C63		0x5C63
 #define PCI_CHIP_R423_5D57              0x5D57
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 8d3455d..ef330e3 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -541,7 +541,7 @@
 #endif /* CONFIG_FB_ATY_CT */
 
 
-static u32 pseudo_palette[17];
+static u32 pseudo_palette[16];
 
 #ifdef CONFIG_FB_ATY_GX
 static char *aty_gx_ram[8] __devinitdata = {
@@ -2290,15 +2290,6 @@
 	init_waitqueue_head(&par->vblank.wait);
 	spin_lock_init(&par->int_lock);
 
-#ifdef CONFIG_PPC_PMAC
-	/* The Apple iBook1 uses non-standard memory frequencies. We detect it
-	 * and set the frequency manually. */
-	if (machine_is_compatible("PowerBook2,1")) {
-		par->pll_limits.mclk = 70;
-		par->pll_limits.xclk = 53;
-	}
-#endif
-
 #ifdef CONFIG_FB_ATY_GX
 	if (!M64_HAS(INTEGRATED)) {
 		u32 stat0;
@@ -2383,6 +2374,14 @@
 			par->pll_limits.xclk = (par->pll_limits.xclk + 1) >> 1;
 	}
 #endif
+#ifdef CONFIG_PPC_PMAC
+	/* The Apple iBook1 uses non-standard memory frequencies. We detect it
+	 * and set the frequency manually. */
+	if (machine_is_compatible("PowerBook2,1")) {
+		par->pll_limits.mclk = 70;
+		par->pll_limits.xclk = 53;
+	}
+#endif
 
 	/* Allow command line to override clocks. */
 	if (pll)
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 2ce0501..47ca62f 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -153,6 +153,8 @@
 	/* Mobility 9200 (M9+) */
 	CHIP_DEF(PCI_CHIP_RV280_5C61,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
 	CHIP_DEF(PCI_CHIP_RV280_5C63,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/*Mobility Xpress 200 */
+	CHIP_DEF(PCI_CHIP_RS485_5975,	R300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
 	/* 9200 */
 	CHIP_DEF(PCI_CHIP_RV280_5960,	RV280,	CHIP_HAS_CRTC2),
 	CHIP_DEF(PCI_CHIP_RV280_5961,	RV280,	CHIP_HAS_CRTC2),
@@ -2102,7 +2104,9 @@
 }
 
 
-static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid1(struct kobject *kobj,
+				 struct bin_attribute *bin_attr,
+				 char *buf, loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -2113,7 +2117,9 @@
 }
 
 
-static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid2(struct kobject *kobj,
+				 struct bin_attribute *bin_attr,
+				 char *buf, loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -2126,7 +2132,6 @@
 static struct bin_attribute edid1_attr = {
 	.attr   = {
 		.name	= "edid1",
-		.owner	= THIS_MODULE,
 		.mode	= 0444,
 	},
 	.size	= EDID_LENGTH,
@@ -2136,7 +2141,6 @@
 static struct bin_attribute edid2_attr = {
 	.attr   = {
 		.name	= "edid2",
-		.owner	= THIS_MODULE,
 		.mode	= 0444,
 	},
 	.size	= EDID_LENGTH,
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 7ebffcd..7c922c7 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -301,7 +301,7 @@
 	void __iomem		*bios_seg;
 	int			fp_bios_start;
 
-	u32			pseudo_palette[17];
+	u32			pseudo_palette[16];
 	struct { u8 red, green, blue, pad; }
 				palette[256];
 
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index c65e81f..7e06223 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -172,7 +172,7 @@
 
 #define DECLARE_ATTR(_name,_mode,_show,_store)			\
 {							 	\
-	.attr	= { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
+	.attr	= { .name = __stringify(_name), .mode = _mode }, \
 	.show	= _show,					\
 	.store	= _store,					\
 }
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 6ef8f0a..648b53c 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -157,7 +157,7 @@
 
 #define DECLARE_ATTR(_name,_mode,_show,_store)			\
 {							 	\
-	.attr	= { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
+	.attr	= { .name = __stringify(_name), .mode = _mode }, \
 	.show	= _show,					\
 	.store	= _store,					\
 }
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index af313bf1..f48e8c5 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -292,7 +292,7 @@
 		write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
 }
 
-static struct fb_fix_screeninfo chipsfb_fix __initdata = {
+static struct fb_fix_screeninfo chipsfb_fix __devinitdata = {
 	.id =		"C&T 65550",
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_PSEUDOCOLOR,
@@ -309,7 +309,7 @@
 	.smem_len =	0x100000,	/* 1MB */
 };
 
-static struct fb_var_screeninfo chipsfb_var __initdata = {
+static struct fb_var_screeninfo chipsfb_var __devinitdata = {
 	.xres = 800,
 	.yres = 600,
 	.xres_virtual = 800,
@@ -330,7 +330,7 @@
 	.vsync_len = 8,
 };
 
-static void __init init_chips(struct fb_info *p, unsigned long addr)
+static void __devinit init_chips(struct fb_info *p, unsigned long addr)
 {
 	memset(p->screen_base, 0, 0x100000);
 
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 63b85bf..4964396 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -6,7 +6,7 @@
 
 config VGA_CONSOLE
 	bool "VGA text console" if EMBEDDED || !X86
-	depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH
+	depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BFIN
 	default y
 	help
 	  Saying Y here will allow you to use Linux in text mode through a
@@ -118,6 +118,22 @@
 	help
 	  Low-level framebuffer-based console driver.
 
+config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
+       bool "Map the console to the primary display device"
+       depends on FRAMEBUFFER_CONSOLE
+       default n
+       ---help---
+         If this option is selected, the framebuffer console will
+         automatically select the primary display device (if the architecture
+	 supports this feature).  Otherwise, the framebuffer console will
+         always select the first framebuffer driver that is loaded. The latter
+         is the default behavior.
+
+	 You can always override the automatic selection of the primary device
+	 by using the fbcon=map: boot option.
+
+	 If unsure, select n.
+
 config FRAMEBUFFER_CONSOLE_ROTATION
        bool "Framebuffer Console Rotation"
        depends on FRAMEBUFFER_CONSOLE
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index 9b26dda..ac46cc3 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -47,7 +47,7 @@
 quiet_cmd_conmakehash = CNMKHSH $@
       cmd_conmakehash = scripts/conmakehash $< | \
 		sed -e '/\#include <[^>]*>/p' -e 's/types/init/' \
-		-e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > $@
+		-e 's/dfont\(_uni.*\]\)/promfont\1 /' > $@
 
 $(obj)/promcon_tbl.c: $(src)/prom.uni
 	$(call cmd,conmakehash)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 73813c6..decfdc8 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -75,6 +75,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/crc32.h> /* For counting font checksums */
+#include <asm/fb.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -125,6 +126,8 @@
 static int last_fb_vc = MAX_NR_CONSOLES - 1;
 static int fbcon_is_default = 1; 
 static int fbcon_has_exited;
+static int primary_device = -1;
+static int map_override;
 
 /* font data */
 static char fontname[40];
@@ -152,6 +155,7 @@
 #define DEFAULT_CURSOR_BLINK_RATE	(20)
 
 static int vbl_cursor_cnt;
+static int fbcon_cursor_noblink;
 
 #define divides(a, b)	((!(a) || (b)%(a)) ? 0 : 1)
 
@@ -188,16 +192,14 @@
 static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx,
 			    int dy, int dx, int height, int width, u_int y_break);
 static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
-			   struct vc_data *vc);
-static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
-			      int unit);
+			   int unit);
 static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
 			      int line, int count, int dy);
 static void fbcon_modechanged(struct fb_info *info);
 static void fbcon_set_all_vcs(struct fb_info *info);
 static void fbcon_start(void);
 static void fbcon_exit(void);
-static struct class_device *fbcon_class_device;
+static struct device *fbcon_device;
 
 #ifdef CONFIG_MAC
 /*
@@ -441,7 +443,8 @@
 	struct fbcon_ops *ops = info->fbcon_par;
 
 	if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
-	    !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
+	    !(ops->flags & FBCON_FLAGS_CURSOR_TIMER) &&
+	    !fbcon_cursor_noblink) {
 		if (!info->queue.func)
 			INIT_WORK(&info->queue, fb_flashcursor);
 
@@ -495,13 +498,17 @@
 		
 		if (!strncmp(options, "map:", 4)) {
 			options += 4;
-			if (*options)
+			if (*options) {
 				for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
 					if (!options[j])
 						j = 0;
 					con2fb_map_boot[i] =
 						(options[j++]-'0') % FB_MAX;
 				}
+
+				map_override = 1;
+			}
+
 			return 1;
 		}
 
@@ -736,7 +743,9 @@
 
 	if (!err) {
 		info->fbcon_par = ops;
-		set_blitting_type(vc, info);
+
+		if (vc)
+			set_blitting_type(vc, info);
 	}
 
 	if (err) {
@@ -798,11 +807,7 @@
 
 	ops->flags |= FBCON_FLAGS_INIT;
 	ops->graphics = 0;
-
-	if (vc)
-		fbcon_set_disp(info, &info->var, vc);
-	else
-		fbcon_preset_disp(info, &info->var, unit);
+	fbcon_set_disp(info, &info->var, unit);
 
 	if (show_logo) {
 		struct vc_data *fg_vc = vc_cons[fg_console].d;
@@ -1107,6 +1112,9 @@
 	if (var_to_display(p, &info->var, info))
 		return;
 
+	if (!info->fbcon_par)
+		con2fb_acquire_newinfo(vc, info, vc->vc_num, -1);
+
 	/* If we are not the first console on this
 	   fb, copy the font from that console */
 	t = &fb_display[fg_console];
@@ -1349,6 +1357,11 @@
 	if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
 		return;
 
+	if (vc->vc_cursor_type & 0x10)
+		fbcon_del_cursor_timer(info);
+	else
+		fbcon_add_cursor_timer(info);
+
 	ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
 	if (mode & CM_SOFTBACK) {
 		mode &= ~CM_SOFTBACK;
@@ -1368,36 +1381,29 @@
 static int scrollback_max = 0;
 static int scrollback_current = 0;
 
-/*
- * If no vc is existent yet, just set struct display
- */
-static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
-			      int unit)
-{
-	struct display *p = &fb_display[unit];
-	struct display *t = &fb_display[fg_console];
-
-	if (var_to_display(p, var, info))
-		return;
-
-	p->fontdata = t->fontdata;
-	p->userfont = t->userfont;
-	if (p->userfont)
-		REFCOUNT(p->fontdata)++;
-}
-
 static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
-			   struct vc_data *vc)
+			   int unit)
 {
-	struct display *p = &fb_display[vc->vc_num], *t;
-	struct vc_data **default_mode = vc->vc_display_fg;
-	struct vc_data *svc = *default_mode;
+	struct display *p, *t;
+	struct vc_data **default_mode, *vc;
+	struct vc_data *svc;
 	struct fbcon_ops *ops = info->fbcon_par;
 	int rows, cols, charcnt = 256;
 
+	p = &fb_display[unit];
+
 	if (var_to_display(p, var, info))
 		return;
+
+	vc = vc_cons[unit].d;
+
+	if (!vc)
+		return;
+
+	default_mode = vc->vc_display_fg;
+	svc = *default_mode;
 	t = &fb_display[svc->vc_num];
+
 	if (!vc->vc_font.data) {
 		vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
 		vc->vc_font.width = (*default_mode)->vc_font.width;
@@ -1704,6 +1710,56 @@
 	}
 }
 
+static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
+			struct display *p, int line, int count, int ycount)
+{
+	int offset = ycount * vc->vc_cols;
+	unsigned short *d = (unsigned short *)
+	    (vc->vc_origin + vc->vc_size_row * line);
+	unsigned short *s = d + offset;
+	struct fbcon_ops *ops = info->fbcon_par;
+
+	while (count--) {
+		unsigned short *start = s;
+		unsigned short *le = advance_row(s, 1);
+		unsigned short c;
+		int x = 0;
+
+		do {
+			c = scr_readw(s);
+
+			if (c == scr_readw(d)) {
+				if (s > start) {
+					ops->bmove(vc, info, line + ycount, x,
+						   line, x, 1, s-start);
+					x += s - start + 1;
+					start = s + 1;
+				} else {
+					x++;
+					start++;
+				}
+			}
+
+			scr_writew(c, d);
+			console_conditional_schedule();
+			s++;
+			d++;
+		} while (s < le);
+		if (s > start)
+			ops->bmove(vc, info, line + ycount, x, line, x, 1,
+				   s-start);
+		console_conditional_schedule();
+		if (ycount > 0)
+			line++;
+		else {
+			line--;
+			/* NOTE: We subtract two lines from these pointers */
+			s -= vc->vc_size_row;
+			d -= vc->vc_size_row;
+		}
+	}
+}
+
 static void fbcon_redraw(struct vc_data *vc, struct display *p,
 			 int line, int count, int offset)
 {
@@ -1789,7 +1845,6 @@
 {
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
-	struct fbcon_ops *ops = info->fbcon_par;
 	int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
 
 	if (fbcon_is_inactive(vc, info))
@@ -1813,10 +1868,15 @@
 			goto redraw_up;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
-			ops->bmove(vc, info, t + count, 0, t, 0,
-				    b - t - count, vc->vc_cols);
-			ops->clear(vc, info, b - count, 0, count,
-				  vc->vc_cols);
+			fbcon_redraw_blit(vc, info, p, t, b - t - count,
+				     count);
+			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+			scr_memsetw((unsigned short *) (vc->vc_origin +
+							vc->vc_size_row *
+							(b - count)),
+				    vc->vc_video_erase_char,
+				    vc->vc_size_row * count);
+			return 1;
 			break;
 
 		case SCROLL_WRAP_MOVE:
@@ -1899,9 +1959,15 @@
 			goto redraw_down;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
-			ops->bmove(vc, info, t, 0, t + count, 0,
-				    b - t - count, vc->vc_cols);
-			ops->clear(vc, info, t, 0, count, vc->vc_cols);
+			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
+				     -count);
+			fbcon_clear(vc, t, 0, count, vc->vc_cols);
+			scr_memsetw((unsigned short *) (vc->vc_origin +
+							vc->vc_size_row *
+							t),
+				    vc->vc_video_erase_char,
+				    vc->vc_size_row * count);
+			return 1;
 			break;
 
 		case SCROLL_WRAP_MOVE:
@@ -2937,9 +3003,48 @@
 	return found;
 }
 
-static int fbcon_fb_unregistered(int idx)
+#ifdef CONFIG_VT_HW_CONSOLE_BINDING
+static int fbcon_unbind(void)
 {
-	int i;
+	int ret;
+
+	ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
+				fbcon_is_default);
+	return ret;
+}
+#else
+static inline int fbcon_unbind(void)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
+
+static int fbcon_fb_unbind(int idx)
+{
+	int i, new_idx = -1, ret = 0;
+
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
+		if (con2fb_map[i] != idx &&
+		    con2fb_map[i] != -1) {
+			new_idx = i;
+			break;
+		}
+	}
+
+	if (new_idx != -1) {
+		for (i = first_fb_vc; i <= last_fb_vc; i++) {
+			if (con2fb_map[i] == idx)
+				set_con2fb_map(i, new_idx, 0);
+		}
+	} else
+		ret = fbcon_unbind();
+
+	return ret;
+}
+
+static int fbcon_fb_unregistered(struct fb_info *info)
+{
+	int i, idx = info->node;
 
 	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (con2fb_map[i] == idx)
@@ -2967,12 +3072,48 @@
 	if (!num_registered_fb)
 		unregister_con_driver(&fb_con);
 
+
+	if (primary_device == idx)
+		primary_device = -1;
+
 	return 0;
 }
 
-static int fbcon_fb_registered(int idx)
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
+static void fbcon_select_primary(struct fb_info *info)
 {
-	int ret = 0, i;
+	if (!map_override && primary_device == -1 &&
+	    fb_is_primary_device(info)) {
+		int i;
+
+		printk(KERN_INFO "fbcon: %s (fb%i) is primary device\n",
+		       info->fix.id, info->node);
+		primary_device = info->node;
+
+		for (i = first_fb_vc; i <= last_fb_vc; i++)
+			con2fb_map_boot[i] = primary_device;
+
+		if (con_is_bound(&fb_con)) {
+			printk(KERN_INFO "fbcon: Remapping primary device, "
+			       "fb%i, to tty %i-%i\n", info->node,
+			       first_fb_vc + 1, last_fb_vc + 1);
+			info_idx = primary_device;
+		}
+	}
+
+}
+#else
+static inline void fbcon_select_primary(struct fb_info *info)
+{
+	return;
+}
+#endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
+
+static int fbcon_fb_registered(struct fb_info *info)
+{
+	int ret = 0, i, idx = info->node;
+
+	fbcon_select_primary(info);
 
 	if (info_idx == -1) {
 		for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -2986,8 +3127,7 @@
 			ret = fbcon_takeover(1);
 	} else {
 		for (i = first_fb_vc; i <= last_fb_vc; i++) {
-			if (con2fb_map_boot[i] == idx &&
-			    con2fb_map[i] == -1)
+			if (con2fb_map_boot[i] == idx)
 				set_con2fb_map(i, idx, 0);
 		}
 	}
@@ -3034,12 +3174,7 @@
 		mode = fb_find_nearest_mode(fb_display[i].mode,
 					    &info->modelist);
 		fb_videomode_to_var(&var, mode);
-
-		if (vc)
-			fbcon_set_disp(info, &var, vc);
-		else
-			fbcon_preset_disp(info, &var, i);
-
+		fbcon_set_disp(info, &var, vc->vc_num);
 	}
 }
 
@@ -3114,11 +3249,14 @@
 		mode = event->data;
 		ret = fbcon_mode_deleted(info, mode);
 		break;
+	case FB_EVENT_FB_UNBIND:
+		ret = fbcon_fb_unbind(info->node);
+		break;
 	case FB_EVENT_FB_REGISTERED:
-		ret = fbcon_fb_registered(info->node);
+		ret = fbcon_fb_registered(info);
 		break;
 	case FB_EVENT_FB_UNREGISTERED:
-		ret = fbcon_fb_unregistered(info->node);
+		ret = fbcon_fb_unregistered(info);
 		break;
 	case FB_EVENT_SET_CONSOLE_MAP:
 		con2fb = event->data;
@@ -3179,8 +3317,9 @@
 	.notifier_call	= fbcon_event_notify,
 };
 
-static ssize_t store_rotate(struct class_device *class_device,
-			    const char *buf, size_t count)
+static ssize_t store_rotate(struct device *device,
+			    struct device_attribute *attr, const char *buf,
+			    size_t count)
 {
 	struct fb_info *info;
 	int rotate, idx;
@@ -3203,8 +3342,9 @@
 	return count;
 }
 
-static ssize_t store_rotate_all(struct class_device *class_device,
-				const char *buf, size_t count)
+static ssize_t store_rotate_all(struct device *device,
+				struct device_attribute *attr,const char *buf,
+				size_t count)
 {
 	struct fb_info *info;
 	int rotate, idx;
@@ -3227,7 +3367,8 @@
 	return count;
 }
 
-static ssize_t show_rotate(struct class_device *class_device, char *buf)
+static ssize_t show_rotate(struct device *device,
+			   struct device_attribute *attr,char *buf)
 {
 	struct fb_info *info;
 	int rotate = 0, idx;
@@ -3248,20 +3389,86 @@
 	return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
 }
 
-static struct class_device_attribute class_device_attrs[] = {
+static ssize_t show_cursor_blink(struct device *device,
+				 struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info;
+	struct fbcon_ops *ops;
+	int idx, blink = -1;
+
+	if (fbcon_has_exited)
+		return 0;
+
+	acquire_console_sem();
+	idx = con2fb_map[fg_console];
+
+	if (idx == -1 || registered_fb[idx] == NULL)
+		goto err;
+
+	info = registered_fb[idx];
+	ops = info->fbcon_par;
+
+	if (!ops)
+		goto err;
+
+	blink = (ops->flags & FBCON_FLAGS_CURSOR_TIMER) ? 1 : 0;
+err:
+	release_console_sem();
+	return snprintf(buf, PAGE_SIZE, "%d\n", blink);
+}
+
+static ssize_t store_cursor_blink(struct device *device,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct fb_info *info;
+	int blink, idx;
+	char **last = NULL;
+
+	if (fbcon_has_exited)
+		return count;
+
+	acquire_console_sem();
+	idx = con2fb_map[fg_console];
+
+	if (idx == -1 || registered_fb[idx] == NULL)
+		goto err;
+
+	info = registered_fb[idx];
+
+	if (!info->fbcon_par)
+		goto err;
+
+	blink = simple_strtoul(buf, last, 0);
+
+	if (blink) {
+		fbcon_cursor_noblink = 0;
+		fbcon_add_cursor_timer(info);
+	} else {
+		fbcon_cursor_noblink = 1;
+		fbcon_del_cursor_timer(info);
+	}
+
+err:
+	release_console_sem();
+	return count;
+}
+
+static struct device_attribute device_attrs[] = {
 	__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
 	__ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all),
+	__ATTR(cursor_blink, S_IRUGO|S_IWUSR, show_cursor_blink,
+	       store_cursor_blink),
 };
 
-static int fbcon_init_class_device(void)
+static int fbcon_init_device(void)
 {
 	int i, error = 0;
 
 	fbcon_has_sysfs = 1;
 
-	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
-		error = class_device_create_file(fbcon_class_device,
-						 &class_device_attrs[i]);
+	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+		error = device_create_file(fbcon_device, &device_attrs[i]);
 
 		if (error)
 			break;
@@ -3269,8 +3476,7 @@
 
 	if (error) {
 		while (--i >= 0)
-			class_device_remove_file(fbcon_class_device,
-						 &class_device_attrs[i]);
+			device_remove_file(fbcon_device, &device_attrs[i]);
 
 		fbcon_has_sysfs = 0;
 	}
@@ -3356,16 +3562,15 @@
 
 	acquire_console_sem();
 	fb_register_client(&fbcon_event_notifier);
-	fbcon_class_device =
-	    class_device_create(fb_class, NULL, MKDEV(0, 0), NULL, "fbcon");
+	fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon");
 
-	if (IS_ERR(fbcon_class_device)) {
-		printk(KERN_WARNING "Unable to create class_device "
+	if (IS_ERR(fbcon_device)) {
+		printk(KERN_WARNING "Unable to create device "
 		       "for fbcon; errno = %ld\n",
-		       PTR_ERR(fbcon_class_device));
-		fbcon_class_device = NULL;
+		       PTR_ERR(fbcon_device));
+		fbcon_device = NULL;
 	} else
-		fbcon_init_class_device();
+		fbcon_init_device();
 
 	for (i = 0; i < MAX_NR_CONSOLES; i++)
 		con2fb_map[i] = -1;
@@ -3379,14 +3584,13 @@
 
 #ifdef MODULE
 
-static void __exit fbcon_deinit_class_device(void)
+static void __exit fbcon_deinit_device(void)
 {
 	int i;
 
 	if (fbcon_has_sysfs) {
-		for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
-			class_device_remove_file(fbcon_class_device,
-						 &class_device_attrs[i]);
+		for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+			device_remove_file(fbcon_device, &device_attrs[i]);
 
 		fbcon_has_sysfs = 0;
 	}
@@ -3396,8 +3600,8 @@
 {
 	acquire_console_sem();
 	fb_unregister_client(&fbcon_event_notifier);
-	fbcon_deinit_class_device();
-	class_device_destroy(fb_class, MKDEV(0, 0));
+	fbcon_deinit_device();
+	device_destroy(fb_class, MKDEV(0, 0));
 	fbcon_exit();
 	release_console_sem();
 	unregister_con_driver(&fb_con);
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 71f24e0..8e6ef4b 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -176,7 +176,6 @@
 #endif
 extern void fbcon_set_bitops(struct fbcon_ops *ops);
 extern int  soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
-extern struct class *fb_class;
 
 #define FBCON_ATTRIBUTE_UNDERLINE 1
 #define FBCON_ATTRIBUTE_REVERSE   2
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 717b360..870017d4 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -240,7 +240,7 @@
 	flush_icache_range(from, from+len);
 }
 
-void __init
+void __devinit
 sti_rom_copy(unsigned long base, unsigned long count, void *dest)
 {
 	unsigned long dest_len = count;
@@ -269,7 +269,7 @@
 static char default_sti_path[21] __read_mostly;
 
 #ifndef MODULE
-static int __init sti_setup(char *str)
+static int __devinit sti_setup(char *str)
 {
 	if (str)
 		strlcpy (default_sti_path, str, sizeof (default_sti_path));
@@ -288,12 +288,12 @@
 
 
 
-static char __initdata	*font_name[MAX_STI_ROMS] = { "VGA8x16", };
-static int __initdata	font_index[MAX_STI_ROMS], 
-			font_height[MAX_STI_ROMS],
-			font_width[MAX_STI_ROMS];
+static char __devinitdata	*font_name[MAX_STI_ROMS] = { "VGA8x16", };
+static int __devinitdata	font_index[MAX_STI_ROMS],
+				font_height[MAX_STI_ROMS],
+				font_width[MAX_STI_ROMS];
 #ifndef MODULE
-static int __init sti_font_setup(char *str)
+static int __devinit sti_font_setup(char *str)
 {
 	char *x;
 	int i = 0;
@@ -346,7 +346,7 @@
 
 
 	
-static void __init
+static void __devinit
 sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request)
 {
 	struct sti_glob_cfg_ext *cfg;
@@ -386,7 +386,7 @@
 		cfg->sti_mem_addr, sti_mem_request));
 }
 
-static void __init
+static void __devinit
 sti_dump_outptr(struct sti_struct *sti)
 {
 	DPRINTK((KERN_INFO
@@ -400,7 +400,7 @@
 		 sti->outptr.attributes));
 }
 
-static int __init
+static int __devinit
 sti_init_glob_cfg(struct sti_struct *sti,
 	    unsigned long rom_address, unsigned long hpa)
 {
@@ -482,7 +482,7 @@
 }
 
 #ifdef CONFIG_FB
-struct sti_cooked_font * __init
+struct sti_cooked_font * __devinit
 sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
 	const struct font_desc *fbfont;
@@ -538,14 +538,14 @@
 	return cooked_font;
 }
 #else
-struct sti_cooked_font * __init
+struct sti_cooked_font * __devinit
 sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
 	return NULL;
 }
 #endif
 
-struct sti_cooked_font * __init
+struct sti_cooked_font * __devinit
 sti_select_font(struct sti_cooked_rom *rom,
 	    int (*search_font_fnc) (struct sti_cooked_rom *,int,int) )
 {
@@ -572,7 +572,7 @@
 }
 
 
-static void __init 
+static void __devinit
 sti_dump_rom(struct sti_rom *rom)
 {
 	printk(KERN_INFO "    id %04x-%04x, conforms to spec rev. %d.%02x\n",
@@ -590,7 +590,7 @@
 }
 
 
-static int __init 
+static int __devinit
 sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
 			struct sti_rom *raw_rom)
 {
@@ -625,7 +625,7 @@
 }
 
 
-static int __init 
+static int __devinit
 sti_search_font(struct sti_cooked_rom *rom, int height, int width)
 {
 	struct sti_cooked_font *font;
@@ -642,7 +642,7 @@
 #define BMODE_RELOCATE(offset)		offset = (offset) / 4;
 #define BMODE_LAST_ADDR_OFFS		0x50
 
-static void * __init
+static void * __devinit
 sti_bmode_font_raw(struct sti_cooked_font *f)
 {
 	unsigned char *n, *p, *q;
@@ -660,7 +660,7 @@
 	return n + 3;
 }
 
-static void __init
+static void __devinit
 sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest)
 {
 	unsigned long dest_len = count;
@@ -675,7 +675,7 @@
 	sti_flush(dest_start, dest_len);
 }
 
-static struct sti_rom * __init
+static struct sti_rom * __devinit
 sti_get_bmode_rom (unsigned long address)
 {
 	struct sti_rom *raw;
@@ -711,7 +711,7 @@
 	return raw;
 }
 
-struct sti_rom * __init
+struct sti_rom * __devinit
 sti_get_wmode_rom (unsigned long address)
 {
 	struct sti_rom *raw;
@@ -727,7 +727,7 @@
 	return raw;
 }
 
-int __init
+int __devinit
 sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
 {
 	struct sti_cooked_rom *cooked;
@@ -783,7 +783,7 @@
 	return 0;
 }
 
-static struct sti_struct * __init
+static struct sti_struct * __devinit
 sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd)
 {
 	struct sti_struct *sti;
@@ -898,7 +898,7 @@
 	return NULL;
 }
 
-static void __init sticore_check_for_default_sti(struct sti_struct *sti, char *path)
+static void __devinit sticore_check_for_default_sti(struct sti_struct *sti, char *path)
 {
 	if (strcmp (path, default_sti_path) == 0)
 		default_sti = sti;
@@ -909,7 +909,7 @@
  * in the additional address field addr[1] while on
  * older Systems the PDC stores it in page0->proc_sti 
  */
-static int __init sticore_pa_init(struct parisc_device *dev)
+static int __devinit sticore_pa_init(struct parisc_device *dev)
 {
 	char pa_path[21];
 	struct sti_struct *sti = NULL;
@@ -1015,7 +1015,7 @@
 
 static int sticore_initialized __read_mostly;
 
-static void __init sti_init_roms(void)
+static void __devinit sti_init_roms(void)
 {
 	if (sticore_initialized)
 		return;
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 8b76273..b0be7ea 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -94,7 +94,7 @@
 struct fb_info_control {
 	struct fb_info		info;
 	struct fb_par_control	par;
-	u32			pseudo_palette[17];
+	u32			pseudo_palette[16];
 		
 	struct cmap_regs	__iomem *cmap_regs;
 	unsigned long		cmap_regs_phys;
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 94a66c2..e23324d 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -1068,15 +1068,18 @@
 		out8(0x3C9, green >> 10);
 		out8(0x3C9, blue >> 10);
 
-	} else if (bpp == 16)	// RGB 565
-		((u32 *) info->pseudo_palette)[regno] =
-		    (red & 0xF800) |
-		    ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
-	else if (bpp == 32)	// ARGB 8888
-		((u32 *) info->pseudo_palette)[regno] =
-		    ((transp & 0xFF00) << 16) |
-		    ((red & 0xFF00) << 8) |
-		    ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
+	} else if (regno < 16) {
+		if (bpp == 16)	// RGB 565
+			((u32 *) info->pseudo_palette)[regno] =
+				(red & 0xF800) |
+				((green & 0xFC00) >> 5) |
+				((blue & 0xF800) >> 11);
+		else if (bpp == 32)	// ARGB 8888
+			((u32 *) info->pseudo_palette)[regno] =
+				((transp & 0xFF00) << 16) |
+				((red & 0xFF00) << 8) |
+				((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
+	}
 
 	return 0;
 }
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index ca2c54c..33be46c 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -63,23 +63,12 @@
 
 struct epson1355_par {
 	unsigned long reg_addr;
+	u32 pseudo_palette[16];
 };
 
 /* ------------------------------------------------------------------------- */
 
-#ifdef CONFIG_SUPERH
-
-static inline u8 epson1355_read_reg(int index)
-{
-	return ctrl_inb(par.reg_addr + index);
-}
-
-static inline void epson1355_write_reg(u8 data, int index)
-{
-	ctrl_outb(data, par.reg_addr + index);
-}
-
-#elif defined(CONFIG_ARM)
+#if defined(CONFIG_ARM)
 
 # ifdef CONFIG_ARCH_CEIVA
 #  include <asm/arch/hardware.h>
@@ -289,7 +278,7 @@
 	struct epson1355_par *par = info->par;
 
 	switch (blank_mode) {
-	case FB_BLANK_UNBLANKING:
+	case FB_BLANK_UNBLANK:
 	case FB_BLANK_NORMAL:
 		lcd_enable(par, 1);
 		backlight_enable(1);
@@ -635,7 +624,7 @@
 		goto bail;
 	}
 
-	info = framebuffer_alloc(sizeof(struct epson1355_par) + sizeof(u32) * 256, &dev->dev);
+	info = framebuffer_alloc(sizeof(struct epson1355_par), &dev->dev);
 	if (!info) {
 		rc = -ENOMEM;
 		goto bail;
@@ -648,7 +637,7 @@
 		rc = -ENOMEM;
 		goto bail;
 	}
-	info->pseudo_palette = (void *)(default_par + 1);
+	info->pseudo_palette = default_par->pseudo_palette;
 
 	info->screen_base = ioremap(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
 	if (!info->screen_base) {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 38c2e25..215ac57 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -33,18 +33,11 @@
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/efi.h>
-
-#if defined(__mc68000__) || defined(CONFIG_APUS)
-#include <asm/setup.h>
-#endif
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
 #include <linux/fb.h>
 
+#include <asm/fb.h>
+
+
     /*
      *  Frame buffer device initialization and setup routines
      */
@@ -411,10 +404,146 @@
 	}
 }
 
+static int fb_show_logo_line(struct fb_info *info, int rotate,
+			     const struct linux_logo *logo, int y,
+			     unsigned int n)
+{
+	u32 *palette = NULL, *saved_pseudo_palette = NULL;
+	unsigned char *logo_new = NULL, *logo_rotate = NULL;
+	struct fb_image image;
+
+	/* Return if the frame buffer is not mapped or suspended */
+	if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
+	    info->flags & FBINFO_MODULE)
+		return 0;
+
+	image.depth = 8;
+	image.data = logo->data;
+
+	if (fb_logo.needs_cmapreset)
+		fb_set_logocmap(info, logo);
+
+	if (fb_logo.needs_truepalette ||
+	    fb_logo.needs_directpalette) {
+		palette = kmalloc(256 * 4, GFP_KERNEL);
+		if (palette == NULL)
+			return 0;
+
+		if (fb_logo.needs_truepalette)
+			fb_set_logo_truepalette(info, logo, palette);
+		else
+			fb_set_logo_directpalette(info, logo, palette);
+
+		saved_pseudo_palette = info->pseudo_palette;
+		info->pseudo_palette = palette;
+	}
+
+	if (fb_logo.depth <= 4) {
+		logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
+		if (logo_new == NULL) {
+			kfree(palette);
+			if (saved_pseudo_palette)
+				info->pseudo_palette = saved_pseudo_palette;
+			return 0;
+		}
+		image.data = logo_new;
+		fb_set_logo(info, logo, logo_new, fb_logo.depth);
+	}
+
+	image.dx = 0;
+	image.dy = y;
+	image.width = logo->width;
+	image.height = logo->height;
+
+	if (rotate) {
+		logo_rotate = kmalloc(logo->width *
+				      logo->height, GFP_KERNEL);
+		if (logo_rotate)
+			fb_rotate_logo(info, logo_rotate, &image, rotate);
+	}
+
+	fb_do_show_logo(info, &image, rotate, n);
+
+	kfree(palette);
+	if (saved_pseudo_palette != NULL)
+		info->pseudo_palette = saved_pseudo_palette;
+	kfree(logo_new);
+	kfree(logo_rotate);
+	return logo->height;
+}
+
+
+#ifdef CONFIG_FB_LOGO_EXTRA
+
+#define FB_LOGO_EX_NUM_MAX 10
+static struct logo_data_extra {
+	const struct linux_logo *logo;
+	unsigned int n;
+} fb_logo_ex[FB_LOGO_EX_NUM_MAX];
+static unsigned int fb_logo_ex_num;
+
+void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
+{
+	if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
+		return;
+
+	fb_logo_ex[fb_logo_ex_num].logo = logo;
+	fb_logo_ex[fb_logo_ex_num].n = n;
+	fb_logo_ex_num++;
+}
+
+static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
+				  unsigned int yres)
+{
+	unsigned int i;
+
+	/* FIXME: logo_ex supports only truecolor fb. */
+	if (info->fix.visual != FB_VISUAL_TRUECOLOR)
+		fb_logo_ex_num = 0;
+
+	for (i = 0; i < fb_logo_ex_num; i++) {
+		height += fb_logo_ex[i].logo->height;
+		if (height > yres) {
+			height -= fb_logo_ex[i].logo->height;
+			fb_logo_ex_num = i;
+			break;
+		}
+	}
+	return height;
+}
+
+static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
+{
+	unsigned int i;
+
+	for (i = 0; i < fb_logo_ex_num; i++)
+		y += fb_show_logo_line(info, rotate,
+				       fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
+
+	return y;
+}
+
+#else /* !CONFIG_FB_LOGO_EXTRA */
+
+static inline int fb_prepare_extra_logos(struct fb_info *info,
+					 unsigned int height,
+					 unsigned int yres)
+{
+	return height;
+}
+
+static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
+{
+	return y;
+}
+
+#endif /* CONFIG_FB_LOGO_EXTRA */
+
+
 int fb_prepare_logo(struct fb_info *info, int rotate)
 {
 	int depth = fb_get_color_depth(&info->var, &info->fix);
-	int yres;
+	unsigned int yres;
 
 	memset(&fb_logo, 0, sizeof(struct logo_data));
 
@@ -456,7 +585,7 @@
 	if (!fb_logo.logo) {
 		return 0;
 	}
-	
+
 	if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
 		yres = info->var.yres;
 	else
@@ -473,75 +602,20 @@
 	else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
 		fb_logo.depth = 4;
 	else
-		fb_logo.depth = 1;		
-	return fb_logo.logo->height;
+		fb_logo.depth = 1;
+
+	return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
 }
 
 int fb_show_logo(struct fb_info *info, int rotate)
 {
-	u32 *palette = NULL, *saved_pseudo_palette = NULL;
-	unsigned char *logo_new = NULL, *logo_rotate = NULL;
-	struct fb_image image;
+	int y;
 
-	/* Return if the frame buffer is not mapped or suspended */
-	if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING ||
-	    info->flags & FBINFO_MODULE)
-		return 0;
+	y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
+			      num_online_cpus());
+	y = fb_show_extra_logos(info, y, rotate);
 
-	image.depth = 8;
-	image.data = fb_logo.logo->data;
-
-	if (fb_logo.needs_cmapreset)
-		fb_set_logocmap(info, fb_logo.logo);
-
-	if (fb_logo.needs_truepalette || 
-	    fb_logo.needs_directpalette) {
-		palette = kmalloc(256 * 4, GFP_KERNEL);
-		if (palette == NULL)
-			return 0;
-
-		if (fb_logo.needs_truepalette)
-			fb_set_logo_truepalette(info, fb_logo.logo, palette);
-		else
-			fb_set_logo_directpalette(info, fb_logo.logo, palette);
-
-		saved_pseudo_palette = info->pseudo_palette;
-		info->pseudo_palette = palette;
-	}
-
-	if (fb_logo.depth <= 4) {
-		logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height, 
-				   GFP_KERNEL);
-		if (logo_new == NULL) {
-			kfree(palette);
-			if (saved_pseudo_palette)
-				info->pseudo_palette = saved_pseudo_palette;
-			return 0;
-		}
-		image.data = logo_new;
-		fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
-	}
-
-	image.dx = 0;
-	image.dy = 0;
-	image.width = fb_logo.logo->width;
-	image.height = fb_logo.logo->height;
-
-	if (rotate) {
-		logo_rotate = kmalloc(fb_logo.logo->width *
-				      fb_logo.logo->height, GFP_KERNEL);
-		if (logo_rotate)
-			fb_rotate_logo(info, logo_rotate, &image, rotate);
-	}
-
-	fb_do_show_logo(info, &image, rotate, num_online_cpus());
-
-	kfree(palette);
-	if (saved_pseudo_palette != NULL)
-		info->pseudo_palette = saved_pseudo_palette;
-	kfree(logo_new);
-	kfree(logo_rotate);
-	return fb_logo.logo->height;
+	return y;
 }
 #else
 int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
@@ -1155,17 +1229,15 @@
 }
 #endif
 
-static int 
+static int
 fb_mmap(struct file *file, struct vm_area_struct * vma)
 {
 	int fbidx = iminor(file->f_path.dentry->d_inode);
 	struct fb_info *info = registered_fb[fbidx];
 	struct fb_ops *fb = info->fbops;
 	unsigned long off;
-#if !defined(__sparc__) || defined(__sparc_v9__)
 	unsigned long start;
 	u32 len;
-#endif
 
 	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
 		return -EINVAL;
@@ -1180,12 +1252,6 @@
 		return res;
 	}
 
-#if defined(__sparc__) && !defined(__sparc_v9__)
-	/* Should never get here, all fb drivers should have their own
-	   mmap routines */
-	return -EINVAL;
-#else
-	/* !sparc32... */
 	lock_kernel();
 
 	/* frame buffer memory */
@@ -1209,50 +1275,11 @@
 	vma->vm_pgoff = off >> PAGE_SHIFT;
 	/* This is an IO map - tell maydump to skip this VMA */
 	vma->vm_flags |= VM_IO | VM_RESERVED;
-#if defined(__mc68000__)
-#if defined(CONFIG_SUN3)
-	pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
-#elif defined(CONFIG_MMU)
-	if (CPU_IS_020_OR_030)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
-	if (CPU_IS_040_OR_060) {
-		pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
-		/* Use no-cache mode, serialized */
-		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
-	}
-#endif
-#elif defined(__powerpc__)
-	vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT,
-						 vma->vm_end - vma->vm_start,
-						 vma->vm_page_prot);
-#elif defined(__alpha__)
-	/* Caching is off in the I/O space quadrant by design.  */
-#elif defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#elif defined(__mips__) || defined(__sparc_v9__)
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#elif defined(__hppa__)
-	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-#elif defined(__arm__) || defined(__sh__) || defined(__m32r__)
-	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-#elif defined(__avr32__)
-	vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
-				      & ~_PAGE_CACHABLE)
-				     | (_PAGE_BUFFER | _PAGE_DIRTY));
-#elif defined(__ia64__)
-	if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
-		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-	else
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#else
-#warning What do we have to do here??
-#endif
+	fb_pgprotect(file, vma, off);
 	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
 			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
 	return 0;
-#endif /* !sparc32 */
 }
 
 static int
@@ -1388,17 +1415,34 @@
  *
  *	Returns negative errno on error, or zero for success.
  *
+ *      This function will also notify the framebuffer console
+ *      to release the driver.
+ *
+ *      This is meant to be called within a driver's module_exit()
+ *      function. If this is called outside module_exit(), ensure
+ *      that the driver implements fb_open() and fb_release() to
+ *      check that no processes are using the device.
  */
 
 int
 unregister_framebuffer(struct fb_info *fb_info)
 {
 	struct fb_event event;
-	int i;
+	int i, ret = 0;
 
 	i = fb_info->node;
-	if (!registered_fb[i])
-		return -EINVAL;
+	if (!registered_fb[i]) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	event.info = fb_info;
+	ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+
+	if (ret) {
+		ret = -EINVAL;
+		goto done;
+	}
 
 	if (fb_info->pixmap.addr &&
 	    (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
@@ -1410,7 +1454,8 @@
 	device_destroy(fb_class, MKDEV(FB_MAJOR, i));
 	event.info = fb_info;
 	fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
-	return 0;
+done:
+	return ret;
 }
 
 /**
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 1d4e835..3f6c98f 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -656,7 +656,7 @@
 {
 	u32 value;
 
-	if (regno >= 256)
+	if (regno >= 16)
 		return 1;
 
 	red >>= 8;
@@ -903,7 +903,7 @@
 struct all_info {
 	struct fb_info info;
 	struct ffb_par par;
-	u32 pseudo_palette[256];
+	u32 pseudo_palette[16];
 };
 
 static int ffb_init_one(struct of_device *op)
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 70ff55b..6c91c61 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -195,13 +195,15 @@
 static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                          u_int transp, struct fb_info *info)
 {
-	if (regno > info->cmap.len)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
+	if (regno < 16) {
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
 
-	((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
+		((u32*)(info->pseudo_palette))[regno] = (red << 16) |
+			(green << 8) | blue;
+	}
+
 	return 0;
 }
 
@@ -237,7 +239,7 @@
 	if (!zorro_request_device(z,"fm2fb"))
 		return -ENXIO;
 
-	info = framebuffer_alloc(256 * sizeof(u32), &z->dev);
+	info = framebuffer_alloc(16 * sizeof(u32), &z->dev);
 	if (!info) {
 		zorro_release_device(z);
 		return -ENOMEM;
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index bf0e60b..b9b572b 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -86,7 +86,7 @@
 
 static int ypan, ywrap;
 
-static uint32_t pseudo_palette[256];
+static uint32_t pseudo_palette[16];
 
 static char *mode_option __initdata = NULL;
 
@@ -854,8 +854,7 @@
 	green >>= 8;
 	blue >>= 8;
 
-	switch (info->var.bits_per_pixel) {
-	case 8:
+	if (info->var.bits_per_pixel <= 8) {
 		/* wait for the color map FIFO to have a free entry */
 		for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
 			udelay(10);
@@ -864,23 +863,25 @@
 			return 1;
 		}
 		gbe->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
-		break;
-	case 15:
-	case 16:
-		red >>= 3;
-		green >>= 3;
-		blue >>= 3;
-		pseudo_palette[regno] =
-			(red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset);
-		break;
-	case 32:
-		pseudo_palette[regno] =
-			(red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset);
-		break;
+	} else if (regno < 16) {
+		switch (info->var.bits_per_pixel) {
+		case 15:
+		case 16:
+			red >>= 3;
+			green >>= 3;
+			blue >>= 3;
+			pseudo_palette[regno] =
+				(red << info->var.red.offset) |
+				(green << info->var.green.offset) |
+				(blue << info->var.blue.offset);
+			break;
+		case 32:
+			pseudo_palette[regno] =
+				(red << info->var.red.offset) |
+				(green << info->var.green.offset) |
+				(blue << info->var.blue.offset);
+			break;
+		}
 	}
 
 	return 0;
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 889e4ea..328ae6c 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -266,7 +266,7 @@
 	struct i810fb_i2c_chan   chan[3];
 	struct mutex		 open_lock;
 	unsigned int		 use_count;
-	u32 pseudo_palette[17];
+	u32 pseudo_palette[16];
 	unsigned long mmio_start_phys;
 	u8 __iomem *mmio_start_virtual;
 	u8 *edid;
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 267c1ff..a125898 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -394,26 +394,18 @@
 
 	/* initialize GPIOs */
 	imx_gpio_mode(PD6_PF_LSCLK);
-	imx_gpio_mode(PD10_PF_SPL_SPR);
 	imx_gpio_mode(PD11_PF_CONTRAST);
 	imx_gpio_mode(PD14_PF_FLM_VSYNC);
 	imx_gpio_mode(PD13_PF_LP_HSYNC);
-	imx_gpio_mode(PD7_PF_REV);
-	imx_gpio_mode(PD8_PF_CLS);
-
-#ifndef CONFIG_MACH_PIMX1
-	/* on PiMX1 used as buffers enable signal
-	 */
-	imx_gpio_mode(PD9_PF_PS);
-#endif
-
-#ifndef CONFIG_MACH_MX1FS2
-	/* on mx1fs2 this pin is used to (de)activate the display, so we need
-	 * it as a normal gpio
-	 */
 	imx_gpio_mode(PD12_PF_ACD_OE);
-#endif
 
+	/* These are only needed for Sharp HR TFT displays */
+	if (fbi->pcr & PCR_SHARP) {
+		imx_gpio_mode(PD7_PF_REV);
+		imx_gpio_mode(PD8_PF_CLS);
+		imx_gpio_mode(PD9_PF_PS);
+		imx_gpio_mode(PD10_PF_SPL_SPR);
+	}
 }
 
 #ifdef CONFIG_PM
@@ -476,7 +468,6 @@
 
 	info->fbops			= &imxfb_ops;
 	info->flags			= FBINFO_FLAG_DEFAULT;
-	info->pseudo_palette		= (fbi + 1);
 
 	fbi->rgb[RGB_16]		= &def_rgb_16;
 	fbi->rgb[RGB_8]			= &def_rgb_8;
@@ -499,6 +490,7 @@
 	info->var.sync			= inf->sync;
 	info->var.grayscale		= inf->cmap_greyscale;
 	fbi->cmap_inverse		= inf->cmap_inverse;
+	fbi->cmap_static		= inf->cmap_static;
 	fbi->pcr			= inf->pcr;
 	fbi->lscr1			= inf->lscr1;
 	fbi->dmacr			= inf->dmacr;
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 80b94c1..6148300 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -302,7 +302,7 @@
 	u32 ring_lockup;
 
 	/* palette */
-	u32 pseudo_palette[17];
+	u32 pseudo_palette[16];
 
 	/* chip info */
 	int pci_chipset;
diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c
index ab5285a..1d3f2080 100644
--- a/drivers/video/kyro/STG4000InitDevice.c
+++ b/drivers/video/kyro/STG4000InitDevice.c
@@ -247,7 +247,6 @@
 	u32 ulCoreClock;
 	u32 tmp;
 	u32 ulChipSpeed;
-	u8 rev;
 
 	STG_WRITE_REG(IntMask, 0xFFFF);
 
@@ -276,9 +275,9 @@
 		      PMX2_SOFTRESET_ROM_RST);
 
 	pci_read_config_word(pDev, PCI_CONFIG_SUBSYS_ID, &sub);
-	pci_read_config_byte(pDev, PCI_REVISION_ID, &rev);
 
-	ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub, (u32)rev);
+	ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub,
+		                         (u32)pDev->revision);
 
 	if (ulChipSpeed == 0)
 		return -EINVAL;
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 9397bce..da219c0 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -10,6 +10,11 @@
 
 if LOGO
 
+config FB_LOGO_EXTRA
+	bool
+	depends on FB
+	default y if SPU_BASE
+
 config LOGO_LINUX_MONO
 	bool "Standard black and white Linux logo"
 	default y
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index b985dfa..a5fc4ed 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -14,6 +14,8 @@
 obj-$(CONFIG_LOGO_SUPERH_CLUT224)	+= logo_superh_clut224.o
 obj-$(CONFIG_LOGO_M32R_CLUT224)		+= logo_m32r_clut224.o
 
+obj-$(CONFIG_SPU_BASE)			+= logo_spe_clut224.o
+
 # How to generate logo's
 
 # Use logo-cfiles to retrieve list of .c files to be built
diff --git a/drivers/video/logo/logo_spe_clut224.ppm b/drivers/video/logo/logo_spe_clut224.ppm
new file mode 100644
index 0000000..d36ad62
--- /dev/null
+++ b/drivers/video/logo/logo_spe_clut224.ppm
@@ -0,0 +1,283 @@
+P3
+40 40
+255
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  2 2 2  6 6 6
+15 15 15  21 21 21  19 19 19  14 14 14  6 6 6  2 2 2
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  2 2 2  21 21 21  55 55 55
+56 56 56  54 54 54  53 53 53  60 60 60  56 56 56  25 25 25
+6 6 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  2 2 2  27 27 27  62 62 62  17 17 19
+2 2 6  2 2 6  2 2 6  2 2 6  16 16 18  57 57 57
+45 45 45  8 8 8  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 1  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  16 16 16  62 62 62  8 8 10  2 2 6
+2 2 6  2 2 6  2 2 6  12 12 14  67 67 67  16 16 17
+45 45 45  41 41 41  4 4 4  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  2 2 2  35 35 35  40 40 40  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  15 15 17  70 70 70  27 27 27
+3 3 6  62 62 62  20 20 20  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  4 4 4  58 58 58  12 12 14  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  4 4 7  4 4 7  2 2 6
+2 2 6  34 34 36  40 40 40  3 3 3  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  7 7 7  64 64 64  2 2 6  5 5 5  17 17 17
+3 3 6  2 2 6  2 2 6  15 15 15  21 21 21  7 7 10
+2 2 6  8 8 10  62 62 62  6 6 6  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  7 7 7  66 66 66  5 5 8  122 122 122  122 122 122
+9 9 11  3 3 6  104 96 81  179 179 179  122 122 122  13 13 13
+2 2 6  2 2 6  67 67 67  10 10 10  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  7 7 7  65 65 65  41 41 43  152 149 142  192 191 189
+48 48 49  23 23 24  228 210 210  86 86 86  192 191 189  59 59 61
+2 2 6  2 2 6  64 64 64  14 14 14  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 1  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  7 7 7  66 66 66  59 59 59  59 59 61  86 86 86
+99 84 50  78 66 28  152 149 142  5 5 8  122 122 122  104 96 81
+2 2 6  2 2 6  67 67 67  14 14 14  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  5 5 5  63 63 63  24 24 24  152 149 142  175 122 13
+238 184 12  220 170 13  226 181 52  112 86 32  194 165 151  46 46 47
+2 2 6  2 2 6  65 65 65  17 17 17  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  5 5 5  59 59 59  21 21 21  175 122 13  231 174 11
+240 192 13  237 183 61  240 192 13  240 192 13  234 179 16  81 64 9
+2 2 6  2 2 6  63 63 63  25 25 25  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  5 5 5  54 54 54  51 48 39  189 138 9  238 184 12
+240 192 13  240 192 13  240 192 13  215 161 11  207 152 19  81 64 9
+16 16 18  5 5 8  40 40 40  44 44 44  4 4 4  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  5 5 5  59 59 59  27 27 27  126 107 64  187 136 12
+220 170 13  201 147 20  189 138 9  198 154 46  199 182 125  70 70 70
+27 27 27  104 96 81  12 12 14  70 70 70  16 16 16  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  17 17 17  70 70 70  12 12 12  168 168 168  174 135 135
+175 122 13  175 122 13  178 151 83  192 191 189  233 233 233  179 179 179
+3 3 6  29 29 31  3 3 6  41 41 41  44 44 44  5 5 5
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+8 8 8  53 53 53  44 44 44  59 59 59  238 238 238  192 191 189
+192 191 189  192 191 189  221 205 205  240 240 240  253 253 253  253 253 253
+70 70 70  2 2 6  2 2 6  5 5 8  67 67 67  22 22 22
+2 2 2  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  5 5 5
+38 38 38  56 56 56  7 7 9  221 205 205  253 253 253  233 233 233
+221 205 205  233 233 233  251 251 251  253 253 253  253 253 253  253 253 253
+192 191 189  2 2 6  2 2 6  2 2 6  25 25 25  64 64 64
+15 15 15  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  2 2 2  27 27 27
+66 66 66  7 7 9  86 86 86  252 252 252  253 253 253  253 253 253
+252 252 252  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+244 244 244  19 19 21  2 2 6  2 2 6  2 2 6  38 38 38
+54 54 54  10 10 10  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  14 14 14  62 62 62
+10 10 12  3 3 6  122 122 122  235 235 235  251 251 251  248 248 248
+235 235 235  248 248 248  252 252 252  246 246 246  233 233 233  237 228 228
+223 207 207  70 70 70  2 2 6  2 2 6  2 2 6  2 2 6
+46 46 47  38 38 38  4 4 4  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  2 2 2  33 33 33  44 44 44
+4 4 7  9 9 11  168 168 168  240 240 240  252 252 252  252 252 252
+246 246 246  253 253 253  253 253 253  251 251 251  245 241 241  233 233 233
+221 205 205  192 191 189  29 29 31  27 27 27  9 9 12  2 2 6
+3 3 6  65 65 65  15 15 15  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  59 59 59  19 19 21
+24 24 24  86 86 86  249 249 249  253 253 253  253 253 253  253 253 253
+253 253 253  228 210 210  241 230 230  253 253 253  253 253 253  253 253 253
+251 251 251  228 210 210  152 149 142  5 5 8  27 27 27  4 4 7
+2 2 6  46 46 47  34 34 34  2 2 2  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  16 16 16  67 67 67  19 19 21
+12 12 14  223 207 207  254 20 20  254 20 20  253 127 127  242 223 223
+254 20 20  253 127 127  254 48 48  242 223 223  254 86 86  254 20 20
+254 20 20  253 137 137  233 233 233  32 32 32  35 35 35  23 23 24
+2 2 6  15 15 15  60 60 60  6 6 6  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  4 4 4  38 38 38  48 48 49  22 22 22
+86 86 86  253 253 253  254 20 20  241 230 230  227 216 186  253 137 137
+253 137 137  253 253 253  253 137 137  253 137 137  254 48 48  253 253 253
+253 253 253  253 253 253  253 253 253  62 62 62  2 2 6  23 23 24
+2 2 6  2 2 6  62 62 62  17 17 17  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  14 14 14  70 70 70  14 14 14  16 16 18
+179 179 179  253 253 253  227 216 186  254 48 48  240 219 160  253 127 127
+254 20 20  253 137 137  254 86 86  231 203 141  254 20 20  254 20 20
+253 137 137  253 253 253  253 253 253  104 96 81  2 2 6  23 23 24
+2 2 6  2 2 6  46 46 47  27 27 27  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  4 4 4  39 39 39  42 42 43  19 19 21  13 13 13
+228 210 210  242 223 223  253 253 253  242 223 223  253 127 127  253 127 127
+253 127 127  253 127 127  253 137 137  253 253 253  254 48 48  253 253 253
+228 210 210  253 253 253  253 253 253  122 122 122  2 2 6  19 19 19
+2 2 6  2 2 6  39 39 39  38 38 38  3 3 3  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  8 8 8  60 60 60  3 3 6  33 33 33  38 38 38
+253 137 137  254 86 86  253 137 137  254 86 86  253 137 137  209 197 168
+253 127 127  253 253 253  253 253 253  253 253 253  253 127 127  254 86 86
+254 86 86  253 137 137  253 253 253  122 122 122  2 2 6  17 17 17
+2 2 6  2 2 6  34 34 36  42 42 43  3 3 3  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  13 13 13  59 59 59  2 2 6  9 9 12  56 56 56
+252 252 252  240 219 160  253 137 137  240 219 160  253 253 253  237 228 228
+254 86 86  253 253 253  253 253 253  253 253 253  253 253 253  242 223 223
+227 216 186  249 249 249  253 253 253  122 122 122  16 16 17  17 17 17
+12 12 14  3 3 6  39 39 39  38 38 38  3 3 3  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  2 2 2
+5 5 5  22 22 22  104 96 81  187 136 12  207 152 19  51 48 39
+221 205 205  253 253 253  253 253 253  253 253 253  253 253 253  240 240 240
+250 247 243  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  250 247 243  240 219 160  99 84 50  5 5 8  2 2 6
+7 7 9  46 46 47  58 58 58  35 35 35  3 3 3  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  8 8 8  33 33 33
+58 58 58  86 86 86  170 136 53  239 182 13  246 190 14  220 170 13
+44 38 29  179 179 179  253 253 253  253 253 253  253 253 253  240 240 240
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  240 219 160  240 192 13  112 86 32  2 2 6  2 2 6
+3 3 6  41 33 20  220 170 13  53 53 53  4 4 4  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  2 2 2  32 32 32  150 116 44
+215 161 11  215 161 11  228 170 11  245 188 14  246 190 14  246 190 14
+187 136 12  9 9 11  122 122 122  251 251 251  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+248 248 248  211 196 135  239 182 13  175 122 13  6 5 6  2 2 6
+16 14 12  187 136 12  238 184 12  84 78 65  10 10 10  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  4 4 4  53 53 53  207 152 19
+242 185 13  245 188 14  246 190 14  246 190 14  246 190 14  246 190 14
+240 192 13  81 64 9  2 2 6  86 86 86  244 244 244  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+233 233 233  199 182 125  231 174 11  207 152 19  175 122 13  175 122 13
+201 147 20  239 182 13  244 187 14  150 116 44  35 35 35  6 6 6
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  5 5 5  53 53 53  201 147 20
+242 185 13  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  220 170 13  13 11 10  2 2 6  152 149 142  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+235 235 235  199 182 125  228 170 11  234 177 12  226 168 11  226 168 11
+234 177 12  246 190 14  246 190 14  234 179 16  126 107 64  36 36 36
+6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  3 3 3  48 48 49  189 142 35
+242 185 13  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  140 112 39  36 36 36  192 191 189  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+192 191 189  112 86 32  226 168 11  244 187 14  244 187 14  244 187 14
+245 188 14  246 190 14  246 190 14  246 190 14  242 185 13  150 116 44
+27 27 27  2 2 2  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  58 58 58  189 142 35
+239 182 13  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  239 188 14  209 197 168  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  252 252 252  168 168 168
+16 16 18  97 67 8  228 170 11  245 188 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  244 187 14  198 154 46
+35 35 35  3 3 3  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  13 13 13  84 78 65  215 161 11
+244 187 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  238 184 12  187 136 12  168 168 168  244 244 244
+253 253 253  252 252 252  240 240 240  179 179 179  67 67 67  2 2 6
+2 2 6  97 67 8  228 170 11  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  245 188 14  234 177 12  189 142 35  86 77 61
+16 16 16  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  13 13 13  103 92 56  207 152 19
+228 170 11  234 177 12  239 182 13  242 186 14  245 188 14  246 190 14
+246 190 14  246 190 14  239 182 13  189 138 9  41 33 20  10 10 12
+30 30 31  23 23 24  5 5 8  2 2 6  2 2 6  2 2 6
+4 4 6  112 86 32  215 161 11  245 188 14  246 190 14  245 188 14
+239 182 13  228 170 11  189 142 35  104 96 81  48 48 49  17 17 17
+2 2 2  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  5 5 5  39 39 39  103 92 56
+141 109 44  175 122 13  187 136 12  189 138 9  207 152 19  228 170 11
+239 182 13  239 182 13  215 161 11  175 122 13  41 33 20  2 2 6
+15 15 17  20 20 22  20 20 22  20 20 22  20 20 22  8 8 10
+4 4 6  97 67 8  189 138 9  231 174 11  239 182 13  226 168 11
+189 138 9  126 107 64  59 59 59  21 21 21  5 5 5  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  5 5 5  17 17 17
+34 34 34  57 57 57  84 78 65  103 92 56  125 101 41  140 112 39
+175 122 13  175 122 13  175 122 13  97 67 8  72 67 58  84 78 65
+60 60 60  56 56 56  56 56 56  56 56 56  57 57 57  65 65 65
+86 86 86  95 73 34  175 122 13  187 136 12  187 136 12  175 122 13
+103 92 56  41 41 41  10 10 10  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+2 2 2  4 4 4  12 12 12  24 24 24  40 40 40  70 70 70
+86 77 61  95 73 34  88 72 41  72 67 58  36 36 36  10 10 10
+5 5 5  5 5 5  5 5 5  4 4 4  5 5 5  6 6 6
+22 22 22  61 61 59  88 72 41  112 86 32  112 86 32  84 78 65
+32 32 32  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  3 3 3  10 10 10
+21 21 21  33 33 33  31 31 31  16 16 16  2 2 2  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+2 2 2  12 12 12  30 30 31  40 40 40  32 32 32  16 16 16
+2 2 2  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index f7d647d..aa8c714 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -170,7 +170,7 @@
 };
 
 static struct fb_info fb_info;
-static u32 pseudo_palette[17];
+static u32 pseudo_palette[16];
 static int inverse   = 0;
 static int vidtest   = 0;
 
@@ -529,56 +529,63 @@
 	if (regno >= fb_info->cmap.len)
 		return 1;
 
-	switch (fb_info->var.bits_per_pixel) {
-	case 1:
-		/* We shouldn't get here */
-		break;
-	case 2:
-	case 4:
-	case 8:
-		if (macfb_setpalette)
-			macfb_setpalette(regno, red, green, blue, fb_info);
-		else
-			return 1;
-		break;
-	case 16:
-		if (fb_info->var.red.offset == 10) {
-			/* 1:5:5:5 */
-			((u32*) (fb_info->pseudo_palette))[regno] =
+	if (fb_info->var.bits_per_pixel <= 8) {
+		switch (fb_info->var.bits_per_pixel) {
+		case 1:
+			/* We shouldn't get here */
+			break;
+		case 2:
+		case 4:
+		case 8:
+			if (macfb_setpalette)
+				macfb_setpalette(regno, red, green, blue,
+						 fb_info);
+			else
+				return 1;
+			break;
+		}
+	} else if (regno < 16) {
+		switch (fb_info->var.bits_per_pixel) {
+		case 16:
+			if (fb_info->var.red.offset == 10) {
+				/* 1:5:5:5 */
+				((u32*) (fb_info->pseudo_palette))[regno] =
 					((red   & 0xf800) >>  1) |
 					((green & 0xf800) >>  6) |
 					((blue  & 0xf800) >> 11) |
 					((transp != 0) << 15);
-		} else {
-			/* 0:5:6:5 */
-			((u32*) (fb_info->pseudo_palette))[regno] =
+			} else {
+				/* 0:5:6:5 */
+				((u32*) (fb_info->pseudo_palette))[regno] =
 					((red   & 0xf800)      ) |
 					((green & 0xfc00) >>  5) |
 					((blue  & 0xf800) >> 11);
+			}
+			break;
+			/* I'm pretty sure that one or the other of these
+			   doesn't exist on 68k Macs */
+		case 24:
+			red   >>= 8;
+			green >>= 8;
+			blue  >>= 8;
+			((u32 *)(fb_info->pseudo_palette))[regno] =
+				(red   << fb_info->var.red.offset)   |
+				(green << fb_info->var.green.offset) |
+				(blue  << fb_info->var.blue.offset);
+			break;
+		case 32:
+			red   >>= 8;
+			green >>= 8;
+			blue  >>= 8;
+			((u32 *)(fb_info->pseudo_palette))[regno] =
+				(red   << fb_info->var.red.offset)   |
+				(green << fb_info->var.green.offset) |
+				(blue  << fb_info->var.blue.offset);
+			break;
 		}
-		break;	
-		/* I'm pretty sure that one or the other of these
-		   doesn't exist on 68k Macs */
-	case 24:
-		red   >>= 8;
-		green >>= 8;
-		blue  >>= 8;
-		((u32 *)(fb_info->pseudo_palette))[regno] =
-			(red   << fb_info->var.red.offset)   |
-			(green << fb_info->var.green.offset) |
-			(blue  << fb_info->var.blue.offset);
-		break;
-	case 32:
-		red   >>= 8;
-		green >>= 8;
-		blue  >>= 8;
-		((u32 *)(fb_info->pseudo_palette))[regno] =
-			(red   << fb_info->var.red.offset)   |
-			(green << fb_info->var.green.offset) |
-			(blue  << fb_info->var.blue.offset);
-		break;
-    }
-    return 0;
+	}
+
+	return 0;
 }
 
 static struct fb_ops macfb_ops = {
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index ab21495..083f603 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -369,9 +369,8 @@
  *
  */
 
-int __devinit mac_find_mode(struct fb_var_screeninfo *var,
-			    struct fb_info *info, const char *mode_option,
-			    unsigned int default_bpp)
+int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+		  const char *mode_option, unsigned int default_bpp)
 {
     const struct fb_videomode *db = NULL;
     unsigned int dbsize = 0;
diff --git a/drivers/video/macmodes.h b/drivers/video/macmodes.h
index babeb81..b86ba08 100644
--- a/drivers/video/macmodes.h
+++ b/drivers/video/macmodes.h
@@ -55,10 +55,10 @@
 extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
 			    int *cmode);
 extern int mac_map_monitor_sense(int sense);
-extern int __devinit mac_find_mode(struct fb_var_screeninfo *var,
-				   struct fb_info *info,
-				   const char *mode_option,
-				   unsigned int default_bpp);
+extern int mac_find_mode(struct fb_var_screeninfo *var,
+			 struct fb_info *info,
+			 const char *mode_option,
+			 unsigned int default_bpp);
 
 
     /*
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index c57aaad..3660d26 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -91,7 +91,6 @@
 	for (i = 0; i < 16; i++) {
 		pal[i] = i * 0x11111111U;
 	}
-	pal[i] = 0xFFFFFFFF;
 }
 
 static inline void matrox_cfb8_pal(u_int32_t* pal) {
@@ -100,7 +99,6 @@
 	for (i = 0; i < 16; i++) {
 		pal[i] = i * 0x01010101U;
 	}
-	pal[i] = 0x0F0F0F0F;
 }
 
 static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area);
@@ -145,13 +143,10 @@
 					ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit;
 				}
 				break;
-		case 16:	if (ACCESS_FBINFO(fbcon).var.green.length == 5) {
+		case 16:	if (ACCESS_FBINFO(fbcon).var.green.length == 5)
 					maccess = 0xC0000001;
-					ACCESS_FBINFO(cmap[16]) = 0x7FFF7FFF;
-				} else {
+				else
 					maccess = 0x40000001;
-					ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
-				}
 				mopmode = M_OPMODE_16BPP;
 				if (accel) {
 					ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
@@ -161,7 +156,6 @@
 				break;
 		case 24:	maccess = 0x00000003;
 				mopmode = M_OPMODE_24BPP;
-				ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
 				if (accel) {
 					ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
 					ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect;
@@ -170,7 +164,6 @@
 				break;
 		case 32:	maccess = 0x00000002;
 				mopmode = M_OPMODE_32BPP;
-				ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
 				if (accel) {
 					ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
 					ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index c8559a7..86ca7b1 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -679,6 +679,8 @@
 		mga_outb(M_DAC_VAL, blue);
 		break;
 	case 16:
+		if (regno >= 16)
+			break;
 		{
 			u_int16_t col =
 				(red << ACCESS_FBINFO(fbcon).var.red.offset)     |
@@ -690,6 +692,8 @@
 		break;
 	case 24:
 	case 32:
+		if (regno >= 16)
+			break;
 		ACCESS_FBINFO(cmap[regno]) =
 			(red   << ACCESS_FBINFO(fbcon).var.red.offset)   |
 			(green << ACCESS_FBINFO(fbcon).var.green.offset) |
@@ -1994,7 +1998,6 @@
 
 static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dummy) {
 	struct board* b;
-	u_int8_t rev;
 	u_int16_t svid;
 	u_int16_t sid;
 	struct matrox_fb_info* minfo;
@@ -2005,11 +2008,10 @@
 #endif
 	DBG(__FUNCTION__)
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
 	svid = pdev->subsystem_vendor;
 	sid = pdev->subsystem_device;
 	for (b = dev_list; b->vendor; b++) {
-		if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < rev)) continue;
+		if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < pdev->revision)) continue;
 		if (b->svid)
 			if ((b->svid != svid) || (b->sid != sid)) continue;
 		break;
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 9c25c2f..d59577c 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -518,7 +518,7 @@
 					dll:1;
 				      } memory;
 			      } values;
-	u_int32_t cmap[17];
+	u_int32_t cmap[16];
 };
 
 #define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon)
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 03ae55b..4b3344e 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -163,11 +163,6 @@
 	ACCESS_FBINFO(hw).crtc2.ctl = 0x00000004;
 }
 
-static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info) {
-	/* no acceleration for secondary head... */
-	m2info->cmap[16] = 0xFFFFFFFF;
-}
-
 static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
 		struct fb_var_screeninfo* var) {
 	unsigned int pos;
@@ -385,7 +380,6 @@
 			}
 		}
 		up_read(&ACCESS_FBINFO(altout).lock);
-		matroxfb_dh_cfbX_init(m2info);
 	}
 	m2info->initialized = 1;
 	return 0;
diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h
index 608e40b..1005582 100644
--- a/drivers/video/matrox/matroxfb_crtc2.h
+++ b/drivers/video/matrox/matroxfb_crtc2.h
@@ -2,8 +2,6 @@
 #define __MATROXFB_CRTC2_H__
 
 #include <linux/ioctl.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
 #include "matroxfb_base.h"
 
 struct matroxfb_dh_fb_info {
@@ -30,7 +28,7 @@
 
 	unsigned int		interlaced:1;
 
-	u_int32_t cmap[17];
+	u_int32_t cmap[16];
 };
 
 #endif /* __MATROXFB_CRTC2_H__ */
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 5d29a26..de0d755 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -273,8 +273,11 @@
 			}
 		}
 	}
+
+	/* if h2/post/in/feed have not been assigned, return zero (error) */
 	if (besth2 < 2)
 		return 0;
+
 	dprintk(KERN_ERR "clk: %02X %02X %02X %d %d\n", *in, *feed, *post, fxtal, fwant);
 	return fxtal * (*feed) / (*in) * ctl->den;
 }
@@ -284,7 +287,7 @@
 		unsigned int* in, unsigned int* feed, unsigned int* post,
 		unsigned int* htotal2) {
 	unsigned int fvco;
-	unsigned int p;
+	unsigned int uninitialized_var(p);
 
 	fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2);
 	if (!fvco)
@@ -715,7 +718,9 @@
 	m->regs[0x82] = 0x81;
 
 	for (x = 0; x < 8; x++) {
-		unsigned int a, b, c, h2;
+		unsigned int c;
+		unsigned int uninitialized_var(a), uninitialized_var(b),
+			     uninitialized_var(h2);
 		unsigned int h = ht + 2 + x;
 
 		if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index bd30aba..731d7a5 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1286,34 +1286,36 @@
 	if (regno >= fb->cmap.len || regno > 255)
 		return -EINVAL;
 
-	switch (fb->var.bits_per_pixel) {
-	case 8:
+	if (fb->var.bits_per_pixel <= 8) {
 		outb(regno, 0x3c8);
 
 		outb(red >> 10, 0x3c9);
 		outb(green >> 10, 0x3c9);
 		outb(blue >> 10, 0x3c9);
-		break;
-	case 16:
-		((u32 *) fb->pseudo_palette)[regno] =
+	} else if (regno < 16) {
+		switch (fb->var.bits_per_pixel) {
+		case 16:
+			((u32 *) fb->pseudo_palette)[regno] =
 				((red & 0xf800)) | ((green & 0xfc00) >> 5) |
 				((blue & 0xf800) >> 11);
-		break;
-	case 24:
-		((u32 *) fb->pseudo_palette)[regno] =
+			break;
+		case 24:
+			((u32 *) fb->pseudo_palette)[regno] =
 				((red & 0xff00) << 8) | ((green & 0xff00)) |
 				((blue & 0xff00) >> 8);
-		break;
+			break;
 #ifdef NO_32BIT_SUPPORT_YET
-	case 32:
-		((u32 *) fb->pseudo_palette)[regno] =
+		case 32:
+			((u32 *) fb->pseudo_palette)[regno] =
 				((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
 				((green & 0xff00)) | ((blue & 0xff00) >> 8);
-		break;
+			break;
 #endif
-	default:
-		return 1;
+		default:
+			return 1;
+		}
 	}
+
 	return 0;
 }
 
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index aff11bb..d1a1054 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -150,8 +150,7 @@
 		M = pll & 0xFF;
 		N = (pll >> 8) & 0xFF;
 		if (((par->Chipset & 0xfff0) == 0x0290) ||
-			((par->Chipset & 0xfff0) == 0x0390) ||
-			((par->Chipset & 0xfff0) == 0x02E0)) {
+		    ((par->Chipset & 0xfff0) == 0x0390)) {
 			MB = 1;
 			NB = 1;
 		} else {
@@ -161,7 +160,7 @@
 		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
 
 		pll = NV_RD32(par->PMC, 0x4000);
-		P = (pll >> 16) & 0x03;
+		P = (pll >> 16) & 0x07;
 		pll = NV_RD32(par->PMC, 0x4004);
 		M = pll & 0xFF;
 		N = (pll >> 8) & 0xFF;
@@ -892,11 +891,17 @@
 		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
 		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
 		break;
+	case NV_ARCH_40:
+		if (!par->FlatPanel)
+			state->control = NV_RD32(par->PRAMDAC0, 0x0580) &
+				0xeffffeff;
+		/* fallthrough */
 	case NV_ARCH_10:
 	case NV_ARCH_20:
 	case NV_ARCH_30:
 	default:
-		if ((par->Chipset & 0xfff0) == 0x0240) {
+		if ((par->Chipset & 0xfff0) == 0x0240 ||
+		    (par->Chipset & 0xfff0) == 0x03d0) {
 			state->arbitration0 = 256;
 			state->arbitration1 = 0x0480;
 		} else if (((par->Chipset & 0xffff) == 0x01A0) ||
@@ -939,7 +944,7 @@
 
 void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
 {
-	int i;
+	int i, j;
 
 	NV_WR32(par->PMC, 0x0140, 0x00000000);
 	NV_WR32(par->PMC, 0x0200, 0xFFFF00FF);
@@ -951,7 +956,8 @@
 	NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF);
 
 	if (par->Architecture == NV_ARCH_04) {
-		NV_WR32(par->PFB, 0x0200, state->config);
+		if (state)
+			NV_WR32(par->PFB, 0x0200, state->config);
 	} else if ((par->Architecture < NV_ARCH_40) ||
 		   (par->Chipset & 0xfff0) == 0x0040) {
 		for (i = 0; i < 8; i++) {
@@ -964,8 +970,9 @@
 
 		if (((par->Chipset & 0xfff0) == 0x0090) ||
 		    ((par->Chipset & 0xfff0) == 0x01D0) ||
-		    ((par->Chipset & 0xfff0) == 0x02E0) ||
-		    ((par->Chipset & 0xfff0) == 0x0290))
+		    ((par->Chipset & 0xfff0) == 0x0290) ||
+		    ((par->Chipset & 0xfff0) == 0x0390) ||
+		    ((par->Chipset & 0xfff0) == 0x03D0))
 			regions = 15;
 		for(i = 0; i < regions; i++) {
 			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
@@ -1206,16 +1213,20 @@
 			NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
 		} else {
 			if (par->Architecture >= NV_ARCH_40) {
-				u32 tmp;
-
 				NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
 				NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
 				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
 				NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+				NV_WR32(par->PGRAPH, 0x0bc4,
+					NV_RD32(par->PGRAPH, 0x0bc4) |
+					0x00008000);
 
-				tmp = NV_RD32(par->REGS, 0x1540) & 0xff;
-				for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++);
-				NV_WR32(par->PGRAPH, 0x5000, i);
+				j = NV_RD32(par->REGS, 0x1540) & 0xff;
+
+				if (j) {
+					for (i = 0; !(j & 1); j >>= 1, i++);
+					NV_WR32(par->PGRAPH, 0x5000, i);
+				}
 
 				if ((par->Chipset & 0xfff0) == 0x0040) {
 					NV_WR32(par->PGRAPH, 0x09b0,
@@ -1250,6 +1261,7 @@
 				case 0x0160:
 				case 0x01D0:
 				case 0x0240:
+				case 0x03D0:
 					NV_WR32(par->PMC, 0x1700,
 						NV_RD32(par->PFB, 0x020C));
 					NV_WR32(par->PMC, 0x1704, 0);
@@ -1269,7 +1281,6 @@
 						0x00000108);
 					break;
 				case 0x0220:
-				case 0x0230:
 					NV_WR32(par->PGRAPH, 0x0860, 0);
 					NV_WR32(par->PGRAPH, 0x0864, 0);
 					NV_WR32(par->PRAMDAC, 0x0608,
@@ -1277,8 +1288,8 @@
 						0x00100000);
 					break;
 				case 0x0090:
-				case 0x02E0:
 				case 0x0290:
+				case 0x0390:
 					NV_WR32(par->PRAMDAC, 0x0608,
 						NV_RD32(par->PRAMDAC, 0x0608) |
 						0x00100000);
@@ -1355,8 +1366,9 @@
 			} else {
 				if (((par->Chipset & 0xfff0) == 0x0090) ||
 				    ((par->Chipset & 0xfff0) == 0x01D0) ||
-				    ((par->Chipset & 0xfff0) == 0x02E0) ||
-				    ((par->Chipset & 0xfff0) == 0x0290)) {
+				    ((par->Chipset & 0xfff0) == 0x0290) ||
+				    ((par->Chipset & 0xfff0) == 0x0390) ||
+				    ((par->Chipset & 0xfff0) == 0x03D0)) {
 					for (i = 0; i < 60; i++) {
 						NV_WR32(par->PGRAPH,
 							0x0D00 + i*4,
@@ -1407,8 +1419,8 @@
 				} else {
 					if ((par->Chipset & 0xfff0) == 0x0090 ||
 					    (par->Chipset & 0xfff0) == 0x01D0 ||
-					    (par->Chipset & 0xfff0) == 0x02E0 ||
-					    (par->Chipset & 0xfff0) == 0x0290) {
+					    (par->Chipset & 0xfff0) == 0x0290 ||
+					    (par->Chipset & 0xfff0) == 0x0390) {
 						NV_WR32(par->PGRAPH, 0x0DF0,
 							NV_RD32(par->PFB, 0x0200));
 						NV_WR32(par->PGRAPH, 0x0DF4,
@@ -1495,6 +1507,12 @@
 	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001);
 	NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001);
 	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001);
+
+    if (!state) {
+	    par->CurrentState = NULL;
+	    return;
+    }
+
 	if (par->Architecture >= NV_ARCH_10) {
 		if (par->twoHeads) {
 			NV_WR32(par->PCRTC0, 0x0860, state->head);
@@ -1566,6 +1584,9 @@
 	VGA_WR08(par->PCIO, 0x03D5, state->interlace);
 
 	if (!par->FlatPanel) {
+		if (par->Architecture >= NV_ARCH_40)
+			NV_WR32(par->PRAMDAC0, 0x0580, state->control);
+
 		NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel);
 		NV_WR32(par->PRAMDAC0, 0x0508, state->vpll);
 		if (par->twoHeads)
@@ -1631,6 +1652,9 @@
 	state->scale = NV_RD32(par->PRAMDAC, 0x0848);
 	state->config = NV_RD32(par->PFB, 0x0200);
 
+	if (par->Architecture >= NV_ARCH_40 && !par->FlatPanel)
+		state->control  = NV_RD32(par->PRAMDAC0, 0x0580);
+
 	if (par->Architecture >= NV_ARCH_10) {
 		if (par->twoHeads) {
 			state->head = NV_RD32(par->PCRTC0, 0x0860);
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 707e2c8..82579d3 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -166,11 +166,13 @@
 static int NVIsConnected(struct nvidia_par *par, int output)
 {
 	volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
-	u32 reg52C, reg608;
+	u32 reg52C, reg608, dac0_reg608 = 0;
 	int present;
 
-	if (output)
-		PRAMDAC += 0x800;
+	if (output) {
+	    dac0_reg608 = NV_RD32(PRAMDAC, 0x0608);
+	    PRAMDAC += 0x800;
+	}
 
 	reg52C = NV_RD32(PRAMDAC, 0x052C);
 	reg608 = NV_RD32(PRAMDAC, 0x0608);
@@ -194,8 +196,8 @@
 	else
 		printk("nvidiafb: CRTC%i analog not found\n", output);
 
-	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) &
-		0x0000EFFF);
+	if (output)
+	    NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608);
 
 	NV_WR32(PRAMDAC, 0x052C, reg52C);
 	NV_WR32(PRAMDAC, 0x0608, reg608);
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
index 38f7cc0..2fdf77ec3 100644
--- a/drivers/video/nvidia/nv_type.h
+++ b/drivers/video/nvidia/nv_type.h
@@ -86,6 +86,7 @@
 	u32 timingV;
 	u32 displayV;
 	u32 crtcSync;
+	u32 control;
 } RIVA_HW_STATE;
 
 struct riva_regs {
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 41f6365..a7fe214 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -674,6 +674,7 @@
 		info->fbops->fb_sync = nvidiafb_sync;
 		info->pixmap.scan_align = 4;
 		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+		info->flags |= FBINFO_READS_FAST;
 		NVResetGraphics(info);
 	} else {
 		info->fbops->fb_imageblit = cfb_imageblit;
@@ -682,6 +683,7 @@
 		info->fbops->fb_sync = NULL;
 		info->pixmap.scan_align = 1;
 		info->flags |= FBINFO_HWACCEL_DISABLED;
+		info->flags &= ~FBINFO_READS_FAST;
 	}
 
 	par->cursor_reset = 1;
@@ -1193,7 +1195,8 @@
 
 	printk(KERN_INFO PFX "Device ID: %x \n", id);
 
-	if ((id & 0xfff0) == 0x00f0) {
+	if ((id & 0xfff0) == 0x00f0 ||
+	    (id & 0xfff0) == 0x02e0) {
 		/* pci-e */
 		id = NV_RD32(par->REGS, 0x1800);
 
@@ -1238,18 +1241,16 @@
 	case 0x0040:		/* GeForce 6800 */
 	case 0x00C0:		/* GeForce 6800 */
 	case 0x0120:		/* GeForce 6800 */
-	case 0x0130:
 	case 0x0140:		/* GeForce 6600 */
 	case 0x0160:		/* GeForce 6200 */
 	case 0x01D0:		/* GeForce 7200, 7300, 7400 */
-	case 0x02E0:		/* GeForce 7300 GT */
 	case 0x0090:		/* GeForce 7800 */
 	case 0x0210:		/* GeForce 6800 */
 	case 0x0220:		/* GeForce 6200 */
-	case 0x0230:
 	case 0x0240:		/* GeForce 6100 */
 	case 0x0290:		/* GeForce 7900 */
 	case 0x0390:		/* GeForce 7600 */
+	case 0x03D0:
 		arch = NV_ARCH_40;
 		break;
 	case 0x0020:		/* TNT, TNT2 */
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 885b428..452433d 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -271,7 +271,7 @@
 		return;
 	}
 
-	size = sizeof(struct fb_info) + sizeof(u32) * 17;
+	size = sizeof(struct fb_info) + sizeof(u32) * 16;
 
 	info = kmalloc(size, GFP_ATOMIC);
 	
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
new file mode 100644
index 0000000..7f4d25b
--- /dev/null
+++ b/drivers/video/omap/Kconfig
@@ -0,0 +1,58 @@
+config FB_OMAP
+	tristate "OMAP frame buffer support (EXPERIMENTAL)"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+          Frame buffer driver for OMAP based boards.
+
+config FB_OMAP_BOOTLOADER_INIT
+	bool "Check bootloader initializaion"
+	depends on FB_OMAP
+	help
+	  Say Y here if you want to enable checking if the bootloader has
+	  already initialized the display controller. In this case the
+	  driver will skip the initialization.
+
+config FB_OMAP_CONSISTENT_DMA_SIZE
+	int "Consistent DMA memory size (MB)"
+	depends on FB_OMAP
+	range 1 14
+	default 2
+	help
+	  Increase the DMA consistent memory size according to your video
+	  memory needs, for example if you want to use multiple planes.
+	  The size must be 2MB aligned.
+	  If unsure say 1.
+
+config FB_OMAP_DMA_TUNE
+        bool "Set DMA SDRAM access priority high"
+        depends on FB_OMAP && ARCH_OMAP1
+        help
+          On systems in which video memory is in system memory
+          (SDRAM) this will speed up graphics DMA operations.
+          If you have such a system and want to use rotation
+          answer yes. Answer no if you have a dedicated video
+          memory, or don't use any of the accelerated features.
+
+config FB_OMAP_LCDC_EXTERNAL
+	bool "External LCD controller support"
+	depends on FB_OMAP
+	help
+	  Say Y here, if you want to have support for boards with an
+	  external LCD controller connected to the SoSSI/RFBI interface.
+
+config FB_OMAP_LCDC_HWA742
+	bool "Epson HWA742 LCD controller support"
+	depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+	help
+	  Say Y here if you want to have support for the external
+	  Epson HWA742 LCD controller.
+
+config FB_OMAP_LCDC_BLIZZARD
+	bool "Epson Blizzard LCD controller support"
+	depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+	help
+	  Say Y here if you want to have support for the external
+	  Epson Blizzard LCD controller.
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
new file mode 100644
index 0000000..99da8b6
--- /dev/null
+++ b/drivers/video/omap/Makefile
@@ -0,0 +1,29 @@
+#
+# Makefile for the new OMAP framebuffer device driver
+#
+
+obj-$(CONFIG_FB_OMAP) += omapfb.o
+
+objs-yy := omapfb_main.o
+
+objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o
+objs-y$(CONFIG_ARCH_OMAP2) += dispc.o
+
+objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
+objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o
+
+objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
+objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
+
+objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o
+objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
+objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
+objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o
+objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o
+objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
+objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
+objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
+objs-y$(CONFIG_MACH_SX1) += lcd_sx1.o
+
+omapfb-objs := $(objs-yy)
+
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
new file mode 100644
index 0000000..e682940
--- /dev/null
+++ b/drivers/video/omap/blizzard.c
@@ -0,0 +1,1568 @@
+/*
+ * Epson Blizzard LCD controller driver
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Authors:     Juha Yrjola   <juha.yrjola@nokia.com>
+ *	        Imre Deak     <imre.deak@nokia.com>
+ * YUV support: Jussi Laako   <jussi.laako@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/blizzard.h>
+
+#include "dispc.h"
+
+#define MODULE_NAME				"blizzard"
+
+#define BLIZZARD_REV_CODE			0x00
+#define BLIZZARD_CONFIG				0x02
+#define BLIZZARD_PLL_DIV			0x04
+#define BLIZZARD_PLL_LOCK_RANGE			0x06
+#define BLIZZARD_PLL_CLOCK_SYNTH_0		0x08
+#define BLIZZARD_PLL_CLOCK_SYNTH_1		0x0a
+#define BLIZZARD_PLL_MODE			0x0c
+#define BLIZZARD_CLK_SRC			0x0e
+#define BLIZZARD_MEM_BANK0_ACTIVATE		0x10
+#define BLIZZARD_MEM_BANK0_STATUS		0x14
+#define BLIZZARD_HDISP				0x2a
+#define BLIZZARD_HNDP				0x2c
+#define BLIZZARD_VDISP0				0x2e
+#define BLIZZARD_VDISP1				0x30
+#define BLIZZARD_VNDP				0x32
+#define BLIZZARD_HSW				0x34
+#define BLIZZARD_VSW				0x38
+#define BLIZZARD_DISPLAY_MODE			0x68
+#define BLIZZARD_INPUT_WIN_X_START_0		0x6c
+#define BLIZZARD_DATA_SOURCE_SELECT		0x8e
+#define BLIZZARD_DISP_MEM_DATA_PORT		0x90
+#define BLIZZARD_DISP_MEM_READ_ADDR0		0x92
+#define BLIZZARD_POWER_SAVE			0xE6
+#define BLIZZARD_NDISP_CTRL_STATUS		0xE8
+
+/* Data source select */
+/* For S1D13745 */
+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND	0x00
+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE	0x01
+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE	0x04
+#define BLIZZARD_SRC_DISABLE_OVERLAY		0x05
+/* For S1D13744 */
+#define BLIZZARD_SRC_WRITE_LCD			0x00
+#define BLIZZARD_SRC_BLT_LCD			0x06
+
+#define BLIZZARD_COLOR_RGB565			0x01
+#define BLIZZARD_COLOR_YUV420			0x09
+
+#define BLIZZARD_VERSION_S1D13745		0x01	/* Hailstorm */
+#define BLIZZARD_VERSION_S1D13744		0x02	/* Blizzard */
+
+#define BLIZZARD_AUTO_UPDATE_TIME		(HZ / 20)
+
+/* Reserve 4 request slots for requests in irq context */
+#define REQ_POOL_SIZE			24
+#define IRQ_REQ_POOL_SIZE		4
+
+#define REQ_FROM_IRQ_POOL 0x01
+
+#define REQ_COMPLETE	0
+#define REQ_PENDING	1
+
+struct blizzard_reg_list {
+	int	start;
+	int	end;
+};
+
+/* These need to be saved / restored separately from the rest. */
+static struct blizzard_reg_list blizzard_pll_regs[] = {
+	{
+		.start	= 0x04,		/* Don't save PLL ctrl (0x0C) */
+		.end	= 0x0a,
+	},
+	{
+		.start	= 0x0e,		/* Clock configuration */
+		.end	= 0x0e,
+	},
+};
+
+static struct blizzard_reg_list blizzard_gen_regs[] = {
+	{
+		.start	= 0x18,		/* SDRAM control */
+		.end	= 0x20,
+	},
+	{
+		.start	= 0x28,		/* LCD Panel configuration */
+		.end	= 0x5a,		/* HSSI interface, TV configuration */
+	},
+};
+
+static u8 blizzard_reg_cache[0x5a / 2];
+
+struct update_param {
+	int	plane;
+	int	x, y, width, height;
+	int	out_x, out_y;
+	int	out_width, out_height;
+	int	color_mode;
+	int	bpp;
+	int	flags;
+};
+
+struct blizzard_request {
+	struct list_head entry;
+	unsigned int	 flags;
+
+	int		 (*handler)(struct blizzard_request *req);
+	void		 (*complete)(void *data);
+	void		 *complete_data;
+
+	union {
+		struct update_param	update;
+		struct completion	*sync;
+	} par;
+};
+
+struct plane_info {
+	unsigned long offset;
+	int pos_x, pos_y;
+	int width, height;
+	int out_width, out_height;
+	int scr_width;
+	int color_mode;
+	int bpp;
+};
+
+struct blizzard_struct {
+	enum omapfb_update_mode	update_mode;
+	enum omapfb_update_mode	update_mode_before_suspend;
+
+	struct timer_list	auto_update_timer;
+	int			stop_auto_update;
+	struct omapfb_update_window	auto_update_window;
+	int			enabled_planes;
+	int			vid_nonstd_color;
+	int			vid_scaled;
+	int			last_color_mode;
+	int			zoom_on;
+	int			screen_width;
+	int			screen_height;
+	unsigned		te_connected:1;
+	unsigned		vsync_only:1;
+
+	struct plane_info	plane[OMAPFB_PLANE_NUM];
+
+	struct blizzard_request	req_pool[REQ_POOL_SIZE];
+	struct list_head	pending_req_list;
+	struct list_head	free_req_list;
+	struct semaphore	req_sema;
+	spinlock_t		req_lock;
+
+	unsigned long		sys_ck_rate;
+	struct extif_timings	reg_timings, lut_timings;
+
+	u32			max_transmit_size;
+	u32			extif_clk_period;
+	int			extif_clk_div;
+	unsigned long		pix_tx_time;
+	unsigned long		line_upd_time;
+
+	struct omapfb_device	*fbdev;
+	struct lcd_ctrl_extif	*extif;
+	struct lcd_ctrl		*int_ctrl;
+
+	void			(*power_up)(struct device *dev);
+	void			(*power_down)(struct device *dev);
+
+	int			version;
+} blizzard;
+
+struct lcd_ctrl blizzard_ctrl;
+
+static u8 blizzard_read_reg(u8 reg)
+{
+	u8 data;
+
+	blizzard.extif->set_bits_per_cycle(8);
+	blizzard.extif->write_command(&reg, 1);
+	blizzard.extif->read_data(&data, 1);
+
+	return data;
+}
+
+static void blizzard_write_reg(u8 reg, u8 val)
+{
+	blizzard.extif->set_bits_per_cycle(8);
+	blizzard.extif->write_command(&reg, 1);
+	blizzard.extif->write_data(&val, 1);
+}
+
+static void blizzard_restart_sdram(void)
+{
+	unsigned long tmo;
+
+	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
+	udelay(50);
+	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1);
+	tmo = jiffies + msecs_to_jiffies(200);
+	while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) {
+		if (time_after(jiffies, tmo)) {
+			dev_err(blizzard.fbdev->dev,
+					"s1d1374x: SDRAM not ready");
+			break;
+		}
+		msleep(1);
+	}
+}
+
+static void blizzard_stop_sdram(void)
+{
+	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
+}
+
+/* Wait until the last window was completely written into the controllers
+ * SDRAM and we can start transferring the next window.
+ */
+static void blizzard_wait_line_buffer(void)
+{
+	unsigned long tmo = jiffies + msecs_to_jiffies(30);
+
+	while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) {
+		if (time_after(jiffies, tmo)) {
+			if (printk_ratelimit())
+				dev_err(blizzard.fbdev->dev,
+					"s1d1374x: line buffer not ready\n");
+			break;
+		}
+	}
+}
+
+/* Wait until the YYC color space converter is idle. */
+static void blizzard_wait_yyc(void)
+{
+	unsigned long tmo = jiffies + msecs_to_jiffies(30);
+
+	while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) {
+		if (time_after(jiffies, tmo)) {
+			if (printk_ratelimit())
+				dev_err(blizzard.fbdev->dev,
+					"s1d1374x: YYC not ready\n");
+			break;
+		}
+	}
+}
+
+static void disable_overlay(void)
+{
+	blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT,
+				BLIZZARD_SRC_DISABLE_OVERLAY);
+}
+
+static void set_window_regs(int x_start, int y_start, int x_end, int y_end,
+			    int x_out_start, int y_out_start,
+			    int x_out_end, int y_out_end, int color_mode,
+			    int zoom_off, int flags)
+{
+	u8 tmp[18];
+	u8 cmd;
+
+	x_end--;
+	y_end--;
+	tmp[0] = x_start;
+	tmp[1] = x_start >> 8;
+	tmp[2] = y_start;
+	tmp[3] = y_start >> 8;
+	tmp[4] = x_end;
+	tmp[5] = x_end >> 8;
+	tmp[6] = y_end;
+	tmp[7] = y_end >> 8;
+
+	x_out_end--;
+	y_out_end--;
+	tmp[8]  = x_out_start;
+	tmp[9]  = x_out_start >> 8;
+	tmp[10] = y_out_start;
+	tmp[11] = y_out_start >> 8;
+	tmp[12] = x_out_end;
+	tmp[13] = x_out_end >> 8;
+	tmp[14] = y_out_end;
+	tmp[15] = y_out_end >> 8;
+
+	tmp[16] = color_mode;
+	if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745)
+		tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
+	else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY)
+		tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE;
+	else
+		tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
+				BLIZZARD_SRC_WRITE_LCD :
+				BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
+
+	blizzard.extif->set_bits_per_cycle(8);
+	cmd = BLIZZARD_INPUT_WIN_X_START_0;
+	blizzard.extif->write_command(&cmd, 1);
+	blizzard.extif->write_data(tmp, 18);
+}
+
+static void enable_tearsync(int y, int width, int height, int screen_height,
+			    int out_height, int force_vsync)
+{
+	u8 b;
+
+	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+	b |= 1 << 3;
+	blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+
+	if (likely(blizzard.vsync_only || force_vsync)) {
+		blizzard.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if (width * blizzard.pix_tx_time < blizzard.line_upd_time) {
+		blizzard.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if ((width * blizzard.pix_tx_time / 1000) * height <
+	    (y + out_height) * (blizzard.line_upd_time / 1000)) {
+		blizzard.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	blizzard.extif->enable_tearsync(1, y + 1);
+}
+
+static void disable_tearsync(void)
+{
+	u8 b;
+
+	blizzard.extif->enable_tearsync(0, 0);
+	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+	b &= ~(1 << 3);
+	blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+}
+
+static inline void set_extif_timings(const struct extif_timings *t);
+
+static inline struct blizzard_request *alloc_req(void)
+{
+	unsigned long flags;
+	struct blizzard_request *req;
+	int req_flags = 0;
+
+	if (!in_interrupt())
+		down(&blizzard.req_sema);
+	else
+		req_flags = REQ_FROM_IRQ_POOL;
+
+	spin_lock_irqsave(&blizzard.req_lock, flags);
+	BUG_ON(list_empty(&blizzard.free_req_list));
+	req = list_entry(blizzard.free_req_list.next,
+			 struct blizzard_request, entry);
+	list_del(&req->entry);
+	spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+	INIT_LIST_HEAD(&req->entry);
+	req->flags = req_flags;
+
+	return req;
+}
+
+static inline void free_req(struct blizzard_request *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&blizzard.req_lock, flags);
+
+	list_del(&req->entry);
+	list_add(&req->entry, &blizzard.free_req_list);
+	if (!(req->flags & REQ_FROM_IRQ_POOL))
+		up(&blizzard.req_sema);
+
+	spin_unlock_irqrestore(&blizzard.req_lock, flags);
+}
+
+static void process_pending_requests(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&blizzard.req_lock, flags);
+
+	while (!list_empty(&blizzard.pending_req_list)) {
+		struct blizzard_request *req;
+		void (*complete)(void *);
+		void *complete_data;
+
+		req = list_entry(blizzard.pending_req_list.next,
+				 struct blizzard_request, entry);
+		spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+		if (req->handler(req) == REQ_PENDING)
+			return;
+
+		complete = req->complete;
+		complete_data = req->complete_data;
+		free_req(req);
+
+		if (complete)
+			complete(complete_data);
+
+		spin_lock_irqsave(&blizzard.req_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&blizzard.req_lock, flags);
+}
+
+static void submit_req_list(struct list_head *head)
+{
+	unsigned long flags;
+	int process = 1;
+
+	spin_lock_irqsave(&blizzard.req_lock, flags);
+	if (likely(!list_empty(&blizzard.pending_req_list)))
+		process = 0;
+	list_splice_init(head, blizzard.pending_req_list.prev);
+	spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+	if (process)
+		process_pending_requests();
+}
+
+static void request_complete(void *data)
+{
+	struct blizzard_request	*req = (struct blizzard_request *)data;
+	void			(*complete)(void *);
+	void			*complete_data;
+
+	complete = req->complete;
+	complete_data = req->complete_data;
+
+	free_req(req);
+
+	if (complete)
+		complete(complete_data);
+
+	process_pending_requests();
+}
+
+
+static int do_full_screen_update(struct blizzard_request *req)
+{
+	int i;
+	int flags;
+
+	for (i = 0; i < 3; i++) {
+		struct plane_info *p = &blizzard.plane[i];
+		if (!(blizzard.enabled_planes & (1 << i))) {
+			blizzard.int_ctrl->enable_plane(i, 0);
+			continue;
+		}
+		dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n",
+			p->width, p->height);
+		blizzard.int_ctrl->setup_plane(i,
+				OMAPFB_CHANNEL_OUT_LCD, p->offset,
+				p->scr_width, p->pos_x, p->pos_y,
+				p->width, p->height,
+				p->color_mode);
+		blizzard.int_ctrl->enable_plane(i, 1);
+	}
+
+	dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n",
+		blizzard.screen_width, blizzard.screen_height);
+	blizzard_wait_line_buffer();
+	flags = req->par.update.flags;
+	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+		enable_tearsync(0, blizzard.screen_width,
+				blizzard.screen_height,
+				blizzard.screen_height,
+				blizzard.screen_height,
+				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+	else
+		disable_tearsync();
+
+	set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height,
+			0, 0, blizzard.screen_width, blizzard.screen_height,
+			BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags);
+	blizzard.zoom_on = 0;
+
+	blizzard.extif->set_bits_per_cycle(16);
+	/* set_window_regs has left the register index at the right
+	 * place, so no need to set it here.
+	 */
+	blizzard.extif->transfer_area(blizzard.screen_width,
+				      blizzard.screen_height,
+				      request_complete, req);
+	return REQ_PENDING;
+}
+
+/* Setup all planes with an overlapping area with the update window. */
+static int do_partial_update(struct blizzard_request *req, int plane,
+			     int x, int y, int w, int h,
+			     int x_out, int y_out, int w_out, int h_out,
+			     int wnd_color_mode, int bpp)
+{
+	int i;
+	int gx1, gy1, gx2, gy2;
+	int gx1_out, gy1_out, gx2_out, gy2_out;
+	int color_mode;
+	int flags;
+	int zoom_off;
+
+	/* Global coordinates, relative to pixel 0,0 of the LCD */
+	gx1 = x + blizzard.plane[plane].pos_x;
+	gy1 = y + blizzard.plane[plane].pos_y;
+	gx2 = gx1 + w;
+	gy2 = gy1 + h;
+
+	flags = req->par.update.flags;
+	if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
+		gx1_out = gx1;
+		gy1_out = gy1;
+		gx2_out = gx1 + w * 2;
+		gy2_out = gy1 + h * 2;
+	} else {
+		gx1_out = x_out + blizzard.plane[plane].pos_x;
+		gy1_out = y_out + blizzard.plane[plane].pos_y;
+		gx2_out = gx1_out + w_out;
+		gy2_out = gy1_out + h_out;
+	}
+	zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 &&
+		w == blizzard.screen_width && h == blizzard.screen_height;
+	blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) ||
+			   (w < w_out || h < h_out);
+
+	for (i = 0; i < OMAPFB_PLANE_NUM; i++) {
+		struct plane_info *p = &blizzard.plane[i];
+		int px1, py1;
+		int px2, py2;
+		int pw, ph;
+		int pposx, pposy;
+		unsigned long offset;
+
+		if (!(blizzard.enabled_planes & (1 << i))  ||
+		    (wnd_color_mode && i != plane)) {
+			blizzard.int_ctrl->enable_plane(i, 0);
+			continue;
+		}
+		/* Plane coordinates */
+		if (i == plane) {
+			/* Plane in which we are doing the update.
+			 * Local coordinates are the one in the update
+			 * request.
+			 */
+			px1 = x;
+			py1 = y;
+			px2 = x + w;
+			py2 = y + h;
+			pposx = 0;
+			pposy = 0;
+		} else {
+			/* Check if this plane has an overlapping part */
+			px1 = gx1 - p->pos_x;
+			py1 = gy1 - p->pos_y;
+			px2 = gx2 - p->pos_x;
+			py2 = gy2 - p->pos_y;
+			if (px1 >= p->width || py1 >= p->height ||
+			    px2 <= 0 || py2 <= 0) {
+				blizzard.int_ctrl->enable_plane(i, 0);
+				continue;
+			}
+			/* Calculate the coordinates for the overlapping
+			 * part in the plane's local coordinates.
+			 */
+			pposx = -px1;
+			pposy = -py1;
+			if (px1 < 0)
+				px1 = 0;
+			if (py1 < 0)
+				py1 = 0;
+			if (px2 > p->width)
+				px2 = p->width;
+			if (py2 > p->height)
+				py2 = p->height;
+			if (pposx < 0)
+				pposx = 0;
+			if (pposy < 0)
+				pposy = 0;
+		}
+		pw = px2 - px1;
+		ph = py2 - py1;
+		offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8;
+		if (wnd_color_mode)
+			/* Window embedded in the plane with a differing
+			 * color mode / bpp. Calculate the number of DMA
+			 * transfer elements in terms of the plane's bpp.
+			 */
+			pw = (pw + 1) * bpp / p->bpp;
+#ifdef VERBOSE
+		dev_dbg(blizzard.fbdev->dev,
+			"plane %d offset %#08lx pposx %d pposy %d "
+			"px1 %d py1 %d pw %d ph %d\n",
+			i, offset, pposx, pposy, px1, py1, pw, ph);
+#endif
+		blizzard.int_ctrl->setup_plane(i,
+				OMAPFB_CHANNEL_OUT_LCD, offset,
+				p->scr_width,
+				pposx, pposy, pw, ph,
+				p->color_mode);
+
+		blizzard.int_ctrl->enable_plane(i, 1);
+	}
+
+	switch (wnd_color_mode) {
+	case OMAPFB_COLOR_YUV420:
+		color_mode = BLIZZARD_COLOR_YUV420;
+		/* Currently only the 16 bits/pixel cycle format is
+		 * supported on the external interface. Adjust the number
+		 * of transfer elements per line for 12bpp format.
+		 */
+		w = (w + 1) * 3 / 4;
+		break;
+	default:
+		color_mode = BLIZZARD_COLOR_RGB565;
+		break;
+	}
+
+	blizzard_wait_line_buffer();
+	if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420)
+		blizzard_wait_yyc();
+	blizzard.last_color_mode = color_mode;
+	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+		enable_tearsync(gy1, w, h,
+				blizzard.screen_height,
+				h_out,
+				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+	else
+		disable_tearsync();
+
+	set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out,
+			color_mode, zoom_off, flags);
+
+	blizzard.extif->set_bits_per_cycle(16);
+	/* set_window_regs has left the register index at the right
+	 * place, so no need to set it here.
+	 */
+	blizzard.extif->transfer_area(w, h, request_complete, req);
+
+	return REQ_PENDING;
+}
+
+static int send_frame_handler(struct blizzard_request *req)
+{
+	struct update_param *par = &req->par.update;
+	int plane = par->plane;
+
+#ifdef VERBOSE
+	dev_dbg(blizzard.fbdev->dev,
+		"send_frame: x %d y %d w %d h %d "
+		"x_out %d y_out %d w_out %d h_out %d "
+		"color_mode %04x flags %04x planes %01x\n",
+		par->x, par->y, par->width, par->height,
+		par->out_x, par->out_y, par->out_width, par->out_height,
+		par->color_mode, par->flags, blizzard.enabled_planes);
+#endif
+	if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY)
+		disable_overlay();
+
+	if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) ||
+	     (blizzard.enabled_planes & blizzard.vid_scaled))
+		return do_full_screen_update(req);
+
+	return do_partial_update(req, plane, par->x, par->y,
+				 par->width, par->height,
+				 par->out_x, par->out_y,
+				 par->out_width, par->out_height,
+				 par->color_mode, par->bpp);
+}
+
+static void send_frame_complete(void *data)
+{
+}
+
+#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do {	\
+	req = alloc_req();			\
+	req->handler	= send_frame_handler;	\
+	req->complete	= send_frame_complete;	\
+	req->par.update.plane = plane_idx;	\
+	req->par.update.x = _x;			\
+	req->par.update.y = _y;			\
+	req->par.update.width  = _w;		\
+	req->par.update.height = _h;		\
+	req->par.update.out_x = _x_out;		\
+	req->par.update.out_y = _y_out;		\
+	req->par.update.out_width = _w_out;	\
+	req->par.update.out_height = _h_out;	\
+	req->par.update.bpp = bpp;		\
+	req->par.update.color_mode = color_mode;\
+	req->par.update.flags	  = flags;	\
+	list_add_tail(&req->entry, req_head);	\
+} while(0)
+
+static void create_req_list(int plane_idx,
+			    struct omapfb_update_window *win,
+			    struct list_head *req_head)
+{
+	struct blizzard_request *req;
+	int x = win->x;
+	int y = win->y;
+	int width = win->width;
+	int height = win->height;
+	int x_out = win->out_x;
+	int y_out = win->out_y;
+	int width_out = win->out_width;
+	int height_out = win->out_height;
+	int color_mode;
+	int bpp;
+	int flags;
+	unsigned int ystart = y;
+	unsigned int yspan = height;
+	unsigned int ystart_out = y_out;
+	unsigned int yspan_out = height_out;
+
+	flags = win->format & ~OMAPFB_FORMAT_MASK;
+	color_mode = win->format & OMAPFB_FORMAT_MASK;
+	switch (color_mode) {
+	case OMAPFB_COLOR_YUV420:
+		/* Embedded window with different color mode */
+		bpp = 12;
+		/* X, Y, height must be aligned at 2, width at 4 pixels */
+		x &= ~1;
+		y &= ~1;
+		height = yspan = height & ~1;
+		width = width & ~3;
+		break;
+	default:
+		/* Same as the plane color mode */
+		bpp = blizzard.plane[plane_idx].bpp;
+		break;
+	}
+	if (width * height * bpp / 8 > blizzard.max_transmit_size) {
+		yspan = blizzard.max_transmit_size / (width * bpp / 8);
+		yspan_out = yspan * height_out / height;
+		ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
+			 width_out, yspan_out);
+		ystart += yspan;
+		ystart_out += yspan_out;
+		yspan = height - yspan;
+		yspan_out = height_out - yspan_out;
+		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+	}
+
+	ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
+		 width_out, yspan_out);
+}
+
+static void auto_update_complete(void *data)
+{
+	if (!blizzard.stop_auto_update)
+		mod_timer(&blizzard.auto_update_timer,
+			  jiffies + BLIZZARD_AUTO_UPDATE_TIME);
+}
+
+static void blizzard_update_window_auto(unsigned long arg)
+{
+	LIST_HEAD(req_list);
+	struct blizzard_request *last;
+	struct omapfb_plane_struct *plane;
+
+	plane = blizzard.fbdev->fb_info[0]->par;
+	create_req_list(plane->idx,
+			&blizzard.auto_update_window, &req_list);
+	last = list_entry(req_list.prev, struct blizzard_request, entry);
+
+	last->complete = auto_update_complete;
+	last->complete_data = NULL;
+
+	submit_req_list(&req_list);
+}
+
+int blizzard_update_window_async(struct fb_info *fbi,
+				 struct omapfb_update_window *win,
+				 void (*complete_callback)(void *arg),
+				 void *complete_callback_data)
+{
+	LIST_HEAD(req_list);
+	struct blizzard_request *last;
+	struct omapfb_plane_struct *plane = fbi->par;
+
+	if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE))
+		return -EINVAL;
+	if (unlikely(!blizzard.te_connected &&
+		     (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC)))
+		return -EINVAL;
+
+	create_req_list(plane->idx, win, &req_list);
+	last = list_entry(req_list.prev, struct blizzard_request, entry);
+
+	last->complete = complete_callback;
+	last->complete_data = (void *)complete_callback_data;
+
+	submit_req_list(&req_list);
+
+	return 0;
+}
+EXPORT_SYMBOL(blizzard_update_window_async);
+
+static int update_full_screen(void)
+{
+	return blizzard_update_window_async(blizzard.fbdev->fb_info[0],
+				     &blizzard.auto_update_window, NULL, NULL);
+
+}
+
+static int blizzard_setup_plane(int plane, int channel_out,
+				  unsigned long offset, int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	struct plane_info *p;
+
+#ifdef VERBOSE
+	dev_dbg(blizzard.fbdev->dev,
+		    "plane %d ch_out %d offset %#08lx scr_width %d "
+		    "pos_x %d pos_y %d width %d height %d color_mode %d\n",
+		    plane, channel_out, offset, screen_width,
+		    pos_x, pos_y, width, height, color_mode);
+#endif
+	if ((unsigned)plane > OMAPFB_PLANE_NUM)
+		return -EINVAL;
+	p = &blizzard.plane[plane];
+
+	switch (color_mode) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUY422:
+		p->bpp = 16;
+		blizzard.vid_nonstd_color &= ~(1 << plane);
+		break;
+	case OMAPFB_COLOR_YUV420:
+		p->bpp = 12;
+		blizzard.vid_nonstd_color |= 1 << plane;
+		break;
+	case OMAPFB_COLOR_RGB565:
+		p->bpp = 16;
+		blizzard.vid_nonstd_color &= ~(1 << plane);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	p->offset = offset;
+	p->pos_x = pos_x;
+	p->pos_y = pos_y;
+	p->width = width;
+	p->height = height;
+	p->scr_width = screen_width;
+	if (!p->out_width)
+		p->out_width = width;
+	if (!p->out_height)
+		p->out_height = height;
+
+	p->color_mode = color_mode;
+
+	return 0;
+}
+
+static int blizzard_set_scale(int plane, int orig_w, int orig_h,
+			      int out_w, int out_h)
+{
+	struct plane_info *p = &blizzard.plane[plane];
+	int r;
+
+	dev_dbg(blizzard.fbdev->dev,
+		"plane %d orig_w %d orig_h %d out_w %d out_h %d\n",
+		plane, orig_w, orig_h, out_w, out_h);
+	if ((unsigned)plane > OMAPFB_PLANE_NUM)
+		return -ENODEV;
+
+	r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h);
+	if (r < 0)
+		return r;
+
+	p->width = orig_w;
+	p->height = orig_h;
+	p->out_width = out_w;
+	p->out_height = out_h;
+	if (orig_w == out_w && orig_h == out_h)
+		blizzard.vid_scaled &= ~(1 << plane);
+	else
+		blizzard.vid_scaled |= 1 << plane;
+
+	return 0;
+}
+
+static int blizzard_enable_plane(int plane, int enable)
+{
+	if (enable)
+		blizzard.enabled_planes |= 1 << plane;
+	else
+		blizzard.enabled_planes &= ~(1 << plane);
+
+	return 0;
+}
+
+static int sync_handler(struct blizzard_request *req)
+{
+	complete(req->par.sync);
+	return REQ_COMPLETE;
+}
+
+static void blizzard_sync(void)
+{
+	LIST_HEAD(req_list);
+	struct blizzard_request *req;
+	struct completion comp;
+
+	req = alloc_req();
+
+	req->handler = sync_handler;
+	req->complete = NULL;
+	init_completion(&comp);
+	req->par.sync = &comp;
+
+	list_add(&req->entry, &req_list);
+	submit_req_list(&req_list);
+
+	wait_for_completion(&comp);
+}
+
+
+static void blizzard_bind_client(struct omapfb_notifier_block *nb)
+{
+	if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) {
+		omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
+	}
+}
+
+static int blizzard_set_update_mode(enum omapfb_update_mode mode)
+{
+	if (unlikely(mode != OMAPFB_MANUAL_UPDATE &&
+		     mode != OMAPFB_AUTO_UPDATE &&
+		     mode != OMAPFB_UPDATE_DISABLED))
+		return -EINVAL;
+
+	if (mode == blizzard.update_mode)
+		return 0;
+
+	dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n",
+			mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
+			(mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
+
+	switch (blizzard.update_mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		blizzard.stop_auto_update = 1;
+		del_timer_sync(&blizzard.auto_update_timer);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	blizzard.update_mode = mode;
+	blizzard_sync();
+	blizzard.stop_auto_update = 0;
+
+	switch (mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		blizzard_update_window_auto(0);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	return 0;
+}
+
+static enum omapfb_update_mode blizzard_get_update_mode(void)
+{
+	return blizzard.update_mode;
+}
+
+static inline void set_extif_timings(const struct extif_timings *t)
+{
+	blizzard.extif->set_timings(t);
+}
+
+static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+	int bus_tick = blizzard.extif_clk_period * div;
+	return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 12.2 ns (regs),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 12 ns (regs),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 2*SYSCLK  (regs),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns */
+
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(blizzard.fbdev->dev,
+		  "Blizzard systim %lu ps extif_clk_period %u div %d\n",
+		  systim, blizzard.extif_clk_period, div);
+
+	t = &blizzard.reg_timings;
+	memset(t, 0, sizeof(*t));
+
+	t->clk_div = div;
+
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return blizzard.extif->convert_timings(t);
+}
+
+static int calc_lut_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns */
+
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(blizzard.fbdev->dev,
+		"Blizzard systim %lu ps extif_clk_period %u div %d\n",
+		systim, blizzard.extif_clk_period, div);
+
+	t = &blizzard.lut_timings;
+	memset(t, 0, sizeof(*t));
+
+	t->clk_div = div;
+
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(blizzard.fbdev->dev,
+		 "[lut]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(blizzard.fbdev->dev,
+		 "[lut]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return blizzard.extif->convert_timings(t);
+}
+
+static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
+{
+	int max_clk_div;
+	int div;
+
+	blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div);
+	for (div = 1; div <= max_clk_div; div++) {
+		if (calc_reg_timing(sysclk, div) == 0)
+			break;
+	}
+	if (div > max_clk_div) {
+		dev_dbg(blizzard.fbdev->dev, "reg timing failed\n");
+		goto err;
+	}
+	*extif_mem_div = div;
+
+	for (div = 1; div <= max_clk_div; div++) {
+		if (calc_lut_timing(sysclk, div) == 0)
+			break;
+	}
+
+	if (div > max_clk_div)
+		goto err;
+
+	blizzard.extif_clk_div = div;
+
+	return 0;
+err:
+	dev_err(blizzard.fbdev->dev, "can't setup timings\n");
+	return -1;
+}
+
+static void calc_blizzard_clk_rates(unsigned long ext_clk,
+				unsigned long *sys_clk, unsigned long *pix_clk)
+{
+	int pix_clk_src;
+	int sys_div = 0, sys_mul = 0;
+	int pix_div;
+
+	pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC);
+	pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
+	if ((pix_clk_src & (0x3 << 1)) == 0) {
+		/* Source is the PLL */
+		sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1;
+		sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0);
+		sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1)
+				& 0x0f)	<< 11);
+		*sys_clk = ext_clk * sys_mul / sys_div;
+	} else	/* else source is ext clk, or oscillator */
+		*sys_clk = ext_clk;
+
+	*pix_clk = *sys_clk / pix_div;			/* HZ */
+	dev_dbg(blizzard.fbdev->dev,
+		"ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
+		ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
+	dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
+		*sys_clk, *pix_clk);
+}
+
+static int setup_tearsync(unsigned long pix_clk, int extif_div)
+{
+	int hdisp, vdisp;
+	int hndp, vndp;
+	int hsw, vsw;
+	int hs, vs;
+	int hs_pol_inv, vs_pol_inv;
+	int use_hsvs, use_ndp;
+	u8  b;
+
+	hsw = blizzard_read_reg(BLIZZARD_HSW);
+	vsw = blizzard_read_reg(BLIZZARD_VSW);
+	hs_pol_inv = !(hsw & 0x80);
+	vs_pol_inv = !(vsw & 0x80);
+	hsw = hsw & 0x7f;
+	vsw = vsw & 0x3f;
+
+	hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8;
+	vdisp = blizzard_read_reg(BLIZZARD_VDISP0) +
+		((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8);
+
+	hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f;
+	vndp = blizzard_read_reg(BLIZZARD_VNDP);
+
+	/* time to transfer one pixel (16bpp) in ps */
+	blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time;
+	if (blizzard.extif->get_max_tx_rate != NULL) {
+		/* The external interface might have a rate limitation,
+		 * if so, we have to maximize our transfer rate.
+		 */
+		unsigned long min_tx_time;
+		unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate();
+
+		dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n",
+			max_tx_rate);
+		min_tx_time = 1000000000 / (max_tx_rate / 1000);  /* ps */
+		if (blizzard.pix_tx_time < min_tx_time)
+			blizzard.pix_tx_time = min_tx_time;
+	}
+
+	/* time to update one line in ps */
+	blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
+	blizzard.line_upd_time *= 1000;
+	if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time)
+		/* transfer speed too low, we might have to use both
+		 * HS and VS */
+		use_hsvs = 1;
+	else
+		/* decent transfer speed, we'll always use only VS */
+		use_hsvs = 0;
+
+	if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
+		/* HS or'ed with VS doesn't work, use the active high
+		 * TE signal based on HNDP / VNDP */
+		use_ndp = 1;
+		hs_pol_inv = 0;
+		vs_pol_inv = 0;
+		hs = hndp;
+		vs = vndp;
+	} else {
+		/* Use HS or'ed with VS as a TE signal if both are needed
+		 * or VNDP if only vsync is needed. */
+		use_ndp = 0;
+		hs = hsw;
+		vs = vsw;
+		if (!use_hsvs) {
+			hs_pol_inv = 0;
+			vs_pol_inv = 0;
+		}
+	}
+
+	hs = hs * 1000000 / (pix_clk / 1000);		  /* ps */
+	hs *= 1000;
+
+	vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */
+	vs *= 1000;
+
+	if (vs <= hs)
+		return -EDOM;
+	/* set VS to 120% of HS to minimize VS detection time */
+	vs = hs * 12 / 10;
+	/* minimize HS too */
+	if (hs > 10000)
+		hs = 10000;
+
+	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+	b &= ~0x3;
+	b |= use_hsvs ? 1 : 0;
+	b |= (use_ndp && use_hsvs) ? 0 : 2;
+	blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+
+	blizzard.vsync_only = !use_hsvs;
+
+	dev_dbg(blizzard.fbdev->dev,
+		"pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
+		pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time);
+	dev_dbg(blizzard.fbdev->dev,
+		"hs %d ps vs %d ps mode %d vsync_only %d\n",
+		hs, vs, b & 0x3, !use_hsvs);
+
+	return blizzard.extif->setup_tearsync(1, hs, vs,
+					      hs_pol_inv, vs_pol_inv,
+					      extif_div);
+}
+
+static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
+{
+	blizzard.int_ctrl->get_caps(plane, caps);
+	caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
+		OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE |
+		OMAPFB_CAPS_WINDOW_SCALE |
+		OMAPFB_CAPS_WINDOW_OVERLAY;
+	if (blizzard.te_connected)
+		caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
+	caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
+			   (1 << OMAPFB_COLOR_YUV420);
+}
+
+static void _save_regs(struct blizzard_reg_list *list, int cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++, list++) {
+		int reg;
+		for (reg = list->start; reg <= list->end; reg += 2)
+			blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg);
+	}
+}
+
+static void _restore_regs(struct blizzard_reg_list *list, int cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++, list++) {
+		int reg;
+		for (reg = list->start; reg <= list->end; reg += 2)
+			blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]);
+	}
+}
+
+static void blizzard_save_all_regs(void)
+{
+	_save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
+	_save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
+}
+
+static void blizzard_restore_pll_regs(void)
+{
+	_restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
+}
+
+static void blizzard_restore_gen_regs(void)
+{
+	_restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
+}
+
+static void blizzard_suspend(void)
+{
+	u32 l;
+	unsigned long tmo;
+
+	if (blizzard.last_color_mode) {
+		update_full_screen();
+		blizzard_sync();
+	}
+	blizzard.update_mode_before_suspend = blizzard.update_mode;
+	/* the following will disable clocks as well */
+	blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
+
+	blizzard_save_all_regs();
+
+	blizzard_stop_sdram();
+
+	l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
+	/* Standby, Sleep. We assume we use an external clock. */
+	l |= 0x03;
+	blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
+
+	tmo = jiffies + msecs_to_jiffies(100);
+	while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) {
+		if (time_after(jiffies, tmo)) {
+			dev_err(blizzard.fbdev->dev,
+				"s1d1374x: sleep timeout, stopping PLL manually\n");
+			l = blizzard_read_reg(BLIZZARD_PLL_MODE);
+			l &= ~0x03;
+			/* Disable PLL, counter function */
+			l |= 0x2;
+			blizzard_write_reg(BLIZZARD_PLL_MODE, l);
+			break;
+		}
+		msleep(1);
+	}
+
+	if (blizzard.power_down != NULL)
+		blizzard.power_down(blizzard.fbdev->dev);
+}
+
+static void blizzard_resume(void)
+{
+	u32 l;
+
+	if (blizzard.power_up != NULL)
+		blizzard.power_up(blizzard.fbdev->dev);
+
+	l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
+	/* Standby, Sleep */
+	l &= ~0x03;
+	blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
+
+	blizzard_restore_pll_regs();
+	l = blizzard_read_reg(BLIZZARD_PLL_MODE);
+	l &= ~0x03;
+	/* Enable PLL, counter function */
+	l |= 0x1;
+	blizzard_write_reg(BLIZZARD_PLL_MODE, l);
+
+	while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7)))
+		msleep(1);
+
+	blizzard_restart_sdram();
+
+	blizzard_restore_gen_regs();
+
+	/* Enable display */
+	blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01);
+
+	/* the following will enable clocks as necessary */
+	blizzard_set_update_mode(blizzard.update_mode_before_suspend);
+
+	/* Force a background update */
+	blizzard.zoom_on = 1;
+	update_full_screen();
+	blizzard_sync();
+}
+
+static int blizzard_init(struct omapfb_device *fbdev, int ext_mode,
+			 struct omapfb_mem_desc *req_vram)
+{
+	int r = 0, i;
+	u8 rev, conf;
+	unsigned long ext_clk;
+	int extif_div;
+	unsigned long sys_clk, pix_clk;
+	struct omapfb_platform_data *omapfb_conf;
+	struct blizzard_platform_data *ctrl_conf;
+
+	blizzard.fbdev = fbdev;
+
+	BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
+
+	blizzard.fbdev = fbdev;
+	blizzard.extif = fbdev->ext_if;
+	blizzard.int_ctrl = fbdev->int_ctrl;
+
+	omapfb_conf = fbdev->dev->platform_data;
+	ctrl_conf = omapfb_conf->ctrl_platform_data;
+	if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
+		dev_err(fbdev->dev, "s1d1374x: missing platform data\n");
+		r = -ENOENT;
+		goto err1;
+	}
+
+	blizzard.power_down = ctrl_conf->power_down;
+	blizzard.power_up = ctrl_conf->power_up;
+
+	spin_lock_init(&blizzard.req_lock);
+
+	if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0)
+		goto err1;
+
+	if ((r = blizzard.extif->init(fbdev)) < 0)
+		goto err2;
+
+	blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key;
+	blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key;
+	blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem;
+	blizzard_ctrl.mmap = blizzard.int_ctrl->mmap;
+
+	ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
+	if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0)
+		goto err3;
+
+	set_extif_timings(&blizzard.reg_timings);
+
+	if (blizzard.power_up != NULL)
+		blizzard.power_up(fbdev->dev);
+
+	calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk);
+
+	if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0)
+		goto err3;
+	set_extif_timings(&blizzard.reg_timings);
+
+	if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) {
+		dev_err(fbdev->dev,
+			"controller not initialized by the bootloader\n");
+		r = -ENODEV;
+		goto err3;
+	}
+
+	if (ctrl_conf->te_connected) {
+		if ((r = setup_tearsync(pix_clk, extif_div)) < 0)
+			goto err3;
+		blizzard.te_connected = 1;
+	}
+
+	rev = blizzard_read_reg(BLIZZARD_REV_CODE);
+	conf = blizzard_read_reg(BLIZZARD_CONFIG);
+
+	switch (rev & 0xfc) {
+	case 0x9c:
+		blizzard.version = BLIZZARD_VERSION_S1D13744;
+		pr_info("omapfb: s1d13744 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+		break;
+	case 0xa4:
+		blizzard.version = BLIZZARD_VERSION_S1D13745;
+		pr_info("omapfb: s1d13745 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+		break;
+	default:
+		dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n",
+			rev);
+		r = -ENODEV;
+		goto err3;
+	}
+
+	blizzard.max_transmit_size = blizzard.extif->max_transmit_size;
+
+	blizzard.update_mode = OMAPFB_UPDATE_DISABLED;
+
+	blizzard.auto_update_window.x = 0;
+	blizzard.auto_update_window.y = 0;
+	blizzard.auto_update_window.width = fbdev->panel->x_res;
+	blizzard.auto_update_window.height = fbdev->panel->y_res;
+	blizzard.auto_update_window.out_x = 0;
+	blizzard.auto_update_window.out_x = 0;
+	blizzard.auto_update_window.out_width = fbdev->panel->x_res;
+	blizzard.auto_update_window.out_height = fbdev->panel->y_res;
+	blizzard.auto_update_window.format = 0;
+
+	blizzard.screen_width = fbdev->panel->x_res;
+	blizzard.screen_height = fbdev->panel->y_res;
+
+	init_timer(&blizzard.auto_update_timer);
+	blizzard.auto_update_timer.function = blizzard_update_window_auto;
+	blizzard.auto_update_timer.data = 0;
+
+	INIT_LIST_HEAD(&blizzard.free_req_list);
+	INIT_LIST_HEAD(&blizzard.pending_req_list);
+	for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++)
+		list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list);
+	BUG_ON(i <= IRQ_REQ_POOL_SIZE);
+	sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE);
+
+	return 0;
+err3:
+	if (blizzard.power_down != NULL)
+		blizzard.power_down(fbdev->dev);
+	blizzard.extif->cleanup();
+err2:
+	blizzard.int_ctrl->cleanup();
+err1:
+	return r;
+}
+
+static void blizzard_cleanup(void)
+{
+	blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	blizzard.extif->cleanup();
+	blizzard.int_ctrl->cleanup();
+	if (blizzard.power_down != NULL)
+		blizzard.power_down(blizzard.fbdev->dev);
+}
+
+struct lcd_ctrl blizzard_ctrl = {
+	.name			= "blizzard",
+	.init			= blizzard_init,
+	.cleanup		= blizzard_cleanup,
+	.bind_client		= blizzard_bind_client,
+	.get_caps		= blizzard_get_caps,
+	.set_update_mode	= blizzard_set_update_mode,
+	.get_update_mode	= blizzard_get_update_mode,
+	.setup_plane		= blizzard_setup_plane,
+	.set_scale		= blizzard_set_scale,
+	.enable_plane		= blizzard_enable_plane,
+	.update_window		= blizzard_update_window_async,
+	.sync			= blizzard_sync,
+	.suspend		= blizzard_suspend,
+	.resume			= blizzard_resume,
+};
+
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
new file mode 100644
index 0000000..f4c2343
--- /dev/null
+++ b/drivers/video/omap/dispc.c
@@ -0,0 +1,1502 @@
+/*
+ * OMAP2 display controller support
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/arch/sram.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/board.h>
+
+#include "dispc.h"
+
+#define MODULE_NAME			"dispc"
+
+#define DSS_BASE			0x48050000
+#define DSS_SYSCONFIG			0x0010
+
+#define DISPC_BASE			0x48050400
+
+/* DISPC common */
+#define DISPC_REVISION			0x0000
+#define DISPC_SYSCONFIG			0x0010
+#define DISPC_SYSSTATUS			0x0014
+#define DISPC_IRQSTATUS			0x0018
+#define DISPC_IRQENABLE			0x001C
+#define DISPC_CONTROL			0x0040
+#define DISPC_CONFIG			0x0044
+#define DISPC_CAPABLE			0x0048
+#define DISPC_DEFAULT_COLOR0		0x004C
+#define DISPC_DEFAULT_COLOR1		0x0050
+#define DISPC_TRANS_COLOR0		0x0054
+#define DISPC_TRANS_COLOR1		0x0058
+#define DISPC_LINE_STATUS		0x005C
+#define DISPC_LINE_NUMBER		0x0060
+#define DISPC_TIMING_H			0x0064
+#define DISPC_TIMING_V			0x0068
+#define DISPC_POL_FREQ			0x006C
+#define DISPC_DIVISOR			0x0070
+#define DISPC_SIZE_DIG			0x0078
+#define DISPC_SIZE_LCD			0x007C
+
+#define DISPC_DATA_CYCLE1		0x01D4
+#define DISPC_DATA_CYCLE2		0x01D8
+#define DISPC_DATA_CYCLE3		0x01DC
+
+/* DISPC GFX plane */
+#define DISPC_GFX_BA0			0x0080
+#define DISPC_GFX_BA1			0x0084
+#define DISPC_GFX_POSITION		0x0088
+#define DISPC_GFX_SIZE			0x008C
+#define DISPC_GFX_ATTRIBUTES		0x00A0
+#define DISPC_GFX_FIFO_THRESHOLD	0x00A4
+#define DISPC_GFX_FIFO_SIZE_STATUS	0x00A8
+#define DISPC_GFX_ROW_INC		0x00AC
+#define DISPC_GFX_PIXEL_INC		0x00B0
+#define DISPC_GFX_WINDOW_SKIP		0x00B4
+#define DISPC_GFX_TABLE_BA		0x00B8
+
+/* DISPC Video plane 1/2 */
+#define DISPC_VID1_BASE			0x00BC
+#define DISPC_VID2_BASE			0x014C
+
+/* Offsets into DISPC_VID1/2_BASE */
+#define DISPC_VID_BA0			0x0000
+#define DISPC_VID_BA1			0x0004
+#define DISPC_VID_POSITION		0x0008
+#define DISPC_VID_SIZE			0x000C
+#define DISPC_VID_ATTRIBUTES		0x0010
+#define DISPC_VID_FIFO_THRESHOLD	0x0014
+#define DISPC_VID_FIFO_SIZE_STATUS	0x0018
+#define DISPC_VID_ROW_INC		0x001C
+#define DISPC_VID_PIXEL_INC		0x0020
+#define DISPC_VID_FIR			0x0024
+#define DISPC_VID_PICTURE_SIZE		0x0028
+#define DISPC_VID_ACCU0			0x002C
+#define DISPC_VID_ACCU1			0x0030
+
+/* 8 elements in 8 byte increments */
+#define DISPC_VID_FIR_COEF_H0		0x0034
+/* 8 elements in 8 byte increments */
+#define DISPC_VID_FIR_COEF_HV0		0x0038
+/* 5 elements in 4 byte increments */
+#define DISPC_VID_CONV_COEF0		0x0074
+
+#define DISPC_IRQ_FRAMEMASK		0x0001
+#define DISPC_IRQ_VSYNC			0x0002
+#define DISPC_IRQ_EVSYNC_EVEN		0x0004
+#define DISPC_IRQ_EVSYNC_ODD		0x0008
+#define DISPC_IRQ_ACBIAS_COUNT_STAT	0x0010
+#define DISPC_IRQ_PROG_LINE_NUM		0x0020
+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW	0x0040
+#define DISPC_IRQ_GFX_END_WIN		0x0080
+#define DISPC_IRQ_PAL_GAMMA_MASK	0x0100
+#define DISPC_IRQ_OCP_ERR		0x0200
+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW	0x0400
+#define DISPC_IRQ_VID1_END_WIN		0x0800
+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW	0x1000
+#define DISPC_IRQ_VID2_END_WIN		0x2000
+#define DISPC_IRQ_SYNC_LOST		0x4000
+
+#define DISPC_IRQ_MASK_ALL		0x7fff
+
+#define DISPC_IRQ_MASK_ERROR		(DISPC_IRQ_GFX_FIFO_UNDERFLOW |	\
+					     DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+					     DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+					     DISPC_IRQ_SYNC_LOST)
+
+#define RFBI_CONTROL			0x48050040
+
+#define MAX_PALETTE_SIZE		(256 * 16)
+
+#define FLD_MASK(pos, len)	(((1 << len) - 1) << pos)
+
+#define MOD_REG_FLD(reg, mask, val) \
+	dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
+
+#define OMAP2_SRAM_START		0x40200000
+/* Maximum size, in reality this is smaller if SRAM is partially locked. */
+#define OMAP2_SRAM_SIZE			0xa0000		/* 640k */
+
+/* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */
+#define DISPC_MEMTYPE_NUM		2
+
+#define RESMAP_SIZE(_page_cnt)						\
+	((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
+#define RESMAP_PTR(_res_map, _page_nr)					\
+	(((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
+#define RESMAP_MASK(_page_nr)						\
+	(1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
+
+struct resmap {
+	unsigned long	start;
+	unsigned	page_cnt;
+	unsigned long	*map;
+};
+
+static struct {
+	u32		base;
+
+	struct omapfb_mem_desc	mem_desc;
+	struct resmap		*res_map[DISPC_MEMTYPE_NUM];
+	atomic_t		map_count[OMAPFB_PLANE_NUM];
+
+	dma_addr_t	palette_paddr;
+	void		*palette_vaddr;
+
+	int		ext_mode;
+
+	unsigned long	enabled_irqs;
+	void		(*irq_callback)(void *);
+	void		*irq_callback_data;
+	struct completion	frame_done;
+
+	int		fir_hinc[OMAPFB_PLANE_NUM];
+	int		fir_vinc[OMAPFB_PLANE_NUM];
+
+	struct clk	*dss_ick, *dss1_fck;
+	struct clk	*dss_54m_fck;
+
+	enum omapfb_update_mode	update_mode;
+	struct omapfb_device	*fbdev;
+
+	struct omapfb_color_key	color_key;
+} dispc;
+
+static void enable_lcd_clocks(int enable);
+
+static void inline dispc_write_reg(int idx, u32 val)
+{
+	__raw_writel(val, dispc.base + idx);
+}
+
+static u32 inline dispc_read_reg(int idx)
+{
+	u32 l = __raw_readl(dispc.base + idx);
+	return l;
+}
+
+/* Select RFBI or bypass mode */
+static void enable_rfbi_mode(int enable)
+{
+	u32 l;
+
+	l = dispc_read_reg(DISPC_CONTROL);
+	/* Enable RFBI, GPIO0/1 */
+	l &= ~((1 << 11) | (1 << 15) | (1 << 16));
+	l |= enable ? (1 << 11) : 0;
+	/* RFBI En: GPIO0/1=10  RFBI Dis: GPIO0/1=11 */
+	l |= 1 << 15;
+	l |= enable ? 0 : (1 << 16);
+	dispc_write_reg(DISPC_CONTROL, l);
+
+	/* Set bypass mode in RFBI module */
+	l = __raw_readl(io_p2v(RFBI_CONTROL));
+	l |= enable ? 0 : (1 << 1);
+	__raw_writel(l, io_p2v(RFBI_CONTROL));
+}
+
+static void set_lcd_data_lines(int data_lines)
+{
+	u32 l;
+	int code = 0;
+
+	switch (data_lines) {
+	case 12:
+		code = 0;
+		break;
+	case 16:
+		code = 1;
+		break;
+	case 18:
+		code = 2;
+		break;
+	case 24:
+		code = 3;
+		break;
+	default:
+		BUG();
+	}
+
+	l = dispc_read_reg(DISPC_CONTROL);
+	l &= ~(0x03 << 8);
+	l |= code << 8;
+	dispc_write_reg(DISPC_CONTROL, l);
+}
+
+static void set_load_mode(int mode)
+{
+	BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |
+			DISPC_LOAD_CLUT_ONCE_FRAME));
+	MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);
+}
+
+void omap_dispc_set_lcd_size(int x, int y)
+{
+	BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+			((y - 1) << 16) | (x - 1));
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_set_lcd_size);
+
+void omap_dispc_set_digit_size(int x, int y)
+{
+	BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+			((y - 1) << 16) | (x - 1));
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_set_digit_size);
+
+static void setup_plane_fifo(int plane, int ext_mode)
+{
+	const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
+				DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,
+			        DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };
+	const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+				DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,
+				DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };
+	int low, high;
+	u32 l;
+
+	BUG_ON(plane > 2);
+
+	l = dispc_read_reg(fsz_reg[plane]);
+	l &= FLD_MASK(0, 9);
+	if (ext_mode) {
+		low = l * 3 / 4;
+		high = l;
+	} else {
+		low = l / 4;
+		high = l * 3 / 4;
+	}
+	MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9),
+			(high << 16) | low);
+}
+
+void omap_dispc_enable_lcd_out(int enable)
+{
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_lcd_out);
+
+void omap_dispc_enable_digit_out(int enable)
+{
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_digit_out);
+
+static inline int _setup_plane(int plane, int channel_out,
+				  u32 paddr, int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
+				DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+			        DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+	const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,
+				DISPC_VID2_BASE + DISPC_VID_BA0 };
+	const u32 ps_reg[] = { DISPC_GFX_POSITION,
+				DISPC_VID1_BASE + DISPC_VID_POSITION,
+				DISPC_VID2_BASE + DISPC_VID_POSITION };
+	const u32 sz_reg[] = { DISPC_GFX_SIZE,
+				DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE,
+				DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE };
+	const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
+				DISPC_VID1_BASE + DISPC_VID_ROW_INC,
+			        DISPC_VID2_BASE + DISPC_VID_ROW_INC };
+	const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
+				DISPC_VID2_BASE + DISPC_VID_SIZE };
+
+	int chout_shift, burst_shift;
+	int chout_val;
+	int color_code;
+	int bpp;
+	int cconv_en;
+	int set_vsize;
+	u32 l;
+
+#ifdef VERBOSE
+	dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d"
+		    " pos_x %d pos_y %d width %d height %d color_mode %d\n",
+		    plane, channel_out, paddr, screen_width, pos_x, pos_y,
+		    width, height, color_mode);
+#endif
+
+	set_vsize = 0;
+	switch (plane) {
+	case OMAPFB_PLANE_GFX:
+		burst_shift = 6;
+		chout_shift = 8;
+		break;
+	case OMAPFB_PLANE_VID1:
+	case OMAPFB_PLANE_VID2:
+		burst_shift = 14;
+		chout_shift = 16;
+		set_vsize = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (channel_out) {
+	case OMAPFB_CHANNEL_OUT_LCD:
+		chout_val = 0;
+		break;
+	case OMAPFB_CHANNEL_OUT_DIGIT:
+		chout_val = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cconv_en = 0;
+	switch (color_mode) {
+	case OMAPFB_COLOR_RGB565:
+		color_code = DISPC_RGB_16_BPP;
+		bpp = 16;
+		break;
+	case OMAPFB_COLOR_YUV422:
+		if (plane == 0)
+			return -EINVAL;
+		color_code = DISPC_UYVY_422;
+		cconv_en = 1;
+		bpp = 16;
+		break;
+	case OMAPFB_COLOR_YUY422:
+		if (plane == 0)
+			return -EINVAL;
+		color_code = DISPC_YUV2_422;
+		cconv_en = 1;
+		bpp = 16;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	l = dispc_read_reg(at_reg[plane]);
+
+	l &= ~(0x0f << 1);
+	l |= color_code << 1;
+	l &= ~(1 << 9);
+	l |= cconv_en << 9;
+
+	l &= ~(0x03 << burst_shift);
+	l |= DISPC_BURST_8x32 << burst_shift;
+
+	l &= ~(1 << chout_shift);
+	l |= chout_val << chout_shift;
+
+	dispc_write_reg(at_reg[plane], l);
+
+	dispc_write_reg(ba_reg[plane], paddr);
+	MOD_REG_FLD(ps_reg[plane],
+		    FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);
+
+	MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
+			((height - 1) << 16) | (width - 1));
+
+	if (set_vsize) {
+		/* Set video size if set_scale hasn't set it */
+		if (!dispc.fir_vinc[plane])
+			MOD_REG_FLD(vs_reg[plane],
+				FLD_MASK(16, 11), (height - 1) << 16);
+		if (!dispc.fir_hinc[plane])
+			MOD_REG_FLD(vs_reg[plane],
+				FLD_MASK(0, 11), width - 1);
+	}
+
+	dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
+
+	return height * screen_width * bpp / 8;
+}
+
+static int omap_dispc_setup_plane(int plane, int channel_out,
+				  unsigned long offset,
+				  int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	u32 paddr;
+	int r;
+
+	if ((unsigned)plane > dispc.mem_desc.region_cnt)
+		return -EINVAL;
+	paddr = dispc.mem_desc.region[plane].paddr + offset;
+	enable_lcd_clocks(1);
+	r = _setup_plane(plane, channel_out, paddr,
+			screen_width,
+			pos_x, pos_y, width, height, color_mode);
+	enable_lcd_clocks(0);
+	return r;
+}
+
+static void write_firh_reg(int plane, int reg, u32 value)
+{
+	u32 base;
+
+	if (plane == 1)
+		base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0;
+	else
+		base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0;
+	dispc_write_reg(base + reg * 8,	value);
+}
+
+static void write_firhv_reg(int plane, int reg, u32 value)
+{
+	u32 base;
+
+	if (plane == 1)
+		base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0;
+	else
+		base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0;
+	dispc_write_reg(base + reg * 8,	value);
+}
+
+static void set_upsampling_coef_table(int plane)
+{
+	const u32 coef[][2] = {
+		{ 0x00800000, 0x00800000 },
+		{ 0x0D7CF800, 0x037B02FF },
+		{ 0x1E70F5FF, 0x0C6F05FE },
+		{ 0x335FF5FE, 0x205907FB },
+		{ 0xF74949F7, 0x00404000 },
+		{ 0xF55F33FB, 0x075920FE },
+		{ 0xF5701EFE, 0x056F0CFF },
+		{ 0xF87C0DFF, 0x027B0300 },
+	};
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		write_firh_reg(plane, i, coef[i][0]);
+		write_firhv_reg(plane, i, coef[i][1]);
+	}
+}
+
+static int omap_dispc_set_scale(int plane,
+				int orig_width, int orig_height,
+				int out_width, int out_height)
+{
+	const u32 at_reg[]  = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+				DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+	const u32 vs_reg[]  = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
+				DISPC_VID2_BASE + DISPC_VID_SIZE };
+	const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR,
+				DISPC_VID2_BASE + DISPC_VID_FIR };
+
+	u32 l;
+	int fir_hinc;
+	int fir_vinc;
+
+	if ((unsigned)plane > OMAPFB_PLANE_NUM)
+		return -ENODEV;
+
+	if (plane == OMAPFB_PLANE_GFX &&
+	    (out_width != orig_width || out_height != orig_height))
+		return -EINVAL;
+
+	enable_lcd_clocks(1);
+	if (orig_width < out_width) {
+		/*
+		 * Upsampling.
+		 * Currently you can only scale both dimensions in one way.
+		 */
+		if (orig_height > out_height ||
+		    orig_width * 8 < out_width ||
+		    orig_height * 8 < out_height) {
+			enable_lcd_clocks(0);
+			return -EINVAL;
+		}
+		set_upsampling_coef_table(plane);
+	} else if (orig_width > out_width) {
+		/* Downsampling not yet supported
+		*/
+
+		enable_lcd_clocks(0);
+		return -EINVAL;
+	}
+	if (!orig_width || orig_width == out_width)
+		fir_hinc = 0;
+	else
+		fir_hinc = 1024 * orig_width / out_width;
+	if (!orig_height || orig_height == out_height)
+		fir_vinc = 0;
+	else
+		fir_vinc = 1024 * orig_height / out_height;
+	dispc.fir_hinc[plane] = fir_hinc;
+	dispc.fir_vinc[plane] = fir_vinc;
+
+	MOD_REG_FLD(fir_reg[plane],
+		    FLD_MASK(16, 12) | FLD_MASK(0, 12),
+		    ((fir_vinc & 4095) << 16) |
+		    (fir_hinc & 4095));
+
+	dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
+		"orig_height %d fir_hinc  %d fir_vinc %d\n",
+		out_width, out_height, orig_width, orig_height,
+		fir_hinc, fir_vinc);
+
+	MOD_REG_FLD(vs_reg[plane],
+		    FLD_MASK(16, 11) | FLD_MASK(0, 11),
+		    ((out_height - 1) << 16) | (out_width - 1));
+
+	l = dispc_read_reg(at_reg[plane]);
+	l &= ~(0x03 << 5);
+	l |= fir_hinc ? (1 << 5) : 0;
+	l |= fir_vinc ? (1 << 6) : 0;
+	dispc_write_reg(at_reg[plane], l);
+
+	enable_lcd_clocks(0);
+	return 0;
+}
+
+static int omap_dispc_enable_plane(int plane, int enable)
+{
+	const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
+				DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+				DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+	if ((unsigned int)plane > dispc.mem_desc.region_cnt)
+		return -EINVAL;
+
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
+	enable_lcd_clocks(0);
+
+	return 0;
+}
+
+static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
+{
+	u32 df_reg, tr_reg;
+	int shift, val;
+
+	switch (ck->channel_out) {
+	case OMAPFB_CHANNEL_OUT_LCD:
+		df_reg = DISPC_DEFAULT_COLOR0;
+		tr_reg = DISPC_TRANS_COLOR0;
+		shift = 10;
+		break;
+	case OMAPFB_CHANNEL_OUT_DIGIT:
+		df_reg = DISPC_DEFAULT_COLOR1;
+		tr_reg = DISPC_TRANS_COLOR1;
+		shift = 12;
+		break;
+	default:
+		return -EINVAL;
+	}
+	switch (ck->key_type) {
+	case OMAPFB_COLOR_KEY_DISABLED:
+		val = 0;
+		break;
+	case OMAPFB_COLOR_KEY_GFX_DST:
+		val = 1;
+		break;
+	case OMAPFB_COLOR_KEY_VID_SRC:
+		val = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+	enable_lcd_clocks(1);
+	MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift);
+
+	if (val != 0)
+		dispc_write_reg(tr_reg, ck->trans_key);
+	dispc_write_reg(df_reg, ck->background);
+	enable_lcd_clocks(0);
+
+	dispc.color_key = *ck;
+
+	return 0;
+}
+
+static int omap_dispc_get_color_key(struct omapfb_color_key *ck)
+{
+	*ck = dispc.color_key;
+	return 0;
+}
+
+static void load_palette(void)
+{
+}
+
+static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
+{
+	int r = 0;
+
+	if (mode != dispc.update_mode) {
+		switch (mode) {
+		case OMAPFB_AUTO_UPDATE:
+		case OMAPFB_MANUAL_UPDATE:
+			enable_lcd_clocks(1);
+			omap_dispc_enable_lcd_out(1);
+			dispc.update_mode = mode;
+			break;
+		case OMAPFB_UPDATE_DISABLED:
+			init_completion(&dispc.frame_done);
+			omap_dispc_enable_lcd_out(0);
+			if (!wait_for_completion_timeout(&dispc.frame_done,
+					msecs_to_jiffies(500))) {
+				dev_err(dispc.fbdev->dev,
+					 "timeout waiting for FRAME DONE\n");
+			}
+			dispc.update_mode = mode;
+			enable_lcd_clocks(0);
+			break;
+		default:
+			r = -EINVAL;
+		}
+	}
+
+	return r;
+}
+
+static void omap_dispc_get_caps(int plane, struct omapfb_caps *caps)
+{
+	caps->ctrl |= OMAPFB_CAPS_PLANE_RELOCATE_MEM;
+	if (plane > 0)
+		caps->ctrl |= OMAPFB_CAPS_PLANE_SCALE;
+	caps->plane_color |= (1 << OMAPFB_COLOR_RGB565) |
+			     (1 << OMAPFB_COLOR_YUV422) |
+			     (1 << OMAPFB_COLOR_YUY422);
+	if (plane == 0)
+		caps->plane_color |= (1 << OMAPFB_COLOR_CLUT_8BPP) |
+				     (1 << OMAPFB_COLOR_CLUT_4BPP) |
+				     (1 << OMAPFB_COLOR_CLUT_2BPP) |
+				     (1 << OMAPFB_COLOR_CLUT_1BPP) |
+				     (1 << OMAPFB_COLOR_RGB444);
+}
+
+static enum omapfb_update_mode omap_dispc_get_update_mode(void)
+{
+	return dispc.update_mode;
+}
+
+static void setup_color_conv_coef(void)
+{
+	u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11);
+	int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0;
+	int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0;
+	int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES;
+	int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES;
+	const struct color_conv_coef {
+		int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
+		int  full_range;
+	}  ctbl_bt601_5 = {
+		    298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
+	};
+	const struct color_conv_coef *ct;
+#define CVAL(x, y)	(((x & 2047) << 16) | (y & 2047))
+
+	ct = &ctbl_bt601_5;
+
+	MOD_REG_FLD(cf1_reg,		mask,	CVAL(ct->rcr, ct->ry));
+	MOD_REG_FLD(cf1_reg + 4,	mask,	CVAL(ct->gy,  ct->rcb));
+	MOD_REG_FLD(cf1_reg + 8,	mask,	CVAL(ct->gcb, ct->gcr));
+	MOD_REG_FLD(cf1_reg + 12,	mask,	CVAL(ct->bcr, ct->by));
+	MOD_REG_FLD(cf1_reg + 16,	mask,	CVAL(0,	      ct->bcb));
+
+	MOD_REG_FLD(cf2_reg,		mask,	CVAL(ct->rcr, ct->ry));
+	MOD_REG_FLD(cf2_reg + 4,	mask,	CVAL(ct->gy,  ct->rcb));
+	MOD_REG_FLD(cf2_reg + 8,	mask,	CVAL(ct->gcb, ct->gcr));
+	MOD_REG_FLD(cf2_reg + 12,	mask,	CVAL(ct->bcr, ct->by));
+	MOD_REG_FLD(cf2_reg + 16,	mask,	CVAL(0,	      ct->bcb));
+#undef CVAL
+
+	MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range);
+	MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range);
+}
+
+static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
+{
+	unsigned long fck, lck;
+
+	*lck_div = 1;
+	pck = max(1, pck);
+	fck = clk_get_rate(dispc.dss1_fck);
+	lck = fck;
+	*pck_div = (lck + pck - 1) / pck;
+	if (is_tft)
+		*pck_div = max(2, *pck_div);
+	else
+		*pck_div = max(3, *pck_div);
+	if (*pck_div > 255) {
+		*pck_div = 255;
+		lck = pck * *pck_div;
+		*lck_div = fck / lck;
+		BUG_ON(*lck_div < 1);
+		if (*lck_div > 255) {
+			*lck_div = 255;
+			dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n",
+				 pck / 1000);
+		}
+	}
+}
+
+static void set_lcd_tft_mode(int enable)
+{
+	u32 mask;
+
+	mask = 1 << 3;
+	MOD_REG_FLD(DISPC_CONTROL, mask, enable ? mask : 0);
+}
+
+static void set_lcd_timings(void)
+{
+	u32 l;
+	int lck_div, pck_div;
+	struct lcd_panel *panel = dispc.fbdev->panel;
+	int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+	unsigned long fck;
+
+	l = dispc_read_reg(DISPC_TIMING_H);
+	l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
+	l |= ( max(1, (min(64,  panel->hsw))) - 1 ) << 0;
+	l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8;
+	l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20;
+	dispc_write_reg(DISPC_TIMING_H, l);
+
+	l = dispc_read_reg(DISPC_TIMING_V);
+	l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
+	l |= ( max(1, (min(64,  panel->vsw))) - 1 ) << 0;
+	l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8;
+	l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20;
+	dispc_write_reg(DISPC_TIMING_V, l);
+
+	l = dispc_read_reg(DISPC_POL_FREQ);
+	l &= ~FLD_MASK(12, 6);
+	l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12;
+	l |= panel->acb & 0xff;
+	dispc_write_reg(DISPC_POL_FREQ, l);
+
+	calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div);
+
+	l = dispc_read_reg(DISPC_DIVISOR);
+	l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
+	l |= (lck_div << 16) | (pck_div << 0);
+	dispc_write_reg(DISPC_DIVISOR, l);
+
+	/* update panel info with the exact clock */
+	fck = clk_get_rate(dispc.dss1_fck);
+	panel->pixel_clock = fck / lck_div / pck_div / 1000;
+}
+
+int omap_dispc_request_irq(void (*callback)(void *data), void *data)
+{
+	int r = 0;
+
+	BUG_ON(callback == NULL);
+
+	if (dispc.irq_callback)
+		r = -EBUSY;
+	else {
+		dispc.irq_callback = callback;
+		dispc.irq_callback_data = data;
+	}
+
+	return r;
+}
+EXPORT_SYMBOL(omap_dispc_request_irq);
+
+void omap_dispc_enable_irqs(int irq_mask)
+{
+	enable_lcd_clocks(1);
+	dispc.enabled_irqs = irq_mask;
+	irq_mask |= DISPC_IRQ_MASK_ERROR;
+	MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_irqs);
+
+void omap_dispc_disable_irqs(int irq_mask)
+{
+	enable_lcd_clocks(1);
+	dispc.enabled_irqs &= ~irq_mask;
+	irq_mask &= ~DISPC_IRQ_MASK_ERROR;
+	MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_disable_irqs);
+
+void omap_dispc_free_irq(void)
+{
+	enable_lcd_clocks(1);
+	omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL);
+	dispc.irq_callback = NULL;
+	dispc.irq_callback_data = NULL;
+	enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_free_irq);
+
+static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
+{
+	u32 stat = dispc_read_reg(DISPC_IRQSTATUS);
+
+	if (stat & DISPC_IRQ_FRAMEMASK)
+		complete(&dispc.frame_done);
+
+	if (stat & DISPC_IRQ_MASK_ERROR) {
+		if (printk_ratelimit()) {
+			dev_err(dispc.fbdev->dev, "irq error status %04x\n",
+				stat & 0x7fff);
+		}
+	}
+
+	if ((stat & dispc.enabled_irqs) && dispc.irq_callback)
+		dispc.irq_callback(dispc.irq_callback_data);
+
+	dispc_write_reg(DISPC_IRQSTATUS, stat);
+
+	return IRQ_HANDLED;
+}
+
+static int get_dss_clocks(void)
+{
+	if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
+		dev_err(dispc.fbdev->dev, "can't get dss_ick");
+		return PTR_ERR(dispc.dss_ick);
+	}
+
+	if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
+		dev_err(dispc.fbdev->dev, "can't get dss1_fck");
+		clk_put(dispc.dss_ick);
+		return PTR_ERR(dispc.dss1_fck);
+	}
+
+	if (IS_ERR((dispc.dss_54m_fck =
+				clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
+		dev_err(dispc.fbdev->dev, "can't get dss_54m_fck");
+		clk_put(dispc.dss_ick);
+		clk_put(dispc.dss1_fck);
+		return PTR_ERR(dispc.dss_54m_fck);
+	}
+
+	return 0;
+}
+
+static void put_dss_clocks(void)
+{
+	clk_put(dispc.dss_54m_fck);
+	clk_put(dispc.dss1_fck);
+	clk_put(dispc.dss_ick);
+}
+
+static void enable_lcd_clocks(int enable)
+{
+	if (enable)
+		clk_enable(dispc.dss1_fck);
+	else
+		clk_disable(dispc.dss1_fck);
+}
+
+static void enable_interface_clocks(int enable)
+{
+	if (enable)
+		clk_enable(dispc.dss_ick);
+	else
+		clk_disable(dispc.dss_ick);
+}
+
+static void enable_digit_clocks(int enable)
+{
+	if (enable)
+		clk_enable(dispc.dss_54m_fck);
+	else
+		clk_disable(dispc.dss_54m_fck);
+}
+
+static void omap_dispc_suspend(void)
+{
+	if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
+		init_completion(&dispc.frame_done);
+		omap_dispc_enable_lcd_out(0);
+		if (!wait_for_completion_timeout(&dispc.frame_done,
+				msecs_to_jiffies(500))) {
+			dev_err(dispc.fbdev->dev,
+				"timeout waiting for FRAME DONE\n");
+		}
+		enable_lcd_clocks(0);
+	}
+}
+
+static void omap_dispc_resume(void)
+{
+	if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
+		enable_lcd_clocks(1);
+		if (!dispc.ext_mode) {
+			set_lcd_timings();
+			load_palette();
+		}
+		omap_dispc_enable_lcd_out(1);
+	}
+}
+
+
+static int omap_dispc_update_window(struct fb_info *fbi,
+				 struct omapfb_update_window *win,
+				 void (*complete_callback)(void *arg),
+				 void *complete_callback_data)
+{
+	return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0;
+}
+
+static int mmap_kern(struct omapfb_mem_region *region)
+{
+	struct vm_struct	*kvma;
+	struct vm_area_struct	vma;
+	pgprot_t		pgprot;
+	unsigned long		vaddr;
+
+	kvma = get_vm_area(region->size, VM_IOREMAP);
+	if (kvma == NULL) {
+		dev_err(dispc.fbdev->dev, "can't get kernel vm area\n");
+		return -ENOMEM;
+	}
+	vma.vm_mm = &init_mm;
+
+	vaddr = (unsigned long)kvma->addr;
+
+	pgprot = pgprot_writecombine(pgprot_kernel);
+	vma.vm_start = vaddr;
+	vma.vm_end = vaddr + region->size;
+	if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT,
+			   region->size, pgprot) < 0) {
+		dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n");
+		return -EAGAIN;
+	}
+	region->vaddr = (void *)vaddr;
+
+	return 0;
+}
+
+static void mmap_user_open(struct vm_area_struct *vma)
+{
+	int plane = (int)vma->vm_private_data;
+
+	atomic_inc(&dispc.map_count[plane]);
+}
+
+static void mmap_user_close(struct vm_area_struct *vma)
+{
+	int plane = (int)vma->vm_private_data;
+
+	atomic_dec(&dispc.map_count[plane]);
+}
+
+static struct vm_operations_struct mmap_user_ops = {
+	.open = mmap_user_open,
+	.close = mmap_user_close,
+};
+
+static int omap_dispc_mmap_user(struct fb_info *info,
+				struct vm_area_struct *vma)
+{
+	struct omapfb_plane_struct *plane = info->par;
+	unsigned long off;
+	unsigned long start;
+	u32 len;
+
+	if (vma->vm_end - vma->vm_start == 0)
+		return 0;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	off = vma->vm_pgoff << PAGE_SHIFT;
+
+	start = info->fix.smem_start;
+	len = info->fix.smem_len;
+	if (off >= len)
+		return -EINVAL;
+	if ((vma->vm_end - vma->vm_start + off) > len)
+		return -EINVAL;
+	off += start;
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	vma->vm_ops = &mmap_user_ops;
+	vma->vm_private_data = (void *)plane->idx;
+	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
+		return -EAGAIN;
+	/* vm_ops.open won't be called for mmap itself. */
+	atomic_inc(&dispc.map_count[plane->idx]);
+	return 0;
+}
+
+static void unmap_kern(struct omapfb_mem_region *region)
+{
+	vunmap(region->vaddr);
+}
+
+static int alloc_palette_ram(void)
+{
+	dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
+		MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL);
+	if (dispc.palette_vaddr == NULL) {
+		dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void free_palette_ram(void)
+{
+	dma_free_writecombine(dispc.fbdev->dev, MAX_PALETTE_SIZE,
+			dispc.palette_vaddr, dispc.palette_paddr);
+}
+
+static int alloc_fbmem(struct omapfb_mem_region *region)
+{
+	region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
+			region->size, &region->paddr, GFP_KERNEL);
+
+	if (region->vaddr == NULL) {
+		dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void free_fbmem(struct omapfb_mem_region *region)
+{
+	dma_free_writecombine(dispc.fbdev->dev, region->size,
+			      region->vaddr, region->paddr);
+}
+
+static struct resmap *init_resmap(unsigned long start, size_t size)
+{
+	unsigned page_cnt;
+	struct resmap *res_map;
+
+	page_cnt = PAGE_ALIGN(size) / PAGE_SIZE;
+	res_map =
+	    kzalloc(sizeof(struct resmap) + RESMAP_SIZE(page_cnt), GFP_KERNEL);
+	if (res_map == NULL)
+		return NULL;
+	res_map->start = start;
+	res_map->page_cnt = page_cnt;
+	res_map->map = (unsigned long *)(res_map + 1);
+	return res_map;
+}
+
+static void cleanup_resmap(struct resmap *res_map)
+{
+	kfree(res_map);
+}
+
+static inline int resmap_mem_type(unsigned long start)
+{
+	if (start >= OMAP2_SRAM_START &&
+	    start < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
+		return OMAPFB_MEMTYPE_SRAM;
+	else
+		return OMAPFB_MEMTYPE_SDRAM;
+}
+
+static inline int resmap_page_reserved(struct resmap *res_map, unsigned page_nr)
+{
+	return *RESMAP_PTR(res_map, page_nr) & RESMAP_MASK(page_nr) ? 1 : 0;
+}
+
+static inline void resmap_reserve_page(struct resmap *res_map, unsigned page_nr)
+{
+	BUG_ON(resmap_page_reserved(res_map, page_nr));
+	*RESMAP_PTR(res_map, page_nr) |= RESMAP_MASK(page_nr);
+}
+
+static inline void resmap_free_page(struct resmap *res_map, unsigned page_nr)
+{
+	BUG_ON(!resmap_page_reserved(res_map, page_nr));
+	*RESMAP_PTR(res_map, page_nr) &= ~RESMAP_MASK(page_nr);
+}
+
+static void resmap_reserve_region(unsigned long start, size_t size)
+{
+
+	struct resmap	*res_map;
+	unsigned	start_page;
+	unsigned	end_page;
+	int		mtype;
+	unsigned	i;
+
+	mtype = resmap_mem_type(start);
+	res_map = dispc.res_map[mtype];
+	dev_dbg(dispc.fbdev->dev, "reserve mem type %d start %08lx size %d\n",
+		mtype, start, size);
+	start_page = (start - res_map->start) / PAGE_SIZE;
+	end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
+	for (i = start_page; i < end_page; i++)
+		resmap_reserve_page(res_map, i);
+}
+
+static void resmap_free_region(unsigned long start, size_t size)
+{
+	struct resmap	*res_map;
+	unsigned	start_page;
+	unsigned	end_page;
+	unsigned	i;
+	int		mtype;
+
+	mtype = resmap_mem_type(start);
+	res_map = dispc.res_map[mtype];
+	dev_dbg(dispc.fbdev->dev, "free mem type %d start %08lx size %d\n",
+		mtype, start, size);
+	start_page = (start - res_map->start) / PAGE_SIZE;
+	end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
+	for (i = start_page; i < end_page; i++)
+		resmap_free_page(res_map, i);
+}
+
+static unsigned long resmap_alloc_region(int mtype, size_t size)
+{
+	unsigned i;
+	unsigned total;
+	unsigned start_page;
+	unsigned long start;
+	struct resmap *res_map = dispc.res_map[mtype];
+
+	BUG_ON(mtype >= DISPC_MEMTYPE_NUM || res_map == NULL || !size);
+
+	size = PAGE_ALIGN(size) / PAGE_SIZE;
+	start_page = 0;
+	total = 0;
+	for (i = 0; i < res_map->page_cnt; i++) {
+		if (resmap_page_reserved(res_map, i)) {
+			start_page = i + 1;
+			total = 0;
+		} else if (++total == size)
+			break;
+	}
+	if (total < size)
+		return 0;
+
+	start = res_map->start + start_page * PAGE_SIZE;
+	resmap_reserve_region(start, size * PAGE_SIZE);
+
+	return start;
+}
+
+/* Note that this will only work for user mappings, we don't deal with
+ * kernel mappings here, so fbcon will keep using the old region.
+ */
+static int omap_dispc_setup_mem(int plane, size_t size, int mem_type,
+				unsigned long *paddr)
+{
+	struct omapfb_mem_region *rg;
+	unsigned long new_addr = 0;
+
+	if ((unsigned)plane > dispc.mem_desc.region_cnt)
+		return -EINVAL;
+	if (mem_type >= DISPC_MEMTYPE_NUM)
+		return -EINVAL;
+	if (dispc.res_map[mem_type] == NULL)
+		return -ENOMEM;
+	rg = &dispc.mem_desc.region[plane];
+	if (size == rg->size && mem_type == rg->type)
+		return 0;
+	if (atomic_read(&dispc.map_count[plane]))
+		return -EBUSY;
+	if (rg->size != 0)
+		resmap_free_region(rg->paddr, rg->size);
+	if (size != 0) {
+		new_addr = resmap_alloc_region(mem_type, size);
+		if (!new_addr) {
+			/* Reallocate old region. */
+			resmap_reserve_region(rg->paddr, rg->size);
+			return -ENOMEM;
+		}
+	}
+	rg->paddr = new_addr;
+	rg->size = size;
+	rg->type = mem_type;
+
+	*paddr = new_addr;
+
+	return 0;
+}
+
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
+{
+	struct omapfb_mem_region	*rg;
+	int i;
+	int r;
+	unsigned long			mem_start[DISPC_MEMTYPE_NUM];
+	unsigned long			mem_end[DISPC_MEMTYPE_NUM];
+
+	if (!req_md->region_cnt) {
+		dev_err(dispc.fbdev->dev, "no memory regions defined\n");
+		return -ENOENT;
+	}
+
+	rg = &req_md->region[0];
+	memset(mem_start, 0xff, sizeof(mem_start));
+	memset(mem_end, 0, sizeof(mem_end));
+
+	for (i = 0; i < req_md->region_cnt; i++, rg++) {
+		int mtype;
+		if (rg->paddr) {
+			rg->alloc = 0;
+			if (rg->vaddr == NULL) {
+				rg->map = 1;
+				if ((r = mmap_kern(rg)) < 0)
+					return r;
+			}
+		} else {
+			if (rg->type != OMAPFB_MEMTYPE_SDRAM) {
+				dev_err(dispc.fbdev->dev,
+					"unsupported memory type\n");
+				return -EINVAL;
+			}
+			rg->alloc = rg->map = 1;
+			if ((r = alloc_fbmem(rg)) < 0)
+				return r;
+		}
+		mtype = rg->type;
+
+		if (rg->paddr < mem_start[mtype])
+			mem_start[mtype] = rg->paddr;
+		if (rg->paddr + rg->size > mem_end[mtype])
+			mem_end[mtype] = rg->paddr + rg->size;
+	}
+
+	for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+		unsigned long start;
+		size_t size;
+		if (mem_end[i] == 0)
+			continue;
+		start = mem_start[i];
+		size = mem_end[i] - start;
+		dispc.res_map[i] = init_resmap(start, size);
+		r = -ENOMEM;
+		if (dispc.res_map[i] == NULL)
+			goto fail;
+		/* Initial state is that everything is reserved. This
+		 * includes possible holes as well, which will never be
+		 * freed.
+		 */
+		resmap_reserve_region(start, size);
+	}
+
+	dispc.mem_desc = *req_md;
+
+	return 0;
+fail:
+	for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+		if (dispc.res_map[i] != NULL)
+			cleanup_resmap(dispc.res_map[i]);
+	}
+	return r;
+}
+
+static void cleanup_fbmem(void)
+{
+	struct omapfb_mem_region *rg;
+	int i;
+
+	for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+		if (dispc.res_map[i] != NULL)
+			cleanup_resmap(dispc.res_map[i]);
+	}
+	rg = &dispc.mem_desc.region[0];
+	for (i = 0; i < dispc.mem_desc.region_cnt; i++, rg++) {
+		if (rg->alloc)
+			free_fbmem(rg);
+		else {
+			if (rg->map)
+				unmap_kern(rg);
+		}
+	}
+}
+
+static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
+			   struct omapfb_mem_desc *req_vram)
+{
+	int r;
+	u32 l;
+	struct lcd_panel *panel = fbdev->panel;
+	int tmo = 10000;
+	int skip_init = 0;
+	int i;
+
+	memset(&dispc, 0, sizeof(dispc));
+
+	dispc.base = io_p2v(DISPC_BASE);
+	dispc.fbdev = fbdev;
+	dispc.ext_mode = ext_mode;
+
+	init_completion(&dispc.frame_done);
+
+	if ((r = get_dss_clocks()) < 0)
+		return r;
+
+	enable_interface_clocks(1);
+	enable_lcd_clocks(1);
+
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+	l = dispc_read_reg(DISPC_CONTROL);
+	/* LCD enabled ? */
+	if (l & 1) {
+		pr_info("omapfb: skipping hardware initialization\n");
+		skip_init = 1;
+	}
+#endif
+
+	if (!skip_init) {
+		/* Reset monitoring works only w/ the 54M clk */
+		enable_digit_clocks(1);
+
+		/* Soft reset */
+		MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1);
+
+		while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
+			if (!--tmo) {
+				dev_err(dispc.fbdev->dev, "soft reset failed\n");
+				r = -ENODEV;
+				enable_digit_clocks(0);
+				goto fail1;
+			}
+		}
+
+		enable_digit_clocks(0);
+	}
+
+	/* Enable smart idle and autoidle */
+	l = dispc_read_reg(DISPC_CONTROL);
+	l &= ~((3 << 12) | (3 << 3));
+	l |= (2 << 12) | (2 << 3) | (1 << 0);
+	dispc_write_reg(DISPC_SYSCONFIG, l);
+	omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG);
+
+	/* Set functional clock autogating */
+	l = dispc_read_reg(DISPC_CONFIG);
+	l |= 1 << 9;
+	dispc_write_reg(DISPC_CONFIG, l);
+
+	l = dispc_read_reg(DISPC_IRQSTATUS);
+	dispc_write_reg(l, DISPC_IRQSTATUS);
+
+	/* Enable those that we handle always */
+	omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
+
+	if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
+			   0, MODULE_NAME, fbdev)) < 0) {
+		dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n");
+		goto fail1;
+	}
+
+	/* L3 firewall setting: enable access to OCM RAM */
+	__raw_writel(0x402000b0, io_p2v(0x680050a0));
+
+	if ((r = alloc_palette_ram()) < 0)
+		goto fail2;
+
+	if ((r = setup_fbmem(req_vram)) < 0)
+		goto fail3;
+
+	if (!skip_init) {
+		for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
+			memset(dispc.mem_desc.region[i].vaddr, 0,
+				dispc.mem_desc.region[i].size);
+		}
+
+		/* Set logic clock to fck, pixel clock to fck/2 for now */
+		MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16);
+		MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(0, 8), 2 << 0);
+
+		setup_plane_fifo(0, ext_mode);
+		setup_plane_fifo(1, ext_mode);
+		setup_plane_fifo(2, ext_mode);
+
+		setup_color_conv_coef();
+
+		set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT);
+		set_load_mode(DISPC_LOAD_FRAME_ONLY);
+
+		if (!ext_mode) {
+			set_lcd_data_lines(panel->data_lines);
+			omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
+			set_lcd_timings();
+		} else
+			set_lcd_data_lines(panel->bpp);
+		enable_rfbi_mode(ext_mode);
+	}
+
+	l = dispc_read_reg(DISPC_REVISION);
+	pr_info("omapfb: DISPC version %d.%d initialized\n",
+		 l >> 4 & 0x0f, l & 0x0f);
+	enable_lcd_clocks(0);
+
+	return 0;
+fail3:
+	free_palette_ram();
+fail2:
+	free_irq(INT_24XX_DSS_IRQ, fbdev);
+fail1:
+	enable_lcd_clocks(0);
+	enable_interface_clocks(0);
+	put_dss_clocks();
+
+	return r;
+}
+
+static void omap_dispc_cleanup(void)
+{
+	int i;
+
+	omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	/* This will also disable clocks that are on */
+	for (i = 0; i < dispc.mem_desc.region_cnt; i++)
+		omap_dispc_enable_plane(i, 0);
+	cleanup_fbmem();
+	free_palette_ram();
+	free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
+	enable_interface_clocks(0);
+	put_dss_clocks();
+}
+
+const struct lcd_ctrl omap2_int_ctrl = {
+	.name			= "internal",
+	.init			= omap_dispc_init,
+	.cleanup		= omap_dispc_cleanup,
+	.get_caps		= omap_dispc_get_caps,
+	.set_update_mode	= omap_dispc_set_update_mode,
+	.get_update_mode	= omap_dispc_get_update_mode,
+	.update_window		= omap_dispc_update_window,
+	.suspend		= omap_dispc_suspend,
+	.resume			= omap_dispc_resume,
+	.setup_plane		= omap_dispc_setup_plane,
+	.setup_mem		= omap_dispc_setup_mem,
+	.set_scale		= omap_dispc_set_scale,
+	.enable_plane		= omap_dispc_enable_plane,
+	.set_color_key		= omap_dispc_set_color_key,
+	.get_color_key		= omap_dispc_get_color_key,
+	.mmap			= omap_dispc_mmap_user,
+};
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
new file mode 100644
index 0000000..eb1512b
--- /dev/null
+++ b/drivers/video/omap/dispc.h
@@ -0,0 +1,43 @@
+#ifndef _DISPC_H
+#define _DISPC_H
+
+#include <linux/interrupt.h>
+
+#define DISPC_PLANE_GFX			0
+#define DISPC_PLANE_VID1		1
+#define DISPC_PLANE_VID2		2
+
+#define DISPC_RGB_1_BPP			0x00
+#define DISPC_RGB_2_BPP			0x01
+#define DISPC_RGB_4_BPP			0x02
+#define DISPC_RGB_8_BPP			0x03
+#define DISPC_RGB_12_BPP		0x04
+#define DISPC_RGB_16_BPP		0x06
+#define DISPC_RGB_24_BPP		0x08
+#define DISPC_RGB_24_BPP_UNPACK_32	0x09
+#define DISPC_YUV2_422			0x0a
+#define DISPC_UYVY_422			0x0b
+
+#define DISPC_BURST_4x32		0
+#define DISPC_BURST_8x32		1
+#define DISPC_BURST_16x32		2
+
+#define DISPC_LOAD_CLUT_AND_FRAME	0x00
+#define DISPC_LOAD_CLUT_ONLY		0x01
+#define DISPC_LOAD_FRAME_ONLY		0x02
+#define DISPC_LOAD_CLUT_ONCE_FRAME	0x03
+
+#define DISPC_TFT_DATA_LINES_12		0
+#define DISPC_TFT_DATA_LINES_16		1
+#define DISPC_TFT_DATA_LINES_18		2
+#define DISPC_TFT_DATA_LINES_24		3
+
+extern void omap_dispc_set_lcd_size(int width, int height);
+
+extern void omap_dispc_enable_lcd_out(int enable);
+extern void omap_dispc_enable_digit_out(int enable);
+
+extern int  omap_dispc_request_irq(void (*callback)(void *data), void *data);
+extern void omap_dispc_free_irq(void);
+
+#endif
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
new file mode 100644
index 0000000..dc48e02
--- /dev/null
+++ b/drivers/video/omap/hwa742.c
@@ -0,0 +1,1077 @@
+/*
+ * Epson HWA742 LCD controller driver
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Authors:     Juha Yrjölä   <juha.yrjola@nokia.com>
+ *	        Imre Deak     <imre.deak@nokia.com>
+ * YUV support: Jussi Laako   <jussi.laako@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/hwa742.h>
+
+#define HWA742_REV_CODE_REG       0x0
+#define HWA742_CONFIG_REG         0x2
+#define HWA742_PLL_DIV_REG        0x4
+#define HWA742_PLL_0_REG          0x6
+#define HWA742_PLL_1_REG          0x8
+#define HWA742_PLL_2_REG          0xa
+#define HWA742_PLL_3_REG          0xc
+#define HWA742_PLL_4_REG          0xe
+#define HWA742_CLK_SRC_REG        0x12
+#define HWA742_PANEL_TYPE_REG     0x14
+#define HWA742_H_DISP_REG         0x16
+#define HWA742_H_NDP_REG          0x18
+#define HWA742_V_DISP_1_REG       0x1a
+#define HWA742_V_DISP_2_REG       0x1c
+#define HWA742_V_NDP_REG          0x1e
+#define HWA742_HS_W_REG           0x20
+#define HWA742_HP_S_REG           0x22
+#define HWA742_VS_W_REG           0x24
+#define HWA742_VP_S_REG           0x26
+#define HWA742_PCLK_POL_REG       0x28
+#define HWA742_INPUT_MODE_REG     0x2a
+#define HWA742_TRANSL_MODE_REG1   0x2e
+#define HWA742_DISP_MODE_REG      0x34
+#define HWA742_WINDOW_TYPE        0x36
+#define HWA742_WINDOW_X_START_0   0x38
+#define HWA742_WINDOW_X_START_1   0x3a
+#define HWA742_WINDOW_Y_START_0   0x3c
+#define HWA742_WINDOW_Y_START_1   0x3e
+#define HWA742_WINDOW_X_END_0     0x40
+#define HWA742_WINDOW_X_END_1     0x42
+#define HWA742_WINDOW_Y_END_0     0x44
+#define HWA742_WINDOW_Y_END_1     0x46
+#define HWA742_MEMORY_WRITE_LSB   0x48
+#define HWA742_MEMORY_WRITE_MSB   0x49
+#define HWA742_MEMORY_READ_0      0x4a
+#define HWA742_MEMORY_READ_1      0x4c
+#define HWA742_MEMORY_READ_2      0x4e
+#define HWA742_POWER_SAVE         0x56
+#define HWA742_NDP_CTRL           0x58
+
+#define HWA742_AUTO_UPDATE_TIME		(HZ / 20)
+
+/* Reserve 4 request slots for requests in irq context */
+#define REQ_POOL_SIZE			24
+#define IRQ_REQ_POOL_SIZE		4
+
+#define REQ_FROM_IRQ_POOL 0x01
+
+#define REQ_COMPLETE	0
+#define REQ_PENDING	1
+
+struct update_param {
+	int	x, y, width, height;
+	int	color_mode;
+	int	flags;
+};
+
+struct hwa742_request {
+	struct list_head entry;
+	unsigned int	 flags;
+
+	int		 (*handler)(struct hwa742_request *req);
+	void		 (*complete)(void *data);
+	void		 *complete_data;
+
+	union {
+		struct update_param	update;
+		struct completion	*sync;
+	} par;
+};
+
+struct {
+	enum omapfb_update_mode	update_mode;
+	enum omapfb_update_mode	update_mode_before_suspend;
+
+	struct timer_list	auto_update_timer;
+	int			stop_auto_update;
+	struct omapfb_update_window	auto_update_window;
+	unsigned		te_connected:1;
+	unsigned		vsync_only:1;
+
+	struct hwa742_request	req_pool[REQ_POOL_SIZE];
+	struct list_head	pending_req_list;
+	struct list_head	free_req_list;
+	struct semaphore	req_sema;
+	spinlock_t		req_lock;
+
+	struct extif_timings	reg_timings, lut_timings;
+
+	int			prev_color_mode;
+	int			prev_flags;
+	int			window_type;
+
+	u32			max_transmit_size;
+	u32			extif_clk_period;
+	unsigned long		pix_tx_time;
+	unsigned long		line_upd_time;
+
+
+	struct omapfb_device	*fbdev;
+	struct lcd_ctrl_extif	*extif;
+	struct lcd_ctrl		*int_ctrl;
+
+	void			(*power_up)(struct device *dev);
+	void			(*power_down)(struct device *dev);
+} hwa742;
+
+struct lcd_ctrl hwa742_ctrl;
+
+static u8 hwa742_read_reg(u8 reg)
+{
+	u8 data;
+
+	hwa742.extif->set_bits_per_cycle(8);
+	hwa742.extif->write_command(&reg, 1);
+	hwa742.extif->read_data(&data, 1);
+
+	return data;
+}
+
+static void hwa742_write_reg(u8 reg, u8 data)
+{
+	hwa742.extif->set_bits_per_cycle(8);
+	hwa742.extif->write_command(&reg, 1);
+	hwa742.extif->write_data(&data, 1);
+}
+
+static void set_window_regs(int x_start, int y_start, int x_end, int y_end)
+{
+	u8 tmp[8];
+	u8 cmd;
+
+	x_end--;
+	y_end--;
+	tmp[0] = x_start;
+	tmp[1] = x_start >> 8;
+	tmp[2] = y_start;
+	tmp[3] = y_start >> 8;
+	tmp[4] = x_end;
+	tmp[5] = x_end >> 8;
+	tmp[6] = y_end;
+	tmp[7] = y_end >> 8;
+
+	hwa742.extif->set_bits_per_cycle(8);
+	cmd = HWA742_WINDOW_X_START_0;
+
+	hwa742.extif->write_command(&cmd, 1);
+
+	hwa742.extif->write_data(tmp, 8);
+}
+
+static void set_format_regs(int conv, int transl, int flags)
+{
+	if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
+		hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01);
+#ifdef VERBOSE
+		dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n");
+#endif
+	} else {
+		hwa742.window_type = (hwa742.window_type & 0xfc);
+#ifdef VERBOSE
+		dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n");
+#endif
+	}
+
+	hwa742_write_reg(HWA742_INPUT_MODE_REG, conv);
+	hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl);
+	hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type);
+}
+
+static void enable_tearsync(int y, int width, int height, int screen_height,
+			    int force_vsync)
+{
+	u8 b;
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b |= 1 << 2;
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+
+	if (likely(hwa742.vsync_only || force_vsync)) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if (width * hwa742.pix_tx_time < hwa742.line_upd_time) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if ((width * hwa742.pix_tx_time / 1000) * height <
+	    (y + height) * (hwa742.line_upd_time / 1000)) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	hwa742.extif->enable_tearsync(1, y + 1);
+}
+
+static void disable_tearsync(void)
+{
+	u8 b;
+
+	hwa742.extif->enable_tearsync(0, 0);
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b &= ~(1 << 2);
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+}
+
+static inline struct hwa742_request *alloc_req(void)
+{
+	unsigned long flags;
+	struct hwa742_request *req;
+	int req_flags = 0;
+
+	if (!in_interrupt())
+		down(&hwa742.req_sema);
+	else
+		req_flags = REQ_FROM_IRQ_POOL;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+	BUG_ON(list_empty(&hwa742.free_req_list));
+	req = list_entry(hwa742.free_req_list.next,
+			 struct hwa742_request, entry);
+	list_del(&req->entry);
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+	INIT_LIST_HEAD(&req->entry);
+	req->flags = req_flags;
+
+	return req;
+}
+
+static inline void free_req(struct hwa742_request *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+
+	list_del(&req->entry);
+	list_add(&req->entry, &hwa742.free_req_list);
+	if (!(req->flags & REQ_FROM_IRQ_POOL))
+		up(&hwa742.req_sema);
+
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+}
+
+static void process_pending_requests(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+
+	while (!list_empty(&hwa742.pending_req_list)) {
+		struct hwa742_request *req;
+		void (*complete)(void *);
+		void *complete_data;
+
+		req = list_entry(hwa742.pending_req_list.next,
+				 struct hwa742_request, entry);
+		spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+		if (req->handler(req) == REQ_PENDING)
+			return;
+
+		complete = req->complete;
+		complete_data = req->complete_data;
+		free_req(req);
+
+		if (complete)
+			complete(complete_data);
+
+		spin_lock_irqsave(&hwa742.req_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+}
+
+static void submit_req_list(struct list_head *head)
+{
+	unsigned long flags;
+	int process = 1;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+	if (likely(!list_empty(&hwa742.pending_req_list)))
+		process = 0;
+	list_splice_init(head, hwa742.pending_req_list.prev);
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+	if (process)
+		process_pending_requests();
+}
+
+static void request_complete(void *data)
+{
+	struct hwa742_request	*req = (struct hwa742_request *)data;
+	void			(*complete)(void *);
+	void			*complete_data;
+
+	complete = req->complete;
+	complete_data = req->complete_data;
+
+	free_req(req);
+
+	if (complete)
+		complete(complete_data);
+
+	process_pending_requests();
+}
+
+static int send_frame_handler(struct hwa742_request *req)
+{
+	struct update_param *par = &req->par.update;
+	int x = par->x;
+	int y = par->y;
+	int w = par->width;
+	int h = par->height;
+	int bpp;
+	int conv, transl;
+	unsigned long offset;
+	int color_mode = par->color_mode;
+	int flags = par->flags;
+	int scr_width = hwa742.fbdev->panel->x_res;
+	int scr_height = hwa742.fbdev->panel->y_res;
+
+#ifdef VERBOSE
+	dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d "
+		"color_mode %d flags %d\n",
+		x, y, w, h, scr_width, color_mode, flags);
+#endif
+
+	switch (color_mode) {
+	case OMAPFB_COLOR_YUV422:
+		bpp = 16;
+		conv = 0x08;
+		transl = 0x25;
+		break;
+	case OMAPFB_COLOR_YUV420:
+		bpp = 12;
+		conv = 0x09;
+		transl = 0x25;
+		break;
+	case OMAPFB_COLOR_RGB565:
+		bpp = 16;
+		conv = 0x01;
+		transl = 0x05;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (hwa742.prev_flags != flags ||
+	    hwa742.prev_color_mode != color_mode) {
+		set_format_regs(conv, transl, flags);
+		hwa742.prev_color_mode = color_mode;
+		hwa742.prev_flags = flags;
+	}
+	flags = req->par.update.flags;
+	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+		enable_tearsync(y, scr_width, h, scr_height,
+				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+	else
+		disable_tearsync();
+
+	set_window_regs(x, y, x + w, y + h);
+
+	offset = (scr_width * y + x) * bpp / 8;
+
+	hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX,
+			OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h,
+			color_mode);
+
+	hwa742.extif->set_bits_per_cycle(16);
+
+	hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+	hwa742.extif->transfer_area(w, h, request_complete, req);
+
+	return REQ_PENDING;
+}
+
+static void send_frame_complete(void *data)
+{
+	hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0);
+}
+
+#define ADD_PREQ(_x, _y, _w, _h) do {		\
+	req = alloc_req();			\
+	req->handler	= send_frame_handler;	\
+	req->complete	= send_frame_complete;	\
+	req->par.update.x = _x;			\
+	req->par.update.y = _y;			\
+	req->par.update.width  = _w;		\
+	req->par.update.height = _h;		\
+	req->par.update.color_mode = color_mode;\
+	req->par.update.flags	  = flags;	\
+	list_add_tail(&req->entry, req_head);	\
+} while(0)
+
+static void create_req_list(struct omapfb_update_window *win,
+			    struct list_head *req_head)
+{
+	struct hwa742_request *req;
+	int x = win->x;
+	int y = win->y;
+	int width = win->width;
+	int height = win->height;
+	int color_mode;
+	int flags;
+
+	flags = win->format & ~OMAPFB_FORMAT_MASK;
+	color_mode = win->format & OMAPFB_FORMAT_MASK;
+
+	if (x & 1) {
+		ADD_PREQ(x, y, 1, height);
+		width--;
+		x++;
+		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+	}
+	if (width & ~1) {
+		unsigned int xspan = width & ~1;
+		unsigned int ystart = y;
+		unsigned int yspan = height;
+
+		if (xspan * height * 2 > hwa742.max_transmit_size) {
+			yspan = hwa742.max_transmit_size / (xspan * 2);
+			ADD_PREQ(x, ystart, xspan, yspan);
+			ystart += yspan;
+			yspan = height - yspan;
+			flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+		}
+
+		ADD_PREQ(x, ystart, xspan, yspan);
+		x += xspan;
+		width -= xspan;
+		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+	}
+	if (width)
+		ADD_PREQ(x, y, 1, height);
+}
+
+static void auto_update_complete(void *data)
+{
+	if (!hwa742.stop_auto_update)
+		mod_timer(&hwa742.auto_update_timer,
+			  jiffies + HWA742_AUTO_UPDATE_TIME);
+}
+
+static void hwa742_update_window_auto(unsigned long arg)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *last;
+
+	create_req_list(&hwa742.auto_update_window, &req_list);
+	last = list_entry(req_list.prev, struct hwa742_request, entry);
+
+	last->complete = auto_update_complete;
+	last->complete_data = NULL;
+
+	submit_req_list(&req_list);
+}
+
+int hwa742_update_window_async(struct fb_info *fbi,
+				 struct omapfb_update_window *win,
+				 void (*complete_callback)(void *arg),
+				 void *complete_callback_data)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *last;
+	int r = 0;
+
+	if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) {
+		dev_dbg(hwa742.fbdev->dev, "invalid update mode\n");
+		r = -EINVAL;
+		goto out;
+	}
+	if (unlikely(win->format &
+	    ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE |
+	    OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) {
+		dev_dbg(hwa742.fbdev->dev, "invalid window flag");
+		r = -EINVAL;
+		goto out;
+	}
+
+	create_req_list(win, &req_list);
+	last = list_entry(req_list.prev, struct hwa742_request, entry);
+
+	last->complete = complete_callback;
+	last->complete_data = (void *)complete_callback_data;
+
+	submit_req_list(&req_list);
+
+out:
+	return r;
+}
+EXPORT_SYMBOL(hwa742_update_window_async);
+
+static int hwa742_setup_plane(int plane, int channel_out,
+				  unsigned long offset, int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	if (plane != OMAPFB_PLANE_GFX ||
+	    channel_out != OMAPFB_CHANNEL_OUT_LCD)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int hwa742_enable_plane(int plane, int enable)
+{
+	if (plane != 0)
+		return -EINVAL;
+
+	hwa742.int_ctrl->enable_plane(plane, enable);
+
+	return 0;
+}
+
+static int sync_handler(struct hwa742_request *req)
+{
+	complete(req->par.sync);
+	return REQ_COMPLETE;
+}
+
+static void hwa742_sync(void)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *req;
+	struct completion comp;
+
+	req = alloc_req();
+
+	req->handler = sync_handler;
+	req->complete = NULL;
+	init_completion(&comp);
+	req->par.sync = &comp;
+
+	list_add(&req->entry, &req_list);
+	submit_req_list(&req_list);
+
+	wait_for_completion(&comp);
+}
+
+static void hwa742_bind_client(struct omapfb_notifier_block *nb)
+{
+	dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode);
+	if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) {
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
+	}
+}
+
+static int hwa742_set_update_mode(enum omapfb_update_mode mode)
+{
+	if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE &&
+	    mode != OMAPFB_UPDATE_DISABLED)
+		return -EINVAL;
+
+	if (mode == hwa742.update_mode)
+		return 0;
+
+	dev_info(hwa742.fbdev->dev, "HWA742: setting update mode to %s\n",
+			mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
+			(mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
+
+	switch (hwa742.update_mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_DISABLED);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		hwa742.stop_auto_update = 1;
+		del_timer_sync(&hwa742.auto_update_timer);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	hwa742.update_mode = mode;
+	hwa742_sync();
+	hwa742.stop_auto_update = 0;
+
+	switch (mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		hwa742_update_window_auto(0);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	return 0;
+}
+
+static enum omapfb_update_mode hwa742_get_update_mode(void)
+{
+	return hwa742.update_mode;
+}
+
+static unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+	int bus_tick = hwa742.extif_clk_period * div;
+	return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 12.2 ns (regs),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 16 ns (regs),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 2*SYSCLK  (regs),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns */
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
+		  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
+
+	t = &hwa742.reg_timings;
+	memset(t, 0, sizeof(*t));
+	t->clk_div = div;
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return hwa742.extif->convert_timings(t);
+}
+
+static int calc_lut_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns
+	 */
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
+		  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
+
+	t = &hwa742.lut_timings;
+	memset(t, 0, sizeof(*t));
+
+	t->clk_div = div;
+
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return hwa742.extif->convert_timings(t);
+}
+
+static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
+{
+	int max_clk_div;
+	int div;
+
+	hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div);
+	for (div = 1; div < max_clk_div; div++) {
+		if (calc_reg_timing(sysclk, div) == 0)
+			break;
+	}
+	if (div > max_clk_div)
+		goto err;
+
+	*extif_mem_div = div;
+
+	for (div = 1; div < max_clk_div; div++) {
+		if (calc_lut_timing(sysclk, div) == 0)
+			break;
+	}
+
+	if (div > max_clk_div)
+		goto err;
+
+	return 0;
+
+err:
+	dev_err(hwa742.fbdev->dev, "can't setup timings\n");
+	return -1;
+}
+
+static void calc_hwa742_clk_rates(unsigned long ext_clk,
+				unsigned long *sys_clk, unsigned long *pix_clk)
+{
+	int pix_clk_src;
+	int sys_div = 0, sys_mul = 0;
+	int pix_div;
+
+	pix_clk_src = hwa742_read_reg(HWA742_CLK_SRC_REG);
+	pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
+	if ((pix_clk_src & (0x3 << 1)) == 0) {
+		/* Source is the PLL */
+		sys_div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1;
+		sys_mul = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1;
+		*sys_clk = ext_clk * sys_mul / sys_div;
+	} else	/* else source is ext clk, or oscillator */
+		*sys_clk = ext_clk;
+
+	*pix_clk = *sys_clk / pix_div;			/* HZ */
+	dev_dbg(hwa742.fbdev->dev,
+		"ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
+		ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
+	dev_dbg(hwa742.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
+		*sys_clk, *pix_clk);
+}
+
+
+static int setup_tearsync(unsigned long pix_clk, int extif_div)
+{
+	int hdisp, vdisp;
+	int hndp, vndp;
+	int hsw, vsw;
+	int hs, vs;
+	int hs_pol_inv, vs_pol_inv;
+	int use_hsvs, use_ndp;
+	u8  b;
+
+	hsw = hwa742_read_reg(HWA742_HS_W_REG);
+	vsw = hwa742_read_reg(HWA742_VS_W_REG);
+	hs_pol_inv = !(hsw & 0x80);
+	vs_pol_inv = !(vsw & 0x80);
+	hsw = hsw & 0x7f;
+	vsw = vsw & 0x3f;
+
+	hdisp = (hwa742_read_reg(HWA742_H_DISP_REG) & 0x7f) * 8;
+	vdisp = hwa742_read_reg(HWA742_V_DISP_1_REG) +
+		((hwa742_read_reg(HWA742_V_DISP_2_REG) & 0x3) << 8);
+
+	hndp = hwa742_read_reg(HWA742_H_NDP_REG) & 0x7f;
+	vndp = hwa742_read_reg(HWA742_V_NDP_REG);
+
+	/* time to transfer one pixel (16bpp) in ps */
+	hwa742.pix_tx_time = hwa742.reg_timings.we_cycle_time;
+	if (hwa742.extif->get_max_tx_rate != NULL) {
+		/*
+		 * The external interface might have a rate limitation,
+		 * if so, we have to maximize our transfer rate.
+		 */
+		unsigned long min_tx_time;
+		unsigned long max_tx_rate = hwa742.extif->get_max_tx_rate();
+
+		dev_dbg(hwa742.fbdev->dev, "max_tx_rate %ld HZ\n",
+			max_tx_rate);
+		min_tx_time = 1000000000 / (max_tx_rate / 1000);  /* ps */
+		if (hwa742.pix_tx_time < min_tx_time)
+			hwa742.pix_tx_time = min_tx_time;
+	}
+
+	/* time to update one line in ps */
+	hwa742.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
+	hwa742.line_upd_time *= 1000;
+	if (hdisp * hwa742.pix_tx_time > hwa742.line_upd_time)
+		/*
+		 * transfer speed too low, we might have to use both
+		 * HS and VS
+		 */
+		use_hsvs = 1;
+	else
+		/* decent transfer speed, we'll always use only VS */
+		use_hsvs = 0;
+
+	if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
+		/*
+		 * HS or'ed with VS doesn't work, use the active high
+		 * TE signal based on HNDP / VNDP
+		 */
+		use_ndp = 1;
+		hs_pol_inv = 0;
+		vs_pol_inv = 0;
+		hs = hndp;
+		vs = vndp;
+	} else {
+		/*
+		 * Use HS or'ed with VS as a TE signal if both are needed
+		 * or VNDP if only vsync is needed.
+		 */
+		use_ndp = 0;
+		hs = hsw;
+		vs = vsw;
+		if (!use_hsvs) {
+			hs_pol_inv = 0;
+			vs_pol_inv = 0;
+		}
+	}
+
+	hs = hs * 1000000 / (pix_clk / 1000);			/* ps */
+	hs *= 1000;
+
+	vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000);	/* ps */
+	vs *= 1000;
+
+	if (vs <= hs)
+		return -EDOM;
+	/* set VS to 120% of HS to minimize VS detection time */
+	vs = hs * 12 / 10;
+	/* minimize HS too */
+	hs = 10000;
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b &= ~0x3;
+	b |= use_hsvs ? 1 : 0;
+	b |= (use_ndp && use_hsvs) ? 0 : 2;
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+
+	hwa742.vsync_only = !use_hsvs;
+
+	dev_dbg(hwa742.fbdev->dev,
+		"pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
+		pix_clk, hwa742.pix_tx_time, hwa742.line_upd_time);
+	dev_dbg(hwa742.fbdev->dev,
+		"hs %d ps vs %d ps mode %d vsync_only %d\n",
+		hs, vs, (b & 0x3), !use_hsvs);
+
+	return hwa742.extif->setup_tearsync(1, hs, vs,
+					    hs_pol_inv, vs_pol_inv, extif_div);
+}
+
+static void hwa742_get_caps(int plane, struct omapfb_caps *caps)
+{
+	hwa742.int_ctrl->get_caps(plane, caps);
+	caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
+		      OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE;
+	if (hwa742.te_connected)
+		caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
+	caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
+			   (1 << OMAPFB_COLOR_YUV420);
+}
+
+static void hwa742_suspend(void)
+{
+	hwa742.update_mode_before_suspend = hwa742.update_mode;
+	hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	/* Enable sleep mode */
+	hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1);
+	if (hwa742.power_down != NULL)
+		hwa742.power_down(hwa742.fbdev->dev);
+}
+
+static void hwa742_resume(void)
+{
+	if (hwa742.power_up != NULL)
+		hwa742.power_up(hwa742.fbdev->dev);
+	/* Disable sleep mode */
+	hwa742_write_reg(HWA742_POWER_SAVE, 0);
+	while (1) {
+		/* Loop until PLL output is stabilized */
+		if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7))
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(msecs_to_jiffies(5));
+	}
+	hwa742_set_update_mode(hwa742.update_mode_before_suspend);
+}
+
+static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
+		       struct omapfb_mem_desc *req_vram)
+{
+	int r = 0, i;
+	u8 rev, conf;
+	unsigned long ext_clk;
+	unsigned long sys_clk, pix_clk;
+	int extif_mem_div;
+	struct omapfb_platform_data *omapfb_conf;
+	struct hwa742_platform_data *ctrl_conf;
+
+	BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
+
+	hwa742.fbdev = fbdev;
+	hwa742.extif = fbdev->ext_if;
+	hwa742.int_ctrl = fbdev->int_ctrl;
+
+	omapfb_conf = fbdev->dev->platform_data;
+	ctrl_conf = omapfb_conf->ctrl_platform_data;
+
+	if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
+		dev_err(fbdev->dev, "HWA742: missing platform data\n");
+		r = -ENOENT;
+		goto err1;
+	}
+
+	hwa742.power_down = ctrl_conf->power_down;
+	hwa742.power_up = ctrl_conf->power_up;
+
+	spin_lock_init(&hwa742.req_lock);
+
+	if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0)
+		goto err1;
+
+	if ((r = hwa742.extif->init(fbdev)) < 0)
+		goto err2;
+
+	ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
+	if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
+		goto err3;
+	hwa742.extif->set_timings(&hwa742.reg_timings);
+	if (hwa742.power_up != NULL)
+		hwa742.power_up(fbdev->dev);
+
+	calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
+	if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
+		goto err4;
+	hwa742.extif->set_timings(&hwa742.reg_timings);
+
+	rev = hwa742_read_reg(HWA742_REV_CODE_REG);
+	if ((rev & 0xfc) != 0x80) {
+		dev_err(fbdev->dev, "HWA742: invalid revision %02x\n", rev);
+		r = -ENODEV;
+		goto err4;
+	}
+
+
+	if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) {
+		dev_err(fbdev->dev,
+		      "HWA742: controller not initialized by the bootloader\n");
+		r = -ENODEV;
+		goto err4;
+	}
+
+	if (ctrl_conf->te_connected) {
+		if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) {
+			dev_err(hwa742.fbdev->dev,
+			       "HWA742: can't setup tearing synchronization\n");
+			goto err4;
+		}
+		hwa742.te_connected = 1;
+	}
+
+	hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
+
+	hwa742.update_mode = OMAPFB_UPDATE_DISABLED;
+
+	hwa742.auto_update_window.x = 0;
+	hwa742.auto_update_window.y = 0;
+	hwa742.auto_update_window.width = fbdev->panel->x_res;
+	hwa742.auto_update_window.height = fbdev->panel->y_res;
+	hwa742.auto_update_window.format = 0;
+
+	init_timer(&hwa742.auto_update_timer);
+	hwa742.auto_update_timer.function = hwa742_update_window_auto;
+	hwa742.auto_update_timer.data = 0;
+
+	hwa742.prev_color_mode = -1;
+	hwa742.prev_flags = 0;
+
+	hwa742.fbdev = fbdev;
+
+	INIT_LIST_HEAD(&hwa742.free_req_list);
+	INIT_LIST_HEAD(&hwa742.pending_req_list);
+	for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++)
+		list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list);
+	BUG_ON(i <= IRQ_REQ_POOL_SIZE);
+	sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE);
+
+	conf = hwa742_read_reg(HWA742_CONFIG_REG);
+	dev_info(fbdev->dev, ": Epson HWA742 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+
+	return 0;
+err4:
+	if (hwa742.power_down != NULL)
+		hwa742.power_down(fbdev->dev);
+err3:
+	hwa742.extif->cleanup();
+err2:
+	hwa742.int_ctrl->cleanup();
+err1:
+	return r;
+}
+
+static void hwa742_cleanup(void)
+{
+	hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	hwa742.extif->cleanup();
+	hwa742.int_ctrl->cleanup();
+	if (hwa742.power_down != NULL)
+		hwa742.power_down(hwa742.fbdev->dev);
+}
+
+struct lcd_ctrl hwa742_ctrl = {
+	.name			= "hwa742",
+	.init			= hwa742_init,
+	.cleanup		= hwa742_cleanup,
+	.bind_client		= hwa742_bind_client,
+	.get_caps		= hwa742_get_caps,
+	.set_update_mode	= hwa742_set_update_mode,
+	.get_update_mode	= hwa742_get_update_mode,
+	.setup_plane		= hwa742_setup_plane,
+	.enable_plane		= hwa742_enable_plane,
+	.update_window		= hwa742_update_window_async,
+	.sync			= hwa742_sync,
+	.suspend		= hwa742_suspend,
+	.resume			= hwa742_resume,
+};
+
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
new file mode 100644
index 0000000..51807b4
--- /dev/null
+++ b/drivers/video/omap/lcd_h3.c
@@ -0,0 +1,141 @@
+/*
+ * LCD panel support for the TI OMAP H3 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME	"omapfb-lcd_h3"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int h3_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void h3_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int h3_panel_enable(struct lcd_panel *panel)
+{
+	int r = 0;
+
+	/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+	r = tps65010_set_gpio_out_value(GPIO1, HIGH);
+	if (!r)
+		r = tps65010_set_gpio_out_value(GPIO2, HIGH);
+	if (r)
+		pr_err("Unable to turn on LCD panel\n");
+
+	return r;
+}
+
+static void h3_panel_disable(struct lcd_panel *panel)
+{
+	int r = 0;
+
+	/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+	r = tps65010_set_gpio_out_value(GPIO1, LOW);
+	if (!r)
+		tps65010_set_gpio_out_value(GPIO2, LOW);
+	if (r)
+		pr_err("Unable to turn off LCD panel\n");
+}
+
+static unsigned long h3_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel h3_panel = {
+	.name		= "h3",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.data_lines	= 16,
+	.bpp		= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12000,
+	.hsw		= 12,
+	.hfp		= 14,
+	.hbp		= 72 - 12,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 0,
+
+	.init		= h3_panel_init,
+	.cleanup	= h3_panel_cleanup,
+	.enable		= h3_panel_enable,
+	.disable	= h3_panel_disable,
+	.get_caps	= h3_panel_get_caps,
+};
+
+static int h3_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&h3_panel);
+	return 0;
+}
+
+static int h3_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int h3_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int h3_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver h3_panel_driver = {
+	.probe		= h3_panel_probe,
+	.remove		= h3_panel_remove,
+	.suspend	= h3_panel_suspend,
+	.resume		= h3_panel_resume,
+	.driver		= {
+		.name	= "lcd_h3",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int h3_panel_drv_init(void)
+{
+	return platform_driver_register(&h3_panel_driver);
+}
+
+static void h3_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&h3_panel_driver);
+}
+
+module_init(h3_panel_drv_init);
+module_exit(h3_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
new file mode 100644
index 0000000..fd6f0eb
--- /dev/null
+++ b/drivers/video/omap/lcd_h4.c
@@ -0,0 +1,117 @@
+/*
+ * LCD panel support for the TI OMAP H4 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/omapfb.h>
+
+static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void h4_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int h4_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void h4_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel h4_panel = {
+	.name		= "h4",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 6250,
+	.hsw		= 15,
+	.hfp		= 15,
+	.hbp		= 60,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 1,
+
+	.init		= h4_panel_init,
+	.cleanup	= h4_panel_cleanup,
+	.enable		= h4_panel_enable,
+	.disable	= h4_panel_disable,
+	.get_caps	= h4_panel_get_caps,
+};
+
+static int h4_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&h4_panel);
+	return 0;
+}
+
+static int h4_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int h4_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver h4_panel_driver = {
+	.probe		= h4_panel_probe,
+	.remove		= h4_panel_remove,
+	.suspend	= h4_panel_suspend,
+	.resume		= h4_panel_resume,
+	.driver		= {
+		.name	= "lcd_h4",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int h4_panel_drv_init(void)
+{
+	return platform_driver_register(&h4_panel_driver);
+}
+
+static void h4_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&h4_panel_driver);
+}
+
+module_init(h4_panel_drv_init);
+module_exit(h4_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
new file mode 100644
index 0000000..551f385
--- /dev/null
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -0,0 +1,124 @@
+/*
+ * LCD panel support for the TI OMAP1510 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/omapfb.h>
+
+static int innovator1510_panel_init(struct lcd_panel *panel,
+				    struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void innovator1510_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int innovator1510_panel_enable(struct lcd_panel *panel)
+{
+	fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+	return 0;
+}
+
+static void innovator1510_panel_disable(struct lcd_panel *panel)
+{
+	fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+}
+
+static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel innovator1510_panel = {
+	.name		= "inn1510",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= innovator1510_panel_init,
+	.cleanup	= innovator1510_panel_cleanup,
+	.enable		= innovator1510_panel_enable,
+	.disable	= innovator1510_panel_disable,
+	.get_caps	= innovator1510_panel_get_caps,
+};
+
+static int innovator1510_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&innovator1510_panel);
+	return 0;
+}
+
+static int innovator1510_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int innovator1510_panel_suspend(struct platform_device *pdev,
+				       pm_message_t mesg)
+{
+	return 0;
+}
+
+static int innovator1510_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver innovator1510_panel_driver = {
+	.probe		= innovator1510_panel_probe,
+	.remove		= innovator1510_panel_remove,
+	.suspend	= innovator1510_panel_suspend,
+	.resume		= innovator1510_panel_resume,
+	.driver		= {
+		.name	= "lcd_inn1510",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int innovator1510_panel_drv_init(void)
+{
+	return platform_driver_register(&innovator1510_panel_driver);
+}
+
+static void innovator1510_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&innovator1510_panel_driver);
+}
+
+module_init(innovator1510_panel_drv_init);
+module_exit(innovator1510_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
new file mode 100644
index 0000000..95604ca
--- /dev/null
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -0,0 +1,150 @@
+/*
+ * LCD panel support for the TI OMAP1610 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME	"omapfb-lcd_h3"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int innovator1610_panel_init(struct lcd_panel *panel,
+				    struct omapfb_device *fbdev)
+{
+	int r = 0;
+
+	if (omap_request_gpio(14)) {
+		pr_err("can't request GPIO 14\n");
+		r = -1;
+		goto exit;
+	}
+	if (omap_request_gpio(15)) {
+		pr_err("can't request GPIO 15\n");
+		omap_free_gpio(14);
+		r = -1;
+		goto exit;
+	}
+	/* configure GPIO(14, 15) as outputs */
+	omap_set_gpio_direction(14, 0);
+	omap_set_gpio_direction(15, 0);
+exit:
+	return r;
+}
+
+static void innovator1610_panel_cleanup(struct lcd_panel *panel)
+{
+	omap_free_gpio(15);
+	omap_free_gpio(14);
+}
+
+static int innovator1610_panel_enable(struct lcd_panel *panel)
+{
+	/* set GPIO14 and GPIO15 high */
+	omap_set_gpio_dataout(14, 1);
+	omap_set_gpio_dataout(15, 1);
+	return 0;
+}
+
+static void innovator1610_panel_disable(struct lcd_panel *panel)
+{
+	/* set GPIO13, GPIO14 and GPIO15 low */
+	omap_set_gpio_dataout(14, 0);
+	omap_set_gpio_dataout(15, 0);
+}
+
+static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel innovator1610_panel = {
+	.name		= "inn1610",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 320,
+	.y_res		= 240,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= innovator1610_panel_init,
+	.cleanup	= innovator1610_panel_cleanup,
+	.enable		= innovator1610_panel_enable,
+	.disable	= innovator1610_panel_disable,
+	.get_caps	= innovator1610_panel_get_caps,
+};
+
+static int innovator1610_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&innovator1610_panel);
+	return 0;
+}
+
+static int innovator1610_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int innovator1610_panel_suspend(struct platform_device *pdev,
+				       pm_message_t mesg)
+{
+	return 0;
+}
+
+static int innovator1610_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver innovator1610_panel_driver = {
+	.probe		= innovator1610_panel_probe,
+	.remove		= innovator1610_panel_remove,
+	.suspend	= innovator1610_panel_suspend,
+	.resume		= innovator1610_panel_resume,
+	.driver		= {
+		.name	= "lcd_inn1610",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int innovator1610_panel_drv_init(void)
+{
+	return platform_driver_register(&innovator1610_panel_driver);
+}
+
+static void innovator1610_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&innovator1610_panel_driver);
+}
+
+module_init(innovator1610_panel_drv_init);
+module_exit(innovator1610_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
new file mode 100644
index 0000000..a380388
--- /dev/null
+++ b/drivers/video/omap/lcd_osk.c
@@ -0,0 +1,144 @@
+/*
+ * LCD panel support for the TI OMAP OSK board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ * Adapted for OSK by <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
+
+static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void osk_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int osk_panel_enable(struct lcd_panel *panel)
+{
+	/* configure PWL pin */
+	omap_cfg_reg(PWL);
+
+	/* Enable PWL unit */
+	omap_writeb(0x01, OMAP_PWL_CLK_ENABLE);
+
+	/* Set PWL level */
+	omap_writeb(0xFF, OMAP_PWL_ENABLE);
+
+	/* configure GPIO2 as output */
+	omap_set_gpio_direction(2, 0);
+
+	/* set GPIO2 high */
+	omap_set_gpio_dataout(2, 1);
+
+	return 0;
+}
+
+static void osk_panel_disable(struct lcd_panel *panel)
+{
+	/* Set PWL level to zero */
+	omap_writeb(0x00, OMAP_PWL_ENABLE);
+
+	/* Disable PWL unit */
+	omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
+
+	/* set GPIO2 low */
+	omap_set_gpio_dataout(2, 0);
+}
+
+static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel osk_panel = {
+	.name		= "osk",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= osk_panel_init,
+	.cleanup	= osk_panel_cleanup,
+	.enable		= osk_panel_enable,
+	.disable	= osk_panel_disable,
+	.get_caps	= osk_panel_get_caps,
+};
+
+static int osk_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&osk_panel);
+	return 0;
+}
+
+static int osk_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int osk_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int osk_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver osk_panel_driver = {
+	.probe		= osk_panel_probe,
+	.remove		= osk_panel_remove,
+	.suspend	= osk_panel_suspend,
+	.resume		= osk_panel_resume,
+	.driver		= {
+		.name	= "lcd_osk",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int osk_panel_drv_init(void)
+{
+	return platform_driver_register(&osk_panel_driver);
+}
+
+static void osk_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&osk_panel_driver);
+}
+
+module_init(osk_panel_drv_init);
+module_exit(osk_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
new file mode 100644
index 0000000..52bdfda
--- /dev/null
+++ b/drivers/video/omap/lcd_palmte.c
@@ -0,0 +1,123 @@
+/*
+ * LCD panel support for the Palm Tungsten E
+ *
+ * Original version : Romain Goyet <r.goyet@gmail.com>
+ * Current version : Laurent Gonzalez <palmte.linux@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/omapfb.h>
+
+static int palmte_panel_init(struct lcd_panel *panel,
+				struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmte_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int palmte_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmte_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmte_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel palmte_panel = {
+	.name		= "palmte",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			  OMAP_LCDC_HSVS_OPPOSITE,
+
+	.data_lines	= 16,
+	.bpp		= 8,
+	.pixel_clock	= 12000,
+	.x_res		= 320,
+	.y_res		= 320,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmte_panel_init,
+	.cleanup	= palmte_panel_cleanup,
+	.enable		= palmte_panel_enable,
+	.disable	= palmte_panel_disable,
+	.get_caps	= palmte_panel_get_caps,
+};
+
+static int palmte_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmte_panel);
+	return 0;
+}
+
+static int palmte_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmte_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmte_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver palmte_panel_driver = {
+	.probe		= palmte_panel_probe,
+	.remove		= palmte_panel_remove,
+	.suspend	= palmte_panel_suspend,
+	.resume		= palmte_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmte",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int palmte_panel_drv_init(void)
+{
+	return platform_driver_register(&palmte_panel_driver);
+}
+
+static void palmte_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&palmte_panel_driver);
+}
+
+module_init(palmte_panel_drv_init);
+module_exit(palmte_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
new file mode 100644
index 0000000..4bb349f
--- /dev/null
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -0,0 +1,127 @@
+/*
+ * LCD panel support for Palm Tungsten|T
+ * Current version : Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Modified from lcd_inn1510.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+GPIO11 - backlight
+GPIO12 - screen blanking
+GPIO13 - screen blanking
+*/
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+
+static int palmtt_panel_init(struct lcd_panel *panel,
+	struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmtt_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int palmtt_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmtt_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmtt_panel_get_caps(struct lcd_panel *panel)
+{
+	return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+struct lcd_panel palmtt_panel = {
+	.name		= "palmtt",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			OMAP_LCDC_HSVS_OPPOSITE,
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 320,
+	.y_res		= 320,
+	.pixel_clock	= 10000,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmtt_panel_init,
+	.cleanup	= palmtt_panel_cleanup,
+	.enable		= palmtt_panel_enable,
+	.disable	= palmtt_panel_disable,
+	.get_caps	= palmtt_panel_get_caps,
+};
+
+static int palmtt_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmtt_panel);
+	return 0;
+}
+
+static int palmtt_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmtt_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmtt_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver palmtt_panel_driver = {
+	.probe		= palmtt_panel_probe,
+	.remove		= palmtt_panel_remove,
+	.suspend	= palmtt_panel_suspend,
+	.resume		= palmtt_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmtt",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int palmtt_panel_drv_init(void)
+{
+	return platform_driver_register(&palmtt_panel_driver);
+}
+
+static void palmtt_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&palmtt_panel_driver);
+}
+
+module_init(palmtt_panel_drv_init);
+module_exit(palmtt_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
new file mode 100644
index 0000000..ea6170d
--- /dev/null
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -0,0 +1,123 @@
+/*
+ * LCD panel support for the Palm Zire71
+ *
+ * Original version : Romain Goyet
+ * Current version : Laurent Gonzalez
+ * Modified for zire71 : Marek Vasut
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/omapfb.h>
+
+static int palmz71_panel_init(struct lcd_panel *panel,
+			      struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmz71_panel_cleanup(struct lcd_panel *panel)
+{
+
+}
+
+static int palmz71_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmz71_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmz71_panel_get_caps(struct lcd_panel *panel)
+{
+	return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+struct lcd_panel palmz71_panel = {
+	.name		= "palmz71",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			  OMAP_LCDC_HSVS_OPPOSITE,
+	.data_lines	= 16,
+	.bpp		= 16,
+	.pixel_clock	= 24000,
+	.x_res		= 320,
+	.y_res		= 320,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmz71_panel_init,
+	.cleanup	= palmz71_panel_cleanup,
+	.enable		= palmz71_panel_enable,
+	.disable	= palmz71_panel_disable,
+	.get_caps	= palmz71_panel_get_caps,
+};
+
+static int palmz71_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmz71_panel);
+	return 0;
+}
+
+static int palmz71_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmz71_panel_suspend(struct platform_device *pdev,
+				 pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmz71_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver palmz71_panel_driver = {
+	.probe		= palmz71_panel_probe,
+	.remove		= palmz71_panel_remove,
+	.suspend	= palmz71_panel_suspend,
+	.resume		= palmz71_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmz71",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int palmz71_panel_drv_init(void)
+{
+	return platform_driver_register(&palmz71_panel_driver);
+}
+
+static void palmz71_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&palmz71_panel_driver);
+}
+
+module_init(palmz71_panel_drv_init);
+module_exit(palmz71_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c
new file mode 100644
index 0000000..c4f306a
--- /dev/null
+++ b/drivers/video/omap/lcd_sx1.c
@@ -0,0 +1,334 @@
+/*
+ * LCD panel support for the Siemens SX1 mobile phone
+ *
+ * Current version : Vovan888@gmail.com, great help from FCA00000
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/mux.h>
+
+/*
+ * OMAP310 GPIO registers
+ */
+#define GPIO_DATA_INPUT		0xfffce000
+#define GPIO_DATA_OUTPUT	0xfffce004
+#define GPIO_DIR_CONTROL	0xfffce008
+#define GPIO_INT_CONTROL	0xfffce00c
+#define GPIO_INT_MASK		0xfffce010
+#define GPIO_INT_STATUS		0xfffce014
+#define GPIO_PIN_CONTROL	0xfffce018
+
+
+#define A_LCD_SSC_RD	3
+#define A_LCD_SSC_SD	7
+#define _A_LCD_RESET	9
+#define _A_LCD_SSC_CS	12
+#define _A_LCD_SSC_A0	13
+
+#define DSP_REG		0xE1017024
+
+const unsigned char INIT_1[12] = {
+	0x1C, 0x02, 0x88, 0x00, 0x1E, 0xE0, 0x00, 0xDC, 0x00, 0x02, 0x00
+};
+
+const unsigned char INIT_2[127] = {
+	0x15, 0x00, 0x29, 0x00, 0x3E, 0x00, 0x51, 0x00,
+	0x65, 0x00, 0x7A, 0x00, 0x8D, 0x00, 0xA1, 0x00,
+	0xB6, 0x00, 0xC7, 0x00, 0xD8, 0x00, 0xEB, 0x00,
+	0xFB, 0x00, 0x0B, 0x01, 0x1B, 0x01, 0x27, 0x01,
+	0x34, 0x01, 0x41, 0x01, 0x4C, 0x01, 0x55, 0x01,
+	0x5F, 0x01, 0x68, 0x01, 0x70, 0x01, 0x78, 0x01,
+	0x7E, 0x01, 0x86, 0x01, 0x8C, 0x01, 0x94, 0x01,
+	0x9B, 0x01, 0xA1, 0x01, 0xA4, 0x01, 0xA9, 0x01,
+	0xAD, 0x01, 0xB2, 0x01, 0xB7, 0x01, 0xBC, 0x01,
+	0xC0, 0x01, 0xC4, 0x01, 0xC8, 0x01, 0xCB, 0x01,
+	0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01,
+	0xDB, 0x01, 0xE0, 0x01, 0xE3, 0x01, 0xE6, 0x01,
+	0xE8, 0x01, 0xEB, 0x01, 0xEE, 0x01, 0xF1, 0x01,
+	0xF3, 0x01, 0xF8, 0x01, 0xF9, 0x01, 0xFC, 0x01,
+	0x00, 0x02, 0x03, 0x02, 0x07, 0x02, 0x09, 0x02,
+	0x0E, 0x02, 0x13, 0x02, 0x1C, 0x02, 0x00
+};
+
+const unsigned char INIT_3[15] = {
+	0x14, 0x26, 0x33, 0x3D, 0x45, 0x4D, 0x53, 0x59,
+	0x5E, 0x63, 0x67, 0x6D, 0x71, 0x78, 0xFF
+};
+
+static void epson_sendbyte(int flag, unsigned char byte)
+{
+	int i, shifter = 0x80;
+
+	if (!flag)
+		omap_set_gpio_dataout(_A_LCD_SSC_A0, 0);
+	mdelay(2);
+	omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
+
+	omap_set_gpio_dataout(A_LCD_SSC_SD, flag);
+
+	OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
+	OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
+	for (i = 0; i < 8; i++) {
+		OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
+		omap_set_gpio_dataout(A_LCD_SSC_SD, shifter & byte);
+		OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
+		shifter >>= 1;
+	}
+	omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+}
+
+static void init_system(void)
+{
+	omap_mcbsp_request(OMAP_MCBSP3);
+	omap_mcbsp_stop(OMAP_MCBSP3);
+}
+
+static void setup_GPIO(void)
+{
+	/* new wave */
+	omap_request_gpio(A_LCD_SSC_RD);
+	omap_request_gpio(A_LCD_SSC_SD);
+	omap_request_gpio(_A_LCD_RESET);
+	omap_request_gpio(_A_LCD_SSC_CS);
+	omap_request_gpio(_A_LCD_SSC_A0);
+
+	/* set all GPIOs to output */
+	omap_set_gpio_direction(A_LCD_SSC_RD, 0);
+	omap_set_gpio_direction(A_LCD_SSC_SD, 0);
+	omap_set_gpio_direction(_A_LCD_RESET, 0);
+	omap_set_gpio_direction(_A_LCD_SSC_CS, 0);
+	omap_set_gpio_direction(_A_LCD_SSC_A0, 0);
+
+	/* set GPIO data */
+	omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
+	omap_set_gpio_dataout(A_LCD_SSC_SD, 0);
+	omap_set_gpio_dataout(_A_LCD_RESET, 0);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+}
+
+static void display_init(void)
+{
+	int i;
+
+	omap_cfg_reg(MCBSP3_CLKX);
+
+	mdelay(2);
+	setup_GPIO();
+	mdelay(2);
+
+	/* reset LCD */
+	omap_set_gpio_dataout(A_LCD_SSC_SD, 1);
+	epson_sendbyte(0, 0x25);
+
+	omap_set_gpio_dataout(_A_LCD_RESET, 0);
+	mdelay(10);
+	omap_set_gpio_dataout(_A_LCD_RESET, 1);
+
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	mdelay(2);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD, phase 1 */
+	epson_sendbyte(0, 0xCA);
+	for (i = 0; i < 10; i++)
+		epson_sendbyte(1, INIT_1[i]);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 2 */
+	epson_sendbyte(0, 0xCB);
+	for (i = 0; i < 125; i++)
+		epson_sendbyte(1, INIT_2[i]);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 2a */
+	epson_sendbyte(0, 0xCC);
+	for (i = 0; i < 14; i++)
+		epson_sendbyte(1, INIT_3[i]);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 3 */
+	epson_sendbyte(0, 0xBC);
+	epson_sendbyte(1, 0x08);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 4 */
+	epson_sendbyte(0, 0x07);
+	epson_sendbyte(1, 0x05);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 5 */
+	epson_sendbyte(0, 0x94);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 6 */
+	epson_sendbyte(0, 0xC6);
+	epson_sendbyte(1, 0x80);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	mdelay(100); /* used to be 1000 */
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 7 */
+	epson_sendbyte(0, 0x16);
+	epson_sendbyte(1, 0x02);
+	epson_sendbyte(1, 0x00);
+	epson_sendbyte(1, 0xB1);
+	epson_sendbyte(1, 0x00);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 8 */
+	epson_sendbyte(0, 0x76);
+	epson_sendbyte(1, 0x00);
+	epson_sendbyte(1, 0x00);
+	epson_sendbyte(1, 0xDB);
+	epson_sendbyte(1, 0x00);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	/* init LCD phase 9 */
+	epson_sendbyte(0, 0xAF);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+}
+
+static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void sx1_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static void sx1_panel_disable(struct lcd_panel *panel)
+{
+	printk(KERN_INFO "SX1: LCD panel disable\n");
+	sx1_setmmipower(0);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+
+	epson_sendbyte(0, 0x25);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	epson_sendbyte(0, 0xAE);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+	mdelay(100);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+	epson_sendbyte(0, 0x95);
+	omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+}
+
+static int sx1_panel_enable(struct lcd_panel *panel)
+{
+	printk(KERN_INFO "lcd_sx1: LCD panel enable\n");
+	init_system();
+	display_init();
+
+	sx1_setmmipower(1);
+	sx1_setbacklight(0x18);
+	sx1_setkeylight (0x06);
+	return 0;
+}
+
+
+static unsigned long sx1_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel sx1_panel = {
+	.name		= "sx1",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_INV_PIX_CLOCK |
+			  OMAP_LCDC_INV_OUTPUT_EN,
+
+	.x_res		= 176,
+	.y_res		= 220,
+	.data_lines	= 16,
+	.bpp		= 16,
+	.hsw		= 5,
+	.hfp		= 5,
+	.hbp		= 5,
+	.vsw		= 2,
+	.vfp		= 1,
+	.vbp		= 1,
+	.pixel_clock	= 1500,
+
+	.init		= sx1_panel_init,
+	.cleanup	= sx1_panel_cleanup,
+	.enable		= sx1_panel_enable,
+	.disable	= sx1_panel_disable,
+	.get_caps	= sx1_panel_get_caps,
+};
+
+static int sx1_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&sx1_panel);
+	return 0;
+}
+
+static int sx1_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int sx1_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int sx1_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver sx1_panel_driver = {
+	.probe		= sx1_panel_probe,
+	.remove		= sx1_panel_remove,
+	.suspend	= sx1_panel_suspend,
+	.resume		= sx1_panel_resume,
+	.driver	= {
+		.name	= "lcd_sx1",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int sx1_panel_drv_init(void)
+{
+	return platform_driver_register(&sx1_panel_driver);
+}
+
+static void sx1_panel_drv_cleanup(void)
+{
+	platform_driver_unregister(&sx1_panel_driver);
+}
+
+module_init(sx1_panel_drv_init);
+module_exit(sx1_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
new file mode 100644
index 0000000..9085188
--- /dev/null
+++ b/drivers/video/omap/lcdc.c
@@ -0,0 +1,893 @@
+/*
+ * OMAP1 internal LCD controller
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#include <asm/mach-types.h>
+
+#define MODULE_NAME			"lcdc"
+
+#define OMAP_LCDC_BASE			0xfffec000
+#define OMAP_LCDC_SIZE			256
+#define OMAP_LCDC_IRQ			INT_LCD_CTRL
+
+#define OMAP_LCDC_CONTROL		(OMAP_LCDC_BASE + 0x00)
+#define OMAP_LCDC_TIMING0		(OMAP_LCDC_BASE + 0x04)
+#define OMAP_LCDC_TIMING1		(OMAP_LCDC_BASE + 0x08)
+#define OMAP_LCDC_TIMING2		(OMAP_LCDC_BASE + 0x0c)
+#define OMAP_LCDC_STATUS		(OMAP_LCDC_BASE + 0x10)
+#define OMAP_LCDC_SUBPANEL		(OMAP_LCDC_BASE + 0x14)
+#define OMAP_LCDC_LINE_INT		(OMAP_LCDC_BASE + 0x18)
+#define OMAP_LCDC_DISPLAY_STATUS	(OMAP_LCDC_BASE + 0x1c)
+
+#define OMAP_LCDC_STAT_DONE		(1 << 0)
+#define OMAP_LCDC_STAT_VSYNC		(1 << 1)
+#define OMAP_LCDC_STAT_SYNC_LOST	(1 << 2)
+#define OMAP_LCDC_STAT_ABC		(1 << 3)
+#define OMAP_LCDC_STAT_LINE_INT		(1 << 4)
+#define OMAP_LCDC_STAT_FUF		(1 << 5)
+#define OMAP_LCDC_STAT_LOADED_PALETTE	(1 << 6)
+
+#define OMAP_LCDC_CTRL_LCD_EN		(1 << 0)
+#define OMAP_LCDC_CTRL_LCD_TFT		(1 << 7)
+#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL	(1 << 10)
+
+#define OMAP_LCDC_IRQ_VSYNC		(1 << 2)
+#define OMAP_LCDC_IRQ_DONE		(1 << 3)
+#define OMAP_LCDC_IRQ_LOADED_PALETTE	(1 << 4)
+#define OMAP_LCDC_IRQ_LINE_NIRQ		(1 << 5)
+#define OMAP_LCDC_IRQ_LINE		(1 << 6)
+#define OMAP_LCDC_IRQ_MASK		(((1 << 5) - 1) << 2)
+
+#define MAX_PALETTE_SIZE		PAGE_SIZE
+
+enum lcdc_load_mode {
+	OMAP_LCDC_LOAD_PALETTE,
+	OMAP_LCDC_LOAD_FRAME,
+	OMAP_LCDC_LOAD_PALETTE_AND_FRAME
+};
+
+static struct omap_lcd_controller {
+	enum omapfb_update_mode	update_mode;
+	int			ext_mode;
+
+	unsigned long		frame_offset;
+	int			screen_width;
+	int			xres;
+	int			yres;
+
+	enum omapfb_color_format	color_mode;
+	int			bpp;
+	void			*palette_virt;
+	dma_addr_t		palette_phys;
+	int			palette_code;
+	int			palette_size;
+
+	unsigned int		irq_mask;
+	struct completion	last_frame_complete;
+	struct completion	palette_load_complete;
+	struct clk		*lcd_ck;
+	struct omapfb_device	*fbdev;
+
+	void			(*dma_callback)(void *data);
+	void			*dma_callback_data;
+
+	int			fbmem_allocated;
+	dma_addr_t		vram_phys;
+	void			*vram_virt;
+	unsigned long		vram_size;
+} lcdc;
+
+static void inline enable_irqs(int mask)
+{
+	lcdc.irq_mask |= mask;
+}
+
+static void inline disable_irqs(int mask)
+{
+	lcdc.irq_mask &= ~mask;
+}
+
+static void set_load_mode(enum lcdc_load_mode mode)
+{
+	u32 l;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l &= ~(3 << 20);
+	switch (mode) {
+	case OMAP_LCDC_LOAD_PALETTE:
+		l |= 1 << 20;
+		break;
+	case OMAP_LCDC_LOAD_FRAME:
+		l |= 2 << 20;
+		break;
+	case OMAP_LCDC_LOAD_PALETTE_AND_FRAME:
+		break;
+	default:
+		BUG();
+	}
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void enable_controller(void)
+{
+	u32 l;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l |= OMAP_LCDC_CTRL_LCD_EN;
+	l &= ~OMAP_LCDC_IRQ_MASK;
+	l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE;	/* enabled IRQs */
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller_async(void)
+{
+	u32 l;
+	u32 mask;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK;
+	/*
+	 * Preserve the DONE mask, since we still want to get the
+	 * final DONE irq. It will be disabled in the IRQ handler.
+	 */
+	mask &= ~OMAP_LCDC_IRQ_DONE;
+	l &= ~mask;
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller(void)
+{
+	init_completion(&lcdc.last_frame_complete);
+	disable_controller_async();
+	if (!wait_for_completion_timeout(&lcdc.last_frame_complete,
+				msecs_to_jiffies(500)))
+		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
+}
+
+static void reset_controller(u32 status)
+{
+	static unsigned long reset_count;
+	static unsigned long last_jiffies;
+
+	disable_controller_async();
+	reset_count++;
+	if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {
+		dev_err(lcdc.fbdev->dev,
+			  "resetting (status %#010x,reset count %lu)\n",
+			  status, reset_count);
+		last_jiffies = jiffies;
+	}
+	if (reset_count < 100) {
+		enable_controller();
+	} else {
+		reset_count = 0;
+		dev_err(lcdc.fbdev->dev,
+			"too many reset attempts, giving up.\n");
+	}
+}
+
+/*
+ * Configure the LCD DMA according to the current mode specified by parameters
+ * in lcdc.fbdev and fbdev->var.
+ */
+static void setup_lcd_dma(void)
+{
+	static const int dma_elem_type[] = {
+		0,
+		OMAP_DMA_DATA_TYPE_S8,
+		OMAP_DMA_DATA_TYPE_S16,
+		0,
+		OMAP_DMA_DATA_TYPE_S32,
+	};
+	struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par;
+	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+	unsigned long	src;
+	int		esize, xelem, yelem;
+
+	src = lcdc.vram_phys + lcdc.frame_offset;
+
+	switch (var->rotate) {
+	case 0:
+		if (plane->info.mirror || (src & 3) ||
+		    lcdc.color_mode == OMAPFB_COLOR_YUV420 ||
+		    (lcdc.xres & 1))
+			esize = 2;
+		else
+			esize = 4;
+		xelem = lcdc.xres * lcdc.bpp / 8 / esize;
+		yelem = lcdc.yres;
+		break;
+	case 90:
+	case 180:
+	case 270:
+		if (cpu_is_omap15xx()) {
+			BUG();
+		}
+		esize = 2;
+		xelem = lcdc.yres * lcdc.bpp / 16;
+		yelem = lcdc.xres;
+		break;
+	default:
+		BUG();
+		return;
+	}
+#ifdef VERBOSE
+	dev_dbg(lcdc.fbdev->dev,
+		 "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
+		 src, esize, xelem, yelem);
+#endif
+	omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);
+	if (!cpu_is_omap15xx()) {
+		int bpp = lcdc.bpp;
+
+		/*
+		 * YUV support is only for external mode when we have the
+		 * YUV window embedded in a 16bpp frame buffer.
+		 */
+		if (lcdc.color_mode == OMAPFB_COLOR_YUV420)
+			bpp = 16;
+		/* Set virtual xres elem size */
+		omap_set_lcd_dma_b1_vxres(
+			lcdc.screen_width * bpp / 8 / esize);
+		/* Setup transformations */
+		omap_set_lcd_dma_b1_rotation(var->rotate);
+		omap_set_lcd_dma_b1_mirror(plane->info.mirror);
+	}
+	omap_setup_lcd_dma();
+}
+
+static irqreturn_t lcdc_irq_handler(int irq, void *dev_id)
+{
+	u32 status;
+
+	status = omap_readl(OMAP_LCDC_STATUS);
+
+	if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST))
+		reset_controller(status);
+	else {
+		if (status & OMAP_LCDC_STAT_DONE) {
+			u32 l;
+
+			/*
+			 * Disable IRQ_DONE. The status bit will be cleared
+			 * only when the controller is reenabled and we don't
+			 * want to get more interrupts.
+			 */
+			l = omap_readl(OMAP_LCDC_CONTROL);
+			l &= ~OMAP_LCDC_IRQ_DONE;
+			omap_writel(l, OMAP_LCDC_CONTROL);
+			complete(&lcdc.last_frame_complete);
+		}
+		if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {
+			disable_controller_async();
+			complete(&lcdc.palette_load_complete);
+		}
+	}
+
+	/*
+	 * Clear these interrupt status bits.
+	 * Sync_lost, FUF bits were cleared by disabling the LCD controller
+	 * LOADED_PALETTE can be cleared this way only in palette only
+	 * load mode. In other load modes it's cleared by disabling the
+	 * controller.
+	 */
+	status &= ~(OMAP_LCDC_STAT_VSYNC |
+		    OMAP_LCDC_STAT_LOADED_PALETTE |
+		    OMAP_LCDC_STAT_ABC |
+		    OMAP_LCDC_STAT_LINE_INT);
+	omap_writel(status, OMAP_LCDC_STATUS);
+	return IRQ_HANDLED;
+}
+
+/*
+ * Change to a new video mode. We defer this to a later time to avoid any
+ * flicker and not to mess up the current LCD DMA context. For this we disable
+ * the LCD controler, which will generate a DONE irq after the last frame has
+ * been transferred. Then it'll be safe to reconfigure both the LCD controller
+ * as well as the LCD DMA.
+ */
+static int omap_lcdc_setup_plane(int plane, int channel_out,
+				 unsigned long offset, int screen_width,
+				 int pos_x, int pos_y, int width, int height,
+				 int color_mode)
+{
+	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+	int rot_x, rot_y;
+
+	if (var->rotate == 0) {
+		rot_x = panel->x_res;
+		rot_y = panel->y_res;
+	} else {
+		rot_x = panel->y_res;
+		rot_y = panel->x_res;
+	}
+	if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||
+	    width > rot_x || height > rot_y) {
+#ifdef VERBOSE
+		dev_dbg(lcdc.fbdev->dev,
+			"invalid plane params plane %d pos_x %d pos_y %d "
+			"w %d h %d\n", plane, pos_x, pos_y, width, height);
+#endif
+		return -EINVAL;
+	}
+
+	lcdc.frame_offset = offset;
+	lcdc.xres = width;
+	lcdc.yres = height;
+	lcdc.screen_width = screen_width;
+	lcdc.color_mode = color_mode;
+
+	switch (color_mode) {
+	case OMAPFB_COLOR_CLUT_8BPP:
+		lcdc.bpp = 8;
+		lcdc.palette_code = 0x3000;
+		lcdc.palette_size = 512;
+		break;
+	case OMAPFB_COLOR_RGB565:
+		lcdc.bpp = 16;
+		lcdc.palette_code = 0x4000;
+		lcdc.palette_size = 32;
+		break;
+	case OMAPFB_COLOR_RGB444:
+		lcdc.bpp = 16;
+		lcdc.palette_code = 0x4000;
+		lcdc.palette_size = 32;
+		break;
+	case OMAPFB_COLOR_YUV420:
+		if (lcdc.ext_mode) {
+			lcdc.bpp = 12;
+			break;
+		}
+		/* fallthrough */
+	case OMAPFB_COLOR_YUV422:
+		if (lcdc.ext_mode) {
+			lcdc.bpp = 16;
+			break;
+		}
+		/* fallthrough */
+	default:
+		/* FIXME: other BPPs.
+		 * bpp1: code  0,     size 256
+		 * bpp2: code  0x1000 size 256
+		 * bpp4: code  0x2000 size 256
+		 * bpp12: code 0x4000 size 32
+		 */
+		dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode);
+		BUG();
+		return -1;
+	}
+
+	if (lcdc.ext_mode) {
+		setup_lcd_dma();
+		return 0;
+	}
+
+	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+		disable_controller();
+		omap_stop_lcd_dma();
+		setup_lcd_dma();
+		enable_controller();
+	}
+
+	return 0;
+}
+
+static int omap_lcdc_enable_plane(int plane, int enable)
+{
+	dev_dbg(lcdc.fbdev->dev,
+		"plane %d enable %d update_mode %d ext_mode %d\n",
+		plane, enable, lcdc.update_mode, lcdc.ext_mode);
+	if (plane != OMAPFB_PLANE_GFX)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Configure the LCD DMA for a palette load operation and do the palette
+ * downloading synchronously. We don't use the frame+palette load mode of
+ * the controller, since the palette can always be downloaded seperately.
+ */
+static void load_palette(void)
+{
+	u16	*palette;
+
+	palette = (u16 *)lcdc.palette_virt;
+
+	*(u16 *)palette &= 0x0fff;
+	*(u16 *)palette |= lcdc.palette_code;
+
+	omap_set_lcd_dma_b1(lcdc.palette_phys,
+		lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
+
+	omap_set_lcd_dma_single_transfer(1);
+	omap_setup_lcd_dma();
+
+	init_completion(&lcdc.palette_load_complete);
+	enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+	set_load_mode(OMAP_LCDC_LOAD_PALETTE);
+	enable_controller();
+	if (!wait_for_completion_timeout(&lcdc.palette_load_complete,
+				msecs_to_jiffies(500)))
+		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
+	/* The controller gets disabled in the irq handler */
+	disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+	omap_stop_lcd_dma();
+
+	omap_set_lcd_dma_single_transfer(lcdc.ext_mode);
+}
+
+/* Used only in internal controller mode */
+static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,
+			       u16 transp, int update_hw_pal)
+{
+	u16 *palette;
+
+	if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
+		return -EINVAL;
+
+	palette = (u16 *)lcdc.palette_virt;
+
+	palette[regno] &= ~0x0fff;
+	palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |
+			   (blue >> 12);
+
+	if (update_hw_pal) {
+		disable_controller();
+		omap_stop_lcd_dma();
+		load_palette();
+		setup_lcd_dma();
+		set_load_mode(OMAP_LCDC_LOAD_FRAME);
+		enable_controller();
+	}
+
+	return 0;
+}
+
+static void calc_ck_div(int is_tft, int pck, int *pck_div)
+{
+	unsigned long lck;
+
+	pck = max(1, pck);
+	lck = clk_get_rate(lcdc.lcd_ck);
+	*pck_div = (lck + pck - 1) / pck;
+	if (is_tft)
+		*pck_div = max(2, *pck_div);
+	else
+		*pck_div = max(3, *pck_div);
+	if (*pck_div > 255) {
+		/* FIXME: try to adjust logic clock divider as well */
+		*pck_div = 255;
+		dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n",
+			 pck / 1000);
+	}
+}
+
+static void inline setup_regs(void)
+{
+	u32 l;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+	int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+	unsigned long lck;
+	int pcd;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l &= ~OMAP_LCDC_CTRL_LCD_TFT;
+	l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0;
+#ifdef CONFIG_MACH_OMAP_PALMTE
+/* FIXME:if (machine_is_omap_palmte()) { */
+		/* PalmTE uses alternate TFT setting in 8BPP mode */
+		l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0;
+/*	} */
+#endif
+	omap_writel(l, OMAP_LCDC_CONTROL);
+
+	l = omap_readl(OMAP_LCDC_TIMING2);
+	l &= ~(((1 << 6) - 1) << 20);
+	l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20;
+	omap_writel(l, OMAP_LCDC_TIMING2);
+
+	l = panel->x_res - 1;
+	l |= (panel->hsw - 1) << 10;
+	l |= (panel->hfp - 1) << 16;
+	l |= (panel->hbp - 1) << 24;
+	omap_writel(l, OMAP_LCDC_TIMING0);
+
+	l = panel->y_res - 1;
+	l |= (panel->vsw - 1) << 10;
+	l |= panel->vfp << 16;
+	l |= panel->vbp << 24;
+	omap_writel(l, OMAP_LCDC_TIMING1);
+
+	l = omap_readl(OMAP_LCDC_TIMING2);
+	l &= ~0xff;
+
+	lck = clk_get_rate(lcdc.lcd_ck);
+
+	if (!panel->pcd)
+		calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);
+	else {
+		dev_warn(lcdc.fbdev->dev,
+		    "Pixel clock divider value is obsolete.\n"
+		    "Try to set pixel_clock to %lu and pcd to 0 "
+		    "in drivers/video/omap/lcd_%s.c and submit a patch.\n",
+			lck / panel->pcd / 1000, panel->name);
+
+		pcd = panel->pcd;
+	}
+	l |= pcd & 0xff;
+	l |= panel->acb << 8;
+	omap_writel(l, OMAP_LCDC_TIMING2);
+
+	/* update panel info with the exact clock */
+	panel->pixel_clock = lck / pcd / 1000;
+}
+
+/*
+ * Configure the LCD controller, download the color palette and start a looped
+ * DMA transfer of the frame image data. Called only in internal
+ * controller mode.
+ */
+static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
+{
+	int r = 0;
+
+	if (mode != lcdc.update_mode) {
+		switch (mode) {
+		case OMAPFB_AUTO_UPDATE:
+			setup_regs();
+			load_palette();
+
+			/* Setup and start LCD DMA */
+			setup_lcd_dma();
+
+			set_load_mode(OMAP_LCDC_LOAD_FRAME);
+			enable_irqs(OMAP_LCDC_IRQ_DONE);
+			/* This will start the actual DMA transfer */
+			enable_controller();
+			lcdc.update_mode = mode;
+			break;
+		case OMAPFB_UPDATE_DISABLED:
+			disable_controller();
+			omap_stop_lcd_dma();
+			lcdc.update_mode = mode;
+			break;
+		default:
+			r = -EINVAL;
+		}
+	}
+
+	return r;
+}
+
+static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
+{
+	return lcdc.update_mode;
+}
+
+/* PM code called only in internal controller mode */
+static void omap_lcdc_suspend(void)
+{
+	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+		disable_controller();
+		omap_stop_lcd_dma();
+	}
+}
+
+static void omap_lcdc_resume(void)
+{
+	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+		setup_regs();
+		load_palette();
+		setup_lcd_dma();
+		set_load_mode(OMAP_LCDC_LOAD_FRAME);
+		enable_irqs(OMAP_LCDC_IRQ_DONE);
+		enable_controller();
+	}
+}
+
+static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
+{
+	return;
+}
+
+int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data)
+{
+	BUG_ON(callback == NULL);
+
+	if (lcdc.dma_callback)
+		return -EBUSY;
+	else {
+		lcdc.dma_callback = callback;
+		lcdc.dma_callback_data = data;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(omap_lcdc_set_dma_callback);
+
+void omap_lcdc_free_dma_callback(void)
+{
+	lcdc.dma_callback = NULL;
+}
+EXPORT_SYMBOL(omap_lcdc_free_dma_callback);
+
+static void lcdc_dma_handler(u16 status, void *data)
+{
+	if (lcdc.dma_callback)
+		lcdc.dma_callback(lcdc.dma_callback_data);
+}
+
+static int mmap_kern(void)
+{
+	struct vm_struct	*kvma;
+	struct vm_area_struct	vma;
+	pgprot_t		pgprot;
+	unsigned long		vaddr;
+
+	kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP);
+	if (kvma == NULL) {
+		dev_err(lcdc.fbdev->dev, "can't get kernel vm area\n");
+		return -ENOMEM;
+	}
+	vma.vm_mm = &init_mm;
+
+	vaddr = (unsigned long)kvma->addr;
+	vma.vm_start = vaddr;
+	vma.vm_end = vaddr + lcdc.vram_size;
+
+	pgprot = pgprot_writecombine(pgprot_kernel);
+	if (io_remap_pfn_range(&vma, vaddr,
+			   lcdc.vram_phys >> PAGE_SHIFT,
+			   lcdc.vram_size, pgprot) < 0) {
+		dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n");
+		return -EAGAIN;
+	}
+
+	lcdc.vram_virt = (void *)vaddr;
+
+	return 0;
+}
+
+static void unmap_kern(void)
+{
+	vunmap(lcdc.vram_virt);
+}
+
+static int alloc_palette_ram(void)
+{
+	lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+		MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL);
+	if (lcdc.palette_virt == NULL) {
+		dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");
+		return -ENOMEM;
+	}
+	memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE);
+
+	return 0;
+}
+
+static void free_palette_ram(void)
+{
+	dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
+			lcdc.palette_virt, lcdc.palette_phys);
+}
+
+static int alloc_fbmem(struct omapfb_mem_region *region)
+{
+	int bpp;
+	int frame_size;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+
+	bpp = panel->bpp;
+	if (bpp == 12)
+		bpp = 16;
+	frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res);
+	if (region->size > frame_size)
+		frame_size = region->size;
+	lcdc.vram_size = frame_size;
+	lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+			lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL);
+	if (lcdc.vram_virt == NULL) {
+		dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");
+		return -ENOMEM;
+	}
+	region->size = frame_size;
+	region->paddr = lcdc.vram_phys;
+	region->vaddr = lcdc.vram_virt;
+	region->alloc = 1;
+
+	memset(lcdc.vram_virt, 0, lcdc.vram_size);
+
+	return 0;
+}
+
+static void free_fbmem(void)
+{
+	dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size,
+			      lcdc.vram_virt, lcdc.vram_phys);
+}
+
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
+{
+	int r;
+
+	if (!req_md->region_cnt) {
+		dev_err(lcdc.fbdev->dev, "no memory regions defined\n");
+		return -EINVAL;
+	}
+
+	if (req_md->region_cnt > 1) {
+		dev_err(lcdc.fbdev->dev, "only one plane is supported\n");
+		req_md->region_cnt = 1;
+	}
+
+	if (req_md->region[0].paddr == 0) {
+		lcdc.fbmem_allocated = 1;
+		if ((r = alloc_fbmem(&req_md->region[0])) < 0)
+			return r;
+		return 0;
+	}
+
+	lcdc.vram_phys = req_md->region[0].paddr;
+	lcdc.vram_size = req_md->region[0].size;
+
+	if ((r = mmap_kern()) < 0)
+		return r;
+
+	dev_dbg(lcdc.fbdev->dev, "vram at %08x size %08lx mapped to 0x%p\n",
+		 lcdc.vram_phys, lcdc.vram_size, lcdc.vram_virt);
+
+	return 0;
+}
+
+static void cleanup_fbmem(void)
+{
+	if (lcdc.fbmem_allocated)
+		free_fbmem();
+	else
+		unmap_kern();
+}
+
+static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
+			  struct omapfb_mem_desc *req_vram)
+{
+	int r;
+	u32 l;
+	int rate;
+	struct clk *tc_ck;
+
+	lcdc.irq_mask = 0;
+
+	lcdc.fbdev = fbdev;
+	lcdc.ext_mode = ext_mode;
+
+	l = 0;
+	omap_writel(l, OMAP_LCDC_CONTROL);
+
+	/* FIXME:
+	 * According to errata some platforms have a clock rate limitiation
+	 */
+	lcdc.lcd_ck = clk_get(NULL, "lcd_ck");
+	if (IS_ERR(lcdc.lcd_ck)) {
+		dev_err(fbdev->dev, "unable to access LCD clock\n");
+		r = PTR_ERR(lcdc.lcd_ck);
+		goto fail0;
+	}
+
+	tc_ck = clk_get(NULL, "tc_ck");
+	if (IS_ERR(tc_ck)) {
+		dev_err(fbdev->dev, "unable to access TC clock\n");
+		r = PTR_ERR(tc_ck);
+		goto fail1;
+	}
+
+	rate = clk_get_rate(tc_ck);
+	clk_put(tc_ck);
+
+	if (machine_is_ams_delta())
+		rate /= 4;
+	if (machine_is_omap_h3())
+		rate /= 3;
+	r = clk_set_rate(lcdc.lcd_ck, rate);
+	if (r) {
+		dev_err(fbdev->dev, "failed to adjust LCD rate\n");
+		goto fail1;
+	}
+	clk_enable(lcdc.lcd_ck);
+
+	r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
+	if (r) {
+		dev_err(fbdev->dev, "unable to get IRQ\n");
+		goto fail2;
+	}
+
+	r = omap_request_lcd_dma(lcdc_dma_handler, NULL);
+	if (r) {
+		dev_err(fbdev->dev, "unable to get LCD DMA\n");
+		goto fail3;
+	}
+
+	omap_set_lcd_dma_single_transfer(ext_mode);
+	omap_set_lcd_dma_ext_controller(ext_mode);
+
+	if (!ext_mode)
+		if ((r = alloc_palette_ram()) < 0)
+			goto fail4;
+
+	if ((r = setup_fbmem(req_vram)) < 0)
+		goto fail5;
+
+	pr_info("omapfb: LCDC initialized\n");
+
+	return 0;
+fail5:
+	if (!ext_mode)
+		free_palette_ram();
+fail4:
+	omap_free_lcd_dma();
+fail3:
+	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+fail2:
+	clk_disable(lcdc.lcd_ck);
+fail1:
+	clk_put(lcdc.lcd_ck);
+fail0:
+	return r;
+}
+
+static void omap_lcdc_cleanup(void)
+{
+	if (!lcdc.ext_mode)
+		free_palette_ram();
+	cleanup_fbmem();
+	omap_free_lcd_dma();
+	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+	clk_disable(lcdc.lcd_ck);
+	clk_put(lcdc.lcd_ck);
+}
+
+const struct lcd_ctrl omap1_int_ctrl = {
+	.name			= "internal",
+	.init			= omap_lcdc_init,
+	.cleanup		= omap_lcdc_cleanup,
+	.get_caps		= omap_lcdc_get_caps,
+	.set_update_mode	= omap_lcdc_set_update_mode,
+	.get_update_mode	= omap_lcdc_get_update_mode,
+	.update_window		= NULL,
+	.suspend		= omap_lcdc_suspend,
+	.resume			= omap_lcdc_resume,
+	.setup_plane		= omap_lcdc_setup_plane,
+	.enable_plane		= omap_lcdc_enable_plane,
+	.setcolreg		= omap_lcdc_setcolreg,
+};
diff --git a/drivers/video/omap/lcdc.h b/drivers/video/omap/lcdc.h
new file mode 100644
index 0000000..adb731e5
--- /dev/null
+++ b/drivers/video/omap/lcdc.h
@@ -0,0 +1,7 @@
+#ifndef LCDC_H
+#define LCDC_H
+
+int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
+void omap_lcdc_free_dma_callback(void);
+
+#endif
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
new file mode 100644
index 0000000..14d0f7a
--- /dev/null
+++ b/drivers/video/omap/omapfb_main.c
@@ -0,0 +1,1941 @@
+/*
+ * Framebuffer driver for TI OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * Acknowledgements:
+ *   Alex McMains <aam@ridgerun.com>       - Original driver
+ *   Juha Yrjola <juha.yrjola@nokia.com>   - Original driver and improvements
+ *   Dirk Behme <dirk.behme@de.bosch.com>  - changes for 2.6 kernel API
+ *   Texas Instruments                     - H3 support
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME	"omapfb"
+
+static unsigned int	def_accel;
+static unsigned long	def_vram[OMAPFB_PLANE_NUM];
+static int		def_vram_cnt;
+static unsigned long	def_vxres;
+static unsigned long	def_vyres;
+static unsigned int	def_rotate;
+static unsigned int	def_mirror;
+
+#ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
+static int		manual_update = 1;
+#else
+static int		manual_update;
+#endif
+
+static struct platform_device	*fbdev_pdev;
+static struct lcd_panel		*fbdev_panel;
+static struct omapfb_device	*omapfb_dev;
+
+struct caps_table_struct {
+	unsigned long flag;
+	const char *name;
+};
+
+static struct caps_table_struct ctrl_caps[] = {
+	{ OMAPFB_CAPS_MANUAL_UPDATE,  "manual update" },
+	{ OMAPFB_CAPS_TEARSYNC,       "tearing synchronization" },
+	{ OMAPFB_CAPS_PLANE_RELOCATE_MEM, "relocate plane memory" },
+	{ OMAPFB_CAPS_PLANE_SCALE,    "scale plane" },
+	{ OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
+	{ OMAPFB_CAPS_WINDOW_SCALE,   "scale window" },
+	{ OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
+	{ OMAPFB_CAPS_SET_BACKLIGHT,  "backlight setting" },
+};
+
+static struct caps_table_struct color_caps[] = {
+	{ 1 << OMAPFB_COLOR_RGB565,	"RGB565", },
+	{ 1 << OMAPFB_COLOR_YUV422,	"YUV422", },
+	{ 1 << OMAPFB_COLOR_YUV420,	"YUV420", },
+	{ 1 << OMAPFB_COLOR_CLUT_8BPP,	"CLUT8", },
+	{ 1 << OMAPFB_COLOR_CLUT_4BPP,	"CLUT4", },
+	{ 1 << OMAPFB_COLOR_CLUT_2BPP,	"CLUT2", },
+	{ 1 << OMAPFB_COLOR_CLUT_1BPP,	"CLUT1", },
+	{ 1 << OMAPFB_COLOR_RGB444,	"RGB444", },
+	{ 1 << OMAPFB_COLOR_YUY422,	"YUY422", },
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD panel
+ * ---------------------------------------------------------------------------
+ */
+extern struct lcd_ctrl omap1_int_ctrl;
+extern struct lcd_ctrl omap2_int_ctrl;
+extern struct lcd_ctrl hwa742_ctrl;
+extern struct lcd_ctrl blizzard_ctrl;
+
+static struct lcd_ctrl *ctrls[] = {
+#ifdef CONFIG_ARCH_OMAP1
+	&omap1_int_ctrl,
+#else
+	&omap2_int_ctrl,
+#endif
+
+#ifdef CONFIG_FB_OMAP_LCDC_HWA742
+	&hwa742_ctrl,
+#endif
+#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD
+	&blizzard_ctrl,
+#endif
+};
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+#ifdef CONFIG_ARCH_OMAP1
+extern struct lcd_ctrl_extif omap1_ext_if;
+#else
+extern struct lcd_ctrl_extif omap2_ext_if;
+#endif
+#endif
+
+static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
+{
+	mutex_lock(&fbdev->rqueue_mutex);
+}
+
+static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
+{
+	mutex_unlock(&fbdev->rqueue_mutex);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD controller and LCD DMA
+ * ---------------------------------------------------------------------------
+ */
+/* Lookup table to map elem size to elem type. */
+static const int dma_elem_type[] = {
+	0,
+	OMAP_DMA_DATA_TYPE_S8,
+	OMAP_DMA_DATA_TYPE_S16,
+	0,
+	OMAP_DMA_DATA_TYPE_S32,
+};
+
+/*
+ * Allocate resources needed for LCD controller and LCD DMA operations. Video
+ * memory is allocated from system memory according to the virtual display
+ * size, except if a bigger memory size is specified explicitly as a kernel
+ * parameter.
+ */
+static int ctrl_init(struct omapfb_device *fbdev)
+{
+	int r;
+	int i;
+
+	/* kernel/module vram parameters override boot tags/board config */
+	if (def_vram_cnt) {
+		for (i = 0; i < def_vram_cnt; i++)
+			fbdev->mem_desc.region[i].size =
+				PAGE_ALIGN(def_vram[i]);
+		fbdev->mem_desc.region_cnt = i;
+	} else {
+		struct omapfb_platform_data *conf;
+
+		conf = fbdev->dev->platform_data;
+		fbdev->mem_desc = conf->mem_desc;
+	}
+
+	if (!fbdev->mem_desc.region_cnt) {
+		struct lcd_panel *panel = fbdev->panel;
+		int def_size;
+		int bpp = panel->bpp;
+
+		/* 12 bpp is packed in 16 bits */
+		if (bpp == 12)
+			bpp = 16;
+		def_size = def_vxres * def_vyres * bpp / 8;
+		fbdev->mem_desc.region_cnt = 1;
+		fbdev->mem_desc.region[0].size = PAGE_ALIGN(def_size);
+	}
+	r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc);
+	if (r < 0) {
+		dev_err(fbdev->dev, "controller initialization failed (%d)\n",
+			r);
+		return r;
+	}
+
+#ifdef DEBUG
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n",
+			 i,
+			 fbdev->mem_desc.region[i].paddr,
+			 fbdev->mem_desc.region[i].vaddr,
+			 fbdev->mem_desc.region[i].size);
+	}
+#endif
+	return 0;
+}
+
+static void ctrl_cleanup(struct omapfb_device *fbdev)
+{
+	fbdev->ctrl->cleanup();
+}
+
+/* Must be called with fbdev->rqueue_mutex held. */
+static int ctrl_change_mode(struct fb_info *fbi)
+{
+	int r;
+	unsigned long offset;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var = &fbi->var;
+
+	offset = var->yoffset * fbi->fix.line_length +
+		 var->xoffset * var->bits_per_pixel / 8;
+
+	if (fbdev->ctrl->sync)
+		fbdev->ctrl->sync();
+	r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out,
+				 offset, var->xres_virtual,
+				 plane->info.pos_x, plane->info.pos_y,
+				 var->xres, var->yres, plane->color_mode);
+	if (fbdev->ctrl->set_scale != NULL)
+		r = fbdev->ctrl->set_scale(plane->idx,
+				   var->xres, var->yres,
+				   plane->info.out_width,
+				   plane->info.out_height);
+
+	return r;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks and the ioctl interface
+ * ---------------------------------------------------------------------------
+ */
+/* Called each time the omapfb device is opened */
+static int omapfb_open(struct fb_info *info, int user)
+{
+	return 0;
+}
+
+static void omapfb_sync(struct fb_info *info);
+
+/* Called when the omapfb device is closed. We make sure that any pending
+ * gfx DMA operations are ended, before we return. */
+static int omapfb_release(struct fb_info *info, int user)
+{
+	omapfb_sync(info);
+	return 0;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
+			u_int blue, u_int transp, int update_hw_pal)
+{
+	struct omapfb_plane_struct *plane = info->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var = &info->var;
+	int r = 0;
+
+	switch (plane->color_mode) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUV420:
+	case OMAPFB_COLOR_YUY422:
+		r = -EINVAL;
+		break;
+	case OMAPFB_COLOR_CLUT_8BPP:
+	case OMAPFB_COLOR_CLUT_4BPP:
+	case OMAPFB_COLOR_CLUT_2BPP:
+	case OMAPFB_COLOR_CLUT_1BPP:
+		if (fbdev->ctrl->setcolreg)
+			r = fbdev->ctrl->setcolreg(regno, red, green, blue,
+							transp, update_hw_pal);
+		/* Fallthrough */
+	case OMAPFB_COLOR_RGB565:
+	case OMAPFB_COLOR_RGB444:
+		if (r != 0)
+			break;
+
+		if (regno < 0) {
+			r = -EINVAL;
+			break;
+		}
+
+		if (regno < 16) {
+			u16 pal;
+			pal = ((red >> (16 - var->red.length)) <<
+					var->red.offset) |
+			      ((green >> (16 - var->green.length)) <<
+					var->green.offset) |
+			      (blue >> (16 - var->blue.length));
+			((u32 *)(info->pseudo_palette))[regno] = pal;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return r;
+}
+
+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			    u_int transp, struct fb_info *info)
+{
+	return _setcolreg(info, regno, red, green, blue, transp, 1);
+}
+
+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+	int count, index, r;
+	u16 *red, *green, *blue, *transp;
+	u16 trans = 0xffff;
+
+	red     = cmap->red;
+	green   = cmap->green;
+	blue    = cmap->blue;
+	transp  = cmap->transp;
+	index   = cmap->start;
+
+	for (count = 0; count < cmap->len; count++) {
+		if (transp)
+			trans = *transp++;
+		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+				count == cmap->len - 1);
+		if (r != 0)
+			return r;
+	}
+
+	return 0;
+}
+
+static int omapfb_update_full_screen(struct fb_info *fbi);
+
+static int omapfb_blank(int blank, struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int do_update = 0;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	switch (blank) {
+	case VESA_NO_BLANKING:
+		if (fbdev->state == OMAPFB_SUSPENDED) {
+			if (fbdev->ctrl->resume)
+				fbdev->ctrl->resume();
+			fbdev->panel->enable(fbdev->panel);
+			fbdev->state = OMAPFB_ACTIVE;
+			if (fbdev->ctrl->get_update_mode() ==
+					OMAPFB_MANUAL_UPDATE)
+				do_update = 1;
+		}
+		break;
+	case VESA_POWERDOWN:
+		if (fbdev->state == OMAPFB_ACTIVE) {
+			fbdev->panel->disable(fbdev->panel);
+			if (fbdev->ctrl->suspend)
+				fbdev->ctrl->suspend();
+			fbdev->state = OMAPFB_SUSPENDED;
+		}
+		break;
+	default:
+		r = -EINVAL;
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	if (r == 0 && do_update)
+		r = omapfb_update_full_screen(fbi);
+
+	return r;
+}
+
+static void omapfb_sync(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+
+	omapfb_rqueue_lock(fbdev);
+	if (fbdev->ctrl->sync)
+		fbdev->ctrl->sync();
+	omapfb_rqueue_unlock(fbdev);
+}
+
+/*
+ * Set fb_info.fix fields and also updates fbdev.
+ * When calling this fb_info.var must be set up already.
+ */
+static void set_fb_fix(struct fb_info *fbi)
+{
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_mem_region *rg;
+	int bpp;
+
+	rg = &plane->fbdev->mem_desc.region[plane->idx];
+	fbi->screen_base	= (char __iomem *)rg->vaddr;
+	fix->smem_start		= rg->paddr;
+	fix->smem_len		= rg->size;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	bpp = var->bits_per_pixel;
+	if (var->nonstd)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else switch (var->bits_per_pixel) {
+	case 16:
+	case 12:
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		/* 12bpp is stored in 16 bits */
+		bpp = 16;
+		break;
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+	fix->accel		= FB_ACCEL_OMAP1610;
+	fix->line_length	= var->xres_virtual * bpp / 8;
+}
+
+static int set_color_mode(struct omapfb_plane_struct *plane,
+			  struct fb_var_screeninfo *var)
+{
+	switch (var->nonstd) {
+	case 0:
+		break;
+	case OMAPFB_COLOR_YUV422:
+		var->bits_per_pixel = 16;
+		plane->color_mode = var->nonstd;
+		return 0;
+	case OMAPFB_COLOR_YUV420:
+		var->bits_per_pixel = 12;
+		plane->color_mode = var->nonstd;
+		return 0;
+	case OMAPFB_COLOR_YUY422:
+		var->bits_per_pixel = 16;
+		plane->color_mode = var->nonstd;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		plane->color_mode = OMAPFB_COLOR_CLUT_1BPP;
+		return 0;
+	case 2:
+		plane->color_mode = OMAPFB_COLOR_CLUT_2BPP;
+		return 0;
+	case 4:
+		plane->color_mode = OMAPFB_COLOR_CLUT_4BPP;
+		return 0;
+	case 8:
+		plane->color_mode = OMAPFB_COLOR_CLUT_8BPP;
+		return 0;
+	case 12:
+		var->bits_per_pixel = 16;
+		plane->color_mode = OMAPFB_COLOR_RGB444;
+		return 0;
+	case 16:
+		plane->color_mode = OMAPFB_COLOR_RGB565;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+/*
+ * Check the values in var against our capabilities and in case of out of
+ * bound values try to adjust them.
+ */
+static int set_fb_var(struct fb_info *fbi,
+		      struct fb_var_screeninfo *var)
+{
+	int		bpp;
+	unsigned long	max_frame_size;
+	unsigned long	line_size;
+	int		xres_min, xres_max;
+	int		yres_min, yres_max;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct lcd_panel *panel = fbdev->panel;
+
+	if (set_color_mode(plane, var) < 0)
+		return -EINVAL;
+
+	bpp = var->bits_per_pixel;
+	if (plane->color_mode == OMAPFB_COLOR_RGB444)
+		bpp = 16;
+
+	switch (var->rotate) {
+	case 0:
+	case 180:
+		xres_min = OMAPFB_PLANE_XRES_MIN;
+		xres_max = panel->x_res;
+		yres_min = OMAPFB_PLANE_YRES_MIN;
+		yres_max = panel->y_res;
+		if (cpu_is_omap15xx()) {
+			var->xres = panel->x_res;
+			var->yres = panel->y_res;
+		}
+		break;
+	case 90:
+	case 270:
+		xres_min = OMAPFB_PLANE_YRES_MIN;
+		xres_max = panel->y_res;
+		yres_min = OMAPFB_PLANE_XRES_MIN;
+		yres_max = panel->x_res;
+		if (cpu_is_omap15xx()) {
+			var->xres = panel->y_res;
+			var->yres = panel->x_res;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (var->xres < xres_min)
+		var->xres = xres_min;
+	if (var->yres < yres_min)
+		var->yres = yres_min;
+	if (var->xres > xres_max)
+		var->xres = xres_max;
+	if (var->yres > yres_max)
+		var->yres = yres_max;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+	max_frame_size = fbdev->mem_desc.region[plane->idx].size;
+	line_size = var->xres_virtual * bpp / 8;
+	if (line_size * var->yres_virtual > max_frame_size) {
+		/* Try to keep yres_virtual first */
+		line_size = max_frame_size / var->yres_virtual;
+		var->xres_virtual = line_size * 8 / bpp;
+		if (var->xres_virtual < var->xres) {
+			/* Still doesn't fit. Shrink yres_virtual too */
+			var->xres_virtual = var->xres;
+			line_size = var->xres * bpp / 8;
+			var->yres_virtual = max_frame_size / line_size;
+		}
+		/* Recheck this, as the virtual size changed. */
+		if (var->xres_virtual < var->xres)
+			var->xres = var->xres_virtual;
+		if (var->yres_virtual < var->yres)
+			var->yres = var->yres_virtual;
+		if (var->xres < xres_min || var->yres < yres_min)
+			return -EINVAL;
+	}
+	if (var->xres + var->xoffset > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yres + var->yoffset > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+	line_size = var->xres * bpp / 8;
+
+	if (plane->color_mode == OMAPFB_COLOR_RGB444) {
+		var->red.offset	  = 8; var->red.length	 = 4;
+						var->red.msb_right   = 0;
+		var->green.offset = 4; var->green.length = 4;
+						var->green.msb_right = 0;
+		var->blue.offset  = 0; var->blue.length  = 4;
+						var->blue.msb_right  = 0;
+	} else {
+		var->red.offset	 = 11; var->red.length	 = 5;
+						var->red.msb_right   = 0;
+		var->green.offset = 5;  var->green.length = 6;
+						var->green.msb_right = 0;
+		var->blue.offset = 0;  var->blue.length  = 5;
+						var->blue.msb_right  = 0;
+	}
+
+	var->height		= -1;
+	var->width		= -1;
+	var->grayscale		= 0;
+
+	/* pixclock in ps, the rest in pixclock */
+	var->pixclock		= 10000000 / (panel->pixel_clock / 100);
+	var->left_margin	= panel->hfp;
+	var->right_margin	= panel->hbp;
+	var->upper_margin	= panel->vfp;
+	var->lower_margin	= panel->vbp;
+	var->hsync_len		= panel->hsw;
+	var->vsync_len		= panel->vsw;
+
+	/* TODO: get these from panel->config */
+	var->vmode		= FB_VMODE_NONINTERLACED;
+	var->sync		= 0;
+
+	return 0;
+}
+
+
+/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
+static void omapfb_rotate(struct fb_info *fbi, int rotate)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+
+	omapfb_rqueue_lock(fbdev);
+	if (cpu_is_omap15xx() && rotate != fbi->var.rotate) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+
+		memcpy(new_var, &fbi->var, sizeof(*new_var));
+		new_var->rotate = rotate;
+		if (set_fb_var(fbi, new_var) == 0 &&
+		    memcmp(new_var, &fbi->var, sizeof(*new_var))) {
+			memcpy(&fbi->var, new_var, sizeof(*new_var));
+			ctrl_change_mode(fbi);
+		}
+	}
+	omapfb_rqueue_unlock(fbdev);
+}
+
+/*
+ * Set new x,y offsets in the virtual display for the visible area and switch
+ * to the new mode.
+ */
+static int omapfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	if (var->xoffset != fbi->var.xoffset ||
+	    var->yoffset != fbi->var.yoffset) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+
+		memcpy(new_var, &fbi->var, sizeof(*new_var));
+		new_var->xoffset = var->xoffset;
+		new_var->yoffset = var->yoffset;
+		if (set_fb_var(fbi, new_var))
+			r = -EINVAL;
+		else {
+			memcpy(&fbi->var, new_var, sizeof(*new_var));
+			ctrl_change_mode(fbi);
+		}
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/* Set mirror to vertical axis and switch to the new mode. */
+static int omapfb_mirror(struct fb_info *fbi, int mirror)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	mirror = mirror ? 1 : 0;
+	if (cpu_is_omap15xx())
+		r = -EINVAL;
+	else if (mirror != plane->info.mirror) {
+		plane->info.mirror = mirror;
+		r = ctrl_change_mode(fbi);
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Check values in var, try to adjust them in case of out of bound values if
+ * possible, or return error.
+ */
+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	if (fbdev->ctrl->sync != NULL)
+		fbdev->ctrl->sync();
+	r = set_fb_var(fbi, var);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Switch to a new mode. The parameters for it has been check already by
+ * omapfb_check_var.
+ */
+static int omapfb_set_par(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	set_fb_fix(fbi);
+	r = ctrl_change_mode(fbi);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+int omapfb_update_window_async(struct fb_info *fbi,
+				struct omapfb_update_window *win,
+				void (*callback)(void *),
+				void *callback_data)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var;
+
+	var = &fbi->var;
+	if (win->x >= var->xres || win->y >= var->yres ||
+	    win->out_x > var->xres || win->out_y >= var->yres)
+		return -EINVAL;
+
+	if (!fbdev->ctrl->update_window ||
+	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+		return -ENODEV;
+
+	if (win->x + win->width >= var->xres)
+		win->width = var->xres - win->x;
+	if (win->y + win->height >= var->yres)
+		win->height = var->yres - win->y;
+	/* The out sizes should be cropped to the LCD size */
+	if (win->out_x + win->out_width > fbdev->panel->x_res)
+		win->out_width = fbdev->panel->x_res - win->out_x;
+	if (win->out_y + win->out_height > fbdev->panel->y_res)
+		win->out_height = fbdev->panel->y_res - win->out_y;
+	if (!win->width || !win->height || !win->out_width || !win->out_height)
+		return 0;
+
+	return fbdev->ctrl->update_window(fbi, win, callback, callback_data);
+}
+EXPORT_SYMBOL(omapfb_update_window_async);
+
+static int omapfb_update_win(struct fb_info *fbi,
+				struct omapfb_update_window *win)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	int ret;
+
+	omapfb_rqueue_lock(plane->fbdev);
+	ret = omapfb_update_window_async(fbi, win, NULL, 0);
+	omapfb_rqueue_unlock(plane->fbdev);
+
+	return ret;
+}
+
+static int omapfb_update_full_screen(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_update_window win;
+	int r;
+
+	if (!fbdev->ctrl->update_window ||
+	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+		return -ENODEV;
+
+	win.x = 0;
+	win.y = 0;
+	win.width = fbi->var.xres;
+	win.height = fbi->var.yres;
+	win.out_x = 0;
+	win.out_y = 0;
+	win.out_width = fbi->var.xres;
+	win.out_height = fbi->var.yres;
+	win.format = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->update_window(fbi, &win, NULL, 0);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct lcd_panel *panel = fbdev->panel;
+	struct omapfb_plane_info old_info;
+	int r = 0;
+
+	if (pi->pos_x + pi->out_width > panel->x_res ||
+	    pi->pos_y + pi->out_height > panel->y_res)
+		return -EINVAL;
+
+	omapfb_rqueue_lock(fbdev);
+	if (pi->enabled && !fbdev->mem_desc.region[plane->idx].size) {
+		/*
+		 * This plane's memory was freed, can't enable it
+		 * until it's reallocated.
+		 */
+		r = -EINVAL;
+		goto out;
+	}
+	old_info = plane->info;
+	plane->info = *pi;
+	if (pi->enabled) {
+		r = ctrl_change_mode(fbi);
+		if (r < 0) {
+			plane->info = old_info;
+			goto out;
+		}
+	}
+	r = fbdev->ctrl->enable_plane(plane->idx, pi->enabled);
+	if (r < 0) {
+		plane->info = old_info;
+		goto out;
+	}
+out:
+	omapfb_rqueue_unlock(fbdev);
+	return r;
+}
+
+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+
+	*pi = plane->info;
+	return 0;
+}
+
+static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_mem_region *rg = &fbdev->mem_desc.region[plane->idx];
+	size_t size;
+	int r = 0;
+
+	if (fbdev->ctrl->setup_mem == NULL)
+		return -ENODEV;
+	if (mi->type > OMAPFB_MEMTYPE_MAX)
+		return -EINVAL;
+
+	size = PAGE_ALIGN(mi->size);
+	omapfb_rqueue_lock(fbdev);
+	if (plane->info.enabled) {
+		r = -EBUSY;
+		goto out;
+	}
+	if (rg->size != size || rg->type != mi->type) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+		unsigned long old_size = rg->size;
+		u8	      old_type = rg->type;
+		unsigned long paddr;
+
+		rg->size = size;
+		rg->type = mi->type;
+		/*
+		 * size == 0 is a special case, for which we
+		 * don't check / adjust the screen parameters.
+		 * This isn't a problem since the plane can't
+		 * be reenabled unless its size is > 0.
+		 */
+		if (old_size != size && size) {
+			if (size) {
+				memcpy(new_var, &fbi->var, sizeof(*new_var));
+				r = set_fb_var(fbi, new_var);
+				if (r < 0)
+					goto out;
+			}
+		}
+
+		if (fbdev->ctrl->sync)
+			fbdev->ctrl->sync();
+		r = fbdev->ctrl->setup_mem(plane->idx, size, mi->type, &paddr);
+		if (r < 0) {
+			/* Revert changes. */
+			rg->size = old_size;
+			rg->type = old_type;
+			goto out;
+		}
+		rg->paddr = paddr;
+
+		if (old_size != size) {
+			if (size) {
+				memcpy(&fbi->var, new_var, sizeof(fbi->var));
+				set_fb_fix(fbi);
+			} else {
+				/*
+				 * Set these explicitly to indicate that the
+				 * plane memory is dealloce'd, the other
+				 * screen parameters in var / fix are invalid.
+				 */
+				fbi->fix.smem_start = 0;
+				fbi->fix.smem_len = 0;
+			}
+		}
+	}
+out:
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_mem_region *rg;
+
+	rg = &fbdev->mem_desc.region[plane->idx];
+	memset(mi, 0, sizeof(*mi));
+	mi->size = rg->size;
+	mi->type = rg->type;
+
+	return 0;
+}
+
+static int omapfb_set_color_key(struct omapfb_device *fbdev,
+				struct omapfb_color_key *ck)
+{
+	int r;
+
+	if (!fbdev->ctrl->set_color_key)
+		return -ENODEV;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->set_color_key(ck);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_get_color_key(struct omapfb_device *fbdev,
+				struct omapfb_color_key *ck)
+{
+	int r;
+
+	if (!fbdev->ctrl->get_color_key)
+		return -ENODEV;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->get_color_key(ck);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static struct blocking_notifier_head omapfb_client_list[OMAPFB_PLANE_NUM];
+static int notifier_inited;
+
+static void omapfb_init_notifier(void)
+{
+	int i;
+
+	for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+		BLOCKING_INIT_NOTIFIER_HEAD(&omapfb_client_list[i]);
+}
+
+int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
+				omapfb_notifier_callback_t callback,
+				void *callback_data)
+{
+	int r;
+
+	if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
+		return -EINVAL;
+
+	if (!notifier_inited) {
+		omapfb_init_notifier();
+		notifier_inited = 1;
+	}
+
+	omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *,
+					unsigned long, void *))callback;
+	omapfb_nb->data = callback_data;
+	r = blocking_notifier_chain_register(
+				&omapfb_client_list[omapfb_nb->plane_idx],
+				&omapfb_nb->nb);
+	if (r)
+		return r;
+	if (omapfb_dev != NULL &&
+	    omapfb_dev->ctrl && omapfb_dev->ctrl->bind_client) {
+		omapfb_dev->ctrl->bind_client(omapfb_nb);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(omapfb_register_client);
+
+int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb)
+{
+	return blocking_notifier_chain_unregister(
+		&omapfb_client_list[omapfb_nb->plane_idx], &omapfb_nb->nb);
+}
+EXPORT_SYMBOL(omapfb_unregister_client);
+
+void omapfb_notify_clients(struct omapfb_device *fbdev, unsigned long event)
+{
+	int i;
+
+	if (!notifier_inited)
+		/* no client registered yet */
+		return;
+
+	for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+		blocking_notifier_call_chain(&omapfb_client_list[i], event,
+				    fbdev->fb_info[i]);
+}
+EXPORT_SYMBOL(omapfb_notify_clients);
+
+static int omapfb_set_update_mode(struct omapfb_device *fbdev,
+				   enum omapfb_update_mode mode)
+{
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->set_update_mode(mode);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev)
+{
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->get_update_mode();
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static void omapfb_get_caps(struct omapfb_device *fbdev, int plane,
+				     struct omapfb_caps *caps)
+{
+	memset(caps, 0, sizeof(*caps));
+	fbdev->ctrl->get_caps(plane, caps);
+	caps->ctrl |= fbdev->panel->get_caps(fbdev->panel);
+}
+
+/* For lcd testing */
+void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
+{
+	omapfb_rqueue_lock(fbdev);
+	*(u16 *)fbdev->mem_desc.region[0].vaddr = pixval;
+	if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) {
+		struct omapfb_update_window win;
+
+		memset(&win, 0, sizeof(win));
+		win.width = 2;
+		win.height = 2;
+		win.out_width = 2;
+		win.out_height = 2;
+		fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0);
+	}
+	omapfb_rqueue_unlock(fbdev);
+}
+EXPORT_SYMBOL(omapfb_write_first_pixel);
+
+/*
+ * Ioctl interface. Part of the kernel mode frame buffer API is duplicated
+ * here to be accessible by user mode code.
+ */
+static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
+			unsigned long arg)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device	*fbdev = plane->fbdev;
+	struct fb_ops		*ops = fbi->fbops;
+	union {
+		struct omapfb_update_window	update_window;
+		struct omapfb_plane_info	plane_info;
+		struct omapfb_mem_info		mem_info;
+		struct omapfb_color_key		color_key;
+		enum omapfb_update_mode		update_mode;
+		struct omapfb_caps		caps;
+		unsigned int		mirror;
+		int			plane_out;
+		int			enable_plane;
+	} p;
+	int r = 0;
+
+	BUG_ON(!ops);
+	switch (cmd) {
+	case OMAPFB_MIRROR:
+		if (get_user(p.mirror, (int __user *)arg))
+			r = -EFAULT;
+		else
+			omapfb_mirror(fbi, p.mirror);
+		break;
+	case OMAPFB_SYNC_GFX:
+		omapfb_sync(fbi);
+		break;
+	case OMAPFB_VSYNC:
+		break;
+	case OMAPFB_SET_UPDATE_MODE:
+		if (get_user(p.update_mode, (int __user *)arg))
+			r = -EFAULT;
+		else
+			r = omapfb_set_update_mode(fbdev, p.update_mode);
+		break;
+	case OMAPFB_GET_UPDATE_MODE:
+		p.update_mode = omapfb_get_update_mode(fbdev);
+		if (put_user(p.update_mode,
+					(enum omapfb_update_mode __user *)arg))
+			r = -EFAULT;
+		break;
+	case OMAPFB_UPDATE_WINDOW_OLD:
+		if (copy_from_user(&p.update_window, (void __user *)arg,
+				   sizeof(struct omapfb_update_window_old)))
+			r = -EFAULT;
+		else {
+			struct omapfb_update_window *u = &p.update_window;
+			u->out_x = u->x;
+			u->out_y = u->y;
+			u->out_width = u->width;
+			u->out_height = u->height;
+			memset(u->reserved, 0, sizeof(u->reserved));
+			r = omapfb_update_win(fbi, u);
+		}
+		break;
+	case OMAPFB_UPDATE_WINDOW:
+		if (copy_from_user(&p.update_window, (void __user *)arg,
+				   sizeof(p.update_window)))
+			r = -EFAULT;
+		else
+			r = omapfb_update_win(fbi, &p.update_window);
+		break;
+	case OMAPFB_SETUP_PLANE:
+		if (copy_from_user(&p.plane_info, (void __user *)arg,
+				   sizeof(p.plane_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_plane(fbi, &p.plane_info);
+		break;
+	case OMAPFB_QUERY_PLANE:
+		if ((r = omapfb_query_plane(fbi, &p.plane_info)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.plane_info,
+				   sizeof(p.plane_info)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_SETUP_MEM:
+		if (copy_from_user(&p.mem_info, (void __user *)arg,
+				   sizeof(p.mem_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_mem(fbi, &p.mem_info);
+		break;
+	case OMAPFB_QUERY_MEM:
+		if ((r = omapfb_query_mem(fbi, &p.mem_info)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.mem_info,
+				   sizeof(p.mem_info)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_SET_COLOR_KEY:
+		if (copy_from_user(&p.color_key, (void __user *)arg,
+				   sizeof(p.color_key)))
+			r = -EFAULT;
+		else
+			r = omapfb_set_color_key(fbdev, &p.color_key);
+		break;
+	case OMAPFB_GET_COLOR_KEY:
+		if ((r = omapfb_get_color_key(fbdev, &p.color_key)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.color_key,
+				 sizeof(p.color_key)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_GET_CAPS:
+		omapfb_get_caps(fbdev, plane->idx, &p.caps);
+		if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_LCD_TEST:
+		{
+			int test_num;
+
+			if (get_user(test_num, (int __user *)arg)) {
+				r = -EFAULT;
+				break;
+			}
+			if (!fbdev->panel->run_test) {
+				r = -EINVAL;
+				break;
+			}
+			r = fbdev->panel->run_test(fbdev->panel, test_num);
+			break;
+		}
+	case OMAPFB_CTRL_TEST:
+		{
+			int test_num;
+
+			if (get_user(test_num, (int __user *)arg)) {
+				r = -EFAULT;
+				break;
+			}
+			if (!fbdev->ctrl->run_test) {
+				r = -EINVAL;
+				break;
+			}
+			r = fbdev->ctrl->run_test(test_num);
+			break;
+		}
+	default:
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct omapfb_plane_struct *plane = info->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->mmap(info, vma);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Callback table for the frame buffer framework. Some of these pointers
+ * will be changed according to the current setting of fb_info->accel_flags.
+ */
+static struct fb_ops omapfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open        = omapfb_open,
+	.fb_release     = omapfb_release,
+	.fb_setcolreg	= omapfb_setcolreg,
+	.fb_setcmap	= omapfb_setcmap,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_blank       = omapfb_blank,
+	.fb_ioctl	= omapfb_ioctl,
+	.fb_check_var	= omapfb_check_var,
+	.fb_set_par	= omapfb_set_par,
+	.fb_rotate	= omapfb_rotate,
+	.fb_pan_display = omapfb_pan_display,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Sysfs interface
+ * ---------------------------------------------------------------------------
+ */
+/* omapfbX sysfs entries */
+static ssize_t omapfb_show_caps_num(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int plane;
+	size_t size;
+	struct omapfb_caps caps;
+
+	plane = 0;
+	size = 0;
+	while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
+		omapfb_get_caps(fbdev, plane, &caps);
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+			"plane#%d %#010x %#010x %#010x\n",
+			plane, caps.ctrl, caps.plane_color, caps.wnd_color);
+		plane++;
+	}
+	return size;
+}
+
+static ssize_t omapfb_show_caps_text(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int i;
+	struct omapfb_caps caps;
+	int plane;
+	size_t size;
+
+	plane = 0;
+	size = 0;
+	while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
+		omapfb_get_caps(fbdev, plane, &caps);
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 "plane#%d:\n", plane);
+		for (i = 0; i < ARRAY_SIZE(ctrl_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (ctrl_caps[i].flag & caps.ctrl)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					" %s\n", ctrl_caps[i].name);
+		}
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 " plane colors:\n");
+		for (i = 0; i < ARRAY_SIZE(color_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (color_caps[i].flag & caps.plane_color)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					"  %s\n", color_caps[i].name);
+		}
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 " window colors:\n");
+		for (i = 0; i < ARRAY_SIZE(color_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (color_caps[i].flag & caps.wnd_color)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					"  %s\n", color_caps[i].name);
+		}
+
+		plane++;
+	}
+	return size;
+}
+
+static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL);
+static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
+
+/* panel sysfs entries */
+static ssize_t omapfb_show_panel_name(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
+}
+
+static ssize_t omapfb_show_bklight_level(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int r;
+
+	if (fbdev->panel->get_bklight_level) {
+		r = snprintf(buf, PAGE_SIZE, "%d\n",
+			     fbdev->panel->get_bklight_level(fbdev->panel));
+	} else
+		r = -ENODEV;
+	return r;
+}
+
+static ssize_t omapfb_store_bklight_level(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t size)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int r;
+
+	if (fbdev->panel->set_bklight_level) {
+		unsigned int level;
+
+		if (sscanf(buf, "%10d", &level) == 1) {
+			r = fbdev->panel->set_bklight_level(fbdev->panel,
+							    level);
+		} else
+			r = -EINVAL;
+	} else
+		r = -ENODEV;
+	return r ? r : size;
+}
+
+static ssize_t omapfb_show_bklight_max(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+	int r;
+
+	if (fbdev->panel->get_bklight_level) {
+		r = snprintf(buf, PAGE_SIZE, "%d\n",
+			     fbdev->panel->get_bklight_max(fbdev->panel));
+	} else
+		r = -ENODEV;
+	return r;
+}
+
+static struct device_attribute dev_attr_panel_name =
+	__ATTR(name, 0444, omapfb_show_panel_name, NULL);
+static DEVICE_ATTR(backlight_level, 0664,
+		   omapfb_show_bklight_level, omapfb_store_bklight_level);
+static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL);
+
+static struct attribute *panel_attrs[] = {
+	&dev_attr_panel_name.attr,
+	&dev_attr_backlight_level.attr,
+	&dev_attr_backlight_max.attr,
+	NULL,
+};
+
+static struct attribute_group panel_attr_grp = {
+	.name  = "panel",
+	.attrs = panel_attrs,
+};
+
+/* ctrl sysfs entries */
+static ssize_t omapfb_show_ctrl_name(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
+}
+
+static struct device_attribute dev_attr_ctrl_name =
+	__ATTR(name, 0444, omapfb_show_ctrl_name, NULL);
+
+static struct attribute *ctrl_attrs[] = {
+	&dev_attr_ctrl_name.attr,
+	NULL,
+};
+
+static struct attribute_group ctrl_attr_grp = {
+	.name  = "ctrl",
+	.attrs = ctrl_attrs,
+};
+
+static int omapfb_register_sysfs(struct omapfb_device *fbdev)
+{
+	int r;
+
+	if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num)))
+		goto fail0;
+
+	if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text)))
+		goto fail1;
+
+	if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp)))
+		goto fail2;
+
+	if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp)))
+		goto fail3;
+
+	return 0;
+fail3:
+	sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+fail2:
+	device_remove_file(fbdev->dev, &dev_attr_caps_text);
+fail1:
+	device_remove_file(fbdev->dev, &dev_attr_caps_num);
+fail0:
+	dev_err(fbdev->dev, "unable to register sysfs interface\n");
+	return r;
+}
+
+static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
+{
+	sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp);
+	sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+	device_remove_file(fbdev->dev, &dev_attr_caps_num);
+	device_remove_file(fbdev->dev, &dev_attr_caps_text);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LDM callbacks
+ * ---------------------------------------------------------------------------
+ */
+/* Initialize system fb_info object and set the default video mode.
+ * The frame buffer memory already allocated by lcddma_init
+ */
+static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info)
+{
+	struct fb_var_screeninfo	*var = &info->var;
+	struct fb_fix_screeninfo	*fix = &info->fix;
+	int				r = 0;
+
+	info->fbops = &omapfb_ops;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
+
+	info->pseudo_palette = fbdev->pseudo_palette;
+
+	var->accel_flags  = def_accel ? FB_ACCELF_TEXT : 0;
+	var->xres = def_vxres;
+	var->yres = def_vyres;
+	var->xres_virtual = def_vxres;
+	var->yres_virtual = def_vyres;
+	var->rotate	  = def_rotate;
+	var->bits_per_pixel = fbdev->panel->bpp;
+
+	set_fb_var(info, var);
+	set_fb_fix(info);
+
+	r = fb_alloc_cmap(&info->cmap, 16, 0);
+	if (r != 0)
+		dev_err(fbdev->dev, "unable to allocate color map memory\n");
+
+	return r;
+}
+
+/* Release the fb_info object */
+static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi)
+{
+	fb_dealloc_cmap(&fbi->cmap);
+}
+
+static void planes_cleanup(struct omapfb_device *fbdev)
+{
+	int i;
+
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		if (fbdev->fb_info[i] == NULL)
+			break;
+		fbinfo_cleanup(fbdev, fbdev->fb_info[i]);
+		framebuffer_release(fbdev->fb_info[i]);
+	}
+}
+
+static int planes_init(struct omapfb_device *fbdev)
+{
+	struct fb_info *fbi;
+	int i;
+	int r;
+
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		struct omapfb_plane_struct *plane;
+		fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct),
+					fbdev->dev);
+		if (fbi == NULL) {
+			dev_err(fbdev->dev,
+				"unable to allocate memory for plane info\n");
+			planes_cleanup(fbdev);
+			return -ENOMEM;
+		}
+		plane = fbi->par;
+		plane->idx = i;
+		plane->fbdev = fbdev;
+		plane->info.mirror = def_mirror;
+		fbdev->fb_info[i] = fbi;
+
+		if ((r = fbinfo_init(fbdev, fbi)) < 0) {
+			framebuffer_release(fbi);
+			planes_cleanup(fbdev);
+			return r;
+		}
+		plane->info.out_width = fbi->var.xres;
+		plane->info.out_height = fbi->var.yres;
+	}
+	return 0;
+}
+
+/*
+ * Free driver resources. Can be called to rollback an aborted initialization
+ * sequence.
+ */
+static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
+{
+	int i;
+
+	switch (state) {
+	case OMAPFB_ACTIVE:
+		for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
+			unregister_framebuffer(fbdev->fb_info[i]);
+	case 7:
+		omapfb_unregister_sysfs(fbdev);
+	case 6:
+		fbdev->panel->disable(fbdev->panel);
+	case 5:
+		omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
+	case 4:
+		planes_cleanup(fbdev);
+	case 3:
+		ctrl_cleanup(fbdev);
+	case 2:
+		fbdev->panel->cleanup(fbdev->panel);
+	case 1:
+		dev_set_drvdata(fbdev->dev, NULL);
+		kfree(fbdev);
+	case 0:
+		/* nothing to free */
+		break;
+	default:
+		BUG();
+	}
+}
+
+static int omapfb_find_ctrl(struct omapfb_device *fbdev)
+{
+	struct omapfb_platform_data *conf;
+	char name[17];
+	int i;
+
+	conf = fbdev->dev->platform_data;
+
+	fbdev->ctrl = NULL;
+
+	strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1);
+	name[sizeof(name) - 1] = '\0';
+
+	if (strcmp(name, "internal") == 0) {
+		fbdev->ctrl = fbdev->int_ctrl;
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
+		dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name);
+		if (strcmp(ctrls[i]->name, name) == 0) {
+			fbdev->ctrl = ctrls[i];
+			break;
+		}
+	}
+
+	if (fbdev->ctrl == NULL) {
+		dev_dbg(fbdev->dev, "ctrl %s not supported\n", name);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void check_required_callbacks(struct omapfb_device *fbdev)
+{
+#define _C(x) (fbdev->ctrl->x != NULL)
+#define _P(x) (fbdev->panel->x != NULL)
+	BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL);
+	BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) &&
+		 _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) &&
+		 _P(init) && _P(cleanup) && _P(enable) && _P(disable) &&
+		 _P(get_caps)));
+#undef _P
+#undef _C
+}
+
+/*
+ * Called by LDM binding to probe and attach a new device.
+ * Initialization sequence:
+ *   1. allocate system omapfb_device structure
+ *   2. select controller type according to platform configuration
+ *      init LCD panel
+ *   3. init LCD controller and LCD DMA
+ *   4. init system fb_info structure for all planes
+ *   5. setup video mode for first plane and enable it
+ *   6. enable LCD panel
+ *   7. register sysfs attributes
+ *   OMAPFB_ACTIVE: register system fb_info structure for all planes
+ */
+static int omapfb_do_probe(struct platform_device *pdev,
+				struct lcd_panel *panel)
+{
+	struct omapfb_device	*fbdev = NULL;
+	int			init_state;
+	unsigned long		phz, hhz, vhz;
+	unsigned long		vram;
+	int			i;
+	int			r = 0;
+
+	init_state = 0;
+
+	if (pdev->num_resources != 0) {
+		dev_err(&pdev->dev, "probed for an unknown device\n");
+		r = -ENODEV;
+		goto cleanup;
+	}
+
+	if (pdev->dev.platform_data == NULL) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		r = -ENOENT;
+		goto cleanup;
+	}
+
+	fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL);
+	if (fbdev == NULL) {
+		dev_err(&pdev->dev,
+			"unable to allocate memory for device info\n");
+		r = -ENOMEM;
+		goto cleanup;
+	}
+	init_state++;
+
+	fbdev->dev = &pdev->dev;
+	fbdev->panel = panel;
+	platform_set_drvdata(pdev, fbdev);
+
+	mutex_init(&fbdev->rqueue_mutex);
+
+#ifdef CONFIG_ARCH_OMAP1
+	fbdev->int_ctrl = &omap1_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+	fbdev->ext_if = &omap1_ext_if;
+#endif
+#else	/* OMAP2 */
+	fbdev->int_ctrl = &omap2_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+	fbdev->ext_if = &omap2_ext_if;
+#endif
+#endif
+	if (omapfb_find_ctrl(fbdev) < 0) {
+		dev_err(fbdev->dev,
+			"LCD controller not found, board not supported\n");
+		r = -ENODEV;
+		goto cleanup;
+	}
+
+	r = fbdev->panel->init(fbdev->panel, fbdev);
+	if (r)
+		goto cleanup;
+
+	pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
+
+	def_vxres = def_vxres ? : fbdev->panel->x_res;
+	def_vyres = def_vyres ? : fbdev->panel->y_res;
+
+	init_state++;
+
+	r = ctrl_init(fbdev);
+	if (r)
+		goto cleanup;
+	if (fbdev->ctrl->mmap != NULL)
+		omapfb_ops.fb_mmap = omapfb_mmap;
+	init_state++;
+
+	check_required_callbacks(fbdev);
+
+	r = planes_init(fbdev);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+#ifdef CONFIG_FB_OMAP_DMA_TUNE
+	/* Set DMA priority for EMIFF access to highest */
+	if (cpu_class_is_omap1())
+		omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
+#endif
+
+	r = ctrl_change_mode(fbdev->fb_info[0]);
+	if (r) {
+		dev_err(fbdev->dev, "mode setting failed\n");
+		goto cleanup;
+	}
+
+	/* GFX plane is enabled by default */
+	r = fbdev->ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+	if (r)
+		goto cleanup;
+
+	omapfb_set_update_mode(fbdev, manual_update ?
+				   OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
+	init_state++;
+
+	r = fbdev->panel->enable(fbdev->panel);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+	r = omapfb_register_sysfs(fbdev);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+	vram = 0;
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		r = register_framebuffer(fbdev->fb_info[i]);
+		if (r != 0) {
+			dev_err(fbdev->dev,
+				"registering framebuffer %d failed\n", i);
+			goto cleanup;
+		}
+		vram += fbdev->mem_desc.region[i].size;
+	}
+
+	fbdev->state = OMAPFB_ACTIVE;
+
+	panel = fbdev->panel;
+	phz = panel->pixel_clock * 1000;
+	hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw);
+	vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw);
+
+	omapfb_dev = fbdev;
+
+	pr_info("omapfb: Framebuffer initialized. Total vram %lu planes %d\n",
+			vram, fbdev->mem_desc.region_cnt);
+	pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz "
+			"vfreq %lu.%lu Hz\n",
+			phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
+
+	return 0;
+
+cleanup:
+	omapfb_free_resources(fbdev, init_state);
+
+	return r;
+}
+
+static int omapfb_probe(struct platform_device *pdev)
+{
+	BUG_ON(fbdev_pdev != NULL);
+
+	/* Delay actual initialization until the LCD is registered */
+	fbdev_pdev = pdev;
+	if (fbdev_panel != NULL)
+		omapfb_do_probe(fbdev_pdev, fbdev_panel);
+	return 0;
+}
+
+void omapfb_register_panel(struct lcd_panel *panel)
+{
+	BUG_ON(fbdev_panel != NULL);
+
+	fbdev_panel = panel;
+	if (fbdev_pdev != NULL)
+		omapfb_do_probe(fbdev_pdev, fbdev_panel);
+}
+
+/* Called when the device is being detached from the driver */
+static int omapfb_remove(struct platform_device *pdev)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+	enum omapfb_state saved_state = fbdev->state;
+
+	/* FIXME: wait till completion of pending events */
+
+	fbdev->state = OMAPFB_DISABLED;
+	omapfb_free_resources(fbdev, saved_state);
+
+	return 0;
+}
+
+/* PM suspend */
+static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+
+	omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]);
+
+	return 0;
+}
+
+/* PM resume */
+static int omapfb_resume(struct platform_device *pdev)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+
+	omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]);
+	return 0;
+}
+
+static struct platform_driver omapfb_driver = {
+	.probe		= omapfb_probe,
+	.remove		= omapfb_remove,
+	.suspend	= omapfb_suspend,
+	.resume		= omapfb_resume,
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+#ifndef MODULE
+
+/* Process kernel command line parameters */
+static int __init omapfb_setup(char *options)
+{
+	char *this_opt = NULL;
+	int r = 0;
+
+	pr_debug("omapfb: options %s\n", options);
+
+	if (!options || !*options)
+		return 0;
+
+	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "accel", 5))
+			def_accel = 1;
+		else if (!strncmp(this_opt, "vram:", 5)) {
+			char *suffix;
+			unsigned long vram;
+			vram = (simple_strtoul(this_opt + 5, &suffix, 0));
+			switch (suffix[0]) {
+			case '\0':
+				break;
+			case 'm':
+			case 'M':
+				vram *= 1024;
+				/* Fall through */
+			case 'k':
+			case 'K':
+				vram *= 1024;
+				break;
+			default:
+				pr_debug("omapfb: invalid vram suffix %c\n",
+					 suffix[0]);
+				r = -1;
+			}
+			def_vram[def_vram_cnt++] = vram;
+		}
+		else if (!strncmp(this_opt, "vxres:", 6))
+			def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
+		else if (!strncmp(this_opt, "vyres:", 6))
+			def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
+		else if (!strncmp(this_opt, "rotate:", 7))
+			def_rotate = (simple_strtoul(this_opt + 7, NULL, 0));
+		else if (!strncmp(this_opt, "mirror:", 7))
+			def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
+		else if (!strncmp(this_opt, "manual_update", 13))
+			manual_update = 1;
+		else {
+			pr_debug("omapfb: invalid option\n");
+			r = -1;
+		}
+	}
+
+	return r;
+}
+
+#endif
+
+/* Register both the driver and the device */
+static int __init omapfb_init(void)
+{
+#ifndef MODULE
+	char *option;
+
+	if (fb_get_options("omapfb", &option))
+		return -ENODEV;
+	omapfb_setup(option);
+#endif
+	/* Register the driver with LDM */
+	if (platform_driver_register(&omapfb_driver)) {
+		pr_debug("failed to register omapfb driver\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit omapfb_cleanup(void)
+{
+	platform_driver_unregister(&omapfb_driver);
+}
+
+module_param_named(accel, def_accel, uint, 0664);
+module_param_array_named(vram, def_vram, ulong, &def_vram_cnt, 0664);
+module_param_named(vxres, def_vxres, long, 0664);
+module_param_named(vyres, def_vyres, long, 0664);
+module_param_named(rotate, def_rotate, uint, 0664);
+module_param_named(mirror, def_mirror, uint, 0664);
+module_param_named(manual_update, manual_update, bool, 0664);
+
+module_init(omapfb_init);
+module_exit(omapfb_cleanup);
+
+MODULE_DESCRIPTION("TI OMAP framebuffer driver");
+MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
new file mode 100644
index 0000000..2b42698
--- /dev/null
+++ b/drivers/video/omap/rfbi.c
@@ -0,0 +1,588 @@
+/*
+ * OMAP2 Remote Frame Buffer Interface support
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *	   Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/arch/omapfb.h>
+
+#include "dispc.h"
+
+/* To work around an RFBI transfer rate limitation */
+#define OMAP_RFBI_RATE_LIMIT	1
+
+#define RFBI_BASE		0x48050800
+#define RFBI_REVISION		0x0000
+#define RFBI_SYSCONFIG		0x0010
+#define RFBI_SYSSTATUS		0x0014
+#define RFBI_CONTROL		0x0040
+#define RFBI_PIXEL_CNT		0x0044
+#define RFBI_LINE_NUMBER	0x0048
+#define RFBI_CMD		0x004c
+#define RFBI_PARAM		0x0050
+#define RFBI_DATA		0x0054
+#define RFBI_READ		0x0058
+#define RFBI_STATUS		0x005c
+#define RFBI_CONFIG0		0x0060
+#define RFBI_ONOFF_TIME0	0x0064
+#define RFBI_CYCLE_TIME0	0x0068
+#define RFBI_DATA_CYCLE1_0	0x006c
+#define RFBI_DATA_CYCLE2_0	0x0070
+#define RFBI_DATA_CYCLE3_0	0x0074
+#define RFBI_VSYNC_WIDTH	0x0090
+#define RFBI_HSYNC_WIDTH	0x0094
+
+#define DISPC_BASE		0x48050400
+#define DISPC_CONTROL		0x0040
+
+static struct {
+	u32		base;
+	void		(*lcdc_callback)(void *data);
+	void		*lcdc_callback_data;
+	unsigned long	l4_khz;
+	int		bits_per_cycle;
+	struct omapfb_device *fbdev;
+	struct clk	*dss_ick;
+	struct clk	*dss1_fck;
+	unsigned	tearsync_pin_cnt;
+	unsigned	tearsync_mode;
+} rfbi;
+
+static inline void rfbi_write_reg(int idx, u32 val)
+{
+	__raw_writel(val, rfbi.base + idx);
+}
+
+static inline u32 rfbi_read_reg(int idx)
+{
+	return __raw_readl(rfbi.base + idx);
+}
+
+static int rfbi_get_clocks(void)
+{
+	if (IS_ERR((rfbi.dss_ick = clk_get(rfbi.fbdev->dev, "dss_ick")))) {
+		dev_err(rfbi.fbdev->dev, "can't get dss_ick");
+		return PTR_ERR(rfbi.dss_ick);
+	}
+
+	if (IS_ERR((rfbi.dss1_fck = clk_get(rfbi.fbdev->dev, "dss1_fck")))) {
+		dev_err(rfbi.fbdev->dev, "can't get dss1_fck");
+		clk_put(rfbi.dss_ick);
+		return PTR_ERR(rfbi.dss1_fck);
+	}
+
+	return 0;
+}
+
+static void rfbi_put_clocks(void)
+{
+	clk_put(rfbi.dss1_fck);
+	clk_put(rfbi.dss_ick);
+}
+
+static void rfbi_enable_clocks(int enable)
+{
+	if (enable) {
+		clk_enable(rfbi.dss_ick);
+		clk_enable(rfbi.dss1_fck);
+	} else {
+		clk_disable(rfbi.dss1_fck);
+		clk_disable(rfbi.dss_ick);
+	}
+}
+
+
+#ifdef VERBOSE
+static void rfbi_print_timings(void)
+{
+	u32 l;
+	u32 time;
+
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	time = 1000000000 / rfbi.l4_khz;
+	if (l & (1 << 4))
+		time *= 2;
+
+	dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time);
+	l = rfbi_read_reg(RFBI_ONOFF_TIME0);
+	dev_dbg(rfbi.fbdev->dev,
+		"CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
+		"REONTIME %d, REOFFTIME %d\n",
+		l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
+		(l >> 20) & 0x0f, (l >> 24) & 0x3f);
+
+	l = rfbi_read_reg(RFBI_CYCLE_TIME0);
+	dev_dbg(rfbi.fbdev->dev,
+		"WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
+		"ACCESSTIME %d\n",
+		(l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
+		(l >> 22) & 0x3f);
+}
+#else
+static void rfbi_print_timings(void) {}
+#endif
+
+static void rfbi_set_timings(const struct extif_timings *t)
+{
+	u32 l;
+
+	BUG_ON(!t->converted);
+
+	rfbi_enable_clocks(1);
+	rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]);
+	rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]);
+
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	l &= ~(1 << 4);
+	l |= (t->tim[2] ? 1 : 0) << 4;
+	rfbi_write_reg(RFBI_CONFIG0, l);
+
+	rfbi_print_timings();
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+	*clk_period = 1000000000 / rfbi.l4_khz;
+	*max_clk_div = 2;
+}
+
+static int ps_to_rfbi_ticks(int time, int div)
+{
+	unsigned long tick_ps;
+	int ret;
+
+	/* Calculate in picosecs to yield more exact results */
+	tick_ps = 1000000000 / (rfbi.l4_khz) * div;
+
+	ret = (time + tick_ps - 1) / tick_ps;
+
+	return ret;
+}
+
+#ifdef OMAP_RFBI_RATE_LIMIT
+static unsigned long rfbi_get_max_tx_rate(void)
+{
+	unsigned long	l4_rate, dss1_rate;
+	int		min_l4_ticks = 0;
+	int		i;
+
+	/* According to TI this can't be calculated so make the
+	 * adjustments for a couple of known frequencies and warn for
+	 * others.
+	 */
+	static const struct {
+		unsigned long l4_clk;		/* HZ */
+		unsigned long dss1_clk;		/* HZ */
+		unsigned long min_l4_ticks;
+	} ftab[] = {
+		{ 55,	132,	7, },		/* 7.86 MPix/s */
+		{ 110,	110,	12, },		/* 9.16 MPix/s */
+		{ 110,	132,	10, },		/* 11   Mpix/s */
+		{ 120,	120,	10, },		/* 12   Mpix/s */
+		{ 133,	133,	10, },		/* 13.3 Mpix/s */
+	};
+
+	l4_rate = rfbi.l4_khz / 1000;
+	dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000;
+
+	for (i = 0; i < ARRAY_SIZE(ftab); i++) {
+		/* Use a window instead of an exact match, to account
+		 * for different DPLL multiplier / divider pairs.
+		 */
+		if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
+		    abs(ftab[i].dss1_clk - dss1_rate) < 3) {
+			min_l4_ticks = ftab[i].min_l4_ticks;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(ftab)) {
+		/* Can't be sure, return anyway the maximum not
+		 * rate-limited. This might cause a problem only for the
+		 * tearing synchronisation.
+		 */
+		dev_err(rfbi.fbdev->dev,
+			"can't determine maximum RFBI transfer rate\n");
+		return rfbi.l4_khz * 1000;
+	}
+	return rfbi.l4_khz * 1000 / min_l4_ticks;
+}
+#else
+static int rfbi_get_max_tx_rate(void)
+{
+	return rfbi.l4_khz * 1000;
+}
+#endif
+
+
+static int rfbi_convert_timings(struct extif_timings *t)
+{
+	u32 l;
+	int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
+	int actim, recyc, wecyc;
+	int div = t->clk_div;
+
+	if (div <= 0 || div > 2)
+		return -1;
+
+	/* Make sure that after conversion it still holds that:
+	 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
+	 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
+	 */
+	weon = ps_to_rfbi_ticks(t->we_on_time, div);
+	weoff = ps_to_rfbi_ticks(t->we_off_time, div);
+	if (weoff <= weon)
+		weoff = weon + 1;
+	if (weon > 0x0f)
+		return -1;
+	if (weoff > 0x3f)
+		return -1;
+
+	reon = ps_to_rfbi_ticks(t->re_on_time, div);
+	reoff = ps_to_rfbi_ticks(t->re_off_time, div);
+	if (reoff <= reon)
+		reoff = reon + 1;
+	if (reon > 0x0f)
+		return -1;
+	if (reoff > 0x3f)
+		return -1;
+
+	cson = ps_to_rfbi_ticks(t->cs_on_time, div);
+	csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
+	if (csoff <= cson)
+		csoff = cson + 1;
+	if (csoff < max(weoff, reoff))
+		csoff = max(weoff, reoff);
+	if (cson > 0x0f)
+		return -1;
+	if (csoff > 0x3f)
+		return -1;
+
+	l =  cson;
+	l |= csoff << 4;
+	l |= weon  << 10;
+	l |= weoff << 14;
+	l |= reon  << 20;
+	l |= reoff << 24;
+
+	t->tim[0] = l;
+
+	actim = ps_to_rfbi_ticks(t->access_time, div);
+	if (actim <= reon)
+		actim = reon + 1;
+	if (actim > 0x3f)
+		return -1;
+
+	wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
+	if (wecyc < weoff)
+		wecyc = weoff;
+	if (wecyc > 0x3f)
+		return -1;
+
+	recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
+	if (recyc < reoff)
+		recyc = reoff;
+	if (recyc > 0x3f)
+		return -1;
+
+	cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
+	if (cs_pulse > 0x3f)
+		return -1;
+
+	l =  wecyc;
+	l |= recyc    << 6;
+	l |= cs_pulse << 12;
+	l |= actim    << 22;
+
+	t->tim[1] = l;
+
+	t->tim[2] = div - 1;
+
+	t->converted = 1;
+
+	return 0;
+}
+
+static int rfbi_setup_tearsync(unsigned pin_cnt,
+			       unsigned hs_pulse_time, unsigned vs_pulse_time,
+			       int hs_pol_inv, int vs_pol_inv, int extif_div)
+{
+	int hs, vs;
+	int min;
+	u32 l;
+
+	if (pin_cnt != 1 && pin_cnt != 2)
+		return -EINVAL;
+
+	hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
+	vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
+	if (hs < 2)
+		return -EDOM;
+	if (pin_cnt == 2)
+		min = 2;
+	else
+		min = 4;
+	if (vs < min)
+		return -EDOM;
+	if (vs == hs)
+		return -EINVAL;
+	rfbi.tearsync_pin_cnt = pin_cnt;
+	dev_dbg(rfbi.fbdev->dev,
+		"setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n",
+		pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv);
+
+	rfbi_enable_clocks(1);
+	rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
+	rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
+
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	if (hs_pol_inv)
+		l &= ~(1 << 21);
+	else
+		l |= 1 << 21;
+	if (vs_pol_inv)
+		l &= ~(1 << 20);
+	else
+		l |= 1 << 20;
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+
+static int rfbi_enable_tearsync(int enable, unsigned line)
+{
+	u32 l;
+
+	dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n",
+		enable, line, rfbi.tearsync_mode);
+	if (line > (1 << 11) - 1)
+		return -EINVAL;
+
+	rfbi_enable_clocks(1);
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	l &= ~(0x3 << 2);
+	if (enable) {
+		rfbi.tearsync_mode = rfbi.tearsync_pin_cnt;
+		l |= rfbi.tearsync_mode << 2;
+	} else
+		rfbi.tearsync_mode = 0;
+	rfbi_write_reg(RFBI_CONFIG0, l);
+	rfbi_write_reg(RFBI_LINE_NUMBER, line);
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+
+static void rfbi_write_command(const void *buf, unsigned int len)
+{
+	rfbi_enable_clocks(1);
+	if (rfbi.bits_per_cycle == 16) {
+		const u16 *w = buf;
+		BUG_ON(len & 1);
+		for (; len; len -= 2)
+			rfbi_write_reg(RFBI_CMD, *w++);
+	} else {
+		const u8 *b = buf;
+		BUG_ON(rfbi.bits_per_cycle != 8);
+		for (; len; len--)
+			rfbi_write_reg(RFBI_CMD, *b++);
+	}
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_read_data(void *buf, unsigned int len)
+{
+	rfbi_enable_clocks(1);
+	if (rfbi.bits_per_cycle == 16) {
+		u16 *w = buf;
+		BUG_ON(len & ~1);
+		for (; len; len -= 2) {
+			rfbi_write_reg(RFBI_READ, 0);
+			*w++ = rfbi_read_reg(RFBI_READ);
+		}
+	} else {
+		u8 *b = buf;
+		BUG_ON(rfbi.bits_per_cycle != 8);
+		for (; len; len--) {
+			rfbi_write_reg(RFBI_READ, 0);
+			*b++ = rfbi_read_reg(RFBI_READ);
+		}
+	}
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_write_data(const void *buf, unsigned int len)
+{
+	rfbi_enable_clocks(1);
+	if (rfbi.bits_per_cycle == 16) {
+		const u16 *w = buf;
+		BUG_ON(len & 1);
+		for (; len; len -= 2)
+			rfbi_write_reg(RFBI_PARAM, *w++);
+	} else {
+		const u8 *b = buf;
+		BUG_ON(rfbi.bits_per_cycle != 8);
+		for (; len; len--)
+			rfbi_write_reg(RFBI_PARAM, *b++);
+	}
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_transfer_area(int width, int height,
+				void (callback)(void * data), void *data)
+{
+	u32 w;
+
+	BUG_ON(callback == NULL);
+
+	rfbi_enable_clocks(1);
+	omap_dispc_set_lcd_size(width, height);
+
+	rfbi.lcdc_callback = callback;
+	rfbi.lcdc_callback_data = data;
+
+	rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
+
+	w = rfbi_read_reg(RFBI_CONTROL);
+	w |= 1;				/* enable */
+	if (!rfbi.tearsync_mode)
+		w |= 1 << 4;		/* internal trigger, reset by HW */
+	rfbi_write_reg(RFBI_CONTROL, w);
+
+	omap_dispc_enable_lcd_out(1);
+}
+
+static inline void _stop_transfer(void)
+{
+	u32 w;
+
+	w = rfbi_read_reg(RFBI_CONTROL);
+	rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
+	rfbi_enable_clocks(0);
+}
+
+static void rfbi_dma_callback(void *data)
+{
+	_stop_transfer();
+	rfbi.lcdc_callback(rfbi.lcdc_callback_data);
+}
+
+static void rfbi_set_bits_per_cycle(int bpc)
+{
+	u32 l;
+
+	rfbi_enable_clocks(1);
+	l = rfbi_read_reg(RFBI_CONFIG0);
+	l &= ~(0x03 << 0);
+
+	switch (bpc) {
+	case 8:
+		break;
+	case 16:
+		l |= 3;
+		break;
+	default:
+		BUG();
+	}
+	rfbi_write_reg(RFBI_CONFIG0, l);
+	rfbi.bits_per_cycle = bpc;
+	rfbi_enable_clocks(0);
+}
+
+static int rfbi_init(struct omapfb_device *fbdev)
+{
+	u32 l;
+	int r;
+
+	rfbi.fbdev = fbdev;
+	rfbi.base = io_p2v(RFBI_BASE);
+
+	if ((r = rfbi_get_clocks()) < 0)
+		return r;
+	rfbi_enable_clocks(1);
+
+	rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
+
+	/* Reset */
+	rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
+	while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
+
+	l = rfbi_read_reg(RFBI_SYSCONFIG);
+	/* Enable autoidle and smart-idle */
+	l |= (1 << 0) | (2 << 3);
+	rfbi_write_reg(RFBI_SYSCONFIG, l);
+
+	/* 16-bit interface, ITE trigger mode, 16-bit data */
+	l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
+	l |= (0 << 9) | (1 << 20) | (1 << 21);
+	rfbi_write_reg(RFBI_CONFIG0, l);
+
+	rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
+
+	l = rfbi_read_reg(RFBI_CONTROL);
+	/* Select CS0, clear bypass mode */
+	l = (0x01 << 2);
+	rfbi_write_reg(RFBI_CONTROL, l);
+
+	if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
+		dev_err(fbdev->dev, "can't get DISPC irq\n");
+		rfbi_enable_clocks(0);
+		return r;
+	}
+
+	l = rfbi_read_reg(RFBI_REVISION);
+	pr_info("omapfb: RFBI version %d.%d initialized\n",
+		(l >> 4) & 0x0f, l & 0x0f);
+
+	rfbi_enable_clocks(0);
+
+	return 0;
+}
+
+static void rfbi_cleanup(void)
+{
+	omap_dispc_free_irq();
+	rfbi_put_clocks();
+}
+
+const struct lcd_ctrl_extif omap2_ext_if = {
+	.init			= rfbi_init,
+	.cleanup		= rfbi_cleanup,
+	.get_clk_info		= rfbi_get_clk_info,
+	.get_max_tx_rate	= rfbi_get_max_tx_rate,
+	.set_bits_per_cycle	= rfbi_set_bits_per_cycle,
+	.convert_timings	= rfbi_convert_timings,
+	.set_timings		= rfbi_set_timings,
+	.write_command		= rfbi_write_command,
+	.read_data		= rfbi_read_data,
+	.write_data		= rfbi_write_data,
+	.transfer_area		= rfbi_transfer_area,
+	.setup_tearsync		= rfbi_setup_tearsync,
+	.enable_tearsync	= rfbi_enable_tearsync,
+
+	.max_transmit_size	= (u32) ~0,
+};
+
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
new file mode 100644
index 0000000..81dbcf5
--- /dev/null
+++ b/drivers/video/omap/sossi.c
@@ -0,0 +1,686 @@
+/*
+ * OMAP1 Special OptimiSed Screen Interface support
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#include "lcdc.h"
+
+#define MODULE_NAME		"omapfb-sossi"
+
+#define OMAP_SOSSI_BASE         0xfffbac00
+#define SOSSI_ID_REG		0x00
+#define SOSSI_INIT1_REG		0x04
+#define SOSSI_INIT2_REG		0x08
+#define SOSSI_INIT3_REG		0x0c
+#define SOSSI_FIFO_REG		0x10
+#define SOSSI_REOTABLE_REG	0x14
+#define SOSSI_TEARING_REG	0x18
+#define SOSSI_INIT1B_REG	0x1c
+#define SOSSI_FIFOB_REG		0x20
+
+#define DMA_GSCR          0xfffedc04
+#define DMA_LCD_CCR       0xfffee3c2
+#define DMA_LCD_CTRL      0xfffee3c4
+#define DMA_LCD_LCH_CTRL  0xfffee3ea
+
+#define CONF_SOSSI_RESET_R      (1 << 23)
+
+#define RD_ACCESS		0
+#define WR_ACCESS		1
+
+#define SOSSI_MAX_XMIT_BYTES	(512 * 1024)
+
+static struct {
+	void __iomem	*base;
+	struct clk	*fck;
+	unsigned long	fck_hz;
+	spinlock_t	lock;
+	int		bus_pick_count;
+	int		bus_pick_width;
+	int		tearsync_mode;
+	int		tearsync_line;
+	void		(*lcdc_callback)(void *data);
+	void		*lcdc_callback_data;
+	int		vsync_dma_pending;
+	/* timing for read and write access */
+	int		clk_div;
+	u8		clk_tw0[2];
+	u8		clk_tw1[2];
+	/*
+	 * if last_access is the same as current we don't have to change
+	 * the timings
+	 */
+	int		last_access;
+
+	struct omapfb_device	*fbdev;
+} sossi;
+
+static inline u32 sossi_read_reg(int reg)
+{
+	return readl(sossi.base + reg);
+}
+
+static inline u16 sossi_read_reg16(int reg)
+{
+	return readw(sossi.base + reg);
+}
+
+static inline u8 sossi_read_reg8(int reg)
+{
+	return readb(sossi.base + reg);
+}
+
+static inline void sossi_write_reg(int reg, u32 value)
+{
+	writel(value, sossi.base + reg);
+}
+
+static inline void sossi_write_reg16(int reg, u16 value)
+{
+	writew(value, sossi.base + reg);
+}
+
+static inline void sossi_write_reg8(int reg, u8 value)
+{
+	writeb(value, sossi.base + reg);
+}
+
+static void sossi_set_bits(int reg, u32 bits)
+{
+	sossi_write_reg(reg, sossi_read_reg(reg) | bits);
+}
+
+static void sossi_clear_bits(int reg, u32 bits)
+{
+	sossi_write_reg(reg, sossi_read_reg(reg) & ~bits);
+}
+
+#define HZ_TO_PS(x)	(1000000000 / (x / 1000))
+
+static u32 ps_to_sossi_ticks(u32 ps, int div)
+{
+	u32 clk_period = HZ_TO_PS(sossi.fck_hz) * div;
+	return (clk_period + ps - 1) / clk_period;
+}
+
+static int calc_rd_timings(struct extif_timings *t)
+{
+	u32 tw0, tw1;
+	int reon, reoff, recyc, actim;
+	int div = t->clk_div;
+
+	/*
+	 * Make sure that after conversion it still holds that:
+	 * reoff > reon, recyc >= reoff, actim > reon
+	 */
+	reon = ps_to_sossi_ticks(t->re_on_time, div);
+	/* reon will be exactly one sossi tick */
+	if (reon > 1)
+		return -1;
+
+	reoff = ps_to_sossi_ticks(t->re_off_time, div);
+
+	if (reoff <= reon)
+		reoff = reon + 1;
+
+	tw0 = reoff - reon;
+	if (tw0 > 0x10)
+		return -1;
+
+	recyc = ps_to_sossi_ticks(t->re_cycle_time, div);
+	if (recyc <= reoff)
+		recyc = reoff + 1;
+
+	tw1 = recyc - tw0;
+	/* values less then 3 result in the SOSSI block resetting itself */
+	if (tw1 < 3)
+		tw1 = 3;
+	if (tw1 > 0x40)
+		return -1;
+
+	actim = ps_to_sossi_ticks(t->access_time, div);
+	if (actim < reoff)
+		actim++;
+	/*
+	 * access time (data hold time) will be exactly one sossi
+	 * tick
+	 */
+	if (actim - reoff > 1)
+		return -1;
+
+	t->tim[0] = tw0 - 1;
+	t->tim[1] = tw1 - 1;
+
+	return 0;
+}
+
+static int calc_wr_timings(struct extif_timings *t)
+{
+	u32 tw0, tw1;
+	int weon, weoff, wecyc;
+	int div = t->clk_div;
+
+	/*
+	 * Make sure that after conversion it still holds that:
+	 * weoff > weon, wecyc >= weoff
+	 */
+	weon = ps_to_sossi_ticks(t->we_on_time, div);
+	/* weon will be exactly one sossi tick */
+	if (weon > 1)
+		return -1;
+
+	weoff = ps_to_sossi_ticks(t->we_off_time, div);
+	if (weoff <= weon)
+		weoff = weon + 1;
+	tw0 = weoff - weon;
+	if (tw0 > 0x10)
+		return -1;
+
+	wecyc = ps_to_sossi_ticks(t->we_cycle_time, div);
+	if (wecyc <= weoff)
+		wecyc = weoff + 1;
+
+	tw1 = wecyc - tw0;
+	/* values less then 3 result in the SOSSI block resetting itself */
+	if (tw1 < 3)
+		tw1 = 3;
+	if (tw1 > 0x40)
+		return -1;
+
+	t->tim[2] = tw0 - 1;
+	t->tim[3] = tw1 - 1;
+
+	return 0;
+}
+
+static void _set_timing(int div, int tw0, int tw1)
+{
+	u32 l;
+
+#ifdef VERBOSE
+	dev_dbg(sossi.fbdev->dev, "Using TW0 = %d, TW1 = %d, div = %d\n",
+		 tw0 + 1, tw1 + 1, div);
+#endif
+
+	clk_set_rate(sossi.fck, sossi.fck_hz / div);
+	clk_enable(sossi.fck);
+	l = sossi_read_reg(SOSSI_INIT1_REG);
+	l &= ~((0x0f << 20) | (0x3f << 24));
+	l |= (tw0 << 20) | (tw1 << 24);
+	sossi_write_reg(SOSSI_INIT1_REG, l);
+	clk_disable(sossi.fck);
+}
+
+static void _set_bits_per_cycle(int bus_pick_count, int bus_pick_width)
+{
+	u32 l;
+
+	l = sossi_read_reg(SOSSI_INIT3_REG);
+	l &= ~0x3ff;
+	l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
+	sossi_write_reg(SOSSI_INIT3_REG, l);
+}
+
+static void _set_tearsync_mode(int mode, unsigned line)
+{
+	u32 l;
+
+	l = sossi_read_reg(SOSSI_TEARING_REG);
+	l &= ~(((1 << 11) - 1) << 15);
+	l |= line << 15;
+	l &= ~(0x3 << 26);
+	l |= mode << 26;
+	sossi_write_reg(SOSSI_TEARING_REG, l);
+	if (mode)
+		sossi_set_bits(SOSSI_INIT2_REG, 1 << 6);	/* TE logic */
+	else
+		sossi_clear_bits(SOSSI_INIT2_REG, 1 << 6);
+}
+
+static inline void set_timing(int access)
+{
+	if (access != sossi.last_access) {
+		sossi.last_access = access;
+		_set_timing(sossi.clk_div,
+			    sossi.clk_tw0[access], sossi.clk_tw1[access]);
+	}
+}
+
+static void sossi_start_transfer(void)
+{
+	/* WE */
+	sossi_clear_bits(SOSSI_INIT2_REG, 1 << 4);
+	/* CS active low */
+	sossi_clear_bits(SOSSI_INIT1_REG, 1 << 30);
+}
+
+static void sossi_stop_transfer(void)
+{
+	/* WE */
+	sossi_set_bits(SOSSI_INIT2_REG, 1 << 4);
+	/* CS active low */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 30);
+}
+
+static void wait_end_of_write(void)
+{
+	/* Before reading we must check if some writings are going on */
+	while (!(sossi_read_reg(SOSSI_INIT2_REG) & (1 << 3)));
+}
+
+static void send_data(const void *data, unsigned int len)
+{
+	while (len >= 4) {
+		sossi_write_reg(SOSSI_FIFO_REG, *(const u32 *) data);
+		len -= 4;
+		data += 4;
+	}
+	while (len >= 2) {
+		sossi_write_reg16(SOSSI_FIFO_REG, *(const u16 *) data);
+		len -= 2;
+		data += 2;
+	}
+	while (len) {
+		sossi_write_reg8(SOSSI_FIFO_REG, *(const u8 *) data);
+		len--;
+		data++;
+	}
+}
+
+static void set_cycles(unsigned int len)
+{
+	unsigned long nr_cycles = len / (sossi.bus_pick_width / 8);
+
+	BUG_ON((nr_cycles - 1) & ~0x3ffff);
+
+	sossi_clear_bits(SOSSI_INIT1_REG, 0x3ffff);
+	sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff);
+}
+
+static int sossi_convert_timings(struct extif_timings *t)
+{
+	int r = 0;
+	int div = t->clk_div;
+
+	t->converted = 0;
+
+	if (div <= 0 || div > 8)
+		return -1;
+
+	/* no CS on SOSSI, so ignore cson, csoff, cs_pulsewidth */
+	if ((r = calc_rd_timings(t)) < 0)
+		return r;
+
+	if ((r = calc_wr_timings(t)) < 0)
+		return r;
+
+	t->tim[4] = div;
+
+	t->converted = 1;
+
+	return 0;
+}
+
+static void sossi_set_timings(const struct extif_timings *t)
+{
+	BUG_ON(!t->converted);
+
+	sossi.clk_tw0[RD_ACCESS] = t->tim[0];
+	sossi.clk_tw1[RD_ACCESS] = t->tim[1];
+
+	sossi.clk_tw0[WR_ACCESS] = t->tim[2];
+	sossi.clk_tw1[WR_ACCESS] = t->tim[3];
+
+	sossi.clk_div = t->tim[4];
+}
+
+static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+	*clk_period = HZ_TO_PS(sossi.fck_hz);
+	*max_clk_div = 8;
+}
+
+static void sossi_set_bits_per_cycle(int bpc)
+{
+	int bus_pick_count, bus_pick_width;
+
+	/*
+	 * We set explicitly the the bus_pick_count as well, although
+	 * with remapping/reordering disabled it will be calculated by HW
+	 * as (32 / bus_pick_width).
+	 */
+	switch (bpc) {
+	case 8:
+		bus_pick_count = 4;
+		bus_pick_width = 8;
+		break;
+	case 16:
+		bus_pick_count = 2;
+		bus_pick_width = 16;
+		break;
+	default:
+		BUG();
+		return;
+	}
+	sossi.bus_pick_width = bus_pick_width;
+	sossi.bus_pick_count = bus_pick_count;
+}
+
+static int sossi_setup_tearsync(unsigned pin_cnt,
+				unsigned hs_pulse_time, unsigned vs_pulse_time,
+				int hs_pol_inv, int vs_pol_inv, int div)
+{
+	int hs, vs;
+	u32 l;
+
+	if (pin_cnt != 1 || div < 1 || div > 8)
+		return -EINVAL;
+
+	hs = ps_to_sossi_ticks(hs_pulse_time, div);
+	vs = ps_to_sossi_ticks(vs_pulse_time, div);
+	if (vs < 8 || vs <= hs || vs >= (1 << 12))
+		return -EDOM;
+	vs /= 8;
+	vs--;
+	if (hs > 8)
+		hs = 8;
+	if (hs)
+		hs--;
+
+	dev_dbg(sossi.fbdev->dev,
+		"setup_tearsync: hs %d vs %d hs_inv %d vs_inv %d\n",
+		hs, vs, hs_pol_inv, vs_pol_inv);
+
+	clk_enable(sossi.fck);
+	l = sossi_read_reg(SOSSI_TEARING_REG);
+	l &= ~((1 << 15) - 1);
+	l |= vs << 3;
+	l |= hs;
+	if (hs_pol_inv)
+		l |= 1 << 29;
+	else
+		l &= ~(1 << 29);
+	if (vs_pol_inv)
+		l |= 1 << 28;
+	else
+		l &= ~(1 << 28);
+	sossi_write_reg(SOSSI_TEARING_REG, l);
+	clk_disable(sossi.fck);
+
+	return 0;
+}
+
+static int sossi_enable_tearsync(int enable, unsigned line)
+{
+	int mode;
+
+	dev_dbg(sossi.fbdev->dev, "tearsync %d line %d\n", enable, line);
+	if (line >= 1 << 11)
+		return -EINVAL;
+	if (enable) {
+		if (line)
+			mode = 2;		/* HS or VS */
+		else
+			mode = 3;		/* VS only */
+	} else
+		mode = 0;
+	sossi.tearsync_line = line;
+	sossi.tearsync_mode = mode;
+
+	return 0;
+}
+
+static void sossi_write_command(const void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_clear_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	send_data(data, len);
+	sossi_stop_transfer();
+	wait_end_of_write();
+	clk_disable(sossi.fck);
+}
+
+static void sossi_write_data(const void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	send_data(data, len);
+	sossi_stop_transfer();
+	wait_end_of_write();
+	clk_disable(sossi.fck);
+}
+
+static void sossi_transfer_area(int width, int height,
+				void (callback)(void *data), void *data)
+{
+	BUG_ON(callback == NULL);
+
+	sossi.lcdc_callback = callback;
+	sossi.lcdc_callback_data = data;
+
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	_set_tearsync_mode(sossi.tearsync_mode, sossi.tearsync_line);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(width * height * sossi.bus_pick_width / 8);
+
+	sossi_start_transfer();
+	if (sossi.tearsync_mode) {
+		/*
+		 * Wait for the sync signal and start the transfer only
+		 * then. We can't seem to be able to use HW sync DMA for
+		 * this since LCD DMA shows huge latencies, as if it
+		 * would ignore some of the DMA requests from SoSSI.
+		 */
+		unsigned long flags;
+
+		spin_lock_irqsave(&sossi.lock, flags);
+		sossi.vsync_dma_pending++;
+		spin_unlock_irqrestore(&sossi.lock, flags);
+	} else
+		/* Just start the transfer right away. */
+		omap_enable_lcd_dma();
+}
+
+static void sossi_dma_callback(void *data)
+{
+	omap_stop_lcd_dma();
+	sossi_stop_transfer();
+	clk_disable(sossi.fck);
+	sossi.lcdc_callback(sossi.lcdc_callback_data);
+}
+
+static void sossi_read_data(void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(RD_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	while (len >= 4) {
+		*(u32 *) data = sossi_read_reg(SOSSI_FIFO_REG);
+		len -= 4;
+		data += 4;
+	}
+	while (len >= 2) {
+		*(u16 *) data = sossi_read_reg16(SOSSI_FIFO_REG);
+		len -= 2;
+		data += 2;
+	}
+	while (len) {
+		*(u8 *) data = sossi_read_reg8(SOSSI_FIFO_REG);
+		len--;
+		data++;
+	}
+	sossi_stop_transfer();
+	clk_disable(sossi.fck);
+}
+
+static irqreturn_t sossi_match_irq(int irq, void *data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sossi.lock, flags);
+	if (sossi.vsync_dma_pending) {
+		sossi.vsync_dma_pending--;
+		omap_enable_lcd_dma();
+	}
+	spin_unlock_irqrestore(&sossi.lock, flags);
+	return IRQ_HANDLED;
+}
+
+static int sossi_init(struct omapfb_device *fbdev)
+{
+	u32 l, k;
+	struct clk *fck;
+	struct clk *dpll1out_ck;
+	int r;
+
+	sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE);
+	sossi.fbdev = fbdev;
+	spin_lock_init(&sossi.lock);
+
+	dpll1out_ck = clk_get(fbdev->dev, "ck_dpll1out");
+	if (IS_ERR(dpll1out_ck)) {
+		dev_err(fbdev->dev, "can't get DPLL1OUT clock\n");
+		return PTR_ERR(dpll1out_ck);
+	}
+	/*
+	 * We need the parent clock rate, which we might divide further
+	 * depending on the timing requirements of the controller. See
+	 * _set_timings.
+	 */
+	sossi.fck_hz = clk_get_rate(dpll1out_ck);
+	clk_put(dpll1out_ck);
+
+	fck = clk_get(fbdev->dev, "ck_sossi");
+	if (IS_ERR(fck)) {
+		dev_err(fbdev->dev, "can't get SoSSI functional clock\n");
+		return PTR_ERR(fck);
+	}
+	sossi.fck = fck;
+
+	/* Reset and enable the SoSSI module */
+	l = omap_readl(MOD_CONF_CTRL_1);
+	l |= CONF_SOSSI_RESET_R;
+	omap_writel(l, MOD_CONF_CTRL_1);
+	l &= ~CONF_SOSSI_RESET_R;
+	omap_writel(l, MOD_CONF_CTRL_1);
+
+	clk_enable(sossi.fck);
+	l = omap_readl(ARM_IDLECT2);
+	l &= ~(1 << 8);			/* DMACK_REQ */
+	omap_writel(l, ARM_IDLECT2);
+
+	l = sossi_read_reg(SOSSI_INIT2_REG);
+	/* Enable and reset the SoSSI block */
+	l |= (1 << 0) | (1 << 1);
+	sossi_write_reg(SOSSI_INIT2_REG, l);
+	/* Take SoSSI out of reset */
+	l &= ~(1 << 1);
+	sossi_write_reg(SOSSI_INIT2_REG, l);
+
+	sossi_write_reg(SOSSI_ID_REG, 0);
+	l = sossi_read_reg(SOSSI_ID_REG);
+	k = sossi_read_reg(SOSSI_ID_REG);
+
+	if (l != 0x55555555 || k != 0xaaaaaaaa) {
+		dev_err(fbdev->dev,
+			"invalid SoSSI sync pattern: %08x, %08x\n", l, k);
+		r = -ENODEV;
+		goto err;
+	}
+
+	if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) {
+		dev_err(fbdev->dev, "can't get LCDC IRQ\n");
+		r = -ENODEV;
+		goto err;
+	}
+
+	l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
+	l = sossi_read_reg(SOSSI_ID_REG);
+	dev_info(fbdev->dev, "SoSSI version %d.%d initialized\n",
+		l >> 16, l & 0xffff);
+
+	l = sossi_read_reg(SOSSI_INIT1_REG);
+	l |= (1 << 19); /* DMA_MODE */
+	l &= ~(1 << 31); /* REORDERING */
+	sossi_write_reg(SOSSI_INIT1_REG, l);
+
+	if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
+			     IRQT_FALLING,
+	     "sossi_match", sossi.fbdev->dev)) < 0) {
+		dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
+		goto err;
+	}
+
+	clk_disable(sossi.fck);
+	return 0;
+
+err:
+	clk_disable(sossi.fck);
+	clk_put(sossi.fck);
+	return r;
+}
+
+static void sossi_cleanup(void)
+{
+	omap_lcdc_free_dma_callback();
+	clk_put(sossi.fck);
+}
+
+struct lcd_ctrl_extif omap1_ext_if = {
+	.init			= sossi_init,
+	.cleanup		= sossi_cleanup,
+	.get_clk_info		= sossi_get_clk_info,
+	.convert_timings	= sossi_convert_timings,
+	.set_timings		= sossi_set_timings,
+	.set_bits_per_cycle	= sossi_set_bits_per_cycle,
+	.setup_tearsync		= sossi_setup_tearsync,
+	.enable_tearsync	= sossi_enable_tearsync,
+	.write_command		= sossi_write_command,
+	.read_data		= sossi_read_data,
+	.write_data		= sossi_write_data,
+	.transfer_area		= sossi_transfer_area,
+
+	.max_transmit_size	= SOSSI_MAX_XMIT_BYTES,
+};
+
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index e64f8b5..8503e73 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -52,7 +52,7 @@
 	struct {
 		__u8 red, green, blue;
 	}				palette[256];
-	u32				pseudo_palette[17];
+	u32				pseudo_palette[16];
 	
 	volatile struct cmap_regs	__iomem *cmap_regs;
 	unsigned long			cmap_regs_phys;
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index ab5e668..10c0cc6 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -24,7 +24,7 @@
  * License. See the file COPYING in the main directory of this archive for
  * more details.
  *
- * 
+ *
  */
 
 #include <linux/module.h>
@@ -58,7 +58,7 @@
 #endif
 
 /*
- * Driver data 
+ * Driver data
  */
 static char *mode __devinitdata = NULL;
 
@@ -82,12 +82,12 @@
 {
 	pm2type_t	type;		/* Board type */
 	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
-	u32 	   	memclock;	/* memclock */
+	u32		memclock;	/* memclock */
 	u32		video;		/* video flags before blanking */
 	u32		mem_config;	/* MemConfig reg at probe */
 	u32		mem_control;	/* MemControl reg at probe */
 	u32		boot_address;	/* BootAddress reg at probe */
-	u32             palette[16];
+	u32		palette[16];
 };
 
 /*
@@ -95,12 +95,12 @@
  * if we don't use modedb.
  */
 static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
-	.id =		"", 
+	.id =		"",
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_PSEUDOCOLOR,
 	.xpanstep =	1,
 	.ypanstep =	1,
-	.ywrapstep =	0, 
+	.ywrapstep =	0,
 	.accel =	FB_ACCEL_3DLABS_PERMEDIA2,
 };
 
@@ -109,26 +109,26 @@
  */
 static struct fb_var_screeninfo pm2fb_var __devinitdata = {
 	/* "640x480, 8 bpp @ 60 Hz */
-	.xres =		640,
-	.yres =		480,
-	.xres_virtual =	640,
-	.yres_virtual =	480,
-	.bits_per_pixel =8,
-	.red =		{0, 8, 0},
-	.blue =		{0, 8, 0},
-	.green =	{0, 8, 0},
-	.activate =	FB_ACTIVATE_NOW,
-	.height =	-1,
-	.width =	-1,
-	.accel_flags =	0,
-	.pixclock =	39721,
-	.left_margin =	40,
-	.right_margin =	24,
-	.upper_margin =	32,
-	.lower_margin =	11,
-	.hsync_len =	96,
-	.vsync_len =	2,
-	.vmode =	FB_VMODE_NONINTERLACED
+	.xres =			640,
+	.yres =			480,
+	.xres_virtual =		640,
+	.yres_virtual =		480,
+	.bits_per_pixel =	8,
+	.red =			{0, 8, 0},
+	.blue =			{0, 8, 0},
+	.green =		{0, 8, 0},
+	.activate =		FB_ACTIVATE_NOW,
+	.height =		-1,
+	.width =		-1,
+	.accel_flags =		0,
+	.pixclock =		39721,
+	.left_margin =		40,
+	.right_margin =		24,
+	.upper_margin =		32,
+	.lower_margin =		11,
+	.hsync_len =		96,
+	.vsync_len =		2,
+	.vmode =		FB_VMODE_NONINTERLACED
 };
 
 /*
@@ -166,7 +166,7 @@
 		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
 		index = PM2VR_RD_INDEXED_DATA;
 		break;
-	}	
+	}
 	mb();
 	return pm2_RD(p, index);
 }
@@ -182,20 +182,22 @@
 		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
 		index = PM2VR_RD_INDEXED_DATA;
 		break;
-	}	
-	mb();
+	}
+	wmb();
 	pm2_WR(p, index, v);
+	wmb();
 }
 
 static inline void pm2v_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
 {
 	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
-	mb();
+	wmb();
 	pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
+	wmb();
 }
 
 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
-#define WAIT_FIFO(p,a)
+#define WAIT_FIFO(p, a)
 #else
 static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a)
 {
@@ -207,7 +209,7 @@
 /*
  * partial products for the supported horizontal resolutions.
  */
-#define PACKPP(p0,p1,p2)	(((p2) << 6) | ((p1) << 3) | (p0))
+#define PACKPP(p0, p1, p2)	(((p2) << 6) | ((p1) << 3) | (p0))
 static const struct {
 	u16 width;
 	u16 pp;
@@ -355,7 +357,7 @@
 static void reset_config(struct pm2fb_par* p)
 {
 	WAIT_FIFO(p, 52);
-	pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
+	pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG) &
 	       ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
 	pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
 	pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
@@ -365,7 +367,7 @@
 	pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
 	pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
 	pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
-	pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0); 
+	pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
 	pm2_WR(p, PM2R_LB_READ_MODE, 0);
 	pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
 	pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
@@ -466,11 +468,9 @@
 		WAIT_FIFO(par, 8);
 		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8);
 		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0);
-		wmb();
 		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m);
 		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_FEEDBACK, n);
 		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p);
-		wmb();
 		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1);
 		rmb();
 		for (i = 256;
@@ -483,12 +483,9 @@
 		pm2_mnp(clk, &m, &n, &p);
 		WAIT_FIFO(par, 10);
 		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
-		wmb();
 		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
 		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
-		wmb();
 		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
-		wmb();
 		pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
 		rmb();
 		for (i = 256;
@@ -509,12 +506,9 @@
 		pm2_mnp(clk, &m, &n, &p);
 		WAIT_FIFO(par, 8);
 		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
-		wmb();
 		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
 		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
-		wmb();
 		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
-		wmb();
 		pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
 		rmb();
 		for (i = 256;
@@ -541,7 +535,7 @@
 	vsync = video;
 
 	DPRINTK("video = 0x%x\n", video);
-	
+
 	/*
 	 * The hardware cursor needs +vsync to recognise vert retrace.
 	 * We may not be using the hardware cursor, but the X Glint
@@ -580,9 +574,9 @@
  */
 
 /**
- *      pm2fb_check_var - Optional function. Validates a var passed in. 
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer 
+ *	pm2fb_check_var - Optional function. Validates a var passed in.
+ *	@var: frame buffer variable screen structure
+ *	@info: frame buffer structure that represents a single frame buffer
  *
  *	Checks to see if the hardware supports the state requested by
  *	var passed in.
@@ -621,23 +615,23 @@
 
 	var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
 	lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
-  
+
 	if (var->xres < 320 || var->xres > 1600) {
 		DPRINTK("width not supported: %u\n", var->xres);
 		return -EINVAL;
 	}
-  
+
 	if (var->yres < 200 || var->yres > 1200) {
 		DPRINTK("height not supported: %u\n", var->yres);
 		return -EINVAL;
 	}
-  
+
 	if (lpitch * var->yres_virtual > info->fix.smem_len) {
 		DPRINTK("no memory for screen (%ux%ux%u)\n",
 			var->xres, var->yres_virtual, var->bits_per_pixel);
 		return -EINVAL;
 	}
-  
+
 	if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
 		DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
 		return -EINVAL;
@@ -678,17 +672,17 @@
 		break;
 	}
 	var->height = var->width = -1;
-  
+
 	var->accel_flags = 0;	/* Can't mmap if this is on */
-	
+
 	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
 		var->xres, var->yres, var->bits_per_pixel);
 	return 0;
 }
 
 /**
- *      pm2fb_set_par - Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
+ *	pm2fb_set_par - Alters the hardware state.
+ *	@info: frame buffer structure that represents a single frame buffer
  *
  *	Using the fb_var_screeninfo in fb_info we set the resolution of the
  *	this particular framebuffer.
@@ -715,7 +709,7 @@
 	clear_palette(par);
 	if ( par->memclock )
 		set_memclock(par, par->memclock);
-    
+
 	width = (info->var.xres_virtual + 7) & ~7;
 	height = info->var.yres_virtual;
 	depth = (info->var.bits_per_pixel + 7) & ~7;
@@ -728,7 +722,7 @@
 		DPRINTK("pixclock too high (%uKHz)\n", pixclock);
 		return -EINVAL;
 	}
-    
+
 	hsstart = to3264(info->var.right_margin, depth, data64);
 	hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
 	hbend = hsend + to3264(info->var.left_margin, depth, data64);
@@ -743,7 +737,7 @@
 	base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
 	if (data64)
 		video |= PM2F_DATA_64_ENABLE;
-    
+
 	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
 		if (lowhsync) {
 			DPRINTK("ignoring +hsync, using -hsync.\n");
@@ -784,9 +778,9 @@
 		WAIT_FIFO(par, 1);
 		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
 	}
-    
+
 	set_aperture(par, depth);
-    
+
 	mb();
 	WAIT_FIFO(par, 19);
 	pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
@@ -853,22 +847,22 @@
 	set_pixclock(par, pixclock);
 	DPRINTK("Setting graphics mode at %dx%d depth %d\n",
 		info->var.xres, info->var.yres, info->var.bits_per_pixel);
-	return 0;	
+	return 0;
 }
 
 /**
- *  	pm2fb_setcolreg - Sets a color register.
- *      @regno: boolean, 0 copy local, 1 get_user() function
- *      @red: frame buffer colormap structure
- *	@green: The green value which can be up to 16 bits wide 
+ *	pm2fb_setcolreg - Sets a color register.
+ *	@regno: boolean, 0 copy local, 1 get_user() function
+ *	@red: frame buffer colormap structure
+ *	@green: The green value which can be up to 16 bits wide
  *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported the alpha value which can be up to 16 bits wide.	
- *      @info: frame buffer info structure
- * 
- *  	Set a single color register. The values supplied have a 16 bit
- *  	magnitude which needs to be scaled in this function for the hardware.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *	@info: frame buffer info structure
+ *
+ *	Set a single color register. The values supplied have a 16 bit
+ *	magnitude which needs to be scaled in this function for the hardware.
  *	Pretty much a direct lift from tdfxfb.c.
- * 
+ *
  *	Returns negative errno on error, or zero on success.
  */
 static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -912,7 +906,7 @@
 	 *    (blue << blue.offset) | (transp << transp.offset)
 	 *    RAMDAC does not exist
 	 */
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF -(val)) >> 16)
 	switch (info->fix.visual) {
 	case FB_VISUAL_TRUECOLOR:
 	case FB_VISUAL_PSEUDOCOLOR:
@@ -922,9 +916,9 @@
 		transp = CNVT_TOHW(transp, info->var.transp.length);
 		break;
 	case FB_VISUAL_DIRECTCOLOR:
-		/* example here assumes 8 bit DAC. Might be different 
-		 * for your hardware */	
-		red = CNVT_TOHW(red, 8);       
+		/* example here assumes 8 bit DAC. Might be different
+		 * for your hardware */
+		red = CNVT_TOHW(red, 8);
 		green = CNVT_TOHW(green, 8);
 		blue = CNVT_TOHW(blue, 8);
 		/* hey, there is bug in transp handling... */
@@ -946,11 +940,11 @@
 
 		switch (info->var.bits_per_pixel) {
 		case 8:
-			break;	
-   		case 16:
+			break;
+		case 16:
 		case 24:
-		case 32:	
-           		par->palette[regno] = v;
+		case 32:
+			par->palette[regno] = v;
 			break;
 		}
 		return 0;
@@ -962,15 +956,15 @@
 }
 
 /**
- *      pm2fb_pan_display - Pans the display.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
+ *	pm2fb_pan_display - Pans the display.
+ *	@var: frame buffer variable screen structure
+ *	@info: frame buffer structure that represents a single frame buffer
  *
  *	Pan (or wrap, depending on the `vmode' field) the display using the
- *  	`xoffset' and `yoffset' fields of the `var' structure.
- *  	If the values don't fit, return -EINVAL.
+ *	`xoffset' and `yoffset' fields of the `var' structure.
+ *	If the values don't fit, return -EINVAL.
  *
- *      Returns negative errno on error, or zero on success.
+ *	Returns negative errno on error, or zero on success.
  *
  */
 static int pm2fb_pan_display(struct fb_var_screeninfo *var,
@@ -986,24 +980,24 @@
 	depth = (depth > 32) ? 32 : depth;
 	base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
 	WAIT_FIFO(p, 1);
-	pm2_WR(p, PM2R_SCREEN_BASE, base);    
+	pm2_WR(p, PM2R_SCREEN_BASE, base);
 	return 0;
 }
 
 /**
- *      pm2fb_blank - Blanks the display.
- *      @blank_mode: the blank mode we want. 
- *      @info: frame buffer structure that represents a single frame buffer
+ *	pm2fb_blank - Blanks the display.
+ *	@blank_mode: the blank mode we want.
+ *	@info: frame buffer structure that represents a single frame buffer
  *
- *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
- *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a 
- *      video mode which doesn't support it. Implements VESA suspend
- *      and powerdown modes on hardware that supports disabling hsync/vsync:
- *      blank_mode == 2: suspend vsync
- *      blank_mode == 3: suspend hsync
- *      blank_mode == 4: powerdown
+ *	Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *	blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *	video mode which doesn't support it. Implements VESA suspend
+ *	and powerdown modes on hardware that supports disabling hsync/vsync:
+ *	blank_mode == 2: suspend vsync
+ *	blank_mode == 3: suspend hsync
+ *	blank_mode == 4: powerdown
  *
- *      Returns negative errno on error, or zero on success.
+ *	Returns negative errno on error, or zero on success.
  *
  */
 static int pm2fb_blank(int blank_mode, struct fb_info *info)
@@ -1066,10 +1060,9 @@
 
 	if (!w || !h)
 		return;
-	WAIT_FIFO(par, 6);
+	WAIT_FIFO(par, 5);
 	pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
 		PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
-	pm2_WR(par, PM2R_FB_PIXEL_OFFSET, 0);
 	if (copy)
 		pm2_WR(par, PM2R_FB_SOURCE_DELTA,
 			((ysrc-y) & 0xfff) << 16 | ((xsrc-x) & 0xfff));
@@ -1078,7 +1071,7 @@
 	pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (y << 16) | x);
 	pm2_WR(par, PM2R_RECTANGLE_SIZE, (h << 16) | w);
 	wmb();
-	pm2_WR(par, PM2R_RENDER,PM2F_RENDER_RECTANGLE |
+	pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE |
 				(x<xsrc ? PM2F_INCREASE_X : 0) |
 				(y<ysrc ? PM2F_INCREASE_Y : 0) |
 				(copy ? 0 : PM2F_RENDER_FASTFILL));
@@ -1241,7 +1234,7 @@
 	DPRINTK("Adjusting register base for big-endian.\n");
 #endif
 	DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
-    
+
 	/* Registers - request region and map it. */
 	if ( !request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
 				 "pm2fb regbase") ) {
@@ -1324,17 +1317,17 @@
 	}
 
 	info->fbops		= &pm2fb_ops;
-	info->fix		= pm2fb_fix; 	
+	info->fix		= pm2fb_fix;
 	info->pseudo_palette	= default_par->palette;
 	info->flags		= FBINFO_DEFAULT |
-                                  FBINFO_HWACCEL_YPAN |
-	                          FBINFO_HWACCEL_COPYAREA |
-	                          FBINFO_HWACCEL_FILLRECT;
+				  FBINFO_HWACCEL_YPAN |
+				  FBINFO_HWACCEL_COPYAREA |
+				  FBINFO_HWACCEL_FILLRECT;
 
 	if (!mode)
 		mode = "640x480@60";
-	 
-	err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8); 
+
+	err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8);
 	if (!err || err == 4)
 		info->var = pm2fb_var;
 
@@ -1355,8 +1348,8 @@
 	return 0;
 
  err_exit_all:
-	fb_dealloc_cmap(&info->cmap);	
- err_exit_both:    
+	fb_dealloc_cmap(&info->cmap);
+ err_exit_both:
 	iounmap(info->screen_base);
 	release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
  err_exit_mmio:
@@ -1381,7 +1374,7 @@
 	struct pm2fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-    
+
 	iounmap(info->screen_base);
 	release_mem_region(fix->smem_start, fix->smem_len);
 	iounmap(par->v_regs);
@@ -1409,9 +1402,9 @@
 
 static struct pci_driver pm2fb_driver = {
 	.name		= "pm2fb",
-	.id_table 	= pm2fb_id_table,
-	.probe 		= pm2fb_probe,
-	.remove 	= __devexit_p(pm2fb_remove),
+	.id_table	= pm2fb_id_table,
+	.probe		= pm2fb_probe,
+	.remove		= __devexit_p(pm2fb_remove),
 };
 
 MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
@@ -1430,7 +1423,7 @@
 	if (!options || !*options)
 		return 0;
 
-	while ((this_opt = strsep(&options, ",")) != NULL) {	
+	while ((this_opt = strsep(&options, ",")) != NULL) {
 		if (!*this_opt)
 			continue;
 		if(!strcmp(this_opt, "lowhsync")) {
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index c77a1a1..5b3f54c 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -52,11 +52,6 @@
 static char *mode_option __devinitdata;
 
 /*
- *  If your driver supports multiple boards, you should make the
- *  below data types arrays, or allocate them dynamically (using kmalloc()).
- */
-
-/*
  * This structure defines the hardware state of the graphics card. Normally
  * you place this in a header file in linux/include/video. This file usually
  * also includes register information. That allows other driver subsystems
@@ -67,7 +62,7 @@
 	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
 	u32		video;		/* video flags before blanking */
 	u32		base;		/* screen base (xoffset+yoffset) in 128 bits unit */
-	u32 		palette[16];
+	u32		palette[16];
 };
 
 /*
@@ -82,7 +77,7 @@
 	.xpanstep =	1,
 	.ypanstep =	1,
 	.ywrapstep =	0,
-	.accel =	FB_ACCEL_NONE,
+	.accel =	FB_ACCEL_3DLABS_PERMEDIA3,
 };
 
 /*
@@ -104,36 +99,28 @@
 	while (PM3_READ_REG(par, PM3InFIFOSpace) < n);
 }
 
-static inline void PM3_SLOW_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
-{
-	if (par->v_regs) {
-		mb();
-		PM3_WAIT(par, 1);
-		wmb();
-		PM3_WRITE_REG(par, off, v);
-	}
-}
-
-static inline void PM3_SET_INDEX(struct pm3_par *par, unsigned index)
-{
-	PM3_SLOW_WRITE_REG(par, PM3RD_IndexHigh, (index >> 8) & 0xff);
-	PM3_SLOW_WRITE_REG(par, PM3RD_IndexLow, index & 0xff);
-}
-
 static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
 {
-	PM3_SET_INDEX(par, r);
+	PM3_WAIT(par, 3);
+	PM3_WRITE_REG(par, PM3RD_IndexHigh, (r >> 8) & 0xff);
+	PM3_WRITE_REG(par, PM3RD_IndexLow, r & 0xff);
 	wmb();
 	PM3_WRITE_REG(par, PM3RD_IndexedData, v);
+	wmb();
 }
 
 static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
 			unsigned char r, unsigned char g, unsigned char b)
 {
-	PM3_SLOW_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
-	PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, r);
-	PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, g);
-	PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, b);
+	PM3_WAIT(par, 4);
+	PM3_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
+	wmb();
+	PM3_WRITE_REG(par, PM3RD_PaletteData, r);
+	wmb();
+	PM3_WRITE_REG(par, PM3RD_PaletteData, g);
+	wmb();
+	PM3_WRITE_REG(par, PM3RD_PaletteData, b);
+	wmb();
 }
 
 static void pm3fb_clear_colormap(struct pm3_par *par,
@@ -141,7 +128,7 @@
 {
 	int i;
 
-	for (i = 0; i < 256 ; i++) /* fill color map with white */
+	for (i = 0; i < 256 ; i++)
 		pm3fb_set_color(par, i, r, g, b);
 
 }
@@ -175,22 +162,261 @@
 	}
 }
 
-static inline int pm3fb_shift_bpp(unsigned long depth, int v)
+static inline int pm3fb_depth(const struct fb_var_screeninfo *var)
 {
-	switch (depth) {
+	if ( var->bits_per_pixel == 16 )
+		return var->red.length + var->green.length
+			+ var->blue.length;
+
+	return var->bits_per_pixel;
+}
+
+static inline int pm3fb_shift_bpp(unsigned bpp, int v)
+{
+	switch (bpp) {
 	case 8:
 		return (v >> 4);
-	case 12:
-	case 15:
 	case 16:
 		return (v >> 3);
 	case 32:
 		return (v >> 2);
 	}
-	DPRINTK("Unsupported depth %ld\n", depth);
+	DPRINTK("Unsupported depth %u\n", bpp);
 	return 0;
 }
 
+/* acceleration */
+static int pm3fb_sync(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+
+	PM3_WAIT(par, 2);
+	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+	PM3_WRITE_REG(par, PM3Sync, 0);
+	mb();
+	do {
+		while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0);
+		rmb();
+	} while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);
+
+	return 0;
+}
+
+static void pm3fb_init_engine(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	const u32 width = (info->var.xres_virtual + 7) & ~7;
+
+	PM3_WAIT(par, 50);
+	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+	PM3_WRITE_REG(par, PM3StatisticMode, 0x0);
+	PM3_WRITE_REG(par, PM3DeltaMode, 0x0);
+	PM3_WRITE_REG(par, PM3RasterizerMode, 0x0);
+	PM3_WRITE_REG(par, PM3ScissorMode, 0x0);
+	PM3_WRITE_REG(par, PM3LineStippleMode, 0x0);
+	PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0);
+	PM3_WRITE_REG(par, PM3GIDMode, 0x0);
+	PM3_WRITE_REG(par, PM3DepthMode, 0x0);
+	PM3_WRITE_REG(par, PM3StencilMode, 0x0);
+	PM3_WRITE_REG(par, PM3StencilData, 0x0);
+	PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0);
+	PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LUTMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0);
+	PM3_WRITE_REG(par, PM3FogMode, 0x0);
+	PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0);
+	PM3_WRITE_REG(par, PM3AntialiasMode, 0x0);
+	PM3_WRITE_REG(par, PM3YUVMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0);
+	PM3_WRITE_REG(par, PM3DitherMode, 0x0);
+	PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0);
+	PM3_WRITE_REG(par, PM3RouterMode, 0x0);
+	PM3_WRITE_REG(par, PM3Window, 0x0);
+
+	PM3_WRITE_REG(par, PM3Config2D, 0x0);
+
+	PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff);
+
+	PM3_WRITE_REG(par, PM3XBias, 0x0);
+	PM3_WRITE_REG(par, PM3YBias, 0x0);
+	PM3_WRITE_REG(par, PM3DeltaControl, 0x0);
+
+	PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff);
+
+	PM3_WRITE_REG(par, PM3FBDestReadEnables,
+			   PM3FBDestReadEnables_E(0xff) |
+			   PM3FBDestReadEnables_R(0xff) |
+			   PM3FBDestReadEnables_ReferenceAlpha(0xff));
+	PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0);
+	PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0);
+	PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0,
+			   PM3FBDestReadBufferWidth_Width(width));
+
+	PM3_WRITE_REG(par, PM3FBDestReadMode,
+			   PM3FBDestReadMode_ReadEnable |
+			   PM3FBDestReadMode_Enable0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth,
+			   PM3FBSourceReadBufferWidth_Width(width));
+	PM3_WRITE_REG(par, PM3FBSourceReadMode,
+			   PM3FBSourceReadMode_Blocking |
+			   PM3FBSourceReadMode_ReadEnable);
+
+	PM3_WAIT(par, 2);
+	{
+		unsigned long rm = 1;
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_8BIT);
+			break;
+		case 16:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_16BIT);
+			break;
+		case 32:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_32BIT);
+			break;
+		default:
+			DPRINTK(1, "Unsupported depth %d\n",
+				info->var.bits_per_pixel);
+			break;
+		}
+		PM3_WRITE_REG(par, PM3RasterizerMode, rm);
+	}
+
+	PM3_WAIT(par, 20);
+	PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff);
+	PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff);
+	PM3_WRITE_REG(par, PM3FBWriteMode,
+			   PM3FBWriteMode_WriteEnable |
+			   PM3FBWriteMode_OpaqueSpan |
+			   PM3FBWriteMode_Enable0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferWidth0,
+			   PM3FBWriteBufferWidth_Width(width));
+
+	PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0);
+	{
+		/* size in lines of FB */
+		unsigned long sofb = info->screen_size /
+			info->fix.line_length;
+		if (sofb > 4095)
+			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095);
+		else
+			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb);
+
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (2 << 3));
+			break;
+		case 16:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (1 << 3));
+			break;
+		case 32:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (0 << 3));
+			break;
+		default:
+			DPRINTK(1, "Unsupported depth %d\n",
+				info->current_par->depth);
+			break;
+		}
+	}
+
+	PM3_WRITE_REG(par, PM3dXDom, 0x0);
+	PM3_WRITE_REG(par, PM3dXSub, 0x0);
+	PM3_WRITE_REG(par, PM3dY, (1 << 16));
+	PM3_WRITE_REG(par, PM3StartXDom, 0x0);
+	PM3_WRITE_REG(par, PM3StartXSub, 0x0);
+	PM3_WRITE_REG(par, PM3StartY, 0x0);
+	PM3_WRITE_REG(par, PM3Count, 0x0);
+
+/* Disable LocalBuffer. better safe than sorry */
+	PM3_WRITE_REG(par, PM3LBDestReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LBDestReadEnables, 0x0);
+	PM3_WRITE_REG(par, PM3LBSourceReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LBWriteMode, 0x0);
+
+	pm3fb_sync(info);
+}
+
+static void pm3fb_fillrect (struct fb_info *info,
+				const struct fb_fillrect *region)
+{
+	struct pm3_par *par = info->par;
+	struct fb_fillrect modded;
+	int vxres, vyres;
+	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+		((u32*)info->pseudo_palette)[region->color] : region->color;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
+		region->rop != ROP_COPY ) {
+		cfb_fillrect(info, region);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if(!modded.width || !modded.height ||
+	   modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if(modded.dx + modded.width  > vxres)
+		modded.width  = vxres - modded.dx;
+	if(modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	if(info->var.bits_per_pixel == 8)
+		color |= color << 8;
+	if(info->var.bits_per_pixel <= 16)
+		color |= color << 16;
+
+	PM3_WAIT(par, 4);
+
+	PM3_WRITE_REG(par, PM3Config2D,
+				  PM3Config2D_UseConstantSource |
+				  PM3Config2D_ForegroundROPEnable |
+				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
+				  PM3Config2D_FBWriteEnable);
+
+	PM3_WRITE_REG(par, PM3ForegroundColor, color);
+
+	PM3_WRITE_REG(par, PM3RectanglePosition,
+		      (PM3RectanglePosition_XOffset(modded.dx)) |
+		      (PM3RectanglePosition_YOffset(modded.dy)));
+
+	PM3_WRITE_REG(par, PM3Render2D,
+		      PM3Render2D_XPositive |
+		      PM3Render2D_YPositive |
+		      PM3Render2D_Operation_Normal |
+		      PM3Render2D_SpanOperation |
+		      (PM3Render2D_Width(modded.width)) |
+		      (PM3Render2D_Height(modded.height)));
+}
+/* end of acceleration functions */
+
 /* write the mode to registers */
 static void pm3fb_write_mode(struct fb_info *info)
 {
@@ -206,56 +432,50 @@
 	const u32 vbend = vsend + info->var.upper_margin;
 	const u32 vtotal = info->var.yres + vbend;
 	const u32 width = (info->var.xres_virtual + 7) & ~7;
+	const unsigned bpp = info->var.bits_per_pixel;
 
-	PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
-	PM3_SLOW_WRITE_REG(par, PM3Aperture0, 0x00000000);
-	PM3_SLOW_WRITE_REG(par, PM3Aperture1, 0x00000000);
-	PM3_SLOW_WRITE_REG(par, PM3FIFODis, 0x00000007);
+	PM3_WAIT(par, 20);
+	PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
+	PM3_WRITE_REG(par, PM3Aperture0, 0x00000000);
+	PM3_WRITE_REG(par, PM3Aperture1, 0x00000000);
+	PM3_WRITE_REG(par, PM3FIFODis, 0x00000007);
 
-	PM3_SLOW_WRITE_REG(par, PM3HTotal,
-			   pm3fb_shift_bpp(info->var.bits_per_pixel,
-					  htotal - 1));
-	PM3_SLOW_WRITE_REG(par, PM3HsEnd,
-			   pm3fb_shift_bpp(info->var.bits_per_pixel,
-					  hsend));
-	PM3_SLOW_WRITE_REG(par, PM3HsStart,
-			   pm3fb_shift_bpp(info->var.bits_per_pixel,
-					  hsstart));
-	PM3_SLOW_WRITE_REG(par, PM3HbEnd,
-			   pm3fb_shift_bpp(info->var.bits_per_pixel,
-					  hbend));
-	PM3_SLOW_WRITE_REG(par, PM3HgEnd,
-			   pm3fb_shift_bpp(info->var.bits_per_pixel,
-					  hbend));
-	PM3_SLOW_WRITE_REG(par, PM3ScreenStride,
-			   pm3fb_shift_bpp(info->var.bits_per_pixel,
-					  width));
-	PM3_SLOW_WRITE_REG(par, PM3VTotal, vtotal - 1);
-	PM3_SLOW_WRITE_REG(par, PM3VsEnd, vsend - 1);
-	PM3_SLOW_WRITE_REG(par, PM3VsStart, vsstart - 1);
-	PM3_SLOW_WRITE_REG(par, PM3VbEnd, vbend);
+	PM3_WRITE_REG(par, PM3HTotal,
+			   pm3fb_shift_bpp(bpp, htotal - 1));
+	PM3_WRITE_REG(par, PM3HsEnd,
+			   pm3fb_shift_bpp(bpp, hsend));
+	PM3_WRITE_REG(par, PM3HsStart,
+			   pm3fb_shift_bpp(bpp, hsstart));
+	PM3_WRITE_REG(par, PM3HbEnd,
+			   pm3fb_shift_bpp(bpp, hbend));
+	PM3_WRITE_REG(par, PM3HgEnd,
+			   pm3fb_shift_bpp(bpp, hbend));
+	PM3_WRITE_REG(par, PM3ScreenStride,
+			   pm3fb_shift_bpp(bpp, width));
+	PM3_WRITE_REG(par, PM3VTotal, vtotal - 1);
+	PM3_WRITE_REG(par, PM3VsEnd, vsend - 1);
+	PM3_WRITE_REG(par, PM3VsStart, vsstart - 1);
+	PM3_WRITE_REG(par, PM3VbEnd, vbend);
 
-	switch (info->var.bits_per_pixel) {
+	switch (bpp) {
 	case 8:
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_8BIT);
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_8BIT);
 		break;
 
-	case 12:
-	case 15:
 	case 16:
 #ifndef __BIG_ENDIAN
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_16BIT);
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_16BIT);
 #else
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_16BIT |
 				   PM3ByApertureMode_BYTESWAP_BADC);
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_16BIT |
 				   PM3ByApertureMode_BYTESWAP_BADC);
 #endif /* ! __BIG_ENDIAN */
@@ -263,23 +483,22 @@
 
 	case 32:
 #ifndef __BIG_ENDIAN
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_32BIT);
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_32BIT);
 #else
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_32BIT |
 				   PM3ByApertureMode_BYTESWAP_DCBA);
-		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_32BIT |
 				   PM3ByApertureMode_BYTESWAP_DCBA);
 #endif /* ! __BIG_ENDIAN */
 		break;
 
 	default:
-		DPRINTK("Unsupported depth %d\n",
-			info->var.bits_per_pixel);
+		DPRINTK("Unsupported depth %d\n", bpp);
 		break;
 	}
 
@@ -296,14 +515,15 @@
 			   PM3VideoControl_VSYNC_MASK);
 		video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
 			 PM3VideoControl_VSYNC_ACTIVE_HIGH;
-		PM3_SLOW_WRITE_REG(par, PM3VideoControl, video);
+		PM3_WRITE_REG(par, PM3VideoControl, video);
 	}
-	PM3_SLOW_WRITE_REG(par, PM3VClkCtl,
+	PM3_WRITE_REG(par, PM3VClkCtl,
 			   (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));
-	PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
-	PM3_SLOW_WRITE_REG(par, PM3ChipConfig,
+	PM3_WRITE_REG(par, PM3ScreenBase, par->base);
+	PM3_WRITE_REG(par, PM3ChipConfig,
 			   (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));
 
+	wmb();
 	{
 		unsigned char uninitialized_var(m);	/* ClkPreScale */
 		unsigned char uninitialized_var(n);	/* ClkFeedBackScale */
@@ -337,7 +557,7 @@
 
 	PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);
 
-	switch (info->var.bits_per_pixel) {
+	switch (pm3fb_depth(&info->var)) {
 	case 8:
 		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
 				  PM3RD_PixelSize_8_BIT_PIXELS);
@@ -392,58 +612,43 @@
 /*
  * hardware independent functions
  */
-int pm3fb_init(void);
-int pm3fb_setup(char*);
-
 static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	u32 lpitch;
+	unsigned bpp = var->red.length + var->green.length
+			+ var->blue.length + var->transp.length;
 
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	switch(var->bits_per_pixel) {
-	case 8:
-		var->red.length = var->green.length = var->blue.length = 8;
-		var->red.offset = var->green.offset = var->blue.offset = 0;
-		break;
-	case 12:
-		var->red.offset   = 8;
-		var->red.length   = 4;
-		var->green.offset = 4;
-		var->green.length = 4;
-		var->blue.offset  = 0;
-		var->blue.length  = 4;
-		var->transp.offset = 12;
-		var->transp.length = 4;
-	case 15:
-		var->red.offset   = 10;
-		var->red.length   = 5;
-		var->green.offset = 5;
-		var->green.length = 5;
-		var->blue.offset  = 0;
-		var->blue.length  = 5;
-		var->transp.offset = 15;
-		var->transp.length = 1;
-		break;
-	case 16:
-		var->red.offset   = 11;
-		var->red.length   = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset  = 0;
-		var->blue.length  = 5;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		var->red.offset	  = 16;
-		var->green.offset = 8;
-		var->blue.offset  = 0;
-		var->red.length = var->green.length = var->blue.length = 8;
-		break;
-	default:
-		DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
-		return -EINVAL;
+	if ( bpp != var->bits_per_pixel ) {
+		/* set predefined mode for bits_per_pixel settings */
+
+		switch(var->bits_per_pixel) {
+		case 8:
+			var->red.length = var->green.length = var->blue.length = 8;
+			var->red.offset = var->green.offset = var->blue.offset = 0;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+			break;
+		case 16:
+			var->red.length = var->blue.length = 5;
+			var->green.length = 6;
+			var->transp.length = 0;
+			break;
+		case 32:
+			var->red.length = var->green.length = var->blue.length = 8;
+			var->transp.length = 8;
+			break;
+		default:
+			DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+			return -EINVAL;
+		}
+	}
+	/* it is assumed BGRA order */
+	if (var->bits_per_pixel > 8 )
+	{
+		var->blue.offset = 0;
+		var->green.offset = var->blue.length;
+		var->red.offset = var->green.offset + var->green.length;
+		var->transp.offset = var->red.offset + var->red.length;
 	}
 	var->height = var->width = -1;
 
@@ -502,10 +707,9 @@
 {
 	struct pm3_par *par = info->par;
 	const u32 xres = (info->var.xres + 31) & ~31;
-	const int depth = (info->var.bits_per_pixel + 7) & ~7;
+	const unsigned bpp = info->var.bits_per_pixel;
 
-	par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
-					(info->var.yoffset * xres)
+	par->base = pm3fb_shift_bpp(bpp,(info->var.yoffset * xres)
 					+ info->var.xoffset);
 	par->video = 0;
 
@@ -524,18 +728,16 @@
 	else
 		par->video |= PM3VideoControl_LINE_DOUBLE_OFF;
 
-	if (info->var.activate == FB_ACTIVATE_NOW)
+	if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
 		par->video |= PM3VideoControl_ENABLE;
 	else {
 		par->video |= PM3VideoControl_DISABLE;
 		DPRINTK("PM3Video disabled\n");
 	}
-	switch (depth) {
+	switch (bpp) {
 	case 8:
 		par->video |= PM3VideoControl_PIXELSIZE_8BIT;
 		break;
-	case 12:
-	case 15:
 	case 16:
 		par->video |= PM3VideoControl_PIXELSIZE_16BIT;
 		break;
@@ -548,14 +750,15 @@
 	}
 
 	info->fix.visual =
-		(depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+		(bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 	info->fix.line_length = ((info->var.xres_virtual + 7)  & ~7)
-					* depth / 8;
+					* bpp / 8;
 
 /*	pm3fb_clear_memory(info, 0);*/
 	pm3fb_clear_colormap(par, 0, 0, 0);
 	PM3_WRITE_DAC_REG(par, PM3RD_CursorMode,
 			  PM3RD_CursorMode_CURSOR_DISABLE);
+	pm3fb_init_engine(info);
 	pm3fb_write_mode(info);
 	return 0;
 }
@@ -580,8 +783,8 @@
 	 *   var->{color}.length contains length of bitfield
 	 *   {hardwarespecific} contains width of DAC
 	 *   pseudo_palette[X] is programmed to (X << red.offset) |
-	 *				      (X << green.offset) |
-	 *				      (X << blue.offset)
+	 *					(X << green.offset) |
+	 *					(X << blue.offset)
 	 *   RAMDAC[X] is programmed to (red, green, blue)
 	 *   color depth = SUM(var->{color}.length)
 	 *
@@ -621,7 +824,6 @@
 		case 8:
 			break;
 		case 16:
-		case 24:
 		case 32:
 			((u32*)(info->pseudo_palette))[regno] = v;
 			break;
@@ -643,7 +845,8 @@
 	par->base = pm3fb_shift_bpp(var->bits_per_pixel,
 					(var->yoffset * xres)
 					+ var->xoffset);
-	PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
+	PM3_WAIT(par, 1);
+	PM3_WRITE_REG(par, PM3ScreenBase, par->base);
 	return 0;
 }
 
@@ -665,31 +868,31 @@
 
 	switch (blank_mode) {
 	case FB_BLANK_UNBLANK:
-		video = video | PM3VideoControl_ENABLE;
+		video |= PM3VideoControl_ENABLE;
 		break;
-	case FB_BLANK_NORMAL:	/* FIXME */
-		video = video & ~(PM3VideoControl_ENABLE);
+	case FB_BLANK_NORMAL:
+		video &= ~(PM3VideoControl_ENABLE);
 		break;
 	case FB_BLANK_HSYNC_SUSPEND:
-		video = video & ~(PM3VideoControl_HSYNC_MASK |
-				  PM3VideoControl_BLANK_ACTIVE_LOW);
+		video &= ~(PM3VideoControl_HSYNC_MASK |
+			  PM3VideoControl_BLANK_ACTIVE_LOW);
 		break;
 	case FB_BLANK_VSYNC_SUSPEND:
-		video = video & ~(PM3VideoControl_VSYNC_MASK |
-				  PM3VideoControl_BLANK_ACTIVE_LOW);
+		video &= ~(PM3VideoControl_VSYNC_MASK |
+			  PM3VideoControl_BLANK_ACTIVE_LOW);
 		break;
 	case FB_BLANK_POWERDOWN:
-		video = video & ~(PM3VideoControl_HSYNC_MASK |
-				  PM3VideoControl_VSYNC_MASK |
-				  PM3VideoControl_BLANK_ACTIVE_LOW);
+		video &= ~(PM3VideoControl_HSYNC_MASK |
+			  PM3VideoControl_VSYNC_MASK |
+			  PM3VideoControl_BLANK_ACTIVE_LOW);
 		break;
 	default:
 		DPRINTK("Unsupported blanking %d\n", blank_mode);
 		return 1;
 	}
 
-	PM3_SLOW_WRITE_REG(par,PM3VideoControl, video);
-
+	PM3_WAIT(par, 1);
+	PM3_WRITE_REG(par,PM3VideoControl, video);
 	return 0;
 }
 
@@ -703,10 +906,11 @@
 	.fb_set_par	= pm3fb_set_par,
 	.fb_setcolreg	= pm3fb_setcolreg,
 	.fb_pan_display	= pm3fb_pan_display,
-	.fb_fillrect	= cfb_fillrect,		/* Needed !!! */
-	.fb_copyarea	= cfb_copyarea,		/* Needed !!! */
-	.fb_imageblit	= cfb_imageblit,	/* Needed !!! */
+	.fb_fillrect	= pm3fb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
 	.fb_blank	= pm3fb_blank,
+	.fb_sync	= pm3fb_sync,
 };
 
 /* ------------------------------------------------------------------------- */
@@ -722,7 +926,7 @@
 	unsigned long	memsize = 0, tempBypass, i, temp1, temp2;
 	unsigned char	__iomem *screen_mem;
 
-	pm3fb_fix.smem_len = 64 * 1024 * 1024; /* request full aperture size */
+	pm3fb_fix.smem_len = 64 * 1024l * 1024; /* request full aperture size */
 	/* Linear frame buffer - request region and map it. */
 	if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
 				 "pm3fb smem")) {
@@ -744,7 +948,8 @@
 
 	DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
 
-	PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
+	PM3_WAIT(par, 1);
+	PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
 
 	/* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
 	for (i = 0; i < 32; i++) {
@@ -765,10 +970,9 @@
 	if (memsize + 1 == i) {
 		for (i = 0; i < 32; i++) {
 			/* Clear first 32MB ; 0 is 0, no need to byteswap */
-			writel(0x0000000,
-			       (screen_mem + (i * 1048576)));
-			mb();
+			writel(0x0000000, (screen_mem + (i * 1048576)));
 		}
+		wmb();
 
 		for (i = 32; i < 64; i++) {
 			fb_writel(i * 0x00345678,
@@ -787,7 +991,8 @@
 	}
 	DPRINTK("Second detect pass got %ld MB\n", memsize + 1);
 
-	PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
+	PM3_WAIT(par, 1);
+	PM3_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
 
 	iounmap(screen_mem);
 	release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
@@ -874,7 +1079,8 @@
 
 	info->fix = pm3fb_fix;
 	info->pseudo_palette = par->palette;
-	info->flags = FBINFO_DEFAULT;/* | FBINFO_HWACCEL_YPAN;*/
+	info->flags = FBINFO_DEFAULT |
+			FBINFO_HWACCEL_FILLRECT;/* | FBINFO_HWACCEL_YPAN;*/
 
 	/*
 	 * This should give a reasonable default video mode. The following is
@@ -890,7 +1096,6 @@
 		goto err_exit_both;
 	}
 
-	/* This has to been done !!! */
 	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
 		retval = -ENOMEM;
 		goto err_exit_both;
@@ -907,7 +1112,7 @@
 	}
 	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
 	   info->fix.id);
-	pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
+	pci_set_drvdata(dev, info);
 	return 0;
 
  err_exit_all:
@@ -949,8 +1154,7 @@
 
 static struct pci_device_id pm3fb_id_table[] = {
 	{ PCI_VENDOR_ID_3DLABS, 0x0a,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
-	  0xff0000, 0 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0, }
 };
 
@@ -964,19 +1168,12 @@
 
 MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
 
-int __init pm3fb_init(void)
+static int __init pm3fb_init(void)
 {
-	/*
-	 *  For kernel boot options (in 'video=pm3fb:<options>' format)
-	 */
 #ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("pm3fb", &option))
+	if (fb_get_options("pm3fb", NULL))
 		return -ENODEV;
-	pm3fb_setup(option);
 #endif
-
 	return pci_register_driver(&pm3fb_driver);
 }
 
@@ -985,22 +1182,6 @@
 	pci_unregister_driver(&pm3fb_driver);
 }
 
-#ifndef MODULE
-	/*
-	 *  Setup
-	 */
-
-/*
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-int __init pm3fb_setup(char *options)
-{
-	/* Parse user speficied options (`video=pm3fb:') */
-	return 0;
-}
-#endif /* MODULE */
-
 module_init(pm3fb_init);
 module_exit(pm3fb_exit);
 
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 9756a72..3972aa8 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -27,7 +27,6 @@
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/ioctl.h>
 #include <linux/notifier.h>
@@ -46,6 +45,9 @@
 #include <asm/ps3fb.h>
 #include <asm/ps3.h>
 
+
+#define DEVICE_NAME		"ps3fb"
+
 #ifdef PS3FB_DEBUG
 #define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
 #else
@@ -126,7 +128,6 @@
 
 struct ps3fb_priv {
 	unsigned int irq_no;
-	void *dev;
 
 	u64 context_handle, memory_handle;
 	void *xdr_ea;
@@ -171,7 +172,7 @@
 	{    0,    0,   0,   0 , 0} };
 
 /* default resolution */
-#define GPU_RES_INDEX 0		/* 720 x 480 */
+#define GPU_RES_INDEX	0		/* 720 x 480 */
 
 static const struct fb_videomode ps3fb_modedb[] = {
     /* 60 Hz broadcast modes (modes "1" to "5") */
@@ -298,10 +299,9 @@
 #define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
 
 static int ps3fb_mode;
-module_param(ps3fb_mode, bool, 0);
+module_param(ps3fb_mode, int, 0);
 
-static char *mode_option __initdata;
-
+static char *mode_option __devinitdata;
 
 static int ps3fb_get_res_table(u32 xres, u32 yres)
 {
@@ -681,15 +681,15 @@
 
 EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
 
-void ps3fb_flip_ctl(int on)
+void ps3fb_flip_ctl(int on, void *data)
 {
+	struct ps3fb_priv *priv = data;
 	if (on)
-		atomic_dec_if_positive(&ps3fb.ext_flip);
+		atomic_dec_if_positive(&priv->ext_flip);
 	else
-		atomic_inc(&ps3fb.ext_flip);
+		atomic_inc(&priv->ext_flip);
 }
 
-EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
 
     /*
      * ioctl
@@ -812,6 +812,7 @@
 
 static int ps3fbd(void *arg)
 {
+	set_freezable();
 	while (!kthread_should_stop()) {
 		try_to_freeze();
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -851,37 +852,9 @@
 	return IRQ_HANDLED;
 }
 
-#ifndef MODULE
-static int __init ps3fb_setup(char *options)
-{
-	char *this_opt;
-	int mode = 0;
 
-	if (!options || !*options)
-		return 0;	/* no options */
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strncmp(this_opt, "mode:", 5))
-			mode = simple_strtoul(this_opt + 5, NULL, 0);
-		else
-			mode_option = this_opt;
-	}
-	return mode;
-}
-#endif	/* MODULE */
-
-    /*
-     *  Initialisation
-     */
-
-static void ps3fb_platform_release(struct device *device)
-{
-	/* This is called when the reference count goes to zero. */
-}
-
-static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
+				struct ps3_system_bus_device *dev)
 {
 	int error;
 
@@ -897,7 +870,6 @@
 		return -EINVAL;
 	}
 
-	ps3fb.dev = dev;
 	error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
 				   &ps3fb.irq_no);
 	if (error) {
@@ -907,7 +879,7 @@
 	}
 
 	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
-			    "ps3fb vsync", ps3fb.dev);
+			    DEVICE_NAME, dev);
 	if (error) {
 		printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
 		       error);
@@ -951,12 +923,14 @@
 static struct fb_ops ps3fb_ops = {
 	.fb_open	= ps3fb_open,
 	.fb_release	= ps3fb_release,
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
 	.fb_check_var	= ps3fb_check_var,
 	.fb_set_par	= ps3fb_set_par,
 	.fb_setcolreg	= ps3fb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
 	.fb_mmap	= ps3fb_mmap,
 	.fb_blank	= ps3fb_blank,
 	.fb_ioctl	= ps3fb_ioctl,
@@ -964,16 +938,45 @@
 };
 
 static struct fb_fix_screeninfo ps3fb_fix __initdata = {
-	.id =		"PS3 FB",
+	.id =		DEVICE_NAME,
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_TRUECOLOR,
 	.accel =	FB_ACCEL_NONE,
 };
 
-static int __init ps3fb_probe(struct platform_device *dev)
+static int ps3fb_set_sync(void)
+{
+	int status;
+
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC "
+		       "failed: %d\n", __func__, status);
+		return -1;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE "
+		       "failed: %d\n", __func__, status);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
 {
 	struct fb_info *info;
 	int retval = -ENOMEM;
+	u32 xres, yres;
 	u64 ddr_lpar = 0;
 	u64 lpar_dma_control = 0;
 	u64 lpar_driver_info = 0;
@@ -984,6 +987,30 @@
 	unsigned long offset;
 	struct task_struct *task;
 
+	status = ps3_open_hv_device(dev);
+	if (status) {
+		printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__);
+		goto err;
+	}
+
+	if (!ps3fb_mode)
+		ps3fb_mode = ps3av_get_mode();
+	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+
+	if (ps3fb_mode > 0 &&
+	    !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
+		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+		DPRINTK("res_index:%d\n", ps3fb.res_index);
+	} else
+		ps3fb.res_index = GPU_RES_INDEX;
+
+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
+	init_waitqueue_head(&ps3fb.wait_vsync);
+	ps3fb.num_frames = 1;
+
+	ps3fb_set_sync();
+
 	/* get gpu context handle */
 	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
 					 &ps3fb.memory_handle, &ddr_lpar);
@@ -1027,7 +1054,7 @@
 	 * leakage into userspace
 	 */
 	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
-	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->core);
 	if (!info)
 		goto err_free_irq;
 
@@ -1059,19 +1086,20 @@
 	if (retval < 0)
 		goto err_fb_dealloc;
 
-	platform_set_drvdata(dev, info);
+	dev->core.driver_data = info;
 
 	printk(KERN_INFO
 	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
 	       info->node, ps3fb_videomemory.size >> 10);
 
-	task = kthread_run(ps3fbd, info, "ps3fbd");
+	task = kthread_run(ps3fbd, info, DEVICE_NAME);
 	if (IS_ERR(task)) {
 		retval = PTR_ERR(task);
 		goto err_unregister_framebuffer;
 	}
 
 	ps3fb.task = task;
+	ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb);
 
 	return 0;
 
@@ -1082,7 +1110,7 @@
 err_framebuffer_release:
 	framebuffer_release(info);
 err_free_irq:
-	free_irq(ps3fb.irq_no, ps3fb.dev);
+	free_irq(ps3fb.irq_no, dev);
 	ps3_irq_plug_destroy(ps3fb.irq_no);
 err_iounmap_dinfo:
 	iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1094,26 +1122,30 @@
 	return retval;
 }
 
-static void ps3fb_shutdown(struct platform_device *dev)
-{
-	ps3fb_flip_ctl(0);	/* flip off */
-	ps3fb.dinfo->irq.mask = 0;
-	free_irq(ps3fb.irq_no, ps3fb.dev);
-	ps3_irq_plug_destroy(ps3fb.irq_no);
-	iounmap((u8 __iomem *)ps3fb.dinfo);
-}
-
-void ps3fb_cleanup(void)
+static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 {
 	int status;
+	struct fb_info *info = dev->core.driver_data;
 
+	DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+
+	ps3fb_flip_ctl(0, &ps3fb);	/* flip off */
+	ps3fb.dinfo->irq.mask = 0;
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+
+	ps3av_register_flip_ctl(NULL, NULL);
 	if (ps3fb.task) {
 		struct task_struct *task = ps3fb.task;
 		ps3fb.task = NULL;
 		kthread_stop(task);
 	}
 	if (ps3fb.irq_no) {
-		free_irq(ps3fb.irq_no, ps3fb.dev);
+		free_irq(ps3fb.irq_no, dev);
 		ps3_irq_plug_destroy(ps3fb.irq_no);
 	}
 	iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1126,134 +1158,69 @@
 	if (status)
 		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
 
-	ps3av_dev_close();
-}
+	ps3_close_hv_device(dev);
+	DPRINTK(" <- %s:%d\n", __func__, __LINE__);
 
-EXPORT_SYMBOL_GPL(ps3fb_cleanup);
-
-static int ps3fb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-	ps3fb_cleanup();
 	return 0;
 }
 
-static struct platform_driver ps3fb_driver = {
-	.probe	= ps3fb_probe,
-	.remove = ps3fb_remove,
-	.shutdown = ps3fb_shutdown,
-	.driver = { .name = "ps3fb" }
+static struct ps3_system_bus_driver ps3fb_driver = {
+	.match_id	= PS3_MATCH_ID_GRAPHICS,
+	.core.name	= DEVICE_NAME,
+	.core.owner	= THIS_MODULE,
+	.probe		= ps3fb_probe,
+	.remove		= ps3fb_shutdown,
+	.shutdown	= ps3fb_shutdown,
 };
 
-static struct platform_device ps3fb_device = {
-	.name	= "ps3fb",
-	.id	= 0,
-	.dev	= { .release = ps3fb_platform_release }
-};
-
-int ps3fb_set_sync(void)
+static int __init ps3fb_setup(void)
 {
-	int status;
+	char *options;
 
-#ifdef HEAD_A
-	status = lv1_gpu_context_attribute(0x0,
-					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
-					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
-	if (status) {
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
-		       __func__, status);
-		return -1;
-	}
+#ifdef MODULE
+	return 0;
 #endif
-#ifdef HEAD_B
-	status = lv1_gpu_context_attribute(0x0,
-					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
-					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
 
-	if (status) {
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
-		       __func__, status);
-		return -1;
+	if (fb_get_options(DEVICE_NAME, &options))
+		return -ENXIO;
+
+	if (!options || !*options)
+		return 0;
+
+	while (1) {
+		char *this_opt = strsep(&options, ",");
+
+		if (!this_opt)
+			break;
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
 	}
-#endif
 	return 0;
 }
 
-EXPORT_SYMBOL_GPL(ps3fb_set_sync);
-
 static int __init ps3fb_init(void)
 {
-	int error;
-#ifndef MODULE
-	int mode;
-	char *option = NULL;
+	if (!ps3fb_videomemory.address ||  ps3fb_setup())
+		return -ENXIO;
 
-	if (fb_get_options("ps3fb", &option))
-		goto err;
-#endif
+	return ps3_system_bus_driver_register(&ps3fb_driver);
+}
 
-	if (!ps3fb_videomemory.address)
-		goto err;
-
-	error = ps3av_dev_open();
-	if (error) {
-		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__);
-		goto err;
-	}
-
-	ps3fb_mode = ps3av_get_mode();
-	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
-#ifndef MODULE
-	mode = ps3fb_setup(option);	/* check boot option */
-	if (mode)
-		ps3fb_mode = mode;
-#endif
-	if (ps3fb_mode > 0) {
-		u32 xres, yres;
-		ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
-		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
-		DPRINTK("res_index:%d\n", ps3fb.res_index);
-	} else
-		ps3fb.res_index = GPU_RES_INDEX;
-
-	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
-	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
-	init_waitqueue_head(&ps3fb.wait_vsync);
-	ps3fb.num_frames = 1;
-
-	error = platform_driver_register(&ps3fb_driver);
-	if (!error) {
-		error = platform_device_register(&ps3fb_device);
-		if (error)
-			platform_driver_unregister(&ps3fb_driver);
-	}
-
-	ps3fb_set_sync();
-
-	return error;
-
-err:
-	return -ENXIO;
+static void __exit ps3fb_exit(void)
+{
+	DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+	ps3_system_bus_driver_unregister(&ps3fb_driver);
+	DPRINTK(" <- %s:%d\n", __func__, __LINE__);
 }
 
 module_init(ps3fb_init);
-
-#ifdef MODULE
-static void __exit ps3fb_exit(void)
-{
-	platform_device_unregister(&ps3fb_device);
-	platform_driver_unregister(&ps3fb_driver);
-}
-
 module_exit(ps3fb_exit);
 
 MODULE_LICENSE("GPL");
-#endif				/* MODULE */
+MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index df2909a..0f88c30 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -115,11 +115,11 @@
 enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 };
 
 struct pvr2_params { unsigned int val; char *name; };
-static struct pvr2_params cables[] __initdata = {
+static struct pvr2_params cables[] __devinitdata = {
 	{ CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },
 };
 
-static struct pvr2_params outputs[] __initdata = {
+static struct pvr2_params outputs[] __devinitdata = {
 	{ VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },
 };
 
@@ -147,16 +147,16 @@
 
 static struct fb_info *fb_info;
 
-static struct fb_fix_screeninfo pvr2_fix __initdata = {
+static struct fb_fix_screeninfo pvr2_fix __devinitdata = {
 	.id =		"NEC PowerVR2",
-	.type = 	FB_TYPE_PACKED_PIXELS,
-	.visual = 	FB_VISUAL_TRUECOLOR,
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
 	.ypanstep =	1,
 	.ywrapstep =	1,
-	.accel = 	FB_ACCEL_NONE,
+	.accel =	FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo pvr2_var __initdata = {
+static struct fb_var_screeninfo pvr2_var __devinitdata = {
 	.xres =		640,
 	.yres =		480,
 	.xres_virtual =	640,
@@ -195,10 +195,6 @@
 static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
 #endif
 
-/* Interface used by the world */
-
-int pvr2fb_setup(char*);
-
 static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue,
                             unsigned int transp, struct fb_info *info);
 static int pvr2fb_blank(int blank, struct fb_info *info);
@@ -227,12 +223,12 @@
 #ifdef CONFIG_SH_DMA
 	.fb_write	= pvr2fb_write,
 #endif
-	.fb_fillrect 	= cfb_fillrect,
+	.fb_fillrect	= cfb_fillrect,
 	.fb_copyarea	= cfb_copyarea,
 	.fb_imageblit	= cfb_imageblit,
 };
 
-static struct fb_videomode pvr2_modedb[] __initdata = {
+static struct fb_videomode pvr2_modedb[] __devinitdata = {
     /*
      * Broadcast video modes (PAL and NTSC).  I'm unfamiliar with
      * PAL-M and PAL-N, but from what I've read both modes parallel PAL and
@@ -252,7 +248,7 @@
 	/* 640x480 @ 60hz (VGA) */
 	"vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26,
 	0, FB_VMODE_YWRAP
-    }, 
+    },
 };
 
 #define NUM_TOTAL_MODES  ARRAY_SIZE(pvr2_modedb)
@@ -262,7 +258,7 @@
 #define DEFMODE_VGA	2
 
 static int defmode = DEFMODE_NTSC;
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 
 static inline void pvr2fb_set_pal_type(unsigned int type)
 {
@@ -293,7 +289,7 @@
 {
 	switch (var->bits_per_pixel) {
 	    case 16:        /* RGB 565 */
-	    	pvr2fb_set_pal_type(PAL_RGB565);
+		pvr2fb_set_pal_type(PAL_RGB565);
 		var->red.offset = 11;    var->red.length = 5;
 		var->green.offset = 5;   var->green.length = 6;
 		var->blue.offset = 0;    var->blue.length = 5;
@@ -306,7 +302,7 @@
 		var->transp.offset = 0;  var->transp.length = 0;
 		break;
 	    case 32:        /* ARGB 8888 */
-	    	pvr2fb_set_pal_type(PAL_ARGB8888);
+		pvr2fb_set_pal_type(PAL_ARGB8888);
 		var->red.offset = 16;    var->red.length = 8;
 		var->green.offset = 8;   var->green.length = 8;
 		var->blue.offset = 0;    var->blue.length = 8;
@@ -337,24 +333,25 @@
 		      ((blue  & 0xf800) >> 11);
 
 		pvr2fb_set_pal_entry(par, regno, tmp);
-		((u16*)(info->pseudo_palette))[regno] = tmp;
 		break;
 	    case 24: /* RGB 888 */
 		red >>= 8; green >>= 8; blue >>= 8;
-		((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
+		tmp = (red << 16) | (green << 8) | blue;
 		break;
 	    case 32: /* ARGB 8888 */
 		red >>= 8; green >>= 8; blue >>= 8;
 		tmp = (transp << 24) | (red << 16) | (green << 8) | blue;
 
 		pvr2fb_set_pal_entry(par, regno, tmp);
-		((u32*)(info->pseudo_palette))[regno] = tmp;
 		break;
 	    default:
 		pr_debug("Invalid bit depth %d?!?\n", info->var.bits_per_pixel);
 		return 1;
 	}
 
+	if (regno < 16)
+		((u32*)(info->pseudo_palette))[regno] = tmp;
+
 	return 0;
 }
 
@@ -379,13 +376,13 @@
 	var->vmode &= FB_VMODE_MASK;
 	if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
 		par->is_interlaced = 1;
-	/* 
+	/*
 	 * XXX: Need to be more creative with this (i.e. allow doublecan for
 	 * PAL/NTSC output).
 	 */
 	if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA)
 		par->is_doublescan = 1;
-	
+
 	par->hsync_total = var->left_margin + var->xres + var->right_margin +
 	                   var->hsync_len;
 	par->vsync_total = var->upper_margin + var->yres + var->lower_margin +
@@ -408,7 +405,7 @@
 	} else {
 		/* VGA mode */
 		/* XXX: What else needs to be checked? */
-		/* 
+		/*
 		 * XXX: We have a little freedom in VGA modes, what ranges
 		 * should be here (i.e. hsync/vsync totals, etc.)?
 		 */
@@ -419,8 +416,8 @@
 	/* Calculate the remainding offsets */
 	par->diwstart_h = par->borderstart_h + var->left_margin;
 	par->diwstart_v = par->borderstart_v + var->upper_margin;
-	par->borderstop_h = par->diwstart_h + var->xres + 
-			    var->right_margin;    
+	par->borderstop_h = par->diwstart_h + var->xres +
+			    var->right_margin;
 	par->borderstop_v = par->diwstart_v + var->yres +
 			    var->lower_margin;
 
@@ -465,12 +462,12 @@
 	set_color_bitfields(var);
 
 	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->xoffset || var->yoffset < 0 || 
+		if (var->xoffset || var->yoffset < 0 ||
 		    var->yoffset >= var->yres_virtual) {
 			var->xoffset = var->yoffset = 0;
 		} else {
 			if (var->xoffset > var->xres_virtual - var->xres ||
-		    	    var->yoffset > var->yres_virtual - var->yres || 
+			    var->yoffset > var->yres_virtual - var->yres ||
 			    var->xoffset < 0 || var->yoffset < 0)
 				var->xoffset = var->yoffset = 0;
 		}
@@ -478,7 +475,7 @@
 		var->xoffset = var->yoffset = 0;
 	}
 
-	/* 
+	/*
 	 * XXX: Need to be more creative with this (i.e. allow doublecan for
 	 * PAL/NTSC output).
 	 */
@@ -507,7 +504,7 @@
 		var->vsync_len    = par->borderstop_v +
 				   (par->vsync_total - par->borderstop_v);
 	}
-		
+
 	hsync_total = var->left_margin + var->xres + var->right_margin +
 		      var->hsync_len;
 	vtotal = var->upper_margin + var->yres + var->lower_margin +
@@ -531,7 +528,7 @@
 			}
 		}
 	}
-	
+
 	/* Check memory sizes */
 	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
 	if (line_length * var->yres_virtual > info->fix.smem_len)
@@ -552,7 +549,7 @@
 	          DISP_DIWADDRS);
 }
 
-/* 
+/*
  * Initialize the video mode.  Currently, the 16bpp and 24bpp modes aren't
  * very stable.  It's probably due to the fact that a lot of the 2D video
  * registers are still undocumented.
@@ -592,18 +589,18 @@
 	/* display window start position */
 	fb_writel(par->diwstart_h, DISP_DIWHSTRT);
 	fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT);
-	
+
 	/* misc. settings */
 	fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF);
 
 	/* clock doubler (for VGA), scan doubler, display enable */
-	fb_writel(((video_output == VO_VGA) << 23) | 
+	fb_writel(((video_output == VO_VGA) << 23) |
 	          (par->is_doublescan << 1) | 1, DISP_DIWMODE);
 
 	/* bits per pixel */
 	fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE);
 
-	/* video enable, color sync, interlace, 
+	/* video enable, color sync, interlace,
 	 * hsync and vsync polarity (currently unused) */
 	fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF);
 }
@@ -657,7 +654,7 @@
 static int pvr2_init_cable(void)
 {
 	if (cable_type < 0) {
-		fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000, 
+		fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000,
 	                  PCTRA);
 		cable_type = (fb_readw(PDTRA) >> 8) & 3;
 	}
@@ -687,7 +684,7 @@
 	pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
 	if (!pages)
 		return -ENOMEM;
-	
+
 	down_read(&current->mm->mmap_sem);
 	ret = get_user_pages(current, current->mm, (unsigned long)buf,
 			     nr_pages, WRITE, 0, pages, NULL);
@@ -700,7 +697,7 @@
 	}
 
 	dma_configure_channel(shdma, 0x12c1);
-	
+
 	dst   = (unsigned long)fb_info->screen_base + *ppos;
 	start = (unsigned long)page_address(pages[0]);
 	end   = (unsigned long)page_address(pages[nr_pages]);
@@ -744,7 +741,7 @@
 	kfree(pages);
 
 	return ret;
-} 
+}
 #endif /* CONFIG_SH_DMA */
 
 /**
@@ -765,21 +762,21 @@
  * in for flexibility anyways. Who knows, maybe someone has tv-out on a
  * PCI-based version of these things ;-)
  */
-static int __init pvr2fb_common_init(void)
+static int __devinit pvr2fb_common_init(void)
 {
 	struct pvr2fb_par *par = currentpar;
 	unsigned long modememused, rev;
 
 	fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start,
 					       pvr2_fix.smem_len);
-	
+
 	if (!fb_info->screen_base) {
 		printk(KERN_ERR "pvr2fb: Failed to remap smem space\n");
 		goto out_err;
 	}
 
 	par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start,
-					 		pvr2_fix.mmio_len);
+							pvr2_fix.mmio_len);
 	if (!par->mmio_base) {
 		printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n");
 		goto out_err;
@@ -820,7 +817,7 @@
 	printk("fb%d: %s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n",
 	       fb_info->node, fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f,
 	       modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10));
-	printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", 
+	printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
 	       fb_info->node, fb_info->var.xres, fb_info->var.yres,
 	       fb_info->var.bits_per_pixel,
 	       get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
@@ -878,8 +875,8 @@
 			video_output = VO_NTSC;
 		}
 	}
-	
-	/* 
+
+	/*
 	 * Nothing exciting about the DC PVR2 .. only a measly 8MiB.
 	 */
 	pvr2_fix.smem_start	= 0xa5000000;	/* RAM starts here */
@@ -903,7 +900,7 @@
 	return pvr2fb_common_init();
 }
 
-static void pvr2fb_dc_exit(void)
+static void __exit pvr2fb_dc_exit(void)
 {
 	if (fb_info->screen_base) {
 		iounmap(fb_info->screen_base);
@@ -987,13 +984,13 @@
 	return pci_register_driver(&pvr2fb_pci_driver);
 }
 
-static void pvr2fb_pci_exit(void)
+static void __exit pvr2fb_pci_exit(void)
 {
 	pci_unregister_driver(&pvr2fb_pci_driver);
 }
 #endif /* CONFIG_PCI */
 
-static int __init pvr2_get_param(const struct pvr2_params *p, const char *s,
+static int __devinit pvr2_get_param(const struct pvr2_params *p, const char *s,
                                    int val, int size)
 {
 	int i;
@@ -1021,7 +1018,7 @@
  */
 
 #ifndef MODULE
-int __init pvr2fb_setup(char *options)
+static int __init pvr2fb_setup(char *options)
 {
 	char *this_opt;
 	char cable_arg[80];
@@ -1061,7 +1058,7 @@
 	int (*init)(void);
 	void (*exit)(void);
 	char name[16];
-} board_list[] = {
+} board_driver[] = {
 #ifdef CONFIG_SH_DREAMCAST
 	{ pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" },
 #endif
@@ -1071,7 +1068,7 @@
 	{ 0, },
 };
 
-int __init pvr2fb_init(void)
+static int __init pvr2fb_init(void)
 {
 	int i, ret = -ENODEV;
 	int size;
@@ -1095,8 +1092,8 @@
 
 	currentpar = (struct pvr2fb_par *)(fb_info + 1);
 
-	for (i = 0; i < ARRAY_SIZE(board_list); i++) {
-		struct pvr2_board *pvr_board = board_list + i;
+	for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+		struct pvr2_board *pvr_board = board_driver + i;
 
 		if (!pvr_board->init)
 			continue;
@@ -1118,13 +1115,13 @@
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(board_list); i++) {
-		struct pvr2_board *pvr_board = board_list + i;
+	for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+		struct pvr2_board *pvr_board = board_driver + i;
 
 		if (pvr_board->exit)
 			pvr_board->exit();
 	}
-		
+
 #ifdef CONFIG_SH_STORE_QUEUES
 	sq_unmap(pvr2fb_map);
 #endif
@@ -1139,4 +1136,3 @@
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
 MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards");
 MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 48536c3..4beac1d 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -95,7 +95,7 @@
 	/* mapped in q40/config.c */
 	q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR;
 
-	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
 	if (!info)
 		return -ENOMEM;
 
diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
index 70bfd78..1330770 100644
--- a/drivers/video/riva/riva_hw.c
+++ b/drivers/video/riva/riva_hw.c
@@ -1223,6 +1223,8 @@
         }
     }
     }
+
+    /* non-zero: M/N/P/clock values assigned.  zero: error (not set) */
     return (DeltaOld != 0xFFFFFFFF);
 }
 /*
@@ -1240,7 +1242,10 @@
     int            dotClock
 )
 {
-    int pixelDepth, VClk, m, n, p;
+    int pixelDepth;
+    int uninitialized_var(VClk),uninitialized_var(m),
+        uninitialized_var(n),	uninitialized_var(p);
+
     /*
      * Save mode parameters.
      */
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index ebb6756..4fb1624 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -752,7 +752,7 @@
 	struct fb_info *info;
 	char *monitor;
 
-	info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
+	info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 16, &dev->dev);
 	if (!info)
 		return -ENOMEM;
 	par = info->par;
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index d5e2d9c..d53bf69 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -479,7 +479,7 @@
 	struct fb_var_screeninfo default_var;
 
 	struct fb_fix_screeninfo sisfb_fix;
-	u32		pseudo_palette[17];
+	u32		pseudo_palette[16];
 
 	struct sisfb_monitor {
 		u16 hmin;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index a30e1e1..e8ccace 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1405,12 +1405,18 @@
 		}
 		break;
 	case 16:
+		if (regno >= 16)
+			break;
+
 		((u32 *)(info->pseudo_palette))[regno] =
 				(red & 0xf800)          |
 				((green & 0xfc00) >> 5) |
 				((blue & 0xf800) >> 11);
 		break;
 	case 32:
+		if (regno >= 16)
+			break;
+
 		red >>= 8;
 		green >>= 8;
 		blue >>= 8;
@@ -5789,7 +5795,7 @@
 	ivideo->warncount = 0;
 	ivideo->chip_id = pdev->device;
 	ivideo->chip_vendor = pdev->vendor;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
+	ivideo->revision_id = pdev->revision;
 	ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
 	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
 	ivideo->sisvga_enabled = reg16 & 0x01;
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 836a612..64779e7 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -132,7 +132,6 @@
 static struct xxx_par __initdata current_par;
 
 int xxxfb_init(void);
-int xxxfb_setup(char*);
 
 /**
  *	xxxfb_open - Optional function. Called when the framebuffer is
@@ -975,6 +974,21 @@
 	.name = "xxxfb",
 };
 
+#ifndef MODULE
+    /*
+     *  Setup
+     */
+
+/*
+ * Only necessary if your driver takes special options,
+ * otherwise we fall back on the generic fb_setup().
+ */
+int __init xxxfb_setup(char *options)
+{
+    /* Parse user speficied options (`video=xxxfb:') */
+}
+#endif /* MODULE */
+
 static int __init xxxfb_init(void)
 {
 	int ret;
@@ -1006,21 +1020,6 @@
 }
 #endif /* CONFIG_PCI */
 
-#ifdef MODULE
-    /*
-     *  Setup
-     */
-
-/* 
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-int __init xxxfb_setup(char *options)
-{
-    /* Parse user speficied options (`video=xxxfb:') */
-}
-#endif /* MODULE */
-
 /* ------------------------------------------------------------------------- */
 
 
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 62fa550..5eff28ce 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1348,7 +1348,7 @@
 	f_ddprintk("found device : %s\n", spec->name);
 
 	par->dev = pdev;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &par->revision);
+	par->revision = pdev->revision;
 
 	fix->mmio_start = pci_resource_start(pdev,0);
 	fix->mmio_len	= 0x400000;
diff --git a/drivers/video/sunxvr2500.c b/drivers/video/sunxvr2500.c
index 4316c7f..c3869a9 100644
--- a/drivers/video/sunxvr2500.c
+++ b/drivers/video/sunxvr2500.c
@@ -28,7 +28,7 @@
 	unsigned int		depth;
 	unsigned int		fb_size;
 
-	u32			pseudo_palette[256];
+	u32			pseudo_palette[16];
 };
 
 static int __devinit s3d_get_props(struct s3d_info *sp)
@@ -52,15 +52,14 @@
 {
 	u32 value;
 
-	if (regno >= 256)
-		return 1;
+	if (regno < 16) {
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
 
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	value = (blue << 24) | (green << 16) | (red << 8);
-	((u32 *)info->pseudo_palette)[regno] = value;
+		value = (blue << 24) | (green << 16) | (red << 8);
+		((u32 *)info->pseudo_palette)[regno] = value;
+	}
 
 	return 0;
 }
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c
index 08880a6..71bf3f1 100644
--- a/drivers/video/sunxvr500.c
+++ b/drivers/video/sunxvr500.c
@@ -50,7 +50,7 @@
 	u32			fb8_0_off;
 	u32			fb8_1_off;
 
-	u32			pseudo_palette[256];
+	u32			pseudo_palette[16];
 };
 
 static int __devinit e3d_get_props(struct e3d_info *ep)
@@ -126,7 +126,9 @@
 	blue_8 = blue >> 8;
 
 	value = (blue_8 << 24) | (green_8 << 16) | (red_8 << 8);
-	((u32 *)info->pseudo_palette)[regno] = value;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16)
+		((u32 *)info->pseudo_palette)[regno] = value;
 
 
 	red_10 = red >> 6;
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index f0fde6e..89facb7 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1625,8 +1625,7 @@
 	par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
 	par->tga_type = tga_type;
 	if (tga_bus_pci)
-		pci_read_config_byte(to_pci_dev(dev), PCI_REVISION_ID,
-				     &par->tga_chip_rev);
+		par->tga_chip_rev = (to_pci_dev(dev))->revision;
 	if (tga_bus_tc)
 		par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;
 
@@ -1635,7 +1634,7 @@
 		      FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
 	info->fbops = &tgafb_ops;
 	info->screen_base = par->tga_fb_base;
-	info->pseudo_palette = (void *)(par + 1);
+	info->pseudo_palette = par->palette;
 
 	/* This should give a reasonable default video mode.  */
 	if (tga_bus_pci) {
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 55e8aa4..c699864 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -976,7 +976,7 @@
 		return 1;
 
 
-	if (bpp==8) {
+	if (bpp == 8) {
 		t_outb(0xFF,0x3C6);
 		t_outb(regno,0x3C8);
 
@@ -984,19 +984,21 @@
 		t_outb(green>>10,0x3C9);
 		t_outb(blue>>10,0x3C9);
 
-	} else if (bpp == 16) {	/* RGB 565 */
-		u32 col;
+	} else if (regno < 16) {
+		if (bpp == 16) {	/* RGB 565 */
+			u32 col;
 
-		col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
-			((blue & 0xF800) >> 11);
-		col |= col << 16;	
-		((u32 *)(info->pseudo_palette))[regno] = col;
-	} else if (bpp == 32)		/* ARGB 8888 */
-		((u32*)info->pseudo_palette)[regno] =
-			((transp & 0xFF00) <<16) 	|
-			((red & 0xFF00) << 8) 		|
-			((green & 0xFF00))		|
-			((blue & 0xFF00)>>8);
+			col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
+				((blue & 0xF800) >> 11);
+			col |= col << 16;
+			((u32 *)(info->pseudo_palette))[regno] = col;
+		} else if (bpp == 32)		/* ARGB 8888 */
+			((u32*)info->pseudo_palette)[regno] =
+				((transp & 0xFF00) <<16) 	|
+				((red & 0xFF00) << 8) 		|
+				((green & 0xFF00))		|
+				((blue & 0xFF00)>>8);
+	}
 
 //	debug("exit\n");
 	return 0;
diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c
index 07389ba..e6f7c78 100644
--- a/drivers/video/tx3912fb.c
+++ b/drivers/video/tx3912fb.c
@@ -291,7 +291,7 @@
 	fb_info.fbops = &tx3912fb_ops;
 	fb_info.var = tx3912fb_var;
 	fb_info.fix = tx3912fb_fix;
-	fb_info.pseudo_palette = pseudo_palette;
+	fb_info.pseudo_palette = cfb8;
 	fb_info.flags = FBINFO_DEFAULT;
 
 	/* Clear the framebuffer */
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index 5e9755e..4c3a633 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -68,26 +68,26 @@
 
 /* CRT timing register sets */
 
-struct vga_regset vt8623_h_total_regs[]       = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
-struct vga_regset vt8623_h_display_regs[]     = {{0x01, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_h_blank_end_regs[]   = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
-struct vga_regset vt8623_h_sync_start_regs[]  = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
-struct vga_regset vt8623_h_sync_end_regs[]    = {{0x05, 0, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_total_regs[]       = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_display_regs[]     = {{0x01, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_blank_end_regs[]   = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_sync_start_regs[]  = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_sync_end_regs[]    = {{0x05, 0, 4}, VGA_REGSET_END};
 
-struct vga_regset vt8623_v_total_regs[]       = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
-struct vga_regset vt8623_v_display_regs[]     = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
-struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
-struct vga_regset vt8623_v_blank_end_regs[]   = {{0x16, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
-struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_total_regs[]       = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_display_regs[]     = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_blank_end_regs[]   = {{0x16, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
 
-struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
-struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
-struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
 
-struct svga_timing_regs vt8623_timing_regs     = {
+static struct svga_timing_regs vt8623_timing_regs     = {
 	vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs,
 	vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs,
 	vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs,
@@ -778,9 +778,10 @@
 static void __devexit vt8623_pci_remove(struct pci_dev *dev)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
-	struct vt8623fb_info *par = info->par;
 
 	if (info) {
+		struct vt8623fb_info *par = info->par;
+
 #ifdef CONFIG_MTRR
 		if (par->mtrr_reg >= 0) {
 			mtrr_del(par->mtrr_reg, 0, 0);
@@ -902,7 +903,7 @@
 
 /* Driver Initialisation */
 
-int __init vt8623fb_init(void)
+static int __init vt8623fb_init(void)
 {
 
 #ifndef MODULE
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 5fc86ea..003c49a 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -660,7 +660,7 @@
 			err = -ENODEV;
 			goto out;
 	}
-	printk(" at 0x%08lx.\n", mem->start+W100_CFG_BASE);
+	printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
 
 	/* Remap the framebuffer */
 	remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
@@ -753,10 +753,14 @@
 		goto out;
 	}
 
-	device_create_file(&pdev->dev, &dev_attr_fastpllclk);
-	device_create_file(&pdev->dev, &dev_attr_reg_read);
-	device_create_file(&pdev->dev, &dev_attr_reg_write);
-	device_create_file(&pdev->dev, &dev_attr_flip);
+	err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
+	err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
+	err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
+	err |= device_create_file(&pdev->dev, &dev_attr_flip);
+
+	if (err != 0)
+		printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
+				info->node, err);
 
 	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
 	return 0;
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index ca75b3a..6854fd6 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -1,8 +1,6 @@
-menu "Dallas's 1-wire bus"
-	depends on HAS_IOMEM
-
-config W1
+menuconfig W1
 	tristate "Dallas's 1-wire support"
+	depends on HAS_IOMEM
 	---help---
 	  Dallas' 1-wire bus is useful to connect slow 1-pin devices
 	  such as iButtons and thermal sensors.
@@ -12,8 +10,10 @@
 	  This W1 support can also be built as a module.  If so, the module
 	  will be called wire.ko.
 
+if W1
+
 config W1_CON
-	depends on CONNECTOR && W1
+	depends on CONNECTOR
 	bool "Userspace communication over connector"
 	default y
 	--- help ---
@@ -27,4 +27,4 @@
 source drivers/w1/masters/Kconfig
 source drivers/w1/slaves/Kconfig
 
-endmenu
+endif # W1
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 8f77933..8236d44 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -3,11 +3,10 @@
 #
 
 menu "1-wire Bus Masters"
-	depends on W1
 
 config W1_MASTER_MATROX
 	tristate "Matrox G400 transport layer for 1-wire"
-	depends on W1 && PCI
+	depends on PCI
 	help
 	  Say Y here if you want to communicate with your 1-wire devices
 	  using Matrox's G400 GPIO pins.
@@ -17,7 +16,7 @@
 
 config W1_MASTER_DS2490
 	tristate "DS2490 USB <-> W1 transport layer for 1-wire"
-  	depends on W1 && USB
+  	depends on USB
   	help
 	  Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges,
 	  for example DS9490*.
@@ -27,7 +26,7 @@
 
 config W1_MASTER_DS2482
 	tristate "Maxim DS2482 I2C to 1-Wire bridge"
-	depends on I2C && W1 && EXPERIMENTAL
+	depends on I2C && EXPERIMENTAL
 	help
 	  If you say yes here you get support for the Maxim DS2482
 	  I2C to 1-Wire bridge.
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 904e5ae..3df29a1 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -3,25 +3,21 @@
 #
 
 menu "1-wire Slaves"
-	depends on W1
 
 config W1_SLAVE_THERM
 	tristate "Thermal family implementation"
-	depends on W1
 	help
 	  Say Y here if you want to connect 1-wire thermal sensors to your
 	  wire.
 
 config W1_SLAVE_SMEM
 	tristate "Simple 64bit memory family implementation"
-	depends on W1
 	help
 	  Say Y here if you want to connect 1-wire
 	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
 
 config W1_SLAVE_DS2433
 	tristate "4kb EEPROM family support (DS2433)"
-	depends on W1
 	help
 	  Say Y here if you want to use a 1-wire
 	  4kb EEPROM family device (DS2433).
@@ -35,4 +31,17 @@
 	  Each block has 30 bytes of data and a two byte CRC16.
 	  Full block writes are only allowed if the CRC is valid.
 
+config W1_SLAVE_DS2760
+	tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
+	depends on W1
+	help
+	  If you enable this you will have the DS2760 battery monitor
+	  chip support.
+
+	  The battery monitor chip is used in many batteries/devices
+	  as the one who is responsible for charging/discharging/monitoring
+	  Li+ batteries.
+
+	  If you are unsure, say N.
+
 endmenu
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index 725dcfd..a8eb752 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -5,4 +5,5 @@
 obj-$(CONFIG_W1_SLAVE_THERM)	+= w1_therm.o
 obj-$(CONFIG_W1_SLAVE_SMEM)	+= w1_smem.o
 obj-$(CONFIG_W1_SLAVE_DS2433)	+= w1_ds2433.o
+obj-$(CONFIG_W1_SLAVE_DS2760)	+= w1_ds2760.o
 
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index 8ea17a5..cab5600 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -91,8 +91,9 @@
 }
 #endif	/* CONFIG_W1_SLAVE_DS2433_CRC */
 
-static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
-			       size_t count)
+static ssize_t w1_f23_read_bin(struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 #ifdef CONFIG_W1_SLAVE_DS2433_CRC
@@ -199,8 +200,9 @@
 	return 0;
 }
 
-static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
-				size_t count)
+static ssize_t w1_f23_write_bin(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	int addr, len, idx;
@@ -252,7 +254,6 @@
 	.attr = {
 		.name = "eeprom",
 		.mode = S_IRUGO | S_IWUSR,
-		.owner = THIS_MODULE,
 	},
 	.size = W1_EEPROM_SIZE,
 	.read = w1_f23_read_bin,
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
new file mode 100644
index 0000000..ed6b057
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -0,0 +1,210 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/idr.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+#include "w1_ds2760.h"
+
+static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
+			int io)
+{
+	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+	if (!dev)
+		return 0;
+
+	mutex_lock(&sl->master->mutex);
+
+	if (addr > DS2760_DATA_SIZE || addr < 0) {
+		count = 0;
+		goto out;
+	}
+	if (addr + count > DS2760_DATA_SIZE)
+		count = DS2760_DATA_SIZE - addr;
+
+	if (!w1_reset_select_slave(sl)) {
+		if (!io) {
+			w1_write_8(sl->master, W1_DS2760_READ_DATA);
+			w1_write_8(sl->master, addr);
+			count = w1_read_block(sl->master, buf, count);
+		} else {
+			w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
+			w1_write_8(sl->master, addr);
+			w1_write_block(sl->master, buf, count);
+			/* XXX w1_write_block returns void, not n_written */
+		}
+	}
+
+out:
+	mutex_unlock(&sl->master->mutex);
+
+	return count;
+}
+
+int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count)
+{
+	return w1_ds2760_io(dev, buf, addr, count, 0);
+}
+
+int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count)
+{
+	return w1_ds2760_io(dev, buf, addr, count, 1);
+}
+
+static ssize_t w1_ds2760_read_bin(struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
+				  char *buf, loff_t off, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	return w1_ds2760_read(dev, buf, off, count);
+}
+
+static struct bin_attribute w1_ds2760_bin_attr = {
+	.attr = {
+		.name = "w1_slave",
+		.mode = S_IRUGO,
+		.owner = THIS_MODULE,
+	},
+	.size = DS2760_DATA_SIZE,
+	.read = w1_ds2760_read_bin,
+};
+
+static DEFINE_IDR(bat_idr);
+static DEFINE_MUTEX(bat_idr_lock);
+
+static int new_bat_id(void)
+{
+	int ret;
+
+	while (1) {
+		int id;
+
+		ret = idr_pre_get(&bat_idr, GFP_KERNEL);
+		if (ret == 0)
+			return -ENOMEM;
+
+		mutex_lock(&bat_idr_lock);
+		ret = idr_get_new(&bat_idr, NULL, &id);
+		mutex_unlock(&bat_idr_lock);
+
+		if (ret == 0) {
+			ret = id & MAX_ID_MASK;
+			break;
+		} else if (ret == -EAGAIN) {
+			continue;
+		} else {
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static void release_bat_id(int id)
+{
+	mutex_lock(&bat_idr_lock);
+	idr_remove(&bat_idr, id);
+	mutex_unlock(&bat_idr_lock);
+}
+
+static int w1_ds2760_add_slave(struct w1_slave *sl)
+{
+	int ret;
+	int id;
+	struct platform_device *pdev;
+
+	id = new_bat_id();
+	if (id < 0) {
+		ret = id;
+		goto noid;
+	}
+
+	pdev = platform_device_alloc("ds2760-battery", id);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto pdev_alloc_failed;
+	}
+	pdev->dev.parent = &sl->dev;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto pdev_add_failed;
+
+	ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+	if (ret)
+		goto bin_attr_failed;
+
+	dev_set_drvdata(&sl->dev, pdev);
+
+	goto success;
+
+bin_attr_failed:
+pdev_add_failed:
+	platform_device_unregister(pdev);
+pdev_alloc_failed:
+	release_bat_id(id);
+noid:
+success:
+	return ret;
+}
+
+static void w1_ds2760_remove_slave(struct w1_slave *sl)
+{
+	struct platform_device *pdev = dev_get_drvdata(&sl->dev);
+	int id = pdev->id;
+
+	platform_device_unregister(pdev);
+	release_bat_id(id);
+	sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+}
+
+static struct w1_family_ops w1_ds2760_fops = {
+	.add_slave    = w1_ds2760_add_slave,
+	.remove_slave = w1_ds2760_remove_slave,
+};
+
+static struct w1_family w1_ds2760_family = {
+	.fid = W1_FAMILY_DS2760,
+	.fops = &w1_ds2760_fops,
+};
+
+static int __init w1_ds2760_init(void)
+{
+	printk(KERN_INFO "1-Wire driver for the DS2760 battery monitor "
+	       " chip  - (c) 2004-2005, Szabolcs Gyurko\n");
+	idr_init(&bat_idr);
+	return w1_register_family(&w1_ds2760_family);
+}
+
+static void __exit w1_ds2760_exit(void)
+{
+	w1_unregister_family(&w1_ds2760_family);
+	idr_destroy(&bat_idr);
+}
+
+EXPORT_SYMBOL(w1_ds2760_read);
+EXPORT_SYMBOL(w1_ds2760_write);
+
+module_init(w1_ds2760_init);
+module_exit(w1_ds2760_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>");
+MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
diff --git a/drivers/w1/slaves/w1_ds2760.h b/drivers/w1/slaves/w1_ds2760.h
new file mode 100644
index 0000000..f130242
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.h
@@ -0,0 +1,50 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#ifndef __w1_ds2760_h__
+#define __w1_ds2760_h__
+
+/* Known commands to the DS2760 chip */
+#define W1_DS2760_SWAP			0xAA
+#define W1_DS2760_READ_DATA		0x69
+#define W1_DS2760_WRITE_DATA		0x6C
+#define W1_DS2760_COPY_DATA		0x48
+#define W1_DS2760_RECALL_DATA		0xB8
+#define W1_DS2760_LOCK			0x6A
+
+/* Number of valid register addresses */
+#define DS2760_DATA_SIZE		0x40
+
+#define DS2760_PROTECTION_REG		0x00
+#define DS2760_STATUS_REG		0x01
+#define DS2760_EEPROM_REG		0x07
+#define DS2760_SPECIAL_FEATURE_REG	0x08
+#define DS2760_VOLTAGE_MSB		0x0c
+#define DS2760_VOLTAGE_LSB		0x0d
+#define DS2760_CURRENT_MSB		0x0e
+#define DS2760_CURRENT_LSB		0x0f
+#define DS2760_CURRENT_ACCUM_MSB	0x10
+#define DS2760_CURRENT_ACCUM_LSB	0x11
+#define DS2760_TEMP_MSB			0x18
+#define DS2760_TEMP_LSB			0x19
+#define DS2760_EEPROM_BLOCK0		0x20
+#define DS2760_ACTIVE_FULL		0x20
+#define DS2760_EEPROM_BLOCK1		0x30
+#define DS2760_RATED_CAPACITY		0x32
+#define DS2760_CURRENT_OFFSET_BIAS	0x33
+#define DS2760_ACTIVE_EMPTY		0x3b
+
+extern int w1_ds2760_read(struct device *dev, char *buf, int addr,
+			  size_t count);
+extern int w1_ds2760_write(struct device *dev, char *buf, int addr,
+			   size_t count);
+
+#endif /* !__w1_ds2760_h__ */
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 732db47..4318935 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -42,13 +42,13 @@
 				{}
 			};
 
-static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
+static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *,
+				 char *, loff_t, size_t);
 
 static struct bin_attribute w1_therm_bin_attr = {
 	.attr = {
 		.name = "w1_slave",
 		.mode = S_IRUGO,
-		.owner = THIS_MODULE,
 	},
 	.size = W1_SLAVE_DATA_SIZE,
 	.read = w1_therm_read_bin,
@@ -159,7 +159,9 @@
 	return 0;
 }
 
-static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_therm_read_bin(struct kobject *kobj,
+				 struct bin_attribute *bin_attr,
+				 char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	struct w1_master *dev = sl->master;
@@ -191,11 +193,7 @@
 
 			w1_write_8(dev, W1_CONVERT_TEMP);
 
-			while (tm) {
-				tm = msleep_interruptible(tm);
-				if (signal_pending(current))
-					flush_signals(current);
-			}
+			msleep(tm);
 
 			if (!w1_reset_select_slave(sl)) {
 
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 7d6876d..c633210 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -105,7 +105,9 @@
 	return sprintf(buf, "%s\n", sl->name);
 }
 
-static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_slave_read_id(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
@@ -128,7 +130,6 @@
       .attr = {
               .name = "id",
               .mode = S_IRUGO,
-              .owner = THIS_MODULE,
       },
       .size = 8,
       .read = w1_slave_read_id,
@@ -136,7 +137,9 @@
 
 /* Default family */
 
-static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_default_write(struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
@@ -153,7 +156,9 @@
 	return count;
 }
 
-static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_default_read(struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
@@ -167,7 +172,6 @@
       .attr = {
               .name = "rw",
               .mode = S_IRUGO | S_IWUSR,
-              .owner = THIS_MODULE,
       },
       .size = PAGE_SIZE,
       .read = w1_default_read,
@@ -801,6 +805,7 @@
 	struct w1_master *dev, *n;
 	int have_to_wait = 0;
 
+	set_freezable();
 	while (!kthread_should_stop() || have_to_wait) {
 		have_to_wait = 0;
 
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 1e2ac40..ef1e1da 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -33,6 +33,7 @@
 #define W1_THERM_DS1822  	0x22
 #define W1_EEPROM_DS2433  	0x23
 #define W1_THERM_DS18B20 	0x28
+#define W1_FAMILY_DS2760	0x30
 
 #define MAXNAMELEN		32
 
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index c3ba0ec..9130f1c 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -49,8 +49,9 @@
 
 static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL);
 
-static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off,
-				 size_t count)
+static ssize_t zorro_read_config(struct kobject *kobj,
+				 struct bin_attribute *bin_attr,
+				 char *buf, loff_t off, size_t count)
 {
 	struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
 					   kobj));
@@ -78,7 +79,6 @@
 	.attr =	{
 		.name = "config",
 		.mode = S_IRUGO | S_IWUSR,
-		.owner = THIS_MODULE
 	},
 	.size = sizeof(struct ConfigDev),
 	.read = zorro_read_config,
diff --git a/fs/9p/9p.h b/fs/9p/9p.h
deleted file mode 100644
index 94e2f92..0000000
--- a/fs/9p/9p.h
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * linux/fs/9p/9p.h
- *
- * 9P protocol definitions.
- *
- *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-/* Message Types */
-enum {
-	TVERSION = 100,
-	RVERSION,
-	TAUTH = 102,
-	RAUTH,
-	TATTACH = 104,
-	RATTACH,
-	TERROR = 106,
-	RERROR,
-	TFLUSH = 108,
-	RFLUSH,
-	TWALK = 110,
-	RWALK,
-	TOPEN = 112,
-	ROPEN,
-	TCREATE = 114,
-	RCREATE,
-	TREAD = 116,
-	RREAD,
-	TWRITE = 118,
-	RWRITE,
-	TCLUNK = 120,
-	RCLUNK,
-	TREMOVE = 122,
-	RREMOVE,
-	TSTAT = 124,
-	RSTAT,
-	TWSTAT = 126,
-	RWSTAT,
-};
-
-/* modes */
-enum {
-	V9FS_OREAD = 0x00,
-	V9FS_OWRITE = 0x01,
-	V9FS_ORDWR = 0x02,
-	V9FS_OEXEC = 0x03,
-	V9FS_OEXCL = 0x04,
-	V9FS_OTRUNC = 0x10,
-	V9FS_OREXEC = 0x20,
-	V9FS_ORCLOSE = 0x40,
-	V9FS_OAPPEND = 0x80,
-};
-
-/* permissions */
-enum {
-	V9FS_DMDIR = 0x80000000,
-	V9FS_DMAPPEND = 0x40000000,
-	V9FS_DMEXCL = 0x20000000,
-	V9FS_DMMOUNT = 0x10000000,
-	V9FS_DMAUTH = 0x08000000,
-	V9FS_DMTMP = 0x04000000,
-	V9FS_DMSYMLINK = 0x02000000,
-	V9FS_DMLINK = 0x01000000,
-	/* 9P2000.u extensions */
-	V9FS_DMDEVICE = 0x00800000,
-	V9FS_DMNAMEDPIPE = 0x00200000,
-	V9FS_DMSOCKET = 0x00100000,
-	V9FS_DMSETUID = 0x00080000,
-	V9FS_DMSETGID = 0x00040000,
-};
-
-/* qid.types */
-enum {
-	V9FS_QTDIR = 0x80,
-	V9FS_QTAPPEND = 0x40,
-	V9FS_QTEXCL = 0x20,
-	V9FS_QTMOUNT = 0x10,
-	V9FS_QTAUTH = 0x08,
-	V9FS_QTTMP = 0x04,
-	V9FS_QTSYMLINK = 0x02,
-	V9FS_QTLINK = 0x01,
-	V9FS_QTFILE = 0x00,
-};
-
-#define V9FS_NOTAG	(u16)(~0)
-#define V9FS_NOFID	(u32)(~0)
-#define V9FS_MAXWELEM	16
-
-/* ample room for Twrite/Rread header (iounit) */
-#define V9FS_IOHDRSZ	24
-
-struct v9fs_str {
-	u16 len;
-	char *str;
-};
-
-/* qids are the unique ID for a file (like an inode */
-struct v9fs_qid {
-	u8 type;
-	u32 version;
-	u64 path;
-};
-
-/* Plan 9 file metadata (stat) structure */
-struct v9fs_stat {
-	u16 size;
-	u16 type;
-	u32 dev;
-	struct v9fs_qid qid;
-	u32 mode;
-	u32 atime;
-	u32 mtime;
-	u64 length;
-	struct v9fs_str name;
-	struct v9fs_str uid;
-	struct v9fs_str gid;
-	struct v9fs_str muid;
-	struct v9fs_str extension;	/* 9p2000.u extensions */
-	u32 n_uid;		/* 9p2000.u extensions */
-	u32 n_gid;		/* 9p2000.u extensions */
-	u32 n_muid;		/* 9p2000.u extensions */
-};
-
-/* file metadata (stat) structure used to create Twstat message
-   The is similar to v9fs_stat, but the strings don't point to
-   the same memory block and should be freed separately
-*/
-struct v9fs_wstat {
-	u16 size;
-	u16 type;
-	u32 dev;
-	struct v9fs_qid qid;
-	u32 mode;
-	u32 atime;
-	u32 mtime;
-	u64 length;
-	char *name;
-	char *uid;
-	char *gid;
-	char *muid;
-	char *extension;	/* 9p2000.u extensions */
-	u32 n_uid;		/* 9p2000.u extensions */
-	u32 n_gid;		/* 9p2000.u extensions */
-	u32 n_muid;		/* 9p2000.u extensions */
-};
-
-/* Structures for Protocol Operations */
-
-struct Tversion {
-	u32 msize;
-	struct v9fs_str version;
-};
-
-struct Rversion {
-	u32 msize;
-	struct v9fs_str version;
-};
-
-struct Tauth {
-	u32 afid;
-	struct v9fs_str uname;
-	struct v9fs_str aname;
-};
-
-struct Rauth {
-	struct v9fs_qid qid;
-};
-
-struct Rerror {
-	struct v9fs_str error;
-	u32 errno;		/* 9p2000.u extension */
-};
-
-struct Tflush {
-	u16 oldtag;
-};
-
-struct Rflush {
-};
-
-struct Tattach {
-	u32 fid;
-	u32 afid;
-	struct v9fs_str uname;
-	struct v9fs_str aname;
-};
-
-struct Rattach {
-	struct v9fs_qid qid;
-};
-
-struct Twalk {
-	u32 fid;
-	u32 newfid;
-	u16 nwname;
-	struct v9fs_str wnames[16];
-};
-
-struct Rwalk {
-	u16 nwqid;
-	struct v9fs_qid wqids[16];
-};
-
-struct Topen {
-	u32 fid;
-	u8 mode;
-};
-
-struct Ropen {
-	struct v9fs_qid qid;
-	u32 iounit;
-};
-
-struct Tcreate {
-	u32 fid;
-	struct v9fs_str name;
-	u32 perm;
-	u8 mode;
-	struct v9fs_str extension;
-};
-
-struct Rcreate {
-	struct v9fs_qid qid;
-	u32 iounit;
-};
-
-struct Tread {
-	u32 fid;
-	u64 offset;
-	u32 count;
-};
-
-struct Rread {
-	u32 count;
-	u8 *data;
-};
-
-struct Twrite {
-	u32 fid;
-	u64 offset;
-	u32 count;
-	u8 *data;
-};
-
-struct Rwrite {
-	u32 count;
-};
-
-struct Tclunk {
-	u32 fid;
-};
-
-struct Rclunk {
-};
-
-struct Tremove {
-	u32 fid;
-};
-
-struct Rremove {
-};
-
-struct Tstat {
-	u32 fid;
-};
-
-struct Rstat {
-	struct v9fs_stat stat;
-};
-
-struct Twstat {
-	u32 fid;
-	struct v9fs_stat stat;
-};
-
-struct Rwstat {
-};
-
-/*
-  * fcall is the primary packet structure
-  *
-  */
-
-struct v9fs_fcall {
-	u32 size;
-	u8 id;
-	u16 tag;
-	void *sdata;
-
-	union {
-		struct Tversion tversion;
-		struct Rversion rversion;
-		struct Tauth tauth;
-		struct Rauth rauth;
-		struct Rerror rerror;
-		struct Tflush tflush;
-		struct Rflush rflush;
-		struct Tattach tattach;
-		struct Rattach rattach;
-		struct Twalk twalk;
-		struct Rwalk rwalk;
-		struct Topen topen;
-		struct Ropen ropen;
-		struct Tcreate tcreate;
-		struct Rcreate rcreate;
-		struct Tread tread;
-		struct Rread rread;
-		struct Twrite twrite;
-		struct Rwrite rwrite;
-		struct Tclunk tclunk;
-		struct Rclunk rclunk;
-		struct Tremove tremove;
-		struct Rremove rremove;
-		struct Tstat tstat;
-		struct Rstat rstat;
-		struct Twstat twstat;
-		struct Rwstat rwstat;
-	} params;
-};
-
-#define PRINT_FCALL_ERROR(s, fcall) dprintk(DEBUG_ERROR, "%s: %.*s\n", s, \
-	fcall?fcall->params.rerror.error.len:0, \
-	fcall?fcall->params.rerror.error.str:"");
-
-int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
-		   char *version, struct v9fs_fcall **rcall);
-
-int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
-		  u32 fid, u32 afid, struct v9fs_fcall **rcall);
-
-int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid);
-
-int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid,
-		struct v9fs_fcall **rcall);
-
-int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
-		 struct v9fs_wstat *wstat, struct v9fs_fcall **rcall);
-
-int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
-		char *name, struct v9fs_fcall **rcall);
-
-int v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
-		struct v9fs_fcall **rcall);
-
-int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
-		  struct v9fs_fcall **rcall);
-
-int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
-	u32 perm, u8 mode, char *extension, struct v9fs_fcall **rcall);
-
-int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
-		u64 offset, u32 count, struct v9fs_fcall **rcall);
-
-int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
-		 u32 count, const char __user * data,
-		 struct v9fs_fcall **rcall);
-int v9fs_printfcall(char *, int, struct v9fs_fcall *, int);
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index 87897f8..bc7f0d1 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -1,18 +1,12 @@
 obj-$(CONFIG_9P_FS) := 9p.o
 
 9p-objs := \
-	trans_fd.o \
-	mux.o \
-	fcall.o \
-	conv.o \
 	vfs_super.o \
 	vfs_inode.o \
 	vfs_addr.o \
 	vfs_file.o \
 	vfs_dir.o \
 	vfs_dentry.o \
-	error.o \
 	v9fs.o \
 	fid.o \
-	fcprint.o
 
diff --git a/fs/9p/conv.c b/fs/9p/conv.c
deleted file mode 100644
index a3ed571..0000000
--- a/fs/9p/conv.c
+++ /dev/null
@@ -1,845 +0,0 @@
-/*
- * linux/fs/9p/conv.c
- *
- * 9P protocol conversion functions
- *
- *  Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net>
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/idr.h>
-#include <asm/uaccess.h>
-#include "debug.h"
-#include "v9fs.h"
-#include "9p.h"
-#include "conv.h"
-
-/*
- * Buffer to help with string parsing
- */
-struct cbuf {
-	unsigned char *sp;
-	unsigned char *p;
-	unsigned char *ep;
-};
-
-static inline void buf_init(struct cbuf *buf, void *data, int datalen)
-{
-	buf->sp = buf->p = data;
-	buf->ep = data + datalen;
-}
-
-static inline int buf_check_overflow(struct cbuf *buf)
-{
-	return buf->p > buf->ep;
-}
-
-static int buf_check_size(struct cbuf *buf, int len)
-{
-	if (buf->p + len > buf->ep) {
-		if (buf->p < buf->ep) {
-			eprintk(KERN_ERR, "buffer overflow: want %d has %d\n",
-				len, (int)(buf->ep - buf->p));
-			dump_stack();
-			buf->p = buf->ep + 1;
-		}
-
-		return 0;
-	}
-
-	return 1;
-}
-
-static void *buf_alloc(struct cbuf *buf, int len)
-{
-	void *ret = NULL;
-
-	if (buf_check_size(buf, len)) {
-		ret = buf->p;
-		buf->p += len;
-	}
-
-	return ret;
-}
-
-static void buf_put_int8(struct cbuf *buf, u8 val)
-{
-	if (buf_check_size(buf, 1)) {
-		buf->p[0] = val;
-		buf->p++;
-	}
-}
-
-static void buf_put_int16(struct cbuf *buf, u16 val)
-{
-	if (buf_check_size(buf, 2)) {
-		*(__le16 *) buf->p = cpu_to_le16(val);
-		buf->p += 2;
-	}
-}
-
-static void buf_put_int32(struct cbuf *buf, u32 val)
-{
-	if (buf_check_size(buf, 4)) {
-		*(__le32 *)buf->p = cpu_to_le32(val);
-		buf->p += 4;
-	}
-}
-
-static void buf_put_int64(struct cbuf *buf, u64 val)
-{
-	if (buf_check_size(buf, 8)) {
-		*(__le64 *)buf->p = cpu_to_le64(val);
-		buf->p += 8;
-	}
-}
-
-static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
-{
-	char *ret;
-
-	ret = NULL;
-	if (buf_check_size(buf, slen + 2)) {
-		buf_put_int16(buf, slen);
-		ret = buf->p;
-		memcpy(buf->p, s, slen);
-		buf->p += slen;
-	}
-
-	return ret;
-}
-
-static inline void buf_put_string(struct cbuf *buf, const char *s)
-{
-	buf_put_stringn(buf, s, strlen(s));
-}
-
-static u8 buf_get_int8(struct cbuf *buf)
-{
-	u8 ret = 0;
-
-	if (buf_check_size(buf, 1)) {
-		ret = buf->p[0];
-		buf->p++;
-	}
-
-	return ret;
-}
-
-static u16 buf_get_int16(struct cbuf *buf)
-{
-	u16 ret = 0;
-
-	if (buf_check_size(buf, 2)) {
-		ret = le16_to_cpu(*(__le16 *)buf->p);
-		buf->p += 2;
-	}
-
-	return ret;
-}
-
-static u32 buf_get_int32(struct cbuf *buf)
-{
-	u32 ret = 0;
-
-	if (buf_check_size(buf, 4)) {
-		ret = le32_to_cpu(*(__le32 *)buf->p);
-		buf->p += 4;
-	}
-
-	return ret;
-}
-
-static u64 buf_get_int64(struct cbuf *buf)
-{
-	u64 ret = 0;
-
-	if (buf_check_size(buf, 8)) {
-		ret = le64_to_cpu(*(__le64 *)buf->p);
-		buf->p += 8;
-	}
-
-	return ret;
-}
-
-static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
-{
-	vstr->len = buf_get_int16(buf);
-	if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
-		vstr->str = buf->p;
-		buf->p += vstr->len;
-	} else {
-		vstr->len = 0;
-		vstr->str = NULL;
-	}
-}
-
-static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid)
-{
-	qid->type = buf_get_int8(bufp);
-	qid->version = buf_get_int32(bufp);
-	qid->path = buf_get_int64(bufp);
-}
-
-/**
- * v9fs_size_wstat - calculate the size of a variable length stat struct
- * @stat: metadata (stat) structure
- * @extended: non-zero if 9P2000.u
- *
- */
-
-static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
-{
-	int size = 0;
-
-	if (wstat == NULL) {
-		eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n");
-		return 0;
-	}
-
-	size =			/* 2 + *//* size[2] */
-	    2 +			/* type[2] */
-	    4 +			/* dev[4] */
-	    1 +			/* qid.type[1] */
-	    4 +			/* qid.vers[4] */
-	    8 +			/* qid.path[8] */
-	    4 +			/* mode[4] */
-	    4 +			/* atime[4] */
-	    4 +			/* mtime[4] */
-	    8 +			/* length[8] */
-	    8;			/* minimum sum of string lengths */
-
-	if (wstat->name)
-		size += strlen(wstat->name);
-	if (wstat->uid)
-		size += strlen(wstat->uid);
-	if (wstat->gid)
-		size += strlen(wstat->gid);
-	if (wstat->muid)
-		size += strlen(wstat->muid);
-
-	if (extended) {
-		size += 4 +	/* n_uid[4] */
-		    4 +		/* n_gid[4] */
-		    4 +		/* n_muid[4] */
-		    2;		/* string length of extension[4] */
-		if (wstat->extension)
-			size += strlen(wstat->extension);
-	}
-
-	return size;
-}
-
-/**
- * buf_get_stat - safely decode a recieved metadata (stat) structure
- * @bufp: buffer to deserialize
- * @stat: metadata (stat) structure
- * @extended: non-zero if 9P2000.u
- *
- */
-
-static void
-buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
-{
-	stat->size = buf_get_int16(bufp);
-	stat->type = buf_get_int16(bufp);
-	stat->dev = buf_get_int32(bufp);
-	stat->qid.type = buf_get_int8(bufp);
-	stat->qid.version = buf_get_int32(bufp);
-	stat->qid.path = buf_get_int64(bufp);
-	stat->mode = buf_get_int32(bufp);
-	stat->atime = buf_get_int32(bufp);
-	stat->mtime = buf_get_int32(bufp);
-	stat->length = buf_get_int64(bufp);
-	buf_get_str(bufp, &stat->name);
-	buf_get_str(bufp, &stat->uid);
-	buf_get_str(bufp, &stat->gid);
-	buf_get_str(bufp, &stat->muid);
-
-	if (extended) {
-		buf_get_str(bufp, &stat->extension);
-		stat->n_uid = buf_get_int32(bufp);
-		stat->n_gid = buf_get_int32(bufp);
-		stat->n_muid = buf_get_int32(bufp);
-	}
-}
-
-/**
- * v9fs_deserialize_stat - decode a received metadata structure
- * @buf: buffer to deserialize
- * @buflen: length of received buffer
- * @stat: metadata structure to decode into
- * @extended: non-zero if 9P2000.u
- *
- * Note: stat will point to the buf region.
- */
-
-int
-v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
-		int extended)
-{
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-	unsigned char *p;
-
-	buf_init(bufp, buf, buflen);
-	p = bufp->p;
-	buf_get_stat(bufp, stat, extended);
-
-	if (buf_check_overflow(bufp))
-		return 0;
-	else
-		return bufp->p - p;
-}
-
-/**
- * deserialize_fcall - unmarshal a response
- * @buf: recieved buffer
- * @buflen: length of received buffer
- * @rcall: fcall structure to populate
- * @rcalllen: length of fcall structure to populate
- * @extended: non-zero if 9P2000.u
- *
- */
-
-int
-v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
-		       int extended)
-{
-
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-	int i = 0;
-
-	buf_init(bufp, buf, buflen);
-
-	rcall->size = buf_get_int32(bufp);
-	rcall->id = buf_get_int8(bufp);
-	rcall->tag = buf_get_int16(bufp);
-
-	dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id,
-		rcall->tag);
-
-	switch (rcall->id) {
-	default:
-		eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id);
-		return -EPROTO;
-	case RVERSION:
-		rcall->params.rversion.msize = buf_get_int32(bufp);
-		buf_get_str(bufp, &rcall->params.rversion.version);
-		break;
-	case RFLUSH:
-		break;
-	case RATTACH:
-		rcall->params.rattach.qid.type = buf_get_int8(bufp);
-		rcall->params.rattach.qid.version = buf_get_int32(bufp);
-		rcall->params.rattach.qid.path = buf_get_int64(bufp);
-		break;
-	case RWALK:
-		rcall->params.rwalk.nwqid = buf_get_int16(bufp);
-		if (rcall->params.rwalk.nwqid > V9FS_MAXWELEM) {
-			eprintk(KERN_ERR, "Rwalk with more than %d qids: %d\n",
-				V9FS_MAXWELEM, rcall->params.rwalk.nwqid);
-			return -EPROTO;
-		}
-
-		for (i = 0; i < rcall->params.rwalk.nwqid; i++)
-			buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]);
-		break;
-	case ROPEN:
-		buf_get_qid(bufp, &rcall->params.ropen.qid);
-		rcall->params.ropen.iounit = buf_get_int32(bufp);
-		break;
-	case RCREATE:
-		buf_get_qid(bufp, &rcall->params.rcreate.qid);
-		rcall->params.rcreate.iounit = buf_get_int32(bufp);
-		break;
-	case RREAD:
-		rcall->params.rread.count = buf_get_int32(bufp);
-		rcall->params.rread.data = bufp->p;
-		buf_check_size(bufp, rcall->params.rread.count);
-		break;
-	case RWRITE:
-		rcall->params.rwrite.count = buf_get_int32(bufp);
-		break;
-	case RCLUNK:
-		break;
-	case RREMOVE:
-		break;
-	case RSTAT:
-		buf_get_int16(bufp);
-		buf_get_stat(bufp, &rcall->params.rstat.stat, extended);
-		break;
-	case RWSTAT:
-		break;
-	case RERROR:
-		buf_get_str(bufp, &rcall->params.rerror.error);
-		if (extended)
-			rcall->params.rerror.errno = buf_get_int16(bufp);
-		break;
-	}
-
-	if (buf_check_overflow(bufp)) {
-		dprintk(DEBUG_ERROR, "buffer overflow\n");
-		return -EIO;
-	}
-
-	return bufp->p - bufp->sp;
-}
-
-static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p)
-{
-	*p = val;
-	buf_put_int8(bufp, val);
-}
-
-static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p)
-{
-	*p = val;
-	buf_put_int16(bufp, val);
-}
-
-static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p)
-{
-	*p = val;
-	buf_put_int32(bufp, val);
-}
-
-static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p)
-{
-	*p = val;
-	buf_put_int64(bufp, val);
-}
-
-static void
-v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
-{
-	int len;
-	char *s;
-
-	if (data)
-		len = strlen(data);
-	else
-		len = 0;
-
-	s = buf_put_stringn(bufp, data, len);
-	if (str) {
-		str->len = len;
-		str->str = s;
-	}
-}
-
-static int
-v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count,
-		   unsigned char **pdata)
-{
-	*pdata = buf_alloc(bufp, count);
-	return copy_from_user(*pdata, data, count);
-}
-
-static void
-v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat,
-	       struct v9fs_stat *stat, int statsz, int extended)
-{
-	v9fs_put_int16(bufp, statsz, &stat->size);
-	v9fs_put_int16(bufp, wstat->type, &stat->type);
-	v9fs_put_int32(bufp, wstat->dev, &stat->dev);
-	v9fs_put_int8(bufp, wstat->qid.type, &stat->qid.type);
-	v9fs_put_int32(bufp, wstat->qid.version, &stat->qid.version);
-	v9fs_put_int64(bufp, wstat->qid.path, &stat->qid.path);
-	v9fs_put_int32(bufp, wstat->mode, &stat->mode);
-	v9fs_put_int32(bufp, wstat->atime, &stat->atime);
-	v9fs_put_int32(bufp, wstat->mtime, &stat->mtime);
-	v9fs_put_int64(bufp, wstat->length, &stat->length);
-
-	v9fs_put_str(bufp, wstat->name, &stat->name);
-	v9fs_put_str(bufp, wstat->uid, &stat->uid);
-	v9fs_put_str(bufp, wstat->gid, &stat->gid);
-	v9fs_put_str(bufp, wstat->muid, &stat->muid);
-
-	if (extended) {
-		v9fs_put_str(bufp, wstat->extension, &stat->extension);
-		v9fs_put_int32(bufp, wstat->n_uid, &stat->n_uid);
-		v9fs_put_int32(bufp, wstat->n_gid, &stat->n_gid);
-		v9fs_put_int32(bufp, wstat->n_muid, &stat->n_muid);
-	}
-}
-
-static struct v9fs_fcall *
-v9fs_create_common(struct cbuf *bufp, u32 size, u8 id)
-{
-	struct v9fs_fcall *fc;
-
-	size += 4 + 1 + 2;	/* size[4] id[1] tag[2] */
-	fc = kmalloc(sizeof(struct v9fs_fcall) + size, GFP_KERNEL);
-	if (!fc)
-		return ERR_PTR(-ENOMEM);
-
-	fc->sdata = (char *)fc + sizeof(*fc);
-
-	buf_init(bufp, (char *)fc->sdata, size);
-	v9fs_put_int32(bufp, size, &fc->size);
-	v9fs_put_int8(bufp, id, &fc->id);
-	v9fs_put_int16(bufp, V9FS_NOTAG, &fc->tag);
-
-	return fc;
-}
-
-void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag)
-{
-	fc->tag = tag;
-	*(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
-}
-
-struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4 + 2 + strlen(version);	/* msize[4] version[s] */
-	fc = v9fs_create_common(bufp, size, TVERSION);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, msize, &fc->params.tversion.msize);
-	v9fs_put_str(bufp, version, &fc->params.tversion.version);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-#if 0
-struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4 + 2 + strlen(uname) + 2 + strlen(aname);	/* afid[4] uname[s] aname[s] */
-	fc = v9fs_create_common(bufp, size, TAUTH);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, afid, &fc->params.tauth.afid);
-	v9fs_put_str(bufp, uname, &fc->params.tauth.uname);
-	v9fs_put_str(bufp, aname, &fc->params.tauth.aname);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-#endif  /*  0  */
-
-struct v9fs_fcall *
-v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname);	/* fid[4] afid[4] uname[s] aname[s] */
-	fc = v9fs_create_common(bufp, size, TATTACH);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.tattach.fid);
-	v9fs_put_int32(bufp, afid, &fc->params.tattach.afid);
-	v9fs_put_str(bufp, uname, &fc->params.tattach.uname);
-	v9fs_put_str(bufp, aname, &fc->params.tattach.aname);
-
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_tflush(u16 oldtag)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 2;		/* oldtag[2] */
-	fc = v9fs_create_common(bufp, size, TFLUSH);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
-				     char **wnames)
-{
-	int i, size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	if (nwname > V9FS_MAXWELEM) {
-		dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM);
-		return NULL;
-	}
-
-	size = 4 + 4 + 2;	/* fid[4] newfid[4] nwname[2] ... */
-	for (i = 0; i < nwname; i++) {
-		size += 2 + strlen(wnames[i]);	/* wname[s] */
-	}
-
-	fc = v9fs_create_common(bufp, size, TWALK);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.twalk.fid);
-	v9fs_put_int32(bufp, newfid, &fc->params.twalk.newfid);
-	v9fs_put_int16(bufp, nwname, &fc->params.twalk.nwname);
-	for (i = 0; i < nwname; i++) {
-		v9fs_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
-	}
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4 + 1;		/* fid[4] mode[1] */
-	fc = v9fs_create_common(bufp, size, TOPEN);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.topen.fid);
-	v9fs_put_int8(bufp, mode, &fc->params.topen.mode);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
-	char *extension, int extended)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4 + 2 + strlen(name) + 4 + 1;	/* fid[4] name[s] perm[4] mode[1] */
-	if (extended) {
-		size += 2 +			/* extension[s] */
-		    (extension == NULL ? 0 : strlen(extension));
-	}
-
-	fc = v9fs_create_common(bufp, size, TCREATE);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid);
-	v9fs_put_str(bufp, name, &fc->params.tcreate.name);
-	v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm);
-	v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode);
-	if (extended)
-		v9fs_put_str(bufp, extension, &fc->params.tcreate.extension);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4 + 8 + 4;	/* fid[4] offset[8] count[4] */
-	fc = v9fs_create_common(bufp, size, TREAD);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.tread.fid);
-	v9fs_put_int64(bufp, offset, &fc->params.tread.offset);
-	v9fs_put_int32(bufp, count, &fc->params.tread.count);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
-				      const char __user * data)
-{
-	int size, err;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4 + 8 + 4 + count;	/* fid[4] offset[8] count[4] data[count] */
-	fc = v9fs_create_common(bufp, size, TWRITE);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.twrite.fid);
-	v9fs_put_int64(bufp, offset, &fc->params.twrite.offset);
-	v9fs_put_int32(bufp, count, &fc->params.twrite.count);
-	err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data);
-	if (err) {
-		kfree(fc);
-		fc = ERR_PTR(err);
-	}
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_tclunk(u32 fid)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4;		/* fid[4] */
-	fc = v9fs_create_common(bufp, size, TCLUNK);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_tremove(u32 fid)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4;		/* fid[4] */
-	fc = v9fs_create_common(bufp, size, TREMOVE);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.tremove.fid);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_tstat(u32 fid)
-{
-	int size;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	size = 4;		/* fid[4] */
-	fc = v9fs_create_common(bufp, size, TSTAT);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.tstat.fid);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
-
-struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
-				      int extended)
-{
-	int size, statsz;
-	struct v9fs_fcall *fc;
-	struct cbuf buffer;
-	struct cbuf *bufp = &buffer;
-
-	statsz = v9fs_size_wstat(wstat, extended);
-	size = 4 + 2 + 2 + statsz;	/* fid[4] stat[n] */
-	fc = v9fs_create_common(bufp, size, TWSTAT);
-	if (IS_ERR(fc))
-		goto error;
-
-	v9fs_put_int32(bufp, fid, &fc->params.twstat.fid);
-	buf_put_int16(bufp, statsz + 2);
-	v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended);
-
-	if (buf_check_overflow(bufp)) {
-		kfree(fc);
-		fc = ERR_PTR(-ENOMEM);
-	}
-      error:
-	return fc;
-}
diff --git a/fs/9p/conv.h b/fs/9p/conv.h
deleted file mode 100644
index dd5b6b1..0000000
--- a/fs/9p/conv.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * linux/fs/9p/conv.h
- *
- * 9P protocol conversion definitions.
- *
- *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
-	int extended);
-int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
-	int extended);
-
-void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag);
-
-struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version);
-struct v9fs_fcall *v9fs_create_tattach(u32 fid, u32 afid, char *uname,
-	char *aname);
-struct v9fs_fcall *v9fs_create_tflush(u16 oldtag);
-struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
-	char **wnames);
-struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode);
-struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
-	char *extension, int extended);
-struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count);
-struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
-	const char __user *data);
-struct v9fs_fcall *v9fs_create_tclunk(u32 fid);
-struct v9fs_fcall *v9fs_create_tremove(u32 fid);
-struct v9fs_fcall *v9fs_create_tstat(u32 fid);
-struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
-	int extended);
diff --git a/fs/9p/debug.h b/fs/9p/debug.h
deleted file mode 100644
index 4228c0b..0000000
--- a/fs/9p/debug.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  linux/fs/9p/debug.h - V9FS Debug Definitions
- *
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-#define DEBUG_ERROR		(1<<0)
-#define DEBUG_CURRENT		(1<<1)
-#define DEBUG_9P	        (1<<2)
-#define DEBUG_VFS	        (1<<3)
-#define DEBUG_CONV		(1<<4)
-#define DEBUG_MUX		(1<<5)
-#define DEBUG_TRANS		(1<<6)
-#define DEBUG_SLABS	      	(1<<7)
-#define DEBUG_FCALL		(1<<8)
-
-#define DEBUG_DUMP_PKT		0
-
-extern int v9fs_debug_level;
-
-#define dprintk(level, format, arg...) \
-do {  \
-	if((v9fs_debug_level & level)==level) \
-		printk(KERN_NOTICE "-- %s (%d): " \
-		format , __FUNCTION__, current->pid , ## arg); \
-} while(0)
-
-#define eprintk(level, format, arg...) \
-do { \
-	printk(level "v9fs: %s (%d): " \
-		format , __FUNCTION__, current->pid , ## arg); \
-} while(0)
-
-#if DEBUG_DUMP_PKT
-static inline void dump_data(const unsigned char *data, unsigned int datalen)
-{
-	int i, n;
-	char buf[5*8];
-
-	n = 0;
-	i = 0;
-	while (i < datalen) {
-		n += snprintf(buf+n, sizeof(buf)-n, "%02x", data[i++]);
-		if (i%4 == 0)
-			n += snprintf(buf+n, sizeof(buf)-n, " ");
-
-		if (i%16 == 0) {
-			dprintk(DEBUG_ERROR, "%s\n", buf);
-			n = 0;
-		}
-	}
-
-	dprintk(DEBUG_ERROR, "%s\n", buf);
-}
-#else				/* DEBUG_DUMP_PKT */
-static inline void dump_data(const unsigned char *data, unsigned int datalen)
-{
-
-}
-#endif				/* DEBUG_DUMP_PKT */
diff --git a/fs/9p/error.c b/fs/9p/error.c
deleted file mode 100644
index 0d7fa4e..0000000
--- a/fs/9p/error.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * linux/fs/9p/error.c
- *
- * Error string handling
- *
- * Plan 9 uses error strings, Unix uses error numbers.  These functions
- * try to help manage that and provide for dynamically adding error
- * mappings.
- *
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/list.h>
-#include <linux/jhash.h>
-
-#include "debug.h"
-#include "error.h"
-
-/**
- * v9fs_error_init - preload
- * @errstr: error string
- *
- */
-
-int v9fs_error_init(void)
-{
-	struct errormap *c;
-	int bucket;
-
-	/* initialize hash table */
-	for (bucket = 0; bucket < ERRHASHSZ; bucket++)
-		INIT_HLIST_HEAD(&hash_errmap[bucket]);
-
-	/* load initial error map into hash table */
-	for (c = errmap; c->name != NULL; c++) {
-		c->namelen = strlen(c->name);
-		bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
-		INIT_HLIST_NODE(&c->list);
-		hlist_add_head(&c->list, &hash_errmap[bucket]);
-	}
-
-	return 1;
-}
-
-/**
- * errstr2errno - convert error string to error number
- * @errstr: error string
- *
- */
-
-int v9fs_errstr2errno(char *errstr, int len)
-{
-	int errno = 0;
-	struct hlist_node *p = NULL;
-	struct errormap *c = NULL;
-	int bucket = jhash(errstr, len, 0) % ERRHASHSZ;
-
-	hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
-		if (c->namelen==len && !memcmp(c->name, errstr, len)) {
-			errno = c->val;
-			break;
-		}
-	}
-
-	if (errno == 0) {
-		/* TODO: if error isn't found, add it dynamically */
-		errstr[len] = 0;
-		printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
-		       errstr);
-		errno = 1;
-	}
-
-	return -errno;
-}
diff --git a/fs/9p/error.h b/fs/9p/error.h
deleted file mode 100644
index 5f3ca52..0000000
--- a/fs/9p/error.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * linux/fs/9p/error.h
- *
- * Huge Nasty Error Table
- *
- * Plan 9 uses error strings, Unix uses error numbers.  This table tries to
- * match UNIX strings and Plan 9 strings to unix error numbers.  It is used
- * to preload the dynamic error table which can also track user-specific error
- * strings.
- *
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-#include <linux/errno.h>
-#include <asm/errno.h>
-
-struct errormap {
-	char *name;
-	int val;
-
-	int namelen;
-	struct hlist_node list;
-};
-
-#define ERRHASHSZ		32
-static struct hlist_head hash_errmap[ERRHASHSZ];
-
-/* FixMe - reduce to a reasonable size */
-static struct errormap errmap[] = {
-	{"Operation not permitted", EPERM},
-	{"wstat prohibited", EPERM},
-	{"No such file or directory", ENOENT},
-	{"directory entry not found", ENOENT},
-	{"file not found", ENOENT},
-	{"Interrupted system call", EINTR},
-	{"Input/output error", EIO},
-	{"No such device or address", ENXIO},
-	{"Argument list too long", E2BIG},
-	{"Bad file descriptor", EBADF},
-	{"Resource temporarily unavailable", EAGAIN},
-	{"Cannot allocate memory", ENOMEM},
-	{"Permission denied", EACCES},
-	{"Bad address", EFAULT},
-	{"Block device required", ENOTBLK},
-	{"Device or resource busy", EBUSY},
-	{"File exists", EEXIST},
-	{"Invalid cross-device link", EXDEV},
-	{"No such device", ENODEV},
-	{"Not a directory", ENOTDIR},
-	{"Is a directory", EISDIR},
-	{"Invalid argument", EINVAL},
-	{"Too many open files in system", ENFILE},
-	{"Too many open files", EMFILE},
-	{"Text file busy", ETXTBSY},
-	{"File too large", EFBIG},
-	{"No space left on device", ENOSPC},
-	{"Illegal seek", ESPIPE},
-	{"Read-only file system", EROFS},
-	{"Too many links", EMLINK},
-	{"Broken pipe", EPIPE},
-	{"Numerical argument out of domain", EDOM},
-	{"Numerical result out of range", ERANGE},
-	{"Resource deadlock avoided", EDEADLK},
-	{"File name too long", ENAMETOOLONG},
-	{"No locks available", ENOLCK},
-	{"Function not implemented", ENOSYS},
-	{"Directory not empty", ENOTEMPTY},
-	{"Too many levels of symbolic links", ELOOP},
-	{"No message of desired type", ENOMSG},
-	{"Identifier removed", EIDRM},
-	{"No data available", ENODATA},
-	{"Machine is not on the network", ENONET},
-	{"Package not installed", ENOPKG},
-	{"Object is remote", EREMOTE},
-	{"Link has been severed", ENOLINK},
-	{"Communication error on send", ECOMM},
-	{"Protocol error", EPROTO},
-	{"Bad message", EBADMSG},
-	{"File descriptor in bad state", EBADFD},
-	{"Streams pipe error", ESTRPIPE},
-	{"Too many users", EUSERS},
-	{"Socket operation on non-socket", ENOTSOCK},
-	{"Message too long", EMSGSIZE},
-	{"Protocol not available", ENOPROTOOPT},
-	{"Protocol not supported", EPROTONOSUPPORT},
-	{"Socket type not supported", ESOCKTNOSUPPORT},
-	{"Operation not supported", EOPNOTSUPP},
-	{"Protocol family not supported", EPFNOSUPPORT},
-	{"Network is down", ENETDOWN},
-	{"Network is unreachable", ENETUNREACH},
-	{"Network dropped connection on reset", ENETRESET},
-	{"Software caused connection abort", ECONNABORTED},
-	{"Connection reset by peer", ECONNRESET},
-	{"No buffer space available", ENOBUFS},
-	{"Transport endpoint is already connected", EISCONN},
-	{"Transport endpoint is not connected", ENOTCONN},
-	{"Cannot send after transport endpoint shutdown", ESHUTDOWN},
-	{"Connection timed out", ETIMEDOUT},
-	{"Connection refused", ECONNREFUSED},
-	{"Host is down", EHOSTDOWN},
-	{"No route to host", EHOSTUNREACH},
-	{"Operation already in progress", EALREADY},
-	{"Operation now in progress", EINPROGRESS},
-	{"Is a named type file", EISNAM},
-	{"Remote I/O error", EREMOTEIO},
-	{"Disk quota exceeded", EDQUOT},
-/* errors from fossil, vacfs, and u9fs */
-	{"fid unknown or out of range", EBADF},
-	{"permission denied", EACCES},
-	{"file does not exist", ENOENT},
-	{"authentication failed", ECONNREFUSED},
-	{"bad offset in directory read", ESPIPE},
-	{"bad use of fid", EBADF},
-	{"wstat can't convert between files and directories", EPERM},
-	{"directory is not empty", ENOTEMPTY},
-	{"file exists", EEXIST},
-	{"file already exists", EEXIST},
-	{"file or directory already exists", EEXIST},
-	{"fid already in use", EBADF},
-	{"file in use", ETXTBSY},
-	{"i/o error", EIO},
-	{"file already open for I/O", ETXTBSY},
-	{"illegal mode", EINVAL},
-	{"illegal name", ENAMETOOLONG},
-	{"not a directory", ENOTDIR},
-	{"not a member of proposed group", EPERM},
-	{"not owner", EACCES},
-	{"only owner can change group in wstat", EACCES},
-	{"read only file system", EROFS},
-	{"no access to special file", EPERM},
-	{"i/o count too large", EIO},
-	{"unknown group", EINVAL},
-	{"unknown user", EINVAL},
-	{"bogus wstat buffer", EPROTO},
-	{"exclusive use file already open", EAGAIN},
-	{"corrupted directory entry", EIO},
-	{"corrupted file entry", EIO},
-	{"corrupted block label", EIO},
-	{"corrupted meta data", EIO},
-	{"illegal offset", EINVAL},
-	{"illegal path element", ENOENT},
-	{"root of file system is corrupted", EIO},
-	{"corrupted super block", EIO},
-	{"protocol botch", EPROTO},
-	{"file system is full", ENOSPC},
-	{"file is in use", EAGAIN},
-	{"directory entry is not allocated", ENOENT},
-	{"file is read only", EROFS},
-	{"file has been removed", EIDRM},
-	{"only support truncation to zero length", EPERM},
-	{"cannot remove root", EPERM},
-	{"file too big", EFBIG},
-	{"venti i/o error", EIO},
-	/* these are not errors */
-	{"u9fs rhostsauth: no authentication required", 0},
-	{"u9fs authnone: no authentication required", 0},
-	{NULL, -1}
-};
-
-extern int v9fs_error_init(void);
diff --git a/fs/9p/fcall.c b/fs/9p/fcall.c
deleted file mode 100644
index dc336a6..0000000
--- a/fs/9p/fcall.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- *  linux/fs/9p/fcall.c
- *
- *  This file contains functions to perform synchronous 9P calls
- *
- *  Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net>
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/idr.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "9p.h"
-#include "conv.h"
-#include "mux.h"
-
-/**
- * v9fs_t_version - negotiate protocol parameters with sever
- * @v9ses: 9P2000 session information
- * @msize: requested max size packet
- * @version: requested version.extension string
- * @fcall: pointer to response fcall pointer
- *
- */
-
-int
-v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
-	       char *version, struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc;
-
-	dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
-	tc = v9fs_create_tversion(msize, version);
-
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-/**
- * v9fs_t_attach - mount the server
- * @v9ses: 9P2000 session information
- * @uname: user name doing the attach
- * @aname: remote name being attached to
- * @fid: mount fid to attatch to root node
- * @afid: authentication fid (in this case result key)
- * @fcall: pointer to response fcall pointer
- *
- */
-
-int
-v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
-	      u32 fid, u32 afid, struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall* tc;
-
-	dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
-		aname, fid, afid);
-
-	tc = v9fs_create_tattach(fid, afid, uname, aname);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
-	struct v9fs_fcall *rc, int err)
-{
-	int fid, id;
-	struct v9fs_session_info *v9ses;
-
-	id = 0;
-	fid = tc->params.tclunk.fid;
-	if (rc)
-		id = rc->id;
-
-	kfree(tc);
-	kfree(rc);
-	if (id == RCLUNK) {
-		v9ses = a;
-		v9fs_put_idpool(fid, &v9ses->fidpool);
-	}
-}
-
-/**
- * v9fs_t_clunk - release a fid (finish a transaction)
- * @v9ses: 9P2000 session information
- * @fid: fid to release
- * @fcall: pointer to response fcall pointer
- *
- */
-
-int
-v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
-{
-	int ret;
-	struct v9fs_fcall *tc, *rc;
-
-	dprintk(DEBUG_9P, "fid %d\n", fid);
-
-	rc = NULL;
-	tc = v9fs_create_tclunk(fid);
-	if (!IS_ERR(tc))
-		ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
-	else
-		ret = PTR_ERR(tc);
-
-	if (ret)
-		dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret);
-
-	v9fs_t_clunk_cb(v9ses, tc, rc, ret);
-	return ret;
-}
-
-#if 0
-/**
- * v9fs_v9fs_t_flush - flush a pending transaction
- * @v9ses: 9P2000 session information
- * @tag: tag to release
- *
- */
-int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
-{
-	int ret;
-	struct v9fs_fcall *tc;
-
-	dprintk(DEBUG_9P, "oldtag %d\n", oldtag);
-
-	tc = v9fs_create_tflush(oldtag);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, NULL);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-#endif
-
-/**
- * v9fs_t_stat - read a file's meta-data
- * @v9ses: 9P2000 session information
- * @fid: fid pointing to file or directory to get info about
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc;
-
-	dprintk(DEBUG_9P, "fid %d\n", fid);
-
-	ret = -ENOMEM;
-	tc = v9fs_create_tstat(fid);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-/**
- * v9fs_t_wstat - write a file's meta-data
- * @v9ses: 9P2000 session information
- * @fid: fid pointing to file or directory to write info about
- * @stat: metadata
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
-	     struct v9fs_wstat *wstat, struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc;
-
-	dprintk(DEBUG_9P, "fid %d\n", fid);
-
-	tc = v9fs_create_twstat(fid, wstat, v9ses->extended);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-/**
- * v9fs_t_walk - walk a fid to a new file or directory
- * @v9ses: 9P2000 session information
- * @fid: fid to walk
- * @newfid: new fid (for clone operations)
- * @name: path to walk fid to
- * @fcall: pointer to response fcall
- *
- */
-
-/* TODO: support multiple walk */
-
-int
-v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
-	    char *name, struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc;
-	int nwname;
-
-	dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);
-
-	if (name)
-		nwname = 1;
-	else
-		nwname = 0;
-
-	tc = v9fs_create_twalk(fid, newfid, nwname, &name);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-/**
- * v9fs_t_open - open a file
- *
- * @v9ses - 9P2000 session information
- * @fid - fid to open
- * @mode - mode to open file (R, RW, etc)
- * @fcall - pointer to response fcall
- *
- */
-
-int
-v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
-	    struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc;
-
-	dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
-
-	tc = v9fs_create_topen(fid, mode);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-/**
- * v9fs_t_remove - remove a file or directory
- * @v9ses: 9P2000 session information
- * @fid: fid to remove
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
-	      struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc;
-
-	dprintk(DEBUG_9P, "fid %d\n", fid);
-
-	tc = v9fs_create_tremove(fid);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-/**
- * v9fs_t_create - create a file or directory
- * @v9ses: 9P2000 session information
- * @fid: fid to create
- * @name: name of the file or directory to create
- * @perm: permissions to create with
- * @mode: mode to open file (R, RW, etc)
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, u32 perm,
-	u8 mode, char *extension, struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc;
-
-	dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
-		fid, name, perm, mode);
-
-	tc = v9fs_create_tcreate(fid, name, perm, mode, extension,
-		v9ses->extended);
-
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-/**
- * v9fs_t_read - read data
- * @v9ses: 9P2000 session information
- * @fid: fid to read from
- * @offset: offset to start read at
- * @count: how many bytes to read
- * @fcall: pointer to response fcall (with data)
- *
- */
-
-int
-v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
-	    u32 count, struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc, *rc;
-
-	dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
-		(long long unsigned) offset, count);
-
-	tc = v9fs_create_tread(fid, offset, count);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
-		if (!ret)
-			ret = rc->params.rread.count;
-		if (rcp)
-			*rcp = rc;
-		else
-			kfree(rc);
-
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
-/**
- * v9fs_t_write - write data
- * @v9ses: 9P2000 session information
- * @fid: fid to write to
- * @offset: offset to start write at
- * @count: how many bytes to write
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count,
-	const char __user *data, struct v9fs_fcall **rcp)
-{
-	int ret;
-	struct v9fs_fcall *tc, *rc;
-
-	dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
-		(long long unsigned) offset, count);
-
-	tc = v9fs_create_twrite(fid, offset, count, data);
-	if (!IS_ERR(tc)) {
-		ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
-
-		if (!ret)
-			ret = rc->params.rwrite.count;
-		if (rcp)
-			*rcp = rc;
-		else
-			kfree(rc);
-
-		kfree(tc);
-	} else
-		ret = PTR_ERR(tc);
-
-	return ret;
-}
-
diff --git a/fs/9p/fcprint.c b/fs/9p/fcprint.c
deleted file mode 100644
index 34b9611..0000000
--- a/fs/9p/fcprint.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- *  linux/fs/9p/fcprint.c
- *
- *  Print 9P call.
- *
- *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/idr.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "9p.h"
-#include "mux.h"
-
-static int
-v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q)
-{
-	int n;
-	char b[10];
-
-	n = 0;
-	if (q->type & V9FS_QTDIR)
-		b[n++] = 'd';
-	if (q->type & V9FS_QTAPPEND)
-		b[n++] = 'a';
-	if (q->type & V9FS_QTAUTH)
-		b[n++] = 'A';
-	if (q->type & V9FS_QTEXCL)
-		b[n++] = 'l';
-	if (q->type & V9FS_QTTMP)
-		b[n++] = 't';
-	if (q->type & V9FS_QTSYMLINK)
-		b[n++] = 'L';
-	b[n] = '\0';
-
-	return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path,
-		q->version, b);
-}
-
-static int
-v9fs_printperm(char *buf, int buflen, int perm)
-{
-	int n;
-	char b[15];
-
-	n = 0;
-	if (perm & V9FS_DMDIR)
-		b[n++] = 'd';
-	if (perm & V9FS_DMAPPEND)
-		b[n++] = 'a';
-	if (perm & V9FS_DMAUTH)
-		b[n++] = 'A';
-	if (perm & V9FS_DMEXCL)
-		b[n++] = 'l';
-	if (perm & V9FS_DMTMP)
-		b[n++] = 't';
-	if (perm & V9FS_DMDEVICE)
-		b[n++] = 'D';
-	if (perm & V9FS_DMSOCKET)
-		b[n++] = 'S';
-	if (perm & V9FS_DMNAMEDPIPE)
-		b[n++] = 'P';
-	if (perm & V9FS_DMSYMLINK)
-		b[n++] = 'L';
-	b[n] = '\0';
-
-	return scnprintf(buf, buflen, "%s%03o", b, perm&077);
-}
-
-static int
-v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended)
-{
-	int n;
-
-	n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len,
-		st->name.str, st->uid.len, st->uid.str);
-	if (extended)
-		n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid);
-
-	n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str);
-	if (extended)
-		n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid);
-
-	n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str);
-	if (extended)
-		n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid);
-
-	n += scnprintf(buf+n, buflen-n, " q ");
-	n += v9fs_printqid(buf+n, buflen-n, &st->qid);
-	n += scnprintf(buf+n, buflen-n, " m ");
-	n += v9fs_printperm(buf+n, buflen-n, st->mode);
-	n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld",
-		st->atime, st->mtime, (long long int) st->length);
-
-	if (extended)
-		n += scnprintf(buf+n, buflen-n, " ext '%.*s'",
-			st->extension.len, st->extension.str);
-
-	return n;
-}
-
-static int
-v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen)
-{
-	int i, n;
-
-	i = n = 0;
-	while (i < datalen) {
-		n += scnprintf(buf + n, buflen - n, "%02x", data[i]);
-		if (i%4 == 3)
-			n += scnprintf(buf + n, buflen - n, " ");
-		if (i%32 == 31)
-			n += scnprintf(buf + n, buflen - n, "\n");
-
-		i++;
-	}
-	n += scnprintf(buf + n, buflen - n, "\n");
-
-	return n;
-}
-
-static int
-v9fs_printdata(char *buf, int buflen, u8 *data, int datalen)
-{
-	return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16);
-}
-
-int
-v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
-{
-	int i, ret, type, tag;
-
-	if (!fc)
-		return scnprintf(buf, buflen, "<NULL>");
-
-	type = fc->id;
-	tag = fc->tag;
-
-	ret = 0;
-	switch (type) {
-	case TVERSION:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Tversion tag %u msize %u version '%.*s'", tag,
-			fc->params.tversion.msize, fc->params.tversion.version.len,
-			fc->params.tversion.version.str);
-		break;
-
-	case RVERSION:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Rversion tag %u msize %u version '%.*s'", tag,
-			fc->params.rversion.msize, fc->params.rversion.version.len,
-			fc->params.rversion.version.str);
-		break;
-
-	case TAUTH:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag,
-			fc->params.tauth.afid, fc->params.tauth.uname.len,
-			fc->params.tauth.uname.str, fc->params.tauth.aname.len,
-			fc->params.tauth.aname.str);
-		break;
-
-	case RAUTH:
-		ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag);
-		v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid);
-		break;
-
-	case TATTACH:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'",
-			tag, fc->params.tattach.fid, fc->params.tattach.afid,
-			fc->params.tattach.uname.len, fc->params.tattach.uname.str,
-			fc->params.tattach.aname.len, fc->params.tattach.aname.str);
-		break;
-
-	case RATTACH:
-		ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag);
-		v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid);
-		break;
-
-	case RERROR:
-		ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'",
-			tag, fc->params.rerror.error.len,
-			fc->params.rerror.error.str);
-		if (extended)
-			ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n",
-				fc->params.rerror.errno);
-		break;
-
-	case TFLUSH:
-		ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u",
-			tag, fc->params.tflush.oldtag);
-		break;
-
-	case RFLUSH:
-		ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag);
-		break;
-
-	case TWALK:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Twalk tag %u fid %d newfid %d nwname %d", tag,
-			fc->params.twalk.fid, fc->params.twalk.newfid,
-			fc->params.twalk.nwname);
-		for(i = 0; i < fc->params.twalk.nwname; i++)
-			ret += scnprintf(buf+ret, buflen-ret," '%.*s'",
-				fc->params.twalk.wnames[i].len,
-				fc->params.twalk.wnames[i].str);
-		break;
-
-	case RWALK:
-		ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d",
-			tag, fc->params.rwalk.nwqid);
-		for(i = 0; i < fc->params.rwalk.nwqid; i++)
-			ret += v9fs_printqid(buf+ret, buflen-ret,
-				&fc->params.rwalk.wqids[i]);
-		break;
-
-	case TOPEN:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Topen tag %u fid %d mode %d", tag,
-			fc->params.topen.fid, fc->params.topen.mode);
-		break;
-
-	case ROPEN:
-		ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag);
-		ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid);
-		ret += scnprintf(buf+ret, buflen-ret," iounit %d",
-			fc->params.ropen.iounit);
-		break;
-
-	case TCREATE:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Tcreate tag %u fid %d name '%.*s' perm ", tag,
-			fc->params.tcreate.fid, fc->params.tcreate.name.len,
-			fc->params.tcreate.name.str);
-
-		ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm);
-		ret += scnprintf(buf+ret, buflen-ret, " mode %d",
-			fc->params.tcreate.mode);
-		break;
-
-	case RCREATE:
-		ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag);
-		ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid);
-		ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
-			fc->params.rcreate.iounit);
-		break;
-
-	case TREAD:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Tread tag %u fid %d offset %lld count %u", tag,
-			fc->params.tread.fid,
-			(long long int) fc->params.tread.offset,
-			fc->params.tread.count);
-		break;
-
-	case RREAD:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Rread tag %u count %u data ", tag,
-			fc->params.rread.count);
-		ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data,
-			fc->params.rread.count);
-		break;
-
-	case TWRITE:
-		ret += scnprintf(buf+ret, buflen-ret,
-			"Twrite tag %u fid %d offset %lld count %u data ",
-			tag, fc->params.twrite.fid,
-			(long long int) fc->params.twrite.offset,
-			fc->params.twrite.count);
-		ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data,
-			fc->params.twrite.count);
-		break;
-
-	case RWRITE:
-		ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u",
-			tag, fc->params.rwrite.count);
-		break;
-
-	case TCLUNK:
-		ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d",
-			tag, fc->params.tclunk.fid);
-		break;
-
-	case RCLUNK:
-		ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag);
-		break;
-
-	case TREMOVE:
-		ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d",
-			tag, fc->params.tremove.fid);
-		break;
-
-	case RREMOVE:
-		ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag);
-		break;
-
-	case TSTAT:
-		ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d",
-			tag, fc->params.tstat.fid);
-		break;
-
-	case RSTAT:
-		ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag);
-		ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat,
-			extended);
-		break;
-
-	case TWSTAT:
-		ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ",
-			tag, fc->params.twstat.fid);
-		ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat,
-			extended);
-		break;
-
-	case RWSTAT:
-		ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag);
-		break;
-
-	default:
-		ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type);
-		break;
-	}
-
-	return ret;
-}
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 9041971..08fa320 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -26,10 +26,10 @@
 #include <linux/sched.h>
 #include <linux/idr.h>
 #include <asm/semaphore.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
 
-#include "debug.h"
 #include "v9fs.h"
-#include "9p.h"
 #include "v9fs_vfs.h"
 #include "fid.h"
 
@@ -40,70 +40,32 @@
  *
  */
 
-int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
+int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
 {
-	struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
-	dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid,
-		dentry->d_iname, dentry);
-	if (dentry->d_fsdata == NULL) {
-		dentry->d_fsdata =
-		    kmalloc(sizeof(struct list_head), GFP_KERNEL);
-		if (dentry->d_fsdata == NULL) {
-			dprintk(DEBUG_ERROR, "Out of memory\n");
+	struct v9fs_dentry *dent;
+
+	P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n",
+					fid->fid, dentry->d_iname);
+
+	dent = dentry->d_fsdata;
+	if (!dent) {
+		dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL);
+		if (!dent)
 			return -ENOMEM;
-		}
-		fid_list = (struct list_head *)dentry->d_fsdata;
-		INIT_LIST_HEAD(fid_list);	/* Initialize list head */
+
+		spin_lock_init(&dent->lock);
+		INIT_LIST_HEAD(&dent->fidlist);
+		dentry->d_fsdata = dent;
 	}
 
-	fid->uid = current->uid;
-	list_add(&fid->list, fid_list);
+	spin_lock(&dent->lock);
+	list_add(&fid->dlist, &dent->fidlist);
+	spin_unlock(&dent->lock);
+
 	return 0;
 }
 
 /**
- * v9fs_fid_create - allocate a FID structure
- * @dentry - dentry to link newly created fid to
- *
- */
-
-struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid)
-{
-	struct v9fs_fid *new;
-
-	dprintk(DEBUG_9P, "fid create fid %d\n", fid);
-	new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
-	if (new == NULL) {
-		dprintk(DEBUG_ERROR, "Out of Memory\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	new->fid = fid;
-	new->v9ses = v9ses;
-	new->fidopen = 0;
-	new->fidclunked = 0;
-	new->iounit = 0;
-	new->rdir_pos = 0;
-	new->rdir_fcall = NULL;
-	init_MUTEX(&new->lock);
-	INIT_LIST_HEAD(&new->list);
-
-	return new;
-}
-
-/**
- * v9fs_fid_destroy - deallocate a FID structure
- * @fid: fid to destroy
- *
- */
-
-void v9fs_fid_destroy(struct v9fs_fid *fid)
-{
-	list_del(&fid->list);
-	kfree(fid);
-}
-
-/**
  * v9fs_fid_lookup - return a locked fid from a dentry
  * @dentry: dentry to look for fid in
  *
@@ -114,30 +76,42 @@
  *
  */
 
-struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
+struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
 {
-	struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
-	struct v9fs_fid *return_fid = NULL;
+	struct v9fs_dentry *dent;
+	struct p9_fid *fid;
 
-	dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+	dent = dentry->d_fsdata;
+	if (dent)
+		fid = list_entry(dent->fidlist.next, struct p9_fid, dlist);
+	else
+		fid = ERR_PTR(-EBADF);
 
-	if (fid_list)
-		return_fid = list_entry(fid_list->next, struct v9fs_fid, list);
+	P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid);
+	return fid;
+}
 
-	if (!return_fid) {
-		dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n");
-		return_fid = ERR_PTR(-EBADF);
+struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry)
+{
+	struct p9_fid *fid;
+	struct v9fs_dentry *dent;
+
+	dent = dentry->d_fsdata;
+	fid = v9fs_fid_lookup(dentry);
+	if (!IS_ERR(fid)) {
+		spin_lock(&dent->lock);
+		list_del(&fid->dlist);
+		spin_unlock(&dent->lock);
 	}
 
-	if(down_interruptible(&return_fid->lock))
-		return ERR_PTR(-EINTR);
-
-	return return_fid;
+	return fid;
 }
 
+
 /**
  * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
- * 			release it
+ * 	release it
  * @dentry: dentry to look for fid in
  *
  * find a fid in the dentry and then clone to a new private fid
@@ -146,49 +120,15 @@
  *
  */
 
-struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry)
+struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
 {
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF);
-	struct v9fs_fcall *fcall = NULL;
-	int fid, err;
+	struct p9_fid *ofid, *fid;
 
-	base_fid = v9fs_fid_lookup(dentry);
+	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+	ofid = v9fs_fid_lookup(dentry);
+	if (IS_ERR(ofid))
+		return ofid;
 
-	if(IS_ERR(base_fid))
-		return base_fid;
-
-	if(base_fid) {  /* clone fid */
-		fid = v9fs_get_idpool(&v9ses->fidpool);
-		if (fid < 0) {
-			eprintk(KERN_WARNING, "newfid fails!\n");
-			new_fid = ERR_PTR(-ENOSPC);
-			goto Release_Fid;
-		}
-
-		err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall);
-		if (err < 0) {
-			dprintk(DEBUG_ERROR, "clone walk didn't work\n");
-			v9fs_put_idpool(fid, &v9ses->fidpool);
-			new_fid = ERR_PTR(err);
-			goto Free_Fcall;
-		}
-		new_fid = v9fs_fid_create(v9ses, fid);
-		if (new_fid == NULL) {
-			dprintk(DEBUG_ERROR, "out of memory\n");
-			new_fid = ERR_PTR(-ENOMEM);
-		}
-Free_Fcall:
-		kfree(fcall);
-	}
-
-Release_Fid:
-	up(&base_fid->lock);
-	return new_fid;
-}
-
-void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid)
-{
-	v9fs_t_clunk(v9ses, fid->fid);
-	v9fs_fid_destroy(fid);
+	fid = p9_client_walk(ofid, 0, NULL, 1);
+	return fid;
 }
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 48fc170..47a0ba7 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -22,41 +22,12 @@
 
 #include <linux/list.h>
 
-#define FID_OP   0
-#define FID_WALK 1
-#define FID_CREATE 2
-
-struct v9fs_fid {
-	struct list_head list;	 /* list of fids associated with a dentry */
-	struct list_head active; /* XXX - debug */
-
-	struct semaphore lock;
-
-	u32 fid;
-	unsigned char fidopen;	  /* set when fid is opened */
-	unsigned char fidclunked; /* set when fid has already been clunked */
-
-	struct v9fs_qid qid;
-	u32 iounit;
-
-	/* readdir stuff */
-	int rdir_fpos;
-	loff_t rdir_pos;
-	struct v9fs_fcall *rdir_fcall;
-
-	/* management stuff */
-	uid_t uid;		/* user associated with this fid */
-
-	/* private data */
-	struct file *filp;	/* backpointer to File struct for open files */
-	struct v9fs_session_info *v9ses;	/* session info for this FID */
+struct v9fs_dentry {
+	spinlock_t lock; /* protect fidlist */
+	struct list_head fidlist;
 };
 
-struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry);
-struct v9fs_fid *v9fs_fid_get_created(struct dentry *);
-void v9fs_fid_destroy(struct v9fs_fid *fid);
-struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid);
-int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry);
-struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry);
-void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid);
-
+struct p9_fid *v9fs_fid_lookup(struct dentry *dentry);
+struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry);
+struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
+int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
deleted file mode 100644
index c783874..0000000
--- a/fs/9p/mux.c
+++ /dev/null
@@ -1,1033 +0,0 @@
-/*
- * linux/fs/9p/mux.c
- *
- * Protocol Multiplexer
- *
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/kthread.h>
-#include <linux/idr.h>
-#include <linux/mutex.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "9p.h"
-#include "conv.h"
-#include "transport.h"
-#include "mux.h"
-
-#define ERREQFLUSH	1
-#define SCHED_TIMEOUT	10
-#define MAXPOLLWADDR	2
-
-enum {
-	Rworksched = 1,		/* read work scheduled or running */
-	Rpending = 2,		/* can read */
-	Wworksched = 4,		/* write work scheduled or running */
-	Wpending = 8,		/* can write */
-};
-
-enum {
-	None,
-	Flushing,
-	Flushed,
-};
-
-struct v9fs_mux_poll_task;
-
-struct v9fs_req {
-	spinlock_t lock;
-	int tag;
-	struct v9fs_fcall *tcall;
-	struct v9fs_fcall *rcall;
-	int err;
-	v9fs_mux_req_callback cb;
-	void *cba;
-	int flush;
-	struct list_head req_list;
-};
-
-struct v9fs_mux_data {
-	spinlock_t lock;
-	struct list_head mux_list;
-	struct v9fs_mux_poll_task *poll_task;
-	int msize;
-	unsigned char *extended;
-	struct v9fs_transport *trans;
-	struct v9fs_idpool tagpool;
-	int err;
-	wait_queue_head_t equeue;
-	struct list_head req_list;
-	struct list_head unsent_req_list;
-	struct v9fs_fcall *rcall;
-	int rpos;
-	char *rbuf;
-	int wpos;
-	int wsize;
-	char *wbuf;
-	wait_queue_t poll_wait[MAXPOLLWADDR];
-	wait_queue_head_t *poll_waddr[MAXPOLLWADDR];
-	poll_table pt;
-	struct work_struct rq;
-	struct work_struct wq;
-	unsigned long wsched;
-};
-
-struct v9fs_mux_poll_task {
-	struct task_struct *task;
-	struct list_head mux_list;
-	int muxnum;
-};
-
-struct v9fs_mux_rpc {
-	struct v9fs_mux_data *m;
-	int err;
-	struct v9fs_fcall *tcall;
-	struct v9fs_fcall *rcall;
-	wait_queue_head_t wqueue;
-};
-
-static int v9fs_poll_proc(void *);
-static void v9fs_read_work(struct work_struct *work);
-static void v9fs_write_work(struct work_struct *work);
-static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
-			  poll_table * p);
-static u16 v9fs_mux_get_tag(struct v9fs_mux_data *);
-static void v9fs_mux_put_tag(struct v9fs_mux_data *, u16);
-
-static DEFINE_MUTEX(v9fs_mux_task_lock);
-static struct workqueue_struct *v9fs_mux_wq;
-
-static int v9fs_mux_num;
-static int v9fs_mux_poll_task_num;
-static struct v9fs_mux_poll_task v9fs_mux_poll_tasks[100];
-
-int v9fs_mux_global_init(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++)
-		v9fs_mux_poll_tasks[i].task = NULL;
-
-	v9fs_mux_wq = create_workqueue("v9fs");
-	if (!v9fs_mux_wq) {
-		printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n");
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-void v9fs_mux_global_exit(void)
-{
-	destroy_workqueue(v9fs_mux_wq);
-}
-
-/**
- * v9fs_mux_calc_poll_procs - calculates the number of polling procs
- * based on the number of mounted v9fs filesystems.
- *
- * The current implementation returns sqrt of the number of mounts.
- */
-static int v9fs_mux_calc_poll_procs(int muxnum)
-{
-	int n;
-
-	if (v9fs_mux_poll_task_num)
-		n = muxnum / v9fs_mux_poll_task_num +
-		    (muxnum % v9fs_mux_poll_task_num ? 1 : 0);
-	else
-		n = 1;
-
-	if (n > ARRAY_SIZE(v9fs_mux_poll_tasks))
-		n = ARRAY_SIZE(v9fs_mux_poll_tasks);
-
-	return n;
-}
-
-static int v9fs_mux_poll_start(struct v9fs_mux_data *m)
-{
-	int i, n;
-	struct v9fs_mux_poll_task *vpt, *vptlast;
-	struct task_struct *pproc;
-
-	dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num,
-		v9fs_mux_poll_task_num);
-	mutex_lock(&v9fs_mux_task_lock);
-
-	n = v9fs_mux_calc_poll_procs(v9fs_mux_num + 1);
-	if (n > v9fs_mux_poll_task_num) {
-		for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) {
-			if (v9fs_mux_poll_tasks[i].task == NULL) {
-				vpt = &v9fs_mux_poll_tasks[i];
-				dprintk(DEBUG_MUX, "create proc %p\n", vpt);
-				pproc = kthread_create(v9fs_poll_proc, vpt,
-						   "v9fs-poll");
-
-				if (!IS_ERR(pproc)) {
-					vpt->task = pproc;
-					INIT_LIST_HEAD(&vpt->mux_list);
-					vpt->muxnum = 0;
-					v9fs_mux_poll_task_num++;
-					wake_up_process(vpt->task);
-				}
-				break;
-			}
-		}
-
-		if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks))
-			dprintk(DEBUG_ERROR, "warning: no free poll slots\n");
-	}
-
-	n = (v9fs_mux_num + 1) / v9fs_mux_poll_task_num +
-	    ((v9fs_mux_num + 1) % v9fs_mux_poll_task_num ? 1 : 0);
-
-	vptlast = NULL;
-	for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) {
-		vpt = &v9fs_mux_poll_tasks[i];
-		if (vpt->task != NULL) {
-			vptlast = vpt;
-			if (vpt->muxnum < n) {
-				dprintk(DEBUG_MUX, "put in proc %d\n", i);
-				list_add(&m->mux_list, &vpt->mux_list);
-				vpt->muxnum++;
-				m->poll_task = vpt;
-				memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
-				init_poll_funcptr(&m->pt, v9fs_pollwait);
-				break;
-			}
-		}
-	}
-
-	if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) {
-		if (vptlast == NULL)
-			return -ENOMEM;
-
-		dprintk(DEBUG_MUX, "put in proc %d\n", i);
-		list_add(&m->mux_list, &vptlast->mux_list);
-		vptlast->muxnum++;
-		m->poll_task = vptlast;
-		memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
-		init_poll_funcptr(&m->pt, v9fs_pollwait);
-	}
-
-	v9fs_mux_num++;
-	mutex_unlock(&v9fs_mux_task_lock);
-
-	return 0;
-}
-
-static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
-{
-	int i;
-	struct v9fs_mux_poll_task *vpt;
-
-	mutex_lock(&v9fs_mux_task_lock);
-	vpt = m->poll_task;
-	list_del(&m->mux_list);
-	for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
-		if (m->poll_waddr[i] != NULL) {
-			remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]);
-			m->poll_waddr[i] = NULL;
-		}
-	}
-	vpt->muxnum--;
-	if (!vpt->muxnum) {
-		dprintk(DEBUG_MUX, "destroy proc %p\n", vpt);
-		kthread_stop(vpt->task);
-		vpt->task = NULL;
-		v9fs_mux_poll_task_num--;
-	}
-	v9fs_mux_num--;
-	mutex_unlock(&v9fs_mux_task_lock);
-}
-
-/**
- * v9fs_mux_init - allocate and initialize the per-session mux data
- * Creates the polling task if this is the first session.
- *
- * @trans - transport structure
- * @msize - maximum message size
- * @extended - pointer to the extended flag
- */
-struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
-				    unsigned char *extended)
-{
-	int i, n;
-	struct v9fs_mux_data *m, *mtmp;
-
-	dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize);
-	m = kmalloc(sizeof(struct v9fs_mux_data), GFP_KERNEL);
-	if (!m)
-		return ERR_PTR(-ENOMEM);
-
-	spin_lock_init(&m->lock);
-	INIT_LIST_HEAD(&m->mux_list);
-	m->msize = msize;
-	m->extended = extended;
-	m->trans = trans;
-	idr_init(&m->tagpool.pool);
-	init_MUTEX(&m->tagpool.lock);
-	m->err = 0;
-	init_waitqueue_head(&m->equeue);
-	INIT_LIST_HEAD(&m->req_list);
-	INIT_LIST_HEAD(&m->unsent_req_list);
-	m->rcall = NULL;
-	m->rpos = 0;
-	m->rbuf = NULL;
-	m->wpos = m->wsize = 0;
-	m->wbuf = NULL;
-	INIT_WORK(&m->rq, v9fs_read_work);
-	INIT_WORK(&m->wq, v9fs_write_work);
-	m->wsched = 0;
-	memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
-	m->poll_task = NULL;
-	n = v9fs_mux_poll_start(m);
-	if (n)
-		return ERR_PTR(n);
-
-	n = trans->poll(trans, &m->pt);
-	if (n & POLLIN) {
-		dprintk(DEBUG_MUX, "mux %p can read\n", m);
-		set_bit(Rpending, &m->wsched);
-	}
-
-	if (n & POLLOUT) {
-		dprintk(DEBUG_MUX, "mux %p can write\n", m);
-		set_bit(Wpending, &m->wsched);
-	}
-
-	for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
-		if (IS_ERR(m->poll_waddr[i])) {
-			v9fs_mux_poll_stop(m);
-			mtmp = (void *)m->poll_waddr;	/* the error code */
-			kfree(m);
-			m = mtmp;
-			break;
-		}
-	}
-
-	return m;
-}
-
-/**
- * v9fs_mux_destroy - cancels all pending requests and frees mux resources
- */
-void v9fs_mux_destroy(struct v9fs_mux_data *m)
-{
-	dprintk(DEBUG_MUX, "mux %p prev %p next %p\n", m,
-		m->mux_list.prev, m->mux_list.next);
-	v9fs_mux_cancel(m, -ECONNRESET);
-
-	if (!list_empty(&m->req_list)) {
-		/* wait until all processes waiting on this session exit */
-		dprintk(DEBUG_MUX, "mux %p waiting for empty request queue\n",
-			m);
-		wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000);
-		dprintk(DEBUG_MUX, "mux %p request queue empty: %d\n", m,
-			list_empty(&m->req_list));
-	}
-
-	v9fs_mux_poll_stop(m);
-	m->trans = NULL;
-
-	kfree(m);
-}
-
-/**
- * v9fs_pollwait - called by files poll operation to add v9fs-poll task
- * 	to files wait queue
- */
-static void
-v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
-	      poll_table * p)
-{
-	int i;
-	struct v9fs_mux_data *m;
-
-	m = container_of(p, struct v9fs_mux_data, pt);
-	for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++)
-		if (m->poll_waddr[i] == NULL)
-			break;
-
-	if (i >= ARRAY_SIZE(m->poll_waddr)) {
-		dprintk(DEBUG_ERROR, "not enough wait_address slots\n");
-		return;
-	}
-
-	m->poll_waddr[i] = wait_address;
-
-	if (!wait_address) {
-		dprintk(DEBUG_ERROR, "no wait_address\n");
-		m->poll_waddr[i] = ERR_PTR(-EIO);
-		return;
-	}
-
-	init_waitqueue_entry(&m->poll_wait[i], m->poll_task->task);
-	add_wait_queue(wait_address, &m->poll_wait[i]);
-}
-
-/**
- * v9fs_poll_mux - polls a mux and schedules read or write works if necessary
- */
-static void v9fs_poll_mux(struct v9fs_mux_data *m)
-{
-	int n;
-
-	if (m->err < 0)
-		return;
-
-	n = m->trans->poll(m->trans, NULL);
-	if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
-		dprintk(DEBUG_MUX, "error mux %p err %d\n", m, n);
-		if (n >= 0)
-			n = -ECONNRESET;
-		v9fs_mux_cancel(m, n);
-	}
-
-	if (n & POLLIN) {
-		set_bit(Rpending, &m->wsched);
-		dprintk(DEBUG_MUX, "mux %p can read\n", m);
-		if (!test_and_set_bit(Rworksched, &m->wsched)) {
-			dprintk(DEBUG_MUX, "schedule read work mux %p\n", m);
-			queue_work(v9fs_mux_wq, &m->rq);
-		}
-	}
-
-	if (n & POLLOUT) {
-		set_bit(Wpending, &m->wsched);
-		dprintk(DEBUG_MUX, "mux %p can write\n", m);
-		if ((m->wsize || !list_empty(&m->unsent_req_list))
-		    && !test_and_set_bit(Wworksched, &m->wsched)) {
-			dprintk(DEBUG_MUX, "schedule write work mux %p\n", m);
-			queue_work(v9fs_mux_wq, &m->wq);
-		}
-	}
-}
-
-/**
- * v9fs_poll_proc - polls all v9fs transports for new events and queues
- * 	the appropriate work to the work queue
- */
-static int v9fs_poll_proc(void *a)
-{
-	struct v9fs_mux_data *m, *mtmp;
-	struct v9fs_mux_poll_task *vpt;
-
-	vpt = a;
-	dprintk(DEBUG_MUX, "start %p %p\n", current, vpt);
-	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) {
-			v9fs_poll_mux(m);
-		}
-
-		dprintk(DEBUG_MUX, "sleeping...\n");
-		schedule_timeout(SCHED_TIMEOUT * HZ);
-	}
-
-	__set_current_state(TASK_RUNNING);
-	dprintk(DEBUG_MUX, "finish\n");
-	return 0;
-}
-
-/**
- * v9fs_write_work - called when a transport can send some data
- */
-static void v9fs_write_work(struct work_struct *work)
-{
-	int n, err;
-	struct v9fs_mux_data *m;
-	struct v9fs_req *req;
-
-	m = container_of(work, struct v9fs_mux_data, wq);
-
-	if (m->err < 0) {
-		clear_bit(Wworksched, &m->wsched);
-		return;
-	}
-
-	if (!m->wsize) {
-		if (list_empty(&m->unsent_req_list)) {
-			clear_bit(Wworksched, &m->wsched);
-			return;
-		}
-
-		spin_lock(&m->lock);
-again:
-		req = list_entry(m->unsent_req_list.next, struct v9fs_req,
-			       req_list);
-		list_move_tail(&req->req_list, &m->req_list);
-		if (req->err == ERREQFLUSH)
-			goto again;
-
-		m->wbuf = req->tcall->sdata;
-		m->wsize = req->tcall->size;
-		m->wpos = 0;
-		dump_data(m->wbuf, m->wsize);
-		spin_unlock(&m->lock);
-	}
-
-	dprintk(DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, m->wsize);
-	clear_bit(Wpending, &m->wsched);
-	err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos);
-	dprintk(DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
-	if (err == -EAGAIN) {
-		clear_bit(Wworksched, &m->wsched);
-		return;
-	}
-
-	if (err <= 0)
-		goto error;
-
-	m->wpos += err;
-	if (m->wpos == m->wsize)
-		m->wpos = m->wsize = 0;
-
-	if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
-		if (test_and_clear_bit(Wpending, &m->wsched))
-			n = POLLOUT;
-		else
-			n = m->trans->poll(m->trans, NULL);
-
-		if (n & POLLOUT) {
-			dprintk(DEBUG_MUX, "schedule write work mux %p\n", m);
-			queue_work(v9fs_mux_wq, &m->wq);
-		} else
-			clear_bit(Wworksched, &m->wsched);
-	} else
-		clear_bit(Wworksched, &m->wsched);
-
-	return;
-
-      error:
-	v9fs_mux_cancel(m, err);
-	clear_bit(Wworksched, &m->wsched);
-}
-
-static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
-{
-	int ecode;
-	struct v9fs_str *ename;
-
-	if (!req->err && req->rcall->id == RERROR) {
-		ecode = req->rcall->params.rerror.errno;
-		ename = &req->rcall->params.rerror.error;
-
-		dprintk(DEBUG_MUX, "Rerror %.*s\n", ename->len, ename->str);
-
-		if (*m->extended)
-			req->err = -ecode;
-
-		if (!req->err) {
-			req->err = v9fs_errstr2errno(ename->str, ename->len);
-
-			if (!req->err) {	/* string match failed */
-				PRINT_FCALL_ERROR("unknown error", req->rcall);
-			}
-
-			if (!req->err)
-				req->err = -ESERVERFAULT;
-		}
-	} else if (req->tcall && req->rcall->id != req->tcall->id + 1) {
-		dprintk(DEBUG_ERROR, "fcall mismatch: expected %d, got %d\n",
-			req->tcall->id + 1, req->rcall->id);
-		if (!req->err)
-			req->err = -EIO;
-	}
-}
-
-/**
- * v9fs_read_work - called when there is some data to be read from a transport
- */
-static void v9fs_read_work(struct work_struct *work)
-{
-	int n, err;
-	struct v9fs_mux_data *m;
-	struct v9fs_req *req, *rptr, *rreq;
-	struct v9fs_fcall *rcall;
-	char *rbuf;
-
-	m = container_of(work, struct v9fs_mux_data, rq);
-
-	if (m->err < 0)
-		return;
-
-	rcall = NULL;
-	dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
-
-	if (!m->rcall) {
-		m->rcall =
-		    kmalloc(sizeof(struct v9fs_fcall) + m->msize, GFP_KERNEL);
-		if (!m->rcall) {
-			err = -ENOMEM;
-			goto error;
-		}
-
-		m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall);
-		m->rpos = 0;
-	}
-
-	clear_bit(Rpending, &m->wsched);
-	err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos);
-	dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err);
-	if (err == -EAGAIN) {
-		clear_bit(Rworksched, &m->wsched);
-		return;
-	}
-
-	if (err <= 0)
-		goto error;
-
-	m->rpos += err;
-	while (m->rpos > 4) {
-		n = le32_to_cpu(*(__le32 *) m->rbuf);
-		if (n >= m->msize) {
-			dprintk(DEBUG_ERROR,
-				"requested packet size too big: %d\n", n);
-			err = -EIO;
-			goto error;
-		}
-
-		if (m->rpos < n)
-			break;
-
-		dump_data(m->rbuf, n);
-		err =
-		    v9fs_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended);
-		if (err < 0) {
-			goto error;
-		}
-
-		if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
-			char buf[150];
-
-			v9fs_printfcall(buf, sizeof(buf), m->rcall,
-				*m->extended);
-			printk(KERN_NOTICE ">>> %p %s\n", m, buf);
-		}
-
-		rcall = m->rcall;
-		rbuf = m->rbuf;
-		if (m->rpos > n) {
-			m->rcall = kmalloc(sizeof(struct v9fs_fcall) + m->msize,
-					   GFP_KERNEL);
-			if (!m->rcall) {
-				err = -ENOMEM;
-				goto error;
-			}
-
-			m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall);
-			memmove(m->rbuf, rbuf + n, m->rpos - n);
-			m->rpos -= n;
-		} else {
-			m->rcall = NULL;
-			m->rbuf = NULL;
-			m->rpos = 0;
-		}
-
-		dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id,
-			rcall->tag);
-
-		req = NULL;
-		spin_lock(&m->lock);
-		list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
-			if (rreq->tag == rcall->tag) {
-				req = rreq;
-				if (req->flush != Flushing)
-					list_del(&req->req_list);
-				break;
-			}
-		}
-		spin_unlock(&m->lock);
-
-		if (req) {
-			req->rcall = rcall;
-			process_request(m, req);
-
-			if (req->flush != Flushing) {
-				if (req->cb)
-					(*req->cb) (req, req->cba);
-				else
-					kfree(req->rcall);
-
-				wake_up(&m->equeue);
-			}
-		} else {
-			if (err >= 0 && rcall->id != RFLUSH)
-				dprintk(DEBUG_ERROR,
-					"unexpected response mux %p id %d tag %d\n",
-					m, rcall->id, rcall->tag);
-			kfree(rcall);
-		}
-	}
-
-	if (!list_empty(&m->req_list)) {
-		if (test_and_clear_bit(Rpending, &m->wsched))
-			n = POLLIN;
-		else
-			n = m->trans->poll(m->trans, NULL);
-
-		if (n & POLLIN) {
-			dprintk(DEBUG_MUX, "schedule read work mux %p\n", m);
-			queue_work(v9fs_mux_wq, &m->rq);
-		} else
-			clear_bit(Rworksched, &m->wsched);
-	} else
-		clear_bit(Rworksched, &m->wsched);
-
-	return;
-
-      error:
-	v9fs_mux_cancel(m, err);
-	clear_bit(Rworksched, &m->wsched);
-}
-
-/**
- * v9fs_send_request - send 9P request
- * The function can sleep until the request is scheduled for sending.
- * The function can be interrupted. Return from the function is not
- * a guarantee that the request is sent successfully. Can return errors
- * that can be retrieved by PTR_ERR macros.
- *
- * @m: mux data
- * @tc: request to be sent
- * @cb: callback function to call when response is received
- * @cba: parameter to pass to the callback function
- */
-static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
-					  struct v9fs_fcall *tc,
-					  v9fs_mux_req_callback cb, void *cba)
-{
-	int n;
-	struct v9fs_req *req;
-
-	dprintk(DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
-		tc, tc->id);
-	if (m->err < 0)
-		return ERR_PTR(m->err);
-
-	req = kmalloc(sizeof(struct v9fs_req), GFP_KERNEL);
-	if (!req)
-		return ERR_PTR(-ENOMEM);
-
-	if (tc->id == TVERSION)
-		n = V9FS_NOTAG;
-	else
-		n = v9fs_mux_get_tag(m);
-
-	if (n < 0)
-		return ERR_PTR(-ENOMEM);
-
-	v9fs_set_tag(tc, n);
-	if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
-		char buf[150];
-
-		v9fs_printfcall(buf, sizeof(buf), tc, *m->extended);
-		printk(KERN_NOTICE "<<< %p %s\n", m, buf);
-	}
-
-	spin_lock_init(&req->lock);
-	req->tag = n;
-	req->tcall = tc;
-	req->rcall = NULL;
-	req->err = 0;
-	req->cb = cb;
-	req->cba = cba;
-	req->flush = None;
-
-	spin_lock(&m->lock);
-	list_add_tail(&req->req_list, &m->unsent_req_list);
-	spin_unlock(&m->lock);
-
-	if (test_and_clear_bit(Wpending, &m->wsched))
-		n = POLLOUT;
-	else
-		n = m->trans->poll(m->trans, NULL);
-
-	if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
-		queue_work(v9fs_mux_wq, &m->wq);
-
-	return req;
-}
-
-static void v9fs_mux_free_request(struct v9fs_mux_data *m, struct v9fs_req *req)
-{
-	v9fs_mux_put_tag(m, req->tag);
-	kfree(req);
-}
-
-static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a)
-{
-	v9fs_mux_req_callback cb;
-	int tag;
-	struct v9fs_mux_data *m;
-	struct v9fs_req *req, *rreq, *rptr;
-
-	m = a;
-	dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
-		freq->tcall, freq->rcall, freq->err,
-		freq->tcall->params.tflush.oldtag);
-
-	spin_lock(&m->lock);
-	cb = NULL;
-	tag = freq->tcall->params.tflush.oldtag;
-	req = NULL;
-	list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
-		if (rreq->tag == tag) {
-			req = rreq;
-			list_del(&req->req_list);
-			break;
-		}
-	}
-	spin_unlock(&m->lock);
-
-	if (req) {
-		spin_lock(&req->lock);
-		req->flush = Flushed;
-		spin_unlock(&req->lock);
-
-		if (req->cb)
-			(*req->cb) (req, req->cba);
-		else
-			kfree(req->rcall);
-
-		wake_up(&m->equeue);
-	}
-
-	kfree(freq->tcall);
-	kfree(freq->rcall);
-	v9fs_mux_free_request(m, freq);
-}
-
-static int
-v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
-{
-	struct v9fs_fcall *fc;
-	struct v9fs_req *rreq, *rptr;
-
-	dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
-
-	/* if a response was received for a request, do nothing */
-	spin_lock(&req->lock);
-	if (req->rcall || req->err) {
-		spin_unlock(&req->lock);
-		dprintk(DEBUG_MUX, "mux %p req %p response already received\n", m, req);
-		return 0;
-	}
-
-	req->flush = Flushing;
-	spin_unlock(&req->lock);
-
-	spin_lock(&m->lock);
-	/* if the request is not sent yet, just remove it from the list */
-	list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
-		if (rreq->tag == req->tag) {
-			dprintk(DEBUG_MUX, "mux %p req %p request is not sent yet\n", m, req);
-			list_del(&rreq->req_list);
-			req->flush = Flushed;
-			spin_unlock(&m->lock);
-			if (req->cb)
-				(*req->cb) (req, req->cba);
-			return 0;
-		}
-	}
-	spin_unlock(&m->lock);
-
-	clear_thread_flag(TIF_SIGPENDING);
-	fc = v9fs_create_tflush(req->tag);
-	v9fs_send_request(m, fc, v9fs_mux_flush_cb, m);
-	return 1;
-}
-
-static void
-v9fs_mux_rpc_cb(struct v9fs_req *req, void *a)
-{
-	struct v9fs_mux_rpc *r;
-
-	dprintk(DEBUG_MUX, "req %p r %p\n", req, a);
-	r = a;
-	r->rcall = req->rcall;
-	r->err = req->err;
-
-	if (req->flush!=None && !req->err)
-		r->err = -ERESTARTSYS;
-
-	wake_up(&r->wqueue);
-}
-
-/**
- * v9fs_mux_rpc - sends 9P request and waits until a response is available.
- *	The function can be interrupted.
- * @m: mux data
- * @tc: request to be sent
- * @rc: pointer where a pointer to the response is stored
- */
-int
-v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
-	     struct v9fs_fcall **rc)
-{
-	int err, sigpending;
-	unsigned long flags;
-	struct v9fs_req *req;
-	struct v9fs_mux_rpc r;
-
-	r.err = 0;
-	r.tcall = tc;
-	r.rcall = NULL;
-	r.m = m;
-	init_waitqueue_head(&r.wqueue);
-
-	if (rc)
-		*rc = NULL;
-
-	sigpending = 0;
-	if (signal_pending(current)) {
-		sigpending = 1;
-		clear_thread_flag(TIF_SIGPENDING);
-	}
-
-	req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r);
-	if (IS_ERR(req)) {
-		err = PTR_ERR(req);
-		dprintk(DEBUG_MUX, "error %d\n", err);
-		return err;
-	}
-
-	err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0);
-	if (r.err < 0)
-		err = r.err;
-
-	if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) {
-		if (v9fs_mux_flush_request(m, req)) {
-			/* wait until we get response of the flush message */
-			do {
-				clear_thread_flag(TIF_SIGPENDING);
-				err = wait_event_interruptible(r.wqueue,
-					r.rcall || r.err);
-			} while (!r.rcall && !r.err && err==-ERESTARTSYS &&
-				m->trans->status==Connected && !m->err);
-
-			err = -ERESTARTSYS;
-		}
-		sigpending = 1;
-	}
-
-	if (sigpending) {
-		spin_lock_irqsave(&current->sighand->siglock, flags);
-		recalc_sigpending();
-		spin_unlock_irqrestore(&current->sighand->siglock, flags);
-	}
-
-	if (rc)
-		*rc = r.rcall;
-	else
-		kfree(r.rcall);
-
-	v9fs_mux_free_request(m, req);
-	if (err > 0)
-		err = -EIO;
-
-	return err;
-}
-
-#if 0
-/**
- * v9fs_mux_rpcnb - sends 9P request without waiting for response.
- * @m: mux data
- * @tc: request to be sent
- * @cb: callback function to be called when response arrives
- * @cba: value to pass to the callback function
- */
-int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
-		   v9fs_mux_req_callback cb, void *a)
-{
-	int err;
-	struct v9fs_req *req;
-
-	req = v9fs_send_request(m, tc, cb, a);
-	if (IS_ERR(req)) {
-		err = PTR_ERR(req);
-		dprintk(DEBUG_MUX, "error %d\n", err);
-		return PTR_ERR(req);
-	}
-
-	dprintk(DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag);
-	return 0;
-}
-#endif  /*  0  */
-
-/**
- * v9fs_mux_cancel - cancel all pending requests with error
- * @m: mux data
- * @err: error code
- */
-void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
-{
-	struct v9fs_req *req, *rtmp;
-	LIST_HEAD(cancel_list);
-
-	dprintk(DEBUG_ERROR, "mux %p err %d\n", m, err);
-	m->err = err;
-	spin_lock(&m->lock);
-	list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
-		list_move(&req->req_list, &cancel_list);
-	}
-	list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
-		list_move(&req->req_list, &cancel_list);
-	}
-	spin_unlock(&m->lock);
-
-	list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
-		list_del(&req->req_list);
-		if (!req->err)
-			req->err = err;
-
-		if (req->cb)
-			(*req->cb) (req, req->cba);
-		else
-			kfree(req->rcall);
-	}
-
-	wake_up(&m->equeue);
-}
-
-static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m)
-{
-	int tag;
-
-	tag = v9fs_get_idpool(&m->tagpool);
-	if (tag < 0)
-		return V9FS_NOTAG;
-	else
-		return (u16) tag;
-}
-
-static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag)
-{
-	if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tagpool))
-		v9fs_put_idpool(tag, &m->tagpool);
-}
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
deleted file mode 100644
index fb10c50..0000000
--- a/fs/9p/mux.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * linux/fs/9p/mux.h
- *
- * Multiplexer Definitions
- *
- *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-struct v9fs_mux_data;
-struct v9fs_req;
-
-/**
- * v9fs_mux_req_callback - callback function that is called when the
- * response of a request is received. The callback is called from
- * a workqueue and shouldn't block.
- *
- * @a - the pointer that was specified when the request was send to be
- *      passed to the callback
- * @tc - request call
- * @rc - response call
- * @err - error code (non-zero if error occured)
- */
-typedef void (*v9fs_mux_req_callback)(struct v9fs_req *req, void *a);
-
-int v9fs_mux_global_init(void);
-void v9fs_mux_global_exit(void);
-
-struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
-	unsigned char *extended);
-void v9fs_mux_destroy(struct v9fs_mux_data *);
-
-int v9fs_mux_send(struct v9fs_mux_data *m, struct v9fs_fcall *tc);
-struct v9fs_fcall *v9fs_mux_recv(struct v9fs_mux_data *m);
-int v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, struct v9fs_fcall **rc);
-
-void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush);
-void v9fs_mux_cancel(struct v9fs_mux_data *m, int err);
-int v9fs_errstr2errno(char *errstr, int len);
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c
deleted file mode 100644
index 34d4335..0000000
--- a/fs/9p/trans_fd.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * linux/fs/9p/trans_fd.c
- *
- * Fd transport layer.  Includes deprecated socket layer.
- *
- *  Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
- *  Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
- *  Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
- *  Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-#include <linux/in.h>
-#include <linux/module.h>
-#include <linux/net.h>
-#include <linux/ipv6.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/un.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
-#include <linux/idr.h>
-#include <linux/file.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "transport.h"
-
-#define V9FS_PORT 564
-
-struct v9fs_trans_fd {
-	struct file *rd;
-	struct file *wr;
-};
-
-/**
- * v9fs_fd_read- read from a fd
- * @v9ses: session information
- * @v: buffer to receive data into
- * @len: size of receive buffer
- *
- */
-static int v9fs_fd_read(struct v9fs_transport *trans, void *v, int len)
-{
-	int ret;
-	struct v9fs_trans_fd *ts;
-
-	if (!trans || trans->status == Disconnected || !(ts = trans->priv))
-		return -EREMOTEIO;
-
-	if (!(ts->rd->f_flags & O_NONBLOCK))
-		dprintk(DEBUG_ERROR, "blocking read ...\n");
-
-	ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
-	if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
-		trans->status = Disconnected;
-	return ret;
-}
-
-/**
- * v9fs_fd_write - write to a socket
- * @v9ses: session information
- * @v: buffer to send data from
- * @len: size of send buffer
- *
- */
-static int v9fs_fd_write(struct v9fs_transport *trans, void *v, int len)
-{
-	int ret;
-	mm_segment_t oldfs;
-	struct v9fs_trans_fd *ts;
-
-	if (!trans || trans->status == Disconnected || !(ts = trans->priv))
-		return -EREMOTEIO;
-
-	if (!(ts->wr->f_flags & O_NONBLOCK))
-		dprintk(DEBUG_ERROR, "blocking write ...\n");
-
-	oldfs = get_fs();
-	set_fs(get_ds());
-	/* The cast to a user pointer is valid due to the set_fs() */
-	ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
-	set_fs(oldfs);
-
-	if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
-		trans->status = Disconnected;
-	return ret;
-}
-
-static unsigned int
-v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt)
-{
-	int ret, n;
-	struct v9fs_trans_fd *ts;
-	mm_segment_t oldfs;
-
-	if (!trans || trans->status != Connected || !(ts = trans->priv))
-		return -EREMOTEIO;
-
-	if (!ts->rd->f_op || !ts->rd->f_op->poll)
-		return -EIO;
-
-	if (!ts->wr->f_op || !ts->wr->f_op->poll)
-		return -EIO;
-
-	oldfs = get_fs();
-	set_fs(get_ds());
-
-	ret = ts->rd->f_op->poll(ts->rd, pt);
-	if (ret < 0)
-		goto end;
-
-	if (ts->rd != ts->wr) {
-		n = ts->wr->f_op->poll(ts->wr, pt);
-		if (n < 0) {
-			ret = n;
-			goto end;
-		}
-		ret = (ret & ~POLLOUT) | (n & ~POLLIN);
-	}
-
-      end:
-	set_fs(oldfs);
-	return ret;
-}
-
-static int v9fs_fd_open(struct v9fs_session_info *v9ses, int rfd, int wfd)
-{
-	struct v9fs_transport *trans = v9ses->transport;
-	struct v9fs_trans_fd *ts = kmalloc(sizeof(struct v9fs_trans_fd),
-					   GFP_KERNEL);
-	if (!ts)
-		return -ENOMEM;
-
-	ts->rd = fget(rfd);
-	ts->wr = fget(wfd);
-	if (!ts->rd || !ts->wr) {
-		if (ts->rd)
-			fput(ts->rd);
-		if (ts->wr)
-			fput(ts->wr);
-		kfree(ts);
-		return -EIO;
-	}
-
-	trans->priv = ts;
-	trans->status = Connected;
-
-	return 0;
-}
-
-static int v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr,
-			char *data)
-{
-	if (v9ses->rfdno == ~0 || v9ses->wfdno == ~0) {
-		printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
-		return -ENOPROTOOPT;
-	}
-
-	return v9fs_fd_open(v9ses, v9ses->rfdno, v9ses->wfdno);
-}
-
-static int v9fs_socket_open(struct v9fs_session_info *v9ses,
-			    struct socket *csocket)
-{
-	int fd, ret;
-
-	csocket->sk->sk_allocation = GFP_NOIO;
-	if ((fd = sock_map_fd(csocket)) < 0) {
-		eprintk(KERN_ERR, "v9fs_socket_open: failed to map fd\n");
-		ret = fd;
-	      release_csocket:
-		sock_release(csocket);
-		return ret;
-	}
-
-	if ((ret = v9fs_fd_open(v9ses, fd, fd)) < 0) {
-		sockfd_put(csocket);
-		eprintk(KERN_ERR, "v9fs_socket_open: failed to open fd\n");
-		goto release_csocket;
-	}
-
-	((struct v9fs_trans_fd *)v9ses->transport->priv)->rd->f_flags |=
-	    O_NONBLOCK;
-	return 0;
-}
-
-static int v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr,
-			 char *data)
-{
-	int ret;
-	struct socket *csocket = NULL;
-	struct sockaddr_in sin_server;
-
-	sin_server.sin_family = AF_INET;
-	sin_server.sin_addr.s_addr = in_aton(addr);
-	sin_server.sin_port = htons(v9ses->port);
-	sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
-
-	if (!csocket) {
-		eprintk(KERN_ERR, "v9fs_trans_tcp: problem creating socket\n");
-		return -1;
-	}
-
-	ret = csocket->ops->connect(csocket,
-				    (struct sockaddr *)&sin_server,
-				    sizeof(struct sockaddr_in), 0);
-	if (ret < 0) {
-		eprintk(KERN_ERR,
-			"v9fs_trans_tcp: problem connecting socket to %s\n",
-			addr);
-		return ret;
-	}
-
-	return v9fs_socket_open(v9ses, csocket);
-}
-
-static int
-v9fs_unix_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
-{
-	int ret;
-	struct socket *csocket;
-	struct sockaddr_un sun_server;
-
-	if (strlen(addr) > UNIX_PATH_MAX) {
-		eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
-			addr);
-		return -ENAMETOOLONG;
-	}
-
-	sun_server.sun_family = PF_UNIX;
-	strcpy(sun_server.sun_path, addr);
-	sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
-	ret = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
-			sizeof(struct sockaddr_un) - 1, 0);
-	if (ret < 0) {
-		eprintk(KERN_ERR,
-			"v9fs_trans_unix: problem connecting socket: %s: %d\n",
-			addr, ret);
-		return ret;
-	}
-
-	return v9fs_socket_open(v9ses, csocket);
-}
-
-/**
- * v9fs_sock_close - shutdown socket
- * @trans: private socket structure
- *
- */
-static void v9fs_fd_close(struct v9fs_transport *trans)
-{
-	struct v9fs_trans_fd *ts;
-
-	if (!trans)
-		return;
-
-	ts = xchg(&trans->priv, NULL);
-
-	if (!ts)
-		return;
-
-	trans->status = Disconnected;
-	if (ts->rd)
-		fput(ts->rd);
-	if (ts->wr)
-		fput(ts->wr);
-	kfree(ts);
-}
-
-struct v9fs_transport v9fs_trans_fd = {
-	.init = v9fs_fd_init,
-	.write = v9fs_fd_write,
-	.read = v9fs_fd_read,
-	.close = v9fs_fd_close,
-	.poll = v9fs_fd_poll,
-};
-
-struct v9fs_transport v9fs_trans_tcp = {
-	.init = v9fs_tcp_init,
-	.write = v9fs_fd_write,
-	.read = v9fs_fd_read,
-	.close = v9fs_fd_close,
-	.poll = v9fs_fd_poll,
-};
-
-struct v9fs_transport v9fs_trans_unix = {
-	.init = v9fs_unix_init,
-	.write = v9fs_fd_write,
-	.read = v9fs_fd_read,
-	.close = v9fs_fd_close,
-	.poll = v9fs_fd_poll,
-};
diff --git a/fs/9p/transport.h b/fs/9p/transport.h
deleted file mode 100644
index b38a4b8..0000000
--- a/fs/9p/transport.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/fs/9p/transport.h
- *
- * Transport Definition
- *
- *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to:
- *  Free Software Foundation
- *  51 Franklin Street, Fifth Floor
- *  Boston, MA  02111-1301  USA
- *
- */
-
-enum v9fs_transport_status {
-	Connected,
-	Disconnected,
-	Hung,
-};
-
-struct v9fs_transport {
-	enum v9fs_transport_status status;
-	void *priv;
-
-	int (*init) (struct v9fs_session_info *, const char *, char *);
-	int (*write) (struct v9fs_transport *, void *, int);
-	int (*read) (struct v9fs_transport *, void *, int);
-	void (*close) (struct v9fs_transport *);
-	unsigned int (*poll)(struct v9fs_transport *, struct poll_table_struct *);
-};
-
-extern struct v9fs_transport v9fs_trans_tcp;
-extern struct v9fs_transport v9fs_trans_unix;
-extern struct v9fs_transport v9fs_trans_fd;
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 6ad6f19..0a7068e 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -29,16 +29,12 @@
 #include <linux/sched.h>
 #include <linux/parser.h>
 #include <linux/idr.h>
-
-#include "debug.h"
+#include <net/9p/9p.h>
+#include <net/9p/transport.h>
+#include <net/9p/conn.h>
+#include <net/9p/client.h>
 #include "v9fs.h"
-#include "9p.h"
 #include "v9fs_vfs.h"
-#include "transport.h"
-#include "mux.h"
-
-/* TODO: sysfs or debugfs interface */
-int v9fs_debug_level = 0;	/* feature-rific global debug level  */
 
 /*
   * Option Parsing (code inspired by NFS code)
@@ -47,12 +43,12 @@
 
 enum {
 	/* Options that take integer arguments */
-	Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug,
+	Opt_debug, Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid,
 	Opt_rfdno, Opt_wfdno,
 	/* String options */
 	Opt_uname, Opt_remotename,
 	/* Options that take no arguments */
-	Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
+	Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci,
 	/* Cache options */
 	Opt_cache_loose,
 	/* Error token */
@@ -60,6 +56,7 @@
 };
 
 static match_table_t tokens = {
+	{Opt_debug, "debug=%x"},
 	{Opt_port, "port=%u"},
 	{Opt_msize, "msize=%u"},
 	{Opt_uid, "uid=%u"},
@@ -67,12 +64,14 @@
 	{Opt_afid, "afid=%u"},
 	{Opt_rfdno, "rfdno=%u"},
 	{Opt_wfdno, "wfdno=%u"},
-	{Opt_debug, "debug=%x"},
 	{Opt_uname, "uname=%s"},
 	{Opt_remotename, "aname=%s"},
 	{Opt_unix, "proto=unix"},
 	{Opt_tcp, "proto=tcp"},
 	{Opt_fd, "proto=fd"},
+#ifdef CONFIG_PCI_9P
+	{Opt_pci, "proto=pci"},
+#endif
 	{Opt_tcp, "tcp"},
 	{Opt_unix, "unix"},
 	{Opt_fd, "fd"},
@@ -83,6 +82,8 @@
 	{Opt_err, NULL}
 };
 
+extern struct p9_transport *p9pci_trans_create(void);
+
 /*
  *  Parse option string.
  */
@@ -122,12 +123,18 @@
 		token = match_token(p, tokens, args);
 		if (token < Opt_uname) {
 			if ((ret = match_int(&args[0], &option)) < 0) {
-				dprintk(DEBUG_ERROR,
+				P9_DPRINTK(P9_DEBUG_ERROR,
 					"integer field, but no integer?\n");
 				continue;
 			}
 		}
 		switch (token) {
+		case Opt_debug:
+			v9ses->debug = option;
+#ifdef CONFIG_NET_9P_DEBUG
+			p9_debug_level = option;
+#endif
+			break;
 		case Opt_port:
 			v9ses->port = option;
 			break;
@@ -149,15 +156,15 @@
 		case Opt_wfdno:
 			v9ses->wfdno = option;
 			break;
-		case Opt_debug:
-			v9ses->debug = option;
-			break;
 		case Opt_tcp:
 			v9ses->proto = PROTO_TCP;
 			break;
 		case Opt_unix:
 			v9ses->proto = PROTO_UNIX;
 			break;
+		case Opt_pci:
+			v9ses->proto = PROTO_PCI;
+			break;
 		case Opt_fd:
 			v9ses->proto = PROTO_FD;
 			break;
@@ -183,82 +190,6 @@
 }
 
 /**
- * v9fs_inode2v9ses - safely extract v9fs session info from super block
- * @inode: inode to extract information from
- *
- * Paranoid function to extract v9ses information from superblock,
- * if anything is missing it will report an error.
- *
- */
-
-struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
-{
-	return (inode->i_sb->s_fs_info);
-}
-
-/**
- * v9fs_get_idpool - allocate numeric id from pool
- * @p - pool to allocate from
- *
- * XXX - This seems to be an awful generic function, should it be in idr.c with
- *            the lock included in struct idr?
- */
-
-int v9fs_get_idpool(struct v9fs_idpool *p)
-{
-	int i = 0;
-	int error;
-
-retry:
-	if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
-		return 0;
-
-	if (down_interruptible(&p->lock) == -EINTR) {
-		eprintk(KERN_WARNING, "Interrupted while locking\n");
-		return -1;
-	}
-
-	/* no need to store exactly p, we just need something non-null */
-	error = idr_get_new(&p->pool, p, &i);
-	up(&p->lock);
-
-	if (error == -EAGAIN)
-		goto retry;
-	else if (error)
-		return -1;
-
-	return i;
-}
-
-/**
- * v9fs_put_idpool - release numeric id from pool
- * @p - pool to allocate from
- *
- * XXX - This seems to be an awful generic function, should it be in idr.c with
- *            the lock included in struct idr?
- */
-
-void v9fs_put_idpool(int id, struct v9fs_idpool *p)
-{
-	if (down_interruptible(&p->lock) == -EINTR) {
-		eprintk(KERN_WARNING, "Interrupted while locking\n");
-		return;
-	}
-	idr_remove(&p->pool, id);
-	up(&p->lock);
-}
-
-/**
- * v9fs_check_idpool - check if the specified id is available
- * @id - id to check
- * @p - pool
- */
-int v9fs_check_idpool(int id, struct v9fs_idpool *p)
-{
-	return idr_find(&p->pool, id) != NULL;
-}
-
-/**
  * v9fs_session_init - initialize session
  * @v9ses: session information structure
  * @dev_name: device being mounted
@@ -266,25 +197,21 @@
  *
  */
 
-int
-v9fs_session_init(struct v9fs_session_info *v9ses,
+struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 		  const char *dev_name, char *data)
 {
-	struct v9fs_fcall *fcall = NULL;
-	struct v9fs_transport *trans_proto;
-	int n = 0;
-	int newfid = -1;
 	int retval = -EINVAL;
-	struct v9fs_str *version;
+	struct p9_transport *trans;
+	struct p9_fid *fid;
 
 	v9ses->name = __getname();
 	if (!v9ses->name)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	v9ses->remotename = __getname();
 	if (!v9ses->remotename) {
 		__putname(v9ses->name);
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	strcpy(v9ses->name, V9FS_DEFUSER);
@@ -292,130 +219,60 @@
 
 	v9fs_parse_options(data, v9ses);
 
-	/* set global debug level */
-	v9fs_debug_level = v9ses->debug;
-
-	/* id pools that are session-dependent: fids and tags */
-	idr_init(&v9ses->fidpool.pool);
-	init_MUTEX(&v9ses->fidpool.lock);
-
 	switch (v9ses->proto) {
 	case PROTO_TCP:
-		trans_proto = &v9fs_trans_tcp;
+		trans = p9_trans_create_tcp(dev_name, v9ses->port);
 		break;
 	case PROTO_UNIX:
-		trans_proto = &v9fs_trans_unix;
+		trans = p9_trans_create_unix(dev_name);
 		*v9ses->remotename = 0;
 		break;
 	case PROTO_FD:
-		trans_proto = &v9fs_trans_fd;
+		trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno);
 		*v9ses->remotename = 0;
 		break;
+#ifdef CONFIG_PCI_9P
+	case PROTO_PCI:
+		trans = p9pci_trans_create();
+		*v9ses->remotename = 0;
+		break;
+#endif
 	default:
 		printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
 		retval = -ENOPROTOOPT;
-		goto SessCleanUp;
+		goto error;
 	};
 
-	v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL);
-	if (!v9ses->transport) {
-		retval = -ENOMEM;
-		goto SessCleanUp;
+	if (IS_ERR(trans)) {
+		retval = PTR_ERR(trans);
+		trans = NULL;
+		goto error;
 	}
 
-	memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport));
+	v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ,
+		v9ses->extended);
 
-	if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) {
-		eprintk(KERN_ERR, "problem initializing transport\n");
-		goto SessCleanUp;
+	if (IS_ERR(v9ses->clnt)) {
+		retval = PTR_ERR(v9ses->clnt);
+		v9ses->clnt = NULL;
+		P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n");
+		goto error;
 	}
 
-	v9ses->inprogress = 0;
-	v9ses->shutdown = 0;
-	v9ses->session_hung = 0;
-
-	v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ,
-		&v9ses->extended);
-
-	if (IS_ERR(v9ses->mux)) {
-		retval = PTR_ERR(v9ses->mux);
-		v9ses->mux = NULL;
-		dprintk(DEBUG_ERROR, "problem initializing mux\n");
-		goto SessCleanUp;
+	fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name,
+							v9ses->remotename);
+	if (IS_ERR(fid)) {
+		retval = PTR_ERR(fid);
+		fid = NULL;
+		P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n");
+		goto error;
 	}
 
-	if (v9ses->afid == ~0) {
-		if (v9ses->extended)
-			retval =
-			    v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u",
-					   &fcall);
-		else
-			retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000",
-						&fcall);
+	return fid;
 
-		if (retval < 0) {
-			dprintk(DEBUG_ERROR, "v9fs_t_version failed\n");
-			goto FreeFcall;
-		}
-
-		version = &fcall->params.rversion.version;
-		if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) {
-			dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
-			v9ses->extended = 1;
-		} else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) {
-			dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n");
-			v9ses->extended = 0;
-		} else {
-			retval = -EREMOTEIO;
-			goto FreeFcall;
-		}
-
-		n = fcall->params.rversion.msize;
-		kfree(fcall);
-
-		if (n < v9ses->maxdata)
-			v9ses->maxdata = n;
-	}
-
-	newfid = v9fs_get_idpool(&v9ses->fidpool);
-	if (newfid < 0) {
-		eprintk(KERN_WARNING, "couldn't allocate FID\n");
-		retval = -ENOMEM;
-		goto SessCleanUp;
-	}
-	/* it is a little bit ugly, but we have to prevent newfid */
-	/* being the same as afid, so if it is, get a new fid     */
-	if (v9ses->afid != ~0 && newfid == v9ses->afid) {
-		newfid = v9fs_get_idpool(&v9ses->fidpool);
-		if (newfid < 0) {
-			eprintk(KERN_WARNING, "couldn't allocate FID\n");
-			retval = -ENOMEM;
-			goto SessCleanUp;
-		}
-	}
-
-	if ((retval =
-	     v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid,
-			   v9ses->afid, NULL))
-	    < 0) {
-		dprintk(DEBUG_ERROR, "cannot attach\n");
-		goto SessCleanUp;
-	}
-
-	if (v9ses->afid != ~0) {
-		dprintk(DEBUG_ERROR, "afid not equal to ~0\n");
-		if (v9fs_t_clunk(v9ses, v9ses->afid))
-			dprintk(DEBUG_ERROR, "clunk failed\n");
-	}
-
-	return newfid;
-
-      FreeFcall:
-	kfree(fcall);
-
-      SessCleanUp:
+error:
 	v9fs_session_close(v9ses);
-	return retval;
+	return ERR_PTR(retval);
 }
 
 /**
@@ -426,15 +283,9 @@
 
 void v9fs_session_close(struct v9fs_session_info *v9ses)
 {
-	if (v9ses->mux) {
-		v9fs_mux_destroy(v9ses->mux);
-		v9ses->mux = NULL;
-	}
-
-	if (v9ses->transport) {
-		v9ses->transport->close(v9ses->transport);
-		kfree(v9ses->transport);
-		v9ses->transport = NULL;
+	if (v9ses->clnt) {
+		p9_client_destroy(v9ses->clnt);
+		v9ses->clnt = NULL;
 	}
 
 	__putname(v9ses->name);
@@ -446,9 +297,8 @@
  * 	and cancel all pending requests.
  */
 void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
-	dprintk(DEBUG_ERROR, "cancel session %p\n", v9ses);
-	v9ses->transport->status = Disconnected;
-	v9fs_mux_cancel(v9ses->mux, -EIO);
+	P9_DPRINTK(P9_DEBUG_ERROR, "cancel session %p\n", v9ses);
+	p9_client_disconnect(v9ses->clnt);
 }
 
 extern int v9fs_error_init(void);
@@ -460,24 +310,9 @@
 
 static int __init init_v9fs(void)
 {
-	int ret;
-
-	v9fs_error_init();
-
 	printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");
 
-	ret = v9fs_mux_global_init();
-	if (ret) {
-		printk(KERN_WARNING "v9fs: starting mux failed\n");
-		return ret;
-	}
-	ret = register_filesystem(&v9fs_fs_type);
-	if (ret) {
-		printk(KERN_WARNING "v9fs: registering file system failed\n");
-		v9fs_mux_global_exit();
-	}
-
-	return ret;
+	return register_filesystem(&v9fs_fs_type);
 }
 
 /**
@@ -487,13 +322,13 @@
 
 static void __exit exit_v9fs(void)
 {
-	v9fs_mux_global_exit();
 	unregister_filesystem(&v9fs_fs_type);
 }
 
 module_init(init_v9fs)
 module_exit(exit_v9fs)
 
+MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
 MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
 MODULE_LICENSE("GPL");
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 820bf5ca..abc4b16 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -22,16 +22,6 @@
  */
 
 /*
-  * Idpool structure provides lock and id management
-  *
-  */
-
-struct v9fs_idpool {
-	struct semaphore lock;
-	struct idr pool;
-};
-
-/*
   * Session structure provides information for an opened session
   *
   */
@@ -54,15 +44,7 @@
 	unsigned int uid;	/* default uid/muid for legacy support */
 	unsigned int gid;	/* default gid for legacy support */
 
-	/* book keeping */
-	struct v9fs_idpool fidpool;	/* The FID pool for file descriptors */
-
-	struct v9fs_transport *transport;
-	struct v9fs_mux_data *mux;
-
-	int inprogress;		/* session in progress => true */
-	int shutdown;		/* session shutting down. no more attaches. */
-	unsigned char session_hung;
+	struct p9_client *clnt;	/* 9p client */
 	struct dentry *debugfs_dir;
 };
 
@@ -71,6 +53,7 @@
 	PROTO_TCP,
 	PROTO_UNIX,
 	PROTO_FD,
+	PROTO_PCI,
 };
 
 /* possible values of ->cache */
@@ -82,12 +65,9 @@
 
 extern struct dentry *v9fs_debugfs_root;
 
-int v9fs_session_init(struct v9fs_session_info *, const char *, char *);
-struct v9fs_session_info *v9fs_inode2v9ses(struct inode *);
+struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
+									char *);
 void v9fs_session_close(struct v9fs_session_info *v9ses);
-int v9fs_get_idpool(struct v9fs_idpool *p);
-void v9fs_put_idpool(int id, struct v9fs_idpool *p);
-int v9fs_check_idpool(int id, struct v9fs_idpool *p);
 void v9fs_session_cancel(struct v9fs_session_info *v9ses);
 
 #define V9FS_MAGIC 0x01021997
@@ -97,3 +77,7 @@
 #define V9FS_DEFUSER	"nobody"
 #define V9FS_DEFANAME	""
 
+static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
+{
+	return (inode->i_sb->s_fs_info);
+}
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 6a82d39..fd01d90 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -45,10 +45,10 @@
 extern struct dentry_operations v9fs_cached_dentry_operations;
 
 struct inode *v9fs_get_inode(struct super_block *sb, int mode);
-ino_t v9fs_qid2ino(struct v9fs_qid *qid);
-void v9fs_stat2inode(struct v9fs_stat *, struct inode *, struct super_block *);
+ino_t v9fs_qid2ino(struct p9_qid *qid);
+void v9fs_stat2inode(struct p9_stat *, struct inode *, struct super_block *);
 int v9fs_dir_release(struct inode *inode, struct file *filp);
 int v9fs_file_open(struct inode *inode, struct file *file);
-void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat);
+void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat);
 void v9fs_dentry_release(struct dentry *);
 int v9fs_uflags2omode(int uflags);
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 3128aa9..6248f0e 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -32,10 +32,11 @@
 #include <linux/inet.h>
 #include <linux/pagemap.h>
 #include <linux/idr.h>
+#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
 
-#include "debug.h"
 #include "v9fs.h"
-#include "9p.h"
 #include "v9fs_vfs.h"
 #include "fid.h"
 
@@ -49,55 +50,26 @@
 
 static int v9fs_vfs_readpage(struct file *filp, struct page *page)
 {
-	char *buffer = NULL;
-	int retval = -EIO;
-	loff_t offset = page_offset(page);
-	int count = PAGE_CACHE_SIZE;
-	struct inode *inode = filp->f_path.dentry->d_inode;
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-	int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
-	struct v9fs_fid *v9f = filp->private_data;
-	struct v9fs_fcall *fcall = NULL;
-	int fid = v9f->fid;
-	int total = 0;
-	int result = 0;
+	int retval;
+	loff_t offset;
+	char *buffer;
+	struct p9_fid *fid;
 
-	dprintk(DEBUG_VFS, "\n");
-
+	P9_DPRINTK(P9_DEBUG_VFS, "\n");
+	fid = filp->private_data;
 	buffer = kmap(page);
-	do {
-		if (count < rsize)
-			rsize = count;
+	offset = page_offset(page);
 
-		result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall);
+	retval = p9_client_readn(fid, buffer, offset, PAGE_CACHE_SIZE);
+	if (retval < 0)
+		goto done;
 
-		if (result < 0) {
-			printk(KERN_ERR "v9fs_t_read returned %d\n",
-			       result);
-
-			kfree(fcall);
-			goto UnmapAndUnlock;
-		} else
-			offset += result;
-
-		memcpy(buffer, fcall->params.rread.data, result);
-
-		count -= result;
-		buffer += result;
-		total += result;
-
-		kfree(fcall);
-
-		if (result < rsize)
-			break;
-	} while (count);
-
-	memset(buffer, 0, count);
+	memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval);
 	flush_dcache_page(page);
 	SetPageUptodate(page);
 	retval = 0;
 
-UnmapAndUnlock:
+done:
 	kunmap(page);
 	unlock_page(page);
 	return retval;
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 775e26e..f9534f1 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -33,10 +33,11 @@
 #include <linux/inet.h>
 #include <linux/namei.h>
 #include <linux/idr.h>
+#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
 
-#include "debug.h"
 #include "v9fs.h"
-#include "9p.h"
 #include "v9fs_vfs.h"
 #include "fid.h"
 
@@ -51,7 +52,7 @@
 
 static int v9fs_dentry_delete(struct dentry *dentry)
 {
-	dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
 
 	return 1;
 }
@@ -68,7 +69,7 @@
 static int v9fs_cached_dentry_delete(struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
-	dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
 
 	if(!inode)
 		return 1;
@@ -84,26 +85,19 @@
 
 void v9fs_dentry_release(struct dentry *dentry)
 {
-	int err;
+	struct v9fs_dentry *dent;
+	struct p9_fid *temp, *current_fid;
 
-	dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
-
-	if (dentry->d_fsdata != NULL) {
-		struct list_head *fid_list = dentry->d_fsdata;
-		struct v9fs_fid *temp = NULL;
-		struct v9fs_fid *current_fid = NULL;
-
-		list_for_each_entry_safe(current_fid, temp, fid_list, list) {
-			err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid);
-
-			if (err < 0)
-				dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n",
-					err, dentry->d_iname);
-
-			v9fs_fid_destroy(current_fid);
+	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+	dent = dentry->d_fsdata;
+	if (dent) {
+		list_for_each_entry_safe(current_fid, temp, &dent->fidlist,
+									dlist) {
+			p9_client_clunk(current_fid);
 		}
 
-		kfree(dentry->d_fsdata);	/* free the list_head */
+		kfree(dent);
+		dentry->d_fsdata = NULL;
 	}
 }
 
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 1dd86ee..0924d44 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -32,11 +32,10 @@
 #include <linux/sched.h>
 #include <linux/inet.h>
 #include <linux/idr.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
 
-#include "debug.h"
 #include "v9fs.h"
-#include "9p.h"
-#include "conv.h"
 #include "v9fs_vfs.h"
 #include "fid.h"
 
@@ -46,14 +45,14 @@
  *
  */
 
-static inline int dt_type(struct v9fs_stat *mistat)
+static inline int dt_type(struct p9_stat *mistat)
 {
 	unsigned long perm = mistat->mode;
 	int rettype = DT_REG;
 
-	if (perm & V9FS_DMDIR)
+	if (perm & P9_DMDIR)
 		rettype = DT_DIR;
-	if (perm & V9FS_DMSYMLINK)
+	if (perm & P9_DMSYMLINK)
 		rettype = DT_LNK;
 
 	return rettype;
@@ -69,106 +68,36 @@
 
 static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-	struct v9fs_fcall *fcall = NULL;
-	struct inode *inode = filp->f_path.dentry->d_inode;
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-	struct v9fs_fid *file = filp->private_data;
-	unsigned int i, n, s;
-	int fid = -1;
-	int ret = 0;
-	struct v9fs_stat stat;
-	int over = 0;
+	int over;
+	struct p9_fid *fid;
+	struct v9fs_session_info *v9ses;
+	struct inode *inode;
+	struct p9_stat *st;
 
-	dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
+	P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
+	inode = filp->f_path.dentry->d_inode;
+	v9ses = v9fs_inode2v9ses(inode);
+	fid = filp->private_data;
+	while ((st = p9_client_dirread(fid, filp->f_pos)) != NULL) {
+		if (IS_ERR(st))
+			return PTR_ERR(st);
 
-	fid = file->fid;
+		over = filldir(dirent, st->name.str, st->name.len, filp->f_pos,
+			v9fs_qid2ino(&st->qid), dt_type(st));
 
-	if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) {
-		kfree(file->rdir_fcall);
-		file->rdir_fcall = NULL;
-	}
-
-	if (file->rdir_fcall) {
-		n = file->rdir_fcall->params.rread.count;
-		i = file->rdir_fpos;
-		while (i < n) {
-			s = v9fs_deserialize_stat(
-				file->rdir_fcall->params.rread.data + i,
-				n - i, &stat, v9ses->extended);
-
-			if (s == 0) {
-				dprintk(DEBUG_ERROR,
-					"error while deserializing stat\n");
-				ret = -EIO;
-				goto FreeStructs;
-			}
-
-			over = filldir(dirent, stat.name.str, stat.name.len,
-				    filp->f_pos, v9fs_qid2ino(&stat.qid),
-				    dt_type(&stat));
-
-			if (over) {
-				file->rdir_fpos = i;
-				file->rdir_pos = filp->f_pos;
-				break;
-			}
-
-			i += s;
-			filp->f_pos += s;
-		}
-
-		if (!over) {
-			kfree(file->rdir_fcall);
-			file->rdir_fcall = NULL;
-		}
-	}
-
-	while (!over) {
-		ret = v9fs_t_read(v9ses, fid, filp->f_pos,
-			v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
-		if (ret < 0) {
-			dprintk(DEBUG_ERROR, "error while reading: %d: %p\n",
-				ret, fcall);
-			goto FreeStructs;
-		} else if (ret == 0)
+		if (over)
 			break;
 
-		n = ret;
-		i = 0;
-		while (i < n) {
-			s = v9fs_deserialize_stat(fcall->params.rread.data + i,
-				n - i, &stat, v9ses->extended);
-
-			if (s == 0) {
-				dprintk(DEBUG_ERROR,
-					"error while deserializing stat\n");
-				return -EIO;
-			}
-
-			over = filldir(dirent, stat.name.str, stat.name.len,
-				    filp->f_pos, v9fs_qid2ino(&stat.qid),
-				    dt_type(&stat));
-
-			if (over) {
-				file->rdir_fcall = fcall;
-				file->rdir_fpos = i;
-				file->rdir_pos = filp->f_pos;
-				fcall = NULL;
-				break;
-			}
-
-			i += s;
-			filp->f_pos += s;
-		}
-
-		kfree(fcall);
+		filp->f_pos += st->size;
+		kfree(st);
+		st = NULL;
 	}
 
-      FreeStructs:
-	kfree(fcall);
-	return ret;
+	kfree(st);
+	return 0;
 }
 
+
 /**
  * v9fs_dir_release - close a directory
  * @inode: inode of the directory
@@ -178,29 +107,13 @@
 
 int v9fs_dir_release(struct inode *inode, struct file *filp)
 {
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-	struct v9fs_fid *fid = filp->private_data;
-	int fidnum = -1;
+	struct p9_fid *fid;
 
-	dprintk(DEBUG_VFS, "inode: %p filp: %p fid: %d\n", inode, filp,
-		fid->fid);
-	fidnum = fid->fid;
-
+	fid = filp->private_data;
+	P9_DPRINTK(P9_DEBUG_VFS,
+			"inode: %p filp: %p fid: %d\n", inode, filp, fid->fid);
 	filemap_write_and_wait(inode->i_mapping);
-
-	if (fidnum >= 0) {
-		dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen,
-			fid->fid);
-
-		if (v9fs_t_clunk(v9ses, fidnum))
-			dprintk(DEBUG_ERROR, "clunk failed\n");
-
-		kfree(fid->rdir_fcall);
-		kfree(fid);
-
-		filp->private_data = NULL;
-	}
-
+	p9_client_clunk(fid);
 	return 0;
 }
 
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 6e7678e..2a40c29 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -34,10 +34,10 @@
 #include <linux/list.h>
 #include <asm/uaccess.h>
 #include <linux/idr.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
 
-#include "debug.h"
 #include "v9fs.h"
-#include "9p.h"
 #include "v9fs_vfs.h"
 #include "fid.h"
 
@@ -52,48 +52,40 @@
 
 int v9fs_file_open(struct inode *inode, struct file *file)
 {
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-	struct v9fs_fid *vfid;
-	struct v9fs_fcall *fcall = NULL;
-	int omode;
 	int err;
+	struct v9fs_session_info *v9ses;
+	struct p9_fid *fid;
+	int omode;
 
-	dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
-
-	vfid = v9fs_fid_clone(file->f_path.dentry);
-	if (IS_ERR(vfid))
-		return PTR_ERR(vfid);
-
+	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file);
+	v9ses = v9fs_inode2v9ses(inode);
 	omode = v9fs_uflags2omode(file->f_flags);
-	err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall);
-	if (err < 0) {
-		PRINT_FCALL_ERROR("open failed", fcall);
-		goto Clunk_Fid;
+	fid = file->private_data;
+	if (!fid) {
+		fid = v9fs_fid_clone(file->f_path.dentry);
+		if (IS_ERR(fid))
+			return PTR_ERR(fid);
+
+		err = p9_client_open(fid, omode);
+		if (err < 0) {
+			p9_client_clunk(fid);
+			return err;
+		}
+		if (omode & P9_OTRUNC) {
+			inode->i_size = 0;
+			inode->i_blocks = 0;
+		}
 	}
 
-	file->private_data = vfid;
-	vfid->fidopen = 1;
-	vfid->fidclunked = 0;
-	vfid->iounit = fcall->params.ropen.iounit;
-	vfid->rdir_pos = 0;
-	vfid->rdir_fcall = NULL;
-	vfid->filp = file;
-	kfree(fcall);
-
-	if((vfid->qid.version) && (v9ses->cache)) {
-		dprintk(DEBUG_VFS, "cached");
+	file->private_data = fid;
+	if ((fid->qid.version) && (v9ses->cache)) {
+		P9_DPRINTK(P9_DEBUG_VFS, "cached");
 		/* enable cached file options */
 		if(file->f_op == &v9fs_file_operations)
 			file->f_op = &v9fs_cached_file_operations;
 	}
 
 	return 0;
-
-Clunk_Fid:
-	v9fs_fid_clunk(v9ses, vfid);
-	kfree(fcall);
-
-	return err;
 }
 
 /**
@@ -110,7 +102,7 @@
 	int res = 0;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 
-	dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
+	P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
 
 	/* No mandatory locks */
 	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
@@ -136,55 +128,16 @@
 v9fs_file_read(struct file *filp, char __user * data, size_t count,
 	       loff_t * offset)
 {
-	struct inode *inode = filp->f_path.dentry->d_inode;
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-	struct v9fs_fid *v9f = filp->private_data;
-	struct v9fs_fcall *fcall = NULL;
-	int fid = v9f->fid;
-	int rsize = 0;
-	int result = 0;
-	int total = 0;
-	int n;
+	int ret;
+	struct p9_fid *fid;
 
-	dprintk(DEBUG_VFS, "\n");
+	P9_DPRINTK(P9_DEBUG_VFS, "\n");
+	fid = filp->private_data;
+	ret = p9_client_uread(fid, data, *offset, count);
+	if (ret > 0)
+		*offset += ret;
 
-	rsize = v9ses->maxdata - V9FS_IOHDRSZ;
-	if (v9f->iounit != 0 && rsize > v9f->iounit)
-		rsize = v9f->iounit;
-
-	do {
-		if (count < rsize)
-			rsize = count;
-
-		result = v9fs_t_read(v9ses, fid, *offset, rsize, &fcall);
-
-		if (result < 0) {
-			printk(KERN_ERR "9P2000: v9fs_t_read returned %d\n",
-			       result);
-
-			kfree(fcall);
-			return total;
-		} else
-			*offset += result;
-
-		n = copy_to_user(data, fcall->params.rread.data, result);
-		if (n) {
-			dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n);
-			kfree(fcall);
-			return -EFAULT;
-		}
-
-		count -= result;
-		data += result;
-		total += result;
-
-		kfree(fcall);
-
-		if (result < rsize)
-			break;
-	} while (count);
-
-	return total;
+	return ret;
 }
 
 /**
@@ -200,50 +153,25 @@
 v9fs_file_write(struct file *filp, const char __user * data,
 		size_t count, loff_t * offset)
 {
+	int ret;
+	struct p9_fid *fid;
 	struct inode *inode = filp->f_path.dentry->d_inode;
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-	struct v9fs_fid *v9fid = filp->private_data;
-	struct v9fs_fcall *fcall;
-	int fid = v9fid->fid;
-	int result = -EIO;
-	int rsize = 0;
-	int total = 0;
 
-	dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count,
-		(int)*offset);
-	rsize = v9ses->maxdata - V9FS_IOHDRSZ;
-	if (v9fid->iounit != 0 && rsize > v9fid->iounit)
-		rsize = v9fid->iounit;
+	P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
+		(int)count, (int)*offset);
 
-	do {
-		if (count < rsize)
-			rsize = count;
+	fid = filp->private_data;
+	ret = p9_client_uwrite(fid, data, *offset, count);
+	if (ret > 0)
+		*offset += ret;
 
-		result = v9fs_t_write(v9ses, fid, *offset, rsize, data, &fcall);
-		if (result < 0) {
-			PRINT_FCALL_ERROR("error while writing", fcall);
-			kfree(fcall);
-			return result;
-		} else
-			*offset += result;
-
-		kfree(fcall);
-		fcall = NULL;
-
-		if (result != rsize) {
-			eprintk(KERN_ERR,
-				"short write: v9fs_t_write returned %d\n",
-				result);
-			break;
-		}
-
-		count -= result;
-		data += result;
-		total += result;
-	} while (count);
+	if (*offset > inode->i_size) {
+		inode->i_size = *offset;
+		inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
+	}
 
 	invalidate_inode_pages2(inode->i_mapping);
-	return total;
+	return ret;
 }
 
 static const struct file_operations v9fs_cached_file_operations = {
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 7624821..e5c45ee 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -33,10 +33,11 @@
 #include <linux/inet.h>
 #include <linux/namei.h>
 #include <linux/idr.h>
+#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
 
-#include "debug.h"
 #include "v9fs.h"
-#include "9p.h"
 #include "v9fs_vfs.h"
 #include "fid.h"
 
@@ -57,27 +58,27 @@
 	int res;
 	res = mode & 0777;
 	if (S_ISDIR(mode))
-		res |= V9FS_DMDIR;
+		res |= P9_DMDIR;
 	if (v9ses->extended) {
 		if (S_ISLNK(mode))
-			res |= V9FS_DMSYMLINK;
+			res |= P9_DMSYMLINK;
 		if (v9ses->nodev == 0) {
 			if (S_ISSOCK(mode))
-				res |= V9FS_DMSOCKET;
+				res |= P9_DMSOCKET;
 			if (S_ISFIFO(mode))
-				res |= V9FS_DMNAMEDPIPE;
+				res |= P9_DMNAMEDPIPE;
 			if (S_ISBLK(mode))
-				res |= V9FS_DMDEVICE;
+				res |= P9_DMDEVICE;
 			if (S_ISCHR(mode))
-				res |= V9FS_DMDEVICE;
+				res |= P9_DMDEVICE;
 		}
 
 		if ((mode & S_ISUID) == S_ISUID)
-			res |= V9FS_DMSETUID;
+			res |= P9_DMSETUID;
 		if ((mode & S_ISGID) == S_ISGID)
-			res |= V9FS_DMSETGID;
-		if ((mode & V9FS_DMLINK))
-			res |= V9FS_DMLINK;
+			res |= P9_DMSETGID;
+		if ((mode & P9_DMLINK))
+			res |= P9_DMLINK;
 	}
 
 	return res;
@@ -96,27 +97,27 @@
 
 	res = mode & 0777;
 
-	if ((mode & V9FS_DMDIR) == V9FS_DMDIR)
+	if ((mode & P9_DMDIR) == P9_DMDIR)
 		res |= S_IFDIR;
-	else if ((mode & V9FS_DMSYMLINK) && (v9ses->extended))
+	else if ((mode & P9_DMSYMLINK) && (v9ses->extended))
 		res |= S_IFLNK;
-	else if ((mode & V9FS_DMSOCKET) && (v9ses->extended)
+	else if ((mode & P9_DMSOCKET) && (v9ses->extended)
 		 && (v9ses->nodev == 0))
 		res |= S_IFSOCK;
-	else if ((mode & V9FS_DMNAMEDPIPE) && (v9ses->extended)
+	else if ((mode & P9_DMNAMEDPIPE) && (v9ses->extended)
 		 && (v9ses->nodev == 0))
 		res |= S_IFIFO;
-	else if ((mode & V9FS_DMDEVICE) && (v9ses->extended)
+	else if ((mode & P9_DMDEVICE) && (v9ses->extended)
 		 && (v9ses->nodev == 0))
 		res |= S_IFBLK;
 	else
 		res |= S_IFREG;
 
 	if (v9ses->extended) {
-		if ((mode & V9FS_DMSETUID) == V9FS_DMSETUID)
+		if ((mode & P9_DMSETUID) == P9_DMSETUID)
 			res |= S_ISUID;
 
-		if ((mode & V9FS_DMSETGID) == V9FS_DMSETGID)
+		if ((mode & P9_DMSETGID) == P9_DMSETGID)
 			res |= S_ISGID;
 	}
 
@@ -131,26 +132,26 @@
 	switch (uflags&3) {
 	default:
 	case O_RDONLY:
-		ret = V9FS_OREAD;
+		ret = P9_OREAD;
 		break;
 
 	case O_WRONLY:
-		ret = V9FS_OWRITE;
+		ret = P9_OWRITE;
 		break;
 
 	case O_RDWR:
-		ret = V9FS_ORDWR;
+		ret = P9_ORDWR;
 		break;
 	}
 
 	if (uflags & O_EXCL)
-		ret |= V9FS_OEXCL;
+		ret |= P9_OEXCL;
 
 	if (uflags & O_TRUNC)
-		ret |= V9FS_OTRUNC;
+		ret |= P9_OTRUNC;
 
 	if (uflags & O_APPEND)
-		ret |= V9FS_OAPPEND;
+		ret |= P9_OAPPEND;
 
 	return ret;
 }
@@ -163,7 +164,7 @@
  */
 
 static void
-v9fs_blank_wstat(struct v9fs_wstat *wstat)
+v9fs_blank_wstat(struct p9_wstat *wstat)
 {
 	wstat->type = ~0;
 	wstat->dev = ~0;
@@ -196,7 +197,7 @@
 	struct inode *inode;
 	struct v9fs_session_info *v9ses = sb->s_fs_info;
 
-	dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
+	P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
 
 	inode = new_inode(sb);
 	if (inode) {
@@ -214,7 +215,8 @@
 		case S_IFCHR:
 		case S_IFSOCK:
 			if(!v9ses->extended) {
-				dprintk(DEBUG_ERROR, "special files without extended mode\n");
+				P9_DPRINTK(P9_DEBUG_ERROR,
+				      "special files without extended mode\n");
 				return ERR_PTR(-EINVAL);
 			}
 			init_special_inode(inode, inode->i_mode,
@@ -226,7 +228,8 @@
 			break;
 		case S_IFLNK:
 			if(!v9ses->extended) {
-				dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n");
+				P9_DPRINTK(P9_DEBUG_ERROR,
+					"extended modes used w/o 9P2000.u\n");
 				return ERR_PTR(-EINVAL);
 			}
 			inode->i_op = &v9fs_symlink_inode_operations;
@@ -240,71 +243,19 @@
 			inode->i_fop = &v9fs_dir_operations;
 			break;
 		default:
-			dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
+			P9_DPRINTK(P9_DEBUG_ERROR,
+				"BAD mode 0x%x S_IFMT 0x%x\n",
 				mode, mode & S_IFMT);
 			return ERR_PTR(-EINVAL);
 		}
 	} else {
-		eprintk(KERN_WARNING, "Problem allocating inode\n");
+		P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	return inode;
 }
 
-static int
-v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
-	u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
-{
-	int fid;
-	int err;
-	struct v9fs_fcall *fcall;
-
-	fid = v9fs_get_idpool(&v9ses->fidpool);
-	if (fid < 0) {
-		eprintk(KERN_WARNING, "no free fids available\n");
-		return -ENOSPC;
-	}
-
-	err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
-	if (err < 0) {
-		PRINT_FCALL_ERROR("clone error", fcall);
-		if (fcall && fcall->id == RWALK)
-			goto clunk_fid;
-		else
-			goto put_fid;
-	}
-	kfree(fcall);
-
-	err = v9fs_t_create(v9ses, fid, name, perm, mode, extension, &fcall);
-	if (err < 0) {
-		PRINT_FCALL_ERROR("create fails", fcall);
-		goto clunk_fid;
-	}
-
-	if (iounit)
-		*iounit = fcall->params.rcreate.iounit;
-
-	if (qid)
-		*qid = fcall->params.rcreate.qid;
-
-	if (fidp)
-		*fidp = fid;
-
-	kfree(fcall);
-	return 0;
-
-clunk_fid:
-	v9fs_t_clunk(v9ses, fid);
-	fid = V9FS_NOFID;
-
-put_fid:
-	if (fid != V9FS_NOFID)
-		v9fs_put_idpool(fid, &v9ses->fidpool);
-
-	kfree(fcall);
-	return err;
-}
-
+/*
 static struct v9fs_fid*
 v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
 {
@@ -354,23 +305,25 @@
 	kfree(fcall);
 	return ERR_PTR(err);
 }
+*/
 
 static struct inode *
-v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
+v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
 	struct super_block *sb)
 {
 	int err, umode;
 	struct inode *ret;
-	struct v9fs_fcall *fcall;
+	struct p9_stat *st;
 
 	ret = NULL;
-	err = v9fs_t_stat(v9ses, fid, &fcall);
-	if (err) {
-		PRINT_FCALL_ERROR("stat error", fcall);
+	st = p9_client_stat(fid);
+	if (IS_ERR(st)) {
+		err = PTR_ERR(st);
+		st = NULL;
 		goto error;
 	}
 
-	umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode);
+	umode = p9mode2unixmode(v9ses, st->mode);
 	ret = v9fs_get_inode(sb, umode);
 	if (IS_ERR(ret)) {
 		err = PTR_ERR(ret);
@@ -378,12 +331,13 @@
 		goto error;
 	}
 
-	v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb);
-	kfree(fcall);
+	v9fs_stat2inode(st, ret, sb);
+	ret->i_ino = v9fs_qid2ino(&st->qid);
+	kfree(st);
 	return ret;
 
 error:
-	kfree(fcall);
+	kfree(st);
 	if (ret)
 		iput(ret);
 
@@ -400,43 +354,20 @@
 
 static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
 {
-	struct v9fs_fcall *fcall = NULL;
-	struct super_block *sb = NULL;
-	struct v9fs_session_info *v9ses = NULL;
-	struct v9fs_fid *v9fid = NULL;
-	struct inode *file_inode = NULL;
-	int fid = -1;
-	int result = 0;
+	struct inode *file_inode;
+	struct v9fs_session_info *v9ses;
+	struct p9_fid *v9fid;
 
-	dprintk(DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
+	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
 		rmdir);
 
 	file_inode = file->d_inode;
-	sb = file_inode->i_sb;
 	v9ses = v9fs_inode2v9ses(file_inode);
 	v9fid = v9fs_fid_clone(file);
 	if(IS_ERR(v9fid))
 		return PTR_ERR(v9fid);
 
-	fid = v9fid->fid;
-	if (fid < 0) {
-		dprintk(DEBUG_ERROR, "inode #%lu, no fid!\n",
-			file_inode->i_ino);
-		return -EBADF;
-	}
-
-	result = v9fs_t_remove(v9ses, fid, &fcall);
-	if (result < 0) {
-		PRINT_FCALL_ERROR("remove fails", fcall);
-		goto Error;
-	}
-
-	v9fs_put_idpool(fid, &v9ses->fidpool);
-	v9fs_fid_destroy(v9fid);
-
-Error:
-	kfree(fcall);
-	return result;
+	return p9_client_remove(v9fid);
 }
 
 static int
@@ -445,9 +376,87 @@
 	return 0;
 }
 
+
+/**
+ * v9fs_create - Create a file
+ * @dentry:  dentry that is being created
+ * @perm: create permissions
+ * @mode: open mode
+ *
+ */
+static struct p9_fid *
+v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
+		struct dentry *dentry, char *extension, u32 perm, u8 mode)
+{
+	int err;
+	char *name;
+	struct p9_fid *dfid, *ofid, *fid;
+	struct inode *inode;
+
+	err = 0;
+	ofid = NULL;
+	fid = NULL;
+	name = (char *) dentry->d_name.name;
+	dfid = v9fs_fid_clone(dentry->d_parent);
+	if(IS_ERR(dfid)) {
+		err = PTR_ERR(dfid);
+		dfid = NULL;
+		goto error;
+	}
+
+	/* clone a fid to use for creation */
+	ofid = p9_client_walk(dfid, 0, NULL, 1);
+	if (IS_ERR(ofid)) {
+		err = PTR_ERR(ofid);
+		ofid = NULL;
+		goto error;
+	}
+
+	err = p9_client_fcreate(ofid, name, perm, mode, extension);
+	if (err < 0)
+		goto error;
+
+	/* now walk from the parent so we can get unopened fid */
+	fid = p9_client_walk(dfid, 1, &name, 0);
+	if (IS_ERR(fid)) {
+		err = PTR_ERR(fid);
+		fid = NULL;
+		goto error;
+	} else
+		dfid = NULL;
+
+	/* instantiate inode and assign the unopened fid to the dentry */
+	inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		goto error;
+	}
+
+	if(v9ses->cache)
+		dentry->d_op = &v9fs_cached_dentry_operations;
+	else
+		dentry->d_op = &v9fs_dentry_operations;
+
+	d_instantiate(dentry, inode);
+	v9fs_fid_add(dentry, fid);
+	return ofid;
+
+error:
+	if (dfid)
+		p9_client_clunk(dfid);
+
+	if (ofid)
+		p9_client_clunk(ofid);
+
+	if (fid)
+		p9_client_clunk(fid);
+
+	return ERR_PTR(err);
+}
+
 /**
  * v9fs_vfs_create - VFS hook to create files
- * @inode: directory inode that is being deleted
+ * @inode: directory inode that is being created
  * @dentry:  dentry that is being deleted
  * @mode: create permissions
  * @nd: path information
@@ -459,83 +468,46 @@
 		struct nameidata *nd)
 {
 	int err;
-	u32 fid, perm, iounit;
+	u32 perm;
 	int flags;
 	struct v9fs_session_info *v9ses;
-	struct v9fs_fid *dfid, *vfid, *ffid;
-	struct inode *inode;
-	struct v9fs_qid qid;
+	struct p9_fid *fid;
 	struct file *filp;
 
-	inode = NULL;
-	vfid = NULL;
+	err = 0;
+	fid = NULL;
 	v9ses = v9fs_inode2v9ses(dir);
-	dfid = v9fs_fid_clone(dentry->d_parent);
-	if(IS_ERR(dfid)) {
-		err = PTR_ERR(dfid);
-		goto error;
-	}
-
 	perm = unixmode2p9mode(v9ses, mode);
 	if (nd && nd->flags & LOOKUP_OPEN)
 		flags = nd->intent.open.flags - 1;
 	else
 		flags = O_RDWR;
 
-	err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
-		perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
-
-	if (err)
-		goto clunk_dfid;
-
-	vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
-	v9fs_fid_clunk(v9ses, dfid);
-	if (IS_ERR(vfid)) {
-		err = PTR_ERR(vfid);
-		vfid = NULL;
+	fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
+						v9fs_uflags2omode(flags));
+	if (IS_ERR(fid)) {
+		err = PTR_ERR(fid);
+		fid = NULL;
 		goto error;
 	}
 
-	inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
-	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
-		inode = NULL;
-		goto error;
-	}
-
-	if(v9ses->cache)
-		dentry->d_op = &v9fs_cached_dentry_operations;
-	else
-		dentry->d_op = &v9fs_dentry_operations;
-	d_instantiate(dentry, inode);
-
+	/* if we are opening a file, assign the open fid to the file */
 	if (nd && nd->flags & LOOKUP_OPEN) {
-		ffid = v9fs_fid_create(v9ses, fid);
-		if (!ffid)
-			return -ENOMEM;
-
 		filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
 		if (IS_ERR(filp)) {
-			v9fs_fid_destroy(ffid);
-			return PTR_ERR(filp);
+			err = PTR_ERR(filp);
+			goto error;
 		}
 
-		ffid->rdir_pos = 0;
-		ffid->rdir_fcall = NULL;
-		ffid->fidopen = 1;
-		ffid->iounit = iounit;
-		ffid->filp = filp;
-		filp->private_data = ffid;
-	}
+		filp->private_data = fid;
+	} else
+		p9_client_clunk(fid);
 
 	return 0;
 
-clunk_dfid:
-	v9fs_fid_clunk(v9ses, dfid);
-
 error:
-	if (vfid)
-		v9fs_fid_destroy(vfid);
+	if (fid)
+		p9_client_clunk(fid);
 
 	return err;
 }
@@ -551,57 +523,23 @@
 static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int err;
-	u32 fid, perm;
+	u32 perm;
 	struct v9fs_session_info *v9ses;
-	struct v9fs_fid *dfid, *vfid;
-	struct inode *inode;
+	struct p9_fid *fid;
 
-	inode = NULL;
-	vfid = NULL;
+	P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
+	err = 0;
 	v9ses = v9fs_inode2v9ses(dir);
-	dfid = v9fs_fid_clone(dentry->d_parent);
-	if(IS_ERR(dfid)) {
-		err = PTR_ERR(dfid);
-		goto error;
-	}
-
 	perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
-
-	err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
-		perm, V9FS_OREAD, NULL, &fid, NULL, NULL);
-
-	if (err) {
-		dprintk(DEBUG_ERROR, "create error %d\n", err);
-		goto clean_up_dfid;
+	fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
+	if (IS_ERR(fid)) {
+		err = PTR_ERR(fid);
+		fid = NULL;
 	}
 
-	vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
-	if (IS_ERR(vfid)) {
-		err = PTR_ERR(vfid);
-		vfid = NULL;
-		goto clean_up_dfid;
-	}
+	if (fid)
+		p9_client_clunk(fid);
 
-	v9fs_fid_clunk(v9ses, dfid);
-	inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
-	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
-		inode = NULL;
-		v9fs_fid_destroy(vfid);
-		goto error;
-	}
-
-	if(v9ses->cache)
-		dentry->d_op = &v9fs_cached_dentry_operations;
-	else
-		dentry->d_op = &v9fs_dentry_operations;
-	d_instantiate(dentry, inode);
-	return 0;
-
-clean_up_dfid:
-	v9fs_fid_clunk(v9ses, dfid);
-
-error:
 	return err;
 }
 
@@ -618,104 +556,54 @@
 {
 	struct super_block *sb;
 	struct v9fs_session_info *v9ses;
-	struct v9fs_fid *dirfid;
-	struct v9fs_fid *fid;
+	struct p9_fid *dfid, *fid;
 	struct inode *inode;
-	struct v9fs_fcall *fcall = NULL;
-	int dirfidnum = -1;
-	int newfid = -1;
+	char *name;
 	int result = 0;
 
-	dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
+	P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
 		dir, dentry->d_name.name, dentry, nameidata);
 
 	sb = dir->i_sb;
 	v9ses = v9fs_inode2v9ses(dir);
-	dirfid = v9fs_fid_lookup(dentry->d_parent);
+	dfid = v9fs_fid_lookup(dentry->d_parent);
+	if (IS_ERR(dfid))
+		return ERR_PTR(PTR_ERR(dfid));
 
-	if(IS_ERR(dirfid))
-		return ERR_PTR(PTR_ERR(dirfid));
-
-	dirfidnum = dirfid->fid;
-
-	newfid = v9fs_get_idpool(&v9ses->fidpool);
-	if (newfid < 0) {
-		eprintk(KERN_WARNING, "newfid fails!\n");
-		result = -ENOSPC;
-		goto Release_Dirfid;
-	}
-
-	result = v9fs_t_walk(v9ses, dirfidnum, newfid,
-		(char *)dentry->d_name.name, &fcall);
-
-	up(&dirfid->lock);
-
-	if (result < 0) {
-		if (fcall && fcall->id == RWALK)
-			v9fs_t_clunk(v9ses, newfid);
-		else
-			v9fs_put_idpool(newfid, &v9ses->fidpool);
-
+	name = (char *) dentry->d_name.name;
+	fid = p9_client_walk(dfid, 1, &name, 1);
+	if (IS_ERR(fid)) {
+		result = PTR_ERR(fid);
 		if (result == -ENOENT) {
 			d_add(dentry, NULL);
-			dprintk(DEBUG_VFS,
-				"Return negative dentry %p count %d\n",
-				dentry, atomic_read(&dentry->d_count));
-			kfree(fcall);
 			return NULL;
 		}
-		dprintk(DEBUG_ERROR, "walk error:%d\n", result);
-		goto FreeFcall;
-	}
-	kfree(fcall);
 
-	result = v9fs_t_stat(v9ses, newfid, &fcall);
-	if (result < 0) {
-		dprintk(DEBUG_ERROR, "stat error\n");
-		goto FreeFcall;
+		return ERR_PTR(result);
 	}
 
-	inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses,
-		fcall->params.rstat.stat.mode));
-
-	if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) {
-		eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n",
-			PTR_ERR(inode));
-
-		result = -ENOSPC;
-		goto FreeFcall;
+	inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+	if (IS_ERR(inode)) {
+		result = PTR_ERR(inode);
+		inode = NULL;
+		goto error;
 	}
 
-	inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid);
-
-	fid = v9fs_fid_create(v9ses, newfid);
-	if (fid == NULL) {
-		dprintk(DEBUG_ERROR, "couldn't insert\n");
-		result = -ENOMEM;
-		goto FreeFcall;
-	}
-
-	result = v9fs_fid_insert(fid, dentry);
+	result = v9fs_fid_add(dentry, fid);
 	if (result < 0)
-		goto FreeFcall;
+		goto error;
 
-	fid->qid = fcall->params.rstat.stat.qid;
-	v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
 	if((fid->qid.version)&&(v9ses->cache))
 		dentry->d_op = &v9fs_cached_dentry_operations;
 	else
 		dentry->d_op = &v9fs_dentry_operations;
 
 	d_add(dentry, inode);
-	kfree(fcall);
-
 	return NULL;
 
-Release_Dirfid:
-	up(&dirfid->lock);
-
-FreeFcall:
-	kfree(fcall);
+error:
+	if (fid)
+		p9_client_clunk(fid);
 
 	return ERR_PTR(result);
 }
@@ -757,73 +645,54 @@
 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		struct inode *new_dir, struct dentry *new_dentry)
 {
-	struct inode *old_inode = old_dentry->d_inode;
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode);
-	struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry);
-	struct v9fs_fid *olddirfid;
-	struct v9fs_fid *newdirfid;
-	struct v9fs_wstat wstat;
-	struct v9fs_fcall *fcall = NULL;
-	int fid = -1;
-	int olddirfidnum = -1;
-	int newdirfidnum = -1;
-	int retval = 0;
+	struct inode *old_inode;
+	struct v9fs_session_info *v9ses;
+	struct p9_fid *oldfid;
+	struct p9_fid *olddirfid;
+	struct p9_fid *newdirfid;
+	struct p9_wstat wstat;
+	int retval;
 
-	dprintk(DEBUG_VFS, "\n");
-
+	P9_DPRINTK(P9_DEBUG_VFS, "\n");
+	retval = 0;
+	old_inode = old_dentry->d_inode;
+	v9ses = v9fs_inode2v9ses(old_inode);
+	oldfid = v9fs_fid_lookup(old_dentry);
 	if(IS_ERR(oldfid))
 		return PTR_ERR(oldfid);
 
 	olddirfid = v9fs_fid_clone(old_dentry->d_parent);
 	if(IS_ERR(olddirfid)) {
 		retval = PTR_ERR(olddirfid);
-		goto Release_lock;
+		goto done;
 	}
 
 	newdirfid = v9fs_fid_clone(new_dentry->d_parent);
 	if(IS_ERR(newdirfid)) {
 		retval = PTR_ERR(newdirfid);
-		goto Clunk_olddir;
+		goto clunk_olddir;
 	}
 
 	/* 9P can only handle file rename in the same directory */
 	if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
-		dprintk(DEBUG_ERROR, "old dir and new dir are different\n");
+		P9_DPRINTK(P9_DEBUG_ERROR,
+				"old dir and new dir are different\n");
 		retval = -EXDEV;
-		goto Clunk_newdir;
-	}
-
-	fid = oldfid->fid;
-	olddirfidnum = olddirfid->fid;
-	newdirfidnum = newdirfid->fid;
-
-	if (fid < 0) {
-		dprintk(DEBUG_ERROR, "no fid for old file #%lu\n",
-			old_inode->i_ino);
-		retval = -EBADF;
-		goto Clunk_newdir;
+		goto clunk_newdir;
 	}
 
 	v9fs_blank_wstat(&wstat);
 	wstat.muid = v9ses->name;
 	wstat.name = (char *) new_dentry->d_name.name;
+	retval = p9_client_wstat(oldfid, &wstat);
 
-	retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall);
+clunk_newdir:
+	p9_client_clunk(olddirfid);
 
-	if (retval < 0)
-		PRINT_FCALL_ERROR("wstat error", fcall);
+clunk_olddir:
+	p9_client_clunk(newdirfid);
 
-	kfree(fcall);
-
-Clunk_newdir:
-	v9fs_fid_clunk(v9ses, newdirfid);
-
-Clunk_olddir:
-	v9fs_fid_clunk(v9ses, olddirfid);
-
-Release_lock:
-	up(&oldfid->lock);
-
+done:
 	return retval;
 }
 
@@ -839,28 +708,30 @@
 v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		 struct kstat *stat)
 {
-	struct v9fs_fcall *fcall = NULL;
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	struct v9fs_fid *fid = v9fs_fid_clone(dentry);
-	int err = -EPERM;
+	int err;
+	struct v9fs_session_info *v9ses;
+	struct p9_fid *fid;
+	struct p9_stat *st;
 
-	dprintk(DEBUG_VFS, "dentry: %p\n", dentry);
-	if(IS_ERR(fid))
+	P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
+	err = -EPERM;
+	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	if (v9ses->cache == CACHE_LOOSE)
+		return simple_getattr(mnt, dentry, stat);
+
+	fid = v9fs_fid_lookup(dentry);
+	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 
-	err = v9fs_t_stat(v9ses, fid->fid, &fcall);
+	st = p9_client_stat(fid);
+	if (IS_ERR(st))
+		return PTR_ERR(st);
 
-	if (err < 0)
-		dprintk(DEBUG_ERROR, "stat error\n");
-	else {
-		v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode,
-				  dentry->d_inode->i_sb);
+	v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
 		generic_fillattr(dentry->d_inode, stat);
-	}
 
-	kfree(fcall);
-	v9fs_fid_clunk(v9ses, fid);
-	return err;
+	kfree(st);
+	return 0;
 }
 
 /**
@@ -872,13 +743,15 @@
 
 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	struct v9fs_fid *fid = v9fs_fid_clone(dentry);
-	struct v9fs_fcall *fcall = NULL;
-	struct v9fs_wstat wstat;
-	int res = -EPERM;
+	int retval;
+	struct v9fs_session_info *v9ses;
+	struct p9_fid *fid;
+	struct p9_wstat wstat;
 
-	dprintk(DEBUG_VFS, "\n");
+	P9_DPRINTK(P9_DEBUG_VFS, "\n");
+	retval = -EPERM;
+	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	fid = v9fs_fid_lookup(dentry);
 	if(IS_ERR(fid))
 		return PTR_ERR(fid);
 
@@ -903,17 +776,11 @@
 			wstat.n_gid = iattr->ia_gid;
 	}
 
-	res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall);
+	retval = p9_client_wstat(fid, &wstat);
+	if (retval >= 0)
+		retval = inode_setattr(dentry->d_inode, iattr);
 
-	if (res < 0)
-		PRINT_FCALL_ERROR("wstat error", fcall);
-
-	kfree(fcall);
-	if (res >= 0)
-		res = inode_setattr(dentry->d_inode, iattr);
-
-	v9fs_fid_clunk(v9ses, fid);
-	return res;
+	return retval;
 }
 
 /**
@@ -925,7 +792,7 @@
  */
 
 void
-v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
+v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
 	struct super_block *sb)
 {
 	int n;
@@ -966,8 +833,9 @@
 		case 'b':
 			break;
 		default:
-			dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n",
-				type, stat->extension.len, stat->extension.str);
+			P9_DPRINTK(P9_DEBUG_ERROR,
+				"Unknown special type %c (%.*s)\n", type,
+				stat->extension.len, stat->extension.str);
 		};
 		inode->i_rdev = MKDEV(major, minor);
 	} else
@@ -975,8 +843,8 @@
 
 	inode->i_size = stat->length;
 
-	inode->i_blocks =
-	    (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	/* not real number of blocks, but 512 byte ones ... */
+	inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
 }
 
 /**
@@ -986,7 +854,7 @@
  * BUG: potential for inode number collisions?
  */
 
-ino_t v9fs_qid2ino(struct v9fs_qid *qid)
+ino_t v9fs_qid2ino(struct p9_qid *qid)
 {
 	u64 path = qid->path + 2;
 	ino_t i = 0;
@@ -1009,56 +877,46 @@
 
 static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
-	int retval = -EPERM;
+	int retval;
 
-	struct v9fs_fcall *fcall = NULL;
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	struct v9fs_fid *fid = v9fs_fid_clone(dentry);
+	struct v9fs_session_info *v9ses;
+	struct p9_fid *fid;
+	struct p9_stat *st;
 
+	P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
+	retval = -EPERM;
+	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	fid = v9fs_fid_lookup(dentry);
 	if(IS_ERR(fid))
 		return PTR_ERR(fid);
 
-	if (!v9ses->extended) {
-		retval = -EBADF;
-		dprintk(DEBUG_ERROR, "not extended\n");
-		goto ClunkFid;
-	}
+	if (!v9ses->extended)
+		return -EBADF;
 
-	dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name);
-	retval = v9fs_t_stat(v9ses, fid->fid, &fcall);
+	st = p9_client_stat(fid);
+	if (IS_ERR(st))
+		return PTR_ERR(st);
 
-	if (retval < 0) {
-		dprintk(DEBUG_ERROR, "stat error\n");
-		goto FreeFcall;
-	}
-
-	if (!fcall) {
-		retval = -EIO;
-		goto ClunkFid;
-	}
-
-	if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) {
+	if (!(st->mode & P9_DMSYMLINK)) {
 		retval = -EINVAL;
-		goto FreeFcall;
+		goto done;
 	}
 
 	/* copy extension buffer into buffer */
-	if (fcall->params.rstat.stat.extension.len < buflen)
-		buflen = fcall->params.rstat.stat.extension.len + 1;
+	if (st->extension.len < buflen)
+		buflen = st->extension.len + 1;
 
-	memmove(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
+	memmove(buffer, st->extension.str, buflen - 1);
 	buffer[buflen-1] = 0;
 
-	dprintk(DEBUG_ERROR, "%s -> %.*s (%s)\n", dentry->d_name.name, fcall->params.rstat.stat.extension.len,
-		fcall->params.rstat.stat.extension.str, buffer);
+	P9_DPRINTK(P9_DEBUG_VFS,
+		"%s -> %.*s (%s)\n", dentry->d_name.name, st->extension.len,
+		st->extension.str, buffer);
+
 	retval = buflen;
 
-FreeFcall:
-	kfree(fcall);
-
-ClunkFid:
-	v9fs_fid_clunk(v9ses, fid);
-
+done:
+	kfree(st);
 	return retval;
 }
 
@@ -1083,14 +941,14 @@
 	if (buflen > PATH_MAX)
 		buflen = PATH_MAX;
 
-	dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
 
 	retval = v9fs_readlink(dentry, link, buflen);
 
 	if (retval > 0) {
 		if ((ret = copy_to_user(buffer, link, retval)) != 0) {
-			dprintk(DEBUG_ERROR, "problem copying to user: %d\n",
-				ret);
+			P9_DPRINTK(P9_DEBUG_ERROR,
+					"problem copying to user: %d\n", ret);
 			retval = ret;
 		}
 	}
@@ -1111,7 +969,7 @@
 	int len = 0;
 	char *link = __getname();
 
-	dprintk(DEBUG_VFS, "%s n", dentry->d_name.name);
+	P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
 
 	if (!link)
 		link = ERR_PTR(-ENOMEM);
@@ -1140,7 +998,7 @@
 {
 	char *s = nd_get_link(nd);
 
-	dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
+	P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
 	if (!IS_ERR(s))
 		__putname(s);
 }
@@ -1148,66 +1006,24 @@
 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 	int mode, const char *extension)
 {
-	int err;
-	u32 fid, perm;
+	u32 perm;
 	struct v9fs_session_info *v9ses;
-	struct v9fs_fid *dfid, *vfid = NULL;
-	struct inode *inode = NULL;
+	struct p9_fid *fid;
 
 	v9ses = v9fs_inode2v9ses(dir);
 	if (!v9ses->extended) {
-		dprintk(DEBUG_ERROR, "not extended\n");
+		P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
 		return -EPERM;
 	}
 
-	dfid = v9fs_fid_clone(dentry->d_parent);
-	if(IS_ERR(dfid)) {
-		err = PTR_ERR(dfid);
-		goto error;
-	}
-
 	perm = unixmode2p9mode(v9ses, mode);
+	fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
+								P9_OREAD);
+	if (IS_ERR(fid))
+		return PTR_ERR(fid);
 
-	err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
-		perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL);
-
-	if (err)
-		goto clunk_dfid;
-
-	err = v9fs_t_clunk(v9ses, fid);
-	if (err)
-		goto clunk_dfid;
-
-	vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
-	if (IS_ERR(vfid)) {
-		err = PTR_ERR(vfid);
-		vfid = NULL;
-		goto clunk_dfid;
-	}
-
-	inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
-	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
-		inode = NULL;
-		goto free_vfid;
-	}
-
-	if(v9ses->cache)
-		dentry->d_op = &v9fs_cached_dentry_operations;
-	else
-		dentry->d_op = &v9fs_dentry_operations;
-	d_instantiate(dentry, inode);
+	p9_client_clunk(fid);
 	return 0;
-
-free_vfid:
-	v9fs_fid_destroy(vfid);
-
-clunk_dfid:
-	v9fs_fid_clunk(v9ses, dfid);
-
-error:
-	return err;
-
 }
 
 /**
@@ -1223,8 +1039,8 @@
 static int
 v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
-	dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
-		symname);
+	P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,
+					dentry->d_name.name, symname);
 
 	return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
 }
@@ -1246,11 +1062,11 @@
 	      struct dentry *dentry)
 {
 	int retval;
-	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
-	struct v9fs_fid *oldfid;
+	struct p9_fid *oldfid;
 	char *name;
 
-	dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
+	P9_DPRINTK(P9_DEBUG_VFS,
+		" %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
 		old_dentry->d_name.name);
 
 	oldfid = v9fs_fid_clone(old_dentry);
@@ -1264,11 +1080,11 @@
 	}
 
 	sprintf(name, "%d\n", oldfid->fid);
-	retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
+	retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
 	__putname(name);
 
 clunk_fid:
-	v9fs_fid_clunk(v9ses, oldfid);
+	p9_client_clunk(oldfid);
 	return retval;
 }
 
@@ -1287,7 +1103,8 @@
 	int retval;
 	char *name;
 
-	dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
+	P9_DPRINTK(P9_DEBUG_VFS,
+		" %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
 		dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
 
 	if (!new_valid_dev(rdev))
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 8eb9263..ba90437 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -36,10 +36,11 @@
 #include <linux/seq_file.h>
 #include <linux/mount.h>
 #include <linux/idr.h>
+#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
 
-#include "debug.h"
 #include "v9fs.h"
-#include "9p.h"
 #include "v9fs_vfs.h"
 #include "fid.h"
 
@@ -106,41 +107,48 @@
 		       struct vfsmount *mnt)
 {
 	struct super_block *sb = NULL;
-	struct v9fs_fcall *fcall = NULL;
 	struct inode *inode = NULL;
 	struct dentry *root = NULL;
 	struct v9fs_session_info *v9ses = NULL;
-	struct v9fs_fid *root_fid = NULL;
+	struct p9_stat *st = NULL;
 	int mode = S_IRWXUGO | S_ISVTX;
 	uid_t uid = current->fsuid;
 	gid_t gid = current->fsgid;
-	int stat_result = 0;
-	int newfid = 0;
+	struct p9_fid *fid;
 	int retval = 0;
 
-	dprintk(DEBUG_VFS, " \n");
+	P9_DPRINTK(P9_DEBUG_VFS, " \n");
 
 	v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
 	if (!v9ses)
 		return -ENOMEM;
 
-	if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
-		dprintk(DEBUG_ERROR, "problem initiating session\n");
-		retval = newfid;
-		goto out_free_session;
+	fid = v9fs_session_init(v9ses, dev_name, data);
+	if (IS_ERR(fid)) {
+		retval = PTR_ERR(fid);
+		fid = NULL;
+		kfree(v9ses);
+		v9ses = NULL;
+		goto error;
+	}
+
+	st = p9_client_stat(fid);
+	if (IS_ERR(st)) {
+		retval = PTR_ERR(st);
+		goto error;
 	}
 
 	sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
 	if (IS_ERR(sb)) {
 		retval = PTR_ERR(sb);
-		goto out_close_session;
+		goto error;
 	}
 	v9fs_fill_super(sb, v9ses, flags);
 
 	inode = v9fs_get_inode(sb, S_IFDIR | mode);
 	if (IS_ERR(inode)) {
 		retval = PTR_ERR(inode);
-		goto put_back_sb;
+		goto error;
 	}
 
 	inode->i_uid = uid;
@@ -149,54 +157,30 @@
 	root = d_alloc_root(inode);
 	if (!root) {
 		retval = -ENOMEM;
-		goto put_back_sb;
+		goto error;
 	}
 
 	sb->s_root = root;
-
-	stat_result = v9fs_t_stat(v9ses, newfid, &fcall);
-	if (stat_result < 0) {
-		dprintk(DEBUG_ERROR, "stat error\n");
-		v9fs_t_clunk(v9ses, newfid);
-	} else {
-		/* Setup the Root Inode */
-		root_fid = v9fs_fid_create(v9ses, newfid);
-		if (root_fid == NULL) {
-			retval = -ENOMEM;
-			goto put_back_sb;
-		}
-
-		retval = v9fs_fid_insert(root_fid, root);
-		if (retval < 0) {
-			kfree(fcall);
-			goto put_back_sb;
-		}
-
-		root_fid->qid = fcall->params.rstat.stat.qid;
-		root->d_inode->i_ino =
-		    v9fs_qid2ino(&fcall->params.rstat.stat.qid);
-		v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb);
-	}
-
-	kfree(fcall);
-
-	if (stat_result < 0) {
-		retval = stat_result;
-		goto put_back_sb;
-	}
+	root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
+	v9fs_stat2inode(st, root->d_inode, sb);
+	v9fs_fid_add(root, fid);
 
 	return simple_set_mnt(mnt, sb);
 
-out_close_session:
-	v9fs_session_close(v9ses);
-out_free_session:
-	kfree(v9ses);
-	return retval;
+error:
+	if (fid)
+		p9_client_clunk(fid);
 
-put_back_sb:
-	/* deactivate_super calls v9fs_kill_super which will frees the rest */
-	up_write(&sb->s_umount);
-	deactivate_super(sb);
+	if (v9ses) {
+		v9fs_session_close(v9ses);
+		kfree(v9ses);
+	}
+
+	if (sb) {
+		up_write(&sb->s_umount);
+		deactivate_super(sb);
+	}
+
 	return retval;
 }
 
@@ -210,7 +194,7 @@
 {
 	struct v9fs_session_info *v9ses = s->s_fs_info;
 
-	dprintk(DEBUG_VFS, " %p\n", s);
+	P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
 
 	v9fs_dentry_release(s->s_root);	/* clunk root */
 
@@ -218,7 +202,7 @@
 
 	v9fs_session_close(v9ses);
 	kfree(v9ses);
-	dprintk(DEBUG_VFS, "exiting kill_super\n");
+	P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
 }
 
 /**
@@ -233,7 +217,7 @@
 	struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
 
 	if (v9ses->debug != 0)
-		seq_printf(m, ",debug=%u", v9ses->debug);
+		seq_printf(m, ",debug=%x", v9ses->debug);
 	if (v9ses->port != V9FS_PORT)
 		seq_printf(m, ",port=%u", v9ses->port);
 	if (v9ses->maxdata != 9000)
diff --git a/fs/Kconfig b/fs/Kconfig
index 0fa0c11..613df55 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -991,7 +991,7 @@
 
 config HUGETLBFS
 	bool "HugeTLB file system support"
-	depends on X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+	depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN
 	help
 	  hugetlbfs is a filesystem backing for HugeTLB pages, based on
 	  ramfs. For architectures that support it, say Y here and read
@@ -1675,6 +1675,7 @@
 config NFSD_V4
 	bool "Provide NFSv4 server support (EXPERIMENTAL)"
 	depends on NFSD_V3 && EXPERIMENTAL
+	select RPCSEC_GSS_KRB5
 	help
 	  If you would like to include the NFSv4 server as well as the NFSv2
 	  and NFSv3 servers, say Y here.  This feature is experimental, and
@@ -2048,7 +2049,7 @@
 
 config 9P_FS
 	tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
-	depends on INET && EXPERIMENTAL
+	depends on INET && NET_9P && EXPERIMENTAL
 	help
 	  If you say Y here, you will get experimental support for
 	  Plan 9 resource sharing via the 9P2000 protocol.
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 74c6440..d4fc609 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -38,7 +38,7 @@
 
 config BINFMT_FLAT
 	tristate "Kernel support for flat binaries"
-	depends on !MMU || SUPERH
+	depends on !MMU
 	help
 	  Support uClinux FLAT format binaries.
 
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index f544a28..36e381c 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -33,7 +33,7 @@
 	.fsync		= file_fsync,
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations adfs_file_inode_operations = {
diff --git a/fs/affs/file.c b/fs/affs/file.c
index c879690..c314a35 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -35,7 +35,7 @@
 	.open		= affs_file_open,
 	.release	= affs_file_release,
 	.fsync		= file_fsync,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations affs_file_inode_operations = {
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index c5b9d73c..4609a6c 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -9,7 +9,7 @@
  *
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
-
+#include <linux/sched.h>
 #include "affs.h"
 
 extern const struct inode_operations affs_symlink_inode_operations;
diff --git a/fs/affs/super.c b/fs/affs/super.c
index b800d45..6d0ebc3 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -15,6 +15,7 @@
 #include <linux/statfs.h>
 #include <linux/parser.h>
 #include <linux/magic.h>
+#include <linux/sched.h>
 #include "affs.h"
 
 extern struct timezone sys_tz;
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 73ce561..a666710 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -8,6 +8,7 @@
 	cmservice.o \
 	dir.o \
 	file.o \
+	flock.o \
 	fsclient.o \
 	inode.o \
 	main.o \
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index 2452579..c548aa3 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -37,6 +37,13 @@
 	AFS_FTYPE_SYMLINK	= 3,
 } afs_file_type_t;
 
+typedef enum {
+	AFS_LOCK_READ		= 0,	/* read lock request */
+	AFS_LOCK_WRITE		= 1,	/* write lock request */
+} afs_lock_type_t;
+
+#define AFS_LOCKWAIT		(5 * 60) /* time until a lock times out (seconds) */
+
 /*
  * AFS file identifier
  */
@@ -120,6 +127,7 @@
 	struct afs_fid		parent;		/* parent dir ID for non-dirs only */
 	time_t			mtime_client;	/* last time client changed data */
 	time_t			mtime_server;	/* last time server changed data */
+	s32			lock_count;	/* file lock count (0=UNLK -1=WRLCK +ve=#RDLCK */
 };
 
 /*
diff --git a/fs/afs/afs_fs.h b/fs/afs/afs_fs.h
index a18c374..eb64732 100644
--- a/fs/afs/afs_fs.h
+++ b/fs/afs/afs_fs.h
@@ -31,6 +31,9 @@
 	FSGETVOLUMEINFO		= 148,	/* AFS Get information about a volume */
 	FSGETVOLUMESTATUS	= 149,	/* AFS Get volume status information */
 	FSGETROOTVOLUME		= 151,	/* AFS Get root volume name */
+	FSSETLOCK		= 156,	/* AFS Request a file lock */
+	FSEXTENDLOCK		= 157,	/* AFS Extend a file lock */
+	FSRELEASELOCK		= 158,	/* AFS Release a file lock */
 	FSLOOKUP		= 161,	/* AFS lookup file in directory */
 	FSFETCHDATA64		= 65537, /* AFS Fetch file data */
 	FSSTOREDATA64		= 65538, /* AFS Store file data */
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index f64e40f..b824394 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/circ_buf.h>
+#include <linux/sched.h>
 #include "internal.h"
 
 unsigned afs_vnode_update_timeout = 10;
@@ -124,6 +125,9 @@
 		spin_unlock(&server->cb_lock);
 
 		queue_work(afs_callback_update_worker, &vnode->cb_broken_work);
+		if (list_empty(&vnode->granted_locks) &&
+		    !list_empty(&vnode->pending_locks))
+			afs_lock_may_be_available(vnode);
 		spin_unlock(&vnode->lock);
 	}
 }
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index 9b1311a..175a567 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/key.h>
 #include <linux/ctype.h>
+#include <linux/sched.h>
 #include <keys/rxrpc-type.h>
 #include "internal.h"
 
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 719af4f..33fe39a 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/ctype.h>
+#include <linux/sched.h>
 #include "internal.h"
 
 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
@@ -43,6 +44,7 @@
 	.open		= afs_dir_open,
 	.release	= afs_release,
 	.readdir	= afs_readdir,
+	.lock		= afs_lock,
 };
 
 const struct inode_operations afs_dir_inode_operations = {
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 9c0e721..525f7c5 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -32,8 +32,10 @@
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= afs_file_write,
 	.mmap		= generic_file_readonly_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.fsync		= afs_fsync,
+	.lock		= afs_lock,
+	.flock		= afs_flock,
 };
 
 const struct inode_operations afs_file_inode_operations = {
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
new file mode 100644
index 0000000..8f07f8d1
--- /dev/null
+++ b/fs/afs/flock.c
@@ -0,0 +1,558 @@
+/* AFS file locking support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/smp_lock.h>
+#include "internal.h"
+
+#define AFS_LOCK_GRANTED	0
+#define AFS_LOCK_PENDING	1
+
+static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl);
+static void afs_fl_release_private(struct file_lock *fl);
+
+static struct workqueue_struct *afs_lock_manager;
+
+static struct file_lock_operations afs_lock_ops = {
+	.fl_copy_lock		= afs_fl_copy_lock,
+	.fl_release_private	= afs_fl_release_private,
+};
+
+/*
+ * initialise the lock manager thread if it isn't already running
+ */
+static int afs_init_lock_manager(void)
+{
+	if (!afs_lock_manager) {
+		afs_lock_manager = create_singlethread_workqueue("kafs_lockd");
+		if (!afs_lock_manager)
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+/*
+ * destroy the lock manager thread if it's running
+ */
+void __exit afs_kill_lock_manager(void)
+{
+	if (afs_lock_manager)
+		destroy_workqueue(afs_lock_manager);
+}
+
+/*
+ * if the callback is broken on this vnode, then the lock may now be available
+ */
+void afs_lock_may_be_available(struct afs_vnode *vnode)
+{
+	_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+
+	queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0);
+}
+
+/*
+ * the lock will time out in 5 minutes unless we extend it, so schedule
+ * extension in a bit less than that time
+ */
+static void afs_schedule_lock_extension(struct afs_vnode *vnode)
+{
+	queue_delayed_work(afs_lock_manager, &vnode->lock_work,
+			   AFS_LOCKWAIT * HZ / 2);
+}
+
+/*
+ * do work for a lock, including:
+ * - probing for a lock we're waiting on but didn't get immediately
+ * - extending a lock that's close to timing out
+ */
+void afs_lock_work(struct work_struct *work)
+{
+	struct afs_vnode *vnode =
+		container_of(work, struct afs_vnode, lock_work.work);
+	struct file_lock *fl;
+	afs_lock_type_t type;
+	struct key *key;
+	int ret;
+
+	_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+
+	spin_lock(&vnode->lock);
+
+	if (test_bit(AFS_VNODE_UNLOCKING, &vnode->flags)) {
+		_debug("unlock");
+		spin_unlock(&vnode->lock);
+
+		/* attempt to release the server lock; if it fails, we just
+		 * wait 5 minutes and it'll time out anyway */
+		ret = afs_vnode_release_lock(vnode, vnode->unlock_key);
+		if (ret < 0)
+			printk(KERN_WARNING "AFS:"
+			       " Failed to release lock on {%x:%x} error %d\n",
+			       vnode->fid.vid, vnode->fid.vnode, ret);
+
+		spin_lock(&vnode->lock);
+		key_put(vnode->unlock_key);
+		vnode->unlock_key = NULL;
+		clear_bit(AFS_VNODE_UNLOCKING, &vnode->flags);
+	}
+
+	/* if we've got a lock, then it must be time to extend that lock as AFS
+	 * locks time out after 5 minutes */
+	if (!list_empty(&vnode->granted_locks)) {
+		_debug("extend");
+
+		if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags))
+			BUG();
+		fl = list_entry(vnode->granted_locks.next,
+				struct file_lock, fl_u.afs.link);
+		key = key_get(fl->fl_file->private_data);
+		spin_unlock(&vnode->lock);
+
+		ret = afs_vnode_extend_lock(vnode, key);
+		clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+		key_put(key);
+		switch (ret) {
+		case 0:
+			afs_schedule_lock_extension(vnode);
+			break;
+		default:
+			/* ummm... we failed to extend the lock - retry
+			 * extension shortly */
+			printk(KERN_WARNING "AFS:"
+			       " Failed to extend lock on {%x:%x} error %d\n",
+			       vnode->fid.vid, vnode->fid.vnode, ret);
+			queue_delayed_work(afs_lock_manager, &vnode->lock_work,
+					   HZ * 10);
+			break;
+		}
+		_leave(" [extend]");
+		return;
+	}
+
+	/* if we don't have a granted lock, then we must've been called back by
+	 * the server, and so if might be possible to get a lock we're
+	 * currently waiting for */
+	if (!list_empty(&vnode->pending_locks)) {
+		_debug("get");
+
+		if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags))
+			BUG();
+		fl = list_entry(vnode->pending_locks.next,
+				struct file_lock, fl_u.afs.link);
+		key = key_get(fl->fl_file->private_data);
+		type = (fl->fl_type == F_RDLCK) ?
+			AFS_LOCK_READ : AFS_LOCK_WRITE;
+		spin_unlock(&vnode->lock);
+
+		ret = afs_vnode_set_lock(vnode, key, type);
+		clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+		switch (ret) {
+		case -EWOULDBLOCK:
+			_debug("blocked");
+			break;
+		case 0:
+			_debug("acquired");
+			if (type == AFS_LOCK_READ)
+				set_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+			else
+				set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+			ret = AFS_LOCK_GRANTED;
+		default:
+			spin_lock(&vnode->lock);
+			/* the pending lock may have been withdrawn due to a
+			 * signal */
+			if (list_entry(vnode->pending_locks.next,
+				       struct file_lock, fl_u.afs.link) == fl) {
+				fl->fl_u.afs.state = ret;
+				if (ret == AFS_LOCK_GRANTED)
+					list_move_tail(&fl->fl_u.afs.link,
+						       &vnode->granted_locks);
+				else
+					list_del_init(&fl->fl_u.afs.link);
+				wake_up(&fl->fl_wait);
+				spin_unlock(&vnode->lock);
+			} else {
+				_debug("withdrawn");
+				clear_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+				clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+				spin_unlock(&vnode->lock);
+				afs_vnode_release_lock(vnode, key);
+				if (!list_empty(&vnode->pending_locks))
+					afs_lock_may_be_available(vnode);
+			}
+			break;
+		}
+		key_put(key);
+		_leave(" [pend]");
+		return;
+	}
+
+	/* looks like the lock request was withdrawn on a signal */
+	spin_unlock(&vnode->lock);
+	_leave(" [no locks]");
+}
+
+/*
+ * pass responsibility for the unlocking of a vnode on the server to the
+ * manager thread, lest a pending signal in the calling thread interrupt
+ * AF_RXRPC
+ * - the caller must hold the vnode lock
+ */
+static void afs_defer_unlock(struct afs_vnode *vnode, struct key *key)
+{
+	cancel_delayed_work(&vnode->lock_work);
+	if (!test_and_clear_bit(AFS_VNODE_READLOCKED, &vnode->flags) &&
+	    !test_and_clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags))
+		BUG();
+	if (test_and_set_bit(AFS_VNODE_UNLOCKING, &vnode->flags))
+		BUG();
+	vnode->unlock_key = key_get(key);
+	afs_lock_may_be_available(vnode);
+}
+
+/*
+ * request a lock on a file on the server
+ */
+static int afs_do_setlk(struct file *file, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+	afs_lock_type_t type;
+	struct key *key = file->private_data;
+	int ret;
+
+	_enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
+
+	/* only whole-file locks are supported */
+	if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
+		return -EINVAL;
+
+	ret = afs_init_lock_manager();
+	if (ret < 0)
+		return ret;
+
+	fl->fl_ops = &afs_lock_ops;
+	INIT_LIST_HEAD(&fl->fl_u.afs.link);
+	fl->fl_u.afs.state = AFS_LOCK_PENDING;
+
+	type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
+
+	lock_kernel();
+
+	/* make sure we've got a callback on this file and that our view of the
+	 * data version is up to date */
+	ret = afs_vnode_fetch_status(vnode, NULL, key);
+	if (ret < 0)
+		goto error;
+
+	if (vnode->status.lock_count != 0 && !(fl->fl_flags & FL_SLEEP)) {
+		ret = -EAGAIN;
+		goto error;
+	}
+
+	spin_lock(&vnode->lock);
+
+	if (list_empty(&vnode->pending_locks)) {
+		/* if there's no-one else with a lock on this vnode, then we
+		 * need to ask the server for a lock */
+		if (list_empty(&vnode->granted_locks)) {
+			_debug("not locked");
+			ASSERTCMP(vnode->flags &
+				  ((1 << AFS_VNODE_LOCKING) |
+				   (1 << AFS_VNODE_READLOCKED) |
+				   (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
+			list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
+			set_bit(AFS_VNODE_LOCKING, &vnode->flags);
+			spin_unlock(&vnode->lock);
+
+			ret = afs_vnode_set_lock(vnode, key, type);
+			clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+			switch (ret) {
+			case 0:
+				goto acquired_server_lock;
+			case -EWOULDBLOCK:
+				spin_lock(&vnode->lock);
+				ASSERT(list_empty(&vnode->granted_locks));
+				ASSERTCMP(vnode->pending_locks.next, ==,
+					  &fl->fl_u.afs.link);
+				goto wait;
+			default:
+				spin_lock(&vnode->lock);
+				list_del_init(&fl->fl_u.afs.link);
+				spin_unlock(&vnode->lock);
+				goto error;
+			}
+		}
+
+		/* if we've already got a readlock on the server and no waiting
+		 * writelocks, then we might be able to instantly grant another
+		 * readlock */
+		if (type == AFS_LOCK_READ &&
+		    vnode->flags & (1 << AFS_VNODE_READLOCKED)) {
+			_debug("instant readlock");
+			ASSERTCMP(vnode->flags &
+				  ((1 << AFS_VNODE_LOCKING) |
+				   (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
+			ASSERT(!list_empty(&vnode->granted_locks));
+			goto sharing_existing_lock;
+		}
+	}
+
+	/* otherwise, we need to wait for a local lock to become available */
+	_debug("wait local");
+	list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
+wait:
+	if (!(fl->fl_flags & FL_SLEEP)) {
+		_debug("noblock");
+		ret = -EAGAIN;
+		goto abort_attempt;
+	}
+	spin_unlock(&vnode->lock);
+
+	/* now we need to sleep and wait for the lock manager thread to get the
+	 * lock from the server */
+	_debug("sleep");
+	ret = wait_event_interruptible(fl->fl_wait,
+				       fl->fl_u.afs.state <= AFS_LOCK_GRANTED);
+	if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) {
+		ret = fl->fl_u.afs.state;
+		if (ret < 0)
+			goto error;
+		spin_lock(&vnode->lock);
+		goto given_lock;
+	}
+
+	/* we were interrupted, but someone may still be in the throes of
+	 * giving us the lock */
+	_debug("intr");
+	ASSERTCMP(ret, ==, -ERESTARTSYS);
+
+	spin_lock(&vnode->lock);
+	if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) {
+		ret = fl->fl_u.afs.state;
+		if (ret < 0) {
+			spin_unlock(&vnode->lock);
+			goto error;
+		}
+		goto given_lock;
+	}
+
+abort_attempt:
+	/* we aren't going to get the lock, either because we're unwilling to
+	 * wait, or because some signal happened */
+	_debug("abort");
+	if (list_empty(&vnode->granted_locks) &&
+	    vnode->pending_locks.next == &fl->fl_u.afs.link) {
+		if (vnode->pending_locks.prev != &fl->fl_u.afs.link) {
+			/* kick the next pending lock into having a go */
+			list_del_init(&fl->fl_u.afs.link);
+			afs_lock_may_be_available(vnode);
+		}
+	} else {
+		list_del_init(&fl->fl_u.afs.link);
+	}
+	spin_unlock(&vnode->lock);
+	goto error;
+
+acquired_server_lock:
+	/* we've acquired a server lock, but it needs to be renewed after 5
+	 * mins */
+	spin_lock(&vnode->lock);
+	afs_schedule_lock_extension(vnode);
+	if (type == AFS_LOCK_READ)
+		set_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+	else
+		set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+sharing_existing_lock:
+	/* the lock has been granted as far as we're concerned... */
+	fl->fl_u.afs.state = AFS_LOCK_GRANTED;
+	list_move_tail(&fl->fl_u.afs.link, &vnode->granted_locks);
+given_lock:
+	/* ... but we do still need to get the VFS's blessing */
+	ASSERT(!(vnode->flags & (1 << AFS_VNODE_LOCKING)));
+	ASSERT((vnode->flags & ((1 << AFS_VNODE_READLOCKED) |
+				(1 << AFS_VNODE_WRITELOCKED))) != 0);
+	ret = posix_lock_file(file, fl, NULL);
+	if (ret < 0)
+		goto vfs_rejected_lock;
+	spin_unlock(&vnode->lock);
+
+	/* again, make sure we've got a callback on this file and, again, make
+	 * sure that our view of the data version is up to date (we ignore
+	 * errors incurred here and deal with the consequences elsewhere) */
+	afs_vnode_fetch_status(vnode, NULL, key);
+
+error:
+	unlock_kernel();
+	_leave(" = %d", ret);
+	return ret;
+
+vfs_rejected_lock:
+	/* the VFS rejected the lock we just obtained, so we have to discard
+	 * what we just got */
+	_debug("vfs refused %d", ret);
+	list_del_init(&fl->fl_u.afs.link);
+	if (list_empty(&vnode->granted_locks))
+		afs_defer_unlock(vnode, key);
+	spin_unlock(&vnode->lock);
+	goto abort_attempt;
+}
+
+/*
+ * unlock on a file on the server
+ */
+static int afs_do_unlk(struct file *file, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+	struct key *key = file->private_data;
+	int ret;
+
+	_enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
+
+	/* only whole-file unlocks are supported */
+	if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
+		return -EINVAL;
+
+	fl->fl_ops = &afs_lock_ops;
+	INIT_LIST_HEAD(&fl->fl_u.afs.link);
+	fl->fl_u.afs.state = AFS_LOCK_PENDING;
+
+	spin_lock(&vnode->lock);
+	ret = posix_lock_file(file, fl, NULL);
+	if (ret < 0) {
+		spin_unlock(&vnode->lock);
+		_leave(" = %d [vfs]", ret);
+		return ret;
+	}
+
+	/* discard the server lock only if all granted locks are gone */
+	if (list_empty(&vnode->granted_locks))
+		afs_defer_unlock(vnode, key);
+	spin_unlock(&vnode->lock);
+	_leave(" = 0");
+	return 0;
+}
+
+/*
+ * return information about a lock we currently hold, if indeed we hold one
+ */
+static int afs_do_getlk(struct file *file, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+	struct key *key = file->private_data;
+	int ret, lock_count;
+
+	_enter("");
+
+	fl->fl_type = F_UNLCK;
+
+	mutex_lock(&vnode->vfs_inode.i_mutex);
+
+	/* check local lock records first */
+	ret = 0;
+	if (posix_test_lock(file, fl) == 0) {
+		/* no local locks; consult the server */
+		ret = afs_vnode_fetch_status(vnode, NULL, key);
+		if (ret < 0)
+			goto error;
+		lock_count = vnode->status.lock_count;
+		if (lock_count) {
+			if (lock_count > 0)
+				fl->fl_type = F_RDLCK;
+			else
+				fl->fl_type = F_WRLCK;
+			fl->fl_start = 0;
+			fl->fl_end = OFFSET_MAX;
+		}
+	}
+
+error:
+	mutex_unlock(&vnode->vfs_inode.i_mutex);
+	_leave(" = %d [%hd]", ret, fl->fl_type);
+	return ret;
+}
+
+/*
+ * manage POSIX locks on a file
+ */
+int afs_lock(struct file *file, int cmd, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+
+	_enter("{%x:%u},%d,{t=%x,fl=%x,r=%Ld:%Ld}",
+	       vnode->fid.vid, vnode->fid.vnode, cmd,
+	       fl->fl_type, fl->fl_flags,
+	       (long long) fl->fl_start, (long long) fl->fl_end);
+
+	/* AFS doesn't support mandatory locks */
+	if ((vnode->vfs_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
+	    fl->fl_type != F_UNLCK)
+		return -ENOLCK;
+
+	if (IS_GETLK(cmd))
+		return afs_do_getlk(file, fl);
+	if (fl->fl_type == F_UNLCK)
+		return afs_do_unlk(file, fl);
+	return afs_do_setlk(file, fl);
+}
+
+/*
+ * manage FLOCK locks on a file
+ */
+int afs_flock(struct file *file, int cmd, struct file_lock *fl)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+
+	_enter("{%x:%u},%d,{t=%x,fl=%x}",
+	       vnode->fid.vid, vnode->fid.vnode, cmd,
+	       fl->fl_type, fl->fl_flags);
+
+	/*
+	 * No BSD flocks over NFS allowed.
+	 * Note: we could try to fake a POSIX lock request here by
+	 * using ((u32) filp | 0x80000000) or some such as the pid.
+	 * Not sure whether that would be unique, though, or whether
+	 * that would break in other places.
+	 */
+	if (!(fl->fl_flags & FL_FLOCK))
+		return -ENOLCK;
+
+	/* we're simulating flock() locks using posix locks on the server */
+	fl->fl_owner = (fl_owner_t) file;
+	fl->fl_start = 0;
+	fl->fl_end = OFFSET_MAX;
+
+	if (fl->fl_type == F_UNLCK)
+		return afs_do_unlk(file, fl);
+	return afs_do_setlk(file, fl);
+}
+
+/*
+ * the POSIX lock management core VFS code copies the lock record and adds the
+ * copy into its own list, so we need to add that copy to the vnode's lock
+ * queue in the same place as the original (which will be deleted shortly
+ * after)
+ */
+static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl)
+{
+	_enter("");
+
+	list_add(&new->fl_u.afs.link, &fl->fl_u.afs.link);
+}
+
+/*
+ * need to remove this lock from the vnode queue when it's removed from the
+ * VFS's list
+ */
+static void afs_fl_release_private(struct file_lock *fl)
+{
+	_enter("");
+
+	list_del_init(&fl->fl_u.afs.link);
+}
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 5dff130..023b95b 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -67,7 +67,7 @@
 	EXTRACT(status->group);
 	bp++; /* sync counter */
 	data_version |= (u64) ntohl(*bp++) << 32;
-	bp++; /* lock count */
+	EXTRACT(status->lock_count);
 	size |= (u64) ntohl(*bp++) << 32;
 	bp++; /* spare 4 */
 	*_bp = bp;
@@ -1748,3 +1748,156 @@
 
 	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
 }
+
+/*
+ * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
+ */
+static int afs_deliver_fs_xxxx_lock(struct afs_call *call,
+				    struct sk_buff *skb, bool last)
+{
+	const __be32 *bp;
+
+	_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+
+	afs_transfer_reply(call, skb);
+	if (!last)
+		return 0;
+
+	if (call->reply_size != call->reply_max)
+		return -EBADMSG;
+
+	/* unmarshall the reply once we've received all of it */
+	bp = call->buffer;
+	/* xdr_decode_AFSVolSync(&bp, call->replyX); */
+
+	_leave(" = 0 [done]");
+	return 0;
+}
+
+/*
+ * FS.SetLock operation type
+ */
+static const struct afs_call_type afs_RXFSSetLock = {
+	.name		= "FS.SetLock",
+	.deliver	= afs_deliver_fs_xxxx_lock,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * FS.ExtendLock operation type
+ */
+static const struct afs_call_type afs_RXFSExtendLock = {
+	.name		= "FS.ExtendLock",
+	.deliver	= afs_deliver_fs_xxxx_lock,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * FS.ReleaseLock operation type
+ */
+static const struct afs_call_type afs_RXFSReleaseLock = {
+	.name		= "FS.ReleaseLock",
+	.deliver	= afs_deliver_fs_xxxx_lock,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * get a lock on a file
+ */
+int afs_fs_set_lock(struct afs_server *server,
+		    struct key *key,
+		    struct afs_vnode *vnode,
+		    afs_lock_type_t type,
+		    const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter("");
+
+	call = afs_alloc_flat_call(&afs_RXFSSetLock, 5 * 4, 6 * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->key = key;
+	call->reply = vnode;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+
+	/* marshall the parameters */
+	bp = call->request;
+	*bp++ = htonl(FSSETLOCK);
+	*bp++ = htonl(vnode->fid.vid);
+	*bp++ = htonl(vnode->fid.vnode);
+	*bp++ = htonl(vnode->fid.unique);
+	*bp++ = htonl(type);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
+/*
+ * extend a lock on a file
+ */
+int afs_fs_extend_lock(struct afs_server *server,
+		       struct key *key,
+		       struct afs_vnode *vnode,
+		       const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter("");
+
+	call = afs_alloc_flat_call(&afs_RXFSExtendLock, 4 * 4, 6 * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->key = key;
+	call->reply = vnode;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+
+	/* marshall the parameters */
+	bp = call->request;
+	*bp++ = htonl(FSEXTENDLOCK);
+	*bp++ = htonl(vnode->fid.vid);
+	*bp++ = htonl(vnode->fid.vnode);
+	*bp++ = htonl(vnode->fid.unique);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
+/*
+ * release a lock on a file
+ */
+int afs_fs_release_lock(struct afs_server *server,
+			struct key *key,
+			struct afs_vnode *vnode,
+			const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter("");
+
+	call = afs_alloc_flat_call(&afs_RXFSReleaseLock, 4 * 4, 6 * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->key = key;
+	call->reply = vnode;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+
+	/* marshall the parameters */
+	bp = call->request;
+	*bp++ = htonl(FSRELEASELOCK);
+	*bp++ = htonl(vnode->fid.vid);
+	*bp++ = htonl(vnode->fid.vnode);
+	*bp++ = htonl(vnode->fid.unique);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 47f5fed..d196840 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/sched.h>
 #include "internal.h"
 
 struct afs_iget_data {
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 4953ba5..6306438 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -16,6 +16,9 @@
 #include <linux/skbuff.h>
 #include <linux/rxrpc.h>
 #include <linux/key.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+
 #include "afs.h"
 #include "afs_vl.h"
 
@@ -348,10 +351,18 @@
 #define AFS_VNODE_ZAP_DATA	3		/* set if vnode's data should be invalidated */
 #define AFS_VNODE_DELETED	4		/* set if vnode deleted on server */
 #define AFS_VNODE_MOUNTPOINT	5		/* set if vnode is a mountpoint symlink */
+#define AFS_VNODE_LOCKING	6		/* set if waiting for lock on vnode */
+#define AFS_VNODE_READLOCKED	7		/* set if vnode is read-locked on the server */
+#define AFS_VNODE_WRITELOCKED	8		/* set if vnode is write-locked on the server */
+#define AFS_VNODE_UNLOCKING	9		/* set if vnode is being unlocked on the server */
 
 	long			acl_order;	/* ACL check count (callback break count) */
 
 	struct list_head	writebacks;	/* alterations in pagecache that need writing */
+	struct list_head	pending_locks;	/* locks waiting to be granted */
+	struct list_head	granted_locks;	/* locks granted on this file */
+	struct delayed_work	lock_work;	/* work to be done in locking */
+	struct key		*unlock_key;	/* key to be used in unlocking */
 
 	/* outstanding callback notification on this file */
 	struct rb_node		server_rb;	/* link in server->fs_vnodes */
@@ -471,6 +482,15 @@
 extern int afs_release(struct inode *, struct file *);
 
 /*
+ * flock.c
+ */
+extern void __exit afs_kill_lock_manager(void);
+extern void afs_lock_work(struct work_struct *);
+extern void afs_lock_may_be_available(struct afs_vnode *);
+extern int afs_lock(struct file *, int, struct file_lock *);
+extern int afs_flock(struct file *, int, struct file_lock *);
+
+/*
  * fsclient.c
  */
 extern int afs_fs_fetch_file_status(struct afs_server *, struct key *,
@@ -510,6 +530,15 @@
 				    struct afs_vnode *,
 				    struct afs_volume_status *,
 				    const struct afs_wait_mode *);
+extern int afs_fs_set_lock(struct afs_server *, struct key *,
+			   struct afs_vnode *, afs_lock_type_t,
+			   const struct afs_wait_mode *);
+extern int afs_fs_extend_lock(struct afs_server *, struct key *,
+			      struct afs_vnode *,
+			      const struct afs_wait_mode *);
+extern int afs_fs_release_lock(struct afs_server *, struct key *,
+			       struct afs_vnode *,
+			       const struct afs_wait_mode *);
 
 /*
  * inode.c
@@ -678,6 +707,10 @@
 extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *);
 extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *,
 				       struct afs_volume_status *);
+extern int afs_vnode_set_lock(struct afs_vnode *, struct key *,
+			      afs_lock_type_t);
+extern int afs_vnode_extend_lock(struct afs_vnode *, struct key *);
+extern int afs_vnode_release_lock(struct afs_vnode *, struct key *);
 
 /*
  * volume.c
diff --git a/fs/afs/main.c b/fs/afs/main.c
index f1f71ff..0f60f6b 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -13,6 +13,7 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/completion.h>
+#include <linux/sched.h>
 #include "internal.h"
 
 MODULE_DESCRIPTION("AFS Client File System");
@@ -167,6 +168,7 @@
 	printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
 
 	afs_fs_exit();
+	afs_kill_lock_manager();
 	afs_close_socket();
 	afs_purge_servers();
 	afs_callback_update_kill();
diff --git a/fs/afs/misc.c b/fs/afs/misc.c
index d1a889c..2d33a5f 100644
--- a/fs/afs/misc.c
+++ b/fs/afs/misc.c
@@ -35,6 +35,7 @@
 	case VOVERQUOTA:	return -EDQUOT;
 	case VBUSY:		return -EBUSY;
 	case VMOVED:		return -ENXIO;
+	case 0x2f6df0a:		return -EWOULDBLOCK;
 	case 0x2f6df0c:		return -EACCES;
 	case 0x2f6df0f:		return -EBUSY;
 	case 0x2f6df10:		return -EEXIST;
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index d5601f6..6edb566 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -200,23 +201,9 @@
  */
 static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	/* lock the list against modification */
 	down_read(&afs_proc_cells_sem);
-
-	/* allow for the header line */
-	if (!pos)
-		return (void *) 1;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &afs_proc_cells)
-		if (!pos--)
-			break;
-
-	return _p != &afs_proc_cells ? _p : NULL;
+	return seq_list_start_head(&afs_proc_cells, *_pos);
 }
 
 /*
@@ -224,14 +211,7 @@
  */
 static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = v == (void *) 1 ? afs_proc_cells.next : _p->next;
-
-	return _p != &afs_proc_cells ? _p : NULL;
+	return seq_list_next(v, &afs_proc_cells, pos);
 }
 
 /*
@@ -249,7 +229,7 @@
 {
 	struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
 
-	if (v == (void *) 1) {
+	if (v == &afs_proc_cells) {
 		/* display header on line 1 */
 		seq_puts(m, "USE NAME\n");
 		return 0;
@@ -502,26 +482,13 @@
  */
 static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
 {
-	struct list_head *_p;
 	struct afs_cell *cell = m->private;
-	loff_t pos = *_pos;
 
 	_enter("cell=%p pos=%Ld", cell, *_pos);
 
 	/* lock the list against modification */
 	down_read(&cell->vl_sem);
-
-	/* allow for the header line */
-	if (!pos)
-		return (void *) 1;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &cell->vl_list)
-		if (!pos--)
-			break;
-
-	return _p != &cell->vl_list ? _p : NULL;
+	return seq_list_start_head(&cell->vl_list, *_pos);
 }
 
 /*
@@ -530,17 +497,10 @@
 static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
 					loff_t *_pos)
 {
-	struct list_head *_p;
 	struct afs_cell *cell = p->private;
 
 	_enter("cell=%p pos=%Ld", cell, *_pos);
-
-	(*_pos)++;
-
-	_p = v;
-	_p = (v == (void *) 1) ? cell->vl_list.next : _p->next;
-
-	return (_p != &cell->vl_list) ? _p : NULL;
+	return seq_list_next(v, &cell->vl_list, _pos);
 }
 
 /*
@@ -568,11 +528,12 @@
  */
 static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
 {
+	struct afs_cell *cell = m->private;
 	struct afs_vlocation *vlocation =
 		list_entry(v, struct afs_vlocation, link);
 
 	/* display header on line 1 */
-	if (v == (void *) 1) {
+	if (v == &cell->vl_list) {
 		seq_puts(m, "USE STT VLID[0]  VLID[1]  VLID[2]  NAME\n");
 		return 0;
 	}
@@ -733,26 +694,13 @@
 static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
 	__acquires(m->private->servers_lock)
 {
-	struct list_head *_p;
 	struct afs_cell *cell = m->private;
-	loff_t pos = *_pos;
 
 	_enter("cell=%p pos=%Ld", cell, *_pos);
 
 	/* lock the list against modification */
 	read_lock(&cell->servers_lock);
-
-	/* allow for the header line */
-	if (!pos)
-		return (void *) 1;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &cell->servers)
-		if (!pos--)
-			break;
-
-	return _p != &cell->servers ? _p : NULL;
+	return seq_list_start_head(&cell->servers, *_pos);
 }
 
 /*
@@ -761,17 +709,10 @@
 static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
 					loff_t *_pos)
 {
-	struct list_head *_p;
 	struct afs_cell *cell = p->private;
 
 	_enter("cell=%p pos=%Ld", cell, *_pos);
-
-	(*_pos)++;
-
-	_p = v;
-	_p = v == (void *) 1 ? cell->servers.next : _p->next;
-
-	return _p != &cell->servers ? _p : NULL;
+	return seq_list_next(v, &cell->servers, _pos);
 }
 
 /*
@@ -790,11 +731,12 @@
  */
 static int afs_proc_cell_servers_show(struct seq_file *m, void *v)
 {
+	struct afs_cell *cell = m->private;
 	struct afs_server *server = list_entry(v, struct afs_server, link);
 	char ipaddr[20];
 
 	/* display header on line 1 */
-	if (v == (void *) 1) {
+	if (v == &cell->servers) {
 		seq_puts(m, "USE ADDR            STATE\n");
 		return 0;
 	}
diff --git a/fs/afs/security.c b/fs/afs/security.c
index e0ea88b..566fe71 100644
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/ctype.h>
+#include <linux/sched.h>
 #include <keys/rxrpc-type.h>
 #include "internal.h"
 
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 8d47ad8..993cdf1 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -22,6 +22,7 @@
 #include <linux/pagemap.h>
 #include <linux/parser.h>
 #include <linux/statfs.h>
+#include <linux/sched.h>
 #include "internal.h"
 
 #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
@@ -459,6 +460,9 @@
 	spin_lock_init(&vnode->writeback_lock);
 	spin_lock_init(&vnode->lock);
 	INIT_LIST_HEAD(&vnode->writebacks);
+	INIT_LIST_HEAD(&vnode->pending_locks);
+	INIT_LIST_HEAD(&vnode->granted_locks);
+	INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work);
 	INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
 }
 
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 3370cdb..09e3ad0 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include "internal.h"
 
 unsigned afs_vlocation_timeout = 10;	/* volume location timeout in seconds */
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index c36c98c..2f05c4f 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/sched.h>
 #include "internal.h"
 
 #if 0
@@ -560,7 +561,7 @@
 /*
  * create a hard link
  */
-extern int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
+int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
 			  struct key *key, const char *name)
 {
 	struct afs_server *server;
@@ -886,11 +887,6 @@
 	       vnode->fid.unique,
 	       key_serial(key));
 
-	/* this op will fetch the status */
-	spin_lock(&vnode->lock);
-	vnode->update_cnt++;
-	spin_unlock(&vnode->lock);
-
 	do {
 		/* pick a server to query */
 		server = afs_volume_pick_fileserver(vnode);
@@ -904,20 +900,127 @@
 	} while (!afs_volume_release_fileserver(vnode, server, ret));
 
 	/* adjust the flags */
-	if (ret == 0) {
-		afs_vnode_finalise_status_update(vnode, server);
+	if (ret == 0)
 		afs_put_server(server);
-	} else {
-		afs_vnode_status_update_failed(vnode, ret);
-	}
 
 	_leave(" = %d", ret);
 	return ret;
 
 no_server:
-	spin_lock(&vnode->lock);
-	vnode->update_cnt--;
-	ASSERTCMP(vnode->update_cnt, >=, 0);
-	spin_unlock(&vnode->lock);
+	return PTR_ERR(server);
+}
+
+/*
+ * get a lock on a file
+ */
+int afs_vnode_set_lock(struct afs_vnode *vnode, struct key *key,
+		       afs_lock_type_t type)
+{
+	struct afs_server *server;
+	int ret;
+
+	_enter("%s{%x:%u.%u},%x,%u",
+	       vnode->volume->vlocation->vldb.name,
+	       vnode->fid.vid,
+	       vnode->fid.vnode,
+	       vnode->fid.unique,
+	       key_serial(key), type);
+
+	do {
+		/* pick a server to query */
+		server = afs_volume_pick_fileserver(vnode);
+		if (IS_ERR(server))
+			goto no_server;
+
+		_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+		ret = afs_fs_set_lock(server, key, vnode, type, &afs_sync_call);
+
+	} while (!afs_volume_release_fileserver(vnode, server, ret));
+
+	/* adjust the flags */
+	if (ret == 0)
+		afs_put_server(server);
+
+	_leave(" = %d", ret);
+	return ret;
+
+no_server:
+	return PTR_ERR(server);
+}
+
+/*
+ * extend a lock on a file
+ */
+int afs_vnode_extend_lock(struct afs_vnode *vnode, struct key *key)
+{
+	struct afs_server *server;
+	int ret;
+
+	_enter("%s{%x:%u.%u},%x",
+	       vnode->volume->vlocation->vldb.name,
+	       vnode->fid.vid,
+	       vnode->fid.vnode,
+	       vnode->fid.unique,
+	       key_serial(key));
+
+	do {
+		/* pick a server to query */
+		server = afs_volume_pick_fileserver(vnode);
+		if (IS_ERR(server))
+			goto no_server;
+
+		_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+		ret = afs_fs_extend_lock(server, key, vnode, &afs_sync_call);
+
+	} while (!afs_volume_release_fileserver(vnode, server, ret));
+
+	/* adjust the flags */
+	if (ret == 0)
+		afs_put_server(server);
+
+	_leave(" = %d", ret);
+	return ret;
+
+no_server:
+	return PTR_ERR(server);
+}
+
+/*
+ * release a lock on a file
+ */
+int afs_vnode_release_lock(struct afs_vnode *vnode, struct key *key)
+{
+	struct afs_server *server;
+	int ret;
+
+	_enter("%s{%x:%u.%u},%x",
+	       vnode->volume->vlocation->vldb.name,
+	       vnode->fid.vid,
+	       vnode->fid.vnode,
+	       vnode->fid.unique,
+	       key_serial(key));
+
+	do {
+		/* pick a server to query */
+		server = afs_volume_pick_fileserver(vnode);
+		if (IS_ERR(server))
+			goto no_server;
+
+		_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+		ret = afs_fs_release_lock(server, key, vnode, &afs_sync_call);
+
+	} while (!afs_volume_release_fileserver(vnode, server, ret));
+
+	/* adjust the flags */
+	if (ret == 0)
+		afs_put_server(server);
+
+	_leave(" = %d", ret);
+	return ret;
+
+no_server:
 	return PTR_ERR(server);
 }
diff --git a/fs/afs/volume.c b/fs/afs/volume.c
index dd160ca..8bab0e3 100644
--- a/fs/afs/volume.c
+++ b/fs/afs/volume.c
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/sched.h>
 #include "internal.h"
 
 static const char *afs_voltypes[] = { "R/W", "R/O", "BAK" };
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 40fe3a3..b4a7588 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -53,7 +53,7 @@
 };
 
 /**
- * anon_inode_getfd - creates a new file instance by hooking it up to and
+ * anon_inode_getfd - creates a new file instance by hooking it up to an
  *                    anonymous inode, and a dentry that describe the "class"
  *                    of the file
  *
@@ -66,7 +66,7 @@
  *
  * Creates a new file by hooking it on a single inode. This is useful for files
  * that do not need to have a full-fledged inode in order to operate correctly.
- * All the files created with anon_inode_getfd() will share a single inode, by
+ * All the files created with anon_inode_getfd() will share a single inode,
  * hence saving memory and avoiding code duplication for the file/inode/dentry
  * setup.
  */
@@ -139,11 +139,12 @@
 	put_filp(file);
 	return error;
 }
+EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
 /*
- * A single inode exist for all anon_inode files. Contrary to pipes,
- * anon_inode inodes has no per-instance data associated, so we can avoid
- * the allocation of multiple of them.
+ * A single inode exists for all anon_inode files. Contrary to pipes,
+ * anon_inode inodes have no associated per-instance data, so we need
+ * only allocate one of them.
  */
 static struct inode *anon_inode_mkinode(void)
 {
diff --git a/fs/attr.c b/fs/attr.c
index a0a0c7b..f8dfc22 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -42,7 +42,7 @@
 
 	/* Make sure a caller can chmod. */
 	if (ia_valid & ATTR_MODE) {
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			goto error;
 		/* Also check the setgid bit! */
 		if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
@@ -52,7 +52,7 @@
 
 	/* Check for setting the inode time. */
 	if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
-		if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			goto error;
 	}
 fine:
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 329ee47..521ff7c 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -114,12 +114,6 @@
 	return -EIO;
 }
 
-static ssize_t bad_file_sendfile(struct file *in_file, loff_t *ppos,
-			size_t count, read_actor_t actor, void *target)
-{
-	return -EIO;
-}
-
 static ssize_t bad_file_sendpage(struct file *file, struct page *page,
 			int off, size_t len, loff_t *pos, int more)
 {
@@ -182,7 +176,6 @@
 	.aio_fsync	= bad_file_aio_fsync,
 	.fasync		= bad_file_fasync,
 	.lock		= bad_file_lock,
-	.sendfile	= bad_file_sendfile,
 	.sendpage	= bad_file_sendpage,
 	.get_unmapped_area = bad_file_get_unmapped_area,
 	.check_flags	= bad_file_check_flags,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index ef4d1fa..24310e9 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -24,7 +24,7 @@
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index fa8ea33..a27e42b 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -45,7 +45,7 @@
 
 static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
 static int load_elf_library(struct file *);
-static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
+static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);
 
 /*
  * If we don't support core dumping, then supply a NULL so we
@@ -80,7 +80,7 @@
 		.hasvdso	= 1
 };
 
-#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
+#define BAD_ADDR(x) IS_ERR_VALUE(x)
 
 static int set_brk(unsigned long start, unsigned long end)
 {
@@ -285,33 +285,70 @@
 #ifndef elf_map
 
 static unsigned long elf_map(struct file *filep, unsigned long addr,
-		struct elf_phdr *eppnt, int prot, int type)
+		struct elf_phdr *eppnt, int prot, int type,
+		unsigned long total_size)
 {
 	unsigned long map_addr;
-	unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
+	unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr);
+	unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr);
+	addr = ELF_PAGESTART(addr);
+	size = ELF_PAGEALIGN(size);
 
-	down_write(&current->mm->mmap_sem);
 	/* mmap() will return -EINVAL if given a zero size, but a
 	 * segment with zero filesize is perfectly valid */
-	if (eppnt->p_filesz + pageoffset)
-		map_addr = do_mmap(filep, ELF_PAGESTART(addr),
-				   eppnt->p_filesz + pageoffset, prot, type,
-				   eppnt->p_offset - pageoffset);
-	else
-		map_addr = ELF_PAGESTART(addr);
+	if (!size)
+		return addr;
+
+	down_write(&current->mm->mmap_sem);
+	/*
+	* total_size is the size of the ELF (interpreter) image.
+	* The _first_ mmap needs to know the full size, otherwise
+	* randomization might put this image into an overlapping
+	* position with the ELF binary image. (since size < total_size)
+	* So we first map the 'big' image - and unmap the remainder at
+	* the end. (which unmap is needed for ELF images with holes.)
+	*/
+	if (total_size) {
+		total_size = ELF_PAGEALIGN(total_size);
+		map_addr = do_mmap(filep, addr, total_size, prot, type, off);
+		if (!BAD_ADDR(map_addr))
+			do_munmap(current->mm, map_addr+size, total_size-size);
+	} else
+		map_addr = do_mmap(filep, addr, size, prot, type, off);
+
 	up_write(&current->mm->mmap_sem);
 	return(map_addr);
 }
 
 #endif /* !elf_map */
 
+static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
+{
+	int i, first_idx = -1, last_idx = -1;
+
+	for (i = 0; i < nr; i++) {
+		if (cmds[i].p_type == PT_LOAD) {
+			last_idx = i;
+			if (first_idx == -1)
+				first_idx = i;
+		}
+	}
+	if (first_idx == -1)
+		return 0;
+
+	return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz -
+				ELF_PAGESTART(cmds[first_idx].p_vaddr);
+}
+
+
 /* This is much more generalized than the library routine read function,
    so we keep this separate.  Technically the library read function
    is only provided so that we can read a.out libraries that have
    an ELF header */
 
 static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
-		struct file *interpreter, unsigned long *interp_load_addr)
+		struct file *interpreter, unsigned long *interp_map_addr,
+		unsigned long no_base)
 {
 	struct elf_phdr *elf_phdata;
 	struct elf_phdr *eppnt;
@@ -319,6 +356,7 @@
 	int load_addr_set = 0;
 	unsigned long last_bss = 0, elf_bss = 0;
 	unsigned long error = ~0UL;
+	unsigned long total_size;
 	int retval, i, size;
 
 	/* First of all, some simple consistency checks */
@@ -357,6 +395,12 @@
 		goto out_close;
 	}
 
+	total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
+	if (!total_size) {
+		error = -EINVAL;
+		goto out_close;
+	}
+
 	eppnt = elf_phdata;
 	for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
 		if (eppnt->p_type == PT_LOAD) {
@@ -374,9 +418,14 @@
 			vaddr = eppnt->p_vaddr;
 			if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
 				elf_type |= MAP_FIXED;
+			else if (no_base && interp_elf_ex->e_type == ET_DYN)
+				load_addr = -vaddr;
 
 			map_addr = elf_map(interpreter, load_addr + vaddr,
-					   eppnt, elf_prot, elf_type);
+					   eppnt, elf_prot, elf_type, total_size);
+			total_size = 0;
+			if (!*interp_map_addr)
+				*interp_map_addr = map_addr;
 			error = map_addr;
 			if (BAD_ADDR(map_addr))
 				goto out_close;
@@ -442,8 +491,7 @@
 			goto out_close;
 	}
 
-	*interp_load_addr = load_addr;
-	error = ((unsigned long)interp_elf_ex->e_entry) + load_addr;
+	error = load_addr;
 
 out_close:
 	kfree(elf_phdata);
@@ -540,7 +588,8 @@
 	int elf_exec_fileno;
 	int retval, i;
 	unsigned int size;
-	unsigned long elf_entry, interp_load_addr = 0;
+	unsigned long elf_entry;
+	unsigned long interp_load_addr = 0;
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long reloc_func_desc = 0;
 	char passed_fileno[6];
@@ -808,9 +857,7 @@
 	current->mm->start_stack = bprm->p;
 
 	/* Now we do a little grungy work by mmaping the ELF image into
-	   the correct location in memory.  At this point, we assume that
-	   the image should be loaded at fixed address, not at a variable
-	   address. */
+	   the correct location in memory. */
 	for(i = 0, elf_ppnt = elf_phdata;
 	    i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
 		int elf_prot = 0, elf_flags;
@@ -864,11 +911,15 @@
 			 * default mmap base, as well as whatever program they
 			 * might try to exec.  This is because the brk will
 			 * follow the loader, and is not movable.  */
+#ifdef CONFIG_X86
+			load_bias = 0;
+#else
 			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
+#endif
 		}
 
 		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-				elf_prot, elf_flags);
+				elf_prot, elf_flags,0);
 		if (BAD_ADDR(error)) {
 			send_sig(SIGKILL, current, 0);
 			retval = IS_ERR((void *)error) ?
@@ -944,13 +995,25 @@
 	}
 
 	if (elf_interpreter) {
-		if (interpreter_type == INTERPRETER_AOUT)
+		if (interpreter_type == INTERPRETER_AOUT) {
 			elf_entry = load_aout_interp(&loc->interp_ex,
 						     interpreter);
-		else
+		} else {
+			unsigned long uninitialized_var(interp_map_addr);
+
 			elf_entry = load_elf_interp(&loc->interp_elf_ex,
 						    interpreter,
-						    &interp_load_addr);
+						    &interp_map_addr,
+						    load_bias);
+			if (!BAD_ADDR(elf_entry)) {
+				/*
+				 * load_elf_interp() returns relocation
+				 * adjustment
+				 */
+				interp_load_addr = elf_entry;
+				elf_entry += loc->interp_elf_ex.e_entry;
+			}
+		}
 		if (BAD_ADDR(elf_entry)) {
 			force_sig(SIGSEGV, current);
 			retval = IS_ERR((void *)elf_entry) ?
@@ -1499,6 +1562,9 @@
 #endif
 	int thread_status_size = 0;
 	elf_addr_t *auxv;
+#ifdef ELF_CORE_WRITE_EXTRA_NOTES
+	int extra_notes_size;
+#endif
 
 	/*
 	 * We no longer stop all VM operations.
@@ -1628,7 +1694,8 @@
 		sz += thread_status_size;
 
 #ifdef ELF_CORE_WRITE_EXTRA_NOTES
-		sz += ELF_CORE_EXTRA_NOTES_SIZE;
+		extra_notes_size = ELF_CORE_EXTRA_NOTES_SIZE;
+		sz += extra_notes_size;
 #endif
 
 		fill_elf_note_phdr(&phdr, sz, offset);
@@ -1674,6 +1741,7 @@
 
 #ifdef ELF_CORE_WRITE_EXTRA_NOTES
 	ELF_CORE_WRITE_EXTRA_NOTES;
+	foffset += extra_notes_size;
 #endif
 
 	/* write out the thread status notes section */
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 7b0265d..861141b 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -558,7 +558,7 @@
 			if (!realdatastart)
 				realdatastart = (unsigned long) -ENOMEM;
 			printk("Unable to allocate RAM for process data, errno %d\n",
-					(int)-datapos);
+					(int)-realdatastart);
 			do_munmap(current->mm, textpos, text_len);
 			ret = realdatastart;
 			goto err;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 72d0b41..330fd3f 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -18,7 +18,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-
+#include <linux/sched.h>
 #include <linux/binfmts.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
diff --git a/fs/bio.c b/fs/bio.c
index 093345f..33e4634 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1223,8 +1223,6 @@
 EXPORT_SYMBOL(bio_add_page);
 EXPORT_SYMBOL(bio_add_pc_page);
 EXPORT_SYMBOL(bio_get_nr_vecs);
-EXPORT_SYMBOL(bio_map_user);
-EXPORT_SYMBOL(bio_unmap_user);
 EXPORT_SYMBOL(bio_map_kern);
 EXPORT_SYMBOL(bio_pair_release);
 EXPORT_SYMBOL(bio_split);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index ea1480a..3635315e 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -588,12 +588,10 @@
 
 long nr_blockdev_pages(void)
 {
-	struct list_head *p;
+	struct block_device *bdev;
 	long ret = 0;
 	spin_lock(&bdev_lock);
-	list_for_each(p, &all_bdevs) {
-		struct block_device *bdev;
-		bdev = list_entry(p, struct block_device, bd_list);
+	list_for_each_entry(bdev, &all_bdevs, bd_list) {
 		ret += bdev->bd_inode->i_mapping->nrpages;
 	}
 	spin_unlock(&bdev_lock);
@@ -874,7 +872,7 @@
  */
 static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
 {
-	int ret;
+	int err;
 
 	if (!bo)
 		return -EINVAL;
@@ -882,15 +880,18 @@
 	if (!bd_holder_grab_dirs(bdev, bo))
 		return -EBUSY;
 
-	ret = add_symlink(bo->sdir, bo->sdev);
-	if (ret == 0) {
-		ret = add_symlink(bo->hdir, bo->hdev);
-		if (ret)
-			del_symlink(bo->sdir, bo->sdev);
+	err = add_symlink(bo->sdir, bo->sdev);
+	if (err)
+		return err;
+
+	err = add_symlink(bo->hdir, bo->hdev);
+	if (err) {
+		del_symlink(bo->sdir, bo->sdev);
+		return err;
 	}
-	if (ret == 0)
-		list_add_tail(&bo->list, &bdev->bd_holder_list);
-	return ret;
+
+	list_add_tail(&bo->list, &bdev->bd_holder_list);
+	return 0;
 }
 
 /**
@@ -948,7 +949,7 @@
 static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
 				struct kobject *kobj)
 {
-	int res;
+	int err;
 	struct bd_holder *bo, *found;
 
 	if (!kobj)
@@ -959,21 +960,24 @@
 		return -ENOMEM;
 
 	mutex_lock(&bdev->bd_mutex);
-	res = bd_claim(bdev, holder);
-	if (res == 0) {
-		found = find_bd_holder(bdev, bo);
-		if (found == NULL) {
-			res = add_bd_holder(bdev, bo);
-			if (res)
-				bd_release(bdev);
-		}
-	}
 
-	if (res || found)
-		free_bd_holder(bo);
+	err = bd_claim(bdev, holder);
+	if (err)
+		goto fail;
+
+	found = find_bd_holder(bdev, bo);
+	if (found)
+		goto fail;
+
+	err = add_bd_holder(bdev, bo);
+	if (err)
+		bd_release(bdev);
+	else
+		bo = NULL;
+fail:
 	mutex_unlock(&bdev->bd_mutex);
-
-	return res;
+	free_bd_holder(bo);
+	return err;
 }
 
 /**
@@ -987,15 +991,12 @@
 static void bd_release_from_kobject(struct block_device *bdev,
 					struct kobject *kobj)
 {
-	struct bd_holder *bo;
-
 	if (!kobj)
 		return;
 
 	mutex_lock(&bdev->bd_mutex);
 	bd_release(bdev);
-	if ((bo = del_bd_holder(bdev, kobj)))
-		free_bd_holder(bo);
+	free_bd_holder(del_bd_holder(bdev, kobj));
 	mutex_unlock(&bdev->bd_mutex);
 }
 
@@ -1346,7 +1347,6 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= compat_blkdev_ioctl,
 #endif
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
diff --git a/fs/buffer.c b/fs/buffer.c
index 49590d59..0f90067 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -356,7 +356,7 @@
 	for_each_online_pgdat(pgdat) {
 		zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
 		if (*zones)
-			try_to_free_pages(zones, GFP_NOFS);
+			try_to_free_pages(zones, 0, GFP_NOFS);
 	}
 }
 
@@ -676,6 +676,39 @@
 EXPORT_SYMBOL(mark_buffer_dirty_inode);
 
 /*
+ * Mark the page dirty, and set it dirty in the radix tree, and mark the inode
+ * dirty.
+ *
+ * If warn is true, then emit a warning if the page is not uptodate and has
+ * not been truncated.
+ */
+static int __set_page_dirty(struct page *page,
+		struct address_space *mapping, int warn)
+{
+	if (unlikely(!mapping))
+		return !TestSetPageDirty(page);
+
+	if (TestSetPageDirty(page))
+		return 0;
+
+	write_lock_irq(&mapping->tree_lock);
+	if (page->mapping) {	/* Race with truncate? */
+		WARN_ON_ONCE(warn && !PageUptodate(page));
+
+		if (mapping_cap_account_dirty(mapping)) {
+			__inc_zone_page_state(page, NR_FILE_DIRTY);
+			task_io_account_write(PAGE_CACHE_SIZE);
+		}
+		radix_tree_tag_set(&mapping->page_tree,
+				page_index(page), PAGECACHE_TAG_DIRTY);
+	}
+	write_unlock_irq(&mapping->tree_lock);
+	__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+
+	return 1;
+}
+
+/*
  * Add a page to the dirty page list.
  *
  * It is a sad fact of life that this function is called from several places
@@ -702,7 +735,7 @@
  */
 int __set_page_dirty_buffers(struct page *page)
 {
-	struct address_space * const mapping = page_mapping(page);
+	struct address_space *mapping = page_mapping(page);
 
 	if (unlikely(!mapping))
 		return !TestSetPageDirty(page);
@@ -719,21 +752,7 @@
 	}
 	spin_unlock(&mapping->private_lock);
 
-	if (TestSetPageDirty(page))
-		return 0;
-
-	write_lock_irq(&mapping->tree_lock);
-	if (page->mapping) {	/* Race with truncate? */
-		if (mapping_cap_account_dirty(mapping)) {
-			__inc_zone_page_state(page, NR_FILE_DIRTY);
-			task_io_account_write(PAGE_CACHE_SIZE);
-		}
-		radix_tree_tag_set(&mapping->page_tree,
-				page_index(page), PAGECACHE_TAG_DIRTY);
-	}
-	write_unlock_irq(&mapping->tree_lock);
-	__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
-	return 1;
+	return __set_page_dirty(page, mapping, 1);
 }
 EXPORT_SYMBOL(__set_page_dirty_buffers);
 
@@ -982,7 +1001,7 @@
 	struct buffer_head *bh;
 
 	page = find_or_create_page(inode->i_mapping, index,
-		mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+		(mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
 	if (!page)
 		return NULL;
 
@@ -1026,11 +1045,6 @@
 /*
  * Create buffers for the specified block device block's page.  If
  * that page was dirty, the buffers are set dirty also.
- *
- * Except that's a bug.  Attaching dirty buffers to a dirty
- * blockdev's page can result in filesystem corruption, because
- * some of those buffers may be aliases of filesystem data.
- * grow_dev_page() will go BUG() if this happens.
  */
 static int
 grow_buffers(struct block_device *bdev, sector_t block, int size)
@@ -1137,8 +1151,9 @@
  */
 void fastcall mark_buffer_dirty(struct buffer_head *bh)
 {
+	WARN_ON_ONCE(!buffer_uptodate(bh));
 	if (!buffer_dirty(bh) && !test_set_buffer_dirty(bh))
-		__set_page_dirty_nobuffers(bh->b_page);
+		__set_page_dirty(bh->b_page, page_mapping(bh->b_page), 0);
 }
 
 /*
@@ -2101,7 +2116,7 @@
 						PAGE_CACHE_SIZE, get_block);
 		if (status)
 			goto out_unmap;
-		zero_user_page(page, zerofrom, PAGE_CACHE_SIZE - zerofrom,
+		zero_user_page(new_page, zerofrom, PAGE_CACHE_SIZE - zerofrom,
 				KM_USER0);
 		generic_commit_write(NULL, new_page, zerofrom, PAGE_CACHE_SIZE);
 		unlock_page(new_page);
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 6017c46..07838b2 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -7,16 +7,16 @@
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or 
+ *   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 
+ *   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/fs.h>
@@ -39,7 +39,7 @@
 	char *charptr = data;
 	char buf[10], line[80];
 
-	printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n", 
+	printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
 		label, length, data);
 	for (i = 0; i < length; i += 16) {
 		line[0] = 0;
@@ -60,10 +60,10 @@
 #ifdef CONFIG_CIFS_DEBUG2
 void cifs_dump_detail(struct smb_hdr * smb)
 {
-	cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
+	cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
 		  smb->Command, smb->Status.CifsError,
 		  smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
-	cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
+	cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
 }
 
 
@@ -72,36 +72,35 @@
 	struct list_head *tmp;
 	struct mid_q_entry * mid_entry;
 
-	if(server == NULL)
+	if (server == NULL)
 		return;
 
-	cERROR(1,("Dump pending requests:"));
+	cERROR(1, ("Dump pending requests:"));
 	spin_lock(&GlobalMid_Lock);
 	list_for_each(tmp, &server->pending_mid_q) {
 		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
-		if(mid_entry) {
-			cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
+		if (mid_entry) {
+			cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
 				mid_entry->midState,
 				(int)mid_entry->command,
 				mid_entry->pid,
 				mid_entry->tsk,
 				mid_entry->mid));
 #ifdef CONFIG_CIFS_STATS2
-			cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
+			cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
 				mid_entry->largeBuf,
 				mid_entry->resp_buf,
 				mid_entry->when_received,
 				jiffies));
 #endif /* STATS2 */
-			cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
+			cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
 				  mid_entry->multiEnd));
-			if(mid_entry->resp_buf) {
+			if (mid_entry->resp_buf) {
 				cifs_dump_detail(mid_entry->resp_buf);
 				cifs_dump_mem("existing buf: ",
 					mid_entry->resp_buf,
 					62 /* fixme */);
 			}
-			
 		}
 	}
 	spin_unlock(&GlobalMid_Lock);
@@ -129,9 +128,10 @@
 		    "Display Internal CIFS Data Structures for Debugging\n"
 		    "---------------------------------------------------\n");
 	buf += length;
-	length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
+	length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
 	buf += length;
-	length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid);
+	length = sprintf(buf,
+		"Active VFS Requests: %d\n", GlobalTotalActiveXid);
 	buf += length;
 	length = sprintf(buf, "Servers:");
 	buf += length;
@@ -141,7 +141,7 @@
 	list_for_each(tmp, &GlobalSMBSessionList) {
 		i++;
 		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
-		if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
+		if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
 		   (ses->serverNOS == NULL)) {
 			buf += sprintf(buf, "\nentry for %s not fully "
 					"displayed\n\t", ses->serverName);
@@ -149,15 +149,18 @@
 		} else {
 			length =
 			    sprintf(buf,
-				    "\n%d) Name: %s  Domain: %s Mounts: %d OS: %s  \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t",
+				    "\n%d) Name: %s  Domain: %s Mounts: %d OS:"
+				    " %s  \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
+				    " session status: %d\t",
 				i, ses->serverName, ses->serverDomain,
 				atomic_read(&ses->inUse),
 				ses->serverOS, ses->serverNOS,
-				ses->capabilities,ses->status);
+				ses->capabilities, ses->status);
 			buf += length;
 		}
-		if(ses->server) {
-			buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
+		if (ses->server) {
+			buf += sprintf(buf, "TCP status: %d\n\tLocal Users To "
+				    "Server: %d SecMode: 0x%x Req On Wire: %d",
 				ses->server->tcpStatus,
 				atomic_read(&ses->server->socketUseCount),
 				ses->server->secMode,
@@ -165,7 +168,7 @@
 
 #ifdef CONFIG_CIFS_STATS2
 			buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
-				atomic_read(&ses->server->inSend), 
+				atomic_read(&ses->server->inSend),
 				atomic_read(&ses->server->num_waiters));
 #endif
 
@@ -177,17 +180,19 @@
 				mid_entry = list_entry(tmp1, struct
 					mid_q_entry,
 					qhead);
-				if(mid_entry) {
-					length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",
-						mid_entry->midState,
-						(int)mid_entry->command,
-						mid_entry->pid,
-						mid_entry->tsk,
-						mid_entry->mid);
+				if (mid_entry) {
+					length = sprintf(buf,
+							"State: %d com: %d pid:"
+							" %d tsk: %p mid %d\n",
+							mid_entry->midState,
+							(int)mid_entry->command,
+							mid_entry->pid,
+							mid_entry->tsk,
+							mid_entry->mid);
 					buf += length;
 				}
 			}
-			spin_unlock(&GlobalMid_Lock); 
+			spin_unlock(&GlobalMid_Lock);
 		}
 
 	}
@@ -207,7 +212,8 @@
 		dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
 		length =
 		    sprintf(buf,
-			    "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
+			    "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
+			    "Attributes: 0x%x\nPathComponentMax: %d Status: %d",
 			    i, tcon->treeName,
 			    atomic_read(&tcon->useCount),
 			    tcon->nativeFileSystem,
@@ -215,7 +221,7 @@
 			    le32_to_cpu(tcon->fsAttrInfo.Attributes),
 			    le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
 			    tcon->tidStatus);
-		buf += length;        
+		buf += length;
 		if (dev_type == FILE_DEVICE_DISK)
 			length = sprintf(buf, " type: DISK ");
 		else if (dev_type == FILE_DEVICE_CD_ROM)
@@ -224,7 +230,7 @@
 			length =
 			    sprintf(buf, " type: %d ", dev_type);
 		buf += length;
-		if(tcon->tidStatus == CifsNeedReconnect) {
+		if (tcon->tidStatus == CifsNeedReconnect) {
 			buf += sprintf(buf, "\tDISCONNECTED ");
 			length += 14;
 		}
@@ -238,9 +244,9 @@
 	/* Now calculate total size of returned data */
 	length = buf - original_buf;
 
-	if(offset + count >= length)
+	if (offset + count >= length)
 		*eof = 1;
-	if(length < offset) {
+	if (length < offset) {
 		*eof = 1;
 		return 0;
 	} else {
@@ -256,18 +262,18 @@
 
 static int
 cifs_stats_write(struct file *file, const char __user *buffer,
-               unsigned long count, void *data)
+		 unsigned long count, void *data)
 {
-        char c;
-        int rc;
+	char c;
+	int rc;
 	struct list_head *tmp;
 	struct cifsTconInfo *tcon;
 
-        rc = get_user(c, buffer);
-        if (rc)
-                return rc;
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
 
-        if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
+	if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
 		read_lock(&GlobalSMBSeslock);
 #ifdef CONFIG_CIFS_STATS2
 		atomic_set(&totBufAllocCount, 0);
@@ -297,14 +303,14 @@
 		read_unlock(&GlobalSMBSeslock);
 	}
 
-        return count;
+	return count;
 }
 
 static int
 cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
 		  int count, int *eof, void *data)
 {
-	int item_length,i,length;
+	int item_length, i, length;
 	struct list_head *tmp;
 	struct cifsTconInfo *tcon;
 
@@ -314,44 +320,44 @@
 			"Resources in use\nCIFS Session: %d\n",
 			sesInfoAllocCount.counter);
 	buf += length;
-	item_length = 
-		sprintf(buf,"Share (unique mount targets): %d\n",
+	item_length =
+		sprintf(buf, "Share (unique mount targets): %d\n",
 			tconInfoAllocCount.counter);
 	length += item_length;
-	buf += item_length;      
-	item_length = 
-		sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
+	buf += item_length;
+	item_length =
+		sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n",
 			bufAllocCount.counter,
 			cifs_min_rcv + tcpSesAllocCount.counter);
 	length += item_length;
 	buf += item_length;
-	item_length = 
-		sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
-			smBufAllocCount.counter,cifs_min_small);
+	item_length =
+		sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
+			smBufAllocCount.counter, cifs_min_small);
 	length += item_length;
 	buf += item_length;
 #ifdef CONFIG_CIFS_STATS2
-        item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
+	item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
 				atomic_read(&totBufAllocCount),
-		                atomic_read(&totSmBufAllocCount));
+				atomic_read(&totSmBufAllocCount));
 	length += item_length;
 	buf += item_length;
 #endif /* CONFIG_CIFS_STATS2 */
 
-	item_length = 
-		sprintf(buf,"Operations (MIDs): %d\n",
+	item_length =
+		sprintf(buf, "Operations (MIDs): %d\n",
 			midCount.counter);
 	length += item_length;
 	buf += item_length;
 	item_length = sprintf(buf,
 		"\n%d session %d share reconnects\n",
-		tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
+		tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
 	length += item_length;
 	buf += item_length;
 
 	item_length = sprintf(buf,
 		"Total vfs operations: %d maximum at one time: %d\n",
-		GlobalCurrentXid,GlobalMaxActiveXid);
+		GlobalCurrentXid, GlobalMaxActiveXid);
 	length += item_length;
 	buf += item_length;
 
@@ -360,10 +366,10 @@
 	list_for_each(tmp, &GlobalTreeConnectionList) {
 		i++;
 		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
-		item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
+		item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName);
 		buf += item_length;
 		length += item_length;
-		if(tcon->tidStatus == CifsNeedReconnect) {
+		if (tcon->tidStatus == CifsNeedReconnect) {
 			buf += sprintf(buf, "\tDISCONNECTED ");
 			length += 14;
 		}
@@ -380,15 +386,15 @@
 		item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
 			atomic_read(&tcon->num_writes),
 			(long long)(tcon->bytes_written));
-                buf += item_length;
-                length += item_length;
-                item_length = sprintf(buf, 
+		buf += item_length;
+		length += item_length;
+		item_length = sprintf(buf,
 			"\nLocks: %d HardLinks: %d Symlinks: %d",
-                        atomic_read(&tcon->num_locks),
+			atomic_read(&tcon->num_locks),
 			atomic_read(&tcon->num_hardlinks),
 			atomic_read(&tcon->num_symlinks));
-                buf += item_length;
-                length += item_length;
+		buf += item_length;
+		length += item_length;
 
 		item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
 			atomic_read(&tcon->num_opens),
@@ -415,12 +421,12 @@
 	}
 	read_unlock(&GlobalSMBSeslock);
 
-	buf += sprintf(buf,"\n");
+	buf += sprintf(buf, "\n");
 	length++;
 
-	if(offset + count >= length)
+	if (offset + count >= length)
 		*eof = 1;
-	if(length < offset) {
+	if (length < offset) {
 		*eof = 1;
 		return 0;
 	} else {
@@ -428,7 +434,7 @@
 	}
 	if (length > count)
 		length = count;
-		
+
 	return length;
 }
 #endif
@@ -547,11 +553,11 @@
 	remove_proc_entry("MultiuserMount", proc_fs_cifs);
 	remove_proc_entry("OplockEnabled", proc_fs_cifs);
 /*	remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
-	remove_proc_entry("SecurityFlags",proc_fs_cifs);
-/*	remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
-	remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
-	remove_proc_entry("Experimental",proc_fs_cifs);
-	remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
+	remove_proc_entry("SecurityFlags", proc_fs_cifs);
+/*	remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */
+	remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
+	remove_proc_entry("Experimental", proc_fs_cifs);
+	remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
 	remove_proc_entry("cifs", proc_root_fs);
 }
 
@@ -590,7 +596,7 @@
 		cifsFYI = 0;
 	else if (c == '1' || c == 'y' || c == 'Y')
 		cifsFYI = 1;
-	else if((c > '1') && (c <= '9'))
+	else if ((c > '1') && (c <= '9'))
 		cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
 
 	return count;
@@ -637,28 +643,28 @@
 
 static int
 experimEnabled_read(char *page, char **start, off_t off,
-                   int count, int *eof, void *data)
+		    int count, int *eof, void *data)
 {
-        int len;
+	int len;
 
-        len = sprintf(page, "%d\n", experimEnabled);
+	len = sprintf(page, "%d\n", experimEnabled);
 
-        len -= off;
-        *start = page + off;
+	len -= off;
+	*start = page + off;
 
-        if (len > count)
-                len = count;
-        else
-                *eof = 1;
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
 
-        if (len < 0)
-                len = 0;
+	if (len < 0)
+		len = 0;
 
-        return len;
+	return len;
 }
 static int
 experimEnabled_write(struct file *file, const char __user *buffer,
-                    unsigned long count, void *data)
+		     unsigned long count, void *data)
 {
 	char c;
 	int rc;
@@ -678,46 +684,46 @@
 
 static int
 linuxExtensionsEnabled_read(char *page, char **start, off_t off,
-                   int count, int *eof, void *data)
+			    int count, int *eof, void *data)
 {
-        int len;
+	int len;
 
-        len = sprintf(page, "%d\n", linuxExtEnabled);
-        len -= off;
-        *start = page + off;
+	len = sprintf(page, "%d\n", linuxExtEnabled);
+	len -= off;
+	*start = page + off;
 
-        if (len > count)
-                len = count;
-        else
-                *eof = 1;
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
 
-        if (len < 0)
-                len = 0;
+	if (len < 0)
+		len = 0;
 
-        return len;
+	return len;
 }
 static int
 linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
-                    unsigned long count, void *data)
+			     unsigned long count, void *data)
 {
-        char c;
-        int rc;
+	char c;
+	int rc;
 
-        rc = get_user(c, buffer);
-        if (rc)
-                return rc;
-        if (c == '0' || c == 'n' || c == 'N')
-                linuxExtEnabled = 0;
-        else if (c == '1' || c == 'y' || c == 'Y')
-                linuxExtEnabled = 1;
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		linuxExtEnabled = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		linuxExtEnabled = 1;
 
-        return count;
+	return count;
 }
 
 
 static int
 lookupFlag_read(char *page, char **start, off_t off,
-		   int count, int *eof, void *data)
+		int count, int *eof, void *data)
 {
 	int len;
 
@@ -860,15 +866,15 @@
 	char flags_string[12];
 	char c;
 
-	if((count < 1) || (count > 11))
+	if ((count < 1) || (count > 11))
 		return -EINVAL;
 
 	memset(flags_string, 0, 12);
 
-	if(copy_from_user(flags_string, buffer, count))
+	if (copy_from_user(flags_string, buffer, count))
 		return -EFAULT;
 
-	if(count < 3) {
+	if (count < 3) {
 		/* single char or single char followed by null */
 		c = flags_string[0];
 		if (c == '0' || c == 'n' || c == 'N')
@@ -881,15 +887,15 @@
 
 	flags = simple_strtoul(flags_string, NULL, 0);
 
-	cFYI(1,("sec flags 0x%x", flags));
+	cFYI(1, ("sec flags 0x%x", flags));
 
-	if(flags <= 0)  {
-		cERROR(1,("invalid security flags %s",flags_string));
+	if (flags <= 0)  {
+		cERROR(1, ("invalid security flags %s", flags_string));
 		return -EINVAL;
 	}
 
-	if(flags & ~CIFSSEC_MASK) {
-		cERROR(1,("attempt to set unsupported security flags 0x%x",
+	if (flags & ~CIFSSEC_MASK) {
+		cERROR(1, ("attempt to set unsupported security flags 0x%x",
 			flags & ~CIFSSEC_MASK));
 		return -EINVAL;
 	}
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 793c4b9..701e9a9 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -6,16 +6,16 @@
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or 
+ *   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 
+ *   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/fs.h>
@@ -32,7 +32,7 @@
  *
  */
 int
-cifs_strfromUCS_le(char *to, const __le16 * from,	
+cifs_strfromUCS_le(char *to, const __le16 * from,
 		   int len, const struct nls_table *codepage)
 {
 	int i;
@@ -66,7 +66,7 @@
 {
 	int charlen;
 	int i;
-	wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */  
+	wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
 
 	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
 
@@ -79,7 +79,7 @@
 			/* A question mark */
 			to[i] = cpu_to_le16(0x003f);
 			charlen = 1;
-		} else 
+		} else
 			to[i] = cpu_to_le16(wchar_to[i]);
 
 	}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d38c69b..bd0f2f2 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -616,7 +616,7 @@
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
-	.sendfile = generic_file_sendfile,
+	.splice_read = generic_file_splice_read,
 	.llseek = cifs_llseek,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl	= cifs_ioctl,
@@ -637,7 +637,7 @@
 	.lock = cifs_lock,
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
-	.sendfile = generic_file_sendfile, /* BB removeme BB */
+	.splice_read = generic_file_splice_read,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl  = cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
@@ -656,7 +656,7 @@
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
-	.sendfile = generic_file_sendfile,
+	.splice_read = generic_file_splice_read,
 	.llseek = cifs_llseek,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl	= cifs_ioctl,
@@ -676,7 +676,7 @@
 	.release = cifs_close,
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
-	.sendfile = generic_file_sendfile, /* BB removeme BB */
+	.splice_read = generic_file_splice_read,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl  = cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
@@ -825,8 +825,8 @@
 				sizeof (struct oplock_q_entry), 0,
 				SLAB_HWCACHE_ALIGN, NULL, NULL);
 	if (cifs_oplock_cachep == NULL) {
-		kmem_cache_destroy(cifs_mid_cachep);
 		mempool_destroy(cifs_mid_poolp);
+		kmem_cache_destroy(cifs_mid_cachep);
 		return -ENOMEM;
 	}
 
@@ -849,6 +849,7 @@
 	__u16  netfid;
 	int rc;
 
+	set_freezable();
 	do {
 		if (try_to_freeze()) 
 			continue;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 14de58f..57419a1 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -433,8 +433,8 @@
 	cFYI(1,("secFlags 0x%x",secFlags));
 
 	pSMB->hdr.Mid = GetNextMid(server);
-	pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
-	if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
+	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
+	if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 	
 	count = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 216fb62..0a1b8bd 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -363,6 +363,7 @@
 			GFP_KERNEL);
 	}
 
+	set_freezable();
 	while (!kthread_should_stop()) {
 		if (try_to_freeze())
 			continue;
@@ -2069,8 +2070,15 @@
 			srvTcp->tcpStatus = CifsExiting;
 			spin_unlock(&GlobalMid_Lock);
 			if (srvTcp->tsk) {
+				struct task_struct *tsk;
+				/* If we could verify that kthread_stop would
+				   always wake up processes blocked in
+				   tcp in recv_mesg then we could remove the
+				   send_sig call */
 				send_sig(SIGKILL,srvTcp->tsk,1);
-				kthread_stop(srvTcp->tsk);
+				tsk = srvTcp->tsk;
+				if(tsk)
+					kthread_stop(tsk);
 			}
 		}
 		 /* If find_unc succeeded then rc == 0 so we can not end */
@@ -2085,8 +2093,11 @@
 					/* if the socketUseCount is now zero */
 					if ((temp_rc == -ESHUTDOWN) &&
 					   (pSesInfo->server) && (pSesInfo->server->tsk)) {
+						struct task_struct *tsk;
 						send_sig(SIGKILL,pSesInfo->server->tsk,1);
-						kthread_stop(pSesInfo->server->tsk);
+						tsk = pSesInfo->server->tsk;
+						if (tsk)
+							kthread_stop(tsk);
 					}
 				} else
 					cFYI(1, ("No session or bad tcon"));
@@ -3334,7 +3345,7 @@
 				return 0;
 			} else if (rc == -ESHUTDOWN) {
 				cFYI(1,("Waking up socket by sending it signal"));
-				if(cifsd_task) {
+				if (cifsd_task) {
 					send_sig(SIGKILL,cifsd_task,1);
 					kthread_stop(cifsd_task);
 				}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e521051..8e86aac 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -2,7 +2,7 @@
  *   fs/cifs/dir.c
  *
  *   vfs operations that deal with dentries
- * 
+ *
  *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
@@ -34,11 +34,12 @@
 static void
 renew_parental_timestamps(struct dentry *direntry)
 {
-	/* BB check if there is a way to get the kernel to do this or if we really need this */
+	/* BB check if there is a way to get the kernel to do this or if we
+	   really need this */
 	do {
 		direntry->d_time = jiffies;
 		direntry = direntry->d_parent;
-	} while (!IS_ROOT(direntry));	
+	} while (!IS_ROOT(direntry));
 }
 
 /* Note: caller must free return buffer */
@@ -51,7 +52,7 @@
 	char *full_path;
 	char dirsep;
 
-	if(direntry == NULL)
+	if (direntry == NULL)
 		return NULL;  /* not much we can do if dentry is freed and
 		we need to reopen the file after it was closed implicitly
 		when the server crashed */
@@ -59,18 +60,18 @@
 	dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
 	pplen = CIFS_SB(direntry->d_sb)->prepathlen;
 cifs_bp_rename_retry:
-	namelen = pplen; 
+	namelen = pplen;
 	for (temp = direntry; !IS_ROOT(temp);) {
 		namelen += (1 + temp->d_name.len);
 		temp = temp->d_parent;
-		if(temp == NULL) {
-			cERROR(1,("corrupt dentry"));
+		if (temp == NULL) {
+			cERROR(1, ("corrupt dentry"));
 			return NULL;
 		}
 	}
 
 	full_path = kmalloc(namelen+1, GFP_KERNEL);
-	if(full_path == NULL)
+	if (full_path == NULL)
 		return full_path;
 	full_path[namelen] = 0;	/* trailing null */
 	for (temp = direntry; !IS_ROOT(temp);) {
@@ -84,8 +85,8 @@
 			cFYI(0, ("name: %s", full_path + namelen));
 		}
 		temp = temp->d_parent;
-		if(temp == NULL) {
-			cERROR(1,("corrupt dentry"));
+		if (temp == NULL) {
+			cERROR(1, ("corrupt dentry"));
 			kfree(full_path);
 			return NULL;
 		}
@@ -94,7 +95,7 @@
 		cERROR(1,
 		       ("did not end path lookup where expected namelen is %d",
 			namelen));
-		/* presumably this is only possible if racing with a rename 
+		/* presumably this is only possible if racing with a rename
 		of one of the parent directories  (we can not lock the dentries
 		above us to prevent this, but retrying should be harmless) */
 		kfree(full_path);
@@ -106,7 +107,7 @@
 	   since the '\' is a valid posix character so we can not switch
 	   those safely to '/' if any are found in the middle of the prepath */
 	/* BB test paths to Windows with '/' in the midst of prepath */
-	strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen);
+	strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen);
 	return full_path;
 }
 
@@ -147,12 +148,12 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
-	if(full_path == NULL) {
+	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
 	}
 
-	if(nd && (nd->flags & LOOKUP_OPEN)) {
+	if (nd && (nd->flags & LOOKUP_OPEN)) {
 		int oflags = nd->intent.open.flags;
 
 		desiredAccess = 0;
@@ -164,28 +165,29 @@
 				write_only = TRUE;
 		}
 
-		if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+		if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
 			disposition = FILE_CREATE;
-		else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+		else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
 			disposition = FILE_OVERWRITE_IF;
-		else if((oflags & O_CREAT) == O_CREAT)
+		else if ((oflags & O_CREAT) == O_CREAT)
 			disposition = FILE_OPEN_IF;
 		else {
-			cFYI(1,("Create flag not set in create function"));
+			cFYI(1, ("Create flag not set in create function"));
 		}
 	}
 
-	/* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
+	/* BB add processing to set equivalent of mode - e.g. via CreateX with
+	   ACLs */
 	if (oplockEnabled)
 		oplock = REQ_OPLOCK;
 
-	buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
-	if(buf == NULL) {
+	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+	if (buf == NULL) {
 		kfree(full_path);
 		FreeXid(xid);
 		return -ENOMEM;
 	}
-	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) 
+	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
 		rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
 			 desiredAccess, CREATE_NOT_DIR,
 			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
@@ -193,27 +195,28 @@
 	else
 		rc = -EIO; /* no NT SMB support fall into legacy open below */
 
-	if(rc == -EIO) {
+	if (rc == -EIO) {
 		/* old server, retry the open legacy style */
 		rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
 			desiredAccess, CREATE_NOT_DIR,
 			&fileHandle, &oplock, buf, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
-	} 
+	}
 	if (rc) {
 		cFYI(1, ("cifs_create returned 0x%x", rc));
 	} else {
 		/* If Open reported that we actually created a file
 		then we now have to set the mode if possible */
 		if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
-			(oplock & CIFS_CREATE_ACTION))
-			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+			(oplock & CIFS_CREATE_ACTION)) {
+			mode &= ~current->fs->umask;
+			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
 					(__u64)current->fsuid,
 					(__u64)current->fsgid,
 					0 /* dev */,
-					cifs_sb->local_nls, 
-					cifs_sb->mnt_cifs_flags & 
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			} else {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
@@ -221,26 +224,28 @@
 					(__u64)-1,
 					0 /* dev */,
 					cifs_sb->local_nls,
-					cifs_sb->mnt_cifs_flags & 
+					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			}
-		else {
-			/* BB implement mode setting via Windows security descriptors */
-			/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
-			/* could set r/o dos attribute if mode & 0222 == 0 */
+		} else {
+			/* BB implement mode setting via Windows security
+			   descriptors e.g. */
+			/* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/
+
+			/* Could set r/o dos attribute if mode & 0222 == 0 */
 		}
 
 	/* BB server might mask mode so we have to query for Unix case*/
 		if (pTcon->ses->capabilities & CAP_UNIX)
 			rc = cifs_get_inode_info_unix(&newinode, full_path,
-						 inode->i_sb,xid);
+						 inode->i_sb, xid);
 		else {
 			rc = cifs_get_inode_info(&newinode, full_path,
-						 buf, inode->i_sb,xid);
-			if(newinode) {
+						 buf, inode->i_sb, xid);
+			if (newinode) {
 				newinode->i_mode = mode;
-				if((oplock & CIFS_CREATE_ACTION) &&
-				  (cifs_sb->mnt_cifs_flags & 
+				if ((oplock & CIFS_CREATE_ACTION) &&
+				    (cifs_sb->mnt_cifs_flags &
 				     CIFS_MOUNT_SET_UID)) {
 					newinode->i_uid = current->fsuid;
 					newinode->i_gid = current->fsgid;
@@ -259,14 +264,14 @@
 				direntry->d_op = &cifs_dentry_ops;
 			d_instantiate(direntry, newinode);
 		}
-		if((nd->flags & LOOKUP_OPEN) == FALSE) {
+		if ((nd->flags & LOOKUP_OPEN) == FALSE) {
 			/* mknod case - do not leave file open */
 			CIFSSMBClose(xid, pTcon, fileHandle);
-		} else if(newinode) {
+		} else if (newinode) {
 			pCifsFile =
 			   kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
-			
-			if(pCifsFile == NULL)
+
+			if (pCifsFile == NULL)
 				goto cifs_create_out;
 			pCifsFile->netfid = fileHandle;
 			pCifsFile->pid = current->tgid;
@@ -276,33 +281,33 @@
 			init_MUTEX(&pCifsFile->fh_sem);
 			mutex_init(&pCifsFile->lock_mutex);
 			INIT_LIST_HEAD(&pCifsFile->llist);
-			atomic_set(&pCifsFile->wrtPending,0);
+			atomic_set(&pCifsFile->wrtPending, 0);
 
-			/* set the following in open now 
+			/* set the following in open now
 				pCifsFile->pfile = file; */
 			write_lock(&GlobalSMBSeslock);
-			list_add(&pCifsFile->tlist,&pTcon->openFileList);
+			list_add(&pCifsFile->tlist, &pTcon->openFileList);
 			pCifsInode = CIFS_I(newinode);
-			if(pCifsInode) {
+			if (pCifsInode) {
 				/* if readable file instance put first in list*/
 				if (write_only == TRUE) {
-                                       	list_add_tail(&pCifsFile->flist,
+					list_add_tail(&pCifsFile->flist,
 						&pCifsInode->openFileList);
 				} else {
 					list_add(&pCifsFile->flist,
 						&pCifsInode->openFileList);
 				}
-				if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+				if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
 					pCifsInode->clientCanCacheAll = TRUE;
 					pCifsInode->clientCanCacheRead = TRUE;
-					cFYI(1,("Exclusive Oplock for inode %p",
+					cFYI(1, ("Exclusive Oplock inode %p",
 						newinode));
-				} else if((oplock & 0xF) == OPLOCK_READ)
+				} else if ((oplock & 0xF) == OPLOCK_READ)
 					pCifsInode->clientCanCacheRead = TRUE;
 			}
 			write_unlock(&GlobalSMBSeslock);
 		}
-	} 
+	}
 cifs_create_out:
 	kfree(buf);
 	kfree(full_path);
@@ -310,8 +315,8 @@
 	return rc;
 }
 
-int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, 
-		dev_t device_number) 
+int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
+		dev_t device_number)
 {
 	int rc = -EPERM;
 	int xid;
@@ -329,43 +334,45 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
-	if(full_path == NULL)
+	if (full_path == NULL)
 		rc = -ENOMEM;
 	else if (pTcon->ses->capabilities & CAP_UNIX) {
-		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+		mode &= ~current->fs->umask;
+		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
-				mode,(__u64)current->fsuid,(__u64)current->fsgid,
+				mode, (__u64)current->fsuid,
+				(__u64)current->fsgid,
 				device_number, cifs_sb->local_nls,
-				cifs_sb->mnt_cifs_flags & 
+				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 		} else {
 			rc = CIFSSMBUnixSetPerms(xid, pTcon,
 				full_path, mode, (__u64)-1, (__u64)-1,
 				device_number, cifs_sb->local_nls,
-				cifs_sb->mnt_cifs_flags & 
+				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 		}
 
-		if(!rc) {
+		if (!rc) {
 			rc = cifs_get_inode_info_unix(&newinode, full_path,
-						inode->i_sb,xid);
+						inode->i_sb, xid);
 			if (pTcon->nocase)
 				direntry->d_op = &cifs_ci_dentry_ops;
 			else
 				direntry->d_op = &cifs_dentry_ops;
-			if(rc == 0)
+			if (rc == 0)
 				d_instantiate(direntry, newinode);
 		}
 	} else {
-		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
 			int oplock = 0;
 			u16 fileHandle;
 			FILE_ALL_INFO * buf;
 
-			cFYI(1,("sfu compat create special file"));
+			cFYI(1, ("sfu compat create special file"));
 
-			buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
-			if(buf == NULL) {
+			buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+			if (buf == NULL) {
 				kfree(full_path);
 				FreeXid(xid);
 				return -ENOMEM;
@@ -373,39 +380,38 @@
 
 			rc = CIFSSMBOpen(xid, pTcon, full_path,
 					 FILE_CREATE, /* fail if exists */
-					 GENERIC_WRITE /* BB would 
+					 GENERIC_WRITE /* BB would
 					  WRITE_OWNER | WRITE_DAC be better? */,
 					 /* Create a file and set the
 					    file attribute to SYSTEM */
 					 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
 					 &fileHandle, &oplock, buf,
 					 cifs_sb->local_nls,
-					 cifs_sb->mnt_cifs_flags & 
+					 cifs_sb->mnt_cifs_flags &
 					    CIFS_MOUNT_MAP_SPECIAL_CHR);
 
 			/* BB FIXME - add handling for backlevel servers
 			   which need legacy open and check for all
-			   calls to SMBOpen for fallback to 
-			   SMBLeagcyOpen */
-			if(!rc) {
+			   calls to SMBOpen for fallback to SMBLeagcyOpen */
+			if (!rc) {
 				/* BB Do not bother to decode buf since no
 				   local inode yet to put timestamps in,
 				   but we can reuse it safely */
 				int bytes_written;
 				struct win_dev *pdev;
 				pdev = (struct win_dev *)buf;
-				if(S_ISCHR(mode)) {
+				if (S_ISCHR(mode)) {
 					memcpy(pdev->type, "IntxCHR", 8);
 					pdev->major =
 					      cpu_to_le64(MAJOR(device_number));
-					pdev->minor = 
+					pdev->minor =
 					      cpu_to_le64(MINOR(device_number));
 					rc = CIFSSMBWrite(xid, pTcon,
 						fileHandle,
 						sizeof(struct win_dev),
 						0, &bytes_written, (char *)pdev,
 						NULL, 0);
-				} else if(S_ISBLK(mode)) {
+				} else if (S_ISBLK(mode)) {
 					memcpy(pdev->type, "IntxBLK", 8);
 					pdev->major =
 					      cpu_to_le64(MAJOR(device_number));
@@ -432,7 +438,8 @@
 
 
 struct dentry *
-cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
+	    struct nameidata *nd)
 {
 	int xid;
 	int rc = 0; /* to get around spurious gcc warning, set to zero here */
@@ -447,8 +454,6 @@
 	     (" parent inode = 0x%p name is: %s and dentry = 0x%p",
 	      parent_dir_inode, direntry->d_name.name, direntry));
 
-	/* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
-
 	/* check whether path exists */
 
 	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
@@ -472,7 +477,7 @@
 	deadlock in the cases (beginning of sys_rename itself)
 	in which we already have the sb rename sem */
 	full_path = build_path_from_dentry(direntry);
-	if(full_path == NULL) {
+	if (full_path == NULL) {
 		FreeXid(xid);
 		return ERR_PTR(-ENOMEM);
 	}
@@ -487,10 +492,10 @@
 
 	if (pTcon->ses->capabilities & CAP_UNIX)
 		rc = cifs_get_inode_info_unix(&newInode, full_path,
-					      parent_dir_inode->i_sb,xid);
+					      parent_dir_inode->i_sb, xid);
 	else
 		rc = cifs_get_inode_info(&newInode, full_path, NULL,
-					 parent_dir_inode->i_sb,xid);
+					 parent_dir_inode->i_sb, xid);
 
 	if ((rc == 0) && (newInode != NULL)) {
 		if (pTcon->nocase)
@@ -499,7 +504,7 @@
 			direntry->d_op = &cifs_dentry_ops;
 		d_add(direntry, newInode);
 
-		/* since paths are not looked up by component - the parent 
+		/* since paths are not looked up by component - the parent
 		   directories are presumed to be good here */
 		renew_parental_timestamps(direntry);
 
@@ -511,13 +516,13 @@
 		else
 			direntry->d_op = &cifs_dentry_ops;
 		d_add(direntry, NULL);
-	/*	if it was once a directory (but how can we tell?) we could do  
-			shrink_dcache_parent(direntry); */
+	/*	if it was once a directory (but how can we tell?) we could do
+		shrink_dcache_parent(direntry); */
 	} else {
-		cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
-			   rc,full_path));
-		/* BB special case check for Access Denied - watch security 
-		exposure of returning dir info implicitly via different rc 
+		cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s",
+			   rc, full_path));
+		/* BB special case check for Access Denied - watch security
+		exposure of returning dir info implicitly via different rc
 		if file exists or not but no access BB */
 	}
 
@@ -538,11 +543,11 @@
 	} else {
 		cFYI(1, ("neg dentry 0x%p name = %s",
 			 direntry, direntry->d_name.name));
-		if(time_after(jiffies, direntry->d_time + HZ) || 
+		if (time_after(jiffies, direntry->d_time + HZ) ||
 			!lookupCacheEnabled) {
 			d_drop(direntry);
 			isValid = 0;
-		} 
+		}
 	}
 
 	return isValid;
@@ -559,8 +564,7 @@
 
 struct dentry_operations cifs_dentry_ops = {
 	.d_revalidate = cifs_d_revalidate,
-/* d_delete:       cifs_d_delete,       *//* not needed except for debugging */
-	/* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
+/* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
 };
 
 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 1d71639..96df1d5 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -29,6 +29,7 @@
   */
 
 #include <linux/fs.h>
+#include <linux/exportfs.h>
  
 #ifdef CONFIG_CIFS_EXPERIMENTAL
  
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index da12b48..8e375bb 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -2,7 +2,7 @@
  *   fs/cifs/fcntl.c
  *
  *   vfs operations that deal with the file control API
- * 
+ *
  *   Copyright (C) International Business Machines  Corp., 2003,2004
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
@@ -35,35 +35,34 @@
 
 	/* No way on Linux VFS to ask to monitor xattr
 	changes (and no stream support either */
-	if(fcntl_notify_flags & DN_ACCESS) {
+	if (fcntl_notify_flags & DN_ACCESS) {
 		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
 	}
-	if(fcntl_notify_flags & DN_MODIFY) {
+	if (fcntl_notify_flags & DN_MODIFY) {
 		/* What does this mean on directories? */
 		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
 			FILE_NOTIFY_CHANGE_SIZE;
 	}
-	if(fcntl_notify_flags & DN_CREATE) {
-		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | 
+	if (fcntl_notify_flags & DN_CREATE) {
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
 			FILE_NOTIFY_CHANGE_LAST_WRITE;
 	}
-	if(fcntl_notify_flags & DN_DELETE) {
+	if (fcntl_notify_flags & DN_DELETE) {
 		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
 	}
-	if(fcntl_notify_flags & DN_RENAME) {
+	if (fcntl_notify_flags & DN_RENAME) {
 		/* BB review this - checking various server behaviors */
-		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | 
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
 			FILE_NOTIFY_CHANGE_FILE_NAME;
 	}
-	if(fcntl_notify_flags & DN_ATTRIB) {
-		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | 
+	if (fcntl_notify_flags & DN_ATTRIB) {
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
 			FILE_NOTIFY_CHANGE_ATTRIBUTES;
 	}
-/*	if(fcntl_notify_flags & DN_MULTISHOT) {
+/*	if (fcntl_notify_flags & DN_MULTISHOT) {
 		cifs_ntfy_flags |= ;
 	} */ /* BB fixme - not sure how to handle this with CIFS yet */
 
-
 	return cifs_ntfy_flags;
 }
 
@@ -78,8 +77,7 @@
 	__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
 	__u16 netfid;
 
-
-	if(experimEnabled == 0)
+	if (experimEnabled == 0)
 		return 0;
 
 	xid = GetXid();
@@ -88,21 +86,21 @@
 
 	full_path = build_path_from_dentry(file->f_path.dentry);
 
-	if(full_path == NULL) {
+	if (full_path == NULL) {
 		rc = -ENOMEM;
 	} else {
-		cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg));
-		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 
+		cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg));
+		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
 			GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
-			&netfid, &oplock,NULL, cifs_sb->local_nls,
+			&netfid, &oplock, NULL, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 		/* BB fixme - add this handle to a notify handle list */
-		if(rc) {
-			cFYI(1,("Could not open directory for notify"));
+		if (rc) {
+			cFYI(1, ("Could not open directory for notify"));
 		} else {
 			filter = convert_to_cifs_notify_flags(arg);
-			if(filter != 0) {
-				rc = CIFSSMBNotify(xid, pTcon, 
+			if (filter != 0) {
+				rc = CIFSSMBNotify(xid, pTcon,
 					0 /* no subdirs */, netfid,
 					filter, file, arg & DN_MULTISHOT,
 					cifs_sb->local_nls);
@@ -113,10 +111,10 @@
 			it would close automatically but may be a way
 			to do it easily when inode freed or when
 			notify info is cleared/changed */
-			cFYI(1,("notify rc %d",rc));
+			cFYI(1, ("notify rc %d", rc));
 		}
 	}
-	
+
 	FreeXid(xid);
 	return rc;
 }
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 3e87dad..f0ff12b 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -986,7 +986,8 @@
 		  * failed to get it from the server or was set bogus */ 
 		if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
 				direntry->d_inode->i_nlink = 2; 
-		if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+		if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+			mode &= ~current->fs->umask;
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
 						    mode,
@@ -1004,7 +1005,7 @@
 						    cifs_sb->mnt_cifs_flags & 
 						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 			}
-		else {
+		} else {
 			/* BB to be implemented via Windows secrty descriptors
 			   eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
 						 -1, -1, local_nls); */
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index e34c7db..a414f17 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -30,7 +30,7 @@
 
 #define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
 
-int cifs_ioctl (struct inode * inode, struct file * filep, 
+int cifs_ioctl (struct inode * inode, struct file * filep,
 		unsigned int command, unsigned long arg)
 {
 	int rc = -ENOTTY; /* strange error - but the precedent */
@@ -47,13 +47,13 @@
 
 	xid = GetXid();
 
-        cFYI(1,("ioctl file %p  cmd %u  arg %lu",filep,command,arg));
+	cFYI(1, ("ioctl file %p  cmd %u  arg %lu", filep, command, arg));
 
 	cifs_sb = CIFS_SB(inode->i_sb);
 
 #ifdef CONFIG_CIFS_POSIX
 	tcon = cifs_sb->tcon;
-	if(tcon)
+	if (tcon)
 		caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
 	else {
 		rc = -EIO;
@@ -62,24 +62,24 @@
 	}
 #endif /* CONFIG_CIFS_POSIX */
 
-	switch(command) {
+	switch (command) {
 		case CIFS_IOC_CHECKUMOUNT:
-			cFYI(1,("User unmount attempted"));
-			if(cifs_sb->mnt_uid == current->uid)
+			cFYI(1, ("User unmount attempted"));
+			if (cifs_sb->mnt_uid == current->uid)
 				rc = 0;
 			else {
 				rc = -EACCES;
-				cFYI(1,("uids do not match"));
+				cFYI(1, ("uids do not match"));
 			}
 			break;
 #ifdef CONFIG_CIFS_POSIX
 		case FS_IOC_GETFLAGS:
-			if(CIFS_UNIX_EXTATTR_CAP & caps) {
+			if (CIFS_UNIX_EXTATTR_CAP & caps) {
 				if (pSMBFile == NULL)
 					break;
 				rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
 					&ExtAttrBits, &ExtAttrMask);
-				if(rc == 0)
+				if (rc == 0)
 					rc = put_user(ExtAttrBits &
 						FS_FL_USER_VISIBLE,
 						(int __user *)arg);
@@ -87,8 +87,8 @@
 			break;
 
 		case FS_IOC_SETFLAGS:
-			if(CIFS_UNIX_EXTATTR_CAP & caps) {
-				if(get_user(ExtAttrBits,(int __user *)arg)) {
+			if (CIFS_UNIX_EXTATTR_CAP & caps) {
+				if (get_user(ExtAttrBits, (int __user *)arg)) {
 					rc = -EFAULT;
 					break;
 				}
@@ -96,16 +96,15 @@
 					break;
 				/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
 					extAttrBits, &ExtAttrMask);*/
-				
 			}
-			cFYI(1,("set flags not implemented yet"));
+			cFYI(1, ("set flags not implemented yet"));
 			break;
 #endif /* CONFIG_CIFS_POSIX */
 		default:
-			cFYI(1,("unsupported ioctl"));
+			cFYI(1, ("unsupported ioctl"));
 			break;
 	}
 
 	FreeXid(xid);
 	return rc;
-} 
+}
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
index aede606..8b69fcc 100644
--- a/fs/cifs/rfc1002pdu.h
+++ b/fs/cifs/rfc1002pdu.h
@@ -18,7 +18,7 @@
  *
  *   You should have received a copy of the GNU Lesser General Public License
  *   along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 /* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 5d05271..fcb88fa 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -16,6 +16,7 @@
 #include <asm/uaccess.h>
 #include <linux/string.h>
 #include <linux/list.h>
+#include <linux/sched.h>
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 9ddf5ed..898a86d 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -470,7 +470,7 @@
 
 		ret = -ENOENT;
 		if (!IS_DEADDIR(host_inode)) {
-			ret = host_file->f_op->readdir(host_file, filldir, dirent);
+			ret = host_file->f_op->readdir(host_file, dirent, filldir);
 			file_accessed(host_file);
 		}
 	}
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 5ef2b60..99dbe86 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -47,8 +47,9 @@
 }
 
 static ssize_t
-coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
-		   read_actor_t actor, void *target)
+coda_file_splice_read(struct file *coda_file, loff_t *ppos,
+		      struct pipe_inode_info *pipe, size_t count,
+		      unsigned int flags)
 {
 	struct coda_file_info *cfi;
 	struct file *host_file;
@@ -57,10 +58,10 @@
 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
 	host_file = cfi->cfi_container;
 
-	if (!host_file->f_op || !host_file->f_op->sendfile)
+	if (!host_file->f_op || !host_file->f_op->splice_read)
 		return -EINVAL;
 
-	return host_file->f_op->sendfile(host_file, ppos, count, actor, target);
+	return host_file->f_op->splice_read(host_file, ppos, pipe, count,flags);
 }
 
 static ssize_t
@@ -295,6 +296,6 @@
 	.flush		= coda_flush,
 	.release	= coda_release,
 	.fsync		= coda_fsync,
-	.sendfile	= coda_file_sendfile,
+	.splice_read	= coda_file_splice_read,
 };
 
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index a5b5e63..5faacdb 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -16,7 +16,7 @@
 
 #include <asm/system.h>
 #include <linux/signal.h>
-
+#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff --git a/fs/compat.c b/fs/compat.c
index 1de2331..4db6216 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1544,9 +1544,10 @@
 	compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
 {
 	fd_set_bits fds;
-	char *bits;
+	void *bits;
 	int size, max_fds, ret = -EINVAL;
 	struct fdtable *fdt;
+	long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
 
 	if (n < 0)
 		goto out_nofds;
@@ -1564,11 +1565,14 @@
 	 * since we used fdset we need to allocate memory in units of
 	 * long-words.
 	 */
-	ret = -ENOMEM;
 	size = FDS_BYTES(n);
-	bits = kmalloc(6 * size, GFP_KERNEL);
-	if (!bits)
-		goto out_nofds;
+	bits = stack_fds;
+	if (size > sizeof(stack_fds) / 6) {
+		bits = kmalloc(6 * size, GFP_KERNEL);
+		ret = -ENOMEM;
+		if (!bits)
+			goto out_nofds;
+	}
 	fds.in      = (unsigned long *)  bits;
 	fds.out     = (unsigned long *) (bits +   size);
 	fds.ex      = (unsigned long *) (bits + 2*size);
@@ -1600,7 +1604,8 @@
 	    compat_set_fd_set(n, exp, fds.res_ex))
 		ret = -EFAULT;
 out:
-	kfree(bits);
+	if (bits != stack_fds)
+		kfree(bits);
 out_nofds:
 	return ret;
 }
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 65643de..e440a7b 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -63,6 +63,7 @@
 #include <linux/wireless.h>
 #include <linux/atalk.h>
 #include <linux/blktrace_api.h>
+#include <linux/loop.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci.h>
@@ -1194,6 +1195,7 @@
 {
 	struct tty_struct *tty;
 	struct inode *inode = file->f_path.dentry->d_inode;
+	struct vc_data *vc;
 	
 	if (file->f_op->ioctl != tty_ioctl)
 		return -EINVAL;
@@ -1204,12 +1206,16 @@
 	                                                
 	if (tty->driver->ioctl != vt_ioctl)
 		return -EINVAL;
-	
+
+	vc = (struct vc_data *)tty->driver_data;
+	if (!vc_cons_allocated(vc->vc_num)) 	/* impossible? */
+		return -ENOIOCTLCMD;
+
 	/*
 	 * To have permissions to do most of the vt ioctls, we either have
-	 * to be the owner of the tty, or super-user.
+	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
 	 */
-	if (current->signal->tty == tty || capable(CAP_SYS_ADMIN))
+	if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
 		return 1;
 	return 0;                                                    
 }
@@ -1310,16 +1316,28 @@
 	struct unimapdesc32 tmp;
 	struct unimapdesc32 __user *user_ud = compat_ptr(arg);
 	int perm = vt_check(file);
-	
-	if (perm < 0) return perm;
+	struct vc_data *vc;
+
+	if (perm < 0)
+		return perm;
 	if (copy_from_user(&tmp, user_ud, sizeof tmp))
 		return -EFAULT;
+	if (tmp.entries)
+		if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries),
+				tmp.entry_ct*sizeof(struct unipair)))
+			return -EFAULT;
+	vc = ((struct tty_struct *)file->private_data)->driver_data;
 	switch (cmd) {
 	case PIO_UNIMAP:
-		if (!perm) return -EPERM;
-		return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries));
+		if (!perm)
+			return -EPERM;
+		return con_set_unimap(vc, tmp.entry_ct,
+						compat_ptr(tmp.entries));
 	case GIO_UNIMAP:
-		return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
+		if (!perm && fg_console != vc->vc_num)
+			return -EPERM;
+		return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
+						compat_ptr(tmp.entries));
 	}
 	return 0;
 }
@@ -3472,6 +3490,9 @@
 
 IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32)
 IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
+
+/* loop */
+IGNORE_IOCTL(LOOP_CLR_FD)
 };
 
 #define IOCTL_HASHSIZE 256
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 7b48c03..3b0185f 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -29,10 +29,11 @@
 
 struct configfs_dirent {
 	atomic_t		s_count;
+	int			s_dependent_count;
 	struct list_head	s_sibling;
 	struct list_head	s_children;
 	struct list_head	s_links;
-	void 			* s_element;
+	void			* s_element;
 	int			s_type;
 	umode_t			s_mode;
 	struct dentry		* s_dentry;
@@ -41,8 +42,8 @@
 
 #define CONFIGFS_ROOT		0x0001
 #define CONFIGFS_DIR		0x0002
-#define CONFIGFS_ITEM_ATTR 	0x0004
-#define CONFIGFS_ITEM_LINK 	0x0020
+#define CONFIGFS_ITEM_ATTR	0x0004
+#define CONFIGFS_ITEM_LINK	0x0020
 #define CONFIGFS_USET_DIR	0x0040
 #define CONFIGFS_USET_DEFAULT	0x0080
 #define CONFIGFS_USET_DROPPING	0x0100
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 5e6e37e..2f436d4 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -355,6 +355,10 @@
 			/* Mark that we've taken i_mutex */
 			sd->s_type |= CONFIGFS_USET_DROPPING;
 
+			/*
+			 * Yup, recursive.  If there's a problem, blame
+			 * deep nesting of default_groups
+			 */
 			ret = configfs_detach_prep(sd->s_dentry);
 			if (!ret)
 				continue;
@@ -562,7 +566,7 @@
 
 /*
  * All of link_obj/unlink_obj/link_group/unlink_group require that
- * subsys->su_sem is held.
+ * subsys->su_mutex is held.
  */
 
 static void unlink_obj(struct config_item *item)
@@ -714,6 +718,28 @@
 }
 
 /*
+ * After the item has been detached from the filesystem view, we are
+ * ready to tear it out of the hierarchy.  Notify the client before
+ * we do that so they can perform any cleanup that requires
+ * navigating the hierarchy.  A client does not need to provide this
+ * callback.  The subsystem semaphore MUST be held by the caller, and
+ * references must be valid for both items.  It also assumes the
+ * caller has validated ci_type.
+ */
+static void client_disconnect_notify(struct config_item *parent_item,
+				     struct config_item *item)
+{
+	struct config_item_type *type;
+
+	type = parent_item->ci_type;
+	BUG_ON(!type);
+
+	if (type->ct_group_ops && type->ct_group_ops->disconnect_notify)
+		type->ct_group_ops->disconnect_notify(to_config_group(parent_item),
+						      item);
+}
+
+/*
  * Drop the initial reference from make_item()/make_group()
  * This function assumes that reference is held on item
  * and that item holds a valid reference to the parent.  Also, it
@@ -733,11 +759,244 @@
 	 */
 	if (type->ct_group_ops && type->ct_group_ops->drop_item)
 		type->ct_group_ops->drop_item(to_config_group(parent_item),
-						item);
+					      item);
 	else
 		config_item_put(item);
 }
 
+#ifdef DEBUG
+static void configfs_dump_one(struct configfs_dirent *sd, int level)
+{
+	printk(KERN_INFO "%*s\"%s\":\n", level, " ", configfs_get_name(sd));
+
+#define type_print(_type) if (sd->s_type & _type) printk(KERN_INFO "%*s %s\n", level, " ", #_type);
+	type_print(CONFIGFS_ROOT);
+	type_print(CONFIGFS_DIR);
+	type_print(CONFIGFS_ITEM_ATTR);
+	type_print(CONFIGFS_ITEM_LINK);
+	type_print(CONFIGFS_USET_DIR);
+	type_print(CONFIGFS_USET_DEFAULT);
+	type_print(CONFIGFS_USET_DROPPING);
+#undef type_print
+}
+
+static int configfs_dump(struct configfs_dirent *sd, int level)
+{
+	struct configfs_dirent *child_sd;
+	int ret = 0;
+
+	configfs_dump_one(sd, level);
+
+	if (!(sd->s_type & (CONFIGFS_DIR|CONFIGFS_ROOT)))
+		return 0;
+
+	list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
+		ret = configfs_dump(child_sd, level + 2);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+#endif
+
+
+/*
+ * configfs_depend_item() and configfs_undepend_item()
+ *
+ * WARNING: Do not call these from a configfs callback!
+ *
+ * This describes these functions and their helpers.
+ *
+ * Allow another kernel system to depend on a config_item.  If this
+ * happens, the item cannot go away until the dependant can live without
+ * it.  The idea is to give client modules as simple an interface as
+ * possible.  When a system asks them to depend on an item, they just
+ * call configfs_depend_item().  If the item is live and the client
+ * driver is in good shape, we'll happily do the work for them.
+ *
+ * Why is the locking complex?  Because configfs uses the VFS to handle
+ * all locking, but this function is called outside the normal
+ * VFS->configfs path.  So it must take VFS locks to prevent the
+ * VFS->configfs stuff (configfs_mkdir(), configfs_rmdir(), etc).  This is
+ * why you can't call these functions underneath configfs callbacks.
+ *
+ * Note, btw, that this can be called at *any* time, even when a configfs
+ * subsystem isn't registered, or when configfs is loading or unloading.
+ * Just like configfs_register_subsystem().  So we take the same
+ * precautions.  We pin the filesystem.  We lock each i_mutex _in_order_
+ * on our way down the tree.  If we can find the target item in the
+ * configfs tree, it must be part of the subsystem tree as well, so we
+ * do not need the subsystem semaphore.  Holding the i_mutex chain locks
+ * out mkdir() and rmdir(), who might be racing us.
+ */
+
+/*
+ * configfs_depend_prep()
+ *
+ * Only subdirectories count here.  Files (CONFIGFS_NOT_PINNED) are
+ * attributes.  This is similar but not the same to configfs_detach_prep().
+ * Note that configfs_detach_prep() expects the parent to be locked when it
+ * is called, but we lock the parent *inside* configfs_depend_prep().  We
+ * do that so we can unlock it if we find nothing.
+ *
+ * Here we do a depth-first search of the dentry hierarchy looking for
+ * our object.  We take i_mutex on each step of the way down.  IT IS
+ * ESSENTIAL THAT i_mutex LOCKING IS ORDERED.  If we come back up a branch,
+ * we'll drop the i_mutex.
+ *
+ * If the target is not found, -ENOENT is bubbled up and we have released
+ * all locks.  If the target was found, the locks will be cleared by
+ * configfs_depend_rollback().
+ *
+ * This adds a requirement that all config_items be unique!
+ *
+ * This is recursive because the locking traversal is tricky.  There isn't
+ * much on the stack, though, so folks that need this function - be careful
+ * about your stack!  Patches will be accepted to make it iterative.
+ */
+static int configfs_depend_prep(struct dentry *origin,
+				struct config_item *target)
+{
+	struct configfs_dirent *child_sd, *sd = origin->d_fsdata;
+	int ret = 0;
+
+	BUG_ON(!origin || !sd);
+
+	/* Lock this guy on the way down */
+	mutex_lock(&sd->s_dentry->d_inode->i_mutex);
+	if (sd->s_element == target)  /* Boo-yah */
+		goto out;
+
+	list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
+		if (child_sd->s_type & CONFIGFS_DIR) {
+			ret = configfs_depend_prep(child_sd->s_dentry,
+						   target);
+			if (!ret)
+				goto out;  /* Child path boo-yah */
+		}
+	}
+
+	/* We looped all our children and didn't find target */
+	mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
+	ret = -ENOENT;
+
+out:
+	return ret;
+}
+
+/*
+ * This is ONLY called if configfs_depend_prep() did its job.  So we can
+ * trust the entire path from item back up to origin.
+ *
+ * We walk backwards from item, unlocking each i_mutex.  We finish by
+ * unlocking origin.
+ */
+static void configfs_depend_rollback(struct dentry *origin,
+				     struct config_item *item)
+{
+	struct dentry *dentry = item->ci_dentry;
+
+	while (dentry != origin) {
+		mutex_unlock(&dentry->d_inode->i_mutex);
+		dentry = dentry->d_parent;
+	}
+
+	mutex_unlock(&origin->d_inode->i_mutex);
+}
+
+int configfs_depend_item(struct configfs_subsystem *subsys,
+			 struct config_item *target)
+{
+	int ret;
+	struct configfs_dirent *p, *root_sd, *subsys_sd = NULL;
+	struct config_item *s_item = &subsys->su_group.cg_item;
+
+	/*
+	 * Pin the configfs filesystem.  This means we can safely access
+	 * the root of the configfs filesystem.
+	 */
+	ret = configfs_pin_fs();
+	if (ret)
+		return ret;
+
+	/*
+	 * Next, lock the root directory.  We're going to check that the
+	 * subsystem is really registered, and so we need to lock out
+	 * configfs_[un]register_subsystem().
+	 */
+	mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
+
+	root_sd = configfs_sb->s_root->d_fsdata;
+
+	list_for_each_entry(p, &root_sd->s_children, s_sibling) {
+		if (p->s_type & CONFIGFS_DIR) {
+			if (p->s_element == s_item) {
+				subsys_sd = p;
+				break;
+			}
+		}
+	}
+
+	if (!subsys_sd) {
+		ret = -ENOENT;
+		goto out_unlock_fs;
+	}
+
+	/* Ok, now we can trust subsys/s_item */
+
+	/* Scan the tree, locking i_mutex recursively, return 0 if found */
+	ret = configfs_depend_prep(subsys_sd->s_dentry, target);
+	if (ret)
+		goto out_unlock_fs;
+
+	/* We hold all i_mutexes from the subsystem down to the target */
+	p = target->ci_dentry->d_fsdata;
+	p->s_dependent_count += 1;
+
+	configfs_depend_rollback(subsys_sd->s_dentry, target);
+
+out_unlock_fs:
+	mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
+
+	/*
+	 * If we succeeded, the fs is pinned via other methods.  If not,
+	 * we're done with it anyway.  So release_fs() is always right.
+	 */
+	configfs_release_fs();
+
+	return ret;
+}
+EXPORT_SYMBOL(configfs_depend_item);
+
+/*
+ * Release the dependent linkage.  This is much simpler than
+ * configfs_depend_item() because we know that that the client driver is
+ * pinned, thus the subsystem is pinned, and therefore configfs is pinned.
+ */
+void configfs_undepend_item(struct configfs_subsystem *subsys,
+			    struct config_item *target)
+{
+	struct configfs_dirent *sd;
+
+	/*
+	 * Since we can trust everything is pinned, we just need i_mutex
+	 * on the item.
+	 */
+	mutex_lock(&target->ci_dentry->d_inode->i_mutex);
+
+	sd = target->ci_dentry->d_fsdata;
+	BUG_ON(sd->s_dependent_count < 1);
+
+	sd->s_dependent_count -= 1;
+
+	/*
+	 * After this unlock, we cannot trust the item to stay alive!
+	 * DO NOT REFERENCE item after this unlock.
+	 */
+	mutex_unlock(&target->ci_dentry->d_inode->i_mutex);
+}
+EXPORT_SYMBOL(configfs_undepend_item);
 
 static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
@@ -783,7 +1042,7 @@
 
 	snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
 
-	down(&subsys->su_sem);
+	mutex_lock(&subsys->su_mutex);
 	group = NULL;
 	item = NULL;
 	if (type->ct_group_ops->make_group) {
@@ -797,7 +1056,7 @@
 		if (item)
 			link_obj(parent_item, item);
 	}
-	up(&subsys->su_sem);
+	mutex_unlock(&subsys->su_mutex);
 
 	kfree(name);
 	if (!item) {
@@ -841,13 +1100,16 @@
 out_unlink:
 	if (ret) {
 		/* Tear down everything we built up */
-		down(&subsys->su_sem);
+		mutex_lock(&subsys->su_mutex);
+
+		client_disconnect_notify(parent_item, item);
 		if (group)
 			unlink_group(group);
 		else
 			unlink_obj(item);
 		client_drop_item(parent_item, item);
-		up(&subsys->su_sem);
+
+		mutex_unlock(&subsys->su_mutex);
 
 		if (module_got)
 			module_put(owner);
@@ -881,6 +1143,13 @@
 	if (sd->s_type & CONFIGFS_USET_DEFAULT)
 		return -EPERM;
 
+	/*
+	 * Here's where we check for dependents.  We're protected by
+	 * i_mutex.
+	 */
+	if (sd->s_dependent_count)
+		return -EBUSY;
+
 	/* Get a working ref until we have the child */
 	parent_item = configfs_get_config_item(dentry->d_parent);
 	subsys = to_config_group(parent_item)->cg_subsys;
@@ -910,17 +1179,19 @@
 	if (sd->s_type & CONFIGFS_USET_DIR) {
 		configfs_detach_group(item);
 
-		down(&subsys->su_sem);
+		mutex_lock(&subsys->su_mutex);
+		client_disconnect_notify(parent_item, item);
 		unlink_group(to_config_group(item));
 	} else {
 		configfs_detach_item(item);
 
-		down(&subsys->su_sem);
+		mutex_lock(&subsys->su_mutex);
+		client_disconnect_notify(parent_item, item);
 		unlink_obj(item);
 	}
 
 	client_drop_item(parent_item, item);
-	up(&subsys->su_sem);
+	mutex_unlock(&subsys->su_mutex);
 
 	/* Drop our reference from above */
 	config_item_put(item);
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index 3527c7c..a3658f9 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -27,19 +27,26 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
-#include <asm/semaphore.h>
 
 #include <linux/configfs.h>
 #include "configfs_internal.h"
 
+/*
+ * A simple attribute can only be 4096 characters.  Why 4k?  Because the
+ * original code limited it to PAGE_SIZE.  That's a bad idea, though,
+ * because an attribute of 16k on ia64 won't work on x86.  So we limit to
+ * 4k, our minimum common page size.
+ */
+#define SIMPLE_ATTR_SIZE 4096
 
 struct configfs_buffer {
 	size_t			count;
 	loff_t			pos;
 	char			* page;
 	struct configfs_item_operations	* ops;
-	struct semaphore	sem;
+	struct mutex		mutex;
 	int			needs_read_fill;
 };
 
@@ -69,7 +76,7 @@
 
 	count = ops->show_attribute(item,attr,buffer->page);
 	buffer->needs_read_fill = 0;
-	BUG_ON(count > (ssize_t)PAGE_SIZE);
+	BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
 	if (count >= 0)
 		buffer->count = count;
 	else
@@ -102,7 +109,7 @@
 	struct configfs_buffer * buffer = file->private_data;
 	ssize_t retval = 0;
 
-	down(&buffer->sem);
+	mutex_lock(&buffer->mutex);
 	if (buffer->needs_read_fill) {
 		if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
 			goto out;
@@ -112,7 +119,7 @@
 	retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
 					 buffer->count);
 out:
-	up(&buffer->sem);
+	mutex_unlock(&buffer->mutex);
 	return retval;
 }
 
@@ -137,8 +144,8 @@
 	if (!buffer->page)
 		return -ENOMEM;
 
-	if (count >= PAGE_SIZE)
-		count = PAGE_SIZE - 1;
+	if (count >= SIMPLE_ATTR_SIZE)
+		count = SIMPLE_ATTR_SIZE - 1;
 	error = copy_from_user(buffer->page,buf,count);
 	buffer->needs_read_fill = 1;
 	/* if buf is assumed to contain a string, terminate it by \0,
@@ -193,13 +200,13 @@
 	struct configfs_buffer * buffer = file->private_data;
 	ssize_t len;
 
-	down(&buffer->sem);
+	mutex_lock(&buffer->mutex);
 	len = fill_write_buffer(buffer, buf, count);
 	if (len > 0)
 		len = flush_write_buffer(file->f_path.dentry, buffer, count);
 	if (len > 0)
 		*ppos += len;
-	up(&buffer->sem);
+	mutex_unlock(&buffer->mutex);
 	return len;
 }
 
@@ -253,7 +260,7 @@
 		error = -ENOMEM;
 		goto Enomem;
 	}
-	init_MUTEX(&buffer->sem);
+	mutex_init(&buffer->mutex);
 	buffer->needs_read_fill = 1;
 	buffer->ops = ops;
 	file->private_data = buffer;
@@ -292,6 +299,7 @@
 	if (buffer) {
 		if (buffer->page)
 			free_page((unsigned long)buffer->page);
+		mutex_destroy(&buffer->mutex);
 		kfree(buffer);
 	}
 	return 0;
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 2ec9bea..ddc003a 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -32,6 +32,7 @@
 #include <linux/namei.h>
 #include <linux/backing-dev.h>
 #include <linux/capability.h>
+#include <linux/sched.h>
 
 #include <linux/configfs.h>
 #include "configfs_internal.h"
diff --git a/fs/configfs/item.c b/fs/configfs/item.c
index 2442120..76dc4c3 100644
--- a/fs/configfs/item.c
+++ b/fs/configfs/item.c
@@ -62,7 +62,6 @@
  *	dynamically allocated string that @item->ci_name points to.
  *	Otherwise, use the static @item->ci_namebuf array.
  */
-
 int config_item_set_name(struct config_item * item, const char * fmt, ...)
 {
 	int error = 0;
@@ -139,12 +138,7 @@
 	return item;
 }
 
-/**
- *	config_item_cleanup - free config_item resources.
- *	@item:	item.
- */
-
-void config_item_cleanup(struct config_item * item)
+static void config_item_cleanup(struct config_item * item)
 {
 	struct config_item_type * t = item->ci_type;
 	struct config_group * s = item->ci_group;
@@ -179,39 +173,35 @@
 		kref_put(&item->ci_kref, config_item_release);
 }
 
-
 /**
  *	config_group_init - initialize a group for use
  *	@k:	group
  */
-
 void config_group_init(struct config_group *group)
 {
 	config_item_init(&group->cg_item);
 	INIT_LIST_HEAD(&group->cg_children);
 }
 
-
 /**
- *	config_group_find_obj - search for item in group.
+ *	config_group_find_item - search for item in group.
  *	@group:	group we're looking in.
  *	@name:	item's name.
  *
- *	Lock group via @group->cg_subsys, and iterate over @group->cg_list,
- *	looking for a matching config_item. If matching item is found
- *	take a reference and return the item.
+ *	Iterate over @group->cg_list, looking for a matching config_item.
+ *	If matching item is found take a reference and return the item.
+ *	Caller must have locked group via @group->cg_subsys->su_mtx.
  */
-
-struct config_item * config_group_find_obj(struct config_group * group, const char * name)
+struct config_item *config_group_find_item(struct config_group *group,
+					   const char *name)
 {
 	struct list_head * entry;
 	struct config_item * ret = NULL;
 
-        /* XXX LOCKING! */
 	list_for_each(entry,&group->cg_children) {
 		struct config_item * item = to_item(entry);
 		if (config_item_name(item) &&
-                    !strcmp(config_item_name(item), name)) {
+		    !strcmp(config_item_name(item), name)) {
 			ret = config_item_get(item);
 			break;
 		}
@@ -219,9 +209,8 @@
 	return ret;
 }
 
-
 EXPORT_SYMBOL(config_item_init);
 EXPORT_SYMBOL(config_group_init);
 EXPORT_SYMBOL(config_item_get);
 EXPORT_SYMBOL(config_item_put);
-EXPORT_SYMBOL(config_group_find_obj);
+EXPORT_SYMBOL(config_group_find_item);
diff --git a/fs/dcache.c b/fs/dcache.c
index 0e73aa0..cb9d050 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -883,6 +883,11 @@
 	return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
 
+static struct shrinker dcache_shrinker = {
+	.shrink = shrink_dcache_memory,
+	.seeks = DEFAULT_SEEKS,
+};
+
 /**
  * d_alloc	-	allocate a dcache entry
  * @parent: parent of entry to allocate
@@ -2115,7 +2120,7 @@
 	dentry_cache = KMEM_CACHE(dentry,
 		SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
 	
-	set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
+	register_shrinker(&dcache_shrinker);
 
 	/* Hash may have been set up in dcache_init_early */
 	if (!hashdist)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index ec8896b..1d533a2 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -368,6 +368,69 @@
 }
 EXPORT_SYMBOL_GPL(debugfs_remove);
 
+/**
+ * debugfs_rename - rename a file/directory in the debugfs filesystem
+ * @old_dir: a pointer to the parent dentry for the renamed object. This
+ *          should be a directory dentry.
+ * @old_dentry: dentry of an object to be renamed.
+ * @new_dir: a pointer to the parent dentry where the object should be
+ *          moved. This should be a directory dentry.
+ * @new_name: a pointer to a string containing the target name.
+ *
+ * This function renames a file/directory in debugfs.  The target must not
+ * exist for rename to succeed.
+ *
+ * This function will return a pointer to old_dentry (which is updated to
+ * reflect renaming) if it succeeds. If an error occurs, %NULL will be
+ * returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+		struct dentry *new_dir, const char *new_name)
+{
+	int error;
+	struct dentry *dentry = NULL, *trap;
+	const char *old_name;
+
+	trap = lock_rename(new_dir, old_dir);
+	/* Source or destination directories don't exist? */
+	if (!old_dir->d_inode || !new_dir->d_inode)
+		goto exit;
+	/* Source does not exist, cyclic rename, or mountpoint? */
+	if (!old_dentry->d_inode || old_dentry == trap ||
+	    d_mountpoint(old_dentry))
+		goto exit;
+	dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
+	/* Lookup failed, cyclic rename or target exists? */
+	if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
+		goto exit;
+
+	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+
+	error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
+		dentry);
+	if (error) {
+		fsnotify_oldname_free(old_name);
+		goto exit;
+	}
+	d_move(old_dentry, dentry);
+	fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
+		old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
+		NULL, old_dentry->d_inode);
+	fsnotify_oldname_free(old_name);
+	unlock_rename(new_dir, old_dir);
+	dput(dentry);
+	return old_dentry;
+exit:
+	if (dentry && !IS_ERR(dentry))
+		dput(dentry);
+	unlock_rename(new_dir, old_dir);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(debugfs_rename);
+
 static decl_subsys(debug, NULL, NULL);
 
 static int __init debugfs_init(void)
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 8593f3d..52bb263 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1106,7 +1106,7 @@
 	spin_lock_irqsave(&dio->bio_lock, flags);
 	ret2 = --dio->refcount;
 	spin_unlock_irqrestore(&dio->bio_lock, flags);
-	BUG_ON(!dio->is_async && ret2 != 0);
+
 	if (ret2 == 0) {
 		ret = dio_complete(dio, offset, ret);
 		kfree(dio);
diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig
index 69a9469..54bcc00 100644
--- a/fs/dlm/Kconfig
+++ b/fs/dlm/Kconfig
@@ -3,7 +3,7 @@
 
 config DLM
 	tristate "Distributed Lock Manager (DLM)"
-	depends on IPV6 || IPV6=n
+	depends on SYSFS && (IPV6 || IPV6=n)
 	select CONFIGFS_FS
 	select IP_SCTP
 	help
diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile
index 604cf7d..d248e60 100644
--- a/fs/dlm/Makefile
+++ b/fs/dlm/Makefile
@@ -8,6 +8,7 @@
 				member.o \
 				memory.o \
 				midcomms.o \
+				netlink.o \
 				lowcomms.o \
 				rcom.o \
 				recover.o \
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 822abdc..2f8e3c8 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -90,6 +90,7 @@
 	unsigned int cl_scan_secs;
 	unsigned int cl_log_debug;
 	unsigned int cl_protocol;
+	unsigned int cl_timewarn_cs;
 };
 
 enum {
@@ -103,6 +104,7 @@
 	CLUSTER_ATTR_SCAN_SECS,
 	CLUSTER_ATTR_LOG_DEBUG,
 	CLUSTER_ATTR_PROTOCOL,
+	CLUSTER_ATTR_TIMEWARN_CS,
 };
 
 struct cluster_attribute {
@@ -131,14 +133,6 @@
 	return len;
 }
 
-#define __CONFIGFS_ATTR(_name,_mode,_read,_write) {                           \
-	.attr   = { .ca_name = __stringify(_name),                            \
-		    .ca_mode = _mode,                                         \
-		    .ca_owner = THIS_MODULE },                                \
-	.show   = _read,                                                      \
-	.store  = _write,                                                     \
-}
-
 #define CLUSTER_ATTR(name, check_zero)                                        \
 static ssize_t name##_write(struct cluster *cl, const char *buf, size_t len)  \
 {                                                                             \
@@ -162,6 +156,7 @@
 CLUSTER_ATTR(scan_secs, 1);
 CLUSTER_ATTR(log_debug, 0);
 CLUSTER_ATTR(protocol, 0);
+CLUSTER_ATTR(timewarn_cs, 1);
 
 static struct configfs_attribute *cluster_attrs[] = {
 	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
@@ -174,6 +169,7 @@
 	[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
 	[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
 	[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
+	[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
 	NULL,
 };
 
@@ -429,6 +425,8 @@
 	cl->cl_toss_secs = dlm_config.ci_toss_secs;
 	cl->cl_scan_secs = dlm_config.ci_scan_secs;
 	cl->cl_log_debug = dlm_config.ci_log_debug;
+	cl->cl_protocol = dlm_config.ci_protocol;
+	cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
 
 	space_list = &sps->ss_group;
 	comm_list = &cms->cs_group;
@@ -609,7 +607,7 @@
 int dlm_config_init(void)
 {
 	config_group_init(&clusters_root.subsys.su_group);
-	init_MUTEX(&clusters_root.subsys.su_sem);
+	mutex_init(&clusters_root.subsys.su_mutex);
 	return configfs_register_subsystem(&clusters_root.subsys);
 }
 
@@ -748,9 +746,16 @@
 
 static struct space *get_space(char *name)
 {
+	struct config_item *i;
+
 	if (!space_list)
 		return NULL;
-	return to_space(config_group_find_obj(space_list, name));
+
+	mutex_lock(&space_list->cg_subsys->su_mutex);
+	i = config_group_find_item(space_list, name);
+	mutex_unlock(&space_list->cg_subsys->su_mutex);
+
+	return to_space(i);
 }
 
 static void put_space(struct space *sp)
@@ -767,7 +772,7 @@
 	if (!comm_list)
 		return NULL;
 
-	down(&clusters_root.subsys.su_sem);
+	mutex_lock(&clusters_root.subsys.su_mutex);
 
 	list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
 		cm = to_comm(i);
@@ -776,20 +781,20 @@
 			if (cm->nodeid != nodeid)
 				continue;
 			found = 1;
+			config_item_get(i);
 			break;
 		} else {
 			if (!cm->addr_count ||
 			    memcmp(cm->addr[0], addr, sizeof(*addr)))
 				continue;
 			found = 1;
+			config_item_get(i);
 			break;
 		}
 	}
-	up(&clusters_root.subsys.su_sem);
+	mutex_unlock(&clusters_root.subsys.su_mutex);
 
-	if (found)
-		config_item_get(i);
-	else
+	if (!found)
 		cm = NULL;
 	return cm;
 }
@@ -909,6 +914,7 @@
 #define DEFAULT_SCAN_SECS          5
 #define DEFAULT_LOG_DEBUG          0
 #define DEFAULT_PROTOCOL           0
+#define DEFAULT_TIMEWARN_CS      500 /* 5 sec = 500 centiseconds */
 
 struct dlm_config_info dlm_config = {
 	.ci_tcp_port = DEFAULT_TCP_PORT,
@@ -920,6 +926,7 @@
 	.ci_toss_secs = DEFAULT_TOSS_SECS,
 	.ci_scan_secs = DEFAULT_SCAN_SECS,
 	.ci_log_debug = DEFAULT_LOG_DEBUG,
-	.ci_protocol = DEFAULT_PROTOCOL
+	.ci_protocol = DEFAULT_PROTOCOL,
+	.ci_timewarn_cs = DEFAULT_TIMEWARN_CS
 };
 
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index 967cc3d..a3170fe 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -27,6 +27,7 @@
 	int ci_scan_secs;
 	int ci_log_debug;
 	int ci_protocol;
+	int ci_timewarn_cs;
 };
 
 extern struct dlm_config_info dlm_config;
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 61ba670..12c3bfd 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -17,6 +17,7 @@
 #include <linux/debugfs.h>
 
 #include "dlm_internal.h"
+#include "lock.h"
 
 #define DLM_DEBUG_BUF_LEN 4096
 static char debug_buf[DLM_DEBUG_BUF_LEN];
@@ -26,6 +27,8 @@
 
 struct rsb_iter {
 	int entry;
+	int locks;
+	int header;
 	struct dlm_ls *ls;
 	struct list_head *next;
 	struct dlm_rsb *rsb;
@@ -57,8 +60,8 @@
 	}
 }
 
-static void print_lock(struct seq_file *s, struct dlm_lkb *lkb,
-		       struct dlm_rsb *res)
+static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
+				struct dlm_rsb *res)
 {
 	seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
 
@@ -85,6 +88,8 @@
 	struct dlm_lkb *lkb;
 	int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
 
+	lock_rsb(res);
+
 	seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
 	for (i = 0; i < res->res_length; i++) {
 		if (isprint(res->res_name[i]))
@@ -129,15 +134,15 @@
 	/* Print the locks attached to this resource */
 	seq_printf(s, "Granted Queue\n");
 	list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
-		print_lock(s, lkb, res);
+		print_resource_lock(s, lkb, res);
 
 	seq_printf(s, "Conversion Queue\n");
 	list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
-		print_lock(s, lkb, res);
+		print_resource_lock(s, lkb, res);
 
 	seq_printf(s, "Waiting Queue\n");
 	list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
-		print_lock(s, lkb, res);
+		print_resource_lock(s, lkb, res);
 
 	if (list_empty(&res->res_lookup))
 		goto out;
@@ -151,6 +156,61 @@
 		seq_printf(s, "\n");
 	}
  out:
+	unlock_rsb(res);
+	return 0;
+}
+
+static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r)
+{
+	struct dlm_user_args *ua;
+	unsigned int waiting = 0;
+	uint64_t xid = 0;
+
+	if (lkb->lkb_flags & DLM_IFL_USER) {
+		ua = (struct dlm_user_args *) lkb->lkb_astparam;
+		if (ua)
+			xid = ua->xid;
+	}
+
+	if (lkb->lkb_timestamp)
+		waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp);
+
+	/* id nodeid remid pid xid exflags flags sts grmode rqmode time_ms
+	   r_nodeid r_len r_name */
+
+	seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %u %u %d \"%s\"\n",
+		   lkb->lkb_id,
+		   lkb->lkb_nodeid,
+		   lkb->lkb_remid,
+		   lkb->lkb_ownpid,
+		   (unsigned long long)xid,
+		   lkb->lkb_exflags,
+		   lkb->lkb_flags,
+		   lkb->lkb_status,
+		   lkb->lkb_grmode,
+		   lkb->lkb_rqmode,
+		   waiting,
+		   r->res_nodeid,
+		   r->res_length,
+		   r->res_name);
+}
+
+static int print_locks(struct dlm_rsb *r, struct seq_file *s)
+{
+	struct dlm_lkb *lkb;
+
+	lock_rsb(r);
+
+	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
+		print_lock(s, lkb, r);
+
+	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
+		print_lock(s, lkb, r);
+
+	list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
+		print_lock(s, lkb, r);
+
+	unlock_rsb(r);
 	return 0;
 }
 
@@ -166,6 +226,9 @@
 			read_lock(&ls->ls_rsbtbl[i].lock);
 			if (!list_empty(&ls->ls_rsbtbl[i].list)) {
 				ri->next = ls->ls_rsbtbl[i].list.next;
+				ri->rsb = list_entry(ri->next, struct dlm_rsb,
+							res_hashchain);
+				dlm_hold_rsb(ri->rsb);
 				read_unlock(&ls->ls_rsbtbl[i].lock);
 				break;
 			}
@@ -176,6 +239,7 @@
 		if (ri->entry >= ls->ls_rsbtbl_size)
 			return 1;
 	} else {
+		struct dlm_rsb *old = ri->rsb;
 		i = ri->entry;
 		read_lock(&ls->ls_rsbtbl[i].lock);
 		ri->next = ri->next->next;
@@ -184,11 +248,14 @@
 			ri->next = NULL;
 			ri->entry++;
 			read_unlock(&ls->ls_rsbtbl[i].lock);
+			dlm_put_rsb(old);
 			goto top;
                 }
+		ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
+		dlm_hold_rsb(ri->rsb);
 		read_unlock(&ls->ls_rsbtbl[i].lock);
+		dlm_put_rsb(old);
 	}
-	ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
 
 	return 0;
 }
@@ -202,7 +269,7 @@
 {
 	struct rsb_iter *ri;
 
-	ri = kmalloc(sizeof *ri, GFP_KERNEL);
+	ri = kzalloc(sizeof *ri, GFP_KERNEL);
 	if (!ri)
 		return NULL;
 
@@ -260,7 +327,17 @@
 {
 	struct rsb_iter *ri = iter_ptr;
 
-	print_resource(ri->rsb, file);
+	if (ri->locks) {
+		if (ri->header) {
+			seq_printf(file, "id nodeid remid pid xid exflags flags "
+					 "sts grmode rqmode time_ms r_nodeid "
+					 "r_len r_name\n");
+			ri->header = 0;
+		}
+		print_locks(ri->rsb, file);
+	} else {
+		print_resource(ri->rsb, file);
+	}
 
 	return 0;
 }
@@ -296,6 +373,83 @@
 };
 
 /*
+ * Dump state in compact per-lock listing
+ */
+
+static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
+{
+	struct rsb_iter *ri;
+
+	ri = kzalloc(sizeof *ri, GFP_KERNEL);
+	if (!ri)
+		return NULL;
+
+	ri->ls = ls;
+	ri->entry = 0;
+	ri->next = NULL;
+	ri->locks = 1;
+
+	if (*pos == 0)
+		ri->header = 1;
+
+	if (rsb_iter_next(ri)) {
+		rsb_iter_free(ri);
+		return NULL;
+	}
+
+	return ri;
+}
+
+static void *locks_seq_start(struct seq_file *file, loff_t *pos)
+{
+	struct rsb_iter *ri;
+	loff_t n = *pos;
+
+	ri = locks_iter_init(file->private, pos);
+	if (!ri)
+		return NULL;
+
+	while (n--) {
+		if (rsb_iter_next(ri)) {
+			rsb_iter_free(ri);
+			return NULL;
+		}
+	}
+
+	return ri;
+}
+
+static struct seq_operations locks_seq_ops = {
+	.start = locks_seq_start,
+	.next  = rsb_seq_next,
+	.stop  = rsb_seq_stop,
+	.show  = rsb_seq_show,
+};
+
+static int locks_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int ret;
+
+	ret = seq_open(file, &locks_seq_ops);
+	if (ret)
+		return ret;
+
+	seq = file->private_data;
+	seq->private = inode->i_private;
+
+	return 0;
+}
+
+static const struct file_operations locks_fops = {
+	.owner   = THIS_MODULE,
+	.open    = locks_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+
+/*
  * dump lkb's on the ls_waiters list
  */
 
@@ -362,6 +516,20 @@
 		return -ENOMEM;
 	}
 
+	memset(name, 0, sizeof(name));
+	snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
+
+	ls->ls_debug_locks_dentry = debugfs_create_file(name,
+							S_IFREG | S_IRUGO,
+							dlm_root,
+							ls,
+							&locks_fops);
+	if (!ls->ls_debug_locks_dentry) {
+		debugfs_remove(ls->ls_debug_waiters_dentry);
+		debugfs_remove(ls->ls_debug_rsb_dentry);
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
@@ -371,6 +539,8 @@
 		debugfs_remove(ls->ls_debug_rsb_dentry);
 	if (ls->ls_debug_waiters_dentry)
 		debugfs_remove(ls->ls_debug_waiters_dentry);
+	if (ls->ls_debug_locks_dentry)
+		debugfs_remove(ls->ls_debug_locks_dentry);
 }
 
 int dlm_register_debugfs(void)
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 30994d6..74901e9 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -151,6 +151,7 @@
 	void			*bastaddr;
 	int			mode;
 	struct dlm_lksb		*lksb;
+	unsigned long		timeout;
 };
 
 
@@ -213,6 +214,9 @@
 #define DLM_IFL_OVERLAP_UNLOCK  0x00080000
 #define DLM_IFL_OVERLAP_CANCEL  0x00100000
 #define DLM_IFL_ENDOFLIFE	0x00200000
+#define DLM_IFL_WATCH_TIMEWARN	0x00400000
+#define DLM_IFL_TIMEOUT_CANCEL	0x00800000
+#define DLM_IFL_DEADLOCK_CANCEL	0x01000000
 #define DLM_IFL_USER		0x00000001
 #define DLM_IFL_ORPHAN		0x00000002
 
@@ -243,6 +247,9 @@
 	struct list_head	lkb_wait_reply;	/* waiting for remote reply */
 	struct list_head	lkb_astqueue;	/* need ast to be sent */
 	struct list_head	lkb_ownqueue;	/* list of locks for a process */
+	struct list_head	lkb_time_list;
+	unsigned long		lkb_timestamp;
+	unsigned long		lkb_timeout_cs;
 
 	char			*lkb_lvbptr;
 	struct dlm_lksb		*lkb_lksb;      /* caller's status block */
@@ -447,12 +454,16 @@
 	struct mutex		ls_orphans_mutex;
 	struct list_head	ls_orphans;
 
+	struct mutex		ls_timeout_mutex;
+	struct list_head	ls_timeout;
+
 	struct list_head	ls_nodes;	/* current nodes in ls */
 	struct list_head	ls_nodes_gone;	/* dead node list, recovery */
 	int			ls_num_nodes;	/* number of nodes in ls */
 	int			ls_low_nodeid;
 	int			ls_total_weight;
 	int			*ls_node_array;
+	gfp_t			ls_allocation;
 
 	struct dlm_rsb		ls_stub_rsb;	/* for returning errors */
 	struct dlm_lkb		ls_stub_lkb;	/* for returning errors */
@@ -460,9 +471,12 @@
 
 	struct dentry		*ls_debug_rsb_dentry; /* debugfs */
 	struct dentry		*ls_debug_waiters_dentry; /* debugfs */
+	struct dentry		*ls_debug_locks_dentry; /* debugfs */
 
 	wait_queue_head_t	ls_uevent_wait;	/* user part of join/leave */
 	int			ls_uevent_result;
+	struct completion	ls_members_done;
+	int			ls_members_result;
 
 	struct miscdevice       ls_device;
 
@@ -472,6 +486,7 @@
 	struct task_struct	*ls_recoverd_task;
 	struct mutex		ls_recoverd_active;
 	spinlock_t		ls_recover_lock;
+	unsigned long		ls_recover_begin; /* jiffies timestamp */
 	uint32_t		ls_recover_status; /* DLM_RS_ */
 	uint64_t		ls_recover_seq;
 	struct dlm_recover	*ls_recover_args;
@@ -501,6 +516,7 @@
 #define LSFL_RCOM_READY		3
 #define LSFL_RCOM_WAIT		4
 #define LSFL_UEVENT_WAIT	5
+#define LSFL_TIMEWARN		6
 
 /* much of this is just saving user space pointers associated with the
    lock that we pass back to the user lib with an ast */
@@ -518,6 +534,7 @@
 	void __user		*castaddr;
 	void __user		*bastparam;
 	void __user		*bastaddr;
+	uint64_t		xid;
 };
 
 #define DLM_PROC_FLAGS_CLOSING 1
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index d8d6e72..b455919 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -82,10 +82,13 @@
 static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb);
 static int send_remove(struct dlm_rsb *r);
 static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
+static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
 static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
 				    struct dlm_message *ms);
 static int receive_extralen(struct dlm_message *ms);
 static void do_purge(struct dlm_ls *ls, int nodeid, int pid);
+static void del_timeout(struct dlm_lkb *lkb);
+void dlm_timeout_warn(struct dlm_lkb *lkb);
 
 /*
  * Lock compatibilty matrix - thanks Steve
@@ -194,17 +197,17 @@
 
 /* Threads cannot use the lockspace while it's being recovered */
 
-static inline void lock_recovery(struct dlm_ls *ls)
+static inline void dlm_lock_recovery(struct dlm_ls *ls)
 {
 	down_read(&ls->ls_in_recovery);
 }
 
-static inline void unlock_recovery(struct dlm_ls *ls)
+void dlm_unlock_recovery(struct dlm_ls *ls)
 {
 	up_read(&ls->ls_in_recovery);
 }
 
-static inline int lock_recovery_try(struct dlm_ls *ls)
+int dlm_lock_recovery_try(struct dlm_ls *ls)
 {
 	return down_read_trylock(&ls->ls_in_recovery);
 }
@@ -286,8 +289,22 @@
 	if (is_master_copy(lkb))
 		return;
 
+	del_timeout(lkb);
+
 	DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb););
 
+	/* if the operation was a cancel, then return -DLM_ECANCEL, if a
+	   timeout caused the cancel then return -ETIMEDOUT */
+	if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_TIMEOUT_CANCEL)) {
+		lkb->lkb_flags &= ~DLM_IFL_TIMEOUT_CANCEL;
+		rv = -ETIMEDOUT;
+	}
+
+	if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_DEADLOCK_CANCEL)) {
+		lkb->lkb_flags &= ~DLM_IFL_DEADLOCK_CANCEL;
+		rv = -EDEADLK;
+	}
+
 	lkb->lkb_lksb->sb_status = rv;
 	lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
 
@@ -581,6 +598,7 @@
 	kref_init(&lkb->lkb_ref);
 	INIT_LIST_HEAD(&lkb->lkb_ownqueue);
 	INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
+	INIT_LIST_HEAD(&lkb->lkb_time_list);
 
 	get_random_bytes(&bucket, sizeof(bucket));
 	bucket &= (ls->ls_lkbtbl_size - 1);
@@ -985,15 +1003,136 @@
 {
 	int i;
 
-	if (dlm_locking_stopped(ls))
-		return;
-
 	for (i = 0; i < ls->ls_rsbtbl_size; i++) {
 		shrink_bucket(ls, i);
+		if (dlm_locking_stopped(ls))
+			break;
 		cond_resched();
 	}
 }
 
+static void add_timeout(struct dlm_lkb *lkb)
+{
+	struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+
+	if (is_master_copy(lkb)) {
+		lkb->lkb_timestamp = jiffies;
+		return;
+	}
+
+	if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) &&
+	    !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
+		lkb->lkb_flags |= DLM_IFL_WATCH_TIMEWARN;
+		goto add_it;
+	}
+	if (lkb->lkb_exflags & DLM_LKF_TIMEOUT)
+		goto add_it;
+	return;
+
+ add_it:
+	DLM_ASSERT(list_empty(&lkb->lkb_time_list), dlm_print_lkb(lkb););
+	mutex_lock(&ls->ls_timeout_mutex);
+	hold_lkb(lkb);
+	lkb->lkb_timestamp = jiffies;
+	list_add_tail(&lkb->lkb_time_list, &ls->ls_timeout);
+	mutex_unlock(&ls->ls_timeout_mutex);
+}
+
+static void del_timeout(struct dlm_lkb *lkb)
+{
+	struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+
+	mutex_lock(&ls->ls_timeout_mutex);
+	if (!list_empty(&lkb->lkb_time_list)) {
+		list_del_init(&lkb->lkb_time_list);
+		unhold_lkb(lkb);
+	}
+	mutex_unlock(&ls->ls_timeout_mutex);
+}
+
+/* FIXME: is it safe to look at lkb_exflags, lkb_flags, lkb_timestamp, and
+   lkb_lksb_timeout without lock_rsb?  Note: we can't lock timeout_mutex
+   and then lock rsb because of lock ordering in add_timeout.  We may need
+   to specify some special timeout-related bits in the lkb that are just to
+   be accessed under the timeout_mutex. */
+
+void dlm_scan_timeout(struct dlm_ls *ls)
+{
+	struct dlm_rsb *r;
+	struct dlm_lkb *lkb;
+	int do_cancel, do_warn;
+
+	for (;;) {
+		if (dlm_locking_stopped(ls))
+			break;
+
+		do_cancel = 0;
+		do_warn = 0;
+		mutex_lock(&ls->ls_timeout_mutex);
+		list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) {
+
+			if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) &&
+			    time_after_eq(jiffies, lkb->lkb_timestamp +
+					  lkb->lkb_timeout_cs * HZ/100))
+				do_cancel = 1;
+
+			if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
+			    time_after_eq(jiffies, lkb->lkb_timestamp +
+				   	   dlm_config.ci_timewarn_cs * HZ/100))
+				do_warn = 1;
+
+			if (!do_cancel && !do_warn)
+				continue;
+			hold_lkb(lkb);
+			break;
+		}
+		mutex_unlock(&ls->ls_timeout_mutex);
+
+		if (!do_cancel && !do_warn)
+			break;
+
+		r = lkb->lkb_resource;
+		hold_rsb(r);
+		lock_rsb(r);
+
+		if (do_warn) {
+			/* clear flag so we only warn once */
+			lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
+			if (!(lkb->lkb_exflags & DLM_LKF_TIMEOUT))
+				del_timeout(lkb);
+			dlm_timeout_warn(lkb);
+		}
+
+		if (do_cancel) {
+			log_debug(ls, "timeout cancel %x node %d %s",
+				  lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+			lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
+			lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
+			del_timeout(lkb);
+			_cancel_lock(r, lkb);
+		}
+
+		unlock_rsb(r);
+		unhold_rsb(r);
+		dlm_put_lkb(lkb);
+	}
+}
+
+/* This is only called by dlm_recoverd, and we rely on dlm_ls_stop() stopping
+   dlm_recoverd before checking/setting ls_recover_begin. */
+
+void dlm_adjust_timeouts(struct dlm_ls *ls)
+{
+	struct dlm_lkb *lkb;
+	long adj = jiffies - ls->ls_recover_begin;
+
+	ls->ls_recover_begin = 0;
+	mutex_lock(&ls->ls_timeout_mutex);
+	list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list)
+		lkb->lkb_timestamp += adj;
+	mutex_unlock(&ls->ls_timeout_mutex);
+}
+
 /* lkb is master or local copy */
 
 static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -1275,10 +1414,8 @@
  * queue for one resource.  The granted mode of each lock blocks the requested
  * mode of the other lock."
  *
- * Part 2: if the granted mode of lkb is preventing the first lkb in the
- * convert queue from being granted, then demote lkb (set grmode to NL).
- * This second form requires that we check for conv-deadlk even when
- * now == 0 in _can_be_granted().
+ * Part 2: if the granted mode of lkb is preventing an earlier lkb in the
+ * convert queue from being granted, then deadlk/demote lkb.
  *
  * Example:
  * Granted Queue: empty
@@ -1287,41 +1424,52 @@
  *
  * The first lock can't be granted because of the granted mode of the second
  * lock and the second lock can't be granted because it's not first in the
- * list.  We demote the granted mode of the second lock (the lkb passed to this
- * function).
+ * list.  We either cancel lkb's conversion (PR->EX) and return EDEADLK, or we
+ * demote the granted mode of lkb (from PR to NL) if it has the CONVDEADLK
+ * flag set and return DEMOTED in the lksb flags.
  *
- * After the resolution, the "grant pending" function needs to go back and try
- * to grant locks on the convert queue again since the first lock can now be
- * granted.
+ * Originally, this function detected conv-deadlk in a more limited scope:
+ * - if !modes_compat(lkb1, lkb2) && !modes_compat(lkb2, lkb1), or
+ * - if lkb1 was the first entry in the queue (not just earlier), and was
+ *   blocked by the granted mode of lkb2, and there was nothing on the
+ *   granted queue preventing lkb1 from being granted immediately, i.e.
+ *   lkb2 was the only thing preventing lkb1 from being granted.
+ *
+ * That second condition meant we'd only say there was conv-deadlk if
+ * resolving it (by demotion) would lead to the first lock on the convert
+ * queue being granted right away.  It allowed conversion deadlocks to exist
+ * between locks on the convert queue while they couldn't be granted anyway.
+ *
+ * Now, we detect and take action on conversion deadlocks immediately when
+ * they're created, even if they may not be immediately consequential.  If
+ * lkb1 exists anywhere in the convert queue and lkb2 comes in with a granted
+ * mode that would prevent lkb1's conversion from being granted, we do a
+ * deadlk/demote on lkb2 right away and don't let it onto the convert queue.
+ * I think this means that the lkb_is_ahead condition below should always
+ * be zero, i.e. there will never be conv-deadlk between two locks that are
+ * both already on the convert queue.
  */
 
-static int conversion_deadlock_detect(struct dlm_rsb *rsb, struct dlm_lkb *lkb)
+static int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2)
 {
-	struct dlm_lkb *this, *first = NULL, *self = NULL;
+	struct dlm_lkb *lkb1;
+	int lkb_is_ahead = 0;
 
-	list_for_each_entry(this, &rsb->res_convertqueue, lkb_statequeue) {
-		if (!first)
-			first = this;
-		if (this == lkb) {
-			self = lkb;
+	list_for_each_entry(lkb1, &r->res_convertqueue, lkb_statequeue) {
+		if (lkb1 == lkb2) {
+			lkb_is_ahead = 1;
 			continue;
 		}
 
-		if (!modes_compat(this, lkb) && !modes_compat(lkb, this))
-			return 1;
+		if (!lkb_is_ahead) {
+			if (!modes_compat(lkb2, lkb1))
+				return 1;
+		} else {
+			if (!modes_compat(lkb2, lkb1) &&
+			    !modes_compat(lkb1, lkb2))
+				return 1;
+		}
 	}
-
-	/* if lkb is on the convert queue and is preventing the first
-	   from being granted, then there's deadlock and we demote lkb.
-	   multiple converting locks may need to do this before the first
-	   converting lock can be granted. */
-
-	if (self && self != first) {
-		if (!modes_compat(lkb, first) &&
-		    !queue_conflict(&rsb->res_grantqueue, first))
-			return 1;
-	}
-
 	return 0;
 }
 
@@ -1450,42 +1598,57 @@
 	if (!now && !conv && list_empty(&r->res_convertqueue) &&
 	    first_in_list(lkb, &r->res_waitqueue))
 		return 1;
-
  out:
-	/*
-	 * The following, enabled by CONVDEADLK, departs from VMS.
-	 */
-
-	if (conv && (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) &&
-	    conversion_deadlock_detect(r, lkb)) {
-		lkb->lkb_grmode = DLM_LOCK_NL;
-		lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
-	}
-
 	return 0;
 }
 
-/*
- * The ALTPR and ALTCW flags aren't traditional lock manager flags, but are a
- * simple way to provide a big optimization to applications that can use them.
- */
-
-static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
+static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
+			  int *err)
 {
-	uint32_t flags = lkb->lkb_exflags;
 	int rv;
 	int8_t alt = 0, rqmode = lkb->lkb_rqmode;
+	int8_t is_convert = (lkb->lkb_grmode != DLM_LOCK_IV);
+
+	if (err)
+		*err = 0;
 
 	rv = _can_be_granted(r, lkb, now);
 	if (rv)
 		goto out;
 
-	if (lkb->lkb_sbflags & DLM_SBF_DEMOTED)
-		goto out;
+	/*
+	 * The CONVDEADLK flag is non-standard and tells the dlm to resolve
+	 * conversion deadlocks by demoting grmode to NL, otherwise the dlm
+	 * cancels one of the locks.
+	 */
 
-	if (rqmode != DLM_LOCK_PR && flags & DLM_LKF_ALTPR)
+	if (is_convert && can_be_queued(lkb) &&
+	    conversion_deadlock_detect(r, lkb)) {
+		if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) {
+			lkb->lkb_grmode = DLM_LOCK_NL;
+			lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
+		} else if (!(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
+			if (err)
+				*err = -EDEADLK;
+			else {
+				log_print("can_be_granted deadlock %x now %d",
+					  lkb->lkb_id, now);
+				dlm_dump_rsb(r);
+			}
+		}
+		goto out;
+	}
+
+	/*
+	 * The ALTPR and ALTCW flags are non-standard and tell the dlm to try
+	 * to grant a request in a mode other than the normal rqmode.  It's a
+	 * simple way to provide a big optimization to applications that can
+	 * use them.
+	 */
+
+	if (rqmode != DLM_LOCK_PR && (lkb->lkb_exflags & DLM_LKF_ALTPR))
 		alt = DLM_LOCK_PR;
-	else if (rqmode != DLM_LOCK_CW && flags & DLM_LKF_ALTCW)
+	else if (rqmode != DLM_LOCK_CW && (lkb->lkb_exflags & DLM_LKF_ALTCW))
 		alt = DLM_LOCK_CW;
 
 	if (alt) {
@@ -1500,10 +1663,20 @@
 	return rv;
 }
 
+/* FIXME: I don't think that can_be_granted() can/will demote or find deadlock
+   for locks pending on the convert list.  Once verified (watch for these
+   log_prints), we should be able to just call _can_be_granted() and not
+   bother with the demote/deadlk cases here (and there's no easy way to deal
+   with a deadlk here, we'd have to generate something like grant_lock with
+   the deadlk error.) */
+
+/* returns the highest requested mode of all blocked conversions */
+
 static int grant_pending_convert(struct dlm_rsb *r, int high)
 {
 	struct dlm_lkb *lkb, *s;
 	int hi, demoted, quit, grant_restart, demote_restart;
+	int deadlk;
 
 	quit = 0;
  restart:
@@ -1513,14 +1686,29 @@
 
 	list_for_each_entry_safe(lkb, s, &r->res_convertqueue, lkb_statequeue) {
 		demoted = is_demoted(lkb);
-		if (can_be_granted(r, lkb, 0)) {
+		deadlk = 0;
+
+		if (can_be_granted(r, lkb, 0, &deadlk)) {
 			grant_lock_pending(r, lkb);
 			grant_restart = 1;
-		} else {
-			hi = max_t(int, lkb->lkb_rqmode, hi);
-			if (!demoted && is_demoted(lkb))
-				demote_restart = 1;
+			continue;
 		}
+
+		if (!demoted && is_demoted(lkb)) {
+			log_print("WARN: pending demoted %x node %d %s",
+				  lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+			demote_restart = 1;
+			continue;
+		}
+
+		if (deadlk) {
+			log_print("WARN: pending deadlock %x node %d %s",
+				  lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+			dlm_dump_rsb(r);
+			continue;
+		}
+
+		hi = max_t(int, lkb->lkb_rqmode, hi);
 	}
 
 	if (grant_restart)
@@ -1538,7 +1726,7 @@
 	struct dlm_lkb *lkb, *s;
 
 	list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
-		if (can_be_granted(r, lkb, 0))
+		if (can_be_granted(r, lkb, 0, NULL))
 			grant_lock_pending(r, lkb);
                 else
 			high = max_t(int, lkb->lkb_rqmode, high);
@@ -1733,7 +1921,7 @@
 }
 
 static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
-			 int namelen, uint32_t parent_lkid, void *ast,
+			 int namelen, unsigned long timeout_cs, void *ast,
 			 void *astarg, void *bast, struct dlm_args *args)
 {
 	int rv = -EINVAL;
@@ -1776,10 +1964,6 @@
 	if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr)
 		goto out;
 
-	/* parent/child locks not yet supported */
-	if (parent_lkid)
-		goto out;
-
 	if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid)
 		goto out;
 
@@ -1791,6 +1975,7 @@
 	args->astaddr = ast;
 	args->astparam = (long) astarg;
 	args->bastaddr = bast;
+	args->timeout = timeout_cs;
 	args->mode = mode;
 	args->lksb = lksb;
 	rv = 0;
@@ -1845,6 +2030,7 @@
 	lkb->lkb_lksb = args->lksb;
 	lkb->lkb_lvbptr = args->lksb->sb_lvbptr;
 	lkb->lkb_ownpid = (int) current->pid;
+	lkb->lkb_timeout_cs = args->timeout;
 	rv = 0;
  out:
 	return rv;
@@ -1903,6 +2089,9 @@
 		if (is_overlap(lkb))
 			goto out;
 
+		/* don't let scand try to do a cancel */
+		del_timeout(lkb);
+
 		if (lkb->lkb_flags & DLM_IFL_RESEND) {
 			lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
 			rv = -EBUSY;
@@ -1934,6 +2123,9 @@
 		if (is_overlap_unlock(lkb))
 			goto out;
 
+		/* don't let scand try to do a cancel */
+		del_timeout(lkb);
+
 		if (lkb->lkb_flags & DLM_IFL_RESEND) {
 			lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
 			rv = -EBUSY;
@@ -1984,7 +2176,7 @@
 {
 	int error = 0;
 
-	if (can_be_granted(r, lkb, 1)) {
+	if (can_be_granted(r, lkb, 1, NULL)) {
 		grant_lock(r, lkb);
 		queue_cast(r, lkb, 0);
 		goto out;
@@ -1994,6 +2186,7 @@
 		error = -EINPROGRESS;
 		add_lkb(r, lkb, DLM_LKSTS_WAITING);
 		send_blocking_asts(r, lkb);
+		add_timeout(lkb);
 		goto out;
 	}
 
@@ -2009,16 +2202,32 @@
 static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
 	int error = 0;
+	int deadlk = 0;
 
 	/* changing an existing lock may allow others to be granted */
 
-	if (can_be_granted(r, lkb, 1)) {
+	if (can_be_granted(r, lkb, 1, &deadlk)) {
 		grant_lock(r, lkb);
 		queue_cast(r, lkb, 0);
 		grant_pending_locks(r);
 		goto out;
 	}
 
+	/* can_be_granted() detected that this lock would block in a conversion
+	   deadlock, so we leave it on the granted queue and return EDEADLK in
+	   the ast for the convert. */
+
+	if (deadlk) {
+		/* it's left on the granted queue */
+		log_debug(r->res_ls, "deadlock %x node %d sts%d g%d r%d %s",
+			  lkb->lkb_id, lkb->lkb_nodeid, lkb->lkb_status,
+			  lkb->lkb_grmode, lkb->lkb_rqmode, r->res_name);
+		revert_lock(r, lkb);
+		queue_cast(r, lkb, -EDEADLK);
+		error = -EDEADLK;
+		goto out;
+	}
+
 	/* is_demoted() means the can_be_granted() above set the grmode
 	   to NL, and left us on the granted queue.  This auto-demotion
 	   (due to CONVDEADLK) might mean other locks, and/or this lock, are
@@ -2041,6 +2250,7 @@
 		del_lkb(r, lkb);
 		add_lkb(r, lkb, DLM_LKSTS_CONVERT);
 		send_blocking_asts(r, lkb);
+		add_timeout(lkb);
 		goto out;
 	}
 
@@ -2274,7 +2484,7 @@
 	if (!ls)
 		return -EINVAL;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	if (convert)
 		error = find_lkb(ls, lksb->sb_lkid, &lkb);
@@ -2284,7 +2494,7 @@
 	if (error)
 		goto out;
 
-	error = set_lock_args(mode, lksb, flags, namelen, parent_lkid, ast,
+	error = set_lock_args(mode, lksb, flags, namelen, 0, ast,
 			      astarg, bast, &args);
 	if (error)
 		goto out_put;
@@ -2299,10 +2509,10 @@
  out_put:
 	if (convert || error)
 		__put_lkb(ls, lkb);
-	if (error == -EAGAIN)
+	if (error == -EAGAIN || error == -EDEADLK)
 		error = 0;
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	dlm_put_lockspace(ls);
 	return error;
 }
@@ -2322,7 +2532,7 @@
 	if (!ls)
 		return -EINVAL;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = find_lkb(ls, lkid, &lkb);
 	if (error)
@@ -2344,7 +2554,7 @@
  out_put:
 	dlm_put_lkb(lkb);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	dlm_put_lockspace(ls);
 	return error;
 }
@@ -2384,7 +2594,7 @@
 	   pass into lowcomms_commit and a message buffer (mb) that we
 	   write our data into */
 
-	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb);
+	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
 	if (!mh)
 		return -ENOBUFS;
 
@@ -3111,9 +3321,10 @@
 		lkb->lkb_remid = ms->m_lkid;
 		if (is_altmode(lkb))
 			munge_altmode(lkb, ms);
-		if (result)
+		if (result) {
 			add_lkb(r, lkb, DLM_LKSTS_WAITING);
-		else {
+			add_timeout(lkb);
+		} else {
 			grant_lock_pc(r, lkb, ms);
 			queue_cast(r, lkb, 0);
 		}
@@ -3172,6 +3383,12 @@
 		queue_cast(r, lkb, -EAGAIN);
 		break;
 
+	case -EDEADLK:
+		receive_flags_reply(lkb, ms);
+		revert_lock_pc(r, lkb);
+		queue_cast(r, lkb, -EDEADLK);
+		break;
+
 	case -EINPROGRESS:
 		/* convert was queued on remote master */
 		receive_flags_reply(lkb, ms);
@@ -3179,6 +3396,7 @@
 			munge_demoted(lkb, ms);
 		del_lkb(r, lkb);
 		add_lkb(r, lkb, DLM_LKSTS_CONVERT);
+		add_timeout(lkb);
 		break;
 
 	case 0:
@@ -3298,8 +3516,7 @@
 	case -DLM_ECANCEL:
 		receive_flags_reply(lkb, ms);
 		revert_lock_pc(r, lkb);
-		if (ms->m_result)
-			queue_cast(r, lkb, -DLM_ECANCEL);
+		queue_cast(r, lkb, -DLM_ECANCEL);
 		break;
 	case 0:
 		break;
@@ -3424,7 +3641,7 @@
 			}
 		}
 
-		if (lock_recovery_try(ls))
+		if (dlm_lock_recovery_try(ls))
 			break;
 		schedule();
 	}
@@ -3503,7 +3720,7 @@
 		log_error(ls, "unknown message type %d", ms->m_type);
 	}
 
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
  out:
 	dlm_put_lockspace(ls);
 	dlm_astd_wake();
@@ -4034,13 +4251,13 @@
 
 int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
 		     int mode, uint32_t flags, void *name, unsigned int namelen,
-		     uint32_t parent_lkid)
+		     unsigned long timeout_cs)
 {
 	struct dlm_lkb *lkb;
 	struct dlm_args args;
 	int error;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = create_lkb(ls, &lkb);
 	if (error) {
@@ -4062,7 +4279,7 @@
 	   When DLM_IFL_USER is set, the dlm knows that this is a userspace
 	   lock and that lkb_astparam is the dlm_user_args structure. */
 
-	error = set_lock_args(mode, &ua->lksb, flags, namelen, parent_lkid,
+	error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
 			      DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
 	lkb->lkb_flags |= DLM_IFL_USER;
 	ua->old_mode = DLM_LOCK_IV;
@@ -4094,19 +4311,20 @@
 	list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks);
 	spin_unlock(&ua->proc->locks_spin);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	return error;
 }
 
 int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
-		     int mode, uint32_t flags, uint32_t lkid, char *lvb_in)
+		     int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+		     unsigned long timeout_cs)
 {
 	struct dlm_lkb *lkb;
 	struct dlm_args args;
 	struct dlm_user_args *ua;
 	int error;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = find_lkb(ls, lkid, &lkb);
 	if (error)
@@ -4127,6 +4345,7 @@
 	if (lvb_in && ua->lksb.sb_lvbptr)
 		memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
 
+	ua->xid = ua_tmp->xid;
 	ua->castparam = ua_tmp->castparam;
 	ua->castaddr = ua_tmp->castaddr;
 	ua->bastparam = ua_tmp->bastparam;
@@ -4134,19 +4353,19 @@
 	ua->user_lksb = ua_tmp->user_lksb;
 	ua->old_mode = lkb->lkb_grmode;
 
-	error = set_lock_args(mode, &ua->lksb, flags, 0, 0, DLM_FAKE_USER_AST,
-			      ua, DLM_FAKE_USER_AST, &args);
+	error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs,
+			      DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
 	if (error)
 		goto out_put;
 
 	error = convert_lock(ls, lkb, &args);
 
-	if (error == -EINPROGRESS || error == -EAGAIN)
+	if (error == -EINPROGRESS || error == -EAGAIN || error == -EDEADLK)
 		error = 0;
  out_put:
 	dlm_put_lkb(lkb);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	kfree(ua_tmp);
 	return error;
 }
@@ -4159,7 +4378,7 @@
 	struct dlm_user_args *ua;
 	int error;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = find_lkb(ls, lkid, &lkb);
 	if (error)
@@ -4194,7 +4413,7 @@
  out_put:
 	dlm_put_lkb(lkb);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	kfree(ua_tmp);
 	return error;
 }
@@ -4207,7 +4426,7 @@
 	struct dlm_user_args *ua;
 	int error;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = find_lkb(ls, lkid, &lkb);
 	if (error)
@@ -4231,11 +4450,59 @@
  out_put:
 	dlm_put_lkb(lkb);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	kfree(ua_tmp);
 	return error;
 }
 
+int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid)
+{
+	struct dlm_lkb *lkb;
+	struct dlm_args args;
+	struct dlm_user_args *ua;
+	struct dlm_rsb *r;
+	int error;
+
+	dlm_lock_recovery(ls);
+
+	error = find_lkb(ls, lkid, &lkb);
+	if (error)
+		goto out;
+
+	ua = (struct dlm_user_args *)lkb->lkb_astparam;
+
+	error = set_unlock_args(flags, ua, &args);
+	if (error)
+		goto out_put;
+
+	/* same as cancel_lock(), but set DEADLOCK_CANCEL after lock_rsb */
+
+	r = lkb->lkb_resource;
+	hold_rsb(r);
+	lock_rsb(r);
+
+	error = validate_unlock_args(lkb, &args);
+	if (error)
+		goto out_r;
+	lkb->lkb_flags |= DLM_IFL_DEADLOCK_CANCEL;
+
+	error = _cancel_lock(r, lkb);
+ out_r:
+	unlock_rsb(r);
+	put_rsb(r);
+
+	if (error == -DLM_ECANCEL)
+		error = 0;
+	/* from validate_unlock_args() */
+	if (error == -EBUSY)
+		error = 0;
+ out_put:
+	dlm_put_lkb(lkb);
+ out:
+	dlm_unlock_recovery(ls);
+	return error;
+}
+
 /* lkb's that are removed from the waiters list by revert are just left on the
    orphans list with the granted orphan locks, to be freed by purge */
 
@@ -4314,12 +4581,13 @@
 {
 	struct dlm_lkb *lkb, *safe;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	while (1) {
 		lkb = del_proc_lock(ls, proc);
 		if (!lkb)
 			break;
+		del_timeout(lkb);
 		if (lkb->lkb_exflags & DLM_LKF_PERSISTENT)
 			orphan_proc_lock(ls, lkb);
 		else
@@ -4347,7 +4615,7 @@
 	}
 
 	mutex_unlock(&ls->ls_clear_proc_locks);
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 }
 
 static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
@@ -4429,12 +4697,12 @@
 	if (nodeid != dlm_our_nodeid()) {
 		error = send_purge(ls, nodeid, pid);
 	} else {
-		lock_recovery(ls);
+		dlm_lock_recovery(ls);
 		if (pid == current->pid)
 			purge_proc_locks(ls, proc);
 		else
 			do_purge(ls, nodeid, pid);
-		unlock_recovery(ls);
+		dlm_unlock_recovery(ls);
 	}
 	return error;
 }
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
index 64fc4ec..1720313 100644
--- a/fs/dlm/lock.h
+++ b/fs/dlm/lock.h
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -24,6 +24,10 @@
 void dlm_hold_rsb(struct dlm_rsb *r);
 int dlm_put_lkb(struct dlm_lkb *lkb);
 void dlm_scan_rsbs(struct dlm_ls *ls);
+int dlm_lock_recovery_try(struct dlm_ls *ls);
+void dlm_unlock_recovery(struct dlm_ls *ls);
+void dlm_scan_timeout(struct dlm_ls *ls);
+void dlm_adjust_timeouts(struct dlm_ls *ls);
 
 int dlm_purge_locks(struct dlm_ls *ls);
 void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
@@ -34,15 +38,18 @@
 int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
 
 int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode,
-	uint32_t flags, void *name, unsigned int namelen, uint32_t parent_lkid);
+	uint32_t flags, void *name, unsigned int namelen,
+	unsigned long timeout_cs);
 int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
-	int mode, uint32_t flags, uint32_t lkid, char *lvb_in);
+	int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+	unsigned long timeout_cs);
 int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
 	uint32_t flags, uint32_t lkid, char *lvb_in);
 int dlm_user_cancel(struct dlm_ls *ls,  struct dlm_user_args *ua_tmp,
 	uint32_t flags, uint32_t lkid);
 int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
 	int nodeid, int pid);
+int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid);
 void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc);
 
 static inline int is_master(struct dlm_rsb *r)
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a677b2a..1dc7210 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -197,13 +197,24 @@
 	else
 		kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
 
+	log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
+
+	/* dlm_controld will see the uevent, do the necessary group management
+	   and then write to sysfs to wake us */
+
 	error = wait_event_interruptible(ls->ls_uevent_wait,
 			test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
+
+	log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
+
 	if (error)
 		goto out;
 
 	error = ls->ls_uevent_result;
  out:
+	if (error)
+		log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
+			  error, ls->ls_uevent_result);
 	return error;
 }
 
@@ -234,8 +245,13 @@
 	struct dlm_ls *ls;
 
 	while (!kthread_should_stop()) {
-		list_for_each_entry(ls, &lslist, ls_list)
-			dlm_scan_rsbs(ls);
+		list_for_each_entry(ls, &lslist, ls_list) {
+			if (dlm_lock_recovery_try(ls)) {
+				dlm_scan_rsbs(ls);
+				dlm_scan_timeout(ls);
+				dlm_unlock_recovery(ls);
+			}
+		}
 		schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
 	}
 	return 0;
@@ -395,6 +411,7 @@
 {
 	struct dlm_ls *ls;
 	int i, size, error = -ENOMEM;
+	int do_unreg = 0;
 
 	if (namelen > DLM_LOCKSPACE_LEN)
 		return -EINVAL;
@@ -417,11 +434,22 @@
 		goto out;
 	memcpy(ls->ls_name, name, namelen);
 	ls->ls_namelen = namelen;
-	ls->ls_exflags = flags;
 	ls->ls_lvblen = lvblen;
 	ls->ls_count = 0;
 	ls->ls_flags = 0;
 
+	if (flags & DLM_LSFL_TIMEWARN)
+		set_bit(LSFL_TIMEWARN, &ls->ls_flags);
+
+	if (flags & DLM_LSFL_FS)
+		ls->ls_allocation = GFP_NOFS;
+	else
+		ls->ls_allocation = GFP_KERNEL;
+
+	/* ls_exflags are forced to match among nodes, and we don't
+	   need to require all nodes to have TIMEWARN or FS set */
+	ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
+
 	size = dlm_config.ci_rsbtbl_size;
 	ls->ls_rsbtbl_size = size;
 
@@ -461,6 +489,8 @@
 	mutex_init(&ls->ls_waiters_mutex);
 	INIT_LIST_HEAD(&ls->ls_orphans);
 	mutex_init(&ls->ls_orphans_mutex);
+	INIT_LIST_HEAD(&ls->ls_timeout);
+	mutex_init(&ls->ls_timeout_mutex);
 
 	INIT_LIST_HEAD(&ls->ls_nodes);
 	INIT_LIST_HEAD(&ls->ls_nodes_gone);
@@ -477,6 +507,8 @@
 
 	init_waitqueue_head(&ls->ls_uevent_wait);
 	ls->ls_uevent_result = 0;
+	init_completion(&ls->ls_members_done);
+	ls->ls_members_result = -1;
 
 	ls->ls_recoverd_task = NULL;
 	mutex_init(&ls->ls_recoverd_active);
@@ -513,32 +545,49 @@
 	error = dlm_recoverd_start(ls);
 	if (error) {
 		log_error(ls, "can't start dlm_recoverd %d", error);
-		goto out_rcomfree;
+		goto out_delist;
 	}
 
-	dlm_create_debug_file(ls);
-
 	error = kobject_setup(ls);
 	if (error)
-		goto out_del;
+		goto out_stop;
 
 	error = kobject_register(&ls->ls_kobj);
 	if (error)
-		goto out_del;
+		goto out_stop;
+
+	/* let kobject handle freeing of ls if there's an error */
+	do_unreg = 1;
+
+	/* This uevent triggers dlm_controld in userspace to add us to the
+	   group of nodes that are members of this lockspace (managed by the
+	   cluster infrastructure.)  Once it's done that, it tells us who the
+	   current lockspace members are (via configfs) and then tells the
+	   lockspace to start running (via sysfs) in dlm_ls_start(). */
 
 	error = do_uevent(ls, 1);
 	if (error)
-		goto out_unreg;
+		goto out_stop;
+
+	wait_for_completion(&ls->ls_members_done);
+	error = ls->ls_members_result;
+	if (error)
+		goto out_members;
+
+	dlm_create_debug_file(ls);
+
+	log_debug(ls, "join complete");
 
 	*lockspace = ls;
 	return 0;
 
- out_unreg:
-	kobject_unregister(&ls->ls_kobj);
- out_del:
-	dlm_delete_debug_file(ls);
+ out_members:
+	do_uevent(ls, 0);
+	dlm_clear_members(ls);
+	kfree(ls->ls_node_array);
+ out_stop:
 	dlm_recoverd_stop(ls);
- out_rcomfree:
+ out_delist:
 	spin_lock(&lslist_lock);
 	list_del(&ls->ls_list);
 	spin_unlock(&lslist_lock);
@@ -550,7 +599,10 @@
  out_rsbfree:
 	kfree(ls->ls_rsbtbl);
  out_lsfree:
-	kfree(ls);
+	if (do_unreg)
+		kobject_unregister(&ls->ls_kobj);
+	else
+		kfree(ls);
  out:
 	module_put(THIS_MODULE);
 	return error;
@@ -570,6 +622,8 @@
 	error = new_lockspace(name, namelen, lockspace, flags, lvblen);
 	if (!error)
 		ls_count++;
+	else if (!ls_count)
+		threads_stop();
  out:
 	mutex_unlock(&ls_lock);
 	return error;
@@ -696,7 +750,7 @@
 	dlm_clear_members_gone(ls);
 	kfree(ls->ls_node_array);
 	kobject_unregister(&ls->ls_kobj);
-        /* The ls structure will be freed when the kobject is done with */
+	/* The ls structure will be freed when the kobject is done with */
 
 	mutex_lock(&ls_lock);
 	ls_count--;
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 27970a5..0553a61 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -260,7 +260,7 @@
 static void lowcomms_data_ready(struct sock *sk, int count_unused)
 {
 	struct connection *con = sock2con(sk);
-	if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
+	if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags))
 		queue_work(recv_workqueue, &con->rwork);
 }
 
@@ -268,7 +268,7 @@
 {
 	struct connection *con = sock2con(sk);
 
-	if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+	if (con && !test_and_set_bit(CF_WRITE_PENDING, &con->flags))
 		queue_work(send_workqueue, &con->swork);
 }
 
@@ -720,11 +720,17 @@
 			INIT_WORK(&othercon->rwork, process_recv_sockets);
 			set_bit(CF_IS_OTHERCON, &othercon->flags);
 			newcon->othercon = othercon;
+			othercon->sock = newsock;
+			newsock->sk->sk_user_data = othercon;
+			add_sock(newsock, othercon);
+			addcon = othercon;
 		}
-		othercon->sock = newsock;
-		newsock->sk->sk_user_data = othercon;
-		add_sock(newsock, othercon);
-		addcon = othercon;
+		else {
+			printk("Extra connection from node %d attempted\n", nodeid);
+			result = -EAGAIN;
+			mutex_unlock(&newcon->sock_mutex);
+			goto accept_err;
+		}
 	}
 	else {
 		newsock->sk->sk_user_data = newcon;
@@ -1400,8 +1406,11 @@
 	down(&connections_lock);
 	for (i = 0; i <= max_nodeid; i++) {
 		con = __nodeid2con(i, 0);
-		if (con)
+		if (con) {
 			con->flags |= 0xFF;
+			if (con->sock)
+				con->sock->sk->sk_user_data = NULL;
+		}
 	}
 	up(&connections_lock);
 
diff --git a/fs/dlm/main.c b/fs/dlm/main.c
index 162fbae..eca2907 100644
--- a/fs/dlm/main.c
+++ b/fs/dlm/main.c
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -25,6 +25,8 @@
 static inline int dlm_register_debugfs(void) { return 0; }
 static inline void dlm_unregister_debugfs(void) { }
 #endif
+int dlm_netlink_init(void);
+void dlm_netlink_exit(void);
 
 static int __init init_dlm(void)
 {
@@ -50,10 +52,16 @@
 	if (error)
 		goto out_debug;
 
+	error = dlm_netlink_init();
+	if (error)
+		goto out_user;
+
 	printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
 
 	return 0;
 
+ out_user:
+	dlm_user_exit();
  out_debug:
 	dlm_unregister_debugfs();
  out_config:
@@ -68,6 +76,7 @@
 
 static void __exit exit_dlm(void)
 {
+	dlm_netlink_exit();
 	dlm_user_exit();
 	dlm_config_exit();
 	dlm_memory_exit();
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 85e2897..073599d 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -233,6 +233,12 @@
 	*neg_out = neg;
 
 	error = ping_members(ls);
+	if (!error || error == -EPROTO) {
+		/* new_lockspace() may be waiting to know if the config
+		   is good or bad */
+		ls->ls_members_result = error;
+		complete(&ls->ls_members_done);
+	}
 	if (error)
 		goto out;
 
@@ -284,6 +290,9 @@
 	dlm_recoverd_suspend(ls);
 	ls->ls_recover_status = 0;
 	dlm_recoverd_resume(ls);
+
+	if (!ls->ls_recover_begin)
+		ls->ls_recover_begin = jiffies;
 	return 0;
 }
 
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
new file mode 100644
index 0000000..863b87d
--- /dev/null
+++ b/fs/dlm/netlink.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc.  All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#include <net/genetlink.h>
+#include <linux/dlm.h>
+#include <linux/dlm_netlink.h>
+
+#include "dlm_internal.h"
+
+static uint32_t dlm_nl_seqnum;
+static uint32_t listener_nlpid;
+
+static struct genl_family family = {
+	.id		= GENL_ID_GENERATE,
+	.name		= DLM_GENL_NAME,
+	.version	= DLM_GENL_VERSION,
+};
+
+static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
+{
+	struct sk_buff *skb;
+	void *data;
+
+	skb = genlmsg_new(size, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	/* add the message headers */
+	data = genlmsg_put(skb, 0, dlm_nl_seqnum++, &family, 0, cmd);
+	if (!data) {
+		nlmsg_free(skb);
+		return -EINVAL;
+	}
+
+	*skbp = skb;
+	return 0;
+}
+
+static struct dlm_lock_data *mk_data(struct sk_buff *skb)
+{
+	struct nlattr *ret;
+
+	ret = nla_reserve(skb, DLM_TYPE_LOCK, sizeof(struct dlm_lock_data));
+	if (!ret)
+		return NULL;
+	return nla_data(ret);
+}
+
+static int send_data(struct sk_buff *skb)
+{
+	struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
+	void *data = genlmsg_data(genlhdr);
+	int rv;
+
+	rv = genlmsg_end(skb, data);
+	if (rv < 0) {
+		nlmsg_free(skb);
+		return rv;
+	}
+
+	return genlmsg_unicast(skb, listener_nlpid);
+}
+
+static int user_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+	listener_nlpid = info->snd_pid;
+	printk("user_cmd nlpid %u\n", listener_nlpid);
+	return 0;
+}
+
+static struct genl_ops dlm_nl_ops = {
+	.cmd		= DLM_CMD_HELLO,
+	.doit		= user_cmd,
+};
+
+int dlm_netlink_init(void)
+{
+	int rv;
+
+	rv = genl_register_family(&family);
+	if (rv)
+		return rv;
+
+	rv = genl_register_ops(&family, &dlm_nl_ops);
+	if (rv < 0)
+		goto err;
+	return 0;
+ err:
+	genl_unregister_family(&family);
+	return rv;
+}
+
+void dlm_netlink_exit(void)
+{
+	genl_unregister_ops(&family, &dlm_nl_ops);
+	genl_unregister_family(&family);
+}
+
+static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
+{
+	struct dlm_rsb *r = lkb->lkb_resource;
+	struct dlm_user_args *ua = (struct dlm_user_args *) lkb->lkb_astparam;
+
+	memset(data, 0, sizeof(struct dlm_lock_data));
+
+	data->version = DLM_LOCK_DATA_VERSION;
+	data->nodeid = lkb->lkb_nodeid;
+	data->ownpid = lkb->lkb_ownpid;
+	data->id = lkb->lkb_id;
+	data->remid = lkb->lkb_remid;
+	data->status = lkb->lkb_status;
+	data->grmode = lkb->lkb_grmode;
+	data->rqmode = lkb->lkb_rqmode;
+	data->timestamp = lkb->lkb_timestamp;
+	if (ua)
+		data->xid = ua->xid;
+	if (r) {
+		data->lockspace_id = r->res_ls->ls_global_id;
+		data->resource_namelen = r->res_length;
+		memcpy(data->resource_name, r->res_name, r->res_length);
+	}
+}
+
+void dlm_timeout_warn(struct dlm_lkb *lkb)
+{
+	struct dlm_lock_data *data;
+	struct sk_buff *send_skb;
+	size_t size;
+	int rv;
+
+	size = nla_total_size(sizeof(struct dlm_lock_data)) +
+	       nla_total_size(0); /* why this? */
+
+	rv = prepare_data(DLM_CMD_TIMEOUT, &send_skb, size);
+	if (rv < 0)
+		return;
+
+	data = mk_data(send_skb);
+	if (!data) {
+		nlmsg_free(send_skb);
+		return;
+	}
+
+	fill_data(data, lkb);
+
+	send_data(send_skb);
+}
+
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 6bfbd61..e3a1527 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -38,7 +38,7 @@
 	char *mb;
 	int mb_len = sizeof(struct dlm_rcom) + len;
 
-	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb);
+	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
 	if (!mh) {
 		log_print("create_rcom to %d type %d len %d ENOBUFS",
 			  to_nodeid, type, len);
@@ -90,7 +90,7 @@
 		log_error(ls, "version mismatch: %x nodeid %d: %x",
 			  DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid,
 			  rc->rc_header.h_version);
-		return -EINVAL;
+		return -EPROTO;
 	}
 
 	if (rf->rf_lvblen != ls->ls_lvblen ||
@@ -98,7 +98,7 @@
 		log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
 			  ls->ls_lvblen, ls->ls_exflags,
 			  nodeid, rf->rf_lvblen, rf->rf_lsflags);
-		return -EINVAL;
+		return -EPROTO;
 	}
 	return 0;
 }
@@ -386,7 +386,8 @@
 	dlm_recover_process_copy(ls, rc_in);
 }
 
-static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
+static int send_ls_not_ready(struct dlm_ls *ls, int nodeid,
+			     struct dlm_rcom *rc_in)
 {
 	struct dlm_rcom *rc;
 	struct rcom_config *rf;
@@ -394,7 +395,7 @@
 	char *mb;
 	int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
 
-	mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb);
+	mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb);
 	if (!mh)
 		return -ENOBUFS;
 	memset(mb, 0, mb_len);
@@ -464,7 +465,7 @@
 		log_print("lockspace %x from %d type %x not found",
 			  hd->h_lockspace, nodeid, rc->rc_type);
 		if (rc->rc_type == DLM_RCOM_STATUS)
-			send_ls_not_ready(nodeid, rc);
+			send_ls_not_ready(ls, nodeid, rc);
 		return;
 	}
 
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 3cb636d..6657599 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -190,6 +190,8 @@
 
 	dlm_clear_members_gone(ls);
 
+	dlm_adjust_timeouts(ls);
+
 	error = enable_locking(ls, rv->seq);
 	if (error) {
 		log_debug(ls, "enable_locking failed %d", error);
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index b0201ec..6438941 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -33,16 +33,17 @@
 struct dlm_lock_params32 {
 	__u8 mode;
 	__u8 namelen;
-	__u16 flags;
+	__u16 unused;
+	__u32 flags;
 	__u32 lkid;
 	__u32 parent;
-
+	__u64 xid;
+	__u64 timeout;
 	__u32 castparam;
 	__u32 castaddr;
 	__u32 bastparam;
 	__u32 bastaddr;
 	__u32 lksb;
-
 	char lvb[DLM_USER_LVB_LEN];
 	char name[0];
 };
@@ -68,6 +69,7 @@
 };
 
 struct dlm_lock_result32 {
+	__u32 version[3];
 	__u32 length;
 	__u32 user_astaddr;
 	__u32 user_astparam;
@@ -102,6 +104,8 @@
 		kb->i.lock.flags = kb32->i.lock.flags;
 		kb->i.lock.lkid = kb32->i.lock.lkid;
 		kb->i.lock.parent = kb32->i.lock.parent;
+		kb->i.lock.xid = kb32->i.lock.xid;
+		kb->i.lock.timeout = kb32->i.lock.timeout;
 		kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
 		kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
 		kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
@@ -115,6 +119,10 @@
 static void compat_output(struct dlm_lock_result *res,
 			  struct dlm_lock_result32 *res32)
 {
+	res32->version[0] = res->version[0];
+	res32->version[1] = res->version[1];
+	res32->version[2] = res->version[2];
+
 	res32->user_astaddr = (__u32)(long)res->user_astaddr;
 	res32->user_astparam = (__u32)(long)res->user_astparam;
 	res32->user_lksb = (__u32)(long)res->user_lksb;
@@ -130,6 +138,36 @@
 }
 #endif
 
+/* Figure out if this lock is at the end of its life and no longer
+   available for the application to use.  The lkb still exists until
+   the final ast is read.  A lock becomes EOL in three situations:
+     1. a noqueue request fails with EAGAIN
+     2. an unlock completes with EUNLOCK
+     3. a cancel of a waiting request completes with ECANCEL/EDEADLK
+   An EOL lock needs to be removed from the process's list of locks.
+   And we can't allow any new operation on an EOL lock.  This is
+   not related to the lifetime of the lkb struct which is managed
+   entirely by refcount. */
+
+static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
+{
+	switch (sb_status) {
+	case -DLM_EUNLOCK:
+		return 1;
+	case -DLM_ECANCEL:
+	case -ETIMEDOUT:
+	case -EDEADLK:
+		if (lkb->lkb_grmode == DLM_LOCK_IV)
+			return 1;
+		break;
+	case -EAGAIN:
+		if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV)
+			return 1;
+		break;
+	}
+	return 0;
+}
+
 /* we could possibly check if the cancel of an orphan has resulted in the lkb
    being removed and then remove that lkb from the orphans list and free it */
 
@@ -176,25 +214,7 @@
 		log_debug(ls, "ast overlap %x status %x %x",
 			  lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
 
-	/* Figure out if this lock is at the end of its life and no longer
-	   available for the application to use.  The lkb still exists until
-	   the final ast is read.  A lock becomes EOL in three situations:
-	     1. a noqueue request fails with EAGAIN
-	     2. an unlock completes with EUNLOCK
-	     3. a cancel of a waiting request completes with ECANCEL
-	   An EOL lock needs to be removed from the process's list of locks.
-	   And we can't allow any new operation on an EOL lock.  This is
-	   not related to the lifetime of the lkb struct which is managed
-	   entirely by refcount. */
-
-	if (type == AST_COMP &&
-	    lkb->lkb_grmode == DLM_LOCK_IV &&
-	    ua->lksb.sb_status == -EAGAIN)
-		eol = 1;
-	else if (ua->lksb.sb_status == -DLM_EUNLOCK ||
-	    (ua->lksb.sb_status == -DLM_ECANCEL &&
-	     lkb->lkb_grmode == DLM_LOCK_IV))
-		eol = 1;
+	eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type);
 	if (eol) {
 		lkb->lkb_ast_type &= ~AST_BAST;
 		lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
@@ -252,16 +272,18 @@
 	ua->castaddr = params->castaddr;
 	ua->bastparam = params->bastparam;
 	ua->bastaddr = params->bastaddr;
+	ua->xid = params->xid;
 
 	if (params->flags & DLM_LKF_CONVERT)
 		error = dlm_user_convert(ls, ua,
 				         params->mode, params->flags,
-				         params->lkid, params->lvb);
+				         params->lkid, params->lvb,
+					 (unsigned long) params->timeout);
 	else {
 		error = dlm_user_request(ls, ua,
 					 params->mode, params->flags,
 					 params->name, params->namelen,
-					 params->parent);
+					 (unsigned long) params->timeout);
 		if (!error)
 			error = ua->lksb.sb_lkid;
 	}
@@ -299,6 +321,22 @@
 	return error;
 }
 
+static int device_user_deadlock(struct dlm_user_proc *proc,
+				struct dlm_lock_params *params)
+{
+	struct dlm_ls *ls;
+	int error;
+
+	ls = dlm_find_lockspace_local(proc->lockspace);
+	if (!ls)
+		return -ENOENT;
+
+	error = dlm_user_deadlock(ls, params->flags, params->lkid);
+
+	dlm_put_lockspace(ls);
+	return error;
+}
+
 static int create_misc_device(struct dlm_ls *ls, char *name)
 {
 	int error, len;
@@ -348,7 +386,7 @@
 		return -EPERM;
 
 	error = dlm_new_lockspace(params->name, strlen(params->name),
-				  &lockspace, 0, DLM_USER_LVB_LEN);
+				  &lockspace, params->flags, DLM_USER_LVB_LEN);
 	if (error)
 		return error;
 
@@ -524,6 +562,14 @@
 		error = device_user_unlock(proc, &kbuf->i.lock);
 		break;
 
+	case DLM_USER_DEADLOCK:
+		if (!proc) {
+			log_print("no locking on control device");
+			goto out_sig;
+		}
+		error = device_user_deadlock(proc, &kbuf->i.lock);
+		break;
+
 	case DLM_USER_CREATE_LOCKSPACE:
 		if (proc) {
 			log_print("create/remove only on control device");
@@ -641,6 +687,9 @@
 	int struct_len;
 
 	memset(&result, 0, sizeof(struct dlm_lock_result));
+	result.version[0] = DLM_DEVICE_VERSION_MAJOR;
+	result.version[1] = DLM_DEVICE_VERSION_MINOR;
+	result.version[2] = DLM_DEVICE_VERSION_PATCH;
 	memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
 	result.user_lksb = ua->user_lksb;
 
@@ -699,6 +748,20 @@
 	return error;
 }
 
+static int copy_version_to_user(char __user *buf, size_t count)
+{
+	struct dlm_device_version ver;
+
+	memset(&ver, 0, sizeof(struct dlm_device_version));
+	ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
+	ver.version[1] = DLM_DEVICE_VERSION_MINOR;
+	ver.version[2] = DLM_DEVICE_VERSION_PATCH;
+
+	if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
+		return -EFAULT;
+	return sizeof(struct dlm_device_version);
+}
+
 /* a read returns a single ast described in a struct dlm_lock_result */
 
 static ssize_t device_read(struct file *file, char __user *buf, size_t count,
@@ -710,6 +773,16 @@
 	DECLARE_WAITQUEUE(wait, current);
 	int error, type=0, bmode=0, removed = 0;
 
+	if (count == sizeof(struct dlm_device_version)) {
+		error = copy_version_to_user(buf, count);
+		return error;
+	}
+
+	if (!proc) {
+		log_print("non-version read from control device %zu", count);
+		return -EINVAL;
+	}
+
 #ifdef CONFIG_COMPAT
 	if (count < sizeof(struct dlm_lock_result32))
 #else
@@ -747,11 +820,6 @@
 		}
 	}
 
-	if (list_empty(&proc->asts)) {
-		spin_unlock(&proc->asts_spin);
-		return -EAGAIN;
-	}
-
 	/* there may be both completion and blocking asts to return for
 	   the lkb, don't remove lkb from asts list unless no asts remain */
 
@@ -823,6 +891,7 @@
 static const struct file_operations ctl_device_fops = {
 	.open    = ctl_device_open,
 	.release = ctl_device_close,
+	.read    = device_read,
 	.write   = device_write,
 	.owner   = THIS_MODULE,
 };
diff --git a/fs/dquot.c b/fs/dquot.c
index 8819d28..7e27315 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -538,6 +538,11 @@
 	return (dqstats.free_dquots / 100) * sysctl_vfs_cache_pressure;
 }
 
+static struct shrinker dqcache_shrinker = {
+	.shrink = shrink_dqcache_memory,
+	.seeks = DEFAULT_SEEKS,
+};
+
 /*
  * Put reference to dquot
  * NOTE: If you change this function please check whether dqput_blocks() works right...
@@ -1870,7 +1875,7 @@
 	printk("Dquot-cache hash table entries: %ld (order %ld, %ld bytes)\n",
 			nr_hash, order, (PAGE_SIZE << order));
 
-	set_shrinker(DEFAULT_SEEKS, shrink_dqcache_memory);
+	register_shrinker(&dqcache_shrinker);
 
 	return 0;
 }
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 03ea769..59375ef 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -20,7 +20,7 @@
 	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
 		if (inode->i_state & (I_FREEING|I_WILL_FREE))
 			continue;
-		invalidate_mapping_pages(inode->i_mapping, 0, -1);
+		__invalidate_mapping_pages(inode->i_mapping, 0, -1, true);
 	}
 	spin_unlock(&inode_lock);
 }
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 403e3ba..1b9dd9a 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -580,5 +580,7 @@
 ecryptfs_write_header_metadata(char *virt,
 			       struct ecryptfs_crypt_stat *crypt_stat,
 			       size_t *written);
+int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start,
+			 int num_zeros);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 9881b5c..94f456f 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -33,63 +33,6 @@
 #include "ecryptfs_kernel.h"
 
 /**
- * ecryptfs_llseek
- * @file: File we are seeking in
- * @offset: The offset to seek to
- * @origin: 2 - offset from i_size; 1 - offset from f_pos
- *
- * Returns the position we have seeked to, or negative on error
- */
-static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin)
-{
-	loff_t rv;
-	loff_t new_end_pos;
-	int rc;
-	int expanding_file = 0;
-	struct inode *inode = file->f_mapping->host;
-
-	/* If our offset is past the end of our file, we're going to
-	 * need to grow it so we have a valid length of 0's */
-	new_end_pos = offset;
-	switch (origin) {
-	case 2:
-		new_end_pos += i_size_read(inode);
-		expanding_file = 1;
-		break;
-	case 1:
-		new_end_pos += file->f_pos;
-		if (new_end_pos > i_size_read(inode)) {
-			ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) "
-					"> i_size_read(inode)(=[0x%.16x])\n",
-					new_end_pos, i_size_read(inode));
-			expanding_file = 1;
-		}
-		break;
-	default:
-		if (new_end_pos > i_size_read(inode)) {
-			ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) "
-					"> i_size_read(inode)(=[0x%.16x])\n",
-					new_end_pos, i_size_read(inode));
-			expanding_file = 1;
-		}
-	}
-	ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos);
-	if (expanding_file) {
-		rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos);
-		if (rc) {
-			rv = rc;
-			ecryptfs_printk(KERN_ERR, "Error on attempt to "
-					"truncate to (higher) offset [0x%.16x];"
-					" rc = [%d]\n", new_end_pos, rc);
-			goto out;
-		}
-	}
-	rv = generic_file_llseek(file, offset, origin);
-out:
-	return rv;
-}
-
-/**
  * ecryptfs_read_update_atime
  *
  * generic_file_read updates the atime of upper layer inode.  But, it
@@ -395,16 +338,17 @@
 	return rc;
 }
 
-static ssize_t ecryptfs_sendfile(struct file *file, loff_t * ppos,
-				 size_t count, read_actor_t actor, void *target)
+static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos,
+				    struct pipe_inode_info *pipe, size_t count,
+				    unsigned int flags)
 {
 	struct file *lower_file = NULL;
 	int rc = -EINVAL;
 
 	lower_file = ecryptfs_file_to_lower(file);
-	if (lower_file->f_op && lower_file->f_op->sendfile)
-		rc = lower_file->f_op->sendfile(lower_file, ppos, count,
-						actor, target);
+	if (lower_file->f_op && lower_file->f_op->splice_read)
+		rc = lower_file->f_op->splice_read(lower_file, ppos, pipe,
+						count, flags);
 
 	return rc;
 }
@@ -421,11 +365,11 @@
 	.release = ecryptfs_release,
 	.fsync = ecryptfs_fsync,
 	.fasync = ecryptfs_fasync,
-	.sendfile = ecryptfs_sendfile,
+	.splice_read = ecryptfs_splice_read,
 };
 
 const struct file_operations ecryptfs_main_fops = {
-	.llseek = ecryptfs_llseek,
+	.llseek = generic_file_llseek,
 	.read = do_sync_read,
 	.aio_read = ecryptfs_read_update_atime,
 	.write = do_sync_write,
@@ -438,7 +382,7 @@
 	.release = ecryptfs_release,
 	.fsync = ecryptfs_fsync,
 	.fasync = ecryptfs_fasync,
-	.sendfile = ecryptfs_sendfile,
+	.splice_read = ecryptfs_splice_read,
 };
 
 static int
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 1548be2..e77a2ec 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -282,7 +282,7 @@
 	struct dentry *lower_dentry;
 	struct vfsmount *lower_mnt;
 	char *encoded_name;
-	unsigned int encoded_namelen;
+	int encoded_namelen;
 	struct ecryptfs_crypt_stat *crypt_stat = NULL;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
 	char *page_virt = NULL;
@@ -473,7 +473,7 @@
 	struct dentry *lower_dir_dentry;
 	umode_t mode;
 	char *encoded_symname;
-	unsigned int encoded_symlen;
+	int encoded_symlen;
 	struct ecryptfs_crypt_stat *crypt_stat = NULL;
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
@@ -800,6 +800,25 @@
 			goto out_fput;
 		}
 	} else { /* new_length < i_size_read(inode) */
+		pgoff_t index = 0;
+		int end_pos_in_page = -1;
+
+		if (new_length != 0) {
+			index = ((new_length - 1) >> PAGE_CACHE_SHIFT);
+			end_pos_in_page = ((new_length - 1) & ~PAGE_CACHE_MASK);
+		}
+		if (end_pos_in_page != (PAGE_CACHE_SIZE - 1)) {
+			if ((rc = ecryptfs_write_zeros(&fake_ecryptfs_file,
+						       index,
+						       (end_pos_in_page + 1),
+						       ((PAGE_CACHE_SIZE - 1)
+							- end_pos_in_page)))) {
+				printk(KERN_ERR "Error attempting to zero out "
+				       "the remainder of the end page on "
+				       "reducing truncate; rc = [%d]\n", rc);
+				goto out_fput;
+			}
+		}
 		vmtruncate(inode, new_length);
 		rc = ecryptfs_write_inode_size_to_metadata(
 			lower_file, lower_dentry->d_inode, inode, dentry,
@@ -875,9 +894,54 @@
 	struct ecryptfs_crypt_stat *crypt_stat;
 
 	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
-	lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
+		ecryptfs_init_crypt_stat(crypt_stat);
 	inode = dentry->d_inode;
 	lower_inode = ecryptfs_inode_to_lower(inode);
+	lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	mutex_lock(&crypt_stat->cs_mutex);
+	if (S_ISDIR(dentry->d_inode->i_mode))
+		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+	else if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
+		 || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
+		struct vfsmount *lower_mnt;
+		struct file *lower_file = NULL;
+		struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
+		int lower_flags;
+
+		lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+		lower_flags = O_RDONLY;
+		if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry,
+						   lower_mnt, lower_flags))) {
+			printk(KERN_ERR
+			       "Error opening lower file; rc = [%d]\n", rc);
+			mutex_unlock(&crypt_stat->cs_mutex);
+			goto out;
+		}
+		mount_crypt_stat = &ecryptfs_superblock_to_private(
+			dentry->d_sb)->mount_crypt_stat;
+		if ((rc = ecryptfs_read_metadata(dentry, lower_file))) {
+			if (!(mount_crypt_stat->flags
+			      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
+				rc = -EIO;
+				printk(KERN_WARNING "Attempt to read file that "
+				       "is not in a valid eCryptfs format, "
+				       "and plaintext passthrough mode is not "
+				       "enabled; returning -EIO\n");
+
+				mutex_unlock(&crypt_stat->cs_mutex);
+				fput(lower_file);
+				goto out;
+			}
+			rc = 0;
+			crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+			mutex_unlock(&crypt_stat->cs_mutex);
+			fput(lower_file);
+			goto out;
+		}
+		fput(lower_file);
+	}
+	mutex_unlock(&crypt_stat->cs_mutex);
 	if (ia->ia_valid & ATTR_SIZE) {
 		ecryptfs_printk(KERN_DEBUG,
 				"ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n",
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 606128f..02ca6f1 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -840,8 +840,6 @@
 		goto out;
 	}
 	kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
-	sysfs_attr_version.attr.owner = THIS_MODULE;
-	sysfs_attr_version_str.attr.owner = THIS_MODULE;
 	rc = do_sysfs_registration();
 	if (rc) {
 		printk(KERN_ERR "sysfs registration failed\n");
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index 3baf253..a9d87c4 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -19,7 +19,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  * 02111-1307, USA.
  */
-
+#include <linux/sched.h>
 #include "ecryptfs_kernel.h"
 
 static LIST_HEAD(ecryptfs_msg_ctx_free_list);
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 88ea669..7d5a43c 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -56,9 +56,6 @@
 	return read_mapping_page(mapping, index, (void *)file);
 }
 
-static
-int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros);
-
 /**
  * ecryptfs_fill_zeros
  * @file: The ecryptfs file
@@ -101,10 +98,13 @@
 	if (old_end_page_index == new_end_page_index) {
 		/* Start and end are in the same page; we just need to
 		 * set a portion of the existing page to zero's */
-		rc = write_zeros(file, index, (old_end_pos_in_page + 1),
-				 (new_end_pos_in_page - old_end_pos_in_page));
+		rc = ecryptfs_write_zeros(file, index,
+					  (old_end_pos_in_page + 1),
+					  (new_end_pos_in_page
+					   - old_end_pos_in_page));
 		if (rc)
-			ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], "
+			ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros("
+					"file=[%p], "
 					"index=[0x%.16x], "
 					"old_end_pos_in_page=[d], "
 					"(PAGE_CACHE_SIZE - new_end_pos_in_page"
@@ -117,10 +117,10 @@
 		goto out;
 	}
 	/* Fill the remainder of the previous last page with zeros */
-	rc = write_zeros(file, index, (old_end_pos_in_page + 1),
+	rc = ecryptfs_write_zeros(file, index, (old_end_pos_in_page + 1),
 			 ((PAGE_CACHE_SIZE - 1) - old_end_pos_in_page));
 	if (rc) {
-		ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], "
+		ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(file=[%p], "
 				"index=[0x%.16x], old_end_pos_in_page=[d], "
 				"(PAGE_CACHE_SIZE - old_end_pos_in_page)=[d]) "
 				"returned [%d]\n", file, index,
@@ -131,9 +131,10 @@
 	index++;
 	while (index < new_end_page_index) {
 		/* Fill all intermediate pages with zeros */
-		rc = write_zeros(file, index, 0, PAGE_CACHE_SIZE);
+		rc = ecryptfs_write_zeros(file, index, 0, PAGE_CACHE_SIZE);
 		if (rc) {
-			ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], "
+			ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros("
+					"file=[%p], "
 					"index=[0x%.16x], "
 					"old_end_pos_in_page=[d], "
 					"(PAGE_CACHE_SIZE - new_end_pos_in_page"
@@ -149,9 +150,9 @@
 	}
 	/* Fill the portion at the beginning of the last new page with
 	 * zero's */
-	rc = write_zeros(file, index, 0, (new_end_pos_in_page + 1));
+	rc = ecryptfs_write_zeros(file, index, 0, (new_end_pos_in_page + 1));
 	if (rc) {
-		ecryptfs_printk(KERN_ERR, "write_zeros(file="
+		ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(file="
 				"[%p], index=[0x%.16x], 0, "
 				"new_end_pos_in_page=[%d]"
 				"returned [%d]\n", file, index,
@@ -376,6 +377,27 @@
 	return 0;
 }
 
+/**
+ * eCryptfs does not currently support holes. When writing after a
+ * seek past the end of the file, eCryptfs fills in 0's through to the
+ * current location. The code to fill in the 0's to all the
+ * intermediate pages calls ecryptfs_prepare_write_no_truncate().
+ */
+static int
+ecryptfs_prepare_write_no_truncate(struct file *file, struct page *page,
+				   unsigned from, unsigned to)
+{
+	int rc = 0;
+
+	if (from == 0 && to == PAGE_CACHE_SIZE)
+		goto out;	/* If we are writing a full page, it will be
+				   up to date. */
+	if (!PageUptodate(page))
+		rc = ecryptfs_do_readpage(file, page, page->index);
+out:
+	return rc;
+}
+
 static int ecryptfs_prepare_write(struct file *file, struct page *page,
 				  unsigned from, unsigned to)
 {
@@ -386,6 +408,23 @@
 				   up to date. */
 	if (!PageUptodate(page))
 		rc = ecryptfs_do_readpage(file, page, page->index);
+	if (page->index != 0) {
+		loff_t end_of_prev_pg_pos =
+			(((loff_t)page->index << PAGE_CACHE_SHIFT) - 1);
+
+		if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) {
+			rc = ecryptfs_truncate(file->f_path.dentry,
+					       end_of_prev_pg_pos);
+			if (rc) {
+				printk(KERN_ERR "Error on attempt to "
+				       "truncate to (higher) offset [%lld];"
+				       " rc = [%d]\n", end_of_prev_pg_pos, rc);
+				goto out;
+			}
+		}
+		if (end_of_prev_pg_pos + 1 > i_size_read(page->mapping->host))
+			zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
+	}
 out:
 	return rc;
 }
@@ -721,7 +760,7 @@
 }
 
 /**
- * write_zeros
+ * ecryptfs_write_zeros
  * @file: The ecryptfs file
  * @index: The index in which we are writing
  * @start: The position after the last block of data
@@ -731,8 +770,8 @@
  *
  * (start + num_zeros) must be less than or equal to PAGE_CACHE_SIZE
  */
-static
-int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
+int
+ecryptfs_write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
 {
 	int rc = 0;
 	struct page *tmp_page;
@@ -744,10 +783,10 @@
 		rc = PTR_ERR(tmp_page);
 		goto out;
 	}
-	rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros);
-	if (rc) {
+	if ((rc = ecryptfs_prepare_write_no_truncate(file, tmp_page, start,
+						     (start + num_zeros)))) {
 		ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
-				"to remainder of page at index [0x%.16x]\n",
+				"to page at index [0x%.16x]\n",
 				index);
 		page_cache_release(tmp_page);
 		goto out;
diff --git a/fs/efs/namei.c b/fs/efs/namei.c
index ed4a207..5276b19 100644
--- a/fs/efs/namei.c
+++ b/fs/efs/namei.c
@@ -75,6 +75,38 @@
 	return NULL;
 }
 
+struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+	    	result = ERR_PTR(-ESTALE);
+		goto out_iput;
+	}
+
+	result = d_alloc_anon(inode);
+	if (!result) {
+		result = ERR_PTR(-ENOMEM);
+		goto out_iput;
+	}
+	return result;
+
+ out_iput:
+	iput(inode);
+	return result;
+}
+
 struct dentry *efs_get_parent(struct dentry *child)
 {
 	struct dentry *parent;
diff --git a/fs/efs/super.c b/fs/efs/super.c
index e0a6839..d360c81 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -11,6 +11,7 @@
 #include <linux/efs_fs.h>
 #include <linux/efs_vh.h>
 #include <linux/efs_fs_sb.h>
+#include <linux/exportfs.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
@@ -113,6 +114,7 @@
 };
 
 static struct export_operations efs_export_ops = {
+	.get_dentry	= efs_get_dentry,
 	.get_parent	= efs_get_parent,
 };
 
diff --git a/fs/exec.c b/fs/exec.c
index 0b68588..f20561f 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -134,6 +134,9 @@
 	if (error)
 		goto out;
 
+	error = -EACCES;
+	if (nd.mnt->mnt_flags & MNT_NOEXEC)
+		goto exit;
 	error = -EINVAL;
 	if (!S_ISREG(nd.dentry->d_inode->i_mode))
 		goto exit;
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index e98f6cd..8adb32a 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -1,15 +1,45 @@
 
+#include <linux/exportfs.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/module.h>
+#include <linux/mount.h>
 #include <linux/namei.h>
 
-struct export_operations export_op_default;
-
-#define	CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
-
 #define dprintk(fmt, args...) do{}while(0)
 
+
+static int get_name(struct dentry *dentry, char *name,
+		struct dentry *child);
+
+
+static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj)
+{
+	struct dentry *result = ERR_PTR(-ESTALE);
+
+	if (sb->s_export_op->get_dentry) {
+		result = sb->s_export_op->get_dentry(sb, obj);
+		if (!result)
+			result = ERR_PTR(-ESTALE);
+	}
+
+	return result;
+}
+
+static int exportfs_get_name(struct dentry *dir, char *name,
+		struct dentry *child)
+{
+	struct export_operations *nop = dir->d_sb->s_export_op;
+
+	if (nop->get_name)
+		return nop->get_name(dir, name, child);
+	else
+		return get_name(dir, name, child);
+}
+
+/*
+ * Check if the dentry or any of it's aliases is acceptable.
+ */
 static struct dentry *
 find_acceptable_alias(struct dentry *result,
 		int (*acceptable)(void *context, struct dentry *dentry),
@@ -17,6 +47,9 @@
 {
 	struct dentry *dentry, *toput = NULL;
 
+	if (acceptable(context, result))
+		return result;
+
 	spin_lock(&dcache_lock);
 	list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
 		dget_locked(dentry);
@@ -37,6 +70,150 @@
 	return NULL;
 }
 
+/*
+ * Find root of a disconnected subtree and return a reference to it.
+ */
+static struct dentry *
+find_disconnected_root(struct dentry *dentry)
+{
+	dget(dentry);
+	spin_lock(&dentry->d_lock);
+	while (!IS_ROOT(dentry) &&
+	       (dentry->d_parent->d_flags & DCACHE_DISCONNECTED)) {
+		struct dentry *parent = dentry->d_parent;
+		dget(parent);
+		spin_unlock(&dentry->d_lock);
+		dput(dentry);
+		dentry = parent;
+		spin_lock(&dentry->d_lock);
+	}
+	spin_unlock(&dentry->d_lock);
+	return dentry;
+}
+
+
+/*
+ * Make sure target_dir is fully connected to the dentry tree.
+ *
+ * It may already be, as the flag isn't always updated when connection happens.
+ */
+static int
+reconnect_path(struct super_block *sb, struct dentry *target_dir)
+{
+	char nbuf[NAME_MAX+1];
+	int noprogress = 0;
+	int err = -ESTALE;
+
+	/*
+	 * It is possible that a confused file system might not let us complete
+	 * the path to the root.  For example, if get_parent returns a directory
+	 * in which we cannot find a name for the child.  While this implies a
+	 * very sick filesystem we don't want it to cause knfsd to spin.  Hence
+	 * the noprogress counter.  If we go through the loop 10 times (2 is
+	 * probably enough) without getting anywhere, we just give up
+	 */
+	while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
+		struct dentry *pd = find_disconnected_root(target_dir);
+
+		if (!IS_ROOT(pd)) {
+			/* must have found a connected parent - great */
+			spin_lock(&pd->d_lock);
+			pd->d_flags &= ~DCACHE_DISCONNECTED;
+			spin_unlock(&pd->d_lock);
+			noprogress = 0;
+		} else if (pd == sb->s_root) {
+			printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
+			spin_lock(&pd->d_lock);
+			pd->d_flags &= ~DCACHE_DISCONNECTED;
+			spin_unlock(&pd->d_lock);
+			noprogress = 0;
+		} else {
+			/*
+			 * We have hit the top of a disconnected path, try to
+			 * find parent and connect.
+			 *
+			 * Racing with some other process renaming a directory
+			 * isn't much of a problem here.  If someone renames
+			 * the directory, it will end up properly connected,
+			 * which is what we want
+			 *
+			 * Getting the parent can't be supported generically,
+			 * the locking is too icky.
+			 *
+			 * Instead we just return EACCES.  If server reboots
+			 * or inodes get flushed, you lose
+			 */
+			struct dentry *ppd = ERR_PTR(-EACCES);
+			struct dentry *npd;
+
+			mutex_lock(&pd->d_inode->i_mutex);
+			if (sb->s_export_op->get_parent)
+				ppd = sb->s_export_op->get_parent(pd);
+			mutex_unlock(&pd->d_inode->i_mutex);
+
+			if (IS_ERR(ppd)) {
+				err = PTR_ERR(ppd);
+				dprintk("%s: get_parent of %ld failed, err %d\n",
+					__FUNCTION__, pd->d_inode->i_ino, err);
+				dput(pd);
+				break;
+			}
+
+			dprintk("%s: find name of %lu in %lu\n", __FUNCTION__,
+				pd->d_inode->i_ino, ppd->d_inode->i_ino);
+			err = exportfs_get_name(ppd, nbuf, pd);
+			if (err) {
+				dput(ppd);
+				dput(pd);
+				if (err == -ENOENT)
+					/* some race between get_parent and
+					 * get_name?  just try again
+					 */
+					continue;
+				break;
+			}
+			dprintk("%s: found name: %s\n", __FUNCTION__, nbuf);
+			mutex_lock(&ppd->d_inode->i_mutex);
+			npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
+			mutex_unlock(&ppd->d_inode->i_mutex);
+			if (IS_ERR(npd)) {
+				err = PTR_ERR(npd);
+				dprintk("%s: lookup failed: %d\n",
+					__FUNCTION__, err);
+				dput(ppd);
+				dput(pd);
+				break;
+			}
+			/* we didn't really want npd, we really wanted
+			 * a side-effect of the lookup.
+			 * hopefully, npd == pd, though it isn't really
+			 * a problem if it isn't
+			 */
+			if (npd == pd)
+				noprogress = 0;
+			else
+				printk("%s: npd != pd\n", __FUNCTION__);
+			dput(npd);
+			dput(ppd);
+			if (IS_ROOT(pd)) {
+				/* something went wrong, we have to give up */
+				dput(pd);
+				break;
+			}
+		}
+		dput(pd);
+	}
+
+	if (target_dir->d_flags & DCACHE_DISCONNECTED) {
+		/* something went wrong - oh-well */
+		if (!err)
+			err = -ESTALE;
+		return err;
+	}
+
+	return 0;
+}
+
 /**
  * find_exported_dentry - helper routine to implement export_operations->decode_fh
  * @sb:		The &super_block identifying the filesystem
@@ -74,184 +251,58 @@
 		     int (*acceptable)(void *context, struct dentry *de),
 		     void *context)
 {
-	struct dentry *result = NULL;
-	struct dentry *target_dir;
-	int err;
-	struct export_operations *nops = sb->s_export_op;
-	struct dentry *alias;
-	int noprogress;
-	char nbuf[NAME_MAX+1];
+	struct dentry *result, *alias;
+	int err = -ESTALE;
 
 	/*
 	 * Attempt to find the inode.
 	 */
-	result = CALL(sb->s_export_op,get_dentry)(sb,obj);
-	err = -ESTALE;
-	if (result == NULL)
-		goto err_out;
-	if (IS_ERR(result)) {
-		err = PTR_ERR(result);
-		goto err_out;
-	}
-	if (S_ISDIR(result->d_inode->i_mode) &&
-	    (result->d_flags & DCACHE_DISCONNECTED)) {
-		/* it is an unconnected directory, we must connect it */
-		;
-	} else {
-		if (acceptable(context, result))
-			return result;
-		if (S_ISDIR(result->d_inode->i_mode)) {
+	result = exportfs_get_dentry(sb, obj);
+	if (IS_ERR(result))
+		return result;
+
+	if (S_ISDIR(result->d_inode->i_mode)) {
+		if (!(result->d_flags & DCACHE_DISCONNECTED)) {
+			if (acceptable(context, result))
+				return result;
 			err = -EACCES;
 			goto err_result;
 		}
 
+		err = reconnect_path(sb, result);
+		if (err)
+			goto err_result;
+	} else {
+		struct dentry *target_dir, *nresult;
+		char nbuf[NAME_MAX+1];
+
 		alias = find_acceptable_alias(result, acceptable, context);
 		if (alias)
 			return alias;
-	}			
 
-	/* It's a directory, or we are required to confirm the file's
-	 * location in the tree based on the parent information
- 	 */
-	dprintk("find_exported_dentry: need to look harder for %s/%d\n",sb->s_id,*(int*)obj);
-	if (S_ISDIR(result->d_inode->i_mode))
-		target_dir = dget(result);
-	else {
 		if (parent == NULL)
 			goto err_result;
 
-		target_dir = CALL(sb->s_export_op,get_dentry)(sb,parent);
-		if (IS_ERR(target_dir))
+		target_dir = exportfs_get_dentry(sb,parent);
+		if (IS_ERR(target_dir)) {
 			err = PTR_ERR(target_dir);
-		if (target_dir == NULL || IS_ERR(target_dir))
 			goto err_result;
-	}
-	/*
-	 * Now we need to make sure that target_dir is properly connected.
-	 * It may already be, as the flag isn't always updated when connection
-	 * happens.
-	 * So, we walk up parent links until we find a connected directory,
-	 * or we run out of directories.  Then we find the parent, find
-	 * the name of the child in that parent, and do a lookup.
-	 * This should connect the child into the parent
-	 * We then repeat.
-	 */
-
-	/* it is possible that a confused file system might not let us complete 
-	 * the path to the root.  For example, if get_parent returns a directory
-	 * in which we cannot find a name for the child.  While this implies a
-	 * very sick filesystem we don't want it to cause knfsd to spin.  Hence
-	 * the noprogress counter.  If we go through the loop 10 times (2 is
-	 * probably enough) without getting anywhere, we just give up
-	 */
-	noprogress= 0;
-	while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
-		struct dentry *pd = target_dir;
-
-		dget(pd);
-		spin_lock(&pd->d_lock);
-		while (!IS_ROOT(pd) &&
-				(pd->d_parent->d_flags&DCACHE_DISCONNECTED)) {
-			struct dentry *parent = pd->d_parent;
-
-			dget(parent);
-			spin_unlock(&pd->d_lock);
-			dput(pd);
-			pd = parent;
-			spin_lock(&pd->d_lock);
 		}
-		spin_unlock(&pd->d_lock);
 
-		if (!IS_ROOT(pd)) {
-			/* must have found a connected parent - great */
-			spin_lock(&pd->d_lock);
-			pd->d_flags &= ~DCACHE_DISCONNECTED;
-			spin_unlock(&pd->d_lock);
-			noprogress = 0;
-		} else if (pd == sb->s_root) {
-			printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
-			spin_lock(&pd->d_lock);
-			pd->d_flags &= ~DCACHE_DISCONNECTED;
-			spin_unlock(&pd->d_lock);
-			noprogress = 0;
-		} else {
-			/* we have hit the top of a disconnected path.  Try
-			 * to find parent and connect
-			 * note: racing with some other process renaming a
-			 * directory isn't much of a problem here.  If someone
-			 * renames the directory, it will end up properly
-			 * connected, which is what we want
-			 */
-			struct dentry *ppd;
-			struct dentry *npd;
-
-			mutex_lock(&pd->d_inode->i_mutex);
-			ppd = CALL(nops,get_parent)(pd);
-			mutex_unlock(&pd->d_inode->i_mutex);
-
-			if (IS_ERR(ppd)) {
-				err = PTR_ERR(ppd);
-				dprintk("find_exported_dentry: get_parent of %ld failed, err %d\n",
-					pd->d_inode->i_ino, err);
-				dput(pd);
-				break;
-			}
-			dprintk("find_exported_dentry: find name of %lu in %lu\n", pd->d_inode->i_ino, ppd->d_inode->i_ino);
-			err = CALL(nops,get_name)(ppd, nbuf, pd);
-			if (err) {
-				dput(ppd);
-				dput(pd);
-				if (err == -ENOENT)
-					/* some race between get_parent and
-					 * get_name?  just try again
-					 */
-					continue;
-				break;
-			}
-			dprintk("find_exported_dentry: found name: %s\n", nbuf);
-			mutex_lock(&ppd->d_inode->i_mutex);
-			npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
-			mutex_unlock(&ppd->d_inode->i_mutex);
-			if (IS_ERR(npd)) {
-				err = PTR_ERR(npd);
-				dprintk("find_exported_dentry: lookup failed: %d\n", err);
-				dput(ppd);
-				dput(pd);
-				break;
-			}
-			/* we didn't really want npd, we really wanted
-			 * a side-effect of the lookup.
-			 * hopefully, npd == pd, though it isn't really
-			 * a problem if it isn't
-			 */
-			if (npd == pd)
-				noprogress = 0;
-			else
-				printk("find_exported_dentry: npd != pd\n");
-			dput(npd);
-			dput(ppd);
-			if (IS_ROOT(pd)) {
-				/* something went wrong, we have to give up */
-				dput(pd);
-				break;
-			}
+		err = reconnect_path(sb, target_dir);
+		if (err) {
+			dput(target_dir);
+			goto err_result;
 		}
-		dput(pd);
-	}
 
-	if (target_dir->d_flags & DCACHE_DISCONNECTED) {
-		/* something went wrong - oh-well */
-		if (!err)
-			err = -ESTALE;
-		goto err_target;
-	}
-	/* if we weren't after a directory, have one more step to go */
-	if (result != target_dir) {
-		struct dentry *nresult;
-		err = CALL(nops,get_name)(target_dir, nbuf, result);
+		/*
+		 * As we weren't after a directory, have one more step to go.
+		 */
+		err = exportfs_get_name(target_dir, nbuf, result);
 		if (!err) {
 			mutex_lock(&target_dir->d_inode->i_mutex);
-			nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
+			nresult = lookup_one_len(nbuf, target_dir,
+						 strlen(nbuf));
 			mutex_unlock(&target_dir->d_inode->i_mutex);
 			if (!IS_ERR(nresult)) {
 				if (nresult->d_inode) {
@@ -261,11 +312,8 @@
 					dput(nresult);
 			}
 		}
+		dput(target_dir);
 	}
-	dput(target_dir);
-	/* now result is properly connected, it is our best bet */
-	if (acceptable(context, result))
-		return result;
 
 	alias = find_acceptable_alias(result, acceptable, context);
 	if (alias)
@@ -275,32 +323,16 @@
 	dput(result);
 	/* It might be justifiable to return ESTALE here,
 	 * but the filehandle at-least looks reasonable good
-	 * and it just be a permission problem, so returning
+	 * and it may just be a permission problem, so returning
 	 * -EACCESS is safer
 	 */
 	return ERR_PTR(-EACCES);
 
- err_target:
-	dput(target_dir);
  err_result:
 	dput(result);
- err_out:
 	return ERR_PTR(err);
 }
 
-
-
-static struct dentry *get_parent(struct dentry *child)
-{
-	/* get_parent cannot be supported generically, the locking
-	 * is too icky.
-	 * instead, we just return EACCES.  If server reboots or inodes
-	 * get flushed, you lose
-	 */
-	return ERR_PTR(-EACCES);
-}
-
-
 struct getdents_callback {
 	char *name;		/* name that was found. It already points to a
 				   buffer NAME_MAX+1 is size */
@@ -390,61 +422,6 @@
 	return error;
 }
 
-
-static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
-{
-
-	/* iget isn't really right if the inode is currently unallocated!!
-	 * This should really all be done inside each filesystem
-	 *
-	 * ext2fs' read_inode has been strengthed to return a bad_inode if
-	 * the inode had been deleted.
-	 *
-	 * Currently we don't know the generation for parent directory, so
-	 * a generation of 0 means "accept any"
-	 */
-	struct inode *inode;
-	struct dentry *result;
-	if (ino == 0)
-		return ERR_PTR(-ESTALE);
-	inode = iget(sb, ino);
-	if (inode == NULL)
-		return ERR_PTR(-ENOMEM);
-	if (is_bad_inode(inode)
-	    || (generation && inode->i_generation != generation)
-		) {
-		/* we didn't find the right inode.. */
-		dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
-			inode->i_ino,
-			inode->i_nlink, atomic_read(&inode->i_count),
-			inode->i_generation,
-			generation);
-
-		iput(inode);
-		return ERR_PTR(-ESTALE);
-	}
-	/* now to find a dentry.
-	 * If possible, get a well-connected one
-	 */
-	result = d_alloc_anon(inode);
-	if (!result) {
-		iput(inode);
-		return ERR_PTR(-ENOMEM);
-	}
-	return result;
-}
-
-
-static struct dentry *get_object(struct super_block *sb, void *vobjp)
-{
-	__u32 *objp = vobjp;
-	unsigned long ino = objp[0];
-	__u32 generation = objp[1];
-
-	return export_iget(sb, ino, generation);
-}
-
-
 /**
  * export_encode_fh - default export_operations->encode_fh function
  * @dentry:  the dentry to encode
@@ -517,16 +494,40 @@
 				   acceptable, context);
 }
 
-struct export_operations export_op_default = {
-	.decode_fh	= export_decode_fh,
-	.encode_fh	= export_encode_fh,
+int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+		int connectable)
+{
+ 	struct export_operations *nop = dentry->d_sb->s_export_op;
+	int error;
 
-	.get_name	= get_name,
-	.get_parent	= get_parent,
-	.get_dentry	= get_object,
-};
+	if (nop->encode_fh)
+		error = nop->encode_fh(dentry, fh, max_len, connectable);
+	else
+		error = export_encode_fh(dentry, fh, max_len, connectable);
 
-EXPORT_SYMBOL(export_op_default);
+	return error;
+}
+EXPORT_SYMBOL_GPL(exportfs_encode_fh);
+
+struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len,
+		int fileid_type, int (*acceptable)(void *, struct dentry *),
+		void *context)
+{
+	struct export_operations *nop = mnt->mnt_sb->s_export_op;
+	struct dentry *result;
+
+	if (nop->decode_fh) {
+		result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
+			acceptable, context);
+	} else {
+		result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
+			acceptable, context);
+	}
+
+	return result;
+}
+EXPORT_SYMBOL_GPL(exportfs_decode_fh);
+
 EXPORT_SYMBOL(find_exported_dentry);
 
 MODULE_LICENSE("GPL");
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 7c420b8..e58669e 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -464,7 +464,7 @@
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		return -EPERM;
 
 	if (value) {
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 566d4e2..ab79612 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -24,9 +24,9 @@
 #include "acl.h"
 
 /*
- * Called when an inode is released. Note that this is different
- * from ext2_open_file: open gets called at every open, but release
- * gets called only when /all/ the files are closed.
+ * Called when filp is released. This happens when all file descriptors
+ * for a single struct file are closed. Note that different open() calls
+ * for the same file yield different struct file structures.
  */
 static int ext2_release_file (struct inode * inode, struct file * filp)
 {
@@ -53,7 +53,6 @@
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
 	.fsync		= ext2_sync_file,
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
@@ -71,7 +70,6 @@
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
 	.fsync		= ext2_sync_file,
-	.sendfile	= xip_file_sendfile,
 };
 #endif
 
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index e85c482..3bcd254 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -36,7 +36,7 @@
 		if (IS_RDONLY(inode))
 			return -EROFS;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(flags, (int __user *) arg))
@@ -74,7 +74,7 @@
 	case EXT2_IOC_GETVERSION:
 		return put_user(inode->i_generation, (int __user *) arg);
 	case EXT2_IOC_SETVERSION:
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EPERM;
 		if (IS_RDONLY(inode))
 			return -EROFS;
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 16337bf..3eefa97 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -25,6 +25,7 @@
 #include <linux/parser.h>
 #include <linux/random.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/seq_file.h>
@@ -1038,6 +1039,15 @@
 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
 		((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
 
+	ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
+				    EXT2_MOUNT_XIP if not */
+
+	if ((ext2_use_xip(sb)) && (sb->s_blocksize != PAGE_SIZE)) {
+		printk("XIP: Unsupported blocksize\n");
+		err = -EINVAL;
+		goto restore_opts;
+	}
+
 	es = sbi->s_es;
 	if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
 	    (old_mount_opt & EXT2_MOUNT_XIP)) &&
@@ -1090,15 +1100,18 @@
 	struct super_block *sb = dentry->d_sb;
 	struct ext2_sb_info *sbi = EXT2_SB(sb);
 	struct ext2_super_block *es = sbi->s_es;
-	unsigned long overhead;
-	int i;
 	u64 fsid;
 
 	if (test_opt (sb, MINIX_DF))
-		overhead = 0;
-	else {
+		sbi->s_overhead_last = 0;
+	else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+		unsigned long i, overhead = 0;
+		smp_rmb();
+
 		/*
-		 * Compute the overhead (FS structures)
+		 * Compute the overhead (FS structures). This is constant
+		 * for a given filesystem unless the number of block groups
+		 * changes so we cache the previous value until it does.
 		 */
 
 		/*
@@ -1122,17 +1135,22 @@
 		 */
 		overhead += (sbi->s_groups_count *
 			     (2 + sbi->s_itb_per_group));
+		sbi->s_overhead_last = overhead;
+		smp_wmb();
+		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
 	}
 
 	buf->f_type = EXT2_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
 	buf->f_bfree = ext2_count_free_blocks(sb);
+	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
 	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = ext2_count_free_inodes(sb);
+	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT2_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 1e5038d..d34e996 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -489,7 +489,7 @@
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		return -EPERM;
 
 	if (value) {
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 1e6f138..acc4913 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -120,7 +120,6 @@
 	.open		= generic_file_open,
 	.release	= ext3_release_file,
 	.fsync		= ext3_sync_file,
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index a6cb617..de4e316 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2677,8 +2677,10 @@
 		 */
 		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
 		if (EXT3_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
-		    EXT3_INODE_SIZE(inode->i_sb))
+		    EXT3_INODE_SIZE(inode->i_sb)) {
+			brelse (bh);
 			goto bad_inode;
+		}
 		if (ei->i_extra_isize == 0) {
 			/* The extra space is currently unused. Use it. */
 			ei->i_extra_isize = sizeof(struct ext3_inode) -
@@ -3193,7 +3195,7 @@
 	 */
 
 	journal = EXT3_JOURNAL(inode);
-	if (is_journal_aborted(journal) || IS_RDONLY(inode))
+	if (is_journal_aborted(journal))
 		return -EROFS;
 
 	journal_lock_updates(journal);
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 965006d..4a2a02c 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -41,7 +41,7 @@
 		if (IS_RDONLY(inode))
 			return -EROFS;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(flags, (int __user *) arg))
@@ -122,7 +122,7 @@
 		__u32 generation;
 		int err;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EPERM;
 		if (IS_RDONLY(inode))
 			return -EROFS;
@@ -181,7 +181,7 @@
 		if (IS_RDONLY(inode))
 			return -EROFS;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(rsv_window_size, (int __user *)arg))
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 9bb046d..1586807 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1019,6 +1019,11 @@
 
 		if (!inode)
 			return ERR_PTR(-EACCES);
+
+		if (is_bad_inode(inode)) {
+			iput(inode);
+			return ERR_PTR(-ENOENT);
+		}
 	}
 	return d_splice_alias(inode, dentry);
 }
@@ -1054,6 +1059,11 @@
 	if (!inode)
 		return ERR_PTR(-EACCES);
 
+	if (is_bad_inode(inode)) {
+		iput(inode);
+		return ERR_PTR(-ENOENT);
+	}
+
 	parent = d_alloc_anon(inode);
 	if (!parent) {
 		iput(inode);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 6e30629..4f84dc8 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -29,12 +29,14 @@
 #include <linux/parser.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/random.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
+#include <linux/log2.h>
 
 #include <asm/uaccess.h>
 
@@ -459,6 +461,14 @@
 
 static void ext3_destroy_inode(struct inode *inode)
 {
+	if (!list_empty(&(EXT3_I(inode)->i_orphan))) {
+		printk("EXT3 Inode %p: orphan list check failed!\n",
+			EXT3_I(inode));
+		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+				EXT3_I(inode), sizeof(struct ext3_inode_info),
+				false);
+		dump_stack();
+	}
 	kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
 }
 
@@ -1566,7 +1576,7 @@
 		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
 		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
 		if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
-		    (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
+		    (!is_power_of_2(sbi->s_inode_size)) ||
 		    (sbi->s_inode_size > blocksize)) {
 			printk (KERN_ERR
 				"EXT3-fs: unsupported inode size: %d\n",
@@ -2075,6 +2085,7 @@
 			       unsigned int journal_inum)
 {
 	journal_t *journal;
+	int err;
 
 	if (sb->s_flags & MS_RDONLY) {
 		printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to "
@@ -2082,13 +2093,15 @@
 		return -EROFS;
 	}
 
-	if (!(journal = ext3_get_journal(sb, journal_inum)))
+	journal = ext3_get_journal(sb, journal_inum);
+	if (!journal)
 		return -EINVAL;
 
 	printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n",
 	       journal_inum);
 
-	if (journal_create(journal)) {
+	err = journal_create(journal);
+	if (err) {
 		printk(KERN_ERR "EXT3-fs: error creating journal.\n");
 		journal_destroy(journal);
 		return -EIO;
@@ -2139,12 +2152,14 @@
 
 	journal_lock_updates(journal);
 	journal_flush(journal);
+	lock_super(sb);
 	if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
 	    sb->s_flags & MS_RDONLY) {
 		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
 		sb->s_dirt = 0;
 		ext3_commit_super(sb, es, 1);
 	}
+	unlock_super(sb);
 	journal_unlock_updates(journal);
 }
 
@@ -2333,7 +2348,13 @@
 			    (sbi->s_mount_state & EXT3_VALID_FS))
 				es->s_state = cpu_to_le16(sbi->s_mount_state);
 
+			/*
+			 * We have to unlock super so that we can wait for
+			 * transactions.
+			 */
+			unlock_super(sb);
 			ext3_mark_recovery_complete(sb, es);
+			lock_super(sb);
 		} else {
 			__le32 ret;
 			if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
@@ -2406,19 +2427,19 @@
 	struct super_block *sb = dentry->d_sb;
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
 	struct ext3_super_block *es = sbi->s_es;
-	ext3_fsblk_t overhead;
-	int i;
 	u64 fsid;
 
-	if (test_opt (sb, MINIX_DF))
-		overhead = 0;
-	else {
-		unsigned long ngroups;
-		ngroups = EXT3_SB(sb)->s_groups_count;
+	if (test_opt(sb, MINIX_DF)) {
+		sbi->s_overhead_last = 0;
+	} else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+		unsigned long ngroups = sbi->s_groups_count, i;
+		ext3_fsblk_t overhead = 0;
 		smp_rmb();
 
 		/*
-		 * Compute the overhead (FS structures)
+		 * Compute the overhead (FS structures).  This is constant
+		 * for a given filesystem unless the number of block groups
+		 * changes so we cache the previous value until it does.
 		 */
 
 		/*
@@ -2442,18 +2463,23 @@
 		 * Every block group has an inode bitmap, a block
 		 * bitmap, and an inode table.
 		 */
-		overhead += (ngroups * (2 + EXT3_SB(sb)->s_itb_per_group));
+		overhead += ngroups * (2 + sbi->s_itb_per_group);
+		sbi->s_overhead_last = overhead;
+		smp_wmb();
+		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
 	}
 
 	buf->f_type = EXT3_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
 	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
 	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT3_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 9e88254..a8bae8c 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -489,7 +489,7 @@
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		return -EPERM;
 
 	if (value) {
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 8a23483..9de54ae 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -30,15 +30,15 @@
 void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
 		unsigned long *blockgrpp, ext4_grpblk_t *offsetp)
 {
-        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
 	ext4_grpblk_t offset;
 
-        blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
+	blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
 	offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
 	if (offsetp)
 		*offsetp = offset;
 	if (blockgrpp)
-	        *blockgrpp = blocknr;
+		*blockgrpp = blocknr;
 
 }
 
@@ -1585,7 +1585,7 @@
 	ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);
 
 	if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
-	    in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+	    in_range(ext4_inode_bitmap(sb, gdp), ret_block, num) ||
 	    in_range(ret_block, ext4_inode_table(sb, gdp),
 		     EXT4_SB(sb)->s_itb_per_group) ||
 	    in_range(ret_block + num - 1, ext4_inode_table(sb, gdp),
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index a0f0c04..b9ce241 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -374,7 +374,7 @@
 				       le32_to_cpu(ix[-1].ei_block));
 			}
 			BUG_ON(k && le32_to_cpu(ix->ei_block)
-				           <= le32_to_cpu(ix[-1].ei_block));
+					   <= le32_to_cpu(ix[-1].ei_block));
 			if (block < le32_to_cpu(ix->ei_block))
 				break;
 			chix = ix;
@@ -423,8 +423,8 @@
 
 	path->p_ext = l - 1;
 	ext_debug("  -> %d:%llu:%d ",
-		        le32_to_cpu(path->p_ext->ee_block),
-		        ext_pblock(path->p_ext),
+			le32_to_cpu(path->p_ext->ee_block),
+			ext_pblock(path->p_ext),
 			le16_to_cpu(path->p_ext->ee_len));
 
 #ifdef CHECK_BINSEARCH
@@ -435,7 +435,7 @@
 		chex = ex = EXT_FIRST_EXTENT(eh);
 		for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ex++) {
 			BUG_ON(k && le32_to_cpu(ex->ee_block)
-				          <= le32_to_cpu(ex[-1].ee_block));
+					  <= le32_to_cpu(ex[-1].ee_block));
 			if (block < le32_to_cpu(ex->ee_block))
 				break;
 			chex = ex;
@@ -577,7 +577,7 @@
 	curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1);
 
 	BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries)
-	                     > le16_to_cpu(curp->p_hdr->eh_max));
+			     > le16_to_cpu(curp->p_hdr->eh_max));
 	BUG_ON(ix > EXT_LAST_INDEX(curp->p_hdr));
 
 	err = ext4_ext_dirty(handle, inode, curp);
@@ -621,12 +621,12 @@
 		border = path[depth].p_ext[1].ee_block;
 		ext_debug("leaf will be split."
 				" next leaf starts at %d\n",
-			          le32_to_cpu(border));
+				  le32_to_cpu(border));
 	} else {
 		border = newext->ee_block;
 		ext_debug("leaf will be added."
 				" next leaf starts at %d\n",
-			        le32_to_cpu(border));
+				le32_to_cpu(border));
 	}
 
 	/*
@@ -684,9 +684,9 @@
 	while (path[depth].p_ext <=
 			EXT_MAX_EXTENT(path[depth].p_hdr)) {
 		ext_debug("move %d:%llu:%d in new leaf %llu\n",
-			        le32_to_cpu(path[depth].p_ext->ee_block),
-			        ext_pblock(path[depth].p_ext),
-			        le16_to_cpu(path[depth].p_ext->ee_len),
+				le32_to_cpu(path[depth].p_ext->ee_block),
+				ext_pblock(path[depth].p_ext),
+				le16_to_cpu(path[depth].p_ext->ee_len),
 				newblock);
 		/*memmove(ex++, path[depth].p_ext++,
 				sizeof(struct ext4_extent));
@@ -765,9 +765,9 @@
 				EXT_LAST_INDEX(path[i].p_hdr));
 		while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
 			ext_debug("%d: move %d:%d in new index %llu\n", i,
-				        le32_to_cpu(path[i].p_idx->ei_block),
-				        idx_pblock(path[i].p_idx),
-				        newblock);
+					le32_to_cpu(path[i].p_idx->ei_block),
+					idx_pblock(path[i].p_idx),
+					newblock);
 			/*memmove(++fidx, path[i].p_idx++,
 					sizeof(struct ext4_extent_idx));
 			neh->eh_entries++;
@@ -1128,6 +1128,55 @@
 }
 
 /*
+ * check if a portion of the "newext" extent overlaps with an
+ * existing extent.
+ *
+ * If there is an overlap discovered, it updates the length of the newext
+ * such that there will be no overlap, and then returns 1.
+ * If there is no overlap found, it returns 0.
+ */
+unsigned int ext4_ext_check_overlap(struct inode *inode,
+				    struct ext4_extent *newext,
+				    struct ext4_ext_path *path)
+{
+	unsigned long b1, b2;
+	unsigned int depth, len1;
+	unsigned int ret = 0;
+
+	b1 = le32_to_cpu(newext->ee_block);
+	len1 = le16_to_cpu(newext->ee_len);
+	depth = ext_depth(inode);
+	if (!path[depth].p_ext)
+		goto out;
+	b2 = le32_to_cpu(path[depth].p_ext->ee_block);
+
+	/*
+	 * get the next allocated block if the extent in the path
+	 * is before the requested block(s) 
+	 */
+	if (b2 < b1) {
+		b2 = ext4_ext_next_allocated_block(path);
+		if (b2 == EXT_MAX_BLOCK)
+			goto out;
+	}
+
+	/* check for wrap through zero */
+	if (b1 + len1 < b1) {
+		len1 = EXT_MAX_BLOCK - b1;
+		newext->ee_len = cpu_to_le16(len1);
+		ret = 1;
+	}
+
+	/* check for overlap */
+	if (b1 + len1 > b2) {
+		newext->ee_len = cpu_to_le16(b2 - b1);
+		ret = 1;
+	}
+out:
+	return ret;
+}
+
+/*
  * ext4_ext_insert_extent:
  * tries to merge requsted extent into the existing extent or
  * inserts requested extent as new one into the tree,
@@ -1212,12 +1261,12 @@
 	if (!nearex) {
 		/* there is no extent in this leaf, create first one */
 		ext_debug("first extent in the leaf: %d:%llu:%d\n",
-			        le32_to_cpu(newext->ee_block),
-			        ext_pblock(newext),
-			        le16_to_cpu(newext->ee_len));
+				le32_to_cpu(newext->ee_block),
+				ext_pblock(newext),
+				le16_to_cpu(newext->ee_len));
 		path[depth].p_ext = EXT_FIRST_EXTENT(eh);
 	} else if (le32_to_cpu(newext->ee_block)
-		           > le32_to_cpu(nearex->ee_block)) {
+			   > le32_to_cpu(nearex->ee_block)) {
 /*		BUG_ON(newext->ee_block == nearex->ee_block); */
 		if (nearex != EXT_LAST_EXTENT(eh)) {
 			len = EXT_MAX_EXTENT(eh) - nearex;
@@ -1225,9 +1274,9 @@
 			len = len < 0 ? 0 : len;
 			ext_debug("insert %d:%llu:%d after: nearest 0x%p, "
 					"move %d from 0x%p to 0x%p\n",
-				        le32_to_cpu(newext->ee_block),
-				        ext_pblock(newext),
-				        le16_to_cpu(newext->ee_len),
+					le32_to_cpu(newext->ee_block),
+					ext_pblock(newext),
+					le16_to_cpu(newext->ee_len),
 					nearex, len, nearex + 1, nearex + 2);
 			memmove(nearex + 2, nearex + 1, len);
 		}
@@ -1358,9 +1407,9 @@
 			cbex.ec_start = 0;
 			cbex.ec_type = EXT4_EXT_CACHE_GAP;
 		} else {
-		        cbex.ec_block = le32_to_cpu(ex->ee_block);
-		        cbex.ec_len = le16_to_cpu(ex->ee_len);
-		        cbex.ec_start = ext_pblock(ex);
+			cbex.ec_block = le32_to_cpu(ex->ee_block);
+			cbex.ec_len = le16_to_cpu(ex->ee_len);
+			cbex.ec_start = ext_pblock(ex);
 			cbex.ec_type = EXT4_EXT_CACHE_EXTENT;
 		}
 
@@ -1431,16 +1480,16 @@
 		len = le32_to_cpu(ex->ee_block) - block;
 		ext_debug("cache gap(before): %lu [%lu:%lu]",
 				(unsigned long) block,
-			        (unsigned long) le32_to_cpu(ex->ee_block),
-			        (unsigned long) le16_to_cpu(ex->ee_len));
+				(unsigned long) le32_to_cpu(ex->ee_block),
+				(unsigned long) le16_to_cpu(ex->ee_len));
 	} else if (block >= le32_to_cpu(ex->ee_block)
-		            + le16_to_cpu(ex->ee_len)) {
-	        lblock = le32_to_cpu(ex->ee_block)
-		         + le16_to_cpu(ex->ee_len);
+			    + le16_to_cpu(ex->ee_len)) {
+		lblock = le32_to_cpu(ex->ee_block)
+			 + le16_to_cpu(ex->ee_len);
 		len = ext4_ext_next_allocated_block(path);
 		ext_debug("cache gap(after): [%lu:%lu] %lu",
-			        (unsigned long) le32_to_cpu(ex->ee_block),
-			        (unsigned long) le16_to_cpu(ex->ee_len),
+				(unsigned long) le32_to_cpu(ex->ee_block),
+				(unsigned long) le16_to_cpu(ex->ee_len),
 				(unsigned long) block);
 		BUG_ON(len == lblock);
 		len = len - lblock;
@@ -1468,9 +1517,9 @@
 	BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
 			cex->ec_type != EXT4_EXT_CACHE_EXTENT);
 	if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
-	        ex->ee_block = cpu_to_le32(cex->ec_block);
+		ex->ee_block = cpu_to_le32(cex->ec_block);
 		ext4_ext_store_pblock(ex, cex->ec_start);
-	        ex->ee_len = cpu_to_le16(cex->ec_len);
+		ex->ee_len = cpu_to_le16(cex->ec_len);
 		ext_debug("%lu cached by %lu:%lu:%llu\n",
 				(unsigned long) block,
 				(unsigned long) cex->ec_block,
@@ -1956,9 +2005,9 @@
 			/* we should allocate requested block */
 		} else if (goal == EXT4_EXT_CACHE_EXTENT) {
 			/* block is already allocated */
-		        newblock = iblock
-		                   - le32_to_cpu(newex.ee_block)
-			           + ext_pblock(&newex);
+			newblock = iblock
+				   - le32_to_cpu(newex.ee_block)
+				   + ext_pblock(&newex);
 			/* number of remaining blocks in the extent */
 			allocated = le16_to_cpu(newex.ee_len) -
 					(iblock - le32_to_cpu(newex.ee_block));
@@ -1987,7 +2036,7 @@
 
 	ex = path[depth].p_ext;
 	if (ex) {
-	        unsigned long ee_block = le32_to_cpu(ex->ee_block);
+		unsigned long ee_block = le32_to_cpu(ex->ee_block);
 		ext4_fsblk_t ee_start = ext_pblock(ex);
 		unsigned short ee_len  = le16_to_cpu(ex->ee_len);
 
@@ -2000,7 +2049,7 @@
 		if (ee_len > EXT_MAX_LEN)
 			goto out2;
 		/* if found extent covers block, simply return it */
-	        if (iblock >= ee_block && iblock < ee_block + ee_len) {
+		if (iblock >= ee_block && iblock < ee_block + ee_len) {
 			newblock = iblock - ee_block + ee_start;
 			/* number of remaining blocks in the extent */
 			allocated = ee_len - (iblock - ee_block);
@@ -2031,7 +2080,15 @@
 
 	/* allocate new block */
 	goal = ext4_ext_find_goal(inode, path, iblock);
-	allocated = max_blocks;
+
+	/* Check if we can really insert (iblock)::(iblock+max_blocks) extent */
+	newex.ee_block = cpu_to_le32(iblock);
+	newex.ee_len = cpu_to_le16(max_blocks);
+	err = ext4_ext_check_overlap(inode, &newex, path);
+	if (err)
+		allocated = le16_to_cpu(newex.ee_len);
+	else
+		allocated = max_blocks;
 	newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err);
 	if (!newblock)
 		goto out2;
@@ -2039,12 +2096,15 @@
 			goal, newblock, allocated);
 
 	/* try to insert new extent into found leaf and return */
-	newex.ee_block = cpu_to_le32(iblock);
 	ext4_ext_store_pblock(&newex, newblock);
 	newex.ee_len = cpu_to_le16(allocated);
 	err = ext4_ext_insert_extent(handle, inode, path, &newex);
-	if (err)
+	if (err) {
+		/* free data blocks we just allocated */
+		ext4_free_blocks(handle, inode, ext_pblock(&newex),
+					le16_to_cpu(newex.ee_len));
 		goto out2;
+	}
 
 	if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize)
 		EXT4_I(inode)->i_disksize = inode->i_size;
@@ -2157,11 +2217,3 @@
 
 	return needed;
 }
-
-EXPORT_SYMBOL(ext4_mark_inode_dirty);
-EXPORT_SYMBOL(ext4_ext_invalidate_cache);
-EXPORT_SYMBOL(ext4_ext_insert_extent);
-EXPORT_SYMBOL(ext4_ext_walk_space);
-EXPORT_SYMBOL(ext4_ext_find_goal);
-EXPORT_SYMBOL(ext4_ext_calc_credits_for_insert);
-
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 3c6c1fd..d4c8186 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -120,7 +120,6 @@
 	.open		= generic_file_open,
 	.release	= ext4_release_file,
 	.fsync		= ext4_sync_file,
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index b34182b..8416fa2 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -255,8 +255,8 @@
  *	@inode: inode in question (we are only interested in its superblock)
  *	@i_block: block number to be parsed
  *	@offsets: array to store the offsets in
- *      @boundary: set this non-zero if the referred-to block is likely to be
- *             followed (on disk) by an indirect block.
+ *	@boundary: set this non-zero if the referred-to block is likely to be
+ *	       followed (on disk) by an indirect block.
  *
  *	To store the locations of file's data ext4 uses a data structure common
  *	for UNIX filesystems - tree of pointers anchored in the inode, with
@@ -2673,8 +2673,10 @@
 		 */
 		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
 		if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
-		    EXT4_INODE_SIZE(inode->i_sb))
+		    EXT4_INODE_SIZE(inode->i_sb)) {
+			brelse (bh);
 			goto bad_inode;
+		}
 		if (ei->i_extra_isize == 0) {
 			/* The extra space is currently unused. Use it. */
 			ei->i_extra_isize = sizeof(struct ext4_inode) -
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 500567d..7b4aa45 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -40,7 +40,7 @@
 		if (IS_RDONLY(inode))
 			return -EROFS;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(flags, (int __user *) arg))
@@ -121,7 +121,7 @@
 		__u32 generation;
 		int err;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EPERM;
 		if (IS_RDONLY(inode))
 			return -EROFS;
@@ -180,7 +180,7 @@
 		if (IS_RDONLY(inode))
 			return -EROFS;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(rsv_window_size, (int __user *)arg))
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 4ec57be..2de339d 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -46,7 +46,7 @@
  */
 #define NAMEI_RA_CHUNKS  2
 #define NAMEI_RA_BLOCKS  4
-#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
+#define NAMEI_RA_SIZE	     (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
 #define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
 
 static struct buffer_head *ext4_append(handle_t *handle,
@@ -241,7 +241,7 @@
 static void dx_show_index (char * label, struct dx_entry *entries)
 {
 	int i, n = dx_get_count (entries);
-        printk("%s index ", label);
+	printk("%s index ", label);
 	for (i = 0; i < n; i++) {
 		printk("%x->%u ", i? dx_get_hash(entries + i) :
 				0, dx_get_block(entries + i));
@@ -1017,6 +1017,11 @@
 
 		if (!inode)
 			return ERR_PTR(-EACCES);
+
+		if (is_bad_inode(inode)) {
+			iput(inode);
+			return ERR_PTR(-ENOENT);
+		}
 	}
 	return d_splice_alias(inode, dentry);
 }
@@ -1052,6 +1057,11 @@
 	if (!inode)
 		return ERR_PTR(-EACCES);
 
+	if (is_bad_inode(inode)) {
+		iput(inode);
+		return ERR_PTR(-ENOENT);
+	}
+
 	parent = d_alloc_anon(inode);
 	if (!parent) {
 		iput(inode);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index cb9afdd..b806e68 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -29,6 +29,7 @@
 #include <linux/parser.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/random.h>
 #include <linux/mount.h>
@@ -510,6 +511,14 @@
 
 static void ext4_destroy_inode(struct inode *inode)
 {
+	if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
+		printk("EXT4 Inode %p: orphan list check failed!\n",
+			EXT4_I(inode));
+		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+				EXT4_I(inode), sizeof(struct ext4_inode_info),
+				true);
+		dump_stack();
+	}
 	kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
@@ -1985,7 +1994,7 @@
 
 	if (bd_claim(bdev, sb)) {
 		printk(KERN_ERR
-		        "EXT4: failed to claim external journal device.\n");
+			"EXT4: failed to claim external journal device.\n");
 		blkdev_put(bdev);
 		return NULL;
 	}
@@ -2150,6 +2159,7 @@
 			       unsigned int journal_inum)
 {
 	journal_t *journal;
+	int err;
 
 	if (sb->s_flags & MS_RDONLY) {
 		printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to "
@@ -2157,13 +2167,15 @@
 		return -EROFS;
 	}
 
-	if (!(journal = ext4_get_journal(sb, journal_inum)))
+	journal = ext4_get_journal(sb, journal_inum);
+	if (!journal)
 		return -EINVAL;
 
 	printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n",
 	       journal_inum);
 
-	if (jbd2_journal_create(journal)) {
+	err = jbd2_journal_create(journal);
+	if (err) {
 		printk(KERN_ERR "EXT4-fs: error creating journal.\n");
 		jbd2_journal_destroy(journal);
 		return -EIO;
@@ -2214,12 +2226,14 @@
 
 	jbd2_journal_lock_updates(journal);
 	jbd2_journal_flush(journal);
+	lock_super(sb);
 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
 	    sb->s_flags & MS_RDONLY) {
 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
 		sb->s_dirt = 0;
 		ext4_commit_super(sb, es, 1);
 	}
+	unlock_super(sb);
 	jbd2_journal_unlock_updates(journal);
 }
 
@@ -2408,7 +2422,13 @@
 			    (sbi->s_mount_state & EXT4_VALID_FS))
 				es->s_state = cpu_to_le16(sbi->s_mount_state);
 
+			/*
+			 * We have to unlock super so that we can wait for
+			 * transactions.
+			 */
+			unlock_super(sb);
 			ext4_mark_recovery_complete(sb, es);
+			lock_super(sb);
 		} else {
 			__le32 ret;
 			if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb,
@@ -2481,19 +2501,19 @@
 	struct super_block *sb = dentry->d_sb;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct ext4_super_block *es = sbi->s_es;
-	ext4_fsblk_t overhead;
-	int i;
 	u64 fsid;
 
-	if (test_opt (sb, MINIX_DF))
-		overhead = 0;
-	else {
-		unsigned long ngroups;
-		ngroups = EXT4_SB(sb)->s_groups_count;
+	if (test_opt(sb, MINIX_DF)) {
+		sbi->s_overhead_last = 0;
+	} else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+		unsigned long ngroups = sbi->s_groups_count, i;
+		ext4_fsblk_t overhead = 0;
 		smp_rmb();
 
 		/*
-		 * Compute the overhead (FS structures)
+		 * Compute the overhead (FS structures).  This is constant
+		 * for a given filesystem unless the number of block groups
+		 * changes so we cache the previous value until it does.
 		 */
 
 		/*
@@ -2517,18 +2537,23 @@
 		 * Every block group has an inode bitmap, a block
 		 * bitmap, and an inode table.
 		 */
-		overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group));
+		overhead += ngroups * (2 + sbi->s_itb_per_group);
+		sbi->s_overhead_last = overhead;
+		smp_wmb();
+		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
 	}
 
 	buf->f_type = EXT4_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = ext4_blocks_count(es) - overhead;
+	buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
 	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
 	if (buf->f_bfree < ext4_r_blocks_count(es))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT4_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index ccf161d..72cbcd6 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -313,7 +313,7 @@
 	wchar_t bufuname[14];
 	unsigned char xlate_len, nr_slots;
 	wchar_t *unicode = NULL;
-	unsigned char work[8], bufname[260];	/* 256 + 4 */
+	unsigned char work[MSDOS_NAME], bufname[260];	/* 256 + 4 */
 	int uni_xlate = sbi->options.unicode_xlate;
 	int utf8 = sbi->options.utf8;
 	int anycase = (sbi->options.name_check != 's');
@@ -351,7 +351,8 @@
 		if (work[0] == 0x05)
 			work[0] = 0xE5;
 		for (i = 0, j = 0, last_u = 0; i < 8;) {
-			if (!work[i]) break;
+			if (!work[i])
+				break;
 			chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
 						&bufuname[j++], opt_shortname,
 						de->lcase & CASE_LOWER_BASE);
@@ -365,13 +366,15 @@
 		}
 		j = last_u;
 		fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
-		for (i = 0; i < 3;) {
-			if (!de->ext[i]) break;
-			chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i,
+		for (i = 8; i < MSDOS_NAME;) {
+			if (!work[i])
+				break;
+			chl = fat_shortname2uni(nls_disk, &work[i],
+						MSDOS_NAME - i,
 						&bufuname[j++], opt_shortname,
 						de->lcase & CASE_LOWER_EXT);
 			if (chl <= 1) {
-				if (de->ext[i] != ' ')
+				if (work[i] != ' ')
 					last_u = j;
 			} else {
 				last_u = j;
@@ -445,7 +448,7 @@
 	int fill_len;
 	wchar_t bufuname[14];
 	wchar_t *unicode = NULL;
-	unsigned char c, work[8], bufname[56], *ptname = bufname;
+	unsigned char c, work[MSDOS_NAME], bufname[56], *ptname = bufname;
 	unsigned long lpos, dummy, *furrfu = &lpos;
 	int uni_xlate = sbi->options.unicode_xlate;
 	int isvfat = sbi->options.isvfat;
@@ -527,7 +530,8 @@
 	if (work[0] == 0x05)
 		work[0] = 0xE5;
 	for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) {
-		if (!(c = work[i])) break;
+		if (!(c = work[i]))
+			break;
 		chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
 					&bufuname[j++], opt_shortname,
 					de->lcase & CASE_LOWER_BASE);
@@ -549,9 +553,10 @@
 	j = last_u;
 	fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
 	ptname[i++] = '.';
-	for (i2 = 0; i2 < 3;) {
-		if (!(c = de->ext[i2])) break;
-		chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2,
+	for (i2 = 8; i2 < MSDOS_NAME;) {
+		if (!(c = work[i2]))
+			break;
+		chl = fat_shortname2uni(nls_disk, &work[i2], MSDOS_NAME - i2,
 					&bufuname[j++], opt_shortname,
 					de->lcase & CASE_LOWER_EXT);
 		if (chl <= 1) {
@@ -563,8 +568,8 @@
 			}
 		} else {
 			last_u = j;
-			for (chi = 0; chi < chl && i2 < 3; chi++) {
-				ptname[i++] = de->ext[i2++];
+			for (chi = 0; chi < chl && i2 < MSDOS_NAME; chi++) {
+				ptname[i++] = work[i2++];
 				last = i;
 			}
 		}
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index ab171ea8..2c1b73f 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -17,6 +17,8 @@
 	int (*ent_next)(struct fat_entry *);
 };
 
+static DEFINE_SPINLOCK(fat12_entry_lock);
+
 static void fat12_ent_blocknr(struct super_block *sb, int entry,
 			      int *offset, sector_t *blocknr)
 {
@@ -116,10 +118,13 @@
 	u8 **ent12_p = fatent->u.ent12_p;
 	int next;
 
+	spin_lock(&fat12_entry_lock);
 	if (fatent->entry & 1)
 		next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);
 	else
 		next = (*ent12_p[1] << 8) | *ent12_p[0];
+	spin_unlock(&fat12_entry_lock);
+
 	next &= 0x0fff;
 	if (next >= BAD_FAT12)
 		next = FAT_ENT_EOF;
@@ -151,6 +156,7 @@
 	if (new == FAT_ENT_EOF)
 		new = EOF_FAT12;
 
+	spin_lock(&fat12_entry_lock);
 	if (fatent->entry & 1) {
 		*ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);
 		*ent12_p[1] = new >> 4;
@@ -158,6 +164,7 @@
 		*ent12_p[0] = new & 0xff;
 		*ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);
 	}
+	spin_unlock(&fat12_entry_lock);
 
 	mark_buffer_dirty(fatent->bhs[0]);
 	if (fatent->nr_bhs == 2)
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 55d3c74..69a83b5 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -134,7 +134,7 @@
 	.release	= fat_file_release,
 	.ioctl		= fat_generic_ioctl,
 	.fsync		= file_fsync,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 static int fat_cont_expand(struct inode *inode, loff_t size)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 479722d..0a7ddb3 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -20,6 +20,7 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/mount.h>
 #include <linux/vfs.h>
 #include <linux/parser.h>
@@ -354,8 +355,7 @@
 	} else { /* not a directory */
 		inode->i_generation |= 1;
 		inode->i_mode = MSDOS_MKMODE(de->attr,
-		    ((sbi->options.showexec &&
-			!is_exec(de->ext))
+		    ((sbi->options.showexec && !is_exec(de->name + 8))
 			? S_IRUGO|S_IWUGO : S_IRWXUGO)
 		    & ~sbi->options.fs_fmask) | S_IFREG;
 		MSDOS_I(inode)->i_start = le16_to_cpu(de->start);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 8e382a5..3f22e9f 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -215,7 +215,7 @@
 
 	/* O_NOATIME can only be set by the owner or superuser */
 	if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME))
-		if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EPERM;
 
 	/* required for strict SunOS emulation */
diff --git a/fs/fifo.c b/fs/fifo.c
index 6e7df72..9785e36 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/sched.h>
 #include <linux/pipe_fs_i.h>
 
 static void wait_for_partner(struct inode* inode, unsigned int *cnt)
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
index 8a4dfef..3c96d6e 100644
--- a/fs/freevxfs/vxfs_dir.h
+++ b/fs/freevxfs/vxfs_dir.h
@@ -80,7 +80,7 @@
  *	a d_name with size len.
  */
 #define VXFS_DIRPAD		4
-#define VXFS_NAMEMIN		((int)((struct vxfs_direct *)0)->d_name)
+#define VXFS_NAMEMIN		offsetof(struct vxfs_direct, d_name)
 #define VXFS_DIRROUND(len)	((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
 #define VXFS_DIRLEN(len)	(VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
 
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 8890eba..bd5a772 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -485,7 +485,7 @@
 static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
 		       struct nameidata *nd)
 {
-	if (nd && (nd->flags & LOOKUP_CREATE)) {
+	if (nd && (nd->flags & LOOKUP_OPEN)) {
 		int err = fuse_create_open(dir, entry, mode, nd);
 		if (err != -ENOSYS)
 			return err;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index acfad65..f79de7c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -11,6 +11,7 @@
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -609,7 +610,9 @@
 	ssize_t res;
 	/* Don't allow parallel writes to the same file */
 	mutex_lock(&inode->i_mutex);
-	res = fuse_direct_io(file, buf, count, ppos, 1);
+	res = generic_write_checks(file, ppos, &count, 0);
+	if (!res)
+		res = fuse_direct_io(file, buf, count, ppos, 1);
 	mutex_unlock(&inode->i_mutex);
 	return res;
 }
@@ -799,7 +802,7 @@
 	.release	= fuse_release,
 	.fsync		= fuse_fsync,
 	.lock		= fuse_file_lock,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 static const struct file_operations fuse_direct_io_file_operations = {
@@ -811,7 +814,7 @@
 	.release	= fuse_release,
 	.fsync		= fuse_fsync,
 	.lock		= fuse_file_lock,
-	/* no mmap and sendfile */
+	/* no mmap and splice_read */
 };
 
 static const struct address_space_operations fuse_file_aops  = {
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index c3a2ad0..cc5efc1 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -17,6 +17,7 @@
 #include <linux/parser.h>
 #include <linux/statfs.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -453,6 +454,7 @@
 	.destroy_inode  = fuse_destroy_inode,
 	.read_inode	= fuse_read_inode,
 	.clear_inode	= fuse_clear_inode,
+	.drop_inode	= generic_delete_inode,
 	.remount_fs	= fuse_remount_fs,
 	.put_super	= fuse_put_super,
 	.umount_begin	= fuse_umount_begin,
@@ -653,10 +655,9 @@
 static struct file_system_type fuseblk_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= "fuseblk",
-	.fs_flags	= FS_HAS_SUBTYPE,
 	.get_sb		= fuse_get_sb_blk,
 	.kill_sb	= kill_block_super,
-	.fs_flags	= FS_REQUIRES_DEV,
+	.fs_flags	= FS_REQUIRES_DEV | FS_HAS_SUBTYPE,
 };
 
 static inline int register_fuseblk(void)
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index 9ccb789..995d63b 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -78,7 +78,7 @@
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
-	if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		return -EPERM;
 	if (value) {
 		acl = posix_acl_from_xattr(value, size);
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index e3f1ada..04ad0ca 100644
--- a/fs/gfs2/Makefile
+++ b/fs/gfs2/Makefile
@@ -1,7 +1,7 @@
 obj-$(CONFIG_GFS2_FS) += gfs2.o
 gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
 	glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \
-	mount.o ondisk.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
+	mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
 	ops_fstype.o ops_inode.o ops_super.o ops_vm.o quota.o \
 	recovery.o rgrp.o super.o sys.o trans.o util.o
 
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 6e80844..1047a8c 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -74,7 +74,7 @@
 {
 	if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl)
 		return -EOPNOTSUPP;
-	if (current->fsuid != ip->i_inode.i_uid && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(&ip->i_inode))
 		return -EPERM;
 	if (S_ISLNK(ip->i_inode.i_mode))
 		return -EOPNOTSUPP;
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index c53a5d2..cd805a6 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -718,7 +718,7 @@
 	for (x = 0; x < rlist.rl_rgrps; x++) {
 		struct gfs2_rgrpd *rgd;
 		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
-		rg_blocks += rgd->rd_ri.ri_length;
+		rg_blocks += rgd->rd_length;
 	}
 
 	error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
@@ -772,7 +772,7 @@
 			gfs2_free_data(ip, bstart, blen);
 	}
 
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
 	gfs2_dinode_out(ip, dibh->b_data);
 
@@ -824,7 +824,7 @@
 		goto out_gunlock_q;
 
 	error = gfs2_trans_begin(sdp,
-			sdp->sd_max_height + al->al_rgd->rd_ri.ri_length +
+			sdp->sd_max_height + al->al_rgd->rd_length +
 			RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
 	if (error)
 		goto out_ipres;
@@ -847,7 +847,7 @@
 	}
 
 	ip->i_di.di_size = size;
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (error)
@@ -885,7 +885,6 @@
 	unsigned blocksize, iblock, length, pos;
 	struct buffer_head *bh;
 	struct page *page;
-	void *kaddr;
 	int err;
 
 	page = grab_cache_page(mapping, index);
@@ -928,15 +927,13 @@
 		/* Uhhuh. Read error. Complain and punt. */
 		if (!buffer_uptodate(bh))
 			goto unlock;
+		err = 0;
 	}
 
 	if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
 		gfs2_trans_add_bh(ip->i_gl, bh, 0);
 
-	kaddr = kmap_atomic(page, KM_USER0);
-	memset(kaddr + offset, 0, length);
-	flush_dcache_page(page);
-	kunmap_atomic(kaddr, KM_USER0);
+	zero_user_page(page, offset, length, KM_USER0);
 
 unlock:
 	unlock_page(page);
@@ -962,7 +959,7 @@
 
 	if (gfs2_is_stuffed(ip)) {
 		ip->i_di.di_size = size;
-		ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
@@ -974,7 +971,7 @@
 
 		if (!error) {
 			ip->i_di.di_size = size;
-			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 			ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
 			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 			gfs2_dinode_out(ip, dibh->b_data);
@@ -1044,10 +1041,10 @@
 		ip->i_di.di_height = 0;
 		ip->i_di.di_goal_meta =
 			ip->i_di.di_goal_data =
-			ip->i_num.no_addr;
+			ip->i_no_addr;
 		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 	}
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 	ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c
index 683cb5b..3548d9f 100644
--- a/fs/gfs2/daemon.c
+++ b/fs/gfs2/daemon.c
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/lm_interface.h>
+#include <linux/freezer.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -49,6 +50,8 @@
 	while (!kthread_should_stop()) {
 		gfs2_scand_internal(sdp);
 		t = gfs2_tune_get(sdp, gt_scand_secs) * HZ;
+		if (freezing(current))
+			refrigerator();
 		schedule_timeout_interruptible(t);
 	}
 
@@ -74,6 +77,8 @@
 		wait_event_interruptible(sdp->sd_reclaim_wq,
 					 (atomic_read(&sdp->sd_reclaim_count) ||
 					 kthread_should_stop()));
+		if (freezing(current))
+			refrigerator();
 	}
 
 	return 0;
@@ -93,6 +98,8 @@
 	while (!kthread_should_stop()) {
 		gfs2_check_journals(sdp);
 		t = gfs2_tune_get(sdp,  gt_recoverd_secs) * HZ;
+		if (freezing(current))
+			refrigerator();
 		schedule_timeout_interruptible(t);
 	}
 
@@ -141,6 +148,8 @@
 		}
 
 		t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
+		if (freezing(current))
+			refrigerator();
 		schedule_timeout_interruptible(t);
 	}
 
@@ -191,6 +200,8 @@
 		gfs2_quota_scan(sdp);
 
 		t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ;
+		if (freezing(current))
+			refrigerator();
 		schedule_timeout_interruptible(t);
 	}
 
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index a96fa07..2beb2f4 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -130,7 +130,7 @@
 	memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
 	if (ip->i_di.di_size < offset + size)
 		ip->i_di.di_size = offset + size;
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_dinode_out(ip, dibh->b_data);
 
 	brelse(dibh);
@@ -228,7 +228,7 @@
 
 	if (ip->i_di.di_size < offset + copied)
 		ip->i_di.di_size = offset + copied;
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
@@ -1456,7 +1456,7 @@
 		if (dip->i_di.di_entries != g.offset) {
 			fs_warn(sdp, "Number of entries corrupt in dir %llu, "
 				"ip->i_di.di_entries (%u) != g.offset (%u)\n",
-				(unsigned long long)dip->i_num.no_addr,
+				(unsigned long long)dip->i_no_addr,
 				dip->i_di.di_entries,
 				g.offset);
 			error = -EIO;
@@ -1488,24 +1488,55 @@
  * Returns: errno
  */
 
-int gfs2_dir_search(struct inode *dir, const struct qstr *name,
-		    struct gfs2_inum_host *inum, unsigned int *type)
+struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
 {
 	struct buffer_head *bh;
 	struct gfs2_dirent *dent;
+	struct inode *inode;
+
+	dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
+	if (dent) {
+		if (IS_ERR(dent))
+			return ERR_PTR(PTR_ERR(dent));
+		inode = gfs2_inode_lookup(dir->i_sb, 
+				be16_to_cpu(dent->de_type),
+				be64_to_cpu(dent->de_inum.no_addr),
+				be64_to_cpu(dent->de_inum.no_formal_ino));
+		brelse(bh);
+		return inode;
+	}
+	return ERR_PTR(-ENOENT);
+}
+
+int gfs2_dir_check(struct inode *dir, const struct qstr *name,
+		   const struct gfs2_inode *ip)
+{
+	struct buffer_head *bh;
+	struct gfs2_dirent *dent;
+	int ret = -ENOENT;
 
 	dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
 	if (dent) {
 		if (IS_ERR(dent))
 			return PTR_ERR(dent);
-		if (inum)
-			gfs2_inum_in(inum, (char *)&dent->de_inum);
-		if (type)
-			*type = be16_to_cpu(dent->de_type);
+		if (ip) {
+			if (be64_to_cpu(dent->de_inum.no_addr) != ip->i_no_addr)
+				goto out;
+			if (be64_to_cpu(dent->de_inum.no_formal_ino) !=
+			    ip->i_no_formal_ino)
+				goto out;
+			if (unlikely(IF2DT(ip->i_inode.i_mode) !=
+			    be16_to_cpu(dent->de_type))) {
+				gfs2_consist_inode(GFS2_I(dir));
+				ret = -EIO;
+				goto out;
+			}
+		}
+		ret = 0;
+out:
 		brelse(bh);
-		return 0;
 	}
-	return -ENOENT;
+	return ret;
 }
 
 static int dir_new_leaf(struct inode *inode, const struct qstr *name)
@@ -1565,7 +1596,7 @@
  */
 
 int gfs2_dir_add(struct inode *inode, const struct qstr *name,
-		 const struct gfs2_inum_host *inum, unsigned type)
+		 const struct gfs2_inode *nip, unsigned type)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct buffer_head *bh;
@@ -1580,7 +1611,7 @@
 			if (IS_ERR(dent))
 				return PTR_ERR(dent);
 			dent = gfs2_init_dirent(inode, dent, name, bh);
-			gfs2_inum_out(inum, (char *)&dent->de_inum);
+			gfs2_inum_out(nip, dent);
 			dent->de_type = cpu_to_be16(type);
 			if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
 				leaf = (struct gfs2_leaf *)bh->b_data;
@@ -1592,7 +1623,7 @@
 				break;
 			gfs2_trans_add_bh(ip->i_gl, bh, 1);
 			ip->i_di.di_entries++;
-			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 			gfs2_dinode_out(ip, bh->b_data);
 			brelse(bh);
 			error = 0;
@@ -1678,7 +1709,7 @@
 		gfs2_consist_inode(dip);
 	gfs2_trans_add_bh(dip->i_gl, bh, 1);
 	dip->i_di.di_entries--;
-	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_dinode_out(dip, bh->b_data);
 	brelse(bh);
 	mark_inode_dirty(&dip->i_inode);
@@ -1700,7 +1731,7 @@
  */
 
 int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
-		   struct gfs2_inum_host *inum, unsigned int new_type)
+		   const struct gfs2_inode *nip, unsigned int new_type)
 {
 	struct buffer_head *bh;
 	struct gfs2_dirent *dent;
@@ -1715,7 +1746,7 @@
 		return PTR_ERR(dent);
 
 	gfs2_trans_add_bh(dip->i_gl, bh, 1);
-	gfs2_inum_out(inum, (char *)&dent->de_inum);
+	gfs2_inum_out(nip, dent);
 	dent->de_type = cpu_to_be16(new_type);
 
 	if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
@@ -1726,7 +1757,7 @@
 		gfs2_trans_add_bh(dip->i_gl, bh, 1);
 	}
 
-	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_dinode_out(dip, bh->b_data);
 	brelse(bh);
 	return 0;
@@ -1867,7 +1898,7 @@
 	for (x = 0; x < rlist.rl_rgrps; x++) {
 		struct gfs2_rgrpd *rgd;
 		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
-		rg_blocks += rgd->rd_ri.ri_length;
+		rg_blocks += rgd->rd_length;
 	}
 
 	error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index 48fe890..8a468ca 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -16,15 +16,16 @@
 struct gfs2_inode;
 struct gfs2_inum;
 
-int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
-		    struct gfs2_inum_host *inum, unsigned int *type);
+struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename);
+int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
+		   const struct gfs2_inode *ip);
 int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
-		 const struct gfs2_inum_host *inum, unsigned int type);
+		 const struct gfs2_inode *ip, unsigned int type);
 int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
 int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
 		  filldir_t filldir);
 int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
-		   struct gfs2_inum_host *new_inum, unsigned int new_type);
+		   const struct gfs2_inode *nip, unsigned int new_type);
 
 int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
 
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c
index c1f4400..1ab3e9d 100644
--- a/fs/gfs2/eaops.c
+++ b/fs/gfs2/eaops.c
@@ -11,6 +11,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
+#include <linux/capability.h>
 #include <linux/xattr.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/lm_interface.h>
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index 5b83ca6..2a7435b 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -254,7 +254,7 @@
 	if (error)
 		return error;
 
-	error = gfs2_trans_begin(sdp, rgd->rd_ri.ri_length + RES_DINODE +
+	error = gfs2_trans_begin(sdp, rgd->rd_length + RES_DINODE +
 				 RES_EATTR + RES_STATFS + RES_QUOTA, blks);
 	if (error)
 		goto out_gunlock;
@@ -300,7 +300,7 @@
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (!error) {
-		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -700,7 +700,7 @@
 		goto out_gunlock_q;
 
 	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
-				 blks + al->al_rgd->rd_ri.ri_length +
+				 blks + al->al_rgd->rd_length +
 				 RES_DINODE + RES_STATFS + RES_QUOTA, 0);
 	if (error)
 		goto out_ipres;
@@ -717,7 +717,7 @@
 					    (er->er_mode & S_IFMT));
 			ip->i_inode.i_mode = er->er_mode;
 		}
-		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -852,7 +852,7 @@
 			(ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));
 		ip->i_inode.i_mode = er->er_mode;
 	}
-	ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
 	brelse(dibh);
@@ -1133,7 +1133,7 @@
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (!error) {
-		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -1352,7 +1352,7 @@
 	for (x = 0; x < rlist.rl_rgrps; x++) {
 		struct gfs2_rgrpd *rgd;
 		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
-		rg_blocks += rgd->rd_ri.ri_length;
+		rg_blocks += rgd->rd_length;
 	}
 
 	error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 1815429..3f0974e 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -422,11 +422,11 @@
 static void gfs2_holder_wake(struct gfs2_holder *gh)
 {
 	clear_bit(HIF_WAIT, &gh->gh_iflags);
-	smp_mb();
+	smp_mb__after_clear_bit();
 	wake_up_bit(&gh->gh_iflags, HIF_WAIT);
 }
 
-static int holder_wait(void *word)
+static int just_schedule(void *word)
 {
         schedule();
         return 0;
@@ -435,7 +435,20 @@
 static void wait_on_holder(struct gfs2_holder *gh)
 {
 	might_sleep();
-	wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE);
+	wait_on_bit(&gh->gh_iflags, HIF_WAIT, just_schedule, TASK_UNINTERRUPTIBLE);
+}
+
+static void gfs2_demote_wake(struct gfs2_glock *gl)
+{
+        clear_bit(GLF_DEMOTE, &gl->gl_flags);
+        smp_mb__after_clear_bit();
+        wake_up_bit(&gl->gl_flags, GLF_DEMOTE);
+}
+
+static void wait_on_demote(struct gfs2_glock *gl)
+{
+	might_sleep();
+	wait_on_bit(&gl->gl_flags, GLF_DEMOTE, just_schedule, TASK_UNINTERRUPTIBLE);
 }
 
 /**
@@ -528,7 +541,7 @@
 
 	if (gl->gl_state == gl->gl_demote_state ||
 	    gl->gl_state == LM_ST_UNLOCKED) {
-		clear_bit(GLF_DEMOTE, &gl->gl_flags);
+		gfs2_demote_wake(gl);
 		return 0;
 	}
 	set_bit(GLF_LOCK, &gl->gl_flags);
@@ -666,12 +679,22 @@
  * practise: LM_ST_SHARED and LM_ST_UNLOCKED
  */
 
-static void handle_callback(struct gfs2_glock *gl, unsigned int state)
+static void handle_callback(struct gfs2_glock *gl, unsigned int state, int remote)
 {
 	spin_lock(&gl->gl_spin);
 	if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) {
 		gl->gl_demote_state = state;
 		gl->gl_demote_time = jiffies;
+		if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN &&
+		    gl->gl_object) {
+			struct inode *inode = igrab(gl->gl_object);
+			spin_unlock(&gl->gl_spin);
+			if (inode) {
+				d_prune_aliases(inode);
+				iput(inode);
+			}
+			return;
+		}
 	} else if (gl->gl_demote_state != LM_ST_UNLOCKED) {
 		gl->gl_demote_state = state;
 	}
@@ -740,7 +763,7 @@
 		if (ret & LM_OUT_CANCELED)
 			op_done = 0;
 		else
-			clear_bit(GLF_DEMOTE, &gl->gl_flags);
+			gfs2_demote_wake(gl);
 	} else {
 		spin_lock(&gl->gl_spin);
 		list_del_init(&gh->gh_list);
@@ -848,7 +871,7 @@
 	gfs2_assert_warn(sdp, !ret);
 
 	state_change(gl, LM_ST_UNLOCKED);
-	clear_bit(GLF_DEMOTE, &gl->gl_flags);
+	gfs2_demote_wake(gl);
 
 	if (glops->go_inval)
 		glops->go_inval(gl, DIO_METADATA);
@@ -1174,7 +1197,7 @@
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
 
 	if (gh->gh_flags & GL_NOCACHE)
-		handle_callback(gl, LM_ST_UNLOCKED);
+		handle_callback(gl, LM_ST_UNLOCKED, 0);
 
 	gfs2_glmutex_lock(gl);
 
@@ -1196,6 +1219,13 @@
 	spin_unlock(&gl->gl_spin);
 }
 
+void gfs2_glock_dq_wait(struct gfs2_holder *gh)
+{
+	struct gfs2_glock *gl = gh->gh_gl;
+	gfs2_glock_dq(gh);
+	wait_on_demote(gl);
+}
+
 /**
  * gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it
  * @gh: the holder structure
@@ -1297,10 +1327,6 @@
  * @num_gh: the number of structures
  * @ghs: an array of struct gfs2_holder structures
  *
- * Figure out how big an impact this function has.  Either:
- * 1) Replace this code with code that calls gfs2_glock_prefetch()
- * 2) Forget async stuff and just call nq_m_sync()
- * 3) Leave it like it is
  *
  * Returns: 0 on success (all glocks acquired),
  *          errno on failure (no glocks acquired)
@@ -1308,62 +1334,28 @@
 
 int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs)
 {
-	int *e;
-	unsigned int x;
-	int borked = 0, serious = 0;
+	struct gfs2_holder *tmp[4];
+	struct gfs2_holder **pph = tmp;
 	int error = 0;
 
-	if (!num_gh)
+	switch(num_gh) {
+	case 0:
 		return 0;
-
-	if (num_gh == 1) {
+	case 1:
 		ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
 		return gfs2_glock_nq(ghs);
-	}
-
-	e = kcalloc(num_gh, sizeof(struct gfs2_holder *), GFP_KERNEL);
-	if (!e)
-		return -ENOMEM;
-
-	for (x = 0; x < num_gh; x++) {
-		ghs[x].gh_flags |= LM_FLAG_TRY | GL_ASYNC;
-		error = gfs2_glock_nq(&ghs[x]);
-		if (error) {
-			borked = 1;
-			serious = error;
-			num_gh = x;
+	default:
+		if (num_gh <= 4)
 			break;
-		}
+		pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS);
+		if (!pph)
+			return -ENOMEM;
 	}
 
-	for (x = 0; x < num_gh; x++) {
-		error = e[x] = glock_wait_internal(&ghs[x]);
-		if (error) {
-			borked = 1;
-			if (error != GLR_TRYFAILED && error != GLR_CANCELED)
-				serious = error;
-		}
-	}
+	error = nq_m_sync(num_gh, ghs, pph);
 
-	if (!borked) {
-		kfree(e);
-		return 0;
-	}
-
-	for (x = 0; x < num_gh; x++)
-		if (!e[x])
-			gfs2_glock_dq(&ghs[x]);
-
-	if (serious)
-		error = serious;
-	else {
-		for (x = 0; x < num_gh; x++)
-			gfs2_holder_reinit(ghs[x].gh_state, ghs[x].gh_flags,
-					  &ghs[x]);
-		error = nq_m_sync(num_gh, ghs, (struct gfs2_holder **)e);
-	}
-
-	kfree(e);
+	if (pph != tmp)
+		kfree(pph);
 
 	return error;
 }
@@ -1456,7 +1448,7 @@
 	if (!gl)
 		return;
 
-	handle_callback(gl, state);
+	handle_callback(gl, state, 1);
 
 	spin_lock(&gl->gl_spin);
 	run_queue(gl);
@@ -1596,7 +1588,7 @@
 	if (gfs2_glmutex_trylock(gl)) {
 		if (list_empty(&gl->gl_holders) &&
 		    gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl))
-			handle_callback(gl, LM_ST_UNLOCKED);
+			handle_callback(gl, LM_ST_UNLOCKED, 0);
 		gfs2_glmutex_unlock(gl);
 	}
 
@@ -1709,7 +1701,7 @@
 	if (gfs2_glmutex_trylock(gl)) {
 		if (list_empty(&gl->gl_holders) &&
 		    gl->gl_state != LM_ST_UNLOCKED)
-			handle_callback(gl, LM_ST_UNLOCKED);
+			handle_callback(gl, LM_ST_UNLOCKED, 0);
 		gfs2_glmutex_unlock(gl);
 	}
 }
@@ -1823,7 +1815,8 @@
 
 	print_dbg(gi, "  Inode:\n");
 	print_dbg(gi, "    num = %llu/%llu\n",
-		    ip->i_num.no_formal_ino, ip->i_num.no_addr);
+		  (unsigned long long)ip->i_no_formal_ino,
+		  (unsigned long long)ip->i_no_addr);
 	print_dbg(gi, "    type = %u\n", IF2DT(ip->i_inode.i_mode));
 	print_dbg(gi, "    i_flags =");
 	for (x = 0; x < 32; x++)
@@ -1909,8 +1902,8 @@
 	}
 	if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
 		print_dbg(gi, "  Demotion req to state %u (%llu uS ago)\n",
-			  gl->gl_demote_state,
-			  (u64)(jiffies - gl->gl_demote_time)*(1000000/HZ));
+			  gl->gl_demote_state, (unsigned long long)
+			  (jiffies - gl->gl_demote_time)*(1000000/HZ));
 	}
 	if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) {
 		if (!test_bit(GLF_LOCK, &gl->gl_flags) &&
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 11477ca..7721ca3 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -10,6 +10,7 @@
 #ifndef __GLOCK_DOT_H__
 #define __GLOCK_DOT_H__
 
+#include <linux/sched.h>
 #include "incore.h"
 
 /* Flags for lock requests; used in gfs2_holder gh_flag field.
@@ -86,6 +87,7 @@
 int gfs2_glock_poll(struct gfs2_holder *gh);
 int gfs2_glock_wait(struct gfs2_holder *gh);
 void gfs2_glock_dq(struct gfs2_holder *gh);
+void gfs2_glock_dq_wait(struct gfs2_holder *gh);
 
 void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
 int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 7b82657..777ca46 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -156,9 +156,9 @@
 		ip = NULL;
 
 	if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
-		gfs2_log_flush(gl->gl_sbd, gl);
 		if (ip)
 			filemap_fdatawrite(ip->i_inode.i_mapping);
+		gfs2_log_flush(gl->gl_sbd, gl);
 		gfs2_meta_sync(gl);
 		if (ip) {
 			struct address_space *mapping = ip->i_inode.i_mapping;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index d995441..170ba93 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -28,6 +28,14 @@
 
 typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret);
 
+struct gfs2_log_header_host {
+	u64 lh_sequence;	/* Sequence number of this transaction */
+	u32 lh_flags;		/* GFS2_LOG_HEAD_... */
+	u32 lh_tail;		/* Block number of log tail */
+	u32 lh_blkno;
+	u32 lh_hash;
+};
+
 /*
  * Structure of operations that are associated with each
  * type of element in the log.
@@ -60,12 +68,23 @@
 	u32 bi_len;
 };
 
+struct gfs2_rgrp_host {
+	u32 rg_flags;
+	u32 rg_free;
+	u32 rg_dinodes;
+	u64 rg_igeneration;
+};
+
 struct gfs2_rgrpd {
 	struct list_head rd_list;	/* Link with superblock */
 	struct list_head rd_list_mru;
 	struct list_head rd_recent;	/* Recently used rgrps */
 	struct gfs2_glock *rd_gl;	/* Glock for this rgrp */
-	struct gfs2_rindex_host rd_ri;
+	u64 rd_addr;			/* grp block disk address */
+	u64 rd_data0;			/* first data location */
+	u32 rd_length;			/* length of rgrp header in fs blocks */
+	u32 rd_data;			/* num of data blocks in rgrp */
+	u32 rd_bitbytes;		/* number of bytes in data bitmaps */
 	struct gfs2_rgrp_host rd_rg;
 	u64 rd_rg_vn;
 	struct gfs2_bitmap *rd_bits;
@@ -76,6 +95,8 @@
 	u32 rd_last_alloc_data;
 	u32 rd_last_alloc_meta;
 	struct gfs2_sbd *rd_sbd;
+	unsigned long rd_flags;
+#define GFS2_RDF_CHECK        0x0001          /* Need to check for unlinked inodes */
 };
 
 enum gfs2_state_bits {
@@ -211,10 +232,24 @@
 	GIF_SW_PAGED		= 3,
 };
 
+struct gfs2_dinode_host {
+	u64 di_size;		/* number of bytes in file */
+	u64 di_blocks;		/* number of blocks in file */
+	u64 di_goal_meta;	/* rgrp to alloc from next */
+	u64 di_goal_data;	/* data block goal */
+	u64 di_generation;	/* generation number for NFS */
+	u32 di_flags;		/* GFS2_DIF_... */
+	u16 di_height;		/* height of metadata */
+	/* These only apply to directories  */
+	u16 di_depth;		/* Number of bits in the table */
+	u32 di_entries;		/* The number of entries in the directory */
+	u64 di_eattr;		/* extended attribute block number */
+};
+
 struct gfs2_inode {
 	struct inode i_inode;
-	struct gfs2_inum_host i_num;
-
+	u64 i_no_addr;
+	u64 i_no_formal_ino;
 	unsigned long i_flags;		/* GIF_... */
 
 	struct gfs2_dinode_host i_di; /* To be replaced by ref to block */
@@ -275,14 +310,6 @@
 	QDF_LOCKED		= 2,
 };
 
-struct gfs2_quota_lvb {
-        __be32 qb_magic;
-        u32 __pad;
-        __be64 qb_limit;      /* Hard limit of # blocks to alloc */
-        __be64 qb_warn;       /* Warn user when alloc is above this # */
-        __be64 qb_value;       /* Current # blocks allocated */
-};
-
 struct gfs2_quota_data {
 	struct list_head qd_list;
 	unsigned int qd_count;
@@ -327,7 +354,9 @@
 
 	unsigned int tr_num_buf;
 	unsigned int tr_num_buf_new;
+	unsigned int tr_num_databuf_new;
 	unsigned int tr_num_buf_rm;
+	unsigned int tr_num_databuf_rm;
 	struct list_head tr_list_buf;
 
 	unsigned int tr_num_revoke;
@@ -354,6 +383,12 @@
 	unsigned int jd_blocks;
 };
 
+struct gfs2_statfs_change_host {
+	s64 sc_total;
+	s64 sc_free;
+	s64 sc_dinodes;
+};
+
 #define GFS2_GLOCKD_DEFAULT	1
 #define GFS2_GLOCKD_MAX		16
 
@@ -426,6 +461,28 @@
 
 #define GFS2_FSNAME_LEN		256
 
+struct gfs2_inum_host {
+	u64 no_formal_ino;
+	u64 no_addr;
+};
+
+struct gfs2_sb_host {
+	u32 sb_magic;
+	u32 sb_type;
+	u32 sb_format;
+
+	u32 sb_fs_format;
+	u32 sb_multihost_format;
+	u32 sb_bsize;
+	u32 sb_bsize_shift;
+
+	struct gfs2_inum_host sb_master_dir;
+	struct gfs2_inum_host sb_root_dir;
+
+	char sb_lockproto[GFS2_LOCKNAME_LEN];
+	char sb_locktable[GFS2_LOCKNAME_LEN];
+};
+
 struct gfs2_sbd {
 	struct super_block *sd_vfs;
 	struct super_block *sd_vfs_meta;
@@ -544,6 +601,7 @@
 
 	unsigned int sd_log_blks_reserved;
 	unsigned int sd_log_commited_buf;
+	unsigned int sd_log_commited_databuf;
 	unsigned int sd_log_commited_revoke;
 
 	unsigned int sd_log_num_gl;
@@ -552,7 +610,6 @@
 	unsigned int sd_log_num_rg;
 	unsigned int sd_log_num_databuf;
 	unsigned int sd_log_num_jdata;
-	unsigned int sd_log_num_hdrs;
 
 	struct list_head sd_log_le_gl;
 	struct list_head sd_log_le_buf;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index df0b8b3..34f7bcd 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -38,12 +38,17 @@
 #include "trans.h"
 #include "util.h"
 
+struct gfs2_inum_range_host {
+	u64 ir_start;
+	u64 ir_length;
+};
+
 static int iget_test(struct inode *inode, void *opaque)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
-	struct gfs2_inum_host *inum = opaque;
+	u64 *no_addr = opaque;
 
-	if (ip->i_num.no_addr == inum->no_addr &&
+	if (ip->i_no_addr == *no_addr &&
 	    inode->i_private != NULL)
 		return 1;
 
@@ -53,37 +58,70 @@
 static int iget_set(struct inode *inode, void *opaque)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
-	struct gfs2_inum_host *inum = opaque;
+	u64 *no_addr = opaque;
 
-	ip->i_num = *inum;
-	inode->i_ino = inum->no_addr;
+	inode->i_ino = (unsigned long)*no_addr;
+	ip->i_no_addr = *no_addr;
 	return 0;
 }
 
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum)
+struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr)
 {
-	return ilookup5(sb, (unsigned long)inum->no_addr,
-			iget_test, inum);
+	unsigned long hash = (unsigned long)no_addr;
+	return ilookup5(sb, hash, iget_test, &no_addr);
 }
 
-static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum)
+static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
 {
-	return iget5_locked(sb, (unsigned long)inum->no_addr,
-		     iget_test, iget_set, inum);
+	unsigned long hash = (unsigned long)no_addr;
+	return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
+}
+
+/**
+ * GFS2 lookup code fills in vfs inode contents based on info obtained
+ * from directory entry inside gfs2_inode_lookup(). This has caused issues
+ * with NFS code path since its get_dentry routine doesn't have the relevant
+ * directory entry when gfs2_inode_lookup() is invoked. Part of the code
+ * segment inside gfs2_inode_lookup code needs to get moved around.
+ *
+ * Clean up I_LOCK and I_NEW as well.
+ **/
+
+void gfs2_set_iop(struct inode *inode)
+{
+	umode_t mode = inode->i_mode;
+
+	if (S_ISREG(mode)) {
+		inode->i_op = &gfs2_file_iops;
+		inode->i_fop = &gfs2_file_fops;
+		inode->i_mapping->a_ops = &gfs2_file_aops;
+	} else if (S_ISDIR(mode)) {
+		inode->i_op = &gfs2_dir_iops;
+		inode->i_fop = &gfs2_dir_fops;
+	} else if (S_ISLNK(mode)) {
+		inode->i_op = &gfs2_symlink_iops;
+	} else {
+		inode->i_op = &gfs2_dev_iops;
+	}
+
+	unlock_new_inode(inode);
 }
 
 /**
  * gfs2_inode_lookup - Lookup an inode
  * @sb: The super block
- * @inum: The inode number
+ * @no_addr: The inode number
  * @type: The type of the inode
  *
  * Returns: A VFS inode, or an error
  */
 
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type)
+struct inode *gfs2_inode_lookup(struct super_block *sb, 
+				unsigned int type,
+				u64 no_addr,
+				u64 no_formal_ino)
 {
-	struct inode *inode = gfs2_iget(sb, inum);
+	struct inode *inode = gfs2_iget(sb, no_addr);
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_glock *io_gl;
 	int error;
@@ -93,29 +131,15 @@
 
 	if (inode->i_state & I_NEW) {
 		struct gfs2_sbd *sdp = GFS2_SB(inode);
-		umode_t mode = DT2IF(type);
 		inode->i_private = ip;
-		inode->i_mode = mode;
+		ip->i_no_formal_ino = no_formal_ino;
 
-		if (S_ISREG(mode)) {
-			inode->i_op = &gfs2_file_iops;
-			inode->i_fop = &gfs2_file_fops;
-			inode->i_mapping->a_ops = &gfs2_file_aops;
-		} else if (S_ISDIR(mode)) {
-			inode->i_op = &gfs2_dir_iops;
-			inode->i_fop = &gfs2_dir_fops;
-		} else if (S_ISLNK(mode)) {
-			inode->i_op = &gfs2_symlink_iops;
-		} else {
-			inode->i_op = &gfs2_dev_iops;
-		}
-
-		error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
+		error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
 		if (unlikely(error))
 			goto fail;
 		ip->i_gl->gl_object = ip;
 
-		error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
+		error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
 		if (unlikely(error))
 			goto fail_put;
 
@@ -123,12 +147,38 @@
 		error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
 		if (unlikely(error))
 			goto fail_iopen;
+		ip->i_iopen_gh.gh_gl->gl_object = ip;
 
 		gfs2_glock_put(io_gl);
-		unlock_new_inode(inode);
+
+		if ((type == DT_UNKNOWN) && (no_formal_ino == 0))
+			goto gfs2_nfsbypass;
+
+		inode->i_mode = DT2IF(type);
+
+		/*
+		 * We must read the inode in order to work out its type in
+		 * this case. Note that this doesn't happen often as we normally
+		 * know the type beforehand. This code path only occurs during
+		 * unlinked inode recovery (where it is safe to do this glock,
+		 * which is not true in the general case).
+		 */
+		if (type == DT_UNKNOWN) {
+			struct gfs2_holder gh;
+			error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+			if (unlikely(error))
+				goto fail_glock;
+			/* Inode is now uptodate */
+			gfs2_glock_dq_uninit(&gh);
+		}
+
+		gfs2_set_iop(inode);
 	}
 
+gfs2_nfsbypass:
 	return inode;
+fail_glock:
+	gfs2_glock_dq(&ip->i_iopen_gh);
 fail_iopen:
 	gfs2_glock_put(io_gl);
 fail_put:
@@ -144,14 +194,12 @@
 	struct gfs2_dinode_host *di = &ip->i_di;
 	const struct gfs2_dinode *str = buf;
 
-	if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) {
+	if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) {
 		if (gfs2_consist_inode(ip))
 			gfs2_dinode_print(ip);
 		return -EIO;
 	}
-	if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino))
-		return -ESTALE;
-
+	ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
 	ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
 	ip->i_inode.i_rdev = 0;
 	switch (ip->i_inode.i_mode & S_IFMT) {
@@ -175,11 +223,11 @@
 	di->di_blocks = be64_to_cpu(str->di_blocks);
 	gfs2_set_inode_blocks(&ip->i_inode);
 	ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
-	ip->i_inode.i_atime.tv_nsec = 0;
+	ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
 	ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
-	ip->i_inode.i_mtime.tv_nsec = 0;
+	ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
 	ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
-	ip->i_inode.i_ctime.tv_nsec = 0;
+	ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
 
 	di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
 	di->di_goal_data = be64_to_cpu(str->di_goal_data);
@@ -247,7 +295,7 @@
 	if (error)
 		goto out_qs;
 
-	rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
 	if (!rgd) {
 		gfs2_consist_inode(ip);
 		error = -EIO;
@@ -314,7 +362,7 @@
 	else
 		drop_nlink(&ip->i_inode);
 
-	ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_ctime = CURRENT_TIME;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
@@ -366,9 +414,7 @@
 	struct super_block *sb = dir->i_sb;
 	struct gfs2_inode *dip = GFS2_I(dir);
 	struct gfs2_holder d_gh;
-	struct gfs2_inum_host inum;
-	unsigned int type;
-	int error;
+	int error = 0;
 	struct inode *inode = NULL;
 	int unlock = 0;
 
@@ -395,12 +441,9 @@
 			goto out;
 	}
 
-	error = gfs2_dir_search(dir, name, &inum, &type);
-	if (error)
-		goto out;
-
-	inode = gfs2_inode_lookup(sb, &inum, type);
-
+	inode = gfs2_dir_search(dir, name);
+	if (IS_ERR(inode))
+		error = PTR_ERR(inode);
 out:
 	if (unlock)
 		gfs2_glock_dq_uninit(&d_gh);
@@ -409,6 +452,22 @@
 	return inode ? inode : ERR_PTR(error);
 }
 
+static void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
+{
+	const struct gfs2_inum_range *str = buf;
+
+	ir->ir_start = be64_to_cpu(str->ir_start);
+	ir->ir_length = be64_to_cpu(str->ir_length);
+}
+
+static void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
+{
+	struct gfs2_inum_range *str = buf;
+
+	str->ir_start = cpu_to_be64(ir->ir_start);
+	str->ir_length = cpu_to_be64(ir->ir_length);
+}
+
 static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino)
 {
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);
@@ -548,7 +607,7 @@
 	if (!dip->i_inode.i_nlink)
 		return -EPERM;
 
-	error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL);
+	error = gfs2_dir_check(&dip->i_inode, name, NULL);
 	switch (error) {
 	case -ENOENT:
 		error = 0;
@@ -588,8 +647,7 @@
 		*gid = current->fsgid;
 }
 
-static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum,
-			u64 *generation)
+static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	int error;
@@ -605,7 +663,7 @@
 	if (error)
 		goto out_ipreserv;
 
-	inum->no_addr = gfs2_alloc_di(dip, generation);
+	*no_addr = gfs2_alloc_di(dip, generation);
 
 	gfs2_trans_end(sdp);
 
@@ -635,6 +693,7 @@
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	struct gfs2_dinode *di;
 	struct buffer_head *dibh;
+	struct timespec tv = CURRENT_TIME;
 
 	dibh = gfs2_meta_new(gl, inum->no_addr);
 	gfs2_trans_add_bh(gl, dibh, 1);
@@ -650,7 +709,7 @@
 	di->di_nlink = 0;
 	di->di_size = 0;
 	di->di_blocks = cpu_to_be64(1);
-	di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds());
+	di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
 	di->di_major = cpu_to_be32(MAJOR(dev));
 	di->di_minor = cpu_to_be32(MINOR(dev));
 	di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
@@ -680,6 +739,9 @@
 	di->di_entries = 0;
 	memset(&di->__pad4, 0, sizeof(di->__pad4));
 	di->di_eattr = 0;
+	di->di_atime_nsec = cpu_to_be32(tv.tv_nsec);
+	di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
+	di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
 	memset(&di->di_reserved, 0, sizeof(di->di_reserved));
 
 	brelse(dibh);
@@ -749,7 +811,7 @@
 			goto fail_quota_locks;
 
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-					 al->al_rgd->rd_ri.ri_length +
+					 al->al_rgd->rd_length +
 					 2 * RES_DINODE +
 					 RES_STATFS + RES_QUOTA, 0);
 		if (error)
@@ -760,7 +822,7 @@
 			goto fail_quota_locks;
 	}
 
-	error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode));
+	error = gfs2_dir_add(&dip->i_inode, name, ip, IF2DT(ip->i_inode.i_mode));
 	if (error)
 		goto fail_end_trans;
 
@@ -840,11 +902,11 @@
 struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
 			   unsigned int mode, dev_t dev)
 {
-	struct inode *inode;
+	struct inode *inode = NULL;
 	struct gfs2_inode *dip = ghs->gh_gl->gl_object;
 	struct inode *dir = &dip->i_inode;
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-	struct gfs2_inum_host inum;
+	struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
 	int error;
 	u64 generation;
 
@@ -864,7 +926,7 @@
 	if (error)
 		goto fail_gunlock;
 
-	error = alloc_dinode(dip, &inum, &generation);
+	error = alloc_dinode(dip, &inum.no_addr, &generation);
 	if (error)
 		goto fail_gunlock;
 
@@ -877,34 +939,36 @@
 	if (error)
 		goto fail_gunlock2;
 
-	inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode));
+	inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode),
+					inum.no_addr,
+					inum.no_formal_ino);
 	if (IS_ERR(inode))
 		goto fail_gunlock2;
 
 	error = gfs2_inode_refresh(GFS2_I(inode));
 	if (error)
-		goto fail_iput;
+		goto fail_gunlock2;
 
 	error = gfs2_acl_create(dip, GFS2_I(inode));
 	if (error)
-		goto fail_iput;
+		goto fail_gunlock2;
 
 	error = gfs2_security_init(dip, GFS2_I(inode));
 	if (error)
-		goto fail_iput;
+		goto fail_gunlock2;
 
 	error = link_dinode(dip, name, GFS2_I(inode));
 	if (error)
-		goto fail_iput;
+		goto fail_gunlock2;
 
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 	return inode;
 
-fail_iput:
-	iput(inode);
 fail_gunlock2:
 	gfs2_glock_dq_uninit(ghs + 1);
+	if (inode)
+		iput(inode);
 fail_gunlock:
 	gfs2_glock_dq(ghs);
 fail:
@@ -976,10 +1040,8 @@
  */
 
 int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
-		   struct gfs2_inode *ip)
+		   const struct gfs2_inode *ip)
 {
-	struct gfs2_inum_host inum;
-	unsigned int type;
 	int error;
 
 	if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
@@ -997,18 +1059,10 @@
 	if (error)
 		return error;
 
-	error = gfs2_dir_search(&dip->i_inode, name, &inum, &type);
+	error = gfs2_dir_check(&dip->i_inode, name, ip);
 	if (error)
 		return error;
 
-	if (!gfs2_inum_equal(&inum, &ip->i_num))
-		return -ENOENT;
-
-	if (IF2DT(ip->i_inode.i_mode) != type) {
-		gfs2_consist_inode(dip);
-		return -EIO;
-	}
-
 	return 0;
 }
 
@@ -1132,10 +1186,11 @@
 	struct gfs2_glock *gl = gh->gh_gl;
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct gfs2_inode *ip = gl->gl_object;
-	s64 curtime, quantum = gfs2_tune_get(sdp, gt_atime_quantum);
+	s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
 	unsigned int state;
 	int flags;
 	int error;
+	struct timespec tv = CURRENT_TIME;
 
 	if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
 	    gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
@@ -1153,8 +1208,7 @@
 	    (sdp->sd_vfs->s_flags & MS_RDONLY))
 		return 0;
 
-	curtime = get_seconds();
-	if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+	if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
 		gfs2_glock_dq(gh);
 		gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
 				   gh);
@@ -1165,8 +1219,8 @@
 		/* Verify that atime hasn't been updated while we were
 		   trying to get exclusive lock. */
 
-		curtime = get_seconds();
-		if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+		tv = CURRENT_TIME;
+		if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
 			struct buffer_head *dibh;
 			struct gfs2_dinode *di;
 
@@ -1180,11 +1234,12 @@
 			if (error)
 				goto fail_end_trans;
 
-			ip->i_inode.i_atime.tv_sec = curtime;
+			ip->i_inode.i_atime = tv;
 
 			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 			di = (struct gfs2_dinode *)dibh->b_data;
 			di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+			di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
 			brelse(dibh);
 
 			gfs2_trans_end(sdp);
@@ -1252,3 +1307,66 @@
 	return error;
 }
 
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
+{
+	const struct gfs2_dinode_host *di = &ip->i_di;
+	struct gfs2_dinode *str = buf;
+
+	str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
+	str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
+	str->di_header.__pad0 = 0;
+	str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
+	str->di_header.__pad1 = 0;
+	str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
+	str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+	str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
+	str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
+	str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+	str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
+	str->di_size = cpu_to_be64(di->di_size);
+	str->di_blocks = cpu_to_be64(di->di_blocks);
+	str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+	str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
+	str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
+
+	str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
+	str->di_goal_data = cpu_to_be64(di->di_goal_data);
+	str->di_generation = cpu_to_be64(di->di_generation);
+
+	str->di_flags = cpu_to_be32(di->di_flags);
+	str->di_height = cpu_to_be16(di->di_height);
+	str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
+					     !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
+					     GFS2_FORMAT_DE : 0);
+	str->di_depth = cpu_to_be16(di->di_depth);
+	str->di_entries = cpu_to_be32(di->di_entries);
+
+	str->di_eattr = cpu_to_be64(di->di_eattr);
+	str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
+	str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec);
+	str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec);
+}
+
+void gfs2_dinode_print(const struct gfs2_inode *ip)
+{
+	const struct gfs2_dinode_host *di = &ip->i_di;
+
+	printk(KERN_INFO "  no_formal_ino = %llu\n",
+	       (unsigned long long)ip->i_no_formal_ino);
+	printk(KERN_INFO "  no_addr = %llu\n",
+	       (unsigned long long)ip->i_no_addr);
+	printk(KERN_INFO "  di_size = %llu\n", (unsigned long long)di->di_size);
+	printk(KERN_INFO "  di_blocks = %llu\n",
+	       (unsigned long long)di->di_blocks);
+	printk(KERN_INFO "  di_goal_meta = %llu\n",
+	       (unsigned long long)di->di_goal_meta);
+	printk(KERN_INFO "  di_goal_data = %llu\n",
+	       (unsigned long long)di->di_goal_data);
+	printk(KERN_INFO "  di_flags = 0x%.8X\n", di->di_flags);
+	printk(KERN_INFO "  di_height = %u\n", di->di_height);
+	printk(KERN_INFO "  di_depth = %u\n", di->di_depth);
+	printk(KERN_INFO "  di_entries = %u\n", di->di_entries);
+	printk(KERN_INFO "  di_eattr = %llu\n",
+	       (unsigned long long)di->di_eattr);
+}
+
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index b57f448..4517ac8 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -10,17 +10,17 @@
 #ifndef __INODE_DOT_H__
 #define __INODE_DOT_H__
 
-static inline int gfs2_is_stuffed(struct gfs2_inode *ip)
+static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
 {
 	return !ip->i_di.di_height;
 }
 
-static inline int gfs2_is_jdata(struct gfs2_inode *ip)
+static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
 {
 	return ip->i_di.di_flags & GFS2_DIF_JDATA;
 }
 
-static inline int gfs2_is_dir(struct gfs2_inode *ip)
+static inline int gfs2_is_dir(const struct gfs2_inode *ip)
 {
 	return S_ISDIR(ip->i_inode.i_mode);
 }
@@ -32,9 +32,25 @@
 		(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
 }
 
+static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr,
+				  u64 no_formal_ino)
+{
+	return ip->i_no_addr == no_addr && ip->i_no_formal_ino == no_formal_ino;
+}
+
+static inline void gfs2_inum_out(const struct gfs2_inode *ip,
+				 struct gfs2_dirent *dent)
+{
+	dent->de_inum.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+	dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr);
+}
+
+
 void gfs2_inode_attr_in(struct gfs2_inode *ip);
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type);
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum);
+void gfs2_set_iop(struct inode *inode);
+struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
+				u64 no_addr, u64 no_formal_ino);
+struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
 
 int gfs2_inode_refresh(struct gfs2_inode *ip);
 
@@ -47,12 +63,14 @@
 int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
 		struct gfs2_inode *ip);
 int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
-		   struct gfs2_inode *ip);
+		   const struct gfs2_inode *ip);
 int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to);
 int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
 int gfs2_glock_nq_atime(struct gfs2_holder *gh);
 int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
 struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
+void gfs2_dinode_print(const struct gfs2_inode *ip);
 
 #endif /* __INODE_DOT_H__ */
 
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c
index c305255..542a797 100644
--- a/fs/gfs2/locking/dlm/lock.c
+++ b/fs/gfs2/locking/dlm/lock.c
@@ -174,7 +174,6 @@
 	lp->cur = DLM_LOCK_IV;
 	lp->lvb = NULL;
 	lp->hold_null = NULL;
-	init_completion(&lp->ast_wait);
 	INIT_LIST_HEAD(&lp->clist);
 	INIT_LIST_HEAD(&lp->blist);
 	INIT_LIST_HEAD(&lp->delay_list);
@@ -399,6 +398,12 @@
 	lp->lksb.sb_lvbptr = NULL;
 }
 
+static int gdlm_ast_wait(void *word)
+{
+	schedule();
+	return 0;
+}
+
 /* This can do a synchronous dlm request (requiring a lock_dlm thread to get
    the completion) because gfs won't call hold_lvb() during a callback (from
    the context of a lock_dlm thread). */
@@ -424,10 +429,10 @@
 	lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE;
 	set_bit(LFL_NOBAST, &lpn->flags);
 	set_bit(LFL_INLOCK, &lpn->flags);
+	set_bit(LFL_AST_WAIT, &lpn->flags);
 
-	init_completion(&lpn->ast_wait);
 	gdlm_do_lock(lpn);
-	wait_for_completion(&lpn->ast_wait);
+	wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE);
 	error = lpn->lksb.sb_status;
 	if (error) {
 		printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n",
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h
index d074c6e..24d70f7 100644
--- a/fs/gfs2/locking/dlm/lock_dlm.h
+++ b/fs/gfs2/locking/dlm/lock_dlm.h
@@ -101,6 +101,7 @@
 	LFL_NOBAST		= 10,
 	LFL_HEADQUE		= 11,
 	LFL_UNLOCK_DELETE	= 12,
+	LFL_AST_WAIT		= 13,
 };
 
 struct gdlm_lock {
@@ -117,7 +118,6 @@
 	unsigned long		flags;		/* lock_dlm flags LFL_ */
 
 	int			bast_mode;	/* protected by async_lock */
-	struct completion	ast_wait;
 
 	struct list_head	clist;		/* complete */
 	struct list_head	blist;		/* blocking */
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
index 1d8faa3..41c5b04 100644
--- a/fs/gfs2/locking/dlm/mount.c
+++ b/fs/gfs2/locking/dlm/mount.c
@@ -147,7 +147,7 @@
 
 	error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
 				  &ls->dlm_lockspace,
-				  nodir ? DLM_LSFL_NODIR : 0,
+				  DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
 				  GDLM_LVB_SIZE);
 	if (error) {
 		log_error("dlm_new_lockspace error %d", error);
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
index f82495e..fba1f1d 100644
--- a/fs/gfs2/locking/dlm/plock.c
+++ b/fs/gfs2/locking/dlm/plock.c
@@ -242,7 +242,7 @@
 	op->info.number		= name->ln_number;
 	op->info.start		= fl->fl_start;
 	op->info.end		= fl->fl_end;
-
+	op->info.owner		= (__u64)(long) fl->fl_owner;
 
 	send_op(op);
 	wait_event(recv_wq, (op->done != 0));
@@ -254,16 +254,20 @@
 	}
 	spin_unlock(&ops_lock);
 
+	/* info.rv from userspace is 1 for conflict, 0 for no-conflict,
+	   -ENOENT if there are no locks on the file */
+
 	rv = op->info.rv;
 
 	fl->fl_type = F_UNLCK;
 	if (rv == -ENOENT)
 		rv = 0;
-	else if (rv == 0 && op->info.pid != fl->fl_pid) {
+	else if (rv > 0) {
 		fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
 		fl->fl_pid = op->info.pid;
 		fl->fl_start = op->info.start;
 		fl->fl_end = op->info.end;
+		rv = 0;
 	}
 
 	kfree(op);
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
index 9cf1f16..1aca51e 100644
--- a/fs/gfs2/locking/dlm/thread.c
+++ b/fs/gfs2/locking/dlm/thread.c
@@ -44,6 +44,13 @@
 	ls->fscb(ls->sdp, cb, &lp->lockname);
 }
 
+static void wake_up_ast(struct gdlm_lock *lp)
+{
+	clear_bit(LFL_AST_WAIT, &lp->flags);
+	smp_mb__after_clear_bit();
+	wake_up_bit(&lp->flags, LFL_AST_WAIT);
+}
+
 static void process_complete(struct gdlm_lock *lp)
 {
 	struct gdlm_ls *ls = lp->ls;
@@ -136,7 +143,7 @@
 	 */
 
 	if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) {
-		complete(&lp->ast_wait);
+		wake_up_ast(lp);
 		return;
 	}
 
@@ -214,7 +221,7 @@
 	if (test_bit(LFL_INLOCK, &lp->flags)) {
 		clear_bit(LFL_NOBLOCK, &lp->flags);
 		lp->cur = lp->req;
-		complete(&lp->ast_wait);
+		wake_up_ast(lp);
 		return;
 	}
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 291415d..f49a12e 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -83,6 +83,11 @@
 
 			gfs2_assert(sdp, bd->bd_ail == ai);
 
+			if (!bh){
+				list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+                                continue;
+                        }
+
 			if (!buffer_busy(bh)) {
 				if (!buffer_uptodate(bh)) {
 					gfs2_log_unlock(sdp);
@@ -125,6 +130,11 @@
 					 bd_ail_st_list) {
 		bh = bd->bd_bh;
 
+		if (!bh){
+			list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+			continue;
+		}
+
 		gfs2_assert(sdp, bd->bd_ail == ai);
 
 		if (buffer_busy(bh)) {
@@ -262,8 +272,8 @@
  * @sdp: The GFS2 superblock
  * @blks: The number of blocks to reserve
  *
- * Note that we never give out the last 6 blocks of the journal. Thats
- * due to the fact that there is are a small number of header blocks
+ * Note that we never give out the last few blocks of the journal. Thats
+ * due to the fact that there is a small number of header blocks
  * associated with each log flush. The exact number can't be known until
  * flush time, so we ensure that we have just enough free blocks at all
  * times to avoid running out during a log flush.
@@ -274,6 +284,7 @@
 int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
 {
 	unsigned int try = 0;
+	unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize);
 
 	if (gfs2_assert_warn(sdp, blks) ||
 	    gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks))
@@ -281,7 +292,7 @@
 
 	mutex_lock(&sdp->sd_log_reserve_mutex);
 	gfs2_log_lock(sdp);
-	while(sdp->sd_log_blks_free <= (blks + 6)) {
+	while(sdp->sd_log_blks_free <= (blks + reserved_blks)) {
 		gfs2_log_unlock(sdp);
 		gfs2_ail1_empty(sdp, 0);
 		gfs2_log_flush(sdp, NULL);
@@ -357,6 +368,58 @@
 	return dist;
 }
 
+/**
+ * calc_reserved - Calculate the number of blocks to reserve when
+ *                 refunding a transaction's unused buffers.
+ * @sdp: The GFS2 superblock
+ *
+ * This is complex.  We need to reserve room for all our currently used
+ * metadata buffers (e.g. normal file I/O rewriting file time stamps) and 
+ * all our journaled data buffers for journaled files (e.g. files in the 
+ * meta_fs like rindex, or files for which chattr +j was done.)
+ * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush
+ * will count it as free space (sd_log_blks_free) and corruption will follow.
+ *
+ * We can have metadata bufs and jdata bufs in the same journal.  So each
+ * type gets its own log header, for which we need to reserve a block.
+ * In fact, each type has the potential for needing more than one header 
+ * in cases where we have more buffers than will fit on a journal page.
+ * Metadata journal entries take up half the space of journaled buffer entries.
+ * Thus, metadata entries have buf_limit (502) and journaled buffers have
+ * databuf_limit (251) before they cause a wrap around.
+ *
+ * Also, we need to reserve blocks for revoke journal entries and one for an
+ * overall header for the lot.
+ *
+ * Returns: the number of blocks reserved
+ */
+static unsigned int calc_reserved(struct gfs2_sbd *sdp)
+{
+	unsigned int reserved = 0;
+	unsigned int mbuf_limit, metabufhdrs_needed;
+	unsigned int dbuf_limit, databufhdrs_needed;
+	unsigned int revokes = 0;
+
+	mbuf_limit = buf_limit(sdp);
+	metabufhdrs_needed = (sdp->sd_log_commited_buf +
+			      (mbuf_limit - 1)) / mbuf_limit;
+	dbuf_limit = databuf_limit(sdp);
+	databufhdrs_needed = (sdp->sd_log_commited_databuf +
+			      (dbuf_limit - 1)) / dbuf_limit;
+
+	if (sdp->sd_log_commited_revoke)
+		revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
+					  sizeof(u64));
+
+	reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
+		sdp->sd_log_commited_databuf + databufhdrs_needed +
+		revokes;
+	/* One for the overall header */
+	if (reserved)
+		reserved++;
+	return reserved;
+}
+
 static unsigned int current_tail(struct gfs2_sbd *sdp)
 {
 	struct gfs2_ail *ai;
@@ -447,14 +510,14 @@
 	return bh;
 }
 
-static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull)
+static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
 {
 	unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
 
 	ail2_empty(sdp, new_tail);
 
 	gfs2_log_lock(sdp);
-	sdp->sd_log_blks_free += dist - (pull ? 1 : 0);
+	sdp->sd_log_blks_free += dist;
 	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
 	gfs2_log_unlock(sdp);
 
@@ -504,7 +567,7 @@
 	brelse(bh);
 
 	if (sdp->sd_log_tail != tail)
-		log_pull_tail(sdp, tail, pull);
+		log_pull_tail(sdp, tail);
 	else
 		gfs2_assert_withdraw(sdp, !pull);
 
@@ -517,6 +580,7 @@
 	struct list_head *head = &sdp->sd_log_flush_list;
 	struct gfs2_log_buf *lb;
 	struct buffer_head *bh;
+	int flushcount = 0;
 
 	while (!list_empty(head)) {
 		lb = list_entry(head->next, struct gfs2_log_buf, lb_list);
@@ -533,9 +597,20 @@
 		} else
 			brelse(bh);
 		kfree(lb);
+		flushcount++;
 	}
 
-	log_write_header(sdp, 0, 0);
+	/* If nothing was journaled, the header is unplanned and unwanted. */
+	if (flushcount) {
+		log_write_header(sdp, 0, 0);
+	} else {
+		unsigned int tail;
+		tail = current_tail(sdp);
+
+		gfs2_ail1_empty(sdp, 0);
+		if (sdp->sd_log_tail != tail)
+			log_pull_tail(sdp, tail);
+	}
 }
 
 /**
@@ -565,7 +640,10 @@
 	INIT_LIST_HEAD(&ai->ai_ail1_list);
 	INIT_LIST_HEAD(&ai->ai_ail2_list);
 
-	gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf == sdp->sd_log_commited_buf);
+	gfs2_assert_withdraw(sdp,
+			     sdp->sd_log_num_buf + sdp->sd_log_num_jdata ==
+			     sdp->sd_log_commited_buf +
+			     sdp->sd_log_commited_databuf);
 	gfs2_assert_withdraw(sdp,
 			sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
 
@@ -576,16 +654,19 @@
 	lops_before_commit(sdp);
 	if (!list_empty(&sdp->sd_log_flush_list))
 		log_flush_commit(sdp);
-	else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle)
+	else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
+		gfs2_log_lock(sdp);
+		sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */
+		gfs2_log_unlock(sdp);
 		log_write_header(sdp, 0, PULL);
+	}
 	lops_after_commit(sdp, ai);
 
 	gfs2_log_lock(sdp);
 	sdp->sd_log_head = sdp->sd_log_flush_head;
-	sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs;
 	sdp->sd_log_blks_reserved = 0;
 	sdp->sd_log_commited_buf = 0;
-	sdp->sd_log_num_hdrs = 0;
+	sdp->sd_log_commited_databuf = 0;
 	sdp->sd_log_commited_revoke = 0;
 
 	if (!list_empty(&ai->ai_ail1_list)) {
@@ -602,32 +683,26 @@
 
 static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
-	unsigned int reserved = 0;
+	unsigned int reserved;
 	unsigned int old;
 
 	gfs2_log_lock(sdp);
 
 	sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
-	gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 0);
+	sdp->sd_log_commited_databuf += tr->tr_num_databuf_new -
+		tr->tr_num_databuf_rm;
+	gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
+			     (((int)sdp->sd_log_commited_databuf) >= 0));
 	sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
 	gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
-
-	if (sdp->sd_log_commited_buf)
-		reserved += sdp->sd_log_commited_buf;
-	if (sdp->sd_log_commited_revoke)
-		reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
-					    sizeof(u64));
-	if (reserved)
-		reserved++;
-
+	reserved = calc_reserved(sdp);
 	old = sdp->sd_log_blks_free;
 	sdp->sd_log_blks_free += tr->tr_reserved -
 				 (reserved - sdp->sd_log_blks_reserved);
 
 	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
-	gfs2_assert_withdraw(sdp,
-			     sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks +
-			     sdp->sd_log_num_hdrs);
+	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
+			     sdp->sd_jdesc->jd_blocks);
 
 	sdp->sd_log_blks_reserved = reserved;
 
@@ -673,13 +748,13 @@
 	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
 	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
 	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
-	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_hdrs);
 	gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
 
 	sdp->sd_log_flush_head = sdp->sd_log_head;
 	sdp->sd_log_flush_wrapped = 0;
 
-	log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0);
+	log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
+			 (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
 
 	gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks);
 	gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index f82d84d..aff70f0 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -17,6 +17,7 @@
 
 #include "gfs2.h"
 #include "incore.h"
+#include "inode.h"
 #include "glock.h"
 #include "log.h"
 #include "lops.h"
@@ -117,15 +118,13 @@
 	struct gfs2_log_descriptor *ld;
 	struct gfs2_bufdata *bd1 = NULL, *bd2;
 	unsigned int total = sdp->sd_log_num_buf;
-	unsigned int offset = sizeof(struct gfs2_log_descriptor);
+	unsigned int offset = BUF_OFFSET;
 	unsigned int limit;
 	unsigned int num;
 	unsigned n;
 	__be64 *ptr;
 
-	offset += sizeof(__be64) - 1;
-	offset &= ~(sizeof(__be64) - 1);
-	limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
+	limit = buf_limit(sdp);
 	/* for 4k blocks, limit = 503 */
 
 	bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
@@ -134,7 +133,6 @@
 		if (total > limit)
 			num = limit;
 		bh = gfs2_log_get_buf(sdp);
-		sdp->sd_log_num_hdrs++;
 		ld = (struct gfs2_log_descriptor *)bh->b_data;
 		ptr = (__be64 *)(bh->b_data + offset);
 		ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
@@ -469,25 +467,28 @@
 	struct gfs2_inode *ip = GFS2_I(mapping->host);
 
 	gfs2_log_lock(sdp);
+	if (!list_empty(&bd->bd_list_tr)) {
+		gfs2_log_unlock(sdp);
+		return;
+	}
 	tr->tr_touched = 1;
-	if (list_empty(&bd->bd_list_tr) &&
-	    (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
+	if (gfs2_is_jdata(ip)) {
 		tr->tr_num_buf++;
 		list_add(&bd->bd_list_tr, &tr->tr_list_buf);
-		gfs2_log_unlock(sdp);
-		gfs2_pin(sdp, bd->bd_bh);
-		tr->tr_num_buf_new++;
-	} else {
-		gfs2_log_unlock(sdp);
 	}
+	gfs2_log_unlock(sdp);
+	if (!list_empty(&le->le_list))
+		return;
+
 	gfs2_trans_add_gl(bd->bd_gl);
-	gfs2_log_lock(sdp);
-	if (list_empty(&le->le_list)) {
-		if (ip->i_di.di_flags & GFS2_DIF_JDATA)
-			sdp->sd_log_num_jdata++;
-		sdp->sd_log_num_databuf++;
-		list_add(&le->le_list, &sdp->sd_log_le_databuf);
+	if (gfs2_is_jdata(ip)) {
+		sdp->sd_log_num_jdata++;
+		gfs2_pin(sdp, bd->bd_bh);
+		tr->tr_num_databuf_new++;
 	}
+	sdp->sd_log_num_databuf++;
+	gfs2_log_lock(sdp);
+	list_add(&le->le_list, &sdp->sd_log_le_databuf);
 	gfs2_log_unlock(sdp);
 }
 
@@ -520,7 +521,6 @@
 	LIST_HEAD(started);
 	struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
 	struct buffer_head *bh = NULL,*bh1 = NULL;
-	unsigned int offset = sizeof(struct gfs2_log_descriptor);
 	struct gfs2_log_descriptor *ld;
 	unsigned int limit;
 	unsigned int total_dbuf = sdp->sd_log_num_databuf;
@@ -528,9 +528,7 @@
 	unsigned int num, n;
 	__be64 *ptr = NULL;
 
-	offset += 2*sizeof(__be64) - 1;
-	offset &= ~(2*sizeof(__be64) - 1);
-	limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
+	limit = databuf_limit(sdp);
 
 	/*
 	 * Start writing ordered buffers, write journaled buffers
@@ -581,10 +579,10 @@
 				gfs2_log_unlock(sdp);
 				if (!bh) {
 					bh = gfs2_log_get_buf(sdp);
-					sdp->sd_log_num_hdrs++;
 					ld = (struct gfs2_log_descriptor *)
 					     bh->b_data;
-					ptr = (__be64 *)(bh->b_data + offset);
+					ptr = (__be64 *)(bh->b_data +
+							 DATABUF_OFFSET);
 					ld->ld_header.mh_magic =
 						cpu_to_be32(GFS2_MAGIC);
 					ld->ld_header.mh_type =
@@ -605,7 +603,7 @@
 				if (unlikely(magic != 0))
 					set_buffer_escaped(bh1);
 				gfs2_log_lock(sdp);
-				if (n++ > num)
+				if (++n >= num)
 					break;
 			} else if (!bh1) {
 				total_dbuf--;
@@ -622,6 +620,7 @@
 		}
 		gfs2_log_unlock(sdp);
 		if (bh) {
+			set_buffer_mapped(bh);
 			set_buffer_dirty(bh);
 			ll_rw_block(WRITE, 1, &bh);
 			bh = NULL;
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 965bc65..41a00df 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -13,6 +13,13 @@
 #include <linux/list.h>
 #include "incore.h"
 
+#define BUF_OFFSET \
+	((sizeof(struct gfs2_log_descriptor) + sizeof(__be64) - 1) & \
+	 ~(sizeof(__be64) - 1))
+#define DATABUF_OFFSET \
+	((sizeof(struct gfs2_log_descriptor) + (2 * sizeof(__be64) - 1)) & \
+	 ~(2 * sizeof(__be64) - 1))
+
 extern const struct gfs2_log_operations gfs2_glock_lops;
 extern const struct gfs2_log_operations gfs2_buf_lops;
 extern const struct gfs2_log_operations gfs2_revoke_lops;
@@ -21,6 +28,22 @@
 
 extern const struct gfs2_log_operations *gfs2_log_ops[];
 
+static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
+{
+	unsigned int limit;
+
+	limit = (sdp->sd_sb.sb_bsize - BUF_OFFSET) / sizeof(__be64);
+	return limit;
+}
+
+static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
+{
+	unsigned int limit;
+
+	limit = (sdp->sd_sb.sb_bsize - DATABUF_OFFSET) / (2 * sizeof(__be64));
+	return limit;
+}
+
 static inline void lops_init_le(struct gfs2_log_element *le,
 				const struct gfs2_log_operations *lops)
 {
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index e62d4f6..8da343b 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -387,12 +387,18 @@
 
 			if (test_clear_buffer_pinned(bh)) {
 				struct gfs2_trans *tr = current->journal_info;
+				struct gfs2_inode *bh_ip =
+					GFS2_I(bh->b_page->mapping->host);
+
 				gfs2_log_lock(sdp);
 				list_del_init(&bd->bd_le.le_list);
 				gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
 				sdp->sd_log_num_buf--;
 				gfs2_log_unlock(sdp);
-				tr->tr_num_buf_rm++;
+				if (bh_ip->i_inode.i_private != NULL)
+					tr->tr_num_databuf_rm++;
+				else
+					tr->tr_num_buf_rm++;
 				brelse(bh);
 			}
 			if (bd) {
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index e037425..527bf19 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -63,7 +63,7 @@
 static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
 					 struct buffer_head **bhp)
 {
-	return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp);
+	return gfs2_meta_indirect_buffer(ip, 0, ip->i_no_addr, 0, bhp);
 }
 
 struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c
index 4864659..6f006a80 100644
--- a/fs/gfs2/mount.c
+++ b/fs/gfs2/mount.c
@@ -82,20 +82,19 @@
 	char *options, *o, *v;
 	int error = 0;
 
-	if (!remount) {
-		/*  If someone preloaded options, use those instead  */
-		spin_lock(&gfs2_sys_margs_lock);
-		if (gfs2_sys_margs) {
-			data = gfs2_sys_margs;
-			gfs2_sys_margs = NULL;
-		}
-		spin_unlock(&gfs2_sys_margs_lock);
-
-		/*  Set some defaults  */
-		args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
-		args->ar_quota = GFS2_QUOTA_DEFAULT;
-		args->ar_data = GFS2_DATA_DEFAULT;
+	/*  If someone preloaded options, use those instead  */
+	spin_lock(&gfs2_sys_margs_lock);
+	if (!remount && gfs2_sys_margs) {
+		data = gfs2_sys_margs;
+		gfs2_sys_margs = NULL;
 	}
+	spin_unlock(&gfs2_sys_margs_lock);
+
+	/*  Set some defaults  */
+	memset(args, 0, sizeof(struct gfs2_args));
+	args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
+	args->ar_quota = GFS2_QUOTA_DEFAULT;
+	args->ar_data = GFS2_DATA_DEFAULT;
 
 	/* Split the options into tokens with the "," character and
 	   process them */
diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c
deleted file mode 100644
index d9ecfd2..0000000
--- a/fs/gfs2/ondisk.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs2.h"
-#include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
-#include "incore.h"
-
-#define pv(struct, member, fmt) printk(KERN_INFO "  "#member" = "fmt"\n", \
-				       struct->member);
-
-/*
- * gfs2_xxx_in - read in an xxx struct
- * first arg: the cpu-order structure
- * buf: the disk-order buffer
- *
- * gfs2_xxx_out - write out an xxx struct
- * first arg: the cpu-order structure
- * buf: the disk-order buffer
- *
- * gfs2_xxx_print - print out an xxx struct
- * first arg: the cpu-order structure
- */
-
-void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf)
-{
-	const struct gfs2_inum *str = buf;
-
-	no->no_formal_ino = be64_to_cpu(str->no_formal_ino);
-	no->no_addr = be64_to_cpu(str->no_addr);
-}
-
-void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf)
-{
-	struct gfs2_inum *str = buf;
-
-	str->no_formal_ino = cpu_to_be64(no->no_formal_ino);
-	str->no_addr = cpu_to_be64(no->no_addr);
-}
-
-static void gfs2_inum_print(const struct gfs2_inum_host *no)
-{
-	printk(KERN_INFO "  no_formal_ino = %llu\n", (unsigned long long)no->no_formal_ino);
-	printk(KERN_INFO "  no_addr = %llu\n", (unsigned long long)no->no_addr);
-}
-
-static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf)
-{
-	const struct gfs2_meta_header *str = buf;
-
-	mh->mh_magic = be32_to_cpu(str->mh_magic);
-	mh->mh_type = be32_to_cpu(str->mh_type);
-	mh->mh_format = be32_to_cpu(str->mh_format);
-}
-
-void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
-{
-	const struct gfs2_sb *str = buf;
-
-	gfs2_meta_header_in(&sb->sb_header, buf);
-
-	sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
-	sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
-	sb->sb_bsize = be32_to_cpu(str->sb_bsize);
-	sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
-
-	gfs2_inum_in(&sb->sb_master_dir, (char *)&str->sb_master_dir);
-	gfs2_inum_in(&sb->sb_root_dir, (char *)&str->sb_root_dir);
-
-	memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
-	memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
-}
-
-void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf)
-{
-	const struct gfs2_rindex *str = buf;
-
-	ri->ri_addr = be64_to_cpu(str->ri_addr);
-	ri->ri_length = be32_to_cpu(str->ri_length);
-	ri->ri_data0 = be64_to_cpu(str->ri_data0);
-	ri->ri_data = be32_to_cpu(str->ri_data);
-	ri->ri_bitbytes = be32_to_cpu(str->ri_bitbytes);
-
-}
-
-void gfs2_rindex_print(const struct gfs2_rindex_host *ri)
-{
-	printk(KERN_INFO "  ri_addr = %llu\n", (unsigned long long)ri->ri_addr);
-	pv(ri, ri_length, "%u");
-
-	printk(KERN_INFO "  ri_data0 = %llu\n", (unsigned long long)ri->ri_data0);
-	pv(ri, ri_data, "%u");
-
-	pv(ri, ri_bitbytes, "%u");
-}
-
-void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
-{
-	const struct gfs2_rgrp *str = buf;
-
-	rg->rg_flags = be32_to_cpu(str->rg_flags);
-	rg->rg_free = be32_to_cpu(str->rg_free);
-	rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
-	rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
-}
-
-void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
-{
-	struct gfs2_rgrp *str = buf;
-
-	str->rg_flags = cpu_to_be32(rg->rg_flags);
-	str->rg_free = cpu_to_be32(rg->rg_free);
-	str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
-	str->__pad = cpu_to_be32(0);
-	str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
-	memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
-}
-
-void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
-{
-	const struct gfs2_quota *str = buf;
-
-	qu->qu_limit = be64_to_cpu(str->qu_limit);
-	qu->qu_warn = be64_to_cpu(str->qu_warn);
-	qu->qu_value = be64_to_cpu(str->qu_value);
-}
-
-void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
-{
-	const struct gfs2_dinode_host *di = &ip->i_di;
-	struct gfs2_dinode *str = buf;
-
-	str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
-	str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
-	str->di_header.__pad0 = 0;
-	str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
-	str->di_header.__pad1 = 0;
-
-	gfs2_inum_out(&ip->i_num, &str->di_num);
-
-	str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
-	str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
-	str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
-	str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
-	str->di_size = cpu_to_be64(di->di_size);
-	str->di_blocks = cpu_to_be64(di->di_blocks);
-	str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
-	str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
-	str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
-
-	str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
-	str->di_goal_data = cpu_to_be64(di->di_goal_data);
-	str->di_generation = cpu_to_be64(di->di_generation);
-
-	str->di_flags = cpu_to_be32(di->di_flags);
-	str->di_height = cpu_to_be16(di->di_height);
-	str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
-					     !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
-					     GFS2_FORMAT_DE : 0);
-	str->di_depth = cpu_to_be16(di->di_depth);
-	str->di_entries = cpu_to_be32(di->di_entries);
-
-	str->di_eattr = cpu_to_be64(di->di_eattr);
-}
-
-void gfs2_dinode_print(const struct gfs2_inode *ip)
-{
-	const struct gfs2_dinode_host *di = &ip->i_di;
-
-	gfs2_inum_print(&ip->i_num);
-
-	printk(KERN_INFO "  di_size = %llu\n", (unsigned long long)di->di_size);
-	printk(KERN_INFO "  di_blocks = %llu\n", (unsigned long long)di->di_blocks);
-	printk(KERN_INFO "  di_goal_meta = %llu\n", (unsigned long long)di->di_goal_meta);
-	printk(KERN_INFO "  di_goal_data = %llu\n", (unsigned long long)di->di_goal_data);
-
-	pv(di, di_flags, "0x%.8X");
-	pv(di, di_height, "%u");
-
-	pv(di, di_depth, "%u");
-	pv(di, di_entries, "%u");
-
-	printk(KERN_INFO "  di_eattr = %llu\n", (unsigned long long)di->di_eattr);
-}
-
-void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
-{
-	const struct gfs2_log_header *str = buf;
-
-	gfs2_meta_header_in(&lh->lh_header, buf);
-	lh->lh_sequence = be64_to_cpu(str->lh_sequence);
-	lh->lh_flags = be32_to_cpu(str->lh_flags);
-	lh->lh_tail = be32_to_cpu(str->lh_tail);
-	lh->lh_blkno = be32_to_cpu(str->lh_blkno);
-	lh->lh_hash = be32_to_cpu(str->lh_hash);
-}
-
-void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
-{
-	const struct gfs2_inum_range *str = buf;
-
-	ir->ir_start = be64_to_cpu(str->ir_start);
-	ir->ir_length = be64_to_cpu(str->ir_length);
-}
-
-void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
-{
-	struct gfs2_inum_range *str = buf;
-
-	str->ir_start = cpu_to_be64(ir->ir_start);
-	str->ir_length = cpu_to_be64(ir->ir_length);
-}
-
-void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
-{
-	const struct gfs2_statfs_change *str = buf;
-
-	sc->sc_total = be64_to_cpu(str->sc_total);
-	sc->sc_free = be64_to_cpu(str->sc_free);
-	sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
-}
-
-void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
-{
-	struct gfs2_statfs_change *str = buf;
-
-	str->sc_total = cpu_to_be64(sc->sc_total);
-	str->sc_free = cpu_to_be64(sc->sc_free);
-	str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
-}
-
-void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
-{
-	const struct gfs2_quota_change *str = buf;
-
-	qc->qc_change = be64_to_cpu(str->qc_change);
-	qc->qc_flags = be32_to_cpu(str->qc_flags);
-	qc->qc_id = be32_to_cpu(str->qc_id);
-}
-
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 30c1562..26c8888 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -32,6 +32,7 @@
 #include "trans.h"
 #include "rgrp.h"
 #include "ops_file.h"
+#include "super.h"
 #include "util.h"
 #include "glops.h"
 
@@ -49,6 +50,8 @@
 		end = start + bsize;
 		if (end <= from || start >= to)
 			continue;
+		if (gfs2_is_jdata(ip))
+			set_buffer_uptodate(bh);
 		gfs2_trans_add_bh(ip->i_gl, bh, 0);
 	}
 }
@@ -134,7 +137,9 @@
 		return 0; /* don't care */
 	}
 
-	if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) {
+	if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) &&
+	    PageChecked(page)) {
+		ClearPageChecked(page);
 		error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0);
 		if (error)
 			goto out_ignore;
@@ -203,11 +208,7 @@
 	 * so we need to supply one here. It doesn't happen often.
 	 */
 	if (unlikely(page->index)) {
-		kaddr = kmap_atomic(page, KM_USER0);
-		memset(kaddr, 0, PAGE_CACHE_SIZE);
-		kunmap_atomic(kaddr, KM_USER0);
-		flush_dcache_page(page);
-		SetPageUptodate(page);
+		zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
 		return 0;
 	}
 
@@ -450,6 +451,31 @@
 }
 
 /**
+ * adjust_fs_space - Adjusts the free space available due to gfs2_grow
+ * @inode: the rindex inode
+ */
+static void adjust_fs_space(struct inode *inode)
+{
+	struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+	struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+	u64 fs_total, new_free;
+
+	/* Total up the file system space, according to the latest rindex. */
+	fs_total = gfs2_ri_total(sdp);
+
+	spin_lock(&sdp->sd_statfs_spin);
+	if (fs_total > (m_sc->sc_total + l_sc->sc_total))
+		new_free = fs_total - (m_sc->sc_total + l_sc->sc_total);
+	else
+		new_free = 0;
+	spin_unlock(&sdp->sd_statfs_spin);
+	fs_warn(sdp, "File system extended by %llu blocks.\n",
+		(unsigned long long)new_free);
+	gfs2_statfs_change(sdp, new_free, new_free, 0);
+}
+
+/**
  * gfs2_commit_write - Commit write to a file
  * @file: The file to write to
  * @page: The page containing the data
@@ -511,6 +537,9 @@
 		di->di_size = cpu_to_be64(inode->i_size);
 	}
 
+	if (inode == sdp->sd_rindex)
+		adjust_fs_space(inode);
+
 	brelse(dibh);
 	gfs2_trans_end(sdp);
 	if (al->al_requested) {
@@ -543,6 +572,23 @@
 }
 
 /**
+ * gfs2_set_page_dirty - Page dirtying function
+ * @page: The page to dirty
+ *
+ * Returns: 1 if it dirtyed the page, or 0 otherwise
+ */
+ 
+static int gfs2_set_page_dirty(struct page *page)
+{
+	struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+	struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
+
+	if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
+		SetPageChecked(page);
+	return __set_page_dirty_buffers(page);
+}
+
+/**
  * gfs2_bmap - Block map function
  * @mapping: Address space info
  * @lblock: The block to map
@@ -578,6 +624,8 @@
 	if (bd) {
 		bd->bd_bh = NULL;
 		bh->b_private = NULL;
+		if (!bd->bd_ail && list_empty(&bd->bd_le.le_list))
+			kmem_cache_free(gfs2_bufdata_cachep, bd);
 	}
 	gfs2_log_unlock(sdp);
 
@@ -598,6 +646,8 @@
 	unsigned int curr_off = 0;
 
 	BUG_ON(!PageLocked(page));
+	if (offset == 0)
+		ClearPageChecked(page);
 	if (!page_has_buffers(page))
 		return;
 
@@ -728,8 +778,8 @@
 			return;
 
 		fs_warn(sdp, "ip = %llu %llu\n",
-			(unsigned long long)ip->i_num.no_formal_ino,
-			(unsigned long long)ip->i_num.no_addr);
+			(unsigned long long)ip->i_no_formal_ino,
+			(unsigned long long)ip->i_no_addr);
 
 		for (x = 0; x < GFS2_MAX_META_HEIGHT; x++)
 			fs_warn(sdp, "ip->i_cache[%u] = %s\n",
@@ -810,6 +860,7 @@
 	.sync_page = block_sync_page,
 	.prepare_write = gfs2_prepare_write,
 	.commit_write = gfs2_commit_write,
+	.set_page_dirty = gfs2_set_page_dirty,
 	.bmap = gfs2_bmap,
 	.invalidatepage = gfs2_invalidatepage,
 	.releasepage = gfs2_releasepage,
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h
index 35aaee4..fa1b5b3 100644
--- a/fs/gfs2/ops_address.h
+++ b/fs/gfs2/ops_address.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index a6fdc52..793e334 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -21,6 +21,7 @@
 #include "glock.h"
 #include "ops_dentry.h"
 #include "util.h"
+#include "inode.h"
 
 /**
  * gfs2_drevalidate - Check directory lookup consistency
@@ -40,14 +41,15 @@
 	struct gfs2_inode *dip = GFS2_I(parent->d_inode);
 	struct inode *inode = dentry->d_inode;
 	struct gfs2_holder d_gh;
-	struct gfs2_inode *ip;
-	struct gfs2_inum_host inum;
-	unsigned int type;
+	struct gfs2_inode *ip = NULL;
 	int error;
 	int had_lock=0;
 
-	if (inode && is_bad_inode(inode))
-		goto invalid;
+	if (inode) {
+		if (is_bad_inode(inode))
+			goto invalid;
+		ip = GFS2_I(inode);
+	}
 
 	if (sdp->sd_args.ar_localcaching)
 		goto valid;
@@ -59,7 +61,7 @@
 			goto fail;
 	} 
 
-	error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type);
+	error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip);
 	switch (error) {
 	case 0:
 		if (!inode)
@@ -73,16 +75,6 @@
 		goto fail_gunlock;
 	}
 
-	ip = GFS2_I(inode);
-
-	if (!gfs2_inum_equal(&ip->i_num, &inum))
-		goto invalid_gunlock;
-
-	if (IF2DT(ip->i_inode.i_mode) != type) {
-		gfs2_consist_inode(dip);
-		goto fail_gunlock;
-	}
-
 valid_gunlock:
 	if (!had_lock)
 		gfs2_glock_dq_uninit(&d_gh);
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index aad9183..b8312ed 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -11,6 +11,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/lm_interface.h>
@@ -22,10 +23,14 @@
 #include "glops.h"
 #include "inode.h"
 #include "ops_dentry.h"
-#include "ops_export.h"
+#include "ops_fstype.h"
 #include "rgrp.h"
 #include "util.h"
 
+#define GFS2_SMALL_FH_SIZE 4
+#define GFS2_LARGE_FH_SIZE 8
+#define GFS2_OLD_FH_SIZE 10
+
 static struct dentry *gfs2_decode_fh(struct super_block *sb,
 				     __u32 *p,
 				     int fh_len,
@@ -35,31 +40,28 @@
 				     void *context)
 {
 	__be32 *fh = (__force __be32 *)p;
-	struct gfs2_fh_obj fh_obj;
-	struct gfs2_inum_host *this, parent;
+	struct gfs2_inum_host inum, parent;
 
-	this 		= &fh_obj.this;
-	fh_obj.imode 	= DT_UNKNOWN;
 	memset(&parent, 0, sizeof(struct gfs2_inum));
 
 	switch (fh_len) {
 	case GFS2_LARGE_FH_SIZE:
+	case GFS2_OLD_FH_SIZE:
 		parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
 		parent.no_formal_ino |= be32_to_cpu(fh[5]);
 		parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
 		parent.no_addr |= be32_to_cpu(fh[7]);
-		fh_obj.imode = be32_to_cpu(fh[8]);
 	case GFS2_SMALL_FH_SIZE:
-		this->no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
-		this->no_formal_ino |= be32_to_cpu(fh[1]);
-		this->no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
-		this->no_addr |= be32_to_cpu(fh[3]);
+		inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
+		inum.no_formal_ino |= be32_to_cpu(fh[1]);
+		inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
+		inum.no_addr |= be32_to_cpu(fh[3]);
 		break;
 	default:
 		return NULL;
 	}
 
-	return gfs2_export_ops.find_exported_dentry(sb, &fh_obj, &parent,
+	return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent,
 						    acceptable, context);
 }
 
@@ -75,10 +77,10 @@
 	    (connectable && *len < GFS2_LARGE_FH_SIZE))
 		return 255;
 
-	fh[0] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
-	fh[1] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
-	fh[2] = cpu_to_be32(ip->i_num.no_addr >> 32);
-	fh[3] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
+	fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
+	fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+	fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
+	fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
 	*len = GFS2_SMALL_FH_SIZE;
 
 	if (!connectable || inode == sb->s_root->d_inode)
@@ -90,13 +92,10 @@
 	igrab(inode);
 	spin_unlock(&dentry->d_lock);
 
-	fh[4] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
-	fh[5] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
-	fh[6] = cpu_to_be32(ip->i_num.no_addr >> 32);
-	fh[7] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
-
-	fh[8]  = cpu_to_be32(inode->i_mode);
-	fh[9]  = 0;	/* pad to double word */
+	fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
+	fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+	fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
+	fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
 	*len = GFS2_LARGE_FH_SIZE;
 
 	iput(inode);
@@ -144,7 +143,8 @@
 	ip = GFS2_I(inode);
 
 	*name = 0;
-	gnfd.inum = ip->i_num;
+	gnfd.inum.no_addr = ip->i_no_addr;
+	gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
 	gnfd.name = name;
 
 	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
@@ -192,8 +192,7 @@
 static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
 {
 	struct gfs2_sbd *sdp = sb->s_fs_info;
-	struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj;
-	struct gfs2_inum_host *inum = &fh_obj->this;
+	struct gfs2_inum_host *inum = inum_obj;
 	struct gfs2_holder i_gh, ri_gh, rgd_gh;
 	struct gfs2_rgrpd *rgd;
 	struct inode *inode;
@@ -202,9 +201,9 @@
 
 	/* System files? */
 
-	inode = gfs2_ilookup(sb, inum);
+	inode = gfs2_ilookup(sb, inum->no_addr);
 	if (inode) {
-		if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) {
+		if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
 			iput(inode);
 			return ERR_PTR(-ESTALE);
 		}
@@ -236,7 +235,9 @@
 	gfs2_glock_dq_uninit(&rgd_gh);
 	gfs2_glock_dq_uninit(&ri_gh);
 
-	inode = gfs2_inode_lookup(sb, inum, fh_obj->imode);
+	inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
+					inum->no_addr,
+					0);
 	if (!inode)
 		goto fail;
 	if (IS_ERR(inode)) {
@@ -250,6 +251,15 @@
 		goto fail;
 	}
 
+	/* Pick up the works we bypass in gfs2_inode_lookup */
+	if (inode->i_state & I_NEW) 
+		gfs2_set_iop(inode);
+
+	if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
+		iput(inode);
+		goto fail;
+	}
+
 	error = -EIO;
 	if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
 		iput(inode);
diff --git a/fs/gfs2/ops_export.h b/fs/gfs2/ops_export.h
deleted file mode 100644
index f925a95..0000000
--- a/fs/gfs2/ops_export.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __OPS_EXPORT_DOT_H__
-#define __OPS_EXPORT_DOT_H__
-
-#define GFS2_SMALL_FH_SIZE 4
-#define GFS2_LARGE_FH_SIZE 10
-
-extern struct export_operations gfs2_export_ops;
-struct gfs2_fh_obj {
-	struct gfs2_inum_host this;
-	__u32            imode;
-};
-
-#endif /* __OPS_EXPORT_DOT_H__ */
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 064df88..196d832 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -502,7 +502,7 @@
 	struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
 	struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
 	struct lm_lockname name =
-		{ .ln_number = ip->i_num.no_addr,
+		{ .ln_number = ip->i_no_addr,
 		  .ln_type = LM_TYPE_PLOCK };
 
 	if (!(fl->fl_flags & FL_POSIX))
@@ -557,7 +557,7 @@
 		gfs2_glock_dq_uninit(fl_gh);
 	} else {
 		error = gfs2_glock_get(GFS2_SB(&ip->i_inode),
-				      ip->i_num.no_addr, &gfs2_flock_glops,
+				      ip->i_no_addr, &gfs2_flock_glops,
 				      CREATE, &gl);
 		if (error)
 			goto out;
@@ -635,7 +635,6 @@
 	.release	= gfs2_close,
 	.fsync		= gfs2_fsync,
 	.lock		= gfs2_lock,
-	.sendfile	= generic_file_sendfile,
 	.flock		= gfs2_flock,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 2c5f8e7..cf5aa50 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -27,7 +27,6 @@
 #include "inode.h"
 #include "lm.h"
 #include "mount.h"
-#include "ops_export.h"
 #include "ops_fstype.h"
 #include "ops_super.h"
 #include "recovery.h"
@@ -105,6 +104,7 @@
 	sb->s_magic = GFS2_MAGIC;
 	sb->s_op = &gfs2_super_ops;
 	sb->s_export_op = &gfs2_export_ops;
+	sb->s_time_gran = 1;
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
 
 	if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME))
@@ -116,7 +116,6 @@
 
 static int init_names(struct gfs2_sbd *sdp, int silent)
 {
-	struct page *page;
 	char *proto, *table;
 	int error = 0;
 
@@ -126,14 +125,9 @@
 	/*  Try to autodetect  */
 
 	if (!proto[0] || !table[0]) {
-		struct gfs2_sb *sb;
-		page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
-		if (!page)
-			return -ENOBUFS;
-		sb = kmap(page);
-		gfs2_sb_in(&sdp->sd_sb, sb);
-		kunmap(page);
-		__free_page(page);
+		error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+		if (error)
+			return error;
 
 		error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
 		if (error)
@@ -151,6 +145,9 @@
 	snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto);
 	snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table);
 
+	while ((table = strchr(sdp->sd_table_name, '/')))
+		*table = '_';
+
 out:
 	return error;
 }
@@ -236,17 +233,17 @@
 	return error;
 }
 
-static struct inode *gfs2_lookup_root(struct super_block *sb,
-				      struct gfs2_inum_host *inum)
+static inline struct inode *gfs2_lookup_root(struct super_block *sb,
+					     u64 no_addr)
 {
-	return gfs2_inode_lookup(sb, inum, DT_DIR);
+	return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0);
 }
 
 static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
 {
 	struct super_block *sb = sdp->sd_vfs;
 	struct gfs2_holder sb_gh;
-	struct gfs2_inum_host *inum;
+	u64 no_addr;
 	struct inode *inode;
 	int error = 0;
 
@@ -289,10 +286,10 @@
 	sb_set_blocksize(sb, sdp->sd_sb.sb_bsize);
 
 	/* Get the root inode */
-	inum = &sdp->sd_sb.sb_root_dir;
+	no_addr = sdp->sd_sb.sb_root_dir.no_addr;
 	if (sb->s_type == &gfs2meta_fs_type)
-		inum = &sdp->sd_sb.sb_master_dir;
-	inode = gfs2_lookup_root(sb, inum);
+		no_addr = sdp->sd_sb.sb_master_dir.no_addr;
+	inode = gfs2_lookup_root(sb, no_addr);
 	if (IS_ERR(inode)) {
 		error = PTR_ERR(inode);
 		fs_err(sdp, "can't read in root inode: %d\n", error);
@@ -449,7 +446,7 @@
 	if (undo)
 		goto fail_qinode;
 
-	inode = gfs2_lookup_root(sdp->sd_vfs, &sdp->sd_sb.sb_master_dir);
+	inode = gfs2_lookup_root(sdp->sd_vfs, sdp->sd_sb.sb_master_dir.no_addr);
 	if (IS_ERR(inode)) {
 		error = PTR_ERR(inode);
 		fs_err(sdp, "can't read in master directory: %d\n", error);
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h
index 7cc2c29..407029b 100644
--- a/fs/gfs2/ops_fstype.h
+++ b/fs/gfs2/ops_fstype.h
@@ -14,5 +14,6 @@
 
 extern struct file_system_type gfs2_fs_type;
 extern struct file_system_type gfs2meta_fs_type;
+extern struct export_operations gfs2_export_ops;
 
 #endif /* __OPS_FSTYPE_DOT_H__ */
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index d85f6e0..911c115 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -157,7 +157,7 @@
 	if (error)
 		goto out_gunlock;
 
-	error = gfs2_dir_search(dir, &dentry->d_name, NULL, NULL);
+	error = gfs2_dir_check(dir, &dentry->d_name, NULL);
 	switch (error) {
 	case -ENOENT:
 		break;
@@ -206,7 +206,7 @@
 			goto out_gunlock_q;
 
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-					 al->al_rgd->rd_ri.ri_length +
+					 al->al_rgd->rd_length +
 					 2 * RES_DINODE + RES_STATFS +
 					 RES_QUOTA, 0);
 		if (error)
@@ -217,8 +217,7 @@
 			goto out_ipres;
 	}
 
-	error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num,
-			     IF2DT(inode->i_mode));
+	error = gfs2_dir_add(dir, &dentry->d_name, ip, IF2DT(inode->i_mode));
 	if (error)
 		goto out_end_trans;
 
@@ -275,7 +274,7 @@
 	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
 	gfs2_holder_init(ip->i_gl,  LM_ST_EXCLUSIVE, 0, ghs + 1);
 
-	rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
 	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
 
 
@@ -420,7 +419,7 @@
 		dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
 		gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
 
-		gfs2_inum_out(&dip->i_num, &dent->de_inum);
+		gfs2_inum_out(dip, dent);
 		dent->de_type = cpu_to_be16(DT_DIR);
 
 		gfs2_dinode_out(ip, di);
@@ -472,7 +471,7 @@
 	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
 	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
 
-	rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
 	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
 
 	error = gfs2_glock_nq_m(3, ghs);
@@ -614,7 +613,7 @@
 		 * this is the case of the target file already existing
 		 * so we unlink before doing the rename
 		 */
-		nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr);
+		nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr);
 		if (nrgd)
 			gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
 	}
@@ -653,7 +652,7 @@
 		if (error)
 			goto out_gunlock;
 
-		error = gfs2_dir_search(ndir, &ndentry->d_name, NULL, NULL);
+		error = gfs2_dir_check(ndir, &ndentry->d_name, NULL);
 		switch (error) {
 		case -ENOENT:
 			error = 0;
@@ -712,7 +711,7 @@
 			goto out_gunlock_q;
 
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-					 al->al_rgd->rd_ri.ri_length +
+					 al->al_rgd->rd_length +
 					 4 * RES_DINODE + 4 * RES_LEAF +
 					 RES_STATFS + RES_QUOTA + 4, 0);
 		if (error)
@@ -750,7 +749,7 @@
 		if (error)
 			goto out_end_trans;
 
-		error = gfs2_dir_mvino(ip, &name, &ndip->i_num, DT_DIR);
+		error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR);
 		if (error)
 			goto out_end_trans;
 	} else {
@@ -758,7 +757,7 @@
 		error = gfs2_meta_inode_buffer(ip, &dibh);
 		if (error)
 			goto out_end_trans;
-		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -768,8 +767,7 @@
 	if (error)
 		goto out_end_trans;
 
-	error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num,
-			     IF2DT(ip->i_inode.i_mode));
+	error = gfs2_dir_add(ndir, &ndentry->d_name, ip, IF2DT(ip->i_inode.i_mode));
 	if (error)
 		goto out_end_trans;
 
@@ -905,8 +903,8 @@
 	}
 
 	error = gfs2_truncatei(ip, attr->ia_size);
-	if (error)
-		return error;
+	if (error && (inode->i_size != ip->i_di.di_size))
+		i_size_write(inode, ip->i_di.di_size);
 
 	return error;
 }
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 485ce3d..603d940 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -326,8 +326,10 @@
 		gfs2_glock_schedule_for_reclaim(ip->i_gl);
 		gfs2_glock_put(ip->i_gl);
 		ip->i_gl = NULL;
-		if (ip->i_iopen_gh.gh_gl)
+		if (ip->i_iopen_gh.gh_gl) {
+			ip->i_iopen_gh.gh_gl->gl_object = NULL;
 			gfs2_glock_dq_uninit(&ip->i_iopen_gh);
+		}
 	}
 }
 
@@ -422,13 +424,13 @@
 	if (!inode->i_private)
 		goto out;
 
-	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh);
+	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
 	if (unlikely(error)) {
 		gfs2_glock_dq_uninit(&ip->i_iopen_gh);
 		goto out;
 	}
 
-	gfs2_glock_dq(&ip->i_iopen_gh);
+	gfs2_glock_dq_wait(&ip->i_iopen_gh);
 	gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
 	error = gfs2_glock_nq(&ip->i_iopen_gh);
 	if (error)
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
index aa0dbd2..404b7cc 100644
--- a/fs/gfs2/ops_vm.c
+++ b/fs/gfs2/ops_vm.c
@@ -66,7 +66,7 @@
 	if (error)
 		goto out_gunlock_q;
 
-	error = gfs2_trans_begin(sdp, al->al_rgd->rd_ri.ri_length +
+	error = gfs2_trans_begin(sdp, al->al_rgd->rd_length +
 				 ind_blocks + RES_DINODE +
 				 RES_STATFS + RES_QUOTA, 0);
 	if (error)
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c186857..6e546ee 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -66,6 +66,18 @@
 #define QUOTA_USER 1
 #define QUOTA_GROUP 0
 
+struct gfs2_quota_host {
+	u64 qu_limit;
+	u64 qu_warn;
+	s64 qu_value;
+};
+
+struct gfs2_quota_change_host {
+	u64 qc_change;
+	u32 qc_flags; /* GFS2_QCF_... */
+	u32 qc_id;
+};
+
 static u64 qd2offset(struct gfs2_quota_data *qd)
 {
 	u64 offset;
@@ -561,6 +573,25 @@
 	mutex_unlock(&sdp->sd_quota_mutex);
 }
 
+static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
+{
+	const struct gfs2_quota *str = buf;
+
+	qu->qu_limit = be64_to_cpu(str->qu_limit);
+	qu->qu_warn = be64_to_cpu(str->qu_warn);
+	qu->qu_value = be64_to_cpu(str->qu_value);
+}
+
+static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf)
+{
+	struct gfs2_quota *str = buf;
+
+	str->qu_limit = cpu_to_be64(qu->qu_limit);
+	str->qu_warn = cpu_to_be64(qu->qu_warn);
+	str->qu_value = cpu_to_be64(qu->qu_value);
+	memset(&str->qu_reserved, 0, sizeof(str->qu_reserved));
+}
+
 /**
  * gfs2_adjust_quota
  *
@@ -573,12 +604,13 @@
 	struct inode *inode = &ip->i_inode;
 	struct address_space *mapping = inode->i_mapping;
 	unsigned long index = loc >> PAGE_CACHE_SHIFT;
-	unsigned offset = loc & (PAGE_CACHE_SHIFT - 1);
+	unsigned offset = loc & (PAGE_CACHE_SIZE - 1);
 	unsigned blocksize, iblock, pos;
 	struct buffer_head *bh;
 	struct page *page;
 	void *kaddr;
-	__be64 *ptr;
+	char *ptr;
+	struct gfs2_quota_host qp;
 	s64 value;
 	int err = -EIO;
 
@@ -620,13 +652,17 @@
 
 	kaddr = kmap_atomic(page, KM_USER0);
 	ptr = kaddr + offset;
-	value = (s64)be64_to_cpu(*ptr) + change;
-	*ptr = cpu_to_be64(value);
+	gfs2_quota_in(&qp, ptr);
+	qp.qu_value += change;
+	value = qp.qu_value;
+	gfs2_quota_out(&qp, ptr);
 	flush_dcache_page(page);
 	kunmap_atomic(kaddr, KM_USER0);
 	err = 0;
 	qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC);
 	qd->qd_qb.qb_value = cpu_to_be64(value);
+	((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC);
+	((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value);
 unlock:
 	unlock_page(page);
 	page_cache_release(page);
@@ -689,7 +725,7 @@
 			goto out_alloc;
 
 		error = gfs2_trans_begin(sdp,
-					 al->al_rgd->rd_ri.ri_length +
+					 al->al_rgd->rd_length +
 					 num_qd * data_blocks +
 					 nalloc * ind_blocks +
 					 RES_DINODE + num_qd +
@@ -709,7 +745,7 @@
 		offset = qd2offset(qd);
 		error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync,
 					  (struct gfs2_quota_data *)
-					  qd->qd_gl->gl_lvb);
+					  qd);
 		if (error)
 			goto out_end_trans;
 
@@ -1050,6 +1086,15 @@
 	return error;
 }
 
+static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
+{
+	const struct gfs2_quota_change *str = buf;
+
+	qc->qc_change = be64_to_cpu(str->qc_change);
+	qc->qc_flags = be32_to_cpu(str->qc_flags);
+	qc->qc_id = be32_to_cpu(str->qc_id);
+}
+
 int gfs2_quota_init(struct gfs2_sbd *sdp)
 {
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 8bc182c..5ada38c 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -116,6 +116,22 @@
 	}
 }
 
+static int gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
+{
+	const struct gfs2_log_header *str = buf;
+
+	if (str->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
+	    str->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH))
+		return 1;
+
+	lh->lh_sequence = be64_to_cpu(str->lh_sequence);
+	lh->lh_flags = be32_to_cpu(str->lh_flags);
+	lh->lh_tail = be32_to_cpu(str->lh_tail);
+	lh->lh_blkno = be32_to_cpu(str->lh_blkno);
+	lh->lh_hash = be32_to_cpu(str->lh_hash);
+	return 0;
+}
+
 /**
  * get_log_header - read the log header for a given segment
  * @jd: the journal
@@ -147,12 +163,10 @@
 					     sizeof(u32));
 	hash = crc32_le(hash, (unsigned char const *)&nothing, sizeof(nothing));
 	hash ^= (u32)~0;
-	gfs2_log_header_in(&lh, bh->b_data);
+	error = gfs2_log_header_in(&lh, bh->b_data);
 	brelse(bh);
 
-	if (lh.lh_header.mh_magic != GFS2_MAGIC ||
-	    lh.lh_header.mh_type != GFS2_METATYPE_LH ||
-	    lh.lh_blkno != blk || lh.lh_hash != hash)
+	if (error || lh.lh_blkno != blk || lh.lh_hash != hash)
 		return 1;
 
 	*head = lh;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 1727f50..e4e0406 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -28,6 +28,7 @@
 #include "ops_file.h"
 #include "util.h"
 #include "log.h"
+#include "inode.h"
 
 #define BFITNOENT ((u32)~0)
 
@@ -50,6 +51,9 @@
 	        1, 0, 0, 0
 };
 
+static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+                        unsigned char old_state, unsigned char new_state);
+
 /**
  * gfs2_setbit - Set a bit in the bitmaps
  * @buffer: the buffer that holds the bitmaps
@@ -204,7 +208,7 @@
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	struct gfs2_bitmap *bi = NULL;
-	u32 length = rgd->rd_ri.ri_length;
+	u32 length = rgd->rd_length;
 	u32 count[4], tmp;
 	int buf, x;
 
@@ -227,7 +231,7 @@
 		return;
 	}
 
-	tmp = rgd->rd_ri.ri_data -
+	tmp = rgd->rd_data -
 		rgd->rd_rg.rg_free -
 		rgd->rd_rg.rg_dinodes;
 	if (count[1] + count[2] != tmp) {
@@ -253,10 +257,10 @@
 
 }
 
-static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block)
+static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
 {
-	u64 first = ri->ri_data0;
-	u64 last = first + ri->ri_data;
+	u64 first = rgd->rd_data0;
+	u64 last = first + rgd->rd_data;
 	return first <= block && block < last;
 }
 
@@ -275,7 +279,7 @@
 	spin_lock(&sdp->sd_rindex_spin);
 
 	list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) {
-		if (rgrp_contains_block(&rgd->rd_ri, blk)) {
+		if (rgrp_contains_block(rgd, blk)) {
 			list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
 			spin_unlock(&sdp->sd_rindex_spin);
 			return rgd;
@@ -354,6 +358,15 @@
 	mutex_unlock(&sdp->sd_rindex_mutex);
 }
 
+static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd)
+{
+	printk(KERN_INFO "  ri_addr = %llu\n", (unsigned long long)rgd->rd_addr);
+	printk(KERN_INFO "  ri_length = %u\n", rgd->rd_length);
+	printk(KERN_INFO "  ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0);
+	printk(KERN_INFO "  ri_data = %u\n", rgd->rd_data);
+	printk(KERN_INFO "  ri_bitbytes = %u\n", rgd->rd_bitbytes);
+}
+
 /**
  * gfs2_compute_bitstructs - Compute the bitmap sizes
  * @rgd: The resource group descriptor
@@ -367,7 +380,7 @@
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	struct gfs2_bitmap *bi;
-	u32 length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */
+	u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */
 	u32 bytes_left, bytes;
 	int x;
 
@@ -378,7 +391,7 @@
 	if (!rgd->rd_bits)
 		return -ENOMEM;
 
-	bytes_left = rgd->rd_ri.ri_bitbytes;
+	bytes_left = rgd->rd_bitbytes;
 
 	for (x = 0; x < length; x++) {
 		bi = rgd->rd_bits + x;
@@ -399,14 +412,14 @@
 		} else if (x + 1 == length) {
 			bytes = bytes_left;
 			bi->bi_offset = sizeof(struct gfs2_meta_header);
-			bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
+			bi->bi_start = rgd->rd_bitbytes - bytes_left;
 			bi->bi_len = bytes;
 		/* other blocks */
 		} else {
 			bytes = sdp->sd_sb.sb_bsize -
 				sizeof(struct gfs2_meta_header);
 			bi->bi_offset = sizeof(struct gfs2_meta_header);
-			bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
+			bi->bi_start = rgd->rd_bitbytes - bytes_left;
 			bi->bi_len = bytes;
 		}
 
@@ -418,9 +431,9 @@
 		return -EIO;
 	}
 	bi = rgd->rd_bits + (length - 1);
-	if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_ri.ri_data) {
+	if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_data) {
 		if (gfs2_consist_rgrpd(rgd)) {
-			gfs2_rindex_print(&rgd->rd_ri);
+			gfs2_rindex_print(rgd);
 			fs_err(sdp, "start=%u len=%u offset=%u\n",
 			       bi->bi_start, bi->bi_len, bi->bi_offset);
 		}
@@ -431,9 +444,104 @@
 }
 
 /**
- * gfs2_ri_update - Pull in a new resource index from the disk
+ * gfs2_ri_total - Total up the file system space, according to the rindex.
+ *
+ */
+u64 gfs2_ri_total(struct gfs2_sbd *sdp)
+{
+	u64 total_data = 0;	
+	struct inode *inode = sdp->sd_rindex;
+	struct gfs2_inode *ip = GFS2_I(inode);
+	char buf[sizeof(struct gfs2_rindex)];
+	struct file_ra_state ra_state;
+	int error, rgrps;
+
+	mutex_lock(&sdp->sd_rindex_mutex);
+	file_ra_state_init(&ra_state, inode->i_mapping);
+	for (rgrps = 0;; rgrps++) {
+		loff_t pos = rgrps * sizeof(struct gfs2_rindex);
+
+		if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size)
+			break;
+		error = gfs2_internal_read(ip, &ra_state, buf, &pos,
+					   sizeof(struct gfs2_rindex));
+		if (error != sizeof(struct gfs2_rindex))
+			break;
+		total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data);
+	}
+	mutex_unlock(&sdp->sd_rindex_mutex);
+	return total_data;
+}
+
+static void gfs2_rindex_in(struct gfs2_rgrpd *rgd, const void *buf)
+{
+	const struct gfs2_rindex *str = buf;
+
+	rgd->rd_addr = be64_to_cpu(str->ri_addr);
+	rgd->rd_length = be32_to_cpu(str->ri_length);
+	rgd->rd_data0 = be64_to_cpu(str->ri_data0);
+	rgd->rd_data = be32_to_cpu(str->ri_data);
+	rgd->rd_bitbytes = be32_to_cpu(str->ri_bitbytes);
+}
+
+/**
+ * read_rindex_entry - Pull in a new resource index entry from the disk
  * @gl: The glock covering the rindex inode
  *
+ * Returns: 0 on success, error code otherwise
+ */
+
+static int read_rindex_entry(struct gfs2_inode *ip,
+			     struct file_ra_state *ra_state)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
+	char buf[sizeof(struct gfs2_rindex)];
+	int error;
+	struct gfs2_rgrpd *rgd;
+
+	error = gfs2_internal_read(ip, ra_state, buf, &pos,
+				   sizeof(struct gfs2_rindex));
+	if (!error)
+		return 0;
+	if (error != sizeof(struct gfs2_rindex)) {
+		if (error > 0)
+			error = -EIO;
+		return error;
+	}
+
+	rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
+	error = -ENOMEM;
+	if (!rgd)
+		return error;
+
+	mutex_init(&rgd->rd_mutex);
+	lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
+	rgd->rd_sbd = sdp;
+
+	list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
+	list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
+
+	gfs2_rindex_in(rgd, buf);
+	error = compute_bitstructs(rgd);
+	if (error)
+		return error;
+
+	error = gfs2_glock_get(sdp, rgd->rd_addr,
+			       &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
+	if (error)
+		return error;
+
+	rgd->rd_gl->gl_object = rgd;
+	rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
+	rgd->rd_flags |= GFS2_RDF_CHECK;
+	return error;
+}
+
+/**
+ * gfs2_ri_update - Pull in a new resource index from the disk
+ * @ip: pointer to the rindex inode
+ *
  * Returns: 0 on successful update, error code otherwise
  */
 
@@ -441,13 +549,11 @@
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct inode *inode = &ip->i_inode;
-	struct gfs2_rgrpd *rgd;
-	char buf[sizeof(struct gfs2_rindex)];
 	struct file_ra_state ra_state;
-	u64 junk = ip->i_di.di_size;
+	u64 rgrp_count = ip->i_di.di_size;
 	int error;
 
-	if (do_div(junk, sizeof(struct gfs2_rindex))) {
+	if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) {
 		gfs2_consist_inode(ip);
 		return -EIO;
 	}
@@ -455,50 +561,50 @@
 	clear_rgrpdi(sdp);
 
 	file_ra_state_init(&ra_state, inode->i_mapping);
-	for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
-		loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
-		error = gfs2_internal_read(ip, &ra_state, buf, &pos,
-					    sizeof(struct gfs2_rindex));
-		if (!error)
-			break;
-		if (error != sizeof(struct gfs2_rindex)) {
-			if (error > 0)
-				error = -EIO;
-			goto fail;
+	for (sdp->sd_rgrps = 0; sdp->sd_rgrps < rgrp_count; sdp->sd_rgrps++) {
+		error = read_rindex_entry(ip, &ra_state);
+		if (error) {
+			clear_rgrpdi(sdp);
+			return error;
 		}
-
-		rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
-		error = -ENOMEM;
-		if (!rgd)
-			goto fail;
-
-		mutex_init(&rgd->rd_mutex);
-		lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
-		rgd->rd_sbd = sdp;
-
-		list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
-		list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
-
-		gfs2_rindex_in(&rgd->rd_ri, buf);
-		error = compute_bitstructs(rgd);
-		if (error)
-			goto fail;
-
-		error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr,
-				       &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
-		if (error)
-			goto fail;
-
-		rgd->rd_gl->gl_object = rgd;
-		rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
 	}
 
 	sdp->sd_rindex_vn = ip->i_gl->gl_vn;
 	return 0;
+}
 
-fail:
-	clear_rgrpdi(sdp);
-	return error;
+/**
+ * gfs2_ri_update_special - Pull in a new resource index from the disk
+ *
+ * This is a special version that's safe to call from gfs2_inplace_reserve_i.
+ * In this case we know that we don't have any resource groups in memory yet.
+ *
+ * @ip: pointer to the rindex inode
+ *
+ * Returns: 0 on successful update, error code otherwise
+ */
+static int gfs2_ri_update_special(struct gfs2_inode *ip)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	struct inode *inode = &ip->i_inode;
+	struct file_ra_state ra_state;
+	int error;
+
+	file_ra_state_init(&ra_state, inode->i_mapping);
+	for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
+		/* Ignore partials */
+		if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
+		    ip->i_di.di_size)
+			break;
+		error = read_rindex_entry(ip, &ra_state);
+		if (error) {
+			clear_rgrpdi(sdp);
+			return error;
+		}
+	}
+
+	sdp->sd_rindex_vn = ip->i_gl->gl_vn;
+	return 0;
 }
 
 /**
@@ -543,6 +649,28 @@
 	return error;
 }
 
+static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
+{
+	const struct gfs2_rgrp *str = buf;
+
+	rg->rg_flags = be32_to_cpu(str->rg_flags);
+	rg->rg_free = be32_to_cpu(str->rg_free);
+	rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
+	rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
+}
+
+static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
+{
+	struct gfs2_rgrp *str = buf;
+
+	str->rg_flags = cpu_to_be32(rg->rg_flags);
+	str->rg_free = cpu_to_be32(rg->rg_free);
+	str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
+	str->__pad = cpu_to_be32(0);
+	str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
+	memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
+}
+
 /**
  * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps
  * @rgd: the struct gfs2_rgrpd describing the RG to read in
@@ -557,7 +685,7 @@
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	struct gfs2_glock *gl = rgd->rd_gl;
-	unsigned int length = rgd->rd_ri.ri_length;
+	unsigned int length = rgd->rd_length;
 	struct gfs2_bitmap *bi;
 	unsigned int x, y;
 	int error;
@@ -575,7 +703,7 @@
 
 	for (x = 0; x < length; x++) {
 		bi = rgd->rd_bits + x;
-		error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh);
+		error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh);
 		if (error)
 			goto fail;
 	}
@@ -637,7 +765,7 @@
 void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd)
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
-	int x, length = rgd->rd_ri.ri_length;
+	int x, length = rgd->rd_length;
 
 	spin_lock(&sdp->sd_rindex_spin);
 	gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count);
@@ -660,7 +788,7 @@
 void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd)
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
-	unsigned int length = rgd->rd_ri.ri_length;
+	unsigned int length = rgd->rd_length;
 	unsigned int x;
 
 	for (x = 0; x < length; x++) {
@@ -722,6 +850,38 @@
 }
 
 /**
+ * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
+ * @rgd: The rgrp
+ *
+ * Returns: The inode, if one has been found
+ */
+
+static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+{
+	struct inode *inode;
+	u32 goal = 0;
+	u64 no_addr;
+
+	for(;;) {
+		goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
+				    GFS2_BLKST_UNLINKED);
+		if (goal == 0)
+			return 0;
+		no_addr = goal + rgd->rd_data0;
+		if (no_addr <= *last_unlinked)
+			continue;
+		*last_unlinked = no_addr;
+		inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
+					no_addr, -1);
+		if (!IS_ERR(inode))
+			return inode;
+	}
+
+	rgd->rd_flags &= ~GFS2_RDF_CHECK;
+	return NULL;
+}
+
+/**
  * recent_rgrp_first - get first RG from "recent" list
  * @sdp: The GFS2 superblock
  * @rglast: address of the rgrp used last
@@ -743,7 +903,7 @@
 		goto first;
 
 	list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
-		if (rgd->rd_ri.ri_addr == rglast)
+		if (rgd->rd_addr == rglast)
 			goto out;
 	}
 
@@ -882,8 +1042,9 @@
  * Returns: errno
  */
 
-static int get_local_rgrp(struct gfs2_inode *ip)
+static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
 {
+	struct inode *inode = NULL;
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrpd *rgd, *begin = NULL;
 	struct gfs2_alloc *al = &ip->i_alloc;
@@ -903,7 +1064,11 @@
 		case 0:
 			if (try_rgrp_fit(rgd, al))
 				goto out;
+			if (rgd->rd_flags & GFS2_RDF_CHECK)
+				inode = try_rgrp_unlink(rgd, last_unlinked);
 			gfs2_glock_dq_uninit(&al->al_rgd_gh);
+			if (inode)
+				return inode;
 			rgd = recent_rgrp_next(rgd, 1);
 			break;
 
@@ -912,7 +1077,7 @@
 			break;
 
 		default:
-			return error;
+			return ERR_PTR(error);
 		}
 	}
 
@@ -927,7 +1092,11 @@
 		case 0:
 			if (try_rgrp_fit(rgd, al))
 				goto out;
+			if (rgd->rd_flags & GFS2_RDF_CHECK)
+				inode = try_rgrp_unlink(rgd, last_unlinked);
 			gfs2_glock_dq_uninit(&al->al_rgd_gh);
+			if (inode)
+				return inode;
 			break;
 
 		case GLR_TRYFAILED:
@@ -935,7 +1104,7 @@
 			break;
 
 		default:
-			return error;
+			return ERR_PTR(error);
 		}
 
 		rgd = gfs2_rgrpd_get_next(rgd);
@@ -944,7 +1113,7 @@
 
 		if (rgd == begin) {
 			if (++loops >= 3)
-				return -ENOSPC;
+				return ERR_PTR(-ENOSPC);
 			if (!skipped)
 				loops++;
 			flags = 0;
@@ -954,7 +1123,7 @@
 	}
 
 out:
-	ip->i_last_rg_alloc = rgd->rd_ri.ri_addr;
+	ip->i_last_rg_alloc = rgd->rd_addr;
 
 	if (begin) {
 		recent_rgrp_add(rgd);
@@ -964,7 +1133,7 @@
 		forward_rgrp_set(sdp, rgd);
 	}
 
-	return 0;
+	return NULL;
 }
 
 /**
@@ -978,19 +1147,33 @@
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_alloc *al = &ip->i_alloc;
-	int error;
+	struct inode *inode;
+	int error = 0;
+	u64 last_unlinked = 0;
 
 	if (gfs2_assert_warn(sdp, al->al_requested))
 		return -EINVAL;
 
-	error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+try_again:
+	/* We need to hold the rindex unless the inode we're using is
+	   the rindex itself, in which case it's already held. */
+	if (ip != GFS2_I(sdp->sd_rindex))
+		error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+	else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */
+		error = gfs2_ri_update_special(ip);
+
 	if (error)
 		return error;
 
-	error = get_local_rgrp(ip);
-	if (error) {
-		gfs2_glock_dq_uninit(&al->al_ri_gh);
-		return error;
+	inode = get_local_rgrp(ip, &last_unlinked);
+	if (inode) {
+		if (ip != GFS2_I(sdp->sd_rindex))
+			gfs2_glock_dq_uninit(&al->al_ri_gh);
+		if (IS_ERR(inode))
+			return PTR_ERR(inode);
+		iput(inode);
+		gfs2_log_flush(sdp, NULL);
+		goto try_again;
 	}
 
 	al->al_file = file;
@@ -1019,7 +1202,8 @@
 
 	al->al_rgd = NULL;
 	gfs2_glock_dq_uninit(&al->al_rgd_gh);
-	gfs2_glock_dq_uninit(&al->al_ri_gh);
+	if (ip != GFS2_I(sdp->sd_rindex))
+		gfs2_glock_dq_uninit(&al->al_ri_gh);
 }
 
 /**
@@ -1037,8 +1221,8 @@
 	unsigned int buf;
 	unsigned char type;
 
-	length = rgd->rd_ri.ri_length;
-	rgrp_block = block - rgd->rd_ri.ri_data0;
+	length = rgd->rd_length;
+	rgrp_block = block - rgd->rd_data0;
 
 	for (buf = 0; buf < length; buf++) {
 		bi = rgd->rd_bits + buf;
@@ -1077,10 +1261,10 @@
  */
 
 static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
-			     unsigned char old_state, unsigned char new_state)
+			unsigned char old_state, unsigned char new_state)
 {
 	struct gfs2_bitmap *bi = NULL;
-	u32 length = rgd->rd_ri.ri_length;
+	u32 length = rgd->rd_length;
 	u32 blk = 0;
 	unsigned int buf, x;
 
@@ -1118,17 +1302,18 @@
 		goal = 0;
 	}
 
-	if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length))
-		blk = 0;
+	if (old_state != new_state) {
+		gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT);
 
-	gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
-	gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
-		    bi->bi_len, blk, new_state);
-	if (bi->bi_clone)
-		gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+		gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+		gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
 			    bi->bi_len, blk, new_state);
+		if (bi->bi_clone)
+			gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+				    bi->bi_len, blk, new_state);
+	}
 
-	return bi->bi_start * GFS2_NBBY + blk;
+	return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk;
 }
 
 /**
@@ -1156,9 +1341,9 @@
 		return NULL;
 	}
 
-	length = rgd->rd_ri.ri_length;
+	length = rgd->rd_length;
 
-	rgrp_blk = bstart - rgd->rd_ri.ri_data0;
+	rgrp_blk = bstart - rgd->rd_data0;
 
 	while (blen--) {
 		for (buf = 0; buf < length; buf++) {
@@ -1202,15 +1387,15 @@
 	u32 goal, blk;
 	u64 block;
 
-	if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_data))
-		goal = ip->i_di.di_goal_data - rgd->rd_ri.ri_data0;
+	if (rgrp_contains_block(rgd, ip->i_di.di_goal_data))
+		goal = ip->i_di.di_goal_data - rgd->rd_data0;
 	else
 		goal = rgd->rd_last_alloc_data;
 
 	blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
 	rgd->rd_last_alloc_data = blk;
 
-	block = rgd->rd_ri.ri_data0 + blk;
+	block = rgd->rd_data0 + blk;
 	ip->i_di.di_goal_data = block;
 
 	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
@@ -1246,15 +1431,15 @@
 	u32 goal, blk;
 	u64 block;
 
-	if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_meta))
-		goal = ip->i_di.di_goal_meta - rgd->rd_ri.ri_data0;
+	if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta))
+		goal = ip->i_di.di_goal_meta - rgd->rd_data0;
 	else
 		goal = rgd->rd_last_alloc_meta;
 
 	blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
 	rgd->rd_last_alloc_meta = blk;
 
-	block = rgd->rd_ri.ri_data0 + blk;
+	block = rgd->rd_data0 + blk;
 	ip->i_di.di_goal_meta = block;
 
 	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
@@ -1296,7 +1481,7 @@
 
 	rgd->rd_last_alloc_meta = blk;
 
-	block = rgd->rd_ri.ri_data0 + blk;
+	block = rgd->rd_data0 + blk;
 
 	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
 	rgd->rd_rg.rg_free--;
@@ -1379,7 +1564,7 @@
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	struct gfs2_rgrpd *rgd;
-	u64 blkno = ip->i_num.no_addr;
+	u64 blkno = ip->i_no_addr;
 
 	rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED);
 	if (!rgd)
@@ -1414,9 +1599,9 @@
 
 void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
 {
-	gfs2_free_uninit_di(rgd, ip->i_num.no_addr);
+	gfs2_free_uninit_di(rgd, ip->i_no_addr);
 	gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid);
-	gfs2_meta_wipe(ip, ip->i_num.no_addr, 1);
+	gfs2_meta_wipe(ip, ip->i_no_addr, 1);
 }
 
 /**
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index b01e0cf..b4c6adf 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -65,5 +65,6 @@
 void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
 		      int flags);
 void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
+u64 gfs2_ri_total(struct gfs2_sbd *sdp);
 
 #endif /* __RGRP_DOT_H__ */
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 4fdda97..f916b97 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -95,8 +95,8 @@
 {
 	unsigned int x;
 
-	if (sb->sb_header.mh_magic != GFS2_MAGIC ||
-	    sb->sb_header.mh_type != GFS2_METATYPE_SB) {
+	if (sb->sb_magic != GFS2_MAGIC ||
+	    sb->sb_type != GFS2_METATYPE_SB) {
 		if (!silent)
 			printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n");
 		return -EINVAL;
@@ -174,10 +174,31 @@
 	return 0;
 }
 
+static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
+{
+	const struct gfs2_sb *str = buf;
+
+	sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic);
+	sb->sb_type = be32_to_cpu(str->sb_header.mh_type);
+	sb->sb_format = be32_to_cpu(str->sb_header.mh_format);
+	sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
+	sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
+	sb->sb_bsize = be32_to_cpu(str->sb_bsize);
+	sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
+	sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr);
+	sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino);
+	sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr);
+	sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino);
+
+	memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
+	memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
+}
+
 /**
  * gfs2_read_super - Read the gfs2 super block from disk
- * @sb: The VFS super block
+ * @sdp: The GFS2 super block
  * @sector: The location of the super block
+ * @error: The error code to return
  *
  * This uses the bio functions to read the super block from disk
  * because we want to be 100% sure that we never read cached data.
@@ -189,17 +210,19 @@
  * the master directory (contains pointers to journals etc) and the
  * root directory.
  *
- * Returns: A page containing the sb or NULL
+ * Returns: 0 on success or error
  */
 
-struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
+int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
 {
+	struct super_block *sb = sdp->sd_vfs;
+	struct gfs2_sb *p;
 	struct page *page;
 	struct bio *bio;
 
 	page = alloc_page(GFP_KERNEL);
 	if (unlikely(!page))
-		return NULL;
+		return -ENOBUFS;
 
 	ClearPageUptodate(page);
 	ClearPageDirty(page);
@@ -208,7 +231,7 @@
 	bio = bio_alloc(GFP_KERNEL, 1);
 	if (unlikely(!bio)) {
 		__free_page(page);
-		return NULL;
+		return -ENOBUFS;
 	}
 
 	bio->bi_sector = sector * (sb->s_blocksize >> 9);
@@ -222,9 +245,13 @@
 	bio_put(bio);
 	if (!PageUptodate(page)) {
 		__free_page(page);
-		return NULL;
+		return -EIO;
 	}
-	return page;
+	p = kmap(page);
+	gfs2_sb_in(&sdp->sd_sb, p);
+	kunmap(page);
+	__free_page(page);
+	return 0;
 }
 
 /**
@@ -241,19 +268,13 @@
 	u32 tmp_blocks;
 	unsigned int x;
 	int error;
-	struct page *page;
-	char *sb;
 
-	page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
-	if (!page) {
+	error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+	if (error) {
 		if (!silent)
 			fs_err(sdp, "can't read superblock\n");
-		return -EIO;
+		return error;
 	}
-	sb = kmap(page);
-	gfs2_sb_in(&sdp->sd_sb, sb);
-	kunmap(page);
-	__free_page(page);
 
 	error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
 	if (error)
@@ -360,7 +381,7 @@
 		name.len = sprintf(buf, "journal%u", sdp->sd_journals);
 		name.hash = gfs2_disk_hash(name.name, name.len);
 
-		error = gfs2_dir_search(sdp->sd_jindex, &name, NULL, NULL);
+		error = gfs2_dir_check(sdp->sd_jindex, &name, NULL);
 		if (error == -ENOENT) {
 			error = 0;
 			break;
@@ -593,6 +614,24 @@
 	return error;
 }
 
+static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
+{
+	const struct gfs2_statfs_change *str = buf;
+
+	sc->sc_total = be64_to_cpu(str->sc_total);
+	sc->sc_free = be64_to_cpu(str->sc_free);
+	sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
+}
+
+static void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
+{
+	struct gfs2_statfs_change *str = buf;
+
+	str->sc_total = cpu_to_be64(sc->sc_total);
+	str->sc_free = cpu_to_be64(sc->sc_free);
+	str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
+}
+
 int gfs2_statfs_init(struct gfs2_sbd *sdp)
 {
 	struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
@@ -772,7 +811,7 @@
 			    struct gfs2_statfs_change_host *sc)
 {
 	gfs2_rgrp_verify(rgd);
-	sc->sc_total += rgd->rd_ri.ri_data;
+	sc->sc_total += rgd->rd_data;
 	sc->sc_free += rgd->rd_rg.rg_free;
 	sc->sc_dinodes += rgd->rd_rg.rg_dinodes;
 	return 0;
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
index e590b2d..60a870e 100644
--- a/fs/gfs2/super.h
+++ b/fs/gfs2/super.h
@@ -16,7 +16,7 @@
 
 int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
 int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
-struct page *gfs2_read_super(struct super_block *sb, sector_t sector);
+int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector);
 
 static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
 {
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 601eaa1..424a077 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -115,8 +115,8 @@
 		"GFS2: fsid=%s:   inode = %llu %llu\n"
 		"GFS2: fsid=%s:   function = %s, file = %s, line = %u\n",
 		sdp->sd_fsname,
-		sdp->sd_fsname, (unsigned long long)ip->i_num.no_formal_ino,
-		(unsigned long long)ip->i_num.no_addr,
+		sdp->sd_fsname, (unsigned long long)ip->i_no_formal_ino,
+		(unsigned long long)ip->i_no_addr,
 		sdp->sd_fsname, function, file, line);
 	return rv;
 }
@@ -137,7 +137,7 @@
 		"GFS2: fsid=%s:   RG = %llu\n"
 		"GFS2: fsid=%s:   function = %s, file = %s, line = %u\n",
 		sdp->sd_fsname,
-		sdp->sd_fsname, (unsigned long long)rgd->rd_ri.ri_addr,
+		sdp->sd_fsname, (unsigned long long)rgd->rd_addr,
 		sdp->sd_fsname, function, file, line);
 	return rv;
 }
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index fafcba5..bc835f2 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -13,6 +13,7 @@
 
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
+#include <linux/sched.h>
 
 #include "hfs_fs.h"
 #include "btree.h"
@@ -606,7 +607,7 @@
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.fsync		= file_fsync,
 	.open		= hfs_file_open,
 	.release	= hfs_file_release,
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 90ebab7..050d29c 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -62,8 +62,10 @@
 		if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
 		    (head->key_type == HFSPLUS_KEY_BINARY))
 			tree->keycmp = hfsplus_cat_bin_cmp_key;
-		else
+		else {
 			tree->keycmp = hfsplus_cat_case_cmp_key;
+			HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD;
+		}
 	} else {
 		printk(KERN_ERR "hfs: unknown B*Tree requested\n");
 		goto fail_page;
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 80b5682..1955ee6 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -36,6 +36,8 @@
 	u16 type;
 
 	sb = dir->i_sb;
+
+	dentry->d_op = &hfsplus_dentry_operations;
 	dentry->d_fsdata = NULL;
 	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
 	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 3915635..d9f5eda 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -150,6 +150,7 @@
 #define HFSPLUS_SB_NODECOMPOSE	0x0002
 #define HFSPLUS_SB_FORCE	0x0004
 #define HFSPLUS_SB_HFSX		0x0008
+#define HFSPLUS_SB_CASEFOLD	0x0010
 
 
 struct hfsplus_inode_info {
@@ -321,6 +322,7 @@
 /* inode.c */
 extern const struct address_space_operations hfsplus_aops;
 extern const struct address_space_operations hfsplus_btree_aops;
+extern struct dentry_operations hfsplus_dentry_operations;
 
 void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
 void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
@@ -353,6 +355,8 @@
 int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
 int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
 int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
+int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str);
+int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2);
 
 /* wrapper.c */
 int hfsplus_read_wrapper(struct super_block *);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 642012a..6f7c662 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -12,6 +12,7 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
+#include <linux/sched.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
@@ -130,6 +131,11 @@
 	.writepages	= hfsplus_writepages,
 };
 
+struct dentry_operations hfsplus_dentry_operations = {
+	.d_hash       = hfsplus_hash_dentry,
+	.d_compare    = hfsplus_compare_dentry,
+};
+
 static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry,
 					  struct nameidata *nd)
 {
@@ -287,7 +293,7 @@
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.fsync		= file_fsync,
 	.open		= hfsplus_file_open,
 	.release	= hfsplus_file_release,
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index 79fd104..b60c0af 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -38,7 +38,7 @@
 		if (IS_RDONLY(inode))
 			return -EROFS;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(flags, (int __user *)arg))
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index ebd1b38..6d87a2a 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -283,11 +283,10 @@
 	struct nls_table *nls = NULL;
 	int err = -EINVAL;
 
-	sbi = kmalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL);
+	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
 
-	memset(sbi, 0, sizeof(HFSPLUS_SB(sb)));
 	sb->s_fs_info = sbi;
 	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 	hfsplus_fill_defaults(sbi);
@@ -381,6 +380,7 @@
 		iput(root);
 		goto cleanup;
 	}
+	sb->s_root->d_op = &hfsplus_dentry_operations;
 
 	str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
 	str.name = HFSP_HIDDENDIR_NAME;
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 689c8bd..9e10f94 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -239,61 +239,201 @@
 	return res;
 }
 
-int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, const char *astr, int len)
+/*
+ * Convert one or more ASCII characters into a single unicode character.
+ * Returns the number of ASCII characters corresponding to the unicode char.
+ */
+static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
+			      wchar_t *uc)
 {
-	struct nls_table *nls = HFSPLUS_SB(sb).nls;
-	int size, off, decompose;
+	int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc);
+	if (size <= 0) {
+		*uc = '?';
+		size = 1;
+	}
+	switch (*uc) {
+	case 0x2400:
+		*uc = 0;
+		break;
+	case ':':
+		*uc = '/';
+		break;
+	}
+	return size;
+}
+
+/* Decomposes a single unicode character. */
+static inline u16 *decompose_unichar(wchar_t uc, int *size)
+{
+	int off;
+
+	off = hfsplus_decompose_table[(uc >> 12) & 0xf];
+	if (off == 0 || off == 0xffff)
+		return NULL;
+
+	off = hfsplus_decompose_table[off + ((uc >> 8) & 0xf)];
+	if (!off)
+		return NULL;
+
+	off = hfsplus_decompose_table[off + ((uc >> 4) & 0xf)];
+	if (!off)
+		return NULL;
+
+	off = hfsplus_decompose_table[off + (uc & 0xf)];
+	*size = off & 3;
+	if (*size == 0)
+		return NULL;
+	return hfsplus_decompose_table + (off / 4);
+}
+
+int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
+		    const char *astr, int len)
+{
+	int size, dsize, decompose;
+	u16 *dstr, outlen = 0;
 	wchar_t c;
-	u16 outlen = 0;
 
 	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
-
 	while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
-		size = nls->char2uni(astr, len, &c);
-		if (size <= 0) {
-			c = '?';
-			size = 1;
-		}
-		astr += size;
-		len -= size;
-		switch (c) {
-		case 0x2400:
-			c = 0;
-			break;
-		case ':':
-			c = '/';
-			break;
-		}
-		if (c >= 0xc0 && decompose) {
-			off = hfsplus_decompose_table[(c >> 12) & 0xf];
-			if (!off)
-				goto done;
-			if (off == 0xffff) {
-				goto done;
-			}
-			off = hfsplus_decompose_table[off + ((c >> 8) & 0xf)];
-			if (!off)
-				goto done;
-			off = hfsplus_decompose_table[off + ((c >> 4) & 0xf)];
-			if (!off)
-				goto done;
-			off = hfsplus_decompose_table[off + (c & 0xf)];
-			size = off & 3;
-			if (!size)
-				goto done;
-			off /= 4;
-			if (outlen + size > HFSPLUS_MAX_STRLEN)
+		size = asc2unichar(sb, astr, len, &c);
+
+		if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+			if (outlen + dsize > HFSPLUS_MAX_STRLEN)
 				break;
 			do {
-				ustr->unicode[outlen++] = cpu_to_be16(hfsplus_decompose_table[off++]);
-			} while (--size > 0);
-			continue;
-		}
-	done:
-		ustr->unicode[outlen++] = cpu_to_be16(c);
+				ustr->unicode[outlen++] = cpu_to_be16(*dstr++);
+			} while (--dsize > 0);
+		} else
+			ustr->unicode[outlen++] = cpu_to_be16(c);
+
+		astr += size;
+		len -= size;
 	}
 	ustr->length = cpu_to_be16(outlen);
 	if (len > 0)
 		return -ENAMETOOLONG;
 	return 0;
 }
+
+/*
+ * Hash a string to an integer as appropriate for the HFS+ filesystem.
+ * Composed unicode characters are decomposed and case-folding is performed
+ * if the appropriate bits are (un)set on the superblock.
+ */
+int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str)
+{
+	struct super_block *sb = dentry->d_sb;
+	const char *astr;
+	const u16 *dstr;
+	int casefold, decompose, size, dsize, len;
+	unsigned long hash;
+	wchar_t c;
+	u16 c2;
+
+	casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
+	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+	hash = init_name_hash();
+	astr = str->name;
+	len = str->len;
+	while (len > 0) {
+		size = asc2unichar(sb, astr, len, &c);
+		astr += size;
+		len -= size;
+
+		if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+			do {
+				c2 = *dstr++;
+				if (!casefold || (c2 = case_fold(c2)))
+					hash = partial_name_hash(c2, hash);
+			} while (--dsize > 0);
+		} else {
+			c2 = c;
+			if (!casefold || (c2 = case_fold(c2)))
+				hash = partial_name_hash(c2, hash);
+		}
+	}
+	str->hash = end_name_hash(hash);
+
+	return 0;
+}
+
+/*
+ * Compare strings with HFS+ filename ordering.
+ * Composed unicode characters are decomposed and case-folding is performed
+ * if the appropriate bits are (un)set on the superblock.
+ */
+int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2)
+{
+	struct super_block *sb = dentry->d_sb;
+	int casefold, decompose, size;
+	int dsize1, dsize2, len1, len2;
+	const u16 *dstr1, *dstr2;
+	const char *astr1, *astr2;
+	u16 c1, c2;
+	wchar_t c;
+
+	casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
+	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+	astr1 = s1->name;
+	len1 = s1->len;
+	astr2 = s2->name;
+	len2 = s2->len;
+	dsize1 = dsize2 = 0;
+	dstr1 = dstr2 = NULL;
+
+	while (len1 > 0 && len2 > 0) {
+		if (!dsize1) {
+			size = asc2unichar(sb, astr1, len1, &c);
+			astr1 += size;
+			len1 -= size;
+
+			if (!decompose || !(dstr1 = decompose_unichar(c, &dsize1))) {
+				c1 = c;
+				dstr1 = &c1;
+				dsize1 = 1;
+			}
+		}
+
+		if (!dsize2) {
+			size = asc2unichar(sb, astr2, len2, &c);
+			astr2 += size;
+			len2 -= size;
+
+			if (!decompose || !(dstr2 = decompose_unichar(c, &dsize2))) {
+				c2 = c;
+				dstr2 = &c2;
+				dsize2 = 1;
+			}
+		}
+
+		c1 = *dstr1;
+		c2 = *dstr2;
+		if (casefold) {
+			if  (!(c1 = case_fold(c1))) {
+				dstr1++;
+				dsize1--;
+				continue;
+			}
+			if (!(c2 = case_fold(c2))) {
+				dstr2++;
+				dsize2--;
+				continue;
+			}
+		}
+		if (c1 < c2)
+			return -1;
+		else if (c1 > c2)
+			return 1;
+
+		dstr1++;
+		dsize1--;
+		dstr2++;
+		dsize2--;
+	}
+
+	if (len1 < len2)
+		return -1;
+	if (len1 > len2)
+		return 1;
+	return 0;
+}
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 8286491..c778620 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -390,7 +390,7 @@
 static const struct file_operations hostfs_file_fops = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.write		= do_sync_write,
diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c
index b52b738..b6fca54 100644
--- a/fs/hpfs/buffer.c
+++ b/fs/hpfs/buffer.c
@@ -5,7 +5,7 @@
  *
  *  general buffer i/o
  */
-
+#include <linux/sched.h>
 #include "hpfs_fn.h"
 
 void hpfs_lock_creation(struct super_block *s)
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index b4eafc0..5b53e5c 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -129,7 +129,7 @@
 	.mmap		= generic_file_mmap,
 	.release	= hpfs_file_release,
 	.fsync		= hpfs_file_fsync,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations hpfs_file_iops =
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 9953cf9..d256559 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -5,7 +5,7 @@
  *
  *  adding & removing files & directories
  */
-
+#include <linux/sched.h>
 #include "hpfs_fn.h"
 
 static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index fca1165d..29cc34a 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/statfs.h>
 #include <linux/magic.h>
+#include <linux/sched.h>
 
 /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
 
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index aa083dd..d145cb7 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -13,15 +13,18 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/file.h>
+#include <linux/kernel.h>
 #include <linux/writeback.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/capability.h>
+#include <linux/ctype.h>
 #include <linux/backing-dev.h>
 #include <linux/hugetlb.h>
 #include <linux/pagevec.h>
+#include <linux/parser.h>
 #include <linux/mman.h>
 #include <linux/quotaops.h>
 #include <linux/slab.h>
@@ -47,6 +50,21 @@
 
 int sysctl_hugetlb_shm_group;
 
+enum {
+	Opt_size, Opt_nr_inodes,
+	Opt_mode, Opt_uid, Opt_gid,
+	Opt_err,
+};
+
+static match_table_t tokens = {
+	{Opt_size,	"size=%s"},
+	{Opt_nr_inodes,	"nr_inodes=%s"},
+	{Opt_mode,	"mode=%o"},
+	{Opt_uid,	"uid=%u"},
+	{Opt_gid,	"gid=%u"},
+	{Opt_err,	NULL},
+};
+
 static void huge_pagevec_release(struct pagevec *pvec)
 {
 	int i;
@@ -594,46 +612,73 @@
 static int
 hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
 {
-	char *opt, *value, *rest;
+	char *p, *rest;
+	substring_t args[MAX_OPT_ARGS];
+	int option;
 
 	if (!options)
 		return 0;
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
+
+	while ((p = strsep(&options, ",")) != NULL) {
+		int token;
+		if (!*p)
 			continue;
 
-		value = strchr(opt, '=');
-		if (!value || !*value)
-			return -EINVAL;
-		else
-			*value++ = '\0';
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_uid:
+			if (match_int(&args[0], &option))
+ 				goto bad_val;
+			pconfig->uid = option;
+			break;
 
-		if (!strcmp(opt, "uid"))
-			pconfig->uid = simple_strtoul(value, &value, 0);
-		else if (!strcmp(opt, "gid"))
-			pconfig->gid = simple_strtoul(value, &value, 0);
-		else if (!strcmp(opt, "mode"))
-			pconfig->mode = simple_strtoul(value,&value,0) & 0777U;
-		else if (!strcmp(opt, "size")) {
-			unsigned long long size = memparse(value, &rest);
+		case Opt_gid:
+			if (match_int(&args[0], &option))
+ 				goto bad_val;
+			pconfig->gid = option;
+			break;
+
+		case Opt_mode:
+			if (match_octal(&args[0], &option))
+ 				goto bad_val;
+			pconfig->mode = option & 0777U;
+			break;
+
+		case Opt_size: {
+ 			unsigned long long size;
+			/* memparse() will accept a K/M/G without a digit */
+			if (!isdigit(*args[0].from))
+				goto bad_val;
+			size = memparse(args[0].from, &rest);
 			if (*rest == '%') {
 				size <<= HPAGE_SHIFT;
 				size *= max_huge_pages;
 				do_div(size, 100);
-				rest++;
 			}
 			pconfig->nr_blocks = (size >> HPAGE_SHIFT);
-			value = rest;
-		} else if (!strcmp(opt,"nr_inodes")) {
-			pconfig->nr_inodes = memparse(value, &rest);
-			value = rest;
-		} else
-			return -EINVAL;
+			break;
+		}
 
-		if (*value)
+		case Opt_nr_inodes:
+			/* memparse() will accept a K/M/G without a digit */
+			if (!isdigit(*args[0].from))
+				goto bad_val;
+			pconfig->nr_inodes = memparse(args[0].from, &rest);
+			break;
+
+		default:
+			printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
+				 p);
 			return -EINVAL;
+			break;
+		}
 	}
 	return 0;
+
+bad_val:
+ 	printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",
+	       args[0].from, p);
+ 	return 1;
 }
 
 static int
@@ -651,7 +696,6 @@
 	config.gid = current->fsgid;
 	config.mode = 0755;
 	ret = hugetlbfs_parse_options(data, &config);
-
 	if (ret)
 		return ret;
 
@@ -736,15 +780,13 @@
 			can_do_mlock());
 }
 
-struct file *hugetlb_zero_setup(size_t size)
+struct file *hugetlb_file_setup(const char *name, size_t size)
 {
 	int error = -ENOMEM;
 	struct file *file;
 	struct inode *inode;
 	struct dentry *dentry, *root;
 	struct qstr quick_string;
-	char buf[16];
-	static atomic_t counter;
 
 	if (!hugetlbfs_vfsmount)
 		return ERR_PTR(-ENOENT);
@@ -756,8 +798,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	root = hugetlbfs_vfsmount->mnt_root;
-	snprintf(buf, 16, "%u", atomic_inc_return(&counter));
-	quick_string.name = buf;
+	quick_string.name = name;
 	quick_string.len = strlen(quick_string.name);
 	quick_string.hash = 0;
 	dentry = d_alloc(root, &quick_string);
diff --git a/fs/inode.c b/fs/inode.c
index 9a012cc..320e088 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -145,7 +145,7 @@
 		mapping->a_ops = &empty_aops;
  		mapping->host = inode;
 		mapping->flags = 0;
-		mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
+		mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE);
 		mapping->assoc_mapping = NULL;
 		mapping->backing_dev_info = &default_backing_dev_info;
 
@@ -462,6 +462,11 @@
 	return (inodes_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
 
+static struct shrinker icache_shrinker = {
+	.shrink = shrink_icache_memory,
+	.seeks = DEFAULT_SEEKS,
+};
+
 static void __wait_on_freeing_inode(struct inode *inode);
 /*
  * Called with the inode lock held.
@@ -519,7 +524,13 @@
  *	new_inode 	- obtain an inode
  *	@sb: superblock
  *
- *	Allocates a new inode for given superblock.
+ *	Allocates a new inode for given superblock. The default gfp_mask
+ *	for allocations related to inode->i_mapping is GFP_HIGHUSER_PAGECACHE.
+ *	If HIGHMEM pages are unsuitable or it is known that pages allocated
+ *	for the page cache are not reclaimable or migratable,
+ *	mapping_set_gfp_mask() must be called with suitable flags on the
+ *	newly created inode's mapping
+ *
  */
 struct inode *new_inode(struct super_block *sb)
 {
@@ -1379,7 +1390,7 @@
 					 SLAB_MEM_SPREAD),
 					 init_once,
 					 NULL);
-	set_shrinker(DEFAULT_SEEKS, shrink_icache_memory);
+	register_shrinker(&icache_shrinker);
 
 	/* Hash may have been set up in inode_init_early */
 	if (!hashdist)
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 479c103..c2a773e 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -174,11 +174,3 @@
  out:
 	return error;
 }
-
-/*
- * Platforms implementing 32 bit compatibility ioctl handlers in
- * modules need this exported
- */
-#ifdef CONFIG_COMPAT
-EXPORT_SYMBOL(sys_ioctl);
-#endif
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 0e94c31..1ba407c 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -7,34 +7,18 @@
  *
  *  Steve Beynon		       : Missing last directory entries fixed
  *  (stephen@askone.demon.co.uk)      : 21st June 1996
- * 
+ *
  *  isofs directory handling functions
  */
 #include <linux/smp_lock.h>
 #include "isofs.h"
 
-static int isofs_readdir(struct file *, void *, filldir_t);
-
-const struct file_operations isofs_dir_operations =
-{
-	.read		= generic_read_dir,
-	.readdir	= isofs_readdir,
-};
-
-/*
- * directories can handle most operations...
- */
-const struct inode_operations isofs_dir_inode_operations =
-{
-	.lookup		= isofs_lookup,
-};
-
 int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
 {
 	char * old = de->name;
 	int len = de->name_len[0];
 	int i;
-			
+
 	for (i = 0; i < len; i++) {
 		unsigned char c = old[i];
 		if (!c)
@@ -62,22 +46,27 @@
 }
 
 /* Acorn extensions written by Matthew Wilcox <willy@bofh.ai> 1998 */
-int get_acorn_filename(struct iso_directory_record * de,
-			    char * retname, struct inode * inode)
+int get_acorn_filename(struct iso_directory_record *de,
+			    char *retname, struct inode *inode)
 {
 	int std;
-	unsigned char * chr;
+	unsigned char *chr;
 	int retnamlen = isofs_name_translate(de, retname, inode);
-	if (retnamlen == 0) return 0;
+
+	if (retnamlen == 0)
+		return 0;
 	std = sizeof(struct iso_directory_record) + de->name_len[0];
-	if (std & 1) std++;
-	if ((*((unsigned char *) de) - std) != 32) return retnamlen;
+	if (std & 1)
+		std++;
+	if ((*((unsigned char *) de) - std) != 32)
+		return retnamlen;
 	chr = ((unsigned char *) de) + std;
-	if (strncmp(chr, "ARCHIMEDES", 10)) return retnamlen;
-	if ((*retname == '_') && ((chr[19] & 1) == 1)) *retname = '!';
+	if (strncmp(chr, "ARCHIMEDES", 10))
+		return retnamlen;
+	if ((*retname == '_') && ((chr[19] & 1) == 1))
+		*retname = '!';
 	if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff)
-		&& ((chr[12] & 0xf0) == 0xf0))
-	{
+		&& ((chr[12] & 0xf0) == 0xf0)) {
 		retname[retnamlen] = ',';
 		sprintf(retname+retnamlen+1, "%3.3x",
 			((chr[12] & 0xf) << 8) | chr[11]);
@@ -91,7 +80,7 @@
  */
 static int do_isofs_readdir(struct inode *inode, struct file *filp,
 		void *dirent, filldir_t filldir,
-		char * tmpname, struct iso_directory_record * tmpde)
+		char *tmpname, struct iso_directory_record *tmpde)
 {
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
@@ -121,9 +110,11 @@
 
 		de_len = *(unsigned char *) de;
 
-		/* If the length byte is zero, we should move on to the next
-		   CDROM sector.  If we are at the end of the directory, we
-		   kick out of the while loop. */
+		/*
+		 * If the length byte is zero, we should move on to the next
+		 * CDROM sector.  If we are at the end of the directory, we
+		 * kick out of the while loop.
+		 */
 
 		if (de_len == 0) {
 			brelse(bh);
@@ -157,11 +148,10 @@
 
 		if (first_de) {
 			isofs_normalize_block_and_offset(de,
-							 &block_saved,
-							 &offset_saved);
+							&block_saved,
+							&offset_saved);
 			inode_number = isofs_get_ino(block_saved,
-						     offset_saved,
-						     bufbits);
+							offset_saved, bufbits);
 		}
 
 		if (de->flags[-sbi->s_high_sierra] & 0x80) {
@@ -199,7 +189,7 @@
 		 */
 		if ((sbi->s_hide == 'y' &&
 				(de->flags[-sbi->s_high_sierra] & 1)) ||
-		      (sbi->s_showassoc =='n' &&
+				(sbi->s_showassoc =='n' &&
 				(de->flags[-sbi->s_high_sierra] & 4))) {
 			filp->f_pos += de_len;
 			continue;
@@ -240,7 +230,8 @@
 
 		continue;
 	}
-	if (bh) brelse(bh);
+	if (bh)
+		brelse(bh);
 	return 0;
 }
 
@@ -253,8 +244,8 @@
 		void *dirent, filldir_t filldir)
 {
 	int result;
-	char * tmpname;
-	struct iso_directory_record * tmpde;
+	char *tmpname;
+	struct iso_directory_record *tmpde;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 
 	tmpname = (char *)__get_free_page(GFP_KERNEL);
@@ -270,3 +261,19 @@
 	unlock_kernel();
 	return result;
 }
+
+const struct file_operations isofs_dir_operations =
+{
+	.read = generic_read_dir,
+	.readdir = isofs_readdir,
+};
+
+/*
+ * directories can handle most operations...
+ */
+const struct inode_operations isofs_dir_inode_operations =
+{
+	.lookup = isofs_lookup,
+};
+
+
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 5c3eecf..4f5418b 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -73,20 +73,20 @@
 	kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
 }
 
-static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
 {
 	struct iso_inode_info *ei = foo;
 
 	inode_init_once(&ei->vfs_inode);
 }
- 
+
 static int init_inodecache(void)
 {
 	isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
-					     sizeof(struct iso_inode_info),
-					     0, (SLAB_RECLAIM_ACCOUNT|
-						SLAB_MEM_SPREAD),
-					     init_once, NULL);
+					sizeof(struct iso_inode_info),
+					0, (SLAB_RECLAIM_ACCOUNT|
+					SLAB_MEM_SPREAD),
+					init_once, NULL);
 	if (isofs_inode_cachep == NULL)
 		return -ENOMEM;
 	return 0;
@@ -150,9 +150,9 @@
 	uid_t uid;
 	char *iocharset;
 	unsigned char utf8;
-        /* LVE */
-        s32 session;
-        s32 sbsector;
+	/* LVE */
+	s32 session;
+	s32 sbsector;
 };
 
 /*
@@ -197,7 +197,7 @@
 	hash = init_name_hash();
 	while (len--) {
 		c = tolower(*name++);
-		hash = partial_name_hash(tolower(c), hash);
+		hash = partial_name_hash(c, hash);
 	}
 	qstr->hash = end_name_hash(hash);
 
@@ -360,10 +360,12 @@
 	popt->check = 'u';		/* unset */
 	popt->nocompress = 0;
 	popt->blocksize = 1024;
-	popt->mode = S_IRUGO | S_IXUGO; /* r-x for all.  The disc could
-					   be shared with DOS machines so
-					   virtually anything could be
-					   a valid executable. */
+	popt->mode = S_IRUGO | S_IXUGO; /*
+					 * r-x for all.  The disc could
+					 * be shared with DOS machines so
+					 * virtually anything could be
+					 * a valid executable.
+					 */
 	popt->gid = 0;
 	popt->uid = 0;
 	popt->iocharset = NULL;
@@ -503,30 +505,30 @@
 		Te.cdte_format=CDROM_LBA;
 		i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);
 		if (!i) {
-			printk(KERN_DEBUG "Session %d start %d type %d\n",
-			       session, Te.cdte_addr.lba,
-			       Te.cdte_ctrl&CDROM_DATA_TRACK);
+			printk(KERN_DEBUG "ISOFS: Session %d start %d type %d\n",
+				session, Te.cdte_addr.lba,
+				Te.cdte_ctrl&CDROM_DATA_TRACK);
 			if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)
 				return Te.cdte_addr.lba;
 		}
-			
-		printk(KERN_ERR "Invalid session number or type of track\n");
+
+		printk(KERN_ERR "ISOFS: Invalid session number or type of track\n");
 	}
 	i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
 	if (session > 0)
-		printk(KERN_ERR "Invalid session number\n");
+		printk(KERN_ERR "ISOFS: Invalid session number\n");
 #if 0
-	printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
+	printk(KERN_DEBUG "isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
 	if (i==0) {
-		printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
-		printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
+		printk(KERN_DEBUG "isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
+		printk(KERN_DEBUG "isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
 	}
 #endif
 	if (i==0)
 #if WE_OBEY_THE_WRITTEN_STANDARDS
-        if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
+		if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
 #endif
-		vol_desc_start=ms_info.addr.lba;
+			vol_desc_start=ms_info.addr.lba;
 	return vol_desc_start;
 }
 
@@ -538,20 +540,20 @@
  */
 static int isofs_fill_super(struct super_block *s, void *data, int silent)
 {
-	struct buffer_head	      * bh = NULL, *pri_bh = NULL;
-	struct hs_primary_descriptor  * h_pri = NULL;
-	struct iso_primary_descriptor * pri = NULL;
+	struct buffer_head *bh = NULL, *pri_bh = NULL;
+	struct hs_primary_descriptor *h_pri = NULL;
+	struct iso_primary_descriptor *pri = NULL;
 	struct iso_supplementary_descriptor *sec = NULL;
-	struct iso_directory_record   * rootp;
-	int				joliet_level = 0;
-	int				iso_blknum, block;
-	int				orig_zonesize;
-	int				table;
-	unsigned int			vol_desc_start;
-	unsigned long			first_data_zone;
-	struct inode		      * inode;
-	struct iso9660_options		opt;
-	struct isofs_sb_info	      * sbi;
+	struct iso_directory_record *rootp;
+	struct inode *inode;
+	struct iso9660_options opt;
+	struct isofs_sb_info *sbi;
+	unsigned long first_data_zone;
+	int joliet_level = 0;
+	int iso_blknum, block;
+	int orig_zonesize;
+	int table;
+	unsigned int vol_desc_start;
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -577,72 +579,73 @@
 	vol_desc_start = (opt.sbsector != -1) ?
 		opt.sbsector : isofs_get_last_session(s,opt.session);
 
-  	for (iso_blknum = vol_desc_start+16;
-             iso_blknum < vol_desc_start+100; iso_blknum++)
-	{
-	    struct hs_volume_descriptor   * hdp;
-	    struct iso_volume_descriptor  * vdp;
+	for (iso_blknum = vol_desc_start+16;
+		iso_blknum < vol_desc_start+100; iso_blknum++) {
+		struct hs_volume_descriptor *hdp;
+		struct iso_volume_descriptor  *vdp;
 
-	    block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits);
-	    if (!(bh = sb_bread(s, block)))
-		goto out_no_read;
+		block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits);
+		if (!(bh = sb_bread(s, block)))
+			goto out_no_read;
 
-	    vdp = (struct iso_volume_descriptor *)bh->b_data;
-	    hdp = (struct hs_volume_descriptor *)bh->b_data;
-	    
-	    /* Due to the overlapping physical location of the descriptors, 
-	     * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure 
-	     * proper identification in this case, we first check for ISO.
-	     */
-	    if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
-		if (isonum_711 (vdp->type) == ISO_VD_END)
-		    break;
-		if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) {
-		    if (pri == NULL) {
-			pri = (struct iso_primary_descriptor *)vdp;
-			/* Save the buffer in case we need it ... */
-			pri_bh = bh;
-			bh = NULL;
-		    }
-		}
-#ifdef CONFIG_JOLIET
-		else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) {
-		    sec = (struct iso_supplementary_descriptor *)vdp;
-		    if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
-			if (opt.joliet == 'y') {
-			    if (sec->escape[2] == 0x40) {
-				joliet_level = 1;
-			    } else if (sec->escape[2] == 0x43) {
-				joliet_level = 2;
-			    } else if (sec->escape[2] == 0x45) {
-				joliet_level = 3;
-			    }
-			    printk(KERN_DEBUG"ISO 9660 Extensions: Microsoft Joliet Level %d\n",
-				   joliet_level);
+		vdp = (struct iso_volume_descriptor *)bh->b_data;
+		hdp = (struct hs_volume_descriptor *)bh->b_data;
+
+		/*
+		 * Due to the overlapping physical location of the descriptors,
+		 * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure
+		 * proper identification in this case, we first check for ISO.
+		 */
+		if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
+			if (isonum_711(vdp->type) == ISO_VD_END)
+				break;
+			if (isonum_711(vdp->type) == ISO_VD_PRIMARY) {
+				if (pri == NULL) {
+					pri = (struct iso_primary_descriptor *)vdp;
+					/* Save the buffer in case we need it ... */
+					pri_bh = bh;
+					bh = NULL;
+				}
 			}
-			goto root_found;
-		    } else {
-			/* Unknown supplementary volume descriptor */
-			sec = NULL;
-		    }
-		}
+#ifdef CONFIG_JOLIET
+			else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) {
+				sec = (struct iso_supplementary_descriptor *)vdp;
+				if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
+					if (opt.joliet == 'y') {
+						if (sec->escape[2] == 0x40)
+							joliet_level = 1;
+						else if (sec->escape[2] == 0x43)
+							joliet_level = 2;
+						else if (sec->escape[2] == 0x45)
+							joliet_level = 3;
+
+						printk(KERN_DEBUG "ISO 9660 Extensions: "
+							"Microsoft Joliet Level %d\n",
+							joliet_level);
+					}
+					goto root_found;
+				} else {
+				/* Unknown supplementary volume descriptor */
+				sec = NULL;
+				}
+			}
 #endif
-	    } else {
-	        if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
-		    if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
-		        goto out_freebh;
-		
-		    sbi->s_high_sierra = 1;
-		    opt.rock = 'n';
-		    h_pri = (struct hs_primary_descriptor *)vdp;
-		    goto root_found;
+		} else {
+			if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
+				if (isonum_711(hdp->type) != ISO_VD_PRIMARY)
+					goto out_freebh;
+
+				sbi->s_high_sierra = 1;
+				opt.rock = 'n';
+				h_pri = (struct hs_primary_descriptor *)vdp;
+				goto root_found;
+			}
 		}
-	    }
 
-            /* Just skip any volume descriptors we don't recognize */
+		/* Just skip any volume descriptors we don't recognize */
 
-	    brelse(bh);
-	    bh = NULL;
+		brelse(bh);
+		bh = NULL;
 	}
 	/*
 	 * If we fall through, either no volume descriptor was found,
@@ -657,24 +660,24 @@
 root_found:
 
 	if (joliet_level && (pri == NULL || opt.rock == 'n')) {
-	    /* This is the case of Joliet with the norock mount flag.
-	     * A disc with both Joliet and Rock Ridge is handled later
-	     */
-	    pri = (struct iso_primary_descriptor *) sec;
+		/* This is the case of Joliet with the norock mount flag.
+		 * A disc with both Joliet and Rock Ridge is handled later
+		 */
+		pri = (struct iso_primary_descriptor *) sec;
 	}
 
 	if(sbi->s_high_sierra){
-	  rootp = (struct iso_directory_record *) h_pri->root_directory_record;
-	  sbi->s_nzones = isonum_733 (h_pri->volume_space_size);
-	  sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size);
-	  sbi->s_max_size = isonum_733(h_pri->volume_space_size);
+		rootp = (struct iso_directory_record *) h_pri->root_directory_record;
+		sbi->s_nzones = isonum_733(h_pri->volume_space_size);
+		sbi->s_log_zone_size = isonum_723(h_pri->logical_block_size);
+		sbi->s_max_size = isonum_733(h_pri->volume_space_size);
 	} else {
-	  if (!pri)
-	    goto out_freebh;
-	  rootp = (struct iso_directory_record *) pri->root_directory_record;
-	  sbi->s_nzones = isonum_733 (pri->volume_space_size);
-	  sbi->s_log_zone_size = isonum_723 (pri->logical_block_size);
-	  sbi->s_max_size = isonum_733(pri->volume_space_size);
+		if (!pri)
+			goto out_freebh;
+		rootp = (struct iso_directory_record *) pri->root_directory_record;
+		sbi->s_nzones = isonum_733(pri->volume_space_size);
+		sbi->s_log_zone_size = isonum_723(pri->logical_block_size);
+		sbi->s_max_size = isonum_733(pri->volume_space_size);
 	}
 
 	sbi->s_ninodes = 0; /* No way to figure this out easily */
@@ -687,42 +690,43 @@
 	 * blocks that were 512 bytes (which should only very rarely
 	 * happen.)
 	 */
-	if(orig_zonesize < opt.blocksize)
+	if (orig_zonesize < opt.blocksize)
 		goto out_bad_size;
 
 	/* RDE: convert log zone size to bit shift */
-	switch (sbi->s_log_zone_size)
-	  { case  512: sbi->s_log_zone_size =  9; break;
-	    case 1024: sbi->s_log_zone_size = 10; break;
-	    case 2048: sbi->s_log_zone_size = 11; break;
+	switch (sbi->s_log_zone_size) {
+	case  512: sbi->s_log_zone_size =  9; break;
+	case 1024: sbi->s_log_zone_size = 10; break;
+	case 2048: sbi->s_log_zone_size = 11; break;
 
-	    default:
+	default:
 		goto out_bad_zone_size;
-	  }
+	}
 
 	s->s_magic = ISOFS_SUPER_MAGIC;
 	s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */
 
-	/* The CDROM is read-only, has no nodes (devices) on it, and since
-	   all of the files appear to be owned by root, we really do not want
-	   to allow suid.  (suid or devices will not show up unless we have
-	   Rock Ridge extensions) */
+	/*
+	 * The CDROM is read-only, has no nodes (devices) on it, and since
+	 * all of the files appear to be owned by root, we really do not want
+	 * to allow suid.  (suid or devices will not show up unless we have
+	 * Rock Ridge extensions)
+	 */
 
 	s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
 
 	/* Set this for reference. Its not currently used except on write
 	   which we don't have .. */
-	   
-	first_data_zone = isonum_733 (rootp->extent) +
-			  isonum_711 (rootp->ext_attr_length);
+
+	first_data_zone = isonum_733(rootp->extent) +
+			  isonum_711(rootp->ext_attr_length);
 	sbi->s_firstdatazone = first_data_zone;
 #ifndef BEQUIET
-	printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
-	       sbi->s_max_size,
-	       1UL << sbi->s_log_zone_size);
-	printk(KERN_DEBUG "First datazone:%ld\n", sbi->s_firstdatazone);
+	printk(KERN_DEBUG "ISOFS: Max size:%ld   Log zone size:%ld\n",
+		sbi->s_max_size, 1UL << sbi->s_log_zone_size);
+	printk(KERN_DEBUG "ISOFS: First datazone:%ld\n", sbi->s_firstdatazone);
 	if(sbi->s_high_sierra)
-		printk(KERN_DEBUG "Disc in High Sierra format.\n");
+		printk(KERN_DEBUG "ISOFS: Disc in High Sierra format.\n");
 #endif
 
 	/*
@@ -737,8 +741,8 @@
 		pri = (struct iso_primary_descriptor *) sec;
 		rootp = (struct iso_directory_record *)
 			pri->root_directory_record;
-		first_data_zone = isonum_733 (rootp->extent) +
-			  	isonum_711 (rootp->ext_attr_length);
+		first_data_zone = isonum_733(rootp->extent) +
+				isonum_711(rootp->ext_attr_length);
 	}
 
 	/*
@@ -771,7 +775,7 @@
 
 #ifdef CONFIG_JOLIET
 	if (joliet_level && opt.utf8 == 0) {
-		char * p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
+		char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
 		sbi->s_nls_iocharset = load_nls(p);
 		if (! sbi->s_nls_iocharset) {
 			/* Fail only if explicit charset specified */
@@ -821,7 +825,7 @@
 		sbi->s_rock = 0;
 		if (sbi->s_firstdatazone != first_data_zone) {
 			sbi->s_firstdatazone = first_data_zone;
-			printk(KERN_DEBUG 
+			printk(KERN_DEBUG
 				"ISOFS: changing to secondary root\n");
 			iput(inode);
 			inode = isofs_iget(s, sbi->s_firstdatazone, 0);
@@ -830,8 +834,10 @@
 
 	if (opt.check == 'u') {
 		/* Only Joliet is case insensitive by default */
-		if (joliet_level) opt.check = 'r';
-		else opt.check = 's';
+		if (joliet_level)
+			opt.check = 'r';
+		else
+			opt.check = 's';
 	}
 	sbi->s_joliet_level = joliet_level;
 
@@ -846,8 +852,10 @@
 		goto out_no_root;
 
 	table = 0;
-	if (joliet_level) table += 2;
-	if (opt.check == 'r') table++;
+	if (joliet_level)
+		table += 2;
+	if (opt.check == 'r')
+		table++;
 	s->s_root->d_op = &isofs_dentry_ops[table];
 
 	kfree(opt.iocharset);
@@ -858,10 +866,10 @@
 	 * Display error messages and free resources.
 	 */
 out_bad_root:
-	printk(KERN_WARNING "isofs_fill_super: root inode not initialized\n");
+	printk(KERN_WARNING "%s: root inode not initialized\n", __func__);
 	goto out_iput;
 out_no_root:
-	printk(KERN_WARNING "isofs_fill_super: get root inode failed\n");
+	printk(KERN_WARNING "%s: get root inode failed\n", __func__);
 out_iput:
 	iput(inode);
 #ifdef CONFIG_JOLIET
@@ -870,21 +878,20 @@
 #endif
 	goto out_freesbi;
 out_no_read:
-	printk(KERN_WARNING "isofs_fill_super: "
-		"bread failed, dev=%s, iso_blknum=%d, block=%d\n",
-		s->s_id, iso_blknum, block);
+	printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n",
+		__func__, s->s_id, iso_blknum, block);
 	goto out_freesbi;
 out_bad_zone_size:
-	printk(KERN_WARNING "Bad logical zone size %ld\n",
+	printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n",
 		sbi->s_log_zone_size);
 	goto out_freebh;
 out_bad_size:
-	printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
+	printk(KERN_WARNING "ISOFS: Logical zone size(%d) < hardware blocksize(%u)\n",
 		orig_zonesize, opt.blocksize);
 	goto out_freebh;
 out_unknown_format:
 	if (!silent)
-		printk(KERN_WARNING "Unable to identify CD-ROM format.\n");
+		printk(KERN_WARNING "ISOFS: Unable to identify CD-ROM format.\n");
 
 out_freebh:
 	brelse(bh);
@@ -902,7 +909,7 @@
 	buf->f_type = ISOFS_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = (ISOFS_SB(sb)->s_nzones
-                  << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
+		<< (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
 	buf->f_bfree = 0;
 	buf->f_bavail = 0;
 	buf->f_files = ISOFS_SB(sb)->s_ninodes;
@@ -931,20 +938,20 @@
 
 	rv = 0;
 	if (iblock < 0 || iblock != iblock_s) {
-		printk("isofs_get_blocks: block number too large\n");
+		printk(KERN_DEBUG "%s: block number too large\n", __func__);
 		goto abort;
 	}
 
 	b_off = iblock;
-	
-	offset    = 0;
-	firstext  = ei->i_first_extent;
-	sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
-	nextblk   = ei->i_next_section_block;
-	nextoff   = ei->i_next_section_offset;
-	section   = 0;
 
-	while ( nblocks ) {
+	offset = 0;
+	firstext = ei->i_first_extent;
+	sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
+	nextblk = ei->i_next_section_block;
+	nextoff = ei->i_next_section_offset;
+	section = 0;
+
+	while (nblocks) {
 		/* If we are *way* beyond the end of the file, print a message.
 		 * Access beyond the end of the file up to the next page boundary
 		 * is normal, however because of the way the page cache works.
@@ -953,11 +960,11 @@
 		 * I/O errors.
 		 */
 		if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) {
-			printk("isofs_get_blocks: block >= EOF (%ld, %ld)\n",
-			       iblock, (unsigned long) inode->i_size);
+			printk(KERN_DEBUG "%s: block >= EOF (%ld, %ld)\n",
+				__func__, iblock, (unsigned long) inode->i_size);
 			goto abort;
 		}
-		
+
 		/* On the last section, nextblk == 0, section size is likely to
 		 * exceed sect_size by a partial block, and access beyond the
 		 * end of the file will reach beyond the section size, too.
@@ -976,20 +983,21 @@
 			iput(ninode);
 
 			if (++section > 100) {
-				printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
-				printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
-				       "nextblk=%lu nextoff=%lu\n",
-				       iblock, firstext, (unsigned) sect_size,
-				       nextblk, nextoff);
+				printk(KERN_DEBUG "%s: More than 100 file sections ?!?"
+					" aborting...\n", __func__);
+				printk(KERN_DEBUG "%s: block=%ld firstext=%u sect_size=%u "
+					"nextblk=%lu nextoff=%lu\n", __func__,
+					iblock, firstext, (unsigned) sect_size,
+					nextblk, nextoff);
 				goto abort;
 			}
 		}
-		
-		if ( *bh ) {
+
+		if (*bh) {
 			map_bh(*bh, inode->i_sb, firstext + b_off - offset);
 		} else {
 			*bh = sb_getblk(inode->i_sb, firstext+b_off-offset);
-			if ( !*bh )
+			if (!*bh)
 				goto abort;
 		}
 		bh++;	/* Next buffer head */
@@ -1010,7 +1018,7 @@
 		    struct buffer_head *bh_result, int create)
 {
 	if (create) {
-		printk("isofs_get_block: Kernel tries to allocate a block\n");
+		printk(KERN_DEBUG "%s: Kernel tries to allocate a block\n", __func__);
 		return -EROFS;
 	}
 
@@ -1070,11 +1078,11 @@
 {
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
-	struct buffer_head * bh = NULL;
+	struct buffer_head *bh = NULL;
 	unsigned long block, offset, block_saved, offset_saved;
 	int i = 0;
 	int more_entries = 0;
-	struct iso_directory_record * tmpde = NULL;
+	struct iso_directory_record *tmpde = NULL;
 	struct iso_inode_info *ei = ISOFS_I(inode);
 
 	inode->i_size = 0;
@@ -1089,7 +1097,7 @@
 	offset = ei->i_iget5_offset;
 
 	do {
-		struct iso_directory_record * de;
+		struct iso_directory_record *de;
 		unsigned int de_len;
 
 		if (!bh) {
@@ -1163,10 +1171,9 @@
 	return -EIO;
 
 out_toomany:
-	printk(KERN_INFO "isofs_read_level3_size: "
-		"More than 100 file sections ?!?, aborting...\n"
-	  	"isofs_read_level3_size: inode=%lu\n",
-		inode->i_ino);
+	printk(KERN_INFO "%s: More than 100 file sections ?!?, aborting...\n"
+		"isofs_read_level3_size: inode=%lu\n",
+		__func__, inode->i_ino);
 	goto out;
 }
 
@@ -1177,9 +1184,9 @@
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	unsigned long block;
 	int high_sierra = sbi->s_high_sierra;
-	struct buffer_head * bh = NULL;
-	struct iso_directory_record * de;
-	struct iso_directory_record * tmpde = NULL;
+	struct buffer_head *bh = NULL;
+	struct iso_directory_record *de;
+	struct iso_directory_record *tmpde = NULL;
 	unsigned int de_len;
 	unsigned long offset;
 	struct iso_inode_info *ei = ISOFS_I(inode);
@@ -1199,7 +1206,7 @@
 
 		tmpde = kmalloc(de_len, GFP_KERNEL);
 		if (tmpde == NULL) {
-			printk(KERN_INFO "isofs_read_inode: out of memory\n");
+			printk(KERN_INFO "%s: out of memory\n", __func__);
 			goto fail;
 		}
 		memcpy(tmpde, bh->b_data + offset, frag1);
@@ -1212,24 +1219,26 @@
 	}
 
 	inode->i_ino = isofs_get_ino(ei->i_iget5_block,
-				     ei->i_iget5_offset,
-				     ISOFS_BUFFER_BITS(inode));
+					ei->i_iget5_offset,
+					ISOFS_BUFFER_BITS(inode));
 
 	/* Assume it is a normal-format file unless told otherwise */
 	ei->i_file_format = isofs_file_normal;
 
 	if (de->flags[-high_sierra] & 2) {
 		inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
-		inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
-				       the find utility tries to optimize
-				       if it is 2, and it screws up.  It is
-				       easier to give 1 which tells find to
-				       do it the hard way. */
+		inode->i_nlink = 1;	/*
+					 * Set to 1.  We know there are 2, but
+					 * the find utility tries to optimize
+					 * if it is 2, and it screws up.  It is
+					 * easier to give 1 which tells find to
+					 * do it the hard way.
+					 */
 	} else {
- 		/* Everybody gets to read the file. */
+		/* Everybody gets to read the file. */
 		inode->i_mode = sbi->s_mode;
 		inode->i_nlink = 1;
-	        inode->i_mode |= S_IFREG;
+		inode->i_mode |= S_IFREG;
 	}
 	inode->i_uid = sbi->s_uid;
 	inode->i_gid = sbi->s_gid;
@@ -1239,13 +1248,14 @@
 	ei->i_format_parm[1] = 0;
 	ei->i_format_parm[2] = 0;
 
-	ei->i_section_size = isonum_733 (de->size);
+	ei->i_section_size = isonum_733(de->size);
 	if (de->flags[-high_sierra] & 0x80) {
-		if(isofs_read_level3_size(inode)) goto fail;
+		if(isofs_read_level3_size(inode))
+			goto fail;
 	} else {
 		ei->i_next_section_block = 0;
 		ei->i_next_section_offset = 0;
-		inode->i_size = isonum_733 (de->size);
+		inode->i_size = isonum_733(de->size);
 	}
 
 	/*
@@ -1258,23 +1268,24 @@
 		inode->i_size &= 0x00ffffff;
 
 	if (de->interleave[0]) {
-		printk("Interleaved files not (yet) supported.\n");
+		printk(KERN_DEBUG "ISOFS: Interleaved files not (yet) supported.\n");
 		inode->i_size = 0;
 	}
 
 	/* I have no idea what file_unit_size is used for, so
 	   we will flag it for now */
 	if (de->file_unit_size[0] != 0) {
-		printk("File unit size != 0 for ISO file (%ld).\n",
-		       inode->i_ino);
+		printk(KERN_DEBUG "ISOFS: File unit size != 0 for ISO file (%ld).\n",
+			inode->i_ino);
 	}
 
 	/* I have no idea what other flag bits are used for, so
 	   we will flag it for now */
 #ifdef DEBUG
 	if((de->flags[-high_sierra] & ~2)!= 0){
-		printk("Unusual flag settings for ISO file (%ld %x).\n",
-		       inode->i_ino, de->flags[-high_sierra]);
+		printk(KERN_DEBUG "ISOFS: Unusual flag settings for ISO file "
+				"(%ld %x).\n",
+			inode->i_ino, de->flags[-high_sierra]);
 	}
 #endif
 
@@ -1285,11 +1296,11 @@
 	inode->i_atime.tv_nsec =
 	inode->i_ctime.tv_nsec = 0;
 
-	ei->i_first_extent = (isonum_733 (de->extent) +
-			      isonum_711 (de->ext_attr_length));
+	ei->i_first_extent = (isonum_733(de->extent) +
+			isonum_711(de->ext_attr_length));
 
 	/* Set the number of blocks for stat() - should be done before RR */
-	inode->i_blocks  = (inode->i_size + 511) >> 9;
+	inode->i_blocks = (inode->i_size + 511) >> 9;
 
 	/*
 	 * Now test for possible Rock Ridge extensions which will override
@@ -1306,7 +1317,7 @@
 	/* Install the inode operations vector */
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_fop = &generic_ro_fops;
-		switch ( ei->i_file_format ) {
+		switch (ei->i_file_format) {
 #ifdef CONFIG_ZISOFS
 		case isofs_file_compressed:
 			inode->i_data.a_ops = &zisofs_aops;
@@ -1350,7 +1361,7 @@
 	struct isofs_iget5_callback_data *d =
 		(struct isofs_iget5_callback_data*)data;
 	return (i->i_iget5_block == d->block)
-	       && (i->i_iget5_offset == d->offset);
+		&& (i->i_iget5_offset == d->offset);
 }
 
 static int isofs_iget5_set(struct inode *ino, void *data)
@@ -1384,7 +1395,7 @@
 	hashval = (block << sb->s_blocksize_bits) | offset;
 
 	inode = iget5_locked(sb, hashval, &isofs_iget5_test,
-			     &isofs_iget5_set, &data);
+				&isofs_iget5_set, &data);
 
 	if (inode && (inode->i_state & I_NEW)) {
 		sb->s_op->read_inode(inode);
@@ -1398,7 +1409,7 @@
 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super,
-			   mnt);
+				mnt);
 }
 
 static struct file_system_type iso9660_fs_type = {
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index efe2872..a07e67b 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -1,5 +1,6 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/iso_fs.h>
 #include <asm/unaligned.h>
 
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
index fb8fe7a..92c14b8 100644
--- a/fs/isofs/joliet.c
+++ b/fs/isofs/joliet.c
@@ -80,22 +80,20 @@
 
 	if (utf8) {
 		len = wcsntombs_be(outname, de->name,
-				   de->name_len[0] >> 1, PAGE_SIZE);
+				de->name_len[0] >> 1, PAGE_SIZE);
 	} else {
 		len = uni16_to_x8(outname, (__be16 *) de->name,
-				  de->name_len[0] >> 1, nls);
+				de->name_len[0] >> 1, nls);
 	}
-	if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) {
+	if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1'))
 		len -= 2;
-	}
 
 	/*
 	 * Windows doesn't like periods at the end of a name,
 	 * so neither do we
 	 */
-	while (len >= 2 && (outname[len-1] == '.')) {
+	while (len >= 2 && (outname[len-1] == '.'))
 		len--;
-	}
 
 	return len;
 }
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index c04b3a1..c8c7e51 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -15,7 +15,7 @@
  * some sanity tests.
  */
 static int
-isofs_cmp(struct dentry * dentry, const char * compare, int dlen)
+isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
 {
 	struct qstr qstr;
 
@@ -48,24 +48,24 @@
  */
 static unsigned long
 isofs_find_entry(struct inode *dir, struct dentry *dentry,
-	unsigned long *block_rv, unsigned long* offset_rv,
-	char * tmpname, struct iso_directory_record * tmpde)
+	unsigned long *block_rv, unsigned long *offset_rv,
+	char *tmpname, struct iso_directory_record *tmpde)
 {
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
 	unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
 	unsigned long block, f_pos, offset, block_saved, offset_saved;
-	struct buffer_head * bh = NULL;
+	struct buffer_head *bh = NULL;
 	struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
 
 	if (!ISOFS_I(dir)->i_first_extent)
 		return 0;
-  
+
 	f_pos = 0;
 	offset = 0;
 	block = 0;
 
 	while (f_pos < dir->i_size) {
-		struct iso_directory_record * de;
+		struct iso_directory_record *de;
 		int de_len, match, i, dlen;
 		char *dpnt;
 
@@ -114,7 +114,7 @@
 
 		if (sbi->s_rock &&
 		    ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
-			dlen = i; 	/* possibly -1 */
+			dlen = i;	/* possibly -1 */
 			dpnt = tmpname;
 #ifdef CONFIG_JOLIET
 		} else if (sbi->s_joliet_level) {
@@ -145,8 +145,8 @@
 			isofs_normalize_block_and_offset(de,
 							 &block_saved,
 							 &offset_saved);
-                        *block_rv = block_saved;
-                        *offset_rv = offset_saved;
+			*block_rv = block_saved;
+			*offset_rv = offset_saved;
 			brelse(bh);
 			return 1;
 		}
@@ -155,7 +155,7 @@
 	return 0;
 }
 
-struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	int found;
 	unsigned long block, offset;
@@ -170,9 +170,9 @@
 
 	lock_kernel();
 	found = isofs_find_entry(dir, dentry,
-				 &block, &offset,
-				 page_address(page),
-				 1024 + page_address(page));
+				&block, &offset,
+				page_address(page),
+				1024 + page_address(page));
 	__free_page(page);
 
 	inode = NULL;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 1facfaf..a003d50 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -887,7 +887,8 @@
 	journal->j_committing_transaction = NULL;
 	spin_unlock(&journal->j_state_lock);
 
-	if (commit_transaction->t_checkpoint_list == NULL) {
+	if (commit_transaction->t_checkpoint_list == NULL &&
+	    commit_transaction->t_checkpoint_io_list == NULL) {
 		__journal_drop_transaction(journal, commit_transaction);
 	} else {
 		if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index 824e3b7..8db2fa2 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -68,6 +68,7 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #endif
+#include <linux/log2.h>
 
 static struct kmem_cache *revoke_record_cache;
 static struct kmem_cache *revoke_table_cache;
@@ -211,7 +212,7 @@
 	journal->j_revoke = journal->j_revoke_table[0];
 
 	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+	J_ASSERT(is_power_of_2(hash_size));
 
 	journal->j_revoke->hash_size = hash_size;
 
@@ -238,7 +239,7 @@
 	journal->j_revoke = journal->j_revoke_table[1];
 
 	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+	J_ASSERT(is_power_of_2(hash_size));
 
 	journal->j_revoke->hash_size = hash_size;
 
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 2856e110..c0f59d1 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -896,7 +896,8 @@
 	journal->j_committing_transaction = NULL;
 	spin_unlock(&journal->j_state_lock);
 
-	if (commit_transaction->t_checkpoint_list == NULL) {
+	if (commit_transaction->t_checkpoint_list == NULL &&
+	    commit_transaction->t_checkpoint_io_list == NULL) {
 		__jbd2_journal_drop_transaction(journal, commit_transaction);
 	} else {
 		if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 9246e76..28cac04 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -68,6 +68,7 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #endif
+#include <linux/log2.h>
 
 static struct kmem_cache *jbd2_revoke_record_cache;
 static struct kmem_cache *jbd2_revoke_table_cache;
@@ -212,7 +213,7 @@
 	journal->j_revoke = journal->j_revoke_table[0];
 
 	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+	J_ASSERT(is_power_of_2(hash_size));
 
 	journal->j_revoke->hash_size = hash_size;
 
@@ -239,7 +240,7 @@
 	journal->j_revoke = journal->j_revoke_table[1];
 
 	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+	J_ASSERT(is_power_of_2(hash_size));
 
 	journal->j_revoke->hash_size = hash_size;
 
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index a46101e..65b3a1b 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -435,7 +435,7 @@
 	struct posix_acl *acl;
 	int rc;
 
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		return -EPERM;
 
 	if (value) {
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 0c82dfc..143c553 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -81,6 +81,7 @@
 
 	set_user_nice(current, 10);
 
+	set_freezable();
 	for (;;) {
 		allow_signal(SIGHUP);
 
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 9987127..c253019 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -47,7 +47,7 @@
 	.ioctl =	jffs2_ioctl,
 	.mmap =		generic_file_readonly_mmap,
 	.fsync =	jffs2_fsync,
-	.sendfile =	generic_file_sendfile
+	.splice_read =	generic_file_splice_read,
 };
 
 /* jffs2_file_inode_operations */
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 4884d5e..7b36378 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -210,8 +210,7 @@
  * offset, and the one with the smallest length will come first in the
  * ordering.
  *
- * Returns 0 if the node was inserted
- *         1 if the node is obsolete (because we can't mark it so yet)
+ * Returns 0 if the node was handled (including marking it obsolete)
  *         < 0 an if error occurred
  */
 static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
@@ -229,9 +228,16 @@
 	   check anyway. */
 	if (!tn->fn->size) {
 		if (rii->mdata_tn) {
-			/* We had a candidate mdata node already */
-			dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
-			jffs2_kill_tn(c, rii->mdata_tn);
+			if (rii->mdata_tn->version < tn->version) {
+				/* We had a candidate mdata node already */
+				dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
+				jffs2_kill_tn(c, rii->mdata_tn);
+			} else {
+				dbg_readinode("kill new mdata with ver %d (older than existing %d\n",
+					      tn->version, rii->mdata_tn->version);
+				jffs2_kill_tn(c, tn);
+				return 0;
+			}
 		}
 		rii->mdata_tn = tn;
 		dbg_readinode("keep new mdata with ver %d\n", tn->version);
@@ -565,8 +571,7 @@
  * Helper function for jffs2_get_inode_nodes().
  * It is called every time an directory entry node is found.
  *
- * Returns: 0 on succes;
- * 	    1 if the node should be marked obsolete;
+ * Returns: 0 on success;
  * 	    negative error code on failure.
  */
 static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
@@ -673,8 +678,7 @@
  * Helper function for jffs2_get_inode_nodes().
  * It is called every time an inode node is found.
  *
- * Returns: 0 on success;
- * 	    1 if the node should be marked obsolete;
+ * Returns: 0 on success (possibly after marking a bad node obsolete);
  * 	    negative error code on failure.
  */
 static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
@@ -683,7 +687,7 @@
 {
 	struct jffs2_tmp_dnode_info *tn;
 	uint32_t len, csize;
-	int ret = 1;
+	int ret = 0;
 	uint32_t crc;
 
 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
@@ -712,8 +716,9 @@
 		/* Sanity checks */
 		if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
 		    unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
-				JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
-				jffs2_dbg_dump_node(c, ref_offset(ref));
+			JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
+			jffs2_dbg_dump_node(c, ref_offset(ref));
+			jffs2_mark_node_obsolete(c, ref);
 			goto free_out;
 		}
 
@@ -768,6 +773,7 @@
 			if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
 				JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
 					ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc));
+				jffs2_mark_node_obsolete(c, ref);
 				goto free_out;
 			}
 
@@ -847,7 +853,6 @@
  * It is called every time an unknown node is found.
  *
  * Returns: 0 on success;
- * 	    1 if the node should be marked obsolete;
  * 	    negative error code on failure.
  */
 static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
@@ -1044,7 +1049,8 @@
 
 		case JFFS2_NODETYPE_DIRENT:
 
-			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) {
+			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) &&
+			    len < sizeof(struct jffs2_raw_dirent)) {
 				err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf);
 				if (unlikely(err))
 					goto free_out;
@@ -1058,7 +1064,8 @@
 
 		case JFFS2_NODETYPE_INODE:
 
-			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) {
+			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) &&
+			    len < sizeof(struct jffs2_raw_inode)) {
 				err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf);
 				if (unlikely(err))
 					goto free_out;
@@ -1071,17 +1078,15 @@
 			break;
 
 		default:
-			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) {
+			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) &&
+			    len < sizeof(struct jffs2_unknown_node)) {
 				err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf);
 				if (unlikely(err))
 					goto free_out;
 			}
 
 			err = read_unknown(c, ref, &node->u);
-			if (err == 1) {
-				jffs2_mark_node_obsolete(c, ref);
-				break;
-			} else if (unlikely(err))
+			if (unlikely(err))
 				goto free_out;
 
 		}
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 6488af4..e220d3b 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -19,7 +19,7 @@
 #include <linux/mount.h>
 #include <linux/jffs2.h>
 #include <linux/pagemap.h>
-#include <linux/mtd/mtd.h>
+#include <linux/mtd/super.h>
 #include <linux/ctype.h>
 #include <linux/namei.h>
 #include "compr.h"
@@ -75,69 +75,27 @@
 	.sync_fs =	jffs2_sync_fs,
 };
 
-static int jffs2_sb_compare(struct super_block *sb, void *data)
+/*
+ * fill in the superblock
+ */
+static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 {
-	struct jffs2_sb_info *p = data;
-	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
-
-	/* The superblocks are considered to be equivalent if the underlying MTD
-	   device is the same one */
-	if (c->mtd == p->mtd) {
-		D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name));
-		return 1;
-	} else {
-		D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n",
-			  c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name));
-		return 0;
-	}
-}
-
-static int jffs2_sb_set(struct super_block *sb, void *data)
-{
-	struct jffs2_sb_info *p = data;
-
-	/* For persistence of NFS exports etc. we use the same s_dev
-	   each time we mount the device, don't just use an anonymous
-	   device */
-	sb->s_fs_info = p;
-	p->os_priv = sb;
-	sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index);
-
-	return 0;
-}
-
-static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
-			    int flags, const char *dev_name,
-			    void *data, struct mtd_info *mtd,
-			    struct vfsmount *mnt)
-{
-	struct super_block *sb;
 	struct jffs2_sb_info *c;
-	int ret;
+
+	D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():"
+		  " New superblock for device %d (\"%s\")\n",
+		  sb->s_mtd->index, sb->s_mtd->name));
 
 	c = kzalloc(sizeof(*c), GFP_KERNEL);
 	if (!c)
 		return -ENOMEM;
-	c->mtd = mtd;
 
-	sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c);
+	c->mtd = sb->s_mtd;
+	c->os_priv = sb;
+	sb->s_fs_info = c;
 
-	if (IS_ERR(sb))
-		goto out_error;
-
-	if (sb->s_root) {
-		/* New mountpoint for JFFS2 which is already mounted */
-		D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n",
-			  mtd->index, mtd->name));
-		ret = simple_set_mnt(mnt, sb);
-		goto out_put;
-	}
-
-	D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n",
-		  mtd->index, mtd->name));
-
-	/* Initialize JFFS2 superblock locks, the further initialization will be
-	 * done later */
+	/* Initialize JFFS2 superblock locks, the further initialization will
+	 * be done later */
 	init_MUTEX(&c->alloc_sem);
 	init_MUTEX(&c->erase_free_sem);
 	init_waitqueue_head(&c->erase_wait);
@@ -146,133 +104,20 @@
 	spin_lock_init(&c->inocache_lock);
 
 	sb->s_op = &jffs2_super_operations;
-	sb->s_flags = flags | MS_NOATIME;
+	sb->s_flags = sb->s_flags | MS_NOATIME;
 	sb->s_xattr = jffs2_xattr_handlers;
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
 	sb->s_flags |= MS_POSIXACL;
 #endif
-	ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
-
-	if (ret) {
-		/* Failure case... */
-		up_write(&sb->s_umount);
-		deactivate_super(sb);
-		return ret;
-	}
-
-	sb->s_flags |= MS_ACTIVE;
-	return simple_set_mnt(mnt, sb);
-
-out_error:
-	ret = PTR_ERR(sb);
- out_put:
-	kfree(c);
-	put_mtd_device(mtd);
-
-	return ret;
-}
-
-static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
-			      int flags, const char *dev_name,
-			      void *data, int mtdnr,
-			      struct vfsmount *mnt)
-{
-	struct mtd_info *mtd;
-
-	mtd = get_mtd_device(NULL, mtdnr);
-	if (IS_ERR(mtd)) {
-		D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr));
-		return PTR_ERR(mtd);
-	}
-
-	return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
+	return jffs2_do_fill_super(sb, data, silent);
 }
 
 static int jffs2_get_sb(struct file_system_type *fs_type,
 			int flags, const char *dev_name,
 			void *data, struct vfsmount *mnt)
 {
-	int err;
-	struct nameidata nd;
-	int mtdnr;
-
-	if (!dev_name)
-		return -EINVAL;
-
-	D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name));
-
-	/* The preferred way of mounting in future; especially when
-	   CONFIG_BLK_DEV is implemented - we specify the underlying
-	   MTD device by number or by name, so that we don't require
-	   block device support to be present in the kernel. */
-
-	/* FIXME: How to do the root fs this way? */
-
-	if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
-		/* Probably mounting without the blkdev crap */
-		if (dev_name[3] == ':') {
-			struct mtd_info *mtd;
-
-			/* Mount by MTD device name */
-			D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4));
-			for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
-				mtd = get_mtd_device(NULL, mtdnr);
-				if (!IS_ERR(mtd)) {
-					if (!strcmp(mtd->name, dev_name+4))
-						return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
-					put_mtd_device(mtd);
-				}
-			}
-			printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4);
-		} else if (isdigit(dev_name[3])) {
-			/* Mount by MTD device number name */
-			char *endptr;
-
-			mtdnr = simple_strtoul(dev_name+3, &endptr, 0);
-			if (!*endptr) {
-				/* It was a valid number */
-				D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr));
-				return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
-			}
-		}
-	}
-
-	/* Try the old way - the hack where we allowed users to mount
-	   /dev/mtdblock$(n) but didn't actually _use_ the blkdev */
-
-	err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
-
-	D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n",
-		  err, nd.dentry->d_inode));
-
-	if (err)
-		return err;
-
-	err = -EINVAL;
-
-	if (!S_ISBLK(nd.dentry->d_inode->i_mode))
-		goto out;
-
-	if (nd.mnt->mnt_flags & MNT_NODEV) {
-		err = -EACCES;
-		goto out;
-	}
-
-	if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) {
-		if (!(flags & MS_SILENT))
-			printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n",
-			       dev_name);
-		goto out;
-	}
-
-	mtdnr = iminor(nd.dentry->d_inode);
-	path_release(&nd);
-
-	return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
-
-out:
-	path_release(&nd);
-	return err;
+	return get_sb_mtd(fs_type, flags, dev_name, data, jffs2_fill_super,
+			  mnt);
 }
 
 static void jffs2_put_super (struct super_block *sb)
@@ -307,8 +152,7 @@
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
 	if (!(sb->s_flags & MS_RDONLY))
 		jffs2_stop_garbage_collect_thread(c);
-	generic_shutdown_super(sb);
-	put_mtd_device(c->mtd);
+	kill_mtd_super(sb);
 	kfree(c);
 }
 
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 78fc088..e486659 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -754,6 +754,10 @@
 		list_del(&xd->xindex);
 		jffs2_free_xattr_datum(xd);
 	}
+	list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
+		list_del(&xd->xindex);
+		jffs2_free_xattr_datum(xd);
+	}
 }
 
 #define XREF_TMPHASH_SIZE	(128)
@@ -825,7 +829,7 @@
 			   ref->xd and ref->ic are not valid yet. */
 			xd = jffs2_find_xattr_datum(c, ref->xid);
 			ic = jffs2_get_ino_cache(c, ref->ino);
-			if (!xd || !ic) {
+			if (!xd || !ic || !ic->nlink) {
 				dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
 					  ref->ino, ref->xid, ref->xseqno);
 				ref->xseqno |= XREF_DELETE_MARKER;
diff --git a/fs/jfs/endian24.h b/fs/jfs/endian24.h
index 79494c4..fa92f7f 100644
--- a/fs/jfs/endian24.h
+++ b/fs/jfs/endian24.h
@@ -29,7 +29,7 @@
 	__u32 __x = (x); \
 	((__u32)( \
 		((__x & (__u32)0x000000ffUL) << 16) | \
-		 (__x & (__u32)0x0000ff00UL)        | \
+		 (__x & (__u32)0x0000ff00UL)	    | \
 		((__x & (__u32)0x00ff0000UL) >> 16) )); \
 })
 
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index f7f8eff..87eb936 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -108,7 +108,6 @@
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 	.fsync		= jfs_fsync,
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
index fe063af..3c8663b 100644
--- a/fs/jfs/ioctl.c
+++ b/fs/jfs/ioctl.c
@@ -69,7 +69,7 @@
 		if (IS_RDONLY(inode))
 			return -EROFS;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(flags, (int __user *) arg))
diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
index 9c5d596..887f575 100644
--- a/fs/jfs/jfs_debug.c
+++ b/fs/jfs/jfs_debug.c
@@ -26,34 +26,6 @@
 #include "jfs_filsys.h"
 #include "jfs_debug.h"
 
-#ifdef CONFIG_JFS_DEBUG
-void dump_mem(char *label, void *data, int length)
-{
-	int i, j;
-	int *intptr = data;
-	char *charptr = data;
-	char buf[10], line[80];
-
-	printk("%s: dump of %d bytes of data at 0x%p\n\n", label, length,
-	       data);
-	for (i = 0; i < length; i += 16) {
-		line[0] = 0;
-		for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
-			sprintf(buf, " %08x", intptr[i / 4 + j]);
-			strcat(line, buf);
-		}
-		buf[0] = ' ';
-		buf[2] = 0;
-		for (j = 0; (j < 16) && (i + j < length); j++) {
-			buf[1] =
-			    isprint(charptr[i + j]) ? charptr[i + j] : '.';
-			strcat(line, buf);
-		}
-		printk("%s\n", line);
-	}
-}
-#endif
-
 #ifdef PROC_FS_JFS /* see jfs_debug.h */
 
 static struct proc_dir_entry *base;
diff --git a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
index 7378798..044c1e6 100644
--- a/fs/jfs/jfs_debug.h
+++ b/fs/jfs/jfs_debug.h
@@ -62,7 +62,6 @@
 
 extern int jfsloglevel;
 
-extern void dump_mem(char *label, void *data, int length);
 extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
 
 /* information message: e.g., configuration, major event */
@@ -94,7 +93,6 @@
  *	---------
  */
 #else				/* CONFIG_JFS_DEBUG */
-#define dump_mem(label,data,length) do {} while (0)
 #define ASSERT(p) do {} while (0)
 #define jfs_info(fmt, arg...) do {} while (0)
 #define jfs_debug(fmt, arg...) do {} while (0)
diff --git a/fs/jfs/jfs_dinode.h b/fs/jfs/jfs_dinode.h
index 40b2011..c387540 100644
--- a/fs/jfs/jfs_dinode.h
+++ b/fs/jfs/jfs_dinode.h
@@ -19,23 +19,23 @@
 #define _H_JFS_DINODE
 
 /*
- *      jfs_dinode.h: on-disk inode manager
+ *	jfs_dinode.h: on-disk inode manager
  */
 
-#define INODESLOTSIZE           128
-#define L2INODESLOTSIZE         7
-#define log2INODESIZE           9	/* log2(bytes per dinode) */
+#define INODESLOTSIZE		128
+#define L2INODESLOTSIZE		7
+#define log2INODESIZE		9	/* log2(bytes per dinode) */
 
 
 /*
- *      on-disk inode : 512 bytes
+ *	on-disk inode : 512 bytes
  *
  * note: align 64-bit fields on 8-byte boundary.
  */
 struct dinode {
 	/*
-	 *      I. base area (128 bytes)
-	 *      ------------------------
+	 *	I. base area (128 bytes)
+	 *	------------------------
 	 *
 	 * define generic/POSIX attributes
 	 */
@@ -70,16 +70,16 @@
 	__le32 di_acltype;	/* 4: Type of ACL */
 
 	/*
-	 *      Extension Areas.
+	 *	Extension Areas.
 	 *
-	 *      Historically, the inode was partitioned into 4 128-byte areas,
-	 *      the last 3 being defined as unions which could have multiple
-	 *      uses.  The first 96 bytes had been completely unused until
-	 *      an index table was added to the directory.  It is now more
-	 *      useful to describe the last 3/4 of the inode as a single
-	 *      union.  We would probably be better off redesigning the
-	 *      entire structure from scratch, but we don't want to break
-	 *      commonality with OS/2's JFS at this time.
+	 *	Historically, the inode was partitioned into 4 128-byte areas,
+	 *	the last 3 being defined as unions which could have multiple
+	 *	uses.  The first 96 bytes had been completely unused until
+	 *	an index table was added to the directory.  It is now more
+	 *	useful to describe the last 3/4 of the inode as a single
+	 *	union.  We would probably be better off redesigning the
+	 *	entire structure from scratch, but we don't want to break
+	 *	commonality with OS/2's JFS at this time.
 	 */
 	union {
 		struct {
@@ -95,7 +95,7 @@
 		} _dir;					/* (384) */
 #define di_dirtable	u._dir._table
 #define di_dtroot	u._dir._dtroot
-#define di_parent       di_dtroot.header.idotdot
+#define di_parent	di_dtroot.header.idotdot
 #define di_DASD		di_dtroot.header.DASD
 
 		struct {
@@ -127,14 +127,14 @@
 #define di_inlinedata	u._file._u2._special._u
 #define di_rdev		u._file._u2._special._u._rdev
 #define di_fastsymlink	u._file._u2._special._u._fastsymlink
-#define di_inlineea     u._file._u2._special._inlineea
+#define di_inlineea	u._file._u2._special._inlineea
 	} u;
 };
 
 /* extended mode bits (on-disk inode di_mode) */
-#define IFJOURNAL       0x00010000	/* journalled file */
-#define ISPARSE         0x00020000	/* sparse file enabled */
-#define INLINEEA        0x00040000	/* inline EA area free */
+#define IFJOURNAL	0x00010000	/* journalled file */
+#define ISPARSE		0x00020000	/* sparse file enabled */
+#define INLINEEA	0x00040000	/* inline EA area free */
 #define ISWAPFILE	0x00800000	/* file open for pager swap space */
 
 /* more extended mode bits: attributes for OS/2 */
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index f3b1ebb..e198506 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -154,12 +154,12 @@
  *		the in-core descriptor is initialized from disk.
  *
  * PARAMETERS:
- *      ipbmap	-  pointer to in-core inode for the block map.
+ *	ipbmap	- pointer to in-core inode for the block map.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOMEM	- insufficient memory
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOMEM	- insufficient memory
+ *	-EIO	- i/o error
  */
 int dbMount(struct inode *ipbmap)
 {
@@ -232,11 +232,11 @@
  *		the memory for this descriptor is freed.
  *
  * PARAMETERS:
- *      ipbmap	-  pointer to in-core inode for the block map.
+ *	ipbmap	- pointer to in-core inode for the block map.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  */
 int dbUnmount(struct inode *ipbmap, int mounterror)
 {
@@ -320,13 +320,13 @@
  *		at a time.
  *
  * PARAMETERS:
- *      ip	-  pointer to in-core inode;
- *      blkno	-  starting block number to be freed.
- *      nblocks	-  number of blocks to be freed.
+ *	ip	- pointer to in-core inode;
+ *	blkno	- starting block number to be freed.
+ *	nblocks	- number of blocks to be freed.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  */
 int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
 {
@@ -395,23 +395,23 @@
 /*
  * NAME:	dbUpdatePMap()
  *
- * FUNCTION:    update the allocation state (free or allocate) of the
+ * FUNCTION:	update the allocation state (free or allocate) of the
  *		specified block range in the persistent block allocation map.
  *
  *		the blocks will be updated in the persistent map one
  *		dmap at a time.
  *
  * PARAMETERS:
- *      ipbmap	-  pointer to in-core inode for the block map.
- *      free	-  'true' if block range is to be freed from the persistent
- *		   map; 'false' if it is to   be allocated.
- *      blkno	-  starting block number of the range.
- *      nblocks	-  number of contiguous blocks in the range.
- *      tblk	-  transaction block;
+ *	ipbmap	- pointer to in-core inode for the block map.
+ *	free	- 'true' if block range is to be freed from the persistent
+ *		  map; 'false' if it is to be allocated.
+ *	blkno	- starting block number of the range.
+ *	nblocks	- number of contiguous blocks in the range.
+ *	tblk	- transaction block;
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  */
 int
 dbUpdatePMap(struct inode *ipbmap,
@@ -573,7 +573,7 @@
 /*
  * NAME:	dbNextAG()
  *
- * FUNCTION:    find the preferred allocation group for new allocations.
+ * FUNCTION:	find the preferred allocation group for new allocations.
  *
  *		Within the allocation groups, we maintain a preferred
  *		allocation group which consists of a group with at least
@@ -589,10 +589,10 @@
  *		empty ags around for large allocations.
  *
  * PARAMETERS:
- *      ipbmap	-  pointer to in-core inode for the block map.
+ *	ipbmap	- pointer to in-core inode for the block map.
  *
  * RETURN VALUES:
- *      the preferred allocation group number.
+ *	the preferred allocation group number.
  */
 int dbNextAG(struct inode *ipbmap)
 {
@@ -656,7 +656,7 @@
 /*
  * NAME:	dbAlloc()
  *
- * FUNCTION:    attempt to allocate a specified number of contiguous free
+ * FUNCTION:	attempt to allocate a specified number of contiguous free
  *		blocks from the working allocation block map.
  *
  *		the block allocation policy uses hints and a multi-step
@@ -680,16 +680,16 @@
  *		size or requests that specify no hint value.
  *
  * PARAMETERS:
- *      ip	-  pointer to in-core inode;
- *      hint	- allocation hint.
- *      nblocks	- number of contiguous blocks in the range.
- *      results	- on successful return, set to the starting block number
+ *	ip	- pointer to in-core inode;
+ *	hint	- allocation hint.
+ *	nblocks	- number of contiguous blocks in the range.
+ *	results	- on successful return, set to the starting block number
  *		  of the newly allocated contiguous range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  */
 int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
 {
@@ -706,12 +706,6 @@
 	/* assert that nblocks is valid */
 	assert(nblocks > 0);
 
-#ifdef _STILL_TO_PORT
-	/* DASD limit check                                     F226941 */
-	if (OVER_LIMIT(ip, nblocks))
-		return -ENOSPC;
-#endif				/* _STILL_TO_PORT */
-
 	/* get the log2 number of blocks to be allocated.
 	 * if the number of blocks is not a log2 multiple,
 	 * it will be rounded up to the next log2 multiple.
@@ -720,7 +714,6 @@
 
 	bmp = JFS_SBI(ip->i_sb)->bmap;
 
-//retry:        /* serialize w.r.t.extendfs() */
 	mapSize = bmp->db_mapsize;
 
 	/* the hint should be within the map */
@@ -879,17 +872,17 @@
 /*
  * NAME:	dbAllocExact()
  *
- * FUNCTION:    try to allocate the requested extent;
+ * FUNCTION:	try to allocate the requested extent;
  *
  * PARAMETERS:
- *      ip	- pointer to in-core inode;
- *      blkno	- extent address;
- *      nblocks	- extent length;
+ *	ip	- pointer to in-core inode;
+ *	blkno	- extent address;
+ *	nblocks	- extent length;
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  */
 int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
 {
@@ -946,7 +939,7 @@
 /*
  * NAME:	dbReAlloc()
  *
- * FUNCTION:    attempt to extend a current allocation by a specified
+ * FUNCTION:	attempt to extend a current allocation by a specified
  *		number of blocks.
  *
  *		this routine attempts to satisfy the allocation request
@@ -959,21 +952,21 @@
  *		number of blocks required.
  *
  * PARAMETERS:
- *      ip	    -  pointer to in-core inode requiring allocation.
- *      blkno	    -  starting block of the current allocation.
- *      nblocks	    -  number of contiguous blocks within the current
+ *	ip	    -  pointer to in-core inode requiring allocation.
+ *	blkno	    -  starting block of the current allocation.
+ *	nblocks	    -  number of contiguous blocks within the current
  *		       allocation.
- *      addnblocks  -  number of blocks to add to the allocation.
- *      results	-      on successful return, set to the starting block number
+ *	addnblocks  -  number of blocks to add to the allocation.
+ *	results	-      on successful return, set to the starting block number
  *		       of the existing allocation if the existing allocation
  *		       was extended in place or to a newly allocated contiguous
  *		       range if the existing allocation could not be extended
  *		       in place.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  */
 int
 dbReAlloc(struct inode *ip,
@@ -1004,7 +997,7 @@
 /*
  * NAME:	dbExtend()
  *
- * FUNCTION:    attempt to extend a current allocation by a specified
+ * FUNCTION:	attempt to extend a current allocation by a specified
  *		number of blocks.
  *
  *		this routine attempts to satisfy the allocation request
@@ -1013,16 +1006,16 @@
  *		immediately following the current allocation.
  *
  * PARAMETERS:
- *      ip	    -  pointer to in-core inode requiring allocation.
- *      blkno	    -  starting block of the current allocation.
- *      nblocks	    -  number of contiguous blocks within the current
+ *	ip	    -  pointer to in-core inode requiring allocation.
+ *	blkno	    -  starting block of the current allocation.
+ *	nblocks	    -  number of contiguous blocks within the current
  *		       allocation.
- *      addnblocks  -  number of blocks to add to the allocation.
+ *	addnblocks  -  number of blocks to add to the allocation.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  */
 static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
 {
@@ -1109,19 +1102,19 @@
 /*
  * NAME:	dbAllocNext()
  *
- * FUNCTION:    attempt to allocate the blocks of the specified block
+ * FUNCTION:	attempt to allocate the blocks of the specified block
  *		range within a dmap.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap.
- *      blkno	-  starting block number of the range.
- *      nblocks	-  number of contiguous free blocks of the range.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap.
+ *	blkno	-  starting block number of the range.
+ *	nblocks	-  number of contiguous free blocks of the range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) held on entry/exit;
  */
@@ -1233,7 +1226,7 @@
 /*
  * NAME:	dbAllocNear()
  *
- * FUNCTION:    attempt to allocate a number of contiguous free blocks near
+ * FUNCTION:	attempt to allocate a number of contiguous free blocks near
  *		a specified block (hint) within a dmap.
  *
  *		starting with the dmap leaf that covers the hint, we'll
@@ -1242,18 +1235,18 @@
  *		the desired free space.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap.
- *      blkno	-  block number to allocate near.
- *      nblocks	-  actual number of contiguous free blocks desired.
- *      l2nb	-  log2 number of contiguous free blocks desired.
- *      results	-  on successful return, set to the starting block number
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap.
+ *	blkno	-  block number to allocate near.
+ *	nblocks	-  actual number of contiguous free blocks desired.
+ *	l2nb	-  log2 number of contiguous free blocks desired.
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) held on entry/exit;
  */
@@ -1316,7 +1309,7 @@
 /*
  * NAME:	dbAllocAG()
  *
- * FUNCTION:    attempt to allocate the specified number of contiguous
+ * FUNCTION:	attempt to allocate the specified number of contiguous
  *		free blocks within the specified allocation group.
  *
  *		unless the allocation group size is equal to the number
@@ -1353,17 +1346,17 @@
  *		the allocation group.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
+ *	bmp	-  pointer to bmap descriptor
  *	agno	- allocation group number.
- *      nblocks	-  actual number of contiguous free blocks desired.
- *      l2nb	-  log2 number of contiguous free blocks desired.
- *      results	-  on successful return, set to the starting block number
+ *	nblocks	-  actual number of contiguous free blocks desired.
+ *	l2nb	-  log2 number of contiguous free blocks desired.
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * note: IWRITE_LOCK(ipmap) held on entry/exit;
  */
@@ -1546,7 +1539,7 @@
 /*
  * NAME:	dbAllocAny()
  *
- * FUNCTION:    attempt to allocate the specified number of contiguous
+ * FUNCTION:	attempt to allocate the specified number of contiguous
  *		free blocks anywhere in the file system.
  *
  *		dbAllocAny() attempts to find the sufficient free space by
@@ -1556,16 +1549,16 @@
  *		desired free space is allocated.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      nblocks	 -  actual number of contiguous free blocks desired.
- *      l2nb	 -  log2 number of contiguous free blocks desired.
- *      results	-  on successful return, set to the starting block number
+ *	bmp	-  pointer to bmap descriptor
+ *	nblocks	 -  actual number of contiguous free blocks desired.
+ *	l2nb	 -  log2 number of contiguous free blocks desired.
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -1598,9 +1591,9 @@
 /*
  * NAME:	dbFindCtl()
  *
- * FUNCTION:    starting at a specified dmap control page level and block
+ * FUNCTION:	starting at a specified dmap control page level and block
  *		number, search down the dmap control levels for a range of
- *	        contiguous free blocks large enough to satisfy an allocation
+ *		contiguous free blocks large enough to satisfy an allocation
  *		request for the specified number of free blocks.
  *
  *		if sufficient contiguous free blocks are found, this routine
@@ -1609,17 +1602,17 @@
  *		is sufficient in size.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      level	-  starting dmap control page level.
- *      l2nb	-  log2 number of contiguous free blocks desired.
- *      *blkno	-  on entry, starting block number for conducting the search.
+ *	bmp	-  pointer to bmap descriptor
+ *	level	-  starting dmap control page level.
+ *	l2nb	-  log2 number of contiguous free blocks desired.
+ *	*blkno	-  on entry, starting block number for conducting the search.
  *		   on successful return, the first block within a dmap page
  *		   that contains or starts a range of contiguous free blocks.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -1699,7 +1692,7 @@
 /*
  * NAME:	dbAllocCtl()
  *
- * FUNCTION:    attempt to allocate a specified number of contiguous
+ * FUNCTION:	attempt to allocate a specified number of contiguous
  *		blocks starting within a specific dmap.
  *
  *		this routine is called by higher level routines that search
@@ -1726,18 +1719,18 @@
  *		first dmap (i.e. blkno).
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      nblocks	 -  actual number of contiguous free blocks to allocate.
- *      l2nb	 -  log2 number of contiguous free blocks to allocate.
- *      blkno	 -  starting block number of the dmap to start the allocation
+ *	bmp	-  pointer to bmap descriptor
+ *	nblocks	 -  actual number of contiguous free blocks to allocate.
+ *	l2nb	 -  log2 number of contiguous free blocks to allocate.
+ *	blkno	 -  starting block number of the dmap to start the allocation
  *		    from.
- *      results	-  on successful return, set to the starting block number
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -1870,7 +1863,7 @@
 /*
  * NAME:	dbAllocDmapLev()
  *
- * FUNCTION:    attempt to allocate a specified number of contiguous blocks
+ * FUNCTION:	attempt to allocate a specified number of contiguous blocks
  *		from a specified dmap.
  *
  *		this routine checks if the contiguous blocks are available.
@@ -1878,17 +1871,17 @@
  *		returned.
  *
  * PARAMETERS:
- *      mp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to attempt to allocate blocks from.
- *      l2nb	-  log2 number of contiguous block desired.
- *      nblocks	-  actual number of contiguous block desired.
- *      results	-  on successful return, set to the starting block number
+ *	mp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to attempt to allocate blocks from.
+ *	l2nb	-  log2 number of contiguous block desired.
+ *	nblocks	-  actual number of contiguous block desired.
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap), e.g., from dbAlloc(), or
  *	IWRITE_LOCK(ipbmap), e.g., dbAllocCtl(), held on entry/exit;
@@ -1933,7 +1926,7 @@
 /*
  * NAME:	dbAllocDmap()
  *
- * FUNCTION:    adjust the disk allocation map to reflect the allocation
+ * FUNCTION:	adjust the disk allocation map to reflect the allocation
  *		of a specified block range within a dmap.
  *
  *		this routine allocates the specified blocks from the dmap
@@ -1946,14 +1939,14 @@
  *		covers this dmap.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to allocate the block range from.
- *      blkno	-  starting block number of the block to be allocated.
- *      nblocks	-  number of blocks to be allocated.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to allocate the block range from.
+ *	blkno	-  starting block number of the block to be allocated.
+ *	nblocks	-  number of blocks to be allocated.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -1989,7 +1982,7 @@
 /*
  * NAME:	dbFreeDmap()
  *
- * FUNCTION:    adjust the disk allocation map to reflect the allocation
+ * FUNCTION:	adjust the disk allocation map to reflect the allocation
  *		of a specified block range within a dmap.
  *
  *		this routine frees the specified blocks from the dmap through
@@ -1997,18 +1990,18 @@
  *		causes the maximum string of free blocks within the dmap to
  *		change (i.e. the value of the root of the dmap's dmtree), this
  *		routine will cause this change to be reflected up through the
- *	        appropriate levels of the dmap control pages by a call to
+ *		appropriate levels of the dmap control pages by a call to
  *		dbAdjCtl() for the L0 dmap control page that covers this dmap.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to free the block range from.
- *      blkno	-  starting block number of the block to be freed.
- *      nblocks	-  number of blocks to be freed.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to free the block range from.
+ *	blkno	-  starting block number of the block to be freed.
+ *	nblocks	-  number of blocks to be freed.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -2055,7 +2048,7 @@
 /*
  * NAME:	dbAllocBits()
  *
- * FUNCTION:    allocate a specified block range from a dmap.
+ * FUNCTION:	allocate a specified block range from a dmap.
  *
  *		this routine updates the dmap to reflect the working
  *		state allocation of the specified block range. it directly
@@ -2065,10 +2058,10 @@
  *		dmap's dmtree, as a whole, to reflect the allocated range.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to allocate bits from.
- *      blkno	-  starting block number of the bits to be allocated.
- *      nblocks	-  number of bits to be allocated.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to allocate bits from.
+ *	blkno	-  starting block number of the bits to be allocated.
+ *	nblocks	-  number of bits to be allocated.
  *
  * RETURN VALUES: none
  *
@@ -2149,7 +2142,7 @@
 			 * the allocated words.
 			 */
 			for (; nwords > 0; nwords -= nw) {
-			        if (leaf[word] < BUDMIN) {
+				if (leaf[word] < BUDMIN) {
 					jfs_error(bmp->db_ipbmap->i_sb,
 						  "dbAllocBits: leaf page "
 						  "corrupt");
@@ -2202,7 +2195,7 @@
 /*
  * NAME:	dbFreeBits()
  *
- * FUNCTION:    free a specified block range from a dmap.
+ * FUNCTION:	free a specified block range from a dmap.
  *
  *		this routine updates the dmap to reflect the working
  *		state allocation of the specified block range. it directly
@@ -2212,10 +2205,10 @@
  *		dmtree, as a whole, to reflect the deallocated range.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to free bits from.
- *      blkno	-  starting block number of the bits to be freed.
- *      nblocks	-  number of bits to be freed.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to free bits from.
+ *	blkno	-  starting block number of the bits to be freed.
+ *	nblocks	-  number of bits to be freed.
  *
  * RETURN VALUES: 0 for success
  *
@@ -2388,19 +2381,19 @@
  *		the new root value and the next dmap control page level to
  *		be adjusted.
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      blkno	-  the first block of a block range within a dmap.  it is
+ *	bmp	-  pointer to bmap descriptor
+ *	blkno	-  the first block of a block range within a dmap.  it is
  *		   the allocation or deallocation of this block range that
  *		   requires the dmap control page to be adjusted.
- *      newval	-  the new value of the lower level dmap or dmap control
+ *	newval	-  the new value of the lower level dmap or dmap control
  *		   page root.
- *      alloc	-  'true' if adjustment is due to an allocation.
- *      level	-  current level of dmap control page (i.e. L0, L1, L2) to
+ *	alloc	-  'true' if adjustment is due to an allocation.
+ *	level	-  current level of dmap control page (i.e. L0, L1, L2) to
  *		   be adjusted.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -2544,16 +2537,16 @@
 /*
  * NAME:	dbSplit()
  *
- * FUNCTION:    update the leaf of a dmtree with a new value, splitting
+ * FUNCTION:	update the leaf of a dmtree with a new value, splitting
  *		the leaf from the binary buddy system of the dmtree's
  *		leaves, as required.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree containing the leaf.
- *      leafno	- the number of the leaf to be updated.
- *      splitsz	- the size the binary buddy system starting at the leaf
+ *	tp	- pointer to the tree containing the leaf.
+ *	leafno	- the number of the leaf to be updated.
+ *	splitsz	- the size the binary buddy system starting at the leaf
  *		  must be split to, specified as the log2 number of blocks.
- *      newval	- the new value for the leaf.
+ *	newval	- the new value for the leaf.
  *
  * RETURN VALUES: none
  *
@@ -2600,7 +2593,7 @@
 /*
  * NAME:	dbBackSplit()
  *
- * FUNCTION:    back split the binary buddy system of dmtree leaves
+ * FUNCTION:	back split the binary buddy system of dmtree leaves
  *		that hold a specified leaf until the specified leaf
  *		starts its own binary buddy system.
  *
@@ -2617,8 +2610,8 @@
  *		in which a previous join operation must be backed out.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree containing the leaf.
- *      leafno	- the number of the leaf to be updated.
+ *	tp	- pointer to the tree containing the leaf.
+ *	leafno	- the number of the leaf to be updated.
  *
  * RETURN VALUES: none
  *
@@ -2692,14 +2685,14 @@
 /*
  * NAME:	dbJoin()
  *
- * FUNCTION:    update the leaf of a dmtree with a new value, joining
+ * FUNCTION:	update the leaf of a dmtree with a new value, joining
  *		the leaf with other leaves of the dmtree into a multi-leaf
  *		binary buddy system, as required.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree containing the leaf.
- *      leafno	- the number of the leaf to be updated.
- *      newval	- the new value for the leaf.
+ *	tp	- pointer to the tree containing the leaf.
+ *	leafno	- the number of the leaf to be updated.
+ *	newval	- the new value for the leaf.
  *
  * RETURN VALUES: none
  */
@@ -2785,15 +2778,15 @@
 /*
  * NAME:	dbAdjTree()
  *
- * FUNCTION:    update a leaf of a dmtree with a new value, adjusting
+ * FUNCTION:	update a leaf of a dmtree with a new value, adjusting
  *		the dmtree, as required, to reflect the new leaf value.
  *		the combination of any buddies must already be done before
  *		this is called.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree to be adjusted.
- *      leafno	- the number of the leaf to be updated.
- *      newval	- the new value for the leaf.
+ *	tp	- pointer to the tree to be adjusted.
+ *	leafno	- the number of the leaf to be updated.
+ *	newval	- the new value for the leaf.
  *
  * RETURN VALUES: none
  */
@@ -2852,7 +2845,7 @@
 /*
  * NAME:	dbFindLeaf()
  *
- * FUNCTION:    search a dmtree_t for sufficient free blocks, returning
+ * FUNCTION:	search a dmtree_t for sufficient free blocks, returning
  *		the index of a leaf describing the free blocks if
  *		sufficient free blocks are found.
  *
@@ -2861,15 +2854,15 @@
  *		free space.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree to be searched.
- *      l2nb	- log2 number of free blocks to search for.
+ *	tp	- pointer to the tree to be searched.
+ *	l2nb	- log2 number of free blocks to search for.
  *	leafidx	- return pointer to be set to the index of the leaf
  *		  describing at least l2nb free blocks if sufficient
  *		  free blocks are found.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient free blocks.
+ *	0	- success
+ *	-ENOSPC	- insufficient free blocks.
  */
 static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
 {
@@ -2916,18 +2909,18 @@
 /*
  * NAME:	dbFindBits()
  *
- * FUNCTION:    find a specified number of binary buddy free bits within a
+ * FUNCTION:	find a specified number of binary buddy free bits within a
  *		dmap bitmap word value.
  *
  *		this routine searches the bitmap value for (1 << l2nb) free
  *		bits at (1 << l2nb) alignments within the value.
  *
  * PARAMETERS:
- *      word	-  dmap bitmap word value.
- *      l2nb	-  number of free bits specified as a log2 number.
+ *	word	-  dmap bitmap word value.
+ *	l2nb	-  number of free bits specified as a log2 number.
  *
  * RETURN VALUES:
- *      starting bit number of free bits.
+ *	starting bit number of free bits.
  */
 static int dbFindBits(u32 word, int l2nb)
 {
@@ -2963,14 +2956,14 @@
 /*
  * NAME:	dbMaxBud(u8 *cp)
  *
- * FUNCTION:    determine the largest binary buddy string of free
+ * FUNCTION:	determine the largest binary buddy string of free
  *		bits within 32-bits of the map.
  *
  * PARAMETERS:
- *      cp	-  pointer to the 32-bit value.
+ *	cp	-  pointer to the 32-bit value.
  *
  * RETURN VALUES:
- *      largest binary buddy of free bits within a dmap word.
+ *	largest binary buddy of free bits within a dmap word.
  */
 static int dbMaxBud(u8 * cp)
 {
@@ -3000,14 +2993,14 @@
 /*
  * NAME:	cnttz(uint word)
  *
- * FUNCTION:    determine the number of trailing zeros within a 32-bit
+ * FUNCTION:	determine the number of trailing zeros within a 32-bit
  *		value.
  *
  * PARAMETERS:
- *      value	-  32-bit value to be examined.
+ *	value	-  32-bit value to be examined.
  *
  * RETURN VALUES:
- *      count of trailing zeros
+ *	count of trailing zeros
  */
 static int cnttz(u32 word)
 {
@@ -3025,14 +3018,14 @@
 /*
  * NAME:	cntlz(u32 value)
  *
- * FUNCTION:    determine the number of leading zeros within a 32-bit
+ * FUNCTION:	determine the number of leading zeros within a 32-bit
  *		value.
  *
  * PARAMETERS:
- *      value	-  32-bit value to be examined.
+ *	value	-  32-bit value to be examined.
  *
  * RETURN VALUES:
- *      count of leading zeros
+ *	count of leading zeros
  */
 static int cntlz(u32 value)
 {
@@ -3050,14 +3043,14 @@
  * NAME:	blkstol2(s64 nb)
  *
  * FUNCTION:	convert a block count to its log2 value. if the block
- *	        count is not a l2 multiple, it is rounded up to the next
+ *		count is not a l2 multiple, it is rounded up to the next
  *		larger l2 multiple.
  *
  * PARAMETERS:
- *      nb	-  number of blocks
+ *	nb	-  number of blocks
  *
  * RETURN VALUES:
- *      log2 number of blocks
+ *	log2 number of blocks
  */
 static int blkstol2(s64 nb)
 {
@@ -3099,13 +3092,13 @@
  *		at a time.
  *
  * PARAMETERS:
- *      ip	-  pointer to in-core inode;
- *      blkno	-  starting block number to be freed.
- *      nblocks	-  number of blocks to be freed.
+ *	ip	-  pointer to in-core inode;
+ *	blkno	-  starting block number to be freed.
+ *	nblocks	-  number of blocks to be freed.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  */
 int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks)
 {
@@ -3278,10 +3271,10 @@
  * L2
  *  |
  *   L1---------------------------------L1
- *    |                                  |
- *     L0---------L0---------L0           L0---------L0---------L0
- *      |          |          |            |          |          |
- *       d0,...,dn  d0,...,dn  d0,...,dn    d0,...,dn  d0,...,dn  d0,.,dm;
+ *    |					 |
+ *     L0---------L0---------L0		  L0---------L0---------L0
+ *      |	   |	      |		   |	      |		 |
+ *	 d0,...,dn  d0,...,dn  d0,...,dn    d0,...,dn  d0,...,dn  d0,.,dm;
  * L2L1L0d0,...,dnL0d0,...,dnL0d0,...,dnL1L0d0,...,dnL0d0,...,dnL0d0,..dm
  *
  * <---old---><----------------------------extend----------------------->
@@ -3307,7 +3300,7 @@
 		 (long long) blkno, (long long) nblocks, (long long) newsize);
 
 	/*
-	 *      initialize bmap control page.
+	 *	initialize bmap control page.
 	 *
 	 * all the data in bmap control page should exclude
 	 * the mkfs hidden dmap page.
@@ -3330,7 +3323,7 @@
 	bmp->db_numag += ((u32) newsize % (u32) bmp->db_agsize) ? 1 : 0;
 
 	/*
-	 *      reconfigure db_agfree[]
+	 *	reconfigure db_agfree[]
 	 * from old AG configuration to new AG configuration;
 	 *
 	 * coalesce contiguous k (newAGSize/oldAGSize) AGs;
@@ -3362,7 +3355,7 @@
 	bmp->db_maxag = bmp->db_maxag / k;
 
 	/*
-	 *      extend bmap
+	 *	extend bmap
 	 *
 	 * update bit maps and corresponding level control pages;
 	 * global control page db_nfree, db_agfree[agno], db_maxfreebud;
@@ -3410,7 +3403,7 @@
 			/* compute start L0 */
 			j = 0;
 			l1leaf = l1dcp->stree + CTLLEAFIND;
-			p += nbperpage;	/* 1st L0 of L1.k  */
+			p += nbperpage;	/* 1st L0 of L1.k */
 		}
 
 		/*
@@ -3548,7 +3541,7 @@
 	return -EIO;
 
 	/*
-	 *      finalize bmap control page
+	 *	finalize bmap control page
 	 */
 finalize:
 
@@ -3567,7 +3560,7 @@
 	int i, n;
 
 	/*
-	 *      finalize bmap control page
+	 *	finalize bmap control page
 	 */
 //finalize:
 	/*
@@ -3953,8 +3946,8 @@
  * convert number of map pages to the zero origin top dmapctl level
  */
 #define BMAPPGTOLEV(npages)	\
-	(((npages) <= 3 + MAXL0PAGES) ? 0 \
-       : ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
+	(((npages) <= 3 + MAXL0PAGES) ? 0 : \
+	 ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
 
 s64 dbMapFileSizeToMapSize(struct inode * ipbmap)
 {
@@ -3981,8 +3974,8 @@
 		factor =
 		    (i == 2) ? MAXL1PAGES : ((i == 1) ? MAXL0PAGES : 1);
 		complete = (u32) npages / factor;
-		ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL
-				      : ((i == 1) ? LPERCTL : 1));
+		ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL :
+				      ((i == 1) ? LPERCTL : 1));
 
 		/* pages in last/incomplete child */
 		npages = (u32) npages % factor;
diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
index 45ea454..11e6d47 100644
--- a/fs/jfs/jfs_dmap.h
+++ b/fs/jfs/jfs_dmap.h
@@ -83,7 +83,7 @@
  *	- 1 is added to account for the control page of the map.
  */
 #define BLKTODMAP(b,s)    \
-        ((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
+	((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
 
 /*
  * convert disk block number to the logical block number of the LEVEL 0
@@ -98,7 +98,7 @@
  *	- 1 is added to account for the control page of the map.
  */
 #define BLKTOL0(b,s)      \
-        (((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
+	(((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
 
 /*
  * convert disk block number to the logical block number of the LEVEL 1
@@ -120,7 +120,7 @@
  * at the specified level which describes the disk block.
  */
 #define BLKTOCTL(b,s,l)   \
-        (((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
+	(((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
 
 /*
  * convert aggregate map size to the zero origin dmapctl level of the
@@ -145,27 +145,27 @@
  * dmaptree must be consistent with dmapctl.
  */
 struct dmaptree {
-	__le32 nleafs;		/* 4: number of tree leafs      */
-	__le32 l2nleafs;	/* 4: l2 number of tree leafs   */
-	__le32 leafidx;		/* 4: index of first tree leaf  */
-	__le32 height;		/* 4: height of the tree        */
+	__le32 nleafs;		/* 4: number of tree leafs	*/
+	__le32 l2nleafs;	/* 4: l2 number of tree leafs	*/
+	__le32 leafidx;		/* 4: index of first tree leaf	*/
+	__le32 height;		/* 4: height of the tree	*/
 	s8 budmin;		/* 1: min l2 tree leaf value to combine */
-	s8 stree[TREESIZE];	/* TREESIZE: tree               */
-	u8 pad[2];		/* 2: pad to word boundary      */
-};				/* - 360 -                      */
+	s8 stree[TREESIZE];	/* TREESIZE: tree		*/
+	u8 pad[2];		/* 2: pad to word boundary	*/
+};				/* - 360 -			*/
 
 /*
  *	dmap page per 8K blocks bitmap
  */
 struct dmap {
-	__le32 nblocks;		/* 4: num blks covered by this dmap     */
-	__le32 nfree;		/* 4: num of free blks in this dmap     */
-	__le64 start;		/* 8: starting blkno for this dmap      */
-	struct dmaptree tree;	/* 360: dmap tree                       */
-	u8 pad[1672];		/* 1672: pad to 2048 bytes              */
-	__le32 wmap[LPERDMAP];	/* 1024: bits of the working map        */
-	__le32 pmap[LPERDMAP];	/* 1024: bits of the persistent map     */
-};				/* - 4096 -                             */
+	__le32 nblocks;		/* 4: num blks covered by this dmap	*/
+	__le32 nfree;		/* 4: num of free blks in this dmap	*/
+	__le64 start;		/* 8: starting blkno for this dmap	*/
+	struct dmaptree tree;	/* 360: dmap tree			*/
+	u8 pad[1672];		/* 1672: pad to 2048 bytes		*/
+	__le32 wmap[LPERDMAP];	/* 1024: bits of the working map	*/
+	__le32 pmap[LPERDMAP];	/* 1024: bits of the persistent map	*/
+};				/* - 4096 -				*/
 
 /*
  *	disk map control page per level.
@@ -173,14 +173,14 @@
  * dmapctl must be consistent with dmaptree.
  */
 struct dmapctl {
-	__le32 nleafs;		/* 4: number of tree leafs      */
-	__le32 l2nleafs;	/* 4: l2 number of tree leafs   */
-	__le32 leafidx;		/* 4: index of the first tree leaf      */
-	__le32 height;		/* 4: height of tree            */
-	s8 budmin;		/* 1: minimum l2 tree leaf value        */
-	s8 stree[CTLTREESIZE];	/* CTLTREESIZE: dmapctl tree    */
-	u8 pad[2714];		/* 2714: pad to 4096            */
-};				/* - 4096 -                     */
+	__le32 nleafs;		/* 4: number of tree leafs	*/
+	__le32 l2nleafs;	/* 4: l2 number of tree leafs	*/
+	__le32 leafidx;		/* 4: index of the first tree leaf	*/
+	__le32 height;		/* 4: height of tree		*/
+	s8 budmin;		/* 1: minimum l2 tree leaf value	*/
+	s8 stree[CTLTREESIZE];	/* CTLTREESIZE: dmapctl tree	*/
+	u8 pad[2714];		/* 2714: pad to 4096		*/
+};				/* - 4096 -			*/
 
 /*
  *	common definition for dmaptree within dmap and dmapctl
@@ -202,41 +202,41 @@
  *	on-disk aggregate disk allocation map descriptor.
  */
 struct dbmap_disk {
-	__le64 dn_mapsize;	/* 8: number of blocks in aggregate     */
-	__le64 dn_nfree;	/* 8: num free blks in aggregate map    */
-	__le32 dn_l2nbperpage;	/* 4: number of blks per page           */
-	__le32 dn_numag;	/* 4: total number of ags               */
-	__le32 dn_maxlevel;	/* 4: number of active ags              */
-	__le32 dn_maxag;	/* 4: max active alloc group number     */
-	__le32 dn_agpref;	/* 4: preferred alloc group (hint)      */
-	__le32 dn_aglevel;	/* 4: dmapctl level holding the AG      */
-	__le32 dn_agheigth;	/* 4: height in dmapctl of the AG       */
-	__le32 dn_agwidth;	/* 4: width in dmapctl of the AG        */
-	__le32 dn_agstart;	/* 4: start tree index at AG height     */
-	__le32 dn_agl2size;	/* 4: l2 num of blks per alloc group    */
-	__le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count           */
-	__le64 dn_agsize;	/* 8: num of blks per alloc group       */
-	s8 dn_maxfreebud;	/* 1: max free buddy system             */
-	u8 pad[3007];		/* 3007: pad to 4096                    */
-};				/* - 4096 -                             */
+	__le64 dn_mapsize;	/* 8: number of blocks in aggregate	*/
+	__le64 dn_nfree;	/* 8: num free blks in aggregate map	*/
+	__le32 dn_l2nbperpage;	/* 4: number of blks per page		*/
+	__le32 dn_numag;	/* 4: total number of ags		*/
+	__le32 dn_maxlevel;	/* 4: number of active ags		*/
+	__le32 dn_maxag;	/* 4: max active alloc group number	*/
+	__le32 dn_agpref;	/* 4: preferred alloc group (hint)	*/
+	__le32 dn_aglevel;	/* 4: dmapctl level holding the AG	*/
+	__le32 dn_agheigth;	/* 4: height in dmapctl of the AG	*/
+	__le32 dn_agwidth;	/* 4: width in dmapctl of the AG	*/
+	__le32 dn_agstart;	/* 4: start tree index at AG height	*/
+	__le32 dn_agl2size;	/* 4: l2 num of blks per alloc group	*/
+	__le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count		*/
+	__le64 dn_agsize;	/* 8: num of blks per alloc group	*/
+	s8 dn_maxfreebud;	/* 1: max free buddy system		*/
+	u8 pad[3007];		/* 3007: pad to 4096			*/
+};				/* - 4096 -				*/
 
 struct dbmap {
-	s64 dn_mapsize;		/* number of blocks in aggregate     */
-	s64 dn_nfree;		/* num free blks in aggregate map    */
-	int dn_l2nbperpage;	/* number of blks per page           */
-	int dn_numag;		/* total number of ags               */
-	int dn_maxlevel;	/* number of active ags              */
-	int dn_maxag;		/* max active alloc group number     */
-	int dn_agpref;		/* preferred alloc group (hint)      */
-	int dn_aglevel;		/* dmapctl level holding the AG      */
-	int dn_agheigth;	/* height in dmapctl of the AG       */
-	int dn_agwidth;		/* width in dmapctl of the AG        */
-	int dn_agstart;		/* start tree index at AG height     */
-	int dn_agl2size;	/* l2 num of blks per alloc group    */
-	s64 dn_agfree[MAXAG];	/* per AG free count           */
-	s64 dn_agsize;		/* num of blks per alloc group       */
-	signed char dn_maxfreebud;	/* max free buddy system             */
-};				/* - 4096 -                             */
+	s64 dn_mapsize;		/* number of blocks in aggregate	*/
+	s64 dn_nfree;		/* num free blks in aggregate map	*/
+	int dn_l2nbperpage;	/* number of blks per page		*/
+	int dn_numag;		/* total number of ags			*/
+	int dn_maxlevel;	/* number of active ags			*/
+	int dn_maxag;		/* max active alloc group number	*/
+	int dn_agpref;		/* preferred alloc group (hint)		*/
+	int dn_aglevel;		/* dmapctl level holding the AG		*/
+	int dn_agheigth;	/* height in dmapctl of the AG		*/
+	int dn_agwidth;		/* width in dmapctl of the AG		*/
+	int dn_agstart;		/* start tree index at AG height	*/
+	int dn_agl2size;	/* l2 num of blks per alloc group	*/
+	s64 dn_agfree[MAXAG];	/* per AG free count			*/
+	s64 dn_agsize;		/* num of blks per alloc group		*/
+	signed char dn_maxfreebud;	/* max free buddy system	*/
+};				/* - 4096 -				*/
 /*
  *	in-memory aggregate disk allocation map descriptor.
  */
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 6d62f32..c14ba3c 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -315,8 +315,8 @@
 	lv = &llck->lv[llck->index];
 
 	/*
-	 *      Linelock slot size is twice the size of directory table
-	 *      slot size.  512 entries per page.
+	 *	Linelock slot size is twice the size of directory table
+	 *	slot size.  512 entries per page.
 	 */
 	lv->offset = ((index - 2) & 511) >> 1;
 	lv->length = 1;
@@ -615,7 +615,7 @@
 	btstack->nsplit = 1;
 
 	/*
-	 *      search down tree from root:
+	 *	search down tree from root:
 	 *
 	 * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
 	 * internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -659,7 +659,7 @@
 			}
 			if (cmp == 0) {
 				/*
-				 *      search hit
+				 *	search hit
 				 */
 				/* search hit - leaf page:
 				 * return the entry found
@@ -723,7 +723,7 @@
 		}
 
 		/*
-		 *      search miss
+		 *	search miss
 		 *
 		 * base is the smallest index with key (Kj) greater than
 		 * search key (K) and may be zero or (maxindex + 1) index.
@@ -834,7 +834,7 @@
 	struct lv *lv;
 
 	/*
-	 *      retrieve search result
+	 *	retrieve search result
 	 *
 	 * dtSearch() returns (leaf page pinned, index at which to insert).
 	 * n.b. dtSearch() may return index of (maxindex + 1) of
@@ -843,7 +843,7 @@
 	DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
 
 	/*
-	 *      insert entry for new key
+	 *	insert entry for new key
 	 */
 	if (DO_INDEX(ip)) {
 		if (JFS_IP(ip)->next_index == DIREND) {
@@ -860,9 +860,9 @@
 	data.leaf.ino = *fsn;
 
 	/*
-	 *      leaf page does not have enough room for new entry:
+	 *	leaf page does not have enough room for new entry:
 	 *
-	 *      extend/split the leaf page;
+	 *	extend/split the leaf page;
 	 *
 	 * dtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -877,9 +877,9 @@
 	}
 
 	/*
-	 *      leaf page does have enough room for new entry:
+	 *	leaf page does have enough room for new entry:
 	 *
-	 *      insert the new data entry into the leaf page;
+	 *	insert the new data entry into the leaf page;
 	 */
 	BT_MARK_DIRTY(mp, ip);
 	/*
@@ -967,13 +967,13 @@
 	}
 
 	/*
-	 *      split leaf page
+	 *	split leaf page
 	 *
 	 * The split routines insert the new entry, and
 	 * acquire txLock as appropriate.
 	 */
 	/*
-	 *      split root leaf page:
+	 *	split root leaf page:
 	 */
 	if (sp->header.flag & BT_ROOT) {
 		/*
@@ -1012,7 +1012,7 @@
 	}
 
 	/*
-	 *      extend first leaf page
+	 *	extend first leaf page
 	 *
 	 * extend the 1st extent if less than buffer page size
 	 * (dtExtendPage() reurns leaf page unpinned)
@@ -1068,7 +1068,7 @@
 	}
 
 	/*
-	 *      split leaf page <sp> into <sp> and a new right page <rp>.
+	 *	split leaf page <sp> into <sp> and a new right page <rp>.
 	 *
 	 * return <rp> pinned and its extent descriptor <rpxd>
 	 */
@@ -1433,7 +1433,7 @@
 	rp->header.freecnt = rp->header.maxslot - fsi;
 
 	/*
-	 *      sequential append at tail: append without split
+	 *	sequential append at tail: append without split
 	 *
 	 * If splitting the last page on a level because of appending
 	 * a entry to it (skip is maxentry), it's likely that the access is
@@ -1467,7 +1467,7 @@
 	}
 
 	/*
-	 *      non-sequential insert (at possibly middle page)
+	 *	non-sequential insert (at possibly middle page)
 	 */
 
 	/*
@@ -1508,7 +1508,7 @@
 	left = 0;
 
 	/*
-	 *      compute fill factor for split pages
+	 *	compute fill factor for split pages
 	 *
 	 * <nxt> traces the next entry to move to rp
 	 * <off> traces the next entry to stay in sp
@@ -1551,7 +1551,7 @@
 	/* <nxt> poins to the 1st entry to move */
 
 	/*
-	 *      move entries to right page
+	 *	move entries to right page
 	 *
 	 * dtMoveEntry() initializes rp and reserves entry for insertion
 	 *
@@ -1677,7 +1677,7 @@
 		return (rc);
 
 	/*
-	 *      extend the extent
+	 *	extend the extent
 	 */
 	pxdlist = split->pxdlist;
 	pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1722,7 +1722,7 @@
 	}
 
 	/*
-	 *      extend the page
+	 *	extend the page
 	 */
 	sp->header.self = *pxd;
 
@@ -1739,9 +1739,6 @@
 	/* update buffer extent descriptor of extended page */
 	xlen = lengthPXD(pxd);
 	xsize = xlen << JFS_SBI(sb)->l2bsize;
-#ifdef _STILL_TO_PORT
-	bmSetXD(smp, xaddr, xsize);
-#endif				/*  _STILL_TO_PORT */
 
 	/*
 	 * copy old stbl to new stbl at start of extended area
@@ -1836,7 +1833,7 @@
 	}
 
 	/*
-	 *      update parent entry on the parent/root page
+	 *	update parent entry on the parent/root page
 	 */
 	/*
 	 * acquire a transaction lock on the parent/root page
@@ -1904,7 +1901,7 @@
 	sp = &JFS_IP(ip)->i_dtroot;
 
 	/*
-	 *      allocate/initialize a single (right) child page
+	 *	allocate/initialize a single (right) child page
 	 *
 	 * N.B. at first split, a one (or two) block to fit new entry
 	 * is allocated; at subsequent split, a full page is allocated;
@@ -1943,7 +1940,7 @@
 	rp->header.prev = 0;
 
 	/*
-	 *      move in-line root page into new right page extent
+	 *	move in-line root page into new right page extent
 	 */
 	/* linelock header + copied entries + new stbl (1st slot) in new page */
 	ASSERT(dtlck->index == 0);
@@ -2016,7 +2013,7 @@
 	dtInsertEntry(rp, split->index, split->key, split->data, &dtlck);
 
 	/*
-	 *      reset parent/root page
+	 *	reset parent/root page
 	 *
 	 * set the 1st entry offset to 0, which force the left-most key
 	 * at any level of the tree to be less than any search key.
@@ -2102,7 +2099,7 @@
 	dtpage_t *np;
 
 	/*
-	 *      search for the entry to delete:
+	 *	search for the entry to delete:
 	 *
 	 * dtSearch() returns (leaf page pinned, index at which to delete).
 	 */
@@ -2253,7 +2250,7 @@
 	int i;
 
 	/*
-	 *      keep the root leaf page which has become empty
+	 *	keep the root leaf page which has become empty
 	 */
 	if (BT_IS_ROOT(fmp)) {
 		/*
@@ -2269,7 +2266,7 @@
 	}
 
 	/*
-	 *      free the non-root leaf page
+	 *	free the non-root leaf page
 	 */
 	/*
 	 * acquire a transaction lock on the page
@@ -2299,7 +2296,7 @@
 	discard_metapage(fmp);
 
 	/*
-	 *      propagate page deletion up the directory tree
+	 *	propagate page deletion up the directory tree
 	 *
 	 * If the delete from the parent page makes it empty,
 	 * continue all the way up the tree.
@@ -2440,10 +2437,10 @@
 
 #ifdef _NOTYET
 /*
- * NAME:        dtRelocate()
+ * NAME:	dtRelocate()
  *
- * FUNCTION:    relocate dtpage (internal or leaf) of directory;
- *              This function is mainly used by defragfs utility.
+ * FUNCTION:	relocate dtpage (internal or leaf) of directory;
+ *		This function is mainly used by defragfs utility.
  */
 int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
 	       s64 nxaddr)
@@ -2471,8 +2468,8 @@
 		   xlen);
 
 	/*
-	 *      1. get the internal parent dtpage covering
-	 *      router entry for the tartget page to be relocated;
+	 *	1. get the internal parent dtpage covering
+	 *	router entry for the tartget page to be relocated;
 	 */
 	rc = dtSearchNode(ip, lmxaddr, opxd, &btstack);
 	if (rc)
@@ -2483,7 +2480,7 @@
 	jfs_info("dtRelocate: parent router entry validated.");
 
 	/*
-	 *      2. relocate the target dtpage
+	 *	2. relocate the target dtpage
 	 */
 	/* read in the target page from src extent */
 	DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
@@ -2581,9 +2578,7 @@
 
 	/* update the buffer extent descriptor of the dtpage */
 	xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
-#ifdef _STILL_TO_PORT
-	bmSetXD(mp, nxaddr, xsize);
-#endif /* _STILL_TO_PORT */
+
 	/* unpin the relocated page */
 	DT_PUTPAGE(mp);
 	jfs_info("dtRelocate: target dtpage relocated.");
@@ -2594,7 +2589,7 @@
 	 */
 
 	/*
-	 *      3. acquire maplock for the source extent to be freed;
+	 *	3. acquire maplock for the source extent to be freed;
 	 */
 	/* for dtpage relocation, write a LOG_NOREDOPAGE record
 	 * for the source dtpage (logredo() will init NoRedoPage
@@ -2609,7 +2604,7 @@
 	pxdlock->index = 1;
 
 	/*
-	 *      4. update the parent router entry for relocation;
+	 *	4. update the parent router entry for relocation;
 	 *
 	 * acquire tlck for the parent entry covering the target dtpage;
 	 * write LOG_REDOPAGE to apply after image only;
@@ -2637,7 +2632,7 @@
  * NAME:	dtSearchNode()
  *
  * FUNCTION:	Search for an dtpage containing a specified address
- *              This function is mainly used by defragfs utility.
+ *		This function is mainly used by defragfs utility.
  *
  * NOTE:	Search result on stack, the found page is pinned at exit.
  *		The result page must be an internal dtpage.
@@ -2660,7 +2655,7 @@
 	BT_CLR(btstack);	/* reset stack */
 
 	/*
-	 *      descend tree to the level with specified leftmost page
+	 *	descend tree to the level with specified leftmost page
 	 *
 	 *  by convention, root bn = 0.
 	 */
@@ -2699,7 +2694,7 @@
 	}
 
 	/*
-	 *      search each page at the current levevl
+	 *	search each page at the current levevl
 	 */
       loop:
 	stbl = DT_GETSTBL(p);
@@ -3044,9 +3039,9 @@
 	if (DO_INDEX(ip)) {
 		/*
 		 * persistent index is stored in directory entries.
-		 * Special cases:        0 = .
-		 *                       1 = ..
-		 *                      -1 = End of directory
+		 * Special cases:	 0 = .
+		 *			 1 = ..
+		 *			-1 = End of directory
 		 */
 		do_index = 1;
 
@@ -3128,10 +3123,10 @@
 		/*
 		 * Legacy filesystem - OS/2 & Linux JFS < 0.3.6
 		 *
-		 * pn = index = 0:      First entry "."
-		 * pn = 0; index = 1:   Second entry ".."
-		 * pn > 0:              Real entries, pn=1 -> leftmost page
-		 * pn = index = -1:     No more entries
+		 * pn = index = 0:	First entry "."
+		 * pn = 0; index = 1:	Second entry ".."
+		 * pn > 0:		Real entries, pn=1 -> leftmost page
+		 * pn = index = -1:	No more entries
 		 */
 		dtpos = filp->f_pos;
 		if (dtpos == 0) {
@@ -3351,7 +3346,7 @@
 	BT_CLR(btstack);	/* reset stack */
 
 	/*
-	 *      descend leftmost path of the tree
+	 *	descend leftmost path of the tree
 	 *
 	 * by convention, root bn = 0.
 	 */
@@ -4531,7 +4526,7 @@
 	struct ldtentry *entry;
 
 	/*
-	 *      search for the entry to modify:
+	 *	search for the entry to modify:
 	 *
 	 * dtSearch() returns (leaf page pinned, index at which to modify).
 	 */
diff --git a/fs/jfs/jfs_dtree.h b/fs/jfs/jfs_dtree.h
index af8513f..8561c6e 100644
--- a/fs/jfs/jfs_dtree.h
+++ b/fs/jfs/jfs_dtree.h
@@ -35,7 +35,7 @@
 
 
 /*
- *      entry segment/slot
+ *	entry segment/slot
  *
  * an entry consists of type dependent head/only segment/slot and
  * additional segments/slots linked vi next field;
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index a35bdca..7ae1e32 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -34,8 +34,8 @@
 #endif
 static s64 extRoundDown(s64 nb);
 
-#define DPD(a)          (printk("(a): %d\n",(a)))
-#define DPC(a)          (printk("(a): %c\n",(a)))
+#define DPD(a)		(printk("(a): %d\n",(a)))
+#define DPC(a)		(printk("(a): %c\n",(a)))
 #define DPL1(a)					\
 {						\
 	if ((a) >> 32)				\
@@ -51,19 +51,19 @@
 		printk("(a): %x\n",(a) << 32);	\
 }
 
-#define DPD1(a)         (printk("(a): %d  ",(a)))
-#define DPX(a)          (printk("(a): %08x\n",(a)))
-#define DPX1(a)         (printk("(a): %08x  ",(a)))
-#define DPS(a)          (printk("%s\n",(a)))
-#define DPE(a)          (printk("\nENTERING: %s\n",(a)))
-#define DPE1(a)          (printk("\nENTERING: %s",(a)))
-#define DPS1(a)         (printk("  %s  ",(a)))
+#define DPD1(a)		(printk("(a): %d  ",(a)))
+#define DPX(a)		(printk("(a): %08x\n",(a)))
+#define DPX1(a)		(printk("(a): %08x  ",(a)))
+#define DPS(a)		(printk("%s\n",(a)))
+#define DPE(a)		(printk("\nENTERING: %s\n",(a)))
+#define DPE1(a)		(printk("\nENTERING: %s",(a)))
+#define DPS1(a)		(printk("  %s  ",(a)))
 
 
 /*
  * NAME:	extAlloc()
  *
- * FUNCTION:    allocate an extent for a specified page range within a
+ * FUNCTION:	allocate an extent for a specified page range within a
  *		file.
  *
  * PARAMETERS:
@@ -78,9 +78,9 @@
  *		  should be marked as allocated but not recorded.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 int
 extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
@@ -192,9 +192,9 @@
 
 #ifdef _NOTYET
 /*
- * NAME:        extRealloc()
+ * NAME:	extRealloc()
  *
- * FUNCTION:    extend the allocation of a file extent containing a
+ * FUNCTION:	extend the allocation of a file extent containing a
  *		partial back last page.
  *
  * PARAMETERS:
@@ -207,9 +207,9 @@
  *		  should be marked as allocated but not recorded.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr)
 {
@@ -345,9 +345,9 @@
 
 
 /*
- * NAME:        extHint()
+ * NAME:	extHint()
  *
- * FUNCTION:    produce an extent allocation hint for a file offset.
+ * FUNCTION:	produce an extent allocation hint for a file offset.
  *
  * PARAMETERS:
  *	ip	- the inode of the file.
@@ -356,8 +356,8 @@
  *		  the hint.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-EIO	- i/o error.
  */
 int extHint(struct inode *ip, s64 offset, xad_t * xp)
 {
@@ -387,7 +387,7 @@
 	lxdl.nlxd = 1;
 	lxdl.lxd = &lxd;
 	LXDoffset(&lxd, prev)
-	    LXDlength(&lxd, nbperpage);
+	LXDlength(&lxd, nbperpage);
 
 	xadl.maxnxad = 1;
 	xadl.nxad = 0;
@@ -397,11 +397,11 @@
 	if ((rc = xtLookupList(ip, &lxdl, &xadl, 0)))
 		return (rc);
 
-	/* check if not extent exists for the previous page.
+	/* check if no extent exists for the previous page.
 	 * this is possible for sparse files.
 	 */
 	if (xadl.nxad == 0) {
-//              assert(ISSPARSE(ip));
+//		assert(ISSPARSE(ip));
 		return (0);
 	}
 
@@ -410,28 +410,28 @@
 	 */
 	xp->flag &= XAD_NOTRECORDED;
 
-        if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
+	if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
 		jfs_error(ip->i_sb, "extHint: corrupt xtree");
 		return -EIO;
-        }
+	}
 
 	return (0);
 }
 
 
 /*
- * NAME:        extRecord()
+ * NAME:	extRecord()
  *
- * FUNCTION:    change a page with a file from not recorded to recorded.
+ * FUNCTION:	change a page with a file from not recorded to recorded.
  *
  * PARAMETERS:
  *	ip	- inode of the file.
  *	cp	- cbuf of the file page.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 int extRecord(struct inode *ip, xad_t * xp)
 {
@@ -451,9 +451,9 @@
 
 #ifdef _NOTYET
 /*
- * NAME:        extFill()
+ * NAME:	extFill()
  *
- * FUNCTION:    allocate disk space for a file page that represents
+ * FUNCTION:	allocate disk space for a file page that represents
  *		a file hole.
  *
  * PARAMETERS:
@@ -461,16 +461,16 @@
  *	cp	- cbuf of the file page represent the hole.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 int extFill(struct inode *ip, xad_t * xp)
 {
 	int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
 	s64 blkno = offsetXAD(xp) >> ip->i_blkbits;
 
-//      assert(ISSPARSE(ip));
+//	assert(ISSPARSE(ip));
 
 	/* initialize the extent allocation hint */
 	XADaddress(xp, 0);
@@ -489,7 +489,7 @@
 /*
  * NAME:	extBalloc()
  *
- * FUNCTION:    allocate disk blocks to form an extent.
+ * FUNCTION:	allocate disk blocks to form an extent.
  *
  *		initially, we will try to allocate disk blocks for the
  *		requested size (nblocks).  if this fails (nblocks
@@ -513,9 +513,9 @@
  *		   allocated block range.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 static int
 extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
@@ -580,7 +580,7 @@
 /*
  * NAME:	extBrealloc()
  *
- * FUNCTION:    attempt to extend an extent's allocation.
+ * FUNCTION:	attempt to extend an extent's allocation.
  *
  *		Initially, we will try to extend the extent's allocation
  *		in place.  If this fails, we'll try to move the extent
@@ -597,8 +597,8 @@
  *
  * PARAMETERS:
  *	ip	 - the inode of the file.
- *	blkno    - starting block number of the extents current allocation.
- *	nblks    - number of blocks within the extents current allocation.
+ *	blkno	 - starting block number of the extents current allocation.
+ *	nblks	 - number of blocks within the extents current allocation.
  *	newnblks - pointer to a s64 value.  on entry, this value is the
  *		   the new desired extent size (number of blocks).  on
  *		   successful exit, this value is set to the extent's actual
@@ -606,9 +606,9 @@
  *	newblkno - the starting block number of the extents new allocation.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 static int
 extBrealloc(struct inode *ip,
@@ -634,16 +634,16 @@
 
 
 /*
- * NAME:        extRoundDown()
+ * NAME:	extRoundDown()
  *
- * FUNCTION:    round down a specified number of blocks to the next
+ * FUNCTION:	round down a specified number of blocks to the next
  *		smallest power of 2 number.
  *
  * PARAMETERS:
  *	nb	- the inode of the file.
  *
  * RETURN VALUES:
- *      next smallest power of 2 number.
+ *	next smallest power of 2 number.
  */
 static s64 extRoundDown(s64 nb)
 {
diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
index 38f70ac..b3f5463 100644
--- a/fs/jfs/jfs_filsys.h
+++ b/fs/jfs/jfs_filsys.h
@@ -34,9 +34,9 @@
 #define JFS_UNICODE	0x00000001	/* unicode name */
 
 /* mount time flags for error handling */
-#define JFS_ERR_REMOUNT_RO 0x00000002   /* remount read-only */
-#define JFS_ERR_CONTINUE   0x00000004   /* continue */
-#define JFS_ERR_PANIC      0x00000008   /* panic */
+#define JFS_ERR_REMOUNT_RO 0x00000002	/* remount read-only */
+#define JFS_ERR_CONTINUE   0x00000004	/* continue */
+#define JFS_ERR_PANIC      0x00000008	/* panic */
 
 /* Quota support */
 #define	JFS_USRQUOTA	0x00000010
@@ -83,7 +83,6 @@
 /*	case-insensitive name/directory support */
 
 #define JFS_AIX		0x80000000	/* AIX support */
-/*	POSIX name/directory  support - Never implemented*/
 
 /*
  *	buffer cache configuration
@@ -113,10 +112,10 @@
 #define IDATASIZE	256	/* inode inline data size */
 #define	IXATTRSIZE	128	/* inode inline extended attribute size */
 
-#define XTPAGE_SIZE     4096
-#define log2_PAGESIZE     12
+#define XTPAGE_SIZE	4096
+#define log2_PAGESIZE	12
 
-#define IAG_SIZE        4096
+#define IAG_SIZE	4096
 #define IAG_EXTENT_SIZE 4096
 #define	INOSPERIAG	4096	/* number of disk inodes per iag */
 #define	L2INOSPERIAG	12	/* l2 number of disk inodes per iag */
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index c653022..3870ba8 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -93,21 +93,21 @@
 static void copy_to_dinode(struct dinode *, struct inode *);
 
 /*
- * NAME:        diMount()
+ * NAME:	diMount()
  *
- * FUNCTION:    initialize the incore inode map control structures for
+ * FUNCTION:	initialize the incore inode map control structures for
  *		a fileset or aggregate init time.
  *
- *              the inode map's control structure (dinomap) is
- *              brought in from disk and placed in virtual memory.
+ *		the inode map's control structure (dinomap) is
+ *		brought in from disk and placed in virtual memory.
  *
  * PARAMETERS:
- *      ipimap  - pointer to inode map inode for the aggregate or fileset.
+ *	ipimap	- pointer to inode map inode for the aggregate or fileset.
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM  - insufficient free virtual memory.
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-ENOMEM	- insufficient free virtual memory.
+ *	-EIO	- i/o error.
  */
 int diMount(struct inode *ipimap)
 {
@@ -180,18 +180,18 @@
 
 
 /*
- * NAME:        diUnmount()
+ * NAME:	diUnmount()
  *
- * FUNCTION:    write to disk the incore inode map control structures for
+ * FUNCTION:	write to disk the incore inode map control structures for
  *		a fileset or aggregate at unmount time.
  *
  * PARAMETERS:
- *      ipimap  - pointer to inode map inode for the aggregate or fileset.
+ *	ipimap	- pointer to inode map inode for the aggregate or fileset.
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM  - insufficient free virtual memory.
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-ENOMEM	- insufficient free virtual memory.
+ *	-EIO	- i/o error.
  */
 int diUnmount(struct inode *ipimap, int mounterror)
 {
@@ -274,9 +274,9 @@
 
 
 /*
- * NAME:        diRead()
+ * NAME:	diRead()
  *
- * FUNCTION:    initialize an incore inode from disk.
+ * FUNCTION:	initialize an incore inode from disk.
  *
  *		on entry, the specifed incore inode should itself
  *		specify the disk inode number corresponding to the
@@ -285,7 +285,7 @@
  *		this routine handles incore inode initialization for
  *		both "special" and "regular" inodes.  special inodes
  *		are those required early in the mount process and
- *	        require special handling since much of the file system
+ *		require special handling since much of the file system
  *		is not yet initialized.  these "special" inodes are
  *		identified by a NULL inode map inode pointer and are
  *		actually initialized by a call to diReadSpecial().
@@ -298,12 +298,12 @@
  *		incore inode.
  *
  * PARAMETERS:
- *      ip  -  pointer to incore inode to be initialized from disk.
+ *	ip	-  pointer to incore inode to be initialized from disk.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOMEM	- insufficient memory
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOMEM	- insufficient memory
  *
  */
 int diRead(struct inode *ip)
@@ -410,26 +410,26 @@
 
 
 /*
- * NAME:        diReadSpecial()
+ * NAME:	diReadSpecial()
  *
- * FUNCTION:    initialize a 'special' inode from disk.
+ * FUNCTION:	initialize a 'special' inode from disk.
  *
  *		this routines handles aggregate level inodes.  The
  *		inode cache cannot differentiate between the
  *		aggregate inodes and the filesystem inodes, so we
  *		handle these here.  We don't actually use the aggregate
- *	        inode map, since these inodes are at a fixed location
+ *		inode map, since these inodes are at a fixed location
  *		and in some cases the aggregate inode map isn't initialized
  *		yet.
  *
  * PARAMETERS:
- *      sb - filesystem superblock
+ *	sb - filesystem superblock
  *	inum - aggregate inode number
  *	secondary - 1 if secondary aggregate inode table
  *
  * RETURN VALUES:
- *      new inode	- success
- *      NULL		- i/o error.
+ *	new inode	- success
+ *	NULL		- i/o error.
  */
 struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
 {
@@ -502,12 +502,12 @@
 }
 
 /*
- * NAME:        diWriteSpecial()
+ * NAME:	diWriteSpecial()
  *
- * FUNCTION:    Write the special inode to disk
+ * FUNCTION:	Write the special inode to disk
  *
  * PARAMETERS:
- *      ip - special inode
+ *	ip - special inode
  *	secondary - 1 if secondary aggregate inode table
  *
  * RETURN VALUES: none
@@ -554,9 +554,9 @@
 }
 
 /*
- * NAME:        diFreeSpecial()
+ * NAME:	diFreeSpecial()
  *
- * FUNCTION:    Free allocated space for special inode
+ * FUNCTION:	Free allocated space for special inode
  */
 void diFreeSpecial(struct inode *ip)
 {
@@ -572,9 +572,9 @@
 
 
 /*
- * NAME:        diWrite()
+ * NAME:	diWrite()
  *
- * FUNCTION:    write the on-disk inode portion of the in-memory inode
+ * FUNCTION:	write the on-disk inode portion of the in-memory inode
  *		to its corresponding on-disk inode.
  *
  *		on entry, the specifed incore inode should itself
@@ -589,11 +589,11 @@
  *
  * PARAMETERS:
  *	tid -  transacation id
- *      ip  -  pointer to incore inode to be written to the inode extent.
+ *	ip  -  pointer to incore inode to be written to the inode extent.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-EIO	- i/o error.
  */
 int diWrite(tid_t tid, struct inode *ip)
 {
@@ -730,7 +730,7 @@
 	ilinelock = (struct linelock *) & tlck->lock;
 
 	/*
-	 *      regular file: 16 byte (XAD slot) granularity
+	 *	regular file: 16 byte (XAD slot) granularity
 	 */
 	if (type & tlckXTREE) {
 		xtpage_t *p, *xp;
@@ -755,7 +755,7 @@
 				xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
 	}
 	/*
-	 *      directory: 32 byte (directory entry slot) granularity
+	 *	directory: 32 byte (directory entry slot) granularity
 	 */
 	else if (type & tlckDTREE) {
 		dtpage_t *p, *xp;
@@ -800,9 +800,8 @@
 	}
 
 	/*
-	 *      lock/copy inode base: 128 byte slot granularity
+	 *	lock/copy inode base: 128 byte slot granularity
 	 */
-// baseDinode:
 	lv = & dilinelock->lv[dilinelock->index];
 	lv->offset = dioffset >> L2INODESLOTSIZE;
 	copy_to_dinode(dp, ip);
@@ -813,17 +812,6 @@
 		lv->length = 1;
 	dilinelock->index++;
 
-#ifdef _JFS_FASTDASD
-	/*
-	 * We aren't logging changes to the DASD used in directory inodes,
-	 * but we need to write them to disk.  If we don't unmount cleanly,
-	 * mount will recalculate the DASD used.
-	 */
-	if (S_ISDIR(ip->i_mode)
-	    && (ip->i_ipmnt->i_mntflag & JFS_DASD_ENABLED))
-		memcpy(&dp->di_DASD, &ip->i_DASD, sizeof(struct dasd));
-#endif				/*  _JFS_FASTDASD */
-
 	/* release the buffer holding the updated on-disk inode.
 	 * the buffer will be later written by commit processing.
 	 */
@@ -834,9 +822,9 @@
 
 
 /*
- * NAME:        diFree(ip)
+ * NAME:	diFree(ip)
  *
- * FUNCTION:    free a specified inode from the inode working map
+ * FUNCTION:	free a specified inode from the inode working map
  *		for a fileset or aggregate.
  *
  *		if the inode to be freed represents the first (only)
@@ -865,11 +853,11 @@
  *		any updates and are held until all updates are complete.
  *
  * PARAMETERS:
- *      ip	- inode to be freed.
+ *	ip	- inode to be freed.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-EIO	- i/o error.
  */
 int diFree(struct inode *ip)
 {
@@ -902,7 +890,8 @@
 	 * the map.
 	 */
 	if (iagno >= imap->im_nextiag) {
-		dump_mem("imap", imap, 32);
+		print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4,
+			       imap, 32, 0);
 		jfs_error(ip->i_sb,
 			  "diFree: inum = %d, iagno = %d, nextiag = %d",
 			  (uint) inum, iagno, imap->im_nextiag);
@@ -964,8 +953,8 @@
 		return -EIO;
 	}
 	/*
-	 *      inode extent still has some inodes or below low water mark:
-	 *      keep the inode extent;
+	 *	inode extent still has some inodes or below low water mark:
+	 *	keep the inode extent;
 	 */
 	if (bitmap ||
 	    imap->im_agctl[agno].numfree < 96 ||
@@ -1047,12 +1036,12 @@
 
 
 	/*
-	 *      inode extent has become free and above low water mark:
-	 *      free the inode extent;
+	 *	inode extent has become free and above low water mark:
+	 *	free the inode extent;
 	 */
 
 	/*
-	 *      prepare to update iag list(s) (careful update step 1)
+	 *	prepare to update iag list(s) (careful update step 1)
 	 */
 	amp = bmp = cmp = dmp = NULL;
 	fwd = back = -1;
@@ -1152,7 +1141,7 @@
 	invalidate_pxd_metapages(ip, freepxd);
 
 	/*
-	 *      update iag list(s) (careful update step 2)
+	 *	update iag list(s) (careful update step 2)
 	 */
 	/* add the iag to the ag extent free list if this is the
 	 * first free extent for the iag.
@@ -1338,20 +1327,20 @@
 
 
 /*
- * NAME:        diAlloc(pip,dir,ip)
+ * NAME:	diAlloc(pip,dir,ip)
  *
- * FUNCTION:    allocate a disk inode from the inode working map
+ * FUNCTION:	allocate a disk inode from the inode working map
  *		for a fileset or aggregate.
  *
  * PARAMETERS:
- *      pip	- pointer to incore inode for the parent inode.
- *      dir	- 'true' if the new disk inode is for a directory.
- *      ip	- pointer to a new inode
+ *	pip	- pointer to incore inode for the parent inode.
+ *	dir	- 'true' if the new disk inode is for a directory.
+ *	ip	- pointer to a new inode
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 int diAlloc(struct inode *pip, bool dir, struct inode *ip)
 {
@@ -1433,7 +1422,7 @@
 	addext = (imap->im_agctl[agno].numfree < 32 && iagp->nfreeexts);
 
 	/*
-	 *      try to allocate from the IAG
+	 *	try to allocate from the IAG
 	 */
 	/* check if the inode may be allocated from the iag
 	 * (i.e. the inode has free inodes or new extent can be added).
@@ -1633,9 +1622,9 @@
 
 
 /*
- * NAME:        diAllocAG(imap,agno,dir,ip)
+ * NAME:	diAllocAG(imap,agno,dir,ip)
  *
- * FUNCTION:    allocate a disk inode from the allocation group.
+ * FUNCTION:	allocate a disk inode from the allocation group.
  *
  *		this routine first determines if a new extent of free
  *		inodes should be added for the allocation group, with
@@ -1649,17 +1638,17 @@
  * PRE CONDITION: Already have the AG lock for this AG.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      agno	- allocation group to allocate from.
- *      dir	- 'true' if the new disk inode is for a directory.
- *      ip	- pointer to the new inode to be filled in on successful return
+ *	imap	- pointer to inode map control structure.
+ *	agno	- allocation group to allocate from.
+ *	dir	- 'true' if the new disk inode is for a directory.
+ *	ip	- pointer to the new inode to be filled in on successful return
  *		  with the disk inode number allocated, its extent address
  *		  and the start of the ag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int
 diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
@@ -1709,9 +1698,9 @@
 
 
 /*
- * NAME:        diAllocAny(imap,agno,dir,iap)
+ * NAME:	diAllocAny(imap,agno,dir,iap)
  *
- * FUNCTION:    allocate a disk inode from any other allocation group.
+ * FUNCTION:	allocate a disk inode from any other allocation group.
  *
  *		this routine is called when an allocation attempt within
  *		the primary allocation group has failed. if attempts to
@@ -1719,17 +1708,17 @@
  *		specified primary group.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      agno	- primary allocation group (to avoid).
- *      dir	- 'true' if the new disk inode is for a directory.
- *      ip	- pointer to a new inode to be filled in on successful return
+ *	imap	- pointer to inode map control structure.
+ *	agno	- primary allocation group (to avoid).
+ *	dir	- 'true' if the new disk inode is for a directory.
+ *	ip	- pointer to a new inode to be filled in on successful return
  *		  with the disk inode number allocated, its extent address
  *		  and the start of the ag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int
 diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
@@ -1772,9 +1761,9 @@
 
 
 /*
- * NAME:        diAllocIno(imap,agno,ip)
+ * NAME:	diAllocIno(imap,agno,ip)
  *
- * FUNCTION:    allocate a disk inode from the allocation group's free
+ * FUNCTION:	allocate a disk inode from the allocation group's free
  *		inode list, returning an error if this free list is
  *		empty (i.e. no iags on the list).
  *
@@ -1785,16 +1774,16 @@
  * PRE CONDITION: Already have AG lock for this AG.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      agno	- allocation group.
- *      ip	- pointer to new inode to be filled in on successful return
+ *	imap	- pointer to inode map control structure.
+ *	agno	- allocation group.
+ *	ip	- pointer to new inode to be filled in on successful return
  *		  with the disk inode number allocated, its extent address
  *		  and the start of the ag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
 {
@@ -1890,7 +1879,7 @@
 
 
 /*
- * NAME:        diAllocExt(imap,agno,ip)
+ * NAME:	diAllocExt(imap,agno,ip)
  *
  * FUNCTION:	add a new extent of free inodes to an iag, allocating
  *		an inode from this extent to satisfy the current allocation
@@ -1910,16 +1899,16 @@
  *		for the purpose of satisfying this request.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      agno	- allocation group number.
- *      ip	- pointer to new inode to be filled in on successful return
+ *	imap	- pointer to inode map control structure.
+ *	agno	- allocation group number.
+ *	ip	- pointer to new inode to be filled in on successful return
  *		  with the disk inode number allocated, its extent address
  *		  and the start of the ag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
 {
@@ -2010,7 +1999,7 @@
 
 
 /*
- * NAME:        diAllocBit(imap,iagp,ino)
+ * NAME:	diAllocBit(imap,iagp,ino)
  *
  * FUNCTION:	allocate a backed inode from an iag.
  *
@@ -2030,14 +2019,14 @@
  *	this AG.  Must have read lock on imap inode.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      iagp	- pointer to iag.
- *      ino	- inode number to be allocated within the iag.
+ *	imap	- pointer to inode map control structure.
+ *	iagp	- pointer to iag.
+ *	ino	- inode number to be allocated within the iag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
 {
@@ -2144,11 +2133,11 @@
 
 
 /*
- * NAME:        diNewExt(imap,iagp,extno)
+ * NAME:	diNewExt(imap,iagp,extno)
  *
- * FUNCTION:    initialize a new extent of inodes for an iag, allocating
- *	        the first inode of the extent for use for the current
- *	        allocation request.
+ * FUNCTION:	initialize a new extent of inodes for an iag, allocating
+ *		the first inode of the extent for use for the current
+ *		allocation request.
  *
  *		disk resources are allocated for the new extent of inodes
  *		and the inodes themselves are initialized to reflect their
@@ -2177,14 +2166,14 @@
  *	this AG.  Must have read lock on imap inode.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      iagp	- pointer to iag.
- *      extno	- extent number.
+ *	imap	- pointer to inode map control structure.
+ *	iagp	- pointer to iag.
+ *	extno	- extent number.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
 {
@@ -2430,7 +2419,7 @@
 
 
 /*
- * NAME:        diNewIAG(imap,iagnop,agno)
+ * NAME:	diNewIAG(imap,iagnop,agno)
  *
  * FUNCTION:	allocate a new iag for an allocation group.
  *
@@ -2443,16 +2432,16 @@
  *		and returned to satisfy the request.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      iagnop	- pointer to an iag number set with the number of the
+ *	imap	- pointer to inode map control structure.
+ *	iagnop	- pointer to an iag number set with the number of the
  *		  newly allocated iag upon successful return.
- *      agno	- allocation group number.
+ *	agno	- allocation group number.
  *	bpp	- Buffer pointer to be filled in with new IAG's buffer
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  *
  * serialization:
  *	AG lock held on entry/exit;
@@ -2461,7 +2450,7 @@
  *
  * note: new iag transaction:
  * . synchronously write iag;
- * . write log of xtree and inode  of imap;
+ * . write log of xtree and inode of imap;
  * . commit;
  * . synchronous write of xtree (right to left, bottom to top);
  * . at start of logredo(): init in-memory imap with one additional iag page;
@@ -2481,9 +2470,6 @@
 	s64 xaddr = 0;
 	s64 blkno;
 	tid_t tid;
-#ifdef _STILL_TO_PORT
-	xad_t xad;
-#endif				/*  _STILL_TO_PORT */
 	struct inode *iplist[1];
 
 	/* pick up pointers to the inode map and mount inodes */
@@ -2674,15 +2660,15 @@
 }
 
 /*
- * NAME:        diIAGRead()
+ * NAME:	diIAGRead()
  *
- * FUNCTION:    get the buffer for the specified iag within a fileset
+ * FUNCTION:	get the buffer for the specified iag within a fileset
  *		or aggregate inode map.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      iagno	- iag number.
- *      bpp	- point to buffer pointer to be filled in on successful
+ *	imap	- pointer to inode map control structure.
+ *	iagno	- iag number.
+ *	bpp	- point to buffer pointer to be filled in on successful
  *		  exit.
  *
  * SERIALIZATION:
@@ -2691,8 +2677,8 @@
  *	 the read lock is unnecessary.)
  *
  * RETURN VALUES:
- *      0       - success.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-EIO	- i/o error.
  */
 static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
 {
@@ -2712,17 +2698,17 @@
 }
 
 /*
- * NAME:        diFindFree()
+ * NAME:	diFindFree()
  *
- * FUNCTION:    find the first free bit in a word starting at
+ * FUNCTION:	find the first free bit in a word starting at
  *		the specified bit position.
  *
  * PARAMETERS:
- *      word	- word to be examined.
- *      start	- starting bit position.
+ *	word	- word to be examined.
+ *	start	- starting bit position.
  *
  * RETURN VALUES:
- *      bit position of first free bit in the word or 32 if
+ *	bit position of first free bit in the word or 32 if
  *	no free bits were found.
  */
 static int diFindFree(u32 word, int start)
@@ -2897,7 +2883,7 @@
 		   atomic_read(&imap->im_numfree));
 
 	/*
-	 *      reconstruct imap
+	 *	reconstruct imap
 	 *
 	 * coalesce contiguous k (newAGSize/oldAGSize) AGs;
 	 * i.e., (AGi, ..., AGj) where i = k*n and j = k*(n+1) - 1 to AGn;
@@ -2913,7 +2899,7 @@
 	}
 
 	/*
-	 *      process each iag page of the map.
+	 *	process each iag page of the map.
 	 *
 	 * rebuild AG Free Inode List, AG Free Inode Extent List;
 	 */
@@ -2932,7 +2918,7 @@
 
 		/* leave free iag in the free iag list */
 		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
-		        release_metapage(bp);
+			release_metapage(bp);
 			continue;
 		}
 
@@ -3063,13 +3049,13 @@
 }
 
 /*
- * NAME:        copy_from_dinode()
+ * NAME:	copy_from_dinode()
  *
- * FUNCTION:    Copies inode info from disk inode to in-memory inode
+ * FUNCTION:	Copies inode info from disk inode to in-memory inode
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM	- insufficient memory
+ *	0	- success
+ *	-ENOMEM	- insufficient memory
  */
 static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 {
@@ -3151,9 +3137,9 @@
 }
 
 /*
- * NAME:        copy_to_dinode()
+ * NAME:	copy_to_dinode()
  *
- * FUNCTION:    Copies inode info from in-memory inode to disk inode
+ * FUNCTION:	Copies inode info from in-memory inode to disk inode
  */
 static void copy_to_dinode(struct dinode * dip, struct inode *ip)
 {
diff --git a/fs/jfs/jfs_imap.h b/fs/jfs/jfs_imap.h
index 4f9c346..610a0e9 100644
--- a/fs/jfs/jfs_imap.h
+++ b/fs/jfs/jfs_imap.h
@@ -24,17 +24,17 @@
  *	jfs_imap.h: disk inode manager
  */
 
-#define	EXTSPERIAG	128	/* number of disk inode extent per iag  */
-#define IMAPBLKNO	0	/* lblkno of dinomap within inode map   */
-#define SMAPSZ		4	/* number of words per summary map      */
+#define	EXTSPERIAG	128	/* number of disk inode extent per iag	*/
+#define IMAPBLKNO	0	/* lblkno of dinomap within inode map	*/
+#define SMAPSZ		4	/* number of words per summary map	*/
 #define	EXTSPERSUM	32	/* number of extents per summary map entry */
 #define	L2EXTSPERSUM	5	/* l2 number of extents per summary map */
 #define	PGSPERIEXT	4	/* number of 4K pages per dinode extent */
-#define	MAXIAGS		((1<<20)-1)	/* maximum number of iags       */
-#define	MAXAG		128	/* maximum number of allocation groups  */
+#define	MAXIAGS		((1<<20)-1)	/* maximum number of iags	*/
+#define	MAXAG		128	/* maximum number of allocation groups	*/
 
-#define AMAPSIZE      512	/* bytes in the IAG allocation maps */
-#define SMAPSIZE      16	/* bytes in the IAG summary maps */
+#define AMAPSIZE	512	/* bytes in the IAG allocation maps */
+#define SMAPSIZE	16	/* bytes in the IAG summary maps */
 
 /* convert inode number to iag number */
 #define	INOTOIAG(ino)	((ino) >> L2INOSPERIAG)
@@ -60,31 +60,31 @@
  *	inode allocation group page (per 4096 inodes of an AG)
  */
 struct iag {
-	__le64 agstart;		/* 8: starting block of ag              */
-	__le32 iagnum;		/* 4: inode allocation group number     */
-	__le32 inofreefwd;	/* 4: ag inode free list forward        */
-	__le32 inofreeback;	/* 4: ag inode free list back           */
-	__le32 extfreefwd;	/* 4: ag inode extent free list forward */
-	__le32 extfreeback;	/* 4: ag inode extent free list back    */
-	__le32 iagfree;		/* 4: iag free list                     */
+	__le64 agstart;		/* 8: starting block of ag		*/
+	__le32 iagnum;		/* 4: inode allocation group number	*/
+	__le32 inofreefwd;	/* 4: ag inode free list forward	*/
+	__le32 inofreeback;	/* 4: ag inode free list back		*/
+	__le32 extfreefwd;	/* 4: ag inode extent free list forward	*/
+	__le32 extfreeback;	/* 4: ag inode extent free list back	*/
+	__le32 iagfree;		/* 4: iag free list			*/
 
 	/* summary map: 1 bit per inode extent */
 	__le32 inosmap[SMAPSZ];	/* 16: sum map of mapwords w/ free inodes;
-				 *      note: this indicates free and backed
-				 *      inodes, if the extent is not backed the
-				 *      value will be 1.  if the extent is
-				 *      backed but all inodes are being used the
-				 *      value will be 1.  if the extent is
-				 *      backed but at least one of the inodes is
-				 *      free the value will be 0.
+				 *	note: this indicates free and backed
+				 *	inodes, if the extent is not backed the
+				 *	value will be 1.  if the extent is
+				 *	backed but all inodes are being used the
+				 *	value will be 1.  if the extent is
+				 *	backed but at least one of the inodes is
+				 *	free the value will be 0.
 				 */
 	__le32 extsmap[SMAPSZ];	/* 16: sum map of mapwords w/ free extents */
-	__le32 nfreeinos;		/* 4: number of free inodes             */
-	__le32 nfreeexts;		/* 4: number of free extents            */
+	__le32 nfreeinos;	/* 4: number of free inodes		*/
+	__le32 nfreeexts;	/* 4: number of free extents		*/
 	/* (72) */
 	u8 pad[1976];		/* 1976: pad to 2048 bytes */
 	/* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */
-	__le32 wmap[EXTSPERIAG];	/* 512: working allocation map  */
+	__le32 wmap[EXTSPERIAG];	/* 512: working allocation map */
 	__le32 pmap[EXTSPERIAG];	/* 512: persistent allocation map */
 	pxd_t inoext[EXTSPERIAG];	/* 1024: inode extent addresses */
 };				/* (4096) */
@@ -93,44 +93,44 @@
  *	per AG control information (in inode map control page)
  */
 struct iagctl_disk {
-	__le32 inofree;		/* 4: free inode list anchor            */
-	__le32 extfree;		/* 4: free extent list anchor           */
-	__le32 numinos;		/* 4: number of backed inodes           */
-	__le32 numfree;		/* 4: number of free inodes             */
+	__le32 inofree;		/* 4: free inode list anchor		*/
+	__le32 extfree;		/* 4: free extent list anchor		*/
+	__le32 numinos;		/* 4: number of backed inodes		*/
+	__le32 numfree;		/* 4: number of free inodes		*/
 };				/* (16) */
 
 struct iagctl {
-	int inofree;		/* free inode list anchor            */
-	int extfree;		/* free extent list anchor           */
-	int numinos;		/* number of backed inodes           */
-	int numfree;		/* number of free inodes             */
+	int inofree;		/* free inode list anchor		*/
+	int extfree;		/* free extent list anchor		*/
+	int numinos;		/* number of backed inodes		*/
+	int numfree;		/* number of free inodes		*/
 };
 
 /*
  *	per fileset/aggregate inode map control page
  */
 struct dinomap_disk {
-	__le32 in_freeiag;	/* 4: free iag list anchor     */
-	__le32 in_nextiag;	/* 4: next free iag number     */
-	__le32 in_numinos;	/* 4: num of backed inodes */
+	__le32 in_freeiag;	/* 4: free iag list anchor	*/
+	__le32 in_nextiag;	/* 4: next free iag number	*/
+	__le32 in_numinos;	/* 4: num of backed inodes	*/
 	__le32 in_numfree;	/* 4: num of free backed inodes */
 	__le32 in_nbperiext;	/* 4: num of blocks per inode extent */
-	__le32 in_l2nbperiext;	/* 4: l2 of in_nbperiext */
-	__le32 in_diskblock;	/* 4: for standalone test driver  */
-	__le32 in_maxag;	/* 4: for standalone test driver  */
-	u8 pad[2016];		/* 2016: pad to 2048 */
+	__le32 in_l2nbperiext;	/* 4: l2 of in_nbperiext	*/
+	__le32 in_diskblock;	/* 4: for standalone test driver */
+	__le32 in_maxag;	/* 4: for standalone test driver */
+	u8 pad[2016];		/* 2016: pad to 2048		*/
 	struct iagctl_disk in_agctl[MAXAG]; /* 2048: AG control information */
 };				/* (4096) */
 
 struct dinomap {
-	int in_freeiag;		/* free iag list anchor     */
-	int in_nextiag;		/* next free iag number     */
-	int in_numinos;		/* num of backed inodes */
-	int in_numfree;		/* num of free backed inodes */
+	int in_freeiag;		/* free iag list anchor		*/
+	int in_nextiag;		/* next free iag number		*/
+	int in_numinos;		/* num of backed inodes		*/
+	int in_numfree;		/* num of free backed inodes	*/
 	int in_nbperiext;	/* num of blocks per inode extent */
-	int in_l2nbperiext;	/* l2 of in_nbperiext */
-	int in_diskblock;	/* for standalone test driver  */
-	int in_maxag;		/* for standalone test driver  */
+	int in_l2nbperiext;	/* l2 of in_nbperiext		*/
+	int in_diskblock;	/* for standalone test driver	*/
+	int in_maxag;		/* for standalone test driver	*/
 	struct iagctl in_agctl[MAXAG];	/* AG control information */
 };
 
@@ -139,9 +139,9 @@
  */
 struct inomap {
 	struct dinomap im_imap;		/* 4096: inode allocation control */
-	struct inode *im_ipimap;	/* 4: ptr to inode for imap   */
-	struct mutex im_freelock;	/* 4: iag free list lock      */
-	struct mutex im_aglock[MAXAG];	/* 512: per AG locks          */
+	struct inode *im_ipimap;	/* 4: ptr to inode for imap	*/
+	struct mutex im_freelock;	/* 4: iag free list lock	*/
+	struct mutex im_aglock[MAXAG];	/* 512: per AG locks		*/
 	u32 *im_DBGdimap;
 	atomic_t im_numinos;	/* num of backed inodes */
 	atomic_t im_numfree;	/* num of free backed inodes */
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index 8f453ef..cb8f309 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -40,7 +40,7 @@
 	uint	mode2;		/* jfs-specific mode		*/
 	uint	saved_uid;	/* saved for uid mount option */
 	uint	saved_gid;	/* saved for gid mount option */
-	pxd_t   ixpxd;		/* inode extent descriptor	*/
+	pxd_t	ixpxd;		/* inode extent descriptor	*/
 	dxd_t	acl;		/* dxd describing acl	*/
 	dxd_t	ea;		/* dxd describing ea	*/
 	time_t	otime;		/* time created	*/
@@ -190,7 +190,7 @@
 	uint		gengen;		/* inode generation generator*/
 	uint		inostamp;	/* shows inode belongs to fileset*/
 
-        /* Formerly in ipbmap */
+	/* Formerly in ipbmap */
 	struct bmap	*bmap;		/* incore bmap descriptor	*/
 	struct nls_table *nls_tab;	/* current codepage		*/
 	struct inode *direct_inode;	/* metadata inode */
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 2374b59..f0ec72b 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -32,6 +32,7 @@
 extern void jfs_free_zero_link(struct inode *);
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
 extern void jfs_get_inode_flags(struct jfs_inode_info *);
+extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp);
 extern void jfs_set_inode_flags(struct inode *);
 extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 44a2f33..de3e4a5 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -244,7 +244,7 @@
 		goto writeRecord;
 
 	/*
-	 *      initialize/update page/transaction recovery lsn
+	 *	initialize/update page/transaction recovery lsn
 	 */
 	lsn = log->lsn;
 
@@ -263,7 +263,7 @@
 	}
 
 	/*
-	 *      initialize/update lsn of tblock of the page
+	 *	initialize/update lsn of tblock of the page
 	 *
 	 * transaction inherits oldest lsn of pages associated
 	 * with allocation/deallocation of resources (their
@@ -307,7 +307,7 @@
 	LOGSYNC_UNLOCK(log, flags);
 
 	/*
-	 *      write the log record
+	 *	write the log record
 	 */
       writeRecord:
 	lsn = lmWriteRecord(log, tblk, lrd, tlck);
@@ -372,7 +372,7 @@
 		goto moveLrd;
 
 	/*
-	 *      move log record data
+	 *	move log record data
 	 */
 	/* retrieve source meta-data page to log */
 	if (tlck->flag & tlckPAGELOCK) {
@@ -465,7 +465,7 @@
 	}
 
 	/*
-	 *      move log record descriptor
+	 *	move log record descriptor
 	 */
       moveLrd:
 	lrd->length = cpu_to_le16(len);
@@ -574,7 +574,7 @@
 	LOGGC_LOCK(log);
 
 	/*
-	 *      write or queue the full page at the tail of write queue
+	 *	write or queue the full page at the tail of write queue
 	 */
 	/* get the tail tblk on commit queue */
 	if (list_empty(&log->cqueue))
@@ -625,7 +625,7 @@
 	LOGGC_UNLOCK(log);
 
 	/*
-	 *      allocate/initialize next page
+	 *	allocate/initialize next page
 	 */
 	/* if log wraps, the first data page of log is 2
 	 * (0 never used, 1 is superblock).
@@ -953,7 +953,7 @@
 		}
 
 	/*
-	 *      forward syncpt
+	 *	forward syncpt
 	 */
 	/* if last sync is same as last syncpt,
 	 * invoke sync point forward processing to update sync.
@@ -989,7 +989,7 @@
 		lsn = log->lsn;
 
 	/*
-	 *      setup next syncpt trigger (SWAG)
+	 *	setup next syncpt trigger (SWAG)
 	 */
 	logsize = log->logsize;
 
@@ -1000,11 +1000,11 @@
 	if (more < 2 * LOGPSIZE) {
 		jfs_warn("\n ... Log Wrap ... Log Wrap ... Log Wrap ...\n");
 		/*
-		 *      log wrapping
+		 *	log wrapping
 		 *
 		 * option 1 - panic ? No.!
 		 * option 2 - shutdown file systems
-		 *            associated with log ?
+		 *	      associated with log ?
 		 * option 3 - extend log ?
 		 */
 		/*
@@ -1062,7 +1062,7 @@
 /*
  * NAME:	lmLogOpen()
  *
- * FUNCTION:    open the log on first open;
+ * FUNCTION:	open the log on first open;
  *	insert filesystem in the active list of the log.
  *
  * PARAMETER:	ipmnt	- file system mount inode
@@ -1113,7 +1113,7 @@
 	init_waitqueue_head(&log->syncwait);
 
 	/*
-	 *      external log as separate logical volume
+	 *	external log as separate logical volume
 	 *
 	 * file systems to log may have n-to-1 relationship;
 	 */
@@ -1155,7 +1155,7 @@
 	return 0;
 
 	/*
-	 *      unwind on error
+	 *	unwind on error
 	 */
       shutdown:		/* unwind lbmLogInit() */
 	list_del(&log->journal_list);
@@ -1427,7 +1427,7 @@
 	return 0;
 
 	/*
-	 *      unwind on error
+	 *	unwind on error
 	 */
       errout30:		/* release log page */
 	log->wqueue = NULL;
@@ -1480,7 +1480,7 @@
 
 	if (test_bit(log_INLINELOG, &log->flag)) {
 		/*
-		 *      in-line log in host file system
+		 *	in-line log in host file system
 		 */
 		rc = lmLogShutdown(log);
 		kfree(log);
@@ -1504,7 +1504,7 @@
 		goto out;
 
 	/*
-	 *      external log as separate logical volume
+	 *	external log as separate logical volume
 	 */
 	list_del(&log->journal_list);
 	bdev = log->bdev;
@@ -1622,20 +1622,26 @@
 	if (!list_empty(&log->synclist)) {
 		struct logsyncblk *lp;
 
+		printk(KERN_ERR "jfs_flush_journal: synclist not empty\n");
 		list_for_each_entry(lp, &log->synclist, synclist) {
 			if (lp->xflag & COMMIT_PAGE) {
 				struct metapage *mp = (struct metapage *)lp;
-				dump_mem("orphan metapage", lp,
-					 sizeof(struct metapage));
-				dump_mem("page", mp->page, sizeof(struct page));
-			}
-			else
-				dump_mem("orphan tblock", lp,
-					 sizeof(struct tblock));
+				print_hex_dump(KERN_ERR, "metapage: ",
+					       DUMP_PREFIX_ADDRESS, 16, 4,
+					       mp, sizeof(struct metapage), 0);
+				print_hex_dump(KERN_ERR, "page: ",
+					       DUMP_PREFIX_ADDRESS, 16,
+					       sizeof(long), mp->page,
+					       sizeof(struct page), 0);
+			} else
+				print_hex_dump(KERN_ERR, "tblock:",
+					       DUMP_PREFIX_ADDRESS, 16, 4,
+					       lp, sizeof(struct tblock), 0);
 		}
 	}
+#else
+	WARN_ON(!list_empty(&log->synclist));
 #endif
-	//assert(list_empty(&log->synclist));
 	clear_bit(log_FLUSH, &log->flag);
 }
 
@@ -1723,7 +1729,7 @@
  *
  * PARAMETE:	log	- pointer to logs inode.
  *		fsdev	- kdev_t of filesystem.
- *		serial  - pointer to returned log serial number
+ *		serial	- pointer to returned log serial number
  *		activate - insert/remove device from active list.
  *
  * RETURN:	0	- success
@@ -1963,7 +1969,7 @@
  * FUNCTION:	add a log buffer to the log redrive list
  *
  * PARAMETER:
- *     bp	- log buffer
+ *	bp	- log buffer
  *
  * NOTES:
  *	Takes log_redrive_lock.
@@ -2054,7 +2060,7 @@
 	bp->l_flag = flag;
 
 	/*
-	 *      insert bp at tail of write queue associated with log
+	 *	insert bp at tail of write queue associated with log
 	 *
 	 * (request is either for bp already/currently at head of queue
 	 * or new bp to be inserted at tail)
@@ -2117,7 +2123,7 @@
 	    log->base + (bp->l_pn << (L2LOGPSIZE - log->l2bsize));
 
 	/*
-	 *      initiate pageout of the page
+	 *	initiate pageout of the page
 	 */
 	lbmStartIO(bp);
 }
@@ -2128,7 +2134,7 @@
  *
  * FUNCTION:	Interface to DD strategy routine
  *
- * RETURN:      none
+ * RETURN:	none
  *
  * serialization: LCACHE_LOCK() is NOT held during log i/o;
  */
@@ -2222,7 +2228,7 @@
 	bio_put(bio);
 
 	/*
-	 *      pagein completion
+	 *	pagein completion
 	 */
 	if (bp->l_flag & lbmREAD) {
 		bp->l_flag &= ~lbmREAD;
@@ -2236,7 +2242,7 @@
 	}
 
 	/*
-	 *      pageout completion
+	 *	pageout completion
 	 *
 	 * the bp at the head of write queue has completed pageout.
 	 *
@@ -2302,7 +2308,7 @@
 	}
 
 	/*
-	 *      synchronous pageout:
+	 *	synchronous pageout:
 	 *
 	 * buffer has not necessarily been removed from write queue
 	 * (e.g., synchronous write of partial-page with COMMIT):
@@ -2316,7 +2322,7 @@
 	}
 
 	/*
-	 *      Group Commit pageout:
+	 *	Group Commit pageout:
 	 */
 	else if (bp->l_flag & lbmGC) {
 		LCACHE_UNLOCK(flags);
@@ -2324,7 +2330,7 @@
 	}
 
 	/*
-	 *      asynchronous pageout:
+	 *	asynchronous pageout:
 	 *
 	 * buffer must have been removed from write queue:
 	 * insert buffer at head of freelist where it can be recycled
@@ -2375,7 +2381,7 @@
  * FUNCTION:	format file system log
  *
  * PARAMETERS:
- *      log	- volume log
+ *	log	- volume log
  *	logAddress - start address of log space in FS block
  *	logSize	- length of log space in FS block;
  *
@@ -2407,16 +2413,16 @@
 	npages = logSize >> sbi->l2nbperpage;
 
 	/*
-	 *      log space:
+	 *	log space:
 	 *
 	 * page 0 - reserved;
 	 * page 1 - log superblock;
 	 * page 2 - log data page: A SYNC log record is written
-	 *          into this page at logform time;
+	 *	    into this page at logform time;
 	 * pages 3-N - log data page: set to empty log data pages;
 	 */
 	/*
-	 *      init log superblock: log page 1
+	 *	init log superblock: log page 1
 	 */
 	logsuper = (struct logsuper *) bp->l_ldata;
 
@@ -2436,7 +2442,7 @@
 		goto exit;
 
 	/*
-	 *      init pages 2 to npages-1 as log data pages:
+	 *	init pages 2 to npages-1 as log data pages:
 	 *
 	 * log page sequence number (lpsn) initialization:
 	 *
@@ -2479,7 +2485,7 @@
 		goto exit;
 
 	/*
-	 *      initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
+	 *	initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
 	 */
 	for (lspn = 0; lspn < npages - 3; lspn++) {
 		lp->h.page = lp->t.page = cpu_to_le32(lspn);
@@ -2495,7 +2501,7 @@
 	rc = 0;
 exit:
 	/*
-	 *      finalize log
+	 *	finalize log
 	 */
 	/* release the buffer */
 	lbmFree(bp);
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index a53fb17..1f85ef0 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -144,7 +144,7 @@
  *
  * (this comment should be rewritten !)
  * jfs uses only "after" log records (only a single writer is allowed
- * in a  page, pages are written to temporary paging space if
+ * in a page, pages are written to temporary paging space if
  * if they must be written to disk before commit, and i/o is
  * scheduled for modified pages to their home location after
  * the log records containing the after values and the commit
@@ -153,7 +153,7 @@
  *
  * a log record consists of a data area of variable length followed by
  * a descriptor of fixed size LOGRDSIZE bytes.
- * the  data area is rounded up to an integral number of 4-bytes and
+ * the data area is rounded up to an integral number of 4-bytes and
  * must be no longer than LOGPSIZE.
  * the descriptor is of size of multiple of 4-bytes and aligned on a
  * 4-byte boundary.
@@ -215,13 +215,13 @@
 	union {
 
 		/*
-		 *      COMMIT: commit
+		 *	COMMIT: commit
 		 *
 		 * transaction commit: no type-dependent information;
 		 */
 
 		/*
-		 *      REDOPAGE: after-image
+		 *	REDOPAGE: after-image
 		 *
 		 * apply after-image;
 		 *
@@ -236,7 +236,7 @@
 		} redopage;	/* (20) */
 
 		/*
-		 *      NOREDOPAGE: the page is freed
+		 *	NOREDOPAGE: the page is freed
 		 *
 		 * do not apply after-image records which precede this record
 		 * in the log with the same page block number to this page.
@@ -252,7 +252,7 @@
 		} noredopage;	/* (20) */
 
 		/*
-		 *      UPDATEMAP: update block allocation map
+		 *	UPDATEMAP: update block allocation map
 		 *
 		 * either in-line PXD,
 		 * or     out-of-line  XADLIST;
@@ -268,7 +268,7 @@
 		} updatemap;	/* (20) */
 
 		/*
-		 *      NOREDOINOEXT: the inode extent is freed
+		 *	NOREDOINOEXT: the inode extent is freed
 		 *
 		 * do not apply after-image records which precede this
 		 * record in the log with the any of the 4 page block
@@ -286,7 +286,7 @@
 		} noredoinoext;	/* (20) */
 
 		/*
-		 *      SYNCPT: log sync point
+		 *	SYNCPT: log sync point
 		 *
 		 * replay log upto syncpt address specified;
 		 */
@@ -295,13 +295,13 @@
 		} syncpt;
 
 		/*
-		 *      MOUNT: file system mount
+		 *	MOUNT: file system mount
 		 *
 		 * file system mount: no type-dependent information;
 		 */
 
 		/*
-		 *      ? FREEXTENT: free specified extent(s)
+		 *	? FREEXTENT: free specified extent(s)
 		 *
 		 * free specified extent(s) from block allocation map
 		 * N.B.: nextents should be length of data/sizeof(xad_t)
@@ -314,7 +314,7 @@
 		} freextent;
 
 		/*
-		 *      ? NOREDOFILE: this file is freed
+		 *	? NOREDOFILE: this file is freed
 		 *
 		 * do not apply records which precede this record in the log
 		 * with the same inode number.
@@ -330,7 +330,7 @@
 		} noredofile;
 
 		/*
-		 *      ? NEWPAGE:
+		 *	? NEWPAGE:
 		 *
 		 * metadata type dependent
 		 */
@@ -342,7 +342,7 @@
 		} newpage;
 
 		/*
-		 *      ? DUMMY: filler
+		 *	? DUMMY: filler
 		 *
 		 * no type-dependent information
 		 */
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 43d4f69..77c7f11 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -472,7 +472,8 @@
 	printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
 	goto skip;
 dump_bio:
-	dump_mem("bio", bio, sizeof(*bio));
+	print_hex_dump(KERN_ERR, "JFS: dump of bio: ", DUMP_PREFIX_ADDRESS, 16,
+		       4, bio, sizeof(*bio), 0);
 skip:
 	bio_put(bio);
 	unlock_page(page);
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index 4dd4798..644429a 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -80,7 +80,7 @@
  */
 int jfs_mount(struct super_block *sb)
 {
-	int rc = 0;		/* Return code          */
+	int rc = 0;		/* Return code */
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 	struct inode *ipaimap = NULL;
 	struct inode *ipaimap2 = NULL;
@@ -169,7 +169,7 @@
 		sbi->ipaimap2 = NULL;
 
 	/*
-	 *      mount (the only/single) fileset
+	 *	mount (the only/single) fileset
 	 */
 	/*
 	 * open fileset inode allocation map (aka fileset inode)
@@ -195,7 +195,7 @@
 	goto out;
 
 	/*
-	 *      unwind on error
+	 *	unwind on error
 	 */
       errout41:		/* close fileset inode allocation map inode */
 	diFreeSpecial(ipimap);
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 25430d0..7aa1f70 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -18,7 +18,7 @@
  */
 
 /*
- *      jfs_txnmgr.c: transaction manager
+ *	jfs_txnmgr.c: transaction manager
  *
  * notes:
  * transaction starts with txBegin() and ends with txCommit()
@@ -60,7 +60,7 @@
 #include "jfs_debug.h"
 
 /*
- *      transaction management structures
+ *	transaction management structures
  */
 static struct {
 	int freetid;		/* index of a free tid structure */
@@ -103,19 +103,19 @@
 MODULE_PARM_DESC(nTxLock,
 		 "Number of transaction locks (max:65536)");
 
-struct tblock *TxBlock;	        /* transaction block table */
-static int TxLockLWM;		/* Low water mark for number of txLocks used */
-static int TxLockHWM;		/* High water mark for number of txLocks used */
-static int TxLockVHWM;		/* Very High water mark */
-struct tlock *TxLock;           /* transaction lock table */
+struct tblock *TxBlock;	/* transaction block table */
+static int TxLockLWM;	/* Low water mark for number of txLocks used */
+static int TxLockHWM;	/* High water mark for number of txLocks used */
+static int TxLockVHWM;	/* Very High water mark */
+struct tlock *TxLock;	/* transaction lock table */
 
 /*
- *      transaction management lock
+ *	transaction management lock
  */
 static DEFINE_SPINLOCK(jfsTxnLock);
 
-#define TXN_LOCK()              spin_lock(&jfsTxnLock)
-#define TXN_UNLOCK()            spin_unlock(&jfsTxnLock)
+#define TXN_LOCK()		spin_lock(&jfsTxnLock)
+#define TXN_UNLOCK()		spin_unlock(&jfsTxnLock)
 
 #define LAZY_LOCK_INIT()	spin_lock_init(&TxAnchor.LazyLock);
 #define LAZY_LOCK(flags)	spin_lock_irqsave(&TxAnchor.LazyLock, flags)
@@ -148,7 +148,7 @@
 #define TXN_WAKEUP(event) wake_up_all(event)
 
 /*
- *      statistics
+ *	statistics
  */
 static struct {
 	tid_t maxtid;		/* 4: biggest tid ever used */
@@ -181,8 +181,8 @@
 static void LogSyncRelease(struct metapage * mp);
 
 /*
- *              transaction block/lock management
- *              ---------------------------------
+ *		transaction block/lock management
+ *		---------------------------------
  */
 
 /*
@@ -227,9 +227,9 @@
 }
 
 /*
- * NAME:        txInit()
+ * NAME:	txInit()
  *
- * FUNCTION:    initialize transaction management structures
+ * FUNCTION:	initialize transaction management structures
  *
  * RETURN:
  *
@@ -333,9 +333,9 @@
 }
 
 /*
- * NAME:        txExit()
+ * NAME:	txExit()
  *
- * FUNCTION:    clean up when module is unloaded
+ * FUNCTION:	clean up when module is unloaded
  */
 void txExit(void)
 {
@@ -346,12 +346,12 @@
 }
 
 /*
- * NAME:        txBegin()
+ * NAME:	txBegin()
  *
- * FUNCTION:    start a transaction.
+ * FUNCTION:	start a transaction.
  *
- * PARAMETER:   sb	- superblock
- *              flag	- force for nested tx;
+ * PARAMETER:	sb	- superblock
+ *		flag	- force for nested tx;
  *
  * RETURN:	tid	- transaction id
  *
@@ -447,13 +447,13 @@
 }
 
 /*
- * NAME:        txBeginAnon()
+ * NAME:	txBeginAnon()
  *
- * FUNCTION:    start an anonymous transaction.
+ * FUNCTION:	start an anonymous transaction.
  *		Blocks if logsync or available tlocks are low to prevent
  *		anonymous tlocks from depleting supply.
  *
- * PARAMETER:   sb	- superblock
+ * PARAMETER:	sb	- superblock
  *
  * RETURN:	none
  */
@@ -489,11 +489,11 @@
 }
 
 /*
- *      txEnd()
+ *	txEnd()
  *
  * function: free specified transaction block.
  *
- *      logsync barrier processing:
+ *	logsync barrier processing:
  *
  * serialization:
  */
@@ -577,13 +577,13 @@
 }
 
 /*
- *      txLock()
+ *	txLock()
  *
  * function: acquire a transaction lock on the specified <mp>
  *
  * parameter:
  *
- * return:      transaction lock id
+ * return:	transaction lock id
  *
  * serialization:
  */
@@ -829,12 +829,16 @@
 	/* Only locks on ipimap or ipaimap should reach here */
 	/* assert(jfs_ip->fileset == AGGREGATE_I); */
 	if (jfs_ip->fileset != AGGREGATE_I) {
-		jfs_err("txLock: trying to lock locked page!");
-		dump_mem("ip", ip, sizeof(struct inode));
-		dump_mem("mp", mp, sizeof(struct metapage));
-		dump_mem("Locker's tblk", tid_to_tblock(tid),
-			 sizeof(struct tblock));
-		dump_mem("Tlock", tlck, sizeof(struct tlock));
+		printk(KERN_ERR "txLock: trying to lock locked page!");
+		print_hex_dump(KERN_ERR, "ip: ", DUMP_PREFIX_ADDRESS, 16, 4,
+			       ip, sizeof(*ip), 0);
+		print_hex_dump(KERN_ERR, "mp: ", DUMP_PREFIX_ADDRESS, 16, 4,
+			       mp, sizeof(*mp), 0);
+		print_hex_dump(KERN_ERR, "Locker's tblock: ",
+			       DUMP_PREFIX_ADDRESS, 16, 4, tid_to_tblock(tid),
+			       sizeof(struct tblock), 0);
+		print_hex_dump(KERN_ERR, "Tlock: ", DUMP_PREFIX_ADDRESS, 16, 4,
+			       tlck, sizeof(*tlck), 0);
 		BUG();
 	}
 	INCREMENT(stattx.waitlock);	/* statistics */
@@ -857,17 +861,17 @@
 }
 
 /*
- * NAME:        txRelease()
+ * NAME:	txRelease()
  *
- * FUNCTION:    Release buffers associated with transaction locks, but don't
+ * FUNCTION:	Release buffers associated with transaction locks, but don't
  *		mark homeok yet.  The allows other transactions to modify
  *		buffers, but won't let them go to disk until commit record
  *		actually gets written.
  *
  * PARAMETER:
- *              tblk    -
+ *		tblk	-
  *
- * RETURN:      Errors from subroutines.
+ * RETURN:	Errors from subroutines.
  */
 static void txRelease(struct tblock * tblk)
 {
@@ -896,10 +900,10 @@
 }
 
 /*
- * NAME:        txUnlock()
+ * NAME:	txUnlock()
  *
- * FUNCTION:    Initiates pageout of pages modified by tid in journalled
- *              objects and frees their lockwords.
+ * FUNCTION:	Initiates pageout of pages modified by tid in journalled
+ *		objects and frees their lockwords.
  */
 static void txUnlock(struct tblock * tblk)
 {
@@ -983,10 +987,10 @@
 }
 
 /*
- *      txMaplock()
+ *	txMaplock()
  *
  * function: allocate a transaction lock for freed page/entry;
- *      for freed page, maplock is used as xtlock/dtlock type;
+ *	for freed page, maplock is used as xtlock/dtlock type;
  */
 struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
 {
@@ -1057,7 +1061,7 @@
 }
 
 /*
- *      txLinelock()
+ *	txLinelock()
  *
  * function: allocate a transaction lock for log vector list
  */
@@ -1092,39 +1096,39 @@
 }
 
 /*
- *              transaction commit management
- *              -----------------------------
+ *		transaction commit management
+ *		-----------------------------
  */
 
 /*
- * NAME:        txCommit()
+ * NAME:	txCommit()
  *
- * FUNCTION:    commit the changes to the objects specified in
- *              clist.  For journalled segments only the
- *              changes of the caller are committed, ie by tid.
- *              for non-journalled segments the data are flushed to
- *              disk and then the change to the disk inode and indirect
- *              blocks committed (so blocks newly allocated to the
- *              segment will be made a part of the segment atomically).
+ * FUNCTION:	commit the changes to the objects specified in
+ *		clist.  For journalled segments only the
+ *		changes of the caller are committed, ie by tid.
+ *		for non-journalled segments the data are flushed to
+ *		disk and then the change to the disk inode and indirect
+ *		blocks committed (so blocks newly allocated to the
+ *		segment will be made a part of the segment atomically).
  *
- *              all of the segments specified in clist must be in
- *              one file system. no more than 6 segments are needed
- *              to handle all unix svcs.
+ *		all of the segments specified in clist must be in
+ *		one file system. no more than 6 segments are needed
+ *		to handle all unix svcs.
  *
- *              if the i_nlink field (i.e. disk inode link count)
- *              is zero, and the type of inode is a regular file or
- *              directory, or symbolic link , the inode is truncated
- *              to zero length. the truncation is committed but the
- *              VM resources are unaffected until it is closed (see
- *              iput and iclose).
+ *		if the i_nlink field (i.e. disk inode link count)
+ *		is zero, and the type of inode is a regular file or
+ *		directory, or symbolic link , the inode is truncated
+ *		to zero length. the truncation is committed but the
+ *		VM resources are unaffected until it is closed (see
+ *		iput and iclose).
  *
  * PARAMETER:
  *
  * RETURN:
  *
  * serialization:
- *              on entry the inode lock on each segment is assumed
- *              to be held.
+ *		on entry the inode lock on each segment is assumed
+ *		to be held.
  *
  * i/o error:
  */
@@ -1175,7 +1179,7 @@
 	if ((flag & (COMMIT_FORCE | COMMIT_SYNC)) == 0)
 		tblk->xflag |= COMMIT_LAZY;
 	/*
-	 *      prepare non-journaled objects for commit
+	 *	prepare non-journaled objects for commit
 	 *
 	 * flush data pages of non-journaled file
 	 * to prevent the file getting non-initialized disk blocks
@@ -1186,7 +1190,7 @@
 	cd.nip = nip;
 
 	/*
-	 *      acquire transaction lock on (on-disk) inodes
+	 *	acquire transaction lock on (on-disk) inodes
 	 *
 	 * update on-disk inode from in-memory inode
 	 * acquiring transaction locks for AFTER records
@@ -1262,7 +1266,7 @@
 	}
 
 	/*
-	 *      write log records from transaction locks
+	 *	write log records from transaction locks
 	 *
 	 * txUpdateMap() resets XAD_NEW in XAD.
 	 */
@@ -1294,7 +1298,7 @@
 		!test_cflag(COMMIT_Nolink, tblk->u.ip)));
 
 	/*
-	 *      write COMMIT log record
+	 *	write COMMIT log record
 	 */
 	lrd->type = cpu_to_le16(LOG_COMMIT);
 	lrd->length = 0;
@@ -1303,7 +1307,7 @@
 	lmGroupCommit(log, tblk);
 
 	/*
-	 *      - transaction is now committed -
+	 *	- transaction is now committed -
 	 */
 
 	/*
@@ -1314,11 +1318,11 @@
 		txForce(tblk);
 
 	/*
-	 *      update allocation map.
+	 *	update allocation map.
 	 *
 	 * update inode allocation map and inode:
 	 * free pager lock on memory object of inode if any.
-	 * update  block allocation map.
+	 * update block allocation map.
 	 *
 	 * txUpdateMap() resets XAD_NEW in XAD.
 	 */
@@ -1326,7 +1330,7 @@
 		txUpdateMap(tblk);
 
 	/*
-	 *      free transaction locks and pageout/free pages
+	 *	free transaction locks and pageout/free pages
 	 */
 	txRelease(tblk);
 
@@ -1335,7 +1339,7 @@
 
 
 	/*
-	 *      reset in-memory object state
+	 *	reset in-memory object state
 	 */
 	for (k = 0; k < cd.nip; k++) {
 		ip = cd.iplist[k];
@@ -1358,11 +1362,11 @@
 }
 
 /*
- * NAME:        txLog()
+ * NAME:	txLog()
  *
- * FUNCTION:    Writes AFTER log records for all lines modified
- *              by tid for segments specified by inodes in comdata.
- *              Code assumes only WRITELOCKS are recorded in lockwords.
+ * FUNCTION:	Writes AFTER log records for all lines modified
+ *		by tid for segments specified by inodes in comdata.
+ *		Code assumes only WRITELOCKS are recorded in lockwords.
  *
  * PARAMETERS:
  *
@@ -1421,12 +1425,12 @@
 }
 
 /*
- *      diLog()
+ *	diLog()
  *
- * function:    log inode tlock and format maplock to update bmap;
+ * function:	log inode tlock and format maplock to update bmap;
  */
 static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
-	  struct tlock * tlck, struct commit * cd)
+		 struct tlock * tlck, struct commit * cd)
 {
 	int rc = 0;
 	struct metapage *mp;
@@ -1442,7 +1446,7 @@
 	pxd = &lrd->log.redopage.pxd;
 
 	/*
-	 *      inode after image
+	 *	inode after image
 	 */
 	if (tlck->type & tlckENTRY) {
 		/* log after-image for logredo(): */
@@ -1456,7 +1460,7 @@
 		tlck->flag |= tlckWRITEPAGE;
 	} else if (tlck->type & tlckFREE) {
 		/*
-		 *      free inode extent
+		 *	free inode extent
 		 *
 		 * (pages of the freed inode extent have been invalidated and
 		 * a maplock for free of the extent has been formatted at
@@ -1498,7 +1502,7 @@
 		jfs_err("diLog: UFO type tlck:0x%p", tlck);
 #ifdef  _JFS_WIP
 	/*
-	 *      alloc/free external EA extent
+	 *	alloc/free external EA extent
 	 *
 	 * a maplock for txUpdateMap() to update bPWMAP for alloc/free
 	 * of the extent has been formatted at txLock() time;
@@ -1534,9 +1538,9 @@
 }
 
 /*
- *      dataLog()
+ *	dataLog()
  *
- * function:    log data tlock
+ * function:	log data tlock
  */
 static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 	    struct tlock * tlck)
@@ -1580,9 +1584,9 @@
 }
 
 /*
- *      dtLog()
+ *	dtLog()
  *
- * function:    log dtree tlock and format maplock to update bmap;
+ * function:	log dtree tlock and format maplock to update bmap;
  */
 static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 	   struct tlock * tlck)
@@ -1603,10 +1607,10 @@
 		lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
 
 	/*
-	 *      page extension via relocation: entry insertion;
-	 *      page extension in-place: entry insertion;
-	 *      new right page from page split, reinitialized in-line
-	 *      root from root page split: entry insertion;
+	 *	page extension via relocation: entry insertion;
+	 *	page extension in-place: entry insertion;
+	 *	new right page from page split, reinitialized in-line
+	 *	root from root page split: entry insertion;
 	 */
 	if (tlck->type & (tlckNEW | tlckEXTEND)) {
 		/* log after-image of the new page for logredo():
@@ -1641,8 +1645,8 @@
 	}
 
 	/*
-	 *      entry insertion/deletion,
-	 *      sibling page link update (old right page before split);
+	 *	entry insertion/deletion,
+	 *	sibling page link update (old right page before split);
 	 */
 	if (tlck->type & (tlckENTRY | tlckRELINK)) {
 		/* log after-image for logredo(): */
@@ -1658,11 +1662,11 @@
 	}
 
 	/*
-	 *      page deletion: page has been invalidated
-	 *      page relocation: source extent
+	 *	page deletion: page has been invalidated
+	 *	page relocation: source extent
 	 *
-	 *      a maplock for free of the page has been formatted
-	 *      at txLock() time);
+	 *	a maplock for free of the page has been formatted
+	 *	at txLock() time);
 	 */
 	if (tlck->type & (tlckFREE | tlckRELOCATE)) {
 		/* log LOG_NOREDOPAGE of the deleted page for logredo()
@@ -1683,9 +1687,9 @@
 }
 
 /*
- *      xtLog()
+ *	xtLog()
  *
- * function:    log xtree tlock and format maplock to update bmap;
+ * function:	log xtree tlock and format maplock to update bmap;
  */
 static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 	   struct tlock * tlck)
@@ -1725,8 +1729,8 @@
 	xadlock = (struct xdlistlock *) maplock;
 
 	/*
-	 *      entry insertion/extension;
-	 *      sibling page link update (old right page before split);
+	 *	entry insertion/extension;
+	 *	sibling page link update (old right page before split);
 	 */
 	if (tlck->type & (tlckNEW | tlckGROW | tlckRELINK)) {
 		/* log after-image for logredo():
@@ -1801,7 +1805,7 @@
 	}
 
 	/*
-	 *      page deletion: file deletion/truncation (ref. xtTruncate())
+	 *	page deletion: file deletion/truncation (ref. xtTruncate())
 	 *
 	 * (page will be invalidated after log is written and bmap
 	 * is updated from the page);
@@ -1908,13 +1912,13 @@
 	}
 
 	/*
-	 *      page/entry truncation: file truncation (ref. xtTruncate())
+	 *	page/entry truncation: file truncation (ref. xtTruncate())
 	 *
-	 *     |----------+------+------+---------------|
-	 *                |      |      |
-	 *                |      |     hwm - hwm before truncation
-	 *                |     next - truncation point
-	 *               lwm - lwm before truncation
+	 *	|----------+------+------+---------------|
+	 *		   |      |      |
+	 *		   |      |     hwm - hwm before truncation
+	 *		   |     next - truncation point
+	 *		  lwm - lwm before truncation
 	 * header ?
 	 */
 	if (tlck->type & tlckTRUNCATE) {
@@ -1937,7 +1941,7 @@
 		twm = xtlck->twm.offset;
 
 		/*
-		 *      write log records
+		 *	write log records
 		 */
 		/* log after-image for logredo():
 		 *
@@ -1997,7 +2001,7 @@
 		}
 
 		/*
-		 *      format maplock(s) for txUpdateMap() to update bmap
+		 *	format maplock(s) for txUpdateMap() to update bmap
 		 */
 		maplock->index = 0;
 
@@ -2069,9 +2073,9 @@
 }
 
 /*
- *      mapLog()
+ *	mapLog()
  *
- * function:    log from maplock of freed data extents;
+ * function:	log from maplock of freed data extents;
  */
 static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 		   struct tlock * tlck)
@@ -2081,7 +2085,7 @@
 	pxd_t *pxd;
 
 	/*
-	 *      page relocation: free the source page extent
+	 *	page relocation: free the source page extent
 	 *
 	 * a maplock for txUpdateMap() for free of the page
 	 * has been formatted at txLock() time saving the src
@@ -2155,10 +2159,10 @@
 }
 
 /*
- *      txEA()
+ *	txEA()
  *
- * function:    acquire maplock for EA/ACL extents or
- *              set COMMIT_INLINE flag;
+ * function:	acquire maplock for EA/ACL extents or
+ *		set COMMIT_INLINE flag;
  */
 void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
 {
@@ -2207,10 +2211,10 @@
 }
 
 /*
- *      txForce()
+ *	txForce()
  *
  * function: synchronously write pages locked by transaction
- *              after txLog() but before txUpdateMap();
+ *	     after txLog() but before txUpdateMap();
  */
 static void txForce(struct tblock * tblk)
 {
@@ -2273,10 +2277,10 @@
 }
 
 /*
- *      txUpdateMap()
+ *	txUpdateMap()
  *
- * function:    update persistent allocation map (and working map
- *              if appropriate);
+ * function:	update persistent allocation map (and working map
+ *		if appropriate);
  *
  * parameter:
  */
@@ -2298,7 +2302,7 @@
 
 
 	/*
-	 *      update block allocation map
+	 *	update block allocation map
 	 *
 	 * update allocation state in pmap (and wmap) and
 	 * update lsn of the pmap page;
@@ -2382,7 +2386,7 @@
 		}
 	}
 	/*
-	 *      update inode allocation map
+	 *	update inode allocation map
 	 *
 	 * update allocation state in pmap and
 	 * update lsn of the pmap page;
@@ -2407,24 +2411,24 @@
 }
 
 /*
- *      txAllocPMap()
+ *	txAllocPMap()
  *
  * function: allocate from persistent map;
  *
  * parameter:
- *      ipbmap  -
- *      malock -
- *              xad list:
- *              pxd:
+ *	ipbmap	-
+ *	malock	-
+ *		xad list:
+ *		pxd:
  *
- *      maptype -
- *              allocate from persistent map;
- *              free from persistent map;
- *              (e.g., tmp file - free from working map at releae
- *               of last reference);
- *              free from persistent and working map;
+ *	maptype -
+ *		allocate from persistent map;
+ *		free from persistent map;
+ *		(e.g., tmp file - free from working map at releae
+ *		 of last reference);
+ *		free from persistent and working map;
  *
- *      lsn     - log sequence number;
+ *	lsn	- log sequence number;
  */
 static void txAllocPMap(struct inode *ip, struct maplock * maplock,
 			struct tblock * tblk)
@@ -2478,9 +2482,9 @@
 }
 
 /*
- *      txFreeMap()
+ *	txFreeMap()
  *
- * function:    free from persistent and/or working map;
+ * function:	free from persistent and/or working map;
  *
  * todo: optimization
  */
@@ -2579,9 +2583,9 @@
 }
 
 /*
- *      txFreelock()
+ *	txFreelock()
  *
- * function:    remove tlock from inode anonymous locklist
+ * function:	remove tlock from inode anonymous locklist
  */
 void txFreelock(struct inode *ip)
 {
@@ -2619,7 +2623,7 @@
 }
 
 /*
- *      txAbort()
+ *	txAbort()
  *
  * function: abort tx before commit;
  *
@@ -2679,7 +2683,7 @@
 }
 
 /*
- *      txLazyCommit(void)
+ *	txLazyCommit(void)
  *
  *	All transactions except those changing ipimap (COMMIT_FORCE) are
  *	processed by this routine.  This insures that the inode and block
@@ -2728,7 +2732,7 @@
 }
 
 /*
- *      jfs_lazycommit(void)
+ *	jfs_lazycommit(void)
  *
  *	To be run as a kernel daemon.  If lbmIODone is called in an interrupt
  *	context, or where blocking is not wanted, this routine will process
@@ -2913,7 +2917,7 @@
 }
 
 /*
- *      jfs_sync(void)
+ *	jfs_sync(void)
  *
  *	To be run as a kernel daemon.  This is awakened when tlocks run low.
  *	We write any inodes that have anonymous tlocks so they will become
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index 7863cf2..ab72889 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -94,7 +94,7 @@
  */
 struct tlock {
 	lid_t next;		/* 2: index next lockword on tid locklist
-				 *          next lockword on freelist
+				 *	    next lockword on freelist
 				 */
 	tid_t tid;		/* 2: transaction id holding lock */
 
diff --git a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
index 09b2529..649f981 100644
--- a/fs/jfs/jfs_types.h
+++ b/fs/jfs/jfs_types.h
@@ -21,7 +21,7 @@
 /*
  *	jfs_types.h:
  *
- * basic type/utility  definitions
+ * basic type/utility definitions
  *
  * note: this header file must be the 1st include file
  * of JFS include list in all JFS .c file.
@@ -54,8 +54,8 @@
  */
 
 #define LEFTMOSTONE	0x80000000
-#define	HIGHORDER	0x80000000u	/* high order bit on            */
-#define	ONES		0xffffffffu	/* all bit on                   */
+#define	HIGHORDER	0x80000000u	/* high order bit on	*/
+#define	ONES		0xffffffffu	/* all bit on		*/
 
 /*
  *	logical xd (lxd)
@@ -148,7 +148,7 @@
 #define sizeDXD(dxd)	le32_to_cpu((dxd)->size)
 
 /*
- *      directory entry argument
+ *	directory entry argument
  */
 struct component_name {
 	int namlen;
@@ -160,14 +160,14 @@
  *	DASD limit information - stored in directory inode
  */
 struct dasd {
-	u8 thresh;		/* Alert Threshold (in percent) */
-	u8 delta;		/* Alert Threshold delta (in percent)   */
+	u8 thresh;		/* Alert Threshold (in percent)		*/
+	u8 delta;		/* Alert Threshold delta (in percent)	*/
 	u8 rsrvd1;
-	u8 limit_hi;		/* DASD limit (in logical blocks)       */
-	__le32 limit_lo;	/* DASD limit (in logical blocks)       */
+	u8 limit_hi;		/* DASD limit (in logical blocks)	*/
+	__le32 limit_lo;	/* DASD limit (in logical blocks)	*/
 	u8 rsrvd2[3];
-	u8 used_hi;		/* DASD usage (in logical blocks)       */
-	__le32 used_lo;		/* DASD usage (in logical blocks)       */
+	u8 used_hi;		/* DASD usage (in logical blocks)	*/
+	__le32 used_lo;		/* DASD usage (in logical blocks)	*/
 };
 
 #define DASDLIMIT(dasdp) \
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index a386f48..7971f37 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -60,7 +60,7 @@
 	jfs_info("UnMount JFS: sb:0x%p", sb);
 
 	/*
-	 *      update superblock and close log
+	 *	update superblock and close log
 	 *
 	 * if mounted read-write and log based recovery was enabled
 	 */
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index acc97c4..1543906 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -16,7 +16,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 /*
- *      jfs_xtree.c: extent allocation descriptor B+-tree manager
+ *	jfs_xtree.c: extent allocation descriptor B+-tree manager
  */
 
 #include <linux/fs.h>
@@ -32,30 +32,30 @@
 /*
  * xtree local flag
  */
-#define XT_INSERT       0x00000001
+#define XT_INSERT	0x00000001
 
 /*
- *       xtree key/entry comparison: extent offset
+ *	xtree key/entry comparison: extent offset
  *
  * return:
- *      -1: k < start of extent
- *       0: start_of_extent <= k <= end_of_extent
- *       1: k > end_of_extent
+ *	-1: k < start of extent
+ *	 0: start_of_extent <= k <= end_of_extent
+ *	 1: k > end_of_extent
  */
 #define XT_CMP(CMP, K, X, OFFSET64)\
 {\
-        OFFSET64 = offsetXAD(X);\
-        (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
-              ((K) < OFFSET64) ? -1 : 0;\
+	OFFSET64 = offsetXAD(X);\
+	(CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
+		((K) < OFFSET64) ? -1 : 0;\
 }
 
 /* write a xad entry */
 #define XT_PUTENTRY(XAD, FLAG, OFF, LEN, ADDR)\
 {\
-        (XAD)->flag = (FLAG);\
-        XADoffset((XAD), (OFF));\
-        XADlength((XAD), (LEN));\
-        XADaddress((XAD), (ADDR));\
+	(XAD)->flag = (FLAG);\
+	XADoffset((XAD), (OFF));\
+	XADlength((XAD), (LEN));\
+	XADaddress((XAD), (ADDR));\
 }
 
 #define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)
@@ -76,13 +76,13 @@
 			MP = NULL;\
 			RC = -EIO;\
 		}\
-        }\
+	}\
 }
 
 /* for consistency */
 #define XT_PUTPAGE(MP) BT_PUTPAGE(MP)
 
-#define XT_GETSEARCH(IP, LEAF, BN, MP,  P, INDEX) \
+#define XT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
 	BT_GETSEARCH(IP, LEAF, BN, MP, xtpage_t, P, INDEX, i_xtroot)
 /* xtree entry parameter descriptor */
 struct xtsplit {
@@ -97,7 +97,7 @@
 
 
 /*
- *      statistics
+ *	statistics
  */
 #ifdef CONFIG_JFS_STATISTICS
 static struct {
@@ -136,7 +136,7 @@
 #endif				/*  _STILL_TO_PORT */
 
 /*
- *      xtLookup()
+ *	xtLookup()
  *
  * function: map a single page into a physical extent;
  */
@@ -179,7 +179,7 @@
 	}
 
 	/*
-	 *      compute the physical extent covering logical extent
+	 *	compute the physical extent covering logical extent
 	 *
 	 * N.B. search may have failed (e.g., hole in sparse file),
 	 * and returned the index of the next entry.
@@ -220,27 +220,27 @@
 
 
 /*
- *      xtLookupList()
+ *	xtLookupList()
  *
  * function: map a single logical extent into a list of physical extent;
  *
  * parameter:
- *      struct inode    *ip,
- *      struct lxdlist  *lxdlist,       lxd list (in)
- *      struct xadlist  *xadlist,       xad list (in/out)
- *      int		flag)
+ *	struct inode	*ip,
+ *	struct lxdlist	*lxdlist,	lxd list (in)
+ *	struct xadlist	*xadlist,	xad list (in/out)
+ *	int		flag)
  *
  * coverage of lxd by xad under assumption of
  * . lxd's are ordered and disjoint.
  * . xad's are ordered and disjoint.
  *
  * return:
- *      0:      success
+ *	0:	success
  *
  * note: a page being written (even a single byte) is backed fully,
- *      except the last page which is only backed with blocks
- *      required to cover the last byte;
- *      the extent backing a page is fully contained within an xad;
+ *	except the last page which is only backed with blocks
+ *	required to cover the last byte;
+ *	the extent backing a page is fully contained within an xad;
  */
 int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
 		 struct xadlist * xadlist, int flag)
@@ -284,7 +284,7 @@
 		return rc;
 
 	/*
-	 *      compute the physical extent covering logical extent
+	 *	compute the physical extent covering logical extent
 	 *
 	 * N.B. search may have failed (e.g., hole in sparse file),
 	 * and returned the index of the next entry.
@@ -343,7 +343,7 @@
 		if (lstart >= size)
 			goto mapend;
 
-		/* compare with the current xad  */
+		/* compare with the current xad */
 		goto compare1;
 	}
 	/* lxd is covered by xad */
@@ -430,7 +430,7 @@
 	/*
 	 * lxd is partially covered by xad
 	 */
-	else {			/* (xend < lend)  */
+	else {			/* (xend < lend) */
 
 		/*
 		 * get next xad
@@ -477,22 +477,22 @@
 
 
 /*
- *      xtSearch()
+ *	xtSearch()
  *
- * function:    search for the xad entry covering specified offset.
+ * function:	search for the xad entry covering specified offset.
  *
  * parameters:
- *      ip      - file object;
- *      xoff    - extent offset;
- *      nextp	- address of next extent (if any) for search miss
- *      cmpp    - comparison result:
- *      btstack - traverse stack;
- *      flag    - search process flag (XT_INSERT);
+ *	ip	- file object;
+ *	xoff	- extent offset;
+ *	nextp	- address of next extent (if any) for search miss
+ *	cmpp	- comparison result:
+ *	btstack - traverse stack;
+ *	flag	- search process flag (XT_INSERT);
  *
  * returns:
- *      btstack contains (bn, index) of search path traversed to the entry.
- *      *cmpp is set to result of comparison with the entry returned.
- *      the page containing the entry is pinned at exit.
+ *	btstack contains (bn, index) of search path traversed to the entry.
+ *	*cmpp is set to result of comparison with the entry returned.
+ *	the page containing the entry is pinned at exit.
  */
 static int xtSearch(struct inode *ip, s64 xoff,	s64 *nextp,
 		    int *cmpp, struct btstack * btstack, int flag)
@@ -517,7 +517,7 @@
 	btstack->nsplit = 0;
 
 	/*
-	 *      search down tree from root:
+	 *	search down tree from root:
 	 *
 	 * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
 	 * internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -642,7 +642,7 @@
 			XT_CMP(cmp, xoff, &p->xad[index], t64);
 			if (cmp == 0) {
 				/*
-				 *      search hit
+				 *	search hit
 				 */
 				/* search hit - leaf page:
 				 * return the entry found
@@ -692,7 +692,7 @@
 		}
 
 		/*
-		 *      search miss
+		 *	search miss
 		 *
 		 * base is the smallest index with key (Kj) greater than
 		 * search key (K) and may be zero or maxentry index.
@@ -773,22 +773,22 @@
 }
 
 /*
- *      xtInsert()
+ *	xtInsert()
  *
  * function:
  *
  * parameter:
- *      tid     - transaction id;
- *      ip      - file object;
- *      xflag   - extent flag (XAD_NOTRECORDED):
- *      xoff    - extent offset;
- *      xlen    - extent length;
- *      xaddrp  - extent address pointer (in/out):
- *              if (*xaddrp)
- *                      caller allocated data extent at *xaddrp;
- *              else
- *                      allocate data extent and return its xaddr;
- *      flag    -
+ *	tid	- transaction id;
+ *	ip	- file object;
+ *	xflag	- extent flag (XAD_NOTRECORDED):
+ *	xoff	- extent offset;
+ *	xlen	- extent length;
+ *	xaddrp	- extent address pointer (in/out):
+ *		if (*xaddrp)
+ *			caller allocated data extent at *xaddrp;
+ *		else
+ *			allocate data extent and return its xaddr;
+ *	flag	-
  *
  * return:
  */
@@ -813,7 +813,7 @@
 	jfs_info("xtInsert: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
 
 	/*
-	 *      search for the entry location at which to insert:
+	 *	search for the entry location at which to insert:
 	 *
 	 * xtFastSearch() and xtSearch() both returns (leaf page
 	 * pinned, index at which to insert).
@@ -853,13 +853,13 @@
 	}
 
 	/*
-	 *      insert entry for new extent
+	 *	insert entry for new extent
 	 */
 	xflag |= XAD_NEW;
 
 	/*
-	 *      if the leaf page is full, split the page and
-	 *      propagate up the router entry for the new page from split
+	 *	if the leaf page is full, split the page and
+	 *	propagate up the router entry for the new page from split
 	 *
 	 * The xtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -886,7 +886,7 @@
 	}
 
 	/*
-	 *      insert the new entry into the leaf page
+	 *	insert the new entry into the leaf page
 	 */
 	/*
 	 * acquire a transaction lock on the leaf page;
@@ -930,16 +930,16 @@
 
 
 /*
- *      xtSplitUp()
+ *	xtSplitUp()
  *
  * function:
- *      split full pages as propagating insertion up the tree
+ *	split full pages as propagating insertion up the tree
  *
  * parameter:
- *      tid     - transaction id;
- *      ip      - file object;
- *      split   - entry parameter descriptor;
- *      btstack - traverse stack from xtSearch()
+ *	tid	- transaction id;
+ *	ip	- file object;
+ *	split	- entry parameter descriptor;
+ *	btstack - traverse stack from xtSearch()
  *
  * return:
  */
@@ -1199,22 +1199,22 @@
 
 
 /*
- *      xtSplitPage()
+ *	xtSplitPage()
  *
  * function:
- *      split a full non-root page into
- *      original/split/left page and new right page
- *      i.e., the original/split page remains as left page.
+ *	split a full non-root page into
+ *	original/split/left page and new right page
+ *	i.e., the original/split page remains as left page.
  *
  * parameter:
- *      int		tid,
- *      struct inode    *ip,
- *      struct xtsplit  *split,
- *      struct metapage	**rmpp,
- *      u64		*rbnp,
+ *	int		tid,
+ *	struct inode	*ip,
+ *	struct xtsplit	*split,
+ *	struct metapage	**rmpp,
+ *	u64		*rbnp,
  *
  * return:
- *      Pointer to page in which to insert or NULL on error.
+ *	Pointer to page in which to insert or NULL on error.
  */
 static int
 xtSplitPage(tid_t tid, struct inode *ip,
@@ -1248,9 +1248,9 @@
 	rbn = addressPXD(pxd);
 
 	/* Allocate blocks to quota. */
-       if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
-	       rc = -EDQUOT;
-	       goto clean_up;
+	if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		rc = -EDQUOT;
+		goto clean_up;
 	}
 
 	quota_allocation += lengthPXD(pxd);
@@ -1304,7 +1304,7 @@
 	skip = split->index;
 
 	/*
-	 *      sequential append at tail (after last entry of last page)
+	 *	sequential append at tail (after last entry of last page)
 	 *
 	 * if splitting the last page on a level because of appending
 	 * a entry to it (skip is maxentry), it's likely that the access is
@@ -1342,7 +1342,7 @@
 	}
 
 	/*
-	 *      non-sequential insert (at possibly middle page)
+	 *	non-sequential insert (at possibly middle page)
 	 */
 
 	/*
@@ -1465,25 +1465,24 @@
 
 
 /*
- *      xtSplitRoot()
+ *	xtSplitRoot()
  *
  * function:
- *      split the full root page into
- *      original/root/split page and new right page
- *      i.e., root remains fixed in tree anchor (inode) and
- *      the root is copied to a single new right child page
- *      since root page << non-root page, and
- *      the split root page contains a single entry for the
- *      new right child page.
+ *	split the full root page into original/root/split page and new
+ *	right page
+ *	i.e., root remains fixed in tree anchor (inode) and the root is
+ *	copied to a single new right child page since root page <<
+ *	non-root page, and the split root page contains a single entry
+ *	for the new right child page.
  *
  * parameter:
- *      int		tid,
- *      struct inode    *ip,
- *      struct xtsplit  *split,
- *      struct metapage	**rmpp)
+ *	int		tid,
+ *	struct inode	*ip,
+ *	struct xtsplit	*split,
+ *	struct metapage	**rmpp)
  *
  * return:
- *      Pointer to page in which to insert or NULL on error.
+ *	Pointer to page in which to insert or NULL on error.
  */
 static int
 xtSplitRoot(tid_t tid,
@@ -1505,7 +1504,7 @@
 	INCREMENT(xtStat.split);
 
 	/*
-	 *      allocate a single (right) child page
+	 *	allocate a single (right) child page
 	 */
 	pxdlist = split->pxdlist;
 	pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1573,7 +1572,7 @@
 	}
 
 	/*
-	 *      reset the root
+	 *	reset the root
 	 *
 	 * init root with the single entry for the new right page
 	 * set the 1st entry offset to 0, which force the left-most key
@@ -1610,7 +1609,7 @@
 
 
 /*
- *      xtExtend()
+ *	xtExtend()
  *
  * function: extend in-place;
  *
@@ -1677,7 +1676,7 @@
 		goto extendOld;
 
 	/*
-	 *      extent overflow: insert entry for new extent
+	 *	extent overflow: insert entry for new extent
 	 */
 //insertNew:
 	xoff = offsetXAD(xad) + MAXXLEN;
@@ -1685,8 +1684,8 @@
 	nextindex = le16_to_cpu(p->header.nextindex);
 
 	/*
-	 *      if the leaf page is full, insert the new entry and
-	 *      propagate up the router entry for the new page from split
+	 *	if the leaf page is full, insert the new entry and
+	 *	propagate up the router entry for the new page from split
 	 *
 	 * The xtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -1731,7 +1730,7 @@
 		}
 	}
 	/*
-	 *      insert the new entry into the leaf page
+	 *	insert the new entry into the leaf page
 	 */
 	else {
 		/* insert the new entry: mark the entry NEW */
@@ -1771,11 +1770,11 @@
 
 #ifdef _NOTYET
 /*
- *      xtTailgate()
+ *	xtTailgate()
  *
  * function: split existing 'tail' extent
- *      (split offset >= start offset of tail extent), and
- *      relocate and extend the split tail half;
+ *	(split offset >= start offset of tail extent), and
+ *	relocate and extend the split tail half;
  *
  * note: existing extent may or may not have been committed.
  * caller is responsible for pager buffer cache update, and
@@ -1804,7 +1803,7 @@
 
 /*
 printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
-        (ulong)xoff, xlen, (ulong)xaddr);
+	(ulong)xoff, xlen, (ulong)xaddr);
 */
 
 	/* there must exist extent to be tailgated */
@@ -1842,18 +1841,18 @@
 	xad = &p->xad[index];
 /*
 printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
-        (ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
+	(ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
 */
 	if ((llen = xoff - offsetXAD(xad)) == 0)
 		goto updateOld;
 
 	/*
-	 *      partially replace extent: insert entry for new extent
+	 *	partially replace extent: insert entry for new extent
 	 */
 //insertNew:
 	/*
-	 *      if the leaf page is full, insert the new entry and
-	 *      propagate up the router entry for the new page from split
+	 *	if the leaf page is full, insert the new entry and
+	 *	propagate up the router entry for the new page from split
 	 *
 	 * The xtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -1898,7 +1897,7 @@
 		}
 	}
 	/*
-	 *      insert the new entry into the leaf page
+	 *	insert the new entry into the leaf page
 	 */
 	else {
 		/* insert the new entry: mark the entry NEW */
@@ -1955,17 +1954,17 @@
 #endif /* _NOTYET */
 
 /*
- *      xtUpdate()
+ *	xtUpdate()
  *
  * function: update XAD;
  *
- *      update extent for allocated_but_not_recorded or
- *      compressed extent;
+ *	update extent for allocated_but_not_recorded or
+ *	compressed extent;
  *
  * parameter:
- *      nxad    - new XAD;
- *                logical extent of the specified XAD must be completely
- *                contained by an existing XAD;
+ *	nxad	- new XAD;
+ *		logical extent of the specified XAD must be completely
+ *		contained by an existing XAD;
  */
 int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
 {				/* new XAD */
@@ -2416,19 +2415,19 @@
 
 
 /*
- *      xtAppend()
+ *	xtAppend()
  *
  * function: grow in append mode from contiguous region specified ;
  *
  * parameter:
- *      tid             - transaction id;
- *      ip              - file object;
- *      xflag           - extent flag:
- *      xoff            - extent offset;
- *      maxblocks       - max extent length;
- *      xlen            - extent length (in/out);
- *      xaddrp          - extent address pointer (in/out):
- *      flag            -
+ *	tid		- transaction id;
+ *	ip		- file object;
+ *	xflag		- extent flag:
+ *	xoff		- extent offset;
+ *	maxblocks	- max extent length;
+ *	xlen		- extent length (in/out);
+ *	xaddrp		- extent address pointer (in/out):
+ *	flag		-
  *
  * return:
  */
@@ -2460,7 +2459,7 @@
 		 (ulong) xoff, maxblocks, xlen, (ulong) xaddr);
 
 	/*
-	 *      search for the entry location at which to insert:
+	 *	search for the entry location at which to insert:
 	 *
 	 * xtFastSearch() and xtSearch() both returns (leaf page
 	 * pinned, index at which to insert).
@@ -2482,13 +2481,13 @@
 		xlen = min(xlen, (int)(next - xoff));
 //insert:
 	/*
-	 *      insert entry for new extent
+	 *	insert entry for new extent
 	 */
 	xflag |= XAD_NEW;
 
 	/*
-	 *      if the leaf page is full, split the page and
-	 *      propagate up the router entry for the new page from split
+	 *	if the leaf page is full, split the page and
+	 *	propagate up the router entry for the new page from split
 	 *
 	 * The xtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -2545,7 +2544,7 @@
 	return 0;
 
 	/*
-	 *      insert the new entry into the leaf page
+	 *	insert the new entry into the leaf page
 	 */
       insertLeaf:
 	/*
@@ -2589,17 +2588,17 @@
 
 /* - TBD for defragmentaion/reorganization -
  *
- *      xtDelete()
+ *	xtDelete()
  *
  * function:
- *      delete the entry with the specified key.
+ *	delete the entry with the specified key.
  *
- *      N.B.: whole extent of the entry is assumed to be deleted.
+ *	N.B.: whole extent of the entry is assumed to be deleted.
  *
  * parameter:
  *
  * return:
- *       ENOENT: if the entry is not found.
+ *	ENOENT: if the entry is not found.
  *
  * exception:
  */
@@ -2665,10 +2664,10 @@
 
 /* - TBD for defragmentaion/reorganization -
  *
- *      xtDeleteUp()
+ *	xtDeleteUp()
  *
  * function:
- *      free empty pages as propagating deletion up the tree
+ *	free empty pages as propagating deletion up the tree
  *
  * parameter:
  *
@@ -2815,15 +2814,15 @@
 
 
 /*
- * NAME:        xtRelocate()
+ * NAME:	xtRelocate()
  *
- * FUNCTION:    relocate xtpage or data extent of regular file;
- *              This function is mainly used by defragfs utility.
+ * FUNCTION:	relocate xtpage or data extent of regular file;
+ *		This function is mainly used by defragfs utility.
  *
- * NOTE:        This routine does not have the logic to handle
- *              uncommitted allocated extent. The caller should call
- *              txCommit() to commit all the allocation before call
- *              this routine.
+ * NOTE:	This routine does not have the logic to handle
+ *		uncommitted allocated extent. The caller should call
+ *		txCommit() to commit all the allocation before call
+ *		this routine.
  */
 int
 xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad,	/* old XAD */
@@ -2865,8 +2864,8 @@
 		 xtype, (ulong) xoff, xlen, (ulong) oxaddr, (ulong) nxaddr);
 
 	/*
-	 *      1. get and validate the parent xtpage/xad entry
-	 *      covering the source extent to be relocated;
+	 *	1. get and validate the parent xtpage/xad entry
+	 *	covering the source extent to be relocated;
 	 */
 	if (xtype == DATAEXT) {
 		/* search in leaf entry */
@@ -2910,7 +2909,7 @@
 	jfs_info("xtRelocate: parent xad entry validated.");
 
 	/*
-	 *      2. relocate the extent
+	 *	2. relocate the extent
 	 */
 	if (xtype == DATAEXT) {
 		/* if the extent is allocated-but-not-recorded
@@ -2923,7 +2922,7 @@
 			XT_PUTPAGE(pmp);
 
 		/*
-		 *      cmRelocate()
+		 *	cmRelocate()
 		 *
 		 * copy target data pages to be relocated;
 		 *
@@ -2945,8 +2944,8 @@
 		pno = offset >> CM_L2BSIZE;
 		npages = (nbytes + (CM_BSIZE - 1)) >> CM_L2BSIZE;
 /*
-                npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
-                         (offset >> CM_L2BSIZE) + 1;
+		npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
+			  (offset >> CM_L2BSIZE) + 1;
 */
 		sxaddr = oxaddr;
 		dxaddr = nxaddr;
@@ -2981,7 +2980,7 @@
 
 		XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
 		jfs_info("xtRelocate: target data extent relocated.");
-	} else {		/* (xtype  == XTPAGE) */
+	} else {		/* (xtype == XTPAGE) */
 
 		/*
 		 * read in the target xtpage from the source extent;
@@ -3026,16 +3025,14 @@
 		 */
 		if (lmp) {
 			BT_MARK_DIRTY(lmp, ip);
-			tlck =
-			    txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
+			tlck = txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
 			lp->header.next = cpu_to_le64(nxaddr);
 			XT_PUTPAGE(lmp);
 		}
 
 		if (rmp) {
 			BT_MARK_DIRTY(rmp, ip);
-			tlck =
-			    txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
+			tlck = txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
 			rp->header.prev = cpu_to_le64(nxaddr);
 			XT_PUTPAGE(rmp);
 		}
@@ -3062,7 +3059,7 @@
 		 * scan may be skipped by commit() and logredo();
 		 */
 		BT_MARK_DIRTY(mp, ip);
-		/* tlckNEW init  xtlck->lwm.offset = XTENTRYSTART; */
+		/* tlckNEW init xtlck->lwm.offset = XTENTRYSTART; */
 		tlck = txLock(tid, ip, mp, tlckXTREE | tlckNEW);
 		xtlck = (struct xtlock *) & tlck->lock;
 
@@ -3084,7 +3081,7 @@
 	}
 
 	/*
-	 *      3. acquire maplock for the source extent to be freed;
+	 *	3. acquire maplock for the source extent to be freed;
 	 *
 	 * acquire a maplock saving the src relocated extent address;
 	 * to free of the extent at commit time;
@@ -3105,7 +3102,7 @@
 	 *      is no buffer associated with this lock since the buffer
 	 *      has been redirected to the target location.
 	 */
-	else			/* (xtype  == XTPAGE) */
+	else			/* (xtype == XTPAGE) */
 		tlck = txMaplock(tid, ip, tlckMAP | tlckRELOCATE);
 
 	pxdlock = (struct pxd_lock *) & tlck->lock;
@@ -3115,7 +3112,7 @@
 	pxdlock->index = 1;
 
 	/*
-	 *      4. update the parent xad entry for relocation;
+	 *	4. update the parent xad entry for relocation;
 	 *
 	 * acquire tlck for the parent entry with XAD_NEW as entry
 	 * update which will write LOG_REDOPAGE and update bmap for
@@ -3143,22 +3140,22 @@
 
 
 /*
- *      xtSearchNode()
+ *	xtSearchNode()
  *
- * function:    search for the internal xad entry covering specified extent.
- *              This function is mainly used by defragfs utility.
+ * function:	search for the internal xad entry covering specified extent.
+ *		This function is mainly used by defragfs utility.
  *
  * parameters:
- *      ip      - file object;
- *      xad     - extent to find;
- *      cmpp    - comparison result:
- *      btstack - traverse stack;
- *      flag    - search process flag;
+ *	ip	- file object;
+ *	xad	- extent to find;
+ *	cmpp	- comparison result:
+ *	btstack - traverse stack;
+ *	flag	- search process flag;
  *
  * returns:
- *      btstack contains (bn, index) of search path traversed to the entry.
- *      *cmpp is set to result of comparison with the entry returned.
- *      the page containing the entry is pinned at exit.
+ *	btstack contains (bn, index) of search path traversed to the entry.
+ *	*cmpp is set to result of comparison with the entry returned.
+ *	the page containing the entry is pinned at exit.
  */
 static int xtSearchNode(struct inode *ip, xad_t * xad,	/* required XAD entry */
 			int *cmpp, struct btstack * btstack, int flag)
@@ -3181,7 +3178,7 @@
 	xaddr = addressXAD(xad);
 
 	/*
-	 *      search down tree from root:
+	 *	search down tree from root:
 	 *
 	 * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
 	 * internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -3217,7 +3214,7 @@
 			XT_CMP(cmp, xoff, &p->xad[index], t64);
 			if (cmp == 0) {
 				/*
-				 *      search hit
+				 *	search hit
 				 *
 				 * verify for exact match;
 				 */
@@ -3245,7 +3242,7 @@
 		}
 
 		/*
-		 *      search miss - non-leaf page:
+		 *	search miss - non-leaf page:
 		 *
 		 * base is the smallest index with key (Kj) greater than
 		 * search key (K) and may be zero or maxentry index.
@@ -3268,15 +3265,15 @@
 
 
 /*
- *      xtRelink()
+ *	xtRelink()
  *
  * function:
- *      link around a freed page.
+ *	link around a freed page.
  *
  * Parameter:
- *      int           tid,
- *      struct inode    *ip,
- *      xtpage_t        *p)
+ *	int		tid,
+ *	struct inode	*ip,
+ *	xtpage_t	*p)
  *
  * returns:
  */
@@ -3338,7 +3335,7 @@
 
 
 /*
- *      xtInitRoot()
+ *	xtInitRoot()
  *
  * initialize file root (inline in inode)
  */
@@ -3385,42 +3382,42 @@
 #define MAX_TRUNCATE_LEAVES 50
 
 /*
- *      xtTruncate()
+ *	xtTruncate()
  *
  * function:
- *      traverse for truncation logging backward bottom up;
- *      terminate at the last extent entry at the current subtree
- *      root page covering new down size.
- *      truncation may occur within the last extent entry.
+ *	traverse for truncation logging backward bottom up;
+ *	terminate at the last extent entry at the current subtree
+ *	root page covering new down size.
+ *	truncation may occur within the last extent entry.
  *
  * parameter:
- *      int           tid,
- *      struct inode    *ip,
- *      s64           newsize,
- *      int           type)   {PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
+ *	int		tid,
+ *	struct inode	*ip,
+ *	s64		newsize,
+ *	int		type)	{PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
  *
  * return:
  *
  * note:
- *      PWMAP:
- *       1. truncate (non-COMMIT_NOLINK file)
- *          by jfs_truncate() or jfs_open(O_TRUNC):
- *          xtree is updated;
+ *	PWMAP:
+ *	 1. truncate (non-COMMIT_NOLINK file)
+ *	    by jfs_truncate() or jfs_open(O_TRUNC):
+ *	    xtree is updated;
  *	 2. truncate index table of directory when last entry removed
- *       map update via tlock at commit time;
- *      PMAP:
+ *	map update via tlock at commit time;
+ *	PMAP:
  *	 Call xtTruncate_pmap instead
- *      WMAP:
- *       1. remove (free zero link count) on last reference release
- *          (pmap has been freed at commit zero link count);
- *       2. truncate (COMMIT_NOLINK file, i.e., tmp file):
- *          xtree is updated;
- *       map update directly at truncation time;
+ *	WMAP:
+ *	 1. remove (free zero link count) on last reference release
+ *	    (pmap has been freed at commit zero link count);
+ *	 2. truncate (COMMIT_NOLINK file, i.e., tmp file):
+ *	    xtree is updated;
+ *	 map update directly at truncation time;
  *
- *      if (DELETE)
- *              no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
- *      else if (TRUNCATE)
- *              must write LOG_NOREDOPAGE for deleted index page;
+ *	if (DELETE)
+ *		no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
+ *	else if (TRUNCATE)
+ *		must write LOG_NOREDOPAGE for deleted index page;
  *
  * pages may already have been tlocked by anonymous transactions
  * during file growth (i.e., write) before truncation;
@@ -3493,7 +3490,7 @@
 	 * retained in the new sized file.
 	 * if type is PMAP, the data and index pages are NOT
 	 * freed, and the data and index blocks are NOT freed
-	 * from  working map.
+	 * from working map.
 	 * (this will allow continued access of data/index of
 	 * temporary file (zerolink count file truncated to zero-length)).
 	 */
@@ -3542,7 +3539,7 @@
 		goto getChild;
 
 	/*
-	 *      leaf page
+	 *	leaf page
 	 */
 	freed = 0;
 
@@ -3916,7 +3913,7 @@
 	}
 
 	/*
-	 *      internal page: go down to child page of current entry
+	 *	internal page: go down to child page of current entry
 	 */
       getChild:
 	/* save current parent entry for the child page */
@@ -3965,7 +3962,7 @@
 
 
 /*
- *      xtTruncate_pmap()
+ *	xtTruncate_pmap()
  *
  * function:
  *	Perform truncate to zero lenghth for deleted file, leaving the
@@ -3974,9 +3971,9 @@
  *	is committed to disk.
  *
  * parameter:
- *      tid_t		tid,
- *      struct inode	*ip,
- *      s64		committed_size)
+ *	tid_t		tid,
+ *	struct inode	*ip,
+ *	s64		committed_size)
  *
  * return: new committed size
  *
@@ -4050,7 +4047,7 @@
 	}
 
 	/*
-	 *      leaf page
+	 *	leaf page
 	 */
 
 	if (++locked_leaves > MAX_TRUNCATE_LEAVES) {
@@ -4062,7 +4059,7 @@
 		xoff = offsetXAD(xad);
 		xlen = lengthXAD(xad);
 		XT_PUTPAGE(mp);
-		return  (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
+		return (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
 	}
 	tlck = txLock(tid, ip, mp, tlckXTREE);
 	tlck->type = tlckXTREE | tlckFREE;
@@ -4099,8 +4096,7 @@
 		 */
 		tlck = txLock(tid, ip, mp, tlckXTREE);
 		xtlck = (struct xtlock *) & tlck->lock;
-		xtlck->hwm.offset =
-		    le16_to_cpu(p->header.nextindex) - 1;
+		xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1;
 		tlck->type = tlckXTREE | tlckFREE;
 
 		XT_PUTPAGE(mp);
@@ -4118,7 +4114,7 @@
 	else
 		index--;
 	/*
-	 *      internal page: go down to child page of current entry
+	 *	internal page: go down to child page of current entry
 	 */
       getChild:
 	/* save current parent entry for the child page */
diff --git a/fs/jfs/jfs_xtree.h b/fs/jfs/jfs_xtree.h
index 164f6f2..70815c8a3 100644
--- a/fs/jfs/jfs_xtree.h
+++ b/fs/jfs/jfs_xtree.h
@@ -19,14 +19,14 @@
 #define _H_JFS_XTREE
 
 /*
- *      jfs_xtree.h: extent allocation descriptor B+-tree manager
+ *	jfs_xtree.h: extent allocation descriptor B+-tree manager
  */
 
 #include "jfs_btree.h"
 
 
 /*
- *      extent allocation descriptor (xad)
+ *	extent allocation descriptor (xad)
  */
 typedef struct xad {
 	unsigned flag:8;	/* 1: flag */
@@ -38,30 +38,30 @@
 	__le32 addr2;		/* 4: address in unit of fsblksize */
 } xad_t;			/* (16) */
 
-#define MAXXLEN         ((1 << 24) - 1)
+#define MAXXLEN		((1 << 24) - 1)
 
-#define XTSLOTSIZE      16
-#define L2XTSLOTSIZE    4
+#define XTSLOTSIZE	16
+#define L2XTSLOTSIZE	4
 
 /* xad_t field construction */
 #define XADoffset(xad, offset64)\
 {\
-        (xad)->off1 = ((u64)offset64) >> 32;\
-        (xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\
+	(xad)->off1 = ((u64)offset64) >> 32;\
+	(xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\
 }
 #define XADaddress(xad, address64)\
 {\
-        (xad)->addr1 = ((u64)address64) >> 32;\
-        (xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
+	(xad)->addr1 = ((u64)address64) >> 32;\
+	(xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
 }
-#define XADlength(xad, length32)        (xad)->len = __cpu_to_le24(length32)
+#define XADlength(xad, length32)	(xad)->len = __cpu_to_le24(length32)
 
 /* xad_t field extraction */
 #define offsetXAD(xad)\
-        ( ((s64)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2))
+	( ((s64)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2))
 #define addressXAD(xad)\
-        ( ((s64)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2))
-#define lengthXAD(xad)  __le24_to_cpu((xad)->len)
+	( ((s64)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2))
+#define lengthXAD(xad)	__le24_to_cpu((xad)->len)
 
 /* xad list */
 struct xadlist {
@@ -71,22 +71,22 @@
 };
 
 /* xad_t flags */
-#define XAD_NEW         0x01	/* new */
-#define XAD_EXTENDED    0x02	/* extended */
-#define XAD_COMPRESSED  0x04	/* compressed with recorded length */
+#define XAD_NEW		0x01	/* new */
+#define XAD_EXTENDED	0x02	/* extended */
+#define XAD_COMPRESSED	0x04	/* compressed with recorded length */
 #define XAD_NOTRECORDED 0x08	/* allocated but not recorded */
-#define XAD_COW         0x10	/* copy-on-write */
+#define XAD_COW		0x10	/* copy-on-write */
 
 
 /* possible values for maxentry */
-#define XTROOTINITSLOT_DIR  6
-#define XTROOTINITSLOT  10
-#define XTROOTMAXSLOT   18
-#define XTPAGEMAXSLOT   256
-#define XTENTRYSTART    2
+#define XTROOTINITSLOT_DIR 6
+#define XTROOTINITSLOT	10
+#define XTROOTMAXSLOT	18
+#define XTPAGEMAXSLOT	256
+#define XTENTRYSTART	2
 
 /*
- *      xtree page:
+ *	xtree page:
  */
 typedef union {
 	struct xtheader {
@@ -106,7 +106,7 @@
 } xtpage_t;
 
 /*
- *      external declaration
+ *	external declaration
  */
 extern int xtLookup(struct inode *ip, s64 lstart, s64 llen,
 		    int *pflag, s64 * paddr, int *plen, int flag);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 41c2047..932797b 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -328,7 +328,7 @@
  *		dentry	- child directory dentry
  *
  * RETURN:	-EINVAL	- if name is . or ..
- *		-EINVAL  - if . or .. exist but are invalid.
+ *		-EINVAL - if . or .. exist but are invalid.
  *		errors from subroutines
  *
  * note:
@@ -517,7 +517,7 @@
 	inode_dec_link_count(ip);
 
 	/*
-	 *      commit zero link count object
+	 *	commit zero link count object
 	 */
 	if (ip->i_nlink == 0) {
 		assert(!test_cflag(COMMIT_Nolink, ip));
@@ -596,7 +596,7 @@
 /*
  * NAME:	commitZeroLink()
  *
- * FUNCTION:    for non-directory, called by jfs_remove(),
+ * FUNCTION:	for non-directory, called by jfs_remove(),
  *		truncate a regular file, directory or symbolic
  *		link to zero length. return 0 if type is not
  *		one of these.
@@ -676,7 +676,7 @@
 /*
  * NAME:	jfs_free_zero_link()
  *
- * FUNCTION:    for non-directory, called by iClose(),
+ * FUNCTION:	for non-directory, called by iClose(),
  *		free resources of a file from cache and WORKING map
  *		for a file previously committed with zero link count
  *		while associated with a pager object,
@@ -855,12 +855,12 @@
  * NAME:	jfs_symlink(dip, dentry, name)
  *
  * FUNCTION:	creates a symbolic link to <symlink> by name <name>
- *		        in directory <dip>
+ *			in directory <dip>
  *
- * PARAMETER:	dip	    - parent directory vnode
- *		        dentry	- dentry of symbolic link
- *		        name    - the path name of the existing object
- *			              that will be the source of the link
+ * PARAMETER:	dip	- parent directory vnode
+ *		dentry	- dentry of symbolic link
+ *		name	- the path name of the existing object
+ *			  that will be the source of the link
  *
  * RETURN:	errors from subroutines
  *
@@ -1052,9 +1052,9 @@
 
 
 /*
- * NAME:        jfs_rename
+ * NAME:	jfs_rename
  *
- * FUNCTION:    rename a file or directory
+ * FUNCTION:	rename a file or directory
  */
 static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	       struct inode *new_dir, struct dentry *new_dentry)
@@ -1331,9 +1331,9 @@
 
 
 /*
- * NAME:        jfs_mknod
+ * NAME:	jfs_mknod
  *
- * FUNCTION:    Create a special file (device)
+ * FUNCTION:	Create a special file (device)
  */
 static int jfs_mknod(struct inode *dir, struct dentry *dentry,
 		int mode, dev_t rdev)
@@ -1477,6 +1477,38 @@
 	return dentry;
 }
 
+struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+	    	result = ERR_PTR(-ESTALE);
+		goto out_iput;
+	}
+
+	result = d_alloc_anon(inode);
+	if (!result) {
+		result = ERR_PTR(-ENOMEM);
+		goto out_iput;
+	}
+	return result;
+
+ out_iput:
+	iput(inode);
+	return result;
+}
+
 struct dentry *jfs_get_parent(struct dentry *dentry)
 {
 	struct super_block *sb = dentry->d_inode->i_sb;
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 79d625f..71984ee 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -29,17 +29,17 @@
 #include "jfs_txnmgr.h"
 #include "jfs_debug.h"
 
-#define BITSPERPAGE     (PSIZE << 3)
-#define L2MEGABYTE      20
-#define MEGABYTE        (1 << L2MEGABYTE)
-#define MEGABYTE32     (MEGABYTE << 5)
+#define BITSPERPAGE	(PSIZE << 3)
+#define L2MEGABYTE	20
+#define MEGABYTE	(1 << L2MEGABYTE)
+#define MEGABYTE32	(MEGABYTE << 5)
 
 /* convert block number to bmap file page number */
 #define BLKTODMAPN(b)\
-        (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)
+	(((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)
 
 /*
- *      jfs_extendfs()
+ *	jfs_extendfs()
  *
  * function: extend file system;
  *
@@ -48,9 +48,9 @@
  *                                   workspace  space
  *
  * input:
- *      new LVSize: in LV blocks (required)
- *      new LogSize: in LV blocks (optional)
- *      new FSSize: in LV blocks (optional)
+ *	new LVSize: in LV blocks (required)
+ *	new LogSize: in LV blocks (optional)
+ *	new FSSize: in LV blocks (optional)
  *
  * new configuration:
  * 1. set new LogSize as specified or default from new LVSize;
@@ -125,8 +125,8 @@
 	}
 
 	/*
-	 *      reconfigure LV spaces
-	 *      ---------------------
+	 *	reconfigure LV spaces
+	 *	---------------------
 	 *
 	 * validate new size, or, if not specified, determine new size
 	 */
@@ -198,7 +198,7 @@
 		log_formatted = 1;
 	}
 	/*
-	 *      quiesce file system
+	 *	quiesce file system
 	 *
 	 * (prepare to move the inline log and to prevent map update)
 	 *
@@ -270,8 +270,8 @@
 	}
 
 	/*
-	 *      extend block allocation map
-	 *      ---------------------------
+	 *	extend block allocation map
+	 *	---------------------------
 	 *
 	 * extendfs() for new extension, retry after crash recovery;
 	 *
@@ -283,7 +283,7 @@
 	 *  s_size: aggregate size in physical blocks;
 	 */
 	/*
-	 *      compute the new block allocation map configuration
+	 *	compute the new block allocation map configuration
 	 *
 	 * map dinode:
 	 *  di_size: map file size in byte;
@@ -301,7 +301,7 @@
 	newNpages = BLKTODMAPN(t64) + 1;
 
 	/*
-	 *      extend map from current map (WITHOUT growing mapfile)
+	 *	extend map from current map (WITHOUT growing mapfile)
 	 *
 	 * map new extension with unmapped part of the last partial
 	 * dmap page, if applicable, and extra page(s) allocated
@@ -341,8 +341,8 @@
 	XSize -= nblocks;
 
 	/*
-	 *      grow map file to cover remaining extension
-	 *      and/or one extra dmap page for next extendfs();
+	 *	grow map file to cover remaining extension
+	 *	and/or one extra dmap page for next extendfs();
 	 *
 	 * allocate new map pages and its backing blocks, and
 	 * update map file xtree
@@ -422,8 +422,8 @@
 	dbFinalizeBmap(ipbmap);
 
 	/*
-	 *      update inode allocation map
-	 *      ---------------------------
+	 *	update inode allocation map
+	 *	---------------------------
 	 *
 	 * move iag lists from old to new iag;
 	 * agstart field is not updated for logredo() to reconstruct
@@ -442,8 +442,8 @@
 	}
 
 	/*
-	 *      finalize
-	 *      --------
+	 *	finalize
+	 *	--------
 	 *
 	 * extension is committed when on-disk super block is
 	 * updated with new descriptors: logredo will recover
@@ -480,7 +480,7 @@
 	diFreeSpecial(ipbmap2);
 
 	/*
-	 *      update superblock
+	 *	update superblock
 	 */
 	if ((rc = readSuper(sb, &bh)))
 		goto error_out;
@@ -530,7 +530,7 @@
 
       resume:
 	/*
-	 *      resume file system transactions
+	 *	resume file system transactions
 	 */
 	txResume(sb);
 
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 20e4ac1..929fcec 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -27,6 +27,7 @@
 #include <linux/kthread.h>
 #include <linux/posix_acl.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
 
@@ -737,6 +738,7 @@
 };
 
 static struct export_operations jfs_export_operations = {
+	.get_dentry	= jfs_get_dentry,
 	.get_parent	= jfs_get_parent,
 };
 
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index b753ba2..9b7f2cd 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -63,9 +63,9 @@
  *
  *   On-disk:
  *
- *     FEALISTs are stored on disk using blocks allocated by dbAlloc() and
- *     written directly. An EA list may be in-lined in the inode if there is
- *     sufficient room available.
+ *	FEALISTs are stored on disk using blocks allocated by dbAlloc() and
+ *	written directly. An EA list may be in-lined in the inode if there is
+ *	sufficient room available.
  */
 
 struct ea_buffer {
@@ -590,7 +590,8 @@
       size_check:
 	if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
 		printk(KERN_ERR "ea_get: invalid extended attribute\n");
-		dump_mem("xattr", ea_buf->xattr, ea_size);
+		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
+				     ea_buf->xattr, ea_size, 1);
 		ea_release(inode, ea_buf);
 		rc = -EIO;
 		goto clean_up;
@@ -696,7 +697,7 @@
 	struct posix_acl *acl;
 	int rc;
 
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		return -EPERM;
 
 	/*
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 96070bf..572601e9 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -44,9 +44,8 @@
  */
 static struct nlm_host *
 nlm_lookup_host(int server, const struct sockaddr_in *sin,
-					int proto, int version,
-					const char *hostname,
-					int hostname_len)
+		int proto, int version, const char *hostname,
+		int hostname_len, const struct sockaddr_in *ssin)
 {
 	struct hlist_head *chain;
 	struct hlist_node *pos;
@@ -54,7 +53,9 @@
 	struct nsm_handle *nsm = NULL;
 	int		hash;
 
-	dprintk("lockd: nlm_lookup_host(%u.%u.%u.%u, p=%d, v=%d, my role=%s, name=%.*s)\n",
+	dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
+			", p=%d, v=%d, my role=%s, name=%.*s)\n",
+			NIPQUAD(ssin->sin_addr.s_addr),
 			NIPQUAD(sin->sin_addr.s_addr), proto, version,
 			server? "server" : "client",
 			hostname_len,
@@ -91,6 +92,8 @@
 			continue;
 		if (host->h_server != server)
 			continue;
+		if (!nlm_cmp_addr(&host->h_saddr, ssin))
+			continue;
 
 		/* Move to head of hash chain. */
 		hlist_del(&host->h_hash);
@@ -118,6 +121,7 @@
 	host->h_name	   = nsm->sm_name;
 	host->h_addr       = *sin;
 	host->h_addr.sin_port = 0;	/* ouch! */
+	host->h_saddr	   = *ssin;
 	host->h_version    = version;
 	host->h_proto      = proto;
 	host->h_rpcclnt    = NULL;
@@ -161,15 +165,9 @@
 	 */
 	nsm_unmonitor(host);
 
-	if ((clnt = host->h_rpcclnt) != NULL) {
-		if (atomic_read(&clnt->cl_users)) {
-			printk(KERN_WARNING
-				"lockd: active RPC handle\n");
-			clnt->cl_dead = 1;
-		} else {
-			rpc_destroy_client(host->h_rpcclnt);
-		}
-	}
+	clnt = host->h_rpcclnt;
+	if (clnt != NULL)
+		rpc_shutdown_client(clnt);
 	kfree(host);
 }
 
@@ -180,8 +178,10 @@
 nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
 			const char *hostname, int hostname_len)
 {
+	struct sockaddr_in ssin = {0};
+
 	return nlm_lookup_host(0, sin, proto, version,
-			       hostname, hostname_len);
+			       hostname, hostname_len, &ssin);
 }
 
 /*
@@ -191,9 +191,12 @@
 nlmsvc_lookup_host(struct svc_rqst *rqstp,
 			const char *hostname, int hostname_len)
 {
+	struct sockaddr_in ssin = {0};
+
+	ssin.sin_addr = rqstp->rq_daddr.addr;
 	return nlm_lookup_host(1, svc_addr_in(rqstp),
 			       rqstp->rq_prot, rqstp->rq_vers,
-			       hostname, hostname_len);
+			       hostname, hostname_len, &ssin);
 }
 
 /*
@@ -204,8 +207,9 @@
 {
 	struct rpc_clnt	*clnt;
 
-	dprintk("lockd: nlm_bind_host(%08x)\n",
-			(unsigned)ntohl(host->h_addr.sin_addr.s_addr));
+	dprintk("lockd: nlm_bind_host("NIPQUAD_FMT"->"NIPQUAD_FMT")\n",
+			NIPQUAD(host->h_saddr.sin_addr),
+			NIPQUAD(host->h_addr.sin_addr));
 
 	/* Lock host handle */
 	mutex_lock(&host->h_mutex);
@@ -232,6 +236,7 @@
 			.protocol	= host->h_proto,
 			.address	= (struct sockaddr *)&host->h_addr,
 			.addrsize	= sizeof(host->h_addr),
+			.saddress	= (struct sockaddr *)&host->h_saddr,
 			.timeout	= &timeparms,
 			.servername	= host->h_name,
 			.program	= &nlm_program,
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 2102e2d..3353ed8 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -61,6 +61,7 @@
 			status);
 	else
 		status = 0;
+	rpc_shutdown_client(clnt);
  out:
 	return status;
 }
@@ -138,7 +139,6 @@
 		.program	= &nsm_program,
 		.version	= SM_VERSION,
 		.authflavor	= RPC_AUTH_NULL,
-		.flags		= (RPC_CLNT_CREATE_ONESHOT),
 	};
 
 	return rpc_create(&args);
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 126b1bf..82e2192 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -25,6 +25,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/stats.h>
@@ -75,18 +76,31 @@
 
 static struct ctl_table_header * nlm_sysctl_table;
 
-static unsigned long set_grace_period(void)
+static unsigned long get_lockd_grace_period(void)
 {
-	unsigned long grace_period;
-
 	/* Note: nlm_timeout should always be nonzero */
 	if (nlm_grace_period)
-		grace_period = ((nlm_grace_period + nlm_timeout - 1)
-				/ nlm_timeout) * nlm_timeout * HZ;
+		return roundup(nlm_grace_period, nlm_timeout) * HZ;
 	else
-		grace_period = nlm_timeout * 5 * HZ;
+		return nlm_timeout * 5 * HZ;
+}
+
+unsigned long get_nfs_grace_period(void)
+{
+	unsigned long lockdgrace = get_lockd_grace_period();
+	unsigned long nfsdgrace = 0;
+
+	if (nlmsvc_ops)
+		nfsdgrace = nlmsvc_ops->get_grace_period();
+
+	return max(lockdgrace, nfsdgrace);
+}
+EXPORT_SYMBOL(get_nfs_grace_period);
+
+static unsigned long set_grace_period(void)
+{
 	nlmsvc_grace_period = 1;
-	return grace_period + jiffies;
+	return get_nfs_grace_period() + jiffies;
 }
 
 static inline void clear_grace_period(void)
@@ -119,13 +133,11 @@
 	complete(&lockd_start_done);
 
 	daemonize("lockd");
+	set_freezable();
 
 	/* Process request with signals blocked, but allow SIGKILL.  */
 	allow_signal(SIGKILL);
 
-	/* kick rpciod */
-	rpciod_up();
-
 	dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
 
 	if (!nlm_timeout)
@@ -202,9 +214,6 @@
 	/* Exit the RPC thread */
 	svc_exit_thread(rqstp);
 
-	/* release rpciod */
-	rpciod_down();
-
 	/* Release module */
 	unlock_kernel();
 	module_put_and_exit(0);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index deeb9dc..fbb1d02 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -100,7 +100,6 @@
 static LIST_HEAD(mb_cache_list);
 static LIST_HEAD(mb_cache_lru_list);
 static DEFINE_SPINLOCK(mb_cache_spinlock);
-static struct shrinker *mb_shrinker;
 
 static inline int
 mb_cache_indexes(struct mb_cache *cache)
@@ -118,6 +117,10 @@
 
 static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask);
 
+static struct shrinker mb_cache_shrinker = {
+	.shrink = mb_cache_shrink_fn,
+	.seeks = DEFAULT_SEEKS,
+};
 
 static inline int
 __mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
@@ -662,13 +665,13 @@
 
 static int __init init_mbcache(void)
 {
-	mb_shrinker = set_shrinker(DEFAULT_SEEKS, mb_cache_shrink_fn);
+	register_shrinker(&mb_cache_shrinker);
 	return 0;
 }
 
 static void __exit exit_mbcache(void)
 {
-	remove_shrinker(mb_shrinker);
+	unregister_shrinker(&mb_cache_shrinker);
 }
 
 module_init(init_mbcache)
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index c4a554d..99a12f1 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -15,6 +15,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/bitops.h>
+#include <linux/sched.h>
 
 static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
 
diff --git a/fs/minix/file.c b/fs/minix/file.c
index f92baa1..17765f6 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -23,7 +23,7 @@
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= minix_sync_file,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations minix_file_inode_operations = {
diff --git a/fs/namei.c b/fs/namei.c
index 5e2d98d..defaa47 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1576,7 +1576,7 @@
 
 	/* O_NOATIME can only be set by the owner or superuser */
 	if (flag & O_NOATIME)
-		if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EPERM;
 
 	/*
diff --git a/fs/namespace.c b/fs/namespace.c
index b696e3a..4198003 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -28,6 +28,7 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include "pnode.h"
+#include "internal.h"
 
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
@@ -320,22 +321,16 @@
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
 	struct mnt_namespace *n = m->private;
-	struct list_head *p;
-	loff_t l = *pos;
 
 	down_read(&namespace_sem);
-	list_for_each(p, &n->list)
-		if (!l--)
-			return list_entry(p, struct vfsmount, mnt_list);
-	return NULL;
+	return seq_list_start(&n->list, *pos);
 }
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	struct mnt_namespace *n = m->private;
-	struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
-	(*pos)++;
-	return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list);
+
+	return seq_list_next(v, &n->list, pos);
 }
 
 static void m_stop(struct seq_file *m, void *v)
@@ -350,7 +345,7 @@
 
 static int show_vfsmnt(struct seq_file *m, void *v)
 {
-	struct vfsmount *mnt = v;
+	struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
 	int err = 0;
 	static struct proc_fs_info {
 		int flag;
@@ -405,7 +400,7 @@
 
 static int show_vfsstat(struct seq_file *m, void *v)
 {
-	struct vfsmount *mnt = v;
+	struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
 	int err = 0;
 
 	/* device */
@@ -1457,7 +1452,7 @@
 
 	new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
 	if (!new_ns)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	atomic_set(&new_ns->count, 1);
 	INIT_LIST_HEAD(&new_ns->list);
@@ -1471,7 +1466,7 @@
 	if (!new_ns->root) {
 		up_write(&namespace_sem);
 		kfree(new_ns);
-		return NULL;
+		return ERR_PTR(-ENOMEM);;
 	}
 	spin_lock(&vfsmount_lock);
 	list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
@@ -1515,7 +1510,7 @@
 	return new_ns;
 }
 
-struct mnt_namespace *copy_mnt_ns(int flags, struct mnt_namespace *ns,
+struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
 		struct fs_struct *new_fs)
 {
 	struct mnt_namespace *new_ns;
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index addfd31..2b145de 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/sched.h>
 
 #include <linux/ncp_fs.h>
 #include "ncplib_kernel.h"
@@ -202,7 +203,6 @@
 
 	if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
 		if (pos >= MAX_NON_LFS) {
-			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
 		}
 		if (count > MAX_NON_LFS - (u32)pos) {
@@ -211,7 +211,6 @@
 	}
 	if (pos >= inode->i_sb->s_maxbytes) {
 		if (count || pos > inode->i_sb->s_maxbytes) {
-			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
 		}
 	}
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 8843a83..c67b4bd 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -17,6 +17,7 @@
 #include <linux/highuid.h>
 #include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
+#include <linux/sched.h>
 
 #include <linux/ncp_fs.h>
 
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index f4580b4..b55cb23 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -6,8 +6,8 @@
 
 nfs-y 			:= client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
 			   pagelist.o proc.o read.o symlink.o unlink.o \
-			   write.o namespace.o
-nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o mount_clnt.o      
+			   write.o namespace.o mount_clnt.o
+nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o
 nfs-$(CONFIG_NFS_V3)	+= nfs3proc.o nfs3xdr.o
 nfs-$(CONFIG_NFS_V3_ACL)	+= nfs3acl.o
 nfs-$(CONFIG_NFS_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 75f309c..a796be5 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -14,6 +14,7 @@
 #include <linux/sunrpc/svcsock.h>
 #include <linux/nfs_fs.h>
 #include <linux/mutex.h>
+#include <linux/freezer.h>
 
 #include <net/inet_sock.h>
 
@@ -67,6 +68,7 @@
 	daemonize("nfsv4-svc");
 	/* Process request with signals blocked, but allow SIGKILL.  */
 	allow_signal(SIGKILL);
+	set_freezable();
 
 	complete(&nfs_callback_info.started);
 
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 50c6821..a49f9fe 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -12,7 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-
+#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -102,19 +102,10 @@
 					   int nfsversion)
 {
 	struct nfs_client *clp;
-	int error;
 
 	if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
 		goto error_0;
 
-	error = rpciod_up();
-	if (error < 0) {
-		dprintk("%s: couldn't start rpciod! Error = %d\n",
-				__FUNCTION__, error);
-		goto error_1;
-	}
-	__set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
-
 	if (nfsversion == 4) {
 		if (nfs_callback_up() < 0)
 			goto error_2;
@@ -139,8 +130,6 @@
 #ifdef CONFIG_NFS_V4
 	init_rwsem(&clp->cl_sem);
 	INIT_LIST_HEAD(&clp->cl_delegations);
-	INIT_LIST_HEAD(&clp->cl_state_owners);
-	INIT_LIST_HEAD(&clp->cl_unused);
 	spin_lock_init(&clp->cl_lock);
 	INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
 	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
@@ -154,9 +143,6 @@
 	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
 		nfs_callback_down();
 error_2:
-	rpciod_down();
-	__clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
-error_1:
 	kfree(clp);
 error_0:
 	return NULL;
@@ -167,16 +153,7 @@
 #ifdef CONFIG_NFS_V4
 	if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
 		nfs4_kill_renewd(clp);
-	while (!list_empty(&clp->cl_unused)) {
-		struct nfs4_state_owner *sp;
-
-		sp = list_entry(clp->cl_unused.next,
-				struct nfs4_state_owner,
-				so_list);
-		list_del(&sp->so_list);
-		kfree(sp);
-	}
-	BUG_ON(!list_empty(&clp->cl_state_owners));
+	BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
 	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
 		nfs_idmap_delete(clp);
 #endif
@@ -198,9 +175,6 @@
 	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
 		nfs_callback_down();
 
-	if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
-		rpciod_down();
-
 	kfree(clp->cl_hostname);
 	kfree(clp);
 
@@ -1232,23 +1206,9 @@
  */
 static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	/* lock the list against modification */
 	spin_lock(&nfs_client_lock);
-
-	/* allow for the header line */
-	if (!pos)
-		return SEQ_START_TOKEN;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &nfs_client_list)
-		if (!pos--)
-			break;
-
-	return _p != &nfs_client_list ? _p : NULL;
+	return seq_list_start_head(&nfs_client_list, *_pos);
 }
 
 /*
@@ -1256,14 +1216,7 @@
  */
 static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next;
-
-	return _p != &nfs_client_list ? _p : NULL;
+	return seq_list_next(v, &nfs_client_list, pos);
 }
 
 /*
@@ -1282,7 +1235,7 @@
 	struct nfs_client *clp;
 
 	/* display header on line 1 */
-	if (v == SEQ_START_TOKEN) {
+	if (v == &nfs_client_list) {
 		seq_puts(m, "NV SERVER   PORT USE HOSTNAME\n");
 		return 0;
 	}
@@ -1323,23 +1276,9 @@
  */
 static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	/* lock the list against modification */
 	spin_lock(&nfs_client_lock);
-
-	/* allow for the header line */
-	if (!pos)
-		return SEQ_START_TOKEN;
-	pos--;
-
-	/* find the n'th element in the list */
-	list_for_each(_p, &nfs_volume_list)
-		if (!pos--)
-			break;
-
-	return _p != &nfs_volume_list ? _p : NULL;
+	return seq_list_start_head(&nfs_volume_list, *_pos);
 }
 
 /*
@@ -1347,14 +1286,7 @@
  */
 static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next;
-
-	return _p != &nfs_volume_list ? _p : NULL;
+	return seq_list_next(v, &nfs_volume_list, pos);
 }
 
 /*
@@ -1375,7 +1307,7 @@
 	char dev[8], fsid[17];
 
 	/* display header on line 1 */
-	if (v == SEQ_START_TOKEN) {
+	if (v == &nfs_volume_list) {
 		seq_puts(m, "NV SERVER   PORT DEV     FSID\n");
 		return 0;
 	}
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 7f37d1b..20ac403 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -27,6 +27,13 @@
 	kfree(delegation);
 }
 
+static void nfs_free_delegation_callback(struct rcu_head *head)
+{
+	struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
+
+	nfs_free_delegation(delegation);
+}
+
 static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
 	struct inode *inode = state->inode;
@@ -57,7 +64,7 @@
 	return status;
 }
 
-static void nfs_delegation_claim_opens(struct inode *inode)
+static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_open_context *ctx;
@@ -72,9 +79,11 @@
 			continue;
 		if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
 			continue;
+		if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
+			continue;
 		get_nfs_open_context(ctx);
 		spin_unlock(&inode->i_lock);
-		err = nfs4_open_delegation_recall(ctx->dentry, state);
+		err = nfs4_open_delegation_recall(ctx, state, stateid);
 		if (err >= 0)
 			err = nfs_delegation_claim_locks(ctx, state);
 		put_nfs_open_context(ctx);
@@ -115,10 +124,6 @@
 	struct nfs_delegation *delegation;
 	int status = 0;
 
-	/* Ensure we first revalidate the attributes and page cache! */
-	if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR)))
-		__nfs_revalidate_inode(NFS_SERVER(inode), inode);
-
 	delegation = kmalloc(sizeof(*delegation), GFP_KERNEL);
 	if (delegation == NULL)
 		return -ENOMEM;
@@ -131,10 +136,10 @@
 	delegation->inode = inode;
 
 	spin_lock(&clp->cl_lock);
-	if (nfsi->delegation == NULL) {
-		list_add(&delegation->super_list, &clp->cl_delegations);
-		nfsi->delegation = delegation;
+	if (rcu_dereference(nfsi->delegation) == NULL) {
+		list_add_rcu(&delegation->super_list, &clp->cl_delegations);
 		nfsi->delegation_state = delegation->type;
+		rcu_assign_pointer(nfsi->delegation, delegation);
 		delegation = NULL;
 	} else {
 		if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
@@ -145,6 +150,12 @@
 			status = -EIO;
 		}
 	}
+
+	/* Ensure we revalidate the attributes and page cache! */
+	spin_lock(&inode->i_lock);
+	nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
+	spin_unlock(&inode->i_lock);
+
 	spin_unlock(&clp->cl_lock);
 	kfree(delegation);
 	return status;
@@ -155,7 +166,7 @@
 	int res = 0;
 
 	res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
-	nfs_free_delegation(delegation);
+	call_rcu(&delegation->rcu, nfs_free_delegation_callback);
 	return res;
 }
 
@@ -170,33 +181,55 @@
 /*
  * Basic procedure for returning a delegation to the server
  */
-int __nfs_inode_return_delegation(struct inode *inode)
+static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
 {
 	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
 	struct nfs_inode *nfsi = NFS_I(inode);
-	struct nfs_delegation *delegation;
-	int res = 0;
 
 	nfs_msync_inode(inode);
 	down_read(&clp->cl_sem);
 	/* Guard against new delegated open calls */
 	down_write(&nfsi->rwsem);
-	spin_lock(&clp->cl_lock);
-	delegation = nfsi->delegation;
-	if (delegation != NULL) {
-		list_del_init(&delegation->super_list);
-		nfsi->delegation = NULL;
-		nfsi->delegation_state = 0;
-	}
-	spin_unlock(&clp->cl_lock);
-	nfs_delegation_claim_opens(inode);
+	nfs_delegation_claim_opens(inode, &delegation->stateid);
 	up_write(&nfsi->rwsem);
 	up_read(&clp->cl_sem);
 	nfs_msync_inode(inode);
 
-	if (delegation != NULL)
-		res = nfs_do_return_delegation(inode, delegation);
-	return res;
+	return nfs_do_return_delegation(inode, delegation);
+}
+
+static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
+{
+	struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
+
+	if (delegation == NULL)
+		goto nomatch;
+	if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
+				sizeof(delegation->stateid.data)) != 0)
+		goto nomatch;
+	list_del_rcu(&delegation->super_list);
+	nfsi->delegation_state = 0;
+	rcu_assign_pointer(nfsi->delegation, NULL);
+	return delegation;
+nomatch:
+	return NULL;
+}
+
+int nfs_inode_return_delegation(struct inode *inode)
+{
+	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_delegation *delegation;
+	int err = 0;
+
+	if (rcu_dereference(nfsi->delegation) != NULL) {
+		spin_lock(&clp->cl_lock);
+		delegation = nfs_detach_delegation_locked(nfsi, NULL);
+		spin_unlock(&clp->cl_lock);
+		if (delegation != NULL)
+			err = __nfs_inode_return_delegation(inode, delegation);
+	}
+	return err;
 }
 
 /*
@@ -211,19 +244,23 @@
 	if (clp == NULL)
 		return;
 restart:
-	spin_lock(&clp->cl_lock);
-	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
 		if (delegation->inode->i_sb != sb)
 			continue;
 		inode = igrab(delegation->inode);
 		if (inode == NULL)
 			continue;
+		spin_lock(&clp->cl_lock);
+		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
 		spin_unlock(&clp->cl_lock);
-		nfs_inode_return_delegation(inode);
+		rcu_read_unlock();
+		if (delegation != NULL)
+			__nfs_inode_return_delegation(inode, delegation);
 		iput(inode);
 		goto restart;
 	}
-	spin_unlock(&clp->cl_lock);
+	rcu_read_unlock();
 }
 
 static int nfs_do_expire_all_delegations(void *ptr)
@@ -234,22 +271,26 @@
 
 	allow_signal(SIGKILL);
 restart:
-	spin_lock(&clp->cl_lock);
 	if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
 		goto out;
 	if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
 		goto out;
-	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
 		inode = igrab(delegation->inode);
 		if (inode == NULL)
 			continue;
+		spin_lock(&clp->cl_lock);
+		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
 		spin_unlock(&clp->cl_lock);
-		nfs_inode_return_delegation(inode);
+		rcu_read_unlock();
+		if (delegation)
+			__nfs_inode_return_delegation(inode, delegation);
 		iput(inode);
 		goto restart;
 	}
+	rcu_read_unlock();
 out:
-	spin_unlock(&clp->cl_lock);
 	nfs_put_client(clp);
 	module_put_and_exit(0);
 }
@@ -280,17 +321,21 @@
 	if (clp == NULL)
 		return;
 restart:
-	spin_lock(&clp->cl_lock);
-	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
 		inode = igrab(delegation->inode);
 		if (inode == NULL)
 			continue;
+		spin_lock(&clp->cl_lock);
+		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
 		spin_unlock(&clp->cl_lock);
-		nfs_inode_return_delegation(inode);
+		rcu_read_unlock();
+		if (delegation != NULL)
+			__nfs_inode_return_delegation(inode, delegation);
 		iput(inode);
 		goto restart;
 	}
-	spin_unlock(&clp->cl_lock);
+	rcu_read_unlock();
 }
 
 struct recall_threadargs {
@@ -316,21 +361,14 @@
 	down_read(&clp->cl_sem);
 	down_write(&nfsi->rwsem);
 	spin_lock(&clp->cl_lock);
-	delegation = nfsi->delegation;
-	if (delegation != NULL && memcmp(delegation->stateid.data,
-				args->stateid->data,
-				sizeof(delegation->stateid.data)) == 0) {
-		list_del_init(&delegation->super_list);
-		nfsi->delegation = NULL;
-		nfsi->delegation_state = 0;
+	delegation = nfs_detach_delegation_locked(nfsi, args->stateid);
+	if (delegation != NULL)
 		args->result = 0;
-	} else {
-		delegation = NULL;
+	else
 		args->result = -ENOENT;
-	}
 	spin_unlock(&clp->cl_lock);
 	complete(&args->started);
-	nfs_delegation_claim_opens(inode);
+	nfs_delegation_claim_opens(inode, args->stateid);
 	up_write(&nfsi->rwsem);
 	up_read(&clp->cl_sem);
 	nfs_msync_inode(inode);
@@ -371,14 +409,14 @@
 {
 	struct nfs_delegation *delegation;
 	struct inode *res = NULL;
-	spin_lock(&clp->cl_lock);
-	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
 		if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
 			res = igrab(delegation->inode);
 			break;
 		}
 	}
-	spin_unlock(&clp->cl_lock);
+	rcu_read_unlock();
 	return res;
 }
 
@@ -388,10 +426,10 @@
 void nfs_delegation_mark_reclaim(struct nfs_client *clp)
 {
 	struct nfs_delegation *delegation;
-	spin_lock(&clp->cl_lock);
-	list_for_each_entry(delegation, &clp->cl_delegations, super_list)
+	rcu_read_lock();
+	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
 		delegation->flags |= NFS_DELEGATION_NEED_RECLAIM;
-	spin_unlock(&clp->cl_lock);
+	rcu_read_unlock();
 }
 
 /*
@@ -399,39 +437,35 @@
  */
 void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
 {
-	struct nfs_delegation *delegation, *n;
-	LIST_HEAD(head);
-	spin_lock(&clp->cl_lock);
-	list_for_each_entry_safe(delegation, n, &clp->cl_delegations, super_list) {
+	struct nfs_delegation *delegation;
+restart:
+	rcu_read_lock();
+	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
 		if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0)
 			continue;
-		list_move(&delegation->super_list, &head);
-		NFS_I(delegation->inode)->delegation = NULL;
-		NFS_I(delegation->inode)->delegation_state = 0;
+		spin_lock(&clp->cl_lock);
+		delegation = nfs_detach_delegation_locked(NFS_I(delegation->inode), NULL);
+		spin_unlock(&clp->cl_lock);
+		rcu_read_unlock();
+		if (delegation != NULL)
+			call_rcu(&delegation->rcu, nfs_free_delegation_callback);
+		goto restart;
 	}
-	spin_unlock(&clp->cl_lock);
-	while(!list_empty(&head)) {
-		delegation = list_entry(head.next, struct nfs_delegation, super_list);
-		list_del(&delegation->super_list);
-		nfs_free_delegation(delegation);
-	}
+	rcu_read_unlock();
 }
 
 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
 {
-	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_delegation *delegation;
-	int res = 0;
+	int ret = 0;
 
-	if (nfsi->delegation_state == 0)
-		return 0;
-	spin_lock(&clp->cl_lock);
-	delegation = nfsi->delegation;
+	rcu_read_lock();
+	delegation = rcu_dereference(nfsi->delegation);
 	if (delegation != NULL) {
 		memcpy(dst->data, delegation->stateid.data, sizeof(dst->data));
-		res = 1;
+		ret = 1;
 	}
-	spin_unlock(&clp->cl_lock);
-	return res;
+	rcu_read_unlock();
+	return ret;
 }
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 2cfd4b2..5874ce7 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -22,11 +22,12 @@
 	long flags;
 	loff_t maxsize;
 	__u64 change_attr;
+	struct rcu_head rcu;
 };
 
 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-int __nfs_inode_return_delegation(struct inode *inode);
+int nfs_inode_return_delegation(struct inode *inode);
 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
 
 struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
@@ -39,27 +40,24 @@
 
 /* NFSv4 delegation-related procedures */
 int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
-int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
 int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
 
 static inline int nfs_have_delegation(struct inode *inode, int flags)
 {
+	struct nfs_delegation *delegation;
+	int ret = 0;
+
 	flags &= FMODE_READ|FMODE_WRITE;
-	smp_rmb();
-	if ((NFS_I(inode)->delegation_state & flags) == flags)
-		return 1;
-	return 0;
+	rcu_read_lock();
+	delegation = rcu_dereference(NFS_I(inode)->delegation);
+	if (delegation != NULL && (delegation->type & flags) == flags)
+		ret = 1;
+	rcu_read_unlock();
+	return ret;
 }
 
-static inline int nfs_inode_return_delegation(struct inode *inode)
-{
-	int err = 0;
-
-	if (NFS_I(inode)->delegation != NULL)
-		err = __nfs_inode_return_delegation(inode);
-	return err;
-}
 #else
 static inline int nfs_have_delegation(struct inode *inode, int flags)
 {
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ac92e45..322141f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -33,6 +33,7 @@
 #include <linux/pagevec.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/sched.h>
 
 #include "nfs4_fs.h"
 #include "delegation.h"
@@ -896,14 +897,13 @@
 	return (nd->intent.open.flags & O_EXCL) != 0;
 }
 
-static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir,
-				 struct nfs_fh *fh, struct nfs_fattr *fattr)
+static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 
 	if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
-		/* Revalidate fsid on root dir */
-		return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode);
+		/* Revalidate fsid using the parent directory */
+		return __nfs_revalidate_inode(server, dir);
 	return 0;
 }
 
@@ -945,7 +945,7 @@
 		res = ERR_PTR(error);
 		goto out_unlock;
 	}
-	error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr);
+	error = nfs_reval_fsid(dir, &fattr);
 	if (error < 0) {
 		res = ERR_PTR(error);
 		goto out_unlock;
@@ -1243,7 +1243,7 @@
 	attr.ia_mode = mode;
 	attr.ia_valid = ATTR_MODE;
 
-	if (nd && (nd->flags & LOOKUP_CREATE))
+	if ((nd->flags & LOOKUP_CREATE) != 0)
 		open_flags = nd->intent.open.flags;
 
 	lock_kernel();
@@ -1534,7 +1534,7 @@
 
 	lock_kernel();
 
-	page = alloc_page(GFP_KERNEL);
+	page = alloc_page(GFP_HIGHUSER);
 	if (!page) {
 		unlock_kernel();
 		return -ENOMEM;
@@ -1743,8 +1743,8 @@
 	struct nfs_inode *nfsi;
 	struct nfs_access_entry *cache;
 
-	spin_lock(&nfs_access_lru_lock);
 restart:
+	spin_lock(&nfs_access_lru_lock);
 	list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
 		struct inode *inode;
 
@@ -1769,6 +1769,7 @@
 			clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags);
 		}
 		spin_unlock(&inode->i_lock);
+		spin_unlock(&nfs_access_lru_lock);
 		iput(inode);
 		goto restart;
 	}
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 345aa5c..a5c82b6 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -122,19 +122,25 @@
 	return -EINVAL;
 }
 
-static void nfs_direct_dirty_pages(struct page **pages, int npages)
+static void nfs_direct_dirty_pages(struct page **pages, unsigned int pgbase, size_t count)
 {
-	int i;
+	unsigned int npages;
+	unsigned int i;
+
+	if (count == 0)
+		return;
+	pages += (pgbase >> PAGE_SHIFT);
+	npages = (count + (pgbase & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	for (i = 0; i < npages; i++) {
 		struct page *page = pages[i];
 		if (!PageCompound(page))
-			set_page_dirty_lock(page);
+			set_page_dirty(page);
 	}
 }
 
-static void nfs_direct_release_pages(struct page **pages, int npages)
+static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
 {
-	int i;
+	unsigned int i;
 	for (i = 0; i < npages; i++)
 		page_cache_release(pages[i]);
 }
@@ -162,7 +168,7 @@
 	return dreq;
 }
 
-static void nfs_direct_req_release(struct kref *kref)
+static void nfs_direct_req_free(struct kref *kref)
 {
 	struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref);
 
@@ -171,6 +177,11 @@
 	kmem_cache_free(nfs_direct_cachep, dreq);
 }
 
+static void nfs_direct_req_release(struct nfs_direct_req *dreq)
+{
+	kref_put(&dreq->kref, nfs_direct_req_free);
+}
+
 /*
  * Collects and returns the final error value/byte-count.
  */
@@ -190,7 +201,6 @@
 		result = dreq->count;
 
 out:
-	kref_put(&dreq->kref, nfs_direct_req_release);
 	return (ssize_t) result;
 }
 
@@ -208,7 +218,7 @@
 	}
 	complete_all(&dreq->completion);
 
-	kref_put(&dreq->kref, nfs_direct_req_release);
+	nfs_direct_req_release(dreq);
 }
 
 /*
@@ -224,17 +234,18 @@
 	if (nfs_readpage_result(task, data) != 0)
 		return;
 
-	nfs_direct_dirty_pages(data->pagevec, data->npages);
-	nfs_direct_release_pages(data->pagevec, data->npages);
-
 	spin_lock(&dreq->lock);
-
-	if (likely(task->tk_status >= 0))
-		dreq->count += data->res.count;
-	else
+	if (unlikely(task->tk_status < 0)) {
 		dreq->error = task->tk_status;
-
-	spin_unlock(&dreq->lock);
+		spin_unlock(&dreq->lock);
+	} else {
+		dreq->count += data->res.count;
+		spin_unlock(&dreq->lock);
+		nfs_direct_dirty_pages(data->pagevec,
+				data->args.pgbase,
+				data->res.count);
+	}
+	nfs_direct_release_pages(data->pagevec, data->npages);
 
 	if (put_dreq(dreq))
 		nfs_direct_complete(dreq);
@@ -255,7 +266,7 @@
 static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos)
 {
 	struct nfs_open_context *ctx = dreq->ctx;
-	struct inode *inode = ctx->dentry->d_inode;
+	struct inode *inode = ctx->path.dentry->d_inode;
 	size_t rsize = NFS_SERVER(inode)->rsize;
 	unsigned int pgbase;
 	int result;
@@ -279,12 +290,20 @@
 		result = get_user_pages(current, current->mm, user_addr,
 					data->npages, 1, 0, data->pagevec, NULL);
 		up_read(&current->mm->mmap_sem);
-		if (unlikely(result < data->npages)) {
-			if (result > 0)
-				nfs_direct_release_pages(data->pagevec, result);
+		if (result < 0) {
 			nfs_readdata_release(data);
 			break;
 		}
+		if ((unsigned)result < data->npages) {
+			bytes = result * PAGE_SIZE;
+			if (bytes <= pgbase) {
+				nfs_direct_release_pages(data->pagevec, result);
+				nfs_readdata_release(data);
+				break;
+			}
+			bytes -= pgbase;
+			data->npages = result;
+		}
 
 		get_dreq(dreq);
 
@@ -359,6 +378,7 @@
 	if (!result)
 		result = nfs_direct_wait(dreq);
 	rpc_clnt_sigunmask(clnt, &oldset);
+	nfs_direct_req_release(dreq);
 
 	return result;
 }
@@ -586,7 +606,7 @@
 static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync)
 {
 	struct nfs_open_context *ctx = dreq->ctx;
-	struct inode *inode = ctx->dentry->d_inode;
+	struct inode *inode = ctx->path.dentry->d_inode;
 	size_t wsize = NFS_SERVER(inode)->wsize;
 	unsigned int pgbase;
 	int result;
@@ -610,12 +630,20 @@
 		result = get_user_pages(current, current->mm, user_addr,
 					data->npages, 0, 0, data->pagevec, NULL);
 		up_read(&current->mm->mmap_sem);
-		if (unlikely(result < data->npages)) {
-			if (result > 0)
-				nfs_direct_release_pages(data->pagevec, result);
+		if (result < 0) {
 			nfs_writedata_release(data);
 			break;
 		}
+		if ((unsigned)result < data->npages) {
+			bytes = result * PAGE_SIZE;
+			if (bytes <= pgbase) {
+				nfs_direct_release_pages(data->pagevec, result);
+				nfs_writedata_release(data);
+				break;
+			}
+			bytes -= pgbase;
+			data->npages = result;
+		}
 
 		get_dreq(dreq);
 
@@ -703,6 +731,7 @@
 	if (!result)
 		result = nfs_direct_wait(dreq);
 	rpc_clnt_sigunmask(clnt, &oldset);
+	nfs_direct_req_release(dreq);
 
 	return result;
 }
@@ -744,10 +773,8 @@
 		(unsigned long) count, (long long) pos);
 
 	if (nr_segs != 1)
-		return -EINVAL;
-
-	if (count < 0)
 		goto out;
+
 	retval = -EFAULT;
 	if (!access_ok(VERIFY_WRITE, buf, count))
 		goto out;
@@ -795,7 +822,7 @@
 ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
 				unsigned long nr_segs, loff_t pos)
 {
-	ssize_t retval;
+	ssize_t retval = -EINVAL;
 	struct file *file = iocb->ki_filp;
 	struct address_space *mapping = file->f_mapping;
 	/* XXX: temporary */
@@ -808,7 +835,7 @@
 		(unsigned long) count, (long long) pos);
 
 	if (nr_segs != 1)
-		return -EINVAL;
+		goto out;
 
 	retval = generic_write_checks(file, &pos, &count, 0);
 	if (retval)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 5eaee6d..8689b73 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
+#include <linux/aio.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -40,7 +41,9 @@
 static int nfs_file_release(struct inode *, struct file *);
 static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
-static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
+static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos,
+					struct pipe_inode_info *pipe,
+					size_t count, unsigned int flags);
 static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
 				unsigned long nr_segs, loff_t pos);
 static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
@@ -64,7 +67,7 @@
 	.fsync		= nfs_fsync,
 	.lock		= nfs_lock,
 	.flock		= nfs_flock,
-	.sendfile	= nfs_file_sendfile,
+	.splice_read	= nfs_file_splice_read,
 	.check_flags	= nfs_check_flags,
 };
 
@@ -223,20 +226,21 @@
 }
 
 static ssize_t
-nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
-		read_actor_t actor, void *target)
+nfs_file_splice_read(struct file *filp, loff_t *ppos,
+		     struct pipe_inode_info *pipe, size_t count,
+		     unsigned int flags)
 {
 	struct dentry *dentry = filp->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
 	ssize_t res;
 
-	dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n",
+	dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long long) *ppos);
 
 	res = nfs_revalidate_mapping(inode, filp->f_mapping);
 	if (!res)
-		res = generic_file_sendfile(filp, ppos, count, actor, target);
+		res = generic_file_splice_read(filp, ppos, pipe, count, flags);
 	return res;
 }
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2b26ad7..3d9fccf 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -15,7 +15,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-
+#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -461,14 +461,14 @@
 
 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
 	if (ctx != NULL) {
-		atomic_set(&ctx->count, 1);
-		ctx->dentry = dget(dentry);
-		ctx->vfsmnt = mntget(mnt);
+		ctx->path.dentry = dget(dentry);
+		ctx->path.mnt = mntget(mnt);
 		ctx->cred = get_rpccred(cred);
 		ctx->state = NULL;
 		ctx->lockowner = current->files;
 		ctx->error = 0;
 		ctx->dir_cookie = 0;
+		kref_init(&ctx->kref);
 	}
 	return ctx;
 }
@@ -476,27 +476,33 @@
 struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
 {
 	if (ctx != NULL)
-		atomic_inc(&ctx->count);
+		kref_get(&ctx->kref);
 	return ctx;
 }
 
+static void nfs_free_open_context(struct kref *kref)
+{
+	struct nfs_open_context *ctx = container_of(kref,
+			struct nfs_open_context, kref);
+
+	if (!list_empty(&ctx->list)) {
+		struct inode *inode = ctx->path.dentry->d_inode;
+		spin_lock(&inode->i_lock);
+		list_del(&ctx->list);
+		spin_unlock(&inode->i_lock);
+	}
+	if (ctx->state != NULL)
+		nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+	if (ctx->cred != NULL)
+		put_rpccred(ctx->cred);
+	dput(ctx->path.dentry);
+	mntput(ctx->path.mnt);
+	kfree(ctx);
+}
+
 void put_nfs_open_context(struct nfs_open_context *ctx)
 {
-	if (atomic_dec_and_test(&ctx->count)) {
-		if (!list_empty(&ctx->list)) {
-			struct inode *inode = ctx->dentry->d_inode;
-			spin_lock(&inode->i_lock);
-			list_del(&ctx->list);
-			spin_unlock(&inode->i_lock);
-		}
-		if (ctx->state != NULL)
-			nfs4_close_state(ctx->state, ctx->mode);
-		if (ctx->cred != NULL)
-			put_rpccred(ctx->cred);
-		dput(ctx->dentry);
-		mntput(ctx->vfsmnt);
-		kfree(ctx);
-	}
+	kref_put(&ctx->kref, nfs_free_open_context);
 }
 
 /*
@@ -961,8 +967,8 @@
 		goto out_changed;
 
 	server = NFS_SERVER(inode);
-	/* Update the fsid if and only if this is the root directory */
-	if (inode == inode->i_sb->s_root->d_inode
+	/* Update the fsid? */
+	if (S_ISDIR(inode->i_mode)
 			&& !nfs_fsid_equal(&server->fsid, &fattr->fsid))
 		server->fsid = fattr->fsid;
 
@@ -1066,8 +1072,10 @@
 		invalid &= ~NFS_INO_INVALID_DATA;
 	if (data_stable)
 		invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE);
-	if (!nfs_have_delegation(inode, FMODE_READ))
+	if (!nfs_have_delegation(inode, FMODE_READ) ||
+			(nfsi->cache_validity & NFS_INO_REVAL_FORCED))
 		nfsi->cache_validity |= invalid;
+	nfsi->cache_validity &= ~NFS_INO_REVAL_FORCED;
 
 	return 0;
  out_changed:
@@ -1103,27 +1111,10 @@
  */
 void nfs4_clear_inode(struct inode *inode)
 {
-	struct nfs_inode *nfsi = NFS_I(inode);
-
 	/* If we are holding a delegation, return it! */
 	nfs_inode_return_delegation(inode);
 	/* First call standard NFS clear_inode() code */
 	nfs_clear_inode(inode);
-	/* Now clear out any remaining state */
-	while (!list_empty(&nfsi->open_states)) {
-		struct nfs4_state *state;
-		
-		state = list_entry(nfsi->open_states.next,
-				struct nfs4_state,
-				inode_states);
-		dprintk("%s(%s/%Ld): found unclaimed NFSv4 state %p\n",
-				__FUNCTION__,
-				inode->i_sb->s_id,
-				(long long)NFS_FILEID(inode),
-				state);
-		BUG_ON(atomic_read(&state->count) != 1);
-		nfs4_close_state(state, state->state);
-	}
 }
 #endif
 
@@ -1165,15 +1156,11 @@
 	struct nfs_inode *nfsi = (struct nfs_inode *) foo;
 
 	inode_init_once(&nfsi->vfs_inode);
-	spin_lock_init(&nfsi->req_lock);
-	INIT_LIST_HEAD(&nfsi->dirty);
-	INIT_LIST_HEAD(&nfsi->commit);
 	INIT_LIST_HEAD(&nfsi->open_files);
 	INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
 	INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
 	INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
 	atomic_set(&nfsi->data_updates, 0);
-	nfsi->ndirty = 0;
 	nfsi->ncommit = 0;
 	nfsi->npages = 0;
 	nfs4_init_once(nfsi);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index ad2b40d..76cf55d 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -183,9 +183,9 @@
 /*
  * Calculate the number of 512byte blocks used.
  */
-static inline unsigned long nfs_calc_block_size(u64 tsize)
+static inline blkcnt_t nfs_calc_block_size(u64 tsize)
 {
-	loff_t used = (tsize + 511) >> 9;
+	blkcnt_t used = (tsize + 511) >> 9;
 	return (used > ULONG_MAX) ? ULONG_MAX : used;
 }
 
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index ca5a266..8afd9f7 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -1,7 +1,5 @@
 /*
- * linux/fs/nfs/mount_clnt.c
- *
- * MOUNT client to support NFSroot.
+ * In-kernel MOUNT protocol client
  *
  * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de>
  */
@@ -18,33 +16,31 @@
 #include <linux/nfs_fs.h>
 
 #ifdef RPC_DEBUG
-# define NFSDBG_FACILITY	NFSDBG_ROOT
+# define NFSDBG_FACILITY	NFSDBG_MOUNT
 #endif
 
-/*
-#define MOUNT_PROGRAM		100005
-#define MOUNT_VERSION		1
-#define MOUNT_MNT		1
-#define MOUNT_UMNT		3
- */
-
-static struct rpc_clnt *	mnt_create(char *, struct sockaddr_in *,
-								int, int);
 static struct rpc_program	mnt_program;
 
 struct mnt_fhstatus {
-	unsigned int		status;
-	struct nfs_fh *		fh;
+	u32 status;
+	struct nfs_fh *fh;
 };
 
-/*
- * Obtain an NFS file handle for the given host and path
+/**
+ * nfs_mount - Obtain an NFS file handle for the given host and path
+ * @addr: pointer to server's address
+ * @len: size of server's address
+ * @hostname: name of server host, or NULL
+ * @path: pointer to string containing export path to mount
+ * @version: mount version to use for this request
+ * @protocol: transport protocol to use for thie request
+ * @fh: pointer to location to place returned file handle
+ *
+ * Uses default timeout parameters specified by underlying transport.
  */
-int
-nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
-		int version, int protocol)
+int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
+	      int version, int protocol, struct nfs_fh *fh)
 {
-	struct rpc_clnt		*mnt_clnt;
 	struct mnt_fhstatus	result = {
 		.fh		= fh
 	};
@@ -52,16 +48,25 @@
 		.rpc_argp	= path,
 		.rpc_resp	= &result,
 	};
-	char			hostname[32];
+	struct rpc_create_args args = {
+		.protocol	= protocol,
+		.address	= addr,
+		.addrsize	= len,
+		.servername	= hostname,
+		.program	= &mnt_program,
+		.version	= version,
+		.authflavor	= RPC_AUTH_UNIX,
+		.flags		= RPC_CLNT_CREATE_INTR,
+	};
+	struct rpc_clnt		*mnt_clnt;
 	int			status;
 
-	dprintk("NFS:      nfs_mount(%08x:%s)\n",
-			(unsigned)ntohl(addr->sin_addr.s_addr), path);
+	dprintk("NFS: sending MNT request for %s:%s\n",
+		(hostname ? hostname : "server"), path);
 
-	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr));
-	mnt_clnt = mnt_create(hostname, addr, version, protocol);
+	mnt_clnt = rpc_create(&args);
 	if (IS_ERR(mnt_clnt))
-		return PTR_ERR(mnt_clnt);
+		goto out_clnt_err;
 
 	if (version == NFS_MNT3_VERSION)
 		msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
@@ -69,33 +74,39 @@
 		msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
 
 	status = rpc_call_sync(mnt_clnt, &msg, 0);
-	return status < 0? status : (result.status? -EACCES : 0);
-}
+	rpc_shutdown_client(mnt_clnt);
 
-static struct rpc_clnt *
-mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
-		int protocol)
-{
-	struct rpc_create_args args = {
-		.protocol	= protocol,
-		.address	= (struct sockaddr *)srvaddr,
-		.addrsize	= sizeof(*srvaddr),
-		.servername	= hostname,
-		.program	= &mnt_program,
-		.version	= version,
-		.authflavor	= RPC_AUTH_UNIX,
-		.flags		= (RPC_CLNT_CREATE_ONESHOT |
-				   RPC_CLNT_CREATE_INTR),
-	};
+	if (status < 0)
+		goto out_call_err;
+	if (result.status != 0)
+		goto out_mnt_err;
 
-	return rpc_create(&args);
+	dprintk("NFS: MNT request succeeded\n");
+	status = 0;
+
+out:
+	return status;
+
+out_clnt_err:
+	status = PTR_ERR(mnt_clnt);
+	dprintk("NFS: failed to create RPC client, status=%d\n", status);
+	goto out;
+
+out_call_err:
+	dprintk("NFS: failed to start MNT request, status=%d\n", status);
+	goto out;
+
+out_mnt_err:
+	dprintk("NFS: MNT server returned result %d\n", result.status);
+	status = -EACCES;
+	goto out;
 }
 
 /*
  * XDR encode/decode functions for MOUNT
  */
-static int
-xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const char *path)
+static int xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p,
+			      const char *path)
 {
 	p = xdr_encode_string(p, path);
 
@@ -103,8 +114,8 @@
 	return 0;
 }
 
-static int
-xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
+static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p,
+			       struct mnt_fhstatus *res)
 {
 	struct nfs_fh *fh = res->fh;
 
@@ -115,8 +126,8 @@
 	return 0;
 }
 
-static int
-xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
+static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
+				struct mnt_fhstatus *res)
 {
 	struct nfs_fh *fh = res->fh;
 
@@ -135,53 +146,53 @@
 #define MNT_fhstatus_sz		(1 + 8)
 #define MNT_fhstatus3_sz	(1 + 16)
 
-static struct rpc_procinfo	mnt_procedures[] = {
-[MNTPROC_MNT] = {
-	  .p_proc		= MNTPROC_MNT,
-	  .p_encode		= (kxdrproc_t) xdr_encode_dirpath,	
-	  .p_decode		= (kxdrproc_t) xdr_decode_fhstatus,
-	  .p_arglen		= MNT_dirpath_sz,
-	  .p_replen		= MNT_fhstatus_sz,
-	  .p_statidx		= MNTPROC_MNT,
-	  .p_name		= "MOUNT",
+static struct rpc_procinfo mnt_procedures[] = {
+	[MNTPROC_MNT] = {
+		.p_proc		= MNTPROC_MNT,
+		.p_encode	= (kxdrproc_t) xdr_encode_dirpath,
+		.p_decode	= (kxdrproc_t) xdr_decode_fhstatus,
+		.p_arglen	= MNT_dirpath_sz,
+		.p_replen	= MNT_fhstatus_sz,
+		.p_statidx	= MNTPROC_MNT,
+		.p_name		= "MOUNT",
 	},
 };
 
 static struct rpc_procinfo mnt3_procedures[] = {
-[MOUNTPROC3_MNT] = {
-	  .p_proc		= MOUNTPROC3_MNT,
-	  .p_encode		= (kxdrproc_t) xdr_encode_dirpath,
-	  .p_decode		= (kxdrproc_t) xdr_decode_fhstatus3,
-	  .p_arglen		= MNT_dirpath_sz,
-	  .p_replen		= MNT_fhstatus3_sz,
-	  .p_statidx		= MOUNTPROC3_MNT,
-	  .p_name		= "MOUNT",
+	[MOUNTPROC3_MNT] = {
+		.p_proc		= MOUNTPROC3_MNT,
+		.p_encode	= (kxdrproc_t) xdr_encode_dirpath,
+		.p_decode	= (kxdrproc_t) xdr_decode_fhstatus3,
+		.p_arglen	= MNT_dirpath_sz,
+		.p_replen	= MNT_fhstatus3_sz,
+		.p_statidx	= MOUNTPROC3_MNT,
+		.p_name		= "MOUNT",
 	},
 };
 
 
-static struct rpc_version	mnt_version1 = {
-		.number		= 1,
-		.nrprocs 	= 2,
-		.procs 		= mnt_procedures
+static struct rpc_version mnt_version1 = {
+	.number		= 1,
+	.nrprocs	= 2,
+	.procs		= mnt_procedures,
 };
 
-static struct rpc_version       mnt_version3 = {
-		.number		= 3,
-		.nrprocs	= 2,
-		.procs		= mnt3_procedures
+static struct rpc_version mnt_version3 = {
+	.number		= 3,
+	.nrprocs	= 2,
+	.procs		= mnt3_procedures,
 };
 
-static struct rpc_version *	mnt_version[] = {
+static struct rpc_version *mnt_version[] = {
 	NULL,
 	&mnt_version1,
 	NULL,
 	&mnt_version3,
 };
 
-static struct rpc_stat		mnt_stats;
+static struct rpc_stat mnt_stats;
 
-static struct rpc_program	mnt_program = {
+static struct rpc_program mnt_program = {
 	.name		= "mount",
 	.number		= NFS_MNT_PROGRAM,
 	.nrvers		= ARRAY_SIZE(mnt_version),
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index cd3ca7b..7fcc78f 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -223,7 +223,7 @@
 static int
 nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
-	struct rpc_auth	*auth = req->rq_task->tk_auth;
+	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	unsigned int replen;
 	u32 offset = (u32)args->offset;
 	u32 count = args->count;
@@ -380,7 +380,7 @@
 nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args)
 {
 	struct rpc_task	*task = req->rq_task;
-	struct rpc_auth	*auth = task->tk_auth;
+	struct rpc_auth	*auth = task->tk_msg.rpc_cred->cr_auth;
 	unsigned int replen;
 	u32 count = args->count;
 
@@ -541,7 +541,7 @@
 static int
 nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
 {
-	struct rpc_auth *auth = req->rq_task->tk_auth;
+	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	unsigned int replen;
 
 	p = xdr_encode_fhandle(p, args->fh);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 45268d6..814d886 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -335,9 +335,7 @@
 		 * not sure this buys us anything (and I'd have
 		 * to revamp the NFSv3 XDR code) */
 		status = nfs3_proc_setattr(dentry, &fattr, sattr);
-		if (status == 0)
-			nfs_setattr_update_inode(dentry->d_inode, sattr);
-		nfs_refresh_inode(dentry->d_inode, &fattr);
+		nfs_post_op_update_inode(dentry->d_inode, &fattr);
 		dprintk("NFS reply setattr (post-create): %d\n", status);
 	}
 	if (status != 0)
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index b51df8eb..b4647a2 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -319,7 +319,7 @@
 static int
 nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
-	struct rpc_auth	*auth = req->rq_task->tk_auth;
+	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	unsigned int replen;
 	u32 count = args->count;
 
@@ -458,7 +458,7 @@
 static int
 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
 {
-	struct rpc_auth	*auth = req->rq_task->tk_auth;
+	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	unsigned int replen;
 	u32 count = args->count;
 
@@ -643,7 +643,7 @@
 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
 		    struct nfs3_getaclargs *args)
 {
-	struct rpc_auth *auth = req->rq_task->tk_auth;
+	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	unsigned int replen;
 
 	p = xdr_encode_fhandle(p, args->fh);
@@ -773,7 +773,7 @@
 static int
 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
 {
-	struct rpc_auth *auth = req->rq_task->tk_auth;
+	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	unsigned int replen;
 
 	p = xdr_encode_fhandle(p, args->fh);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index cf3a17e..6c028e7 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -70,19 +70,26 @@
 		seqid->flags |= NFS_SEQID_CONFIRMED;
 }
 
+struct nfs_unique_id {
+	struct rb_node rb_node;
+	__u64 id;
+};
+
 /*
  * NFS4 state_owners and lock_owners are simply labels for ordered
  * sequences of RPC calls. Their sole purpose is to provide once-only
  * semantics by allowing the server to identify replayed requests.
  */
 struct nfs4_state_owner {
-	spinlock_t	     so_lock;
-	struct list_head     so_list;	 /* per-clientid list of state_owners */
+	struct nfs_unique_id so_owner_id;
 	struct nfs_client    *so_client;
-	u32                  so_id;      /* 32-bit identifier, unique */
-	atomic_t	     so_count;
+	struct nfs_server    *so_server;
+	struct rb_node	     so_client_node;
 
 	struct rpc_cred	     *so_cred;	 /* Associated cred */
+
+	spinlock_t	     so_lock;
+	atomic_t	     so_count;
 	struct list_head     so_states;
 	struct list_head     so_delegations;
 	struct nfs_seqid_counter so_seqid;
@@ -108,7 +115,7 @@
 #define NFS_LOCK_INITIALIZED 1
 	int			ls_flags;
 	struct nfs_seqid_counter	ls_seqid;
-	u32			ls_id;
+	struct nfs_unique_id	ls_id;
 	nfs4_stateid		ls_stateid;
 	atomic_t		ls_count;
 };
@@ -116,7 +123,10 @@
 /* bits for nfs4_state->flags */
 enum {
 	LK_STATE_IN_USE,
-	NFS_DELEGATED_STATE,
+	NFS_DELEGATED_STATE,		/* Current stateid is delegation */
+	NFS_O_RDONLY_STATE,		/* OPEN stateid has read-only state */
+	NFS_O_WRONLY_STATE,		/* OPEN stateid has write-only state */
+	NFS_O_RDWR_STATE,		/* OPEN stateid has read/write state */
 };
 
 struct nfs4_state {
@@ -130,11 +140,14 @@
 	unsigned long flags;		/* Do we hold any locks? */
 	spinlock_t state_lock;		/* Protects the lock_states list */
 
-	nfs4_stateid stateid;
+	seqlock_t seqlock;		/* Protects the stateid/open_stateid */
+	nfs4_stateid stateid;		/* Current stateid: may be delegation */
+	nfs4_stateid open_stateid;	/* OPEN stateid */
 
-	unsigned int n_rdonly;
-	unsigned int n_wronly;
-	unsigned int n_rdwr;
+	/* The following 3 fields are protected by owner->so_lock */
+	unsigned int n_rdonly;		/* Number of read-only references */
+	unsigned int n_wronly;		/* Number of write-only references */
+	unsigned int n_rdwr;		/* Number of read/write references */
 	int state;			/* State on the server (R,W, or RW) */
 	atomic_t count;
 };
@@ -165,7 +178,7 @@
 extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
+extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
 extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
@@ -189,14 +202,13 @@
 
 /* nfs4state.c */
 struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
-extern u32 nfs4_alloc_lockowner_id(struct nfs_client *);
 
 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
 extern void nfs4_put_state_owner(struct nfs4_state_owner *);
 extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
-extern void nfs4_close_state(struct nfs4_state *, mode_t);
+extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
 extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
 extern void nfs4_schedule_state_recovery(struct nfs_client *);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
@@ -222,7 +234,7 @@
 
 #else
 
-#define nfs4_close_state(a, b) do { } while (0)
+#define nfs4_close_state(a, b, c) do { } while (0)
 
 #endif /* CONFIG_NFS_V4 */
 #endif /* __LINUX_FS_NFS_NFS4_FS.H */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 648e0ac..fee2da8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -65,6 +65,7 @@
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
 static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
 static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
 
 /* Prevent leaks of NFSv4 errors into userland */
 int nfs4_map_errors(int err)
@@ -214,27 +215,39 @@
 }
 
 struct nfs4_opendata {
-	atomic_t count;
+	struct kref kref;
 	struct nfs_openargs o_arg;
 	struct nfs_openres o_res;
 	struct nfs_open_confirmargs c_arg;
 	struct nfs_open_confirmres c_res;
 	struct nfs_fattr f_attr;
 	struct nfs_fattr dir_attr;
-	struct dentry *dentry;
+	struct path path;
 	struct dentry *dir;
 	struct nfs4_state_owner *owner;
+	struct nfs4_state *state;
 	struct iattr attrs;
 	unsigned long timestamp;
+	unsigned int rpc_done : 1;
 	int rpc_status;
 	int cancelled;
 };
 
-static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
+
+static void nfs4_init_opendata_res(struct nfs4_opendata *p)
+{
+	p->o_res.f_attr = &p->f_attr;
+	p->o_res.dir_attr = &p->dir_attr;
+	p->o_res.server = p->o_arg.server;
+	nfs_fattr_init(&p->f_attr);
+	nfs_fattr_init(&p->dir_attr);
+}
+
+static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 		struct nfs4_state_owner *sp, int flags,
 		const struct iattr *attrs)
 {
-	struct dentry *parent = dget_parent(dentry);
+	struct dentry *parent = dget_parent(path->dentry);
 	struct inode *dir = parent->d_inode;
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs4_opendata *p;
@@ -245,24 +258,19 @@
 	p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
 	if (p->o_arg.seqid == NULL)
 		goto err_free;
-	atomic_set(&p->count, 1);
-	p->dentry = dget(dentry);
+	p->path.mnt = mntget(path->mnt);
+	p->path.dentry = dget(path->dentry);
 	p->dir = parent;
 	p->owner = sp;
 	atomic_inc(&sp->so_count);
 	p->o_arg.fh = NFS_FH(dir);
 	p->o_arg.open_flags = flags,
 	p->o_arg.clientid = server->nfs_client->cl_clientid;
-	p->o_arg.id = sp->so_id;
-	p->o_arg.name = &dentry->d_name;
+	p->o_arg.id = sp->so_owner_id.id;
+	p->o_arg.name = &p->path.dentry->d_name;
 	p->o_arg.server = server;
 	p->o_arg.bitmask = server->attr_bitmask;
 	p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
-	p->o_res.f_attr = &p->f_attr;
-	p->o_res.dir_attr = &p->dir_attr;
-	p->o_res.server = server;
-	nfs_fattr_init(&p->f_attr);
-	nfs_fattr_init(&p->dir_attr);
 	if (flags & O_EXCL) {
 		u32 *s = (u32 *) p->o_arg.u.verifier.data;
 		s[0] = jiffies;
@@ -274,6 +282,8 @@
 	p->c_arg.fh = &p->o_res.fh;
 	p->c_arg.stateid = &p->o_res.stateid;
 	p->c_arg.seqid = p->o_arg.seqid;
+	nfs4_init_opendata_res(p);
+	kref_init(&p->kref);
 	return p;
 err_free:
 	kfree(p);
@@ -282,27 +292,25 @@
 	return NULL;
 }
 
-static void nfs4_opendata_free(struct nfs4_opendata *p)
+static void nfs4_opendata_free(struct kref *kref)
 {
-	if (p != NULL && atomic_dec_and_test(&p->count)) {
-		nfs_free_seqid(p->o_arg.seqid);
-		nfs4_put_state_owner(p->owner);
-		dput(p->dir);
-		dput(p->dentry);
-		kfree(p);
-	}
+	struct nfs4_opendata *p = container_of(kref,
+			struct nfs4_opendata, kref);
+
+	nfs_free_seqid(p->o_arg.seqid);
+	if (p->state != NULL)
+		nfs4_put_open_state(p->state);
+	nfs4_put_state_owner(p->owner);
+	dput(p->dir);
+	dput(p->path.dentry);
+	mntput(p->path.mnt);
+	kfree(p);
 }
 
-/* Helper for asynchronous RPC calls */
-static int nfs4_call_async(struct rpc_clnt *clnt,
-		const struct rpc_call_ops *tk_ops, void *calldata)
+static void nfs4_opendata_put(struct nfs4_opendata *p)
 {
-	struct rpc_task *task;
-
-	if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata)))
-		return -ENOMEM;
-	rpc_execute(task);
-	return 0;
+	if (p != NULL)
+		kref_put(&p->kref, nfs4_opendata_free);
 }
 
 static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
@@ -316,7 +324,34 @@
 	return ret;
 }
 
-static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
+static int can_open_cached(struct nfs4_state *state, int mode)
+{
+	int ret = 0;
+	switch (mode & (FMODE_READ|FMODE_WRITE|O_EXCL)) {
+		case FMODE_READ:
+			ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0;
+			ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+			break;
+		case FMODE_WRITE:
+			ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0;
+			ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+			break;
+		case FMODE_READ|FMODE_WRITE:
+			ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+	}
+	return ret;
+}
+
+static int can_open_delegated(struct nfs_delegation *delegation, mode_t open_flags)
+{
+	if ((delegation->type & open_flags) != open_flags)
+		return 0;
+	if (delegation->flags & NFS_DELEGATION_NEED_RECLAIM)
+		return 0;
+	return 1;
+}
+
+static void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
 {
 	switch (open_flags) {
 		case FMODE_WRITE:
@@ -328,41 +363,176 @@
 		case FMODE_READ|FMODE_WRITE:
 			state->n_rdwr++;
 	}
+	nfs4_state_set_mode_locked(state, state->state | open_flags);
 }
 
-static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
 {
-	struct inode *inode = state->inode;
+	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
+		memcpy(state->stateid.data, stateid->data, sizeof(state->stateid.data));
+	memcpy(state->open_stateid.data, stateid->data, sizeof(state->open_stateid.data));
+	switch (open_flags) {
+		case FMODE_READ:
+			set_bit(NFS_O_RDONLY_STATE, &state->flags);
+			break;
+		case FMODE_WRITE:
+			set_bit(NFS_O_WRONLY_STATE, &state->flags);
+			break;
+		case FMODE_READ|FMODE_WRITE:
+			set_bit(NFS_O_RDWR_STATE, &state->flags);
+	}
+}
 
+static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+{
+	write_seqlock(&state->seqlock);
+	nfs_set_open_stateid_locked(state, stateid, open_flags);
+	write_sequnlock(&state->seqlock);
+}
+
+static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *deleg_stateid, int open_flags)
+{
 	open_flags &= (FMODE_READ|FMODE_WRITE);
-	/* Protect against nfs4_find_state_byowner() */
+	/*
+	 * Protect the call to nfs4_state_set_mode_locked and
+	 * serialise the stateid update
+	 */
+	write_seqlock(&state->seqlock);
+	if (deleg_stateid != NULL) {
+		memcpy(state->stateid.data, deleg_stateid->data, sizeof(state->stateid.data));
+		set_bit(NFS_DELEGATED_STATE, &state->flags);
+	}
+	if (open_stateid != NULL)
+		nfs_set_open_stateid_locked(state, open_stateid, open_flags);
+	write_sequnlock(&state->seqlock);
 	spin_lock(&state->owner->so_lock);
-	spin_lock(&inode->i_lock);
-	memcpy(&state->stateid, stateid, sizeof(state->stateid));
 	update_open_stateflags(state, open_flags);
-	nfs4_state_set_mode_locked(state, state->state | open_flags);
-	spin_unlock(&inode->i_lock);
 	spin_unlock(&state->owner->so_lock);
 }
 
+static void nfs4_return_incompatible_delegation(struct inode *inode, mode_t open_flags)
+{
+	struct nfs_delegation *delegation;
+
+	rcu_read_lock();
+	delegation = rcu_dereference(NFS_I(inode)->delegation);
+	if (delegation == NULL || (delegation->type & open_flags) == open_flags) {
+		rcu_read_unlock();
+		return;
+	}
+	rcu_read_unlock();
+	nfs_inode_return_delegation(inode);
+}
+
+static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
+{
+	struct nfs4_state *state = opendata->state;
+	struct nfs_inode *nfsi = NFS_I(state->inode);
+	struct nfs_delegation *delegation;
+	int open_mode = opendata->o_arg.open_flags & (FMODE_READ|FMODE_WRITE|O_EXCL);
+	nfs4_stateid stateid;
+	int ret = -EAGAIN;
+
+	rcu_read_lock();
+	delegation = rcu_dereference(nfsi->delegation);
+	for (;;) {
+		if (can_open_cached(state, open_mode)) {
+			spin_lock(&state->owner->so_lock);
+			if (can_open_cached(state, open_mode)) {
+				update_open_stateflags(state, open_mode);
+				spin_unlock(&state->owner->so_lock);
+				rcu_read_unlock();
+				goto out_return_state;
+			}
+			spin_unlock(&state->owner->so_lock);
+		}
+		if (delegation == NULL)
+			break;
+		if (!can_open_delegated(delegation, open_mode))
+			break;
+		/* Save the delegation */
+		memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data));
+		rcu_read_unlock();
+		lock_kernel();
+		ret = _nfs4_do_access(state->inode, state->owner->so_cred, open_mode);
+		unlock_kernel();
+		if (ret != 0)
+			goto out;
+		ret = -EAGAIN;
+		rcu_read_lock();
+		delegation = rcu_dereference(nfsi->delegation);
+		/* If no delegation, try a cached open */
+		if (delegation == NULL)
+			continue;
+		/* Is the delegation still valid? */
+		if (memcmp(stateid.data, delegation->stateid.data, sizeof(stateid.data)) != 0)
+			continue;
+		rcu_read_unlock();
+		update_open_stateid(state, NULL, &stateid, open_mode);
+		goto out_return_state;
+	}
+	rcu_read_unlock();
+out:
+	return ERR_PTR(ret);
+out_return_state:
+	atomic_inc(&state->count);
+	return state;
+}
+
 static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
 {
 	struct inode *inode;
 	struct nfs4_state *state = NULL;
+	struct nfs_delegation *delegation;
+	nfs4_stateid *deleg_stateid = NULL;
+	int ret;
 
+	if (!data->rpc_done) {
+		state = nfs4_try_open_cached(data);
+		goto out;
+	}
+
+	ret = -EAGAIN;
 	if (!(data->f_attr.valid & NFS_ATTR_FATTR))
-		goto out;
+		goto err;
 	inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr);
+	ret = PTR_ERR(inode);
 	if (IS_ERR(inode))
-		goto out;
+		goto err;
+	ret = -ENOMEM;
 	state = nfs4_get_open_state(inode, data->owner);
 	if (state == NULL)
-		goto put_inode;
-	update_open_stateid(state, &data->o_res.stateid, data->o_arg.open_flags);
-put_inode:
+		goto err_put_inode;
+	if (data->o_res.delegation_type != 0) {
+		int delegation_flags = 0;
+
+		rcu_read_lock();
+		delegation = rcu_dereference(NFS_I(inode)->delegation);
+		if (delegation)
+			delegation_flags = delegation->flags;
+		rcu_read_unlock();
+		if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
+			nfs_inode_set_delegation(state->inode,
+					data->owner->so_cred,
+					&data->o_res);
+		else
+			nfs_inode_reclaim_delegation(state->inode,
+					data->owner->so_cred,
+					&data->o_res);
+	}
+	rcu_read_lock();
+	delegation = rcu_dereference(NFS_I(inode)->delegation);
+	if (delegation != NULL)
+		deleg_stateid = &delegation->stateid;
+	update_open_stateid(state, &data->o_res.stateid, deleg_stateid, data->o_arg.open_flags);
+	rcu_read_unlock();
 	iput(inode);
 out:
 	return state;
+err_put_inode:
+	iput(inode);
+err:
+	return ERR_PTR(ret);
 }
 
 static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
@@ -382,79 +552,66 @@
 	return ERR_PTR(-ENOENT);
 }
 
-static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, nfs4_stateid *stateid)
+static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res)
 {
+	struct nfs4_state *newstate;
 	int ret;
 
 	opendata->o_arg.open_flags = openflags;
+	memset(&opendata->o_res, 0, sizeof(opendata->o_res));
+	memset(&opendata->c_res, 0, sizeof(opendata->c_res));
+	nfs4_init_opendata_res(opendata);
 	ret = _nfs4_proc_open(opendata);
 	if (ret != 0)
 		return ret; 
-	memcpy(stateid->data, opendata->o_res.stateid.data,
-			sizeof(stateid->data));
+	newstate = nfs4_opendata_to_nfs4_state(opendata);
+	if (IS_ERR(newstate))
+		return PTR_ERR(newstate);
+	nfs4_close_state(&opendata->path, newstate, openflags);
+	*res = newstate;
 	return 0;
 }
 
 static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state)
 {
-	nfs4_stateid stateid;
 	struct nfs4_state *newstate;
-	int mode = 0;
-	int delegation = 0;
 	int ret;
 
 	/* memory barrier prior to reading state->n_* */
+	clear_bit(NFS_DELEGATED_STATE, &state->flags);
 	smp_rmb();
 	if (state->n_rdwr != 0) {
-		ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &stateid);
+		ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
 		if (ret != 0)
 			return ret;
-		mode |= FMODE_READ|FMODE_WRITE;
-		if (opendata->o_res.delegation_type != 0)
-			delegation = opendata->o_res.delegation_type;
-		smp_rmb();
+		if (newstate != state)
+			return -ESTALE;
 	}
 	if (state->n_wronly != 0) {
-		ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &stateid);
+		ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
 		if (ret != 0)
 			return ret;
-		mode |= FMODE_WRITE;
-		if (opendata->o_res.delegation_type != 0)
-			delegation = opendata->o_res.delegation_type;
-		smp_rmb();
+		if (newstate != state)
+			return -ESTALE;
 	}
 	if (state->n_rdonly != 0) {
-		ret = nfs4_open_recover_helper(opendata, FMODE_READ, &stateid);
+		ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
 		if (ret != 0)
 			return ret;
-		mode |= FMODE_READ;
+		if (newstate != state)
+			return -ESTALE;
 	}
-	clear_bit(NFS_DELEGATED_STATE, &state->flags);
-	if (mode == 0)
-		return 0;
-	if (opendata->o_res.delegation_type == 0)
-		opendata->o_res.delegation_type = delegation;
-	opendata->o_arg.open_flags |= mode;
-	newstate = nfs4_opendata_to_nfs4_state(opendata);
-	if (newstate != NULL) {
-		if (opendata->o_res.delegation_type != 0) {
-			struct nfs_inode *nfsi = NFS_I(newstate->inode);
-			int delegation_flags = 0;
-			if (nfsi->delegation)
-				delegation_flags = nfsi->delegation->flags;
-			if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
-				nfs_inode_set_delegation(newstate->inode,
-						opendata->owner->so_cred,
-						&opendata->o_res);
-			else
-				nfs_inode_reclaim_delegation(newstate->inode,
-						opendata->owner->so_cred,
-						&opendata->o_res);
-		}
-		nfs4_close_state(newstate, opendata->o_arg.open_flags);
+	/*
+	 * We may have performed cached opens for all three recoveries.
+	 * Check if we need to update the current stateid.
+	 */
+	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 &&
+	    memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) {
+		write_seqlock(&state->seqlock);
+		if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
+			memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data));
+		write_sequnlock(&state->seqlock);
 	}
-	if (newstate != state)
-		return -ESTALE;
 	return 0;
 }
 
@@ -462,41 +619,37 @@
  * OPEN_RECLAIM:
  * 	reclaim state on the server after a reboot.
  */
-static int _nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
-	struct nfs_delegation *delegation = NFS_I(state->inode)->delegation;
+	struct nfs_delegation *delegation;
 	struct nfs4_opendata *opendata;
 	int delegation_type = 0;
 	int status;
 
-	if (delegation != NULL) {
-		if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
-			memcpy(&state->stateid, &delegation->stateid,
-					sizeof(state->stateid));
-			set_bit(NFS_DELEGATED_STATE, &state->flags);
-			return 0;
-		}
-		delegation_type = delegation->type;
-	}
-	opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+	opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
 	if (opendata == NULL)
 		return -ENOMEM;
 	opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
 	opendata->o_arg.fh = NFS_FH(state->inode);
 	nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
+	rcu_read_lock();
+	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
+	if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0)
+		delegation_type = delegation->flags;
+	rcu_read_unlock();
 	opendata->o_arg.u.delegation_type = delegation_type;
 	status = nfs4_open_recover(opendata, state);
-	nfs4_opendata_free(opendata);
+	nfs4_opendata_put(opendata);
 	return status;
 }
 
-static int nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
 	struct nfs_server *server = NFS_SERVER(state->inode);
 	struct nfs4_exception exception = { };
 	int err;
 	do {
-		err = _nfs4_do_open_reclaim(sp, state, dentry);
+		err = _nfs4_do_open_reclaim(ctx, state);
 		if (err != -NFS4ERR_DELAY)
 			break;
 		nfs4_handle_exception(server, err, &exception);
@@ -512,37 +665,35 @@
 	ctx = nfs4_state_find_open_context(state);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
-	ret = nfs4_do_open_reclaim(sp, state, ctx->dentry);
+	ret = nfs4_do_open_reclaim(ctx, state);
 	put_nfs_open_context(ctx);
 	return ret;
 }
 
-static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
 	struct nfs4_state_owner  *sp  = state->owner;
 	struct nfs4_opendata *opendata;
 	int ret;
 
-	if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
-		return 0;
-	opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+	opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL);
 	if (opendata == NULL)
 		return -ENOMEM;
 	opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
-	memcpy(opendata->o_arg.u.delegation.data, state->stateid.data,
+	memcpy(opendata->o_arg.u.delegation.data, stateid->data,
 			sizeof(opendata->o_arg.u.delegation.data));
 	ret = nfs4_open_recover(opendata, state);
-	nfs4_opendata_free(opendata);
+	nfs4_opendata_put(opendata);
 	return ret;
 }
 
-int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
 	struct nfs4_exception exception = { };
-	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+	struct nfs_server *server = NFS_SERVER(state->inode);
 	int err;
 	do {
-		err = _nfs4_open_delegation_recall(dentry, state);
+		err = _nfs4_open_delegation_recall(ctx, state, stateid);
 		switch (err) {
 			case 0:
 				return err;
@@ -582,9 +733,10 @@
 		memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
 				sizeof(data->o_res.stateid.data));
 		renew_lease(data->o_res.server, data->timestamp);
+		data->rpc_done = 1;
 	}
-	nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
 	nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
+	nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
 }
 
 static void nfs4_open_confirm_release(void *calldata)
@@ -596,14 +748,14 @@
 	if (data->cancelled == 0)
 		goto out_free;
 	/* In case of error, no cleanup! */
-	if (data->rpc_status != 0)
+	if (!data->rpc_done)
 		goto out_free;
 	nfs_confirm_seqid(&data->owner->so_seqid, 0);
 	state = nfs4_opendata_to_nfs4_state(data);
-	if (state != NULL)
-		nfs4_close_state(state, data->o_arg.open_flags);
+	if (!IS_ERR(state))
+		nfs4_close_state(&data->path, state, data->o_arg.open_flags);
 out_free:
-	nfs4_opendata_free(data);
+	nfs4_opendata_put(data);
 }
 
 static const struct rpc_call_ops nfs4_open_confirm_ops = {
@@ -621,12 +773,9 @@
 	struct rpc_task *task;
 	int status;
 
-	atomic_inc(&data->count);
-	/*
-	 * If rpc_run_task() ends up calling ->rpc_release(), we
-	 * want to ensure that it takes the 'error' code path.
-	 */
-	data->rpc_status = -ENOMEM;
+	kref_get(&data->kref);
+	data->rpc_done = 0;
+	data->rpc_status = 0;
 	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
@@ -653,13 +802,35 @@
 	
 	if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
 		return;
+	/*
+	 * Check if we still need to send an OPEN call, or if we can use
+	 * a delegation instead.
+	 */
+	if (data->state != NULL) {
+		struct nfs_delegation *delegation;
+
+		if (can_open_cached(data->state, data->o_arg.open_flags & (FMODE_READ|FMODE_WRITE|O_EXCL)))
+			goto out_no_action;
+		rcu_read_lock();
+		delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
+		if (delegation != NULL &&
+		   (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0) {
+			rcu_read_unlock();
+			goto out_no_action;
+		}
+		rcu_read_unlock();
+	}
 	/* Update sequence id. */
-	data->o_arg.id = sp->so_id;
+	data->o_arg.id = sp->so_owner_id.id;
 	data->o_arg.clientid = sp->so_client->cl_clientid;
 	if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
 		msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
 	data->timestamp = jiffies;
 	rpc_call_setup(task, &msg, 0);
+	return;
+out_no_action:
+	task->tk_action = NULL;
+
 }
 
 static void nfs4_open_done(struct rpc_task *task, void *calldata)
@@ -683,8 +854,11 @@
 				data->rpc_status = -ENOTDIR;
 		}
 		renew_lease(data->o_res.server, data->timestamp);
+		if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
+			nfs_confirm_seqid(&data->owner->so_seqid, 0);
 	}
 	nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid);
+	data->rpc_done = 1;
 }
 
 static void nfs4_open_release(void *calldata)
@@ -696,17 +870,17 @@
 	if (data->cancelled == 0)
 		goto out_free;
 	/* In case of error, no cleanup! */
-	if (data->rpc_status != 0)
+	if (data->rpc_status != 0 || !data->rpc_done)
 		goto out_free;
 	/* In case we need an open_confirm, no cleanup! */
 	if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
 		goto out_free;
 	nfs_confirm_seqid(&data->owner->so_seqid, 0);
 	state = nfs4_opendata_to_nfs4_state(data);
-	if (state != NULL)
-		nfs4_close_state(state, data->o_arg.open_flags);
+	if (!IS_ERR(state))
+		nfs4_close_state(&data->path, state, data->o_arg.open_flags);
 out_free:
-	nfs4_opendata_free(data);
+	nfs4_opendata_put(data);
 }
 
 static const struct rpc_call_ops nfs4_open_ops = {
@@ -727,12 +901,10 @@
 	struct rpc_task *task;
 	int status;
 
-	atomic_inc(&data->count);
-	/*
-	 * If rpc_run_task() ends up calling ->rpc_release(), we
-	 * want to ensure that it takes the 'error' code path.
-	 */
-	data->rpc_status = -ENOMEM;
+	kref_get(&data->kref);
+	data->rpc_done = 0;
+	data->rpc_status = 0;
+	data->cancelled = 0;
 	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
@@ -743,7 +915,7 @@
 	} else
 		status = data->rpc_status;
 	rpc_put_task(task);
-	if (status != 0)
+	if (status != 0 || !data->rpc_done)
 		return status;
 
 	if (o_arg->open_flags & O_CREAT) {
@@ -756,7 +928,6 @@
 		if (status != 0)
 			return status;
 	}
-	nfs_confirm_seqid(&data->owner->so_seqid, 0);
 	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
 		return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
 	return 0;
@@ -772,6 +943,8 @@
 		mask |= MAY_READ;
 	if (openflags & FMODE_WRITE)
 		mask |= MAY_WRITE;
+	if (openflags & FMODE_EXEC)
+		mask |= MAY_EXEC;
 	status = nfs_access_get_cached(inode, cred, &cache);
 	if (status == 0)
 		goto out;
@@ -811,43 +984,32 @@
  * 	reclaim state on the server after a network partition.
  * 	Assumes caller holds the appropriate lock
  */
-static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
-	struct inode *inode = state->inode;
-	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
 	struct nfs4_opendata *opendata;
-	int openflags = state->state & (FMODE_READ|FMODE_WRITE);
 	int ret;
 
-	if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
-		ret = _nfs4_do_access(inode, sp->so_cred, openflags);
-		if (ret < 0)
-			return ret;
-		memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
-		set_bit(NFS_DELEGATED_STATE, &state->flags);
-		return 0;
-	}
-	opendata = nfs4_opendata_alloc(dentry, sp, openflags, NULL);
+	opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
 	if (opendata == NULL)
 		return -ENOMEM;
 	ret = nfs4_open_recover(opendata, state);
 	if (ret == -ESTALE) {
 		/* Invalidate the state owner so we don't ever use it again */
-		nfs4_drop_state_owner(sp);
-		d_drop(dentry);
+		nfs4_drop_state_owner(state->owner);
+		d_drop(ctx->path.dentry);
 	}
-	nfs4_opendata_free(opendata);
+	nfs4_opendata_put(opendata);
 	return ret;
 }
 
-static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
-	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+	struct nfs_server *server = NFS_SERVER(state->inode);
 	struct nfs4_exception exception = { };
 	int err;
 
 	do {
-		err = _nfs4_open_expired(sp, state, dentry);
+		err = _nfs4_open_expired(ctx, state);
 		if (err == -NFS4ERR_DELAY)
 			nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
@@ -862,107 +1024,38 @@
 	ctx = nfs4_state_find_open_context(state);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
-	ret = nfs4_do_open_expired(sp, state, ctx->dentry);
+	ret = nfs4_do_open_expired(ctx, state);
 	put_nfs_open_context(ctx);
 	return ret;
 }
 
 /*
- * Returns a referenced nfs4_state if there is an open delegation on the file
+ * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
+ * fields corresponding to attributes that were used to store the verifier.
+ * Make sure we clobber those fields in the later setattr call
  */
-static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
+static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct iattr *sattr)
 {
-	struct nfs_delegation *delegation;
-	struct nfs_server *server = NFS_SERVER(inode);
-	struct nfs_client *clp = server->nfs_client;
-	struct nfs_inode *nfsi = NFS_I(inode);
-	struct nfs4_state_owner *sp = NULL;
-	struct nfs4_state *state = NULL;
-	int open_flags = flags & (FMODE_READ|FMODE_WRITE);
-	int err;
+	if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
+	    !(sattr->ia_valid & ATTR_ATIME_SET))
+		sattr->ia_valid |= ATTR_ATIME;
 
-	err = -ENOMEM;
-	if (!(sp = nfs4_get_state_owner(server, cred))) {
-		dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
-		return err;
-	}
-	err = nfs4_recover_expired_lease(server);
-	if (err != 0)
-		goto out_put_state_owner;
-	/* Protect against reboot recovery - NOTE ORDER! */
-	down_read(&clp->cl_sem);
-	/* Protect against delegation recall */
-	down_read(&nfsi->rwsem);
-	delegation = NFS_I(inode)->delegation;
-	err = -ENOENT;
-	if (delegation == NULL || (delegation->type & open_flags) != open_flags)
-		goto out_err;
-	err = -ENOMEM;
-	state = nfs4_get_open_state(inode, sp);
-	if (state == NULL)
-		goto out_err;
-
-	err = -ENOENT;
-	if ((state->state & open_flags) == open_flags) {
-		spin_lock(&inode->i_lock);
-		update_open_stateflags(state, open_flags);
-		spin_unlock(&inode->i_lock);
-		goto out_ok;
-	} else if (state->state != 0)
-		goto out_put_open_state;
-
-	lock_kernel();
-	err = _nfs4_do_access(inode, cred, open_flags);
-	unlock_kernel();
-	if (err != 0)
-		goto out_put_open_state;
-	set_bit(NFS_DELEGATED_STATE, &state->flags);
-	update_open_stateid(state, &delegation->stateid, open_flags);
-out_ok:
-	nfs4_put_state_owner(sp);
-	up_read(&nfsi->rwsem);
-	up_read(&clp->cl_sem);
-	*res = state;
-	return 0;
-out_put_open_state:
-	nfs4_put_open_state(state);
-out_err:
-	up_read(&nfsi->rwsem);
-	up_read(&clp->cl_sem);
-	if (err != -EACCES)
-		nfs_inode_return_delegation(inode);
-out_put_state_owner:
-	nfs4_put_state_owner(sp);
-	return err;
-}
-
-static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred)
-{
-	struct nfs4_exception exception = { };
-	struct nfs4_state *res = ERR_PTR(-EIO);
-	int err;
-
-	do {
-		err = _nfs4_open_delegated(inode, flags, cred, &res);
-		if (err == 0)
-			break;
-		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(inode),
-					err, &exception));
-	} while (exception.retry);
-	return res;
+	if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
+	    !(sattr->ia_valid & ATTR_MTIME_SET))
+		sattr->ia_valid |= ATTR_MTIME;
 }
 
 /*
  * Returns a referenced nfs4_state
  */
-static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
 {
 	struct nfs4_state_owner  *sp;
 	struct nfs4_state     *state = NULL;
 	struct nfs_server       *server = NFS_SERVER(dir);
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs4_opendata *opendata;
-	int                     status;
+	int status;
 
 	/* Protect against reboot recovery conflicts */
 	status = -ENOMEM;
@@ -973,29 +1066,35 @@
 	status = nfs4_recover_expired_lease(server);
 	if (status != 0)
 		goto err_put_state_owner;
+	if (path->dentry->d_inode != NULL)
+		nfs4_return_incompatible_delegation(path->dentry->d_inode, flags & (FMODE_READ|FMODE_WRITE));
 	down_read(&clp->cl_sem);
 	status = -ENOMEM;
-	opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
+	opendata = nfs4_opendata_alloc(path, sp, flags, sattr);
 	if (opendata == NULL)
 		goto err_release_rwsem;
 
+	if (path->dentry->d_inode != NULL)
+		opendata->state = nfs4_get_open_state(path->dentry->d_inode, sp);
+
 	status = _nfs4_proc_open(opendata);
 	if (status != 0)
-		goto err_opendata_free;
+		goto err_opendata_put;
 
-	status = -ENOMEM;
+	if (opendata->o_arg.open_flags & O_EXCL)
+		nfs4_exclusive_attrset(opendata, sattr);
+
 	state = nfs4_opendata_to_nfs4_state(opendata);
-	if (state == NULL)
-		goto err_opendata_free;
-	if (opendata->o_res.delegation_type != 0)
-		nfs_inode_set_delegation(state->inode, cred, &opendata->o_res);
-	nfs4_opendata_free(opendata);
+	status = PTR_ERR(state);
+	if (IS_ERR(state))
+		goto err_opendata_put;
+	nfs4_opendata_put(opendata);
 	nfs4_put_state_owner(sp);
 	up_read(&clp->cl_sem);
 	*res = state;
 	return 0;
-err_opendata_free:
-	nfs4_opendata_free(opendata);
+err_opendata_put:
+	nfs4_opendata_put(opendata);
 err_release_rwsem:
 	up_read(&clp->cl_sem);
 err_put_state_owner:
@@ -1006,14 +1105,14 @@
 }
 
 
-static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred)
 {
 	struct nfs4_exception exception = { };
 	struct nfs4_state *res;
 	int status;
 
 	do {
-		status = _nfs4_do_open(dir, dentry, flags, sattr, cred, &res);
+		status = _nfs4_do_open(dir, path, flags, sattr, cred, &res);
 		if (status == 0)
 			break;
 		/* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1028,7 +1127,9 @@
 		 * the user though...
 		 */
 		if (status == -NFS4ERR_BAD_SEQID) {
-			printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");
+			printk(KERN_WARNING "NFS: v4 server %s "
+					" returned a bad sequence-id error!\n",
+					NFS_SERVER(dir)->nfs_client->cl_hostname);
 			exception.retry = 1;
 			continue;
 		}
@@ -1042,6 +1143,11 @@
 			exception.retry = 1;
 			continue;
 		}
+		if (status == -EAGAIN) {
+			/* We must have found a delegation */
+			exception.retry = 1;
+			continue;
+		}
 		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
 					status, &exception));
 	} while (exception.retry);
@@ -1101,6 +1207,7 @@
 }
 
 struct nfs4_closedata {
+	struct path path;
 	struct inode *inode;
 	struct nfs4_state *state;
 	struct nfs_closeargs arg;
@@ -1117,6 +1224,8 @@
 	nfs4_put_open_state(calldata->state);
 	nfs_free_seqid(calldata->arg.seqid);
 	nfs4_put_state_owner(sp);
+	dput(calldata->path.dentry);
+	mntput(calldata->path.mnt);
 	kfree(calldata);
 }
 
@@ -1134,8 +1243,7 @@
 	nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
 	switch (task->tk_status) {
 		case 0:
-			memcpy(&state->stateid, &calldata->res.stateid,
-					sizeof(state->stateid));
+			nfs_set_open_stateid(state, &calldata->res.stateid, calldata->arg.open_flags);
 			renew_lease(server, calldata->timestamp);
 			break;
 		case -NFS4ERR_STALE_STATEID:
@@ -1160,26 +1268,30 @@
 		.rpc_resp = &calldata->res,
 		.rpc_cred = state->owner->so_cred,
 	};
-	int mode = 0, old_mode;
+	int clear_rd, clear_wr, clear_rdwr;
+	int mode;
 
 	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
 		return;
-	/* Recalculate the new open mode in case someone reopened the file
-	 * while we were waiting in line to be scheduled.
-	 */
+
+	mode = FMODE_READ|FMODE_WRITE;
+	clear_rd = clear_wr = clear_rdwr = 0;
 	spin_lock(&state->owner->so_lock);
-	spin_lock(&calldata->inode->i_lock);
-	mode = old_mode = state->state;
+	/* Calculate the change in open mode */
 	if (state->n_rdwr == 0) {
-		if (state->n_rdonly == 0)
+		if (state->n_rdonly == 0) {
 			mode &= ~FMODE_READ;
-		if (state->n_wronly == 0)
+			clear_rd |= test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+			clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
+		}
+		if (state->n_wronly == 0) {
 			mode &= ~FMODE_WRITE;
+			clear_wr |= test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+			clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
+		}
 	}
-	nfs4_state_set_mode_locked(state, mode);
-	spin_unlock(&calldata->inode->i_lock);
 	spin_unlock(&state->owner->so_lock);
-	if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) {
+	if (!clear_rd && !clear_wr && !clear_rdwr) {
 		/* Note: exit _without_ calling nfs4_close_done */
 		task->tk_action = NULL;
 		return;
@@ -1209,19 +1321,21 @@
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
+int nfs4_do_close(struct path *path, struct nfs4_state *state)
 {
-	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_server *server = NFS_SERVER(state->inode);
 	struct nfs4_closedata *calldata;
+	struct nfs4_state_owner *sp = state->owner;
+	struct rpc_task *task;
 	int status = -ENOMEM;
 
 	calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
 	if (calldata == NULL)
 		goto out;
-	calldata->inode = inode;
+	calldata->inode = state->inode;
 	calldata->state = state;
-	calldata->arg.fh = NFS_FH(inode);
-	calldata->arg.stateid = &state->stateid;
+	calldata->arg.fh = NFS_FH(state->inode);
+	calldata->arg.stateid = &state->open_stateid;
 	/* Serialization for the sequence id */
 	calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
 	if (calldata->arg.seqid == NULL)
@@ -1229,36 +1343,55 @@
 	calldata->arg.bitmask = server->attr_bitmask;
 	calldata->res.fattr = &calldata->fattr;
 	calldata->res.server = server;
+	calldata->path.mnt = mntget(path->mnt);
+	calldata->path.dentry = dget(path->dentry);
 
-	status = nfs4_call_async(server->client, &nfs4_close_ops, calldata);
-	if (status == 0)
-		goto out;
-
-	nfs_free_seqid(calldata->arg.seqid);
+	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
+	if (IS_ERR(task))
+		return PTR_ERR(task);
+	rpc_put_task(task);
+	return 0;
 out_free_calldata:
 	kfree(calldata);
 out:
+	nfs4_put_open_state(state);
+	nfs4_put_state_owner(sp);
 	return status;
 }
 
-static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state)
 {
 	struct file *filp;
+	int ret;
 
-	filp = lookup_instantiate_filp(nd, dentry, NULL);
+	/* If the open_intent is for execute, we have an extra check to make */
+	if (nd->intent.open.flags & FMODE_EXEC) {
+		ret = _nfs4_do_access(state->inode,
+				state->owner->so_cred,
+				nd->intent.open.flags);
+		if (ret < 0)
+			goto out_close;
+	}
+	filp = lookup_instantiate_filp(nd, path->dentry, NULL);
 	if (!IS_ERR(filp)) {
 		struct nfs_open_context *ctx;
 		ctx = (struct nfs_open_context *)filp->private_data;
 		ctx->state = state;
 		return 0;
 	}
-	nfs4_close_state(state, nd->intent.open.flags);
-	return PTR_ERR(filp);
+	ret = PTR_ERR(filp);
+out_close:
+	nfs4_close_state(path, state, nd->intent.open.flags);
+	return ret;
 }
 
 struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct path path = {
+		.mnt = nd->mnt,
+		.dentry = dentry,
+	};
 	struct iattr attr;
 	struct rpc_cred *cred;
 	struct nfs4_state *state;
@@ -1277,7 +1410,7 @@
 	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
 	if (IS_ERR(cred))
 		return (struct dentry *)cred;
-	state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
+	state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
 	put_rpccred(cred);
 	if (IS_ERR(state)) {
 		if (PTR_ERR(state) == -ENOENT)
@@ -1287,22 +1420,24 @@
 	res = d_add_unique(dentry, igrab(state->inode));
 	if (res != NULL)
 		dentry = res;
-	nfs4_intent_set_file(nd, dentry, state);
+	nfs4_intent_set_file(nd, &path, state);
 	return res;
 }
 
 int
 nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
 {
+	struct path path = {
+		.mnt = nd->mnt,
+		.dentry = dentry,
+	};
 	struct rpc_cred *cred;
 	struct nfs4_state *state;
 
 	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
-	if (IS_ERR(state))
-		state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
+	state = nfs4_do_open(dir, &path, openflags, NULL, cred);
 	put_rpccred(cred);
 	if (IS_ERR(state)) {
 		switch (PTR_ERR(state)) {
@@ -1318,10 +1453,10 @@
 		}
 	}
 	if (state->inode == dentry->d_inode) {
-		nfs4_intent_set_file(nd, dentry, state);
+		nfs4_intent_set_file(nd, &path, state);
 		return 1;
 	}
-	nfs4_close_state(state, openflags);
+	nfs4_close_state(&path, state, openflags);
 out_drop:
 	d_drop(dentry);
 	return 0;
@@ -1559,8 +1694,6 @@
 	dprintk("NFS call  lookupfh %s\n", name->name);
 	status = rpc_call_sync(server->client, &msg, 0);
 	dprintk("NFS reply lookupfh: %d\n", status);
-	if (status == -NFS4ERR_MOVED)
-		status = -EREMOTE;
 	return status;
 }
 
@@ -1571,10 +1704,13 @@
 	struct nfs4_exception exception = { };
 	int err;
 	do {
-		err = nfs4_handle_exception(server,
-				_nfs4_proc_lookupfh(server, dirfh, name,
-						    fhandle, fattr),
-				&exception);
+		err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr);
+		/* FIXME: !!!! */
+		if (err == -NFS4ERR_MOVED) {
+			err = -EREMOTE;
+			break;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
 	return err;
 }
@@ -1582,28 +1718,10 @@
 static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,
 		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
-	int		       status;
-	struct nfs_server *server = NFS_SERVER(dir);
-	struct nfs4_lookup_arg args = {
-		.bitmask = server->attr_bitmask,
-		.dir_fh = NFS_FH(dir),
-		.name = name,
-	};
-	struct nfs4_lookup_res res = {
-		.server = server,
-		.fattr = fattr,
-		.fh = fhandle,
-	};
-	struct rpc_message msg = {
-		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
-		.rpc_argp = &args,
-		.rpc_resp = &res,
-	};
-	
-	nfs_fattr_init(fattr);
+	int status;
 	
 	dprintk("NFS call  lookup %s\n", name->name);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr);
 	if (status == -NFS4ERR_MOVED)
 		status = nfs4_get_referral(dir, name, fattr, fhandle);
 	dprintk("NFS reply lookup: %d\n", status);
@@ -1752,6 +1870,10 @@
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                  int flags, struct nameidata *nd)
 {
+	struct path path = {
+		.mnt = nd->mnt,
+		.dentry = dentry,
+	};
 	struct nfs4_state *state;
 	struct rpc_cred *cred;
 	int status = 0;
@@ -1761,7 +1883,7 @@
 		status = PTR_ERR(cred);
 		goto out;
 	}
-	state = nfs4_do_open(dir, dentry, flags, sattr, cred);
+	state = nfs4_do_open(dir, &path, flags, sattr, cred);
 	put_rpccred(cred);
 	if (IS_ERR(state)) {
 		status = PTR_ERR(state);
@@ -1773,11 +1895,12 @@
 		status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
 		if (status == 0)
 			nfs_setattr_update_inode(state->inode, sattr);
+		nfs_post_op_update_inode(state->inode, &fattr);
 	}
-	if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
-		status = nfs4_intent_set_file(nd, dentry, state);
+	if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
+		status = nfs4_intent_set_file(nd, &path, state);
 	else
-		nfs4_close_state(state, flags);
+		nfs4_close_state(&path, state, flags);
 out:
 	return status;
 }
@@ -3008,7 +3131,7 @@
 	if (status != 0)
 		goto out;
 	lsp = request->fl_u.nfs4_fl.owner;
-	arg.lock_owner.id = lsp->ls_id; 
+	arg.lock_owner.id = lsp->ls_id.id;
 	status = rpc_call_sync(server->client, &msg, 0);
 	switch (status) {
 		case 0:
@@ -3152,6 +3275,11 @@
 {
 	struct nfs4_unlockdata *data;
 
+	/* Ensure this is an unlock - when canceling a lock, the
+	 * canceled lock is passed in, and it won't be an unlock.
+	 */
+	fl->fl_type = F_UNLCK;
+
 	data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
 	if (data == NULL) {
 		nfs_free_seqid(seqid);
@@ -3222,7 +3350,7 @@
 		goto out_free;
 	p->arg.lock_stateid = &lsp->ls_stateid;
 	p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
-	p->arg.lock_owner.id = lsp->ls_id;
+	p->arg.lock_owner.id = lsp->ls_id.id;
 	p->lsp = lsp;
 	atomic_inc(&lsp->ls_count);
 	p->ctx = get_nfs_open_context(ctx);
@@ -3285,7 +3413,7 @@
 		memcpy(data->lsp->ls_stateid.data, data->res.stateid.data,
 					sizeof(data->lsp->ls_stateid.data));
 		data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
-		renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
+		renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
 	}
 	nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
 out:
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 8ed79d5..e9662ba 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -38,12 +38,14 @@
  * subsequent patch.
  */
 
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
+#include <linux/random.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 
@@ -69,33 +71,14 @@
 	return status;
 }
 
-u32
-nfs4_alloc_lockowner_id(struct nfs_client *clp)
-{
-	return clp->cl_lockowner_id ++;
-}
-
-static struct nfs4_state_owner *
-nfs4_client_grab_unused(struct nfs_client *clp, struct rpc_cred *cred)
-{
-	struct nfs4_state_owner *sp = NULL;
-
-	if (!list_empty(&clp->cl_unused)) {
-		sp = list_entry(clp->cl_unused.next, struct nfs4_state_owner, so_list);
-		atomic_inc(&sp->so_count);
-		sp->so_cred = cred;
-		list_move(&sp->so_list, &clp->cl_state_owners);
-		clp->cl_nunused--;
-	}
-	return sp;
-}
-
 struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
 {
 	struct nfs4_state_owner *sp;
+	struct rb_node *pos;
 	struct rpc_cred *cred = NULL;
 
-	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+	for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+		sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
 		if (list_empty(&sp->so_states))
 			continue;
 		cred = get_rpccred(sp->so_cred);
@@ -107,32 +90,146 @@
 static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
 {
 	struct nfs4_state_owner *sp;
+	struct rb_node *pos;
 
-	if (!list_empty(&clp->cl_state_owners)) {
-		sp = list_entry(clp->cl_state_owners.next,
-				struct nfs4_state_owner, so_list);
+	pos = rb_first(&clp->cl_state_owners);
+	if (pos != NULL) {
+		sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
 		return get_rpccred(sp->so_cred);
 	}
 	return NULL;
 }
 
-static struct nfs4_state_owner *
-nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred)
+static void nfs_alloc_unique_id(struct rb_root *root, struct nfs_unique_id *new,
+		__u64 minval, int maxbits)
 {
+	struct rb_node **p, *parent;
+	struct nfs_unique_id *pos;
+	__u64 mask = ~0ULL;
+
+	if (maxbits < 64)
+		mask = (1ULL << maxbits) - 1ULL;
+
+	/* Ensure distribution is more or less flat */
+	get_random_bytes(&new->id, sizeof(new->id));
+	new->id &= mask;
+	if (new->id < minval)
+		new->id += minval;
+retry:
+	p = &root->rb_node;
+	parent = NULL;
+
+	while (*p != NULL) {
+		parent = *p;
+		pos = rb_entry(parent, struct nfs_unique_id, rb_node);
+
+		if (new->id < pos->id)
+			p = &(*p)->rb_left;
+		else if (new->id > pos->id)
+			p = &(*p)->rb_right;
+		else
+			goto id_exists;
+	}
+	rb_link_node(&new->rb_node, parent, p);
+	rb_insert_color(&new->rb_node, root);
+	return;
+id_exists:
+	for (;;) {
+		new->id++;
+		if (new->id < minval || (new->id & mask) != new->id) {
+			new->id = minval;
+			break;
+		}
+		parent = rb_next(parent);
+		if (parent == NULL)
+			break;
+		pos = rb_entry(parent, struct nfs_unique_id, rb_node);
+		if (new->id < pos->id)
+			break;
+	}
+	goto retry;
+}
+
+static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id)
+{
+	rb_erase(&id->rb_node, root);
+}
+
+static struct nfs4_state_owner *
+nfs4_find_state_owner(struct nfs_server *server, struct rpc_cred *cred)
+{
+	struct nfs_client *clp = server->nfs_client;
+	struct rb_node **p = &clp->cl_state_owners.rb_node,
+		       *parent = NULL;
 	struct nfs4_state_owner *sp, *res = NULL;
 
-	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
-		if (sp->so_cred != cred)
+	while (*p != NULL) {
+		parent = *p;
+		sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
+
+		if (server < sp->so_server) {
+			p = &parent->rb_left;
 			continue;
-		atomic_inc(&sp->so_count);
-		/* Move to the head of the list */
-		list_move(&sp->so_list, &clp->cl_state_owners);
-		res = sp;
-		break;
+		}
+		if (server > sp->so_server) {
+			p = &parent->rb_right;
+			continue;
+		}
+		if (cred < sp->so_cred)
+			p = &parent->rb_left;
+		else if (cred > sp->so_cred)
+			p = &parent->rb_right;
+		else {
+			atomic_inc(&sp->so_count);
+			res = sp;
+			break;
+		}
 	}
 	return res;
 }
 
+static struct nfs4_state_owner *
+nfs4_insert_state_owner(struct nfs_client *clp, struct nfs4_state_owner *new)
+{
+	struct rb_node **p = &clp->cl_state_owners.rb_node,
+		       *parent = NULL;
+	struct nfs4_state_owner *sp;
+
+	while (*p != NULL) {
+		parent = *p;
+		sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
+
+		if (new->so_server < sp->so_server) {
+			p = &parent->rb_left;
+			continue;
+		}
+		if (new->so_server > sp->so_server) {
+			p = &parent->rb_right;
+			continue;
+		}
+		if (new->so_cred < sp->so_cred)
+			p = &parent->rb_left;
+		else if (new->so_cred > sp->so_cred)
+			p = &parent->rb_right;
+		else {
+			atomic_inc(&sp->so_count);
+			return sp;
+		}
+	}
+	nfs_alloc_unique_id(&clp->cl_openowner_id, &new->so_owner_id, 1, 64);
+	rb_link_node(&new->so_client_node, parent, p);
+	rb_insert_color(&new->so_client_node, &clp->cl_state_owners);
+	return new;
+}
+
+static void
+nfs4_remove_state_owner(struct nfs_client *clp, struct nfs4_state_owner *sp)
+{
+	if (!RB_EMPTY_NODE(&sp->so_client_node))
+		rb_erase(&sp->so_client_node, &clp->cl_state_owners);
+	nfs_free_unique_id(&clp->cl_openowner_id, &sp->so_owner_id);
+}
+
 /*
  * nfs4_alloc_state_owner(): this is called on the OPEN or CREATE path to
  * create a new state_owner.
@@ -160,10 +257,14 @@
 void
 nfs4_drop_state_owner(struct nfs4_state_owner *sp)
 {
-	struct nfs_client *clp = sp->so_client;
-	spin_lock(&clp->cl_lock);
-	list_del_init(&sp->so_list);
-	spin_unlock(&clp->cl_lock);
+	if (!RB_EMPTY_NODE(&sp->so_client_node)) {
+		struct nfs_client *clp = sp->so_client;
+
+		spin_lock(&clp->cl_lock);
+		rb_erase(&sp->so_client_node, &clp->cl_state_owners);
+		RB_CLEAR_NODE(&sp->so_client_node);
+		spin_unlock(&clp->cl_lock);
+	}
 }
 
 /*
@@ -175,26 +276,25 @@
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs4_state_owner *sp, *new;
 
-	get_rpccred(cred);
-	new = nfs4_alloc_state_owner();
 	spin_lock(&clp->cl_lock);
-	sp = nfs4_find_state_owner(clp, cred);
-	if (sp == NULL)
-		sp = nfs4_client_grab_unused(clp, cred);
-	if (sp == NULL && new != NULL) {
-		list_add(&new->so_list, &clp->cl_state_owners);
-		new->so_client = clp;
-		new->so_id = nfs4_alloc_lockowner_id(clp);
-		new->so_cred = cred;
-		sp = new;
-		new = NULL;
-	}
+	sp = nfs4_find_state_owner(server, cred);
 	spin_unlock(&clp->cl_lock);
-	kfree(new);
 	if (sp != NULL)
 		return sp;
-	put_rpccred(cred);
-	return NULL;
+	new = nfs4_alloc_state_owner();
+	if (new == NULL)
+		return NULL;
+	new->so_client = clp;
+	new->so_server = server;
+	new->so_cred = cred;
+	spin_lock(&clp->cl_lock);
+	sp = nfs4_insert_state_owner(clp, new);
+	spin_unlock(&clp->cl_lock);
+	if (sp == new)
+		get_rpccred(cred);
+	else
+		kfree(new);
+	return sp;
 }
 
 /*
@@ -208,18 +308,7 @@
 
 	if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock))
 		return;
-	if (clp->cl_nunused >= OPENOWNER_POOL_SIZE)
-		goto out_free;
-	if (list_empty(&sp->so_list))
-		goto out_free;
-	list_move(&sp->so_list, &clp->cl_unused);
-	clp->cl_nunused++;
-	spin_unlock(&clp->cl_lock);
-	put_rpccred(cred);
-	cred = NULL;
-	return;
-out_free:
-	list_del(&sp->so_list);
+	nfs4_remove_state_owner(clp, sp);
 	spin_unlock(&clp->cl_lock);
 	put_rpccred(cred);
 	kfree(sp);
@@ -236,6 +325,7 @@
 	atomic_set(&state->count, 1);
 	INIT_LIST_HEAD(&state->lock_states);
 	spin_lock_init(&state->state_lock);
+	seqlock_init(&state->seqlock);
 	return state;
 }
 
@@ -263,13 +353,10 @@
 	struct nfs4_state *state;
 
 	list_for_each_entry(state, &nfsi->open_states, inode_states) {
-		/* Is this in the process of being freed? */
-		if (state->state == 0)
+		if (state->owner != owner)
 			continue;
-		if (state->owner == owner) {
-			atomic_inc(&state->count);
+		if (atomic_inc_not_zero(&state->count))
 			return state;
-		}
 	}
 	return NULL;
 }
@@ -341,16 +428,15 @@
 /*
  * Close the current file.
  */
-void nfs4_close_state(struct nfs4_state *state, mode_t mode)
+void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
 {
-	struct inode *inode = state->inode;
 	struct nfs4_state_owner *owner = state->owner;
-	int oldstate, newstate = 0;
+	int call_close = 0;
+	int newstate;
 
 	atomic_inc(&owner->so_count);
 	/* Protect against nfs4_find_state() */
 	spin_lock(&owner->so_lock);
-	spin_lock(&inode->i_lock);
 	switch (mode & (FMODE_READ | FMODE_WRITE)) {
 		case FMODE_READ:
 			state->n_rdonly--;
@@ -361,24 +447,29 @@
 		case FMODE_READ|FMODE_WRITE:
 			state->n_rdwr--;
 	}
-	oldstate = newstate = state->state;
+	newstate = FMODE_READ|FMODE_WRITE;
 	if (state->n_rdwr == 0) {
-		if (state->n_rdonly == 0)
+		if (state->n_rdonly == 0) {
 			newstate &= ~FMODE_READ;
-		if (state->n_wronly == 0)
+			call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags);
+			call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+		}
+		if (state->n_wronly == 0) {
 			newstate &= ~FMODE_WRITE;
+			call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags);
+			call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+		}
+		if (newstate == 0)
+			clear_bit(NFS_DELEGATED_STATE, &state->flags);
 	}
-	if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
-		nfs4_state_set_mode_locked(state, newstate);
-		oldstate = newstate;
-	}
-	spin_unlock(&inode->i_lock);
+	nfs4_state_set_mode_locked(state, newstate);
 	spin_unlock(&owner->so_lock);
 
-	if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
-		return;
-	nfs4_put_open_state(state);
-	nfs4_put_state_owner(owner);
+	if (!call_close) {
+		nfs4_put_open_state(state);
+		nfs4_put_state_owner(owner);
+	} else
+		nfs4_do_close(path, state);
 }
 
 /*
@@ -415,12 +506,22 @@
 	atomic_set(&lsp->ls_count, 1);
 	lsp->ls_owner = fl_owner;
 	spin_lock(&clp->cl_lock);
-	lsp->ls_id = nfs4_alloc_lockowner_id(clp);
+	nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
 	spin_unlock(&clp->cl_lock);
 	INIT_LIST_HEAD(&lsp->ls_locks);
 	return lsp;
 }
 
+static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
+{
+	struct nfs_client *clp = lsp->ls_state->owner->so_client;
+
+	spin_lock(&clp->cl_lock);
+	nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id);
+	spin_unlock(&clp->cl_lock);
+	kfree(lsp);
+}
+
 /*
  * Return a compatible lock_state. If no initialized lock_state structure
  * exists, return an uninitialized one.
@@ -450,7 +551,8 @@
 			return NULL;
 	}
 	spin_unlock(&state->state_lock);
-	kfree(new);
+	if (new != NULL)
+		nfs4_free_lock_state(new);
 	return lsp;
 }
 
@@ -471,7 +573,7 @@
 	if (list_empty(&state->lock_states))
 		clear_bit(LK_STATE_IN_USE, &state->flags);
 	spin_unlock(&state->state_lock);
-	kfree(lsp);
+	nfs4_free_lock_state(lsp);
 }
 
 static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
@@ -513,8 +615,12 @@
 void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
 {
 	struct nfs4_lock_state *lsp;
+	int seq;
 
-	memcpy(dst, &state->stateid, sizeof(*dst));
+	do {
+		seq = read_seqbegin(&state->seqlock);
+		memcpy(dst, &state->stateid, sizeof(*dst));
+	} while (read_seqretry(&state->seqlock, seq));
 	if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
 		return;
 
@@ -557,12 +663,18 @@
  * failed with a seqid incrementing error -
  * see comments nfs_fs.h:seqid_mutating_error()
  */
-static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
+static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
 {
 	switch (status) {
 		case 0:
 			break;
 		case -NFS4ERR_BAD_SEQID:
+			if (seqid->sequence->flags & NFS_SEQID_CONFIRMED)
+				return;
+			printk(KERN_WARNING "NFS: v4 server returned a bad"
+					"sequence-id error on an"
+					"unconfirmed sequence %p!\n",
+					seqid->sequence);
 		case -NFS4ERR_STALE_CLIENTID:
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_BAD_STATEID:
@@ -586,7 +698,7 @@
 				struct nfs4_state_owner, so_seqid);
 		nfs4_drop_state_owner(sp);
 	}
-	return nfs_increment_seqid(status, seqid);
+	nfs_increment_seqid(status, seqid);
 }
 
 /*
@@ -596,7 +708,7 @@
  */
 void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
 {
-	return nfs_increment_seqid(status, seqid);
+	nfs_increment_seqid(status, seqid);
 }
 
 int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
@@ -748,15 +860,21 @@
 static void nfs4_state_mark_reclaim(struct nfs_client *clp)
 {
 	struct nfs4_state_owner *sp;
+	struct rb_node *pos;
 	struct nfs4_state *state;
 	struct nfs4_lock_state *lock;
 
 	/* Reset all sequence ids to zero */
-	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+	for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+		sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
 		sp->so_seqid.counter = 0;
 		sp->so_seqid.flags = 0;
 		spin_lock(&sp->so_lock);
 		list_for_each_entry(state, &sp->so_states, open_states) {
+			clear_bit(NFS_DELEGATED_STATE, &state->flags);
+			clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+			clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+			clear_bit(NFS_O_RDWR_STATE, &state->flags);
 			list_for_each_entry(lock, &state->lock_states, ls_locks) {
 				lock->ls_seqid.counter = 0;
 				lock->ls_seqid.flags = 0;
@@ -771,6 +889,7 @@
 {
 	struct nfs_client *clp = ptr;
 	struct nfs4_state_owner *sp;
+	struct rb_node *pos;
 	struct nfs4_state_recovery_ops *ops;
 	struct rpc_cred *cred;
 	int status = 0;
@@ -816,7 +935,8 @@
 	/* Mark all delegations for reclaim */
 	nfs_delegation_mark_reclaim(clp);
 	/* Note: list is protected by exclusive lock on cl->cl_sem */
-	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+	for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+		sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
 		status = nfs4_reclaim_open_state(ops, sp);
 		if (status < 0) {
 			if (status == -NFS4ERR_NO_GRACE) {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 8003c91..c087384 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -68,9 +68,10 @@
 #endif
 
 /* lock,open owner id: 
- * we currently use size 1 (u32) out of (NFS4_OPAQUE_LIMIT  >> 2)
+ * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT  >> 2)
  */
-#define owner_id_maxsz          (1 + 1)
+#define open_owner_id_maxsz	(1 + 4)
+#define lock_owner_id_maxsz	(1 + 4)
 #define compound_encode_hdr_maxsz	(3 + (NFS4_MAXTAGLEN >> 2))
 #define compound_decode_hdr_maxsz	(3 + (NFS4_MAXTAGLEN >> 2))
 #define op_encode_hdr_maxsz	(1)
@@ -87,9 +88,11 @@
 #define encode_getattr_maxsz    (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
 #define nfs4_name_maxsz		(1 + ((3 + NFS4_MAXNAMLEN) >> 2))
 #define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
+#define nfs4_owner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
+#define nfs4_group_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
 /* This is based on getfattr, which uses the most attributes: */
 #define nfs4_fattr_value_maxsz	(1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
-				3 + 3 + 3 + 2 * nfs4_name_maxsz))
+				3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz))
 #define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
 				nfs4_fattr_value_maxsz)
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
@@ -116,8 +119,27 @@
 				3 + (NFS4_VERIFIER_SIZE >> 2))
 #define decode_setclientid_confirm_maxsz \
 				(op_decode_hdr_maxsz)
-#define encode_lookup_maxsz	(op_encode_hdr_maxsz + \
-				1 + ((3 + NFS4_FHSIZE) >> 2))
+#define encode_lookup_maxsz	(op_encode_hdr_maxsz + nfs4_name_maxsz)
+#define decode_lookup_maxsz	(op_decode_hdr_maxsz)
+#define encode_share_access_maxsz \
+				(2)
+#define encode_createmode_maxsz	(1 + nfs4_fattr_maxsz)
+#define encode_opentype_maxsz	(1 + encode_createmode_maxsz)
+#define encode_claim_null_maxsz	(1 + nfs4_name_maxsz)
+#define encode_open_maxsz	(op_encode_hdr_maxsz + \
+				2 + encode_share_access_maxsz + 2 + \
+				open_owner_id_maxsz + \
+				encode_opentype_maxsz + \
+				encode_claim_null_maxsz)
+#define decode_ace_maxsz	(3 + nfs4_owner_maxsz)
+#define decode_delegation_maxsz	(1 + XDR_QUADLEN(NFS4_STATEID_SIZE) + 1 + \
+				decode_ace_maxsz)
+#define decode_change_info_maxsz	(5)
+#define decode_open_maxsz	(op_decode_hdr_maxsz + \
+				XDR_QUADLEN(NFS4_STATEID_SIZE) + \
+				decode_change_info_maxsz + 1 + \
+				nfs4_fattr_bitmap_maxsz + \
+				decode_delegation_maxsz)
 #define encode_remove_maxsz	(op_encode_hdr_maxsz + \
 				nfs4_name_maxsz)
 #define encode_rename_maxsz	(op_encode_hdr_maxsz + \
@@ -134,9 +156,15 @@
 #define encode_create_maxsz	(op_encode_hdr_maxsz + \
 				2 + nfs4_name_maxsz + \
 				nfs4_fattr_maxsz)
-#define decode_create_maxsz	(op_decode_hdr_maxsz + 8)
+#define decode_create_maxsz	(op_decode_hdr_maxsz + \
+				decode_change_info_maxsz + \
+				nfs4_fattr_bitmap_maxsz)
 #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
 #define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
+#define encode_fs_locations_maxsz \
+				(encode_getattr_maxsz)
+#define decode_fs_locations_maxsz \
+				(0)
 #define NFS4_enc_compound_sz	(1024)  /* XXX: large enough? */
 #define NFS4_dec_compound_sz	(1024)  /* XXX: large enough? */
 #define NFS4_enc_read_sz	(compound_encode_hdr_maxsz + \
@@ -174,16 +202,21 @@
 				op_decode_hdr_maxsz + 2 + \
 				decode_getattr_maxsz)
 #define NFS4_enc_open_sz        (compound_encode_hdr_maxsz + \
-                                encode_putfh_maxsz + \
-                                op_encode_hdr_maxsz + \
-                                13 + 3 + 2 + 64 + \
-                                encode_getattr_maxsz + \
-                                encode_getfh_maxsz)
+				encode_putfh_maxsz + \
+				encode_savefh_maxsz + \
+				encode_open_maxsz + \
+				encode_getfh_maxsz + \
+				encode_getattr_maxsz + \
+				encode_restorefh_maxsz + \
+				encode_getattr_maxsz)
 #define NFS4_dec_open_sz        (compound_decode_hdr_maxsz + \
-                                decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + 4 + 5 + 2 + 3 + \
-                                decode_getattr_maxsz + \
-                                decode_getfh_maxsz)
+				decode_putfh_maxsz + \
+				decode_savefh_maxsz + \
+				decode_open_maxsz + \
+				decode_getfh_maxsz + \
+				decode_getattr_maxsz + \
+				decode_restorefh_maxsz + \
+				decode_getattr_maxsz)
 #define NFS4_enc_open_confirm_sz      \
                                 (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
@@ -193,12 +226,12 @@
                                         op_decode_hdr_maxsz + 4)
 #define NFS4_enc_open_noattr_sz	(compound_encode_hdr_maxsz + \
 					encode_putfh_maxsz + \
-					op_encode_hdr_maxsz + \
-					11)
+					encode_open_maxsz + \
+					encode_getattr_maxsz)
 #define NFS4_dec_open_noattr_sz	(compound_decode_hdr_maxsz + \
 					decode_putfh_maxsz + \
-					op_decode_hdr_maxsz + \
-					4 + 5 + 2 + 3)
+					decode_open_maxsz + \
+					decode_getattr_maxsz)
 #define NFS4_enc_open_downgrade_sz \
 				(compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
@@ -256,19 +289,19 @@
 				op_encode_hdr_maxsz + \
 				1 + 1 + 2 + 2 + \
 				1 + 4 + 1 + 2 + \
-				owner_id_maxsz)
+				lock_owner_id_maxsz)
 #define NFS4_dec_lock_sz        (compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
 				decode_getattr_maxsz + \
 				op_decode_hdr_maxsz + \
 				2 + 2 + 1 + 2 + \
-				owner_id_maxsz)
+				lock_owner_id_maxsz)
 #define NFS4_enc_lockt_sz       (compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
 				encode_getattr_maxsz + \
 				op_encode_hdr_maxsz + \
 				1 + 2 + 2 + 2 + \
-				owner_id_maxsz)
+				lock_owner_id_maxsz)
 #define NFS4_dec_lockt_sz       (NFS4_dec_lock_sz)
 #define NFS4_enc_locku_sz       (compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
@@ -298,7 +331,7 @@
 				encode_getfh_maxsz)
 #define NFS4_dec_lookup_sz	(compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
-				op_decode_hdr_maxsz + \
+				decode_lookup_maxsz + \
 				decode_getattr_maxsz + \
 				decode_getfh_maxsz)
 #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
@@ -417,12 +450,13 @@
 #define NFS4_enc_fs_locations_sz \
 				(compound_encode_hdr_maxsz + \
 				 encode_putfh_maxsz + \
-				 encode_getattr_maxsz)
+				 encode_lookup_maxsz + \
+				 encode_fs_locations_maxsz)
 #define NFS4_dec_fs_locations_sz \
 				(compound_decode_hdr_maxsz + \
 				 decode_putfh_maxsz + \
-				 op_decode_hdr_maxsz + \
-				 nfs4_fattr_bitmap_maxsz)
+				 decode_lookup_maxsz + \
+				 decode_fs_locations_maxsz)
 
 static struct {
 	unsigned int	mode;
@@ -793,13 +827,14 @@
 	WRITE64(nfs4_lock_length(args->fl));
 	WRITE32(args->new_lock_owner);
 	if (args->new_lock_owner){
-		RESERVE_SPACE(4+NFS4_STATEID_SIZE+20);
+		RESERVE_SPACE(4+NFS4_STATEID_SIZE+32);
 		WRITE32(args->open_seqid->sequence->counter);
 		WRITEMEM(args->open_stateid->data, NFS4_STATEID_SIZE);
 		WRITE32(args->lock_seqid->sequence->counter);
 		WRITE64(args->lock_owner.clientid);
-		WRITE32(4);
-		WRITE32(args->lock_owner.id);
+		WRITE32(16);
+		WRITEMEM("lock id:", 8);
+		WRITE64(args->lock_owner.id);
 	}
 	else {
 		RESERVE_SPACE(NFS4_STATEID_SIZE+4);
@@ -814,14 +849,15 @@
 {
 	__be32 *p;
 
-	RESERVE_SPACE(40);
+	RESERVE_SPACE(52);
 	WRITE32(OP_LOCKT);
 	WRITE32(nfs4_lock_type(args->fl, 0));
 	WRITE64(args->fl->fl_start);
 	WRITE64(nfs4_lock_length(args->fl));
 	WRITE64(args->lock_owner.clientid);
-	WRITE32(4);
-	WRITE32(args->lock_owner.id);
+	WRITE32(16);
+	WRITEMEM("lock id:", 8);
+	WRITE64(args->lock_owner.id);
 
 	return 0;
 }
@@ -886,10 +922,11 @@
 	WRITE32(OP_OPEN);
 	WRITE32(arg->seqid->sequence->counter);
 	encode_share_access(xdr, arg->open_flags);
-	RESERVE_SPACE(16);
+	RESERVE_SPACE(28);
 	WRITE64(arg->clientid);
-	WRITE32(4);
-	WRITE32(arg->id);
+	WRITE32(16);
+	WRITEMEM("open id:", 8);
+	WRITE64(arg->id);
 }
 
 static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
@@ -1071,7 +1108,7 @@
 
 static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
 {
-	struct rpc_auth *auth = req->rq_task->tk_auth;
+	struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	uint32_t attrs[2] = {
 		FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
 		FATTR4_WORD1_MOUNTED_ON_FILEID,
@@ -1117,7 +1154,7 @@
 
 static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
 {
-	struct rpc_auth *auth = req->rq_task->tk_auth;
+	struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	unsigned int replen;
 	__be32 *p;
 
@@ -1735,7 +1772,7 @@
  */
 static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
-	struct rpc_auth	*auth = req->rq_task->tk_auth;
+	struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
 		.nops = 2,
@@ -1795,7 +1832,7 @@
 		struct nfs_getaclargs *args)
 {
 	struct xdr_stream xdr;
-	struct rpc_auth *auth = req->rq_task->tk_auth;
+	struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	struct compound_hdr hdr = {
 		.nops   = 2,
 	};
@@ -2030,7 +2067,7 @@
 	struct compound_hdr hdr = {
 		.nops = 3,
 	};
-	struct rpc_auth *auth = req->rq_task->tk_auth;
+	struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 	int replen;
 	int status;
 
@@ -3269,7 +3306,7 @@
 static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
 {
         __be32 *p;
-        uint32_t bmlen;
+	uint32_t savewords, bmlen, i;
         int status;
 
         status = decode_op_hdr(xdr, OP_OPEN);
@@ -3287,7 +3324,12 @@
                 goto xdr_error;
 
         READ_BUF(bmlen << 2);
-        p += bmlen;
+	savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
+	for (i = 0; i < savewords; ++i)
+		READ32(res->attrset[i]);
+	for (; i < NFS4_BITMAP_SIZE; i++)
+		res->attrset[i] = 0;
+
 	return decode_delegation(xdr, res);
 xdr_error:
 	dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen);
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 49d1008..3490322 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -428,7 +428,7 @@
 	printk(KERN_NOTICE "Looking up port of RPC %d/%d on %u.%u.%u.%u\n",
 		program, version, NIPQUAD(servaddr));
 	set_sockaddr(&sin, servaddr, 0);
-	return rpcb_getport_external(&sin, program, version, proto);
+	return rpcb_getport_sync(&sin, program, version, proto);
 }
 
 
@@ -496,7 +496,8 @@
 					NFS_MNT3_VERSION : NFS_MNT_VERSION;
 
 	set_sockaddr(&sin, servaddr, htons(mount_port));
-	status = nfsroot_mount(&sin, nfs_path, &fh, version, protocol);
+	status = nfs_mount((struct sockaddr *) &sin, sizeof(sin), NULL,
+			   nfs_path, version, protocol, &fh);
 	if (status < 0)
 		printk(KERN_ERR "Root-NFS: Server returned error %d "
 				"while mounting %s\n", status, nfs_path);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index e12054c..f56dae5 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -11,6 +11,7 @@
 
 #include <linux/slab.h>
 #include <linux/file.h>
+#include <linux/sched.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs3.h>
 #include <linux/nfs4.h>
@@ -84,9 +85,8 @@
 	req->wb_offset  = offset;
 	req->wb_pgbase	= offset;
 	req->wb_bytes   = count;
-	atomic_set(&req->wb_count, 1);
 	req->wb_context = get_nfs_open_context(ctx);
-
+	kref_init(&req->wb_kref);
 	return req;
 }
 
@@ -108,30 +108,31 @@
 }
 
 /**
- * nfs_set_page_writeback_locked - Lock a request for writeback
+ * nfs_set_page_tag_locked - Tag a request as locked
  * @req:
  */
-int nfs_set_page_writeback_locked(struct nfs_page *req)
+static int nfs_set_page_tag_locked(struct nfs_page *req)
 {
-	struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+	struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode);
 
 	if (!nfs_lock_request(req))
 		return 0;
-	radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+	radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
 	return 1;
 }
 
 /**
- * nfs_clear_page_writeback - Unlock request and wake up sleepers
+ * nfs_clear_page_tag_locked - Clear request tag and wake up sleepers
  */
-void nfs_clear_page_writeback(struct nfs_page *req)
+void nfs_clear_page_tag_locked(struct nfs_page *req)
 {
-	struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+	struct inode *inode = req->wb_context->path.dentry->d_inode;
+	struct nfs_inode *nfsi = NFS_I(inode);
 
 	if (req->wb_page != NULL) {
-		spin_lock(&nfsi->req_lock);
-		radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
-		spin_unlock(&nfsi->req_lock);
+		spin_lock(&inode->i_lock);
+		radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
+		spin_unlock(&inode->i_lock);
 	}
 	nfs_unlock_request(req);
 }
@@ -159,11 +160,9 @@
  *
  * Note: Should never be called with the spinlock held!
  */
-void
-nfs_release_request(struct nfs_page *req)
+static void nfs_free_request(struct kref *kref)
 {
-	if (!atomic_dec_and_test(&req->wb_count))
-		return;
+	struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
 
 	/* Release struct file or cached credential */
 	nfs_clear_request(req);
@@ -171,6 +170,11 @@
 	nfs_page_free(req);
 }
 
+void nfs_release_request(struct nfs_page *req)
+{
+	kref_put(&req->wb_kref, nfs_free_request);
+}
+
 static int nfs_wait_bit_interruptible(void *word)
 {
 	int ret = 0;
@@ -192,7 +196,7 @@
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-        struct rpc_clnt	*clnt = NFS_CLIENT(req->wb_context->dentry->d_inode);
+	struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->path.dentry->d_inode);
 	sigset_t oldmask;
 	int ret = 0;
 
@@ -354,24 +358,44 @@
 	nfs_pageio_doio(desc);
 }
 
+/**
+ * nfs_pageio_cond_complete - Conditional I/O completion
+ * @desc: pointer to io descriptor
+ * @index: page index
+ *
+ * It is important to ensure that processes don't try to take locks
+ * on non-contiguous ranges of pages as that might deadlock. This
+ * function should be called before attempting to wait on a locked
+ * nfs_page. It will complete the I/O if the page index 'index'
+ * is not contiguous with the existing list of pages in 'desc'.
+ */
+void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
+{
+	if (!list_empty(&desc->pg_list)) {
+		struct nfs_page *prev = nfs_list_entry(desc->pg_list.prev);
+		if (index != prev->wb_index + 1)
+			nfs_pageio_doio(desc);
+	}
+}
+
 #define NFS_SCAN_MAXENTRIES 16
 /**
  * nfs_scan_list - Scan a list for matching requests
  * @nfsi: NFS inode
- * @head: One of the NFS inode request lists
  * @dst: Destination list
  * @idx_start: lower bound of page->index to scan
  * @npages: idx_start + npages sets the upper bound to scan.
+ * @tag: tag to scan for
  *
  * Moves elements from one of the inode request lists.
  * If the number of requests is set to 0, the entire address_space
  * starting at index idx_start, is scanned.
  * The requests are *not* checked to ensure that they form a contiguous set.
- * You must be holding the inode's req_lock when calling this function
+ * You must be holding the inode's i_lock when calling this function
  */
-int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
+int nfs_scan_list(struct nfs_inode *nfsi,
 		struct list_head *dst, pgoff_t idx_start,
-		unsigned int npages)
+		unsigned int npages, int tag)
 {
 	struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
 	struct nfs_page *req;
@@ -386,9 +410,9 @@
 		idx_end = idx_start + npages - 1;
 
 	for (;;) {
-		found = radix_tree_gang_lookup(&nfsi->nfs_page_tree,
+		found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
 				(void **)&pgvec[0], idx_start,
-				NFS_SCAN_MAXENTRIES);
+				NFS_SCAN_MAXENTRIES, tag);
 		if (found <= 0)
 			break;
 		for (i = 0; i < found; i++) {
@@ -396,15 +420,18 @@
 			if (req->wb_index > idx_end)
 				goto out;
 			idx_start = req->wb_index + 1;
-			if (req->wb_list_head != head)
-				continue;
-			if (nfs_set_page_writeback_locked(req)) {
+			if (nfs_set_page_tag_locked(req)) {
 				nfs_list_remove_request(req);
+				radix_tree_tag_clear(&nfsi->nfs_page_tree,
+						req->wb_index, tag);
 				nfs_list_add_request(req, dst);
 				res++;
+				if (res == INT_MAX)
+					goto out;
 			}
 		}
-
+		/* for latency reduction */
+		cond_resched_lock(&nfsi->vfs_inode.i_lock);
 	}
 out:
 	return res;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 7bd7cb9..6ae2e58 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -145,8 +145,8 @@
 	unlock_page(req->wb_page);
 
 	dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
-			req->wb_context->dentry->d_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+			req->wb_context->path.dentry->d_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 	nfs_clear_request(req);
@@ -164,7 +164,7 @@
 	int flags;
 
 	data->req	  = req;
-	data->inode	  = inode = req->wb_context->dentry->d_inode;
+	data->inode	  = inode = req->wb_context->path.dentry->d_inode;
 	data->cred	  = req->wb_context->cred;
 
 	data->args.fh     = NFS_FH(inode);
@@ -483,17 +483,19 @@
 	 */
 	error = nfs_wb_page(inode, page);
 	if (error)
-		goto out_error;
+		goto out_unlock;
+	if (PageUptodate(page))
+		goto out_unlock;
 
 	error = -ESTALE;
 	if (NFS_STALE(inode))
-		goto out_error;
+		goto out_unlock;
 
 	if (file == NULL) {
 		error = -EBADF;
 		ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
 		if (ctx == NULL)
-			goto out_error;
+			goto out_unlock;
 	} else
 		ctx = get_nfs_open_context((struct nfs_open_context *)
 				file->private_data);
@@ -502,8 +504,7 @@
 
 	put_nfs_open_context(ctx);
 	return error;
-
-out_error:
+out_unlock:
 	unlock_page(page);
 	return error;
 }
@@ -520,21 +521,32 @@
 	struct inode *inode = page->mapping->host;
 	struct nfs_page *new;
 	unsigned int len;
+	int error;
 
-	nfs_wb_page(inode, page);
+	error = nfs_wb_page(inode, page);
+	if (error)
+		goto out_unlock;
+	if (PageUptodate(page))
+		goto out_unlock;
+
 	len = nfs_page_length(page);
 	if (len == 0)
 		return nfs_return_empty_page(page);
+
 	new = nfs_create_request(desc->ctx, inode, page, 0, len);
-	if (IS_ERR(new)) {
-			SetPageError(page);
-			unlock_page(page);
-			return PTR_ERR(new);
-	}
+	if (IS_ERR(new))
+		goto out_error;
+
 	if (len < PAGE_CACHE_SIZE)
 		zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0);
 	nfs_pageio_add_request(desc->pgio, new);
 	return 0;
+out_error:
+	error = PTR_ERR(new);
+	SetPageError(page);
+out_unlock:
+	unlock_page(page);
+	return error;
 }
 
 int nfs_readpages(struct file *filp, struct address_space *mapping,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ca20d3c..adffe16 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -45,6 +45,7 @@
 #include <linux/inet.h>
 #include <linux/nfs_xdr.h>
 #include <linux/magic.h>
+#include <linux/parser.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -57,6 +58,167 @@
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
 
+
+struct nfs_parsed_mount_data {
+	int			flags;
+	int			rsize, wsize;
+	int			timeo, retrans;
+	int			acregmin, acregmax,
+				acdirmin, acdirmax;
+	int			namlen;
+	unsigned int		bsize;
+	unsigned int		auth_flavor_len;
+	rpc_authflavor_t	auth_flavors[1];
+	char			*client_address;
+
+	struct {
+		struct sockaddr_in	address;
+		unsigned int		program;
+		unsigned int		version;
+		unsigned short		port;
+		int			protocol;
+	} mount_server;
+
+	struct {
+		struct sockaddr_in	address;
+		char			*hostname;
+		char			*export_path;
+		unsigned int		program;
+		int			protocol;
+	} nfs_server;
+};
+
+enum {
+	/* Mount options that take no arguments */
+	Opt_soft, Opt_hard,
+	Opt_intr, Opt_nointr,
+	Opt_posix, Opt_noposix,
+	Opt_cto, Opt_nocto,
+	Opt_ac, Opt_noac,
+	Opt_lock, Opt_nolock,
+	Opt_v2, Opt_v3,
+	Opt_udp, Opt_tcp,
+	Opt_acl, Opt_noacl,
+	Opt_rdirplus, Opt_nordirplus,
+	Opt_sharecache, Opt_nosharecache,
+
+	/* Mount options that take integer arguments */
+	Opt_port,
+	Opt_rsize, Opt_wsize, Opt_bsize,
+	Opt_timeo, Opt_retrans,
+	Opt_acregmin, Opt_acregmax,
+	Opt_acdirmin, Opt_acdirmax,
+	Opt_actimeo,
+	Opt_namelen,
+	Opt_mountport,
+	Opt_mountprog, Opt_mountvers,
+	Opt_nfsprog, Opt_nfsvers,
+
+	/* Mount options that take string arguments */
+	Opt_sec, Opt_proto, Opt_mountproto,
+	Opt_addr, Opt_mounthost, Opt_clientaddr,
+
+	/* Mount options that are ignored */
+	Opt_userspace, Opt_deprecated,
+
+	Opt_err
+};
+
+static match_table_t nfs_mount_option_tokens = {
+	{ Opt_userspace, "bg" },
+	{ Opt_userspace, "fg" },
+	{ Opt_soft, "soft" },
+	{ Opt_hard, "hard" },
+	{ Opt_intr, "intr" },
+	{ Opt_nointr, "nointr" },
+	{ Opt_posix, "posix" },
+	{ Opt_noposix, "noposix" },
+	{ Opt_cto, "cto" },
+	{ Opt_nocto, "nocto" },
+	{ Opt_ac, "ac" },
+	{ Opt_noac, "noac" },
+	{ Opt_lock, "lock" },
+	{ Opt_nolock, "nolock" },
+	{ Opt_v2, "v2" },
+	{ Opt_v3, "v3" },
+	{ Opt_udp, "udp" },
+	{ Opt_tcp, "tcp" },
+	{ Opt_acl, "acl" },
+	{ Opt_noacl, "noacl" },
+	{ Opt_rdirplus, "rdirplus" },
+	{ Opt_nordirplus, "nordirplus" },
+	{ Opt_sharecache, "sharecache" },
+	{ Opt_nosharecache, "nosharecache" },
+
+	{ Opt_port, "port=%u" },
+	{ Opt_rsize, "rsize=%u" },
+	{ Opt_wsize, "wsize=%u" },
+	{ Opt_bsize, "bsize=%u" },
+	{ Opt_timeo, "timeo=%u" },
+	{ Opt_retrans, "retrans=%u" },
+	{ Opt_acregmin, "acregmin=%u" },
+	{ Opt_acregmax, "acregmax=%u" },
+	{ Opt_acdirmin, "acdirmin=%u" },
+	{ Opt_acdirmax, "acdirmax=%u" },
+	{ Opt_actimeo, "actimeo=%u" },
+	{ Opt_userspace, "retry=%u" },
+	{ Opt_namelen, "namlen=%u" },
+	{ Opt_mountport, "mountport=%u" },
+	{ Opt_mountprog, "mountprog=%u" },
+	{ Opt_mountvers, "mountvers=%u" },
+	{ Opt_nfsprog, "nfsprog=%u" },
+	{ Opt_nfsvers, "nfsvers=%u" },
+	{ Opt_nfsvers, "vers=%u" },
+
+	{ Opt_sec, "sec=%s" },
+	{ Opt_proto, "proto=%s" },
+	{ Opt_mountproto, "mountproto=%s" },
+	{ Opt_addr, "addr=%s" },
+	{ Opt_clientaddr, "clientaddr=%s" },
+	{ Opt_mounthost, "mounthost=%s" },
+
+	{ Opt_err, NULL }
+};
+
+enum {
+	Opt_xprt_udp, Opt_xprt_tcp,
+
+	Opt_xprt_err
+};
+
+static match_table_t nfs_xprt_protocol_tokens = {
+	{ Opt_xprt_udp, "udp" },
+	{ Opt_xprt_tcp, "tcp" },
+
+	{ Opt_xprt_err, NULL }
+};
+
+enum {
+	Opt_sec_none, Opt_sec_sys,
+	Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
+	Opt_sec_lkey, Opt_sec_lkeyi, Opt_sec_lkeyp,
+	Opt_sec_spkm, Opt_sec_spkmi, Opt_sec_spkmp,
+
+	Opt_sec_err
+};
+
+static match_table_t nfs_secflavor_tokens = {
+	{ Opt_sec_none, "none" },
+	{ Opt_sec_none, "null" },
+	{ Opt_sec_sys, "sys" },
+
+	{ Opt_sec_krb5, "krb5" },
+	{ Opt_sec_krb5i, "krb5i" },
+	{ Opt_sec_krb5p, "krb5p" },
+
+	{ Opt_sec_lkey, "lkey" },
+	{ Opt_sec_lkeyi, "lkeyi" },
+	{ Opt_sec_lkeyp, "lkeyp" },
+
+	{ Opt_sec_err, NULL }
+};
+
+
 static void nfs_umount_begin(struct vfsmount *, int);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
@@ -138,7 +300,10 @@
 };
 #endif
 
-static struct shrinker *acl_shrinker;
+static struct shrinker acl_shrinker = {
+	.shrink		= nfs_access_cache_shrinker,
+	.seeks		= DEFAULT_SEEKS,
+};
 
 /*
  * Register the NFS filesystems
@@ -159,7 +324,7 @@
 	if (ret < 0)
 		goto error_2;
 #endif
-	acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker);
+	register_shrinker(&acl_shrinker);
 	return 0;
 
 #ifdef CONFIG_NFS_V4
@@ -177,8 +342,7 @@
  */
 void __exit unregister_nfs_fs(void)
 {
-	if (acl_shrinker != NULL)
-		remove_shrinker(acl_shrinker);
+	unregister_shrinker(&acl_shrinker);
 #ifdef CONFIG_NFS_V4
 	unregister_filesystem(&nfs4_fs_type);
 	nfs_unregister_sysctl();
@@ -263,11 +427,11 @@
 		{ RPC_AUTH_GSS_SPKM, "spkm" },
 		{ RPC_AUTH_GSS_SPKMI, "spkmi" },
 		{ RPC_AUTH_GSS_SPKMP, "spkmp" },
-		{ -1, "unknown" }
+		{ UINT_MAX, "unknown" }
 	};
 	int i;
 
-	for (i=0; sec_flavours[i].flavour != -1; i++) {
+	for (i = 0; sec_flavours[i].flavour != UINT_MAX; i++) {
 		if (sec_flavours[i].flavour == flavour)
 			break;
 	}
@@ -291,6 +455,7 @@
 		{ NFS_MOUNT_NONLM, ",nolock", "" },
 		{ NFS_MOUNT_NOACL, ",noacl", "" },
 		{ NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
+		{ NFS_MOUNT_UNSHARED, ",nosharecache", ""},
 		{ 0, NULL, NULL }
 	};
 	const struct proc_nfs_info *nfs_infop;
@@ -430,87 +595,641 @@
  */
 static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
 {
+	struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
+	struct rpc_clnt *rpc;
+
 	shrink_submounts(vfsmnt, &nfs_automount_list);
+
+	if (!(flags & MNT_FORCE))
+		return;
+	/* -EIO all pending I/O */
+	rpc = server->client_acl;
+	if (!IS_ERR(rpc))
+		rpc_killall_tasks(rpc);
+	rpc = server->client;
+	if (!IS_ERR(rpc))
+		rpc_killall_tasks(rpc);
+}
+
+/*
+ * Sanity-check a server address provided by the mount command
+ */
+static int nfs_verify_server_address(struct sockaddr *addr)
+{
+	switch (addr->sa_family) {
+	case AF_INET: {
+		struct sockaddr_in *sa = (struct sockaddr_in *) addr;
+		if (sa->sin_addr.s_addr != INADDR_ANY)
+			return 1;
+		break;
+	}
+	}
+
+	return 0;
+}
+
+/*
+ * Error-check and convert a string of mount options from user space into
+ * a data structure
+ */
+static int nfs_parse_mount_options(char *raw,
+				   struct nfs_parsed_mount_data *mnt)
+{
+	char *p, *string;
+
+	if (!raw) {
+		dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
+		return 1;
+	}
+	dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
+
+	while ((p = strsep(&raw, ",")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int option, token;
+
+		if (!*p)
+			continue;
+
+		dfprintk(MOUNT, "NFS:   parsing nfs mount option '%s'\n", p);
+
+		token = match_token(p, nfs_mount_option_tokens, args);
+		switch (token) {
+		case Opt_soft:
+			mnt->flags |= NFS_MOUNT_SOFT;
+			break;
+		case Opt_hard:
+			mnt->flags &= ~NFS_MOUNT_SOFT;
+			break;
+		case Opt_intr:
+			mnt->flags |= NFS_MOUNT_INTR;
+			break;
+		case Opt_nointr:
+			mnt->flags &= ~NFS_MOUNT_INTR;
+			break;
+		case Opt_posix:
+			mnt->flags |= NFS_MOUNT_POSIX;
+			break;
+		case Opt_noposix:
+			mnt->flags &= ~NFS_MOUNT_POSIX;
+			break;
+		case Opt_cto:
+			mnt->flags &= ~NFS_MOUNT_NOCTO;
+			break;
+		case Opt_nocto:
+			mnt->flags |= NFS_MOUNT_NOCTO;
+			break;
+		case Opt_ac:
+			mnt->flags &= ~NFS_MOUNT_NOAC;
+			break;
+		case Opt_noac:
+			mnt->flags |= NFS_MOUNT_NOAC;
+			break;
+		case Opt_lock:
+			mnt->flags &= ~NFS_MOUNT_NONLM;
+			break;
+		case Opt_nolock:
+			mnt->flags |= NFS_MOUNT_NONLM;
+			break;
+		case Opt_v2:
+			mnt->flags &= ~NFS_MOUNT_VER3;
+			break;
+		case Opt_v3:
+			mnt->flags |= NFS_MOUNT_VER3;
+			break;
+		case Opt_udp:
+			mnt->flags &= ~NFS_MOUNT_TCP;
+			mnt->nfs_server.protocol = IPPROTO_UDP;
+			mnt->timeo = 7;
+			mnt->retrans = 5;
+			break;
+		case Opt_tcp:
+			mnt->flags |= NFS_MOUNT_TCP;
+			mnt->nfs_server.protocol = IPPROTO_TCP;
+			mnt->timeo = 600;
+			mnt->retrans = 2;
+			break;
+		case Opt_acl:
+			mnt->flags &= ~NFS_MOUNT_NOACL;
+			break;
+		case Opt_noacl:
+			mnt->flags |= NFS_MOUNT_NOACL;
+			break;
+		case Opt_rdirplus:
+			mnt->flags &= ~NFS_MOUNT_NORDIRPLUS;
+			break;
+		case Opt_nordirplus:
+			mnt->flags |= NFS_MOUNT_NORDIRPLUS;
+			break;
+		case Opt_sharecache:
+			mnt->flags &= ~NFS_MOUNT_UNSHARED;
+			break;
+		case Opt_nosharecache:
+			mnt->flags |= NFS_MOUNT_UNSHARED;
+			break;
+
+		case Opt_port:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0 || option > 65535)
+				return 0;
+			mnt->nfs_server.address.sin_port = htonl(option);
+			break;
+		case Opt_rsize:
+			if (match_int(args, &mnt->rsize))
+				return 0;
+			break;
+		case Opt_wsize:
+			if (match_int(args, &mnt->wsize))
+				return 0;
+			break;
+		case Opt_bsize:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0)
+				return 0;
+			mnt->bsize = option;
+			break;
+		case Opt_timeo:
+			if (match_int(args, &mnt->timeo))
+				return 0;
+			break;
+		case Opt_retrans:
+			if (match_int(args, &mnt->retrans))
+				return 0;
+			break;
+		case Opt_acregmin:
+			if (match_int(args, &mnt->acregmin))
+				return 0;
+			break;
+		case Opt_acregmax:
+			if (match_int(args, &mnt->acregmax))
+				return 0;
+			break;
+		case Opt_acdirmin:
+			if (match_int(args, &mnt->acdirmin))
+				return 0;
+			break;
+		case Opt_acdirmax:
+			if (match_int(args, &mnt->acdirmax))
+				return 0;
+			break;
+		case Opt_actimeo:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0)
+				return 0;
+			mnt->acregmin =
+			mnt->acregmax =
+			mnt->acdirmin =
+			mnt->acdirmax = option;
+			break;
+		case Opt_namelen:
+			if (match_int(args, &mnt->namlen))
+				return 0;
+			break;
+		case Opt_mountport:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0 || option > 65535)
+				return 0;
+			mnt->mount_server.port = option;
+			break;
+		case Opt_mountprog:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0)
+				return 0;
+			mnt->mount_server.program = option;
+			break;
+		case Opt_mountvers:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0)
+				return 0;
+			mnt->mount_server.version = option;
+			break;
+		case Opt_nfsprog:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0)
+				return 0;
+			mnt->nfs_server.program = option;
+			break;
+		case Opt_nfsvers:
+			if (match_int(args, &option))
+				return 0;
+			switch (option) {
+			case 2:
+				mnt->flags &= ~NFS_MOUNT_VER3;
+				break;
+			case 3:
+				mnt->flags |= NFS_MOUNT_VER3;
+				break;
+			default:
+				goto out_unrec_vers;
+			}
+			break;
+
+		case Opt_sec:
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			token = match_token(string, nfs_secflavor_tokens, args);
+			kfree(string);
+
+			/*
+			 * The flags setting is for v2/v3.  The flavor_len
+			 * setting is for v4.  v2/v3 also need to know the
+			 * difference between NULL and UNIX.
+			 */
+			switch (token) {
+			case Opt_sec_none:
+				mnt->flags &= ~NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 0;
+				mnt->auth_flavors[0] = RPC_AUTH_NULL;
+				break;
+			case Opt_sec_sys:
+				mnt->flags &= ~NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 0;
+				mnt->auth_flavors[0] = RPC_AUTH_UNIX;
+				break;
+			case Opt_sec_krb5:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5;
+				break;
+			case Opt_sec_krb5i:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5I;
+				break;
+			case Opt_sec_krb5p:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5P;
+				break;
+			case Opt_sec_lkey:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEY;
+				break;
+			case Opt_sec_lkeyi:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYI;
+				break;
+			case Opt_sec_lkeyp:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYP;
+				break;
+			case Opt_sec_spkm:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKM;
+				break;
+			case Opt_sec_spkmi:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMI;
+				break;
+			case Opt_sec_spkmp:
+				mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+				mnt->auth_flavor_len = 1;
+				mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMP;
+				break;
+			default:
+				goto out_unrec_sec;
+			}
+			break;
+		case Opt_proto:
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			token = match_token(string,
+					    nfs_xprt_protocol_tokens, args);
+			kfree(string);
+
+			switch (token) {
+			case Opt_udp:
+				mnt->flags &= ~NFS_MOUNT_TCP;
+				mnt->nfs_server.protocol = IPPROTO_UDP;
+				mnt->timeo = 7;
+				mnt->retrans = 5;
+				break;
+			case Opt_tcp:
+				mnt->flags |= NFS_MOUNT_TCP;
+				mnt->nfs_server.protocol = IPPROTO_TCP;
+				mnt->timeo = 600;
+				mnt->retrans = 2;
+				break;
+			default:
+				goto out_unrec_xprt;
+			}
+			break;
+		case Opt_mountproto:
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			token = match_token(string,
+					    nfs_xprt_protocol_tokens, args);
+			kfree(string);
+
+			switch (token) {
+			case Opt_udp:
+				mnt->mount_server.protocol = IPPROTO_UDP;
+				break;
+			case Opt_tcp:
+				mnt->mount_server.protocol = IPPROTO_TCP;
+				break;
+			default:
+				goto out_unrec_xprt;
+			}
+			break;
+		case Opt_addr:
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			mnt->nfs_server.address.sin_family = AF_INET;
+			mnt->nfs_server.address.sin_addr.s_addr =
+							in_aton(string);
+			kfree(string);
+			break;
+		case Opt_clientaddr:
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			mnt->client_address = string;
+			break;
+		case Opt_mounthost:
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			mnt->mount_server.address.sin_family = AF_INET;
+			mnt->mount_server.address.sin_addr.s_addr =
+							in_aton(string);
+			kfree(string);
+			break;
+
+		case Opt_userspace:
+		case Opt_deprecated:
+			break;
+
+		default:
+			goto out_unknown;
+		}
+	}
+
+	return 1;
+
+out_nomem:
+	printk(KERN_INFO "NFS: not enough memory to parse option\n");
+	return 0;
+
+out_unrec_vers:
+	printk(KERN_INFO "NFS: unrecognized NFS version number\n");
+	return 0;
+
+out_unrec_xprt:
+	printk(KERN_INFO "NFS: unrecognized transport protocol\n");
+	return 0;
+
+out_unrec_sec:
+	printk(KERN_INFO "NFS: unrecognized security flavor\n");
+	return 0;
+
+out_unknown:
+	printk(KERN_INFO "NFS: unknown mount option: %s\n", p);
+	return 0;
+}
+
+/*
+ * Use the remote server's MOUNT service to request the NFS file handle
+ * corresponding to the provided path.
+ */
+static int nfs_try_mount(struct nfs_parsed_mount_data *args,
+			 struct nfs_fh *root_fh)
+{
+	struct sockaddr_in sin;
+	int status;
+
+	if (args->mount_server.version == 0) {
+		if (args->flags & NFS_MOUNT_VER3)
+			args->mount_server.version = NFS_MNT3_VERSION;
+		else
+			args->mount_server.version = NFS_MNT_VERSION;
+	}
+
+	/*
+	 * Construct the mount server's address.
+	 */
+	if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY)
+		sin = args->mount_server.address;
+	else
+		sin = args->nfs_server.address;
+	if (args->mount_server.port == 0) {
+		status = rpcb_getport_sync(&sin,
+					   args->mount_server.program,
+					   args->mount_server.version,
+					   args->mount_server.protocol);
+		if (status < 0)
+			goto out_err;
+		sin.sin_port = htons(status);
+	} else
+		sin.sin_port = htons(args->mount_server.port);
+
+	/*
+	 * Now ask the mount server to map our export path
+	 * to a file handle.
+	 */
+	status = nfs_mount((struct sockaddr *) &sin,
+			   sizeof(sin),
+			   args->nfs_server.hostname,
+			   args->nfs_server.export_path,
+			   args->mount_server.version,
+			   args->mount_server.protocol,
+			   root_fh);
+	if (status < 0)
+		goto out_err;
+
+	return status;
+
+out_err:
+	dfprintk(MOUNT, "NFS: unable to contact server on host "
+		 NIPQUAD_FMT "\n", NIPQUAD(sin.sin_addr.s_addr));
+	return status;
 }
 
 /*
  * Validate the NFS2/NFS3 mount data
  * - fills in the mount root filehandle
+ *
+ * For option strings, user space handles the following behaviors:
+ *
+ * + DNS: mapping server host name to IP address ("addr=" option)
+ *
+ * + failure mode: how to behave if a mount request can't be handled
+ *   immediately ("fg/bg" option)
+ *
+ * + retry: how often to retry a mount request ("retry=" option)
+ *
+ * + breaking back: trying proto=udp after proto=tcp, v2 after v3,
+ *   mountproto=tcp after mountproto=udp, and so on
+ *
+ * XXX: as far as I can tell, changing the NFS program number is not
+ *      supported in the NFS client.
  */
-static int nfs_validate_mount_data(struct nfs_mount_data *data,
-				   struct nfs_fh *mntfh)
+static int nfs_validate_mount_data(struct nfs_mount_data **options,
+				   struct nfs_fh *mntfh,
+				   const char *dev_name)
 {
-	if (data == NULL) {
-		dprintk("%s: missing data argument\n", __FUNCTION__);
-		return -EINVAL;
-	}
+	struct nfs_mount_data *data = *options;
 
-	if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
-		dprintk("%s: bad mount version\n", __FUNCTION__);
-		return -EINVAL;
-	}
+	if (data == NULL)
+		goto out_no_data;
 
 	switch (data->version) {
-		case 1:
-			data->namlen = 0;
-		case 2:
-			data->bsize  = 0;
-		case 3:
-			if (data->flags & NFS_MOUNT_VER3) {
-				dprintk("%s: mount structure version %d does not support NFSv3\n",
-						__FUNCTION__,
-						data->version);
-				return -EINVAL;
-			}
-			data->root.size = NFS2_FHSIZE;
-			memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
-		case 4:
-			if (data->flags & NFS_MOUNT_SECFLAVOUR) {
-				dprintk("%s: mount structure version %d does not support strong security\n",
-						__FUNCTION__,
-						data->version);
-				return -EINVAL;
-			}
-		case 5:
-			memset(data->context, 0, sizeof(data->context));
+	case 1:
+		data->namlen = 0;
+	case 2:
+		data->bsize = 0;
+	case 3:
+		if (data->flags & NFS_MOUNT_VER3)
+			goto out_no_v3;
+		data->root.size = NFS2_FHSIZE;
+		memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
+	case 4:
+		if (data->flags & NFS_MOUNT_SECFLAVOUR)
+			goto out_no_sec;
+	case 5:
+		memset(data->context, 0, sizeof(data->context));
+	case 6:
+		if (data->flags & NFS_MOUNT_VER3)
+			mntfh->size = data->root.size;
+		else
+			mntfh->size = NFS2_FHSIZE;
+
+		if (mntfh->size > sizeof(mntfh->data))
+			goto out_invalid_fh;
+
+		memcpy(mntfh->data, data->root.data, mntfh->size);
+		if (mntfh->size < sizeof(mntfh->data))
+			memset(mntfh->data + mntfh->size, 0,
+			       sizeof(mntfh->data) - mntfh->size);
+		break;
+	default: {
+		unsigned int len;
+		char *c;
+		int status;
+		struct nfs_parsed_mount_data args = {
+			.flags		= (NFS_MOUNT_VER3 | NFS_MOUNT_TCP),
+			.rsize		= NFS_MAX_FILE_IO_SIZE,
+			.wsize		= NFS_MAX_FILE_IO_SIZE,
+			.timeo		= 600,
+			.retrans	= 2,
+			.acregmin	= 3,
+			.acregmax	= 60,
+			.acdirmin	= 30,
+			.acdirmax	= 60,
+			.mount_server.protocol = IPPROTO_UDP,
+			.mount_server.program = NFS_MNT_PROGRAM,
+			.nfs_server.protocol = IPPROTO_TCP,
+			.nfs_server.program = NFS_PROGRAM,
+		};
+
+		if (nfs_parse_mount_options((char *) *options, &args) == 0)
+			return -EINVAL;
+
+		data = kzalloc(sizeof(*data), GFP_KERNEL);
+		if (data == NULL)
+			return -ENOMEM;
+
+		/*
+		 * NB: after this point, caller will free "data"
+		 * if we return an error
+		 */
+		*options = data;
+
+		c = strchr(dev_name, ':');
+		if (c == NULL)
+			return -EINVAL;
+		len = c - dev_name - 1;
+		if (len > sizeof(data->hostname))
+			return -EINVAL;
+		strncpy(data->hostname, dev_name, len);
+		args.nfs_server.hostname = data->hostname;
+
+		c++;
+		if (strlen(c) > NFS_MAXPATHLEN)
+			return -EINVAL;
+		args.nfs_server.export_path = c;
+
+		status = nfs_try_mount(&args, mntfh);
+		if (status)
+			return -EINVAL;
+
+		/*
+		 * Translate to nfs_mount_data, which nfs_fill_super
+		 * can deal with.
+		 */
+		data->version		= 6;
+		data->flags		= args.flags;
+		data->rsize		= args.rsize;
+		data->wsize		= args.wsize;
+		data->timeo		= args.timeo;
+		data->retrans		= args.retrans;
+		data->acregmin		= args.acregmin;
+		data->acregmax		= args.acregmax;
+		data->acdirmin		= args.acdirmin;
+		data->acdirmax		= args.acdirmax;
+		data->addr		= args.nfs_server.address;
+		data->namlen		= args.namlen;
+		data->bsize		= args.bsize;
+		data->pseudoflavor	= args.auth_flavors[0];
+
+		break;
+		}
 	}
 
-	/* Set the pseudoflavor */
 	if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
 		data->pseudoflavor = RPC_AUTH_UNIX;
 
 #ifndef CONFIG_NFS_V3
-	/* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
-	if (data->flags & NFS_MOUNT_VER3) {
-		dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
-		return -EPROTONOSUPPORT;
-	}
-#endif /* CONFIG_NFS_V3 */
-
-	/* We now require that the mount process passes the remote address */
-	if (data->addr.sin_addr.s_addr == INADDR_ANY) {
-		dprintk("%s: mount program didn't pass remote address!\n",
-			__FUNCTION__);
-		return -EINVAL;
-	}
-
-	/* Prepare the root filehandle */
 	if (data->flags & NFS_MOUNT_VER3)
-		mntfh->size = data->root.size;
-	else
-		mntfh->size = NFS2_FHSIZE;
+		goto out_v3_not_compiled;
+#endif /* !CONFIG_NFS_V3 */
 
-	if (mntfh->size > sizeof(mntfh->data)) {
-		dprintk("%s: invalid root filehandle\n", __FUNCTION__);
-		return -EINVAL;
-	}
-
-	memcpy(mntfh->data, data->root.data, mntfh->size);
-	if (mntfh->size < sizeof(mntfh->data))
-		memset(mntfh->data + mntfh->size, 0,
-		       sizeof(mntfh->data) - mntfh->size);
+	if (!nfs_verify_server_address((struct sockaddr *) &data->addr))
+		goto out_no_address;
 
 	return 0;
+
+out_no_data:
+	dfprintk(MOUNT, "NFS: mount program didn't pass any mount data\n");
+	return -EINVAL;
+
+out_no_v3:
+	dfprintk(MOUNT, "NFS: nfs_mount_data version %d does not support v3\n",
+		 data->version);
+	return -EINVAL;
+
+out_no_sec:
+	dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n");
+	return -EINVAL;
+
+#ifndef CONFIG_NFS_V3
+out_v3_not_compiled:
+	dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n");
+	return -EPROTONOSUPPORT;
+#endif /* !CONFIG_NFS_V3 */
+
+out_no_address:
+	dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
+	return -EINVAL;
+
+out_invalid_fh:
+	dfprintk(MOUNT, "NFS: invalid root filehandle\n");
+	return -EINVAL;
 }
 
 /*
@@ -600,13 +1319,51 @@
 {
 	struct nfs_server *server = data, *old = NFS_SB(sb);
 
-	if (old->nfs_client != server->nfs_client)
+	if (memcmp(&old->nfs_client->cl_addr,
+				&server->nfs_client->cl_addr,
+				sizeof(old->nfs_client->cl_addr)) != 0)
+		return 0;
+	/* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
+	if (old->flags & NFS_MOUNT_UNSHARED)
 		return 0;
 	if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
 		return 0;
 	return 1;
 }
 
+#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)
+
+static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
+{
+	const struct nfs_server *a = s->s_fs_info;
+	const struct rpc_clnt *clnt_a = a->client;
+	const struct rpc_clnt *clnt_b = b->client;
+
+	if ((s->s_flags & NFS_MS_MASK) != (flags & NFS_MS_MASK))
+		goto Ebusy;
+	if (a->nfs_client != b->nfs_client)
+		goto Ebusy;
+	if (a->flags != b->flags)
+		goto Ebusy;
+	if (a->wsize != b->wsize)
+		goto Ebusy;
+	if (a->rsize != b->rsize)
+		goto Ebusy;
+	if (a->acregmin != b->acregmin)
+		goto Ebusy;
+	if (a->acregmax != b->acregmax)
+		goto Ebusy;
+	if (a->acdirmin != b->acdirmin)
+		goto Ebusy;
+	if (a->acdirmax != b->acdirmax)
+		goto Ebusy;
+	if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
+		goto Ebusy;
+	return 0;
+Ebusy:
+	return -EBUSY;
+}
+
 static int nfs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
 {
@@ -615,30 +1372,37 @@
 	struct nfs_fh mntfh;
 	struct nfs_mount_data *data = raw_data;
 	struct dentry *mntroot;
+	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
 	int error;
 
 	/* Validate the mount data */
-	error = nfs_validate_mount_data(data, &mntfh);
+	error = nfs_validate_mount_data(&data, &mntfh, dev_name);
 	if (error < 0)
-		return error;
+		goto out;
 
 	/* Get a volume representation */
 	server = nfs_create_server(data, &mntfh);
 	if (IS_ERR(server)) {
 		error = PTR_ERR(server);
-		goto out_err_noserver;
+		goto out;
 	}
 
+	if (server->flags & NFS_MOUNT_UNSHARED)
+		compare_super = NULL;
+
 	/* Get a superblock - note that we may end up sharing one that already exists */
-	s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+	s = sget(fs_type, compare_super, nfs_set_super, server);
 	if (IS_ERR(s)) {
 		error = PTR_ERR(s);
 		goto out_err_nosb;
 	}
 
 	if (s->s_fs_info != server) {
+		error = nfs_compare_mount_options(s, server, flags);
 		nfs_free_server(server);
 		server = NULL;
+		if (error < 0)
+			goto error_splat_super;
 	}
 
 	if (!s->s_root) {
@@ -656,17 +1420,21 @@
 	s->s_flags |= MS_ACTIVE;
 	mnt->mnt_sb = s;
 	mnt->mnt_root = mntroot;
-	return 0;
+	error = 0;
+
+out:
+	if (data != raw_data)
+		kfree(data);
+	return error;
 
 out_err_nosb:
 	nfs_free_server(server);
-out_err_noserver:
-	return error;
+	goto out;
 
 error_splat_super:
 	up_write(&s->s_umount);
 	deactivate_super(s);
-	return error;
+	goto out;
 }
 
 /*
@@ -691,6 +1459,7 @@
 	struct super_block *s;
 	struct nfs_server *server;
 	struct dentry *mntroot;
+	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
 	int error;
 
 	dprintk("--> nfs_xdev_get_sb()\n");
@@ -702,16 +1471,22 @@
 		goto out_err_noserver;
 	}
 
+	if (server->flags & NFS_MOUNT_UNSHARED)
+		compare_super = NULL;
+
 	/* Get a superblock - note that we may end up sharing one that already exists */
-	s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+	s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
 	if (IS_ERR(s)) {
 		error = PTR_ERR(s);
 		goto out_err_nosb;
 	}
 
 	if (s->s_fs_info != server) {
+		error = nfs_compare_mount_options(s, server, flags);
 		nfs_free_server(server);
 		server = NULL;
+		if (error < 0)
+			goto error_splat_super;
 	}
 
 	if (!s->s_root) {
@@ -772,25 +1547,164 @@
 	nfs_initialise_sb(sb);
 }
 
-static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
+/*
+ * Validate NFSv4 mount options
+ */
+static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
+				    const char *dev_name,
+				    struct sockaddr_in *addr,
+				    rpc_authflavor_t *authflavour,
+				    char **hostname,
+				    char **mntpath,
+				    char **ip_addr)
 {
-	void *p = NULL;
+	struct nfs4_mount_data *data = *options;
+	char *c;
 
-	if (!src->len)
-		return ERR_PTR(-EINVAL);
-	if (src->len < maxlen)
-		maxlen = src->len;
-	if (dst == NULL) {
-		p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
-		if (p == NULL)
-			return ERR_PTR(-ENOMEM);
+	if (data == NULL)
+		goto out_no_data;
+
+	switch (data->version) {
+	case 1:
+		if (data->host_addrlen != sizeof(*addr))
+			goto out_no_address;
+		if (copy_from_user(addr, data->host_addr, sizeof(*addr)))
+			return -EFAULT;
+		if (addr->sin_port == 0)
+			addr->sin_port = htons(NFS_PORT);
+		if (!nfs_verify_server_address((struct sockaddr *) addr))
+			goto out_no_address;
+
+		switch (data->auth_flavourlen) {
+		case 0:
+			*authflavour = RPC_AUTH_UNIX;
+			break;
+		case 1:
+			if (copy_from_user(authflavour, data->auth_flavours,
+					   sizeof(*authflavour)))
+				return -EFAULT;
+			break;
+		default:
+			goto out_inval_auth;
+		}
+
+		c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
+		if (IS_ERR(c))
+			return PTR_ERR(c);
+		*hostname = c;
+
+		c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
+		if (IS_ERR(c))
+			return PTR_ERR(c);
+		*mntpath = c;
+		dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath);
+
+		c = strndup_user(data->client_addr.data, 16);
+		if (IS_ERR(c))
+			return PTR_ERR(c);
+		*ip_addr = c;
+
+		break;
+	default: {
+		unsigned int len;
+		struct nfs_parsed_mount_data args = {
+			.rsize		= NFS_MAX_FILE_IO_SIZE,
+			.wsize		= NFS_MAX_FILE_IO_SIZE,
+			.timeo		= 600,
+			.retrans	= 2,
+			.acregmin	= 3,
+			.acregmax	= 60,
+			.acdirmin	= 30,
+			.acdirmax	= 60,
+			.nfs_server.protocol = IPPROTO_TCP,
+		};
+
+		if (nfs_parse_mount_options((char *) *options, &args) == 0)
+			return -EINVAL;
+
+		if (!nfs_verify_server_address((struct sockaddr *)
+						&args.nfs_server.address))
+			return -EINVAL;
+		*addr = args.nfs_server.address;
+
+		switch (args.auth_flavor_len) {
+		case 0:
+			*authflavour = RPC_AUTH_UNIX;
+			break;
+		case 1:
+			*authflavour = (rpc_authflavor_t) args.auth_flavors[0];
+			break;
+		default:
+			goto out_inval_auth;
+		}
+
+		/*
+		 * Translate to nfs4_mount_data, which nfs4_fill_super
+		 * can deal with.
+		 */
+		data = kzalloc(sizeof(*data), GFP_KERNEL);
+		if (data == NULL)
+			return -ENOMEM;
+		*options = data;
+
+		data->version	= 1;
+		data->flags	= args.flags & NFS4_MOUNT_FLAGMASK;
+		data->rsize	= args.rsize;
+		data->wsize	= args.wsize;
+		data->timeo	= args.timeo;
+		data->retrans	= args.retrans;
+		data->acregmin	= args.acregmin;
+		data->acregmax	= args.acregmax;
+		data->acdirmin	= args.acdirmin;
+		data->acdirmax	= args.acdirmax;
+		data->proto	= args.nfs_server.protocol;
+
+		/*
+		 * Split "dev_name" into "hostname:mntpath".
+		 */
+		c = strchr(dev_name, ':');
+		if (c == NULL)
+			return -EINVAL;
+		/* while calculating len, pretend ':' is '\0' */
+		len = c - dev_name;
+		if (len > NFS4_MAXNAMLEN)
+			return -EINVAL;
+		*hostname = kzalloc(len, GFP_KERNEL);
+		if (*hostname == NULL)
+			return -ENOMEM;
+		strncpy(*hostname, dev_name, len - 1);
+
+		c++;			/* step over the ':' */
+		len = strlen(c);
+		if (len > NFS4_MAXPATHLEN)
+			return -EINVAL;
+		*mntpath = kzalloc(len + 1, GFP_KERNEL);
+		if (*mntpath == NULL)
+			return -ENOMEM;
+		strncpy(*mntpath, c, len);
+
+		dprintk("MNTPATH: %s\n", *mntpath);
+
+		*ip_addr = args.client_address;
+
+		break;
+		}
 	}
-	if (copy_from_user(dst, src->data, maxlen)) {
-		kfree(p);
-		return ERR_PTR(-EFAULT);
-	}
-	dst[maxlen] = '\0';
-	return dst;
+
+	return 0;
+
+out_no_data:
+	dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
+	return -EINVAL;
+
+out_inval_auth:
+	dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
+		 data->auth_flavourlen);
+	return -EINVAL;
+
+out_no_address:
+	dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
+	return -EINVAL;
 }
 
 /*
@@ -806,81 +1720,29 @@
 	rpc_authflavor_t authflavour;
 	struct nfs_fh mntfh;
 	struct dentry *mntroot;
-	char *mntpath = NULL, *hostname = NULL, ip_addr[16];
-	void *p;
+	char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
+	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
 	int error;
 
-	if (data == NULL) {
-		dprintk("%s: missing data argument\n", __FUNCTION__);
-		return -EINVAL;
-	}
-	if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
-		dprintk("%s: bad mount version\n", __FUNCTION__);
-		return -EINVAL;
-	}
-
-	/* We now require that the mount process passes the remote address */
-	if (data->host_addrlen != sizeof(addr))
-		return -EINVAL;
-
-	if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
-		return -EFAULT;
-
-	if (addr.sin_family != AF_INET ||
-	    addr.sin_addr.s_addr == INADDR_ANY
-	    ) {
-		dprintk("%s: mount program didn't pass remote IP address!\n",
-				__FUNCTION__);
-		return -EINVAL;
-	}
-	/* RFC3530: The default port for NFS is 2049 */
-	if (addr.sin_port == 0)
-		addr.sin_port = htons(NFS_PORT);
-
-	/* Grab the authentication type */
-	authflavour = RPC_AUTH_UNIX;
-	if (data->auth_flavourlen != 0) {
-		if (data->auth_flavourlen != 1) {
-			dprintk("%s: Invalid number of RPC auth flavours %d.\n",
-					__FUNCTION__, data->auth_flavourlen);
-			error = -EINVAL;
-			goto out_err_noserver;
-		}
-
-		if (copy_from_user(&authflavour, data->auth_flavours,
-				   sizeof(authflavour))) {
-			error = -EFAULT;
-			goto out_err_noserver;
-		}
-	}
-
-	p = nfs_copy_user_string(NULL, &data->hostname, 256);
-	if (IS_ERR(p))
-		goto out_err;
-	hostname = p;
-
-	p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
-	if (IS_ERR(p))
-		goto out_err;
-	mntpath = p;
-
-	dprintk("MNTPATH: %s\n", mntpath);
-
-	p = nfs_copy_user_string(ip_addr, &data->client_addr,
-				 sizeof(ip_addr) - 1);
-	if (IS_ERR(p))
-		goto out_err;
+	/* Validate the mount data */
+	error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour,
+					 &hostname, &mntpath, &ip_addr);
+	if (error < 0)
+		goto out;
 
 	/* Get a volume representation */
 	server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
 				    authflavour, &mntfh);
 	if (IS_ERR(server)) {
 		error = PTR_ERR(server);
-		goto out_err_noserver;
+		goto out;
 	}
 
+	if (server->flags & NFS4_MOUNT_UNSHARED)
+		compare_super = NULL;
+
 	/* Get a superblock - note that we may end up sharing one that already exists */
-	s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+	s = sget(fs_type, compare_super, nfs_set_super, server);
 	if (IS_ERR(s)) {
 		error = PTR_ERR(s);
 		goto out_free;
@@ -906,25 +1768,22 @@
 	s->s_flags |= MS_ACTIVE;
 	mnt->mnt_sb = s;
 	mnt->mnt_root = mntroot;
-	kfree(mntpath);
-	kfree(hostname);
-	return 0;
+	error = 0;
 
-out_err:
-	error = PTR_ERR(p);
-	goto out_err_noserver;
-
-out_free:
-	nfs_free_server(server);
-out_err_noserver:
+out:
+	kfree(ip_addr);
 	kfree(mntpath);
 	kfree(hostname);
 	return error;
 
+out_free:
+	nfs_free_server(server);
+	goto out;
+
 error_splat_super:
 	up_write(&s->s_umount);
 	deactivate_super(s);
-	goto out_err_noserver;
+	goto out;
 }
 
 static void nfs4_kill_super(struct super_block *sb)
@@ -949,6 +1808,7 @@
 	struct super_block *s;
 	struct nfs_server *server;
 	struct dentry *mntroot;
+	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
 	int error;
 
 	dprintk("--> nfs4_xdev_get_sb()\n");
@@ -960,8 +1820,11 @@
 		goto out_err_noserver;
 	}
 
+	if (server->flags & NFS4_MOUNT_UNSHARED)
+		compare_super = NULL;
+
 	/* Get a superblock - note that we may end up sharing one that already exists */
-	s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+	s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
 	if (IS_ERR(s)) {
 		error = PTR_ERR(s);
 		goto out_err_nosb;
@@ -1016,6 +1879,7 @@
 	struct nfs_server *server;
 	struct dentry *mntroot;
 	struct nfs_fh mntfh;
+	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
 	int error;
 
 	dprintk("--> nfs4_referral_get_sb()\n");
@@ -1027,8 +1891,11 @@
 		goto out_err_noserver;
 	}
 
+	if (server->flags & NFS4_MOUNT_UNSHARED)
+		compare_super = NULL;
+
 	/* Get a superblock - note that we may end up sharing one that already exists */
-	s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+	s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
 	if (IS_ERR(s)) {
 		error = PTR_ERR(s);
 		goto out_err_nosb;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index b084c03..73ac992 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -117,19 +117,19 @@
 	if (PagePrivate(page)) {
 		req = (struct nfs_page *)page_private(page);
 		if (req != NULL)
-			atomic_inc(&req->wb_count);
+			kref_get(&req->wb_kref);
 	}
 	return req;
 }
 
 static struct nfs_page *nfs_page_find_request(struct page *page)
 {
+	struct inode *inode = page->mapping->host;
 	struct nfs_page *req = NULL;
-	spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
 
-	spin_lock(req_lock);
+	spin_lock(&inode->i_lock);
 	req = nfs_page_find_request_locked(page);
-	spin_unlock(req_lock);
+	spin_unlock(&inode->i_lock);
 	return req;
 }
 
@@ -191,8 +191,6 @@
 	}
 	/* Update file length */
 	nfs_grow_file(page, offset, count);
-	/* Set the PG_uptodate flag? */
-	nfs_mark_uptodate(page, offset, count);
 	nfs_unlock_request(req);
 	return 0;
 }
@@ -253,16 +251,16 @@
 static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
 				struct page *page)
 {
+	struct inode *inode = page->mapping->host;
+	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_page *req;
-	struct nfs_inode *nfsi = NFS_I(page->mapping->host);
-	spinlock_t *req_lock = &nfsi->req_lock;
 	int ret;
 
-	spin_lock(req_lock);
+	spin_lock(&inode->i_lock);
 	for(;;) {
 		req = nfs_page_find_request_locked(page);
 		if (req == NULL) {
-			spin_unlock(req_lock);
+			spin_unlock(&inode->i_lock);
 			return 1;
 		}
 		if (nfs_lock_request_dontget(req))
@@ -272,30 +270,28 @@
 		 *	 succeed provided that someone hasn't already marked the
 		 *	 request as dirty (in which case we don't care).
 		 */
-		spin_unlock(req_lock);
-		/* Prevent deadlock! */
-		nfs_pageio_complete(pgio);
+		spin_unlock(&inode->i_lock);
 		ret = nfs_wait_on_request(req);
 		nfs_release_request(req);
 		if (ret != 0)
 			return ret;
-		spin_lock(req_lock);
+		spin_lock(&inode->i_lock);
 	}
 	if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) {
 		/* This request is marked for commit */
-		spin_unlock(req_lock);
+		spin_unlock(&inode->i_lock);
 		nfs_unlock_request(req);
 		nfs_pageio_complete(pgio);
 		return 1;
 	}
 	if (nfs_set_page_writeback(page) != 0) {
-		spin_unlock(req_lock);
+		spin_unlock(&inode->i_lock);
 		BUG();
 	}
 	radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
-			NFS_PAGE_TAG_WRITEBACK);
+			NFS_PAGE_TAG_LOCKED);
 	ret = test_bit(PG_NEED_FLUSH, &req->wb_flags);
-	spin_unlock(req_lock);
+	spin_unlock(&inode->i_lock);
 	nfs_pageio_add_request(pgio, req);
 	return ret;
 }
@@ -321,6 +317,8 @@
 		pgio = &mypgio;
 	}
 
+	nfs_pageio_cond_complete(pgio, page->index);
+
 	err = nfs_page_async_flush(pgio, page);
 	if (err <= 0)
 		goto out;
@@ -329,6 +327,8 @@
 	if (!offset)
 		goto out;
 
+	nfs_pageio_cond_complete(pgio, page->index);
+
 	ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE);
 	if (ctx == NULL) {
 		err = -EBADF;
@@ -398,7 +398,7 @@
 	if (PageDirty(req->wb_page))
 		set_bit(PG_NEED_FLUSH, &req->wb_flags);
 	nfsi->npages++;
-	atomic_inc(&req->wb_count);
+	kref_get(&req->wb_kref);
 	return 0;
 }
 
@@ -407,12 +407,12 @@
  */
 static void nfs_inode_remove_request(struct nfs_page *req)
 {
-	struct inode *inode = req->wb_context->dentry->d_inode;
+	struct inode *inode = req->wb_context->path.dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
 	BUG_ON (!NFS_WBACK_BUSY(req));
 
-	spin_lock(&nfsi->req_lock);
+	spin_lock(&inode->i_lock);
 	set_page_private(req->wb_page, 0);
 	ClearPagePrivate(req->wb_page);
 	radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
@@ -420,11 +420,11 @@
 		__set_page_dirty_nobuffers(req->wb_page);
 	nfsi->npages--;
 	if (!nfsi->npages) {
-		spin_unlock(&nfsi->req_lock);
+		spin_unlock(&inode->i_lock);
 		nfs_end_data_update(inode);
 		iput(inode);
 	} else
-		spin_unlock(&nfsi->req_lock);
+		spin_unlock(&inode->i_lock);
 	nfs_clear_request(req);
 	nfs_release_request(req);
 }
@@ -455,14 +455,16 @@
 static void
 nfs_mark_request_commit(struct nfs_page *req)
 {
-	struct inode *inode = req->wb_context->dentry->d_inode;
+	struct inode *inode = req->wb_context->path.dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	spin_lock(&nfsi->req_lock);
-	nfs_list_add_request(req, &nfsi->commit);
+	spin_lock(&inode->i_lock);
 	nfsi->ncommit++;
 	set_bit(PG_NEED_COMMIT, &(req)->wb_flags);
-	spin_unlock(&nfsi->req_lock);
+	radix_tree_tag_set(&nfsi->nfs_page_tree,
+			req->wb_index,
+			NFS_PAGE_TAG_COMMIT);
+	spin_unlock(&inode->i_lock);
 	inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
 	__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
 }
@@ -524,18 +526,18 @@
 		idx_end = idx_start + npages - 1;
 
 	next = idx_start;
-	while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
+	while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_LOCKED)) {
 		if (req->wb_index > idx_end)
 			break;
 
 		next = req->wb_index + 1;
 		BUG_ON(!NFS_WBACK_BUSY(req));
 
-		atomic_inc(&req->wb_count);
-		spin_unlock(&nfsi->req_lock);
+		kref_get(&req->wb_kref);
+		spin_unlock(&inode->i_lock);
 		error = nfs_wait_on_request(req);
 		nfs_release_request(req);
-		spin_lock(&nfsi->req_lock);
+		spin_lock(&inode->i_lock);
 		if (error < 0)
 			return error;
 		res++;
@@ -575,10 +577,9 @@
 	int res = 0;
 
 	if (nfsi->ncommit != 0) {
-		res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages);
+		res = nfs_scan_list(nfsi, dst, idx_start, npages,
+				NFS_PAGE_TAG_COMMIT);
 		nfsi->ncommit -= res;
-		if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
-			printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
 	}
 	return res;
 }
@@ -601,7 +602,6 @@
 {
 	struct address_space *mapping = page->mapping;
 	struct inode *inode = mapping->host;
-	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_page		*req, *new = NULL;
 	pgoff_t		rqend, end;
 
@@ -611,13 +611,13 @@
 		/* Loop over all inode entries and see if we find
 		 * A request for the page we wish to update
 		 */
-		spin_lock(&nfsi->req_lock);
+		spin_lock(&inode->i_lock);
 		req = nfs_page_find_request_locked(page);
 		if (req) {
 			if (!nfs_lock_request_dontget(req)) {
 				int error;
 
-				spin_unlock(&nfsi->req_lock);
+				spin_unlock(&inode->i_lock);
 				error = nfs_wait_on_request(req);
 				nfs_release_request(req);
 				if (error < 0) {
@@ -627,7 +627,7 @@
 				}
 				continue;
 			}
-			spin_unlock(&nfsi->req_lock);
+			spin_unlock(&inode->i_lock);
 			if (new)
 				nfs_release_request(new);
 			break;
@@ -638,14 +638,14 @@
 			nfs_lock_request_dontget(new);
 			error = nfs_inode_add_request(inode, new);
 			if (error) {
-				spin_unlock(&nfsi->req_lock);
+				spin_unlock(&inode->i_lock);
 				nfs_unlock_request(new);
 				return ERR_PTR(error);
 			}
-			spin_unlock(&nfsi->req_lock);
+			spin_unlock(&inode->i_lock);
 			return new;
 		}
-		spin_unlock(&nfsi->req_lock);
+		spin_unlock(&inode->i_lock);
 
 		new = nfs_create_request(ctx, inode, page, offset, bytes);
 		if (IS_ERR(new))
@@ -749,12 +749,17 @@
 static void nfs_writepage_release(struct nfs_page *req)
 {
 
-	if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) {
+	if (PageError(req->wb_page)) {
+		nfs_end_page_writeback(req->wb_page);
+		nfs_inode_remove_request(req);
+	} else if (!nfs_reschedule_unstable_write(req)) {
+		/* Set the PG_uptodate flag */
+		nfs_mark_uptodate(req->wb_page, req->wb_pgbase, req->wb_bytes);
 		nfs_end_page_writeback(req->wb_page);
 		nfs_inode_remove_request(req);
 	} else
 		nfs_end_page_writeback(req->wb_page);
-	nfs_clear_page_writeback(req);
+	nfs_clear_page_tag_locked(req);
 }
 
 static inline int flush_task_priority(int how)
@@ -784,7 +789,7 @@
 	 * NB: take care not to mess about with data->commit et al. */
 
 	data->req = req;
-	data->inode = inode = req->wb_context->dentry->d_inode;
+	data->inode = inode = req->wb_context->path.dentry->d_inode;
 	data->cred = req->wb_context->cred;
 
 	data->args.fh     = NFS_FH(inode);
@@ -883,7 +888,7 @@
 	}
 	nfs_redirty_request(req);
 	nfs_end_page_writeback(req->wb_page);
-	nfs_clear_page_writeback(req);
+	nfs_clear_page_tag_locked(req);
 	return -ENOMEM;
 }
 
@@ -926,7 +931,7 @@
 		nfs_list_remove_request(req);
 		nfs_redirty_request(req);
 		nfs_end_page_writeback(req->wb_page);
-		nfs_clear_page_writeback(req);
+		nfs_clear_page_tag_locked(req);
 	}
 	return -ENOMEM;
 }
@@ -952,8 +957,8 @@
 	struct page		*page = req->wb_page;
 
 	dprintk("NFS: write (%s/%Ld %d@%Ld)",
-		req->wb_context->dentry->d_inode->i_sb->s_id,
-		(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+		req->wb_context->path.dentry->d_inode->i_sb->s_id,
+		(long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
 		req->wb_bytes,
 		(long long)req_offset(req));
 
@@ -968,9 +973,9 @@
 	}
 
 	if (nfs_write_need_commit(data)) {
-		spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
+		struct inode *inode = page->mapping->host;
 
-		spin_lock(req_lock);
+		spin_lock(&inode->i_lock);
 		if (test_bit(PG_NEED_RESCHED, &req->wb_flags)) {
 			/* Do nothing we need to resend the writes */
 		} else if (!test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags)) {
@@ -981,7 +986,7 @@
 			clear_bit(PG_NEED_COMMIT, &req->wb_flags);
 			dprintk(" server reboot detected\n");
 		}
-		spin_unlock(req_lock);
+		spin_unlock(&inode->i_lock);
 	} else
 		dprintk(" OK\n");
 
@@ -1018,8 +1023,8 @@
 		page = req->wb_page;
 
 		dprintk("NFS: write (%s/%Ld %d@%Ld)",
-			req->wb_context->dentry->d_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+			req->wb_context->path.dentry->d_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 
@@ -1037,12 +1042,14 @@
 			dprintk(" marked for commit\n");
 			goto next;
 		}
+		/* Set the PG_uptodate flag? */
+		nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
 		dprintk(" OK\n");
 remove_request:
 		nfs_end_page_writeback(page);
 		nfs_inode_remove_request(req);
 	next:
-		nfs_clear_page_writeback(req);
+		nfs_clear_page_tag_locked(req);
 	}
 }
 
@@ -1155,7 +1162,7 @@
 
 	list_splice_init(head, &data->pages);
 	first = nfs_list_entry(data->pages.next);
-	inode = first->wb_context->dentry->d_inode;
+	inode = first->wb_context->path.dentry->d_inode;
 
 	data->inode	  = inode;
 	data->cred	  = first->wb_context->cred;
@@ -1205,7 +1212,7 @@
 		nfs_list_remove_request(req);
 		nfs_mark_request_commit(req);
 		dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-		nfs_clear_page_writeback(req);
+		nfs_clear_page_tag_locked(req);
 	}
 	return -ENOMEM;
 }
@@ -1232,8 +1239,8 @@
 		dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
 
 		dprintk("NFS: commit (%s/%Ld %d@%Ld)",
-			req->wb_context->dentry->d_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+			req->wb_context->path.dentry->d_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 		if (task->tk_status < 0) {
@@ -1247,6 +1254,9 @@
 		 * returned by the server against all stored verfs. */
 		if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) {
 			/* We have a match */
+			/* Set the PG_uptodate flag */
+			nfs_mark_uptodate(req->wb_page, req->wb_pgbase,
+					req->wb_bytes);
 			nfs_inode_remove_request(req);
 			dprintk(" OK\n");
 			goto next;
@@ -1255,7 +1265,7 @@
 		dprintk(" mismatch\n");
 		nfs_redirty_request(req);
 	next:
-		nfs_clear_page_writeback(req);
+		nfs_clear_page_tag_locked(req);
 	}
 }
 
@@ -1266,13 +1276,12 @@
 
 int nfs_commit_inode(struct inode *inode, int how)
 {
-	struct nfs_inode *nfsi = NFS_I(inode);
 	LIST_HEAD(head);
 	int res;
 
-	spin_lock(&nfsi->req_lock);
+	spin_lock(&inode->i_lock);
 	res = nfs_scan_commit(inode, &head, 0, 0);
-	spin_unlock(&nfsi->req_lock);
+	spin_unlock(&inode->i_lock);
 	if (res) {
 		int error = nfs_commit_list(inode, &head, how);
 		if (error < 0)
@@ -1290,7 +1299,6 @@
 long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how)
 {
 	struct inode *inode = mapping->host;
-	struct nfs_inode *nfsi = NFS_I(inode);
 	pgoff_t idx_start, idx_end;
 	unsigned int npages = 0;
 	LIST_HEAD(head);
@@ -1312,7 +1320,7 @@
 		}
 	}
 	how &= ~FLUSH_NOCOMMIT;
-	spin_lock(&nfsi->req_lock);
+	spin_lock(&inode->i_lock);
 	do {
 		ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
 		if (ret != 0)
@@ -1323,18 +1331,19 @@
 		if (pages == 0)
 			break;
 		if (how & FLUSH_INVALIDATE) {
-			spin_unlock(&nfsi->req_lock);
+			spin_unlock(&inode->i_lock);
 			nfs_cancel_commit_list(&head);
 			ret = pages;
-			spin_lock(&nfsi->req_lock);
+			spin_lock(&inode->i_lock);
 			continue;
 		}
 		pages += nfs_scan_commit(inode, &head, 0, 0);
-		spin_unlock(&nfsi->req_lock);
+		spin_unlock(&inode->i_lock);
 		ret = nfs_commit_list(inode, &head, how);
-		spin_lock(&nfsi->req_lock);
+		spin_lock(&inode->i_lock);
+
 	} while (ret >= 0);
-	spin_unlock(&nfsi->req_lock);
+	spin_unlock(&inode->i_lock);
 	return ret;
 }
 
@@ -1428,7 +1437,6 @@
 {
 	struct address_space *mapping = page->mapping;
 	struct inode *inode;
-	spinlock_t *req_lock;
 	struct nfs_page *req;
 	int ret;
 
@@ -1437,18 +1445,17 @@
 	inode = mapping->host;
 	if (!inode)
 		goto out_raced;
-	req_lock = &NFS_I(inode)->req_lock;
-	spin_lock(req_lock);
+	spin_lock(&inode->i_lock);
 	req = nfs_page_find_request_locked(page);
 	if (req != NULL) {
 		/* Mark any existing write requests for flushing */
 		ret = !test_and_set_bit(PG_NEED_FLUSH, &req->wb_flags);
-		spin_unlock(req_lock);
+		spin_unlock(&inode->i_lock);
 		nfs_release_request(req);
 		return ret;
 	}
 	ret = __set_page_dirty_nobuffers(page);
-	spin_unlock(req_lock);
+	spin_unlock(&inode->i_lock);
 	return ret;
 out_raced:
 	return !TestSetPageDirty(page);
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 6e92b0f..cf61dc8 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -12,17 +12,31 @@
 
 #define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
 
+static int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
+{
+	struct exp_flavor_info *f;
+	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+	for (f = exp->ex_flavors; f < end; f++) {
+		if (f->pseudoflavor == rqstp->rq_flavor)
+			return f->flags;
+	}
+	return exp->ex_flags;
+
+}
+
 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
 	struct svc_cred	cred = rqstp->rq_cred;
 	int i;
+	int flags = nfsexp_flags(rqstp, exp);
 	int ret;
 
-	if (exp->ex_flags & NFSEXP_ALLSQUASH) {
+	if (flags & NFSEXP_ALLSQUASH) {
 		cred.cr_uid = exp->ex_anon_uid;
 		cred.cr_gid = exp->ex_anon_gid;
 		cred.cr_group_info = groups_alloc(0);
-	} else if (exp->ex_flags & NFSEXP_ROOTSQUASH) {
+	} else if (flags & NFSEXP_ROOTSQUASH) {
 		struct group_info *gi;
 		if (!cred.cr_uid)
 			cred.cr_uid = exp->ex_anon_uid;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 79bd03b..c7bbf46 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -26,12 +26,15 @@
 #include <linux/mount.h>
 #include <linux/hash.h>
 #include <linux/module.h>
+#include <linux/exportfs.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/nfsfh.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/lockd/bind.h>
+#include <linux/sunrpc/msg_prot.h>
+#include <linux/sunrpc/gss_api.h>
 
 #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
 
@@ -451,8 +454,48 @@
 	return err;
 }
 
+static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
+{
+	int listsize, err;
+	struct exp_flavor_info *f;
+
+	err = get_int(mesg, &listsize);
+	if (err)
+		return err;
+	if (listsize < 0 || listsize > MAX_SECINFO_LIST)
+		return -EINVAL;
+
+	for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
+		err = get_int(mesg, &f->pseudoflavor);
+		if (err)
+			return err;
+		/*
+		 * Just a quick sanity check; we could also try to check
+		 * whether this pseudoflavor is supported, but at worst
+		 * an unsupported pseudoflavor on the export would just
+		 * be a pseudoflavor that won't match the flavor of any
+		 * authenticated request.  The administrator will
+		 * probably discover the problem when someone fails to
+		 * authenticate.
+		 */
+		if (f->pseudoflavor < 0)
+			return -EINVAL;
+		err = get_int(mesg, &f->flags);
+		if (err)
+			return err;
+		/* Only some flags are allowed to differ between flavors: */
+		if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags))
+			return -EINVAL;
+	}
+	exp->ex_nflavors = listsize;
+	return 0;
+}
+
 #else /* CONFIG_NFSD_V4 */
-static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; }
+static inline int
+fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;}
+static inline int
+secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
 #endif
 
 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
@@ -476,6 +519,9 @@
 
 	exp.ex_uuid = NULL;
 
+	/* secinfo */
+	exp.ex_nflavors = 0;
+
 	if (mesg[mlen-1] != '\n')
 		return -EINVAL;
 	mesg[mlen-1] = 0;
@@ -553,7 +599,9 @@
 					if (exp.ex_uuid == NULL)
 						err = -ENOMEM;
 				}
-			} else
+			} else if (strcmp(buf, "secinfo") == 0)
+				err = secinfo_parse(&mesg, buf, &exp);
+			else
 				/* quietly ignore unknown words and anything
 				 * following. Newer user-space can try to set
 				 * new values, then see what the result was.
@@ -593,6 +641,7 @@
 
 static void exp_flags(struct seq_file *m, int flag, int fsid,
 		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs);
+static void show_secinfo(struct seq_file *m, struct svc_export *exp);
 
 static int svc_export_show(struct seq_file *m,
 			   struct cache_detail *cd,
@@ -622,6 +671,7 @@
 				seq_printf(m, "%02x", exp->ex_uuid[i]);
 			}
 		}
+		show_secinfo(m, exp);
 	}
 	seq_puts(m, ")\n");
 	return 0;
@@ -654,6 +704,7 @@
 {
 	struct svc_export *new = container_of(cnew, struct svc_export, h);
 	struct svc_export *item = container_of(citem, struct svc_export, h);
+	int i;
 
 	new->ex_flags = item->ex_flags;
 	new->ex_anon_uid = item->ex_anon_uid;
@@ -669,6 +720,10 @@
 	item->ex_fslocs.locations_count = 0;
 	new->ex_fslocs.migrated = item->ex_fslocs.migrated;
 	item->ex_fslocs.migrated = 0;
+	new->ex_nflavors = item->ex_nflavors;
+	for (i = 0; i < MAX_SECINFO_LIST; i++) {
+		new->ex_flavors[i] = item->ex_flavors[i];
+	}
 }
 
 static struct cache_head *svc_export_alloc(void)
@@ -738,16 +793,18 @@
 	int err;
 	
 	if (!clp)
-		return NULL;
+		return ERR_PTR(-ENOENT);
 
 	key.ek_client = clp;
 	key.ek_fsidtype = fsid_type;
 	memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
 
 	ek = svc_expkey_lookup(&key);
-	if (ek != NULL)
-		if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
-			ek = ERR_PTR(err);
+	if (ek == NULL)
+		return ERR_PTR(-ENOMEM);
+	err = cache_check(&svc_expkey_cache, &ek->h, reqp);
+	if (err)
+		return ERR_PTR(err);
 	return ek;
 }
 
@@ -808,30 +865,21 @@
 		struct cache_req *reqp)
 {
 	struct svc_export *exp, key;
+	int err;
 	
 	if (!clp)
-		return NULL;
+		return ERR_PTR(-ENOENT);
 
 	key.ex_client = clp;
 	key.ex_mnt = mnt;
 	key.ex_dentry = dentry;
 
 	exp = svc_export_lookup(&key);
-	if (exp != NULL)  {
-		int err;
-
-		err = cache_check(&svc_export_cache, &exp->h, reqp);
-		switch (err) {
-		case 0: break;
-		case -EAGAIN:
-		case -ETIMEDOUT:
-			exp = ERR_PTR(err);
-			break;
-		default:
-			exp = NULL;
-		}
-	}
-
+	if (exp == NULL)
+		return ERR_PTR(-ENOMEM);
+	err = cache_check(&svc_export_cache, &exp->h, reqp);
+	if (err)
+		return ERR_PTR(err);
 	return exp;
 }
 
@@ -847,7 +895,7 @@
 	dget(dentry);
 	exp = exp_get_by_name(clp, mnt, dentry, reqp);
 
-	while (exp == NULL && !IS_ROOT(dentry)) {
+	while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
 		struct dentry *parent;
 
 		parent = dget_parent(dentry);
@@ -900,7 +948,7 @@
 		return;
 
 	ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
-	if (ek && !IS_ERR(ek)) {
+	if (!IS_ERR(ek)) {
 		ek->h.expiry_time = get_seconds()-1;
 		cache_put(&ek->h, &svc_expkey_cache);
 	}
@@ -938,7 +986,7 @@
 	struct inode *inode = exp->ex_dentry->d_inode;
 
 	ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
-	if (ek && !IS_ERR(ek)) {
+	if (!IS_ERR(ek)) {
 		ek->h.expiry_time = get_seconds()-1;
 		cache_put(&ek->h, &svc_expkey_cache);
 	}
@@ -989,13 +1037,12 @@
 
 	/* must make sure there won't be an ex_fsid clash */
 	if ((nxp->ex_flags & NFSEXP_FSID) &&
-	    (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
-	    !IS_ERR(fsid_key) &&
+	    (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
 	    fsid_key->ek_mnt &&
 	    (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
 		goto finish;
 
-	if (exp) {
+	if (!IS_ERR(exp)) {
 		/* just a flags/id/fsid update */
 
 		exp_fsid_unhash(exp);
@@ -1104,7 +1151,7 @@
 	err = -EINVAL;
 	exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
 	path_release(&nd);
-	if (!exp)
+	if (IS_ERR(exp))
 		goto out_domain;
 
 	exp_do_unexport(exp);
@@ -1149,10 +1196,6 @@
 		err = PTR_ERR(exp);
 		goto out;
 	}
-	if (!exp) {
-		dprintk("nfsd: exp_rootfh export not found.\n");
-		goto out;
-	}
 
 	/*
 	 * fh must be initialized before calling fh_compose
@@ -1176,17 +1219,130 @@
 {
 	struct svc_export *exp;
 	struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
-	if (!ek || IS_ERR(ek))
+	if (IS_ERR(ek))
 		return ERR_PTR(PTR_ERR(ek));
 
 	exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
 	cache_put(&ek->h, &svc_expkey_cache);
 
-	if (!exp || IS_ERR(exp))
+	if (IS_ERR(exp))
 		return ERR_PTR(PTR_ERR(exp));
 	return exp;
 }
 
+__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
+{
+	struct exp_flavor_info *f;
+	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+	/* legacy gss-only clients are always OK: */
+	if (exp->ex_client == rqstp->rq_gssclient)
+		return 0;
+	/* ip-address based client; check sec= export option: */
+	for (f = exp->ex_flavors; f < end; f++) {
+		if (f->pseudoflavor == rqstp->rq_flavor)
+			return 0;
+	}
+	/* defaults in absence of sec= options: */
+	if (exp->ex_nflavors == 0) {
+		if (rqstp->rq_flavor == RPC_AUTH_NULL ||
+		    rqstp->rq_flavor == RPC_AUTH_UNIX)
+			return 0;
+	}
+	return nfserr_wrongsec;
+}
+
+/*
+ * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
+ * auth_unix client) if it's available and has secinfo information;
+ * otherwise, will try to use rq_gssclient.
+ *
+ * Called from functions that handle requests; functions that do work on
+ * behalf of mountd are passed a single client name to use, and should
+ * use exp_get_by_name() or exp_find().
+ */
+struct svc_export *
+rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+		struct dentry *dentry)
+{
+	struct svc_export *gssexp, *exp = NULL;
+
+	if (rqstp->rq_client == NULL)
+		goto gss;
+
+	/* First try the auth_unix client: */
+	exp = exp_get_by_name(rqstp->rq_client, mnt, dentry,
+						&rqstp->rq_chandle);
+	if (PTR_ERR(exp) == -ENOENT)
+		goto gss;
+	if (IS_ERR(exp))
+		return exp;
+	/* If it has secinfo, assume there are no gss/... clients */
+	if (exp->ex_nflavors > 0)
+		return exp;
+gss:
+	/* Otherwise, try falling back on gss client */
+	if (rqstp->rq_gssclient == NULL)
+		return exp;
+	gssexp = exp_get_by_name(rqstp->rq_gssclient, mnt, dentry,
+						&rqstp->rq_chandle);
+	if (PTR_ERR(gssexp) == -ENOENT)
+		return exp;
+	if (exp && !IS_ERR(exp))
+		exp_put(exp);
+	return gssexp;
+}
+
+struct svc_export *
+rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
+{
+	struct svc_export *gssexp, *exp = NULL;
+
+	if (rqstp->rq_client == NULL)
+		goto gss;
+
+	/* First try the auth_unix client: */
+	exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle);
+	if (PTR_ERR(exp) == -ENOENT)
+		goto gss;
+	if (IS_ERR(exp))
+		return exp;
+	/* If it has secinfo, assume there are no gss/... clients */
+	if (exp->ex_nflavors > 0)
+		return exp;
+gss:
+	/* Otherwise, try falling back on gss client */
+	if (rqstp->rq_gssclient == NULL)
+		return exp;
+	gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv,
+						&rqstp->rq_chandle);
+	if (PTR_ERR(gssexp) == -ENOENT)
+		return exp;
+	if (exp && !IS_ERR(exp))
+		exp_put(exp);
+	return gssexp;
+}
+
+struct svc_export *
+rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
+		struct dentry *dentry)
+{
+	struct svc_export *exp;
+
+	dget(dentry);
+	exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
+
+	while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
+		struct dentry *parent;
+
+		parent = dget_parent(dentry);
+		dput(dentry);
+		dentry = parent;
+		exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
+	}
+	dput(dentry);
+	return exp;
+}
 
 /*
  * Called when we need the filehandle for the root of the pseudofs,
@@ -1194,8 +1350,7 @@
  * export point with fsid==0
  */
 __be32
-exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
-	       struct cache_req *creq)
+exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
 {
 	struct svc_export *exp;
 	__be32 rv;
@@ -1203,12 +1358,16 @@
 
 	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
 
-	exp = exp_find(clp, FSID_NUM, fsidv, creq);
+	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
+	if (PTR_ERR(exp) == -ENOENT)
+		return nfserr_perm;
 	if (IS_ERR(exp))
 		return nfserrno(PTR_ERR(exp));
-	if (exp == NULL)
-		return nfserr_perm;
 	rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
+	if (rv)
+		goto out;
+	rv = check_nfsd_access(exp, rqstp);
+out:
 	exp_put(exp);
 	return rv;
 }
@@ -1296,28 +1455,62 @@
 	{ 0, {"", ""}}
 };
 
-static void exp_flags(struct seq_file *m, int flag, int fsid,
-		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
+static void show_expflags(struct seq_file *m, int flags, int mask)
 {
-	int first = 0;
 	struct flags *flg;
+	int state, first = 0;
 
 	for (flg = expflags; flg->flag; flg++) {
-		int state = (flg->flag & flag)?0:1;
+		if (flg->flag & ~mask)
+			continue;
+		state = (flg->flag & flags) ? 0 : 1;
 		if (*flg->name[state])
 			seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
 	}
+}
+
+static void show_secinfo_flags(struct seq_file *m, int flags)
+{
+	seq_printf(m, ",");
+	show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
+}
+
+static void show_secinfo(struct seq_file *m, struct svc_export *exp)
+{
+	struct exp_flavor_info *f;
+	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+	int lastflags = 0, first = 0;
+
+	if (exp->ex_nflavors == 0)
+		return;
+	for (f = exp->ex_flavors; f < end; f++) {
+		if (first || f->flags != lastflags) {
+			if (!first)
+				show_secinfo_flags(m, lastflags);
+			seq_printf(m, ",sec=%d", f->pseudoflavor);
+			lastflags = f->flags;
+		} else {
+			seq_printf(m, ":%d", f->pseudoflavor);
+		}
+	}
+	show_secinfo_flags(m, lastflags);
+}
+
+static void exp_flags(struct seq_file *m, int flag, int fsid,
+		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
+{
+	show_expflags(m, flag, NFSEXP_ALLFLAGS);
 	if (flag & NFSEXP_FSID)
-		seq_printf(m, "%sfsid=%d", first++?",":"", fsid);
+		seq_printf(m, ",fsid=%d", fsid);
 	if (anonu != (uid_t)-2 && anonu != (0x10000-2))
-		seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
+		seq_printf(m, ",sanonuid=%d", anonu);
 	if (anong != (gid_t)-2 && anong != (0x10000-2))
-		seq_printf(m, "%sanongid=%d", first++?",":"", anong);
+		seq_printf(m, ",sanongid=%d", anong);
 	if (fsloc && fsloc->locations_count > 0) {
 		char *loctype = (fsloc->migrated) ? "refer" : "replicas";
 		int i;
 
-		seq_printf(m, "%s%s=", first++?",":"", loctype);
+		seq_printf(m, ",%s=", loctype);
 		seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
 		seq_putc(m, '@');
 		seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 221acd1..9e4a568 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -65,6 +65,7 @@
 static struct nlmsvc_binding	nfsd_nlm_ops = {
 	.fopen		= nlm_fopen,		/* open file for locking */
 	.fclose		= nlm_fclose,		/* close file */
+	.get_grace_period = get_nfs4_grace_period,
 };
 
 void
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index cc3b7ba..b6ed383 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -183,8 +183,13 @@
 summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
 {
 	struct posix_acl_entry *pa, *pe;
-	pas->users = 0;
-	pas->groups = 0;
+
+	/*
+	 * Only pas.users and pas.groups need initialization; previous
+	 * posix_acl_valid() calls ensure that the other fields will be
+	 * initialized in the following loop.  But, just to placate gcc:
+	 */
+	memset(pas, 0, sizeof(*pas));
 	pas->mask = 07;
 
 	pe = acl->a_entries + acl->a_count;
@@ -732,13 +737,16 @@
 	*pacl = posix_state_to_acl(&effective_acl_state, flags);
 	if (IS_ERR(*pacl)) {
 		ret = PTR_ERR(*pacl);
+		*pacl = NULL;
 		goto out_dstate;
 	}
 	*dpacl = posix_state_to_acl(&default_acl_state,
 						flags | NFS4_ACL_TYPE_DEFAULT);
 	if (IS_ERR(*dpacl)) {
 		ret = PTR_ERR(*dpacl);
+		*dpacl = NULL;
 		posix_acl_release(*pacl);
+		*pacl = NULL;
 		goto out_dstate;
 	}
 	sort_pacl(*pacl);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 32ffea0..31d6633 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -38,6 +38,7 @@
 #include <linux/inet.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
@@ -74,7 +75,7 @@
 #define op_enc_sz			1
 #define op_dec_sz			2
 #define enc_nfs4_fh_sz			(1 + (NFS4_FHSIZE >> 2))
-#define enc_stateid_sz			16
+#define enc_stateid_sz			(NFS4_STATEID_SIZE >> 2)
 #define NFS4_enc_cb_recall_sz		(cb_compound_enc_hdr_sz +       \
 					1 + enc_stateid_sz +            \
 					enc_nfs4_fh_sz)
@@ -393,7 +394,6 @@
 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
 		.rpc_argp       = clp,
 	};
-	char clientname[16];
 	int status;
 
 	if (atomic_read(&cb->cb_set))
@@ -416,11 +416,6 @@
 	memset(program->stats, 0, sizeof(cb->cb_stat));
 	program->stats->program = program;
 
-	/* Just here to make some printk's more useful: */
-	snprintf(clientname, sizeof(clientname),
-		"%u.%u.%u.%u", NIPQUAD(addr.sin_addr));
-	args.servername = clientname;
-
 	/* Create RPC client */
 	cb->cb_client = rpc_create(&args);
 	if (IS_ERR(cb->cb_client)) {
@@ -428,29 +423,23 @@
 		goto out_err;
 	}
 
-	/* Kick rpciod, put the call on the wire. */
-	if (rpciod_up() != 0)
-		goto out_clnt;
-
 	/* the task holds a reference to the nfs4_client struct */
 	atomic_inc(&clp->cl_count);
 
 	msg.rpc_cred = nfsd4_lookupcred(clp,0);
 	if (IS_ERR(msg.rpc_cred))
-		goto out_rpciod;
+		goto out_release_clp;
 	status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
 	put_rpccred(msg.rpc_cred);
 
 	if (status != 0) {
 		dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
-		goto out_rpciod;
+		goto out_release_clp;
 	}
 	return;
 
-out_rpciod:
+out_release_clp:
 	atomic_dec(&clp->cl_count);
-	rpciod_down();
-out_clnt:
 	rpc_shutdown_client(cb->cb_client);
 out_err:
 	cb->cb_client = NULL;
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 45aa21c..2cf9a9a 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -587,6 +587,15 @@
 	return ret;
 }
 
+static char *
+rqst_authname(struct svc_rqst *rqstp)
+{
+	struct auth_domain *clp;
+
+	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+	return clp->name;
+}
+
 static int
 idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
 		uid_t *id)
@@ -600,7 +609,7 @@
 		return -EINVAL;
 	memcpy(key.name, name, namelen);
 	key.name[namelen] = '\0';
-	strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
 	ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
 	if (ret == -ENOENT)
 		ret = -ESRCH; /* nfserr_badname */
@@ -620,7 +629,7 @@
 	};
 	int ret;
 
-	strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
 	ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
 	if (ret == -ENOENT)
 		return sprintf(name, "%u", id);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 8522729..3c62712 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -47,6 +47,7 @@
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 #include <linux/nfs4_acl.h>
+#include <linux/sunrpc/gss_api.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
@@ -286,8 +287,7 @@
 	__be32 status;
 
 	fh_put(&cstate->current_fh);
-	status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
-			      &rqstp->rq_chandle);
+	status = exp_pseudoroot(rqstp, &cstate->current_fh);
 	return status;
 }
 
@@ -474,8 +474,8 @@
 	__be32 ret;
 
 	fh_init(&tmp_fh, NFS4_FHSIZE);
-	if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
-			      &rqstp->rq_chandle)) != 0)
+	ret = exp_pseudoroot(rqstp, &tmp_fh);
+	if (ret)
 		return ret;
 	if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
 		fh_put(&tmp_fh);
@@ -611,6 +611,30 @@
 }
 
 static __be32
+nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_secinfo *secinfo)
+{
+	struct svc_fh resfh;
+	struct svc_export *exp;
+	struct dentry *dentry;
+	__be32 err;
+
+	fh_init(&resfh, NFS4_FHSIZE);
+	err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
+				    secinfo->si_name, secinfo->si_namelen,
+				    &exp, &dentry);
+	if (err)
+		return err;
+	if (dentry->d_inode == NULL) {
+		exp_put(exp);
+		err = nfserr_noent;
+	} else
+		secinfo->si_exp = exp;
+	dput(dentry);
+	return err;
+}
+
+static __be32
 nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	      struct nfsd4_setattr *setattr)
 {
@@ -1009,6 +1033,9 @@
 	[OP_SAVEFH] = {
 		.op_func = (nfsd4op_func)nfsd4_savefh,
 	},
+	[OP_SECINFO] = {
+		.op_func = (nfsd4op_func)nfsd4_secinfo,
+	},
 	[OP_SETATTR] = {
 		.op_func = (nfsd4op_func)nfsd4_setattr,
 	},
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index c7774e3..ebd03cc 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -45,7 +45,7 @@
 #include <asm/uaccess.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
-
+#include <linux/sched.h>
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 3cc8ce4..e4a4c87 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -49,8 +49,10 @@
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 #include <linux/namei.h>
+#include <linux/swap.h>
 #include <linux/mutex.h>
 #include <linux/lockd/bind.h>
+#include <linux/module.h>
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -149,6 +151,7 @@
 }
 
 static int num_delegations;
+unsigned int max_delegations;
 
 /*
  * Open owner state (share locks)
@@ -192,7 +195,9 @@
 	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
 
 	dprintk("NFSD alloc_init_deleg\n");
-	if (num_delegations > STATEID_HASH_SIZE * 4)
+	if (fp->fi_had_conflict)
+		return NULL;
+	if (num_delegations > max_delegations)
 		return NULL;
 	dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
 	if (dp == NULL)
@@ -378,7 +383,6 @@
 	if (clnt) {
 		clp->cl_callback.cb_client = NULL;
 		rpc_shutdown_client(clnt);
-		rpciod_down();
 	}
 }
 
@@ -1000,6 +1004,7 @@
 		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
 		fp->fi_inode = igrab(ino);
 		fp->fi_id = current_fileid++;
+		fp->fi_had_conflict = false;
 		return fp;
 	}
 	return NULL;
@@ -1326,6 +1331,7 @@
 {
 	struct nfs4_delegation *dp = __dp;
 
+	dp->dl_file->fi_had_conflict = true;
 	nfsd4_cb_recall(dp);
 	return 0;
 }
@@ -3191,20 +3197,49 @@
 		printk("NFSD: Failure reading reboot recovery data\n");
 }
 
+unsigned long
+get_nfs4_grace_period(void)
+{
+	return max(user_lease_time, lease_time) * HZ;
+}
+
+/*
+ * Since the lifetime of a delegation isn't limited to that of an open, a
+ * client may quite reasonably hang on to a delegation as long as it has
+ * the inode cached.  This becomes an obvious problem the first time a
+ * client's inode cache approaches the size of the server's total memory.
+ *
+ * For now we avoid this problem by imposing a hard limit on the number
+ * of delegations, which varies according to the server's memory size.
+ */
+static void
+set_max_delegations(void)
+{
+	/*
+	 * Allow at most 4 delegations per megabyte of RAM.  Quick
+	 * estimates suggest that in the worst case (where every delegation
+	 * is for a different inode), a delegation could take about 1.5K,
+	 * giving a worst case usage of about 6% of memory.
+	 */
+	max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT);
+}
+
 /* initialization to perform when the nfsd service is started: */
 
 static void
 __nfs4_state_start(void)
 {
-	time_t grace_time;
+	unsigned long grace_time;
 
 	boot_time = get_seconds();
-	grace_time = max(user_lease_time, lease_time);
+	grace_time = get_nfs_grace_period();
 	lease_time = user_lease_time;
 	in_grace = 1;
-	printk("NFSD: starting %ld-second grace period\n", grace_time);
+	printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
+	       grace_time/HZ);
 	laundry_wq = create_singlethread_workqueue("nfsd4");
-	queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
+	queue_delayed_work(laundry_wq, &laundromat_work, grace_time);
+	set_max_delegations();
 }
 
 int
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 15809df..b3d55c6 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -56,6 +56,8 @@
 #include <linux/nfsd_idmap.h>
 #include <linux/nfs4.h>
 #include <linux/nfs4_acl.h>
+#include <linux/sunrpc/gss_api.h>
+#include <linux/sunrpc/svcauth_gss.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
@@ -819,6 +821,23 @@
 }
 
 static __be32
+nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
+		     struct nfsd4_secinfo *secinfo)
+{
+	DECODE_HEAD;
+
+	READ_BUF(4);
+	READ32(secinfo->si_namelen);
+	READ_BUF(secinfo->si_namelen);
+	SAVEMEM(secinfo->si_name, secinfo->si_namelen);
+	status = check_filename(secinfo->si_name, secinfo->si_namelen,
+								nfserr_noent);
+	if (status)
+		return status;
+	DECODE_TAIL;
+}
+
+static __be32
 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
 {
 	DECODE_HEAD;
@@ -1131,6 +1150,9 @@
 		case OP_SAVEFH:
 			op->status = nfs_ok;
 			break;
+		case OP_SECINFO:
+			op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo);
+			break;
 		case OP_SETATTR:
 			op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
 			break;
@@ -1296,7 +1318,7 @@
 	char *path, *rootpath;
 
 	fh_init(&tmp_fh, NFS4_FHSIZE);
-	*stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle);
+	*stat = exp_pseudoroot(rqstp, &tmp_fh);
 	if (*stat)
 		return NULL;
 	rootpath = tmp_fh.fh_export->ex_path;
@@ -1847,11 +1869,19 @@
 	if (d_mountpoint(dentry)) {
 		int err;
 
+		/*
+		 * Why the heck aren't we just using nfsd_lookup??
+		 * Different "."/".." handling?  Something else?
+		 * At least, add a comment here to explain....
+		 */
 		err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
 		if (err) {
 			nfserr = nfserrno(err);
 			goto out_put;
 		}
+		nfserr = check_nfsd_access(exp, cd->rd_rqstp);
+		if (nfserr)
+			goto out_put;
 
 	}
 	nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
@@ -2419,6 +2449,72 @@
 	}
 }
 
+static void
+nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr,
+		     struct nfsd4_secinfo *secinfo)
+{
+	int i = 0;
+	struct svc_export *exp = secinfo->si_exp;
+	u32 nflavs;
+	struct exp_flavor_info *flavs;
+	struct exp_flavor_info def_flavs[2];
+	ENCODE_HEAD;
+
+	if (nfserr)
+		goto out;
+	if (exp->ex_nflavors) {
+		flavs = exp->ex_flavors;
+		nflavs = exp->ex_nflavors;
+	} else { /* Handling of some defaults in absence of real secinfo: */
+		flavs = def_flavs;
+		if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
+			nflavs = 2;
+			flavs[0].pseudoflavor = RPC_AUTH_UNIX;
+			flavs[1].pseudoflavor = RPC_AUTH_NULL;
+		} else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
+			nflavs = 1;
+			flavs[0].pseudoflavor
+					= svcauth_gss_flavor(exp->ex_client);
+		} else {
+			nflavs = 1;
+			flavs[0].pseudoflavor
+					= exp->ex_client->flavour->flavour;
+		}
+	}
+
+	RESERVE_SPACE(4);
+	WRITE32(nflavs);
+	ADJUST_ARGS();
+	for (i = 0; i < nflavs; i++) {
+		u32 flav = flavs[i].pseudoflavor;
+		struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
+
+		if (gm) {
+			RESERVE_SPACE(4);
+			WRITE32(RPC_AUTH_GSS);
+			ADJUST_ARGS();
+			RESERVE_SPACE(4 + gm->gm_oid.len);
+			WRITE32(gm->gm_oid.len);
+			WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
+			ADJUST_ARGS();
+			RESERVE_SPACE(4);
+			WRITE32(0); /* qop */
+			ADJUST_ARGS();
+			RESERVE_SPACE(4);
+			WRITE32(gss_pseudoflavor_to_service(gm, flav));
+			ADJUST_ARGS();
+			gss_mech_put(gm);
+		} else {
+			RESERVE_SPACE(4);
+			WRITE32(flav);
+			ADJUST_ARGS();
+		}
+	}
+out:
+	if (exp)
+		exp_put(exp);
+}
+
 /*
  * The SETATTR encode routine is special -- it always encodes a bitmap,
  * regardless of the error status.
@@ -2559,6 +2655,9 @@
 		break;
 	case OP_SAVEFH:
 		break;
+	case OP_SECINFO:
+		nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo);
+		break;
 	case OP_SETATTR:
 		nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
 		break;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 71c686d..baac89d 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -35,7 +35,6 @@
 #include <linux/nfsd/cache.h>
 #include <linux/nfsd/xdr.h>
 #include <linux/nfsd/syscall.h>
-#include <linux/nfsd/interface.h>
 
 #include <asm/uaccess.h>
 
@@ -245,7 +244,7 @@
 	}
 	exp_readunlock();
 	if (err == 0)
-		err = res->fh_size + (int)&((struct knfsd_fh*)0)->fh_base;
+		err = res->fh_size + offsetof(struct knfsd_fh, fh_base);
  out:
 	return err;
 }
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 6ca2d24..0eb464a 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -15,10 +15,12 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/dcache.h>
+#include <linux/exportfs.h>
 #include <linux/mount.h>
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
+#include <linux/sunrpc/svcauth_gss.h>
 #include <linux/nfsd/nfsd.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_FH
@@ -27,10 +29,6 @@
 static int nfsd_nr_verified;
 static int nfsd_nr_put;
 
-extern struct export_operations export_op_default;
-
-#define	CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
-
 /*
  * our acceptability function.
  * if NOSUBTREECHECK, accept anything
@@ -123,8 +121,6 @@
 		int data_left = fh->fh_size/4;
 
 		error = nfserr_stale;
-		if (rqstp->rq_client == NULL)
-			goto out;
 		if (rqstp->rq_vers > 2)
 			error = nfserr_badhandle;
 		if (rqstp->rq_vers == 4 && fh->fh_size == 0)
@@ -148,7 +144,7 @@
 				fh->fh_fsid[1] = fh->fh_fsid[2];
 			}
 			if ((data_left -= len)<0) goto out;
-			exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap, &rqstp->rq_chandle);
+			exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap);
 			datap += len;
 		} else {
 			dev_t xdev;
@@ -159,20 +155,18 @@
 			xdev = old_decode_dev(fh->ofh_xdev);
 			xino = u32_to_ino_t(fh->ofh_xino);
 			mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
-			exp = exp_find(rqstp->rq_client, FSID_DEV, tfh,
-				       &rqstp->rq_chandle);
+			exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
 		}
 
-		if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
-				|| PTR_ERR(exp) == -ETIMEDOUT)) {
+		error = nfserr_stale;
+		if (PTR_ERR(exp) == -ENOENT)
+			goto out;
+
+		if (IS_ERR(exp)) {
 			error = nfserrno(PTR_ERR(exp));
 			goto out;
 		}
 
-		error = nfserr_stale; 
-		if (!exp || IS_ERR(exp))
-			goto out;
-
 		/* Check if the request originated from a secure port. */
 		error = nfserr_perm;
 		if (!rqstp->rq_secure && EX_SECURE(exp)) {
@@ -211,11 +205,9 @@
 		if (fileid_type == 0)
 			dentry = dget(exp->ex_dentry);
 		else {
-			struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-			dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
-						     datap, data_left,
-						     fileid_type,
-						     nfsd_acceptable, exp);
+			dentry = exportfs_decode_fh(exp->ex_mnt, datap,
+					data_left, fileid_type,
+					nfsd_acceptable, exp);
 		}
 		if (dentry == NULL)
 			goto out;
@@ -257,8 +249,19 @@
 	if (error)
 		goto out;
 
+	if (!(access & MAY_LOCK)) {
+		/*
+		 * pseudoflavor restrictions are not enforced on NLM,
+		 * which clients virtually always use auth_sys for,
+		 * even while using RPCSEC_GSS for NFS.
+		 */
+		error = check_nfsd_access(exp, rqstp);
+		if (error)
+			goto out;
+	}
+
 	/* Finally, check access permissions. */
-	error = nfsd_permission(exp, dentry, access);
+	error = nfsd_permission(rqstp, exp, dentry, access);
 
 	if (error) {
 		dprintk("fh_verify: %s/%s permission failure, "
@@ -286,15 +289,13 @@
 static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
 			     __u32 *datap, int *maxsize)
 {
-	struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-
 	if (dentry == exp->ex_dentry) {
 		*maxsize = 0;
 		return 0;
 	}
 
-	return CALL(nop,encode_fh)(dentry, datap, maxsize,
-			  !(exp->ex_flags&NFSEXP_NOSUBTREECHECK));
+	return exportfs_encode_fh(dentry, datap, maxsize,
+			  !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
 }
 
 /*
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index b2c7147..977a71f 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -278,7 +278,8 @@
 					 *   echo thing > device-special-file-or-pipe
 					 * by doing a CREATE with type==0
 					 */
-					nfserr = nfsd_permission(newfhp->fh_export,
+					nfserr = nfsd_permission(rqstp,
+								 newfhp->fh_export,
 								 newfhp->fh_dentry,
 								 MAY_WRITE|MAY_LOCAL_ACCESS);
 					if (nfserr && nfserr != nfserr_rofs)
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index d7759ce..a8c89ae 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -9,7 +9,7 @@
  */
 
 #include <linux/module.h>
-
+#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/nfs.h>
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/freezer.h>
 #include <linux/fs_struct.h>
 
 #include <linux/sunrpc/types.h>
@@ -432,6 +433,7 @@
 	 * dirty pages.
 	 */
 	current->flags |= PF_LESS_THROTTLE;
+	set_freezable();
 
 	/*
 	 * The main request loop
@@ -492,6 +494,15 @@
 	module_put_and_exit(0);
 }
 
+static __be32 map_new_errors(u32 vers, __be32 nfserr)
+{
+	if (nfserr == nfserr_jukebox && vers == 2)
+		return nfserr_dropit;
+	if (nfserr == nfserr_wrongsec && vers < 4)
+		return nfserr_acces;
+	return nfserr;
+}
+
 int
 nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 {
@@ -534,6 +545,7 @@
 
 	/* Now call the procedure handler, and encode NFS status. */
 	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
+	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
 	if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
 		nfserr = nfserr_dropit;
 	if (nfserr == nfserr_dropit) {
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7e6aa24..e90f4a8 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -23,7 +23,7 @@
 #include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/major.h>
-#include <linux/ext2_fs.h>
+#include <linux/splice.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
@@ -113,7 +113,7 @@
 
 	while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
 
-	exp2 = exp_get_by_name(exp->ex_client, mnt, mounts, &rqstp->rq_chandle);
+	exp2 = rqst_exp_get_by_name(rqstp, mnt, mounts);
 	if (IS_ERR(exp2)) {
 		err = PTR_ERR(exp2);
 		dput(mounts);
@@ -135,21 +135,10 @@
 	return err;
 }
 
-/*
- * Look up one component of a pathname.
- * N.B. After this call _both_ fhp and resfh need an fh_put
- *
- * If the lookup would cross a mountpoint, and the mounted filesystem
- * is exported to the client with NFSEXP_NOHIDE, then the lookup is
- * accepted as it stands and the mounted directory is
- * returned. Otherwise the covered directory is returned.
- * NOTE: this mountpoint crossing is not supported properly by all
- *   clients and is explicitly disallowed for NFSv3
- *      NeilBrown <neilb@cse.unsw.edu.au>
- */
 __be32
-nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
-					int len, struct svc_fh *resfh)
+nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+		   const char *name, int len,
+		   struct svc_export **exp_ret, struct dentry **dentry_ret)
 {
 	struct svc_export	*exp;
 	struct dentry		*dparent;
@@ -168,8 +157,6 @@
 	exp  = fhp->fh_export;
 	exp_get(exp);
 
-	err = nfserr_acces;
-
 	/* Lookup the name, but don't follow links */
 	if (isdotent(name, len)) {
 		if (len==1)
@@ -190,17 +177,15 @@
 			dput(dentry);
 			dentry = dp;
 
-			exp2 = exp_parent(exp->ex_client, mnt, dentry,
-					  &rqstp->rq_chandle);
-			if (IS_ERR(exp2)) {
+			exp2 = rqst_exp_parent(rqstp, mnt, dentry);
+			if (PTR_ERR(exp2) == -ENOENT) {
+				dput(dentry);
+				dentry = dget(dparent);
+			} else if (IS_ERR(exp2)) {
 				host_err = PTR_ERR(exp2);
 				dput(dentry);
 				mntput(mnt);
 				goto out_nfserr;
-			}
-			if (!exp2) {
-				dput(dentry);
-				dentry = dget(dparent);
 			} else {
 				exp_put(exp);
 				exp = exp2;
@@ -223,6 +208,41 @@
 			}
 		}
 	}
+	*dentry_ret = dentry;
+	*exp_ret = exp;
+	return 0;
+
+out_nfserr:
+	exp_put(exp);
+	return nfserrno(host_err);
+}
+
+/*
+ * Look up one component of a pathname.
+ * N.B. After this call _both_ fhp and resfh need an fh_put
+ *
+ * If the lookup would cross a mountpoint, and the mounted filesystem
+ * is exported to the client with NFSEXP_NOHIDE, then the lookup is
+ * accepted as it stands and the mounted directory is
+ * returned. Otherwise the covered directory is returned.
+ * NOTE: this mountpoint crossing is not supported properly by all
+ *   clients and is explicitly disallowed for NFSv3
+ *      NeilBrown <neilb@cse.unsw.edu.au>
+ */
+__be32
+nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+					int len, struct svc_fh *resfh)
+{
+	struct svc_export	*exp;
+	struct dentry		*dentry;
+	__be32 err;
+
+	err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry);
+	if (err)
+		return err;
+	err = check_nfsd_access(exp, rqstp);
+	if (err)
+		goto out;
 	/*
 	 * Note: we compose the file handle now, but as the
 	 * dentry may be negative, it may need to be updated.
@@ -230,16 +250,13 @@
 	err = fh_compose(resfh, exp, dentry, fhp);
 	if (!err && !dentry->d_inode)
 		err = nfserr_noent;
-	dput(dentry);
 out:
+	dput(dentry);
 	exp_put(exp);
 	return err;
-
-out_nfserr:
-	err = nfserrno(host_err);
-	goto out;
 }
 
+
 /*
  * Set various file attributes.
  * N.B. After this call fhp needs an fh_put
@@ -311,7 +328,7 @@
 	/* The size case is special. It changes the file as well as the attributes.  */
 	if (iap->ia_valid & ATTR_SIZE) {
 		if (iap->ia_size < inode->i_size) {
-			err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
+			err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
 			if (err)
 				goto out;
 		}
@@ -435,7 +452,7 @@
 	/* Get inode */
 	error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR);
 	if (error)
-		goto out;
+		return error;
 
 	dentry = fhp->fh_dentry;
 	inode = dentry->d_inode;
@@ -444,33 +461,25 @@
 
 	host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
 	if (host_error == -EINVAL) {
-		error = nfserr_attrnotsupp;
-		goto out;
+		return nfserr_attrnotsupp;
 	} else if (host_error < 0)
 		goto out_nfserr;
 
 	host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
 	if (host_error < 0)
-		goto out_nfserr;
+		goto out_release;
 
-	if (S_ISDIR(inode->i_mode)) {
+	if (S_ISDIR(inode->i_mode))
 		host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
-		if (host_error < 0)
-			goto out_nfserr;
-	}
 
-	error = nfs_ok;
-
-out:
+out_release:
 	posix_acl_release(pacl);
 	posix_acl_release(dpacl);
-	return (error);
 out_nfserr:
 	if (host_error == -EOPNOTSUPP)
-		error = nfserr_attrnotsupp;
+		return nfserr_attrnotsupp;
 	else
-		error = nfserrno(host_error);
-	goto out;
+		return nfserrno(host_error);
 }
 
 static struct posix_acl *
@@ -607,7 +616,7 @@
 
 			sresult |= map->access;
 
-			err2 = nfsd_permission(export, dentry, map->how);
+			err2 = nfsd_permission(rqstp, export, dentry, map->how);
 			switch (err2) {
 			case nfs_ok:
 				result |= map->access;
@@ -801,26 +810,32 @@
 }
 
 /*
- * Grab and keep cached pages assosiated with a file in the svc_rqst
- * so that they can be passed to the netowork sendmsg/sendpage routines
- * directrly. They will be released after the sending has completed.
+ * Grab and keep cached pages associated with a file in the svc_rqst
+ * so that they can be passed to the network sendmsg/sendpage routines
+ * directly. They will be released after the sending has completed.
  */
 static int
-nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
+nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+		  struct splice_desc *sd)
 {
-	unsigned long count = desc->count;
-	struct svc_rqst *rqstp = desc->arg.data;
+	struct svc_rqst *rqstp = sd->u.data;
 	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
+	struct page *page = buf->page;
+	size_t size;
+	int ret;
 
-	if (size > count)
-		size = count;
+	ret = buf->ops->confirm(pipe, buf);
+	if (unlikely(ret))
+		return ret;
+
+	size = sd->len;
 
 	if (rqstp->rq_res.page_len == 0) {
 		get_page(page);
 		put_page(*pp);
 		*pp = page;
 		rqstp->rq_resused++;
-		rqstp->rq_res.page_base = offset;
+		rqstp->rq_res.page_base = buf->offset;
 		rqstp->rq_res.page_len = size;
 	} else if (page != pp[-1]) {
 		get_page(page);
@@ -832,11 +847,15 @@
 	} else
 		rqstp->rq_res.page_len += size;
 
-	desc->count = count - size;
-	desc->written += size;
 	return size;
 }
 
+static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
+				    struct splice_desc *sd)
+{
+	return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
+}
+
 static __be32
 nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
               loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
@@ -861,10 +880,16 @@
 	if (ra && ra->p_set)
 		file->f_ra = ra->p_ra;
 
-	if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
+	if (file->f_op->splice_read && rqstp->rq_splice_ok) {
+		struct splice_desc sd = {
+			.len		= 0,
+			.total_len	= *count,
+			.pos		= offset,
+			.u.data		= rqstp,
+		};
+
 		rqstp->rq_resused = 1;
-		host_err = file->f_op->sendfile(file, &offset, *count,
-						 nfsd_read_actor, rqstp);
+		host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
 	} else {
 		oldfs = get_fs();
 		set_fs(KERNEL_DS);
@@ -1018,7 +1043,7 @@
 	__be32		err;
 
 	if (file) {
-		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+		err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
 				MAY_READ|MAY_OWNER_OVERRIDE);
 		if (err)
 			goto out;
@@ -1047,7 +1072,7 @@
 	__be32			err = 0;
 
 	if (file) {
-		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+		err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
 				MAY_WRITE|MAY_OWNER_OVERRIDE);
 		if (err)
 			goto out;
@@ -1776,7 +1801,8 @@
  * Check for a user's access permissions to this inode.
  */
 __be32
-nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
+nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+					struct dentry *dentry, int acc)
 {
 	struct inode	*inode = dentry->d_inode;
 	int		err;
@@ -1807,7 +1833,7 @@
 	 */
 	if (!(acc & MAY_LOCAL_ACCESS))
 		if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
-			if (EX_RDONLY(exp) || IS_RDONLY(inode))
+			if (EX_RDONLY(exp, rqstp) || IS_RDONLY(inode))
 				return nfserr_rofs;
 			if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
 				return nfserr_perm;
diff --git a/fs/nls/Makefile b/fs/nls/Makefile
index a7ade13..f499dd7 100644
--- a/fs/nls/Makefile
+++ b/fs/nls/Makefile
@@ -36,11 +36,9 @@
 obj-$(CONFIG_NLS_ISO8859_7)	+= nls_iso8859-7.o
 obj-$(CONFIG_NLS_ISO8859_8)	+= nls_cp1255.o
 obj-$(CONFIG_NLS_ISO8859_9)	+= nls_iso8859-9.o
-obj-$(CONFIG_NLS_ISO8859_10)	+= nls_iso8859-10.o
 obj-$(CONFIG_NLS_ISO8859_13)	+= nls_iso8859-13.o
 obj-$(CONFIG_NLS_ISO8859_14)	+= nls_iso8859-14.o
 obj-$(CONFIG_NLS_ISO8859_15)	+= nls_iso8859-15.o
 obj-$(CONFIG_NLS_KOI8_R)	+= nls_koi8-r.o
 obj-$(CONFIG_NLS_KOI8_U)	+= nls_koi8-u.o nls_koi8-ru.o
-obj-$(CONFIG_NLS_ABC)		+= nls_abc.o
 obj-$(CONFIG_NLS_UTF8)		+= nls_utf8.o
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 39a1669..ffcc504 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -26,6 +26,7 @@
 #include <linux/swap.h>
 #include <linux/uio.h>
 #include <linux/writeback.h>
+#include <linux/sched.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -2275,7 +2276,7 @@
 						    mounted filesystem. */
 	.mmap		= generic_file_mmap,	 /* Mmap file. */
 	.open		= ntfs_file_open,	 /* Open file. */
-	.sendfile	= generic_file_sendfile, /* Zero-copy data send with
+	.splice_read	= generic_file_splice_read /* Zero-copy data send with
 						    the data source being on
 						    the ntfs partition.  We do
 						    not need to care about the
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 074791c..b532a73 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -140,7 +140,7 @@
 		if (!ni->name)
 			return -ENOMEM;
 		memcpy(ni->name, na->name, i);
-		ni->name[i] = 0;
+		ni->name[na->name_len] = 0;
 	}
 	return 0;
 }
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index bff01a5..e93c614 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/dcache.h>
+#include <linux/exportfs.h>
 #include <linux/security.h>
 
 #include "attrib.h"
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 19712a7..f5e11f4 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -50,6 +50,8 @@
 #include "buffer_head_io.h"
 
 static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
+static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
+					 struct ocfs2_extent_block *eb);
 
 /*
  * Structures which describe a path through a btree, and functions to
@@ -117,6 +119,31 @@
 }
 
 /*
+ * All the elements of src into dest. After this call, src could be freed
+ * without affecting dest.
+ *
+ * Both paths should have the same root. Any non-root elements of dest
+ * will be freed.
+ */
+static void ocfs2_cp_path(struct ocfs2_path *dest, struct ocfs2_path *src)
+{
+	int i;
+
+	BUG_ON(path_root_bh(dest) != path_root_bh(src));
+	BUG_ON(path_root_el(dest) != path_root_el(src));
+
+	ocfs2_reinit_path(dest, 1);
+
+	for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
+		dest->p_node[i].bh = src->p_node[i].bh;
+		dest->p_node[i].el = src->p_node[i].el;
+
+		if (dest->p_node[i].bh)
+			get_bh(dest->p_node[i].bh);
+	}
+}
+
+/*
  * Make the *dest path the same as src and re-initialize src path to
  * have a root only.
  */
@@ -212,10 +239,41 @@
 	return ret;
 }
 
+/*
+ * Return the index of the extent record which contains cluster #v_cluster.
+ * -1 is returned if it was not found.
+ *
+ * Should work fine on interior and exterior nodes.
+ */
+int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster)
+{
+	int ret = -1;
+	int i;
+	struct ocfs2_extent_rec *rec;
+	u32 rec_end, rec_start, clusters;
+
+	for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
+		rec = &el->l_recs[i];
+
+		rec_start = le32_to_cpu(rec->e_cpos);
+		clusters = ocfs2_rec_clusters(el, rec);
+
+		rec_end = rec_start + clusters;
+
+		if (v_cluster >= rec_start && v_cluster < rec_end) {
+			ret = i;
+			break;
+		}
+	}
+
+	return ret;
+}
+
 enum ocfs2_contig_type {
 	CONTIG_NONE = 0,
 	CONTIG_LEFT,
-	CONTIG_RIGHT
+	CONTIG_RIGHT,
+	CONTIG_LEFTRIGHT,
 };
 
 
@@ -253,6 +311,14 @@
 {
 	u64 blkno = le64_to_cpu(insert_rec->e_blkno);
 
+	/*
+	 * Refuse to coalesce extent records with different flag
+	 * fields - we don't want to mix unwritten extents with user
+	 * data.
+	 */
+	if (ext->e_flags != insert_rec->e_flags)
+		return CONTIG_NONE;
+
 	if (ocfs2_extents_adjacent(ext, insert_rec) &&
 	    ocfs2_block_extent_contig(inode->i_sb, ext, blkno))
 			return CONTIG_RIGHT;
@@ -277,7 +343,14 @@
 	APPEND_TAIL,
 };
 
+enum ocfs2_split_type {
+	SPLIT_NONE = 0,
+	SPLIT_LEFT,
+	SPLIT_RIGHT,
+};
+
 struct ocfs2_insert_type {
+	enum ocfs2_split_type	ins_split;
 	enum ocfs2_append_type	ins_appending;
 	enum ocfs2_contig_type	ins_contig;
 	int			ins_contig_index;
@@ -285,6 +358,13 @@
 	int			ins_tree_depth;
 };
 
+struct ocfs2_merge_ctxt {
+	enum ocfs2_contig_type	c_contig_type;
+	int			c_has_empty_extent;
+	int			c_split_covers_rec;
+	int			c_used_tail_recs;
+};
+
 /*
  * How many free extents have we got before we need more meta data?
  */
@@ -384,13 +464,7 @@
 			strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
 			eb->h_blkno = cpu_to_le64(first_blkno);
 			eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
-
-#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
-			/* we always use slot zero's suballocator */
-			eb->h_suballoc_slot = 0;
-#else
 			eb->h_suballoc_slot = cpu_to_le16(osb->slot_num);
-#endif
 			eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 			eb->h_list.l_count =
 				cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
@@ -461,7 +535,7 @@
 			    struct inode *inode,
 			    struct buffer_head *fe_bh,
 			    struct buffer_head *eb_bh,
-			    struct buffer_head *last_eb_bh,
+			    struct buffer_head **last_eb_bh,
 			    struct ocfs2_alloc_context *meta_ac)
 {
 	int status, new_blocks, i;
@@ -476,7 +550,7 @@
 
 	mlog_entry_void();
 
-	BUG_ON(!last_eb_bh);
+	BUG_ON(!last_eb_bh || !*last_eb_bh);
 
 	fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
@@ -507,7 +581,7 @@
 		goto bail;
 	}
 
-	eb = (struct ocfs2_extent_block *)last_eb_bh->b_data;
+	eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
 	new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list);
 
 	/* Note: new_eb_bhs[new_blocks - 1] is the guy which will be
@@ -568,7 +642,7 @@
 	 * journal_dirty erroring as it won't unless we've aborted the
 	 * handle (in which case we would never be here) so reserving
 	 * the write with journal_access is all we need to do. */
-	status = ocfs2_journal_access(handle, inode, last_eb_bh,
+	status = ocfs2_journal_access(handle, inode, *last_eb_bh,
 				      OCFS2_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
 		mlog_errno(status);
@@ -601,10 +675,10 @@
 	 * next_leaf on the previously last-extent-block. */
 	fe->i_last_eb_blk = cpu_to_le64(new_last_eb_blk);
 
-	eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+	eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
 	eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);
 
-	status = ocfs2_journal_dirty(handle, last_eb_bh);
+	status = ocfs2_journal_dirty(handle, *last_eb_bh);
 	if (status < 0)
 		mlog_errno(status);
 	status = ocfs2_journal_dirty(handle, fe_bh);
@@ -616,6 +690,14 @@
 			mlog_errno(status);
 	}
 
+	/*
+	 * Some callers want to track the rightmost leaf so pass it
+	 * back here.
+	 */
+	brelse(*last_eb_bh);
+	get_bh(new_eb_bhs[0]);
+	*last_eb_bh = new_eb_bhs[0];
+
 	status = 0;
 bail:
 	if (new_eb_bhs) {
@@ -829,6 +911,87 @@
 }
 
 /*
+ * Grow a b-tree so that it has more records.
+ *
+ * We might shift the tree depth in which case existing paths should
+ * be considered invalid.
+ *
+ * Tree depth after the grow is returned via *final_depth.
+ *
+ * *last_eb_bh will be updated by ocfs2_add_branch().
+ */
+static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
+			   struct buffer_head *di_bh, int *final_depth,
+			   struct buffer_head **last_eb_bh,
+			   struct ocfs2_alloc_context *meta_ac)
+{
+	int ret, shift;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+	int depth = le16_to_cpu(di->id2.i_list.l_tree_depth);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct buffer_head *bh = NULL;
+
+	BUG_ON(meta_ac == NULL);
+
+	shift = ocfs2_find_branch_target(osb, inode, di_bh, &bh);
+	if (shift < 0) {
+		ret = shift;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/* We traveled all the way to the bottom of the allocation tree
+	 * and didn't find room for any more extents - we need to add
+	 * another tree level */
+	if (shift) {
+		BUG_ON(bh);
+		mlog(0, "need to shift tree depth (current = %d)\n", depth);
+
+		/* ocfs2_shift_tree_depth will return us a buffer with
+		 * the new extent block (so we can pass that to
+		 * ocfs2_add_branch). */
+		ret = ocfs2_shift_tree_depth(osb, handle, inode, di_bh,
+					     meta_ac, &bh);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
+		depth++;
+		if (depth == 1) {
+			/*
+			 * Special case: we have room now if we shifted from
+			 * tree_depth 0, so no more work needs to be done.
+			 *
+			 * We won't be calling add_branch, so pass
+			 * back *last_eb_bh as the new leaf. At depth
+			 * zero, it should always be null so there's
+			 * no reason to brelse.
+			 */
+			BUG_ON(*last_eb_bh);
+			get_bh(bh);
+			*last_eb_bh = bh;
+			goto out;
+		}
+	}
+
+	/* call ocfs2_add_branch to add the final part of the tree with
+	 * the new data. */
+	mlog(0, "add branch. bh = %p\n", bh);
+	ret = ocfs2_add_branch(osb, handle, inode, di_bh, bh, last_eb_bh,
+			       meta_ac);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+out:
+	if (final_depth)
+		*final_depth = depth;
+	brelse(bh);
+	return ret;
+}
+
+/*
  * This is only valid for leaf nodes, which are the only ones that can
  * have empty extents anyway.
  */
@@ -934,6 +1097,22 @@
 
 }
 
+static void ocfs2_remove_empty_extent(struct ocfs2_extent_list *el)
+{
+	int size, num_recs = le16_to_cpu(el->l_next_free_rec);
+
+	BUG_ON(num_recs == 0);
+
+	if (ocfs2_is_empty_extent(&el->l_recs[0])) {
+		num_recs--;
+		size = num_recs * sizeof(struct ocfs2_extent_rec);
+		memmove(&el->l_recs[0], &el->l_recs[1], size);
+		memset(&el->l_recs[num_recs], 0,
+		       sizeof(struct ocfs2_extent_rec));
+		el->l_next_free_rec = cpu_to_le16(num_recs);
+	}
+}
+
 /*
  * Create an empty extent record .
  *
@@ -1211,6 +1390,10 @@
 	 * immediately to their right.
 	 */
 	left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
+	if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {
+		BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
+		left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
+	}
 	left_clusters -= le32_to_cpu(left_rec->e_cpos);
 	left_rec->e_int_clusters = cpu_to_le32(left_clusters);
 
@@ -1531,10 +1714,16 @@
 	return ret;
 }
 
+/*
+ * Extend the transaction by enough credits to complete the rotation,
+ * and still leave at least the original number of credits allocated
+ * to this transaction.
+ */
 static int ocfs2_extend_rotate_transaction(handle_t *handle, int subtree_depth,
+					   int op_credits,
 					   struct ocfs2_path *path)
 {
-	int credits = (path->p_tree_depth - subtree_depth) * 2 + 1;
+	int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits;
 
 	if (handle->h_buffer_credits < credits)
 		return ocfs2_extend_trans(handle, credits);
@@ -1568,6 +1757,29 @@
 	return 0;
 }
 
+static int ocfs2_leftmost_rec_contains(struct ocfs2_extent_list *el, u32 cpos)
+{
+	int next_free = le16_to_cpu(el->l_next_free_rec);
+	unsigned int range;
+	struct ocfs2_extent_rec *rec;
+
+	if (next_free == 0)
+		return 0;
+
+	rec = &el->l_recs[0];
+	if (ocfs2_is_empty_extent(rec)) {
+		/* Empty list. */
+		if (next_free == 1)
+			return 0;
+		rec = &el->l_recs[1];
+	}
+
+	range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+	if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)
+		return 1;
+	return 0;
+}
+
 /*
  * Rotate all the records in a btree right one record, starting at insert_cpos.
  *
@@ -1586,11 +1798,12 @@
  */
 static int ocfs2_rotate_tree_right(struct inode *inode,
 				   handle_t *handle,
+				   enum ocfs2_split_type split,
 				   u32 insert_cpos,
 				   struct ocfs2_path *right_path,
 				   struct ocfs2_path **ret_left_path)
 {
-	int ret, start;
+	int ret, start, orig_credits = handle->h_buffer_credits;
 	u32 cpos;
 	struct ocfs2_path *left_path = NULL;
 
@@ -1657,9 +1870,9 @@
 				(unsigned long long)
 				path_leaf_bh(left_path)->b_blocknr);
 
-		if (ocfs2_rotate_requires_path_adjustment(left_path,
+		if (split == SPLIT_NONE &&
+		    ocfs2_rotate_requires_path_adjustment(left_path,
 							  insert_cpos)) {
-			mlog(0, "Path adjustment required\n");
 
 			/*
 			 * We've rotated the tree as much as we
@@ -1687,7 +1900,7 @@
 		     right_path->p_tree_depth);
 
 		ret = ocfs2_extend_rotate_transaction(handle, start,
-						      right_path);
+						      orig_credits, right_path);
 		if (ret) {
 			mlog_errno(ret);
 			goto out;
@@ -1700,6 +1913,24 @@
 			goto out;
 		}
 
+		if (split != SPLIT_NONE &&
+		    ocfs2_leftmost_rec_contains(path_leaf_el(right_path),
+						insert_cpos)) {
+			/*
+			 * A rotate moves the rightmost left leaf
+			 * record over to the leftmost right leaf
+			 * slot. If we're doing an extent split
+			 * instead of a real insert, then we have to
+			 * check that the extent to be split wasn't
+			 * just moved over. If it was, then we can
+			 * exit here, passing left_path back -
+			 * ocfs2_split_extent() is smart enough to
+			 * search both leaves.
+			 */
+			*ret_left_path = left_path;
+			goto out_ret_path;
+		}
+
 		/*
 		 * There is no need to re-read the next right path
 		 * as we know that it'll be our current left
@@ -1722,6 +1953,1031 @@
 	return ret;
 }
 
+static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
+				      struct ocfs2_path *path)
+{
+	int i, idx;
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_extent_list *el;
+	struct ocfs2_extent_block *eb;
+	u32 range;
+
+	/* Path should always be rightmost. */
+	eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+	BUG_ON(eb->h_next_leaf_blk != 0ULL);
+
+	el = &eb->h_list;
+	BUG_ON(le16_to_cpu(el->l_next_free_rec) == 0);
+	idx = le16_to_cpu(el->l_next_free_rec) - 1;
+	rec = &el->l_recs[idx];
+	range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+
+	for (i = 0; i < path->p_tree_depth; i++) {
+		el = path->p_node[i].el;
+		idx = le16_to_cpu(el->l_next_free_rec) - 1;
+		rec = &el->l_recs[idx];
+
+		rec->e_int_clusters = cpu_to_le32(range);
+		le32_add_cpu(&rec->e_int_clusters, -le32_to_cpu(rec->e_cpos));
+
+		ocfs2_journal_dirty(handle, path->p_node[i].bh);
+	}
+}
+
+static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
+			      struct ocfs2_cached_dealloc_ctxt *dealloc,
+			      struct ocfs2_path *path, int unlink_start)
+{
+	int ret, i;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_list *el;
+	struct buffer_head *bh;
+
+	for(i = unlink_start; i < path_num_items(path); i++) {
+		bh = path->p_node[i].bh;
+
+		eb = (struct ocfs2_extent_block *)bh->b_data;
+		/*
+		 * Not all nodes might have had their final count
+		 * decremented by the caller - handle this here.
+		 */
+		el = &eb->h_list;
+		if (le16_to_cpu(el->l_next_free_rec) > 1) {
+			mlog(ML_ERROR,
+			     "Inode %llu, attempted to remove extent block "
+			     "%llu with %u records\n",
+			     (unsigned long long)OCFS2_I(inode)->ip_blkno,
+			     (unsigned long long)le64_to_cpu(eb->h_blkno),
+			     le16_to_cpu(el->l_next_free_rec));
+
+			ocfs2_journal_dirty(handle, bh);
+			ocfs2_remove_from_cache(inode, bh);
+			continue;
+		}
+
+		el->l_next_free_rec = 0;
+		memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+
+		ocfs2_journal_dirty(handle, bh);
+
+		ret = ocfs2_cache_extent_block_free(dealloc, eb);
+		if (ret)
+			mlog_errno(ret);
+
+		ocfs2_remove_from_cache(inode, bh);
+	}
+}
+
+static void ocfs2_unlink_subtree(struct inode *inode, handle_t *handle,
+				 struct ocfs2_path *left_path,
+				 struct ocfs2_path *right_path,
+				 int subtree_index,
+				 struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int i;
+	struct buffer_head *root_bh = left_path->p_node[subtree_index].bh;
+	struct ocfs2_extent_list *root_el = left_path->p_node[subtree_index].el;
+	struct ocfs2_extent_list *el;
+	struct ocfs2_extent_block *eb;
+
+	el = path_leaf_el(left_path);
+
+	eb = (struct ocfs2_extent_block *)right_path->p_node[subtree_index + 1].bh->b_data;
+
+	for(i = 1; i < le16_to_cpu(root_el->l_next_free_rec); i++)
+		if (root_el->l_recs[i].e_blkno == eb->h_blkno)
+			break;
+
+	BUG_ON(i >= le16_to_cpu(root_el->l_next_free_rec));
+
+	memset(&root_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
+	le16_add_cpu(&root_el->l_next_free_rec, -1);
+
+	eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+	eb->h_next_leaf_blk = 0;
+
+	ocfs2_journal_dirty(handle, root_bh);
+	ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
+
+	ocfs2_unlink_path(inode, handle, dealloc, right_path,
+			  subtree_index + 1);
+}
+
+static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
+				     struct ocfs2_path *left_path,
+				     struct ocfs2_path *right_path,
+				     int subtree_index,
+				     struct ocfs2_cached_dealloc_ctxt *dealloc,
+				     int *deleted)
+{
+	int ret, i, del_right_subtree = 0, right_has_empty = 0;
+	struct buffer_head *root_bh, *di_bh = path_root_bh(right_path);
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+	struct ocfs2_extent_list *right_leaf_el, *left_leaf_el;
+	struct ocfs2_extent_block *eb;
+
+	*deleted = 0;
+
+	right_leaf_el = path_leaf_el(right_path);
+	left_leaf_el = path_leaf_el(left_path);
+	root_bh = left_path->p_node[subtree_index].bh;
+	BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
+
+	if (!ocfs2_is_empty_extent(&left_leaf_el->l_recs[0]))
+		return 0;
+
+	eb = (struct ocfs2_extent_block *)path_leaf_bh(right_path)->b_data;
+	if (ocfs2_is_empty_extent(&right_leaf_el->l_recs[0])) {
+		/*
+		 * It's legal for us to proceed if the right leaf is
+		 * the rightmost one and it has an empty extent. There
+		 * are two cases to handle - whether the leaf will be
+		 * empty after removal or not. If the leaf isn't empty
+		 * then just remove the empty extent up front. The
+		 * next block will handle empty leaves by flagging
+		 * them for unlink.
+		 *
+		 * Non rightmost leaves will throw -EAGAIN and the
+		 * caller can manually move the subtree and retry.
+		 */
+
+		if (eb->h_next_leaf_blk != 0ULL)
+			return -EAGAIN;
+
+		if (le16_to_cpu(right_leaf_el->l_next_free_rec) > 1) {
+			ret = ocfs2_journal_access(handle, inode,
+						   path_leaf_bh(right_path),
+						   OCFS2_JOURNAL_ACCESS_WRITE);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+
+			ocfs2_remove_empty_extent(right_leaf_el);
+		} else
+			right_has_empty = 1;
+	}
+
+	if (eb->h_next_leaf_blk == 0ULL &&
+	    le16_to_cpu(right_leaf_el->l_next_free_rec) == 1) {
+		/*
+		 * We have to update i_last_eb_blk during the meta
+		 * data delete.
+		 */
+		ret = ocfs2_journal_access(handle, inode, di_bh,
+					   OCFS2_JOURNAL_ACCESS_WRITE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		del_right_subtree = 1;
+	}
+
+	/*
+	 * Getting here with an empty extent in the right path implies
+	 * that it's the rightmost path and will be deleted.
+	 */
+	BUG_ON(right_has_empty && !del_right_subtree);
+
+	ret = ocfs2_journal_access(handle, inode, root_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
+		ret = ocfs2_journal_access(handle, inode,
+					   right_path->p_node[i].bh,
+					   OCFS2_JOURNAL_ACCESS_WRITE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ret = ocfs2_journal_access(handle, inode,
+					   left_path->p_node[i].bh,
+					   OCFS2_JOURNAL_ACCESS_WRITE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	}
+
+	if (!right_has_empty) {
+		/*
+		 * Only do this if we're moving a real
+		 * record. Otherwise, the action is delayed until
+		 * after removal of the right path in which case we
+		 * can do a simple shift to remove the empty extent.
+		 */
+		ocfs2_rotate_leaf(left_leaf_el, &right_leaf_el->l_recs[0]);
+		memset(&right_leaf_el->l_recs[0], 0,
+		       sizeof(struct ocfs2_extent_rec));
+	}
+	if (eb->h_next_leaf_blk == 0ULL) {
+		/*
+		 * Move recs over to get rid of empty extent, decrease
+		 * next_free. This is allowed to remove the last
+		 * extent in our leaf (setting l_next_free_rec to
+		 * zero) - the delete code below won't care.
+		 */
+		ocfs2_remove_empty_extent(right_leaf_el);
+	}
+
+	ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
+	if (ret)
+		mlog_errno(ret);
+	ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path));
+	if (ret)
+		mlog_errno(ret);
+
+	if (del_right_subtree) {
+		ocfs2_unlink_subtree(inode, handle, left_path, right_path,
+				     subtree_index, dealloc);
+		ocfs2_update_edge_lengths(inode, handle, left_path);
+
+		eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+		di->i_last_eb_blk = eb->h_blkno;
+
+		/*
+		 * Removal of the extent in the left leaf was skipped
+		 * above so we could delete the right path
+		 * 1st.
+		 */
+		if (right_has_empty)
+			ocfs2_remove_empty_extent(left_leaf_el);
+
+		ret = ocfs2_journal_dirty(handle, di_bh);
+		if (ret)
+			mlog_errno(ret);
+
+		*deleted = 1;
+	} else
+		ocfs2_complete_edge_insert(inode, handle, left_path, right_path,
+					   subtree_index);
+
+out:
+	return ret;
+}
+
+/*
+ * Given a full path, determine what cpos value would return us a path
+ * containing the leaf immediately to the right of the current one.
+ *
+ * Will return zero if the path passed in is already the rightmost path.
+ *
+ * This looks similar, but is subtly different to
+ * ocfs2_find_cpos_for_left_leaf().
+ */
+static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+					  struct ocfs2_path *path, u32 *cpos)
+{
+	int i, j, ret = 0;
+	u64 blkno;
+	struct ocfs2_extent_list *el;
+
+	*cpos = 0;
+
+	if (path->p_tree_depth == 0)
+		return 0;
+
+	blkno = path_leaf_bh(path)->b_blocknr;
+
+	/* Start at the tree node just above the leaf and work our way up. */
+	i = path->p_tree_depth - 1;
+	while (i >= 0) {
+		int next_free;
+
+		el = path->p_node[i].el;
+
+		/*
+		 * Find the extent record just after the one in our
+		 * path.
+		 */
+		next_free = le16_to_cpu(el->l_next_free_rec);
+		for(j = 0; j < le16_to_cpu(el->l_next_free_rec); j++) {
+			if (le64_to_cpu(el->l_recs[j].e_blkno) == blkno) {
+				if (j == (next_free - 1)) {
+					if (i == 0) {
+						/*
+						 * We've determined that the
+						 * path specified is already
+						 * the rightmost one - return a
+						 * cpos of zero.
+						 */
+						goto out;
+					}
+					/*
+					 * The rightmost record points to our
+					 * leaf - we need to travel up the
+					 * tree one level.
+					 */
+					goto next_node;
+				}
+
+				*cpos = le32_to_cpu(el->l_recs[j + 1].e_cpos);
+				goto out;
+			}
+		}
+
+		/*
+		 * If we got here, we never found a valid node where
+		 * the tree indicated one should be.
+		 */
+		ocfs2_error(sb,
+			    "Invalid extent tree at extent block %llu\n",
+			    (unsigned long long)blkno);
+		ret = -EROFS;
+		goto out;
+
+next_node:
+		blkno = path->p_node[i].bh->b_blocknr;
+		i--;
+	}
+
+out:
+	return ret;
+}
+
+static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
+					    handle_t *handle,
+					    struct buffer_head *bh,
+					    struct ocfs2_extent_list *el)
+{
+	int ret;
+
+	if (!ocfs2_is_empty_extent(&el->l_recs[0]))
+		return 0;
+
+	ret = ocfs2_journal_access(handle, inode, bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ocfs2_remove_empty_extent(el);
+
+	ret = ocfs2_journal_dirty(handle, bh);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	return ret;
+}
+
+static int __ocfs2_rotate_tree_left(struct inode *inode,
+				    handle_t *handle, int orig_credits,
+				    struct ocfs2_path *path,
+				    struct ocfs2_cached_dealloc_ctxt *dealloc,
+				    struct ocfs2_path **empty_extent_path)
+{
+	int ret, subtree_root, deleted;
+	u32 right_cpos;
+	struct ocfs2_path *left_path = NULL;
+	struct ocfs2_path *right_path = NULL;
+
+	BUG_ON(!ocfs2_is_empty_extent(&(path_leaf_el(path)->l_recs[0])));
+
+	*empty_extent_path = NULL;
+
+	ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, path,
+					     &right_cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	left_path = ocfs2_new_path(path_root_bh(path),
+				   path_root_el(path));
+	if (!left_path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ocfs2_cp_path(left_path, path);
+
+	right_path = ocfs2_new_path(path_root_bh(path),
+				    path_root_el(path));
+	if (!right_path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	while (right_cpos) {
+		ret = ocfs2_find_path(inode, right_path, right_cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		subtree_root = ocfs2_find_subtree_root(inode, left_path,
+						       right_path);
+
+		mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
+		     subtree_root,
+		     (unsigned long long)
+		     right_path->p_node[subtree_root].bh->b_blocknr,
+		     right_path->p_tree_depth);
+
+		ret = ocfs2_extend_rotate_transaction(handle, subtree_root,
+						      orig_credits, left_path);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ret = ocfs2_rotate_subtree_left(inode, handle, left_path,
+						right_path, subtree_root,
+						dealloc, &deleted);
+		if (ret == -EAGAIN) {
+			/*
+			 * The rotation has to temporarily stop due to
+			 * the right subtree having an empty
+			 * extent. Pass it back to the caller for a
+			 * fixup.
+			 */
+			*empty_extent_path = right_path;
+			right_path = NULL;
+			goto out;
+		}
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		/*
+		 * The subtree rotate might have removed records on
+		 * the rightmost edge. If so, then rotation is
+		 * complete.
+		 */
+		if (deleted)
+			break;
+
+		ocfs2_mv_path(left_path, right_path);
+
+		ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
+						     &right_cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	}
+
+out:
+	ocfs2_free_path(right_path);
+	ocfs2_free_path(left_path);
+
+	return ret;
+}
+
+static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
+				       struct ocfs2_path *path,
+				       struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret, subtree_index;
+	u32 cpos;
+	struct ocfs2_path *left_path = NULL;
+	struct ocfs2_dinode *di;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_list *el;
+
+	/*
+	 * XXX: This code assumes that the root is an inode, which is
+	 * true for now but may change as tree code gets generic.
+	 */
+	di = (struct ocfs2_dinode *)path_root_bh(path)->b_data;
+	if (!OCFS2_IS_VALID_DINODE(di)) {
+		ret = -EIO;
+		ocfs2_error(inode->i_sb,
+			    "Inode %llu has invalid path root",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+		goto out;
+	}
+
+	/*
+	 * There's two ways we handle this depending on
+	 * whether path is the only existing one.
+	 */
+	ret = ocfs2_extend_rotate_transaction(handle, 0,
+					      handle->h_buffer_credits,
+					      path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access_path(inode, handle, path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path, &cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (cpos) {
+		/*
+		 * We have a path to the left of this one - it needs
+		 * an update too.
+		 */
+		left_path = ocfs2_new_path(path_root_bh(path),
+					   path_root_el(path));
+		if (!left_path) {
+			ret = -ENOMEM;
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ret = ocfs2_find_path(inode, left_path, cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ret = ocfs2_journal_access_path(inode, handle, left_path);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		subtree_index = ocfs2_find_subtree_root(inode, left_path, path);
+
+		ocfs2_unlink_subtree(inode, handle, left_path, path,
+				     subtree_index, dealloc);
+		ocfs2_update_edge_lengths(inode, handle, left_path);
+
+		eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+		di->i_last_eb_blk = eb->h_blkno;
+	} else {
+		/*
+		 * 'path' is also the leftmost path which
+		 * means it must be the only one. This gets
+		 * handled differently because we want to
+		 * revert the inode back to having extents
+		 * in-line.
+		 */
+		ocfs2_unlink_path(inode, handle, dealloc, path, 1);
+
+		el = &di->id2.i_list;
+		el->l_tree_depth = 0;
+		el->l_next_free_rec = 0;
+		memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+
+		di->i_last_eb_blk = 0;
+	}
+
+	ocfs2_journal_dirty(handle, path_root_bh(path));
+
+out:
+	ocfs2_free_path(left_path);
+	return ret;
+}
+
+/*
+ * Left rotation of btree records.
+ *
+ * In many ways, this is (unsurprisingly) the opposite of right
+ * rotation. We start at some non-rightmost path containing an empty
+ * extent in the leaf block. The code works its way to the rightmost
+ * path by rotating records to the left in every subtree.
+ *
+ * This is used by any code which reduces the number of extent records
+ * in a leaf. After removal, an empty record should be placed in the
+ * leftmost list position.
+ *
+ * This won't handle a length update of the rightmost path records if
+ * the rightmost tree leaf record is removed so the caller is
+ * responsible for detecting and correcting that.
+ */
+static int ocfs2_rotate_tree_left(struct inode *inode, handle_t *handle,
+				  struct ocfs2_path *path,
+				  struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret, orig_credits = handle->h_buffer_credits;
+	struct ocfs2_path *tmp_path = NULL, *restart_path = NULL;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_list *el;
+
+	el = path_leaf_el(path);
+	if (!ocfs2_is_empty_extent(&el->l_recs[0]))
+		return 0;
+
+	if (path->p_tree_depth == 0) {
+rightmost_no_delete:
+		/*
+		 * In-inode extents. This is trivially handled, so do
+		 * it up front.
+		 */
+		ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
+						       path_leaf_bh(path),
+						       path_leaf_el(path));
+		if (ret)
+			mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * Handle rightmost branch now. There's several cases:
+	 *  1) simple rotation leaving records in there. That's trivial.
+	 *  2) rotation requiring a branch delete - there's no more
+	 *     records left. Two cases of this:
+	 *     a) There are branches to the left.
+	 *     b) This is also the leftmost (the only) branch.
+	 *
+	 *  1) is handled via ocfs2_rotate_rightmost_leaf_left()
+	 *  2a) we need the left branch so that we can update it with the unlink
+	 *  2b) we need to bring the inode back to inline extents.
+	 */
+
+	eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+	el = &eb->h_list;
+	if (eb->h_next_leaf_blk == 0) {
+		/*
+		 * This gets a bit tricky if we're going to delete the
+		 * rightmost path. Get the other cases out of the way
+		 * 1st.
+		 */
+		if (le16_to_cpu(el->l_next_free_rec) > 1)
+			goto rightmost_no_delete;
+
+		if (le16_to_cpu(el->l_next_free_rec) == 0) {
+			ret = -EIO;
+			ocfs2_error(inode->i_sb,
+				    "Inode %llu has empty extent block at %llu",
+				    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+				    (unsigned long long)le64_to_cpu(eb->h_blkno));
+			goto out;
+		}
+
+		/*
+		 * XXX: The caller can not trust "path" any more after
+		 * this as it will have been deleted. What do we do?
+		 *
+		 * In theory the rotate-for-merge code will never get
+		 * here because it'll always ask for a rotate in a
+		 * nonempty list.
+		 */
+
+		ret = ocfs2_remove_rightmost_path(inode, handle, path,
+						  dealloc);
+		if (ret)
+			mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * Now we can loop, remembering the path we get from -EAGAIN
+	 * and restarting from there.
+	 */
+try_rotate:
+	ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits, path,
+				       dealloc, &restart_path);
+	if (ret && ret != -EAGAIN) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	while (ret == -EAGAIN) {
+		tmp_path = restart_path;
+		restart_path = NULL;
+
+		ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits,
+					       tmp_path, dealloc,
+					       &restart_path);
+		if (ret && ret != -EAGAIN) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		ocfs2_free_path(tmp_path);
+		tmp_path = NULL;
+
+		if (ret == 0)
+			goto try_rotate;
+	}
+
+out:
+	ocfs2_free_path(tmp_path);
+	ocfs2_free_path(restart_path);
+	return ret;
+}
+
+static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el,
+				int index)
+{
+	struct ocfs2_extent_rec *rec = &el->l_recs[index];
+	unsigned int size;
+
+	if (rec->e_leaf_clusters == 0) {
+		/*
+		 * We consumed all of the merged-from record. An empty
+		 * extent cannot exist anywhere but the 1st array
+		 * position, so move things over if the merged-from
+		 * record doesn't occupy that position.
+		 *
+		 * This creates a new empty extent so the caller
+		 * should be smart enough to have removed any existing
+		 * ones.
+		 */
+		if (index > 0) {
+			BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
+			size = index * sizeof(struct ocfs2_extent_rec);
+			memmove(&el->l_recs[1], &el->l_recs[0], size);
+		}
+
+		/*
+		 * Always memset - the caller doesn't check whether it
+		 * created an empty extent, so there could be junk in
+		 * the other fields.
+		 */
+		memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+	}
+}
+
+/*
+ * Remove split_rec clusters from the record at index and merge them
+ * onto the beginning of the record at index + 1.
+ */
+static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
+				handle_t *handle,
+				struct ocfs2_extent_rec *split_rec,
+				struct ocfs2_extent_list *el, int index)
+{
+	int ret;
+	unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+	struct ocfs2_extent_rec *left_rec;
+	struct ocfs2_extent_rec *right_rec;
+
+	BUG_ON(index >= le16_to_cpu(el->l_next_free_rec));
+
+	left_rec = &el->l_recs[index];
+	right_rec = &el->l_recs[index + 1];
+
+	ret = ocfs2_journal_access(handle, inode, bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	le16_add_cpu(&left_rec->e_leaf_clusters, -split_clusters);
+
+	le32_add_cpu(&right_rec->e_cpos, -split_clusters);
+	le64_add_cpu(&right_rec->e_blkno,
+		     -ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+	le16_add_cpu(&right_rec->e_leaf_clusters, split_clusters);
+
+	ocfs2_cleanup_merge(el, index);
+
+	ret = ocfs2_journal_dirty(handle, bh);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	return ret;
+}
+
+/*
+ * Remove split_rec clusters from the record at index and merge them
+ * onto the tail of the record at index - 1.
+ */
+static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
+				handle_t *handle,
+				struct ocfs2_extent_rec *split_rec,
+				struct ocfs2_extent_list *el, int index)
+{
+	int ret, has_empty_extent = 0;
+	unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+	struct ocfs2_extent_rec *left_rec;
+	struct ocfs2_extent_rec *right_rec;
+
+	BUG_ON(index <= 0);
+
+	left_rec = &el->l_recs[index - 1];
+	right_rec = &el->l_recs[index];
+	if (ocfs2_is_empty_extent(&el->l_recs[0]))
+		has_empty_extent = 1;
+
+	ret = ocfs2_journal_access(handle, inode, bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (has_empty_extent && index == 1) {
+		/*
+		 * The easy case - we can just plop the record right in.
+		 */
+		*left_rec = *split_rec;
+
+		has_empty_extent = 0;
+	} else {
+		le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters);
+	}
+
+	le32_add_cpu(&right_rec->e_cpos, split_clusters);
+	le64_add_cpu(&right_rec->e_blkno,
+		     ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+	le16_add_cpu(&right_rec->e_leaf_clusters, -split_clusters);
+
+	ocfs2_cleanup_merge(el, index);
+
+	ret = ocfs2_journal_dirty(handle, bh);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	return ret;
+}
+
+static int ocfs2_try_to_merge_extent(struct inode *inode,
+				     handle_t *handle,
+				     struct ocfs2_path *left_path,
+				     int split_index,
+				     struct ocfs2_extent_rec *split_rec,
+				     struct ocfs2_cached_dealloc_ctxt *dealloc,
+				     struct ocfs2_merge_ctxt *ctxt)
+
+{
+	int ret = 0, delete_tail_recs = 0;
+	struct ocfs2_extent_list *el = path_leaf_el(left_path);
+	struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+
+	BUG_ON(ctxt->c_contig_type == CONTIG_NONE);
+
+	if (ctxt->c_split_covers_rec) {
+		delete_tail_recs++;
+
+		if (ctxt->c_contig_type == CONTIG_LEFTRIGHT ||
+		    ctxt->c_has_empty_extent)
+			delete_tail_recs++;
+
+		if (ctxt->c_has_empty_extent) {
+			/*
+			 * The merge code will need to create an empty
+			 * extent to take the place of the newly
+			 * emptied slot. Remove any pre-existing empty
+			 * extents - having more than one in a leaf is
+			 * illegal.
+			 */
+			ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+						     dealloc);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+			split_index--;
+			rec = &el->l_recs[split_index];
+		}
+	}
+
+	if (ctxt->c_contig_type == CONTIG_LEFTRIGHT) {
+		/*
+		 * Left-right contig implies this.
+		 */
+		BUG_ON(!ctxt->c_split_covers_rec);
+		BUG_ON(split_index == 0);
+
+		/*
+		 * Since the leftright insert always covers the entire
+		 * extent, this call will delete the insert record
+		 * entirely, resulting in an empty extent record added to
+		 * the extent block.
+		 *
+		 * Since the adding of an empty extent shifts
+		 * everything back to the right, there's no need to
+		 * update split_index here.
+		 */
+		ret = ocfs2_merge_rec_left(inode, path_leaf_bh(left_path),
+					   handle, split_rec, el, split_index);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		/*
+		 * We can only get this from logic error above.
+		 */
+		BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+
+		/*
+		 * The left merge left us with an empty extent, remove
+		 * it.
+		 */
+		ret = ocfs2_rotate_tree_left(inode, handle, left_path, dealloc);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+		split_index--;
+		rec = &el->l_recs[split_index];
+
+		/*
+		 * Note that we don't pass split_rec here on purpose -
+		 * we've merged it into the left side.
+		 */
+		ret = ocfs2_merge_rec_right(inode, path_leaf_bh(left_path),
+					    handle, rec, el, split_index);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+
+		ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+					     dealloc);
+		/*
+		 * Error from this last rotate is not critical, so
+		 * print but don't bubble it up.
+		 */
+		if (ret)
+			mlog_errno(ret);
+		ret = 0;
+	} else {
+		/*
+		 * Merge a record to the left or right.
+		 *
+		 * 'contig_type' is relative to the existing record,
+		 * so for example, if we're "right contig", it's to
+		 * the record on the left (hence the left merge).
+		 */
+		if (ctxt->c_contig_type == CONTIG_RIGHT) {
+			ret = ocfs2_merge_rec_left(inode,
+						   path_leaf_bh(left_path),
+						   handle, split_rec, el,
+						   split_index);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+		} else {
+			ret = ocfs2_merge_rec_right(inode,
+						    path_leaf_bh(left_path),
+						    handle, split_rec, el,
+						    split_index);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+		}
+
+		if (ctxt->c_split_covers_rec) {
+			/*
+			 * The merge may have left an empty extent in
+			 * our leaf. Try to rotate it away.
+			 */
+			ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+						     dealloc);
+			if (ret)
+				mlog_errno(ret);
+			ret = 0;
+		}
+	}
+
+out:
+	return ret;
+}
+
+static void ocfs2_subtract_from_rec(struct super_block *sb,
+				    enum ocfs2_split_type split,
+				    struct ocfs2_extent_rec *rec,
+				    struct ocfs2_extent_rec *split_rec)
+{
+	u64 len_blocks;
+
+	len_blocks = ocfs2_clusters_to_blocks(sb,
+				le16_to_cpu(split_rec->e_leaf_clusters));
+
+	if (split == SPLIT_LEFT) {
+		/*
+		 * Region is on the left edge of the existing
+		 * record.
+		 */
+		le32_add_cpu(&rec->e_cpos,
+			     le16_to_cpu(split_rec->e_leaf_clusters));
+		le64_add_cpu(&rec->e_blkno, len_blocks);
+		le16_add_cpu(&rec->e_leaf_clusters,
+			     -le16_to_cpu(split_rec->e_leaf_clusters));
+	} else {
+		/*
+		 * Region is on the right edge of the existing
+		 * record.
+		 */
+		le16_add_cpu(&rec->e_leaf_clusters,
+			     -le16_to_cpu(split_rec->e_leaf_clusters));
+	}
+}
+
 /*
  * Do the final bits of extent record insertion at the target leaf
  * list. If this leaf is part of an allocation tree, it is assumed
@@ -1738,6 +2994,15 @@
 
 	BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
 
+	if (insert->ins_split != SPLIT_NONE) {
+		i = ocfs2_search_extent_list(el, le32_to_cpu(insert_rec->e_cpos));
+		BUG_ON(i == -1);
+		rec = &el->l_recs[i];
+		ocfs2_subtract_from_rec(inode->i_sb, insert->ins_split, rec,
+					insert_rec);
+		goto rotate;
+	}
+
 	/*
 	 * Contiguous insert - either left or right.
 	 */
@@ -1792,6 +3057,7 @@
 		return;
 	}
 
+rotate:
 	/*
 	 * Ok, we have to rotate.
 	 *
@@ -1815,13 +3081,53 @@
 	spin_unlock(&OCFS2_I(inode)->ip_lock);
 }
 
+static void ocfs2_adjust_rightmost_records(struct inode *inode,
+					   handle_t *handle,
+					   struct ocfs2_path *path,
+					   struct ocfs2_extent_rec *insert_rec)
+{
+	int ret, i, next_free;
+	struct buffer_head *bh;
+	struct ocfs2_extent_list *el;
+	struct ocfs2_extent_rec *rec;
+
+	/*
+	 * Update everything except the leaf block.
+	 */
+	for (i = 0; i < path->p_tree_depth; i++) {
+		bh = path->p_node[i].bh;
+		el = path->p_node[i].el;
+
+		next_free = le16_to_cpu(el->l_next_free_rec);
+		if (next_free == 0) {
+			ocfs2_error(inode->i_sb,
+				    "Dinode %llu has a bad extent list",
+				    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+			ret = -EIO;
+			return;
+		}
+
+		rec = &el->l_recs[next_free - 1];
+
+		rec->e_int_clusters = insert_rec->e_cpos;
+		le32_add_cpu(&rec->e_int_clusters,
+			     le16_to_cpu(insert_rec->e_leaf_clusters));
+		le32_add_cpu(&rec->e_int_clusters,
+			     -le32_to_cpu(rec->e_cpos));
+
+		ret = ocfs2_journal_dirty(handle, bh);
+		if (ret)
+			mlog_errno(ret);
+
+	}
+}
+
 static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
 				    struct ocfs2_extent_rec *insert_rec,
 				    struct ocfs2_path *right_path,
 				    struct ocfs2_path **ret_left_path)
 {
-	int ret, i, next_free;
-	struct buffer_head *bh;
+	int ret, next_free;
 	struct ocfs2_extent_list *el;
 	struct ocfs2_path *left_path = NULL;
 
@@ -1887,40 +3193,7 @@
 		goto out;
 	}
 
-	el = path_root_el(right_path);
-	bh = path_root_bh(right_path);
-	i = 0;
-	while (1) {
-		struct ocfs2_extent_rec *rec;
-
-		next_free = le16_to_cpu(el->l_next_free_rec);
-		if (next_free == 0) {
-			ocfs2_error(inode->i_sb,
-				    "Dinode %llu has a bad extent list",
-				    (unsigned long long)OCFS2_I(inode)->ip_blkno);
-			ret = -EIO;
-			goto out;
-		}
-
-		rec = &el->l_recs[next_free - 1];
-
-		rec->e_int_clusters = insert_rec->e_cpos;
-		le32_add_cpu(&rec->e_int_clusters,
-			     le16_to_cpu(insert_rec->e_leaf_clusters));
-		le32_add_cpu(&rec->e_int_clusters,
-			     -le32_to_cpu(rec->e_cpos));
-
-		ret = ocfs2_journal_dirty(handle, bh);
-		if (ret)
-			mlog_errno(ret);
-
-		/* Don't touch the leaf node */
-		if (++i >= right_path->p_tree_depth)
-			break;
-
-		bh = right_path->p_node[i].bh;
-		el = right_path->p_node[i].el;
-	}
+	ocfs2_adjust_rightmost_records(inode, handle, right_path, insert_rec);
 
 	*ret_left_path = left_path;
 	ret = 0;
@@ -1931,6 +3204,83 @@
 	return ret;
 }
 
+static void ocfs2_split_record(struct inode *inode,
+			       struct ocfs2_path *left_path,
+			       struct ocfs2_path *right_path,
+			       struct ocfs2_extent_rec *split_rec,
+			       enum ocfs2_split_type split)
+{
+	int index;
+	u32 cpos = le32_to_cpu(split_rec->e_cpos);
+	struct ocfs2_extent_list *left_el = NULL, *right_el, *insert_el, *el;
+	struct ocfs2_extent_rec *rec, *tmprec;
+
+	right_el = path_leaf_el(right_path);;
+	if (left_path)
+		left_el = path_leaf_el(left_path);
+
+	el = right_el;
+	insert_el = right_el;
+	index = ocfs2_search_extent_list(el, cpos);
+	if (index != -1) {
+		if (index == 0 && left_path) {
+			BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
+
+			/*
+			 * This typically means that the record
+			 * started in the left path but moved to the
+			 * right as a result of rotation. We either
+			 * move the existing record to the left, or we
+			 * do the later insert there.
+			 *
+			 * In this case, the left path should always
+			 * exist as the rotate code will have passed
+			 * it back for a post-insert update.
+			 */
+
+			if (split == SPLIT_LEFT) {
+				/*
+				 * It's a left split. Since we know
+				 * that the rotate code gave us an
+				 * empty extent in the left path, we
+				 * can just do the insert there.
+				 */
+				insert_el = left_el;
+			} else {
+				/*
+				 * Right split - we have to move the
+				 * existing record over to the left
+				 * leaf. The insert will be into the
+				 * newly created empty extent in the
+				 * right leaf.
+				 */
+				tmprec = &right_el->l_recs[index];
+				ocfs2_rotate_leaf(left_el, tmprec);
+				el = left_el;
+
+				memset(tmprec, 0, sizeof(*tmprec));
+				index = ocfs2_search_extent_list(left_el, cpos);
+				BUG_ON(index == -1);
+			}
+		}
+	} else {
+		BUG_ON(!left_path);
+		BUG_ON(!ocfs2_is_empty_extent(&left_el->l_recs[0]));
+		/*
+		 * Left path is easy - we can just allow the insert to
+		 * happen.
+		 */
+		el = left_el;
+		insert_el = left_el;
+		index = ocfs2_search_extent_list(el, cpos);
+		BUG_ON(index == -1);
+	}
+
+	rec = &el->l_recs[index];
+	ocfs2_subtract_from_rec(inode->i_sb, split, rec, split_rec);
+	ocfs2_rotate_leaf(insert_el, split_rec);
+}
+
 /*
  * This function only does inserts on an allocation b-tree. For dinode
  * lists, ocfs2_insert_at_leaf() is called directly.
@@ -1948,7 +3298,6 @@
 {
 	int ret, subtree_index;
 	struct buffer_head *leaf_bh = path_leaf_bh(right_path);
-	struct ocfs2_extent_list *el;
 
 	/*
 	 * Pass both paths to the journal. The majority of inserts
@@ -1984,9 +3333,18 @@
 		}
 	}
 
-	el = path_leaf_el(right_path);
+	if (insert->ins_split != SPLIT_NONE) {
+		/*
+		 * We could call ocfs2_insert_at_leaf() for some types
+		 * of splits, but it's easier to just let one seperate
+		 * function sort it all out.
+		 */
+		ocfs2_split_record(inode, left_path, right_path,
+				   insert_rec, insert->ins_split);
+	} else
+		ocfs2_insert_at_leaf(insert_rec, path_leaf_el(right_path),
+				     insert, inode);
 
-	ocfs2_insert_at_leaf(insert_rec, el, insert, inode);
 	ret = ocfs2_journal_dirty(handle, leaf_bh);
 	if (ret)
 		mlog_errno(ret);
@@ -2075,7 +3433,7 @@
 	 * can wind up skipping both of these two special cases...
 	 */
 	if (rotate) {
-		ret = ocfs2_rotate_tree_right(inode, handle,
+		ret = ocfs2_rotate_tree_right(inode, handle, type->ins_split,
 					      le32_to_cpu(insert_rec->e_cpos),
 					      right_path, &left_path);
 		if (ret) {
@@ -2100,8 +3458,9 @@
 	}
 
 out_update_clusters:
-	ocfs2_update_dinode_clusters(inode, di,
-				     le16_to_cpu(insert_rec->e_leaf_clusters));
+	if (type->ins_split == SPLIT_NONE)
+		ocfs2_update_dinode_clusters(inode, di,
+					     le16_to_cpu(insert_rec->e_leaf_clusters));
 
 	ret = ocfs2_journal_dirty(handle, di_bh);
 	if (ret)
@@ -2114,6 +3473,44 @@
 	return ret;
 }
 
+static enum ocfs2_contig_type
+ocfs2_figure_merge_contig_type(struct inode *inode,
+			       struct ocfs2_extent_list *el, int index,
+			       struct ocfs2_extent_rec *split_rec)
+{
+	struct ocfs2_extent_rec *rec;
+	enum ocfs2_contig_type ret = CONTIG_NONE;
+
+	/*
+	 * We're careful to check for an empty extent record here -
+	 * the merge code will know what to do if it sees one.
+	 */
+
+	if (index > 0) {
+		rec = &el->l_recs[index - 1];
+		if (index == 1 && ocfs2_is_empty_extent(rec)) {
+			if (split_rec->e_cpos == el->l_recs[index].e_cpos)
+				ret = CONTIG_RIGHT;
+		} else {
+			ret = ocfs2_extent_contig(inode, rec, split_rec);
+		}
+	}
+
+	if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) {
+		enum ocfs2_contig_type contig_type;
+
+		rec = &el->l_recs[index + 1];
+		contig_type = ocfs2_extent_contig(inode, rec, split_rec);
+
+		if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
+			ret = CONTIG_LEFTRIGHT;
+		else if (ret == CONTIG_NONE)
+			ret = contig_type;
+	}
+
+	return ret;
+}
+
 static void ocfs2_figure_contig_type(struct inode *inode,
 				     struct ocfs2_insert_type *insert,
 				     struct ocfs2_extent_list *el,
@@ -2205,6 +3602,8 @@
 	struct ocfs2_path *path = NULL;
 	struct buffer_head *bh = NULL;
 
+	insert->ins_split = SPLIT_NONE;
+
 	el = &di->id2.i_list;
 	insert->ins_tree_depth = le16_to_cpu(el->l_tree_depth);
 
@@ -2327,9 +3726,10 @@
 			u32 cpos,
 			u64 start_blk,
 			u32 new_clusters,
+			u8 flags,
 			struct ocfs2_alloc_context *meta_ac)
 {
-	int status, shift;
+	int status;
 	struct buffer_head *last_eb_bh = NULL;
 	struct buffer_head *bh = NULL;
 	struct ocfs2_insert_type insert = {0, };
@@ -2350,6 +3750,7 @@
 	rec.e_cpos = cpu_to_le32(cpos);
 	rec.e_blkno = cpu_to_le64(start_blk);
 	rec.e_leaf_clusters = cpu_to_le16(new_clusters);
+	rec.e_flags = flags;
 
 	status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
 					  &insert);
@@ -2364,55 +3765,16 @@
 	     insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
 	     insert.ins_free_records, insert.ins_tree_depth);
 
-	/*
-	 * Avoid growing the tree unless we're out of records and the
-	 * insert type requres one.
-	 */
-	if (insert.ins_contig != CONTIG_NONE || insert.ins_free_records)
-		goto out_add;
-
-	shift = ocfs2_find_branch_target(osb, inode, fe_bh, &bh);
-	if (shift < 0) {
-		status = shift;
-		mlog_errno(status);
-		goto bail;
-	}
-
-	/* We traveled all the way to the bottom of the allocation tree
-	 * and didn't find room for any more extents - we need to add
-	 * another tree level */
-	if (shift) {
-		BUG_ON(bh);
-		mlog(0, "need to shift tree depth "
-		     "(current = %d)\n", insert.ins_tree_depth);
-
-		/* ocfs2_shift_tree_depth will return us a buffer with
-		 * the new extent block (so we can pass that to
-		 * ocfs2_add_branch). */
-		status = ocfs2_shift_tree_depth(osb, handle, inode, fe_bh,
-						meta_ac, &bh);
-		if (status < 0) {
+	if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) {
+		status = ocfs2_grow_tree(inode, handle, fe_bh,
+					 &insert.ins_tree_depth, &last_eb_bh,
+					 meta_ac);
+		if (status) {
 			mlog_errno(status);
 			goto bail;
 		}
-		insert.ins_tree_depth++;
-		/* Special case: we have room now if we shifted from
-		 * tree_depth 0 */
-		if (insert.ins_tree_depth == 1)
-			goto out_add;
 	}
 
-	/* call ocfs2_add_branch to add the final part of the tree with
-	 * the new data. */
-	mlog(0, "add branch. bh = %p\n", bh);
-	status = ocfs2_add_branch(osb, handle, inode, fe_bh, bh, last_eb_bh,
-				  meta_ac);
-	if (status < 0) {
-		mlog_errno(status);
-		goto bail;
-	}
-
-out_add:
 	/* Finally, we can add clusters. This might rotate the tree for us. */
 	status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
 	if (status < 0)
@@ -2431,7 +3793,720 @@
 	return status;
 }
 
-static inline int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
+static void ocfs2_make_right_split_rec(struct super_block *sb,
+				       struct ocfs2_extent_rec *split_rec,
+				       u32 cpos,
+				       struct ocfs2_extent_rec *rec)
+{
+	u32 rec_cpos = le32_to_cpu(rec->e_cpos);
+	u32 rec_range = rec_cpos + le16_to_cpu(rec->e_leaf_clusters);
+
+	memset(split_rec, 0, sizeof(struct ocfs2_extent_rec));
+
+	split_rec->e_cpos = cpu_to_le32(cpos);
+	split_rec->e_leaf_clusters = cpu_to_le16(rec_range - cpos);
+
+	split_rec->e_blkno = rec->e_blkno;
+	le64_add_cpu(&split_rec->e_blkno,
+		     ocfs2_clusters_to_blocks(sb, cpos - rec_cpos));
+
+	split_rec->e_flags = rec->e_flags;
+}
+
+static int ocfs2_split_and_insert(struct inode *inode,
+				  handle_t *handle,
+				  struct ocfs2_path *path,
+				  struct buffer_head *di_bh,
+				  struct buffer_head **last_eb_bh,
+				  int split_index,
+				  struct ocfs2_extent_rec *orig_split_rec,
+				  struct ocfs2_alloc_context *meta_ac)
+{
+	int ret = 0, depth;
+	unsigned int insert_range, rec_range, do_leftright = 0;
+	struct ocfs2_extent_rec tmprec;
+	struct ocfs2_extent_list *rightmost_el;
+	struct ocfs2_extent_rec rec;
+	struct ocfs2_extent_rec split_rec = *orig_split_rec;
+	struct ocfs2_insert_type insert;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_dinode *di;
+
+leftright:
+	/*
+	 * Store a copy of the record on the stack - it might move
+	 * around as the tree is manipulated below.
+	 */
+	rec = path_leaf_el(path)->l_recs[split_index];
+
+	di = (struct ocfs2_dinode *)di_bh->b_data;
+	rightmost_el = &di->id2.i_list;
+
+	depth = le16_to_cpu(rightmost_el->l_tree_depth);
+	if (depth) {
+		BUG_ON(!(*last_eb_bh));
+		eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
+		rightmost_el = &eb->h_list;
+	}
+
+	if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
+	    le16_to_cpu(rightmost_el->l_count)) {
+		int old_depth = depth;
+
+		ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, last_eb_bh,
+				      meta_ac);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		if (old_depth != depth) {
+			eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
+			rightmost_el = &eb->h_list;
+		}
+	}
+
+	memset(&insert, 0, sizeof(struct ocfs2_insert_type));
+	insert.ins_appending = APPEND_NONE;
+	insert.ins_contig = CONTIG_NONE;
+	insert.ins_free_records = le16_to_cpu(rightmost_el->l_count)
+		- le16_to_cpu(rightmost_el->l_next_free_rec);
+	insert.ins_tree_depth = depth;
+
+	insert_range = le32_to_cpu(split_rec.e_cpos) +
+		le16_to_cpu(split_rec.e_leaf_clusters);
+	rec_range = le32_to_cpu(rec.e_cpos) +
+		le16_to_cpu(rec.e_leaf_clusters);
+
+	if (split_rec.e_cpos == rec.e_cpos) {
+		insert.ins_split = SPLIT_LEFT;
+	} else if (insert_range == rec_range) {
+		insert.ins_split = SPLIT_RIGHT;
+	} else {
+		/*
+		 * Left/right split. We fake this as a right split
+		 * first and then make a second pass as a left split.
+		 */
+		insert.ins_split = SPLIT_RIGHT;
+
+		ocfs2_make_right_split_rec(inode->i_sb, &tmprec, insert_range,
+					   &rec);
+
+		split_rec = tmprec;
+
+		BUG_ON(do_leftright);
+		do_leftright = 1;
+	}
+
+	ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec,
+				     &insert);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (do_leftright == 1) {
+		u32 cpos;
+		struct ocfs2_extent_list *el;
+
+		do_leftright++;
+		split_rec = *orig_split_rec;
+
+		ocfs2_reinit_path(path, 1);
+
+		cpos = le32_to_cpu(split_rec.e_cpos);
+		ret = ocfs2_find_path(inode, path, cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		el = path_leaf_el(path);
+		split_index = ocfs2_search_extent_list(el, cpos);
+		goto leftright;
+	}
+out:
+
+	return ret;
+}
+
+/*
+ * Mark part or all of the extent record at split_index in the leaf
+ * pointed to by path as written. This removes the unwritten
+ * extent flag.
+ *
+ * Care is taken to handle contiguousness so as to not grow the tree.
+ *
+ * meta_ac is not strictly necessary - we only truly need it if growth
+ * of the tree is required. All other cases will degrade into a less
+ * optimal tree layout.
+ *
+ * last_eb_bh should be the rightmost leaf block for any inode with a
+ * btree. Since a split may grow the tree or a merge might shrink it, the caller cannot trust the contents of that buffer after this call.
+ *
+ * This code is optimized for readability - several passes might be
+ * made over certain portions of the tree. All of those blocks will
+ * have been brought into cache (and pinned via the journal), so the
+ * extra overhead is not expressed in terms of disk reads.
+ */
+static int __ocfs2_mark_extent_written(struct inode *inode,
+				       struct buffer_head *di_bh,
+				       handle_t *handle,
+				       struct ocfs2_path *path,
+				       int split_index,
+				       struct ocfs2_extent_rec *split_rec,
+				       struct ocfs2_alloc_context *meta_ac,
+				       struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret = 0;
+	struct ocfs2_extent_list *el = path_leaf_el(path);
+	struct buffer_head *eb_bh, *last_eb_bh = NULL;
+	struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+	struct ocfs2_merge_ctxt ctxt;
+	struct ocfs2_extent_list *rightmost_el;
+
+	if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) {
+		ret = -EIO;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) ||
+	    ((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) <
+	     (le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) {
+		ret = -EIO;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	eb_bh = path_leaf_bh(path);
+	ret = ocfs2_journal_access(handle, inode, eb_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el,
+							    split_index,
+							    split_rec);
+
+	/*
+	 * The core merge / split code wants to know how much room is
+	 * left in this inodes allocation tree, so we pass the
+	 * rightmost extent list.
+	 */
+	if (path->p_tree_depth) {
+		struct ocfs2_extent_block *eb;
+		struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+
+		ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+				       le64_to_cpu(di->i_last_eb_blk),
+				       &last_eb_bh, OCFS2_BH_CACHED, inode);
+		if (ret) {
+			mlog_exit(ret);
+			goto out;
+		}
+
+		eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+		if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+			OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+			ret = -EROFS;
+			goto out;
+		}
+
+		rightmost_el = &eb->h_list;
+	} else
+		rightmost_el = path_root_el(path);
+
+	ctxt.c_used_tail_recs = le16_to_cpu(rightmost_el->l_next_free_rec);
+	if (ctxt.c_used_tail_recs > 0 &&
+	    ocfs2_is_empty_extent(&rightmost_el->l_recs[0]))
+		ctxt.c_used_tail_recs--;
+
+	if (rec->e_cpos == split_rec->e_cpos &&
+	    rec->e_leaf_clusters == split_rec->e_leaf_clusters)
+		ctxt.c_split_covers_rec = 1;
+	else
+		ctxt.c_split_covers_rec = 0;
+
+	ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]);
+
+	mlog(0, "index: %d, contig: %u, used_tail_recs: %u, "
+	     "has_empty: %u, split_covers: %u\n", split_index,
+	     ctxt.c_contig_type, ctxt.c_used_tail_recs,
+	     ctxt.c_has_empty_extent, ctxt.c_split_covers_rec);
+
+	if (ctxt.c_contig_type == CONTIG_NONE) {
+		if (ctxt.c_split_covers_rec)
+			el->l_recs[split_index] = *split_rec;
+		else
+			ret = ocfs2_split_and_insert(inode, handle, path, di_bh,
+						     &last_eb_bh, split_index,
+						     split_rec, meta_ac);
+		if (ret)
+			mlog_errno(ret);
+	} else {
+		ret = ocfs2_try_to_merge_extent(inode, handle, path,
+						split_index, split_rec,
+						dealloc, &ctxt);
+		if (ret)
+			mlog_errno(ret);
+	}
+
+	ocfs2_journal_dirty(handle, eb_bh);
+
+out:
+	brelse(last_eb_bh);
+	return ret;
+}
+
+/*
+ * Mark the already-existing extent at cpos as written for len clusters.
+ *
+ * If the existing extent is larger than the request, initiate a
+ * split. An attempt will be made at merging with adjacent extents.
+ *
+ * The caller is responsible for passing down meta_ac if we'll need it.
+ */
+int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+			      handle_t *handle, u32 cpos, u32 len, u32 phys,
+			      struct ocfs2_alloc_context *meta_ac,
+			      struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret, index;
+	u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
+	struct ocfs2_extent_rec split_rec;
+	struct ocfs2_path *left_path = NULL;
+	struct ocfs2_extent_list *el;
+
+	mlog(0, "Inode %lu cpos %u, len %u, phys %u (%llu)\n",
+	     inode->i_ino, cpos, len, phys, (unsigned long long)start_blkno);
+
+	if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
+		ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
+			    "that are being written to, but the feature bit "
+			    "is not set in the super block.",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+		ret = -EROFS;
+		goto out;
+	}
+
+	/*
+	 * XXX: This should be fixed up so that we just re-insert the
+	 * next extent records.
+	 */
+	ocfs2_extent_map_trunc(inode, 0);
+
+	left_path = ocfs2_new_inode_path(di_bh);
+	if (!left_path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_find_path(inode, left_path, cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+	el = path_leaf_el(left_path);
+
+	index = ocfs2_search_extent_list(el, cpos);
+	if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+		ocfs2_error(inode->i_sb,
+			    "Inode %llu has an extent at cpos %u which can no "
+			    "longer be found.\n",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+		ret = -EROFS;
+		goto out;
+	}
+
+	memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec));
+	split_rec.e_cpos = cpu_to_le32(cpos);
+	split_rec.e_leaf_clusters = cpu_to_le16(len);
+	split_rec.e_blkno = cpu_to_le64(start_blkno);
+	split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
+	split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
+
+	ret = __ocfs2_mark_extent_written(inode, di_bh, handle, left_path,
+					  index, &split_rec, meta_ac, dealloc);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	ocfs2_free_path(left_path);
+	return ret;
+}
+
+static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh,
+			    handle_t *handle, struct ocfs2_path *path,
+			    int index, u32 new_range,
+			    struct ocfs2_alloc_context *meta_ac)
+{
+	int ret, depth, credits = handle->h_buffer_credits;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+	struct buffer_head *last_eb_bh = NULL;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_list *rightmost_el, *el;
+	struct ocfs2_extent_rec split_rec;
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_insert_type insert;
+
+	/*
+	 * Setup the record to split before we grow the tree.
+	 */
+	el = path_leaf_el(path);
+	rec = &el->l_recs[index];
+	ocfs2_make_right_split_rec(inode->i_sb, &split_rec, new_range, rec);
+
+	depth = path->p_tree_depth;
+	if (depth > 0) {
+		ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+				       le64_to_cpu(di->i_last_eb_blk),
+				       &last_eb_bh, OCFS2_BH_CACHED, inode);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+		rightmost_el = &eb->h_list;
+	} else
+		rightmost_el = path_leaf_el(path);
+
+	credits += path->p_tree_depth + ocfs2_extend_meta_needed(di);
+	ret = ocfs2_extend_trans(handle, credits);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
+	    le16_to_cpu(rightmost_el->l_count)) {
+		int old_depth = depth;
+
+		ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, &last_eb_bh,
+				      meta_ac);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		if (old_depth != depth) {
+			eb = (struct ocfs2_extent_block *)last_eb_bh->b_data;
+			rightmost_el = &eb->h_list;
+		}
+	}
+
+	memset(&insert, 0, sizeof(struct ocfs2_insert_type));
+	insert.ins_appending = APPEND_NONE;
+	insert.ins_contig = CONTIG_NONE;
+	insert.ins_split = SPLIT_RIGHT;
+	insert.ins_free_records = le16_to_cpu(rightmost_el->l_count)
+		- le16_to_cpu(rightmost_el->l_next_free_rec);
+	insert.ins_tree_depth = depth;
+
+	ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec, &insert);
+	if (ret)
+		mlog_errno(ret);
+
+out:
+	brelse(last_eb_bh);
+	return ret;
+}
+
+static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
+			      struct ocfs2_path *path, int index,
+			      struct ocfs2_cached_dealloc_ctxt *dealloc,
+			      u32 cpos, u32 len)
+{
+	int ret;
+	u32 left_cpos, rec_range, trunc_range;
+	int wants_rotate = 0, is_rightmost_tree_rec = 0;
+	struct super_block *sb = inode->i_sb;
+	struct ocfs2_path *left_path = NULL;
+	struct ocfs2_extent_list *el = path_leaf_el(path);
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_extent_block *eb;
+
+	if (ocfs2_is_empty_extent(&el->l_recs[0]) && index > 0) {
+		ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		index--;
+	}
+
+	if (index == (le16_to_cpu(el->l_next_free_rec) - 1) &&
+	    path->p_tree_depth) {
+		/*
+		 * Check whether this is the rightmost tree record. If
+		 * we remove all of this record or part of its right
+		 * edge then an update of the record lengths above it
+		 * will be required.
+		 */
+		eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+		if (eb->h_next_leaf_blk == 0)
+			is_rightmost_tree_rec = 1;
+	}
+
+	rec = &el->l_recs[index];
+	if (index == 0 && path->p_tree_depth &&
+	    le32_to_cpu(rec->e_cpos) == cpos) {
+		/*
+		 * Changing the leftmost offset (via partial or whole
+		 * record truncate) of an interior (or rightmost) path
+		 * means we have to update the subtree that is formed
+		 * by this leaf and the one to it's left.
+		 *
+		 * There are two cases we can skip:
+		 *   1) Path is the leftmost one in our inode tree.
+		 *   2) The leaf is rightmost and will be empty after
+		 *      we remove the extent record - the rotate code
+		 *      knows how to update the newly formed edge.
+		 */
+
+		ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path,
+						    &left_cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		if (left_cpos && le16_to_cpu(el->l_next_free_rec) > 1) {
+			left_path = ocfs2_new_path(path_root_bh(path),
+						   path_root_el(path));
+			if (!left_path) {
+				ret = -ENOMEM;
+				mlog_errno(ret);
+				goto out;
+			}
+
+			ret = ocfs2_find_path(inode, left_path, left_cpos);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+		}
+	}
+
+	ret = ocfs2_extend_rotate_transaction(handle, 0,
+					      handle->h_buffer_credits,
+					      path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access_path(inode, handle, path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access_path(inode, handle, left_path);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	rec_range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+	trunc_range = cpos + len;
+
+	if (le32_to_cpu(rec->e_cpos) == cpos && rec_range == trunc_range) {
+		int next_free;
+
+		memset(rec, 0, sizeof(*rec));
+		ocfs2_cleanup_merge(el, index);
+		wants_rotate = 1;
+
+		next_free = le16_to_cpu(el->l_next_free_rec);
+		if (is_rightmost_tree_rec && next_free > 1) {
+			/*
+			 * We skip the edge update if this path will
+			 * be deleted by the rotate code.
+			 */
+			rec = &el->l_recs[next_free - 1];
+			ocfs2_adjust_rightmost_records(inode, handle, path,
+						       rec);
+		}
+	} else if (le32_to_cpu(rec->e_cpos) == cpos) {
+		/* Remove leftmost portion of the record. */
+		le32_add_cpu(&rec->e_cpos, len);
+		le64_add_cpu(&rec->e_blkno, ocfs2_clusters_to_blocks(sb, len));
+		le16_add_cpu(&rec->e_leaf_clusters, -len);
+	} else if (rec_range == trunc_range) {
+		/* Remove rightmost portion of the record */
+		le16_add_cpu(&rec->e_leaf_clusters, -len);
+		if (is_rightmost_tree_rec)
+			ocfs2_adjust_rightmost_records(inode, handle, path, rec);
+	} else {
+		/* Caller should have trapped this. */
+		mlog(ML_ERROR, "Inode %llu: Invalid record truncate: (%u, %u) "
+		     "(%u, %u)\n", (unsigned long long)OCFS2_I(inode)->ip_blkno,
+		     le32_to_cpu(rec->e_cpos),
+		     le16_to_cpu(rec->e_leaf_clusters), cpos, len);
+		BUG();
+	}
+
+	if (left_path) {
+		int subtree_index;
+
+		subtree_index = ocfs2_find_subtree_root(inode, left_path, path);
+		ocfs2_complete_edge_insert(inode, handle, left_path, path,
+					   subtree_index);
+	}
+
+	ocfs2_journal_dirty(handle, path_leaf_bh(path));
+
+	ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+out:
+	ocfs2_free_path(left_path);
+	return ret;
+}
+
+int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
+			u32 cpos, u32 len, handle_t *handle,
+			struct ocfs2_alloc_context *meta_ac,
+			struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret, index;
+	u32 rec_range, trunc_range;
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_extent_list *el;
+	struct ocfs2_path *path;
+
+	ocfs2_extent_map_trunc(inode, 0);
+
+	path = ocfs2_new_inode_path(di_bh);
+	if (!path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_find_path(inode, path, cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	el = path_leaf_el(path);
+	index = ocfs2_search_extent_list(el, cpos);
+	if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+		ocfs2_error(inode->i_sb,
+			    "Inode %llu has an extent at cpos %u which can no "
+			    "longer be found.\n",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+		ret = -EROFS;
+		goto out;
+	}
+
+	/*
+	 * We have 3 cases of extent removal:
+	 *   1) Range covers the entire extent rec
+	 *   2) Range begins or ends on one edge of the extent rec
+	 *   3) Range is in the middle of the extent rec (no shared edges)
+	 *
+	 * For case 1 we remove the extent rec and left rotate to
+	 * fill the hole.
+	 *
+	 * For case 2 we just shrink the existing extent rec, with a
+	 * tree update if the shrinking edge is also the edge of an
+	 * extent block.
+	 *
+	 * For case 3 we do a right split to turn the extent rec into
+	 * something case 2 can handle.
+	 */
+	rec = &el->l_recs[index];
+	rec_range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+	trunc_range = cpos + len;
+
+	BUG_ON(cpos < le32_to_cpu(rec->e_cpos) || trunc_range > rec_range);
+
+	mlog(0, "Inode %llu, remove (cpos %u, len %u). Existing index %d "
+	     "(cpos %u, len %u)\n",
+	     (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos, len, index,
+	     le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec));
+
+	if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) {
+		ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
+					 cpos, len);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	} else {
+		ret = ocfs2_split_tree(inode, di_bh, handle, path, index,
+				       trunc_range, meta_ac);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		/*
+		 * The split could have manipulated the tree enough to
+		 * move the record location, so we have to look for it again.
+		 */
+		ocfs2_reinit_path(path, 1);
+
+		ret = ocfs2_find_path(inode, path, cpos);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		el = path_leaf_el(path);
+		index = ocfs2_search_extent_list(el, cpos);
+		if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+			ocfs2_error(inode->i_sb,
+				    "Inode %llu: split at cpos %u lost record.",
+				    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+				    cpos);
+			ret = -EROFS;
+			goto out;
+		}
+
+		/*
+		 * Double check our values here. If anything is fishy,
+		 * it's easier to catch it at the top level.
+		 */
+		rec = &el->l_recs[index];
+		rec_range = le32_to_cpu(rec->e_cpos) +
+			ocfs2_rec_clusters(el, rec);
+		if (rec_range != trunc_range) {
+			ocfs2_error(inode->i_sb,
+				    "Inode %llu: error after split at cpos %u"
+				    "trunc len %u, existing record is (%u,%u)",
+				    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+				    cpos, len, le32_to_cpu(rec->e_cpos),
+				    ocfs2_rec_clusters(el, rec));
+			ret = -EROFS;
+			goto out;
+		}
+
+		ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
+					 cpos, len);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	}
+
+out:
+	ocfs2_free_path(path);
+	return ret;
+}
+
+int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
 {
 	struct buffer_head *tl_bh = osb->osb_tl_bh;
 	struct ocfs2_dinode *di;
@@ -2464,10 +4539,10 @@
 	return current_tail == new_start;
 }
 
-static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
-				     handle_t *handle,
-				     u64 start_blk,
-				     unsigned int num_clusters)
+int ocfs2_truncate_log_append(struct ocfs2_super *osb,
+			      handle_t *handle,
+			      u64 start_blk,
+			      unsigned int num_clusters)
 {
 	int status, index;
 	unsigned int start_cluster, tl_count;
@@ -2623,7 +4698,7 @@
 }
 
 /* Expects you to already be holding tl_inode->i_mutex */
-static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
+int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
 {
 	int status;
 	unsigned int num_to_flush;
@@ -2957,6 +5032,219 @@
 	return status;
 }
 
+/*
+ * Delayed de-allocation of suballocator blocks.
+ *
+ * Some sets of block de-allocations might involve multiple suballocator inodes.
+ *
+ * The locking for this can get extremely complicated, especially when
+ * the suballocator inodes to delete from aren't known until deep
+ * within an unrelated codepath.
+ *
+ * ocfs2_extent_block structures are a good example of this - an inode
+ * btree could have been grown by any number of nodes each allocating
+ * out of their own suballoc inode.
+ *
+ * These structures allow the delay of block de-allocation until a
+ * later time, when locking of multiple cluster inodes won't cause
+ * deadlock.
+ */
+
+/*
+ * Describes a single block free from a suballocator
+ */
+struct ocfs2_cached_block_free {
+	struct ocfs2_cached_block_free		*free_next;
+	u64					free_blk;
+	unsigned int				free_bit;
+};
+
+struct ocfs2_per_slot_free_list {
+	struct ocfs2_per_slot_free_list		*f_next_suballocator;
+	int					f_inode_type;
+	int					f_slot;
+	struct ocfs2_cached_block_free		*f_first;
+};
+
+static int ocfs2_free_cached_items(struct ocfs2_super *osb,
+				   int sysfile_type,
+				   int slot,
+				   struct ocfs2_cached_block_free *head)
+{
+	int ret;
+	u64 bg_blkno;
+	handle_t *handle;
+	struct inode *inode;
+	struct buffer_head *di_bh = NULL;
+	struct ocfs2_cached_block_free *tmp;
+
+	inode = ocfs2_get_system_file_inode(osb, sysfile_type, slot);
+	if (!inode) {
+		ret = -EINVAL;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	mutex_lock(&inode->i_mutex);
+
+	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_mutex;
+	}
+
+	handle = ocfs2_start_trans(osb, OCFS2_SUBALLOC_FREE);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		mlog_errno(ret);
+		goto out_unlock;
+	}
+
+	while (head) {
+		bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
+						      head->free_bit);
+		mlog(0, "Free bit: (bit %u, blkno %llu)\n",
+		     head->free_bit, (unsigned long long)head->free_blk);
+
+		ret = ocfs2_free_suballoc_bits(handle, inode, di_bh,
+					       head->free_bit, bg_blkno, 1);
+		if (ret) {
+			mlog_errno(ret);
+			goto out_journal;
+		}
+
+		ret = ocfs2_extend_trans(handle, OCFS2_SUBALLOC_FREE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out_journal;
+		}
+
+		tmp = head;
+		head = head->free_next;
+		kfree(tmp);
+	}
+
+out_journal:
+	ocfs2_commit_trans(osb, handle);
+
+out_unlock:
+	ocfs2_meta_unlock(inode, 1);
+	brelse(di_bh);
+out_mutex:
+	mutex_unlock(&inode->i_mutex);
+	iput(inode);
+out:
+	while(head) {
+		/* Premature exit may have left some dangling items. */
+		tmp = head;
+		head = head->free_next;
+		kfree(tmp);
+	}
+
+	return ret;
+}
+
+int ocfs2_run_deallocs(struct ocfs2_super *osb,
+		       struct ocfs2_cached_dealloc_ctxt *ctxt)
+{
+	int ret = 0, ret2;
+	struct ocfs2_per_slot_free_list *fl;
+
+	if (!ctxt)
+		return 0;
+
+	while (ctxt->c_first_suballocator) {
+		fl = ctxt->c_first_suballocator;
+
+		if (fl->f_first) {
+			mlog(0, "Free items: (type %u, slot %d)\n",
+			     fl->f_inode_type, fl->f_slot);
+			ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type,
+						       fl->f_slot, fl->f_first);
+			if (ret2)
+				mlog_errno(ret2);
+			if (!ret)
+				ret = ret2;
+		}
+
+		ctxt->c_first_suballocator = fl->f_next_suballocator;
+		kfree(fl);
+	}
+
+	return ret;
+}
+
+static struct ocfs2_per_slot_free_list *
+ocfs2_find_per_slot_free_list(int type,
+			      int slot,
+			      struct ocfs2_cached_dealloc_ctxt *ctxt)
+{
+	struct ocfs2_per_slot_free_list *fl = ctxt->c_first_suballocator;
+
+	while (fl) {
+		if (fl->f_inode_type == type && fl->f_slot == slot)
+			return fl;
+
+		fl = fl->f_next_suballocator;
+	}
+
+	fl = kmalloc(sizeof(*fl), GFP_NOFS);
+	if (fl) {
+		fl->f_inode_type = type;
+		fl->f_slot = slot;
+		fl->f_first = NULL;
+		fl->f_next_suballocator = ctxt->c_first_suballocator;
+
+		ctxt->c_first_suballocator = fl;
+	}
+	return fl;
+}
+
+static int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
+				     int type, int slot, u64 blkno,
+				     unsigned int bit)
+{
+	int ret;
+	struct ocfs2_per_slot_free_list *fl;
+	struct ocfs2_cached_block_free *item;
+
+	fl = ocfs2_find_per_slot_free_list(type, slot, ctxt);
+	if (fl == NULL) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	item = kmalloc(sizeof(*item), GFP_NOFS);
+	if (item == NULL) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n",
+	     type, slot, bit, (unsigned long long)blkno);
+
+	item->free_blk = blkno;
+	item->free_bit = bit;
+	item->free_next = fl->f_first;
+
+	fl->f_first = item;
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
+					 struct ocfs2_extent_block *eb)
+{
+	return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
+					 le16_to_cpu(eb->h_suballoc_slot),
+					 le64_to_cpu(eb->h_blkno),
+					 le16_to_cpu(eb->h_suballoc_bit));
+}
+
 /* This function will figure out whether the currently last extent
  * block will be deleted, and if it will, what the new last extent
  * block will be so we can update his h_next_leaf_blk field, as well
@@ -3238,27 +5526,10 @@
 			BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
 			BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));
 
-			if (le16_to_cpu(eb->h_suballoc_slot) == 0) {
-				/*
-				 * This code only understands how to
-				 * lock the suballocator in slot 0,
-				 * which is fine because allocation is
-				 * only ever done out of that
-				 * suballocator too. A future version
-				 * might change that however, so avoid
-				 * a free if we don't know how to
-				 * handle it. This way an fs incompat
-				 * bit will not be necessary.
-				 */
-				ret = ocfs2_free_extent_block(handle,
-							      tc->tc_ext_alloc_inode,
-							      tc->tc_ext_alloc_bh,
-							      eb);
-
-				/* An error here is not fatal. */
-				if (ret < 0)
-					mlog_errno(ret);
-			}
+			ret = ocfs2_cache_extent_block_free(&tc->tc_dealloc, eb);
+			/* An error here is not fatal. */
+			if (ret < 0)
+				mlog_errno(ret);
 		} else {
 			deleted_eb = 0;
 		}
@@ -3397,9 +5668,9 @@
 	return ocfs2_journal_dirty_data(handle, bh);
 }
 
-static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize,
-				     struct page **pages, int numpages,
-				     u64 phys, handle_t *handle)
+static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start,
+				     loff_t end, struct page **pages,
+				     int numpages, u64 phys, handle_t *handle)
 {
 	int i, ret, partial = 0;
 	void *kaddr;
@@ -3412,26 +5683,14 @@
 	if (numpages == 0)
 		goto out;
 
-	from = isize & (PAGE_CACHE_SIZE - 1); /* 1st page offset */
-	if (PAGE_CACHE_SHIFT > OCFS2_SB(sb)->s_clustersize_bits) {
-		/*
-		 * Since 'from' has been capped to a value below page
-		 * size, this calculation won't be able to overflow
-		 * 'to'
-		 */
-		to = ocfs2_align_bytes_to_clusters(sb, from);
-
-		/*
-		 * The truncate tail in this case should never contain
-		 * more than one page at maximum. The loop below also
-		 * assumes this.
-		 */
-		BUG_ON(numpages != 1);
-	}
-
+	to = PAGE_CACHE_SIZE;
 	for(i = 0; i < numpages; i++) {
 		page = pages[i];
 
+		from = start & (PAGE_CACHE_SIZE - 1);
+		if ((end >> PAGE_CACHE_SHIFT) == page->index)
+			to = end & (PAGE_CACHE_SIZE - 1);
+
 		BUG_ON(from > PAGE_CACHE_SIZE);
 		BUG_ON(to > PAGE_CACHE_SIZE);
 
@@ -3468,10 +5727,7 @@
 
 		flush_dcache_page(page);
 
-		/*
-		 * Every page after the 1st one should be completely zero'd.
-		 */
-		from = 0;
+		start = (page->index + 1) << PAGE_CACHE_SHIFT;
 	}
 out:
 	if (pages) {
@@ -3484,24 +5740,26 @@
 	}
 }
 
-static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page **pages,
-				int *num, u64 *phys)
+static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
+				struct page **pages, int *num, u64 *phys)
 {
 	int i, numpages = 0, ret = 0;
-	unsigned int csize = OCFS2_SB(inode->i_sb)->s_clustersize;
 	unsigned int ext_flags;
 	struct super_block *sb = inode->i_sb;
 	struct address_space *mapping = inode->i_mapping;
 	unsigned long index;
-	u64 next_cluster_bytes;
+	loff_t last_page_bytes;
 
 	BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(sb)));
+	BUG_ON(start > end);
 
-	/* Cluster boundary, so we don't need to grab any pages. */
-	if ((isize & (csize - 1)) == 0)
+	if (start == end)
 		goto out;
 
-	ret = ocfs2_extent_map_get_blocks(inode, isize >> sb->s_blocksize_bits,
+	BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
+	       (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
+
+	ret = ocfs2_extent_map_get_blocks(inode, start >> sb->s_blocksize_bits,
 					  phys, NULL, &ext_flags);
 	if (ret) {
 		mlog_errno(ret);
@@ -3517,8 +5775,8 @@
 	if (ext_flags & OCFS2_EXT_UNWRITTEN)
 		goto out;
 
-	next_cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, isize);
-	index = isize >> PAGE_CACHE_SHIFT;
+	last_page_bytes = PAGE_ALIGN(end);
+	index = start >> PAGE_CACHE_SHIFT;
 	do {
 		pages[numpages] = grab_cache_page(mapping, index);
 		if (!pages[numpages]) {
@@ -3529,7 +5787,7 @@
 
 		numpages++;
 		index++;
-	} while (index < (next_cluster_bytes >> PAGE_CACHE_SHIFT));
+	} while (index < (last_page_bytes >> PAGE_CACHE_SHIFT));
 
 out:
 	if (ret != 0) {
@@ -3558,11 +5816,10 @@
  * otherwise block_write_full_page() will skip writeout of pages past
  * i_size. The new_i_size parameter is passed for this reason.
  */
-int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
-				 u64 new_i_size)
+int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
+				  u64 range_start, u64 range_end)
 {
 	int ret, numpages;
-	loff_t endbyte;
 	struct page **pages = NULL;
 	u64 phys;
 
@@ -3581,7 +5838,8 @@
 		goto out;
 	}
 
-	ret = ocfs2_grab_eof_pages(inode, new_i_size, pages, &numpages, &phys);
+	ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages,
+				   &numpages, &phys);
 	if (ret) {
 		mlog_errno(ret);
 		goto out;
@@ -3590,17 +5848,16 @@
 	if (numpages == 0)
 		goto out;
 
-	ocfs2_zero_cluster_pages(inode, new_i_size, pages, numpages, phys,
-				 handle);
+	ocfs2_zero_cluster_pages(inode, range_start, range_end, pages,
+				 numpages, phys, handle);
 
 	/*
 	 * Initiate writeout of the pages we zero'd here. We don't
 	 * wait on them - the truncate_inode_pages() call later will
 	 * do that for us.
 	 */
-	endbyte = ocfs2_align_bytes_to_clusters(inode->i_sb, new_i_size);
-	ret = do_sync_mapping_range(inode->i_mapping, new_i_size,
-				    endbyte - 1, SYNC_FILE_RANGE_WRITE);
+	ret = do_sync_mapping_range(inode->i_mapping, range_start,
+				    range_end - 1, SYNC_FILE_RANGE_WRITE);
 	if (ret)
 		mlog_errno(ret);
 
@@ -3631,8 +5888,6 @@
 
 	mlog_entry_void();
 
-	down_write(&OCFS2_I(inode)->ip_alloc_sem);
-
 	new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
 						     i_size_read(inode));
 
@@ -3754,7 +6009,6 @@
 	goto start;
 
 bail:
-	up_write(&OCFS2_I(inode)->ip_alloc_sem);
 
 	ocfs2_schedule_truncate_log_flush(osb, 1);
 
@@ -3764,6 +6018,8 @@
 	if (handle)
 		ocfs2_commit_trans(osb, handle);
 
+	ocfs2_run_deallocs(osb, &tc->tc_dealloc);
+
 	ocfs2_free_path(path);
 
 	/* This will drop the ext_alloc cluster lock for us */
@@ -3774,23 +6030,18 @@
 }
 
 /*
- * Expects the inode to already be locked. This will figure out which
- * inodes need to be locked and will put them on the returned truncate
- * context.
+ * Expects the inode to already be locked.
  */
 int ocfs2_prepare_truncate(struct ocfs2_super *osb,
 			   struct inode *inode,
 			   struct buffer_head *fe_bh,
 			   struct ocfs2_truncate_context **tc)
 {
-	int status, metadata_delete, i;
+	int status;
 	unsigned int new_i_clusters;
 	struct ocfs2_dinode *fe;
 	struct ocfs2_extent_block *eb;
-	struct ocfs2_extent_list *el;
 	struct buffer_head *last_eb_bh = NULL;
-	struct inode *ext_alloc_inode = NULL;
-	struct buffer_head *ext_alloc_bh = NULL;
 
 	mlog_entry_void();
 
@@ -3810,12 +6061,9 @@
 		mlog_errno(status);
 		goto bail;
 	}
+	ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
 
-	metadata_delete = 0;
 	if (fe->id2.i_list.l_tree_depth) {
-		/* If we have a tree, then the truncate may result in
-		 * metadata deletes. Figure this out from the
-		 * rightmost leaf block.*/
 		status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
 					  &last_eb_bh, OCFS2_BH_CACHED, inode);
 		if (status < 0) {
@@ -3830,43 +6078,10 @@
 			status = -EIO;
 			goto bail;
 		}
-		el = &(eb->h_list);
-
-		i = 0;
-		if (ocfs2_is_empty_extent(&el->l_recs[0]))
-			i = 1;
-		/*
-		 * XXX: Should we check that next_free_rec contains
-		 * the extent?
-		 */
-		if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_i_clusters)
-			metadata_delete = 1;
 	}
 
 	(*tc)->tc_last_eb_bh = last_eb_bh;
 
-	if (metadata_delete) {
-		mlog(0, "Will have to delete metadata for this trunc. "
-		     "locking allocator.\n");
-		ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);
-		if (!ext_alloc_inode) {
-			status = -ENOMEM;
-			mlog_errno(status);
-			goto bail;
-		}
-
-		mutex_lock(&ext_alloc_inode->i_mutex);
-		(*tc)->tc_ext_alloc_inode = ext_alloc_inode;
-
-		status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
-		if (status < 0) {
-			mlog_errno(status);
-			goto bail;
-		}
-		(*tc)->tc_ext_alloc_bh = ext_alloc_bh;
-		(*tc)->tc_ext_alloc_locked = 1;
-	}
-
 	status = 0;
 bail:
 	if (status < 0) {
@@ -3880,16 +6095,13 @@
 
 static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
 {
-	if (tc->tc_ext_alloc_inode) {
-		if (tc->tc_ext_alloc_locked)
-			ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1);
-
-		mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex);
-		iput(tc->tc_ext_alloc_inode);
-	}
-
-	if (tc->tc_ext_alloc_bh)
-		brelse(tc->tc_ext_alloc_bh);
+	/*
+	 * The caller is responsible for completing deallocation
+	 * before freeing the context.
+	 */
+	if (tc->tc_dealloc.c_first_suballocator != NULL)
+		mlog(ML_NOTICE,
+		     "Truncate completion has non-empty dealloc context\n");
 
 	if (tc->tc_last_eb_bh)
 		brelse(tc->tc_last_eb_bh);
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
index fbcb593..990df48 100644
--- a/fs/ocfs2/alloc.h
+++ b/fs/ocfs2/alloc.h
@@ -34,7 +34,17 @@
 			u32 cpos,
 			u64 start_blk,
 			u32 new_clusters,
+			u8 flags,
 			struct ocfs2_alloc_context *meta_ac);
+struct ocfs2_cached_dealloc_ctxt;
+int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+			      handle_t *handle, u32 cpos, u32 len, u32 phys,
+			      struct ocfs2_alloc_context *meta_ac,
+			      struct ocfs2_cached_dealloc_ctxt *dealloc);
+int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
+			u32 cpos, u32 len, handle_t *handle,
+			struct ocfs2_alloc_context *meta_ac,
+			struct ocfs2_cached_dealloc_ctxt *dealloc);
 int ocfs2_num_free_extents(struct ocfs2_super *osb,
 			   struct inode *inode,
 			   struct ocfs2_dinode *fe);
@@ -62,17 +72,41 @@
 				      struct ocfs2_dinode **tl_copy);
 int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
 					 struct ocfs2_dinode *tl_copy);
+int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb);
+int ocfs2_truncate_log_append(struct ocfs2_super *osb,
+			      handle_t *handle,
+			      u64 start_blk,
+			      unsigned int num_clusters);
+int __ocfs2_flush_truncate_log(struct ocfs2_super *osb);
+
+/*
+ * Process local structure which describes the block unlinks done
+ * during an operation. This is populated via
+ * ocfs2_cache_block_dealloc().
+ *
+ * ocfs2_run_deallocs() should be called after the potentially
+ * de-allocating routines. No journal handles should be open, and most
+ * locks should have been dropped.
+ */
+struct ocfs2_cached_dealloc_ctxt {
+	struct ocfs2_per_slot_free_list		*c_first_suballocator;
+};
+static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
+{
+	c->c_first_suballocator = NULL;
+}
+int ocfs2_run_deallocs(struct ocfs2_super *osb,
+		       struct ocfs2_cached_dealloc_ctxt *ctxt);
 
 struct ocfs2_truncate_context {
-	struct inode *tc_ext_alloc_inode;
-	struct buffer_head *tc_ext_alloc_bh;
+	struct ocfs2_cached_dealloc_ctxt tc_dealloc;
 	int tc_ext_alloc_locked; /* is it cluster locked? */
 	/* these get destroyed once it's passed to ocfs2_commit_truncate. */
 	struct buffer_head *tc_last_eb_bh;
 };
 
-int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
-				 u64 new_i_size);
+int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
+				  u64 range_start, u64 range_end);
 int ocfs2_prepare_truncate(struct ocfs2_super *osb,
 			   struct inode *inode,
 			   struct buffer_head *fe_bh,
@@ -84,6 +118,7 @@
 
 int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
 		    u32 cpos, struct buffer_head **leaf_bh);
+int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster);
 
 /*
  * Helper function to look at the # of clusters in an extent record.
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 8e7cafb5..84bf6e7 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -222,7 +222,10 @@
 		goto out;
 	}
 
-	down_read(&OCFS2_I(inode)->ip_alloc_sem);
+	if (down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem) == 0) {
+		ret = AOP_TRUNCATED_PAGE;
+		goto out_meta_unlock;
+	}
 
 	/*
 	 * i_size might have just been updated as we grabed the meta lock.  We
@@ -235,10 +238,7 @@
 	 * XXX sys_readahead() seems to get that wrong?
 	 */
 	if (start >= i_size_read(inode)) {
-		char *addr = kmap(page);
-		memset(addr, 0, PAGE_SIZE);
-		flush_dcache_page(page);
-		kunmap(page);
+		zero_user_page(page, 0, PAGE_SIZE, KM_USER0);
 		SetPageUptodate(page);
 		ret = 0;
 		goto out_alloc;
@@ -258,6 +258,7 @@
 	ocfs2_data_unlock(inode, 0);
 out_alloc:
 	up_read(&OCFS2_I(inode)->ip_alloc_sem);
+out_meta_unlock:
 	ocfs2_meta_unlock(inode, 0);
 out:
 	if (unlock)
@@ -683,6 +684,8 @@
 	     bh = bh->b_this_page, block_start += bsize) {
 		block_end = block_start + bsize;
 
+		clear_buffer_new(bh);
+
 		/*
 		 * Ignore blocks outside of our i/o range -
 		 * they may belong to unallocated clusters.
@@ -697,9 +700,8 @@
 		 * For an allocating write with cluster size >= page
 		 * size, we always write the entire page.
 		 */
-
-		if (buffer_new(bh))
-			clear_buffer_new(bh);
+		if (new)
+			set_buffer_new(bh);
 
 		if (!buffer_mapped(bh)) {
 			map_bh(bh, inode->i_sb, *p_blkno);
@@ -710,7 +712,8 @@
 			if (!buffer_uptodate(bh))
 				set_buffer_uptodate(bh);
 		} else if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
-		     (block_start < from || block_end > to)) {
+			   !buffer_new(bh) &&
+			   (block_start < from || block_end > to)) {
 			ll_rw_block(READ, 1, &bh);
 			*wait_bh++=bh;
 		}
@@ -737,18 +740,13 @@
 	bh = head;
 	block_start = 0;
 	do {
-		void *kaddr;
-
 		block_end = block_start + bsize;
 		if (block_end <= from)
 			goto next_bh;
 		if (block_start >= to)
 			break;
 
-		kaddr = kmap_atomic(page, KM_USER0);
-		memset(kaddr+block_start, 0, bh->b_size);
-		flush_dcache_page(page);
-		kunmap_atomic(kaddr, KM_USER0);
+		zero_user_page(page, block_start, bh->b_size, KM_USER0);
 		set_buffer_uptodate(bh);
 		mark_buffer_dirty(bh);
 
@@ -760,217 +758,240 @@
 	return ret;
 }
 
+#if (PAGE_CACHE_SIZE >= OCFS2_MAX_CLUSTERSIZE)
+#define OCFS2_MAX_CTXT_PAGES	1
+#else
+#define OCFS2_MAX_CTXT_PAGES	(OCFS2_MAX_CLUSTERSIZE / PAGE_CACHE_SIZE)
+#endif
+
+#define OCFS2_MAX_CLUSTERS_PER_PAGE	(PAGE_CACHE_SIZE / OCFS2_MIN_CLUSTERSIZE)
+
 /*
- * This will copy user data from the buffer page in the splice
- * context.
- *
- * For now, we ignore SPLICE_F_MOVE as that would require some extra
- * communication out all the way to ocfs2_write().
+ * Describe the state of a single cluster to be written to.
  */
-int ocfs2_map_and_write_splice_data(struct inode *inode,
-				  struct ocfs2_write_ctxt *wc, u64 *p_blkno,
-				  unsigned int *ret_from, unsigned int *ret_to)
+struct ocfs2_write_cluster_desc {
+	u32		c_cpos;
+	u32		c_phys;
+	/*
+	 * Give this a unique field because c_phys eventually gets
+	 * filled.
+	 */
+	unsigned	c_new;
+	unsigned	c_unwritten;
+};
+
+static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
 {
-	int ret;
-	unsigned int to, from, cluster_start, cluster_end;
-	char *src, *dst;
-	struct ocfs2_splice_write_priv *sp = wc->w_private;
-	struct pipe_buffer *buf = sp->s_buf;
-	unsigned long bytes, src_from;
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-
-	ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
-					&cluster_end);
-
-	from = sp->s_offset;
-	src_from = sp->s_buf_offset;
-	bytes = wc->w_count;
-
-	if (wc->w_large_pages) {
-		/*
-		 * For cluster size < page size, we have to
-		 * calculate pos within the cluster and obey
-		 * the rightmost boundary.
-		 */
-		bytes = min(bytes, (unsigned long)(osb->s_clustersize
-				   - (wc->w_pos & (osb->s_clustersize - 1))));
-	}
-	to = from + bytes;
-
-	if (wc->w_this_page_new)
-		ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
-					    cluster_start, cluster_end, 1);
-	else
-		ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
-					    from, to, 0);
-	if (ret) {
-		mlog_errno(ret);
-		goto out;
-	}
-
-	BUG_ON(from > PAGE_CACHE_SIZE);
-	BUG_ON(to > PAGE_CACHE_SIZE);
-	BUG_ON(from > osb->s_clustersize);
-	BUG_ON(to > osb->s_clustersize);
-
-	src = buf->ops->map(sp->s_pipe, buf, 1);
-	dst = kmap_atomic(wc->w_this_page, KM_USER1);
-	memcpy(dst + from, src + src_from, bytes);
-	kunmap_atomic(wc->w_this_page, KM_USER1);
-	buf->ops->unmap(sp->s_pipe, buf, src);
-
-	wc->w_finished_copy = 1;
-
-	*ret_from = from;
-	*ret_to = to;
-out:
-
-	return bytes ? (unsigned int)bytes : ret;
+	return d->c_new || d->c_unwritten;
 }
 
-/*
- * This will copy user data from the iovec in the buffered write
- * context.
- */
-int ocfs2_map_and_write_user_data(struct inode *inode,
-				  struct ocfs2_write_ctxt *wc, u64 *p_blkno,
-				  unsigned int *ret_from, unsigned int *ret_to)
-{
-	int ret;
-	unsigned int to, from, cluster_start, cluster_end;
-	unsigned long bytes, src_from;
-	char *dst;
-	struct ocfs2_buffered_write_priv *bp = wc->w_private;
-	const struct iovec *cur_iov = bp->b_cur_iov;
-	char __user *buf;
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+struct ocfs2_write_ctxt {
+	/* Logical cluster position / len of write */
+	u32				w_cpos;
+	u32				w_clen;
 
-	ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
-					&cluster_end);
-
-	buf = cur_iov->iov_base + bp->b_cur_off;
-	src_from = (unsigned long)buf & ~PAGE_CACHE_MASK;
-
-	from = wc->w_pos & (PAGE_CACHE_SIZE - 1);
+	struct ocfs2_write_cluster_desc	w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
 
 	/*
-	 * This is a lot of comparisons, but it reads quite
-	 * easily, which is important here.
-	 */
-	/* Stay within the src page */
-	bytes = PAGE_SIZE - src_from;
-	/* Stay within the vector */
-	bytes = min(bytes,
-		    (unsigned long)(cur_iov->iov_len - bp->b_cur_off));
-	/* Stay within count */
-	bytes = min(bytes, (unsigned long)wc->w_count);
-	/*
-	 * For clustersize > page size, just stay within
-	 * target page, otherwise we have to calculate pos
-	 * within the cluster and obey the rightmost
-	 * boundary.
-	 */
-	if (wc->w_large_pages) {
-		/*
-		 * For cluster size < page size, we have to
-		 * calculate pos within the cluster and obey
-		 * the rightmost boundary.
-		 */
-		bytes = min(bytes, (unsigned long)(osb->s_clustersize
-				   - (wc->w_pos & (osb->s_clustersize - 1))));
-	} else {
-		/*
-		 * cluster size > page size is the most common
-		 * case - we just stay within the target page
-		 * boundary.
-		 */
-		bytes = min(bytes, PAGE_CACHE_SIZE - from);
-	}
-
-	to = from + bytes;
-
-	if (wc->w_this_page_new)
-		ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
-					    cluster_start, cluster_end, 1);
-	else
-		ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
-					    from, to, 0);
-	if (ret) {
-		mlog_errno(ret);
-		goto out;
-	}
-
-	BUG_ON(from > PAGE_CACHE_SIZE);
-	BUG_ON(to > PAGE_CACHE_SIZE);
-	BUG_ON(from > osb->s_clustersize);
-	BUG_ON(to > osb->s_clustersize);
-
-	dst = kmap(wc->w_this_page);
-	memcpy(dst + from, bp->b_src_buf + src_from, bytes);
-	kunmap(wc->w_this_page);
-
-	/*
-	 * XXX: This is slow, but simple. The caller of
-	 * ocfs2_buffered_write_cluster() is responsible for
-	 * passing through the iovecs, so it's difficult to
-	 * predict what our next step is in here after our
-	 * initial write. A future version should be pushing
-	 * that iovec manipulation further down.
+	 * This is true if page_size > cluster_size.
 	 *
-	 * By setting this, we indicate that a copy from user
-	 * data was done, and subsequent calls for this
-	 * cluster will skip copying more data.
+	 * It triggers a set of special cases during write which might
+	 * have to deal with allocating writes to partial pages.
 	 */
-	wc->w_finished_copy = 1;
+	unsigned int			w_large_pages;
 
-	*ret_from = from;
-	*ret_to = to;
-out:
+	/*
+	 * Pages involved in this write.
+	 *
+	 * w_target_page is the page being written to by the user.
+	 *
+	 * w_pages is an array of pages which always contains
+	 * w_target_page, and in the case of an allocating write with
+	 * page_size < cluster size, it will contain zero'd and mapped
+	 * pages adjacent to w_target_page which need to be written
+	 * out in so that future reads from that region will get
+	 * zero's.
+	 */
+	struct page			*w_pages[OCFS2_MAX_CTXT_PAGES];
+	unsigned int			w_num_pages;
+	struct page			*w_target_page;
 
-	return bytes ? (unsigned int)bytes : ret;
+	/*
+	 * ocfs2_write_end() uses this to know what the real range to
+	 * write in the target should be.
+	 */
+	unsigned int			w_target_from;
+	unsigned int			w_target_to;
+
+	/*
+	 * We could use journal_current_handle() but this is cleaner,
+	 * IMHO -Mark
+	 */
+	handle_t			*w_handle;
+
+	struct buffer_head		*w_di_bh;
+
+	struct ocfs2_cached_dealloc_ctxt w_dealloc;
+};
+
+static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
+{
+	int i;
+
+	for(i = 0; i < wc->w_num_pages; i++) {
+		if (wc->w_pages[i] == NULL)
+			continue;
+
+		unlock_page(wc->w_pages[i]);
+		mark_page_accessed(wc->w_pages[i]);
+		page_cache_release(wc->w_pages[i]);
+	}
+
+	brelse(wc->w_di_bh);
+	kfree(wc);
+}
+
+static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
+				  struct ocfs2_super *osb, loff_t pos,
+				  unsigned len, struct buffer_head *di_bh)
+{
+	struct ocfs2_write_ctxt *wc;
+
+	wc = kzalloc(sizeof(struct ocfs2_write_ctxt), GFP_NOFS);
+	if (!wc)
+		return -ENOMEM;
+
+	wc->w_cpos = pos >> osb->s_clustersize_bits;
+	wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len);
+	get_bh(di_bh);
+	wc->w_di_bh = di_bh;
+
+	if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
+		wc->w_large_pages = 1;
+	else
+		wc->w_large_pages = 0;
+
+	ocfs2_init_dealloc_ctxt(&wc->w_dealloc);
+
+	*wcp = wc;
+
+	return 0;
 }
 
 /*
- * Map, fill and write a page to disk.
- *
- * The work of copying data is done via callback.  Newly allocated
- * pages which don't take user data will be zero'd (set 'new' to
- * indicate an allocating write)
- *
- * Returns a negative error code or the number of bytes copied into
- * the page.
+ * If a page has any new buffers, zero them out here, and mark them uptodate
+ * and dirty so they'll be written out (in order to prevent uninitialised
+ * block data from leaking). And clear the new bit.
  */
-static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
-				 u64 *p_blkno, struct page *page,
-				 struct ocfs2_write_ctxt *wc, int new)
+static void ocfs2_zero_new_buffers(struct page *page, unsigned from, unsigned to)
 {
-	int ret, copied = 0;
-	unsigned int from = 0, to = 0;
-	unsigned int cluster_start, cluster_end;
-	unsigned int zero_from = 0, zero_to = 0;
+	unsigned int block_start, block_end;
+	struct buffer_head *head, *bh;
 
-	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), wc->w_cpos,
+	BUG_ON(!PageLocked(page));
+	if (!page_has_buffers(page))
+		return;
+
+	bh = head = page_buffers(page);
+	block_start = 0;
+	do {
+		block_end = block_start + bh->b_size;
+
+		if (buffer_new(bh)) {
+			if (block_end > from && block_start < to) {
+				if (!PageUptodate(page)) {
+					unsigned start, end;
+
+					start = max(from, block_start);
+					end = min(to, block_end);
+
+					zero_user_page(page, start, end - start, KM_USER0);
+					set_buffer_uptodate(bh);
+				}
+
+				clear_buffer_new(bh);
+				mark_buffer_dirty(bh);
+			}
+		}
+
+		block_start = block_end;
+		bh = bh->b_this_page;
+	} while (bh != head);
+}
+
+/*
+ * Only called when we have a failure during allocating write to write
+ * zero's to the newly allocated region.
+ */
+static void ocfs2_write_failure(struct inode *inode,
+				struct ocfs2_write_ctxt *wc,
+				loff_t user_pos, unsigned user_len)
+{
+	int i;
+	unsigned from, to;
+	struct page *tmppage;
+
+	ocfs2_zero_new_buffers(wc->w_target_page, user_pos, user_len);
+
+	if (wc->w_large_pages) {
+		from = wc->w_target_from;
+		to = wc->w_target_to;
+	} else {
+		from = 0;
+		to = PAGE_CACHE_SIZE;
+	}
+
+	for(i = 0; i < wc->w_num_pages; i++) {
+		tmppage = wc->w_pages[i];
+
+		if (ocfs2_should_order_data(inode))
+			walk_page_buffers(wc->w_handle, page_buffers(tmppage),
+					  from, to, NULL,
+					  ocfs2_journal_dirty_data);
+
+		block_commit_write(tmppage, from, to);
+	}
+}
+
+static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
+					struct ocfs2_write_ctxt *wc,
+					struct page *page, u32 cpos,
+					loff_t user_pos, unsigned user_len,
+					int new)
+{
+	int ret;
+	unsigned int map_from = 0, map_to = 0;
+	unsigned int cluster_start, cluster_end;
+	unsigned int user_data_from = 0, user_data_to = 0;
+
+	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
 					&cluster_start, &cluster_end);
 
-	if ((wc->w_pos >> PAGE_CACHE_SHIFT) == page->index
-	    && !wc->w_finished_copy) {
+	if (page == wc->w_target_page) {
+		map_from = user_pos & (PAGE_CACHE_SIZE - 1);
+		map_to = map_from + user_len;
 
-		wc->w_this_page = page;
-		wc->w_this_page_new = new;
-		ret = wc->w_write_data_page(inode, wc, p_blkno, &from, &to);
-		if (ret < 0) {
+		if (new)
+			ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+						    cluster_start, cluster_end,
+						    new);
+		else
+			ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+						    map_from, map_to, new);
+		if (ret) {
 			mlog_errno(ret);
 			goto out;
 		}
 
-		copied = ret;
-
-		zero_from = from;
-		zero_to = to;
+		user_data_from = map_from;
+		user_data_to = map_to;
 		if (new) {
-			from = cluster_start;
-			to = cluster_end;
+			map_from = cluster_start;
+			map_to = cluster_end;
 		}
+
+		wc->w_target_from = map_from;
+		wc->w_target_to = map_to;
 	} else {
 		/*
 		 * If we haven't allocated the new page yet, we
@@ -979,11 +1000,11 @@
 		 */
 		BUG_ON(!new);
 
-		from = cluster_start;
-		to = cluster_end;
+		map_from = cluster_start;
+		map_to = cluster_end;
 
 		ret = ocfs2_map_page_blocks(page, p_blkno, inode,
-					    cluster_start, cluster_end, 1);
+					    cluster_start, cluster_end, new);
 		if (ret) {
 			mlog_errno(ret);
 			goto out;
@@ -1002,108 +1023,113 @@
 	 */
 	if (new && !PageUptodate(page))
 		ocfs2_clear_page_regions(page, OCFS2_SB(inode->i_sb),
-					 wc->w_cpos, zero_from, zero_to);
+					 cpos, user_data_from, user_data_to);
 
 	flush_dcache_page(page);
 
-	if (ocfs2_should_order_data(inode)) {
-		ret = walk_page_buffers(handle,
-					page_buffers(page),
-					from, to, NULL,
-					ocfs2_journal_dirty_data);
-		if (ret < 0)
-			mlog_errno(ret);
-	}
-
-	/*
-	 * We don't use generic_commit_write() because we need to
-	 * handle our own i_size update.
-	 */
-	ret = block_commit_write(page, from, to);
-	if (ret)
-		mlog_errno(ret);
 out:
-
-	return copied ? copied : ret;
+	return ret;
 }
 
 /*
- * Do the actual write of some data into an inode. Optionally allocate
- * in order to fulfill the write.
- *
- * cpos is the logical cluster offset within the file to write at
- *
- * 'phys' is the physical mapping of that offset. a 'phys' value of
- * zero indicates that allocation is required. In this case, data_ac
- * and meta_ac should be valid (meta_ac can be null if metadata
- * allocation isn't required).
+ * This function will only grab one clusters worth of pages.
  */
-static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
-			   struct buffer_head *di_bh,
-			   struct ocfs2_alloc_context *data_ac,
-			   struct ocfs2_alloc_context *meta_ac,
-			   struct ocfs2_write_ctxt *wc)
+static int ocfs2_grab_pages_for_write(struct address_space *mapping,
+				      struct ocfs2_write_ctxt *wc,
+				      u32 cpos, loff_t user_pos, int new,
+				      struct page *mmap_page)
 {
-	int ret, i, numpages = 1, new;
-	unsigned int copied = 0;
-	u32 tmp_pos;
-	u64 v_blkno, p_blkno;
-	struct address_space *mapping = file->f_mapping;
+	int ret = 0, i;
+	unsigned long start, target_index, index;
 	struct inode *inode = mapping->host;
-	unsigned long index, start;
-	struct page **cpages;
 
-	new = phys == 0 ? 1 : 0;
+	target_index = user_pos >> PAGE_CACHE_SHIFT;
 
 	/*
 	 * Figure out how many pages we'll be manipulating here. For
 	 * non allocating write, we just change the one
 	 * page. Otherwise, we'll need a whole clusters worth.
 	 */
-	if (new)
-		numpages = ocfs2_pages_per_cluster(inode->i_sb);
-
-	cpages = kzalloc(sizeof(*cpages) * numpages, GFP_NOFS);
-	if (!cpages) {
-		ret = -ENOMEM;
-		mlog_errno(ret);
-		return ret;
-	}
-
-	/*
-	 * Fill our page array first. That way we've grabbed enough so
-	 * that we can zero and flush if we error after adding the
-	 * extent.
-	 */
 	if (new) {
-		start = ocfs2_align_clusters_to_page_index(inode->i_sb,
-							   wc->w_cpos);
-		v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, wc->w_cpos);
+		wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb);
+		start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos);
 	} else {
-		start = wc->w_pos >> PAGE_CACHE_SHIFT;
-		v_blkno = wc->w_pos >> inode->i_sb->s_blocksize_bits;
+		wc->w_num_pages = 1;
+		start = target_index;
 	}
 
-	for(i = 0; i < numpages; i++) {
+	for(i = 0; i < wc->w_num_pages; i++) {
 		index = start + i;
 
-		cpages[i] = find_or_create_page(mapping, index, GFP_NOFS);
-		if (!cpages[i]) {
-			ret = -ENOMEM;
-			mlog_errno(ret);
-			goto out;
+		if (index == target_index && mmap_page) {
+			/*
+			 * ocfs2_pagemkwrite() is a little different
+			 * and wants us to directly use the page
+			 * passed in.
+			 */
+			lock_page(mmap_page);
+
+			if (mmap_page->mapping != mapping) {
+				unlock_page(mmap_page);
+				/*
+				 * Sanity check - the locking in
+				 * ocfs2_pagemkwrite() should ensure
+				 * that this code doesn't trigger.
+				 */
+				ret = -EINVAL;
+				mlog_errno(ret);
+				goto out;
+			}
+
+			page_cache_get(mmap_page);
+			wc->w_pages[i] = mmap_page;
+		} else {
+			wc->w_pages[i] = find_or_create_page(mapping, index,
+							     GFP_NOFS);
+			if (!wc->w_pages[i]) {
+				ret = -ENOMEM;
+				mlog_errno(ret);
+				goto out;
+			}
 		}
+
+		if (index == target_index)
+			wc->w_target_page = wc->w_pages[i];
 	}
+out:
+	return ret;
+}
+
+/*
+ * Prepare a single cluster for write one cluster into the file.
+ */
+static int ocfs2_write_cluster(struct address_space *mapping,
+			       u32 phys, unsigned int unwritten,
+			       struct ocfs2_alloc_context *data_ac,
+			       struct ocfs2_alloc_context *meta_ac,
+			       struct ocfs2_write_ctxt *wc, u32 cpos,
+			       loff_t user_pos, unsigned user_len)
+{
+	int ret, i, new, should_zero = 0;
+	u64 v_blkno, p_blkno;
+	struct inode *inode = mapping->host;
+
+	new = phys == 0 ? 1 : 0;
+	if (new || unwritten)
+		should_zero = 1;
 
 	if (new) {
+		u32 tmp_pos;
+
 		/*
 		 * This is safe to call with the page locks - it won't take
 		 * any additional semaphores or cluster locks.
 		 */
-		tmp_pos = wc->w_cpos;
+		tmp_pos = cpos;
 		ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode,
-						 &tmp_pos, 1, di_bh, handle,
-						 data_ac, meta_ac, NULL);
+						 &tmp_pos, 1, 0, wc->w_di_bh,
+						 wc->w_handle, data_ac,
+						 meta_ac, NULL);
 		/*
 		 * This shouldn't happen because we must have already
 		 * calculated the correct meta data allocation required. The
@@ -1120,103 +1146,344 @@
 			mlog_errno(ret);
 			goto out;
 		}
+	} else if (unwritten) {
+		ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
+						wc->w_handle, cpos, 1, phys,
+						meta_ac, &wc->w_dealloc);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
 	}
 
+	if (should_zero)
+		v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, cpos);
+	else
+		v_blkno = user_pos >> inode->i_sb->s_blocksize_bits;
+
+	/*
+	 * The only reason this should fail is due to an inability to
+	 * find the extent added.
+	 */
 	ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL,
 					  NULL);
 	if (ret < 0) {
-
-		/*
-		 * XXX: Should we go readonly here?
-		 */
-
-		mlog_errno(ret);
+		ocfs2_error(inode->i_sb, "Corrupting extend for inode %llu, "
+			    "at logical block %llu",
+			    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+			    (unsigned long long)v_blkno);
 		goto out;
 	}
 
 	BUG_ON(p_blkno == 0);
 
-	for(i = 0; i < numpages; i++) {
-		ret = ocfs2_write_data_page(inode, handle, &p_blkno, cpages[i],
-					    wc, new);
-		if (ret < 0) {
+	for(i = 0; i < wc->w_num_pages; i++) {
+		int tmpret;
+
+		tmpret = ocfs2_prepare_page_for_write(inode, &p_blkno, wc,
+						      wc->w_pages[i], cpos,
+						      user_pos, user_len,
+						      should_zero);
+		if (tmpret) {
+			mlog_errno(tmpret);
+			if (ret == 0)
+				tmpret = ret;
+		}
+	}
+
+	/*
+	 * We only have cleanup to do in case of allocating write.
+	 */
+	if (ret && new)
+		ocfs2_write_failure(inode, wc, user_pos, user_len);
+
+out:
+
+	return ret;
+}
+
+static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
+				       struct ocfs2_alloc_context *data_ac,
+				       struct ocfs2_alloc_context *meta_ac,
+				       struct ocfs2_write_ctxt *wc,
+				       loff_t pos, unsigned len)
+{
+	int ret, i;
+	struct ocfs2_write_cluster_desc *desc;
+
+	for (i = 0; i < wc->w_clen; i++) {
+		desc = &wc->w_desc[i];
+
+		ret = ocfs2_write_cluster(mapping, desc->c_phys,
+					  desc->c_unwritten, data_ac, meta_ac,
+					  wc, desc->c_cpos, pos, len);
+		if (ret) {
 			mlog_errno(ret);
 			goto out;
 		}
-
-		copied += ret;
 	}
 
+	ret = 0;
 out:
-	for(i = 0; i < numpages; i++) {
-		unlock_page(cpages[i]);
-		mark_page_accessed(cpages[i]);
-		page_cache_release(cpages[i]);
-	}
-	kfree(cpages);
-
-	return copied ? copied : ret;
-}
-
-static void ocfs2_write_ctxt_init(struct ocfs2_write_ctxt *wc,
-				  struct ocfs2_super *osb, loff_t pos,
-				  size_t count, ocfs2_page_writer *cb,
-				  void *cb_priv)
-{
-	wc->w_count = count;
-	wc->w_pos = pos;
-	wc->w_cpos = wc->w_pos >> osb->s_clustersize_bits;
-	wc->w_finished_copy = 0;
-
-	if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
-		wc->w_large_pages = 1;
-	else
-		wc->w_large_pages = 0;
-
-	wc->w_write_data_page = cb;
-	wc->w_private = cb_priv;
+	return ret;
 }
 
 /*
- * Write a cluster to an inode. The cluster may not be allocated yet,
- * in which case it will be. This only exists for buffered writes -
- * O_DIRECT takes a more "traditional" path through the kernel.
- *
- * The caller is responsible for incrementing pos, written counts, etc
- *
- * For file systems that don't support sparse files, pre-allocation
- * and page zeroing up until cpos should be done prior to this
- * function call.
- *
- * Callers should be holding i_sem, and the rw cluster lock.
- *
- * Returns the number of user bytes written, or less than zero for
- * error.
+ * ocfs2_write_end() wants to know which parts of the target page it
+ * should complete the write on. It's easiest to compute them ahead of
+ * time when a more complete view of the write is available.
  */
-ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
-				     size_t count, ocfs2_page_writer *actor,
-				     void *priv)
+static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
+					struct ocfs2_write_ctxt *wc,
+					loff_t pos, unsigned len, int alloc)
+{
+	struct ocfs2_write_cluster_desc *desc;
+
+	wc->w_target_from = pos & (PAGE_CACHE_SIZE - 1);
+	wc->w_target_to = wc->w_target_from + len;
+
+	if (alloc == 0)
+		return;
+
+	/*
+	 * Allocating write - we may have different boundaries based
+	 * on page size and cluster size.
+	 *
+	 * NOTE: We can no longer compute one value from the other as
+	 * the actual write length and user provided length may be
+	 * different.
+	 */
+
+	if (wc->w_large_pages) {
+		/*
+		 * We only care about the 1st and last cluster within
+		 * our range and whether they should be zero'd or not. Either
+		 * value may be extended out to the start/end of a
+		 * newly allocated cluster.
+		 */
+		desc = &wc->w_desc[0];
+		if (ocfs2_should_zero_cluster(desc))
+			ocfs2_figure_cluster_boundaries(osb,
+							desc->c_cpos,
+							&wc->w_target_from,
+							NULL);
+
+		desc = &wc->w_desc[wc->w_clen - 1];
+		if (ocfs2_should_zero_cluster(desc))
+			ocfs2_figure_cluster_boundaries(osb,
+							desc->c_cpos,
+							NULL,
+							&wc->w_target_to);
+	} else {
+		wc->w_target_from = 0;
+		wc->w_target_to = PAGE_CACHE_SIZE;
+	}
+}
+
+/*
+ * Populate each single-cluster write descriptor in the write context
+ * with information about the i/o to be done.
+ *
+ * Returns the number of clusters that will have to be allocated, as
+ * well as a worst case estimate of the number of extent records that
+ * would have to be created during a write to an unwritten region.
+ */
+static int ocfs2_populate_write_desc(struct inode *inode,
+				     struct ocfs2_write_ctxt *wc,
+				     unsigned int *clusters_to_alloc,
+				     unsigned int *extents_to_split)
+{
+	int ret;
+	struct ocfs2_write_cluster_desc *desc;
+	unsigned int num_clusters = 0;
+	unsigned int ext_flags = 0;
+	u32 phys = 0;
+	int i;
+
+	*clusters_to_alloc = 0;
+	*extents_to_split = 0;
+
+	for (i = 0; i < wc->w_clen; i++) {
+		desc = &wc->w_desc[i];
+		desc->c_cpos = wc->w_cpos + i;
+
+		if (num_clusters == 0) {
+			/*
+			 * Need to look up the next extent record.
+			 */
+			ret = ocfs2_get_clusters(inode, desc->c_cpos, &phys,
+						 &num_clusters, &ext_flags);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+
+			/*
+			 * Assume worst case - that we're writing in
+			 * the middle of the extent.
+			 *
+			 * We can assume that the write proceeds from
+			 * left to right, in which case the extent
+			 * insert code is smart enough to coalesce the
+			 * next splits into the previous records created.
+			 */
+			if (ext_flags & OCFS2_EXT_UNWRITTEN)
+				*extents_to_split = *extents_to_split + 2;
+		} else if (phys) {
+			/*
+			 * Only increment phys if it doesn't describe
+			 * a hole.
+			 */
+			phys++;
+		}
+
+		desc->c_phys = phys;
+		if (phys == 0) {
+			desc->c_new = 1;
+			*clusters_to_alloc = *clusters_to_alloc + 1;
+		}
+		if (ext_flags & OCFS2_EXT_UNWRITTEN)
+			desc->c_unwritten = 1;
+
+		num_clusters--;
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+int ocfs2_write_begin_nolock(struct address_space *mapping,
+			     loff_t pos, unsigned len, unsigned flags,
+			     struct page **pagep, void **fsdata,
+			     struct buffer_head *di_bh, struct page *mmap_page)
 {
 	int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
-	ssize_t written = 0;
-	u32 phys;
-	struct inode *inode = file->f_mapping->host;
+	unsigned int clusters_to_alloc, extents_to_split;
+	struct ocfs2_write_ctxt *wc;
+	struct inode *inode = mapping->host;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-	struct buffer_head *di_bh = NULL;
 	struct ocfs2_dinode *di;
 	struct ocfs2_alloc_context *data_ac = NULL;
 	struct ocfs2_alloc_context *meta_ac = NULL;
 	handle_t *handle;
-	struct ocfs2_write_ctxt wc;
 
-	ocfs2_write_ctxt_init(&wc, osb, pos, count, actor, priv);
+	ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
+	if (ret) {
+		mlog_errno(ret);
+		return ret;
+	}
 
-	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
+					&extents_to_split);
 	if (ret) {
 		mlog_errno(ret);
 		goto out;
 	}
-	di = (struct ocfs2_dinode *)di_bh->b_data;
+
+	di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+
+	/*
+	 * We set w_target_from, w_target_to here so that
+	 * ocfs2_write_end() knows which range in the target page to
+	 * write out. An allocation requires that we write the entire
+	 * cluster range.
+	 */
+	if (clusters_to_alloc || extents_to_split) {
+		/*
+		 * XXX: We are stretching the limits of
+		 * ocfs2_lock_allocators(). It greatly over-estimates
+		 * the work to be done.
+		 */
+		ret = ocfs2_lock_allocators(inode, di, clusters_to_alloc,
+					    extents_to_split, &data_ac, &meta_ac);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		credits = ocfs2_calc_extend_credits(inode->i_sb, di,
+						    clusters_to_alloc);
+
+	}
+
+	ocfs2_set_target_boundaries(osb, wc, pos, len,
+				    clusters_to_alloc + extents_to_split);
+
+	handle = ocfs2_start_trans(osb, credits);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		mlog_errno(ret);
+		goto out;
+	}
+
+	wc->w_handle = handle;
+
+	/*
+	 * We don't want this to fail in ocfs2_write_end(), so do it
+	 * here.
+	 */
+	ret = ocfs2_journal_access(handle, inode, wc->w_di_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	/*
+	 * Fill our page array first. That way we've grabbed enough so
+	 * that we can zero and flush if we error after adding the
+	 * extent.
+	 */
+	ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
+					 clusters_to_alloc + extents_to_split,
+					 mmap_page);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
+					  len);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	if (data_ac)
+		ocfs2_free_alloc_context(data_ac);
+	if (meta_ac)
+		ocfs2_free_alloc_context(meta_ac);
+
+	*pagep = wc->w_target_page;
+	*fsdata = wc;
+	return 0;
+out_commit:
+	ocfs2_commit_trans(osb, handle);
+
+out:
+	ocfs2_free_write_ctxt(wc);
+
+	if (data_ac)
+		ocfs2_free_alloc_context(data_ac);
+	if (meta_ac)
+		ocfs2_free_alloc_context(meta_ac);
+	return ret;
+}
+
+int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+		      loff_t pos, unsigned len, unsigned flags,
+		      struct page **pagep, void **fsdata)
+{
+	int ret;
+	struct buffer_head *di_bh = NULL;
+	struct inode *inode = mapping->host;
+
+	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	if (ret) {
+		mlog_errno(ret);
+		return ret;
+	}
 
 	/*
 	 * Take alloc sem here to prevent concurrent lookups. That way
@@ -1227,52 +1494,85 @@
 	 */
 	down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
-	ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL, NULL);
-	if (ret) {
-		mlog_errno(ret);
-		goto out_meta;
-	}
-
-	/* phys == 0 means that allocation is required. */
-	if (phys == 0) {
-		ret = ocfs2_lock_allocators(inode, di, 1, &data_ac, &meta_ac);
-		if (ret) {
-			mlog_errno(ret);
-			goto out_meta;
-		}
-
-		credits = ocfs2_calc_extend_credits(inode->i_sb, di, 1);
-	}
-
 	ret = ocfs2_data_lock(inode, 1);
 	if (ret) {
 		mlog_errno(ret);
-		goto out_meta;
+		goto out_fail;
 	}
 
-	handle = ocfs2_start_trans(osb, credits);
-	if (IS_ERR(handle)) {
-		ret = PTR_ERR(handle);
-		mlog_errno(ret);
-		goto out_data;
-	}
-
-	written = ocfs2_write(file, phys, handle, di_bh, data_ac,
-			      meta_ac, &wc);
-	if (written < 0) {
-		ret = written;
-		mlog_errno(ret);
-		goto out_commit;
-	}
-
-	ret = ocfs2_journal_access(handle, inode, di_bh,
-				   OCFS2_JOURNAL_ACCESS_WRITE);
+	ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
+				       fsdata, di_bh, NULL);
 	if (ret) {
 		mlog_errno(ret);
-		goto out_commit;
+		goto out_fail_data;
 	}
 
-	pos += written;
+	brelse(di_bh);
+
+	return 0;
+
+out_fail_data:
+	ocfs2_data_unlock(inode, 1);
+out_fail:
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+	brelse(di_bh);
+	ocfs2_meta_unlock(inode, 1);
+
+	return ret;
+}
+
+int ocfs2_write_end_nolock(struct address_space *mapping,
+			   loff_t pos, unsigned len, unsigned copied,
+			   struct page *page, void *fsdata)
+{
+	int i;
+	unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
+	struct inode *inode = mapping->host;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_write_ctxt *wc = fsdata;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+	handle_t *handle = wc->w_handle;
+	struct page *tmppage;
+
+	if (unlikely(copied < len)) {
+		if (!PageUptodate(wc->w_target_page))
+			copied = 0;
+
+		ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
+				       start+len);
+	}
+	flush_dcache_page(wc->w_target_page);
+
+	for(i = 0; i < wc->w_num_pages; i++) {
+		tmppage = wc->w_pages[i];
+
+		if (tmppage == wc->w_target_page) {
+			from = wc->w_target_from;
+			to = wc->w_target_to;
+
+			BUG_ON(from > PAGE_CACHE_SIZE ||
+			       to > PAGE_CACHE_SIZE ||
+			       to < from);
+		} else {
+			/*
+			 * Pages adjacent to the target (if any) imply
+			 * a hole-filling write in which case we want
+			 * to flush their entire range.
+			 */
+			from = 0;
+			to = PAGE_CACHE_SIZE;
+		}
+
+		if (ocfs2_should_order_data(inode))
+			walk_page_buffers(wc->w_handle, page_buffers(tmppage),
+					  from, to, NULL,
+					  ocfs2_journal_dirty_data);
+
+		block_commit_write(tmppage, from, to);
+	}
+
+	pos += copied;
 	if (pos > inode->i_size) {
 		i_size_write(inode, pos);
 		mark_inode_dirty(inode);
@@ -1282,29 +1582,31 @@
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
 	di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+	ocfs2_journal_dirty(handle, wc->w_di_bh);
 
-	ret = ocfs2_journal_dirty(handle, di_bh);
-	if (ret)
-		mlog_errno(ret);
-
-out_commit:
 	ocfs2_commit_trans(osb, handle);
 
-out_data:
-	ocfs2_data_unlock(inode, 1);
+	ocfs2_run_deallocs(osb, &wc->w_dealloc);
 
-out_meta:
+	ocfs2_free_write_ctxt(wc);
+
+	return copied;
+}
+
+int ocfs2_write_end(struct file *file, struct address_space *mapping,
+		    loff_t pos, unsigned len, unsigned copied,
+		    struct page *page, void *fsdata)
+{
+	int ret;
+	struct inode *inode = mapping->host;
+
+	ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata);
+
+	ocfs2_data_unlock(inode, 1);
 	up_write(&OCFS2_I(inode)->ip_alloc_sem);
 	ocfs2_meta_unlock(inode, 1);
 
-out:
-	brelse(di_bh);
-	if (data_ac)
-		ocfs2_free_alloc_context(data_ac);
-	if (meta_ac)
-		ocfs2_free_alloc_context(meta_ac);
-
-	return written ? written : ret;
+	return ret;
 }
 
 const struct address_space_operations ocfs2_aops = {
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index 45821d4..389579b 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -42,57 +42,22 @@
 			int (*fn)(	handle_t *handle,
 					struct buffer_head *bh));
 
-struct ocfs2_write_ctxt;
-typedef int (ocfs2_page_writer)(struct inode *, struct ocfs2_write_ctxt *,
-				u64 *, unsigned int *, unsigned int *);
+int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+		      loff_t pos, unsigned len, unsigned flags,
+		      struct page **pagep, void **fsdata);
 
-ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
-				     size_t count, ocfs2_page_writer *actor,
-				     void *priv);
+int ocfs2_write_end(struct file *file, struct address_space *mapping,
+		    loff_t pos, unsigned len, unsigned copied,
+		    struct page *page, void *fsdata);
 
-struct ocfs2_write_ctxt {
-	size_t				w_count;
-	loff_t				w_pos;
-	u32				w_cpos;
-	unsigned int			w_finished_copy;
+int ocfs2_write_end_nolock(struct address_space *mapping,
+			   loff_t pos, unsigned len, unsigned copied,
+			   struct page *page, void *fsdata);
 
-	/* This is true if page_size > cluster_size */
-	unsigned int			w_large_pages;
-
-	/* Filler callback and private data */
-	ocfs2_page_writer		*w_write_data_page;
-	void				*w_private;
-
-	/* Only valid for the filler callback */
-	struct page			*w_this_page;
-	unsigned int			w_this_page_new;
-};
-
-struct ocfs2_buffered_write_priv {
-	char				*b_src_buf;
-	const struct iovec		*b_cur_iov; /* Current iovec */
-	size_t				b_cur_off; /* Offset in the
-						    * current iovec */
-};
-int ocfs2_map_and_write_user_data(struct inode *inode,
-				  struct ocfs2_write_ctxt *wc,
-				  u64 *p_blkno,
-				  unsigned int *ret_from,
-				  unsigned int *ret_to);
-
-struct ocfs2_splice_write_priv {
-	struct splice_desc		*s_sd;
-	struct pipe_buffer		*s_buf;
-	struct pipe_inode_info		*s_pipe;
-	/* Neither offset value is ever larger than one page */
-	unsigned int			s_offset;
-	unsigned int			s_buf_offset;
-};
-int ocfs2_map_and_write_splice_data(struct inode *inode,
-				    struct ocfs2_write_ctxt *wc,
-				    u64 *p_blkno,
-				    unsigned int *ret_from,
-				    unsigned int *ret_to);
+int ocfs2_write_begin_nolock(struct address_space *mapping,
+			     loff_t pos, unsigned len, unsigned flags,
+			     struct page **pagep, void **fsdata,
+			     struct buffer_head *di_bh, struct page *mmap_page);
 
 /* all ocfs2_dio_end_io()'s fault */
 #define ocfs2_iocb_is_rw_locked(iocb) \
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 9791134..2bd7f78 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -1335,6 +1335,7 @@
 	ret = wait_event_interruptible(o2hb_steady_queue,
 				atomic_read(&reg->hr_steady_iterations) == 0);
 	if (ret) {
+		/* We got interrupted (hello ptrace!).  Clean up */
 		spin_lock(&o2hb_live_lock);
 		hb_task = reg->hr_task;
 		reg->hr_task = NULL;
@@ -1345,7 +1346,16 @@
 		goto out;
 	}
 
-	ret = count;
+	/* Ok, we were woken.  Make sure it wasn't by drop_item() */
+	spin_lock(&o2hb_live_lock);
+	hb_task = reg->hr_task;
+	spin_unlock(&o2hb_live_lock);
+
+	if (hb_task)
+		ret = count;
+	else
+		ret = -EIO;
+
 out:
 	if (filp)
 		fput(filp);
@@ -1523,6 +1533,15 @@
 	if (hb_task)
 		kthread_stop(hb_task);
 
+	/*
+	 * If we're racing a dev_write(), we need to wake them.  They will
+	 * check reg->hr_task
+	 */
+	if (atomic_read(&reg->hr_steady_iterations) != 0) {
+		atomic_set(&reg->hr_steady_iterations, 0);
+		wake_up(&o2hb_steady_queue);
+	}
+
 	config_item_put(item);
 }
 
@@ -1665,7 +1684,67 @@
 }
 EXPORT_SYMBOL_GPL(o2hb_setup_callback);
 
-int o2hb_register_callback(struct o2hb_callback_func *hc)
+static struct o2hb_region *o2hb_find_region(const char *region_uuid)
+{
+	struct o2hb_region *p, *reg = NULL;
+
+	assert_spin_locked(&o2hb_live_lock);
+
+	list_for_each_entry(p, &o2hb_all_regions, hr_all_item) {
+		if (!strcmp(region_uuid, config_item_name(&p->hr_item))) {
+			reg = p;
+			break;
+		}
+	}
+
+	return reg;
+}
+
+static int o2hb_region_get(const char *region_uuid)
+{
+	int ret = 0;
+	struct o2hb_region *reg;
+
+	spin_lock(&o2hb_live_lock);
+
+	reg = o2hb_find_region(region_uuid);
+	if (!reg)
+		ret = -ENOENT;
+	spin_unlock(&o2hb_live_lock);
+
+	if (ret)
+		goto out;
+
+	ret = o2nm_depend_this_node();
+	if (ret)
+		goto out;
+
+	ret = o2nm_depend_item(&reg->hr_item);
+	if (ret)
+		o2nm_undepend_this_node();
+
+out:
+	return ret;
+}
+
+static void o2hb_region_put(const char *region_uuid)
+{
+	struct o2hb_region *reg;
+
+	spin_lock(&o2hb_live_lock);
+
+	reg = o2hb_find_region(region_uuid);
+
+	spin_unlock(&o2hb_live_lock);
+
+	if (reg) {
+		o2nm_undepend_item(&reg->hr_item);
+		o2nm_undepend_this_node();
+	}
+}
+
+int o2hb_register_callback(const char *region_uuid,
+			   struct o2hb_callback_func *hc)
 {
 	struct o2hb_callback_func *tmp;
 	struct list_head *iter;
@@ -1681,6 +1760,12 @@
 		goto out;
 	}
 
+	if (region_uuid) {
+		ret = o2hb_region_get(region_uuid);
+		if (ret)
+			goto out;
+	}
+
 	down_write(&o2hb_callback_sem);
 
 	list_for_each(iter, &hbcall->list) {
@@ -1702,16 +1787,21 @@
 }
 EXPORT_SYMBOL_GPL(o2hb_register_callback);
 
-void o2hb_unregister_callback(struct o2hb_callback_func *hc)
+void o2hb_unregister_callback(const char *region_uuid,
+			      struct o2hb_callback_func *hc)
 {
 	BUG_ON(hc->hc_magic != O2HB_CB_MAGIC);
 
 	mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n",
 	     __builtin_return_address(0), hc);
 
+	/* XXX Can this happen _with_ a region reference? */
 	if (list_empty(&hc->hc_item))
 		return;
 
+	if (region_uuid)
+		o2hb_region_put(region_uuid);
+
 	down_write(&o2hb_callback_sem);
 
 	list_del_init(&hc->hc_item);
diff --git a/fs/ocfs2/cluster/heartbeat.h b/fs/ocfs2/cluster/heartbeat.h
index cc6d40b..35397dd 100644
--- a/fs/ocfs2/cluster/heartbeat.h
+++ b/fs/ocfs2/cluster/heartbeat.h
@@ -69,8 +69,10 @@
 			 o2hb_cb_func *func,
 			 void *data,
 			 int priority);
-int o2hb_register_callback(struct o2hb_callback_func *hc);
-void o2hb_unregister_callback(struct o2hb_callback_func *hc);
+int o2hb_register_callback(const char *region_uuid,
+			   struct o2hb_callback_func *hc);
+void o2hb_unregister_callback(const char *region_uuid,
+			      struct o2hb_callback_func *hc);
 void o2hb_fill_node_map(unsigned long *map,
 			unsigned bytes);
 void o2hb_init(void);
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index a93620c..e9e042b 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -74,7 +74,6 @@
 #define define_mask(_name) {			\
 	.attr = {				\
 		.name = #_name,			\
-		.owner = THIS_MODULE,		\
 		.mode = S_IRUGO | S_IWUSR,	\
 	},					\
 	.mask = ML_##_name,			\
@@ -144,8 +143,7 @@
 };
 
 static struct kset mlog_kset = {
-	.kobj  = {.name = "logmask"},
-	.ktype = &mlog_ktype
+	.kobj   = {.name = "logmask", .ktype = &mlog_ktype},
 };
 
 int mlog_sys_init(struct kset *o2cb_subsys)
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index 9f5ad0f..af2070d 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -900,6 +900,46 @@
 	},
 };
 
+int o2nm_depend_item(struct config_item *item)
+{
+	return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item);
+}
+
+void o2nm_undepend_item(struct config_item *item)
+{
+	configfs_undepend_item(&o2nm_cluster_group.cs_subsys, item);
+}
+
+int o2nm_depend_this_node(void)
+{
+	int ret = 0;
+	struct o2nm_node *local_node;
+
+	local_node = o2nm_get_node_by_num(o2nm_this_node());
+	if (!local_node) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = o2nm_depend_item(&local_node->nd_item);
+	o2nm_node_put(local_node);
+
+out:
+	return ret;
+}
+
+void o2nm_undepend_this_node(void)
+{
+	struct o2nm_node *local_node;
+
+	local_node = o2nm_get_node_by_num(o2nm_this_node());
+	BUG_ON(!local_node);
+
+	o2nm_undepend_item(&local_node->nd_item);
+	o2nm_node_put(local_node);
+}
+
+
 static void __exit exit_o2nm(void)
 {
 	if (ocfs2_table_header)
@@ -934,7 +974,7 @@
 		goto out_sysctl;
 
 	config_group_init(&o2nm_cluster_group.cs_subsys.su_group);
-	init_MUTEX(&o2nm_cluster_group.cs_subsys.su_sem);
+	mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex);
 	ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys);
 	if (ret) {
 		printk(KERN_ERR "nodemanager: Registration returned %d\n", ret);
diff --git a/fs/ocfs2/cluster/nodemanager.h b/fs/ocfs2/cluster/nodemanager.h
index 0705221..7c86036 100644
--- a/fs/ocfs2/cluster/nodemanager.h
+++ b/fs/ocfs2/cluster/nodemanager.h
@@ -77,4 +77,9 @@
 void o2nm_node_get(struct o2nm_node *node);
 void o2nm_node_put(struct o2nm_node *node);
 
+int o2nm_depend_item(struct config_item *item);
+void o2nm_undepend_item(struct config_item *item);
+int o2nm_depend_this_node(void);
+void o2nm_undepend_this_node(void);
+
 #endif /* O2CLUSTER_NODEMANAGER_H */
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 0b229a9..f0bdfd9 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -261,14 +261,12 @@
 
 static void o2net_complete_nodes_nsw(struct o2net_node *nn)
 {
-	struct list_head *iter, *tmp;
+	struct o2net_status_wait *nsw, *tmp;
 	unsigned int num_kills = 0;
-	struct o2net_status_wait *nsw;
 
 	assert_spin_locked(&nn->nn_lock);
 
-	list_for_each_safe(iter, tmp, &nn->nn_status_list) {
-		nsw = list_entry(iter, struct o2net_status_wait, ns_node_item);
+	list_for_each_entry_safe(nsw, tmp, &nn->nn_status_list, ns_node_item) {
 		o2net_complete_nsw_locked(nn, nsw, O2NET_ERR_DIED, 0);
 		num_kills++;
 	}
@@ -764,13 +762,10 @@
 
 void o2net_unregister_handler_list(struct list_head *list)
 {
-	struct list_head *pos, *n;
-	struct o2net_msg_handler *nmh;
+	struct o2net_msg_handler *nmh, *n;
 
 	write_lock(&o2net_handler_lock);
-	list_for_each_safe(pos, n, list) {
-		nmh = list_entry(pos, struct o2net_msg_handler,
-				 nh_unregister_item);
+	list_for_each_entry_safe(nmh, n, list, nh_unregister_item) {
 		mlog(ML_TCP, "unregistering handler func %p type %u key %08x\n",
 		     nmh->nh_func, nmh->nh_msg_type, nmh->nh_key);
 		rb_erase(&nmh->nh_node, &o2net_handler_tree);
@@ -1638,8 +1633,8 @@
 
 void o2net_unregister_hb_callbacks(void)
 {
-	o2hb_unregister_callback(&o2net_hb_up);
-	o2hb_unregister_callback(&o2net_hb_down);
+	o2hb_unregister_callback(NULL, &o2net_hb_up);
+	o2hb_unregister_callback(NULL, &o2net_hb_down);
 }
 
 int o2net_register_hb_callbacks(void)
@@ -1651,9 +1646,9 @@
 	o2hb_setup_callback(&o2net_hb_up, O2HB_NODE_UP_CB,
 			    o2net_hb_node_up_cb, NULL, O2NET_HB_PRI);
 
-	ret = o2hb_register_callback(&o2net_hb_up);
+	ret = o2hb_register_callback(NULL, &o2net_hb_up);
 	if (ret == 0)
-		ret = o2hb_register_callback(&o2net_hb_down);
+		ret = o2hb_register_callback(NULL, &o2net_hb_down);
 
 	if (ret)
 		o2net_unregister_hb_callbacks();
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index c441ef1..0d5fdde 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -368,7 +368,7 @@
 		u32 offset = OCFS2_I(dir)->ip_clusters;
 
 		status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset,
-						    1, parent_fe_bh, handle,
+						    1, 0, parent_fe_bh, handle,
 						    data_ac, meta_ac, NULL);
 		BUG_ON(status == -EAGAIN);
 		if (status < 0) {
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index d836b98..6954565 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -1128,8 +1128,8 @@
 
 static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm)
 {
-	o2hb_unregister_callback(&dlm->dlm_hb_up);
-	o2hb_unregister_callback(&dlm->dlm_hb_down);
+	o2hb_unregister_callback(NULL, &dlm->dlm_hb_up);
+	o2hb_unregister_callback(NULL, &dlm->dlm_hb_down);
 	o2net_unregister_handler_list(&dlm->dlm_domain_handlers);
 }
 
@@ -1141,13 +1141,13 @@
 
 	o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB,
 			    dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI);
-	status = o2hb_register_callback(&dlm->dlm_hb_down);
+	status = o2hb_register_callback(NULL, &dlm->dlm_hb_down);
 	if (status)
 		goto bail;
 
 	o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB,
 			    dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI);
-	status = o2hb_register_callback(&dlm->dlm_hb_up);
+	status = o2hb_register_callback(NULL, &dlm->dlm_hb_up);
 	if (status)
 		goto bail;
 
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 6edffca..65b2b9b 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -192,25 +192,20 @@
 static void dlm_dump_mles(struct dlm_ctxt *dlm)
 {
 	struct dlm_master_list_entry *mle;
-	struct list_head *iter;
 	
 	mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
 	spin_lock(&dlm->master_lock);
-	list_for_each(iter, &dlm->master_list) {
-		mle = list_entry(iter, struct dlm_master_list_entry, list);
+	list_for_each_entry(mle, &dlm->master_list, list)
 		dlm_print_one_mle(mle);
-	}
 	spin_unlock(&dlm->master_lock);
 }
 
 int dlm_dump_all_mles(const char __user *data, unsigned int len)
 {
-	struct list_head *iter;
 	struct dlm_ctxt *dlm;
 
 	spin_lock(&dlm_domain_lock);
-	list_for_each(iter, &dlm_domains) {
-		dlm = list_entry (iter, struct dlm_ctxt, list);
+	list_for_each_entry(dlm, &dlm_domains, list) {
 		mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
 		dlm_dump_mles(dlm);
 	}
@@ -454,12 +449,10 @@
 			char *name, unsigned int namelen)
 {
 	struct dlm_master_list_entry *tmpmle;
-	struct list_head *iter;
 
 	assert_spin_locked(&dlm->master_lock);
 
-	list_for_each(iter, &dlm->master_list) {
-		tmpmle = list_entry(iter, struct dlm_master_list_entry, list);
+	list_for_each_entry(tmpmle, &dlm->master_list, list) {
 		if (!dlm_mle_equal(dlm, tmpmle, name, namelen))
 			continue;
 		dlm_get_mle(tmpmle);
@@ -472,13 +465,10 @@
 void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up)
 {
 	struct dlm_master_list_entry *mle;
-	struct list_head *iter;
 
 	assert_spin_locked(&dlm->spinlock);
 	
-	list_for_each(iter, &dlm->mle_hb_events) {
-		mle = list_entry(iter, struct dlm_master_list_entry, 
-				 hb_events);
+	list_for_each_entry(mle, &dlm->mle_hb_events, hb_events) {
 		if (node_up)
 			dlm_mle_node_up(dlm, mle, NULL, idx);
 		else
@@ -2434,7 +2424,7 @@
 	int ret;
 	int i;
 	int count = 0;
-	struct list_head *queue, *iter;
+	struct list_head *queue;
 	struct dlm_lock *lock;
 
 	assert_spin_locked(&res->spinlock);
@@ -2453,8 +2443,7 @@
 	ret = 0;
 	queue = &res->granted;
 	for (i = 0; i < 3; i++) {
-		list_for_each(iter, queue) {
-			lock = list_entry(iter, struct dlm_lock, list);
+		list_for_each_entry(lock, queue, list) {
 			++count;
 			if (lock->ml.node == dlm->node_num) {
 				mlog(0, "found a lock owned by this node still "
@@ -2923,18 +2912,16 @@
 static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
 				      struct dlm_lock_resource *res)
 {
-	struct list_head *iter, *iter2;
 	struct list_head *queue = &res->granted;
 	int i, bit;
-	struct dlm_lock *lock;
+	struct dlm_lock *lock, *next;
 
 	assert_spin_locked(&res->spinlock);
 
 	BUG_ON(res->owner == dlm->node_num);
 
 	for (i=0; i<3; i++) {
-		list_for_each_safe(iter, iter2, queue) {
-			lock = list_entry (iter, struct dlm_lock, list);
+		list_for_each_entry_safe(lock, next, queue, list) {
 			if (lock->ml.node != dlm->node_num) {
 				mlog(0, "putting lock for node %u\n",
 				     lock->ml.node);
@@ -2976,7 +2963,6 @@
 {
 	int i;
 	struct list_head *queue = &res->granted;
-	struct list_head *iter;
 	struct dlm_lock *lock;
 	int nodenum;
 
@@ -2984,10 +2970,9 @@
 
 	spin_lock(&res->spinlock);
 	for (i=0; i<3; i++) {
-		list_for_each(iter, queue) {
+		list_for_each_entry(lock, queue, list) {
 			/* up to the caller to make sure this node
 			 * is alive */
-			lock = list_entry (iter, struct dlm_lock, list);
 			if (lock->ml.node != dlm->node_num) {
 				spin_unlock(&res->spinlock);
 				return lock->ml.node;
@@ -3234,8 +3219,7 @@
 
 void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
 {
-	struct list_head *iter, *iter2;
-	struct dlm_master_list_entry *mle;
+	struct dlm_master_list_entry *mle, *next;
 	struct dlm_lock_resource *res;
 	unsigned int hash;
 
@@ -3245,9 +3229,7 @@
 
 	/* clean the master list */
 	spin_lock(&dlm->master_lock);
-	list_for_each_safe(iter, iter2, &dlm->master_list) {
-		mle = list_entry(iter, struct dlm_master_list_entry, list);
-
+	list_for_each_entry_safe(mle, next, &dlm->master_list, list) {
 		BUG_ON(mle->type != DLM_MLE_BLOCK &&
 		       mle->type != DLM_MLE_MASTER &&
 		       mle->type != DLM_MLE_MIGRATION);
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 671c4ed..a2c3316 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -158,8 +158,7 @@
 	struct dlm_ctxt *dlm =
 		container_of(work, struct dlm_ctxt, dispatched_work);
 	LIST_HEAD(tmp_list);
-	struct list_head *iter, *iter2;
-	struct dlm_work_item *item;
+	struct dlm_work_item *item, *next;
 	dlm_workfunc_t *workfunc;
 	int tot=0;
 
@@ -167,13 +166,12 @@
 	list_splice_init(&dlm->work_list, &tmp_list);
 	spin_unlock(&dlm->work_lock);
 
-	list_for_each_safe(iter, iter2, &tmp_list) {
+	list_for_each_entry(item, &tmp_list, list) {
 		tot++;
 	}
 	mlog(0, "%s: work thread has %d work items\n", dlm->name, tot);
 
-	list_for_each_safe(iter, iter2, &tmp_list) {
-		item = list_entry(iter, struct dlm_work_item, list);
+	list_for_each_entry_safe(item, next, &tmp_list, list) {
 		workfunc = item->func;
 		list_del_init(&item->list);
 
@@ -549,7 +547,6 @@
 {
 	int status = 0;
 	struct dlm_reco_node_data *ndata;
-	struct list_head *iter;
 	int all_nodes_done;
 	int destroy = 0;
 	int pass = 0;
@@ -567,8 +564,7 @@
 
 	/* safe to access the node data list without a lock, since this
 	 * process is the only one to change the list */
-	list_for_each(iter, &dlm->reco.node_data) {
-		ndata = list_entry (iter, struct dlm_reco_node_data, list);
+	list_for_each_entry(ndata, &dlm->reco.node_data, list) {
 		BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT);
 		ndata->state = DLM_RECO_NODE_DATA_REQUESTING;
 
@@ -655,9 +651,7 @@
 		 * done, or if anyone died */
 		all_nodes_done = 1;
 		spin_lock(&dlm_reco_state_lock);
-		list_for_each(iter, &dlm->reco.node_data) {
-			ndata = list_entry (iter, struct dlm_reco_node_data, list);
-
+		list_for_each_entry(ndata, &dlm->reco.node_data, list) {
 			mlog(0, "checking recovery state of node %u\n",
 			     ndata->node_num);
 			switch (ndata->state) {
@@ -774,16 +768,14 @@
 
 static void dlm_destroy_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
 {
-	struct list_head *iter, *iter2;
-	struct dlm_reco_node_data *ndata;
+	struct dlm_reco_node_data *ndata, *next;
 	LIST_HEAD(tmplist);
 
 	spin_lock(&dlm_reco_state_lock);
 	list_splice_init(&dlm->reco.node_data, &tmplist);
 	spin_unlock(&dlm_reco_state_lock);
 
-	list_for_each_safe(iter, iter2, &tmplist) {
-		ndata = list_entry (iter, struct dlm_reco_node_data, list);
+	list_for_each_entry_safe(ndata, next, &tmplist, list) {
 		list_del_init(&ndata->list);
 		kfree(ndata);
 	}
@@ -876,7 +868,6 @@
 	struct dlm_lock_resource *res;
 	struct dlm_ctxt *dlm;
 	LIST_HEAD(resources);
-	struct list_head *iter;
 	int ret;
 	u8 dead_node, reco_master;
 	int skip_all_done = 0;
@@ -920,8 +911,7 @@
 
 	/* any errors returned will be due to the new_master dying,
 	 * the dlm_reco_thread should detect this */
-	list_for_each(iter, &resources) {
-		res = list_entry (iter, struct dlm_lock_resource, recovering);
+	list_for_each_entry(res, &resources, recovering) {
 		ret = dlm_send_one_lockres(dlm, res, mres, reco_master,
 				   	DLM_MRES_RECOVERY);
 		if (ret < 0) {
@@ -983,7 +973,6 @@
 {
 	struct dlm_ctxt *dlm = data;
 	struct dlm_reco_data_done *done = (struct dlm_reco_data_done *)msg->buf;
-	struct list_head *iter;
 	struct dlm_reco_node_data *ndata = NULL;
 	int ret = -EINVAL;
 
@@ -1000,8 +989,7 @@
 			dlm->reco.dead_node, done->node_idx, dlm->node_num);
 
 	spin_lock(&dlm_reco_state_lock);
-	list_for_each(iter, &dlm->reco.node_data) {
-		ndata = list_entry (iter, struct dlm_reco_node_data, list);
+	list_for_each_entry(ndata, &dlm->reco.node_data, list) {
 		if (ndata->node_num != done->node_idx)
 			continue;
 
@@ -1049,13 +1037,11 @@
 					struct list_head *list,
 				       	u8 dead_node)
 {
-	struct dlm_lock_resource *res;
-	struct list_head *iter, *iter2;
+	struct dlm_lock_resource *res, *next;
 	struct dlm_lock *lock;
 
 	spin_lock(&dlm->spinlock);
-	list_for_each_safe(iter, iter2, &dlm->reco.resources) {
-		res = list_entry (iter, struct dlm_lock_resource, recovering);
+	list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
 		/* always prune any $RECOVERY entries for dead nodes,
 		 * otherwise hangs can occur during later recovery */
 		if (dlm_is_recovery_lock(res->lockname.name,
@@ -1169,7 +1155,7 @@
 					u8 flags, u8 master)
 {
 	/* mres here is one full page */
-	memset(mres, 0, PAGE_SIZE);
+	clear_page(mres);
 	mres->lockname_len = namelen;
 	memcpy(mres->lockname, lockname, namelen);
 	mres->num_locks = 0;
@@ -1252,7 +1238,7 @@
 			 struct dlm_migratable_lockres *mres,
 			 u8 send_to, u8 flags)
 {
-	struct list_head *queue, *iter;
+	struct list_head *queue;
 	int total_locks, i;
 	u64 mig_cookie = 0;
 	struct dlm_lock *lock;
@@ -1278,9 +1264,7 @@
 	total_locks = 0;
 	for (i=DLM_GRANTED_LIST; i<=DLM_BLOCKED_LIST; i++) {
 		queue = dlm_list_idx_to_ptr(res, i);
-		list_for_each(iter, queue) {
-			lock = list_entry (iter, struct dlm_lock, list);
-
+		list_for_each_entry(lock, queue, list) {
 			/* add another lock. */
 			total_locks++;
 			if (!dlm_add_lock_to_array(lock, mres, i))
@@ -1717,7 +1701,6 @@
 	struct dlm_lockstatus *lksb = NULL;
 	int ret = 0;
 	int i, j, bad;
-	struct list_head *iter;
 	struct dlm_lock *lock = NULL;
 	u8 from = O2NM_MAX_NODES;
 	unsigned int added = 0;
@@ -1755,8 +1738,7 @@
 			spin_lock(&res->spinlock);
 			for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) {
 				tmpq = dlm_list_idx_to_ptr(res, j);
-				list_for_each(iter, tmpq) {
-					lock = list_entry (iter, struct dlm_lock, list);
+				list_for_each_entry(lock, tmpq, list) {
 					if (lock->ml.cookie != ml->cookie)
 						lock = NULL;
 					else
@@ -1930,8 +1912,8 @@
 				       struct dlm_lock_resource *res)
 {
 	int i;
-	struct list_head *queue, *iter, *iter2;
-	struct dlm_lock *lock;
+	struct list_head *queue;
+	struct dlm_lock *lock, *next;
 
 	res->state |= DLM_LOCK_RES_RECOVERING;
 	if (!list_empty(&res->recovering)) {
@@ -1947,8 +1929,7 @@
 	/* find any pending locks and put them back on proper list */
 	for (i=DLM_BLOCKED_LIST; i>=DLM_GRANTED_LIST; i--) {
 		queue = dlm_list_idx_to_ptr(res, i);
-		list_for_each_safe(iter, iter2, queue) {
-			lock = list_entry (iter, struct dlm_lock, list);
+		list_for_each_entry_safe(lock, next, queue, list) {
 			dlm_lock_get(lock);
 			if (lock->convert_pending) {
 				/* move converting lock back to granted */
@@ -2013,18 +1994,15 @@
 					      u8 dead_node, u8 new_master)
 {
 	int i;
-	struct list_head *iter, *iter2;
 	struct hlist_node *hash_iter;
 	struct hlist_head *bucket;
-
-	struct dlm_lock_resource *res;
+	struct dlm_lock_resource *res, *next;
 
 	mlog_entry_void();
 
 	assert_spin_locked(&dlm->spinlock);
 
-	list_for_each_safe(iter, iter2, &dlm->reco.resources) {
-		res = list_entry (iter, struct dlm_lock_resource, recovering);
+	list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
 		if (res->owner == dead_node) {
 			list_del_init(&res->recovering);
 			spin_lock(&res->spinlock);
@@ -2099,7 +2077,7 @@
 static void dlm_revalidate_lvb(struct dlm_ctxt *dlm,
 			       struct dlm_lock_resource *res, u8 dead_node)
 {
-	struct list_head *iter, *queue;
+	struct list_head *queue;
 	struct dlm_lock *lock;
 	int blank_lvb = 0, local = 0;
 	int i;
@@ -2121,8 +2099,7 @@
 
 	for (i=DLM_GRANTED_LIST; i<=DLM_CONVERTING_LIST; i++) {
 		queue = dlm_list_idx_to_ptr(res, i);
-		list_for_each(iter, queue) {
-			lock = list_entry (iter, struct dlm_lock, list);
+		list_for_each_entry(lock, queue, list) {
 			if (lock->ml.node == search_node) {
 				if (dlm_lvb_needs_invalidation(lock, local)) {
 					/* zero the lksb lvb and lockres lvb */
@@ -2143,8 +2120,7 @@
 static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
 				struct dlm_lock_resource *res, u8 dead_node)
 {
-	struct list_head *iter, *tmpiter;
-	struct dlm_lock *lock;
+	struct dlm_lock *lock, *next;
 	unsigned int freed = 0;
 
 	/* this node is the lockres master:
@@ -2155,24 +2131,21 @@
 	assert_spin_locked(&res->spinlock);
 
 	/* TODO: check pending_asts, pending_basts here */
-	list_for_each_safe(iter, tmpiter, &res->granted) {
-		lock = list_entry (iter, struct dlm_lock, list);
+	list_for_each_entry_safe(lock, next, &res->granted, list) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
 			freed++;
 		}
 	}
-	list_for_each_safe(iter, tmpiter, &res->converting) {
-		lock = list_entry (iter, struct dlm_lock, list);
+	list_for_each_entry_safe(lock, next, &res->converting, list) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
 			freed++;
 		}
 	}
-	list_for_each_safe(iter, tmpiter, &res->blocked) {
-		lock = list_entry (iter, struct dlm_lock, list);
+	list_for_each_entry_safe(lock, next, &res->blocked, list) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index d1bd305..f71250e 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -600,15 +600,13 @@
 static void lockres_set_flags(struct ocfs2_lock_res *lockres,
 			      unsigned long newflags)
 {
-	struct list_head *pos, *tmp;
-	struct ocfs2_mask_waiter *mw;
+	struct ocfs2_mask_waiter *mw, *tmp;
 
  	assert_spin_locked(&lockres->l_lock);
 
 	lockres->l_flags = newflags;
 
-	list_for_each_safe(pos, tmp, &lockres->l_mask_waiters) {
-		mw = list_entry(pos, struct ocfs2_mask_waiter, mw_item);
+	list_for_each_entry_safe(mw, tmp, &lockres->l_mask_waiters, mw_item) {
 		if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
 			continue;
 
diff --git a/fs/ocfs2/endian.h b/fs/ocfs2/endian.h
index f226b22..ff25762 100644
--- a/fs/ocfs2/endian.h
+++ b/fs/ocfs2/endian.h
@@ -32,6 +32,11 @@
 	*var = cpu_to_le32(le32_to_cpu(*var) + val);
 }
 
+static inline void le64_add_cpu(__le64 *var, u64 val)
+{
+	*var = cpu_to_le64(le64_to_cpu(*var) + val);
+}
+
 static inline void le32_and_cpu(__le32 *var, u32 val)
 {
 	*var = cpu_to_le32(le32_to_cpu(*var) & val);
diff --git a/fs/ocfs2/export.h b/fs/ocfs2/export.h
index 5b77ee7..e08bed9 100644
--- a/fs/ocfs2/export.h
+++ b/fs/ocfs2/export.h
@@ -26,6 +26,8 @@
 #ifndef OCFS2_EXPORT_H
 #define OCFS2_EXPORT_H
 
+#include <linux/exportfs.h>
+
 extern struct export_operations ocfs2_export_ops;
 
 #endif /* OCFS2_EXPORT_H */
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index ba2b2ab..03c1d365 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -109,17 +109,14 @@
  */
 void ocfs2_extent_map_trunc(struct inode *inode, unsigned int cpos)
 {
-	struct list_head *p, *n;
-	struct ocfs2_extent_map_item *emi;
+	struct ocfs2_extent_map_item *emi, *n;
 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
 	struct ocfs2_extent_map *em = &oi->ip_extent_map;
 	LIST_HEAD(tmp_list);
 	unsigned int range;
 
 	spin_lock(&oi->ip_lock);
-	list_for_each_safe(p, n, &em->em_list) {
-		emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
-
+	list_for_each_entry_safe(emi, n, &em->em_list, ei_list) {
 		if (emi->ei_cpos >= cpos) {
 			/* Full truncate of this record. */
 			list_move(&emi->ei_list, &tmp_list);
@@ -136,8 +133,7 @@
 	}
 	spin_unlock(&oi->ip_lock);
 
-	list_for_each_safe(p, n, &tmp_list) {
-		emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
+	list_for_each_entry_safe(emi, n, &tmp_list, ei_list) {
 		list_del(&emi->ei_list);
 		kfree(emi);
 	}
@@ -377,37 +373,6 @@
 	return ret;
 }
 
-/*
- * Return the index of the extent record which contains cluster #v_cluster.
- * -1 is returned if it was not found.
- *
- * Should work fine on interior and exterior nodes.
- */
-static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
-				    u32 v_cluster)
-{
-	int ret = -1;
-	int i;
-	struct ocfs2_extent_rec *rec;
-	u32 rec_end, rec_start, clusters;
-
-	for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
-		rec = &el->l_recs[i];
-
-		rec_start = le32_to_cpu(rec->e_cpos);
-		clusters = ocfs2_rec_clusters(el, rec);
-
-		rec_end = rec_start + clusters;
-
-		if (v_cluster >= rec_start && v_cluster < rec_end) {
-			ret = i;
-			break;
-		}
-	}
-
-	return ret;
-}
-
 int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
 		       u32 *p_cluster, u32 *num_clusters,
 		       unsigned int *extent_flags)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 9395b4f..004c2abb 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -31,7 +31,7 @@
 #include <linux/pagemap.h>
 #include <linux/uio.h>
 #include <linux/sched.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
 #include <linux/mount.h>
 #include <linux/writeback.h>
 
@@ -263,6 +263,7 @@
 	int status;
 	handle_t *handle;
 	struct ocfs2_dinode *di;
+	u64 cluster_bytes;
 
 	mlog_entry_void();
 
@@ -286,7 +287,9 @@
 	/*
 	 * Do this before setting i_size.
 	 */
-	status = ocfs2_zero_tail_for_truncate(inode, handle, new_i_size);
+	cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, new_i_size);
+	status = ocfs2_zero_range_for_truncate(inode, handle, new_i_size,
+					       cluster_bytes);
 	if (status) {
 		mlog_errno(status);
 		goto out_commit;
@@ -326,8 +329,6 @@
 		   (unsigned long long)OCFS2_I(inode)->ip_blkno,
 		   (unsigned long long)new_i_size);
 
-	truncate_inode_pages(inode->i_mapping, new_i_size);
-
 	fe = (struct ocfs2_dinode *) di_bh->b_data;
 	if (!OCFS2_IS_VALID_DINODE(fe)) {
 		OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
@@ -362,16 +363,23 @@
 	if (new_i_size == le64_to_cpu(fe->i_size))
 		goto bail;
 
+	down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
 	/* This forces other nodes to sync and drop their pages. Do
 	 * this even if we have a truncate without allocation change -
 	 * ocfs2 cluster sizes can be much greater than page size, so
 	 * we have to truncate them anyway.  */
 	status = ocfs2_data_lock(inode, 1);
 	if (status < 0) {
+		up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
 		mlog_errno(status);
 		goto bail;
 	}
 
+	unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
+	truncate_inode_pages(inode->i_mapping, new_i_size);
+
 	/* alright, we're going to need to do a full blown alloc size
 	 * change. Orphan the inode so that recovery can complete the
 	 * truncate if necessary. This does the task of marking
@@ -398,6 +406,8 @@
 bail_unlock_data:
 	ocfs2_data_unlock(inode, 1);
 
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
 bail:
 
 	mlog_exit(status);
@@ -418,6 +428,7 @@
 			       struct inode *inode,
 			       u32 *logical_offset,
 			       u32 clusters_to_add,
+			       int mark_unwritten,
 			       struct buffer_head *fe_bh,
 			       handle_t *handle,
 			       struct ocfs2_alloc_context *data_ac,
@@ -430,9 +441,13 @@
 	enum ocfs2_alloc_restarted reason = RESTART_NONE;
 	u32 bit_off, num_bits;
 	u64 block;
+	u8 flags = 0;
 
 	BUG_ON(!clusters_to_add);
 
+	if (mark_unwritten)
+		flags = OCFS2_EXT_UNWRITTEN;
+
 	free_extents = ocfs2_num_free_extents(osb, inode, fe);
 	if (free_extents < 0) {
 		status = free_extents;
@@ -482,7 +497,7 @@
 	     num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
 	status = ocfs2_insert_extent(osb, handle, inode, fe_bh,
 				     *logical_offset, block, num_bits,
-				     meta_ac);
+				     flags, meta_ac);
 	if (status < 0) {
 		mlog_errno(status);
 		goto leave;
@@ -515,25 +530,31 @@
  * For a given allocation, determine which allocators will need to be
  * accessed, and lock them, reserving the appropriate number of bits.
  *
- * Called from ocfs2_extend_allocation() for file systems which don't
- * support holes, and from ocfs2_write() for file systems which
- * understand sparse inodes.
+ * Sparse file systems call this from ocfs2_write_begin_nolock()
+ * and ocfs2_allocate_unwritten_extents().
+ *
+ * File systems which don't support holes call this from
+ * ocfs2_extend_allocation().
  */
 int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
-			  u32 clusters_to_add,
+			  u32 clusters_to_add, u32 extents_to_split,
 			  struct ocfs2_alloc_context **data_ac,
 			  struct ocfs2_alloc_context **meta_ac)
 {
-	int ret, num_free_extents;
+	int ret = 0, num_free_extents;
+	unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	*meta_ac = NULL;
-	*data_ac = NULL;
+	if (data_ac)
+		*data_ac = NULL;
+
+	BUG_ON(clusters_to_add != 0 && data_ac == NULL);
 
 	mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
-	     "clusters_to_add = %u\n",
+	     "clusters_to_add = %u, extents_to_split = %u\n",
 	     (unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode),
-	     le32_to_cpu(di->i_clusters), clusters_to_add);
+	     le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split);
 
 	num_free_extents = ocfs2_num_free_extents(osb, inode, di);
 	if (num_free_extents < 0) {
@@ -551,9 +572,12 @@
 	 *
 	 * Most of the time we'll only be seeing this 1 cluster at a time
 	 * anyway.
+	 *
+	 * Always lock for any unwritten extents - we might want to
+	 * add blocks during a split.
 	 */
 	if (!num_free_extents ||
-	    (ocfs2_sparse_alloc(osb) && num_free_extents < clusters_to_add)) {
+	    (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
 		ret = ocfs2_reserve_new_metadata(osb, di, meta_ac);
 		if (ret < 0) {
 			if (ret != -ENOSPC)
@@ -562,6 +586,9 @@
 		}
 	}
 
+	if (clusters_to_add == 0)
+		goto out;
+
 	ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac);
 	if (ret < 0) {
 		if (ret != -ENOSPC)
@@ -584,14 +611,13 @@
 	return ret;
 }
 
-static int ocfs2_extend_allocation(struct inode *inode,
-				   u32 clusters_to_add)
+static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
+				     u32 clusters_to_add, int mark_unwritten)
 {
 	int status = 0;
 	int restart_func = 0;
-	int drop_alloc_sem = 0;
 	int credits;
-	u32 prev_clusters, logical_start;
+	u32 prev_clusters;
 	struct buffer_head *bh = NULL;
 	struct ocfs2_dinode *fe = NULL;
 	handle_t *handle = NULL;
@@ -606,7 +632,7 @@
 	 * This function only exists for file systems which don't
 	 * support holes.
 	 */
-	BUG_ON(ocfs2_sparse_alloc(osb));
+	BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
 
 	status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
 				  OCFS2_BH_CACHED, inode);
@@ -622,19 +648,10 @@
 		goto leave;
 	}
 
-	logical_start = OCFS2_I(inode)->ip_clusters;
-
 restart_all:
 	BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
 
-	/* blocks peope in read/write from reading our allocation
-	 * until we're done changing it. We depend on i_mutex to block
-	 * other extend/truncate calls while we're here. Ordering wrt
-	 * start_trans is important here -- always do it before! */
-	down_write(&OCFS2_I(inode)->ip_alloc_sem);
-	drop_alloc_sem = 1;
-
-	status = ocfs2_lock_allocators(inode, fe, clusters_to_add, &data_ac,
+	status = ocfs2_lock_allocators(inode, fe, clusters_to_add, 0, &data_ac,
 				       &meta_ac);
 	if (status) {
 		mlog_errno(status);
@@ -667,6 +684,7 @@
 					    inode,
 					    &logical_start,
 					    clusters_to_add,
+					    mark_unwritten,
 					    bh,
 					    handle,
 					    data_ac,
@@ -719,10 +737,6 @@
 	     OCFS2_I(inode)->ip_clusters, i_size_read(inode));
 
 leave:
-	if (drop_alloc_sem) {
-		up_write(&OCFS2_I(inode)->ip_alloc_sem);
-		drop_alloc_sem = 0;
-	}
 	if (handle) {
 		ocfs2_commit_trans(osb, handle);
 		handle = NULL;
@@ -748,6 +762,25 @@
 	return status;
 }
 
+static int ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
+				   u32 clusters_to_add, int mark_unwritten)
+{
+	int ret;
+
+	/*
+	 * The alloc sem blocks peope in read/write from reading our
+	 * allocation until we're done changing it. We depend on
+	 * i_mutex to block other extend/truncate calls while we're
+	 * here.
+	 */
+	down_write(&OCFS2_I(inode)->ip_alloc_sem);
+	ret = __ocfs2_extend_allocation(inode, logical_start, clusters_to_add,
+					mark_unwritten);
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+	return ret;
+}
+
 /* Some parts of this taken from generic_cont_expand, which turned out
  * to be too fragile to do exactly what we need without us having to
  * worry about recursive locking in ->prepare_write() and
@@ -889,7 +922,9 @@
 	}
 
 	if (clusters_to_add) {
-		ret = ocfs2_extend_allocation(inode, clusters_to_add);
+		ret = ocfs2_extend_allocation(inode,
+					      OCFS2_I(inode)->ip_clusters,
+					      clusters_to_add, 0);
 		if (ret < 0) {
 			mlog_errno(ret);
 			goto out_unlock;
@@ -994,6 +1029,13 @@
 		goto bail_unlock;
 	}
 
+	/*
+	 * This will intentionally not wind up calling vmtruncate(),
+	 * since all the work for a size change has been done above.
+	 * Otherwise, we could get into problems with truncate as
+	 * ip_alloc_sem is used there to protect against i_size
+	 * changes.
+	 */
 	status = inode_setattr(inode, attr);
 	if (status < 0) {
 		mlog_errno(status);
@@ -1069,17 +1111,16 @@
 	return ret;
 }
 
-static int ocfs2_write_remove_suid(struct inode *inode)
+static int __ocfs2_write_remove_suid(struct inode *inode,
+				     struct buffer_head *bh)
 {
 	int ret;
-	struct buffer_head *bh = NULL;
-	struct ocfs2_inode_info *oi = OCFS2_I(inode);
 	handle_t *handle;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	struct ocfs2_dinode *di;
 
 	mlog_entry("(Inode %llu, mode 0%o)\n",
-		   (unsigned long long)oi->ip_blkno, inode->i_mode);
+		   (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode);
 
 	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
 	if (handle == NULL) {
@@ -1088,17 +1129,11 @@
 		goto out;
 	}
 
-	ret = ocfs2_read_block(osb, oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
-	if (ret < 0) {
-		mlog_errno(ret);
-		goto out_trans;
-	}
-
 	ret = ocfs2_journal_access(handle, inode, bh,
 				   OCFS2_JOURNAL_ACCESS_WRITE);
 	if (ret < 0) {
 		mlog_errno(ret);
-		goto out_bh;
+		goto out_trans;
 	}
 
 	inode->i_mode &= ~S_ISUID;
@@ -1111,8 +1146,7 @@
 	ret = ocfs2_journal_dirty(handle, bh);
 	if (ret < 0)
 		mlog_errno(ret);
-out_bh:
-	brelse(bh);
+
 out_trans:
 	ocfs2_commit_trans(osb, handle);
 out:
@@ -1158,6 +1192,460 @@
 	return ret;
 }
 
+static int ocfs2_write_remove_suid(struct inode *inode)
+{
+	int ret;
+	struct buffer_head *bh = NULL;
+	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+	ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+			       oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret =  __ocfs2_write_remove_suid(inode, bh);
+out:
+	brelse(bh);
+	return ret;
+}
+
+/*
+ * Allocate enough extents to cover the region starting at byte offset
+ * start for len bytes. Existing extents are skipped, any extents
+ * added are marked as "unwritten".
+ */
+static int ocfs2_allocate_unwritten_extents(struct inode *inode,
+					    u64 start, u64 len)
+{
+	int ret;
+	u32 cpos, phys_cpos, clusters, alloc_size;
+
+	/*
+	 * We consider both start and len to be inclusive.
+	 */
+	cpos = start >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+	clusters = ocfs2_clusters_for_bytes(inode->i_sb, start + len);
+	clusters -= cpos;
+
+	while (clusters) {
+		ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
+					 &alloc_size, NULL);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		/*
+		 * Hole or existing extent len can be arbitrary, so
+		 * cap it to our own allocation request.
+		 */
+		if (alloc_size > clusters)
+			alloc_size = clusters;
+
+		if (phys_cpos) {
+			/*
+			 * We already have an allocation at this
+			 * region so we can safely skip it.
+			 */
+			goto next;
+		}
+
+		ret = __ocfs2_extend_allocation(inode, cpos, alloc_size, 1);
+		if (ret) {
+			if (ret != -ENOSPC)
+				mlog_errno(ret);
+			goto out;
+		}
+
+next:
+		cpos += alloc_size;
+		clusters -= alloc_size;
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static int __ocfs2_remove_inode_range(struct inode *inode,
+				      struct buffer_head *di_bh,
+				      u32 cpos, u32 phys_cpos, u32 len,
+				      struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+	int ret;
+	u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct inode *tl_inode = osb->osb_tl_inode;
+	handle_t *handle;
+	struct ocfs2_alloc_context *meta_ac = NULL;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+
+	ret = ocfs2_lock_allocators(inode, di, 0, 1, NULL, &meta_ac);
+	if (ret) {
+		mlog_errno(ret);
+		return ret;
+	}
+
+	mutex_lock(&tl_inode->i_mutex);
+
+	if (ocfs2_truncate_log_needs_flush(osb)) {
+		ret = __ocfs2_flush_truncate_log(osb);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out;
+		}
+	}
+
+	handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
+	if (handle == NULL) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_journal_access(handle, inode, di_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac,
+				  dealloc);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	OCFS2_I(inode)->ip_clusters -= len;
+	di->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
+
+	ret = ocfs2_journal_dirty(handle, di_bh);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
+	if (ret)
+		mlog_errno(ret);
+
+out_commit:
+	ocfs2_commit_trans(osb, handle);
+out:
+	mutex_unlock(&tl_inode->i_mutex);
+
+	if (meta_ac)
+		ocfs2_free_alloc_context(meta_ac);
+
+	return ret;
+}
+
+/*
+ * Truncate a byte range, avoiding pages within partial clusters. This
+ * preserves those pages for the zeroing code to write to.
+ */
+static void ocfs2_truncate_cluster_pages(struct inode *inode, u64 byte_start,
+					 u64 byte_len)
+{
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	loff_t start, end;
+	struct address_space *mapping = inode->i_mapping;
+
+	start = (loff_t)ocfs2_align_bytes_to_clusters(inode->i_sb, byte_start);
+	end = byte_start + byte_len;
+	end = end & ~(osb->s_clustersize - 1);
+
+	if (start < end) {
+		unmap_mapping_range(mapping, start, end - start, 0);
+		truncate_inode_pages_range(mapping, start, end - 1);
+	}
+}
+
+static int ocfs2_zero_partial_clusters(struct inode *inode,
+				       u64 start, u64 len)
+{
+	int ret = 0;
+	u64 tmpend, end = start + len;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	unsigned int csize = osb->s_clustersize;
+	handle_t *handle;
+
+	/*
+	 * The "start" and "end" values are NOT necessarily part of
+	 * the range whose allocation is being deleted. Rather, this
+	 * is what the user passed in with the request. We must zero
+	 * partial clusters here. There's no need to worry about
+	 * physical allocation - the zeroing code knows to skip holes.
+	 */
+	mlog(0, "byte start: %llu, end: %llu\n",
+	     (unsigned long long)start, (unsigned long long)end);
+
+	/*
+	 * If both edges are on a cluster boundary then there's no
+	 * zeroing required as the region is part of the allocation to
+	 * be truncated.
+	 */
+	if ((start & (csize - 1)) == 0 && (end & (csize - 1)) == 0)
+		goto out;
+
+	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+	if (handle == NULL) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * We want to get the byte offset of the end of the 1st cluster.
+	 */
+	tmpend = (u64)osb->s_clustersize + (start & ~(osb->s_clustersize - 1));
+	if (tmpend > end)
+		tmpend = end;
+
+	mlog(0, "1st range: start: %llu, tmpend: %llu\n",
+	     (unsigned long long)start, (unsigned long long)tmpend);
+
+	ret = ocfs2_zero_range_for_truncate(inode, handle, start, tmpend);
+	if (ret)
+		mlog_errno(ret);
+
+	if (tmpend < end) {
+		/*
+		 * This may make start and end equal, but the zeroing
+		 * code will skip any work in that case so there's no
+		 * need to catch it up here.
+		 */
+		start = end & ~(osb->s_clustersize - 1);
+
+		mlog(0, "2nd range: start: %llu, end: %llu\n",
+		     (unsigned long long)start, (unsigned long long)end);
+
+		ret = ocfs2_zero_range_for_truncate(inode, handle, start, end);
+		if (ret)
+			mlog_errno(ret);
+	}
+
+	ocfs2_commit_trans(osb, handle);
+out:
+	return ret;
+}
+
+static int ocfs2_remove_inode_range(struct inode *inode,
+				    struct buffer_head *di_bh, u64 byte_start,
+				    u64 byte_len)
+{
+	int ret = 0;
+	u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_cached_dealloc_ctxt dealloc;
+
+	ocfs2_init_dealloc_ctxt(&dealloc);
+
+	if (byte_len == 0)
+		return 0;
+
+	trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start);
+	trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits;
+	if (trunc_len >= trunc_start)
+		trunc_len -= trunc_start;
+	else
+		trunc_len = 0;
+
+	mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, clen: %u\n",
+	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
+	     (unsigned long long)byte_start,
+	     (unsigned long long)byte_len, trunc_start, trunc_len);
+
+	ret = ocfs2_zero_partial_clusters(inode, byte_start, byte_len);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	cpos = trunc_start;
+	while (trunc_len) {
+		ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
+					 &alloc_size, NULL);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		if (alloc_size > trunc_len)
+			alloc_size = trunc_len;
+
+		/* Only do work for non-holes */
+		if (phys_cpos != 0) {
+			ret = __ocfs2_remove_inode_range(inode, di_bh, cpos,
+							 phys_cpos, alloc_size,
+							 &dealloc);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+		}
+
+		cpos += alloc_size;
+		trunc_len -= alloc_size;
+	}
+
+	ocfs2_truncate_cluster_pages(inode, byte_start, byte_len);
+
+out:
+	ocfs2_schedule_truncate_log_flush(osb, 1);
+	ocfs2_run_deallocs(osb, &dealloc);
+
+	return ret;
+}
+
+/*
+ * Parts of this function taken from xfs_change_file_space()
+ */
+int ocfs2_change_file_space(struct file *file, unsigned int cmd,
+			    struct ocfs2_space_resv *sr)
+{
+	int ret;
+	s64 llen;
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct buffer_head *di_bh = NULL;
+	handle_t *handle;
+	unsigned long long max_off = ocfs2_max_file_offset(inode->i_sb->s_blocksize_bits);
+
+	if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) &&
+	    !ocfs2_writes_unwritten_extents(osb))
+		return -ENOTTY;
+	else if ((cmd == OCFS2_IOC_UNRESVSP || cmd == OCFS2_IOC_UNRESVSP64) &&
+		 !ocfs2_sparse_alloc(osb))
+		return -ENOTTY;
+
+	if (!S_ISREG(inode->i_mode))
+		return -EINVAL;
+
+	if (!(file->f_mode & FMODE_WRITE))
+		return -EBADF;
+
+	if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
+		return -EROFS;
+
+	mutex_lock(&inode->i_mutex);
+
+	/*
+	 * This prevents concurrent writes on other nodes
+	 */
+	ret = ocfs2_rw_lock(inode, 1);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_rw_unlock;
+	}
+
+	if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
+		ret = -EPERM;
+		goto out_meta_unlock;
+	}
+
+	switch (sr->l_whence) {
+	case 0: /*SEEK_SET*/
+		break;
+	case 1: /*SEEK_CUR*/
+		sr->l_start += file->f_pos;
+		break;
+	case 2: /*SEEK_END*/
+		sr->l_start += i_size_read(inode);
+		break;
+	default:
+		ret = -EINVAL;
+		goto out_meta_unlock;
+	}
+	sr->l_whence = 0;
+
+	llen = sr->l_len > 0 ? sr->l_len - 1 : sr->l_len;
+
+	if (sr->l_start < 0
+	    || sr->l_start > max_off
+	    || (sr->l_start + llen) < 0
+	    || (sr->l_start + llen) > max_off) {
+		ret = -EINVAL;
+		goto out_meta_unlock;
+	}
+
+	if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) {
+		if (sr->l_len <= 0) {
+			ret = -EINVAL;
+			goto out_meta_unlock;
+		}
+	}
+
+	if (should_remove_suid(file->f_path.dentry)) {
+		ret = __ocfs2_write_remove_suid(inode, di_bh);
+		if (ret) {
+			mlog_errno(ret);
+			goto out_meta_unlock;
+		}
+	}
+
+	down_write(&OCFS2_I(inode)->ip_alloc_sem);
+	switch (cmd) {
+	case OCFS2_IOC_RESVSP:
+	case OCFS2_IOC_RESVSP64:
+		/*
+		 * This takes unsigned offsets, but the signed ones we
+		 * pass have been checked against overflow above.
+		 */
+		ret = ocfs2_allocate_unwritten_extents(inode, sr->l_start,
+						       sr->l_len);
+		break;
+	case OCFS2_IOC_UNRESVSP:
+	case OCFS2_IOC_UNRESVSP64:
+		ret = ocfs2_remove_inode_range(inode, di_bh, sr->l_start,
+					       sr->l_len);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_meta_unlock;
+	}
+
+	/*
+	 * We update c/mtime for these changes
+	 */
+	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		mlog_errno(ret);
+		goto out_meta_unlock;
+	}
+
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+	ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
+	if (ret < 0)
+		mlog_errno(ret);
+
+	ocfs2_commit_trans(osb, handle);
+
+out_meta_unlock:
+	brelse(di_bh);
+	ocfs2_meta_unlock(inode, 1);
+out_rw_unlock:
+	ocfs2_rw_unlock(inode, 1);
+
+	mutex_unlock(&inode->i_mutex);
+out:
+	return ret;
+}
+
 static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
 					 loff_t *ppos,
 					 size_t count,
@@ -1328,15 +1816,16 @@
 	*basep = base;
 }
 
-static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp,
+static struct page * ocfs2_get_write_source(char **ret_src_buf,
 					    const struct iovec *cur_iov,
 					    size_t iov_offset)
 {
 	int ret;
-	char *buf;
+	char *buf = cur_iov->iov_base + iov_offset;
 	struct page *src_page = NULL;
+	unsigned long off;
 
-	buf = cur_iov->iov_base + iov_offset;
+	off = (unsigned long)(buf) & ~PAGE_CACHE_MASK;
 
 	if (!segment_eq(get_fs(), KERNEL_DS)) {
 		/*
@@ -1348,18 +1837,17 @@
 				     (unsigned long)buf & PAGE_CACHE_MASK, 1,
 				     0, 0, &src_page, NULL);
 		if (ret == 1)
-			bp->b_src_buf = kmap(src_page);
+			*ret_src_buf = kmap(src_page) + off;
 		else
 			src_page = ERR_PTR(-EFAULT);
 	} else {
-		bp->b_src_buf = buf;
+		*ret_src_buf = buf;
 	}
 
 	return src_page;
 }
 
-static void ocfs2_put_write_source(struct ocfs2_buffered_write_priv *bp,
-				   struct page *page)
+static void ocfs2_put_write_source(struct page *page)
 {
 	if (page) {
 		kunmap(page);
@@ -1375,10 +1863,13 @@
 {
 	int ret = 0;
 	ssize_t copied, total = 0;
-	size_t iov_offset = 0;
+	size_t iov_offset = 0, bytes;
+	loff_t pos;
 	const struct iovec *cur_iov = iov;
-	struct ocfs2_buffered_write_priv bp;
-	struct page *page;
+	struct page *user_page, *page;
+	char * uninitialized_var(buf);
+	char *dst;
+	void *fsdata;
 
 	/*
 	 * handle partial DIO write.  Adjust cur_iov if needed.
@@ -1386,21 +1877,38 @@
 	ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written);
 
 	do {
-		bp.b_cur_off = iov_offset;
-		bp.b_cur_iov = cur_iov;
+		pos = *ppos;
 
-		page = ocfs2_get_write_source(&bp, cur_iov, iov_offset);
-		if (IS_ERR(page)) {
-			ret = PTR_ERR(page);
+		user_page = ocfs2_get_write_source(&buf, cur_iov, iov_offset);
+		if (IS_ERR(user_page)) {
+			ret = PTR_ERR(user_page);
 			goto out;
 		}
 
-		copied = ocfs2_buffered_write_cluster(file, *ppos, count,
-						      ocfs2_map_and_write_user_data,
-						      &bp);
+		/* Stay within our page boundaries */
+		bytes = min((PAGE_CACHE_SIZE - ((unsigned long)pos & ~PAGE_CACHE_MASK)),
+			    (PAGE_CACHE_SIZE - ((unsigned long)buf & ~PAGE_CACHE_MASK)));
+		/* Stay within the vector boundary */
+		bytes = min_t(size_t, bytes, cur_iov->iov_len - iov_offset);
+		/* Stay within count */
+		bytes = min(bytes, count);
 
-		ocfs2_put_write_source(&bp, page);
+		page = NULL;
+		ret = ocfs2_write_begin(file, file->f_mapping, pos, bytes, 0,
+					&page, &fsdata);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
 
+		dst = kmap_atomic(page, KM_USER0);
+		memcpy(dst + (pos & (PAGE_CACHE_SIZE - 1)), buf, bytes);
+		kunmap_atomic(dst, KM_USER0);
+		flush_dcache_page(page);
+		ocfs2_put_write_source(user_page);
+
+		copied = ocfs2_write_end(file, file->f_mapping, pos, bytes,
+					 bytes, page, fsdata);
 		if (copied < 0) {
 			mlog_errno(copied);
 			ret = copied;
@@ -1408,7 +1916,7 @@
 		}
 
 		total += copied;
-		*ppos = *ppos + copied;
+		*ppos = pos + copied;
 		count -= copied;
 
 		ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied);
@@ -1418,36 +1926,6 @@
 	return total ? total : ret;
 }
 
-static int ocfs2_check_iovec(const struct iovec *iov, size_t *counted,
-			     unsigned long *nr_segs)
-{
-	size_t ocount;		/* original count */
-	unsigned long seg;
-
-	ocount = 0;
-	for (seg = 0; seg < *nr_segs; seg++) {
-		const struct iovec *iv = &iov[seg];
-
-		/*
-		 * If any segment has a negative length, or the cumulative
-		 * length ever wraps negative then return -EINVAL.
-		 */
-		ocount += iv->iov_len;
-		if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
-			return -EINVAL;
-		if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
-			continue;
-		if (seg == 0)
-			return -EFAULT;
-		*nr_segs = seg;
-		ocount -= iv->iov_len;	/* This segment is no good */
-		break;
-	}
-
-	*counted = ocount;
-	return 0;
-}
-
 static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 				    const struct iovec *iov,
 				    unsigned long nr_segs,
@@ -1470,7 +1948,7 @@
 	if (iocb->ki_left == 0)
 		return 0;
 
-	ret = ocfs2_check_iovec(iov, &ocount, &nr_segs);
+	ret = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
 	if (ret)
 		return ret;
 
@@ -1608,52 +2086,46 @@
 				    struct pipe_buffer *buf,
 				    struct splice_desc *sd)
 {
-	int ret, count, total = 0;
+	int ret, count;
 	ssize_t copied = 0;
-	struct ocfs2_splice_write_priv sp;
+	struct file *file = sd->u.file;
+	unsigned int offset;
+	struct page *page = NULL;
+	void *fsdata;
+	char *src, *dst;
 
-	ret = buf->ops->pin(pipe, buf);
+	ret = buf->ops->confirm(pipe, buf);
 	if (ret)
 		goto out;
 
-	sp.s_sd = sd;
-	sp.s_buf = buf;
-	sp.s_pipe = pipe;
-	sp.s_offset = sd->pos & ~PAGE_CACHE_MASK;
-	sp.s_buf_offset = buf->offset;
-
+	offset = sd->pos & ~PAGE_CACHE_MASK;
 	count = sd->len;
-	if (count + sp.s_offset > PAGE_CACHE_SIZE)
-		count = PAGE_CACHE_SIZE - sp.s_offset;
+	if (count + offset > PAGE_CACHE_SIZE)
+		count = PAGE_CACHE_SIZE - offset;
 
-	do {
-		/*
-		 * splice wants us to copy up to one page at a
-		 * time. For pagesize > cluster size, this means we
-		 * might enter ocfs2_buffered_write_cluster() more
-		 * than once, so keep track of our progress here.
-		 */
-		copied = ocfs2_buffered_write_cluster(sd->file,
-						      (loff_t)sd->pos + total,
-						      count,
-						      ocfs2_map_and_write_splice_data,
-						      &sp);
-		if (copied < 0) {
-			mlog_errno(copied);
-			ret = copied;
-			goto out;
-		}
+	ret = ocfs2_write_begin(file, file->f_mapping, sd->pos, count, 0,
+				&page, &fsdata);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
 
-		count -= copied;
-		sp.s_offset += copied;
-		sp.s_buf_offset += copied;
-		total += copied;
-	} while (count);
+	src = buf->ops->map(pipe, buf, 1);
+	dst = kmap_atomic(page, KM_USER1);
+	memcpy(dst + offset, src + buf->offset, count);
+	kunmap_atomic(page, KM_USER1);
+	buf->ops->unmap(pipe, buf, src);
 
-	ret = 0;
+	copied = ocfs2_write_end(file, file->f_mapping, sd->pos, count, count,
+				 page, fsdata);
+	if (copied < 0) {
+		mlog_errno(copied);
+		ret = copied;
+		goto out;
+	}
 out:
 
-	return total ? total : ret;
+	return copied ? copied : ret;
 }
 
 static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,
@@ -1665,9 +2137,14 @@
 	int ret, err;
 	struct address_space *mapping = out->f_mapping;
 	struct inode *inode = mapping->host;
+	struct splice_desc sd = {
+		.total_len = len,
+		.flags = flags,
+		.pos = *ppos,
+		.u.file = out,
+	};
 
-	ret = __splice_from_pipe(pipe, out, ppos, len, flags,
-				 ocfs2_splice_write_actor);
+	ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor);
 	if (ret > 0) {
 		*ppos += ret;
 
@@ -1846,7 +2323,6 @@
 const struct file_operations ocfs2_fops = {
 	.read		= do_sync_read,
 	.write		= do_sync_write,
-	.sendfile	= generic_file_sendfile,
 	.mmap		= ocfs2_mmap,
 	.fsync		= ocfs2_sync_file,
 	.release	= ocfs2_file_release,
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index a4dd1fa..36fe27f 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -39,15 +39,16 @@
 };
 int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
 			       struct inode *inode,
-			       u32 *cluster_start,
+			       u32 *logical_offset,
 			       u32 clusters_to_add,
+			       int mark_unwritten,
 			       struct buffer_head *fe_bh,
 			       handle_t *handle,
 			       struct ocfs2_alloc_context *data_ac,
 			       struct ocfs2_alloc_context *meta_ac,
-			       enum ocfs2_alloc_restarted *reason);
+			       enum ocfs2_alloc_restarted *reason_ret);
 int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
-			  u32 clusters_to_add,
+			  u32 clusters_to_add, u32 extents_to_split,
 			  struct ocfs2_alloc_context **data_ac,
 			  struct ocfs2_alloc_context **meta_ac);
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
@@ -61,4 +62,7 @@
 int ocfs2_update_inode_atime(struct inode *inode,
 			     struct buffer_head *bh);
 
+int ocfs2_change_file_space(struct file *file, unsigned int cmd,
+			    struct ocfs2_space_resv *sr);
+
 #endif /* OCFS2_FILE_H */
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
index b25ef63..352eb4a 100644
--- a/fs/ocfs2/heartbeat.c
+++ b/fs/ocfs2/heartbeat.c
@@ -157,16 +157,16 @@
 	if (ocfs2_mount_local(osb))
 		return 0;
 
-	status = o2hb_register_callback(&osb->osb_hb_down);
+	status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_down);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
 	}
 
-	status = o2hb_register_callback(&osb->osb_hb_up);
+	status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_up);
 	if (status < 0) {
 		mlog_errno(status);
-		o2hb_unregister_callback(&osb->osb_hb_down);
+		o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
 	}
 
 bail:
@@ -178,8 +178,8 @@
 	if (ocfs2_mount_local(osb))
 		return;
 
-	o2hb_unregister_callback(&osb->osb_hb_down);
-	o2hb_unregister_callback(&osb->osb_hb_up);
+	o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
+	o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_up);
 }
 
 void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index f3ad21a..87dcece 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
@@ -14,6 +14,7 @@
 #include "ocfs2.h"
 #include "alloc.h"
 #include "dlmglue.h"
+#include "file.h"
 #include "inode.h"
 #include "journal.h"
 
@@ -62,7 +63,7 @@
 		goto bail_unlock;
 
 	status = -EACCES;
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		goto bail_unlock;
 
 	if (!S_ISDIR(inode->i_mode))
@@ -115,6 +116,7 @@
 {
 	unsigned int flags;
 	int status;
+	struct ocfs2_space_resv sr;
 
 	switch (cmd) {
 	case OCFS2_IOC_GETFLAGS:
@@ -130,6 +132,14 @@
 
 		return ocfs2_set_inode_attr(inode, flags,
 			OCFS2_FL_MODIFIABLE);
+	case OCFS2_IOC_RESVSP:
+	case OCFS2_IOC_RESVSP64:
+	case OCFS2_IOC_UNRESVSP:
+	case OCFS2_IOC_UNRESVSP64:
+		if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
+			return -EFAULT;
+
+		return ocfs2_change_file_space(filp, cmd, &sr);
 	default:
 		return -ENOTTY;
 	}
@@ -148,6 +158,11 @@
 	case OCFS2_IOC32_SETFLAGS:
 		cmd = OCFS2_IOC_SETFLAGS;
 		break;
+	case OCFS2_IOC_RESVSP:
+	case OCFS2_IOC_RESVSP64:
+	case OCFS2_IOC_UNRESVSP:
+	case OCFS2_IOC_UNRESVSP64:
+		break;
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index dc11880..dbfb20b 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -722,8 +722,7 @@
 		container_of(work, struct ocfs2_journal, j_recovery_work);
 	struct ocfs2_super *osb = journal->j_osb;
 	struct ocfs2_dinode *la_dinode, *tl_dinode;
-	struct ocfs2_la_recovery_item *item;
-	struct list_head *p, *n;
+	struct ocfs2_la_recovery_item *item, *n;
 	LIST_HEAD(tmp_la_list);
 
 	mlog_entry_void();
@@ -734,8 +733,7 @@
 	list_splice_init(&journal->j_la_cleanups, &tmp_la_list);
 	spin_unlock(&journal->j_lock);
 
-	list_for_each_safe(p, n, &tmp_la_list) {
-		item = list_entry(p, struct ocfs2_la_recovery_item, lri_list);
+	list_for_each_entry_safe(item, n, &tmp_la_list, lri_list) {
 		list_del_init(&item->lri_list);
 
 		mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 3db5de4..ce60aab 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -289,6 +289,8 @@
 #define OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC (OCFS2_SUBALLOC_FREE 		      \
 					 + OCFS2_TRUNCATE_LOG_UPDATE)
 
+#define OCFS2_REMOVE_EXTENT_CREDITS (OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS)
+
 /* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
  * bitmap block for the new bit) */
 #define OCFS2_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 4dedd97..545f789 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -471,9 +471,6 @@
 
 	mutex_lock(&local_alloc_inode->i_mutex);
 
-	ac->ac_inode = local_alloc_inode;
-	ac->ac_which = OCFS2_AC_USE_LOCAL;
-
 	if (osb->local_alloc_state != OCFS2_LA_ENABLED) {
 		status = -ENOSPC;
 		goto bail;
@@ -511,10 +508,14 @@
 		}
 	}
 
+	ac->ac_inode = local_alloc_inode;
+	ac->ac_which = OCFS2_AC_USE_LOCAL;
 	get_bh(osb->local_alloc_bh);
 	ac->ac_bh = osb->local_alloc_bh;
 	status = 0;
 bail:
+	if (status < 0 && local_alloc_inode)
+		iput(local_alloc_inode);
 
 	mlog_exit(status);
 	return status;
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index af01158..d79aa12 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -37,11 +37,29 @@
 
 #include "ocfs2.h"
 
+#include "aops.h"
 #include "dlmglue.h"
 #include "file.h"
 #include "inode.h"
 #include "mmap.h"
 
+static inline int ocfs2_vm_op_block_sigs(sigset_t *blocked, sigset_t *oldset)
+{
+	/* The best way to deal with signals in the vm path is
+	 * to block them upfront, rather than allowing the
+	 * locking paths to return -ERESTARTSYS. */
+	sigfillset(blocked);
+
+	/* We should technically never get a bad return value
+	 * from sigprocmask */
+	return sigprocmask(SIG_BLOCK, blocked, oldset);
+}
+
+static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
+{
+	return sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
 static struct page *ocfs2_nopage(struct vm_area_struct * area,
 				 unsigned long address,
 				 int *type)
@@ -53,14 +71,7 @@
 	mlog_entry("(area=%p, address=%lu, type=%p)\n", area, address,
 		   type);
 
-	/* The best way to deal with signals in this path is
-	 * to block them upfront, rather than allowing the
-	 * locking paths to return -ERESTARTSYS. */
-	sigfillset(&blocked);
-
-	/* We should technically never get a bad ret return
-	 * from sigprocmask */
-	ret = sigprocmask(SIG_BLOCK, &blocked, &oldset);
+	ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
 	if (ret < 0) {
 		mlog_errno(ret);
 		goto out;
@@ -68,7 +79,7 @@
 
 	page = filemap_nopage(area, address, type);
 
-	ret = sigprocmask(SIG_SETMASK, &oldset, NULL);
+	ret = ocfs2_vm_op_unblock_sigs(&oldset);
 	if (ret < 0)
 		mlog_errno(ret);
 out:
@@ -76,27 +87,135 @@
 	return page;
 }
 
+static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
+				struct page *page)
+{
+	int ret;
+	struct address_space *mapping = inode->i_mapping;
+	loff_t pos = page->index << PAGE_CACHE_SHIFT;
+	unsigned int len = PAGE_CACHE_SIZE;
+	pgoff_t last_index;
+	struct page *locked_page = NULL;
+	void *fsdata;
+	loff_t size = i_size_read(inode);
+
+	/*
+	 * Another node might have truncated while we were waiting on
+	 * cluster locks.
+	 */
+	last_index = size >> PAGE_CACHE_SHIFT;
+	if (page->index > last_index) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * The i_size check above doesn't catch the case where nodes
+	 * truncated and then re-extended the file. We'll re-check the
+	 * page mapping after taking the page lock inside of
+	 * ocfs2_write_begin_nolock().
+	 */
+	if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Call ocfs2_write_begin() and ocfs2_write_end() to take
+	 * advantage of the allocation code there. We pass a write
+	 * length of the whole page (chopped to i_size) to make sure
+	 * the whole thing is allocated.
+	 *
+	 * Since we know the page is up to date, we don't have to
+	 * worry about ocfs2_write_begin() skipping some buffer reads
+	 * because the "write" would invalidate their data.
+	 */
+	if (page->index == last_index)
+		len = size & ~PAGE_CACHE_MASK;
+
+	ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page,
+				       &fsdata, di_bh, page);
+	if (ret) {
+		if (ret != -ENOSPC)
+			mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
+				     fsdata);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+	BUG_ON(ret != len);
+	ret = 0;
+out:
+	return ret;
+}
+
+static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+	struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+	struct buffer_head *di_bh = NULL;
+	sigset_t blocked, oldset;
+	int ret, ret2;
+
+	ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
+	if (ret < 0) {
+		mlog_errno(ret);
+		return ret;
+	}
+
+	/*
+	 * The cluster locks taken will block a truncate from another
+	 * node. Taking the data lock will also ensure that we don't
+	 * attempt page truncation as part of a downconvert.
+	 */
+	ret = ocfs2_meta_lock(inode, &di_bh, 1);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * The alloc sem should be enough to serialize with
+	 * ocfs2_truncate_file() changing i_size as well as any thread
+	 * modifying the inode btree.
+	 */
+	down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+	ret = ocfs2_data_lock(inode, 1);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out_meta_unlock;
+	}
+
+	ret = __ocfs2_page_mkwrite(inode, di_bh, page);
+
+	ocfs2_data_unlock(inode, 1);
+
+out_meta_unlock:
+	up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+	brelse(di_bh);
+	ocfs2_meta_unlock(inode, 1);
+
+out:
+	ret2 = ocfs2_vm_op_unblock_sigs(&oldset);
+	if (ret2 < 0)
+		mlog_errno(ret2);
+
+	return ret;
+}
+
 static struct vm_operations_struct ocfs2_file_vm_ops = {
-	.nopage = ocfs2_nopage,
+	.nopage		= ocfs2_nopage,
+	.page_mkwrite	= ocfs2_page_mkwrite,
 };
 
 int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	int ret = 0, lock_level = 0;
-	struct ocfs2_super *osb = OCFS2_SB(file->f_dentry->d_inode->i_sb);
-
-	/*
-	 * Only support shared writeable mmap for local mounts which
-	 * don't know about holes.
-	 */
-	if ((!ocfs2_mount_local(osb) || ocfs2_sparse_alloc(osb)) &&
-	    ((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) &&
-	    ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
-		mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
-		/* This is -EINVAL because generic_file_readonly_mmap
-		 * returns it in a similar situation. */
-		return -EINVAL;
-	}
 
 	ret = ocfs2_meta_lock_atime(file->f_dentry->d_inode,
 				    file->f_vfsmnt, &lock_level);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 36289e6..d430fda 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1674,7 +1674,7 @@
 		u32 offset = 0;
 
 		inode->i_op = &ocfs2_symlink_inode_operations;
-		status = ocfs2_do_extend_allocation(osb, inode, &offset, 1,
+		status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0,
 						    new_fe_bh,
 						    handle, data_ac, NULL,
 						    NULL);
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index a860633..5cc90a4 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -219,6 +219,7 @@
 	u16 max_slots;
 	s16 node_num;
 	s16 slot_num;
+	s16 preferred_slot;
 	int s_sectsize_bits;
 	int s_clustersize;
 	int s_clustersize_bits;
@@ -305,6 +306,19 @@
 	return 0;
 }
 
+static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super *osb)
+{
+	/*
+	 * Support for sparse files is a pre-requisite
+	 */
+	if (!ocfs2_sparse_alloc(osb))
+		return 0;
+
+	if (osb->s_feature_ro_compat & OCFS2_FEATURE_RO_COMPAT_UNWRITTEN)
+		return 1;
+	return 0;
+}
+
 /* set / clear functions because cluster events can make these happen
  * in parallel so we want the transitions to be atomic. this also
  * means that any future flags osb_flags must be protected by spinlock
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index f0d9eb0..82f8a75 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -88,7 +88,7 @@
 #define OCFS2_FEATURE_COMPAT_SUPP	OCFS2_FEATURE_COMPAT_BACKUP_SB
 #define OCFS2_FEATURE_INCOMPAT_SUPP	(OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
 					 | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC)
-#define OCFS2_FEATURE_RO_COMPAT_SUPP	0
+#define OCFS2_FEATURE_RO_COMPAT_SUPP	OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
 
 /*
  * Heartbeat-only devices are missing journals and other files.  The
@@ -116,6 +116,11 @@
  */
 #define OCFS2_FEATURE_COMPAT_BACKUP_SB		0x0001
 
+/*
+ * Unwritten extents support.
+ */
+#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN	0x0001
+
 /* The byte offset of the first backup block will be 1G.
  * The following will be 4G, 16G, 64G, 256G and 1T.
  */
@@ -170,6 +175,32 @@
 #define OCFS2_IOC32_SETFLAGS	_IOW('f', 2, int)
 
 /*
+ * Space reservation / allocation / free ioctls and argument structure
+ * are designed to be compatible with XFS.
+ *
+ * ALLOCSP* and FREESP* are not and will never be supported, but are
+ * included here for completeness.
+ */
+struct ocfs2_space_resv {
+	__s16		l_type;
+	__s16		l_whence;
+	__s64		l_start;
+	__s64		l_len;		/* len == 0 means until end of file */
+	__s32		l_sysid;
+	__u32		l_pid;
+	__s32		l_pad[4];	/* reserve area			    */
+};
+
+#define OCFS2_IOC_ALLOCSP		_IOW ('X', 10, struct ocfs2_space_resv)
+#define OCFS2_IOC_FREESP		_IOW ('X', 11, struct ocfs2_space_resv)
+#define OCFS2_IOC_RESVSP		_IOW ('X', 40, struct ocfs2_space_resv)
+#define OCFS2_IOC_UNRESVSP	_IOW ('X', 41, struct ocfs2_space_resv)
+#define OCFS2_IOC_ALLOCSP64	_IOW ('X', 36, struct ocfs2_space_resv)
+#define OCFS2_IOC_FREESP64	_IOW ('X', 37, struct ocfs2_space_resv)
+#define OCFS2_IOC_RESVSP64	_IOW ('X', 42, struct ocfs2_space_resv)
+#define OCFS2_IOC_UNRESVSP64	_IOW ('X', 43, struct ocfs2_space_resv)
+
+/*
  * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
  */
 #define OCFS2_JOURNAL_DIRTY_FL	(0x00000001)	/* Journal needs recovery */
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index d8b7906..af4882b 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -121,17 +121,25 @@
 	return ret;
 }
 
-static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si)
+static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, s16 preferred)
 {
 	int i;
 	s16 ret = OCFS2_INVALID_SLOT;
 
+	if (preferred >= 0 && preferred < si->si_num_slots) {
+		if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) {
+			ret = preferred;
+			goto out;
+		}
+	}
+
 	for(i = 0; i < si->si_num_slots; i++) {
 		if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
 			ret = (s16) i;
 			break;
 		}
 	}
+out:
 	return ret;
 }
 
@@ -248,7 +256,7 @@
 	if (slot == OCFS2_INVALID_SLOT) {
 		/* if no slot yet, then just take 1st available
 		 * one. */
-		slot = __ocfs2_find_empty_slot(si);
+		slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
 		if (slot == OCFS2_INVALID_SLOT) {
 			spin_unlock(&si->si_lock);
 			mlog(ML_ERROR, "no free slots available!\n");
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index e343762..d9c5c9f 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -98,14 +98,6 @@
 				    u16 chain);
 static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
 						     u32 wanted);
-static int ocfs2_free_suballoc_bits(handle_t *handle,
-				    struct inode *alloc_inode,
-				    struct buffer_head *alloc_bh,
-				    unsigned int start_bit,
-				    u64 bg_blkno,
-				    unsigned int count);
-static inline u64 ocfs2_which_suballoc_group(u64 block,
-					     unsigned int bit);
 static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
 						   u64 bg_blkno,
 						   u16 bg_bit_off);
@@ -496,13 +488,7 @@
 
 	(*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
 	(*ac)->ac_which = OCFS2_AC_USE_META;
-
-#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
-	slot = 0;
-#else
 	slot = osb->slot_num;
-#endif
-
 	(*ac)->ac_group_search = ocfs2_block_group_search;
 
 	status = ocfs2_reserve_suballoc_bits(osb, (*ac),
@@ -1626,12 +1612,12 @@
 /*
  * expects the suballoc inode to already be locked.
  */
-static int ocfs2_free_suballoc_bits(handle_t *handle,
-				    struct inode *alloc_inode,
-				    struct buffer_head *alloc_bh,
-				    unsigned int start_bit,
-				    u64 bg_blkno,
-				    unsigned int count)
+int ocfs2_free_suballoc_bits(handle_t *handle,
+			     struct inode *alloc_inode,
+			     struct buffer_head *alloc_bh,
+			     unsigned int start_bit,
+			     u64 bg_blkno,
+			     unsigned int count)
 {
 	int status = 0;
 	u32 tmp_used;
@@ -1703,13 +1689,6 @@
 	return status;
 }
 
-static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
-{
-	u64 group = block - (u64) bit;
-
-	return group;
-}
-
 int ocfs2_free_dinode(handle_t *handle,
 		      struct inode *inode_alloc_inode,
 		      struct buffer_head *inode_alloc_bh,
@@ -1723,19 +1702,6 @@
 					inode_alloc_bh, bit, bg_blkno, 1);
 }
 
-int ocfs2_free_extent_block(handle_t *handle,
-			    struct inode *eb_alloc_inode,
-			    struct buffer_head *eb_alloc_bh,
-			    struct ocfs2_extent_block *eb)
-{
-	u64 blk = le64_to_cpu(eb->h_blkno);
-	u16 bit = le16_to_cpu(eb->h_suballoc_bit);
-	u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
-
-	return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
-					bit, bg_blkno, 1);
-}
-
 int ocfs2_free_clusters(handle_t *handle,
 		       struct inode *bitmap_inode,
 		       struct buffer_head *bitmap_bh,
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index 1a3c94c..f212dc0 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -86,20 +86,29 @@
 			 u32 *cluster_start,
 			 u32 *num_clusters);
 
+int ocfs2_free_suballoc_bits(handle_t *handle,
+			     struct inode *alloc_inode,
+			     struct buffer_head *alloc_bh,
+			     unsigned int start_bit,
+			     u64 bg_blkno,
+			     unsigned int count);
 int ocfs2_free_dinode(handle_t *handle,
 		      struct inode *inode_alloc_inode,
 		      struct buffer_head *inode_alloc_bh,
 		      struct ocfs2_dinode *di);
-int ocfs2_free_extent_block(handle_t *handle,
-			    struct inode *eb_alloc_inode,
-			    struct buffer_head *eb_alloc_bh,
-			    struct ocfs2_extent_block *eb);
 int ocfs2_free_clusters(handle_t *handle,
 			struct inode *bitmap_inode,
 			struct buffer_head *bitmap_bh,
 			u64 start_blk,
 			unsigned int num_clusters);
 
+static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
+{
+	u64 group = block - (u64) bit;
+
+	return group;
+}
+
 static inline u32 ocfs2_cluster_from_desc(struct ocfs2_super *osb,
 					  u64 bg_blkno)
 {
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 86b559c..3a5a1ed 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -82,7 +82,8 @@
 MODULE_LICENSE("GPL");
 
 static int ocfs2_parse_options(struct super_block *sb, char *options,
-			       unsigned long *mount_opt, int is_remount);
+			       unsigned long *mount_opt, s16 *slot,
+			       int is_remount);
 static void ocfs2_put_super(struct super_block *sb);
 static int ocfs2_mount_volume(struct super_block *sb);
 static int ocfs2_remount(struct super_block *sb, int *flags, char *data);
@@ -114,8 +115,6 @@
 static struct inode *ocfs2_alloc_inode(struct super_block *sb);
 static void ocfs2_destroy_inode(struct inode *inode);
 
-static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
-
 static const struct super_operations ocfs2_sops = {
 	.statfs		= ocfs2_statfs,
 	.alloc_inode	= ocfs2_alloc_inode,
@@ -140,6 +139,7 @@
 	Opt_data_ordered,
 	Opt_data_writeback,
 	Opt_atime_quantum,
+	Opt_slot,
 	Opt_err,
 };
 
@@ -154,6 +154,7 @@
 	{Opt_data_ordered, "data=ordered"},
 	{Opt_data_writeback, "data=writeback"},
 	{Opt_atime_quantum, "atime_quantum=%u"},
+	{Opt_slot, "preferred_slot=%u"},
 	{Opt_err, NULL}
 };
 
@@ -318,7 +319,7 @@
 /* From xfs_super.c:xfs_max_file_offset
  * Copyright (c) 2000-2004 Silicon Graphics, Inc.
  */
-static unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
+unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
 {
 	unsigned int pagefactor = 1;
 	unsigned int bitshift = BITS_PER_LONG - 1;
@@ -355,9 +356,10 @@
 	int incompat_features;
 	int ret = 0;
 	unsigned long parsed_options;
+	s16 slot;
 	struct ocfs2_super *osb = OCFS2_SB(sb);
 
-	if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) {
+	if (!ocfs2_parse_options(sb, data, &parsed_options, &slot, 1)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -534,6 +536,7 @@
 	struct dentry *root;
 	int status, sector_size;
 	unsigned long parsed_opt;
+	s16 slot;
 	struct inode *inode = NULL;
 	struct ocfs2_super *osb = NULL;
 	struct buffer_head *bh = NULL;
@@ -541,7 +544,7 @@
 
 	mlog_entry("%p, %p, %i", sb, data, silent);
 
-	if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
+	if (!ocfs2_parse_options(sb, data, &parsed_opt, &slot, 0)) {
 		status = -EINVAL;
 		goto read_super_error;
 	}
@@ -571,6 +574,7 @@
 	brelse(bh);
 	bh = NULL;
 	osb->s_mount_opt = parsed_opt;
+	osb->preferred_slot = slot;
 
 	sb->s_magic = OCFS2_SUPER_MAGIC;
 
@@ -713,6 +717,7 @@
 static int ocfs2_parse_options(struct super_block *sb,
 			       char *options,
 			       unsigned long *mount_opt,
+			       s16 *slot,
 			       int is_remount)
 {
 	int status;
@@ -722,6 +727,7 @@
 		   options ? options : "(none)");
 
 	*mount_opt = 0;
+	*slot = OCFS2_INVALID_SLOT;
 
 	if (!options) {
 		status = 1;
@@ -782,6 +788,15 @@
 			else
 				osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
 			break;
+		case Opt_slot:
+			option = 0;
+			if (match_int(&args[0], &option)) {
+				status = 0;
+				goto bail;
+			}
+			if (option)
+				*slot = (s16)option;
+			break;
 		default:
 			mlog(ML_ERROR,
 			     "Unrecognized mount option \"%s\" "
diff --git a/fs/ocfs2/super.h b/fs/ocfs2/super.h
index 783f527..3b9cb3d 100644
--- a/fs/ocfs2/super.h
+++ b/fs/ocfs2/super.h
@@ -45,4 +45,6 @@
 
 #define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args)
 
+unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
+
 #endif /* OCFS2_SUPER_H */
diff --git a/fs/open.c b/fs/open.c
index 0d515d1..be6a457 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -855,7 +855,7 @@
 /*
  * Find an empty file descriptor entry, and mark it busy.
  */
-int get_unused_fd(void)
+int get_unused_fd_flags(int flags)
 {
 	struct files_struct * files = current->files;
 	int fd, error;
@@ -891,7 +891,10 @@
 	}
 
 	FD_SET(fd, fdt->open_fds);
-	FD_CLR(fd, fdt->close_on_exec);
+	if (flags & O_CLOEXEC)
+		FD_SET(fd, fdt->close_on_exec);
+	else
+		FD_CLR(fd, fdt->close_on_exec);
 	files->next_fd = fd + 1;
 #if 1
 	/* Sanity check */
@@ -907,6 +910,11 @@
 	return error;
 }
 
+int get_unused_fd(void)
+{
+	return get_unused_fd_flags(0);
+}
+
 EXPORT_SYMBOL(get_unused_fd);
 
 static void __put_unused_fd(struct files_struct *files, unsigned int fd)
@@ -959,7 +967,7 @@
 	int fd = PTR_ERR(tmp);
 
 	if (!IS_ERR(tmp)) {
-		fd = get_unused_fd();
+		fd = get_unused_fd_flags(flags);
 		if (fd >= 0) {
 			struct file *f = do_filp_open(dfd, tmp, flags, mode);
 			if (IS_ERR(f)) {
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig
index 7638a1c..a99acd8 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -166,8 +166,12 @@
 	depends on PARTITION_ADVANCED
 	---help---
 	  Say Y here if you would like to use hard disks under Linux which
-	  were partitioned using Windows 2000's or XP's Logical Disk Manager.
-	  They are also known as "Dynamic Disks".
+	  were partitioned using Windows 2000's/XP's or Vista's Logical Disk
+	  Manager.  They are also known as "Dynamic Disks".
+
+	  Note this driver only supports Dynamic Disks with a protective MBR
+	  label, i.e. DOS partition table.  It does not support GPT labelled
+	  Dynamic Disks yet as can be created with Vista.
 
 	  Windows 2000 introduced the concept of Dynamic Disks to get around
 	  the limitations of the PC's partitioning scheme.  The Logical Disk
@@ -175,8 +179,8 @@
 	  mirrored, striped or RAID volumes, all without the need for
 	  rebooting.
 
-	  Normal partitions are now called Basic Disks under Windows 2000 and
-	  XP.
+	  Normal partitions are now called Basic Disks under Windows 2000, XP,
+	  and Vista.
 
 	  For a fuller description read <file:Documentation/ldm.txt>.
 
diff --git a/fs/partitions/acorn.c b/fs/partitions/acorn.c
index e349132..3d3e166 100644
--- a/fs/partitions/acorn.c
+++ b/fs/partitions/acorn.c
@@ -25,6 +25,8 @@
 #define PARTITION_RISCIX_SCSI	2
 #define PARTITION_LINUX		9
 
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+	defined(CONFIG_ACORN_PARTITION_ADFS)
 static struct adfs_discrecord *
 adfs_partition(struct parsed_partitions *state, char *name, char *data,
 	       unsigned long first_sector, int slot)
@@ -48,6 +50,7 @@
 	put_partition(state, slot, first_sector, nr_sects);
 	return dr;
 }
+#endif
 
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
 
@@ -65,6 +68,8 @@
 	struct riscix_part part[8];
 };
 
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+	defined(CONFIG_ACORN_PARTITION_ADFS)
 static int
 riscix_partition(struct parsed_partitions *state, struct block_device *bdev,
 		unsigned long first_sect, int slot, unsigned long nr_sects)
@@ -105,6 +110,7 @@
 	return slot;
 }
 #endif
+#endif
 
 #define LINUX_NATIVE_MAGIC 0xdeafa1de
 #define LINUX_SWAP_MAGIC   0xdeafab1e
@@ -115,6 +121,8 @@
 	__le32 nr_sects;
 };
 
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+	defined(CONFIG_ACORN_PARTITION_ADFS)
 static int
 linux_partition(struct parsed_partitions *state, struct block_device *bdev,
 		unsigned long first_sect, int slot, unsigned long nr_sects)
@@ -146,6 +154,7 @@
 	put_dev_sector(sect);
 	return slot;
 }
+#endif
 
 #ifdef CONFIG_ACORN_PARTITION_CUMANA
 int
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 9a3a058..98e0b85 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -397,7 +397,6 @@
 		static struct attribute addpartattr = {
 			.name = "whole_disk",
 			.mode = S_IRUSR | S_IRGRP | S_IROTH,
-			.owner = THIS_MODULE,
 		};
 
 		sysfs_create_file(&p->kobj, &addpartattr);
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index 9f7ad42..1e064c4 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -45,7 +45,7 @@
 {
 	int blocksize, offset, size,res;
 	loff_t i_size;
-	dasd_information_t *info;
+	dasd_information2_t *info;
 	struct hd_geometry *geo;
 	char type[5] = {0,};
 	char name[7] = {0,};
@@ -64,14 +64,17 @@
 	if (i_size == 0)
 		goto out_exit;
 
-	if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
+	info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
+	if (info == NULL)
 		goto out_exit;
-	if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
+	geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL);
+	if (geo == NULL)
 		goto out_nogeo;
-	if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL)
+	label = kmalloc(sizeof(union label_t), GFP_KERNEL);
+	if (label == NULL)
 		goto out_nolab;
 
-	if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
+	if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 ||
 	    ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
 		goto out_freeall;
 
@@ -96,84 +99,108 @@
 	res = 1;
 
 	/*
-	 * Three different types: CMS1, VOL1 and LNX1/unlabeled
+	 * Three different formats: LDL, CDL and unformated disk
+	 *
+	 * identified by info->format
+	 *
+	 * unformated disks we do not have to care about
 	 */
-	if (strncmp(type, "CMS1", 4) == 0) {
-		/*
-		 * VM style CMS1 labeled disk
-		 */
-		if (label->cms.disk_offset != 0) {
-			printk("CMS1/%8s(MDSK):", name);
-			/* disk is reserved minidisk */
-			blocksize = label->cms.block_size;
-			offset = label->cms.disk_offset;
-			size = (label->cms.block_count - 1) * (blocksize >> 9);
+	if (info->format == DASD_FORMAT_LDL) {
+		if (strncmp(type, "CMS1", 4) == 0) {
+			/*
+			 * VM style CMS1 labeled disk
+			 */
+			if (label->cms.disk_offset != 0) {
+				printk("CMS1/%8s(MDSK):", name);
+				/* disk is reserved minidisk */
+				blocksize = label->cms.block_size;
+				offset = label->cms.disk_offset;
+				size = (label->cms.block_count - 1)
+					* (blocksize >> 9);
+			} else {
+				printk("CMS1/%8s:", name);
+				offset = (info->label_block + 1);
+				size = i_size >> 9;
+			}
 		} else {
-			printk("CMS1/%8s:", name);
+			/*
+			 * Old style LNX1 or unlabeled disk
+			 */
+			if (strncmp(type, "LNX1", 4) == 0)
+				printk ("LNX1/%8s:", name);
+			else
+				printk("(nonl)");
 			offset = (info->label_block + 1);
 			size = i_size >> 9;
 		}
 		put_partition(state, 1, offset*(blocksize >> 9),
-				 size-offset*(blocksize >> 9));
-	} else if ((strncmp(type, "VOL1", 4) == 0) &&
-		(!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
+				      size-offset*(blocksize >> 9));
+	} else if (info->format == DASD_FORMAT_CDL) {
 		/*
-		 * New style VOL1 labeled disk
+		 * New style CDL formatted disk
 		 */
 		unsigned int blk;
 		int counter;
 
-		printk("VOL1/%8s:", name);
+		/*
+		 * check if VOL1 label is available
+		 * if not, something is wrong, skipping partition detection
+		 */
+		if (strncmp(type, "VOL1",  4) == 0) {
+			printk("VOL1/%8s:", name);
+			/*
+			 * get block number and read then go through format1
+			 * labels
+			 */
+			blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
+			counter = 0;
+			data = read_dev_sector(bdev, blk * (blocksize/512),
+					       &sect);
+			while (data != NULL) {
+				struct vtoc_format1_label f1;
 
-		/* get block number and read then go through format1 labels */
-		blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
-		counter = 0;
-		while ((data = read_dev_sector(bdev, blk*(blocksize/512),
-					       &sect)) != NULL) {
-			struct vtoc_format1_label f1;
+				memcpy(&f1, data,
+				       sizeof(struct vtoc_format1_label));
+				put_dev_sector(sect);
 
-			memcpy(&f1, data, sizeof(struct vtoc_format1_label));
-			put_dev_sector(sect);
+				/* skip FMT4 / FMT5 / FMT7 labels */
+				if (f1.DS1FMTID == _ascebc['4']
+				    || f1.DS1FMTID == _ascebc['5']
+				    || f1.DS1FMTID == _ascebc['7']) {
+					blk++;
+					data = read_dev_sector(bdev, blk *
+							       (blocksize/512),
+								&sect);
+					continue;
+				}
 
-			/* skip FMT4 / FMT5 / FMT7 labels */
-			if (f1.DS1FMTID == _ascebc['4']
-			    || f1.DS1FMTID == _ascebc['5']
-			    || f1.DS1FMTID == _ascebc['7']) {
-			        blk++;
-				continue;
+				/* only FMT1 valid at this point */
+				if (f1.DS1FMTID != _ascebc['1'])
+					break;
+
+				/* OK, we got valid partition data */
+				offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
+				size  = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
+					offset + geo->sectors;
+				if (counter >= state->limit)
+					break;
+				put_partition(state, counter + 1,
+					      offset * (blocksize >> 9),
+					      size * (blocksize >> 9));
+				counter++;
+				blk++;
+				data = read_dev_sector(bdev,
+						       blk * (blocksize/512),
+						       &sect);
 			}
 
-			/* only FMT1 valid at this point */
-			if (f1.DS1FMTID != _ascebc['1'])
-				break;
+			if (!data)
+				/* Are we not supposed to report this ? */
+				goto out_readerr;
+		} else
+			printk(KERN_WARNING "Warning, expected Label VOL1 not "
+			       "found, treating as CDL formated Disk");
 
-			/* OK, we got valid partition data */
-		        offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
-			size  = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
-				offset + geo->sectors;
-			if (counter >= state->limit)
-				break;
-			put_partition(state, counter + 1,
-				      offset * (blocksize >> 9),
-				      size * (blocksize >> 9));
-			counter++;
-			blk++;
-		}
-		if (!data)
-		/* Are we not supposed to report this ? */
-			goto out_readerr;
-	} else {
-		/*
-		 * Old style LNX1 or unlabeled disk
-		 */
-		if (strncmp(type, "LNX1", 4) == 0)
-			printk ("LNX1/%8s:", name);
-		else
-			printk("(nonl)/%8s:", name);
-		offset = (info->label_block + 1);
-		size = i_size >> 9;
-		put_partition(state, 1, offset*(blocksize >> 9),
-			      size-offset*(blocksize >> 9));
 	}
 
 	printk("\n");
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c
index 1a60926..e7dd1d4 100644
--- a/fs/partitions/ldm.c
+++ b/fs/partitions/ldm.c
@@ -2,10 +2,10 @@
  * ldm - Support for Windows Logical Disk Manager (Dynamic Disks)
  *
  * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
- * Copyright (c) 2001-2004 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
  * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
  *
- * Documentation is available at http://linux-ntfs.sf.net/ldm
+ * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/
  *
  * This program is free software; you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free Software
@@ -62,7 +62,6 @@
 	printk ("%s%s(): %s\n", level, function, buf);
 }
 
-
 /**
  * ldm_parse_hexbyte - Convert a ASCII hex number to a byte
  * @src:  Pointer to at least 2 characters to convert.
@@ -118,7 +117,6 @@
 	return true;
 }
 
-
 /**
  * ldm_parse_privhead - Read the LDM Database PRIVHEAD structure
  * @data:  Raw database PRIVHEAD structure loaded from the device
@@ -130,46 +128,48 @@
  * Return:  'true'   @ph contains the PRIVHEAD data
  *          'false'  @ph contents are undefined
  */
-static bool ldm_parse_privhead (const u8 *data, struct privhead *ph)
+static bool ldm_parse_privhead(const u8 *data, struct privhead *ph)
 {
-	BUG_ON (!data || !ph);
+	bool is_vista = false;
 
-	if (MAGIC_PRIVHEAD != BE64 (data)) {
-		ldm_error ("Cannot find PRIVHEAD structure. LDM database is"
+	BUG_ON(!data || !ph);
+	if (MAGIC_PRIVHEAD != BE64(data)) {
+		ldm_error("Cannot find PRIVHEAD structure. LDM database is"
 			" corrupt. Aborting.");
 		return false;
 	}
-
-	ph->ver_major          = BE16 (data + 0x000C);
-	ph->ver_minor          = BE16 (data + 0x000E);
-	ph->logical_disk_start = BE64 (data + 0x011B);
-	ph->logical_disk_size  = BE64 (data + 0x0123);
-	ph->config_start       = BE64 (data + 0x012B);
-	ph->config_size        = BE64 (data + 0x0133);
-
-	if ((ph->ver_major != 2) || (ph->ver_minor != 11)) {
-		ldm_error ("Expected PRIVHEAD version %d.%d, got %d.%d."
-			" Aborting.", 2, 11, ph->ver_major, ph->ver_minor);
+	ph->ver_major = BE16(data + 0x000C);
+	ph->ver_minor = BE16(data + 0x000E);
+	ph->logical_disk_start = BE64(data + 0x011B);
+	ph->logical_disk_size = BE64(data + 0x0123);
+	ph->config_start = BE64(data + 0x012B);
+	ph->config_size = BE64(data + 0x0133);
+	/* Version 2.11 is Win2k/XP and version 2.12 is Vista. */
+	if (ph->ver_major == 2 && ph->ver_minor == 12)
+		is_vista = true;
+	if (!is_vista && (ph->ver_major != 2 || ph->ver_minor != 11)) {
+		ldm_error("Expected PRIVHEAD version 2.11 or 2.12, got %d.%d."
+			" Aborting.", ph->ver_major, ph->ver_minor);
 		return false;
 	}
+	ldm_debug("PRIVHEAD version %d.%d (Windows %s).", ph->ver_major,
+			ph->ver_minor, is_vista ? "Vista" : "2000/XP");
 	if (ph->config_size != LDM_DB_SIZE) {	/* 1 MiB in sectors. */
-		/* Warn the user and continue, carefully */
-		ldm_info ("Database is normally %u bytes, it claims to "
+		/* Warn the user and continue, carefully. */
+		ldm_info("Database is normally %u bytes, it claims to "
 			"be %llu bytes.", LDM_DB_SIZE,
-			(unsigned long long)ph->config_size );
+			(unsigned long long)ph->config_size);
 	}
-	if ((ph->logical_disk_size == 0) ||
-	    (ph->logical_disk_start + ph->logical_disk_size > ph->config_start)) {
-		ldm_error ("PRIVHEAD disk size doesn't match real disk size");
+	if ((ph->logical_disk_size == 0) || (ph->logical_disk_start +
+			ph->logical_disk_size > ph->config_start)) {
+		ldm_error("PRIVHEAD disk size doesn't match real disk size");
 		return false;
 	}
-
-	if (!ldm_parse_guid (data + 0x0030, ph->disk_id)) {
-		ldm_error ("PRIVHEAD contains an invalid GUID.");
+	if (!ldm_parse_guid(data + 0x0030, ph->disk_id)) {
+		ldm_error("PRIVHEAD contains an invalid GUID.");
 		return false;
 	}
-
-	ldm_debug ("Parsed PRIVHEAD successfully.");
+	ldm_debug("Parsed PRIVHEAD successfully.");
 	return true;
 }
 
@@ -409,7 +409,7 @@
  * Return:  'true'   @toc1 contains validated TOCBLOCK info
  *          'false'  @toc1 contents are undefined
  */
-static bool ldm_validate_tocblocks (struct block_device *bdev,
+static bool ldm_validate_tocblocks(struct block_device *bdev,
 	unsigned long base, struct ldmdb *ldb)
 {
 	static const int off[4] = { OFF_TOCB1, OFF_TOCB2, OFF_TOCB3, OFF_TOCB4};
@@ -417,54 +417,57 @@
 	struct privhead *ph;
 	Sector sect;
 	u8 *data;
+	int i, nr_tbs;
 	bool result = false;
-	int i;
 
-	BUG_ON (!bdev || !ldb);
-
-	ph    = &ldb->ph;
+	BUG_ON(!bdev || !ldb);
+	ph = &ldb->ph;
 	tb[0] = &ldb->toc;
-	tb[1] = kmalloc (sizeof (*tb[1]), GFP_KERNEL);
-	tb[2] = kmalloc (sizeof (*tb[2]), GFP_KERNEL);
-	tb[3] = kmalloc (sizeof (*tb[3]), GFP_KERNEL);
-	if (!tb[1] || !tb[2] || !tb[3]) {
-		ldm_crit ("Out of memory.");
-		goto out;
+	tb[1] = kmalloc(sizeof(*tb[1]) * 3, GFP_KERNEL);
+	if (!tb[1]) {
+		ldm_crit("Out of memory.");
+		goto err;
 	}
-
-	for (i = 0; i < 4; i++)		/* Read and parse all four toc's. */
-	{
-		data = read_dev_sector (bdev, base + off[i], &sect);
+	tb[2] = (struct tocblock*)((u8*)tb[1] + sizeof(*tb[1]));
+	tb[3] = (struct tocblock*)((u8*)tb[2] + sizeof(*tb[2]));
+	/*
+	 * Try to read and parse all four TOCBLOCKs.
+	 *
+	 * Windows Vista LDM v2.12 does not always have all four TOCBLOCKs so
+	 * skip any that fail as long as we get at least one valid TOCBLOCK.
+	 */
+	for (nr_tbs = i = 0; i < 4; i++) {
+		data = read_dev_sector(bdev, base + off[i], &sect);
 		if (!data) {
-			ldm_crit ("Disk read failed.");
-			goto out;
+			ldm_error("Disk read failed for TOCBLOCK %d.", i);
+			continue;
 		}
-		result = ldm_parse_tocblock (data, tb[i]);
-		put_dev_sector (sect);
-		if (!result)
-			goto out;	/* Already logged */
+		if (ldm_parse_tocblock(data, tb[nr_tbs]))
+			nr_tbs++;
+		put_dev_sector(sect);
 	}
-
-	/* Range check the toc against a privhead. */
+	if (!nr_tbs) {
+		ldm_crit("Failed to find a valid TOCBLOCK.");
+		goto err;
+	}
+	/* Range check the TOCBLOCK against a privhead. */
 	if (((tb[0]->bitmap1_start + tb[0]->bitmap1_size) > ph->config_size) ||
-	    ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) > ph->config_size)) {
-		ldm_crit ("The bitmaps are out of range.  Giving up.");
-		goto out;
+			((tb[0]->bitmap2_start + tb[0]->bitmap2_size) >
+			ph->config_size)) {
+		ldm_crit("The bitmaps are out of range.  Giving up.");
+		goto err;
 	}
-
-	if (!ldm_compare_tocblocks (tb[0], tb[1]) ||	/* Compare all tocs. */
-	    !ldm_compare_tocblocks (tb[0], tb[2]) ||
-	    !ldm_compare_tocblocks (tb[0], tb[3])) {
-		ldm_crit ("The TOCBLOCKs don't match.");
-		goto out;
+	/* Compare all loaded TOCBLOCKs. */
+	for (i = 1; i < nr_tbs; i++) {
+		if (!ldm_compare_tocblocks(tb[0], tb[i])) {
+			ldm_crit("TOCBLOCKs 0 and %d do not match.", i);
+			goto err;
+		}
 	}
-
-	ldm_debug ("Validated TOCBLOCKs successfully.");
+	ldm_debug("Validated %d TOCBLOCKs successfully.", nr_tbs);
 	result = true;
-out:
-	kfree (tb[1]);
-	kfree (tb[2]);
-	kfree (tb[3]);
+err:
+	kfree(tb[1]);
 	return result;
 }
 
@@ -566,7 +569,7 @@
 
 	p = (struct partition*)(data + 0x01BE);
 	for (i = 0; i < 4; i++, p++)
-		if (SYS_IND (p) == WIN2K_DYNAMIC_PARTITION) {
+		if (SYS_IND (p) == LDM_PARTITION) {
 			result = true;
 			break;
 		}
@@ -674,15 +677,24 @@
  * Return:  -1 Error, the calculated offset exceeded the size of the buffer
  *           n OK, a range-checked offset into buffer
  */
-static int ldm_relative (const u8 *buffer, int buflen, int base, int offset)
+static int ldm_relative(const u8 *buffer, int buflen, int base, int offset)
 {
 
 	base += offset;
-	if ((!buffer) || (offset < 0) || (base > buflen))
+	if (!buffer || offset < 0 || base > buflen) {
+		if (!buffer)
+			ldm_error("!buffer");
+		if (offset < 0)
+			ldm_error("offset (%d) < 0", offset);
+		if (base > buflen)
+			ldm_error("base (%d) > buflen (%d)", base, buflen);
 		return -1;
-	if ((base + buffer[base]) >= buflen)
+	}
+	if (base + buffer[base] >= buflen) {
+		ldm_error("base (%d) + buffer[base] (%d) >= buflen (%d)", base,
+				buffer[base], buflen);
 		return -1;
-
+	}
 	return buffer[base] + offset + 1;
 }
 
@@ -975,44 +987,68 @@
  * Return:  'true'   @vb contains a Partition VBLK
  *          'false'  @vb contents are not defined
  */
-static bool ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb)
 {
 	int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len;
 	struct vblk_part *part;
 
-	BUG_ON (!buffer || !vb);
-
-	r_objid  = ldm_relative (buffer, buflen, 0x18, 0);
-	r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);
-	r_size   = ldm_relative (buffer, buflen, 0x34, r_name);
-	r_parent = ldm_relative (buffer, buflen, 0x34, r_size);
-	r_diskid = ldm_relative (buffer, buflen, 0x34, r_parent);
-
+	BUG_ON(!buffer || !vb);
+	r_objid = ldm_relative(buffer, buflen, 0x18, 0);
+	if (r_objid < 0) {
+		ldm_error("r_objid %d < 0", r_objid);
+		return false;
+	}
+	r_name = ldm_relative(buffer, buflen, 0x18, r_objid);
+	if (r_name < 0) {
+		ldm_error("r_name %d < 0", r_name);
+		return false;
+	}
+	r_size = ldm_relative(buffer, buflen, 0x34, r_name);
+	if (r_size < 0) {
+		ldm_error("r_size %d < 0", r_size);
+		return false;
+	}
+	r_parent = ldm_relative(buffer, buflen, 0x34, r_size);
+	if (r_parent < 0) {
+		ldm_error("r_parent %d < 0", r_parent);
+		return false;
+	}
+	r_diskid = ldm_relative(buffer, buflen, 0x34, r_parent);
+	if (r_diskid < 0) {
+		ldm_error("r_diskid %d < 0", r_diskid);
+		return false;
+	}
 	if (buffer[0x12] & VBLK_FLAG_PART_INDEX) {
-		r_index = ldm_relative (buffer, buflen, 0x34, r_diskid);
+		r_index = ldm_relative(buffer, buflen, 0x34, r_diskid);
+		if (r_index < 0) {
+			ldm_error("r_index %d < 0", r_index);
+			return false;
+		}
 		len = r_index;
 	} else {
 		r_index = 0;
 		len = r_diskid;
 	}
-	if (len < 0)
+	if (len < 0) {
+		ldm_error("len %d < 0", len);
 		return false;
-
+	}
 	len += VBLK_SIZE_PRT3;
-	if (len != BE32 (buffer + 0x14))
+	if (len > BE32(buffer + 0x14)) {
+		ldm_error("len %d > BE32(buffer + 0x14) %d", len,
+				BE32(buffer + 0x14));
 		return false;
-
+	}
 	part = &vb->vblk.part;
-	part->start         = BE64         (buffer + 0x24 + r_name);
-	part->volume_offset = BE64         (buffer + 0x2C + r_name);
-	part->size          = ldm_get_vnum (buffer + 0x34 + r_name);
-	part->parent_id     = ldm_get_vnum (buffer + 0x34 + r_size);
-	part->disk_id       = ldm_get_vnum (buffer + 0x34 + r_parent);
+	part->start = BE64(buffer + 0x24 + r_name);
+	part->volume_offset = BE64(buffer + 0x2C + r_name);
+	part->size = ldm_get_vnum(buffer + 0x34 + r_name);
+	part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size);
+	part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent);
 	if (vb->flags & VBLK_FLAG_PART_INDEX)
 		part->partnum = buffer[0x35 + r_diskid];
 	else
 		part->partnum = 0;
-
 	return true;
 }
 
@@ -1027,60 +1063,98 @@
  * Return:  'true'   @vb contains a Volume VBLK
  *          'false'  @vb contents are not defined
  */
-static bool ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb)
 {
-	int r_objid, r_name, r_vtype, r_child, r_size, r_id1, r_id2, r_size2;
-	int r_drive, len;
+	int r_objid, r_name, r_vtype, r_disable_drive_letter, r_child, r_size;
+	int r_id1, r_id2, r_size2, r_drive, len;
 	struct vblk_volu *volu;
 
-	BUG_ON (!buffer || !vb);
-
-	r_objid  = ldm_relative (buffer, buflen, 0x18, 0);
-	r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);
-	r_vtype  = ldm_relative (buffer, buflen, 0x18, r_name);
-	r_child  = ldm_relative (buffer, buflen, 0x2E, r_vtype);
-	r_size   = ldm_relative (buffer, buflen, 0x3E, r_child);
-
-	if (buffer[0x12] & VBLK_FLAG_VOLU_ID1)
-		r_id1 = ldm_relative (buffer, buflen, 0x53, r_size);
-	else
+	BUG_ON(!buffer || !vb);
+	r_objid = ldm_relative(buffer, buflen, 0x18, 0);
+	if (r_objid < 0) {
+		ldm_error("r_objid %d < 0", r_objid);
+		return false;
+	}
+	r_name = ldm_relative(buffer, buflen, 0x18, r_objid);
+	if (r_name < 0) {
+		ldm_error("r_name %d < 0", r_name);
+		return false;
+	}
+	r_vtype = ldm_relative(buffer, buflen, 0x18, r_name);
+	if (r_vtype < 0) {
+		ldm_error("r_vtype %d < 0", r_vtype);
+		return false;
+	}
+	r_disable_drive_letter = ldm_relative(buffer, buflen, 0x18, r_vtype);
+	if (r_disable_drive_letter < 0) {
+		ldm_error("r_disable_drive_letter %d < 0",
+				r_disable_drive_letter);
+		return false;
+	}
+	r_child = ldm_relative(buffer, buflen, 0x2D, r_disable_drive_letter);
+	if (r_child < 0) {
+		ldm_error("r_child %d < 0", r_child);
+		return false;
+	}
+	r_size = ldm_relative(buffer, buflen, 0x3D, r_child);
+	if (r_size < 0) {
+		ldm_error("r_size %d < 0", r_size);
+		return false;
+	}
+	if (buffer[0x12] & VBLK_FLAG_VOLU_ID1) {
+		r_id1 = ldm_relative(buffer, buflen, 0x52, r_size);
+		if (r_id1 < 0) {
+			ldm_error("r_id1 %d < 0", r_id1);
+			return false;
+		}
+	} else
 		r_id1 = r_size;
-
-	if (buffer[0x12] & VBLK_FLAG_VOLU_ID2)
-		r_id2 = ldm_relative (buffer, buflen, 0x53, r_id1);
-	else
+	if (buffer[0x12] & VBLK_FLAG_VOLU_ID2) {
+		r_id2 = ldm_relative(buffer, buflen, 0x52, r_id1);
+		if (r_id2 < 0) {
+			ldm_error("r_id2 %d < 0", r_id2);
+			return false;
+		}
+	} else
 		r_id2 = r_id1;
-
-	if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE)
-		r_size2 = ldm_relative (buffer, buflen, 0x53, r_id2);
-	else
+	if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE) {
+		r_size2 = ldm_relative(buffer, buflen, 0x52, r_id2);
+		if (r_size2 < 0) {
+			ldm_error("r_size2 %d < 0", r_size2);
+			return false;
+		}
+	} else
 		r_size2 = r_id2;
-
-	if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE)
-		r_drive = ldm_relative (buffer, buflen, 0x53, r_size2);
-	else
-		r_drive = r_size2;
-
-	len = r_drive;
-	if (len < 0)
-		return false;
-
-	len += VBLK_SIZE_VOL5;
-	if (len != BE32 (buffer + 0x14))
-		return false;
-
-	volu = &vb->vblk.volu;
-
-	ldm_get_vstr (buffer + 0x18 + r_name,  volu->volume_type,
-		sizeof (volu->volume_type));
-	memcpy (volu->volume_state, buffer + 0x19 + r_vtype,
-			sizeof (volu->volume_state));
-	volu->size = ldm_get_vnum (buffer + 0x3E + r_child);
-	volu->partition_type = buffer[0x42 + r_size];
-	memcpy (volu->guid, buffer + 0x43 + r_size,  sizeof (volu->guid));
 	if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
-		ldm_get_vstr (buffer + 0x53 + r_size,  volu->drive_hint,
-			sizeof (volu->drive_hint));
+		r_drive = ldm_relative(buffer, buflen, 0x52, r_size2);
+		if (r_drive < 0) {
+			ldm_error("r_drive %d < 0", r_drive);
+			return false;
+		}
+	} else
+		r_drive = r_size2;
+	len = r_drive;
+	if (len < 0) {
+		ldm_error("len %d < 0", len);
+		return false;
+	}
+	len += VBLK_SIZE_VOL5;
+	if (len > BE32(buffer + 0x14)) {
+		ldm_error("len %d > BE32(buffer + 0x14) %d", len,
+				BE32(buffer + 0x14));
+		return false;
+	}
+	volu = &vb->vblk.volu;
+	ldm_get_vstr(buffer + 0x18 + r_name, volu->volume_type,
+			sizeof(volu->volume_type));
+	memcpy(volu->volume_state, buffer + 0x18 + r_disable_drive_letter,
+			sizeof(volu->volume_state));
+	volu->size = ldm_get_vnum(buffer + 0x3D + r_child);
+	volu->partition_type = buffer[0x41 + r_size];
+	memcpy(volu->guid, buffer + 0x42 + r_size, sizeof(volu->guid));
+	if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
+		ldm_get_vstr(buffer + 0x52 + r_size, volu->drive_hint,
+				sizeof(volu->drive_hint));
 	}
 	return true;
 }
@@ -1475,4 +1549,3 @@
 	kfree (ldb);
 	return result;
 }
-
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h
index 6e8d795..80f63b5 100644
--- a/fs/partitions/ldm.h
+++ b/fs/partitions/ldm.h
@@ -2,10 +2,10 @@
  * ldm - Part of the Linux-NTFS project.
  *
  * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
- * Copyright (C) 2001      Anton Altaparmakov <aia21@cantab.net>
+ * Copyright (c) 2001-2007 Anton Altaparmakov
  * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
  *
- * Documentation is available at http://linux-ntfs.sf.net/ldm
+ * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -68,7 +68,7 @@
 #define VBLK_SIZE_DSK3		12
 #define VBLK_SIZE_DSK4		45
 #define VBLK_SIZE_PRT3		28
-#define VBLK_SIZE_VOL5		59
+#define VBLK_SIZE_VOL5		58
 
 /* component types */
 #define COMP_STRIPE		0x01		/* Stripe-set */
@@ -93,7 +93,7 @@
 
 #define OFF_VMDB		17		/* List of partitions. */
 
-#define WIN2K_DYNAMIC_PARTITION	0x42		/* Formerly SFS (Landis). */
+#define LDM_PARTITION		0x42		/* Formerly SFS (Landis). */
 
 #define TOC_BITMAP1		"config"	/* Names of the two defined */
 #define TOC_BITMAP2		"log"		/* bitmaps in the TOCBLOCK. */
diff --git a/fs/pipe.c b/fs/pipe.c
index 3a89592..d007830 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -164,6 +164,20 @@
 		page_cache_release(page);
 }
 
+/**
+ * generic_pipe_buf_map - virtually map a pipe buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer that should be mapped
+ * @atomic:	whether to use an atomic map
+ *
+ * Description:
+ *	This function returns a kernel virtual address mapping for the
+ *	passed in @pipe_buffer. If @atomic is set, an atomic map is provided
+ *	and the caller has to be careful not to fault before calling
+ *	the unmap function.
+ *
+ *	Note that this function occupies KM_USER0 if @atomic != 0.
+ */
 void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
 			   struct pipe_buffer *buf, int atomic)
 {
@@ -175,6 +189,15 @@
 	return kmap(buf->page);
 }
 
+/**
+ * generic_pipe_buf_unmap - unmap a previously mapped pipe buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer that should be unmapped
+ * @map_data:	the data that the mapping function returned
+ *
+ * Description:
+ *	This function undoes the mapping that ->map() provided.
+ */
 void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
 			    struct pipe_buffer *buf, void *map_data)
 {
@@ -185,11 +208,28 @@
 		kunmap(buf->page);
 }
 
+/**
+ * generic_pipe_buf_steal - attempt to take ownership of a @pipe_buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer to attempt to steal
+ *
+ * Description:
+ *	This function attempts to steal the @struct page attached to
+ *	@buf. If successful, this function returns 0 and returns with
+ *	the page locked. The caller may then reuse the page for whatever
+ *	he wishes, the typical use is insertion into a different file
+ *	page cache.
+ */
 int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
 			   struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
 
+	/*
+	 * A reference of one is golden, that means that the owner of this
+	 * page is the only one holding a reference to it. lock the page
+	 * and return OK.
+	 */
 	if (page_count(page) == 1) {
 		lock_page(page);
 		return 0;
@@ -198,12 +238,32 @@
 	return 1;
 }
 
-void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/**
+ * generic_pipe_buf_get - get a reference to a @struct pipe_buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer to get a reference to
+ *
+ * Description:
+ *	This function grabs an extra reference to @buf. It's used in
+ *	in the tee() system call, when we duplicate the buffers in one
+ *	pipe into another.
+ */
+void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
 {
 	page_cache_get(buf->page);
 }
 
-int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/**
+ * generic_pipe_buf_confirm - verify contents of the pipe buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer to confirm
+ *
+ * Description:
+ *	This function does nothing, because the generic pipe code uses
+ *	pages that are always good when inserted into the pipe.
+ */
+int generic_pipe_buf_confirm(struct pipe_inode_info *info,
+			     struct pipe_buffer *buf)
 {
 	return 0;
 }
@@ -212,7 +272,7 @@
 	.can_merge = 1,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
-	.pin = generic_pipe_buf_pin,
+	.confirm = generic_pipe_buf_confirm,
 	.release = anon_pipe_buf_release,
 	.steal = generic_pipe_buf_steal,
 	.get = generic_pipe_buf_get,
@@ -252,7 +312,7 @@
 			if (chars > total_len)
 				chars = total_len;
 
-			error = ops->pin(pipe, buf);
+			error = ops->confirm(pipe, buf);
 			if (error) {
 				if (!ret)
 					error = ret;
@@ -373,7 +433,7 @@
 			int error, atomic = 1;
 			void *addr;
 
-			error = ops->pin(pipe, buf);
+			error = ops->confirm(pipe, buf);
 			if (error)
 				goto out;
 
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 74f30e0..965625a 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -62,6 +62,8 @@
 #include <linux/mman.h>
 #include <linux/proc_fs.h>
 #include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
@@ -76,9 +78,7 @@
 #include <linux/rcupdate.h>
 #include <linux/delayacct.h>
 
-#include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/io.h>
 #include <asm/processor.h>
 #include "internal.h"
 
@@ -87,10 +87,10 @@
 do { memcpy(buffer, string, strlen(string)); \
      buffer += strlen(string); } while (0)
 
-static inline char * task_name(struct task_struct *p, char * buf)
+static inline char *task_name(struct task_struct *p, char *buf)
 {
 	int i;
-	char * name;
+	char *name;
 	char tcomm[sizeof(p->comm)];
 
 	get_task_comm(tcomm, p);
@@ -138,7 +138,7 @@
 	"X (dead)"		/* 32 */
 };
 
-static inline const char * get_task_state(struct task_struct *tsk)
+static inline const char *get_task_state(struct task_struct *tsk)
 {
 	unsigned int state = (tsk->state & (TASK_RUNNING |
 					    TASK_INTERRUPTIBLE |
@@ -156,7 +156,7 @@
 	return *p;
 }
 
-static inline char * task_state(struct task_struct *p, char *buffer)
+static inline char *task_state(struct task_struct *p, char *buffer)
 {
 	struct group_info *group_info;
 	int g;
@@ -165,7 +165,6 @@
 	rcu_read_lock();
 	buffer += sprintf(buffer,
 		"State:\t%s\n"
-		"SleepAVG:\t%lu%%\n"
 		"Tgid:\t%d\n"
 		"Pid:\t%d\n"
 		"PPid:\t%d\n"
@@ -173,9 +172,8 @@
 		"Uid:\t%d\t%d\t%d\t%d\n"
 		"Gid:\t%d\t%d\t%d\t%d\n",
 		get_task_state(p),
-		(p->sleep_avg/1024)*100/(1020000000/1024),
-	       	p->tgid, p->pid,
-	       	pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
+		p->tgid, p->pid,
+		pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
 		pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
 		p->uid, p->euid, p->suid, p->fsuid,
 		p->gid, p->egid, p->sgid, p->fsgid);
@@ -193,15 +191,15 @@
 	get_group_info(group_info);
 	task_unlock(p);
 
-	for (g = 0; g < min(group_info->ngroups,NGROUPS_SMALL); g++)
-		buffer += sprintf(buffer, "%d ", GROUP_AT(group_info,g));
+	for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
+		buffer += sprintf(buffer, "%d ", GROUP_AT(group_info, g));
 	put_group_info(group_info);
 
 	buffer += sprintf(buffer, "\n");
 	return buffer;
 }
 
-static char * render_sigset_t(const char *header, sigset_t *set, char *buffer)
+static char *render_sigset_t(const char *header, sigset_t *set, char *buffer)
 {
 	int i, len;
 
@@ -241,7 +239,7 @@
 	}
 }
 
-static inline char * task_sig(struct task_struct *p, char *buffer)
+static inline char *task_sig(struct task_struct *p, char *buffer)
 {
 	unsigned long flags;
 	sigset_t pending, shpending, blocked, ignored, caught;
@@ -291,14 +289,23 @@
 			    cap_t(p->cap_effective));
 }
 
-int proc_pid_status(struct task_struct *task, char * buffer)
+static inline char *task_context_switch_counts(struct task_struct *p,
+						char *buffer)
 {
-	char * orig = buffer;
+	return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n"
+			    "nonvoluntary_ctxt_switches:\t%lu\n",
+			    p->nvcsw,
+			    p->nivcsw);
+}
+
+int proc_pid_status(struct task_struct *task, char *buffer)
+{
+	char *orig = buffer;
 	struct mm_struct *mm = get_task_mm(task);
 
 	buffer = task_name(task, buffer);
 	buffer = task_state(task, buffer);
- 
+
 	if (mm) {
 		buffer = task_mem(mm, buffer);
 		mmput(mm);
@@ -309,10 +316,45 @@
 #if defined(CONFIG_S390)
 	buffer = task_show_regs(task, buffer);
 #endif
+	buffer = task_context_switch_counts(task, buffer);
 	return buffer - orig;
 }
 
-static int do_task_stat(struct task_struct *task, char * buffer, int whole)
+static clock_t task_utime(struct task_struct *p)
+{
+	clock_t utime = cputime_to_clock_t(p->utime),
+		total = utime + cputime_to_clock_t(p->stime);
+	u64 temp;
+
+	/*
+	 * Use CFS's precise accounting:
+	 */
+	temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
+
+	if (total) {
+		temp *= utime;
+		do_div(temp, total);
+	}
+	utime = (clock_t)temp;
+
+	return utime;
+}
+
+static clock_t task_stime(struct task_struct *p)
+{
+	clock_t stime;
+
+	/*
+	 * Use CFS's precise accounting. (we subtract utime from
+	 * the total, to make sure the total observed by userspace
+	 * grows monotonically - apps rely on that):
+	 */
+	stime = nsec_to_clock_t(p->se.sum_exec_runtime) - task_utime(p);
+
+	return stime;
+}
+
+static int do_task_stat(struct task_struct *task, char *buffer, int whole)
 {
 	unsigned long vsize, eip, esp, wchan = ~0UL;
 	long priority, nice;
@@ -320,13 +362,14 @@
 	sigset_t sigign, sigcatch;
 	char state;
 	int res;
- 	pid_t ppid = 0, pgid = -1, sid = -1;
+	pid_t ppid = 0, pgid = -1, sid = -1;
 	int num_threads = 0;
 	struct mm_struct *mm;
 	unsigned long long start_time;
 	unsigned long cmin_flt = 0, cmaj_flt = 0;
 	unsigned long  min_flt = 0,  maj_flt = 0;
-	cputime_t cutime, cstime, utime, stime;
+	cputime_t cutime, cstime;
+	clock_t utime, stime;
 	unsigned long rsslim = 0;
 	char tcomm[sizeof(task->comm)];
 	unsigned long flags;
@@ -344,7 +387,8 @@
 
 	sigemptyset(&sigign);
 	sigemptyset(&sigcatch);
-	cutime = cstime = utime = stime = cputime_zero;
+	cutime = cstime = cputime_zero;
+	utime = stime = 0;
 
 	rcu_read_lock();
 	if (lock_task_sighand(task, &flags)) {
@@ -370,15 +414,15 @@
 			do {
 				min_flt += t->min_flt;
 				maj_flt += t->maj_flt;
-				utime = cputime_add(utime, t->utime);
-				stime = cputime_add(stime, t->stime);
+				utime += task_utime(t);
+				stime += task_stime(t);
 				t = next_thread(t);
 			} while (t != task);
 
 			min_flt += sig->min_flt;
 			maj_flt += sig->maj_flt;
-			utime = cputime_add(utime, sig->utime);
-			stime = cputime_add(stime, sig->stime);
+			utime += cputime_to_clock_t(sig->utime);
+			stime += cputime_to_clock_t(sig->stime);
 		}
 
 		sid = signal_session(sig);
@@ -389,13 +433,13 @@
 	}
 	rcu_read_unlock();
 
-	if (!whole || num_threads<2)
+	if (!whole || num_threads < 2)
 		wchan = get_wchan(task);
 	if (!whole) {
 		min_flt = task->min_flt;
 		maj_flt = task->maj_flt;
-		utime = task->utime;
-		stime = task->stime;
+		utime = task_utime(task);
+		stime = task_stime(task);
 	}
 
 	/* scale priority and nice values from timeslices to -20..20 */
@@ -405,12 +449,13 @@
 
 	/* Temporary variable needed for gcc-2.96 */
 	/* convert timespec -> nsec*/
-	start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC
-				+ task->start_time.tv_nsec;
+	start_time =
+		(unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
+				+ task->real_start_time.tv_nsec;
 	/* convert nsec -> ticks */
 	start_time = nsec_to_clock_t(start_time);
 
-	res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %lu \
+	res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
 %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu\n",
 		task->pid,
@@ -426,8 +471,8 @@
 		cmin_flt,
 		maj_flt,
 		cmaj_flt,
-		cputime_to_clock_t(utime),
-		cputime_to_clock_t(stime),
+		utime,
+		stime,
 		cputime_to_clock_t(cutime),
 		cputime_to_clock_t(cstime),
 		priority,
@@ -436,7 +481,7 @@
 		start_time,
 		vsize,
 		mm ? get_mm_rss(mm) : 0,
-	        rsslim,
+		rsslim,
 		mm ? mm->start_code : 0,
 		mm ? mm->end_code : 0,
 		mm ? mm->start_stack : 0,
@@ -458,17 +503,17 @@
 		task->rt_priority,
 		task->policy,
 		(unsigned long long)delayacct_blkio_ticks(task));
-	if(mm)
+	if (mm)
 		mmput(mm);
 	return res;
 }
 
-int proc_tid_stat(struct task_struct *task, char * buffer)
+int proc_tid_stat(struct task_struct *task, char *buffer)
 {
 	return do_task_stat(task, buffer, 0);
 }
 
-int proc_tgid_stat(struct task_struct *task, char * buffer)
+int proc_tgid_stat(struct task_struct *task, char *buffer)
 {
 	return do_task_stat(task, buffer, 1);
 }
@@ -477,12 +522,12 @@
 {
 	int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
 	struct mm_struct *mm = get_task_mm(task);
-	
+
 	if (mm) {
 		size = task_statm(mm, &shared, &text, &data, &resident);
 		mmput(mm);
 	}
 
-	return sprintf(buffer,"%d %d %d %d %d %d %d\n",
+	return sprintf(buffer, "%d %d %d %d %d %d %d\n",
 		       size, resident, shared, text, lib, data, 0);
 }
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a5fa1fd..42cb4f5 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -67,7 +67,6 @@
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
-#include <linux/seccomp.h>
 #include <linux/cpuset.h>
 #include <linux/audit.h>
 #include <linux/poll.h>
@@ -204,12 +203,17 @@
 	int res = 0;
 	struct mm_struct *mm = get_task_mm(task);
 	if (mm) {
-		unsigned int len = mm->env_end - mm->env_start;
+		unsigned int len;
+
+		res = -ESRCH;
+		if (!ptrace_may_attach(task))
+			goto out;
+
+		len  = mm->env_end - mm->env_start;
 		if (len > PAGE_SIZE)
 			len = PAGE_SIZE;
 		res = access_process_vm(task, mm->env_start, buffer, len, 0);
-		if (!ptrace_may_attach(task))
-			res = -ESRCH;
+out:
 		mmput(mm);
 	}
 	return res;
@@ -279,7 +283,7 @@
 static int proc_pid_wchan(struct task_struct *task, char *buffer)
 {
 	unsigned long wchan;
-	char symname[KSYM_NAME_LEN+1];
+	char symname[KSYM_NAME_LEN];
 
 	wchan = get_wchan(task);
 
@@ -296,7 +300,7 @@
  */
 static int proc_pid_schedstat(struct task_struct *task, char *buffer)
 {
-	return sprintf(buffer, "%lu %lu %lu\n",
+	return sprintf(buffer, "%llu %llu %lu\n",
 			task->sched_info.cpu_time,
 			task->sched_info.run_delay,
 			task->sched_info.pcnt);
@@ -812,71 +816,6 @@
 };
 #endif
 
-#ifdef CONFIG_SECCOMP
-static ssize_t seccomp_read(struct file *file, char __user *buf,
-			    size_t count, loff_t *ppos)
-{
-	struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
-	char __buf[20];
-	size_t len;
-
-	if (!tsk)
-		return -ESRCH;
-	/* no need to print the trailing zero, so use only len */
-	len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
-	put_task_struct(tsk);
-
-	return simple_read_from_buffer(buf, count, ppos, __buf, len);
-}
-
-static ssize_t seccomp_write(struct file *file, const char __user *buf,
-			     size_t count, loff_t *ppos)
-{
-	struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
-	char __buf[20], *end;
-	unsigned int seccomp_mode;
-	ssize_t result;
-
-	result = -ESRCH;
-	if (!tsk)
-		goto out_no_task;
-
-	/* can set it only once to be even more secure */
-	result = -EPERM;
-	if (unlikely(tsk->seccomp.mode))
-		goto out;
-
-	result = -EFAULT;
-	memset(__buf, 0, sizeof(__buf));
-	count = min(count, sizeof(__buf) - 1);
-	if (copy_from_user(__buf, buf, count))
-		goto out;
-
-	seccomp_mode = simple_strtoul(__buf, &end, 0);
-	if (*end == '\n')
-		end++;
-	result = -EINVAL;
-	if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
-		tsk->seccomp.mode = seccomp_mode;
-		set_tsk_thread_flag(tsk, TIF_SECCOMP);
-	} else
-		goto out;
-	result = -EIO;
-	if (unlikely(!(end - __buf)))
-		goto out;
-	result = end - __buf;
-out:
-	put_task_struct(tsk);
-out_no_task:
-	return result;
-}
-
-static const struct file_operations proc_seccomp_operations = {
-	.read		= seccomp_read,
-	.write		= seccomp_write,
-};
-#endif /* CONFIG_SECCOMP */
-
 #ifdef CONFIG_FAULT_INJECTION
 static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
 				      size_t count, loff_t *ppos)
@@ -929,6 +868,69 @@
 };
 #endif
 
+#ifdef CONFIG_SCHED_DEBUG
+/*
+ * Print out various scheduling related per-task fields:
+ */
+static int sched_show(struct seq_file *m, void *v)
+{
+	struct inode *inode = m->private;
+	struct task_struct *p;
+
+	WARN_ON(!inode);
+
+	p = get_proc_task(inode);
+	if (!p)
+		return -ESRCH;
+	proc_sched_show_task(p, m);
+
+	put_task_struct(p);
+
+	return 0;
+}
+
+static ssize_t
+sched_write(struct file *file, const char __user *buf,
+	    size_t count, loff_t *offset)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct task_struct *p;
+
+	WARN_ON(!inode);
+
+	p = get_proc_task(inode);
+	if (!p)
+		return -ESRCH;
+	proc_sched_set_task(p);
+
+	put_task_struct(p);
+
+	return count;
+}
+
+static int sched_open(struct inode *inode, struct file *filp)
+{
+	int ret;
+
+	ret = single_open(filp, sched_show, NULL);
+	if (!ret) {
+		struct seq_file *m = filp->private_data;
+
+		m->private = inode;
+	}
+	return ret;
+}
+
+static const struct file_operations proc_pid_sched_operations = {
+	.open		= sched_open,
+	.read		= seq_read,
+	.write		= sched_write,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+#endif
+
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
@@ -1963,6 +1965,9 @@
 	INF("environ",    S_IRUSR, pid_environ),
 	INF("auxv",       S_IRUSR, pid_auxv),
 	INF("status",     S_IRUGO, pid_status),
+#ifdef CONFIG_SCHED_DEBUG
+	REG("sched",      S_IRUGO|S_IWUSR, pid_sched),
+#endif
 	INF("cmdline",    S_IRUGO, pid_cmdline),
 	INF("stat",       S_IRUGO, tgid_stat),
 	INF("statm",      S_IRUGO, pid_statm),
@@ -1971,9 +1976,6 @@
 	REG("numa_maps",  S_IRUGO, numa_maps),
 #endif
 	REG("mem",        S_IRUSR|S_IWUSR, mem),
-#ifdef CONFIG_SECCOMP
-	REG("seccomp",    S_IRUSR|S_IWUSR, seccomp),
-#endif
 	LNK("cwd",        cwd),
 	LNK("root",       root),
 	LNK("exe",        exe),
@@ -2247,6 +2249,9 @@
 	INF("environ",   S_IRUSR, pid_environ),
 	INF("auxv",      S_IRUSR, pid_auxv),
 	INF("status",    S_IRUGO, pid_status),
+#ifdef CONFIG_SCHED_DEBUG
+	REG("sched",     S_IRUGO|S_IWUSR, pid_sched),
+#endif
 	INF("cmdline",   S_IRUGO, pid_cmdline),
 	INF("stat",      S_IRUGO, tid_stat),
 	INF("statm",     S_IRUGO, pid_statm),
@@ -2255,9 +2260,6 @@
 	REG("numa_maps", S_IRUGO, numa_maps),
 #endif
 	REG("mem",       S_IRUSR|S_IWUSR, mem),
-#ifdef CONFIG_SECCOMP
-	REG("seccomp",   S_IRUSR|S_IWUSR, seccomp),
-#endif
 	LNK("cwd",       cwd),
 	LNK("root",      root),
 	LNK("exe",       exe),
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 8a40e15..b5e7155 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -20,6 +20,7 @@
 #include <linux/namei.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
+#include <linux/completion.h>
 #include <asm/uaccess.h>
 
 #include "internal.h"
@@ -529,12 +530,6 @@
 		return -EAGAIN;
 	dp->low_ino = i;
 
-	spin_lock(&proc_subdir_lock);
-	dp->next = dir->subdir;
-	dp->parent = dir;
-	dir->subdir = dp;
-	spin_unlock(&proc_subdir_lock);
-
 	if (S_ISDIR(dp->mode)) {
 		if (dp->proc_iops == NULL) {
 			dp->proc_fops = &proc_dir_operations;
@@ -550,6 +545,13 @@
 		if (dp->proc_iops == NULL)
 			dp->proc_iops = &proc_file_inode_operations;
 	}
+
+	spin_lock(&proc_subdir_lock);
+	dp->next = dir->subdir;
+	dp->parent = dir;
+	dir->subdir = dp;
+	spin_unlock(&proc_subdir_lock);
+
 	return 0;
 }
 
@@ -613,6 +615,9 @@
 	ent->namelen = len;
 	ent->mode = mode;
 	ent->nlink = nlink;
+	ent->pde_users = 0;
+	spin_lock_init(&ent->pde_unload_lock);
+	ent->pde_unload_completion = NULL;
  out:
 	return ent;
 }
@@ -649,9 +654,6 @@
 
 	ent = proc_create(&parent, name, S_IFDIR | mode, 2);
 	if (ent) {
-		ent->proc_fops = &proc_dir_operations;
-		ent->proc_iops = &proc_dir_inode_operations;
-
 		if (proc_register(parent, ent) < 0) {
 			kfree(ent);
 			ent = NULL;
@@ -686,10 +688,6 @@
 
 	ent = proc_create(&parent,name,mode,nlink);
 	if (ent) {
-		if (S_ISDIR(mode)) {
-			ent->proc_fops = &proc_dir_operations;
-			ent->proc_iops = &proc_dir_inode_operations;
-		}
 		if (proc_register(parent, ent) < 0) {
 			kfree(ent);
 			ent = NULL;
@@ -734,9 +732,35 @@
 		de = *p;
 		*p = de->next;
 		de->next = NULL;
+
+		spin_lock(&de->pde_unload_lock);
+		/*
+		 * Stop accepting new callers into module. If you're
+		 * dynamically allocating ->proc_fops, save a pointer somewhere.
+		 */
+		de->proc_fops = NULL;
+		/* Wait until all existing callers into module are done. */
+		if (de->pde_users > 0) {
+			DECLARE_COMPLETION_ONSTACK(c);
+
+			if (!de->pde_unload_completion)
+				de->pde_unload_completion = &c;
+
+			spin_unlock(&de->pde_unload_lock);
+			spin_unlock(&proc_subdir_lock);
+
+			wait_for_completion(de->pde_unload_completion);
+
+			spin_lock(&proc_subdir_lock);
+			goto continue_removing;
+		}
+		spin_unlock(&de->pde_unload_lock);
+
+continue_removing:
 		if (S_ISDIR(de->mode))
 			parent->nlink--;
-		proc_kill_inodes(de);
+		if (!S_ISREG(de->mode))
+			proc_kill_inodes(de);
 		de->nlink = 0;
 		WARN_ON(de->subdir);
 		if (!atomic_read(&de->count))
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index d5ce65c..dd28e86 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/completion.h>
 #include <linux/file.h>
 #include <linux/limits.h>
 #include <linux/init.h>
@@ -140,6 +141,251 @@
 	.remount_fs	= proc_remount,
 };
 
+static void pde_users_dec(struct proc_dir_entry *pde)
+{
+	spin_lock(&pde->pde_unload_lock);
+	pde->pde_users--;
+	if (pde->pde_unload_completion && pde->pde_users == 0)
+		complete(pde->pde_unload_completion);
+	spin_unlock(&pde->pde_unload_lock);
+}
+
+static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	loff_t rv = -EINVAL;
+	loff_t (*llseek)(struct file *, loff_t, int);
+
+	spin_lock(&pde->pde_unload_lock);
+	/*
+	 * remove_proc_entry() is going to delete PDE (as part of module
+	 * cleanup sequence). No new callers into module allowed.
+	 */
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	/*
+	 * Bump refcount so that remove_proc_entry will wail for ->llseek to
+	 * complete.
+	 */
+	pde->pde_users++;
+	/*
+	 * Save function pointer under lock, to protect against ->proc_fops
+	 * NULL'ifying right after ->pde_unload_lock is dropped.
+	 */
+	llseek = pde->proc_fops->llseek;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (!llseek)
+		llseek = default_llseek;
+	rv = llseek(file, offset, whence);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	ssize_t rv = -EIO;
+	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	read = pde->proc_fops->read;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (read)
+		rv = read(file, buf, count, ppos);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	ssize_t rv = -EIO;
+	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	write = pde->proc_fops->write;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (write)
+		rv = write(file, buf, count, ppos);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	unsigned int rv = 0;
+	unsigned int (*poll)(struct file *, struct poll_table_struct *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	poll = pde->proc_fops->poll;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (poll)
+		rv = poll(file, pts);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	long rv = -ENOTTY;
+	long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
+	int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	unlocked_ioctl = pde->proc_fops->unlocked_ioctl;
+	ioctl = pde->proc_fops->ioctl;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (unlocked_ioctl) {
+		rv = unlocked_ioctl(file, cmd, arg);
+		if (rv == -ENOIOCTLCMD)
+			rv = -EINVAL;
+	} else if (ioctl) {
+		lock_kernel();
+		rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
+		unlock_kernel();
+	}
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+#ifdef CONFIG_COMPAT
+static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	long rv = -ENOTTY;
+	long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	compat_ioctl = pde->proc_fops->compat_ioctl;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (compat_ioctl)
+		rv = compat_ioctl(file, cmd, arg);
+
+	pde_users_dec(pde);
+	return rv;
+}
+#endif
+
+static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+	int rv = -EIO;
+	int (*mmap)(struct file *, struct vm_area_struct *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	mmap = pde->proc_fops->mmap;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (mmap)
+		rv = mmap(file, vma);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static int proc_reg_open(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *pde = PDE(inode);
+	int rv = 0;
+	int (*open)(struct inode *, struct file *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	open = pde->proc_fops->open;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (open)
+		rv = open(inode, file);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static int proc_reg_release(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *pde = PDE(inode);
+	int rv = 0;
+	int (*release)(struct inode *, struct file *);
+
+	spin_lock(&pde->pde_unload_lock);
+	if (!pde->proc_fops) {
+		spin_unlock(&pde->pde_unload_lock);
+		return rv;
+	}
+	pde->pde_users++;
+	release = pde->proc_fops->release;
+	spin_unlock(&pde->pde_unload_lock);
+
+	if (release)
+		rv = release(inode, file);
+
+	pde_users_dec(pde);
+	return rv;
+}
+
+static const struct file_operations proc_reg_file_ops = {
+	.llseek		= proc_reg_llseek,
+	.read		= proc_reg_read,
+	.write		= proc_reg_write,
+	.poll		= proc_reg_poll,
+	.unlocked_ioctl	= proc_reg_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= proc_reg_compat_ioctl,
+#endif
+	.mmap		= proc_reg_mmap,
+	.open		= proc_reg_open,
+	.release	= proc_reg_release,
+};
+
 struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
 				struct proc_dir_entry *de)
 {
@@ -166,8 +412,12 @@
 			inode->i_nlink = de->nlink;
 		if (de->proc_iops)
 			inode->i_op = de->proc_iops;
-		if (de->proc_fops)
-			inode->i_fop = de->proc_fops;
+		if (de->proc_fops) {
+			if (S_ISREG(inode->i_mode))
+				inode->i_fop = &proc_reg_file_ops;
+			else
+				inode->i_fop = de->proc_fops;
+		}
 	}
 
 	return inode;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 5fd49e4..d24b8d4 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -105,6 +105,7 @@
 	cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
 
 	do_posix_clock_monotonic_gettime(&uptime);
+	monotonic_to_bootbased(&uptime);
 	cputime_to_timespec(idletime, &idle);
 	len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
 			(unsigned long) uptime.tv_sec,
@@ -443,12 +444,12 @@
 	unsigned long jif;
 	cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
 	u64 sum = 0;
+	struct timespec boottime;
 
 	user = nice = system = idle = iowait =
 		irq = softirq = steal = cputime64_zero;
-	jif = - wall_to_monotonic.tv_sec;
-	if (wall_to_monotonic.tv_nsec)
-		--jif;
+	getboottime(&boottime);
+	jif = boottime.tv_sec;
 
 	for_each_possible_cpu(i) {
 		int j;
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index b3a473b..2284622 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -69,7 +69,7 @@
 
 static int show_tty_driver(struct seq_file *m, void *v)
 {
-	struct tty_driver *p = v;
+	struct tty_driver *p = list_entry(v, struct tty_driver, tty_drivers);
 	dev_t from = MKDEV(p->major, p->minor_start);
 	dev_t to = from + p->num;
 
@@ -106,22 +106,13 @@
 /* iterator */
 static void *t_start(struct seq_file *m, loff_t *pos)
 {
-	struct list_head *p;
-	loff_t l = *pos;
-
 	mutex_lock(&tty_mutex);
-	list_for_each(p, &tty_drivers)
-		if (!l--)
-			return list_entry(p, struct tty_driver, tty_drivers);
-	return NULL;
+	return seq_list_start(&tty_drivers, *pos);
 }
 
 static void *t_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	struct list_head *p = ((struct tty_driver *)v)->tty_drivers.next;
-	(*pos)++;
-	return p==&tty_drivers ? NULL :
-			list_entry(p, struct tty_driver, tty_drivers);
+	return seq_list_next(v, &tty_drivers, pos);
 }
 
 static void t_stop(struct seq_file *m, void *v)
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 4464998..867f42b 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -25,7 +25,7 @@
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 #ifdef CONFIG_QNX4FS_RW
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
diff --git a/fs/quota.c b/fs/quota.c
index 9f237d6..e6577ac 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -10,12 +10,14 @@
 #include <linux/slab.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
+#include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/types.h>
 
 /* Check validity of generic quotactl commands */
 static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
@@ -384,3 +386,119 @@
 
 	return ret;
 }
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+/*
+ * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
+ * and is necessary due to alignment problems.
+ */
+struct compat_if_dqblk {
+	compat_u64 dqb_bhardlimit;
+	compat_u64 dqb_bsoftlimit;
+	compat_u64 dqb_curspace;
+	compat_u64 dqb_ihardlimit;
+	compat_u64 dqb_isoftlimit;
+	compat_u64 dqb_curinodes;
+	compat_u64 dqb_btime;
+	compat_u64 dqb_itime;
+	compat_uint_t dqb_valid;
+};
+
+/* XFS structures */
+struct compat_fs_qfilestat {
+	compat_u64 dqb_bhardlimit;
+	compat_u64 qfs_nblks;
+	compat_uint_t qfs_nextents;
+};
+
+struct compat_fs_quota_stat {
+	__s8		qs_version;
+	__u16		qs_flags;
+	__s8		qs_pad;
+	struct compat_fs_qfilestat	qs_uquota;
+	struct compat_fs_qfilestat	qs_gquota;
+	compat_uint_t	qs_incoredqs;
+	compat_int_t	qs_btimelimit;
+	compat_int_t	qs_itimelimit;
+	compat_int_t	qs_rtbtimelimit;
+	__u16		qs_bwarnlimit;
+	__u16		qs_iwarnlimit;
+};
+
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	unsigned int cmds;
+	struct if_dqblk __user *dqblk;
+	struct compat_if_dqblk __user *compat_dqblk;
+	struct fs_quota_stat __user *fsqstat;
+	struct compat_fs_quota_stat __user *compat_fsqstat;
+	compat_uint_t data;
+	u16 xdata;
+	long ret;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+	case Q_GETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		if (ret)
+			break;
+		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &dqblk->dqb_valid) ||
+			put_user(data, &compat_dqblk->dqb_valid))
+			ret = -EFAULT;
+		break;
+	case Q_SETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = -EFAULT;
+		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &compat_dqblk->dqb_valid) ||
+			put_user(data, &dqblk->dqb_valid))
+			break;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		break;
+	case Q_XGETQSTAT:
+		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
+		compat_fsqstat = addr;
+		ret = sys_quotactl(cmd, special, id, fsqstat);
+		if (ret)
+			break;
+		ret = -EFAULT;
+		/* Copying qs_version, qs_flags, qs_pad */
+		if (copy_in_user(compat_fsqstat, fsqstat,
+			offsetof(struct compat_fs_quota_stat, qs_uquota)))
+			break;
+		/* Copying qs_uquota */
+		if (copy_in_user(&compat_fsqstat->qs_uquota,
+			&fsqstat->qs_uquota,
+			sizeof(compat_fsqstat->qs_uquota)) ||
+			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
+			break;
+		/* Copying qs_gquota */
+		if (copy_in_user(&compat_fsqstat->qs_gquota,
+			&fsqstat->qs_gquota,
+			sizeof(compat_fsqstat->qs_gquota)) ||
+			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
+			break;
+		/* Copying the rest */
+		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
+			&fsqstat->qs_incoredqs,
+			sizeof(struct compat_fs_quota_stat) -
+			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
+			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
+			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
+			break;
+		ret = 0;
+		break;
+	default:
+		ret = sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}
+#endif
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 2f14774..97bdc0b 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -41,7 +41,7 @@
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= simple_sync_file,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.llseek		= generic_file_llseek,
 };
 
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 3b481d5..cad2b7a 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -42,7 +42,7 @@
 	.write			= do_sync_write,
 	.aio_write		= generic_file_aio_write,
 	.fsync			= simple_sync_file,
-	.sendfile		= generic_file_sendfile,
+	.splice_read		= generic_file_splice_read,
 	.llseek			= generic_file_llseek,
 };
 
@@ -179,7 +179,7 @@
 			return ret;
 	}
 
-	ret = vmtruncate(inode, size);
+	ret = vmtruncate(inode, newsize);
 
 	return ret;
 }
@@ -195,6 +195,11 @@
 	unsigned int old_ia_valid = ia->ia_valid;
 	int ret = 0;
 
+	/* POSIX UID/GID verification for setting inode attributes */
+	ret = inode_change_ok(inode, ia);
+	if (ret)
+		return ret;
+
 	/* by providing our own setattr() method, we skip this quotaism */
 	if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) ||
 	    (old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid))
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 4ace5d7..ef2b46d 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -32,7 +32,7 @@
 #include <linux/string.h>
 #include <linux/backing-dev.h>
 #include <linux/ramfs.h>
-
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -60,6 +60,7 @@
 		inode->i_blocks = 0;
 		inode->i_mapping->a_ops = &ramfs_aops;
 		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
+		mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		switch (mode & S_IFMT) {
 		default:
diff --git a/fs/read_write.c b/fs/read_write.c
index 4d03008..507ddff 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/pagemap.h>
+#include <linux/splice.h>
 #include "read_write.h"
 
 #include <asm/uaccess.h>
@@ -25,7 +26,7 @@
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
 	.mmap		= generic_file_readonly_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 EXPORT_SYMBOL(generic_ro_fops);
@@ -708,7 +709,7 @@
 	struct inode * in_inode, * out_inode;
 	loff_t pos;
 	ssize_t retval;
-	int fput_needed_in, fput_needed_out;
+	int fput_needed_in, fput_needed_out, fl;
 
 	/*
 	 * Get input file, and verify that it is ok..
@@ -723,7 +724,7 @@
 	in_inode = in_file->f_path.dentry->d_inode;
 	if (!in_inode)
 		goto fput_in;
-	if (!in_file->f_op || !in_file->f_op->sendfile)
+	if (!in_file->f_op || !in_file->f_op->splice_read)
 		goto fput_in;
 	retval = -ESPIPE;
 	if (!ppos)
@@ -776,7 +777,18 @@
 		count = max - pos;
 	}
 
-	retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
+	fl = 0;
+#if 0
+	/*
+	 * We need to debate whether we can enable this or not. The
+	 * man page documents EAGAIN return for the output at least,
+	 * and the application is arguably buggy if it doesn't expect
+	 * EAGAIN on a non-blocking file descriptor.
+	 */
+	if (in_file->f_flags & O_NONBLOCK)
+		fl = SPLICE_F_NONBLOCK;
+#endif
+	retval = do_splice_direct(in_file, ppos, out_file, count, fl);
 
 	if (retval > 0) {
 		add_rchar(current, retval);
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index 9c23fee..ffbfc2c 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -10,7 +10,7 @@
 #include <linux/buffer_head.h>
 #include <asm/uaccess.h>
 
-extern struct reiserfs_key MIN_KEY;
+extern const struct reiserfs_key MIN_KEY;
 
 static int reiserfs_readdir(struct file *, void *, filldir_t);
 static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 9e451a6..2070aee 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1305,7 +1305,6 @@
 	if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
 	    *ppos + count > MAX_NON_LFS) {
 		if (*ppos >= MAX_NON_LFS) {
-			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
 		}
 		if (count > MAX_NON_LFS - (unsigned long)*ppos)
@@ -1531,7 +1530,6 @@
 	.open = generic_file_open,
 	.release = reiserfs_file_release,
 	.fsync = reiserfs_sync_file,
-	.sendfile = generic_file_sendfile,
 	.aio_read = generic_file_aio_read,
 	.aio_write = generic_file_aio_write,
 	.splice_read = generic_file_splice_read,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 1272d11..ddde489 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -7,6 +7,7 @@
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
 #include <linux/reiserfs_xattr.h>
+#include <linux/exportfs.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index b484d29..11a0fcc 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -51,8 +51,7 @@
 			if (IS_RDONLY(inode))
 				return -EROFS;
 
-			if ((current->fsuid != inode->i_uid)
-			    && !capable(CAP_FOWNER))
+			if (!is_owner_or_cap(inode))
 				return -EPERM;
 
 			if (get_user(flags, (int __user *)arg))
@@ -81,7 +80,7 @@
 	case REISERFS_IOC_GETVERSION:
 		return put_user(inode->i_generation, (int __user *)arg);
 	case REISERFS_IOC_SETVERSION:
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if (!is_owner_or_cap(inode))
 			return -EPERM;
 		if (IS_RDONLY(inode))
 			return -EROFS;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b4ac911..5a93cfe 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/mnt_namespace.h>
 #include <linux/mount.h>
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 5296a29..b7e4fa4 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -21,7 +21,7 @@
 
 	if (!reiserfs_posixacl(inode->i_sb))
 		return -EOPNOTSUPP;
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		return -EPERM;
 
 	if (value) {
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 0ac22af..bbb19be 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -177,21 +177,23 @@
 
 static int traverse(struct seq_file *m, loff_t offset)
 {
-	loff_t pos = 0;
+	loff_t pos = 0, index;
 	int error = 0;
 	void *p;
 
 	m->version = 0;
-	m->index = 0;
+	index = 0;
 	m->count = m->from = 0;
-	if (!offset)
+	if (!offset) {
+		m->index = index;
 		return 0;
+	}
 	if (!m->buf) {
 		m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
 		if (!m->buf)
 			return -ENOMEM;
 	}
-	p = m->op->start(m, &m->index);
+	p = m->op->start(m, &index);
 	while (p) {
 		error = PTR_ERR(p);
 		if (IS_ERR(p))
@@ -204,15 +206,17 @@
 		if (pos + m->count > offset) {
 			m->from = offset - pos;
 			m->count -= m->from;
+			m->index = index;
 			break;
 		}
 		pos += m->count;
 		m->count = 0;
 		if (pos == offset) {
-			m->index++;
+			index++;
+			m->index = index;
 			break;
 		}
-		p = m->op->next(m, p, &m->index);
+		p = m->op->next(m, p, &index);
 	}
 	m->op->stop(m, p);
 	return error;
@@ -260,8 +264,8 @@
 				}
 			}
 	}
-	mutex_unlock(&m->lock);
 	file->f_version = m->version;
+	mutex_unlock(&m->lock);
 	return retval;
 }
 EXPORT_SYMBOL(seq_lseek);
@@ -447,3 +451,37 @@
 	return -1;
 }
 EXPORT_SYMBOL(seq_puts);
+
+struct list_head *seq_list_start(struct list_head *head, loff_t pos)
+{
+	struct list_head *lh;
+
+	list_for_each(lh, head)
+		if (pos-- == 0)
+			return lh;
+
+	return NULL;
+}
+
+EXPORT_SYMBOL(seq_list_start);
+
+struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
+{
+	if (!pos)
+		return head;
+
+	return seq_list_start(head, pos - 1);
+}
+
+EXPORT_SYMBOL(seq_list_start_head);
+
+struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
+{
+	struct list_head *lh;
+
+	lh = ((struct list_head *)v)->next;
+	++*ppos;
+	return lh == head ? NULL : lh;
+}
+
+EXPORT_SYMBOL(seq_list_next);
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 7cfeab4..3b07f26 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -11,6 +11,8 @@
  *      Now using anonymous inode source.
  *      Thanks to Oleg Nesterov for useful code review and suggestions.
  *      More comments and suggestions from Arnd Bergmann.
+ * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br>
+ *      Retrieve multiple signals with one read() call
  */
 
 #include <linux/file.h>
@@ -131,7 +133,8 @@
 	 * the peer disconnects.
 	 */
 	if (signalfd_lock(ctx, &lk)) {
-		if (next_signal(&lk.tsk->pending, &ctx->sigmask) > 0 ||
+		if ((lk.tsk == current &&
+		     next_signal(&lk.tsk->pending, &ctx->sigmask) > 0) ||
 		    next_signal(&lk.tsk->signal->shared_pending,
 				&ctx->sigmask) > 0)
 			events |= POLLIN;
@@ -206,6 +209,59 @@
 	return err ? -EFAULT: sizeof(*uinfo);
 }
 
+static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info,
+				int nonblock)
+{
+	ssize_t ret;
+	struct signalfd_lockctx lk;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (!signalfd_lock(ctx, &lk))
+		return 0;
+
+	ret = dequeue_signal(lk.tsk, &ctx->sigmask, info);
+	switch (ret) {
+	case 0:
+		if (!nonblock)
+			break;
+		ret = -EAGAIN;
+	default:
+		signalfd_unlock(&lk);
+		return ret;
+	}
+
+	add_wait_queue(&ctx->wqh, &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		ret = dequeue_signal(lk.tsk, &ctx->sigmask, info);
+		signalfd_unlock(&lk);
+		if (ret != 0)
+			break;
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+		schedule();
+		ret = signalfd_lock(ctx, &lk);
+		if (unlikely(!ret)) {
+			/*
+			 * Let the caller read zero byte, ala socket
+			 * recv() when the peer disconnect. This test
+			 * must be done before doing a dequeue_signal(),
+			 * because if the sighand has been orphaned,
+			 * the dequeue_signal() call is going to crash
+			 * because ->sighand will be long gone.
+			 */
+			 break;
+		}
+	}
+
+	remove_wait_queue(&ctx->wqh, &wait);
+	__set_current_state(TASK_RUNNING);
+
+	return ret;
+}
+
 /*
  * Returns either the size of a "struct signalfd_siginfo", or zero if the
  * sighand we are attached to, has been orphaned. The "count" parameter
@@ -215,55 +271,30 @@
 			     loff_t *ppos)
 {
 	struct signalfd_ctx *ctx = file->private_data;
-	ssize_t res = 0;
-	int locked, signo;
+	struct signalfd_siginfo __user *siginfo;
+	int nonblock = file->f_flags & O_NONBLOCK;
+	ssize_t ret, total = 0;
 	siginfo_t info;
-	struct signalfd_lockctx lk;
-	DECLARE_WAITQUEUE(wait, current);
 
-	if (count < sizeof(struct signalfd_siginfo))
+	count /= sizeof(struct signalfd_siginfo);
+	if (!count)
 		return -EINVAL;
-	locked = signalfd_lock(ctx, &lk);
-	if (!locked)
-		return 0;
-	res = -EAGAIN;
-	signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info);
-	if (signo == 0 && !(file->f_flags & O_NONBLOCK)) {
-		add_wait_queue(&ctx->wqh, &wait);
-		for (;;) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info);
-			if (signo != 0)
-				break;
-			if (signal_pending(current)) {
-				res = -ERESTARTSYS;
-				break;
-			}
-			signalfd_unlock(&lk);
-			schedule();
-			locked = signalfd_lock(ctx, &lk);
-			if (unlikely(!locked)) {
-				/*
-				 * Let the caller read zero byte, ala socket
-				 * recv() when the peer disconnect. This test
-				 * must be done before doing a dequeue_signal(),
-				 * because if the sighand has been orphaned,
-				 * the dequeue_signal() call is going to crash.
-				 */
-				res = 0;
-				break;
-			}
-		}
-		remove_wait_queue(&ctx->wqh, &wait);
-		__set_current_state(TASK_RUNNING);
-	}
-	if (likely(locked))
-		signalfd_unlock(&lk);
-	if (likely(signo))
-		res = signalfd_copyinfo((struct signalfd_siginfo __user *) buf,
-					&info);
 
-	return res;
+	siginfo = (struct signalfd_siginfo __user *) buf;
+
+	do {
+		ret = signalfd_dequeue(ctx, &info, nonblock);
+		if (unlikely(ret <= 0))
+			break;
+		ret = signalfd_copyinfo(siginfo, &info);
+		if (ret < 0)
+			break;
+		siginfo++;
+		total += ret;
+		nonblock = 1;
+	} while (--count);
+
+	return total ? total : ret;
 }
 
 static const struct file_operations signalfd_fops = {
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 50136b1..48da4fa 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -13,6 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/ctype.h>
 #include <linux/net.h>
+#include <linux/sched.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smb_mount.h>
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index f161797..c5d78a7 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -17,6 +17,7 @@
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 #include <linux/net.h>
+#include <linux/aio.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -261,8 +262,9 @@
 }
 
 static ssize_t
-smb_file_sendfile(struct file *file, loff_t *ppos,
-		  size_t count, read_actor_t actor, void *target)
+smb_file_splice_read(struct file *file, loff_t *ppos,
+		     struct pipe_inode_info *pipe, size_t count,
+		     unsigned int flags)
 {
 	struct dentry *dentry = file->f_path.dentry;
 	ssize_t status;
@@ -276,7 +278,7 @@
 			 DENTRY_PATH(dentry), status);
 		goto out;
 	}
-	status = generic_file_sendfile(file, ppos, count, actor, target);
+	status = generic_file_splice_read(file, ppos, pipe, count, flags);
 out:
 	return status;
 }
@@ -415,7 +417,7 @@
 	.open		= smb_file_open,
 	.release	= smb_file_release,
 	.fsync		= smb_fsync,
-	.sendfile	= smb_file_sendfile,
+	.splice_read	= smb_file_splice_read,
 };
 
 const struct inode_operations smb_file_inode_operations =
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 5c9243a..6724a6c 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -25,6 +25,7 @@
 #include <linux/net.h>
 #include <linux/vfs.h>
 #include <linux/highuid.h>
+#include <linux/sched.h>
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
 #include <linux/smb_mount.h>
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index c288fbe..3f54a0f 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -11,6 +11,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/net.h>
+#include <linux/sched.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
diff --git a/fs/splice.c b/fs/splice.c
index 12f2828..53fc208 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -20,7 +20,7 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/pagemap.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
 #include <linux/mm_inline.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
@@ -28,22 +28,7 @@
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/uio.h>
-
-struct partial_page {
-	unsigned int offset;
-	unsigned int len;
-};
-
-/*
- * Passed to splice_to_pipe
- */
-struct splice_pipe_desc {
-	struct page **pages;		/* page map */
-	struct partial_page *partial;	/* pages[] may not be contig */
-	int nr_pages;			/* number of pages in map */
-	unsigned int flags;		/* splice flags */
-	const struct pipe_buf_operations *ops;/* ops associated with output pipe */
-};
+#include <linux/security.h>
 
 /*
  * Attempt to steal a page from a pipe buffer. This should perhaps go into
@@ -101,8 +86,12 @@
 	buf->flags &= ~PIPE_BUF_FLAG_LRU;
 }
 
-static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe,
-				   struct pipe_buffer *buf)
+/*
+ * Check whether the contents of buf is OK to access. Since the content
+ * is a page cache page, IO may be in flight.
+ */
+static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe,
+				       struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
 	int err;
@@ -143,7 +132,7 @@
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
-	.pin = page_cache_pipe_buf_pin,
+	.confirm = page_cache_pipe_buf_confirm,
 	.release = page_cache_pipe_buf_release,
 	.steal = page_cache_pipe_buf_steal,
 	.get = generic_pipe_buf_get,
@@ -163,19 +152,27 @@
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
-	.pin = generic_pipe_buf_pin,
+	.confirm = generic_pipe_buf_confirm,
 	.release = page_cache_pipe_buf_release,
 	.steal = user_page_pipe_buf_steal,
 	.get = generic_pipe_buf_get,
 };
 
-/*
- * Pipe output worker. This sets up our pipe format with the page cache
- * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
+/**
+ * splice_to_pipe - fill passed data into a pipe
+ * @pipe:	pipe to fill
+ * @spd:	data to fill
+ *
+ * Description:
+ *    @spd contains a map of pages and len/offset tupples, a long with
+ *    the struct pipe_buf_operations associated with these pages. This
+ *    function will link that data to the pipe.
+ *
  */
-static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
-			      struct splice_pipe_desc *spd)
+ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
+		       struct splice_pipe_desc *spd)
 {
+	unsigned int spd_pages = spd->nr_pages;
 	int ret, do_wakeup, page_nr;
 
 	ret = 0;
@@ -200,6 +197,7 @@
 			buf->page = spd->pages[page_nr];
 			buf->offset = spd->partial[page_nr].offset;
 			buf->len = spd->partial[page_nr].len;
+			buf->private = spd->partial[page_nr].private;
 			buf->ops = spd->ops;
 			if (spd->flags & SPLICE_F_GIFT)
 				buf->flags |= PIPE_BUF_FLAG_GIFT;
@@ -244,17 +242,18 @@
 		pipe->waiting_writers--;
 	}
 
-	if (pipe->inode)
+	if (pipe->inode) {
 		mutex_unlock(&pipe->inode->i_mutex);
 
-	if (do_wakeup) {
-		smp_mb();
-		if (waitqueue_active(&pipe->wait))
-			wake_up_interruptible(&pipe->wait);
-		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+		if (do_wakeup) {
+			smp_mb();
+			if (waitqueue_active(&pipe->wait))
+				wake_up_interruptible(&pipe->wait);
+			kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+		}
 	}
 
-	while (page_nr < spd->nr_pages)
+	while (page_nr < spd_pages)
 		page_cache_release(spd->pages[page_nr++]);
 
 	return ret;
@@ -272,7 +271,6 @@
 	struct page *page;
 	pgoff_t index, end_index;
 	loff_t isize;
-	size_t total_len;
 	int error, page_nr;
 	struct splice_pipe_desc spd = {
 		.pages = pages,
@@ -295,20 +293,15 @@
 	page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
 
 	/*
-	 * Now fill in the holes:
-	 */
-	error = 0;
-	total_len = 0;
-
-	/*
 	 * Lookup the (hopefully) full range of pages we need.
 	 */
 	spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages);
 
 	/*
 	 * If find_get_pages_contig() returned fewer pages than we needed,
-	 * allocate the rest.
+	 * allocate the rest and fill in the holes.
 	 */
+	error = 0;
 	index += spd.nr_pages;
 	while (spd.nr_pages < nr_pages) {
 		/*
@@ -415,43 +408,47 @@
 
 				break;
 			}
+		}
+fill_it:
+		/*
+		 * i_size must be checked after PageUptodate.
+		 */
+		isize = i_size_read(mapping->host);
+		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+		if (unlikely(!isize || index > end_index))
+			break;
+
+		/*
+		 * if this is the last page, see if we need to shrink
+		 * the length and stop
+		 */
+		if (end_index == index) {
+			unsigned int plen;
 
 			/*
-			 * i_size must be checked after ->readpage().
+			 * max good bytes in this page
 			 */
-			isize = i_size_read(mapping->host);
-			end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
-			if (unlikely(!isize || index > end_index))
+			plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (plen <= loff)
 				break;
 
 			/*
-			 * if this is the last page, see if we need to shrink
-			 * the length and stop
+			 * force quit after adding this page
 			 */
-			if (end_index == index) {
-				loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
-				if (total_len + loff > isize)
-					break;
-				/*
-				 * force quit after adding this page
-				 */
-				len = this_len;
-				this_len = min(this_len, loff);
-				loff = 0;
-			}
+			this_len = min(this_len, plen - loff);
+			len = this_len;
 		}
-fill_it:
+
 		partial[page_nr].offset = loff;
 		partial[page_nr].len = this_len;
 		len -= this_len;
-		total_len += this_len;
 		loff = 0;
 		spd.nr_pages++;
 		index++;
 	}
 
 	/*
-	 * Release any pages at the end, if we quit early. 'i' is how far
+	 * Release any pages at the end, if we quit early. 'page_nr' is how far
 	 * we got, 'nr_pages' is how many pages are in the map.
 	 */
 	while (page_nr < nr_pages)
@@ -466,11 +463,16 @@
 /**
  * generic_file_splice_read - splice data from file to a pipe
  * @in:		file to splice from
+ * @ppos:	position in @in
  * @pipe:	pipe to splice to
  * @len:	number of bytes to splice
  * @flags:	splice modifier flags
  *
- * Will read pages from given file and fill them into a pipe.
+ * Description:
+ *    Will read pages from given file and fill them into a pipe. Can be
+ *    used as long as the address_space operations for the source implements
+ *    a readpage() hook.
+ *
  */
 ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
 				 struct pipe_inode_info *pipe, size_t len,
@@ -478,11 +480,19 @@
 {
 	ssize_t spliced;
 	int ret;
+	loff_t isize, left;
+
+	isize = i_size_read(in->f_mapping->host);
+	if (unlikely(*ppos >= isize))
+		return 0;
+
+	left = isize - *ppos;
+	if (unlikely(left < len))
+		len = left;
 
 	ret = 0;
 	spliced = 0;
-
-	while (len) {
+	while (len && !spliced) {
 		ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
 
 		if (ret < 0)
@@ -516,11 +526,11 @@
 static int pipe_to_sendpage(struct pipe_inode_info *pipe,
 			    struct pipe_buffer *buf, struct splice_desc *sd)
 {
-	struct file *file = sd->file;
+	struct file *file = sd->u.file;
 	loff_t pos = sd->pos;
 	int ret, more;
 
-	ret = buf->ops->pin(pipe, buf);
+	ret = buf->ops->confirm(pipe, buf);
 	if (!ret) {
 		more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
 
@@ -554,7 +564,7 @@
 static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 			struct splice_desc *sd)
 {
-	struct file *file = sd->file;
+	struct file *file = sd->u.file;
 	struct address_space *mapping = file->f_mapping;
 	unsigned int offset, this_len;
 	struct page *page;
@@ -564,7 +574,7 @@
 	/*
 	 * make sure the data in this buffer is uptodate
 	 */
-	ret = buf->ops->pin(pipe, buf);
+	ret = buf->ops->confirm(pipe, buf);
 	if (unlikely(ret))
 		return ret;
 
@@ -644,7 +654,6 @@
 	 * accessed, we are now done!
 	 */
 	mark_page_accessed(page);
-	balance_dirty_pages_ratelimited(mapping);
 out:
 	page_cache_release(page);
 	unlock_page(page);
@@ -652,36 +661,37 @@
 	return ret;
 }
 
-/*
- * Pipe input worker. Most of this logic works like a regular pipe, the
- * key here is the 'actor' worker passed in that actually moves the data
- * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
+/**
+ * __splice_from_pipe - splice data from a pipe to given actor
+ * @pipe:	pipe to splice from
+ * @sd:		information to @actor
+ * @actor:	handler that splices the data
+ *
+ * Description:
+ *    This function does little more than loop over the pipe and call
+ *    @actor to do the actual moving of a single struct pipe_buffer to
+ *    the desired destination. See pipe_to_file, pipe_to_sendpage, or
+ *    pipe_to_user.
+ *
  */
-ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
-			   struct file *out, loff_t *ppos, size_t len,
-			   unsigned int flags, splice_actor *actor)
+ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
+			   splice_actor *actor)
 {
 	int ret, do_wakeup, err;
-	struct splice_desc sd;
 
 	ret = 0;
 	do_wakeup = 0;
 
-	sd.total_len = len;
-	sd.flags = flags;
-	sd.file = out;
-	sd.pos = *ppos;
-
 	for (;;) {
 		if (pipe->nrbufs) {
 			struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
 			const struct pipe_buf_operations *ops = buf->ops;
 
-			sd.len = buf->len;
-			if (sd.len > sd.total_len)
-				sd.len = sd.total_len;
+			sd->len = buf->len;
+			if (sd->len > sd->total_len)
+				sd->len = sd->total_len;
 
-			err = actor(pipe, buf, &sd);
+			err = actor(pipe, buf, sd);
 			if (err <= 0) {
 				if (!ret && err != -ENODATA)
 					ret = err;
@@ -693,10 +703,10 @@
 			buf->offset += err;
 			buf->len -= err;
 
-			sd.len -= err;
-			sd.pos += err;
-			sd.total_len -= err;
-			if (sd.len)
+			sd->len -= err;
+			sd->pos += err;
+			sd->total_len -= err;
+			if (sd->len)
 				continue;
 
 			if (!buf->len) {
@@ -708,7 +718,7 @@
 					do_wakeup = 1;
 			}
 
-			if (!sd.total_len)
+			if (!sd->total_len)
 				break;
 		}
 
@@ -721,7 +731,7 @@
 				break;
 		}
 
-		if (flags & SPLICE_F_NONBLOCK) {
+		if (sd->flags & SPLICE_F_NONBLOCK) {
 			if (!ret)
 				ret = -EAGAIN;
 			break;
@@ -755,12 +765,32 @@
 }
 EXPORT_SYMBOL(__splice_from_pipe);
 
+/**
+ * splice_from_pipe - splice data from a pipe to a file
+ * @pipe:	pipe to splice from
+ * @out:	file to splice to
+ * @ppos:	position in @out
+ * @len:	how many bytes to splice
+ * @flags:	splice modifier flags
+ * @actor:	handler that splices the data
+ *
+ * Description:
+ *    See __splice_from_pipe. This function locks the input and output inodes,
+ *    otherwise it's identical to __splice_from_pipe().
+ *
+ */
 ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
 			 loff_t *ppos, size_t len, unsigned int flags,
 			 splice_actor *actor)
 {
 	ssize_t ret;
 	struct inode *inode = out->f_mapping->host;
+	struct splice_desc sd = {
+		.total_len = len,
+		.flags = flags,
+		.pos = *ppos,
+		.u.file = out,
+	};
 
 	/*
 	 * The actor worker might be calling ->prepare_write and
@@ -769,7 +799,7 @@
 	 * pipe->inode, we have to order lock acquiry here.
 	 */
 	inode_double_lock(inode, pipe->inode);
-	ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor);
+	ret = __splice_from_pipe(pipe, &sd, actor);
 	inode_double_unlock(inode, pipe->inode);
 
 	return ret;
@@ -779,12 +809,14 @@
  * generic_file_splice_write_nolock - generic_file_splice_write without mutexes
  * @pipe:	pipe info
  * @out:	file to write to
+ * @ppos:	position in @out
  * @len:	number of bytes to splice
  * @flags:	splice modifier flags
  *
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file. The caller is responsible
- * for acquiring i_mutex on both inodes.
+ * Description:
+ *    Will either move or copy pages (determined by @flags options) from
+ *    the given pipe inode to the given file. The caller is responsible
+ *    for acquiring i_mutex on both inodes.
  *
  */
 ssize_t
@@ -793,6 +825,12 @@
 {
 	struct address_space *mapping = out->f_mapping;
 	struct inode *inode = mapping->host;
+	struct splice_desc sd = {
+		.total_len = len,
+		.flags = flags,
+		.pos = *ppos,
+		.u.file = out,
+	};
 	ssize_t ret;
 	int err;
 
@@ -800,9 +838,12 @@
 	if (unlikely(err))
 		return err;
 
-	ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+	ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
 	if (ret > 0) {
+		unsigned long nr_pages;
+
 		*ppos += ret;
+		nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 		/*
 		 * If file or inode is SYNC and we actually wrote some data,
@@ -815,6 +856,7 @@
 			if (err)
 				ret = err;
 		}
+		balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
 	}
 
 	return ret;
@@ -826,11 +868,13 @@
  * generic_file_splice_write - splice data from a pipe to a file
  * @pipe:	pipe info
  * @out:	file to write to
+ * @ppos:	position in @out
  * @len:	number of bytes to splice
  * @flags:	splice modifier flags
  *
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file.
+ * Description:
+ *    Will either move or copy pages (determined by @flags options) from
+ *    the given pipe inode to the given file.
  *
  */
 ssize_t
@@ -853,7 +897,10 @@
 
 	ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
 	if (ret > 0) {
+		unsigned long nr_pages;
+
 		*ppos += ret;
+		nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 		/*
 		 * If file or inode is SYNC and we actually wrote some data,
@@ -868,6 +915,7 @@
 			if (err)
 				ret = err;
 		}
+		balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
 	}
 
 	return ret;
@@ -877,13 +925,15 @@
 
 /**
  * generic_splice_sendpage - splice data from a pipe to a socket
- * @inode:	pipe inode
+ * @pipe:	pipe to splice from
  * @out:	socket to write to
+ * @ppos:	position in @out
  * @len:	number of bytes to splice
  * @flags:	splice modifier flags
  *
- * Will send @len bytes from the pipe to a network socket. No data copying
- * is involved.
+ * Description:
+ *    Will send @len bytes from the pipe to a network socket. No data copying
+ *    is involved.
  *
  */
 ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
@@ -912,6 +962,10 @@
 	if (unlikely(ret < 0))
 		return ret;
 
+	ret = security_file_permission(out, MAY_WRITE);
+	if (unlikely(ret < 0))
+		return ret;
+
 	return out->f_op->splice_write(pipe, out, ppos, len, flags);
 }
 
@@ -922,7 +976,6 @@
 			 struct pipe_inode_info *pipe, size_t len,
 			 unsigned int flags)
 {
-	loff_t isize, left;
 	int ret;
 
 	if (unlikely(!in->f_op || !in->f_op->splice_read))
@@ -935,25 +988,34 @@
 	if (unlikely(ret < 0))
 		return ret;
 
-	isize = i_size_read(in->f_mapping->host);
-	if (unlikely(*ppos >= isize))
-		return 0;
-	
-	left = isize - *ppos;
-	if (unlikely(left < len))
-		len = left;
+	ret = security_file_permission(in, MAY_READ);
+	if (unlikely(ret < 0))
+		return ret;
 
 	return in->f_op->splice_read(in, ppos, pipe, len, flags);
 }
 
-long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
-		      size_t len, unsigned int flags)
+/**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+ * @in:		file to splice from
+ * @sd:		actor information on where to splice to
+ * @actor:	handles the data splicing
+ *
+ * Description:
+ *    This is a special case helper to splice directly between two
+ *    points, without requiring an explicit pipe. Internally an allocated
+ *    pipe is cached in the process, and reused during the life time of
+ *    that process.
+ *
+ */
+ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+			       splice_direct_actor *actor)
 {
 	struct pipe_inode_info *pipe;
 	long ret, bytes;
-	loff_t out_off;
 	umode_t i_mode;
-	int i;
+	size_t len;
+	int i, flags;
 
 	/*
 	 * We require the input being a regular file, as we don't want to
@@ -989,49 +1051,43 @@
 	 */
 	ret = 0;
 	bytes = 0;
-	out_off = 0;
+	len = sd->total_len;
+	flags = sd->flags;
+
+	/*
+	 * Don't block on output, we have to drain the direct pipe.
+	 */
+	sd->flags &= ~SPLICE_F_NONBLOCK;
 
 	while (len) {
-		size_t read_len, max_read_len;
+		size_t read_len;
+		loff_t pos = sd->pos;
 
-		/*
-		 * Do at most PIPE_BUFFERS pages worth of transfer:
-		 */
-		max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
-
-		ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
-		if (unlikely(ret < 0))
+		ret = do_splice_to(in, &pos, pipe, len, flags);
+		if (unlikely(ret <= 0))
 			goto out_release;
 
 		read_len = ret;
+		sd->total_len = read_len;
 
 		/*
 		 * NOTE: nonblocking mode only applies to the input. We
 		 * must not do the output in nonblocking mode as then we
 		 * could get stuck data in the internal pipe:
 		 */
-		ret = do_splice_from(pipe, out, &out_off, read_len,
-				     flags & ~SPLICE_F_NONBLOCK);
-		if (unlikely(ret < 0))
+		ret = actor(pipe, sd);
+		if (unlikely(ret <= 0))
 			goto out_release;
 
 		bytes += ret;
 		len -= ret;
+		sd->pos = pos;
 
-		/*
-		 * In nonblocking mode, if we got back a short read then
-		 * that was due to either an IO error or due to the
-		 * pagecache entry not being there. In the IO error case
-		 * the _next_ splice attempt will produce a clean IO error
-		 * return value (not a short read), so in both cases it's
-		 * correct to break out of the loop here:
-		 */
-		if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len))
-			break;
+		if (ret < read_len)
+			goto out_release;
 	}
 
 	pipe->nrbufs = pipe->curbuf = 0;
-
 	return bytes;
 
 out_release:
@@ -1056,9 +1112,51 @@
 		return bytes;
 
 	return ret;
+
+}
+EXPORT_SYMBOL(splice_direct_to_actor);
+
+static int direct_splice_actor(struct pipe_inode_info *pipe,
+			       struct splice_desc *sd)
+{
+	struct file *file = sd->u.file;
+
+	return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
 }
 
-EXPORT_SYMBOL(do_splice_direct);
+/**
+ * do_splice_direct - splices data directly between two files
+ * @in:		file to splice from
+ * @ppos:	input file offset
+ * @out:	file to splice to
+ * @len:	number of bytes to splice
+ * @flags:	splice modifier flags
+ *
+ * Description:
+ *    For use by do_sendfile(). splice can easily emulate sendfile, but
+ *    doing it in the application would incur an extra system call
+ *    (splice in + splice out, as compared to just sendfile()). So this helper
+ *    can splice directly through a process-private pipe.
+ *
+ */
+long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+		      size_t len, unsigned int flags)
+{
+	struct splice_desc sd = {
+		.len		= len,
+		.total_len	= len,
+		.flags		= flags,
+		.pos		= *ppos,
+		.u.file		= out,
+	};
+	long ret;
+
+	ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
+	if (ret > 0)
+		*ppos += ret;
+
+	return ret;
+}
 
 /*
  * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
@@ -1240,28 +1338,131 @@
 	return error;
 }
 
+static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+			struct splice_desc *sd)
+{
+	char *src;
+	int ret;
+
+	ret = buf->ops->confirm(pipe, buf);
+	if (unlikely(ret))
+		return ret;
+
+	/*
+	 * See if we can use the atomic maps, by prefaulting in the
+	 * pages and doing an atomic copy
+	 */
+	if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) {
+		src = buf->ops->map(pipe, buf, 1);
+		ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset,
+							sd->len);
+		buf->ops->unmap(pipe, buf, src);
+		if (!ret) {
+			ret = sd->len;
+			goto out;
+		}
+	}
+
+	/*
+	 * No dice, use slow non-atomic map and copy
+ 	 */
+	src = buf->ops->map(pipe, buf, 0);
+
+	ret = sd->len;
+	if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len))
+		ret = -EFAULT;
+
+out:
+	if (ret > 0)
+		sd->u.userptr += ret;
+	buf->ops->unmap(pipe, buf, src);
+	return ret;
+}
+
+/*
+ * For lack of a better implementation, implement vmsplice() to userspace
+ * as a simple copy of the pipes pages to the user iov.
+ */
+static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
+			     unsigned long nr_segs, unsigned int flags)
+{
+	struct pipe_inode_info *pipe;
+	struct splice_desc sd;
+	ssize_t size;
+	int error;
+	long ret;
+
+	pipe = pipe_info(file->f_path.dentry->d_inode);
+	if (!pipe)
+		return -EBADF;
+
+	if (pipe->inode)
+		mutex_lock(&pipe->inode->i_mutex);
+
+	error = ret = 0;
+	while (nr_segs) {
+		void __user *base;
+		size_t len;
+
+		/*
+		 * Get user address base and length for this iovec.
+		 */
+		error = get_user(base, &iov->iov_base);
+		if (unlikely(error))
+			break;
+		error = get_user(len, &iov->iov_len);
+		if (unlikely(error))
+			break;
+
+		/*
+		 * Sanity check this iovec. 0 read succeeds.
+		 */
+		if (unlikely(!len))
+			break;
+		if (unlikely(!base)) {
+			error = -EFAULT;
+			break;
+		}
+
+		sd.len = 0;
+		sd.total_len = len;
+		sd.flags = flags;
+		sd.u.userptr = base;
+		sd.pos = 0;
+
+		size = __splice_from_pipe(pipe, &sd, pipe_to_user);
+		if (size < 0) {
+			if (!ret)
+				ret = size;
+
+			break;
+		}
+
+		ret += size;
+
+		if (size < len)
+			break;
+
+		nr_segs--;
+		iov++;
+	}
+
+	if (pipe->inode)
+		mutex_unlock(&pipe->inode->i_mutex);
+
+	if (!ret)
+		ret = error;
+
+	return ret;
+}
+
 /*
  * vmsplice splices a user address range into a pipe. It can be thought of
  * as splice-from-memory, where the regular splice is splice-from-file (or
  * to file). In both cases the output is a pipe, naturally.
- *
- * Note that vmsplice only supports splicing _from_ user memory to a pipe,
- * not the other way around. Splicing from user memory is a simple operation
- * that can be supported without any funky alignment restrictions or nasty
- * vm tricks. We simply map in the user memory and fill them into a pipe.
- * The reverse isn't quite as easy, though. There are two possible solutions
- * for that:
- *
- *	- memcpy() the data internally, at which point we might as well just
- *	  do a regular read() on the buffer anyway.
- *	- Lots of nasty vm tricks, that are neither fast nor flexible (it
- *	  has restriction limitations on both ends of the pipe).
- *
- * Alas, it isn't here.
- *
  */
-static long do_vmsplice(struct file *file, const struct iovec __user *iov,
-			unsigned long nr_segs, unsigned int flags)
+static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
+			     unsigned long nr_segs, unsigned int flags)
 {
 	struct pipe_inode_info *pipe;
 	struct page *pages[PIPE_BUFFERS];
@@ -1276,10 +1477,6 @@
 	pipe = pipe_info(file->f_path.dentry->d_inode);
 	if (!pipe)
 		return -EBADF;
-	if (unlikely(nr_segs > UIO_MAXIOV))
-		return -EINVAL;
-	else if (unlikely(!nr_segs))
-		return 0;
 
 	spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
 					    flags & SPLICE_F_GIFT);
@@ -1289,6 +1486,22 @@
 	return splice_to_pipe(pipe, &spd);
 }
 
+/*
+ * Note that vmsplice only really supports true splicing _from_ user memory
+ * to a pipe, not the other way around. Splicing from user memory is a simple
+ * operation that can be supported without any funky alignment restrictions
+ * or nasty vm tricks. We simply map in the user memory and fill them into
+ * a pipe. The reverse isn't quite as easy, though. There are two possible
+ * solutions for that:
+ *
+ *	- memcpy() the data internally, at which point we might as well just
+ *	  do a regular read() on the buffer anyway.
+ *	- Lots of nasty vm tricks, that are neither fast nor flexible (it
+ *	  has restriction limitations on both ends of the pipe).
+ *
+ * Currently we punt and implement it as a normal copy, see pipe_to_user().
+ *
+ */
 asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
 			     unsigned long nr_segs, unsigned int flags)
 {
@@ -1296,11 +1509,18 @@
 	long error;
 	int fput;
 
+	if (unlikely(nr_segs > UIO_MAXIOV))
+		return -EINVAL;
+	else if (unlikely(!nr_segs))
+		return 0;
+
 	error = -EBADF;
 	file = fget_light(fd, &fput);
 	if (file) {
 		if (file->f_mode & FMODE_WRITE)
-			error = do_vmsplice(file, iov, nr_segs, flags);
+			error = vmsplice_to_pipe(file, iov, nr_segs, flags);
+		else if (file->f_mode & FMODE_READ)
+			error = vmsplice_to_user(file, iov, nr_segs, flags);
 
 		fput_light(file, fput);
 	}
diff --git a/fs/super.c b/fs/super.c
index 5260d62..fc8ebed 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -884,6 +884,7 @@
 	error = type->get_sb(type, flags, name, data, mnt);
 	if (error < 0)
 		goto out_free_secdata;
+	BUG_ON(!mnt->mnt_sb);
 
  	error = security_sb_kern_mount(mnt->mnt_sb, secdata);
  	if (error)
diff --git a/fs/sync.c b/fs/sync.c
index 2f97576..7cd005ea 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -236,6 +236,14 @@
 	return ret;
 }
 
+/* It would be nice if people remember that not all the world's an i386
+   when they introduce new system calls */
+asmlinkage long sys_sync_file_range2(int fd, unsigned int flags,
+				     loff_t offset, loff_t nbytes)
+{
+	return sys_sync_file_range(fd, offset, nbytes, flags);
+}
+
 /*
  * `endbyte' is inclusive
  */
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d3b9f5f..135353f 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -20,29 +20,41 @@
 
 #include "sysfs.h"
 
+struct bin_buffer {
+	struct mutex	mutex;
+	void		*buffer;
+	int		mmapped;
+};
+
 static int
 fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
 {
-	struct bin_attribute * attr = to_bin_attr(dentry);
-	struct kobject * kobj = to_kobj(dentry->d_parent);
+	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+	struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+	struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+	int rc;
 
-	if (!attr->read)
-		return -EIO;
+	/* need attr_sd for attr, its parent for kobj */
+	if (!sysfs_get_active_two(attr_sd))
+		return -ENODEV;
 
-	return attr->read(kobj, buffer, off, count);
+	rc = -EIO;
+	if (attr->read)
+		rc = attr->read(kobj, attr, buffer, off, count);
+
+	sysfs_put_active_two(attr_sd);
+
+	return rc;
 }
 
 static ssize_t
-read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
+read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
 {
-	char *buffer = file->private_data;
+	struct bin_buffer *bb = file->private_data;
 	struct dentry *dentry = file->f_path.dentry;
 	int size = dentry->d_inode->i_size;
 	loff_t offs = *off;
-	int ret;
-
-	if (count > PAGE_SIZE)
-		count = PAGE_SIZE;
+	int count = min_t(size_t, bytes, PAGE_SIZE);
 
 	if (size) {
 		if (offs > size)
@@ -51,43 +63,56 @@
 			count = size - offs;
 	}
 
-	ret = fill_read(dentry, buffer, offs, count);
-	if (ret < 0) 
-		return ret;
-	count = ret;
+	mutex_lock(&bb->mutex);
 
-	if (copy_to_user(userbuf, buffer, count))
-		return -EFAULT;
+	count = fill_read(dentry, bb->buffer, offs, count);
+	if (count < 0)
+		goto out_unlock;
 
-	pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
+	if (copy_to_user(userbuf, bb->buffer, count)) {
+		count = -EFAULT;
+		goto out_unlock;
+	}
+
+	pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
 
 	*off = offs + count;
 
+ out_unlock:
+	mutex_unlock(&bb->mutex);
 	return count;
 }
 
 static int
 flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
 {
-	struct bin_attribute *attr = to_bin_attr(dentry);
-	struct kobject *kobj = to_kobj(dentry->d_parent);
+	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+	struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+	struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+	int rc;
 
-	if (!attr->write)
-		return -EIO;
+	/* need attr_sd for attr, its parent for kobj */
+	if (!sysfs_get_active_two(attr_sd))
+		return -ENODEV;
 
-	return attr->write(kobj, buffer, offset, count);
+	rc = -EIO;
+	if (attr->write)
+		rc = attr->write(kobj, attr, buffer, offset, count);
+
+	sysfs_put_active_two(attr_sd);
+
+	return rc;
 }
 
-static ssize_t write(struct file * file, const char __user * userbuf,
-		     size_t count, loff_t * off)
+static ssize_t write(struct file *file, const char __user *userbuf,
+		     size_t bytes, loff_t *off)
 {
-	char *buffer = file->private_data;
+	struct bin_buffer *bb = file->private_data;
 	struct dentry *dentry = file->f_path.dentry;
 	int size = dentry->d_inode->i_size;
 	loff_t offs = *off;
+	int count = min_t(size_t, bytes, PAGE_SIZE);
 
-	if (count > PAGE_SIZE)
-		count = PAGE_SIZE;
 	if (size) {
 		if (offs > size)
 			return 0;
@@ -95,72 +120,100 @@
 			count = size - offs;
 	}
 
-	if (copy_from_user(buffer, userbuf, count))
-		return -EFAULT;
+	mutex_lock(&bb->mutex);
 
-	count = flush_write(dentry, buffer, offs, count);
+	if (copy_from_user(bb->buffer, userbuf, count)) {
+		count = -EFAULT;
+		goto out_unlock;
+	}
+
+	count = flush_write(dentry, bb->buffer, offs, count);
 	if (count > 0)
 		*off = offs + count;
+
+ out_unlock:
+	mutex_unlock(&bb->mutex);
 	return count;
 }
 
 static int mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct dentry *dentry = file->f_path.dentry;
-	struct bin_attribute *attr = to_bin_attr(dentry);
-	struct kobject *kobj = to_kobj(dentry->d_parent);
+	struct bin_buffer *bb = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+	struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+	int rc;
 
-	if (!attr->mmap)
-		return -EINVAL;
+	mutex_lock(&bb->mutex);
 
-	return attr->mmap(kobj, attr, vma);
+	/* need attr_sd for attr, its parent for kobj */
+	if (!sysfs_get_active_two(attr_sd))
+		return -ENODEV;
+
+	rc = -EINVAL;
+	if (attr->mmap)
+		rc = attr->mmap(kobj, attr, vma);
+
+	if (rc == 0 && !bb->mmapped)
+		bb->mmapped = 1;
+	else
+		sysfs_put_active_two(attr_sd);
+
+	mutex_unlock(&bb->mutex);
+
+	return rc;
 }
 
 static int open(struct inode * inode, struct file * file)
 {
-	struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
-	struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
-	int error = -EINVAL;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+	struct bin_buffer *bb = NULL;
+	int error;
 
-	if (!kobj || !attr)
-		goto Done;
-
-	/* Grab the module reference for this attribute if we have one */
-	error = -ENODEV;
-	if (!try_module_get(attr->attr.owner)) 
-		goto Done;
+	/* need attr_sd for attr */
+	if (!sysfs_get_active(attr_sd))
+		return -ENODEV;
 
 	error = -EACCES;
 	if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
-		goto Error;
+		goto err_out;
 	if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
-		goto Error;
+		goto err_out;
 
 	error = -ENOMEM;
-	file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!file->private_data)
-		goto Error;
+	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+	if (!bb)
+		goto err_out;
 
-	error = 0;
-    goto Done;
+	bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!bb->buffer)
+		goto err_out;
 
- Error:
-	module_put(attr->attr.owner);
- Done:
-	if (error)
-		kobject_put(kobj);
+	mutex_init(&bb->mutex);
+	file->private_data = bb;
+
+	/* open succeeded, put active reference and pin attr_sd */
+	sysfs_put_active(attr_sd);
+	sysfs_get(attr_sd);
+	return 0;
+
+ err_out:
+	sysfs_put_active(attr_sd);
+	kfree(bb);
 	return error;
 }
 
 static int release(struct inode * inode, struct file * file)
 {
-	struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
-	struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
-	u8 * buffer = file->private_data;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	struct bin_buffer *bb = file->private_data;
 
-	kobject_put(kobj);
-	module_put(attr->attr.owner);
-	kfree(buffer);
+	if (bb->mmapped)
+		sysfs_put_active_two(attr_sd);
+	sysfs_put(attr_sd);
+	kfree(bb->buffer);
+	kfree(bb);
 	return 0;
 }
 
@@ -181,9 +234,9 @@
 
 int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
 {
-	BUG_ON(!kobj || !kobj->dentry || !attr);
+	BUG_ON(!kobj || !kobj->sd || !attr);
 
-	return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
+	return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
 }
 
 
@@ -195,7 +248,7 @@
 
 void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
 {
-	if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) {
+	if (sysfs_hash_and_remove(kobj->sd, attr->attr.name) < 0) {
 		printk(KERN_ERR "%s: "
 			"bad dentry or inode or no such file: \"%s\"\n",
 			__FUNCTION__, attr->attr.name);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 85a6686..aee966c 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -9,18 +9,346 @@
 #include <linux/module.h>
 #include <linux/kobject.h>
 #include <linux/namei.h>
+#include <linux/idr.h>
+#include <linux/completion.h>
 #include <asm/semaphore.h>
 #include "sysfs.h"
 
-DECLARE_RWSEM(sysfs_rename_sem);
+DEFINE_MUTEX(sysfs_mutex);
+spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
+
+static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_IDA(sysfs_ino_ida);
+
+/**
+ *	sysfs_link_sibling - link sysfs_dirent into sibling list
+ *	@sd: sysfs_dirent of interest
+ *
+ *	Link @sd into its sibling list which starts from
+ *	sd->s_parent->s_children.
+ *
+ *	Locking:
+ *	mutex_lock(sysfs_mutex)
+ */
+void sysfs_link_sibling(struct sysfs_dirent *sd)
+{
+	struct sysfs_dirent *parent_sd = sd->s_parent;
+
+	BUG_ON(sd->s_sibling);
+	sd->s_sibling = parent_sd->s_children;
+	parent_sd->s_children = sd;
+}
+
+/**
+ *	sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
+ *	@sd: sysfs_dirent of interest
+ *
+ *	Unlink @sd from its sibling list which starts from
+ *	sd->s_parent->s_children.
+ *
+ *	Locking:
+ *	mutex_lock(sysfs_mutex)
+ */
+void sysfs_unlink_sibling(struct sysfs_dirent *sd)
+{
+	struct sysfs_dirent **pos;
+
+	for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) {
+		if (*pos == sd) {
+			*pos = sd->s_sibling;
+			sd->s_sibling = NULL;
+			break;
+		}
+	}
+}
+
+/**
+ *	sysfs_get_dentry - get dentry for the given sysfs_dirent
+ *	@sd: sysfs_dirent of interest
+ *
+ *	Get dentry for @sd.  Dentry is looked up if currently not
+ *	present.  This function climbs sysfs_dirent tree till it
+ *	reaches a sysfs_dirent with valid dentry attached and descends
+ *	down from there looking up dentry for each step.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ *
+ *	RETURNS:
+ *	Pointer to found dentry on success, ERR_PTR() value on error.
+ */
+struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
+{
+	struct sysfs_dirent *cur;
+	struct dentry *parent_dentry, *dentry;
+	int i, depth;
+
+	/* Find the first parent which has valid s_dentry and get the
+	 * dentry.
+	 */
+	mutex_lock(&sysfs_mutex);
+ restart0:
+	spin_lock(&sysfs_assoc_lock);
+ restart1:
+	spin_lock(&dcache_lock);
+
+	dentry = NULL;
+	depth = 0;
+	cur = sd;
+	while (!cur->s_dentry || !cur->s_dentry->d_inode) {
+		if (cur->s_flags & SYSFS_FLAG_REMOVED) {
+			dentry = ERR_PTR(-ENOENT);
+			depth = 0;
+			break;
+		}
+		cur = cur->s_parent;
+		depth++;
+	}
+	if (!IS_ERR(dentry))
+		dentry = dget_locked(cur->s_dentry);
+
+	spin_unlock(&dcache_lock);
+	spin_unlock(&sysfs_assoc_lock);
+
+	/* from the found dentry, look up depth times */
+	while (depth--) {
+		/* find and get depth'th ancestor */
+		for (cur = sd, i = 0; cur && i < depth; i++)
+			cur = cur->s_parent;
+
+		/* This can happen if tree structure was modified due
+		 * to move/rename.  Restart.
+		 */
+		if (i != depth) {
+			dput(dentry);
+			goto restart0;
+		}
+
+		sysfs_get(cur);
+
+		mutex_unlock(&sysfs_mutex);
+
+		/* look it up */
+		parent_dentry = dentry;
+		dentry = lookup_one_len_kern(cur->s_name, parent_dentry,
+					     strlen(cur->s_name));
+		dput(parent_dentry);
+
+		if (IS_ERR(dentry)) {
+			sysfs_put(cur);
+			return dentry;
+		}
+
+		mutex_lock(&sysfs_mutex);
+		spin_lock(&sysfs_assoc_lock);
+
+		/* This, again, can happen if tree structure has
+		 * changed and we looked up the wrong thing.  Restart.
+		 */
+		if (cur->s_dentry != dentry) {
+			dput(dentry);
+			sysfs_put(cur);
+			goto restart1;
+		}
+
+		spin_unlock(&sysfs_assoc_lock);
+
+		sysfs_put(cur);
+	}
+
+	mutex_unlock(&sysfs_mutex);
+	return dentry;
+}
+
+/**
+ *	sysfs_get_active - get an active reference to sysfs_dirent
+ *	@sd: sysfs_dirent to get an active reference to
+ *
+ *	Get an active reference of @sd.  This function is noop if @sd
+ *	is NULL.
+ *
+ *	RETURNS:
+ *	Pointer to @sd on success, NULL on failure.
+ */
+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
+{
+	if (unlikely(!sd))
+		return NULL;
+
+	while (1) {
+		int v, t;
+
+		v = atomic_read(&sd->s_active);
+		if (unlikely(v < 0))
+			return NULL;
+
+		t = atomic_cmpxchg(&sd->s_active, v, v + 1);
+		if (likely(t == v))
+			return sd;
+		if (t < 0)
+			return NULL;
+
+		cpu_relax();
+	}
+}
+
+/**
+ *	sysfs_put_active - put an active reference to sysfs_dirent
+ *	@sd: sysfs_dirent to put an active reference to
+ *
+ *	Put an active reference to @sd.  This function is noop if @sd
+ *	is NULL.
+ */
+void sysfs_put_active(struct sysfs_dirent *sd)
+{
+	struct completion *cmpl;
+	int v;
+
+	if (unlikely(!sd))
+		return;
+
+	v = atomic_dec_return(&sd->s_active);
+	if (likely(v != SD_DEACTIVATED_BIAS))
+		return;
+
+	/* atomic_dec_return() is a mb(), we'll always see the updated
+	 * sd->s_sibling.
+	 */
+	cmpl = (void *)sd->s_sibling;
+	complete(cmpl);
+}
+
+/**
+ *	sysfs_get_active_two - get active references to sysfs_dirent and parent
+ *	@sd: sysfs_dirent of interest
+ *
+ *	Get active reference to @sd and its parent.  Parent's active
+ *	reference is grabbed first.  This function is noop if @sd is
+ *	NULL.
+ *
+ *	RETURNS:
+ *	Pointer to @sd on success, NULL on failure.
+ */
+struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
+{
+	if (sd) {
+		if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
+			return NULL;
+		if (unlikely(!sysfs_get_active(sd))) {
+			sysfs_put_active(sd->s_parent);
+			return NULL;
+		}
+	}
+	return sd;
+}
+
+/**
+ *	sysfs_put_active_two - put active references to sysfs_dirent and parent
+ *	@sd: sysfs_dirent of interest
+ *
+ *	Put active references to @sd and its parent.  This function is
+ *	noop if @sd is NULL.
+ */
+void sysfs_put_active_two(struct sysfs_dirent *sd)
+{
+	if (sd) {
+		sysfs_put_active(sd);
+		sysfs_put_active(sd->s_parent);
+	}
+}
+
+/**
+ *	sysfs_deactivate - deactivate sysfs_dirent
+ *	@sd: sysfs_dirent to deactivate
+ *
+ *	Deny new active references and drain existing ones.
+ */
+static void sysfs_deactivate(struct sysfs_dirent *sd)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
+	int v;
+
+	BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
+	sd->s_sibling = (void *)&wait;
+
+	/* atomic_add_return() is a mb(), put_active() will always see
+	 * the updated sd->s_sibling.
+	 */
+	v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
+
+	if (v != SD_DEACTIVATED_BIAS)
+		wait_for_completion(&wait);
+
+	sd->s_sibling = NULL;
+}
+
+static int sysfs_alloc_ino(ino_t *pino)
+{
+	int ino, rc;
+
+ retry:
+	spin_lock(&sysfs_ino_lock);
+	rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
+	spin_unlock(&sysfs_ino_lock);
+
+	if (rc == -EAGAIN) {
+		if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
+			goto retry;
+		rc = -ENOMEM;
+	}
+
+	*pino = ino;
+	return rc;
+}
+
+static void sysfs_free_ino(ino_t ino)
+{
+	spin_lock(&sysfs_ino_lock);
+	ida_remove(&sysfs_ino_ida, ino);
+	spin_unlock(&sysfs_ino_lock);
+}
+
+void release_sysfs_dirent(struct sysfs_dirent * sd)
+{
+	struct sysfs_dirent *parent_sd;
+
+ repeat:
+	/* Moving/renaming is always done while holding reference.
+	 * sd->s_parent won't change beneath us.
+	 */
+	parent_sd = sd->s_parent;
+
+	if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
+		sysfs_put(sd->s_elem.symlink.target_sd);
+	if (sysfs_type(sd) & SYSFS_COPY_NAME)
+		kfree(sd->s_name);
+	kfree(sd->s_iattr);
+	sysfs_free_ino(sd->s_ino);
+	kmem_cache_free(sysfs_dir_cachep, sd);
+
+	sd = parent_sd;
+	if (sd && atomic_dec_and_test(&sd->s_count))
+		goto repeat;
+}
 
 static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
 {
 	struct sysfs_dirent * sd = dentry->d_fsdata;
 
 	if (sd) {
-		BUG_ON(sd->s_dentry != dentry);
-		sd->s_dentry = NULL;
+		/* sd->s_dentry is protected with sysfs_assoc_lock.
+		 * This allows sysfs_drop_dentry() to dereference it.
+		 */
+		spin_lock(&sysfs_assoc_lock);
+
+		/* The dentry might have been deleted or another
+		 * lookup could have happened updating sd->s_dentry to
+		 * point the new dentry.  Ignore if it isn't pointing
+		 * to this dentry.
+		 */
+		if (sd->s_dentry == dentry)
+			sd->s_dentry = NULL;
+		spin_unlock(&sysfs_assoc_lock);
 		sysfs_put(sd);
 	}
 	iput(inode);
@@ -30,245 +358,402 @@
 	.d_iput		= sysfs_d_iput,
 };
 
-/*
- * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
- */
-static struct sysfs_dirent * __sysfs_new_dirent(void * element)
+struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
 {
-	struct sysfs_dirent * sd;
+	char *dup_name = NULL;
+	struct sysfs_dirent *sd = NULL;
+
+	if (type & SYSFS_COPY_NAME) {
+		name = dup_name = kstrdup(name, GFP_KERNEL);
+		if (!name)
+			goto err_out;
+	}
 
 	sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
 	if (!sd)
-		return NULL;
+		goto err_out;
+
+	if (sysfs_alloc_ino(&sd->s_ino))
+		goto err_out;
 
 	atomic_set(&sd->s_count, 1);
+	atomic_set(&sd->s_active, 0);
 	atomic_set(&sd->s_event, 1);
-	INIT_LIST_HEAD(&sd->s_children);
-	INIT_LIST_HEAD(&sd->s_sibling);
-	sd->s_element = element;
 
-	return sd;
-}
-
-static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd,
-			      struct sysfs_dirent *sd)
-{
-	if (sd)
-		list_add(&sd->s_sibling, &parent_sd->s_children);
-}
-
-static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd,
-						void * element)
-{
-	struct sysfs_dirent *sd;
-	sd = __sysfs_new_dirent(element);
-	__sysfs_list_dirent(parent_sd, sd);
-	return sd;
-}
-
-/*
- *
- * Return -EEXIST if there is already a sysfs element with the same name for
- * the same parent.
- *
- * called with parent inode's i_mutex held
- */
-int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
-			  const unsigned char *new)
-{
-	struct sysfs_dirent * sd;
-
-	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
-		if (sd->s_element) {
-			const unsigned char *existing = sysfs_get_name(sd);
-			if (strcmp(existing, new))
-				continue;
-			else
-				return -EEXIST;
-		}
-	}
-
-	return 0;
-}
-
-
-static struct sysfs_dirent *
-__sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type)
-{
-	struct sysfs_dirent * sd;
-
-	sd = __sysfs_new_dirent(element);
-	if (!sd)
-		goto out;
-
+	sd->s_name = name;
 	sd->s_mode = mode;
-	sd->s_type = type;
-	sd->s_dentry = dentry;
-	if (dentry) {
-		dentry->d_fsdata = sysfs_get(sd);
-		dentry->d_op = &sysfs_dentry_ops;
-	}
+	sd->s_flags = type;
 
-out:
 	return sd;
+
+ err_out:
+	kfree(dup_name);
+	kmem_cache_free(sysfs_dir_cachep, sd);
+	return NULL;
 }
 
-int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
-			void * element, umode_t mode, int type)
+/**
+ *	sysfs_attach_dentry - associate sysfs_dirent with dentry
+ *	@sd: target sysfs_dirent
+ *	@dentry: dentry to associate
+ *
+ *	Associate @sd with @dentry.  This is protected by
+ *	sysfs_assoc_lock to avoid race with sysfs_d_iput().
+ *
+ *	LOCKING:
+ *	mutex_lock(sysfs_mutex)
+ */
+static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry)
+{
+	dentry->d_op = &sysfs_dentry_ops;
+	dentry->d_fsdata = sysfs_get(sd);
+
+	/* protect sd->s_dentry against sysfs_d_iput */
+	spin_lock(&sysfs_assoc_lock);
+	sd->s_dentry = dentry;
+	spin_unlock(&sysfs_assoc_lock);
+
+	d_rehash(dentry);
+}
+
+static int sysfs_ilookup_test(struct inode *inode, void *arg)
+{
+	struct sysfs_dirent *sd = arg;
+	return inode->i_ino == sd->s_ino;
+}
+
+/**
+ *	sysfs_addrm_start - prepare for sysfs_dirent add/remove
+ *	@acxt: pointer to sysfs_addrm_cxt to be used
+ *	@parent_sd: parent sysfs_dirent
+ *
+ *	This function is called when the caller is about to add or
+ *	remove sysfs_dirent under @parent_sd.  This function acquires
+ *	sysfs_mutex, grabs inode for @parent_sd if available and lock
+ *	i_mutex of it.  @acxt is used to keep and pass context to
+ *	other addrm functions.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).  sysfs_mutex is locked on
+ *	return.  i_mutex of parent inode is locked on return if
+ *	available.
+ */
+void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+		       struct sysfs_dirent *parent_sd)
+{
+	struct inode *inode;
+
+	memset(acxt, 0, sizeof(*acxt));
+	acxt->parent_sd = parent_sd;
+
+	/* Lookup parent inode.  inode initialization and I_NEW
+	 * clearing are protected by sysfs_mutex.  By grabbing it and
+	 * looking up with _nowait variant, inode state can be
+	 * determined reliably.
+	 */
+	mutex_lock(&sysfs_mutex);
+
+	inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
+				parent_sd);
+
+	if (inode && !(inode->i_state & I_NEW)) {
+		/* parent inode available */
+		acxt->parent_inode = inode;
+
+		/* sysfs_mutex is below i_mutex in lock hierarchy.
+		 * First, trylock i_mutex.  If fails, unlock
+		 * sysfs_mutex and lock them in order.
+		 */
+		if (!mutex_trylock(&inode->i_mutex)) {
+			mutex_unlock(&sysfs_mutex);
+			mutex_lock(&inode->i_mutex);
+			mutex_lock(&sysfs_mutex);
+		}
+	} else
+		iput(inode);
+}
+
+/**
+ *	sysfs_add_one - add sysfs_dirent to parent
+ *	@acxt: addrm context to use
+ *	@sd: sysfs_dirent to be added
+ *
+ *	Get @acxt->parent_sd and set sd->s_parent to it and increment
+ *	nlink of parent inode if @sd is a directory.  @sd is NOT
+ *	linked into the children list of the parent.  The caller
+ *	should invoke sysfs_link_sibling() after this function
+ *	completes if @sd needs to be on the children list.
+ *
+ *	This function should be called between calls to
+ *	sysfs_addrm_start() and sysfs_addrm_finish() and should be
+ *	passed the same @acxt as passed to sysfs_addrm_start().
+ *
+ *	LOCKING:
+ *	Determined by sysfs_addrm_start().
+ */
+void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+{
+	sd->s_parent = sysfs_get(acxt->parent_sd);
+
+	if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+		inc_nlink(acxt->parent_inode);
+
+	acxt->cnt++;
+}
+
+/**
+ *	sysfs_remove_one - remove sysfs_dirent from parent
+ *	@acxt: addrm context to use
+ *	@sd: sysfs_dirent to be added
+ *
+ *	Mark @sd removed and drop nlink of parent inode if @sd is a
+ *	directory.  @sd is NOT unlinked from the children list of the
+ *	parent.  The caller is repsonsible for removing @sd from the
+ *	children list before calling this function.
+ *
+ *	This function should be called between calls to
+ *	sysfs_addrm_start() and sysfs_addrm_finish() and should be
+ *	passed the same @acxt as passed to sysfs_addrm_start().
+ *
+ *	LOCKING:
+ *	Determined by sysfs_addrm_start().
+ */
+void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+{
+	BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED));
+
+	sd->s_flags |= SYSFS_FLAG_REMOVED;
+	sd->s_sibling = acxt->removed;
+	acxt->removed = sd;
+
+	if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+		drop_nlink(acxt->parent_inode);
+
+	acxt->cnt++;
+}
+
+/**
+ *	sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
+ *	@sd: target sysfs_dirent
+ *
+ *	Drop dentry for @sd.  @sd must have been unlinked from its
+ *	parent on entry to this function such that it can't be looked
+ *	up anymore.
+ *
+ *	@sd->s_dentry which is protected with sysfs_assoc_lock points
+ *	to the currently associated dentry but we're not holding a
+ *	reference to it and racing with dput().  Grab dcache_lock and
+ *	verify dentry before dropping it.  If @sd->s_dentry is NULL or
+ *	dput() beats us, no need to bother.
+ */
+static void sysfs_drop_dentry(struct sysfs_dirent *sd)
+{
+	struct dentry *dentry = NULL;
+	struct inode *inode;
+
+	/* We're not holding a reference to ->s_dentry dentry but the
+	 * field will stay valid as long as sysfs_assoc_lock is held.
+	 */
+	spin_lock(&sysfs_assoc_lock);
+	spin_lock(&dcache_lock);
+
+	/* drop dentry if it's there and dput() didn't kill it yet */
+	if (sd->s_dentry && sd->s_dentry->d_inode) {
+		dentry = dget_locked(sd->s_dentry);
+		spin_lock(&dentry->d_lock);
+		__d_drop(dentry);
+		spin_unlock(&dentry->d_lock);
+	}
+
+	spin_unlock(&dcache_lock);
+	spin_unlock(&sysfs_assoc_lock);
+
+	/* dentries for shadowed inodes are pinned, unpin */
+	if (dentry && sysfs_is_shadowed_inode(dentry->d_inode))
+		dput(dentry);
+	dput(dentry);
+
+	/* adjust nlink and update timestamp */
+	inode = ilookup(sysfs_sb, sd->s_ino);
+	if (inode) {
+		mutex_lock(&inode->i_mutex);
+
+		inode->i_ctime = CURRENT_TIME;
+		drop_nlink(inode);
+		if (sysfs_type(sd) == SYSFS_DIR)
+			drop_nlink(inode);
+
+		mutex_unlock(&inode->i_mutex);
+		iput(inode);
+	}
+}
+
+/**
+ *	sysfs_addrm_finish - finish up sysfs_dirent add/remove
+ *	@acxt: addrm context to finish up
+ *
+ *	Finish up sysfs_dirent add/remove.  Resources acquired by
+ *	sysfs_addrm_start() are released and removed sysfs_dirents are
+ *	cleaned up.  Timestamps on the parent inode are updated.
+ *
+ *	LOCKING:
+ *	All mutexes acquired by sysfs_addrm_start() are released.
+ *
+ *	RETURNS:
+ *	Number of added/removed sysfs_dirents since sysfs_addrm_start().
+ */
+int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
+{
+	/* release resources acquired by sysfs_addrm_start() */
+	mutex_unlock(&sysfs_mutex);
+	if (acxt->parent_inode) {
+		struct inode *inode = acxt->parent_inode;
+
+		/* if added/removed, update timestamps on the parent */
+		if (acxt->cnt)
+			inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+		mutex_unlock(&inode->i_mutex);
+		iput(inode);
+	}
+
+	/* kill removed sysfs_dirents */
+	while (acxt->removed) {
+		struct sysfs_dirent *sd = acxt->removed;
+
+		acxt->removed = sd->s_sibling;
+		sd->s_sibling = NULL;
+
+		sysfs_drop_dentry(sd);
+		sysfs_deactivate(sd);
+		sysfs_put(sd);
+	}
+
+	return acxt->cnt;
+}
+
+/**
+ *	sysfs_find_dirent - find sysfs_dirent with the given name
+ *	@parent_sd: sysfs_dirent to search under
+ *	@name: name to look for
+ *
+ *	Look for sysfs_dirent with name @name under @parent_sd.
+ *
+ *	LOCKING:
+ *	mutex_lock(sysfs_mutex)
+ *
+ *	RETURNS:
+ *	Pointer to sysfs_dirent if found, NULL if not.
+ */
+struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+				       const unsigned char *name)
 {
 	struct sysfs_dirent *sd;
 
-	sd = __sysfs_make_dirent(dentry, element, mode, type);
-	__sysfs_list_dirent(parent_sd, sd);
-
-	return sd ? 0 : -ENOMEM;
+	for (sd = parent_sd->s_children; sd; sd = sd->s_sibling)
+		if (sysfs_type(sd) && !strcmp(sd->s_name, name))
+			return sd;
+	return NULL;
 }
 
-static int init_dir(struct inode * inode)
+/**
+ *	sysfs_get_dirent - find and get sysfs_dirent with the given name
+ *	@parent_sd: sysfs_dirent to search under
+ *	@name: name to look for
+ *
+ *	Look for sysfs_dirent with name @name under @parent_sd and get
+ *	it if found.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).  Grabs sysfs_mutex.
+ *
+ *	RETURNS:
+ *	Pointer to sysfs_dirent if found, NULL if not.
+ */
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+				      const unsigned char *name)
 {
-	inode->i_op = &sysfs_dir_inode_operations;
-	inode->i_fop = &sysfs_dir_operations;
+	struct sysfs_dirent *sd;
 
-	/* directory inodes start off with i_nlink == 2 (for "." entry) */
-	inc_nlink(inode);
-	return 0;
+	mutex_lock(&sysfs_mutex);
+	sd = sysfs_find_dirent(parent_sd, name);
+	sysfs_get(sd);
+	mutex_unlock(&sysfs_mutex);
+
+	return sd;
 }
 
-static int init_file(struct inode * inode)
+static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
+		      const char *name, struct sysfs_dirent **p_sd)
 {
-	inode->i_size = PAGE_SIZE;
-	inode->i_fop = &sysfs_file_operations;
-	return 0;
-}
-
-static int init_symlink(struct inode * inode)
-{
-	inode->i_op = &sysfs_symlink_inode_operations;
-	return 0;
-}
-
-static int create_dir(struct kobject * k, struct dentry * p,
-		      const char * n, struct dentry ** d)
-{
-	int error;
 	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
+	struct sysfs_addrm_cxt acxt;
+	struct sysfs_dirent *sd;
 
-	mutex_lock(&p->d_inode->i_mutex);
-	*d = lookup_one_len(n, p, strlen(n));
-	if (!IS_ERR(*d)) {
- 		if (sysfs_dirent_exist(p->d_fsdata, n))
-  			error = -EEXIST;
-  		else
-			error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
-								SYSFS_DIR);
-		if (!error) {
-			error = sysfs_create(*d, mode, init_dir);
-			if (!error) {
-				inc_nlink(p->d_inode);
-				(*d)->d_op = &sysfs_dentry_ops;
-				d_rehash(*d);
-			}
-		}
-		if (error && (error != -EEXIST)) {
-			struct sysfs_dirent *sd = (*d)->d_fsdata;
-			if (sd) {
- 				list_del_init(&sd->s_sibling);
-				sysfs_put(sd);
-			}
-			d_drop(*d);
-		}
-		dput(*d);
-	} else
-		error = PTR_ERR(*d);
-	mutex_unlock(&p->d_inode->i_mutex);
-	return error;
+	/* allocate */
+	sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
+	if (!sd)
+		return -ENOMEM;
+	sd->s_elem.dir.kobj = kobj;
+
+	/* link in */
+	sysfs_addrm_start(&acxt, parent_sd);
+	if (!sysfs_find_dirent(parent_sd, name)) {
+		sysfs_add_one(&acxt, sd);
+		sysfs_link_sibling(sd);
+	}
+	if (sysfs_addrm_finish(&acxt)) {
+		*p_sd = sd;
+		return 0;
+	}
+
+	sysfs_put(sd);
+	return -EEXIST;
 }
 
-
-int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d)
+int sysfs_create_subdir(struct kobject *kobj, const char *name,
+			struct sysfs_dirent **p_sd)
 {
-	return create_dir(k,k->dentry,n,d);
+	return create_dir(kobj, kobj->sd, name, p_sd);
 }
 
 /**
  *	sysfs_create_dir - create a directory for an object.
  *	@kobj:		object we're creating directory for. 
- *	@shadow_parent:	parent parent object.
+ *	@shadow_parent:	parent object.
  */
-
-int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent)
+int sysfs_create_dir(struct kobject *kobj,
+		     struct sysfs_dirent *shadow_parent_sd)
 {
-	struct dentry * dentry = NULL;
-	struct dentry * parent;
+	struct sysfs_dirent *parent_sd, *sd;
 	int error = 0;
 
 	BUG_ON(!kobj);
 
-	if (shadow_parent)
-		parent = shadow_parent;
+	if (shadow_parent_sd)
+		parent_sd = shadow_parent_sd;
 	else if (kobj->parent)
-		parent = kobj->parent->dentry;
+		parent_sd = kobj->parent->sd;
 	else if (sysfs_mount && sysfs_mount->mnt_sb)
-		parent = sysfs_mount->mnt_sb->s_root;
+		parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
 	else
 		return -EFAULT;
 
-	error = create_dir(kobj,parent,kobject_name(kobj),&dentry);
+	error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);
 	if (!error)
-		kobj->dentry = dentry;
+		kobj->sd = sd;
 	return error;
 }
 
-/* attaches attribute's sysfs_dirent to the dentry corresponding to the
- * attribute file
- */
-static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
+static int sysfs_count_nlink(struct sysfs_dirent *sd)
 {
-	struct attribute * attr = NULL;
-	struct bin_attribute * bin_attr = NULL;
-	int (* init) (struct inode *) = NULL;
-	int error = 0;
+	struct sysfs_dirent *child;
+	int nr = 0;
 
-        if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
-                bin_attr = sd->s_element;
-                attr = &bin_attr->attr;
-        } else {
-                attr = sd->s_element;
-                init = init_file;
-        }
-
-	dentry->d_fsdata = sysfs_get(sd);
-	sd->s_dentry = dentry;
-	error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
-	if (error) {
-		sysfs_put(sd);
-		return error;
-	}
-
-        if (bin_attr) {
-		dentry->d_inode->i_size = bin_attr->size;
-		dentry->d_inode->i_fop = &bin_fops;
-	}
-	dentry->d_op = &sysfs_dentry_ops;
-	d_rehash(dentry);
-
-	return 0;
-}
-
-static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
-{
-	int err = 0;
-
-	dentry->d_fsdata = sysfs_get(sd);
-	sd->s_dentry = dentry;
-	err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
-	if (!err) {
-		dentry->d_op = &sysfs_dentry_ops;
-		d_rehash(dentry);
-	} else
-		sysfs_put(sd);
-
-	return err;
+	for (child = sd->s_children; child; child = child->s_sibling)
+		if (sysfs_type(child) == SYSFS_DIR)
+			nr++;
+	return nr + 2;
 }
 
 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
@@ -276,24 +761,60 @@
 {
 	struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
 	struct sysfs_dirent * sd;
-	int err = 0;
+	struct bin_attribute *bin_attr;
+	struct inode *inode;
+	int found = 0;
 
-	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
-		if (sd->s_type & SYSFS_NOT_PINNED) {
-			const unsigned char * name = sysfs_get_name(sd);
-
-			if (strcmp(name, dentry->d_name.name))
-				continue;
-
-			if (sd->s_type & SYSFS_KOBJ_LINK)
-				err = sysfs_attach_link(sd, dentry);
-			else
-				err = sysfs_attach_attr(sd, dentry);
+	for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
+		if (sysfs_type(sd) &&
+		    !strcmp(sd->s_name, dentry->d_name.name)) {
+			found = 1;
 			break;
 		}
 	}
 
-	return ERR_PTR(err);
+	/* no such entry */
+	if (!found)
+		return NULL;
+
+	/* attach dentry and inode */
+	inode = sysfs_get_inode(sd);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_lock(&sysfs_mutex);
+
+	if (inode->i_state & I_NEW) {
+		/* initialize inode according to type */
+		switch (sysfs_type(sd)) {
+		case SYSFS_DIR:
+			inode->i_op = &sysfs_dir_inode_operations;
+			inode->i_fop = &sysfs_dir_operations;
+			inode->i_nlink = sysfs_count_nlink(sd);
+			break;
+		case SYSFS_KOBJ_ATTR:
+			inode->i_size = PAGE_SIZE;
+			inode->i_fop = &sysfs_file_operations;
+			break;
+		case SYSFS_KOBJ_BIN_ATTR:
+			bin_attr = sd->s_elem.bin_attr.bin_attr;
+			inode->i_size = bin_attr->size;
+			inode->i_fop = &bin_fops;
+			break;
+		case SYSFS_KOBJ_LINK:
+			inode->i_op = &sysfs_symlink_inode_operations;
+			break;
+		default:
+			BUG();
+		}
+	}
+
+	sysfs_instantiate(dentry, inode);
+	sysfs_attach_dentry(sd, dentry);
+
+	mutex_unlock(&sysfs_mutex);
+
+	return NULL;
 }
 
 const struct inode_operations sysfs_dir_inode_operations = {
@@ -301,58 +822,46 @@
 	.setattr	= sysfs_setattr,
 };
 
-static void remove_dir(struct dentry * d)
+static void remove_dir(struct sysfs_dirent *sd)
 {
-	struct dentry * parent = dget(d->d_parent);
-	struct sysfs_dirent * sd;
+	struct sysfs_addrm_cxt acxt;
 
-	mutex_lock(&parent->d_inode->i_mutex);
-	d_delete(d);
-	sd = d->d_fsdata;
- 	list_del_init(&sd->s_sibling);
-	sysfs_put(sd);
-	if (d->d_inode)
-		simple_rmdir(parent->d_inode,d);
-
-	pr_debug(" o %s removing done (%d)\n",d->d_name.name,
-		 atomic_read(&d->d_count));
-
-	mutex_unlock(&parent->d_inode->i_mutex);
-	dput(parent);
+	sysfs_addrm_start(&acxt, sd->s_parent);
+	sysfs_unlink_sibling(sd);
+	sysfs_remove_one(&acxt, sd);
+	sysfs_addrm_finish(&acxt);
 }
 
-void sysfs_remove_subdir(struct dentry * d)
+void sysfs_remove_subdir(struct sysfs_dirent *sd)
 {
-	remove_dir(d);
+	remove_dir(sd);
 }
 
 
-static void __sysfs_remove_dir(struct dentry *dentry)
+static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
 {
-	struct sysfs_dirent * parent_sd;
-	struct sysfs_dirent * sd, * tmp;
+	struct sysfs_addrm_cxt acxt;
+	struct sysfs_dirent **pos;
 
-	dget(dentry);
-	if (!dentry)
+	if (!dir_sd)
 		return;
 
-	pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
-	mutex_lock(&dentry->d_inode->i_mutex);
-	parent_sd = dentry->d_fsdata;
-	list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
-		if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED))
-			continue;
-		list_del_init(&sd->s_sibling);
-		sysfs_drop_dentry(sd, dentry);
-		sysfs_put(sd);
-	}
-	mutex_unlock(&dentry->d_inode->i_mutex);
+	pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
+	sysfs_addrm_start(&acxt, dir_sd);
+	pos = &dir_sd->s_children;
+	while (*pos) {
+		struct sysfs_dirent *sd = *pos;
 
-	remove_dir(dentry);
-	/**
-	 * Drop reference from dget() on entrance.
-	 */
-	dput(dentry);
+		if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) {
+			*pos = sd->s_sibling;
+			sd->s_sibling = NULL;
+			sysfs_remove_one(&acxt, sd);
+		} else
+			pos = &(*pos)->s_sibling;
+	}
+	sysfs_addrm_finish(&acxt);
+
+	remove_dir(dir_sd);
 }
 
 /**
@@ -366,102 +875,166 @@
 
 void sysfs_remove_dir(struct kobject * kobj)
 {
-	__sysfs_remove_dir(kobj->dentry);
-	kobj->dentry = NULL;
+	struct sysfs_dirent *sd = kobj->sd;
+
+	spin_lock(&sysfs_assoc_lock);
+	kobj->sd = NULL;
+	spin_unlock(&sysfs_assoc_lock);
+
+	__sysfs_remove_dir(sd);
 }
 
-int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
+int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
 		     const char *new_name)
 {
-	int error = 0;
-	struct dentry * new_dentry;
+	struct sysfs_dirent *sd = kobj->sd;
+	struct dentry *new_parent = NULL;
+	struct dentry *old_dentry = NULL, *new_dentry = NULL;
+	const char *dup_name = NULL;
+	int error;
 
-	if (!new_parent)
-		return -EFAULT;
+	/* get dentries */
+	old_dentry = sysfs_get_dentry(sd);
+	if (IS_ERR(old_dentry)) {
+		error = PTR_ERR(old_dentry);
+		goto out_dput;
+	}
 
-	down_write(&sysfs_rename_sem);
+	new_parent = sysfs_get_dentry(new_parent_sd);
+	if (IS_ERR(new_parent)) {
+		error = PTR_ERR(new_parent);
+		goto out_dput;
+	}
+
+	/* lock new_parent and get dentry for new name */
 	mutex_lock(&new_parent->d_inode->i_mutex);
 
 	new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
-	if (!IS_ERR(new_dentry)) {
-		/* By allowing two different directories with the
-		 * same d_parent we allow this routine to move
-		 * between different shadows of the same directory
-		 */
-		if (kobj->dentry->d_parent->d_inode != new_parent->d_inode)
-			return -EINVAL;
-		else if (new_dentry->d_parent->d_inode != new_parent->d_inode)
-			error = -EINVAL;
-		else if (new_dentry == kobj->dentry)
-			error = -EINVAL;
-		else if (!new_dentry->d_inode) {
-			error = kobject_set_name(kobj, "%s", new_name);
-			if (!error) {
-				struct sysfs_dirent *sd, *parent_sd;
-
-				d_add(new_dentry, NULL);
-				d_move(kobj->dentry, new_dentry);
-
-				sd = kobj->dentry->d_fsdata;
-				parent_sd = new_parent->d_fsdata;
-
-				list_del_init(&sd->s_sibling);
-				list_add(&sd->s_sibling, &parent_sd->s_children);
-			}
-			else
-				d_drop(new_dentry);
-		} else
-			error = -EEXIST;
-		dput(new_dentry);
+	if (IS_ERR(new_dentry)) {
+		error = PTR_ERR(new_dentry);
+		goto out_unlock;
 	}
-	mutex_unlock(&new_parent->d_inode->i_mutex);
-	up_write(&sysfs_rename_sem);
 
+	/* By allowing two different directories with the same
+	 * d_parent we allow this routine to move between different
+	 * shadows of the same directory
+	 */
+	error = -EINVAL;
+	if (old_dentry->d_parent->d_inode != new_parent->d_inode ||
+	    new_dentry->d_parent->d_inode != new_parent->d_inode ||
+	    old_dentry == new_dentry)
+		goto out_unlock;
+
+	error = -EEXIST;
+	if (new_dentry->d_inode)
+		goto out_unlock;
+
+	/* rename kobject and sysfs_dirent */
+	error = -ENOMEM;
+	new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
+	if (!new_name)
+		goto out_drop;
+
+	error = kobject_set_name(kobj, "%s", new_name);
+	if (error)
+		goto out_drop;
+
+	dup_name = sd->s_name;
+	sd->s_name = new_name;
+
+	/* move under the new parent */
+	d_add(new_dentry, NULL);
+	d_move(sd->s_dentry, new_dentry);
+
+	mutex_lock(&sysfs_mutex);
+
+	sysfs_unlink_sibling(sd);
+	sysfs_get(new_parent_sd);
+	sysfs_put(sd->s_parent);
+	sd->s_parent = new_parent_sd;
+	sysfs_link_sibling(sd);
+
+	mutex_unlock(&sysfs_mutex);
+
+	error = 0;
+	goto out_unlock;
+
+ out_drop:
+	d_drop(new_dentry);
+ out_unlock:
+	mutex_unlock(&new_parent->d_inode->i_mutex);
+ out_dput:
+	kfree(dup_name);
+	dput(new_parent);
+	dput(old_dentry);
+	dput(new_dentry);
 	return error;
 }
 
-int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
+int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
 {
-	struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
-	struct sysfs_dirent *new_parent_sd, *sd;
+	struct sysfs_dirent *sd = kobj->sd;
+	struct sysfs_dirent *new_parent_sd;
+	struct dentry *old_parent, *new_parent = NULL;
+	struct dentry *old_dentry = NULL, *new_dentry = NULL;
 	int error;
 
-	old_parent_dentry = kobj->parent ?
-		kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
-	new_parent_dentry = new_parent ?
-		new_parent->dentry : sysfs_mount->mnt_sb->s_root;
+	BUG_ON(!sd->s_parent);
+	new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root;
 
-	if (old_parent_dentry->d_inode == new_parent_dentry->d_inode)
-		return 0;	/* nothing to move */
+	/* get dentries */
+	old_dentry = sysfs_get_dentry(sd);
+	if (IS_ERR(old_dentry)) {
+		error = PTR_ERR(old_dentry);
+		goto out_dput;
+	}
+	old_parent = sd->s_parent->s_dentry;
+
+	new_parent = sysfs_get_dentry(new_parent_sd);
+	if (IS_ERR(new_parent)) {
+		error = PTR_ERR(new_parent);
+		goto out_dput;
+	}
+
+	if (old_parent->d_inode == new_parent->d_inode) {
+		error = 0;
+		goto out_dput;	/* nothing to move */
+	}
 again:
-	mutex_lock(&old_parent_dentry->d_inode->i_mutex);
-	if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
-		mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+	mutex_lock(&old_parent->d_inode->i_mutex);
+	if (!mutex_trylock(&new_parent->d_inode->i_mutex)) {
+		mutex_unlock(&old_parent->d_inode->i_mutex);
 		goto again;
 	}
 
-	new_parent_sd = new_parent_dentry->d_fsdata;
-	sd = kobj->dentry->d_fsdata;
-
-	new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
-				    strlen(kobj->name));
+	new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name));
 	if (IS_ERR(new_dentry)) {
 		error = PTR_ERR(new_dentry);
-		goto out;
+		goto out_unlock;
 	} else
 		error = 0;
 	d_add(new_dentry, NULL);
-	d_move(kobj->dentry, new_dentry);
+	d_move(sd->s_dentry, new_dentry);
 	dput(new_dentry);
 
 	/* Remove from old parent's list and insert into new parent's list. */
-	list_del_init(&sd->s_sibling);
-	list_add(&sd->s_sibling, &new_parent_sd->s_children);
+	mutex_lock(&sysfs_mutex);
 
-out:
-	mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
-	mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+	sysfs_unlink_sibling(sd);
+	sysfs_get(new_parent_sd);
+	sysfs_put(sd->s_parent);
+	sd->s_parent = new_parent_sd;
+	sysfs_link_sibling(sd);
 
+	mutex_unlock(&sysfs_mutex);
+
+ out_unlock:
+	mutex_unlock(&new_parent->d_inode->i_mutex);
+	mutex_unlock(&old_parent->d_inode->i_mutex);
+ out_dput:
+	dput(new_parent);
+	dput(old_dentry);
+	dput(new_dentry);
 	return error;
 }
 
@@ -469,23 +1042,27 @@
 {
 	struct dentry * dentry = file->f_path.dentry;
 	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
+	struct sysfs_dirent * sd;
 
-	mutex_lock(&dentry->d_inode->i_mutex);
-	file->private_data = sysfs_new_dirent(parent_sd, NULL);
-	mutex_unlock(&dentry->d_inode->i_mutex);
+	sd = sysfs_new_dirent("_DIR_", 0, 0);
+	if (sd) {
+		mutex_lock(&sysfs_mutex);
+		sd->s_parent = sysfs_get(parent_sd);
+		sysfs_link_sibling(sd);
+		mutex_unlock(&sysfs_mutex);
+	}
 
-	return file->private_data ? 0 : -ENOMEM;
-
+	file->private_data = sd;
+	return sd ? 0 : -ENOMEM;
 }
 
 static int sysfs_dir_close(struct inode *inode, struct file *file)
 {
-	struct dentry * dentry = file->f_path.dentry;
 	struct sysfs_dirent * cursor = file->private_data;
 
-	mutex_lock(&dentry->d_inode->i_mutex);
-	list_del_init(&cursor->s_sibling);
-	mutex_unlock(&dentry->d_inode->i_mutex);
+	mutex_lock(&sysfs_mutex);
+	sysfs_unlink_sibling(cursor);
+	mutex_unlock(&sysfs_mutex);
 
 	release_sysfs_dirent(cursor);
 
@@ -503,54 +1080,65 @@
 	struct dentry *dentry = filp->f_path.dentry;
 	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
 	struct sysfs_dirent *cursor = filp->private_data;
-	struct list_head *p, *q = &cursor->s_sibling;
+	struct sysfs_dirent **pos;
 	ino_t ino;
 	int i = filp->f_pos;
 
 	switch (i) {
 		case 0:
-			ino = dentry->d_inode->i_ino;
+			ino = parent_sd->s_ino;
 			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
 				break;
 			filp->f_pos++;
 			i++;
 			/* fallthrough */
 		case 1:
-			ino = parent_ino(dentry);
+			if (parent_sd->s_parent)
+				ino = parent_sd->s_parent->s_ino;
+			else
+				ino = parent_sd->s_ino;
 			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
 				break;
 			filp->f_pos++;
 			i++;
 			/* fallthrough */
 		default:
-			if (filp->f_pos == 2)
-				list_move(q, &parent_sd->s_children);
+			mutex_lock(&sysfs_mutex);
 
-			for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
-				struct sysfs_dirent *next;
+			pos = &parent_sd->s_children;
+			while (*pos != cursor)
+				pos = &(*pos)->s_sibling;
+
+			/* unlink cursor */
+			*pos = cursor->s_sibling;
+
+			if (filp->f_pos == 2)
+				pos = &parent_sd->s_children;
+
+			for ( ; *pos; pos = &(*pos)->s_sibling) {
+				struct sysfs_dirent *next = *pos;
 				const char * name;
 				int len;
 
-				next = list_entry(p, struct sysfs_dirent,
-						   s_sibling);
-				if (!next->s_element)
+				if (!sysfs_type(next))
 					continue;
 
-				name = sysfs_get_name(next);
+				name = next->s_name;
 				len = strlen(name);
-				if (next->s_dentry)
-					ino = next->s_dentry->d_inode->i_ino;
-				else
-					ino = iunique(sysfs_sb, 2);
+				ino = next->s_ino;
 
 				if (filldir(dirent, name, len, filp->f_pos, ino,
 						 dt_type(next)) < 0)
-					return 0;
+					break;
 
-				list_move(q, p);
-				p = q;
 				filp->f_pos++;
 			}
+
+			/* put cursor back in */
+			cursor->s_sibling = *pos;
+			*pos = cursor;
+
+			mutex_unlock(&sysfs_mutex);
 	}
 	return 0;
 }
@@ -559,7 +1147,6 @@
 {
 	struct dentry * dentry = file->f_path.dentry;
 
-	mutex_lock(&dentry->d_inode->i_mutex);
 	switch (origin) {
 		case 1:
 			offset += file->f_pos;
@@ -567,31 +1154,35 @@
 			if (offset >= 0)
 				break;
 		default:
-			mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
 			return -EINVAL;
 	}
 	if (offset != file->f_pos) {
+		mutex_lock(&sysfs_mutex);
+
 		file->f_pos = offset;
 		if (file->f_pos >= 2) {
 			struct sysfs_dirent *sd = dentry->d_fsdata;
 			struct sysfs_dirent *cursor = file->private_data;
-			struct list_head *p;
+			struct sysfs_dirent **pos;
 			loff_t n = file->f_pos - 2;
 
-			list_del(&cursor->s_sibling);
-			p = sd->s_children.next;
-			while (n && p != &sd->s_children) {
-				struct sysfs_dirent *next;
-				next = list_entry(p, struct sysfs_dirent,
-						   s_sibling);
-				if (next->s_element)
+			sysfs_unlink_sibling(cursor);
+
+			pos = &sd->s_children;
+			while (n && *pos) {
+				struct sysfs_dirent *next = *pos;
+				if (sysfs_type(next))
 					n--;
-				p = p->next;
+				pos = &(*pos)->s_sibling;
 			}
-			list_add_tail(&cursor->s_sibling, p);
+
+			cursor->s_sibling = *pos;
+			*pos = cursor;
 		}
+
+		mutex_unlock(&sysfs_mutex);
 	}
-	mutex_unlock(&dentry->d_inode->i_mutex);
+
 	return offset;
 }
 
@@ -604,12 +1195,20 @@
 int sysfs_make_shadowed_dir(struct kobject *kobj,
 	void * (*follow_link)(struct dentry *, struct nameidata *))
 {
+	struct dentry *dentry;
 	struct inode *inode;
 	struct inode_operations *i_op;
 
-	inode = kobj->dentry->d_inode;
-	if (inode->i_op != &sysfs_dir_inode_operations)
+	/* get dentry for @kobj->sd, dentry of a shadowed dir is pinned */
+	dentry = sysfs_get_dentry(kobj->sd);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+
+	inode = dentry->d_inode;
+	if (inode->i_op != &sysfs_dir_inode_operations) {
+		dput(dentry);
 		return -EINVAL;
+	}
 
 	i_op = kmalloc(sizeof(*i_op), GFP_KERNEL);
 	if (!i_op)
@@ -634,54 +1233,72 @@
  *	directory.
  */
 
-struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
+struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj)
 {
-	struct sysfs_dirent *sd;
-	struct dentry *parent, *dir, *shadow;
+	struct sysfs_dirent *parent_sd = kobj->sd->s_parent;
+	struct dentry *dir, *parent, *shadow;
 	struct inode *inode;
+	struct sysfs_dirent *sd;
+	struct sysfs_addrm_cxt acxt;
 
-	dir = kobj->dentry;
-	inode = dir->d_inode;
-	parent = dir->d_parent;
-	shadow = ERR_PTR(-EINVAL);
-	if (!sysfs_is_shadowed_inode(inode))
+	dir = sysfs_get_dentry(kobj->sd);
+	if (IS_ERR(dir)) {
+		sd = (void *)dir;
 		goto out;
+	}
+	parent = dir->d_parent;
+
+	inode = dir->d_inode;
+	sd = ERR_PTR(-EINVAL);
+	if (!sysfs_is_shadowed_inode(inode))
+		goto out_dput;
 
 	shadow = d_alloc(parent, &dir->d_name);
 	if (!shadow)
 		goto nomem;
 
-	sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR);
+	sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR);
 	if (!sd)
 		goto nomem;
+	sd->s_elem.dir.kobj = kobj;
 
+	sysfs_addrm_start(&acxt, parent_sd);
+
+	/* add but don't link into children list */
+	sysfs_add_one(&acxt, sd);
+
+	/* attach and instantiate dentry */
+	sysfs_attach_dentry(sd, shadow);
 	d_instantiate(shadow, igrab(inode));
-	inc_nlink(inode);
-	inc_nlink(parent->d_inode);
-	shadow->d_op = &sysfs_dentry_ops;
+	inc_nlink(inode);	/* tj: synchronization? */
+
+	sysfs_addrm_finish(&acxt);
 
 	dget(shadow);		/* Extra count - pin the dentry in core */
 
-out:
-	return shadow;
-nomem:
+	goto out_dput;
+
+ nomem:
 	dput(shadow);
-	shadow = ERR_PTR(-ENOMEM);
-	goto out;
+	sd = ERR_PTR(-ENOMEM);
+ out_dput:
+	dput(dir);
+ out:
+	return sd;
 }
 
 /**
  *	sysfs_remove_shadow_dir - remove an object's directory.
- *	@shadow: dentry of shadow directory
+ *	@shadow_sd: sysfs_dirent of shadow directory
  *
  *	The only thing special about this is that we remove any files in
  *	the directory before we remove the directory, and we've inlined
  *	what used to be sysfs_rmdir() below, instead of calling separately.
  */
 
-void sysfs_remove_shadow_dir(struct dentry *shadow)
+void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd)
 {
-	__sysfs_remove_dir(shadow);
+	__sysfs_remove_dir(shadow_sd);
 }
 
 const struct file_operations sysfs_dir_operations = {
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index b502c71..cc49799 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -50,29 +50,15 @@
 	.store	= subsys_attr_store,
 };
 
-/**
- *	add_to_collection - add buffer to a collection
- *	@buffer:	buffer to be added
- *	@node:		inode of set to add to
- */
-
-static inline void
-add_to_collection(struct sysfs_buffer *buffer, struct inode *node)
-{
-	struct sysfs_buffer_collection *set = node->i_private;
-
-	mutex_lock(&node->i_mutex);
-	list_add(&buffer->associates, &set->associates);
-	mutex_unlock(&node->i_mutex);
-}
-
-static inline void
-remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
-{
-	mutex_lock(&node->i_mutex);
-	list_del(&buffer->associates);
-	mutex_unlock(&node->i_mutex);
-}
+struct sysfs_buffer {
+	size_t			count;
+	loff_t			pos;
+	char			* page;
+	struct sysfs_ops	* ops;
+	struct semaphore	sem;
+	int			needs_read_fill;
+	int			event;
+};
 
 /**
  *	fill_read_buffer - allocate and fill buffer from object.
@@ -87,9 +73,8 @@
  */
 static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
 {
-	struct sysfs_dirent * sd = dentry->d_fsdata;
-	struct attribute * attr = to_attr(dentry);
-	struct kobject * kobj = to_kobj(dentry->d_parent);
+	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+	struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
 	struct sysfs_ops * ops = buffer->ops;
 	int ret = 0;
 	ssize_t count;
@@ -99,8 +84,15 @@
 	if (!buffer->page)
 		return -ENOMEM;
 
-	buffer->event = atomic_read(&sd->s_event);
-	count = ops->show(kobj,attr,buffer->page);
+	/* need attr_sd for attr and ops, its parent for kobj */
+	if (!sysfs_get_active_two(attr_sd))
+		return -ENODEV;
+
+	buffer->event = atomic_read(&attr_sd->s_event);
+	count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
+
+	sysfs_put_active_two(attr_sd);
+
 	BUG_ON(count > (ssize_t)PAGE_SIZE);
 	if (count >= 0) {
 		buffer->needs_read_fill = 0;
@@ -138,10 +130,7 @@
 
 	down(&buffer->sem);
 	if (buffer->needs_read_fill) {
-		if (buffer->orphaned)
-			retval = -ENODEV;
-		else
-			retval = fill_read_buffer(file->f_path.dentry,buffer);
+		retval = fill_read_buffer(file->f_path.dentry,buffer);
 		if (retval)
 			goto out;
 	}
@@ -196,14 +185,23 @@
  *	passing the buffer that we acquired in fill_write_buffer().
  */
 
-static int 
+static int
 flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
 {
-	struct attribute * attr = to_attr(dentry);
-	struct kobject * kobj = to_kobj(dentry->d_parent);
+	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+	struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
 	struct sysfs_ops * ops = buffer->ops;
+	int rc;
 
-	return ops->store(kobj,attr,buffer->page,count);
+	/* need attr_sd for attr and ops, its parent for kobj */
+	if (!sysfs_get_active_two(attr_sd))
+		return -ENODEV;
+
+	rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
+
+	sysfs_put_active_two(attr_sd);
+
+	return rc;
 }
 
 
@@ -231,37 +229,26 @@
 	ssize_t len;
 
 	down(&buffer->sem);
-	if (buffer->orphaned) {
-		len = -ENODEV;
-		goto out;
-	}
 	len = fill_write_buffer(buffer, buf, count);
 	if (len > 0)
 		len = flush_write_buffer(file->f_path.dentry, buffer, len);
 	if (len > 0)
 		*ppos += len;
-out:
 	up(&buffer->sem);
 	return len;
 }
 
 static int sysfs_open_file(struct inode *inode, struct file *file)
 {
-	struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
-	struct attribute * attr = to_attr(file->f_path.dentry);
-	struct sysfs_buffer_collection *set;
+	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+	struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
 	struct sysfs_buffer * buffer;
 	struct sysfs_ops * ops = NULL;
-	int error = 0;
+	int error;
 
-	if (!kobj || !attr)
-		goto Einval;
-
-	/* Grab the module reference for this attribute if we have one */
-	if (!try_module_get(attr->owner)) {
-		error = -ENODEV;
-		goto Done;
-	}
+	/* need attr_sd for attr and ops, its parent for kobj */
+	if (!sysfs_get_active_two(attr_sd))
+		return -ENODEV;
 
 	/* if the kobject has no ktype, then we assume that it is a subsystem
 	 * itself, and use ops for it.
@@ -273,33 +260,21 @@
 	else
 		ops = &subsys_sysfs_ops;
 
+	error = -EACCES;
+
 	/* No sysfs operations, either from having no subsystem,
 	 * or the subsystem have no operations.
 	 */
 	if (!ops)
-		goto Eaccess;
-
-	/* make sure we have a collection to add our buffers to */
-	mutex_lock(&inode->i_mutex);
-	if (!(set = inode->i_private)) {
-		if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) {
-			error = -ENOMEM;
-			goto Done;
-		} else {
-			INIT_LIST_HEAD(&set->associates);
-		}
-	}
-	mutex_unlock(&inode->i_mutex);
+		goto err_out;
 
 	/* File needs write support.
 	 * The inode's perms must say it's ok, 
 	 * and we must have a store method.
 	 */
 	if (file->f_mode & FMODE_WRITE) {
-
 		if (!(inode->i_mode & S_IWUGO) || !ops->store)
-			goto Eaccess;
-
+			goto err_out;
 	}
 
 	/* File needs read support.
@@ -308,48 +283,38 @@
 	 */
 	if (file->f_mode & FMODE_READ) {
 		if (!(inode->i_mode & S_IRUGO) || !ops->show)
-			goto Eaccess;
+			goto err_out;
 	}
 
 	/* No error? Great, allocate a buffer for the file, and store it
 	 * it in file->private_data for easy access.
 	 */
+	error = -ENOMEM;
 	buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
-	if (buffer) {
-		INIT_LIST_HEAD(&buffer->associates);
-		init_MUTEX(&buffer->sem);
-		buffer->needs_read_fill = 1;
-		buffer->ops = ops;
-		add_to_collection(buffer, inode);
-		file->private_data = buffer;
-	} else
-		error = -ENOMEM;
-	goto Done;
+	if (!buffer)
+		goto err_out;
 
- Einval:
-	error = -EINVAL;
-	goto Done;
- Eaccess:
-	error = -EACCES;
-	module_put(attr->owner);
- Done:
-	if (error)
-		kobject_put(kobj);
+	init_MUTEX(&buffer->sem);
+	buffer->needs_read_fill = 1;
+	buffer->ops = ops;
+	file->private_data = buffer;
+
+	/* open succeeded, put active references and pin attr_sd */
+	sysfs_put_active_two(attr_sd);
+	sysfs_get(attr_sd);
+	return 0;
+
+ err_out:
+	sysfs_put_active_two(attr_sd);
 	return error;
 }
 
 static int sysfs_release(struct inode * inode, struct file * filp)
 {
-	struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
-	struct attribute * attr = to_attr(filp->f_path.dentry);
-	struct module * owner = attr->owner;
-	struct sysfs_buffer * buffer = filp->private_data;
+	struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
+	struct sysfs_buffer *buffer = filp->private_data;
 
-	if (buffer)
-		remove_from_collection(buffer, inode);
-	kobject_put(kobj);
-	/* After this point, attr should not be accessed. */
-	module_put(owner);
+	sysfs_put(attr_sd);
 
 	if (buffer) {
 		if (buffer->page)
@@ -376,57 +341,43 @@
 static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
 {
 	struct sysfs_buffer * buffer = filp->private_data;
-	struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
-	struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
-	int res = 0;
+	struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
+	struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+
+	/* need parent for the kobj, grab both */
+	if (!sysfs_get_active_two(attr_sd))
+		goto trigger;
 
 	poll_wait(filp, &kobj->poll, wait);
 
-	if (buffer->event != atomic_read(&sd->s_event)) {
-		res = POLLERR|POLLPRI;
-		buffer->needs_read_fill = 1;
-	}
+	sysfs_put_active_two(attr_sd);
 
-	return res;
+	if (buffer->event != atomic_read(&attr_sd->s_event))
+		goto trigger;
+
+	return 0;
+
+ trigger:
+	buffer->needs_read_fill = 1;
+	return POLLERR|POLLPRI;
 }
 
-
-static struct dentry *step_down(struct dentry *dir, const char * name)
+void sysfs_notify(struct kobject *k, char *dir, char *attr)
 {
-	struct dentry * de;
+	struct sysfs_dirent *sd = k->sd;
 
-	if (dir == NULL || dir->d_inode == NULL)
-		return NULL;
+	mutex_lock(&sysfs_mutex);
 
-	mutex_lock(&dir->d_inode->i_mutex);
-	de = lookup_one_len(name, dir, strlen(name));
-	mutex_unlock(&dir->d_inode->i_mutex);
-	dput(dir);
-	if (IS_ERR(de))
-		return NULL;
-	if (de->d_inode == NULL) {
-		dput(de);
-		return NULL;
-	}
-	return de;
-}
-
-void sysfs_notify(struct kobject * k, char *dir, char *attr)
-{
-	struct dentry *de = k->dentry;
-	if (de)
-		dget(de);
-	if (de && dir)
-		de = step_down(de, dir);
-	if (de && attr)
-		de = step_down(de, attr);
-	if (de) {
-		struct sysfs_dirent * sd = de->d_fsdata;
-		if (sd)
-			atomic_inc(&sd->s_event);
+	if (sd && dir)
+		sd = sysfs_find_dirent(sd, dir);
+	if (sd && attr)
+		sd = sysfs_find_dirent(sd, attr);
+	if (sd) {
+		atomic_inc(&sd->s_event);
 		wake_up_interruptible(&k->poll);
-		dput(de);
 	}
+
+	mutex_unlock(&sysfs_mutex);
 }
 EXPORT_SYMBOL_GPL(sysfs_notify);
 
@@ -440,19 +391,30 @@
 };
 
 
-int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
+int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
+		   int type)
 {
-	struct sysfs_dirent * parent_sd = dir->d_fsdata;
 	umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
-	int error = -EEXIST;
+	struct sysfs_addrm_cxt acxt;
+	struct sysfs_dirent *sd;
 
-	mutex_lock(&dir->d_inode->i_mutex);
-	if (!sysfs_dirent_exist(parent_sd, attr->name))
-		error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
-					  mode, type);
-	mutex_unlock(&dir->d_inode->i_mutex);
+	sd = sysfs_new_dirent(attr->name, mode, type);
+	if (!sd)
+		return -ENOMEM;
+	sd->s_elem.attr.attr = (void *)attr;
 
-	return error;
+	sysfs_addrm_start(&acxt, dir_sd);
+
+	if (!sysfs_find_dirent(dir_sd, attr->name)) {
+		sysfs_add_one(&acxt, sd);
+		sysfs_link_sibling(sd);
+	}
+
+	if (sysfs_addrm_finish(&acxt))
+		return 0;
+
+	sysfs_put(sd);
+	return -EEXIST;
 }
 
 
@@ -464,9 +426,9 @@
 
 int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
 {
-	BUG_ON(!kobj || !kobj->dentry || !attr);
+	BUG_ON(!kobj || !kobj->sd || !attr);
 
-	return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
+	return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
 
 }
 
@@ -480,16 +442,16 @@
 int sysfs_add_file_to_group(struct kobject *kobj,
 		const struct attribute *attr, const char *group)
 {
-	struct dentry *dir;
+	struct sysfs_dirent *dir_sd;
 	int error;
 
-	dir = lookup_one_len(group, kobj->dentry, strlen(group));
-	if (IS_ERR(dir))
-		error = PTR_ERR(dir);
-	else {
-		error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
-		dput(dir);
-	}
+	dir_sd = sysfs_get_dirent(kobj->sd, group);
+	if (!dir_sd)
+		return -ENOENT;
+
+	error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR);
+	sysfs_put(dir_sd);
+
 	return error;
 }
 EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
@@ -502,30 +464,31 @@
  */
 int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
 {
-	struct dentry * dir = kobj->dentry;
-	struct dentry * victim;
-	int res = -ENOENT;
+	struct sysfs_dirent *victim_sd = NULL;
+	struct dentry *victim = NULL;
+	int rc;
 
-	mutex_lock(&dir->d_inode->i_mutex);
-	victim = lookup_one_len(attr->name, dir, strlen(attr->name));
-	if (!IS_ERR(victim)) {
-		/* make sure dentry is really there */
-		if (victim->d_inode && 
-		    (victim->d_parent->d_inode == dir->d_inode)) {
-			victim->d_inode->i_mtime = CURRENT_TIME;
-			fsnotify_modify(victim);
-			res = 0;
-		} else
-			d_drop(victim);
-		
-		/**
-		 * Drop the reference acquired from lookup_one_len() above.
-		 */
-		dput(victim);
+	rc = -ENOENT;
+	victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
+	if (!victim_sd)
+		goto out;
+
+	victim = sysfs_get_dentry(victim_sd);
+	if (IS_ERR(victim)) {
+		rc = PTR_ERR(victim);
+		victim = NULL;
+		goto out;
 	}
-	mutex_unlock(&dir->d_inode->i_mutex);
 
-	return res;
+	mutex_lock(&victim->d_inode->i_mutex);
+	victim->d_inode->i_mtime = CURRENT_TIME;
+	fsnotify_modify(victim);
+	mutex_unlock(&victim->d_inode->i_mutex);
+	rc = 0;
+ out:
+	dput(victim);
+	sysfs_put(victim_sd);
+	return rc;
 }
 
 
@@ -538,30 +501,34 @@
  */
 int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
 {
-	struct dentry *dir = kobj->dentry;
-	struct dentry *victim;
+	struct sysfs_dirent *victim_sd = NULL;
+	struct dentry *victim = NULL;
 	struct inode * inode;
 	struct iattr newattrs;
-	int res = -ENOENT;
+	int rc;
 
-	mutex_lock(&dir->d_inode->i_mutex);
-	victim = lookup_one_len(attr->name, dir, strlen(attr->name));
-	if (!IS_ERR(victim)) {
-		if (victim->d_inode &&
-		    (victim->d_parent->d_inode == dir->d_inode)) {
-			inode = victim->d_inode;
-			mutex_lock(&inode->i_mutex);
-			newattrs.ia_mode = (mode & S_IALLUGO) |
-						(inode->i_mode & ~S_IALLUGO);
-			newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-			res = notify_change(victim, &newattrs);
-			mutex_unlock(&inode->i_mutex);
-		}
-		dput(victim);
+	rc = -ENOENT;
+	victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
+	if (!victim_sd)
+		goto out;
+
+	victim = sysfs_get_dentry(victim_sd);
+	if (IS_ERR(victim)) {
+		rc = PTR_ERR(victim);
+		victim = NULL;
+		goto out;
 	}
-	mutex_unlock(&dir->d_inode->i_mutex);
 
-	return res;
+	inode = victim->d_inode;
+	mutex_lock(&inode->i_mutex);
+	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+	rc = notify_change(victim, &newattrs);
+	mutex_unlock(&inode->i_mutex);
+ out:
+	dput(victim);
+	sysfs_put(victim_sd);
+	return rc;
 }
 EXPORT_SYMBOL_GPL(sysfs_chmod_file);
 
@@ -576,7 +543,7 @@
 
 void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
 {
-	sysfs_hash_and_remove(kobj->dentry, attr->name);
+	sysfs_hash_and_remove(kobj->sd, attr->name);
 }
 
 
@@ -589,12 +556,12 @@
 void sysfs_remove_file_from_group(struct kobject *kobj,
 		const struct attribute *attr, const char *group)
 {
-	struct dentry *dir;
+	struct sysfs_dirent *dir_sd;
 
-	dir = lookup_one_len(group, kobj->dentry, strlen(group));
-	if (!IS_ERR(dir)) {
-		sysfs_hash_and_remove(dir, attr->name);
-		dput(dir);
+	dir_sd = sysfs_get_dirent(kobj->sd, group);
+	if (dir_sd) {
+		sysfs_hash_and_remove(dir_sd, attr->name);
+		sysfs_put(dir_sd);
 	}
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 52eed2a..f318b73 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -18,26 +18,25 @@
 #include "sysfs.h"
 
 
-static void remove_files(struct dentry * dir, 
-			 const struct attribute_group * grp)
+static void remove_files(struct sysfs_dirent *dir_sd,
+			 const struct attribute_group *grp)
 {
 	struct attribute *const* attr;
 
 	for (attr = grp->attrs; *attr; attr++)
-		sysfs_hash_and_remove(dir,(*attr)->name);
+		sysfs_hash_and_remove(dir_sd, (*attr)->name);
 }
 
-static int create_files(struct dentry * dir,
-			const struct attribute_group * grp)
+static int create_files(struct sysfs_dirent *dir_sd,
+			const struct attribute_group *grp)
 {
 	struct attribute *const* attr;
 	int error = 0;
 
-	for (attr = grp->attrs; *attr && !error; attr++) {
-		error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
-	}
+	for (attr = grp->attrs; *attr && !error; attr++)
+		error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
 	if (error)
-		remove_files(dir,grp);
+		remove_files(dir_sd, grp);
 	return error;
 }
 
@@ -45,44 +44,44 @@
 int sysfs_create_group(struct kobject * kobj, 
 		       const struct attribute_group * grp)
 {
-	struct dentry * dir;
+	struct sysfs_dirent *sd;
 	int error;
 
-	BUG_ON(!kobj || !kobj->dentry);
+	BUG_ON(!kobj || !kobj->sd);
 
 	if (grp->name) {
-		error = sysfs_create_subdir(kobj,grp->name,&dir);
+		error = sysfs_create_subdir(kobj, grp->name, &sd);
 		if (error)
 			return error;
 	} else
-		dir = kobj->dentry;
-	dir = dget(dir);
-	if ((error = create_files(dir,grp))) {
+		sd = kobj->sd;
+	sysfs_get(sd);
+	error = create_files(sd, grp);
+	if (error) {
 		if (grp->name)
-			sysfs_remove_subdir(dir);
+			sysfs_remove_subdir(sd);
 	}
-	dput(dir);
+	sysfs_put(sd);
 	return error;
 }
 
 void sysfs_remove_group(struct kobject * kobj, 
 			const struct attribute_group * grp)
 {
-	struct dentry * dir;
+	struct sysfs_dirent *dir_sd = kobj->sd;
+	struct sysfs_dirent *sd;
 
 	if (grp->name) {
-		dir = lookup_one_len_kern(grp->name, kobj->dentry,
-				strlen(grp->name));
-		BUG_ON(IS_ERR(dir));
-	}
-	else
-		dir = dget(kobj->dentry);
+		sd = sysfs_get_dirent(dir_sd, grp->name);
+		BUG_ON(!sd);
+	} else
+		sd = sysfs_get(dir_sd);
 
-	remove_files(dir,grp);
+	remove_files(sd, grp);
 	if (grp->name)
-		sysfs_remove_subdir(dir);
-	/* release the ref. taken in this routine */
-	dput(dir);
+		sysfs_remove_subdir(sd);
+
+	sysfs_put(sd);
 }
 
 
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 4de5c6b..3756e15 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -13,6 +13,7 @@
 #include <linux/backing-dev.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
+#include <linux/sched.h>
 #include <asm/semaphore.h>
 #include "sysfs.h"
 
@@ -132,170 +133,94 @@
  */
 static struct lock_class_key sysfs_inode_imutex_key;
 
-struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
+void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 {
-	struct inode * inode = new_inode(sysfs_sb);
-	if (inode) {
-		inode->i_blocks = 0;
-		inode->i_mapping->a_ops = &sysfs_aops;
-		inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
-		inode->i_op = &sysfs_inode_operations;
-		lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
+	inode->i_blocks = 0;
+	inode->i_mapping->a_ops = &sysfs_aops;
+	inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+	inode->i_op = &sysfs_inode_operations;
+	inode->i_ino = sd->s_ino;
+	lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
 
-		if (sd->s_iattr) {
-			/* sysfs_dirent has non-default attributes
-			 * get them for the new inode from persistent copy
-			 * in sysfs_dirent
-			 */
-			set_inode_attr(inode, sd->s_iattr);
-		} else
-			set_default_inode_attr(inode, mode);
-	}
+	if (sd->s_iattr) {
+		/* sysfs_dirent has non-default attributes
+		 * get them for the new inode from persistent copy
+		 * in sysfs_dirent
+		 */
+		set_inode_attr(inode, sd->s_iattr);
+	} else
+		set_default_inode_attr(inode, sd->s_mode);
+}
+
+/**
+ *	sysfs_get_inode - get inode for sysfs_dirent
+ *	@sd: sysfs_dirent to allocate inode for
+ *
+ *	Get inode for @sd.  If such inode doesn't exist, a new inode
+ *	is allocated and basics are initialized.  New inode is
+ *	returned locked.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	Pointer to allocated inode on success, NULL on failure.
+ */
+struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
+{
+	struct inode *inode;
+
+	inode = iget_locked(sysfs_sb, sd->s_ino);
+	if (inode && (inode->i_state & I_NEW))
+		sysfs_init_inode(sd, inode);
+
 	return inode;
 }
 
-int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
-{
-	int error = 0;
-	struct inode * inode = NULL;
-	if (dentry) {
-		if (!dentry->d_inode) {
-			struct sysfs_dirent * sd = dentry->d_fsdata;
-			if ((inode = sysfs_new_inode(mode, sd))) {
-				if (dentry->d_parent && dentry->d_parent->d_inode) {
-					struct inode *p_inode = dentry->d_parent->d_inode;
-					p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
-				}
-				goto Proceed;
-			}
-			else 
-				error = -ENOMEM;
-		} else
-			error = -EEXIST;
-	} else 
-		error = -ENOENT;
-	goto Done;
-
- Proceed:
-	if (init)
-		error = init(inode);
-	if (!error) {
-		d_instantiate(dentry, inode);
-		if (S_ISDIR(mode))
-			dget(dentry);  /* pin only directory dentry in core */
-	} else
-		iput(inode);
- Done:
-	return error;
-}
-
-/*
- * Get the name for corresponding element represented by the given sysfs_dirent
+/**
+ *	sysfs_instantiate - instantiate dentry
+ *	@dentry: dentry to be instantiated
+ *	@inode: inode associated with @sd
+ *
+ *	Unlock @inode if locked and instantiate @dentry with @inode.
+ *
+ *	LOCKING:
+ *	None.
  */
-const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
+void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
 {
-	struct attribute * attr;
-	struct bin_attribute * bin_attr;
-	struct sysfs_symlink  * sl;
+	BUG_ON(!dentry || dentry->d_inode);
 
-	BUG_ON(!sd || !sd->s_element);
+	if (inode->i_state & I_NEW)
+		unlock_new_inode(inode);
 
-	switch (sd->s_type) {
-		case SYSFS_DIR:
-			/* Always have a dentry so use that */
-			return sd->s_dentry->d_name.name;
-
-		case SYSFS_KOBJ_ATTR:
-			attr = sd->s_element;
-			return attr->name;
-
-		case SYSFS_KOBJ_BIN_ATTR:
-			bin_attr = sd->s_element;
-			return bin_attr->attr.name;
-
-		case SYSFS_KOBJ_LINK:
-			sl = sd->s_element;
-			return sl->link_name;
-	}
-	return NULL;
+	d_instantiate(dentry, inode);
 }
 
-static inline void orphan_all_buffers(struct inode *node)
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
 {
-	struct sysfs_buffer_collection *set;
-	struct sysfs_buffer *buf;
+	struct sysfs_addrm_cxt acxt;
+	struct sysfs_dirent **pos, *sd;
 
-	mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
-	set = node->i_private;
-	if (set) {
-		list_for_each_entry(buf, &set->associates, associates) {
-			down(&buf->sem);
-			buf->orphaned = 1;
-			up(&buf->sem);
-		}
-	}
-	mutex_unlock(&node->i_mutex);
-}
-
-
-/*
- * Unhashes the dentry corresponding to given sysfs_dirent
- * Called with parent inode's i_mutex held.
- */
-void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
-{
-	struct dentry * dentry = sd->s_dentry;
-	struct inode *inode;
-
-	if (dentry) {
-		spin_lock(&dcache_lock);
-		spin_lock(&dentry->d_lock);
-		if (!(d_unhashed(dentry) && dentry->d_inode)) {
-			inode = dentry->d_inode;
-			spin_lock(&inode->i_lock);
-			__iget(inode);
-			spin_unlock(&inode->i_lock);
-			dget_locked(dentry);
-			__d_drop(dentry);
-			spin_unlock(&dentry->d_lock);
-			spin_unlock(&dcache_lock);
-			simple_unlink(parent->d_inode, dentry);
-			orphan_all_buffers(inode);
-			iput(inode);
-		} else {
-			spin_unlock(&dentry->d_lock);
-			spin_unlock(&dcache_lock);
-		}
-	}
-}
-
-int sysfs_hash_and_remove(struct dentry * dir, const char * name)
-{
-	struct sysfs_dirent * sd;
-	struct sysfs_dirent * parent_sd;
-	int found = 0;
-
-	if (!dir)
+	if (!dir_sd)
 		return -ENOENT;
 
-	if (dir->d_inode == NULL)
-		/* no inode means this hasn't been made visible yet */
-		return -ENOENT;
+	sysfs_addrm_start(&acxt, dir_sd);
 
-	parent_sd = dir->d_fsdata;
-	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
-	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
-		if (!sd->s_element)
+	for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
+		sd = *pos;
+
+		if (!sysfs_type(sd))
 			continue;
-		if (!strcmp(sysfs_get_name(sd), name)) {
-			list_del_init(&sd->s_sibling);
-			sysfs_drop_dentry(sd, dir);
-			sysfs_put(sd);
-			found = 1;
+		if (!strcmp(sd->s_name, name)) {
+			*pos = sd->s_sibling;
+			sd->s_sibling = NULL;
+			sysfs_remove_one(&acxt, sd);
 			break;
 		}
 	}
-	mutex_unlock(&dir->d_inode->i_mutex);
 
-	return found ? 0 : -ENOENT;
+	if (sysfs_addrm_finish(&acxt))
+		return 0;
+	return -ENOENT;
 }
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 23a48a3..402cc35 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -19,27 +19,18 @@
 struct super_block * sysfs_sb = NULL;
 struct kmem_cache *sysfs_dir_cachep;
 
-static void sysfs_clear_inode(struct inode *inode);
-
 static const struct super_operations sysfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= sysfs_delete_inode,
-	.clear_inode	= sysfs_clear_inode,
 };
 
-static struct sysfs_dirent sysfs_root = {
-	.s_sibling	= LIST_HEAD_INIT(sysfs_root.s_sibling),
-	.s_children	= LIST_HEAD_INIT(sysfs_root.s_children),
-	.s_element	= NULL,
-	.s_type		= SYSFS_ROOT,
-	.s_iattr	= NULL,
+struct sysfs_dirent sysfs_root = {
+	.s_count	= ATOMIC_INIT(1),
+	.s_flags	= SYSFS_ROOT,
+	.s_mode		= S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+	.s_ino		= 1,
 };
 
-static void sysfs_clear_inode(struct inode *inode)
-{
-	kfree(inode->i_private);
-}
-
 static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode;
@@ -52,24 +43,26 @@
 	sb->s_time_gran = 1;
 	sysfs_sb = sb;
 
-	inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
-				 &sysfs_root);
-	if (inode) {
-		inode->i_op = &sysfs_dir_inode_operations;
-		inode->i_fop = &sysfs_dir_operations;
-		/* directory inodes start off with i_nlink == 2 (for "." entry) */
-		inc_nlink(inode);
-	} else {
+	inode = new_inode(sysfs_sb);
+	if (!inode) {
 		pr_debug("sysfs: could not get root inode\n");
 		return -ENOMEM;
 	}
 
+	sysfs_init_inode(&sysfs_root, inode);
+
+	inode->i_op = &sysfs_dir_inode_operations;
+	inode->i_fop = &sysfs_dir_operations;
+	/* directory inodes start off with i_nlink == 2 (for "." entry) */
+	inc_nlink(inode);
+
 	root = d_alloc_root(inode);
 	if (!root) {
 		pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
 		iput(inode);
 		return -ENOMEM;
 	}
+	sysfs_root.s_dentry = root;
 	root->d_fsdata = &sysfs_root;
 	sb->s_root = root;
 	return 0;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 7b9c5bf..2f86e04 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -11,71 +11,39 @@
 
 #include "sysfs.h"
 
-static int object_depth(struct kobject * kobj)
+static int object_depth(struct sysfs_dirent *sd)
 {
-	struct kobject * p = kobj;
 	int depth = 0;
-	do { depth++; } while ((p = p->parent));
+
+	for (; sd->s_parent; sd = sd->s_parent)
+		depth++;
+
 	return depth;
 }
 
-static int object_path_length(struct kobject * kobj)
+static int object_path_length(struct sysfs_dirent * sd)
 {
-	struct kobject * p = kobj;
 	int length = 1;
-	do {
-		length += strlen(kobject_name(p)) + 1;
-		p = p->parent;
-	} while (p);
+
+	for (; sd->s_parent; sd = sd->s_parent)
+		length += strlen(sd->s_name) + 1;
+
 	return length;
 }
 
-static void fill_object_path(struct kobject * kobj, char * buffer, int length)
+static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length)
 {
-	struct kobject * p;
-
 	--length;
-	for (p = kobj; p; p = p->parent) {
-		int cur = strlen(kobject_name(p));
+	for (; sd->s_parent; sd = sd->s_parent) {
+		int cur = strlen(sd->s_name);
 
 		/* back up enough to print this bus id with '/' */
 		length -= cur;
-		strncpy(buffer + length,kobject_name(p),cur);
+		strncpy(buffer + length, sd->s_name, cur);
 		*(buffer + --length) = '/';
 	}
 }
 
-static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
-{
-	struct sysfs_dirent * parent_sd = parent->d_fsdata;
-	struct sysfs_symlink * sl;
-	int error = 0;
-
-	error = -ENOMEM;
-	sl = kmalloc(sizeof(*sl), GFP_KERNEL);
-	if (!sl)
-		goto exit1;
-
-	sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
-	if (!sl->link_name)
-		goto exit2;
-
-	strcpy(sl->link_name, name);
-	sl->target_kobj = kobject_get(target);
-
-	error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO,
-				SYSFS_KOBJ_LINK);
-	if (!error)
-		return 0;
-
-	kobject_put(target);
-	kfree(sl->link_name);
-exit2:
-	kfree(sl);
-exit1:
-	return error;
-}
-
 /**
  *	sysfs_create_link - create symlink between two objects.
  *	@kobj:	object whose directory we're creating the link in.
@@ -84,24 +52,57 @@
  */
 int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
 {
-	struct dentry *dentry = NULL;
-	int error = -EEXIST;
+	struct sysfs_dirent *parent_sd = NULL;
+	struct sysfs_dirent *target_sd = NULL;
+	struct sysfs_dirent *sd = NULL;
+	struct sysfs_addrm_cxt acxt;
+	int error;
 
 	BUG_ON(!name);
 
 	if (!kobj) {
 		if (sysfs_mount && sysfs_mount->mnt_sb)
-			dentry = sysfs_mount->mnt_sb->s_root;
+			parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
 	} else
-		dentry = kobj->dentry;
+		parent_sd = kobj->sd;
 
-	if (!dentry)
-		return -EFAULT;
+	error = -EFAULT;
+	if (!parent_sd)
+		goto out_put;
 
-	mutex_lock(&dentry->d_inode->i_mutex);
-	if (!sysfs_dirent_exist(dentry->d_fsdata, name))
-		error = sysfs_add_link(dentry, name, target);
-	mutex_unlock(&dentry->d_inode->i_mutex);
+	/* target->sd can go away beneath us but is protected with
+	 * sysfs_assoc_lock.  Fetch target_sd from it.
+	 */
+	spin_lock(&sysfs_assoc_lock);
+	if (target->sd)
+		target_sd = sysfs_get(target->sd);
+	spin_unlock(&sysfs_assoc_lock);
+
+	error = -ENOENT;
+	if (!target_sd)
+		goto out_put;
+
+	error = -ENOMEM;
+	sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
+	if (!sd)
+		goto out_put;
+	sd->s_elem.symlink.target_sd = target_sd;
+
+	sysfs_addrm_start(&acxt, parent_sd);
+
+	if (!sysfs_find_dirent(parent_sd, name)) {
+		sysfs_add_one(&acxt, sd);
+		sysfs_link_sibling(sd);
+	}
+
+	if (sysfs_addrm_finish(&acxt))
+		return 0;
+
+	error = -EEXIST;
+	/* fall through */
+ out_put:
+	sysfs_put(target_sd);
+	sysfs_put(sd);
 	return error;
 }
 
@@ -114,17 +115,17 @@
 
 void sysfs_remove_link(struct kobject * kobj, const char * name)
 {
-	sysfs_hash_and_remove(kobj->dentry,name);
+	sysfs_hash_and_remove(kobj->sd, name);
 }
 
-static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
-				 char *path)
+static int sysfs_get_target_path(struct sysfs_dirent * parent_sd,
+				 struct sysfs_dirent * target_sd, char *path)
 {
 	char * s;
 	int depth, size;
 
-	depth = object_depth(kobj);
-	size = object_path_length(target) + depth * 3 - 1;
+	depth = object_depth(parent_sd);
+	size = object_path_length(target_sd) + depth * 3 - 1;
 	if (size > PATH_MAX)
 		return -ENAMETOOLONG;
 
@@ -133,7 +134,7 @@
 	for (s = path; depth--; s += 3)
 		strcpy(s,"../");
 
-	fill_object_path(target, path, size);
+	fill_object_path(target_sd, path, size);
 	pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
 
 	return 0;
@@ -141,27 +142,16 @@
 
 static int sysfs_getlink(struct dentry *dentry, char * path)
 {
-	struct kobject *kobj, *target_kobj;
-	int error = 0;
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct sysfs_dirent *parent_sd = sd->s_parent;
+	struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
+	int error;
 
-	kobj = sysfs_get_kobject(dentry->d_parent);
-	if (!kobj)
-		return -EINVAL;
+	mutex_lock(&sysfs_mutex);
+	error = sysfs_get_target_path(parent_sd, target_sd, path);
+	mutex_unlock(&sysfs_mutex);
 
-	target_kobj = sysfs_get_kobject(dentry);
-	if (!target_kobj) {
-		kobject_put(kobj);
-		return -EINVAL;
-	}
-
-	down_read(&sysfs_rename_sem);
-	error = sysfs_get_target_path(kobj, target_kobj, path);
-	up_read(&sysfs_rename_sem);
-	
-	kobject_put(kobj);
-	kobject_put(target_kobj);
 	return error;
-
 }
 
 static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a77c57e..6a37f23 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -1,38 +1,101 @@
+struct sysfs_elem_dir {
+	struct kobject		* kobj;
+};
+
+struct sysfs_elem_symlink {
+	struct sysfs_dirent	* target_sd;
+};
+
+struct sysfs_elem_attr {
+	struct attribute	* attr;
+};
+
+struct sysfs_elem_bin_attr {
+	struct bin_attribute	* bin_attr;
+};
+
+/*
+ * As long as s_count reference is held, the sysfs_dirent itself is
+ * accessible.  Dereferencing s_elem or any other outer entity
+ * requires s_active reference.
+ */
 struct sysfs_dirent {
 	atomic_t		s_count;
-	struct list_head	s_sibling;
-	struct list_head	s_children;
-	void 			* s_element;
-	int			s_type;
+	atomic_t		s_active;
+	struct sysfs_dirent	* s_parent;
+	struct sysfs_dirent	* s_sibling;
+	struct sysfs_dirent	* s_children;
+	const char		* s_name;
+
+	union {
+		struct sysfs_elem_dir		dir;
+		struct sysfs_elem_symlink	symlink;
+		struct sysfs_elem_attr		attr;
+		struct sysfs_elem_bin_attr	bin_attr;
+	}			s_elem;
+
+	unsigned int		s_flags;
 	umode_t			s_mode;
+	ino_t			s_ino;
 	struct dentry		* s_dentry;
 	struct iattr		* s_iattr;
 	atomic_t		s_event;
 };
 
+#define SD_DEACTIVATED_BIAS	INT_MIN
+
+struct sysfs_addrm_cxt {
+	struct sysfs_dirent	*parent_sd;
+	struct inode		*parent_inode;
+	struct sysfs_dirent	*removed;
+	int			cnt;
+};
+
 extern struct vfsmount * sysfs_mount;
+extern struct sysfs_dirent sysfs_root;
 extern struct kmem_cache *sysfs_dir_cachep;
 
+extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
+extern void sysfs_link_sibling(struct sysfs_dirent *sd);
+extern void sysfs_unlink_sibling(struct sysfs_dirent *sd);
+extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
+extern void sysfs_put_active(struct sysfs_dirent *sd);
+extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
+extern void sysfs_put_active_two(struct sysfs_dirent *sd);
+extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+			      struct sysfs_dirent *parent_sd);
+extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt,
+			  struct sysfs_dirent *sd);
+extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
+			     struct sysfs_dirent *sd);
+extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
+
 extern void sysfs_delete_inode(struct inode *inode);
-extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
-extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
+extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
+extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
+extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
 
-extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
-extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
-				umode_t, int);
+extern void release_sysfs_dirent(struct sysfs_dirent * sd);
+extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+					      const unsigned char *name);
+extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+					     const unsigned char *name);
+extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
+					     int type);
 
-extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
-extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);
+extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
+			  const struct attribute *attr, int type);
+extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
 extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
 
-extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
-extern void sysfs_remove_subdir(struct dentry *);
+extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
+			       struct sysfs_dirent **p_sd);
+extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
 
-extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
-extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
 extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
 
-extern struct rw_semaphore sysfs_rename_sem;
+extern spinlock_t sysfs_assoc_lock;
+extern struct mutex sysfs_mutex;
 extern struct super_block * sysfs_sb;
 extern const struct file_operations sysfs_dir_operations;
 extern const struct file_operations sysfs_file_operations;
@@ -40,73 +103,9 @@
 extern const struct inode_operations sysfs_dir_inode_operations;
 extern const struct inode_operations sysfs_symlink_inode_operations;
 
-struct sysfs_symlink {
-	char * link_name;
-	struct kobject * target_kobj;
-};
-
-struct sysfs_buffer {
-	struct list_head		associates;
-	size_t				count;
-	loff_t				pos;
-	char				* page;
-	struct sysfs_ops		* ops;
-	struct semaphore		sem;
-	int				orphaned;
-	int				needs_read_fill;
-	int				event;
-};
-
-struct sysfs_buffer_collection {
-	struct list_head	associates;
-};
-
-static inline struct kobject * to_kobj(struct dentry * dentry)
+static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
 {
-	struct sysfs_dirent * sd = dentry->d_fsdata;
-	return ((struct kobject *) sd->s_element);
-}
-
-static inline struct attribute * to_attr(struct dentry * dentry)
-{
-	struct sysfs_dirent * sd = dentry->d_fsdata;
-	return ((struct attribute *) sd->s_element);
-}
-
-static inline struct bin_attribute * to_bin_attr(struct dentry * dentry)
-{
-	struct sysfs_dirent * sd = dentry->d_fsdata;
-	return ((struct bin_attribute *) sd->s_element);
-}
-
-static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
-{
-	struct kobject * kobj = NULL;
-
-	spin_lock(&dcache_lock);
-	if (!d_unhashed(dentry)) {
-		struct sysfs_dirent * sd = dentry->d_fsdata;
-		if (sd->s_type & SYSFS_KOBJ_LINK) {
-			struct sysfs_symlink * sl = sd->s_element;
-			kobj = kobject_get(sl->target_kobj);
-		} else
-			kobj = kobject_get(sd->s_element);
-	}
-	spin_unlock(&dcache_lock);
-
-	return kobj;
-}
-
-static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
-{
-	if (sd->s_type & SYSFS_KOBJ_LINK) {
-		struct sysfs_symlink * sl = sd->s_element;
-		kfree(sl->link_name);
-		kobject_put(sl->target_kobj);
-		kfree(sl);
-	}
-	kfree(sd->s_iattr);
-	kmem_cache_free(sysfs_dir_cachep, sd);
+	return sd->s_flags & SYSFS_TYPE_MASK;
 }
 
 static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
@@ -120,7 +119,7 @@
 
 static inline void sysfs_put(struct sysfs_dirent * sd)
 {
-	if (atomic_dec_and_test(&sd->s_count))
+	if (sd && atomic_dec_and_test(&sd->s_count))
 		release_sysfs_dirent(sd);
 }
 
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 0732ddb..589be21 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -27,7 +27,7 @@
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= sysv_sync_file,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations sysv_file_inode_operations = {
diff --git a/fs/udf/crc.c b/fs/udf/crc.c
index 1b82a4a..ef2bfaa 100644
--- a/fs/udf/crc.c
+++ b/fs/udf/crc.c
@@ -106,8 +106,8 @@
 {
 	unsigned short x;
 
-	x = udf_crc16(bytes, sizeof bytes);
-	printf("udf_crc16: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
+	x = udf_crc(bytes, sizeof bytes);
+	printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
 
 	return 0;
 }
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 40d5047..df070be 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -36,6 +36,7 @@
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
+#include <linux/aio.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -260,7 +261,7 @@
 	.aio_write		= udf_file_aio_write,
 	.release		= udf_release_file,
 	.fsync			= udf_fsync_file,
-	.sendfile		= generic_file_sendfile,
+	.splice_read		= generic_file_splice_read,
 };
 
 const struct inode_operations udf_file_inode_operations = {
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 8206983..10f3188 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -50,7 +50,7 @@
 		else
 			UDF_SB_LVIDIU(sb)->numFiles =
 				cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) - 1);
-		
+
 		mark_buffer_dirty(sbi->s_lvidbh);
 	}
 	mutex_unlock(&sbi->s_alloc_mutex);
@@ -136,6 +136,13 @@
 		UDF_I_EFE(inode) = 0;
 		UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
 	}
+	if (!UDF_I_DATA(inode))
+	{
+		iput(inode);
+		*err = -ENOMEM;
+		mutex_unlock(&sbi->s_alloc_mutex);
+		return NULL;
+	}
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
 	else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index c846155..5b82e48 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -49,6 +49,7 @@
 static mode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
+static int udf_alloc_i_data(struct inode *inode, size_t size);
 static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
 	long *, int *);
 static int8_t udf_insert_aext(struct inode *, struct extent_position,
@@ -100,14 +101,23 @@
 	clear_inode(inode);
 }
 
+/*
+ * If we are going to release inode from memory, we discard preallocation and
+ * truncate last inode extent to proper length. We could use drop_inode() but
+ * it's called under inode_lock and thus we cannot mark inode dirty there.  We
+ * use clear_inode() but we have to make sure to write inode as it's not written
+ * automatically.
+ */
 void udf_clear_inode(struct inode *inode)
 {
 	if (!(inode->i_sb->s_flags & MS_RDONLY)) {
 		lock_kernel();
+		/* Discard preallocation for directories, symlinks, etc. */
 		udf_discard_prealloc(inode);
+		udf_truncate_tail_extent(inode);
 		unlock_kernel();
+		write_inode_now(inode, 1);
 	}
-
 	kfree(UDF_I_DATA(inode));
 	UDF_I_DATA(inode) = NULL;
 }
@@ -460,8 +470,8 @@
 	kernel_long_ad laarr[EXTENT_MERGE_SIZE];
 	struct extent_position prev_epos, cur_epos, next_epos;
 	int count = 0, startnum = 0, endnum = 0;
-	uint32_t elen = 0;
-	kernel_lb_addr eloc;
+	uint32_t elen = 0, tmpelen;
+	kernel_lb_addr eloc, tmpeloc;
 	int c = 1;
 	loff_t lbcount = 0, b_off = 0;
 	uint32_t newblocknum, newblock;
@@ -520,8 +530,12 @@
 
 	b_off -= lbcount;
 	offset = b_off >> inode->i_sb->s_blocksize_bits;
-	/* Move into indirect extent if we are at a pointer to it */
-	udf_next_aext(inode, &prev_epos, &eloc, &elen, 0);
+	/*
+	 * Move prev_epos and cur_epos into indirect extent if we are at
+	 * the pointer to it
+	 */
+	udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0);
+	udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0);
 
 	/* if the extent is allocated and recorded, return the block
        if the extent is not a multiple of the blocksize, round up */
@@ -721,7 +735,7 @@
 			(*c) ++;
 			(*endnum) ++;
 		}
-		
+
 		laarr[curr].extLocation.logicalBlockNum = newblocknum;
 		if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
 			laarr[curr].extLocation.partitionReferenceNum =
@@ -823,7 +837,7 @@
 				{
 					numalloc -= elen;
 					if (*endnum > (i+1))
-						memmove(&laarr[i], &laarr[i+1], 
+						memmove(&laarr[i], &laarr[i+1],
 							sizeof(long_ad) * (*endnum - (i+1)));
 					i --;
 					(*endnum) --;
@@ -1011,7 +1025,7 @@
 	{
 		block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block);
 		udf_truncate_extents(inode);
-	}	
+	}
 
 	inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
 	if (IS_SYNC(inode))
@@ -1074,10 +1088,10 @@
 			{
 				kernel_lb_addr loc;
 				ie = (struct indirectEntry *)ibh->b_data;
-	
+
 				loc = lelb_to_cpu(ie->indirectICB.extLocation);
-	
-				if (ie->indirectICB.extLength && 
+
+				if (ie->indirectICB.extLength &&
 					(nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident)))
 				{
 					if (ident == TAG_IDENT_FE ||
@@ -1143,14 +1157,22 @@
 	{
 		UDF_I_EFE(inode) = 1;
 		UDF_I_USE(inode) = 0;
-		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)))
+		{
+			make_bad_inode(inode);
+			return;
+		}
 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
 	}
 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
 	{
 		UDF_I_EFE(inode) = 0;
 		UDF_I_USE(inode) = 0;
-		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct fileEntry)))
+		{
+			make_bad_inode(inode);
+			return;
+		}
 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
 	}
 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
@@ -1160,7 +1182,11 @@
 		UDF_I_LENALLOC(inode) =
 			le32_to_cpu(
 				((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
-		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
+		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)))
+		{
+			make_bad_inode(inode);
+			return;
+		}
 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
 		return;
 	}
@@ -1178,7 +1204,7 @@
 	inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
 	if (!inode->i_nlink)
 		inode->i_nlink = 1;
-	
+
 	inode->i_size = le64_to_cpu(fe->informationLength);
 	UDF_I_LENEXTENTS(inode) = inode->i_size;
 
@@ -1230,7 +1256,7 @@
 	}
 	else
 	{
-		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << 
+		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
 			(inode->i_sb->s_blocksize_bits - 9);
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
@@ -1361,6 +1387,20 @@
 	}
 }
 
+static int udf_alloc_i_data(struct inode *inode, size_t size)
+{
+	UDF_I_DATA(inode) = kmalloc(size, GFP_KERNEL);
+
+	if (!UDF_I_DATA(inode))
+	{
+		printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) no free memory\n",
+		       inode->i_ino);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
 static mode_t
 udf_convert_permissions(struct fileEntry *fe)
 {
@@ -2059,7 +2099,7 @@
 			mark_buffer_dirty_inode(oepos.bh, inode);
 		}
 	}
-	
+
 	brelse(epos.bh);
 	brelse(oepos.bh);
 	return (elen >> 30);
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 91df492..51fe307 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -30,6 +30,7 @@
 #include <linux/quotaops.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/sched.h>
 
 static inline int udf_match(int len1, const char *name1, int len2, const char *name2)
 {
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 3a743d8..d6a504f 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1351,12 +1351,12 @@
 
 	for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
 	{
-		switch UDF_SB_PARTTYPE(sb, i)
+		switch (UDF_SB_PARTTYPE(sb, i))
 		{
 			case UDF_VIRTUAL_MAP15:
 			case UDF_VIRTUAL_MAP20:
 			{
-				kernel_lb_addr ino;
+				kernel_lb_addr uninitialized_var(ino);
 
 				if (!UDF_SB_LASTBLOCK(sb))
 				{
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 77975ae..60d2776 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -61,7 +61,11 @@
 	}
 }
 
-void udf_discard_prealloc(struct inode * inode)
+/*
+ * Truncate the last extent to match i_size. This function assumes
+ * that preallocation extent is already truncated.
+ */
+void udf_truncate_tail_extent(struct inode *inode)
 {
 	struct extent_position epos = { NULL, 0, {0, 0}};
 	kernel_lb_addr eloc;
@@ -71,6 +75,62 @@
 	int adsize;
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
+	    inode->i_size == UDF_I_LENEXTENTS(inode))
+		return;
+	/* Are we going to delete the file anyway? */
+	if (inode->i_nlink == 0)
+		return;
+
+	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
+		adsize = sizeof(short_ad);
+	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
+		adsize = sizeof(long_ad);
+	else
+		BUG();
+
+	/* Find the last extent in the file */
+	while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
+	{
+		etype = netype;
+		lbcount += elen;
+		if (lbcount > inode->i_size) {
+			if (lbcount - inode->i_size >= inode->i_sb->s_blocksize)
+				printk(KERN_WARNING
+				       "udf_truncate_tail_extent(): Too long "
+				       "extent after EOF in inode %u: i_size: "
+				       "%Ld lbcount: %Ld extent %u+%u\n",
+				       (unsigned)inode->i_ino,
+				       (long long)inode->i_size,
+				       (long long)lbcount,
+				       (unsigned)eloc.logicalBlockNum,
+				       (unsigned)elen);
+			nelen = elen - (lbcount - inode->i_size);
+			epos.offset -= adsize;
+			extent_trunc(inode, &epos, eloc, etype, elen, nelen);
+			epos.offset += adsize;
+			if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1)
+				printk(KERN_ERR "udf_truncate_tail_extent(): "
+				       "Extent after EOF in inode %u.\n",
+				       (unsigned)inode->i_ino);
+			break;
+		}
+	}
+	/* This inode entry is in-memory only and thus we don't have to mark
+	 * the inode dirty */
+	UDF_I_LENEXTENTS(inode) = inode->i_size;
+	brelse(epos.bh);
+}
+
+void udf_discard_prealloc(struct inode *inode)
+{
+	struct extent_position epos = { NULL, 0, {0, 0}};
+	kernel_lb_addr eloc;
+	uint32_t elen;
+	uint64_t lbcount = 0;
+	int8_t etype = -1, netype;
+	int adsize;
+
+	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
 		inode->i_size == UDF_I_LENEXTENTS(inode))
 		return;
 
@@ -84,31 +144,18 @@
 	epos.block = UDF_I_LOCATION(inode);
 
 	/* Find the last extent in the file */
-	while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
-	{
+	while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
 		etype = netype;
 		lbcount += elen;
-		if (lbcount > inode->i_size && lbcount - elen < inode->i_size)
-		{
-			WARN_ON(lbcount - inode->i_size >= inode->i_sb->s_blocksize);
-			nelen = elen - (lbcount - inode->i_size);
-			epos.offset -= adsize;
-			extent_trunc(inode, &epos, eloc, etype, elen, nelen);
-			epos.offset += adsize;
-			lbcount = inode->i_size;
-		}
 	}
 	if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
 		epos.offset -= adsize;
 		lbcount -= elen;
 		extent_trunc(inode, &epos, eloc, etype, elen, 0);
-		if (!epos.bh)
-		{
+		if (!epos.bh) {
 			UDF_I_LENALLOC(inode) = epos.offset - udf_file_entry_alloc_offset(inode);
 			mark_inode_dirty(inode);
-		}
-		else
-		{
+		} else {
 			struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
 			aed->lengthAllocDescs = cpu_to_le32(epos.offset - sizeof(struct allocExtDesc));
 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
@@ -118,9 +165,9 @@
 			mark_buffer_dirty_inode(epos.bh, inode);
 		}
 	}
+	/* This inode entry is in-memory only and thus we don't have to mark
+	 * the inode dirty */
 	UDF_I_LENEXTENTS(inode) = lbcount;
-
-	WARN_ON(lbcount != inode->i_size);
 	brelse(epos.bh);
 }
 
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 67ded28..f581f2f 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -146,6 +146,7 @@
 extern struct inode * udf_new_inode (struct inode *, int, int *);
 
 /* truncate.c */
+extern void udf_truncate_tail_extent(struct inode *);
 extern void udf_discard_prealloc(struct inode *);
 extern void udf_truncate_extents(struct inode *);
 
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 1e09632..6705d74 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -60,5 +60,5 @@
 	.mmap		= generic_file_mmap,
 	.open           = generic_file_open,
 	.fsync		= ufs_sync_file,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 22ff6ed..2b30116 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -87,6 +87,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
+#include <linux/log2.h>
 
 #include "swab.h"
 #include "util.h"
@@ -854,7 +855,7 @@
 	uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
 	uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
 
-	if (uspi->s_fsize & (uspi->s_fsize - 1)) {
+	if (!is_power_of_2(uspi->s_fsize)) {
 		printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2\n",
 			uspi->s_fsize);
 			goto failed;
@@ -869,7 +870,7 @@
 			uspi->s_fsize);
 		goto failed;
 	}
-	if (uspi->s_bsize & (uspi->s_bsize - 1)) {
+	if (!is_power_of_2(uspi->s_bsize)) {
 		printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2\n",
 			uspi->s_bsize);
 		goto failed;
diff --git a/fs/utimes.c b/fs/utimes.c
index 480f7c8..682eb63 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -106,9 +106,16 @@
                 if (IS_IMMUTABLE(inode))
                         goto dput_and_out;
 
-		if (current->fsuid != inode->i_uid &&
-		    (error = vfs_permission(&nd, MAY_WRITE)) != 0)
-			goto dput_and_out;
+		if (!is_owner_or_cap(inode)) {
+			if (f) {
+				if (!(f->f_mode & FMODE_WRITE))
+					goto dput_and_out;
+			} else {
+				error = vfs_permission(&nd, MAY_WRITE);
+				if (error)
+					goto dput_and_out;
+			}
+		}
 	}
 	mutex_lock(&inode->i_mutex);
 	error = notify_change(dentry, &newattrs);
diff --git a/fs/xattr.c b/fs/xattr.c
index 4523aca..a44fd92 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -60,8 +60,7 @@
 		if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
 			return -EPERM;
 		if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
-		    (mask & MAY_WRITE) && (current->fsuid != inode->i_uid) &&
-		    !capable(CAP_FOWNER))
+		    (mask & MAY_WRITE) && !is_owner_or_cap(inode))
 			return -EPERM;
 	}
 
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
index b49989b..e7a9a83 100644
--- a/fs/xfs/Makefile-linux-2.6
+++ b/fs/xfs/Makefile-linux-2.6
@@ -64,6 +64,7 @@
 				   xfs_dir2_sf.o \
 				   xfs_error.o \
 				   xfs_extfree_item.o \
+				   xfs_filestream.o \
 				   xfs_fsops.o \
 				   xfs_ialloc.o \
 				   xfs_ialloc_btree.o \
@@ -77,6 +78,7 @@
 				   xfs_log.o \
 				   xfs_log_recover.o \
 				   xfs_mount.o \
+				   xfs_mru_cache.o \
 				   xfs_rename.o \
 				   xfs_trans.o \
 				   xfs_trans_ail.o \
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index 9ebabdf..4b6470c 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -100,25 +100,6 @@
 extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
 extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
 
-/*
- * Low memory cache shrinkers
- */
-
-typedef struct shrinker *kmem_shaker_t;
-typedef int (*kmem_shake_func_t)(int, gfp_t);
-
-static inline kmem_shaker_t
-kmem_shake_register(kmem_shake_func_t sfunc)
-{
-	return set_shrinker(DEFAULT_SEEKS, sfunc);
-}
-
-static inline void
-kmem_shake_deregister(kmem_shaker_t shrinker)
-{
-	remove_shrinker(shrinker);
-}
-
 static inline int
 kmem_shake_allow(gfp_t gfp_mask)
 {
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 4475588..fd4105d 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -108,14 +108,19 @@
 
 /*
  * Schedule IO completion handling on a xfsdatad if this was
- * the final hold on this ioend.
+ * the final hold on this ioend. If we are asked to wait,
+ * flush the workqueue.
  */
 STATIC void
 xfs_finish_ioend(
-	xfs_ioend_t		*ioend)
+	xfs_ioend_t	*ioend,
+	int		wait)
 {
-	if (atomic_dec_and_test(&ioend->io_remaining))
+	if (atomic_dec_and_test(&ioend->io_remaining)) {
 		queue_work(xfsdatad_workqueue, &ioend->io_work);
+		if (wait)
+			flush_workqueue(xfsdatad_workqueue);
+	}
 }
 
 /*
@@ -156,6 +161,8 @@
 	xfs_fsize_t		bsize;
 
 	ip = xfs_vtoi(ioend->io_vnode);
+	if (!ip)
+		return;
 
 	ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
 	ASSERT(ioend->io_type != IOMAP_READ);
@@ -334,7 +341,7 @@
 	bio->bi_end_io = NULL;
 	bio_put(bio);
 
-	xfs_finish_ioend(ioend);
+	xfs_finish_ioend(ioend, 0);
 	return 0;
 }
 
@@ -470,7 +477,7 @@
 		}
 		if (bio)
 			xfs_submit_ioend_bio(ioend, bio);
-		xfs_finish_ioend(ioend);
+		xfs_finish_ioend(ioend, 0);
 	} while ((ioend = next) != NULL);
 }
 
@@ -701,7 +708,7 @@
 			else if (buffer_delay(bh))
 				acceptable = (type == IOMAP_DELAY);
 			else if (buffer_dirty(bh) && buffer_mapped(bh))
-				acceptable = (type == 0);
+				acceptable = (type == IOMAP_NEW);
 			else
 				break;
 		} while ((bh = bh->b_this_page) != head);
@@ -810,7 +817,7 @@
 			page_dirty--;
 			count++;
 		} else {
-			type = 0;
+			type = IOMAP_NEW;
 			if (buffer_mapped(bh) && all_bh && startio) {
 				lock_buffer(bh);
 				xfs_add_to_ioend(inode, bh, offset,
@@ -968,8 +975,8 @@
 
 	bh = head = page_buffers(page);
 	offset = page_offset(page);
-	flags = -1;
-	type = IOMAP_READ;
+	flags = BMAPI_READ;
+	type = IOMAP_NEW;
 
 	/* TODO: cleanup count and page_dirty */
 
@@ -999,14 +1006,16 @@
 		 *
 		 * Third case, an unmapped buffer was found, and we are
 		 * in a path where we need to write the whole page out.
- 		 */
+		 */
 		if (buffer_unwritten(bh) || buffer_delay(bh) ||
 		    ((buffer_uptodate(bh) || PageUptodate(page)) &&
 		     !buffer_mapped(bh) && (unmapped || startio))) {
-		     	/*
+			int new_ioend = 0;
+
+			/*
 			 * Make sure we don't use a read-only iomap
 			 */
-		     	if (flags == BMAPI_READ)
+			if (flags == BMAPI_READ)
 				iomap_valid = 0;
 
 			if (buffer_unwritten(bh)) {
@@ -1021,6 +1030,15 @@
 			}
 
 			if (!iomap_valid) {
+				/*
+				 * if we didn't have a valid mapping then we
+				 * need to ensure that we put the new mapping
+				 * in a new ioend structure. This needs to be
+				 * done to ensure that the ioends correctly
+				 * reflect the block mappings at io completion
+				 * for unwritten extent conversion.
+				 */
+				new_ioend = 1;
 				if (type == IOMAP_NEW) {
 					size = xfs_probe_cluster(inode,
 							page, bh, head, 0);
@@ -1040,7 +1058,7 @@
 				if (startio) {
 					xfs_add_to_ioend(inode, bh, offset,
 							type, &ioend,
-							!iomap_valid);
+							new_ioend);
 				} else {
 					set_buffer_dirty(bh);
 					unlock_buffer(bh);
@@ -1055,7 +1073,7 @@
 			 * That means it must already have extents allocated
 			 * underneath it. Map the extent by reading it.
 			 */
-			if (!iomap_valid || type != IOMAP_READ) {
+			if (!iomap_valid || flags != BMAPI_READ) {
 				flags = BMAPI_READ;
 				size = xfs_probe_cluster(inode, page, bh,
 								head, 1);
@@ -1066,7 +1084,15 @@
 				iomap_valid = xfs_iomap_valid(&iomap, offset);
 			}
 
-			type = IOMAP_READ;
+			/*
+			 * We set the type to IOMAP_NEW in case we are doing a
+			 * small write at EOF that is extending the file but
+			 * without needing an allocation. We need to update the
+			 * file size on I/O completion in this case so it is
+			 * the same case as having just allocated a new extent
+			 * that we are writing into for the first time.
+			 */
+			type = IOMAP_NEW;
 			if (!test_and_set_bit(BH_Lock, &bh->b_state)) {
 				ASSERT(buffer_mapped(bh));
 				if (iomap_valid)
@@ -1408,6 +1434,13 @@
 	 * This is not necessary for synchronous direct I/O, but we do
 	 * it anyway to keep the code uniform and simpler.
 	 *
+	 * Well, if only it were that simple. Because synchronous direct I/O
+	 * requires extent conversion to occur *before* we return to userspace,
+	 * we have to wait for extent conversion to complete. Look at the
+	 * iocb that has been passed to us to determine if this is AIO or
+	 * not. If it is synchronous, tell xfs_finish_ioend() to kick the
+	 * workqueue and wait for it to complete.
+	 *
 	 * The core direct I/O code might be changed to always call the
 	 * completion handler in the future, in which case all this can
 	 * go away.
@@ -1415,9 +1448,9 @@
 	ioend->io_offset = offset;
 	ioend->io_size = size;
 	if (ioend->io_type == IOMAP_READ) {
-		xfs_finish_ioend(ioend);
+		xfs_finish_ioend(ioend, 0);
 	} else if (private && size > 0) {
-		xfs_finish_ioend(ioend);
+		xfs_finish_ioend(ioend, is_sync_kiocb(iocb));
 	} else {
 		/*
 		 * A direct I/O write ioend starts it's life in unwritten
@@ -1426,7 +1459,7 @@
 		 * handler.
 		 */
 		INIT_WORK(&ioend->io_work, xfs_end_bio_written);
-		xfs_finish_ioend(ioend);
+		xfs_finish_ioend(ioend, 0);
 	}
 
 	/*
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index fe4f66a..b0f0e58 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -35,10 +35,13 @@
 #include <linux/freezer.h>
 
 static kmem_zone_t *xfs_buf_zone;
-static kmem_shaker_t xfs_buf_shake;
 STATIC int xfsbufd(void *);
 STATIC int xfsbufd_wakeup(int, gfp_t);
 STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
+static struct shrinker xfs_buf_shake = {
+	.shrink = xfsbufd_wakeup,
+	.seeks = DEFAULT_SEEKS,
+};
 
 static struct workqueue_struct *xfslogd_workqueue;
 struct workqueue_struct *xfsdatad_workqueue;
@@ -314,7 +317,7 @@
 
 	ASSERT(list_empty(&bp->b_hash_list));
 
-	if (bp->b_flags & _XBF_PAGE_CACHE) {
+	if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
 		uint		i;
 
 		if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
@@ -323,18 +326,11 @@
 		for (i = 0; i < bp->b_page_count; i++) {
 			struct page	*page = bp->b_pages[i];
 
-			ASSERT(!PagePrivate(page));
+			if (bp->b_flags & _XBF_PAGE_CACHE)
+				ASSERT(!PagePrivate(page));
 			page_cache_release(page);
 		}
 		_xfs_buf_free_pages(bp);
-	} else if (bp->b_flags & _XBF_KMEM_ALLOC) {
-		 /*
-		  * XXX(hch): bp->b_count_desired might be incorrect (see
-		  * xfs_buf_associate_memory for details), but fortunately
-		  * the Linux version of kmem_free ignores the len argument..
-		  */
-		kmem_free(bp->b_addr, bp->b_count_desired);
-		_xfs_buf_free_pages(bp);
 	}
 
 	xfs_buf_deallocate(bp);
@@ -764,43 +760,44 @@
 	size_t			len,
 	xfs_buftarg_t		*target)
 {
-	size_t			malloc_len = len;
+	unsigned long		page_count = PAGE_ALIGN(len) >> PAGE_SHIFT;
+	int			error, i;
 	xfs_buf_t		*bp;
-	void			*data;
-	int			error;
 
 	bp = xfs_buf_allocate(0);
 	if (unlikely(bp == NULL))
 		goto fail;
 	_xfs_buf_initialize(bp, target, 0, len, 0);
 
- try_again:
-	data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL | KM_LARGE);
-	if (unlikely(data == NULL))
+	error = _xfs_buf_get_pages(bp, page_count, 0);
+	if (error)
 		goto fail_free_buf;
 
-	/* check whether alignment matches.. */
-	if ((__psunsigned_t)data !=
-	    ((__psunsigned_t)data & ~target->bt_smask)) {
-		/* .. else double the size and try again */
-		kmem_free(data, malloc_len);
-		malloc_len <<= 1;
-		goto try_again;
+	for (i = 0; i < page_count; i++) {
+		bp->b_pages[i] = alloc_page(GFP_KERNEL);
+		if (!bp->b_pages[i])
+			goto fail_free_mem;
 	}
+	bp->b_flags |= _XBF_PAGES;
 
-	error = xfs_buf_associate_memory(bp, data, len);
-	if (error)
+	error = _xfs_buf_map_pages(bp, XBF_MAPPED);
+	if (unlikely(error)) {
+		printk(KERN_WARNING "%s: failed to map pages\n",
+				__FUNCTION__);
 		goto fail_free_mem;
-	bp->b_flags |= _XBF_KMEM_ALLOC;
+	}
 
 	xfs_buf_unlock(bp);
 
-	XB_TRACE(bp, "no_daddr", data);
+	XB_TRACE(bp, "no_daddr", len);
 	return bp;
+
  fail_free_mem:
-	kmem_free(data, malloc_len);
+	while (--i >= 0)
+		__free_page(bp->b_pages[i]);
+	_xfs_buf_free_pages(bp);
  fail_free_buf:
-	xfs_buf_free(bp);
+	xfs_buf_deallocate(bp);
  fail:
 	return NULL;
 }
@@ -1453,6 +1450,7 @@
 	int			external)
 {
 	xfs_flush_buftarg(btp, 1);
+	xfs_blkdev_issue_flush(btp);
 	if (external)
 		xfs_blkdev_put(btp->bt_bdev);
 	xfs_free_bufhash(btp);
@@ -1837,14 +1835,9 @@
 	if (!xfsdatad_workqueue)
 		goto out_destroy_xfslogd_workqueue;
 
-	xfs_buf_shake = kmem_shake_register(xfsbufd_wakeup);
-	if (!xfs_buf_shake)
-		goto out_destroy_xfsdatad_workqueue;
-
+	register_shrinker(&xfs_buf_shake);
 	return 0;
 
- out_destroy_xfsdatad_workqueue:
-	destroy_workqueue(xfsdatad_workqueue);
  out_destroy_xfslogd_workqueue:
 	destroy_workqueue(xfslogd_workqueue);
  out_free_buf_zone:
@@ -1859,7 +1852,7 @@
 void
 xfs_buf_terminate(void)
 {
-	kmem_shake_deregister(xfs_buf_shake);
+	unregister_shrinker(&xfs_buf_shake);
 	destroy_workqueue(xfsdatad_workqueue);
 	destroy_workqueue(xfslogd_workqueue);
 	kmem_zone_destroy(xfs_buf_zone);
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index b6241f6..b5908a3 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -63,7 +63,7 @@
 
 	/* flags used only internally */
 	_XBF_PAGE_CACHE = (1 << 17),/* backed by pagecache		   */
-	_XBF_KMEM_ALLOC = (1 << 18),/* backed by kmem_alloc()		   */
+	_XBF_PAGES = (1 << 18),	    /* backed by refcounted pages	   */
 	_XBF_RUN_QUEUES = (1 << 19),/* run block device task queue	   */
 	_XBF_DELWRI_Q = (1 << 21),   /* buffer on delwri queue		   */
 } xfs_buf_flags_t;
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index cb51dc9..cbcd40c 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -124,30 +124,6 @@
 }
 
 STATIC ssize_t
-xfs_file_sendfile(
-	struct file		*filp,
-	loff_t			*pos,
-	size_t			count,
-	read_actor_t		actor,
-	void			*target)
-{
-	return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
-				filp, pos, 0, count, actor, target, NULL);
-}
-
-STATIC ssize_t
-xfs_file_sendfile_invis(
-	struct file		*filp,
-	loff_t			*pos,
-	size_t			count,
-	read_actor_t		actor,
-	void			*target)
-{
-	return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
-				filp, pos, IO_INVIS, count, actor, target, NULL);
-}
-
-STATIC ssize_t
 xfs_file_splice_read(
 	struct file		*infilp,
 	loff_t			*ppos,
@@ -208,15 +184,6 @@
 }
 
 STATIC int
-xfs_file_close(
-	struct file	*filp,
-	fl_owner_t	id)
-{
-	return -bhv_vop_close(vn_from_inode(filp->f_path.dentry->d_inode), 0,
-				file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
-}
-
-STATIC int
 xfs_file_release(
 	struct inode	*inode,
 	struct file	*filp)
@@ -452,7 +419,6 @@
 	.write		= do_sync_write,
 	.aio_read	= xfs_file_aio_read,
 	.aio_write	= xfs_file_aio_write,
-	.sendfile	= xfs_file_sendfile,
 	.splice_read	= xfs_file_splice_read,
 	.splice_write	= xfs_file_splice_write,
 	.unlocked_ioctl	= xfs_file_ioctl,
@@ -461,7 +427,6 @@
 #endif
 	.mmap		= xfs_file_mmap,
 	.open		= xfs_file_open,
-	.flush		= xfs_file_close,
 	.release	= xfs_file_release,
 	.fsync		= xfs_file_fsync,
 #ifdef HAVE_FOP_OPEN_EXEC
@@ -475,7 +440,6 @@
 	.write		= do_sync_write,
 	.aio_read	= xfs_file_aio_read_invis,
 	.aio_write	= xfs_file_aio_write_invis,
-	.sendfile	= xfs_file_sendfile_invis,
 	.splice_read	= xfs_file_splice_read_invis,
 	.splice_write	= xfs_file_splice_write_invis,
 	.unlocked_ioctl	= xfs_file_ioctl_invis,
@@ -484,7 +448,6 @@
 #endif
 	.mmap		= xfs_file_mmap,
 	.open		= xfs_file_open,
-	.flush		= xfs_file_close,
 	.release	= xfs_file_release,
 	.fsync		= xfs_file_fsync,
 };
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index ed3a5e1..bb72c3d 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -46,6 +46,7 @@
 	.inherit_nosym	= {	0,		0,		1	},
 	.rotorstep	= {	1,		1,		255	},
 	.inherit_nodfrg	= {	0,		1,		1	},
+	.fstrm_timer	= {	1,		50,		3600*100},
 };
 
 /*
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index ff5c41f..5917808 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -1019,7 +1019,7 @@
 
 	if (cmd == XFS_IOC_FSINUMBERS)
 		error = xfs_inumbers(mp, &inlast, &count,
-						bulkreq.ubuffer);
+					bulkreq.ubuffer, xfs_inumbers_fmt);
 	else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
 		error = xfs_bulkstat_single(mp, &inlast,
 						bulkreq.ubuffer, &done);
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index b83cebc..141cf15 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -23,10 +23,25 @@
 #include <linux/fs.h>
 #include <asm/uaccess.h>
 #include "xfs.h"
-#include "xfs_types.h"
 #include "xfs_fs.h"
+#include "xfs_bit.h"
+#include "xfs_log.h"
+#include "xfs_inum.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_dir2.h"
+#include "xfs_dmapi.h"
+#include "xfs_mount.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dir2_sf.h"
 #include "xfs_vfs.h"
 #include "xfs_vnode.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_itable.h"
+#include "xfs_error.h"
 #include "xfs_dfrag.h"
 
 #define  _NATIVE_IOC(cmd, type) \
@@ -34,6 +49,7 @@
 
 #if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
 #define BROKEN_X86_ALIGNMENT
+#define _PACKED __attribute__((packed))
 /* on ia32 l_start is on a 32-bit boundary */
 typedef struct xfs_flock64_32 {
 	__s16		l_type;
@@ -75,35 +91,276 @@
 	return (unsigned long)p;
 }
 
+typedef struct compat_xfs_fsop_geom_v1 {
+	__u32		blocksize;	/* filesystem (data) block size */
+	__u32		rtextsize;	/* realtime extent size		*/
+	__u32		agblocks;	/* fsblocks in an AG		*/
+	__u32		agcount;	/* number of allocation groups	*/
+	__u32		logblocks;	/* fsblocks in the log		*/
+	__u32		sectsize;	/* (data) sector size, bytes	*/
+	__u32		inodesize;	/* inode size in bytes		*/
+	__u32		imaxpct;	/* max allowed inode space(%)	*/
+	__u64		datablocks;	/* fsblocks in data subvolume	*/
+	__u64		rtblocks;	/* fsblocks in realtime subvol	*/
+	__u64		rtextents;	/* rt extents in realtime subvol*/
+	__u64		logstart;	/* starting fsblock of the log	*/
+	unsigned char	uuid[16];	/* unique id of the filesystem	*/
+	__u32		sunit;		/* stripe unit, fsblocks	*/
+	__u32		swidth;		/* stripe width, fsblocks	*/
+	__s32		version;	/* structure version		*/
+	__u32		flags;		/* superblock version flags	*/
+	__u32		logsectsize;	/* log sector size, bytes	*/
+	__u32		rtsectsize;	/* realtime sector size, bytes	*/
+	__u32		dirblocksize;	/* directory block size, bytes	*/
+} __attribute__((packed)) compat_xfs_fsop_geom_v1_t;
+
+#define XFS_IOC_FSGEOMETRY_V1_32  \
+	_IOR ('X', 100, struct compat_xfs_fsop_geom_v1)
+
+STATIC unsigned long xfs_ioctl32_geom_v1(unsigned long arg)
+{
+	compat_xfs_fsop_geom_v1_t __user *p32 = (void __user *)arg;
+	xfs_fsop_geom_v1_t __user *p = compat_alloc_user_space(sizeof(*p));
+
+	if (copy_in_user(p, p32, sizeof(*p32)))
+		return -EFAULT;
+	return (unsigned long)p;
+}
+
+typedef struct compat_xfs_inogrp {
+	__u64		xi_startino;	/* starting inode number	*/
+	__s32		xi_alloccount;	/* # bits set in allocmask	*/
+	__u64		xi_allocmask;	/* mask of allocated inodes	*/
+} __attribute__((packed)) compat_xfs_inogrp_t;
+
+STATIC int xfs_inumbers_fmt_compat(
+	void __user *ubuffer,
+	const xfs_inogrp_t *buffer,
+	long count,
+	long *written)
+{
+	compat_xfs_inogrp_t *p32 = ubuffer;
+	long i;
+
+	for (i = 0; i < count; i++) {
+		if (put_user(buffer[i].xi_startino,   &p32[i].xi_startino) ||
+		    put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) ||
+		    put_user(buffer[i].xi_allocmask,  &p32[i].xi_allocmask))
+			return -EFAULT;
+	}
+	*written = count * sizeof(*p32);
+	return 0;
+}
+
 #else
 
-typedef struct xfs_fsop_bulkreq32 {
+#define xfs_inumbers_fmt_compat xfs_inumbers_fmt
+#define _PACKED
+
+#endif
+
+/* XFS_IOC_FSBULKSTAT and friends */
+
+typedef struct compat_xfs_bstime {
+	__s32		tv_sec;		/* seconds		*/
+	__s32		tv_nsec;	/* and nanoseconds	*/
+} compat_xfs_bstime_t;
+
+STATIC int xfs_bstime_store_compat(
+	compat_xfs_bstime_t __user *p32,
+	const xfs_bstime_t *p)
+{
+	__s32 sec32;
+
+	sec32 = p->tv_sec;
+	if (put_user(sec32, &p32->tv_sec) ||
+	    put_user(p->tv_nsec, &p32->tv_nsec))
+		return -EFAULT;
+	return 0;
+}
+
+typedef struct compat_xfs_bstat {
+	__u64		bs_ino;		/* inode number			*/
+	__u16		bs_mode;	/* type and mode		*/
+	__u16		bs_nlink;	/* number of links		*/
+	__u32		bs_uid;		/* user id			*/
+	__u32		bs_gid;		/* group id			*/
+	__u32		bs_rdev;	/* device value			*/
+	__s32		bs_blksize;	/* block size			*/
+	__s64		bs_size;	/* file size			*/
+	compat_xfs_bstime_t bs_atime;	/* access time			*/
+	compat_xfs_bstime_t bs_mtime;	/* modify time			*/
+	compat_xfs_bstime_t bs_ctime;	/* inode change time		*/
+	int64_t		bs_blocks;	/* number of blocks		*/
+	__u32		bs_xflags;	/* extended flags		*/
+	__s32		bs_extsize;	/* extent size			*/
+	__s32		bs_extents;	/* number of extents		*/
+	__u32		bs_gen;		/* generation count		*/
+	__u16		bs_projid;	/* project id			*/
+	unsigned char	bs_pad[14];	/* pad space, unused		*/
+	__u32		bs_dmevmask;	/* DMIG event mask		*/
+	__u16		bs_dmstate;	/* DMIG state info		*/
+	__u16		bs_aextents;	/* attribute number of extents	*/
+} _PACKED compat_xfs_bstat_t;
+
+STATIC int xfs_bulkstat_one_fmt_compat(
+	void			__user *ubuffer,
+	const xfs_bstat_t	*buffer)
+{
+	compat_xfs_bstat_t __user *p32 = ubuffer;
+
+	if (put_user(buffer->bs_ino, &p32->bs_ino) ||
+	    put_user(buffer->bs_mode, &p32->bs_mode) ||
+	    put_user(buffer->bs_nlink, &p32->bs_nlink) ||
+	    put_user(buffer->bs_uid, &p32->bs_uid) ||
+	    put_user(buffer->bs_gid, &p32->bs_gid) ||
+	    put_user(buffer->bs_rdev, &p32->bs_rdev) ||
+	    put_user(buffer->bs_blksize, &p32->bs_blksize) ||
+	    put_user(buffer->bs_size, &p32->bs_size) ||
+	    xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) ||
+	    xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) ||
+	    xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) ||
+	    put_user(buffer->bs_blocks, &p32->bs_blocks) ||
+	    put_user(buffer->bs_xflags, &p32->bs_xflags) ||
+	    put_user(buffer->bs_extsize, &p32->bs_extsize) ||
+	    put_user(buffer->bs_extents, &p32->bs_extents) ||
+	    put_user(buffer->bs_gen, &p32->bs_gen) ||
+	    put_user(buffer->bs_projid, &p32->bs_projid) ||
+	    put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) ||
+	    put_user(buffer->bs_dmstate, &p32->bs_dmstate) ||
+	    put_user(buffer->bs_aextents, &p32->bs_aextents))
+		return -EFAULT;
+	return sizeof(*p32);
+}
+
+
+
+typedef struct compat_xfs_fsop_bulkreq {
 	compat_uptr_t	lastip;		/* last inode # pointer		*/
 	__s32		icount;		/* count of entries in buffer	*/
 	compat_uptr_t	ubuffer;	/* user buffer for inode desc.	*/
-	__s32		ocount;		/* output count pointer		*/
-} xfs_fsop_bulkreq32_t;
+	compat_uptr_t	ocount;		/* output count pointer		*/
+} compat_xfs_fsop_bulkreq_t;
 
-STATIC unsigned long
-xfs_ioctl32_bulkstat(
-	unsigned long		arg)
+#define XFS_IOC_FSBULKSTAT_32 \
+	_IOWR('X', 101, struct compat_xfs_fsop_bulkreq)
+#define XFS_IOC_FSBULKSTAT_SINGLE_32 \
+	_IOWR('X', 102, struct compat_xfs_fsop_bulkreq)
+#define XFS_IOC_FSINUMBERS_32 \
+	_IOWR('X', 103, struct compat_xfs_fsop_bulkreq)
+
+/* copied from xfs_ioctl.c */
+STATIC int
+xfs_ioc_bulkstat_compat(
+	xfs_mount_t		*mp,
+	unsigned int		cmd,
+	void			__user *arg)
 {
-	xfs_fsop_bulkreq32_t	__user *p32 = (void __user *)arg;
-	xfs_fsop_bulkreq_t	__user *p = compat_alloc_user_space(sizeof(*p));
+	compat_xfs_fsop_bulkreq_t __user *p32 = (void __user *)arg;
 	u32			addr;
+	xfs_fsop_bulkreq_t	bulkreq;
+	int			count;	/* # of records returned */
+	xfs_ino_t		inlast;	/* last inode number */
+	int			done;
+	int			error;
 
-	if (get_user(addr, &p32->lastip) ||
-	    put_user(compat_ptr(addr), &p->lastip) ||
-	    copy_in_user(&p->icount, &p32->icount, sizeof(s32)) ||
-	    get_user(addr, &p32->ubuffer) ||
-	    put_user(compat_ptr(addr), &p->ubuffer) ||
-	    get_user(addr, &p32->ocount) ||
-	    put_user(compat_ptr(addr), &p->ocount))
+	/* done = 1 if there are more stats to get and if bulkstat */
+	/* should be called again (unused here, but used in dmapi) */
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -XFS_ERROR(EIO);
+
+	if (get_user(addr, &p32->lastip))
+		return -EFAULT;
+	bulkreq.lastip = compat_ptr(addr);
+	if (get_user(bulkreq.icount, &p32->icount) ||
+	    get_user(addr, &p32->ubuffer))
+		return -EFAULT;
+	bulkreq.ubuffer = compat_ptr(addr);
+	if (get_user(addr, &p32->ocount))
+		return -EFAULT;
+	bulkreq.ocount = compat_ptr(addr);
+
+	if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
+		return -XFS_ERROR(EFAULT);
+
+	if ((count = bulkreq.icount) <= 0)
+		return -XFS_ERROR(EINVAL);
+
+	if (cmd == XFS_IOC_FSINUMBERS)
+		error = xfs_inumbers(mp, &inlast, &count,
+				bulkreq.ubuffer, xfs_inumbers_fmt_compat);
+	else {
+		/* declare a var to get a warning in case the type changes */
+		bulkstat_one_fmt_pf formatter = xfs_bulkstat_one_fmt_compat;
+		error = xfs_bulkstat(mp, &inlast, &count,
+			xfs_bulkstat_one, formatter,
+			sizeof(compat_xfs_bstat_t), bulkreq.ubuffer,
+			BULKSTAT_FG_QUICK, &done);
+	}
+	if (error)
+		return -error;
+
+	if (bulkreq.ocount != NULL) {
+		if (copy_to_user(bulkreq.lastip, &inlast,
+						sizeof(xfs_ino_t)))
+			return -XFS_ERROR(EFAULT);
+
+		if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
+			return -XFS_ERROR(EFAULT);
+	}
+
+	return 0;
+}
+
+
+
+typedef struct compat_xfs_fsop_handlereq {
+	__u32		fd;		/* fd for FD_TO_HANDLE		*/
+	compat_uptr_t	path;		/* user pathname		*/
+	__u32		oflags;		/* open flags			*/
+	compat_uptr_t	ihandle;	/* user supplied handle		*/
+	__u32		ihandlen;	/* user supplied length		*/
+	compat_uptr_t	ohandle;	/* user buffer for handle	*/
+	compat_uptr_t	ohandlen;	/* user buffer length		*/
+} compat_xfs_fsop_handlereq_t;
+
+#define XFS_IOC_PATH_TO_FSHANDLE_32 \
+	_IOWR('X', 104, struct compat_xfs_fsop_handlereq)
+#define XFS_IOC_PATH_TO_HANDLE_32 \
+	_IOWR('X', 105, struct compat_xfs_fsop_handlereq)
+#define XFS_IOC_FD_TO_HANDLE_32 \
+	_IOWR('X', 106, struct compat_xfs_fsop_handlereq)
+#define XFS_IOC_OPEN_BY_HANDLE_32 \
+	_IOWR('X', 107, struct compat_xfs_fsop_handlereq)
+#define XFS_IOC_READLINK_BY_HANDLE_32 \
+	_IOWR('X', 108, struct compat_xfs_fsop_handlereq)
+
+STATIC unsigned long xfs_ioctl32_fshandle(unsigned long arg)
+{
+	compat_xfs_fsop_handlereq_t __user *p32 = (void __user *)arg;
+	xfs_fsop_handlereq_t __user *p = compat_alloc_user_space(sizeof(*p));
+	u32 addr;
+
+	if (copy_in_user(&p->fd, &p32->fd, sizeof(__u32)) ||
+	    get_user(addr, &p32->path) ||
+	    put_user(compat_ptr(addr), &p->path) ||
+	    copy_in_user(&p->oflags, &p32->oflags, sizeof(__u32)) ||
+	    get_user(addr, &p32->ihandle) ||
+	    put_user(compat_ptr(addr), &p->ihandle) ||
+	    copy_in_user(&p->ihandlen, &p32->ihandlen, sizeof(__u32)) ||
+	    get_user(addr, &p32->ohandle) ||
+	    put_user(compat_ptr(addr), &p->ohandle) ||
+	    get_user(addr, &p32->ohandlen) ||
+	    put_user(compat_ptr(addr), &p->ohandlen))
 		return -EFAULT;
 
 	return (unsigned long)p;
 }
-#endif
+
 
 STATIC long
 xfs_compat_ioctl(
@@ -118,7 +375,6 @@
 
 	switch (cmd) {
 	case XFS_IOC_DIOINFO:
-	case XFS_IOC_FSGEOMETRY_V1:
 	case XFS_IOC_FSGEOMETRY:
 	case XFS_IOC_GETVERSION:
 	case XFS_IOC_GETXFLAGS:
@@ -131,12 +387,7 @@
 	case XFS_IOC_GETBMAPA:
 	case XFS_IOC_GETBMAPX:
 /* not handled
-	case XFS_IOC_FD_TO_HANDLE:
-	case XFS_IOC_PATH_TO_HANDLE:
-	case XFS_IOC_PATH_TO_FSHANDLE:
-	case XFS_IOC_OPEN_BY_HANDLE:
 	case XFS_IOC_FSSETDM_BY_HANDLE:
-	case XFS_IOC_READLINK_BY_HANDLE:
 	case XFS_IOC_ATTRLIST_BY_HANDLE:
 	case XFS_IOC_ATTRMULTI_BY_HANDLE:
 */
@@ -166,6 +417,10 @@
 		arg = xfs_ioctl32_flock(arg);
 		cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
 		break;
+	case XFS_IOC_FSGEOMETRY_V1_32:
+		arg = xfs_ioctl32_geom_v1(arg);
+		cmd = _NATIVE_IOC(cmd, struct xfs_fsop_geom_v1);
+		break;
 
 #else /* These are handled fine if no alignment issues */
 	case XFS_IOC_ALLOCSP:
@@ -176,18 +431,28 @@
 	case XFS_IOC_FREESP64:
 	case XFS_IOC_RESVSP64:
 	case XFS_IOC_UNRESVSP64:
+	case XFS_IOC_FSGEOMETRY_V1:
 		break;
 
 	/* xfs_bstat_t still has wrong u32 vs u64 alignment */
 	case XFS_IOC_SWAPEXT:
 		break;
 
-	case XFS_IOC_FSBULKSTAT_SINGLE:
-	case XFS_IOC_FSBULKSTAT:
-	case XFS_IOC_FSINUMBERS:
-		arg = xfs_ioctl32_bulkstat(arg);
-		break;
 #endif
+	case XFS_IOC_FSBULKSTAT_32:
+	case XFS_IOC_FSBULKSTAT_SINGLE_32:
+	case XFS_IOC_FSINUMBERS_32:
+		cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq);
+		return xfs_ioc_bulkstat_compat(XFS_BHVTOI(VNHEAD(vp))->i_mount,
+				cmd, (void*)arg);
+	case XFS_IOC_FD_TO_HANDLE_32:
+	case XFS_IOC_PATH_TO_HANDLE_32:
+	case XFS_IOC_PATH_TO_FSHANDLE_32:
+	case XFS_IOC_OPEN_BY_HANDLE_32:
+	case XFS_IOC_READLINK_BY_HANDLE_32:
+		arg = xfs_ioctl32_fshandle(arg);
+		cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq);
+		break;
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 715adad..330c4ba 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -101,7 +101,6 @@
  * Feature macros (disable/enable)
  */
 #undef  HAVE_REFCACHE	/* reference cache not needed for NFS in 2.6 */
-#define HAVE_SENDFILE	/* sendfile(2) exists in 2.6, but not in 2.4 */
 #define HAVE_SPLICE	/* a splice(2) exists in 2.6, but not in 2.4 */
 #ifdef CONFIG_SMP
 #define HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
@@ -124,6 +123,7 @@
 #define xfs_inherit_nosymlinks	xfs_params.inherit_nosym.val
 #define xfs_rotorstep		xfs_params.rotorstep.val
 #define xfs_inherit_nodefrag	xfs_params.inherit_nodfrg.val
+#define xfs_fstrm_centisecs	xfs_params.fstrm_timer.val
 
 #define current_cpu()		(raw_smp_processor_id())
 #define current_pid()		(current->pid)
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 86fb671..765ec16 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -159,7 +159,7 @@
 		if (status)
 			goto unlock;
 
-		memclear_highpage_flush(page, offset, bytes);
+		zero_user_page(page, offset, bytes, KM_USER0);
 
 		status = mapping->a_ops->commit_write(NULL, page, offset,
 							offset + bytes);
@@ -287,50 +287,6 @@
 }
 
 ssize_t
-xfs_sendfile(
-	bhv_desc_t		*bdp,
-	struct file		*filp,
-	loff_t			*offset,
-	int			ioflags,
-	size_t			count,
-	read_actor_t		actor,
-	void			*target,
-	cred_t			*credp)
-{
-	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
-	xfs_mount_t		*mp = ip->i_mount;
-	ssize_t			ret;
-
-	XFS_STATS_INC(xs_read_calls);
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return -EIO;
-
-	xfs_ilock(ip, XFS_IOLOCK_SHARED);
-
-	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
-	    (!(ioflags & IO_INVIS))) {
-		bhv_vrwlock_t locktype = VRWLOCK_READ;
-		int error;
-
-		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
-				      *offset, count,
-				      FILP_DELAY_FLAG(filp), &locktype);
-		if (error) {
-			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-			return -error;
-		}
-	}
-	xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
-		   (void *)(unsigned long)target, count, *offset, ioflags);
-	ret = generic_file_sendfile(filp, offset, count, actor, target);
-	if (ret > 0)
-		XFS_STATS_ADD(xs_read_bytes, ret);
-
-	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-	return ret;
-}
-
-ssize_t
 xfs_splice_read(
 	bhv_desc_t		*bdp,
 	struct file		*infilp,
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 7ac51b1..7c60a1e 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -90,9 +90,6 @@
 extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
 				const struct iovec *, unsigned int,
 				loff_t *, int, struct cred *);
-extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
-				loff_t *, int, size_t, read_actor_t,
-				void *, struct cred *);
 extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
 				struct pipe_inode_info *, size_t, int, int,
 				struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index bf9a9d5..4528f9a 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -547,7 +547,8 @@
 
 	if (!(vfsp->vfs_flag & VFS_RDONLY))
 		error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
-					SYNC_ATTR | SYNC_REFCACHE, NULL);
+					SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER,
+					NULL);
 	vfsp->vfs_sync_seq++;
 	wake_up(&vfsp->vfs_wait_single_sync_task);
 }
@@ -561,6 +562,7 @@
 	bhv_vfs_sync_work_t	*work, *n;
 	LIST_HEAD		(tmp);
 
+	set_freezable();
 	timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
 	for (;;) {
 		timeleft = schedule_timeout_interruptible(timeleft);
@@ -663,7 +665,7 @@
 		 * occur here so don't bother flushing the buftarg (i.e
 		 * SYNC_QUIESCE) because it'll just get dirty again.
 		 */
-		flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_IOWAIT;
+		flags = SYNC_DATA_QUIESCE;
 	} else
 		flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
 
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 33dd1ca..201cc32 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -18,6 +18,8 @@
 #ifndef __XFS_SUPER_H__
 #define __XFS_SUPER_H__
 
+#include <linux/exportfs.h>
+
 #ifdef CONFIG_XFS_DMAPI
 # define vfs_insertdmapi(vfs)	vfs_insertops(vfsp, &xfs_dmops)
 # define vfs_initdmapi()	dmapi_init()
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index cd6eaa4..bb997d7 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -210,6 +210,17 @@
 		.extra1		= &xfs_params.inherit_nodfrg.min,
 		.extra2		= &xfs_params.inherit_nodfrg.max
 	},
+	{
+		.ctl_name	= XFS_FILESTREAM_TIMER,
+		.procname	= "filestream_centisecs",
+		.data		= &xfs_params.fstrm_timer.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.fstrm_timer.min,
+		.extra2		= &xfs_params.fstrm_timer.max,
+	},
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
 	{
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h
index a631fb8..98b97e3 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.h
+++ b/fs/xfs/linux-2.6/xfs_sysctl.h
@@ -47,6 +47,7 @@
 	xfs_sysctl_val_t inherit_nosym;	/* Inherit the "nosymlinks" flag. */
 	xfs_sysctl_val_t rotorstep;	/* inode32 AG rotoring control knob */
 	xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
+	xfs_sysctl_val_t fstrm_timer;	/* Filestream dir-AG assoc'n timeout. */
 } xfs_param_t;
 
 /*
@@ -86,6 +87,7 @@
 	XFS_INHERIT_NOSYM = 19,
 	XFS_ROTORSTEP = 20,
 	XFS_INHERIT_NODFRG = 21,
+	XFS_FILESTREAM_TIMER = 22,
 };
 
 extern xfs_param_t	xfs_params;
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index e2c2ce9..dca3481 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -92,6 +92,21 @@
 #define SYNC_REFCACHE		0x0040  /* prune some of the nfs ref cache */
 #define SYNC_REMOUNT		0x0080  /* remount readonly, no dummy LRs */
 #define SYNC_IOWAIT		0x0100  /* wait for all I/O to complete */
+#define SYNC_SUPER		0x0200  /* flush superblock to disk */
+
+/*
+ * When remounting a filesystem read-only or freezing the filesystem,
+ * we have two phases to execute. This first phase is syncing the data
+ * before we quiesce the fielsystem, and the second is flushing all the
+ * inodes out after we've waited for all the transactions created by
+ * the first phase to complete. The second phase uses SYNC_INODE_QUIESCE
+ * to ensure that the inodes are written to their location on disk
+ * rather than just existing in transactions in the log. This means
+ * after a quiesce there is no log replay required to write the inodes
+ * to disk (this is the main difference between a sync and a quiesce).
+ */
+#define SYNC_DATA_QUIESCE	(SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
+#define SYNC_INODE_QUIESCE	(SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
 
 #define SHUTDOWN_META_IO_ERROR	0x0001	/* write attempt to metadata failed */
 #define SHUTDOWN_LOG_IO_ERROR	0x0002	/* write attempt to the log failed */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index d1b2d01..5742d65 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -129,19 +129,13 @@
 	VCHANGE_FLAGS_IOEXCL_COUNT	= 4
 } bhv_vchange_t;
 
-typedef enum { L_FALSE, L_TRUE } lastclose_t;
-
 typedef int	(*vop_open_t)(bhv_desc_t *, struct cred *);
-typedef int	(*vop_close_t)(bhv_desc_t *, int, lastclose_t, struct cred *);
 typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
 				const struct iovec *, unsigned int,
 				loff_t *, int, struct cred *);
 typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
 				const struct iovec *, unsigned int,
 				loff_t *, int, struct cred *);
-typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
-				loff_t *, int, size_t, read_actor_t,
-				void *, struct cred *);
 typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
 				struct pipe_inode_info *, size_t, int, int,
 				struct cred *);
@@ -203,10 +197,8 @@
 typedef struct bhv_vnodeops {
 	bhv_position_t  vn_position;    /* position within behavior chain */
 	vop_open_t		vop_open;
-	vop_close_t		vop_close;
 	vop_read_t		vop_read;
 	vop_write_t		vop_write;
-	vop_sendfile_t		vop_sendfile;
 	vop_splice_read_t	vop_splice_read;
 	vop_splice_write_t	vop_splice_write;
 	vop_ioctl_t		vop_ioctl;
@@ -249,13 +241,10 @@
 #define VNHEAD(vp)	((vp)->v_bh.bh_first)
 #define VOP(op, vp)	(*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op)
 #define bhv_vop_open(vp, cr)		VOP(vop_open, vp)(VNHEAD(vp),cr)
-#define bhv_vop_close(vp, f,last,cr)	VOP(vop_close, vp)(VNHEAD(vp),f,last,cr)
 #define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr)		\
 		VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
 #define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr)		\
 		VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
-#define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr)		\
-		VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr)
 #define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr)			\
 		VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
 #define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr)		\
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 3e4a8ad..2d274b2 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -62,10 +62,8 @@
 
 kmem_zone_t	*qm_dqzone;
 kmem_zone_t	*qm_dqtrxzone;
-static kmem_shaker_t	xfs_qm_shaker;
 
 static cred_t	xfs_zerocr;
-static xfs_inode_t	xfs_zeroino;
 
 STATIC void	xfs_qm_list_init(xfs_dqlist_t *, char *, int);
 STATIC void	xfs_qm_list_destroy(xfs_dqlist_t *);
@@ -79,6 +77,11 @@
 STATIC int	xfs_qm_init_quotainfo(xfs_mount_t *);
 STATIC int	xfs_qm_shake(int, gfp_t);
 
+static struct shrinker xfs_qm_shaker = {
+	.shrink = xfs_qm_shake,
+	.seeks = DEFAULT_SEEKS,
+};
+
 #ifdef DEBUG
 extern mutex_t	qcheck_lock;
 #endif
@@ -150,7 +153,7 @@
 	} else
 		xqm->qm_dqzone = qm_dqzone;
 
-	xfs_qm_shaker = kmem_shake_register(xfs_qm_shake);
+	register_shrinker(&xfs_qm_shaker);
 
 	/*
 	 * The t_dqinfo portion of transactions.
@@ -182,7 +185,7 @@
 
 	ASSERT(xqm != NULL);
 	ASSERT(xqm->qm_nrefs == 0);
-	kmem_shake_deregister(xfs_qm_shaker);
+	unregister_shrinker(&xfs_qm_shaker);
 	hsize = xqm->qm_dqhashmask + 1;
 	for (i = 0; i < hsize; i++) {
 		xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
@@ -1415,7 +1418,7 @@
 		return error;
 	}
 
-	if ((error = xfs_dir_ialloc(&tp, &xfs_zeroino, S_IFREG, 1, 0,
+	if ((error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
 				   &xfs_zerocr, 0, 1, ip, &committed))) {
 		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
 				 XFS_TRANS_ABORT);
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
index bf0a120..b5a7d92 100644
--- a/fs/xfs/xfs.h
+++ b/fs/xfs/xfs.h
@@ -38,6 +38,7 @@
 #define XFS_RW_TRACE 1
 #define XFS_BUF_TRACE 1
 #define XFS_VNODE_TRACE 1
+#define XFS_FILESTREAMS_TRACE 1
 #endif
 
 #include <linux-2.6/xfs_linux.h>
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 9ece7f87..51c09c1 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -68,6 +68,7 @@
 	__be32		agf_flcount;	/* count of blocks in freelist */
 	__be32		agf_freeblks;	/* total free blocks */
 	__be32		agf_longest;	/* longest free space */
+	__be32		agf_btreeblks;	/* # of blocks held in AGF btrees */
 } xfs_agf_t;
 
 #define	XFS_AGF_MAGICNUM	0x00000001
@@ -81,7 +82,8 @@
 #define	XFS_AGF_FLCOUNT		0x00000100
 #define	XFS_AGF_FREEBLKS	0x00000200
 #define	XFS_AGF_LONGEST		0x00000400
-#define	XFS_AGF_NUM_BITS	11
+#define	XFS_AGF_BTREEBLKS	0x00000800
+#define	XFS_AGF_NUM_BITS	12
 #define	XFS_AGF_ALL_BITS	((1 << XFS_AGF_NUM_BITS) - 1)
 
 /* disk block (xfs_daddr_t) in the AG */
@@ -186,12 +188,15 @@
 	__uint32_t	pagf_flcount;	/* count of blocks in freelist */
 	xfs_extlen_t	pagf_freeblks;	/* total free blocks */
 	xfs_extlen_t	pagf_longest;	/* longest free space */
+	__uint32_t	pagf_btreeblks;	/* # of blocks held in AGF btrees */
 	xfs_agino_t	pagi_freecount;	/* number of free inodes */
+	xfs_agino_t	pagi_count;	/* number of allocated inodes */
+	int		pagb_count;	/* pagb slots in use */
 #ifdef __KERNEL__
 	lock_t		pagb_lock;	/* lock for pagb_list */
 #endif
-	int		pagb_count;	/* pagb slots in use */
 	xfs_perag_busy_t *pagb_list;	/* unstable blocks */
+	atomic_t        pagf_fstrms;    /* # of filestreams active in this AG */
 } xfs_perag_t;
 
 #define	XFS_AG_MAXLEVELS(mp)		((mp)->m_ag_maxlevels)
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 8e9a40a..012a649 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -55,17 +55,17 @@
 ktrace_t *xfs_alloc_trace_buf;
 
 #define	TRACE_ALLOC(s,a)	\
-	xfs_alloc_trace_alloc(fname, s, a, __LINE__)
+	xfs_alloc_trace_alloc(__FUNCTION__, s, a, __LINE__)
 #define	TRACE_FREE(s,a,b,x,f)	\
-	xfs_alloc_trace_free(fname, s, mp, a, b, x, f, __LINE__)
+	xfs_alloc_trace_free(__FUNCTION__, s, mp, a, b, x, f, __LINE__)
 #define	TRACE_MODAGF(s,a,f)	\
-	xfs_alloc_trace_modagf(fname, s, mp, a, f, __LINE__)
-#define	TRACE_BUSY(fname,s,ag,agb,l,sl,tp)	\
-	xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
-#define	TRACE_UNBUSY(fname,s,ag,sl,tp)	\
-	xfs_alloc_trace_busy(fname, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
-#define	TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp)	\
-	xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
+	xfs_alloc_trace_modagf(__FUNCTION__, s, mp, a, f, __LINE__)
+#define	TRACE_BUSY(__FUNCTION__,s,ag,agb,l,sl,tp)	\
+	xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
+#define	TRACE_UNBUSY(__FUNCTION__,s,ag,sl,tp)	\
+	xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
+#define	TRACE_BUSYSEARCH(__FUNCTION__,s,ag,agb,l,sl,tp)	\
+	xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
 #else
 #define	TRACE_ALLOC(s,a)
 #define	TRACE_FREE(s,a,b,x,f)
@@ -420,7 +420,7 @@
  */
 STATIC void
 xfs_alloc_trace_alloc(
-	char		*name,		/* function tag string */
+	const char	*name,		/* function tag string */
 	char		*str,		/* additional string */
 	xfs_alloc_arg_t	*args,		/* allocation argument structure */
 	int		line)		/* source line number */
@@ -453,7 +453,7 @@
  */
 STATIC void
 xfs_alloc_trace_free(
-	char		*name,		/* function tag string */
+	const char	*name,		/* function tag string */
 	char		*str,		/* additional string */
 	xfs_mount_t	*mp,		/* file system mount point */
 	xfs_agnumber_t	agno,		/* allocation group number */
@@ -479,7 +479,7 @@
  */
 STATIC void
 xfs_alloc_trace_modagf(
-	char		*name,		/* function tag string */
+	const char	*name,		/* function tag string */
 	char		*str,		/* additional string */
 	xfs_mount_t	*mp,		/* file system mount point */
 	xfs_agf_t	*agf,		/* new agf value */
@@ -507,7 +507,7 @@
 
 STATIC void
 xfs_alloc_trace_busy(
-	char		*name,		/* function tag string */
+	const char	*name,		/* function tag string */
 	char		*str,		/* additional string */
 	xfs_mount_t	*mp,		/* file system mount point */
 	xfs_agnumber_t	agno,		/* allocation group number */
@@ -549,9 +549,6 @@
 	xfs_alloc_arg_t	*args)	/* argument structure for allocation */
 {
 	int		error=0;
-#ifdef XFS_ALLOC_TRACE
-	static char	fname[] = "xfs_alloc_ag_vextent";
-#endif
 
 	ASSERT(args->minlen > 0);
 	ASSERT(args->maxlen > 0);
@@ -635,9 +632,6 @@
 	xfs_agblock_t	fbno;	/* start block of found extent */
 	xfs_agblock_t	fend;	/* end block of found extent */
 	xfs_extlen_t	flen;	/* length of found extent */
-#ifdef XFS_ALLOC_TRACE
-	static char	fname[] = "xfs_alloc_ag_vextent_exact";
-#endif
 	int		i;	/* success/failure of operation */
 	xfs_agblock_t	maxend;	/* end of maximal extent */
 	xfs_agblock_t	minend;	/* end of minimal extent */
@@ -737,9 +731,6 @@
 	xfs_btree_cur_t	*bno_cur_gt;	/* cursor for bno btree, right side */
 	xfs_btree_cur_t	*bno_cur_lt;	/* cursor for bno btree, left side */
 	xfs_btree_cur_t	*cnt_cur;	/* cursor for count btree */
-#ifdef XFS_ALLOC_TRACE
-	static char	fname[] = "xfs_alloc_ag_vextent_near";
-#endif
 	xfs_agblock_t	gtbno;		/* start bno of right side entry */
 	xfs_agblock_t	gtbnoa;		/* aligned ... */
 	xfs_extlen_t	gtdiff;		/* difference to right side entry */
@@ -1270,9 +1261,6 @@
 	int		error;		/* error result */
 	xfs_agblock_t	fbno;		/* start of found freespace */
 	xfs_extlen_t	flen;		/* length of found freespace */
-#ifdef XFS_ALLOC_TRACE
-	static char	fname[] = "xfs_alloc_ag_vextent_size";
-#endif
 	int		i;		/* temp status variable */
 	xfs_agblock_t	rbno;		/* returned block number */
 	xfs_extlen_t	rlen;		/* length of returned extent */
@@ -1427,9 +1415,6 @@
 	int		error;
 	xfs_agblock_t	fbno;
 	xfs_extlen_t	flen;
-#ifdef XFS_ALLOC_TRACE
-	static char	fname[] = "xfs_alloc_ag_vextent_small";
-#endif
 	int		i;
 
 	if ((error = xfs_alloc_decrement(ccur, 0, &i)))
@@ -1447,7 +1432,8 @@
 	else if (args->minlen == 1 && args->alignment == 1 && !args->isfl &&
 		 (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount)
 		  > args->minleft)) {
-		if ((error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno)))
+		error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0);
+		if (error)
 			goto error0;
 		if (fbno != NULLAGBLOCK) {
 			if (args->userdata) {
@@ -1515,9 +1501,6 @@
 	xfs_btree_cur_t	*bno_cur;	/* cursor for by-block btree */
 	xfs_btree_cur_t	*cnt_cur;	/* cursor for by-size btree */
 	int		error;		/* error return value */
-#ifdef XFS_ALLOC_TRACE
-	static char	fname[] = "xfs_free_ag_extent";
-#endif
 	xfs_agblock_t	gtbno;		/* start of right neighbor block */
 	xfs_extlen_t	gtlen;		/* length of right neighbor block */
 	int		haveleft;	/* have a left neighbor block */
@@ -1923,7 +1906,8 @@
 	while (be32_to_cpu(agf->agf_flcount) > need) {
 		xfs_buf_t	*bp;
 
-		if ((error = xfs_alloc_get_freelist(tp, agbp, &bno)))
+		error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
+		if (error)
 			return error;
 		if ((error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1)))
 			return error;
@@ -1973,8 +1957,9 @@
 		 * Put each allocated block on the list.
 		 */
 		for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) {
-			if ((error = xfs_alloc_put_freelist(tp, agbp, agflbp,
-					bno)))
+			error = xfs_alloc_put_freelist(tp, agbp,
+							agflbp, bno, 0);
+			if (error)
 				return error;
 		}
 	}
@@ -1991,16 +1976,15 @@
 xfs_alloc_get_freelist(
 	xfs_trans_t	*tp,	/* transaction pointer */
 	xfs_buf_t	*agbp,	/* buffer containing the agf structure */
-	xfs_agblock_t	*bnop)	/* block address retrieved from freelist */
+	xfs_agblock_t	*bnop,	/* block address retrieved from freelist */
+	int		btreeblk) /* destination is a AGF btree */
 {
 	xfs_agf_t	*agf;	/* a.g. freespace structure */
 	xfs_agfl_t	*agfl;	/* a.g. freelist structure */
 	xfs_buf_t	*agflbp;/* buffer for a.g. freelist structure */
 	xfs_agblock_t	bno;	/* block number returned */
 	int		error;
-#ifdef XFS_ALLOC_TRACE
-	static char	fname[] = "xfs_alloc_get_freelist";
-#endif
+	int		logflags;
 	xfs_mount_t	*mp;	/* mount structure */
 	xfs_perag_t	*pag;	/* per allocation group data */
 
@@ -2032,8 +2016,16 @@
 	be32_add(&agf->agf_flcount, -1);
 	xfs_trans_agflist_delta(tp, -1);
 	pag->pagf_flcount--;
-	TRACE_MODAGF(NULL, agf, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
-	xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
+
+	logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
+	if (btreeblk) {
+		be32_add(&agf->agf_btreeblks, 1);
+		pag->pagf_btreeblks++;
+		logflags |= XFS_AGF_BTREEBLKS;
+	}
+
+	TRACE_MODAGF(NULL, agf, logflags);
+	xfs_alloc_log_agf(tp, agbp, logflags);
 	*bnop = bno;
 
 	/*
@@ -2071,6 +2063,7 @@
 		offsetof(xfs_agf_t, agf_flcount),
 		offsetof(xfs_agf_t, agf_freeblks),
 		offsetof(xfs_agf_t, agf_longest),
+		offsetof(xfs_agf_t, agf_btreeblks),
 		sizeof(xfs_agf_t)
 	};
 
@@ -2106,15 +2099,14 @@
 	xfs_trans_t		*tp,	/* transaction pointer */
 	xfs_buf_t		*agbp,	/* buffer for a.g. freelist header */
 	xfs_buf_t		*agflbp,/* buffer for a.g. free block array */
-	xfs_agblock_t		bno)	/* block being freed */
+	xfs_agblock_t		bno,	/* block being freed */
+	int			btreeblk) /* block came from a AGF btree */
 {
 	xfs_agf_t		*agf;	/* a.g. freespace structure */
 	xfs_agfl_t		*agfl;	/* a.g. free block array */
 	__be32			*blockp;/* pointer to array entry */
 	int			error;
-#ifdef XFS_ALLOC_TRACE
-	static char		fname[] = "xfs_alloc_put_freelist";
-#endif
+	int			logflags;
 	xfs_mount_t		*mp;	/* mount structure */
 	xfs_perag_t		*pag;	/* per allocation group data */
 
@@ -2132,11 +2124,22 @@
 	be32_add(&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);
+		pag->pagf_btreeblks--;
+		logflags |= XFS_AGF_BTREEBLKS;
+	}
+
+	TRACE_MODAGF(NULL, agf, logflags);
+	xfs_alloc_log_agf(tp, agbp, logflags);
+
 	ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
 	blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
 	*blockp = cpu_to_be32(bno);
-	TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
-	xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
+	TRACE_MODAGF(NULL, agf, logflags);
+	xfs_alloc_log_agf(tp, agbp, logflags);
 	xfs_trans_log_buf(tp, agflbp,
 		(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
 		(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
@@ -2196,6 +2199,7 @@
 	pag = &mp->m_perag[agno];
 	if (!pag->pagf_init) {
 		pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
+		pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
 		pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);
 		pag->pagf_longest = be32_to_cpu(agf->agf_longest);
 		pag->pagf_levels[XFS_BTNUM_BNOi] =
@@ -2235,9 +2239,6 @@
 	xfs_agblock_t	agsize;	/* allocation group size */
 	int		error;
 	int		flags;	/* XFS_ALLOC_FLAG_... locking flags */
-#ifdef XFS_ALLOC_TRACE
-	static char	fname[] = "xfs_alloc_vextent";
-#endif
 	xfs_extlen_t	minleft;/* minimum left value, temp copy */
 	xfs_mount_t	*mp;	/* mount structure pointer */
 	xfs_agnumber_t	sagno;	/* starting allocation group number */
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index 5a42561..5aec15d 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -136,7 +136,8 @@
 xfs_alloc_get_freelist(
 	struct xfs_trans *tp,	/* transaction pointer */
 	struct xfs_buf	*agbp,	/* buffer containing the agf structure */
-	xfs_agblock_t	*bnop);	/* block address retrieved from freelist */
+	xfs_agblock_t	*bnop,	/* block address retrieved from freelist */
+	int		btreeblk); /* destination is a AGF btree */
 
 /*
  * Log the given fields from the agf structure.
@@ -165,7 +166,8 @@
 	struct xfs_trans *tp,	/* transaction pointer */
 	struct xfs_buf	*agbp,	/* buffer for a.g. freelist header */
 	struct xfs_buf	*agflbp,/* buffer for a.g. free block array */
-	xfs_agblock_t	bno);	/* block being freed */
+	xfs_agblock_t	bno,	/* block being freed */
+	int		btreeblk); /* owner was a AGF btree */
 
 /*
  * Read in the allocation group header (free/alloc section).
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 74cadf9..1603ce5 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -226,8 +226,9 @@
 			/*
 			 * Put this buffer/block on the ag's freelist.
 			 */
-			if ((error = xfs_alloc_put_freelist(cur->bc_tp,
-					cur->bc_private.a.agbp, NULL, bno)))
+			error = xfs_alloc_put_freelist(cur->bc_tp,
+					cur->bc_private.a.agbp, NULL, bno, 1);
+			if (error)
 				return error;
 			/*
 			 * Since blocks move to the free list without the
@@ -549,8 +550,9 @@
 	/*
 	 * Free the deleting block by putting it on the freelist.
 	 */
-	if ((error = xfs_alloc_put_freelist(cur->bc_tp, cur->bc_private.a.agbp,
-			NULL, rbno)))
+	error = xfs_alloc_put_freelist(cur->bc_tp,
+					 cur->bc_private.a.agbp, NULL, rbno, 1);
+	if (error)
 		return error;
 	/*
 	 * Since blocks move to the free list without the coordination
@@ -1320,8 +1322,9 @@
 	/*
 	 * Get a buffer from the freelist blocks, for the new root.
 	 */
-	if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
-			&nbno)))
+	error = xfs_alloc_get_freelist(cur->bc_tp,
+					cur->bc_private.a.agbp, &nbno, 1);
+	if (error)
 		return error;
 	/*
 	 * None available, we fail.
@@ -1604,8 +1607,9 @@
 	 * Allocate the new block from the freelist.
 	 * If we can't do it, we're toast.  Give up.
 	 */
-	if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
-			&rbno)))
+	error = xfs_alloc_get_freelist(cur->bc_tp,
+					 cur->bc_private.a.agbp, &rbno, 1);
+	if (error)
 		return error;
 	if (rbno == NULLAGBLOCK) {
 		*stat = 0;
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index 1afe07f..fab0b6d 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -66,44 +66,6 @@
 #endif
 
 /*
- * Count of bits set in byte, 0..8.
- */
-static const char xfs_countbit[256] = {
-	0, 1, 1, 2, 1, 2, 2, 3,			/* 00 .. 07 */
-	1, 2, 2, 3, 2, 3, 3, 4,			/* 08 .. 0f */
-	1, 2, 2, 3, 2, 3, 3, 4,			/* 10 .. 17 */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* 18 .. 1f */
-	1, 2, 2, 3, 2, 3, 3, 4,			/* 20 .. 27 */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* 28 .. 2f */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* 30 .. 37 */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* 38 .. 3f */
-	1, 2, 2, 3, 2, 3, 3, 4,			/* 40 .. 47 */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* 48 .. 4f */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* 50 .. 57 */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* 58 .. 5f */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* 60 .. 67 */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* 68 .. 6f */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* 70 .. 77 */
-	4, 5, 5, 6, 5, 6, 6, 7,			/* 78 .. 7f */
-	1, 2, 2, 3, 2, 3, 3, 4,			/* 80 .. 87 */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* 88 .. 8f */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* 90 .. 97 */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* 98 .. 9f */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* a0 .. a7 */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* a8 .. af */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* b0 .. b7 */
-	4, 5, 5, 6, 5, 6, 6, 7,			/* b8 .. bf */
-	2, 3, 3, 4, 3, 4, 4, 5,			/* c0 .. c7 */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* c8 .. cf */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* d0 .. d7 */
-	4, 5, 5, 6, 5, 6, 6, 7,			/* d8 .. df */
-	3, 4, 4, 5, 4, 5, 5, 6,			/* e0 .. e7 */
-	4, 5, 5, 6, 5, 6, 6, 7,			/* e8 .. ef */
-	4, 5, 5, 6, 5, 6, 6, 7,			/* f0 .. f7 */
-	5, 6, 6, 7, 6, 7, 7, 8,			/* f8 .. ff */
-};
-
-/*
  * xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set.
  */
 inline int
@@ -167,56 +129,21 @@
 
 
 /*
- * Count the number of bits set in the bitmap starting with bit
- * start_bit.  Size is the size of the bitmap in words.
- *
- * Do the counting by mapping a byte value to the number of set
- * bits for that value using the xfs_countbit array, i.e.
- * xfs_countbit[0] == 0, xfs_countbit[1] == 1, xfs_countbit[2] == 1,
- * xfs_countbit[3] == 2, etc.
+ * Return whether bitmap is empty.
+ * Size is number of words in the bitmap, which is padded to word boundary
+ * Returns 1 for empty, 0 for non-empty.
  */
 int
-xfs_count_bits(uint *map, uint size, uint start_bit)
+xfs_bitmap_empty(uint *map, uint size)
 {
-	register int	bits;
-	register unsigned char	*bytep;
-	register unsigned char	*end_map;
-	int		byte_bit;
+	uint i;
+	uint ret = 0;
 
-	bits = 0;
-	end_map = (char*)(map + size);
-	bytep = (char*)(map + (start_bit & ~0x7));
-	byte_bit = start_bit & 0x7;
-
-	/*
-	 * If the caller fell off the end of the map, return 0.
-	 */
-	if (bytep >= end_map) {
-		return (0);
+	for (i = 0; i < size; i++) {
+		ret |= map[i];
 	}
 
-	/*
-	 * If start_bit is not byte aligned, then process the
-	 * first byte separately.
-	 */
-	if (byte_bit != 0) {
-		/*
-		 * Shift off the bits we don't want to look at,
-		 * before indexing into xfs_countbit.
-		 */
-		bits += xfs_countbit[(*bytep >> byte_bit)];
-		bytep++;
-	}
-
-	/*
-	 * Count the bits in each byte until the end of the bitmap.
-	 */
-	while (bytep < end_map) {
-		bits += xfs_countbit[*bytep];
-		bytep++;
-	}
-
-	return (bits);
+	return (ret == 0);
 }
 
 /*
diff --git a/fs/xfs/xfs_bit.h b/fs/xfs/xfs_bit.h
index 0bbe568..082641a 100644
--- a/fs/xfs/xfs_bit.h
+++ b/fs/xfs/xfs_bit.h
@@ -55,8 +55,8 @@
 /* Get high bit set out of 64-bit argument, -1 if none set */
 extern int xfs_highbit64(__uint64_t);
 
-/* Count set bits in map starting with start_bit */
-extern int xfs_count_bits(uint *map, uint size, uint start_bit);
+/* Return whether bitmap is empty (1 == empty) */
+extern int xfs_bitmap_empty(uint *map, uint size);
 
 /* Count continuous one bits in map starting with start_bit */
 extern int xfs_contig_bits(uint *map, uint size, uint start_bit);
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index b1ea26e..94b5c5f 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -52,6 +52,7 @@
 #include "xfs_quota.h"
 #include "xfs_trans_space.h"
 #include "xfs_buf_item.h"
+#include "xfs_filestream.h"
 
 
 #ifdef DEBUG
@@ -277,7 +278,7 @@
 STATIC void
 xfs_bmap_trace_addentry(
 	int		opcode,		/* operation */
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry(ies) */
@@ -291,7 +292,7 @@
  */
 STATIC void
 xfs_bmap_trace_delete(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry(entries) deleted */
@@ -304,7 +305,7 @@
  */
 STATIC void
 xfs_bmap_trace_insert(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry(entries) inserted */
@@ -318,7 +319,7 @@
  */
 STATIC void
 xfs_bmap_trace_post_update(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry updated */
@@ -329,17 +330,25 @@
  */
 STATIC void
 xfs_bmap_trace_pre_update(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry to be updated */
 	int		whichfork);	/* data or attr fork */
 
+#define	XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)	\
+	xfs_bmap_trace_delete(__FUNCTION__,d,ip,i,c,w)
+#define	XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)	\
+	xfs_bmap_trace_insert(__FUNCTION__,d,ip,i,c,r1,r2,w)
+#define	XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)	\
+	xfs_bmap_trace_post_update(__FUNCTION__,d,ip,i,w)
+#define	XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)	\
+	xfs_bmap_trace_pre_update(__FUNCTION__,d,ip,i,w)
 #else
-#define	xfs_bmap_trace_delete(f,d,ip,i,c,w)
-#define	xfs_bmap_trace_insert(f,d,ip,i,c,r1,r2,w)
-#define	xfs_bmap_trace_post_update(f,d,ip,i,w)
-#define	xfs_bmap_trace_pre_update(f,d,ip,i,w)
+#define	XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)
+#define	XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)
+#define	XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)
+#define	XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)
 #endif	/* XFS_BMAP_TRACE */
 
 /*
@@ -531,9 +540,6 @@
 	xfs_filblks_t		da_new; /* new count del alloc blocks used */
 	xfs_filblks_t		da_old; /* old count del alloc blocks used */
 	int			error;	/* error return value */
-#ifdef XFS_BMAP_TRACE
-	static char		fname[] = "xfs_bmap_add_extent";
-#endif
 	xfs_ifork_t		*ifp;	/* inode fork ptr */
 	int			logflags; /* returned value */
 	xfs_extnum_t		nextents; /* number of extents in file now */
@@ -551,8 +557,8 @@
 	 * already extents in the list.
 	 */
 	if (nextents == 0) {
-		xfs_bmap_trace_insert(fname, "insert empty", ip, 0, 1, new,
-			NULL, whichfork);
+		XFS_BMAP_TRACE_INSERT("insert empty", ip, 0, 1, new, NULL,
+			whichfork);
 		xfs_iext_insert(ifp, 0, 1, new);
 		ASSERT(cur == NULL);
 		ifp->if_lastex = 0;
@@ -710,9 +716,6 @@
 	int			diff;	/* temp value */
 	xfs_bmbt_rec_t		*ep;	/* extent entry for idx */
 	int			error;	/* error return value */
-#ifdef XFS_BMAP_TRACE
-	static char		fname[] = "xfs_bmap_add_extent_delay_real";
-#endif
 	int			i;	/* temp state */
 	xfs_ifork_t		*ifp;	/* inode fork pointer */
 	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
@@ -808,15 +811,14 @@
 		 * Filling in all of a previously delayed allocation extent.
 		 * The left and right neighbors are both contiguous with new.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 			LEFT.br_blockcount + PREV.br_blockcount +
 			RIGHT.br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
+		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
 			XFS_DATA_FORK);
-		xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
 		xfs_iext_remove(ifp, idx, 2);
 		ip->i_df.if_lastex = idx - 1;
 		ip->i_d.di_nextents--;
@@ -855,15 +857,14 @@
 		 * Filling in all of a previously delayed allocation extent.
 		 * The left neighbor is contiguous, the right is not.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 			LEFT.br_blockcount + PREV.br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
+		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
 			XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx - 1;
-		xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
 		xfs_iext_remove(ifp, idx, 1);
 		if (cur == NULL)
 			rval = XFS_ILOG_DEXT;
@@ -892,16 +893,13 @@
 		 * Filling in all of a previously delayed allocation extent.
 		 * The right neighbor is contiguous, the left is not.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
 		xfs_bmbt_set_startblock(ep, new->br_startblock);
 		xfs_bmbt_set_blockcount(ep,
 			PREV.br_blockcount + RIGHT.br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx;
-		xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
 		xfs_iext_remove(ifp, idx + 1, 1);
 		if (cur == NULL)
 			rval = XFS_ILOG_DEXT;
@@ -931,11 +929,9 @@
 		 * Neither the left nor right neighbors are contiguous with
 		 * the new one.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
 		xfs_bmbt_set_startblock(ep, new->br_startblock);
-		xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx;
 		ip->i_d.di_nextents++;
 		if (cur == NULL)
@@ -963,17 +959,14 @@
 		 * Filling in the first part of a previous delayed allocation.
 		 * The left neighbor is contiguous.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 			LEFT.br_blockcount + new->br_blockcount);
 		xfs_bmbt_set_startoff(ep,
 			PREV.br_startoff + new->br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
 		temp = PREV.br_blockcount - new->br_blockcount;
-		xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(ep, temp);
 		ip->i_df.if_lastex = idx - 1;
 		if (cur == NULL)
@@ -995,8 +988,7 @@
 		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 			STARTBLOCKVAL(PREV.br_startblock));
 		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
-		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
 		*dnew = temp;
 		/* DELTA: The boundary between two in-core extents moved. */
 		temp = LEFT.br_startoff;
@@ -1009,11 +1001,11 @@
 		 * Filling in the first part of a previous delayed allocation.
 		 * The left neighbor is not contiguous.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
 		xfs_bmbt_set_startoff(ep, new_endoff);
 		temp = PREV.br_blockcount - new->br_blockcount;
 		xfs_bmbt_set_blockcount(ep, temp);
-		xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
+		XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
 			XFS_DATA_FORK);
 		xfs_iext_insert(ifp, idx, 1, new);
 		ip->i_df.if_lastex = idx;
@@ -1046,8 +1038,7 @@
 			(cur ? cur->bc_private.b.allocated : 0));
 		ep = xfs_iext_get_ext(ifp, idx + 1);
 		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
-		xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx + 1, XFS_DATA_FORK);
 		*dnew = temp;
 		/* DELTA: One in-core extent is split in two. */
 		temp = PREV.br_startoff;
@@ -1060,17 +1051,14 @@
 		 * The right neighbor is contiguous with the new allocation.
 		 */
 		temp = PREV.br_blockcount - new->br_blockcount;
-		xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
-			XFS_DATA_FORK);
-		xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(ep, temp);
 		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
 			new->br_startoff, new->br_startblock,
 			new->br_blockcount + RIGHT.br_blockcount,
 			RIGHT.br_state);
-		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx + 1;
 		if (cur == NULL)
 			rval = XFS_ILOG_DEXT;
@@ -1091,8 +1079,7 @@
 		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 			STARTBLOCKVAL(PREV.br_startblock));
 		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
-		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
 		*dnew = temp;
 		/* DELTA: The boundary between two in-core extents moved. */
 		temp = PREV.br_startoff;
@@ -1106,10 +1093,10 @@
 		 * The right neighbor is not contiguous.
 		 */
 		temp = PREV.br_blockcount - new->br_blockcount;
-		xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(ep, temp);
-		xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
-			new, NULL, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
+			XFS_DATA_FORK);
 		xfs_iext_insert(ifp, idx + 1, 1, new);
 		ip->i_df.if_lastex = idx + 1;
 		ip->i_d.di_nextents++;
@@ -1141,7 +1128,7 @@
 			(cur ? cur->bc_private.b.allocated : 0));
 		ep = xfs_iext_get_ext(ifp, idx);
 		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
-		xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
 		*dnew = temp;
 		/* DELTA: One in-core extent is split in two. */
 		temp = PREV.br_startoff;
@@ -1155,7 +1142,7 @@
 		 * This case is avoided almost all the time.
 		 */
 		temp = new->br_startoff - PREV.br_startoff;
-		xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(ep, temp);
 		r[0] = *new;
 		r[1].br_state = PREV.br_state;
@@ -1163,7 +1150,7 @@
 		r[1].br_startoff = new_endoff;
 		temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
 		r[1].br_blockcount = temp2;
-		xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
+		XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
 			XFS_DATA_FORK);
 		xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
 		ip->i_df.if_lastex = idx + 1;
@@ -1222,13 +1209,11 @@
 		}
 		ep = xfs_iext_get_ext(ifp, idx);
 		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
-		xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
-		xfs_bmap_trace_pre_update(fname, "0", ip, idx + 2,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
 		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2),
 			NULLSTARTBLOCK((int)temp2));
-		xfs_bmap_trace_post_update(fname, "0", ip, idx + 2,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
 		*dnew = temp + temp2;
 		/* DELTA: One in-core extent is split in three. */
 		temp = PREV.br_startoff;
@@ -1287,9 +1272,6 @@
 	xfs_btree_cur_t		*cur;	/* btree cursor */
 	xfs_bmbt_rec_t		*ep;	/* extent entry for idx */
 	int			error;	/* error return value */
-#ifdef XFS_BMAP_TRACE
-	static char		fname[] = "xfs_bmap_add_extent_unwritten_real";
-#endif
 	int			i;	/* temp state */
 	xfs_ifork_t		*ifp;	/* inode fork pointer */
 	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
@@ -1390,15 +1372,14 @@
 		 * Setting all of a previous oldext extent to newext.
 		 * The left and right neighbors are both contiguous with new.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 			LEFT.br_blockcount + PREV.br_blockcount +
 			RIGHT.br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
+		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
 			XFS_DATA_FORK);
-		xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
 		xfs_iext_remove(ifp, idx, 2);
 		ip->i_df.if_lastex = idx - 1;
 		ip->i_d.di_nextents -= 2;
@@ -1441,15 +1422,14 @@
 		 * Setting all of a previous oldext extent to newext.
 		 * The left neighbor is contiguous, the right is not.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 			LEFT.br_blockcount + PREV.br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
+		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
 			XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx - 1;
-		xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
 		xfs_iext_remove(ifp, idx, 1);
 		ip->i_d.di_nextents--;
 		if (cur == NULL)
@@ -1484,16 +1464,15 @@
 		 * Setting all of a previous oldext extent to newext.
 		 * The right neighbor is contiguous, the left is not.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(ep,
 			PREV.br_blockcount + RIGHT.br_blockcount);
 		xfs_bmbt_set_state(ep, newext);
-		xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
+		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx,
 			XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx;
-		xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
 		xfs_iext_remove(ifp, idx + 1, 1);
 		ip->i_d.di_nextents--;
 		if (cur == NULL)
@@ -1529,10 +1508,10 @@
 		 * Neither the left nor right neighbors are contiguous with
 		 * the new one.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_state(ep, newext);
-		xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
+		XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx,
 			XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx;
 		if (cur == NULL)
@@ -1559,21 +1538,21 @@
 		 * Setting the first part of a previous oldext extent to newext.
 		 * The left neighbor is contiguous.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 			LEFT.br_blockcount + new->br_blockcount);
 		xfs_bmbt_set_startoff(ep,
 			PREV.br_startoff + new->br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
+		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1,
 			XFS_DATA_FORK);
-		xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
+		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_startblock(ep,
 			new->br_startblock + new->br_blockcount);
 		xfs_bmbt_set_blockcount(ep,
 			PREV.br_blockcount - new->br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
+		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx,
 			XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx - 1;
 		if (cur == NULL)
@@ -1610,15 +1589,15 @@
 		 * Setting the first part of a previous oldext extent to newext.
 		 * The left neighbor is not contiguous.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
 		ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
 		xfs_bmbt_set_startoff(ep, new_endoff);
 		xfs_bmbt_set_blockcount(ep,
 			PREV.br_blockcount - new->br_blockcount);
 		xfs_bmbt_set_startblock(ep,
 			new->br_startblock + new->br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LF", ip, idx, XFS_DATA_FORK);
-		xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
+		XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
 			XFS_DATA_FORK);
 		xfs_iext_insert(ifp, idx, 1, new);
 		ip->i_df.if_lastex = idx;
@@ -1653,18 +1632,18 @@
 		 * Setting the last part of a previous oldext extent to newext.
 		 * The right neighbor is contiguous with the new allocation.
 		 */
-		xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
+		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx,
 			XFS_DATA_FORK);
-		xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(ep,
 			PREV.br_blockcount - new->br_blockcount);
-		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
+		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
 			new->br_startoff, new->br_startblock,
 			new->br_blockcount + RIGHT.br_blockcount, newext);
-		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
+		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1,
 			XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx + 1;
 		if (cur == NULL)
@@ -1700,12 +1679,12 @@
 		 * Setting the last part of a previous oldext extent to newext.
 		 * The right neighbor is not contiguous.
 		 */
-		xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(ep,
 			PREV.br_blockcount - new->br_blockcount);
-		xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
-		xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
-			new, NULL, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
+			XFS_DATA_FORK);
 		xfs_iext_insert(ifp, idx + 1, 1, new);
 		ip->i_df.if_lastex = idx + 1;
 		ip->i_d.di_nextents++;
@@ -1744,17 +1723,17 @@
 		 * newext.  Contiguity is impossible here.
 		 * One extent becomes three extents.
 		 */
-		xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(ep,
 			new->br_startoff - PREV.br_startoff);
-		xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
 		r[0] = *new;
 		r[1].br_startoff = new_endoff;
 		r[1].br_blockcount =
 			PREV.br_startoff + PREV.br_blockcount - new_endoff;
 		r[1].br_startblock = new->br_startblock + new->br_blockcount;
 		r[1].br_state = oldext;
-		xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
+		XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
 			XFS_DATA_FORK);
 		xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
 		ip->i_df.if_lastex = idx + 1;
@@ -1845,9 +1824,6 @@
 	int			rsvd)		/* OK to allocate reserved blocks */
 {
 	xfs_bmbt_rec_t		*ep;	/* extent record for idx */
-#ifdef XFS_BMAP_TRACE
-	static char		fname[] = "xfs_bmap_add_extent_hole_delay";
-#endif
 	xfs_ifork_t		*ifp;	/* inode fork pointer */
 	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
 	xfs_filblks_t		newlen=0;	/* new indirect size */
@@ -1919,7 +1895,7 @@
 		 */
 		temp = left.br_blockcount + new->br_blockcount +
 			right.br_blockcount;
-		xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
 		oldlen = STARTBLOCKVAL(left.br_startblock) +
@@ -1928,10 +1904,9 @@
 		newlen = xfs_bmap_worst_indlen(ip, temp);
 		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
 			NULLSTARTBLOCK((int)newlen));
-		xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
+		XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
 			XFS_DATA_FORK);
-		xfs_bmap_trace_delete(fname, "LC|RC", ip, idx, 1,
-			XFS_DATA_FORK);
+		XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, XFS_DATA_FORK);
 		xfs_iext_remove(ifp, idx, 1);
 		ip->i_df.if_lastex = idx - 1;
 		/* DELTA: Two in-core extents were replaced by one. */
@@ -1946,7 +1921,7 @@
 		 * Merge the new allocation with the left neighbor.
 		 */
 		temp = left.br_blockcount + new->br_blockcount;
-		xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1,
 			XFS_DATA_FORK);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
 		oldlen = STARTBLOCKVAL(left.br_startblock) +
@@ -1954,7 +1929,7 @@
 		newlen = xfs_bmap_worst_indlen(ip, temp);
 		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
 			NULLSTARTBLOCK((int)newlen));
-		xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1,
+		XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1,
 			XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx - 1;
 		/* DELTA: One in-core extent grew into a hole. */
@@ -1968,14 +1943,14 @@
 		 * on the right.
 		 * Merge the new allocation with the right neighbor.
 		 */
-		xfs_bmap_trace_pre_update(fname, "RC", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, XFS_DATA_FORK);
 		temp = new->br_blockcount + right.br_blockcount;
 		oldlen = STARTBLOCKVAL(new->br_startblock) +
 			STARTBLOCKVAL(right.br_startblock);
 		newlen = xfs_bmap_worst_indlen(ip, temp);
 		xfs_bmbt_set_allf(ep, new->br_startoff,
 			NULLSTARTBLOCK((int)newlen), temp, right.br_state);
-		xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK);
+		XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx;
 		/* DELTA: One in-core extent grew into a hole. */
 		temp2 = temp;
@@ -1989,7 +1964,7 @@
 		 * Insert a new entry.
 		 */
 		oldlen = newlen = 0;
-		xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
+		XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL,
 			XFS_DATA_FORK);
 		xfs_iext_insert(ifp, idx, 1, new);
 		ip->i_df.if_lastex = idx;
@@ -2039,9 +2014,6 @@
 {
 	xfs_bmbt_rec_t		*ep;	/* pointer to extent entry ins. point */
 	int			error;	/* error return value */
-#ifdef XFS_BMAP_TRACE
-	static char		fname[] = "xfs_bmap_add_extent_hole_real";
-#endif
 	int			i;	/* temp state */
 	xfs_ifork_t		*ifp;	/* inode fork pointer */
 	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
@@ -2118,15 +2090,14 @@
 		 * left and on the right.
 		 * Merge all three into a single extent record.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
+		XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
 			whichfork);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 			left.br_blockcount + new->br_blockcount +
 			right.br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
+		XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
 			whichfork);
-		xfs_bmap_trace_delete(fname, "LC|RC", ip,
-			idx, 1, whichfork);
+		XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, whichfork);
 		xfs_iext_remove(ifp, idx, 1);
 		ifp->if_lastex = idx - 1;
 		XFS_IFORK_NEXT_SET(ip, whichfork,
@@ -2168,10 +2139,10 @@
 		 * on the left.
 		 * Merge the new allocation with the left neighbor.
 		 */
-		xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1, whichfork);
+		XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1, whichfork);
 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 			left.br_blockcount + new->br_blockcount);
-		xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork);
+		XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1, whichfork);
 		ifp->if_lastex = idx - 1;
 		if (cur == NULL) {
 			rval = XFS_ILOG_FEXT(whichfork);
@@ -2202,11 +2173,11 @@
 		 * on the right.
 		 * Merge the new allocation with the right neighbor.
 		 */
-		xfs_bmap_trace_pre_update(fname, "RC", ip, idx, whichfork);
+		XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, whichfork);
 		xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock,
 			new->br_blockcount + right.br_blockcount,
 			right.br_state);
-		xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork);
+		XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, whichfork);
 		ifp->if_lastex = idx;
 		if (cur == NULL) {
 			rval = XFS_ILOG_FEXT(whichfork);
@@ -2237,8 +2208,7 @@
 		 * real allocation.
 		 * Insert a new entry.
 		 */
-		xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
-			whichfork);
+		XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL, whichfork);
 		xfs_iext_insert(ifp, idx, 1, new);
 		ifp->if_lastex = idx;
 		XFS_IFORK_NEXT_SET(ip, whichfork,
@@ -2605,12 +2575,10 @@
 	xfs_extlen_t	prod = 0;	/* product factor for allocators */
 	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
 	xfs_extlen_t	align;		/* minimum allocation alignment */
-	xfs_rtblock_t	rtx;		/* realtime extent number */
 	xfs_rtblock_t	rtb;
 
 	mp = ap->ip->i_mount;
-	align = ap->ip->i_d.di_extsize ?
-		ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
+	align = xfs_get_extsz_hint(ap->ip);
 	prod = align / mp->m_sb.sb_rextsize;
 	error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
 					align, 1, ap->eof, 0,
@@ -2644,6 +2612,8 @@
 	 * pick an extent that will space things out in the rt area.
 	 */
 	if (ap->eof && ap->off == 0) {
+		xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */
+
 		error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
 		if (error)
 			return error;
@@ -2715,9 +2685,7 @@
 	int		error;
 
 	mp = ap->ip->i_mount;
-	align = (ap->userdata && ap->ip->i_d.di_extsize &&
-		(ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
-		ap->ip->i_d.di_extsize : 0;
+	align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
 	if (unlikely(align)) {
 		error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
 						align, 0, ap->eof, 0, ap->conv,
@@ -2727,9 +2695,15 @@
 	}
 	nullfb = ap->firstblock == NULLFSBLOCK;
 	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
-	if (nullfb)
-		ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
-	else
+	if (nullfb) {
+		if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
+			ag = xfs_filestream_lookup_ag(ap->ip);
+			ag = (ag != NULLAGNUMBER) ? ag : 0;
+			ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
+		} else {
+			ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
+		}
+	} else
 		ap->rval = ap->firstblock;
 
 	xfs_bmap_adjacent(ap);
@@ -2753,13 +2727,22 @@
 	args.firstblock = ap->firstblock;
 	blen = 0;
 	if (nullfb) {
-		args.type = XFS_ALLOCTYPE_START_BNO;
+		if (ap->userdata && xfs_inode_is_filestream(ap->ip))
+			args.type = XFS_ALLOCTYPE_NEAR_BNO;
+		else
+			args.type = XFS_ALLOCTYPE_START_BNO;
 		args.total = ap->total;
+
 		/*
-		 * Find the longest available space.
-		 * We're going to try for the whole allocation at once.
+		 * Search for an allocation group with a single extent
+		 * large enough for the request.
+		 *
+		 * If one isn't found, then adjust the minimum allocation
+		 * size to the largest space found.
 		 */
 		startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
+		if (startag == NULLAGNUMBER)
+			startag = ag = 0;
 		notinit = 0;
 		down_read(&mp->m_peraglock);
 		while (blen < ap->alen) {
@@ -2785,6 +2768,35 @@
 					blen = longest;
 			} else
 				notinit = 1;
+
+			if (xfs_inode_is_filestream(ap->ip)) {
+				if (blen >= ap->alen)
+					break;
+
+				if (ap->userdata) {
+					/*
+					 * If startag is an invalid AG, we've
+					 * come here once before and
+					 * xfs_filestream_new_ag picked the
+					 * best currently available.
+					 *
+					 * Don't continue looping, since we
+					 * could loop forever.
+					 */
+					if (startag == NULLAGNUMBER)
+						break;
+
+					error = xfs_filestream_new_ag(ap, &ag);
+					if (error) {
+						up_read(&mp->m_peraglock);
+						return error;
+					}
+
+					/* loop again to set 'blen'*/
+					startag = NULLAGNUMBER;
+					continue;
+				}
+			}
 			if (++ag == mp->m_sb.sb_agcount)
 				ag = 0;
 			if (ag == startag)
@@ -2809,17 +2821,27 @@
 		 */
 		else
 			args.minlen = ap->alen;
+
+		/*
+		 * set the failure fallback case to look in the selected
+		 * AG as the stream may have moved.
+		 */
+		if (xfs_inode_is_filestream(ap->ip))
+			ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
 	} else if (ap->low) {
-		args.type = XFS_ALLOCTYPE_START_BNO;
+		if (xfs_inode_is_filestream(ap->ip))
+			args.type = XFS_ALLOCTYPE_FIRST_AG;
+		else
+			args.type = XFS_ALLOCTYPE_START_BNO;
 		args.total = args.minlen = ap->minlen;
 	} else {
 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
 		args.total = ap->total;
 		args.minlen = ap->minlen;
 	}
-	if (unlikely(ap->userdata && ap->ip->i_d.di_extsize &&
-		    (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) {
-		args.prod = ap->ip->i_d.di_extsize;
+	/* apply extent size hints if obtained earlier */
+	if (unlikely(align)) {
+		args.prod = align;
 		if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
 			args.mod = (xfs_extlen_t)(args.prod - args.mod);
 	} else if (mp->m_sb.sb_blocksize >= NBPP) {
@@ -3051,9 +3073,6 @@
 	xfs_bmbt_rec_t		*ep;	/* current extent entry pointer */
 	int			error;	/* error return value */
 	int			flags;	/* inode logging flags */
-#ifdef XFS_BMAP_TRACE
-	static char		fname[] = "xfs_bmap_del_extent";
-#endif
 	xfs_bmbt_irec_t		got;	/* current extent entry */
 	xfs_fileoff_t		got_endoff;	/* first offset past got */
 	int			i;	/* temp state */
@@ -3147,7 +3166,7 @@
 		/*
 		 * Matches the whole extent.  Delete the entry.
 		 */
-		xfs_bmap_trace_delete(fname, "3", ip, idx, 1, whichfork);
+		XFS_BMAP_TRACE_DELETE("3", ip, idx, 1, whichfork);
 		xfs_iext_remove(ifp, idx, 1);
 		ifp->if_lastex = idx;
 		if (delay)
@@ -3168,7 +3187,7 @@
 		/*
 		 * Deleting the first part of the extent.
 		 */
-		xfs_bmap_trace_pre_update(fname, "2", ip, idx, whichfork);
+		XFS_BMAP_TRACE_PRE_UPDATE("2", ip, idx, whichfork);
 		xfs_bmbt_set_startoff(ep, del_endoff);
 		temp = got.br_blockcount - del->br_blockcount;
 		xfs_bmbt_set_blockcount(ep, temp);
@@ -3177,13 +3196,13 @@
 			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 				da_old);
 			xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
-			xfs_bmap_trace_post_update(fname, "2", ip, idx,
+			XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx,
 				whichfork);
 			da_new = temp;
 			break;
 		}
 		xfs_bmbt_set_startblock(ep, del_endblock);
-		xfs_bmap_trace_post_update(fname, "2", ip, idx, whichfork);
+		XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx, whichfork);
 		if (!cur) {
 			flags |= XFS_ILOG_FEXT(whichfork);
 			break;
@@ -3199,19 +3218,19 @@
 		 * Deleting the last part of the extent.
 		 */
 		temp = got.br_blockcount - del->br_blockcount;
-		xfs_bmap_trace_pre_update(fname, "1", ip, idx, whichfork);
+		XFS_BMAP_TRACE_PRE_UPDATE("1", ip, idx, whichfork);
 		xfs_bmbt_set_blockcount(ep, temp);
 		ifp->if_lastex = idx;
 		if (delay) {
 			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 				da_old);
 			xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
-			xfs_bmap_trace_post_update(fname, "1", ip, idx,
+			XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx,
 				whichfork);
 			da_new = temp;
 			break;
 		}
-		xfs_bmap_trace_post_update(fname, "1", ip, idx, whichfork);
+		XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx, whichfork);
 		if (!cur) {
 			flags |= XFS_ILOG_FEXT(whichfork);
 			break;
@@ -3228,7 +3247,7 @@
 		 * Deleting the middle of the extent.
 		 */
 		temp = del->br_startoff - got.br_startoff;
-		xfs_bmap_trace_pre_update(fname, "0", ip, idx, whichfork);
+		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, whichfork);
 		xfs_bmbt_set_blockcount(ep, temp);
 		new.br_startoff = del_endoff;
 		temp2 = got_endoff - del_endoff;
@@ -3315,8 +3334,8 @@
 				}
 			}
 		}
-		xfs_bmap_trace_post_update(fname, "0", ip, idx, whichfork);
-		xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 1, &new, NULL,
+		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, whichfork);
+		XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 1, &new, NULL,
 			whichfork);
 		xfs_iext_insert(ifp, idx + 1, 1, &new);
 		ifp->if_lastex = idx + 1;
@@ -3556,9 +3575,6 @@
 {
 	int		error;		/* error return value */
 	int		flags;		/* logging flags returned */
-#ifdef XFS_BMAP_TRACE
-	static char	fname[] = "xfs_bmap_local_to_extents";
-#endif
 	xfs_ifork_t	*ifp;		/* inode fork pointer */
 
 	/*
@@ -3613,7 +3629,7 @@
 		xfs_iext_add(ifp, 0, 1);
 		ep = xfs_iext_get_ext(ifp, 0);
 		xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
-		xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork);
+		XFS_BMAP_TRACE_POST_UPDATE("new", ip, 0, whichfork);
 		XFS_IFORK_NEXT_SET(ip, whichfork, 1);
 		ip->i_d.di_nblocks = 1;
 		XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip,
@@ -3736,7 +3752,7 @@
 STATIC void
 xfs_bmap_trace_addentry(
 	int		opcode,		/* operation */
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry(ies) */
@@ -3795,7 +3811,7 @@
  */
 STATIC void
 xfs_bmap_trace_delete(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry(entries) deleted */
@@ -3817,7 +3833,7 @@
  */
 STATIC void
 xfs_bmap_trace_insert(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry(entries) inserted */
@@ -3846,7 +3862,7 @@
  */
 STATIC void
 xfs_bmap_trace_post_update(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry updated */
@@ -3864,7 +3880,7 @@
  */
 STATIC void
 xfs_bmap_trace_pre_update(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	char		*desc,		/* operation description */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	idx,		/* index of entry to be updated */
@@ -4481,9 +4497,6 @@
 	xfs_buf_t		*bp;	/* buffer for "block" */
 	int			error;	/* error return value */
 	xfs_exntfmt_t		exntf;	/* XFS_EXTFMT_NOSTATE, if checking */
-#ifdef XFS_BMAP_TRACE
-	static char		fname[] = "xfs_bmap_read_extents";
-#endif
 	xfs_extnum_t		i, j;	/* index into the extents list */
 	xfs_ifork_t		*ifp;	/* fork structure */
 	int			level;	/* btree level, for checking */
@@ -4600,7 +4613,7 @@
 	}
 	ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
 	ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
-	xfs_bmap_trace_exlist(fname, ip, i, whichfork);
+	XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
 	return 0;
 error0:
 	xfs_trans_brelse(tp, bp);
@@ -4613,7 +4626,7 @@
  */
 void
 xfs_bmap_trace_exlist(
-	char		*fname,		/* function name */
+	const char	*fname,		/* function name */
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_extnum_t	cnt,		/* count of entries in the list */
 	int		whichfork)	/* data or attr fork */
@@ -4628,7 +4641,7 @@
 	for (idx = 0; idx < cnt; idx++) {
 		ep = xfs_iext_get_ext(ifp, idx);
 		xfs_bmbt_get_all(ep, &s);
-		xfs_bmap_trace_insert(fname, "exlist", ip, idx, 1, &s, NULL,
+		XFS_BMAP_TRACE_INSERT("exlist", ip, idx, 1, &s, NULL,
 			whichfork);
 	}
 }
@@ -4868,12 +4881,7 @@
 				xfs_extlen_t	extsz;
 
 				/* Figure out the extent size, adjust alen */
-				if (rt) {
-					if (!(extsz = ip->i_d.di_extsize))
-						extsz = mp->m_sb.sb_rextsize;
-				} else {
-					extsz = ip->i_d.di_extsize;
-				}
+				extsz = xfs_get_extsz_hint(ip);
 				if (extsz) {
 					error = xfs_bmap_extsize_align(mp,
 							&got, &prev, extsz,
@@ -5219,10 +5227,10 @@
 		 * Else go on to the next record.
 		 */
 		ep = xfs_iext_get_ext(ifp, ++lastx);
-		if (lastx >= nextents) {
+		prev = got;
+		if (lastx >= nextents)
 			eof = 1;
-			prev = got;
-		} else
+		else
 			xfs_bmbt_get_all(ep, &got);
 	}
 	ifp->if_lastex = lastx;
@@ -5813,8 +5821,7 @@
 		   ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
 		return XFS_ERROR(EINVAL);
 	if (whichfork == XFS_DATA_FORK) {
-		if ((ip->i_d.di_extsize && (ip->i_d.di_flags &
-				(XFS_DIFLAG_REALTIME|XFS_DIFLAG_EXTSIZE))) ||
+		if (xfs_get_extsz_hint(ip) ||
 		    ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
 			prealloced = 1;
 			fixlen = XFS_MAXIOFFSET(mp);
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 4f24c7e..524b1c9 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -144,12 +144,14 @@
  */
 void
 xfs_bmap_trace_exlist(
-	char			*fname,		/* function name */
+	const char		*fname,		/* function name */
 	struct xfs_inode	*ip,		/* incore inode pointer */
 	xfs_extnum_t		cnt,		/* count of entries in list */
 	int			whichfork);	/* data or attr fork */
+#define	XFS_BMAP_TRACE_EXLIST(ip,c,w)	\
+	xfs_bmap_trace_exlist(__FUNCTION__,ip,c,w)
 #else
-#define	xfs_bmap_trace_exlist(f,ip,c,w)
+#define	XFS_BMAP_TRACE_EXLIST(ip,c,w)
 #endif
 
 /*
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 0bf192f..89b891f 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -76,7 +76,7 @@
  */
 STATIC void
 xfs_bmbt_trace_enter(
-	char		*func,
+	const char	*func,
 	xfs_btree_cur_t	*cur,
 	char		*s,
 	int		type,
@@ -117,7 +117,7 @@
  */
 STATIC void
 xfs_bmbt_trace_argbi(
-	char		*func,
+	const char	*func,
 	xfs_btree_cur_t	*cur,
 	xfs_buf_t	*b,
 	int		i,
@@ -134,7 +134,7 @@
  */
 STATIC void
 xfs_bmbt_trace_argbii(
-	char		*func,
+	const char	*func,
 	xfs_btree_cur_t	*cur,
 	xfs_buf_t	*b,
 	int		i0,
@@ -153,7 +153,7 @@
  */
 STATIC void
 xfs_bmbt_trace_argfffi(
-	char			*func,
+	const char		*func,
 	xfs_btree_cur_t		*cur,
 	xfs_dfiloff_t		o,
 	xfs_dfsbno_t		b,
@@ -172,7 +172,7 @@
  */
 STATIC void
 xfs_bmbt_trace_argi(
-	char		*func,
+	const char	*func,
 	xfs_btree_cur_t	*cur,
 	int		i,
 	int		line)
@@ -188,7 +188,7 @@
  */
 STATIC void
 xfs_bmbt_trace_argifk(
-	char			*func,
+	const char		*func,
 	xfs_btree_cur_t		*cur,
 	int			i,
 	xfs_fsblock_t		f,
@@ -206,7 +206,7 @@
  */
 STATIC void
 xfs_bmbt_trace_argifr(
-	char			*func,
+	const char		*func,
 	xfs_btree_cur_t		*cur,
 	int			i,
 	xfs_fsblock_t		f,
@@ -235,7 +235,7 @@
  */
 STATIC void
 xfs_bmbt_trace_argik(
-	char			*func,
+	const char		*func,
 	xfs_btree_cur_t		*cur,
 	int			i,
 	xfs_bmbt_key_t		*k,
@@ -255,7 +255,7 @@
  */
 STATIC void
 xfs_bmbt_trace_cursor(
-	char		*func,
+	const char	*func,
 	xfs_btree_cur_t	*cur,
 	char		*s,
 	int		line)
@@ -274,21 +274,21 @@
 }
 
 #define	XFS_BMBT_TRACE_ARGBI(c,b,i)	\
-	xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__)
+	xfs_bmbt_trace_argbi(__FUNCTION__, c, b, i, __LINE__)
 #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)	\
-	xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__)
+	xfs_bmbt_trace_argbii(__FUNCTION__, c, b, i, j, __LINE__)
 #define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)	\
-	xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
+	xfs_bmbt_trace_argfffi(__FUNCTION__, c, o, b, i, j, __LINE__)
 #define	XFS_BMBT_TRACE_ARGI(c,i)	\
-	xfs_bmbt_trace_argi(fname, c, i, __LINE__)
+	xfs_bmbt_trace_argi(__FUNCTION__, c, i, __LINE__)
 #define	XFS_BMBT_TRACE_ARGIFK(c,i,f,s)	\
-	xfs_bmbt_trace_argifk(fname, c, i, f, s, __LINE__)
+	xfs_bmbt_trace_argifk(__FUNCTION__, c, i, f, s, __LINE__)
 #define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)	\
-	xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
+	xfs_bmbt_trace_argifr(__FUNCTION__, c, i, f, r, __LINE__)
 #define	XFS_BMBT_TRACE_ARGIK(c,i,k)	\
-	xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
+	xfs_bmbt_trace_argik(__FUNCTION__, c, i, k, __LINE__)
 #define	XFS_BMBT_TRACE_CURSOR(c,s)	\
-	xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
+	xfs_bmbt_trace_cursor(__FUNCTION__, c, s, __LINE__)
 #else
 #define	XFS_BMBT_TRACE_ARGBI(c,b,i)
 #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)
@@ -318,9 +318,6 @@
 	xfs_fsblock_t		bno;		/* fs-relative block number */
 	xfs_buf_t		*bp;		/* buffer for block */
 	int			error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_delrec";
-#endif
 	int			i;		/* loop counter */
 	int			j;		/* temp state */
 	xfs_bmbt_key_t		key;		/* bmap btree key */
@@ -694,9 +691,6 @@
 	xfs_bmbt_block_t	*block;		/* bmap btree block */
 	xfs_buf_t		*bp;		/* buffer for block */
 	int			error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_insrec";
-#endif
 	int			i;		/* loop index */
 	xfs_bmbt_key_t		key;		/* bmap btree key */
 	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */
@@ -881,9 +875,6 @@
 #ifdef DEBUG
 	int			error;
 #endif
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_killroot";
-#endif
 	int			i;
 	xfs_bmbt_key_t		*kp;
 	xfs_inode_t		*ip;
@@ -973,9 +964,6 @@
 	int		kfirst,
 	int		klast)
 {
-#ifdef XFS_BMBT_TRACE
-	static char	fname[] = "xfs_bmbt_log_keys";
-#endif
 	xfs_trans_t	*tp;
 
 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
@@ -1012,9 +1000,6 @@
 	int		pfirst,
 	int		plast)
 {
-#ifdef XFS_BMBT_TRACE
-	static char	fname[] = "xfs_bmbt_log_ptrs";
-#endif
 	xfs_trans_t	*tp;
 
 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
@@ -1055,9 +1040,6 @@
 	xfs_daddr_t		d;
 	xfs_sfiloff_t		diff;
 	int			error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char	fname[] = "xfs_bmbt_lookup";
-#endif
 	xfs_fsblock_t		fsbno=0;
 	int			high;
 	int			i;
@@ -1195,9 +1177,6 @@
 	int			*stat)		/* success/failure */
 {
 	int			error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_lshift";
-#endif
 #ifdef DEBUG
 	int			i;		/* loop counter */
 #endif
@@ -1331,9 +1310,6 @@
 	int			*stat)		/* success/failure */
 {
 	int			error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_rshift";
-#endif
 	int			i;		/* loop counter */
 	xfs_bmbt_key_t		key;		/* bmap btree key */
 	xfs_buf_t		*lbp;		/* left buffer pointer */
@@ -1492,9 +1468,6 @@
 {
 	xfs_alloc_arg_t		args;		/* block allocation args */
 	int			error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_split";
-#endif
 	int			i;		/* loop counter */
 	xfs_fsblock_t		lbno;		/* left sibling block number */
 	xfs_buf_t		*lbp;		/* left buffer pointer */
@@ -1641,9 +1614,6 @@
 #ifdef DEBUG
 	int			error;
 #endif
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_updkey";
-#endif
 	xfs_bmbt_key_t		*kp;
 	int			ptr;
 
@@ -1712,9 +1682,6 @@
 	xfs_bmbt_block_t	*block;
 	xfs_buf_t		*bp;
 	int			error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_decrement";
-#endif
 	xfs_fsblock_t		fsbno;
 	int			lev;
 	xfs_mount_t		*mp;
@@ -1785,9 +1752,6 @@
 	int		*stat)		/* success/failure */
 {
 	int		error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char	fname[] = "xfs_bmbt_delete";
-#endif
 	int		i;
 	int		level;
 
@@ -2000,9 +1964,6 @@
 	xfs_bmbt_block_t	*block;
 	xfs_buf_t		*bp;
 	int			error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_increment";
-#endif
 	xfs_fsblock_t		fsbno;
 	int			lev;
 	xfs_mount_t		*mp;
@@ -2080,9 +2041,6 @@
 	int		*stat)		/* success/failure */
 {
 	int		error;		/* error return value */
-#ifdef XFS_BMBT_TRACE
-	static char	fname[] = "xfs_bmbt_insert";
-#endif
 	int		i;
 	int		level;
 	xfs_fsblock_t	nbno;
@@ -2142,9 +2100,6 @@
 	int			fields)
 {
 	int			first;
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_log_block";
-#endif
 	int			last;
 	xfs_trans_t		*tp;
 	static const short	offsets[] = {
@@ -2181,9 +2136,6 @@
 {
 	xfs_bmbt_block_t	*block;
 	int			first;
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_log_recs";
-#endif
 	int			last;
 	xfs_bmbt_rec_t		*rp;
 	xfs_trans_t		*tp;
@@ -2245,9 +2197,6 @@
 	xfs_bmbt_key_t		*ckp;		/* child key pointer */
 	xfs_bmbt_ptr_t		*cpp;		/* child ptr pointer */
 	int			error;		/* error return code */
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_newroot";
-#endif
 #ifdef DEBUG
 	int			i;		/* loop counter */
 #endif
@@ -2630,9 +2579,6 @@
 	xfs_bmbt_block_t	*block;
 	xfs_buf_t		*bp;
 	int			error;
-#ifdef XFS_BMBT_TRACE
-	static char		fname[] = "xfs_bmbt_update";
-#endif
 	xfs_bmbt_key_t		key;
 	int			ptr;
 	xfs_bmbt_rec_t		*rp;
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 4e27d55..6e40a0a 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -444,30 +444,14 @@
 /*
  * Min and max functions for extlen, agblock, fileoff, and filblks types.
  */
-#define	XFS_EXTLEN_MIN(a,b)	\
-	((xfs_extlen_t)(a) < (xfs_extlen_t)(b) ? \
-		(xfs_extlen_t)(a) : (xfs_extlen_t)(b))
-#define	XFS_EXTLEN_MAX(a,b)	\
-	((xfs_extlen_t)(a) > (xfs_extlen_t)(b) ? \
-		(xfs_extlen_t)(a) : (xfs_extlen_t)(b))
-#define	XFS_AGBLOCK_MIN(a,b)	\
-	((xfs_agblock_t)(a) < (xfs_agblock_t)(b) ? \
-		(xfs_agblock_t)(a) : (xfs_agblock_t)(b))
-#define	XFS_AGBLOCK_MAX(a,b)	\
-	((xfs_agblock_t)(a) > (xfs_agblock_t)(b) ? \
-		(xfs_agblock_t)(a) : (xfs_agblock_t)(b))
-#define	XFS_FILEOFF_MIN(a,b)	\
-	((xfs_fileoff_t)(a) < (xfs_fileoff_t)(b) ? \
-		(xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
-#define	XFS_FILEOFF_MAX(a,b)	\
-	((xfs_fileoff_t)(a) > (xfs_fileoff_t)(b) ? \
-		(xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
-#define	XFS_FILBLKS_MIN(a,b)	\
-	((xfs_filblks_t)(a) < (xfs_filblks_t)(b) ? \
-		(xfs_filblks_t)(a) : (xfs_filblks_t)(b))
-#define	XFS_FILBLKS_MAX(a,b)	\
-	((xfs_filblks_t)(a) > (xfs_filblks_t)(b) ? \
-		(xfs_filblks_t)(a) : (xfs_filblks_t)(b))
+#define	XFS_EXTLEN_MIN(a,b)	min_t(xfs_extlen_t, (a), (b))
+#define	XFS_EXTLEN_MAX(a,b)	max_t(xfs_extlen_t, (a), (b))
+#define	XFS_AGBLOCK_MIN(a,b)	min_t(xfs_agblock_t, (a), (b))
+#define	XFS_AGBLOCK_MAX(a,b)	max_t(xfs_agblock_t, (a), (b))
+#define	XFS_FILEOFF_MIN(a,b)	min_t(xfs_fileoff_t, (a), (b))
+#define	XFS_FILEOFF_MAX(a,b)	max_t(xfs_fileoff_t, (a), (b))
+#define	XFS_FILBLKS_MIN(a,b)	min_t(xfs_filblks_t, (a), (b))
+#define	XFS_FILBLKS_MAX(a,b)	max_t(xfs_filblks_t, (a), (b))
 
 #define	XFS_FSB_SANITY_CHECK(mp,fsb)	\
 	(XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 6c1bddc..b0667cb 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -580,8 +580,8 @@
 	 * If the buf item isn't tracking any data, free it.
 	 * Otherwise, if XFS_BLI_HOLD is set clear it.
 	 */
-	if (xfs_count_bits(bip->bli_format.blf_data_map,
-			      bip->bli_format.blf_map_size, 0) == 0) {
+	if (xfs_bitmap_empty(bip->bli_format.blf_data_map,
+			     bip->bli_format.blf_map_size)) {
 		xfs_buf_item_relse(bp);
 	} else if (hold) {
 		bip->bli_flags &= ~XFS_BLI_HOLD;
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index 5b7eb81..f89196c 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -99,5 +99,7 @@
  */
 #define XFSMNT2_COMPAT_IOSIZE	0x00000001	/* don't report large preferred
 						 * I/O size in stat(2) */
+#define XFSMNT2_FILESTREAMS	0x00000002	/* enable the filestreams
+						 * allocator */
 
 #endif	/* __XFS_CLNT_H__ */
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index b338269..fefd011 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -257,6 +257,7 @@
 #define XFS_DIFLAG_EXTSIZE_BIT      11	/* inode extent size allocator hint */
 #define XFS_DIFLAG_EXTSZINHERIT_BIT 12	/* inherit inode extent size */
 #define XFS_DIFLAG_NODEFRAG_BIT     13	/* do not reorganize/defragment */
+#define XFS_DIFLAG_FILESTREAM_BIT   14  /* use filestream allocator */
 #define XFS_DIFLAG_REALTIME      (1 << XFS_DIFLAG_REALTIME_BIT)
 #define XFS_DIFLAG_PREALLOC      (1 << XFS_DIFLAG_PREALLOC_BIT)
 #define XFS_DIFLAG_NEWRTBM       (1 << XFS_DIFLAG_NEWRTBM_BIT)
@@ -271,12 +272,13 @@
 #define XFS_DIFLAG_EXTSIZE       (1 << XFS_DIFLAG_EXTSIZE_BIT)
 #define XFS_DIFLAG_EXTSZINHERIT  (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
 #define XFS_DIFLAG_NODEFRAG      (1 << XFS_DIFLAG_NODEFRAG_BIT)
+#define XFS_DIFLAG_FILESTREAM    (1 << XFS_DIFLAG_FILESTREAM_BIT)
 
 #define XFS_DIFLAG_ANY \
 	(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
 	 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
 	 XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
 	 XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
-	 XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG)
+	 XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM)
 
 #endif	/* __XFS_DINODE_H__ */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 8e8e527..29e0919 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -55,9 +55,9 @@
 	       XFS_MAX_BLOCKSIZE);
 	mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
 	mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
-	mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp));
-	mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
-	mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp));
+	mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp));
+	mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
+	mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp));
 	mp->m_attr_node_ents =
 		(mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) /
 		(uint)sizeof(xfs_da_node_entry_t);
@@ -554,7 +554,7 @@
 	 */
 	if (mapp != &map)
 		kmem_free(mapp, sizeof(*mapp) * count);
-	*dbp = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)bno);
+	*dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
 	/*
 	 * Update file's size if this is the data space and it grew.
 	 */
@@ -706,7 +706,7 @@
 	dp = args->dp;
 	mp = dp->i_mount;
 	tp = args->trans;
-	da = XFS_DIR2_DB_TO_DA(mp, db);
+	da = xfs_dir2_db_to_da(mp, db);
 	/*
 	 * Unmap the fsblock(s).
 	 */
@@ -742,7 +742,7 @@
 	/*
 	 * If the block isn't the last one in the directory, we're done.
 	 */
-	if (dp->i_d.di_size > XFS_DIR2_DB_OFF_TO_BYTE(mp, db + 1, 0))
+	if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(mp, db + 1, 0))
 		return 0;
 	bno = da;
 	if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 3accc1d..e4df1aa 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -115,13 +115,13 @@
 		xfs_da_brelse(tp, bp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
-	len = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+	len = xfs_dir2_data_entsize(args->namelen);
 	/*
 	 * Set up pointers to parts of the block.
 	 */
 	bf = block->hdr.bestfree;
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	btp = xfs_dir2_block_tail_p(mp, block);
+	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * No stale entries?  Need space for entry and new leaf.
 	 */
@@ -396,7 +396,7 @@
 	 * Fill in the leaf entry.
 	 */
 	blp[mid].hashval = cpu_to_be32(args->hashval);
-	blp[mid].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
+	blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
 				(char *)dep - (char *)block));
 	xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
 	/*
@@ -411,7 +411,7 @@
 	dep->inumber = cpu_to_be64(args->inumber);
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, args->namelen);
-	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+	tagp = xfs_dir2_data_entry_tag_p(dep);
 	*tagp = cpu_to_be16((char *)dep - (char *)block);
 	/*
 	 * Clean up the bestfree array and log the header, tail, and entry.
@@ -455,7 +455,7 @@
 	/*
 	 * If the block number in the offset is out of range, we're done.
 	 */
-	if (XFS_DIR2_DATAPTR_TO_DB(mp, uio->uio_offset) > mp->m_dirdatablk) {
+	if (xfs_dir2_dataptr_to_db(mp, uio->uio_offset) > mp->m_dirdatablk) {
 		*eofp = 1;
 		return 0;
 	}
@@ -471,15 +471,15 @@
 	 * Extract the byte offset we start at from the seek pointer.
 	 * We'll skip entries before this.
 	 */
-	wantoff = XFS_DIR2_DATAPTR_TO_OFF(mp, uio->uio_offset);
+	wantoff = xfs_dir2_dataptr_to_off(mp, uio->uio_offset);
 	block = bp->data;
 	xfs_dir2_data_check(dp, bp);
 	/*
 	 * Set up values for the loop.
 	 */
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, block);
 	ptr = (char *)block->u;
-	endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
+	endptr = (char *)xfs_dir2_block_leaf_p(btp);
 	p.dbp = dbp;
 	p.put = put;
 	p.uio = uio;
@@ -502,7 +502,7 @@
 		/*
 		 * Bump pointer for the next iteration.
 		 */
-		ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+		ptr += xfs_dir2_data_entsize(dep->namelen);
 		/*
 		 * The entry is before the desired starting point, skip it.
 		 */
@@ -513,7 +513,7 @@
 		 */
 		p.namelen = dep->namelen;
 
-		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+		p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 						    ptr - (char *)block);
 		p.ino = be64_to_cpu(dep->inumber);
 #if XFS_BIG_INUMS
@@ -531,7 +531,7 @@
 		 */
 		if (!p.done) {
 			uio->uio_offset =
-				XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+				xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 					(char *)dep - (char *)block);
 			xfs_da_brelse(tp, bp);
 			return error;
@@ -545,7 +545,7 @@
 	*eofp = 1;
 
 	uio->uio_offset =
-		XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
+		xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
 
 	xfs_da_brelse(tp, bp);
 
@@ -569,8 +569,8 @@
 
 	mp = tp->t_mountp;
 	block = bp->data;
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	btp = xfs_dir2_block_tail_p(mp, block);
+	blp = xfs_dir2_block_leaf_p(btp);
 	xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)block),
 		(uint)((char *)&blp[last + 1] - (char *)block - 1));
 }
@@ -589,7 +589,7 @@
 
 	mp = tp->t_mountp;
 	block = bp->data;
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, block);
 	xfs_da_log_buf(tp, bp, (uint)((char *)btp - (char *)block),
 		(uint)((char *)(btp + 1) - (char *)block - 1));
 }
@@ -623,13 +623,13 @@
 	mp = dp->i_mount;
 	block = bp->data;
 	xfs_dir2_data_check(dp, bp);
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	btp = xfs_dir2_block_tail_p(mp, block);
+	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Get the offset from the leaf entry, to point to the data.
 	 */
 	dep = (xfs_dir2_data_entry_t *)
-	      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
+	      ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
 	/*
 	 * Fill in inode number, release the block.
 	 */
@@ -675,8 +675,8 @@
 	ASSERT(bp != NULL);
 	block = bp->data;
 	xfs_dir2_data_check(dp, bp);
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	btp = xfs_dir2_block_tail_p(mp, block);
+	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Loop doing a binary search for our hash value.
 	 * Find our entry, ENOENT if it's not there.
@@ -713,7 +713,7 @@
 		 * Get pointer to the entry from the leaf.
 		 */
 		dep = (xfs_dir2_data_entry_t *)
-			((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
+			((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
 		/*
 		 * Compare, if it's right give back buffer & entry number.
 		 */
@@ -768,20 +768,20 @@
 	tp = args->trans;
 	mp = dp->i_mount;
 	block = bp->data;
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	btp = xfs_dir2_block_tail_p(mp, block);
+	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Point to the data entry using the leaf entry.
 	 */
 	dep = (xfs_dir2_data_entry_t *)
-	      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
+	      ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
 	/*
 	 * Mark the data entry's space free.
 	 */
 	needlog = needscan = 0;
 	xfs_dir2_data_make_free(tp, bp,
 		(xfs_dir2_data_aoff_t)((char *)dep - (char *)block),
-		XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
+		xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
 	/*
 	 * Fix up the block tail.
 	 */
@@ -843,13 +843,13 @@
 	dp = args->dp;
 	mp = dp->i_mount;
 	block = bp->data;
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	btp = xfs_dir2_block_tail_p(mp, block);
+	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Point to the data entry we need to change.
 	 */
 	dep = (xfs_dir2_data_entry_t *)
-	      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
+	      ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
 	ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
 	/*
 	 * Change the inode number to the new value.
@@ -912,7 +912,7 @@
 	mp = dp->i_mount;
 	leaf = lbp->data;
 	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	/*
 	 * If there are data blocks other than the first one, take this
 	 * opportunity to remove trailing empty data blocks that may have
@@ -920,7 +920,7 @@
 	 * These will show up in the leaf bests table.
 	 */
 	while (dp->i_d.di_size > mp->m_dirblksize) {
-		bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
+		bestsp = xfs_dir2_leaf_bests_p(ltp);
 		if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
 		    mp->m_dirblksize - (uint)sizeof(block->hdr)) {
 			if ((error =
@@ -974,14 +974,14 @@
 	/*
 	 * Initialize the block tail.
 	 */
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, block);
 	btp->count = cpu_to_be32(be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale));
 	btp->stale = 0;
 	xfs_dir2_block_log_tail(tp, dbp);
 	/*
 	 * Initialize the block leaf area.  We compact out stale entries.
 	 */
-	lep = XFS_DIR2_BLOCK_LEAF_P(btp);
+	lep = xfs_dir2_block_leaf_p(btp);
 	for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) {
 		if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR)
 			continue;
@@ -1067,7 +1067,7 @@
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
 	/*
 	 * Copy the directory into the stack buffer.
 	 * Then pitch the incore inode data so we can make extents.
@@ -1119,10 +1119,10 @@
 	/*
 	 * Fill in the tail.
 	 */
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, block);
 	btp->count = cpu_to_be32(sfp->hdr.count + 2);	/* ., .. */
 	btp->stale = 0;
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	blp = xfs_dir2_block_leaf_p(btp);
 	endoffset = (uint)((char *)blp - (char *)block);
 	/*
 	 * Remove the freespace, we'll manage it.
@@ -1138,25 +1138,25 @@
 	dep->inumber = cpu_to_be64(dp->i_ino);
 	dep->namelen = 1;
 	dep->name[0] = '.';
-	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+	tagp = xfs_dir2_data_entry_tag_p(dep);
 	*tagp = cpu_to_be16((char *)dep - (char *)block);
 	xfs_dir2_data_log_entry(tp, bp, dep);
 	blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
-	blp[0].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
+	blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
 				(char *)dep - (char *)block));
 	/*
 	 * Create entry for ..
 	 */
 	dep = (xfs_dir2_data_entry_t *)
 		((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET);
-	dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
+	dep->inumber = cpu_to_be64(xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
 	dep->namelen = 2;
 	dep->name[0] = dep->name[1] = '.';
-	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+	tagp = xfs_dir2_data_entry_tag_p(dep);
 	*tagp = cpu_to_be16((char *)dep - (char *)block);
 	xfs_dir2_data_log_entry(tp, bp, dep);
 	blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
-	blp[1].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
+	blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
 				(char *)dep - (char *)block));
 	offset = XFS_DIR2_DATA_FIRST_OFFSET;
 	/*
@@ -1165,7 +1165,7 @@
 	if ((i = 0) == sfp->hdr.count)
 		sfep = NULL;
 	else
-		sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+		sfep = xfs_dir2_sf_firstentry(sfp);
 	/*
 	 * Need to preserve the existing offset values in the sf directory.
 	 * Insert holes (unused entries) where necessary.
@@ -1177,7 +1177,7 @@
 		if (sfep == NULL)
 			newoffset = endoffset;
 		else
-			newoffset = XFS_DIR2_SF_GET_OFFSET(sfep);
+			newoffset = xfs_dir2_sf_get_offset(sfep);
 		/*
 		 * There should be a hole here, make one.
 		 */
@@ -1186,7 +1186,7 @@
 			      ((char *)block + offset);
 			dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 			dup->length = cpu_to_be16(newoffset - offset);
-			*XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16(
+			*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(
 				((char *)dup - (char *)block));
 			xfs_dir2_data_log_unused(tp, bp, dup);
 			(void)xfs_dir2_data_freeinsert((xfs_dir2_data_t *)block,
@@ -1198,22 +1198,22 @@
 		 * Copy a real entry.
 		 */
 		dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset);
-		dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp,
-				XFS_DIR2_SF_INUMBERP(sfep)));
+		dep->inumber = cpu_to_be64(xfs_dir2_sf_get_inumber(sfp,
+				xfs_dir2_sf_inumberp(sfep)));
 		dep->namelen = sfep->namelen;
 		memcpy(dep->name, sfep->name, dep->namelen);
-		tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+		tagp = xfs_dir2_data_entry_tag_p(dep);
 		*tagp = cpu_to_be16((char *)dep - (char *)block);
 		xfs_dir2_data_log_entry(tp, bp, dep);
 		blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname(
 					(char *)sfep->name, sfep->namelen));
-		blp[2 + i].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
+		blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
 						 (char *)dep - (char *)block));
 		offset = (int)((char *)(tagp + 1) - (char *)block);
 		if (++i == sfp->hdr.count)
 			sfep = NULL;
 		else
-			sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+			sfep = xfs_dir2_sf_nextentry(sfp, sfep);
 	}
 	/* Done with the temporary buffer */
 	kmem_free(buf, buf_len);
diff --git a/fs/xfs/xfs_dir2_block.h b/fs/xfs/xfs_dir2_block.h
index 6722eff..e7c2606 100644
--- a/fs/xfs/xfs_dir2_block.h
+++ b/fs/xfs/xfs_dir2_block.h
@@ -60,7 +60,6 @@
 /*
  * Pointer to the leaf header embedded in a data block (1-block format)
  */
-#define	XFS_DIR2_BLOCK_TAIL_P(mp,block)	xfs_dir2_block_tail_p(mp,block)
 static inline xfs_dir2_block_tail_t *
 xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block)
 {
@@ -71,7 +70,6 @@
 /*
  * Pointer to the leaf entries embedded in a data block (1-block format)
  */
-#define	XFS_DIR2_BLOCK_LEAF_P(btp)	xfs_dir2_block_leaf_p(btp)
 static inline struct xfs_dir2_leaf_entry *
 xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
 {
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index c211c37..7ebe295 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -72,8 +72,8 @@
 	bf = d->hdr.bestfree;
 	p = (char *)d->u;
 	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
-		btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
-		lep = XFS_DIR2_BLOCK_LEAF_P(btp);
+		btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+		lep = xfs_dir2_block_leaf_p(btp);
 		endp = (char *)lep;
 	} else
 		endp = (char *)d + mp->m_dirblksize;
@@ -107,7 +107,7 @@
 		 */
 		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
 			ASSERT(lastfree == 0);
-			ASSERT(be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)) ==
+			ASSERT(be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
 			       (char *)dup - (char *)d);
 			dfp = xfs_dir2_data_freefind(d, dup);
 			if (dfp) {
@@ -131,12 +131,12 @@
 		dep = (xfs_dir2_data_entry_t *)p;
 		ASSERT(dep->namelen != 0);
 		ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0);
-		ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) ==
+		ASSERT(be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) ==
 		       (char *)dep - (char *)d);
 		count++;
 		lastfree = 0;
 		if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
-			addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+			addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 				(xfs_dir2_data_aoff_t)
 				((char *)dep - (char *)d));
 			hash = xfs_da_hashname((char *)dep->name, dep->namelen);
@@ -147,7 +147,7 @@
 			}
 			ASSERT(i < be32_to_cpu(btp->count));
 		}
-		p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+		p += xfs_dir2_data_entsize(dep->namelen);
 	}
 	/*
 	 * Need to have seen all the entries and all the bestfree slots.
@@ -346,8 +346,8 @@
 	 */
 	p = (char *)d->u;
 	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
-		btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
-		endp = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
+		btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+		endp = (char *)xfs_dir2_block_leaf_p(btp);
 	} else
 		endp = (char *)d + mp->m_dirblksize;
 	/*
@@ -360,7 +360,7 @@
 		 */
 		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
 			ASSERT((char *)dup - (char *)d ==
-			       be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
+			       be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
 			xfs_dir2_data_freeinsert(d, dup, loghead);
 			p += be16_to_cpu(dup->length);
 		}
@@ -370,8 +370,8 @@
 		else {
 			dep = (xfs_dir2_data_entry_t *)p;
 			ASSERT((char *)dep - (char *)d ==
-			       be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)));
-			p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+			       be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)));
+			p += xfs_dir2_data_entsize(dep->namelen);
 		}
 	}
 }
@@ -402,7 +402,7 @@
 	/*
 	 * Get the buffer set up for the block.
 	 */
-	error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, blkno), -1, &bp,
+	error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, blkno), -1, &bp,
 		XFS_DATA_FORK);
 	if (error) {
 		return error;
@@ -427,7 +427,7 @@
 	t=mp->m_dirblksize - (uint)sizeof(d->hdr);
 	d->hdr.bestfree[0].length = cpu_to_be16(t);
 	dup->length = cpu_to_be16(t);
-	*XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16((char *)dup - (char *)d);
+	*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)d);
 	/*
 	 * Log it and return it.
 	 */
@@ -452,7 +452,7 @@
 	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
 	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
 	xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)d),
-		(uint)((char *)(XFS_DIR2_DATA_ENTRY_TAG_P(dep) + 1) -
+		(uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -
 		       (char *)d - 1));
 }
 
@@ -497,8 +497,8 @@
 	 * Log the end (tag) of the unused entry.
 	 */
 	xfs_da_log_buf(tp, bp,
-		(uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d),
-		(uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d +
+		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d),
+		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d +
 		       sizeof(xfs_dir2_data_off_t) - 1));
 }
 
@@ -535,8 +535,8 @@
 		xfs_dir2_block_tail_t	*btp;	/* block tail */
 
 		ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
-		btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
-		endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
+		btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+		endptr = (char *)xfs_dir2_block_leaf_p(btp);
 	}
 	/*
 	 * If this isn't the start of the block, then back up to
@@ -587,7 +587,7 @@
 		 * Fix up the new big freespace.
 		 */
 		be16_add(&prevdup->length, len + be16_to_cpu(postdup->length));
-		*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
+		*xfs_dir2_data_unused_tag_p(prevdup) =
 			cpu_to_be16((char *)prevdup - (char *)d);
 		xfs_dir2_data_log_unused(tp, bp, prevdup);
 		if (!needscan) {
@@ -621,7 +621,7 @@
 	else if (prevdup) {
 		dfp = xfs_dir2_data_freefind(d, prevdup);
 		be16_add(&prevdup->length, len);
-		*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
+		*xfs_dir2_data_unused_tag_p(prevdup) =
 			cpu_to_be16((char *)prevdup - (char *)d);
 		xfs_dir2_data_log_unused(tp, bp, prevdup);
 		/*
@@ -649,7 +649,7 @@
 		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
 		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 		newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
-		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+		*xfs_dir2_data_unused_tag_p(newdup) =
 			cpu_to_be16((char *)newdup - (char *)d);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
 		/*
@@ -676,7 +676,7 @@
 		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
 		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 		newdup->length = cpu_to_be16(len);
-		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+		*xfs_dir2_data_unused_tag_p(newdup) =
 			cpu_to_be16((char *)newdup - (char *)d);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
 		(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
@@ -712,7 +712,7 @@
 	ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
 	ASSERT(offset >= (char *)dup - (char *)d);
 	ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)d);
-	ASSERT((char *)dup - (char *)d == be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
+	ASSERT((char *)dup - (char *)d == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
 	/*
 	 * Look up the entry in the bestfree table.
 	 */
@@ -745,7 +745,7 @@
 		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
 		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 		newdup->length = cpu_to_be16(oldlen - len);
-		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+		*xfs_dir2_data_unused_tag_p(newdup) =
 			cpu_to_be16((char *)newdup - (char *)d);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
 		/*
@@ -772,7 +772,7 @@
 	else if (matchback) {
 		newdup = dup;
 		newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
-		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+		*xfs_dir2_data_unused_tag_p(newdup) =
 			cpu_to_be16((char *)newdup - (char *)d);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
 		/*
@@ -799,13 +799,13 @@
 	else {
 		newdup = dup;
 		newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
-		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+		*xfs_dir2_data_unused_tag_p(newdup) =
 			cpu_to_be16((char *)newdup - (char *)d);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
 		newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
 		newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 		newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
-		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup2) =
+		*xfs_dir2_data_unused_tag_p(newdup2) =
 			cpu_to_be16((char *)newdup2 - (char *)d);
 		xfs_dir2_data_log_unused(tp, bp, newdup2);
 		/*
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
index c94c909..b816e02 100644
--- a/fs/xfs/xfs_dir2_data.h
+++ b/fs/xfs/xfs_dir2_data.h
@@ -44,7 +44,7 @@
 #define	XFS_DIR2_DATA_SPACE	0
 #define	XFS_DIR2_DATA_OFFSET	(XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
 #define	XFS_DIR2_DATA_FIRSTDB(mp)	\
-	XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATA_OFFSET)
+	xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
 
 /*
  * Offsets of . and .. in data space (always block 0)
@@ -52,9 +52,9 @@
 #define	XFS_DIR2_DATA_DOT_OFFSET	\
 	((xfs_dir2_data_aoff_t)sizeof(xfs_dir2_data_hdr_t))
 #define	XFS_DIR2_DATA_DOTDOT_OFFSET	\
-	(XFS_DIR2_DATA_DOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(1))
+	(XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1))
 #define	XFS_DIR2_DATA_FIRST_OFFSET		\
-	(XFS_DIR2_DATA_DOTDOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(2))
+	(XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2))
 
 /*
  * Structures.
@@ -123,7 +123,6 @@
 /*
  * Size of a data entry.
  */
-#define XFS_DIR2_DATA_ENTSIZE(n)	xfs_dir2_data_entsize(n)
 static inline int xfs_dir2_data_entsize(int n)
 {
 	return (int)roundup(offsetof(xfs_dir2_data_entry_t, name[0]) + (n) + \
@@ -133,19 +132,16 @@
 /*
  * Pointer to an entry's tag word.
  */
-#define	XFS_DIR2_DATA_ENTRY_TAG_P(dep)	xfs_dir2_data_entry_tag_p(dep)
 static inline __be16 *
 xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep)
 {
 	return (__be16 *)((char *)dep +
-		XFS_DIR2_DATA_ENTSIZE(dep->namelen) - sizeof(__be16));
+		xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
 }
 
 /*
  * Pointer to a freespace's tag word.
  */
-#define	XFS_DIR2_DATA_UNUSED_TAG_P(dup) \
-	xfs_dir2_data_unused_tag_p(dup)
 static inline __be16 *
 xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup)
 {
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index db14ea7..1b73c9a 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -92,7 +92,7 @@
 	if ((error = xfs_da_grow_inode(args, &blkno))) {
 		return error;
 	}
-	ldb = XFS_DIR2_DA_TO_DB(mp, blkno);
+	ldb = xfs_dir2_da_to_db(mp, blkno);
 	ASSERT(ldb == XFS_DIR2_LEAF_FIRSTDB(mp));
 	/*
 	 * Initialize the leaf block, get a buffer for it.
@@ -104,8 +104,8 @@
 	leaf = lbp->data;
 	block = dbp->data;
 	xfs_dir2_data_check(dp, dbp);
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	btp = xfs_dir2_block_tail_p(mp, block);
+	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Set the counts in the leaf header.
 	 */
@@ -137,9 +137,9 @@
 	/*
 	 * Set up leaf tail and bests table.
 	 */
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	ltp->bestcount = cpu_to_be32(1);
-	bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
+	bestsp = xfs_dir2_leaf_bests_p(ltp);
 	bestsp[0] =  block->hdr.bestfree[0].length;
 	/*
 	 * Log the data header and leaf bests table.
@@ -209,9 +209,9 @@
 	 */
 	index = xfs_dir2_leaf_search_hash(args, lbp);
 	leaf = lbp->data;
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
-	bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
-	length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+	bestsp = xfs_dir2_leaf_bests_p(ltp);
+	length = xfs_dir2_data_entsize(args->namelen);
 	/*
 	 * See if there are any entries with the same hash value
 	 * and space in their block for the new entry.
@@ -223,7 +223,7 @@
 	     index++, lep++) {
 		if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
 			continue;
-		i = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+		i = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
 		ASSERT(i < be32_to_cpu(ltp->bestcount));
 		ASSERT(be16_to_cpu(bestsp[i]) != NULLDATAOFF);
 		if (be16_to_cpu(bestsp[i]) >= length) {
@@ -378,7 +378,7 @@
 	 */
 	else {
 		if ((error =
-		    xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, use_block),
+		    xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, use_block),
 			    -1, &dbp, XFS_DATA_FORK))) {
 			xfs_da_brelse(tp, lbp);
 			return error;
@@ -407,7 +407,7 @@
 	dep->inumber = cpu_to_be64(args->inumber);
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, dep->namelen);
-	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+	tagp = xfs_dir2_data_entry_tag_p(dep);
 	*tagp = cpu_to_be16((char *)dep - (char *)data);
 	/*
 	 * Need to scan fix up the bestfree table.
@@ -529,7 +529,7 @@
 	 * Fill in the new leaf entry.
 	 */
 	lep->hashval = cpu_to_be32(args->hashval);
-	lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp, use_block,
+	lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, use_block,
 				be16_to_cpu(*tagp)));
 	/*
 	 * Log the leaf fields and give up the buffers.
@@ -567,13 +567,13 @@
 	 * Should factor in the size of the bests table as well.
 	 * We can deduce a value for that from di_size.
 	 */
-	ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp));
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+	ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	/*
 	 * Leaves and bests don't overlap.
 	 */
 	ASSERT((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <=
-	       (char *)XFS_DIR2_LEAF_BESTS_P(ltp));
+	       (char *)xfs_dir2_leaf_bests_p(ltp));
 	/*
 	 * Check hash value order, count stale entries.
 	 */
@@ -815,12 +815,12 @@
 	 * Inside the loop we keep the main offset value as a byte offset
 	 * in the directory file.
 	 */
-	curoff = XFS_DIR2_DATAPTR_TO_BYTE(mp, uio->uio_offset);
+	curoff = xfs_dir2_dataptr_to_byte(mp, uio->uio_offset);
 	/*
 	 * Force this conversion through db so we truncate the offset
 	 * down to get the start of the data block.
 	 */
-	map_off = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, curoff));
+	map_off = xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, curoff));
 	/*
 	 * Loop over directory entries until we reach the end offset.
 	 * Get more blocks and readahead as necessary.
@@ -870,7 +870,7 @@
 			 */
 			if (1 + ra_want > map_blocks &&
 			    map_off <
-			    XFS_DIR2_BYTE_TO_DA(mp, XFS_DIR2_LEAF_OFFSET)) {
+			    xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) {
 				/*
 				 * Get more bmaps, fill in after the ones
 				 * we already have in the table.
@@ -878,7 +878,7 @@
 				nmap = map_size - map_valid;
 				error = xfs_bmapi(tp, dp,
 					map_off,
-					XFS_DIR2_BYTE_TO_DA(mp,
+					xfs_dir2_byte_to_da(mp,
 						XFS_DIR2_LEAF_OFFSET) - map_off,
 					XFS_BMAPI_METADATA, NULL, 0,
 					&map[map_valid], &nmap, NULL, NULL);
@@ -903,7 +903,7 @@
 					map[map_valid + nmap - 1].br_blockcount;
 				else
 					map_off =
-						XFS_DIR2_BYTE_TO_DA(mp,
+						xfs_dir2_byte_to_da(mp,
 							XFS_DIR2_LEAF_OFFSET);
 				/*
 				 * Look for holes in the mapping, and
@@ -931,14 +931,14 @@
 			 * No valid mappings, so no more data blocks.
 			 */
 			if (!map_valid) {
-				curoff = XFS_DIR2_DA_TO_BYTE(mp, map_off);
+				curoff = xfs_dir2_da_to_byte(mp, map_off);
 				break;
 			}
 			/*
 			 * Read the directory block starting at the first
 			 * mapping.
 			 */
-			curdb = XFS_DIR2_DA_TO_DB(mp, map->br_startoff);
+			curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
 			error = xfs_da_read_buf(tp, dp, map->br_startoff,
 				map->br_blockcount >= mp->m_dirblkfsbs ?
 				    XFS_FSB_TO_DADDR(mp, map->br_startblock) :
@@ -1014,7 +1014,7 @@
 			/*
 			 * Having done a read, we need to set a new offset.
 			 */
-			newoff = XFS_DIR2_DB_OFF_TO_BYTE(mp, curdb, 0);
+			newoff = xfs_dir2_db_off_to_byte(mp, curdb, 0);
 			/*
 			 * Start of the current block.
 			 */
@@ -1024,7 +1024,7 @@
 			 * Make sure we're in the right block.
 			 */
 			else if (curoff > newoff)
-				ASSERT(XFS_DIR2_BYTE_TO_DB(mp, curoff) ==
+				ASSERT(xfs_dir2_byte_to_db(mp, curoff) ==
 				       curdb);
 			data = bp->data;
 			xfs_dir2_data_check(dp, bp);
@@ -1032,7 +1032,7 @@
 			 * Find our position in the block.
 			 */
 			ptr = (char *)&data->u;
-			byteoff = XFS_DIR2_BYTE_TO_OFF(mp, curoff);
+			byteoff = xfs_dir2_byte_to_off(mp, curoff);
 			/*
 			 * Skip past the header.
 			 */
@@ -1054,15 +1054,15 @@
 					}
 					dep = (xfs_dir2_data_entry_t *)ptr;
 					length =
-					   XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+					   xfs_dir2_data_entsize(dep->namelen);
 					ptr += length;
 				}
 				/*
 				 * Now set our real offset.
 				 */
 				curoff =
-					XFS_DIR2_DB_OFF_TO_BYTE(mp,
-					    XFS_DIR2_BYTE_TO_DB(mp, curoff),
+					xfs_dir2_db_off_to_byte(mp,
+					    xfs_dir2_byte_to_db(mp, curoff),
 					    (char *)ptr - (char *)data);
 				if (ptr >= (char *)data + mp->m_dirblksize) {
 					continue;
@@ -1091,9 +1091,9 @@
 
 		p->namelen = dep->namelen;
 
-		length = XFS_DIR2_DATA_ENTSIZE(p->namelen);
+		length = xfs_dir2_data_entsize(p->namelen);
 
-		p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length);
+		p->cook = xfs_dir2_byte_to_dataptr(mp, curoff + length);
 
 		p->ino = be64_to_cpu(dep->inumber);
 #if XFS_BIG_INUMS
@@ -1121,10 +1121,10 @@
 	 * All done.  Set output offset value to current offset.
 	 */
 	*eofp = eof;
-	if (curoff > XFS_DIR2_DATAPTR_TO_BYTE(mp, XFS_DIR2_MAX_DATAPTR))
+	if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
 		uio->uio_offset = XFS_DIR2_MAX_DATAPTR;
 	else
-		uio->uio_offset = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff);
+		uio->uio_offset = xfs_dir2_byte_to_dataptr(mp, curoff);
 	kmem_free(map, map_size * sizeof(*map));
 	kmem_free(p, sizeof(*p));
 	if (bp)
@@ -1159,7 +1159,7 @@
 	/*
 	 * Get the buffer for the block.
 	 */
-	error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, bno), -1, &bp,
+	error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp,
 		XFS_DATA_FORK);
 	if (error) {
 		return error;
@@ -1181,7 +1181,7 @@
 	 * the block.
 	 */
 	if (magic == XFS_DIR2_LEAF1_MAGIC) {
-		ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+		ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 		ltp->bestcount = 0;
 		xfs_dir2_leaf_log_tail(tp, bp);
 	}
@@ -1206,9 +1206,9 @@
 
 	leaf = bp->data;
 	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
-	ltp = XFS_DIR2_LEAF_TAIL_P(tp->t_mountp, leaf);
-	firstb = XFS_DIR2_LEAF_BESTS_P(ltp) + first;
-	lastb = XFS_DIR2_LEAF_BESTS_P(ltp) + last;
+	ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf);
+	firstb = xfs_dir2_leaf_bests_p(ltp) + first;
+	lastb = xfs_dir2_leaf_bests_p(ltp) + last;
 	xfs_da_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf),
 		(uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1));
 }
@@ -1268,7 +1268,7 @@
 	mp = tp->t_mountp;
 	leaf = bp->data;
 	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	xfs_da_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf),
 		(uint)(mp->m_dirblksize - 1));
 }
@@ -1312,7 +1312,7 @@
 	 */
 	dep = (xfs_dir2_data_entry_t *)
 	      ((char *)dbp->data +
-	       XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
+	       xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
 	/*
 	 * Return the found inode number.
 	 */
@@ -1381,7 +1381,7 @@
 		/*
 		 * Get the new data block number.
 		 */
-		newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+		newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
 		/*
 		 * If it's not the same as the old data block number,
 		 * need to pitch the old one and read the new one.
@@ -1391,7 +1391,7 @@
 				xfs_da_brelse(tp, dbp);
 			if ((error =
 			    xfs_da_read_buf(tp, dp,
-				    XFS_DIR2_DB_TO_DA(mp, newdb), -1, &dbp,
+				    xfs_dir2_db_to_da(mp, newdb), -1, &dbp,
 				    XFS_DATA_FORK))) {
 				xfs_da_brelse(tp, lbp);
 				return error;
@@ -1404,7 +1404,7 @@
 		 */
 		dep = (xfs_dir2_data_entry_t *)
 		      ((char *)dbp->data +
-		       XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
+		       xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
 		/*
 		 * If it matches then return it.
 		 */
@@ -1469,20 +1469,20 @@
 	 * Point to the leaf entry, use that to point to the data entry.
 	 */
 	lep = &leaf->ents[index];
-	db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+	db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
 	dep = (xfs_dir2_data_entry_t *)
-	      ((char *)data + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
+	      ((char *)data + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
 	needscan = needlog = 0;
 	oldbest = be16_to_cpu(data->hdr.bestfree[0].length);
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
-	bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+	bestsp = xfs_dir2_leaf_bests_p(ltp);
 	ASSERT(be16_to_cpu(bestsp[db]) == oldbest);
 	/*
 	 * Mark the former data entry unused.
 	 */
 	xfs_dir2_data_make_free(tp, dbp,
 		(xfs_dir2_data_aoff_t)((char *)dep - (char *)data),
-		XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
+		xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
 	/*
 	 * We just mark the leaf entry stale by putting a null in it.
 	 */
@@ -1602,7 +1602,7 @@
 	 */
 	dep = (xfs_dir2_data_entry_t *)
 	      ((char *)dbp->data +
-	       XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
+	       xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
 	ASSERT(args->inumber != be64_to_cpu(dep->inumber));
 	/*
 	 * Put the new inode number in, log it.
@@ -1698,7 +1698,7 @@
 	/*
 	 * Read the offending data block.  We need its buffer.
 	 */
-	if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, db), -1, &dbp,
+	if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp,
 			XFS_DATA_FORK))) {
 		return error;
 	}
@@ -1712,7 +1712,7 @@
 	 */
 
 	leaf = lbp->data;
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) ==
 	       mp->m_dirblksize - (uint)sizeof(data->hdr));
 	ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);
@@ -1727,7 +1727,7 @@
 	/*
 	 * Eliminate the last bests entry from the table.
 	 */
-	bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
+	bestsp = xfs_dir2_leaf_bests_p(ltp);
 	be32_add(&ltp->bestcount, -1);
 	memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp));
 	xfs_dir2_leaf_log_tail(tp, lbp);
@@ -1838,12 +1838,12 @@
 	/*
 	 * Set up the leaf tail from the freespace block.
 	 */
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	ltp->bestcount = free->hdr.nvalid;
 	/*
 	 * Set up the leaf bests table.
 	 */
-	memcpy(XFS_DIR2_LEAF_BESTS_P(ltp), free->bests,
+	memcpy(xfs_dir2_leaf_bests_p(ltp), free->bests,
 		be32_to_cpu(ltp->bestcount) * sizeof(leaf->bests[0]));
 	xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
 	xfs_dir2_leaf_log_tail(tp, lbp);
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index f57ca116..70c97f3 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -32,7 +32,7 @@
 #define	XFS_DIR2_LEAF_SPACE	1
 #define	XFS_DIR2_LEAF_OFFSET	(XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
 #define	XFS_DIR2_LEAF_FIRSTDB(mp)	\
-	XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_LEAF_OFFSET)
+	xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
 
 /*
  * Offset in data space of a data entry.
@@ -82,7 +82,6 @@
  * DB blocks here are logical directory block numbers, not filesystem blocks.
  */
 
-#define	XFS_DIR2_MAX_LEAF_ENTS(mp)	xfs_dir2_max_leaf_ents(mp)
 static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
 {
 	return (int)(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_leaf_hdr_t)) /
@@ -92,7 +91,6 @@
 /*
  * Get address of the bestcount field in the single-leaf block.
  */
-#define	XFS_DIR2_LEAF_TAIL_P(mp,lp)	xfs_dir2_leaf_tail_p(mp, lp)
 static inline xfs_dir2_leaf_tail_t *
 xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp)
 {
@@ -104,7 +102,6 @@
 /*
  * Get address of the bests array in the single-leaf block.
  */
-#define	XFS_DIR2_LEAF_BESTS_P(ltp)	xfs_dir2_leaf_bests_p(ltp)
 static inline __be16 *
 xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
 {
@@ -114,7 +111,6 @@
 /*
  * Convert dataptr to byte in file space
  */
-#define	XFS_DIR2_DATAPTR_TO_BYTE(mp,dp)	xfs_dir2_dataptr_to_byte(mp, dp)
 static inline xfs_dir2_off_t
 xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
 {
@@ -124,7 +120,6 @@
 /*
  * Convert byte in file space to dataptr.  It had better be aligned.
  */
-#define	XFS_DIR2_BYTE_TO_DATAPTR(mp,by)	xfs_dir2_byte_to_dataptr(mp,by)
 static inline xfs_dir2_dataptr_t
 xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
 {
@@ -134,7 +129,6 @@
 /*
  * Convert byte in space to (DB) block
  */
-#define	XFS_DIR2_BYTE_TO_DB(mp,by)	xfs_dir2_byte_to_db(mp, by)
 static inline xfs_dir2_db_t
 xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
 {
@@ -145,17 +139,15 @@
 /*
  * Convert dataptr to a block number
  */
-#define	XFS_DIR2_DATAPTR_TO_DB(mp,dp)	xfs_dir2_dataptr_to_db(mp, dp)
 static inline xfs_dir2_db_t
 xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
 {
-	return XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
+	return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
 }
 
 /*
  * Convert byte in space to offset in a block
  */
-#define	XFS_DIR2_BYTE_TO_OFF(mp,by)	xfs_dir2_byte_to_off(mp, by)
 static inline xfs_dir2_data_aoff_t
 xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
 {
@@ -166,18 +158,15 @@
 /*
  * Convert dataptr to a byte offset in a block
  */
-#define	XFS_DIR2_DATAPTR_TO_OFF(mp,dp)	xfs_dir2_dataptr_to_off(mp, dp)
 static inline xfs_dir2_data_aoff_t
 xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
 {
-	return XFS_DIR2_BYTE_TO_OFF(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
+	return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
 }
 
 /*
  * Convert block and offset to byte in space
  */
-#define	XFS_DIR2_DB_OFF_TO_BYTE(mp,db,o)	\
-	xfs_dir2_db_off_to_byte(mp, db, o)
 static inline xfs_dir2_off_t
 xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
 			xfs_dir2_data_aoff_t o)
@@ -189,7 +178,6 @@
 /*
  * Convert block (DB) to block (dablk)
  */
-#define	XFS_DIR2_DB_TO_DA(mp,db)	xfs_dir2_db_to_da(mp, db)
 static inline xfs_dablk_t
 xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
 {
@@ -199,29 +187,25 @@
 /*
  * Convert byte in space to (DA) block
  */
-#define	XFS_DIR2_BYTE_TO_DA(mp,by)	xfs_dir2_byte_to_da(mp, by)
 static inline xfs_dablk_t
 xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
 {
-	return XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, by));
+	return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
 }
 
 /*
  * Convert block and offset to dataptr
  */
-#define	XFS_DIR2_DB_OFF_TO_DATAPTR(mp,db,o)	\
-	xfs_dir2_db_off_to_dataptr(mp, db, o)
 static inline xfs_dir2_dataptr_t
 xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
 			   xfs_dir2_data_aoff_t o)
 {
-	return XFS_DIR2_BYTE_TO_DATAPTR(mp, XFS_DIR2_DB_OFF_TO_BYTE(mp, db, o));
+	return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
 }
 
 /*
  * Convert block (dablk) to block (DB)
  */
-#define	XFS_DIR2_DA_TO_DB(mp,da)	xfs_dir2_da_to_db(mp, da)
 static inline xfs_dir2_db_t
 xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
 {
@@ -231,11 +215,10 @@
 /*
  * Convert block (dablk) to byte offset in space
  */
-#define XFS_DIR2_DA_TO_BYTE(mp,da)	xfs_dir2_da_to_byte(mp, da)
 static inline xfs_dir2_off_t
 xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
 {
-	return XFS_DIR2_DB_OFF_TO_BYTE(mp, XFS_DIR2_DA_TO_DB(mp, da), 0);
+	return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
 }
 
 /*
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index d083c38..91c61d9 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -136,14 +136,14 @@
 	/*
 	 * Get the buffer for the new freespace block.
 	 */
-	if ((error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fdb), -1, &fbp,
+	if ((error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp,
 			XFS_DATA_FORK))) {
 		return error;
 	}
 	ASSERT(fbp != NULL);
 	free = fbp->data;
 	leaf = lbp->data;
-	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	/*
 	 * Initialize the freespace block header.
 	 */
@@ -155,7 +155,7 @@
 	 * Copy freespace entries from the leaf block to the new block.
 	 * Count active entries.
 	 */
-	for (i = n = 0, from = XFS_DIR2_LEAF_BESTS_P(ltp), to = free->bests;
+	for (i = n = 0, from = xfs_dir2_leaf_bests_p(ltp), to = free->bests;
 	     i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
 		if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
 			n++;
@@ -215,7 +215,7 @@
 	 * a compact.
 	 */
 
-	if (be16_to_cpu(leaf->hdr.count) == XFS_DIR2_MAX_LEAF_ENTS(mp)) {
+	if (be16_to_cpu(leaf->hdr.count) == xfs_dir2_max_leaf_ents(mp)) {
 		if (!leaf->hdr.stale)
 			return XFS_ERROR(ENOSPC);
 		compact = be16_to_cpu(leaf->hdr.stale) > 1;
@@ -327,7 +327,7 @@
 	 * Insert the new entry, log everything.
 	 */
 	lep->hashval = cpu_to_be32(args->hashval);
-	lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp,
+	lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp,
 				args->blkno, args->index));
 	xfs_dir2_leaf_log_header(tp, bp);
 	xfs_dir2_leaf_log_ents(tp, bp, lfloglow, lfloghigh);
@@ -352,7 +352,7 @@
 	leaf = bp->data;
 	mp = dp->i_mount;
 	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
-	ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp));
+	ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
 	for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {
 		if (i + 1 < be16_to_cpu(leaf->hdr.count)) {
 			ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=
@@ -440,7 +440,7 @@
 	if (args->addname) {
 		curfdb = curbp ? state->extrablk.blkno : -1;
 		curdb = -1;
-		length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+		length = xfs_dir2_data_entsize(args->namelen);
 		if ((free = (curbp ? curbp->data : NULL)))
 			ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
 	}
@@ -465,7 +465,7 @@
 		/*
 		 * Pull the data block number from the entry.
 		 */
-		newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+		newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
 		/*
 		 * For addname, we're looking for a place to put the new entry.
 		 * We want to use a data block with an entry of equal
@@ -482,7 +482,7 @@
 				 * Convert the data block to the free block
 				 * holding its freespace information.
 				 */
-				newfdb = XFS_DIR2_DB_TO_FDB(mp, newdb);
+				newfdb = xfs_dir2_db_to_fdb(mp, newdb);
 				/*
 				 * If it's not the one we have in hand,
 				 * read it in.
@@ -497,7 +497,7 @@
 					 * Read the free block.
 					 */
 					if ((error = xfs_da_read_buf(tp, dp,
-							XFS_DIR2_DB_TO_DA(mp,
+							xfs_dir2_db_to_da(mp,
 								newfdb),
 							-1, &curbp,
 							XFS_DATA_FORK))) {
@@ -517,7 +517,7 @@
 				/*
 				 * Get the index for our entry.
 				 */
-				fi = XFS_DIR2_DB_TO_FDINDEX(mp, curdb);
+				fi = xfs_dir2_db_to_fdindex(mp, curdb);
 				/*
 				 * If it has room, return it.
 				 */
@@ -561,7 +561,7 @@
 				 */
 				if ((error =
 				    xfs_da_read_buf(tp, dp,
-					    XFS_DIR2_DB_TO_DA(mp, newdb), -1,
+					    xfs_dir2_db_to_da(mp, newdb), -1,
 					    &curbp, XFS_DATA_FORK))) {
 					return error;
 				}
@@ -573,7 +573,7 @@
 			 */
 			dep = (xfs_dir2_data_entry_t *)
 			      ((char *)curbp->data +
-			       XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
+			       xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
 			/*
 			 * Compare the entry, return it if it matches.
 			 */
@@ -876,9 +876,9 @@
 	/*
 	 * Extract the data block and offset from the entry.
 	 */
-	db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+	db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
 	ASSERT(dblk->blkno == db);
-	off = XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address));
+	off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address));
 	ASSERT(dblk->index == off);
 	/*
 	 * Kill the leaf entry by marking it stale.
@@ -898,7 +898,7 @@
 	longest = be16_to_cpu(data->hdr.bestfree[0].length);
 	needlog = needscan = 0;
 	xfs_dir2_data_make_free(tp, dbp, off,
-		XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
+		xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
 	/*
 	 * Rescan the data block freespaces for bestfree.
 	 * Log the data block header if needed.
@@ -924,8 +924,8 @@
 		 * Convert the data block number to a free block,
 		 * read in the free block.
 		 */
-		fdb = XFS_DIR2_DB_TO_FDB(mp, db);
-		if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fdb),
+		fdb = xfs_dir2_db_to_fdb(mp, db);
+		if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb),
 				-1, &fbp, XFS_DATA_FORK))) {
 			return error;
 		}
@@ -937,7 +937,7 @@
 		/*
 		 * Calculate which entry we need to fix.
 		 */
-		findex = XFS_DIR2_DB_TO_FDINDEX(mp, db);
+		findex = xfs_dir2_db_to_fdindex(mp, db);
 		longest = be16_to_cpu(data->hdr.bestfree[0].length);
 		/*
 		 * If the data block is now empty we can get rid of it
@@ -1073,7 +1073,7 @@
 	/*
 	 * Initialize the new leaf block.
 	 */
-	error = xfs_dir2_leaf_init(args, XFS_DIR2_DA_TO_DB(mp, blkno),
+	error = xfs_dir2_leaf_init(args, xfs_dir2_da_to_db(mp, blkno),
 		&newblk->bp, XFS_DIR2_LEAFN_MAGIC);
 	if (error) {
 		return error;
@@ -1385,7 +1385,7 @@
 	dp = args->dp;
 	mp = dp->i_mount;
 	tp = args->trans;
-	length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+	length = xfs_dir2_data_entsize(args->namelen);
 	/*
 	 * If we came in with a freespace block that means that lookup
 	 * found an entry with our hash value.  This is the freespace
@@ -1438,7 +1438,7 @@
 
 		if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK)))
 			return error;
-		lastfbno = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)fo);
+		lastfbno = xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo);
 		fbno = ifbno;
 	}
 	/*
@@ -1474,7 +1474,7 @@
 			 * to avoid it.
 			 */
 			if ((error = xfs_da_read_buf(tp, dp,
-					XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
+					xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
 					XFS_DATA_FORK))) {
 				return error;
 			}
@@ -1550,9 +1550,9 @@
 		 * Get the freespace block corresponding to the data block
 		 * that was just allocated.
 		 */
-		fbno = XFS_DIR2_DB_TO_FDB(mp, dbno);
+		fbno = xfs_dir2_db_to_fdb(mp, dbno);
 		if (unlikely(error = xfs_da_read_buf(tp, dp,
-				XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
+				xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
 				XFS_DATA_FORK))) {
 			xfs_da_buf_done(dbp);
 			return error;
@@ -1567,14 +1567,14 @@
 				return error;
 			}
 
-			if (unlikely(XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno)) {
+			if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
 				cmn_err(CE_ALERT,
 					"xfs_dir2_node_addname_int: dir ino "
 					"%llu needed freesp block %lld for\n"
 					"  data block %lld, got %lld\n"
 					"  ifbno %llu lastfbno %d\n",
 					(unsigned long long)dp->i_ino,
-					(long long)XFS_DIR2_DB_TO_FDB(mp, dbno),
+					(long long)xfs_dir2_db_to_fdb(mp, dbno),
 					(long long)dbno, (long long)fbno,
 					(unsigned long long)ifbno, lastfbno);
 				if (fblk) {
@@ -1598,7 +1598,7 @@
 			 * Get a buffer for the new block.
 			 */
 			if ((error = xfs_da_get_buf(tp, dp,
-						   XFS_DIR2_DB_TO_DA(mp, fbno),
+						   xfs_dir2_db_to_da(mp, fbno),
 						   -1, &fbp, XFS_DATA_FORK))) {
 				return error;
 			}
@@ -1623,7 +1623,7 @@
 		/*
 		 * Set the freespace block index from the data block number.
 		 */
-		findex = XFS_DIR2_DB_TO_FDINDEX(mp, dbno);
+		findex = xfs_dir2_db_to_fdindex(mp, dbno);
 		/*
 		 * If it's after the end of the current entries in the
 		 * freespace block, extend that table.
@@ -1669,7 +1669,7 @@
 		 * Read the data block in.
 		 */
 		if (unlikely(
-		    error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, dbno),
+		    error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno),
 				-1, &dbp, XFS_DATA_FORK))) {
 			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
 				xfs_da_buf_done(fbp);
@@ -1698,7 +1698,7 @@
 	dep->inumber = cpu_to_be64(args->inumber);
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, dep->namelen);
-	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+	tagp = xfs_dir2_data_entry_tag_p(dep);
 	*tagp = cpu_to_be16((char *)dep - (char *)data);
 	xfs_dir2_data_log_entry(tp, dbp, dep);
 	/*
@@ -1904,7 +1904,7 @@
 		ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);
 		dep = (xfs_dir2_data_entry_t *)
 		      ((char *)data +
-		       XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address)));
+		       xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address)));
 		ASSERT(inum != be64_to_cpu(dep->inumber));
 		/*
 		 * Fill in the new inode number and log the entry.
@@ -1980,7 +1980,7 @@
 	 * Blow the block away.
 	 */
 	if ((error =
-	    xfs_dir2_shrink_inode(args, XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)fo),
+	    xfs_dir2_shrink_inode(args, xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo),
 		    bp))) {
 		/*
 		 * Can't fail with ENOSPC since that only happens with no
diff --git a/fs/xfs/xfs_dir2_node.h b/fs/xfs/xfs_dir2_node.h
index c7c870e..dde72db 100644
--- a/fs/xfs/xfs_dir2_node.h
+++ b/fs/xfs/xfs_dir2_node.h
@@ -36,7 +36,7 @@
 #define	XFS_DIR2_FREE_SPACE	2
 #define	XFS_DIR2_FREE_OFFSET	(XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
 #define	XFS_DIR2_FREE_FIRSTDB(mp)	\
-	XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_FREE_OFFSET)
+	xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
 
 #define	XFS_DIR2_FREE_MAGIC	0x58443246	/* XD2F */
 
@@ -60,7 +60,6 @@
 /*
  * Convert data space db to the corresponding free db.
  */
-#define	XFS_DIR2_DB_TO_FDB(mp,db)	xfs_dir2_db_to_fdb(mp, db)
 static inline xfs_dir2_db_t
 xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
 {
@@ -70,7 +69,6 @@
 /*
  * Convert data space db to the corresponding index in a free db.
  */
-#define	XFS_DIR2_DB_TO_FDINDEX(mp,db)	xfs_dir2_db_to_fdindex(mp, db)
 static inline int
 xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
 {
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 0cd77b1..38fc4f2 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -89,8 +89,8 @@
 	mp = dp->i_mount;
 
 	count = i8count = namelen = 0;
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+	btp = xfs_dir2_block_tail_p(mp, block);
+	blp = xfs_dir2_block_leaf_p(btp);
 
 	/*
 	 * Iterate over the block's data entries by using the leaf pointers.
@@ -102,7 +102,7 @@
 		 * Calculate the pointer to the entry at hand.
 		 */
 		dep = (xfs_dir2_data_entry_t *)
-		      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
+		      ((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
 		/*
 		 * Detect . and .., so we can special-case them.
 		 * . is not included in sf directories.
@@ -124,7 +124,7 @@
 		/*
 		 * Calculate the new size, see if we should give up yet.
 		 */
-		size = XFS_DIR2_SF_HDR_SIZE(i8count) +		/* header */
+		size = xfs_dir2_sf_hdr_size(i8count) +		/* header */
 		       count +					/* namelen */
 		       count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
 		       namelen +				/* name */
@@ -139,7 +139,7 @@
 	 */
 	sfhp->count = count;
 	sfhp->i8count = i8count;
-	XFS_DIR2_SF_PUT_INUMBER((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
+	xfs_dir2_sf_put_inumber((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
 	return size;
 }
 
@@ -199,15 +199,15 @@
 	 * Copy the header into the newly allocate local space.
 	 */
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	memcpy(sfp, sfhp, XFS_DIR2_SF_HDR_SIZE(sfhp->i8count));
+	memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));
 	dp->i_d.di_size = size;
 	/*
 	 * Set up to loop over the block's entries.
 	 */
-	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, block);
 	ptr = (char *)block->u;
-	endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
-	sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+	endptr = (char *)xfs_dir2_block_leaf_p(btp);
+	sfep = xfs_dir2_sf_firstentry(sfp);
 	/*
 	 * Loop over the active and unused entries.
 	 * Stop when we reach the leaf/tail portion of the block.
@@ -233,22 +233,22 @@
 		else if (dep->namelen == 2 &&
 			 dep->name[0] == '.' && dep->name[1] == '.')
 			ASSERT(be64_to_cpu(dep->inumber) ==
-			       XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
+			       xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
 		/*
 		 * Normal entry, copy it into shortform.
 		 */
 		else {
 			sfep->namelen = dep->namelen;
-			XFS_DIR2_SF_PUT_OFFSET(sfep,
+			xfs_dir2_sf_put_offset(sfep,
 				(xfs_dir2_data_aoff_t)
 				((char *)dep - (char *)block));
 			memcpy(sfep->name, dep->name, dep->namelen);
 			temp = be64_to_cpu(dep->inumber);
-			XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
-				XFS_DIR2_SF_INUMBERP(sfep));
-			sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+			xfs_dir2_sf_put_inumber(sfp, &temp,
+				xfs_dir2_sf_inumberp(sfep));
+			sfep = xfs_dir2_sf_nextentry(sfp, sfep);
 		}
-		ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+		ptr += xfs_dir2_data_entsize(dep->namelen);
 	}
 	ASSERT((char *)sfep - (char *)sfp == size);
 	xfs_dir2_sf_check(args);
@@ -294,11 +294,11 @@
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
 	/*
 	 * Compute entry (and change in) size.
 	 */
-	add_entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
+	add_entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
 	incr_isize = add_entsize;
 	objchange = 0;
 #if XFS_BIG_INUMS
@@ -392,7 +392,7 @@
 	/*
 	 * Grow the in-inode space.
 	 */
-	xfs_idata_realloc(dp, XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen),
+	xfs_idata_realloc(dp, xfs_dir2_sf_entsize_byname(sfp, args->namelen),
 		XFS_DATA_FORK);
 	/*
 	 * Need to set up again due to realloc of the inode data.
@@ -403,10 +403,10 @@
 	 * Fill in the new entry.
 	 */
 	sfep->namelen = args->namelen;
-	XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
+	xfs_dir2_sf_put_offset(sfep, offset);
 	memcpy(sfep->name, args->name, sfep->namelen);
-	XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
-		XFS_DIR2_SF_INUMBERP(sfep));
+	xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+		xfs_dir2_sf_inumberp(sfep));
 	/*
 	 * Update the header and inode.
 	 */
@@ -463,14 +463,14 @@
 	 * If it's going to end up at the end then oldsfep will point there.
 	 */
 	for (offset = XFS_DIR2_DATA_FIRST_OFFSET,
-	      oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp),
-	      add_datasize = XFS_DIR2_DATA_ENTSIZE(args->namelen),
+	      oldsfep = xfs_dir2_sf_firstentry(oldsfp),
+	      add_datasize = xfs_dir2_data_entsize(args->namelen),
 	      eof = (char *)oldsfep == &buf[old_isize];
 	     !eof;
-	     offset = new_offset + XFS_DIR2_DATA_ENTSIZE(oldsfep->namelen),
-	      oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep),
+	     offset = new_offset + xfs_dir2_data_entsize(oldsfep->namelen),
+	      oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep),
 	      eof = (char *)oldsfep == &buf[old_isize]) {
-		new_offset = XFS_DIR2_SF_GET_OFFSET(oldsfep);
+		new_offset = xfs_dir2_sf_get_offset(oldsfep);
 		if (offset + add_datasize <= new_offset)
 			break;
 	}
@@ -495,10 +495,10 @@
 	 * Fill in the new entry, and update the header counts.
 	 */
 	sfep->namelen = args->namelen;
-	XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
+	xfs_dir2_sf_put_offset(sfep, offset);
 	memcpy(sfep->name, args->name, sfep->namelen);
-	XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
-		XFS_DIR2_SF_INUMBERP(sfep));
+	xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+		xfs_dir2_sf_inumberp(sfep));
 	sfp->hdr.count++;
 #if XFS_BIG_INUMS
 	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
@@ -508,7 +508,7 @@
 	 * If there's more left to copy, do that.
 	 */
 	if (!eof) {
-		sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+		sfep = xfs_dir2_sf_nextentry(sfp, sfep);
 		memcpy(sfep, oldsfep, old_isize - nbytes);
 	}
 	kmem_free(buf, old_isize);
@@ -544,9 +544,9 @@
 	mp = dp->i_mount;
 
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	size = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+	size = xfs_dir2_data_entsize(args->namelen);
 	offset = XFS_DIR2_DATA_FIRST_OFFSET;
-	sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+	sfep = xfs_dir2_sf_firstentry(sfp);
 	holefit = 0;
 	/*
 	 * Loop over sf entries.
@@ -555,10 +555,10 @@
 	 */
 	for (i = 0; i < sfp->hdr.count; i++) {
 		if (!holefit)
-			holefit = offset + size <= XFS_DIR2_SF_GET_OFFSET(sfep);
-		offset = XFS_DIR2_SF_GET_OFFSET(sfep) +
-			 XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
-		sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+			holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
+		offset = xfs_dir2_sf_get_offset(sfep) +
+			 xfs_dir2_data_entsize(sfep->namelen);
+		sfep = xfs_dir2_sf_nextentry(sfp, sfep);
 	}
 	/*
 	 * Calculate data bytes used excluding the new entry, if this
@@ -617,18 +617,18 @@
 
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
 	offset = XFS_DIR2_DATA_FIRST_OFFSET;
-	ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+	ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
 	i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
 
-	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
 	     i < sfp->hdr.count;
-	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
-		ASSERT(XFS_DIR2_SF_GET_OFFSET(sfep) >= offset);
-		ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
+	     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
+		ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
+		ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
 		i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
 		offset =
-			XFS_DIR2_SF_GET_OFFSET(sfep) +
-			XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
+			xfs_dir2_sf_get_offset(sfep) +
+			xfs_dir2_data_entsize(sfep->namelen);
 	}
 	ASSERT(i8count == sfp->hdr.i8count);
 	ASSERT(XFS_BIG_INUMS || i8count == 0);
@@ -671,7 +671,7 @@
 	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
 	ASSERT(dp->i_df.if_bytes == 0);
 	i8count = pino > XFS_DIR2_MAX_SHORT_INUM;
-	size = XFS_DIR2_SF_HDR_SIZE(i8count);
+	size = xfs_dir2_sf_hdr_size(i8count);
 	/*
 	 * Make a buffer for the data.
 	 */
@@ -684,7 +684,7 @@
 	/*
 	 * Now can put in the inode number, since i8count is set.
 	 */
-	XFS_DIR2_SF_PUT_INUMBER(sfp, &pino, &sfp->hdr.parent);
+	xfs_dir2_sf_put_inumber(sfp, &pino, &sfp->hdr.parent);
 	sfp->hdr.count = 0;
 	dp->i_d.di_size = size;
 	xfs_dir2_sf_check(args);
@@ -727,12 +727,12 @@
 
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
 
-	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
 
 	/*
 	 * If the block number in the offset is out of range, we're done.
 	 */
-	if (XFS_DIR2_DATAPTR_TO_DB(mp, dir_offset) > mp->m_dirdatablk) {
+	if (xfs_dir2_dataptr_to_db(mp, dir_offset) > mp->m_dirdatablk) {
 		*eofp = 1;
 		return 0;
 	}
@@ -747,9 +747,9 @@
 	 * Put . entry unless we're starting past it.
 	 */
 	if (dir_offset <=
-		    XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+		    xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 					       XFS_DIR2_DATA_DOT_OFFSET)) {
-		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, 0,
+		p.cook = xfs_dir2_db_off_to_dataptr(mp, 0,
 						XFS_DIR2_DATA_DOTDOT_OFFSET);
 		p.ino = dp->i_ino;
 #if XFS_BIG_INUMS
@@ -762,7 +762,7 @@
 
 		if (!p.done) {
 			uio->uio_offset =
-				XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+				xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 						XFS_DIR2_DATA_DOT_OFFSET);
 			return error;
 		}
@@ -772,11 +772,11 @@
 	 * Put .. entry unless we're starting past it.
 	 */
 	if (dir_offset <=
-		    XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+		    xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 					       XFS_DIR2_DATA_DOTDOT_OFFSET)) {
-		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+		p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 						XFS_DIR2_DATA_FIRST_OFFSET);
-		p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+		p.ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
 #if XFS_BIG_INUMS
 		p.ino += mp->m_inoadd;
 #endif
@@ -787,7 +787,7 @@
 
 		if (!p.done) {
 			uio->uio_offset =
-				XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+				xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 					XFS_DIR2_DATA_DOTDOT_OFFSET);
 			return error;
 		}
@@ -796,23 +796,23 @@
 	/*
 	 * Loop while there are more entries and put'ing works.
 	 */
-	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
 		     i < sfp->hdr.count;
-			     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
+			     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
 
-		off = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-				XFS_DIR2_SF_GET_OFFSET(sfep));
+		off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+				xfs_dir2_sf_get_offset(sfep));
 
 		if (dir_offset > off)
 			continue;
 
 		p.namelen = sfep->namelen;
 
-		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-			XFS_DIR2_SF_GET_OFFSET(sfep) +
-			XFS_DIR2_DATA_ENTSIZE(p.namelen));
+		p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+			xfs_dir2_sf_get_offset(sfep) +
+			xfs_dir2_data_entsize(p.namelen));
 
-		p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
+		p.ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
 #if XFS_BIG_INUMS
 		p.ino += mp->m_inoadd;
 #endif
@@ -832,7 +832,7 @@
 	*eofp = 1;
 
 	uio->uio_offset =
-		XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
+		xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
 
 	return 0;
 }
@@ -865,7 +865,7 @@
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
 	/*
 	 * Special case for .
 	 */
@@ -878,21 +878,21 @@
 	 */
 	if (args->namelen == 2 &&
 	    args->name[0] == '.' && args->name[1] == '.') {
-		args->inumber = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+		args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
 		return XFS_ERROR(EEXIST);
 	}
 	/*
 	 * Loop over all the entries trying to match ours.
 	 */
-	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
 	     i < sfp->hdr.count;
-	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
+	     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
 		if (sfep->namelen == args->namelen &&
 		    sfep->name[0] == args->name[0] &&
 		    memcmp(args->name, sfep->name, args->namelen) == 0) {
 			args->inumber =
-				XFS_DIR2_SF_GET_INUMBER(sfp,
-					XFS_DIR2_SF_INUMBERP(sfep));
+				xfs_dir2_sf_get_inumber(sfp,
+					xfs_dir2_sf_inumberp(sfep));
 			return XFS_ERROR(EEXIST);
 		}
 	}
@@ -934,19 +934,19 @@
 	ASSERT(dp->i_df.if_bytes == oldsize);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(oldsize >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+	ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
 	/*
 	 * Loop over the old directory entries.
 	 * Find the one we're deleting.
 	 */
-	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
 	     i < sfp->hdr.count;
-	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
+	     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
 		if (sfep->namelen == args->namelen &&
 		    sfep->name[0] == args->name[0] &&
 		    memcmp(sfep->name, args->name, args->namelen) == 0) {
-			ASSERT(XFS_DIR2_SF_GET_INUMBER(sfp,
-					XFS_DIR2_SF_INUMBERP(sfep)) ==
+			ASSERT(xfs_dir2_sf_get_inumber(sfp,
+					xfs_dir2_sf_inumberp(sfep)) ==
 				args->inumber);
 			break;
 		}
@@ -961,7 +961,7 @@
 	 * Calculate sizes.
 	 */
 	byteoff = (int)((char *)sfep - (char *)sfp);
-	entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
+	entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
 	newsize = oldsize - entsize;
 	/*
 	 * Copy the part if any after the removed entry, sliding it down.
@@ -1027,7 +1027,7 @@
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
 #if XFS_BIG_INUMS
 	/*
 	 * New inode number is large, and need to convert to 8-byte inodes.
@@ -1067,28 +1067,28 @@
 	if (args->namelen == 2 &&
 	    args->name[0] == '.' && args->name[1] == '.') {
 #if XFS_BIG_INUMS || defined(DEBUG)
-		ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+		ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
 		ASSERT(args->inumber != ino);
 #endif
-		XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber, &sfp->hdr.parent);
+		xfs_dir2_sf_put_inumber(sfp, &args->inumber, &sfp->hdr.parent);
 	}
 	/*
 	 * Normal entry, look for the name.
 	 */
 	else {
-		for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+		for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
 		     i < sfp->hdr.count;
-		     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
+		     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
 			if (sfep->namelen == args->namelen &&
 			    sfep->name[0] == args->name[0] &&
 			    memcmp(args->name, sfep->name, args->namelen) == 0) {
 #if XFS_BIG_INUMS || defined(DEBUG)
-				ino = XFS_DIR2_SF_GET_INUMBER(sfp,
-					XFS_DIR2_SF_INUMBERP(sfep));
+				ino = xfs_dir2_sf_get_inumber(sfp,
+					xfs_dir2_sf_inumberp(sfep));
 				ASSERT(args->inumber != ino);
 #endif
-				XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
-					XFS_DIR2_SF_INUMBERP(sfep));
+				xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+					xfs_dir2_sf_inumberp(sfep));
 				break;
 			}
 		}
@@ -1189,22 +1189,22 @@
 	 */
 	sfp->hdr.count = oldsfp->hdr.count;
 	sfp->hdr.i8count = 0;
-	ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
-	XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
+	ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
+	xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
 	/*
 	 * Copy the entries field by field.
 	 */
-	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
-		    oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
+	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
+		    oldsfep = xfs_dir2_sf_firstentry(oldsfp);
 	     i < sfp->hdr.count;
-	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
-		  oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
+	     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
+		  oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
 		sfep->namelen = oldsfep->namelen;
 		sfep->offset = oldsfep->offset;
 		memcpy(sfep->name, oldsfep->name, sfep->namelen);
-		ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
-			XFS_DIR2_SF_INUMBERP(oldsfep));
-		XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
+		ino = xfs_dir2_sf_get_inumber(oldsfp,
+			xfs_dir2_sf_inumberp(oldsfep));
+		xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
 	}
 	/*
 	 * Clean up the inode.
@@ -1266,22 +1266,22 @@
 	 */
 	sfp->hdr.count = oldsfp->hdr.count;
 	sfp->hdr.i8count = 1;
-	ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
-	XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
+	ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
+	xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
 	/*
 	 * Copy the entries field by field.
 	 */
-	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
-		    oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
+	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
+		    oldsfep = xfs_dir2_sf_firstentry(oldsfp);
 	     i < sfp->hdr.count;
-	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
-		  oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
+	     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
+		  oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
 		sfep->namelen = oldsfep->namelen;
 		sfep->offset = oldsfep->offset;
 		memcpy(sfep->name, oldsfep->name, sfep->namelen);
-		ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
-			XFS_DIR2_SF_INUMBERP(oldsfep));
-		XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
+		ino = xfs_dir2_sf_get_inumber(oldsfp,
+			xfs_dir2_sf_inumberp(oldsfep));
+		xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
 	}
 	/*
 	 * Clean up the inode.
diff --git a/fs/xfs/xfs_dir2_sf.h b/fs/xfs/xfs_dir2_sf.h
index 42f015b..11e5032 100644
--- a/fs/xfs/xfs_dir2_sf.h
+++ b/fs/xfs/xfs_dir2_sf.h
@@ -90,7 +90,6 @@
 	xfs_dir2_sf_entry_t	list[1];	/* shortform entries */
 } xfs_dir2_sf_t;
 
-#define	XFS_DIR2_SF_HDR_SIZE(i8count)	xfs_dir2_sf_hdr_size(i8count)
 static inline int xfs_dir2_sf_hdr_size(int i8count)
 {
 	return ((uint)sizeof(xfs_dir2_sf_hdr_t) - \
@@ -98,14 +97,11 @@
 		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
 }
 
-#define	XFS_DIR2_SF_INUMBERP(sfep)	xfs_dir2_sf_inumberp(sfep)
 static inline xfs_dir2_inou_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep)
 {
 	return (xfs_dir2_inou_t *)&(sfep)->name[(sfep)->namelen];
 }
 
-#define	XFS_DIR2_SF_GET_INUMBER(sfp, from) \
-	xfs_dir2_sf_get_inumber(sfp, from)
 static inline xfs_intino_t
 xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from)
 {
@@ -114,8 +110,6 @@
 		(xfs_intino_t)XFS_GET_DIR_INO8((from)->i8));
 }
 
-#define	XFS_DIR2_SF_PUT_INUMBER(sfp,from,to) \
-	xfs_dir2_sf_put_inumber(sfp,from,to)
 static inline void xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
 						xfs_dir2_inou_t *to)
 {
@@ -125,24 +119,18 @@
 		XFS_PUT_DIR_INO8(*(from), (to)->i8);
 }
 
-#define	XFS_DIR2_SF_GET_OFFSET(sfep)	\
-	xfs_dir2_sf_get_offset(sfep)
 static inline xfs_dir2_data_aoff_t
 xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
 {
 	return INT_GET_UNALIGNED_16_BE(&(sfep)->offset.i);
 }
 
-#define	XFS_DIR2_SF_PUT_OFFSET(sfep,off) \
-	xfs_dir2_sf_put_offset(sfep,off)
 static inline void
 xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
 {
 	INT_SET_UNALIGNED_16_BE(&(sfep)->offset.i, off);
 }
 
-#define XFS_DIR2_SF_ENTSIZE_BYNAME(sfp,len)	\
-	xfs_dir2_sf_entsize_byname(sfp,len)
 static inline int xfs_dir2_sf_entsize_byname(xfs_dir2_sf_t *sfp, int len)
 {
 	return ((uint)sizeof(xfs_dir2_sf_entry_t) - 1 + (len) - \
@@ -150,8 +138,6 @@
 		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
 }
 
-#define XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,sfep)	\
-	xfs_dir2_sf_entsize_byentry(sfp,sfep)
 static inline int
 xfs_dir2_sf_entsize_byentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
 {
@@ -160,19 +146,17 @@
 		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
 }
 
-#define XFS_DIR2_SF_FIRSTENTRY(sfp)	xfs_dir2_sf_firstentry(sfp)
 static inline xfs_dir2_sf_entry_t *xfs_dir2_sf_firstentry(xfs_dir2_sf_t *sfp)
 {
 	return ((xfs_dir2_sf_entry_t *) \
-		((char *)(sfp) + XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count)));
+		((char *)(sfp) + xfs_dir2_sf_hdr_size(sfp->hdr.i8count)));
 }
 
-#define XFS_DIR2_SF_NEXTENTRY(sfp,sfep)	xfs_dir2_sf_nextentry(sfp,sfep)
 static inline xfs_dir2_sf_entry_t *
 xfs_dir2_sf_nextentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
 {
 	return ((xfs_dir2_sf_entry_t *) \
-		((char *)(sfep) + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,sfep)));
+		((char *)(sfep) + xfs_dir2_sf_entsize_byentry(sfp,sfep)));
 }
 
 /*
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
new file mode 100644
index 0000000..ce22786
--- /dev/null
+++ b/fs/xfs/xfs_filestream.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2006-2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "xfs.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_inum.h"
+#include "xfs_dir2.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_ag.h"
+#include "xfs_dmapi.h"
+#include "xfs_log.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_bmap.h"
+#include "xfs_alloc.h"
+#include "xfs_utils.h"
+#include "xfs_mru_cache.h"
+#include "xfs_filestream.h"
+
+#ifdef XFS_FILESTREAMS_TRACE
+
+ktrace_t *xfs_filestreams_trace_buf;
+
+STATIC void
+xfs_filestreams_trace(
+	xfs_mount_t	*mp,	/* mount point */
+	int		type,	/* type of trace */
+	const char	*func,	/* source function */
+	int		line,	/* source line number */
+	__psunsigned_t	arg0,
+	__psunsigned_t	arg1,
+	__psunsigned_t	arg2,
+	__psunsigned_t	arg3,
+	__psunsigned_t	arg4,
+	__psunsigned_t	arg5)
+{
+	ktrace_enter(xfs_filestreams_trace_buf,
+		(void *)(__psint_t)(type | (line << 16)),
+		(void *)func,
+		(void *)(__psunsigned_t)current_pid(),
+		(void *)mp,
+		(void *)(__psunsigned_t)arg0,
+		(void *)(__psunsigned_t)arg1,
+		(void *)(__psunsigned_t)arg2,
+		(void *)(__psunsigned_t)arg3,
+		(void *)(__psunsigned_t)arg4,
+		(void *)(__psunsigned_t)arg5,
+		NULL, NULL, NULL, NULL, NULL, NULL);
+}
+
+#define TRACE0(mp,t)			TRACE6(mp,t,0,0,0,0,0,0)
+#define TRACE1(mp,t,a0)			TRACE6(mp,t,a0,0,0,0,0,0)
+#define TRACE2(mp,t,a0,a1)		TRACE6(mp,t,a0,a1,0,0,0,0)
+#define TRACE3(mp,t,a0,a1,a2)		TRACE6(mp,t,a0,a1,a2,0,0,0)
+#define TRACE4(mp,t,a0,a1,a2,a3)	TRACE6(mp,t,a0,a1,a2,a3,0,0)
+#define TRACE5(mp,t,a0,a1,a2,a3,a4)	TRACE6(mp,t,a0,a1,a2,a3,a4,0)
+#define TRACE6(mp,t,a0,a1,a2,a3,a4,a5) \
+	xfs_filestreams_trace(mp, t, __FUNCTION__, __LINE__, \
+				(__psunsigned_t)a0, (__psunsigned_t)a1, \
+				(__psunsigned_t)a2, (__psunsigned_t)a3, \
+				(__psunsigned_t)a4, (__psunsigned_t)a5)
+
+#define TRACE_AG_SCAN(mp, ag, ag2) \
+		TRACE2(mp, XFS_FSTRM_KTRACE_AGSCAN, ag, ag2);
+#define TRACE_AG_PICK1(mp, max_ag, maxfree) \
+		TRACE2(mp, XFS_FSTRM_KTRACE_AGPICK1, max_ag, maxfree);
+#define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag) \
+		TRACE6(mp, XFS_FSTRM_KTRACE_AGPICK2, ag, ag2, \
+			 cnt, free, scan, flag)
+#define TRACE_UPDATE(mp, ip, ag, cnt, ag2, cnt2) \
+		TRACE5(mp, XFS_FSTRM_KTRACE_UPDATE, ip, ag, cnt, ag2, cnt2)
+#define TRACE_FREE(mp, ip, pip, ag, cnt) \
+		TRACE4(mp, XFS_FSTRM_KTRACE_FREE, ip, pip, ag, cnt)
+#define TRACE_LOOKUP(mp, ip, pip, ag, cnt) \
+		TRACE4(mp, XFS_FSTRM_KTRACE_ITEM_LOOKUP, ip, pip, ag, cnt)
+#define TRACE_ASSOCIATE(mp, ip, pip, ag, cnt) \
+		TRACE4(mp, XFS_FSTRM_KTRACE_ASSOCIATE, ip, pip, ag, cnt)
+#define TRACE_MOVEAG(mp, ip, pip, oag, ocnt, nag, ncnt) \
+		TRACE6(mp, XFS_FSTRM_KTRACE_MOVEAG, ip, pip, oag, ocnt, nag, ncnt)
+#define TRACE_ORPHAN(mp, ip, ag) \
+		TRACE2(mp, XFS_FSTRM_KTRACE_ORPHAN, ip, ag);
+
+
+#else
+#define TRACE_AG_SCAN(mp, ag, ag2)
+#define TRACE_AG_PICK1(mp, max_ag, maxfree)
+#define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag)
+#define TRACE_UPDATE(mp, ip, ag, cnt, ag2, cnt2)
+#define TRACE_FREE(mp, ip, pip, ag, cnt)
+#define TRACE_LOOKUP(mp, ip, pip, ag, cnt)
+#define TRACE_ASSOCIATE(mp, ip, pip, ag, cnt)
+#define TRACE_MOVEAG(mp, ip, pip, oag, ocnt, nag, ncnt)
+#define TRACE_ORPHAN(mp, ip, ag)
+#endif
+
+static kmem_zone_t *item_zone;
+
+/*
+ * Structure for associating a file or a directory with an allocation group.
+ * The parent directory pointer is only needed for files, but since there will
+ * generally be vastly more files than directories in the cache, using the same
+ * data structure simplifies the code with very little memory overhead.
+ */
+typedef struct fstrm_item
+{
+	xfs_agnumber_t	ag;	/* AG currently in use for the file/directory. */
+	xfs_inode_t	*ip;	/* inode self-pointer. */
+	xfs_inode_t	*pip;	/* Parent directory inode pointer. */
+} fstrm_item_t;
+
+
+/*
+ * Scan the AGs starting at startag looking for an AG that isn't in use and has
+ * at least minlen blocks free.
+ */
+static int
+_xfs_filestream_pick_ag(
+	xfs_mount_t	*mp,
+	xfs_agnumber_t	startag,
+	xfs_agnumber_t	*agp,
+	int		flags,
+	xfs_extlen_t	minlen)
+{
+	int		err, trylock, nscan;
+	xfs_extlen_t	delta, longest, need, free, minfree, maxfree = 0;
+	xfs_agnumber_t	ag, max_ag = NULLAGNUMBER;
+	struct xfs_perag *pag;
+
+	/* 2% of an AG's blocks must be free for it to be chosen. */
+	minfree = mp->m_sb.sb_agblocks / 50;
+
+	ag = startag;
+	*agp = NULLAGNUMBER;
+
+	/* For the first pass, don't sleep trying to init the per-AG. */
+	trylock = XFS_ALLOC_FLAG_TRYLOCK;
+
+	for (nscan = 0; 1; nscan++) {
+
+		TRACE_AG_SCAN(mp, ag, xfs_filestream_peek_ag(mp, ag));
+
+		pag = mp->m_perag + ag;
+
+		if (!pag->pagf_init) {
+			err = xfs_alloc_pagf_init(mp, NULL, ag, trylock);
+			if (err && !trylock)
+				return err;
+		}
+
+		/* Might fail sometimes during the 1st pass with trylock set. */
+		if (!pag->pagf_init)
+			goto next_ag;
+
+		/* Keep track of the AG with the most free blocks. */
+		if (pag->pagf_freeblks > maxfree) {
+			maxfree = pag->pagf_freeblks;
+			max_ag = ag;
+		}
+
+		/*
+		 * The AG reference count does two things: it enforces mutual
+		 * exclusion when examining the suitability of an AG in this
+		 * loop, and it guards against two filestreams being established
+		 * in the same AG as each other.
+		 */
+		if (xfs_filestream_get_ag(mp, ag) > 1) {
+			xfs_filestream_put_ag(mp, ag);
+			goto next_ag;
+		}
+
+		need = XFS_MIN_FREELIST_PAG(pag, mp);
+		delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
+		longest = (pag->pagf_longest > delta) ?
+		          (pag->pagf_longest - delta) :
+		          (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
+
+		if (((minlen && longest >= minlen) ||
+		     (!minlen && pag->pagf_freeblks >= minfree)) &&
+		    (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) ||
+		     (flags & XFS_PICK_LOWSPACE))) {
+
+			/* Break out, retaining the reference on the AG. */
+			free = pag->pagf_freeblks;
+			*agp = ag;
+			break;
+		}
+
+		/* Drop the reference on this AG, it's not usable. */
+		xfs_filestream_put_ag(mp, ag);
+next_ag:
+		/* Move to the next AG, wrapping to AG 0 if necessary. */
+		if (++ag >= mp->m_sb.sb_agcount)
+			ag = 0;
+
+		/* If a full pass of the AGs hasn't been done yet, continue. */
+		if (ag != startag)
+			continue;
+
+		/* Allow sleeping in xfs_alloc_pagf_init() on the 2nd pass. */
+		if (trylock != 0) {
+			trylock = 0;
+			continue;
+		}
+
+		/* Finally, if lowspace wasn't set, set it for the 3rd pass. */
+		if (!(flags & XFS_PICK_LOWSPACE)) {
+			flags |= XFS_PICK_LOWSPACE;
+			continue;
+		}
+
+		/*
+		 * Take the AG with the most free space, regardless of whether
+		 * it's already in use by another filestream.
+		 */
+		if (max_ag != NULLAGNUMBER) {
+			xfs_filestream_get_ag(mp, max_ag);
+			TRACE_AG_PICK1(mp, max_ag, maxfree);
+			free = maxfree;
+			*agp = max_ag;
+			break;
+		}
+
+		/* take AG 0 if none matched */
+		TRACE_AG_PICK1(mp, max_ag, maxfree);
+		*agp = 0;
+		return 0;
+	}
+
+	TRACE_AG_PICK2(mp, startag, *agp, xfs_filestream_peek_ag(mp, *agp),
+			free, nscan, flags);
+
+	return 0;
+}
+
+/*
+ * Set the allocation group number for a file or a directory, updating inode
+ * references and per-AG references as appropriate.  Must be called with the
+ * m_peraglock held in read mode.
+ */
+static int
+_xfs_filestream_update_ag(
+	xfs_inode_t	*ip,
+	xfs_inode_t	*pip,
+	xfs_agnumber_t	ag)
+{
+	int		err = 0;
+	xfs_mount_t	*mp;
+	xfs_mru_cache_t	*cache;
+	fstrm_item_t	*item;
+	xfs_agnumber_t	old_ag;
+	xfs_inode_t	*old_pip;
+
+	/*
+	 * Either ip is a regular file and pip is a directory, or ip is a
+	 * directory and pip is NULL.
+	 */
+	ASSERT(ip && (((ip->i_d.di_mode & S_IFREG) && pip &&
+	               (pip->i_d.di_mode & S_IFDIR)) ||
+	              ((ip->i_d.di_mode & S_IFDIR) && !pip)));
+
+	mp = ip->i_mount;
+	cache = mp->m_filestream;
+
+	item = xfs_mru_cache_lookup(cache, ip->i_ino);
+	if (item) {
+		ASSERT(item->ip == ip);
+		old_ag = item->ag;
+		item->ag = ag;
+		old_pip = item->pip;
+		item->pip = pip;
+		xfs_mru_cache_done(cache);
+
+		/*
+		 * If the AG has changed, drop the old ref and take a new one,
+		 * effectively transferring the reference from old to new AG.
+		 */
+		if (ag != old_ag) {
+			xfs_filestream_put_ag(mp, old_ag);
+			xfs_filestream_get_ag(mp, ag);
+		}
+
+		/*
+		 * If ip is a file and its pip has changed, drop the old ref and
+		 * take a new one.
+		 */
+		if (pip && pip != old_pip) {
+			IRELE(old_pip);
+			IHOLD(pip);
+		}
+
+		TRACE_UPDATE(mp, ip, old_ag, xfs_filestream_peek_ag(mp, old_ag),
+				ag, xfs_filestream_peek_ag(mp, ag));
+		return 0;
+	}
+
+	item = kmem_zone_zalloc(item_zone, KM_MAYFAIL);
+	if (!item)
+		return ENOMEM;
+
+	item->ag = ag;
+	item->ip = ip;
+	item->pip = pip;
+
+	err = xfs_mru_cache_insert(cache, ip->i_ino, item);
+	if (err) {
+		kmem_zone_free(item_zone, item);
+		return err;
+	}
+
+	/* Take a reference on the AG. */
+	xfs_filestream_get_ag(mp, ag);
+
+	/*
+	 * Take a reference on the inode itself regardless of whether it's a
+	 * regular file or a directory.
+	 */
+	IHOLD(ip);
+
+	/*
+	 * In the case of a regular file, take a reference on the parent inode
+	 * as well to ensure it remains in-core.
+	 */
+	if (pip)
+		IHOLD(pip);
+
+	TRACE_UPDATE(mp, ip, ag, xfs_filestream_peek_ag(mp, ag),
+			ag, xfs_filestream_peek_ag(mp, ag));
+
+	return 0;
+}
+
+/* xfs_fstrm_free_func(): callback for freeing cached stream items. */
+void
+xfs_fstrm_free_func(
+	xfs_ino_t	ino,
+	fstrm_item_t	*item)
+{
+	xfs_inode_t	*ip = item->ip;
+	int ref;
+
+	ASSERT(ip->i_ino == ino);
+
+	xfs_iflags_clear(ip, XFS_IFILESTREAM);
+
+	/* Drop the reference taken on the AG when the item was added. */
+	ref = xfs_filestream_put_ag(ip->i_mount, item->ag);
+
+	ASSERT(ref >= 0);
+	TRACE_FREE(ip->i_mount, ip, item->pip, item->ag,
+		xfs_filestream_peek_ag(ip->i_mount, item->ag));
+
+	/*
+	 * _xfs_filestream_update_ag() always takes a reference on the inode
+	 * itself, whether it's a file or a directory.  Release it here.
+	 * This can result in the inode being freed and so we must
+	 * not hold any inode locks when freeing filesstreams objects
+	 * otherwise we can deadlock here.
+	 */
+	IRELE(ip);
+
+	/*
+	 * In the case of a regular file, _xfs_filestream_update_ag() also
+	 * takes a ref on the parent inode to keep it in-core.  Release that
+	 * too.
+	 */
+	if (item->pip)
+		IRELE(item->pip);
+
+	/* Finally, free the memory allocated for the item. */
+	kmem_zone_free(item_zone, item);
+}
+
+/*
+ * xfs_filestream_init() is called at xfs initialisation time to set up the
+ * memory zone that will be used for filestream data structure allocation.
+ */
+int
+xfs_filestream_init(void)
+{
+	item_zone = kmem_zone_init(sizeof(fstrm_item_t), "fstrm_item");
+#ifdef XFS_FILESTREAMS_TRACE
+	xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_SLEEP);
+#endif
+	return item_zone ? 0 : -ENOMEM;
+}
+
+/*
+ * xfs_filestream_uninit() is called at xfs termination time to destroy the
+ * memory zone that was used for filestream data structure allocation.
+ */
+void
+xfs_filestream_uninit(void)
+{
+#ifdef XFS_FILESTREAMS_TRACE
+	ktrace_free(xfs_filestreams_trace_buf);
+#endif
+	kmem_zone_destroy(item_zone);
+}
+
+/*
+ * xfs_filestream_mount() is called when a file system is mounted with the
+ * filestream option.  It is responsible for allocating the data structures
+ * needed to track the new file system's file streams.
+ */
+int
+xfs_filestream_mount(
+	xfs_mount_t	*mp)
+{
+	int		err;
+	unsigned int	lifetime, grp_count;
+
+	/*
+	 * The filestream timer tunable is currently fixed within the range of
+	 * one second to four minutes, with five seconds being the default.  The
+	 * group count is somewhat arbitrary, but it'd be nice to adhere to the
+	 * timer tunable to within about 10 percent.  This requires at least 10
+	 * groups.
+	 */
+	lifetime  = xfs_fstrm_centisecs * 10;
+	grp_count = 10;
+
+	err = xfs_mru_cache_create(&mp->m_filestream, lifetime, grp_count,
+	                     (xfs_mru_cache_free_func_t)xfs_fstrm_free_func);
+
+	return err;
+}
+
+/*
+ * xfs_filestream_unmount() is called when a file system that was mounted with
+ * the filestream option is unmounted.  It drains the data structures created
+ * to track the file system's file streams and frees all the memory that was
+ * allocated.
+ */
+void
+xfs_filestream_unmount(
+	xfs_mount_t	*mp)
+{
+	xfs_mru_cache_destroy(mp->m_filestream);
+}
+
+/*
+ * If the mount point's m_perag array is going to be reallocated, all
+ * outstanding cache entries must be flushed to avoid accessing reference count
+ * addresses that have been freed.  The call to xfs_filestream_flush() must be
+ * made inside the block that holds the m_peraglock in write mode to do the
+ * reallocation.
+ */
+void
+xfs_filestream_flush(
+	xfs_mount_t	*mp)
+{
+	/* point in time flush, so keep the reaper running */
+	xfs_mru_cache_flush(mp->m_filestream, 1);
+}
+
+/*
+ * Return the AG of the filestream the file or directory belongs to, or
+ * NULLAGNUMBER otherwise.
+ */
+xfs_agnumber_t
+xfs_filestream_lookup_ag(
+	xfs_inode_t	*ip)
+{
+	xfs_mru_cache_t	*cache;
+	fstrm_item_t	*item;
+	xfs_agnumber_t	ag;
+	int		ref;
+
+	if (!(ip->i_d.di_mode & (S_IFREG | S_IFDIR))) {
+		ASSERT(0);
+		return NULLAGNUMBER;
+	}
+
+	cache = ip->i_mount->m_filestream;
+	item = xfs_mru_cache_lookup(cache, ip->i_ino);
+	if (!item) {
+		TRACE_LOOKUP(ip->i_mount, ip, NULL, NULLAGNUMBER, 0);
+		return NULLAGNUMBER;
+	}
+
+	ASSERT(ip == item->ip);
+	ag = item->ag;
+	ref = xfs_filestream_peek_ag(ip->i_mount, ag);
+	xfs_mru_cache_done(cache);
+
+	TRACE_LOOKUP(ip->i_mount, ip, item->pip, ag, ref);
+	return ag;
+}
+
+/*
+ * xfs_filestream_associate() should only be called to associate a regular file
+ * with its parent directory.  Calling it with a child directory isn't
+ * appropriate because filestreams don't apply to entire directory hierarchies.
+ * Creating a file in a child directory of an existing filestream directory
+ * starts a new filestream with its own allocation group association.
+ *
+ * Returns < 0 on error, 0 if successful association occurred, > 0 if
+ * we failed to get an association because of locking issues.
+ */
+int
+xfs_filestream_associate(
+	xfs_inode_t	*pip,
+	xfs_inode_t	*ip)
+{
+	xfs_mount_t	*mp;
+	xfs_mru_cache_t	*cache;
+	fstrm_item_t	*item;
+	xfs_agnumber_t	ag, rotorstep, startag;
+	int		err = 0;
+
+	ASSERT(pip->i_d.di_mode & S_IFDIR);
+	ASSERT(ip->i_d.di_mode & S_IFREG);
+	if (!(pip->i_d.di_mode & S_IFDIR) || !(ip->i_d.di_mode & S_IFREG))
+		return -EINVAL;
+
+	mp = pip->i_mount;
+	cache = mp->m_filestream;
+	down_read(&mp->m_peraglock);
+
+	/*
+	 * We have a problem, Houston.
+	 *
+	 * Taking the iolock here violates inode locking order - we already
+	 * hold the ilock. Hence if we block getting this lock we may never
+	 * wake. Unfortunately, that means if we can't get the lock, we're
+	 * screwed in terms of getting a stream association - we can't spin
+	 * waiting for the lock because someone else is waiting on the lock we
+	 * hold and we cannot drop that as we are in a transaction here.
+	 *
+	 * Lucky for us, this inversion is rarely a problem because it's a
+	 * directory inode that we are trying to lock here and that means the
+	 * only place that matters is xfs_sync_inodes() and SYNC_DELWRI is
+	 * used. i.e. freeze, remount-ro, quotasync or unmount.
+	 *
+	 * So, if we can't get the iolock without sleeping then just give up
+	 */
+	if (!xfs_ilock_nowait(pip, XFS_IOLOCK_EXCL)) {
+		up_read(&mp->m_peraglock);
+		return 1;
+	}
+
+	/* If the parent directory is already in the cache, use its AG. */
+	item = xfs_mru_cache_lookup(cache, pip->i_ino);
+	if (item) {
+		ASSERT(item->ip == pip);
+		ag = item->ag;
+		xfs_mru_cache_done(cache);
+
+		TRACE_LOOKUP(mp, pip, pip, ag, xfs_filestream_peek_ag(mp, ag));
+		err = _xfs_filestream_update_ag(ip, pip, ag);
+
+		goto exit;
+	}
+
+	/*
+	 * Set the starting AG using the rotor for inode32, otherwise
+	 * use the directory inode's AG.
+	 */
+	if (mp->m_flags & XFS_MOUNT_32BITINODES) {
+		rotorstep = xfs_rotorstep;
+		startag = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount;
+		mp->m_agfrotor = (mp->m_agfrotor + 1) %
+		                 (mp->m_sb.sb_agcount * rotorstep);
+	} else
+		startag = XFS_INO_TO_AGNO(mp, pip->i_ino);
+
+	/* Pick a new AG for the parent inode starting at startag. */
+	err = _xfs_filestream_pick_ag(mp, startag, &ag, 0, 0);
+	if (err || ag == NULLAGNUMBER)
+		goto exit_did_pick;
+
+	/* Associate the parent inode with the AG. */
+	err = _xfs_filestream_update_ag(pip, NULL, ag);
+	if (err)
+		goto exit_did_pick;
+
+	/* Associate the file inode with the AG. */
+	err = _xfs_filestream_update_ag(ip, pip, ag);
+	if (err)
+		goto exit_did_pick;
+
+	TRACE_ASSOCIATE(mp, ip, pip, ag, xfs_filestream_peek_ag(mp, ag));
+
+exit_did_pick:
+	/*
+	 * If _xfs_filestream_pick_ag() returned a valid AG, remove the
+	 * reference it took on it, since the file and directory will have taken
+	 * their own now if they were successfully cached.
+	 */
+	if (ag != NULLAGNUMBER)
+		xfs_filestream_put_ag(mp, ag);
+
+exit:
+	xfs_iunlock(pip, XFS_IOLOCK_EXCL);
+	up_read(&mp->m_peraglock);
+	return -err;
+}
+
+/*
+ * Pick a new allocation group for the current file and its file stream.  This
+ * function is called by xfs_bmap_filestreams() with the mount point's per-ag
+ * lock held.
+ */
+int
+xfs_filestream_new_ag(
+	xfs_bmalloca_t	*ap,
+	xfs_agnumber_t	*agp)
+{
+	int		flags, err;
+	xfs_inode_t	*ip, *pip = NULL;
+	xfs_mount_t	*mp;
+	xfs_mru_cache_t	*cache;
+	xfs_extlen_t	minlen;
+	fstrm_item_t	*dir, *file;
+	xfs_agnumber_t	ag = NULLAGNUMBER;
+
+	ip = ap->ip;
+	mp = ip->i_mount;
+	cache = mp->m_filestream;
+	minlen = ap->alen;
+	*agp = NULLAGNUMBER;
+
+	/*
+	 * Look for the file in the cache, removing it if it's found.  Doing
+	 * this allows it to be held across the dir lookup that follows.
+	 */
+	file = xfs_mru_cache_remove(cache, ip->i_ino);
+	if (file) {
+		ASSERT(ip == file->ip);
+
+		/* Save the file's parent inode and old AG number for later. */
+		pip = file->pip;
+		ag = file->ag;
+
+		/* Look for the file's directory in the cache. */
+		dir = xfs_mru_cache_lookup(cache, pip->i_ino);
+		if (dir) {
+			ASSERT(pip == dir->ip);
+
+			/*
+			 * If the directory has already moved on to a new AG,
+			 * use that AG as the new AG for the file. Don't
+			 * forget to twiddle the AG refcounts to match the
+			 * movement.
+			 */
+			if (dir->ag != file->ag) {
+				xfs_filestream_put_ag(mp, file->ag);
+				xfs_filestream_get_ag(mp, dir->ag);
+				*agp = file->ag = dir->ag;
+			}
+
+			xfs_mru_cache_done(cache);
+		}
+
+		/*
+		 * Put the file back in the cache.  If this fails, the free
+		 * function needs to be called to tidy up in the same way as if
+		 * the item had simply expired from the cache.
+		 */
+		err = xfs_mru_cache_insert(cache, ip->i_ino, file);
+		if (err) {
+			xfs_fstrm_free_func(ip->i_ino, file);
+			return err;
+		}
+
+		/*
+		 * If the file's AG was moved to the directory's new AG, there's
+		 * nothing more to be done.
+		 */
+		if (*agp != NULLAGNUMBER) {
+			TRACE_MOVEAG(mp, ip, pip,
+					ag, xfs_filestream_peek_ag(mp, ag),
+					*agp, xfs_filestream_peek_ag(mp, *agp));
+			return 0;
+		}
+	}
+
+	/*
+	 * If the file's parent directory is known, take its iolock in exclusive
+	 * mode to prevent two sibling files from racing each other to migrate
+	 * themselves and their parent to different AGs.
+	 */
+	if (pip)
+		xfs_ilock(pip, XFS_IOLOCK_EXCL);
+
+	/*
+	 * A new AG needs to be found for the file.  If the file's parent
+	 * directory is also known, it will be moved to the new AG as well to
+	 * ensure that files created inside it in future use the new AG.
+	 */
+	ag = (ag == NULLAGNUMBER) ? 0 : (ag + 1) % mp->m_sb.sb_agcount;
+	flags = (ap->userdata ? XFS_PICK_USERDATA : 0) |
+	        (ap->low ? XFS_PICK_LOWSPACE : 0);
+
+	err = _xfs_filestream_pick_ag(mp, ag, agp, flags, minlen);
+	if (err || *agp == NULLAGNUMBER)
+		goto exit;
+
+	/*
+	 * If the file wasn't found in the file cache, then its parent directory
+	 * inode isn't known.  For this to have happened, the file must either
+	 * be pre-existing, or it was created long enough ago that its cache
+	 * entry has expired.  This isn't the sort of usage that the filestreams
+	 * allocator is trying to optimise, so there's no point trying to track
+	 * its new AG somehow in the filestream data structures.
+	 */
+	if (!pip) {
+		TRACE_ORPHAN(mp, ip, *agp);
+		goto exit;
+	}
+
+	/* Associate the parent inode with the AG. */
+	err = _xfs_filestream_update_ag(pip, NULL, *agp);
+	if (err)
+		goto exit;
+
+	/* Associate the file inode with the AG. */
+	err = _xfs_filestream_update_ag(ip, pip, *agp);
+	if (err)
+		goto exit;
+
+	TRACE_MOVEAG(mp, ip, pip, NULLAGNUMBER, 0,
+			*agp, xfs_filestream_peek_ag(mp, *agp));
+
+exit:
+	/*
+	 * If _xfs_filestream_pick_ag() returned a valid AG, remove the
+	 * reference it took on it, since the file and directory will have taken
+	 * their own now if they were successfully cached.
+	 */
+	if (*agp != NULLAGNUMBER)
+		xfs_filestream_put_ag(mp, *agp);
+	else
+		*agp = 0;
+
+	if (pip)
+		xfs_iunlock(pip, XFS_IOLOCK_EXCL);
+
+	return err;
+}
+
+/*
+ * Remove an association between an inode and a filestream object.
+ * Typically this is done on last close of an unlinked file.
+ */
+void
+xfs_filestream_deassociate(
+	xfs_inode_t	*ip)
+{
+	xfs_mru_cache_t	*cache = ip->i_mount->m_filestream;
+
+	xfs_mru_cache_delete(cache, ip->i_ino);
+}
diff --git a/fs/xfs/xfs_filestream.h b/fs/xfs/xfs_filestream.h
new file mode 100644
index 0000000..f655f7d
--- /dev/null
+++ b/fs/xfs/xfs_filestream.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2006-2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __XFS_FILESTREAM_H__
+#define __XFS_FILESTREAM_H__
+
+#ifdef __KERNEL__
+
+struct xfs_mount;
+struct xfs_inode;
+struct xfs_perag;
+struct xfs_bmalloca;
+
+#ifdef XFS_FILESTREAMS_TRACE
+#define XFS_FSTRM_KTRACE_INFO		1
+#define XFS_FSTRM_KTRACE_AGSCAN		2
+#define XFS_FSTRM_KTRACE_AGPICK1	3
+#define XFS_FSTRM_KTRACE_AGPICK2	4
+#define XFS_FSTRM_KTRACE_UPDATE		5
+#define XFS_FSTRM_KTRACE_FREE		6
+#define	XFS_FSTRM_KTRACE_ITEM_LOOKUP	7
+#define	XFS_FSTRM_KTRACE_ASSOCIATE	8
+#define	XFS_FSTRM_KTRACE_MOVEAG		9
+#define	XFS_FSTRM_KTRACE_ORPHAN		10
+
+#define XFS_FSTRM_KTRACE_SIZE	16384
+extern ktrace_t *xfs_filestreams_trace_buf;
+
+#endif
+
+/*
+ * Allocation group filestream associations are tracked with per-ag atomic
+ * counters.  These counters allow _xfs_filestream_pick_ag() to tell whether a
+ * particular AG already has active filestreams associated with it. The mount
+ * point's m_peraglock is used to protect these counters from per-ag array
+ * re-allocation during a growfs operation.  When xfs_growfs_data_private() is
+ * about to reallocate the array, it calls xfs_filestream_flush() with the
+ * m_peraglock held in write mode.
+ *
+ * Since xfs_mru_cache_flush() guarantees that all the free functions for all
+ * the cache elements have finished executing before it returns, it's safe for
+ * the free functions to use the atomic counters without m_peraglock protection.
+ * This allows the implementation of xfs_fstrm_free_func() to be agnostic about
+ * whether it was called with the m_peraglock held in read mode, write mode or
+ * not held at all.  The race condition this addresses is the following:
+ *
+ *  - The work queue scheduler fires and pulls a filestream directory cache
+ *    element off the LRU end of the cache for deletion, then gets pre-empted.
+ *  - A growfs operation grabs the m_peraglock in write mode, flushes all the
+ *    remaining items from the cache and reallocates the mount point's per-ag
+ *    array, resetting all the counters to zero.
+ *  - The work queue thread resumes and calls the free function for the element
+ *    it started cleaning up earlier.  In the process it decrements the
+ *    filestreams counter for an AG that now has no references.
+ *
+ * With a shrinkfs feature, the above scenario could panic the system.
+ *
+ * All other uses of the following macros should be protected by either the
+ * m_peraglock held in read mode, or the cache's internal locking exposed by the
+ * interval between a call to xfs_mru_cache_lookup() and a call to
+ * xfs_mru_cache_done().  In addition, the m_peraglock must be held in read mode
+ * when new elements are added to the cache.
+ *
+ * Combined, these locking rules ensure that no associations will ever exist in
+ * the cache that reference per-ag array elements that have since been
+ * reallocated.
+ */
+STATIC_INLINE int
+xfs_filestream_peek_ag(
+	xfs_mount_t	*mp,
+	xfs_agnumber_t	agno)
+{
+	return atomic_read(&mp->m_perag[agno].pagf_fstrms);
+}
+
+STATIC_INLINE int
+xfs_filestream_get_ag(
+	xfs_mount_t	*mp,
+	xfs_agnumber_t	agno)
+{
+	return atomic_inc_return(&mp->m_perag[agno].pagf_fstrms);
+}
+
+STATIC_INLINE int
+xfs_filestream_put_ag(
+	xfs_mount_t	*mp,
+	xfs_agnumber_t	agno)
+{
+	return atomic_dec_return(&mp->m_perag[agno].pagf_fstrms);
+}
+
+/* allocation selection flags */
+typedef enum xfs_fstrm_alloc {
+	XFS_PICK_USERDATA = 1,
+	XFS_PICK_LOWSPACE = 2,
+} xfs_fstrm_alloc_t;
+
+/* prototypes for filestream.c */
+int xfs_filestream_init(void);
+void xfs_filestream_uninit(void);
+int xfs_filestream_mount(struct xfs_mount *mp);
+void xfs_filestream_unmount(struct xfs_mount *mp);
+void xfs_filestream_flush(struct xfs_mount *mp);
+xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip);
+int xfs_filestream_associate(struct xfs_inode *dip, struct xfs_inode *ip);
+void xfs_filestream_deassociate(struct xfs_inode *ip);
+int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp);
+
+
+/* filestreams for the inode? */
+STATIC_INLINE int
+xfs_inode_is_filestream(
+	struct xfs_inode	*ip)
+{
+	return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) ||
+		xfs_iflags_test(ip, XFS_IFILESTREAM) ||
+		(ip->i_d.di_flags & XFS_DIFLAG_FILESTREAM);
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __XFS_FILESTREAM_H__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 1335449..ec3c9c2 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -66,6 +66,7 @@
 #define XFS_XFLAG_EXTSIZE	0x00000800	/* extent size allocator hint */
 #define XFS_XFLAG_EXTSZINHERIT	0x00001000	/* inherit inode extent size */
 #define XFS_XFLAG_NODEFRAG	0x00002000  	/* do not defragment */
+#define XFS_XFLAG_FILESTREAM	0x00004000	/* use filestream allocator */
 #define XFS_XFLAG_HASATTR	0x80000000	/* no DIFLAG for this	*/
 
 /*
@@ -238,6 +239,7 @@
 #define XFS_FSOP_GEOM_FLAGS_LOGV2	0x0100	/* log format version 2	*/
 #define XFS_FSOP_GEOM_FLAGS_SECTOR	0x0200	/* sector sizes >1BB	*/
 #define XFS_FSOP_GEOM_FLAGS_ATTR2	0x0400	/* inline attributes rework */
+#define XFS_FSOP_GEOM_FLAGS_LAZYSB	0x4000	/* lazy superblock counters */
 
 
 /*
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index b599e6b..432e823 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -44,6 +44,7 @@
 #include "xfs_trans_space.h"
 #include "xfs_rtalloc.h"
 #include "xfs_rw.h"
+#include "xfs_filestream.h"
 
 /*
  * File system operations
@@ -94,6 +95,8 @@
 				XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) |
 			(XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
 				XFS_FSOP_GEOM_FLAGS_SECTOR : 0) |
+			(xfs_sb_version_haslazysbcount(&mp->m_sb) ?
+				XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) |
 			(XFS_SB_VERSION_HASATTR2(&mp->m_sb) ?
 				XFS_FSOP_GEOM_FLAGS_ATTR2 : 0);
 		geo->logsectsize = XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
@@ -140,6 +143,8 @@
 	pct = in->imaxpct;
 	if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
 		return XFS_ERROR(EINVAL);
+	if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
+		return error;
 	dpct = pct - mp->m_sb.sb_imax_pct;
 	error = xfs_read_buf(mp, mp->m_ddev_targp,
 			XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
@@ -161,6 +166,7 @@
 	new = nb - mp->m_sb.sb_dblocks;
 	oagcount = mp->m_sb.sb_agcount;
 	if (nagcount > oagcount) {
+		xfs_filestream_flush(mp);
 		down_write(&mp->m_peraglock);
 		mp->m_perag = kmem_realloc(mp->m_perag,
 			sizeof(xfs_perag_t) * nagcount,
@@ -173,6 +179,7 @@
 		up_write(&mp->m_peraglock);
 	}
 	tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
+	tp->t_flags |= XFS_TRANS_RESERVE;
 	if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp),
 			XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) {
 		xfs_trans_cancel(tp, 0);
@@ -328,6 +335,7 @@
 		be32_add(&agf->agf_length, new);
 		ASSERT(be32_to_cpu(agf->agf_length) ==
 		       be32_to_cpu(agi->agi_length));
+		xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH);
 		/*
 		 * Free the new space.
 		 */
@@ -494,8 +502,9 @@
 	unsigned long		s;
 
 	/* If inval is null, report current values and return */
-
 	if (inval == (__uint64_t *)NULL) {
+		if (!outval)
+			return EINVAL;
 		outval->resblks = mp->m_resblks;
 		outval->resblks_avail = mp->m_resblks_avail;
 		return 0;
@@ -558,8 +567,10 @@
 		}
 	}
 out:
-	outval->resblks = mp->m_resblks;
-	outval->resblks_avail = mp->m_resblks_avail;
+	if (outval) {
+		outval->resblks = mp->m_resblks;
+		outval->resblks_avail = mp->m_resblks_avail;
+	}
 	XFS_SB_UNLOCK(mp, s);
 
 	if (fdblks_delta) {
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index b5feb3e..f943368 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -123,6 +123,7 @@
 	int		blks_per_cluster;  /* fs blocks per inode cluster */
 	xfs_btree_cur_t	*cur;		/* inode btree cursor */
 	xfs_daddr_t	d;		/* disk addr of buffer */
+	xfs_agnumber_t	agno;
 	int		error;
 	xfs_buf_t	*fbuf;		/* new free inodes' buffer */
 	xfs_dinode_t	*free;		/* new free inode structure */
@@ -302,15 +303,15 @@
 	}
 	be32_add(&agi->agi_count, newlen);
 	be32_add(&agi->agi_freecount, newlen);
+	agno = be32_to_cpu(agi->agi_seqno);
 	down_read(&args.mp->m_peraglock);
-	args.mp->m_perag[be32_to_cpu(agi->agi_seqno)].pagi_freecount += newlen;
+	args.mp->m_perag[agno].pagi_freecount += newlen;
 	up_read(&args.mp->m_peraglock);
 	agi->agi_newino = cpu_to_be32(newino);
 	/*
 	 * Insert records describing the new inode chunk into the btree.
 	 */
-	cur = xfs_btree_init_cursor(args.mp, tp, agbp,
-			be32_to_cpu(agi->agi_seqno),
+	cur = xfs_btree_init_cursor(args.mp, tp, agbp, agno,
 			XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
 	for (thisino = newino;
 	     thisino < newino + newlen;
@@ -1387,6 +1388,7 @@
 	pag = &mp->m_perag[agno];
 	if (!pag->pagi_init) {
 		pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
+		pag->pagi_count = be32_to_cpu(agi->agi_count);
 		pag->pagi_init = 1;
 	} else {
 		/*
@@ -1410,3 +1412,23 @@
 	*bpp = bp;
 	return 0;
 }
+
+/*
+ * Read in the agi to initialise the per-ag data in the mount structure
+ */
+int
+xfs_ialloc_pagi_init(
+	xfs_mount_t	*mp,		/* file system mount structure */
+	xfs_trans_t	*tp,		/* transaction pointer */
+	xfs_agnumber_t	agno)		/* allocation group number */
+{
+	xfs_buf_t	*bp = NULL;
+	int		error;
+
+	error = xfs_ialloc_read_agi(mp, tp, agno, &bp);
+	if (error)
+		return error;
+	if (bp)
+		xfs_trans_brelse(tp, bp);
+	return 0;
+}
diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h
index 7f5debe..97f4040 100644
--- a/fs/xfs/xfs_ialloc.h
+++ b/fs/xfs/xfs_ialloc.h
@@ -149,6 +149,16 @@
 	xfs_agnumber_t	agno,		/* allocation group number */
 	struct xfs_buf	**bpp);		/* allocation group hdr buf */
 
+/*
+ * Read in the allocation group header to initialise the per-ag data
+ * in the mount structure
+ */
+int
+xfs_ialloc_pagi_init(
+	struct xfs_mount *mp,		/* file system mount structure */
+	struct xfs_trans *tp,		/* transaction pointer */
+        xfs_agnumber_t  agno);		/* allocation group number */
+
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_IALLOC_H__ */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 3ca5d43..cdc4c28 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -48,7 +48,9 @@
 #include "xfs_dir2_trace.h"
 #include "xfs_quota.h"
 #include "xfs_acl.h"
+#include "xfs_filestream.h"
 
+#include <linux/log2.h>
 
 kmem_zone_t *xfs_ifork_zone;
 kmem_zone_t *xfs_inode_zone;
@@ -643,8 +645,7 @@
 			ep->l1 = INT_GET(get_unaligned((__uint64_t*)&dp->l1),
 								ARCH_CONVERT);
 		}
-		xfs_bmap_trace_exlist("xfs_iformat_extents", ip, nex,
-			whichfork);
+		XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
 		if (whichfork != XFS_DATA_FORK ||
 			XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
 				if (unlikely(xfs_check_nostate_extents(
@@ -817,6 +818,8 @@
 			flags |= XFS_XFLAG_EXTSZINHERIT;
 		if (di_flags & XFS_DIFLAG_NODEFRAG)
 			flags |= XFS_XFLAG_NODEFRAG;
+		if (di_flags & XFS_DIFLAG_FILESTREAM)
+			flags |= XFS_XFLAG_FILESTREAM;
 	}
 
 	return flags;
@@ -1074,6 +1077,11 @@
  * also returns the [locked] bp pointing to the head of the freelist
  * as ialloc_context.  The caller should hold this buffer across
  * the commit and pass it back into this routine on the second call.
+ *
+ * If we are allocating quota inodes, we do not have a parent inode
+ * to attach to or associate with (i.e. pip == NULL) because they
+ * are not linked into the directory structure - they are attached
+ * directly to the superblock - and so have no parent.
  */
 int
 xfs_ialloc(
@@ -1099,7 +1107,7 @@
 	 * Call the space management code to pick
 	 * the on-disk inode to be allocated.
 	 */
-	error = xfs_dialloc(tp, pip->i_ino, mode, okalloc,
+	error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc,
 			    ialloc_context, call_again, &ino);
 	if (error != 0) {
 		return error;
@@ -1150,10 +1158,10 @@
 	/*
 	 * Project ids won't be stored on disk if we are using a version 1 inode.
 	 */
-	if ( (prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
+	if ((prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
 		xfs_bump_ino_vers2(tp, ip);
 
-	if (XFS_INHERIT_GID(pip, vp->v_vfsp)) {
+	if (pip && XFS_INHERIT_GID(pip, vp->v_vfsp)) {
 		ip->i_d.di_gid = pip->i_d.di_gid;
 		if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
 			ip->i_d.di_mode |= S_ISGID;
@@ -1195,8 +1203,16 @@
 		flags |= XFS_ILOG_DEV;
 		break;
 	case S_IFREG:
+		if (pip && xfs_inode_is_filestream(pip)) {
+			error = xfs_filestream_associate(pip, ip);
+			if (error < 0)
+				return -error;
+			if (!error)
+				xfs_iflags_set(ip, XFS_IFILESTREAM);
+		}
+		/* fall through */
 	case S_IFDIR:
-		if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
+		if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
 			uint	di_flags = 0;
 
 			if ((mode & S_IFMT) == S_IFDIR) {
@@ -1233,6 +1249,8 @@
 			if ((pip->i_d.di_flags & XFS_DIFLAG_NODEFRAG) &&
 			    xfs_inherit_nodefrag)
 				di_flags |= XFS_DIFLAG_NODEFRAG;
+			if (pip->i_d.di_flags & XFS_DIFLAG_FILESTREAM)
+				di_flags |= XFS_DIFLAG_FILESTREAM;
 			ip->i_d.di_flags |= di_flags;
 		}
 		/* FALLTHROUGH */
@@ -2875,9 +2893,6 @@
 	int			copied;
 	xfs_bmbt_rec_t		*dest_ep;
 	xfs_bmbt_rec_t		*ep;
-#ifdef XFS_BMAP_TRACE
-	static char		fname[] = "xfs_iextents_copy";
-#endif
 	int			i;
 	xfs_ifork_t		*ifp;
 	int			nrecs;
@@ -2888,7 +2903,7 @@
 	ASSERT(ifp->if_bytes > 0);
 
 	nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
-	xfs_bmap_trace_exlist(fname, ip, nrecs, whichfork);
+	XFS_BMAP_TRACE_EXLIST(ip, nrecs, whichfork);
 	ASSERT(nrecs > 0);
 
 	/*
@@ -4184,7 +4199,7 @@
 			ifp->if_bytes = new_size;
 			return;
 		}
-		if ((new_size & (new_size - 1)) != 0) {
+		if (!is_power_of_2(new_size)){
 			rnew_size = xfs_iroundup(new_size);
 		}
 		if (rnew_size != ifp->if_real_bytes) {
@@ -4207,7 +4222,7 @@
 	 */
 	else {
 		new_size += ifp->if_bytes;
-		if ((new_size & (new_size - 1)) != 0) {
+		if (!is_power_of_2(new_size)) {
 			rnew_size = xfs_iroundup(new_size);
 		}
 		xfs_iext_inline_to_direct(ifp, rnew_size);
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index f75afec..012dfd4 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -379,6 +379,7 @@
 #define XFS_ISTALE	0x0010	/* inode has been staled */
 #define XFS_IRECLAIMABLE 0x0020 /* inode can be reclaimed */
 #define XFS_INEW	0x0040
+#define XFS_IFILESTREAM	0x0080	/* inode is in a filestream directory */
 
 /*
  * Flags for inode locking.
@@ -414,19 +415,22 @@
  * gets a lockdep subclass of 1 and the second lock will have a lockdep
  * subclass of 0.
  *
- * XFS_I[O]LOCK_INUMORDER - for locking several inodes at the some time
+ * XFS_LOCK_INUMORDER - for locking several inodes at the some time
  * with xfs_lock_inodes().  This flag is used as the starting subclass
  * and each subsequent lock acquired will increment the subclass by one.
  * So the first lock acquired will have a lockdep subclass of 2, the
- * second lock will have a lockdep subclass of 3, and so on.
+ * second lock will have a lockdep subclass of 3, and so on. It is
+ * the responsibility of the class builder to shift this to the correct
+ * portion of the lock_mode lockdep mask.
  */
+#define XFS_LOCK_PARENT		1
+#define XFS_LOCK_INUMORDER	2
+
 #define XFS_IOLOCK_SHIFT	16
-#define	XFS_IOLOCK_PARENT	(1 << XFS_IOLOCK_SHIFT)
-#define	XFS_IOLOCK_INUMORDER	(2 << XFS_IOLOCK_SHIFT)
+#define	XFS_IOLOCK_PARENT	(XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT)
 
 #define XFS_ILOCK_SHIFT		24
-#define	XFS_ILOCK_PARENT	(1 << XFS_ILOCK_SHIFT)
-#define	XFS_ILOCK_INUMORDER	(2 << XFS_ILOCK_SHIFT)
+#define	XFS_ILOCK_PARENT	(XFS_LOCK_PARENT << XFS_ILOCK_SHIFT)
 
 #define XFS_IOLOCK_DEP_MASK	0x00ff0000
 #define XFS_ILOCK_DEP_MASK	0xff000000
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 3f2b9f2..bf57b75 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -451,19 +451,14 @@
 		return XFS_ERROR(error);
 
 	rt = XFS_IS_REALTIME_INODE(ip);
-	if (unlikely(rt)) {
-		if (!(extsz = ip->i_d.di_extsize))
-			extsz = mp->m_sb.sb_rextsize;
-	} else {
-		extsz = ip->i_d.di_extsize;
-	}
+	extsz = xfs_get_extsz_hint(ip);
 
 	isize = ip->i_size;
 	if (io->io_new_size > isize)
 		isize = io->io_new_size;
 
-  	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-  	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
+	offset_fsb = XFS_B_TO_FSBT(mp, offset);
+	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
 	if ((offset + count) > isize) {
 		error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
 							&last_fsb);
@@ -489,13 +484,13 @@
 	if (unlikely(rt)) {
 		resrtextents = qblocks = resaligned;
 		resrtextents /= mp->m_sb.sb_rextsize;
-  		resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
-  		quota_flag = XFS_QMOPT_RES_RTBLKS;
-  	} else {
-  		resrtextents = 0;
+		resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+		quota_flag = XFS_QMOPT_RES_RTBLKS;
+	} else {
+		resrtextents = 0;
 		resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
-  		quota_flag = XFS_QMOPT_RES_REGBLKS;
-  	}
+		quota_flag = XFS_QMOPT_RES_REGBLKS;
+	}
 
 	/*
 	 * Allocate and setup the transaction
@@ -666,13 +661,7 @@
 	if (error)
 		return XFS_ERROR(error);
 
-	if (XFS_IS_REALTIME_INODE(ip)) {
-		if (!(extsz = ip->i_d.di_extsize))
-			extsz = mp->m_sb.sb_rextsize;
-	} else {
-		extsz = ip->i_d.di_extsize;
-	}
-
+	extsz = xfs_get_extsz_hint(ip);
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
 
 retry:
@@ -788,18 +777,12 @@
 		nimaps = 0;
 		while (nimaps == 0) {
 			tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
+			tp->t_flags |= XFS_TRANS_RESERVE;
 			nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
 			error = xfs_trans_reserve(tp, nres,
 					XFS_WRITE_LOG_RES(mp),
 					0, XFS_TRANS_PERM_LOG_RES,
 					XFS_WRITE_LOG_COUNT);
-			if (error == ENOSPC) {
-				error = xfs_trans_reserve(tp, 0,
-						XFS_WRITE_LOG_RES(mp),
-						0,
-						XFS_TRANS_PERM_LOG_RES,
-						XFS_WRITE_LOG_COUNT);
-			}
 			if (error) {
 				xfs_trans_cancel(tp, 0);
 				return XFS_ERROR(error);
@@ -917,8 +900,8 @@
 		 * from unwritten to real. Do allocations in a loop until
 		 * we have covered the range passed in.
 		 */
-
 		tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
+		tp->t_flags |= XFS_TRANS_RESERVE;
 		error = xfs_trans_reserve(tp, resblks,
 				XFS_WRITE_LOG_RES(mp), 0,
 				XFS_TRANS_PERM_LOG_RES,
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index e725ddd..4c2454b 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -202,6 +202,16 @@
 	return 0;
 }
 
+STATIC int
+xfs_bulkstat_one_fmt(
+	void			__user *ubuffer,
+	const xfs_bstat_t	*buffer)
+{
+	if (copy_to_user(ubuffer, buffer, sizeof(*buffer)))
+		return -EFAULT;
+	return sizeof(*buffer);
+}
+
 /*
  * Return stat information for one inode.
  * Return 0 if ok, else errno.
@@ -221,6 +231,7 @@
 	xfs_bstat_t	*buf;		/* return buffer */
 	int		error = 0;	/* error value */
 	xfs_dinode_t	*dip;		/* dinode inode pointer */
+	bulkstat_one_fmt_pf formatter = private_data ? : xfs_bulkstat_one_fmt;
 
 	dip = (xfs_dinode_t *)dibuff;
 	*stat = BULKSTAT_RV_NOTHING;
@@ -243,14 +254,15 @@
 		xfs_bulkstat_one_dinode(mp, ino, dip, buf);
 	}
 
-	if (copy_to_user(buffer, buf, sizeof(*buf)))  {
+	error = formatter(buffer, buf);
+	if (error < 0)  {
 		error = EFAULT;
 		goto out_free;
 	}
 
 	*stat = BULKSTAT_RV_DIDONE;
 	if (ubused)
-		*ubused = sizeof(*buf);
+		*ubused = error;
 
  out_free:
 	kmem_free(buf, sizeof(*buf));
@@ -748,6 +760,19 @@
 	return 0;
 }
 
+int
+xfs_inumbers_fmt(
+	void			__user *ubuffer, /* buffer to write to */
+	const xfs_inogrp_t	*buffer,	/* buffer to read from */
+	long			count,		/* # of elements to read */
+	long			*written)	/* # of bytes written */
+{
+	if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer)))
+		return -EFAULT;
+	*written = count * sizeof(*buffer);
+	return 0;
+}
+
 /*
  * Return inode number table for the filesystem.
  */
@@ -756,7 +781,8 @@
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	*lastino,	/* last inode returned */
 	int		*count,		/* size of buffer/count returned */
-	xfs_inogrp_t	__user *ubuffer)/* buffer with inode descriptions */
+	void		__user *ubuffer,/* buffer with inode descriptions */
+	inumbers_fmt_pf	formatter)
 {
 	xfs_buf_t	*agbp;
 	xfs_agino_t	agino;
@@ -835,12 +861,12 @@
 		bufidx++;
 		left--;
 		if (bufidx == bcount) {
-			if (copy_to_user(ubuffer, buffer,
-					bufidx * sizeof(*buffer))) {
+			long written;
+			if (formatter(ubuffer, buffer, bufidx, &written)) {
 				error = XFS_ERROR(EFAULT);
 				break;
 			}
-			ubuffer += bufidx;
+			ubuffer += written;
 			*count += bufidx;
 			bufidx = 0;
 		}
@@ -862,8 +888,8 @@
 	}
 	if (!error) {
 		if (bufidx) {
-			if (copy_to_user(ubuffer, buffer,
-					bufidx * sizeof(*buffer)))
+			long written;
+			if (formatter(ubuffer, buffer, bufidx, &written))
 				error = XFS_ERROR(EFAULT);
 			else
 				*count += bufidx;
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index f25a288..a1f18fc 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -69,6 +69,10 @@
 	char			__user *buffer,
 	int			*done);
 
+typedef int (*bulkstat_one_fmt_pf)(  /* used size in bytes or negative error */
+	void			__user *ubuffer, /* buffer to write to */
+	const xfs_bstat_t	*buffer);        /* buffer to read from */
+
 int
 xfs_bulkstat_one(
 	xfs_mount_t		*mp,
@@ -86,11 +90,25 @@
 	xfs_mount_t		*mp,
 	xfs_ino_t		ino);
 
+typedef int (*inumbers_fmt_pf)(
+	void			__user *ubuffer, /* buffer to write to */
+	const xfs_inogrp_t	*buffer,	/* buffer to read from */
+	long			count,		/* # of elements to read */
+	long			*written);	/* # of bytes written */
+
+int
+xfs_inumbers_fmt(
+	void			__user *ubuffer, /* buffer to write to */
+	const xfs_inogrp_t	*buffer,	/* buffer to read from */
+	long			count,		/* # of elements to read */
+	long			*written);	/* # of bytes written */
+
 int					/* error status */
 xfs_inumbers(
 	xfs_mount_t		*mp,	/* mount point for filesystem */
 	xfs_ino_t		*last,	/* last inode returned */
 	int			*count,	/* size of buffer/count returned */
-	xfs_inogrp_t		__user *buffer);/* buffer with inode info */
+	void			__user *buffer, /* buffer with inode info */
+	inumbers_fmt_pf		formatter);
 
 #endif	/* __XFS_ITABLE_H__ */
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index c48bf61..9d4c4fb 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -817,10 +817,8 @@
 	SPLDECL(s);
 	int		needed = 0, gen;
 	xlog_t		*log = mp->m_log;
-	bhv_vfs_t	*vfsp = XFS_MTOVFS(mp);
 
-	if (vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
-	    (vfsp->vfs_flag & VFS_RDONLY))
+	if (!xfs_fs_writable(mp))
 		return 0;
 
 	s = LOG_LOCK(log);
@@ -967,14 +965,16 @@
 	} else if (iclog->ic_state & XLOG_STATE_IOERROR) {
 		aborted = XFS_LI_ABORTED;
 	}
+
+	/* log I/O is always issued ASYNC */
+	ASSERT(XFS_BUF_ISASYNC(bp));
 	xlog_state_done_syncing(iclog, aborted);
-	if (!(XFS_BUF_ISASYNC(bp))) {
-		/*
-		 * Corresponding psema() will be done in bwrite().  If we don't
-		 * vsema() here, panic.
-		 */
-		XFS_BUF_V_IODONESEMA(bp);
-	}
+	/*
+	 * do not reference the buffer (bp) here as we could race
+	 * with it being freed after writing the unmount record to the
+	 * log.
+	 */
+
 }	/* xlog_iodone */
 
 /*
@@ -1199,11 +1199,18 @@
 		*iclogp = (xlog_in_core_t *)
 			  kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
 		iclog = *iclogp;
-		iclog->hic_data = (xlog_in_core_2_t *)
-			  kmem_zalloc(iclogsize, KM_SLEEP | KM_LARGE);
-
 		iclog->ic_prev = prev_iclog;
 		prev_iclog = iclog;
+
+		bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
+		if (!XFS_BUF_CPSEMA(bp))
+			ASSERT(0);
+		XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
+		XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
+		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
+		iclog->ic_bp = bp;
+		iclog->hic_data = bp->b_addr;
+
 		log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
 
 		head = &iclog->ic_header;
@@ -1216,11 +1223,6 @@
 		INT_SET(head->h_fmt, ARCH_CONVERT, XLOG_FMT);
 		memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
 
-		bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
-		XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
-		XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
-		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
-		iclog->ic_bp = bp;
 
 		iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
 		iclog->ic_state = XLOG_STATE_ACTIVE;
@@ -1432,7 +1434,7 @@
 	} else {
 		iclog->ic_bwritecnt = 1;
 	}
-	XFS_BUF_SET_PTR(bp, (xfs_caddr_t) &(iclog->ic_header), count);
+	XFS_BUF_SET_COUNT(bp, count);
 	XFS_BUF_SET_FSPRIVATE(bp, iclog);	/* save for later */
 	XFS_BUF_ZEROFLAGS(bp);
 	XFS_BUF_BUSY(bp);
@@ -1528,7 +1530,6 @@
 		}
 #endif
 		next_iclog = iclog->ic_next;
-		kmem_free(iclog->hic_data, log->l_iclog_size);
 		kmem_free(iclog, sizeof(xlog_in_core_t));
 		iclog = next_iclog;
 	}
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 080fabf..fddbb09 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -927,6 +927,14 @@
 			ASSIGN_ANY_LSN_HOST(log->l_last_sync_lsn, log->l_curr_cycle,
 					after_umount_blk);
 			*tail_blk = after_umount_blk;
+
+			/*
+			 * Note that the unmount was clean. If the unmount
+			 * was not clean, we need to know this to rebuild the
+			 * superblock counters from the perag headers if we
+			 * have a filesystem using non-persistent counters.
+			 */
+			log->l_mp->m_flags |= XFS_MOUNT_WAS_CLEAN;
 		}
 	}
 
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index a96bde6..a66b398 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -202,6 +202,27 @@
 	kmem_free(mp, sizeof(xfs_mount_t));
 }
 
+/*
+ * Check size of device based on the (data/realtime) block count.
+ * Note: this check is used by the growfs code as well as mount.
+ */
+int
+xfs_sb_validate_fsb_count(
+	xfs_sb_t	*sbp,
+	__uint64_t	nblocks)
+{
+	ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
+	ASSERT(sbp->sb_blocklog >= BBSHIFT);
+
+#if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */
+	if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
+		return E2BIG;
+#else                  /* Limited by UINT_MAX of sectors */
+	if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)
+		return E2BIG;
+#endif
+	return 0;
+}
 
 /*
  * Check the validity of the SB found.
@@ -284,18 +305,8 @@
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
-	ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
-	ASSERT(sbp->sb_blocklog >= BBSHIFT);
-
-#if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */
-	if (unlikely(
-	    (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX ||
-	    (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) {
-#else                  /* Limited by UINT_MAX of sectors */
-	if (unlikely(
-	    (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
-	    (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
-#endif
+	if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
+	    xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
 		xfs_fs_mount_cmn_err(flags,
 			"file system too large to be mounted on this system.");
 		return XFS_ERROR(E2BIG);
@@ -632,6 +643,64 @@
 					sbp->sb_inopblock);
 	mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
 }
+
+/*
+ * xfs_initialize_perag_data
+ *
+ * Read in each per-ag structure so we can count up the number of
+ * allocated inodes, free inodes and used filesystem blocks as this
+ * information is no longer persistent in the superblock. Once we have
+ * this information, write it into the in-core superblock structure.
+ */
+STATIC int
+xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
+{
+	xfs_agnumber_t	index;
+	xfs_perag_t	*pag;
+	xfs_sb_t	*sbp = &mp->m_sb;
+	uint64_t	ifree = 0;
+	uint64_t	ialloc = 0;
+	uint64_t	bfree = 0;
+	uint64_t	bfreelst = 0;
+	uint64_t	btree = 0;
+	int		error;
+	int		s;
+
+	for (index = 0; index < agcount; index++) {
+		/*
+		 * read the agf, then the agi. This gets us
+		 * all the inforamtion we need and populates the
+		 * per-ag structures for us.
+		 */
+		error = xfs_alloc_pagf_init(mp, NULL, index, 0);
+		if (error)
+			return error;
+
+		error = xfs_ialloc_pagi_init(mp, NULL, index);
+		if (error)
+			return error;
+		pag = &mp->m_perag[index];
+		ifree += pag->pagi_freecount;
+		ialloc += pag->pagi_count;
+		bfree += pag->pagf_freeblks;
+		bfreelst += pag->pagf_flcount;
+		btree += pag->pagf_btreeblks;
+	}
+	/*
+	 * Overwrite incore superblock counters with just-read data
+	 */
+	s = XFS_SB_LOCK(mp);
+	sbp->sb_ifree = ifree;
+	sbp->sb_icount = ialloc;
+	sbp->sb_fdblocks = bfree + bfreelst + btree;
+	XFS_SB_UNLOCK(mp, s);
+
+	/* Fixup the per-cpu counters as well. */
+	xfs_icsb_reinit_counters(mp);
+
+	return 0;
+}
+
 /*
  * xfs_mountfs
  *
@@ -656,7 +725,7 @@
 	bhv_vnode_t	*rvp = NULL;
 	int		readio_log, writeio_log;
 	xfs_daddr_t	d;
-	__uint64_t	ret64;
+	__uint64_t	resblks;
 	__int64_t	update_flags;
 	uint		quotamount, quotaflags;
 	int		agno;
@@ -773,6 +842,7 @@
 	 */
 	if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
 	    (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
+		__uint64_t	ret64;
 		if (xfs_uuid_mount(mp)) {
 			error = XFS_ERROR(EINVAL);
 			goto error1;
@@ -976,6 +1046,34 @@
 	}
 
 	/*
+	 * Now the log is mounted, we know if it was an unclean shutdown or
+	 * not. If it was, with the first phase of recovery has completed, we
+	 * have consistent AG blocks on disk. We have not recovered EFIs yet,
+	 * but they are recovered transactionally in the second recovery phase
+	 * later.
+	 *
+	 * Hence we can safely re-initialise incore superblock counters from
+	 * the per-ag data. These may not be correct if the filesystem was not
+	 * cleanly unmounted, so we need to wait for recovery to finish before
+	 * doing this.
+	 *
+	 * If the filesystem was cleanly unmounted, then we can trust the
+	 * values in the superblock to be correct and we don't need to do
+	 * anything here.
+	 *
+	 * If we are currently making the filesystem, the initialisation will
+	 * fail as the perag data is in an undefined state.
+	 */
+
+	if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
+	    !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
+	     !mp->m_sb.sb_inprogress) {
+		error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
+		if (error) {
+			goto error2;
+		}
+	}
+	/*
 	 * Get and sanity-check the root inode.
 	 * Save the pointer to it in the mount structure.
 	 */
@@ -1044,6 +1142,23 @@
 	if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags)))
 		goto error4;
 
+	/*
+	 * Now we are mounted, reserve a small amount of unused space for
+	 * privileged transactions. This is needed so that transaction
+	 * space required for critical operations can dip into this pool
+	 * when at ENOSPC. This is needed for operations like create with
+	 * attr, unwritten extent conversion at ENOSPC, etc. Data allocations
+	 * are not allowed to use this reserved space.
+	 *
+	 * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
+	 * This may drive us straight to ENOSPC on mount, but that implies
+	 * we were already there on the last unmount.
+	 */
+	resblks = mp->m_sb.sb_dblocks;
+	do_div(resblks, 20);
+	resblks = min_t(__uint64_t, resblks, 1024);
+	xfs_reserve_blocks(mp, &resblks, NULL);
+
 	return 0;
 
  error4:
@@ -1083,7 +1198,19 @@
 #if defined(DEBUG) || defined(INDUCE_IO_ERROR)
 	int64_t		fsid;
 #endif
+	__uint64_t	resblks;
 
+	/*
+	 * We can potentially deadlock here if we have an inode cluster
+	 * that has been freed has it's buffer still pinned in memory because
+	 * the transaction is still sitting in a iclog. The stale inodes
+	 * on that buffer will have their flush locks held until the
+	 * transaction hits the disk and the callbacks run. the inode
+	 * flush takes the flush lock unconditionally and with nothing to
+	 * push out the iclog we will never get that unlocked. hence we
+	 * need to force the log first.
+	 */
+	xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
 	xfs_iflush_all(mp);
 
 	XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);
@@ -1100,10 +1227,26 @@
 		xfs_binval(mp->m_rtdev_targp);
 	}
 
+	/*
+	 * Unreserve any blocks we have so that when we unmount we don't account
+	 * the reserved free space as used. This is really only necessary for
+	 * lazy superblock counting because it trusts the incore superblock
+	 * counters to be aboslutely correct on clean unmount.
+	 *
+	 * We don't bother correcting this elsewhere for lazy superblock
+	 * counting because on mount of an unclean filesystem we reconstruct the
+	 * correct counter value and this is irrelevant.
+	 *
+	 * For non-lazy counter filesystems, this doesn't matter at all because
+	 * we only every apply deltas to the superblock and hence the incore
+	 * value does not matter....
+	 */
+	resblks = 0;
+	xfs_reserve_blocks(mp, &resblks, NULL);
+
+	xfs_log_sbcount(mp, 1);
 	xfs_unmountfs_writesb(mp);
-
 	xfs_unmountfs_wait(mp); 		/* wait for async bufs */
-
 	xfs_log_unmount(mp);			/* Done! No more fs ops. */
 
 	xfs_freesb(mp);
@@ -1150,6 +1293,62 @@
 }
 
 int
+xfs_fs_writable(xfs_mount_t *mp)
+{
+	bhv_vfs_t	*vfsp = XFS_MTOVFS(mp);
+
+	return !(vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
+		(vfsp->vfs_flag & VFS_RDONLY));
+}
+
+/*
+ * xfs_log_sbcount
+ *
+ * Called either periodically to keep the on disk superblock values
+ * roughly up to date or from unmount to make sure the values are
+ * correct on a clean unmount.
+ *
+ * Note this code can be called during the process of freezing, so
+ * we may need to use the transaction allocator which does not not
+ * block when the transaction subsystem is in its frozen state.
+ */
+int
+xfs_log_sbcount(
+	xfs_mount_t	*mp,
+	uint		sync)
+{
+	xfs_trans_t	*tp;
+	int		error;
+
+	if (!xfs_fs_writable(mp))
+		return 0;
+
+	xfs_icsb_sync_counters(mp);
+
+	/*
+	 * we don't need to do this if we are updating the superblock
+	 * counters on every modification.
+	 */
+	if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
+		return 0;
+
+	tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT);
+	error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
+					XFS_DEFAULT_LOG_COUNT);
+	if (error) {
+		xfs_trans_cancel(tp, 0);
+		return error;
+	}
+
+	xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
+	if (sync)
+		xfs_trans_set_sync(tp);
+	xfs_trans_commit(tp, 0);
+
+	return 0;
+}
+
+int
 xfs_unmountfs_writesb(xfs_mount_t *mp)
 {
 	xfs_buf_t	*sbp;
@@ -1160,16 +1359,15 @@
 	 * skip superblock write if fs is read-only, or
 	 * if we are doing a forced umount.
 	 */
-	sbp = xfs_getsb(mp, 0);
 	if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY ||
 		XFS_FORCED_SHUTDOWN(mp))) {
 
-		xfs_icsb_sync_counters(mp);
+		sbp = xfs_getsb(mp, 0);
+ 		sb = XFS_BUF_TO_SBP(sbp);
 
 		/*
 		 * mark shared-readonly if desired
 		 */
-		sb = XFS_BUF_TO_SBP(sbp);
 		if (mp->m_mk_sharedro) {
 			if (!(sb->sb_flags & XFS_SBF_READONLY))
 				sb->sb_flags |= XFS_SBF_READONLY;
@@ -1178,6 +1376,7 @@
 			xfs_fs_cmn_err(CE_NOTE, mp,
 				"Unmounting, marking shared read-only");
 		}
+
 		XFS_BUF_UNDONE(sbp);
 		XFS_BUF_UNREAD(sbp);
 		XFS_BUF_UNDELAYWRITE(sbp);
@@ -1192,8 +1391,8 @@
 					  mp, sbp, XFS_BUF_ADDR(sbp));
 		if (error && mp->m_mk_sharedro)
 			xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting.  Filesystem may not be marked shared readonly");
+		xfs_buf_relse(sbp);
 	}
-	xfs_buf_relse(sbp);
 	return error;
 }
 
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 82304b9..76ad747 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -66,6 +66,7 @@
 struct xfs_bmap_free;
 struct xfs_extdelta;
 struct xfs_swapext;
+struct xfs_mru_cache;
 
 extern struct bhv_vfsops xfs_vfsops;
 extern struct bhv_vnodeops xfs_vnodeops;
@@ -424,17 +425,18 @@
 	struct notifier_block	m_icsb_notifier; /* hotplug cpu notifier */
 	struct mutex		m_icsb_mutex;	/* balancer sync lock */
 #endif
+	struct xfs_mru_cache	*m_filestream;  /* per-mount filestream data */
 } xfs_mount_t;
 
 /*
  * Flags for m_flags.
  */
-#define	XFS_MOUNT_WSYNC		(1ULL << 0)	/* for nfs - all metadata ops
+#define XFS_MOUNT_WSYNC		(1ULL << 0)	/* for nfs - all metadata ops
 						   must be synchronous except
 						   for space allocations */
-#define	XFS_MOUNT_INO64		(1ULL << 1)
+#define XFS_MOUNT_INO64		(1ULL << 1)
 			     /* (1ULL << 2)	-- currently unused */
-			     /* (1ULL << 3)	-- currently unused */
+#define XFS_MOUNT_WAS_CLEAN	(1ULL << 3)
 #define XFS_MOUNT_FS_SHUTDOWN	(1ULL << 4)	/* atomic stop of all filesystem
 						   operations, typically for
 						   disk errors in metadata */
@@ -463,6 +465,8 @@
 						 * I/O size in stat() */
 #define XFS_MOUNT_NO_PERCPU_SB	(1ULL << 23)	/* don't use per-cpu superblock
 						   counters */
+#define XFS_MOUNT_FILESTREAMS	(1ULL << 24)	/* enable the filestreams
+						   allocator */
 
 
 /*
@@ -511,6 +515,8 @@
 
 #define XFS_MAXIOFFSET(mp)	((mp)->m_maxioffset)
 
+#define XFS_LAST_UNMOUNT_WAS_CLEAN(mp)	\
+				((mp)->m_flags & XFS_MOUNT_WAS_CLEAN)
 #define XFS_FORCED_SHUTDOWN(mp)	((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
 #define xfs_force_shutdown(m,f)	\
 	bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
@@ -602,6 +608,7 @@
 
 extern xfs_mount_t *xfs_mount_init(void);
 extern void	xfs_mod_sb(xfs_trans_t *, __int64_t);
+extern int	xfs_log_sbcount(xfs_mount_t *, uint);
 extern void	xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
 extern int	xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int);
 extern void	xfs_mountfs_check_barriers(xfs_mount_t *mp);
@@ -618,12 +625,14 @@
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern int	xfs_readsb(xfs_mount_t *, int);
 extern void	xfs_freesb(xfs_mount_t *);
+extern int	xfs_fs_writable(xfs_mount_t *);
 extern void	xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
 extern int	xfs_syncsub(xfs_mount_t *, int, int *);
 extern int	xfs_sync_inodes(xfs_mount_t *, int, int *);
 extern xfs_agnumber_t	xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
 						xfs_agnumber_t);
 extern void	xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
+extern int	xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
 
 extern struct xfs_dmops xfs_dmcore_stub;
 extern struct xfs_qmops xfs_qmcore_stub;
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
new file mode 100644
index 0000000..7deb9e3
--- /dev/null
+++ b/fs/xfs/xfs_mru_cache.c
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2006-2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "xfs.h"
+#include "xfs_mru_cache.h"
+
+/*
+ * The MRU Cache data structure consists of a data store, an array of lists and
+ * a lock to protect its internal state.  At initialisation time, the client
+ * supplies an element lifetime in milliseconds and a group count, as well as a
+ * function pointer to call when deleting elements.  A data structure for
+ * queueing up work in the form of timed callbacks is also included.
+ *
+ * The group count controls how many lists are created, and thereby how finely
+ * the elements are grouped in time.  When reaping occurs, all the elements in
+ * all the lists whose time has expired are deleted.
+ *
+ * To give an example of how this works in practice, consider a client that
+ * initialises an MRU Cache with a lifetime of ten seconds and a group count of
+ * five.  Five internal lists will be created, each representing a two second
+ * period in time.  When the first element is added, time zero for the data
+ * structure is initialised to the current time.
+ *
+ * All the elements added in the first two seconds are appended to the first
+ * list.  Elements added in the third second go into the second list, and so on.
+ * If an element is accessed at any point, it is removed from its list and
+ * inserted at the head of the current most-recently-used list.
+ *
+ * The reaper function will have nothing to do until at least twelve seconds
+ * have elapsed since the first element was added.  The reason for this is that
+ * if it were called at t=11s, there could be elements in the first list that
+ * have only been inactive for nine seconds, so it still does nothing.  If it is
+ * called anywhere between t=12 and t=14 seconds, it will delete all the
+ * elements that remain in the first list.  It's therefore possible for elements
+ * to remain in the data store even after they've been inactive for up to
+ * (t + t/g) seconds, where t is the inactive element lifetime and g is the
+ * number of groups.
+ *
+ * The above example assumes that the reaper function gets called at least once
+ * every (t/g) seconds.  If it is called less frequently, unused elements will
+ * accumulate in the reap list until the reaper function is eventually called.
+ * The current implementation uses work queue callbacks to carefully time the
+ * reaper function calls, so this should happen rarely, if at all.
+ *
+ * From a design perspective, the primary reason for the choice of a list array
+ * representing discrete time intervals is that it's only practical to reap
+ * expired elements in groups of some appreciable size.  This automatically
+ * introduces a granularity to element lifetimes, so there's no point storing an
+ * individual timeout with each element that specifies a more precise reap time.
+ * The bonus is a saving of sizeof(long) bytes of memory per element stored.
+ *
+ * The elements could have been stored in just one list, but an array of
+ * counters or pointers would need to be maintained to allow them to be divided
+ * up into discrete time groups.  More critically, the process of touching or
+ * removing an element would involve walking large portions of the entire list,
+ * which would have a detrimental effect on performance.  The additional memory
+ * requirement for the array of list heads is minimal.
+ *
+ * When an element is touched or deleted, it needs to be removed from its
+ * current list.  Doubly linked lists are used to make the list maintenance
+ * portion of these operations O(1).  Since reaper timing can be imprecise,
+ * inserts and lookups can occur when there are no free lists available.  When
+ * this happens, all the elements on the LRU list need to be migrated to the end
+ * of the reap list.  To keep the list maintenance portion of these operations
+ * O(1) also, list tails need to be accessible without walking the entire list.
+ * This is the reason why doubly linked list heads are used.
+ */
+
+/*
+ * An MRU Cache is a dynamic data structure that stores its elements in a way
+ * that allows efficient lookups, but also groups them into discrete time
+ * intervals based on insertion time.  This allows elements to be efficiently
+ * and automatically reaped after a fixed period of inactivity.
+ *
+ * When a client data pointer is stored in the MRU Cache it needs to be added to
+ * both the data store and to one of the lists.  It must also be possible to
+ * access each of these entries via the other, i.e. to:
+ *
+ *    a) Walk a list, removing the corresponding data store entry for each item.
+ *    b) Look up a data store entry, then access its list entry directly.
+ *
+ * To achieve both of these goals, each entry must contain both a list entry and
+ * a key, in addition to the user's data pointer.  Note that it's not a good
+ * idea to have the client embed one of these structures at the top of their own
+ * data structure, because inserting the same item more than once would most
+ * likely result in a loop in one of the lists.  That's a sure-fire recipe for
+ * an infinite loop in the code.
+ */
+typedef struct xfs_mru_cache_elem
+{
+	struct list_head list_node;
+	unsigned long	key;
+	void		*value;
+} xfs_mru_cache_elem_t;
+
+static kmem_zone_t		*xfs_mru_elem_zone;
+static struct workqueue_struct	*xfs_mru_reap_wq;
+
+/*
+ * When inserting, destroying or reaping, it's first necessary to update the
+ * lists relative to a particular time.  In the case of destroying, that time
+ * will be well in the future to ensure that all items are moved to the reap
+ * list.  In all other cases though, the time will be the current time.
+ *
+ * This function enters a loop, moving the contents of the LRU list to the reap
+ * list again and again until either a) the lists are all empty, or b) time zero
+ * has been advanced sufficiently to be within the immediate element lifetime.
+ *
+ * Case a) above is detected by counting how many groups are migrated and
+ * stopping when they've all been moved.  Case b) is detected by monitoring the
+ * time_zero field, which is updated as each group is migrated.
+ *
+ * The return value is the earliest time that more migration could be needed, or
+ * zero if there's no need to schedule more work because the lists are empty.
+ */
+STATIC unsigned long
+_xfs_mru_cache_migrate(
+	xfs_mru_cache_t	*mru,
+	unsigned long	now)
+{
+	unsigned int	grp;
+	unsigned int	migrated = 0;
+	struct list_head *lru_list;
+
+	/* Nothing to do if the data store is empty. */
+	if (!mru->time_zero)
+		return 0;
+
+	/* While time zero is older than the time spanned by all the lists. */
+	while (mru->time_zero <= now - mru->grp_count * mru->grp_time) {
+
+		/*
+		 * If the LRU list isn't empty, migrate its elements to the tail
+		 * of the reap list.
+		 */
+		lru_list = mru->lists + mru->lru_grp;
+		if (!list_empty(lru_list))
+			list_splice_init(lru_list, mru->reap_list.prev);
+
+		/*
+		 * Advance the LRU group number, freeing the old LRU list to
+		 * become the new MRU list; advance time zero accordingly.
+		 */
+		mru->lru_grp = (mru->lru_grp + 1) % mru->grp_count;
+		mru->time_zero += mru->grp_time;
+
+		/*
+		 * If reaping is so far behind that all the elements on all the
+		 * lists have been migrated to the reap list, it's now empty.
+		 */
+		if (++migrated == mru->grp_count) {
+			mru->lru_grp = 0;
+			mru->time_zero = 0;
+			return 0;
+		}
+	}
+
+	/* Find the first non-empty list from the LRU end. */
+	for (grp = 0; grp < mru->grp_count; grp++) {
+
+		/* Check the grp'th list from the LRU end. */
+		lru_list = mru->lists + ((mru->lru_grp + grp) % mru->grp_count);
+		if (!list_empty(lru_list))
+			return mru->time_zero +
+			       (mru->grp_count + grp) * mru->grp_time;
+	}
+
+	/* All the lists must be empty. */
+	mru->lru_grp = 0;
+	mru->time_zero = 0;
+	return 0;
+}
+
+/*
+ * When inserting or doing a lookup, an element needs to be inserted into the
+ * MRU list.  The lists must be migrated first to ensure that they're
+ * up-to-date, otherwise the new element could be given a shorter lifetime in
+ * the cache than it should.
+ */
+STATIC void
+_xfs_mru_cache_list_insert(
+	xfs_mru_cache_t		*mru,
+	xfs_mru_cache_elem_t	*elem)
+{
+	unsigned int	grp = 0;
+	unsigned long	now = jiffies;
+
+	/*
+	 * If the data store is empty, initialise time zero, leave grp set to
+	 * zero and start the work queue timer if necessary.  Otherwise, set grp
+	 * to the number of group times that have elapsed since time zero.
+	 */
+	if (!_xfs_mru_cache_migrate(mru, now)) {
+		mru->time_zero = now;
+		if (!mru->next_reap)
+			mru->next_reap = mru->grp_count * mru->grp_time;
+	} else {
+		grp = (now - mru->time_zero) / mru->grp_time;
+		grp = (mru->lru_grp + grp) % mru->grp_count;
+	}
+
+	/* Insert the element at the tail of the corresponding list. */
+	list_add_tail(&elem->list_node, mru->lists + grp);
+}
+
+/*
+ * When destroying or reaping, all the elements that were migrated to the reap
+ * list need to be deleted.  For each element this involves removing it from the
+ * data store, removing it from the reap list, calling the client's free
+ * function and deleting the element from the element zone.
+ */
+STATIC void
+_xfs_mru_cache_clear_reap_list(
+	xfs_mru_cache_t		*mru)
+{
+	xfs_mru_cache_elem_t	*elem, *next;
+	struct list_head	tmp;
+
+	INIT_LIST_HEAD(&tmp);
+	list_for_each_entry_safe(elem, next, &mru->reap_list, list_node) {
+
+		/* Remove the element from the data store. */
+		radix_tree_delete(&mru->store, elem->key);
+
+		/*
+		 * remove to temp list so it can be freed without
+		 * needing to hold the lock
+		 */
+		list_move(&elem->list_node, &tmp);
+	}
+	mutex_spinunlock(&mru->lock, 0);
+
+	list_for_each_entry_safe(elem, next, &tmp, list_node) {
+
+		/* Remove the element from the reap list. */
+		list_del_init(&elem->list_node);
+
+		/* Call the client's free function with the key and value pointer. */
+		mru->free_func(elem->key, elem->value);
+
+		/* Free the element structure. */
+		kmem_zone_free(xfs_mru_elem_zone, elem);
+	}
+
+	mutex_spinlock(&mru->lock);
+}
+
+/*
+ * We fire the reap timer every group expiry interval so
+ * we always have a reaper ready to run. This makes shutdown
+ * and flushing of the reaper easy to do. Hence we need to
+ * keep when the next reap must occur so we can determine
+ * at each interval whether there is anything we need to do.
+ */
+STATIC void
+_xfs_mru_cache_reap(
+	struct work_struct	*work)
+{
+	xfs_mru_cache_t		*mru = container_of(work, xfs_mru_cache_t, work.work);
+	unsigned long		now;
+
+	ASSERT(mru && mru->lists);
+	if (!mru || !mru->lists)
+		return;
+
+	mutex_spinlock(&mru->lock);
+	now = jiffies;
+	if (mru->reap_all ||
+	    (mru->next_reap && time_after(now, mru->next_reap))) {
+		if (mru->reap_all)
+			now += mru->grp_count * mru->grp_time * 2;
+		mru->next_reap = _xfs_mru_cache_migrate(mru, now);
+		_xfs_mru_cache_clear_reap_list(mru);
+	}
+
+	/*
+	 * the process that triggered the reap_all is responsible
+	 * for restating the periodic reap if it is required.
+	 */
+	if (!mru->reap_all)
+		queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
+	mru->reap_all = 0;
+	mutex_spinunlock(&mru->lock, 0);
+}
+
+int
+xfs_mru_cache_init(void)
+{
+	xfs_mru_elem_zone = kmem_zone_init(sizeof(xfs_mru_cache_elem_t),
+	                                 "xfs_mru_cache_elem");
+	if (!xfs_mru_elem_zone)
+		return ENOMEM;
+
+	xfs_mru_reap_wq = create_singlethread_workqueue("xfs_mru_cache");
+	if (!xfs_mru_reap_wq) {
+		kmem_zone_destroy(xfs_mru_elem_zone);
+		return ENOMEM;
+	}
+
+	return 0;
+}
+
+void
+xfs_mru_cache_uninit(void)
+{
+	destroy_workqueue(xfs_mru_reap_wq);
+	kmem_zone_destroy(xfs_mru_elem_zone);
+}
+
+/*
+ * To initialise a struct xfs_mru_cache pointer, call xfs_mru_cache_create()
+ * with the address of the pointer, a lifetime value in milliseconds, a group
+ * count and a free function to use when deleting elements.  This function
+ * returns 0 if the initialisation was successful.
+ */
+int
+xfs_mru_cache_create(
+	xfs_mru_cache_t		**mrup,
+	unsigned int		lifetime_ms,
+	unsigned int		grp_count,
+	xfs_mru_cache_free_func_t free_func)
+{
+	xfs_mru_cache_t	*mru = NULL;
+	int		err = 0, grp;
+	unsigned int	grp_time;
+
+	if (mrup)
+		*mrup = NULL;
+
+	if (!mrup || !grp_count || !lifetime_ms || !free_func)
+		return EINVAL;
+
+	if (!(grp_time = msecs_to_jiffies(lifetime_ms) / grp_count))
+		return EINVAL;
+
+	if (!(mru = kmem_zalloc(sizeof(*mru), KM_SLEEP)))
+		return ENOMEM;
+
+	/* An extra list is needed to avoid reaping up to a grp_time early. */
+	mru->grp_count = grp_count + 1;
+	mru->lists = kmem_alloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP);
+
+	if (!mru->lists) {
+		err = ENOMEM;
+		goto exit;
+	}
+
+	for (grp = 0; grp < mru->grp_count; grp++)
+		INIT_LIST_HEAD(mru->lists + grp);
+
+	/*
+	 * We use GFP_KERNEL radix tree preload and do inserts under a
+	 * spinlock so GFP_ATOMIC is appropriate for the radix tree itself.
+	 */
+	INIT_RADIX_TREE(&mru->store, GFP_ATOMIC);
+	INIT_LIST_HEAD(&mru->reap_list);
+	spinlock_init(&mru->lock, "xfs_mru_cache");
+	INIT_DELAYED_WORK(&mru->work, _xfs_mru_cache_reap);
+
+	mru->grp_time  = grp_time;
+	mru->free_func = free_func;
+
+	/* start up the reaper event */
+	mru->next_reap = 0;
+	mru->reap_all = 0;
+	queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
+
+	*mrup = mru;
+
+exit:
+	if (err && mru && mru->lists)
+		kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists));
+	if (err && mru)
+		kmem_free(mru, sizeof(*mru));
+
+	return err;
+}
+
+/*
+ * Call xfs_mru_cache_flush() to flush out all cached entries, calling their
+ * free functions as they're deleted.  When this function returns, the caller is
+ * guaranteed that all the free functions for all the elements have finished
+ * executing.
+ *
+ * While we are flushing, we stop the periodic reaper event from triggering.
+ * Normally, we want to restart this periodic event, but if we are shutting
+ * down the cache we do not want it restarted. hence the restart parameter
+ * where 0 = do not restart reaper and 1 = restart reaper.
+ */
+void
+xfs_mru_cache_flush(
+	xfs_mru_cache_t		*mru,
+	int			restart)
+{
+	if (!mru || !mru->lists)
+		return;
+
+	cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
+
+	mutex_spinlock(&mru->lock);
+	mru->reap_all = 1;
+	mutex_spinunlock(&mru->lock, 0);
+
+	queue_work(xfs_mru_reap_wq, &mru->work.work);
+	flush_workqueue(xfs_mru_reap_wq);
+
+	mutex_spinlock(&mru->lock);
+	WARN_ON_ONCE(mru->reap_all != 0);
+	mru->reap_all = 0;
+	if (restart)
+		queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
+	mutex_spinunlock(&mru->lock, 0);
+}
+
+void
+xfs_mru_cache_destroy(
+	xfs_mru_cache_t		*mru)
+{
+	if (!mru || !mru->lists)
+		return;
+
+	/* we don't want the reaper to restart here */
+	xfs_mru_cache_flush(mru, 0);
+
+	kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists));
+	kmem_free(mru, sizeof(*mru));
+}
+
+/*
+ * To insert an element, call xfs_mru_cache_insert() with the data store, the
+ * element's key and the client data pointer.  This function returns 0 on
+ * success or ENOMEM if memory for the data element couldn't be allocated.
+ */
+int
+xfs_mru_cache_insert(
+	xfs_mru_cache_t	*mru,
+	unsigned long	key,
+	void		*value)
+{
+	xfs_mru_cache_elem_t *elem;
+
+	ASSERT(mru && mru->lists);
+	if (!mru || !mru->lists)
+		return EINVAL;
+
+	elem = kmem_zone_zalloc(xfs_mru_elem_zone, KM_SLEEP);
+	if (!elem)
+		return ENOMEM;
+
+	if (radix_tree_preload(GFP_KERNEL)) {
+		kmem_zone_free(xfs_mru_elem_zone, elem);
+		return ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&elem->list_node);
+	elem->key = key;
+	elem->value = value;
+
+	mutex_spinlock(&mru->lock);
+
+	radix_tree_insert(&mru->store, key, elem);
+	radix_tree_preload_end();
+	_xfs_mru_cache_list_insert(mru, elem);
+
+	mutex_spinunlock(&mru->lock, 0);
+
+	return 0;
+}
+
+/*
+ * To remove an element without calling the free function, call
+ * xfs_mru_cache_remove() with the data store and the element's key.  On success
+ * the client data pointer for the removed element is returned, otherwise this
+ * function will return a NULL pointer.
+ */
+void *
+xfs_mru_cache_remove(
+	xfs_mru_cache_t	*mru,
+	unsigned long	key)
+{
+	xfs_mru_cache_elem_t *elem;
+	void		*value = NULL;
+
+	ASSERT(mru && mru->lists);
+	if (!mru || !mru->lists)
+		return NULL;
+
+	mutex_spinlock(&mru->lock);
+	elem = radix_tree_delete(&mru->store, key);
+	if (elem) {
+		value = elem->value;
+		list_del(&elem->list_node);
+	}
+
+	mutex_spinunlock(&mru->lock, 0);
+
+	if (elem)
+		kmem_zone_free(xfs_mru_elem_zone, elem);
+
+	return value;
+}
+
+/*
+ * To remove and element and call the free function, call xfs_mru_cache_delete()
+ * with the data store and the element's key.
+ */
+void
+xfs_mru_cache_delete(
+	xfs_mru_cache_t	*mru,
+	unsigned long	key)
+{
+	void		*value = xfs_mru_cache_remove(mru, key);
+
+	if (value)
+		mru->free_func(key, value);
+}
+
+/*
+ * To look up an element using its key, call xfs_mru_cache_lookup() with the
+ * data store and the element's key.  If found, the element will be moved to the
+ * head of the MRU list to indicate that it's been touched.
+ *
+ * The internal data structures are protected by a spinlock that is STILL HELD
+ * when this function returns.  Call xfs_mru_cache_done() to release it.  Note
+ * that it is not safe to call any function that might sleep in the interim.
+ *
+ * The implementation could have used reference counting to avoid this
+ * restriction, but since most clients simply want to get, set or test a member
+ * of the returned data structure, the extra per-element memory isn't warranted.
+ *
+ * If the element isn't found, this function returns NULL and the spinlock is
+ * released.  xfs_mru_cache_done() should NOT be called when this occurs.
+ */
+void *
+xfs_mru_cache_lookup(
+	xfs_mru_cache_t	*mru,
+	unsigned long	key)
+{
+	xfs_mru_cache_elem_t *elem;
+
+	ASSERT(mru && mru->lists);
+	if (!mru || !mru->lists)
+		return NULL;
+
+	mutex_spinlock(&mru->lock);
+	elem = radix_tree_lookup(&mru->store, key);
+	if (elem) {
+		list_del(&elem->list_node);
+		_xfs_mru_cache_list_insert(mru, elem);
+	}
+	else
+		mutex_spinunlock(&mru->lock, 0);
+
+	return elem ? elem->value : NULL;
+}
+
+/*
+ * To look up an element using its key, but leave its location in the internal
+ * lists alone, call xfs_mru_cache_peek().  If the element isn't found, this
+ * function returns NULL.
+ *
+ * See the comments above the declaration of the xfs_mru_cache_lookup() function
+ * for important locking information pertaining to this call.
+ */
+void *
+xfs_mru_cache_peek(
+	xfs_mru_cache_t	*mru,
+	unsigned long	key)
+{
+	xfs_mru_cache_elem_t *elem;
+
+	ASSERT(mru && mru->lists);
+	if (!mru || !mru->lists)
+		return NULL;
+
+	mutex_spinlock(&mru->lock);
+	elem = radix_tree_lookup(&mru->store, key);
+	if (!elem)
+		mutex_spinunlock(&mru->lock, 0);
+
+	return elem ? elem->value : NULL;
+}
+
+/*
+ * To release the internal data structure spinlock after having performed an
+ * xfs_mru_cache_lookup() or an xfs_mru_cache_peek(), call xfs_mru_cache_done()
+ * with the data store pointer.
+ */
+void
+xfs_mru_cache_done(
+	xfs_mru_cache_t	*mru)
+{
+	mutex_spinunlock(&mru->lock, 0);
+}
diff --git a/fs/xfs/xfs_mru_cache.h b/fs/xfs/xfs_mru_cache.h
new file mode 100644
index 0000000..624fd10
--- /dev/null
+++ b/fs/xfs/xfs_mru_cache.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2006-2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __XFS_MRU_CACHE_H__
+#define __XFS_MRU_CACHE_H__
+
+
+/* Function pointer type for callback to free a client's data pointer. */
+typedef void (*xfs_mru_cache_free_func_t)(unsigned long, void*);
+
+typedef struct xfs_mru_cache
+{
+	struct radix_tree_root	store;     /* Core storage data structure.  */
+	struct list_head	*lists;    /* Array of lists, one per grp.  */
+	struct list_head	reap_list; /* Elements overdue for reaping. */
+	spinlock_t		lock;      /* Lock to protect this struct.  */
+	unsigned int		grp_count; /* Number of discrete groups.    */
+	unsigned int		grp_time;  /* Time period spanned by grps.  */
+	unsigned int		lru_grp;   /* Group containing time zero.   */
+	unsigned long		time_zero; /* Time first element was added. */
+	unsigned long		next_reap; /* Time that the reaper should
+					      next do something. */
+	unsigned int		reap_all;  /* if set, reap all lists */
+	xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */
+	struct delayed_work	work;      /* Workqueue data for reaping.   */
+} xfs_mru_cache_t;
+
+int xfs_mru_cache_init(void);
+void xfs_mru_cache_uninit(void);
+int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms,
+			     unsigned int grp_count,
+			     xfs_mru_cache_free_func_t free_func);
+void xfs_mru_cache_flush(xfs_mru_cache_t *mru, int restart);
+void xfs_mru_cache_destroy(struct xfs_mru_cache *mru);
+int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key,
+				void *value);
+void * xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key);
+void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key);
+void *xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key);
+void *xfs_mru_cache_peek(struct xfs_mru_cache *mru, unsigned long key);
+void xfs_mru_cache_done(struct xfs_mru_cache *mru);
+
+#endif /* __XFS_MRU_CACHE_H__ */
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index b3a5f07..47082c0 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1882,11 +1882,13 @@
 	    (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
 	    (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
 		return XFS_ERROR(EINVAL);
+	if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks)))
+		return error;
 	/*
 	 * Read in the last block of the device, make sure it exists.
 	 */
 	error = xfs_read_buf(mp, mp->m_rtdev_targp,
-			XFS_FSB_TO_BB(mp, in->newblocks - 1),
+			XFS_FSB_TO_BB(mp, nrblocks - 1),
 			XFS_FSB_TO_BB(mp, 1), 0, &bp);
 	if (error)
 		return error;
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h
index 188b296..fcf28db 100644
--- a/fs/xfs/xfs_rw.h
+++ b/fs/xfs/xfs_rw.h
@@ -72,6 +72,34 @@
 }
 
 /*
+ * Flags for xfs_free_eofblocks
+ */
+#define XFS_FREE_EOF_LOCK	(1<<0)
+#define XFS_FREE_EOF_NOLOCK	(1<<1)
+
+
+/*
+ * helper function to extract extent size hint from inode
+ */
+STATIC_INLINE xfs_extlen_t
+xfs_get_extsz_hint(
+	xfs_inode_t	*ip)
+{
+	xfs_extlen_t	extsz;
+
+	if (unlikely(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
+		extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
+				? ip->i_d.di_extsize
+				: ip->i_mount->m_sb.sb_rextsize;
+		ASSERT(extsz);
+	} else {
+		extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
+				? ip->i_d.di_extsize : 0;
+	}
+	return extsz;
+}
+
+/*
  * Prototypes for functions in xfs_rw.c.
  */
 extern int xfs_write_clear_setuid(struct xfs_inode *ip);
@@ -91,10 +119,12 @@
 extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
 extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
 extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags,
-		       cred_t *credp);
+			cred_t *credp);
 extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf,
-				 xfs_off_t offset, cred_t *credp, int flags);
+			xfs_off_t offset, cred_t *credp, int flags);
 extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
-			   cred_t *credp);
+			cred_t *credp);
+extern int xfs_free_eofblocks(struct xfs_mount *mp, struct xfs_inode *ip,
+			int flags);
 
 #endif /* __XFS_RW_H__ */
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 467854b..ef42537 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -74,12 +74,13 @@
  */
 #define XFS_SB_VERSION2_REALFBITS	0x00ffffff	/* Mask: features */
 #define XFS_SB_VERSION2_RESERVED1BIT	0x00000001
-#define XFS_SB_VERSION2_RESERVED2BIT	0x00000002
+#define XFS_SB_VERSION2_LAZYSBCOUNTBIT	0x00000002	/* Superblk counters */
 #define XFS_SB_VERSION2_RESERVED4BIT	0x00000004
 #define XFS_SB_VERSION2_ATTR2BIT	0x00000008	/* Inline attr rework */
 
 #define	XFS_SB_VERSION2_OKREALFBITS	\
-	(XFS_SB_VERSION2_ATTR2BIT)
+	(XFS_SB_VERSION2_LAZYSBCOUNTBIT	| \
+	 XFS_SB_VERSION2_ATTR2BIT)
 #define	XFS_SB_VERSION2_OKSASHFBITS	\
 	(0)
 #define XFS_SB_VERSION2_OKREALBITS	\
@@ -181,6 +182,9 @@
 #define XFS_SB_SHARED_VN	XFS_SB_MVAL(SHARED_VN)
 #define XFS_SB_UNIT		XFS_SB_MVAL(UNIT)
 #define XFS_SB_WIDTH		XFS_SB_MVAL(WIDTH)
+#define XFS_SB_ICOUNT		XFS_SB_MVAL(ICOUNT)
+#define XFS_SB_IFREE		XFS_SB_MVAL(IFREE)
+#define XFS_SB_FDBLOCKS		XFS_SB_MVAL(FDBLOCKS)
 #define XFS_SB_FEATURES2	XFS_SB_MVAL(FEATURES2)
 #define	XFS_SB_NUM_BITS		((int)XFS_SBS_FIELDCOUNT)
 #define	XFS_SB_ALL_BITS		((1LL << XFS_SB_NUM_BITS) - 1)
@@ -188,7 +192,7 @@
 	(XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
 	 XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
 	 XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
-	 XFS_SB_FEATURES2)
+	 XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2)
 
 
 /*
@@ -414,6 +418,12 @@
  *	 ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT)
  */
 
+static inline int xfs_sb_version_haslazysbcount(xfs_sb_t *sbp)
+{
+	return (XFS_SB_VERSION_HASMOREBITS(sbp) &&	\
+		((sbp)->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT));
+}
+
 #define XFS_SB_VERSION_HASATTR2(sbp)	xfs_sb_version_hasattr2(sbp)
 static inline int xfs_sb_version_hasattr2(xfs_sb_t *sbp)
 {
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index cc2d609..356d662 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -427,6 +427,14 @@
  *
  * Mark the transaction structure to indicate that the superblock
  * needs to be updated before committing.
+ *
+ * Because we may not be keeping track of allocated/free inodes and
+ * used filesystem blocks in the superblock, we do not mark the
+ * superblock dirty in this transaction if we modify these fields.
+ * We still need to update the transaction deltas so that they get
+ * applied to the incore superblock, but we don't want them to
+ * cause the superblock to get locked and logged if these are the
+ * only fields in the superblock that the transaction modifies.
  */
 void
 xfs_trans_mod_sb(
@@ -434,13 +442,19 @@
 	uint		field,
 	int64_t		delta)
 {
+	uint32_t	flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY);
+	xfs_mount_t	*mp = tp->t_mountp;
 
 	switch (field) {
 	case XFS_TRANS_SB_ICOUNT:
 		tp->t_icount_delta += delta;
+		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+			flags &= ~XFS_TRANS_SB_DIRTY;
 		break;
 	case XFS_TRANS_SB_IFREE:
 		tp->t_ifree_delta += delta;
+		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+			flags &= ~XFS_TRANS_SB_DIRTY;
 		break;
 	case XFS_TRANS_SB_FDBLOCKS:
 		/*
@@ -453,6 +467,8 @@
 			ASSERT(tp->t_blk_res_used <= tp->t_blk_res);
 		}
 		tp->t_fdblocks_delta += delta;
+		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+			flags &= ~XFS_TRANS_SB_DIRTY;
 		break;
 	case XFS_TRANS_SB_RES_FDBLOCKS:
 		/*
@@ -462,6 +478,8 @@
 		 */
 		ASSERT(delta < 0);
 		tp->t_res_fdblocks_delta += delta;
+		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+			flags &= ~XFS_TRANS_SB_DIRTY;
 		break;
 	case XFS_TRANS_SB_FREXTENTS:
 		/*
@@ -515,7 +533,7 @@
 		return;
 	}
 
-	tp->t_flags |= (XFS_TRANS_SB_DIRTY | XFS_TRANS_DIRTY);
+	tp->t_flags |= flags;
 }
 
 /*
@@ -544,18 +562,23 @@
 	       (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta +
 		tp->t_ag_btree_delta));
 
-	if (tp->t_icount_delta != 0) {
-		INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
-	}
-	if (tp->t_ifree_delta != 0) {
-		INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
-	}
+	/*
+	 * Only update the superblock counters if we are logging them
+	 */
+	if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
+		if (tp->t_icount_delta != 0) {
+			INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
+		}
+		if (tp->t_ifree_delta != 0) {
+			INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
+		}
 
-	if (tp->t_fdblocks_delta != 0) {
-		INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
-	}
-	if (tp->t_res_fdblocks_delta != 0) {
-		INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
+		if (tp->t_fdblocks_delta != 0) {
+			INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
+		}
+		if (tp->t_res_fdblocks_delta != 0) {
+			INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
+		}
 	}
 
 	if (tp->t_frextents_delta != 0) {
@@ -615,11 +638,23 @@
 }
 
 /*
- * xfs_trans_unreserve_and_mod_sb() is called to release unused
- * reservations and apply superblock counter changes to the in-core
- * superblock.
+ * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
+ * and apply superblock counter changes to the in-core superblock.  The
+ * t_res_fdblocks_delta and t_res_frextents_delta fields are explicitly NOT
+ * applied to the in-core superblock.  The idea is that that has already been
+ * done.
  *
  * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
+ * However, we have to ensure that we only modify each superblock field only
+ * once because the application of the delta values may not be atomic. That can
+ * lead to ENOSPC races occurring if we have two separate modifcations of the
+ * free space counter to put back the entire reservation and then take away
+ * what we used.
+ *
+ * If we are not logging superblock counters, then the inode allocated/free and
+ * used block counts are not updated in the on disk superblock. In this case,
+ * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
+ * still need to update the incore superblock with the changes.
  */
 STATIC void
 xfs_trans_unreserve_and_mod_sb(
@@ -627,40 +662,49 @@
 {
 	xfs_mod_sb_t	msb[14];	/* If you add cases, add entries */
 	xfs_mod_sb_t	*msbp;
+	xfs_mount_t	*mp = tp->t_mountp;
 	/* REFERENCED */
 	int		error;
 	int		rsvd;
+	int64_t		blkdelta = 0;
+	int64_t		rtxdelta = 0;
 
 	msbp = msb;
 	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
 
-	/*
-	 * Release any reserved blocks.  Any that were allocated
-	 * will be taken back again by fdblocks_delta below.
-	 */
-	if (tp->t_blk_res > 0) {
+	/* calculate free blocks delta */
+	if (tp->t_blk_res > 0)
+		blkdelta = tp->t_blk_res;
+
+	if ((tp->t_fdblocks_delta != 0) &&
+	    (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
+	     (tp->t_flags & XFS_TRANS_SB_DIRTY)))
+	        blkdelta += tp->t_fdblocks_delta;
+
+	if (blkdelta != 0) {
 		msbp->msb_field = XFS_SBS_FDBLOCKS;
-		msbp->msb_delta = tp->t_blk_res;
+		msbp->msb_delta = blkdelta;
 		msbp++;
 	}
 
-	/*
-	 * Release any reserved real time extents .  Any that were
-	 * allocated will be taken back again by frextents_delta below.
-	 */
-	if (tp->t_rtx_res > 0) {
+	/* calculate free realtime extents delta */
+	if (tp->t_rtx_res > 0)
+		rtxdelta = tp->t_rtx_res;
+
+	if ((tp->t_frextents_delta != 0) &&
+	    (tp->t_flags & XFS_TRANS_SB_DIRTY))
+		rtxdelta += tp->t_frextents_delta;
+
+	if (rtxdelta != 0) {
 		msbp->msb_field = XFS_SBS_FREXTENTS;
-		msbp->msb_delta = tp->t_rtx_res;
+		msbp->msb_delta = rtxdelta;
 		msbp++;
 	}
 
-	/*
-	 * Apply any superblock modifications to the in-core version.
-	 * The t_res_fdblocks_delta and t_res_frextents_delta fields are
-	 * explicitly NOT applied to the in-core superblock.
-	 * The idea is that that has already been done.
-	 */
-	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
+	/* apply remaining deltas */
+
+	if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
+	     (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
 		if (tp->t_icount_delta != 0) {
 			msbp->msb_field = XFS_SBS_ICOUNT;
 			msbp->msb_delta = tp->t_icount_delta;
@@ -671,16 +715,9 @@
 			msbp->msb_delta = tp->t_ifree_delta;
 			msbp++;
 		}
-		if (tp->t_fdblocks_delta != 0) {
-			msbp->msb_field = XFS_SBS_FDBLOCKS;
-			msbp->msb_delta = tp->t_fdblocks_delta;
-			msbp++;
-		}
-		if (tp->t_frextents_delta != 0) {
-			msbp->msb_field = XFS_SBS_FREXTENTS;
-			msbp->msb_delta = tp->t_frextents_delta;
-			msbp++;
-		}
+	}
+
+	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
 		if (tp->t_dblocks_delta != 0) {
 			msbp->msb_field = XFS_SBS_DBLOCKS;
 			msbp->msb_delta = tp->t_dblocks_delta;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 7dfcc45..0e26e72 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -94,7 +94,8 @@
 #define	XFS_TRANS_GROWFSRT_ZERO		38
 #define	XFS_TRANS_GROWFSRT_FREE		39
 #define	XFS_TRANS_SWAPEXT		40
-#define	XFS_TRANS_TYPE_MAX		40
+#define	XFS_TRANS_SB_COUNT		41
+#define	XFS_TRANS_TYPE_MAX		41
 /* new transaction types need to be reflected in xfs_logprint(8) */
 
 
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 65c5612..11f5ea2 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -51,6 +51,8 @@
 #include "xfs_acl.h"
 #include "xfs_attr.h"
 #include "xfs_clnt.h"
+#include "xfs_mru_cache.h"
+#include "xfs_filestream.h"
 #include "xfs_fsops.h"
 
 STATIC int	xfs_sync(bhv_desc_t *, int, cred_t *);
@@ -81,6 +83,8 @@
 	xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
 	xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
 	xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
+	xfs_mru_cache_init();
+	xfs_filestream_init();
 
 	/*
 	 * The size of the zone allocated buf log item is the maximum
@@ -164,6 +168,8 @@
 	xfs_cleanup_procfs();
 	xfs_sysctl_unregister();
 	xfs_refcache_destroy();
+	xfs_filestream_uninit();
+	xfs_mru_cache_uninit();
 	xfs_acl_zone_destroy(xfs_acl_zone);
 
 #ifdef XFS_DIR2_TRACE
@@ -320,6 +326,9 @@
 	else
 		mp->m_flags &= ~XFS_MOUNT_BARRIER;
 
+	if (ap->flags2 & XFSMNT2_FILESTREAMS)
+		mp->m_flags |= XFS_MOUNT_FILESTREAMS;
+
 	return 0;
 }
 
@@ -518,6 +527,9 @@
 	if (mp->m_flags & XFS_MOUNT_BARRIER)
 		xfs_mountfs_check_barriers(mp);
 
+	if ((error = xfs_filestream_mount(mp)))
+		goto error2;
+
 	error = XFS_IOINIT(vfsp, args, flags);
 	if (error)
 		goto error2;
@@ -575,6 +587,13 @@
 	 */
 	xfs_refcache_purge_mp(mp);
 
+	/*
+	 * Blow away any referenced inode in the filestreams cache.
+	 * This can and will cause log traffic as inodes go inactive
+	 * here.
+	 */
+	xfs_filestream_unmount(mp);
+
 	XFS_bflush(mp->m_ddev_targp);
 	error = xfs_unmount_flush(mp, 0);
 	if (error)
@@ -640,7 +659,7 @@
 	 * we can write the unmount record.
 	 */
 	do {
-		xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, NULL);
+		xfs_syncsub(mp, SYNC_INODE_QUIESCE, NULL);
 		pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
 		if (!pincount) {
 			delay(50);
@@ -651,6 +670,30 @@
 	return 0;
 }
 
+/*
+ * Second stage of a quiesce. The data is already synced, now we have to take
+ * care of the metadata. New transactions are already blocked, so we need to
+ * wait for any remaining transactions to drain out before proceding.
+ */
+STATIC void
+xfs_attr_quiesce(
+	xfs_mount_t	*mp)
+{
+	/* wait for all modifications to complete */
+	while (atomic_read(&mp->m_active_trans) > 0)
+		delay(100);
+
+	/* flush inodes and push all remaining buffers out to disk */
+	xfs_quiesce_fs(mp);
+
+	ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
+
+	/* Push the superblock and write an unmount record */
+	xfs_log_sbcount(mp, 1);
+	xfs_log_unmount_write(mp);
+	xfs_unmountfs_writesb(mp);
+}
+
 STATIC int
 xfs_mntupdate(
 	bhv_desc_t			*bdp,
@@ -670,10 +713,9 @@
 			mp->m_flags &= ~XFS_MOUNT_BARRIER;
 		}
 	} else if (!(vfsp->vfs_flag & VFS_RDONLY)) {	/* rw -> ro */
-		bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL);
-		xfs_quiesce_fs(mp);
-		xfs_log_unmount_write(mp);
-		xfs_unmountfs_writesb(mp);
+		xfs_filestream_flush(mp);
+		bhv_vfs_sync(vfsp, SYNC_DATA_QUIESCE, NULL);
+		xfs_attr_quiesce(mp);
 		vfsp->vfs_flag |= VFS_RDONLY;
 	}
 	return 0;
@@ -887,6 +929,9 @@
 {
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
 
+	if (flags & SYNC_IOWAIT)
+		xfs_filestream_flush(mp);
+
 	return xfs_syncsub(mp, flags, NULL);
 }
 
@@ -1128,58 +1173,41 @@
 		 * in the inode list.
 		 */
 
-		if ((flags & SYNC_CLOSE)  && (vp != NULL)) {
-			/*
-			 * This is the shutdown case.  We just need to
-			 * flush and invalidate all the pages associated
-			 * with the inode.  Drop the inode lock since
-			 * we can't hold it across calls to the buffer
-			 * cache.
-			 *
-			 * We don't set the VREMAPPING bit in the vnode
-			 * here, because we don't hold the vnode lock
-			 * exclusively.  It doesn't really matter, though,
-			 * because we only come here when we're shutting
-			 * down anyway.
-			 */
+		/*
+		 * If we have to flush data or wait for I/O completion
+		 * we need to drop the ilock that we currently hold.
+		 * If we need to drop the lock, insert a marker if we
+		 * have not already done so.
+		 */
+		if ((flags & (SYNC_CLOSE|SYNC_IOWAIT)) ||
+		    ((flags & SYNC_DELWRI) && VN_DIRTY(vp))) {
+			if (mount_locked) {
+				IPOINTER_INSERT(ip, mp);
+			}
 			xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
-			if (XFS_FORCED_SHUTDOWN(mp)) {
-				bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
-			} else {
-				error = bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF);
-			}
-
-			xfs_ilock(ip, XFS_ILOCK_SHARED);
-
-		} else if ((flags & SYNC_DELWRI) && (vp != NULL)) {
-			if (VN_DIRTY(vp)) {
-				/* We need to have dropped the lock here,
-				 * so insert a marker if we have not already
-				 * done so.
-				 */
-				if (mount_locked) {
-					IPOINTER_INSERT(ip, mp);
-				}
-
-				/*
-				 * Drop the inode lock since we can't hold it
-				 * across calls to the buffer cache.
-				 */
-				xfs_iunlock(ip, XFS_ILOCK_SHARED);
+			if (flags & SYNC_CLOSE) {
+				/* Shutdown case. Flush and invalidate. */
+				if (XFS_FORCED_SHUTDOWN(mp))
+					bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
+				else
+					error = bhv_vop_flushinval_pages(vp, 0,
+								-1, FI_REMAPF);
+			} else if ((flags & SYNC_DELWRI) && VN_DIRTY(vp)) {
 				error = bhv_vop_flush_pages(vp, (xfs_off_t)0,
 							-1, fflag, FI_NONE);
-				xfs_ilock(ip, XFS_ILOCK_SHARED);
 			}
 
+			/*
+			 * When freezing, we need to wait ensure all I/O (including direct
+			 * I/O) is complete to ensure no further data modification can take
+			 * place after this point
+			 */
+			if (flags & SYNC_IOWAIT)
+				vn_iowait(vp);
+
+			xfs_ilock(ip, XFS_ILOCK_SHARED);
 		}
-		/*
-		 * When freezing, we need to wait ensure all I/O (including direct
-		 * I/O) is complete to ensure no further data modification can take
-		 * place after this point
-		 */
-		if (flags & SYNC_IOWAIT)
-			vn_iowait(vp);
 
 		if (flags & SYNC_BDFLUSH) {
 			if ((flags & SYNC_ATTR) &&
@@ -1514,6 +1542,15 @@
 	}
 
 	/*
+	 * If asked, update the disk superblock with incore counter values if we
+	 * are using non-persistent counters so that they don't get too far out
+	 * of sync if we crash or get a forced shutdown. We don't want to force
+	 * this to disk, just get a transaction into the iclogs....
+	 */
+	if (flags & SYNC_SUPER)
+		xfs_log_sbcount(mp, 0);
+
+	/*
 	 * Now check to see if the log needs a "dummy" transaction.
 	 */
 
@@ -1645,6 +1682,7 @@
 					 * in stat(). */
 #define MNTOPT_ATTR2	"attr2"		/* do use attr2 attribute format */
 #define MNTOPT_NOATTR2	"noattr2"	/* do not use attr2 attribute format */
+#define MNTOPT_FILESTREAM  "filestreams" /* use filestreams allocator */
 
 STATIC unsigned long
 suffix_strtoul(char *s, char **endp, unsigned int base)
@@ -1831,6 +1869,8 @@
 			args->flags |= XFSMNT_ATTR2;
 		} else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
 			args->flags &= ~XFSMNT_ATTR2;
+		} else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
+			args->flags2 |= XFSMNT2_FILESTREAMS;
 		} else if (!strcmp(this_char, "osyncisdsync")) {
 			/* no-op, this is now the default */
 			cmn_err(CE_WARN,
@@ -1959,9 +1999,9 @@
 }
 
 /*
- * Second stage of a freeze. The data is already frozen, now we have to take
- * care of the metadata. New transactions are already blocked, so we need to
- * wait for any remaining transactions to drain out before proceding.
+ * Second stage of a freeze. The data is already frozen so we only
+ * need to take care of themetadata. Once that's done write a dummy
+ * record to dirty the log in case of a crash while frozen.
  */
 STATIC void
 xfs_freeze(
@@ -1969,18 +2009,7 @@
 {
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
 
-	/* wait for all modifications to complete */
-	while (atomic_read(&mp->m_active_trans) > 0)
-		delay(100);
-
-	/* flush inodes and push all remaining buffers out to disk */
-	xfs_quiesce_fs(mp);
-
-	ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
-
-	/* Push the superblock and write an unmount record */
-	xfs_log_unmount_write(mp);
-	xfs_unmountfs_writesb(mp);
+	xfs_attr_quiesce(mp);
 	xfs_fs_log_dummy(mp);
 }
 
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index de17aed..79b5227 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -51,6 +51,7 @@
 #include "xfs_refcache.h"
 #include "xfs_trans_space.h"
 #include "xfs_log_priv.h"
+#include "xfs_filestream.h"
 
 STATIC int
 xfs_open(
@@ -77,36 +78,6 @@
 	return 0;
 }
 
-STATIC int
-xfs_close(
-	bhv_desc_t	*bdp,
-	int		flags,
-	lastclose_t	lastclose,
-	cred_t		*credp)
-{
-	bhv_vnode_t	*vp = BHV_TO_VNODE(bdp);
-	xfs_inode_t	*ip = XFS_BHVTOI(bdp);
-
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		return XFS_ERROR(EIO);
-
-	if (lastclose != L_TRUE || !VN_ISREG(vp))
-		return 0;
-
-	/*
-	 * If we previously truncated this file and removed old data in
-	 * the process, we want to initiate "early" writeout on the last
-	 * close.  This is an attempt to combat the notorious NULL files
-	 * problem which is particularly noticable from a truncate down,
-	 * buffered (re-)write (delalloc), followed by a crash.  What we
-	 * are effectively doing here is significantly reducing the time
-	 * window where we'd otherwise be exposed to that problem.
-	 */
-	if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
-		return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
-	return 0;
-}
-
 /*
  * xfs_getattr
  */
@@ -183,9 +154,8 @@
 			 * realtime extent size or the realtime volume's
 			 * extent size.
 			 */
-			vap->va_blocksize = ip->i_d.di_extsize ?
-				(ip->i_d.di_extsize << mp->m_sb.sb_blocklog) :
-				(mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog);
+			vap->va_blocksize =
+				xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog;
 		}
 		break;
 	}
@@ -814,6 +784,8 @@
 				di_flags |= XFS_DIFLAG_PROJINHERIT;
 			if (vap->va_xflags & XFS_XFLAG_NODEFRAG)
 				di_flags |= XFS_DIFLAG_NODEFRAG;
+			if (vap->va_xflags & XFS_XFLAG_FILESTREAM)
+				di_flags |= XFS_DIFLAG_FILESTREAM;
 			if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
 				if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
 					di_flags |= XFS_DIFLAG_RTINHERIT;
@@ -1201,13 +1173,15 @@
 }
 
 /*
- * This is called by xfs_inactive to free any blocks beyond eof,
- * when the link count isn't zero.
+ * This is called by xfs_inactive to free any blocks beyond eof
+ * when the link count isn't zero and by xfs_dm_punch_hole() when
+ * punching a hole to EOF.
  */
-STATIC int
-xfs_inactive_free_eofblocks(
+int
+xfs_free_eofblocks(
 	xfs_mount_t	*mp,
-	xfs_inode_t	*ip)
+	xfs_inode_t	*ip,
+	int		flags)
 {
 	xfs_trans_t	*tp;
 	int		error;
@@ -1216,6 +1190,7 @@
 	xfs_filblks_t	map_len;
 	int		nimaps;
 	xfs_bmbt_irec_t	imap;
+	int		use_iolock = (flags & XFS_FREE_EOF_LOCK);
 
 	/*
 	 * Figure out if there are any blocks beyond the end
@@ -1256,11 +1231,14 @@
 		 * cache and we can't
 		 * do that within a transaction.
 		 */
-		xfs_ilock(ip, XFS_IOLOCK_EXCL);
+		if (use_iolock)
+			xfs_ilock(ip, XFS_IOLOCK_EXCL);
 		error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
 				    ip->i_size);
 		if (error) {
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			xfs_trans_cancel(tp, 0);
+			if (use_iolock)
+				xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 			return error;
 		}
 
@@ -1297,7 +1275,8 @@
 			error = xfs_trans_commit(tp,
 						XFS_TRANS_RELEASE_LOG_RES);
 		}
-		xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
+		xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)
+					    : XFS_ILOCK_EXCL));
 	}
 	return error;
 }
@@ -1560,6 +1539,31 @@
 	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
 		return 0;
 
+	if (!XFS_FORCED_SHUTDOWN(mp)) {
+		/*
+		 * If we are using filestreams, and we have an unlinked
+		 * file that we are processing the last close on, then nothing
+		 * will be able to reopen and write to this file. Purge this
+		 * inode from the filestreams cache so that it doesn't delay
+		 * teardown of the inode.
+		 */
+		if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip))
+			xfs_filestream_deassociate(ip);
+
+		/*
+		 * If we previously truncated this file and removed old data
+		 * in the process, we want to initiate "early" writeout on
+		 * the last close.  This is an attempt to combat the notorious
+		 * NULL files problem which is particularly noticable from a
+		 * truncate down, buffered (re-)write (delalloc), followed by
+		 * a crash.  What we are effectively doing here is
+		 * significantly reducing the time window where we'd otherwise
+		 * be exposed to that problem.
+		 */
+		if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
+			bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
+	}
+
 #ifdef HAVE_REFCACHE
 	/* If we are in the NFS reference cache then don't do this now */
 	if (ip->i_refcache)
@@ -1573,7 +1577,8 @@
 		     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
 		    (!(ip->i_d.di_flags &
 				(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
-			if ((error = xfs_inactive_free_eofblocks(mp, ip)))
+			error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
+			if (error)
 				return error;
 			/* Update linux inode block count after free above */
 			vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
@@ -1654,7 +1659,8 @@
 		     (!(ip->i_d.di_flags &
 				(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
 		      (ip->i_delayed_blks != 0)))) {
-			if ((error = xfs_inactive_free_eofblocks(mp, ip)))
+			error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
+			if (error)
 				return VN_INACTIVE_CACHE;
 			/* Update linux inode block count after free above */
 			vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
@@ -1680,6 +1686,7 @@
 
 		error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
 		if (error) {
+			xfs_trans_cancel(tp, 0);
 			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 			return VN_INACTIVE_CACHE;
 		}
@@ -2217,9 +2224,9 @@
 xfs_lock_inumorder(int lock_mode, int subclass)
 {
 	if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
-		lock_mode |= (subclass + XFS_IOLOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
+		lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
 	if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))
-		lock_mode |= (subclass + XFS_ILOCK_INUMORDER) << XFS_ILOCK_SHIFT;
+		lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT;
 
 	return lock_mode;
 }
@@ -2546,6 +2553,15 @@
 	 */
 	xfs_refcache_purge_ip(ip);
 
+	/*
+	 * If we are using filestreams, kill the stream association.
+	 * If the file is still open it may get a new one but that
+	 * will get killed on last close in xfs_close() so we don't
+	 * have to worry about that.
+	 */
+	if (link_zero && xfs_inode_is_filestream(ip))
+		xfs_filestream_deassociate(ip);
+
 	vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
 
 	/*
@@ -4047,22 +4063,16 @@
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
 
-	rt = XFS_IS_REALTIME_INODE(ip);
-	if (unlikely(rt)) {
-		if (!(extsz = ip->i_d.di_extsize))
-			extsz = mp->m_sb.sb_rextsize;
-	} else {
-		extsz = ip->i_d.di_extsize;
-	}
-
 	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
 		return error;
 
 	if (len <= 0)
 		return XFS_ERROR(EINVAL);
 
+	rt = XFS_IS_REALTIME_INODE(ip);
+	extsz = xfs_get_extsz_hint(ip);
+
 	count = len;
-	error = 0;
 	imapp = &imaps[0];
 	nimaps = 1;
 	bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
@@ -4678,11 +4688,7 @@
 bhv_vnodeops_t xfs_vnodeops = {
 	BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
 	.vop_open		= xfs_open,
-	.vop_close		= xfs_close,
 	.vop_read		= xfs_read,
-#ifdef HAVE_SENDFILE
-	.vop_sendfile		= xfs_sendfile,
-#endif
 #ifdef HAVE_SPLICE
 	.vop_splice_read	= xfs_splice_read,
 	.vop_splice_write	= xfs_splice_write,
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
index b62cd36..e2fcee2 100644
--- a/include/acpi/acpi_numa.h
+++ b/include/acpi/acpi_numa.h
@@ -13,7 +13,7 @@
 
 extern int pxm_to_node(int);
 extern int node_to_pxm(int);
-extern int __cpuinit acpi_map_pxm_to_node(int);
+extern int acpi_map_pxm_to_node(int);
 extern void __cpuinit acpi_unmap_pxm_to_node(int);
 
 #endif				/* CONFIG_ACPI_NUMA */
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 5e07db0..ca882b8 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -78,7 +78,7 @@
 /*
  * OSL Initialization and shutdown primitives
  */
-acpi_status acpi_os_initialize(void);
+acpi_status __initdata acpi_os_initialize(void);
 
 acpi_status acpi_os_terminate(void);
 
@@ -236,6 +236,7 @@
  * Miscellaneous
  */
 acpi_status acpi_os_validate_interface(char *interface);
+acpi_status acpi_osi_invalidate(char* interface);
 
 acpi_status
 acpi_os_validate_address(u8 space_id,
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index e08f7df..b5cca5d 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -55,7 +55,7 @@
 acpi_initialize_tables(struct acpi_table_desc *initial_storage,
 		       u32 initial_table_count, u8 allow_resize);
 
-acpi_status acpi_initialize_subsystem(void);
+acpi_status __init acpi_initialize_subsystem(void);
 
 acpi_status acpi_enable_subsystem(u32 flags);
 
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index 15a8388..a87ef1c 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -390,6 +390,8 @@
 
 u8 acpi_ut_valid_internal_object(void *object);
 
+union acpi_operand_object *acpi_ut_create_package_object(u32 count);
+
 union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size);
 
 union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);
diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
index 4b6ef7f..3a0cbeb 100644
--- a/include/asm-alpha/bitops.h
+++ b/include/asm-alpha/bitops.h
@@ -313,32 +313,29 @@
  * fls: find last bit set.
  */
 #if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
-static inline int fls(int word)
+static inline int fls64(unsigned long word)
 {
-	return 64 - __kernel_ctlz(word & 0xffffffff);
+	return 64 - __kernel_ctlz(word);
 }
 #else
-#include <asm-generic/bitops/fls.h>
-#endif
-#include <asm-generic/bitops/fls64.h>
+extern const unsigned char __flsm1_tab[256];
 
-/* Compute powers of two for the given integer.  */
-static inline long floor_log2(unsigned long word)
+static inline int fls64(unsigned long x)
 {
-#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
-	return 63 - __kernel_ctlz(word);
-#else
-	long bit;
-	for (bit = -1; word ; bit++)
-		word >>= 1;
-	return bit;
-#endif
+	unsigned long t, a, r;
+
+	t = __kernel_cmpbge (x, 0x0101010101010101);
+	a = __flsm1_tab[t];
+	t = __kernel_extbl (x, a);
+	r = a*8 + __flsm1_tab[t] + (x != 0);
+
+	return r;
 }
+#endif
 
-static inline long ceil_log2(unsigned long word)
+static inline int fls(int x)
 {
-	long bit = floor_log2(word);
-	return bit + (word > (1UL << bit));
+	return fls64((unsigned int) x);
 }
 
 /*
@@ -353,9 +350,20 @@
 	return __kernel_ctpop(w);
 }
 
-#define hweight32(x)	(unsigned int) hweight64((x) & 0xfffffffful)
-#define hweight16(x)	(unsigned int) hweight64((x) & 0xfffful)
-#define hweight8(x)	(unsigned int) hweight64((x) & 0xfful)
+static inline unsigned int hweight32(unsigned int w)
+{
+	return hweight64(w);
+}
+
+static inline unsigned int hweight16(unsigned int w)
+{
+	return hweight64(w & 0xffff);
+}
+
+static inline unsigned int hweight8(unsigned int w)
+{
+	return hweight64(w & 0xff);
+}
 #else
 #include <asm-generic/bitops/hweight.h>
 #endif
diff --git a/include/asm-alpha/core_t2.h b/include/asm-alpha/core_t2.h
index 457c34b..90e6b5d 100644
--- a/include/asm-alpha/core_t2.h
+++ b/include/asm-alpha/core_t2.h
@@ -437,9 +437,15 @@
 
 static DEFINE_SPINLOCK(t2_hae_lock);
 
+/*
+ * NOTE: take T2_DENSE_MEM off in each readX/writeX routine, since
+ *       they may be called directly, rather than through the
+ *       ioreadNN/iowriteNN routines.
+ */
+
 __EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long) xaddr;
+	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -453,7 +459,7 @@
 
 __EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long) xaddr;
+	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -471,7 +477,7 @@
  */
 __EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long) xaddr;
+	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -485,7 +491,7 @@
 
 __EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long) xaddr;
+	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
 	unsigned long r0, r1, work, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -501,7 +507,7 @@
 
 __EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long) xaddr;
+	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
 	unsigned long msb, w;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -515,7 +521,7 @@
 
 __EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long) xaddr;
+	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
 	unsigned long msb, w;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -533,7 +539,7 @@
  */
 __EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long) xaddr;
+	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
 	unsigned long msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -546,7 +552,7 @@
 
 __EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long) xaddr;
+	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
 	unsigned long msb, work;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -587,14 +593,14 @@
 __EXTERN_INLINE unsigned int t2_ioread##NS(void __iomem *xaddr)		\
 {									\
 	if (t2_is_mmio(xaddr))						\
-		return t2_read##OS(xaddr - T2_DENSE_MEM);		\
+		return t2_read##OS(xaddr);				\
 	else								\
 		return t2_in##OS((unsigned long)xaddr - T2_IO);		\
 }									\
 __EXTERN_INLINE void t2_iowrite##NS(u##NS b, void __iomem *xaddr)	\
 {									\
 	if (t2_is_mmio(xaddr))						\
-		t2_write##OS(b, xaddr - T2_DENSE_MEM);			\
+		t2_write##OS(b, xaddr);					\
 	else								\
 		t2_out##OS(b, (unsigned long)xaddr - T2_IO);		\
 }
diff --git a/include/asm-alpha/core_titan.h b/include/asm-alpha/core_titan.h
index a64ccbf..a17f6f3 100644
--- a/include/asm-alpha/core_titan.h
+++ b/include/asm-alpha/core_titan.h
@@ -380,12 +380,7 @@
 /*
  * Memory functions.  all accesses are done through linear space.
  */
-
-__EXTERN_INLINE void __iomem *titan_ioportmap(unsigned long addr)
-{
-	return (void __iomem *)(addr + TITAN_IO_BIAS);
-}
-
+extern void __iomem *titan_ioportmap(unsigned long addr);
 extern void __iomem *titan_ioremap(unsigned long addr, unsigned long size);
 extern void titan_iounmap(volatile void __iomem *addr);
 
diff --git a/include/asm-alpha/core_tsunami.h b/include/asm-alpha/core_tsunami.h
index 44e635d..58d4fe4 100644
--- a/include/asm-alpha/core_tsunami.h
+++ b/include/asm-alpha/core_tsunami.h
@@ -2,6 +2,7 @@
 #define __ALPHA_TSUNAMI__H__
 
 #include <linux/types.h>
+#include <linux/pci.h>
 #include <asm/compiler.h>
 
 /*
@@ -302,18 +303,8 @@
 /*
  * Memory functions.  all accesses are done through linear space.
  */
-
-__EXTERN_INLINE void __iomem *tsunami_ioportmap(unsigned long addr)
-{
-	return (void __iomem *)(addr + TSUNAMI_IO_BIAS);
-}
-
-__EXTERN_INLINE void __iomem *tsunami_ioremap(unsigned long addr, 
-					      unsigned long size)
-{
-	return (void __iomem *)(addr + TSUNAMI_MEM_BIAS);
-}
-
+extern void __iomem *tsunami_ioportmap(unsigned long addr);
+extern void __iomem *tsunami_ioremap(unsigned long addr, unsigned long size);
 __EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
 {
 	return addr >= TSUNAMI_BASE;
diff --git a/include/asm-alpha/core_wildfire.h b/include/asm-alpha/core_wildfire.h
index 12af803..cd562f5 100644
--- a/include/asm-alpha/core_wildfire.h
+++ b/include/asm-alpha/core_wildfire.h
@@ -295,7 +295,7 @@
 
 __EXTERN_INLINE int wildfire_is_mmio(const volatile void __iomem *xaddr)
 {
-	unsigned long addr = (unsigned long)addr;
+	unsigned long addr = (unsigned long)xaddr;
 	return (addr & 0x100000000UL) == 0;
 }
 
diff --git a/include/asm-alpha/fb.h b/include/asm-alpha/fb.h
new file mode 100644
index 0000000..fa9bbb9
--- /dev/null
+++ b/include/asm-alpha/fb.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/device.h>
+
+/* Caching is off in the I/O space quadrant by design.  */
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index 21a86f1..ab5b60d 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -4,6 +4,7 @@
 #ifdef __KERNEL__
 
 #include <linux/kernel.h>
+#include <linux/mm.h>
 #include <asm/compiler.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -90,6 +91,11 @@
 
 #define page_to_phys(page)	page_to_pa(page)
 
+static inline dma_addr_t __deprecated isa_page_to_bus(struct page *page)
+{
+	return page_to_phys(page);
+}
+
 /* This depends on working iommu.  */
 #define BIO_VMERGE_BOUNDARY	(alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0)
 
@@ -102,12 +108,12 @@
  *
  * Note that this only works for a limited range of kernel addresses,
  * and very well may not span all memory.  Consider this interface 
- * deprecated in favour of the mapping functions in <asm/pci.h>.
+ * deprecated in favour of the DMA-mapping API.
  */
 extern unsigned long __direct_map_base;
 extern unsigned long __direct_map_size;
 
-static inline unsigned long virt_to_bus(void *address)
+static inline unsigned long __deprecated virt_to_bus(void *address)
 {
 	unsigned long phys = virt_to_phys(address);
 	unsigned long bus = phys + __direct_map_base;
@@ -115,7 +121,7 @@
 }
 #define isa_virt_to_bus virt_to_bus
 
-static inline void *bus_to_virt(unsigned long address)
+static inline void * __deprecated bus_to_virt(unsigned long address)
 {
 	void *virt;
 
@@ -126,6 +132,7 @@
 	virt = phys_to_virt(address);
 	return (long)address <= 0 ? NULL : virt;
 }
+#define isa_bus_to_virt bus_to_virt
 
 /*
  * There are different chipsets to interface the Alpha CPUs to the world.
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index d2bed3c..bae7f05 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -17,7 +17,8 @@
 extern void clear_page(void *page);
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vmaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vmaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 extern void copy_page(void * _to, void * _from);
diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
index 85aa112..30ee766 100644
--- a/include/asm-alpha/pci.h
+++ b/include/asm-alpha/pci.h
@@ -199,30 +199,6 @@
 
 extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
 
-/* True if the machine supports DAC addressing, and DEV can
-   make use of it given MASK.  */
-extern int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
-
-/* Convert to/from DAC dma address and struct page.  */
-extern dma64_addr_t pci_dac_page_to_dma(struct pci_dev *, struct page *,
-					unsigned long, int);
-extern struct page *pci_dac_dma_to_page(struct pci_dev *, dma64_addr_t);
-extern unsigned long pci_dac_dma_to_offset(struct pci_dev *, dma64_addr_t);
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr,
-				size_t len, int direction)
-{
-	/* Nothing to do. */
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr,
-				   size_t len, int direction)
-{
-	/* Nothing to do. */
-}
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
@@ -275,11 +251,6 @@
 	return hose->need_domain_info;
 }
 
-static inline void
-pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 struct pci_dev *alpha_gendev_to_pci(struct device *dev);
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 616d206..99037b0 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -264,21 +264,15 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-extern inline int pte_read(pte_t pte)		{ return !(pte_val(pte) & _PAGE_FOR); }
 extern inline int pte_write(pte_t pte)		{ return !(pte_val(pte) & _PAGE_FOW); }
-extern inline int pte_exec(pte_t pte)		{ return !(pte_val(pte) & _PAGE_FOE); }
 extern inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 extern inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 extern inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
 
 extern inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_FOW; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_FOR; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_FOE; return pte; }
 extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~(__DIRTY_BITS); return pte; }
 extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~(__ACCESS_BITS); return pte; }
 extern inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) &= ~_PAGE_FOW; return pte; }
-extern inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) &= ~_PAGE_FOR; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte)	{ pte_val(pte) &= ~_PAGE_FOE; return pte; }
 extern inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= __DIRTY_BITS; return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= __ACCESS_BITS; return pte; }
 
diff --git a/include/asm-alpha/termios.h b/include/asm-alpha/termios.h
index 39e492c..fa13716 100644
--- a/include/asm-alpha/termios.h
+++ b/include/asm-alpha/termios.h
@@ -81,7 +81,7 @@
 
 #define user_termio_to_kernel_termios(a_termios, u_termio)			\
 ({										\
-	struct termios *k_termios = (a_termios);				\
+	struct ktermios *k_termios = (a_termios);				\
 	struct termio k_termio;							\
 	int canon, ret;								\
 										\
@@ -113,7 +113,7 @@
  */
 #define kernel_termios_to_user_termio(u_termio, a_termios)		\
 ({									\
-	struct termios *k_termios = (a_termios);			\
+	struct ktermios *k_termios = (a_termios);			\
 	struct termio k_termio;						\
 	int canon;							\
 									\
diff --git a/include/asm-alpha/thread_info.h b/include/asm-alpha/thread_info.h
index f4defc2..48a22e3 100644
--- a/include/asm-alpha/thread_info.h
+++ b/include/asm-alpha/thread_info.h
@@ -76,12 +76,14 @@
 #define TIF_UAC_NOFIX		7
 #define TIF_UAC_SIGBUS		8
 #define TIF_MEMDIE		9
+#define TIF_RESTORE_SIGMASK	10	/* restore signal mask in do_signal */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 
 /* Work to do on interrupt/exception return.  */
 #define _TIF_WORK_MASK		(_TIF_NOTIFY_RESUME	\
diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
index e58a427..29bf2fd 100644
--- a/include/asm-alpha/unistd.h
+++ b/include/asm-alpha/unistd.h
@@ -233,6 +233,20 @@
 #define __NR_osf_memcntl	260	/* not implemented */
 #define __NR_osf_fdatasync	261	/* not implemented */
 
+/*
+ * Ignore legacy syscalls that we don't use.
+ */
+#define __IGNORE_alarm
+#define __IGNORE_creat
+#define __IGNORE_getegid
+#define __IGNORE_geteuid
+#define __IGNORE_getgid
+#define __IGNORE_getpid
+#define __IGNORE_getppid
+#define __IGNORE_getuid
+#define __IGNORE_pause
+#define __IGNORE_time
+#define __IGNORE_utime
 
 /*
  * Linux-specific system calls begin at 300
@@ -387,10 +401,42 @@
 #define __NR_inotify_init		444
 #define __NR_inotify_add_watch		445
 #define __NR_inotify_rm_watch		446
+#define __NR_fdatasync			447
+#define __NR_kexec_load			448
+#define __NR_migrate_pages		449
+#define __NR_openat			450
+#define __NR_mkdirat			451
+#define __NR_mknodat			452
+#define __NR_fchownat			453
+#define __NR_futimesat			454
+#define __NR_fstatat64			455
+#define __NR_unlinkat			456
+#define __NR_renameat			457
+#define __NR_linkat			458
+#define __NR_symlinkat			459
+#define __NR_readlinkat			460
+#define __NR_fchmodat			461
+#define __NR_faccessat			462
+#define __NR_pselect6			463
+#define __NR_ppoll			464
+#define __NR_unshare			465
+#define __NR_set_robust_list		466
+#define __NR_get_robust_list		467
+#define __NR_splice			468
+#define __NR_sync_file_range		469
+#define __NR_tee			470
+#define __NR_vmsplice			471
+#define __NR_move_pages			472
+#define __NR_getcpu			473
+#define __NR_epoll_pwait		474
+#define __NR_utimensat			475
+#define __NR_signalfd			476
+#define __NR_timerfd			477
+#define __NR_eventfd			478
 
 #ifdef __KERNEL__
 
-#define NR_SYSCALLS			447
+#define NR_SYSCALLS			479
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-alpha/vga.h b/include/asm-alpha/vga.h
index ed06f59b..e8df1e7 100644
--- a/include/asm-alpha/vga.h
+++ b/include/asm-alpha/vga.h
@@ -46,6 +46,37 @@
 #define vga_readb(a)	readb((u8 __iomem *)(a))
 #define vga_writeb(v,a)	writeb(v, (u8 __iomem *)(a))
 
+#ifdef CONFIG_VGA_HOSE
+#include <linux/ioport.h>
+#include <linux/pci.h>
+
+extern struct pci_controller *pci_vga_hose;
+
+# define __is_port_vga(a)       \
+	(((a) >= 0x3b0) && ((a) < 0x3e0) && \
+	 ((a) != 0x3b3) && ((a) != 0x3d3))
+
+# define __is_mem_vga(a) \
+	(((a) >= 0xa0000) && ((a) <= 0xc0000))
+
+# define FIXUP_IOADDR_VGA(a) do {                       \
+	if (pci_vga_hose && __is_port_vga(a))     \
+		(a) += pci_vga_hose->io_space->start;	  \
+ } while(0)
+
+# define FIXUP_MEMADDR_VGA(a) do {                       \
+	if (pci_vga_hose && __is_mem_vga(a))     \
+		(a) += pci_vga_hose->mem_space->start; \
+ } while(0)
+
+#else /* CONFIG_VGA_HOSE */
+# define pci_vga_hose 0
+# define __is_port_vga(a) 0
+# define __is_mem_vga(a) 0
+# define FIXUP_IOADDR_VGA(a)
+# define FIXUP_MEMADDR_VGA(a)
+#endif /* CONFIG_VGA_HOSE */
+
 #define VGA_MAP_MEM(x,s)	((unsigned long) ioremap(x, s))
 
 #endif
diff --git a/include/asm-arm/Kbuild b/include/asm-arm/Kbuild
index c68e168..73237bd 100644
--- a/include/asm-arm/Kbuild
+++ b/include/asm-arm/Kbuild
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+unifdef-y += hwcap.h
diff --git a/include/asm-arm/arch-at91/at91_adc.h b/include/asm-arm/arch-at91/at91_adc.h
index 1ed66ea..6d71ea26 100644
--- a/include/asm-arm/arch-at91/at91_adc.h
+++ b/include/asm-arm/arch-at91/at91_adc.h
@@ -55,7 +55,7 @@
 #define AT91_ADC_IDR		0x28		/* Interrupt Disable Register */
 #define AT91_ADC_IMR		0x2C		/* Interrupt Mask Register */
 
-#define AT91_ADC_CHR(n)		(0x30 + ((n) * 4)	/* Channel Data Register N */
+#define AT91_ADC_CHR(n)		(0x30 + ((n) * 4))	/* Channel Data Register N */
 #define		AT91_ADC_DATA		(0x3ff)
 
 #endif
diff --git a/include/asm-arm/arch-at91/at91_dbgu.h b/include/asm-arm/arch-at91/at91_dbgu.h
index b0369e1..8019ffd 100644
--- a/include/asm-arm/arch-at91/at91_dbgu.h
+++ b/include/asm-arm/arch-at91/at91_dbgu.h
@@ -16,6 +16,7 @@
 #ifndef AT91_DBGU_H
 #define AT91_DBGU_H
 
+#ifdef AT91_DBGU
 #define AT91_DBGU_CR		(AT91_DBGU + 0x00)	/* Control Register */
 #define AT91_DBGU_MR		(AT91_DBGU + 0x04)	/* Mode Register */
 #define AT91_DBGU_IER		(AT91_DBGU + 0x08)	/* Interrupt Enable Register */
@@ -30,6 +31,15 @@
 
 #define AT91_DBGU_CIDR		(AT91_DBGU + 0x40)	/* Chip ID Register */
 #define AT91_DBGU_EXID		(AT91_DBGU + 0x44)	/* Chip ID Extension Register */
+#define AT91_DBGU_FNR		(AT91_DBGU + 0x48)	/* Force NTRST Register [SAM9 only] */
+#define		AT91_DBGU_FNTRST	(1 << 0)		/* Force NTRST */
+
+#endif /* AT91_DBGU */
+
+/*
+ * Some AT91 parts that don't have full DEBUG units still support the ID
+ * and extensions register.
+ */
 #define		AT91_CIDR_VERSION	(0x1f << 0)		/* Version of the Device */
 #define		AT91_CIDR_EPROC		(7    << 5)		/* Embedded Processor */
 #define		AT91_CIDR_NVPSIZ	(0xf  << 8)		/* Nonvolatile Program Memory Size */
@@ -53,7 +63,4 @@
 #define		AT91_CIDR_NVPTYP	(7    << 28)		/* Nonvolatile Program Memory Type */
 #define		AT91_CIDR_EXT		(1    << 31)		/* Extension Flag */
 
-#define AT91_DBGU_FNR		(AT91_DBGU + 0x48)	/* Force NTRST Register [SAM9 only] */
-#define		AT91_DBGU_FNTRST	(1 << 0)		/* Force NTRST */
-
 #endif
diff --git a/include/asm-arm/arch-at91/at91_shdwc.h b/include/asm-arm/arch-at91/at91_shdwc.h
index 795fcc2..01b433d 100644
--- a/include/asm-arm/arch-at91/at91_shdwc.h
+++ b/include/asm-arm/arch-at91/at91_shdwc.h
@@ -14,8 +14,8 @@
 #define AT91_SHDWC_H
 
 #define AT91_SHDW_CR		(AT91_SHDWC + 0x00)	/* Shut Down Control Register */
-#define		AT91_SHDW_SHDW		(1    << 0)		/* Processor Reset */
-#define		AT91_SHDW_KEY		(0xff << 24)		/* KEY Password */
+#define		AT91_SHDW_SHDW		(1    << 0)		/* Shut Down command */
+#define		AT91_SHDW_KEY		(0xa5 << 24)		/* KEY Password */
 
 #define AT91_SHDW_MR		(AT91_SHDWC + 0x04)	/* Shut Down Mode Register */
 #define		AT91_SHDW_WKMODE0	(3 << 0)		/* Wake-up 0 Mode Selection */
diff --git a/include/asm-arm/arch-at91/at91_wdt.h b/include/asm-arm/arch-at91/at91_wdt.h
index 7251a34..1014e9b 100644
--- a/include/asm-arm/arch-at91/at91_wdt.h
+++ b/include/asm-arm/arch-at91/at91_wdt.h
@@ -15,7 +15,7 @@
 
 #define AT91_WDT_CR		(AT91_WDT + 0x00)	/* Watchdog Control Register */
 #define		AT91_WDT_WDRSTT		(1    << 0)		/* Restart */
-#define		AT91_WDT_KEY		(0xff << 24)		/* KEY Password */
+#define		AT91_WDT_KEY		(0xa5 << 24)		/* KEY Password */
 
 #define AT91_WDT_MR		(AT91_WDT + 0x04)	/* Watchdog Mode Register */
 #define		AT91_WDT_WDV		(0xfff << 0)		/* Counter Value */
diff --git a/include/asm-arm/arch-at91/at91x40.h b/include/asm-arm/arch-at91/at91x40.h
new file mode 100644
index 0000000..612203e
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91x40.h
@@ -0,0 +1,55 @@
+/*
+ * include/asm-arm/arch-at91/at91x40.h
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91X40_H
+#define AT91X40_H
+
+/*
+ *	IRQ list.
+ */
+#define AT91_ID_FIQ		0	/* FIQ */
+#define AT91_ID_SYS		1	/* System Peripheral */
+#define AT91X40_ID_USART0	2	/* USART port 0 */
+#define AT91X40_ID_USART1	3	/* USART port 1 */
+#define AT91X40_ID_TC0		4	/* Timer/Counter 0 */
+#define AT91X40_ID_TC1		5	/* Timer/Counter 1*/
+#define AT91X40_ID_TC2		6	/* Timer/Counter 2*/
+#define AT91X40_ID_WD		7	/* Watchdog? */
+#define AT91X40_ID_PIOA		8	/* Parallel IO Controller A */
+
+#define AT91X40_ID_IRQ0		16	/* External IRQ 0 */
+#define AT91X40_ID_IRQ1		17	/* External IRQ 1 */
+#define AT91X40_ID_IRQ2		18	/* External IRQ 2 */
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_BASE_SYS	0xffc00000
+
+#define AT91_EBI	(0xffe00000 - AT91_BASE_SYS)	/* External Bus Interface */
+#define AT91_SF		(0xfff00000 - AT91_BASE_SYS)	/* Special Function */
+#define AT91_USART1	(0xfffcc000 - AT91_BASE_SYS)	/* USART 1 */
+#define AT91_USART0	(0xfffd0000 - AT91_BASE_SYS)	/* USART 0 */
+#define AT91_TC		(0xfffe0000 - AT91_BASE_SYS)	/* Timer Counter */
+#define AT91_PIOA	(0xffff0000 - AT91_BASE_SYS)	/* PIO Controller A */
+#define AT91_PS		(0xffff4000 - AT91_BASE_SYS)	/* Power Save */
+#define AT91_WD		(0xffff8000 - AT91_BASE_SYS)	/* Watchdog Timer */
+#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)	/* Advanced Interrupt Controller */
+
+/*
+ * The AT91x40 series doesn't have a debug unit like the other AT91 parts.
+ * But it does have a chip identify register and extension ID, so define at
+ * least these here.
+ */
+#define AT91_DBGU_CIDR	(AT91_SF + 0)	/* CIDR in PS segment */
+#define AT91_DBGU_EXID	(AT91_SF + 4)	/* EXID in PS segment */
+
+#endif /* AT91X40_H */
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h
index 0ce6ee9..d96b10f 100644
--- a/include/asm-arm/arch-at91/board.h
+++ b/include/asm-arm/arch-at91/board.h
@@ -64,6 +64,7 @@
 
  /* Ethernet (EMAC & MACB) */
 struct at91_eth_data {
+	u32		phy_mask;
 	u8		phy_irq_pin;	/* PHY IRQ */
 	u8		is_rmii;	/* using RMII interface? */
 };
diff --git a/include/asm-arm/arch-at91/cpu.h b/include/asm-arm/arch-at91/cpu.h
index ef93c30..080cbb4 100644
--- a/include/asm-arm/arch-at91/cpu.h
+++ b/include/asm-arm/arch-at91/cpu.h
@@ -28,6 +28,11 @@
 
 #define ARCH_ID_AT91SAM9RL64	0x019b03a0
 
+#define ARCH_ID_AT91M40800	0x14080044
+#define ARCH_ID_AT91R40807	0x44080746
+#define ARCH_ID_AT91M40807	0x14080745
+#define ARCH_ID_AT91R40008	0x44000840
+
 static inline unsigned long at91_cpu_identify(void)
 {
 	return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
diff --git a/include/asm-arm/arch-at91/hardware.h b/include/asm-arm/arch-at91/hardware.h
index 46835e9..8f1cdd3 100644
--- a/include/asm-arm/arch-at91/hardware.h
+++ b/include/asm-arm/arch-at91/hardware.h
@@ -26,18 +26,29 @@
 #include <asm/arch/at91sam9263.h>
 #elif defined(CONFIG_ARCH_AT91SAM9RL)
 #include <asm/arch/at91sam9rl.h>
+#elif defined(CONFIG_ARCH_AT91X40)
+#include <asm/arch/at91x40.h>
 #else
 #error "Unsupported AT91 processor"
 #endif
 
 
+#ifdef CONFIG_MMU
 /*
  * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
  * to 0xFEF78000 .. 0xFF000000.  (544Kb)
  */
 #define AT91_IO_PHYS_BASE	0xFFF78000
-#define AT91_IO_SIZE		(0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 #define AT91_IO_VIRT_BASE	(0xFF000000 - AT91_IO_SIZE)
+#else
+/*
+ * Identity mapping for the non MMU case.
+ */
+#define AT91_IO_PHYS_BASE	AT91_BASE_SYS
+#define AT91_IO_VIRT_BASE	AT91_IO_PHYS_BASE
+#endif
+
+#define AT91_IO_SIZE		(0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 
  /* Convert a physical IO address to virtual IO address */
 #define AT91_IO_P2V(x)		((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
@@ -66,7 +77,11 @@
 #define AT91_CHIPSELECT_7	0x80000000
 
 /* SDRAM */
+#ifdef CONFIG_DRAM_BASE
+#define AT91_SDRAM_BASE		CONFIG_DRAM_BASE
+#else
 #define AT91_SDRAM_BASE		AT91_CHIPSELECT_1
+#endif
 
 /* Clocks */
 #define AT91_SLOW_CLOCK		32768		/* slow clock */
diff --git a/include/asm-arm/arch-at91/timex.h b/include/asm-arm/arch-at91/timex.h
index 2df1ee1..a310698 100644
--- a/include/asm-arm/arch-at91/timex.h
+++ b/include/asm-arm/arch-at91/timex.h
@@ -42,6 +42,11 @@
 #define AT91SAM9_MASTER_CLOCK	100000000
 #define CLOCK_TICK_RATE		(AT91SAM9_MASTER_CLOCK/16)
 
+#elif defined(CONFIG_ARCH_AT91X40)
+
+#define AT91X40_MASTER_CLOCK	40000000
+#define CLOCK_TICK_RATE		(AT91X40_MASTER_CLOCK)
+
 #endif
 
 #endif
diff --git a/include/asm-arm/arch-at91/uncompress.h b/include/asm-arm/arch-at91/uncompress.h
index 30ac587..272a7e0 100644
--- a/include/asm-arm/arch-at91/uncompress.h
+++ b/include/asm-arm/arch-at91/uncompress.h
@@ -33,20 +33,24 @@
  */
 static void putc(int c)
 {
+#ifdef AT91_DBGU
 	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
 
 	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
 		barrier();
 	__raw_writel(c, sys + AT91_DBGU_THR);
+#endif
 }
 
 static inline void flush(void)
 {
+#ifdef AT91_DBGU
 	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
 
 	/* wait for transmission to complete */
 	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
 		barrier();
+#endif
 }
 
 #define arch_decomp_setup()
diff --git a/include/asm-arm/arch-davinci/clock.h b/include/asm-arm/arch-davinci/clock.h
new file mode 100644
index 0000000..cc168b7
--- /dev/null
+++ b/include/asm-arm/arch-davinci/clock.h
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-davinci/clock.h
+ *
+ * Clock control driver for DaVinci - header file
+ *
+ * Authors: Vladimir Barinov <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
+#define __ASM_ARCH_DAVINCI_CLOCK_H
+
+struct clk;
+
+extern int clk_register(struct clk *clk);
+extern void clk_unregister(struct clk *clk);
+extern int davinci_clk_init(void);
+
+#endif
diff --git a/include/asm-arm/arch-davinci/gpio.h b/include/asm-arm/arch-davinci/gpio.h
new file mode 100644
index 0000000..ea24a0e
--- /dev/null
+++ b/include/asm-arm/arch-davinci/gpio.h
@@ -0,0 +1,156 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef	__DAVINCI_GPIO_H
+#define	__DAVINCI_GPIO_H
+
+/*
+ * basic gpio routines
+ *
+ * board-specific init should be done by arch/.../.../board-XXX.c (maybe
+ * initializing banks together) rather than boot loaders; kexec() won't
+ * go through boot loaders.
+ *
+ * the gpio clock will be turned on when gpios are used, and you may also
+ * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation, and maybe
+ * for later updates, code should write GPIO(N) or:
+ *  - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
+ *  - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
+ *
+ * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
+ * for now, that's != GPIO(N)
+ */
+#define	GPIO(X)		(X)		/* 0 <= X <= 70 */
+#define	GPIOV18(X)	(X)		/* 1.8V i/o; 0 <= X <= 53 */
+#define	GPIOV33(X)	((X)+54)	/* 3.3V i/o; 0 <= X <= 17 */
+
+struct gpio_controller {
+	u32	dir;
+	u32	out_data;
+	u32	set_data;
+	u32	clr_data;
+	u32	in_data;
+	u32	set_rising;
+	u32	clr_rising;
+	u32	set_falling;
+	u32	clr_falling;
+	u32	intstat;
+};
+
+/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
+ * with constant parameters; or in outlined code they execute at runtime.
+ *
+ * You'd access the controller directly when reading or writing more than
+ * one gpio value at a time, and to support wired logic where the value
+ * being driven by the cpu need not match the value read back.
+ *
+ * These are NOT part of the cross-platform GPIO interface
+ */
+static inline struct gpio_controller *__iomem
+__gpio_to_controller(unsigned gpio)
+{
+	void *__iomem ptr;
+
+	if (gpio < 32)
+		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
+	else if (gpio < 64)
+		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
+	else if (gpio < DAVINCI_N_GPIO)
+		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+	else
+		ptr = NULL;
+	return ptr;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+	return 1 << (gpio % 32);
+}
+
+/* The get/set/clear functions will inline when called with constant
+ * parameters, for low-overhead bitbanging.  Illegal constant parameters
+ * cause link-time errors.
+ *
+ * Otherwise, calls with variable parameters use outlined functions.
+ */
+extern int __error_inval_gpio(void);
+
+extern void __gpio_set(unsigned gpio, int value);
+extern int __gpio_get(unsigned gpio);
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	if (__builtin_constant_p(value)) {
+		struct gpio_controller	*__iomem g;
+		u32			mask;
+
+		if (gpio >= DAVINCI_N_GPIO)
+			__error_inval_gpio();
+
+		g = __gpio_to_controller(gpio);
+		mask = __gpio_mask(gpio);
+		if (value)
+			__raw_writel(mask, &g->set_data);
+		else
+			__raw_writel(mask, &g->clr_data);
+		return;
+	}
+
+	__gpio_set(gpio, value);
+}
+
+/* Returns zero or nonzero; works for gpios configured as inputs OR
+ * as outputs.
+ *
+ * NOTE: changes in reported values are synchronized to the GPIO clock.
+ * This is most easily seen after calling gpio_set_value() and then immediatly
+ * gpio_get_value(), where the gpio_get_value() would return the old value
+ * until the GPIO clock ticks and the new value gets latched.
+ */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	struct gpio_controller *__iomem g;
+
+	if (!__builtin_constant_p(gpio))
+		return __gpio_get(gpio);
+
+	if (gpio >= DAVINCI_N_GPIO)
+		return __error_inval_gpio();
+
+	g = __gpio_to_controller(gpio);
+	return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+
+/* powerup default direction is IN */
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio, int value);
+
+#include <asm-generic/gpio.h>	/* cansleep wrappers */
+
+extern int gpio_request(unsigned gpio, const char *tag);
+extern void gpio_free(unsigned gpio);
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return DAVINCI_N_AINTC_IRQ + gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return irq - DAVINCI_N_AINTC_IRQ;
+}
+
+#endif				/* __DAVINCI_GPIO_H */
diff --git a/include/asm-arm/arch-davinci/hardware.h b/include/asm-arm/arch-davinci/hardware.h
index 60362d8..a2e8969 100644
--- a/include/asm-arm/arch-davinci/hardware.h
+++ b/include/asm-arm/arch-davinci/hardware.h
@@ -11,4 +11,42 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
+/*
+ * Base register addresses
+ */
+#define DAVINCI_DMA_3PCC_BASE			(0x01C00000)
+#define DAVINCI_DMA_3PTC0_BASE			(0x01C10000)
+#define DAVINCI_DMA_3PTC1_BASE			(0x01C10400)
+#define DAVINCI_I2C_BASE			(0x01C21000)
+#define DAVINCI_PWM0_BASE			(0x01C22000)
+#define DAVINCI_PWM1_BASE			(0x01C22400)
+#define DAVINCI_PWM2_BASE			(0x01C22800)
+#define DAVINCI_SYSTEM_MODULE_BASE		(0x01C40000)
+#define DAVINCI_PLL_CNTRL0_BASE			(0x01C40800)
+#define DAVINCI_PLL_CNTRL1_BASE			(0x01C40C00)
+#define DAVINCI_PWR_SLEEP_CNTRL_BASE		(0x01C41000)
+#define DAVINCI_SYSTEM_DFT_BASE			(0x01C42000)
+#define DAVINCI_IEEE1394_BASE			(0x01C60000)
+#define DAVINCI_USB_OTG_BASE			(0x01C64000)
+#define DAVINCI_CFC_ATA_BASE			(0x01C66000)
+#define DAVINCI_SPI_BASE			(0x01C66800)
+#define DAVINCI_GPIO_BASE			(0x01C67000)
+#define DAVINCI_UHPI_BASE			(0x01C67800)
+#define DAVINCI_VPSS_REGS_BASE			(0x01C70000)
+#define DAVINCI_EMAC_CNTRL_REGS_BASE		(0x01C80000)
+#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE	(0x01C81000)
+#define DAVINCI_EMAC_WRAPPER_RAM_BASE		(0x01C82000)
+#define DAVINCI_MDIO_CNTRL_REGS_BASE		(0x01C84000)
+#define DAVINCI_IMCOP_BASE			(0x01CC0000)
+#define DAVINCI_ASYNC_EMIF_CNTRL_BASE		(0x01E00000)
+#define DAVINCI_VLYNQ_BASE			(0x01E01000)
+#define DAVINCI_MCBSP_BASE			(0x01E02000)
+#define DAVINCI_MMC_SD_BASE			(0x01E10000)
+#define DAVINCI_MS_BASE				(0x01E20000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE	(0x02000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE	(0x04000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE	(0x06000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE	(0x08000000)
+#define DAVINCI_VLYNQ_REMOTE_BASE		(0x0C000000)
+
 #endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-davinci/mux.h b/include/asm-arm/arch-davinci/mux.h
new file mode 100644
index 0000000..c24b678
--- /dev/null
+++ b/include/asm-arm/arch-davinci/mux.h
@@ -0,0 +1,55 @@
+/*
+ * DaVinci pin multiplexing defines
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_MUX_H
+#define __ASM_ARCH_MUX_H
+
+#define DAVINCI_MUX_AEAW0	0
+#define DAVINCI_MUX_AEAW1	1
+#define DAVINCI_MUX_AEAW2	2
+#define DAVINCI_MUX_AEAW3	3
+#define DAVINCI_MUX_AEAW4	4
+#define DAVINCI_MUX_AECS4	10
+#define DAVINCI_MUX_AECS5	11
+#define DAVINCI_MUX_VLYNQWD0	12
+#define DAVINCI_MUX_VLYNQWD1	13
+#define DAVINCI_MUX_VLSCREN	14
+#define DAVINCI_MUX_VLYNQEN	15
+#define DAVINCI_MUX_HDIREN	16
+#define DAVINCI_MUX_ATAEN	17
+#define DAVINCI_MUX_RGB666	22
+#define DAVINCI_MUX_RGB888	23
+#define DAVINCI_MUX_LOEEN	24
+#define DAVINCI_MUX_LFLDEN	25
+#define DAVINCI_MUX_CWEN	26
+#define DAVINCI_MUX_CFLDEN	27
+#define DAVINCI_MUX_HPIEN	29
+#define DAVINCI_MUX_1394EN	30
+#define DAVINCI_MUX_EMACEN	31
+
+#define DAVINCI_MUX_LEVEL2	32
+#define DAVINCI_MUX_UART0	(DAVINCI_MUX_LEVEL2 + 0)
+#define DAVINCI_MUX_UART1	(DAVINCI_MUX_LEVEL2 + 1)
+#define DAVINCI_MUX_UART2	(DAVINCI_MUX_LEVEL2 + 2)
+#define DAVINCI_MUX_U2FLO	(DAVINCI_MUX_LEVEL2 + 3)
+#define DAVINCI_MUX_PWM0	(DAVINCI_MUX_LEVEL2 + 4)
+#define DAVINCI_MUX_PWM1	(DAVINCI_MUX_LEVEL2 + 5)
+#define DAVINCI_MUX_PWM2	(DAVINCI_MUX_LEVEL2 + 6)
+#define DAVINCI_MUX_I2C		(DAVINCI_MUX_LEVEL2 + 7)
+#define DAVINCI_MUX_SPI		(DAVINCI_MUX_LEVEL2 + 8)
+#define DAVINCI_MUX_MSTK	(DAVINCI_MUX_LEVEL2 + 9)
+#define DAVINCI_MUX_ASP		(DAVINCI_MUX_LEVEL2 + 10)
+#define DAVINCI_MUX_CLK0	(DAVINCI_MUX_LEVEL2 + 16)
+#define DAVINCI_MUX_CLK1	(DAVINCI_MUX_LEVEL2 + 17)
+#define DAVINCI_MUX_TIMIN	(DAVINCI_MUX_LEVEL2 + 18)
+
+extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable);
+
+#endif /* __ASM_ARCH_MUX_H */
diff --git a/include/asm-arm/arch-imx/gpio.h b/include/asm-arm/arch-imx/gpio.h
new file mode 100644
index 0000000..4860232
--- /dev/null
+++ b/include/asm-arm/arch-imx/gpio.h
@@ -0,0 +1,102 @@
+#ifndef _IMX_GPIO_H
+
+#include <asm/arch/imx-regs.h>
+
+#define IMX_GPIO_ALLOC_MODE_NORMAL	0
+#define IMX_GPIO_ALLOC_MODE_NO_ALLOC	1
+#define IMX_GPIO_ALLOC_MODE_TRY_ALLOC	2
+#define IMX_GPIO_ALLOC_MODE_ALLOC_ONLY	4
+#define IMX_GPIO_ALLOC_MODE_RELEASE	8
+
+extern int imx_gpio_request(unsigned gpio, const char *label);
+
+extern void imx_gpio_free(unsigned gpio);
+
+extern int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+					int alloc_mode, const char *label);
+
+extern int imx_gpio_direction_input(unsigned gpio);
+
+extern int imx_gpio_direction_output(unsigned gpio, int value);
+
+extern void __imx_gpio_set_value(unsigned gpio, int value);
+
+static inline int imx_gpio_get_value(unsigned gpio)
+{
+	return SSR(gpio >> GPIO_PORT_SHIFT) & (1 << (gpio & GPIO_PIN_MASK));
+}
+
+static inline void imx_gpio_set_value_inline(unsigned gpio, int value)
+{
+	unsigned long flags;
+
+	raw_local_irq_save(flags);
+	if(value)
+		DR(gpio >> GPIO_PORT_SHIFT) |= (1 << (gpio & GPIO_PIN_MASK));
+	else
+		DR(gpio >> GPIO_PORT_SHIFT) &= ~(1 << (gpio & GPIO_PIN_MASK));
+	raw_local_irq_restore(flags);
+}
+
+static inline void imx_gpio_set_value(unsigned gpio, int value)
+{
+	if(__builtin_constant_p(gpio))
+		imx_gpio_set_value_inline(gpio, value);
+	else
+		__imx_gpio_set_value(gpio, value);
+}
+
+extern int imx_gpio_to_irq(unsigned gpio);
+
+extern int imx_irq_to_gpio(unsigned irq);
+
+/*-------------------------------------------------------------------------*/
+
+/* Wrappers for "new style" GPIO calls. These calls i.MX specific versions
+ * to allow future extension of GPIO logic.
+ */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return imx_gpio_request(gpio, label);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	imx_gpio_free(gpio);
+}
+
+static inline  int gpio_direction_input(unsigned gpio)
+{
+	return imx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+	return imx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return imx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	imx_gpio_set_value(gpio, value);
+}
+
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return imx_gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return imx_irq_to_gpio(irq);
+}
+
+
+#endif
diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h
index 30de404..fb9de27 100644
--- a/include/asm-arm/arch-imx/imx-regs.h
+++ b/include/asm-arm/arch-imx/imx-regs.h
@@ -77,6 +77,8 @@
 #define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
 #define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
 
+#define GPIO_PORT_MAX  3
+
 #define GPIO_PIN_MASK 0x1f
 #define GPIO_PORT_MASK (0x3 << 5)
 
diff --git a/include/asm-arm/arch-integrator/smp.h b/include/asm-arm/arch-integrator/smp.h
deleted file mode 100644
index ab2c79b..0000000
--- a/include/asm-arm/arch-integrator/smp.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef ASMARM_ARCH_SMP_H
-#define ASMARM_ARCH_SMP_H
-
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#define hard_smp_processor_id()				\
-	({						\
-		unsigned int cpunum;			\
-		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
-			: "=r" (cpunum));		\
-		cpunum &= 0x0F;				\
-	})
-
-extern void secondary_scan_irqs(void);
-
-#endif
diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
new file mode 100644
index 0000000..04006c1
--- /dev/null
+++ b/include/asm-arm/arch-iop13xx/adma.h
@@ -0,0 +1,544 @@
+/*
+ * Copyright(c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _ADMA_H
+#define _ADMA_H
+#include <linux/types.h>
+#include <linux/io.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop_adma.h>
+
+#define ADMA_ACCR(chan)	(chan->mmr_base + 0x0)
+#define ADMA_ACSR(chan)	(chan->mmr_base + 0x4)
+#define ADMA_ADAR(chan)	(chan->mmr_base + 0x8)
+#define ADMA_IIPCR(chan)	(chan->mmr_base + 0x18)
+#define ADMA_IIPAR(chan)	(chan->mmr_base + 0x1c)
+#define ADMA_IIPUAR(chan)	(chan->mmr_base + 0x20)
+#define ADMA_ANDAR(chan)	(chan->mmr_base + 0x24)
+#define ADMA_ADCR(chan)	(chan->mmr_base + 0x28)
+#define ADMA_CARMD(chan)	(chan->mmr_base + 0x2c)
+#define ADMA_ABCR(chan)	(chan->mmr_base + 0x30)
+#define ADMA_DLADR(chan)	(chan->mmr_base + 0x34)
+#define ADMA_DUADR(chan)	(chan->mmr_base + 0x38)
+#define ADMA_SLAR(src, chan)	(chan->mmr_base + (0x3c + (src << 3)))
+#define ADMA_SUAR(src, chan)	(chan->mmr_base + (0x40 + (src << 3)))
+
+struct iop13xx_adma_src {
+	u32 src_addr;
+	union {
+		u32 upper_src_addr;
+		struct {
+			unsigned int pq_upper_src_addr:24;
+			unsigned int pq_dmlt:8;
+		};
+	};
+};
+
+struct iop13xx_adma_desc_ctrl {
+	unsigned int int_en:1;
+	unsigned int xfer_dir:2;
+	unsigned int src_select:4;
+	unsigned int zero_result:1;
+	unsigned int block_fill_en:1;
+	unsigned int crc_gen_en:1;
+	unsigned int crc_xfer_dis:1;
+	unsigned int crc_seed_fetch_dis:1;
+	unsigned int status_write_back_en:1;
+	unsigned int endian_swap_en:1;
+	unsigned int reserved0:2;
+	unsigned int pq_update_xfer_en:1;
+	unsigned int dual_xor_en:1;
+	unsigned int pq_xfer_en:1;
+	unsigned int p_xfer_dis:1;
+	unsigned int reserved1:10;
+	unsigned int relax_order_en:1;
+	unsigned int no_snoop_en:1;
+};
+
+struct iop13xx_adma_byte_count {
+	unsigned int byte_count:24;
+	unsigned int host_if:3;
+	unsigned int reserved:2;
+	unsigned int zero_result_err_q:1;
+	unsigned int zero_result_err:1;
+	unsigned int tx_complete:1;
+};
+
+struct iop13xx_adma_desc_hw {
+	u32 next_desc;
+	union {
+		u32 desc_ctrl;
+		struct iop13xx_adma_desc_ctrl desc_ctrl_field;
+	};
+	union {
+		u32 crc_addr;
+		u32 block_fill_data;
+		u32 q_dest_addr;
+	};
+	union {
+		u32 byte_count;
+		struct iop13xx_adma_byte_count byte_count_field;
+	};
+	union {
+		u32 dest_addr;
+		u32 p_dest_addr;
+	};
+	union {
+		u32 upper_dest_addr;
+		u32 pq_upper_dest_addr;
+	};
+	struct iop13xx_adma_src src[1];
+};
+
+struct iop13xx_adma_desc_dual_xor {
+	u32 next_desc;
+	u32 desc_ctrl;
+	u32 reserved;
+	u32 byte_count;
+	u32 h_dest_addr;
+	u32 h_upper_dest_addr;
+	u32 src0_addr;
+	u32 upper_src0_addr;
+	u32 src1_addr;
+	u32 upper_src1_addr;
+	u32 h_src_addr;
+	u32 h_upper_src_addr;
+	u32 d_src_addr;
+	u32 d_upper_src_addr;
+	u32 d_dest_addr;
+	u32 d_upper_dest_addr;
+};
+
+struct iop13xx_adma_desc_pq_update {
+	u32 next_desc;
+	u32 desc_ctrl;
+	u32 reserved;
+	u32 byte_count;
+	u32 p_dest_addr;
+	u32 p_upper_dest_addr;
+	u32 src0_addr;
+	u32 upper_src0_addr;
+	u32 src1_addr;
+	u32 upper_src1_addr;
+	u32 p_src_addr;
+	u32 p_upper_src_addr;
+	u32 q_src_addr;
+	struct {
+		unsigned int q_upper_src_addr:24;
+		unsigned int q_dmlt:8;
+	};
+	u32 q_dest_addr;
+	u32 q_upper_dest_addr;
+};
+
+static inline int iop_adma_get_max_xor(void)
+{
+	return 16;
+}
+
+static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
+{
+	return __raw_readl(ADMA_ADAR(chan));
+}
+
+static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
+						u32 next_desc_addr)
+{
+	__raw_writel(next_desc_addr, ADMA_ANDAR(chan));
+}
+
+#define ADMA_STATUS_BUSY (1 << 13)
+
+static inline char iop_chan_is_busy(struct iop_adma_chan *chan)
+{
+	if (__raw_readl(ADMA_ACSR(chan)) &
+		ADMA_STATUS_BUSY)
+		return 1;
+	else
+		return 0;
+}
+
+static inline int
+iop_chan_get_desc_align(struct iop_adma_chan *chan, int num_slots)
+{
+	return 1;
+}
+#define iop_desc_is_aligned(x, y) 1
+
+static inline int
+iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
+{
+	*slots_per_op = 1;
+	return 1;
+}
+
+#define iop_chan_interrupt_slot_count(s, c) iop_chan_memcpy_slot_count(0, s)
+
+static inline int
+iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+{
+	*slots_per_op = 1;
+	return 1;
+}
+
+static inline int
+iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)
+{
+	int num_slots;
+	/* slots_to_find = 1 for basic descriptor + 1 per 4 sources above 1
+	 * (1 source => 8 bytes) (1 slot => 32 bytes)
+	 */
+	num_slots = 1 + (((src_cnt - 1) << 3) >> 5);
+	if (((src_cnt - 1) << 3) & 0x1f)
+		num_slots++;
+
+	*slots_per_op = num_slots;
+
+	return num_slots;
+}
+
+#define ADMA_MAX_BYTE_COUNT	(16 * 1024 * 1024)
+#define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o)
+
+static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	return hw_desc->dest_addr;
+}
+
+static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	return hw_desc->byte_count_field.byte_count;
+}
+
+static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan,
+					int src_idx)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	return hw_desc->src[src_idx].src_addr;
+}
+
+static inline u32 iop_desc_get_src_count(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	return hw_desc->desc_ctrl_field.src_select + 1;
+}
+
+static inline void
+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	union {
+		u32 value;
+		struct iop13xx_adma_desc_ctrl field;
+	} u_desc_ctrl;
+
+	u_desc_ctrl.value = 0;
+	u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+	u_desc_ctrl.field.int_en = int_en;
+	hw_desc->desc_ctrl = u_desc_ctrl.value;
+	hw_desc->crc_addr = 0;
+}
+
+static inline void
+iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	union {
+		u32 value;
+		struct iop13xx_adma_desc_ctrl field;
+	} u_desc_ctrl;
+
+	u_desc_ctrl.value = 0;
+	u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+	u_desc_ctrl.field.block_fill_en = 1;
+	u_desc_ctrl.field.int_en = int_en;
+	hw_desc->desc_ctrl = u_desc_ctrl.value;
+	hw_desc->crc_addr = 0;
+}
+
+/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
+static inline void
+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	union {
+		u32 value;
+		struct iop13xx_adma_desc_ctrl field;
+	} u_desc_ctrl;
+
+	u_desc_ctrl.value = 0;
+	u_desc_ctrl.field.src_select = src_cnt - 1;
+	u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+	u_desc_ctrl.field.int_en = int_en;
+	hw_desc->desc_ctrl = u_desc_ctrl.value;
+	hw_desc->crc_addr = 0;
+
+}
+#define iop_desc_init_null_xor(d, s, i) iop_desc_init_xor(d, s, i)
+
+/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
+static inline int
+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	union {
+		u32 value;
+		struct iop13xx_adma_desc_ctrl field;
+	} u_desc_ctrl;
+
+	u_desc_ctrl.value = 0;
+	u_desc_ctrl.field.src_select = src_cnt - 1;
+	u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+	u_desc_ctrl.field.zero_result = 1;
+	u_desc_ctrl.field.status_write_back_en = 1;
+	u_desc_ctrl.field.int_en = int_en;
+	hw_desc->desc_ctrl = u_desc_ctrl.value;
+	hw_desc->crc_addr = 0;
+
+	return 1;
+}
+
+static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan,
+					u32 byte_count)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	hw_desc->byte_count = byte_count;
+}
+
+static inline void
+iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
+{
+	int slots_per_op = desc->slots_per_op;
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
+	int i = 0;
+
+	if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+		hw_desc->byte_count = len;
+	} else {
+		do {
+			iter = iop_hw_desc_slot_idx(hw_desc, i);
+			iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+			len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+			i += slots_per_op;
+		} while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
+
+		if (len) {
+			iter = iop_hw_desc_slot_idx(hw_desc, i);
+			iter->byte_count = len;
+		}
+	}
+}
+
+
+static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan,
+					dma_addr_t addr)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	hw_desc->dest_addr = addr;
+	hw_desc->upper_dest_addr = 0;
+}
+
+static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
+					dma_addr_t addr)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	hw_desc->src[0].src_addr = addr;
+	hw_desc->src[0].upper_src_addr = 0;
+}
+
+static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
+					int src_idx, dma_addr_t addr)
+{
+	int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
+	int i = 0;
+
+	do {
+		iter = iop_hw_desc_slot_idx(hw_desc, i);
+		iter->src[src_idx].src_addr = addr;
+		iter->src[src_idx].upper_src_addr = 0;
+		slot_cnt -= slots_per_op;
+		if (slot_cnt) {
+			i += slots_per_op;
+			addr += IOP_ADMA_XOR_MAX_BYTE_COUNT;
+		}
+	} while (slot_cnt);
+}
+
+static inline void
+iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
+	struct iop_adma_chan *chan)
+{
+	iop_desc_init_memcpy(desc, 1);
+	iop_desc_set_byte_count(desc, chan, 0);
+	iop_desc_set_dest_addr(desc, chan, 0);
+	iop_desc_set_memcpy_src_addr(desc, 0);
+}
+
+#define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr
+
+static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
+					u32 next_desc_addr)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	BUG_ON(hw_desc->next_desc);
+	hw_desc->next_desc = next_desc_addr;
+}
+
+static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	return hw_desc->next_desc;
+}
+
+static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	hw_desc->next_desc = 0;
+}
+
+static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
+						u32 val)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	hw_desc->block_fill_data = val;
+}
+
+static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+{
+	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+	struct iop13xx_adma_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
+	struct iop13xx_adma_byte_count byte_count = hw_desc->byte_count_field;
+
+	BUG_ON(!(byte_count.tx_complete && desc_ctrl.zero_result));
+
+	if (desc_ctrl.pq_xfer_en)
+		return byte_count.zero_result_err_q;
+	else
+		return byte_count.zero_result_err;
+}
+
+static inline void iop_chan_append(struct iop_adma_chan *chan)
+{
+	u32 adma_accr;
+
+	adma_accr = __raw_readl(ADMA_ACCR(chan));
+	adma_accr |= 0x2;
+	__raw_writel(adma_accr, ADMA_ACCR(chan));
+}
+
+static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+{
+	do { } while (0);
+}
+
+static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+{
+	return __raw_readl(ADMA_ACSR(chan));
+}
+
+static inline void iop_chan_disable(struct iop_adma_chan *chan)
+{
+	u32 adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
+	adma_chan_ctrl &= ~0x1;
+	__raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
+}
+
+static inline void iop_chan_enable(struct iop_adma_chan *chan)
+{
+	u32 adma_chan_ctrl;
+
+	adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
+	adma_chan_ctrl |= 0x1;
+	__raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
+}
+
+static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
+{
+	u32 status = __raw_readl(ADMA_ACSR(chan));
+	status &= (1 << 12);
+	__raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
+{
+	u32 status = __raw_readl(ADMA_ACSR(chan));
+	status &= (1 << 11);
+	__raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+{
+	u32 status = __raw_readl(ADMA_ACSR(chan));
+	status &= (1 << 9) | (1 << 5) | (1 << 4) | (1 << 3);
+	__raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline int
+iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
+{
+	return test_bit(9, &status);
+}
+
+static inline int
+iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
+{
+	return test_bit(5, &status);
+}
+
+static inline int
+iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+	return test_bit(4, &status);
+}
+
+static inline int
+iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+	return test_bit(3, &status);
+}
+
+static inline int
+iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+	return 0;
+}
+
+static inline int
+iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+	return 0;
+}
+
+static inline int
+iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
+{
+	return 0;
+}
+
+#endif /* _ADMA_H */
diff --git a/include/asm-arm/arch-iop13xx/iop13xx.h b/include/asm-arm/arch-iop13xx/iop13xx.h
index e6736c3..d4e4f82 100644
--- a/include/asm-arm/arch-iop13xx/iop13xx.h
+++ b/include/asm-arm/arch-iop13xx/iop13xx.h
@@ -166,12 +166,22 @@
 #define IOP13XX_INIT_I2C_1	      (1 << 1)
 #define IOP13XX_INIT_I2C_2	      (1 << 2)
 
-#define IQ81340_NUM_UART     2
-#define IQ81340_NUM_I2C      3
-#define IQ81340_NUM_PHYS_MAP_FLASH 1
-#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART +\
-				IQ81340_NUM_I2C +\
-				IQ81340_NUM_PHYS_MAP_FLASH)
+/* ADMA selection flags */
+/* INIT_ADMA_DEFAULT = Rely on CONFIG_IOP13XX_ADMA* */
+#define IOP13XX_INIT_ADMA_DEFAULT     (0)
+#define IOP13XX_INIT_ADMA_0           (1 << 0)
+#define IOP13XX_INIT_ADMA_1           (1 << 1)
+#define IOP13XX_INIT_ADMA_2           (1 << 2)
+
+/* Platform devices */
+#define IQ81340_NUM_UART     		2
+#define IQ81340_NUM_I2C      		3
+#define IQ81340_NUM_PHYS_MAP_FLASH	1
+#define IQ81340_NUM_ADMA     		3
+#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART + \
+				IQ81340_NUM_I2C + \
+				IQ81340_NUM_PHYS_MAP_FLASH + \
+				IQ81340_NUM_ADMA)
 
 /*========================== PMMR offsets for key registers ============*/
 #define IOP13XX_ATU0_PMMR_OFFSET   	0x00048000
@@ -444,22 +454,6 @@
 /*==============================ADMA UNITS===============================*/
 #define IOP13XX_ADMA_PHYS_BASE(chan)	IOP13XX_REG_ADDR32_PHYS((chan << 9))
 #define IOP13XX_ADMA_UPPER_PA(chan)	(IOP13XX_ADMA_PHYS_BASE(chan) + 0xc0)
-#define IOP13XX_ADMA_OFFSET(chan, ofs)	IOP13XX_REG_ADDR32((chan << 9) + (ofs))
-
-#define IOP13XX_ADMA_ACCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x0)
-#define IOP13XX_ADMA_ACSR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x4)
-#define IOP13XX_ADMA_ADAR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x8)
-#define IOP13XX_ADMA_IIPCR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x18)
-#define IOP13XX_ADMA_IIPAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x1c)
-#define IOP13XX_ADMA_IIPUAR(chan)    IOP13XX_ADMA_OFFSET(chan, 0x20)
-#define IOP13XX_ADMA_ANDAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x24)
-#define IOP13XX_ADMA_ADCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x28)
-#define IOP13XX_ADMA_CARMD(chan)     IOP13XX_ADMA_OFFSET(chan, 0x2c)
-#define IOP13XX_ADMA_ABCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x30)
-#define IOP13XX_ADMA_DLADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x34)
-#define IOP13XX_ADMA_DUADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x38)
-#define IOP13XX_ADMA_SLAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x3c + (src <<3))
-#define IOP13XX_ADMA_SUAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x40 + (src <<3))
 
 /*==============================XSI BRIDGE===============================*/
 #define IOP13XX_XBG_BECSR		IOP13XX_REG_ADDR32(0x178c)
diff --git a/include/asm-arm/arch-iop32x/adma.h b/include/asm-arm/arch-iop32x/adma.h
new file mode 100644
index 0000000..5ed9203
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/adma.h
@@ -0,0 +1,5 @@
+#ifndef IOP32X_ADMA_H
+#define IOP32X_ADMA_H
+#include <asm/hardware/iop3xx-adma.h>
+#endif
+
diff --git a/include/asm-arm/arch-iop33x/adma.h b/include/asm-arm/arch-iop33x/adma.h
new file mode 100644
index 0000000..4b92f79
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/adma.h
@@ -0,0 +1,5 @@
+#ifndef IOP33X_ADMA_H
+#define IOP33X_ADMA_H
+#include <asm/hardware/iop3xx-adma.h>
+#endif
+
diff --git a/include/asm-arm/arch-ixp4xx/ixdp425.h b/include/asm-arm/arch-ixp4xx/ixdp425.h
index 3d3820d..e0791af 100644
--- a/include/asm-arm/arch-ixp4xx/ixdp425.h
+++ b/include/asm-arm/arch-ixp4xx/ixdp425.h
@@ -32,4 +32,8 @@
 #define	IXDP425_PCI_INTC_PIN	9
 #define	IXDP425_PCI_INTD_PIN	8
 
+/* NAND Flash pins */
+#define	IXDP425_NAND_NCE_PIN	12
 
+#define	IXDP425_NAND_CMD_BYTE	0x01
+#define	IXDP425_NAND_ADDR_BYTE	0x02
diff --git a/include/asm-arm/arch-ixp4xx/nas100d.h b/include/asm-arm/arch-ixp4xx/nas100d.h
index 84467a5..131e0a1 100644
--- a/include/asm-arm/arch-ixp4xx/nas100d.h
+++ b/include/asm-arm/arch-ixp4xx/nas100d.h
@@ -10,7 +10,7 @@
  * based on ixdp425.h:
  *	Copyright 2004 (c) MontaVista, Software, Inc.
  *
- * This file is licensed under  the terms of the GNU General Public
+ * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
@@ -36,31 +36,11 @@
 #define NAS100D_PCI_INTD_PIN	8
 #define NAS100D_PCI_INTE_PIN	7
 
-/* GPIO */
-
-#define NAS100D_GPIO0           0
-#define NAS100D_GPIO1           1
-#define NAS100D_GPIO2           2
-#define NAS100D_GPIO3           3
-#define NAS100D_GPIO4           4
-#define NAS100D_GPIO5           5
-#define NAS100D_GPIO6           6
-#define NAS100D_GPIO7           7
-#define NAS100D_GPIO8           8
-#define NAS100D_GPIO9           9
-#define NAS100D_GPIO10          10
-#define NAS100D_GPIO11          11
-#define NAS100D_GPIO12          12
-#define NAS100D_GPIO13          13
-#define NAS100D_GPIO14          14
-#define NAS100D_GPIO15          15
-
-
 /* Buttons */
 
-#define NAS100D_PB_GPIO         NAS100D_GPIO14
-#define NAS100D_RB_GPIO         NAS100D_GPIO4
-#define NAS100D_PO_GPIO         NAS100D_GPIO12   /* power off */
+#define NAS100D_PB_GPIO         14
+#define NAS100D_RB_GPIO         4
+#define NAS100D_PO_GPIO         12   /* power off */
 
 #define NAS100D_PB_IRQ          IRQ_IXP4XX_GPIO14
 #define NAS100D_RB_IRQ          IRQ_IXP4XX_GPIO4
diff --git a/include/asm-arm/arch-ixp4xx/nslu2.h b/include/asm-arm/arch-ixp4xx/nslu2.h
index 6b437f7..850fdc5 100644
--- a/include/asm-arm/arch-ixp4xx/nslu2.h
+++ b/include/asm-arm/arch-ixp4xx/nslu2.h
@@ -9,7 +9,7 @@
  * based on ixdp425.h:
  *	Copyright 2004 (c) MontaVista, Software, Inc.
  *
- * This file is licensed under  the terms of the GNU General Public
+ * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
@@ -34,36 +34,14 @@
 #define NSLU2_PCI_INTC_PIN	9
 #define NSLU2_PCI_INTD_PIN	8
 
-
 /* NSLU2 Timer */
 #define NSLU2_FREQ 66000000
-#define NSLU2_CLOCK_TICK_RATE (((NSLU2_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ)
-#define NSLU2_CLOCK_TICKS_PER_USEC ((NSLU2_CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
-
-/* GPIO */
-
-#define NSLU2_GPIO0		0
-#define NSLU2_GPIO1		1
-#define NSLU2_GPIO2		2
-#define NSLU2_GPIO3		3
-#define NSLU2_GPIO4		4
-#define NSLU2_GPIO5		5
-#define NSLU2_GPIO6		6
-#define NSLU2_GPIO7		7
-#define NSLU2_GPIO8		8
-#define NSLU2_GPIO9		9
-#define NSLU2_GPIO10		10
-#define NSLU2_GPIO11		11
-#define NSLU2_GPIO12		12
-#define NSLU2_GPIO13		13
-#define NSLU2_GPIO14		14
-#define NSLU2_GPIO15		15
 
 /* Buttons */
 
-#define NSLU2_PB_GPIO		NSLU2_GPIO5
-#define NSLU2_PO_GPIO		NSLU2_GPIO8	/* power off */
-#define NSLU2_RB_GPIO		NSLU2_GPIO12
+#define NSLU2_PB_GPIO		5
+#define NSLU2_PO_GPIO		8	/* power off */
+#define NSLU2_RB_GPIO		12
 
 #define NSLU2_PB_IRQ		IRQ_IXP4XX_GPIO5
 #define NSLU2_RB_IRQ		IRQ_IXP4XX_GPIO12
@@ -79,16 +57,16 @@
 
 /* LEDs */
 
-#define NSLU2_LED_RED		NSLU2_GPIO0
-#define NSLU2_LED_GRN		NSLU2_GPIO1
+#define NSLU2_LED_RED_GPIO	0
+#define NSLU2_LED_GRN_GPIO	1
 
-#define NSLU2_LED_RED_BM	(1L << NSLU2_LED_RED)
-#define NSLU2_LED_GRN_BM	(1L << NSLU2_LED_GRN)
+#define NSLU2_LED_RED_BM	(1L << NSLU2_LED_RED_GPIO)
+#define NSLU2_LED_GRN_BM	(1L << NSLU2_LED_GRN_GPIO)
 
-#define NSLU2_LED_DISK1		NSLU2_GPIO3
-#define NSLU2_LED_DISK2		NSLU2_GPIO2
+#define NSLU2_LED_DISK1_GPIO	3
+#define NSLU2_LED_DISK2_GPIO	2
 
-#define NSLU2_LED_DISK1_BM	(1L << NSLU2_GPIO2)
-#define NSLU2_LED_DISK2_BM	(1L << NSLU2_GPIO3)
+#define NSLU2_LED_DISK1_BM	(1L << NSLU2_LED_DISK1_GPIO)
+#define NSLU2_LED_DISK2_BM	(1L << NSLU2_LED_DISK2_GPIO)
 
 
diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
index ab194e5..2a44d3d 100644
--- a/include/asm-arm/arch-ixp4xx/platform.h
+++ b/include/asm-arm/arch-ixp4xx/platform.h
@@ -113,6 +113,7 @@
 extern void ixp4xx_map_io(void);
 extern void ixp4xx_init_irq(void);
 extern void ixp4xx_sys_init(void);
+extern void ixp4xx_timer_init(void);
 extern struct sys_timer ixp4xx_timer;
 extern void ixp4xx_pci_preinit(void);
 struct pci_sys_data;
diff --git a/include/asm-arm/arch-ixp4xx/udc.h b/include/asm-arm/arch-ixp4xx/udc.h
index 79b850a..dbdec36f 100644
--- a/include/asm-arm/arch-ixp4xx/udc.h
+++ b/include/asm-arm/arch-ixp4xx/udc.h
@@ -6,25 +6,3 @@
 
 extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
-static inline int udc_gpio_to_irq(unsigned gpio)
-{
-	return 0;
-}
-
-static inline void udc_gpio_init_vbus(unsigned gpio)
-{
-}
-
-static inline void udc_gpio_init_pullup(unsigned gpio)
-{
-}
-
-static inline int udc_gpio_get(unsigned gpio)
-{
-	return 0;
-}
-
-static inline void udc_gpio_set(unsigned gpio, int is_on)
-{
-}
-
diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h
index 09ae6c9..f7a35b7 100644
--- a/include/asm-arm/arch-ixp4xx/uncompress.h
+++ b/include/asm-arm/arch-ixp4xx/uncompress.h
@@ -38,9 +38,10 @@
 static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 {
 	/*
-	 * Coyote and gtwx5715 only have UART2 connected
+	 * Some boards are using UART2 as console
 	 */
-	if (machine_is_adi_coyote() || machine_is_gtwx5715())
+	if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
+			 machine_is_gateway7001() || machine_is_wg302v2())
 		uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
 	else
 		uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff --git a/include/asm-arm/arch-ks8695/gpio.h b/include/asm-arm/arch-ks8695/gpio.h
new file mode 100644
index 0000000..65ceea2
--- /dev/null
+++ b/include/asm-arm/arch-ks8695/gpio.h
@@ -0,0 +1,79 @@
+/*
+ * include/asm-arm/arch-ks8695/gpio.h
+ *
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_GPIO_H_
+#define __ASM_ARCH_GPIO_H_
+
+#define KS8695_GPIO_0		0
+#define KS8695_GPIO_1		1
+#define KS8695_GPIO_2		2
+#define KS8695_GPIO_3		3
+#define KS8695_GPIO_4		4
+#define KS8695_GPIO_5		5
+#define KS8695_GPIO_6		6
+#define KS8695_GPIO_7		7
+#define KS8695_GPIO_8		8
+#define KS8695_GPIO_9		9
+#define KS8695_GPIO_10		10
+#define KS8695_GPIO_11		11
+#define KS8695_GPIO_12		12
+#define KS8695_GPIO_13		13
+#define KS8695_GPIO_14		14
+#define KS8695_GPIO_15		15
+
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
+
+/*
+ * Configure the GPIO line as an input.
+ */
+int __init_or_module gpio_direction_input(unsigned int pin);
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state);
+
+/*
+ * Set the state of an output GPIO line.
+ */
+void gpio_set_value(unsigned int pin, unsigned int state);
+
+/*
+ * Read the state of a GPIO line.
+ */
+int gpio_get_value(unsigned int pin);
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+int gpio_to_irq(unsigned int pin);
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq);
+
+
+#include <asm-generic/gpio.h>
+
+static inline int gpio_request(unsigned int pin, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned int pin)
+{
+}
+
+#endif
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index bed042d..3280ee2 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -30,30 +30,12 @@
 	DMA_PRIO_LOW = 2
 } pxa_dma_prio;
 
-#if defined(CONFIG_PXA27x)
-
-#define PXA_DMA_CHANNELS	32
-
-#define pxa_for_each_dma_prio(ch, prio)					\
-for (									\
-	ch = prio * 4;							\
-	ch != (4 << prio) + 16;						\
-	ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1)	\
-)
-
-#elif defined(CONFIG_PXA25x)
-
-#define PXA_DMA_CHANNELS	16
-
-#define pxa_for_each_dma_prio(ch, prio)					\
-	for (ch = prio * 4; ch != (4 << prio); ch++)
-
-#endif
-
 /*
  * DMA registration
  */
 
+int __init pxa_init_dma(int num_ch);
+
 int pxa_request_dma (char *name,
 			 pxa_dma_prio prio,
 			 void (*irq_handler)(int, void *),
diff --git a/include/asm-arm/arch-pxa/entry-macro.S b/include/asm-arm/arch-pxa/entry-macro.S
index 1d5fbb9..b7e7308 100644
--- a/include/asm-arm/arch-pxa/entry-macro.S
+++ b/include/asm-arm/arch-pxa/entry-macro.S
@@ -20,20 +20,38 @@
 		.endm
 
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifdef CONFIG_PXA27x
-		mrc	p6, 0, \irqstat, c0, c0, 0		@ ICIP
-		mrc	p6, 0, \irqnr, c1, c0, 0		@ ICMR
-#else
+		mrc	p15, 0, \tmp, c0, c0, 0		@ CPUID
+		mov	\tmp, \tmp, lsr #13
+		and	\tmp, \tmp, #0x7		@ Core G
+		cmp	\tmp, #1
+		bhi	1004f
+
 		mov	\base, #io_p2v(0x40000000)	@ IIR Ctl = 0x40d00000
 		add	\base, \base, #0x00d00000
 		ldr	\irqstat, [\base, #0]		@ ICIP
 		ldr	\irqnr, [\base, #4]		@ ICMR
-#endif
+		b	1002f
+
+1004:
+		mrc	p6, 0, \irqstat, c6, c0, 0	@ ICIP2
+		mrc	p6, 0, \irqnr, c7, c0, 0	@ ICMR2
+		ands	\irqstat, \irqstat, \irqnr
+		beq	1003f
+		rsb	\irqstat, \irqnr, #0
+		and	\irqstat, \irqstat, \irqnr
+		clz	\irqnr, \irqstat
+		rsb	\irqnr, \irqnr, #31
+		add	\irqnr, \irqnr, #32
+		b	1001f
+1003:
+		mrc	p6, 0, \irqstat, c0, c0, 0	@ ICIP
+		mrc	p6, 0, \irqnr, c1, c0, 0	@ ICMR
+1002:
 		ands	\irqnr, \irqstat, \irqnr
 		beq	1001f
 		rsb	\irqstat, \irqnr, #0
 		and	\irqstat, \irqstat, \irqnr
 		clz	\irqnr, \irqstat
-		rsb	\irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
+		rsb	\irqnr, \irqnr, #31
 1001:
 		.endm
diff --git a/include/asm-arm/arch-pxa/gpio.h b/include/asm-arm/arch-pxa/gpio.h
index aeba2434..9e99241 100644
--- a/include/asm-arm/arch-pxa/gpio.h
+++ b/include/asm-arm/arch-pxa/gpio.h
@@ -45,7 +45,8 @@
 
 static inline int gpio_direction_output(unsigned gpio, int value)
 {
-	return pxa_gpio_mode(gpio | GPIO_OUT | (value ? 0 : GPIO_DFLT_LOW));
+	return pxa_gpio_mode(gpio | GPIO_OUT |
+                         (value ? GPIO_DFLT_HIGH : GPIO_DFLT_LOW));
 }
 
 static inline int __gpio_get_value(unsigned gpio)
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index e2bdc2f..3861217 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -62,6 +62,42 @@
 
 #ifndef __ASSEMBLY__
 
+#define __cpu_is_pxa21x(id)				\
+	({						\
+		unsigned int _id = (id) >> 4 & 0xf3f;	\
+		_id == 0x212;				\
+	})
+
+#define __cpu_is_pxa25x(id)				\
+	({						\
+		unsigned int _id = (id) >> 4 & 0xfff;	\
+		_id == 0x2d0 || _id == 0x290;		\
+	})
+
+#define __cpu_is_pxa27x(id)				\
+	({						\
+		unsigned int _id = (id) >> 4 & 0xfff;	\
+		_id == 0x411;				\
+	})
+
+#define cpu_is_pxa21x()					\
+	({						\
+		unsigned int id = read_cpuid(CPUID_ID);	\
+		__cpu_is_pxa21x(id);			\
+	})
+
+#define cpu_is_pxa25x()					\
+	({						\
+		unsigned int id = read_cpuid(CPUID_ID);	\
+		__cpu_is_pxa25x(id);			\
+	})
+
+#define cpu_is_pxa27x()					\
+	({						\
+		unsigned int id = read_cpuid(CPUID_ID);	\
+		__cpu_is_pxa27x(id);			\
+	})
+
 /*
  * Handy routine to set GPIO alternate functions
  */
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index 67ed436..a07fe0f 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -11,14 +11,9 @@
  */
 
 
+#define PXA_IRQ(x)	(x)
+
 #ifdef CONFIG_PXA27x
-#define PXA_IRQ_SKIP	0
-#else
-#define PXA_IRQ_SKIP	7
-#endif
-
-#define PXA_IRQ(x)	((x) - PXA_IRQ_SKIP)
-
 #define IRQ_SSP3	PXA_IRQ(0)	/* SSP3 service request */
 #define IRQ_MSL		PXA_IRQ(1)	/* MSL Interface interrupt */
 #define IRQ_USBH2	PXA_IRQ(2)	/* USB Host interrupt 1 (OHCI) */
@@ -26,6 +21,8 @@
 #define IRQ_KEYPAD	PXA_IRQ(4)	/* Key pad controller */
 #define IRQ_MEMSTK	PXA_IRQ(5)	/* Memory Stick interrupt */
 #define IRQ_PWRI2C	PXA_IRQ(6)	/* Power I2C interrupt */
+#endif
+
 #define IRQ_HWUART	PXA_IRQ(7)	/* HWUART Transmit/Receive/Error (PXA26x) */
 #define IRQ_OST_4_11	PXA_IRQ(7)	/* OS timer 4-11 matches (PXA27x) */
 #define	IRQ_GPIO0	PXA_IRQ(8)	/* GPIO0 Edge Detect */
@@ -58,18 +55,15 @@
 #ifdef CONFIG_PXA27x
 #define IRQ_TPM		PXA_IRQ(32)	/* TPM interrupt */
 #define IRQ_CAMERA	PXA_IRQ(33)	/* Camera Interface */
-
-#define PXA_INTERNAL_IRQS 34
-#else
-#define PXA_INTERNAL_IRQS 32
 #endif
 
-#define GPIO_2_x_TO_IRQ(x)	\
-			PXA_IRQ((x) - 2 + PXA_INTERNAL_IRQS)
+#define PXA_GPIO_IRQ_BASE	(64)
+#define PXA_GPIO_IRQ_NUM	(128)
+
+#define GPIO_2_x_TO_IRQ(x)	(PXA_GPIO_IRQ_BASE + (x))
 #define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
 
-#define IRQ_TO_GPIO_2_x(i)	\
-			((i) - IRQ_GPIO(2) + 2)
+#define IRQ_TO_GPIO_2_x(i)	((i) - PXA_GPIO_IRQ_BASE)
 #define IRQ_TO_GPIO(i)	(((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
 
 #if defined(CONFIG_PXA25x)
@@ -84,7 +78,7 @@
  * these.  If you need more, increase IRQ_BOARD_END, but keep it
  * within sensible limits.
  */
-#define IRQ_BOARD_START		(IRQ_GPIO(PXA_LAST_GPIO) + 1)
+#define IRQ_BOARD_START		(PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
 #define IRQ_BOARD_END		(IRQ_BOARD_START + 16)
 
 #define IRQ_SA1111_START	(IRQ_BOARD_END)
diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h
index 7a8a1cd..52243a6 100644
--- a/include/asm-arm/arch-pxa/pm.h
+++ b/include/asm-arm/arch-pxa/pm.h
@@ -9,4 +9,3 @@
 
 extern int pxa_pm_prepare(suspend_state_t state);
 extern int pxa_pm_enter(suspend_state_t state);
-extern int pxa_pm_finish(suspend_state_t state);
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index dbcc929..e68b593 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1765,29 +1765,9 @@
 #define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : NULL))
 
 /*
- * MultiMediaCard (MMC) controller
+ * MultiMediaCard (MMC) controller - see drivers/mmc/host/pxamci.h
  */
 
-#define MMC_STRPCL	__REG(0x41100000)  /* Control to start and stop MMC clock */
-#define MMC_STAT	__REG(0x41100004)  /* MMC Status Register (read only) */
-#define MMC_CLKRT	__REG(0x41100008)  /* MMC clock rate */
-#define MMC_SPI		__REG(0x4110000c)  /* SPI mode control bits */
-#define MMC_CMDAT	__REG(0x41100010)  /* Command/response/data sequence control */
-#define MMC_RESTO	__REG(0x41100014)  /* Expected response time out */
-#define MMC_RDTO	__REG(0x41100018)  /* Expected data read time out */
-#define MMC_BLKLEN	__REG(0x4110001c)  /* Block length of data transaction */
-#define MMC_NOB		__REG(0x41100020)  /* Number of blocks, for block mode */
-#define MMC_PRTBUF	__REG(0x41100024)  /* Partial MMC_TXFIFO FIFO written */
-#define MMC_I_MASK	__REG(0x41100028)  /* Interrupt Mask */
-#define MMC_I_REG	__REG(0x4110002c)  /* Interrupt Register (read only) */
-#define MMC_CMD		__REG(0x41100030)  /* Index of current command */
-#define MMC_ARGH	__REG(0x41100034)  /* MSW part of the current command argument */
-#define MMC_ARGL	__REG(0x41100038)  /* LSW part of the current command argument */
-#define MMC_RES		__REG(0x4110003c)  /* Response FIFO (read only) */
-#define MMC_RXFIFO	__REG(0x41100040)  /* Receive FIFO (read only) */
-#define MMC_TXFIFO	__REG(0x41100044)  /* Transmit FIFO (write only) */
-
-
 /*
  * Core Clock
  */
diff --git a/include/asm-arm/arch-pxa/udc.h b/include/asm-arm/arch-pxa/udc.h
index 8bc6f9c..27aa3a9 100644
--- a/include/asm-arm/arch-pxa/udc.h
+++ b/include/asm-arm/arch-pxa/udc.h
@@ -1,41 +1,8 @@
 /*
  * linux/include/asm-arm/arch-pxa/udc.h
  *
- * This supports machine-specific differences in how the PXA2xx
- * USB Device Controller (UDC) is wired.
- *
  */
 #include <asm/mach/udc_pxa2xx.h>
 
 extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
-static inline int udc_gpio_to_irq(unsigned gpio)
-{
-	return IRQ_GPIO(gpio & GPIO_MD_MASK_NR);
-}
-
-static inline void udc_gpio_init_vbus(unsigned gpio)
-{
-	pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_IN);
-}
-
-static inline void udc_gpio_init_pullup(unsigned gpio)
-{
-	pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_OUT | GPIO_DFLT_LOW);
-}
-
-static inline int udc_gpio_get(unsigned gpio)
-{
-	return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
-}
-
-static inline void udc_gpio_set(unsigned gpio, int is_on)
-{
-	int mask = GPIO_bit(gpio);
-
-	if (is_on)
-		GPSR(gpio) = mask;
-	else
-		GPCR(gpio) = mask;
-}
-
diff --git a/include/asm-arm/arch-s3c2410/anubis-cpld.h b/include/asm-arm/arch-s3c2410/anubis-cpld.h
index dcebf6d..168b93f 100644
--- a/include/asm-arm/arch-s3c2410/anubis-cpld.h
+++ b/include/asm-arm/arch-s3c2410/anubis-cpld.h
@@ -18,4 +18,8 @@
 
 #define ANUBIS_CTRL1_NANDSEL		(0x3)
 
+/* IDREG - revision */
+
+#define ANUBIS_IDREG_REVMASK		(0x7)
+
 #endif /* __ASM_ARCH_ANUBISCPLD_H */
diff --git a/include/asm-arm/arch-s3c2410/anubis-map.h b/include/asm-arm/arch-s3c2410/anubis-map.h
index ab076de..830d114 100644
--- a/include/asm-arm/arch-s3c2410/anubis-map.h
+++ b/include/asm-arm/arch-s3c2410/anubis-map.h
@@ -27,14 +27,8 @@
 #define ANUBIS_VA_CTRL1	    ANUBIS_IOADDR(0x00000000)	 /* 0x01800000 */
 #define ANUBIS_PA_CTRL1	    (ANUBIS_PA_CPLD)
 
-#define ANUBIS_VA_CTRL2	    ANUBIS_IOADDR(0x00100000)	 /* 0x01900000 */
-#define ANUBIS_PA_CTRL2	    (ANUBIS_PA_CPLD)
-
-#define ANUBIS_VA_CTRL3	    ANUBIS_IOADDR(0x00200000)	 /* 0x01A00000 */
-#define ANUBIS_PA_CTRL3	    (ANUBIS_PA_CPLD)
-
-#define ANUBIS_VA_CTRL4	    ANUBIS_IOADDR(0x00300000)	 /* 0x01B00000 */
-#define ANUBIS_PA_CTRL4	    (ANUBIS_PA_CPLD)
+#define ANUBIS_VA_IDREG	    ANUBIS_IOADDR(0x00300000)	 /* 0x01B00000 */
+#define ANUBIS_PA_IDREG	    (ANUBIS_PA_CPLD + (3<<23))
 
 #define ANUBIS_IDEPRI	    ANUBIS_IOADDR(0x01000000)
 #define ANUBIS_IDEPRIAUX    ANUBIS_IOADDR(0x01100000)
diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index c79cb18..3b49cd1 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -124,7 +124,7 @@
 #define IRQ_S3C2443_DMA		S3C2410_IRQ(17)		/* IRQ_DMA1 */
 #define IRQ_S3C2443_UART3	S3C2410_IRQ(18)		/* IRQ_DMA2 */
 #define IRQ_S3C2443_CFCON	S3C2410_IRQ(19)		/* IRQ_DMA3 */
-#define IRQ_S3C2443_SDI1	S3C2410_IRQ(20)		/* IRQ_SDI */
+#define IRQ_S3C2443_HSMMC	S3C2410_IRQ(20)		/* IRQ_SDI */
 #define IRQ_S3C2443_NAND	S3C2410_IRQ(24)		/* reserved */
 
 #define IRQ_S3C2443_LCD1	S3C2410_IRQSUB(14)
diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
index 4505aef..19e77f0 100644
--- a/include/asm-arm/arch-s3c2410/map.h
+++ b/include/asm-arm/arch-s3c2410/map.h
@@ -153,6 +153,10 @@
 #define S3C2440_PA_AC97	   (0x5B000000)
 #define S3C2440_SZ_AC97	   SZ_1M
 
+/* S3C2443 High-speed SD/MMC */
+#define S3C2443_PA_HSMMC   (0x4A800000)
+#define S3C2443_SZ_HSMMC   (256)
+
 /* ISA style IO, for each machine to sort out mappings for, if it
  * implements it. We reserve two 16M regions for ISA.
  */
diff --git a/include/asm-arm/arch-s3c2410/osiris-cpld.h b/include/asm-arm/arch-s3c2410/osiris-cpld.h
index 3b64984..229ab23 100644
--- a/include/asm-arm/arch-s3c2410/osiris-cpld.h
+++ b/include/asm-arm/arch-s3c2410/osiris-cpld.h
@@ -1,6 +1,6 @@
 /* linux/include/asm-arm/arch-s3c2410/osiris-cpld.h
  *
- * Copyright (c) 2005 Simtec Electronics
+ * Copyright 2005 Simtec Electronics
  *	http://www.simtec.co.uk/products/
  *	Ben Dooks <ben@simtec.co.uk>
  *
@@ -14,12 +14,17 @@
 #ifndef __ASM_ARCH_OSIRISCPLD_H
 #define __ASM_ARCH_OSIRISCPLD_H
 
-/* CTRL1 - NAND WP control */
+/* CTRL0 - NAND WP control */
 
-#define OSIRIS_CTRL1_NANDSEL		(0x3)
-#define OSIRIS_CTRL1_BOOT_INT		(1<<3)
-#define OSIRIS_CTRL1_PCMCIA		(1<<4)
-#define OSIRIS_CTRL1_PCMCIA_nWAIT	(1<<6)
-#define OSIRIS_CTRL1_PCMCIA_nIOIS16	(1<<7)
+#define OSIRIS_CTRL0_NANDSEL		(0x3)
+#define OSIRIS_CTRL0_BOOT_INT		(1<<3)
+#define OSIRIS_CTRL0_PCMCIA		(1<<4)
+#define OSIRIS_CTRL0_FIX8		(1<<5)
+#define OSIRIS_CTRL0_PCMCIA_nWAIT	(1<<6)
+#define OSIRIS_CTRL0_PCMCIA_nIOIS16	(1<<7)
+
+#define OSIRIS_CTRL1_FIX8		(1<<0)
+
+#define OSIRIS_ID_REVMASK		(0x7)
 
 #endif /* __ASM_ARCH_OSIRISCPLD_H */
diff --git a/include/asm-arm/arch-s3c2410/osiris-map.h b/include/asm-arm/arch-s3c2410/osiris-map.h
index a14164d..b5c74d2 100644
--- a/include/asm-arm/arch-s3c2410/osiris-map.h
+++ b/include/asm-arm/arch-s3c2410/osiris-map.h
@@ -24,16 +24,19 @@
 
 /* we put the CPLD registers next, to get them out of the way */
 
-#define OSIRIS_VA_CTRL1	    OSIRIS_IOADDR(0x00000000)
-#define OSIRIS_PA_CTRL1	    (OSIRIS_PA_CPLD)
+#define OSIRIS_VA_CTRL0		OSIRIS_IOADDR(0x00000000)
+#define OSIRIS_PA_CTRL0		(OSIRIS_PA_CPLD)
 
-#define OSIRIS_VA_CTRL2	    OSIRIS_IOADDR(0x00100000)
-#define OSIRIS_PA_CTRL2	    (OSIRIS_PA_CPLD + (1<<23))
+#define OSIRIS_VA_CTRL1		OSIRIS_IOADDR(0x00100000)
+#define OSIRIS_PA_CTRL1		(OSIRIS_PA_CPLD + (1<<23))
 
-#define OSIRIS_VA_CTRL3	    OSIRIS_IOADDR(0x00200000)
-#define OSIRIS_PA_CTRL3	    (OSIRIS_PA_CPLD + (2<<23))
+#define OSIRIS_VA_CTRL2		OSIRIS_IOADDR(0x00200000)
+#define OSIRIS_PA_CTRL2		(OSIRIS_PA_CPLD + (2<<23))
 
-#define OSIRIS_VA_CTRL4	    OSIRIS_IOADDR(0x00300000)
-#define OSIRIS_PA_CTRL4	    (OSIRIS_PA_CPLD + (3<<23))
+#define OSIRIS_VA_CTRL3		OSIRIS_IOADDR(0x00300000)
+#define OSIRIS_PA_CTRL3		(OSIRIS_PA_CPLD + (2<<23))
+
+#define OSIRIS_VA_IDREG		OSIRIS_IOADDR(0x00700000)
+#define OSIRIS_PA_IDREG		(OSIRIS_PA_CPLD + (7<<23))
 
 #endif /* __ASM_ARCH_OSIRISMAP_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-gpioj.h b/include/asm-arm/arch-s3c2410/regs-gpioj.h
index 02131a5..0362332 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpioj.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpioj.h
@@ -98,5 +98,9 @@
 #define S3C2440_GPJ12_OUTP      (0x01 << 24)
 #define S3C2440_GPJ12_CAMRESET  (0x02 << 24)
 
+#define S3C2443_GPJ13		S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 13)
+#define S3C2443_GPJ14		S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 14)
+#define S3C2443_GPJ15		S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 15)
+
 #endif	/* __ASM_ARCH_REGS_GPIOJ_H */
 
diff --git a/include/asm-arm/arch-s3c2410/regs-s3c2412.h b/include/asm-arm/arch-s3c2410/regs-s3c2412.h
new file mode 100644
index 0000000..8ca6a3b
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/regs-s3c2412.h
@@ -0,0 +1,21 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-s3c2412.h
+ *
+ * Copyright 2007 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2412 specific register definitions
+*/
+
+#ifndef __ASM_ARCH_REGS_S3C2412_H
+#define __ASM_ARCH_REGS_S3C2412_H "s3c2412"
+
+#define S3C2412_SWRST		(S3C24XX_VA_CLKPWR + 0x30)
+#define S3C2412_SWRST_RESET	(0x533C2412)
+
+#endif	/* __ASM_ARCH_REGS_S3C2412_H */
+
diff --git a/include/asm-arm/arch-s3c2410/regs-spi.h b/include/asm-arm/arch-s3c2410/regs-spi.h
index 3552280..4a499a1 100644
--- a/include/asm-arm/arch-s3c2410/regs-spi.h
+++ b/include/asm-arm/arch-s3c2410/regs-spi.h
@@ -12,6 +12,8 @@
 #ifndef __ASM_ARCH_REGS_SPI_H
 #define __ASM_ARCH_REGS_SPI_H
 
+#define S3C2410_SPI1	(0x20)
+#define S3C2412_SPI1	(0x100)
 
 #define S3C2410_SPCON	(0x00)
 
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index 3679a8a..d7a777f 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -7,6 +7,7 @@
  */
 #include <asm/ptrace.h>
 #include <asm/user.h>
+#include <asm/hwcap.h>
 
 typedef unsigned long elf_greg_t;
 typedef unsigned long elf_freg_t[3];
@@ -39,31 +40,9 @@
 #endif
 #define ELF_ARCH	EM_ARM
 
-/*
- * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
- */
-#define HWCAP_SWP	1
-#define HWCAP_HALF	2
-#define HWCAP_THUMB	4
-#define HWCAP_26BIT	8	/* Play it safe */
-#define HWCAP_FAST_MULT	16
-#define HWCAP_FPA	32
-#define HWCAP_VFP	64
-#define HWCAP_EDSP	128
-#define HWCAP_JAVA	256
-#define HWCAP_IWMMXT	512
-#define HWCAP_CRUNCH	1024
-
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 /*
- * This yields a mask that user programs can use to figure out what
- * instruction set this cpu supports.
- */
-#define ELF_HWCAP	(elf_hwcap)
-extern unsigned int elf_hwcap;
-
-/*
  * This yields a string that ld.so will use to load implementation
  * specific libraries for optimization.  This is more specific in
  * intent than poking at uname or /proc/cpuinfo.
diff --git a/include/asm-arm/fb.h b/include/asm-arm/fb.h
new file mode 100644
index 0000000..d92e99c
--- /dev/null
+++ b/include/asm-arm/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
new file mode 100644
index 0000000..10834b5
--- /dev/null
+++ b/include/asm-arm/hardware/iop3xx-adma.h
@@ -0,0 +1,892 @@
+/*
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _ADMA_H
+#define _ADMA_H
+#include <linux/types.h>
+#include <linux/io.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop_adma.h>
+
+/* Memory copy units */
+#define DMA_CCR(chan)		(chan->mmr_base + 0x0)
+#define DMA_CSR(chan)		(chan->mmr_base + 0x4)
+#define DMA_DAR(chan)		(chan->mmr_base + 0xc)
+#define DMA_NDAR(chan)		(chan->mmr_base + 0x10)
+#define DMA_PADR(chan)		(chan->mmr_base + 0x14)
+#define DMA_PUADR(chan)	(chan->mmr_base + 0x18)
+#define DMA_LADR(chan)		(chan->mmr_base + 0x1c)
+#define DMA_BCR(chan)		(chan->mmr_base + 0x20)
+#define DMA_DCR(chan)		(chan->mmr_base + 0x24)
+
+/* Application accelerator unit  */
+#define AAU_ACR(chan)		(chan->mmr_base + 0x0)
+#define AAU_ASR(chan)		(chan->mmr_base + 0x4)
+#define AAU_ADAR(chan)		(chan->mmr_base + 0x8)
+#define AAU_ANDAR(chan)	(chan->mmr_base + 0xc)
+#define AAU_SAR(src, chan)	(chan->mmr_base + (0x10 + ((src) << 2)))
+#define AAU_DAR(chan)		(chan->mmr_base + 0x20)
+#define AAU_ABCR(chan)		(chan->mmr_base + 0x24)
+#define AAU_ADCR(chan)		(chan->mmr_base + 0x28)
+#define AAU_SAR_EDCR(src_edc)	(chan->mmr_base + (0x02c + ((src_edc-4) << 2)))
+#define AAU_EDCR0_IDX	8
+#define AAU_EDCR1_IDX	17
+#define AAU_EDCR2_IDX	26
+
+#define DMA0_ID 0
+#define DMA1_ID 1
+#define AAU_ID 2
+
+struct iop3xx_aau_desc_ctrl {
+	unsigned int int_en:1;
+	unsigned int blk1_cmd_ctrl:3;
+	unsigned int blk2_cmd_ctrl:3;
+	unsigned int blk3_cmd_ctrl:3;
+	unsigned int blk4_cmd_ctrl:3;
+	unsigned int blk5_cmd_ctrl:3;
+	unsigned int blk6_cmd_ctrl:3;
+	unsigned int blk7_cmd_ctrl:3;
+	unsigned int blk8_cmd_ctrl:3;
+	unsigned int blk_ctrl:2;
+	unsigned int dual_xor_en:1;
+	unsigned int tx_complete:1;
+	unsigned int zero_result_err:1;
+	unsigned int zero_result_en:1;
+	unsigned int dest_write_en:1;
+};
+
+struct iop3xx_aau_e_desc_ctrl {
+	unsigned int reserved:1;
+	unsigned int blk1_cmd_ctrl:3;
+	unsigned int blk2_cmd_ctrl:3;
+	unsigned int blk3_cmd_ctrl:3;
+	unsigned int blk4_cmd_ctrl:3;
+	unsigned int blk5_cmd_ctrl:3;
+	unsigned int blk6_cmd_ctrl:3;
+	unsigned int blk7_cmd_ctrl:3;
+	unsigned int blk8_cmd_ctrl:3;
+	unsigned int reserved2:7;
+};
+
+struct iop3xx_dma_desc_ctrl {
+	unsigned int pci_transaction:4;
+	unsigned int int_en:1;
+	unsigned int dac_cycle_en:1;
+	unsigned int mem_to_mem_en:1;
+	unsigned int crc_data_tx_en:1;
+	unsigned int crc_gen_en:1;
+	unsigned int crc_seed_dis:1;
+	unsigned int reserved:21;
+	unsigned int crc_tx_complete:1;
+};
+
+struct iop3xx_desc_dma {
+	u32 next_desc;
+	union {
+		u32 pci_src_addr;
+		u32 pci_dest_addr;
+		u32 src_addr;
+	};
+	union {
+		u32 upper_pci_src_addr;
+		u32 upper_pci_dest_addr;
+	};
+	union {
+		u32 local_pci_src_addr;
+		u32 local_pci_dest_addr;
+		u32 dest_addr;
+	};
+	u32 byte_count;
+	union {
+		u32 desc_ctrl;
+		struct iop3xx_dma_desc_ctrl desc_ctrl_field;
+	};
+	u32 crc_addr;
+};
+
+struct iop3xx_desc_aau {
+	u32 next_desc;
+	u32 src[4];
+	u32 dest_addr;
+	u32 byte_count;
+	union {
+		u32 desc_ctrl;
+		struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+	};
+	union {
+		u32 src_addr;
+		u32 e_desc_ctrl;
+		struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
+	} src_edc[31];
+};
+
+struct iop3xx_aau_gfmr {
+	unsigned int gfmr1:8;
+	unsigned int gfmr2:8;
+	unsigned int gfmr3:8;
+	unsigned int gfmr4:8;
+};
+
+struct iop3xx_desc_pq_xor {
+	u32 next_desc;
+	u32 src[3];
+	union {
+		u32 data_mult1;
+		struct iop3xx_aau_gfmr data_mult1_field;
+	};
+	u32 dest_addr;
+	u32 byte_count;
+	union {
+		u32 desc_ctrl;
+		struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+	};
+	union {
+		u32 src_addr;
+		u32 e_desc_ctrl;
+		struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
+		u32 data_multiplier;
+		struct iop3xx_aau_gfmr data_mult_field;
+		u32 reserved;
+	} src_edc_gfmr[19];
+};
+
+struct iop3xx_desc_dual_xor {
+	u32 next_desc;
+	u32 src0_addr;
+	u32 src1_addr;
+	u32 h_src_addr;
+	u32 d_src_addr;
+	u32 h_dest_addr;
+	u32 byte_count;
+	union {
+		u32 desc_ctrl;
+		struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+	};
+	u32 d_dest_addr;
+};
+
+union iop3xx_desc {
+	struct iop3xx_desc_aau *aau;
+	struct iop3xx_desc_dma *dma;
+	struct iop3xx_desc_pq_xor *pq_xor;
+	struct iop3xx_desc_dual_xor *dual_xor;
+	void *ptr;
+};
+
+static inline int iop_adma_get_max_xor(void)
+{
+	return 32;
+}
+
+static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
+{
+	int id = chan->device->id;
+
+	switch (id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		return __raw_readl(DMA_DAR(chan));
+	case AAU_ID:
+		return __raw_readl(AAU_ADAR(chan));
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
+						u32 next_desc_addr)
+{
+	int id = chan->device->id;
+
+	switch (id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		__raw_writel(next_desc_addr, DMA_NDAR(chan));
+		break;
+	case AAU_ID:
+		__raw_writel(next_desc_addr, AAU_ANDAR(chan));
+		break;
+	}
+
+}
+
+#define IOP_ADMA_STATUS_BUSY (1 << 10)
+#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT (1024)
+#define IOP_ADMA_XOR_MAX_BYTE_COUNT (16 * 1024 * 1024)
+#define IOP_ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
+
+static inline int iop_chan_is_busy(struct iop_adma_chan *chan)
+{
+	u32 status = __raw_readl(DMA_CSR(chan));
+	return (status & IOP_ADMA_STATUS_BUSY) ? 1 : 0;
+}
+
+static inline int iop_desc_is_aligned(struct iop_adma_desc_slot *desc,
+					int num_slots)
+{
+	/* num_slots will only ever be 1, 2, 4, or 8 */
+	return (desc->idx & (num_slots - 1)) ? 0 : 1;
+}
+
+/* to do: support large (i.e. > hw max) buffer sizes */
+static inline int iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
+{
+	*slots_per_op = 1;
+	return 1;
+}
+
+/* to do: support large (i.e. > hw max) buffer sizes */
+static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+{
+	*slots_per_op = 1;
+	return 1;
+}
+
+static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
+					int *slots_per_op)
+{
+	const static int slot_count_table[] = { 0,
+						1, 1, 1, 1, /* 01 - 04 */
+						2, 2, 2, 2, /* 05 - 08 */
+						4, 4, 4, 4, /* 09 - 12 */
+						4, 4, 4, 4, /* 13 - 16 */
+						8, 8, 8, 8, /* 17 - 20 */
+						8, 8, 8, 8, /* 21 - 24 */
+						8, 8, 8, 8, /* 25 - 28 */
+						8, 8, 8, 8, /* 29 - 32 */
+					      };
+	*slots_per_op = slot_count_table[src_cnt];
+	return *slots_per_op;
+}
+
+static inline int
+iop_chan_interrupt_slot_count(int *slots_per_op, struct iop_adma_chan *chan)
+{
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		return iop_chan_memcpy_slot_count(0, slots_per_op);
+	case AAU_ID:
+		return iop3xx_aau_xor_slot_count(0, 2, slots_per_op);
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+static inline int iop_chan_xor_slot_count(size_t len, int src_cnt,
+						int *slots_per_op)
+{
+	int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
+
+	if (len <= IOP_ADMA_XOR_MAX_BYTE_COUNT)
+		return slot_cnt;
+
+	len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
+	while (len > IOP_ADMA_XOR_MAX_BYTE_COUNT) {
+		len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
+		slot_cnt += *slots_per_op;
+	}
+
+	if (len)
+		slot_cnt += *slots_per_op;
+
+	return slot_cnt;
+}
+
+/* zero sum on iop3xx is limited to 1k at a time so it requires multiple
+ * descriptors
+ */
+static inline int iop_chan_zero_sum_slot_count(size_t len, int src_cnt,
+						int *slots_per_op)
+{
+	int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
+
+	if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT)
+		return slot_cnt;
+
+	len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+	while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+		len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+		slot_cnt += *slots_per_op;
+	}
+
+	if (len)
+		slot_cnt += *slots_per_op;
+
+	return slot_cnt;
+}
+
+static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan)
+{
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		return hw_desc.dma->dest_addr;
+	case AAU_ID:
+		return hw_desc.aau->dest_addr;
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan)
+{
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		return hw_desc.dma->byte_count;
+	case AAU_ID:
+		return hw_desc.aau->byte_count;
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+/* translate the src_idx to a descriptor word index */
+static inline int __desc_idx(int src_idx)
+{
+	const static int desc_idx_table[] = { 0, 0, 0, 0,
+					      0, 1, 2, 3,
+					      5, 6, 7, 8,
+					      9, 10, 11, 12,
+					      14, 15, 16, 17,
+					      18, 19, 20, 21,
+					      23, 24, 25, 26,
+					      27, 28, 29, 30,
+					    };
+
+	return desc_idx_table[src_idx];
+}
+
+static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan,
+					int src_idx)
+{
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		return hw_desc.dma->src_addr;
+	case AAU_ID:
+		break;
+	default:
+		BUG();
+	}
+
+	if (src_idx < 4)
+		return hw_desc.aau->src[src_idx];
+	else
+		return hw_desc.aau->src_edc[__desc_idx(src_idx)].src_addr;
+}
+
+static inline void iop3xx_aau_desc_set_src_addr(struct iop3xx_desc_aau *hw_desc,
+					int src_idx, dma_addr_t addr)
+{
+	if (src_idx < 4)
+		hw_desc->src[src_idx] = addr;
+	else
+		hw_desc->src_edc[__desc_idx(src_idx)].src_addr = addr;
+}
+
+static inline void
+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+{
+	struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
+	union {
+		u32 value;
+		struct iop3xx_dma_desc_ctrl field;
+	} u_desc_ctrl;
+
+	u_desc_ctrl.value = 0;
+	u_desc_ctrl.field.mem_to_mem_en = 1;
+	u_desc_ctrl.field.pci_transaction = 0xe; /* memory read block */
+	u_desc_ctrl.field.int_en = int_en;
+	hw_desc->desc_ctrl = u_desc_ctrl.value;
+	hw_desc->upper_pci_src_addr = 0;
+	hw_desc->crc_addr = 0;
+}
+
+static inline void
+iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+{
+	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+	union {
+		u32 value;
+		struct iop3xx_aau_desc_ctrl field;
+	} u_desc_ctrl;
+
+	u_desc_ctrl.value = 0;
+	u_desc_ctrl.field.blk1_cmd_ctrl = 0x2; /* memory block fill */
+	u_desc_ctrl.field.dest_write_en = 1;
+	u_desc_ctrl.field.int_en = int_en;
+	hw_desc->desc_ctrl = u_desc_ctrl.value;
+}
+
+static inline u32
+iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, int int_en)
+{
+	int i, shift;
+	u32 edcr;
+	union {
+		u32 value;
+		struct iop3xx_aau_desc_ctrl field;
+	} u_desc_ctrl;
+
+	u_desc_ctrl.value = 0;
+	switch (src_cnt) {
+	case 25 ... 32:
+		u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+		edcr = 0;
+		shift = 1;
+		for (i = 24; i < src_cnt; i++) {
+			edcr |= (1 << shift);
+			shift += 3;
+		}
+		hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr;
+		src_cnt = 24;
+		/* fall through */
+	case 17 ... 24:
+		if (!u_desc_ctrl.field.blk_ctrl) {
+			hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+			u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+		}
+		edcr = 0;
+		shift = 1;
+		for (i = 16; i < src_cnt; i++) {
+			edcr |= (1 << shift);
+			shift += 3;
+		}
+		hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr;
+		src_cnt = 16;
+		/* fall through */
+	case 9 ... 16:
+		if (!u_desc_ctrl.field.blk_ctrl)
+			u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
+		edcr = 0;
+		shift = 1;
+		for (i = 8; i < src_cnt; i++) {
+			edcr |= (1 << shift);
+			shift += 3;
+		}
+		hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr;
+		src_cnt = 8;
+		/* fall through */
+	case 2 ... 8:
+		shift = 1;
+		for (i = 0; i < src_cnt; i++) {
+			u_desc_ctrl.value |= (1 << shift);
+			shift += 3;
+		}
+
+		if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
+			u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
+	}
+
+	u_desc_ctrl.field.dest_write_en = 1;
+	u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */
+	u_desc_ctrl.field.int_en = int_en;
+	hw_desc->desc_ctrl = u_desc_ctrl.value;
+
+	return u_desc_ctrl.value;
+}
+
+static inline void
+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+	iop3xx_desc_init_xor(desc->hw_desc, src_cnt, int_en);
+}
+
+/* return the number of operations */
+static inline int
+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+	int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+	struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
+	union {
+		u32 value;
+		struct iop3xx_aau_desc_ctrl field;
+	} u_desc_ctrl;
+	int i, j;
+
+	hw_desc = desc->hw_desc;
+
+	for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;
+		i += slots_per_op, j++) {
+		iter = iop_hw_desc_slot_idx(hw_desc, i);
+		u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, int_en);
+		u_desc_ctrl.field.dest_write_en = 0;
+		u_desc_ctrl.field.zero_result_en = 1;
+		u_desc_ctrl.field.int_en = int_en;
+		iter->desc_ctrl = u_desc_ctrl.value;
+
+		/* for the subsequent descriptors preserve the store queue
+		 * and chain them together
+		 */
+		if (i) {
+			prev_hw_desc =
+				iop_hw_desc_slot_idx(hw_desc, i - slots_per_op);
+			prev_hw_desc->next_desc =
+				(u32) (desc->async_tx.phys + (i << 5));
+		}
+	}
+
+	return j;
+}
+
+static inline void
+iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+	union {
+		u32 value;
+		struct iop3xx_aau_desc_ctrl field;
+	} u_desc_ctrl;
+
+	u_desc_ctrl.value = 0;
+	switch (src_cnt) {
+	case 25 ... 32:
+		u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+		hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+		/* fall through */
+	case 17 ... 24:
+		if (!u_desc_ctrl.field.blk_ctrl) {
+			hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+			u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+		}
+		hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0;
+		/* fall through */
+	case 9 ... 16:
+		if (!u_desc_ctrl.field.blk_ctrl)
+			u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
+		hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0;
+		/* fall through */
+	case 1 ... 8:
+		if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
+			u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
+	}
+
+	u_desc_ctrl.field.dest_write_en = 0;
+	u_desc_ctrl.field.int_en = int_en;
+	hw_desc->desc_ctrl = u_desc_ctrl.value;
+}
+
+static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan,
+					u32 byte_count)
+{
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		hw_desc.dma->byte_count = byte_count;
+		break;
+	case AAU_ID:
+		hw_desc.aau->byte_count = byte_count;
+		break;
+	default:
+		BUG();
+	}
+}
+
+static inline void
+iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
+			struct iop_adma_chan *chan)
+{
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		iop_desc_init_memcpy(desc, 1);
+		hw_desc.dma->byte_count = 0;
+		hw_desc.dma->dest_addr = 0;
+		hw_desc.dma->src_addr = 0;
+		break;
+	case AAU_ID:
+		iop_desc_init_null_xor(desc, 2, 1);
+		hw_desc.aau->byte_count = 0;
+		hw_desc.aau->dest_addr = 0;
+		hw_desc.aau->src[0] = 0;
+		hw_desc.aau->src[1] = 0;
+		break;
+	default:
+		BUG();
+	}
+}
+
+static inline void
+iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
+{
+	int slots_per_op = desc->slots_per_op;
+	struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+	int i = 0;
+
+	if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+		hw_desc->byte_count = len;
+	} else {
+		do {
+			iter = iop_hw_desc_slot_idx(hw_desc, i);
+			iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+			len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+			i += slots_per_op;
+		} while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
+
+		if (len) {
+			iter = iop_hw_desc_slot_idx(hw_desc, i);
+			iter->byte_count = len;
+		}
+	}
+}
+
+static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
+					struct iop_adma_chan *chan,
+					dma_addr_t addr)
+{
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		hw_desc.dma->dest_addr = addr;
+		break;
+	case AAU_ID:
+		hw_desc.aau->dest_addr = addr;
+		break;
+	default:
+		BUG();
+	}
+}
+
+static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
+					dma_addr_t addr)
+{
+	struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
+	hw_desc->src_addr = addr;
+}
+
+static inline void
+iop_desc_set_zero_sum_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
+				dma_addr_t addr)
+{
+
+	struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+	int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+	int i;
+
+	for (i = 0; (slot_cnt -= slots_per_op) >= 0;
+		i += slots_per_op, addr += IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+		iter = iop_hw_desc_slot_idx(hw_desc, i);
+		iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
+	}
+}
+
+static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
+					int src_idx, dma_addr_t addr)
+{
+
+	struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+	int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+	int i;
+
+	for (i = 0; (slot_cnt -= slots_per_op) >= 0;
+		i += slots_per_op, addr += IOP_ADMA_XOR_MAX_BYTE_COUNT) {
+		iter = iop_hw_desc_slot_idx(hw_desc, i);
+		iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
+	}
+}
+
+static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
+					u32 next_desc_addr)
+{
+	/* hw_desc->next_desc is the same location for all channels */
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+	BUG_ON(hw_desc.dma->next_desc);
+	hw_desc.dma->next_desc = next_desc_addr;
+}
+
+static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
+{
+	/* hw_desc->next_desc is the same location for all channels */
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+	return hw_desc.dma->next_desc;
+}
+
+static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
+{
+	/* hw_desc->next_desc is the same location for all channels */
+	union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+	hw_desc.dma->next_desc = 0;
+}
+
+static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
+						u32 val)
+{
+	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+	hw_desc->src[0] = val;
+}
+
+static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+{
+	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+	struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
+
+	BUG_ON(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
+	return desc_ctrl.zero_result_err;
+}
+
+static inline void iop_chan_append(struct iop_adma_chan *chan)
+{
+	u32 dma_chan_ctrl;
+	/* workaround dropped interrupts on 3xx */
+	mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));
+
+	dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+	dma_chan_ctrl |= 0x2;
+	__raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+{
+	if (!busy)
+		del_timer(&chan->cleanup_watchdog);
+}
+
+static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+{
+	return __raw_readl(DMA_CSR(chan));
+}
+
+static inline void iop_chan_disable(struct iop_adma_chan *chan)
+{
+	u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+	dma_chan_ctrl &= ~1;
+	__raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_chan_enable(struct iop_adma_chan *chan)
+{
+	u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+
+	dma_chan_ctrl |= 1;
+	__raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
+{
+	u32 status = __raw_readl(DMA_CSR(chan));
+	status &= (1 << 9);
+	__raw_writel(status, DMA_CSR(chan));
+}
+
+static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
+{
+	u32 status = __raw_readl(DMA_CSR(chan));
+	status &= (1 << 8);
+	__raw_writel(status, DMA_CSR(chan));
+}
+
+static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+{
+	u32 status = __raw_readl(DMA_CSR(chan));
+
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		status &= (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1);
+		break;
+	case AAU_ID:
+		status &= (1 << 5);
+		break;
+	default:
+		BUG();
+	}
+
+	__raw_writel(status, DMA_CSR(chan));
+}
+
+static inline int
+iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
+{
+	return 0;
+}
+
+static inline int
+iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
+{
+	return 0;
+}
+
+static inline int
+iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+	return 0;
+}
+
+static inline int
+iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+	return test_bit(5, &status);
+}
+
+static inline int
+iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		return test_bit(2, &status);
+	default:
+		return 0;
+	}
+}
+
+static inline int
+iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		return test_bit(3, &status);
+	default:
+		return 0;
+	}
+}
+
+static inline int
+iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
+{
+	switch (chan->device->id) {
+	case DMA0_ID:
+	case DMA1_ID:
+		return test_bit(1, &status);
+	default:
+		return 0;
+	}
+}
+#endif /* _ADMA_H */
diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
index 63feceb..81ca5d3 100644
--- a/include/asm-arm/hardware/iop3xx.h
+++ b/include/asm-arm/hardware/iop3xx.h
@@ -144,24 +144,9 @@
 #define IOP3XX_IAR		(volatile u32 *)IOP3XX_REG_ADDR(0x0380)
 
 /* DMA Controller  */
-#define IOP3XX_DMA0_CCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0400)
-#define IOP3XX_DMA0_CSR		(volatile u32 *)IOP3XX_REG_ADDR(0x0404)
-#define IOP3XX_DMA0_DAR		(volatile u32 *)IOP3XX_REG_ADDR(0x040c)
-#define IOP3XX_DMA0_NDAR	(volatile u32 *)IOP3XX_REG_ADDR(0x0410)
-#define IOP3XX_DMA0_PADR	(volatile u32 *)IOP3XX_REG_ADDR(0x0414)
-#define IOP3XX_DMA0_PUADR	(volatile u32 *)IOP3XX_REG_ADDR(0x0418)
-#define IOP3XX_DMA0_LADR	(volatile u32 *)IOP3XX_REG_ADDR(0x041c)
-#define IOP3XX_DMA0_BCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0420)
-#define IOP3XX_DMA0_DCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0424)
-#define IOP3XX_DMA1_CCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0440)
-#define IOP3XX_DMA1_CSR		(volatile u32 *)IOP3XX_REG_ADDR(0x0444)
-#define IOP3XX_DMA1_DAR		(volatile u32 *)IOP3XX_REG_ADDR(0x044c)
-#define IOP3XX_DMA1_NDAR	(volatile u32 *)IOP3XX_REG_ADDR(0x0450)
-#define IOP3XX_DMA1_PADR	(volatile u32 *)IOP3XX_REG_ADDR(0x0454)
-#define IOP3XX_DMA1_PUADR	(volatile u32 *)IOP3XX_REG_ADDR(0x0458)
-#define IOP3XX_DMA1_LADR	(volatile u32 *)IOP3XX_REG_ADDR(0x045c)
-#define IOP3XX_DMA1_BCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0460)
-#define IOP3XX_DMA1_DCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0464)
+#define IOP3XX_DMA_PHYS_BASE(chan) (IOP3XX_PERIPHERAL_PHYS_BASE + \
+					(0x400 + (chan << 6)))
+#define IOP3XX_DMA_UPPER_PA(chan)  (IOP3XX_DMA_PHYS_BASE(chan) + 0x27)
 
 /* Peripheral bus interface  */
 #define IOP3XX_PBCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0680)
@@ -210,48 +195,8 @@
 #define IOP_TMR_RATIO_1_1  0x00
 
 /* Application accelerator unit  */
-#define IOP3XX_AAU_ACR		(volatile u32 *)IOP3XX_REG_ADDR(0x0800)
-#define IOP3XX_AAU_ASR		(volatile u32 *)IOP3XX_REG_ADDR(0x0804)
-#define IOP3XX_AAU_ADAR		(volatile u32 *)IOP3XX_REG_ADDR(0x0808)
-#define IOP3XX_AAU_ANDAR	(volatile u32 *)IOP3XX_REG_ADDR(0x080c)
-#define IOP3XX_AAU_SAR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0810)
-#define IOP3XX_AAU_SAR2		(volatile u32 *)IOP3XX_REG_ADDR(0x0814)
-#define IOP3XX_AAU_SAR3		(volatile u32 *)IOP3XX_REG_ADDR(0x0818)
-#define IOP3XX_AAU_SAR4		(volatile u32 *)IOP3XX_REG_ADDR(0x081c)
-#define IOP3XX_AAU_DAR		(volatile u32 *)IOP3XX_REG_ADDR(0x0820)
-#define IOP3XX_AAU_ABCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0824)
-#define IOP3XX_AAU_ADCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0828)
-#define IOP3XX_AAU_SAR5		(volatile u32 *)IOP3XX_REG_ADDR(0x082c)
-#define IOP3XX_AAU_SAR6		(volatile u32 *)IOP3XX_REG_ADDR(0x0830)
-#define IOP3XX_AAU_SAR7		(volatile u32 *)IOP3XX_REG_ADDR(0x0834)
-#define IOP3XX_AAU_SAR8		(volatile u32 *)IOP3XX_REG_ADDR(0x0838)
-#define IOP3XX_AAU_EDCR0	(volatile u32 *)IOP3XX_REG_ADDR(0x083c)
-#define IOP3XX_AAU_SAR9		(volatile u32 *)IOP3XX_REG_ADDR(0x0840)
-#define IOP3XX_AAU_SAR10	(volatile u32 *)IOP3XX_REG_ADDR(0x0844)
-#define IOP3XX_AAU_SAR11	(volatile u32 *)IOP3XX_REG_ADDR(0x0848)
-#define IOP3XX_AAU_SAR12	(volatile u32 *)IOP3XX_REG_ADDR(0x084c)
-#define IOP3XX_AAU_SAR13	(volatile u32 *)IOP3XX_REG_ADDR(0x0850)
-#define IOP3XX_AAU_SAR14	(volatile u32 *)IOP3XX_REG_ADDR(0x0854)
-#define IOP3XX_AAU_SAR15	(volatile u32 *)IOP3XX_REG_ADDR(0x0858)
-#define IOP3XX_AAU_SAR16	(volatile u32 *)IOP3XX_REG_ADDR(0x085c)
-#define IOP3XX_AAU_EDCR1	(volatile u32 *)IOP3XX_REG_ADDR(0x0860)
-#define IOP3XX_AAU_SAR17	(volatile u32 *)IOP3XX_REG_ADDR(0x0864)
-#define IOP3XX_AAU_SAR18	(volatile u32 *)IOP3XX_REG_ADDR(0x0868)
-#define IOP3XX_AAU_SAR19	(volatile u32 *)IOP3XX_REG_ADDR(0x086c)
-#define IOP3XX_AAU_SAR20	(volatile u32 *)IOP3XX_REG_ADDR(0x0870)
-#define IOP3XX_AAU_SAR21	(volatile u32 *)IOP3XX_REG_ADDR(0x0874)
-#define IOP3XX_AAU_SAR22	(volatile u32 *)IOP3XX_REG_ADDR(0x0878)
-#define IOP3XX_AAU_SAR23	(volatile u32 *)IOP3XX_REG_ADDR(0x087c)
-#define IOP3XX_AAU_SAR24	(volatile u32 *)IOP3XX_REG_ADDR(0x0880)
-#define IOP3XX_AAU_EDCR2	(volatile u32 *)IOP3XX_REG_ADDR(0x0884)
-#define IOP3XX_AAU_SAR25	(volatile u32 *)IOP3XX_REG_ADDR(0x0888)
-#define IOP3XX_AAU_SAR26	(volatile u32 *)IOP3XX_REG_ADDR(0x088c)
-#define IOP3XX_AAU_SAR27	(volatile u32 *)IOP3XX_REG_ADDR(0x0890)
-#define IOP3XX_AAU_SAR28	(volatile u32 *)IOP3XX_REG_ADDR(0x0894)
-#define IOP3XX_AAU_SAR29	(volatile u32 *)IOP3XX_REG_ADDR(0x0898)
-#define IOP3XX_AAU_SAR30	(volatile u32 *)IOP3XX_REG_ADDR(0x089c)
-#define IOP3XX_AAU_SAR31	(volatile u32 *)IOP3XX_REG_ADDR(0x08a0)
-#define IOP3XX_AAU_SAR32	(volatile u32 *)IOP3XX_REG_ADDR(0x08a4)
+#define IOP3XX_AAU_PHYS_BASE (IOP3XX_PERIPHERAL_PHYS_BASE + 0x800)
+#define IOP3XX_AAU_UPPER_PA (IOP3XX_AAU_PHYS_BASE + 0xa7)
 
 /* I2C bus interface unit  */
 #define IOP3XX_ICR0		(volatile u32 *)IOP3XX_REG_ADDR(0x1680)
@@ -329,6 +274,9 @@
 	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (val));
 }
 
+extern struct platform_device iop3xx_dma_0_channel;
+extern struct platform_device iop3xx_dma_1_channel;
+extern struct platform_device iop3xx_aau_channel;
 extern struct platform_device iop3xx_i2c0_device;
 extern struct platform_device iop3xx_i2c1_device;
 
diff --git a/include/asm-arm/hardware/iop_adma.h b/include/asm-arm/hardware/iop_adma.h
new file mode 100644
index 0000000..ca8e71f
--- /dev/null
+++ b/include/asm-arm/hardware/iop_adma.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef IOP_ADMA_H
+#define IOP_ADMA_H
+#include <linux/types.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+
+#define IOP_ADMA_SLOT_SIZE 32
+#define IOP_ADMA_THRESHOLD 4
+
+/**
+ * struct iop_adma_device - internal representation of an ADMA device
+ * @pdev: Platform device
+ * @id: HW ADMA Device selector
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
+ * @common: embedded struct dma_device
+ */
+struct iop_adma_device {
+	struct platform_device *pdev;
+	int id;
+	dma_addr_t dma_desc_pool;
+	void *dma_desc_pool_virt;
+	struct dma_device common;
+};
+
+/**
+ * struct iop_adma_chan - internal representation of an ADMA device
+ * @pending: allows batching of hardware operations
+ * @completed_cookie: identifier for the most recently completed operation
+ * @lock: serializes enqueue/dequeue operations to the slot pool
+ * @mmr_base: memory mapped register base
+ * @chain: device chain view of the descriptors
+ * @device: parent device
+ * @common: common dmaengine channel object members
+ * @last_used: place holder for allocation to continue from where it left off
+ * @all_slots: complete domain of slots usable by the channel
+ * @cleanup_watchdog: workaround missed interrupts on iop3xx
+ * @slots_allocated: records the actual size of the descriptor slot pool
+ * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs
+ */
+struct iop_adma_chan {
+	int pending;
+	dma_cookie_t completed_cookie;
+	spinlock_t lock; /* protects the descriptor slot pool */
+	void __iomem *mmr_base;
+	struct list_head chain;
+	struct iop_adma_device *device;
+	struct dma_chan common;
+	struct iop_adma_desc_slot *last_used;
+	struct list_head all_slots;
+	struct timer_list cleanup_watchdog;
+	int slots_allocated;
+	struct tasklet_struct irq_tasklet;
+};
+
+/**
+ * struct iop_adma_desc_slot - IOP-ADMA software descriptor
+ * @slot_node: node on the iop_adma_chan.all_slots list
+ * @chain_node: node on the op_adma_chan.chain list
+ * @hw_desc: virtual address of the hardware descriptor chain
+ * @phys: hardware address of the hardware descriptor chain
+ * @group_head: first operation in a transaction
+ * @slot_cnt: total slots used in an transaction (group of operations)
+ * @slots_per_op: number of slots per operation
+ * @idx: pool index
+ * @unmap_src_cnt: number of xor sources
+ * @unmap_len: transaction bytecount
+ * @async_tx: support for the async_tx api
+ * @group_list: list of slots that make up a multi-descriptor transaction
+ *	for example transfer lengths larger than the supported hw max
+ * @xor_check_result: result of zero sum
+ * @crc32_result: result crc calculation
+ */
+struct iop_adma_desc_slot {
+	struct list_head slot_node;
+	struct list_head chain_node;
+	void *hw_desc;
+	struct iop_adma_desc_slot *group_head;
+	u16 slot_cnt;
+	u16 slots_per_op;
+	u16 idx;
+	u16 unmap_src_cnt;
+	size_t unmap_len;
+	struct dma_async_tx_descriptor async_tx;
+	union {
+		u32 *xor_check_result;
+		u32 *crc32_result;
+	};
+};
+
+struct iop_adma_platform_data {
+	int hw_id;
+	dma_cap_mask_t cap_mask;
+	size_t pool_size;
+};
+
+#define to_iop_sw_desc(addr_hw_desc) \
+	container_of(addr_hw_desc, struct iop_adma_desc_slot, hw_desc)
+#define iop_hw_desc_slot_idx(hw_desc, idx) \
+	( (void *) (((unsigned long) hw_desc) + ((idx) << 5)) )
+#endif
diff --git a/include/asm-arm/hwcap.h b/include/asm-arm/hwcap.h
new file mode 100644
index 0000000..01a1391
--- /dev/null
+++ b/include/asm-arm/hwcap.h
@@ -0,0 +1,28 @@
+#ifndef __ASMARM_HWCAP_H
+#define __ASMARM_HWCAP_H
+
+/*
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
+ */
+#define HWCAP_SWP	1
+#define HWCAP_HALF	2
+#define HWCAP_THUMB	4
+#define HWCAP_26BIT	8	/* Play it safe */
+#define HWCAP_FAST_MULT	16
+#define HWCAP_FPA	32
+#define HWCAP_VFP	64
+#define HWCAP_EDSP	128
+#define HWCAP_JAVA	256
+#define HWCAP_IWMMXT	512
+#define HWCAP_CRUNCH	1024
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP	(elf_hwcap)
+extern unsigned int elf_hwcap;
+#endif
+
+#endif
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 8261ff9..1d3caa4 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -259,9 +259,11 @@
 #define BIOVEC_MERGEABLE(vec1, vec2)	\
 	((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
 
+#ifdef CONFIG_MMU
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
 extern int valid_phys_addr_range(unsigned long addr, size_t size);
 extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+#endif
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
diff --git a/include/asm-arm/ioctls.h b/include/asm-arm/ioctls.h
index bb9a7aa..a91d8a1 100644
--- a/include/asm-arm/ioctls.h
+++ b/include/asm-arm/ioctls.h
@@ -46,6 +46,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-arm/linkage.h b/include/asm-arm/linkage.h
index dbe4b4e..5a25632 100644
--- a/include/asm-arm/linkage.h
+++ b/include/asm-arm/linkage.h
@@ -4,4 +4,8 @@
 #define __ALIGN .align 0
 #define __ALIGN_STR ".align 0"
 
+#define ENDPROC(name) \
+  .type name, %function; \
+  END(name)
+
 #endif
diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h
index fd2f9bf..c59fad1 100644
--- a/include/asm-arm/mach/arch.h
+++ b/include/asm-arm/mach/arch.h
@@ -49,7 +49,7 @@
  */
 #define MACHINE_START(_type,_name)			\
 static const struct machine_desc __mach_desc_##_type	\
- __attribute_used__					\
+ __used							\
  __attribute__((__section__(".arch.info.init"))) = {	\
 	.nr		= MACH_TYPE_##_type,		\
 	.name		= _name,
diff --git a/include/asm-arm/mmu.h b/include/asm-arm/mmu.h
index fe2a23b..53099d4 100644
--- a/include/asm-arm/mmu.h
+++ b/include/asm-arm/mmu.h
@@ -4,13 +4,13 @@
 #ifdef CONFIG_MMU
 
 typedef struct {
-#if __LINUX_ARM_ARCH__ >= 6
+#ifdef CONFIG_CPU_HAS_ASID
 	unsigned int id;
 #endif
 	unsigned int kvm_seq;
 } mm_context_t;
 
-#if __LINUX_ARM_ARCH__ >= 6
+#ifdef CONFIG_CPU_HAS_ASID
 #define ASID(mm)	((mm)->context.id & 255)
 #else
 #define ASID(mm)	(0)
diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h
index 4981ad4..6913d02 100644
--- a/include/asm-arm/mmu_context.h
+++ b/include/asm-arm/mmu_context.h
@@ -20,7 +20,7 @@
 
 void __check_kvm_seq(struct mm_struct *mm);
 
-#if __LINUX_ARM_ARCH__ >= 6
+#ifdef CONFIG_CPU_HAS_ASID
 
 /*
  * On ARMv6, we have the following structure in the Context ID:
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index f21abd4..ed3f898 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -26,11 +26,6 @@
 #define PCI_DMA_BUS_IS_PHYS     (0)
 
 /*
- * We don't support DAC DMA cycles.
- */
-#define pci_dac_dma_supported(pci_dev, mask)	(0)
-
-/*
  * Whether pci_unmap_{single,page} is a nop depends upon the
  * configuration.
  */
@@ -76,10 +71,6 @@
 	return root;
 }
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
  
 #endif
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 21dec9f..d2e8171 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -83,14 +83,14 @@
  * means that a write to a clean page will cause a permission fault, and
  * the Linux MM layer will mark the page dirty via handle_pte_fault().
  * For the hardware to notice the permission change, the TLB entry must
- * be flushed, and ptep_establish() does that for us.
+ * be flushed, and ptep_set_access_flags() does that for us.
  *
  * The "accessed" or "young" bit is emulated by a similar method; we only
  * allow accesses to the page if the "young" bit is set.  Accesses to the
  * page will cause a fault, and handle_pte_fault() will set the young bit
  * for us as long as the page is marked present in the corresponding Linux
- * PTE entry.  Again, ptep_establish() will ensure that the TLB is up to
- * date.
+ * PTE entry.  Again, ptep_set_access_flags() will ensure that the TLB is
+ * up to date.
  *
  * However, when the "young" bit is cleared, we deny access to the page
  * by clearing the hardware PTE.  Currently Linux does not flush the TLB
@@ -257,9 +257,7 @@
  * Undefined behaviour if not..
  */
 #define pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT)
-#define pte_read(pte)		(pte_val(pte) & L_PTE_USER)
 #define pte_write(pte)		(pte_val(pte) & L_PTE_WRITE)
-#define pte_exec(pte)		(pte_val(pte) & L_PTE_EXEC)
 #define pte_dirty(pte)		(pte_val(pte) & L_PTE_DIRTY)
 #define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG)
 
@@ -275,12 +273,8 @@
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
-/*PTE_BIT_FUNC(rdprotect, &= ~L_PTE_USER);*/
-/*PTE_BIT_FUNC(mkread,    |= L_PTE_USER);*/
 PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE);
 PTE_BIT_FUNC(mkwrite,   |= L_PTE_WRITE);
-PTE_BIT_FUNC(exprotect, &= ~L_PTE_EXEC);
-PTE_BIT_FUNC(mkexec,    |= L_PTE_EXEC);
 PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
 PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
 PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
diff --git a/include/asm-arm/plat-s3c24xx/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
index dddf485..f9d6f03 100644
--- a/include/asm-arm/plat-s3c24xx/devs.h
+++ b/include/asm-arm/plat-s3c24xx/devs.h
@@ -29,6 +29,7 @@
 extern struct platform_device s3c_device_rtc;
 extern struct platform_device s3c_device_adc;
 extern struct platform_device s3c_device_sdi;
+extern struct platform_device s3c_device_hsmmc;
 
 extern struct platform_device s3c_device_spi0;
 extern struct platform_device s3c_device_spi1;
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index 2d0dad8..7aaa206 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -10,6 +10,8 @@
 #ifndef __ASM_ARM_PTRACE_H
 #define __ASM_ARM_PTRACE_H
 
+#include <asm/hwcap.h>
+
 #define PTRACE_GETREGS		12
 #define PTRACE_SETREGS		13
 #define PTRACE_GETFPREGS	14
@@ -45,6 +47,7 @@
 #define PSR_T_BIT	0x00000020
 #define PSR_F_BIT	0x00000040
 #define PSR_I_BIT	0x00000080
+#define PSR_A_BIT	0x00000100
 #define PSR_J_BIT	0x01000000
 #define PSR_Q_BIT	0x08000000
 #define PSR_V_BIT	0x10000000
@@ -103,6 +106,10 @@
 #define thumb_mode(regs) (0)
 #endif
 
+#define isa_mode(regs) \
+	((((regs)->ARM_cpsr & PSR_J_BIT) >> 23) | \
+	 (((regs)->ARM_cpsr & PSR_T_BIT) >> 5))
+
 #define processor_mode(regs) \
 	((regs)->ARM_cpsr & MODE_MASK)
 
@@ -112,22 +119,22 @@
 #define fast_interrupts_enabled(regs) \
 	(!((regs)->ARM_cpsr & PSR_F_BIT))
 
-#define condition_codes(regs) \
-	((regs)->ARM_cpsr & (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT))
-	
 /* Are the current registers suitable for user mode?
  * (used to maintain security in signal handlers)
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
-	if (user_mode(regs) &&
-	    (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0)
+	if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) {
+		regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
 		return 1;
+	}
 
 	/*
 	 * Force CPSR to something logical...
 	 */
-	regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT;
+	regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT;
+	if (!(elf_hwcap & HWCAP_26BIT))
+		regs->ARM_cpsr |= USR_MODE;
 
 	return 0;
 }
diff --git a/include/asm-arm/setup.h b/include/asm-arm/setup.h
index e540739..7bbf105 100644
--- a/include/asm-arm/setup.h
+++ b/include/asm-arm/setup.h
@@ -185,7 +185,7 @@
 
 #ifdef __KERNEL__
 
-#define __tag __attribute_used__ __attribute__((__section__(".taglist.init")))
+#define __tag __used __attribute__((__section__(".taglist.init")))
 #define __tagtable(tag, fn) \
 static struct tagtable __tagtable_##fn __tag = { tag, fn }
 
@@ -218,7 +218,7 @@
 };
 
 #define __early_param(name,fn)					\
-static struct early_params __early_##fn __attribute_used__	\
+static struct early_params __early_##fn __used			\
 __attribute__((__section__(".early_param.init"))) = { name, fn }
 
 #endif  /*  __KERNEL__  */
diff --git a/include/asm-arm/termbits.h b/include/asm-arm/termbits.h
index a3f4fe1..f784d11 100644
--- a/include/asm-arm/termbits.h
+++ b/include/asm-arm/termbits.h
@@ -15,6 +15,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
@@ -128,6 +139,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -143,10 +155,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR    010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define IBSHIFT	   16
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-arm/termios.h b/include/asm-arm/termios.h
index 329c324..293e3f1 100644
--- a/include/asm-arm/termios.h
+++ b/include/asm-arm/termios.h
@@ -82,8 +82,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index 08c6991..71be4fd 100644
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -138,12 +138,27 @@
 # define v6wbi_always_flags	(-1UL)
 #endif
 
+#ifdef CONFIG_CPU_TLB_V7
+# define v7wbi_possible_flags	v6wbi_tlb_flags
+# define v7wbi_always_flags	v6wbi_tlb_flags
+# ifdef _TLB
+#  define MULTI_TLB 1
+# else
+#  define _TLB v7wbi
+# endif
+#else
+# define v7wbi_possible_flags	0
+# define v7wbi_always_flags	(-1UL)
+#endif
+
 #ifndef _TLB
 #error Unknown TLB model
 #endif
 
 #ifndef __ASSEMBLY__
 
+#include <linux/sched.h>
+
 struct cpu_tlb_fns {
 	void (*flush_user_range)(unsigned long, unsigned long, struct vm_area_struct *);
 	void (*flush_kern_range)(unsigned long, unsigned long);
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index c025ab4..bfdbebe 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -367,12 +367,17 @@
 #define __NR_get_robust_list		(__NR_SYSCALL_BASE+339)
 #define __NR_splice			(__NR_SYSCALL_BASE+340)
 #define __NR_arm_sync_file_range	(__NR_SYSCALL_BASE+341)
+#define __NR_sync_file_range2		__NR_arm_sync_file_range
 #define __NR_tee			(__NR_SYSCALL_BASE+342)
 #define __NR_vmsplice			(__NR_SYSCALL_BASE+343)
 #define __NR_move_pages			(__NR_SYSCALL_BASE+344)
 #define __NR_getcpu			(__NR_SYSCALL_BASE+345)
 					/* 346 for epoll_pwait */
 #define __NR_kexec_load			(__NR_SYSCALL_BASE+347)
+#define __NR_utimensat			(__NR_SYSCALL_BASE+348)
+#define __NR_signalfd			(__NR_SYSCALL_BASE+349)
+#define __NR_timerfd			(__NR_SYSCALL_BASE+350)
+#define __NR_eventfd			(__NR_SYSCALL_BASE+351)
 
 /*
  * The following SWIs are ARM private.
@@ -433,5 +438,11 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+/*
+ * Unimplemented (or alternatively implemented) syscalls
+ */
+#define __IGNORE_sync_file_range	1
+#define __IGNORE_fadvise64_64		1
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_ARM_UNISTD_H */
diff --git a/include/asm-arm26/dma-mapping.h b/include/asm-arm26/dma-mapping.h
deleted file mode 100644
index a95eae0..0000000
--- a/include/asm-arm26/dma-mapping.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include <asm-generic/dma-mapping-broken.h>
-
diff --git a/include/asm-arm26/fb.h b/include/asm-arm26/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-arm26/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-arm26/ioctls.h b/include/asm-arm26/ioctls.h
index ba9c7d8..8a32962 100644
--- a/include/asm-arm26/ioctls.h
+++ b/include/asm-arm26/ioctls.h
@@ -47,6 +47,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index 2b20e9f..55a1a69 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -218,9 +218,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-#define pte_read(pte)                   (!(pte_val(pte) & _PAGE_NOT_USER))
 #define pte_write(pte)                  (!(pte_val(pte) & _PAGE_READONLY))
-#define pte_exec(pte)                   (!(pte_val(pte) & _PAGE_NOT_USER))
 #define pte_dirty(pte)                  (!(pte_val(pte) & _PAGE_CLEAN))
 #define pte_young(pte)                  (!(pte_val(pte) & _PAGE_OLD))
 //ONLY when !pte_present() I think. nicked from arm32 (FIXME!)
@@ -231,8 +229,6 @@
 
 PTE_BIT_FUNC(wrprotect, |=  _PAGE_READONLY);
 PTE_BIT_FUNC(mkwrite,   &= ~_PAGE_READONLY);
-PTE_BIT_FUNC(exprotect, |=  _PAGE_NOT_USER);
-PTE_BIT_FUNC(mkexec,    &= ~_PAGE_NOT_USER);
 PTE_BIT_FUNC(mkclean,   |=  _PAGE_CLEAN);
 PTE_BIT_FUNC(mkdirty,   &= ~_PAGE_CLEAN);
 PTE_BIT_FUNC(mkold,     |=  _PAGE_OLD);
diff --git a/include/asm-arm26/setup.h b/include/asm-arm26/setup.h
index 10fd07c..e825623 100644
--- a/include/asm-arm26/setup.h
+++ b/include/asm-arm26/setup.h
@@ -173,7 +173,7 @@
 	int (*parse)(const struct tag *);
 };
 
-#define __tag __attribute_used__ __attribute__((__section__(".taglist")))
+#define __tag __used __attribute__((__section__(".taglist")))
 #define __tagtable(tag, fn) \
 static struct tagtable __tagtable_##fn __tag = { tag, fn }
 
diff --git a/include/asm-arm26/termbits.h b/include/asm-arm26/termbits.h
index a3f4fe1..48d2f5c 100644
--- a/include/asm-arm26/termbits.h
+++ b/include/asm-arm26/termbits.h
@@ -15,7 +15,7 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
-struct ktermios {
+struct termios2 {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
 	tcflag_t c_cflag;		/* control mode flags */
@@ -26,6 +26,16 @@
 	speed_t c_ospeed;		/* output speed */
 };
 
+struct ktermios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
 
 /* c_cc characters */
 #define VINTR 0
@@ -128,6 +138,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define   BOTHER  0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -143,10 +154,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR    010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define IBSHIFT	  16		/* Shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-arm26/termios.h b/include/asm-arm26/termios.h
index 329c324..293e3f1 100644
--- a/include/asm-arm26/termios.h
+++ b/include/asm-arm26/termios.h
@@ -82,8 +82,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index 9fd2e32..9744804 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -21,6 +21,7 @@
 struct platform_device *at32_add_device_usart(unsigned int id);
 
 struct eth_platform_data {
+	u32	phy_mask;
 	u8	is_rmii;
 };
 struct platform_device *
diff --git a/include/asm-avr32/arch-at32ap/gpio.h b/include/asm-avr32/arch-at32ap/gpio.h
index 80a21aa..af7f953 100644
--- a/include/asm-avr32/arch-at32ap/gpio.h
+++ b/include/asm-avr32/arch-at32ap/gpio.h
@@ -14,6 +14,8 @@
 int gpio_get_value(unsigned int gpio);
 void gpio_set_value(unsigned int gpio, int value);
 
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
 static inline int gpio_to_irq(unsigned int gpio)
 {
 	return gpio + GPIO_IRQ_BASE;
diff --git a/include/asm-avr32/cache.h b/include/asm-avr32/cache.h
index dabb955..d3cf35a 100644
--- a/include/asm-avr32/cache.h
+++ b/include/asm-avr32/cache.h
@@ -4,6 +4,15 @@
 #define L1_CACHE_SHIFT 5
 #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
 
+/*
+ * Memory returned by kmalloc() may be used for DMA, so we must make
+ * sure that all such allocations are cache aligned. Otherwise,
+ * unrelated code may cause parts of the buffer to be read into the
+ * cache before the transfer is done, causing old data to be seen by
+ * the CPU.
+ */
+#define ARCH_KMALLOC_MINALIGN	L1_CACHE_BYTES
+
 #ifndef __ASSEMBLER__
 struct cache_info {
 	unsigned int ways;
diff --git a/include/asm-avr32/fb.h b/include/asm-avr32/fb.h
new file mode 100644
index 0000000..41baf84
--- /dev/null
+++ b/include/asm-avr32/fb.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
+				      & ~_PAGE_CACHABLE)
+				     | (_PAGE_BUFFER | _PAGE_DIRTY));
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-avr32/pgtable.h b/include/asm-avr32/pgtable.h
index f6cc2b0..c07bdd1 100644
--- a/include/asm-avr32/pgtable.h
+++ b/include/asm-avr32/pgtable.h
@@ -201,18 +201,10 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_USER;
-}
 static inline int pte_write(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_RW;
 }
-static inline int pte_exec(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_EXECUTE;
-}
 static inline int pte_dirty(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_DIRTY;
@@ -231,21 +223,11 @@
 }
 
 /* Mutator functions for PTE bits */
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER));
-	return pte;
-}
 static inline pte_t pte_wrprotect(pte_t pte)
 {
 	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW));
 	return pte;
 }
-static inline pte_t pte_exprotect(pte_t pte)
-{
-	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE));
-	return pte;
-}
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY));
@@ -256,21 +238,11 @@
 	set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED));
 	return pte;
 }
-static inline pte_t pte_mkread(pte_t pte)
-{
-	set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER));
-	return pte;
-}
 static inline pte_t pte_mkwrite(pte_t pte)
 {
 	set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW));
 	return pte;
 }
-static inline pte_t pte_mkexec(pte_t pte)
-{
-	set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE));
-	return pte;
-}
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY));
diff --git a/include/asm-avr32/termbits.h b/include/asm-avr32/termbits.h
index c215fafda..db2daab 100644
--- a/include/asm-avr32/termbits.h
+++ b/include/asm-avr32/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-blackfin/Kbuild b/include/asm-blackfin/Kbuild
index c68e168..71f8fe7 100644
--- a/include/asm-blackfin/Kbuild
+++ b/include/asm-blackfin/Kbuild
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+header-y += fixed_code.h
diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h
index e37f816..c4d6cbb 100644
--- a/include/asm-blackfin/bfin-global.h
+++ b/include/asm-blackfin/bfin-global.h
@@ -67,6 +67,18 @@
 extern asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
 extern void bfin_gpio_interrupt_setup(int irq, int irq_pfx, int type);
 
+extern asmlinkage void finish_atomic_sections (struct pt_regs *regs);
+extern char fixed_code_start;
+extern char fixed_code_end;
+extern int atomic_xchg32(void);
+extern int atomic_cas32(void);
+extern int atomic_add32(void);
+extern int atomic_sub32(void);
+extern int atomic_ior32(void);
+extern int atomic_and32(void);
+extern int atomic_xor32(void);
+extern void sigreturn_stub(void);
+
 extern void *l1_data_A_sram_alloc(size_t);
 extern void *l1_data_B_sram_alloc(size_t);
 extern void *l1_inst_sram_alloc(size_t);
@@ -104,6 +116,7 @@
 
 extern unsigned long table_start, table_end;
 
+extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
 extern struct file_operations dpmc_fops;
 extern char _start;
 extern unsigned long _ramstart, _ramend, _rambase;
diff --git a/include/asm-blackfin/blackfin.h b/include/asm-blackfin/blackfin.h
index 14e58de..25b934b 100644
--- a/include/asm-blackfin/blackfin.h
+++ b/include/asm-blackfin/blackfin.h
@@ -6,7 +6,11 @@
 #ifndef _BLACKFIN_H_
 #define _BLACKFIN_H_
 
-#include <asm/macros.h>
+#define LO(con32) ((con32) & 0xFFFF)
+#define lo(con32) ((con32) & 0xFFFF)
+#define HI(con32) (((con32) >> 16) & 0xFFFF)
+#define hi(con32) (((con32) >> 16) & 0xFFFF)
+
 #include <asm/mach/blackfin.h>
 #include <asm/bfin-global.h>
 
@@ -35,7 +39,9 @@
 #elif !defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
 static inline void SSYNC (void)
 {
-	__builtin_bfin_ssync();
+	__asm__ __volatile__ ("nop; nop; nop;\n\t"
+			"ssync;\n\t"
+			::);
 }
 #elif !defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
 static inline void SSYNC (void)
@@ -67,7 +73,9 @@
 #elif !defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
 static inline void CSYNC (void)
 {
-	__builtin_bfin_csync();
+	__asm__ __volatile__ ("nop; nop; nop;\n\t"
+			"ssync;\n\t"
+			::);
 }
 #elif !defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
 static inline void CSYNC (void)
@@ -76,6 +84,31 @@
 }
 #endif
 
+#else  /* __ASSEMBLY__ */
+
+/* SSYNC & CSYNC implementations for assembly files */
+
+#define ssync(x) SSYNC(x)
+#define csync(x) CSYNC(x)
+
+#if defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
+#define SSYNC(scratch) cli scratch; nop; nop; SSYNC; sti scratch;
+#define CSYNC(scratch) cli scratch; nop; nop; CSYNC; sti scratch;
+
+#elif defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
+#define SSYNC(scratch) cli scratch; nop; nop; SSYNC; sti scratch;
+#define CSYNC(scratch) cli scratch; nop; nop; CSYNC; sti scratch;
+
+#elif !defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
+#define SSYNC(scratch) nop; nop; nop; SSYNC;
+#define CSYNC(scratch) nop; nop; nop; CSYNC;
+
+#elif !defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
+#define SSYNC(scratch) SSYNC;
+#define CSYNC(scratch) CSYNC;
+
+#endif /* ANOMALY_05000312 & ANOMALY_05000244 handling */
+
 #endif /* __ASSEMBLY__ */
 
 #endif				/* _BLACKFIN_H_ */
diff --git a/include/asm-blackfin/cplbinit.h b/include/asm-blackfin/cplbinit.h
index 3bad2d1..bec6ecd 100644
--- a/include/asm-blackfin/cplbinit.h
+++ b/include/asm-blackfin/cplbinit.h
@@ -57,8 +57,8 @@
 	u16 size;
 };
 
-u_long icplb_table[MAX_CPLBS+1];
-u_long dcplb_table[MAX_CPLBS+1];
+extern u_long icplb_table[MAX_CPLBS+1];
+extern u_long dcplb_table[MAX_CPLBS+1];
 
 /* Till here we are discussing about the static memory management model.
  * However, the operating envoronments commonly define more CPLB
@@ -70,134 +70,27 @@
  */
 
 #ifdef CONFIG_CPLB_SWITCH_TAB_L1
-u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
-u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
+extern u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
+extern u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
 
 #ifdef CONFIG_CPLB_INFO
-u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
-u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
+extern u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
+extern u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
 #endif /* CONFIG_CPLB_INFO */
 
 #else
 
-u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
-u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
+extern u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
+extern u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
 
 #ifdef CONFIG_CPLB_INFO
-u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
-u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
+extern u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
+extern u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
 #endif /* CONFIG_CPLB_INFO */
 
 #endif /*CONFIG_CPLB_SWITCH_TAB_L1*/
 
-struct s_cplb {
-	struct cplb_tab init_i;
-	struct cplb_tab init_d;
-	struct cplb_tab switch_i;
-	struct cplb_tab switch_d;
-};
+extern unsigned long reserved_mem_dcache_on;
+extern unsigned long reserved_mem_icache_on;
 
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-static struct cplb_desc cplb_data[] = {
-	{
-		.start = 0,
-		.end = SIZE_4K,
-		.psize = SIZE_4K,
-		.attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
-		.i_conf = SDRAM_OOPS,
-		.d_conf = SDRAM_OOPS,
-#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
-		.valid = 1,
-#else
-		.valid = 0,
-#endif
-		.name = "ZERO Pointer Saveguard",
-	},
-	{
-		.start = L1_CODE_START,
-		.end = L1_CODE_START + L1_CODE_LENGTH,
-		.psize = SIZE_4M,
-		.attr = INITIAL_T | SWITCH_T | I_CPLB,
-		.i_conf = L1_IMEMORY,
-		.d_conf = 0,
-		.valid = 1,
-		.name = "L1 I-Memory",
-	},
-	{
-		.start = L1_DATA_A_START,
-		.end = L1_DATA_B_START + L1_DATA_B_LENGTH,
-		.psize = SIZE_4M,
-		.attr = INITIAL_T | SWITCH_T | D_CPLB,
-		.i_conf = 0,
-		.d_conf = L1_DMEMORY,
-#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
-		.valid = 1,
-#else
-		.valid = 0,
-#endif
-		.name = "L1 D-Memory",
-	},
-	{
-		.start = 0,
-		.end = 0,  /* dynamic */
-		.psize = 0,
-		.attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
-		.i_conf =  SDRAM_IGENERIC,
-		.d_conf =  SDRAM_DGENERIC,
-		.valid = 1,
-		.name = "SDRAM Kernel",
-	},
-	{
-		.start = 0, /* dynamic */
-		.end = 0, /* dynamic */
-		.psize = 0,
-		.attr = INITIAL_T | SWITCH_T | D_CPLB,
-		.i_conf =  SDRAM_IGENERIC,
-		.d_conf =  SDRAM_DNON_CHBL,
-		.valid = 1,
-		.name = "SDRAM RAM MTD",
-	},
-	{
-		.start = 0, /* dynamic */
-		.end = 0,   /* dynamic */
-		.psize = SIZE_1M,
-		.attr = INITIAL_T | SWITCH_T | D_CPLB,
-		.d_conf = SDRAM_DNON_CHBL,
-		.valid = 1,//(DMA_UNCACHED_REGION > 0),
-		.name = "SDRAM Uncached DMA ZONE",
-	},
-	{
-		.start = 0, /* dynamic */
-		.end = 0, /* dynamic */
-		.psize = 0,
-		.attr = SWITCH_T | D_CPLB,
-		.i_conf = 0, /* dynamic */
-		.d_conf = 0, /* dynamic */
-		.valid = 1,
-		.name = "SDRAM Reserved Memory",
-	},
-	{
-		.start = ASYNC_BANK0_BASE,
-		.end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
-		.psize = 0,
-		.attr = SWITCH_T | D_CPLB,
-		.d_conf = SDRAM_EBIU,
-		.valid = 1,
-		.name = "ASYNC Memory",
-	},
-	{
-#if defined(CONFIG_BF561)
-		.start = L2_SRAM,
-		.end = L2_SRAM_END,
-		.psize = SIZE_1M,
-		.attr = SWITCH_T | D_CPLB,
-		.i_conf = L2_MEMORY,
-		.d_conf = L2_MEMORY,
-		.valid = 1,
-#else
-		.valid = 0,
-#endif
-		.name = "L2 Memory",
-	}
-};
-#endif
+extern void generate_cpl_tables(void);
diff --git a/include/asm-blackfin/dma-mapping.h b/include/asm-blackfin/dma-mapping.h
index 7a77d7f..282fabc 100644
--- a/include/asm-blackfin/dma-mapping.h
+++ b/include/asm-blackfin/dma-mapping.h
@@ -15,6 +15,8 @@
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+#define dma_mapping_error
+
 /*
  * Map a single buffer of the indicated size for DMA in streaming mode.
  * The 32-bit bus address to use is returned.
diff --git a/include/asm-blackfin/fb.h b/include/asm-blackfin/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-blackfin/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-blackfin/fixed_code.h b/include/asm-blackfin/fixed_code.h
new file mode 100644
index 0000000..e6df84e
--- /dev/null
+++ b/include/asm-blackfin/fixed_code.h
@@ -0,0 +1,20 @@
+/* This file defines the fixed addresses where userspace programs can find
+   atomic code sequences.  */
+
+#define FIXED_CODE_START	0x400
+
+#define SIGRETURN_STUB		0x400
+
+#define ATOMIC_SEQS_START	0x410
+
+#define ATOMIC_XCHG32		0x410
+#define ATOMIC_CAS32		0x420
+#define ATOMIC_ADD32		0x430
+#define ATOMIC_SUB32		0x440
+#define ATOMIC_IOR32		0x450
+#define ATOMIC_AND32		0x460
+#define ATOMIC_XOR32		0x470
+
+#define ATOMIC_SEQS_END		0x480
+
+#define FIXED_CODE_END		0x480
diff --git a/include/asm-blackfin/gpio.h b/include/asm-blackfin/gpio.h
index d16fe3c..7480cfa 100644
--- a/include/asm-blackfin/gpio.h
+++ b/include/asm-blackfin/gpio.h
@@ -148,10 +148,6 @@
 
 #ifdef BF537_FAMILY
 #define MAX_BLACKFIN_GPIOS 48
-#define PORT_F 0
-#define PORT_G 1
-#define PORT_H 2
-#define PORT_J 3
 
 #define	GPIO_PF0	0
 #define	GPIO_PF1	1
@@ -202,13 +198,71 @@
 #define	GPIO_PH14      	46
 #define	GPIO_PH15      	47
 
+#define PORT_F GPIO_PF0
+#define PORT_G GPIO_PG0
+#define PORT_H GPIO_PH0
+
+#endif
+
+#ifdef BF548_FAMILY
+#include <asm-blackfin/mach-bf548/gpio.h>
 #endif
 
 #ifdef BF561_FAMILY
 #define MAX_BLACKFIN_GPIOS 48
-#define PORT_FIO0 0
-#define PORT_FIO1 1
-#define PORT_FIO2 2
+
+#define	GPIO_PF0	0
+#define	GPIO_PF1	1
+#define	GPIO_PF2	2
+#define	GPIO_PF3	3
+#define	GPIO_PF4	4
+#define	GPIO_PF5	5
+#define	GPIO_PF6	6
+#define	GPIO_PF7	7
+#define	GPIO_PF8	8
+#define	GPIO_PF9	9
+#define	GPIO_PF10	10
+#define	GPIO_PF11	11
+#define	GPIO_PF12	12
+#define	GPIO_PF13	13
+#define	GPIO_PF14	14
+#define	GPIO_PF15	15
+#define	GPIO_PF16	16
+#define	GPIO_PF17	17
+#define	GPIO_PF18	18
+#define	GPIO_PF19	19
+#define	GPIO_PF20	20
+#define	GPIO_PF21	21
+#define	GPIO_PF22	22
+#define	GPIO_PF23	23
+#define	GPIO_PF24	24
+#define	GPIO_PF25	25
+#define	GPIO_PF26	26
+#define	GPIO_PF27	27
+#define	GPIO_PF28	28
+#define	GPIO_PF29	29
+#define	GPIO_PF30	30
+#define	GPIO_PF31	31
+#define	GPIO_PF32	32
+#define	GPIO_PF33	33
+#define	GPIO_PF34	34
+#define	GPIO_PF35	35
+#define	GPIO_PF36	36
+#define	GPIO_PF37	37
+#define	GPIO_PF38	38
+#define	GPIO_PF39	39
+#define	GPIO_PF40	40
+#define	GPIO_PF41	41
+#define	GPIO_PF42	42
+#define	GPIO_PF43	43
+#define	GPIO_PF44	44
+#define	GPIO_PF45	45
+#define	GPIO_PF46	46
+#define	GPIO_PF47	47
+
+#define PORT_FIO0 GPIO_0
+#define PORT_FIO1 GPIO_16
+#define PORT_FIO2 GPIO_32
 #endif
 
 #ifndef __ASSEMBLY__
@@ -230,6 +284,7 @@
 * MODIFICATION HISTORY :
 **************************************************************/
 
+#ifndef BF548_FAMILY
 void set_gpio_dir(unsigned short, unsigned short);
 void set_gpio_inen(unsigned short, unsigned short);
 void set_gpio_polar(unsigned short, unsigned short);
@@ -299,6 +354,7 @@
 	unsigned short dummy16;
 	unsigned short inen;
 };
+#endif
 
 #ifdef CONFIG_PM
 #define PM_WAKE_RISING	0x1
@@ -332,6 +388,7 @@
 	unsigned short inen;
 
 	unsigned short fer;
+	unsigned short reserved;
 };
 #endif /*CONFIG_PM*/
 
@@ -356,8 +413,10 @@
 void gpio_set_value(unsigned short gpio, unsigned short arg);
 unsigned short gpio_get_value(unsigned short gpio);
 
+#ifndef BF548_FAMILY
 #define gpio_get_value(gpio) 		get_gpio_data(gpio)
 #define gpio_set_value(gpio, value)	set_gpio_data(gpio, value)
+#endif
 
 void gpio_direction_input(unsigned short gpio);
 void gpio_direction_output(unsigned short gpio);
diff --git a/include/asm-blackfin/hardirq.h b/include/asm-blackfin/hardirq.h
index 0cab0d3..b6b19f1 100644
--- a/include/asm-blackfin/hardirq.h
+++ b/include/asm-blackfin/hardirq.h
@@ -28,7 +28,11 @@
  * SOFTIRQ_MASK: 0x00ff0000
  */
 
+#if NR_IRQS > 256
+#define HARDIRQ_BITS	9
+#else
 #define HARDIRQ_BITS	8
+#endif
 
 #ifdef NR_IRQS
 # if (1 << HARDIRQ_BITS) < NR_IRQS
diff --git a/include/asm-blackfin/io.h b/include/asm-blackfin/io.h
index 7e6995e8..142cb33 100644
--- a/include/asm-blackfin/io.h
+++ b/include/asm-blackfin/io.h
@@ -20,7 +20,7 @@
  */
 #ifndef __ASSEMBLY__
 
-static inline unsigned char readb(void __iomem *addr)
+static inline unsigned char readb(const volatile void __iomem *addr)
 {
 	unsigned int val;
 	int tmp;
@@ -35,7 +35,7 @@
 	return (unsigned char) val;
 }
 
-static inline unsigned short readw(void __iomem *addr)
+static inline unsigned short readw(const volatile void __iomem *addr)
 {
 	unsigned int val;
 	int tmp;
@@ -50,7 +50,7 @@
 	return (unsigned short) val;
 }
 
-static inline unsigned int readl(void __iomem *addr)
+static inline unsigned int readl(const volatile void __iomem *addr)
 {
 	unsigned int val;
 	int tmp;
@@ -115,13 +115,21 @@
 
 #ifndef __ASSEMBLY__
 
-extern void outsb(void __iomem *port, const void *addr, unsigned long count);
-extern void outsw(void __iomem *port, const void *addr, unsigned long count);
-extern void outsl(void __iomem *port, const void *addr, unsigned long count);
+extern void outsb(void __iomem *port, const void *addr, unsigned short count);
+extern void outsw(void __iomem *port, const void *addr, unsigned short count);
+extern void outsl(void __iomem *port, const void *addr, unsigned short count);
 
-extern void insb(const void __iomem *port, void *addr, unsigned long count);
-extern void insw(const void __iomem *port, void *addr, unsigned long count);
-extern void insl(const void __iomem *port, void *addr, unsigned long count);
+extern void insb(const void __iomem *port, void *addr, unsigned short count);
+extern void insw(const void __iomem *port, void *addr, unsigned short count);
+extern void insl(const void __iomem *port, void *addr, unsigned short count);
+
+extern void dma_outsb(void __iomem *port, const void *addr, unsigned short count);
+extern void dma_outsw(void __iomem *port, const void *addr, unsigned short count);
+extern void dma_outsl(void __iomem *port, const void *addr, unsigned short count);
+
+extern void dma_insb(const void __iomem *port, void *addr, unsigned short count);
+extern void dma_insw(const void __iomem *port, void *addr, unsigned short count);
+extern void dma_insl(const void __iomem *port, void *addr, unsigned short count);
 
 /*
  * Map some physical address range into the kernel address space.
diff --git a/include/asm-blackfin/kgdb.h b/include/asm-blackfin/kgdb.h
new file mode 100644
index 0000000..532bd90
--- /dev/null
+++ b/include/asm-blackfin/kgdb.h
@@ -0,0 +1,183 @@
+/*
+ * File:         include/asm-blackfin/kgdb.h
+ * Based on:
+ * Author:       Sonic Zhang
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:          $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
+ *
+ * Modified:
+ *               Copyright 2005-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __ASM_BLACKFIN_KGDB_H__
+#define __ASM_BLACKFIN_KGDB_H__
+
+#include <linux/ptrace.h>
+
+/* gdb locks */
+#define KGDB_MAX_NO_CPUS 8
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+/* Longer buffer is needed to list all threads */
+#define BUFMAX 2048
+
+/*
+ *  Note that this register image is different from
+ *  the register image that Linux produces at interrupt time.
+ *  
+ *  Linux's register image is defined by struct pt_regs in ptrace.h.
+ */
+enum regnames {
+  /* Core Registers */
+  BFIN_R0 = 0,
+  BFIN_R1,
+  BFIN_R2,
+  BFIN_R3,
+  BFIN_R4,
+  BFIN_R5,
+  BFIN_R6,
+  BFIN_R7,
+  BFIN_P0,
+  BFIN_P1,
+  BFIN_P2,
+  BFIN_P3,
+  BFIN_P4,
+  BFIN_P5,
+  BFIN_SP,
+  BFIN_FP,
+  BFIN_I0,
+  BFIN_I1,
+  BFIN_I2,
+  BFIN_I3,
+  BFIN_M0,
+  BFIN_M1,
+  BFIN_M2,
+  BFIN_M3,
+  BFIN_B0,
+  BFIN_B1,
+  BFIN_B2,
+  BFIN_B3,
+  BFIN_L0,
+  BFIN_L1,
+  BFIN_L2,
+  BFIN_L3,
+  BFIN_A0_DOT_X,
+  BFIN_A0_DOT_W,
+  BFIN_A1_DOT_X,
+  BFIN_A1_DOT_W,
+  BFIN_ASTAT,
+  BFIN_RETS,
+  BFIN_LC0,
+  BFIN_LT0,
+  BFIN_LB0,
+  BFIN_LC1,
+  BFIN_LT1,
+  BFIN_LB1,
+  BFIN_CYCLES,
+  BFIN_CYCLES2,
+  BFIN_USP,
+  BFIN_SEQSTAT,
+  BFIN_SYSCFG,
+  BFIN_RETI,
+  BFIN_RETX,
+  BFIN_RETN,
+  BFIN_RETE,
+  
+  /* Pseudo Registers */
+  BFIN_PC,
+  BFIN_CC,
+  BFIN_EXTRA1,		/* Address of .text section.  */
+  BFIN_EXTRA2,		/* Address of .data section.  */
+  BFIN_EXTRA3,		/* Address of .bss section.  */
+  BFIN_FDPIC_EXEC, 
+  BFIN_FDPIC_INTERP,
+
+  /* MMRs */
+  BFIN_IPEND,
+
+  /* LAST ENTRY SHOULD NOT BE CHANGED.  */
+  BFIN_NUM_REGS		/* The number of all registers.  */
+};
+
+/* Number of bytes of registers.  */
+#define NUMREGBYTES BFIN_NUM_REGS*4
+
+#define BREAKPOINT() asm("   EXCPT 2;");
+#define BREAK_INSTR_SIZE       2
+#define HW_BREAKPOINT_NUM		6
+
+/* Instruction watchpoint address control register bits mask */
+#define WPPWR		0x1
+#define WPIREN01	0x2
+#define WPIRINV01	0x4
+#define WPIAEN0		0x8
+#define WPIAEN1		0x10
+#define WPICNTEN0	0x20
+#define WPICNTEN1	0x40
+#define EMUSW0		0x80
+#define EMUSW1		0x100
+#define WPIREN23	0x200
+#define WPIRINV23	0x400
+#define WPIAEN2		0x800
+#define WPIAEN3		0x1000
+#define WPICNTEN2	0x2000
+#define WPICNTEN3	0x4000
+#define EMUSW2		0x8000
+#define EMUSW3		0x10000
+#define WPIREN45	0x20000
+#define WPIRINV45	0x40000
+#define WPIAEN4		0x80000
+#define WPIAEN5		0x100000
+#define WPICNTEN4	0x200000
+#define WPICNTEN5	0x400000
+#define EMUSW4		0x800000
+#define EMUSW5		0x1000000
+#define WPAND		0x2000000
+
+/* Data watchpoint address control register bits mask */
+#define WPDREN01	0x1
+#define WPDRINV01	0x2
+#define WPDAEN0		0x4
+#define WPDAEN1		0x8
+#define WPDCNTEN0	0x10
+#define WPDCNTEN1	0x20
+#define WPDSRC0		0xc0
+#define WPDACC0		0x300
+#define WPDSRC1		0xc00
+#define WPDACC1		0x3000
+
+/* Watchpoint status register bits mask */
+#define STATIA0		0x1
+#define STATIA1		0x2
+#define STATIA2		0x4
+#define STATIA3		0x8
+#define STATIA4		0x10
+#define STATIA5		0x20
+#define STATDA0		0x40
+#define STATDA1		0x80
+
+extern void kgdb_print(const char *fmt, ...);
+
+#endif
diff --git a/include/asm-blackfin/mach-bf527/cdefBF522.h b/include/asm-blackfin/mach-bf527/cdefBF522.h
new file mode 100644
index 0000000..52c0649
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/cdefBF522.h
@@ -0,0 +1,46 @@
+/*
+ * File:         include/asm-blackfin/mach-bf527/cdefbf522.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  system mmr register map
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF522_H
+#define _CDEF_BF522_H
+
+/* include all Core registers and bit definitions */
+#include "defBF522.h"
+
+/* include core specific register pointer definitions */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF522 */
+
+/* include cdefBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
+#include "cdefBF52x_base.h"
+
+#endif /* _CDEF_BF522_H */
diff --git a/include/asm-blackfin/mach-bf527/cdefBF525.h b/include/asm-blackfin/mach-bf527/cdefBF525.h
new file mode 100644
index 0000000..2cc67e4
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/cdefBF525.h
@@ -0,0 +1,461 @@
+/*
+ * File:         include/asm-blackfin/mach-bf527/cdefbf525.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  system mmr register map
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF525_H
+#define _CDEF_BF525_H
+
+/* include all Core registers and bit definitions */
+#include "defBF525.h"
+
+/* include core specific register pointer definitions */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF525 */
+
+/* include cdefBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
+#include "cdefBF52x_base.h"
+
+/* The following are the #defines needed by ADSP-BF525 that are not in the common header */
+
+/* USB Control Registers */
+
+#define bfin_read_USB_FADDR()			bfin_read16(USB_FADDR)
+#define bfin_write_USB_FADDR(val)		bfin_write16(USB_FADDR, val)
+#define bfin_read_USB_POWER()			bfin_read16(USB_POWER)
+#define bfin_write_USB_POWER(val)		bfin_write16(USB_POWER, val)
+#define bfin_read_USB_INTRTX()			bfin_read16(USB_INTRTX)
+#define bfin_write_USB_INTRTX(val)		bfin_write16(USB_INTRTX, val)
+#define bfin_read_USB_INTRRX()			bfin_read16(USB_INTRRX)
+#define bfin_write_USB_INTRRX(val)		bfin_write16(USB_INTRRX, val)
+#define bfin_read_USB_INTRTXE()			bfin_read16(USB_INTRTXE)
+#define bfin_write_USB_INTRTXE(val)		bfin_write16(USB_INTRTXE, val)
+#define bfin_read_USB_INTRRXE()			bfin_read16(USB_INTRRXE)
+#define bfin_write_USB_INTRRXE(val)		bfin_write16(USB_INTRRXE, val)
+#define bfin_read_USB_INTRUSB()			bfin_read16(USB_INTRUSB)
+#define bfin_write_USB_INTRUSB(val)		bfin_write16(USB_INTRUSB, val)
+#define bfin_read_USB_INTRUSBE()		bfin_read16(USB_INTRUSBE)
+#define bfin_write_USB_INTRUSBE(val)		bfin_write16(USB_INTRUSBE, val)
+#define bfin_read_USB_FRAME()			bfin_read16(USB_FRAME)
+#define bfin_write_USB_FRAME(val)		bfin_write16(USB_FRAME, val)
+#define bfin_read_USB_INDEX()			bfin_read16(USB_INDEX)
+#define bfin_write_USB_INDEX(val)		bfin_write16(USB_INDEX, val)
+#define bfin_read_USB_TESTMODE()		bfin_read16(USB_TESTMODE)
+#define bfin_write_USB_TESTMODE(val)		bfin_write16(USB_TESTMODE, val)
+#define bfin_read_USB_GLOBINTR()		bfin_read16(USB_GLOBINTR)
+#define bfin_write_USB_GLOBINTR(val)		bfin_write16(USB_GLOBINTR, val)
+#define bfin_read_USB_GLOBAL_CTL()		bfin_read16(USB_GLOBAL_CTL)
+#define bfin_write_USB_GLOBAL_CTL(val)		bfin_write16(USB_GLOBAL_CTL, val)
+
+/* USB Packet Control Registers */
+
+#define bfin_read_USB_TX_MAX_PACKET()		bfin_read16(USB_TX_MAX_PACKET)
+#define bfin_write_USB_TX_MAX_PACKET(val)	bfin_write16(USB_TX_MAX_PACKET, val)
+#define bfin_read_USB_CSR0()			bfin_read16(USB_CSR0)
+#define bfin_write_USB_CSR0(val)		bfin_write16(USB_CSR0, val)
+#define bfin_read_USB_TXCSR()			bfin_read16(USB_TXCSR)
+#define bfin_write_USB_TXCSR(val)		bfin_write16(USB_TXCSR, val)
+#define bfin_read_USB_RX_MAX_PACKET()		bfin_read16(USB_RX_MAX_PACKET)
+#define bfin_write_USB_RX_MAX_PACKET(val)	bfin_write16(USB_RX_MAX_PACKET, val)
+#define bfin_read_USB_RXCSR()			bfin_read16(USB_RXCSR)
+#define bfin_write_USB_RXCSR(val)		bfin_write16(USB_RXCSR, val)
+#define bfin_read_USB_COUNT0()			bfin_read16(USB_COUNT0)
+#define bfin_write_USB_COUNT0(val)		bfin_write16(USB_COUNT0, val)
+#define bfin_read_USB_RXCOUNT()			bfin_read16(USB_RXCOUNT)
+#define bfin_write_USB_RXCOUNT(val)		bfin_write16(USB_RXCOUNT, val)
+#define bfin_read_USB_TXTYPE()			bfin_read16(USB_TXTYPE)
+#define bfin_write_USB_TXTYPE(val)		bfin_write16(USB_TXTYPE, val)
+#define bfin_read_USB_NAKLIMIT0()		bfin_read16(USB_NAKLIMIT0)
+#define bfin_write_USB_NAKLIMIT0(val)		bfin_write16(USB_NAKLIMIT0, val)
+#define bfin_read_USB_TXINTERVAL()		bfin_read16(USB_TXINTERVAL)
+#define bfin_write_USB_TXINTERVAL(val)		bfin_write16(USB_TXINTERVAL, val)
+#define bfin_read_USB_RXTYPE()			bfin_read16(USB_RXTYPE)
+#define bfin_write_USB_RXTYPE(val)		bfin_write16(USB_RXTYPE, val)
+#define bfin_read_USB_RXINTERVAL()		bfin_read16(USB_RXINTERVAL)
+#define bfin_write_USB_RXINTERVAL(val)		bfin_write16(USB_RXINTERVAL, val)
+#define bfin_read_USB_TXCOUNT()			bfin_read16(USB_TXCOUNT)
+#define bfin_write_USB_TXCOUNT(val)		bfin_write16(USB_TXCOUNT, val)
+
+/* USB Endpoint FIFO Registers */
+
+#define bfin_read_USB_EP0_FIFO()		bfin_read16(USB_EP0_FIFO)
+#define bfin_write_USB_EP0_FIFO(val)		bfin_write16(USB_EP0_FIFO, val)
+#define bfin_read_USB_EP1_FIFO()		bfin_read16(USB_EP1_FIFO)
+#define bfin_write_USB_EP1_FIFO(val)		bfin_write16(USB_EP1_FIFO, val)
+#define bfin_read_USB_EP2_FIFO()		bfin_read16(USB_EP2_FIFO)
+#define bfin_write_USB_EP2_FIFO(val)		bfin_write16(USB_EP2_FIFO, val)
+#define bfin_read_USB_EP3_FIFO()		bfin_read16(USB_EP3_FIFO)
+#define bfin_write_USB_EP3_FIFO(val)		bfin_write16(USB_EP3_FIFO, val)
+#define bfin_read_USB_EP4_FIFO()		bfin_read16(USB_EP4_FIFO)
+#define bfin_write_USB_EP4_FIFO(val)		bfin_write16(USB_EP4_FIFO, val)
+#define bfin_read_USB_EP5_FIFO()		bfin_read16(USB_EP5_FIFO)
+#define bfin_write_USB_EP5_FIFO(val)		bfin_write16(USB_EP5_FIFO, val)
+#define bfin_read_USB_EP6_FIFO()		bfin_read16(USB_EP6_FIFO)
+#define bfin_write_USB_EP6_FIFO(val)		bfin_write16(USB_EP6_FIFO, val)
+#define bfin_read_USB_EP7_FIFO()		bfin_read16(USB_EP7_FIFO)
+#define bfin_write_USB_EP7_FIFO(val)		bfin_write16(USB_EP7_FIFO, val)
+
+/* USB OTG Control Registers */
+
+#define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
+#define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
+#define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
+#define bfin_write_USB_OTG_VBUS_IRQ(val)	bfin_write16(USB_OTG_VBUS_IRQ, val)
+#define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
+#define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
+
+/* USB Phy Control Registers */
+
+#define bfin_read_USB_LINKINFO()		bfin_read16(USB_LINKINFO)
+#define bfin_write_USB_LINKINFO(val)		bfin_write16(USB_LINKINFO, val)
+#define bfin_read_USB_VPLEN()			bfin_read16(USB_VPLEN)
+#define bfin_write_USB_VPLEN(val)		bfin_write16(USB_VPLEN, val)
+#define bfin_read_USB_HS_EOF1()			bfin_read16(USB_HS_EOF1)
+#define bfin_write_USB_HS_EOF1(val)		bfin_write16(USB_HS_EOF1, val)
+#define bfin_read_USB_FS_EOF1()			bfin_read16(USB_FS_EOF1)
+#define bfin_write_USB_FS_EOF1(val)		bfin_write16(USB_FS_EOF1, val)
+#define bfin_read_USB_LS_EOF1()			bfin_read16(USB_LS_EOF1)
+#define bfin_write_USB_LS_EOF1(val)		bfin_write16(USB_LS_EOF1, val)
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CNTRL()		bfin_read16(USB_APHY_CNTRL)
+#define bfin_write_USB_APHY_CNTRL(val)		bfin_write16(USB_APHY_CNTRL, val)
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CALIB()		bfin_read16(USB_APHY_CALIB)
+#define bfin_write_USB_APHY_CALIB(val)		bfin_write16(USB_APHY_CALIB, val)
+
+#define bfin_read_USB_APHY_CNTRL2()		bfin_read16(USB_APHY_CNTRL2)
+#define bfin_write_USB_APHY_CNTRL2(val)		bfin_write16(USB_APHY_CNTRL2, val)
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define bfin_read_USB_PHY_TEST()		bfin_read16(USB_PHY_TEST)
+#define bfin_write_USB_PHY_TEST(val)		bfin_write16(USB_PHY_TEST, val)
+
+#define bfin_read_USB_PLLOSC_CTRL()		bfin_read16(USB_PLLOSC_CTRL)
+#define bfin_write_USB_PLLOSC_CTRL(val)		bfin_write16(USB_PLLOSC_CTRL, val)
+#define bfin_read_USB_SRP_CLKDIV()		bfin_read16(USB_SRP_CLKDIV)
+#define bfin_write_USB_SRP_CLKDIV(val)		bfin_write16(USB_SRP_CLKDIV, val)
+
+/* USB Endpoint 0 Control Registers */
+
+#define bfin_read_USB_EP_NI0_TXMAXP()		bfin_read16(USB_EP_NI0_TXMAXP)
+#define bfin_write_USB_EP_NI0_TXMAXP(val)	bfin_write16(USB_EP_NI0_TXMAXP, val)
+#define bfin_read_USB_EP_NI0_TXCSR()		bfin_read16(USB_EP_NI0_TXCSR)
+#define bfin_write_USB_EP_NI0_TXCSR(val)	bfin_write16(USB_EP_NI0_TXCSR, val)
+#define bfin_read_USB_EP_NI0_RXMAXP()		bfin_read16(USB_EP_NI0_RXMAXP)
+#define bfin_write_USB_EP_NI0_RXMAXP(val)	bfin_write16(USB_EP_NI0_RXMAXP, val)
+#define bfin_read_USB_EP_NI0_RXCSR()		bfin_read16(USB_EP_NI0_RXCSR)
+#define bfin_write_USB_EP_NI0_RXCSR(val)	bfin_write16(USB_EP_NI0_RXCSR, val)
+#define bfin_read_USB_EP_NI0_RXCOUNT()		bfin_read16(USB_EP_NI0_RXCOUNT)
+#define bfin_write_USB_EP_NI0_RXCOUNT(val)	bfin_write16(USB_EP_NI0_RXCOUNT, val)
+#define bfin_read_USB_EP_NI0_TXTYPE()		bfin_read16(USB_EP_NI0_TXTYPE)
+#define bfin_write_USB_EP_NI0_TXTYPE(val)	bfin_write16(USB_EP_NI0_TXTYPE, val)
+#define bfin_read_USB_EP_NI0_TXINTERVAL()	bfin_read16(USB_EP_NI0_TXINTERVAL)
+#define bfin_write_USB_EP_NI0_TXINTERVAL(val)	bfin_write16(USB_EP_NI0_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI0_RXTYPE()		bfin_read16(USB_EP_NI0_RXTYPE)
+#define bfin_write_USB_EP_NI0_RXTYPE(val)	bfin_write16(USB_EP_NI0_RXTYPE, val)
+#define bfin_read_USB_EP_NI0_RXINTERVAL()	bfin_read16(USB_EP_NI0_RXINTERVAL)
+#define bfin_write_USB_EP_NI0_RXINTERVAL(val)	bfin_write16(USB_EP_NI0_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI0_TXCOUNT()		bfin_read16(USB_EP_NI0_TXCOUNT)
+#define bfin_write_USB_EP_NI0_TXCOUNT(val)	bfin_write16(USB_EP_NI0_TXCOUNT, val)
+
+/* USB Endpoint 1 Control Registers */
+
+#define bfin_read_USB_EP_NI1_TXMAXP()		bfin_read16(USB_EP_NI1_TXMAXP)
+#define bfin_write_USB_EP_NI1_TXMAXP(val)	bfin_write16(USB_EP_NI1_TXMAXP, val)
+#define bfin_read_USB_EP_NI1_TXCSR()		bfin_read16(USB_EP_NI1_TXCSR)
+#define bfin_write_USB_EP_NI1_TXCSR(val)	bfin_write16(USB_EP_NI1_TXCSR, val)
+#define bfin_read_USB_EP_NI1_RXMAXP()		bfin_read16(USB_EP_NI1_RXMAXP)
+#define bfin_write_USB_EP_NI1_RXMAXP(val)	bfin_write16(USB_EP_NI1_RXMAXP, val)
+#define bfin_read_USB_EP_NI1_RXCSR()		bfin_read16(USB_EP_NI1_RXCSR)
+#define bfin_write_USB_EP_NI1_RXCSR(val)	bfin_write16(USB_EP_NI1_RXCSR, val)
+#define bfin_read_USB_EP_NI1_RXCOUNT()		bfin_read16(USB_EP_NI1_RXCOUNT)
+#define bfin_write_USB_EP_NI1_RXCOUNT(val)	bfin_write16(USB_EP_NI1_RXCOUNT, val)
+#define bfin_read_USB_EP_NI1_TXTYPE()		bfin_read16(USB_EP_NI1_TXTYPE)
+#define bfin_write_USB_EP_NI1_TXTYPE(val)	bfin_write16(USB_EP_NI1_TXTYPE, val)
+#define bfin_read_USB_EP_NI1_TXINTERVAL()	bfin_read16(USB_EP_NI1_TXINTERVAL)
+#define bfin_write_USB_EP_NI1_TXINTERVAL(val)	bfin_write16(USB_EP_NI1_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI1_RXTYPE()		bfin_read16(USB_EP_NI1_RXTYPE)
+#define bfin_write_USB_EP_NI1_RXTYPE(val)	bfin_write16(USB_EP_NI1_RXTYPE, val)
+#define bfin_read_USB_EP_NI1_RXINTERVAL()	bfin_read16(USB_EP_NI1_RXINTERVAL)
+#define bfin_write_USB_EP_NI1_RXINTERVAL(val)	bfin_write16(USB_EP_NI1_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI1_TXCOUNT()		bfin_read16(USB_EP_NI1_TXCOUNT)
+#define bfin_write_USB_EP_NI1_TXCOUNT(val)	bfin_write16(USB_EP_NI1_TXCOUNT, val)
+
+/* USB Endpoint 2 Control Registers */
+
+#define bfin_read_USB_EP_NI2_TXMAXP()		bfin_read16(USB_EP_NI2_TXMAXP)
+#define bfin_write_USB_EP_NI2_TXMAXP(val)	bfin_write16(USB_EP_NI2_TXMAXP, val)
+#define bfin_read_USB_EP_NI2_TXCSR()		bfin_read16(USB_EP_NI2_TXCSR)
+#define bfin_write_USB_EP_NI2_TXCSR(val)	bfin_write16(USB_EP_NI2_TXCSR, val)
+#define bfin_read_USB_EP_NI2_RXMAXP()		bfin_read16(USB_EP_NI2_RXMAXP)
+#define bfin_write_USB_EP_NI2_RXMAXP(val)	bfin_write16(USB_EP_NI2_RXMAXP, val)
+#define bfin_read_USB_EP_NI2_RXCSR()		bfin_read16(USB_EP_NI2_RXCSR)
+#define bfin_write_USB_EP_NI2_RXCSR(val)	bfin_write16(USB_EP_NI2_RXCSR, val)
+#define bfin_read_USB_EP_NI2_RXCOUNT()		bfin_read16(USB_EP_NI2_RXCOUNT)
+#define bfin_write_USB_EP_NI2_RXCOUNT(val)	bfin_write16(USB_EP_NI2_RXCOUNT, val)
+#define bfin_read_USB_EP_NI2_TXTYPE()		bfin_read16(USB_EP_NI2_TXTYPE)
+#define bfin_write_USB_EP_NI2_TXTYPE(val)	bfin_write16(USB_EP_NI2_TXTYPE, val)
+#define bfin_read_USB_EP_NI2_TXINTERVAL()	bfin_read16(USB_EP_NI2_TXINTERVAL)
+#define bfin_write_USB_EP_NI2_TXINTERVAL(val)	bfin_write16(USB_EP_NI2_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI2_RXTYPE()		bfin_read16(USB_EP_NI2_RXTYPE)
+#define bfin_write_USB_EP_NI2_RXTYPE(val)	bfin_write16(USB_EP_NI2_RXTYPE, val)
+#define bfin_read_USB_EP_NI2_RXINTERVAL()	bfin_read16(USB_EP_NI2_RXINTERVAL)
+#define bfin_write_USB_EP_NI2_RXINTERVAL(val)	bfin_write16(USB_EP_NI2_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI2_TXCOUNT()		bfin_read16(USB_EP_NI2_TXCOUNT)
+#define bfin_write_USB_EP_NI2_TXCOUNT(val)	bfin_write16(USB_EP_NI2_TXCOUNT, val)
+
+/* USB Endpoint 3 Control Registers */
+
+#define bfin_read_USB_EP_NI3_TXMAXP()		bfin_read16(USB_EP_NI3_TXMAXP)
+#define bfin_write_USB_EP_NI3_TXMAXP(val)	bfin_write16(USB_EP_NI3_TXMAXP, val)
+#define bfin_read_USB_EP_NI3_TXCSR()		bfin_read16(USB_EP_NI3_TXCSR)
+#define bfin_write_USB_EP_NI3_TXCSR(val)	bfin_write16(USB_EP_NI3_TXCSR, val)
+#define bfin_read_USB_EP_NI3_RXMAXP()		bfin_read16(USB_EP_NI3_RXMAXP)
+#define bfin_write_USB_EP_NI3_RXMAXP(val)	bfin_write16(USB_EP_NI3_RXMAXP, val)
+#define bfin_read_USB_EP_NI3_RXCSR()		bfin_read16(USB_EP_NI3_RXCSR)
+#define bfin_write_USB_EP_NI3_RXCSR(val)	bfin_write16(USB_EP_NI3_RXCSR, val)
+#define bfin_read_USB_EP_NI3_RXCOUNT()		bfin_read16(USB_EP_NI3_RXCOUNT)
+#define bfin_write_USB_EP_NI3_RXCOUNT(val)	bfin_write16(USB_EP_NI3_RXCOUNT, val)
+#define bfin_read_USB_EP_NI3_TXTYPE()		bfin_read16(USB_EP_NI3_TXTYPE)
+#define bfin_write_USB_EP_NI3_TXTYPE(val)	bfin_write16(USB_EP_NI3_TXTYPE, val)
+#define bfin_read_USB_EP_NI3_TXINTERVAL()	bfin_read16(USB_EP_NI3_TXINTERVAL)
+#define bfin_write_USB_EP_NI3_TXINTERVAL(val)	bfin_write16(USB_EP_NI3_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI3_RXTYPE()		bfin_read16(USB_EP_NI3_RXTYPE)
+#define bfin_write_USB_EP_NI3_RXTYPE(val)	bfin_write16(USB_EP_NI3_RXTYPE, val)
+#define bfin_read_USB_EP_NI3_RXINTERVAL()	bfin_read16(USB_EP_NI3_RXINTERVAL)
+#define bfin_write_USB_EP_NI3_RXINTERVAL(val)	bfin_write16(USB_EP_NI3_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI3_TXCOUNT()		bfin_read16(USB_EP_NI3_TXCOUNT)
+#define bfin_write_USB_EP_NI3_TXCOUNT(val)	bfin_write16(USB_EP_NI3_TXCOUNT, val)
+
+/* USB Endpoint 4 Control Registers */
+
+#define bfin_read_USB_EP_NI4_TXMAXP()		bfin_read16(USB_EP_NI4_TXMAXP)
+#define bfin_write_USB_EP_NI4_TXMAXP(val)	bfin_write16(USB_EP_NI4_TXMAXP, val)
+#define bfin_read_USB_EP_NI4_TXCSR()		bfin_read16(USB_EP_NI4_TXCSR)
+#define bfin_write_USB_EP_NI4_TXCSR(val)	bfin_write16(USB_EP_NI4_TXCSR, val)
+#define bfin_read_USB_EP_NI4_RXMAXP()		bfin_read16(USB_EP_NI4_RXMAXP)
+#define bfin_write_USB_EP_NI4_RXMAXP(val)	bfin_write16(USB_EP_NI4_RXMAXP, val)
+#define bfin_read_USB_EP_NI4_RXCSR()		bfin_read16(USB_EP_NI4_RXCSR)
+#define bfin_write_USB_EP_NI4_RXCSR(val)	bfin_write16(USB_EP_NI4_RXCSR, val)
+#define bfin_read_USB_EP_NI4_RXCOUNT()		bfin_read16(USB_EP_NI4_RXCOUNT)
+#define bfin_write_USB_EP_NI4_RXCOUNT(val)	bfin_write16(USB_EP_NI4_RXCOUNT, val)
+#define bfin_read_USB_EP_NI4_TXTYPE()		bfin_read16(USB_EP_NI4_TXTYPE)
+#define bfin_write_USB_EP_NI4_TXTYPE(val)	bfin_write16(USB_EP_NI4_TXTYPE, val)
+#define bfin_read_USB_EP_NI4_TXINTERVAL()	bfin_read16(USB_EP_NI4_TXINTERVAL)
+#define bfin_write_USB_EP_NI4_TXINTERVAL(val)	bfin_write16(USB_EP_NI4_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI4_RXTYPE()		bfin_read16(USB_EP_NI4_RXTYPE)
+#define bfin_write_USB_EP_NI4_RXTYPE(val)	bfin_write16(USB_EP_NI4_RXTYPE, val)
+#define bfin_read_USB_EP_NI4_RXINTERVAL()	bfin_read16(USB_EP_NI4_RXINTERVAL)
+#define bfin_write_USB_EP_NI4_RXINTERVAL(val)	bfin_write16(USB_EP_NI4_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI4_TXCOUNT()		bfin_read16(USB_EP_NI4_TXCOUNT)
+#define bfin_write_USB_EP_NI4_TXCOUNT(val)	bfin_write16(USB_EP_NI4_TXCOUNT, val)
+
+/* USB Endpoint 5 Control Registers */
+
+#define bfin_read_USB_EP_NI5_TXMAXP()		bfin_read16(USB_EP_NI5_TXMAXP)
+#define bfin_write_USB_EP_NI5_TXMAXP(val)	bfin_write16(USB_EP_NI5_TXMAXP, val)
+#define bfin_read_USB_EP_NI5_TXCSR()		bfin_read16(USB_EP_NI5_TXCSR)
+#define bfin_write_USB_EP_NI5_TXCSR(val)	bfin_write16(USB_EP_NI5_TXCSR, val)
+#define bfin_read_USB_EP_NI5_RXMAXP()		bfin_read16(USB_EP_NI5_RXMAXP)
+#define bfin_write_USB_EP_NI5_RXMAXP(val)	bfin_write16(USB_EP_NI5_RXMAXP, val)
+#define bfin_read_USB_EP_NI5_RXCSR()		bfin_read16(USB_EP_NI5_RXCSR)
+#define bfin_write_USB_EP_NI5_RXCSR(val)	bfin_write16(USB_EP_NI5_RXCSR, val)
+#define bfin_read_USB_EP_NI5_RXCOUNT()		bfin_read16(USB_EP_NI5_RXCOUNT)
+#define bfin_write_USB_EP_NI5_RXCOUNT(val)	bfin_write16(USB_EP_NI5_RXCOUNT, val)
+#define bfin_read_USB_EP_NI5_TXTYPE()		bfin_read16(USB_EP_NI5_TXTYPE)
+#define bfin_write_USB_EP_NI5_TXTYPE(val)	bfin_write16(USB_EP_NI5_TXTYPE, val)
+#define bfin_read_USB_EP_NI5_TXINTERVAL()	bfin_read16(USB_EP_NI5_TXINTERVAL)
+#define bfin_write_USB_EP_NI5_TXINTERVAL(val)	bfin_write16(USB_EP_NI5_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI5_RXTYPE()		bfin_read16(USB_EP_NI5_RXTYPE)
+#define bfin_write_USB_EP_NI5_RXTYPE(val)	bfin_write16(USB_EP_NI5_RXTYPE, val)
+#define bfin_read_USB_EP_NI5_RXINTERVAL()	bfin_read16(USB_EP_NI5_RXINTERVAL)
+#define bfin_write_USB_EP_NI5_RXINTERVAL(val)	bfin_write16(USB_EP_NI5_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI5_TXCOUNT()		bfin_read16(USB_EP_NI5_TXCOUNT)
+#define bfin_write_USB_EP_NI5_TXCOUNT(val)	bfin_write16(USB_EP_NI5_TXCOUNT, val)
+
+/* USB Endpoint 6 Control Registers */
+
+#define bfin_read_USB_EP_NI6_TXMAXP()		bfin_read16(USB_EP_NI6_TXMAXP)
+#define bfin_write_USB_EP_NI6_TXMAXP(val)	bfin_write16(USB_EP_NI6_TXMAXP, val)
+#define bfin_read_USB_EP_NI6_TXCSR()		bfin_read16(USB_EP_NI6_TXCSR)
+#define bfin_write_USB_EP_NI6_TXCSR(val)	bfin_write16(USB_EP_NI6_TXCSR, val)
+#define bfin_read_USB_EP_NI6_RXMAXP()		bfin_read16(USB_EP_NI6_RXMAXP)
+#define bfin_write_USB_EP_NI6_RXMAXP(val)	bfin_write16(USB_EP_NI6_RXMAXP, val)
+#define bfin_read_USB_EP_NI6_RXCSR()		bfin_read16(USB_EP_NI6_RXCSR)
+#define bfin_write_USB_EP_NI6_RXCSR(val)	bfin_write16(USB_EP_NI6_RXCSR, val)
+#define bfin_read_USB_EP_NI6_RXCOUNT()		bfin_read16(USB_EP_NI6_RXCOUNT)
+#define bfin_write_USB_EP_NI6_RXCOUNT(val)	bfin_write16(USB_EP_NI6_RXCOUNT, val)
+#define bfin_read_USB_EP_NI6_TXTYPE()		bfin_read16(USB_EP_NI6_TXTYPE)
+#define bfin_write_USB_EP_NI6_TXTYPE(val)	bfin_write16(USB_EP_NI6_TXTYPE, val)
+#define bfin_read_USB_EP_NI6_TXINTERVAL()	bfin_read16(USB_EP_NI6_TXINTERVAL)
+#define bfin_write_USB_EP_NI6_TXINTERVAL(val)	bfin_write16(USB_EP_NI6_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI6_RXTYPE()		bfin_read16(USB_EP_NI6_RXTYPE)
+#define bfin_write_USB_EP_NI6_RXTYPE(val)	bfin_write16(USB_EP_NI6_RXTYPE, val)
+#define bfin_read_USB_EP_NI6_RXINTERVAL()	bfin_read16(USB_EP_NI6_RXINTERVAL)
+#define bfin_write_USB_EP_NI6_RXINTERVAL(val)	bfin_write16(USB_EP_NI6_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI6_TXCOUNT()		bfin_read16(USB_EP_NI6_TXCOUNT)
+#define bfin_write_USB_EP_NI6_TXCOUNT(val)	bfin_write16(USB_EP_NI6_TXCOUNT, val)
+
+/* USB Endpoint 7 Control Registers */
+
+#define bfin_read_USB_EP_NI7_TXMAXP()		bfin_read16(USB_EP_NI7_TXMAXP)
+#define bfin_write_USB_EP_NI7_TXMAXP(val)	bfin_write16(USB_EP_NI7_TXMAXP, val)
+#define bfin_read_USB_EP_NI7_TXCSR()		bfin_read16(USB_EP_NI7_TXCSR)
+#define bfin_write_USB_EP_NI7_TXCSR(val)	bfin_write16(USB_EP_NI7_TXCSR, val)
+#define bfin_read_USB_EP_NI7_RXMAXP()		bfin_read16(USB_EP_NI7_RXMAXP)
+#define bfin_write_USB_EP_NI7_RXMAXP(val)	bfin_write16(USB_EP_NI7_RXMAXP, val)
+#define bfin_read_USB_EP_NI7_RXCSR()		bfin_read16(USB_EP_NI7_RXCSR)
+#define bfin_write_USB_EP_NI7_RXCSR(val)	bfin_write16(USB_EP_NI7_RXCSR, val)
+#define bfin_read_USB_EP_NI7_RXCOUNT()		bfin_read16(USB_EP_NI7_RXCOUNT)
+#define bfin_write_USB_EP_NI7_RXCOUNT(val)	bfin_write16(USB_EP_NI7_RXCOUNT, val)
+#define bfin_read_USB_EP_NI7_TXTYPE()		bfin_read16(USB_EP_NI7_TXTYPE)
+#define bfin_write_USB_EP_NI7_TXTYPE(val)	bfin_write16(USB_EP_NI7_TXTYPE, val)
+#define bfin_read_USB_EP_NI7_TXINTERVAL()	bfin_read16(USB_EP_NI7_TXINTERVAL)
+#define bfin_write_USB_EP_NI7_TXINTERVAL(val)	bfin_write16(USB_EP_NI7_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_RXTYPE()		bfin_read16(USB_EP_NI7_RXTYPE)
+#define bfin_write_USB_EP_NI7_RXTYPE(val)	bfin_write16(USB_EP_NI7_RXTYPE, val)
+#define bfin_read_USB_EP_NI7_RXINTERVAL()	bfin_read16(USB_EP_NI7_RXINTERVAL)
+#define bfin_write_USB_EP_NI7_RXINTERVAL(val)	bfin_write16(USB_EP_NI7_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_TXCOUNT()		bfin_read16(USB_EP_NI7_TXCOUNT)
+#define bfin_write_USB_EP_NI7_TXCOUNT(val)	bfin_write16(USB_EP_NI7_TXCOUNT, val)
+
+#define bfin_read_USB_DMA_INTERRUPT()		bfin_read16(USB_DMA_INTERRUPT)
+#define bfin_write_USB_DMA_INTERRUPT(val)	bfin_write16(USB_DMA_INTERRUPT, val)
+
+/* USB Channel 0 Config Registers */
+
+#define bfin_read_USB_DMA0CONTROL()		bfin_read16(USB_DMA0CONTROL)
+#define bfin_write_USB_DMA0CONTROL(val)		bfin_write16(USB_DMA0CONTROL, val)
+#define bfin_read_USB_DMA0ADDRLOW()		bfin_read16(USB_DMA0ADDRLOW)
+#define bfin_write_USB_DMA0ADDRLOW(val)		bfin_write16(USB_DMA0ADDRLOW, val)
+#define bfin_read_USB_DMA0ADDRHIGH()		bfin_read16(USB_DMA0ADDRHIGH)
+#define bfin_write_USB_DMA0ADDRHIGH(val)	bfin_write16(USB_DMA0ADDRHIGH, val)
+#define bfin_read_USB_DMA0COUNTLOW()		bfin_read16(USB_DMA0COUNTLOW)
+#define bfin_write_USB_DMA0COUNTLOW(val)	bfin_write16(USB_DMA0COUNTLOW, val)
+#define bfin_read_USB_DMA0COUNTHIGH()		bfin_read16(USB_DMA0COUNTHIGH)
+#define bfin_write_USB_DMA0COUNTHIGH(val)	bfin_write16(USB_DMA0COUNTHIGH, val)
+
+/* USB Channel 1 Config Registers */
+
+#define bfin_read_USB_DMA1CONTROL()		bfin_read16(USB_DMA1CONTROL)
+#define bfin_write_USB_DMA1CONTROL(val)		bfin_write16(USB_DMA1CONTROL, val)
+#define bfin_read_USB_DMA1ADDRLOW()		bfin_read16(USB_DMA1ADDRLOW)
+#define bfin_write_USB_DMA1ADDRLOW(val)		bfin_write16(USB_DMA1ADDRLOW, val)
+#define bfin_read_USB_DMA1ADDRHIGH()		bfin_read16(USB_DMA1ADDRHIGH)
+#define bfin_write_USB_DMA1ADDRHIGH(val)	bfin_write16(USB_DMA1ADDRHIGH, val)
+#define bfin_read_USB_DMA1COUNTLOW()		bfin_read16(USB_DMA1COUNTLOW)
+#define bfin_write_USB_DMA1COUNTLOW(val)	bfin_write16(USB_DMA1COUNTLOW, val)
+#define bfin_read_USB_DMA1COUNTHIGH()		bfin_read16(USB_DMA1COUNTHIGH)
+#define bfin_write_USB_DMA1COUNTHIGH(val)	bfin_write16(USB_DMA1COUNTHIGH, val)
+
+/* USB Channel 2 Config Registers */
+
+#define bfin_read_USB_DMA2CONTROL()		bfin_read16(USB_DMA2CONTROL)
+#define bfin_write_USB_DMA2CONTROL(val)		bfin_write16(USB_DMA2CONTROL, val)
+#define bfin_read_USB_DMA2ADDRLOW()		bfin_read16(USB_DMA2ADDRLOW)
+#define bfin_write_USB_DMA2ADDRLOW(val)		bfin_write16(USB_DMA2ADDRLOW, val)
+#define bfin_read_USB_DMA2ADDRHIGH()		bfin_read16(USB_DMA2ADDRHIGH)
+#define bfin_write_USB_DMA2ADDRHIGH(val)	bfin_write16(USB_DMA2ADDRHIGH, val)
+#define bfin_read_USB_DMA2COUNTLOW()		bfin_read16(USB_DMA2COUNTLOW)
+#define bfin_write_USB_DMA2COUNTLOW(val)	bfin_write16(USB_DMA2COUNTLOW, val)
+#define bfin_read_USB_DMA2COUNTHIGH()		bfin_read16(USB_DMA2COUNTHIGH)
+#define bfin_write_USB_DMA2COUNTHIGH(val)	bfin_write16(USB_DMA2COUNTHIGH, val)
+
+/* USB Channel 3 Config Registers */
+
+#define bfin_read_USB_DMA3CONTROL()		bfin_read16(USB_DMA3CONTROL)
+#define bfin_write_USB_DMA3CONTROL(val)		bfin_write16(USB_DMA3CONTROL, val)
+#define bfin_read_USB_DMA3ADDRLOW()		bfin_read16(USB_DMA3ADDRLOW)
+#define bfin_write_USB_DMA3ADDRLOW(val)		bfin_write16(USB_DMA3ADDRLOW, val)
+#define bfin_read_USB_DMA3ADDRHIGH()		bfin_read16(USB_DMA3ADDRHIGH)
+#define bfin_write_USB_DMA3ADDRHIGH(val)	bfin_write16(USB_DMA3ADDRHIGH, val)
+#define bfin_read_USB_DMA3COUNTLOW()		bfin_read16(USB_DMA3COUNTLOW)
+#define bfin_write_USB_DMA3COUNTLOW(val)	bfin_write16(USB_DMA3COUNTLOW, val)
+#define bfin_read_USB_DMA3COUNTHIGH()		bfin_read16(USB_DMA3COUNTHIGH)
+#define bfin_write_USB_DMA3COUNTHIGH(val)	bfin_write16(USB_DMA3COUNTHIGH, val)
+
+/* USB Channel 4 Config Registers */
+
+#define bfin_read_USB_DMA4CONTROL()		bfin_read16(USB_DMA4CONTROL)
+#define bfin_write_USB_DMA4CONTROL(val)		bfin_write16(USB_DMA4CONTROL, val)
+#define bfin_read_USB_DMA4ADDRLOW()		bfin_read16(USB_DMA4ADDRLOW)
+#define bfin_write_USB_DMA4ADDRLOW(val)		bfin_write16(USB_DMA4ADDRLOW, val)
+#define bfin_read_USB_DMA4ADDRHIGH()		bfin_read16(USB_DMA4ADDRHIGH)
+#define bfin_write_USB_DMA4ADDRHIGH(val)	bfin_write16(USB_DMA4ADDRHIGH, val)
+#define bfin_read_USB_DMA4COUNTLOW()		bfin_read16(USB_DMA4COUNTLOW)
+#define bfin_write_USB_DMA4COUNTLOW(val)	bfin_write16(USB_DMA4COUNTLOW, val)
+#define bfin_read_USB_DMA4COUNTHIGH()		bfin_read16(USB_DMA4COUNTHIGH)
+#define bfin_write_USB_DMA4COUNTHIGH(val)	bfin_write16(USB_DMA4COUNTHIGH, val)
+
+/* USB Channel 5 Config Registers */
+
+#define bfin_read_USB_DMA5CONTROL()		bfin_read16(USB_DMA5CONTROL)
+#define bfin_write_USB_DMA5CONTROL(val)		bfin_write16(USB_DMA5CONTROL, val)
+#define bfin_read_USB_DMA5ADDRLOW()		bfin_read16(USB_DMA5ADDRLOW)
+#define bfin_write_USB_DMA5ADDRLOW(val)		bfin_write16(USB_DMA5ADDRLOW, val)
+#define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
+#define bfin_write_USB_DMA5ADDRHIGH(val)	bfin_write16(USB_DMA5ADDRHIGH, val)
+#define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
+#define bfin_write_USB_DMA5COUNTLOW(val)	bfin_write16(USB_DMA5COUNTLOW, val)
+#define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
+#define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
+
+/* USB Channel 6 Config Registers */
+
+#define bfin_read_USB_DMA6CONTROL()		bfin_read16(USB_DMA6CONTROL)
+#define bfin_write_USB_DMA6CONTROL(val)		bfin_write16(USB_DMA6CONTROL, val)
+#define bfin_read_USB_DMA6ADDRLOW()		bfin_read16(USB_DMA6ADDRLOW)
+#define bfin_write_USB_DMA6ADDRLOW(val)		bfin_write16(USB_DMA6ADDRLOW, val)
+#define bfin_read_USB_DMA6ADDRHIGH()		bfin_read16(USB_DMA6ADDRHIGH)
+#define bfin_write_USB_DMA6ADDRHIGH(val)	bfin_write16(USB_DMA6ADDRHIGH, val)
+#define bfin_read_USB_DMA6COUNTLOW()		bfin_read16(USB_DMA6COUNTLOW)
+#define bfin_write_USB_DMA6COUNTLOW(val)	bfin_write16(USB_DMA6COUNTLOW, val)
+#define bfin_read_USB_DMA6COUNTHIGH()		bfin_read16(USB_DMA6COUNTHIGH)
+#define bfin_write_USB_DMA6COUNTHIGH(val)	bfin_write16(USB_DMA6COUNTHIGH, val)
+
+/* USB Channel 7 Config Registers */
+
+#define bfin_read_USB_DMA7CONTROL()		bfin_read16(USB_DMA7CONTROL)
+#define bfin_write_USB_DMA7CONTROL(val)		bfin_write16(USB_DMA7CONTROL, val)
+#define bfin_read_USB_DMA7ADDRLOW()		bfin_read16(USB_DMA7ADDRLOW)
+#define bfin_write_USB_DMA7ADDRLOW(val)		bfin_write16(USB_DMA7ADDRLOW, val)
+#define bfin_read_USB_DMA7ADDRHIGH()		bfin_read16(USB_DMA7ADDRHIGH)
+#define bfin_write_USB_DMA7ADDRHIGH(val)	bfin_write16(USB_DMA7ADDRHIGH, val)
+#define bfin_read_USB_DMA7COUNTLOW()		bfin_read16(USB_DMA7COUNTLOW)
+#define bfin_write_USB_DMA7COUNTLOW(val)	bfin_write16(USB_DMA7COUNTLOW, val)
+#define bfin_read_USB_DMA7COUNTHIGH()		bfin_read16(USB_DMA7COUNTHIGH)
+#define bfin_write_USB_DMA7COUNTHIGH(val)	bfin_write16(USB_DMA7COUNTHIGH, val)
+
+#endif /* _CDEF_BF525_H */
diff --git a/include/asm-blackfin/mach-bf527/cdefBF527.h b/include/asm-blackfin/mach-bf527/cdefBF527.h
new file mode 100644
index 0000000..5bd1a86
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/cdefBF527.h
@@ -0,0 +1,626 @@
+/*
+ * File:         include/asm-blackfin/mach-bf527/cdefbf527.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  system mmr register map
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF527_H
+#define _CDEF_BF527_H
+
+/* include all Core registers and bit definitions */
+#include "defBF527.h"
+
+/* include core specific register pointer definitions */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF527 */
+
+/* include cdefBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
+#include "cdefBF52x_base.h"
+
+/* The following are the #defines needed by ADSP-BF527 that are not in the common header */
+
+/* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) */
+
+#define bfin_read_EMAC_OPMODE()			bfin_read32(EMAC_OPMODE)
+#define bfin_write_EMAC_OPMODE(val)		bfin_write32(EMAC_OPMODE, val)
+#define bfin_read_EMAC_ADDRLO()			bfin_read32(EMAC_ADDRLO)
+#define bfin_write_EMAC_ADDRLO(val)		bfin_write32(EMAC_ADDRLO, val)
+#define bfin_read_EMAC_ADDRHI()			bfin_read32(EMAC_ADDRHI)
+#define bfin_write_EMAC_ADDRHI(val)		bfin_write32(EMAC_ADDRHI, val)
+#define bfin_read_EMAC_HASHLO()			bfin_read32(EMAC_HASHLO)
+#define bfin_write_EMAC_HASHLO(val)		bfin_write32(EMAC_HASHLO, val)
+#define bfin_read_EMAC_HASHHI()			bfin_read32(EMAC_HASHHI)
+#define bfin_write_EMAC_HASHHI(val)		bfin_write32(EMAC_HASHHI, val)
+#define bfin_read_EMAC_STAADD()			bfin_read32(EMAC_STAADD)
+#define bfin_write_EMAC_STAADD(val)		bfin_write32(EMAC_STAADD, val)
+#define bfin_read_EMAC_STADAT()			bfin_read32(EMAC_STADAT)
+#define bfin_write_EMAC_STADAT(val)		bfin_write32(EMAC_STADAT, val)
+#define bfin_read_EMAC_FLC()			bfin_read32(EMAC_FLC)
+#define bfin_write_EMAC_FLC(val)		bfin_write32(EMAC_FLC, val)
+#define bfin_read_EMAC_VLAN1()			bfin_read32(EMAC_VLAN1)
+#define bfin_write_EMAC_VLAN1(val)		bfin_write32(EMAC_VLAN1, val)
+#define bfin_read_EMAC_VLAN2()			bfin_read32(EMAC_VLAN2)
+#define bfin_write_EMAC_VLAN2(val)		bfin_write32(EMAC_VLAN2, val)
+#define bfin_read_EMAC_WKUP_CTL()		bfin_read32(EMAC_WKUP_CTL)
+#define bfin_write_EMAC_WKUP_CTL(val)		bfin_write32(EMAC_WKUP_CTL, val)
+#define bfin_read_EMAC_WKUP_FFMSK0()		bfin_read32(EMAC_WKUP_FFMSK0)
+#define bfin_write_EMAC_WKUP_FFMSK0(val)	bfin_write32(EMAC_WKUP_FFMSK0, val)
+#define bfin_read_EMAC_WKUP_FFMSK1()		bfin_read32(EMAC_WKUP_FFMSK1)
+#define bfin_write_EMAC_WKUP_FFMSK1(val)	bfin_write32(EMAC_WKUP_FFMSK1, val)
+#define bfin_read_EMAC_WKUP_FFMSK2()		bfin_read32(EMAC_WKUP_FFMSK2)
+#define bfin_write_EMAC_WKUP_FFMSK2(val)	bfin_write32(EMAC_WKUP_FFMSK2, val)
+#define bfin_read_EMAC_WKUP_FFMSK3()		bfin_read32(EMAC_WKUP_FFMSK3)
+#define bfin_write_EMAC_WKUP_FFMSK3(val)	bfin_write32(EMAC_WKUP_FFMSK3, val)
+#define bfin_read_EMAC_WKUP_FFCMD()		bfin_read32(EMAC_WKUP_FFCMD)
+#define bfin_write_EMAC_WKUP_FFCMD(val)		bfin_write32(EMAC_WKUP_FFCMD, val)
+#define bfin_read_EMAC_WKUP_FFOFF()		bfin_read32(EMAC_WKUP_FFOFF)
+#define bfin_write_EMAC_WKUP_FFOFF(val)		bfin_write32(EMAC_WKUP_FFOFF, val)
+#define bfin_read_EMAC_WKUP_FFCRC0()		bfin_read32(EMAC_WKUP_FFCRC0)
+#define bfin_write_EMAC_WKUP_FFCRC0(val)	bfin_write32(EMAC_WKUP_FFCRC0, val)
+#define bfin_read_EMAC_WKUP_FFCRC1()		bfin_read32(EMAC_WKUP_FFCRC1)
+#define bfin_write_EMAC_WKUP_FFCRC1(val)	bfin_write32(EMAC_WKUP_FFCRC1, val)
+
+#define bfin_read_EMAC_SYSCTL()			bfin_read32(EMAC_SYSCTL)
+#define bfin_write_EMAC_SYSCTL(val)		bfin_write32(EMAC_SYSCTL, val)
+#define bfin_read_EMAC_SYSTAT()			bfin_read32(EMAC_SYSTAT)
+#define bfin_write_EMAC_SYSTAT(val)		bfin_write32(EMAC_SYSTAT, val)
+#define bfin_read_EMAC_RX_STAT()		bfin_read32(EMAC_RX_STAT)
+#define bfin_write_EMAC_RX_STAT(val)		bfin_write32(EMAC_RX_STAT, val)
+#define bfin_read_EMAC_RX_STKY()		bfin_read32(EMAC_RX_STKY)
+#define bfin_write_EMAC_RX_STKY(val)		bfin_write32(EMAC_RX_STKY, val)
+#define bfin_read_EMAC_RX_IRQE()		bfin_read32(EMAC_RX_IRQE)
+#define bfin_write_EMAC_RX_IRQE(val)		bfin_write32(EMAC_RX_IRQE, val)
+#define bfin_read_EMAC_TX_STAT()		bfin_read32(EMAC_TX_STAT)
+#define bfin_write_EMAC_TX_STAT(val)		bfin_write32(EMAC_TX_STAT, val)
+#define bfin_read_EMAC_TX_STKY()		bfin_read32(EMAC_TX_STKY)
+#define bfin_write_EMAC_TX_STKY(val)		bfin_write32(EMAC_TX_STKY, val)
+#define bfin_read_EMAC_TX_IRQE()		bfin_read32(EMAC_TX_IRQE)
+#define bfin_write_EMAC_TX_IRQE(val)		bfin_write32(EMAC_TX_IRQE, val)
+
+#define bfin_read_EMAC_MMC_CTL()		bfin_read32(EMAC_MMC_CTL)
+#define bfin_write_EMAC_MMC_CTL(val)		bfin_write32(EMAC_MMC_CTL, val)
+#define bfin_read_EMAC_MMC_RIRQS()		bfin_read32(EMAC_MMC_RIRQS)
+#define bfin_write_EMAC_MMC_RIRQS(val)		bfin_write32(EMAC_MMC_RIRQS, val)
+#define bfin_read_EMAC_MMC_RIRQE()		bfin_read32(EMAC_MMC_RIRQE)
+#define bfin_write_EMAC_MMC_RIRQE(val)		bfin_write32(EMAC_MMC_RIRQE, val)
+#define bfin_read_EMAC_MMC_TIRQS()		bfin_read32(EMAC_MMC_TIRQS)
+#define bfin_write_EMAC_MMC_TIRQS(val)		bfin_write32(EMAC_MMC_TIRQS, val)
+#define bfin_read_EMAC_MMC_TIRQE()		bfin_read32(EMAC_MMC_TIRQE)
+#define bfin_write_EMAC_MMC_TIRQE(val)		bfin_write32(EMAC_MMC_TIRQE, val)
+
+#define bfin_read_EMAC_RXC_OK()			bfin_read32(EMAC_RXC_OK)
+#define bfin_write_EMAC_RXC_OK(val)		bfin_write32(EMAC_RXC_OK, val)
+#define bfin_read_EMAC_RXC_FCS()		bfin_read32(EMAC_RXC_FCS)
+#define bfin_write_EMAC_RXC_FCS(val)		bfin_write32(EMAC_RXC_FCS, val)
+#define bfin_read_EMAC_RXC_ALIGN()		bfin_read32(EMAC_RXC_ALIGN)
+#define bfin_write_EMAC_RXC_ALIGN(val)		bfin_write32(EMAC_RXC_ALIGN, val)
+#define bfin_read_EMAC_RXC_OCTET()		bfin_read32(EMAC_RXC_OCTET)
+#define bfin_write_EMAC_RXC_OCTET(val)		bfin_write32(EMAC_RXC_OCTET, val)
+#define bfin_read_EMAC_RXC_DMAOVF()		bfin_read32(EMAC_RXC_DMAOVF)
+#define bfin_write_EMAC_RXC_DMAOVF(val)		bfin_write32(EMAC_RXC_DMAOVF, val)
+#define bfin_read_EMAC_RXC_UNICST()		bfin_read32(EMAC_RXC_UNICST)
+#define bfin_write_EMAC_RXC_UNICST(val)		bfin_write32(EMAC_RXC_UNICST, val)
+#define bfin_read_EMAC_RXC_MULTI()		bfin_read32(EMAC_RXC_MULTI)
+#define bfin_write_EMAC_RXC_MULTI(val)		bfin_write32(EMAC_RXC_MULTI, val)
+#define bfin_read_EMAC_RXC_BROAD()		bfin_read32(EMAC_RXC_BROAD)
+#define bfin_write_EMAC_RXC_BROAD(val)		bfin_write32(EMAC_RXC_BROAD, val)
+#define bfin_read_EMAC_RXC_LNERRI()		bfin_read32(EMAC_RXC_LNERRI)
+#define bfin_write_EMAC_RXC_LNERRI(val)		bfin_write32(EMAC_RXC_LNERRI, val)
+#define bfin_read_EMAC_RXC_LNERRO()		bfin_read32(EMAC_RXC_LNERRO)
+#define bfin_write_EMAC_RXC_LNERRO(val)		bfin_write32(EMAC_RXC_LNERRO, val)
+#define bfin_read_EMAC_RXC_LONG()		bfin_read32(EMAC_RXC_LONG)
+#define bfin_write_EMAC_RXC_LONG(val)		bfin_write32(EMAC_RXC_LONG, val)
+#define bfin_read_EMAC_RXC_MACCTL()		bfin_read32(EMAC_RXC_MACCTL)
+#define bfin_write_EMAC_RXC_MACCTL(val)		bfin_write32(EMAC_RXC_MACCTL, val)
+#define bfin_read_EMAC_RXC_OPCODE()		bfin_read32(EMAC_RXC_OPCODE)
+#define bfin_write_EMAC_RXC_OPCODE(val)		bfin_write32(EMAC_RXC_OPCODE, val)
+#define bfin_read_EMAC_RXC_PAUSE()		bfin_read32(EMAC_RXC_PAUSE)
+#define bfin_write_EMAC_RXC_PAUSE(val)		bfin_write32(EMAC_RXC_PAUSE, val)
+#define bfin_read_EMAC_RXC_ALLFRM()		bfin_read32(EMAC_RXC_ALLFRM)
+#define bfin_write_EMAC_RXC_ALLFRM(val)		bfin_write32(EMAC_RXC_ALLFRM, val)
+#define bfin_read_EMAC_RXC_ALLOCT()		bfin_read32(EMAC_RXC_ALLOCT)
+#define bfin_write_EMAC_RXC_ALLOCT(val)		bfin_write32(EMAC_RXC_ALLOCT, val)
+#define bfin_read_EMAC_RXC_TYPED()		bfin_read32(EMAC_RXC_TYPED)
+#define bfin_write_EMAC_RXC_TYPED(val)		bfin_write32(EMAC_RXC_TYPED, val)
+#define bfin_read_EMAC_RXC_SHORT()		bfin_read32(EMAC_RXC_SHORT)
+#define bfin_write_EMAC_RXC_SHORT(val)		bfin_write32(EMAC_RXC_SHORT, val)
+#define bfin_read_EMAC_RXC_EQ64()		bfin_read32(EMAC_RXC_EQ64)
+#define bfin_write_EMAC_RXC_EQ64(val)		bfin_write32(EMAC_RXC_EQ64, val)
+#define bfin_read_EMAC_RXC_LT128()		bfin_read32(EMAC_RXC_LT128)
+#define bfin_write_EMAC_RXC_LT128(val)		bfin_write32(EMAC_RXC_LT128, val)
+#define bfin_read_EMAC_RXC_LT256()		bfin_read32(EMAC_RXC_LT256)
+#define bfin_write_EMAC_RXC_LT256(val)		bfin_write32(EMAC_RXC_LT256, val)
+#define bfin_read_EMAC_RXC_LT512()		bfin_read32(EMAC_RXC_LT512)
+#define bfin_write_EMAC_RXC_LT512(val)		bfin_write32(EMAC_RXC_LT512, val)
+#define bfin_read_EMAC_RXC_LT1024()		bfin_read32(EMAC_RXC_LT1024)
+#define bfin_write_EMAC_RXC_LT1024(val)		bfin_write32(EMAC_RXC_LT1024, val)
+#define bfin_read_EMAC_RXC_GE1024()		bfin_read32(EMAC_RXC_GE1024)
+#define bfin_write_EMAC_RXC_GE1024(val)		bfin_write32(EMAC_RXC_GE1024, val)
+
+#define bfin_read_EMAC_TXC_OK()			bfin_read32(EMAC_TXC_OK)
+#define bfin_write_EMAC_TXC_OK(val)		bfin_write32(EMAC_TXC_OK, val)
+#define bfin_read_EMAC_TXC_1COL()		bfin_read32(EMAC_TXC_1COL)
+#define bfin_write_EMAC_TXC_1COL(val)		bfin_write32(EMAC_TXC_1COL, val)
+#define bfin_read_EMAC_TXC_GT1COL()		bfin_read32(EMAC_TXC_GT1COL)
+#define bfin_write_EMAC_TXC_GT1COL(val)		bfin_write32(EMAC_TXC_GT1COL, val)
+#define bfin_read_EMAC_TXC_OCTET()		bfin_read32(EMAC_TXC_OCTET)
+#define bfin_write_EMAC_TXC_OCTET(val)		bfin_write32(EMAC_TXC_OCTET, val)
+#define bfin_read_EMAC_TXC_DEFER()		bfin_read32(EMAC_TXC_DEFER)
+#define bfin_write_EMAC_TXC_DEFER(val)		bfin_write32(EMAC_TXC_DEFER, val)
+#define bfin_read_EMAC_TXC_LATECL()		bfin_read32(EMAC_TXC_LATECL)
+#define bfin_write_EMAC_TXC_LATECL(val)		bfin_write32(EMAC_TXC_LATECL, val)
+#define bfin_read_EMAC_TXC_XS_COL()		bfin_read32(EMAC_TXC_XS_COL)
+#define bfin_write_EMAC_TXC_XS_COL(val)		bfin_write32(EMAC_TXC_XS_COL, val)
+#define bfin_read_EMAC_TXC_DMAUND()		bfin_read32(EMAC_TXC_DMAUND)
+#define bfin_write_EMAC_TXC_DMAUND(val)		bfin_write32(EMAC_TXC_DMAUND, val)
+#define bfin_read_EMAC_TXC_CRSERR()		bfin_read32(EMAC_TXC_CRSERR)
+#define bfin_write_EMAC_TXC_CRSERR(val)		bfin_write32(EMAC_TXC_CRSERR, val)
+#define bfin_read_EMAC_TXC_UNICST()		bfin_read32(EMAC_TXC_UNICST)
+#define bfin_write_EMAC_TXC_UNICST(val)		bfin_write32(EMAC_TXC_UNICST, val)
+#define bfin_read_EMAC_TXC_MULTI()		bfin_read32(EMAC_TXC_MULTI)
+#define bfin_write_EMAC_TXC_MULTI(val)		bfin_write32(EMAC_TXC_MULTI, val)
+#define bfin_read_EMAC_TXC_BROAD()		bfin_read32(EMAC_TXC_BROAD)
+#define bfin_write_EMAC_TXC_BROAD(val)		bfin_write32(EMAC_TXC_BROAD, val)
+#define bfin_read_EMAC_TXC_XS_DFR()		bfin_read32(EMAC_TXC_XS_DFR)
+#define bfin_write_EMAC_TXC_XS_DFR(val)		bfin_write32(EMAC_TXC_XS_DFR, val)
+#define bfin_read_EMAC_TXC_MACCTL()		bfin_read32(EMAC_TXC_MACCTL)
+#define bfin_write_EMAC_TXC_MACCTL(val)		bfin_write32(EMAC_TXC_MACCTL, val)
+#define bfin_read_EMAC_TXC_ALLFRM()		bfin_read32(EMAC_TXC_ALLFRM)
+#define bfin_write_EMAC_TXC_ALLFRM(val)		bfin_write32(EMAC_TXC_ALLFRM, val)
+#define bfin_read_EMAC_TXC_ALLOCT()		bfin_read32(EMAC_TXC_ALLOCT)
+#define bfin_write_EMAC_TXC_ALLOCT(val)		bfin_write32(EMAC_TXC_ALLOCT, val)
+#define bfin_read_EMAC_TXC_EQ64()		bfin_read32(EMAC_TXC_EQ64)
+#define bfin_write_EMAC_TXC_EQ64(val)		bfin_write32(EMAC_TXC_EQ64, val)
+#define bfin_read_EMAC_TXC_LT128()		bfin_read32(EMAC_TXC_LT128)
+#define bfin_write_EMAC_TXC_LT128(val)		bfin_write32(EMAC_TXC_LT128, val)
+#define bfin_read_EMAC_TXC_LT256()		bfin_read32(EMAC_TXC_LT256)
+#define bfin_write_EMAC_TXC_LT256(val)		bfin_write32(EMAC_TXC_LT256, val)
+#define bfin_read_EMAC_TXC_LT512()		bfin_read32(EMAC_TXC_LT512)
+#define bfin_write_EMAC_TXC_LT512(val)		bfin_write32(EMAC_TXC_LT512, val)
+#define bfin_read_EMAC_TXC_LT1024()		bfin_read32(EMAC_TXC_LT1024)
+#define bfin_write_EMAC_TXC_LT1024(val)		bfin_write32(EMAC_TXC_LT1024, val)
+#define bfin_read_EMAC_TXC_GE1024()		bfin_read32(EMAC_TXC_GE1024)
+#define bfin_write_EMAC_TXC_GE1024(val)		bfin_write32(EMAC_TXC_GE1024, val)
+#define bfin_read_EMAC_TXC_ABORT()		bfin_read32(EMAC_TXC_ABORT)
+#define bfin_write_EMAC_TXC_ABORT(val)		bfin_write32(EMAC_TXC_ABORT, val)
+
+/* USB Control Registers */
+
+#define bfin_read_USB_FADDR()			bfin_read16(USB_FADDR)
+#define bfin_write_USB_FADDR(val)		bfin_write16(USB_FADDR, val)
+#define bfin_read_USB_POWER()			bfin_read16(USB_POWER)
+#define bfin_write_USB_POWER(val)		bfin_write16(USB_POWER, val)
+#define bfin_read_USB_INTRTX()			bfin_read16(USB_INTRTX)
+#define bfin_write_USB_INTRTX(val)		bfin_write16(USB_INTRTX, val)
+#define bfin_read_USB_INTRRX()			bfin_read16(USB_INTRRX)
+#define bfin_write_USB_INTRRX(val)		bfin_write16(USB_INTRRX, val)
+#define bfin_read_USB_INTRTXE()			bfin_read16(USB_INTRTXE)
+#define bfin_write_USB_INTRTXE(val)		bfin_write16(USB_INTRTXE, val)
+#define bfin_read_USB_INTRRXE()			bfin_read16(USB_INTRRXE)
+#define bfin_write_USB_INTRRXE(val)		bfin_write16(USB_INTRRXE, val)
+#define bfin_read_USB_INTRUSB()			bfin_read16(USB_INTRUSB)
+#define bfin_write_USB_INTRUSB(val)		bfin_write16(USB_INTRUSB, val)
+#define bfin_read_USB_INTRUSBE()		bfin_read16(USB_INTRUSBE)
+#define bfin_write_USB_INTRUSBE(val)		bfin_write16(USB_INTRUSBE, val)
+#define bfin_read_USB_FRAME()			bfin_read16(USB_FRAME)
+#define bfin_write_USB_FRAME(val)		bfin_write16(USB_FRAME, val)
+#define bfin_read_USB_INDEX()			bfin_read16(USB_INDEX)
+#define bfin_write_USB_INDEX(val)		bfin_write16(USB_INDEX, val)
+#define bfin_read_USB_TESTMODE()		bfin_read16(USB_TESTMODE)
+#define bfin_write_USB_TESTMODE(val)		bfin_write16(USB_TESTMODE, val)
+#define bfin_read_USB_GLOBINTR()		bfin_read16(USB_GLOBINTR)
+#define bfin_write_USB_GLOBINTR(val)		bfin_write16(USB_GLOBINTR, val)
+#define bfin_read_USB_GLOBAL_CTL()		bfin_read16(USB_GLOBAL_CTL)
+#define bfin_write_USB_GLOBAL_CTL(val)		bfin_write16(USB_GLOBAL_CTL, val)
+
+/* USB Packet Control Registers */
+
+#define bfin_read_USB_TX_MAX_PACKET()		bfin_read16(USB_TX_MAX_PACKET)
+#define bfin_write_USB_TX_MAX_PACKET(val)	bfin_write16(USB_TX_MAX_PACKET, val)
+#define bfin_read_USB_CSR0()			bfin_read16(USB_CSR0)
+#define bfin_write_USB_CSR0(val)		bfin_write16(USB_CSR0, val)
+#define bfin_read_USB_TXCSR()			bfin_read16(USB_TXCSR)
+#define bfin_write_USB_TXCSR(val)		bfin_write16(USB_TXCSR, val)
+#define bfin_read_USB_RX_MAX_PACKET()		bfin_read16(USB_RX_MAX_PACKET)
+#define bfin_write_USB_RX_MAX_PACKET(val)	bfin_write16(USB_RX_MAX_PACKET, val)
+#define bfin_read_USB_RXCSR()			bfin_read16(USB_RXCSR)
+#define bfin_write_USB_RXCSR(val)		bfin_write16(USB_RXCSR, val)
+#define bfin_read_USB_COUNT0()			bfin_read16(USB_COUNT0)
+#define bfin_write_USB_COUNT0(val)		bfin_write16(USB_COUNT0, val)
+#define bfin_read_USB_RXCOUNT()			bfin_read16(USB_RXCOUNT)
+#define bfin_write_USB_RXCOUNT(val)		bfin_write16(USB_RXCOUNT, val)
+#define bfin_read_USB_TXTYPE()			bfin_read16(USB_TXTYPE)
+#define bfin_write_USB_TXTYPE(val)		bfin_write16(USB_TXTYPE, val)
+#define bfin_read_USB_NAKLIMIT0()		bfin_read16(USB_NAKLIMIT0)
+#define bfin_write_USB_NAKLIMIT0(val)		bfin_write16(USB_NAKLIMIT0, val)
+#define bfin_read_USB_TXINTERVAL()		bfin_read16(USB_TXINTERVAL)
+#define bfin_write_USB_TXINTERVAL(val)		bfin_write16(USB_TXINTERVAL, val)
+#define bfin_read_USB_RXTYPE()			bfin_read16(USB_RXTYPE)
+#define bfin_write_USB_RXTYPE(val)		bfin_write16(USB_RXTYPE, val)
+#define bfin_read_USB_RXINTERVAL()		bfin_read16(USB_RXINTERVAL)
+#define bfin_write_USB_RXINTERVAL(val)		bfin_write16(USB_RXINTERVAL, val)
+#define bfin_read_USB_TXCOUNT()			bfin_read16(USB_TXCOUNT)
+#define bfin_write_USB_TXCOUNT(val)		bfin_write16(USB_TXCOUNT, val)
+
+/* USB Endpoint FIFO Registers */
+
+#define bfin_read_USB_EP0_FIFO()		bfin_read16(USB_EP0_FIFO)
+#define bfin_write_USB_EP0_FIFO(val)		bfin_write16(USB_EP0_FIFO, val)
+#define bfin_read_USB_EP1_FIFO()		bfin_read16(USB_EP1_FIFO)
+#define bfin_write_USB_EP1_FIFO(val)		bfin_write16(USB_EP1_FIFO, val)
+#define bfin_read_USB_EP2_FIFO()		bfin_read16(USB_EP2_FIFO)
+#define bfin_write_USB_EP2_FIFO(val)		bfin_write16(USB_EP2_FIFO, val)
+#define bfin_read_USB_EP3_FIFO()		bfin_read16(USB_EP3_FIFO)
+#define bfin_write_USB_EP3_FIFO(val)		bfin_write16(USB_EP3_FIFO, val)
+#define bfin_read_USB_EP4_FIFO()		bfin_read16(USB_EP4_FIFO)
+#define bfin_write_USB_EP4_FIFO(val)		bfin_write16(USB_EP4_FIFO, val)
+#define bfin_read_USB_EP5_FIFO()		bfin_read16(USB_EP5_FIFO)
+#define bfin_write_USB_EP5_FIFO(val)		bfin_write16(USB_EP5_FIFO, val)
+#define bfin_read_USB_EP6_FIFO()		bfin_read16(USB_EP6_FIFO)
+#define bfin_write_USB_EP6_FIFO(val)		bfin_write16(USB_EP6_FIFO, val)
+#define bfin_read_USB_EP7_FIFO()		bfin_read16(USB_EP7_FIFO)
+#define bfin_write_USB_EP7_FIFO(val)		bfin_write16(USB_EP7_FIFO, val)
+
+/* USB OTG Control Registers */
+
+#define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
+#define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
+#define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
+#define bfin_write_USB_OTG_VBUS_IRQ(val)	bfin_write16(USB_OTG_VBUS_IRQ, val)
+#define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
+#define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
+
+/* USB Phy Control Registers */
+
+#define bfin_read_USB_LINKINFO()		bfin_read16(USB_LINKINFO)
+#define bfin_write_USB_LINKINFO(val)		bfin_write16(USB_LINKINFO, val)
+#define bfin_read_USB_VPLEN()			bfin_read16(USB_VPLEN)
+#define bfin_write_USB_VPLEN(val)		bfin_write16(USB_VPLEN, val)
+#define bfin_read_USB_HS_EOF1()			bfin_read16(USB_HS_EOF1)
+#define bfin_write_USB_HS_EOF1(val)		bfin_write16(USB_HS_EOF1, val)
+#define bfin_read_USB_FS_EOF1()			bfin_read16(USB_FS_EOF1)
+#define bfin_write_USB_FS_EOF1(val)		bfin_write16(USB_FS_EOF1, val)
+#define bfin_read_USB_LS_EOF1()			bfin_read16(USB_LS_EOF1)
+#define bfin_write_USB_LS_EOF1(val)		bfin_write16(USB_LS_EOF1, val)
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CNTRL()		bfin_read16(USB_APHY_CNTRL)
+#define bfin_write_USB_APHY_CNTRL(val)		bfin_write16(USB_APHY_CNTRL, val)
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CALIB()		bfin_read16(USB_APHY_CALIB)
+#define bfin_write_USB_APHY_CALIB(val)		bfin_write16(USB_APHY_CALIB, val)
+
+#define bfin_read_USB_APHY_CNTRL2()		bfin_read16(USB_APHY_CNTRL2)
+#define bfin_write_USB_APHY_CNTRL2(val)		bfin_write16(USB_APHY_CNTRL2, val)
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define bfin_read_USB_PHY_TEST()		bfin_read16(USB_PHY_TEST)
+#define bfin_write_USB_PHY_TEST(val)		bfin_write16(USB_PHY_TEST, val)
+
+#define bfin_read_USB_PLLOSC_CTRL()		bfin_read16(USB_PLLOSC_CTRL)
+#define bfin_write_USB_PLLOSC_CTRL(val)		bfin_write16(USB_PLLOSC_CTRL, val)
+#define bfin_read_USB_SRP_CLKDIV()		bfin_read16(USB_SRP_CLKDIV)
+#define bfin_write_USB_SRP_CLKDIV(val)		bfin_write16(USB_SRP_CLKDIV, val)
+
+/* USB Endpoint 0 Control Registers */
+
+#define bfin_read_USB_EP_NI0_TXMAXP()		bfin_read16(USB_EP_NI0_TXMAXP)
+#define bfin_write_USB_EP_NI0_TXMAXP(val)	bfin_write16(USB_EP_NI0_TXMAXP, val)
+#define bfin_read_USB_EP_NI0_TXCSR()		bfin_read16(USB_EP_NI0_TXCSR)
+#define bfin_write_USB_EP_NI0_TXCSR(val)	bfin_write16(USB_EP_NI0_TXCSR, val)
+#define bfin_read_USB_EP_NI0_RXMAXP()		bfin_read16(USB_EP_NI0_RXMAXP)
+#define bfin_write_USB_EP_NI0_RXMAXP(val)	bfin_write16(USB_EP_NI0_RXMAXP, val)
+#define bfin_read_USB_EP_NI0_RXCSR()		bfin_read16(USB_EP_NI0_RXCSR)
+#define bfin_write_USB_EP_NI0_RXCSR(val)	bfin_write16(USB_EP_NI0_RXCSR, val)
+#define bfin_read_USB_EP_NI0_RXCOUNT()		bfin_read16(USB_EP_NI0_RXCOUNT)
+#define bfin_write_USB_EP_NI0_RXCOUNT(val)	bfin_write16(USB_EP_NI0_RXCOUNT, val)
+#define bfin_read_USB_EP_NI0_TXTYPE()		bfin_read16(USB_EP_NI0_TXTYPE)
+#define bfin_write_USB_EP_NI0_TXTYPE(val)	bfin_write16(USB_EP_NI0_TXTYPE, val)
+#define bfin_read_USB_EP_NI0_TXINTERVAL()	bfin_read16(USB_EP_NI0_TXINTERVAL)
+#define bfin_write_USB_EP_NI0_TXINTERVAL(val)	bfin_write16(USB_EP_NI0_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI0_RXTYPE()		bfin_read16(USB_EP_NI0_RXTYPE)
+#define bfin_write_USB_EP_NI0_RXTYPE(val)	bfin_write16(USB_EP_NI0_RXTYPE, val)
+#define bfin_read_USB_EP_NI0_RXINTERVAL()	bfin_read16(USB_EP_NI0_RXINTERVAL)
+#define bfin_write_USB_EP_NI0_RXINTERVAL(val)	bfin_write16(USB_EP_NI0_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI0_TXCOUNT()		bfin_read16(USB_EP_NI0_TXCOUNT)
+#define bfin_write_USB_EP_NI0_TXCOUNT(val)	bfin_write16(USB_EP_NI0_TXCOUNT, val)
+
+/* USB Endpoint 1 Control Registers */
+
+#define bfin_read_USB_EP_NI1_TXMAXP()		bfin_read16(USB_EP_NI1_TXMAXP)
+#define bfin_write_USB_EP_NI1_TXMAXP(val)	bfin_write16(USB_EP_NI1_TXMAXP, val)
+#define bfin_read_USB_EP_NI1_TXCSR()		bfin_read16(USB_EP_NI1_TXCSR)
+#define bfin_write_USB_EP_NI1_TXCSR(val)	bfin_write16(USB_EP_NI1_TXCSR, val)
+#define bfin_read_USB_EP_NI1_RXMAXP()		bfin_read16(USB_EP_NI1_RXMAXP)
+#define bfin_write_USB_EP_NI1_RXMAXP(val)	bfin_write16(USB_EP_NI1_RXMAXP, val)
+#define bfin_read_USB_EP_NI1_RXCSR()		bfin_read16(USB_EP_NI1_RXCSR)
+#define bfin_write_USB_EP_NI1_RXCSR(val)	bfin_write16(USB_EP_NI1_RXCSR, val)
+#define bfin_read_USB_EP_NI1_RXCOUNT()		bfin_read16(USB_EP_NI1_RXCOUNT)
+#define bfin_write_USB_EP_NI1_RXCOUNT(val)	bfin_write16(USB_EP_NI1_RXCOUNT, val)
+#define bfin_read_USB_EP_NI1_TXTYPE()		bfin_read16(USB_EP_NI1_TXTYPE)
+#define bfin_write_USB_EP_NI1_TXTYPE(val)	bfin_write16(USB_EP_NI1_TXTYPE, val)
+#define bfin_read_USB_EP_NI1_TXINTERVAL()	bfin_read16(USB_EP_NI1_TXINTERVAL)
+#define bfin_write_USB_EP_NI1_TXINTERVAL(val)	bfin_write16(USB_EP_NI1_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI1_RXTYPE()		bfin_read16(USB_EP_NI1_RXTYPE)
+#define bfin_write_USB_EP_NI1_RXTYPE(val)	bfin_write16(USB_EP_NI1_RXTYPE, val)
+#define bfin_read_USB_EP_NI1_RXINTERVAL()	bfin_read16(USB_EP_NI1_RXINTERVAL)
+#define bfin_write_USB_EP_NI1_RXINTERVAL(val)	bfin_write16(USB_EP_NI1_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI1_TXCOUNT()		bfin_read16(USB_EP_NI1_TXCOUNT)
+#define bfin_write_USB_EP_NI1_TXCOUNT(val)	bfin_write16(USB_EP_NI1_TXCOUNT, val)
+
+/* USB Endpoint 2 Control Registers */
+
+#define bfin_read_USB_EP_NI2_TXMAXP()		bfin_read16(USB_EP_NI2_TXMAXP)
+#define bfin_write_USB_EP_NI2_TXMAXP(val)	bfin_write16(USB_EP_NI2_TXMAXP, val)
+#define bfin_read_USB_EP_NI2_TXCSR()		bfin_read16(USB_EP_NI2_TXCSR)
+#define bfin_write_USB_EP_NI2_TXCSR(val)	bfin_write16(USB_EP_NI2_TXCSR, val)
+#define bfin_read_USB_EP_NI2_RXMAXP()		bfin_read16(USB_EP_NI2_RXMAXP)
+#define bfin_write_USB_EP_NI2_RXMAXP(val)	bfin_write16(USB_EP_NI2_RXMAXP, val)
+#define bfin_read_USB_EP_NI2_RXCSR()		bfin_read16(USB_EP_NI2_RXCSR)
+#define bfin_write_USB_EP_NI2_RXCSR(val)	bfin_write16(USB_EP_NI2_RXCSR, val)
+#define bfin_read_USB_EP_NI2_RXCOUNT()		bfin_read16(USB_EP_NI2_RXCOUNT)
+#define bfin_write_USB_EP_NI2_RXCOUNT(val)	bfin_write16(USB_EP_NI2_RXCOUNT, val)
+#define bfin_read_USB_EP_NI2_TXTYPE()		bfin_read16(USB_EP_NI2_TXTYPE)
+#define bfin_write_USB_EP_NI2_TXTYPE(val)	bfin_write16(USB_EP_NI2_TXTYPE, val)
+#define bfin_read_USB_EP_NI2_TXINTERVAL()	bfin_read16(USB_EP_NI2_TXINTERVAL)
+#define bfin_write_USB_EP_NI2_TXINTERVAL(val)	bfin_write16(USB_EP_NI2_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI2_RXTYPE()		bfin_read16(USB_EP_NI2_RXTYPE)
+#define bfin_write_USB_EP_NI2_RXTYPE(val)	bfin_write16(USB_EP_NI2_RXTYPE, val)
+#define bfin_read_USB_EP_NI2_RXINTERVAL()	bfin_read16(USB_EP_NI2_RXINTERVAL)
+#define bfin_write_USB_EP_NI2_RXINTERVAL(val)	bfin_write16(USB_EP_NI2_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI2_TXCOUNT()		bfin_read16(USB_EP_NI2_TXCOUNT)
+#define bfin_write_USB_EP_NI2_TXCOUNT(val)	bfin_write16(USB_EP_NI2_TXCOUNT, val)
+
+/* USB Endpoint 3 Control Registers */
+
+#define bfin_read_USB_EP_NI3_TXMAXP()		bfin_read16(USB_EP_NI3_TXMAXP)
+#define bfin_write_USB_EP_NI3_TXMAXP(val)	bfin_write16(USB_EP_NI3_TXMAXP, val)
+#define bfin_read_USB_EP_NI3_TXCSR()		bfin_read16(USB_EP_NI3_TXCSR)
+#define bfin_write_USB_EP_NI3_TXCSR(val)	bfin_write16(USB_EP_NI3_TXCSR, val)
+#define bfin_read_USB_EP_NI3_RXMAXP()		bfin_read16(USB_EP_NI3_RXMAXP)
+#define bfin_write_USB_EP_NI3_RXMAXP(val)	bfin_write16(USB_EP_NI3_RXMAXP, val)
+#define bfin_read_USB_EP_NI3_RXCSR()		bfin_read16(USB_EP_NI3_RXCSR)
+#define bfin_write_USB_EP_NI3_RXCSR(val)	bfin_write16(USB_EP_NI3_RXCSR, val)
+#define bfin_read_USB_EP_NI3_RXCOUNT()		bfin_read16(USB_EP_NI3_RXCOUNT)
+#define bfin_write_USB_EP_NI3_RXCOUNT(val)	bfin_write16(USB_EP_NI3_RXCOUNT, val)
+#define bfin_read_USB_EP_NI3_TXTYPE()		bfin_read16(USB_EP_NI3_TXTYPE)
+#define bfin_write_USB_EP_NI3_TXTYPE(val)	bfin_write16(USB_EP_NI3_TXTYPE, val)
+#define bfin_read_USB_EP_NI3_TXINTERVAL()	bfin_read16(USB_EP_NI3_TXINTERVAL)
+#define bfin_write_USB_EP_NI3_TXINTERVAL(val)	bfin_write16(USB_EP_NI3_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI3_RXTYPE()		bfin_read16(USB_EP_NI3_RXTYPE)
+#define bfin_write_USB_EP_NI3_RXTYPE(val)	bfin_write16(USB_EP_NI3_RXTYPE, val)
+#define bfin_read_USB_EP_NI3_RXINTERVAL()	bfin_read16(USB_EP_NI3_RXINTERVAL)
+#define bfin_write_USB_EP_NI3_RXINTERVAL(val)	bfin_write16(USB_EP_NI3_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI3_TXCOUNT()		bfin_read16(USB_EP_NI3_TXCOUNT)
+#define bfin_write_USB_EP_NI3_TXCOUNT(val)	bfin_write16(USB_EP_NI3_TXCOUNT, val)
+
+/* USB Endpoint 4 Control Registers */
+
+#define bfin_read_USB_EP_NI4_TXMAXP()		bfin_read16(USB_EP_NI4_TXMAXP)
+#define bfin_write_USB_EP_NI4_TXMAXP(val)	bfin_write16(USB_EP_NI4_TXMAXP, val)
+#define bfin_read_USB_EP_NI4_TXCSR()		bfin_read16(USB_EP_NI4_TXCSR)
+#define bfin_write_USB_EP_NI4_TXCSR(val)	bfin_write16(USB_EP_NI4_TXCSR, val)
+#define bfin_read_USB_EP_NI4_RXMAXP()		bfin_read16(USB_EP_NI4_RXMAXP)
+#define bfin_write_USB_EP_NI4_RXMAXP(val)	bfin_write16(USB_EP_NI4_RXMAXP, val)
+#define bfin_read_USB_EP_NI4_RXCSR()		bfin_read16(USB_EP_NI4_RXCSR)
+#define bfin_write_USB_EP_NI4_RXCSR(val)	bfin_write16(USB_EP_NI4_RXCSR, val)
+#define bfin_read_USB_EP_NI4_RXCOUNT()		bfin_read16(USB_EP_NI4_RXCOUNT)
+#define bfin_write_USB_EP_NI4_RXCOUNT(val)	bfin_write16(USB_EP_NI4_RXCOUNT, val)
+#define bfin_read_USB_EP_NI4_TXTYPE()		bfin_read16(USB_EP_NI4_TXTYPE)
+#define bfin_write_USB_EP_NI4_TXTYPE(val)	bfin_write16(USB_EP_NI4_TXTYPE, val)
+#define bfin_read_USB_EP_NI4_TXINTERVAL()	bfin_read16(USB_EP_NI4_TXINTERVAL)
+#define bfin_write_USB_EP_NI4_TXINTERVAL(val)	bfin_write16(USB_EP_NI4_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI4_RXTYPE()		bfin_read16(USB_EP_NI4_RXTYPE)
+#define bfin_write_USB_EP_NI4_RXTYPE(val)	bfin_write16(USB_EP_NI4_RXTYPE, val)
+#define bfin_read_USB_EP_NI4_RXINTERVAL()	bfin_read16(USB_EP_NI4_RXINTERVAL)
+#define bfin_write_USB_EP_NI4_RXINTERVAL(val)	bfin_write16(USB_EP_NI4_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI4_TXCOUNT()		bfin_read16(USB_EP_NI4_TXCOUNT)
+#define bfin_write_USB_EP_NI4_TXCOUNT(val)	bfin_write16(USB_EP_NI4_TXCOUNT, val)
+
+/* USB Endpoint 5 Control Registers */
+
+#define bfin_read_USB_EP_NI5_TXMAXP()		bfin_read16(USB_EP_NI5_TXMAXP)
+#define bfin_write_USB_EP_NI5_TXMAXP(val)	bfin_write16(USB_EP_NI5_TXMAXP, val)
+#define bfin_read_USB_EP_NI5_TXCSR()		bfin_read16(USB_EP_NI5_TXCSR)
+#define bfin_write_USB_EP_NI5_TXCSR(val)	bfin_write16(USB_EP_NI5_TXCSR, val)
+#define bfin_read_USB_EP_NI5_RXMAXP()		bfin_read16(USB_EP_NI5_RXMAXP)
+#define bfin_write_USB_EP_NI5_RXMAXP(val)	bfin_write16(USB_EP_NI5_RXMAXP, val)
+#define bfin_read_USB_EP_NI5_RXCSR()		bfin_read16(USB_EP_NI5_RXCSR)
+#define bfin_write_USB_EP_NI5_RXCSR(val)	bfin_write16(USB_EP_NI5_RXCSR, val)
+#define bfin_read_USB_EP_NI5_RXCOUNT()		bfin_read16(USB_EP_NI5_RXCOUNT)
+#define bfin_write_USB_EP_NI5_RXCOUNT(val)	bfin_write16(USB_EP_NI5_RXCOUNT, val)
+#define bfin_read_USB_EP_NI5_TXTYPE()		bfin_read16(USB_EP_NI5_TXTYPE)
+#define bfin_write_USB_EP_NI5_TXTYPE(val)	bfin_write16(USB_EP_NI5_TXTYPE, val)
+#define bfin_read_USB_EP_NI5_TXINTERVAL()	bfin_read16(USB_EP_NI5_TXINTERVAL)
+#define bfin_write_USB_EP_NI5_TXINTERVAL(val)	bfin_write16(USB_EP_NI5_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI5_RXTYPE()		bfin_read16(USB_EP_NI5_RXTYPE)
+#define bfin_write_USB_EP_NI5_RXTYPE(val)	bfin_write16(USB_EP_NI5_RXTYPE, val)
+#define bfin_read_USB_EP_NI5_RXINTERVAL()	bfin_read16(USB_EP_NI5_RXINTERVAL)
+#define bfin_write_USB_EP_NI5_RXINTERVAL(val)	bfin_write16(USB_EP_NI5_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI5_TXCOUNT()		bfin_read16(USB_EP_NI5_TXCOUNT)
+#define bfin_write_USB_EP_NI5_TXCOUNT(val)	bfin_write16(USB_EP_NI5_TXCOUNT, val)
+
+/* USB Endpoint 6 Control Registers */
+
+#define bfin_read_USB_EP_NI6_TXMAXP()		bfin_read16(USB_EP_NI6_TXMAXP)
+#define bfin_write_USB_EP_NI6_TXMAXP(val)	bfin_write16(USB_EP_NI6_TXMAXP, val)
+#define bfin_read_USB_EP_NI6_TXCSR()		bfin_read16(USB_EP_NI6_TXCSR)
+#define bfin_write_USB_EP_NI6_TXCSR(val)	bfin_write16(USB_EP_NI6_TXCSR, val)
+#define bfin_read_USB_EP_NI6_RXMAXP()		bfin_read16(USB_EP_NI6_RXMAXP)
+#define bfin_write_USB_EP_NI6_RXMAXP(val)	bfin_write16(USB_EP_NI6_RXMAXP, val)
+#define bfin_read_USB_EP_NI6_RXCSR()		bfin_read16(USB_EP_NI6_RXCSR)
+#define bfin_write_USB_EP_NI6_RXCSR(val)	bfin_write16(USB_EP_NI6_RXCSR, val)
+#define bfin_read_USB_EP_NI6_RXCOUNT()		bfin_read16(USB_EP_NI6_RXCOUNT)
+#define bfin_write_USB_EP_NI6_RXCOUNT(val)	bfin_write16(USB_EP_NI6_RXCOUNT, val)
+#define bfin_read_USB_EP_NI6_TXTYPE()		bfin_read16(USB_EP_NI6_TXTYPE)
+#define bfin_write_USB_EP_NI6_TXTYPE(val)	bfin_write16(USB_EP_NI6_TXTYPE, val)
+#define bfin_read_USB_EP_NI6_TXINTERVAL()	bfin_read16(USB_EP_NI6_TXINTERVAL)
+#define bfin_write_USB_EP_NI6_TXINTERVAL(val)	bfin_write16(USB_EP_NI6_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI6_RXTYPE()		bfin_read16(USB_EP_NI6_RXTYPE)
+#define bfin_write_USB_EP_NI6_RXTYPE(val)	bfin_write16(USB_EP_NI6_RXTYPE, val)
+#define bfin_read_USB_EP_NI6_RXINTERVAL()	bfin_read16(USB_EP_NI6_RXINTERVAL)
+#define bfin_write_USB_EP_NI6_RXINTERVAL(val)	bfin_write16(USB_EP_NI6_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI6_TXCOUNT()		bfin_read16(USB_EP_NI6_TXCOUNT)
+#define bfin_write_USB_EP_NI6_TXCOUNT(val)	bfin_write16(USB_EP_NI6_TXCOUNT, val)
+
+/* USB Endpoint 7 Control Registers */
+
+#define bfin_read_USB_EP_NI7_TXMAXP()		bfin_read16(USB_EP_NI7_TXMAXP)
+#define bfin_write_USB_EP_NI7_TXMAXP(val)	bfin_write16(USB_EP_NI7_TXMAXP, val)
+#define bfin_read_USB_EP_NI7_TXCSR()		bfin_read16(USB_EP_NI7_TXCSR)
+#define bfin_write_USB_EP_NI7_TXCSR(val)	bfin_write16(USB_EP_NI7_TXCSR, val)
+#define bfin_read_USB_EP_NI7_RXMAXP()		bfin_read16(USB_EP_NI7_RXMAXP)
+#define bfin_write_USB_EP_NI7_RXMAXP(val)	bfin_write16(USB_EP_NI7_RXMAXP, val)
+#define bfin_read_USB_EP_NI7_RXCSR()		bfin_read16(USB_EP_NI7_RXCSR)
+#define bfin_write_USB_EP_NI7_RXCSR(val)	bfin_write16(USB_EP_NI7_RXCSR, val)
+#define bfin_read_USB_EP_NI7_RXCOUNT()		bfin_read16(USB_EP_NI7_RXCOUNT)
+#define bfin_write_USB_EP_NI7_RXCOUNT(val)	bfin_write16(USB_EP_NI7_RXCOUNT, val)
+#define bfin_read_USB_EP_NI7_TXTYPE()		bfin_read16(USB_EP_NI7_TXTYPE)
+#define bfin_write_USB_EP_NI7_TXTYPE(val)	bfin_write16(USB_EP_NI7_TXTYPE, val)
+#define bfin_read_USB_EP_NI7_TXINTERVAL()	bfin_read16(USB_EP_NI7_TXINTERVAL)
+#define bfin_write_USB_EP_NI7_TXINTERVAL(val)	bfin_write16(USB_EP_NI7_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_RXTYPE()		bfin_read16(USB_EP_NI7_RXTYPE)
+#define bfin_write_USB_EP_NI7_RXTYPE(val)	bfin_write16(USB_EP_NI7_RXTYPE, val)
+#define bfin_read_USB_EP_NI7_RXINTERVAL()	bfin_read16(USB_EP_NI7_RXINTERVAL)
+#define bfin_write_USB_EP_NI7_RXINTERVAL(val)	bfin_write16(USB_EP_NI7_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_TXCOUNT()		bfin_read16(USB_EP_NI7_TXCOUNT)
+#define bfin_write_USB_EP_NI7_TXCOUNT(val)	bfin_write16(USB_EP_NI7_TXCOUNT, val)
+
+#define bfin_read_USB_DMA_INTERRUPT()		bfin_read16(USB_DMA_INTERRUPT)
+#define bfin_write_USB_DMA_INTERRUPT(val)	bfin_write16(USB_DMA_INTERRUPT, val)
+
+/* USB Channel 0 Config Registers */
+
+#define bfin_read_USB_DMA0CONTROL()		bfin_read16(USB_DMA0CONTROL)
+#define bfin_write_USB_DMA0CONTROL(val)		bfin_write16(USB_DMA0CONTROL, val)
+#define bfin_read_USB_DMA0ADDRLOW()		bfin_read16(USB_DMA0ADDRLOW)
+#define bfin_write_USB_DMA0ADDRLOW(val)		bfin_write16(USB_DMA0ADDRLOW, val)
+#define bfin_read_USB_DMA0ADDRHIGH()		bfin_read16(USB_DMA0ADDRHIGH)
+#define bfin_write_USB_DMA0ADDRHIGH(val)	bfin_write16(USB_DMA0ADDRHIGH, val)
+#define bfin_read_USB_DMA0COUNTLOW()		bfin_read16(USB_DMA0COUNTLOW)
+#define bfin_write_USB_DMA0COUNTLOW(val)	bfin_write16(USB_DMA0COUNTLOW, val)
+#define bfin_read_USB_DMA0COUNTHIGH()		bfin_read16(USB_DMA0COUNTHIGH)
+#define bfin_write_USB_DMA0COUNTHIGH(val)	bfin_write16(USB_DMA0COUNTHIGH, val)
+
+/* USB Channel 1 Config Registers */
+
+#define bfin_read_USB_DMA1CONTROL()		bfin_read16(USB_DMA1CONTROL)
+#define bfin_write_USB_DMA1CONTROL(val)		bfin_write16(USB_DMA1CONTROL, val)
+#define bfin_read_USB_DMA1ADDRLOW()		bfin_read16(USB_DMA1ADDRLOW)
+#define bfin_write_USB_DMA1ADDRLOW(val)		bfin_write16(USB_DMA1ADDRLOW, val)
+#define bfin_read_USB_DMA1ADDRHIGH()		bfin_read16(USB_DMA1ADDRHIGH)
+#define bfin_write_USB_DMA1ADDRHIGH(val)	bfin_write16(USB_DMA1ADDRHIGH, val)
+#define bfin_read_USB_DMA1COUNTLOW()		bfin_read16(USB_DMA1COUNTLOW)
+#define bfin_write_USB_DMA1COUNTLOW(val)	bfin_write16(USB_DMA1COUNTLOW, val)
+#define bfin_read_USB_DMA1COUNTHIGH()		bfin_read16(USB_DMA1COUNTHIGH)
+#define bfin_write_USB_DMA1COUNTHIGH(val)	bfin_write16(USB_DMA1COUNTHIGH, val)
+
+/* USB Channel 2 Config Registers */
+
+#define bfin_read_USB_DMA2CONTROL()		bfin_read16(USB_DMA2CONTROL)
+#define bfin_write_USB_DMA2CONTROL(val)		bfin_write16(USB_DMA2CONTROL, val)
+#define bfin_read_USB_DMA2ADDRLOW()		bfin_read16(USB_DMA2ADDRLOW)
+#define bfin_write_USB_DMA2ADDRLOW(val)		bfin_write16(USB_DMA2ADDRLOW, val)
+#define bfin_read_USB_DMA2ADDRHIGH()		bfin_read16(USB_DMA2ADDRHIGH)
+#define bfin_write_USB_DMA2ADDRHIGH(val)	bfin_write16(USB_DMA2ADDRHIGH, val)
+#define bfin_read_USB_DMA2COUNTLOW()		bfin_read16(USB_DMA2COUNTLOW)
+#define bfin_write_USB_DMA2COUNTLOW(val)	bfin_write16(USB_DMA2COUNTLOW, val)
+#define bfin_read_USB_DMA2COUNTHIGH()		bfin_read16(USB_DMA2COUNTHIGH)
+#define bfin_write_USB_DMA2COUNTHIGH(val)	bfin_write16(USB_DMA2COUNTHIGH, val)
+
+/* USB Channel 3 Config Registers */
+
+#define bfin_read_USB_DMA3CONTROL()		bfin_read16(USB_DMA3CONTROL)
+#define bfin_write_USB_DMA3CONTROL(val)		bfin_write16(USB_DMA3CONTROL, val)
+#define bfin_read_USB_DMA3ADDRLOW()		bfin_read16(USB_DMA3ADDRLOW)
+#define bfin_write_USB_DMA3ADDRLOW(val)		bfin_write16(USB_DMA3ADDRLOW, val)
+#define bfin_read_USB_DMA3ADDRHIGH()		bfin_read16(USB_DMA3ADDRHIGH)
+#define bfin_write_USB_DMA3ADDRHIGH(val)	bfin_write16(USB_DMA3ADDRHIGH, val)
+#define bfin_read_USB_DMA3COUNTLOW()		bfin_read16(USB_DMA3COUNTLOW)
+#define bfin_write_USB_DMA3COUNTLOW(val)	bfin_write16(USB_DMA3COUNTLOW, val)
+#define bfin_read_USB_DMA3COUNTHIGH()		bfin_read16(USB_DMA3COUNTHIGH)
+#define bfin_write_USB_DMA3COUNTHIGH(val)	bfin_write16(USB_DMA3COUNTHIGH, val)
+
+/* USB Channel 4 Config Registers */
+
+#define bfin_read_USB_DMA4CONTROL()		bfin_read16(USB_DMA4CONTROL)
+#define bfin_write_USB_DMA4CONTROL(val)		bfin_write16(USB_DMA4CONTROL, val)
+#define bfin_read_USB_DMA4ADDRLOW()		bfin_read16(USB_DMA4ADDRLOW)
+#define bfin_write_USB_DMA4ADDRLOW(val)		bfin_write16(USB_DMA4ADDRLOW, val)
+#define bfin_read_USB_DMA4ADDRHIGH()		bfin_read16(USB_DMA4ADDRHIGH)
+#define bfin_write_USB_DMA4ADDRHIGH(val)	bfin_write16(USB_DMA4ADDRHIGH, val)
+#define bfin_read_USB_DMA4COUNTLOW()		bfin_read16(USB_DMA4COUNTLOW)
+#define bfin_write_USB_DMA4COUNTLOW(val)	bfin_write16(USB_DMA4COUNTLOW, val)
+#define bfin_read_USB_DMA4COUNTHIGH()		bfin_read16(USB_DMA4COUNTHIGH)
+#define bfin_write_USB_DMA4COUNTHIGH(val)	bfin_write16(USB_DMA4COUNTHIGH, val)
+
+/* USB Channel 5 Config Registers */
+
+#define bfin_read_USB_DMA5CONTROL()		bfin_read16(USB_DMA5CONTROL)
+#define bfin_write_USB_DMA5CONTROL(val)		bfin_write16(USB_DMA5CONTROL, val)
+#define bfin_read_USB_DMA5ADDRLOW()		bfin_read16(USB_DMA5ADDRLOW)
+#define bfin_write_USB_DMA5ADDRLOW(val)		bfin_write16(USB_DMA5ADDRLOW, val)
+#define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
+#define bfin_write_USB_DMA5ADDRHIGH(val)	bfin_write16(USB_DMA5ADDRHIGH, val)
+#define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
+#define bfin_write_USB_DMA5COUNTLOW(val)	bfin_write16(USB_DMA5COUNTLOW, val)
+#define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
+#define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
+
+/* USB Channel 6 Config Registers */
+
+#define bfin_read_USB_DMA6CONTROL()		bfin_read16(USB_DMA6CONTROL)
+#define bfin_write_USB_DMA6CONTROL(val)		bfin_write16(USB_DMA6CONTROL, val)
+#define bfin_read_USB_DMA6ADDRLOW()		bfin_read16(USB_DMA6ADDRLOW)
+#define bfin_write_USB_DMA6ADDRLOW(val)		bfin_write16(USB_DMA6ADDRLOW, val)
+#define bfin_read_USB_DMA6ADDRHIGH()		bfin_read16(USB_DMA6ADDRHIGH)
+#define bfin_write_USB_DMA6ADDRHIGH(val)	bfin_write16(USB_DMA6ADDRHIGH, val)
+#define bfin_read_USB_DMA6COUNTLOW()		bfin_read16(USB_DMA6COUNTLOW)
+#define bfin_write_USB_DMA6COUNTLOW(val)	bfin_write16(USB_DMA6COUNTLOW, val)
+#define bfin_read_USB_DMA6COUNTHIGH()		bfin_read16(USB_DMA6COUNTHIGH)
+#define bfin_write_USB_DMA6COUNTHIGH(val)	bfin_write16(USB_DMA6COUNTHIGH, val)
+
+/* USB Channel 7 Config Registers */
+
+#define bfin_read_USB_DMA7CONTROL()		bfin_read16(USB_DMA7CONTROL)
+#define bfin_write_USB_DMA7CONTROL(val)		bfin_write16(USB_DMA7CONTROL, val)
+#define bfin_read_USB_DMA7ADDRLOW()		bfin_read16(USB_DMA7ADDRLOW)
+#define bfin_write_USB_DMA7ADDRLOW(val)		bfin_write16(USB_DMA7ADDRLOW, val)
+#define bfin_read_USB_DMA7ADDRHIGH()		bfin_read16(USB_DMA7ADDRHIGH)
+#define bfin_write_USB_DMA7ADDRHIGH(val)	bfin_write16(USB_DMA7ADDRHIGH, val)
+#define bfin_read_USB_DMA7COUNTLOW()		bfin_read16(USB_DMA7COUNTLOW)
+#define bfin_write_USB_DMA7COUNTLOW(val)	bfin_write16(USB_DMA7COUNTLOW, val)
+#define bfin_read_USB_DMA7COUNTHIGH()		bfin_read16(USB_DMA7COUNTHIGH)
+#define bfin_write_USB_DMA7COUNTHIGH(val)	bfin_write16(USB_DMA7COUNTHIGH, val)
+
+#endif /* _CDEF_BF527_H */
diff --git a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
new file mode 100644
index 0000000..5f801a0
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
@@ -0,0 +1,1187 @@
+/*
+ * File:         include/asm-blackfin/mach-bf527/cdefBF52x_base.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF52X_H
+
+#include "defBF52x_base.h"
+
+/* ==== begin from cdefBF534.h ==== */
+
+/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
+#define bfin_read_PLL_CTL()			bfin_read16(PLL_CTL)
+#define bfin_write_PLL_CTL(val)			bfin_write16(PLL_CTL, val)
+#define bfin_read_PLL_DIV()			bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val)			bfin_write16(PLL_DIV, val)
+#define bfin_read_VR_CTL()			bfin_read16(VR_CTL)
+#define bfin_write_VR_CTL(val)			bfin_write16(VR_CTL, val)
+#define bfin_read_PLL_STAT()			bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val)		bfin_write16(PLL_STAT, val)
+#define bfin_read_PLL_LOCKCNT()			bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val)		bfin_write16(PLL_LOCKCNT, val)
+#define bfin_read_CHIPID()			bfin_read16(CHIPID)
+#define bfin_write_CHIPID(val)			bfin_write16(CHIPID, val)
+
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)							*/
+#define bfin_read_SWRST()			bfin_read16(SWRST)
+#define bfin_write_SWRST(val)			bfin_write16(SWRST, val)
+#define bfin_read_SYSCR()			bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val)			bfin_write16(SYSCR, val)
+
+#define bfin_read_SIC_RVECT()			bfin_read32(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val)		bfin_write32(SIC_RVECT, val)
+#define bfin_read_SIC_IMASK0()			bfin_read32(SIC_IMASK0)
+#define bfin_write_SIC_IMASK0(val)		bfin_write32(SIC_IMASK0, val)
+/* legacy register name (below) provided for backwards code compatibility */
+#define bfin_read_SIC_IMASK()			bfin_read32(SIC_IMASK)
+#define bfin_write_SIC_IMASK(val)		bfin_write32(SIC_IMASK, val)
+
+#define bfin_read_SIC_IAR0()			bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val)		bfin_write32(SIC_IAR0, val)
+#define bfin_read_SIC_IAR1()			bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val)		bfin_write32(SIC_IAR1, val)
+#define bfin_read_SIC_IAR2()			bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val)		bfin_write32(SIC_IAR2, val)
+#define bfin_read_SIC_IAR3()			bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val)		bfin_write32(SIC_IAR3, val)
+
+#define bfin_read_SIC_ISR0()			bfin_read32(SIC_ISR0)
+#define bfin_write_SIC_ISR0(val)		bfin_write32(SIC_ISR0, val)
+/* legacy register name (below) provided for backwards code compatibility */
+#define bfin_read_SIC_ISR()			bfin_read32(SIC_ISR)
+#define bfin_write_SIC_ISR(val)			bfin_write32(SIC_ISR, val)
+
+#define bfin_read_SIC_IWR0()			bfin_read32(SIC_IWR0)
+#define bfin_write_SIC_IWR0(val)		bfin_write32(SIC_IWR0, val)
+/* legacy register name (below) provided for backwards code compatibility */
+#define bfin_read_SIC_IWR()			bfin_read32(SIC_IWR)
+#define bfin_write_SIC_IWR(val)			bfin_write32(SIC_IWR, val)
+
+/* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */
+
+#define bfin_read_SIC_IMASK1()			bfin_read32(SIC_IMASK1)
+#define bfin_write_SIC_IMASK1(val)		bfin_write32(SIC_IMASK1, val)
+#define bfin_read_SIC_IAR4()			bfin_read32(SIC_IAR4)
+#define bfin_write_SIC_IAR4(val)		bfin_write32(SIC_IAR4, val)
+#define bfin_read_SIC_IAR5()			bfin_read32(SIC_IAR5)
+#define bfin_write_SIC_IAR5(val)		bfin_write32(SIC_IAR5, val)
+#define bfin_read_SIC_IAR6()			bfin_read32(SIC_IAR6)
+#define bfin_write_SIC_IAR6(val)		bfin_write32(SIC_IAR6, val)
+#define bfin_read_SIC_IAR7()			bfin_read32(SIC_IAR7)
+#define bfin_write_SIC_IAR7(val)		bfin_write32(SIC_IAR7, val)
+#define bfin_read_SIC_ISR1()			bfin_read32(SIC_ISR1)
+#define bfin_write_SIC_ISR1(val)		bfin_write32(SIC_ISR1, val)
+#define bfin_read_SIC_IWR1()			bfin_read32(SIC_IWR1)
+#define bfin_write_SIC_IWR1(val)		bfin_write32(SIC_IWR1, val)
+
+/* Watchdog Timer		(0xFFC00200 - 0xFFC002FF)									*/
+#define bfin_read_WDOG_CTL()			bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val)		bfin_write16(WDOG_CTL, val)
+#define bfin_read_WDOG_CNT()			bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val)		bfin_write32(WDOG_CNT, val)
+#define bfin_read_WDOG_STAT()			bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val)		bfin_write32(WDOG_STAT, val)
+
+
+/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
+#define bfin_read_RTC_STAT()			bfin_read32(RTC_STAT)
+#define bfin_write_RTC_STAT(val)		bfin_write32(RTC_STAT, val)
+#define bfin_read_RTC_ICTL()			bfin_read16(RTC_ICTL)
+#define bfin_write_RTC_ICTL(val)		bfin_write16(RTC_ICTL, val)
+#define bfin_read_RTC_ISTAT()			bfin_read16(RTC_ISTAT)
+#define bfin_write_RTC_ISTAT(val)		bfin_write16(RTC_ISTAT, val)
+#define bfin_read_RTC_SWCNT()			bfin_read16(RTC_SWCNT)
+#define bfin_write_RTC_SWCNT(val)		bfin_write16(RTC_SWCNT, val)
+#define bfin_read_RTC_ALARM()			bfin_read32(RTC_ALARM)
+#define bfin_write_RTC_ALARM(val)		bfin_write32(RTC_ALARM, val)
+#define bfin_read_RTC_FAST()			bfin_read16(RTC_FAST)
+#define bfin_write_RTC_FAST(val)		bfin_write16(RTC_FAST, val)
+#define bfin_read_RTC_PREN()			bfin_read16(RTC_PREN)
+#define bfin_write_RTC_PREN(val)		bfin_write16(RTC_PREN, val)
+
+
+/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
+#define bfin_read_UART0_THR()			bfin_read16(UART0_THR)
+#define bfin_write_UART0_THR(val)		bfin_write16(UART0_THR, val)
+#define bfin_read_UART0_RBR()			bfin_read16(UART0_RBR)
+#define bfin_write_UART0_RBR(val)		bfin_write16(UART0_RBR, val)
+#define bfin_read_UART0_DLL()			bfin_read16(UART0_DLL)
+#define bfin_write_UART0_DLL(val)		bfin_write16(UART0_DLL, val)
+#define bfin_read_UART0_IER()			bfin_read16(UART0_IER)
+#define bfin_write_UART0_IER(val)		bfin_write16(UART0_IER, val)
+#define bfin_read_UART0_DLH()			bfin_read16(UART0_DLH)
+#define bfin_write_UART0_DLH(val)		bfin_write16(UART0_DLH, val)
+#define bfin_read_UART0_IIR()			bfin_read16(UART0_IIR)
+#define bfin_write_UART0_IIR(val)		bfin_write16(UART0_IIR, val)
+#define bfin_read_UART0_LCR()			bfin_read16(UART0_LCR)
+#define bfin_write_UART0_LCR(val)		bfin_write16(UART0_LCR, val)
+#define bfin_read_UART0_MCR()			bfin_read16(UART0_MCR)
+#define bfin_write_UART0_MCR(val)		bfin_write16(UART0_MCR, val)
+#define bfin_read_UART0_LSR()			bfin_read16(UART0_LSR)
+#define bfin_write_UART0_LSR(val)		bfin_write16(UART0_LSR, val)
+#define bfin_read_UART0_MSR()			bfin_read16(UART0_MSR)
+#define bfin_write_UART0_MSR(val)		bfin_write16(UART0_MSR, val)
+#define bfin_read_UART0_SCR()			bfin_read16(UART0_SCR)
+#define bfin_write_UART0_SCR(val)		bfin_write16(UART0_SCR, val)
+#define bfin_read_UART0_GCTL()			bfin_read16(UART0_GCTL)
+#define bfin_write_UART0_GCTL(val)		bfin_write16(UART0_GCTL, val)
+
+
+/* SPI Controller		(0xFFC00500 - 0xFFC005FF)									*/
+#define bfin_read_SPI_CTL()			bfin_read16(SPI_CTL)
+#define bfin_write_SPI_CTL(val)			bfin_write16(SPI_CTL, val)
+#define bfin_read_SPI_FLG()			bfin_read16(SPI_FLG)
+#define bfin_write_SPI_FLG(val)			bfin_write16(SPI_FLG, val)
+#define bfin_read_SPI_STAT()			bfin_read16(SPI_STAT)
+#define bfin_write_SPI_STAT(val)		bfin_write16(SPI_STAT, val)
+#define bfin_read_SPI_TDBR()			bfin_read16(SPI_TDBR)
+#define bfin_write_SPI_TDBR(val)		bfin_write16(SPI_TDBR, val)
+#define bfin_read_SPI_RDBR()			bfin_read16(SPI_RDBR)
+#define bfin_write_SPI_RDBR(val)		bfin_write16(SPI_RDBR, val)
+#define bfin_read_SPI_BAUD()			bfin_read16(SPI_BAUD)
+#define bfin_write_SPI_BAUD(val)		bfin_write16(SPI_BAUD, val)
+#define bfin_read_SPI_SHADOW()			bfin_read16(SPI_SHADOW)
+#define bfin_write_SPI_SHADOW(val)		bfin_write16(SPI_SHADOW, val)
+
+
+/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
+#define bfin_read_TIMER0_CONFIG()		bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val)		bfin_write16(TIMER0_CONFIG, val)
+#define bfin_read_TIMER0_COUNTER()		bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val)		bfin_write32(TIMER0_COUNTER, val)
+#define bfin_read_TIMER0_PERIOD()		bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val)		bfin_write32(TIMER0_PERIOD, val)
+#define bfin_read_TIMER0_WIDTH()		bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val)		bfin_write32(TIMER0_WIDTH, val)
+
+#define bfin_read_TIMER1_CONFIG()		bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val)		bfin_write16(TIMER1_CONFIG, val)
+#define bfin_read_TIMER1_COUNTER()		bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val)		bfin_write32(TIMER1_COUNTER, val)
+#define bfin_read_TIMER1_PERIOD()		bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val)		bfin_write32(TIMER1_PERIOD, val)
+#define bfin_read_TIMER1_WIDTH()		bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val)		bfin_write32(TIMER1_WIDTH, val)
+
+#define bfin_read_TIMER2_CONFIG()		bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val)		bfin_write16(TIMER2_CONFIG, val)
+#define bfin_read_TIMER2_COUNTER()		bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val)		bfin_write32(TIMER2_COUNTER, val)
+#define bfin_read_TIMER2_PERIOD()		bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val)		bfin_write32(TIMER2_PERIOD, val)
+#define bfin_read_TIMER2_WIDTH()		bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val)		bfin_write32(TIMER2_WIDTH, val)
+
+#define bfin_read_TIMER3_CONFIG()		bfin_read16(TIMER3_CONFIG)
+#define bfin_write_TIMER3_CONFIG(val)		bfin_write16(TIMER3_CONFIG, val)
+#define bfin_read_TIMER3_COUNTER()		bfin_read32(TIMER3_COUNTER)
+#define bfin_write_TIMER3_COUNTER(val)		bfin_write32(TIMER3_COUNTER, val)
+#define bfin_read_TIMER3_PERIOD()		bfin_read32(TIMER3_PERIOD)
+#define bfin_write_TIMER3_PERIOD(val)		bfin_write32(TIMER3_PERIOD, val)
+#define bfin_read_TIMER3_WIDTH()		bfin_read32(TIMER3_WIDTH)
+#define bfin_write_TIMER3_WIDTH(val)		bfin_write32(TIMER3_WIDTH, val)
+
+#define bfin_read_TIMER4_CONFIG()		bfin_read16(TIMER4_CONFIG)
+#define bfin_write_TIMER4_CONFIG(val)		bfin_write16(TIMER4_CONFIG, val)
+#define bfin_read_TIMER4_COUNTER()		bfin_read32(TIMER4_COUNTER)
+#define bfin_write_TIMER4_COUNTER(val)		bfin_write32(TIMER4_COUNTER, val)
+#define bfin_read_TIMER4_PERIOD()		bfin_read32(TIMER4_PERIOD)
+#define bfin_write_TIMER4_PERIOD(val)		bfin_write32(TIMER4_PERIOD, val)
+#define bfin_read_TIMER4_WIDTH()		bfin_read32(TIMER4_WIDTH)
+#define bfin_write_TIMER4_WIDTH(val)		bfin_write32(TIMER4_WIDTH, val)
+
+#define bfin_read_TIMER5_CONFIG()		bfin_read16(TIMER5_CONFIG)
+#define bfin_write_TIMER5_CONFIG(val)		bfin_write16(TIMER5_CONFIG, val)
+#define bfin_read_TIMER5_COUNTER()		bfin_read32(TIMER5_COUNTER)
+#define bfin_write_TIMER5_COUNTER(val)		bfin_write32(TIMER5_COUNTER, val)
+#define bfin_read_TIMER5_PERIOD()		bfin_read32(TIMER5_PERIOD)
+#define bfin_write_TIMER5_PERIOD(val)		bfin_write32(TIMER5_PERIOD, val)
+#define bfin_read_TIMER5_WIDTH()		bfin_read32(TIMER5_WIDTH)
+#define bfin_write_TIMER5_WIDTH(val)		bfin_write32(TIMER5_WIDTH, val)
+
+#define bfin_read_TIMER6_CONFIG()		bfin_read16(TIMER6_CONFIG)
+#define bfin_write_TIMER6_CONFIG(val)		bfin_write16(TIMER6_CONFIG, val)
+#define bfin_read_TIMER6_COUNTER()		bfin_read32(TIMER6_COUNTER)
+#define bfin_write_TIMER6_COUNTER(val)		bfin_write32(TIMER6_COUNTER, val)
+#define bfin_read_TIMER6_PERIOD()		bfin_read32(TIMER6_PERIOD)
+#define bfin_write_TIMER6_PERIOD(val)		bfin_write32(TIMER6_PERIOD, val)
+#define bfin_read_TIMER6_WIDTH()		bfin_read32(TIMER6_WIDTH)
+#define bfin_write_TIMER6_WIDTH(val)		bfin_write32(TIMER6_WIDTH, val)
+
+#define bfin_read_TIMER7_CONFIG()		bfin_read16(TIMER7_CONFIG)
+#define bfin_write_TIMER7_CONFIG(val)		bfin_write16(TIMER7_CONFIG, val)
+#define bfin_read_TIMER7_COUNTER()		bfin_read32(TIMER7_COUNTER)
+#define bfin_write_TIMER7_COUNTER(val)		bfin_write32(TIMER7_COUNTER, val)
+#define bfin_read_TIMER7_PERIOD()		bfin_read32(TIMER7_PERIOD)
+#define bfin_write_TIMER7_PERIOD(val)		bfin_write32(TIMER7_PERIOD, val)
+#define bfin_read_TIMER7_WIDTH()		bfin_read32(TIMER7_WIDTH)
+#define bfin_write_TIMER7_WIDTH(val)		bfin_write32(TIMER7_WIDTH, val)
+
+#define bfin_read_TIMER_ENABLE()		bfin_read16(TIMER_ENABLE)
+#define bfin_write_TIMER_ENABLE(val)		bfin_write16(TIMER_ENABLE, val)
+#define bfin_read_TIMER_DISABLE()		bfin_read16(TIMER_DISABLE)
+#define bfin_write_TIMER_DISABLE(val)		bfin_write16(TIMER_DISABLE, val)
+#define bfin_read_TIMER_STATUS()		bfin_read32(TIMER_STATUS)
+#define bfin_write_TIMER_STATUS(val)		bfin_write32(TIMER_STATUS, val)
+
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)								*/
+#define bfin_read_PORTFIO()			bfin_read16(PORTFIO)
+#define bfin_write_PORTFIO(val)			bfin_write16(PORTFIO, val)
+#define bfin_read_PORTFIO_CLEAR()		bfin_read16(PORTFIO_CLEAR)
+#define bfin_write_PORTFIO_CLEAR(val)		bfin_write16(PORTFIO_CLEAR, val)
+#define bfin_read_PORTFIO_SET()			bfin_read16(PORTFIO_SET)
+#define bfin_write_PORTFIO_SET(val)		bfin_write16(PORTFIO_SET, val)
+#define bfin_read_PORTFIO_TOGGLE()		bfin_read16(PORTFIO_TOGGLE)
+#define bfin_write_PORTFIO_TOGGLE(val)		bfin_write16(PORTFIO_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKA()		bfin_read16(PORTFIO_MASKA)
+#define bfin_write_PORTFIO_MASKA(val)		bfin_write16(PORTFIO_MASKA, val)
+#define bfin_read_PORTFIO_MASKA_CLEAR()		bfin_read16(PORTFIO_MASKA_CLEAR)
+#define bfin_write_PORTFIO_MASKA_CLEAR(val)	bfin_write16(PORTFIO_MASKA_CLEAR, val)
+#define bfin_read_PORTFIO_MASKA_SET()		bfin_read16(PORTFIO_MASKA_SET)
+#define bfin_write_PORTFIO_MASKA_SET(val)	bfin_write16(PORTFIO_MASKA_SET, val)
+#define bfin_read_PORTFIO_MASKA_TOGGLE()	bfin_read16(PORTFIO_MASKA_TOGGLE)
+#define bfin_write_PORTFIO_MASKA_TOGGLE(val)	bfin_write16(PORTFIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKB()		bfin_read16(PORTFIO_MASKB)
+#define bfin_write_PORTFIO_MASKB(val)		bfin_write16(PORTFIO_MASKB, val)
+#define bfin_read_PORTFIO_MASKB_CLEAR()		bfin_read16(PORTFIO_MASKB_CLEAR)
+#define bfin_write_PORTFIO_MASKB_CLEAR(val)	bfin_write16(PORTFIO_MASKB_CLEAR, val)
+#define bfin_read_PORTFIO_MASKB_SET()		bfin_read16(PORTFIO_MASKB_SET)
+#define bfin_write_PORTFIO_MASKB_SET(val)	bfin_write16(PORTFIO_MASKB_SET, val)
+#define bfin_read_PORTFIO_MASKB_TOGGLE()	bfin_read16(PORTFIO_MASKB_TOGGLE)
+#define bfin_write_PORTFIO_MASKB_TOGGLE(val)	bfin_write16(PORTFIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTFIO_DIR()			bfin_read16(PORTFIO_DIR)
+#define bfin_write_PORTFIO_DIR(val)		bfin_write16(PORTFIO_DIR, val)
+#define bfin_read_PORTFIO_POLAR()		bfin_read16(PORTFIO_POLAR)
+#define bfin_write_PORTFIO_POLAR(val)		bfin_write16(PORTFIO_POLAR, val)
+#define bfin_read_PORTFIO_EDGE()		bfin_read16(PORTFIO_EDGE)
+#define bfin_write_PORTFIO_EDGE(val)		bfin_write16(PORTFIO_EDGE, val)
+#define bfin_read_PORTFIO_BOTH()		bfin_read16(PORTFIO_BOTH)
+#define bfin_write_PORTFIO_BOTH(val)		bfin_write16(PORTFIO_BOTH, val)
+#define bfin_read_PORTFIO_INEN()		bfin_read16(PORTFIO_INEN)
+#define bfin_write_PORTFIO_INEN(val)		bfin_write16(PORTFIO_INEN, val)
+
+
+/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)								*/
+#define bfin_read_SPORT0_TCR1()			bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val)		bfin_write16(SPORT0_TCR1, val)
+#define bfin_read_SPORT0_TCR2()			bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val)		bfin_write16(SPORT0_TCR2, val)
+#define bfin_read_SPORT0_TCLKDIV()		bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val)		bfin_write16(SPORT0_TCLKDIV, val)
+#define bfin_read_SPORT0_TFSDIV()		bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val)		bfin_write16(SPORT0_TFSDIV, val)
+#define bfin_read_SPORT0_TX()			bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX32)
+#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX32, val)
+#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX32)
+#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX32, val)
+#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX16)
+#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX16, val)
+#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX16)
+#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX16, val)
+#define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
+#define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val)		bfin_write16(SPORT0_RCR2, val)
+#define bfin_read_SPORT0_RCLKDIV()		bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val)		bfin_write16(SPORT0_RCLKDIV, val)
+#define bfin_read_SPORT0_RFSDIV()		bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val)		bfin_write16(SPORT0_RFSDIV, val)
+#define bfin_read_SPORT0_STAT()			bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val)		bfin_write16(SPORT0_STAT, val)
+#define bfin_read_SPORT0_CHNL()			bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val)		bfin_write16(SPORT0_CHNL, val)
+#define bfin_read_SPORT0_MCMC1()		bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val)		bfin_write16(SPORT0_MCMC1, val)
+#define bfin_read_SPORT0_MCMC2()		bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val)		bfin_write16(SPORT0_MCMC2, val)
+#define bfin_read_SPORT0_MTCS0()		bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val)		bfin_write32(SPORT0_MTCS0, val)
+#define bfin_read_SPORT0_MTCS1()		bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val)		bfin_write32(SPORT0_MTCS1, val)
+#define bfin_read_SPORT0_MTCS2()		bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val)		bfin_write32(SPORT0_MTCS2, val)
+#define bfin_read_SPORT0_MTCS3()		bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val)		bfin_write32(SPORT0_MTCS3, val)
+#define bfin_read_SPORT0_MRCS0()		bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val)		bfin_write32(SPORT0_MRCS0, val)
+#define bfin_read_SPORT0_MRCS1()		bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val)		bfin_write32(SPORT0_MRCS1, val)
+#define bfin_read_SPORT0_MRCS2()		bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val)		bfin_write32(SPORT0_MRCS2, val)
+#define bfin_read_SPORT0_MRCS3()		bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val)		bfin_write32(SPORT0_MRCS3, val)
+
+
+/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)								*/
+#define bfin_read_SPORT1_TCR1()			bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val)		bfin_write16(SPORT1_TCR1, val)
+#define bfin_read_SPORT1_TCR2()			bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val)		bfin_write16(SPORT1_TCR2, val)
+#define bfin_read_SPORT1_TCLKDIV()		bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val)		bfin_write16(SPORT1_TCLKDIV, val)
+#define bfin_read_SPORT1_TFSDIV()		bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val)		bfin_write16(SPORT1_TFSDIV, val)
+#define bfin_read_SPORT1_TX()			bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val)		bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX()			bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val)		bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX32)
+#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX32, val)
+#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX32)
+#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX32, val)
+#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX16)
+#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX16, val)
+#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX16)
+#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX16, val)
+#define bfin_read_SPORT1_RCR1()			bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val)		bfin_write16(SPORT1_RCR1, val)
+#define bfin_read_SPORT1_RCR2()			bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val)		bfin_write16(SPORT1_RCR2, val)
+#define bfin_read_SPORT1_RCLKDIV()		bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val)		bfin_write16(SPORT1_RCLKDIV, val)
+#define bfin_read_SPORT1_RFSDIV()		bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val)		bfin_write16(SPORT1_RFSDIV, val)
+#define bfin_read_SPORT1_STAT()			bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val)		bfin_write16(SPORT1_STAT, val)
+#define bfin_read_SPORT1_CHNL()			bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val)		bfin_write16(SPORT1_CHNL, val)
+#define bfin_read_SPORT1_MCMC1()		bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val)		bfin_write16(SPORT1_MCMC1, val)
+#define bfin_read_SPORT1_MCMC2()		bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val)		bfin_write16(SPORT1_MCMC2, val)
+#define bfin_read_SPORT1_MTCS0()		bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val)		bfin_write32(SPORT1_MTCS0, val)
+#define bfin_read_SPORT1_MTCS1()		bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val)		bfin_write32(SPORT1_MTCS1, val)
+#define bfin_read_SPORT1_MTCS2()		bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val)		bfin_write32(SPORT1_MTCS2, val)
+#define bfin_read_SPORT1_MTCS3()		bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val)		bfin_write32(SPORT1_MTCS3, val)
+#define bfin_read_SPORT1_MRCS0()		bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val)		bfin_write32(SPORT1_MRCS0, val)
+#define bfin_read_SPORT1_MRCS1()		bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val)		bfin_write32(SPORT1_MRCS1, val)
+#define bfin_read_SPORT1_MRCS2()		bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val)		bfin_write32(SPORT1_MRCS2, val)
+#define bfin_read_SPORT1_MRCS3()		bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val)		bfin_write32(SPORT1_MRCS3, val)
+
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)							*/
+#define bfin_read_EBIU_AMGCTL()			bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val)		bfin_write16(EBIU_AMGCTL, val)
+#define bfin_read_EBIU_AMBCTL0()		bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val)		bfin_write32(EBIU_AMBCTL0, val)
+#define bfin_read_EBIU_AMBCTL1()		bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val)		bfin_write32(EBIU_AMBCTL1, val)
+#define bfin_read_EBIU_SDGCTL()			bfin_read32(EBIU_SDGCTL)
+#define bfin_write_EBIU_SDGCTL(val)		bfin_write32(EBIU_SDGCTL, val)
+#define bfin_read_EBIU_SDBCTL()			bfin_read16(EBIU_SDBCTL)
+#define bfin_write_EBIU_SDBCTL(val)		bfin_write16(EBIU_SDBCTL, val)
+#define bfin_read_EBIU_SDRRC()			bfin_read16(EBIU_SDRRC)
+#define bfin_write_EBIU_SDRRC(val)		bfin_write16(EBIU_SDRRC, val)
+#define bfin_read_EBIU_SDSTAT()			bfin_read16(EBIU_SDSTAT)
+#define bfin_write_EBIU_SDSTAT(val)		bfin_write16(EBIU_SDSTAT, val)
+
+
+/* DMA Traffic Control Registers													*/
+#define bfin_read_DMA_TC_PER()			bfin_read16(DMA_TC_PER)
+#define bfin_write_DMA_TC_PER(val)		bfin_write16(DMA_TC_PER, val)
+#define bfin_read_DMA_TC_CNT()			bfin_read16(DMA_TC_CNT)
+#define bfin_write_DMA_TC_CNT(val)		bfin_write16(DMA_TC_CNT, val)
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define bfin_read_DMA_TCPER()			bfin_read16(DMA_TCPER)
+#define bfin_write_DMA_TCPER(val)		bfin_write16(DMA_TCPER, val)
+#define bfin_read_DMA_TCCNT()			bfin_read16(DMA_TCCNT)
+#define bfin_write_DMA_TCCNT(val)		bfin_write16(DMA_TCCNT, val)
+
+/* DMA Controller																	*/
+#define bfin_read_DMA0_CONFIG()			bfin_read16(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val)		bfin_write16(DMA0_CONFIG, val)
+#define bfin_read_DMA0_NEXT_DESC_PTR()		bfin_read32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val)	bfin_write32(DMA0_NEXT_DESC_PTR, val)
+#define bfin_read_DMA0_START_ADDR()		bfin_read32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val)		bfin_write32(DMA0_START_ADDR, val)
+#define bfin_read_DMA0_X_COUNT()		bfin_read16(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val)		bfin_write16(DMA0_X_COUNT, val)
+#define bfin_read_DMA0_Y_COUNT()		bfin_read16(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val)		bfin_write16(DMA0_Y_COUNT, val)
+#define bfin_read_DMA0_X_MODIFY()		bfin_read16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val)		bfin_write16(DMA0_X_MODIFY, val)
+#define bfin_read_DMA0_Y_MODIFY()		bfin_read16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val)		bfin_write16(DMA0_Y_MODIFY, val)
+#define bfin_read_DMA0_CURR_DESC_PTR()		bfin_read32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val)	bfin_write32(DMA0_CURR_DESC_PTR, val)
+#define bfin_read_DMA0_CURR_ADDR()		bfin_read32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val)		bfin_write32(DMA0_CURR_ADDR, val)
+#define bfin_read_DMA0_CURR_X_COUNT()		bfin_read16(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val)	bfin_write16(DMA0_CURR_X_COUNT, val)
+#define bfin_read_DMA0_CURR_Y_COUNT()		bfin_read16(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val)	bfin_write16(DMA0_CURR_Y_COUNT, val)
+#define bfin_read_DMA0_IRQ_STATUS()		bfin_read16(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val)		bfin_write16(DMA0_IRQ_STATUS, val)
+#define bfin_read_DMA0_PERIPHERAL_MAP()		bfin_read16(DMA0_PERIPHERAL_MAP)
+#define bfin_write_DMA0_PERIPHERAL_MAP(val)	bfin_write16(DMA0_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA1_CONFIG()			bfin_read16(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val)		bfin_write16(DMA1_CONFIG, val)
+#define bfin_read_DMA1_NEXT_DESC_PTR()		bfin_read32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val)	bfin_write32(DMA1_NEXT_DESC_PTR, val)
+#define bfin_read_DMA1_START_ADDR()		bfin_read32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val)		bfin_write32(DMA1_START_ADDR, val)
+#define bfin_read_DMA1_X_COUNT()		bfin_read16(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val)		bfin_write16(DMA1_X_COUNT, val)
+#define bfin_read_DMA1_Y_COUNT()		bfin_read16(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val)		bfin_write16(DMA1_Y_COUNT, val)
+#define bfin_read_DMA1_X_MODIFY()		bfin_read16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val)		bfin_write16(DMA1_X_MODIFY, val)
+#define bfin_read_DMA1_Y_MODIFY()		bfin_read16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val)		bfin_write16(DMA1_Y_MODIFY, val)
+#define bfin_read_DMA1_CURR_DESC_PTR()		bfin_read32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val)	bfin_write32(DMA1_CURR_DESC_PTR, val)
+#define bfin_read_DMA1_CURR_ADDR()		bfin_read32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val)		bfin_write32(DMA1_CURR_ADDR, val)
+#define bfin_read_DMA1_CURR_X_COUNT()		bfin_read16(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val)	bfin_write16(DMA1_CURR_X_COUNT, val)
+#define bfin_read_DMA1_CURR_Y_COUNT()		bfin_read16(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val)	bfin_write16(DMA1_CURR_Y_COUNT, val)
+#define bfin_read_DMA1_IRQ_STATUS()		bfin_read16(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val)		bfin_write16(DMA1_IRQ_STATUS, val)
+#define bfin_read_DMA1_PERIPHERAL_MAP()		bfin_read16(DMA1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_PERIPHERAL_MAP(val)	bfin_write16(DMA1_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA2_CONFIG()			bfin_read16(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val)		bfin_write16(DMA2_CONFIG, val)
+#define bfin_read_DMA2_NEXT_DESC_PTR()		bfin_read32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val)	bfin_write32(DMA2_NEXT_DESC_PTR, val)
+#define bfin_read_DMA2_START_ADDR()		bfin_read32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val)		bfin_write32(DMA2_START_ADDR, val)
+#define bfin_read_DMA2_X_COUNT()		bfin_read16(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val)		bfin_write16(DMA2_X_COUNT, val)
+#define bfin_read_DMA2_Y_COUNT()		bfin_read16(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val)		bfin_write16(DMA2_Y_COUNT, val)
+#define bfin_read_DMA2_X_MODIFY()		bfin_read16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val)		bfin_write16(DMA2_X_MODIFY, val)
+#define bfin_read_DMA2_Y_MODIFY()		bfin_read16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val)		bfin_write16(DMA2_Y_MODIFY, val)
+#define bfin_read_DMA2_CURR_DESC_PTR()		bfin_read32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val)	bfin_write32(DMA2_CURR_DESC_PTR, val)
+#define bfin_read_DMA2_CURR_ADDR()		bfin_read32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val)		bfin_write32(DMA2_CURR_ADDR, val)
+#define bfin_read_DMA2_CURR_X_COUNT()		bfin_read16(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val)	bfin_write16(DMA2_CURR_X_COUNT, val)
+#define bfin_read_DMA2_CURR_Y_COUNT()		bfin_read16(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val)	bfin_write16(DMA2_CURR_Y_COUNT, val)
+#define bfin_read_DMA2_IRQ_STATUS()		bfin_read16(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val)		bfin_write16(DMA2_IRQ_STATUS, val)
+#define bfin_read_DMA2_PERIPHERAL_MAP()		bfin_read16(DMA2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_PERIPHERAL_MAP(val)	bfin_write16(DMA2_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA3_CONFIG()			bfin_read16(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val)		bfin_write16(DMA3_CONFIG, val)
+#define bfin_read_DMA3_NEXT_DESC_PTR()		bfin_read32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val)	bfin_write32(DMA3_NEXT_DESC_PTR, val)
+#define bfin_read_DMA3_START_ADDR()		bfin_read32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val)		bfin_write32(DMA3_START_ADDR, val)
+#define bfin_read_DMA3_X_COUNT()		bfin_read16(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val)		bfin_write16(DMA3_X_COUNT, val)
+#define bfin_read_DMA3_Y_COUNT()		bfin_read16(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val)		bfin_write16(DMA3_Y_COUNT, val)
+#define bfin_read_DMA3_X_MODIFY()		bfin_read16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val)		bfin_write16(DMA3_X_MODIFY, val)
+#define bfin_read_DMA3_Y_MODIFY()		bfin_read16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val)		bfin_write16(DMA3_Y_MODIFY, val)
+#define bfin_read_DMA3_CURR_DESC_PTR()		bfin_read32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val)	bfin_write32(DMA3_CURR_DESC_PTR, val)
+#define bfin_read_DMA3_CURR_ADDR()		bfin_read32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val)		bfin_write32(DMA3_CURR_ADDR, val)
+#define bfin_read_DMA3_CURR_X_COUNT()		bfin_read16(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val)	bfin_write16(DMA3_CURR_X_COUNT, val)
+#define bfin_read_DMA3_CURR_Y_COUNT()		bfin_read16(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val)	bfin_write16(DMA3_CURR_Y_COUNT, val)
+#define bfin_read_DMA3_IRQ_STATUS()		bfin_read16(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val)		bfin_write16(DMA3_IRQ_STATUS, val)
+#define bfin_read_DMA3_PERIPHERAL_MAP()		bfin_read16(DMA3_PERIPHERAL_MAP)
+#define bfin_write_DMA3_PERIPHERAL_MAP(val)	bfin_write16(DMA3_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA4_CONFIG()			bfin_read16(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val)		bfin_write16(DMA4_CONFIG, val)
+#define bfin_read_DMA4_NEXT_DESC_PTR()		bfin_read32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val)	bfin_write32(DMA4_NEXT_DESC_PTR, val)
+#define bfin_read_DMA4_START_ADDR()		bfin_read32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val)		bfin_write32(DMA4_START_ADDR, val)
+#define bfin_read_DMA4_X_COUNT()		bfin_read16(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val)		bfin_write16(DMA4_X_COUNT, val)
+#define bfin_read_DMA4_Y_COUNT()		bfin_read16(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val)		bfin_write16(DMA4_Y_COUNT, val)
+#define bfin_read_DMA4_X_MODIFY()		bfin_read16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val)		bfin_write16(DMA4_X_MODIFY, val)
+#define bfin_read_DMA4_Y_MODIFY()		bfin_read16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val)		bfin_write16(DMA4_Y_MODIFY, val)
+#define bfin_read_DMA4_CURR_DESC_PTR()		bfin_read32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val)	bfin_write32(DMA4_CURR_DESC_PTR, val)
+#define bfin_read_DMA4_CURR_ADDR()		bfin_read32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val)		bfin_write32(DMA4_CURR_ADDR, val)
+#define bfin_read_DMA4_CURR_X_COUNT()		bfin_read16(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val)	bfin_write16(DMA4_CURR_X_COUNT, val)
+#define bfin_read_DMA4_CURR_Y_COUNT()		bfin_read16(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val)	bfin_write16(DMA4_CURR_Y_COUNT, val)
+#define bfin_read_DMA4_IRQ_STATUS()		bfin_read16(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val)		bfin_write16(DMA4_IRQ_STATUS, val)
+#define bfin_read_DMA4_PERIPHERAL_MAP()		bfin_read16(DMA4_PERIPHERAL_MAP)
+#define bfin_write_DMA4_PERIPHERAL_MAP(val)	bfin_write16(DMA4_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA5_CONFIG()			bfin_read16(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val)		bfin_write16(DMA5_CONFIG, val)
+#define bfin_read_DMA5_NEXT_DESC_PTR()		bfin_read32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val)	bfin_write32(DMA5_NEXT_DESC_PTR, val)
+#define bfin_read_DMA5_START_ADDR()		bfin_read32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val)		bfin_write32(DMA5_START_ADDR, val)
+#define bfin_read_DMA5_X_COUNT()		bfin_read16(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val)		bfin_write16(DMA5_X_COUNT, val)
+#define bfin_read_DMA5_Y_COUNT()		bfin_read16(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val)		bfin_write16(DMA5_Y_COUNT, val)
+#define bfin_read_DMA5_X_MODIFY()		bfin_read16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val)		bfin_write16(DMA5_X_MODIFY, val)
+#define bfin_read_DMA5_Y_MODIFY()		bfin_read16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val)		bfin_write16(DMA5_Y_MODIFY, val)
+#define bfin_read_DMA5_CURR_DESC_PTR()		bfin_read32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val)	bfin_write32(DMA5_CURR_DESC_PTR, val)
+#define bfin_read_DMA5_CURR_ADDR()		bfin_read32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val)		bfin_write32(DMA5_CURR_ADDR, val)
+#define bfin_read_DMA5_CURR_X_COUNT()		bfin_read16(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val)	bfin_write16(DMA5_CURR_X_COUNT, val)
+#define bfin_read_DMA5_CURR_Y_COUNT()		bfin_read16(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val)	bfin_write16(DMA5_CURR_Y_COUNT, val)
+#define bfin_read_DMA5_IRQ_STATUS()		bfin_read16(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val)		bfin_write16(DMA5_IRQ_STATUS, val)
+#define bfin_read_DMA5_PERIPHERAL_MAP()		bfin_read16(DMA5_PERIPHERAL_MAP)
+#define bfin_write_DMA5_PERIPHERAL_MAP(val)	bfin_write16(DMA5_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA6_CONFIG()			bfin_read16(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val)		bfin_write16(DMA6_CONFIG, val)
+#define bfin_read_DMA6_NEXT_DESC_PTR()		bfin_read32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val)	bfin_write32(DMA6_NEXT_DESC_PTR, val)
+#define bfin_read_DMA6_START_ADDR()		bfin_read32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val)		bfin_write32(DMA6_START_ADDR, val)
+#define bfin_read_DMA6_X_COUNT()		bfin_read16(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val)		bfin_write16(DMA6_X_COUNT, val)
+#define bfin_read_DMA6_Y_COUNT()		bfin_read16(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val)		bfin_write16(DMA6_Y_COUNT, val)
+#define bfin_read_DMA6_X_MODIFY()		bfin_read16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val)		bfin_write16(DMA6_X_MODIFY, val)
+#define bfin_read_DMA6_Y_MODIFY()		bfin_read16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val)		bfin_write16(DMA6_Y_MODIFY, val)
+#define bfin_read_DMA6_CURR_DESC_PTR()		bfin_read32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val)	bfin_write32(DMA6_CURR_DESC_PTR, val)
+#define bfin_read_DMA6_CURR_ADDR()		bfin_read32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val)		bfin_write32(DMA6_CURR_ADDR, val)
+#define bfin_read_DMA6_CURR_X_COUNT()		bfin_read16(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val)	bfin_write16(DMA6_CURR_X_COUNT, val)
+#define bfin_read_DMA6_CURR_Y_COUNT()		bfin_read16(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val)	bfin_write16(DMA6_CURR_Y_COUNT, val)
+#define bfin_read_DMA6_IRQ_STATUS()		bfin_read16(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val)		bfin_write16(DMA6_IRQ_STATUS, val)
+#define bfin_read_DMA6_PERIPHERAL_MAP()		bfin_read16(DMA6_PERIPHERAL_MAP)
+#define bfin_write_DMA6_PERIPHERAL_MAP(val)	bfin_write16(DMA6_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA7_CONFIG()			bfin_read16(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val)		bfin_write16(DMA7_CONFIG, val)
+#define bfin_read_DMA7_NEXT_DESC_PTR()		bfin_read32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val)	bfin_write32(DMA7_NEXT_DESC_PTR, val)
+#define bfin_read_DMA7_START_ADDR()		bfin_read32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val)		bfin_write32(DMA7_START_ADDR, val)
+#define bfin_read_DMA7_X_COUNT()		bfin_read16(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val)		bfin_write16(DMA7_X_COUNT, val)
+#define bfin_read_DMA7_Y_COUNT()		bfin_read16(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val)		bfin_write16(DMA7_Y_COUNT, val)
+#define bfin_read_DMA7_X_MODIFY()		bfin_read16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val)		bfin_write16(DMA7_X_MODIFY, val)
+#define bfin_read_DMA7_Y_MODIFY()		bfin_read16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val)		bfin_write16(DMA7_Y_MODIFY, val)
+#define bfin_read_DMA7_CURR_DESC_PTR()		bfin_read32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val)	bfin_write32(DMA7_CURR_DESC_PTR, val)
+#define bfin_read_DMA7_CURR_ADDR()		bfin_read32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val)		bfin_write32(DMA7_CURR_ADDR, val)
+#define bfin_read_DMA7_CURR_X_COUNT()		bfin_read16(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val)	bfin_write16(DMA7_CURR_X_COUNT, val)
+#define bfin_read_DMA7_CURR_Y_COUNT()		bfin_read16(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val)	bfin_write16(DMA7_CURR_Y_COUNT, val)
+#define bfin_read_DMA7_IRQ_STATUS()		bfin_read16(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val)		bfin_write16(DMA7_IRQ_STATUS, val)
+#define bfin_read_DMA7_PERIPHERAL_MAP()		bfin_read16(DMA7_PERIPHERAL_MAP)
+#define bfin_write_DMA7_PERIPHERAL_MAP(val)	bfin_write16(DMA7_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA8_CONFIG()			bfin_read16(DMA8_CONFIG)
+#define bfin_write_DMA8_CONFIG(val)		bfin_write16(DMA8_CONFIG, val)
+#define bfin_read_DMA8_NEXT_DESC_PTR()		bfin_read32(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val)	bfin_write32(DMA8_NEXT_DESC_PTR, val)
+#define bfin_read_DMA8_START_ADDR()		bfin_read32(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val)		bfin_write32(DMA8_START_ADDR, val)
+#define bfin_read_DMA8_X_COUNT()		bfin_read16(DMA8_X_COUNT)
+#define bfin_write_DMA8_X_COUNT(val)		bfin_write16(DMA8_X_COUNT, val)
+#define bfin_read_DMA8_Y_COUNT()		bfin_read16(DMA8_Y_COUNT)
+#define bfin_write_DMA8_Y_COUNT(val)		bfin_write16(DMA8_Y_COUNT, val)
+#define bfin_read_DMA8_X_MODIFY()		bfin_read16(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val)		bfin_write16(DMA8_X_MODIFY, val)
+#define bfin_read_DMA8_Y_MODIFY()		bfin_read16(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val)		bfin_write16(DMA8_Y_MODIFY, val)
+#define bfin_read_DMA8_CURR_DESC_PTR()		bfin_read32(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val)	bfin_write32(DMA8_CURR_DESC_PTR, val)
+#define bfin_read_DMA8_CURR_ADDR()		bfin_read32(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val)		bfin_write32(DMA8_CURR_ADDR, val)
+#define bfin_read_DMA8_CURR_X_COUNT()		bfin_read16(DMA8_CURR_X_COUNT)
+#define bfin_write_DMA8_CURR_X_COUNT(val)	bfin_write16(DMA8_CURR_X_COUNT, val)
+#define bfin_read_DMA8_CURR_Y_COUNT()		bfin_read16(DMA8_CURR_Y_COUNT)
+#define bfin_write_DMA8_CURR_Y_COUNT(val)	bfin_write16(DMA8_CURR_Y_COUNT, val)
+#define bfin_read_DMA8_IRQ_STATUS()		bfin_read16(DMA8_IRQ_STATUS)
+#define bfin_write_DMA8_IRQ_STATUS(val)		bfin_write16(DMA8_IRQ_STATUS, val)
+#define bfin_read_DMA8_PERIPHERAL_MAP()		bfin_read16(DMA8_PERIPHERAL_MAP)
+#define bfin_write_DMA8_PERIPHERAL_MAP(val)	bfin_write16(DMA8_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA9_CONFIG()			bfin_read16(DMA9_CONFIG)
+#define bfin_write_DMA9_CONFIG(val)		bfin_write16(DMA9_CONFIG, val)
+#define bfin_read_DMA9_NEXT_DESC_PTR()		bfin_read32(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val)	bfin_write32(DMA9_NEXT_DESC_PTR, val)
+#define bfin_read_DMA9_START_ADDR()		bfin_read32(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val)		bfin_write32(DMA9_START_ADDR, val)
+#define bfin_read_DMA9_X_COUNT()		bfin_read16(DMA9_X_COUNT)
+#define bfin_write_DMA9_X_COUNT(val)		bfin_write16(DMA9_X_COUNT, val)
+#define bfin_read_DMA9_Y_COUNT()		bfin_read16(DMA9_Y_COUNT)
+#define bfin_write_DMA9_Y_COUNT(val)		bfin_write16(DMA9_Y_COUNT, val)
+#define bfin_read_DMA9_X_MODIFY()		bfin_read16(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val)		bfin_write16(DMA9_X_MODIFY, val)
+#define bfin_read_DMA9_Y_MODIFY()		bfin_read16(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val)		bfin_write16(DMA9_Y_MODIFY, val)
+#define bfin_read_DMA9_CURR_DESC_PTR()		bfin_read32(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val)	bfin_write32(DMA9_CURR_DESC_PTR, val)
+#define bfin_read_DMA9_CURR_ADDR()		bfin_read32(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val)		bfin_write32(DMA9_CURR_ADDR, val)
+#define bfin_read_DMA9_CURR_X_COUNT()		bfin_read16(DMA9_CURR_X_COUNT)
+#define bfin_write_DMA9_CURR_X_COUNT(val)	bfin_write16(DMA9_CURR_X_COUNT, val)
+#define bfin_read_DMA9_CURR_Y_COUNT()		bfin_read16(DMA9_CURR_Y_COUNT)
+#define bfin_write_DMA9_CURR_Y_COUNT(val)	bfin_write16(DMA9_CURR_Y_COUNT, val)
+#define bfin_read_DMA9_IRQ_STATUS()		bfin_read16(DMA9_IRQ_STATUS)
+#define bfin_write_DMA9_IRQ_STATUS(val)		bfin_write16(DMA9_IRQ_STATUS, val)
+#define bfin_read_DMA9_PERIPHERAL_MAP()		bfin_read16(DMA9_PERIPHERAL_MAP)
+#define bfin_write_DMA9_PERIPHERAL_MAP(val)	bfin_write16(DMA9_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA10_CONFIG()		bfin_read16(DMA10_CONFIG)
+#define bfin_write_DMA10_CONFIG(val)		bfin_write16(DMA10_CONFIG, val)
+#define bfin_read_DMA10_NEXT_DESC_PTR()		bfin_read32(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val)	bfin_write32(DMA10_NEXT_DESC_PTR, val)
+#define bfin_read_DMA10_START_ADDR()		bfin_read32(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val)	bfin_write32(DMA10_START_ADDR, val)
+#define bfin_read_DMA10_X_COUNT()		bfin_read16(DMA10_X_COUNT)
+#define bfin_write_DMA10_X_COUNT(val)		bfin_write16(DMA10_X_COUNT, val)
+#define bfin_read_DMA10_Y_COUNT()		bfin_read16(DMA10_Y_COUNT)
+#define bfin_write_DMA10_Y_COUNT(val)		bfin_write16(DMA10_Y_COUNT, val)
+#define bfin_read_DMA10_X_MODIFY()		bfin_read16(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val)		bfin_write16(DMA10_X_MODIFY, val)
+#define bfin_read_DMA10_Y_MODIFY()		bfin_read16(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val)		bfin_write16(DMA10_Y_MODIFY, val)
+#define bfin_read_DMA10_CURR_DESC_PTR()		bfin_read32(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val)	bfin_write32(DMA10_CURR_DESC_PTR, val)
+#define bfin_read_DMA10_CURR_ADDR()		bfin_read32(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val)		bfin_write32(DMA10_CURR_ADDR, val)
+#define bfin_read_DMA10_CURR_X_COUNT()		bfin_read16(DMA10_CURR_X_COUNT)
+#define bfin_write_DMA10_CURR_X_COUNT(val)	bfin_write16(DMA10_CURR_X_COUNT, val)
+#define bfin_read_DMA10_CURR_Y_COUNT()		bfin_read16(DMA10_CURR_Y_COUNT)
+#define bfin_write_DMA10_CURR_Y_COUNT(val)	bfin_write16(DMA10_CURR_Y_COUNT, val)
+#define bfin_read_DMA10_IRQ_STATUS()		bfin_read16(DMA10_IRQ_STATUS)
+#define bfin_write_DMA10_IRQ_STATUS(val)	bfin_write16(DMA10_IRQ_STATUS, val)
+#define bfin_read_DMA10_PERIPHERAL_MAP()	bfin_read16(DMA10_PERIPHERAL_MAP)
+#define bfin_write_DMA10_PERIPHERAL_MAP(val)	bfin_write16(DMA10_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA11_CONFIG()		bfin_read16(DMA11_CONFIG)
+#define bfin_write_DMA11_CONFIG(val)		bfin_write16(DMA11_CONFIG, val)
+#define bfin_read_DMA11_NEXT_DESC_PTR()		bfin_read32(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val)	bfin_write32(DMA11_NEXT_DESC_PTR, val)
+#define bfin_read_DMA11_START_ADDR()		bfin_read32(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val)	bfin_write32(DMA11_START_ADDR, val)
+#define bfin_read_DMA11_X_COUNT()		bfin_read16(DMA11_X_COUNT)
+#define bfin_write_DMA11_X_COUNT(val)		bfin_write16(DMA11_X_COUNT, val)
+#define bfin_read_DMA11_Y_COUNT()		bfin_read16(DMA11_Y_COUNT)
+#define bfin_write_DMA11_Y_COUNT(val)		bfin_write16(DMA11_Y_COUNT, val)
+#define bfin_read_DMA11_X_MODIFY()		bfin_read16(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val)		bfin_write16(DMA11_X_MODIFY, val)
+#define bfin_read_DMA11_Y_MODIFY()		bfin_read16(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val)		bfin_write16(DMA11_Y_MODIFY, val)
+#define bfin_read_DMA11_CURR_DESC_PTR()		bfin_read32(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val)	bfin_write32(DMA11_CURR_DESC_PTR, val)
+#define bfin_read_DMA11_CURR_ADDR()		bfin_read32(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val)		bfin_write32(DMA11_CURR_ADDR, val)
+#define bfin_read_DMA11_CURR_X_COUNT()		bfin_read16(DMA11_CURR_X_COUNT)
+#define bfin_write_DMA11_CURR_X_COUNT(val)	bfin_write16(DMA11_CURR_X_COUNT, val)
+#define bfin_read_DMA11_CURR_Y_COUNT()		bfin_read16(DMA11_CURR_Y_COUNT)
+#define bfin_write_DMA11_CURR_Y_COUNT(val)	bfin_write16(DMA11_CURR_Y_COUNT, val)
+#define bfin_read_DMA11_IRQ_STATUS()		bfin_read16(DMA11_IRQ_STATUS)
+#define bfin_write_DMA11_IRQ_STATUS(val)	bfin_write16(DMA11_IRQ_STATUS, val)
+#define bfin_read_DMA11_PERIPHERAL_MAP()	bfin_read16(DMA11_PERIPHERAL_MAP)
+#define bfin_write_DMA11_PERIPHERAL_MAP(val)	bfin_write16(DMA11_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_D0_CONFIG()		bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val)		bfin_write16(MDMA_D0_CONFIG, val)
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR()	bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D0_START_ADDR()		bfin_read32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val)	bfin_write32(MDMA_D0_START_ADDR, val)
+#define bfin_read_MDMA_D0_X_COUNT()		bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val)		bfin_write16(MDMA_D0_X_COUNT, val)
+#define bfin_read_MDMA_D0_Y_COUNT()		bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val)		bfin_write16(MDMA_D0_Y_COUNT, val)
+#define bfin_read_MDMA_D0_X_MODIFY()		bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val)	bfin_write16(MDMA_D0_X_MODIFY, val)
+#define bfin_read_MDMA_D0_Y_MODIFY()		bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val)	bfin_write16(MDMA_D0_Y_MODIFY, val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR()	bfin_read32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val)	bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D0_CURR_ADDR()		bfin_read32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val)	bfin_write32(MDMA_D0_CURR_ADDR, val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT()	bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val)	bfin_write16(MDMA_D0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT()	bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val)	bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()		bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val)	bfin_write16(MDMA_D0_IRQ_STATUS, val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP()	bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D0_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_S0_CONFIG()		bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val)		bfin_write16(MDMA_S0_CONFIG, val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR()	bfin_read32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S0_START_ADDR()		bfin_read32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val)	bfin_write32(MDMA_S0_START_ADDR, val)
+#define bfin_read_MDMA_S0_X_COUNT()		bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val)		bfin_write16(MDMA_S0_X_COUNT, val)
+#define bfin_read_MDMA_S0_Y_COUNT()		bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val)		bfin_write16(MDMA_S0_Y_COUNT, val)
+#define bfin_read_MDMA_S0_X_MODIFY()		bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val)	bfin_write16(MDMA_S0_X_MODIFY, val)
+#define bfin_read_MDMA_S0_Y_MODIFY()		bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val)	bfin_write16(MDMA_S0_Y_MODIFY, val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR()	bfin_read32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val)	bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S0_CURR_ADDR()		bfin_read32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val)	bfin_write32(MDMA_S0_CURR_ADDR, val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT()	bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val)	bfin_write16(MDMA_S0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT()	bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val)	bfin_write16(MDMA_S0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()		bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val)	bfin_write16(MDMA_S0_IRQ_STATUS, val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP()	bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S0_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_D1_CONFIG()		bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val)		bfin_write16(MDMA_D1_CONFIG, val)
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR()	bfin_read32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D1_START_ADDR()		bfin_read32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val)	bfin_write32(MDMA_D1_START_ADDR, val)
+#define bfin_read_MDMA_D1_X_COUNT()		bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val)		bfin_write16(MDMA_D1_X_COUNT, val)
+#define bfin_read_MDMA_D1_Y_COUNT()		bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val)		bfin_write16(MDMA_D1_Y_COUNT, val)
+#define bfin_read_MDMA_D1_X_MODIFY()		bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val)	bfin_write16(MDMA_D1_X_MODIFY, val)
+#define bfin_read_MDMA_D1_Y_MODIFY()		bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val)	bfin_write16(MDMA_D1_Y_MODIFY, val)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR()	bfin_read32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val)	bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D1_CURR_ADDR()		bfin_read32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val)	bfin_write32(MDMA_D1_CURR_ADDR, val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT()	bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val)	bfin_write16(MDMA_D1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT()	bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val)	bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()		bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val)	bfin_write16(MDMA_D1_IRQ_STATUS, val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP()	bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D1_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_S1_CONFIG()		bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val)		bfin_write16(MDMA_S1_CONFIG, val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR()	bfin_read32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S1_START_ADDR()		bfin_read32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val)	bfin_write32(MDMA_S1_START_ADDR, val)
+#define bfin_read_MDMA_S1_X_COUNT()		bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val)		bfin_write16(MDMA_S1_X_COUNT, val)
+#define bfin_read_MDMA_S1_Y_COUNT()		bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val)		bfin_write16(MDMA_S1_Y_COUNT, val)
+#define bfin_read_MDMA_S1_X_MODIFY()		bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val)	bfin_write16(MDMA_S1_X_MODIFY, val)
+#define bfin_read_MDMA_S1_Y_MODIFY()		bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val)	bfin_write16(MDMA_S1_Y_MODIFY, val)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR()	bfin_read32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val)	bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S1_CURR_ADDR()		bfin_read32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val)	bfin_write32(MDMA_S1_CURR_ADDR, val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT()	bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val)	bfin_write16(MDMA_S1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT()	bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val)	bfin_write16(MDMA_S1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()		bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val)	bfin_write16(MDMA_S1_IRQ_STATUS, val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP()	bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S1_PERIPHERAL_MAP, val)
+
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)							*/
+#define bfin_read_PPI_CONTROL()			bfin_read16(PPI_CONTROL)
+#define bfin_write_PPI_CONTROL(val)		bfin_write16(PPI_CONTROL, val)
+#define bfin_read_PPI_STATUS()			bfin_read16(PPI_STATUS)
+#define bfin_write_PPI_STATUS(val)		bfin_write16(PPI_STATUS, val)
+#define bfin_read_PPI_DELAY()			bfin_read16(PPI_DELAY)
+#define bfin_write_PPI_DELAY(val)		bfin_write16(PPI_DELAY, val)
+#define bfin_read_PPI_COUNT()			bfin_read16(PPI_COUNT)
+#define bfin_write_PPI_COUNT(val)		bfin_write16(PPI_COUNT, val)
+#define bfin_read_PPI_FRAME()			bfin_read16(PPI_FRAME)
+#define bfin_write_PPI_FRAME(val)		bfin_write16(PPI_FRAME, val)
+
+
+/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
+#define bfin_read_TWI_CLKDIV()			bfin_read16(TWI_CLKDIV)
+#define bfin_write_TWI_CLKDIV(val)		bfin_write16(TWI_CLKDIV, val)
+#define bfin_read_TWI_CONTROL()			bfin_read16(TWI_CONTROL)
+#define bfin_write_TWI_CONTROL(val)		bfin_write16(TWI_CONTROL, val)
+#define bfin_read_TWI_SLAVE_CTL()		bfin_read16(TWI_SLAVE_CTL)
+#define bfin_write_TWI_SLAVE_CTL(val)		bfin_write16(TWI_SLAVE_CTL, val)
+#define bfin_read_TWI_SLAVE_STAT()		bfin_read16(TWI_SLAVE_STAT)
+#define bfin_write_TWI_SLAVE_STAT(val)		bfin_write16(TWI_SLAVE_STAT, val)
+#define bfin_read_TWI_SLAVE_ADDR()		bfin_read16(TWI_SLAVE_ADDR)
+#define bfin_write_TWI_SLAVE_ADDR(val)		bfin_write16(TWI_SLAVE_ADDR, val)
+#define bfin_read_TWI_MASTER_CTL()		bfin_read16(TWI_MASTER_CTL)
+#define bfin_write_TWI_MASTER_CTL(val)		bfin_write16(TWI_MASTER_CTL, val)
+#define bfin_read_TWI_MASTER_STAT()		bfin_read16(TWI_MASTER_STAT)
+#define bfin_write_TWI_MASTER_STAT(val)		bfin_write16(TWI_MASTER_STAT, val)
+#define bfin_read_TWI_MASTER_ADDR()		bfin_read16(TWI_MASTER_ADDR)
+#define bfin_write_TWI_MASTER_ADDR(val)		bfin_write16(TWI_MASTER_ADDR, val)
+#define bfin_read_TWI_INT_STAT()		bfin_read16(TWI_INT_STAT)
+#define bfin_write_TWI_INT_STAT(val)		bfin_write16(TWI_INT_STAT, val)
+#define bfin_read_TWI_INT_MASK()		bfin_read16(TWI_INT_MASK)
+#define bfin_write_TWI_INT_MASK(val)		bfin_write16(TWI_INT_MASK, val)
+#define bfin_read_TWI_FIFO_CTL()		bfin_read16(TWI_FIFO_CTL)
+#define bfin_write_TWI_FIFO_CTL(val)		bfin_write16(TWI_FIFO_CTL, val)
+#define bfin_read_TWI_FIFO_STAT()		bfin_read16(TWI_FIFO_STAT)
+#define bfin_write_TWI_FIFO_STAT(val)		bfin_write16(TWI_FIFO_STAT, val)
+#define bfin_read_TWI_XMT_DATA8()		bfin_read16(TWI_XMT_DATA8)
+#define bfin_write_TWI_XMT_DATA8(val)		bfin_write16(TWI_XMT_DATA8, val)
+#define bfin_read_TWI_XMT_DATA16()		bfin_read16(TWI_XMT_DATA16)
+#define bfin_write_TWI_XMT_DATA16(val)		bfin_write16(TWI_XMT_DATA16, val)
+#define bfin_read_TWI_RCV_DATA8()		bfin_read16(TWI_RCV_DATA8)
+#define bfin_write_TWI_RCV_DATA8(val)		bfin_write16(TWI_RCV_DATA8, val)
+#define bfin_read_TWI_RCV_DATA16()		bfin_read16(TWI_RCV_DATA16)
+#define bfin_write_TWI_RCV_DATA16(val)		bfin_write16(TWI_RCV_DATA16, val)
+
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)								*/
+#define bfin_read_PORTGIO()			bfin_read16(PORTGIO)
+#define bfin_write_PORTGIO(val)			bfin_write16(PORTGIO, val)
+#define bfin_read_PORTGIO_CLEAR()		bfin_read16(PORTGIO_CLEAR)
+#define bfin_write_PORTGIO_CLEAR(val)		bfin_write16(PORTGIO_CLEAR, val)
+#define bfin_read_PORTGIO_SET()			bfin_read16(PORTGIO_SET)
+#define bfin_write_PORTGIO_SET(val)		bfin_write16(PORTGIO_SET, val)
+#define bfin_read_PORTGIO_TOGGLE()		bfin_read16(PORTGIO_TOGGLE)
+#define bfin_write_PORTGIO_TOGGLE(val)		bfin_write16(PORTGIO_TOGGLE, val)
+#define bfin_read_PORTGIO_MASKA()		bfin_read16(PORTGIO_MASKA)
+#define bfin_write_PORTGIO_MASKA(val)		bfin_write16(PORTGIO_MASKA, val)
+#define bfin_read_PORTGIO_MASKA_CLEAR()		bfin_read16(PORTGIO_MASKA_CLEAR)
+#define bfin_write_PORTGIO_MASKA_CLEAR(val)	bfin_write16(PORTGIO_MASKA_CLEAR, val)
+#define bfin_read_PORTGIO_MASKA_SET()		bfin_read16(PORTGIO_MASKA_SET)
+#define bfin_write_PORTGIO_MASKA_SET(val)	bfin_write16(PORTGIO_MASKA_SET, val)
+#define bfin_read_PORTGIO_MASKA_TOGGLE()	bfin_read16(PORTGIO_MASKA_TOGGLE)
+#define bfin_write_PORTGIO_MASKA_TOGGLE(val)	bfin_write16(PORTGIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTGIO_MASKB()		bfin_read16(PORTGIO_MASKB)
+#define bfin_write_PORTGIO_MASKB(val)		bfin_write16(PORTGIO_MASKB, val)
+#define bfin_read_PORTGIO_MASKB_CLEAR()		bfin_read16(PORTGIO_MASKB_CLEAR)
+#define bfin_write_PORTGIO_MASKB_CLEAR(val)	bfin_write16(PORTGIO_MASKB_CLEAR, val)
+#define bfin_read_PORTGIO_MASKB_SET()		bfin_read16(PORTGIO_MASKB_SET)
+#define bfin_write_PORTGIO_MASKB_SET(val)	bfin_write16(PORTGIO_MASKB_SET, val)
+#define bfin_read_PORTGIO_MASKB_TOGGLE()	bfin_read16(PORTGIO_MASKB_TOGGLE)
+#define bfin_write_PORTGIO_MASKB_TOGGLE(val)	bfin_write16(PORTGIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTGIO_DIR()			bfin_read16(PORTGIO_DIR)
+#define bfin_write_PORTGIO_DIR(val)		bfin_write16(PORTGIO_DIR, val)
+#define bfin_read_PORTGIO_POLAR()		bfin_read16(PORTGIO_POLAR)
+#define bfin_write_PORTGIO_POLAR(val)		bfin_write16(PORTGIO_POLAR, val)
+#define bfin_read_PORTGIO_EDGE()		bfin_read16(PORTGIO_EDGE)
+#define bfin_write_PORTGIO_EDGE(val)		bfin_write16(PORTGIO_EDGE, val)
+#define bfin_read_PORTGIO_BOTH()		bfin_read16(PORTGIO_BOTH)
+#define bfin_write_PORTGIO_BOTH(val)		bfin_write16(PORTGIO_BOTH, val)
+#define bfin_read_PORTGIO_INEN()		bfin_read16(PORTGIO_INEN)
+#define bfin_write_PORTGIO_INEN(val)		bfin_write16(PORTGIO_INEN, val)
+
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)								*/
+#define bfin_read_PORTHIO()			bfin_read16(PORTHIO)
+#define bfin_write_PORTHIO(val)			bfin_write16(PORTHIO, val)
+#define bfin_read_PORTHIO_CLEAR()		bfin_read16(PORTHIO_CLEAR)
+#define bfin_write_PORTHIO_CLEAR(val)		bfin_write16(PORTHIO_CLEAR, val)
+#define bfin_read_PORTHIO_SET()			bfin_read16(PORTHIO_SET)
+#define bfin_write_PORTHIO_SET(val)		bfin_write16(PORTHIO_SET, val)
+#define bfin_read_PORTHIO_TOGGLE()		bfin_read16(PORTHIO_TOGGLE)
+#define bfin_write_PORTHIO_TOGGLE(val)		bfin_write16(PORTHIO_TOGGLE, val)
+#define bfin_read_PORTHIO_MASKA()		bfin_read16(PORTHIO_MASKA)
+#define bfin_write_PORTHIO_MASKA(val)		bfin_write16(PORTHIO_MASKA, val)
+#define bfin_read_PORTHIO_MASKA_CLEAR()		bfin_read16(PORTHIO_MASKA_CLEAR)
+#define bfin_write_PORTHIO_MASKA_CLEAR(val)	bfin_write16(PORTHIO_MASKA_CLEAR, val)
+#define bfin_read_PORTHIO_MASKA_SET()		bfin_read16(PORTHIO_MASKA_SET)
+#define bfin_write_PORTHIO_MASKA_SET(val)	bfin_write16(PORTHIO_MASKA_SET, val)
+#define bfin_read_PORTHIO_MASKA_TOGGLE()	bfin_read16(PORTHIO_MASKA_TOGGLE)
+#define bfin_write_PORTHIO_MASKA_TOGGLE(val)	bfin_write16(PORTHIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTHIO_MASKB()		bfin_read16(PORTHIO_MASKB)
+#define bfin_write_PORTHIO_MASKB(val)		bfin_write16(PORTHIO_MASKB, val)
+#define bfin_read_PORTHIO_MASKB_CLEAR()		bfin_read16(PORTHIO_MASKB_CLEAR)
+#define bfin_write_PORTHIO_MASKB_CLEAR(val)	bfin_write16(PORTHIO_MASKB_CLEAR, val)
+#define bfin_read_PORTHIO_MASKB_SET()		bfin_read16(PORTHIO_MASKB_SET)
+#define bfin_write_PORTHIO_MASKB_SET(val)	bfin_write16(PORTHIO_MASKB_SET, val)
+#define bfin_read_PORTHIO_MASKB_TOGGLE()	bfin_read16(PORTHIO_MASKB_TOGGLE)
+#define bfin_write_PORTHIO_MASKB_TOGGLE(val)	bfin_write16(PORTHIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTHIO_DIR()			bfin_read16(PORTHIO_DIR)
+#define bfin_write_PORTHIO_DIR(val)		bfin_write16(PORTHIO_DIR, val)
+#define bfin_read_PORTHIO_POLAR()		bfin_read16(PORTHIO_POLAR)
+#define bfin_write_PORTHIO_POLAR(val)		bfin_write16(PORTHIO_POLAR, val)
+#define bfin_read_PORTHIO_EDGE()		bfin_read16(PORTHIO_EDGE)
+#define bfin_write_PORTHIO_EDGE(val)		bfin_write16(PORTHIO_EDGE, val)
+#define bfin_read_PORTHIO_BOTH()		bfin_read16(PORTHIO_BOTH)
+#define bfin_write_PORTHIO_BOTH(val)		bfin_write16(PORTHIO_BOTH, val)
+#define bfin_read_PORTHIO_INEN()		bfin_read16(PORTHIO_INEN)
+#define bfin_write_PORTHIO_INEN(val)		bfin_write16(PORTHIO_INEN, val)
+
+
+/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
+#define bfin_read_UART1_THR()			bfin_read16(UART1_THR)
+#define bfin_write_UART1_THR(val)		bfin_write16(UART1_THR, val)
+#define bfin_read_UART1_RBR()			bfin_read16(UART1_RBR)
+#define bfin_write_UART1_RBR(val)		bfin_write16(UART1_RBR, val)
+#define bfin_read_UART1_DLL()			bfin_read16(UART1_DLL)
+#define bfin_write_UART1_DLL(val)		bfin_write16(UART1_DLL, val)
+#define bfin_read_UART1_IER()			bfin_read16(UART1_IER)
+#define bfin_write_UART1_IER(val)		bfin_write16(UART1_IER, val)
+#define bfin_read_UART1_DLH()			bfin_read16(UART1_DLH)
+#define bfin_write_UART1_DLH(val)		bfin_write16(UART1_DLH, val)
+#define bfin_read_UART1_IIR()			bfin_read16(UART1_IIR)
+#define bfin_write_UART1_IIR(val)		bfin_write16(UART1_IIR, val)
+#define bfin_read_UART1_LCR()			bfin_read16(UART1_LCR)
+#define bfin_write_UART1_LCR(val)		bfin_write16(UART1_LCR, val)
+#define bfin_read_UART1_MCR()			bfin_read16(UART1_MCR)
+#define bfin_write_UART1_MCR(val)		bfin_write16(UART1_MCR, val)
+#define bfin_read_UART1_LSR()			bfin_read16(UART1_LSR)
+#define bfin_write_UART1_LSR(val)		bfin_write16(UART1_LSR, val)
+#define bfin_read_UART1_MSR()			bfin_read16(UART1_MSR)
+#define bfin_write_UART1_MSR(val)		bfin_write16(UART1_MSR, val)
+#define bfin_read_UART1_SCR()			bfin_read16(UART1_SCR)
+#define bfin_write_UART1_SCR(val)		bfin_write16(UART1_SCR, val)
+#define bfin_read_UART1_GCTL()			bfin_read16(UART1_GCTL)
+#define bfin_write_UART1_GCTL(val)		bfin_write16(UART1_GCTL, val)
+
+/* Omit CAN register sets from the cdefBF534.h (CAN is not in the ADSP-BF52x processor) */
+
+/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)								*/
+#define bfin_read_PORTF_FER()			bfin_read16(PORTF_FER)
+#define bfin_write_PORTF_FER(val)		bfin_write16(PORTF_FER, val)
+#define bfin_read_PORTG_FER()			bfin_read16(PORTG_FER)
+#define bfin_write_PORTG_FER(val)		bfin_write16(PORTG_FER, val)
+#define bfin_read_PORTH_FER()			bfin_read16(PORTH_FER)
+#define bfin_write_PORTH_FER(val)		bfin_write16(PORTH_FER, val)
+#define bfin_read_PORT_MUX()			bfin_read16(PORT_MUX)
+#define bfin_write_PORT_MUX(val)		bfin_write16(PORT_MUX, val)
+
+
+/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)								*/
+#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
+#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
+#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
+#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
+#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
+#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
+#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
+#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
+#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
+#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
+#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
+#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
+#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
+#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
+
+#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
+#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
+#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
+#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
+#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
+#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
+#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
+#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
+#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
+#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
+#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
+#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
+#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
+#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
+
+/* ==== end from cdefBF534.h ==== */
+
+/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
+
+#define bfin_read_PORTF_MUX()			bfin_read16(PORTF_MUX)
+#define bfin_write_PORTF_MUX(val)		bfin_write16(PORTF_MUX, val)
+#define bfin_read_PORTG_MUX()			bfin_read16(PORTG_MUX)
+#define bfin_write_PORTG_MUX(val)		bfin_write16(PORTG_MUX, val)
+#define bfin_read_PORTH_MUX()			bfin_read16(PORTH_MUX)
+#define bfin_write_PORTH_MUX(val)		bfin_write16(PORTH_MUX, val)
+
+#define bfin_read_PORTF_DRIVE()			bfin_read16(PORTF_DRIVE)
+#define bfin_write_PORTF_DRIVE(val)		bfin_write16(PORTF_DRIVE, val)
+#define bfin_read_PORTG_DRIVE()			bfin_read16(PORTG_DRIVE)
+#define bfin_write_PORTG_DRIVE(val)		bfin_write16(PORTG_DRIVE, val)
+#define bfin_read_PORTH_DRIVE()			bfin_read16(PORTH_DRIVE)
+#define bfin_write_PORTH_DRIVE(val)		bfin_write16(PORTH_DRIVE, val)
+#define bfin_read_PORTF_SLEW()			bfin_read16(PORTF_SLEW)
+#define bfin_write_PORTF_SLEW(val)		bfin_write16(PORTF_SLEW, val)
+#define bfin_read_PORTG_SLEW()			bfin_read16(PORTG_SLEW)
+#define bfin_write_PORTG_SLEW(val)		bfin_write16(PORTG_SLEW, val)
+#define bfin_read_PORTH_SLEW()			bfin_read16(PORTH_SLEW)
+#define bfin_write_PORTH_SLEW(val)		bfin_write16(PORTH_SLEW, val)
+#define bfin_read_PORTF_HYSTERISIS()		bfin_read16(PORTF_HYSTERISIS)
+#define bfin_write_PORTF_HYSTERISIS(val)	bfin_write16(PORTF_HYSTERISIS, val)
+#define bfin_read_PORTG_HYSTERISIS()		bfin_read16(PORTG_HYSTERISIS)
+#define bfin_write_PORTG_HYSTERISIS(val)	bfin_write16(PORTG_HYSTERISIS, val)
+#define bfin_read_PORTH_HYSTERISIS()		bfin_read16(PORTH_HYSTERISIS)
+#define bfin_write_PORTH_HYSTERISIS(val)	bfin_write16(PORTH_HYSTERISIS, val)
+#define bfin_read_MISCPORT_DRIVE()		bfin_read16(MISCPORT_DRIVE)
+#define bfin_write_MISCPORT_DRIVE(val)		bfin_write16(MISCPORT_DRIVE, val)
+#define bfin_read_MISCPORT_SLEW()		bfin_read16(MISCPORT_SLEW)
+#define bfin_write_MISCPORT_SLEW(val)		bfin_write16(MISCPORT_SLEW, val)
+#define bfin_read_MISCPORT_HYSTERISIS()		bfin_read16(MISCPORT_HYSTERISIS)
+#define bfin_write_MISCPORT_HYSTERISIS(val)	bfin_write16(MISCPORT_HYSTERISIS, val)
+
+/* HOST Port Registers */
+
+#define bfin_read_HOST_CONTROL()		bfin_read16(HOST_CONTROL)
+#define bfin_write_HOST_CONTROL(val)		bfin_write16(HOST_CONTROL, val)
+#define bfin_read_HOST_STATUS()			bfin_read16(HOST_STATUS)
+#define bfin_write_HOST_STATUS(val)		bfin_write16(HOST_STATUS, val)
+#define bfin_read_HOST_TIMEOUT()		bfin_read16(HOST_TIMEOUT)
+#define bfin_write_HOST_TIMEOUT(val)		bfin_write16(HOST_TIMEOUT, val)
+
+/* Counter Registers */
+
+#define bfin_read_CNT_CONFIG()			bfin_read16(CNT_CONFIG)
+#define bfin_write_CNT_CONFIG(val)		bfin_write16(CNT_CONFIG, val)
+#define bfin_read_CNT_IMASK()			bfin_read16(CNT_IMASK)
+#define bfin_write_CNT_IMASK(val)		bfin_write16(CNT_IMASK, val)
+#define bfin_read_CNT_STATUS()			bfin_read16(CNT_STATUS)
+#define bfin_write_CNT_STATUS(val)		bfin_write16(CNT_STATUS, val)
+#define bfin_read_CNT_COMMAND()			bfin_read16(CNT_COMMAND)
+#define bfin_write_CNT_COMMAND(val)		bfin_write16(CNT_COMMAND, val)
+#define bfin_read_CNT_DEBOUNCE()		bfin_read16(CNT_DEBOUNCE)
+#define bfin_write_CNT_DEBOUNCE(val)		bfin_write16(CNT_DEBOUNCE, val)
+#define bfin_read_CNT_COUNTER()			bfin_read32(CNT_COUNTER)
+#define bfin_write_CNT_COUNTER(val)		bfin_write32(CNT_COUNTER, val)
+#define bfin_read_CNT_MAX()			bfin_read32(CNT_MAX)
+#define bfin_write_CNT_MAX(val)			bfin_write32(CNT_MAX, val)
+#define bfin_read_CNT_MIN()			bfin_read32(CNT_MIN)
+#define bfin_write_CNT_MIN(val)			bfin_write32(CNT_MIN, val)
+
+/* OTP/FUSE Registers */
+
+#define bfin_read_OTP_CONTROL()			bfin_read16(OTP_CONTROL)
+#define bfin_write_OTP_CONTROL(val)		bfin_write16(OTP_CONTROL, val)
+#define bfin_read_OTP_BEN()			bfin_read16(OTP_BEN)
+#define bfin_write_OTP_BEN(val)			bfin_write16(OTP_BEN, val)
+#define bfin_read_OTP_STATUS()			bfin_read16(OTP_STATUS)
+#define bfin_write_OTP_STATUS(val)		bfin_write16(OTP_STATUS, val)
+#define bfin_read_OTP_TIMING()			bfin_read32(OTP_TIMING)
+#define bfin_write_OTP_TIMING(val)		bfin_write32(OTP_TIMING, val)
+
+/* Security Registers */
+
+#define bfin_read_SECURE_SYSSWT()		bfin_read32(SECURE_SYSSWT)
+#define bfin_write_SECURE_SYSSWT(val)		bfin_write32(SECURE_SYSSWT, val)
+#define bfin_read_SECURE_CONTROL()		bfin_read16(SECURE_CONTROL)
+#define bfin_write_SECURE_CONTROL(val)		bfin_write16(SECURE_CONTROL, val)
+#define bfin_read_SECURE_STATUS()		bfin_read16(SECURE_STATUS)
+#define bfin_write_SECURE_STATUS(val)		bfin_write16(SECURE_STATUS, val)
+
+/* OTP Read/Write Data Buffer Registers */
+
+#define bfin_read_OTP_DATA0()			bfin_read32(OTP_DATA0)
+#define bfin_write_OTP_DATA0(val)		bfin_write32(OTP_DATA0, val)
+#define bfin_read_OTP_DATA1()			bfin_read32(OTP_DATA1)
+#define bfin_write_OTP_DATA1(val)		bfin_write32(OTP_DATA1, val)
+#define bfin_read_OTP_DATA2()			bfin_read32(OTP_DATA2)
+#define bfin_write_OTP_DATA2(val)		bfin_write32(OTP_DATA2, val)
+#define bfin_read_OTP_DATA3()			bfin_read32(OTP_DATA3)
+#define bfin_write_OTP_DATA3(val)		bfin_write32(OTP_DATA3, val)
+
+/* NFC Registers */
+
+#define bfin_read_NFC_CTL()			bfin_read16(NFC_CTL)
+#define bfin_write_NFC_CTL(val)			bfin_write16(NFC_CTL, val)
+#define bfin_read_NFC_STAT()			bfin_read16(NFC_STAT)
+#define bfin_write_NFC_STAT(val)		bfin_write16(NFC_STAT, val)
+#define bfin_read_NFC_IRQSTAT()			bfin_read16(NFC_IRQSTAT)
+#define bfin_write_NFC_IRQSTAT(val)		bfin_write16(NFC_IRQSTAT, val)
+#define bfin_read_NFC_IRQMASK()			bfin_read16(NFC_IRQMASK)
+#define bfin_write_NFC_IRQMASK(val)		bfin_write16(NFC_IRQMASK, val)
+#define bfin_read_NFC_ECC0()			bfin_read16(NFC_ECC0)
+#define bfin_write_NFC_ECC0(val)		bfin_write16(NFC_ECC0, val)
+#define bfin_read_NFC_ECC1()			bfin_read16(NFC_ECC1)
+#define bfin_write_NFC_ECC1(val)		bfin_write16(NFC_ECC1, val)
+#define bfin_read_NFC_ECC2()			bfin_read16(NFC_ECC2)
+#define bfin_write_NFC_ECC2(val)		bfin_write16(NFC_ECC2, val)
+#define bfin_read_NFC_ECC3()			bfin_read16(NFC_ECC3)
+#define bfin_write_NFC_ECC3(val)		bfin_write16(NFC_ECC3, val)
+#define bfin_read_NFC_COUNT()			bfin_read16(NFC_COUNT)
+#define bfin_write_NFC_COUNT(val)		bfin_write16(NFC_COUNT, val)
+#define bfin_read_NFC_RST()			bfin_read16(NFC_RST)
+#define bfin_write_NFC_RST(val)			bfin_write16(NFC_RST, val)
+#define bfin_read_NFC_PGCTL()			bfin_read16(NFC_PGCTL)
+#define bfin_write_NFC_PGCTL(val)		bfin_write16(NFC_PGCTL, val)
+#define bfin_read_NFC_READ()			bfin_read16(NFC_READ)
+#define bfin_write_NFC_READ(val)		bfin_write16(NFC_READ, val)
+#define bfin_read_NFC_ADDR()			bfin_read16(NFC_ADDR)
+#define bfin_write_NFC_ADDR(val)		bfin_write16(NFC_ADDR, val)
+#define bfin_read_NFC_CMD()			bfin_read16(NFC_CMD)
+#define bfin_write_NFC_CMD(val)			bfin_write16(NFC_CMD, val)
+#define bfin_read_NFC_DATA_WR()			bfin_read16(NFC_DATA_WR)
+#define bfin_write_NFC_DATA_WR(val)		bfin_write16(NFC_DATA_WR, val)
+#define bfin_read_NFC_DATA_RD()			bfin_read16(NFC_DATA_RD)
+#define bfin_write_NFC_DATA_RD(val)		bfin_write16(NFC_DATA_RD, val)
+
+#endif /* _CDEF_BF52X_H */
diff --git a/include/asm-blackfin/mach-bf527/defBF522.h b/include/asm-blackfin/mach-bf527/defBF522.h
new file mode 100644
index 0000000..9671d8f
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/defBF522.h
@@ -0,0 +1,42 @@
+/*
+ * File:         include/asm-blackfin/mach-bf527/defBF522.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF522_H
+#define _DEF_BF522_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF522 */
+
+/* Include defBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
+#include "defBF52x_base.h"
+
+#endif /* _DEF_BF522_H */
diff --git a/include/asm-blackfin/mach-bf527/defBF525.h b/include/asm-blackfin/mach-bf527/defBF525.h
new file mode 100644
index 0000000..6a375a0
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/defBF525.h
@@ -0,0 +1,713 @@
+/*
+ * File:         include/asm-blackfin/mach-bf527/defBF525.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF525_H
+#define _DEF_BF525_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF525 */
+
+/* Include defBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
+#include "defBF52x_base.h"
+
+/* The following are the #defines needed by ADSP-BF525 that are not in the common header */
+
+/* USB Control Registers */
+
+#define                        USB_FADDR  0xffc03800   /* Function address register */
+#define                        USB_POWER  0xffc03804   /* Power management register */
+#define                       USB_INTRTX  0xffc03808   /* Interrupt register for endpoint 0 and Tx endpoint 1 to 7 */
+#define                       USB_INTRRX  0xffc0380c   /* Interrupt register for Rx endpoints 1 to 7 */
+#define                      USB_INTRTXE  0xffc03810   /* Interrupt enable register for IntrTx */
+#define                      USB_INTRRXE  0xffc03814   /* Interrupt enable register for IntrRx */
+#define                      USB_INTRUSB  0xffc03818   /* Interrupt register for common USB interrupts */
+#define                     USB_INTRUSBE  0xffc0381c   /* Interrupt enable register for IntrUSB */
+#define                        USB_FRAME  0xffc03820   /* USB frame number */
+#define                        USB_INDEX  0xffc03824   /* Index register for selecting the indexed endpoint registers */
+#define                     USB_TESTMODE  0xffc03828   /* Enabled USB 20 test modes */
+#define                     USB_GLOBINTR  0xffc0382c   /* Global Interrupt Mask register and Wakeup Exception Interrupt */
+#define                   USB_GLOBAL_CTL  0xffc03830   /* Global Clock Control for the core */
+
+/* USB Packet Control Registers */
+
+#define                USB_TX_MAX_PACKET  0xffc03840   /* Maximum packet size for Host Tx endpoint */
+#define                         USB_CSR0  0xffc03844   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                        USB_TXCSR  0xffc03844   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                USB_RX_MAX_PACKET  0xffc03848   /* Maximum packet size for Host Rx endpoint */
+#define                        USB_RXCSR  0xffc0384c   /* Control Status register for Host Rx endpoint */
+#define                       USB_COUNT0  0xffc03850   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                      USB_RXCOUNT  0xffc03850   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                       USB_TXTYPE  0xffc03854   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint */
+#define                    USB_NAKLIMIT0  0xffc03858   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                   USB_TXINTERVAL  0xffc03858   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                       USB_RXTYPE  0xffc0385c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint */
+#define                   USB_RXINTERVAL  0xffc03860   /* Sets the polling interval for Interrupt and Isochronous transfers or the NAK response timeout on Bulk transfers */
+#define                      USB_TXCOUNT  0xffc03868   /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* USB Endpoint FIFO Registers */
+
+#define                     USB_EP0_FIFO  0xffc03880   /* Endpoint 0 FIFO */
+#define                     USB_EP1_FIFO  0xffc03888   /* Endpoint 1 FIFO */
+#define                     USB_EP2_FIFO  0xffc03890   /* Endpoint 2 FIFO */
+#define                     USB_EP3_FIFO  0xffc03898   /* Endpoint 3 FIFO */
+#define                     USB_EP4_FIFO  0xffc038a0   /* Endpoint 4 FIFO */
+#define                     USB_EP5_FIFO  0xffc038a8   /* Endpoint 5 FIFO */
+#define                     USB_EP6_FIFO  0xffc038b0   /* Endpoint 6 FIFO */
+#define                     USB_EP7_FIFO  0xffc038b8   /* Endpoint 7 FIFO */
+
+/* USB OTG Control Registers */
+
+#define                  USB_OTG_DEV_CTL  0xffc03900   /* OTG Device Control Register */
+#define                 USB_OTG_VBUS_IRQ  0xffc03904   /* OTG VBUS Control Interrupts */
+#define                USB_OTG_VBUS_MASK  0xffc03908   /* VBUS Control Interrupt Enable */
+
+/* USB Phy Control Registers */
+
+#define                     USB_LINKINFO  0xffc03948   /* Enables programming of some PHY-side delays */
+#define                        USB_VPLEN  0xffc0394c   /* Determines duration of VBUS pulse for VBUS charging */
+#define                      USB_HS_EOF1  0xffc03950   /* Time buffer for High-Speed transactions */
+#define                      USB_FS_EOF1  0xffc03954   /* Time buffer for Full-Speed transactions */
+#define                      USB_LS_EOF1  0xffc03958   /* Time buffer for Low-Speed transactions */
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define                   USB_APHY_CNTRL  0xffc039e0   /* Register that increases visibility of Analog PHY */
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define                   USB_APHY_CALIB  0xffc039e4   /* Register used to set some calibration values */
+
+#define                  USB_APHY_CNTRL2  0xffc039e8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define                     USB_PHY_TEST  0xffc039ec   /* Used for reducing simulation time and simplifies FIFO testability */
+
+#define                  USB_PLLOSC_CTRL  0xffc039f0   /* Used to program different parameters for USB PLL and Oscillator */
+#define                   USB_SRP_CLKDIV  0xffc039f4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
+
+/* USB Endpoint 0 Control Registers */
+
+#define                USB_EP_NI0_TXMAXP  0xffc03a00   /* Maximum packet size for Host Tx endpoint0 */
+#define                 USB_EP_NI0_TXCSR  0xffc03a04   /* Control Status register for endpoint 0 */
+#define                USB_EP_NI0_RXMAXP  0xffc03a08   /* Maximum packet size for Host Rx endpoint0 */
+#define                 USB_EP_NI0_RXCSR  0xffc03a0c   /* Control Status register for Host Rx endpoint0 */
+#define               USB_EP_NI0_RXCOUNT  0xffc03a10   /* Number of bytes received in endpoint 0 FIFO */
+#define                USB_EP_NI0_TXTYPE  0xffc03a14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint0 */
+#define            USB_EP_NI0_TXINTERVAL  0xffc03a18   /* Sets the NAK response timeout on Endpoint 0 */
+#define                USB_EP_NI0_RXTYPE  0xffc03a1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint0 */
+#define            USB_EP_NI0_RXINTERVAL  0xffc03a20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint0 */
+#define               USB_EP_NI0_TXCOUNT  0xffc03a28   /* Number of bytes to be written to the endpoint0 Tx FIFO */
+
+/* USB Endpoint 1 Control Registers */
+
+#define                USB_EP_NI1_TXMAXP  0xffc03a40   /* Maximum packet size for Host Tx endpoint1 */
+#define                 USB_EP_NI1_TXCSR  0xffc03a44   /* Control Status register for endpoint1 */
+#define                USB_EP_NI1_RXMAXP  0xffc03a48   /* Maximum packet size for Host Rx endpoint1 */
+#define                 USB_EP_NI1_RXCSR  0xffc03a4c   /* Control Status register for Host Rx endpoint1 */
+#define               USB_EP_NI1_RXCOUNT  0xffc03a50   /* Number of bytes received in endpoint1 FIFO */
+#define                USB_EP_NI1_TXTYPE  0xffc03a54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint1 */
+#define            USB_EP_NI1_TXINTERVAL  0xffc03a58   /* Sets the NAK response timeout on Endpoint1 */
+#define                USB_EP_NI1_RXTYPE  0xffc03a5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint1 */
+#define            USB_EP_NI1_RXINTERVAL  0xffc03a60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint1 */
+#define               USB_EP_NI1_TXCOUNT  0xffc03a68   /* Number of bytes to be written to the+H102 endpoint1 Tx FIFO */
+
+/* USB Endpoint 2 Control Registers */
+
+#define                USB_EP_NI2_TXMAXP  0xffc03a80   /* Maximum packet size for Host Tx endpoint2 */
+#define                 USB_EP_NI2_TXCSR  0xffc03a84   /* Control Status register for endpoint2 */
+#define                USB_EP_NI2_RXMAXP  0xffc03a88   /* Maximum packet size for Host Rx endpoint2 */
+#define                 USB_EP_NI2_RXCSR  0xffc03a8c   /* Control Status register for Host Rx endpoint2 */
+#define               USB_EP_NI2_RXCOUNT  0xffc03a90   /* Number of bytes received in endpoint2 FIFO */
+#define                USB_EP_NI2_TXTYPE  0xffc03a94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint2 */
+#define            USB_EP_NI2_TXINTERVAL  0xffc03a98   /* Sets the NAK response timeout on Endpoint2 */
+#define                USB_EP_NI2_RXTYPE  0xffc03a9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint2 */
+#define            USB_EP_NI2_RXINTERVAL  0xffc03aa0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint2 */
+#define               USB_EP_NI2_TXCOUNT  0xffc03aa8   /* Number of bytes to be written to the endpoint2 Tx FIFO */
+
+/* USB Endpoint 3 Control Registers */
+
+#define                USB_EP_NI3_TXMAXP  0xffc03ac0   /* Maximum packet size for Host Tx endpoint3 */
+#define                 USB_EP_NI3_TXCSR  0xffc03ac4   /* Control Status register for endpoint3 */
+#define                USB_EP_NI3_RXMAXP  0xffc03ac8   /* Maximum packet size for Host Rx endpoint3 */
+#define                 USB_EP_NI3_RXCSR  0xffc03acc   /* Control Status register for Host Rx endpoint3 */
+#define               USB_EP_NI3_RXCOUNT  0xffc03ad0   /* Number of bytes received in endpoint3 FIFO */
+#define                USB_EP_NI3_TXTYPE  0xffc03ad4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint3 */
+#define            USB_EP_NI3_TXINTERVAL  0xffc03ad8   /* Sets the NAK response timeout on Endpoint3 */
+#define                USB_EP_NI3_RXTYPE  0xffc03adc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint3 */
+#define            USB_EP_NI3_RXINTERVAL  0xffc03ae0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint3 */
+#define               USB_EP_NI3_TXCOUNT  0xffc03ae8   /* Number of bytes to be written to the H124endpoint3 Tx FIFO */
+
+/* USB Endpoint 4 Control Registers */
+
+#define                USB_EP_NI4_TXMAXP  0xffc03b00   /* Maximum packet size for Host Tx endpoint4 */
+#define                 USB_EP_NI4_TXCSR  0xffc03b04   /* Control Status register for endpoint4 */
+#define                USB_EP_NI4_RXMAXP  0xffc03b08   /* Maximum packet size for Host Rx endpoint4 */
+#define                 USB_EP_NI4_RXCSR  0xffc03b0c   /* Control Status register for Host Rx endpoint4 */
+#define               USB_EP_NI4_RXCOUNT  0xffc03b10   /* Number of bytes received in endpoint4 FIFO */
+#define                USB_EP_NI4_TXTYPE  0xffc03b14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint4 */
+#define            USB_EP_NI4_TXINTERVAL  0xffc03b18   /* Sets the NAK response timeout on Endpoint4 */
+#define                USB_EP_NI4_RXTYPE  0xffc03b1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint4 */
+#define            USB_EP_NI4_RXINTERVAL  0xffc03b20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint4 */
+#define               USB_EP_NI4_TXCOUNT  0xffc03b28   /* Number of bytes to be written to the endpoint4 Tx FIFO */
+
+/* USB Endpoint 5 Control Registers */
+
+#define                USB_EP_NI5_TXMAXP  0xffc03b40   /* Maximum packet size for Host Tx endpoint5 */
+#define                 USB_EP_NI5_TXCSR  0xffc03b44   /* Control Status register for endpoint5 */
+#define                USB_EP_NI5_RXMAXP  0xffc03b48   /* Maximum packet size for Host Rx endpoint5 */
+#define                 USB_EP_NI5_RXCSR  0xffc03b4c   /* Control Status register for Host Rx endpoint5 */
+#define               USB_EP_NI5_RXCOUNT  0xffc03b50   /* Number of bytes received in endpoint5 FIFO */
+#define                USB_EP_NI5_TXTYPE  0xffc03b54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint5 */
+#define            USB_EP_NI5_TXINTERVAL  0xffc03b58   /* Sets the NAK response timeout on Endpoint5 */
+#define                USB_EP_NI5_RXTYPE  0xffc03b5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint5 */
+#define            USB_EP_NI5_RXINTERVAL  0xffc03b60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint5 */
+#define               USB_EP_NI5_TXCOUNT  0xffc03b68   /* Number of bytes to be written to the endpoint5 Tx FIFO */
+
+/* USB Endpoint 6 Control Registers */
+
+#define                USB_EP_NI6_TXMAXP  0xffc03b80   /* Maximum packet size for Host Tx endpoint6 */
+#define                 USB_EP_NI6_TXCSR  0xffc03b84   /* Control Status register for endpoint6 */
+#define                USB_EP_NI6_RXMAXP  0xffc03b88   /* Maximum packet size for Host Rx endpoint6 */
+#define                 USB_EP_NI6_RXCSR  0xffc03b8c   /* Control Status register for Host Rx endpoint6 */
+#define               USB_EP_NI6_RXCOUNT  0xffc03b90   /* Number of bytes received in endpoint6 FIFO */
+#define                USB_EP_NI6_TXTYPE  0xffc03b94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint6 */
+#define            USB_EP_NI6_TXINTERVAL  0xffc03b98   /* Sets the NAK response timeout on Endpoint6 */
+#define                USB_EP_NI6_RXTYPE  0xffc03b9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint6 */
+#define            USB_EP_NI6_RXINTERVAL  0xffc03ba0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint6 */
+#define               USB_EP_NI6_TXCOUNT  0xffc03ba8   /* Number of bytes to be written to the endpoint6 Tx FIFO */
+
+/* USB Endpoint 7 Control Registers */
+
+#define                USB_EP_NI7_TXMAXP  0xffc03bc0   /* Maximum packet size for Host Tx endpoint7 */
+#define                 USB_EP_NI7_TXCSR  0xffc03bc4   /* Control Status register for endpoint7 */
+#define                USB_EP_NI7_RXMAXP  0xffc03bc8   /* Maximum packet size for Host Rx endpoint7 */
+#define                 USB_EP_NI7_RXCSR  0xffc03bcc   /* Control Status register for Host Rx endpoint7 */
+#define               USB_EP_NI7_RXCOUNT  0xffc03bd0   /* Number of bytes received in endpoint7 FIFO */
+#define                USB_EP_NI7_TXTYPE  0xffc03bd4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint7 */
+#define            USB_EP_NI7_TXINTERVAL  0xffc03bd8   /* Sets the NAK response timeout on Endpoint7 */
+#define                USB_EP_NI7_RXTYPE  0xffc03bdc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint7 */
+#define            USB_EP_NI7_RXINTERVAL  0xffc03bf0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint7 */
+#define               USB_EP_NI7_TXCOUNT  0xffc03bf8   /* Number of bytes to be written to the endpoint7 Tx FIFO */
+
+#define                USB_DMA_INTERRUPT  0xffc03c00   /* Indicates pending interrupts for the DMA channels */
+
+/* USB Channel 0 Config Registers */
+
+#define                  USB_DMA0CONTROL  0xffc03c04   /* DMA master channel 0 configuration */
+#define                  USB_DMA0ADDRLOW  0xffc03c08   /* Lower 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0ADDRHIGH  0xffc03c0c   /* Upper 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0COUNTLOW  0xffc03c10   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 0 */
+#define                USB_DMA0COUNTHIGH  0xffc03c14   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 0 */
+
+/* USB Channel 1 Config Registers */
+
+#define                  USB_DMA1CONTROL  0xffc03c24   /* DMA master channel 1 configuration */
+#define                  USB_DMA1ADDRLOW  0xffc03c28   /* Lower 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1ADDRHIGH  0xffc03c2c   /* Upper 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1COUNTLOW  0xffc03c30   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 1 */
+#define                USB_DMA1COUNTHIGH  0xffc03c34   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 1 */
+
+/* USB Channel 2 Config Registers */
+
+#define                  USB_DMA2CONTROL  0xffc03c44   /* DMA master channel 2 configuration */
+#define                  USB_DMA2ADDRLOW  0xffc03c48   /* Lower 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2ADDRHIGH  0xffc03c4c   /* Upper 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2COUNTLOW  0xffc03c50   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 2 */
+#define                USB_DMA2COUNTHIGH  0xffc03c54   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 2 */
+
+/* USB Channel 3 Config Registers */
+
+#define                  USB_DMA3CONTROL  0xffc03c64   /* DMA master channel 3 configuration */
+#define                  USB_DMA3ADDRLOW  0xffc03c68   /* Lower 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3ADDRHIGH  0xffc03c6c   /* Upper 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3COUNTLOW  0xffc03c70   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 3 */
+#define                USB_DMA3COUNTHIGH  0xffc03c74   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 3 */
+
+/* USB Channel 4 Config Registers */
+
+#define                  USB_DMA4CONTROL  0xffc03c84   /* DMA master channel 4 configuration */
+#define                  USB_DMA4ADDRLOW  0xffc03c88   /* Lower 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4ADDRHIGH  0xffc03c8c   /* Upper 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4COUNTLOW  0xffc03c90   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 4 */
+#define                USB_DMA4COUNTHIGH  0xffc03c94   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 4 */
+
+/* USB Channel 5 Config Registers */
+
+#define                  USB_DMA5CONTROL  0xffc03ca4   /* DMA master channel 5 configuration */
+#define                  USB_DMA5ADDRLOW  0xffc03ca8   /* Lower 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5ADDRHIGH  0xffc03cac   /* Upper 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5COUNTLOW  0xffc03cb0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 5 */
+#define                USB_DMA5COUNTHIGH  0xffc03cb4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 5 */
+
+/* USB Channel 6 Config Registers */
+
+#define                  USB_DMA6CONTROL  0xffc03cc4   /* DMA master channel 6 configuration */
+#define                  USB_DMA6ADDRLOW  0xffc03cc8   /* Lower 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6ADDRHIGH  0xffc03ccc   /* Upper 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6COUNTLOW  0xffc03cd0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 6 */
+#define                USB_DMA6COUNTHIGH  0xffc03cd4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 6 */
+
+/* USB Channel 7 Config Registers */
+
+#define                  USB_DMA7CONTROL  0xffc03ce4   /* DMA master channel 7 configuration */
+#define                  USB_DMA7ADDRLOW  0xffc03ce8   /* Lower 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7ADDRHIGH  0xffc03cec   /* Upper 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7COUNTLOW  0xffc03cf0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 7 */
+#define                USB_DMA7COUNTHIGH  0xffc03cf4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 7 */
+
+/* Bit masks for USB_FADDR */
+
+#define          FUNCTION_ADDRESS  0x7f       /* Function address */
+
+/* Bit masks for USB_POWER */
+
+#define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
+#define          nENABLE_SUSPENDM  0x0       
+#define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
+#define             nSUSPEND_MODE  0x0       
+#define               RESUME_MODE  0x4        /* DMA Mode */
+#define              nRESUME_MODE  0x0       
+#define                     RESET  0x8        /* Reset indicator */
+#define                    nRESET  0x0       
+#define                   HS_MODE  0x10       /* High Speed mode indicator */
+#define                  nHS_MODE  0x0       
+#define                 HS_ENABLE  0x20       /* high Speed Enable */
+#define                nHS_ENABLE  0x0       
+#define                 SOFT_CONN  0x40       /* Soft connect */
+#define                nSOFT_CONN  0x0       
+#define                ISO_UPDATE  0x80       /* Isochronous update */
+#define               nISO_UPDATE  0x0       
+
+/* Bit masks for USB_INTRTX */
+
+#define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
+#define                   nEP0_TX  0x0       
+#define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
+#define                   nEP1_TX  0x0       
+#define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
+#define                   nEP2_TX  0x0       
+#define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
+#define                   nEP3_TX  0x0       
+#define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
+#define                   nEP4_TX  0x0       
+#define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
+#define                   nEP5_TX  0x0       
+#define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
+#define                   nEP6_TX  0x0       
+#define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
+#define                   nEP7_TX  0x0       
+
+/* Bit masks for USB_INTRRX */
+
+#define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
+#define                   nEP1_RX  0x0       
+#define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
+#define                   nEP2_RX  0x0       
+#define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
+#define                   nEP3_RX  0x0       
+#define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
+#define                   nEP4_RX  0x0       
+#define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
+#define                   nEP5_RX  0x0       
+#define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
+#define                   nEP6_RX  0x0       
+#define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
+#define                   nEP7_RX  0x0       
+
+/* Bit masks for USB_INTRTXE */
+
+#define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
+#define                 nEP0_TX_E  0x0       
+#define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
+#define                 nEP1_TX_E  0x0       
+#define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
+#define                 nEP2_TX_E  0x0       
+#define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
+#define                 nEP3_TX_E  0x0       
+#define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
+#define                 nEP4_TX_E  0x0       
+#define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
+#define                 nEP5_TX_E  0x0       
+#define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
+#define                 nEP6_TX_E  0x0       
+#define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
+#define                 nEP7_TX_E  0x0       
+
+/* Bit masks for USB_INTRRXE */
+
+#define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
+#define                 nEP1_RX_E  0x0       
+#define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
+#define                 nEP2_RX_E  0x0       
+#define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
+#define                 nEP3_RX_E  0x0       
+#define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
+#define                 nEP4_RX_E  0x0       
+#define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
+#define                 nEP5_RX_E  0x0       
+#define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
+#define                 nEP6_RX_E  0x0       
+#define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
+#define                 nEP7_RX_E  0x0       
+
+/* Bit masks for USB_INTRUSB */
+
+#define                 SUSPEND_B  0x1        /* Suspend indicator */
+#define                nSUSPEND_B  0x0       
+#define                  RESUME_B  0x2        /* Resume indicator */
+#define                 nRESUME_B  0x0       
+#define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
+#define         nRESET_OR_BABLE_B  0x0       
+#define                     SOF_B  0x8        /* Start of frame */
+#define                    nSOF_B  0x0       
+#define                    CONN_B  0x10       /* Connection indicator */
+#define                   nCONN_B  0x0       
+#define                  DISCON_B  0x20       /* Disconnect indicator */
+#define                 nDISCON_B  0x0       
+#define             SESSION_REQ_B  0x40       /* Session Request */
+#define            nSESSION_REQ_B  0x0       
+#define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
+#define             nVBUS_ERROR_B  0x0       
+
+/* Bit masks for USB_INTRUSBE */
+
+#define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
+#define               nSUSPEND_BE  0x0       
+#define                 RESUME_BE  0x2        /* Resume indicator int enable */
+#define                nRESUME_BE  0x0       
+#define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
+#define        nRESET_OR_BABLE_BE  0x0       
+#define                    SOF_BE  0x8        /* Start of frame int enable */
+#define                   nSOF_BE  0x0       
+#define                   CONN_BE  0x10       /* Connection indicator int enable */
+#define                  nCONN_BE  0x0       
+#define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
+#define                nDISCON_BE  0x0       
+#define            SESSION_REQ_BE  0x40       /* Session Request int enable */
+#define           nSESSION_REQ_BE  0x0       
+#define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
+#define            nVBUS_ERROR_BE  0x0       
+
+/* Bit masks for USB_FRAME */
+
+#define              FRAME_NUMBER  0x7ff      /* Frame number */
+
+/* Bit masks for USB_INDEX */
+
+#define         SELECTED_ENDPOINT  0xf        /* selected endpoint */
+
+/* Bit masks for USB_GLOBAL_CTL */
+
+#define                GLOBAL_ENA  0x1        /* enables USB module */
+#define               nGLOBAL_ENA  0x0       
+#define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
+#define               nEP1_TX_ENA  0x0       
+#define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
+#define               nEP2_TX_ENA  0x0       
+#define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
+#define               nEP3_TX_ENA  0x0       
+#define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
+#define               nEP4_TX_ENA  0x0       
+#define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
+#define               nEP5_TX_ENA  0x0       
+#define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
+#define               nEP6_TX_ENA  0x0       
+#define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
+#define               nEP7_TX_ENA  0x0       
+#define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
+#define               nEP1_RX_ENA  0x0       
+#define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
+#define               nEP2_RX_ENA  0x0       
+#define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
+#define               nEP3_RX_ENA  0x0       
+#define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
+#define               nEP4_RX_ENA  0x0       
+#define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
+#define               nEP5_RX_ENA  0x0       
+#define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
+#define               nEP6_RX_ENA  0x0       
+#define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
+#define               nEP7_RX_ENA  0x0       
+
+/* Bit masks for USB_OTG_DEV_CTL */
+
+#define                   SESSION  0x1        /* session indicator */
+#define                  nSESSION  0x0       
+#define                  HOST_REQ  0x2        /* Host negotiation request */
+#define                 nHOST_REQ  0x0       
+#define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
+#define                nHOST_MODE  0x0       
+#define                     VBUS0  0x8        /* Vbus level indicator[0] */
+#define                    nVBUS0  0x0       
+#define                     VBUS1  0x10       /* Vbus level indicator[1] */
+#define                    nVBUS1  0x0       
+#define                     LSDEV  0x20       /* Low-speed indicator */
+#define                    nLSDEV  0x0       
+#define                     FSDEV  0x40       /* Full or High-speed indicator */
+#define                    nFSDEV  0x0       
+#define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
+#define                 nB_DEVICE  0x0       
+
+/* Bit masks for USB_OTG_VBUS_IRQ */
+
+#define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
+#define            nDRIVE_VBUS_ON  0x0       
+#define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
+#define           nDRIVE_VBUS_OFF  0x0       
+#define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
+#define          nCHRG_VBUS_START  0x0       
+#define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
+#define            nCHRG_VBUS_END  0x0       
+#define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
+#define       nDISCHRG_VBUS_START  0x0       
+#define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
+#define         nDISCHRG_VBUS_END  0x0       
+
+/* Bit masks for USB_OTG_VBUS_MASK */
+
+#define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
+#define        nDRIVE_VBUS_ON_ENA  0x0       
+#define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
+#define       nDRIVE_VBUS_OFF_ENA  0x0       
+#define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
+#define      nCHRG_VBUS_START_ENA  0x0       
+#define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
+#define        nCHRG_VBUS_END_ENA  0x0       
+#define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
+#define   nDISCHRG_VBUS_START_ENA  0x0       
+#define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
+#define     nDISCHRG_VBUS_END_ENA  0x0       
+
+/* Bit masks for USB_CSR0 */
+
+#define                  RXPKTRDY  0x1        /* data packet receive indicator */
+#define                 nRXPKTRDY  0x0       
+#define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
+#define                 nTXPKTRDY  0x0       
+#define                STALL_SENT  0x4        /* STALL handshake sent */
+#define               nSTALL_SENT  0x0       
+#define                   DATAEND  0x8        /* Data end indicator */
+#define                  nDATAEND  0x0       
+#define                  SETUPEND  0x10       /* Setup end */
+#define                 nSETUPEND  0x0       
+#define                 SENDSTALL  0x20       /* Send STALL handshake */
+#define                nSENDSTALL  0x0       
+#define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
+#define        nSERVICED_RXPKTRDY  0x0       
+#define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
+#define        nSERVICED_SETUPEND  0x0       
+#define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
+#define                nFLUSHFIFO  0x0       
+#define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
+#define         nSTALL_RECEIVED_H  0x0       
+#define                SETUPPKT_H  0x8        /* send Setup token host mode */
+#define               nSETUPPKT_H  0x0       
+#define                   ERROR_H  0x10       /* timeout error indicator host mode */
+#define                  nERROR_H  0x0       
+#define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
+#define                 nREQPKT_H  0x0       
+#define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
+#define              nSTATUSPKT_H  0x0       
+#define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
+#define            nNAK_TIMEOUT_H  0x0       
+
+/* Bit masks for USB_COUNT0 */
+
+#define              EP0_RX_COUNT  0x7f       /* number of received bytes in EP0 FIFO */
+
+/* Bit masks for USB_NAKLIMIT0 */
+
+#define             EP0_NAK_LIMIT  0x1f       /* number of frames/micro frames after which EP0 timeouts */
+
+/* Bit masks for USB_TX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_T  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_RX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_R  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_TXCSR */
+
+#define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
+#define               nTXPKTRDY_T  0x0       
+#define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
+#define         nFIFO_NOT_EMPTY_T  0x0       
+#define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
+#define               nUNDERRUN_T  0x0       
+#define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
+#define              nFLUSHFIFO_T  0x0       
+#define              STALL_SEND_T  0x10       /* issue a Stall handshake */
+#define             nSTALL_SEND_T  0x0       
+#define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
+#define             nSTALL_SENT_T  0x0       
+#define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
+#define       nCLEAR_DATATOGGLE_T  0x0       
+#define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
+#define               nINCOMPTX_T  0x0       
+#define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
+#define             nDMAREQMODE_T  0x0       
+#define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
+#define       nFORCE_DATATOGGLE_T  0x0       
+#define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
+#define             nDMAREQ_ENA_T  0x0       
+#define                     ISO_T  0x4000     /* enable Isochronous transfers */
+#define                    nISO_T  0x0       
+#define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
+#define                nAUTOSET_T  0x0       
+#define                  ERROR_TH  0x4        /* error condition host mode */
+#define                 nERROR_TH  0x0       
+#define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
+#define        nSTALL_RECEIVED_TH  0x0       
+#define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
+#define           nNAK_TIMEOUT_TH  0x0       
+
+/* Bit masks for USB_TXCOUNT */
+
+#define                  TX_COUNT  0x1fff     /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* Bit masks for USB_RXCSR */
+
+#define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
+#define               nRXPKTRDY_R  0x0       
+#define               FIFO_FULL_R  0x2        /* FIFO not empty */
+#define              nFIFO_FULL_R  0x0       
+#define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
+#define                nOVERRUN_R  0x0       
+#define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
+#define              nDATAERROR_R  0x0       
+#define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
+#define              nFLUSHFIFO_R  0x0       
+#define              STALL_SEND_R  0x20       /* issue a Stall handshake */
+#define             nSTALL_SEND_R  0x0       
+#define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
+#define             nSTALL_SENT_R  0x0       
+#define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
+#define       nCLEAR_DATATOGGLE_R  0x0       
+#define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
+#define               nINCOMPRX_R  0x0       
+#define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
+#define             nDMAREQMODE_R  0x0       
+#define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
+#define                nDISNYET_R  0x0       
+#define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
+#define             nDMAREQ_ENA_R  0x0       
+#define                     ISO_R  0x4000     /* enable Isochronous transfers */
+#define                    nISO_R  0x0       
+#define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
+#define              nAUTOCLEAR_R  0x0       
+#define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
+#define                 nERROR_RH  0x0       
+#define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
+#define                nREQPKT_RH  0x0       
+#define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
+#define        nSTALL_RECEIVED_RH  0x0       
+#define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
+#define              nINCOMPRX_RH  0x0       
+#define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
+#define            nDMAREQMODE_RH  0x0       
+#define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
+#define               nAUTOREQ_RH  0x0       
+
+/* Bit masks for USB_RXCOUNT */
+
+#define                  RX_COUNT  0x1fff     /* Number of received bytes in the packet in the Rx FIFO */
+
+/* Bit masks for USB_TXTYPE */
+
+#define            TARGET_EP_NO_T  0xf        /* EP number */
+#define                PROTOCOL_T  0xc        /* transfer type */
+
+/* Bit masks for USB_TXINTERVAL */
+
+#define          TX_POLL_INTERVAL  0xff       /* polling interval for selected Tx EP */
+
+/* Bit masks for USB_RXTYPE */
+
+#define            TARGET_EP_NO_R  0xf        /* EP number */
+#define                PROTOCOL_R  0xc        /* transfer type */
+
+/* Bit masks for USB_RXINTERVAL */
+
+#define          RX_POLL_INTERVAL  0xff       /* polling interval for selected Rx EP */
+
+/* Bit masks for USB_DMA_INTERRUPT */
+
+#define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
+#define                 nDMA0_INT  0x0       
+#define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
+#define                 nDMA1_INT  0x0       
+#define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
+#define                 nDMA2_INT  0x0       
+#define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
+#define                 nDMA3_INT  0x0       
+#define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
+#define                 nDMA4_INT  0x0       
+#define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
+#define                 nDMA5_INT  0x0       
+#define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
+#define                 nDMA6_INT  0x0       
+#define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
+#define                 nDMA7_INT  0x0       
+
+/* Bit masks for USB_DMAxCONTROL */
+
+#define                   DMA_ENA  0x1        /* DMA enable */
+#define                  nDMA_ENA  0x0       
+#define                 DIRECTION  0x2        /* direction of DMA transfer */
+#define                nDIRECTION  0x0       
+#define                      MODE  0x4        /* DMA Bus error */
+#define                     nMODE  0x0       
+#define                   INT_ENA  0x8        /* Interrupt enable */
+#define                  nINT_ENA  0x0       
+#define                     EPNUM  0xf0       /* EP number */
+#define                  BUSERROR  0x100      /* DMA Bus error */
+#define                 nBUSERROR  0x0       
+
+/* Bit masks for USB_DMAxADDRHIGH */
+
+#define             DMA_ADDR_HIGH  0xffff     /* Upper 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxADDRLOW */
+
+#define              DMA_ADDR_LOW  0xffff     /* Lower 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTHIGH */
+
+#define            DMA_COUNT_HIGH  0xffff     /* Upper 16-bits of byte count of DMA transfer for DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTLOW */
+
+#define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
+
+#endif /* _DEF_BF525_H */
diff --git a/include/asm-blackfin/mach-bf527/defBF527.h b/include/asm-blackfin/mach-bf527/defBF527.h
new file mode 100644
index 0000000..2be3293
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/defBF527.h
@@ -0,0 +1,1089 @@
+/*
+ * File:         include/asm-blackfin/mach-bf527/defBF527.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF527_H
+#define _DEF_BF527_H
+
+/* Include all Core registers and bit definitions */
+#include <def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF527 */
+
+/* Include defBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
+#include <defBF52x_base.h>
+
+/* The following are the #defines needed by ADSP-BF527 that are not in the common header */
+/* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) */
+
+#define EMAC_OPMODE             0xFFC03000       /* Operating Mode Register                              */
+#define EMAC_ADDRLO             0xFFC03004       /* Address Low (32 LSBs) Register                       */
+#define EMAC_ADDRHI             0xFFC03008       /* Address High (16 MSBs) Register                      */
+#define EMAC_HASHLO             0xFFC0300C       /* Multicast Hash Table Low (Bins 31-0) Register        */
+#define EMAC_HASHHI             0xFFC03010       /* Multicast Hash Table High (Bins 63-32) Register      */
+#define EMAC_STAADD             0xFFC03014       /* Station Management Address Register                  */
+#define EMAC_STADAT             0xFFC03018       /* Station Management Data Register                     */
+#define EMAC_FLC                0xFFC0301C       /* Flow Control Register                                */
+#define EMAC_VLAN1              0xFFC03020       /* VLAN1 Tag Register                                   */
+#define EMAC_VLAN2              0xFFC03024       /* VLAN2 Tag Register                                   */
+#define EMAC_WKUP_CTL           0xFFC0302C       /* Wake-Up Control/Status Register                      */
+#define EMAC_WKUP_FFMSK0        0xFFC03030       /* Wake-Up Frame Filter 0 Byte Mask Register            */
+#define EMAC_WKUP_FFMSK1        0xFFC03034       /* Wake-Up Frame Filter 1 Byte Mask Register            */
+#define EMAC_WKUP_FFMSK2        0xFFC03038       /* Wake-Up Frame Filter 2 Byte Mask Register            */
+#define EMAC_WKUP_FFMSK3        0xFFC0303C       /* Wake-Up Frame Filter 3 Byte Mask Register            */
+#define EMAC_WKUP_FFCMD         0xFFC03040       /* Wake-Up Frame Filter Commands Register               */
+#define EMAC_WKUP_FFOFF         0xFFC03044       /* Wake-Up Frame Filter Offsets Register                */
+#define EMAC_WKUP_FFCRC0        0xFFC03048       /* Wake-Up Frame Filter 0,1 CRC-16 Register             */
+#define EMAC_WKUP_FFCRC1        0xFFC0304C       /* Wake-Up Frame Filter 2,3 CRC-16 Register             */
+
+#define EMAC_SYSCTL             0xFFC03060       /* EMAC System Control Register                         */
+#define EMAC_SYSTAT             0xFFC03064       /* EMAC System Status Register                          */
+#define EMAC_RX_STAT            0xFFC03068       /* RX Current Frame Status Register                     */
+#define EMAC_RX_STKY            0xFFC0306C       /* RX Sticky Frame Status Register                      */
+#define EMAC_RX_IRQE            0xFFC03070       /* RX Frame Status Interrupt Enables Register           */
+#define EMAC_TX_STAT            0xFFC03074       /* TX Current Frame Status Register                     */
+#define EMAC_TX_STKY            0xFFC03078       /* TX Sticky Frame Status Register                      */
+#define EMAC_TX_IRQE            0xFFC0307C       /* TX Frame Status Interrupt Enables Register           */
+
+#define EMAC_MMC_CTL            0xFFC03080       /* MMC Counter Control Register                         */
+#define EMAC_MMC_RIRQS          0xFFC03084       /* MMC RX Interrupt Status Register                     */
+#define EMAC_MMC_RIRQE          0xFFC03088       /* MMC RX Interrupt Enables Register                    */
+#define EMAC_MMC_TIRQS          0xFFC0308C       /* MMC TX Interrupt Status Register                     */
+#define EMAC_MMC_TIRQE          0xFFC03090       /* MMC TX Interrupt Enables Register                    */
+
+#define EMAC_RXC_OK             0xFFC03100       /* RX Frame Successful Count                            */
+#define EMAC_RXC_FCS            0xFFC03104       /* RX Frame FCS Failure Count                           */
+#define EMAC_RXC_ALIGN          0xFFC03108       /* RX Alignment Error Count                             */
+#define EMAC_RXC_OCTET          0xFFC0310C       /* RX Octets Successfully Received Count                */
+#define EMAC_RXC_DMAOVF         0xFFC03110       /* Internal MAC Sublayer Error RX Frame Count           */
+#define EMAC_RXC_UNICST         0xFFC03114       /* Unicast RX Frame Count                               */
+#define EMAC_RXC_MULTI          0xFFC03118       /* Multicast RX Frame Count                             */
+#define EMAC_RXC_BROAD          0xFFC0311C       /* Broadcast RX Frame Count                             */
+#define EMAC_RXC_LNERRI         0xFFC03120       /* RX Frame In Range Error Count                        */
+#define EMAC_RXC_LNERRO         0xFFC03124       /* RX Frame Out Of Range Error Count                    */
+#define EMAC_RXC_LONG           0xFFC03128       /* RX Frame Too Long Count                              */
+#define EMAC_RXC_MACCTL         0xFFC0312C       /* MAC Control RX Frame Count                           */
+#define EMAC_RXC_OPCODE         0xFFC03130       /* Unsupported Op-Code RX Frame Count                   */
+#define EMAC_RXC_PAUSE          0xFFC03134       /* MAC Control Pause RX Frame Count                     */
+#define EMAC_RXC_ALLFRM         0xFFC03138       /* Overall RX Frame Count                               */
+#define EMAC_RXC_ALLOCT         0xFFC0313C       /* Overall RX Octet Count                               */
+#define EMAC_RXC_TYPED          0xFFC03140       /* Type/Length Consistent RX Frame Count                */
+#define EMAC_RXC_SHORT          0xFFC03144       /* RX Frame Fragment Count - Byte Count x < 64          */
+#define EMAC_RXC_EQ64           0xFFC03148       /* Good RX Frame Count - Byte Count x = 64              */
+#define EMAC_RXC_LT128          0xFFC0314C       /* Good RX Frame Count - Byte Count  64 < x < 128       */
+#define EMAC_RXC_LT256          0xFFC03150       /* Good RX Frame Count - Byte Count 128 <= x < 256      */
+#define EMAC_RXC_LT512          0xFFC03154       /* Good RX Frame Count - Byte Count 256 <= x < 512      */
+#define EMAC_RXC_LT1024         0xFFC03158       /* Good RX Frame Count - Byte Count 512 <= x < 1024     */
+#define EMAC_RXC_GE1024         0xFFC0315C       /* Good RX Frame Count - Byte Count x >= 1024           */
+
+#define EMAC_TXC_OK             0xFFC03180       /* TX Frame Successful Count                             */
+#define EMAC_TXC_1COL           0xFFC03184       /* TX Frames Successful After Single Collision Count     */
+#define EMAC_TXC_GT1COL         0xFFC03188       /* TX Frames Successful After Multiple Collisions Count  */
+#define EMAC_TXC_OCTET          0xFFC0318C       /* TX Octets Successfully Received Count                 */
+#define EMAC_TXC_DEFER          0xFFC03190       /* TX Frame Delayed Due To Busy Count                    */
+#define EMAC_TXC_LATECL         0xFFC03194       /* Late TX Collisions Count                              */
+#define EMAC_TXC_XS_COL         0xFFC03198       /* TX Frame Failed Due To Excessive Collisions Count     */
+#define EMAC_TXC_DMAUND         0xFFC0319C       /* Internal MAC Sublayer Error TX Frame Count            */
+#define EMAC_TXC_CRSERR         0xFFC031A0       /* Carrier Sense Deasserted During TX Frame Count        */
+#define EMAC_TXC_UNICST         0xFFC031A4       /* Unicast TX Frame Count                                */
+#define EMAC_TXC_MULTI          0xFFC031A8       /* Multicast TX Frame Count                              */
+#define EMAC_TXC_BROAD          0xFFC031AC       /* Broadcast TX Frame Count                              */
+#define EMAC_TXC_XS_DFR         0xFFC031B0       /* TX Frames With Excessive Deferral Count               */
+#define EMAC_TXC_MACCTL         0xFFC031B4       /* MAC Control TX Frame Count                            */
+#define EMAC_TXC_ALLFRM         0xFFC031B8       /* Overall TX Frame Count                                */
+#define EMAC_TXC_ALLOCT         0xFFC031BC       /* Overall TX Octet Count                                */
+#define EMAC_TXC_EQ64           0xFFC031C0       /* Good TX Frame Count - Byte Count x = 64               */
+#define EMAC_TXC_LT128          0xFFC031C4       /* Good TX Frame Count - Byte Count  64 < x < 128        */
+#define EMAC_TXC_LT256          0xFFC031C8       /* Good TX Frame Count - Byte Count 128 <= x < 256       */
+#define EMAC_TXC_LT512          0xFFC031CC       /* Good TX Frame Count - Byte Count 256 <= x < 512       */
+#define EMAC_TXC_LT1024         0xFFC031D0       /* Good TX Frame Count - Byte Count 512 <= x < 1024      */
+#define EMAC_TXC_GE1024         0xFFC031D4       /* Good TX Frame Count - Byte Count x >= 1024            */
+#define EMAC_TXC_ABORT          0xFFC031D8       /* Total TX Frames Aborted Count                         */
+
+/* Listing for IEEE-Supported Count Registers */
+
+#define FramesReceivedOK                EMAC_RXC_OK        /* RX Frame Successful Count                            */
+#define FrameCheckSequenceErrors        EMAC_RXC_FCS       /* RX Frame FCS Failure Count                           */
+#define AlignmentErrors                 EMAC_RXC_ALIGN     /* RX Alignment Error Count                             */
+#define OctetsReceivedOK                EMAC_RXC_OCTET     /* RX Octets Successfully Received Count                */
+#define FramesLostDueToIntMACRcvError   EMAC_RXC_DMAOVF    /* Internal MAC Sublayer Error RX Frame Count           */
+#define UnicastFramesReceivedOK         EMAC_RXC_UNICST    /* Unicast RX Frame Count                               */
+#define MulticastFramesReceivedOK       EMAC_RXC_MULTI     /* Multicast RX Frame Count                             */
+#define BroadcastFramesReceivedOK       EMAC_RXC_BROAD     /* Broadcast RX Frame Count                             */
+#define InRangeLengthErrors             EMAC_RXC_LNERRI    /* RX Frame In Range Error Count                        */
+#define OutOfRangeLengthField           EMAC_RXC_LNERRO    /* RX Frame Out Of Range Error Count                    */
+#define FrameTooLongErrors              EMAC_RXC_LONG      /* RX Frame Too Long Count                              */
+#define MACControlFramesReceived        EMAC_RXC_MACCTL    /* MAC Control RX Frame Count                           */
+#define UnsupportedOpcodesReceived      EMAC_RXC_OPCODE    /* Unsupported Op-Code RX Frame Count                   */
+#define PAUSEMACCtrlFramesReceived      EMAC_RXC_PAUSE     /* MAC Control Pause RX Frame Count                     */
+#define FramesReceivedAll               EMAC_RXC_ALLFRM    /* Overall RX Frame Count                               */
+#define OctetsReceivedAll               EMAC_RXC_ALLOCT    /* Overall RX Octet Count                               */
+#define TypedFramesReceived             EMAC_RXC_TYPED     /* Type/Length Consistent RX Frame Count                */
+#define FramesLenLt64Received           EMAC_RXC_SHORT     /* RX Frame Fragment Count - Byte Count x < 64          */
+#define FramesLenEq64Received           EMAC_RXC_EQ64      /* Good RX Frame Count - Byte Count x = 64              */
+#define FramesLen65_127Received         EMAC_RXC_LT128     /* Good RX Frame Count - Byte Count  64 < x < 128       */
+#define FramesLen128_255Received        EMAC_RXC_LT256     /* Good RX Frame Count - Byte Count 128 <= x < 256      */
+#define FramesLen256_511Received        EMAC_RXC_LT512     /* Good RX Frame Count - Byte Count 256 <= x < 512      */
+#define FramesLen512_1023Received       EMAC_RXC_LT1024    /* Good RX Frame Count - Byte Count 512 <= x < 1024     */
+#define FramesLen1024_MaxReceived       EMAC_RXC_GE1024    /* Good RX Frame Count - Byte Count x >= 1024           */
+
+#define FramesTransmittedOK             EMAC_TXC_OK        /* TX Frame Successful Count                            */
+#define SingleCollisionFrames           EMAC_TXC_1COL      /* TX Frames Successful After Single Collision Count    */
+#define MultipleCollisionFrames         EMAC_TXC_GT1COL    /* TX Frames Successful After Multiple Collisions Count */
+#define OctetsTransmittedOK             EMAC_TXC_OCTET     /* TX Octets Successfully Received Count                */
+#define FramesWithDeferredXmissions     EMAC_TXC_DEFER     /* TX Frame Delayed Due To Busy Count                   */
+#define LateCollisions                  EMAC_TXC_LATECL    /* Late TX Collisions Count                             */
+#define FramesAbortedDueToXSColls       EMAC_TXC_XS_COL    /* TX Frame Failed Due To Excessive Collisions Count    */
+#define FramesLostDueToIntMacXmitError  EMAC_TXC_DMAUND    /* Internal MAC Sublayer Error TX Frame Count           */
+#define CarrierSenseErrors              EMAC_TXC_CRSERR    /* Carrier Sense Deasserted During TX Frame Count       */
+#define UnicastFramesXmittedOK          EMAC_TXC_UNICST    /* Unicast TX Frame Count                               */
+#define MulticastFramesXmittedOK        EMAC_TXC_MULTI     /* Multicast TX Frame Count                             */
+#define BroadcastFramesXmittedOK        EMAC_TXC_BROAD     /* Broadcast TX Frame Count                             */
+#define FramesWithExcessiveDeferral     EMAC_TXC_XS_DFR    /* TX Frames With Excessive Deferral Count              */
+#define MACControlFramesTransmitted     EMAC_TXC_MACCTL    /* MAC Control TX Frame Count                           */
+#define FramesTransmittedAll            EMAC_TXC_ALLFRM    /* Overall TX Frame Count                               */
+#define OctetsTransmittedAll            EMAC_TXC_ALLOCT    /* Overall TX Octet Count                               */
+#define FramesLenEq64Transmitted        EMAC_TXC_EQ64      /* Good TX Frame Count - Byte Count x = 64              */
+#define FramesLen65_127Transmitted      EMAC_TXC_LT128     /* Good TX Frame Count - Byte Count  64 < x < 128       */
+#define FramesLen128_255Transmitted     EMAC_TXC_LT256     /* Good TX Frame Count - Byte Count 128 <= x < 256      */
+#define FramesLen256_511Transmitted     EMAC_TXC_LT512     /* Good TX Frame Count - Byte Count 256 <= x < 512      */
+#define FramesLen512_1023Transmitted    EMAC_TXC_LT1024    /* Good TX Frame Count - Byte Count 512 <= x < 1024     */
+#define FramesLen1024_MaxTransmitted    EMAC_TXC_GE1024    /* Good TX Frame Count - Byte Count x >= 1024           */
+#define TxAbortedFrames                 EMAC_TXC_ABORT     /* Total TX Frames Aborted Count                        */
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer:	All macros are intended to make C and Assembly code more readable.
+**				Use these macros carefully, as any that do left shifts for field
+**				depositing will result in the lower order bits being destroyed.  Any
+**				macro that shifts left to properly position the bit-field should be
+**				used as part of an OR to initialize a register and NOT as a dynamic
+**				modifier UNLESS the lower order bits are saved and ORed back in when
+**				the macro is used.
+*************************************************************************************/
+
+/************************  ETHERNET 10/100 CONTROLLER MASKS  ************************/
+
+/* EMAC_OPMODE Masks */
+
+#define	RE                 0x00000001     /* Receiver Enable                                    */
+#define	ASTP               0x00000002     /* Enable Automatic Pad Stripping On RX Frames        */
+#define	HU                 0x00000010     /* Hash Filter Unicast Address                        */
+#define	HM                 0x00000020     /* Hash Filter Multicast Address                      */
+#define	PAM                0x00000040     /* Pass-All-Multicast Mode Enable                     */
+#define	PR                 0x00000080     /* Promiscuous Mode Enable                            */
+#define	IFE                0x00000100     /* Inverse Filtering Enable                           */
+#define	DBF                0x00000200     /* Disable Broadcast Frame Reception                  */
+#define	PBF                0x00000400     /* Pass Bad Frames Enable                             */
+#define	PSF                0x00000800     /* Pass Short Frames Enable                           */
+#define	RAF                0x00001000     /* Receive-All Mode                                   */
+#define	TE                 0x00010000     /* Transmitter Enable                                 */
+#define	DTXPAD             0x00020000     /* Disable Automatic TX Padding                       */
+#define	DTXCRC             0x00040000     /* Disable Automatic TX CRC Generation                */
+#define	DC                 0x00080000     /* Deferral Check                                     */
+#define	BOLMT              0x00300000     /* Back-Off Limit                                     */
+#define	BOLMT_10           0x00000000     /*		10-bit range                            */
+#define	BOLMT_8            0x00100000     /*		8-bit range                             */
+#define	BOLMT_4            0x00200000     /*		4-bit range                             */
+#define	BOLMT_1            0x00300000     /*		1-bit range                             */
+#define	DRTY               0x00400000     /* Disable TX Retry On Collision                      */
+#define	LCTRE              0x00800000     /* Enable TX Retry On Late Collision                  */
+#define	RMII               0x01000000     /* RMII/MII* Mode                                     */
+#define	RMII_10            0x02000000     /* Speed Select for RMII Port (10MBit/100MBit*)       */
+#define	FDMODE             0x04000000     /* Duplex Mode Enable (Full/Half*)                    */
+#define	LB                 0x08000000     /* Internal Loopback Enable                           */
+#define	DRO                0x10000000     /* Disable Receive Own Frames (Half-Duplex Mode)      */
+
+/* EMAC_STAADD Masks */
+
+#define	STABUSY            0x00000001     /* Initiate Station Mgt Reg Access / STA Busy Stat    */
+#define	STAOP              0x00000002     /* Station Management Operation Code (Write/Read*)    */
+#define	STADISPRE          0x00000004     /* Disable Preamble Generation                        */
+#define	STAIE              0x00000008     /* Station Mgt. Transfer Done Interrupt Enable        */
+#define	REGAD              0x000007C0     /* STA Register Address                               */
+#define	PHYAD              0x0000F800     /* PHY Device Address                                 */
+
+#define	SET_REGAD(x) (((x)&0x1F)<<  6 )   /* Set STA Register Address                           */
+#define	SET_PHYAD(x) (((x)&0x1F)<< 11 )   /* Set PHY Device Address                             */
+
+/* EMAC_STADAT Mask */
+
+#define	STADATA            0x0000FFFF     /* Station Management Data                            */
+
+/* EMAC_FLC Masks */
+
+#define	FLCBUSY            0x00000001     /* Send Flow Ctrl Frame / Flow Ctrl Busy Status       */
+#define	FLCE               0x00000002     /* Flow Control Enable                                */
+#define	PCF                0x00000004     /* Pass Control Frames                                */
+#define	BKPRSEN            0x00000008     /* Enable Backpressure                                */
+#define	FLCPAUSE           0xFFFF0000     /* Pause Time                                         */
+
+#define	SET_FLCPAUSE(x) (((x)&0xFFFF)<< 16) /* Set Pause Time                                   */
+
+/* EMAC_WKUP_CTL Masks */
+
+#define	CAPWKFRM           0x00000001    /* Capture Wake-Up Frames                              */
+#define	MPKE               0x00000002    /* Magic Packet Enable                                 */
+#define	RWKE               0x00000004    /* Remote Wake-Up Frame Enable                         */
+#define	GUWKE              0x00000008    /* Global Unicast Wake Enable                          */
+#define	MPKS               0x00000020    /* Magic Packet Received Status                        */
+#define	RWKS               0x00000F00    /* Wake-Up Frame Received Status, Filters 3:0          */
+
+/* EMAC_WKUP_FFCMD Masks */
+
+#define	WF0_E              0x00000001    /* Enable Wake-Up Filter 0                              */
+#define	WF0_T              0x00000008    /* Wake-Up Filter 0 Addr Type (Multicast/Unicast*)      */
+#define	WF1_E              0x00000100    /* Enable Wake-Up Filter 1                              */
+#define	WF1_T              0x00000800    /* Wake-Up Filter 1 Addr Type (Multicast/Unicast*)      */
+#define	WF2_E              0x00010000    /* Enable Wake-Up Filter 2                              */
+#define	WF2_T              0x00080000    /* Wake-Up Filter 2 Addr Type (Multicast/Unicast*)      */
+#define	WF3_E              0x01000000    /* Enable Wake-Up Filter 3                              */
+#define	WF3_T              0x08000000    /* Wake-Up Filter 3 Addr Type (Multicast/Unicast*)      */
+
+/* EMAC_WKUP_FFOFF Masks */
+
+#define	WF0_OFF            0x000000FF    /* Wake-Up Filter 0 Pattern Offset                      */
+#define	WF1_OFF            0x0000FF00    /* Wake-Up Filter 1 Pattern Offset                      */
+#define	WF2_OFF            0x00FF0000    /* Wake-Up Filter 2 Pattern Offset                      */
+#define	WF3_OFF            0xFF000000    /* Wake-Up Filter 3 Pattern Offset                      */
+
+#define	SET_WF0_OFF(x) (((x)&0xFF)<<  0 ) /* Set Wake-Up Filter 0 Byte Offset                    */
+#define	SET_WF1_OFF(x) (((x)&0xFF)<<  8 ) /* Set Wake-Up Filter 1 Byte Offset                    */
+#define	SET_WF2_OFF(x) (((x)&0xFF)<< 16 ) /* Set Wake-Up Filter 2 Byte Offset                    */
+#define	SET_WF3_OFF(x) (((x)&0xFF)<< 24 ) /* Set Wake-Up Filter 3 Byte Offset                    */
+/* Set ALL Offsets */
+#define	SET_WF_OFFS(x0,x1,x2,x3) (SET_WF0_OFF((x0))|SET_WF1_OFF((x1))|SET_WF2_OFF((x2))|SET_WF3_OFF((x3)))
+
+/* EMAC_WKUP_FFCRC0 Masks */
+
+#define	WF0_CRC           0x0000FFFF    /* Wake-Up Filter 0 Pattern CRC                           */
+#define	WF1_CRC           0xFFFF0000    /* Wake-Up Filter 1 Pattern CRC                           */
+
+#define	SET_WF0_CRC(x) (((x)&0xFFFF)<<   0 ) /* Set Wake-Up Filter 0 Target CRC                   */
+#define	SET_WF1_CRC(x) (((x)&0xFFFF)<<  16 ) /* Set Wake-Up Filter 1 Target CRC                   */
+
+/* EMAC_WKUP_FFCRC1 Masks */
+
+#define	WF2_CRC           0x0000FFFF    /* Wake-Up Filter 2 Pattern CRC                           */
+#define	WF3_CRC           0xFFFF0000    /* Wake-Up Filter 3 Pattern CRC                           */
+
+#define	SET_WF2_CRC(x) (((x)&0xFFFF)<<   0 ) /* Set Wake-Up Filter 2 Target CRC                   */
+#define	SET_WF3_CRC(x) (((x)&0xFFFF)<<  16 ) /* Set Wake-Up Filter 3 Target CRC                   */
+
+/* EMAC_SYSCTL Masks */
+
+#define	PHYIE             0x00000001    /* PHY_INT Interrupt Enable                               */
+#define	RXDWA             0x00000002    /* Receive Frame DMA Word Alignment (Odd/Even*)           */
+#define	RXCKS             0x00000004    /* Enable RX Frame TCP/UDP Checksum Computation           */
+#define	MDCDIV            0x00003F00    /* SCLK:MDC Clock Divisor [MDC=SCLK/(2*(N+1))]            */
+
+#define	SET_MDCDIV(x) (((x)&0x3F)<< 8)   /* Set MDC Clock Divisor                                 */
+
+/* EMAC_SYSTAT Masks */
+
+#define	PHYINT            0x00000001    /* PHY_INT Interrupt Status                               */
+#define	MMCINT            0x00000002    /* MMC Counter Interrupt Status                           */
+#define	RXFSINT           0x00000004    /* RX Frame-Status Interrupt Status                       */
+#define	TXFSINT           0x00000008    /* TX Frame-Status Interrupt Status                       */
+#define	WAKEDET           0x00000010    /* Wake-Up Detected Status                                */
+#define	RXDMAERR          0x00000020    /* RX DMA Direction Error Status                          */
+#define	TXDMAERR          0x00000040    /* TX DMA Direction Error Status                          */
+#define	STMDONE           0x00000080    /* Station Mgt. Transfer Done Interrupt Status            */
+
+/* EMAC_RX_STAT, EMAC_RX_STKY, and EMAC_RX_IRQE Masks */
+
+#define	RX_FRLEN          0x000007FF    /* Frame Length In Bytes                                  */
+#define	RX_COMP           0x00001000    /* RX Frame Complete                                      */
+#define	RX_OK             0x00002000    /* RX Frame Received With No Errors                       */
+#define	RX_LONG           0x00004000    /* RX Frame Too Long Error                                */
+#define	RX_ALIGN          0x00008000    /* RX Frame Alignment Error                               */
+#define	RX_CRC            0x00010000    /* RX Frame CRC Error                                     */
+#define	RX_LEN            0x00020000    /* RX Frame Length Error                                  */
+#define	RX_FRAG           0x00040000    /* RX Frame Fragment Error                                */
+#define	RX_ADDR           0x00080000    /* RX Frame Address Filter Failed Error                   */
+#define	RX_DMAO           0x00100000    /* RX Frame DMA Overrun Error                             */
+#define	RX_PHY            0x00200000    /* RX Frame PHY Error                                     */
+#define	RX_LATE           0x00400000    /* RX Frame Late Collision Error                          */
+#define	RX_RANGE          0x00800000    /* RX Frame Length Field Out of Range Error               */
+#define	RX_MULTI          0x01000000    /* RX Multicast Frame Indicator                           */
+#define	RX_BROAD          0x02000000    /* RX Broadcast Frame Indicator                           */
+#define	RX_CTL            0x04000000    /* RX Control Frame Indicator                             */
+#define	RX_UCTL           0x08000000    /* Unsupported RX Control Frame Indicator                 */
+#define	RX_TYPE           0x10000000    /* RX Typed Frame Indicator                               */
+#define	RX_VLAN1          0x20000000    /* RX VLAN1 Frame Indicator                               */
+#define	RX_VLAN2          0x40000000    /* RX VLAN2 Frame Indicator                               */
+#define	RX_ACCEPT         0x80000000    /* RX Frame Accepted Indicator                            */
+
+/*  EMAC_TX_STAT, EMAC_TX_STKY, and EMAC_TX_IRQE Masks  */
+
+#define	TX_COMP           0x00000001    /* TX Frame Complete                                      */
+#define	TX_OK             0x00000002    /* TX Frame Sent With No Errors                           */
+#define	TX_ECOLL          0x00000004    /* TX Frame Excessive Collision Error                     */
+#define	TX_LATE           0x00000008    /* TX Frame Late Collision Error                          */
+#define	TX_DMAU           0x00000010    /* TX Frame DMA Underrun Error (STAT)                     */
+#define	TX_MACE           0x00000010    /* Internal MAC Error Detected (STKY and IRQE)            */
+#define	TX_EDEFER         0x00000020    /* TX Frame Excessive Deferral Error                      */
+#define	TX_BROAD          0x00000040    /* TX Broadcast Frame Indicator                           */
+#define	TX_MULTI          0x00000080    /* TX Multicast Frame Indicator                           */
+#define	TX_CCNT           0x00000F00    /* TX Frame Collision Count                               */
+#define	TX_DEFER          0x00001000    /* TX Frame Deferred Indicator                            */
+#define	TX_CRS            0x00002000    /* TX Frame Carrier Sense Not Asserted Error              */
+#define	TX_LOSS           0x00004000    /* TX Frame Carrier Lost During TX Error                  */
+#define	TX_RETRY          0x00008000    /* TX Frame Successful After Retry                        */
+#define	TX_FRLEN          0x07FF0000    /* TX Frame Length (Bytes)                                */
+
+/* EMAC_MMC_CTL Masks */
+#define	RSTC              0x00000001    /* Reset All Counters                                     */
+#define	CROLL             0x00000002    /* Counter Roll-Over Enable                               */
+#define	CCOR              0x00000004    /* Counter Clear-On-Read Mode Enable                      */
+#define	MMCE              0x00000008    /* Enable MMC Counter Operation                           */
+
+/* EMAC_MMC_RIRQS and EMAC_MMC_RIRQE Masks */
+#define	RX_OK_CNT         0x00000001    /* RX Frames Received With No Errors                      */
+#define	RX_FCS_CNT        0x00000002    /* RX Frames W/Frame Check Sequence Errors                */
+#define	RX_ALIGN_CNT      0x00000004    /* RX Frames With Alignment Errors                        */
+#define	RX_OCTET_CNT      0x00000008    /* RX Octets Received OK                                  */
+#define	RX_LOST_CNT       0x00000010    /* RX Frames Lost Due To Internal MAC RX Error            */
+#define	RX_UNI_CNT        0x00000020    /* Unicast RX Frames Received OK                          */
+#define	RX_MULTI_CNT      0x00000040    /* Multicast RX Frames Received OK                        */
+#define	RX_BROAD_CNT      0x00000080    /* Broadcast RX Frames Received OK                        */
+#define	RX_IRL_CNT        0x00000100    /* RX Frames With In-Range Length Errors                  */
+#define	RX_ORL_CNT        0x00000200    /* RX Frames With Out-Of-Range Length Errors              */
+#define	RX_LONG_CNT       0x00000400    /* RX Frames With Frame Too Long Errors                   */
+#define	RX_MACCTL_CNT     0x00000800    /* MAC Control RX Frames Received                         */
+#define	RX_OPCODE_CTL     0x00001000    /* Unsupported Op-Code RX Frames Received                 */
+#define	RX_PAUSE_CNT      0x00002000    /* PAUSEMAC Control RX Frames Received                    */
+#define	RX_ALLF_CNT       0x00004000    /* All RX Frames Received                                 */
+#define	RX_ALLO_CNT       0x00008000    /* All RX Octets Received                                 */
+#define	RX_TYPED_CNT      0x00010000    /* Typed RX Frames Received                               */
+#define	RX_SHORT_CNT      0x00020000    /* RX Frame Fragments (< 64 Bytes) Received               */
+#define	RX_EQ64_CNT       0x00040000    /* 64-Byte RX Frames Received                             */
+#define	RX_LT128_CNT      0x00080000    /* 65-127-Byte RX Frames Received                         */
+#define	RX_LT256_CNT      0x00100000    /* 128-255-Byte RX Frames Received                        */
+#define	RX_LT512_CNT      0x00200000    /* 256-511-Byte RX Frames Received                        */
+#define	RX_LT1024_CNT     0x00400000    /* 512-1023-Byte RX Frames Received                       */
+#define	RX_GE1024_CNT     0x00800000    /* 1024-Max-Byte RX Frames Received                       */
+
+/* EMAC_MMC_TIRQS and EMAC_MMC_TIRQE Masks  */
+
+#define	TX_OK_CNT         0x00000001    /* TX Frames Sent OK                                      */
+#define	TX_SCOLL_CNT      0x00000002    /* TX Frames With Single Collisions                       */
+#define	TX_MCOLL_CNT      0x00000004    /* TX Frames With Multiple Collisions                     */
+#define	TX_OCTET_CNT      0x00000008    /* TX Octets Sent OK                                      */
+#define	TX_DEFER_CNT      0x00000010    /* TX Frames With Deferred Transmission                   */
+#define	TX_LATE_CNT       0x00000020    /* TX Frames With Late Collisions                         */
+#define	TX_ABORTC_CNT     0x00000040    /* TX Frames Aborted Due To Excess Collisions             */
+#define	TX_LOST_CNT       0x00000080    /* TX Frames Lost Due To Internal MAC TX Error            */
+#define	TX_CRS_CNT        0x00000100    /* TX Frames With Carrier Sense Errors                    */
+#define	TX_UNI_CNT        0x00000200    /* Unicast TX Frames Sent                                 */
+#define	TX_MULTI_CNT      0x00000400    /* Multicast TX Frames Sent                               */
+#define	TX_BROAD_CNT      0x00000800    /* Broadcast TX Frames Sent                               */
+#define	TX_EXDEF_CTL      0x00001000    /* TX Frames With Excessive Deferral                      */
+#define	TX_MACCTL_CNT     0x00002000    /* MAC Control TX Frames Sent                             */
+#define	TX_ALLF_CNT       0x00004000    /* All TX Frames Sent                                     */
+#define	TX_ALLO_CNT       0x00008000    /* All TX Octets Sent                                     */
+#define	TX_EQ64_CNT       0x00010000    /* 64-Byte TX Frames Sent                                 */
+#define	TX_LT128_CNT      0x00020000    /* 65-127-Byte TX Frames Sent                             */
+#define	TX_LT256_CNT      0x00040000    /* 128-255-Byte TX Frames Sent                            */
+#define	TX_LT512_CNT      0x00080000    /* 256-511-Byte TX Frames Sent                            */
+#define	TX_LT1024_CNT     0x00100000    /* 512-1023-Byte TX Frames Sent                           */
+#define	TX_GE1024_CNT     0x00200000    /* 1024-Max-Byte TX Frames Sent                           */
+#define	TX_ABORT_CNT      0x00400000    /* TX Frames Aborted                                      */
+
+/* USB Control Registers */
+
+#define                        USB_FADDR  0xffc03800   /* Function address register */
+#define                        USB_POWER  0xffc03804   /* Power management register */
+#define                       USB_INTRTX  0xffc03808   /* Interrupt register for endpoint 0 and Tx endpoint 1 to 7 */
+#define                       USB_INTRRX  0xffc0380c   /* Interrupt register for Rx endpoints 1 to 7 */
+#define                      USB_INTRTXE  0xffc03810   /* Interrupt enable register for IntrTx */
+#define                      USB_INTRRXE  0xffc03814   /* Interrupt enable register for IntrRx */
+#define                      USB_INTRUSB  0xffc03818   /* Interrupt register for common USB interrupts */
+#define                     USB_INTRUSBE  0xffc0381c   /* Interrupt enable register for IntrUSB */
+#define                        USB_FRAME  0xffc03820   /* USB frame number */
+#define                        USB_INDEX  0xffc03824   /* Index register for selecting the indexed endpoint registers */
+#define                     USB_TESTMODE  0xffc03828   /* Enabled USB 20 test modes */
+#define                     USB_GLOBINTR  0xffc0382c   /* Global Interrupt Mask register and Wakeup Exception Interrupt */
+#define                   USB_GLOBAL_CTL  0xffc03830   /* Global Clock Control for the core */
+
+/* USB Packet Control Registers */
+
+#define                USB_TX_MAX_PACKET  0xffc03840   /* Maximum packet size for Host Tx endpoint */
+#define                         USB_CSR0  0xffc03844   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                        USB_TXCSR  0xffc03844   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                USB_RX_MAX_PACKET  0xffc03848   /* Maximum packet size for Host Rx endpoint */
+#define                        USB_RXCSR  0xffc0384c   /* Control Status register for Host Rx endpoint */
+#define                       USB_COUNT0  0xffc03850   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                      USB_RXCOUNT  0xffc03850   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                       USB_TXTYPE  0xffc03854   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint */
+#define                    USB_NAKLIMIT0  0xffc03858   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                   USB_TXINTERVAL  0xffc03858   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                       USB_RXTYPE  0xffc0385c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint */
+#define                   USB_RXINTERVAL  0xffc03860   /* Sets the polling interval for Interrupt and Isochronous transfers or the NAK response timeout on Bulk transfers */
+#define                      USB_TXCOUNT  0xffc03868   /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* USB Endpoint FIFO Registers */
+
+#define                     USB_EP0_FIFO  0xffc03880   /* Endpoint 0 FIFO */
+#define                     USB_EP1_FIFO  0xffc03888   /* Endpoint 1 FIFO */
+#define                     USB_EP2_FIFO  0xffc03890   /* Endpoint 2 FIFO */
+#define                     USB_EP3_FIFO  0xffc03898   /* Endpoint 3 FIFO */
+#define                     USB_EP4_FIFO  0xffc038a0   /* Endpoint 4 FIFO */
+#define                     USB_EP5_FIFO  0xffc038a8   /* Endpoint 5 FIFO */
+#define                     USB_EP6_FIFO  0xffc038b0   /* Endpoint 6 FIFO */
+#define                     USB_EP7_FIFO  0xffc038b8   /* Endpoint 7 FIFO */
+
+/* USB OTG Control Registers */
+
+#define                  USB_OTG_DEV_CTL  0xffc03900   /* OTG Device Control Register */
+#define                 USB_OTG_VBUS_IRQ  0xffc03904   /* OTG VBUS Control Interrupts */
+#define                USB_OTG_VBUS_MASK  0xffc03908   /* VBUS Control Interrupt Enable */
+
+/* USB Phy Control Registers */
+
+#define                     USB_LINKINFO  0xffc03948   /* Enables programming of some PHY-side delays */
+#define                        USB_VPLEN  0xffc0394c   /* Determines duration of VBUS pulse for VBUS charging */
+#define                      USB_HS_EOF1  0xffc03950   /* Time buffer for High-Speed transactions */
+#define                      USB_FS_EOF1  0xffc03954   /* Time buffer for Full-Speed transactions */
+#define                      USB_LS_EOF1  0xffc03958   /* Time buffer for Low-Speed transactions */
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define                   USB_APHY_CNTRL  0xffc039e0   /* Register that increases visibility of Analog PHY */
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define                   USB_APHY_CALIB  0xffc039e4   /* Register used to set some calibration values */
+
+#define                  USB_APHY_CNTRL2  0xffc039e8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define                     USB_PHY_TEST  0xffc039ec   /* Used for reducing simulation time and simplifies FIFO testability */
+
+#define                  USB_PLLOSC_CTRL  0xffc039f0   /* Used to program different parameters for USB PLL and Oscillator */
+#define                   USB_SRP_CLKDIV  0xffc039f4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
+
+/* USB Endpoint 0 Control Registers */
+
+#define                USB_EP_NI0_TXMAXP  0xffc03a00   /* Maximum packet size for Host Tx endpoint0 */
+#define                 USB_EP_NI0_TXCSR  0xffc03a04   /* Control Status register for endpoint 0 */
+#define                USB_EP_NI0_RXMAXP  0xffc03a08   /* Maximum packet size for Host Rx endpoint0 */
+#define                 USB_EP_NI0_RXCSR  0xffc03a0c   /* Control Status register for Host Rx endpoint0 */
+#define               USB_EP_NI0_RXCOUNT  0xffc03a10   /* Number of bytes received in endpoint 0 FIFO */
+#define                USB_EP_NI0_TXTYPE  0xffc03a14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint0 */
+#define            USB_EP_NI0_TXINTERVAL  0xffc03a18   /* Sets the NAK response timeout on Endpoint 0 */
+#define                USB_EP_NI0_RXTYPE  0xffc03a1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint0 */
+#define            USB_EP_NI0_RXINTERVAL  0xffc03a20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint0 */
+#define               USB_EP_NI0_TXCOUNT  0xffc03a28   /* Number of bytes to be written to the endpoint0 Tx FIFO */
+
+/* USB Endpoint 1 Control Registers */
+
+#define                USB_EP_NI1_TXMAXP  0xffc03a40   /* Maximum packet size for Host Tx endpoint1 */
+#define                 USB_EP_NI1_TXCSR  0xffc03a44   /* Control Status register for endpoint1 */
+#define                USB_EP_NI1_RXMAXP  0xffc03a48   /* Maximum packet size for Host Rx endpoint1 */
+#define                 USB_EP_NI1_RXCSR  0xffc03a4c   /* Control Status register for Host Rx endpoint1 */
+#define               USB_EP_NI1_RXCOUNT  0xffc03a50   /* Number of bytes received in endpoint1 FIFO */
+#define                USB_EP_NI1_TXTYPE  0xffc03a54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint1 */
+#define            USB_EP_NI1_TXINTERVAL  0xffc03a58   /* Sets the NAK response timeout on Endpoint1 */
+#define                USB_EP_NI1_RXTYPE  0xffc03a5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint1 */
+#define            USB_EP_NI1_RXINTERVAL  0xffc03a60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint1 */
+#define               USB_EP_NI1_TXCOUNT  0xffc03a68   /* Number of bytes to be written to the+H102 endpoint1 Tx FIFO */
+
+/* USB Endpoint 2 Control Registers */
+
+#define                USB_EP_NI2_TXMAXP  0xffc03a80   /* Maximum packet size for Host Tx endpoint2 */
+#define                 USB_EP_NI2_TXCSR  0xffc03a84   /* Control Status register for endpoint2 */
+#define                USB_EP_NI2_RXMAXP  0xffc03a88   /* Maximum packet size for Host Rx endpoint2 */
+#define                 USB_EP_NI2_RXCSR  0xffc03a8c   /* Control Status register for Host Rx endpoint2 */
+#define               USB_EP_NI2_RXCOUNT  0xffc03a90   /* Number of bytes received in endpoint2 FIFO */
+#define                USB_EP_NI2_TXTYPE  0xffc03a94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint2 */
+#define            USB_EP_NI2_TXINTERVAL  0xffc03a98   /* Sets the NAK response timeout on Endpoint2 */
+#define                USB_EP_NI2_RXTYPE  0xffc03a9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint2 */
+#define            USB_EP_NI2_RXINTERVAL  0xffc03aa0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint2 */
+#define               USB_EP_NI2_TXCOUNT  0xffc03aa8   /* Number of bytes to be written to the endpoint2 Tx FIFO */
+
+/* USB Endpoint 3 Control Registers */
+
+#define                USB_EP_NI3_TXMAXP  0xffc03ac0   /* Maximum packet size for Host Tx endpoint3 */
+#define                 USB_EP_NI3_TXCSR  0xffc03ac4   /* Control Status register for endpoint3 */
+#define                USB_EP_NI3_RXMAXP  0xffc03ac8   /* Maximum packet size for Host Rx endpoint3 */
+#define                 USB_EP_NI3_RXCSR  0xffc03acc   /* Control Status register for Host Rx endpoint3 */
+#define               USB_EP_NI3_RXCOUNT  0xffc03ad0   /* Number of bytes received in endpoint3 FIFO */
+#define                USB_EP_NI3_TXTYPE  0xffc03ad4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint3 */
+#define            USB_EP_NI3_TXINTERVAL  0xffc03ad8   /* Sets the NAK response timeout on Endpoint3 */
+#define                USB_EP_NI3_RXTYPE  0xffc03adc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint3 */
+#define            USB_EP_NI3_RXINTERVAL  0xffc03ae0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint3 */
+#define               USB_EP_NI3_TXCOUNT  0xffc03ae8   /* Number of bytes to be written to the H124endpoint3 Tx FIFO */
+
+/* USB Endpoint 4 Control Registers */
+
+#define                USB_EP_NI4_TXMAXP  0xffc03b00   /* Maximum packet size for Host Tx endpoint4 */
+#define                 USB_EP_NI4_TXCSR  0xffc03b04   /* Control Status register for endpoint4 */
+#define                USB_EP_NI4_RXMAXP  0xffc03b08   /* Maximum packet size for Host Rx endpoint4 */
+#define                 USB_EP_NI4_RXCSR  0xffc03b0c   /* Control Status register for Host Rx endpoint4 */
+#define               USB_EP_NI4_RXCOUNT  0xffc03b10   /* Number of bytes received in endpoint4 FIFO */
+#define                USB_EP_NI4_TXTYPE  0xffc03b14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint4 */
+#define            USB_EP_NI4_TXINTERVAL  0xffc03b18   /* Sets the NAK response timeout on Endpoint4 */
+#define                USB_EP_NI4_RXTYPE  0xffc03b1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint4 */
+#define            USB_EP_NI4_RXINTERVAL  0xffc03b20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint4 */
+#define               USB_EP_NI4_TXCOUNT  0xffc03b28   /* Number of bytes to be written to the endpoint4 Tx FIFO */
+
+/* USB Endpoint 5 Control Registers */
+
+#define                USB_EP_NI5_TXMAXP  0xffc03b40   /* Maximum packet size for Host Tx endpoint5 */
+#define                 USB_EP_NI5_TXCSR  0xffc03b44   /* Control Status register for endpoint5 */
+#define                USB_EP_NI5_RXMAXP  0xffc03b48   /* Maximum packet size for Host Rx endpoint5 */
+#define                 USB_EP_NI5_RXCSR  0xffc03b4c   /* Control Status register for Host Rx endpoint5 */
+#define               USB_EP_NI5_RXCOUNT  0xffc03b50   /* Number of bytes received in endpoint5 FIFO */
+#define                USB_EP_NI5_TXTYPE  0xffc03b54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint5 */
+#define            USB_EP_NI5_TXINTERVAL  0xffc03b58   /* Sets the NAK response timeout on Endpoint5 */
+#define                USB_EP_NI5_RXTYPE  0xffc03b5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint5 */
+#define            USB_EP_NI5_RXINTERVAL  0xffc03b60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint5 */
+#define               USB_EP_NI5_TXCOUNT  0xffc03b68   /* Number of bytes to be written to the endpoint5 Tx FIFO */
+
+/* USB Endpoint 6 Control Registers */
+
+#define                USB_EP_NI6_TXMAXP  0xffc03b80   /* Maximum packet size for Host Tx endpoint6 */
+#define                 USB_EP_NI6_TXCSR  0xffc03b84   /* Control Status register for endpoint6 */
+#define                USB_EP_NI6_RXMAXP  0xffc03b88   /* Maximum packet size for Host Rx endpoint6 */
+#define                 USB_EP_NI6_RXCSR  0xffc03b8c   /* Control Status register for Host Rx endpoint6 */
+#define               USB_EP_NI6_RXCOUNT  0xffc03b90   /* Number of bytes received in endpoint6 FIFO */
+#define                USB_EP_NI6_TXTYPE  0xffc03b94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint6 */
+#define            USB_EP_NI6_TXINTERVAL  0xffc03b98   /* Sets the NAK response timeout on Endpoint6 */
+#define                USB_EP_NI6_RXTYPE  0xffc03b9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint6 */
+#define            USB_EP_NI6_RXINTERVAL  0xffc03ba0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint6 */
+#define               USB_EP_NI6_TXCOUNT  0xffc03ba8   /* Number of bytes to be written to the endpoint6 Tx FIFO */
+
+/* USB Endpoint 7 Control Registers */
+
+#define                USB_EP_NI7_TXMAXP  0xffc03bc0   /* Maximum packet size for Host Tx endpoint7 */
+#define                 USB_EP_NI7_TXCSR  0xffc03bc4   /* Control Status register for endpoint7 */
+#define                USB_EP_NI7_RXMAXP  0xffc03bc8   /* Maximum packet size for Host Rx endpoint7 */
+#define                 USB_EP_NI7_RXCSR  0xffc03bcc   /* Control Status register for Host Rx endpoint7 */
+#define               USB_EP_NI7_RXCOUNT  0xffc03bd0   /* Number of bytes received in endpoint7 FIFO */
+#define                USB_EP_NI7_TXTYPE  0xffc03bd4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint7 */
+#define            USB_EP_NI7_TXINTERVAL  0xffc03bd8   /* Sets the NAK response timeout on Endpoint7 */
+#define                USB_EP_NI7_RXTYPE  0xffc03bdc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint7 */
+#define            USB_EP_NI7_RXINTERVAL  0xffc03bf0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint7 */
+#define               USB_EP_NI7_TXCOUNT  0xffc03bf8   /* Number of bytes to be written to the endpoint7 Tx FIFO */
+
+#define                USB_DMA_INTERRUPT  0xffc03c00   /* Indicates pending interrupts for the DMA channels */
+
+/* USB Channel 0 Config Registers */
+
+#define                  USB_DMA0CONTROL  0xffc03c04   /* DMA master channel 0 configuration */
+#define                  USB_DMA0ADDRLOW  0xffc03c08   /* Lower 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0ADDRHIGH  0xffc03c0c   /* Upper 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0COUNTLOW  0xffc03c10   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 0 */
+#define                USB_DMA0COUNTHIGH  0xffc03c14   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 0 */
+
+/* USB Channel 1 Config Registers */
+
+#define                  USB_DMA1CONTROL  0xffc03c24   /* DMA master channel 1 configuration */
+#define                  USB_DMA1ADDRLOW  0xffc03c28   /* Lower 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1ADDRHIGH  0xffc03c2c   /* Upper 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1COUNTLOW  0xffc03c30   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 1 */
+#define                USB_DMA1COUNTHIGH  0xffc03c34   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 1 */
+
+/* USB Channel 2 Config Registers */
+
+#define                  USB_DMA2CONTROL  0xffc03c44   /* DMA master channel 2 configuration */
+#define                  USB_DMA2ADDRLOW  0xffc03c48   /* Lower 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2ADDRHIGH  0xffc03c4c   /* Upper 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2COUNTLOW  0xffc03c50   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 2 */
+#define                USB_DMA2COUNTHIGH  0xffc03c54   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 2 */
+
+/* USB Channel 3 Config Registers */
+
+#define                  USB_DMA3CONTROL  0xffc03c64   /* DMA master channel 3 configuration */
+#define                  USB_DMA3ADDRLOW  0xffc03c68   /* Lower 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3ADDRHIGH  0xffc03c6c   /* Upper 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3COUNTLOW  0xffc03c70   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 3 */
+#define                USB_DMA3COUNTHIGH  0xffc03c74   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 3 */
+
+/* USB Channel 4 Config Registers */
+
+#define                  USB_DMA4CONTROL  0xffc03c84   /* DMA master channel 4 configuration */
+#define                  USB_DMA4ADDRLOW  0xffc03c88   /* Lower 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4ADDRHIGH  0xffc03c8c   /* Upper 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4COUNTLOW  0xffc03c90   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 4 */
+#define                USB_DMA4COUNTHIGH  0xffc03c94   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 4 */
+
+/* USB Channel 5 Config Registers */
+
+#define                  USB_DMA5CONTROL  0xffc03ca4   /* DMA master channel 5 configuration */
+#define                  USB_DMA5ADDRLOW  0xffc03ca8   /* Lower 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5ADDRHIGH  0xffc03cac   /* Upper 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5COUNTLOW  0xffc03cb0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 5 */
+#define                USB_DMA5COUNTHIGH  0xffc03cb4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 5 */
+
+/* USB Channel 6 Config Registers */
+
+#define                  USB_DMA6CONTROL  0xffc03cc4   /* DMA master channel 6 configuration */
+#define                  USB_DMA6ADDRLOW  0xffc03cc8   /* Lower 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6ADDRHIGH  0xffc03ccc   /* Upper 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6COUNTLOW  0xffc03cd0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 6 */
+#define                USB_DMA6COUNTHIGH  0xffc03cd4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 6 */
+
+/* USB Channel 7 Config Registers */
+
+#define                  USB_DMA7CONTROL  0xffc03ce4   /* DMA master channel 7 configuration */
+#define                  USB_DMA7ADDRLOW  0xffc03ce8   /* Lower 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7ADDRHIGH  0xffc03cec   /* Upper 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7COUNTLOW  0xffc03cf0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 7 */
+#define                USB_DMA7COUNTHIGH  0xffc03cf4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 7 */
+
+/* Bit masks for USB_FADDR */
+
+#define          FUNCTION_ADDRESS  0x7f       /* Function address */
+
+/* Bit masks for USB_POWER */
+
+#define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
+#define          nENABLE_SUSPENDM  0x0       
+#define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
+#define             nSUSPEND_MODE  0x0       
+#define               RESUME_MODE  0x4        /* DMA Mode */
+#define              nRESUME_MODE  0x0       
+#define                     RESET  0x8        /* Reset indicator */
+#define                    nRESET  0x0       
+#define                   HS_MODE  0x10       /* High Speed mode indicator */
+#define                  nHS_MODE  0x0       
+#define                 HS_ENABLE  0x20       /* high Speed Enable */
+#define                nHS_ENABLE  0x0       
+#define                 SOFT_CONN  0x40       /* Soft connect */
+#define                nSOFT_CONN  0x0       
+#define                ISO_UPDATE  0x80       /* Isochronous update */
+#define               nISO_UPDATE  0x0       
+
+/* Bit masks for USB_INTRTX */
+
+#define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
+#define                   nEP0_TX  0x0       
+#define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
+#define                   nEP1_TX  0x0       
+#define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
+#define                   nEP2_TX  0x0       
+#define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
+#define                   nEP3_TX  0x0       
+#define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
+#define                   nEP4_TX  0x0       
+#define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
+#define                   nEP5_TX  0x0       
+#define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
+#define                   nEP6_TX  0x0       
+#define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
+#define                   nEP7_TX  0x0       
+
+/* Bit masks for USB_INTRRX */
+
+#define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
+#define                   nEP1_RX  0x0       
+#define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
+#define                   nEP2_RX  0x0       
+#define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
+#define                   nEP3_RX  0x0       
+#define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
+#define                   nEP4_RX  0x0       
+#define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
+#define                   nEP5_RX  0x0       
+#define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
+#define                   nEP6_RX  0x0       
+#define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
+#define                   nEP7_RX  0x0       
+
+/* Bit masks for USB_INTRTXE */
+
+#define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
+#define                 nEP0_TX_E  0x0       
+#define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
+#define                 nEP1_TX_E  0x0       
+#define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
+#define                 nEP2_TX_E  0x0       
+#define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
+#define                 nEP3_TX_E  0x0       
+#define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
+#define                 nEP4_TX_E  0x0       
+#define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
+#define                 nEP5_TX_E  0x0       
+#define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
+#define                 nEP6_TX_E  0x0       
+#define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
+#define                 nEP7_TX_E  0x0       
+
+/* Bit masks for USB_INTRRXE */
+
+#define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
+#define                 nEP1_RX_E  0x0       
+#define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
+#define                 nEP2_RX_E  0x0       
+#define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
+#define                 nEP3_RX_E  0x0       
+#define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
+#define                 nEP4_RX_E  0x0       
+#define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
+#define                 nEP5_RX_E  0x0       
+#define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
+#define                 nEP6_RX_E  0x0       
+#define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
+#define                 nEP7_RX_E  0x0       
+
+/* Bit masks for USB_INTRUSB */
+
+#define                 SUSPEND_B  0x1        /* Suspend indicator */
+#define                nSUSPEND_B  0x0       
+#define                  RESUME_B  0x2        /* Resume indicator */
+#define                 nRESUME_B  0x0       
+#define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
+#define         nRESET_OR_BABLE_B  0x0       
+#define                     SOF_B  0x8        /* Start of frame */
+#define                    nSOF_B  0x0       
+#define                    CONN_B  0x10       /* Connection indicator */
+#define                   nCONN_B  0x0       
+#define                  DISCON_B  0x20       /* Disconnect indicator */
+#define                 nDISCON_B  0x0       
+#define             SESSION_REQ_B  0x40       /* Session Request */
+#define            nSESSION_REQ_B  0x0       
+#define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
+#define             nVBUS_ERROR_B  0x0       
+
+/* Bit masks for USB_INTRUSBE */
+
+#define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
+#define               nSUSPEND_BE  0x0       
+#define                 RESUME_BE  0x2        /* Resume indicator int enable */
+#define                nRESUME_BE  0x0       
+#define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
+#define        nRESET_OR_BABLE_BE  0x0       
+#define                    SOF_BE  0x8        /* Start of frame int enable */
+#define                   nSOF_BE  0x0       
+#define                   CONN_BE  0x10       /* Connection indicator int enable */
+#define                  nCONN_BE  0x0       
+#define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
+#define                nDISCON_BE  0x0       
+#define            SESSION_REQ_BE  0x40       /* Session Request int enable */
+#define           nSESSION_REQ_BE  0x0       
+#define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
+#define            nVBUS_ERROR_BE  0x0       
+
+/* Bit masks for USB_FRAME */
+
+#define              FRAME_NUMBER  0x7ff      /* Frame number */
+
+/* Bit masks for USB_INDEX */
+
+#define         SELECTED_ENDPOINT  0xf        /* selected endpoint */
+
+/* Bit masks for USB_GLOBAL_CTL */
+
+#define                GLOBAL_ENA  0x1        /* enables USB module */
+#define               nGLOBAL_ENA  0x0       
+#define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
+#define               nEP1_TX_ENA  0x0       
+#define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
+#define               nEP2_TX_ENA  0x0       
+#define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
+#define               nEP3_TX_ENA  0x0       
+#define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
+#define               nEP4_TX_ENA  0x0       
+#define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
+#define               nEP5_TX_ENA  0x0       
+#define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
+#define               nEP6_TX_ENA  0x0       
+#define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
+#define               nEP7_TX_ENA  0x0       
+#define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
+#define               nEP1_RX_ENA  0x0       
+#define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
+#define               nEP2_RX_ENA  0x0       
+#define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
+#define               nEP3_RX_ENA  0x0       
+#define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
+#define               nEP4_RX_ENA  0x0       
+#define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
+#define               nEP5_RX_ENA  0x0       
+#define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
+#define               nEP6_RX_ENA  0x0       
+#define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
+#define               nEP7_RX_ENA  0x0       
+
+/* Bit masks for USB_OTG_DEV_CTL */
+
+#define                   SESSION  0x1        /* session indicator */
+#define                  nSESSION  0x0       
+#define                  HOST_REQ  0x2        /* Host negotiation request */
+#define                 nHOST_REQ  0x0       
+#define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
+#define                nHOST_MODE  0x0       
+#define                     VBUS0  0x8        /* Vbus level indicator[0] */
+#define                    nVBUS0  0x0       
+#define                     VBUS1  0x10       /* Vbus level indicator[1] */
+#define                    nVBUS1  0x0       
+#define                     LSDEV  0x20       /* Low-speed indicator */
+#define                    nLSDEV  0x0       
+#define                     FSDEV  0x40       /* Full or High-speed indicator */
+#define                    nFSDEV  0x0       
+#define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
+#define                 nB_DEVICE  0x0       
+
+/* Bit masks for USB_OTG_VBUS_IRQ */
+
+#define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
+#define            nDRIVE_VBUS_ON  0x0       
+#define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
+#define           nDRIVE_VBUS_OFF  0x0       
+#define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
+#define          nCHRG_VBUS_START  0x0       
+#define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
+#define            nCHRG_VBUS_END  0x0       
+#define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
+#define       nDISCHRG_VBUS_START  0x0       
+#define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
+#define         nDISCHRG_VBUS_END  0x0       
+
+/* Bit masks for USB_OTG_VBUS_MASK */
+
+#define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
+#define        nDRIVE_VBUS_ON_ENA  0x0       
+#define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
+#define       nDRIVE_VBUS_OFF_ENA  0x0       
+#define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
+#define      nCHRG_VBUS_START_ENA  0x0       
+#define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
+#define        nCHRG_VBUS_END_ENA  0x0       
+#define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
+#define   nDISCHRG_VBUS_START_ENA  0x0       
+#define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
+#define     nDISCHRG_VBUS_END_ENA  0x0       
+
+/* Bit masks for USB_CSR0 */
+
+#define                  RXPKTRDY  0x1        /* data packet receive indicator */
+#define                 nRXPKTRDY  0x0       
+#define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
+#define                 nTXPKTRDY  0x0       
+#define                STALL_SENT  0x4        /* STALL handshake sent */
+#define               nSTALL_SENT  0x0       
+#define                   DATAEND  0x8        /* Data end indicator */
+#define                  nDATAEND  0x0       
+#define                  SETUPEND  0x10       /* Setup end */
+#define                 nSETUPEND  0x0       
+#define                 SENDSTALL  0x20       /* Send STALL handshake */
+#define                nSENDSTALL  0x0       
+#define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
+#define        nSERVICED_RXPKTRDY  0x0       
+#define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
+#define        nSERVICED_SETUPEND  0x0       
+#define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
+#define                nFLUSHFIFO  0x0       
+#define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
+#define         nSTALL_RECEIVED_H  0x0       
+#define                SETUPPKT_H  0x8        /* send Setup token host mode */
+#define               nSETUPPKT_H  0x0       
+#define                   ERROR_H  0x10       /* timeout error indicator host mode */
+#define                  nERROR_H  0x0       
+#define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
+#define                 nREQPKT_H  0x0       
+#define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
+#define              nSTATUSPKT_H  0x0       
+#define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
+#define            nNAK_TIMEOUT_H  0x0       
+
+/* Bit masks for USB_COUNT0 */
+
+#define              EP0_RX_COUNT  0x7f       /* number of received bytes in EP0 FIFO */
+
+/* Bit masks for USB_NAKLIMIT0 */
+
+#define             EP0_NAK_LIMIT  0x1f       /* number of frames/micro frames after which EP0 timeouts */
+
+/* Bit masks for USB_TX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_T  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_RX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_R  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_TXCSR */
+
+#define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
+#define               nTXPKTRDY_T  0x0       
+#define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
+#define         nFIFO_NOT_EMPTY_T  0x0       
+#define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
+#define               nUNDERRUN_T  0x0       
+#define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
+#define              nFLUSHFIFO_T  0x0       
+#define              STALL_SEND_T  0x10       /* issue a Stall handshake */
+#define             nSTALL_SEND_T  0x0       
+#define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
+#define             nSTALL_SENT_T  0x0       
+#define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
+#define       nCLEAR_DATATOGGLE_T  0x0       
+#define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
+#define               nINCOMPTX_T  0x0       
+#define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
+#define             nDMAREQMODE_T  0x0       
+#define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
+#define       nFORCE_DATATOGGLE_T  0x0       
+#define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
+#define             nDMAREQ_ENA_T  0x0       
+#define                     ISO_T  0x4000     /* enable Isochronous transfers */
+#define                    nISO_T  0x0       
+#define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
+#define                nAUTOSET_T  0x0       
+#define                  ERROR_TH  0x4        /* error condition host mode */
+#define                 nERROR_TH  0x0       
+#define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
+#define        nSTALL_RECEIVED_TH  0x0       
+#define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
+#define           nNAK_TIMEOUT_TH  0x0       
+
+/* Bit masks for USB_TXCOUNT */
+
+#define                  TX_COUNT  0x1fff     /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* Bit masks for USB_RXCSR */
+
+#define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
+#define               nRXPKTRDY_R  0x0       
+#define               FIFO_FULL_R  0x2        /* FIFO not empty */
+#define              nFIFO_FULL_R  0x0       
+#define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
+#define                nOVERRUN_R  0x0       
+#define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
+#define              nDATAERROR_R  0x0       
+#define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
+#define              nFLUSHFIFO_R  0x0       
+#define              STALL_SEND_R  0x20       /* issue a Stall handshake */
+#define             nSTALL_SEND_R  0x0       
+#define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
+#define             nSTALL_SENT_R  0x0       
+#define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
+#define       nCLEAR_DATATOGGLE_R  0x0       
+#define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
+#define               nINCOMPRX_R  0x0       
+#define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
+#define             nDMAREQMODE_R  0x0       
+#define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
+#define                nDISNYET_R  0x0       
+#define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
+#define             nDMAREQ_ENA_R  0x0       
+#define                     ISO_R  0x4000     /* enable Isochronous transfers */
+#define                    nISO_R  0x0       
+#define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
+#define              nAUTOCLEAR_R  0x0       
+#define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
+#define                 nERROR_RH  0x0       
+#define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
+#define                nREQPKT_RH  0x0       
+#define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
+#define        nSTALL_RECEIVED_RH  0x0       
+#define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
+#define              nINCOMPRX_RH  0x0       
+#define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
+#define            nDMAREQMODE_RH  0x0       
+#define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
+#define               nAUTOREQ_RH  0x0       
+
+/* Bit masks for USB_RXCOUNT */
+
+#define                  RX_COUNT  0x1fff     /* Number of received bytes in the packet in the Rx FIFO */
+
+/* Bit masks for USB_TXTYPE */
+
+#define            TARGET_EP_NO_T  0xf        /* EP number */
+#define                PROTOCOL_T  0xc        /* transfer type */
+
+/* Bit masks for USB_TXINTERVAL */
+
+#define          TX_POLL_INTERVAL  0xff       /* polling interval for selected Tx EP */
+
+/* Bit masks for USB_RXTYPE */
+
+#define            TARGET_EP_NO_R  0xf        /* EP number */
+#define                PROTOCOL_R  0xc        /* transfer type */
+
+/* Bit masks for USB_RXINTERVAL */
+
+#define          RX_POLL_INTERVAL  0xff       /* polling interval for selected Rx EP */
+
+/* Bit masks for USB_DMA_INTERRUPT */
+
+#define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
+#define                 nDMA0_INT  0x0       
+#define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
+#define                 nDMA1_INT  0x0       
+#define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
+#define                 nDMA2_INT  0x0       
+#define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
+#define                 nDMA3_INT  0x0       
+#define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
+#define                 nDMA4_INT  0x0       
+#define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
+#define                 nDMA5_INT  0x0       
+#define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
+#define                 nDMA6_INT  0x0       
+#define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
+#define                 nDMA7_INT  0x0       
+
+/* Bit masks for USB_DMAxCONTROL */
+
+#define                   DMA_ENA  0x1        /* DMA enable */
+#define                  nDMA_ENA  0x0       
+#define                 DIRECTION  0x2        /* direction of DMA transfer */
+#define                nDIRECTION  0x0       
+#define                      MODE  0x4        /* DMA Bus error */
+#define                     nMODE  0x0       
+#define                   INT_ENA  0x8        /* Interrupt enable */
+#define                  nINT_ENA  0x0       
+#define                     EPNUM  0xf0       /* EP number */
+#define                  BUSERROR  0x100      /* DMA Bus error */
+#define                 nBUSERROR  0x0       
+
+/* Bit masks for USB_DMAxADDRHIGH */
+
+#define             DMA_ADDR_HIGH  0xffff     /* Upper 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxADDRLOW */
+
+#define              DMA_ADDR_LOW  0xffff     /* Lower 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTHIGH */
+
+#define            DMA_COUNT_HIGH  0xffff     /* Upper 16-bits of byte count of DMA transfer for DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTLOW */
+
+#define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
+
+#endif /* _DEF_BF527_H */
diff --git a/include/asm-blackfin/mach-bf527/defBF52x_base.h b/include/asm-blackfin/mach-bf527/defBF52x_base.h
new file mode 100644
index 0000000..0b2fb50
--- /dev/null
+++ b/include/asm-blackfin/mach-bf527/defBF52x_base.h
@@ -0,0 +1,2009 @@
+/*
+ * File:         include/asm-blackfin/mach-bf527/defBF52x_base.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF52X_H
+#define _DEF_BF52X_H
+
+
+/* ************************************************************** */
+/*   SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF52x    */
+/* ************************************************************** */
+
+/* ==== begin from defBF534.h ==== */
+
+/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
+#define PLL_CTL				0xFFC00000	/* PLL Control Register						*/
+#define PLL_DIV				0xFFC00004	/* PLL Divide Register						*/
+#define VR_CTL				0xFFC00008	/* Voltage Regulator Control Register		*/
+#define PLL_STAT			0xFFC0000C	/* PLL Status Register						*/
+#define PLL_LOCKCNT			0xFFC00010	/* PLL Lock Count Register					*/
+#define CHIPID        0xFFC00014  /* Device ID Register */
+
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)							*/
+#define SWRST				0xFFC00100	/* Software Reset Register					*/
+#define SYSCR				0xFFC00104	/* System Configuration Register			*/
+#define SIC_RVECT			0xFFC00108	/* Interrupt Reset Vector Address Register	*/
+
+#define SIC_IMASK			0xFFC0010C	/* Interrupt Mask Register					*/
+#define SIC_IAR0			0xFFC00110	/* Interrupt Assignment Register 0			*/
+#define SIC_IAR1			0xFFC00114	/* Interrupt Assignment Register 1			*/
+#define SIC_IAR2			0xFFC00118	/* Interrupt Assignment Register 2			*/
+#define SIC_IAR3			0xFFC0011C	/* Interrupt Assignment Register 3			*/
+#define SIC_ISR				0xFFC00120	/* Interrupt Status Register				*/
+#define SIC_IWR				0xFFC00124	/* Interrupt Wakeup Register				*/
+
+/* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */
+#define SIC_IMASK1                      0xFFC0014C     /* Interrupt Mask register of SIC2 */
+#define SIC_IAR4                        0xFFC00150     /* Interrupt Assignment register4 */
+#define SIC_IAR5                        0xFFC00154     /* Interrupt Assignment register5 */
+#define SIC_IAR6                        0xFFC00158     /* Interrupt Assignment register6 */
+#define SIC_IAR7                        0xFFC0015C     /* Interrupt Assignment register7 */
+#define SIC_ISR1                        0xFFC00160     /* Interrupt Statur register */
+#define SIC_IWR1                        0xFFC00164     /* Interrupt Wakeup register */
+
+
+/* Watchdog Timer			(0xFFC00200 - 0xFFC002FF)								*/
+#define WDOG_CTL			0xFFC00200	/* Watchdog Control Register				*/
+#define WDOG_CNT			0xFFC00204	/* Watchdog Count Register					*/
+#define WDOG_STAT			0xFFC00208	/* Watchdog Status Register					*/
+
+
+/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
+#define RTC_STAT			0xFFC00300	/* RTC Status Register						*/
+#define RTC_ICTL			0xFFC00304	/* RTC Interrupt Control Register			*/
+#define RTC_ISTAT			0xFFC00308	/* RTC Interrupt Status Register			*/
+#define RTC_SWCNT			0xFFC0030C	/* RTC Stopwatch Count Register				*/
+#define RTC_ALARM			0xFFC00310	/* RTC Alarm Time Register					*/
+#define RTC_FAST			0xFFC00314	/* RTC Prescaler Enable Register			*/
+#define RTC_PREN			0xFFC00314	/* RTC Prescaler Enable Alternate Macro		*/
+
+
+/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
+#define UART0_THR			0xFFC00400	/* Transmit Holding register				*/
+#define UART0_RBR			0xFFC00400	/* Receive Buffer register					*/
+#define UART0_DLL			0xFFC00400	/* Divisor Latch (Low-Byte)					*/
+#define UART0_IER			0xFFC00404	/* Interrupt Enable Register				*/
+#define UART0_DLH			0xFFC00404	/* Divisor Latch (High-Byte)				*/
+#define UART0_IIR			0xFFC00408	/* Interrupt Identification Register		*/
+#define UART0_LCR			0xFFC0040C	/* Line Control Register					*/
+#define UART0_MCR			0xFFC00410	/* Modem Control Register					*/
+#define UART0_LSR			0xFFC00414	/* Line Status Register						*/
+#define UART0_MSR			0xFFC00418	/* Modem Status Register					*/
+#define UART0_SCR			0xFFC0041C	/* SCR Scratch Register						*/
+#define UART0_GCTL			0xFFC00424	/* Global Control Register					*/
+
+
+/* SPI Controller			(0xFFC00500 - 0xFFC005FF)								*/
+#define SPI_CTL				0xFFC00500	/* SPI Control Register						*/
+#define SPI_FLG				0xFFC00504	/* SPI Flag register						*/
+#define SPI_STAT			0xFFC00508	/* SPI Status register						*/
+#define SPI_TDBR			0xFFC0050C	/* SPI Transmit Data Buffer Register		*/
+#define SPI_RDBR			0xFFC00510	/* SPI Receive Data Buffer Register			*/
+#define SPI_BAUD			0xFFC00514	/* SPI Baud rate Register					*/
+#define SPI_SHADOW			0xFFC00518	/* SPI_RDBR Shadow Register					*/
+
+
+/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
+#define TIMER0_CONFIG		0xFFC00600	/* Timer 0 Configuration Register			*/
+#define TIMER0_COUNTER		0xFFC00604	/* Timer 0 Counter Register					*/
+#define TIMER0_PERIOD		0xFFC00608	/* Timer 0 Period Register					*/
+#define TIMER0_WIDTH		0xFFC0060C	/* Timer 0 Width Register					*/
+
+#define TIMER1_CONFIG		0xFFC00610	/* Timer 1 Configuration Register  			*/
+#define TIMER1_COUNTER		0xFFC00614	/* Timer 1 Counter Register        			*/
+#define TIMER1_PERIOD		0xFFC00618	/* Timer 1 Period Register         			*/
+#define TIMER1_WIDTH		0xFFC0061C	/* Timer 1 Width Register          			*/
+
+#define TIMER2_CONFIG		0xFFC00620	/* Timer 2 Configuration Register  			*/
+#define TIMER2_COUNTER		0xFFC00624	/* Timer 2 Counter Register        			*/
+#define TIMER2_PERIOD		0xFFC00628	/* Timer 2 Period Register         			*/
+#define TIMER2_WIDTH		0xFFC0062C	/* Timer 2 Width Register          			*/
+
+#define TIMER3_CONFIG		0xFFC00630	/* Timer 3 Configuration Register			*/
+#define TIMER3_COUNTER		0xFFC00634	/* Timer 3 Counter Register					*/
+#define TIMER3_PERIOD		0xFFC00638	/* Timer 3 Period Register					*/
+#define TIMER3_WIDTH		0xFFC0063C	/* Timer 3 Width Register					*/
+
+#define TIMER4_CONFIG		0xFFC00640	/* Timer 4 Configuration Register  			*/
+#define TIMER4_COUNTER		0xFFC00644	/* Timer 4 Counter Register        			*/
+#define TIMER4_PERIOD		0xFFC00648	/* Timer 4 Period Register         			*/
+#define TIMER4_WIDTH		0xFFC0064C	/* Timer 4 Width Register          			*/
+
+#define TIMER5_CONFIG		0xFFC00650	/* Timer 5 Configuration Register  			*/
+#define TIMER5_COUNTER		0xFFC00654	/* Timer 5 Counter Register        			*/
+#define TIMER5_PERIOD		0xFFC00658	/* Timer 5 Period Register         			*/
+#define TIMER5_WIDTH		0xFFC0065C	/* Timer 5 Width Register          			*/
+
+#define TIMER6_CONFIG		0xFFC00660	/* Timer 6 Configuration Register  			*/
+#define TIMER6_COUNTER		0xFFC00664	/* Timer 6 Counter Register        			*/
+#define TIMER6_PERIOD		0xFFC00668	/* Timer 6 Period Register         			*/
+#define TIMER6_WIDTH		0xFFC0066C	/* Timer 6 Width Register          			*/
+
+#define TIMER7_CONFIG		0xFFC00670	/* Timer 7 Configuration Register  			*/
+#define TIMER7_COUNTER		0xFFC00674	/* Timer 7 Counter Register        			*/
+#define TIMER7_PERIOD		0xFFC00678	/* Timer 7 Period Register         			*/
+#define TIMER7_WIDTH		0xFFC0067C	/* Timer 7 Width Register       			*/   
+
+#define TIMER_ENABLE		0xFFC00680	/* Timer Enable Register					*/
+#define TIMER_DISABLE		0xFFC00684	/* Timer Disable Register					*/
+#define TIMER_STATUS		0xFFC00688	/* Timer Status Register					*/
+
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)												*/
+#define PORTFIO					0xFFC00700	/* Port F I/O Pin State Specify Register				*/
+#define PORTFIO_CLEAR			0xFFC00704	/* Port F I/O Peripheral Interrupt Clear Register		*/
+#define PORTFIO_SET				0xFFC00708	/* Port F I/O Peripheral Interrupt Set Register			*/
+#define PORTFIO_TOGGLE			0xFFC0070C	/* Port F I/O Pin State Toggle Register					*/
+#define PORTFIO_MASKA			0xFFC00710	/* Port F I/O Mask State Specify Interrupt A Register	*/
+#define PORTFIO_MASKA_CLEAR		0xFFC00714	/* Port F I/O Mask Disable Interrupt A Register			*/
+#define PORTFIO_MASKA_SET		0xFFC00718	/* Port F I/O Mask Enable Interrupt A Register			*/
+#define PORTFIO_MASKA_TOGGLE	0xFFC0071C	/* Port F I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTFIO_MASKB			0xFFC00720	/* Port F I/O Mask State Specify Interrupt B Register	*/
+#define PORTFIO_MASKB_CLEAR		0xFFC00724	/* Port F I/O Mask Disable Interrupt B Register			*/
+#define PORTFIO_MASKB_SET		0xFFC00728	/* Port F I/O Mask Enable Interrupt B Register			*/
+#define PORTFIO_MASKB_TOGGLE	0xFFC0072C	/* Port F I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTFIO_DIR				0xFFC00730	/* Port F I/O Direction Register						*/
+#define PORTFIO_POLAR			0xFFC00734	/* Port F I/O Source Polarity Register					*/
+#define PORTFIO_EDGE			0xFFC00738	/* Port F I/O Source Sensitivity Register				*/
+#define PORTFIO_BOTH			0xFFC0073C	/* Port F I/O Set on BOTH Edges Register				*/
+#define PORTFIO_INEN			0xFFC00740	/* Port F I/O Input Enable Register 					*/
+
+
+/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)										*/
+#define SPORT0_TCR1			0xFFC00800	/* SPORT0 Transmit Configuration 1 Register			*/
+#define SPORT0_TCR2			0xFFC00804	/* SPORT0 Transmit Configuration 2 Register			*/
+#define SPORT0_TCLKDIV		0xFFC00808	/* SPORT0 Transmit Clock Divider					*/
+#define SPORT0_TFSDIV		0xFFC0080C	/* SPORT0 Transmit Frame Sync Divider				*/
+#define SPORT0_TX			0xFFC00810	/* SPORT0 TX Data Register							*/
+#define SPORT0_RX			0xFFC00818	/* SPORT0 RX Data Register							*/
+#define SPORT0_RCR1			0xFFC00820	/* SPORT0 Transmit Configuration 1 Register			*/
+#define SPORT0_RCR2			0xFFC00824	/* SPORT0 Transmit Configuration 2 Register			*/
+#define SPORT0_RCLKDIV		0xFFC00828	/* SPORT0 Receive Clock Divider						*/
+#define SPORT0_RFSDIV		0xFFC0082C	/* SPORT0 Receive Frame Sync Divider				*/
+#define SPORT0_STAT			0xFFC00830	/* SPORT0 Status Register							*/
+#define SPORT0_CHNL			0xFFC00834	/* SPORT0 Current Channel Register					*/
+#define SPORT0_MCMC1		0xFFC00838	/* SPORT0 Multi-Channel Configuration Register 1	*/
+#define SPORT0_MCMC2		0xFFC0083C	/* SPORT0 Multi-Channel Configuration Register 2	*/
+#define SPORT0_MTCS0		0xFFC00840	/* SPORT0 Multi-Channel Transmit Select Register 0	*/
+#define SPORT0_MTCS1		0xFFC00844	/* SPORT0 Multi-Channel Transmit Select Register 1	*/
+#define SPORT0_MTCS2		0xFFC00848	/* SPORT0 Multi-Channel Transmit Select Register 2	*/
+#define SPORT0_MTCS3		0xFFC0084C	/* SPORT0 Multi-Channel Transmit Select Register 3	*/
+#define SPORT0_MRCS0		0xFFC00850	/* SPORT0 Multi-Channel Receive Select Register 0	*/
+#define SPORT0_MRCS1		0xFFC00854	/* SPORT0 Multi-Channel Receive Select Register 1	*/
+#define SPORT0_MRCS2		0xFFC00858	/* SPORT0 Multi-Channel Receive Select Register 2	*/
+#define SPORT0_MRCS3		0xFFC0085C	/* SPORT0 Multi-Channel Receive Select Register 3	*/
+
+
+/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)										*/
+#define SPORT1_TCR1			0xFFC00900	/* SPORT1 Transmit Configuration 1 Register			*/
+#define SPORT1_TCR2			0xFFC00904	/* SPORT1 Transmit Configuration 2 Register			*/
+#define SPORT1_TCLKDIV		0xFFC00908	/* SPORT1 Transmit Clock Divider					*/
+#define SPORT1_TFSDIV		0xFFC0090C	/* SPORT1 Transmit Frame Sync Divider				*/
+#define SPORT1_TX			0xFFC00910	/* SPORT1 TX Data Register							*/
+#define SPORT1_RX			0xFFC00918	/* SPORT1 RX Data Register							*/
+#define SPORT1_RCR1			0xFFC00920	/* SPORT1 Transmit Configuration 1 Register			*/
+#define SPORT1_RCR2			0xFFC00924	/* SPORT1 Transmit Configuration 2 Register			*/
+#define SPORT1_RCLKDIV		0xFFC00928	/* SPORT1 Receive Clock Divider						*/
+#define SPORT1_RFSDIV		0xFFC0092C	/* SPORT1 Receive Frame Sync Divider				*/
+#define SPORT1_STAT			0xFFC00930	/* SPORT1 Status Register							*/
+#define SPORT1_CHNL			0xFFC00934	/* SPORT1 Current Channel Register					*/
+#define SPORT1_MCMC1		0xFFC00938	/* SPORT1 Multi-Channel Configuration Register 1	*/
+#define SPORT1_MCMC2		0xFFC0093C	/* SPORT1 Multi-Channel Configuration Register 2	*/
+#define SPORT1_MTCS0		0xFFC00940	/* SPORT1 Multi-Channel Transmit Select Register 0	*/
+#define SPORT1_MTCS1		0xFFC00944	/* SPORT1 Multi-Channel Transmit Select Register 1	*/
+#define SPORT1_MTCS2		0xFFC00948	/* SPORT1 Multi-Channel Transmit Select Register 2	*/
+#define SPORT1_MTCS3		0xFFC0094C	/* SPORT1 Multi-Channel Transmit Select Register 3	*/
+#define SPORT1_MRCS0		0xFFC00950	/* SPORT1 Multi-Channel Receive Select Register 0	*/
+#define SPORT1_MRCS1		0xFFC00954	/* SPORT1 Multi-Channel Receive Select Register 1	*/
+#define SPORT1_MRCS2		0xFFC00958	/* SPORT1 Multi-Channel Receive Select Register 2	*/
+#define SPORT1_MRCS3		0xFFC0095C	/* SPORT1 Multi-Channel Receive Select Register 3	*/
+
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)								*/
+#define EBIU_AMGCTL			0xFFC00A00	/* Asynchronous Memory Global Control Register	*/
+#define EBIU_AMBCTL0		0xFFC00A04	/* Asynchronous Memory Bank Control Register 0	*/
+#define EBIU_AMBCTL1		0xFFC00A08	/* Asynchronous Memory Bank Control Register 1	*/
+#define EBIU_SDGCTL			0xFFC00A10	/* SDRAM Global Control Register				*/
+#define EBIU_SDBCTL			0xFFC00A14	/* SDRAM Bank Control Register					*/
+#define EBIU_SDRRC			0xFFC00A18	/* SDRAM Refresh Rate Control Register			*/
+#define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register						*/
+
+
+/* DMA Traffic Control Registers													*/
+#define DMA_TC_PER			0xFFC00B0C	/* Traffic Control Periods Register			*/
+#define DMA_TC_CNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define DMA_TCPER			0xFFC00B0C	/* Traffic Control Periods Register			*/
+#define DMA_TCCNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
+
+/* DMA Controller (0xFFC00C00 - 0xFFC00FFF)															*/
+#define DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register		*/
+#define DMA0_START_ADDR			0xFFC00C04	/* DMA Channel 0 Start Address Register					*/
+#define DMA0_CONFIG				0xFFC00C08	/* DMA Channel 0 Configuration Register					*/
+#define DMA0_X_COUNT			0xFFC00C10	/* DMA Channel 0 X Count Register						*/
+#define DMA0_X_MODIFY			0xFFC00C14	/* DMA Channel 0 X Modify Register						*/
+#define DMA0_Y_COUNT			0xFFC00C18	/* DMA Channel 0 Y Count Register						*/
+#define DMA0_Y_MODIFY			0xFFC00C1C	/* DMA Channel 0 Y Modify Register						*/
+#define DMA0_CURR_DESC_PTR		0xFFC00C20	/* DMA Channel 0 Current Descriptor Pointer Register	*/
+#define DMA0_CURR_ADDR			0xFFC00C24	/* DMA Channel 0 Current Address Register				*/
+#define DMA0_IRQ_STATUS			0xFFC00C28	/* DMA Channel 0 Interrupt/Status Register				*/
+#define DMA0_PERIPHERAL_MAP		0xFFC00C2C	/* DMA Channel 0 Peripheral Map Register				*/
+#define DMA0_CURR_X_COUNT		0xFFC00C30	/* DMA Channel 0 Current X Count Register				*/
+#define DMA0_CURR_Y_COUNT		0xFFC00C38	/* DMA Channel 0 Current Y Count Register				*/
+
+#define DMA1_NEXT_DESC_PTR		0xFFC00C40	/* DMA Channel 1 Next Descriptor Pointer Register		*/
+#define DMA1_START_ADDR			0xFFC00C44	/* DMA Channel 1 Start Address Register					*/
+#define DMA1_CONFIG				0xFFC00C48	/* DMA Channel 1 Configuration Register					*/
+#define DMA1_X_COUNT			0xFFC00C50	/* DMA Channel 1 X Count Register						*/
+#define DMA1_X_MODIFY			0xFFC00C54	/* DMA Channel 1 X Modify Register						*/
+#define DMA1_Y_COUNT			0xFFC00C58	/* DMA Channel 1 Y Count Register						*/
+#define DMA1_Y_MODIFY			0xFFC00C5C	/* DMA Channel 1 Y Modify Register						*/
+#define DMA1_CURR_DESC_PTR		0xFFC00C60	/* DMA Channel 1 Current Descriptor Pointer Register	*/
+#define DMA1_CURR_ADDR			0xFFC00C64	/* DMA Channel 1 Current Address Register				*/
+#define DMA1_IRQ_STATUS			0xFFC00C68	/* DMA Channel 1 Interrupt/Status Register				*/
+#define DMA1_PERIPHERAL_MAP		0xFFC00C6C	/* DMA Channel 1 Peripheral Map Register				*/
+#define DMA1_CURR_X_COUNT		0xFFC00C70	/* DMA Channel 1 Current X Count Register				*/
+#define DMA1_CURR_Y_COUNT		0xFFC00C78	/* DMA Channel 1 Current Y Count Register				*/
+
+#define DMA2_NEXT_DESC_PTR		0xFFC00C80	/* DMA Channel 2 Next Descriptor Pointer Register		*/
+#define DMA2_START_ADDR			0xFFC00C84	/* DMA Channel 2 Start Address Register					*/
+#define DMA2_CONFIG				0xFFC00C88	/* DMA Channel 2 Configuration Register					*/
+#define DMA2_X_COUNT			0xFFC00C90	/* DMA Channel 2 X Count Register						*/
+#define DMA2_X_MODIFY			0xFFC00C94	/* DMA Channel 2 X Modify Register						*/
+#define DMA2_Y_COUNT			0xFFC00C98	/* DMA Channel 2 Y Count Register						*/
+#define DMA2_Y_MODIFY			0xFFC00C9C	/* DMA Channel 2 Y Modify Register						*/
+#define DMA2_CURR_DESC_PTR		0xFFC00CA0	/* DMA Channel 2 Current Descriptor Pointer Register	*/
+#define DMA2_CURR_ADDR			0xFFC00CA4	/* DMA Channel 2 Current Address Register				*/
+#define DMA2_IRQ_STATUS			0xFFC00CA8	/* DMA Channel 2 Interrupt/Status Register				*/
+#define DMA2_PERIPHERAL_MAP		0xFFC00CAC	/* DMA Channel 2 Peripheral Map Register				*/
+#define DMA2_CURR_X_COUNT		0xFFC00CB0	/* DMA Channel 2 Current X Count Register				*/
+#define DMA2_CURR_Y_COUNT		0xFFC00CB8	/* DMA Channel 2 Current Y Count Register				*/
+
+#define DMA3_NEXT_DESC_PTR		0xFFC00CC0	/* DMA Channel 3 Next Descriptor Pointer Register		*/
+#define DMA3_START_ADDR			0xFFC00CC4	/* DMA Channel 3 Start Address Register					*/
+#define DMA3_CONFIG				0xFFC00CC8	/* DMA Channel 3 Configuration Register					*/
+#define DMA3_X_COUNT			0xFFC00CD0	/* DMA Channel 3 X Count Register						*/
+#define DMA3_X_MODIFY			0xFFC00CD4	/* DMA Channel 3 X Modify Register						*/
+#define DMA3_Y_COUNT			0xFFC00CD8	/* DMA Channel 3 Y Count Register						*/
+#define DMA3_Y_MODIFY			0xFFC00CDC	/* DMA Channel 3 Y Modify Register						*/
+#define DMA3_CURR_DESC_PTR		0xFFC00CE0	/* DMA Channel 3 Current Descriptor Pointer Register	*/
+#define DMA3_CURR_ADDR			0xFFC00CE4	/* DMA Channel 3 Current Address Register				*/
+#define DMA3_IRQ_STATUS			0xFFC00CE8	/* DMA Channel 3 Interrupt/Status Register				*/
+#define DMA3_PERIPHERAL_MAP		0xFFC00CEC	/* DMA Channel 3 Peripheral Map Register				*/
+#define DMA3_CURR_X_COUNT		0xFFC00CF0	/* DMA Channel 3 Current X Count Register				*/
+#define DMA3_CURR_Y_COUNT		0xFFC00CF8	/* DMA Channel 3 Current Y Count Register				*/
+
+#define DMA4_NEXT_DESC_PTR		0xFFC00D00	/* DMA Channel 4 Next Descriptor Pointer Register		*/
+#define DMA4_START_ADDR			0xFFC00D04	/* DMA Channel 4 Start Address Register					*/
+#define DMA4_CONFIG				0xFFC00D08	/* DMA Channel 4 Configuration Register					*/
+#define DMA4_X_COUNT			0xFFC00D10	/* DMA Channel 4 X Count Register						*/
+#define DMA4_X_MODIFY			0xFFC00D14	/* DMA Channel 4 X Modify Register						*/
+#define DMA4_Y_COUNT			0xFFC00D18	/* DMA Channel 4 Y Count Register						*/
+#define DMA4_Y_MODIFY			0xFFC00D1C	/* DMA Channel 4 Y Modify Register						*/
+#define DMA4_CURR_DESC_PTR		0xFFC00D20	/* DMA Channel 4 Current Descriptor Pointer Register	*/
+#define DMA4_CURR_ADDR			0xFFC00D24	/* DMA Channel 4 Current Address Register				*/
+#define DMA4_IRQ_STATUS			0xFFC00D28	/* DMA Channel 4 Interrupt/Status Register				*/
+#define DMA4_PERIPHERAL_MAP		0xFFC00D2C	/* DMA Channel 4 Peripheral Map Register				*/
+#define DMA4_CURR_X_COUNT		0xFFC00D30	/* DMA Channel 4 Current X Count Register				*/
+#define DMA4_CURR_Y_COUNT		0xFFC00D38	/* DMA Channel 4 Current Y Count Register				*/
+
+#define DMA5_NEXT_DESC_PTR		0xFFC00D40	/* DMA Channel 5 Next Descriptor Pointer Register		*/
+#define DMA5_START_ADDR			0xFFC00D44	/* DMA Channel 5 Start Address Register					*/
+#define DMA5_CONFIG				0xFFC00D48	/* DMA Channel 5 Configuration Register					*/
+#define DMA5_X_COUNT			0xFFC00D50	/* DMA Channel 5 X Count Register						*/
+#define DMA5_X_MODIFY			0xFFC00D54	/* DMA Channel 5 X Modify Register						*/
+#define DMA5_Y_COUNT			0xFFC00D58	/* DMA Channel 5 Y Count Register						*/
+#define DMA5_Y_MODIFY			0xFFC00D5C	/* DMA Channel 5 Y Modify Register						*/
+#define DMA5_CURR_DESC_PTR		0xFFC00D60	/* DMA Channel 5 Current Descriptor Pointer Register	*/
+#define DMA5_CURR_ADDR			0xFFC00D64	/* DMA Channel 5 Current Address Register				*/
+#define DMA5_IRQ_STATUS			0xFFC00D68	/* DMA Channel 5 Interrupt/Status Register				*/
+#define DMA5_PERIPHERAL_MAP		0xFFC00D6C	/* DMA Channel 5 Peripheral Map Register				*/
+#define DMA5_CURR_X_COUNT		0xFFC00D70	/* DMA Channel 5 Current X Count Register				*/
+#define DMA5_CURR_Y_COUNT		0xFFC00D78	/* DMA Channel 5 Current Y Count Register				*/
+
+#define DMA6_NEXT_DESC_PTR		0xFFC00D80	/* DMA Channel 6 Next Descriptor Pointer Register		*/
+#define DMA6_START_ADDR			0xFFC00D84	/* DMA Channel 6 Start Address Register					*/
+#define DMA6_CONFIG				0xFFC00D88	/* DMA Channel 6 Configuration Register					*/
+#define DMA6_X_COUNT			0xFFC00D90	/* DMA Channel 6 X Count Register						*/
+#define DMA6_X_MODIFY			0xFFC00D94	/* DMA Channel 6 X Modify Register						*/
+#define DMA6_Y_COUNT			0xFFC00D98	/* DMA Channel 6 Y Count Register						*/
+#define DMA6_Y_MODIFY			0xFFC00D9C	/* DMA Channel 6 Y Modify Register						*/
+#define DMA6_CURR_DESC_PTR		0xFFC00DA0	/* DMA Channel 6 Current Descriptor Pointer Register	*/
+#define DMA6_CURR_ADDR			0xFFC00DA4	/* DMA Channel 6 Current Address Register				*/
+#define DMA6_IRQ_STATUS			0xFFC00DA8	/* DMA Channel 6 Interrupt/Status Register				*/
+#define DMA6_PERIPHERAL_MAP		0xFFC00DAC	/* DMA Channel 6 Peripheral Map Register				*/
+#define DMA6_CURR_X_COUNT		0xFFC00DB0	/* DMA Channel 6 Current X Count Register				*/
+#define DMA6_CURR_Y_COUNT		0xFFC00DB8	/* DMA Channel 6 Current Y Count Register				*/
+
+#define DMA7_NEXT_DESC_PTR		0xFFC00DC0	/* DMA Channel 7 Next Descriptor Pointer Register		*/
+#define DMA7_START_ADDR			0xFFC00DC4	/* DMA Channel 7 Start Address Register					*/
+#define DMA7_CONFIG				0xFFC00DC8	/* DMA Channel 7 Configuration Register					*/
+#define DMA7_X_COUNT			0xFFC00DD0	/* DMA Channel 7 X Count Register						*/
+#define DMA7_X_MODIFY			0xFFC00DD4	/* DMA Channel 7 X Modify Register						*/
+#define DMA7_Y_COUNT			0xFFC00DD8	/* DMA Channel 7 Y Count Register						*/
+#define DMA7_Y_MODIFY			0xFFC00DDC	/* DMA Channel 7 Y Modify Register						*/
+#define DMA7_CURR_DESC_PTR		0xFFC00DE0	/* DMA Channel 7 Current Descriptor Pointer Register	*/
+#define DMA7_CURR_ADDR			0xFFC00DE4	/* DMA Channel 7 Current Address Register				*/
+#define DMA7_IRQ_STATUS			0xFFC00DE8	/* DMA Channel 7 Interrupt/Status Register				*/
+#define DMA7_PERIPHERAL_MAP		0xFFC00DEC	/* DMA Channel 7 Peripheral Map Register				*/
+#define DMA7_CURR_X_COUNT		0xFFC00DF0	/* DMA Channel 7 Current X Count Register				*/
+#define DMA7_CURR_Y_COUNT		0xFFC00DF8	/* DMA Channel 7 Current Y Count Register				*/
+
+#define DMA8_NEXT_DESC_PTR		0xFFC00E00	/* DMA Channel 8 Next Descriptor Pointer Register		*/
+#define DMA8_START_ADDR			0xFFC00E04	/* DMA Channel 8 Start Address Register					*/
+#define DMA8_CONFIG				0xFFC00E08	/* DMA Channel 8 Configuration Register					*/
+#define DMA8_X_COUNT			0xFFC00E10	/* DMA Channel 8 X Count Register						*/
+#define DMA8_X_MODIFY			0xFFC00E14	/* DMA Channel 8 X Modify Register						*/
+#define DMA8_Y_COUNT			0xFFC00E18	/* DMA Channel 8 Y Count Register						*/
+#define DMA8_Y_MODIFY			0xFFC00E1C	/* DMA Channel 8 Y Modify Register						*/
+#define DMA8_CURR_DESC_PTR		0xFFC00E20	/* DMA Channel 8 Current Descriptor Pointer Register	*/
+#define DMA8_CURR_ADDR			0xFFC00E24	/* DMA Channel 8 Current Address Register				*/
+#define DMA8_IRQ_STATUS			0xFFC00E28	/* DMA Channel 8 Interrupt/Status Register				*/
+#define DMA8_PERIPHERAL_MAP		0xFFC00E2C	/* DMA Channel 8 Peripheral Map Register				*/
+#define DMA8_CURR_X_COUNT		0xFFC00E30	/* DMA Channel 8 Current X Count Register				*/
+#define DMA8_CURR_Y_COUNT		0xFFC00E38	/* DMA Channel 8 Current Y Count Register				*/
+
+#define DMA9_NEXT_DESC_PTR		0xFFC00E40	/* DMA Channel 9 Next Descriptor Pointer Register		*/
+#define DMA9_START_ADDR			0xFFC00E44	/* DMA Channel 9 Start Address Register					*/
+#define DMA9_CONFIG				0xFFC00E48	/* DMA Channel 9 Configuration Register					*/
+#define DMA9_X_COUNT			0xFFC00E50	/* DMA Channel 9 X Count Register						*/
+#define DMA9_X_MODIFY			0xFFC00E54	/* DMA Channel 9 X Modify Register						*/
+#define DMA9_Y_COUNT			0xFFC00E58	/* DMA Channel 9 Y Count Register						*/
+#define DMA9_Y_MODIFY			0xFFC00E5C	/* DMA Channel 9 Y Modify Register						*/
+#define DMA9_CURR_DESC_PTR		0xFFC00E60	/* DMA Channel 9 Current Descriptor Pointer Register	*/
+#define DMA9_CURR_ADDR			0xFFC00E64	/* DMA Channel 9 Current Address Register				*/
+#define DMA9_IRQ_STATUS			0xFFC00E68	/* DMA Channel 9 Interrupt/Status Register				*/
+#define DMA9_PERIPHERAL_MAP		0xFFC00E6C	/* DMA Channel 9 Peripheral Map Register				*/
+#define DMA9_CURR_X_COUNT		0xFFC00E70	/* DMA Channel 9 Current X Count Register				*/
+#define DMA9_CURR_Y_COUNT		0xFFC00E78	/* DMA Channel 9 Current Y Count Register				*/
+
+#define DMA10_NEXT_DESC_PTR		0xFFC00E80	/* DMA Channel 10 Next Descriptor Pointer Register		*/
+#define DMA10_START_ADDR		0xFFC00E84	/* DMA Channel 10 Start Address Register				*/
+#define DMA10_CONFIG			0xFFC00E88	/* DMA Channel 10 Configuration Register				*/
+#define DMA10_X_COUNT			0xFFC00E90	/* DMA Channel 10 X Count Register						*/
+#define DMA10_X_MODIFY			0xFFC00E94	/* DMA Channel 10 X Modify Register						*/
+#define DMA10_Y_COUNT			0xFFC00E98	/* DMA Channel 10 Y Count Register						*/
+#define DMA10_Y_MODIFY			0xFFC00E9C	/* DMA Channel 10 Y Modify Register						*/
+#define DMA10_CURR_DESC_PTR		0xFFC00EA0	/* DMA Channel 10 Current Descriptor Pointer Register	*/
+#define DMA10_CURR_ADDR			0xFFC00EA4	/* DMA Channel 10 Current Address Register				*/
+#define DMA10_IRQ_STATUS		0xFFC00EA8	/* DMA Channel 10 Interrupt/Status Register				*/
+#define DMA10_PERIPHERAL_MAP	0xFFC00EAC	/* DMA Channel 10 Peripheral Map Register				*/
+#define DMA10_CURR_X_COUNT		0xFFC00EB0	/* DMA Channel 10 Current X Count Register				*/
+#define DMA10_CURR_Y_COUNT		0xFFC00EB8	/* DMA Channel 10 Current Y Count Register				*/
+
+#define DMA11_NEXT_DESC_PTR		0xFFC00EC0	/* DMA Channel 11 Next Descriptor Pointer Register		*/
+#define DMA11_START_ADDR		0xFFC00EC4	/* DMA Channel 11 Start Address Register				*/
+#define DMA11_CONFIG			0xFFC00EC8	/* DMA Channel 11 Configuration Register				*/
+#define DMA11_X_COUNT			0xFFC00ED0	/* DMA Channel 11 X Count Register						*/
+#define DMA11_X_MODIFY			0xFFC00ED4	/* DMA Channel 11 X Modify Register						*/
+#define DMA11_Y_COUNT			0xFFC00ED8	/* DMA Channel 11 Y Count Register						*/
+#define DMA11_Y_MODIFY			0xFFC00EDC	/* DMA Channel 11 Y Modify Register						*/
+#define DMA11_CURR_DESC_PTR		0xFFC00EE0	/* DMA Channel 11 Current Descriptor Pointer Register	*/
+#define DMA11_CURR_ADDR			0xFFC00EE4	/* DMA Channel 11 Current Address Register				*/
+#define DMA11_IRQ_STATUS		0xFFC00EE8	/* DMA Channel 11 Interrupt/Status Register				*/
+#define DMA11_PERIPHERAL_MAP	0xFFC00EEC	/* DMA Channel 11 Peripheral Map Register				*/
+#define DMA11_CURR_X_COUNT		0xFFC00EF0	/* DMA Channel 11 Current X Count Register				*/
+#define DMA11_CURR_Y_COUNT		0xFFC00EF8	/* DMA Channel 11 Current Y Count Register				*/
+
+#define MDMA_D0_NEXT_DESC_PTR	0xFFC00F00	/* MemDMA Stream 0 Destination Next Descriptor Pointer Register		*/
+#define MDMA_D0_START_ADDR		0xFFC00F04	/* MemDMA Stream 0 Destination Start Address Register				*/
+#define MDMA_D0_CONFIG			0xFFC00F08	/* MemDMA Stream 0 Destination Configuration Register				*/
+#define MDMA_D0_X_COUNT			0xFFC00F10	/* MemDMA Stream 0 Destination X Count Register						*/
+#define MDMA_D0_X_MODIFY		0xFFC00F14	/* MemDMA Stream 0 Destination X Modify Register					*/
+#define MDMA_D0_Y_COUNT			0xFFC00F18	/* MemDMA Stream 0 Destination Y Count Register						*/
+#define MDMA_D0_Y_MODIFY		0xFFC00F1C	/* MemDMA Stream 0 Destination Y Modify Register					*/
+#define MDMA_D0_CURR_DESC_PTR	0xFFC00F20	/* MemDMA Stream 0 Destination Current Descriptor Pointer Register	*/
+#define MDMA_D0_CURR_ADDR		0xFFC00F24	/* MemDMA Stream 0 Destination Current Address Register				*/
+#define MDMA_D0_IRQ_STATUS		0xFFC00F28	/* MemDMA Stream 0 Destination Interrupt/Status Register			*/
+#define MDMA_D0_PERIPHERAL_MAP	0xFFC00F2C	/* MemDMA Stream 0 Destination Peripheral Map Register				*/
+#define MDMA_D0_CURR_X_COUNT	0xFFC00F30	/* MemDMA Stream 0 Destination Current X Count Register				*/
+#define MDMA_D0_CURR_Y_COUNT	0xFFC00F38	/* MemDMA Stream 0 Destination Current Y Count Register				*/
+
+#define MDMA_S0_NEXT_DESC_PTR	0xFFC00F40	/* MemDMA Stream 0 Source Next Descriptor Pointer Register			*/
+#define MDMA_S0_START_ADDR		0xFFC00F44	/* MemDMA Stream 0 Source Start Address Register					*/
+#define MDMA_S0_CONFIG			0xFFC00F48	/* MemDMA Stream 0 Source Configuration Register					*/
+#define MDMA_S0_X_COUNT			0xFFC00F50	/* MemDMA Stream 0 Source X Count Register							*/
+#define MDMA_S0_X_MODIFY		0xFFC00F54	/* MemDMA Stream 0 Source X Modify Register							*/
+#define MDMA_S0_Y_COUNT			0xFFC00F58	/* MemDMA Stream 0 Source Y Count Register							*/
+#define MDMA_S0_Y_MODIFY		0xFFC00F5C	/* MemDMA Stream 0 Source Y Modify Register							*/
+#define MDMA_S0_CURR_DESC_PTR	0xFFC00F60	/* MemDMA Stream 0 Source Current Descriptor Pointer Register		*/
+#define MDMA_S0_CURR_ADDR		0xFFC00F64	/* MemDMA Stream 0 Source Current Address Register					*/
+#define MDMA_S0_IRQ_STATUS		0xFFC00F68	/* MemDMA Stream 0 Source Interrupt/Status Register					*/
+#define MDMA_S0_PERIPHERAL_MAP	0xFFC00F6C	/* MemDMA Stream 0 Source Peripheral Map Register					*/
+#define MDMA_S0_CURR_X_COUNT	0xFFC00F70	/* MemDMA Stream 0 Source Current X Count Register					*/
+#define MDMA_S0_CURR_Y_COUNT	0xFFC00F78	/* MemDMA Stream 0 Source Current Y Count Register					*/
+
+#define MDMA_D1_NEXT_DESC_PTR	0xFFC00F80	/* MemDMA Stream 1 Destination Next Descriptor Pointer Register		*/
+#define MDMA_D1_START_ADDR		0xFFC00F84	/* MemDMA Stream 1 Destination Start Address Register				*/
+#define MDMA_D1_CONFIG			0xFFC00F88	/* MemDMA Stream 1 Destination Configuration Register				*/
+#define MDMA_D1_X_COUNT			0xFFC00F90	/* MemDMA Stream 1 Destination X Count Register						*/
+#define MDMA_D1_X_MODIFY		0xFFC00F94	/* MemDMA Stream 1 Destination X Modify Register					*/
+#define MDMA_D1_Y_COUNT			0xFFC00F98	/* MemDMA Stream 1 Destination Y Count Register						*/
+#define MDMA_D1_Y_MODIFY		0xFFC00F9C	/* MemDMA Stream 1 Destination Y Modify Register					*/
+#define MDMA_D1_CURR_DESC_PTR	0xFFC00FA0	/* MemDMA Stream 1 Destination Current Descriptor Pointer Register	*/
+#define MDMA_D1_CURR_ADDR		0xFFC00FA4	/* MemDMA Stream 1 Destination Current Address Register				*/
+#define MDMA_D1_IRQ_STATUS		0xFFC00FA8	/* MemDMA Stream 1 Destination Interrupt/Status Register			*/
+#define MDMA_D1_PERIPHERAL_MAP	0xFFC00FAC	/* MemDMA Stream 1 Destination Peripheral Map Register				*/
+#define MDMA_D1_CURR_X_COUNT	0xFFC00FB0	/* MemDMA Stream 1 Destination Current X Count Register				*/
+#define MDMA_D1_CURR_Y_COUNT	0xFFC00FB8	/* MemDMA Stream 1 Destination Current Y Count Register				*/
+
+#define MDMA_S1_NEXT_DESC_PTR	0xFFC00FC0	/* MemDMA Stream 1 Source Next Descriptor Pointer Register			*/
+#define MDMA_S1_START_ADDR		0xFFC00FC4	/* MemDMA Stream 1 Source Start Address Register					*/
+#define MDMA_S1_CONFIG			0xFFC00FC8	/* MemDMA Stream 1 Source Configuration Register					*/
+#define MDMA_S1_X_COUNT			0xFFC00FD0	/* MemDMA Stream 1 Source X Count Register							*/
+#define MDMA_S1_X_MODIFY		0xFFC00FD4	/* MemDMA Stream 1 Source X Modify Register							*/
+#define MDMA_S1_Y_COUNT			0xFFC00FD8	/* MemDMA Stream 1 Source Y Count Register							*/
+#define MDMA_S1_Y_MODIFY		0xFFC00FDC	/* MemDMA Stream 1 Source Y Modify Register							*/
+#define MDMA_S1_CURR_DESC_PTR	0xFFC00FE0	/* MemDMA Stream 1 Source Current Descriptor Pointer Register		*/
+#define MDMA_S1_CURR_ADDR		0xFFC00FE4	/* MemDMA Stream 1 Source Current Address Register					*/
+#define MDMA_S1_IRQ_STATUS		0xFFC00FE8	/* MemDMA Stream 1 Source Interrupt/Status Register					*/
+#define MDMA_S1_PERIPHERAL_MAP	0xFFC00FEC	/* MemDMA Stream 1 Source Peripheral Map Register					*/
+#define MDMA_S1_CURR_X_COUNT	0xFFC00FF0	/* MemDMA Stream 1 Source Current X Count Register					*/
+#define MDMA_S1_CURR_Y_COUNT	0xFFC00FF8	/* MemDMA Stream 1 Source Current Y Count Register					*/
+
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)				*/
+#define PPI_CONTROL			0xFFC01000	/* PPI Control Register			*/
+#define PPI_STATUS			0xFFC01004	/* PPI Status Register			*/
+#define PPI_COUNT			0xFFC01008	/* PPI Transfer Count Register	*/
+#define PPI_DELAY			0xFFC0100C	/* PPI Delay Count Register		*/
+#define PPI_FRAME			0xFFC01010	/* PPI Frame Length Register	*/
+
+
+/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
+#define TWI_CLKDIV			0xFFC01400	/* Serial Clock Divider Register			*/
+#define TWI_CONTROL			0xFFC01404	/* TWI Control Register						*/
+#define TWI_SLAVE_CTL		0xFFC01408	/* Slave Mode Control Register				*/
+#define TWI_SLAVE_STAT		0xFFC0140C	/* Slave Mode Status Register				*/
+#define TWI_SLAVE_ADDR		0xFFC01410	/* Slave Mode Address Register				*/
+#define TWI_MASTER_CTL		0xFFC01414	/* Master Mode Control Register				*/
+#define TWI_MASTER_STAT		0xFFC01418	/* Master Mode Status Register				*/
+#define TWI_MASTER_ADDR		0xFFC0141C	/* Master Mode Address Register				*/
+#define TWI_INT_STAT		0xFFC01420	/* TWI Interrupt Status Register			*/
+#define TWI_INT_MASK		0xFFC01424	/* TWI Master Interrupt Mask Register		*/
+#define TWI_FIFO_CTL		0xFFC01428	/* FIFO Control Register					*/
+#define TWI_FIFO_STAT		0xFFC0142C	/* FIFO Status Register						*/
+#define TWI_XMT_DATA8		0xFFC01480	/* FIFO Transmit Data Single Byte Register	*/
+#define TWI_XMT_DATA16		0xFFC01484	/* FIFO Transmit Data Double Byte Register	*/
+#define TWI_RCV_DATA8		0xFFC01488	/* FIFO Receive Data Single Byte Register	*/
+#define TWI_RCV_DATA16		0xFFC0148C	/* FIFO Receive Data Double Byte Register	*/
+
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)												*/
+#define PORTGIO					0xFFC01500	/* Port G I/O Pin State Specify Register				*/
+#define PORTGIO_CLEAR			0xFFC01504	/* Port G I/O Peripheral Interrupt Clear Register		*/
+#define PORTGIO_SET				0xFFC01508	/* Port G I/O Peripheral Interrupt Set Register			*/
+#define PORTGIO_TOGGLE			0xFFC0150C	/* Port G I/O Pin State Toggle Register					*/
+#define PORTGIO_MASKA			0xFFC01510	/* Port G I/O Mask State Specify Interrupt A Register	*/
+#define PORTGIO_MASKA_CLEAR		0xFFC01514	/* Port G I/O Mask Disable Interrupt A Register			*/
+#define PORTGIO_MASKA_SET		0xFFC01518	/* Port G I/O Mask Enable Interrupt A Register			*/
+#define PORTGIO_MASKA_TOGGLE	0xFFC0151C	/* Port G I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTGIO_MASKB			0xFFC01520	/* Port G I/O Mask State Specify Interrupt B Register	*/
+#define PORTGIO_MASKB_CLEAR		0xFFC01524	/* Port G I/O Mask Disable Interrupt B Register			*/
+#define PORTGIO_MASKB_SET		0xFFC01528	/* Port G I/O Mask Enable Interrupt B Register			*/
+#define PORTGIO_MASKB_TOGGLE	0xFFC0152C	/* Port G I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTGIO_DIR				0xFFC01530	/* Port G I/O Direction Register						*/
+#define PORTGIO_POLAR			0xFFC01534	/* Port G I/O Source Polarity Register					*/
+#define PORTGIO_EDGE			0xFFC01538	/* Port G I/O Source Sensitivity Register				*/
+#define PORTGIO_BOTH			0xFFC0153C	/* Port G I/O Set on BOTH Edges Register				*/
+#define PORTGIO_INEN			0xFFC01540	/* Port G I/O Input Enable Register						*/
+
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)												*/
+#define PORTHIO					0xFFC01700	/* Port H I/O Pin State Specify Register				*/
+#define PORTHIO_CLEAR			0xFFC01704	/* Port H I/O Peripheral Interrupt Clear Register		*/
+#define PORTHIO_SET				0xFFC01708	/* Port H I/O Peripheral Interrupt Set Register			*/
+#define PORTHIO_TOGGLE			0xFFC0170C	/* Port H I/O Pin State Toggle Register					*/
+#define PORTHIO_MASKA			0xFFC01710	/* Port H I/O Mask State Specify Interrupt A Register	*/
+#define PORTHIO_MASKA_CLEAR		0xFFC01714	/* Port H I/O Mask Disable Interrupt A Register			*/
+#define PORTHIO_MASKA_SET		0xFFC01718	/* Port H I/O Mask Enable Interrupt A Register			*/
+#define PORTHIO_MASKA_TOGGLE	0xFFC0171C	/* Port H I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTHIO_MASKB			0xFFC01720	/* Port H I/O Mask State Specify Interrupt B Register	*/
+#define PORTHIO_MASKB_CLEAR		0xFFC01724	/* Port H I/O Mask Disable Interrupt B Register			*/
+#define PORTHIO_MASKB_SET		0xFFC01728	/* Port H I/O Mask Enable Interrupt B Register			*/
+#define PORTHIO_MASKB_TOGGLE	0xFFC0172C	/* Port H I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTHIO_DIR				0xFFC01730	/* Port H I/O Direction Register						*/
+#define PORTHIO_POLAR			0xFFC01734	/* Port H I/O Source Polarity Register					*/
+#define PORTHIO_EDGE			0xFFC01738	/* Port H I/O Source Sensitivity Register				*/
+#define PORTHIO_BOTH			0xFFC0173C	/* Port H I/O Set on BOTH Edges Register				*/
+#define PORTHIO_INEN			0xFFC01740	/* Port H I/O Input Enable Register						*/
+
+
+/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
+#define UART1_THR			0xFFC02000	/* Transmit Holding register			*/
+#define UART1_RBR			0xFFC02000	/* Receive Buffer register				*/
+#define UART1_DLL			0xFFC02000	/* Divisor Latch (Low-Byte)				*/
+#define UART1_IER			0xFFC02004	/* Interrupt Enable Register			*/
+#define UART1_DLH			0xFFC02004	/* Divisor Latch (High-Byte)			*/
+#define UART1_IIR			0xFFC02008	/* Interrupt Identification Register	*/
+#define UART1_LCR			0xFFC0200C	/* Line Control Register				*/
+#define UART1_MCR			0xFFC02010	/* Modem Control Register				*/
+#define UART1_LSR			0xFFC02014	/* Line Status Register					*/
+#define UART1_MSR			0xFFC02018	/* Modem Status Register				*/
+#define UART1_SCR			0xFFC0201C	/* SCR Scratch Register					*/
+#define UART1_GCTL			0xFFC02024	/* Global Control Register				*/
+
+
+/* Omit CAN register sets from the defBF534.h (CAN is not in the ADSP-BF52x processor) */
+
+/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)											*/
+#define PORTF_FER			0xFFC03200	/* Port F Function Enable Register (Alternate/Flag*)	*/
+#define PORTG_FER			0xFFC03204	/* Port G Function Enable Register (Alternate/Flag*)	*/
+#define PORTH_FER			0xFFC03208	/* Port H Function Enable Register (Alternate/Flag*)	*/
+#define BFIN_PORT_MUX			0xFFC0320C	/* Port Multiplexer Control Register					*/
+
+
+/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)										*/
+#define HMDMA0_CONTROL		0xFFC03300	/* Handshake MDMA0 Control Register					*/
+#define HMDMA0_ECINIT		0xFFC03304	/* HMDMA0 Initial Edge Count Register				*/
+#define HMDMA0_BCINIT		0xFFC03308	/* HMDMA0 Initial Block Count Register				*/
+#define HMDMA0_ECURGENT		0xFFC0330C	/* HMDMA0 Urgent Edge Count Threshhold Register		*/
+#define HMDMA0_ECOVERFLOW	0xFFC03310	/* HMDMA0 Edge Count Overflow Interrupt Register	*/
+#define HMDMA0_ECOUNT		0xFFC03314	/* HMDMA0 Current Edge Count Register				*/
+#define HMDMA0_BCOUNT		0xFFC03318	/* HMDMA0 Current Block Count Register				*/
+
+#define HMDMA1_CONTROL		0xFFC03340	/* Handshake MDMA1 Control Register					*/
+#define HMDMA1_ECINIT		0xFFC03344	/* HMDMA1 Initial Edge Count Register				*/
+#define HMDMA1_BCINIT		0xFFC03348	/* HMDMA1 Initial Block Count Register				*/
+#define HMDMA1_ECURGENT		0xFFC0334C	/* HMDMA1 Urgent Edge Count Threshhold Register		*/
+#define HMDMA1_ECOVERFLOW	0xFFC03350	/* HMDMA1 Edge Count Overflow Interrupt Register	*/
+#define HMDMA1_ECOUNT		0xFFC03354	/* HMDMA1 Current Edge Count Register				*/
+#define HMDMA1_BCOUNT		0xFFC03358	/* HMDMA1 Current Block Count Register				*/
+
+/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
+#define PORTF_MUX               0xFFC03210      /* Port F mux control */
+#define PORTG_MUX               0xFFC03214      /* Port G mux control */
+#define PORTH_MUX               0xFFC03218      /* Port H mux control */
+#define PORTF_DRIVE             0xFFC03220      /* Port F drive strength control */
+#define PORTG_DRIVE             0xFFC03224      /* Port G drive strength control */
+#define PORTH_DRIVE             0xFFC03228      /* Port H drive strength control */
+#define PORTF_SLEW              0xFFC03230      /* Port F slew control */
+#define PORTG_SLEW              0xFFC03234      /* Port G slew control */
+#define PORTH_SLEW              0xFFC03238      /* Port H slew control */
+#define PORTF_HYSTERISIS        0xFFC03240      /* Port F Schmitt trigger control */
+#define PORTG_HYSTERISIS        0xFFC03244      /* Port G Schmitt trigger control */
+#define PORTH_HYSTERISIS        0xFFC03248      /* Port H Schmitt trigger control */
+#define MISCPORT_DRIVE          0xFFC03280      /* Misc Port drive strength control */
+#define MISCPORT_SLEW           0xFFC03284      /* Misc Port slew control */
+#define MISCPORT_HYSTERISIS     0xFFC03288      /* Misc Port Schmitt trigger control */
+
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer:	All macros are intended to make C and Assembly code more readable.
+**				Use these macros carefully, as any that do left shifts for field
+**				depositing will result in the lower order bits being destroyed.  Any
+**				macro that shifts left to properly position the bit-field should be
+**				used as part of an OR to initialize a register and NOT as a dynamic
+**				modifier UNLESS the lower order bits are saved and ORed back in when
+**				the macro is used.
+*************************************************************************************/
+/*
+** ********************* PLL AND RESET MASKS ****************************************/
+/* PLL_CTL Masks																	*/
+#define DF				0x0001	/* 0: PLL = CLKIN, 1: PLL = CLKIN/2					*/
+#define PLL_OFF			0x0002	/* PLL Not Powered									*/
+#define STOPCK			0x0008	/* Core Clock Off									*/
+#define PDWN			0x0020	/* Enter Deep Sleep Mode							*/
+#define	IN_DELAY		0x0040	/* Add 200ps Delay To EBIU Input Latches			*/
+#define	OUT_DELAY		0x0080	/* Add 200ps Delay To EBIU Output Signals			*/
+#define BYPASS			0x0100	/* Bypass the PLL									*/
+#define	MSEL			0x7E00	/* Multiplier Select For CCLK/VCO Factors			*/
+/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits)			*/
+#define	SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL		*/
+
+/* PLL_DIV Masks														*/
+#define SSEL			0x000F	/* System Select						*/
+#define	CSEL			0x0030	/* Core Select							*/
+#define CSEL_DIV1		0x0000	/* 		CCLK = VCO / 1					*/
+#define CSEL_DIV2		0x0010	/* 		CCLK = VCO / 2					*/
+#define	CSEL_DIV4		0x0020	/* 		CCLK = VCO / 4					*/
+#define	CSEL_DIV8		0x0030	/* 		CCLK = VCO / 8					*/
+/* PLL_DIV Macros														*/
+#define SET_SSEL(x)		((x)&0xF)		/* Set SSEL = 0-15 --> SCLK = VCO/SSEL	*/
+
+/* VR_CTL Masks																	*/
+#define	FREQ			0x0003	/* Switching Oscillator Frequency For Regulator	*/
+#define	HIBERNATE		0x0000	/* 		Powerdown/Bypass On-Board Regulation	*/
+#define	FREQ_333		0x0001	/* 		Switching Frequency Is 333 kHz			*/
+#define	FREQ_667		0x0002	/* 		Switching Frequency Is 667 kHz			*/
+#define	FREQ_1000		0x0003	/* 		Switching Frequency Is 1 MHz			*/
+
+#define GAIN			0x000C	/* Voltage Level Gain	*/
+#define	GAIN_5			0x0000	/* 		GAIN = 5		*/
+#define	GAIN_10			0x0004	/* 		GAIN = 10		*/
+#define	GAIN_20			0x0008	/* 		GAIN = 20		*/
+#define	GAIN_50			0x000C	/* 		GAIN = 50		*/
+
+#define	VLEV			0x00F0	/* Internal Voltage Level					*/
+#define	VLEV_085 		0x0060	/* 		VLEV = 0.85 V (-5% - +10% Accuracy)	*/
+#define	VLEV_090		0x0070	/* 		VLEV = 0.90 V (-5% - +10% Accuracy)	*/
+#define	VLEV_095		0x0080	/* 		VLEV = 0.95 V (-5% - +10% Accuracy)	*/
+#define	VLEV_100		0x0090	/* 		VLEV = 1.00 V (-5% - +10% Accuracy)	*/
+#define	VLEV_105		0x00A0	/* 		VLEV = 1.05 V (-5% - +10% Accuracy)	*/
+#define	VLEV_110		0x00B0	/* 		VLEV = 1.10 V (-5% - +10% Accuracy)	*/
+#define	VLEV_115		0x00C0	/* 		VLEV = 1.15 V (-5% - +10% Accuracy)	*/
+#define	VLEV_120		0x00D0	/* 		VLEV = 1.20 V (-5% - +10% Accuracy)	*/
+#define	VLEV_125		0x00E0	/* 		VLEV = 1.25 V (-5% - +10% Accuracy)	*/
+#define	VLEV_130		0x00F0	/* 		VLEV = 1.30 V (-5% - +10% Accuracy)	*/
+
+#define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate	*/
+#define	CANWE			0x0200	/* Enable CAN Wakeup From Hibernate			*/
+#define	PHYWE			0x0400	/* Enable PHY Wakeup From Hibernate			*/
+#define	CLKBUFOE		0x4000	/* CLKIN Buffer Output Enable */
+#define	PHYCLKOE		CLKBUFOE	/* Alternative legacy name for the above */
+#define	SCKELOW		0x8000	/* Enable Drive CKE Low During Reset		*/
+
+/* PLL_STAT Masks																	*/
+#define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled	*/
+#define	FULL_ON				0x0002	/* Processor In Full On Mode					*/
+#define ACTIVE_PLLDISABLED	0x0004	/* Processor In Active Mode With PLL Disabled	*/
+#define	PLL_LOCKED			0x0020	/* PLL_LOCKCNT Has Been Reached					*/
+
+/* CHIPID Masks */
+#define CHIPID_VERSION         0xF0000000
+#define CHIPID_FAMILY          0x0FFFF000
+#define CHIPID_MANUFACTURE     0x00000FFE
+
+/* SWRST Masks																		*/
+#define SYSTEM_RESET		0x0007	/* Initiates A System Software Reset			*/
+#define	DOUBLE_FAULT		0x0008	/* Core Double Fault Causes Reset				*/
+#define RESET_DOUBLE		0x2000	/* SW Reset Generated By Core Double-Fault		*/
+#define RESET_WDOG			0x4000	/* SW Reset Generated By Watchdog Timer			*/
+#define RESET_SOFTWARE		0x8000	/* SW Reset Occurred Since Last Read Of SWRST	*/
+
+/* SYSCR Masks																				*/
+#define BMODE				0x0007	/* Boot Mode - Latched During HW Reset From Mode Pins	*/
+#define	NOBOOT				0x0010	/* Execute From L1 or ASYNC Bank 0 When BMODE = 0		*/
+
+
+/* *************  SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
+/* Peripheral Masks For SIC_ISR, SIC_IWR, SIC_IMASK										*/
+#define IRQ_PLL_WAKEUP	0x00000001	/* PLL Wakeup Interrupt			 					*/
+
+#define IRQ_ERROR1      0x00000002  /* Error Interrupt (DMA, DMARx Block, DMARx Overflow) */
+#define IRQ_ERROR2      0x00000004  /* Error Interrupt (CAN, Ethernet, SPORTx, PPI, SPI, UARTx) */
+#define IRQ_RTC			0x00000008	/* Real Time Clock Interrupt 						*/ 
+#define IRQ_DMA0		0x00000010	/* DMA Channel 0 (PPI) Interrupt 					*/ 
+#define IRQ_DMA3		0x00000020	/* DMA Channel 3 (SPORT0 RX) Interrupt 				*/ 
+#define IRQ_DMA4		0x00000040	/* DMA Channel 4 (SPORT0 TX) Interrupt 				*/
+#define IRQ_DMA5		0x00000080	/* DMA Channel 5 (SPORT1 RX) Interrupt 				*/
+
+#define IRQ_DMA6		0x00000100	/* DMA Channel 6 (SPORT1 TX) Interrupt 		 		*/
+#define IRQ_TWI			0x00000200	/* TWI Interrupt									*/
+#define IRQ_DMA7		0x00000400	/* DMA Channel 7 (SPI) Interrupt 					*/
+#define IRQ_DMA8		0x00000800	/* DMA Channel 8 (UART0 RX) Interrupt 				*/ 
+#define IRQ_DMA9		0x00001000	/* DMA Channel 9 (UART0 TX) Interrupt 				*/
+#define IRQ_DMA10		0x00002000	/* DMA Channel 10 (UART1 RX) Interrupt 				*/
+#define IRQ_DMA11		0x00004000	/* DMA Channel 11 (UART1 TX) Interrupt 				*/
+#define IRQ_CAN_RX		0x00008000	/* CAN Receive Interrupt 							*/
+
+#define IRQ_CAN_TX		0x00010000	/* CAN Transmit Interrupt  							*/
+#define IRQ_DMA1		0x00020000	/* DMA Channel 1 (Ethernet RX) Interrupt 			*/
+#define IRQ_PFA_PORTH	0x00020000	/* PF Port H (PF47:32) Interrupt A 					*/
+#define IRQ_DMA2		0x00040000	/* DMA Channel 2 (Ethernet TX) Interrupt 			*/
+#define IRQ_PFB_PORTH	0x00040000	/* PF Port H (PF47:32) Interrupt B 					*/
+#define IRQ_TIMER0		0x00080000	/* Timer 0 Interrupt								*/
+#define IRQ_TIMER1		0x00100000	/* Timer 1 Interrupt 								*/
+#define IRQ_TIMER2		0x00200000	/* Timer 2 Interrupt 								*/
+#define IRQ_TIMER3		0x00400000	/* Timer 3 Interrupt 								*/
+#define IRQ_TIMER4		0x00800000	/* Timer 4 Interrupt 								*/
+
+#define IRQ_TIMER5		0x01000000	/* Timer 5 Interrupt 								*/
+#define IRQ_TIMER6		0x02000000	/* Timer 6 Interrupt 								*/
+#define IRQ_TIMER7		0x04000000	/* Timer 7 Interrupt 								*/
+#define IRQ_PFA_PORTFG	0x08000000	/* PF Ports F&G (PF31:0) Interrupt A 				*/
+#define IRQ_PFB_PORTF	0x80000000	/* PF Port F (PF15:0) Interrupt B 					*/
+#define IRQ_DMA12		0x20000000	/* DMA Channels 12 (MDMA1 Source) RX Interrupt 		*/
+#define IRQ_DMA13		0x20000000	/* DMA Channels 13 (MDMA1 Destination) TX Interrupt */
+#define IRQ_DMA14		0x40000000	/* DMA Channels 14 (MDMA0 Source) RX Interrupt 		*/
+#define IRQ_DMA15		0x40000000	/* DMA Channels 15 (MDMA0 Destination) TX Interrupt */
+#define IRQ_WDOG		0x80000000	/* Software Watchdog Timer Interrupt 				*/
+#define IRQ_PFB_PORTG	0x10000000	/* PF Port G (PF31:16) Interrupt B 					*/
+
+/* SIC_IAR0 Macros															*/
+#define P0_IVG(x)		(((x)&0xF)-7)			/* Peripheral #0 assigned IVG #x 	*/
+#define P1_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #1 assigned IVG #x 	*/
+#define P2_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #2 assigned IVG #x 	*/
+#define P3_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #3 assigned IVG #x	*/
+#define P4_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #4 assigned IVG #x	*/
+#define P5_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #5 assigned IVG #x	*/
+#define P6_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #6 assigned IVG #x	*/
+#define P7_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #7 assigned IVG #x	*/
+
+/* SIC_IAR1 Macros															*/
+#define P8_IVG(x)		(((x)&0xF)-7)			/* Peripheral #8 assigned IVG #x 	*/
+#define P9_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #9 assigned IVG #x 	*/
+#define P10_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #10 assigned IVG #x	*/
+#define P11_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #11 assigned IVG #x 	*/
+#define P12_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #12 assigned IVG #x	*/
+#define P13_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #13 assigned IVG #x	*/
+#define P14_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #14 assigned IVG #x	*/
+#define P15_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #15 assigned IVG #x	*/
+
+/* SIC_IAR2 Macros															*/
+#define P16_IVG(x)		(((x)&0xF)-7)			/* Peripheral #16 assigned IVG #x	*/
+#define P17_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #17 assigned IVG #x	*/
+#define P18_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #18 assigned IVG #x	*/
+#define P19_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #19 assigned IVG #x	*/
+#define P20_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #20 assigned IVG #x	*/
+#define P21_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #21 assigned IVG #x	*/
+#define P22_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #22 assigned IVG #x	*/
+#define P23_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #23 assigned IVG #x	*/
+
+/* SIC_IAR3 Macros															*/
+#define P24_IVG(x)		(((x)&0xF)-7)			/* Peripheral #24 assigned IVG #x	*/
+#define P25_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #25 assigned IVG #x	*/
+#define P26_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #26 assigned IVG #x	*/
+#define P27_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #27 assigned IVG #x	*/
+#define P28_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #28 assigned IVG #x	*/
+#define P29_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #29 assigned IVG #x	*/
+#define P30_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #30 assigned IVG #x	*/
+#define P31_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #31 assigned IVG #x	*/
+
+
+/* SIC_IMASK Masks																		*/
+#define SIC_UNMASK_ALL	0x00000000					/* Unmask all peripheral interrupts	*/
+#define SIC_MASK_ALL	0xFFFFFFFF					/* Mask all peripheral interrupts	*/
+#define SIC_MASK(x)		(1 << ((x)&0x1F))					/* Mask Peripheral #x interrupt		*/
+#define SIC_UNMASK(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Unmask Peripheral #x interrupt	*/
+
+/* SIC_IWR Masks																		*/
+#define IWR_DISABLE_ALL	0x00000000					/* Wakeup Disable all peripherals	*/
+#define IWR_ENABLE_ALL	0xFFFFFFFF					/* Wakeup Enable all peripherals	*/
+#define IWR_ENABLE(x)	(1 << ((x)&0x1F))					/* Wakeup Enable Peripheral #x		*/
+#define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F))) 	/* Wakeup Disable Peripheral #x		*/
+
+
+/* ********* WATCHDOG TIMER MASKS ******************** */
+
+/* Watchdog Timer WDOG_CTL Register Masks */
+
+#define WDEV(x) (((x)<<1) & 0x0006) /* event generated on roll over */
+#define WDEV_RESET 0x0000 /* generate reset event on roll over */
+#define WDEV_NMI 0x0002 /* generate NMI event on roll over */
+#define WDEV_GPI 0x0004 /* generate GP IRQ on roll over */
+#define WDEV_NONE 0x0006 /* no event on roll over */
+#define WDEN 0x0FF0 /* enable watchdog */
+#define WDDIS 0x0AD0 /* disable watchdog */
+#define WDRO 0x8000 /* watchdog rolled over latch */ 
+
+/* depreciated WDOG_CTL Register Masks for legacy code */
+
+
+#define ICTL WDEV
+#define ENABLE_RESET WDEV_RESET
+#define WDOG_RESET WDEV_RESET
+#define ENABLE_NMI WDEV_NMI
+#define WDOG_NMI WDEV_NMI
+#define ENABLE_GPI WDEV_GPI
+#define WDOG_GPI WDEV_GPI
+#define DISABLE_EVT WDEV_NONE
+#define WDOG_NONE WDEV_NONE
+
+#define TMR_EN WDEN
+#define TMR_DIS WDDIS
+#define TRO WDRO
+#define ICTL_P0 0x01
+ #define ICTL_P1 0x02
+#define TRO_P 0x0F
+
+
+
+/* ***************  REAL TIME CLOCK MASKS  **************************/
+/* RTC_STAT and RTC_ALARM Masks										*/
+#define	RTC_SEC				0x0000003F	/* Real-Time Clock Seconds	*/
+#define	RTC_MIN				0x00000FC0	/* Real-Time Clock Minutes	*/
+#define	RTC_HR				0x0001F000	/* Real-Time Clock Hours	*/
+#define	RTC_DAY				0xFFFE0000	/* Real-Time Clock Days		*/
+
+/* RTC_ALARM Macro			z=day		y=hr	x=min	w=sec		*/
+#define SET_ALARM(z,y,x,w)	((((z)&0x7FFF)<<0x11)|(((y)&0x1F)<<0xC)|(((x)&0x3F)<<0x6)|((w)&0x3F))
+
+/* RTC_ICTL and RTC_ISTAT Masks																		*/
+#define	STOPWATCH			0x0001		/* Stopwatch Interrupt Enable								*/
+#define	ALARM				0x0002		/* Alarm Interrupt Enable									*/
+#define	SECOND				0x0004		/* Seconds (1 Hz) Interrupt Enable							*/
+#define	MINUTE				0x0008		/* Minutes Interrupt Enable									*/
+#define	HOUR				0x0010		/* Hours Interrupt Enable									*/
+#define	DAY					0x0020		/* 24 Hours (Days) Interrupt Enable							*/
+#define	DAY_ALARM			0x0040		/* Day Alarm (Day, Hour, Minute, Second) Interrupt Enable	*/
+#define	WRITE_PENDING		0x4000		/* Write Pending Status										*/
+#define	WRITE_COMPLETE		0x8000		/* Write Complete Interrupt Enable							*/
+
+/* RTC_FAST / RTC_PREN Mask												*/
+#define PREN				0x0001	/* Enable Prescaler, RTC Runs @1 Hz	*/
+
+
+/* ************** UART CONTROLLER MASKS *************************/
+/* UARTx_LCR Masks												*/
+#define WLS(x)		(((x)-5) & 0x03)	/* Word Length Select */
+#define STB			0x04				/* Stop Bits			*/
+#define PEN			0x08				/* Parity Enable		*/
+#define EPS			0x10				/* Even Parity Select	*/
+#define STP			0x20				/* Stick Parity			*/
+#define SB			0x40				/* Set Break			*/
+#define DLAB		0x80				/* Divisor Latch Access	*/
+
+/* UARTx_MCR Mask										*/
+#define LOOP_ENA	0x10	/* Loopback Mode Enable */
+#define LOOP_ENA_P	0x04
+
+/* UARTx_LSR Masks										*/
+#define DR			0x01	/* Data Ready				*/
+#define OE			0x02	/* Overrun Error			*/
+#define PE			0x04	/* Parity Error				*/
+#define FE			0x08	/* Framing Error			*/
+#define BI			0x10	/* Break Interrupt			*/
+#define THRE		0x20	/* THR Empty				*/
+#define TEMT		0x40	/* TSR and UART_THR Empty	*/
+
+/* UARTx_IER Masks															*/
+#define ERBFI		0x01		/* Enable Receive Buffer Full Interrupt		*/
+#define ETBEI		0x02		/* Enable Transmit Buffer Empty Interrupt	*/
+#define ELSI		0x04		/* Enable RX Status Interrupt				*/
+
+/* UARTx_IIR Masks														*/
+#define NINT		0x01		/* Pending Interrupt					*/
+#define IIR_TX_READY    0x02		/* UART_THR empty                               */
+#define IIR_RX_READY    0x04		/* Receive data ready                           */
+#define IIR_LINE_CHANGE 0x06		/* Receive line status    			*/ 
+#define IIR_STATUS	0x06		/* Highest Priority Pending Interrupt	*/
+
+/* UARTx_GCTL Masks													*/
+#define UCEN		0x01		/* Enable UARTx Clocks				*/
+#define IREN		0x02		/* Enable IrDA Mode					*/
+#define TPOLC		0x04		/* IrDA TX Polarity Change			*/
+#define RPOLC		0x08		/* IrDA RX Polarity Change			*/
+#define FPE			0x10		/* Force Parity Error On Transmit	*/
+#define FFE			0x20		/* Force Framing Error On Transmit	*/
+
+
+/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  ****************************/
+/* SPI_CTL Masks																	*/
+#define	TIMOD		0x0003		/* Transfer Initiate Mode							*/
+#define RDBR_CORE	0x0000		/* 		RDBR Read Initiates, IRQ When RDBR Full		*/
+#define	TDBR_CORE	0x0001		/* 		TDBR Write Initiates, IRQ When TDBR Empty	*/
+#define RDBR_DMA	0x0002		/* 		DMA Read, DMA Until FIFO Empty				*/
+#define TDBR_DMA	0x0003		/* 		DMA Write, DMA Until FIFO Full				*/
+#define SZ			0x0004		/* Send Zero (When TDBR Empty, Send Zero/Last*)		*/
+#define GM			0x0008		/* Get More (When RDBR Full, Overwrite/Discard*)	*/
+#define PSSE		0x0010		/* Slave-Select Input Enable						*/
+#define EMISO		0x0020		/* Enable MISO As Output							*/
+#define SIZE		0x0100		/* Size of Words (16/8* Bits)						*/
+#define LSBF		0x0200		/* LSB First										*/
+#define CPHA		0x0400		/* Clock Phase										*/
+#define CPOL		0x0800		/* Clock Polarity									*/
+#define MSTR		0x1000		/* Master/Slave*									*/
+#define WOM			0x2000		/* Write Open Drain Master							*/
+#define SPE			0x4000		/* SPI Enable										*/
+
+/* SPI_FLG Masks																	*/
+#define FLS1		0x0002		/* Enables SPI_FLOUT1 as SPI Slave-Select Output	*/
+#define FLS2		0x0004		/* Enables SPI_FLOUT2 as SPI Slave-Select Output	*/
+#define FLS3		0x0008		/* Enables SPI_FLOUT3 as SPI Slave-Select Output	*/
+#define FLS4		0x0010		/* Enables SPI_FLOUT4 as SPI Slave-Select Output	*/
+#define FLS5		0x0020		/* Enables SPI_FLOUT5 as SPI Slave-Select Output	*/
+#define FLS6		0x0040		/* Enables SPI_FLOUT6 as SPI Slave-Select Output	*/
+#define FLS7		0x0080		/* Enables SPI_FLOUT7 as SPI Slave-Select Output	*/
+#define FLG1		0xFDFF		/* Activates SPI_FLOUT1 							*/
+#define FLG2		0xFBFF		/* Activates SPI_FLOUT2								*/
+#define FLG3		0xF7FF		/* Activates SPI_FLOUT3								*/
+#define FLG4		0xEFFF		/* Activates SPI_FLOUT4								*/
+#define FLG5		0xDFFF		/* Activates SPI_FLOUT5								*/
+#define FLG6		0xBFFF		/* Activates SPI_FLOUT6								*/
+#define FLG7		0x7FFF		/* Activates SPI_FLOUT7								*/
+
+/* SPI_STAT Masks																				*/
+#define SPIF		0x0001		/* SPI Finished (Single-Word Transfer Complete)					*/
+#define MODF		0x0002		/* Mode Fault Error (Another Device Tried To Become Master)		*/
+#define TXE			0x0004		/* Transmission Error (Data Sent With No New Data In TDBR)		*/
+#define TXS			0x0008		/* SPI_TDBR Data Buffer Status (Full/Empty*)					*/
+#define RBSY		0x0010		/* Receive Error (Data Received With RDBR Full)					*/
+#define RXS			0x0020		/* SPI_RDBR Data Buffer Status (Full/Empty*)					*/
+#define TXCOL		0x0040		/* Transmit Collision Error (Corrupt Data May Have Been Sent)	*/
+
+
+/*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
+/* TIMER_ENABLE Masks													*/
+#define TIMEN0			0x0001		/* Enable Timer 0					*/
+#define TIMEN1			0x0002		/* Enable Timer 1					*/
+#define TIMEN2			0x0004		/* Enable Timer 2					*/
+#define TIMEN3			0x0008		/* Enable Timer 3					*/
+#define TIMEN4			0x0010		/* Enable Timer 4					*/
+#define TIMEN5			0x0020		/* Enable Timer 5					*/
+#define TIMEN6			0x0040		/* Enable Timer 6					*/
+#define TIMEN7			0x0080		/* Enable Timer 7					*/
+
+/* TIMER_DISABLE Masks													*/
+#define TIMDIS0			TIMEN0		/* Disable Timer 0					*/
+#define TIMDIS1			TIMEN1		/* Disable Timer 1					*/
+#define TIMDIS2			TIMEN2		/* Disable Timer 2					*/
+#define TIMDIS3			TIMEN3		/* Disable Timer 3					*/
+#define TIMDIS4			TIMEN4		/* Disable Timer 4					*/
+#define TIMDIS5			TIMEN5		/* Disable Timer 5					*/
+#define TIMDIS6			TIMEN6		/* Disable Timer 6					*/
+#define TIMDIS7			TIMEN7		/* Disable Timer 7					*/
+
+/* TIMER_STATUS Masks													*/
+#define TIMIL0			0x00000001	/* Timer 0 Interrupt				*/
+#define TIMIL1			0x00000002	/* Timer 1 Interrupt				*/
+#define TIMIL2			0x00000004	/* Timer 2 Interrupt				*/
+#define TIMIL3			0x00000008	/* Timer 3 Interrupt				*/
+#define TOVF_ERR0		0x00000010	/* Timer 0 Counter Overflow			*/
+#define TOVF_ERR1		0x00000020	/* Timer 1 Counter Overflow			*/
+#define TOVF_ERR2		0x00000040	/* Timer 2 Counter Overflow			*/
+#define TOVF_ERR3		0x00000080	/* Timer 3 Counter Overflow			*/
+#define TRUN0			0x00001000	/* Timer 0 Slave Enable Status		*/
+#define TRUN1			0x00002000	/* Timer 1 Slave Enable Status		*/
+#define TRUN2			0x00004000	/* Timer 2 Slave Enable Status		*/
+#define TRUN3			0x00008000	/* Timer 3 Slave Enable Status		*/
+#define TIMIL4			0x00010000	/* Timer 4 Interrupt				*/
+#define TIMIL5			0x00020000	/* Timer 5 Interrupt				*/
+#define TIMIL6			0x00040000	/* Timer 6 Interrupt				*/
+#define TIMIL7			0x00080000	/* Timer 7 Interrupt				*/
+#define TOVF_ERR4		0x00100000	/* Timer 4 Counter Overflow			*/
+#define TOVF_ERR5		0x00200000	/* Timer 5 Counter Overflow			*/
+#define TOVF_ERR6		0x00400000	/* Timer 6 Counter Overflow			*/
+#define TOVF_ERR7		0x00800000	/* Timer 7 Counter Overflow			*/
+#define TRUN4			0x10000000	/* Timer 4 Slave Enable Status		*/
+#define TRUN5			0x20000000	/* Timer 5 Slave Enable Status		*/
+#define TRUN6			0x40000000	/* Timer 6 Slave Enable Status		*/
+#define TRUN7			0x80000000	/* Timer 7 Slave Enable Status		*/
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define TOVL_ERR0 TOVF_ERR0
+#define TOVL_ERR1 TOVF_ERR1
+#define TOVL_ERR2 TOVF_ERR2
+#define TOVL_ERR3 TOVF_ERR3
+#define TOVL_ERR4 TOVF_ERR4
+#define TOVL_ERR5 TOVF_ERR5
+#define TOVL_ERR6 TOVF_ERR6
+#define TOVL_ERR7 TOVF_ERR7
+
+/* TIMERx_CONFIG Masks													*/
+#define PWM_OUT			0x0001	/* Pulse-Width Modulation Output Mode	*/
+#define WDTH_CAP		0x0002	/* Width Capture Input Mode				*/
+#define EXT_CLK			0x0003	/* External Clock Mode					*/
+#define PULSE_HI		0x0004	/* Action Pulse (Positive/Negative*)	*/
+#define PERIOD_CNT		0x0008	/* Period Count							*/
+#define IRQ_ENA			0x0010	/* Interrupt Request Enable				*/
+#define TIN_SEL			0x0020	/* Timer Input Select					*/
+#define OUT_DIS			0x0040	/* Output Pad Disable					*/
+#define CLK_SEL			0x0080	/* Timer Clock Select					*/
+#define TOGGLE_HI		0x0100	/* PWM_OUT PULSE_HI Toggle Mode			*/
+#define EMU_RUN			0x0200	/* Emulation Behavior Select			*/
+#define ERR_TYP			0xC000	/* Error Type							*/
+
+
+/* ******************   GPIO PORTS F, G, H MASKS  ***********************/
+/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks 				*/
+/* Port F Masks 														*/
+#define PF0		0x0001
+#define PF1		0x0002
+#define PF2		0x0004
+#define PF3		0x0008
+#define PF4		0x0010
+#define PF5		0x0020
+#define PF6		0x0040
+#define PF7		0x0080
+#define PF8		0x0100
+#define PF9		0x0200
+#define PF10	0x0400
+#define PF11	0x0800
+#define PF12	0x1000
+#define PF13	0x2000
+#define PF14	0x4000
+#define PF15	0x8000
+
+/* Port G Masks															*/
+#define PG0		0x0001
+#define PG1		0x0002
+#define PG2		0x0004
+#define PG3		0x0008
+#define PG4		0x0010
+#define PG5		0x0020
+#define PG6		0x0040
+#define PG7		0x0080
+#define PG8		0x0100
+#define PG9		0x0200
+#define PG10	0x0400
+#define PG11	0x0800
+#define PG12	0x1000
+#define PG13	0x2000
+#define PG14	0x4000
+#define PG15	0x8000
+
+/* Port H Masks															*/
+#define PH0		0x0001
+#define PH1		0x0002
+#define PH2		0x0004
+#define PH3		0x0008
+#define PH4		0x0010
+#define PH5		0x0020
+#define PH6		0x0040
+#define PH7		0x0080
+#define PH8		0x0100
+#define PH9		0x0200
+#define PH10	0x0400
+#define PH11	0x0800
+#define PH12	0x1000
+#define PH13	0x2000
+#define PH14	0x4000
+#define PH15	0x8000
+
+
+/* *******************  SERIAL PORT MASKS  **************************************/
+/* SPORTx_TCR1 Masks															*/
+#define TSPEN		0x0001		/* Transmit Enable								*/
+#define ITCLK		0x0002		/* Internal Transmit Clock Select				*/
+#define DTYPE_NORM	0x0004		/* Data Format Normal							*/
+#define DTYPE_ULAW	0x0008		/* Compand Using u-Law							*/
+#define DTYPE_ALAW	0x000C		/* Compand Using A-Law							*/
+#define TLSBIT		0x0010		/* Transmit Bit Order							*/
+#define ITFS		0x0200		/* Internal Transmit Frame Sync Select			*/
+#define TFSR		0x0400		/* Transmit Frame Sync Required Select			*/
+#define DITFS		0x0800		/* Data-Independent Transmit Frame Sync Select	*/
+#define LTFS		0x1000		/* Low Transmit Frame Sync Select				*/
+#define LATFS		0x2000		/* Late Transmit Frame Sync Select				*/
+#define TCKFE		0x4000		/* Clock Falling Edge Select					*/
+
+/* SPORTx_TCR2 Masks and Macro													*/
+#define SLEN(x)		((x)&0x1F)	/* SPORT TX Word Length (2 - 31)				*/
+#define TXSE		0x0100		/* TX Secondary Enable							*/
+#define TSFSE		0x0200		/* Transmit Stereo Frame Sync Enable			*/
+#define TRFST		0x0400		/* Left/Right Order (1 = Right Channel 1st)		*/
+
+/* SPORTx_RCR1 Masks															*/
+#define RSPEN		0x0001		/* Receive Enable 								*/
+#define IRCLK		0x0002		/* Internal Receive Clock Select 				*/
+#define DTYPE_NORM	0x0004		/* Data Format Normal							*/
+#define DTYPE_ULAW	0x0008		/* Compand Using u-Law							*/
+#define DTYPE_ALAW	0x000C		/* Compand Using A-Law							*/
+#define RLSBIT		0x0010		/* Receive Bit Order							*/
+#define IRFS		0x0200		/* Internal Receive Frame Sync Select 			*/
+#define RFSR		0x0400		/* Receive Frame Sync Required Select 			*/
+#define LRFS		0x1000		/* Low Receive Frame Sync Select 				*/
+#define LARFS		0x2000		/* Late Receive Frame Sync Select 				*/
+#define RCKFE		0x4000		/* Clock Falling Edge Select 					*/
+
+/* SPORTx_RCR2 Masks															*/
+#define SLEN(x)		((x)&0x1F)	/* SPORT RX Word Length (2 - 31)				*/
+#define RXSE		0x0100		/* RX Secondary Enable							*/
+#define RSFSE		0x0200		/* RX Stereo Frame Sync Enable					*/
+#define RRFST		0x0400		/* Right-First Data Order 						*/
+
+/* SPORTx_STAT Masks															*/
+#define RXNE		0x0001		/* Receive FIFO Not Empty Status				*/
+#define RUVF		0x0002		/* Sticky Receive Underflow Status				*/
+#define ROVF		0x0004		/* Sticky Receive Overflow Status				*/
+#define TXF			0x0008		/* Transmit FIFO Full Status					*/
+#define TUVF		0x0010		/* Sticky Transmit Underflow Status				*/
+#define TOVF		0x0020		/* Sticky Transmit Overflow Status				*/
+#define TXHRE		0x0040		/* Transmit Hold Register Empty					*/
+
+/* SPORTx_MCMC1 Macros															*/
+#define SP_WOFF(x)	((x) & 0x3FF) 	/* Multichannel Window Offset Field			*/
+
+/* Only use WSIZE Macro With Logic OR While Setting Lower Order Bits						*/
+#define SP_WSIZE(x)	(((((x)>>0x3)-1)&0xF) << 0xC)	/* Multichannel Window Size = (x/8)-1	*/
+
+/* SPORTx_MCMC2 Masks															*/
+#define REC_BYPASS	0x0000		/* Bypass Mode (No Clock Recovery)				*/
+#define REC_2FROM4	0x0002		/* Recover 2 MHz Clock from 4 MHz Clock			*/
+#define REC_8FROM16	0x0003		/* Recover 8 MHz Clock from 16 MHz Clock		*/
+#define MCDTXPE		0x0004 		/* Multichannel DMA Transmit Packing			*/
+#define MCDRXPE		0x0008 		/* Multichannel DMA Receive Packing				*/
+#define MCMEN		0x0010 		/* Multichannel Frame Mode Enable				*/
+#define FSDR		0x0080 		/* Multichannel Frame Sync to Data Relationship	*/
+#define MFD_0		0x0000		/* Multichannel Frame Delay = 0					*/
+#define MFD_1		0x1000		/* Multichannel Frame Delay = 1					*/
+#define MFD_2		0x2000		/* Multichannel Frame Delay = 2					*/
+#define MFD_3		0x3000		/* Multichannel Frame Delay = 3					*/
+#define MFD_4		0x4000		/* Multichannel Frame Delay = 4					*/
+#define MFD_5		0x5000		/* Multichannel Frame Delay = 5					*/
+#define MFD_6		0x6000		/* Multichannel Frame Delay = 6					*/
+#define MFD_7		0x7000		/* Multichannel Frame Delay = 7					*/
+#define MFD_8		0x8000		/* Multichannel Frame Delay = 8					*/
+#define MFD_9		0x9000		/* Multichannel Frame Delay = 9					*/
+#define MFD_10		0xA000		/* Multichannel Frame Delay = 10				*/
+#define MFD_11		0xB000		/* Multichannel Frame Delay = 11				*/
+#define MFD_12		0xC000		/* Multichannel Frame Delay = 12				*/
+#define MFD_13		0xD000		/* Multichannel Frame Delay = 13				*/
+#define MFD_14		0xE000		/* Multichannel Frame Delay = 14				*/
+#define MFD_15		0xF000		/* Multichannel Frame Delay = 15				*/
+
+
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
+/* EBIU_AMGCTL Masks																	*/
+#define AMCKEN			0x0001		/* Enable CLKOUT									*/
+#define	AMBEN_NONE		0x0000		/* All Banks Disabled								*/
+#define AMBEN_B0		0x0002		/* Enable Async Memory Bank 0 only					*/
+#define AMBEN_B0_B1		0x0004		/* Enable Async Memory Banks 0 & 1 only				*/
+#define AMBEN_B0_B1_B2	0x0006		/* Enable Async Memory Banks 0, 1, and 2			*/
+#define AMBEN_ALL		0x0008		/* Enable Async Memory Banks (all) 0, 1, 2, and 3	*/
+
+/* EBIU_AMBCTL0 Masks																	*/
+#define B0RDYEN			0x00000001  /* Bank 0 (B0) RDY Enable							*/
+#define B0RDYPOL		0x00000002  /* B0 RDY Active High								*/
+#define B0TT_1			0x00000004  /* B0 Transition Time (Read to Write) = 1 cycle		*/
+#define B0TT_2			0x00000008  /* B0 Transition Time (Read to Write) = 2 cycles	*/
+#define B0TT_3			0x0000000C  /* B0 Transition Time (Read to Write) = 3 cycles	*/
+#define B0TT_4			0x00000000  /* B0 Transition Time (Read to Write) = 4 cycles	*/
+#define B0ST_1			0x00000010  /* B0 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B0ST_2			0x00000020  /* B0 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B0ST_3			0x00000030  /* B0 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B0ST_4			0x00000000  /* B0 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B0HT_1			0x00000040  /* B0 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B0HT_2			0x00000080  /* B0 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B0HT_3			0x000000C0  /* B0 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B0HT_0			0x00000000  /* B0 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B0RAT_1			0x00000100  /* B0 Read Access Time = 1 cycle					*/
+#define B0RAT_2			0x00000200  /* B0 Read Access Time = 2 cycles					*/
+#define B0RAT_3			0x00000300  /* B0 Read Access Time = 3 cycles					*/
+#define B0RAT_4			0x00000400  /* B0 Read Access Time = 4 cycles					*/
+#define B0RAT_5			0x00000500  /* B0 Read Access Time = 5 cycles					*/
+#define B0RAT_6			0x00000600  /* B0 Read Access Time = 6 cycles					*/
+#define B0RAT_7			0x00000700  /* B0 Read Access Time = 7 cycles					*/
+#define B0RAT_8			0x00000800  /* B0 Read Access Time = 8 cycles					*/
+#define B0RAT_9			0x00000900  /* B0 Read Access Time = 9 cycles					*/
+#define B0RAT_10		0x00000A00  /* B0 Read Access Time = 10 cycles					*/
+#define B0RAT_11		0x00000B00  /* B0 Read Access Time = 11 cycles					*/
+#define B0RAT_12		0x00000C00  /* B0 Read Access Time = 12 cycles					*/
+#define B0RAT_13		0x00000D00  /* B0 Read Access Time = 13 cycles					*/
+#define B0RAT_14		0x00000E00  /* B0 Read Access Time = 14 cycles					*/
+#define B0RAT_15		0x00000F00  /* B0 Read Access Time = 15 cycles					*/
+#define B0WAT_1			0x00001000  /* B0 Write Access Time = 1 cycle					*/
+#define B0WAT_2			0x00002000  /* B0 Write Access Time = 2 cycles					*/
+#define B0WAT_3			0x00003000  /* B0 Write Access Time = 3 cycles					*/
+#define B0WAT_4			0x00004000  /* B0 Write Access Time = 4 cycles					*/
+#define B0WAT_5			0x00005000  /* B0 Write Access Time = 5 cycles					*/
+#define B0WAT_6			0x00006000  /* B0 Write Access Time = 6 cycles					*/
+#define B0WAT_7			0x00007000  /* B0 Write Access Time = 7 cycles					*/
+#define B0WAT_8			0x00008000  /* B0 Write Access Time = 8 cycles					*/
+#define B0WAT_9			0x00009000  /* B0 Write Access Time = 9 cycles					*/
+#define B0WAT_10		0x0000A000  /* B0 Write Access Time = 10 cycles					*/
+#define B0WAT_11		0x0000B000  /* B0 Write Access Time = 11 cycles					*/
+#define B0WAT_12		0x0000C000  /* B0 Write Access Time = 12 cycles					*/
+#define B0WAT_13		0x0000D000  /* B0 Write Access Time = 13 cycles					*/
+#define B0WAT_14		0x0000E000  /* B0 Write Access Time = 14 cycles					*/
+#define B0WAT_15		0x0000F000  /* B0 Write Access Time = 15 cycles					*/
+
+#define B1RDYEN			0x00010000  /* Bank 1 (B1) RDY Enable                       	*/
+#define B1RDYPOL		0x00020000  /* B1 RDY Active High                           	*/
+#define B1TT_1			0x00040000  /* B1 Transition Time (Read to Write) = 1 cycle 	*/
+#define B1TT_2			0x00080000  /* B1 Transition Time (Read to Write) = 2 cycles	*/
+#define B1TT_3			0x000C0000  /* B1 Transition Time (Read to Write) = 3 cycles	*/
+#define B1TT_4			0x00000000  /* B1 Transition Time (Read to Write) = 4 cycles	*/
+#define B1ST_1			0x00100000  /* B1 Setup Time (AOE to Read/Write) = 1 cycle  	*/
+#define B1ST_2			0x00200000  /* B1 Setup Time (AOE to Read/Write) = 2 cycles 	*/
+#define B1ST_3			0x00300000  /* B1 Setup Time (AOE to Read/Write) = 3 cycles 	*/
+#define B1ST_4			0x00000000  /* B1 Setup Time (AOE to Read/Write) = 4 cycles 	*/
+#define B1HT_1			0x00400000  /* B1 Hold Time (~Read/Write to ~AOE) = 1 cycle 	*/
+#define B1HT_2			0x00800000  /* B1 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B1HT_3			0x00C00000  /* B1 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B1HT_0			0x00000000  /* B1 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B1RAT_1			0x01000000  /* B1 Read Access Time = 1 cycle					*/
+#define B1RAT_2			0x02000000  /* B1 Read Access Time = 2 cycles					*/
+#define B1RAT_3			0x03000000  /* B1 Read Access Time = 3 cycles					*/
+#define B1RAT_4			0x04000000  /* B1 Read Access Time = 4 cycles					*/
+#define B1RAT_5			0x05000000  /* B1 Read Access Time = 5 cycles					*/
+#define B1RAT_6			0x06000000  /* B1 Read Access Time = 6 cycles					*/
+#define B1RAT_7			0x07000000  /* B1 Read Access Time = 7 cycles					*/
+#define B1RAT_8			0x08000000  /* B1 Read Access Time = 8 cycles					*/
+#define B1RAT_9			0x09000000  /* B1 Read Access Time = 9 cycles					*/
+#define B1RAT_10		0x0A000000  /* B1 Read Access Time = 10 cycles					*/
+#define B1RAT_11		0x0B000000  /* B1 Read Access Time = 11 cycles					*/
+#define B1RAT_12		0x0C000000  /* B1 Read Access Time = 12 cycles					*/
+#define B1RAT_13		0x0D000000  /* B1 Read Access Time = 13 cycles					*/
+#define B1RAT_14		0x0E000000  /* B1 Read Access Time = 14 cycles					*/
+#define B1RAT_15		0x0F000000  /* B1 Read Access Time = 15 cycles					*/
+#define B1WAT_1			0x10000000  /* B1 Write Access Time = 1 cycle					*/
+#define B1WAT_2			0x20000000  /* B1 Write Access Time = 2 cycles					*/
+#define B1WAT_3			0x30000000  /* B1 Write Access Time = 3 cycles					*/
+#define B1WAT_4			0x40000000  /* B1 Write Access Time = 4 cycles					*/
+#define B1WAT_5			0x50000000  /* B1 Write Access Time = 5 cycles					*/
+#define B1WAT_6			0x60000000  /* B1 Write Access Time = 6 cycles					*/
+#define B1WAT_7			0x70000000  /* B1 Write Access Time = 7 cycles					*/
+#define B1WAT_8			0x80000000  /* B1 Write Access Time = 8 cycles					*/
+#define B1WAT_9			0x90000000  /* B1 Write Access Time = 9 cycles					*/
+#define B1WAT_10		0xA0000000  /* B1 Write Access Time = 10 cycles					*/
+#define B1WAT_11		0xB0000000  /* B1 Write Access Time = 11 cycles					*/
+#define B1WAT_12		0xC0000000  /* B1 Write Access Time = 12 cycles					*/
+#define B1WAT_13		0xD0000000  /* B1 Write Access Time = 13 cycles					*/
+#define B1WAT_14		0xE0000000  /* B1 Write Access Time = 14 cycles					*/
+#define B1WAT_15		0xF0000000  /* B1 Write Access Time = 15 cycles					*/
+
+/* EBIU_AMBCTL1 Masks																	*/
+#define B2RDYEN			0x00000001  /* Bank 2 (B2) RDY Enable							*/
+#define B2RDYPOL		0x00000002  /* B2 RDY Active High								*/
+#define B2TT_1			0x00000004  /* B2 Transition Time (Read to Write) = 1 cycle		*/
+#define B2TT_2			0x00000008  /* B2 Transition Time (Read to Write) = 2 cycles	*/
+#define B2TT_3			0x0000000C  /* B2 Transition Time (Read to Write) = 3 cycles	*/
+#define B2TT_4			0x00000000  /* B2 Transition Time (Read to Write) = 4 cycles	*/
+#define B2ST_1			0x00000010  /* B2 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B2ST_2			0x00000020  /* B2 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B2ST_3			0x00000030  /* B2 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B2ST_4			0x00000000  /* B2 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B2HT_1			0x00000040  /* B2 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B2HT_2			0x00000080  /* B2 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B2HT_3			0x000000C0  /* B2 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B2HT_0			0x00000000  /* B2 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B2RAT_1			0x00000100  /* B2 Read Access Time = 1 cycle					*/
+#define B2RAT_2			0x00000200  /* B2 Read Access Time = 2 cycles					*/
+#define B2RAT_3			0x00000300  /* B2 Read Access Time = 3 cycles					*/
+#define B2RAT_4			0x00000400  /* B2 Read Access Time = 4 cycles					*/
+#define B2RAT_5			0x00000500  /* B2 Read Access Time = 5 cycles					*/
+#define B2RAT_6			0x00000600  /* B2 Read Access Time = 6 cycles					*/
+#define B2RAT_7			0x00000700  /* B2 Read Access Time = 7 cycles					*/
+#define B2RAT_8			0x00000800  /* B2 Read Access Time = 8 cycles					*/
+#define B2RAT_9			0x00000900  /* B2 Read Access Time = 9 cycles					*/
+#define B2RAT_10		0x00000A00  /* B2 Read Access Time = 10 cycles					*/
+#define B2RAT_11		0x00000B00  /* B2 Read Access Time = 11 cycles					*/
+#define B2RAT_12		0x00000C00  /* B2 Read Access Time = 12 cycles					*/
+#define B2RAT_13		0x00000D00  /* B2 Read Access Time = 13 cycles					*/
+#define B2RAT_14		0x00000E00  /* B2 Read Access Time = 14 cycles					*/
+#define B2RAT_15		0x00000F00  /* B2 Read Access Time = 15 cycles					*/
+#define B2WAT_1			0x00001000  /* B2 Write Access Time = 1 cycle					*/
+#define B2WAT_2			0x00002000  /* B2 Write Access Time = 2 cycles					*/
+#define B2WAT_3			0x00003000  /* B2 Write Access Time = 3 cycles					*/
+#define B2WAT_4			0x00004000  /* B2 Write Access Time = 4 cycles					*/
+#define B2WAT_5			0x00005000  /* B2 Write Access Time = 5 cycles					*/
+#define B2WAT_6			0x00006000  /* B2 Write Access Time = 6 cycles					*/
+#define B2WAT_7			0x00007000  /* B2 Write Access Time = 7 cycles					*/
+#define B2WAT_8			0x00008000  /* B2 Write Access Time = 8 cycles					*/
+#define B2WAT_9			0x00009000  /* B2 Write Access Time = 9 cycles					*/
+#define B2WAT_10		0x0000A000  /* B2 Write Access Time = 10 cycles					*/
+#define B2WAT_11		0x0000B000  /* B2 Write Access Time = 11 cycles					*/
+#define B2WAT_12		0x0000C000  /* B2 Write Access Time = 12 cycles					*/
+#define B2WAT_13		0x0000D000  /* B2 Write Access Time = 13 cycles					*/
+#define B2WAT_14		0x0000E000  /* B2 Write Access Time = 14 cycles					*/
+#define B2WAT_15		0x0000F000  /* B2 Write Access Time = 15 cycles					*/
+
+#define B3RDYEN			0x00010000  /* Bank 3 (B3) RDY Enable							*/
+#define B3RDYPOL		0x00020000  /* B3 RDY Active High								*/
+#define B3TT_1			0x00040000  /* B3 Transition Time (Read to Write) = 1 cycle		*/
+#define B3TT_2			0x00080000  /* B3 Transition Time (Read to Write) = 2 cycles	*/
+#define B3TT_3			0x000C0000  /* B3 Transition Time (Read to Write) = 3 cycles	*/
+#define B3TT_4			0x00000000  /* B3 Transition Time (Read to Write) = 4 cycles	*/
+#define B3ST_1			0x00100000  /* B3 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B3ST_2			0x00200000  /* B3 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B3ST_3			0x00300000  /* B3 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B3ST_4			0x00000000  /* B3 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B3HT_1			0x00400000  /* B3 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B3HT_2			0x00800000  /* B3 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B3HT_3			0x00C00000  /* B3 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B3HT_0			0x00000000  /* B3 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B3RAT_1			0x01000000  /* B3 Read Access Time = 1 cycle					*/
+#define B3RAT_2			0x02000000  /* B3 Read Access Time = 2 cycles					*/
+#define B3RAT_3			0x03000000  /* B3 Read Access Time = 3 cycles					*/
+#define B3RAT_4			0x04000000  /* B3 Read Access Time = 4 cycles					*/
+#define B3RAT_5			0x05000000  /* B3 Read Access Time = 5 cycles					*/
+#define B3RAT_6			0x06000000  /* B3 Read Access Time = 6 cycles					*/
+#define B3RAT_7			0x07000000  /* B3 Read Access Time = 7 cycles					*/
+#define B3RAT_8			0x08000000  /* B3 Read Access Time = 8 cycles					*/
+#define B3RAT_9			0x09000000  /* B3 Read Access Time = 9 cycles					*/
+#define B3RAT_10		0x0A000000  /* B3 Read Access Time = 10 cycles					*/
+#define B3RAT_11		0x0B000000  /* B3 Read Access Time = 11 cycles					*/
+#define B3RAT_12		0x0C000000  /* B3 Read Access Time = 12 cycles					*/
+#define B3RAT_13		0x0D000000  /* B3 Read Access Time = 13 cycles					*/
+#define B3RAT_14		0x0E000000  /* B3 Read Access Time = 14 cycles					*/
+#define B3RAT_15		0x0F000000  /* B3 Read Access Time = 15 cycles					*/
+#define B3WAT_1			0x10000000  /* B3 Write Access Time = 1 cycle					*/
+#define B3WAT_2			0x20000000  /* B3 Write Access Time = 2 cycles					*/
+#define B3WAT_3			0x30000000  /* B3 Write Access Time = 3 cycles					*/
+#define B3WAT_4			0x40000000  /* B3 Write Access Time = 4 cycles					*/
+#define B3WAT_5			0x50000000  /* B3 Write Access Time = 5 cycles					*/
+#define B3WAT_6			0x60000000  /* B3 Write Access Time = 6 cycles					*/
+#define B3WAT_7			0x70000000  /* B3 Write Access Time = 7 cycles					*/
+#define B3WAT_8			0x80000000  /* B3 Write Access Time = 8 cycles					*/
+#define B3WAT_9			0x90000000  /* B3 Write Access Time = 9 cycles					*/
+#define B3WAT_10		0xA0000000  /* B3 Write Access Time = 10 cycles					*/
+#define B3WAT_11		0xB0000000  /* B3 Write Access Time = 11 cycles					*/
+#define B3WAT_12		0xC0000000  /* B3 Write Access Time = 12 cycles					*/
+#define B3WAT_13		0xD0000000  /* B3 Write Access Time = 13 cycles					*/
+#define B3WAT_14		0xE0000000  /* B3 Write Access Time = 14 cycles					*/
+#define B3WAT_15		0xF0000000  /* B3 Write Access Time = 15 cycles					*/
+
+
+/* **********************  SDRAM CONTROLLER MASKS  **********************************************/
+/* EBIU_SDGCTL Masks																			*/
+#define SCTLE			0x00000001	/* Enable SDRAM Signals										*/
+#define CL_2			0x00000008	/* SDRAM CAS Latency = 2 cycles								*/
+#define CL_3			0x0000000C	/* SDRAM CAS Latency = 3 cycles								*/
+#define PASR_ALL		0x00000000	/* All 4 SDRAM Banks Refreshed In Self-Refresh				*/
+#define PASR_B0_B1		0x00000010	/* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh		*/
+#define PASR_B0			0x00000020	/* Only SDRAM Bank 0 Is Refreshed In Self-Refresh			*/
+#define TRAS_1			0x00000040	/* SDRAM tRAS = 1 cycle										*/
+#define TRAS_2			0x00000080	/* SDRAM tRAS = 2 cycles									*/
+#define TRAS_3			0x000000C0	/* SDRAM tRAS = 3 cycles									*/
+#define TRAS_4			0x00000100	/* SDRAM tRAS = 4 cycles									*/
+#define TRAS_5			0x00000140	/* SDRAM tRAS = 5 cycles									*/
+#define TRAS_6			0x00000180	/* SDRAM tRAS = 6 cycles									*/
+#define TRAS_7			0x000001C0	/* SDRAM tRAS = 7 cycles									*/
+#define TRAS_8			0x00000200	/* SDRAM tRAS = 8 cycles									*/
+#define TRAS_9			0x00000240	/* SDRAM tRAS = 9 cycles									*/
+#define TRAS_10			0x00000280	/* SDRAM tRAS = 10 cycles									*/
+#define TRAS_11			0x000002C0	/* SDRAM tRAS = 11 cycles									*/
+#define TRAS_12			0x00000300	/* SDRAM tRAS = 12 cycles									*/
+#define TRAS_13			0x00000340	/* SDRAM tRAS = 13 cycles									*/
+#define TRAS_14			0x00000380	/* SDRAM tRAS = 14 cycles									*/
+#define TRAS_15			0x000003C0	/* SDRAM tRAS = 15 cycles									*/
+#define TRP_1			0x00000800	/* SDRAM tRP = 1 cycle										*/
+#define TRP_2			0x00001000	/* SDRAM tRP = 2 cycles										*/
+#define TRP_3			0x00001800	/* SDRAM tRP = 3 cycles										*/
+#define TRP_4			0x00002000	/* SDRAM tRP = 4 cycles										*/
+#define TRP_5			0x00002800	/* SDRAM tRP = 5 cycles										*/
+#define TRP_6			0x00003000	/* SDRAM tRP = 6 cycles										*/
+#define TRP_7			0x00003800	/* SDRAM tRP = 7 cycles										*/
+#define TRCD_1			0x00008000	/* SDRAM tRCD = 1 cycle										*/
+#define TRCD_2			0x00010000	/* SDRAM tRCD = 2 cycles									*/
+#define TRCD_3			0x00018000	/* SDRAM tRCD = 3 cycles									*/
+#define TRCD_4			0x00020000	/* SDRAM tRCD = 4 cycles									*/
+#define TRCD_5			0x00028000	/* SDRAM tRCD = 5 cycles									*/
+#define TRCD_6			0x00030000	/* SDRAM tRCD = 6 cycles									*/
+#define TRCD_7			0x00038000	/* SDRAM tRCD = 7 cycles									*/
+#define TWR_1			0x00080000	/* SDRAM tWR = 1 cycle										*/
+#define TWR_2			0x00100000	/* SDRAM tWR = 2 cycles										*/
+#define TWR_3			0x00180000	/* SDRAM tWR = 3 cycles										*/
+#define PUPSD			0x00200000	/* Power-Up Start Delay (15 SCLK Cycles Delay)				*/
+#define PSM				0x00400000	/* Power-Up Sequence (Mode Register Before/After* Refresh)	*/
+#define PSS				0x00800000	/* Enable Power-Up Sequence on Next SDRAM Access			*/
+#define SRFS			0x01000000	/* Enable SDRAM Self-Refresh Mode							*/
+#define EBUFE			0x02000000	/* Enable External Buffering Timing							*/
+#define FBBRW			0x04000000	/* Enable Fast Back-To-Back Read To Write					*/
+#define EMREN			0x10000000	/* Extended Mode Register Enable							*/
+#define TCSR			0x20000000	/* Temp-Compensated Self-Refresh Value (85/45* Deg C)		*/
+#define CDDBG			0x40000000	/* Tristate SDRAM Controls During Bus Grant					*/
+
+/* EBIU_SDBCTL Masks																		*/
+#define EBE				0x0001		/* Enable SDRAM External Bank							*/
+#define EBSZ_16			0x0000		/* SDRAM External Bank Size = 16MB	*/
+#define EBSZ_32			0x0002		/* SDRAM External Bank Size = 32MB	*/
+#define EBSZ_64			0x0004		/* SDRAM External Bank Size = 64MB	*/
+#define EBSZ_128		0x0006		/* SDRAM External Bank Size = 128MB		*/
+#define EBSZ_256		0x0008		/* SDRAM External Bank Size = 256MB 	*/
+#define EBSZ_512		0x000A		/* SDRAM External Bank Size = 512MB		*/
+#define EBCAW_8			0x0000		/* SDRAM External Bank Column Address Width = 8 Bits	*/
+#define EBCAW_9			0x0010		/* SDRAM External Bank Column Address Width = 9 Bits	*/
+#define EBCAW_10		0x0020		/* SDRAM External Bank Column Address Width = 10 Bits	*/
+#define EBCAW_11		0x0030		/* SDRAM External Bank Column Address Width = 11 Bits	*/
+
+/* EBIU_SDSTAT Masks														*/
+#define SDCI			0x0001		/* SDRAM Controller Idle 				*/
+#define SDSRA			0x0002		/* SDRAM Self-Refresh Active			*/
+#define SDPUA			0x0004		/* SDRAM Power-Up Active 				*/
+#define SDRS			0x0008		/* SDRAM Will Power-Up On Next Access	*/
+#define SDEASE			0x0010		/* SDRAM EAB Sticky Error Status		*/
+#define BGSTAT			0x0020		/* Bus Grant Status						*/
+
+
+/* **************************  DMA CONTROLLER MASKS  ********************************/
+/* DMAx_CONFIG, MDMA_yy_CONFIG Masks												*/
+#define DMAEN			0x0001		/* DMA Channel Enable							*/
+#define WNR				0x0002		/* Channel Direction (W/R*)						*/
+#define WDSIZE_8		0x0000		/* Transfer Word Size = 8						*/
+#define WDSIZE_16		0x0004		/* Transfer Word Size = 16						*/
+#define WDSIZE_32		0x0008		/* Transfer Word Size = 32						*/
+#define DMA2D			0x0010		/* DMA Mode (2D/1D*)							*/
+#define RESTART			0x0020		/* DMA Buffer Clear								*/
+#define DI_SEL			0x0040		/* Data Interrupt Timing Select					*/
+#define DI_EN			0x0080		/* Data Interrupt Enable						*/
+#define NDSIZE_0		0x0000		/* Next Descriptor Size = 0 (Stop/Autobuffer)	*/
+#define NDSIZE_1		0x0100		/* Next Descriptor Size = 1						*/
+#define NDSIZE_2		0x0200		/* Next Descriptor Size = 2						*/
+#define NDSIZE_3		0x0300		/* Next Descriptor Size = 3						*/
+#define NDSIZE_4		0x0400		/* Next Descriptor Size = 4						*/
+#define NDSIZE_5		0x0500		/* Next Descriptor Size = 5						*/
+#define NDSIZE_6		0x0600		/* Next Descriptor Size = 6						*/
+#define NDSIZE_7		0x0700		/* Next Descriptor Size = 7						*/
+#define NDSIZE_8		0x0800		/* Next Descriptor Size = 8						*/
+#define NDSIZE_9		0x0900		/* Next Descriptor Size = 9						*/
+#define NDSIZE	        	0x0900	/* Next Descriptor Size */
+#define DMAFLOW	        	0x7000	/* Flow Control */
+#define DMAFLOW_STOP		0x0000		/* Stop Mode									*/
+#define DMAFLOW_AUTO		0x1000		/* Autobuffer Mode								*/
+#define DMAFLOW_ARRAY		0x4000		/* Descriptor Array Mode						*/
+#define DMAFLOW_SMALL		0x6000		/* Small Model Descriptor List Mode				*/
+#define DMAFLOW_LARGE		0x7000		/* Large Model Descriptor List Mode				*/
+
+/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks								*/
+#define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*)	*/
+#define PMAP			0xF000	/* Peripheral Mapped To This Channel				*/
+#define PMAP_PPI		0x0000	/* 		PPI Port DMA								*/
+#define	PMAP_EMACRX		0x1000	/* 		Ethernet Receive DMA						*/
+#define PMAP_EMACTX		0x2000	/* 		Ethernet Transmit DMA						*/
+#define PMAP_SPORT0RX	0x3000	/* 		SPORT0 Receive DMA							*/
+#define PMAP_SPORT0TX	0x4000	/* 		SPORT0 Transmit DMA							*/
+#define PMAP_SPORT1RX	0x5000	/* 		SPORT1 Receive DMA							*/
+#define PMAP_SPORT1TX	0x6000	/* 		SPORT1 Transmit DMA							*/
+#define PMAP_SPI		0x7000	/* 		SPI Port DMA								*/
+#define PMAP_UART0RX	0x8000	/* 		UART0 Port Receive DMA						*/
+#define PMAP_UART0TX	0x9000	/* 		UART0 Port Transmit DMA						*/
+#define	PMAP_UART1RX	0xA000	/* 		UART1 Port Receive DMA						*/
+#define	PMAP_UART1TX	0xB000	/* 		UART1 Port Transmit DMA						*/
+
+/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks						*/
+#define DMA_DONE		0x0001	/* DMA Completion Interrupt Status	*/
+#define DMA_ERR			0x0002	/* DMA Error Interrupt Status		*/
+#define DFETCH			0x0004	/* DMA Descriptor Fetch Indicator	*/
+#define DMA_RUN			0x0008	/* DMA Channel Running Indicator	*/
+
+
+/*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
+/*  PPI_CONTROL Masks													*/
+#define PORT_EN			0x0001		/* PPI Port Enable					*/
+#define PORT_DIR		0x0002		/* PPI Port Direction				*/
+#define XFR_TYPE		0x000C		/* PPI Transfer Type				*/
+#define PORT_CFG		0x0030		/* PPI Port Configuration			*/
+#define FLD_SEL			0x0040		/* PPI Active Field Select			*/
+#define PACK_EN			0x0080		/* PPI Packing Mode					*/
+#define DMA32			0x0100		/* PPI 32-bit DMA Enable			*/
+#define SKIP_EN			0x0200		/* PPI Skip Element Enable			*/
+#define SKIP_EO			0x0400		/* PPI Skip Even/Odd Elements		*/
+#define DLEN_8			0x0000		/* Data Length = 8 Bits				*/
+#define DLEN_10			0x0800		/* Data Length = 10 Bits			*/
+#define DLEN_11			0x1000		/* Data Length = 11 Bits			*/
+#define DLEN_12			0x1800		/* Data Length = 12 Bits			*/
+#define DLEN_13			0x2000		/* Data Length = 13 Bits			*/
+#define DLEN_14			0x2800		/* Data Length = 14 Bits			*/
+#define DLEN_15			0x3000		/* Data Length = 15 Bits			*/
+#define DLEN_16			0x3800		/* Data Length = 16 Bits			*/
+#define DLENGTH			0x3800		/* PPI Data Length  */
+#define POLC			0x4000		/* PPI Clock Polarity				*/
+#define POLS			0x8000		/* PPI Frame Sync Polarity			*/
+
+/* PPI_STATUS Masks														*/
+#define FLD				0x0400		/* Field Indicator					*/
+#define FT_ERR			0x0800		/* Frame Track Error				*/
+#define OVR				0x1000		/* FIFO Overflow Error				*/
+#define UNDR			0x2000		/* FIFO Underrun Error				*/
+#define ERR_DET			0x4000		/* Error Detected Indicator			*/
+#define ERR_NCOR		0x8000		/* Error Not Corrected Indicator	*/
+
+
+/*  ********************  TWO-WIRE INTERFACE (TWI) MASKS  ***********************/
+/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y);  )				*/
+#define	CLKLOW(x)	((x) & 0xFF)		/* Periods Clock Is Held Low			*/
+#define CLKHI(y)	(((y)&0xFF)<<0x8)	/* Periods Before New Clock Low			*/
+
+/* TWI_PRESCALE Masks															*/
+#define	PRESCALE	0x007F		/* SCLKs Per Internal Time Reference (10MHz)	*/
+#define	TWI_ENA		0x0080		/* TWI Enable									*/
+#define	SCCB		0x0200		/* SCCB Compatibility Enable					*/
+
+/* TWI_SLAVE_CTRL Masks															*/
+#define	SEN			0x0001		/* Slave Enable									*/
+#define	SADD_LEN	0x0002		/* Slave Address Length							*/
+#define	STDVAL		0x0004		/* Slave Transmit Data Valid					*/
+#define	NAK			0x0008		/* NAK/ACK* Generated At Conclusion Of Transfer */
+#define	GEN			0x0010		/* General Call Adrress Matching Enabled		*/
+
+/* TWI_SLAVE_STAT Masks															*/
+#define	SDIR		0x0001		/* Slave Transfer Direction (Transmit/Receive*)	*/
+#define GCALL		0x0002		/* General Call Indicator						*/
+
+/* TWI_MASTER_CTRL Masks													*/
+#define	MEN			0x0001		/* Master Mode Enable						*/
+#define	MADD_LEN	0x0002		/* Master Address Length					*/
+#define	MDIR		0x0004		/* Master Transmit Direction (RX/TX*)		*/
+#define	FAST		0x0008		/* Use Fast Mode Timing Specs				*/
+#define	STOP		0x0010		/* Issue Stop Condition						*/
+#define	RSTART		0x0020		/* Repeat Start or Stop* At End Of Transfer	*/
+#define	DCNT		0x3FC0		/* Data Bytes To Transfer					*/
+#define	SDAOVR		0x4000		/* Serial Data Override						*/
+#define	SCLOVR		0x8000		/* Serial Clock Override					*/
+
+/* TWI_MASTER_STAT Masks														*/
+#define	MPROG		0x0001		/* Master Transfer In Progress					*/
+#define	LOSTARB		0x0002		/* Lost Arbitration Indicator (Xfer Aborted)	*/
+#define	ANAK		0x0004		/* Address Not Acknowledged						*/
+#define	DNAK		0x0008		/* Data Not Acknowledged						*/
+#define	BUFRDERR	0x0010		/* Buffer Read Error							*/
+#define	BUFWRERR	0x0020		/* Buffer Write Error							*/
+#define	SDASEN		0x0040		/* Serial Data Sense							*/
+#define	SCLSEN		0x0080		/* Serial Clock Sense							*/
+#define	BUSBUSY		0x0100		/* Bus Busy Indicator							*/
+
+/* TWI_INT_SRC and TWI_INT_ENABLE Masks						*/
+#define	SINIT		0x0001		/* Slave Transfer Initiated	*/
+#define	SCOMP		0x0002		/* Slave Transfer Complete	*/
+#define	SERR		0x0004		/* Slave Transfer Error		*/
+#define	SOVF		0x0008		/* Slave Overflow			*/
+#define	MCOMP		0x0010		/* Master Transfer Complete	*/
+#define	MERR		0x0020		/* Master Transfer Error	*/
+#define	XMTSERV		0x0040		/* Transmit FIFO Service	*/
+#define	RCVSERV		0x0080		/* Receive FIFO Service		*/
+
+/* TWI_FIFO_CTRL Masks												*/
+#define	XMTFLUSH	0x0001		/* Transmit Buffer Flush			*/
+#define	RCVFLUSH	0x0002		/* Receive Buffer Flush				*/
+#define	XMTINTLEN	0x0004		/* Transmit Buffer Interrupt Length	*/
+#define	RCVINTLEN	0x0008		/* Receive Buffer Interrupt Length	*/
+
+/* TWI_FIFO_STAT Masks															*/
+#define	XMTSTAT		0x0003		/* Transmit FIFO Status							*/
+#define	XMT_EMPTY	0x0000		/* 		Transmit FIFO Empty						*/
+#define	XMT_HALF	0x0001		/* 		Transmit FIFO Has 1 Byte To Write		*/
+#define	XMT_FULL	0x0003		/* 		Transmit FIFO Full (2 Bytes To Write)	*/
+
+#define	RCVSTAT		0x000C		/* Receive FIFO Status							*/
+#define	RCV_EMPTY	0x0000		/* 		Receive FIFO Empty						*/
+#define	RCV_HALF	0x0004		/* 		Receive FIFO Has 1 Byte To Read			*/
+#define	RCV_FULL	0x000C		/* 		Receive FIFO Full (2 Bytes To Read)		*/
+
+
+/* Omit CAN masks from defBF534.h */
+
+/*  *******************  PIN CONTROL REGISTER MASKS  ************************/
+/* PORT_MUX Masks															*/
+#define	PJSE			0x0001			/* Port J SPI/SPORT Enable			*/
+#define	PJSE_SPORT		0x0000			/* 		Enable TFS0/DT0PRI			*/
+#define	PJSE_SPI		0x0001			/* 		Enable SPI_SSEL3:2			*/
+
+#define	PJCE(x)			(((x)&0x3)<<1)	/* Port J CAN/SPI/SPORT Enable		*/
+#define	PJCE_SPORT		0x0000			/* 		Enable DR0SEC/DT0SEC		*/
+#define	PJCE_CAN		0x0002			/* 		Enable CAN RX/TX			*/
+#define	PJCE_SPI		0x0004			/* 		Enable SPI_SSEL7			*/
+
+#define	PFDE			0x0008			/* Port F DMA Request Enable		*/
+#define	PFDE_UART		0x0000			/* 		Enable UART0 RX/TX			*/
+#define	PFDE_DMA		0x0008			/* 		Enable DMAR1:0				*/
+
+#define	PFTE			0x0010			/* Port F Timer Enable				*/
+#define	PFTE_UART		0x0000			/*		Enable UART1 RX/TX			*/
+#define	PFTE_TIMER		0x0010			/* 		Enable TMR7:6				*/
+
+#define	PFS6E			0x0020			/* Port F SPI SSEL 6 Enable			*/
+#define	PFS6E_TIMER		0x0000			/*		Enable TMR5					*/
+#define	PFS6E_SPI		0x0020			/* 		Enable SPI_SSEL6			*/
+
+#define	PFS5E			0x0040			/* Port F SPI SSEL 5 Enable			*/
+#define	PFS5E_TIMER		0x0000			/*		Enable TMR4					*/
+#define	PFS5E_SPI		0x0040			/* 		Enable SPI_SSEL5			*/
+
+#define	PFS4E			0x0080			/* Port F SPI SSEL 4 Enable			*/
+#define	PFS4E_TIMER		0x0000			/*		Enable TMR3					*/
+#define	PFS4E_SPI		0x0080			/* 		Enable SPI_SSEL4			*/
+
+#define	PFFE			0x0100			/* Port F PPI Frame Sync Enable		*/
+#define	PFFE_TIMER		0x0000			/* 		Enable TMR2					*/
+#define	PFFE_PPI		0x0100			/* 		Enable PPI FS3				*/
+
+#define	PGSE			0x0200			/* Port G SPORT1 Secondary Enable	*/
+#define	PGSE_PPI		0x0000			/* 		Enable PPI D9:8				*/
+#define	PGSE_SPORT		0x0200			/* 		Enable DR1SEC/DT1SEC		*/
+
+#define	PGRE			0x0400			/* Port G SPORT1 Receive Enable		*/
+#define	PGRE_PPI		0x0000			/* 		Enable PPI D12:10			*/
+#define	PGRE_SPORT		0x0400			/* 		Enable DR1PRI/RFS1/RSCLK1	*/
+
+#define	PGTE			0x0800			/* Port G SPORT1 Transmit Enable	*/
+#define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
+#define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
+
+
+/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
+/* HDMAx_CTL Masks														*/
+#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
+#define	REP			0x0002	/* HDMA Request Polarity					*/
+#define	UTE			0x0004	/* Urgency Threshold Enable					*/
+#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
+#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
+#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
+#define	DRQ			0x0300	/* HDMA Request Type						*/
+#define	DRQ_NONE	0x0000	/* 		No Request							*/
+#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
+#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
+#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
+#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
+#define	PS			0x2000	/* HDMA Pin Status							*/
+#define	OI			0x4000	/* Overflow Interrupt Generated				*/
+#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
+
+/* entry addresses of the user-callable Boot ROM functions */
+
+#define _BOOTROM_RESET 0xEF000000 
+#define _BOOTROM_FINAL_INIT 0xEF000002 
+#define _BOOTROM_DO_MEMORY_DMA 0xEF000006
+#define _BOOTROM_BOOT_DXE_FLASH 0xEF000008 
+#define _BOOTROM_BOOT_DXE_SPI 0xEF00000A 
+#define _BOOTROM_BOOT_DXE_TWI 0xEF00000C 
+#define _BOOTROM_GET_DXE_ADDRESS_FLASH 0xEF000010
+#define _BOOTROM_GET_DXE_ADDRESS_SPI 0xEF000012
+#define _BOOTROM_GET_DXE_ADDRESS_TWI 0xEF000014
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define	PGDE_UART   PFDE_UART
+#define	PGDE_DMA    PFDE_DMA
+#define	CKELOW		SCKELOW
+
+/* ==== end from defBF534.h ==== */
+
+/* HOST Port Registers */
+
+#define                     HOST_CONTROL  0xffc03400   /* HOST Control Register */
+#define                      HOST_STATUS  0xffc03404   /* HOST Status Register */
+#define                     HOST_TIMEOUT  0xffc03408   /* HOST Acknowledge Mode Timeout Register */
+
+/* Counter Registers */
+
+#define                       CNT_CONFIG  0xffc03500   /* Configuration Register */
+#define                        CNT_IMASK  0xffc03504   /* Interrupt Mask Register */
+#define                       CNT_STATUS  0xffc03508   /* Status Register */
+#define                      CNT_COMMAND  0xffc0350c   /* Command Register */
+#define                     CNT_DEBOUNCE  0xffc03510   /* Debounce Register */
+#define                      CNT_COUNTER  0xffc03514   /* Counter Register */
+#define                          CNT_MAX  0xffc03518   /* Maximal Count Register */
+#define                          CNT_MIN  0xffc0351c   /* Minimal Count Register */
+
+/* OTP/FUSE Registers */
+
+#define                      OTP_CONTROL  0xffc03600   /* OTP/Fuse Control Register */
+#define                          OTP_BEN  0xffc03604   /* OTP/Fuse Byte Enable */
+#define                       OTP_STATUS  0xffc03608   /* OTP/Fuse Status */
+#define                       OTP_TIMING  0xffc0360c   /* OTP/Fuse Access Timing */
+
+/* Security Registers */
+
+#define                    SECURE_SYSSWT  0xffc03620   /* Secure System Switches */
+#define                   SECURE_CONTROL  0xffc03624   /* Secure Control */
+#define                    SECURE_STATUS  0xffc03628   /* Secure Status */
+
+/* OTP Read/Write Data Buffer Registers */
+
+#define                        OTP_DATA0  0xffc03680   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA1  0xffc03684   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA2  0xffc03688   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA3  0xffc0368c   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+
+/* NFC Registers */
+
+#define                          NFC_CTL  0xffc03700   /* NAND Control Register */
+#define                         NFC_STAT  0xffc03704   /* NAND Status Register */
+#define                      NFC_IRQSTAT  0xffc03708   /* NAND Interrupt Status Register */
+#define                      NFC_IRQMASK  0xffc0370c   /* NAND Interrupt Mask Register */
+#define                         NFC_ECC0  0xffc03710   /* NAND ECC Register 0 */
+#define                         NFC_ECC1  0xffc03714   /* NAND ECC Register 1 */
+#define                         NFC_ECC2  0xffc03718   /* NAND ECC Register 2 */
+#define                         NFC_ECC3  0xffc0371c   /* NAND ECC Register 3 */
+#define                        NFC_COUNT  0xffc03720   /* NAND ECC Count Register */
+#define                          NFC_RST  0xffc03724   /* NAND ECC Reset Register */
+#define                        NFC_PGCTL  0xffc03728   /* NAND Page Control Register */
+#define                         NFC_READ  0xffc0372c   /* NAND Read Data Register */
+#define                         NFC_ADDR  0xffc03740   /* NAND Address Register */
+#define                          NFC_CMD  0xffc03744   /* NAND Command Register */
+#define                      NFC_DATA_WR  0xffc03748   /* NAND Data Write Register */
+#define                      NFC_DATA_RD  0xffc0374c   /* NAND Data Read Register */
+
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for HOST_CONTROL */
+
+#define                   HOST_EN  0x1        /* Host Enable */
+#define                  nHOST_EN  0x0       
+#define                  HOST_END  0x2        /* Host Endianess */
+#define                 nHOST_END  0x0       
+#define                 DATA_SIZE  0x4        /* Data Size */
+#define                nDATA_SIZE  0x0       
+#define                  HOST_RST  0x8        /* Host Reset */
+#define                 nHOST_RST  0x0       
+#define                  HRDY_OVR  0x20       /* Host Ready Override */
+#define                 nHRDY_OVR  0x0       
+#define                  INT_MODE  0x40       /* Interrupt Mode */
+#define                 nINT_MODE  0x0       
+#define                     BT_EN  0x80       /* Bus Timeout Enable */
+#define                    nBT_EN  0x0       
+#define                       EHW  0x100      /* Enable Host Write */
+#define                      nEHW  0x0       
+#define                       EHR  0x200      /* Enable Host Read */
+#define                      nEHR  0x0       
+#define                       BDR  0x400      /* Burst DMA Requests */
+#define                      nBDR  0x0       
+
+/* Bit masks for HOST_STATUS */
+
+#define                     READY  0x1        /* DMA Ready */
+#define                    nREADY  0x0       
+#define                  FIFOFULL  0x2        /* FIFO Full */
+#define                 nFIFOFULL  0x0       
+#define                 FIFOEMPTY  0x4        /* FIFO Empty */
+#define                nFIFOEMPTY  0x0       
+#define                  COMPLETE  0x8        /* DMA Complete */
+#define                 nCOMPLETE  0x0       
+#define                      HSHK  0x10       /* Host Handshake */
+#define                     nHSHK  0x0       
+#define                   TIMEOUT  0x20       /* Host Timeout */
+#define                  nTIMEOUT  0x0       
+#define                      HIRQ  0x40       /* Host Interrupt Request */
+#define                     nHIRQ  0x0       
+#define                ALLOW_CNFG  0x80       /* Allow New Configuration */
+#define               nALLOW_CNFG  0x0       
+#define                   DMA_DIR  0x100      /* DMA Direction */
+#define                  nDMA_DIR  0x0       
+#define                       BTE  0x200      /* Bus Timeout Enabled */
+#define                      nBTE  0x0       
+#define               HOSTRD_DONE  0x8000     /* Host Read Completion Interrupt */
+#define              nHOSTRD_DONE  0x0
+
+/* Bit masks for HOST_TIMEOUT */
+
+#define             COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
+
+/* Bit masks for CNT_CONFIG */
+
+#define                      CNTE  0x1        /* Counter Enable */
+#define                     nCNTE  0x0       
+#define                      DEBE  0x2        /* Debounce Enable */
+#define                     nDEBE  0x0       
+#define                    CDGINV  0x10       /* CDG Pin Polarity Invert */
+#define                   nCDGINV  0x0       
+#define                    CUDINV  0x20       /* CUD Pin Polarity Invert */
+#define                   nCUDINV  0x0       
+#define                    CZMINV  0x40       /* CZM Pin Polarity Invert */
+#define                   nCZMINV  0x0       
+#define                   CNTMODE  0x700      /* Counter Operating Mode */
+#define                      ZMZC  0x800      /* CZM Zeroes Counter Enable */
+#define                     nZMZC  0x0       
+#define                   BNDMODE  0x3000     /* Boundary register Mode */
+#define                    INPDIS  0x8000     /* CUG and CDG Input Disable */
+#define                   nINPDIS  0x0       
+
+/* Bit masks for CNT_IMASK */
+
+#define                      ICIE  0x1        /* Illegal Gray/Binary Code Interrupt Enable */
+#define                     nICIE  0x0       
+#define                      UCIE  0x2        /* Up count Interrupt Enable */
+#define                     nUCIE  0x0       
+#define                      DCIE  0x4        /* Down count Interrupt Enable */
+#define                     nDCIE  0x0       
+#define                    MINCIE  0x8        /* Min Count Interrupt Enable */
+#define                   nMINCIE  0x0       
+#define                    MAXCIE  0x10       /* Max Count Interrupt Enable */
+#define                   nMAXCIE  0x0       
+#define                   COV31IE  0x20       /* Bit 31 Overflow Interrupt Enable */
+#define                  nCOV31IE  0x0       
+#define                   COV15IE  0x40       /* Bit 15 Overflow Interrupt Enable */
+#define                  nCOV15IE  0x0       
+#define                   CZEROIE  0x80       /* Count to Zero Interrupt Enable */
+#define                  nCZEROIE  0x0       
+#define                     CZMIE  0x100      /* CZM Pin Interrupt Enable */
+#define                    nCZMIE  0x0       
+#define                    CZMEIE  0x200      /* CZM Error Interrupt Enable */
+#define                   nCZMEIE  0x0       
+#define                    CZMZIE  0x400      /* CZM Zeroes Counter Interrupt Enable */
+#define                   nCZMZIE  0x0       
+
+/* Bit masks for CNT_STATUS */
+
+#define                      ICII  0x1        /* Illegal Gray/Binary Code Interrupt Identifier */
+#define                     nICII  0x0       
+#define                      UCII  0x2        /* Up count Interrupt Identifier */
+#define                     nUCII  0x0       
+#define                      DCII  0x4        /* Down count Interrupt Identifier */
+#define                     nDCII  0x0       
+#define                    MINCII  0x8        /* Min Count Interrupt Identifier */
+#define                   nMINCII  0x0       
+#define                    MAXCII  0x10       /* Max Count Interrupt Identifier */
+#define                   nMAXCII  0x0       
+#define                   COV31II  0x20       /* Bit 31 Overflow Interrupt Identifier */
+#define                  nCOV31II  0x0       
+#define                   COV15II  0x40       /* Bit 15 Overflow Interrupt Identifier */
+#define                  nCOV15II  0x0       
+#define                   CZEROII  0x80       /* Count to Zero Interrupt Identifier */
+#define                  nCZEROII  0x0       
+#define                     CZMII  0x100      /* CZM Pin Interrupt Identifier */
+#define                    nCZMII  0x0       
+#define                    CZMEII  0x200      /* CZM Error Interrupt Identifier */
+#define                   nCZMEII  0x0       
+#define                    CZMZII  0x400      /* CZM Zeroes Counter Interrupt Identifier */
+#define                   nCZMZII  0x0       
+
+/* Bit masks for CNT_COMMAND */
+
+#define                    W1LCNT  0xf        /* Load Counter Register */
+#define                    W1LMIN  0xf0       /* Load Min Register */
+#define                    W1LMAX  0xf00      /* Load Max Register */
+#define                  W1ZMONCE  0x1000     /* Enable CZM Clear Counter Once */
+#define                 nW1ZMONCE  0x0       
+
+/* Bit masks for CNT_DEBOUNCE */
+
+#define                 DPRESCALE  0xf        /* Load Counter Register */
+
+/* Bit masks for OTP_CONTROL */
+
+#define                FUSE_FADDR  0x1ff      /* OTP/Fuse Address */
+#define                      FIEN  0x800      /* OTP/Fuse Interrupt Enable */
+#define                     nFIEN  0x0       
+#define                  FTESTDEC  0x1000     /* OTP/Fuse Test Decoder */
+#define                 nFTESTDEC  0x0       
+#define                   FWRTEST  0x2000     /* OTP/Fuse Write Test */
+#define                  nFWRTEST  0x0       
+#define                     FRDEN  0x4000     /* OTP/Fuse Read Enable */
+#define                    nFRDEN  0x0       
+#define                     FWREN  0x8000     /* OTP/Fuse Write Enable */
+#define                    nFWREN  0x0       
+
+/* Bit masks for OTP_BEN */
+
+#define                      FBEN  0xffff     /* OTP/Fuse Byte Enable */
+
+/* Bit masks for OTP_STATUS */
+
+#define                     FCOMP  0x1        /* OTP/Fuse Access Complete */
+#define                    nFCOMP  0x0       
+#define                    FERROR  0x2        /* OTP/Fuse Access Error */
+#define                   nFERROR  0x0       
+#define                  MMRGLOAD  0x10       /* Memory Mapped Register Gasket Load */
+#define                 nMMRGLOAD  0x0       
+#define                  MMRGLOCK  0x20       /* Memory Mapped Register Gasket Lock */
+#define                 nMMRGLOCK  0x0       
+#define                    FPGMEN  0x40       /* OTP/Fuse Program Enable */
+#define                   nFPGMEN  0x0       
+
+/* Bit masks for OTP_TIMING */
+
+#define                   USECDIV  0xff       /* Micro Second Divider */
+#define                   READACC  0x7f00     /* Read Access Time */
+#define                   CPUMPRL  0x38000    /* Charge Pump Release Time */
+#define                   CPUMPSU  0xc0000    /* Charge Pump Setup Time */
+#define                   CPUMPHD  0xf00000   /* Charge Pump Hold Time */
+#define                   PGMTIME  0xff000000 /* Program Time */
+
+/* Bit masks for SECURE_SYSSWT */
+
+#define                   EMUDABL  0x1        /* Emulation Disable. */
+#define                  nEMUDABL  0x0       
+#define                   RSTDABL  0x2        /* Reset Disable */
+#define                  nRSTDABL  0x0       
+#define                   L1IDABL  0x1c       /* L1 Instruction Memory Disable. */
+#define                  L1DADABL  0xe0       /* L1 Data Bank A Memory Disable. */
+#define                  L1DBDABL  0x700      /* L1 Data Bank B Memory Disable. */
+#define                   DMA0OVR  0x800      /* DMA0 Memory Access Override */
+#define                  nDMA0OVR  0x0       
+#define                   DMA1OVR  0x1000     /* DMA1 Memory Access Override */
+#define                  nDMA1OVR  0x0       
+#define                    EMUOVR  0x4000     /* Emulation Override */
+#define                   nEMUOVR  0x0       
+#define                    OTPSEN  0x8000     /* OTP Secrets Enable. */
+#define                   nOTPSEN  0x0       
+#define                    L2DABL  0x70000    /* L2 Memory Disable. */
+
+/* Bit masks for SECURE_CONTROL */
+
+#define                   SECURE0  0x1        /* SECURE 0 */
+#define                  nSECURE0  0x0       
+#define                   SECURE1  0x2        /* SECURE 1 */
+#define                  nSECURE1  0x0       
+#define                   SECURE2  0x4        /* SECURE 2 */
+#define                  nSECURE2  0x0       
+#define                   SECURE3  0x8        /* SECURE 3 */
+#define                  nSECURE3  0x0       
+
+/* Bit masks for SECURE_STATUS */
+
+#define                   SECMODE  0x3        /* Secured Mode Control State */
+#define                       NMI  0x4        /* Non Maskable Interrupt */
+#define                      nNMI  0x0       
+#define                   AFVALID  0x8        /* Authentication Firmware Valid */
+#define                  nAFVALID  0x0       
+#define                    AFEXIT  0x10       /* Authentication Firmware Exit */
+#define                   nAFEXIT  0x0       
+#define                   SECSTAT  0xe0       /* Secure Status */
+
+/* Bit masks for NFC_CTL */
+
+#define                    WR_DLY  0xf        /* Write Strobe Delay */
+#define                    RD_DLY  0xf0       /* Read Strobe Delay */
+#define                    NWIDTH  0x100      /* NAND Data Width */
+#define                   nNWIDTH  0x0       
+#define                   PG_SIZE  0x200      /* Page Size */
+#define                  nPG_SIZE  0x0       
+
+/* Bit masks for NFC_STAT */
+
+#define                     NBUSY  0x1        /* Not Busy */
+#define                    nNBUSY  0x0       
+#define                   WB_FULL  0x2        /* Write Buffer Full */
+#define                  nWB_FULL  0x0       
+#define                PG_WR_STAT  0x4        /* Page Write Pending */
+#define               nPG_WR_STAT  0x0       
+#define                PG_RD_STAT  0x8        /* Page Read Pending */
+#define               nPG_RD_STAT  0x0       
+#define                  WB_EMPTY  0x10       /* Write Buffer Empty */
+#define                 nWB_EMPTY  0x0       
+
+/* Bit masks for NFC_IRQSTAT */
+
+#define                  NBUSYIRQ  0x1        /* Not Busy IRQ */
+#define                 nNBUSYIRQ  0x0       
+#define                    WB_OVF  0x2        /* Write Buffer Overflow */
+#define                   nWB_OVF  0x0       
+#define                   WB_EDGE  0x4        /* Write Buffer Edge Detect */
+#define                  nWB_EDGE  0x0       
+#define                    RD_RDY  0x8        /* Read Data Ready */
+#define                   nRD_RDY  0x0       
+#define                   WR_DONE  0x10       /* Page Write Done */
+#define                  nWR_DONE  0x0       
+
+/* Bit masks for NFC_IRQMASK */
+
+#define              MASK_BUSYIRQ  0x1        /* Mask Not Busy IRQ */
+#define             nMASK_BUSYIRQ  0x0       
+#define                MASK_WBOVF  0x2        /* Mask Write Buffer Overflow */
+#define               nMASK_WBOVF  0x0       
+#define              MASK_WBEMPTY  0x4        /* Mask Write Buffer Empty */
+#define             nMASK_WBEMPTY  0x0       
+#define                MASK_RDRDY  0x8        /* Mask Read Data Ready */
+#define               nMASK_RDRDY  0x0       
+#define               MASK_WRDONE  0x10       /* Mask Write Done */
+#define              nMASK_WRDONE  0x0       
+
+/* Bit masks for NFC_RST */
+
+#define                   ECC_RST  0x1        /* ECC (and NFC counters) Reset */
+#define                  nECC_RST  0x0       
+
+/* Bit masks for NFC_PGCTL */
+
+#define               PG_RD_START  0x1        /* Page Read Start */
+#define              nPG_RD_START  0x0       
+#define               PG_WR_START  0x2        /* Page Write Start */
+#define              nPG_WR_START  0x0       
+
+/* Bit masks for NFC_ECC0 */
+
+#define                      ECC0  0x7ff      /* Parity Calculation Result0 */
+
+/* Bit masks for NFC_ECC1 */
+
+#define                      ECC1  0x7ff      /* Parity Calculation Result1 */
+
+/* Bit masks for NFC_ECC2 */
+
+#define                      ECC2  0x7ff      /* Parity Calculation Result2 */
+
+/* Bit masks for NFC_ECC3 */
+
+#define                      ECC3  0x7ff      /* Parity Calculation Result3 */
+
+/* Bit masks for NFC_COUNT */
+
+#define                    ECCCNT  0x3ff      /* Transfer Count */
+
+
+#endif /* _DEF_BF52X_H */
diff --git a/include/asm-blackfin/mach-bf533/anomaly.h b/include/asm-blackfin/mach-bf533/anomaly.h
index a84d390..7302f29 100644
--- a/include/asm-blackfin/mach-bf533/anomaly.h
+++ b/include/asm-blackfin/mach-bf533/anomaly.h
@@ -43,7 +43,8 @@
 #endif
 
 /* Issues that are common to 0.5, 0.4, and 0.3 silicon */
-#if  (defined(CONFIG_BF_REV_0_5) || defined(CONFIG_BF_REV_0_4) || defined(CONFIG_BF_REV_0_3))
+#if  (defined(CONFIG_BF_REV_0_5) || defined(CONFIG_BF_REV_0_4) \
+		|| defined(CONFIG_BF_REV_0_3))
 #define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in
                             slot1 and store of a P register in slot 2 is not
                             supported */
@@ -76,11 +77,16 @@
                             control */
 #define ANOMALY_05000283 /* A system MMR write is stalled indefinitely when
                             killed in a particular stage*/
+#define ANOMALY_05000311 /* Erroneous flag pin operations under specific
+			    sequences */
 #define ANOMALY_05000312 /* Errors when SSYNC, CSYNC, or loads to LT, LB and LC
 			    registers are interrupted */
-#define ANOMALY_05000311 /* Erroneous flag pin operations under specific sequences*/
-
-#endif
+#define ANOMALY_05000313 /* PPI Is Level-Sensitive on First Transfer  */
+#define ANOMALY_05000315 /* Killed System MMR Write Completes Erroneously On
+			  *  Next System MMR Access */
+#define ANOMALY_05000319 /* Internal Voltage Regulator Values of 1.05V, 1.10V
+			  *  and 1.15V Not Allowed for LQFP Packages */
+#endif /* Issues that are common to 0.5, 0.4, and 0.3 silicon */
 
 /* These issues only occur on 0.3 or 0.4 BF533 */
 #if (defined(CONFIG_BF_REV_0_4) || defined(CONFIG_BF_REV_0_3))
@@ -134,14 +140,14 @@
                             internal voltage regulator (VDDint) to increase. */
 #define ANOMALY_05000270 /* High I/O activity causes the output voltage of the
                             internal voltage regulator (VDDint) to decrease */
-#endif
+#endif /* issues only occur on 0.3 or 0.4 BF533 */
 
 /* These issues are only on 0.4 silicon */
 #if (defined(CONFIG_BF_REV_0_4))
 #define ANOMALY_05000234 /* Incorrect Revision Number in DSPID Register */
 #define ANOMALY_05000250 /* Incorrect Bit-Shift of Data Word in Multichannel
                             (TDM) */
-#endif
+#endif /* issues are only on 0.4 silicon */
 
 /* These issues are only on 0.3 silicon */
 #if defined(CONFIG_BF_REV_0_3)
@@ -170,6 +176,72 @@
 #define ANOMALY_05000233 /* PPI_FS3 is not driven in 2 or 3 internal Frame
                             Sync Transmit Mode */
 #define ANOMALY_05000271 /* Spontaneous reset of Internal Voltage Regulator */
+#endif /* only on 0.3 silicon */
+
+#if defined(CONFIG_BF_REV_0_2)
+#define ANOMALY_05000067 /* Watchpoints (Hardware Breakpoints) are not
+			  *  supported */
+#define ANOMALY_05000109 /* Reserved bits in SYSCFG register not set at
+			  *  power on */
+#define ANOMALY_05000116 /* Trace Buffers may record discontinuities into
+			  *  emulation mode and/or exception, NMI, reset
+			  *  handlers */
+#define ANOMALY_05000123 /* DTEST_COMMAND initiated memory access may be
+			  *  incorrect if data cache or DMA is active */
+#define ANOMALY_05000124 /* DMA Lock-up at CCLK to SCLK ratios of 4:1, 2:1,
+			  *  or 1:1 */
+#define ANOMALY_05000125 /* Erroneous exception when enabling cache */
+#define ANOMALY_05000126 /* SPI clock polarity and phase bits incorrect
+			  *  during booting */
+#define ANOMALY_05000137 /* DMEM_CONTROL is not set on Reset */
+#define ANOMALY_05000138 /* SPI boot will not complete if there is a zero fill
+			  * block in the loader file */
+#define ANOMALY_05000140 /* Allowing the SPORT RX FIFO to fill will cause an
+			  *  overflow */
+#define ANOMALY_05000141 /* An Infinite Stall occurs with a particular sequence
+			  *  of consecutive dual dag events */
+#define ANOMALY_05000142 /* Interrupts may be lost when a programmable input
+			  *  flag is configured to be edge sensitive */
+#define ANOMALY_05000143 /* A read from external memory may return a wrong
+			  *  value with data cache enabled */
+#define ANOMALY_05000144 /* DMA and TESTSET conflict when both are accessing
+			  *  external memory */
+#define ANOMALY_05000145 /* In PWM_OUT mode, you must enable the PPI block to
+			  *  generate a waveform from PPI_CLK */
+#define ANOMALY_05000146 /* MDMA may lose the first few words of a descriptor
+			  *  chain */
+#define ANOMALY_05000147 /* The source MDMA descriptor may stop with a DMA
+			  *  Error */
+#define ANOMALY_05000148 /* When booting from a 16-bit asynchronous memory
+			  *  device, the upper 8-bits of each word must be
+			  *  0x00 */
+#define ANOMALY_05000153 /* Frame Delay in SPORT Multichannel Mode */
+#define ANOMALY_05000154 /* SPORT TFS signal is active in Multi-channel mode
+			  *  outside of valid channels */
+#define ANOMALY_05000155 /* Timer1 can not be used for PWMOUT mode when a
+			  *  certain PPI mode is in use */
+#define ANOMALY_05000157 /* A killed 32-bit System MMR write will lead to
+			  *  the next system MMR access thinking it should be
+			  *  32-bit. */
+#define ANOMALY_05000163 /* SPORT transmit data is not gated by external frame
+			  *  sync in certain conditions */
+#define ANOMALY_05000168 /* SDRAM auto-refresh and subsequent Power Ups */
+#define ANOMALY_05000169 /* DATA CPLB page miss can result in lost
+			  *  write-through cache data writes */
+#define ANOMALY_05000173 /* DMA vs Core accesses to external memory */
+#define ANOMALY_05000174 /* Cache Fill Buffer Data lost */
+#define ANOMALY_05000175 /* Overlapping Sequencer and Memory Stalls */
+#define ANOMALY_05000176 /* Multiplication of (-1) by (-1) followed by an
+			  *  accumulator saturation */
+#define ANOMALY_05000181 /* Disabling the PPI resets the PPI configuration
+			  *  registers */
+#define ANOMALY_05000185 /* PPI TX Mode with 2 External Frame Syncs */
+#define ANOMALY_05000191 /* PPI does not invert the Driving PPICLK edge in
+			  *  Transmit Modes */
+#define ANOMALY_05000192 /* In PPI Transmit Modes with External Frame Syncs
+			  *  POLC */
+#define ANOMALY_05000206 /* Internal Voltage Regulator may not start up */
+
 #endif
 
 #endif /*  _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
index 23bf76a..e043caf 100644
--- a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
@@ -78,6 +78,7 @@
 };
 
 struct bfin_serial_res bfin_serial_resource[] = {
+	{
 	0xFFC00400,
 	IRQ_UART_RX,
 #ifdef CONFIG_SERIAL_BFIN_DMA
@@ -88,6 +89,7 @@
 	CONFIG_UART0_CTS_PIN,
 	CONFIG_UART0_RTS_PIN,
 #endif
+	}
 };
 
 
diff --git a/include/asm-blackfin/mach-bf533/cdefBF532.h b/include/asm-blackfin/mach-bf533/cdefBF532.h
index 1d7c494..74f967b 100644
--- a/include/asm-blackfin/mach-bf533/cdefBF532.h
+++ b/include/asm-blackfin/mach-bf533/cdefBF532.h
@@ -51,10 +51,6 @@
 #define bfin_read_PLL_LOCKCNT()              bfin_read16(PLL_LOCKCNT)
 #define bfin_write_PLL_LOCKCNT(val)          bfin_write16(PLL_LOCKCNT,val)
 #define bfin_read_CHIPID()                   bfin_read32(CHIPID)
-#define bfin_read_SWRST()                    bfin_read16(SWRST)
-#define bfin_write_SWRST(val)                bfin_write16(SWRST,val)
-#define bfin_read_SYSCR()                    bfin_read16(SYSCR)
-#define bfin_write_SYSCR(val)                bfin_write16(SYSCR,val)
 #define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
 #define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
@@ -63,12 +59,14 @@
 {
 	unsigned long flags, iwr;
 
-	bfin_write16(VR_CTL, val);
-	__builtin_bfin_ssync();
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr = bfin_read32(SIC_IWR);
 	/* Only allow PPL Wakeup) */
 	bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+	bfin_write16(VR_CTL, val);
+	__builtin_bfin_ssync();
+
 	local_irq_save(flags);
 	asm("IDLE;");
 	local_irq_restore(flags);
@@ -76,6 +74,10 @@
 }
 
 /* System Interrupt Controller (0xFFC0 0C00-0xFFC0 0FFF) */
+#define bfin_read_SWRST()                    bfin_read16(SWRST)
+#define bfin_write_SWRST(val)                bfin_write16(SWRST,val)
+#define bfin_read_SYSCR()                    bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val)                bfin_write16(SYSCR,val)
 #define bfin_read_SIC_IAR0()                 bfin_read32(SIC_IAR0)
 #define bfin_write_SIC_IAR0(val)             bfin_write32(SIC_IAR0,val)
 #define bfin_read_SIC_IAR1()                 bfin_read32(SIC_IAR1)
@@ -115,6 +117,18 @@
 #define bfin_read_RTC_PREN()                 bfin_read16(RTC_PREN)
 #define bfin_write_RTC_PREN(val)             bfin_write16(RTC_PREN,val)
 
+/* DMA Traffic controls */
+#define bfin_read_DMA_TCPER()                bfin_read16(DMA_TCPER)
+#define bfin_write_DMA_TCPER(val)            bfin_write16(DMA_TCPER,val)
+#define bfin_read_DMA_TCCNT()                bfin_read16(DMA_TCCNT)
+#define bfin_write_DMA_TCCNT(val)            bfin_write16(DMA_TCCNT,val)
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define bfin_read_DMA_TC_PER()               bfin_read16(DMA_TC_PER)
+#define bfin_write_DMA_TC_PER(val)           bfin_write16(DMA_TC_PER,val)
+#define bfin_read_DMA_TC_CNT()               bfin_read16(DMA_TC_CNT)
+#define bfin_write_DMA_TC_CNT(val)           bfin_write16(DMA_TC_CNT,val)
+
 /* General Purpose IO (0xFFC0 2400-0xFFC0 27FF) */
 #define bfin_read_FIO_DIR()                  bfin_read16(FIO_DIR)
 #define bfin_write_FIO_DIR(val)              bfin_write16(FIO_DIR,val)
@@ -151,16 +165,6 @@
 #define bfin_read_FIO_MASKB_T()              bfin_read16(FIO_MASKB_T)
 #define bfin_write_FIO_MASKB_T(val)          bfin_write16(FIO_MASKB_T,val)
 
-/* DMA Traffic controls */
-#define bfin_read_DMA_TCPER()                bfin_read16(DMA_TCPER)
-#define bfin_write_DMA_TCPER(val)            bfin_write16(DMA_TCPER,val)
-#define bfin_read_DMA_TCCNT()                bfin_read16(DMA_TCCNT)
-#define bfin_write_DMA_TCCNT(val)            bfin_write16(DMA_TCCNT,val)
-#define bfin_read_DMA_TC_PER()               bfin_read16(DMA_TC_PER)
-#define bfin_write_DMA_TC_PER(val)           bfin_write16(DMA_TC_PER,val)
-#define bfin_read_DMA_TC_CNT()               bfin_read16(DMA_TC_CNT)
-#define bfin_write_DMA_TC_CNT(val)           bfin_write16(DMA_TC_CNT,val)
-
 /* DMA Controller */
 #define bfin_read_DMA0_CONFIG()              bfin_read16(DMA0_CONFIG)
 #define bfin_write_DMA0_CONFIG(val)          bfin_write16(DMA0_CONFIG,val)
diff --git a/include/asm-blackfin/mach-bf533/defBF532.h b/include/asm-blackfin/mach-bf533/defBF532.h
index b240a08..6a3cf93 100644
--- a/include/asm-blackfin/mach-bf533/defBF532.h
+++ b/include/asm-blackfin/mach-bf533/defBF532.h
@@ -46,11 +46,7 @@
 
 #ifndef _DEF_BF532_H
 #define _DEF_BF532_H
-/*
-#if !defined(__ADSPLPBLACKFIN__)
-#warning defBF532.h should only be included for 532 compatible chips
-#endif
-*/
+
 /* include all Core registers and bit definitions */
 #include <asm/mach-common/def_LPBlackfin.h>
 
@@ -65,10 +61,10 @@
 #define PLL_STAT               0xFFC0000C	/* PLL Status register (16-bit) */
 #define PLL_LOCKCNT            0xFFC00010	/* PLL Lock Count register (16-bit) */
 #define CHIPID                 0xFFC00014       /* Chip ID Register */
-#define SWRST                  0xFFC00100	/* Software Reset Register (16-bit) */
-#define SYSCR                  0xFFC00104	/* System Configuration registe */
 
 /* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
+#define SWRST			0xFFC00100  /* Software Reset Register (16-bit) */
+#define SYSCR			0xFFC00104  /* System Configuration registe */
 #define SIC_RVECT             		0xFFC00108	/* Interrupt Reset Vector Address Register */
 #define SIC_IMASK             		0xFFC0010C	/* Interrupt Mask Register */
 #define SIC_IAR0               		0xFFC00110	/* Interrupt Assignment Register 0 */
@@ -218,11 +214,13 @@
 #define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register */
 
 /* DMA Traffic controls */
-#define DMA_TCPER 0xFFC00B0C	/* Traffic Control Periods Register */
-#define DMA_TCCNT 0xFFC00B10	/* Traffic Control Current Counts Register */
 #define DMA_TC_PER 0xFFC00B0C	/* Traffic Control Periods Register */
 #define DMA_TC_CNT 0xFFC00B10	/* Traffic Control Current Counts Register */
 
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define DMA_TCPER 0xFFC00B0C	/* Traffic Control Periods Register */
+#define DMA_TCCNT 0xFFC00B10	/* Traffic Control Current Counts Register */
+
 /* DMA Controller (0xFFC00C00 - 0xFFC00FFF) */
 #define DMA0_CONFIG		0xFFC00C08	/* DMA Channel 0 Configuration Register */
 #define DMA0_NEXT_DESC_PTR	0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register */
@@ -407,14 +405,25 @@
 /* ********************* PLL AND RESET MASKS ************************ */
 
 /* PLL_CTL Masks */
-#define PLL_CLKIN              0x00000000	/* Pass CLKIN to PLL */
-#define PLL_CLKIN_DIV2         0x00000001	/* Pass CLKIN/2 to PLL */
-#define PLL_OFF                0x00000002	/* Shut off PLL clocks */
-#define STOPCK_OFF             0x00000008	/* Core clock off */
-#define PDWN                   0x00000020	/* Put the PLL in a Deep Sleep state */
-#define BYPASS                 0x00000100	/* Bypass the PLL */
+#define PLL_CLKIN			0x0000  /* Pass CLKIN to PLL */
+#define PLL_CLKIN_DIV2			0x0001  /* Pass CLKIN/2 to PLL */
+#define DF				0x0001	/* 0: PLL = CLKIN, 1: PLL = CLKIN/2					*/
+#define PLL_OFF				0x0002  /* Shut off PLL clocks */
+#define STOPCK_OFF			0x0008  /* Core clock off */
+#define STOPCK				0x0008	/* Core Clock Off									*/
+#define PDWN				0x0020  /* Put the PLL in a Deep Sleep state */
+#if !defined(__ADSPBF538__)
+/* this file is included in defBF538.h but IN_DELAY/OUT_DELAY are different */
+# define IN_DELAY        0x0040  /* Add 200ps Delay To EBIU Input Latches */
+# define OUT_DELAY       0x0080  /* Add 200ps Delay To EBIU Output Signals */
+#endif
+#define BYPASS				0x0100  /* Bypass the PLL */
+/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits)			*/
+#define	SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL		*/
 
 /* PLL_DIV Masks */
+#define SSEL				0x000F	/* System Select						*/
+#define	CSEL				0x0030	/* Core Select							*/
 
 #define SCLK_DIV(x)  (x)	/* SCLK = VCO / x */
 
@@ -422,6 +431,8 @@
 #define CCLK_DIV2              0x00000010	/* CCLK = VCO / 2 */
 #define CCLK_DIV4              0x00000020	/* CCLK = VCO / 4 */
 #define CCLK_DIV8              0x00000030	/* CCLK = VCO / 8 */
+/* PLL_DIV Macros														*/
+#define SET_SSEL(x)			((x)&0xF)	/* Set SSEL = 0-15 --> SCLK = VCO/SSEL	*/
 
 /* PLL_STAT Masks																	*/
 #define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled    */
@@ -429,13 +440,47 @@
 #define ACTIVE_PLLDISABLED	0x0004	/* Processor In Active Mode With PLL Disabled   */
 #define	PLL_LOCKED			0x0020	/* PLL_LOCKCNT Has Been Reached                                 */
 
+/* VR_CTL Masks																	*/
+#define	FREQ			0x0003	/* Switching Oscillator Frequency For Regulator	*/
+#define	HIBERNATE		0x0000	/* 		Powerdown/Bypass On-Board Regulation	*/
+#define	FREQ_333		0x0001	/* 		Switching Frequency Is 333 kHz			*/
+#define	FREQ_667		0x0002	/* 		Switching Frequency Is 667 kHz			*/
+#define	FREQ_1000		0x0003	/* 		Switching Frequency Is 1 MHz			*/
+
+#define GAIN			0x000C	/* Voltage Level Gain	*/
+#define	GAIN_5			0x0000	/* 		GAIN = 5		*/
+#define	GAIN_10			0x0004	/* 		GAIN = 10		*/
+#define	GAIN_20			0x0008	/* 		GAIN = 20		*/
+#define	GAIN_50			0x000C	/* 		GAIN = 50		*/
+
+#define	VLEV			0x00F0	/* Internal Voltage Level					*/
+#define	VLEV_085 		0x0060	/* 		VLEV = 0.85 V (-5% - +10% Accuracy)	*/
+#define	VLEV_090		0x0070	/* 		VLEV = 0.90 V (-5% - +10% Accuracy)	*/
+#define	VLEV_095		0x0080	/* 		VLEV = 0.95 V (-5% - +10% Accuracy)	*/
+#define	VLEV_100		0x0090	/* 		VLEV = 1.00 V (-5% - +10% Accuracy)	*/
+#define	VLEV_105		0x00A0	/* 		VLEV = 1.05 V (-5% - +10% Accuracy)	*/
+#define	VLEV_110		0x00B0	/* 		VLEV = 1.10 V (-5% - +10% Accuracy)	*/
+#define	VLEV_115		0x00C0	/* 		VLEV = 1.15 V (-5% - +10% Accuracy)	*/
+#define	VLEV_120		0x00D0	/* 		VLEV = 1.20 V (-5% - +10% Accuracy)	*/
+
+#define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate	*/
+#define	SCKELOW			0x8000	/* Do Not Drive SCKE High During Reset After Hibernate */
+
 /* CHIPID Masks */
 #define CHIPID_VERSION         0xF0000000
 #define CHIPID_FAMILY          0x0FFFF000
 #define CHIPID_MANUFACTURE     0x00000FFE
 
 /* SWRST Mask */
-#define SYSTEM_RESET           0x00000007	/* Initiates a system software reset */
+#define SYSTEM_RESET	0x0007	/* Initiates A System Software Reset			*/
+#define	DOUBLE_FAULT	0x0008	/* Core Double Fault Causes Reset				*/
+#define RESET_DOUBLE	0x2000	/* SW Reset Generated By Core Double-Fault		*/
+#define RESET_WDOG	0x4000	/* SW Reset Generated By Watchdog Timer			*/
+#define RESET_SOFTWARE	0x8000	/* SW Reset Occurred Since Last Read Of SWRST	*/
+
+/* SYSCR Masks																				*/
+#define BMODE			0x0006	/* Boot Mode - Latched During HW Reset From Mode Pins	*/
+#define	NOBOOT			0x0010	/* Execute From L1 or ASYNC Bank 0 When BMODE = 0		*/
 
 /* *************  SYSTEM INTERRUPT CONTROLLER MASKS ***************** */
 
@@ -483,23 +528,6 @@
 #define IWR_ENABLE(x)	       (1 << (x))	/* Wakeup Enable Peripheral #x */
 #define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x)))	/* Wakeup Disable Peripheral #x */
 
-/* *********  WATCHDOG TIMER MASKS  ********************8 */
-
-/* Watchdog Timer WDOG_CTL Register */
-#define ICTL(x) ((x<<1) & 0x0006)
-#define ENABLE_RESET     0x00000000	/* Set Watchdog Timer to generate reset */
-#define ENABLE_NMI       0x00000002	/* Set Watchdog Timer to generate non-maskable interrupt */
-#define ENABLE_GPI       0x00000004	/* Set Watchdog Timer to generate general-purpose interrupt */
-#define DISABLE_EVT      0x00000006	/* Disable Watchdog Timer interrupts */
-
-#define TMR_EN		0x0000
-#define TMR_DIS		0x0AD0
-#define TRO		0x8000
-
-#define ICTL_P0		0x01
-#define ICTL_P1		0x02
-#define TRO_P		0x0F
-
 /* ***************************** UART CONTROLLER MASKS ********************** */
 
 /* UART_LCR Register */
@@ -583,6 +611,9 @@
 #define TSPEN    0x0001		/* TX enable  */
 #define ITCLK    0x0002		/* Internal TX Clock Select  */
 #define TDTYPE   0x000C		/* TX Data Formatting Select */
+#define DTYPE_NORM	0x0000		/* Data Format Normal							*/
+#define DTYPE_ULAW	0x0008		/* Compand Using u-Law							*/
+#define DTYPE_ALAW	0x000C		/* Compand Using A-Law							*/
 #define TLSBIT   0x0010		/* TX Bit Order */
 #define ITFS     0x0200		/* Internal TX Frame Sync Select  */
 #define TFSR     0x0400		/* TX Frame Sync Required Select  */
@@ -592,7 +623,12 @@
 #define TCKFE    0x4000		/* TX Clock Falling Edge Select  */
 
 /* SPORTx_TCR2 Masks */
-#define SLEN	    0x001F	/*TX Word Length  */
+#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || \
+    defined(__ADSPBF533__)
+# define SLEN	    0x001F	/*TX Word Length  */
+#else
+# define SLEN(x)		((x)&0x1F)	/* SPORT TX Word Length (2 - 31)				*/
+#endif
 #define TXSE        0x0100	/*TX Secondary Enable */
 #define TSFSE       0x0200	/*TX Stereo Frame Sync Enable */
 #define TRFST       0x0400	/*TX Right-First Data Order  */
@@ -601,8 +637,9 @@
 #define RSPEN    0x0001		/* RX enable  */
 #define IRCLK    0x0002		/* Internal RX Clock Select  */
 #define RDTYPE   0x000C		/* RX Data Formatting Select */
-#define RULAW    0x0008		/* u-Law enable  */
-#define RALAW    0x000C		/* A-Law enable  */
+#define DTYPE_NORM	0x0000		/* no companding							*/
+#define DTYPE_ULAW	0x0008		/* Compand Using u-Law							*/
+#define DTYPE_ALAW	0x000C		/* Compand Using A-Law							*/
 #define RLSBIT   0x0010		/* RX Bit Order */
 #define IRFS     0x0200		/* Internal RX Frame Sync Select  */
 #define RFSR     0x0400		/* RX Frame Sync Required Select  */
@@ -611,7 +648,7 @@
 #define RCKFE    0x4000		/* RX Clock Falling Edge Select  */
 
 /* SPORTx_RCR2 Masks */
-#define SLEN	    0x001F	/*RX Word Length  */
+/* SLEN defined above */
 #define RXSE        0x0100	/*RX Secondary Enable */
 #define RSFSE       0x0200	/*RX Stereo Frame Sync Enable */
 #define RRFST       0x0400	/*Right-First Data Order  */
@@ -628,14 +665,37 @@
 /*SPORTx_MCMC1 Masks */
 #define SP_WSIZE		0x0000F000	/*Multichannel Window Size Field */
 #define SP_WOFF		0x000003FF	/*Multichannel Window Offset Field */
+/* SPORTx_MCMC1 Macros															*/
+#define SET_SP_WOFF(x)	((x) & 0x3FF) 	/* Multichannel Window Offset Field			*/
+/* Only use SET_WSIZE Macro With Logic OR While Setting Lower Order Bits						*/
+#define SET_SP_WSIZE(x)	(((((x)>>0x3)-1)&0xF) << 0xC)	/* Multichannel Window Size = (x/8)-1	*/
 
 /*SPORTx_MCMC2 Masks */
-#define MCCRM		0x00000003	/*Multichannel Clock Recovery Mode */
-#define MCDTXPE		0x00000004	/*Multichannel DMA Transmit Packing */
-#define MCDRXPE		0x00000008	/*Multichannel DMA Receive Packing */
-#define MCMEN		0x00000010	/*Multichannel Frame Mode Enable */
-#define FSDR		0x00000080	/*Multichannel Frame Sync to Data Relationship */
-#define MFD		0x0000F000	/*Multichannel Frame Delay    */
+#define MCCRM		0x00000003 	/*Multichannel Clock Recovery Mode */
+#define REC_BYPASS	0x0000		/* Bypass Mode (No Clock Recovery)				*/
+#define REC_2FROM4	0x0002		/* Recover 2 MHz Clock from 4 MHz Clock			*/
+#define REC_8FROM16	0x0003		/* Recover 8 MHz Clock from 16 MHz Clock		*/
+#define MCDTXPE		0x00000004 	/*Multichannel DMA Transmit Packing */
+#define MCDRXPE		0x00000008 	/*Multichannel DMA Receive Packing */
+#define MCMEN		0x00000010 	/*Multichannel Frame Mode Enable */
+#define FSDR		0x00000080 	/*Multichannel Frame Sync to Data Relationship */
+#define MFD		0x0000F000 	/*Multichannel Frame Delay    */
+#define MFD_0		0x0000		/* Multichannel Frame Delay = 0					*/
+#define MFD_1		0x1000		/* Multichannel Frame Delay = 1					*/
+#define MFD_2		0x2000		/* Multichannel Frame Delay = 2					*/
+#define MFD_3		0x3000		/* Multichannel Frame Delay = 3					*/
+#define MFD_4		0x4000		/* Multichannel Frame Delay = 4					*/
+#define MFD_5		0x5000		/* Multichannel Frame Delay = 5					*/
+#define MFD_6		0x6000		/* Multichannel Frame Delay = 6					*/
+#define MFD_7		0x7000		/* Multichannel Frame Delay = 7					*/
+#define MFD_8		0x8000		/* Multichannel Frame Delay = 8					*/
+#define MFD_9		0x9000		/* Multichannel Frame Delay = 9					*/
+#define MFD_10		0xA000		/* Multichannel Frame Delay = 10				*/
+#define MFD_11		0xB000		/* Multichannel Frame Delay = 11				*/
+#define MFD_12		0xC000		/* Multichannel Frame Delay = 12				*/
+#define MFD_13		0xD000		/* Multichannel Frame Delay = 13				*/
+#define MFD_14		0xE000		/* Multichannel Frame Delay = 14				*/
+#define MFD_15		0xF000		/* Multichannel Frame Delay = 15				*/
 
 /*  *********  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS ****************   */
 
@@ -660,6 +720,8 @@
 #define DLEN_16			0x3800	/* Data Length = 16 Bits                        */
 #define DLEN(x)	(((x-9) & 0x07) << 11)	/* PPI Data Length (only works for x=10-->x=16) */
 #define POL                  0x0000C000	/* PPI Signal Polarities       */
+#define POLC		0x4000		/* PPI Clock Polarity				*/
+#define POLS		0x8000		/* PPI Frame Sync Polarity			*/
 
 /* PPI_STATUS Masks                                          */
 #define FLD	             0x00000400	/* Field Indicator   */
@@ -729,6 +791,15 @@
 #define PCAPRD	            0x00000800	/* DMA Read Operation Indicator */
 #define PMAP	            0x00007000	/* DMA Peripheral Map Field */
 
+#define PMAP_PPI		0x0000	/* PMAP PPI Port DMA */
+#define	PMAP_SPORT0RX		0x1000	/* PMAP SPORT0 Receive DMA */
+#define PMAP_SPORT0TX		0x2000	/* PMAP SPORT0 Transmit DMA */
+#define	PMAP_SPORT1RX		0x3000	/* PMAP SPORT1 Receive DMA */
+#define PMAP_SPORT1TX		0x4000	/* PMAP SPORT1 Transmit DMA */
+#define PMAP_SPI		0x5000	/* PMAP SPI DMA */
+#define PMAP_UARTRX		0x6000	/* PMAP UART Receive DMA */
+#define PMAP_UARTTX		0x7000	/* PMAP UART Transmit DMA */
+
 /*  *************  GENERAL PURPOSE TIMER MASKS  ******************** */
 
 /* PWM Timer bit definitions */
@@ -755,9 +826,9 @@
 #define TIMIL0		0x0001
 #define TIMIL1		0x0002
 #define TIMIL2		0x0004
-#define TOVL_ERR0	0x0010
-#define TOVL_ERR1	0x0020
-#define TOVL_ERR2	0x0040
+#define TOVF_ERR0		0x0010	/* Timer 0 Counter Overflow		*/
+#define TOVF_ERR1		0x0020	/* Timer 1 Counter Overflow		*/
+#define TOVF_ERR2		0x0040	/* Timer 2 Counter Overflow		*/
 #define TRUN0		0x1000
 #define TRUN1		0x2000
 #define TRUN2		0x4000
@@ -765,13 +836,21 @@
 #define TIMIL0_P	0x00
 #define TIMIL1_P	0x01
 #define TIMIL2_P	0x02
-#define TOVL_ERR0_P	0x04
-#define TOVL_ERR1_P	0x05
-#define TOVL_ERR2_P	0x06
+#define TOVF_ERR0_P		0x04
+#define TOVF_ERR1_P		0x05
+#define TOVF_ERR2_P		0x06
 #define TRUN0_P		0x0C
 #define TRUN1_P		0x0D
 #define TRUN2_P		0x0E
 
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define TOVL_ERR0 		TOVF_ERR0
+#define TOVL_ERR1 		TOVF_ERR1
+#define TOVL_ERR2 		TOVF_ERR2
+#define TOVL_ERR0_P		TOVF_ERR0_P
+#define TOVL_ERR1_P 		TOVF_ERR1_P
+#define TOVL_ERR2_P 		TOVF_ERR2_P
+
 /* TIMERx_CONFIG Registers */
 #define PWM_OUT		0x0001
 #define WDTH_CAP	0x0002
@@ -841,6 +920,10 @@
 
 /* SPI_CTL Masks */
 #define TIMOD                  0x00000003	/* Transfer initiation mode and interrupt generation */
+#define RDBR_CORE	0x0000		/* 		RDBR Read Initiates, IRQ When RDBR Full		*/
+#define	TDBR_CORE	0x0001		/* 		TDBR Write Initiates, IRQ When TDBR Empty	*/
+#define RDBR_DMA	0x0002		/* 		DMA Read, DMA Until FIFO Empty				*/
+#define TDBR_DMA	0x0003		/* 		DMA Write, DMA Until FIFO Full				*/
 #define SZ                     0x00000004	/* Send Zero (=0) or last (=1) word when TDBR empty. */
 #define GM                     0x00000008	/* When RDBR full, get more (=1) data or discard (=0) incoming Data */
 #define PSSE                   0x00000010	/* Enable (=1) Slave-Select input for Master. */
@@ -894,10 +977,20 @@
 #define RXS                    0x00000020	/* SPI_RDBR Data Buffer Status (0=Empty, 1=Full)  */
 #define TXCOL                  0x00000040	/* When set (=1), corrupt data may have been transmitted  */
 
+/* SPIx_FLG Masks																	*/
+#define FLG1E	0xFDFF		/* Activates SPI_FLOUT1 							*/
+#define FLG2E	0xFBFF		/* Activates SPI_FLOUT2								*/
+#define FLG3E	0xF7FF		/* Activates SPI_FLOUT3								*/
+#define FLG4E	0xEFFF		/* Activates SPI_FLOUT4								*/
+#define FLG5E	0xDFFF		/* Activates SPI_FLOUT5								*/
+#define FLG6E	0xBFFF		/* Activates SPI_FLOUT6								*/
+#define FLG7E	0x7FFF		/* Activates SPI_FLOUT7								*/
+
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  ************* */
 
 /* AMGCTL Masks */
 #define AMCKEN			0x00000001	/* Enable CLKOUT */
+#define	AMBEN_NONE		0x00000000	/* All Banks Disabled								*/
 #define AMBEN_B0		0x00000002	/* Enable Asynchronous Memory Bank 0 only */
 #define AMBEN_B0_B1		0x00000004	/* Enable Asynchronous Memory Banks 0 & 1 only */
 #define AMBEN_B0_B1_B2		0x00000006	/* Enable Asynchronous Memory Banks 0, 1, and 2 */
@@ -1097,6 +1190,9 @@
 #define CL_3			0x0000000C	/* SDRAM CAS latency = 3 cycles */
 #define PFE			0x00000010	/* Enable SDRAM prefetch */
 #define PFP			0x00000020	/* Prefetch has priority over AMC requests */
+#define PASR_ALL		0x00000000	/* All 4 SDRAM Banks Refreshed In Self-Refresh				*/
+#define PASR_B0_B1		0x00000010	/* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh		*/
+#define PASR_B0			0x00000020	/* Only SDRAM Bank 0 Is Refreshed In Self-Refresh			*/
 #define TRAS_1			0x00000040	/* SDRAM tRAS = 1 cycle */
 #define TRAS_2			0x00000080	/* SDRAM tRAS = 2 cycles */
 #define TRAS_3			0x000000C0	/* SDRAM tRAS = 3 cycles */
@@ -1158,18 +1254,5 @@
 #define SDEASE		      0x00000010	/* SDRAM EAB sticky error status - W1C */
 #define BGSTAT			0x00000020	/* Bus granted */
 
-/*VR_CTL Masks*/
-#define WAKE                    0x100
-#define VLEV_6                  0x60
-#define VLEV_7                  0x70
-#define VLEV_8                  0x80
-#define VLEV_9                  0x90
-#define VLEV_10                 0xA0
-#define VLEV_11                 0xB0
-#define VLEV_12                 0xC0
-#define VLEV_13                 0xD0
-#define VLEV_14                 0xE0
-#define VLEV_15                 0xF0
-#define FREQ_3                  0x03
 
 #endif				/* _DEF_BF532_H */
diff --git a/include/asm-blackfin/mach-bf533/dma.h b/include/asm-blackfin/mach-bf533/dma.h
index bd9d5e9..16c672c 100644
--- a/include/asm-blackfin/mach-bf533/dma.h
+++ b/include/asm-blackfin/mach-bf533/dma.h
@@ -51,4 +51,7 @@
 #define CH_MEM_STREAM1_DEST     10	 /* TX */
 #define CH_MEM_STREAM1_SRC      11	 /* RX */
 
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
 #endif
diff --git a/include/asm-blackfin/mach-bf533/portmux.h b/include/asm-blackfin/mach-bf533/portmux.h
new file mode 100644
index 0000000..b88d7a0
--- /dev/null
+++ b/include/asm-blackfin/mach-bf533/portmux.h
@@ -0,0 +1,65 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_PPI0_CLK	(P_DONTCARE)
+#define P_PPI0_FS1	(P_DONTCARE)
+#define P_PPI0_FS2	(P_DONTCARE)
+#define P_PPI0_FS3	(P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_PPI0_D15	(P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_PPI0_D14	(P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_PPI0_D13	(P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_PPI0_D12	(P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_PPI0_D11	(P_DEFINED | P_IDENT(GPIO_PF8))
+#define P_PPI0_D10	(P_DEFINED | P_IDENT(GPIO_PF9))
+#define P_PPI0_D9	(P_DEFINED | P_IDENT(GPIO_PF10))
+#define P_PPI0_D8	(P_DEFINED | P_IDENT(GPIO_PF11))
+#define P_PPI0_D0	(P_DONTCARE)
+#define P_PPI0_D1	(P_DONTCARE)
+#define P_PPI0_D2	(P_DONTCARE)
+#define P_PPI0_D3	(P_DONTCARE)
+#define P_PPI0_D4	(P_DEFINED | P_IDENT(GPIO_PF15))
+#define P_PPI0_D5	(P_DEFINED | P_IDENT(GPIO_PF14))
+#define P_PPI0_D6	(P_DEFINED | P_IDENT(GPIO_PF13))
+#define P_PPI0_D7	(P_DEFINED | P_IDENT(GPIO_PF12))
+
+#define P_SPORT1_TSCLK	(P_DONTCARE)
+#define P_SPORT1_RSCLK	(P_DONTCARE)
+#define P_SPORT0_TSCLK	(P_DONTCARE)
+#define P_SPORT0_RSCLK	(P_DONTCARE)
+#define P_UART0_RX	(P_DONTCARE)
+#define P_UART0_TX	(P_DONTCARE)
+#define P_SPORT1_DRSEC	(P_DONTCARE)
+#define P_SPORT1_RFS	(P_DONTCARE)
+#define P_SPORT1_DTPRI	(P_DONTCARE)
+#define P_SPORT1_DTSEC	(P_DONTCARE)
+#define P_SPORT1_TFS	(P_DONTCARE)
+#define P_SPORT1_DRPRI	(P_DONTCARE)
+#define P_SPORT0_DRSEC	(P_DONTCARE)
+#define P_SPORT0_RFS	(P_DONTCARE)
+#define P_SPORT0_DTPRI	(P_DONTCARE)
+#define P_SPORT0_DTSEC	(P_DONTCARE)
+#define P_SPORT0_TFS	(P_DONTCARE)
+#define P_SPORT0_DRPRI	(P_DONTCARE)
+
+#define P_SPI0_MOSI	(P_DONTCARE)
+#define P_SPI0_MIS0	(P_DONTCARE)
+#define P_SPI0_SCK	(P_DONTCARE)
+#define P_SPI0_SSEL7	(P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_SPI0_SSEL6	(P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_SPI0_SSEL5	(P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_SPI0_SSEL4	(P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_SPI0_SSEL3	(P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_SPI0_SSEL2	(P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_SPI0_SSEL1	(P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_SPI0_SS	(P_DEFINED | P_IDENT(GPIO_PF0))
+
+#define P_TMR2		(P_DONTCARE)
+#define P_TMR1		(P_DONTCARE)
+#define P_TMR0		(P_DONTCARE)
+#define P_TMRCLK	(P_DEFINED | P_IDENT(GPIO_PF1))
+
+
+
+
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf537/anomaly.h b/include/asm-blackfin/mach-bf537/anomaly.h
index 7f040f5..4453e61 100644
--- a/include/asm-blackfin/mach-bf537/anomaly.h
+++ b/include/asm-blackfin/mach-bf537/anomaly.h
@@ -73,8 +73,13 @@
                             control */
 #define ANOMALY_05000283 /* A system MMR write is stalled indefinitely when
                             killed in a particular stage*/
+#define ANOMALY_05000310 /* False hardware errors caused by fetches at the
+			  *  boundary of reserved memory */
 #define ANOMALY_05000312 /* Errors when SSYNC, CSYNC, or loads to LT, LB and LC
 			    registers are interrupted */
+#define ANOMALY_05000313 /* PPI is level sensitive on first transfer */
+#define ANOMALY_05000322 /* EMAC RMII mode at 10-Base-T speed: RX frames not
+			  *  received properly */
 #endif
 
 #if defined(CONFIG_BF_REV_0_2)
@@ -114,7 +119,21 @@
                             DMA system instability */
 #define ANOMALY_05000280 /* SPI Master boot mode does not work well with
                             Atmel Dataflash devices */
-
+#define ANOMALY_05000281 /* False Hardware Error Exception when ISR context
+			  *  is not restored */
+#define ANOMALY_05000282 /* Memory DMA corruption with 32-bit data and traffic
+			  *  control */
+#define ANOMALY_05000283 /* System MMR Write Is Stalled Indefinitely When
+			  *  Killed in a Particular Stage */
+#define ANOMALY_05000285 /* New Feature: EMAC TX DMA Word Alignment
+			  *  (Not Available On Older Silicon) */
+#define ANOMALY_05000288 /* SPORTs may receive bad data if FIFOs fill up */
+#define ANOMALY_05000315 /* Killed System MMR Write Completes Erroneously
+			  *  On Next System MMR Access */
+#define ANOMALY_05000316 /* EMAC RMII mode: collisions occur in Full Duplex
+			  *  mode */
+#define ANOMALY_05000321 /* EMAC RMII mode: TX frames in half duplex fail with
+			  *  status No Carrier */
 #endif  /* CONFIG_BF_REV_0_2 */
 
 #endif /* _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf537/cdefBF534.h b/include/asm-blackfin/mach-bf537/cdefBF534.h
index 7b658c1..84e58fa 100644
--- a/include/asm-blackfin/mach-bf537/cdefBF534.h
+++ b/include/asm-blackfin/mach-bf537/cdefBF534.h
@@ -51,12 +51,14 @@
 {
 	unsigned long flags, iwr;
 
-	bfin_write16(VR_CTL, val);
-	__builtin_bfin_ssync();
 	/* Enable the PLL Wakeup bit in SIC IWR */
 	iwr = bfin_read32(SIC_IWR);
 	/* Only allow PPL Wakeup) */
 	bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+	bfin_write16(VR_CTL, val);
+	__builtin_bfin_ssync();
+
 	local_irq_save(flags);
 	asm("IDLE;");
 	local_irq_restore(flags);
@@ -73,7 +75,6 @@
 #define bfin_write_SWRST(val)                bfin_write16(SWRST,val)
 #define bfin_read_SYSCR()                    bfin_read16(SYSCR)
 #define bfin_write_SYSCR(val)                bfin_write16(SYSCR,val)
-#define	pSIC_RVECT			((void * volatile *)SIC_RVECT)
 #define bfin_read_SIC_RVECT()                bfin_read32(SIC_RVECT)
 #define bfin_write_SIC_RVECT(val)            bfin_write32(SIC_RVECT,val)
 #define bfin_read_SIC_IMASK()                bfin_read32(SIC_IMASK)
@@ -398,10 +399,14 @@
 #define bfin_write_EBIU_SDSTAT(val)          bfin_write16(EBIU_SDSTAT,val)
 
 /* DMA Traffic Control Registers													*/
-#define	pDMA_TCPER			((volatile unsigned short *)DMA_TCPER)
+#define bfin_read_DMA_TC_PER()                bfin_read16(DMA_TC_PER)
+#define bfin_write_DMA_TC_PER(val)            bfin_write16(DMA_TC_PER,val)
+#define bfin_read_DMA_TC_CNT()                bfin_read16(DMA_TC_CNT)
+#define bfin_write_DMA_TC_CNT(val)            bfin_write16(DMA_TC_CNT,val)
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
 #define bfin_read_DMA_TCPER()                bfin_read16(DMA_TCPER)
 #define bfin_write_DMA_TCPER(val)            bfin_write16(DMA_TCPER,val)
-#define	pDMA_TCCNT			((volatile unsigned short *)DMA_TCCNT)
 #define bfin_read_DMA_TCCNT()                bfin_read16(DMA_TCCNT)
 #define bfin_write_DMA_TCCNT(val)            bfin_write16(DMA_TCCNT,val)
 
@@ -1076,8 +1081,6 @@
 #define bfin_write_CAN_UCRC(val)             bfin_write16(CAN_UCRC,val)
 #define bfin_read_CAN_UCCNF()                bfin_read16(CAN_UCCNF)
 #define bfin_write_CAN_UCCNF(val)            bfin_write16(CAN_UCCNF,val)
-#define bfin_read_CAN_SFCMVER2()             bfin_read16(CAN_SFCMVER2)
-#define bfin_write_CAN_SFCMVER2(val)         bfin_write16(CAN_SFCMVER2,val)
 
 /* Mailbox Acceptance Masks */
 #define bfin_read_CAN_AM00L()                bfin_read16(CAN_AM00L)
diff --git a/include/asm-blackfin/mach-bf537/cdefBF537.h b/include/asm-blackfin/mach-bf537/cdefBF537.h
index 932a1b6..b8fc949 100644
--- a/include/asm-blackfin/mach-bf537/cdefBF537.h
+++ b/include/asm-blackfin/mach-bf537/cdefBF537.h
@@ -40,7 +40,6 @@
 
 /* Include Macro "Defines" For EMAC (Unique to BF536/BF537		*/
 /* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) 						*/
-#define	pEMAC_OPMODE		((volatile unsigned long  *)EMAC_OPMODE)
 #define bfin_read_EMAC_OPMODE()              bfin_read32(EMAC_OPMODE)
 #define bfin_write_EMAC_OPMODE(val)          bfin_write32(EMAC_OPMODE,val)
 #define bfin_read_EMAC_ADDRLO()              bfin_read32(EMAC_ADDRLO)
@@ -80,7 +79,6 @@
 #define bfin_read_EMAC_WKUP_FFCRC1()         bfin_read32(EMAC_WKUP_FFCRC1)
 #define bfin_write_EMAC_WKUP_FFCRC1(val)     bfin_write32(EMAC_WKUP_FFCRC1,val)
 
-#define	pEMAC_SYSCTL		((volatile unsigned long  *)EMAC_SYSCTL)
 #define bfin_read_EMAC_SYSCTL()              bfin_read32(EMAC_SYSCTL)
 #define bfin_write_EMAC_SYSCTL(val)          bfin_write32(EMAC_SYSCTL,val)
 #define bfin_read_EMAC_SYSTAT()              bfin_read32(EMAC_SYSTAT)
@@ -147,7 +145,6 @@
 #define bfin_write_EMAC_RXC_SHORT(val)       bfin_write32(EMAC_RXC_SHORT,val)
 #define bfin_read_EMAC_RXC_EQ64()            bfin_read32(EMAC_RXC_EQ64)
 #define bfin_write_EMAC_RXC_EQ64(val)        bfin_write32(EMAC_RXC_EQ64,val)
-#define	pEMAC_RXC_LT128		((volatile unsigned long  *)EMAC_RXC_LT128)
 #define bfin_read_EMAC_RXC_LT128()           bfin_read32(EMAC_RXC_LT128)
 #define bfin_write_EMAC_RXC_LT128(val)       bfin_write32(EMAC_RXC_LT128,val)
 #define bfin_read_EMAC_RXC_LT256()           bfin_read32(EMAC_RXC_LT256)
diff --git a/include/asm-blackfin/mach-bf537/defBF534.h b/include/asm-blackfin/mach-bf537/defBF534.h
index e605e970..1859f2f 100644
--- a/include/asm-blackfin/mach-bf537/defBF534.h
+++ b/include/asm-blackfin/mach-bf537/defBF534.h
@@ -216,8 +216,12 @@
 #define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register                                                */
 
 /* DMA Traffic Control Registers													*/
-#define DMA_TCPER			0xFFC00B0C	/* Traffic Control Periods Register                     */
-#define DMA_TCCNT			0xFFC00B10	/* Traffic Control Current Counts Register      */
+#define DMA_TC_PER			0xFFC00B0C	/* Traffic Control Periods Register			*/
+#define DMA_TC_CNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define DMA_TCPER			0xFFC00B0C	/* Traffic Control Periods Register			*/
+#define DMA_TCCNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
 
 /* DMA Controller (0xFFC00C00 - 0xFFC00FFF)															*/
 #define DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register               */
@@ -563,7 +567,7 @@
 #define CAN_GIF				0xFFC02A9C	/* Global Interrupt Flag Register                               */
 #define CAN_CONTROL			0xFFC02AA0	/* Master Control Register                                              */
 #define CAN_INTR			0xFFC02AA4	/* Interrupt Pending Register                                   */
-#define CAN_SFCMVER			0xFFC02AA8	/* Version Code Register                                                */
+
 #define CAN_MBTD			0xFFC02AAC	/* Mailbox Temporary Disable Feature                    */
 #define CAN_EWR				0xFFC02AB0	/* Programmable Warning Level                                   */
 #define CAN_ESR				0xFFC02AB4	/* Error Status Register                                                */
@@ -1026,10 +1030,11 @@
 #define	VLEV_130		0x00F0	/*              VLEV = 1.30 V (-5% - +10% Accuracy)     */
 
 #define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate       */
-#define PHYWE			0x0200	/* Enable PHY Wakeup From Hibernate                     */
-#define	CANWE			0x0400	/* Enable CAN Wakeup From Hibernate                     */
-#define	PHYCLKOE		0x4000	/* PHY Clock Output Enable                                      */
-#define	CKELOW			0x8000	/* Enable Drive CKE Low During Reset            */
+#define	CANWE			0x0200	/* Enable CAN Wakeup From Hibernate			*/
+#define	PHYWE			0x0400	/* Enable PHY Wakeup From Hibernate			*/
+#define	CLKBUFOE		0x4000	/* CLKIN Buffer Output Enable */
+#define	PHYCLKOE		CLKBUFOE	/* Alternative legacy name for the above */
+#define	SCKELOW		0x8000	/* Enable Drive CKE Low During Reset		*/
 
 /* PLL_STAT Masks																	*/
 #define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled    */
@@ -1050,7 +1055,7 @@
 #define RESET_SOFTWARE		0x8000	/* SW Reset Occurred Since Last Read Of SWRST   */
 
 /* SYSCR Masks																				*/
-#define BMODE				0x0006	/* Boot Mode - Latched During HW Reset From Mode Pins   */
+#define BMODE				0x0007	/* Boot Mode - Latched During HW Reset From Mode Pins   */
 #define	NOBOOT				0x0010	/* Execute From L1 or ASYNC Bank 0 When BMODE = 0               */
 
 /* *************  SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
@@ -1107,19 +1112,9 @@
 #define IWR_ENABLE(x)	(1 << ((x)&0x1F))	/* Wakeup Enable Peripheral #x          */
 #define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Wakeup Disable Peripheral #x         */
 
-/* ***************  WATCHDOG TIMER MASKS  *******************************************/
-/* WDOG_CTL Masks																	*/
-#define WDOG_RESET		0x0000	/* Generate Reset Event                                                 */
-#define WDOG_NMI		0x0002	/* Generate Non-Maskable Interrupt (NMI) Event  */
-#define WDOG_GPI		0x0004	/* Generate General Purpose (GP) Interrupt              */
-#define WDOG_NONE		0x0006	/* Disable Watchdog Timer Interrupts                    */
-#define TMR_EN			0x0FF0	/* Watchdog Counter Enable                                              */
-#define	TMR_DIS			0x0AD0	/* Watchdog Counter Disable                                             */
-#define TRO			0x8000	/* Watchdog Expired                                                     */
-
 /* ************** UART CONTROLLER MASKS *************************/
 /* UARTx_LCR Masks												*/
-#define WLS(x)		((((x)&0x3)-5) & 0x03)	/* Word Length Select   */
+#define WLS(x)		(((x)-5) & 0x03)	/* Word Length Select   */
 #define STB			0x04	/* Stop Bits                    */
 #define PEN			0x08	/* Parity Enable                */
 #define EPS			0x10	/* Even Parity Select   */
@@ -1128,8 +1123,8 @@
 #define DLAB		0x80	/* Divisor Latch Access */
 
 /* UARTx_MCR Mask										*/
-#define LOOP		0x10	/* Loopback Mode Enable         */
-
+#define LOOP_ENA		0x10	/* Loopback Mode Enable         */
+#define LOOP_ENA_P	0x04
 /* UARTx_LSR Masks										*/
 #define DR			0x01	/* Data Ready                           */
 #define OE			0x02	/* Overrun Error                        */
@@ -1229,10 +1224,10 @@
 #define TIMIL1			0x00000002	/* Timer 1 Interrupt                            */
 #define TIMIL2			0x00000004	/* Timer 2 Interrupt                            */
 #define TIMIL3			0x00000008	/* Timer 3 Interrupt                            */
-#define TOVL_ERR0		0x00000010	/* Timer 0 Counter Overflow                     */
-#define TOVL_ERR1		0x00000020	/* Timer 1 Counter Overflow                     */
-#define TOVL_ERR2		0x00000040	/* Timer 2 Counter Overflow                     */
-#define TOVL_ERR3		0x00000080	/* Timer 3 Counter Overflow                     */
+#define TOVF_ERR0		0x00000010	/* Timer 0 Counter Overflow			*/
+#define TOVF_ERR1		0x00000020	/* Timer 1 Counter Overflow			*/
+#define TOVF_ERR2		0x00000040	/* Timer 2 Counter Overflow			*/
+#define TOVF_ERR3		0x00000080	/* Timer 3 Counter Overflow			*/
 #define TRUN0			0x00001000	/* Timer 0 Slave Enable Status          */
 #define TRUN1			0x00002000	/* Timer 1 Slave Enable Status          */
 #define TRUN2			0x00004000	/* Timer 2 Slave Enable Status          */
@@ -1241,15 +1236,24 @@
 #define TIMIL5			0x00020000	/* Timer 5 Interrupt                            */
 #define TIMIL6			0x00040000	/* Timer 6 Interrupt                            */
 #define TIMIL7			0x00080000	/* Timer 7 Interrupt                            */
-#define TOVL_ERR4		0x00100000	/* Timer 4 Counter Overflow                     */
-#define TOVL_ERR5		0x00200000	/* Timer 5 Counter Overflow                     */
-#define TOVL_ERR6		0x00400000	/* Timer 6 Counter Overflow                     */
-#define TOVL_ERR7		0x00800000	/* Timer 7 Counter Overflow                     */
+#define TOVF_ERR4		0x00100000	/* Timer 4 Counter Overflow			*/
+#define TOVF_ERR5		0x00200000	/* Timer 5 Counter Overflow			*/
+#define TOVF_ERR6		0x00400000	/* Timer 6 Counter Overflow			*/
+#define TOVF_ERR7		0x00800000	/* Timer 7 Counter Overflow			*/
 #define TRUN4			0x10000000	/* Timer 4 Slave Enable Status          */
 #define TRUN5			0x20000000	/* Timer 5 Slave Enable Status          */
 #define TRUN6			0x40000000	/* Timer 6 Slave Enable Status          */
 #define TRUN7			0x80000000	/* Timer 7 Slave Enable Status          */
 
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define TOVL_ERR0 TOVF_ERR0
+#define TOVL_ERR1 TOVF_ERR1
+#define TOVL_ERR2 TOVF_ERR2
+#define TOVL_ERR3 TOVF_ERR3
+#define TOVL_ERR4 TOVF_ERR4
+#define TOVL_ERR5 TOVF_ERR5
+#define TOVL_ERR6 TOVF_ERR6
+#define TOVL_ERR7 TOVF_ERR7
 /* TIMERx_CONFIG Masks													*/
 #define PWM_OUT			0x0001	/* Pulse-Width Modulation Output Mode   */
 #define WDTH_CAP		0x0002	/* Width Capture Input Mode                             */
@@ -1647,6 +1651,8 @@
 #define EBSZ_32			0x0002	/* SDRAM External Bank Size = 32MB                                              */
 #define EBSZ_64			0x0004	/* SDRAM External Bank Size = 64MB                                              */
 #define EBSZ_128		0x0006	/* SDRAM External Bank Size = 128MB                                             */
+#define EBSZ_256		0x0008		/* SDRAM External Bank Size = 256MB 	*/
+#define EBSZ_512		0x000A		/* SDRAM External Bank Size = 512MB		*/
 #define EBCAW_8			0x0000	/* SDRAM External Bank Column Address Width = 8 Bits    */
 #define EBCAW_9			0x0010	/* SDRAM External Bank Column Address Width = 9 Bits    */
 #define EBCAW_10		0x0020	/* SDRAM External Bank Column Address Width = 10 Bits   */
@@ -1859,8 +1865,10 @@
 #define	TXECNT		0xFF00	/* Transmit Error Counter       */
 
 /* CAN_INTR Masks											*/
-#define	MBRIF		0x0001	/* Mailbox Receive Interrupt    */
-#define	MBTIF		0x0002	/* Mailbox Transmit Interrupt   */
+#define	MBRIRQ	0x0001	/* Mailbox Receive Interrupt	*/
+#define	MBRIF		MBRIRQ	/* legacy */
+#define	MBTIRQ	0x0002	/* Mailbox Transmit Interrupt	*/
+#define	MBTIF		MBTIRQ	/* legacy */
 #define	GIRQ		0x0004	/* Global Interrupt                             */
 #define	SMACK		0x0008	/* Sleep Mode Acknowledge               */
 #define	CANTX		0x0040	/* CAN TX Bus Value                             */
@@ -2445,8 +2453,8 @@
 #define	PJCE_SPI		0x0004	/*              Enable SPI_SSEL7                        */
 
 #define	PFDE			0x0008	/* Port F DMA Request Enable            */
-#define	PGDE_UART		0x0000	/*              Enable UART0 RX/TX                      */
-#define	PGDE_DMA		0x0008	/*              Enable DMAR1:0                          */
+#define	PFDE_UART		0x0000	/*              Enable UART0 RX/TX                      */
+#define	PFDE_DMA		0x0008	/*              Enable DMAR1:0                          */
 
 #define	PFTE			0x0010	/* Port F Timer Enable                          */
 #define	PFTE_UART		0x0000	/*              Enable UART1 RX/TX                      */
@@ -2498,4 +2506,20 @@
 #define	OI			0x4000	/* Overflow Interrupt Generated                         */
 #define	BDI			0x8000	/* Block Done Interrupt Generated                       */
 
+/* entry addresses of the user-callable Boot ROM functions */
+
+#define _BOOTROM_RESET 0xEF000000 
+#define _BOOTROM_FINAL_INIT 0xEF000002 
+#define _BOOTROM_DO_MEMORY_DMA 0xEF000006
+#define _BOOTROM_BOOT_DXE_FLASH 0xEF000008 
+#define _BOOTROM_BOOT_DXE_SPI 0xEF00000A 
+#define _BOOTROM_BOOT_DXE_TWI 0xEF00000C 
+#define _BOOTROM_GET_DXE_ADDRESS_FLASH 0xEF000010
+#define _BOOTROM_GET_DXE_ADDRESS_SPI 0xEF000012
+#define _BOOTROM_GET_DXE_ADDRESS_TWI 0xEF000014
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define	PGDE_UART   PFDE_UART
+#define	PGDE_DMA    PFDE_DMA
+#define	CKELOW		SCKELOW
 #endif				/* _DEF_BF534_H */
diff --git a/include/asm-blackfin/mach-bf537/defBF537.h b/include/asm-blackfin/mach-bf537/defBF537.h
index 26f9c02..3f45590 100644
--- a/include/asm-blackfin/mach-bf537/defBF537.h
+++ b/include/asm-blackfin/mach-bf537/defBF537.h
@@ -32,12 +32,12 @@
 #ifndef _DEF_BF537_H
 #define _DEF_BF537_H
 
-/*include all Core registers and bit definitions*/
-#include "defBF537.h"
-
-/*include core specific register pointer definitions*/
+/* Include all Core registers and bit definitions*/
 #include <asm/mach-common/cdef_LPBlackfin.h>
 
+/* Include all MMR and bit defines common to BF534 */
+#include "defBF534.h"
+
 /************************************************************************************
 ** Define EMAC Section Unique to BF536/BF537
 *************************************************************************************/
diff --git a/include/asm-blackfin/mach-bf537/dma.h b/include/asm-blackfin/mach-bf537/dma.h
index 7a96404..0219919 100644
--- a/include/asm-blackfin/mach-bf537/dma.h
+++ b/include/asm-blackfin/mach-bf537/dma.h
@@ -52,4 +52,7 @@
 #define CH_MEM_STREAM1_DEST	14	 /* TX */
 #define CH_MEM_STREAM1_SRC 	15	 /* RX */
 
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
 #endif
diff --git a/include/asm-blackfin/mach-bf537/portmux.h b/include/asm-blackfin/mach-bf537/portmux.h
new file mode 100644
index 0000000..23e13c5
--- /dev/null
+++ b/include/asm-blackfin/mach-bf537/portmux.h
@@ -0,0 +1,109 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_UART0_TX	(P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0))
+#define P_UART0_RX	(P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0))
+#define P_UART1_TX	(P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0))
+#define P_UART1_RX	(P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0))
+#define P_TMR5		(P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0))
+#define P_TMR4		(P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0))
+#define P_TMR3		(P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0))
+#define P_TMR2		(P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0))
+#define P_TMR1		(P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_TMR0		(P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_SPI0_SSEL1	(P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0))
+#define P_SPI0_MOSI	(P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0))
+#define P_SPI0_MISO	(P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0))
+#define P_SPI0_SCK	(P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
+#define P_SPI0_SS	(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
+#define P_PPI0_CLK	(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
+#define P_DMAR0		(P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_DMAR1		(P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_TMR7		(P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_TMR6		(P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_SPI0_SSEL6	(P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_SPI0_SSEL5	(P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_SPI0_SSEL4	(P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_PPI0_FS3	(P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#define P_PPI0_FS2	(P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_PPI0_FS1	(P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_TACLK0	(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_TMRCLK	(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#define P_PPI0_D0	(P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
+#define P_PPI0_D1	(P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_PPI0_D2	(P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0))
+#define P_PPI0_D3	(P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
+#define P_PPI0_D4	(P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
+#define P_PPI0_D5	(P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_PPI0_D6	(P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+#define P_PPI0_D7	(P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_PPI0_D8	(P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_PPI0_D9	(P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_PPI0_D10	(P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+#define P_PPI0_D11	(P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0))
+#define P_PPI0_D12	(P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_PPI0_D13	(P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+#define P_PPI0_D14	(P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+#define P_PPI0_D15	(P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#define P_SPORT1_DRSEC	(P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(1))
+#define P_SPORT1_DTSEC	(P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(1))
+#define P_SPORT1_RSCLK	(P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(1))
+#define P_SPORT1_RFS	(P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_SPORT1_DRPRI	(P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1))
+#define P_SPORT1_TSCLK	(P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1))
+#define P_SPORT1_TFS	(P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1))
+#define P_SPORT1_DTPRI	(P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
+
+#define P_MII0_ETxD0	(P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0))
+#define P_MII0_ETxD1	(P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0))
+#define P_MII0_ETxD2	(P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0))
+#define P_MII0_ETxD3	(P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0))
+#define P_MII0_ETxEN	(P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0))
+#define P_MII0_TxCLK	(P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0))
+#define P_MII0_PHYINT	(P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0))
+#define P_MII0_COL	(P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0))
+#define P_MII0_ERxD0	(P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(0))
+#define P_MII0_ERxD1	(P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(0))
+#define P_MII0_ERxD2	(P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(0))
+#define P_MII0_ERxD3	(P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(0))
+#define P_MII0_ERxDV	(P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(0))
+#define P_MII0_ERxCLK	(P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(0))
+#define P_MII0_ERxER	(P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(0))
+#define P_MII0_CRS	(P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(0))
+#define P_RMII0_REF_CLK	(P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(1))
+#define P_RMII0_MDINT	(P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1))
+#define P_RMII0_CRS_DV	(P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(1))
+
+#define PORT_PJ0	(GPIO_PH15 + 1)
+#define PORT_PJ1	(GPIO_PH15 + 2)
+#define PORT_PJ2	(GPIO_PH15 + 3)
+#define PORT_PJ3	(GPIO_PH15 + 4)
+#define PORT_PJ4	(GPIO_PH15 + 5)
+#define PORT_PJ5	(GPIO_PH15 + 6)
+#define PORT_PJ6	(GPIO_PH15 + 7)
+#define PORT_PJ7	(GPIO_PH15 + 8)
+#define PORT_PJ8	(GPIO_PH15 + 9)
+#define PORT_PJ9	(GPIO_PH15 + 10)
+#define PORT_PJ10	(GPIO_PH15 + 11)
+#define PORT_PJ11	(GPIO_PH15 + 12)
+
+#define P_MDC		(P_DEFINED | P_IDENT(PORT_PJ0) | P_FUNCT(0))
+#define P_MDIO		(P_DEFINED | P_IDENT(PORT_PJ1) | P_FUNCT(0))
+#define P_TWI0_SCL	(P_DEFINED | P_IDENT(PORT_PJ2) | P_FUNCT(0))
+#define P_TWI0_SDA	(P_DEFINED | P_IDENT(PORT_PJ3) | P_FUNCT(0))
+#define P_SPORT0_DRSEC	(P_DEFINED | P_IDENT(PORT_PJ4) | P_FUNCT(0))
+#define P_SPORT0_DTSEC	(P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(0))
+#define P_SPORT0_RSCLK	(P_DEFINED | P_IDENT(PORT_PJ6) | P_FUNCT(0))
+#define P_SPORT0_RFS	(P_DEFINED | P_IDENT(PORT_PJ7) | P_FUNCT(0))
+#define P_SPORT0_DRPRI	(P_DEFINED | P_IDENT(PORT_PJ8) | P_FUNCT(0))
+#define P_SPORT0_TSCLK	(P_DEFINED | P_IDENT(PORT_PJ9) | P_FUNCT(0))
+#define P_SPORT0_TFS	(P_DEFINED | P_IDENT(PORT_PJ10) | P_FUNCT(0))
+#define P_SPORT0_DTPRI	(P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1))
+#define P_CAN0_RX	(P_DEFINED | P_IDENT(PORT_PJ4) | P_FUNCT(1))
+#define P_CAN0_TX	(P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(1))
+#define P_SPI0_SSEL3	(P_DEFINED | P_IDENT(PORT_PJ10) | P_FUNCT(1))
+#define P_SPI0_SSEL2	(P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1))
+#define P_SPI0_SSEL7	(P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(2))
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf548/anomaly.h b/include/asm-blackfin/mach-bf548/anomaly.h
new file mode 100644
index 0000000..aca1d4b
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/anomaly.h
@@ -0,0 +1,74 @@
+
+/*
+ * File:         include/asm-blackfin/mach-bf548/anomaly.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+#define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in
+			    slot1 and store of a P register in slot 2 is not
+			    supported */
+#define ANOMALY_05000119 /* DMA_RUN bit is not valid after a Peripheral Receive
+			    Channel DMA stops */
+#define ANOMALY_05000122 /* Rx.H can not be used to access 16-bit System MMR
+			    registers. */
+#define ANOMALY_05000245 /* Spurious Hardware Error from an Access in the
+			    Shadow of a Conditional Branch */
+#define ANOMALY_05000255 /* Entering Hibernate Mode with RTC Seconds event
+			    interrupt not functional */
+#define ANOMALY_05000265 /* Sensitivity to noise with slow input edge rates on
+			    SPORT external receive and transmit clocks. */
+#define ANOMALY_05000272 /* Certain data cache write through modes fail for
+			    VDDint <=0.9V */
+#define ANOMALY_05000281 /* False Hardware Error Exception when ISR context is
+			    not restored */
+#define ANOMALY_05000310 /* False Hardware Errors Caused by Fetches at the
+			    Boundary of Reserved Memory */
+#define ANOMALY_05000312 /* Errors When SSYNC, CSYNC, or Loads to LT, LB and
+			    LC Registers Are Interrupted */
+#define ANOMALY_05000324 /* TWI Slave Boot Mode Is Not Functional */
+#define ANOMALY_05000325 /* External FIFO Boot Mode Is Not Functional */
+#define ANOMALY_05000327 /* Data Lost When Core and DMA Accesses Are Made to
+			    the USB FIFO Simultaneously */
+#define ANOMALY_05000328 /* Incorrect Access of OTP_STATUS During otp_write()
+			    function */
+#define ANOMALY_05000329 /* Synchronous Burst Flash Boot Mode Is Not Functional
+			    */
+#define ANOMALY_05000330 /* Host DMA Boot Mode Is Not Functional */
+#define ANOMALY_05000334 /* Inadequate Timing Margins on DDR DQS to DQ and DQM
+			    Skew */
+#define ANOMALY_05000335 /* Inadequate Rotary Debounce Logic Duration */
+#define ANOMALY_05000336 /* Phantom Interrupt Occurs After First Configuration
+			    of Host DMA Port */
+#define ANOMALY_05000337 /* Disallowed Configuration Prevents Subsequent
+			    Allowed Configuration on Host DMA Port */
+#define ANOMALY_05000338 /* Slave-Mode SPI0 MISO Failure With CPHA = 0 */
+
+#endif /* _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf548/bf548.h b/include/asm-blackfin/mach-bf548/bf548.h
new file mode 100644
index 0000000..9498313
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/bf548.h
@@ -0,0 +1,271 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/bf548.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  System MMR register and memory map for ADSP-BF548
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __MACH_BF548_H__
+#define __MACH_BF548_H__
+
+#define SUPPORTED_REVID 0
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15		0x8000
+#define IMASK_IVG14		0x4000
+#define IMASK_IVG13		0x2000
+#define IMASK_IVG12		0x1000
+
+#define IMASK_IVG11		0x0800
+#define IMASK_IVG10		0x0400
+#define IMASK_IVG9		0x0200
+#define IMASK_IVG8		0x0100
+
+#define IMASK_IVG7		0x0080
+#define IMASK_IVGTMR	0x0040
+#define IMASK_IVGHW		0x0020
+
+/***************************/
+
+
+#define BLKFIN_DSUBBANKS	4
+#define BLKFIN_DWAYS		2
+#define BLKFIN_DLINES		64
+#define BLKFIN_ISUBBANKS	4
+#define BLKFIN_IWAYS		4
+#define BLKFIN_ILINES		32
+
+#define WAY0_L			0x1
+#define WAY1_L			0x2
+#define WAY01_L			0x3
+#define WAY2_L			0x4
+#define WAY02_L			0x5
+#define	WAY12_L			0x6
+#define	WAY012_L		0x7
+
+#define	WAY3_L			0x8
+#define	WAY03_L			0x9
+#define	WAY13_L			0xA
+#define	WAY013_L		0xB
+
+#define	WAY32_L			0xC
+#define	WAY320_L		0xD
+#define	WAY321_L		0xE
+#define	WAYALL_L		0xF
+
+#define DMC_ENABLE (2<<2)	/*yes, 2, not 1 */
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL	((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL	((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+
+#define AMGCTLVAL	(V_AMBEN | V_AMCKEN)
+
+#define MAX_VC	650000000
+#define MIN_VC	50000000
+
+/********************************PLL Settings **************************************/
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
+#if (CONFIG_VCO_MULT < 0)
+#error "VCO Multiplier is less than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT == 0)
+#error "VCO Multiplier should be greater than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT > 64)
+#error "VCO Multiplier is more than 64. Please select a different value"
+#endif
+
+#ifndef CONFIG_CLKIN_HALF
+#define CONFIG_VCO_HZ	(CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)
+#else
+#define CONFIG_VCO_HZ	((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)/2)
+#endif
+
+#ifndef CONFIG_PLL_BYPASS
+#define CONFIG_CCLK_HZ	(CONFIG_VCO_HZ/CONFIG_CCLK_DIV)
+#define CONFIG_SCLK_HZ	(CONFIG_VCO_HZ/CONFIG_SCLK_DIV)
+#else
+#define CONFIG_CCLK_HZ	CONFIG_CLKIN_HZ
+#define CONFIG_SCLK_HZ	CONFIG_CLKIN_HZ
+#endif
+
+#if (CONFIG_SCLK_DIV < 1)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_SCLK_DIV > 15)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_CCLK_DIV != 1)
+#if (CONFIG_CCLK_DIV != 2)
+#if (CONFIG_CCLK_DIV != 4)
+#if (CONFIG_CCLK_DIV != 8)
+#error "CCLK DIV can be 1,2,4 or 8 only. Please select a proper value"
+#endif
+#endif
+#endif
+#endif
+
+#if (CONFIG_VCO_HZ > MAX_VC)
+#error "VCO selected is more than maximum value. Please change the VCO multipler"
+#endif
+
+#if (CONFIG_SCLK_HZ > 133000000)
+#error "Sclk value selected is more than maximum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ < 27000000)
+#error "Sclk value selected is less than minimum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ >= CONFIG_CCLK_HZ)
+#if (CONFIG_SCLK_HZ != CONFIG_CLKIN_HZ)
+#if (CONFIG_CCLK_HZ != CONFIG_CLKIN_HZ)
+#error "Please select sclk less than cclk"
+#endif
+#endif
+#endif
+
+#if (CONFIG_CCLK_DIV == 1)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV1
+#endif
+#if (CONFIG_CCLK_DIV == 2)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV2
+#endif
+#if (CONFIG_CCLK_DIV == 4)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV4
+#endif
+#if (CONFIG_CCLK_DIV == 8)
+#define CONFIG_CCLK_ACT_DIV   CCLK_DIV8
+#endif
+#ifndef CONFIG_CCLK_ACT_DIV
+#define CONFIG_CCLK_ACT_DIV   CONFIG_CCLK_DIV_not_defined_properly
+#endif
+
+#endif	/* CONFIG_BFIN_KERNEL_CLOCK */
+
+#ifdef CONFIG_BF542
+#define CPU "BF542"
+#define CPUID 0x027c8000
+#endif
+#ifdef CONFIG_BF544
+#define CPU "BF544"
+#define CPUID 0x027c8000
+#endif
+#ifdef CONFIG_BF548
+#define CPU "BF548"
+#define CPUID 0x027c6000
+#endif
+#ifdef CONFIG_BF549
+#define CPU "BF549"
+#endif
+#ifndef CPU
+#define	CPU "UNKNOWN"
+#define CPUID 0x0
+#endif
+
+#if (CONFIG_MEM_SIZE % 4)
+#error "SDRAM mem size must be multible of 4MB"
+#endif
+
+#define SDRAM_IGENERIC    (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO)
+#define SDRAM_IKERNEL     (SDRAM_IGENERIC | CPLB_LOCK)
+#define L1_IMEMORY        (               CPLB_USER_RD | CPLB_VALID | CPLB_LOCK)
+#define SDRAM_INON_CHBL   (               CPLB_USER_RD | CPLB_VALID)
+
+/*Use the menuconfig cache policy here - CONFIG_BLKFIN_WT/CONFIG_BLKFIN_WB*/
+
+#define ANOMALY_05000158_WORKAROUND		0x200
+#ifdef CONFIG_BLKFIN_WB		/*Write Back Policy */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_DIRTY \
+			| CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
+#else				/*Write Through */
+#define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW \
+			| CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#endif
+
+
+#define L1_DMEMORY       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY )
+#define SDRAM_DNON_CHBL  (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#define SDRAM_EBIU       (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#define SDRAM_OOPS  	 (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY )
+
+#define SIZE_1K 0x00000400	/* 1K */
+#define SIZE_4K 0x00001000	/* 4K */
+#define SIZE_1M 0x00100000	/* 1M */
+#define SIZE_4M 0x00400000	/* 4M */
+
+#define MAX_CPLBS (16 * 2)
+
+/*
+* Number of required data CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Data Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+* 1 for ASYNC Memory
+*/
+
+
+#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1) * 2)
+
+/*
+* Number of required instruction CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Instruction Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+*/
+
+#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1) * 2)
+
+#endif	/* __MACH_BF48_H__  */
diff --git a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
new file mode 100644
index 0000000..2f4afc9
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
@@ -0,0 +1,193 @@
+#include <linux/serial.h>
+#include <asm/dma.h>
+
+#define NR_PORTS		4
+
+#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
+#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
+#define OFFSET_GCTL             0x08	/* Global Control Register              */
+#define OFFSET_LCR              0x0C	/* Line Control Register                */
+#define OFFSET_MCR              0x10	/* Modem Control Register               */
+#define OFFSET_LSR              0x14	/* Line Status Register                 */
+#define OFFSET_MSR              0x18	/* Modem Status Register                */
+#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
+#define OFFSET_IER_SET          0x20	/* Set Interrupt Enable Register        */
+#define OFFSET_IER_CLEAR        0x24	/* Clear Interrupt Enable Register      */
+#define OFFSET_THR              0x28	/* Transmit Holding register            */
+#define OFFSET_RBR              0x2C	/* Receive Buffer register              */
+
+#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER_SET))
+#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_LSR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LSR))
+#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
+#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
+#define UART_SET_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER_SET),v)
+#define UART_CLEAR_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER_CLEAR),v)
+#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
+#define UART_PUT_LSR(uart,v)	bfin_write16(((uart)->port.membase + OFFSET_LSR),v)
+#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
+#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
+
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
+# define CONFIG_SERIAL_BFIN_CTSRTS
+
+# ifndef CONFIG_UART0_CTS_PIN
+#  define CONFIG_UART0_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART0_RTS_PIN
+#  define CONFIG_UART0_RTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_CTS_PIN
+#  define CONFIG_UART1_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_RTS_PIN
+#  define CONFIG_UART1_RTS_PIN -1
+# endif
+#endif
+/*
+ * The pin configuration is different from schematic
+ */
+struct bfin_serial_port {
+        struct uart_port        port;
+        unsigned int            old_status;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+	int			tx_done;
+	int			tx_count;
+	struct circ_buf		rx_dma_buf;
+	struct timer_list       rx_dma_timer;
+	int			rx_dma_nrows;
+	unsigned int		tx_dma_channel;
+	unsigned int		rx_dma_channel;
+	struct work_struct	tx_dma_workqueue;
+#else
+	struct work_struct 	cts_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+	int		cts_pin;
+	int 		rts_pin;
+#endif
+};
+
+struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_res {
+	unsigned long	uart_base_addr;
+	int		uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+	unsigned int	uart_tx_dma_channel;
+	unsigned int	uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+	int	uart_cts_pin;
+	int	uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	{
+	0xFFC00400,
+	IRQ_UART0_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+	CH_UART0_TX,
+	CH_UART0_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+	CONFIG_UART0_CTS_PIN,
+	CONFIG_UART0_RTS_PIN,
+#endif
+	},
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+	{
+	0xFFC02000,
+	IRQ_UART1_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+	CH_UART1_TX,
+	CH_UART1_RX,
+#endif
+	},
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART2
+	{
+	0xFFC02100,
+	IRQ_UART2_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+	CH_UART2_TX,
+	CH_UART2_RX,
+#endif
+#ifdef CONFIG_BFIN_UART2_CTSRTS
+	CONFIG_UART2_CTS_PIN,
+	CONFIG_UART2_RTS_PIN,
+#endif
+	},
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART3
+	{
+	0xFFC03100,
+	IRQ_UART3_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+	CH_UART3_TX,
+	CH_UART3_RX,
+#endif
+	},
+#endif
+};
+
+int nr_ports = ARRAY_SIZE(bfin_serial_resource);
+
+static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+{
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	/* Enable UART0 RX and TX on pin 7 & 8 of PORT E */
+	bfin_write_PORTE_FER(0x180 | bfin_read_PORTE_FER());
+	bfin_write_PORTE_MUX(0x3C000 | bfin_read_PORTE_MUX());
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART1
+	/* Enable UART1 RX and TX on pin 0 & 1 of PORT H */
+	bfin_write_PORTH_FER(0x3 | bfin_read_PORTH_FER());
+	bfin_write_PORTH_MUX(~0xF & bfin_read_PORTH_MUX());
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+	/* Enable UART1 RTS and CTS on pin 9 & 10 of PORT E */
+	bfin_write_PORTE_FER(0x600 | bfin_read_PORTE_FER());
+	bfin_write_PORTE_MUX(~0x3C0000 & bfin_read_PORTE_MUX());
+#endif
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART2
+	/* Enable UART2 RX and TX on pin 4 & 5 of PORT B */
+	bfin_write_PORTB_FER(0x30 | bfin_read_PORTB_FER());
+	bfin_write_PORTB_MUX(~0xF00 & bfin_read_PORTB_MUX());
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART3
+	/* Enable UART3 RX and TX on pin 6 & 7 of PORT B */
+	bfin_write_PORTB_FER(0xC0 | bfin_read_PORTB_FER());
+	bfin_write_PORTB_MUX(~0xF000 | bfin_read_PORTB_MUX());
+#ifdef CONFIG_BFIN_UART3_CTSRTS
+	/* Enable UART3 RTS and CTS on pin 2 & 3 of PORT B */
+	bfin_write_PORTB_FER(0xC | bfin_read_PORTB_FER());
+	bfin_write_PORTB_MUX(~0xF0 | bfin_read_PORTB_MUX());
+#endif
+#endif
+	SSYNC();
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+	if (uart->cts_pin >= 0) {
+		gpio_request(uart->cts_pin, NULL);
+		gpio_direction_input(uart->cts_pin);
+	}
+
+	if (uart->rts_pin >= 0) {
+		gpio_request(uart->rts_pin, NULL);
+		gpio_direction_output(uart->rts_pin);
+	}
+#endif
+}
diff --git a/include/asm-blackfin/mach-bf548/blackfin.h b/include/asm-blackfin/mach-bf548/blackfin.h
new file mode 100644
index 0000000..791218f
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/blackfin.h
@@ -0,0 +1,168 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF548_FAMILY
+
+#include "bf548.h"
+#include "mem_map.h"
+#include "anomaly.h"
+
+#ifdef CONFIG_BF542
+#include "defBF542.h"
+#endif
+
+#ifdef CONFIG_BF544
+#include "defBF544.h"
+#endif
+
+#ifdef CONFIG_BF548
+#include "defBF548.h"
+#endif
+
+#ifdef CONFIG_BF549
+#include "defBF549.h"
+#endif
+
+#if !(defined(__ASSEMBLY__) || defined(ASSEMBLY))
+#ifdef CONFIG_BF542
+#include "cdefBF542.h"
+#endif
+
+#ifdef CONFIG_BF544
+#include "cdefBF544.h"
+#endif
+#ifdef CONFIG_BF548
+#include "cdefBF548.h"
+#endif
+#ifdef CONFIG_BF549
+#include "cdefBF549.h"
+#endif
+
+/* UART 1*/
+#define bfin_read_UART_THR()		bfin_read_UART1_THR()
+#define bfin_write_UART_THR(val)	bfin_write_UART1_THR(val)
+#define bfin_read_UART_RBR()		bfin_read_UART1_RBR()
+#define bfin_write_UART_RBR(val)	bfin_write_UART1_RBR(val)
+#define bfin_read_UART_DLL()		bfin_read_UART1_DLL()
+#define bfin_write_UART_DLL(val)	bfin_write_UART1_DLL(val)
+#define bfin_read_UART_IER()		bfin_read_UART1_IER()
+#define bfin_write_UART_IER(val)	bfin_write_UART1_IER(val)
+#define bfin_read_UART_DLH()		bfin_read_UART1_DLH()
+#define bfin_write_UART_DLH(val)	bfin_write_UART1_DLH(val)
+#define bfin_read_UART_IIR()		bfin_read_UART1_IIR()
+#define bfin_write_UART_IIR(val)	bfin_write_UART1_IIR(val)
+#define bfin_read_UART_LCR()		bfin_read_UART1_LCR()
+#define bfin_write_UART_LCR(val)	bfin_write_UART1_LCR(val)
+#define bfin_read_UART_MCR()		bfin_read_UART1_MCR()
+#define bfin_write_UART_MCR(val)	bfin_write_UART1_MCR(val)
+#define bfin_read_UART_LSR()		bfin_read_UART1_LSR()
+#define bfin_write_UART_LSR(val)	bfin_write_UART1_LSR(val)
+#define bfin_read_UART_SCR()		bfin_read_UART1_SCR()
+#define bfin_write_UART_SCR(val)	bfin_write_UART1_SCR(val)
+#define bfin_read_UART_GCTL()		bfin_read_UART1_GCTL()
+#define bfin_write_UART_GCTL(val)	bfin_write_UART1_GCTL(val)
+
+#endif
+
+/* MAP used DEFINES from BF533 to BF54x - so we don't need to change 
+ * them in the driver, kernel, etc. */
+
+/* UART_IIR Register */
+#define STATUS(x)	((x << 1) & 0x06)
+#define STATUS_P1	0x02
+#define STATUS_P0	0x01
+
+/* UART 0*/
+
+/* DMA Channnel */
+#define bfin_read_CH_UART_RX()		bfin_read_CH_UART1_RX()
+#define bfin_write_CH_UART_RX(val)	bfin_write_CH_UART1_RX(val)
+#define bfin_read_CH_UART_TX()		bfin_read_CH_UART1_TX()
+#define bfin_write_CH_UART_TX(val)	bfin_write_CH_UART1_TX(val)
+#define CH_UART_RX			CH_UART1_RX
+#define CH_UART_TX			CH_UART1_TX
+
+/* System Interrupt Controller */
+#define bfin_read_IRQ_UART_RX()		bfin_read_IRQ_UART1_RX()
+#define bfin_write_IRQ_UART_RX(val)	bfin_write_IRQ_UART1_RX(val)
+#define bfin_read_IRQ_UART_TX()		bfin_read_IRQ_UART1_TX()
+#define bfin_write_IRQ_UART_TX(val)	bfin_write_IRQ_UART1_TX(val)
+#define bfin_read_IRQ_UART_ERROR()	bfin_read_IRQ_UART1_ERROR()
+#define bfin_write_IRQ_UART_ERROR(val)	bfin_write_IRQ_UART1_ERROR(val)
+#define IRQ_UART_RX			IRQ_UART1_RX
+#define	IRQ_UART_TX			IRQ_UART1_TX
+#define	IRQ_UART_ERROR			IRQ_UART1_ERROR
+
+/* MMR Registers*/
+#define bfin_read_UART_THR()		bfin_read_UART1_THR()
+#define bfin_write_UART_THR(val)	bfin_write_UART1_THR(val)
+#define bfin_read_UART_RBR()		bfin_read_UART1_RBR()
+#define bfin_write_UART_RBR(val)	bfin_write_UART1_RBR(val)
+#define bfin_read_UART_DLL()		bfin_read_UART1_DLL()
+#define bfin_write_UART_DLL(val)	bfin_write_UART1_DLL(val)
+#define bfin_read_UART_IER()		bfin_read_UART1_IER()
+#define bfin_write_UART_IER(val)	bfin_write_UART1_IER(val)
+#define bfin_read_UART_DLH()		bfin_read_UART1_DLH()
+#define bfin_write_UART_DLH(val)	bfin_write_UART1_DLH(val)
+#define bfin_read_UART_IIR()		bfin_read_UART1_IIR()
+#define bfin_write_UART_IIR(val)	bfin_write_UART1_IIR(val)
+#define bfin_read_UART_LCR()		bfin_read_UART1_LCR()
+#define bfin_write_UART_LCR(val)	bfin_write_UART1_LCR(val)
+#define bfin_read_UART_MCR()		bfin_read_UART1_MCR()
+#define bfin_write_UART_MCR(val)	bfin_write_UART1_MCR(val)
+#define bfin_read_UART_LSR()		bfin_read_UART1_LSR()
+#define bfin_write_UART_LSR(val)	bfin_write_UART1_LSR(val)
+#define bfin_read_UART_SCR()		bfin_read_UART1_SCR()
+#define bfin_write_UART_SCR(val)	bfin_write_UART1_SCR(val)
+#define bfin_read_UART_GCTL()		bfin_read_UART1_GCTL()
+#define bfin_write_UART_GCTL(val)	bfin_write_UART1_GCTL(val)
+#define UART_THR			UART1_THR
+#define UART_RBR			UART1_RBR
+#define UART_DLL			UART1_DLL
+#define UART_IER			UART1_IER
+#define UART_DLH			UART1_DLH
+#define UART_IIR			UART1_IIR
+#define UART_LCR			UART1_LCR
+#define UART_MCR			UART1_MCR
+#define UART_LSR			UART1_LSR
+#define UART_SCR			UART1_SCR
+#define UART_GCTL			UART1_GCTL
+
+/* PLL_DIV Masks */
+#define CCLK_DIV1 CSEL_DIV1	/* CCLK = VCO / 1 */
+#define CCLK_DIV2 CSEL_DIV2	/* CCLK = VCO / 2 */
+#define CCLK_DIV4 CSEL_DIV4	/* CCLK = VCO / 4 */
+#define CCLK_DIV8 CSEL_DIV8	/* CCLK = VCO / 8 */
+
+#endif
diff --git a/include/asm-blackfin/mach-bf548/cdefBF542.h b/include/asm-blackfin/mach-bf548/cdefBF542.h
new file mode 100644
index 0000000..308b33a
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/cdefBF542.h
@@ -0,0 +1,590 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/cdefBF542.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF542_H
+#define _CDEF_BF542_H
+
+/* include all Core registers and bit definitions */
+#include "defBF542.h"
+
+/* include core sbfin_read_()ecific register pointer definitions */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF542 */
+
+/* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
+#include "cdefBF54x_base.h"
+
+/* The following are the #defines needed by ADSP-BF542 that are not in the common header */
+
+/* ATAPI Registers */
+
+#define bfin_read_ATAPI_CONTROL()		bfin_read16(ATAPI_CONTROL)
+#define bfin_write_ATAPI_CONTROL(val)		bfin_write16(ATAPI_CONTROL, val)
+#define bfin_read_ATAPI_STATUS()		bfin_read16(ATAPI_STATUS)
+#define bfin_write_ATAPI_STATUS(val)		bfin_write16(ATAPI_STATUS, val)
+#define bfin_read_ATAPI_DEV_ADDR()		bfin_read16(ATAPI_DEV_ADDR)
+#define bfin_write_ATAPI_DEV_ADDR(val)		bfin_write16(ATAPI_DEV_ADDR, val)
+#define bfin_read_ATAPI_DEV_TXBUF()		bfin_read16(ATAPI_DEV_TXBUF)
+#define bfin_write_ATAPI_DEV_TXBUF(val)		bfin_write16(ATAPI_DEV_TXBUF, val)
+#define bfin_read_ATAPI_DEV_RXBUF()		bfin_read16(ATAPI_DEV_RXBUF)
+#define bfin_write_ATAPI_DEV_RXBUF(val)		bfin_write16(ATAPI_DEV_RXBUF, val)
+#define bfin_read_ATAPI_INT_MASK()		bfin_read16(ATAPI_INT_MASK)
+#define bfin_write_ATAPI_INT_MASK(val)		bfin_write16(ATAPI_INT_MASK, val)
+#define bfin_read_ATAPI_INT_STATUS()		bfin_read16(ATAPI_INT_STATUS)
+#define bfin_write_ATAPI_INT_STATUS(val)	bfin_write16(ATAPI_INT_STATUS, val)
+#define bfin_read_ATAPI_XFER_LEN()		bfin_read16(ATAPI_XFER_LEN)
+#define bfin_write_ATAPI_XFER_LEN(val)		bfin_write16(ATAPI_XFER_LEN, val)
+#define bfin_read_ATAPI_LINE_STATUS()		bfin_read16(ATAPI_LINE_STATUS)
+#define bfin_write_ATAPI_LINE_STATUS(val)	bfin_write16(ATAPI_LINE_STATUS, val)
+#define bfin_read_ATAPI_SM_STATE()		bfin_read16(ATAPI_SM_STATE)
+#define bfin_write_ATAPI_SM_STATE(val)		bfin_write16(ATAPI_SM_STATE, val)
+#define bfin_read_ATAPI_TERMINATE()		bfin_read16(ATAPI_TERMINATE)
+#define bfin_write_ATAPI_TERMINATE(val)		bfin_write16(ATAPI_TERMINATE, val)
+#define bfin_read_ATAPI_PIO_TFRCNT()		bfin_read16(ATAPI_PIO_TFRCNT)
+#define bfin_write_ATAPI_PIO_TFRCNT(val)	bfin_write16(ATAPI_PIO_TFRCNT, val)
+#define bfin_read_ATAPI_DMA_TFRCNT()		bfin_read16(ATAPI_DMA_TFRCNT)
+#define bfin_write_ATAPI_DMA_TFRCNT(val)	bfin_write16(ATAPI_DMA_TFRCNT, val)
+#define bfin_read_ATAPI_UMAIN_TFRCNT()		bfin_read16(ATAPI_UMAIN_TFRCNT)
+#define bfin_write_ATAPI_UMAIN_TFRCNT(val)	bfin_write16(ATAPI_UMAIN_TFRCNT, val)
+#define bfin_read_ATAPI_UDMAOUT_TFRCNT()	bfin_read16(ATAPI_UDMAOUT_TFRCNT)
+#define bfin_write_ATAPI_UDMAOUT_TFRCNT(val)	bfin_write16(ATAPI_UDMAOUT_TFRCNT, val)
+#define bfin_read_ATAPI_REG_TIM_0()		bfin_read16(ATAPI_REG_TIM_0)
+#define bfin_write_ATAPI_REG_TIM_0(val)		bfin_write16(ATAPI_REG_TIM_0, val)
+#define bfin_read_ATAPI_PIO_TIM_0()		bfin_read16(ATAPI_PIO_TIM_0)
+#define bfin_write_ATAPI_PIO_TIM_0(val)		bfin_write16(ATAPI_PIO_TIM_0, val)
+#define bfin_read_ATAPI_PIO_TIM_1()		bfin_read16(ATAPI_PIO_TIM_1)
+#define bfin_write_ATAPI_PIO_TIM_1(val)		bfin_write16(ATAPI_PIO_TIM_1, val)
+#define bfin_read_ATAPI_MULTI_TIM_0()		bfin_read16(ATAPI_MULTI_TIM_0)
+#define bfin_write_ATAPI_MULTI_TIM_0(val)	bfin_write16(ATAPI_MULTI_TIM_0, val)
+#define bfin_read_ATAPI_MULTI_TIM_1()		bfin_read16(ATAPI_MULTI_TIM_1)
+#define bfin_write_ATAPI_MULTI_TIM_1(val)	bfin_write16(ATAPI_MULTI_TIM_1, val)
+#define bfin_read_ATAPI_MULTI_TIM_2()		bfin_read16(ATAPI_MULTI_TIM_2)
+#define bfin_write_ATAPI_MULTI_TIM_2(val)	bfin_write16(ATAPI_MULTI_TIM_2, val)
+#define bfin_read_ATAPI_ULTRA_TIM_0()		bfin_read16(ATAPI_ULTRA_TIM_0)
+#define bfin_write_ATAPI_ULTRA_TIM_0(val)	bfin_write16(ATAPI_ULTRA_TIM_0, val)
+#define bfin_read_ATAPI_ULTRA_TIM_1()		bfin_read16(ATAPI_ULTRA_TIM_1)
+#define bfin_write_ATAPI_ULTRA_TIM_1(val)	bfin_write16(ATAPI_ULTRA_TIM_1, val)
+#define bfin_read_ATAPI_ULTRA_TIM_2()		bfin_read16(ATAPI_ULTRA_TIM_2)
+#define bfin_write_ATAPI_ULTRA_TIM_2(val)	bfin_write16(ATAPI_ULTRA_TIM_2, val)
+#define bfin_read_ATAPI_ULTRA_TIM_3()		bfin_read16(ATAPI_ULTRA_TIM_3)
+#define bfin_write_ATAPI_ULTRA_TIM_3(val)	bfin_write16(ATAPI_ULTRA_TIM_3, val)
+
+/* SDH Registers */
+
+#define bfin_read_SDH_PWR_CTL()		bfin_read16(SDH_PWR_CTL)
+#define bfin_write_SDH_PWR_CTL(val)	bfin_write16(SDH_PWR_CTL, val)
+#define bfin_read_SDH_CLK_CTL()		bfin_read16(SDH_CLK_CTL)
+#define bfin_write_SDH_CLK_CTL(val)	bfin_write16(SDH_CLK_CTL, val)
+#define bfin_read_SDH_ARGUMENT()	bfin_read32(SDH_ARGUMENT)
+#define bfin_write_SDH_ARGUMENT(val)	bfin_write32(SDH_ARGUMENT, val)
+#define bfin_read_SDH_COMMAND()		bfin_read16(SDH_COMMAND)
+#define bfin_write_SDH_COMMAND(val)	bfin_write16(SDH_COMMAND, val)
+#define bfin_read_SDH_RESP_CMD()	bfin_read16(SDH_RESP_CMD)
+#define bfin_write_SDH_RESP_CMD(val)	bfin_write16(SDH_RESP_CMD, val)
+#define bfin_read_SDH_RESPONSE0()	bfin_read32(SDH_RESPONSE0)
+#define bfin_write_SDH_RESPONSE0(val)	bfin_write32(SDH_RESPONSE0, val)
+#define bfin_read_SDH_RESPONSE1()	bfin_read32(SDH_RESPONSE1)
+#define bfin_write_SDH_RESPONSE1(val)	bfin_write32(SDH_RESPONSE1, val)
+#define bfin_read_SDH_RESPONSE2()	bfin_read32(SDH_RESPONSE2)
+#define bfin_write_SDH_RESPONSE2(val)	bfin_write32(SDH_RESPONSE2, val)
+#define bfin_read_SDH_RESPONSE3()	bfin_read32(SDH_RESPONSE3)
+#define bfin_write_SDH_RESPONSE3(val)	bfin_write32(SDH_RESPONSE3, val)
+#define bfin_read_SDH_DATA_TIMER()	bfin_read32(SDH_DATA_TIMER)
+#define bfin_write_SDH_DATA_TIMER(val)	bfin_write32(SDH_DATA_TIMER, val)
+#define bfin_read_SDH_DATA_LGTH()	bfin_read16(SDH_DATA_LGTH)
+#define bfin_write_SDH_DATA_LGTH(val)	bfin_write16(SDH_DATA_LGTH, val)
+#define bfin_read_SDH_DATA_CTL()	bfin_read16(SDH_DATA_CTL)
+#define bfin_write_SDH_DATA_CTL(val)	bfin_write16(SDH_DATA_CTL, val)
+#define bfin_read_SDH_DATA_CNT()	fin_read16(SDH_DATA_CNT)
+#define bfin_write_SDH_DATA_CNT(val)	bfin_write16(SDH_DATA_CNT, val)
+#define bfin_read_SDH_STATUS()		bfin_read32(SDH_STATUS)
+#define bfin_write_SDH_STATUS(val)	bfin_write32(SDH_STATUS, val)
+#define bfin_read_SDH_STATUS_CLR()	fin_read16(SDH_STATUS_CLR)
+#define bfin_write_SDH_STATUS_CLR(val)	fin_write16(SDH_STATUS_CLR, val)
+#define bfin_read_SDH_MASK0()		bfin_read32(SDH_MASK0)
+#define bfin_write_SDH_MASK0(val)	bfin_write32(SDH_MASK0, val)
+#define bfin_read_SDH_MASK1()		bfin_read32(SDH_MASK1)
+#define bfin_write_SDH_MASK1(val)	bfin_write32(SDH_MASK1, val)
+#define bfin_read_SDH_FIFO_CNT()	bfin_read16(SDH_FIFO_CNT)
+#define bfin_write_SDH_FIFO_CNT(val)	bfin_write16(SDH_FIFO_CNT, val)
+#define bfin_read_SDH_FIFO()		bfin_read32(SDH_FIFO)
+#define bfin_write_SDH_FIFO(val)	bfin_write32(SDH_FIFO, val)
+#define bfin_read_SDH_E_STATUS()	bfin_read16(SDH_E_STATUS)
+#define bfin_write_SDH_E_STATUS(val)	bfin_write16(SDH_E_STATUS, val)
+#define bfin_read_SDH_E_MASK()		bfin_read16(SDH_E_MASK)
+#define bfin_write_SDH_E_MASK(val)	bfin_write16(SDH_E_MASK, val)
+#define bfin_read_SDH_CFG()		bfin_read16(SDH_CFG)
+#define bfin_write_SDH_CFG(val)		bfin_write16(SDH_CFG, val)
+#define bfin_read_SDH_RD_WAIT_EN()	bfin_read16(SDH_RD_WAIT_EN)
+#define bfin_write_SDH_RD_WAIT_EN(val)	bfin_write16(SDH_RD_WAIT_EN, val)
+#define bfin_read_SDH_PID0()		bfin_read16(SDH_PID0)
+#define bfin_write_SDH_PID0(val)	bfin_write16(SDH_PID0, val)
+#define bfin_read_SDH_PID1()		bfin_read16(SDH_PID1)
+#define bfin_write_SDH_PID1(val)	bfin_write16(SDH_PID1, val)
+#define bfin_read_SDH_PID2()		bfin_read16(SDH_PID2)
+#define bfin_write_SDH_PID2(val)	bfin_write16(SDH_PID2, val)
+#define bfin_read_SDH_PID3()		bfin_read16(SDH_PID3)
+#define bfin_write_SDH_PID3(val)	bfin_write16(SDH_PID3, val)
+#define bfin_read_SDH_PID4()		bfin_read16(SDH_PID4)
+#define bfin_write_SDH_PID4(val)	bfin_write16(SDH_PID4, val)
+#define bfin_read_SDH_PID5()		bfin_read16(SDH_PID5)
+#define bfin_write_SDH_PID5(val)	bfin_write16(SDH_PID5, val)
+#define bfin_read_SDH_PID6()		bfin_read16(SDH_PID6)
+#define bfin_write_SDH_PID6(val)	bfin_write16(SDH_PID6, val)
+#define bfin_read_SDH_PID7()		bfin_read16(SDH_PID7)
+#define bfin_write_SDH_PID7(val)	bfin_write16(SDH_PID7, val)
+
+/* USB Control Registers */
+
+#define bfin_read_USB_FADDR()		bfin_read16(USB_FADDR)
+#define bfin_write_USB_FADDR(val)	bfin_write16(USB_FADDR, val)
+#define bfin_read_USB_POWER()		bfin_read16(USB_POWER)
+#define bfin_write_USB_POWER(val)	bfin_write16(USB_POWER, val)
+#define bfin_read_USB_INTRTX()		bfin_read16(USB_INTRTX)
+#define bfin_write_USB_INTRTX(val)	bfin_write16(USB_INTRTX, val)
+#define bfin_read_USB_INTRRX()		bfin_read16(USB_INTRRX)
+#define bfin_write_USB_INTRRX(val)	bfin_write16(USB_INTRRX, val)
+#define bfin_read_USB_INTRTXE()		bfin_read16(USB_INTRTXE)
+#define bfin_write_USB_INTRTXE(val)	bfin_write16(USB_INTRTXE, val)
+#define bfin_read_USB_INTRRXE()		bfin_read16(USB_INTRRXE)
+#define bfin_write_USB_INTRRXE(val)	bfin_write16(USB_INTRRXE, val)
+#define bfin_read_USB_INTRUSB()		bfin_read16(USB_INTRUSB)
+#define bfin_write_USB_INTRUSB(val)	bfin_write16(USB_INTRUSB, val)
+#define bfin_read_USB_INTRUSBE()	bfin_read16(USB_INTRUSBE)
+#define bfin_write_USB_INTRUSBE(val)	bfin_write16(USB_INTRUSBE, val)
+#define bfin_read_USB_FRAME()		bfin_read16(USB_FRAME)
+#define bfin_write_USB_FRAME(val)	bfin_write16(USB_FRAME, val)
+#define bfin_read_USB_INDEX()		bfin_read16(USB_INDEX)
+#define bfin_write_USB_INDEX(val)	bfin_write16(USB_INDEX, val)
+#define bfin_read_USB_TESTMODE()	fin_read16(USB_TESTMODE)
+#define bfin_write_USB_TESTMODE(val)	fin_write16(USB_TESTMODE, val)
+#define bfin_read_USB_GLOBINTR()	bfin_read16(USB_GLOBINTR)
+#define bfin_write_USB_GLOBINTR(val)	bfin_write16(USB_GLOBINTR, val)
+#define bfin_read_USB_GLOBAL_CTL()	bfin_read16(USB_GLOBAL_CTL)
+#define bfin_write_USB_GLOBAL_CTL(val)	bfin_write16(USB_GLOBAL_CTL, val)
+
+/* USB Packet Control Registers */
+
+#define bfin_read_USB_TX_MAX_PACKET()		bfin_read16(USB_TX_MAX_PACKET)
+#define bfin_write_USB_TX_MAX_PACKET(val)	bfin_write16(USB_TX_MAX_PACKET, val)
+#define bfin_read_USB_CSR0()			bfin_read16(USB_CSR0)
+#define bfin_write_USB_CSR0(val)		bfin_write16(USB_CSR0, val)
+#define bfin_read_USB_TXCSR()			bfin_read16(USB_TXCSR)
+#define bfin_write_USB_TXCSR(val)		bfin_write16(USB_TXCSR, val)
+#define bfin_read_USB_RX_MAX_PACKET()		bfin_read16(USB_RX_MAX_PACKET)
+#define bfin_write_USB_RX_MAX_PACKET(val)	bfin_write16(USB_RX_MAX_PACKET, val)
+#define bfin_read_USB_RXCSR()			bfin_read16(USB_RXCSR)
+#define bfin_write_USB_RXCSR(val)		bfin_write16(USB_RXCSR, val)
+#define bfin_read_USB_COUNT0()			bfin_read16(USB_COUNT0)
+#define bfin_write_USB_COUNT0(val)		bfin_write16(USB_COUNT0, val)
+#define bfin_read_USB_RXCOUNT()			bfin_read16(USB_RXCOUNT)
+#define bfin_write_USB_RXCOUNT(val)		bfin_write16(USB_RXCOUNT, val)
+#define bfin_read_USB_TXTYPE()			bfin_read16(USB_TXTYPE)
+#define bfin_write_USB_TXTYPE(val)		bfin_write16(USB_TXTYPE, val)
+#define bfin_read_USB_NAKLIMIT0()		bfin_read16(USB_NAKLIMIT0)
+#define bfin_write_USB_NAKLIMIT0(val)		bfin_write16(USB_NAKLIMIT0, val)
+#define bfin_read_USB_TXINTERVAL()		bfin_read16(USB_TXINTERVAL)
+#define bfin_write_USB_TXINTERVAL(val)		bfin_write16(USB_TXINTERVAL, val)
+#define bfin_read_USB_RXTYPE()			bfin_read16(USB_RXTYPE)
+#define bfin_write_USB_RXTYPE(val)		bfin_write16(USB_RXTYPE, val)
+#define bfin_read_USB_RXINTERVAL()		bfin_read16(USB_RXINTERVAL)
+#define bfin_write_USB_RXINTERVAL(val)		bfin_write16(USB_RXINTERVAL, val)
+#define bfin_read_USB_TXCOUNT()			bfin_read16(USB_TXCOUNT)
+#define bfin_write_USB_TXCOUNT(val)		bfin_write16(USB_TXCOUNT, val)
+
+/* USB Endbfin_read_()oint FIFO Registers */
+
+#define bfin_read_USB_EP0_FIFO()		bfin_read16(USB_EP0_FIFO)
+#define bfin_write_USB_EP0_FIFO(val)		bfin_write16(USB_EP0_FIFO, val)
+#define bfin_read_USB_EP1_FIFO()		bfin_read16(USB_EP1_FIFO)
+#define bfin_write_USB_EP1_FIFO(val)		bfin_write16(USB_EP1_FIFO, val)
+#define bfin_read_USB_EP2_FIFO()		bfin_read16(USB_EP2_FIFO)
+#define bfin_write_USB_EP2_FIFO(val)		bfin_write16(USB_EP2_FIFO, val)
+#define bfin_read_USB_EP3_FIFO()		bfin_read16(USB_EP3_FIFO)
+#define bfin_write_USB_EP3_FIFO(val)		bfin_write16(USB_EP3_FIFO, val)
+#define bfin_read_USB_EP4_FIFO()		bfin_read16(USB_EP4_FIFO)
+#define bfin_write_USB_EP4_FIFO(val)		bfin_write16(USB_EP4_FIFO, val)
+#define bfin_read_USB_EP5_FIFO()		bfin_read16(USB_EP5_FIFO)
+#define bfin_write_USB_EP5_FIFO(val)		bfin_write16(USB_EP5_FIFO, val)
+#define bfin_read_USB_EP6_FIFO()		bfin_read16(USB_EP6_FIFO)
+#define bfin_write_USB_EP6_FIFO(val)		bfin_write16(USB_EP6_FIFO, val)
+#define bfin_read_USB_EP7_FIFO()		bfin_read16(USB_EP7_FIFO)
+#define bfin_write_USB_EP7_FIFO(val)		bfin_write16(USB_EP7_FIFO, val)
+
+/* USB OTG Control Registers */
+
+#define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
+#define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
+#define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
+#define bfin_write_USB_OTG_VBUS_IRQ(val)	fin_write16(USB_OTG_VBUS_IRQ, val)
+#define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
+#define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
+
+/* USB Phy Control Registers */
+
+#define bfin_read_USB_LINKINFO()		bfin_read16(USB_LINKINFO)
+#define bfin_write_USB_LINKINFO(val)		bfin_write16(USB_LINKINFO, val)
+#define bfin_read_USB_VPLEN()			bfin_read16(USB_VPLEN)
+#define bfin_write_USB_VPLEN(val)		bfin_write16(USB_VPLEN, val)
+#define bfin_read_USB_HS_EOF1()			bfin_read16(USB_HS_EOF1)
+#define bfin_write_USB_HS_EOF1(val)		bfin_write16(USB_HS_EOF1, val)
+#define bfin_read_USB_FS_EOF1()			bfin_read16(USB_FS_EOF1)
+#define bfin_write_USB_FS_EOF1(val)		bfin_write16(USB_FS_EOF1, val)
+#define bfin_read_USB_LS_EOF1()			bfin_read16(USB_LS_EOF1)
+#define bfin_write_USB_LS_EOF1(val)		bfin_write16(USB_LS_EOF1, val)
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CNTRL()		bfin_read16(USB_APHY_CNTRL)
+#define bfin_write_USB_APHY_CNTRL(val)		bfin_write16(USB_APHY_CNTRL, val)
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CALIB()		bfin_read16(USB_APHY_CALIB)
+#define bfin_write_USB_APHY_CALIB(val)		bfin_write16(USB_APHY_CALIB, val)
+#define bfin_read_USB_APHY_CNTRL2()		bfin_read16(USB_APHY_CNTRL2)
+#define bfin_write_USB_APHY_CNTRL2(val)		bfin_write16(USB_APHY_CNTRL2, val)
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define bfin_read_USB_PHY_TEST()		bfin_read16(USB_PHY_TEST)
+#define bfin_write_USB_PHY_TEST(val)		bfin_write16(USB_PHY_TEST, val)
+#define bfin_read_USB_PLLOSC_CTRL()		bfin_read16(USB_PLLOSC_CTRL)
+#define bfin_write_USB_PLLOSC_CTRL(val)		bfin_write16(USB_PLLOSC_CTRL, val)
+#define bfin_read_USB_SRP_CLKDIV()		bfin_read16(USB_SRP_CLKDIV)
+#define bfin_write_USB_SRP_CLKDIV(val)		bfin_write16(USB_SRP_CLKDIV, val)
+
+/* USB Endbfin_read_()oint 0 Control Registers */
+
+#define bfin_read_USB_EP_NI0_TXMAXP()		bfin_read16(USB_EP_NI0_TXMAXP)
+#define bfin_write_USB_EP_NI0_TXMAXP(val)	bfin_write16(USB_EP_NI0_TXMAXP, val)
+#define bfin_read_USB_EP_NI0_TXCSR()		bfin_read16(USB_EP_NI0_TXCSR)
+#define bfin_write_USB_EP_NI0_TXCSR(val)	bfin_write16(USB_EP_NI0_TXCSR, val)
+#define bfin_read_USB_EP_NI0_RXMAXP()		bfin_read16(USB_EP_NI0_RXMAXP)
+#define bfin_write_USB_EP_NI0_RXMAXP(val)	bfin_write16(USB_EP_NI0_RXMAXP, val)
+#define bfin_read_USB_EP_NI0_RXCSR()		bfin_read16(USB_EP_NI0_RXCSR)
+#define bfin_write_USB_EP_NI0_RXCSR(val)	bfin_write16(USB_EP_NI0_RXCSR, val)
+#define bfin_read_USB_EP_NI0_RXCOUNT()		bfin_read16(USB_EP_NI0_RXCOUNT)
+#define bfin_write_USB_EP_NI0_RXCOUNT(val)	bfin_write16(USB_EP_NI0_RXCOUNT, val)
+#define bfin_read_USB_EP_NI0_TXTYPE()		bfin_read16(USB_EP_NI0_TXTYPE)
+#define bfin_write_USB_EP_NI0_TXTYPE(val)	bfin_write16(USB_EP_NI0_TXTYPE, val)
+#define bfin_read_USB_EP_NI0_TXINTERVAL()	bfin_read16(USB_EP_NI0_TXINTERVAL)
+#define bfin_write_USB_EP_NI0_TXINTERVAL(val)	bfin_write16(USB_EP_NI0_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI0_RXTYPE()		bfin_read16(USB_EP_NI0_RXTYPE)
+#define bfin_write_USB_EP_NI0_RXTYPE(val)	bfin_write16(USB_EP_NI0_RXTYPE, val)
+#define bfin_read_USB_EP_NI0_RXINTERVAL()	bfin_read16(USB_EP_NI0_RXINTERVAL)
+#define bfin_write_USB_EP_NI0_RXINTERVAL(val)	bfin_write16(USB_EP_NI0_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 1 Control Registers */
+
+#define bfin_read_USB_EP_NI0_TXCOUNT()		bfin_read16(USB_EP_NI0_TXCOUNT)
+#define bfin_write_USB_EP_NI0_TXCOUNT(val)	bfin_write16(USB_EP_NI0_TXCOUNT, val)
+#define bfin_read_USB_EP_NI1_TXMAXP()		bfin_read16(USB_EP_NI1_TXMAXP)
+#define bfin_write_USB_EP_NI1_TXMAXP(val)	bfin_write16(USB_EP_NI1_TXMAXP, val)
+#define bfin_read_USB_EP_NI1_TXCSR()		bfin_read16(USB_EP_NI1_TXCSR)
+#define bfin_write_USB_EP_NI1_TXCSR(val)	bfin_write16(USB_EP_NI1_TXCSR, val)
+#define bfin_read_USB_EP_NI1_RXMAXP()		bfin_read16(USB_EP_NI1_RXMAXP)
+#define bfin_write_USB_EP_NI1_RXMAXP(val)	bfin_write16(USB_EP_NI1_RXMAXP, val)
+#define bfin_read_USB_EP_NI1_RXCSR()		bfin_read16(USB_EP_NI1_RXCSR)
+#define bfin_write_USB_EP_NI1_RXCSR(val)	bfin_write16(USB_EP_NI1_RXCSR, val)
+#define bfin_read_USB_EP_NI1_RXCOUNT()		bfin_read16(USB_EP_NI1_RXCOUNT)
+#define bfin_write_USB_EP_NI1_RXCOUNT(val)	bfin_write16(USB_EP_NI1_RXCOUNT, val)
+#define bfin_read_USB_EP_NI1_TXTYPE()		bfin_read16(USB_EP_NI1_TXTYPE)
+#define bfin_write_USB_EP_NI1_TXTYPE(val)	bfin_write16(USB_EP_NI1_TXTYPE, val)
+#define bfin_read_USB_EP_NI1_TXINTERVAL()	bfin_read16(USB_EP_NI1_TXINTERVAL)
+#define bfin_write_USB_EP_NI1_TXINTERVAL(val)	bfin_write16(USB_EP_NI1_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI1_RXTYPE()		bfin_read16(USB_EP_NI1_RXTYPE)
+#define bfin_write_USB_EP_NI1_RXTYPE(val)	bfin_write16(USB_EP_NI1_RXTYPE, val)
+#define bfin_read_USB_EP_NI1_RXINTERVAL()	bfin_read16(USB_EP_NI1_RXINTERVAL)
+#define bfin_write_USB_EP_NI1_RXINTERVAL(val)	bfin_write16(USB_EP_NI1_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 2 Control Registers */
+
+#define bfin_read_USB_EP_NI1_TXCOUNT()		bfin_read16(USB_EP_NI1_TXCOUNT)
+#define bfin_write_USB_EP_NI1_TXCOUNT(val)	bfin_write16(USB_EP_NI1_TXCOUNT, val)
+#define bfin_read_USB_EP_NI2_TXMAXP()		bfin_read16(USB_EP_NI2_TXMAXP)
+#define bfin_write_USB_EP_NI2_TXMAXP(val)	bfin_write16(USB_EP_NI2_TXMAXP, val)
+#define bfin_read_USB_EP_NI2_TXCSR()		bfin_read16(USB_EP_NI2_TXCSR)
+#define bfin_write_USB_EP_NI2_TXCSR(val)	bfin_write16(USB_EP_NI2_TXCSR, val)
+#define bfin_read_USB_EP_NI2_RXMAXP()		bfin_read16(USB_EP_NI2_RXMAXP)
+#define bfin_write_USB_EP_NI2_RXMAXP(val)	bfin_write16(USB_EP_NI2_RXMAXP, val)
+#define bfin_read_USB_EP_NI2_RXCSR()		bfin_read16(USB_EP_NI2_RXCSR)
+#define bfin_write_USB_EP_NI2_RXCSR(val)	bfin_write16(USB_EP_NI2_RXCSR, val)
+#define bfin_read_USB_EP_NI2_RXCOUNT()		bfin_read16(USB_EP_NI2_RXCOUNT)
+#define bfin_write_USB_EP_NI2_RXCOUNT(val)	bfin_write16(USB_EP_NI2_RXCOUNT, val)
+#define bfin_read_USB_EP_NI2_TXTYPE()		bfin_read16(USB_EP_NI2_TXTYPE)
+#define bfin_write_USB_EP_NI2_TXTYPE(val)	bfin_write16(USB_EP_NI2_TXTYPE, val)
+#define bfin_read_USB_EP_NI2_TXINTERVAL()	bfin_read16(USB_EP_NI2_TXINTERVAL)
+#define bfin_write_USB_EP_NI2_TXINTERVAL(val)	bfin_write16(USB_EP_NI2_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI2_RXTYPE()		bfin_read16(USB_EP_NI2_RXTYPE)
+#define bfin_write_USB_EP_NI2_RXTYPE(val)	bfin_write16(USB_EP_NI2_RXTYPE, val)
+#define bfin_read_USB_EP_NI2_RXINTERVAL()	bfin_read16(USB_EP_NI2_RXINTERVAL)
+#define bfin_write_USB_EP_NI2_RXINTERVAL(val)	bfin_write16(USB_EP_NI2_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 3 Control Registers */
+
+#define bfin_read_USB_EP_NI2_TXCOUNT()		bfin_read16(USB_EP_NI2_TXCOUNT)
+#define bfin_write_USB_EP_NI2_TXCOUNT(val)	bfin_write16(USB_EP_NI2_TXCOUNT, val)
+#define bfin_read_USB_EP_NI3_TXMAXP()		bfin_read16(USB_EP_NI3_TXMAXP)
+#define bfin_write_USB_EP_NI3_TXMAXP(val)	bfin_write16(USB_EP_NI3_TXMAXP, val)
+#define bfin_read_USB_EP_NI3_TXCSR()		bfin_read16(USB_EP_NI3_TXCSR)
+#define bfin_write_USB_EP_NI3_TXCSR(val)	bfin_write16(USB_EP_NI3_TXCSR, val)
+#define bfin_read_USB_EP_NI3_RXMAXP()		bfin_read16(USB_EP_NI3_RXMAXP)
+#define bfin_write_USB_EP_NI3_RXMAXP(val)	bfin_write16(USB_EP_NI3_RXMAXP, val)
+#define bfin_read_USB_EP_NI3_RXCSR()		bfin_read16(USB_EP_NI3_RXCSR)
+#define bfin_write_USB_EP_NI3_RXCSR(val)	bfin_write16(USB_EP_NI3_RXCSR, val)
+#define bfin_read_USB_EP_NI3_RXCOUNT()		bfin_read16(USB_EP_NI3_RXCOUNT)
+#define bfin_write_USB_EP_NI3_RXCOUNT(val)	bfin_write16(USB_EP_NI3_RXCOUNT, val)
+#define bfin_read_USB_EP_NI3_TXTYPE()		bfin_read16(USB_EP_NI3_TXTYPE)
+#define bfin_write_USB_EP_NI3_TXTYPE(val)	bfin_write16(USB_EP_NI3_TXTYPE, val)
+#define bfin_read_USB_EP_NI3_TXINTERVAL()	bfin_read16(USB_EP_NI3_TXINTERVAL)
+#define bfin_write_USB_EP_NI3_TXINTERVAL(val)	bfin_write16(USB_EP_NI3_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI3_RXTYPE()		bfin_read16(USB_EP_NI3_RXTYPE)
+#define bfin_write_USB_EP_NI3_RXTYPE(val)	bfin_write16(USB_EP_NI3_RXTYPE, val)
+#define bfin_read_USB_EP_NI3_RXINTERVAL()	bfin_read16(USB_EP_NI3_RXINTERVAL)
+#define bfin_write_USB_EP_NI3_RXINTERVAL(val)	bfin_write16(USB_EP_NI3_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 4 Control Registers */
+
+#define bfin_read_USB_EP_NI3_TXCOUNT()		bfin_read16(USB_EP_NI3_TXCOUNT)
+#define bfin_write_USB_EP_NI3_TXCOUNT(val)	bfin_write16(USB_EP_NI3_TXCOUNT, val)
+#define bfin_read_USB_EP_NI4_TXMAXP()		bfin_read16(USB_EP_NI4_TXMAXP)
+#define bfin_write_USB_EP_NI4_TXMAXP(val)	bfin_write16(USB_EP_NI4_TXMAXP, val)
+#define bfin_read_USB_EP_NI4_TXCSR()		bfin_read16(USB_EP_NI4_TXCSR)
+#define bfin_write_USB_EP_NI4_TXCSR(val)	bfin_write16(USB_EP_NI4_TXCSR, val)
+#define bfin_read_USB_EP_NI4_RXMAXP()		bfin_read16(USB_EP_NI4_RXMAXP)
+#define bfin_write_USB_EP_NI4_RXMAXP(val)	bfin_write16(USB_EP_NI4_RXMAXP, val)
+#define bfin_read_USB_EP_NI4_RXCSR()		bfin_read16(USB_EP_NI4_RXCSR)
+#define bfin_write_USB_EP_NI4_RXCSR(val)	bfin_write16(USB_EP_NI4_RXCSR, val)
+#define bfin_read_USB_EP_NI4_RXCOUNT()		bfin_read16(USB_EP_NI4_RXCOUNT)
+#define bfin_write_USB_EP_NI4_RXCOUNT(val)	bfin_write16(USB_EP_NI4_RXCOUNT, val)
+#define bfin_read_USB_EP_NI4_TXTYPE()		bfin_read16(USB_EP_NI4_TXTYPE)
+#define bfin_write_USB_EP_NI4_TXTYPE(val)	bfin_write16(USB_EP_NI4_TXTYPE, val)
+#define bfin_read_USB_EP_NI4_TXINTERVAL()	bfin_read16(USB_EP_NI4_TXINTERVAL)
+#define bfin_write_USB_EP_NI4_TXINTERVAL(val)	bfin_write16(USB_EP_NI4_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI4_RXTYPE()		bfin_read16(USB_EP_NI4_RXTYPE)
+#define bfin_write_USB_EP_NI4_RXTYPE(val)	bfin_write16(USB_EP_NI4_RXTYPE, val)
+#define bfin_read_USB_EP_NI4_RXINTERVAL()	bfin_read16(USB_EP_NI4_RXINTERVAL)
+#define bfin_write_USB_EP_NI4_RXINTERVAL(val)	bfin_write16(USB_EP_NI4_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 5 Control Registers */
+
+#define bfin_read_USB_EP_NI4_TXCOUNT()		bfin_read16(USB_EP_NI4_TXCOUNT)
+#define bfin_write_USB_EP_NI4_TXCOUNT(val)	bfin_write16(USB_EP_NI4_TXCOUNT, val)
+#define bfin_read_USB_EP_NI5_TXMAXP()		bfin_read16(USB_EP_NI5_TXMAXP)
+#define bfin_write_USB_EP_NI5_TXMAXP(val)	bfin_write16(USB_EP_NI5_TXMAXP, val)
+#define bfin_read_USB_EP_NI5_TXCSR()		bfin_read16(USB_EP_NI5_TXCSR)
+#define bfin_write_USB_EP_NI5_TXCSR(val)	bfin_write16(USB_EP_NI5_TXCSR, val)
+#define bfin_read_USB_EP_NI5_RXMAXP()		bfin_read16(USB_EP_NI5_RXMAXP)
+#define bfin_write_USB_EP_NI5_RXMAXP(val)	bfin_write16(USB_EP_NI5_RXMAXP, val)
+#define bfin_read_USB_EP_NI5_RXCSR()		bfin_read16(USB_EP_NI5_RXCSR)
+#define bfin_write_USB_EP_NI5_RXCSR(val)	bfin_write16(USB_EP_NI5_RXCSR, val)
+#define bfin_read_USB_EP_NI5_RXCOUNT()		bfin_read16(USB_EP_NI5_RXCOUNT)
+#define bfin_write_USB_EP_NI5_RXCOUNT(val)	bfin_write16(USB_EP_NI5_RXCOUNT, val)
+#define bfin_read_USB_EP_NI5_TXTYPE()		bfin_read16(USB_EP_NI5_TXTYPE)
+#define bfin_write_USB_EP_NI5_TXTYPE(val)	bfin_write16(USB_EP_NI5_TXTYPE, val)
+#define bfin_read_USB_EP_NI5_TXINTERVAL()	bfin_read16(USB_EP_NI5_TXINTERVAL)
+#define bfin_write_USB_EP_NI5_TXINTERVAL(val)	bfin_write16(USB_EP_NI5_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI5_RXTYPE()		bfin_read16(USB_EP_NI5_RXTYPE)
+#define bfin_write_USB_EP_NI5_RXTYPE(val)	bfin_write16(USB_EP_NI5_RXTYPE, val)
+#define bfin_read_USB_EP_NI5_RXINTERVAL()	bfin_read16(USB_EP_NI5_RXINTERVAL)
+#define bfin_write_USB_EP_NI5_RXINTERVAL(val)	bfin_write16(USB_EP_NI5_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 6 Control Registers */
+
+#define bfin_read_USB_EP_NI5_TXCOUNT()		bfin_read16(USB_EP_NI5_TXCOUNT)
+#define bfin_write_USB_EP_NI5_TXCOUNT(val)	bfin_write16(USB_EP_NI5_TXCOUNT, val)
+#define bfin_read_USB_EP_NI6_TXMAXP()		bfin_read16(USB_EP_NI6_TXMAXP)
+#define bfin_write_USB_EP_NI6_TXMAXP(val)	bfin_write16(USB_EP_NI6_TXMAXP, val)
+#define bfin_read_USB_EP_NI6_TXCSR()		bfin_read16(USB_EP_NI6_TXCSR)
+#define bfin_write_USB_EP_NI6_TXCSR(val)	bfin_write16(USB_EP_NI6_TXCSR, val)
+#define bfin_read_USB_EP_NI6_RXMAXP()		bfin_read16(USB_EP_NI6_RXMAXP)
+#define bfin_write_USB_EP_NI6_RXMAXP(val)	bfin_write16(USB_EP_NI6_RXMAXP, val)
+#define bfin_read_USB_EP_NI6_RXCSR()		bfin_read16(USB_EP_NI6_RXCSR)
+#define bfin_write_USB_EP_NI6_RXCSR(val)	bfin_write16(USB_EP_NI6_RXCSR, val)
+#define bfin_read_USB_EP_NI6_RXCOUNT()		bfin_read16(USB_EP_NI6_RXCOUNT)
+#define bfin_write_USB_EP_NI6_RXCOUNT(val)	bfin_write16(USB_EP_NI6_RXCOUNT, val)
+#define bfin_read_USB_EP_NI6_TXTYPE()		bfin_read16(USB_EP_NI6_TXTYPE)
+#define bfin_write_USB_EP_NI6_TXTYPE(val)	bfin_write16(USB_EP_NI6_TXTYPE, val)
+#define bfin_read_USB_EP_NI6_TXINTERVAL()	bfin_read16(USB_EP_NI6_TXINTERVAL)
+#define bfin_write_USB_EP_NI6_TXINTERVAL(val)	bfin_write16(USB_EP_NI6_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI6_RXTYPE()		bfin_read16(USB_EP_NI6_RXTYPE)
+#define bfin_write_USB_EP_NI6_RXTYPE(val)	bfin_write16(USB_EP_NI6_RXTYPE, val)
+#define bfin_read_USB_EP_NI6_RXINTERVAL()	bfin_read16(USB_EP_NI6_RXINTERVAL)
+#define bfin_write_USB_EP_NI6_RXINTERVAL(val)	bfin_write16(USB_EP_NI6_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 7 Control Registers */
+
+#define bfin_read_USB_EP_NI6_TXCOUNT()		bfin_read16(USB_EP_NI6_TXCOUNT)
+#define bfin_write_USB_EP_NI6_TXCOUNT(val)	bfin_write16(USB_EP_NI6_TXCOUNT, val)
+#define bfin_read_USB_EP_NI7_TXMAXP()		bfin_read16(USB_EP_NI7_TXMAXP)
+#define bfin_write_USB_EP_NI7_TXMAXP(val)	bfin_write16(USB_EP_NI7_TXMAXP, val)
+#define bfin_read_USB_EP_NI7_TXCSR()		bfin_read16(USB_EP_NI7_TXCSR)
+#define bfin_write_USB_EP_NI7_TXCSR(val)	bfin_write16(USB_EP_NI7_TXCSR, val)
+#define bfin_read_USB_EP_NI7_RXMAXP()		bfin_read16(USB_EP_NI7_RXMAXP)
+#define bfin_write_USB_EP_NI7_RXMAXP(val)	bfin_write16(USB_EP_NI7_RXMAXP, val)
+#define bfin_read_USB_EP_NI7_RXCSR()		bfin_read16(USB_EP_NI7_RXCSR)
+#define bfin_write_USB_EP_NI7_RXCSR(val)	bfin_write16(USB_EP_NI7_RXCSR, val)
+#define bfin_read_USB_EP_NI7_RXCOUNT()		bfin_read16(USB_EP_NI7_RXCOUNT)
+#define bfin_write_USB_EP_NI7_RXCOUNT(val)	bfin_write16(USB_EP_NI7_RXCOUNT, val)
+#define bfin_read_USB_EP_NI7_TXTYPE()		bfin_read16(USB_EP_NI7_TXTYPE)
+#define bfin_write_USB_EP_NI7_TXTYPE(val)	bfin_write16(USB_EP_NI7_TXTYPE, val)
+#define bfin_read_USB_EP_NI7_TXINTERVAL()	bfin_read16(USB_EP_NI7_TXINTERVAL)
+#define bfin_write_USB_EP_NI7_TXINTERVAL(val)	bfin_write16(USB_EP_NI7_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_RXTYPE()		bfin_read16(USB_EP_NI7_RXTYPE)
+#define bfin_write_USB_EP_NI7_RXTYPE(val)	bfin_write16(USB_EP_NI7_RXTYPE, val)
+#define bfin_read_USB_EP_NI7_RXINTERVAL()	bfin_read16(USB_EP_NI7_RXINTERVAL)
+#define bfin_write_USB_EP_NI7_RXINTERVAL(val)	bfin_write16(USB_EP_NI7_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_TXCOUNT()		bfin_read16(USB_EP_NI7_TXCOUNT)
+#define bfin_write_USB_EP_NI7_TXCOUNT(val)	bfin_write16(USB_EP_NI7_TXCOUNT, val)
+#define bfin_read_USB_DMA_INTERRUPT()		bfin_read16(USB_DMA_INTERRUPT)
+#define bfin_write_USB_DMA_INTERRUPT(val)	bfin_write16(USB_DMA_INTERRUPT, val)
+
+/* USB Channel 0 Config Registers */
+
+#define bfin_read_USB_DMA0CONTROL()		bfin_read16(USB_DMA0CONTROL)
+#define bfin_write_USB_DMA0CONTROL(val)		bfin_write16(USB_DMA0CONTROL, val)
+#define bfin_read_USB_DMA0ADDRLOW()		bfin_read16(USB_DMA0ADDRLOW)
+#define bfin_write_USB_DMA0ADDRLOW(val)		bfin_write16(USB_DMA0ADDRLOW, val)
+#define bfin_read_USB_DMA0ADDRHIGH()		bfin_read16(USB_DMA0ADDRHIGH)
+#define bfin_write_USB_DMA0ADDRHIGH(val)	bfin_write16(USB_DMA0ADDRHIGH, val)
+#define bfin_read_USB_DMA0COUNTLOW()		bfin_read16(USB_DMA0COUNTLOW)
+#define bfin_write_USB_DMA0COUNTLOW(val)	bfin_write16(USB_DMA0COUNTLOW, val)
+#define bfin_read_USB_DMA0COUNTHIGH()		bfin_read16(USB_DMA0COUNTHIGH)
+#define bfin_write_USB_DMA0COUNTHIGH(val)	bfin_write16(USB_DMA0COUNTHIGH, val)
+
+/* USB Channel 1 Config Registers */
+
+#define bfin_read_USB_DMA1CONTROL()		bfin_read16(USB_DMA1CONTROL)
+#define bfin_write_USB_DMA1CONTROL(val)		bfin_write16(USB_DMA1CONTROL, val)
+#define bfin_read_USB_DMA1ADDRLOW()		bfin_read16(USB_DMA1ADDRLOW)
+#define bfin_write_USB_DMA1ADDRLOW(val)		bfin_write16(USB_DMA1ADDRLOW, val)
+#define bfin_read_USB_DMA1ADDRHIGH()		bfin_read16(USB_DMA1ADDRHIGH)
+#define bfin_write_USB_DMA1ADDRHIGH(val)	bfin_write16(USB_DMA1ADDRHIGH, val)
+#define bfin_read_USB_DMA1COUNTLOW()		bfin_read16(USB_DMA1COUNTLOW)
+#define bfin_write_USB_DMA1COUNTLOW(val)	bfin_write16(USB_DMA1COUNTLOW, val)
+#define bfin_read_USB_DMA1COUNTHIGH()		bfin_read16(USB_DMA1COUNTHIGH)
+#define bfin_write_USB_DMA1COUNTHIGH(val)	bfin_write16(USB_DMA1COUNTHIGH, val)
+
+/* USB Channel 2 Config Registers */
+
+#define bfin_read_USB_DMA2CONTROL()		bfin_read16(USB_DMA2CONTROL)
+#define bfin_write_USB_DMA2CONTROL(val)		bfin_write16(USB_DMA2CONTROL, val)
+#define bfin_read_USB_DMA2ADDRLOW()		bfin_read16(USB_DMA2ADDRLOW)
+#define bfin_write_USB_DMA2ADDRLOW(val)		bfin_write16(USB_DMA2ADDRLOW, val)
+#define bfin_read_USB_DMA2ADDRHIGH()		bfin_read16(USB_DMA2ADDRHIGH)
+#define bfin_write_USB_DMA2ADDRHIGH(val)	bfin_write16(USB_DMA2ADDRHIGH, val)
+#define bfin_read_USB_DMA2COUNTLOW()		bfin_read16(USB_DMA2COUNTLOW)
+#define bfin_write_USB_DMA2COUNTLOW(val)	bfin_write16(USB_DMA2COUNTLOW, val)
+#define bfin_read_USB_DMA2COUNTHIGH()		bfin_read16(USB_DMA2COUNTHIGH)
+#define bfin_write_USB_DMA2COUNTHIGH(val)	bfin_write16(USB_DMA2COUNTHIGH, val)
+
+/* USB Channel 3 Config Registers */
+
+#define bfin_read_USB_DMA3CONTROL()		bfin_read16(USB_DMA3CONTROL)
+#define bfin_write_USB_DMA3CONTROL(val)		bfin_write16(USB_DMA3CONTROL, val)
+#define bfin_read_USB_DMA3ADDRLOW()		bfin_read16(USB_DMA3ADDRLOW)
+#define bfin_write_USB_DMA3ADDRLOW(val)		bfin_write16(USB_DMA3ADDRLOW, val)
+#define bfin_read_USB_DMA3ADDRHIGH()		bfin_read16(USB_DMA3ADDRHIGH)
+#define bfin_write_USB_DMA3ADDRHIGH(val)	bfin_write16(USB_DMA3ADDRHIGH, val)
+#define bfin_read_USB_DMA3COUNTLOW()		bfin_read16(USB_DMA3COUNTLOW)
+#define bfin_write_USB_DMA3COUNTLOW(val)	bfin_write16(USB_DMA3COUNTLOW, val)
+#define bfin_read_USB_DMA3COUNTHIGH()		bfin_read16(USB_DMA3COUNTHIGH)
+#define bfin_write_USB_DMA3COUNTHIGH(val)	bfin_write16(USB_DMA3COUNTHIGH, val)
+
+/* USB Channel 4 Config Registers */
+
+#define bfin_read_USB_DMA4CONTROL()		bfin_read16(USB_DMA4CONTROL)
+#define bfin_write_USB_DMA4CONTROL(val)		bfin_write16(USB_DMA4CONTROL, val)
+#define bfin_read_USB_DMA4ADDRLOW()		bfin_read16(USB_DMA4ADDRLOW)
+#define bfin_write_USB_DMA4ADDRLOW(val)		bfin_write16(USB_DMA4ADDRLOW, val)
+#define bfin_read_USB_DMA4ADDRHIGH()		bfin_read16(USB_DMA4ADDRHIGH)
+#define bfin_write_USB_DMA4ADDRHIGH(val)	bfin_write16(USB_DMA4ADDRHIGH, val)
+#define bfin_read_USB_DMA4COUNTLOW()		bfin_read16(USB_DMA4COUNTLOW)
+#define bfin_write_USB_DMA4COUNTLOW(val)	bfin_write16(USB_DMA4COUNTLOW, val)
+#define bfin_read_USB_DMA4COUNTHIGH()		bfin_read16(USB_DMA4COUNTHIGH)
+#define bfin_write_USB_DMA4COUNTHIGH(val)	bfin_write16(USB_DMA4COUNTHIGH, val)
+
+/* USB Channel 5 Config Registers */
+
+#define bfin_read_USB_DMA5CONTROL()		bfin_read16(USB_DMA5CONTROL)
+#define bfin_write_USB_DMA5CONTROL(val)		bfin_write16(USB_DMA5CONTROL, val)
+#define bfin_read_USB_DMA5ADDRLOW()		bfin_read16(USB_DMA5ADDRLOW)
+#define bfin_write_USB_DMA5ADDRLOW(val)		bfin_write16(USB_DMA5ADDRLOW, val)
+#define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
+#define bfin_write_USB_DMA5ADDRHIGH(val)	bfin_write16(USB_DMA5ADDRHIGH, val)
+#define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
+#define bfin_write_USB_DMA5COUNTLOW(val)	bfin_write16(USB_DMA5COUNTLOW, val)
+#define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
+#define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
+
+/* USB Channel 6 Config Registers */
+
+#define bfin_read_USB_DMA6CONTROL()		bfin_read16(USB_DMA6CONTROL)
+#define bfin_write_USB_DMA6CONTROL(val)		bfin_write16(USB_DMA6CONTROL, val)
+#define bfin_read_USB_DMA6ADDRLOW()		bfin_read16(USB_DMA6ADDRLOW)
+#define bfin_write_USB_DMA6ADDRLOW(val)		bfin_write16(USB_DMA6ADDRLOW, val)
+#define bfin_read_USB_DMA6ADDRHIGH()		bfin_read16(USB_DMA6ADDRHIGH)
+#define bfin_write_USB_DMA6ADDRHIGH(val)	bfin_write16(USB_DMA6ADDRHIGH, val)
+#define bfin_read_USB_DMA6COUNTLOW()		bfin_read16(USB_DMA6COUNTLOW)
+#define bfin_write_USB_DMA6COUNTLOW(val)	bfin_write16(USB_DMA6COUNTLOW, val)
+#define bfin_read_USB_DMA6COUNTHIGH()		bfin_read16(USB_DMA6COUNTHIGH)
+#define bfin_write_USB_DMA6COUNTHIGH(val)	bfin_write16(USB_DMA6COUNTHIGH, val)
+
+/* USB Channel 7 Config Registers */
+
+#define bfin_read_USB_DMA7CONTROL()		bfin_read16(USB_DMA7CONTROL)
+#define bfin_write_USB_DMA7CONTROL(val)		bfin_write16(USB_DMA7CONTROL, val)
+#define bfin_read_USB_DMA7ADDRLOW()		bfin_read16(USB_DMA7ADDRLOW)
+#define bfin_write_USB_DMA7ADDRLOW(val)		bfin_write16(USB_DMA7ADDRLOW, val)
+#define bfin_read_USB_DMA7ADDRHIGH()		bfin_read16(USB_DMA7ADDRHIGH)
+#define bfin_write_USB_DMA7ADDRHIGH(val)	bfin_write16(USB_DMA7ADDRHIGH, val)
+#define bfin_read_USB_DMA7COUNTLOW()		bfin_read16(USB_DMA7COUNTLOW)
+#define bfin_write_USB_DMA7COUNTLOW(val)	bfin_write16(USB_DMA7COUNTLOW, val)
+#define bfin_read_USB_DMA7COUNTHIGH()		bfin_read16(USB_DMA7COUNTHIGH)
+#define bfin_write_USB_DMA7COUNTHIGH(val)	bfin_write16(USB_DMA7COUNTHIGH, val)
+
+/* Keybfin_read_()ad Registers */
+
+#define bfin_read_KPAD_CTL()			bfin_read16(KPAD_CTL)
+#define bfin_write_KPAD_CTL(val)		bfin_write16(KPAD_CTL, val)
+#define bfin_read_KPAD_PRESCALE()		bfin_read16(KPAD_PRESCALE)
+#define bfin_write_KPAD_PRESCALE(val)		bfin_write16(KPAD_PRESCALE, val)
+#define bfin_read_KPAD_MSEL()			bfin_read16(KPAD_MSEL)
+#define bfin_write_KPAD_MSEL(val)		bfin_write16(KPAD_MSEL, val)
+#define bfin_read_KPAD_ROWCOL()			bfin_read16(KPAD_ROWCOL)
+#define bfin_write_KPAD_ROWCOL(val)		bfin_write16(KPAD_ROWCOL, val)
+#define bfin_read_KPAD_STAT()			bfin_read16(KPAD_STAT)
+#define bfin_write_KPAD_STAT(val)		bfin_write16(KPAD_STAT, val)
+#define bfin_read_KPAD_SOFTEVAL()		bfin_read16(KPAD_SOFTEVAL)
+#define bfin_write_KPAD_SOFTEVAL(val)		bfin_write16(KPAD_SOFTEVAL, val)
+
+#endif /* _CDEF_BF542_H */
diff --git a/include/asm-blackfin/mach-bf548/cdefBF544.h b/include/asm-blackfin/mach-bf548/cdefBF544.h
new file mode 100644
index 0000000..7a2d177
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/cdefBF544.h
@@ -0,0 +1,978 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/cdefBF544.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF544_H
+#define _CDEF_BF544_H
+
+/* include all Core registers and bit definitions */
+#include "defBF544.h"
+
+/* include core sbfin_read_()ecific register pointer definitions */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF544 */
+
+/* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
+#include "cdefBF54x_base.h"
+
+/* The following are the #defines needed by ADSP-BF544 that are not in the common header */
+
+/* Timer Registers */
+
+#define bfin_read_TIMER8_CONFIG()		bfin_read16(TIMER8_CONFIG)
+#define bfin_write_TIMER8_CONFIG(val)		bfin_write16(TIMER8_CONFIG, val)
+#define bfin_read_TIMER8_COUNTER()		bfin_read32(TIMER8_COUNTER)
+#define bfin_write_TIMER8_COUNTER(val)		bfin_write32(TIMER8_COUNTER, val)
+#define bfin_read_TIMER8_PERIOD()		bfin_read32(TIMER8_PERIOD)
+#define bfin_write_TIMER8_PERIOD(val)		bfin_write32(TIMER8_PERIOD, val)
+#define bfin_read_TIMER8_WIDTH()		bfin_read32(TIMER8_WIDTH)
+#define bfin_write_TIMER8_WIDTH(val)		bfin_write32(TIMER8_WIDTH, val)
+#define bfin_read_TIMER9_CONFIG()		bfin_read16(TIMER9_CONFIG)
+#define bfin_write_TIMER9_CONFIG(val)		bfin_write16(TIMER9_CONFIG, val)
+#define bfin_read_TIMER9_COUNTER()		bfin_read32(TIMER9_COUNTER)
+#define bfin_write_TIMER9_COUNTER(val)		bfin_write32(TIMER9_COUNTER, val)
+#define bfin_read_TIMER9_PERIOD()		bfin_read32(TIMER9_PERIOD)
+#define bfin_write_TIMER9_PERIOD(val)		bfin_write32(TIMER9_PERIOD, val)
+#define bfin_read_TIMER9_WIDTH()		bfin_read32(TIMER9_WIDTH)
+#define bfin_write_TIMER9_WIDTH(val)		bfin_write32(TIMER9_WIDTH, val)
+#define bfin_read_TIMER10_CONFIG()		bfin_read16(TIMER10_CONFIG)
+#define bfin_write_TIMER10_CONFIG(val)		bfin_write16(TIMER10_CONFIG, val)
+#define bfin_read_TIMER10_COUNTER()		bfin_read32(TIMER10_COUNTER)
+#define bfin_write_TIMER10_COUNTER(val)		bfin_write32(TIMER10_COUNTER, val)
+#define bfin_read_TIMER10_PERIOD()		bfin_read32(TIMER10_PERIOD)
+#define bfin_write_TIMER10_PERIOD(val)		bfin_write32(TIMER10_PERIOD, val)
+#define bfin_read_TIMER10_WIDTH()		bfin_read32(TIMER10_WIDTH)
+#define bfin_write_TIMER10_WIDTH(val)		bfin_write32(TIMER10_WIDTH, val)
+
+/* Timer Groubfin_read_() of 3 */
+
+#define bfin_read_TIMER_ENABLE1()		bfin_read16(TIMER_ENABLE1)
+#define bfin_write_TIMER_ENABLE1(val)		bfin_write16(TIMER_ENABLE1, val)
+#define bfin_read_TIMER_DISABLE1()		bfin_read16(TIMER_DISABLE1)
+#define bfin_write_TIMER_DISABLE1(val)		bfin_write16(TIMER_DISABLE1, val)
+#define bfin_read_TIMER_STATUS1()		bfin_read32(TIMER_STATUS1)
+#define bfin_write_TIMER_STATUS1(val)		bfin_write32(TIMER_STATUS1, val)
+
+/* EPPI0 Registers */
+
+#define bfin_read_EPPI0_STATUS()		bfin_read16(EPPI0_STATUS)
+#define bfin_write_EPPI0_STATUS(val)		bfin_write16(EPPI0_STATUS, val)
+#define bfin_read_EPPI0_HCOUNT()		bfin_read16(EPPI0_HCOUNT)
+#define bfin_write_EPPI0_HCOUNT(val)		bfin_write16(EPPI0_HCOUNT, val)
+#define bfin_read_EPPI0_HDELAY()		bfin_read16(EPPI0_HDELAY)
+#define bfin_write_EPPI0_HDELAY(val)		bfin_write16(EPPI0_HDELAY, val)
+#define bfin_read_EPPI0_VCOUNT()		bfin_read16(EPPI0_VCOUNT)
+#define bfin_write_EPPI0_VCOUNT(val)		bfin_write16(EPPI0_VCOUNT, val)
+#define bfin_read_EPPI0_VDELAY()		bfin_read16(EPPI0_VDELAY)
+#define bfin_write_EPPI0_VDELAY(val)		bfin_write16(EPPI0_VDELAY, val)
+#define bfin_read_EPPI0_FRAME()			bfin_read16(EPPI0_FRAME)
+#define bfin_write_EPPI0_FRAME(val)		bfin_write16(EPPI0_FRAME, val)
+#define bfin_read_EPPI0_LINE()			bfin_read16(EPPI0_LINE)
+#define bfin_write_EPPI0_LINE(val)		bfin_write16(EPPI0_LINE, val)
+#define bfin_read_EPPI0_CLKDIV()		bfin_read16(EPPI0_CLKDIV)
+#define bfin_write_EPPI0_CLKDIV(val)		bfin_write16(EPPI0_CLKDIV, val)
+#define bfin_read_EPPI0_CONTROL()		bfin_read32(EPPI0_CONTROL)
+#define bfin_write_EPPI0_CONTROL(val)		bfin_write32(EPPI0_CONTROL, val)
+#define bfin_read_EPPI0_FS1W_HBL()		bfin_read32(EPPI0_FS1W_HBL)
+#define bfin_write_EPPI0_FS1W_HBL(val)		bfin_write32(EPPI0_FS1W_HBL, val)
+#define bfin_read_EPPI0_FS1P_AVPL()		bfin_read32(EPPI0_FS1P_AVPL)
+#define bfin_write_EPPI0_FS1P_AVPL(val)		bfin_write32(EPPI0_FS1P_AVPL, val)
+#define bfin_read_EPPI0_FS2W_LVB()		bfin_read32(EPPI0_FS2W_LVB)
+#define bfin_write_EPPI0_FS2W_LVB(val)		bfin_write32(EPPI0_FS2W_LVB, val)
+#define bfin_read_EPPI0_FS2P_LAVF()		bfin_read32(EPPI0_FS2P_LAVF)
+#define bfin_write_EPPI0_FS2P_LAVF(val)		bfin_write32(EPPI0_FS2P_LAVF, val)
+#define bfin_read_EPPI0_CLIP()			bfin_read32(EPPI0_CLIP)
+#define bfin_write_EPPI0_CLIP(val)		bfin_write32(EPPI0_CLIP, val)
+
+/* Two Wire Interface Registers (TWI1) */
+
+#define bfin_read_TWI1_CLKDIV()			bfin_read16(TWI1_CLKDIV)
+#define bfin_write_TWI1_CLKDIV(val)		bfin_write16(TWI1_CLKDIV, val)
+#define bfin_read_TWI1_CONTROL()		bfin_read16(TWI1_CONTROL)
+#define bfin_write_TWI1_CONTROL(val)		bfin_write16(TWI1_CONTROL, val)
+#define bfin_read_TWI1_SLAVE_CTRL()		bfin_read16(TWI1_SLAVE_CTRL)
+#define bfin_write_TWI1_SLAVE_CTRL(val)		bfin_write16(TWI1_SLAVE_CTRL, val)
+#define bfin_read_TWI1_SLAVE_STAT()		bfin_read16(TWI1_SLAVE_STAT)
+#define bfin_write_TWI1_SLAVE_STAT(val)		bfin_write16(TWI1_SLAVE_STAT, val)
+#define bfin_read_TWI1_SLAVE_ADDR()		bfin_read16(TWI1_SLAVE_ADDR)
+#define bfin_write_TWI1_SLAVE_ADDR(val)		bfin_write16(TWI1_SLAVE_ADDR, val)
+#define bfin_read_TWI1_MASTER_CTRL()		bfin_read16(TWI1_MASTER_CTRL)
+#define bfin_write_TWI1_MASTER_CTRL(val)	bfin_write16(TWI1_MASTER_CTRL, val)
+#define bfin_read_TWI1_MASTER_STAT()		bfin_read16(TWI1_MASTER_STAT)
+#define bfin_write_TWI1_MASTER_STAT(val)	bfin_write16(TWI1_MASTER_STAT, val)
+#define bfin_read_TWI1_MASTER_ADDR()		bfin_read16(TWI1_MASTER_ADDR)
+#define bfin_write_TWI1_MASTER_ADDR(val)	bfin_write16(TWI1_MASTER_ADDR, val)
+#define bfin_read_TWI1_INT_STAT()		bfin_read16(TWI1_INT_STAT)
+#define bfin_write_TWI1_INT_STAT(val)		bfin_write16(TWI1_INT_STAT, val)
+#define bfin_read_TWI1_INT_MASK()		bfin_read16(TWI1_INT_MASK)
+#define bfin_write_TWI1_INT_MASK(val)		bfin_write16(TWI1_INT_MASK, val)
+#define bfin_read_TWI1_FIFO_CTRL()		bfin_read16(TWI1_FIFO_CTRL)
+#define bfin_write_TWI1_FIFO_CTRL(val)		bfin_write16(TWI1_FIFO_CTRL, val)
+#define bfin_read_TWI1_FIFO_STAT()		bfin_read16(TWI1_FIFO_STAT)
+#define bfin_write_TWI1_FIFO_STAT(val)		bfin_write16(TWI1_FIFO_STAT, val)
+#define bfin_read_TWI1_XMT_DATA8()		bfin_read16(TWI1_XMT_DATA8)
+#define bfin_write_TWI1_XMT_DATA8(val)		bfin_write16(TWI1_XMT_DATA8, val)
+#define bfin_read_TWI1_XMT_DATA16()		bfin_read16(TWI1_XMT_DATA16)
+#define bfin_write_TWI1_XMT_DATA16(val)		bfin_write16(TWI1_XMT_DATA16, val)
+#define bfin_read_TWI1_RCV_DATA8()		bfin_read16(TWI1_RCV_DATA8)
+#define bfin_write_TWI1_RCV_DATA8(val)		bfin_write16(TWI1_RCV_DATA8, val)
+#define bfin_read_TWI1_RCV_DATA16()		bfin_read16(TWI1_RCV_DATA16)
+#define bfin_write_TWI1_RCV_DATA16(val)		bfin_write16(TWI1_RCV_DATA16, val)
+
+/* CAN Controller 1 Config 1 Registers */
+
+#define bfin_read_CAN1_MC1()		bfin_read16(CAN1_MC1)
+#define bfin_write_CAN1_MC1(val)	bfin_write16(CAN1_MC1, val)
+#define bfin_read_CAN1_MD1()		bfin_read16(CAN1_MD1)
+#define bfin_write_CAN1_MD1(val)	bfin_write16(CAN1_MD1, val)
+#define bfin_read_CAN1_TRS1()		bfin_read16(CAN1_TRS1)
+#define bfin_write_CAN1_TRS1(val)	bfin_write16(CAN1_TRS1, val)
+#define bfin_read_CAN1_TRR1()		bfin_read16(CAN1_TRR1)
+#define bfin_write_CAN1_TRR1(val)	bfin_write16(CAN1_TRR1, val)
+#define bfin_read_CAN1_TA1()		bfin_read16(CAN1_TA1)
+#define bfin_write_CAN1_TA1(val)	bfin_write16(CAN1_TA1, val)
+#define bfin_read_CAN1_AA1()		bfin_read16(CAN1_AA1)
+#define bfin_write_CAN1_AA1(val)	bfin_write16(CAN1_AA1, val)
+#define bfin_read_CAN1_RMP1()		bfin_read16(CAN1_RMP1)
+#define bfin_write_CAN1_RMP1(val)	bfin_write16(CAN1_RMP1, val)
+#define bfin_read_CAN1_RML1()		bfin_read16(CAN1_RML1)
+#define bfin_write_CAN1_RML1(val)	bfin_write16(CAN1_RML1, val)
+#define bfin_read_CAN1_MBTIF1()		bfin_read16(CAN1_MBTIF1)
+#define bfin_write_CAN1_MBTIF1(val)	bfin_write16(CAN1_MBTIF1, val)
+#define bfin_read_CAN1_MBRIF1()		bfin_read16(CAN1_MBRIF1)
+#define bfin_write_CAN1_MBRIF1(val)	bfin_write16(CAN1_MBRIF1, val)
+#define bfin_read_CAN1_MBIM1()		bfin_read16(CAN1_MBIM1)
+#define bfin_write_CAN1_MBIM1(val)	bfin_write16(CAN1_MBIM1, val)
+#define bfin_read_CAN1_RFH1()		bfin_read16(CAN1_RFH1)
+#define bfin_write_CAN1_RFH1(val)	bfin_write16(CAN1_RFH1, val)
+#define bfin_read_CAN1_OPSS1()		bfin_read16(CAN1_OPSS1)
+#define bfin_write_CAN1_OPSS1(val)	bfin_write16(CAN1_OPSS1, val)
+
+/* CAN Controller 1 Config 2 Registers */
+
+#define bfin_read_CAN1_MC2()		bfin_read16(CAN1_MC2)
+#define bfin_write_CAN1_MC2(val)	bfin_write16(CAN1_MC2, val)
+#define bfin_read_CAN1_MD2()		bfin_read16(CAN1_MD2)
+#define bfin_write_CAN1_MD2(val)	bfin_write16(CAN1_MD2, val)
+#define bfin_read_CAN1_TRS2()		bfin_read16(CAN1_TRS2)
+#define bfin_write_CAN1_TRS2(val)	bfin_write16(CAN1_TRS2, val)
+#define bfin_read_CAN1_TRR2()		bfin_read16(CAN1_TRR2)
+#define bfin_write_CAN1_TRR2(val)	bfin_write16(CAN1_TRR2, val)
+#define bfin_read_CAN1_TA2()		bfin_read16(CAN1_TA2)
+#define bfin_write_CAN1_TA2(val)	bfin_write16(CAN1_TA2, val)
+#define bfin_read_CAN1_AA2()		bfin_read16(CAN1_AA2)
+#define bfin_write_CAN1_AA2(val)	bfin_write16(CAN1_AA2, val)
+#define bfin_read_CAN1_RMP2()		bfin_read16(CAN1_RMP2)
+#define bfin_write_CAN1_RMP2(val)	bfin_write16(CAN1_RMP2, val)
+#define bfin_read_CAN1_RML2()		bfin_read16(CAN1_RML2)
+#define bfin_write_CAN1_RML2(val)	bfin_write16(CAN1_RML2, val)
+#define bfin_read_CAN1_MBTIF2()		bfin_read16(CAN1_MBTIF2)
+#define bfin_write_CAN1_MBTIF2(val)	bfin_write16(CAN1_MBTIF2, val)
+#define bfin_read_CAN1_MBRIF2()		bfin_read16(CAN1_MBRIF2)
+#define bfin_write_CAN1_MBRIF2(val)	bfin_write16(CAN1_MBRIF2, val)
+#define bfin_read_CAN1_MBIM2()		bfin_read16(CAN1_MBIM2)
+#define bfin_write_CAN1_MBIM2(val)	bfin_write16(CAN1_MBIM2, val)
+#define bfin_read_CAN1_RFH2()		bfin_read16(CAN1_RFH2)
+#define bfin_write_CAN1_RFH2(val)	bfin_write16(CAN1_RFH2, val)
+#define bfin_read_CAN1_OPSS2()		bfin_read16(CAN1_OPSS2)
+#define bfin_write_CAN1_OPSS2(val)	bfin_write16(CAN1_OPSS2, val)
+
+/* CAN Controller 1 Clock/Interrubfin_read_()t/Counter Registers */
+
+#define bfin_read_CAN1_CLOCK()		bfin_read16(CAN1_CLOCK)
+#define bfin_write_CAN1_CLOCK(val)	bfin_write16(CAN1_CLOCK, val)
+#define bfin_read_CAN1_TIMING()		bfin_read16(CAN1_TIMING)
+#define bfin_write_CAN1_TIMING(val)	bfin_write16(CAN1_TIMING, val)
+#define bfin_read_CAN1_DEBUG()		bfin_read16(CAN1_DEBUG)
+#define bfin_write_CAN1_DEBUG(val)	bfin_write16(CAN1_DEBUG, val)
+#define bfin_read_CAN1_STATUS()		bfin_read16(CAN1_STATUS)
+#define bfin_write_CAN1_STATUS(val)	bfin_write16(CAN1_STATUS, val)
+#define bfin_read_CAN1_CEC()		bfin_read16(CAN1_CEC)
+#define bfin_write_CAN1_CEC(val)	bfin_write16(CAN1_CEC, val)
+#define bfin_read_CAN1_GIS()		bfin_read16(CAN1_GIS)
+#define bfin_write_CAN1_GIS(val)	bfin_write16(CAN1_GIS, val)
+#define bfin_read_CAN1_GIM()		bfin_read16(CAN1_GIM)
+#define bfin_write_CAN1_GIM(val)	bfin_write16(CAN1_GIM, val)
+#define bfin_read_CAN1_GIF()		bfin_read16(CAN1_GIF)
+#define bfin_write_CAN1_GIF(val)	bfin_write16(CAN1_GIF, val)
+#define bfin_read_CAN1_CONTROL()	bfin_read16(CAN1_CONTROL)
+#define bfin_write_CAN1_CONTROL(val)	bfin_write16(CAN1_CONTROL, val)
+#define bfin_read_CAN1_INTR()		bfin_read16(CAN1_INTR)
+#define bfin_write_CAN1_INTR(val)	bfin_write16(CAN1_INTR, val)
+#define bfin_read_CAN1_MBTD()		bfin_read16(CAN1_MBTD)
+#define bfin_write_CAN1_MBTD(val)	bfin_write16(CAN1_MBTD, val)
+#define bfin_read_CAN1_EWR()		bfin_read16(CAN1_EWR)
+#define bfin_write_CAN1_EWR(val)	bfin_write16(CAN1_EWR, val)
+#define bfin_read_CAN1_ESR()		bfin_read16(CAN1_ESR)
+#define bfin_write_CAN1_ESR(val)	bfin_write16(CAN1_ESR, val)
+#define bfin_read_CAN1_UCCNT()		bfin_read16(CAN1_UCCNT)
+#define bfin_write_CAN1_UCCNT(val)	bfin_write16(CAN1_UCCNT, val)
+#define bfin_read_CAN1_UCRC()		bfin_read16(CAN1_UCRC)
+#define bfin_write_CAN1_UCRC(val)	bfin_write16(CAN1_UCRC, val)
+#define bfin_read_CAN1_UCCNF()		bfin_read16(CAN1_UCCNF)
+#define bfin_write_CAN1_UCCNF(val)	bfin_write16(CAN1_UCCNF, val)
+
+/* CAN Controller 1 Mailbox Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN1_AM00L()		bfin_read16(CAN1_AM00L)
+#define bfin_write_CAN1_AM00L(val)	bfin_write16(CAN1_AM00L, val)
+#define bfin_read_CAN1_AM00H()		bfin_read16(CAN1_AM00H)
+#define bfin_write_CAN1_AM00H(val)	bfin_write16(CAN1_AM00H, val)
+#define bfin_read_CAN1_AM01L()		bfin_read16(CAN1_AM01L)
+#define bfin_write_CAN1_AM01L(val)	bfin_write16(CAN1_AM01L, val)
+#define bfin_read_CAN1_AM01H()		bfin_read16(CAN1_AM01H)
+#define bfin_write_CAN1_AM01H(val)	bfin_write16(CAN1_AM01H, val)
+#define bfin_read_CAN1_AM02L()		bfin_read16(CAN1_AM02L)
+#define bfin_write_CAN1_AM02L(val)	bfin_write16(CAN1_AM02L, val)
+#define bfin_read_CAN1_AM02H()		bfin_read16(CAN1_AM02H)
+#define bfin_write_CAN1_AM02H(val)	bfin_write16(CAN1_AM02H, val)
+#define bfin_read_CAN1_AM03L()		bfin_read16(CAN1_AM03L)
+#define bfin_write_CAN1_AM03L(val)	bfin_write16(CAN1_AM03L, val)
+#define bfin_read_CAN1_AM03H()		bfin_read16(CAN1_AM03H)
+#define bfin_write_CAN1_AM03H(val)	bfin_write16(CAN1_AM03H, val)
+#define bfin_read_CAN1_AM04L()		bfin_read16(CAN1_AM04L)
+#define bfin_write_CAN1_AM04L(val)	bfin_write16(CAN1_AM04L, val)
+#define bfin_read_CAN1_AM04H()		bfin_read16(CAN1_AM04H)
+#define bfin_write_CAN1_AM04H(val)	bfin_write16(CAN1_AM04H, val)
+#define bfin_read_CAN1_AM05L()		bfin_read16(CAN1_AM05L)
+#define bfin_write_CAN1_AM05L(val)	bfin_write16(CAN1_AM05L, val)
+#define bfin_read_CAN1_AM05H()		bfin_read16(CAN1_AM05H)
+#define bfin_write_CAN1_AM05H(val)	bfin_write16(CAN1_AM05H, val)
+#define bfin_read_CAN1_AM06L()		bfin_read16(CAN1_AM06L)
+#define bfin_write_CAN1_AM06L(val)	bfin_write16(CAN1_AM06L, val)
+#define bfin_read_CAN1_AM06H()		bfin_read16(CAN1_AM06H)
+#define bfin_write_CAN1_AM06H(val)	bfin_write16(CAN1_AM06H, val)
+#define bfin_read_CAN1_AM07L()		bfin_read16(CAN1_AM07L)
+#define bfin_write_CAN1_AM07L(val)	bfin_write16(CAN1_AM07L, val)
+#define bfin_read_CAN1_AM07H()		bfin_read16(CAN1_AM07H)
+#define bfin_write_CAN1_AM07H(val)	bfin_write16(CAN1_AM07H, val)
+#define bfin_read_CAN1_AM08L()		bfin_read16(CAN1_AM08L)
+#define bfin_write_CAN1_AM08L(val)	bfin_write16(CAN1_AM08L, val)
+#define bfin_read_CAN1_AM08H()		bfin_read16(CAN1_AM08H)
+#define bfin_write_CAN1_AM08H(val)	bfin_write16(CAN1_AM08H, val)
+#define bfin_read_CAN1_AM09L()		bfin_read16(CAN1_AM09L)
+#define bfin_write_CAN1_AM09L(val)	bfin_write16(CAN1_AM09L, val)
+#define bfin_read_CAN1_AM09H()		bfin_read16(CAN1_AM09H)
+#define bfin_write_CAN1_AM09H(val)	bfin_write16(CAN1_AM09H, val)
+#define bfin_read_CAN1_AM10L()		bfin_read16(CAN1_AM10L)
+#define bfin_write_CAN1_AM10L(val)	bfin_write16(CAN1_AM10L, val)
+#define bfin_read_CAN1_AM10H()		bfin_read16(CAN1_AM10H)
+#define bfin_write_CAN1_AM10H(val)	bfin_write16(CAN1_AM10H, val)
+#define bfin_read_CAN1_AM11L()		bfin_read16(CAN1_AM11L)
+#define bfin_write_CAN1_AM11L(val)	bfin_write16(CAN1_AM11L, val)
+#define bfin_read_CAN1_AM11H()		bfin_read16(CAN1_AM11H)
+#define bfin_write_CAN1_AM11H(val)	bfin_write16(CAN1_AM11H, val)
+#define bfin_read_CAN1_AM12L()		bfin_read16(CAN1_AM12L)
+#define bfin_write_CAN1_AM12L(val)	bfin_write16(CAN1_AM12L, val)
+#define bfin_read_CAN1_AM12H()		bfin_read16(CAN1_AM12H)
+#define bfin_write_CAN1_AM12H(val)	bfin_write16(CAN1_AM12H, val)
+#define bfin_read_CAN1_AM13L()		bfin_read16(CAN1_AM13L)
+#define bfin_write_CAN1_AM13L(val)	bfin_write16(CAN1_AM13L, val)
+#define bfin_read_CAN1_AM13H()		bfin_read16(CAN1_AM13H)
+#define bfin_write_CAN1_AM13H(val)	bfin_write16(CAN1_AM13H, val)
+#define bfin_read_CAN1_AM14L()		bfin_read16(CAN1_AM14L)
+#define bfin_write_CAN1_AM14L(val)	bfin_write16(CAN1_AM14L, val)
+#define bfin_read_CAN1_AM14H()		bfin_read16(CAN1_AM14H)
+#define bfin_write_CAN1_AM14H(val)	bfin_write16(CAN1_AM14H, val)
+#define bfin_read_CAN1_AM15L()		bfin_read16(CAN1_AM15L)
+#define bfin_write_CAN1_AM15L(val)	bfin_write16(CAN1_AM15L, val)
+#define bfin_read_CAN1_AM15H()		bfin_read16(CAN1_AM15H)
+#define bfin_write_CAN1_AM15H(val)	bfin_write16(CAN1_AM15H, val)
+
+/* CAN Controller 1 Mailbox Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN1_AM16L()		bfin_read16(CAN1_AM16L)
+#define bfin_write_CAN1_AM16L(val)	bfin_write16(CAN1_AM16L, val)
+#define bfin_read_CAN1_AM16H()		bfin_read16(CAN1_AM16H)
+#define bfin_write_CAN1_AM16H(val)	bfin_write16(CAN1_AM16H, val)
+#define bfin_read_CAN1_AM17L()		bfin_read16(CAN1_AM17L)
+#define bfin_write_CAN1_AM17L(val)	bfin_write16(CAN1_AM17L, val)
+#define bfin_read_CAN1_AM17H()		bfin_read16(CAN1_AM17H)
+#define bfin_write_CAN1_AM17H(val)	bfin_write16(CAN1_AM17H, val)
+#define bfin_read_CAN1_AM18L()		bfin_read16(CAN1_AM18L)
+#define bfin_write_CAN1_AM18L(val)	bfin_write16(CAN1_AM18L, val)
+#define bfin_read_CAN1_AM18H()		bfin_read16(CAN1_AM18H)
+#define bfin_write_CAN1_AM18H(val)	bfin_write16(CAN1_AM18H, val)
+#define bfin_read_CAN1_AM19L()		bfin_read16(CAN1_AM19L)
+#define bfin_write_CAN1_AM19L(val)	bfin_write16(CAN1_AM19L, val)
+#define bfin_read_CAN1_AM19H()		bfin_read16(CAN1_AM19H)
+#define bfin_write_CAN1_AM19H(val)	bfin_write16(CAN1_AM19H, val)
+#define bfin_read_CAN1_AM20L()		bfin_read16(CAN1_AM20L)
+#define bfin_write_CAN1_AM20L(val)	bfin_write16(CAN1_AM20L, val)
+#define bfin_read_CAN1_AM20H()		bfin_read16(CAN1_AM20H)
+#define bfin_write_CAN1_AM20H(val)	bfin_write16(CAN1_AM20H, val)
+#define bfin_read_CAN1_AM21L()		bfin_read16(CAN1_AM21L)
+#define bfin_write_CAN1_AM21L(val)	bfin_write16(CAN1_AM21L, val)
+#define bfin_read_CAN1_AM21H()		bfin_read16(CAN1_AM21H)
+#define bfin_write_CAN1_AM21H(val)	bfin_write16(CAN1_AM21H, val)
+#define bfin_read_CAN1_AM22L()		bfin_read16(CAN1_AM22L)
+#define bfin_write_CAN1_AM22L(val)	bfin_write16(CAN1_AM22L, val)
+#define bfin_read_CAN1_AM22H()		bfin_read16(CAN1_AM22H)
+#define bfin_write_CAN1_AM22H(val)	bfin_write16(CAN1_AM22H, val)
+#define bfin_read_CAN1_AM23L()		bfin_read16(CAN1_AM23L)
+#define bfin_write_CAN1_AM23L(val)	bfin_write16(CAN1_AM23L, val)
+#define bfin_read_CAN1_AM23H()		bfin_read16(CAN1_AM23H)
+#define bfin_write_CAN1_AM23H(val)	bfin_write16(CAN1_AM23H, val)
+#define bfin_read_CAN1_AM24L()		bfin_read16(CAN1_AM24L)
+#define bfin_write_CAN1_AM24L(val)	bfin_write16(CAN1_AM24L, val)
+#define bfin_read_CAN1_AM24H()		bfin_read16(CAN1_AM24H)
+#define bfin_write_CAN1_AM24H(val)	bfin_write16(CAN1_AM24H, val)
+#define bfin_read_CAN1_AM25L()		bfin_read16(CAN1_AM25L)
+#define bfin_write_CAN1_AM25L(val)	bfin_write16(CAN1_AM25L, val)
+#define bfin_read_CAN1_AM25H()		bfin_read16(CAN1_AM25H)
+#define bfin_write_CAN1_AM25H(val)	bfin_write16(CAN1_AM25H, val)
+#define bfin_read_CAN1_AM26L()		bfin_read16(CAN1_AM26L)
+#define bfin_write_CAN1_AM26L(val)	bfin_write16(CAN1_AM26L, val)
+#define bfin_read_CAN1_AM26H()		bfin_read16(CAN1_AM26H)
+#define bfin_write_CAN1_AM26H(val)	bfin_write16(CAN1_AM26H, val)
+#define bfin_read_CAN1_AM27L()		bfin_read16(CAN1_AM27L)
+#define bfin_write_CAN1_AM27L(val)	bfin_write16(CAN1_AM27L, val)
+#define bfin_read_CAN1_AM27H()		bfin_read16(CAN1_AM27H)
+#define bfin_write_CAN1_AM27H(val)	bfin_write16(CAN1_AM27H, val)
+#define bfin_read_CAN1_AM28L()		bfin_read16(CAN1_AM28L)
+#define bfin_write_CAN1_AM28L(val)	bfin_write16(CAN1_AM28L, val)
+#define bfin_read_CAN1_AM28H()		bfin_read16(CAN1_AM28H)
+#define bfin_write_CAN1_AM28H(val)	bfin_write16(CAN1_AM28H, val)
+#define bfin_read_CAN1_AM29L()		bfin_read16(CAN1_AM29L)
+#define bfin_write_CAN1_AM29L(val)	bfin_write16(CAN1_AM29L, val)
+#define bfin_read_CAN1_AM29H()		bfin_read16(CAN1_AM29H)
+#define bfin_write_CAN1_AM29H(val)	bfin_write16(CAN1_AM29H, val)
+#define bfin_read_CAN1_AM30L()		bfin_read16(CAN1_AM30L)
+#define bfin_write_CAN1_AM30L(val)	bfin_write16(CAN1_AM30L, val)
+#define bfin_read_CAN1_AM30H()		bfin_read16(CAN1_AM30H)
+#define bfin_write_CAN1_AM30H(val)	bfin_write16(CAN1_AM30H, val)
+#define bfin_read_CAN1_AM31L()		bfin_read16(CAN1_AM31L)
+#define bfin_write_CAN1_AM31L(val)	bfin_write16(CAN1_AM31L, val)
+#define bfin_read_CAN1_AM31H()		bfin_read16(CAN1_AM31H)
+#define bfin_write_CAN1_AM31H(val)	bfin_write16(CAN1_AM31H, val)
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define bfin_read_CAN1_MB00_DATA0()		bfin_read16(CAN1_MB00_DATA0)
+#define bfin_write_CAN1_MB00_DATA0(val)		bfin_write16(CAN1_MB00_DATA0, val)
+#define bfin_read_CAN1_MB00_DATA1()		bfin_read16(CAN1_MB00_DATA1)
+#define bfin_write_CAN1_MB00_DATA1(val)		bfin_write16(CAN1_MB00_DATA1, val)
+#define bfin_read_CAN1_MB00_DATA2()		bfin_read16(CAN1_MB00_DATA2)
+#define bfin_write_CAN1_MB00_DATA2(val)		bfin_write16(CAN1_MB00_DATA2, val)
+#define bfin_read_CAN1_MB00_DATA3()		bfin_read16(CAN1_MB00_DATA3)
+#define bfin_write_CAN1_MB00_DATA3(val)		bfin_write16(CAN1_MB00_DATA3, val)
+#define bfin_read_CAN1_MB00_LENGTH()		bfin_read16(CAN1_MB00_LENGTH)
+#define bfin_write_CAN1_MB00_LENGTH(val)	bfin_write16(CAN1_MB00_LENGTH, val)
+#define bfin_read_CAN1_MB00_TIMESTAMP()		bfin_read16(CAN1_MB00_TIMESTAMP)
+#define bfin_write_CAN1_MB00_TIMESTAMP(val)	bfin_write16(CAN1_MB00_TIMESTAMP, val)
+#define bfin_read_CAN1_MB00_ID0()		bfin_read16(CAN1_MB00_ID0)
+#define bfin_write_CAN1_MB00_ID0(val)		bfin_write16(CAN1_MB00_ID0, val)
+#define bfin_read_CAN1_MB00_ID1()		bfin_read16(CAN1_MB00_ID1)
+#define bfin_write_CAN1_MB00_ID1(val)		bfin_write16(CAN1_MB00_ID1, val)
+#define bfin_read_CAN1_MB01_DATA0()		bfin_read16(CAN1_MB01_DATA0)
+#define bfin_write_CAN1_MB01_DATA0(val)		bfin_write16(CAN1_MB01_DATA0, val)
+#define bfin_read_CAN1_MB01_DATA1()		bfin_read16(CAN1_MB01_DATA1)
+#define bfin_write_CAN1_MB01_DATA1(val)		bfin_write16(CAN1_MB01_DATA1, val)
+#define bfin_read_CAN1_MB01_DATA2()		bfin_read16(CAN1_MB01_DATA2)
+#define bfin_write_CAN1_MB01_DATA2(val)		bfin_write16(CAN1_MB01_DATA2, val)
+#define bfin_read_CAN1_MB01_DATA3()		bfin_read16(CAN1_MB01_DATA3)
+#define bfin_write_CAN1_MB01_DATA3(val)		bfin_write16(CAN1_MB01_DATA3, val)
+#define bfin_read_CAN1_MB01_LENGTH()		bfin_read16(CAN1_MB01_LENGTH)
+#define bfin_write_CAN1_MB01_LENGTH(val)	bfin_write16(CAN1_MB01_LENGTH, val)
+#define bfin_read_CAN1_MB01_TIMESTAMP()		bfin_read16(CAN1_MB01_TIMESTAMP)
+#define bfin_write_CAN1_MB01_TIMESTAMP(val)	bfin_write16(CAN1_MB01_TIMESTAMP, val)
+#define bfin_read_CAN1_MB01_ID0()		bfin_read16(CAN1_MB01_ID0)
+#define bfin_write_CAN1_MB01_ID0(val)		bfin_write16(CAN1_MB01_ID0, val)
+#define bfin_read_CAN1_MB01_ID1()		bfin_read16(CAN1_MB01_ID1)
+#define bfin_write_CAN1_MB01_ID1(val)		bfin_write16(CAN1_MB01_ID1, val)
+#define bfin_read_CAN1_MB02_DATA0()		bfin_read16(CAN1_MB02_DATA0)
+#define bfin_write_CAN1_MB02_DATA0(val)		bfin_write16(CAN1_MB02_DATA0, val)
+#define bfin_read_CAN1_MB02_DATA1()		bfin_read16(CAN1_MB02_DATA1)
+#define bfin_write_CAN1_MB02_DATA1(val)		bfin_write16(CAN1_MB02_DATA1, val)
+#define bfin_read_CAN1_MB02_DATA2()		bfin_read16(CAN1_MB02_DATA2)
+#define bfin_write_CAN1_MB02_DATA2(val)		bfin_write16(CAN1_MB02_DATA2, val)
+#define bfin_read_CAN1_MB02_DATA3()		bfin_read16(CAN1_MB02_DATA3)
+#define bfin_write_CAN1_MB02_DATA3(val)		bfin_write16(CAN1_MB02_DATA3, val)
+#define bfin_read_CAN1_MB02_LENGTH()		bfin_read16(CAN1_MB02_LENGTH)
+#define bfin_write_CAN1_MB02_LENGTH(val)	bfin_write16(CAN1_MB02_LENGTH, val)
+#define bfin_read_CAN1_MB02_TIMESTAMP()		bfin_read16(CAN1_MB02_TIMESTAMP)
+#define bfin_write_CAN1_MB02_TIMESTAMP(val)	bfin_write16(CAN1_MB02_TIMESTAMP, val)
+#define bfin_read_CAN1_MB02_ID0()		bfin_read16(CAN1_MB02_ID0)
+#define bfin_write_CAN1_MB02_ID0(val)		bfin_write16(CAN1_MB02_ID0, val)
+#define bfin_read_CAN1_MB02_ID1()		bfin_read16(CAN1_MB02_ID1)
+#define bfin_write_CAN1_MB02_ID1(val)		bfin_write16(CAN1_MB02_ID1, val)
+#define bfin_read_CAN1_MB03_DATA0()		bfin_read16(CAN1_MB03_DATA0)
+#define bfin_write_CAN1_MB03_DATA0(val)		bfin_write16(CAN1_MB03_DATA0, val)
+#define bfin_read_CAN1_MB03_DATA1()		bfin_read16(CAN1_MB03_DATA1)
+#define bfin_write_CAN1_MB03_DATA1(val)		bfin_write16(CAN1_MB03_DATA1, val)
+#define bfin_read_CAN1_MB03_DATA2()		bfin_read16(CAN1_MB03_DATA2)
+#define bfin_write_CAN1_MB03_DATA2(val)		bfin_write16(CAN1_MB03_DATA2, val)
+#define bfin_read_CAN1_MB03_DATA3()		bfin_read16(CAN1_MB03_DATA3)
+#define bfin_write_CAN1_MB03_DATA3(val)		bfin_write16(CAN1_MB03_DATA3, val)
+#define bfin_read_CAN1_MB03_LENGTH()		bfin_read16(CAN1_MB03_LENGTH)
+#define bfin_write_CAN1_MB03_LENGTH(val)	bfin_write16(CAN1_MB03_LENGTH, val)
+#define bfin_read_CAN1_MB03_TIMESTAMP()		bfin_read16(CAN1_MB03_TIMESTAMP)
+#define bfin_write_CAN1_MB03_TIMESTAMP(val)	bfin_write16(CAN1_MB03_TIMESTAMP, val)
+#define bfin_read_CAN1_MB03_ID0()		bfin_read16(CAN1_MB03_ID0)
+#define bfin_write_CAN1_MB03_ID0(val)		bfin_write16(CAN1_MB03_ID0, val)
+#define bfin_read_CAN1_MB03_ID1()		bfin_read16(CAN1_MB03_ID1)
+#define bfin_write_CAN1_MB03_ID1(val)		bfin_write16(CAN1_MB03_ID1, val)
+#define bfin_read_CAN1_MB04_DATA0()		bfin_read16(CAN1_MB04_DATA0)
+#define bfin_write_CAN1_MB04_DATA0(val)		bfin_write16(CAN1_MB04_DATA0, val)
+#define bfin_read_CAN1_MB04_DATA1()		bfin_read16(CAN1_MB04_DATA1)
+#define bfin_write_CAN1_MB04_DATA1(val)		bfin_write16(CAN1_MB04_DATA1, val)
+#define bfin_read_CAN1_MB04_DATA2()		bfin_read16(CAN1_MB04_DATA2)
+#define bfin_write_CAN1_MB04_DATA2(val)		bfin_write16(CAN1_MB04_DATA2, val)
+#define bfin_read_CAN1_MB04_DATA3()		bfin_read16(CAN1_MB04_DATA3)
+#define bfin_write_CAN1_MB04_DATA3(val)		bfin_write16(CAN1_MB04_DATA3, val)
+#define bfin_read_CAN1_MB04_LENGTH()		bfin_read16(CAN1_MB04_LENGTH)
+#define bfin_write_CAN1_MB04_LENGTH(val)	bfin_write16(CAN1_MB04_LENGTH, val)
+#define bfin_read_CAN1_MB04_TIMESTAMP()		bfin_read16(CAN1_MB04_TIMESTAMP)
+#define bfin_write_CAN1_MB04_TIMESTAMP(val)	bfin_write16(CAN1_MB04_TIMESTAMP, val)
+#define bfin_read_CAN1_MB04_ID0()		bfin_read16(CAN1_MB04_ID0)
+#define bfin_write_CAN1_MB04_ID0(val)		bfin_write16(CAN1_MB04_ID0, val)
+#define bfin_read_CAN1_MB04_ID1()		bfin_read16(CAN1_MB04_ID1)
+#define bfin_write_CAN1_MB04_ID1(val)		bfin_write16(CAN1_MB04_ID1, val)
+#define bfin_read_CAN1_MB05_DATA0()		bfin_read16(CAN1_MB05_DATA0)
+#define bfin_write_CAN1_MB05_DATA0(val)		bfin_write16(CAN1_MB05_DATA0, val)
+#define bfin_read_CAN1_MB05_DATA1()		bfin_read16(CAN1_MB05_DATA1)
+#define bfin_write_CAN1_MB05_DATA1(val)		bfin_write16(CAN1_MB05_DATA1, val)
+#define bfin_read_CAN1_MB05_DATA2()		bfin_read16(CAN1_MB05_DATA2)
+#define bfin_write_CAN1_MB05_DATA2(val)		bfin_write16(CAN1_MB05_DATA2, val)
+#define bfin_read_CAN1_MB05_DATA3()		bfin_read16(CAN1_MB05_DATA3)
+#define bfin_write_CAN1_MB05_DATA3(val)		bfin_write16(CAN1_MB05_DATA3, val)
+#define bfin_read_CAN1_MB05_LENGTH()		bfin_read16(CAN1_MB05_LENGTH)
+#define bfin_write_CAN1_MB05_LENGTH(val)	bfin_write16(CAN1_MB05_LENGTH, val)
+#define bfin_read_CAN1_MB05_TIMESTAMP()		bfin_read16(CAN1_MB05_TIMESTAMP)
+#define bfin_write_CAN1_MB05_TIMESTAMP(val)	bfin_write16(CAN1_MB05_TIMESTAMP, val)
+#define bfin_read_CAN1_MB05_ID0()		bfin_read16(CAN1_MB05_ID0)
+#define bfin_write_CAN1_MB05_ID0(val)		bfin_write16(CAN1_MB05_ID0, val)
+#define bfin_read_CAN1_MB05_ID1()		bfin_read16(CAN1_MB05_ID1)
+#define bfin_write_CAN1_MB05_ID1(val)		bfin_write16(CAN1_MB05_ID1, val)
+#define bfin_read_CAN1_MB06_DATA0()		bfin_read16(CAN1_MB06_DATA0)
+#define bfin_write_CAN1_MB06_DATA0(val)		bfin_write16(CAN1_MB06_DATA0, val)
+#define bfin_read_CAN1_MB06_DATA1()		bfin_read16(CAN1_MB06_DATA1)
+#define bfin_write_CAN1_MB06_DATA1(val)		bfin_write16(CAN1_MB06_DATA1, val)
+#define bfin_read_CAN1_MB06_DATA2()		bfin_read16(CAN1_MB06_DATA2)
+#define bfin_write_CAN1_MB06_DATA2(val)		bfin_write16(CAN1_MB06_DATA2, val)
+#define bfin_read_CAN1_MB06_DATA3()		bfin_read16(CAN1_MB06_DATA3)
+#define bfin_write_CAN1_MB06_DATA3(val)		bfin_write16(CAN1_MB06_DATA3, val)
+#define bfin_read_CAN1_MB06_LENGTH()		bfin_read16(CAN1_MB06_LENGTH)
+#define bfin_write_CAN1_MB06_LENGTH(val)	bfin_write16(CAN1_MB06_LENGTH, val)
+#define bfin_read_CAN1_MB06_TIMESTAMP()		bfin_read16(CAN1_MB06_TIMESTAMP)
+#define bfin_write_CAN1_MB06_TIMESTAMP(val)	bfin_write16(CAN1_MB06_TIMESTAMP, val)
+#define bfin_read_CAN1_MB06_ID0()		bfin_read16(CAN1_MB06_ID0)
+#define bfin_write_CAN1_MB06_ID0(val)		bfin_write16(CAN1_MB06_ID0, val)
+#define bfin_read_CAN1_MB06_ID1()		bfin_read16(CAN1_MB06_ID1)
+#define bfin_write_CAN1_MB06_ID1(val)		bfin_write16(CAN1_MB06_ID1, val)
+#define bfin_read_CAN1_MB07_DATA0()		bfin_read16(CAN1_MB07_DATA0)
+#define bfin_write_CAN1_MB07_DATA0(val)		bfin_write16(CAN1_MB07_DATA0, val)
+#define bfin_read_CAN1_MB07_DATA1()		bfin_read16(CAN1_MB07_DATA1)
+#define bfin_write_CAN1_MB07_DATA1(val)		bfin_write16(CAN1_MB07_DATA1, val)
+#define bfin_read_CAN1_MB07_DATA2()		bfin_read16(CAN1_MB07_DATA2)
+#define bfin_write_CAN1_MB07_DATA2(val)		bfin_write16(CAN1_MB07_DATA2, val)
+#define bfin_read_CAN1_MB07_DATA3()		bfin_read16(CAN1_MB07_DATA3)
+#define bfin_write_CAN1_MB07_DATA3(val)		bfin_write16(CAN1_MB07_DATA3, val)
+#define bfin_read_CAN1_MB07_LENGTH()		bfin_read16(CAN1_MB07_LENGTH)
+#define bfin_write_CAN1_MB07_LENGTH(val)	bfin_write16(CAN1_MB07_LENGTH, val)
+#define bfin_read_CAN1_MB07_TIMESTAMP()		bfin_read16(CAN1_MB07_TIMESTAMP)
+#define bfin_write_CAN1_MB07_TIMESTAMP(val)	bfin_write16(CAN1_MB07_TIMESTAMP, val)
+#define bfin_read_CAN1_MB07_ID0()		bfin_read16(CAN1_MB07_ID0)
+#define bfin_write_CAN1_MB07_ID0(val)		bfin_write16(CAN1_MB07_ID0, val)
+#define bfin_read_CAN1_MB07_ID1()		bfin_read16(CAN1_MB07_ID1)
+#define bfin_write_CAN1_MB07_ID1(val)		bfin_write16(CAN1_MB07_ID1, val)
+#define bfin_read_CAN1_MB08_DATA0()		bfin_read16(CAN1_MB08_DATA0)
+#define bfin_write_CAN1_MB08_DATA0(val)		bfin_write16(CAN1_MB08_DATA0, val)
+#define bfin_read_CAN1_MB08_DATA1()		bfin_read16(CAN1_MB08_DATA1)
+#define bfin_write_CAN1_MB08_DATA1(val)		bfin_write16(CAN1_MB08_DATA1, val)
+#define bfin_read_CAN1_MB08_DATA2()		bfin_read16(CAN1_MB08_DATA2)
+#define bfin_write_CAN1_MB08_DATA2(val)		bfin_write16(CAN1_MB08_DATA2, val)
+#define bfin_read_CAN1_MB08_DATA3()		bfin_read16(CAN1_MB08_DATA3)
+#define bfin_write_CAN1_MB08_DATA3(val)		bfin_write16(CAN1_MB08_DATA3, val)
+#define bfin_read_CAN1_MB08_LENGTH()		bfin_read16(CAN1_MB08_LENGTH)
+#define bfin_write_CAN1_MB08_LENGTH(val)	bfin_write16(CAN1_MB08_LENGTH, val)
+#define bfin_read_CAN1_MB08_TIMESTAMP()		bfin_read16(CAN1_MB08_TIMESTAMP)
+#define bfin_write_CAN1_MB08_TIMESTAMP(val)	bfin_write16(CAN1_MB08_TIMESTAMP, val)
+#define bfin_read_CAN1_MB08_ID0()		bfin_read16(CAN1_MB08_ID0)
+#define bfin_write_CAN1_MB08_ID0(val)		bfin_write16(CAN1_MB08_ID0, val)
+#define bfin_read_CAN1_MB08_ID1()		bfin_read16(CAN1_MB08_ID1)
+#define bfin_write_CAN1_MB08_ID1(val)		bfin_write16(CAN1_MB08_ID1, val)
+#define bfin_read_CAN1_MB09_DATA0()		bfin_read16(CAN1_MB09_DATA0)
+#define bfin_write_CAN1_MB09_DATA0(val)		bfin_write16(CAN1_MB09_DATA0, val)
+#define bfin_read_CAN1_MB09_DATA1()		bfin_read16(CAN1_MB09_DATA1)
+#define bfin_write_CAN1_MB09_DATA1(val)		bfin_write16(CAN1_MB09_DATA1, val)
+#define bfin_read_CAN1_MB09_DATA2()		bfin_read16(CAN1_MB09_DATA2)
+#define bfin_write_CAN1_MB09_DATA2(val)		bfin_write16(CAN1_MB09_DATA2, val)
+#define bfin_read_CAN1_MB09_DATA3()		bfin_read16(CAN1_MB09_DATA3)
+#define bfin_write_CAN1_MB09_DATA3(val)		bfin_write16(CAN1_MB09_DATA3, val)
+#define bfin_read_CAN1_MB09_LENGTH()		bfin_read16(CAN1_MB09_LENGTH)
+#define bfin_write_CAN1_MB09_LENGTH(val)	bfin_write16(CAN1_MB09_LENGTH, val)
+#define bfin_read_CAN1_MB09_TIMESTAMP()		bfin_read16(CAN1_MB09_TIMESTAMP)
+#define bfin_write_CAN1_MB09_TIMESTAMP(val)	bfin_write16(CAN1_MB09_TIMESTAMP, val)
+#define bfin_read_CAN1_MB09_ID0()		bfin_read16(CAN1_MB09_ID0)
+#define bfin_write_CAN1_MB09_ID0(val)		bfin_write16(CAN1_MB09_ID0, val)
+#define bfin_read_CAN1_MB09_ID1()		bfin_read16(CAN1_MB09_ID1)
+#define bfin_write_CAN1_MB09_ID1(val)		bfin_write16(CAN1_MB09_ID1, val)
+#define bfin_read_CAN1_MB10_DATA0()		bfin_read16(CAN1_MB10_DATA0)
+#define bfin_write_CAN1_MB10_DATA0(val)		bfin_write16(CAN1_MB10_DATA0, val)
+#define bfin_read_CAN1_MB10_DATA1()		bfin_read16(CAN1_MB10_DATA1)
+#define bfin_write_CAN1_MB10_DATA1(val)		bfin_write16(CAN1_MB10_DATA1, val)
+#define bfin_read_CAN1_MB10_DATA2()		bfin_read16(CAN1_MB10_DATA2)
+#define bfin_write_CAN1_MB10_DATA2(val)		bfin_write16(CAN1_MB10_DATA2, val)
+#define bfin_read_CAN1_MB10_DATA3()		bfin_read16(CAN1_MB10_DATA3)
+#define bfin_write_CAN1_MB10_DATA3(val)		bfin_write16(CAN1_MB10_DATA3, val)
+#define bfin_read_CAN1_MB10_LENGTH()		bfin_read16(CAN1_MB10_LENGTH)
+#define bfin_write_CAN1_MB10_LENGTH(val)	bfin_write16(CAN1_MB10_LENGTH, val)
+#define bfin_read_CAN1_MB10_TIMESTAMP()		bfin_read16(CAN1_MB10_TIMESTAMP)
+#define bfin_write_CAN1_MB10_TIMESTAMP(val)	bfin_write16(CAN1_MB10_TIMESTAMP, val)
+#define bfin_read_CAN1_MB10_ID0()		bfin_read16(CAN1_MB10_ID0)
+#define bfin_write_CAN1_MB10_ID0(val)		bfin_write16(CAN1_MB10_ID0, val)
+#define bfin_read_CAN1_MB10_ID1()		bfin_read16(CAN1_MB10_ID1)
+#define bfin_write_CAN1_MB10_ID1(val)		bfin_write16(CAN1_MB10_ID1, val)
+#define bfin_read_CAN1_MB11_DATA0()		bfin_read16(CAN1_MB11_DATA0)
+#define bfin_write_CAN1_MB11_DATA0(val)		bfin_write16(CAN1_MB11_DATA0, val)
+#define bfin_read_CAN1_MB11_DATA1()		bfin_read16(CAN1_MB11_DATA1)
+#define bfin_write_CAN1_MB11_DATA1(val)		bfin_write16(CAN1_MB11_DATA1, val)
+#define bfin_read_CAN1_MB11_DATA2()		bfin_read16(CAN1_MB11_DATA2)
+#define bfin_write_CAN1_MB11_DATA2(val)		bfin_write16(CAN1_MB11_DATA2, val)
+#define bfin_read_CAN1_MB11_DATA3()		bfin_read16(CAN1_MB11_DATA3)
+#define bfin_write_CAN1_MB11_DATA3(val)		bfin_write16(CAN1_MB11_DATA3, val)
+#define bfin_read_CAN1_MB11_LENGTH()		bfin_read16(CAN1_MB11_LENGTH)
+#define bfin_write_CAN1_MB11_LENGTH(val)	bfin_write16(CAN1_MB11_LENGTH, val)
+#define bfin_read_CAN1_MB11_TIMESTAMP()		bfin_read16(CAN1_MB11_TIMESTAMP)
+#define bfin_write_CAN1_MB11_TIMESTAMP(val)	bfin_write16(CAN1_MB11_TIMESTAMP, val)
+#define bfin_read_CAN1_MB11_ID0()		bfin_read16(CAN1_MB11_ID0)
+#define bfin_write_CAN1_MB11_ID0(val)		bfin_write16(CAN1_MB11_ID0, val)
+#define bfin_read_CAN1_MB11_ID1()		bfin_read16(CAN1_MB11_ID1)
+#define bfin_write_CAN1_MB11_ID1(val)		bfin_write16(CAN1_MB11_ID1, val)
+#define bfin_read_CAN1_MB12_DATA0()		bfin_read16(CAN1_MB12_DATA0)
+#define bfin_write_CAN1_MB12_DATA0(val)		bfin_write16(CAN1_MB12_DATA0, val)
+#define bfin_read_CAN1_MB12_DATA1()		bfin_read16(CAN1_MB12_DATA1)
+#define bfin_write_CAN1_MB12_DATA1(val)		bfin_write16(CAN1_MB12_DATA1, val)
+#define bfin_read_CAN1_MB12_DATA2()		bfin_read16(CAN1_MB12_DATA2)
+#define bfin_write_CAN1_MB12_DATA2(val)		bfin_write16(CAN1_MB12_DATA2, val)
+#define bfin_read_CAN1_MB12_DATA3()		bfin_read16(CAN1_MB12_DATA3)
+#define bfin_write_CAN1_MB12_DATA3(val)		bfin_write16(CAN1_MB12_DATA3, val)
+#define bfin_read_CAN1_MB12_LENGTH()		bfin_read16(CAN1_MB12_LENGTH)
+#define bfin_write_CAN1_MB12_LENGTH(val)	bfin_write16(CAN1_MB12_LENGTH, val)
+#define bfin_read_CAN1_MB12_TIMESTAMP()		bfin_read16(CAN1_MB12_TIMESTAMP)
+#define bfin_write_CAN1_MB12_TIMESTAMP(val)	bfin_write16(CAN1_MB12_TIMESTAMP, val)
+#define bfin_read_CAN1_MB12_ID0()		bfin_read16(CAN1_MB12_ID0)
+#define bfin_write_CAN1_MB12_ID0(val)		bfin_write16(CAN1_MB12_ID0, val)
+#define bfin_read_CAN1_MB12_ID1()		bfin_read16(CAN1_MB12_ID1)
+#define bfin_write_CAN1_MB12_ID1(val)		bfin_write16(CAN1_MB12_ID1, val)
+#define bfin_read_CAN1_MB13_DATA0()		bfin_read16(CAN1_MB13_DATA0)
+#define bfin_write_CAN1_MB13_DATA0(val)		bfin_write16(CAN1_MB13_DATA0, val)
+#define bfin_read_CAN1_MB13_DATA1()		bfin_read16(CAN1_MB13_DATA1)
+#define bfin_write_CAN1_MB13_DATA1(val)		bfin_write16(CAN1_MB13_DATA1, val)
+#define bfin_read_CAN1_MB13_DATA2()		bfin_read16(CAN1_MB13_DATA2)
+#define bfin_write_CAN1_MB13_DATA2(val)		bfin_write16(CAN1_MB13_DATA2, val)
+#define bfin_read_CAN1_MB13_DATA3()		bfin_read16(CAN1_MB13_DATA3)
+#define bfin_write_CAN1_MB13_DATA3(val)		bfin_write16(CAN1_MB13_DATA3, val)
+#define bfin_read_CAN1_MB13_LENGTH()		bfin_read16(CAN1_MB13_LENGTH)
+#define bfin_write_CAN1_MB13_LENGTH(val)	bfin_write16(CAN1_MB13_LENGTH, val)
+#define bfin_read_CAN1_MB13_TIMESTAMP()		bfin_read16(CAN1_MB13_TIMESTAMP)
+#define bfin_write_CAN1_MB13_TIMESTAMP(val)	bfin_write16(CAN1_MB13_TIMESTAMP, val)
+#define bfin_read_CAN1_MB13_ID0()		bfin_read16(CAN1_MB13_ID0)
+#define bfin_write_CAN1_MB13_ID0(val)		bfin_write16(CAN1_MB13_ID0, val)
+#define bfin_read_CAN1_MB13_ID1()		bfin_read16(CAN1_MB13_ID1)
+#define bfin_write_CAN1_MB13_ID1(val)		bfin_write16(CAN1_MB13_ID1, val)
+#define bfin_read_CAN1_MB14_DATA0()		bfin_read16(CAN1_MB14_DATA0)
+#define bfin_write_CAN1_MB14_DATA0(val)		bfin_write16(CAN1_MB14_DATA0, val)
+#define bfin_read_CAN1_MB14_DATA1()		bfin_read16(CAN1_MB14_DATA1)
+#define bfin_write_CAN1_MB14_DATA1(val)		bfin_write16(CAN1_MB14_DATA1, val)
+#define bfin_read_CAN1_MB14_DATA2()		bfin_read16(CAN1_MB14_DATA2)
+#define bfin_write_CAN1_MB14_DATA2(val)		bfin_write16(CAN1_MB14_DATA2, val)
+#define bfin_read_CAN1_MB14_DATA3()		bfin_read16(CAN1_MB14_DATA3)
+#define bfin_write_CAN1_MB14_DATA3(val)		bfin_write16(CAN1_MB14_DATA3, val)
+#define bfin_read_CAN1_MB14_LENGTH()		bfin_read16(CAN1_MB14_LENGTH)
+#define bfin_write_CAN1_MB14_LENGTH(val)	bfin_write16(CAN1_MB14_LENGTH, val)
+#define bfin_read_CAN1_MB14_TIMESTAMP()		bfin_read16(CAN1_MB14_TIMESTAMP)
+#define bfin_write_CAN1_MB14_TIMESTAMP(val)	bfin_write16(CAN1_MB14_TIMESTAMP, val)
+#define bfin_read_CAN1_MB14_ID0()		bfin_read16(CAN1_MB14_ID0)
+#define bfin_write_CAN1_MB14_ID0(val)		bfin_write16(CAN1_MB14_ID0, val)
+#define bfin_read_CAN1_MB14_ID1()		bfin_read16(CAN1_MB14_ID1)
+#define bfin_write_CAN1_MB14_ID1(val)		bfin_write16(CAN1_MB14_ID1, val)
+#define bfin_read_CAN1_MB15_DATA0()		bfin_read16(CAN1_MB15_DATA0)
+#define bfin_write_CAN1_MB15_DATA0(val)		bfin_write16(CAN1_MB15_DATA0, val)
+#define bfin_read_CAN1_MB15_DATA1()		bfin_read16(CAN1_MB15_DATA1)
+#define bfin_write_CAN1_MB15_DATA1(val)		bfin_write16(CAN1_MB15_DATA1, val)
+#define bfin_read_CAN1_MB15_DATA2()		bfin_read16(CAN1_MB15_DATA2)
+#define bfin_write_CAN1_MB15_DATA2(val)		bfin_write16(CAN1_MB15_DATA2, val)
+#define bfin_read_CAN1_MB15_DATA3()		bfin_read16(CAN1_MB15_DATA3)
+#define bfin_write_CAN1_MB15_DATA3(val)		bfin_write16(CAN1_MB15_DATA3, val)
+#define bfin_read_CAN1_MB15_LENGTH()		bfin_read16(CAN1_MB15_LENGTH)
+#define bfin_write_CAN1_MB15_LENGTH(val)	bfin_write16(CAN1_MB15_LENGTH, val)
+#define bfin_read_CAN1_MB15_TIMESTAMP()		bfin_read16(CAN1_MB15_TIMESTAMP)
+#define bfin_write_CAN1_MB15_TIMESTAMP(val)	bfin_write16(CAN1_MB15_TIMESTAMP, val)
+#define bfin_read_CAN1_MB15_ID0()		bfin_read16(CAN1_MB15_ID0)
+#define bfin_write_CAN1_MB15_ID0(val)		bfin_write16(CAN1_MB15_ID0, val)
+#define bfin_read_CAN1_MB15_ID1()		bfin_read16(CAN1_MB15_ID1)
+#define bfin_write_CAN1_MB15_ID1(val)		bfin_write16(CAN1_MB15_ID1, val)
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define bfin_read_CAN1_MB16_DATA0()		bfin_read16(CAN1_MB16_DATA0)
+#define bfin_write_CAN1_MB16_DATA0(val)		bfin_write16(CAN1_MB16_DATA0, val)
+#define bfin_read_CAN1_MB16_DATA1()		bfin_read16(CAN1_MB16_DATA1)
+#define bfin_write_CAN1_MB16_DATA1(val)		bfin_write16(CAN1_MB16_DATA1, val)
+#define bfin_read_CAN1_MB16_DATA2()		bfin_read16(CAN1_MB16_DATA2)
+#define bfin_write_CAN1_MB16_DATA2(val)		bfin_write16(CAN1_MB16_DATA2, val)
+#define bfin_read_CAN1_MB16_DATA3()		bfin_read16(CAN1_MB16_DATA3)
+#define bfin_write_CAN1_MB16_DATA3(val)		bfin_write16(CAN1_MB16_DATA3, val)
+#define bfin_read_CAN1_MB16_LENGTH()		bfin_read16(CAN1_MB16_LENGTH)
+#define bfin_write_CAN1_MB16_LENGTH(val)	bfin_write16(CAN1_MB16_LENGTH, val)
+#define bfin_read_CAN1_MB16_TIMESTAMP()		bfin_read16(CAN1_MB16_TIMESTAMP)
+#define bfin_write_CAN1_MB16_TIMESTAMP(val)	bfin_write16(CAN1_MB16_TIMESTAMP, val)
+#define bfin_read_CAN1_MB16_ID0()		bfin_read16(CAN1_MB16_ID0)
+#define bfin_write_CAN1_MB16_ID0(val)		bfin_write16(CAN1_MB16_ID0, val)
+#define bfin_read_CAN1_MB16_ID1()		bfin_read16(CAN1_MB16_ID1)
+#define bfin_write_CAN1_MB16_ID1(val)		bfin_write16(CAN1_MB16_ID1, val)
+#define bfin_read_CAN1_MB17_DATA0()		bfin_read16(CAN1_MB17_DATA0)
+#define bfin_write_CAN1_MB17_DATA0(val)		bfin_write16(CAN1_MB17_DATA0, val)
+#define bfin_read_CAN1_MB17_DATA1()		bfin_read16(CAN1_MB17_DATA1)
+#define bfin_write_CAN1_MB17_DATA1(val)		bfin_write16(CAN1_MB17_DATA1, val)
+#define bfin_read_CAN1_MB17_DATA2()		bfin_read16(CAN1_MB17_DATA2)
+#define bfin_write_CAN1_MB17_DATA2(val)		bfin_write16(CAN1_MB17_DATA2, val)
+#define bfin_read_CAN1_MB17_DATA3()		bfin_read16(CAN1_MB17_DATA3)
+#define bfin_write_CAN1_MB17_DATA3(val)		bfin_write16(CAN1_MB17_DATA3, val)
+#define bfin_read_CAN1_MB17_LENGTH()		bfin_read16(CAN1_MB17_LENGTH)
+#define bfin_write_CAN1_MB17_LENGTH(val)	bfin_write16(CAN1_MB17_LENGTH, val)
+#define bfin_read_CAN1_MB17_TIMESTAMP()		bfin_read16(CAN1_MB17_TIMESTAMP)
+#define bfin_write_CAN1_MB17_TIMESTAMP(val)	bfin_write16(CAN1_MB17_TIMESTAMP, val)
+#define bfin_read_CAN1_MB17_ID0()		bfin_read16(CAN1_MB17_ID0)
+#define bfin_write_CAN1_MB17_ID0(val)		bfin_write16(CAN1_MB17_ID0, val)
+#define bfin_read_CAN1_MB17_ID1()		bfin_read16(CAN1_MB17_ID1)
+#define bfin_write_CAN1_MB17_ID1(val)		bfin_write16(CAN1_MB17_ID1, val)
+#define bfin_read_CAN1_MB18_DATA0()		bfin_read16(CAN1_MB18_DATA0)
+#define bfin_write_CAN1_MB18_DATA0(val)		bfin_write16(CAN1_MB18_DATA0, val)
+#define bfin_read_CAN1_MB18_DATA1()		bfin_read16(CAN1_MB18_DATA1)
+#define bfin_write_CAN1_MB18_DATA1(val)		bfin_write16(CAN1_MB18_DATA1, val)
+#define bfin_read_CAN1_MB18_DATA2()		bfin_read16(CAN1_MB18_DATA2)
+#define bfin_write_CAN1_MB18_DATA2(val)		bfin_write16(CAN1_MB18_DATA2, val)
+#define bfin_read_CAN1_MB18_DATA3()		bfin_read16(CAN1_MB18_DATA3)
+#define bfin_write_CAN1_MB18_DATA3(val)		bfin_write16(CAN1_MB18_DATA3, val)
+#define bfin_read_CAN1_MB18_LENGTH()		bfin_read16(CAN1_MB18_LENGTH)
+#define bfin_write_CAN1_MB18_LENGTH(val)	bfin_write16(CAN1_MB18_LENGTH, val)
+#define bfin_read_CAN1_MB18_TIMESTAMP()		bfin_read16(CAN1_MB18_TIMESTAMP)
+#define bfin_write_CAN1_MB18_TIMESTAMP(val)	bfin_write16(CAN1_MB18_TIMESTAMP, val)
+#define bfin_read_CAN1_MB18_ID0()		bfin_read16(CAN1_MB18_ID0)
+#define bfin_write_CAN1_MB18_ID0(val)		bfin_write16(CAN1_MB18_ID0, val)
+#define bfin_read_CAN1_MB18_ID1()		bfin_read16(CAN1_MB18_ID1)
+#define bfin_write_CAN1_MB18_ID1(val)		bfin_write16(CAN1_MB18_ID1, val)
+#define bfin_read_CAN1_MB19_DATA0()		bfin_read16(CAN1_MB19_DATA0)
+#define bfin_write_CAN1_MB19_DATA0(val)		bfin_write16(CAN1_MB19_DATA0, val)
+#define bfin_read_CAN1_MB19_DATA1()		bfin_read16(CAN1_MB19_DATA1)
+#define bfin_write_CAN1_MB19_DATA1(val)		bfin_write16(CAN1_MB19_DATA1, val)
+#define bfin_read_CAN1_MB19_DATA2()		bfin_read16(CAN1_MB19_DATA2)
+#define bfin_write_CAN1_MB19_DATA2(val)		bfin_write16(CAN1_MB19_DATA2, val)
+#define bfin_read_CAN1_MB19_DATA3()		bfin_read16(CAN1_MB19_DATA3)
+#define bfin_write_CAN1_MB19_DATA3(val)		bfin_write16(CAN1_MB19_DATA3, val)
+#define bfin_read_CAN1_MB19_LENGTH()		bfin_read16(CAN1_MB19_LENGTH)
+#define bfin_write_CAN1_MB19_LENGTH(val)	bfin_write16(CAN1_MB19_LENGTH, val)
+#define bfin_read_CAN1_MB19_TIMESTAMP()		bfin_read16(CAN1_MB19_TIMESTAMP)
+#define bfin_write_CAN1_MB19_TIMESTAMP(val)	bfin_write16(CAN1_MB19_TIMESTAMP, val)
+#define bfin_read_CAN1_MB19_ID0()		bfin_read16(CAN1_MB19_ID0)
+#define bfin_write_CAN1_MB19_ID0(val)		bfin_write16(CAN1_MB19_ID0, val)
+#define bfin_read_CAN1_MB19_ID1()		bfin_read16(CAN1_MB19_ID1)
+#define bfin_write_CAN1_MB19_ID1(val)		bfin_write16(CAN1_MB19_ID1, val)
+#define bfin_read_CAN1_MB20_DATA0()		bfin_read16(CAN1_MB20_DATA0)
+#define bfin_write_CAN1_MB20_DATA0(val)		bfin_write16(CAN1_MB20_DATA0, val)
+#define bfin_read_CAN1_MB20_DATA1()		bfin_read16(CAN1_MB20_DATA1)
+#define bfin_write_CAN1_MB20_DATA1(val)		bfin_write16(CAN1_MB20_DATA1, val)
+#define bfin_read_CAN1_MB20_DATA2()		bfin_read16(CAN1_MB20_DATA2)
+#define bfin_write_CAN1_MB20_DATA2(val)		bfin_write16(CAN1_MB20_DATA2, val)
+#define bfin_read_CAN1_MB20_DATA3()		bfin_read16(CAN1_MB20_DATA3)
+#define bfin_write_CAN1_MB20_DATA3(val)		bfin_write16(CAN1_MB20_DATA3, val)
+#define bfin_read_CAN1_MB20_LENGTH()		bfin_read16(CAN1_MB20_LENGTH)
+#define bfin_write_CAN1_MB20_LENGTH(val)	bfin_write16(CAN1_MB20_LENGTH, val)
+#define bfin_read_CAN1_MB20_TIMESTAMP()		bfin_read16(CAN1_MB20_TIMESTAMP)
+#define bfin_write_CAN1_MB20_TIMESTAMP(val)	bfin_write16(CAN1_MB20_TIMESTAMP, val)
+#define bfin_read_CAN1_MB20_ID0()		bfin_read16(CAN1_MB20_ID0)
+#define bfin_write_CAN1_MB20_ID0(val)		bfin_write16(CAN1_MB20_ID0, val)
+#define bfin_read_CAN1_MB20_ID1()		bfin_read16(CAN1_MB20_ID1)
+#define bfin_write_CAN1_MB20_ID1(val)		bfin_write16(CAN1_MB20_ID1, val)
+#define bfin_read_CAN1_MB21_DATA0()		bfin_read16(CAN1_MB21_DATA0)
+#define bfin_write_CAN1_MB21_DATA0(val)		bfin_write16(CAN1_MB21_DATA0, val)
+#define bfin_read_CAN1_MB21_DATA1()		bfin_read16(CAN1_MB21_DATA1)
+#define bfin_write_CAN1_MB21_DATA1(val)		bfin_write16(CAN1_MB21_DATA1, val)
+#define bfin_read_CAN1_MB21_DATA2()		bfin_read16(CAN1_MB21_DATA2)
+#define bfin_write_CAN1_MB21_DATA2(val)		bfin_write16(CAN1_MB21_DATA2, val)
+#define bfin_read_CAN1_MB21_DATA3()		bfin_read16(CAN1_MB21_DATA3)
+#define bfin_write_CAN1_MB21_DATA3(val)		bfin_write16(CAN1_MB21_DATA3, val)
+#define bfin_read_CAN1_MB21_LENGTH()		bfin_read16(CAN1_MB21_LENGTH)
+#define bfin_write_CAN1_MB21_LENGTH(val)	bfin_write16(CAN1_MB21_LENGTH, val)
+#define bfin_read_CAN1_MB21_TIMESTAMP()		bfin_read16(CAN1_MB21_TIMESTAMP)
+#define bfin_write_CAN1_MB21_TIMESTAMP(val)	bfin_write16(CAN1_MB21_TIMESTAMP, val)
+#define bfin_read_CAN1_MB21_ID0()		bfin_read16(CAN1_MB21_ID0)
+#define bfin_write_CAN1_MB21_ID0(val)		bfin_write16(CAN1_MB21_ID0, val)
+#define bfin_read_CAN1_MB21_ID1()		bfin_read16(CAN1_MB21_ID1)
+#define bfin_write_CAN1_MB21_ID1(val)		bfin_write16(CAN1_MB21_ID1, val)
+#define bfin_read_CAN1_MB22_DATA0()		bfin_read16(CAN1_MB22_DATA0)
+#define bfin_write_CAN1_MB22_DATA0(val)		bfin_write16(CAN1_MB22_DATA0, val)
+#define bfin_read_CAN1_MB22_DATA1()		bfin_read16(CAN1_MB22_DATA1)
+#define bfin_write_CAN1_MB22_DATA1(val)		bfin_write16(CAN1_MB22_DATA1, val)
+#define bfin_read_CAN1_MB22_DATA2()		bfin_read16(CAN1_MB22_DATA2)
+#define bfin_write_CAN1_MB22_DATA2(val)		bfin_write16(CAN1_MB22_DATA2, val)
+#define bfin_read_CAN1_MB22_DATA3()		bfin_read16(CAN1_MB22_DATA3)
+#define bfin_write_CAN1_MB22_DATA3(val)		bfin_write16(CAN1_MB22_DATA3, val)
+#define bfin_read_CAN1_MB22_LENGTH()		bfin_read16(CAN1_MB22_LENGTH)
+#define bfin_write_CAN1_MB22_LENGTH(val)	bfin_write16(CAN1_MB22_LENGTH, val)
+#define bfin_read_CAN1_MB22_TIMESTAMP()		bfin_read16(CAN1_MB22_TIMESTAMP)
+#define bfin_write_CAN1_MB22_TIMESTAMP(val)	bfin_write16(CAN1_MB22_TIMESTAMP, val)
+#define bfin_read_CAN1_MB22_ID0()		bfin_read16(CAN1_MB22_ID0)
+#define bfin_write_CAN1_MB22_ID0(val)		bfin_write16(CAN1_MB22_ID0, val)
+#define bfin_read_CAN1_MB22_ID1()		bfin_read16(CAN1_MB22_ID1)
+#define bfin_write_CAN1_MB22_ID1(val)		bfin_write16(CAN1_MB22_ID1, val)
+#define bfin_read_CAN1_MB23_DATA0()		bfin_read16(CAN1_MB23_DATA0)
+#define bfin_write_CAN1_MB23_DATA0(val)		bfin_write16(CAN1_MB23_DATA0, val)
+#define bfin_read_CAN1_MB23_DATA1()		bfin_read16(CAN1_MB23_DATA1)
+#define bfin_write_CAN1_MB23_DATA1(val)		bfin_write16(CAN1_MB23_DATA1, val)
+#define bfin_read_CAN1_MB23_DATA2()		bfin_read16(CAN1_MB23_DATA2)
+#define bfin_write_CAN1_MB23_DATA2(val)		bfin_write16(CAN1_MB23_DATA2, val)
+#define bfin_read_CAN1_MB23_DATA3()		bfin_read16(CAN1_MB23_DATA3)
+#define bfin_write_CAN1_MB23_DATA3(val)		bfin_write16(CAN1_MB23_DATA3, val)
+#define bfin_read_CAN1_MB23_LENGTH()		bfin_read16(CAN1_MB23_LENGTH)
+#define bfin_write_CAN1_MB23_LENGTH(val)	bfin_write16(CAN1_MB23_LENGTH, val)
+#define bfin_read_CAN1_MB23_TIMESTAMP()		bfin_read16(CAN1_MB23_TIMESTAMP)
+#define bfin_write_CAN1_MB23_TIMESTAMP(val)	bfin_write16(CAN1_MB23_TIMESTAMP, val)
+#define bfin_read_CAN1_MB23_ID0()		bfin_read16(CAN1_MB23_ID0)
+#define bfin_write_CAN1_MB23_ID0(val)		bfin_write16(CAN1_MB23_ID0, val)
+#define bfin_read_CAN1_MB23_ID1()		bfin_read16(CAN1_MB23_ID1)
+#define bfin_write_CAN1_MB23_ID1(val)		bfin_write16(CAN1_MB23_ID1, val)
+#define bfin_read_CAN1_MB24_DATA0()		bfin_read16(CAN1_MB24_DATA0)
+#define bfin_write_CAN1_MB24_DATA0(val)		bfin_write16(CAN1_MB24_DATA0, val)
+#define bfin_read_CAN1_MB24_DATA1()		bfin_read16(CAN1_MB24_DATA1)
+#define bfin_write_CAN1_MB24_DATA1(val)		bfin_write16(CAN1_MB24_DATA1, val)
+#define bfin_read_CAN1_MB24_DATA2()		bfin_read16(CAN1_MB24_DATA2)
+#define bfin_write_CAN1_MB24_DATA2(val)		bfin_write16(CAN1_MB24_DATA2, val)
+#define bfin_read_CAN1_MB24_DATA3()		bfin_read16(CAN1_MB24_DATA3)
+#define bfin_write_CAN1_MB24_DATA3(val)		bfin_write16(CAN1_MB24_DATA3, val)
+#define bfin_read_CAN1_MB24_LENGTH()		bfin_read16(CAN1_MB24_LENGTH)
+#define bfin_write_CAN1_MB24_LENGTH(val)	bfin_write16(CAN1_MB24_LENGTH, val)
+#define bfin_read_CAN1_MB24_TIMESTAMP()		bfin_read16(CAN1_MB24_TIMESTAMP)
+#define bfin_write_CAN1_MB24_TIMESTAMP(val)	bfin_write16(CAN1_MB24_TIMESTAMP, val)
+#define bfin_read_CAN1_MB24_ID0()		bfin_read16(CAN1_MB24_ID0)
+#define bfin_write_CAN1_MB24_ID0(val)		bfin_write16(CAN1_MB24_ID0, val)
+#define bfin_read_CAN1_MB24_ID1()		bfin_read16(CAN1_MB24_ID1)
+#define bfin_write_CAN1_MB24_ID1(val)		bfin_write16(CAN1_MB24_ID1, val)
+#define bfin_read_CAN1_MB25_DATA0()		bfin_read16(CAN1_MB25_DATA0)
+#define bfin_write_CAN1_MB25_DATA0(val)		bfin_write16(CAN1_MB25_DATA0, val)
+#define bfin_read_CAN1_MB25_DATA1()		bfin_read16(CAN1_MB25_DATA1)
+#define bfin_write_CAN1_MB25_DATA1(val)		bfin_write16(CAN1_MB25_DATA1, val)
+#define bfin_read_CAN1_MB25_DATA2()		bfin_read16(CAN1_MB25_DATA2)
+#define bfin_write_CAN1_MB25_DATA2(val)		bfin_write16(CAN1_MB25_DATA2, val)
+#define bfin_read_CAN1_MB25_DATA3()		bfin_read16(CAN1_MB25_DATA3)
+#define bfin_write_CAN1_MB25_DATA3(val)		bfin_write16(CAN1_MB25_DATA3, val)
+#define bfin_read_CAN1_MB25_LENGTH()		bfin_read16(CAN1_MB25_LENGTH)
+#define bfin_write_CAN1_MB25_LENGTH(val)	bfin_write16(CAN1_MB25_LENGTH, val)
+#define bfin_read_CAN1_MB25_TIMESTAMP()		bfin_read16(CAN1_MB25_TIMESTAMP)
+#define bfin_write_CAN1_MB25_TIMESTAMP(val)	bfin_write16(CAN1_MB25_TIMESTAMP, val)
+#define bfin_read_CAN1_MB25_ID0()		bfin_read16(CAN1_MB25_ID0)
+#define bfin_write_CAN1_MB25_ID0(val)		bfin_write16(CAN1_MB25_ID0, val)
+#define bfin_read_CAN1_MB25_ID1()		bfin_read16(CAN1_MB25_ID1)
+#define bfin_write_CAN1_MB25_ID1(val)		bfin_write16(CAN1_MB25_ID1, val)
+#define bfin_read_CAN1_MB26_DATA0()		bfin_read16(CAN1_MB26_DATA0)
+#define bfin_write_CAN1_MB26_DATA0(val)		bfin_write16(CAN1_MB26_DATA0, val)
+#define bfin_read_CAN1_MB26_DATA1()		bfin_read16(CAN1_MB26_DATA1)
+#define bfin_write_CAN1_MB26_DATA1(val)		bfin_write16(CAN1_MB26_DATA1, val)
+#define bfin_read_CAN1_MB26_DATA2()		bfin_read16(CAN1_MB26_DATA2)
+#define bfin_write_CAN1_MB26_DATA2(val)		bfin_write16(CAN1_MB26_DATA2, val)
+#define bfin_read_CAN1_MB26_DATA3()		bfin_read16(CAN1_MB26_DATA3)
+#define bfin_write_CAN1_MB26_DATA3(val)		bfin_write16(CAN1_MB26_DATA3, val)
+#define bfin_read_CAN1_MB26_LENGTH()		bfin_read16(CAN1_MB26_LENGTH)
+#define bfin_write_CAN1_MB26_LENGTH(val)	bfin_write16(CAN1_MB26_LENGTH, val)
+#define bfin_read_CAN1_MB26_TIMESTAMP()		bfin_read16(CAN1_MB26_TIMESTAMP)
+#define bfin_write_CAN1_MB26_TIMESTAMP(val)	bfin_write16(CAN1_MB26_TIMESTAMP, val)
+#define bfin_read_CAN1_MB26_ID0()		bfin_read16(CAN1_MB26_ID0)
+#define bfin_write_CAN1_MB26_ID0(val)		bfin_write16(CAN1_MB26_ID0, val)
+#define bfin_read_CAN1_MB26_ID1()		bfin_read16(CAN1_MB26_ID1)
+#define bfin_write_CAN1_MB26_ID1(val)		bfin_write16(CAN1_MB26_ID1, val)
+#define bfin_read_CAN1_MB27_DATA0()		bfin_read16(CAN1_MB27_DATA0)
+#define bfin_write_CAN1_MB27_DATA0(val)		bfin_write16(CAN1_MB27_DATA0, val)
+#define bfin_read_CAN1_MB27_DATA1()		bfin_read16(CAN1_MB27_DATA1)
+#define bfin_write_CAN1_MB27_DATA1(val)		bfin_write16(CAN1_MB27_DATA1, val)
+#define bfin_read_CAN1_MB27_DATA2()		bfin_read16(CAN1_MB27_DATA2)
+#define bfin_write_CAN1_MB27_DATA2(val)		bfin_write16(CAN1_MB27_DATA2, val)
+#define bfin_read_CAN1_MB27_DATA3()		bfin_read16(CAN1_MB27_DATA3)
+#define bfin_write_CAN1_MB27_DATA3(val)		bfin_write16(CAN1_MB27_DATA3, val)
+#define bfin_read_CAN1_MB27_LENGTH()		bfin_read16(CAN1_MB27_LENGTH)
+#define bfin_write_CAN1_MB27_LENGTH(val)	bfin_write16(CAN1_MB27_LENGTH, val)
+#define bfin_read_CAN1_MB27_TIMESTAMP()		bfin_read16(CAN1_MB27_TIMESTAMP)
+#define bfin_write_CAN1_MB27_TIMESTAMP(val)	bfin_write16(CAN1_MB27_TIMESTAMP, val)
+#define bfin_read_CAN1_MB27_ID0()		bfin_read16(CAN1_MB27_ID0)
+#define bfin_write_CAN1_MB27_ID0(val)		bfin_write16(CAN1_MB27_ID0, val)
+#define bfin_read_CAN1_MB27_ID1()		bfin_read16(CAN1_MB27_ID1)
+#define bfin_write_CAN1_MB27_ID1(val)		bfin_write16(CAN1_MB27_ID1, val)
+#define bfin_read_CAN1_MB28_DATA0()		bfin_read16(CAN1_MB28_DATA0)
+#define bfin_write_CAN1_MB28_DATA0(val)		bfin_write16(CAN1_MB28_DATA0, val)
+#define bfin_read_CAN1_MB28_DATA1()		bfin_read16(CAN1_MB28_DATA1)
+#define bfin_write_CAN1_MB28_DATA1(val)		bfin_write16(CAN1_MB28_DATA1, val)
+#define bfin_read_CAN1_MB28_DATA2()		bfin_read16(CAN1_MB28_DATA2)
+#define bfin_write_CAN1_MB28_DATA2(val)		bfin_write16(CAN1_MB28_DATA2, val)
+#define bfin_read_CAN1_MB28_DATA3()		bfin_read16(CAN1_MB28_DATA3)
+#define bfin_write_CAN1_MB28_DATA3(val)		bfin_write16(CAN1_MB28_DATA3, val)
+#define bfin_read_CAN1_MB28_LENGTH()		bfin_read16(CAN1_MB28_LENGTH)
+#define bfin_write_CAN1_MB28_LENGTH(val)	bfin_write16(CAN1_MB28_LENGTH, val)
+#define bfin_read_CAN1_MB28_TIMESTAMP()		bfin_read16(CAN1_MB28_TIMESTAMP)
+#define bfin_write_CAN1_MB28_TIMESTAMP(val)	bfin_write16(CAN1_MB28_TIMESTAMP, val)
+#define bfin_read_CAN1_MB28_ID0()		bfin_read16(CAN1_MB28_ID0)
+#define bfin_write_CAN1_MB28_ID0(val)		bfin_write16(CAN1_MB28_ID0, val)
+#define bfin_read_CAN1_MB28_ID1()		bfin_read16(CAN1_MB28_ID1)
+#define bfin_write_CAN1_MB28_ID1(val)		bfin_write16(CAN1_MB28_ID1, val)
+#define bfin_read_CAN1_MB29_DATA0()		bfin_read16(CAN1_MB29_DATA0)
+#define bfin_write_CAN1_MB29_DATA0(val)		bfin_write16(CAN1_MB29_DATA0, val)
+#define bfin_read_CAN1_MB29_DATA1()		bfin_read16(CAN1_MB29_DATA1)
+#define bfin_write_CAN1_MB29_DATA1(val)		bfin_write16(CAN1_MB29_DATA1, val)
+#define bfin_read_CAN1_MB29_DATA2()		bfin_read16(CAN1_MB29_DATA2)
+#define bfin_write_CAN1_MB29_DATA2(val)		bfin_write16(CAN1_MB29_DATA2, val)
+#define bfin_read_CAN1_MB29_DATA3()		bfin_read16(CAN1_MB29_DATA3)
+#define bfin_write_CAN1_MB29_DATA3(val)		bfin_write16(CAN1_MB29_DATA3, val)
+#define bfin_read_CAN1_MB29_LENGTH()		bfin_read16(CAN1_MB29_LENGTH)
+#define bfin_write_CAN1_MB29_LENGTH(val)	bfin_write16(CAN1_MB29_LENGTH, val)
+#define bfin_read_CAN1_MB29_TIMESTAMP()		bfin_read16(CAN1_MB29_TIMESTAMP)
+#define bfin_write_CAN1_MB29_TIMESTAMP(val)	bfin_write16(CAN1_MB29_TIMESTAMP, val)
+#define bfin_read_CAN1_MB29_ID0()		bfin_read16(CAN1_MB29_ID0)
+#define bfin_write_CAN1_MB29_ID0(val)		bfin_write16(CAN1_MB29_ID0, val)
+#define bfin_read_CAN1_MB29_ID1()		bfin_read16(CAN1_MB29_ID1)
+#define bfin_write_CAN1_MB29_ID1(val)		bfin_write16(CAN1_MB29_ID1, val)
+#define bfin_read_CAN1_MB30_DATA0()		bfin_read16(CAN1_MB30_DATA0)
+#define bfin_write_CAN1_MB30_DATA0(val)		bfin_write16(CAN1_MB30_DATA0, val)
+#define bfin_read_CAN1_MB30_DATA1()		bfin_read16(CAN1_MB30_DATA1)
+#define bfin_write_CAN1_MB30_DATA1(val)		bfin_write16(CAN1_MB30_DATA1, val)
+#define bfin_read_CAN1_MB30_DATA2()		bfin_read16(CAN1_MB30_DATA2)
+#define bfin_write_CAN1_MB30_DATA2(val)		bfin_write16(CAN1_MB30_DATA2, val)
+#define bfin_read_CAN1_MB30_DATA3()		bfin_read16(CAN1_MB30_DATA3)
+#define bfin_write_CAN1_MB30_DATA3(val)		bfin_write16(CAN1_MB30_DATA3, val)
+#define bfin_read_CAN1_MB30_LENGTH()		bfin_read16(CAN1_MB30_LENGTH)
+#define bfin_write_CAN1_MB30_LENGTH(val)	bfin_write16(CAN1_MB30_LENGTH, val)
+#define bfin_read_CAN1_MB30_TIMESTAMP()		bfin_read16(CAN1_MB30_TIMESTAMP)
+#define bfin_write_CAN1_MB30_TIMESTAMP(val)	bfin_write16(CAN1_MB30_TIMESTAMP, val)
+#define bfin_read_CAN1_MB30_ID0()		bfin_read16(CAN1_MB30_ID0)
+#define bfin_write_CAN1_MB30_ID0(val)		bfin_write16(CAN1_MB30_ID0, val)
+#define bfin_read_CAN1_MB30_ID1()		bfin_read16(CAN1_MB30_ID1)
+#define bfin_write_CAN1_MB30_ID1(val)		bfin_write16(CAN1_MB30_ID1, val)
+#define bfin_read_CAN1_MB31_DATA0()		bfin_read16(CAN1_MB31_DATA0)
+#define bfin_write_CAN1_MB31_DATA0(val)		bfin_write16(CAN1_MB31_DATA0, val)
+#define bfin_read_CAN1_MB31_DATA1()		bfin_read16(CAN1_MB31_DATA1)
+#define bfin_write_CAN1_MB31_DATA1(val)		bfin_write16(CAN1_MB31_DATA1, val)
+#define bfin_read_CAN1_MB31_DATA2()		bfin_read16(CAN1_MB31_DATA2)
+#define bfin_write_CAN1_MB31_DATA2(val)		bfin_write16(CAN1_MB31_DATA2, val)
+#define bfin_read_CAN1_MB31_DATA3()		bfin_read16(CAN1_MB31_DATA3)
+#define bfin_write_CAN1_MB31_DATA3(val)		bfin_write16(CAN1_MB31_DATA3, val)
+#define bfin_read_CAN1_MB31_LENGTH()		bfin_read16(CAN1_MB31_LENGTH)
+#define bfin_write_CAN1_MB31_LENGTH(val)	bfin_write16(CAN1_MB31_LENGTH, val)
+#define bfin_read_CAN1_MB31_TIMESTAMP()		bfin_read16(CAN1_MB31_TIMESTAMP)
+#define bfin_write_CAN1_MB31_TIMESTAMP(val)	bfin_write16(CAN1_MB31_TIMESTAMP, val)
+#define bfin_read_CAN1_MB31_ID0()		bfin_read16(CAN1_MB31_ID0)
+#define bfin_write_CAN1_MB31_ID0(val)		bfin_write16(CAN1_MB31_ID0, val)
+#define bfin_read_CAN1_MB31_ID1()		bfin_read16(CAN1_MB31_ID1)
+#define bfin_write_CAN1_MB31_ID1(val)		bfin_write16(CAN1_MB31_ID1, val)
+
+/* HOST Port Registers */
+
+#define bfin_read_HOST_CONTROL()		bfin_read16(HOST_CONTROL)
+#define bfin_write_HOST_CONTROL(val)		bfin_write16(HOST_CONTROL, val)
+#define bfin_read_HOST_STATUS()		bfin_read16(HOST_STATUS)
+#define bfin_write_HOST_STATUS(val)		bfin_write16(HOST_STATUS, val)
+#define bfin_read_HOST_TIMEOUT()		bfin_read16(HOST_TIMEOUT)
+#define bfin_write_HOST_TIMEOUT(val)		bfin_write16(HOST_TIMEOUT, val)
+
+/* Pixel Combfin_read_()ositor (PIXC) Registers */
+
+#define bfin_read_PIXC_CTL()		bfin_read16(PIXC_CTL)
+#define bfin_write_PIXC_CTL(val)	bfin_write16(PIXC_CTL, val)
+#define bfin_read_PIXC_PPL()		bfin_read16(PIXC_PPL)
+#define bfin_write_PIXC_PPL(val)	bfin_write16(PIXC_PPL, val)
+#define bfin_read_PIXC_LPF()		bfin_read16(PIXC_LPF)
+#define bfin_write_PIXC_LPF(val)	bfin_write16(PIXC_LPF, val)
+#define bfin_read_PIXC_AHSTART()	bfin_read16(PIXC_AHSTART)
+#define bfin_write_PIXC_AHSTART(val)	bfin_write16(PIXC_AHSTART, val)
+#define bfin_read_PIXC_AHEND()		bfin_read16(PIXC_AHEND)
+#define bfin_write_PIXC_AHEND(val)	bfin_write16(PIXC_AHEND, val)
+#define bfin_read_PIXC_AVSTART()	bfin_read16(PIXC_AVSTART)
+#define bfin_write_PIXC_AVSTART(val)	bfin_write16(PIXC_AVSTART, val)
+#define bfin_read_PIXC_AVEND()		bfin_read16(PIXC_AVEND)
+#define bfin_write_PIXC_AVEND(val)	bfin_write16(PIXC_AVEND, val)
+#define bfin_read_PIXC_ATRANSP()	bfin_read16(PIXC_ATRANSP)
+#define bfin_write_PIXC_ATRANSP(val)	bfin_write16(PIXC_ATRANSP, val)
+#define bfin_read_PIXC_BHSTART()	bfin_read16(PIXC_BHSTART)
+#define bfin_write_PIXC_BHSTART(val)	bfin_write16(PIXC_BHSTART, val)
+#define bfin_read_PIXC_BHEND()		bfin_read16(PIXC_BHEND)
+#define bfin_write_PIXC_BHEND(val)	bfin_write16(PIXC_BHEND, val)
+#define bfin_read_PIXC_BVSTART()	bfin_read16(PIXC_BVSTART)
+#define bfin_write_PIXC_BVSTART(val)	bfin_write16(PIXC_BVSTART, val)
+#define bfin_read_PIXC_BVEND()		bfin_read16(PIXC_BVEND)
+#define bfin_write_PIXC_BVEND(val)	bfin_write16(PIXC_BVEND, val)
+#define bfin_read_PIXC_BTRANSP()	bfin_read16(PIXC_BTRANSP)
+#define bfin_write_PIXC_BTRANSP(val)	bfin_write16(PIXC_BTRANSP, val)
+#define bfin_read_PIXC_INTRSTAT()	bfin_read16(PIXC_INTRSTAT)
+#define bfin_write_PIXC_INTRSTAT(val)	bfin_write16(PIXC_INTRSTAT, val)
+#define bfin_read_PIXC_RYCON()		bfin_read32(PIXC_RYCON)
+#define bfin_write_PIXC_RYCON(val)	bfin_write32(PIXC_RYCON, val)
+#define bfin_read_PIXC_GUCON()		bfin_read32(PIXC_GUCON)
+#define bfin_write_PIXC_GUCON(val)	bfin_write32(PIXC_GUCON, val)
+#define bfin_read_PIXC_BVCON()		bfin_read32(PIXC_BVCON)
+#define bfin_write_PIXC_BVCON(val)	bfin_write32(PIXC_BVCON, val)
+#define bfin_read_PIXC_CCBIAS()		bfin_read32(PIXC_CCBIAS)
+#define bfin_write_PIXC_CCBIAS(val)	bfin_write32(PIXC_CCBIAS, val)
+#define bfin_read_PIXC_TC()		bfin_read32(PIXC_TC)
+#define bfin_write_PIXC_TC(val)		bfin_write32(PIXC_TC, val)
+
+/* Handshake MDMA 0 Registers */
+
+#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
+#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
+#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
+#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
+#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
+#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
+#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
+#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
+#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
+#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
+#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
+#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
+#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
+#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
+
+/* Handshake MDMA 1 Registers */
+
+#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
+#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
+#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
+#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
+#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
+#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
+#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
+#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
+#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
+#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
+#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
+#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
+#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
+#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
+
+#endif /* _CDEF_BF544_H */
diff --git a/include/asm-blackfin/mach-bf548/cdefBF548.h b/include/asm-blackfin/mach-bf548/cdefBF548.h
new file mode 100644
index 0000000..674be02
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/cdefBF548.h
@@ -0,0 +1,1610 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/cdefBF548.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF548_H
+#define _CDEF_BF548_H
+
+/* include all Core registers and bit definitions */
+#include "defBF548.h"
+
+/* include core sbfin_read_()ecific register pointer definitions */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF548 */
+
+/* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
+#include "cdefBF54x_base.h"
+
+/* The following are the #defines needed by ADSP-BF548 that are not in the common header */
+
+/* Timer Registers */
+
+#define bfin_read_TIMER8_CONFIG()	bfin_read16(TIMER8_CONFIG)
+#define bfin_write_TIMER8_CONFIG(val)	bfin_write16(TIMER8_CONFIG, val)
+#define bfin_read_TIMER8_COUNTER()	bfin_read32(TIMER8_COUNTER)
+#define bfin_write_TIMER8_COUNTER(val)	bfin_write32(TIMER8_COUNTER, val)
+#define bfin_read_TIMER8_PERIOD()	bfin_read32(TIMER8_PERIOD)
+#define bfin_write_TIMER8_PERIOD(val)	bfin_write32(TIMER8_PERIOD, val)
+#define bfin_read_TIMER8_WIDTH()	bfin_read32(TIMER8_WIDTH)
+#define bfin_write_TIMER8_WIDTH(val)	bfin_write32(TIMER8_WIDTH, val)
+#define bfin_read_TIMER9_CONFIG()	bfin_read16(TIMER9_CONFIG)
+#define bfin_write_TIMER9_CONFIG(val)	bfin_write16(TIMER9_CONFIG, val)
+#define bfin_read_TIMER9_COUNTER()	bfin_read32(TIMER9_COUNTER)
+#define bfin_write_TIMER9_COUNTER(val)	bfin_write32(TIMER9_COUNTER, val)
+#define bfin_read_TIMER9_PERIOD()	bfin_read32(TIMER9_PERIOD)
+#define bfin_write_TIMER9_PERIOD(val)	bfin_write32(TIMER9_PERIOD, val)
+#define bfin_read_TIMER9_WIDTH()	bfin_read32(TIMER9_WIDTH)
+#define bfin_write_TIMER9_WIDTH(val)	bfin_write32(TIMER9_WIDTH, val)
+#define bfin_read_TIMER10_CONFIG()	bfin_read16(TIMER10_CONFIG)
+#define bfin_write_TIMER10_CONFIG(val)	bfin_write16(TIMER10_CONFIG, val)
+#define bfin_read_TIMER10_COUNTER()	bfin_read32(TIMER10_COUNTER)
+#define bfin_write_TIMER10_COUNTER(val)	bfin_write32(TIMER10_COUNTER, val)
+#define bfin_read_TIMER10_PERIOD()	bfin_read32(TIMER10_PERIOD)
+#define bfin_write_TIMER10_PERIOD(val)	bfin_write32(TIMER10_PERIOD, val)
+#define bfin_read_TIMER10_WIDTH()	bfin_read32(TIMER10_WIDTH)
+#define bfin_write_TIMER10_WIDTH(val)	bfin_write32(TIMER10_WIDTH, val)
+
+/* Timer Groubfin_read_() of 3 */
+
+#define bfin_read_TIMER_ENABLE1()	bfin_read16(TIMER_ENABLE1)
+#define bfin_write_TIMER_ENABLE1(val)	bfin_write16(TIMER_ENABLE1, val)
+#define bfin_read_TIMER_DISABLE1()	bfin_read16(TIMER_DISABLE1)
+#define bfin_write_TIMER_DISABLE1(val)	bfin_write16(TIMER_DISABLE1, val)
+#define bfin_read_TIMER_STATUS1()	bfin_read32(TIMER_STATUS1)
+#define bfin_write_TIMER_STATUS1(val)	bfin_write32(TIMER_STATUS1, val)
+
+/* SPORT0 Registers */
+
+#define bfin_read_SPORT0_TCR1()		bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val)	bfin_write16(SPORT0_TCR1, val)
+#define bfin_read_SPORT0_TCR2()		bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val)	bfin_write16(SPORT0_TCR2, val)
+#define bfin_read_SPORT0_TCLKDIV()	bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val)	bfin_write16(SPORT0_TCLKDIV, val)
+#define bfin_read_SPORT0_TFSDIV()	bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val)	bfin_write16(SPORT0_TFSDIV, val)
+#define bfin_read_SPORT0_TX()		bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val)	bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX()		bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val)	bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_RCR1()		bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val)	bfin_write16(SPORT0_RCR1, val)
+#define bfin_read_SPORT0_RCR2()		bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val)	bfin_write16(SPORT0_RCR2, val)
+#define bfin_read_SPORT0_RCLKDIV()	bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val)	bfin_write16(SPORT0_RCLKDIV, val)
+#define bfin_read_SPORT0_RFSDIV()	bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val)	bfin_write16(SPORT0_RFSDIV, val)
+#define bfin_read_SPORT0_STAT()		bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val)	bfin_write16(SPORT0_STAT, val)
+#define bfin_read_SPORT0_CHNL()		bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val)	bfin_write16(SPORT0_CHNL, val)
+#define bfin_read_SPORT0_MCMC1()	bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val)	bfin_write16(SPORT0_MCMC1, val)
+#define bfin_read_SPORT0_MCMC2()	bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val)	bfin_write16(SPORT0_MCMC2, val)
+#define bfin_read_SPORT0_MTCS0()	bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val)	bfin_write32(SPORT0_MTCS0, val)
+#define bfin_read_SPORT0_MTCS1()	bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val)	bfin_write32(SPORT0_MTCS1, val)
+#define bfin_read_SPORT0_MTCS2()	bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val)	bfin_write32(SPORT0_MTCS2, val)
+#define bfin_read_SPORT0_MTCS3()	bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val)	bfin_write32(SPORT0_MTCS3, val)
+#define bfin_read_SPORT0_MRCS0()	bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val)	bfin_write32(SPORT0_MRCS0, val)
+#define bfin_read_SPORT0_MRCS1()	bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val)	bfin_write32(SPORT0_MRCS1, val)
+#define bfin_read_SPORT0_MRCS2()	bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val)	bfin_write32(SPORT0_MRCS2, val)
+#define bfin_read_SPORT0_MRCS3()	bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val)	bfin_write32(SPORT0_MRCS3, val)
+
+/* EPPI0 Registers */
+
+#define bfin_read_EPPI0_STATUS()	bfin_read16(EPPI0_STATUS)
+#define bfin_write_EPPI0_STATUS(val)	bfin_write16(EPPI0_STATUS, val)
+#define bfin_read_EPPI0_HCOUNT()	bfin_read16(EPPI0_HCOUNT)
+#define bfin_write_EPPI0_HCOUNT(val)	bfin_write16(EPPI0_HCOUNT, val)
+#define bfin_read_EPPI0_HDELAY()	bfin_read16(EPPI0_HDELAY)
+#define bfin_write_EPPI0_HDELAY(val)	bfin_write16(EPPI0_HDELAY, val)
+#define bfin_read_EPPI0_VCOUNT()	bfin_read16(EPPI0_VCOUNT)
+#define bfin_write_EPPI0_VCOUNT(val)	bfin_write16(EPPI0_VCOUNT, val)
+#define bfin_read_EPPI0_VDELAY()	bfin_read16(EPPI0_VDELAY)
+#define bfin_write_EPPI0_VDELAY(val)	bfin_write16(EPPI0_VDELAY, val)
+#define bfin_read_EPPI0_FRAME()		bfin_read16(EPPI0_FRAME)
+#define bfin_write_EPPI0_FRAME(val)	bfin_write16(EPPI0_FRAME, val)
+#define bfin_read_EPPI0_LINE()		bfin_read16(EPPI0_LINE)
+#define bfin_write_EPPI0_LINE(val)	bfin_write16(EPPI0_LINE, val)
+#define bfin_read_EPPI0_CLKDIV()	bfin_read16(EPPI0_CLKDIV)
+#define bfin_write_EPPI0_CLKDIV(val)	bfin_write16(EPPI0_CLKDIV, val)
+#define bfin_read_EPPI0_CONTROL()	bfin_read32(EPPI0_CONTROL)
+#define bfin_write_EPPI0_CONTROL(val)	bfin_write32(EPPI0_CONTROL, val)
+#define bfin_read_EPPI0_FS1W_HBL()	bfin_read32(EPPI0_FS1W_HBL)
+#define bfin_write_EPPI0_FS1W_HBL(val)	bfin_write32(EPPI0_FS1W_HBL, val)
+#define bfin_read_EPPI0_FS1P_AVPL()	bfin_read32(EPPI0_FS1P_AVPL)
+#define bfin_write_EPPI0_FS1P_AVPL(val)	bfin_write32(EPPI0_FS1P_AVPL, val)
+#define bfin_read_EPPI0_FS2W_LVB()	bfin_read32(EPPI0_FS2W_LVB)
+#define bfin_write_EPPI0_FS2W_LVB(val)	bfin_write32(EPPI0_FS2W_LVB, val)
+#define bfin_read_EPPI0_FS2P_LAVF()	bfin_read32(EPPI0_FS2P_LAVF)
+#define bfin_write_EPPI0_FS2P_LAVF(val)	bfin_write32(EPPI0_FS2P_LAVF, val)
+#define bfin_read_EPPI0_CLIP()		bfin_read32(EPPI0_CLIP)
+#define bfin_write_EPPI0_CLIP(val)	bfin_write32(EPPI0_CLIP, val)
+
+/* UART2 Registers */
+
+#define bfin_read_UART2_DLL()		bfin_read16(UART2_DLL)
+#define bfin_write_UART2_DLL(val)	bfin_write16(UART2_DLL, val)
+#define bfin_read_UART2_DLH()		bfin_read16(UART2_DLH)
+#define bfin_write_UART2_DLH(val)	bfin_write16(UART2_DLH, val)
+#define bfin_read_UART2_GCTL()		bfin_read16(UART2_GCTL)
+#define bfin_write_UART2_GCTL(val)	bfin_write16(UART2_GCTL, val)
+#define bfin_read_UART2_LCR()		bfin_read16(UART2_LCR)
+#define bfin_write_UART2_LCR(val)	bfin_write16(UART2_LCR, val)
+#define bfin_read_UART2_MCR()		bfin_read16(UART2_MCR)
+#define bfin_write_UART2_MCR(val)	bfin_write16(UART2_MCR, val)
+#define bfin_read_UART2_LSR()		bfin_read16(UART2_LSR)
+#define bfin_write_UART2_LSR(val)	bfin_write16(UART2_LSR, val)
+#define bfin_read_UART2_MSR()		bfin_read16(UART2_MSR)
+#define bfin_write_UART2_MSR(val)	bfin_write16(UART2_MSR, val)
+#define bfin_read_UART2_SCR()		bfin_read16(UART2_SCR)
+#define bfin_write_UART2_SCR(val)	bfin_write16(UART2_SCR, val)
+#define bfin_read_UART2_IER_SET()	bfin_read16(UART2_IER_SET)
+#define bfin_write_UART2_IER_SET(val)	bfin_write16(UART2_IER_SET, val)
+#define bfin_read_UART2_IER_CLEAR()	bfin_read16(UART2_IER_CLEAR)
+#define bfin_write_UART2_IER_CLEAR(val)	bfin_write16(UART2_IER_CLEAR, val)
+#define bfin_read_UART2_RBR()		bfin_read16(UART2_RBR)
+#define bfin_write_UART2_RBR(val)	bfin_write16(UART2_RBR, val)
+
+/* Two Wire Interface Registers (TWI1) */
+
+#define bfin_read_TWI1_CLKDIV()			bfin_read16(TWI1_CLKDIV)
+#define bfin_write_TWI1_CLKDIV(val)		bfin_write16(TWI1_CLKDIV, val)
+#define bfin_read_TWI1_CONTROL()		bfin_read16(TWI1_CONTROL)
+#define bfin_write_TWI1_CONTROL(val)		bfin_write16(TWI1_CONTROL, val)
+#define bfin_read_TWI1_SLAVE_CTRL()		bfin_read16(TWI1_SLAVE_CTRL)
+#define bfin_write_TWI1_SLAVE_CTRL(val)		bfin_write16(TWI1_SLAVE_CTRL, val)
+#define bfin_read_TWI1_SLAVE_STAT()		bfin_read16(TWI1_SLAVE_STAT)
+#define bfin_write_TWI1_SLAVE_STAT(val)		bfin_write16(TWI1_SLAVE_STAT, val)
+#define bfin_read_TWI1_SLAVE_ADDR()		bfin_read16(TWI1_SLAVE_ADDR)
+#define bfin_write_TWI1_SLAVE_ADDR(val)		bfin_write16(TWI1_SLAVE_ADDR, val)
+#define bfin_read_TWI1_MASTER_CTRL()		bfin_read16(TWI1_MASTER_CTRL)
+#define bfin_write_TWI1_MASTER_CTRL(val)	bfin_write16(TWI1_MASTER_CTRL, val)
+#define bfin_read_TWI1_MASTER_STAT()		bfin_read16(TWI1_MASTER_STAT)
+#define bfin_write_TWI1_MASTER_STAT(val)	bfin_write16(TWI1_MASTER_STAT, val)
+#define bfin_read_TWI1_MASTER_ADDR()		bfin_read16(TWI1_MASTER_ADDR)
+#define bfin_write_TWI1_MASTER_ADDR(val)	bfin_write16(TWI1_MASTER_ADDR, val)
+#define bfin_read_TWI1_INT_STAT()		bfin_read16(TWI1_INT_STAT)
+#define bfin_write_TWI1_INT_STAT(val)		bfin_write16(TWI1_INT_STAT, val)
+#define bfin_read_TWI1_INT_MASK()		bfin_read16(TWI1_INT_MASK)
+#define bfin_write_TWI1_INT_MASK(val)		bfin_write16(TWI1_INT_MASK, val)
+#define bfin_read_TWI1_FIFO_CTRL()		bfin_read16(TWI1_FIFO_CTRL)
+#define bfin_write_TWI1_FIFO_CTRL(val)		bfin_write16(TWI1_FIFO_CTRL, val)
+#define bfin_read_TWI1_FIFO_STAT()		bfin_read16(TWI1_FIFO_STAT)
+#define bfin_write_TWI1_FIFO_STAT(val)		bfin_write16(TWI1_FIFO_STAT, val)
+#define bfin_read_TWI1_XMT_DATA8()		bfin_read16(TWI1_XMT_DATA8)
+#define bfin_write_TWI1_XMT_DATA8(val)		bfin_write16(TWI1_XMT_DATA8, val)
+#define bfin_read_TWI1_XMT_DATA16()		bfin_read16(TWI1_XMT_DATA16)
+#define bfin_write_TWI1_XMT_DATA16(val)		bfin_write16(TWI1_XMT_DATA16, val)
+#define bfin_read_TWI1_RCV_DATA8()		bfin_read16(TWI1_RCV_DATA8)
+#define bfin_write_TWI1_RCV_DATA8(val)		bfin_write16(TWI1_RCV_DATA8, val)
+#define bfin_read_TWI1_RCV_DATA16()		bfin_read16(TWI1_RCV_DATA16)
+#define bfin_write_TWI1_RCV_DATA16(val)		bfin_write16(TWI1_RCV_DATA16, val)
+
+/* SPI2  Registers */
+
+#define bfin_read_SPI2_CTL()		bfin_read16(SPI2_CTL)
+#define bfin_write_SPI2_CTL(val)	bfin_write16(SPI2_CTL, val)
+#define bfin_read_SPI2_FLG()		bfin_read16(SPI2_FLG)
+#define bfin_write_SPI2_FLG(val)	bfin_write16(SPI2_FLG, val)
+#define bfin_read_SPI2_STAT()		bfin_read16(SPI2_STAT)
+#define bfin_write_SPI2_STAT(val)	bfin_write16(SPI2_STAT, val)
+#define bfin_read_SPI2_TDBR()		bfin_read16(SPI2_TDBR)
+#define bfin_write_SPI2_TDBR(val)	bfin_write16(SPI2_TDBR, val)
+#define bfin_read_SPI2_RDBR()		bfin_read16(SPI2_RDBR)
+#define bfin_write_SPI2_RDBR(val)	bfin_write16(SPI2_RDBR, val)
+#define bfin_read_SPI2_BAUD()		bfin_read16(SPI2_BAUD)
+#define bfin_write_SPI2_BAUD(val)	bfin_write16(SPI2_BAUD, val)
+#define bfin_read_SPI2_SHADOW()		bfin_read16(SPI2_SHADOW)
+#define bfin_write_SPI2_SHADOW(val)	bfin_write16(SPI2_SHADOW, val)
+
+/* CAN Controller 1 Config 1 Registers */
+
+#define bfin_read_CAN1_MC1()		bfin_read16(CAN1_MC1)
+#define bfin_write_CAN1_MC1(val)	bfin_write16(CAN1_MC1, val)
+#define bfin_read_CAN1_MD1()		bfin_read16(CAN1_MD1)
+#define bfin_write_CAN1_MD1(val)	bfin_write16(CAN1_MD1, val)
+#define bfin_read_CAN1_TRS1()		bfin_read16(CAN1_TRS1)
+#define bfin_write_CAN1_TRS1(val)	bfin_write16(CAN1_TRS1, val)
+#define bfin_read_CAN1_TRR1()		bfin_read16(CAN1_TRR1)
+#define bfin_write_CAN1_TRR1(val)	bfin_write16(CAN1_TRR1, val)
+#define bfin_read_CAN1_TA1()		bfin_read16(CAN1_TA1)
+#define bfin_write_CAN1_TA1(val)	bfin_write16(CAN1_TA1, val)
+#define bfin_read_CAN1_AA1()		bfin_read16(CAN1_AA1)
+#define bfin_write_CAN1_AA1(val)	bfin_write16(CAN1_AA1, val)
+#define bfin_read_CAN1_RMP1()		bfin_read16(CAN1_RMP1)
+#define bfin_write_CAN1_RMP1(val)	bfin_write16(CAN1_RMP1, val)
+#define bfin_read_CAN1_RML1()		bfin_read16(CAN1_RML1)
+#define bfin_write_CAN1_RML1(val)	bfin_write16(CAN1_RML1, val)
+#define bfin_read_CAN1_MBTIF1()		bfin_read16(CAN1_MBTIF1)
+#define bfin_write_CAN1_MBTIF1(val)	bfin_write16(CAN1_MBTIF1, val)
+#define bfin_read_CAN1_MBRIF1()		bfin_read16(CAN1_MBRIF1)
+#define bfin_write_CAN1_MBRIF1(val)	bfin_write16(CAN1_MBRIF1, val)
+#define bfin_read_CAN1_MBIM1()		bfin_read16(CAN1_MBIM1)
+#define bfin_write_CAN1_MBIM1(val)	bfin_write16(CAN1_MBIM1, val)
+#define bfin_read_CAN1_RFH1()		bfin_read16(CAN1_RFH1)
+#define bfin_write_CAN1_RFH1(val)	bfin_write16(CAN1_RFH1, val)
+#define bfin_read_CAN1_OPSS1()		bfin_read16(CAN1_OPSS1)
+#define bfin_write_CAN1_OPSS1(val)	bfin_write16(CAN1_OPSS1, val)
+
+/* CAN Controller 1 Config 2 Registers */
+
+#define bfin_read_CAN1_MC2()		bfin_read16(CAN1_MC2)
+#define bfin_write_CAN1_MC2(val)	bfin_write16(CAN1_MC2, val)
+#define bfin_read_CAN1_MD2()		bfin_read16(CAN1_MD2)
+#define bfin_write_CAN1_MD2(val)	bfin_write16(CAN1_MD2, val)
+#define bfin_read_CAN1_TRS2()		bfin_read16(CAN1_TRS2)
+#define bfin_write_CAN1_TRS2(val)	bfin_write16(CAN1_TRS2, val)
+#define bfin_read_CAN1_TRR2()		bfin_read16(CAN1_TRR2)
+#define bfin_write_CAN1_TRR2(val)	bfin_write16(CAN1_TRR2, val)
+#define bfin_read_CAN1_TA2()		bfin_read16(CAN1_TA2)
+#define bfin_write_CAN1_TA2(val)	bfin_write16(CAN1_TA2, val)
+#define bfin_read_CAN1_AA2()		bfin_read16(CAN1_AA2)
+#define bfin_write_CAN1_AA2(val)	bfin_write16(CAN1_AA2, val)
+#define bfin_read_CAN1_RMP2()		bfin_read16(CAN1_RMP2)
+#define bfin_write_CAN1_RMP2(val)	bfin_write16(CAN1_RMP2, val)
+#define bfin_read_CAN1_RML2()		bfin_read16(CAN1_RML2)
+#define bfin_write_CAN1_RML2(val)	bfin_write16(CAN1_RML2, val)
+#define bfin_read_CAN1_MBTIF2()		bfin_read16(CAN1_MBTIF2)
+#define bfin_write_CAN1_MBTIF2(val)	bfin_write16(CAN1_MBTIF2, val)
+#define bfin_read_CAN1_MBRIF2()		bfin_read16(CAN1_MBRIF2)
+#define bfin_write_CAN1_MBRIF2(val)	bfin_write16(CAN1_MBRIF2, val)
+#define bfin_read_CAN1_MBIM2()		bfin_read16(CAN1_MBIM2)
+#define bfin_write_CAN1_MBIM2(val)	bfin_write16(CAN1_MBIM2, val)
+#define bfin_read_CAN1_RFH2()		bfin_read16(CAN1_RFH2)
+#define bfin_write_CAN1_RFH2(val)	bfin_write16(CAN1_RFH2, val)
+#define bfin_read_CAN1_OPSS2()		bfin_read16(CAN1_OPSS2)
+#define bfin_write_CAN1_OPSS2(val)	bfin_write16(CAN1_OPSS2, val)
+
+/* CAN Controller 1 Clock/Interrubfin_read_()t/Counter Registers */
+
+#define bfin_read_CAN1_CLOCK()		bfin_read16(CAN1_CLOCK)
+#define bfin_write_CAN1_CLOCK(val)	bfin_write16(CAN1_CLOCK, val)
+#define bfin_read_CAN1_TIMING()		bfin_read16(CAN1_TIMING)
+#define bfin_write_CAN1_TIMING(val)	bfin_write16(CAN1_TIMING, val)
+#define bfin_read_CAN1_DEBUG()		bfin_read16(CAN1_DEBUG)
+#define bfin_write_CAN1_DEBUG(val)	bfin_write16(CAN1_DEBUG, val)
+#define bfin_read_CAN1_STATUS()		bfin_read16(CAN1_STATUS)
+#define bfin_write_CAN1_STATUS(val)	bfin_write16(CAN1_STATUS, val)
+#define bfin_read_CAN1_CEC()		bfin_read16(CAN1_CEC)
+#define bfin_write_CAN1_CEC(val)	bfin_write16(CAN1_CEC, val)
+#define bfin_read_CAN1_GIS()		bfin_read16(CAN1_GIS)
+#define bfin_write_CAN1_GIS(val)	bfin_write16(CAN1_GIS, val)
+#define bfin_read_CAN1_GIM()		bfin_read16(CAN1_GIM)
+#define bfin_write_CAN1_GIM(val)	bfin_write16(CAN1_GIM, val)
+#define bfin_read_CAN1_GIF()		bfin_read16(CAN1_GIF)
+#define bfin_write_CAN1_GIF(val)	bfin_write16(CAN1_GIF, val)
+#define bfin_read_CAN1_CONTROL()	bfin_read16(CAN1_CONTROL)
+#define bfin_write_CAN1_CONTROL(val)	bfin_write16(CAN1_CONTROL, val)
+#define bfin_read_CAN1_INTR()		bfin_read16(CAN1_INTR)
+#define bfin_write_CAN1_INTR(val)	bfin_write16(CAN1_INTR, val)
+#define bfin_read_CAN1_MBTD()		bfin_read16(CAN1_MBTD)
+#define bfin_write_CAN1_MBTD(val)	bfin_write16(CAN1_MBTD, val)
+#define bfin_read_CAN1_EWR()		bfin_read16(CAN1_EWR)
+#define bfin_write_CAN1_EWR(val)	bfin_write16(CAN1_EWR, val)
+#define bfin_read_CAN1_ESR()		bfin_read16(CAN1_ESR)
+#define bfin_write_CAN1_ESR(val)	bfin_write16(CAN1_ESR, val)
+#define bfin_read_CAN1_UCCNT()		bfin_read16(CAN1_UCCNT)
+#define bfin_write_CAN1_UCCNT(val)	bfin_write16(CAN1_UCCNT, val)
+#define bfin_read_CAN1_UCRC()		bfin_read16(CAN1_UCRC)
+#define bfin_write_CAN1_UCRC(val)	bfin_write16(CAN1_UCRC, val)
+#define bfin_read_CAN1_UCCNF()		bfin_read16(CAN1_UCCNF)
+#define bfin_write_CAN1_UCCNF(val)	bfin_write16(CAN1_UCCNF, val)
+
+/* CAN Controller 1 Mailbox Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN1_AM00L()		bfin_read16(CAN1_AM00L)
+#define bfin_write_CAN1_AM00L(val)	bfin_write16(CAN1_AM00L, val)
+#define bfin_read_CAN1_AM00H()		bfin_read16(CAN1_AM00H)
+#define bfin_write_CAN1_AM00H(val)	bfin_write16(CAN1_AM00H, val)
+#define bfin_read_CAN1_AM01L()		bfin_read16(CAN1_AM01L)
+#define bfin_write_CAN1_AM01L(val)	bfin_write16(CAN1_AM01L, val)
+#define bfin_read_CAN1_AM01H()		bfin_read16(CAN1_AM01H)
+#define bfin_write_CAN1_AM01H(val)	bfin_write16(CAN1_AM01H, val)
+#define bfin_read_CAN1_AM02L()		bfin_read16(CAN1_AM02L)
+#define bfin_write_CAN1_AM02L(val)	bfin_write16(CAN1_AM02L, val)
+#define bfin_read_CAN1_AM02H()		bfin_read16(CAN1_AM02H)
+#define bfin_write_CAN1_AM02H(val)	bfin_write16(CAN1_AM02H, val)
+#define bfin_read_CAN1_AM03L()		bfin_read16(CAN1_AM03L)
+#define bfin_write_CAN1_AM03L(val)	bfin_write16(CAN1_AM03L, val)
+#define bfin_read_CAN1_AM03H()		bfin_read16(CAN1_AM03H)
+#define bfin_write_CAN1_AM03H(val)	bfin_write16(CAN1_AM03H, val)
+#define bfin_read_CAN1_AM04L()		bfin_read16(CAN1_AM04L)
+#define bfin_write_CAN1_AM04L(val)	bfin_write16(CAN1_AM04L, val)
+#define bfin_read_CAN1_AM04H()		bfin_read16(CAN1_AM04H)
+#define bfin_write_CAN1_AM04H(val)	bfin_write16(CAN1_AM04H, val)
+#define bfin_read_CAN1_AM05L()		bfin_read16(CAN1_AM05L)
+#define bfin_write_CAN1_AM05L(val)	bfin_write16(CAN1_AM05L, val)
+#define bfin_read_CAN1_AM05H()		bfin_read16(CAN1_AM05H)
+#define bfin_write_CAN1_AM05H(val)	bfin_write16(CAN1_AM05H, val)
+#define bfin_read_CAN1_AM06L()		bfin_read16(CAN1_AM06L)
+#define bfin_write_CAN1_AM06L(val)	bfin_write16(CAN1_AM06L, val)
+#define bfin_read_CAN1_AM06H()		bfin_read16(CAN1_AM06H)
+#define bfin_write_CAN1_AM06H(val)	bfin_write16(CAN1_AM06H, val)
+#define bfin_read_CAN1_AM07L()		bfin_read16(CAN1_AM07L)
+#define bfin_write_CAN1_AM07L(val)	bfin_write16(CAN1_AM07L, val)
+#define bfin_read_CAN1_AM07H()		bfin_read16(CAN1_AM07H)
+#define bfin_write_CAN1_AM07H(val)	bfin_write16(CAN1_AM07H, val)
+#define bfin_read_CAN1_AM08L()		bfin_read16(CAN1_AM08L)
+#define bfin_write_CAN1_AM08L(val)	bfin_write16(CAN1_AM08L, val)
+#define bfin_read_CAN1_AM08H()		bfin_read16(CAN1_AM08H)
+#define bfin_write_CAN1_AM08H(val)	bfin_write16(CAN1_AM08H, val)
+#define bfin_read_CAN1_AM09L()		bfin_read16(CAN1_AM09L)
+#define bfin_write_CAN1_AM09L(val)	bfin_write16(CAN1_AM09L, val)
+#define bfin_read_CAN1_AM09H()		bfin_read16(CAN1_AM09H)
+#define bfin_write_CAN1_AM09H(val)	bfin_write16(CAN1_AM09H, val)
+#define bfin_read_CAN1_AM10L()		bfin_read16(CAN1_AM10L)
+#define bfin_write_CAN1_AM10L(val)	bfin_write16(CAN1_AM10L, val)
+#define bfin_read_CAN1_AM10H()		bfin_read16(CAN1_AM10H)
+#define bfin_write_CAN1_AM10H(val)	bfin_write16(CAN1_AM10H, val)
+#define bfin_read_CAN1_AM11L()		bfin_read16(CAN1_AM11L)
+#define bfin_write_CAN1_AM11L(val)	bfin_write16(CAN1_AM11L, val)
+#define bfin_read_CAN1_AM11H()		bfin_read16(CAN1_AM11H)
+#define bfin_write_CAN1_AM11H(val)	bfin_write16(CAN1_AM11H, val)
+#define bfin_read_CAN1_AM12L()		bfin_read16(CAN1_AM12L)
+#define bfin_write_CAN1_AM12L(val)	bfin_write16(CAN1_AM12L, val)
+#define bfin_read_CAN1_AM12H()		bfin_read16(CAN1_AM12H)
+#define bfin_write_CAN1_AM12H(val)	bfin_write16(CAN1_AM12H, val)
+#define bfin_read_CAN1_AM13L()		bfin_read16(CAN1_AM13L)
+#define bfin_write_CAN1_AM13L(val)	bfin_write16(CAN1_AM13L, val)
+#define bfin_read_CAN1_AM13H()		bfin_read16(CAN1_AM13H)
+#define bfin_write_CAN1_AM13H(val)	bfin_write16(CAN1_AM13H, val)
+#define bfin_read_CAN1_AM14L()		bfin_read16(CAN1_AM14L)
+#define bfin_write_CAN1_AM14L(val)	bfin_write16(CAN1_AM14L, val)
+#define bfin_read_CAN1_AM14H()		bfin_read16(CAN1_AM14H)
+#define bfin_write_CAN1_AM14H(val)	bfin_write16(CAN1_AM14H, val)
+#define bfin_read_CAN1_AM15L()		bfin_read16(CAN1_AM15L)
+#define bfin_write_CAN1_AM15L(val)	bfin_write16(CAN1_AM15L, val)
+#define bfin_read_CAN1_AM15H()		bfin_read16(CAN1_AM15H)
+#define bfin_write_CAN1_AM15H(val)	bfin_write16(CAN1_AM15H, val)
+
+/* CAN Controller 1 Mailbox Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN1_AM16L()		bfin_read16(CAN1_AM16L)
+#define bfin_write_CAN1_AM16L(val)	bfin_write16(CAN1_AM16L, val)
+#define bfin_read_CAN1_AM16H()		bfin_read16(CAN1_AM16H)
+#define bfin_write_CAN1_AM16H(val)	bfin_write16(CAN1_AM16H, val)
+#define bfin_read_CAN1_AM17L()		bfin_read16(CAN1_AM17L)
+#define bfin_write_CAN1_AM17L(val)	bfin_write16(CAN1_AM17L, val)
+#define bfin_read_CAN1_AM17H()		bfin_read16(CAN1_AM17H)
+#define bfin_write_CAN1_AM17H(val)	bfin_write16(CAN1_AM17H, val)
+#define bfin_read_CAN1_AM18L()		bfin_read16(CAN1_AM18L)
+#define bfin_write_CAN1_AM18L(val)	bfin_write16(CAN1_AM18L, val)
+#define bfin_read_CAN1_AM18H()		bfin_read16(CAN1_AM18H)
+#define bfin_write_CAN1_AM18H(val)	bfin_write16(CAN1_AM18H, val)
+#define bfin_read_CAN1_AM19L()		bfin_read16(CAN1_AM19L)
+#define bfin_write_CAN1_AM19L(val)	bfin_write16(CAN1_AM19L, val)
+#define bfin_read_CAN1_AM19H()		bfin_read16(CAN1_AM19H)
+#define bfin_write_CAN1_AM19H(val)	bfin_write16(CAN1_AM19H, val)
+#define bfin_read_CAN1_AM20L()		bfin_read16(CAN1_AM20L)
+#define bfin_write_CAN1_AM20L(val)	bfin_write16(CAN1_AM20L, val)
+#define bfin_read_CAN1_AM20H()		bfin_read16(CAN1_AM20H)
+#define bfin_write_CAN1_AM20H(val)	bfin_write16(CAN1_AM20H, val)
+#define bfin_read_CAN1_AM21L()		bfin_read16(CAN1_AM21L)
+#define bfin_write_CAN1_AM21L(val)	bfin_write16(CAN1_AM21L, val)
+#define bfin_read_CAN1_AM21H()		bfin_read16(CAN1_AM21H)
+#define bfin_write_CAN1_AM21H(val)	bfin_write16(CAN1_AM21H, val)
+#define bfin_read_CAN1_AM22L()		bfin_read16(CAN1_AM22L)
+#define bfin_write_CAN1_AM22L(val)	bfin_write16(CAN1_AM22L, val)
+#define bfin_read_CAN1_AM22H()		bfin_read16(CAN1_AM22H)
+#define bfin_write_CAN1_AM22H(val)	bfin_write16(CAN1_AM22H, val)
+#define bfin_read_CAN1_AM23L()		bfin_read16(CAN1_AM23L)
+#define bfin_write_CAN1_AM23L(val)	bfin_write16(CAN1_AM23L, val)
+#define bfin_read_CAN1_AM23H()		bfin_read16(CAN1_AM23H)
+#define bfin_write_CAN1_AM23H(val)	bfin_write16(CAN1_AM23H, val)
+#define bfin_read_CAN1_AM24L()		bfin_read16(CAN1_AM24L)
+#define bfin_write_CAN1_AM24L(val)	bfin_write16(CAN1_AM24L, val)
+#define bfin_read_CAN1_AM24H()		bfin_read16(CAN1_AM24H)
+#define bfin_write_CAN1_AM24H(val)	bfin_write16(CAN1_AM24H, val)
+#define bfin_read_CAN1_AM25L()		bfin_read16(CAN1_AM25L)
+#define bfin_write_CAN1_AM25L(val)	bfin_write16(CAN1_AM25L, val)
+#define bfin_read_CAN1_AM25H()		bfin_read16(CAN1_AM25H)
+#define bfin_write_CAN1_AM25H(val)	bfin_write16(CAN1_AM25H, val)
+#define bfin_read_CAN1_AM26L()		bfin_read16(CAN1_AM26L)
+#define bfin_write_CAN1_AM26L(val)	bfin_write16(CAN1_AM26L, val)
+#define bfin_read_CAN1_AM26H()		bfin_read16(CAN1_AM26H)
+#define bfin_write_CAN1_AM26H(val)	bfin_write16(CAN1_AM26H, val)
+#define bfin_read_CAN1_AM27L()		bfin_read16(CAN1_AM27L)
+#define bfin_write_CAN1_AM27L(val)	bfin_write16(CAN1_AM27L, val)
+#define bfin_read_CAN1_AM27H()		bfin_read16(CAN1_AM27H)
+#define bfin_write_CAN1_AM27H(val)	bfin_write16(CAN1_AM27H, val)
+#define bfin_read_CAN1_AM28L()		bfin_read16(CAN1_AM28L)
+#define bfin_write_CAN1_AM28L(val)	bfin_write16(CAN1_AM28L, val)
+#define bfin_read_CAN1_AM28H()		bfin_read16(CAN1_AM28H)
+#define bfin_write_CAN1_AM28H(val)	bfin_write16(CAN1_AM28H, val)
+#define bfin_read_CAN1_AM29L()		bfin_read16(CAN1_AM29L)
+#define bfin_write_CAN1_AM29L(val)	bfin_write16(CAN1_AM29L, val)
+#define bfin_read_CAN1_AM29H()		bfin_read16(CAN1_AM29H)
+#define bfin_write_CAN1_AM29H(val)	bfin_write16(CAN1_AM29H, val)
+#define bfin_read_CAN1_AM30L()		bfin_read16(CAN1_AM30L)
+#define bfin_write_CAN1_AM30L(val)	bfin_write16(CAN1_AM30L, val)
+#define bfin_read_CAN1_AM30H()		bfin_read16(CAN1_AM30H)
+#define bfin_write_CAN1_AM30H(val)	bfin_write16(CAN1_AM30H, val)
+#define bfin_read_CAN1_AM31L()		bfin_read16(CAN1_AM31L)
+#define bfin_write_CAN1_AM31L(val)	bfin_write16(CAN1_AM31L, val)
+#define bfin_read_CAN1_AM31H()		bfin_read16(CAN1_AM31H)
+#define bfin_write_CAN1_AM31H(val)	bfin_write16(CAN1_AM31H, val)
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define bfin_read_CAN1_MB00_DATA0()		bfin_read16(CAN1_MB00_DATA0)
+#define bfin_write_CAN1_MB00_DATA0(val)		bfin_write16(CAN1_MB00_DATA0, val)
+#define bfin_read_CAN1_MB00_DATA1()		bfin_read16(CAN1_MB00_DATA1)
+#define bfin_write_CAN1_MB00_DATA1(val)		bfin_write16(CAN1_MB00_DATA1, val)
+#define bfin_read_CAN1_MB00_DATA2()		bfin_read16(CAN1_MB00_DATA2)
+#define bfin_write_CAN1_MB00_DATA2(val)		bfin_write16(CAN1_MB00_DATA2, val)
+#define bfin_read_CAN1_MB00_DATA3()		bfin_read16(CAN1_MB00_DATA3)
+#define bfin_write_CAN1_MB00_DATA3(val)		bfin_write16(CAN1_MB00_DATA3, val)
+#define bfin_read_CAN1_MB00_LENGTH()		bfin_read16(CAN1_MB00_LENGTH)
+#define bfin_write_CAN1_MB00_LENGTH(val)	bfin_write16(CAN1_MB00_LENGTH, val)
+#define bfin_read_CAN1_MB00_TIMESTAMP()		bfin_read16(CAN1_MB00_TIMESTAMP)
+#define bfin_write_CAN1_MB00_TIMESTAMP(val)	bfin_write16(CAN1_MB00_TIMESTAMP, val)
+#define bfin_read_CAN1_MB00_ID0()		bfin_read16(CAN1_MB00_ID0)
+#define bfin_write_CAN1_MB00_ID0(val)		bfin_write16(CAN1_MB00_ID0, val)
+#define bfin_read_CAN1_MB00_ID1()		bfin_read16(CAN1_MB00_ID1)
+#define bfin_write_CAN1_MB00_ID1(val)		bfin_write16(CAN1_MB00_ID1, val)
+#define bfin_read_CAN1_MB01_DATA0()		bfin_read16(CAN1_MB01_DATA0)
+#define bfin_write_CAN1_MB01_DATA0(val)		bfin_write16(CAN1_MB01_DATA0, val)
+#define bfin_read_CAN1_MB01_DATA1()		bfin_read16(CAN1_MB01_DATA1)
+#define bfin_write_CAN1_MB01_DATA1(val)		bfin_write16(CAN1_MB01_DATA1, val)
+#define bfin_read_CAN1_MB01_DATA2()		bfin_read16(CAN1_MB01_DATA2)
+#define bfin_write_CAN1_MB01_DATA2(val)		bfin_write16(CAN1_MB01_DATA2, val)
+#define bfin_read_CAN1_MB01_DATA3()		bfin_read16(CAN1_MB01_DATA3)
+#define bfin_write_CAN1_MB01_DATA3(val)		bfin_write16(CAN1_MB01_DATA3, val)
+#define bfin_read_CAN1_MB01_LENGTH()		bfin_read16(CAN1_MB01_LENGTH)
+#define bfin_write_CAN1_MB01_LENGTH(val)	bfin_write16(CAN1_MB01_LENGTH, val)
+#define bfin_read_CAN1_MB01_TIMESTAMP()		bfin_read16(CAN1_MB01_TIMESTAMP)
+#define bfin_write_CAN1_MB01_TIMESTAMP(val)	bfin_write16(CAN1_MB01_TIMESTAMP, val)
+#define bfin_read_CAN1_MB01_ID0()		bfin_read16(CAN1_MB01_ID0)
+#define bfin_write_CAN1_MB01_ID0(val)		bfin_write16(CAN1_MB01_ID0, val)
+#define bfin_read_CAN1_MB01_ID1()		bfin_read16(CAN1_MB01_ID1)
+#define bfin_write_CAN1_MB01_ID1(val)		bfin_write16(CAN1_MB01_ID1, val)
+#define bfin_read_CAN1_MB02_DATA0()		bfin_read16(CAN1_MB02_DATA0)
+#define bfin_write_CAN1_MB02_DATA0(val)		bfin_write16(CAN1_MB02_DATA0, val)
+#define bfin_read_CAN1_MB02_DATA1()		bfin_read16(CAN1_MB02_DATA1)
+#define bfin_write_CAN1_MB02_DATA1(val)		bfin_write16(CAN1_MB02_DATA1, val)
+#define bfin_read_CAN1_MB02_DATA2()		bfin_read16(CAN1_MB02_DATA2)
+#define bfin_write_CAN1_MB02_DATA2(val)		bfin_write16(CAN1_MB02_DATA2, val)
+#define bfin_read_CAN1_MB02_DATA3()		bfin_read16(CAN1_MB02_DATA3)
+#define bfin_write_CAN1_MB02_DATA3(val)		bfin_write16(CAN1_MB02_DATA3, val)
+#define bfin_read_CAN1_MB02_LENGTH()		bfin_read16(CAN1_MB02_LENGTH)
+#define bfin_write_CAN1_MB02_LENGTH(val)	bfin_write16(CAN1_MB02_LENGTH, val)
+#define bfin_read_CAN1_MB02_TIMESTAMP()		bfin_read16(CAN1_MB02_TIMESTAMP)
+#define bfin_write_CAN1_MB02_TIMESTAMP(val)	bfin_write16(CAN1_MB02_TIMESTAMP, val)
+#define bfin_read_CAN1_MB02_ID0()		bfin_read16(CAN1_MB02_ID0)
+#define bfin_write_CAN1_MB02_ID0(val)		bfin_write16(CAN1_MB02_ID0, val)
+#define bfin_read_CAN1_MB02_ID1()		bfin_read16(CAN1_MB02_ID1)
+#define bfin_write_CAN1_MB02_ID1(val)		bfin_write16(CAN1_MB02_ID1, val)
+#define bfin_read_CAN1_MB03_DATA0()		bfin_read16(CAN1_MB03_DATA0)
+#define bfin_write_CAN1_MB03_DATA0(val)		bfin_write16(CAN1_MB03_DATA0, val)
+#define bfin_read_CAN1_MB03_DATA1()		bfin_read16(CAN1_MB03_DATA1)
+#define bfin_write_CAN1_MB03_DATA1(val)		bfin_write16(CAN1_MB03_DATA1, val)
+#define bfin_read_CAN1_MB03_DATA2()		bfin_read16(CAN1_MB03_DATA2)
+#define bfin_write_CAN1_MB03_DATA2(val)		bfin_write16(CAN1_MB03_DATA2, val)
+#define bfin_read_CAN1_MB03_DATA3()		bfin_read16(CAN1_MB03_DATA3)
+#define bfin_write_CAN1_MB03_DATA3(val)		bfin_write16(CAN1_MB03_DATA3, val)
+#define bfin_read_CAN1_MB03_LENGTH()		bfin_read16(CAN1_MB03_LENGTH)
+#define bfin_write_CAN1_MB03_LENGTH(val)	bfin_write16(CAN1_MB03_LENGTH, val)
+#define bfin_read_CAN1_MB03_TIMESTAMP()		bfin_read16(CAN1_MB03_TIMESTAMP)
+#define bfin_write_CAN1_MB03_TIMESTAMP(val)	bfin_write16(CAN1_MB03_TIMESTAMP, val)
+#define bfin_read_CAN1_MB03_ID0()		bfin_read16(CAN1_MB03_ID0)
+#define bfin_write_CAN1_MB03_ID0(val)		bfin_write16(CAN1_MB03_ID0, val)
+#define bfin_read_CAN1_MB03_ID1()		bfin_read16(CAN1_MB03_ID1)
+#define bfin_write_CAN1_MB03_ID1(val)		bfin_write16(CAN1_MB03_ID1, val)
+#define bfin_read_CAN1_MB04_DATA0()		bfin_read16(CAN1_MB04_DATA0)
+#define bfin_write_CAN1_MB04_DATA0(val)		bfin_write16(CAN1_MB04_DATA0, val)
+#define bfin_read_CAN1_MB04_DATA1()		bfin_read16(CAN1_MB04_DATA1)
+#define bfin_write_CAN1_MB04_DATA1(val)		bfin_write16(CAN1_MB04_DATA1, val)
+#define bfin_read_CAN1_MB04_DATA2()		bfin_read16(CAN1_MB04_DATA2)
+#define bfin_write_CAN1_MB04_DATA2(val)		bfin_write16(CAN1_MB04_DATA2, val)
+#define bfin_read_CAN1_MB04_DATA3()		bfin_read16(CAN1_MB04_DATA3)
+#define bfin_write_CAN1_MB04_DATA3(val)		bfin_write16(CAN1_MB04_DATA3, val)
+#define bfin_read_CAN1_MB04_LENGTH()		bfin_read16(CAN1_MB04_LENGTH)
+#define bfin_write_CAN1_MB04_LENGTH(val)	bfin_write16(CAN1_MB04_LENGTH, val)
+#define bfin_read_CAN1_MB04_TIMESTAMP()		bfin_read16(CAN1_MB04_TIMESTAMP)
+#define bfin_write_CAN1_MB04_TIMESTAMP(val)	bfin_write16(CAN1_MB04_TIMESTAMP, val)
+#define bfin_read_CAN1_MB04_ID0()		bfin_read16(CAN1_MB04_ID0)
+#define bfin_write_CAN1_MB04_ID0(val)		bfin_write16(CAN1_MB04_ID0, val)
+#define bfin_read_CAN1_MB04_ID1()		bfin_read16(CAN1_MB04_ID1)
+#define bfin_write_CAN1_MB04_ID1(val)		bfin_write16(CAN1_MB04_ID1, val)
+#define bfin_read_CAN1_MB05_DATA0()		bfin_read16(CAN1_MB05_DATA0)
+#define bfin_write_CAN1_MB05_DATA0(val)		bfin_write16(CAN1_MB05_DATA0, val)
+#define bfin_read_CAN1_MB05_DATA1()		bfin_read16(CAN1_MB05_DATA1)
+#define bfin_write_CAN1_MB05_DATA1(val)		bfin_write16(CAN1_MB05_DATA1, val)
+#define bfin_read_CAN1_MB05_DATA2()		bfin_read16(CAN1_MB05_DATA2)
+#define bfin_write_CAN1_MB05_DATA2(val)		bfin_write16(CAN1_MB05_DATA2, val)
+#define bfin_read_CAN1_MB05_DATA3()		bfin_read16(CAN1_MB05_DATA3)
+#define bfin_write_CAN1_MB05_DATA3(val)		bfin_write16(CAN1_MB05_DATA3, val)
+#define bfin_read_CAN1_MB05_LENGTH()		bfin_read16(CAN1_MB05_LENGTH)
+#define bfin_write_CAN1_MB05_LENGTH(val)	bfin_write16(CAN1_MB05_LENGTH, val)
+#define bfin_read_CAN1_MB05_TIMESTAMP()		bfin_read16(CAN1_MB05_TIMESTAMP)
+#define bfin_write_CAN1_MB05_TIMESTAMP(val)	bfin_write16(CAN1_MB05_TIMESTAMP, val)
+#define bfin_read_CAN1_MB05_ID0()		bfin_read16(CAN1_MB05_ID0)
+#define bfin_write_CAN1_MB05_ID0(val)		bfin_write16(CAN1_MB05_ID0, val)
+#define bfin_read_CAN1_MB05_ID1()		bfin_read16(CAN1_MB05_ID1)
+#define bfin_write_CAN1_MB05_ID1(val)		bfin_write16(CAN1_MB05_ID1, val)
+#define bfin_read_CAN1_MB06_DATA0()		bfin_read16(CAN1_MB06_DATA0)
+#define bfin_write_CAN1_MB06_DATA0(val)		bfin_write16(CAN1_MB06_DATA0, val)
+#define bfin_read_CAN1_MB06_DATA1()		bfin_read16(CAN1_MB06_DATA1)
+#define bfin_write_CAN1_MB06_DATA1(val)		bfin_write16(CAN1_MB06_DATA1, val)
+#define bfin_read_CAN1_MB06_DATA2()		bfin_read16(CAN1_MB06_DATA2)
+#define bfin_write_CAN1_MB06_DATA2(val)		bfin_write16(CAN1_MB06_DATA2, val)
+#define bfin_read_CAN1_MB06_DATA3()		bfin_read16(CAN1_MB06_DATA3)
+#define bfin_write_CAN1_MB06_DATA3(val)		bfin_write16(CAN1_MB06_DATA3, val)
+#define bfin_read_CAN1_MB06_LENGTH()		bfin_read16(CAN1_MB06_LENGTH)
+#define bfin_write_CAN1_MB06_LENGTH(val)	bfin_write16(CAN1_MB06_LENGTH, val)
+#define bfin_read_CAN1_MB06_TIMESTAMP()		bfin_read16(CAN1_MB06_TIMESTAMP)
+#define bfin_write_CAN1_MB06_TIMESTAMP(val)	bfin_write16(CAN1_MB06_TIMESTAMP, val)
+#define bfin_read_CAN1_MB06_ID0()		bfin_read16(CAN1_MB06_ID0)
+#define bfin_write_CAN1_MB06_ID0(val)		bfin_write16(CAN1_MB06_ID0, val)
+#define bfin_read_CAN1_MB06_ID1()		bfin_read16(CAN1_MB06_ID1)
+#define bfin_write_CAN1_MB06_ID1(val)		bfin_write16(CAN1_MB06_ID1, val)
+#define bfin_read_CAN1_MB07_DATA0()		bfin_read16(CAN1_MB07_DATA0)
+#define bfin_write_CAN1_MB07_DATA0(val)		bfin_write16(CAN1_MB07_DATA0, val)
+#define bfin_read_CAN1_MB07_DATA1()		bfin_read16(CAN1_MB07_DATA1)
+#define bfin_write_CAN1_MB07_DATA1(val)		bfin_write16(CAN1_MB07_DATA1, val)
+#define bfin_read_CAN1_MB07_DATA2()		bfin_read16(CAN1_MB07_DATA2)
+#define bfin_write_CAN1_MB07_DATA2(val)		bfin_write16(CAN1_MB07_DATA2, val)
+#define bfin_read_CAN1_MB07_DATA3()		bfin_read16(CAN1_MB07_DATA3)
+#define bfin_write_CAN1_MB07_DATA3(val)		bfin_write16(CAN1_MB07_DATA3, val)
+#define bfin_read_CAN1_MB07_LENGTH()		bfin_read16(CAN1_MB07_LENGTH)
+#define bfin_write_CAN1_MB07_LENGTH(val)	bfin_write16(CAN1_MB07_LENGTH, val)
+#define bfin_read_CAN1_MB07_TIMESTAMP()		bfin_read16(CAN1_MB07_TIMESTAMP)
+#define bfin_write_CAN1_MB07_TIMESTAMP(val)	bfin_write16(CAN1_MB07_TIMESTAMP, val)
+#define bfin_read_CAN1_MB07_ID0()		bfin_read16(CAN1_MB07_ID0)
+#define bfin_write_CAN1_MB07_ID0(val)		bfin_write16(CAN1_MB07_ID0, val)
+#define bfin_read_CAN1_MB07_ID1()		bfin_read16(CAN1_MB07_ID1)
+#define bfin_write_CAN1_MB07_ID1(val)		bfin_write16(CAN1_MB07_ID1, val)
+#define bfin_read_CAN1_MB08_DATA0()		bfin_read16(CAN1_MB08_DATA0)
+#define bfin_write_CAN1_MB08_DATA0(val)		bfin_write16(CAN1_MB08_DATA0, val)
+#define bfin_read_CAN1_MB08_DATA1()		bfin_read16(CAN1_MB08_DATA1)
+#define bfin_write_CAN1_MB08_DATA1(val)		bfin_write16(CAN1_MB08_DATA1, val)
+#define bfin_read_CAN1_MB08_DATA2()		bfin_read16(CAN1_MB08_DATA2)
+#define bfin_write_CAN1_MB08_DATA2(val)		bfin_write16(CAN1_MB08_DATA2, val)
+#define bfin_read_CAN1_MB08_DATA3()		bfin_read16(CAN1_MB08_DATA3)
+#define bfin_write_CAN1_MB08_DATA3(val)		bfin_write16(CAN1_MB08_DATA3, val)
+#define bfin_read_CAN1_MB08_LENGTH()		bfin_read16(CAN1_MB08_LENGTH)
+#define bfin_write_CAN1_MB08_LENGTH(val)	bfin_write16(CAN1_MB08_LENGTH, val)
+#define bfin_read_CAN1_MB08_TIMESTAMP()		bfin_read16(CAN1_MB08_TIMESTAMP)
+#define bfin_write_CAN1_MB08_TIMESTAMP(val)	bfin_write16(CAN1_MB08_TIMESTAMP, val)
+#define bfin_read_CAN1_MB08_ID0()		bfin_read16(CAN1_MB08_ID0)
+#define bfin_write_CAN1_MB08_ID0(val)		bfin_write16(CAN1_MB08_ID0, val)
+#define bfin_read_CAN1_MB08_ID1()		bfin_read16(CAN1_MB08_ID1)
+#define bfin_write_CAN1_MB08_ID1(val)		bfin_write16(CAN1_MB08_ID1, val)
+#define bfin_read_CAN1_MB09_DATA0()		bfin_read16(CAN1_MB09_DATA0)
+#define bfin_write_CAN1_MB09_DATA0(val)		bfin_write16(CAN1_MB09_DATA0, val)
+#define bfin_read_CAN1_MB09_DATA1()		bfin_read16(CAN1_MB09_DATA1)
+#define bfin_write_CAN1_MB09_DATA1(val)		bfin_write16(CAN1_MB09_DATA1, val)
+#define bfin_read_CAN1_MB09_DATA2()		bfin_read16(CAN1_MB09_DATA2)
+#define bfin_write_CAN1_MB09_DATA2(val)		bfin_write16(CAN1_MB09_DATA2, val)
+#define bfin_read_CAN1_MB09_DATA3()		bfin_read16(CAN1_MB09_DATA3)
+#define bfin_write_CAN1_MB09_DATA3(val)		bfin_write16(CAN1_MB09_DATA3, val)
+#define bfin_read_CAN1_MB09_LENGTH()		bfin_read16(CAN1_MB09_LENGTH)
+#define bfin_write_CAN1_MB09_LENGTH(val)	bfin_write16(CAN1_MB09_LENGTH, val)
+#define bfin_read_CAN1_MB09_TIMESTAMP()		bfin_read16(CAN1_MB09_TIMESTAMP)
+#define bfin_write_CAN1_MB09_TIMESTAMP(val)	bfin_write16(CAN1_MB09_TIMESTAMP, val)
+#define bfin_read_CAN1_MB09_ID0()		bfin_read16(CAN1_MB09_ID0)
+#define bfin_write_CAN1_MB09_ID0(val)		bfin_write16(CAN1_MB09_ID0, val)
+#define bfin_read_CAN1_MB09_ID1()		bfin_read16(CAN1_MB09_ID1)
+#define bfin_write_CAN1_MB09_ID1(val)		bfin_write16(CAN1_MB09_ID1, val)
+#define bfin_read_CAN1_MB10_DATA0()		bfin_read16(CAN1_MB10_DATA0)
+#define bfin_write_CAN1_MB10_DATA0(val)		bfin_write16(CAN1_MB10_DATA0, val)
+#define bfin_read_CAN1_MB10_DATA1()		bfin_read16(CAN1_MB10_DATA1)
+#define bfin_write_CAN1_MB10_DATA1(val)		bfin_write16(CAN1_MB10_DATA1, val)
+#define bfin_read_CAN1_MB10_DATA2()		bfin_read16(CAN1_MB10_DATA2)
+#define bfin_write_CAN1_MB10_DATA2(val)		bfin_write16(CAN1_MB10_DATA2, val)
+#define bfin_read_CAN1_MB10_DATA3()		bfin_read16(CAN1_MB10_DATA3)
+#define bfin_write_CAN1_MB10_DATA3(val)		bfin_write16(CAN1_MB10_DATA3, val)
+#define bfin_read_CAN1_MB10_LENGTH()		bfin_read16(CAN1_MB10_LENGTH)
+#define bfin_write_CAN1_MB10_LENGTH(val)	bfin_write16(CAN1_MB10_LENGTH, val)
+#define bfin_read_CAN1_MB10_TIMESTAMP()		bfin_read16(CAN1_MB10_TIMESTAMP)
+#define bfin_write_CAN1_MB10_TIMESTAMP(val)	bfin_write16(CAN1_MB10_TIMESTAMP, val)
+#define bfin_read_CAN1_MB10_ID0()		bfin_read16(CAN1_MB10_ID0)
+#define bfin_write_CAN1_MB10_ID0(val)		bfin_write16(CAN1_MB10_ID0, val)
+#define bfin_read_CAN1_MB10_ID1()		bfin_read16(CAN1_MB10_ID1)
+#define bfin_write_CAN1_MB10_ID1(val)		bfin_write16(CAN1_MB10_ID1, val)
+#define bfin_read_CAN1_MB11_DATA0()		bfin_read16(CAN1_MB11_DATA0)
+#define bfin_write_CAN1_MB11_DATA0(val)		bfin_write16(CAN1_MB11_DATA0, val)
+#define bfin_read_CAN1_MB11_DATA1()		bfin_read16(CAN1_MB11_DATA1)
+#define bfin_write_CAN1_MB11_DATA1(val)		bfin_write16(CAN1_MB11_DATA1, val)
+#define bfin_read_CAN1_MB11_DATA2()		bfin_read16(CAN1_MB11_DATA2)
+#define bfin_write_CAN1_MB11_DATA2(val)		bfin_write16(CAN1_MB11_DATA2, val)
+#define bfin_read_CAN1_MB11_DATA3()		bfin_read16(CAN1_MB11_DATA3)
+#define bfin_write_CAN1_MB11_DATA3(val)		bfin_write16(CAN1_MB11_DATA3, val)
+#define bfin_read_CAN1_MB11_LENGTH()		bfin_read16(CAN1_MB11_LENGTH)
+#define bfin_write_CAN1_MB11_LENGTH(val)	bfin_write16(CAN1_MB11_LENGTH, val)
+#define bfin_read_CAN1_MB11_TIMESTAMP()		bfin_read16(CAN1_MB11_TIMESTAMP)
+#define bfin_write_CAN1_MB11_TIMESTAMP(val)	bfin_write16(CAN1_MB11_TIMESTAMP, val)
+#define bfin_read_CAN1_MB11_ID0()		bfin_read16(CAN1_MB11_ID0)
+#define bfin_write_CAN1_MB11_ID0(val)		bfin_write16(CAN1_MB11_ID0, val)
+#define bfin_read_CAN1_MB11_ID1()		bfin_read16(CAN1_MB11_ID1)
+#define bfin_write_CAN1_MB11_ID1(val)		bfin_write16(CAN1_MB11_ID1, val)
+#define bfin_read_CAN1_MB12_DATA0()		bfin_read16(CAN1_MB12_DATA0)
+#define bfin_write_CAN1_MB12_DATA0(val)		bfin_write16(CAN1_MB12_DATA0, val)
+#define bfin_read_CAN1_MB12_DATA1()		bfin_read16(CAN1_MB12_DATA1)
+#define bfin_write_CAN1_MB12_DATA1(val)		bfin_write16(CAN1_MB12_DATA1, val)
+#define bfin_read_CAN1_MB12_DATA2()		bfin_read16(CAN1_MB12_DATA2)
+#define bfin_write_CAN1_MB12_DATA2(val)		bfin_write16(CAN1_MB12_DATA2, val)
+#define bfin_read_CAN1_MB12_DATA3()		bfin_read16(CAN1_MB12_DATA3)
+#define bfin_write_CAN1_MB12_DATA3(val)		bfin_write16(CAN1_MB12_DATA3, val)
+#define bfin_read_CAN1_MB12_LENGTH()		bfin_read16(CAN1_MB12_LENGTH)
+#define bfin_write_CAN1_MB12_LENGTH(val)	bfin_write16(CAN1_MB12_LENGTH, val)
+#define bfin_read_CAN1_MB12_TIMESTAMP()		bfin_read16(CAN1_MB12_TIMESTAMP)
+#define bfin_write_CAN1_MB12_TIMESTAMP(val)	bfin_write16(CAN1_MB12_TIMESTAMP, val)
+#define bfin_read_CAN1_MB12_ID0()		bfin_read16(CAN1_MB12_ID0)
+#define bfin_write_CAN1_MB12_ID0(val)		bfin_write16(CAN1_MB12_ID0, val)
+#define bfin_read_CAN1_MB12_ID1()		bfin_read16(CAN1_MB12_ID1)
+#define bfin_write_CAN1_MB12_ID1(val)		bfin_write16(CAN1_MB12_ID1, val)
+#define bfin_read_CAN1_MB13_DATA0()		bfin_read16(CAN1_MB13_DATA0)
+#define bfin_write_CAN1_MB13_DATA0(val)		bfin_write16(CAN1_MB13_DATA0, val)
+#define bfin_read_CAN1_MB13_DATA1()		bfin_read16(CAN1_MB13_DATA1)
+#define bfin_write_CAN1_MB13_DATA1(val)		bfin_write16(CAN1_MB13_DATA1, val)
+#define bfin_read_CAN1_MB13_DATA2()		bfin_read16(CAN1_MB13_DATA2)
+#define bfin_write_CAN1_MB13_DATA2(val)		bfin_write16(CAN1_MB13_DATA2, val)
+#define bfin_read_CAN1_MB13_DATA3()		bfin_read16(CAN1_MB13_DATA3)
+#define bfin_write_CAN1_MB13_DATA3(val)		bfin_write16(CAN1_MB13_DATA3, val)
+#define bfin_read_CAN1_MB13_LENGTH()		bfin_read16(CAN1_MB13_LENGTH)
+#define bfin_write_CAN1_MB13_LENGTH(val)	bfin_write16(CAN1_MB13_LENGTH, val)
+#define bfin_read_CAN1_MB13_TIMESTAMP()		bfin_read16(CAN1_MB13_TIMESTAMP)
+#define bfin_write_CAN1_MB13_TIMESTAMP(val)	bfin_write16(CAN1_MB13_TIMESTAMP, val)
+#define bfin_read_CAN1_MB13_ID0()		bfin_read16(CAN1_MB13_ID0)
+#define bfin_write_CAN1_MB13_ID0(val)		bfin_write16(CAN1_MB13_ID0, val)
+#define bfin_read_CAN1_MB13_ID1()		bfin_read16(CAN1_MB13_ID1)
+#define bfin_write_CAN1_MB13_ID1(val)		bfin_write16(CAN1_MB13_ID1, val)
+#define bfin_read_CAN1_MB14_DATA0()		bfin_read16(CAN1_MB14_DATA0)
+#define bfin_write_CAN1_MB14_DATA0(val)		bfin_write16(CAN1_MB14_DATA0, val)
+#define bfin_read_CAN1_MB14_DATA1()		bfin_read16(CAN1_MB14_DATA1)
+#define bfin_write_CAN1_MB14_DATA1(val)		bfin_write16(CAN1_MB14_DATA1, val)
+#define bfin_read_CAN1_MB14_DATA2()		bfin_read16(CAN1_MB14_DATA2)
+#define bfin_write_CAN1_MB14_DATA2(val)		bfin_write16(CAN1_MB14_DATA2, val)
+#define bfin_read_CAN1_MB14_DATA3()		bfin_read16(CAN1_MB14_DATA3)
+#define bfin_write_CAN1_MB14_DATA3(val)		bfin_write16(CAN1_MB14_DATA3, val)
+#define bfin_read_CAN1_MB14_LENGTH()		bfin_read16(CAN1_MB14_LENGTH)
+#define bfin_write_CAN1_MB14_LENGTH(val)	bfin_write16(CAN1_MB14_LENGTH, val)
+#define bfin_read_CAN1_MB14_TIMESTAMP()		bfin_read16(CAN1_MB14_TIMESTAMP)
+#define bfin_write_CAN1_MB14_TIMESTAMP(val)	bfin_write16(CAN1_MB14_TIMESTAMP, val)
+#define bfin_read_CAN1_MB14_ID0()		bfin_read16(CAN1_MB14_ID0)
+#define bfin_write_CAN1_MB14_ID0(val)		bfin_write16(CAN1_MB14_ID0, val)
+#define bfin_read_CAN1_MB14_ID1()		bfin_read16(CAN1_MB14_ID1)
+#define bfin_write_CAN1_MB14_ID1(val)		bfin_write16(CAN1_MB14_ID1, val)
+#define bfin_read_CAN1_MB15_DATA0()		bfin_read16(CAN1_MB15_DATA0)
+#define bfin_write_CAN1_MB15_DATA0(val)		bfin_write16(CAN1_MB15_DATA0, val)
+#define bfin_read_CAN1_MB15_DATA1()		bfin_read16(CAN1_MB15_DATA1)
+#define bfin_write_CAN1_MB15_DATA1(val)		bfin_write16(CAN1_MB15_DATA1, val)
+#define bfin_read_CAN1_MB15_DATA2()		bfin_read16(CAN1_MB15_DATA2)
+#define bfin_write_CAN1_MB15_DATA2(val)		bfin_write16(CAN1_MB15_DATA2, val)
+#define bfin_read_CAN1_MB15_DATA3()		bfin_read16(CAN1_MB15_DATA3)
+#define bfin_write_CAN1_MB15_DATA3(val)		bfin_write16(CAN1_MB15_DATA3, val)
+#define bfin_read_CAN1_MB15_LENGTH()		bfin_read16(CAN1_MB15_LENGTH)
+#define bfin_write_CAN1_MB15_LENGTH(val)	bfin_write16(CAN1_MB15_LENGTH, val)
+#define bfin_read_CAN1_MB15_TIMESTAMP()		bfin_read16(CAN1_MB15_TIMESTAMP)
+#define bfin_write_CAN1_MB15_TIMESTAMP(val)	bfin_write16(CAN1_MB15_TIMESTAMP, val)
+#define bfin_read_CAN1_MB15_ID0()		bfin_read16(CAN1_MB15_ID0)
+#define bfin_write_CAN1_MB15_ID0(val)		bfin_write16(CAN1_MB15_ID0, val)
+#define bfin_read_CAN1_MB15_ID1()		bfin_read16(CAN1_MB15_ID1)
+#define bfin_write_CAN1_MB15_ID1(val)		bfin_write16(CAN1_MB15_ID1, val)
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define bfin_read_CAN1_MB16_DATA0()		bfin_read16(CAN1_MB16_DATA0)
+#define bfin_write_CAN1_MB16_DATA0(val)		bfin_write16(CAN1_MB16_DATA0, val)
+#define bfin_read_CAN1_MB16_DATA1()		bfin_read16(CAN1_MB16_DATA1)
+#define bfin_write_CAN1_MB16_DATA1(val)		bfin_write16(CAN1_MB16_DATA1, val)
+#define bfin_read_CAN1_MB16_DATA2()		bfin_read16(CAN1_MB16_DATA2)
+#define bfin_write_CAN1_MB16_DATA2(val)		bfin_write16(CAN1_MB16_DATA2, val)
+#define bfin_read_CAN1_MB16_DATA3()		bfin_read16(CAN1_MB16_DATA3)
+#define bfin_write_CAN1_MB16_DATA3(val)		bfin_write16(CAN1_MB16_DATA3, val)
+#define bfin_read_CAN1_MB16_LENGTH()		bfin_read16(CAN1_MB16_LENGTH)
+#define bfin_write_CAN1_MB16_LENGTH(val)	bfin_write16(CAN1_MB16_LENGTH, val)
+#define bfin_read_CAN1_MB16_TIMESTAMP()		bfin_read16(CAN1_MB16_TIMESTAMP)
+#define bfin_write_CAN1_MB16_TIMESTAMP(val)	bfin_write16(CAN1_MB16_TIMESTAMP, val)
+#define bfin_read_CAN1_MB16_ID0()		bfin_read16(CAN1_MB16_ID0)
+#define bfin_write_CAN1_MB16_ID0(val)		bfin_write16(CAN1_MB16_ID0, val)
+#define bfin_read_CAN1_MB16_ID1()		bfin_read16(CAN1_MB16_ID1)
+#define bfin_write_CAN1_MB16_ID1(val)		bfin_write16(CAN1_MB16_ID1, val)
+#define bfin_read_CAN1_MB17_DATA0()		bfin_read16(CAN1_MB17_DATA0)
+#define bfin_write_CAN1_MB17_DATA0(val)		bfin_write16(CAN1_MB17_DATA0, val)
+#define bfin_read_CAN1_MB17_DATA1()		bfin_read16(CAN1_MB17_DATA1)
+#define bfin_write_CAN1_MB17_DATA1(val)		bfin_write16(CAN1_MB17_DATA1, val)
+#define bfin_read_CAN1_MB17_DATA2()		bfin_read16(CAN1_MB17_DATA2)
+#define bfin_write_CAN1_MB17_DATA2(val)		bfin_write16(CAN1_MB17_DATA2, val)
+#define bfin_read_CAN1_MB17_DATA3()		bfin_read16(CAN1_MB17_DATA3)
+#define bfin_write_CAN1_MB17_DATA3(val)		bfin_write16(CAN1_MB17_DATA3, val)
+#define bfin_read_CAN1_MB17_LENGTH()		bfin_read16(CAN1_MB17_LENGTH)
+#define bfin_write_CAN1_MB17_LENGTH(val)	bfin_write16(CAN1_MB17_LENGTH, val)
+#define bfin_read_CAN1_MB17_TIMESTAMP()		bfin_read16(CAN1_MB17_TIMESTAMP)
+#define bfin_write_CAN1_MB17_TIMESTAMP(val)	bfin_write16(CAN1_MB17_TIMESTAMP, val)
+#define bfin_read_CAN1_MB17_ID0()		bfin_read16(CAN1_MB17_ID0)
+#define bfin_write_CAN1_MB17_ID0(val)		bfin_write16(CAN1_MB17_ID0, val)
+#define bfin_read_CAN1_MB17_ID1()		bfin_read16(CAN1_MB17_ID1)
+#define bfin_write_CAN1_MB17_ID1(val)		bfin_write16(CAN1_MB17_ID1, val)
+#define bfin_read_CAN1_MB18_DATA0()		bfin_read16(CAN1_MB18_DATA0)
+#define bfin_write_CAN1_MB18_DATA0(val)		bfin_write16(CAN1_MB18_DATA0, val)
+#define bfin_read_CAN1_MB18_DATA1()		bfin_read16(CAN1_MB18_DATA1)
+#define bfin_write_CAN1_MB18_DATA1(val)		bfin_write16(CAN1_MB18_DATA1, val)
+#define bfin_read_CAN1_MB18_DATA2()		bfin_read16(CAN1_MB18_DATA2)
+#define bfin_write_CAN1_MB18_DATA2(val)		bfin_write16(CAN1_MB18_DATA2, val)
+#define bfin_read_CAN1_MB18_DATA3()		bfin_read16(CAN1_MB18_DATA3)
+#define bfin_write_CAN1_MB18_DATA3(val)		bfin_write16(CAN1_MB18_DATA3, val)
+#define bfin_read_CAN1_MB18_LENGTH()		bfin_read16(CAN1_MB18_LENGTH)
+#define bfin_write_CAN1_MB18_LENGTH(val)	bfin_write16(CAN1_MB18_LENGTH, val)
+#define bfin_read_CAN1_MB18_TIMESTAMP()		bfin_read16(CAN1_MB18_TIMESTAMP)
+#define bfin_write_CAN1_MB18_TIMESTAMP(val)	bfin_write16(CAN1_MB18_TIMESTAMP, val)
+#define bfin_read_CAN1_MB18_ID0()		bfin_read16(CAN1_MB18_ID0)
+#define bfin_write_CAN1_MB18_ID0(val)		bfin_write16(CAN1_MB18_ID0, val)
+#define bfin_read_CAN1_MB18_ID1()		bfin_read16(CAN1_MB18_ID1)
+#define bfin_write_CAN1_MB18_ID1(val)		bfin_write16(CAN1_MB18_ID1, val)
+#define bfin_read_CAN1_MB19_DATA0()		bfin_read16(CAN1_MB19_DATA0)
+#define bfin_write_CAN1_MB19_DATA0(val)		bfin_write16(CAN1_MB19_DATA0, val)
+#define bfin_read_CAN1_MB19_DATA1()		bfin_read16(CAN1_MB19_DATA1)
+#define bfin_write_CAN1_MB19_DATA1(val)		bfin_write16(CAN1_MB19_DATA1, val)
+#define bfin_read_CAN1_MB19_DATA2()		bfin_read16(CAN1_MB19_DATA2)
+#define bfin_write_CAN1_MB19_DATA2(val)		bfin_write16(CAN1_MB19_DATA2, val)
+#define bfin_read_CAN1_MB19_DATA3()		bfin_read16(CAN1_MB19_DATA3)
+#define bfin_write_CAN1_MB19_DATA3(val)		bfin_write16(CAN1_MB19_DATA3, val)
+#define bfin_read_CAN1_MB19_LENGTH()		bfin_read16(CAN1_MB19_LENGTH)
+#define bfin_write_CAN1_MB19_LENGTH(val)	bfin_write16(CAN1_MB19_LENGTH, val)
+#define bfin_read_CAN1_MB19_TIMESTAMP()		bfin_read16(CAN1_MB19_TIMESTAMP)
+#define bfin_write_CAN1_MB19_TIMESTAMP(val)	bfin_write16(CAN1_MB19_TIMESTAMP, val)
+#define bfin_read_CAN1_MB19_ID0()		bfin_read16(CAN1_MB19_ID0)
+#define bfin_write_CAN1_MB19_ID0(val)		bfin_write16(CAN1_MB19_ID0, val)
+#define bfin_read_CAN1_MB19_ID1()		bfin_read16(CAN1_MB19_ID1)
+#define bfin_write_CAN1_MB19_ID1(val)		bfin_write16(CAN1_MB19_ID1, val)
+#define bfin_read_CAN1_MB20_DATA0()		bfin_read16(CAN1_MB20_DATA0)
+#define bfin_write_CAN1_MB20_DATA0(val)		bfin_write16(CAN1_MB20_DATA0, val)
+#define bfin_read_CAN1_MB20_DATA1()		bfin_read16(CAN1_MB20_DATA1)
+#define bfin_write_CAN1_MB20_DATA1(val)		bfin_write16(CAN1_MB20_DATA1, val)
+#define bfin_read_CAN1_MB20_DATA2()		bfin_read16(CAN1_MB20_DATA2)
+#define bfin_write_CAN1_MB20_DATA2(val)		bfin_write16(CAN1_MB20_DATA2, val)
+#define bfin_read_CAN1_MB20_DATA3()		bfin_read16(CAN1_MB20_DATA3)
+#define bfin_write_CAN1_MB20_DATA3(val)		bfin_write16(CAN1_MB20_DATA3, val)
+#define bfin_read_CAN1_MB20_LENGTH()		bfin_read16(CAN1_MB20_LENGTH)
+#define bfin_write_CAN1_MB20_LENGTH(val)	bfin_write16(CAN1_MB20_LENGTH, val)
+#define bfin_read_CAN1_MB20_TIMESTAMP()		bfin_read16(CAN1_MB20_TIMESTAMP)
+#define bfin_write_CAN1_MB20_TIMESTAMP(val)	bfin_write16(CAN1_MB20_TIMESTAMP, val)
+#define bfin_read_CAN1_MB20_ID0()		bfin_read16(CAN1_MB20_ID0)
+#define bfin_write_CAN1_MB20_ID0(val)		bfin_write16(CAN1_MB20_ID0, val)
+#define bfin_read_CAN1_MB20_ID1()		bfin_read16(CAN1_MB20_ID1)
+#define bfin_write_CAN1_MB20_ID1(val)		bfin_write16(CAN1_MB20_ID1, val)
+#define bfin_read_CAN1_MB21_DATA0()		bfin_read16(CAN1_MB21_DATA0)
+#define bfin_write_CAN1_MB21_DATA0(val)		bfin_write16(CAN1_MB21_DATA0, val)
+#define bfin_read_CAN1_MB21_DATA1()		bfin_read16(CAN1_MB21_DATA1)
+#define bfin_write_CAN1_MB21_DATA1(val)		bfin_write16(CAN1_MB21_DATA1, val)
+#define bfin_read_CAN1_MB21_DATA2()		bfin_read16(CAN1_MB21_DATA2)
+#define bfin_write_CAN1_MB21_DATA2(val)		bfin_write16(CAN1_MB21_DATA2, val)
+#define bfin_read_CAN1_MB21_DATA3()		bfin_read16(CAN1_MB21_DATA3)
+#define bfin_write_CAN1_MB21_DATA3(val)		bfin_write16(CAN1_MB21_DATA3, val)
+#define bfin_read_CAN1_MB21_LENGTH()		bfin_read16(CAN1_MB21_LENGTH)
+#define bfin_write_CAN1_MB21_LENGTH(val)	bfin_write16(CAN1_MB21_LENGTH, val)
+#define bfin_read_CAN1_MB21_TIMESTAMP()		bfin_read16(CAN1_MB21_TIMESTAMP)
+#define bfin_write_CAN1_MB21_TIMESTAMP(val)	bfin_write16(CAN1_MB21_TIMESTAMP, val)
+#define bfin_read_CAN1_MB21_ID0()		bfin_read16(CAN1_MB21_ID0)
+#define bfin_write_CAN1_MB21_ID0(val)		bfin_write16(CAN1_MB21_ID0, val)
+#define bfin_read_CAN1_MB21_ID1()		bfin_read16(CAN1_MB21_ID1)
+#define bfin_write_CAN1_MB21_ID1(val)		bfin_write16(CAN1_MB21_ID1, val)
+#define bfin_read_CAN1_MB22_DATA0()		bfin_read16(CAN1_MB22_DATA0)
+#define bfin_write_CAN1_MB22_DATA0(val)		bfin_write16(CAN1_MB22_DATA0, val)
+#define bfin_read_CAN1_MB22_DATA1()		bfin_read16(CAN1_MB22_DATA1)
+#define bfin_write_CAN1_MB22_DATA1(val)		bfin_write16(CAN1_MB22_DATA1, val)
+#define bfin_read_CAN1_MB22_DATA2()		bfin_read16(CAN1_MB22_DATA2)
+#define bfin_write_CAN1_MB22_DATA2(val)		bfin_write16(CAN1_MB22_DATA2, val)
+#define bfin_read_CAN1_MB22_DATA3()		bfin_read16(CAN1_MB22_DATA3)
+#define bfin_write_CAN1_MB22_DATA3(val)		bfin_write16(CAN1_MB22_DATA3, val)
+#define bfin_read_CAN1_MB22_LENGTH()		bfin_read16(CAN1_MB22_LENGTH)
+#define bfin_write_CAN1_MB22_LENGTH(val)	bfin_write16(CAN1_MB22_LENGTH, val)
+#define bfin_read_CAN1_MB22_TIMESTAMP()		bfin_read16(CAN1_MB22_TIMESTAMP)
+#define bfin_write_CAN1_MB22_TIMESTAMP(val)	bfin_write16(CAN1_MB22_TIMESTAMP, val)
+#define bfin_read_CAN1_MB22_ID0()		bfin_read16(CAN1_MB22_ID0)
+#define bfin_write_CAN1_MB22_ID0(val)		bfin_write16(CAN1_MB22_ID0, val)
+#define bfin_read_CAN1_MB22_ID1()		bfin_read16(CAN1_MB22_ID1)
+#define bfin_write_CAN1_MB22_ID1(val)		bfin_write16(CAN1_MB22_ID1, val)
+#define bfin_read_CAN1_MB23_DATA0()		bfin_read16(CAN1_MB23_DATA0)
+#define bfin_write_CAN1_MB23_DATA0(val)		bfin_write16(CAN1_MB23_DATA0, val)
+#define bfin_read_CAN1_MB23_DATA1()		bfin_read16(CAN1_MB23_DATA1)
+#define bfin_write_CAN1_MB23_DATA1(val)		bfin_write16(CAN1_MB23_DATA1, val)
+#define bfin_read_CAN1_MB23_DATA2()		bfin_read16(CAN1_MB23_DATA2)
+#define bfin_write_CAN1_MB23_DATA2(val)		bfin_write16(CAN1_MB23_DATA2, val)
+#define bfin_read_CAN1_MB23_DATA3()		bfin_read16(CAN1_MB23_DATA3)
+#define bfin_write_CAN1_MB23_DATA3(val)		bfin_write16(CAN1_MB23_DATA3, val)
+#define bfin_read_CAN1_MB23_LENGTH()		bfin_read16(CAN1_MB23_LENGTH)
+#define bfin_write_CAN1_MB23_LENGTH(val)	bfin_write16(CAN1_MB23_LENGTH, val)
+#define bfin_read_CAN1_MB23_TIMESTAMP()		bfin_read16(CAN1_MB23_TIMESTAMP)
+#define bfin_write_CAN1_MB23_TIMESTAMP(val)	bfin_write16(CAN1_MB23_TIMESTAMP, val)
+#define bfin_read_CAN1_MB23_ID0()		bfin_read16(CAN1_MB23_ID0)
+#define bfin_write_CAN1_MB23_ID0(val)		bfin_write16(CAN1_MB23_ID0, val)
+#define bfin_read_CAN1_MB23_ID1()		bfin_read16(CAN1_MB23_ID1)
+#define bfin_write_CAN1_MB23_ID1(val)		bfin_write16(CAN1_MB23_ID1, val)
+#define bfin_read_CAN1_MB24_DATA0()		bfin_read16(CAN1_MB24_DATA0)
+#define bfin_write_CAN1_MB24_DATA0(val)		bfin_write16(CAN1_MB24_DATA0, val)
+#define bfin_read_CAN1_MB24_DATA1()		bfin_read16(CAN1_MB24_DATA1)
+#define bfin_write_CAN1_MB24_DATA1(val)		bfin_write16(CAN1_MB24_DATA1, val)
+#define bfin_read_CAN1_MB24_DATA2()		bfin_read16(CAN1_MB24_DATA2)
+#define bfin_write_CAN1_MB24_DATA2(val)		bfin_write16(CAN1_MB24_DATA2, val)
+#define bfin_read_CAN1_MB24_DATA3()		bfin_read16(CAN1_MB24_DATA3)
+#define bfin_write_CAN1_MB24_DATA3(val)		bfin_write16(CAN1_MB24_DATA3, val)
+#define bfin_read_CAN1_MB24_LENGTH()		bfin_read16(CAN1_MB24_LENGTH)
+#define bfin_write_CAN1_MB24_LENGTH(val)	bfin_write16(CAN1_MB24_LENGTH, val)
+#define bfin_read_CAN1_MB24_TIMESTAMP()		bfin_read16(CAN1_MB24_TIMESTAMP)
+#define bfin_write_CAN1_MB24_TIMESTAMP(val)	bfin_write16(CAN1_MB24_TIMESTAMP, val)
+#define bfin_read_CAN1_MB24_ID0()		bfin_read16(CAN1_MB24_ID0)
+#define bfin_write_CAN1_MB24_ID0(val)		bfin_write16(CAN1_MB24_ID0, val)
+#define bfin_read_CAN1_MB24_ID1()		bfin_read16(CAN1_MB24_ID1)
+#define bfin_write_CAN1_MB24_ID1(val)		bfin_write16(CAN1_MB24_ID1, val)
+#define bfin_read_CAN1_MB25_DATA0()		bfin_read16(CAN1_MB25_DATA0)
+#define bfin_write_CAN1_MB25_DATA0(val)		bfin_write16(CAN1_MB25_DATA0, val)
+#define bfin_read_CAN1_MB25_DATA1()		bfin_read16(CAN1_MB25_DATA1)
+#define bfin_write_CAN1_MB25_DATA1(val)		bfin_write16(CAN1_MB25_DATA1, val)
+#define bfin_read_CAN1_MB25_DATA2()		bfin_read16(CAN1_MB25_DATA2)
+#define bfin_write_CAN1_MB25_DATA2(val)		bfin_write16(CAN1_MB25_DATA2, val)
+#define bfin_read_CAN1_MB25_DATA3()		bfin_read16(CAN1_MB25_DATA3)
+#define bfin_write_CAN1_MB25_DATA3(val)		bfin_write16(CAN1_MB25_DATA3, val)
+#define bfin_read_CAN1_MB25_LENGTH()		bfin_read16(CAN1_MB25_LENGTH)
+#define bfin_write_CAN1_MB25_LENGTH(val)	bfin_write16(CAN1_MB25_LENGTH, val)
+#define bfin_read_CAN1_MB25_TIMESTAMP()		bfin_read16(CAN1_MB25_TIMESTAMP)
+#define bfin_write_CAN1_MB25_TIMESTAMP(val)	bfin_write16(CAN1_MB25_TIMESTAMP, val)
+#define bfin_read_CAN1_MB25_ID0()		bfin_read16(CAN1_MB25_ID0)
+#define bfin_write_CAN1_MB25_ID0(val)		bfin_write16(CAN1_MB25_ID0, val)
+#define bfin_read_CAN1_MB25_ID1()		bfin_read16(CAN1_MB25_ID1)
+#define bfin_write_CAN1_MB25_ID1(val)		bfin_write16(CAN1_MB25_ID1, val)
+#define bfin_read_CAN1_MB26_DATA0()		bfin_read16(CAN1_MB26_DATA0)
+#define bfin_write_CAN1_MB26_DATA0(val)		bfin_write16(CAN1_MB26_DATA0, val)
+#define bfin_read_CAN1_MB26_DATA1()		bfin_read16(CAN1_MB26_DATA1)
+#define bfin_write_CAN1_MB26_DATA1(val)		bfin_write16(CAN1_MB26_DATA1, val)
+#define bfin_read_CAN1_MB26_DATA2()		bfin_read16(CAN1_MB26_DATA2)
+#define bfin_write_CAN1_MB26_DATA2(val)		bfin_write16(CAN1_MB26_DATA2, val)
+#define bfin_read_CAN1_MB26_DATA3()		bfin_read16(CAN1_MB26_DATA3)
+#define bfin_write_CAN1_MB26_DATA3(val)		bfin_write16(CAN1_MB26_DATA3, val)
+#define bfin_read_CAN1_MB26_LENGTH()		bfin_read16(CAN1_MB26_LENGTH)
+#define bfin_write_CAN1_MB26_LENGTH(val)	bfin_write16(CAN1_MB26_LENGTH, val)
+#define bfin_read_CAN1_MB26_TIMESTAMP()		bfin_read16(CAN1_MB26_TIMESTAMP)
+#define bfin_write_CAN1_MB26_TIMESTAMP(val)	bfin_write16(CAN1_MB26_TIMESTAMP, val)
+#define bfin_read_CAN1_MB26_ID0()		bfin_read16(CAN1_MB26_ID0)
+#define bfin_write_CAN1_MB26_ID0(val)		bfin_write16(CAN1_MB26_ID0, val)
+#define bfin_read_CAN1_MB26_ID1()		bfin_read16(CAN1_MB26_ID1)
+#define bfin_write_CAN1_MB26_ID1(val)		bfin_write16(CAN1_MB26_ID1, val)
+#define bfin_read_CAN1_MB27_DATA0()		bfin_read16(CAN1_MB27_DATA0)
+#define bfin_write_CAN1_MB27_DATA0(val)		bfin_write16(CAN1_MB27_DATA0, val)
+#define bfin_read_CAN1_MB27_DATA1()		bfin_read16(CAN1_MB27_DATA1)
+#define bfin_write_CAN1_MB27_DATA1(val)		bfin_write16(CAN1_MB27_DATA1, val)
+#define bfin_read_CAN1_MB27_DATA2()		bfin_read16(CAN1_MB27_DATA2)
+#define bfin_write_CAN1_MB27_DATA2(val)		bfin_write16(CAN1_MB27_DATA2, val)
+#define bfin_read_CAN1_MB27_DATA3()		bfin_read16(CAN1_MB27_DATA3)
+#define bfin_write_CAN1_MB27_DATA3(val)		bfin_write16(CAN1_MB27_DATA3, val)
+#define bfin_read_CAN1_MB27_LENGTH()		bfin_read16(CAN1_MB27_LENGTH)
+#define bfin_write_CAN1_MB27_LENGTH(val)	bfin_write16(CAN1_MB27_LENGTH, val)
+#define bfin_read_CAN1_MB27_TIMESTAMP()		bfin_read16(CAN1_MB27_TIMESTAMP)
+#define bfin_write_CAN1_MB27_TIMESTAMP(val)	bfin_write16(CAN1_MB27_TIMESTAMP, val)
+#define bfin_read_CAN1_MB27_ID0()		bfin_read16(CAN1_MB27_ID0)
+#define bfin_write_CAN1_MB27_ID0(val)		bfin_write16(CAN1_MB27_ID0, val)
+#define bfin_read_CAN1_MB27_ID1()		bfin_read16(CAN1_MB27_ID1)
+#define bfin_write_CAN1_MB27_ID1(val)		bfin_write16(CAN1_MB27_ID1, val)
+#define bfin_read_CAN1_MB28_DATA0()		bfin_read16(CAN1_MB28_DATA0)
+#define bfin_write_CAN1_MB28_DATA0(val)		bfin_write16(CAN1_MB28_DATA0, val)
+#define bfin_read_CAN1_MB28_DATA1()		bfin_read16(CAN1_MB28_DATA1)
+#define bfin_write_CAN1_MB28_DATA1(val)		bfin_write16(CAN1_MB28_DATA1, val)
+#define bfin_read_CAN1_MB28_DATA2()		bfin_read16(CAN1_MB28_DATA2)
+#define bfin_write_CAN1_MB28_DATA2(val)		bfin_write16(CAN1_MB28_DATA2, val)
+#define bfin_read_CAN1_MB28_DATA3()		bfin_read16(CAN1_MB28_DATA3)
+#define bfin_write_CAN1_MB28_DATA3(val)		bfin_write16(CAN1_MB28_DATA3, val)
+#define bfin_read_CAN1_MB28_LENGTH()		bfin_read16(CAN1_MB28_LENGTH)
+#define bfin_write_CAN1_MB28_LENGTH(val)	bfin_write16(CAN1_MB28_LENGTH, val)
+#define bfin_read_CAN1_MB28_TIMESTAMP()		bfin_read16(CAN1_MB28_TIMESTAMP)
+#define bfin_write_CAN1_MB28_TIMESTAMP(val)	bfin_write16(CAN1_MB28_TIMESTAMP, val)
+#define bfin_read_CAN1_MB28_ID0()		bfin_read16(CAN1_MB28_ID0)
+#define bfin_write_CAN1_MB28_ID0(val)		bfin_write16(CAN1_MB28_ID0, val)
+#define bfin_read_CAN1_MB28_ID1()		bfin_read16(CAN1_MB28_ID1)
+#define bfin_write_CAN1_MB28_ID1(val)		bfin_write16(CAN1_MB28_ID1, val)
+#define bfin_read_CAN1_MB29_DATA0()		bfin_read16(CAN1_MB29_DATA0)
+#define bfin_write_CAN1_MB29_DATA0(val)		bfin_write16(CAN1_MB29_DATA0, val)
+#define bfin_read_CAN1_MB29_DATA1()		bfin_read16(CAN1_MB29_DATA1)
+#define bfin_write_CAN1_MB29_DATA1(val)		bfin_write16(CAN1_MB29_DATA1, val)
+#define bfin_read_CAN1_MB29_DATA2()		bfin_read16(CAN1_MB29_DATA2)
+#define bfin_write_CAN1_MB29_DATA2(val)		bfin_write16(CAN1_MB29_DATA2, val)
+#define bfin_read_CAN1_MB29_DATA3()		bfin_read16(CAN1_MB29_DATA3)
+#define bfin_write_CAN1_MB29_DATA3(val)		bfin_write16(CAN1_MB29_DATA3, val)
+#define bfin_read_CAN1_MB29_LENGTH()		bfin_read16(CAN1_MB29_LENGTH)
+#define bfin_write_CAN1_MB29_LENGTH(val)	bfin_write16(CAN1_MB29_LENGTH, val)
+#define bfin_read_CAN1_MB29_TIMESTAMP()		bfin_read16(CAN1_MB29_TIMESTAMP)
+#define bfin_write_CAN1_MB29_TIMESTAMP(val)	bfin_write16(CAN1_MB29_TIMESTAMP, val)
+#define bfin_read_CAN1_MB29_ID0()		bfin_read16(CAN1_MB29_ID0)
+#define bfin_write_CAN1_MB29_ID0(val)		bfin_write16(CAN1_MB29_ID0, val)
+#define bfin_read_CAN1_MB29_ID1()		bfin_read16(CAN1_MB29_ID1)
+#define bfin_write_CAN1_MB29_ID1(val)		bfin_write16(CAN1_MB29_ID1, val)
+#define bfin_read_CAN1_MB30_DATA0()		bfin_read16(CAN1_MB30_DATA0)
+#define bfin_write_CAN1_MB30_DATA0(val)		bfin_write16(CAN1_MB30_DATA0, val)
+#define bfin_read_CAN1_MB30_DATA1()		bfin_read16(CAN1_MB30_DATA1)
+#define bfin_write_CAN1_MB30_DATA1(val)		bfin_write16(CAN1_MB30_DATA1, val)
+#define bfin_read_CAN1_MB30_DATA2()		bfin_read16(CAN1_MB30_DATA2)
+#define bfin_write_CAN1_MB30_DATA2(val)		bfin_write16(CAN1_MB30_DATA2, val)
+#define bfin_read_CAN1_MB30_DATA3()		bfin_read16(CAN1_MB30_DATA3)
+#define bfin_write_CAN1_MB30_DATA3(val)		bfin_write16(CAN1_MB30_DATA3, val)
+#define bfin_read_CAN1_MB30_LENGTH()		bfin_read16(CAN1_MB30_LENGTH)
+#define bfin_write_CAN1_MB30_LENGTH(val)	bfin_write16(CAN1_MB30_LENGTH, val)
+#define bfin_read_CAN1_MB30_TIMESTAMP()		bfin_read16(CAN1_MB30_TIMESTAMP)
+#define bfin_write_CAN1_MB30_TIMESTAMP(val)	bfin_write16(CAN1_MB30_TIMESTAMP, val)
+#define bfin_read_CAN1_MB30_ID0()		bfin_read16(CAN1_MB30_ID0)
+#define bfin_write_CAN1_MB30_ID0(val)		bfin_write16(CAN1_MB30_ID0, val)
+#define bfin_read_CAN1_MB30_ID1()		bfin_read16(CAN1_MB30_ID1)
+#define bfin_write_CAN1_MB30_ID1(val)		bfin_write16(CAN1_MB30_ID1, val)
+#define bfin_read_CAN1_MB31_DATA0()		bfin_read16(CAN1_MB31_DATA0)
+#define bfin_write_CAN1_MB31_DATA0(val)		bfin_write16(CAN1_MB31_DATA0, val)
+#define bfin_read_CAN1_MB31_DATA1()		bfin_read16(CAN1_MB31_DATA1)
+#define bfin_write_CAN1_MB31_DATA1(val)		bfin_write16(CAN1_MB31_DATA1, val)
+#define bfin_read_CAN1_MB31_DATA2()		bfin_read16(CAN1_MB31_DATA2)
+#define bfin_write_CAN1_MB31_DATA2(val)		bfin_write16(CAN1_MB31_DATA2, val)
+#define bfin_read_CAN1_MB31_DATA3()		bfin_read16(CAN1_MB31_DATA3)
+#define bfin_write_CAN1_MB31_DATA3(val)		bfin_write16(CAN1_MB31_DATA3, val)
+#define bfin_read_CAN1_MB31_LENGTH()		bfin_read16(CAN1_MB31_LENGTH)
+#define bfin_write_CAN1_MB31_LENGTH(val)	bfin_write16(CAN1_MB31_LENGTH, val)
+#define bfin_read_CAN1_MB31_TIMESTAMP()		bfin_read16(CAN1_MB31_TIMESTAMP)
+#define bfin_write_CAN1_MB31_TIMESTAMP(val)	bfin_write16(CAN1_MB31_TIMESTAMP, val)
+#define bfin_read_CAN1_MB31_ID0()		bfin_read16(CAN1_MB31_ID0)
+#define bfin_write_CAN1_MB31_ID0(val)		bfin_write16(CAN1_MB31_ID0, val)
+#define bfin_read_CAN1_MB31_ID1()		bfin_read16(CAN1_MB31_ID1)
+#define bfin_write_CAN1_MB31_ID1(val)		bfin_write16(CAN1_MB31_ID1, val)
+
+/* ATAPI Registers */
+
+#define bfin_read_ATAPI_CONTROL()		bfin_read16(ATAPI_CONTROL)
+#define bfin_write_ATAPI_CONTROL(val)		bfin_write16(ATAPI_CONTROL, val)
+#define bfin_read_ATAPI_STATUS()		bfin_read16(ATAPI_STATUS)
+#define bfin_write_ATAPI_STATUS(val)		bfin_write16(ATAPI_STATUS, val)
+#define bfin_read_ATAPI_DEV_ADDR()		bfin_read16(ATAPI_DEV_ADDR)
+#define bfin_write_ATAPI_DEV_ADDR(val)		bfin_write16(ATAPI_DEV_ADDR, val)
+#define bfin_read_ATAPI_DEV_TXBUF()		bfin_read16(ATAPI_DEV_TXBUF)
+#define bfin_write_ATAPI_DEV_TXBUF(val)		bfin_write16(ATAPI_DEV_TXBUF, val)
+#define bfin_read_ATAPI_DEV_RXBUF()		bfin_read16(ATAPI_DEV_RXBUF)
+#define bfin_write_ATAPI_DEV_RXBUF(val)		bfin_write16(ATAPI_DEV_RXBUF, val)
+#define bfin_read_ATAPI_INT_MASK()		bfin_read16(ATAPI_INT_MASK)
+#define bfin_write_ATAPI_INT_MASK(val)		bfin_write16(ATAPI_INT_MASK, val)
+#define bfin_read_ATAPI_INT_STATUS()		bfin_read16(ATAPI_INT_STATUS)
+#define bfin_write_ATAPI_INT_STATUS(val)	bfin_write16(ATAPI_INT_STATUS, val)
+#define bfin_read_ATAPI_XFER_LEN()		bfin_read16(ATAPI_XFER_LEN)
+#define bfin_write_ATAPI_XFER_LEN(val)		bfin_write16(ATAPI_XFER_LEN, val)
+#define bfin_read_ATAPI_LINE_STATUS()		bfin_read16(ATAPI_LINE_STATUS)
+#define bfin_write_ATAPI_LINE_STATUS(val)	bfin_write16(ATAPI_LINE_STATUS, val)
+#define bfin_read_ATAPI_SM_STATE()		bfin_read16(ATAPI_SM_STATE)
+#define bfin_write_ATAPI_SM_STATE(val)		bfin_write16(ATAPI_SM_STATE, val)
+#define bfin_read_ATAPI_TERMINATE()		bfin_read16(ATAPI_TERMINATE)
+#define bfin_write_ATAPI_TERMINATE(val)		bfin_write16(ATAPI_TERMINATE, val)
+#define bfin_read_ATAPI_PIO_TFRCNT()		bfin_read16(ATAPI_PIO_TFRCNT)
+#define bfin_write_ATAPI_PIO_TFRCNT(val)	bfin_write16(ATAPI_PIO_TFRCNT, val)
+#define bfin_read_ATAPI_DMA_TFRCNT()		bfin_read16(ATAPI_DMA_TFRCNT)
+#define bfin_write_ATAPI_DMA_TFRCNT(val)	bfin_write16(ATAPI_DMA_TFRCNT, val)
+#define bfin_read_ATAPI_UMAIN_TFRCNT()		bfin_read16(ATAPI_UMAIN_TFRCNT)
+#define bfin_write_ATAPI_UMAIN_TFRCNT(val)	bfin_write16(ATAPI_UMAIN_TFRCNT, val)
+#define bfin_read_ATAPI_UDMAOUT_TFRCNT()	bfin_read16(ATAPI_UDMAOUT_TFRCNT)
+#define bfin_write_ATAPI_UDMAOUT_TFRCNT(val)	bfin_write16(ATAPI_UDMAOUT_TFRCNT, val)
+#define bfin_read_ATAPI_REG_TIM_0()		bfin_read16(ATAPI_REG_TIM_0)
+#define bfin_write_ATAPI_REG_TIM_0(val)		bfin_write16(ATAPI_REG_TIM_0, val)
+#define bfin_read_ATAPI_PIO_TIM_0()		bfin_read16(ATAPI_PIO_TIM_0)
+#define bfin_write_ATAPI_PIO_TIM_0(val)		bfin_write16(ATAPI_PIO_TIM_0, val)
+#define bfin_read_ATAPI_PIO_TIM_1()		bfin_read16(ATAPI_PIO_TIM_1)
+#define bfin_write_ATAPI_PIO_TIM_1(val)		bfin_write16(ATAPI_PIO_TIM_1, val)
+#define bfin_read_ATAPI_MULTI_TIM_0()		bfin_read16(ATAPI_MULTI_TIM_0)
+#define bfin_write_ATAPI_MULTI_TIM_0(val)	bfin_write16(ATAPI_MULTI_TIM_0, val)
+#define bfin_read_ATAPI_MULTI_TIM_1()		bfin_read16(ATAPI_MULTI_TIM_1)
+#define bfin_write_ATAPI_MULTI_TIM_1(val)	bfin_write16(ATAPI_MULTI_TIM_1, val)
+#define bfin_read_ATAPI_MULTI_TIM_2()		bfin_read16(ATAPI_MULTI_TIM_2)
+#define bfin_write_ATAPI_MULTI_TIM_2(val)	bfin_write16(ATAPI_MULTI_TIM_2, val)
+#define bfin_read_ATAPI_ULTRA_TIM_0()		bfin_read16(ATAPI_ULTRA_TIM_0)
+#define bfin_write_ATAPI_ULTRA_TIM_0(val)	bfin_write16(ATAPI_ULTRA_TIM_0, val)
+#define bfin_read_ATAPI_ULTRA_TIM_1()		bfin_read16(ATAPI_ULTRA_TIM_1)
+#define bfin_write_ATAPI_ULTRA_TIM_1(val)	bfin_write16(ATAPI_ULTRA_TIM_1, val)
+#define bfin_read_ATAPI_ULTRA_TIM_2()		bfin_read16(ATAPI_ULTRA_TIM_2)
+#define bfin_write_ATAPI_ULTRA_TIM_2(val)	bfin_write16(ATAPI_ULTRA_TIM_2, val)
+#define bfin_read_ATAPI_ULTRA_TIM_3()		bfin_read16(ATAPI_ULTRA_TIM_3)
+#define bfin_write_ATAPI_ULTRA_TIM_3(val)	bfin_write16(ATAPI_ULTRA_TIM_3, val)
+
+/* SDH Registers */
+
+#define bfin_read_SDH_PWR_CTL()		bfin_read16(SDH_PWR_CTL)
+#define bfin_write_SDH_PWR_CTL(val)	bfin_write16(SDH_PWR_CTL, val)
+#define bfin_read_SDH_CLK_CTL()		bfin_read16(SDH_CLK_CTL)
+#define bfin_write_SDH_CLK_CTL(val)	bfin_write16(SDH_CLK_CTL, val)
+#define bfin_read_SDH_ARGUMENT()	bfin_read32(SDH_ARGUMENT)
+#define bfin_write_SDH_ARGUMENT(val)	bfin_write32(SDH_ARGUMENT, val)
+#define bfin_read_SDH_COMMAND()		bfin_read16(SDH_COMMAND)
+#define bfin_write_SDH_COMMAND(val)	bfin_write16(SDH_COMMAND, val)
+#define bfin_read_SDH_RESP_CMD()	bfin_read16(SDH_RESP_CMD)
+#define bfin_write_SDH_RESP_CMD(val)	bfin_write16(SDH_RESP_CMD, val)
+#define bfin_read_SDH_RESPONSE0()	bfin_read32(SDH_RESPONSE0)
+#define bfin_write_SDH_RESPONSE0(val)	bfin_write32(SDH_RESPONSE0, val)
+#define bfin_read_SDH_RESPONSE1()	bfin_read32(SDH_RESPONSE1)
+#define bfin_write_SDH_RESPONSE1(val)	bfin_write32(SDH_RESPONSE1, val)
+#define bfin_read_SDH_RESPONSE2()	bfin_read32(SDH_RESPONSE2)
+#define bfin_write_SDH_RESPONSE2(val)	bfin_write32(SDH_RESPONSE2, val)
+#define bfin_read_SDH_RESPONSE3()	bfin_read32(SDH_RESPONSE3)
+#define bfin_write_SDH_RESPONSE3(val)	bfin_write32(SDH_RESPONSE3, val)
+#define bfin_read_SDH_DATA_TIMER()	bfin_read32(SDH_DATA_TIMER)
+#define bfin_write_SDH_DATA_TIMER(val)	bfin_write32(SDH_DATA_TIMER, val)
+#define bfin_read_SDH_DATA_LGTH()	bfin_read16(SDH_DATA_LGTH)
+#define bfin_write_SDH_DATA_LGTH(val)	bfin_write16(SDH_DATA_LGTH, val)
+#define bfin_read_SDH_DATA_CTL()	bfin_read16(SDH_DATA_CTL)
+#define bfin_write_SDH_DATA_CTL(val)	bfin_write16(SDH_DATA_CTL, val)
+#define bfin_read_SDH_DATA_CNT()	bfin_read16(SDH_DATA_CNT)
+#define bfin_write_SDH_DATA_CNT(val)	bfin_write16(SDH_DATA_CNT, val)
+#define bfin_read_SDH_STATUS()		bfin_read32(SDH_STATUS)
+#define bfin_write_SDH_STATUS(val)	bfin_write32(SDH_STATUS, val)
+#define bfin_read_SDH_STATUS_CLR()	bfin_read16(SDH_STATUS_CLR)
+#define bfin_write_SDH_STATUS_CLR(val)	bfin_write16(SDH_STATUS_CLR, val)
+#define bfin_read_SDH_MASK0()		bfin_read32(SDH_MASK0)
+#define bfin_write_SDH_MASK0(val)	bfin_write32(SDH_MASK0, val)
+#define bfin_read_SDH_MASK1()		bfin_read32(SDH_MASK1)
+#define bfin_write_SDH_MASK1(val)	bfin_write32(SDH_MASK1, val)
+#define bfin_read_SDH_FIFO_CNT()	bfin_read16(SDH_FIFO_CNT)
+#define bfin_write_SDH_FIFO_CNT(val)	bfin_write16(SDH_FIFO_CNT, val)
+#define bfin_read_SDH_FIFO()		bfin_read32(SDH_FIFO)
+#define bfin_write_SDH_FIFO(val)	bfin_write32(SDH_FIFO, val)
+#define bfin_read_SDH_E_STATUS()	bfin_read16(SDH_E_STATUS)
+#define bfin_write_SDH_E_STATUS(val)	bfin_write16(SDH_E_STATUS, val)
+#define bfin_read_SDH_E_MASK()		bfin_read16(SDH_E_MASK)
+#define bfin_write_SDH_E_MASK(val)	bfin_write16(SDH_E_MASK, val)
+#define bfin_read_SDH_CFG()		bfin_read16(SDH_CFG)
+#define bfin_write_SDH_CFG(val)		bfin_write16(SDH_CFG, val)
+#define bfin_read_SDH_RD_WAIT_EN()	bfin_read16(SDH_RD_WAIT_EN)
+#define bfin_write_SDH_RD_WAIT_EN(val)	bfin_write16(SDH_RD_WAIT_EN, val)
+#define bfin_read_SDH_PID0()		bfin_read16(SDH_PID0)
+#define bfin_write_SDH_PID0(val)	bfin_write16(SDH_PID0, val)
+#define bfin_read_SDH_PID1()		bfin_read16(SDH_PID1)
+#define bfin_write_SDH_PID1(val)	bfin_write16(SDH_PID1, val)
+#define bfin_read_SDH_PID2()		bfin_read16(SDH_PID2)
+#define bfin_write_SDH_PID2(val)	bfin_write16(SDH_PID2, val)
+#define bfin_read_SDH_PID3()		bfin_read16(SDH_PID3)
+#define bfin_write_SDH_PID3(val)	bfin_write16(SDH_PID3, val)
+#define bfin_read_SDH_PID4()		bfin_read16(SDH_PID4)
+#define bfin_write_SDH_PID4(val)	bfin_write16(SDH_PID4, val)
+#define bfin_read_SDH_PID5()		bfin_read16(SDH_PID5)
+#define bfin_write_SDH_PID5(val)	bfin_write16(SDH_PID5, val)
+#define bfin_read_SDH_PID6()		bfin_read16(SDH_PID6)
+#define bfin_write_SDH_PID6(val)	bfin_write16(SDH_PID6, val)
+#define bfin_read_SDH_PID7()		bfin_read16(SDH_PID7)
+#define bfin_write_SDH_PID7(val)	bfin_write16(SDH_PID7, val)
+
+/* HOST Port Registers */
+
+#define bfin_read_HOST_CONTROL()	bfin_read16(HOST_CONTROL)
+#define bfin_write_HOST_CONTROL(val)	bfin_write16(HOST_CONTROL, val)
+#define bfin_read_HOST_STATUS()		bfin_read16(HOST_STATUS)
+#define bfin_write_HOST_STATUS(val)	bfin_write16(HOST_STATUS, val)
+#define bfin_read_HOST_TIMEOUT()	bfin_read16(HOST_TIMEOUT)
+#define bfin_write_HOST_TIMEOUT(val)	bfin_write16(HOST_TIMEOUT, val)
+
+/* USB Control Registers */
+
+#define bfin_read_USB_FADDR()		bfin_read16(USB_FADDR)
+#define bfin_write_USB_FADDR(val)	bfin_write16(USB_FADDR, val)
+#define bfin_read_USB_POWER()		bfin_read16(USB_POWER)
+#define bfin_write_USB_POWER(val)	bfin_write16(USB_POWER, val)
+#define bfin_read_USB_INTRTX()		bfin_read16(USB_INTRTX)
+#define bfin_write_USB_INTRTX(val)	bfin_write16(USB_INTRTX, val)
+#define bfin_read_USB_INTRRX()		bfin_read16(USB_INTRRX)
+#define bfin_write_USB_INTRRX(val)	bfin_write16(USB_INTRRX, val)
+#define bfin_read_USB_INTRTXE()		bfin_read16(USB_INTRTXE)
+#define bfin_write_USB_INTRTXE(val)	bfin_write16(USB_INTRTXE, val)
+#define bfin_read_USB_INTRRXE()		bfin_read16(USB_INTRRXE)
+#define bfin_write_USB_INTRRXE(val)	bfin_write16(USB_INTRRXE, val)
+#define bfin_read_USB_INTRUSB()		bfin_read16(USB_INTRUSB)
+#define bfin_write_USB_INTRUSB(val)	bfin_write16(USB_INTRUSB, val)
+#define bfin_read_USB_INTRUSBE()	bfin_read16(USB_INTRUSBE)
+#define bfin_write_USB_INTRUSBE(val)	bfin_write16(USB_INTRUSBE, val)
+#define bfin_read_USB_FRAME()		bfin_read16(USB_FRAME)
+#define bfin_write_USB_FRAME(val)	bfin_write16(USB_FRAME, val)
+#define bfin_read_USB_INDEX()		bfin_read16(USB_INDEX)
+#define bfin_write_USB_INDEX(val)	bfin_write16(USB_INDEX, val)
+#define bfin_read_USB_TESTMODE()	bfin_read16(USB_TESTMODE)
+#define bfin_write_USB_TESTMODE(val)	bfin_write16(USB_TESTMODE, val)
+#define bfin_read_USB_GLOBINTR()	bfin_read16(USB_GLOBINTR)
+#define bfin_write_USB_GLOBINTR(val)	bfin_write16(USB_GLOBINTR, val)
+#define bfin_read_USB_GLOBAL_CTL()	bfin_read16(USB_GLOBAL_CTL)
+#define bfin_write_USB_GLOBAL_CTL(val)		bfin_write16(USB_GLOBAL_CTL, val)
+
+/* USB Packet Control Registers */
+
+#define bfin_read_USB_TX_MAX_PACKET()		bfin_read16(USB_TX_MAX_PACKET)
+#define bfin_write_USB_TX_MAX_PACKET(val)	bfin_write16(USB_TX_MAX_PACKET, val)
+#define bfin_read_USB_CSR0()		bfin_read16(USB_CSR0)
+#define bfin_write_USB_CSR0(val)	bfin_write16(USB_CSR0, val)
+#define bfin_read_USB_TXCSR()		bfin_read16(USB_TXCSR)
+#define bfin_write_USB_TXCSR(val)	bfin_write16(USB_TXCSR, val)
+#define bfin_read_USB_RX_MAX_PACKET()		bfin_read16(USB_RX_MAX_PACKET)
+#define bfin_write_USB_RX_MAX_PACKET(val)	bfin_write16(USB_RX_MAX_PACKET, val)
+#define bfin_read_USB_RXCSR()		bfin_read16(USB_RXCSR)
+#define bfin_write_USB_RXCSR(val)	bfin_write16(USB_RXCSR, val)
+#define bfin_read_USB_COUNT0()		bfin_read16(USB_COUNT0)
+#define bfin_write_USB_COUNT0(val)	bfin_write16(USB_COUNT0, val)
+#define bfin_read_USB_RXCOUNT()		bfin_read16(USB_RXCOUNT)
+#define bfin_write_USB_RXCOUNT(val)	bfin_write16(USB_RXCOUNT, val)
+#define bfin_read_USB_TXTYPE()		bfin_read16(USB_TXTYPE)
+#define bfin_write_USB_TXTYPE(val)	bfin_write16(USB_TXTYPE, val)
+#define bfin_read_USB_NAKLIMIT0()	bfin_read16(USB_NAKLIMIT0)
+#define bfin_write_USB_NAKLIMIT0(val)	bfin_write16(USB_NAKLIMIT0, val)
+#define bfin_read_USB_TXINTERVAL()	bfin_read16(USB_TXINTERVAL)
+#define bfin_write_USB_TXINTERVAL(val)	bfin_write16(USB_TXINTERVAL, val)
+#define bfin_read_USB_RXTYPE()		bfin_read16(USB_RXTYPE)
+#define bfin_write_USB_RXTYPE(val)	bfin_write16(USB_RXTYPE, val)
+#define bfin_read_USB_RXINTERVAL()	bfin_read16(USB_RXINTERVAL)
+#define bfin_write_USB_RXINTERVAL(val)	bfin_write16(USB_RXINTERVAL, val)
+#define bfin_read_USB_TXCOUNT()		bfin_read16(USB_TXCOUNT)
+#define bfin_write_USB_TXCOUNT(val)	bfin_write16(USB_TXCOUNT, val)
+
+/* USB Endbfin_read_()oint FIFO Registers */
+
+#define bfin_read_USB_EP0_FIFO()	bfin_read16(USB_EP0_FIFO)
+#define bfin_write_USB_EP0_FIFO(val)	bfin_write16(USB_EP0_FIFO, val)
+#define bfin_read_USB_EP1_FIFO()	bfin_read16(USB_EP1_FIFO)
+#define bfin_write_USB_EP1_FIFO(val)	bfin_write16(USB_EP1_FIFO, val)
+#define bfin_read_USB_EP2_FIFO()	bfin_read16(USB_EP2_FIFO)
+#define bfin_write_USB_EP2_FIFO(val)	bfin_write16(USB_EP2_FIFO, val)
+#define bfin_read_USB_EP3_FIFO()	bfin_read16(USB_EP3_FIFO)
+#define bfin_write_USB_EP3_FIFO(val)	bfin_write16(USB_EP3_FIFO, val)
+#define bfin_read_USB_EP4_FIFO()	bfin_read16(USB_EP4_FIFO)
+#define bfin_write_USB_EP4_FIFO(val)	bfin_write16(USB_EP4_FIFO, val)
+#define bfin_read_USB_EP5_FIFO()	bfin_read16(USB_EP5_FIFO)
+#define bfin_write_USB_EP5_FIFO(val)	bfin_write16(USB_EP5_FIFO, val)
+#define bfin_read_USB_EP6_FIFO()	bfin_read16(USB_EP6_FIFO)
+#define bfin_write_USB_EP6_FIFO(val)	bfin_write16(USB_EP6_FIFO, val)
+#define bfin_read_USB_EP7_FIFO()	bfin_read16(USB_EP7_FIFO)
+#define bfin_write_USB_EP7_FIFO(val)	bfin_write16(USB_EP7_FIFO, val)
+
+/* USB OTG Control Registers */
+
+#define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
+#define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
+#define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
+#define bfin_write_USB_OTG_VBUS_IRQ(val)	bfin_write16(USB_OTG_VBUS_IRQ, val)
+#define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
+#define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
+
+/* USB Phy Control Registers */
+
+#define bfin_read_USB_LINKINFO()	bfin_read16(USB_LINKINFO)
+#define bfin_write_USB_LINKINFO(val)	bfin_write16(USB_LINKINFO, val)
+#define bfin_read_USB_VPLEN()		bfin_read16(USB_VPLEN)
+#define bfin_write_USB_VPLEN(val)	bfin_write16(USB_VPLEN, val)
+#define bfin_read_USB_HS_EOF1()		bfin_read16(USB_HS_EOF1)
+#define bfin_write_USB_HS_EOF1(val)	bfin_write16(USB_HS_EOF1, val)
+#define bfin_read_USB_FS_EOF1()		bfin_read16(USB_FS_EOF1)
+#define bfin_write_USB_FS_EOF1(val)	bfin_write16(USB_FS_EOF1, val)
+#define bfin_read_USB_LS_EOF1()		bfin_read16(USB_LS_EOF1)
+#define bfin_write_USB_LS_EOF1(val)	bfin_write16(USB_LS_EOF1, val)
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CNTRL()		bfin_read16(USB_APHY_CNTRL)
+#define bfin_write_USB_APHY_CNTRL(val)		bfin_write16(USB_APHY_CNTRL, val)
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CALIB()		bfin_read16(USB_APHY_CALIB)
+#define bfin_write_USB_APHY_CALIB(val)		bfin_write16(USB_APHY_CALIB, val)
+#define bfin_read_USB_APHY_CNTRL2()		bfin_read16(USB_APHY_CNTRL2)
+#define bfin_write_USB_APHY_CNTRL2(val)		bfin_write16(USB_APHY_CNTRL2, val)
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define bfin_read_USB_PHY_TEST()		bfin_read16(USB_PHY_TEST)
+#define bfin_write_USB_PHY_TEST(val)		bfin_write16(USB_PHY_TEST, val)
+#define bfin_read_USB_PLLOSC_CTRL()		bfin_read16(USB_PLLOSC_CTRL)
+#define bfin_write_USB_PLLOSC_CTRL(val)		bfin_write16(USB_PLLOSC_CTRL, val)
+#define bfin_read_USB_SRP_CLKDIV()		bfin_read16(USB_SRP_CLKDIV)
+#define bfin_write_USB_SRP_CLKDIV(val)		bfin_write16(USB_SRP_CLKDIV, val)
+
+/* USB Endbfin_read_()oint 0 Control Registers */
+
+#define bfin_read_USB_EP_NI0_TXMAXP()		bfin_read16(USB_EP_NI0_TXMAXP)
+#define bfin_write_USB_EP_NI0_TXMAXP(val)	bfin_write16(USB_EP_NI0_TXMAXP, val)
+#define bfin_read_USB_EP_NI0_TXCSR()		bfin_read16(USB_EP_NI0_TXCSR)
+#define bfin_write_USB_EP_NI0_TXCSR(val)	bfin_write16(USB_EP_NI0_TXCSR, val)
+#define bfin_read_USB_EP_NI0_RXMAXP()		bfin_read16(USB_EP_NI0_RXMAXP)
+#define bfin_write_USB_EP_NI0_RXMAXP(val)	bfin_write16(USB_EP_NI0_RXMAXP, val)
+#define bfin_read_USB_EP_NI0_RXCSR()		bfin_read16(USB_EP_NI0_RXCSR)
+#define bfin_write_USB_EP_NI0_RXCSR(val)	bfin_write16(USB_EP_NI0_RXCSR, val)
+#define bfin_read_USB_EP_NI0_RXCOUNT()		bfin_read16(USB_EP_NI0_RXCOUNT)
+#define bfin_write_USB_EP_NI0_RXCOUNT(val)	bfin_write16(USB_EP_NI0_RXCOUNT, val)
+#define bfin_read_USB_EP_NI0_TXTYPE()		bfin_read16(USB_EP_NI0_TXTYPE)
+#define bfin_write_USB_EP_NI0_TXTYPE(val)	bfin_write16(USB_EP_NI0_TXTYPE, val)
+#define bfin_read_USB_EP_NI0_TXINTERVAL()	bfin_read16(USB_EP_NI0_TXINTERVAL)
+#define bfin_write_USB_EP_NI0_TXINTERVAL(val)	bfin_write16(USB_EP_NI0_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI0_RXTYPE()		bfin_read16(USB_EP_NI0_RXTYPE)
+#define bfin_write_USB_EP_NI0_RXTYPE(val)	bfin_write16(USB_EP_NI0_RXTYPE, val)
+#define bfin_read_USB_EP_NI0_RXINTERVAL()	bfin_read16(USB_EP_NI0_RXINTERVAL)
+#define bfin_write_USB_EP_NI0_RXINTERVAL(val)	bfin_write16(USB_EP_NI0_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 1 Control Registers */
+
+#define bfin_read_USB_EP_NI0_TXCOUNT()		bfin_read16(USB_EP_NI0_TXCOUNT)
+#define bfin_write_USB_EP_NI0_TXCOUNT(val)	bfin_write16(USB_EP_NI0_TXCOUNT, val)
+#define bfin_read_USB_EP_NI1_TXMAXP()		bfin_read16(USB_EP_NI1_TXMAXP)
+#define bfin_write_USB_EP_NI1_TXMAXP(val)	bfin_write16(USB_EP_NI1_TXMAXP, val)
+#define bfin_read_USB_EP_NI1_TXCSR()		bfin_read16(USB_EP_NI1_TXCSR)
+#define bfin_write_USB_EP_NI1_TXCSR(val)	bfin_write16(USB_EP_NI1_TXCSR, val)
+#define bfin_read_USB_EP_NI1_RXMAXP()		bfin_read16(USB_EP_NI1_RXMAXP)
+#define bfin_write_USB_EP_NI1_RXMAXP(val)	bfin_write16(USB_EP_NI1_RXMAXP, val)
+#define bfin_read_USB_EP_NI1_RXCSR()		bfin_read16(USB_EP_NI1_RXCSR)
+#define bfin_write_USB_EP_NI1_RXCSR(val)	bfin_write16(USB_EP_NI1_RXCSR, val)
+#define bfin_read_USB_EP_NI1_RXCOUNT()		bfin_read16(USB_EP_NI1_RXCOUNT)
+#define bfin_write_USB_EP_NI1_RXCOUNT(val)	bfin_write16(USB_EP_NI1_RXCOUNT, val)
+#define bfin_read_USB_EP_NI1_TXTYPE()		bfin_read16(USB_EP_NI1_TXTYPE)
+#define bfin_write_USB_EP_NI1_TXTYPE(val)	bfin_write16(USB_EP_NI1_TXTYPE, val)
+#define bfin_read_USB_EP_NI1_TXINTERVAL()	bfin_read16(USB_EP_NI1_TXINTERVAL)
+#define bfin_write_USB_EP_NI1_TXINTERVAL(val)	bfin_write16(USB_EP_NI1_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI1_RXTYPE()		bfin_read16(USB_EP_NI1_RXTYPE)
+#define bfin_write_USB_EP_NI1_RXTYPE(val)	bfin_write16(USB_EP_NI1_RXTYPE, val)
+#define bfin_read_USB_EP_NI1_RXINTERVAL()	bfin_read16(USB_EP_NI1_RXINTERVAL)
+#define bfin_write_USB_EP_NI1_RXINTERVAL(val)	bfin_write16(USB_EP_NI1_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 2 Control Registers */
+
+#define bfin_read_USB_EP_NI1_TXCOUNT()		bfin_read16(USB_EP_NI1_TXCOUNT)
+#define bfin_write_USB_EP_NI1_TXCOUNT(val)	bfin_write16(USB_EP_NI1_TXCOUNT, val)
+#define bfin_read_USB_EP_NI2_TXMAXP()		bfin_read16(USB_EP_NI2_TXMAXP)
+#define bfin_write_USB_EP_NI2_TXMAXP(val)	bfin_write16(USB_EP_NI2_TXMAXP, val)
+#define bfin_read_USB_EP_NI2_TXCSR()		bfin_read16(USB_EP_NI2_TXCSR)
+#define bfin_write_USB_EP_NI2_TXCSR(val)	bfin_write16(USB_EP_NI2_TXCSR, val)
+#define bfin_read_USB_EP_NI2_RXMAXP()		bfin_read16(USB_EP_NI2_RXMAXP)
+#define bfin_write_USB_EP_NI2_RXMAXP(val)	bfin_write16(USB_EP_NI2_RXMAXP, val)
+#define bfin_read_USB_EP_NI2_RXCSR()		bfin_read16(USB_EP_NI2_RXCSR)
+#define bfin_write_USB_EP_NI2_RXCSR(val)	bfin_write16(USB_EP_NI2_RXCSR, val)
+#define bfin_read_USB_EP_NI2_RXCOUNT()		bfin_read16(USB_EP_NI2_RXCOUNT)
+#define bfin_write_USB_EP_NI2_RXCOUNT(val)	bfin_write16(USB_EP_NI2_RXCOUNT, val)
+#define bfin_read_USB_EP_NI2_TXTYPE()		bfin_read16(USB_EP_NI2_TXTYPE)
+#define bfin_write_USB_EP_NI2_TXTYPE(val)	bfin_write16(USB_EP_NI2_TXTYPE, val)
+#define bfin_read_USB_EP_NI2_TXINTERVAL()	bfin_read16(USB_EP_NI2_TXINTERVAL)
+#define bfin_write_USB_EP_NI2_TXINTERVAL(val)	bfin_write16(USB_EP_NI2_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI2_RXTYPE()		bfin_read16(USB_EP_NI2_RXTYPE)
+#define bfin_write_USB_EP_NI2_RXTYPE(val)	bfin_write16(USB_EP_NI2_RXTYPE, val)
+#define bfin_read_USB_EP_NI2_RXINTERVAL()	bfin_read16(USB_EP_NI2_RXINTERVAL)
+#define bfin_write_USB_EP_NI2_RXINTERVAL(val)	bfin_write16(USB_EP_NI2_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 3 Control Registers */
+
+#define bfin_read_USB_EP_NI2_TXCOUNT()		bfin_read16(USB_EP_NI2_TXCOUNT)
+#define bfin_write_USB_EP_NI2_TXCOUNT(val)	bfin_write16(USB_EP_NI2_TXCOUNT, val)
+#define bfin_read_USB_EP_NI3_TXMAXP()		bfin_read16(USB_EP_NI3_TXMAXP)
+#define bfin_write_USB_EP_NI3_TXMAXP(val)	bfin_write16(USB_EP_NI3_TXMAXP, val)
+#define bfin_read_USB_EP_NI3_TXCSR()		bfin_read16(USB_EP_NI3_TXCSR)
+#define bfin_write_USB_EP_NI3_TXCSR(val)	bfin_write16(USB_EP_NI3_TXCSR, val)
+#define bfin_read_USB_EP_NI3_RXMAXP()		bfin_read16(USB_EP_NI3_RXMAXP)
+#define bfin_write_USB_EP_NI3_RXMAXP(val)	bfin_write16(USB_EP_NI3_RXMAXP, val)
+#define bfin_read_USB_EP_NI3_RXCSR()		bfin_read16(USB_EP_NI3_RXCSR)
+#define bfin_write_USB_EP_NI3_RXCSR(val)	bfin_write16(USB_EP_NI3_RXCSR, val)
+#define bfin_read_USB_EP_NI3_RXCOUNT()		bfin_read16(USB_EP_NI3_RXCOUNT)
+#define bfin_write_USB_EP_NI3_RXCOUNT(val)	bfin_write16(USB_EP_NI3_RXCOUNT, val)
+#define bfin_read_USB_EP_NI3_TXTYPE()		bfin_read16(USB_EP_NI3_TXTYPE)
+#define bfin_write_USB_EP_NI3_TXTYPE(val)	bfin_write16(USB_EP_NI3_TXTYPE, val)
+#define bfin_read_USB_EP_NI3_TXINTERVAL()	bfin_read16(USB_EP_NI3_TXINTERVAL)
+#define bfin_write_USB_EP_NI3_TXINTERVAL(val)	bfin_write16(USB_EP_NI3_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI3_RXTYPE()		bfin_read16(USB_EP_NI3_RXTYPE)
+#define bfin_write_USB_EP_NI3_RXTYPE(val)	bfin_write16(USB_EP_NI3_RXTYPE, val)
+#define bfin_read_USB_EP_NI3_RXINTERVAL()	bfin_read16(USB_EP_NI3_RXINTERVAL)
+#define bfin_write_USB_EP_NI3_RXINTERVAL(val)	bfin_write16(USB_EP_NI3_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 4 Control Registers */
+
+#define bfin_read_USB_EP_NI3_TXCOUNT()		bfin_read16(USB_EP_NI3_TXCOUNT)
+#define bfin_write_USB_EP_NI3_TXCOUNT(val)	bfin_write16(USB_EP_NI3_TXCOUNT, val)
+#define bfin_read_USB_EP_NI4_TXMAXP()		bfin_read16(USB_EP_NI4_TXMAXP)
+#define bfin_write_USB_EP_NI4_TXMAXP(val)	bfin_write16(USB_EP_NI4_TXMAXP, val)
+#define bfin_read_USB_EP_NI4_TXCSR()		bfin_read16(USB_EP_NI4_TXCSR)
+#define bfin_write_USB_EP_NI4_TXCSR(val)	bfin_write16(USB_EP_NI4_TXCSR, val)
+#define bfin_read_USB_EP_NI4_RXMAXP()		bfin_read16(USB_EP_NI4_RXMAXP)
+#define bfin_write_USB_EP_NI4_RXMAXP(val)	bfin_write16(USB_EP_NI4_RXMAXP, val)
+#define bfin_read_USB_EP_NI4_RXCSR()		bfin_read16(USB_EP_NI4_RXCSR)
+#define bfin_write_USB_EP_NI4_RXCSR(val)	bfin_write16(USB_EP_NI4_RXCSR, val)
+#define bfin_read_USB_EP_NI4_RXCOUNT()		bfin_read16(USB_EP_NI4_RXCOUNT)
+#define bfin_write_USB_EP_NI4_RXCOUNT(val)	bfin_write16(USB_EP_NI4_RXCOUNT, val)
+#define bfin_read_USB_EP_NI4_TXTYPE()		bfin_read16(USB_EP_NI4_TXTYPE)
+#define bfin_write_USB_EP_NI4_TXTYPE(val)	bfin_write16(USB_EP_NI4_TXTYPE, val)
+#define bfin_read_USB_EP_NI4_TXINTERVAL()	bfin_read16(USB_EP_NI4_TXINTERVAL)
+#define bfin_write_USB_EP_NI4_TXINTERVAL(val)	bfin_write16(USB_EP_NI4_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI4_RXTYPE()		bfin_read16(USB_EP_NI4_RXTYPE)
+#define bfin_write_USB_EP_NI4_RXTYPE(val)	bfin_write16(USB_EP_NI4_RXTYPE, val)
+#define bfin_read_USB_EP_NI4_RXINTERVAL()	bfin_read16(USB_EP_NI4_RXINTERVAL)
+#define bfin_write_USB_EP_NI4_RXINTERVAL(val)	bfin_write16(USB_EP_NI4_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 5 Control Registers */
+
+#define bfin_read_USB_EP_NI4_TXCOUNT()		bfin_read16(USB_EP_NI4_TXCOUNT)
+#define bfin_write_USB_EP_NI4_TXCOUNT(val)	bfin_write16(USB_EP_NI4_TXCOUNT, val)
+#define bfin_read_USB_EP_NI5_TXMAXP()		bfin_read16(USB_EP_NI5_TXMAXP)
+#define bfin_write_USB_EP_NI5_TXMAXP(val)	bfin_write16(USB_EP_NI5_TXMAXP, val)
+#define bfin_read_USB_EP_NI5_TXCSR()		bfin_read16(USB_EP_NI5_TXCSR)
+#define bfin_write_USB_EP_NI5_TXCSR(val)	bfin_write16(USB_EP_NI5_TXCSR, val)
+#define bfin_read_USB_EP_NI5_RXMAXP()		bfin_read16(USB_EP_NI5_RXMAXP)
+#define bfin_write_USB_EP_NI5_RXMAXP(val)	bfin_write16(USB_EP_NI5_RXMAXP, val)
+#define bfin_read_USB_EP_NI5_RXCSR()		bfin_read16(USB_EP_NI5_RXCSR)
+#define bfin_write_USB_EP_NI5_RXCSR(val)	bfin_write16(USB_EP_NI5_RXCSR, val)
+#define bfin_read_USB_EP_NI5_RXCOUNT()		bfin_read16(USB_EP_NI5_RXCOUNT)
+#define bfin_write_USB_EP_NI5_RXCOUNT(val)	bfin_write16(USB_EP_NI5_RXCOUNT, val)
+#define bfin_read_USB_EP_NI5_TXTYPE()		bfin_read16(USB_EP_NI5_TXTYPE)
+#define bfin_write_USB_EP_NI5_TXTYPE(val)	bfin_write16(USB_EP_NI5_TXTYPE, val)
+#define bfin_read_USB_EP_NI5_TXINTERVAL()	bfin_read16(USB_EP_NI5_TXINTERVAL)
+#define bfin_write_USB_EP_NI5_TXINTERVAL(val)	bfin_write16(USB_EP_NI5_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI5_RXTYPE()		bfin_read16(USB_EP_NI5_RXTYPE)
+#define bfin_write_USB_EP_NI5_RXTYPE(val)	bfin_write16(USB_EP_NI5_RXTYPE, val)
+#define bfin_read_USB_EP_NI5_RXINTERVAL()	bfin_read16(USB_EP_NI5_RXINTERVAL)
+#define bfin_write_USB_EP_NI5_RXINTERVAL(val)	bfin_write16(USB_EP_NI5_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 6 Control Registers */
+
+#define bfin_read_USB_EP_NI5_TXCOUNT()		bfin_read16(USB_EP_NI5_TXCOUNT)
+#define bfin_write_USB_EP_NI5_TXCOUNT(val)	bfin_write16(USB_EP_NI5_TXCOUNT, val)
+#define bfin_read_USB_EP_NI6_TXMAXP()		bfin_read16(USB_EP_NI6_TXMAXP)
+#define bfin_write_USB_EP_NI6_TXMAXP(val)	bfin_write16(USB_EP_NI6_TXMAXP, val)
+#define bfin_read_USB_EP_NI6_TXCSR()		bfin_read16(USB_EP_NI6_TXCSR)
+#define bfin_write_USB_EP_NI6_TXCSR(val)	bfin_write16(USB_EP_NI6_TXCSR, val)
+#define bfin_read_USB_EP_NI6_RXMAXP()		bfin_read16(USB_EP_NI6_RXMAXP)
+#define bfin_write_USB_EP_NI6_RXMAXP(val)	bfin_write16(USB_EP_NI6_RXMAXP, val)
+#define bfin_read_USB_EP_NI6_RXCSR()		bfin_read16(USB_EP_NI6_RXCSR)
+#define bfin_write_USB_EP_NI6_RXCSR(val)	bfin_write16(USB_EP_NI6_RXCSR, val)
+#define bfin_read_USB_EP_NI6_RXCOUNT()		bfin_read16(USB_EP_NI6_RXCOUNT)
+#define bfin_write_USB_EP_NI6_RXCOUNT(val)	bfin_write16(USB_EP_NI6_RXCOUNT, val)
+#define bfin_read_USB_EP_NI6_TXTYPE()		bfin_read16(USB_EP_NI6_TXTYPE)
+#define bfin_write_USB_EP_NI6_TXTYPE(val)	bfin_write16(USB_EP_NI6_TXTYPE, val)
+#define bfin_read_USB_EP_NI6_TXINTERVAL()	bfin_read16(USB_EP_NI6_TXINTERVAL)
+#define bfin_write_USB_EP_NI6_TXINTERVAL(val)	bfin_write16(USB_EP_NI6_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI6_RXTYPE()		bfin_read16(USB_EP_NI6_RXTYPE)
+#define bfin_write_USB_EP_NI6_RXTYPE(val)	bfin_write16(USB_EP_NI6_RXTYPE, val)
+#define bfin_read_USB_EP_NI6_RXINTERVAL()	bfin_read16(USB_EP_NI6_RXINTERVAL)
+#define bfin_write_USB_EP_NI6_RXINTERVAL(val)	bfin_write16(USB_EP_NI6_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 7 Control Registers */
+
+#define bfin_read_USB_EP_NI6_TXCOUNT()		bfin_read16(USB_EP_NI6_TXCOUNT)
+#define bfin_write_USB_EP_NI6_TXCOUNT(val)	bfin_write16(USB_EP_NI6_TXCOUNT, val)
+#define bfin_read_USB_EP_NI7_TXMAXP()		bfin_read16(USB_EP_NI7_TXMAXP)
+#define bfin_write_USB_EP_NI7_TXMAXP(val)	bfin_write16(USB_EP_NI7_TXMAXP, val)
+#define bfin_read_USB_EP_NI7_TXCSR()		bfin_read16(USB_EP_NI7_TXCSR)
+#define bfin_write_USB_EP_NI7_TXCSR(val)	bfin_write16(USB_EP_NI7_TXCSR, val)
+#define bfin_read_USB_EP_NI7_RXMAXP()		bfin_read16(USB_EP_NI7_RXMAXP)
+#define bfin_write_USB_EP_NI7_RXMAXP(val)	bfin_write16(USB_EP_NI7_RXMAXP, val)
+#define bfin_read_USB_EP_NI7_RXCSR()		bfin_read16(USB_EP_NI7_RXCSR)
+#define bfin_write_USB_EP_NI7_RXCSR(val)	bfin_write16(USB_EP_NI7_RXCSR, val)
+#define bfin_read_USB_EP_NI7_RXCOUNT()		bfin_read16(USB_EP_NI7_RXCOUNT)
+#define bfin_write_USB_EP_NI7_RXCOUNT(val)	bfin_write16(USB_EP_NI7_RXCOUNT, val)
+#define bfin_read_USB_EP_NI7_TXTYPE()		bfin_read16(USB_EP_NI7_TXTYPE)
+#define bfin_write_USB_EP_NI7_TXTYPE(val)	bfin_write16(USB_EP_NI7_TXTYPE, val)
+#define bfin_read_USB_EP_NI7_TXINTERVAL()	bfin_read16(USB_EP_NI7_TXINTERVAL)
+#define bfin_write_USB_EP_NI7_TXINTERVAL(val)	bfin_write16(USB_EP_NI7_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_RXTYPE()		bfin_read16(USB_EP_NI7_RXTYPE)
+#define bfin_write_USB_EP_NI7_RXTYPE(val)	bfin_write16(USB_EP_NI7_RXTYPE, val)
+#define bfin_read_USB_EP_NI7_RXINTERVAL()	bfin_read16(USB_EP_NI7_RXINTERVAL)
+#define bfin_write_USB_EP_NI7_RXINTERVAL(val)	bfin_write16(USB_EP_NI7_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_TXCOUNT()		bfin_read16(USB_EP_NI7_TXCOUNT)
+#define bfin_write_USB_EP_NI7_TXCOUNT(val)	bfin_write16(USB_EP_NI7_TXCOUNT, val)
+#define bfin_read_USB_DMA_INTERRUPT()		bfin_read16(USB_DMA_INTERRUPT)
+#define bfin_write_USB_DMA_INTERRUPT(val)	bfin_write16(USB_DMA_INTERRUPT, val)
+
+/* USB Channel 0 Config Registers */
+
+#define bfin_read_USB_DMA0CONTROL()		bfin_read16(USB_DMA0CONTROL)
+#define bfin_write_USB_DMA0CONTROL(val)		bfin_write16(USB_DMA0CONTROL, val)
+#define bfin_read_USB_DMA0ADDRLOW()		bfin_read16(USB_DMA0ADDRLOW)
+#define bfin_write_USB_DMA0ADDRLOW(val)		bfin_write16(USB_DMA0ADDRLOW, val)
+#define bfin_read_USB_DMA0ADDRHIGH()		bfin_read16(USB_DMA0ADDRHIGH)
+#define bfin_write_USB_DMA0ADDRHIGH(val)	bfin_write16(USB_DMA0ADDRHIGH, val)
+#define bfin_read_USB_DMA0COUNTLOW()		bfin_read16(USB_DMA0COUNTLOW)
+#define bfin_write_USB_DMA0COUNTLOW(val)	bfin_write16(USB_DMA0COUNTLOW, val)
+#define bfin_read_USB_DMA0COUNTHIGH()		bfin_read16(USB_DMA0COUNTHIGH)
+#define bfin_write_USB_DMA0COUNTHIGH(val)	bfin_write16(USB_DMA0COUNTHIGH, val)
+
+/* USB Channel 1 Config Registers */
+
+#define bfin_read_USB_DMA1CONTROL()		bfin_read16(USB_DMA1CONTROL)
+#define bfin_write_USB_DMA1CONTROL(val)		bfin_write16(USB_DMA1CONTROL, val)
+#define bfin_read_USB_DMA1ADDRLOW()		bfin_read16(USB_DMA1ADDRLOW)
+#define bfin_write_USB_DMA1ADDRLOW(val)		bfin_write16(USB_DMA1ADDRLOW, val)
+#define bfin_read_USB_DMA1ADDRHIGH()		bfin_read16(USB_DMA1ADDRHIGH)
+#define bfin_write_USB_DMA1ADDRHIGH(val)	bfin_write16(USB_DMA1ADDRHIGH, val)
+#define bfin_read_USB_DMA1COUNTLOW()		bfin_read16(USB_DMA1COUNTLOW)
+#define bfin_write_USB_DMA1COUNTLOW(val)	bfin_write16(USB_DMA1COUNTLOW, val)
+#define bfin_read_USB_DMA1COUNTHIGH()		bfin_read16(USB_DMA1COUNTHIGH)
+#define bfin_write_USB_DMA1COUNTHIGH(val)	bfin_write16(USB_DMA1COUNTHIGH, val)
+
+/* USB Channel 2 Config Registers */
+
+#define bfin_read_USB_DMA2CONTROL()		bfin_read16(USB_DMA2CONTROL)
+#define bfin_write_USB_DMA2CONTROL(val)		bfin_write16(USB_DMA2CONTROL, val)
+#define bfin_read_USB_DMA2ADDRLOW()		bfin_read16(USB_DMA2ADDRLOW)
+#define bfin_write_USB_DMA2ADDRLOW(val)		bfin_write16(USB_DMA2ADDRLOW, val)
+#define bfin_read_USB_DMA2ADDRHIGH()		bfin_read16(USB_DMA2ADDRHIGH)
+#define bfin_write_USB_DMA2ADDRHIGH(val)	bfin_write16(USB_DMA2ADDRHIGH, val)
+#define bfin_read_USB_DMA2COUNTLOW()		bfin_read16(USB_DMA2COUNTLOW)
+#define bfin_write_USB_DMA2COUNTLOW(val)	bfin_write16(USB_DMA2COUNTLOW, val)
+#define bfin_read_USB_DMA2COUNTHIGH()		bfin_read16(USB_DMA2COUNTHIGH)
+#define bfin_write_USB_DMA2COUNTHIGH(val)	bfin_write16(USB_DMA2COUNTHIGH, val)
+
+/* USB Channel 3 Config Registers */
+
+#define bfin_read_USB_DMA3CONTROL()		bfin_read16(USB_DMA3CONTROL)
+#define bfin_write_USB_DMA3CONTROL(val)		bfin_write16(USB_DMA3CONTROL, val)
+#define bfin_read_USB_DMA3ADDRLOW()		bfin_read16(USB_DMA3ADDRLOW)
+#define bfin_write_USB_DMA3ADDRLOW(val)		bfin_write16(USB_DMA3ADDRLOW, val)
+#define bfin_read_USB_DMA3ADDRHIGH()		bfin_read16(USB_DMA3ADDRHIGH)
+#define bfin_write_USB_DMA3ADDRHIGH(val)	bfin_write16(USB_DMA3ADDRHIGH, val)
+#define bfin_read_USB_DMA3COUNTLOW()		bfin_read16(USB_DMA3COUNTLOW)
+#define bfin_write_USB_DMA3COUNTLOW(val)	bfin_write16(USB_DMA3COUNTLOW, val)
+#define bfin_read_USB_DMA3COUNTHIGH()		bfin_read16(USB_DMA3COUNTHIGH)
+#define bfin_write_USB_DMA3COUNTHIGH(val)	bfin_write16(USB_DMA3COUNTHIGH, val)
+
+/* USB Channel 4 Config Registers */
+
+#define bfin_read_USB_DMA4CONTROL()		bfin_read16(USB_DMA4CONTROL)
+#define bfin_write_USB_DMA4CONTROL(val)		bfin_write16(USB_DMA4CONTROL, val)
+#define bfin_read_USB_DMA4ADDRLOW()		bfin_read16(USB_DMA4ADDRLOW)
+#define bfin_write_USB_DMA4ADDRLOW(val)		bfin_write16(USB_DMA4ADDRLOW, val)
+#define bfin_read_USB_DMA4ADDRHIGH()		bfin_read16(USB_DMA4ADDRHIGH)
+#define bfin_write_USB_DMA4ADDRHIGH(val)	bfin_write16(USB_DMA4ADDRHIGH, val)
+#define bfin_read_USB_DMA4COUNTLOW()		bfin_read16(USB_DMA4COUNTLOW)
+#define bfin_write_USB_DMA4COUNTLOW(val)	bfin_write16(USB_DMA4COUNTLOW, val)
+#define bfin_read_USB_DMA4COUNTHIGH()		bfin_read16(USB_DMA4COUNTHIGH)
+#define bfin_write_USB_DMA4COUNTHIGH(val)	bfin_write16(USB_DMA4COUNTHIGH, val)
+
+/* USB Channel 5 Config Registers */
+
+#define bfin_read_USB_DMA5CONTROL()		bfin_read16(USB_DMA5CONTROL)
+#define bfin_write_USB_DMA5CONTROL(val)		bfin_write16(USB_DMA5CONTROL, val)
+#define bfin_read_USB_DMA5ADDRLOW()		bfin_read16(USB_DMA5ADDRLOW)
+#define bfin_write_USB_DMA5ADDRLOW(val)		bfin_write16(USB_DMA5ADDRLOW, val)
+#define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
+#define bfin_write_USB_DMA5ADDRHIGH(val)	bfin_write16(USB_DMA5ADDRHIGH, val)
+#define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
+#define bfin_write_USB_DMA5COUNTLOW(val)	bfin_write16(USB_DMA5COUNTLOW, val)
+#define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
+#define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
+
+/* USB Channel 6 Config Registers */
+
+#define bfin_read_USB_DMA6CONTROL()		bfin_read16(USB_DMA6CONTROL)
+#define bfin_write_USB_DMA6CONTROL(val)		bfin_write16(USB_DMA6CONTROL, val)
+#define bfin_read_USB_DMA6ADDRLOW()		bfin_read16(USB_DMA6ADDRLOW)
+#define bfin_write_USB_DMA6ADDRLOW(val)		bfin_write16(USB_DMA6ADDRLOW, val)
+#define bfin_read_USB_DMA6ADDRHIGH()		bfin_read16(USB_DMA6ADDRHIGH)
+#define bfin_write_USB_DMA6ADDRHIGH(val)	bfin_write16(USB_DMA6ADDRHIGH, val)
+#define bfin_read_USB_DMA6COUNTLOW()		bfin_read16(USB_DMA6COUNTLOW)
+#define bfin_write_USB_DMA6COUNTLOW(val)	bfin_write16(USB_DMA6COUNTLOW, val)
+#define bfin_read_USB_DMA6COUNTHIGH()		bfin_read16(USB_DMA6COUNTHIGH)
+#define bfin_write_USB_DMA6COUNTHIGH(val)	bfin_write16(USB_DMA6COUNTHIGH, val)
+
+/* USB Channel 7 Config Registers */
+
+#define bfin_read_USB_DMA7CONTROL()		bfin_read16(USB_DMA7CONTROL)
+#define bfin_write_USB_DMA7CONTROL(val)		bfin_write16(USB_DMA7CONTROL, val)
+#define bfin_read_USB_DMA7ADDRLOW()		bfin_read16(USB_DMA7ADDRLOW)
+#define bfin_write_USB_DMA7ADDRLOW(val)		bfin_write16(USB_DMA7ADDRLOW, val)
+#define bfin_read_USB_DMA7ADDRHIGH()		bfin_read16(USB_DMA7ADDRHIGH)
+#define bfin_write_USB_DMA7ADDRHIGH(val)	bfin_write16(USB_DMA7ADDRHIGH, val)
+#define bfin_read_USB_DMA7COUNTLOW()		bfin_read16(USB_DMA7COUNTLOW)
+#define bfin_write_USB_DMA7COUNTLOW(val)	bfin_write16(USB_DMA7COUNTLOW, val)
+#define bfin_read_USB_DMA7COUNTHIGH()		bfin_read16(USB_DMA7COUNTHIGH)
+#define bfin_write_USB_DMA7COUNTHIGH(val)	bfin_write16(USB_DMA7COUNTHIGH, val)
+
+/* Keybfin_read_()ad Registers */
+
+#define bfin_read_KPAD_CTL()		bfin_read16(KPAD_CTL)
+#define bfin_write_KPAD_CTL(val)	bfin_write16(KPAD_CTL, val)
+#define bfin_read_KPAD_PRESCALE()	bfin_read16(KPAD_PRESCALE)
+#define bfin_write_KPAD_PRESCALE(val)	bfin_write16(KPAD_PRESCALE, val)
+#define bfin_read_KPAD_MSEL()		bfin_read16(KPAD_MSEL)
+#define bfin_write_KPAD_MSEL(val)	bfin_write16(KPAD_MSEL, val)
+#define bfin_read_KPAD_ROWCOL()		bfin_read16(KPAD_ROWCOL)
+#define bfin_write_KPAD_ROWCOL(val)	bfin_write16(KPAD_ROWCOL, val)
+#define bfin_read_KPAD_STAT()		bfin_read16(KPAD_STAT)
+#define bfin_write_KPAD_STAT(val)	bfin_write16(KPAD_STAT, val)
+#define bfin_read_KPAD_SOFTEVAL()	bfin_read16(KPAD_SOFTEVAL)
+#define bfin_write_KPAD_SOFTEVAL(val)	bfin_write16(KPAD_SOFTEVAL, val)
+
+/* Pixel Combfin_read_()ositor (PIXC) Registers */
+
+#define bfin_read_PIXC_CTL()		bfin_read16(PIXC_CTL)
+#define bfin_write_PIXC_CTL(val)	bfin_write16(PIXC_CTL, val)
+#define bfin_read_PIXC_PPL()		bfin_read16(PIXC_PPL)
+#define bfin_write_PIXC_PPL(val)	bfin_write16(PIXC_PPL, val)
+#define bfin_read_PIXC_LPF()		bfin_read16(PIXC_LPF)
+#define bfin_write_PIXC_LPF(val)	bfin_write16(PIXC_LPF, val)
+#define bfin_read_PIXC_AHSTART()	bfin_read16(PIXC_AHSTART)
+#define bfin_write_PIXC_AHSTART(val)	bfin_write16(PIXC_AHSTART, val)
+#define bfin_read_PIXC_AHEND()		bfin_read16(PIXC_AHEND)
+#define bfin_write_PIXC_AHEND(val)	bfin_write16(PIXC_AHEND, val)
+#define bfin_read_PIXC_AVSTART()	bfin_read16(PIXC_AVSTART)
+#define bfin_write_PIXC_AVSTART(val)	bfin_write16(PIXC_AVSTART, val)
+#define bfin_read_PIXC_AVEND()		bfin_read16(PIXC_AVEND)
+#define bfin_write_PIXC_AVEND(val)	bfin_write16(PIXC_AVEND, val)
+#define bfin_read_PIXC_ATRANSP()	bfin_read16(PIXC_ATRANSP)
+#define bfin_write_PIXC_ATRANSP(val)	bfin_write16(PIXC_ATRANSP, val)
+#define bfin_read_PIXC_BHSTART()	bfin_read16(PIXC_BHSTART)
+#define bfin_write_PIXC_BHSTART(val)	bfin_write16(PIXC_BHSTART, val)
+#define bfin_read_PIXC_BHEND()		bfin_read16(PIXC_BHEND)
+#define bfin_write_PIXC_BHEND(val)	bfin_write16(PIXC_BHEND, val)
+#define bfin_read_PIXC_BVSTART()	bfin_read16(PIXC_BVSTART)
+#define bfin_write_PIXC_BVSTART(val)	bfin_write16(PIXC_BVSTART, val)
+#define bfin_read_PIXC_BVEND()		bfin_read16(PIXC_BVEND)
+#define bfin_write_PIXC_BVEND(val)	bfin_write16(PIXC_BVEND, val)
+#define bfin_read_PIXC_BTRANSP()	bfin_read16(PIXC_BTRANSP)
+#define bfin_write_PIXC_BTRANSP(val)	bfin_write16(PIXC_BTRANSP, val)
+#define bfin_read_PIXC_INTRSTAT()	bfin_read16(PIXC_INTRSTAT)
+#define bfin_write_PIXC_INTRSTAT(val)	bfin_write16(PIXC_INTRSTAT, val)
+#define bfin_read_PIXC_RYCON()		bfin_read32(PIXC_RYCON)
+#define bfin_write_PIXC_RYCON(val)	bfin_write32(PIXC_RYCON, val)
+#define bfin_read_PIXC_GUCON()		bfin_read32(PIXC_GUCON)
+#define bfin_write_PIXC_GUCON(val)	bfin_write32(PIXC_GUCON, val)
+#define bfin_read_PIXC_BVCON()		bfin_read32(PIXC_BVCON)
+#define bfin_write_PIXC_BVCON(val)	bfin_write32(PIXC_BVCON, val)
+#define bfin_read_PIXC_CCBIAS()		bfin_read32(PIXC_CCBIAS)
+#define bfin_write_PIXC_CCBIAS(val)	bfin_write32(PIXC_CCBIAS, val)
+#define bfin_read_PIXC_TC()		bfin_read32(PIXC_TC)
+#define bfin_write_PIXC_TC(val)		bfin_write32(PIXC_TC, val)
+
+/* Handshake MDMA 0 Registers */
+
+#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
+#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
+#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
+#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
+#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
+#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
+#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
+#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
+#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
+#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
+#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
+#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
+#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
+#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
+
+/* Handshake MDMA 1 Registers */
+
+#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
+#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
+#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
+#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
+#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
+#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
+#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
+#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
+#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
+#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
+#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
+#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
+#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
+#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
+
+#endif /* _CDEF_BF548_H */
diff --git a/include/asm-blackfin/mach-bf548/cdefBF549.h b/include/asm-blackfin/mach-bf548/cdefBF549.h
new file mode 100644
index 0000000..2ab5b7c
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/cdefBF549.h
@@ -0,0 +1,1896 @@
+/*
+ * File:         include/asm-blackfin/mach-bf549/cdefBF549.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF549_H
+#define _CDEF_BF549_H
+
+/* include all Core registers and bit definitions */
+#include "defBF549.h"
+
+/* include core sbfin_read_()ecific register pointer definitions */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF549 */
+
+/* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
+#include "cdefBF54x_base.h"
+
+/* The following are the #defines needed by ADSP-BF549 that are not in the common header */
+
+/* Timer Registers */
+
+#define bfin_read_TIMER8_CONFIG()		bfin_read16(TIMER8_CONFIG)
+#define bfin_write_TIMER8_CONFIG(val)		bfin_write16(TIMER8_CONFIG, val)
+#define bfin_read_TIMER8_COUNTER()		bfin_read32(TIMER8_COUNTER)
+#define bfin_write_TIMER8_COUNTER(val)		bfin_write32(TIMER8_COUNTER, val)
+#define bfin_read_TIMER8_PERIOD()		bfin_read32(TIMER8_PERIOD)
+#define bfin_write_TIMER8_PERIOD(val)		bfin_write32(TIMER8_PERIOD, val)
+#define bfin_read_TIMER8_WIDTH()		bfin_read32(TIMER8_WIDTH)
+#define bfin_write_TIMER8_WIDTH(val)		bfin_write32(TIMER8_WIDTH, val)
+#define bfin_read_TIMER9_CONFIG()		bfin_read16(TIMER9_CONFIG)
+#define bfin_write_TIMER9_CONFIG(val)		bfin_write16(TIMER9_CONFIG, val)
+#define bfin_read_TIMER9_COUNTER()		bfin_read32(TIMER9_COUNTER)
+#define bfin_write_TIMER9_COUNTER(val)		bfin_write32(TIMER9_COUNTER, val)
+#define bfin_read_TIMER9_PERIOD()		bfin_read32(TIMER9_PERIOD)
+#define bfin_write_TIMER9_PERIOD(val)		bfin_write32(TIMER9_PERIOD, val)
+#define bfin_read_TIMER9_WIDTH()		bfin_read32(TIMER9_WIDTH)
+#define bfin_write_TIMER9_WIDTH(val)		bfin_write32(TIMER9_WIDTH, val)
+#define bfin_read_TIMER10_CONFIG()		bfin_read16(TIMER10_CONFIG)
+#define bfin_write_TIMER10_CONFIG(val)		bfin_write16(TIMER10_CONFIG, val)
+#define bfin_read_TIMER10_COUNTER()		bfin_read32(TIMER10_COUNTER)
+#define bfin_write_TIMER10_COUNTER(val)		bfin_write32(TIMER10_COUNTER, val)
+#define bfin_read_TIMER10_PERIOD()		bfin_read32(TIMER10_PERIOD)
+#define bfin_write_TIMER10_PERIOD(val)		bfin_write32(TIMER10_PERIOD, val)
+#define bfin_read_TIMER10_WIDTH()		bfin_read32(TIMER10_WIDTH)
+#define bfin_write_TIMER10_WIDTH(val)		bfin_write32(TIMER10_WIDTH, val)
+
+/* Timer Groubfin_read_() of 3 */
+
+#define bfin_read_TIMER_ENABLE1()		bfin_read16(TIMER_ENABLE1)
+#define bfin_write_TIMER_ENABLE1(val)		bfin_write16(TIMER_ENABLE1, val)
+#define bfin_read_TIMER_DISABLE1()		bfin_read16(TIMER_DISABLE1)
+#define bfin_write_TIMER_DISABLE1(val)		bfin_write16(TIMER_DISABLE1, val)
+#define bfin_read_TIMER_STATUS1()		bfin_read32(TIMER_STATUS1)
+#define bfin_write_TIMER_STATUS1(val)		bfin_write32(TIMER_STATUS1, val)
+
+/* SPORT0 Registers */
+
+#define bfin_read_SPORT0_TCR1()			bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val)		bfin_write16(SPORT0_TCR1, val)
+#define bfin_read_SPORT0_TCR2()			bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val)		bfin_write16(SPORT0_TCR2, val)
+#define bfin_read_SPORT0_TCLKDIV()		bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val)		bfin_write16(SPORT0_TCLKDIV, val)
+#define bfin_read_SPORT0_TFSDIV()		bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val)		bfin_write16(SPORT0_TFSDIV, val)
+#define bfin_read_SPORT0_TX()			bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
+#define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val)		bfin_write16(SPORT0_RCR2, val)
+#define bfin_read_SPORT0_RCLKDIV()		bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val)		bfin_write16(SPORT0_RCLKDIV, val)
+#define bfin_read_SPORT0_RFSDIV()		bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val)		bfin_write16(SPORT0_RFSDIV, val)
+#define bfin_read_SPORT0_STAT()			bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val)		bfin_write16(SPORT0_STAT, val)
+#define bfin_read_SPORT0_CHNL()			bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val)		bfin_write16(SPORT0_CHNL, val)
+#define bfin_read_SPORT0_MCMC1()		bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val)		bfin_write16(SPORT0_MCMC1, val)
+#define bfin_read_SPORT0_MCMC2()		bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val)		bfin_write16(SPORT0_MCMC2, val)
+#define bfin_read_SPORT0_MTCS0()		bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val)		bfin_write32(SPORT0_MTCS0, val)
+#define bfin_read_SPORT0_MTCS1()		bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val)		bfin_write32(SPORT0_MTCS1, val)
+#define bfin_read_SPORT0_MTCS2()		bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val)		bfin_write32(SPORT0_MTCS2, val)
+#define bfin_read_SPORT0_MTCS3()		bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val)		bfin_write32(SPORT0_MTCS3, val)
+#define bfin_read_SPORT0_MRCS0()		bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val)		bfin_write32(SPORT0_MRCS0, val)
+#define bfin_read_SPORT0_MRCS1()		bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val)		bfin_write32(SPORT0_MRCS1, val)
+#define bfin_read_SPORT0_MRCS2()		bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val)		bfin_write32(SPORT0_MRCS2, val)
+#define bfin_read_SPORT0_MRCS3()		bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val)		bfin_write32(SPORT0_MRCS3, val)
+
+/* EPPI0 Registers */
+
+#define bfin_read_EPPI0_STATUS()		bfin_read16(EPPI0_STATUS)
+#define bfin_write_EPPI0_STATUS(val)		bfin_write16(EPPI0_STATUS, val)
+#define bfin_read_EPPI0_HCOUNT()		bfin_read16(EPPI0_HCOUNT)
+#define bfin_write_EPPI0_HCOUNT(val)		bfin_write16(EPPI0_HCOUNT, val)
+#define bfin_read_EPPI0_HDELAY()		bfin_read16(EPPI0_HDELAY)
+#define bfin_write_EPPI0_HDELAY(val)		bfin_write16(EPPI0_HDELAY, val)
+#define bfin_read_EPPI0_VCOUNT()		bfin_read16(EPPI0_VCOUNT)
+#define bfin_write_EPPI0_VCOUNT(val)		bfin_write16(EPPI0_VCOUNT, val)
+#define bfin_read_EPPI0_VDELAY()		bfin_read16(EPPI0_VDELAY)
+#define bfin_write_EPPI0_VDELAY(val)		bfin_write16(EPPI0_VDELAY, val)
+#define bfin_read_EPPI0_FRAME()			bfin_read16(EPPI0_FRAME)
+#define bfin_write_EPPI0_FRAME(val)		bfin_write16(EPPI0_FRAME, val)
+#define bfin_read_EPPI0_LINE()			bfin_read16(EPPI0_LINE)
+#define bfin_write_EPPI0_LINE(val)		bfin_write16(EPPI0_LINE, val)
+#define bfin_read_EPPI0_CLKDIV()		bfin_read16(EPPI0_CLKDIV)
+#define bfin_write_EPPI0_CLKDIV(val)		bfin_write16(EPPI0_CLKDIV, val)
+#define bfin_read_EPPI0_CONTROL()		bfin_read32(EPPI0_CONTROL)
+#define bfin_write_EPPI0_CONTROL(val)		bfin_write32(EPPI0_CONTROL, val)
+#define bfin_read_EPPI0_FS1W_HBL()		bfin_read32(EPPI0_FS1W_HBL)
+#define bfin_write_EPPI0_FS1W_HBL(val)		bfin_write32(EPPI0_FS1W_HBL, val)
+#define bfin_read_EPPI0_FS1P_AVPL()		bfin_read32(EPPI0_FS1P_AVPL)
+#define bfin_write_EPPI0_FS1P_AVPL(val)		bfin_write32(EPPI0_FS1P_AVPL, val)
+#define bfin_read_EPPI0_FS2W_LVB()		bfin_read32(EPPI0_FS2W_LVB)
+#define bfin_write_EPPI0_FS2W_LVB(val)		bfin_write32(EPPI0_FS2W_LVB, val)
+#define bfin_read_EPPI0_FS2P_LAVF()		bfin_read32(EPPI0_FS2P_LAVF)
+#define bfin_write_EPPI0_FS2P_LAVF(val)		bfin_write32(EPPI0_FS2P_LAVF, val)
+#define bfin_read_EPPI0_CLIP()			bfin_read32(EPPI0_CLIP)
+#define bfin_write_EPPI0_CLIP(val)		bfin_write32(EPPI0_CLIP, val)
+
+/* UART2 Registers */
+
+#define bfin_read_UART2_DLL()			bfin_read16(UART2_DLL)
+#define bfin_write_UART2_DLL(val)		bfin_write16(UART2_DLL, val)
+#define bfin_read_UART2_DLH()			bfin_read16(UART2_DLH)
+#define bfin_write_UART2_DLH(val)		bfin_write16(UART2_DLH, val)
+#define bfin_read_UART2_GCTL()			bfin_read16(UART2_GCTL)
+#define bfin_write_UART2_GCTL(val)		bfin_write16(UART2_GCTL, val)
+#define bfin_read_UART2_LCR()			bfin_read16(UART2_LCR)
+#define bfin_write_UART2_LCR(val)		bfin_write16(UART2_LCR, val)
+#define bfin_read_UART2_MCR()			bfin_read16(UART2_MCR)
+#define bfin_write_UART2_MCR(val)		bfin_write16(UART2_MCR, val)
+#define bfin_read_UART2_LSR()			bfin_read16(UART2_LSR)
+#define bfin_write_UART2_LSR(val)		bfin_write16(UART2_LSR, val)
+#define bfin_read_UART2_MSR()			bfin_read16(UART2_MSR)
+#define bfin_write_UART2_MSR(val)		bfin_write16(UART2_MSR, val)
+#define bfin_read_UART2_SCR()			bfin_read16(UART2_SCR)
+#define bfin_write_UART2_SCR(val)		bfin_write16(UART2_SCR, val)
+#define bfin_read_UART2_IER_SET()		bfin_read16(UART2_IER_SET)
+#define bfin_write_UART2_IER_SET(val)		bfin_write16(UART2_IER_SET, val)
+#define bfin_read_UART2_IER_CLEAR()		bfin_read16(UART2_IER_CLEAR)
+#define bfin_write_UART2_IER_CLEAR(val)		bfin_write16(UART2_IER_CLEAR, val)
+#define bfin_read_UART2_RBR()			bfin_read16(UART2_RBR)
+#define bfin_write_UART2_RBR(val)		bfin_write16(UART2_RBR, val)
+
+/* Two Wire Interface Registers (TWI1) */
+
+#define bfin_read_TWI1_CLKDIV()			bfin_read16(TWI1_CLKDIV)
+#define bfin_write_TWI1_CLKDIV(val)		bfin_write16(TWI1_CLKDIV, val)
+#define bfin_read_TWI1_CONTROL()		bfin_read16(TWI1_CONTROL)
+#define bfin_write_TWI1_CONTROL(val)		bfin_write16(TWI1_CONTROL, val)
+#define bfin_read_TWI1_SLAVE_CTRL()		bfin_read16(TWI1_SLAVE_CTRL)
+#define bfin_write_TWI1_SLAVE_CTRL(val)		bfin_write16(TWI1_SLAVE_CTRL, val)
+#define bfin_read_TWI1_SLAVE_STAT()		bfin_read16(TWI1_SLAVE_STAT)
+#define bfin_write_TWI1_SLAVE_STAT(val)		bfin_write16(TWI1_SLAVE_STAT, val)
+#define bfin_read_TWI1_SLAVE_ADDR()		bfin_read16(TWI1_SLAVE_ADDR)
+#define bfin_write_TWI1_SLAVE_ADDR(val)		bfin_write16(TWI1_SLAVE_ADDR, val)
+#define bfin_read_TWI1_MASTER_CTRL()		bfin_read16(TWI1_MASTER_CTRL)
+#define bfin_write_TWI1_MASTER_CTRL(val)	bfin_write16(TWI1_MASTER_CTRL, val)
+#define bfin_read_TWI1_MASTER_STAT()		bfin_read16(TWI1_MASTER_STAT)
+#define bfin_write_TWI1_MASTER_STAT(val)	bfin_write16(TWI1_MASTER_STAT, val)
+#define bfin_read_TWI1_MASTER_ADDR()		bfin_read16(TWI1_MASTER_ADDR)
+#define bfin_write_TWI1_MASTER_ADDR(val)	bfin_write16(TWI1_MASTER_ADDR, val)
+#define bfin_read_TWI1_INT_STAT()		bfin_read16(TWI1_INT_STAT)
+#define bfin_write_TWI1_INT_STAT(val)		bfin_write16(TWI1_INT_STAT, val)
+#define bfin_read_TWI1_INT_MASK()		bfin_read16(TWI1_INT_MASK)
+#define bfin_write_TWI1_INT_MASK(val)		bfin_write16(TWI1_INT_MASK, val)
+#define bfin_read_TWI1_FIFO_CTRL()		bfin_read16(TWI1_FIFO_CTRL)
+#define bfin_write_TWI1_FIFO_CTRL(val)		bfin_write16(TWI1_FIFO_CTRL, val)
+#define bfin_read_TWI1_FIFO_STAT()		bfin_read16(TWI1_FIFO_STAT)
+#define bfin_write_TWI1_FIFO_STAT(val)		bfin_write16(TWI1_FIFO_STAT, val)
+#define bfin_read_TWI1_XMT_DATA8()		bfin_read16(TWI1_XMT_DATA8)
+#define bfin_write_TWI1_XMT_DATA8(val)		bfin_write16(TWI1_XMT_DATA8, val)
+#define bfin_read_TWI1_XMT_DATA16()		bfin_read16(TWI1_XMT_DATA16)
+#define bfin_write_TWI1_XMT_DATA16(val)		bfin_write16(TWI1_XMT_DATA16, val)
+#define bfin_read_TWI1_RCV_DATA8()		bfin_read16(TWI1_RCV_DATA8)
+#define bfin_write_TWI1_RCV_DATA8(val)		bfin_write16(TWI1_RCV_DATA8, val)
+#define bfin_read_TWI1_RCV_DATA16()		bfin_read16(TWI1_RCV_DATA16)
+#define bfin_write_TWI1_RCV_DATA16(val)		bfin_write16(TWI1_RCV_DATA16, val)
+
+/* SPI2 Registers */
+
+#define bfin_read_SPI2_CTL()		bfin_read16(SPI2_CTL)
+#define bfin_write_SPI2_CTL(val)	bfin_write16(SPI2_CTL, val)
+#define bfin_read_SPI2_FLG()		bfin_read16(SPI2_FLG)
+#define bfin_write_SPI2_FLG(val)	bfin_write16(SPI2_FLG, val)
+#define bfin_read_SPI2_STAT()		bfin_read16(SPI2_STAT)
+#define bfin_write_SPI2_STAT(val)	bfin_write16(SPI2_STAT, val)
+#define bfin_read_SPI2_TDBR()		bfin_read16(SPI2_TDBR)
+#define bfin_write_SPI2_TDBR(val)	bfin_write16(SPI2_TDBR, val)
+#define bfin_read_SPI2_RDBR()		bfin_read16(SPI2_RDBR)
+#define bfin_write_SPI2_RDBR(val)	bfin_write16(SPI2_RDBR, val)
+#define bfin_read_SPI2_BAUD()		bfin_read16(SPI2_BAUD)
+#define bfin_write_SPI2_BAUD(val)	bfin_write16(SPI2_BAUD, val)
+#define bfin_read_SPI2_SHADOW()		bfin_read16(SPI2_SHADOW)
+#define bfin_write_SPI2_SHADOW(val)	bfin_write16(SPI2_SHADOW, val)
+
+/* MXVR Registers */
+
+#define bfin_read_MXVR_CONFIG()			bfin_read16(MXVR_CONFIG)
+#define bfin_write_MXVR_CONFIG(val)		bfin_write16(MXVR_CONFIG, val)
+#define bfin_read_MXVR_STATE_0()		bfin_read32(MXVR_STATE_0)
+#define bfin_write_MXVR_STATE_0(val)		bfin_write32(MXVR_STATE_0, val)
+#define bfin_read_MXVR_STATE_1()		bfin_read32(MXVR_STATE_1)
+#define bfin_write_MXVR_STATE_1(val)		bfin_write32(MXVR_STATE_1, val)
+#define bfin_read_MXVR_INT_STAT_0()		bfin_read32(MXVR_INT_STAT_0)
+#define bfin_write_MXVR_INT_STAT_0(val)		bfin_write32(MXVR_INT_STAT_0, val)
+#define bfin_read_MXVR_INT_STAT_1()		bfin_read32(MXVR_INT_STAT_1)
+#define bfin_write_MXVR_INT_STAT_1(val)		bfin_write32(MXVR_INT_STAT_1, val)
+#define bfin_read_MXVR_INT_EN_0()		bfin_read32(MXVR_INT_EN_0)
+#define bfin_write_MXVR_INT_EN_0(val)		bfin_write32(MXVR_INT_EN_0, val)
+#define bfin_read_MXVR_INT_EN_1()		bfin_read32(MXVR_INT_EN_1)
+#define bfin_write_MXVR_INT_EN_1(val)		bfin_write32(MXVR_INT_EN_1, val)
+#define bfin_read_MXVR_POSITION()		bfin_read16(MXVR_POSITION)
+#define bfin_write_MXVR_POSITION(val)		bfin_write16(MXVR_POSITION, val)
+#define bfin_read_MXVR_MAX_POSITION()		bfin_read16(MXVR_MAX_POSITION)
+#define bfin_write_MXVR_MAX_POSITION(val)	bfin_write16(MXVR_MAX_POSITION, val)
+#define bfin_read_MXVR_DELAY()			bfin_read16(MXVR_DELAY)
+#define bfin_write_MXVR_DELAY(val)		bfin_write16(MXVR_DELAY, val)
+#define bfin_read_MXVR_MAX_DELAY()		bfin_read16(MXVR_MAX_DELAY)
+#define bfin_write_MXVR_MAX_DELAY(val)		bfin_write16(MXVR_MAX_DELAY, val)
+#define bfin_read_MXVR_LADDR()			bfin_read32(MXVR_LADDR)
+#define bfin_write_MXVR_LADDR(val)		bfin_write32(MXVR_LADDR, val)
+#define bfin_read_MXVR_GADDR()			bfin_read16(MXVR_GADDR)
+#define bfin_write_MXVR_GADDR(val)		bfin_write16(MXVR_GADDR, val)
+#define bfin_read_MXVR_AADDR()			bfin_read32(MXVR_AADDR)
+#define bfin_write_MXVR_AADDR(val)		bfin_write32(MXVR_AADDR, val)
+
+/* MXVR Allocation Table Registers */
+
+#define bfin_read_MXVR_ALLOC_0()		bfin_read32(MXVR_ALLOC_0)
+#define bfin_write_MXVR_ALLOC_0(val)		bfin_write32(MXVR_ALLOC_0, val)
+#define bfin_read_MXVR_ALLOC_1()		bfin_read32(MXVR_ALLOC_1)
+#define bfin_write_MXVR_ALLOC_1(val)		bfin_write32(MXVR_ALLOC_1, val)
+#define bfin_read_MXVR_ALLOC_2()		bfin_read32(MXVR_ALLOC_2)
+#define bfin_write_MXVR_ALLOC_2(val)		bfin_write32(MXVR_ALLOC_2, val)
+#define bfin_read_MXVR_ALLOC_3()		bfin_read32(MXVR_ALLOC_3)
+#define bfin_write_MXVR_ALLOC_3(val)		bfin_write32(MXVR_ALLOC_3, val)
+#define bfin_read_MXVR_ALLOC_4()		bfin_read32(MXVR_ALLOC_4)
+#define bfin_write_MXVR_ALLOC_4(val)		bfin_write32(MXVR_ALLOC_4, val)
+#define bfin_read_MXVR_ALLOC_5()		bfin_read32(MXVR_ALLOC_5)
+#define bfin_write_MXVR_ALLOC_5(val)		bfin_write32(MXVR_ALLOC_5, val)
+#define bfin_read_MXVR_ALLOC_6()		bfin_read32(MXVR_ALLOC_6)
+#define bfin_write_MXVR_ALLOC_6(val)		bfin_write32(MXVR_ALLOC_6, val)
+#define bfin_read_MXVR_ALLOC_7()		bfin_read32(MXVR_ALLOC_7)
+#define bfin_write_MXVR_ALLOC_7(val)		bfin_write32(MXVR_ALLOC_7, val)
+#define bfin_read_MXVR_ALLOC_8()		bfin_read32(MXVR_ALLOC_8)
+#define bfin_write_MXVR_ALLOC_8(val)		bfin_write32(MXVR_ALLOC_8, val)
+#define bfin_read_MXVR_ALLOC_9()		bfin_read32(MXVR_ALLOC_9)
+#define bfin_write_MXVR_ALLOC_9(val)		bfin_write32(MXVR_ALLOC_9, val)
+#define bfin_read_MXVR_ALLOC_10()		bfin_read32(MXVR_ALLOC_10)
+#define bfin_write_MXVR_ALLOC_10(val)		bfin_write32(MXVR_ALLOC_10, val)
+#define bfin_read_MXVR_ALLOC_11()		bfin_read32(MXVR_ALLOC_11)
+#define bfin_write_MXVR_ALLOC_11(val)		bfin_write32(MXVR_ALLOC_11, val)
+#define bfin_read_MXVR_ALLOC_12()		bfin_read32(MXVR_ALLOC_12)
+#define bfin_write_MXVR_ALLOC_12(val)		bfin_write32(MXVR_ALLOC_12, val)
+#define bfin_read_MXVR_ALLOC_13()		bfin_read32(MXVR_ALLOC_13)
+#define bfin_write_MXVR_ALLOC_13(val)		bfin_write32(MXVR_ALLOC_13, val)
+#define bfin_read_MXVR_ALLOC_14()		bfin_read32(MXVR_ALLOC_14)
+#define bfin_write_MXVR_ALLOC_14(val)		bfin_write32(MXVR_ALLOC_14, val)
+
+/* MXVR Channel Assign Registers */
+
+#define bfin_read_MXVR_SYNC_LCHAN_0()		bfin_read32(MXVR_SYNC_LCHAN_0)
+#define bfin_write_MXVR_SYNC_LCHAN_0(val)	bfin_write32(MXVR_SYNC_LCHAN_0, val)
+#define bfin_read_MXVR_SYNC_LCHAN_1()		bfin_read32(MXVR_SYNC_LCHAN_1)
+#define bfin_write_MXVR_SYNC_LCHAN_1(val)	bfin_write32(MXVR_SYNC_LCHAN_1, val)
+#define bfin_read_MXVR_SYNC_LCHAN_2()		bfin_read32(MXVR_SYNC_LCHAN_2)
+#define bfin_write_MXVR_SYNC_LCHAN_2(val)	bfin_write32(MXVR_SYNC_LCHAN_2, val)
+#define bfin_read_MXVR_SYNC_LCHAN_3()		bfin_read32(MXVR_SYNC_LCHAN_3)
+#define bfin_write_MXVR_SYNC_LCHAN_3(val)	bfin_write32(MXVR_SYNC_LCHAN_3, val)
+#define bfin_read_MXVR_SYNC_LCHAN_4()		bfin_read32(MXVR_SYNC_LCHAN_4)
+#define bfin_write_MXVR_SYNC_LCHAN_4(val)	bfin_write32(MXVR_SYNC_LCHAN_4, val)
+#define bfin_read_MXVR_SYNC_LCHAN_5()		bfin_read32(MXVR_SYNC_LCHAN_5)
+#define bfin_write_MXVR_SYNC_LCHAN_5(val)	bfin_write32(MXVR_SYNC_LCHAN_5, val)
+#define bfin_read_MXVR_SYNC_LCHAN_6()		bfin_read32(MXVR_SYNC_LCHAN_6)
+#define bfin_write_MXVR_SYNC_LCHAN_6(val)	bfin_write32(MXVR_SYNC_LCHAN_6, val)
+#define bfin_read_MXVR_SYNC_LCHAN_7()		bfin_read32(MXVR_SYNC_LCHAN_7)
+#define bfin_write_MXVR_SYNC_LCHAN_7(val)	bfin_write32(MXVR_SYNC_LCHAN_7, val)
+
+/* MXVR DMA0 Registers */
+
+#define bfin_read_MXVR_DMA0_CONFIG()		bfin_read32(MXVR_DMA0_CONFIG)
+#define bfin_write_MXVR_DMA0_CONFIG(val)	bfin_write32(MXVR_DMA0_CONFIG, val)
+#define bfin_read_MXVR_DMA0_START_ADDR()	bfin_read32(MXVR_DMA0_START_ADDR)
+#define bfin_write_MXVR_DMA0_START_ADDR(val)	bfin_write32(MXVR_DMA0_START_ADDR)
+#define bfin_read_MXVR_DMA0_COUNT()		bfin_read16(MXVR_DMA0_COUNT)
+#define bfin_write_MXVR_DMA0_COUNT(val)		bfin_write16(MXVR_DMA0_COUNT, val)
+#define bfin_read_MXVR_DMA0_CURR_ADDR()		bfin_read32(MXVR_DMA0_CURR_ADDR)
+#define bfin_write_MXVR_DMA0_CURR_ADDR(val)	bfin_write32(MXVR_DMA0_CURR_ADDR)
+#define bfin_read_MXVR_DMA0_CURR_COUNT()	bfin_read16(MXVR_DMA0_CURR_COUNT)
+#define bfin_write_MXVR_DMA0_CURR_COUNT(val)	bfin_write16(MXVR_DMA0_CURR_COUNT, val)
+
+/* MXVR DMA1 Registers */
+
+#define bfin_read_MXVR_DMA1_CONFIG()		bfin_read32(MXVR_DMA1_CONFIG)
+#define bfin_write_MXVR_DMA1_CONFIG(val)	bfin_write32(MXVR_DMA1_CONFIG, val)
+#define bfin_read_MXVR_DMA1_START_ADDR()	bfin_read32(MXVR_DMA1_START_ADDR)
+#define bfin_write_MXVR_DMA1_START_ADDR(val)	bfin_write32(MXVR_DMA1_START_ADDR)
+#define bfin_read_MXVR_DMA1_COUNT()		bfin_read16(MXVR_DMA1_COUNT)
+#define bfin_write_MXVR_DMA1_COUNT(val)		bfin_write16(MXVR_DMA1_COUNT, val)
+#define bfin_read_MXVR_DMA1_CURR_ADDR()		bfin_read32(MXVR_DMA1_CURR_ADDR)
+#define bfin_write_MXVR_DMA1_CURR_ADDR(val)	bfin_write32(MXVR_DMA1_CURR_ADDR)
+#define bfin_read_MXVR_DMA1_CURR_COUNT()	bfin_read16(MXVR_DMA1_CURR_COUNT)
+#define bfin_write_MXVR_DMA1_CURR_COUNT(val)	bfin_write16(MXVR_DMA1_CURR_COUNT, val)
+
+/* MXVR DMA2 Registers */
+
+#define bfin_read_MXVR_DMA2_CONFIG()		bfin_read32(MXVR_DMA2_CONFIG)
+#define bfin_write_MXVR_DMA2_CONFIG(val)	bfin_write32(MXVR_DMA2_CONFIG, val)
+#define bfin_read_MXVR_DMA2_START_ADDR() 	bfin_read32(MXVR_DMA2_START_ADDR)
+#define bfin_write_MXVR_DMA2_START_ADDR(val) 	bfin_write32(MXVR_DMA2_START_ADDR)
+#define bfin_read_MXVR_DMA2_COUNT()		bfin_read16(MXVR_DMA2_COUNT)
+#define bfin_write_MXVR_DMA2_COUNT(val)		bfin_write16(MXVR_DMA2_COUNT, val)
+#define bfin_read_MXVR_DMA2_CURR_ADDR() 	bfin_read32(MXVR_DMA2_CURR_ADDR)
+#define bfin_write_MXVR_DMA2_CURR_ADDR(val) 	bfin_write32(MXVR_DMA2_CURR_ADDR)
+#define bfin_read_MXVR_DMA2_CURR_COUNT()	bfin_read16(MXVR_DMA2_CURR_COUNT)
+#define bfin_write_MXVR_DMA2_CURR_COUNT(val)	bfin_write16(MXVR_DMA2_CURR_COUNT, val)
+
+/* MXVR DMA3 Registers */
+
+#define bfin_read_MXVR_DMA3_CONFIG()		bfin_read32(MXVR_DMA3_CONFIG)
+#define bfin_write_MXVR_DMA3_CONFIG(val)	bfin_write32(MXVR_DMA3_CONFIG, val)
+#define bfin_read_MXVR_DMA3_START_ADDR() 	bfin_read32(MXVR_DMA3_START_ADDR)
+#define bfin_write_MXVR_DMA3_START_ADDR(val) 	bfin_write32(MXVR_DMA3_START_ADDR)
+#define bfin_read_MXVR_DMA3_COUNT()		bfin_read16(MXVR_DMA3_COUNT)
+#define bfin_write_MXVR_DMA3_COUNT(val)		bfin_write16(MXVR_DMA3_COUNT, val)
+#define bfin_read_MXVR_DMA3_CURR_ADDR() 	bfin_read32(MXVR_DMA3_CURR_ADDR)
+#define bfin_write_MXVR_DMA3_CURR_ADDR(val) 	bfin_write32(MXVR_DMA3_CURR_ADDR)
+#define bfin_read_MXVR_DMA3_CURR_COUNT()	bfin_read16(MXVR_DMA3_CURR_COUNT)
+#define bfin_write_MXVR_DMA3_CURR_COUNT(val)	bfin_write16(MXVR_DMA3_CURR_COUNT, val)
+
+/* MXVR DMA4 Registers */
+
+#define bfin_read_MXVR_DMA4_CONFIG()		bfin_read32(MXVR_DMA4_CONFIG)
+#define bfin_write_MXVR_DMA4_CONFIG(val)	bfin_write32(MXVR_DMA4_CONFIG, val)
+#define bfin_read_MXVR_DMA4_START_ADDR() 	bfin_read32(MXVR_DMA4_START_ADDR)
+#define bfin_write_MXVR_DMA4_START_ADDR(val) 	bfin_write32(MXVR_DMA4_START_ADDR)
+#define bfin_read_MXVR_DMA4_COUNT()		bfin_read16(MXVR_DMA4_COUNT)
+#define bfin_write_MXVR_DMA4_COUNT(val)		bfin_write16(MXVR_DMA4_COUNT, val)
+#define bfin_read_MXVR_DMA4_CURR_ADDR() 	bfin_read32(MXVR_DMA4_CURR_ADDR)
+#define bfin_write_MXVR_DMA4_CURR_ADDR(val) 	bfin_write32(MXVR_DMA4_CURR_ADDR)
+#define bfin_read_MXVR_DMA4_CURR_COUNT()	bfin_read16(MXVR_DMA4_CURR_COUNT)
+#define bfin_write_MXVR_DMA4_CURR_COUNT(val)	bfin_write16(MXVR_DMA4_CURR_COUNT, val)
+
+/* MXVR DMA5 Registers */
+
+#define bfin_read_MXVR_DMA5_CONFIG()		bfin_read32(MXVR_DMA5_CONFIG)
+#define bfin_write_MXVR_DMA5_CONFIG(val)	bfin_write32(MXVR_DMA5_CONFIG, val)
+#define bfin_read_MXVR_DMA5_START_ADDR() 	bfin_read32(MXVR_DMA5_START_ADDR)
+#define bfin_write_MXVR_DMA5_START_ADDR(val) 	bfin_write32(MXVR_DMA5_START_ADDR)
+#define bfin_read_MXVR_DMA5_COUNT()		bfin_read16(MXVR_DMA5_COUNT)
+#define bfin_write_MXVR_DMA5_COUNT(val)		bfin_write16(MXVR_DMA5_COUNT, val)
+#define bfin_read_MXVR_DMA5_CURR_ADDR() 	bfin_read32(MXVR_DMA5_CURR_ADDR)
+#define bfin_write_MXVR_DMA5_CURR_ADDR(val) 	bfin_write32(MXVR_DMA5_CURR_ADDR)
+#define bfin_read_MXVR_DMA5_CURR_COUNT()	bfin_read16(MXVR_DMA5_CURR_COUNT)
+#define bfin_write_MXVR_DMA5_CURR_COUNT(val)	bfin_write16(MXVR_DMA5_CURR_COUNT, val)
+
+/* MXVR DMA6 Registers */
+
+#define bfin_read_MXVR_DMA6_CONFIG()		bfin_read32(MXVR_DMA6_CONFIG)
+#define bfin_write_MXVR_DMA6_CONFIG(val)	bfin_write32(MXVR_DMA6_CONFIG, val)
+#define bfin_read_MXVR_DMA6_START_ADDR() 	bfin_read32(MXVR_DMA6_START_ADDR)
+#define bfin_write_MXVR_DMA6_START_ADDR(val) 	bfin_write32(MXVR_DMA6_START_ADDR)
+#define bfin_read_MXVR_DMA6_COUNT()		bfin_read16(MXVR_DMA6_COUNT)
+#define bfin_write_MXVR_DMA6_COUNT(val)		bfin_write16(MXVR_DMA6_COUNT, val)
+#define bfin_read_MXVR_DMA6_CURR_ADDR() 	bfin_read32(MXVR_DMA6_CURR_ADDR)
+#define bfin_write_MXVR_DMA6_CURR_ADDR(val) 	bfin_write32(MXVR_DMA6_CURR_ADDR)
+#define bfin_read_MXVR_DMA6_CURR_COUNT()	bfin_read16(MXVR_DMA6_CURR_COUNT)
+#define bfin_write_MXVR_DMA6_CURR_COUNT(val)	bfin_write16(MXVR_DMA6_CURR_COUNT, val)
+
+/* MXVR DMA7 Registers */
+
+#define bfin_read_MXVR_DMA7_CONFIG()		bfin_read32(MXVR_DMA7_CONFIG)
+#define bfin_write_MXVR_DMA7_CONFIG(val)	bfin_write32(MXVR_DMA7_CONFIG, val)
+#define bfin_read_MXVR_DMA7_START_ADDR() 	bfin_read32(MXVR_DMA7_START_ADDR)
+#define bfin_write_MXVR_DMA7_START_ADDR(val) 	bfin_write32(MXVR_DMA7_START_ADDR)
+#define bfin_read_MXVR_DMA7_COUNT()		bfin_read16(MXVR_DMA7_COUNT)
+#define bfin_write_MXVR_DMA7_COUNT(val)		bfin_write16(MXVR_DMA7_COUNT, val)
+#define bfin_read_MXVR_DMA7_CURR_ADDR() 	bfin_read32(MXVR_DMA7_CURR_ADDR)
+#define bfin_write_MXVR_DMA7_CURR_ADDR(val) 	bfin_write32(MXVR_DMA7_CURR_ADDR)
+#define bfin_read_MXVR_DMA7_CURR_COUNT()	bfin_read16(MXVR_DMA7_CURR_COUNT)
+#define bfin_write_MXVR_DMA7_CURR_COUNT(val)	bfin_write16(MXVR_DMA7_CURR_COUNT, val)
+
+/* MXVR Asynch Packet Registers */
+
+#define bfin_read_MXVR_AP_CTL()			bfin_read16(MXVR_AP_CTL)
+#define bfin_write_MXVR_AP_CTL(val)		bfin_write16(MXVR_AP_CTL, val)
+#define bfin_read_MXVR_APRB_START_ADDR() 	bfin_read32(MXVR_APRB_START_ADDR)
+#define bfin_write_MXVR_APRB_START_ADDR(val) 	bfin_write32(MXVR_APRB_START_ADDR)
+#define bfin_read_MXVR_APRB_CURR_ADDR() 	bfin_read32(MXVR_APRB_CURR_ADDR)
+#define bfin_write_MXVR_APRB_CURR_ADDR(val) 	bfin_write32(MXVR_APRB_CURR_ADDR)
+#define bfin_read_MXVR_APTB_START_ADDR() 	bfin_read32(MXVR_APTB_START_ADDR)
+#define bfin_write_MXVR_APTB_START_ADDR(val) 	bfin_write32(MXVR_APTB_START_ADDR)
+#define bfin_read_MXVR_APTB_CURR_ADDR() 	bfin_read32(MXVR_APTB_CURR_ADDR)
+#define bfin_write_MXVR_APTB_CURR_ADDR(val) 	bfin_write32(MXVR_APTB_CURR_ADDR)
+
+/* MXVR Control Message Registers */
+
+#define bfin_read_MXVR_CM_CTL()			bfin_read32(MXVR_CM_CTL)
+#define bfin_write_MXVR_CM_CTL(val)		bfin_write32(MXVR_CM_CTL, val)
+#define bfin_read_MXVR_CMRB_START_ADDR() 	bfin_read32(MXVR_CMRB_START_ADDR)
+#define bfin_write_MXVR_CMRB_START_ADDR(val) 	bfin_write32(MXVR_CMRB_START_ADDR)
+#define bfin_read_MXVR_CMRB_CURR_ADDR() 	bfin_read32(MXVR_CMRB_CURR_ADDR)
+#define bfin_write_MXVR_CMRB_CURR_ADDR(val) 	bfin_write32(MXVR_CMRB_CURR_ADDR)
+#define bfin_read_MXVR_CMTB_START_ADDR() 	bfin_read32(MXVR_CMTB_START_ADDR)
+#define bfin_write_MXVR_CMTB_START_ADDR(val) 	bfin_write32(MXVR_CMTB_START_ADDR)
+#define bfin_read_MXVR_CMTB_CURR_ADDR() 	bfin_read32(MXVR_CMTB_CURR_ADDR)
+#define bfin_write_MXVR_CMTB_CURR_ADDR(val) 	bfin_write32(MXVR_CMTB_CURR_ADDR)
+
+/* MXVR Remote Read Registers */
+
+#define bfin_read_MXVR_RRDB_START_ADDR() 	bfin_read32(MXVR_RRDB_START_ADDR)
+#define bfin_write_MXVR_RRDB_START_ADDR(val) 	bfin_write32(MXVR_RRDB_START_ADDR)
+#define bfin_read_MXVR_RRDB_CURR_ADDR() 	bfin_read32(MXVR_RRDB_CURR_ADDR)
+#define bfin_write_MXVR_RRDB_CURR_ADDR(val) 	bfin_write32(MXVR_RRDB_CURR_ADDR)
+
+/* MXVR Pattern Data Registers */
+
+#define bfin_read_MXVR_PAT_DATA_0()		bfin_read32(MXVR_PAT_DATA_0)
+#define bfin_write_MXVR_PAT_DATA_0(val)		bfin_write32(MXVR_PAT_DATA_0, val)
+#define bfin_read_MXVR_PAT_EN_0()		bfin_read32(MXVR_PAT_EN_0)
+#define bfin_write_MXVR_PAT_EN_0(val)		bfin_write32(MXVR_PAT_EN_0, val)
+#define bfin_read_MXVR_PAT_DATA_1()		bfin_read32(MXVR_PAT_DATA_1)
+#define bfin_write_MXVR_PAT_DATA_1(val)		bfin_write32(MXVR_PAT_DATA_1, val)
+#define bfin_read_MXVR_PAT_EN_1()		bfin_read32(MXVR_PAT_EN_1)
+#define bfin_write_MXVR_PAT_EN_1(val)		bfin_write32(MXVR_PAT_EN_1, val)
+
+/* MXVR Frame Counter Registers */
+
+#define bfin_read_MXVR_FRAME_CNT_0()		bfin_read16(MXVR_FRAME_CNT_0)
+#define bfin_write_MXVR_FRAME_CNT_0(val)	bfin_write16(MXVR_FRAME_CNT_0, val)
+#define bfin_read_MXVR_FRAME_CNT_1()		bfin_read16(MXVR_FRAME_CNT_1)
+#define bfin_write_MXVR_FRAME_CNT_1(val)	bfin_write16(MXVR_FRAME_CNT_1, val)
+
+/* MXVR Routing Table Registers */
+
+#define bfin_read_MXVR_ROUTING_0()		bfin_read32(MXVR_ROUTING_0)
+#define bfin_write_MXVR_ROUTING_0(val)		bfin_write32(MXVR_ROUTING_0, val)
+#define bfin_read_MXVR_ROUTING_1()		bfin_read32(MXVR_ROUTING_1)
+#define bfin_write_MXVR_ROUTING_1(val)		bfin_write32(MXVR_ROUTING_1, val)
+#define bfin_read_MXVR_ROUTING_2()		bfin_read32(MXVR_ROUTING_2)
+#define bfin_write_MXVR_ROUTING_2(val)		bfin_write32(MXVR_ROUTING_2, val)
+#define bfin_read_MXVR_ROUTING_3()		bfin_read32(MXVR_ROUTING_3)
+#define bfin_write_MXVR_ROUTING_3(val)		bfin_write32(MXVR_ROUTING_3, val)
+#define bfin_read_MXVR_ROUTING_4()		bfin_read32(MXVR_ROUTING_4)
+#define bfin_write_MXVR_ROUTING_4(val)		bfin_write32(MXVR_ROUTING_4, val)
+#define bfin_read_MXVR_ROUTING_5()		bfin_read32(MXVR_ROUTING_5)
+#define bfin_write_MXVR_ROUTING_5(val)		bfin_write32(MXVR_ROUTING_5, val)
+#define bfin_read_MXVR_ROUTING_6()		bfin_read32(MXVR_ROUTING_6)
+#define bfin_write_MXVR_ROUTING_6(val)		bfin_write32(MXVR_ROUTING_6, val)
+#define bfin_read_MXVR_ROUTING_7()		bfin_read32(MXVR_ROUTING_7)
+#define bfin_write_MXVR_ROUTING_7(val)		bfin_write32(MXVR_ROUTING_7, val)
+#define bfin_read_MXVR_ROUTING_8()		bfin_read32(MXVR_ROUTING_8)
+#define bfin_write_MXVR_ROUTING_8(val)		bfin_write32(MXVR_ROUTING_8, val)
+#define bfin_read_MXVR_ROUTING_9()		bfin_read32(MXVR_ROUTING_9)
+#define bfin_write_MXVR_ROUTING_9(val)		bfin_write32(MXVR_ROUTING_9, val)
+#define bfin_read_MXVR_ROUTING_10()		bfin_read32(MXVR_ROUTING_10)
+#define bfin_write_MXVR_ROUTING_10(val)		bfin_write32(MXVR_ROUTING_10, val)
+#define bfin_read_MXVR_ROUTING_11()		bfin_read32(MXVR_ROUTING_11)
+#define bfin_write_MXVR_ROUTING_11(val)		bfin_write32(MXVR_ROUTING_11, val)
+#define bfin_read_MXVR_ROUTING_12()		bfin_read32(MXVR_ROUTING_12)
+#define bfin_write_MXVR_ROUTING_12(val)		bfin_write32(MXVR_ROUTING_12, val)
+#define bfin_read_MXVR_ROUTING_13()		bfin_read32(MXVR_ROUTING_13)
+#define bfin_write_MXVR_ROUTING_13(val)		bfin_write32(MXVR_ROUTING_13, val)
+#define bfin_read_MXVR_ROUTING_14()		bfin_read32(MXVR_ROUTING_14)
+#define bfin_write_MXVR_ROUTING_14(val)		bfin_write32(MXVR_ROUTING_14, val)
+
+/* MXVR Counter-Clock-Control Registers */
+
+#define bfin_read_MXVR_BLOCK_CNT()		bfin_read16(MXVR_BLOCK_CNT)
+#define bfin_write_MXVR_BLOCK_CNT(val)		bfin_write16(MXVR_BLOCK_CNT, val)
+#define bfin_read_MXVR_CLK_CTL()		bfin_read32(MXVR_CLK_CTL)
+#define bfin_write_MXVR_CLK_CTL(val)		bfin_write32(MXVR_CLK_CTL, val)
+#define bfin_read_MXVR_CDRPLL_CTL()		bfin_read32(MXVR_CDRPLL_CTL)
+#define bfin_write_MXVR_CDRPLL_CTL(val)		bfin_write32(MXVR_CDRPLL_CTL, val)
+#define bfin_read_MXVR_FMPLL_CTL()		bfin_read32(MXVR_FMPLL_CTL)
+#define bfin_write_MXVR_FMPLL_CTL(val)		bfin_write32(MXVR_FMPLL_CTL, val)
+#define bfin_read_MXVR_PIN_CTL()		bfin_read16(MXVR_PIN_CTL)
+#define bfin_write_MXVR_PIN_CTL(val)		bfin_write16(MXVR_PIN_CTL, val)
+#define bfin_read_MXVR_SCLK_CNT()		bfin_read16(MXVR_SCLK_CNT)
+#define bfin_write_MXVR_SCLK_CNT(val)		bfin_write16(MXVR_SCLK_CNT, val)
+
+/* CAN Controller 1 Config 1 Registers */
+
+#define bfin_read_CAN1_MC1()		bfin_read16(CAN1_MC1)
+#define bfin_write_CAN1_MC1(val)	bfin_write16(CAN1_MC1, val)
+#define bfin_read_CAN1_MD1()		bfin_read16(CAN1_MD1)
+#define bfin_write_CAN1_MD1(val)	bfin_write16(CAN1_MD1, val)
+#define bfin_read_CAN1_TRS1()		bfin_read16(CAN1_TRS1)
+#define bfin_write_CAN1_TRS1(val)	bfin_write16(CAN1_TRS1, val)
+#define bfin_read_CAN1_TRR1()		bfin_read16(CAN1_TRR1)
+#define bfin_write_CAN1_TRR1(val)	bfin_write16(CAN1_TRR1, val)
+#define bfin_read_CAN1_TA1()		bfin_read16(CAN1_TA1)
+#define bfin_write_CAN1_TA1(val)	bfin_write16(CAN1_TA1, val)
+#define bfin_read_CAN1_AA1()		bfin_read16(CAN1_AA1)
+#define bfin_write_CAN1_AA1(val)	bfin_write16(CAN1_AA1, val)
+#define bfin_read_CAN1_RMP1()		bfin_read16(CAN1_RMP1)
+#define bfin_write_CAN1_RMP1(val)	bfin_write16(CAN1_RMP1, val)
+#define bfin_read_CAN1_RML1()		bfin_read16(CAN1_RML1)
+#define bfin_write_CAN1_RML1(val)	bfin_write16(CAN1_RML1, val)
+#define bfin_read_CAN1_MBTIF1()		bfin_read16(CAN1_MBTIF1)
+#define bfin_write_CAN1_MBTIF1(val)	bfin_write16(CAN1_MBTIF1, val)
+#define bfin_read_CAN1_MBRIF1()		bfin_read16(CAN1_MBRIF1)
+#define bfin_write_CAN1_MBRIF1(val)	bfin_write16(CAN1_MBRIF1, val)
+#define bfin_read_CAN1_MBIM1()		bfin_read16(CAN1_MBIM1)
+#define bfin_write_CAN1_MBIM1(val)	bfin_write16(CAN1_MBIM1, val)
+#define bfin_read_CAN1_RFH1()		bfin_read16(CAN1_RFH1)
+#define bfin_write_CAN1_RFH1(val)	bfin_write16(CAN1_RFH1, val)
+#define bfin_read_CAN1_OPSS1()		bfin_read16(CAN1_OPSS1)
+#define bfin_write_CAN1_OPSS1(val)	bfin_write16(CAN1_OPSS1, val)
+
+/* CAN Controller 1 Config 2 Registers */
+
+#define bfin_read_CAN1_MC2()		bfin_read16(CAN1_MC2)
+#define bfin_write_CAN1_MC2(val)	bfin_write16(CAN1_MC2, val)
+#define bfin_read_CAN1_MD2()		bfin_read16(CAN1_MD2)
+#define bfin_write_CAN1_MD2(val)	bfin_write16(CAN1_MD2, val)
+#define bfin_read_CAN1_TRS2()		bfin_read16(CAN1_TRS2)
+#define bfin_write_CAN1_TRS2(val)	bfin_write16(CAN1_TRS2, val)
+#define bfin_read_CAN1_TRR2()		bfin_read16(CAN1_TRR2)
+#define bfin_write_CAN1_TRR2(val)	bfin_write16(CAN1_TRR2, val)
+#define bfin_read_CAN1_TA2()		bfin_read16(CAN1_TA2)
+#define bfin_write_CAN1_TA2(val)	bfin_write16(CAN1_TA2, val)
+#define bfin_read_CAN1_AA2()		bfin_read16(CAN1_AA2)
+#define bfin_write_CAN1_AA2(val)	bfin_write16(CAN1_AA2, val)
+#define bfin_read_CAN1_RMP2()		bfin_read16(CAN1_RMP2)
+#define bfin_write_CAN1_RMP2(val)	bfin_write16(CAN1_RMP2, val)
+#define bfin_read_CAN1_RML2()		bfin_read16(CAN1_RML2)
+#define bfin_write_CAN1_RML2(val)	bfin_write16(CAN1_RML2, val)
+#define bfin_read_CAN1_MBTIF2()		bfin_read16(CAN1_MBTIF2)
+#define bfin_write_CAN1_MBTIF2(val)	bfin_write16(CAN1_MBTIF2, val)
+#define bfin_read_CAN1_MBRIF2()		bfin_read16(CAN1_MBRIF2)
+#define bfin_write_CAN1_MBRIF2(val)	bfin_write16(CAN1_MBRIF2, val)
+#define bfin_read_CAN1_MBIM2()		bfin_read16(CAN1_MBIM2)
+#define bfin_write_CAN1_MBIM2(val)	bfin_write16(CAN1_MBIM2, val)
+#define bfin_read_CAN1_RFH2()		bfin_read16(CAN1_RFH2)
+#define bfin_write_CAN1_RFH2(val)	bfin_write16(CAN1_RFH2, val)
+#define bfin_read_CAN1_OPSS2()		bfin_read16(CAN1_OPSS2)
+#define bfin_write_CAN1_OPSS2(val)	bfin_write16(CAN1_OPSS2, val)
+
+/* CAN Controller 1 Clock/Interrubfin_read_()t/Counter Registers */
+
+#define bfin_read_CAN1_CLOCK()		bfin_read16(CAN1_CLOCK)
+#define bfin_write_CAN1_CLOCK(val)	bfin_write16(CAN1_CLOCK, val)
+#define bfin_read_CAN1_TIMING()		bfin_read16(CAN1_TIMING)
+#define bfin_write_CAN1_TIMING(val)	bfin_write16(CAN1_TIMING, val)
+#define bfin_read_CAN1_DEBUG()		bfin_read16(CAN1_DEBUG)
+#define bfin_write_CAN1_DEBUG(val)	bfin_write16(CAN1_DEBUG, val)
+#define bfin_read_CAN1_STATUS()		bfin_read16(CAN1_STATUS)
+#define bfin_write_CAN1_STATUS(val)	bfin_write16(CAN1_STATUS, val)
+#define bfin_read_CAN1_CEC()		bfin_read16(CAN1_CEC)
+#define bfin_write_CAN1_CEC(val)	bfin_write16(CAN1_CEC, val)
+#define bfin_read_CAN1_GIS()		bfin_read16(CAN1_GIS)
+#define bfin_write_CAN1_GIS(val)	bfin_write16(CAN1_GIS, val)
+#define bfin_read_CAN1_GIM()		bfin_read16(CAN1_GIM)
+#define bfin_write_CAN1_GIM(val)	bfin_write16(CAN1_GIM, val)
+#define bfin_read_CAN1_GIF()		bfin_read16(CAN1_GIF)
+#define bfin_write_CAN1_GIF(val)	bfin_write16(CAN1_GIF, val)
+#define bfin_read_CAN1_CONTROL()	bfin_read16(CAN1_CONTROL)
+#define bfin_write_CAN1_CONTROL(val)	bfin_write16(CAN1_CONTROL, val)
+#define bfin_read_CAN1_INTR()		bfin_read16(CAN1_INTR)
+#define bfin_write_CAN1_INTR(val)	bfin_write16(CAN1_INTR, val)
+#define bfin_read_CAN1_MBTD()		bfin_read16(CAN1_MBTD)
+#define bfin_write_CAN1_MBTD(val)	bfin_write16(CAN1_MBTD, val)
+#define bfin_read_CAN1_EWR()		bfin_read16(CAN1_EWR)
+#define bfin_write_CAN1_EWR(val)	bfin_write16(CAN1_EWR, val)
+#define bfin_read_CAN1_ESR()		bfin_read16(CAN1_ESR)
+#define bfin_write_CAN1_ESR(val)	bfin_write16(CAN1_ESR, val)
+#define bfin_read_CAN1_UCCNT()		bfin_read16(CAN1_UCCNT)
+#define bfin_write_CAN1_UCCNT(val)	bfin_write16(CAN1_UCCNT, val)
+#define bfin_read_CAN1_UCRC()		bfin_read16(CAN1_UCRC)
+#define bfin_write_CAN1_UCRC(val)	bfin_write16(CAN1_UCRC, val)
+#define bfin_read_CAN1_UCCNF()		bfin_read16(CAN1_UCCNF)
+#define bfin_write_CAN1_UCCNF(val)	bfin_write16(CAN1_UCCNF, val)
+
+/* CAN Controller 1 Mailbox Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN1_AM00L()		bfin_read16(CAN1_AM00L)
+#define bfin_write_CAN1_AM00L(val)	bfin_write16(CAN1_AM00L, val)
+#define bfin_read_CAN1_AM00H()		bfin_read16(CAN1_AM00H)
+#define bfin_write_CAN1_AM00H(val)	bfin_write16(CAN1_AM00H, val)
+#define bfin_read_CAN1_AM01L()		bfin_read16(CAN1_AM01L)
+#define bfin_write_CAN1_AM01L(val)	bfin_write16(CAN1_AM01L, val)
+#define bfin_read_CAN1_AM01H()		bfin_read16(CAN1_AM01H)
+#define bfin_write_CAN1_AM01H(val)	bfin_write16(CAN1_AM01H, val)
+#define bfin_read_CAN1_AM02L()		bfin_read16(CAN1_AM02L)
+#define bfin_write_CAN1_AM02L(val)	bfin_write16(CAN1_AM02L, val)
+#define bfin_read_CAN1_AM02H()		bfin_read16(CAN1_AM02H)
+#define bfin_write_CAN1_AM02H(val)	bfin_write16(CAN1_AM02H, val)
+#define bfin_read_CAN1_AM03L()		bfin_read16(CAN1_AM03L)
+#define bfin_write_CAN1_AM03L(val)	bfin_write16(CAN1_AM03L, val)
+#define bfin_read_CAN1_AM03H()		bfin_read16(CAN1_AM03H)
+#define bfin_write_CAN1_AM03H(val)	bfin_write16(CAN1_AM03H, val)
+#define bfin_read_CAN1_AM04L()		bfin_read16(CAN1_AM04L)
+#define bfin_write_CAN1_AM04L(val)	bfin_write16(CAN1_AM04L, val)
+#define bfin_read_CAN1_AM04H()		bfin_read16(CAN1_AM04H)
+#define bfin_write_CAN1_AM04H(val)	bfin_write16(CAN1_AM04H, val)
+#define bfin_read_CAN1_AM05L()		bfin_read16(CAN1_AM05L)
+#define bfin_write_CAN1_AM05L(val)	bfin_write16(CAN1_AM05L, val)
+#define bfin_read_CAN1_AM05H()		bfin_read16(CAN1_AM05H)
+#define bfin_write_CAN1_AM05H(val)	bfin_write16(CAN1_AM05H, val)
+#define bfin_read_CAN1_AM06L()		bfin_read16(CAN1_AM06L)
+#define bfin_write_CAN1_AM06L(val)	bfin_write16(CAN1_AM06L, val)
+#define bfin_read_CAN1_AM06H()		bfin_read16(CAN1_AM06H)
+#define bfin_write_CAN1_AM06H(val)	bfin_write16(CAN1_AM06H, val)
+#define bfin_read_CAN1_AM07L()		bfin_read16(CAN1_AM07L)
+#define bfin_write_CAN1_AM07L(val)	bfin_write16(CAN1_AM07L, val)
+#define bfin_read_CAN1_AM07H()		bfin_read16(CAN1_AM07H)
+#define bfin_write_CAN1_AM07H(val)	bfin_write16(CAN1_AM07H, val)
+#define bfin_read_CAN1_AM08L()		bfin_read16(CAN1_AM08L)
+#define bfin_write_CAN1_AM08L(val)	bfin_write16(CAN1_AM08L, val)
+#define bfin_read_CAN1_AM08H()		bfin_read16(CAN1_AM08H)
+#define bfin_write_CAN1_AM08H(val)	bfin_write16(CAN1_AM08H, val)
+#define bfin_read_CAN1_AM09L()		bfin_read16(CAN1_AM09L)
+#define bfin_write_CAN1_AM09L(val)	bfin_write16(CAN1_AM09L, val)
+#define bfin_read_CAN1_AM09H()		bfin_read16(CAN1_AM09H)
+#define bfin_write_CAN1_AM09H(val)	bfin_write16(CAN1_AM09H, val)
+#define bfin_read_CAN1_AM10L()		bfin_read16(CAN1_AM10L)
+#define bfin_write_CAN1_AM10L(val)	bfin_write16(CAN1_AM10L, val)
+#define bfin_read_CAN1_AM10H()		bfin_read16(CAN1_AM10H)
+#define bfin_write_CAN1_AM10H(val)	bfin_write16(CAN1_AM10H, val)
+#define bfin_read_CAN1_AM11L()		bfin_read16(CAN1_AM11L)
+#define bfin_write_CAN1_AM11L(val)	bfin_write16(CAN1_AM11L, val)
+#define bfin_read_CAN1_AM11H()		bfin_read16(CAN1_AM11H)
+#define bfin_write_CAN1_AM11H(val)	bfin_write16(CAN1_AM11H, val)
+#define bfin_read_CAN1_AM12L()		bfin_read16(CAN1_AM12L)
+#define bfin_write_CAN1_AM12L(val)	bfin_write16(CAN1_AM12L, val)
+#define bfin_read_CAN1_AM12H()		bfin_read16(CAN1_AM12H)
+#define bfin_write_CAN1_AM12H(val)	bfin_write16(CAN1_AM12H, val)
+#define bfin_read_CAN1_AM13L()		bfin_read16(CAN1_AM13L)
+#define bfin_write_CAN1_AM13L(val)	bfin_write16(CAN1_AM13L, val)
+#define bfin_read_CAN1_AM13H()		bfin_read16(CAN1_AM13H)
+#define bfin_write_CAN1_AM13H(val)	bfin_write16(CAN1_AM13H, val)
+#define bfin_read_CAN1_AM14L()		bfin_read16(CAN1_AM14L)
+#define bfin_write_CAN1_AM14L(val)	bfin_write16(CAN1_AM14L, val)
+#define bfin_read_CAN1_AM14H()		bfin_read16(CAN1_AM14H)
+#define bfin_write_CAN1_AM14H(val)	bfin_write16(CAN1_AM14H, val)
+#define bfin_read_CAN1_AM15L()		bfin_read16(CAN1_AM15L)
+#define bfin_write_CAN1_AM15L(val)	bfin_write16(CAN1_AM15L, val)
+#define bfin_read_CAN1_AM15H()		bfin_read16(CAN1_AM15H)
+#define bfin_write_CAN1_AM15H(val)	bfin_write16(CAN1_AM15H, val)
+
+/* CAN Controller 1 Mailbox Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN1_AM16L()		bfin_read16(CAN1_AM16L)
+#define bfin_write_CAN1_AM16L(val)	bfin_write16(CAN1_AM16L, val)
+#define bfin_read_CAN1_AM16H()		bfin_read16(CAN1_AM16H)
+#define bfin_write_CAN1_AM16H(val)	bfin_write16(CAN1_AM16H, val)
+#define bfin_read_CAN1_AM17L()		bfin_read16(CAN1_AM17L)
+#define bfin_write_CAN1_AM17L(val)	bfin_write16(CAN1_AM17L, val)
+#define bfin_read_CAN1_AM17H()		bfin_read16(CAN1_AM17H)
+#define bfin_write_CAN1_AM17H(val)	bfin_write16(CAN1_AM17H, val)
+#define bfin_read_CAN1_AM18L()		bfin_read16(CAN1_AM18L)
+#define bfin_write_CAN1_AM18L(val)	bfin_write16(CAN1_AM18L, val)
+#define bfin_read_CAN1_AM18H()		bfin_read16(CAN1_AM18H)
+#define bfin_write_CAN1_AM18H(val)	bfin_write16(CAN1_AM18H, val)
+#define bfin_read_CAN1_AM19L()		bfin_read16(CAN1_AM19L)
+#define bfin_write_CAN1_AM19L(val)	bfin_write16(CAN1_AM19L, val)
+#define bfin_read_CAN1_AM19H()		bfin_read16(CAN1_AM19H)
+#define bfin_write_CAN1_AM19H(val)	bfin_write16(CAN1_AM19H, val)
+#define bfin_read_CAN1_AM20L()		bfin_read16(CAN1_AM20L)
+#define bfin_write_CAN1_AM20L(val)	bfin_write16(CAN1_AM20L, val)
+#define bfin_read_CAN1_AM20H()		bfin_read16(CAN1_AM20H)
+#define bfin_write_CAN1_AM20H(val)	bfin_write16(CAN1_AM20H, val)
+#define bfin_read_CAN1_AM21L()		bfin_read16(CAN1_AM21L)
+#define bfin_write_CAN1_AM21L(val)	bfin_write16(CAN1_AM21L, val)
+#define bfin_read_CAN1_AM21H()		bfin_read16(CAN1_AM21H)
+#define bfin_write_CAN1_AM21H(val)	bfin_write16(CAN1_AM21H, val)
+#define bfin_read_CAN1_AM22L()		bfin_read16(CAN1_AM22L)
+#define bfin_write_CAN1_AM22L(val)	bfin_write16(CAN1_AM22L, val)
+#define bfin_read_CAN1_AM22H()		bfin_read16(CAN1_AM22H)
+#define bfin_write_CAN1_AM22H(val)	bfin_write16(CAN1_AM22H, val)
+#define bfin_read_CAN1_AM23L()		bfin_read16(CAN1_AM23L)
+#define bfin_write_CAN1_AM23L(val)	bfin_write16(CAN1_AM23L, val)
+#define bfin_read_CAN1_AM23H()		bfin_read16(CAN1_AM23H)
+#define bfin_write_CAN1_AM23H(val)	bfin_write16(CAN1_AM23H, val)
+#define bfin_read_CAN1_AM24L()		bfin_read16(CAN1_AM24L)
+#define bfin_write_CAN1_AM24L(val)	bfin_write16(CAN1_AM24L, val)
+#define bfin_read_CAN1_AM24H()		bfin_read16(CAN1_AM24H)
+#define bfin_write_CAN1_AM24H(val)	bfin_write16(CAN1_AM24H, val)
+#define bfin_read_CAN1_AM25L()		bfin_read16(CAN1_AM25L)
+#define bfin_write_CAN1_AM25L(val)	bfin_write16(CAN1_AM25L, val)
+#define bfin_read_CAN1_AM25H()		bfin_read16(CAN1_AM25H)
+#define bfin_write_CAN1_AM25H(val)	bfin_write16(CAN1_AM25H, val)
+#define bfin_read_CAN1_AM26L()		bfin_read16(CAN1_AM26L)
+#define bfin_write_CAN1_AM26L(val)	bfin_write16(CAN1_AM26L, val)
+#define bfin_read_CAN1_AM26H()		bfin_read16(CAN1_AM26H)
+#define bfin_write_CAN1_AM26H(val)	bfin_write16(CAN1_AM26H, val)
+#define bfin_read_CAN1_AM27L()		bfin_read16(CAN1_AM27L)
+#define bfin_write_CAN1_AM27L(val)	bfin_write16(CAN1_AM27L, val)
+#define bfin_read_CAN1_AM27H()		bfin_read16(CAN1_AM27H)
+#define bfin_write_CAN1_AM27H(val)	bfin_write16(CAN1_AM27H, val)
+#define bfin_read_CAN1_AM28L()		bfin_read16(CAN1_AM28L)
+#define bfin_write_CAN1_AM28L(val)	bfin_write16(CAN1_AM28L, val)
+#define bfin_read_CAN1_AM28H()		bfin_read16(CAN1_AM28H)
+#define bfin_write_CAN1_AM28H(val)	bfin_write16(CAN1_AM28H, val)
+#define bfin_read_CAN1_AM29L()		bfin_read16(CAN1_AM29L)
+#define bfin_write_CAN1_AM29L(val)	bfin_write16(CAN1_AM29L, val)
+#define bfin_read_CAN1_AM29H()		bfin_read16(CAN1_AM29H)
+#define bfin_write_CAN1_AM29H(val)	bfin_write16(CAN1_AM29H, val)
+#define bfin_read_CAN1_AM30L()		bfin_read16(CAN1_AM30L)
+#define bfin_write_CAN1_AM30L(val)	bfin_write16(CAN1_AM30L, val)
+#define bfin_read_CAN1_AM30H()		bfin_read16(CAN1_AM30H)
+#define bfin_write_CAN1_AM30H(val)	bfin_write16(CAN1_AM30H, val)
+#define bfin_read_CAN1_AM31L()		bfin_read16(CAN1_AM31L)
+#define bfin_write_CAN1_AM31L(val)	bfin_write16(CAN1_AM31L, val)
+#define bfin_read_CAN1_AM31H()		bfin_read16(CAN1_AM31H)
+#define bfin_write_CAN1_AM31H(val)	bfin_write16(CAN1_AM31H, val)
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define bfin_read_CAN1_MB00_DATA0()		bfin_read16(CAN1_MB00_DATA0)
+#define bfin_write_CAN1_MB00_DATA0(val)		bfin_write16(CAN1_MB00_DATA0, val)
+#define bfin_read_CAN1_MB00_DATA1()		bfin_read16(CAN1_MB00_DATA1)
+#define bfin_write_CAN1_MB00_DATA1(val)		bfin_write16(CAN1_MB00_DATA1, val)
+#define bfin_read_CAN1_MB00_DATA2()		bfin_read16(CAN1_MB00_DATA2)
+#define bfin_write_CAN1_MB00_DATA2(val)		bfin_write16(CAN1_MB00_DATA2, val)
+#define bfin_read_CAN1_MB00_DATA3()		bfin_read16(CAN1_MB00_DATA3)
+#define bfin_write_CAN1_MB00_DATA3(val)		bfin_write16(CAN1_MB00_DATA3, val)
+#define bfin_read_CAN1_MB00_LENGTH()		bfin_read16(CAN1_MB00_LENGTH)
+#define bfin_write_CAN1_MB00_LENGTH(val)	bfin_write16(CAN1_MB00_LENGTH, val)
+#define bfin_read_CAN1_MB00_TIMESTAMP()		bfin_read16(CAN1_MB00_TIMESTAMP)
+#define bfin_write_CAN1_MB00_TIMESTAMP(val)	bfin_write16(CAN1_MB00_TIMESTAMP, val)
+#define bfin_read_CAN1_MB00_ID0()		bfin_read16(CAN1_MB00_ID0)
+#define bfin_write_CAN1_MB00_ID0(val)		bfin_write16(CAN1_MB00_ID0, val)
+#define bfin_read_CAN1_MB00_ID1()		bfin_read16(CAN1_MB00_ID1)
+#define bfin_write_CAN1_MB00_ID1(val)		bfin_write16(CAN1_MB00_ID1, val)
+#define bfin_read_CAN1_MB01_DATA0()		bfin_read16(CAN1_MB01_DATA0)
+#define bfin_write_CAN1_MB01_DATA0(val)		bfin_write16(CAN1_MB01_DATA0, val)
+#define bfin_read_CAN1_MB01_DATA1()		bfin_read16(CAN1_MB01_DATA1)
+#define bfin_write_CAN1_MB01_DATA1(val)		bfin_write16(CAN1_MB01_DATA1, val)
+#define bfin_read_CAN1_MB01_DATA2()		bfin_read16(CAN1_MB01_DATA2)
+#define bfin_write_CAN1_MB01_DATA2(val)		bfin_write16(CAN1_MB01_DATA2, val)
+#define bfin_read_CAN1_MB01_DATA3()		bfin_read16(CAN1_MB01_DATA3)
+#define bfin_write_CAN1_MB01_DATA3(val)		bfin_write16(CAN1_MB01_DATA3, val)
+#define bfin_read_CAN1_MB01_LENGTH()		bfin_read16(CAN1_MB01_LENGTH)
+#define bfin_write_CAN1_MB01_LENGTH(val)	bfin_write16(CAN1_MB01_LENGTH, val)
+#define bfin_read_CAN1_MB01_TIMESTAMP()		bfin_read16(CAN1_MB01_TIMESTAMP)
+#define bfin_write_CAN1_MB01_TIMESTAMP(val)	bfin_write16(CAN1_MB01_TIMESTAMP, val)
+#define bfin_read_CAN1_MB01_ID0()		bfin_read16(CAN1_MB01_ID0)
+#define bfin_write_CAN1_MB01_ID0(val)		bfin_write16(CAN1_MB01_ID0, val)
+#define bfin_read_CAN1_MB01_ID1()		bfin_read16(CAN1_MB01_ID1)
+#define bfin_write_CAN1_MB01_ID1(val)		bfin_write16(CAN1_MB01_ID1, val)
+#define bfin_read_CAN1_MB02_DATA0()		bfin_read16(CAN1_MB02_DATA0)
+#define bfin_write_CAN1_MB02_DATA0(val)		bfin_write16(CAN1_MB02_DATA0, val)
+#define bfin_read_CAN1_MB02_DATA1()		bfin_read16(CAN1_MB02_DATA1)
+#define bfin_write_CAN1_MB02_DATA1(val)		bfin_write16(CAN1_MB02_DATA1, val)
+#define bfin_read_CAN1_MB02_DATA2()		bfin_read16(CAN1_MB02_DATA2)
+#define bfin_write_CAN1_MB02_DATA2(val)		bfin_write16(CAN1_MB02_DATA2, val)
+#define bfin_read_CAN1_MB02_DATA3()		bfin_read16(CAN1_MB02_DATA3)
+#define bfin_write_CAN1_MB02_DATA3(val)		bfin_write16(CAN1_MB02_DATA3, val)
+#define bfin_read_CAN1_MB02_LENGTH()		bfin_read16(CAN1_MB02_LENGTH)
+#define bfin_write_CAN1_MB02_LENGTH(val)	bfin_write16(CAN1_MB02_LENGTH, val)
+#define bfin_read_CAN1_MB02_TIMESTAMP()		bfin_read16(CAN1_MB02_TIMESTAMP)
+#define bfin_write_CAN1_MB02_TIMESTAMP(val)	bfin_write16(CAN1_MB02_TIMESTAMP, val)
+#define bfin_read_CAN1_MB02_ID0()		bfin_read16(CAN1_MB02_ID0)
+#define bfin_write_CAN1_MB02_ID0(val)		bfin_write16(CAN1_MB02_ID0, val)
+#define bfin_read_CAN1_MB02_ID1()		bfin_read16(CAN1_MB02_ID1)
+#define bfin_write_CAN1_MB02_ID1(val)		bfin_write16(CAN1_MB02_ID1, val)
+#define bfin_read_CAN1_MB03_DATA0()		bfin_read16(CAN1_MB03_DATA0)
+#define bfin_write_CAN1_MB03_DATA0(val)		bfin_write16(CAN1_MB03_DATA0, val)
+#define bfin_read_CAN1_MB03_DATA1()		bfin_read16(CAN1_MB03_DATA1)
+#define bfin_write_CAN1_MB03_DATA1(val)		bfin_write16(CAN1_MB03_DATA1, val)
+#define bfin_read_CAN1_MB03_DATA2()		bfin_read16(CAN1_MB03_DATA2)
+#define bfin_write_CAN1_MB03_DATA2(val)		bfin_write16(CAN1_MB03_DATA2, val)
+#define bfin_read_CAN1_MB03_DATA3()		bfin_read16(CAN1_MB03_DATA3)
+#define bfin_write_CAN1_MB03_DATA3(val)		bfin_write16(CAN1_MB03_DATA3, val)
+#define bfin_read_CAN1_MB03_LENGTH()		bfin_read16(CAN1_MB03_LENGTH)
+#define bfin_write_CAN1_MB03_LENGTH(val)	bfin_write16(CAN1_MB03_LENGTH, val)
+#define bfin_read_CAN1_MB03_TIMESTAMP()		bfin_read16(CAN1_MB03_TIMESTAMP)
+#define bfin_write_CAN1_MB03_TIMESTAMP(val)	bfin_write16(CAN1_MB03_TIMESTAMP, val)
+#define bfin_read_CAN1_MB03_ID0()		bfin_read16(CAN1_MB03_ID0)
+#define bfin_write_CAN1_MB03_ID0(val)		bfin_write16(CAN1_MB03_ID0, val)
+#define bfin_read_CAN1_MB03_ID1()		bfin_read16(CAN1_MB03_ID1)
+#define bfin_write_CAN1_MB03_ID1(val)		bfin_write16(CAN1_MB03_ID1, val)
+#define bfin_read_CAN1_MB04_DATA0()		bfin_read16(CAN1_MB04_DATA0)
+#define bfin_write_CAN1_MB04_DATA0(val)		bfin_write16(CAN1_MB04_DATA0, val)
+#define bfin_read_CAN1_MB04_DATA1()		bfin_read16(CAN1_MB04_DATA1)
+#define bfin_write_CAN1_MB04_DATA1(val)		bfin_write16(CAN1_MB04_DATA1, val)
+#define bfin_read_CAN1_MB04_DATA2()		bfin_read16(CAN1_MB04_DATA2)
+#define bfin_write_CAN1_MB04_DATA2(val)		bfin_write16(CAN1_MB04_DATA2, val)
+#define bfin_read_CAN1_MB04_DATA3()		bfin_read16(CAN1_MB04_DATA3)
+#define bfin_write_CAN1_MB04_DATA3(val)		bfin_write16(CAN1_MB04_DATA3, val)
+#define bfin_read_CAN1_MB04_LENGTH()		bfin_read16(CAN1_MB04_LENGTH)
+#define bfin_write_CAN1_MB04_LENGTH(val)	bfin_write16(CAN1_MB04_LENGTH, val)
+#define bfin_read_CAN1_MB04_TIMESTAMP()		bfin_read16(CAN1_MB04_TIMESTAMP)
+#define bfin_write_CAN1_MB04_TIMESTAMP(val)	bfin_write16(CAN1_MB04_TIMESTAMP, val)
+#define bfin_read_CAN1_MB04_ID0()		bfin_read16(CAN1_MB04_ID0)
+#define bfin_write_CAN1_MB04_ID0(val)		bfin_write16(CAN1_MB04_ID0, val)
+#define bfin_read_CAN1_MB04_ID1()		bfin_read16(CAN1_MB04_ID1)
+#define bfin_write_CAN1_MB04_ID1(val)		bfin_write16(CAN1_MB04_ID1, val)
+#define bfin_read_CAN1_MB05_DATA0()		bfin_read16(CAN1_MB05_DATA0)
+#define bfin_write_CAN1_MB05_DATA0(val)		bfin_write16(CAN1_MB05_DATA0, val)
+#define bfin_read_CAN1_MB05_DATA1()		bfin_read16(CAN1_MB05_DATA1)
+#define bfin_write_CAN1_MB05_DATA1(val)		bfin_write16(CAN1_MB05_DATA1, val)
+#define bfin_read_CAN1_MB05_DATA2()		bfin_read16(CAN1_MB05_DATA2)
+#define bfin_write_CAN1_MB05_DATA2(val)		bfin_write16(CAN1_MB05_DATA2, val)
+#define bfin_read_CAN1_MB05_DATA3()		bfin_read16(CAN1_MB05_DATA3)
+#define bfin_write_CAN1_MB05_DATA3(val)		bfin_write16(CAN1_MB05_DATA3, val)
+#define bfin_read_CAN1_MB05_LENGTH()		bfin_read16(CAN1_MB05_LENGTH)
+#define bfin_write_CAN1_MB05_LENGTH(val)	bfin_write16(CAN1_MB05_LENGTH, val)
+#define bfin_read_CAN1_MB05_TIMESTAMP()		bfin_read16(CAN1_MB05_TIMESTAMP)
+#define bfin_write_CAN1_MB05_TIMESTAMP(val)	bfin_write16(CAN1_MB05_TIMESTAMP, val)
+#define bfin_read_CAN1_MB05_ID0()		bfin_read16(CAN1_MB05_ID0)
+#define bfin_write_CAN1_MB05_ID0(val)		bfin_write16(CAN1_MB05_ID0, val)
+#define bfin_read_CAN1_MB05_ID1()		bfin_read16(CAN1_MB05_ID1)
+#define bfin_write_CAN1_MB05_ID1(val)		bfin_write16(CAN1_MB05_ID1, val)
+#define bfin_read_CAN1_MB06_DATA0()		bfin_read16(CAN1_MB06_DATA0)
+#define bfin_write_CAN1_MB06_DATA0(val)		bfin_write16(CAN1_MB06_DATA0, val)
+#define bfin_read_CAN1_MB06_DATA1()		bfin_read16(CAN1_MB06_DATA1)
+#define bfin_write_CAN1_MB06_DATA1(val)		bfin_write16(CAN1_MB06_DATA1, val)
+#define bfin_read_CAN1_MB06_DATA2()		bfin_read16(CAN1_MB06_DATA2)
+#define bfin_write_CAN1_MB06_DATA2(val)		bfin_write16(CAN1_MB06_DATA2, val)
+#define bfin_read_CAN1_MB06_DATA3()		bfin_read16(CAN1_MB06_DATA3)
+#define bfin_write_CAN1_MB06_DATA3(val)		bfin_write16(CAN1_MB06_DATA3, val)
+#define bfin_read_CAN1_MB06_LENGTH()		bfin_read16(CAN1_MB06_LENGTH)
+#define bfin_write_CAN1_MB06_LENGTH(val)	bfin_write16(CAN1_MB06_LENGTH, val)
+#define bfin_read_CAN1_MB06_TIMESTAMP()		bfin_read16(CAN1_MB06_TIMESTAMP)
+#define bfin_write_CAN1_MB06_TIMESTAMP(val)	bfin_write16(CAN1_MB06_TIMESTAMP, val)
+#define bfin_read_CAN1_MB06_ID0()		bfin_read16(CAN1_MB06_ID0)
+#define bfin_write_CAN1_MB06_ID0(val)		bfin_write16(CAN1_MB06_ID0, val)
+#define bfin_read_CAN1_MB06_ID1()		bfin_read16(CAN1_MB06_ID1)
+#define bfin_write_CAN1_MB06_ID1(val)		bfin_write16(CAN1_MB06_ID1, val)
+#define bfin_read_CAN1_MB07_DATA0()		bfin_read16(CAN1_MB07_DATA0)
+#define bfin_write_CAN1_MB07_DATA0(val)		bfin_write16(CAN1_MB07_DATA0, val)
+#define bfin_read_CAN1_MB07_DATA1()		bfin_read16(CAN1_MB07_DATA1)
+#define bfin_write_CAN1_MB07_DATA1(val)		bfin_write16(CAN1_MB07_DATA1, val)
+#define bfin_read_CAN1_MB07_DATA2()		bfin_read16(CAN1_MB07_DATA2)
+#define bfin_write_CAN1_MB07_DATA2(val)		bfin_write16(CAN1_MB07_DATA2, val)
+#define bfin_read_CAN1_MB07_DATA3()		bfin_read16(CAN1_MB07_DATA3)
+#define bfin_write_CAN1_MB07_DATA3(val)		bfin_write16(CAN1_MB07_DATA3, val)
+#define bfin_read_CAN1_MB07_LENGTH()		bfin_read16(CAN1_MB07_LENGTH)
+#define bfin_write_CAN1_MB07_LENGTH(val)	bfin_write16(CAN1_MB07_LENGTH, val)
+#define bfin_read_CAN1_MB07_TIMESTAMP()		bfin_read16(CAN1_MB07_TIMESTAMP)
+#define bfin_write_CAN1_MB07_TIMESTAMP(val)	bfin_write16(CAN1_MB07_TIMESTAMP, val)
+#define bfin_read_CAN1_MB07_ID0()		bfin_read16(CAN1_MB07_ID0)
+#define bfin_write_CAN1_MB07_ID0(val)		bfin_write16(CAN1_MB07_ID0, val)
+#define bfin_read_CAN1_MB07_ID1()		bfin_read16(CAN1_MB07_ID1)
+#define bfin_write_CAN1_MB07_ID1(val)		bfin_write16(CAN1_MB07_ID1, val)
+#define bfin_read_CAN1_MB08_DATA0()		bfin_read16(CAN1_MB08_DATA0)
+#define bfin_write_CAN1_MB08_DATA0(val)		bfin_write16(CAN1_MB08_DATA0, val)
+#define bfin_read_CAN1_MB08_DATA1()		bfin_read16(CAN1_MB08_DATA1)
+#define bfin_write_CAN1_MB08_DATA1(val)		bfin_write16(CAN1_MB08_DATA1, val)
+#define bfin_read_CAN1_MB08_DATA2()		bfin_read16(CAN1_MB08_DATA2)
+#define bfin_write_CAN1_MB08_DATA2(val)		bfin_write16(CAN1_MB08_DATA2, val)
+#define bfin_read_CAN1_MB08_DATA3()		bfin_read16(CAN1_MB08_DATA3)
+#define bfin_write_CAN1_MB08_DATA3(val)		bfin_write16(CAN1_MB08_DATA3, val)
+#define bfin_read_CAN1_MB08_LENGTH()		bfin_read16(CAN1_MB08_LENGTH)
+#define bfin_write_CAN1_MB08_LENGTH(val)	bfin_write16(CAN1_MB08_LENGTH, val)
+#define bfin_read_CAN1_MB08_TIMESTAMP()		bfin_read16(CAN1_MB08_TIMESTAMP)
+#define bfin_write_CAN1_MB08_TIMESTAMP(val)	bfin_write16(CAN1_MB08_TIMESTAMP, val)
+#define bfin_read_CAN1_MB08_ID0()		bfin_read16(CAN1_MB08_ID0)
+#define bfin_write_CAN1_MB08_ID0(val)		bfin_write16(CAN1_MB08_ID0, val)
+#define bfin_read_CAN1_MB08_ID1()		bfin_read16(CAN1_MB08_ID1)
+#define bfin_write_CAN1_MB08_ID1(val)		bfin_write16(CAN1_MB08_ID1, val)
+#define bfin_read_CAN1_MB09_DATA0()		bfin_read16(CAN1_MB09_DATA0)
+#define bfin_write_CAN1_MB09_DATA0(val)		bfin_write16(CAN1_MB09_DATA0, val)
+#define bfin_read_CAN1_MB09_DATA1()		bfin_read16(CAN1_MB09_DATA1)
+#define bfin_write_CAN1_MB09_DATA1(val)		bfin_write16(CAN1_MB09_DATA1, val)
+#define bfin_read_CAN1_MB09_DATA2()		bfin_read16(CAN1_MB09_DATA2)
+#define bfin_write_CAN1_MB09_DATA2(val)		bfin_write16(CAN1_MB09_DATA2, val)
+#define bfin_read_CAN1_MB09_DATA3()		bfin_read16(CAN1_MB09_DATA3)
+#define bfin_write_CAN1_MB09_DATA3(val)		bfin_write16(CAN1_MB09_DATA3, val)
+#define bfin_read_CAN1_MB09_LENGTH()		bfin_read16(CAN1_MB09_LENGTH)
+#define bfin_write_CAN1_MB09_LENGTH(val)	bfin_write16(CAN1_MB09_LENGTH, val)
+#define bfin_read_CAN1_MB09_TIMESTAMP()		bfin_read16(CAN1_MB09_TIMESTAMP)
+#define bfin_write_CAN1_MB09_TIMESTAMP(val)	bfin_write16(CAN1_MB09_TIMESTAMP, val)
+#define bfin_read_CAN1_MB09_ID0()		bfin_read16(CAN1_MB09_ID0)
+#define bfin_write_CAN1_MB09_ID0(val)		bfin_write16(CAN1_MB09_ID0, val)
+#define bfin_read_CAN1_MB09_ID1()		bfin_read16(CAN1_MB09_ID1)
+#define bfin_write_CAN1_MB09_ID1(val)		bfin_write16(CAN1_MB09_ID1, val)
+#define bfin_read_CAN1_MB10_DATA0()		bfin_read16(CAN1_MB10_DATA0)
+#define bfin_write_CAN1_MB10_DATA0(val)		bfin_write16(CAN1_MB10_DATA0, val)
+#define bfin_read_CAN1_MB10_DATA1()		bfin_read16(CAN1_MB10_DATA1)
+#define bfin_write_CAN1_MB10_DATA1(val)		bfin_write16(CAN1_MB10_DATA1, val)
+#define bfin_read_CAN1_MB10_DATA2()		bfin_read16(CAN1_MB10_DATA2)
+#define bfin_write_CAN1_MB10_DATA2(val)		bfin_write16(CAN1_MB10_DATA2, val)
+#define bfin_read_CAN1_MB10_DATA3()		bfin_read16(CAN1_MB10_DATA3)
+#define bfin_write_CAN1_MB10_DATA3(val)		bfin_write16(CAN1_MB10_DATA3, val)
+#define bfin_read_CAN1_MB10_LENGTH()		bfin_read16(CAN1_MB10_LENGTH)
+#define bfin_write_CAN1_MB10_LENGTH(val)	bfin_write16(CAN1_MB10_LENGTH, val)
+#define bfin_read_CAN1_MB10_TIMESTAMP()		bfin_read16(CAN1_MB10_TIMESTAMP)
+#define bfin_write_CAN1_MB10_TIMESTAMP(val)	bfin_write16(CAN1_MB10_TIMESTAMP, val)
+#define bfin_read_CAN1_MB10_ID0()		bfin_read16(CAN1_MB10_ID0)
+#define bfin_write_CAN1_MB10_ID0(val)		bfin_write16(CAN1_MB10_ID0, val)
+#define bfin_read_CAN1_MB10_ID1()		bfin_read16(CAN1_MB10_ID1)
+#define bfin_write_CAN1_MB10_ID1(val)		bfin_write16(CAN1_MB10_ID1, val)
+#define bfin_read_CAN1_MB11_DATA0()		bfin_read16(CAN1_MB11_DATA0)
+#define bfin_write_CAN1_MB11_DATA0(val)		bfin_write16(CAN1_MB11_DATA0, val)
+#define bfin_read_CAN1_MB11_DATA1()		bfin_read16(CAN1_MB11_DATA1)
+#define bfin_write_CAN1_MB11_DATA1(val)		bfin_write16(CAN1_MB11_DATA1, val)
+#define bfin_read_CAN1_MB11_DATA2()		bfin_read16(CAN1_MB11_DATA2)
+#define bfin_write_CAN1_MB11_DATA2(val)		bfin_write16(CAN1_MB11_DATA2, val)
+#define bfin_read_CAN1_MB11_DATA3()		bfin_read16(CAN1_MB11_DATA3)
+#define bfin_write_CAN1_MB11_DATA3(val)		bfin_write16(CAN1_MB11_DATA3, val)
+#define bfin_read_CAN1_MB11_LENGTH()		bfin_read16(CAN1_MB11_LENGTH)
+#define bfin_write_CAN1_MB11_LENGTH(val)	bfin_write16(CAN1_MB11_LENGTH, val)
+#define bfin_read_CAN1_MB11_TIMESTAMP()		bfin_read16(CAN1_MB11_TIMESTAMP)
+#define bfin_write_CAN1_MB11_TIMESTAMP(val)	bfin_write16(CAN1_MB11_TIMESTAMP, val)
+#define bfin_read_CAN1_MB11_ID0()		bfin_read16(CAN1_MB11_ID0)
+#define bfin_write_CAN1_MB11_ID0(val)		bfin_write16(CAN1_MB11_ID0, val)
+#define bfin_read_CAN1_MB11_ID1()		bfin_read16(CAN1_MB11_ID1)
+#define bfin_write_CAN1_MB11_ID1(val)		bfin_write16(CAN1_MB11_ID1, val)
+#define bfin_read_CAN1_MB12_DATA0()		bfin_read16(CAN1_MB12_DATA0)
+#define bfin_write_CAN1_MB12_DATA0(val)		bfin_write16(CAN1_MB12_DATA0, val)
+#define bfin_read_CAN1_MB12_DATA1()		bfin_read16(CAN1_MB12_DATA1)
+#define bfin_write_CAN1_MB12_DATA1(val)		bfin_write16(CAN1_MB12_DATA1, val)
+#define bfin_read_CAN1_MB12_DATA2()		bfin_read16(CAN1_MB12_DATA2)
+#define bfin_write_CAN1_MB12_DATA2(val)		bfin_write16(CAN1_MB12_DATA2, val)
+#define bfin_read_CAN1_MB12_DATA3()		bfin_read16(CAN1_MB12_DATA3)
+#define bfin_write_CAN1_MB12_DATA3(val)		bfin_write16(CAN1_MB12_DATA3, val)
+#define bfin_read_CAN1_MB12_LENGTH()		bfin_read16(CAN1_MB12_LENGTH)
+#define bfin_write_CAN1_MB12_LENGTH(val)	bfin_write16(CAN1_MB12_LENGTH, val)
+#define bfin_read_CAN1_MB12_TIMESTAMP()		bfin_read16(CAN1_MB12_TIMESTAMP)
+#define bfin_write_CAN1_MB12_TIMESTAMP(val)	bfin_write16(CAN1_MB12_TIMESTAMP, val)
+#define bfin_read_CAN1_MB12_ID0()		bfin_read16(CAN1_MB12_ID0)
+#define bfin_write_CAN1_MB12_ID0(val)		bfin_write16(CAN1_MB12_ID0, val)
+#define bfin_read_CAN1_MB12_ID1()		bfin_read16(CAN1_MB12_ID1)
+#define bfin_write_CAN1_MB12_ID1(val)		bfin_write16(CAN1_MB12_ID1, val)
+#define bfin_read_CAN1_MB13_DATA0()		bfin_read16(CAN1_MB13_DATA0)
+#define bfin_write_CAN1_MB13_DATA0(val)		bfin_write16(CAN1_MB13_DATA0, val)
+#define bfin_read_CAN1_MB13_DATA1()		bfin_read16(CAN1_MB13_DATA1)
+#define bfin_write_CAN1_MB13_DATA1(val)		bfin_write16(CAN1_MB13_DATA1, val)
+#define bfin_read_CAN1_MB13_DATA2()		bfin_read16(CAN1_MB13_DATA2)
+#define bfin_write_CAN1_MB13_DATA2(val)		bfin_write16(CAN1_MB13_DATA2, val)
+#define bfin_read_CAN1_MB13_DATA3()		bfin_read16(CAN1_MB13_DATA3)
+#define bfin_write_CAN1_MB13_DATA3(val)		bfin_write16(CAN1_MB13_DATA3, val)
+#define bfin_read_CAN1_MB13_LENGTH()		bfin_read16(CAN1_MB13_LENGTH)
+#define bfin_write_CAN1_MB13_LENGTH(val)	bfin_write16(CAN1_MB13_LENGTH, val)
+#define bfin_read_CAN1_MB13_TIMESTAMP()		bfin_read16(CAN1_MB13_TIMESTAMP)
+#define bfin_write_CAN1_MB13_TIMESTAMP(val)	bfin_write16(CAN1_MB13_TIMESTAMP, val)
+#define bfin_read_CAN1_MB13_ID0()		bfin_read16(CAN1_MB13_ID0)
+#define bfin_write_CAN1_MB13_ID0(val)		bfin_write16(CAN1_MB13_ID0, val)
+#define bfin_read_CAN1_MB13_ID1()		bfin_read16(CAN1_MB13_ID1)
+#define bfin_write_CAN1_MB13_ID1(val)		bfin_write16(CAN1_MB13_ID1, val)
+#define bfin_read_CAN1_MB14_DATA0()		bfin_read16(CAN1_MB14_DATA0)
+#define bfin_write_CAN1_MB14_DATA0(val)		bfin_write16(CAN1_MB14_DATA0, val)
+#define bfin_read_CAN1_MB14_DATA1()		bfin_read16(CAN1_MB14_DATA1)
+#define bfin_write_CAN1_MB14_DATA1(val)		bfin_write16(CAN1_MB14_DATA1, val)
+#define bfin_read_CAN1_MB14_DATA2()		bfin_read16(CAN1_MB14_DATA2)
+#define bfin_write_CAN1_MB14_DATA2(val)		bfin_write16(CAN1_MB14_DATA2, val)
+#define bfin_read_CAN1_MB14_DATA3()		bfin_read16(CAN1_MB14_DATA3)
+#define bfin_write_CAN1_MB14_DATA3(val)		bfin_write16(CAN1_MB14_DATA3, val)
+#define bfin_read_CAN1_MB14_LENGTH()		bfin_read16(CAN1_MB14_LENGTH)
+#define bfin_write_CAN1_MB14_LENGTH(val)	bfin_write16(CAN1_MB14_LENGTH, val)
+#define bfin_read_CAN1_MB14_TIMESTAMP()		bfin_read16(CAN1_MB14_TIMESTAMP)
+#define bfin_write_CAN1_MB14_TIMESTAMP(val)	bfin_write16(CAN1_MB14_TIMESTAMP, val)
+#define bfin_read_CAN1_MB14_ID0()		bfin_read16(CAN1_MB14_ID0)
+#define bfin_write_CAN1_MB14_ID0(val)		bfin_write16(CAN1_MB14_ID0, val)
+#define bfin_read_CAN1_MB14_ID1()		bfin_read16(CAN1_MB14_ID1)
+#define bfin_write_CAN1_MB14_ID1(val)		bfin_write16(CAN1_MB14_ID1, val)
+#define bfin_read_CAN1_MB15_DATA0()		bfin_read16(CAN1_MB15_DATA0)
+#define bfin_write_CAN1_MB15_DATA0(val)		bfin_write16(CAN1_MB15_DATA0, val)
+#define bfin_read_CAN1_MB15_DATA1()		bfin_read16(CAN1_MB15_DATA1)
+#define bfin_write_CAN1_MB15_DATA1(val)		bfin_write16(CAN1_MB15_DATA1, val)
+#define bfin_read_CAN1_MB15_DATA2()		bfin_read16(CAN1_MB15_DATA2)
+#define bfin_write_CAN1_MB15_DATA2(val)		bfin_write16(CAN1_MB15_DATA2, val)
+#define bfin_read_CAN1_MB15_DATA3()		bfin_read16(CAN1_MB15_DATA3)
+#define bfin_write_CAN1_MB15_DATA3(val)		bfin_write16(CAN1_MB15_DATA3, val)
+#define bfin_read_CAN1_MB15_LENGTH()		bfin_read16(CAN1_MB15_LENGTH)
+#define bfin_write_CAN1_MB15_LENGTH(val)	bfin_write16(CAN1_MB15_LENGTH, val)
+#define bfin_read_CAN1_MB15_TIMESTAMP()		bfin_read16(CAN1_MB15_TIMESTAMP)
+#define bfin_write_CAN1_MB15_TIMESTAMP(val)	bfin_write16(CAN1_MB15_TIMESTAMP, val)
+#define bfin_read_CAN1_MB15_ID0()		bfin_read16(CAN1_MB15_ID0)
+#define bfin_write_CAN1_MB15_ID0(val)		bfin_write16(CAN1_MB15_ID0, val)
+#define bfin_read_CAN1_MB15_ID1()		bfin_read16(CAN1_MB15_ID1)
+#define bfin_write_CAN1_MB15_ID1(val)		bfin_write16(CAN1_MB15_ID1, val)
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define bfin_read_CAN1_MB16_DATA0()		bfin_read16(CAN1_MB16_DATA0)
+#define bfin_write_CAN1_MB16_DATA0(val)		bfin_write16(CAN1_MB16_DATA0, val)
+#define bfin_read_CAN1_MB16_DATA1()		bfin_read16(CAN1_MB16_DATA1)
+#define bfin_write_CAN1_MB16_DATA1(val)		bfin_write16(CAN1_MB16_DATA1, val)
+#define bfin_read_CAN1_MB16_DATA2()		bfin_read16(CAN1_MB16_DATA2)
+#define bfin_write_CAN1_MB16_DATA2(val)		bfin_write16(CAN1_MB16_DATA2, val)
+#define bfin_read_CAN1_MB16_DATA3()		bfin_read16(CAN1_MB16_DATA3)
+#define bfin_write_CAN1_MB16_DATA3(val)		bfin_write16(CAN1_MB16_DATA3, val)
+#define bfin_read_CAN1_MB16_LENGTH()		bfin_read16(CAN1_MB16_LENGTH)
+#define bfin_write_CAN1_MB16_LENGTH(val)	bfin_write16(CAN1_MB16_LENGTH, val)
+#define bfin_read_CAN1_MB16_TIMESTAMP()		bfin_read16(CAN1_MB16_TIMESTAMP)
+#define bfin_write_CAN1_MB16_TIMESTAMP(val)	bfin_write16(CAN1_MB16_TIMESTAMP, val)
+#define bfin_read_CAN1_MB16_ID0()		bfin_read16(CAN1_MB16_ID0)
+#define bfin_write_CAN1_MB16_ID0(val)		bfin_write16(CAN1_MB16_ID0, val)
+#define bfin_read_CAN1_MB16_ID1()		bfin_read16(CAN1_MB16_ID1)
+#define bfin_write_CAN1_MB16_ID1(val)		bfin_write16(CAN1_MB16_ID1, val)
+#define bfin_read_CAN1_MB17_DATA0()		bfin_read16(CAN1_MB17_DATA0)
+#define bfin_write_CAN1_MB17_DATA0(val)		bfin_write16(CAN1_MB17_DATA0, val)
+#define bfin_read_CAN1_MB17_DATA1()		bfin_read16(CAN1_MB17_DATA1)
+#define bfin_write_CAN1_MB17_DATA1(val)		bfin_write16(CAN1_MB17_DATA1, val)
+#define bfin_read_CAN1_MB17_DATA2()		bfin_read16(CAN1_MB17_DATA2)
+#define bfin_write_CAN1_MB17_DATA2(val)		bfin_write16(CAN1_MB17_DATA2, val)
+#define bfin_read_CAN1_MB17_DATA3()		bfin_read16(CAN1_MB17_DATA3)
+#define bfin_write_CAN1_MB17_DATA3(val)		bfin_write16(CAN1_MB17_DATA3, val)
+#define bfin_read_CAN1_MB17_LENGTH()		bfin_read16(CAN1_MB17_LENGTH)
+#define bfin_write_CAN1_MB17_LENGTH(val)	bfin_write16(CAN1_MB17_LENGTH, val)
+#define bfin_read_CAN1_MB17_TIMESTAMP()		bfin_read16(CAN1_MB17_TIMESTAMP)
+#define bfin_write_CAN1_MB17_TIMESTAMP(val)	bfin_write16(CAN1_MB17_TIMESTAMP, val)
+#define bfin_read_CAN1_MB17_ID0()		bfin_read16(CAN1_MB17_ID0)
+#define bfin_write_CAN1_MB17_ID0(val)		bfin_write16(CAN1_MB17_ID0, val)
+#define bfin_read_CAN1_MB17_ID1()		bfin_read16(CAN1_MB17_ID1)
+#define bfin_write_CAN1_MB17_ID1(val)		bfin_write16(CAN1_MB17_ID1, val)
+#define bfin_read_CAN1_MB18_DATA0()		bfin_read16(CAN1_MB18_DATA0)
+#define bfin_write_CAN1_MB18_DATA0(val)		bfin_write16(CAN1_MB18_DATA0, val)
+#define bfin_read_CAN1_MB18_DATA1()		bfin_read16(CAN1_MB18_DATA1)
+#define bfin_write_CAN1_MB18_DATA1(val)		bfin_write16(CAN1_MB18_DATA1, val)
+#define bfin_read_CAN1_MB18_DATA2()		bfin_read16(CAN1_MB18_DATA2)
+#define bfin_write_CAN1_MB18_DATA2(val)		bfin_write16(CAN1_MB18_DATA2, val)
+#define bfin_read_CAN1_MB18_DATA3()		bfin_read16(CAN1_MB18_DATA3)
+#define bfin_write_CAN1_MB18_DATA3(val)		bfin_write16(CAN1_MB18_DATA3, val)
+#define bfin_read_CAN1_MB18_LENGTH()		bfin_read16(CAN1_MB18_LENGTH)
+#define bfin_write_CAN1_MB18_LENGTH(val)	bfin_write16(CAN1_MB18_LENGTH, val)
+#define bfin_read_CAN1_MB18_TIMESTAMP()		bfin_read16(CAN1_MB18_TIMESTAMP)
+#define bfin_write_CAN1_MB18_TIMESTAMP(val)	bfin_write16(CAN1_MB18_TIMESTAMP, val)
+#define bfin_read_CAN1_MB18_ID0()		bfin_read16(CAN1_MB18_ID0)
+#define bfin_write_CAN1_MB18_ID0(val)		bfin_write16(CAN1_MB18_ID0, val)
+#define bfin_read_CAN1_MB18_ID1()		bfin_read16(CAN1_MB18_ID1)
+#define bfin_write_CAN1_MB18_ID1(val)		bfin_write16(CAN1_MB18_ID1, val)
+#define bfin_read_CAN1_MB19_DATA0()		bfin_read16(CAN1_MB19_DATA0)
+#define bfin_write_CAN1_MB19_DATA0(val)		bfin_write16(CAN1_MB19_DATA0, val)
+#define bfin_read_CAN1_MB19_DATA1()		bfin_read16(CAN1_MB19_DATA1)
+#define bfin_write_CAN1_MB19_DATA1(val)		bfin_write16(CAN1_MB19_DATA1, val)
+#define bfin_read_CAN1_MB19_DATA2()		bfin_read16(CAN1_MB19_DATA2)
+#define bfin_write_CAN1_MB19_DATA2(val)		bfin_write16(CAN1_MB19_DATA2, val)
+#define bfin_read_CAN1_MB19_DATA3()		bfin_read16(CAN1_MB19_DATA3)
+#define bfin_write_CAN1_MB19_DATA3(val)		bfin_write16(CAN1_MB19_DATA3, val)
+#define bfin_read_CAN1_MB19_LENGTH()		bfin_read16(CAN1_MB19_LENGTH)
+#define bfin_write_CAN1_MB19_LENGTH(val)	bfin_write16(CAN1_MB19_LENGTH, val)
+#define bfin_read_CAN1_MB19_TIMESTAMP()		bfin_read16(CAN1_MB19_TIMESTAMP)
+#define bfin_write_CAN1_MB19_TIMESTAMP(val)	bfin_write16(CAN1_MB19_TIMESTAMP, val)
+#define bfin_read_CAN1_MB19_ID0()		bfin_read16(CAN1_MB19_ID0)
+#define bfin_write_CAN1_MB19_ID0(val)		bfin_write16(CAN1_MB19_ID0, val)
+#define bfin_read_CAN1_MB19_ID1()		bfin_read16(CAN1_MB19_ID1)
+#define bfin_write_CAN1_MB19_ID1(val)		bfin_write16(CAN1_MB19_ID1, val)
+#define bfin_read_CAN1_MB20_DATA0()		bfin_read16(CAN1_MB20_DATA0)
+#define bfin_write_CAN1_MB20_DATA0(val)		bfin_write16(CAN1_MB20_DATA0, val)
+#define bfin_read_CAN1_MB20_DATA1()		bfin_read16(CAN1_MB20_DATA1)
+#define bfin_write_CAN1_MB20_DATA1(val)		bfin_write16(CAN1_MB20_DATA1, val)
+#define bfin_read_CAN1_MB20_DATA2()		bfin_read16(CAN1_MB20_DATA2)
+#define bfin_write_CAN1_MB20_DATA2(val)		bfin_write16(CAN1_MB20_DATA2, val)
+#define bfin_read_CAN1_MB20_DATA3()		bfin_read16(CAN1_MB20_DATA3)
+#define bfin_write_CAN1_MB20_DATA3(val)		bfin_write16(CAN1_MB20_DATA3, val)
+#define bfin_read_CAN1_MB20_LENGTH()		bfin_read16(CAN1_MB20_LENGTH)
+#define bfin_write_CAN1_MB20_LENGTH(val)	bfin_write16(CAN1_MB20_LENGTH, val)
+#define bfin_read_CAN1_MB20_TIMESTAMP()		bfin_read16(CAN1_MB20_TIMESTAMP)
+#define bfin_write_CAN1_MB20_TIMESTAMP(val)	bfin_write16(CAN1_MB20_TIMESTAMP, val)
+#define bfin_read_CAN1_MB20_ID0()		bfin_read16(CAN1_MB20_ID0)
+#define bfin_write_CAN1_MB20_ID0(val)		bfin_write16(CAN1_MB20_ID0, val)
+#define bfin_read_CAN1_MB20_ID1()		bfin_read16(CAN1_MB20_ID1)
+#define bfin_write_CAN1_MB20_ID1(val)		bfin_write16(CAN1_MB20_ID1, val)
+#define bfin_read_CAN1_MB21_DATA0()		bfin_read16(CAN1_MB21_DATA0)
+#define bfin_write_CAN1_MB21_DATA0(val)		bfin_write16(CAN1_MB21_DATA0, val)
+#define bfin_read_CAN1_MB21_DATA1()		bfin_read16(CAN1_MB21_DATA1)
+#define bfin_write_CAN1_MB21_DATA1(val)		bfin_write16(CAN1_MB21_DATA1, val)
+#define bfin_read_CAN1_MB21_DATA2()		bfin_read16(CAN1_MB21_DATA2)
+#define bfin_write_CAN1_MB21_DATA2(val)		bfin_write16(CAN1_MB21_DATA2, val)
+#define bfin_read_CAN1_MB21_DATA3()		bfin_read16(CAN1_MB21_DATA3)
+#define bfin_write_CAN1_MB21_DATA3(val)		bfin_write16(CAN1_MB21_DATA3, val)
+#define bfin_read_CAN1_MB21_LENGTH()		bfin_read16(CAN1_MB21_LENGTH)
+#define bfin_write_CAN1_MB21_LENGTH(val)	bfin_write16(CAN1_MB21_LENGTH, val)
+#define bfin_read_CAN1_MB21_TIMESTAMP()		bfin_read16(CAN1_MB21_TIMESTAMP)
+#define bfin_write_CAN1_MB21_TIMESTAMP(val)	bfin_write16(CAN1_MB21_TIMESTAMP, val)
+#define bfin_read_CAN1_MB21_ID0()		bfin_read16(CAN1_MB21_ID0)
+#define bfin_write_CAN1_MB21_ID0(val)		bfin_write16(CAN1_MB21_ID0, val)
+#define bfin_read_CAN1_MB21_ID1()		bfin_read16(CAN1_MB21_ID1)
+#define bfin_write_CAN1_MB21_ID1(val)		bfin_write16(CAN1_MB21_ID1, val)
+#define bfin_read_CAN1_MB22_DATA0()		bfin_read16(CAN1_MB22_DATA0)
+#define bfin_write_CAN1_MB22_DATA0(val)		bfin_write16(CAN1_MB22_DATA0, val)
+#define bfin_read_CAN1_MB22_DATA1()		bfin_read16(CAN1_MB22_DATA1)
+#define bfin_write_CAN1_MB22_DATA1(val)		bfin_write16(CAN1_MB22_DATA1, val)
+#define bfin_read_CAN1_MB22_DATA2()		bfin_read16(CAN1_MB22_DATA2)
+#define bfin_write_CAN1_MB22_DATA2(val)		bfin_write16(CAN1_MB22_DATA2, val)
+#define bfin_read_CAN1_MB22_DATA3()		bfin_read16(CAN1_MB22_DATA3)
+#define bfin_write_CAN1_MB22_DATA3(val)		bfin_write16(CAN1_MB22_DATA3, val)
+#define bfin_read_CAN1_MB22_LENGTH()		bfin_read16(CAN1_MB22_LENGTH)
+#define bfin_write_CAN1_MB22_LENGTH(val)	bfin_write16(CAN1_MB22_LENGTH, val)
+#define bfin_read_CAN1_MB22_TIMESTAMP()		bfin_read16(CAN1_MB22_TIMESTAMP)
+#define bfin_write_CAN1_MB22_TIMESTAMP(val)	bfin_write16(CAN1_MB22_TIMESTAMP, val)
+#define bfin_read_CAN1_MB22_ID0()		bfin_read16(CAN1_MB22_ID0)
+#define bfin_write_CAN1_MB22_ID0(val)		bfin_write16(CAN1_MB22_ID0, val)
+#define bfin_read_CAN1_MB22_ID1()		bfin_read16(CAN1_MB22_ID1)
+#define bfin_write_CAN1_MB22_ID1(val)		bfin_write16(CAN1_MB22_ID1, val)
+#define bfin_read_CAN1_MB23_DATA0()		bfin_read16(CAN1_MB23_DATA0)
+#define bfin_write_CAN1_MB23_DATA0(val)		bfin_write16(CAN1_MB23_DATA0, val)
+#define bfin_read_CAN1_MB23_DATA1()		bfin_read16(CAN1_MB23_DATA1)
+#define bfin_write_CAN1_MB23_DATA1(val)		bfin_write16(CAN1_MB23_DATA1, val)
+#define bfin_read_CAN1_MB23_DATA2()		bfin_read16(CAN1_MB23_DATA2)
+#define bfin_write_CAN1_MB23_DATA2(val)		bfin_write16(CAN1_MB23_DATA2, val)
+#define bfin_read_CAN1_MB23_DATA3()		bfin_read16(CAN1_MB23_DATA3)
+#define bfin_write_CAN1_MB23_DATA3(val)		bfin_write16(CAN1_MB23_DATA3, val)
+#define bfin_read_CAN1_MB23_LENGTH()		bfin_read16(CAN1_MB23_LENGTH)
+#define bfin_write_CAN1_MB23_LENGTH(val)	bfin_write16(CAN1_MB23_LENGTH, val)
+#define bfin_read_CAN1_MB23_TIMESTAMP()		bfin_read16(CAN1_MB23_TIMESTAMP)
+#define bfin_write_CAN1_MB23_TIMESTAMP(val)	bfin_write16(CAN1_MB23_TIMESTAMP, val)
+#define bfin_read_CAN1_MB23_ID0()		bfin_read16(CAN1_MB23_ID0)
+#define bfin_write_CAN1_MB23_ID0(val)		bfin_write16(CAN1_MB23_ID0, val)
+#define bfin_read_CAN1_MB23_ID1()		bfin_read16(CAN1_MB23_ID1)
+#define bfin_write_CAN1_MB23_ID1(val)		bfin_write16(CAN1_MB23_ID1, val)
+#define bfin_read_CAN1_MB24_DATA0()		bfin_read16(CAN1_MB24_DATA0)
+#define bfin_write_CAN1_MB24_DATA0(val)		bfin_write16(CAN1_MB24_DATA0, val)
+#define bfin_read_CAN1_MB24_DATA1()		bfin_read16(CAN1_MB24_DATA1)
+#define bfin_write_CAN1_MB24_DATA1(val)		bfin_write16(CAN1_MB24_DATA1, val)
+#define bfin_read_CAN1_MB24_DATA2()		bfin_read16(CAN1_MB24_DATA2)
+#define bfin_write_CAN1_MB24_DATA2(val)		bfin_write16(CAN1_MB24_DATA2, val)
+#define bfin_read_CAN1_MB24_DATA3()		bfin_read16(CAN1_MB24_DATA3)
+#define bfin_write_CAN1_MB24_DATA3(val)		bfin_write16(CAN1_MB24_DATA3, val)
+#define bfin_read_CAN1_MB24_LENGTH()		bfin_read16(CAN1_MB24_LENGTH)
+#define bfin_write_CAN1_MB24_LENGTH(val)	bfin_write16(CAN1_MB24_LENGTH, val)
+#define bfin_read_CAN1_MB24_TIMESTAMP()		bfin_read16(CAN1_MB24_TIMESTAMP)
+#define bfin_write_CAN1_MB24_TIMESTAMP(val)	bfin_write16(CAN1_MB24_TIMESTAMP, val)
+#define bfin_read_CAN1_MB24_ID0()		bfin_read16(CAN1_MB24_ID0)
+#define bfin_write_CAN1_MB24_ID0(val)		bfin_write16(CAN1_MB24_ID0, val)
+#define bfin_read_CAN1_MB24_ID1()		bfin_read16(CAN1_MB24_ID1)
+#define bfin_write_CAN1_MB24_ID1(val)		bfin_write16(CAN1_MB24_ID1, val)
+#define bfin_read_CAN1_MB25_DATA0()		bfin_read16(CAN1_MB25_DATA0)
+#define bfin_write_CAN1_MB25_DATA0(val)		bfin_write16(CAN1_MB25_DATA0, val)
+#define bfin_read_CAN1_MB25_DATA1()		bfin_read16(CAN1_MB25_DATA1)
+#define bfin_write_CAN1_MB25_DATA1(val)		bfin_write16(CAN1_MB25_DATA1, val)
+#define bfin_read_CAN1_MB25_DATA2()		bfin_read16(CAN1_MB25_DATA2)
+#define bfin_write_CAN1_MB25_DATA2(val)		bfin_write16(CAN1_MB25_DATA2, val)
+#define bfin_read_CAN1_MB25_DATA3()		bfin_read16(CAN1_MB25_DATA3)
+#define bfin_write_CAN1_MB25_DATA3(val)		bfin_write16(CAN1_MB25_DATA3, val)
+#define bfin_read_CAN1_MB25_LENGTH()		bfin_read16(CAN1_MB25_LENGTH)
+#define bfin_write_CAN1_MB25_LENGTH(val)	bfin_write16(CAN1_MB25_LENGTH, val)
+#define bfin_read_CAN1_MB25_TIMESTAMP()		bfin_read16(CAN1_MB25_TIMESTAMP)
+#define bfin_write_CAN1_MB25_TIMESTAMP(val)	bfin_write16(CAN1_MB25_TIMESTAMP, val)
+#define bfin_read_CAN1_MB25_ID0()		bfin_read16(CAN1_MB25_ID0)
+#define bfin_write_CAN1_MB25_ID0(val)		bfin_write16(CAN1_MB25_ID0, val)
+#define bfin_read_CAN1_MB25_ID1()		bfin_read16(CAN1_MB25_ID1)
+#define bfin_write_CAN1_MB25_ID1(val)		bfin_write16(CAN1_MB25_ID1, val)
+#define bfin_read_CAN1_MB26_DATA0()		bfin_read16(CAN1_MB26_DATA0)
+#define bfin_write_CAN1_MB26_DATA0(val)		bfin_write16(CAN1_MB26_DATA0, val)
+#define bfin_read_CAN1_MB26_DATA1()		bfin_read16(CAN1_MB26_DATA1)
+#define bfin_write_CAN1_MB26_DATA1(val)		bfin_write16(CAN1_MB26_DATA1, val)
+#define bfin_read_CAN1_MB26_DATA2()		bfin_read16(CAN1_MB26_DATA2)
+#define bfin_write_CAN1_MB26_DATA2(val)		bfin_write16(CAN1_MB26_DATA2, val)
+#define bfin_read_CAN1_MB26_DATA3()		bfin_read16(CAN1_MB26_DATA3)
+#define bfin_write_CAN1_MB26_DATA3(val)		bfin_write16(CAN1_MB26_DATA3, val)
+#define bfin_read_CAN1_MB26_LENGTH()		bfin_read16(CAN1_MB26_LENGTH)
+#define bfin_write_CAN1_MB26_LENGTH(val)	bfin_write16(CAN1_MB26_LENGTH, val)
+#define bfin_read_CAN1_MB26_TIMESTAMP()		bfin_read16(CAN1_MB26_TIMESTAMP)
+#define bfin_write_CAN1_MB26_TIMESTAMP(val)	bfin_write16(CAN1_MB26_TIMESTAMP, val)
+#define bfin_read_CAN1_MB26_ID0()		bfin_read16(CAN1_MB26_ID0)
+#define bfin_write_CAN1_MB26_ID0(val)		bfin_write16(CAN1_MB26_ID0, val)
+#define bfin_read_CAN1_MB26_ID1()		bfin_read16(CAN1_MB26_ID1)
+#define bfin_write_CAN1_MB26_ID1(val)		bfin_write16(CAN1_MB26_ID1, val)
+#define bfin_read_CAN1_MB27_DATA0()		bfin_read16(CAN1_MB27_DATA0)
+#define bfin_write_CAN1_MB27_DATA0(val)		bfin_write16(CAN1_MB27_DATA0, val)
+#define bfin_read_CAN1_MB27_DATA1()		bfin_read16(CAN1_MB27_DATA1)
+#define bfin_write_CAN1_MB27_DATA1(val)		bfin_write16(CAN1_MB27_DATA1, val)
+#define bfin_read_CAN1_MB27_DATA2()		bfin_read16(CAN1_MB27_DATA2)
+#define bfin_write_CAN1_MB27_DATA2(val)		bfin_write16(CAN1_MB27_DATA2, val)
+#define bfin_read_CAN1_MB27_DATA3()		bfin_read16(CAN1_MB27_DATA3)
+#define bfin_write_CAN1_MB27_DATA3(val)		bfin_write16(CAN1_MB27_DATA3, val)
+#define bfin_read_CAN1_MB27_LENGTH()		bfin_read16(CAN1_MB27_LENGTH)
+#define bfin_write_CAN1_MB27_LENGTH(val)	bfin_write16(CAN1_MB27_LENGTH, val)
+#define bfin_read_CAN1_MB27_TIMESTAMP()		bfin_read16(CAN1_MB27_TIMESTAMP)
+#define bfin_write_CAN1_MB27_TIMESTAMP(val)	bfin_write16(CAN1_MB27_TIMESTAMP, val)
+#define bfin_read_CAN1_MB27_ID0()		bfin_read16(CAN1_MB27_ID0)
+#define bfin_write_CAN1_MB27_ID0(val)		bfin_write16(CAN1_MB27_ID0, val)
+#define bfin_read_CAN1_MB27_ID1()		bfin_read16(CAN1_MB27_ID1)
+#define bfin_write_CAN1_MB27_ID1(val)		bfin_write16(CAN1_MB27_ID1, val)
+#define bfin_read_CAN1_MB28_DATA0()		bfin_read16(CAN1_MB28_DATA0)
+#define bfin_write_CAN1_MB28_DATA0(val)		bfin_write16(CAN1_MB28_DATA0, val)
+#define bfin_read_CAN1_MB28_DATA1()		bfin_read16(CAN1_MB28_DATA1)
+#define bfin_write_CAN1_MB28_DATA1(val)		bfin_write16(CAN1_MB28_DATA1, val)
+#define bfin_read_CAN1_MB28_DATA2()		bfin_read16(CAN1_MB28_DATA2)
+#define bfin_write_CAN1_MB28_DATA2(val)		bfin_write16(CAN1_MB28_DATA2, val)
+#define bfin_read_CAN1_MB28_DATA3()		bfin_read16(CAN1_MB28_DATA3)
+#define bfin_write_CAN1_MB28_DATA3(val)		bfin_write16(CAN1_MB28_DATA3, val)
+#define bfin_read_CAN1_MB28_LENGTH()		bfin_read16(CAN1_MB28_LENGTH)
+#define bfin_write_CAN1_MB28_LENGTH(val)	bfin_write16(CAN1_MB28_LENGTH, val)
+#define bfin_read_CAN1_MB28_TIMESTAMP()		bfin_read16(CAN1_MB28_TIMESTAMP)
+#define bfin_write_CAN1_MB28_TIMESTAMP(val)	bfin_write16(CAN1_MB28_TIMESTAMP, val)
+#define bfin_read_CAN1_MB28_ID0()		bfin_read16(CAN1_MB28_ID0)
+#define bfin_write_CAN1_MB28_ID0(val)		bfin_write16(CAN1_MB28_ID0, val)
+#define bfin_read_CAN1_MB28_ID1()		bfin_read16(CAN1_MB28_ID1)
+#define bfin_write_CAN1_MB28_ID1(val)		bfin_write16(CAN1_MB28_ID1, val)
+#define bfin_read_CAN1_MB29_DATA0()		bfin_read16(CAN1_MB29_DATA0)
+#define bfin_write_CAN1_MB29_DATA0(val)		bfin_write16(CAN1_MB29_DATA0, val)
+#define bfin_read_CAN1_MB29_DATA1()		bfin_read16(CAN1_MB29_DATA1)
+#define bfin_write_CAN1_MB29_DATA1(val)		bfin_write16(CAN1_MB29_DATA1, val)
+#define bfin_read_CAN1_MB29_DATA2()		bfin_read16(CAN1_MB29_DATA2)
+#define bfin_write_CAN1_MB29_DATA2(val)		bfin_write16(CAN1_MB29_DATA2, val)
+#define bfin_read_CAN1_MB29_DATA3()		bfin_read16(CAN1_MB29_DATA3)
+#define bfin_write_CAN1_MB29_DATA3(val)		bfin_write16(CAN1_MB29_DATA3, val)
+#define bfin_read_CAN1_MB29_LENGTH()		bfin_read16(CAN1_MB29_LENGTH)
+#define bfin_write_CAN1_MB29_LENGTH(val)	bfin_write16(CAN1_MB29_LENGTH, val)
+#define bfin_read_CAN1_MB29_TIMESTAMP()		bfin_read16(CAN1_MB29_TIMESTAMP)
+#define bfin_write_CAN1_MB29_TIMESTAMP(val)	bfin_write16(CAN1_MB29_TIMESTAMP, val)
+#define bfin_read_CAN1_MB29_ID0()		bfin_read16(CAN1_MB29_ID0)
+#define bfin_write_CAN1_MB29_ID0(val)		bfin_write16(CAN1_MB29_ID0, val)
+#define bfin_read_CAN1_MB29_ID1()		bfin_read16(CAN1_MB29_ID1)
+#define bfin_write_CAN1_MB29_ID1(val)		bfin_write16(CAN1_MB29_ID1, val)
+#define bfin_read_CAN1_MB30_DATA0()		bfin_read16(CAN1_MB30_DATA0)
+#define bfin_write_CAN1_MB30_DATA0(val)		bfin_write16(CAN1_MB30_DATA0, val)
+#define bfin_read_CAN1_MB30_DATA1()		bfin_read16(CAN1_MB30_DATA1)
+#define bfin_write_CAN1_MB30_DATA1(val)		bfin_write16(CAN1_MB30_DATA1, val)
+#define bfin_read_CAN1_MB30_DATA2()		bfin_read16(CAN1_MB30_DATA2)
+#define bfin_write_CAN1_MB30_DATA2(val)		bfin_write16(CAN1_MB30_DATA2, val)
+#define bfin_read_CAN1_MB30_DATA3()		bfin_read16(CAN1_MB30_DATA3)
+#define bfin_write_CAN1_MB30_DATA3(val)		bfin_write16(CAN1_MB30_DATA3, val)
+#define bfin_read_CAN1_MB30_LENGTH()		bfin_read16(CAN1_MB30_LENGTH)
+#define bfin_write_CAN1_MB30_LENGTH(val)	bfin_write16(CAN1_MB30_LENGTH, val)
+#define bfin_read_CAN1_MB30_TIMESTAMP()		bfin_read16(CAN1_MB30_TIMESTAMP)
+#define bfin_write_CAN1_MB30_TIMESTAMP(val)	bfin_write16(CAN1_MB30_TIMESTAMP, val)
+#define bfin_read_CAN1_MB30_ID0()		bfin_read16(CAN1_MB30_ID0)
+#define bfin_write_CAN1_MB30_ID0(val)		bfin_write16(CAN1_MB30_ID0, val)
+#define bfin_read_CAN1_MB30_ID1()		bfin_read16(CAN1_MB30_ID1)
+#define bfin_write_CAN1_MB30_ID1(val)		bfin_write16(CAN1_MB30_ID1, val)
+#define bfin_read_CAN1_MB31_DATA0()		bfin_read16(CAN1_MB31_DATA0)
+#define bfin_write_CAN1_MB31_DATA0(val)		bfin_write16(CAN1_MB31_DATA0, val)
+#define bfin_read_CAN1_MB31_DATA1()		bfin_read16(CAN1_MB31_DATA1)
+#define bfin_write_CAN1_MB31_DATA1(val)		bfin_write16(CAN1_MB31_DATA1, val)
+#define bfin_read_CAN1_MB31_DATA2()		bfin_read16(CAN1_MB31_DATA2)
+#define bfin_write_CAN1_MB31_DATA2(val)		bfin_write16(CAN1_MB31_DATA2, val)
+#define bfin_read_CAN1_MB31_DATA3()		bfin_read16(CAN1_MB31_DATA3)
+#define bfin_write_CAN1_MB31_DATA3(val)		bfin_write16(CAN1_MB31_DATA3, val)
+#define bfin_read_CAN1_MB31_LENGTH()		bfin_read16(CAN1_MB31_LENGTH)
+#define bfin_write_CAN1_MB31_LENGTH(val)	bfin_write16(CAN1_MB31_LENGTH, val)
+#define bfin_read_CAN1_MB31_TIMESTAMP()		bfin_read16(CAN1_MB31_TIMESTAMP)
+#define bfin_write_CAN1_MB31_TIMESTAMP(val)	bfin_write16(CAN1_MB31_TIMESTAMP, val)
+#define bfin_read_CAN1_MB31_ID0()		bfin_read16(CAN1_MB31_ID0)
+#define bfin_write_CAN1_MB31_ID0(val)		bfin_write16(CAN1_MB31_ID0, val)
+#define bfin_read_CAN1_MB31_ID1()		bfin_read16(CAN1_MB31_ID1)
+#define bfin_write_CAN1_MB31_ID1(val)		bfin_write16(CAN1_MB31_ID1, val)
+
+/* ATAPI Registers */
+
+#define bfin_read_ATAPI_CONTROL()		bfin_read16(ATAPI_CONTROL)
+#define bfin_write_ATAPI_CONTROL(val)		bfin_write16(ATAPI_CONTROL, val)
+#define bfin_read_ATAPI_STATUS()		bfin_read16(ATAPI_STATUS)
+#define bfin_write_ATAPI_STATUS(val)		bfin_write16(ATAPI_STATUS, val)
+#define bfin_read_ATAPI_DEV_ADDR()		bfin_read16(ATAPI_DEV_ADDR)
+#define bfin_write_ATAPI_DEV_ADDR(val)		bfin_write16(ATAPI_DEV_ADDR, val)
+#define bfin_read_ATAPI_DEV_TXBUF()		bfin_read16(ATAPI_DEV_TXBUF)
+#define bfin_write_ATAPI_DEV_TXBUF(val)		bfin_write16(ATAPI_DEV_TXBUF, val)
+#define bfin_read_ATAPI_DEV_RXBUF()		bfin_read16(ATAPI_DEV_RXBUF)
+#define bfin_write_ATAPI_DEV_RXBUF(val)		bfin_write16(ATAPI_DEV_RXBUF, val)
+#define bfin_read_ATAPI_INT_MASK()		bfin_read16(ATAPI_INT_MASK)
+#define bfin_write_ATAPI_INT_MASK(val)		bfin_write16(ATAPI_INT_MASK, val)
+#define bfin_read_ATAPI_INT_STATUS()		bfin_read16(ATAPI_INT_STATUS)
+#define bfin_write_ATAPI_INT_STATUS(val)	bfin_write16(ATAPI_INT_STATUS, val)
+#define bfin_read_ATAPI_XFER_LEN()		bfin_read16(ATAPI_XFER_LEN)
+#define bfin_write_ATAPI_XFER_LEN(val)		bfin_write16(ATAPI_XFER_LEN, val)
+#define bfin_read_ATAPI_LINE_STATUS()		bfin_read16(ATAPI_LINE_STATUS)
+#define bfin_write_ATAPI_LINE_STATUS(val)	bfin_write16(ATAPI_LINE_STATUS, val)
+#define bfin_read_ATAPI_SM_STATE()		bfin_read16(ATAPI_SM_STATE)
+#define bfin_write_ATAPI_SM_STATE(val)		bfin_write16(ATAPI_SM_STATE, val)
+#define bfin_read_ATAPI_TERMINATE()		bfin_read16(ATAPI_TERMINATE)
+#define bfin_write_ATAPI_TERMINATE(val)		bfin_write16(ATAPI_TERMINATE, val)
+#define bfin_read_ATAPI_PIO_TFRCNT()		bfin_read16(ATAPI_PIO_TFRCNT)
+#define bfin_write_ATAPI_PIO_TFRCNT(val)	bfin_write16(ATAPI_PIO_TFRCNT, val)
+#define bfin_read_ATAPI_DMA_TFRCNT()		bfin_read16(ATAPI_DMA_TFRCNT)
+#define bfin_write_ATAPI_DMA_TFRCNT(val)	bfin_write16(ATAPI_DMA_TFRCNT, val)
+#define bfin_read_ATAPI_UMAIN_TFRCNT()		bfin_read16(ATAPI_UMAIN_TFRCNT)
+#define bfin_write_ATAPI_UMAIN_TFRCNT(val)	bfin_write16(ATAPI_UMAIN_TFRCNT, val)
+#define bfin_read_ATAPI_UDMAOUT_TFRCNT()	bfin_read16(ATAPI_UDMAOUT_TFRCNT)
+#define bfin_write_ATAPI_UDMAOUT_TFRCNT(val)	bfin_write16(ATAPI_UDMAOUT_TFRCNT, val)
+#define bfin_read_ATAPI_REG_TIM_0()		bfin_read16(ATAPI_REG_TIM_0)
+#define bfin_write_ATAPI_REG_TIM_0(val)		bfin_write16(ATAPI_REG_TIM_0, val)
+#define bfin_read_ATAPI_PIO_TIM_0()		bfin_read16(ATAPI_PIO_TIM_0)
+#define bfin_write_ATAPI_PIO_TIM_0(val)		bfin_write16(ATAPI_PIO_TIM_0, val)
+#define bfin_read_ATAPI_PIO_TIM_1()		bfin_read16(ATAPI_PIO_TIM_1)
+#define bfin_write_ATAPI_PIO_TIM_1(val)		bfin_write16(ATAPI_PIO_TIM_1, val)
+#define bfin_read_ATAPI_MULTI_TIM_0()		bfin_read16(ATAPI_MULTI_TIM_0)
+#define bfin_write_ATAPI_MULTI_TIM_0(val)	bfin_write16(ATAPI_MULTI_TIM_0, val)
+#define bfin_read_ATAPI_MULTI_TIM_1()		bfin_read16(ATAPI_MULTI_TIM_1)
+#define bfin_write_ATAPI_MULTI_TIM_1(val)	bfin_write16(ATAPI_MULTI_TIM_1, val)
+#define bfin_read_ATAPI_MULTI_TIM_2()		bfin_read16(ATAPI_MULTI_TIM_2)
+#define bfin_write_ATAPI_MULTI_TIM_2(val)	bfin_write16(ATAPI_MULTI_TIM_2, val)
+#define bfin_read_ATAPI_ULTRA_TIM_0()		bfin_read16(ATAPI_ULTRA_TIM_0)
+#define bfin_write_ATAPI_ULTRA_TIM_0(val)	bfin_write16(ATAPI_ULTRA_TIM_0, val)
+#define bfin_read_ATAPI_ULTRA_TIM_1()		bfin_read16(ATAPI_ULTRA_TIM_1)
+#define bfin_write_ATAPI_ULTRA_TIM_1(val)	bfin_write16(ATAPI_ULTRA_TIM_1, val)
+#define bfin_read_ATAPI_ULTRA_TIM_2()		bfin_read16(ATAPI_ULTRA_TIM_2)
+#define bfin_write_ATAPI_ULTRA_TIM_2(val)	bfin_write16(ATAPI_ULTRA_TIM_2, val)
+#define bfin_read_ATAPI_ULTRA_TIM_3()		bfin_read16(ATAPI_ULTRA_TIM_3)
+#define bfin_write_ATAPI_ULTRA_TIM_3(val)	bfin_write16(ATAPI_ULTRA_TIM_3, val)
+
+/* SDH Registers */
+
+#define bfin_read_SDH_PWR_CTL()		bfin_read16(SDH_PWR_CTL)
+#define bfin_write_SDH_PWR_CTL(val)	bfin_write16(SDH_PWR_CTL, val)
+#define bfin_read_SDH_CLK_CTL()		bfin_read16(SDH_CLK_CTL)
+#define bfin_write_SDH_CLK_CTL(val)	bfin_write16(SDH_CLK_CTL, val)
+#define bfin_read_SDH_ARGUMENT()	bfin_read32(SDH_ARGUMENT)
+#define bfin_write_SDH_ARGUMENT(val)	bfin_write32(SDH_ARGUMENT, val)
+#define bfin_read_SDH_COMMAND()		bfin_read16(SDH_COMMAND)
+#define bfin_write_SDH_COMMAND(val)	bfin_write16(SDH_COMMAND, val)
+#define bfin_read_SDH_RESP_CMD()	bfin_read16(SDH_RESP_CMD)
+#define bfin_write_SDH_RESP_CMD(val)	bfin_write16(SDH_RESP_CMD, val)
+#define bfin_read_SDH_RESPONSE0()	bfin_read32(SDH_RESPONSE0)
+#define bfin_write_SDH_RESPONSE0(val)	bfin_write32(SDH_RESPONSE0, val)
+#define bfin_read_SDH_RESPONSE1()	bfin_read32(SDH_RESPONSE1)
+#define bfin_write_SDH_RESPONSE1(val)	bfin_write32(SDH_RESPONSE1, val)
+#define bfin_read_SDH_RESPONSE2()	bfin_read32(SDH_RESPONSE2)
+#define bfin_write_SDH_RESPONSE2(val)	bfin_write32(SDH_RESPONSE2, val)
+#define bfin_read_SDH_RESPONSE3()	bfin_read32(SDH_RESPONSE3)
+#define bfin_write_SDH_RESPONSE3(val)	bfin_write32(SDH_RESPONSE3, val)
+#define bfin_read_SDH_DATA_TIMER()	bfin_read32(SDH_DATA_TIMER)
+#define bfin_write_SDH_DATA_TIMER(val)	bfin_write32(SDH_DATA_TIMER, val)
+#define bfin_read_SDH_DATA_LGTH()	bfin_read16(SDH_DATA_LGTH)
+#define bfin_write_SDH_DATA_LGTH(val)	bfin_write16(SDH_DATA_LGTH, val)
+#define bfin_read_SDH_DATA_CTL()	bfin_read16(SDH_DATA_CTL)
+#define bfin_write_SDH_DATA_CTL(val)	bfin_write16(SDH_DATA_CTL, val)
+#define bfin_read_SDH_DATA_CNT()	bfin_read16(SDH_DATA_CNT)
+#define bfin_write_SDH_DATA_CNT(val)	bfin_write16(SDH_DATA_CNT, val)
+#define bfin_read_SDH_STATUS()		bfin_read32(SDH_STATUS)
+#define bfin_write_SDH_STATUS(val)	bfin_write32(SDH_STATUS, val)
+#define bfin_read_SDH_STATUS_CLR()	bfin_read16(SDH_STATUS_CLR)
+#define bfin_write_SDH_STATUS_CLR(val)	bfin_write16(SDH_STATUS_CLR, val)
+#define bfin_read_SDH_MASK0()		bfin_read32(SDH_MASK0)
+#define bfin_write_SDH_MASK0(val)	bfin_write32(SDH_MASK0, val)
+#define bfin_read_SDH_MASK1()		bfin_read32(SDH_MASK1)
+#define bfin_write_SDH_MASK1(val)	bfin_write32(SDH_MASK1, val)
+#define bfin_read_SDH_FIFO_CNT()	bfin_read16(SDH_FIFO_CNT)
+#define bfin_write_SDH_FIFO_CNT(val)	bfin_write16(SDH_FIFO_CNT, val)
+#define bfin_read_SDH_FIFO()		bfin_read32(SDH_FIFO)
+#define bfin_write_SDH_FIFO(val)	bfin_write32(SDH_FIFO, val)
+#define bfin_read_SDH_E_STATUS()	bfin_read16(SDH_E_STATUS)
+#define bfin_write_SDH_E_STATUS(val)	bfin_write16(SDH_E_STATUS, val)
+#define bfin_read_SDH_E_MASK()		bfin_read16(SDH_E_MASK)
+#define bfin_write_SDH_E_MASK(val)	bfin_write16(SDH_E_MASK, val)
+#define bfin_read_SDH_CFG()		bfin_read16(SDH_CFG)
+#define bfin_write_SDH_CFG(val)		bfin_write16(SDH_CFG, val)
+#define bfin_read_SDH_RD_WAIT_EN()	bfin_read16(SDH_RD_WAIT_EN)
+#define bfin_write_SDH_RD_WAIT_EN(val)	bfin_write16(SDH_RD_WAIT_EN, val)
+#define bfin_read_SDH_PID0()		bfin_read16(SDH_PID0)
+#define bfin_write_SDH_PID0(val)	bfin_write16(SDH_PID0, val)
+#define bfin_read_SDH_PID1()		bfin_read16(SDH_PID1)
+#define bfin_write_SDH_PID1(val)	bfin_write16(SDH_PID1, val)
+#define bfin_read_SDH_PID2()		bfin_read16(SDH_PID2)
+#define bfin_write_SDH_PID2(val)	bfin_write16(SDH_PID2, val)
+#define bfin_read_SDH_PID3()		bfin_read16(SDH_PID3)
+#define bfin_write_SDH_PID3(val)	bfin_write16(SDH_PID3, val)
+#define bfin_read_SDH_PID4()		bfin_read16(SDH_PID4)
+#define bfin_write_SDH_PID4(val)	bfin_write16(SDH_PID4, val)
+#define bfin_read_SDH_PID5()		bfin_read16(SDH_PID5)
+#define bfin_write_SDH_PID5(val)	bfin_write16(SDH_PID5, val)
+#define bfin_read_SDH_PID6()		bfin_read16(SDH_PID6)
+#define bfin_write_SDH_PID6(val)	bfin_write16(SDH_PID6, val)
+#define bfin_read_SDH_PID7()		bfin_read16(SDH_PID7)
+#define bfin_write_SDH_PID7(val)	bfin_write16(SDH_PID7, val)
+
+/* HOST Port Registers */
+
+#define bfin_read_HOST_CONTROL()	bfin_read16(HOST_CONTROL)
+#define bfin_write_HOST_CONTROL(val)	bfin_write16(HOST_CONTROL, val)
+#define bfin_read_HOST_STATUS()		bfin_read16(HOST_STATUS)
+#define bfin_write_HOST_STATUS(val)	bfin_write16(HOST_STATUS, val)
+#define bfin_read_HOST_TIMEOUT()	bfin_read16(HOST_TIMEOUT)
+#define bfin_write_HOST_TIMEOUT(val)	bfin_write16(HOST_TIMEOUT, val)
+
+/* USB Control Registers */
+
+#define bfin_read_USB_FADDR()		bfin_read16(USB_FADDR)
+#define bfin_write_USB_FADDR(val)	bfin_write16(USB_FADDR, val)
+#define bfin_read_USB_POWER()		bfin_read16(USB_POWER)
+#define bfin_write_USB_POWER(val)	bfin_write16(USB_POWER, val)
+#define bfin_read_USB_INTRTX()		bfin_read16(USB_INTRTX)
+#define bfin_write_USB_INTRTX(val)	bfin_write16(USB_INTRTX, val)
+#define bfin_read_USB_INTRRX()		bfin_read16(USB_INTRRX)
+#define bfin_write_USB_INTRRX(val)	bfin_write16(USB_INTRRX, val)
+#define bfin_read_USB_INTRTXE()		bfin_read16(USB_INTRTXE)
+#define bfin_write_USB_INTRTXE(val)	bfin_write16(USB_INTRTXE, val)
+#define bfin_read_USB_INTRRXE()		bfin_read16(USB_INTRRXE)
+#define bfin_write_USB_INTRRXE(val)	bfin_write16(USB_INTRRXE, val)
+#define bfin_read_USB_INTRUSB()		bfin_read16(USB_INTRUSB)
+#define bfin_write_USB_INTRUSB(val)	bfin_write16(USB_INTRUSB, val)
+#define bfin_read_USB_INTRUSBE()	bfin_read16(USB_INTRUSBE)
+#define bfin_write_USB_INTRUSBE(val)	bfin_write16(USB_INTRUSBE, val)
+#define bfin_read_USB_FRAME()		bfin_read16(USB_FRAME)
+#define bfin_write_USB_FRAME(val)	bfin_write16(USB_FRAME, val)
+#define bfin_read_USB_INDEX()		bfin_read16(USB_INDEX)
+#define bfin_write_USB_INDEX(val)	bfin_write16(USB_INDEX, val)
+#define bfin_read_USB_TESTMODE()	bfin_read16(USB_TESTMODE)
+#define bfin_write_USB_TESTMODE(val)	bfin_write16(USB_TESTMODE, val)
+#define bfin_read_USB_GLOBINTR()	bfin_read16(USB_GLOBINTR)
+#define bfin_write_USB_GLOBINTR(val)	bfin_write16(USB_GLOBINTR, val)
+#define bfin_read_USB_GLOBAL_CTL()	bfin_read16(USB_GLOBAL_CTL)
+#define bfin_write_USB_GLOBAL_CTL(val)	bfin_write16(USB_GLOBAL_CTL, val)
+
+/* USB Packet Control Registers */
+
+#define bfin_read_USB_TX_MAX_PACKET()		bfin_read16(USB_TX_MAX_PACKET)
+#define bfin_write_USB_TX_MAX_PACKET(val)	bfin_write16(USB_TX_MAX_PACKET, val)
+#define bfin_read_USB_CSR0()			bfin_read16(USB_CSR0)
+#define bfin_write_USB_CSR0(val)		bfin_write16(USB_CSR0, val)
+#define bfin_read_USB_TXCSR()			bfin_read16(USB_TXCSR)
+#define bfin_write_USB_TXCSR(val)		bfin_write16(USB_TXCSR, val)
+#define bfin_read_USB_RX_MAX_PACKET()		bfin_read16(USB_RX_MAX_PACKET)
+#define bfin_write_USB_RX_MAX_PACKET(val)	bfin_write16(USB_RX_MAX_PACKET, val)
+#define bfin_read_USB_RXCSR()			bfin_read16(USB_RXCSR)
+#define bfin_write_USB_RXCSR(val)		bfin_write16(USB_RXCSR, val)
+#define bfin_read_USB_COUNT0()			bfin_read16(USB_COUNT0)
+#define bfin_write_USB_COUNT0(val)		bfin_write16(USB_COUNT0, val)
+#define bfin_read_USB_RXCOUNT()			bfin_read16(USB_RXCOUNT)
+#define bfin_write_USB_RXCOUNT(val)		bfin_write16(USB_RXCOUNT, val)
+#define bfin_read_USB_TXTYPE()			bfin_read16(USB_TXTYPE)
+#define bfin_write_USB_TXTYPE(val)		bfin_write16(USB_TXTYPE, val)
+#define bfin_read_USB_NAKLIMIT0()		bfin_read16(USB_NAKLIMIT0)
+#define bfin_write_USB_NAKLIMIT0(val)		bfin_write16(USB_NAKLIMIT0, val)
+#define bfin_read_USB_TXINTERVAL()		bfin_read16(USB_TXINTERVAL)
+#define bfin_write_USB_TXINTERVAL(val)		bfin_write16(USB_TXINTERVAL, val)
+#define bfin_read_USB_RXTYPE()			bfin_read16(USB_RXTYPE)
+#define bfin_write_USB_RXTYPE(val)		bfin_write16(USB_RXTYPE, val)
+#define bfin_read_USB_RXINTERVAL()		bfin_read16(USB_RXINTERVAL)
+#define bfin_write_USB_RXINTERVAL(val)		bfin_write16(USB_RXINTERVAL, val)
+#define bfin_read_USB_TXCOUNT()			bfin_read16(USB_TXCOUNT)
+#define bfin_write_USB_TXCOUNT(val)		bfin_write16(USB_TXCOUNT, val)
+
+/* USB Endbfin_read_()oint FIFO Registers */
+
+#define bfin_read_USB_EP0_FIFO()		bfin_read16(USB_EP0_FIFO)
+#define bfin_write_USB_EP0_FIFO(val)		bfin_write16(USB_EP0_FIFO, val)
+#define bfin_read_USB_EP1_FIFO()		bfin_read16(USB_EP1_FIFO)
+#define bfin_write_USB_EP1_FIFO(val)		bfin_write16(USB_EP1_FIFO, val)
+#define bfin_read_USB_EP2_FIFO()		bfin_read16(USB_EP2_FIFO)
+#define bfin_write_USB_EP2_FIFO(val)		bfin_write16(USB_EP2_FIFO, val)
+#define bfin_read_USB_EP3_FIFO()		bfin_read16(USB_EP3_FIFO)
+#define bfin_write_USB_EP3_FIFO(val)		bfin_write16(USB_EP3_FIFO, val)
+#define bfin_read_USB_EP4_FIFO()		bfin_read16(USB_EP4_FIFO)
+#define bfin_write_USB_EP4_FIFO(val)		bfin_write16(USB_EP4_FIFO, val)
+#define bfin_read_USB_EP5_FIFO()		bfin_read16(USB_EP5_FIFO)
+#define bfin_write_USB_EP5_FIFO(val)		bfin_write16(USB_EP5_FIFO, val)
+#define bfin_read_USB_EP6_FIFO()		bfin_read16(USB_EP6_FIFO)
+#define bfin_write_USB_EP6_FIFO(val)		bfin_write16(USB_EP6_FIFO, val)
+#define bfin_read_USB_EP7_FIFO()		bfin_read16(USB_EP7_FIFO)
+#define bfin_write_USB_EP7_FIFO(val)		bfin_write16(USB_EP7_FIFO, val)
+
+/* USB OTG Control Registers */
+
+#define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
+#define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
+#define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
+#define bfin_write_USB_OTG_VBUS_IRQ(val)	bfin_write16(USB_OTG_VBUS_IRQ, val)
+#define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
+#define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
+
+/* USB Phy Control Registers */
+
+#define bfin_read_USB_LINKINFO()		bfin_read16(USB_LINKINFO)
+#define bfin_write_USB_LINKINFO(val)		bfin_write16(USB_LINKINFO, val)
+#define bfin_read_USB_VPLEN()			bfin_read16(USB_VPLEN)
+#define bfin_write_USB_VPLEN(val)		bfin_write16(USB_VPLEN, val)
+#define bfin_read_USB_HS_EOF1()			bfin_read16(USB_HS_EOF1)
+#define bfin_write_USB_HS_EOF1(val)		bfin_write16(USB_HS_EOF1, val)
+#define bfin_read_USB_FS_EOF1()			bfin_read16(USB_FS_EOF1)
+#define bfin_write_USB_FS_EOF1(val)		bfin_write16(USB_FS_EOF1, val)
+#define bfin_read_USB_LS_EOF1()			bfin_read16(USB_LS_EOF1)
+#define bfin_write_USB_LS_EOF1(val)		bfin_write16(USB_LS_EOF1, val)
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CNTRL()		bfin_read16(USB_APHY_CNTRL)
+#define bfin_write_USB_APHY_CNTRL(val)		bfin_write16(USB_APHY_CNTRL, val)
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define bfin_read_USB_APHY_CALIB()		bfin_read16(USB_APHY_CALIB)
+#define bfin_write_USB_APHY_CALIB(val)		bfin_write16(USB_APHY_CALIB, val)
+#define bfin_read_USB_APHY_CNTRL2()		bfin_read16(USB_APHY_CNTRL2)
+#define bfin_write_USB_APHY_CNTRL2(val)		bfin_write16(USB_APHY_CNTRL2, val)
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define bfin_read_USB_PHY_TEST()		bfin_read16(USB_PHY_TEST)
+#define bfin_write_USB_PHY_TEST(val)		bfin_write16(USB_PHY_TEST, val)
+#define bfin_read_USB_PLLOSC_CTRL()		bfin_read16(USB_PLLOSC_CTRL)
+#define bfin_write_USB_PLLOSC_CTRL(val)		bfin_write16(USB_PLLOSC_CTRL, val)
+#define bfin_read_USB_SRP_CLKDIV()		bfin_read16(USB_SRP_CLKDIV)
+#define bfin_write_USB_SRP_CLKDIV(val)		bfin_write16(USB_SRP_CLKDIV, val)
+
+/* USB Endbfin_read_()oint 0 Control Registers */
+
+#define bfin_read_USB_EP_NI0_TXMAXP()		bfin_read16(USB_EP_NI0_TXMAXP)
+#define bfin_write_USB_EP_NI0_TXMAXP(val)	bfin_write16(USB_EP_NI0_TXMAXP, val)
+#define bfin_read_USB_EP_NI0_TXCSR()		bfin_read16(USB_EP_NI0_TXCSR)
+#define bfin_write_USB_EP_NI0_TXCSR(val)	bfin_write16(USB_EP_NI0_TXCSR, val)
+#define bfin_read_USB_EP_NI0_RXMAXP()		bfin_read16(USB_EP_NI0_RXMAXP)
+#define bfin_write_USB_EP_NI0_RXMAXP(val)	bfin_write16(USB_EP_NI0_RXMAXP, val)
+#define bfin_read_USB_EP_NI0_RXCSR()		bfin_read16(USB_EP_NI0_RXCSR)
+#define bfin_write_USB_EP_NI0_RXCSR(val)	bfin_write16(USB_EP_NI0_RXCSR, val)
+#define bfin_read_USB_EP_NI0_RXCOUNT()		bfin_read16(USB_EP_NI0_RXCOUNT)
+#define bfin_write_USB_EP_NI0_RXCOUNT(val)	bfin_write16(USB_EP_NI0_RXCOUNT, val)
+#define bfin_read_USB_EP_NI0_TXTYPE()		bfin_read16(USB_EP_NI0_TXTYPE)
+#define bfin_write_USB_EP_NI0_TXTYPE(val)	bfin_write16(USB_EP_NI0_TXTYPE, val)
+#define bfin_read_USB_EP_NI0_TXINTERVAL()	bfin_read16(USB_EP_NI0_TXINTERVAL)
+#define bfin_write_USB_EP_NI0_TXINTERVAL(val)	bfin_write16(USB_EP_NI0_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI0_RXTYPE()		bfin_read16(USB_EP_NI0_RXTYPE)
+#define bfin_write_USB_EP_NI0_RXTYPE(val)	bfin_write16(USB_EP_NI0_RXTYPE, val)
+#define bfin_read_USB_EP_NI0_RXINTERVAL()	bfin_read16(USB_EP_NI0_RXINTERVAL)
+#define bfin_write_USB_EP_NI0_RXINTERVAL(val)	bfin_write16(USB_EP_NI0_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 1 Control Registers */
+
+#define bfin_read_USB_EP_NI0_TXCOUNT()		bfin_read16(USB_EP_NI0_TXCOUNT)
+#define bfin_write_USB_EP_NI0_TXCOUNT(val)	bfin_write16(USB_EP_NI0_TXCOUNT, val)
+#define bfin_read_USB_EP_NI1_TXMAXP()		bfin_read16(USB_EP_NI1_TXMAXP)
+#define bfin_write_USB_EP_NI1_TXMAXP(val)	bfin_write16(USB_EP_NI1_TXMAXP, val)
+#define bfin_read_USB_EP_NI1_TXCSR()		bfin_read16(USB_EP_NI1_TXCSR)
+#define bfin_write_USB_EP_NI1_TXCSR(val)	bfin_write16(USB_EP_NI1_TXCSR, val)
+#define bfin_read_USB_EP_NI1_RXMAXP()		bfin_read16(USB_EP_NI1_RXMAXP)
+#define bfin_write_USB_EP_NI1_RXMAXP(val)	bfin_write16(USB_EP_NI1_RXMAXP, val)
+#define bfin_read_USB_EP_NI1_RXCSR()		bfin_read16(USB_EP_NI1_RXCSR)
+#define bfin_write_USB_EP_NI1_RXCSR(val)	bfin_write16(USB_EP_NI1_RXCSR, val)
+#define bfin_read_USB_EP_NI1_RXCOUNT()		bfin_read16(USB_EP_NI1_RXCOUNT)
+#define bfin_write_USB_EP_NI1_RXCOUNT(val)	bfin_write16(USB_EP_NI1_RXCOUNT, val)
+#define bfin_read_USB_EP_NI1_TXTYPE()		bfin_read16(USB_EP_NI1_TXTYPE)
+#define bfin_write_USB_EP_NI1_TXTYPE(val)	bfin_write16(USB_EP_NI1_TXTYPE, val)
+#define bfin_read_USB_EP_NI1_TXINTERVAL()	bfin_read16(USB_EP_NI1_TXINTERVAL)
+#define bfin_write_USB_EP_NI1_TXINTERVAL(val)	bfin_write16(USB_EP_NI1_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI1_RXTYPE()		bfin_read16(USB_EP_NI1_RXTYPE)
+#define bfin_write_USB_EP_NI1_RXTYPE(val)	bfin_write16(USB_EP_NI1_RXTYPE, val)
+#define bfin_read_USB_EP_NI1_RXINTERVAL()	bfin_read16(USB_EP_NI1_RXINTERVAL)
+#define bfin_write_USB_EP_NI1_RXINTERVAL(val)	bfin_write16(USB_EP_NI1_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 2 Control Registers */
+
+#define bfin_read_USB_EP_NI1_TXCOUNT()		bfin_read16(USB_EP_NI1_TXCOUNT)
+#define bfin_write_USB_EP_NI1_TXCOUNT(val)	bfin_write16(USB_EP_NI1_TXCOUNT, val)
+#define bfin_read_USB_EP_NI2_TXMAXP()		bfin_read16(USB_EP_NI2_TXMAXP)
+#define bfin_write_USB_EP_NI2_TXMAXP(val)	bfin_write16(USB_EP_NI2_TXMAXP, val)
+#define bfin_read_USB_EP_NI2_TXCSR()		bfin_read16(USB_EP_NI2_TXCSR)
+#define bfin_write_USB_EP_NI2_TXCSR(val)	bfin_write16(USB_EP_NI2_TXCSR, val)
+#define bfin_read_USB_EP_NI2_RXMAXP()		bfin_read16(USB_EP_NI2_RXMAXP)
+#define bfin_write_USB_EP_NI2_RXMAXP(val)	bfin_write16(USB_EP_NI2_RXMAXP, val)
+#define bfin_read_USB_EP_NI2_RXCSR()		bfin_read16(USB_EP_NI2_RXCSR)
+#define bfin_write_USB_EP_NI2_RXCSR(val)	bfin_write16(USB_EP_NI2_RXCSR, val)
+#define bfin_read_USB_EP_NI2_RXCOUNT()		bfin_read16(USB_EP_NI2_RXCOUNT)
+#define bfin_write_USB_EP_NI2_RXCOUNT(val)	bfin_write16(USB_EP_NI2_RXCOUNT, val)
+#define bfin_read_USB_EP_NI2_TXTYPE()		bfin_read16(USB_EP_NI2_TXTYPE)
+#define bfin_write_USB_EP_NI2_TXTYPE(val)	bfin_write16(USB_EP_NI2_TXTYPE, val)
+#define bfin_read_USB_EP_NI2_TXINTERVAL()	bfin_read16(USB_EP_NI2_TXINTERVAL)
+#define bfin_write_USB_EP_NI2_TXINTERVAL(val)	bfin_write16(USB_EP_NI2_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI2_RXTYPE()		bfin_read16(USB_EP_NI2_RXTYPE)
+#define bfin_write_USB_EP_NI2_RXTYPE(val)	bfin_write16(USB_EP_NI2_RXTYPE, val)
+#define bfin_read_USB_EP_NI2_RXINTERVAL()	bfin_read16(USB_EP_NI2_RXINTERVAL)
+#define bfin_write_USB_EP_NI2_RXINTERVAL(val)	bfin_write16(USB_EP_NI2_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 3 Control Registers */
+
+#define bfin_read_USB_EP_NI2_TXCOUNT()		bfin_read16(USB_EP_NI2_TXCOUNT)
+#define bfin_write_USB_EP_NI2_TXCOUNT(val)	bfin_write16(USB_EP_NI2_TXCOUNT, val)
+#define bfin_read_USB_EP_NI3_TXMAXP()		bfin_read16(USB_EP_NI3_TXMAXP)
+#define bfin_write_USB_EP_NI3_TXMAXP(val)	bfin_write16(USB_EP_NI3_TXMAXP, val)
+#define bfin_read_USB_EP_NI3_TXCSR()		bfin_read16(USB_EP_NI3_TXCSR)
+#define bfin_write_USB_EP_NI3_TXCSR(val)	bfin_write16(USB_EP_NI3_TXCSR, val)
+#define bfin_read_USB_EP_NI3_RXMAXP()		bfin_read16(USB_EP_NI3_RXMAXP)
+#define bfin_write_USB_EP_NI3_RXMAXP(val)	bfin_write16(USB_EP_NI3_RXMAXP, val)
+#define bfin_read_USB_EP_NI3_RXCSR()		bfin_read16(USB_EP_NI3_RXCSR)
+#define bfin_write_USB_EP_NI3_RXCSR(val)	bfin_write16(USB_EP_NI3_RXCSR, val)
+#define bfin_read_USB_EP_NI3_RXCOUNT()		bfin_read16(USB_EP_NI3_RXCOUNT)
+#define bfin_write_USB_EP_NI3_RXCOUNT(val)	bfin_write16(USB_EP_NI3_RXCOUNT, val)
+#define bfin_read_USB_EP_NI3_TXTYPE()		bfin_read16(USB_EP_NI3_TXTYPE)
+#define bfin_write_USB_EP_NI3_TXTYPE(val)	bfin_write16(USB_EP_NI3_TXTYPE, val)
+#define bfin_read_USB_EP_NI3_TXINTERVAL()	bfin_read16(USB_EP_NI3_TXINTERVAL)
+#define bfin_write_USB_EP_NI3_TXINTERVAL(val)	bfin_write16(USB_EP_NI3_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI3_RXTYPE()		bfin_read16(USB_EP_NI3_RXTYPE)
+#define bfin_write_USB_EP_NI3_RXTYPE(val)	bfin_write16(USB_EP_NI3_RXTYPE, val)
+#define bfin_read_USB_EP_NI3_RXINTERVAL()	bfin_read16(USB_EP_NI3_RXINTERVAL)
+#define bfin_write_USB_EP_NI3_RXINTERVAL(val)	bfin_write16(USB_EP_NI3_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 4 Control Registers */
+
+#define bfin_read_USB_EP_NI3_TXCOUNT()		bfin_read16(USB_EP_NI3_TXCOUNT)
+#define bfin_write_USB_EP_NI3_TXCOUNT(val)	bfin_write16(USB_EP_NI3_TXCOUNT, val)
+#define bfin_read_USB_EP_NI4_TXMAXP()		bfin_read16(USB_EP_NI4_TXMAXP)
+#define bfin_write_USB_EP_NI4_TXMAXP(val)	bfin_write16(USB_EP_NI4_TXMAXP, val)
+#define bfin_read_USB_EP_NI4_TXCSR()		bfin_read16(USB_EP_NI4_TXCSR)
+#define bfin_write_USB_EP_NI4_TXCSR(val)	bfin_write16(USB_EP_NI4_TXCSR, val)
+#define bfin_read_USB_EP_NI4_RXMAXP()		bfin_read16(USB_EP_NI4_RXMAXP)
+#define bfin_write_USB_EP_NI4_RXMAXP(val)	bfin_write16(USB_EP_NI4_RXMAXP, val)
+#define bfin_read_USB_EP_NI4_RXCSR()		bfin_read16(USB_EP_NI4_RXCSR)
+#define bfin_write_USB_EP_NI4_RXCSR(val)	bfin_write16(USB_EP_NI4_RXCSR, val)
+#define bfin_read_USB_EP_NI4_RXCOUNT()		bfin_read16(USB_EP_NI4_RXCOUNT)
+#define bfin_write_USB_EP_NI4_RXCOUNT(val)	bfin_write16(USB_EP_NI4_RXCOUNT, val)
+#define bfin_read_USB_EP_NI4_TXTYPE()		bfin_read16(USB_EP_NI4_TXTYPE)
+#define bfin_write_USB_EP_NI4_TXTYPE(val)	bfin_write16(USB_EP_NI4_TXTYPE, val)
+#define bfin_read_USB_EP_NI4_TXINTERVAL()	bfin_read16(USB_EP_NI4_TXINTERVAL)
+#define bfin_write_USB_EP_NI4_TXINTERVAL(val)	bfin_write16(USB_EP_NI4_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI4_RXTYPE()		bfin_read16(USB_EP_NI4_RXTYPE)
+#define bfin_write_USB_EP_NI4_RXTYPE(val)	bfin_write16(USB_EP_NI4_RXTYPE, val)
+#define bfin_read_USB_EP_NI4_RXINTERVAL()	bfin_read16(USB_EP_NI4_RXINTERVAL)
+#define bfin_write_USB_EP_NI4_RXINTERVAL(val)	bfin_write16(USB_EP_NI4_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 5 Control Registers */
+
+#define bfin_read_USB_EP_NI4_TXCOUNT()		bfin_read16(USB_EP_NI4_TXCOUNT)
+#define bfin_write_USB_EP_NI4_TXCOUNT(val)	bfin_write16(USB_EP_NI4_TXCOUNT, val)
+#define bfin_read_USB_EP_NI5_TXMAXP()		bfin_read16(USB_EP_NI5_TXMAXP)
+#define bfin_write_USB_EP_NI5_TXMAXP(val)	bfin_write16(USB_EP_NI5_TXMAXP, val)
+#define bfin_read_USB_EP_NI5_TXCSR()		bfin_read16(USB_EP_NI5_TXCSR)
+#define bfin_write_USB_EP_NI5_TXCSR(val)	bfin_write16(USB_EP_NI5_TXCSR, val)
+#define bfin_read_USB_EP_NI5_RXMAXP()		bfin_read16(USB_EP_NI5_RXMAXP)
+#define bfin_write_USB_EP_NI5_RXMAXP(val)	bfin_write16(USB_EP_NI5_RXMAXP, val)
+#define bfin_read_USB_EP_NI5_RXCSR()		bfin_read16(USB_EP_NI5_RXCSR)
+#define bfin_write_USB_EP_NI5_RXCSR(val)	bfin_write16(USB_EP_NI5_RXCSR, val)
+#define bfin_read_USB_EP_NI5_RXCOUNT()		bfin_read16(USB_EP_NI5_RXCOUNT)
+#define bfin_write_USB_EP_NI5_RXCOUNT(val)	bfin_write16(USB_EP_NI5_RXCOUNT, val)
+#define bfin_read_USB_EP_NI5_TXTYPE()		bfin_read16(USB_EP_NI5_TXTYPE)
+#define bfin_write_USB_EP_NI5_TXTYPE(val)	bfin_write16(USB_EP_NI5_TXTYPE, val)
+#define bfin_read_USB_EP_NI5_TXINTERVAL()	bfin_read16(USB_EP_NI5_TXINTERVAL)
+#define bfin_write_USB_EP_NI5_TXINTERVAL(val)	bfin_write16(USB_EP_NI5_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI5_RXTYPE()		bfin_read16(USB_EP_NI5_RXTYPE)
+#define bfin_write_USB_EP_NI5_RXTYPE(val)	bfin_write16(USB_EP_NI5_RXTYPE, val)
+#define bfin_read_USB_EP_NI5_RXINTERVAL()	bfin_read16(USB_EP_NI5_RXINTERVAL)
+#define bfin_write_USB_EP_NI5_RXINTERVAL(val)	bfin_write16(USB_EP_NI5_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 6 Control Registers */
+
+#define bfin_read_USB_EP_NI5_TXCOUNT()		bfin_read16(USB_EP_NI5_TXCOUNT)
+#define bfin_write_USB_EP_NI5_TXCOUNT(val)	bfin_write16(USB_EP_NI5_TXCOUNT, val)
+#define bfin_read_USB_EP_NI6_TXMAXP()		bfin_read16(USB_EP_NI6_TXMAXP)
+#define bfin_write_USB_EP_NI6_TXMAXP(val)	bfin_write16(USB_EP_NI6_TXMAXP, val)
+#define bfin_read_USB_EP_NI6_TXCSR()		bfin_read16(USB_EP_NI6_TXCSR)
+#define bfin_write_USB_EP_NI6_TXCSR(val)	bfin_write16(USB_EP_NI6_TXCSR, val)
+#define bfin_read_USB_EP_NI6_RXMAXP()		bfin_read16(USB_EP_NI6_RXMAXP)
+#define bfin_write_USB_EP_NI6_RXMAXP(val)	bfin_write16(USB_EP_NI6_RXMAXP, val)
+#define bfin_read_USB_EP_NI6_RXCSR()		bfin_read16(USB_EP_NI6_RXCSR)
+#define bfin_write_USB_EP_NI6_RXCSR(val)	bfin_write16(USB_EP_NI6_RXCSR, val)
+#define bfin_read_USB_EP_NI6_RXCOUNT()		bfin_read16(USB_EP_NI6_RXCOUNT)
+#define bfin_write_USB_EP_NI6_RXCOUNT(val)	bfin_write16(USB_EP_NI6_RXCOUNT, val)
+#define bfin_read_USB_EP_NI6_TXTYPE()		bfin_read16(USB_EP_NI6_TXTYPE)
+#define bfin_write_USB_EP_NI6_TXTYPE(val)	bfin_write16(USB_EP_NI6_TXTYPE, val)
+#define bfin_read_USB_EP_NI6_TXINTERVAL()	bfin_read16(USB_EP_NI6_TXINTERVAL)
+#define bfin_write_USB_EP_NI6_TXINTERVAL(val)	bfin_write16(USB_EP_NI6_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI6_RXTYPE()		bfin_read16(USB_EP_NI6_RXTYPE)
+#define bfin_write_USB_EP_NI6_RXTYPE(val)	bfin_write16(USB_EP_NI6_RXTYPE, val)
+#define bfin_read_USB_EP_NI6_RXINTERVAL()	bfin_read16(USB_EP_NI6_RXINTERVAL)
+#define bfin_write_USB_EP_NI6_RXINTERVAL(val)	bfin_write16(USB_EP_NI6_RXINTERVAL, val)
+
+/* USB Endbfin_read_()oint 7 Control Registers */
+
+#define bfin_read_USB_EP_NI6_TXCOUNT()		bfin_read16(USB_EP_NI6_TXCOUNT)
+#define bfin_write_USB_EP_NI6_TXCOUNT(val)	bfin_write16(USB_EP_NI6_TXCOUNT, val)
+#define bfin_read_USB_EP_NI7_TXMAXP()		bfin_read16(USB_EP_NI7_TXMAXP)
+#define bfin_write_USB_EP_NI7_TXMAXP(val)	bfin_write16(USB_EP_NI7_TXMAXP, val)
+#define bfin_read_USB_EP_NI7_TXCSR()		bfin_read16(USB_EP_NI7_TXCSR)
+#define bfin_write_USB_EP_NI7_TXCSR(val)	bfin_write16(USB_EP_NI7_TXCSR, val)
+#define bfin_read_USB_EP_NI7_RXMAXP()		bfin_read16(USB_EP_NI7_RXMAXP)
+#define bfin_write_USB_EP_NI7_RXMAXP(val)	bfin_write16(USB_EP_NI7_RXMAXP, val)
+#define bfin_read_USB_EP_NI7_RXCSR()		bfin_read16(USB_EP_NI7_RXCSR)
+#define bfin_write_USB_EP_NI7_RXCSR(val)	bfin_write16(USB_EP_NI7_RXCSR, val)
+#define bfin_read_USB_EP_NI7_RXCOUNT()		bfin_read16(USB_EP_NI7_RXCOUNT)
+#define bfin_write_USB_EP_NI7_RXCOUNT(val)	bfin_write16(USB_EP_NI7_RXCOUNT, val)
+#define bfin_read_USB_EP_NI7_TXTYPE()		bfin_read16(USB_EP_NI7_TXTYPE)
+#define bfin_write_USB_EP_NI7_TXTYPE(val)	bfin_write16(USB_EP_NI7_TXTYPE, val)
+#define bfin_read_USB_EP_NI7_TXINTERVAL()	bfin_read16(USB_EP_NI7_TXINTERVAL)
+#define bfin_write_USB_EP_NI7_TXINTERVAL(val)	bfin_write16(USB_EP_NI7_TXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_RXTYPE()		bfin_read16(USB_EP_NI7_RXTYPE)
+#define bfin_write_USB_EP_NI7_RXTYPE(val)	bfin_write16(USB_EP_NI7_RXTYPE, val)
+#define bfin_read_USB_EP_NI7_RXINTERVAL()	bfin_read16(USB_EP_NI7_RXINTERVAL)
+#define bfin_write_USB_EP_NI7_RXINTERVAL(val)	bfin_write16(USB_EP_NI7_RXINTERVAL, val)
+#define bfin_read_USB_EP_NI7_TXCOUNT()		bfin_read16(USB_EP_NI7_TXCOUNT)
+#define bfin_write_USB_EP_NI7_TXCOUNT(val)	bfin_write16(USB_EP_NI7_TXCOUNT, val)
+#define bfin_read_USB_DMA_INTERRUPT()		bfin_read16(USB_DMA_INTERRUPT)
+#define bfin_write_USB_DMA_INTERRUPT(val)	bfin_write16(USB_DMA_INTERRUPT, val)
+
+/* USB Channel 0 Config Registers */
+
+#define bfin_read_USB_DMA0CONTROL()		bfin_read16(USB_DMA0CONTROL)
+#define bfin_write_USB_DMA0CONTROL(val)		bfin_write16(USB_DMA0CONTROL, val)
+#define bfin_read_USB_DMA0ADDRLOW()		bfin_read16(USB_DMA0ADDRLOW)
+#define bfin_write_USB_DMA0ADDRLOW(val)		bfin_write16(USB_DMA0ADDRLOW, val)
+#define bfin_read_USB_DMA0ADDRHIGH()		bfin_read16(USB_DMA0ADDRHIGH)
+#define bfin_write_USB_DMA0ADDRHIGH(val)	bfin_write16(USB_DMA0ADDRHIGH, val)
+#define bfin_read_USB_DMA0COUNTLOW()		bfin_read16(USB_DMA0COUNTLOW)
+#define bfin_write_USB_DMA0COUNTLOW(val)	bfin_write16(USB_DMA0COUNTLOW, val)
+#define bfin_read_USB_DMA0COUNTHIGH()		bfin_read16(USB_DMA0COUNTHIGH)
+#define bfin_write_USB_DMA0COUNTHIGH(val)	bfin_write16(USB_DMA0COUNTHIGH, val)
+
+/* USB Channel 1 Config Registers */
+
+#define bfin_read_USB_DMA1CONTROL()		bfin_read16(USB_DMA1CONTROL)
+#define bfin_write_USB_DMA1CONTROL(val)		bfin_write16(USB_DMA1CONTROL, val)
+#define bfin_read_USB_DMA1ADDRLOW()		bfin_read16(USB_DMA1ADDRLOW)
+#define bfin_write_USB_DMA1ADDRLOW(val)		bfin_write16(USB_DMA1ADDRLOW, val)
+#define bfin_read_USB_DMA1ADDRHIGH()		bfin_read16(USB_DMA1ADDRHIGH)
+#define bfin_write_USB_DMA1ADDRHIGH(val)	bfin_write16(USB_DMA1ADDRHIGH, val)
+#define bfin_read_USB_DMA1COUNTLOW()		bfin_read16(USB_DMA1COUNTLOW)
+#define bfin_write_USB_DMA1COUNTLOW(val)	bfin_write16(USB_DMA1COUNTLOW, val)
+#define bfin_read_USB_DMA1COUNTHIGH()		bfin_read16(USB_DMA1COUNTHIGH)
+#define bfin_write_USB_DMA1COUNTHIGH(val)	bfin_write16(USB_DMA1COUNTHIGH, val)
+
+/* USB Channel 2 Config Registers */
+
+#define bfin_read_USB_DMA2CONTROL()		bfin_read16(USB_DMA2CONTROL)
+#define bfin_write_USB_DMA2CONTROL(val)		bfin_write16(USB_DMA2CONTROL, val)
+#define bfin_read_USB_DMA2ADDRLOW()		bfin_read16(USB_DMA2ADDRLOW)
+#define bfin_write_USB_DMA2ADDRLOW(val)		bfin_write16(USB_DMA2ADDRLOW, val)
+#define bfin_read_USB_DMA2ADDRHIGH()		bfin_read16(USB_DMA2ADDRHIGH)
+#define bfin_write_USB_DMA2ADDRHIGH(val)	bfin_write16(USB_DMA2ADDRHIGH, val)
+#define bfin_read_USB_DMA2COUNTLOW()		bfin_read16(USB_DMA2COUNTLOW)
+#define bfin_write_USB_DMA2COUNTLOW(val)	bfin_write16(USB_DMA2COUNTLOW, val)
+#define bfin_read_USB_DMA2COUNTHIGH()		bfin_read16(USB_DMA2COUNTHIGH)
+#define bfin_write_USB_DMA2COUNTHIGH(val)	bfin_write16(USB_DMA2COUNTHIGH, val)
+
+/* USB Channel 3 Config Registers */
+
+#define bfin_read_USB_DMA3CONTROL()		bfin_read16(USB_DMA3CONTROL)
+#define bfin_write_USB_DMA3CONTROL(val)		bfin_write16(USB_DMA3CONTROL, val)
+#define bfin_read_USB_DMA3ADDRLOW()		bfin_read16(USB_DMA3ADDRLOW)
+#define bfin_write_USB_DMA3ADDRLOW(val)		bfin_write16(USB_DMA3ADDRLOW, val)
+#define bfin_read_USB_DMA3ADDRHIGH()		bfin_read16(USB_DMA3ADDRHIGH)
+#define bfin_write_USB_DMA3ADDRHIGH(val)	bfin_write16(USB_DMA3ADDRHIGH, val)
+#define bfin_read_USB_DMA3COUNTLOW()		bfin_read16(USB_DMA3COUNTLOW)
+#define bfin_write_USB_DMA3COUNTLOW(val)	bfin_write16(USB_DMA3COUNTLOW, val)
+#define bfin_read_USB_DMA3COUNTHIGH()		bfin_read16(USB_DMA3COUNTHIGH)
+#define bfin_write_USB_DMA3COUNTHIGH(val)	bfin_write16(USB_DMA3COUNTHIGH, val)
+
+/* USB Channel 4 Config Registers */
+
+#define bfin_read_USB_DMA4CONTROL()		bfin_read16(USB_DMA4CONTROL)
+#define bfin_write_USB_DMA4CONTROL(val)		bfin_write16(USB_DMA4CONTROL, val)
+#define bfin_read_USB_DMA4ADDRLOW()		bfin_read16(USB_DMA4ADDRLOW)
+#define bfin_write_USB_DMA4ADDRLOW(val)		bfin_write16(USB_DMA4ADDRLOW, val)
+#define bfin_read_USB_DMA4ADDRHIGH()		bfin_read16(USB_DMA4ADDRHIGH)
+#define bfin_write_USB_DMA4ADDRHIGH(val)	bfin_write16(USB_DMA4ADDRHIGH, val)
+#define bfin_read_USB_DMA4COUNTLOW()		bfin_read16(USB_DMA4COUNTLOW)
+#define bfin_write_USB_DMA4COUNTLOW(val)	bfin_write16(USB_DMA4COUNTLOW, val)
+#define bfin_read_USB_DMA4COUNTHIGH()		bfin_read16(USB_DMA4COUNTHIGH)
+#define bfin_write_USB_DMA4COUNTHIGH(val)	bfin_write16(USB_DMA4COUNTHIGH, val)
+
+/* USB Channel 5 Config Registers */
+
+#define bfin_read_USB_DMA5CONTROL()		bfin_read16(USB_DMA5CONTROL)
+#define bfin_write_USB_DMA5CONTROL(val)		bfin_write16(USB_DMA5CONTROL, val)
+#define bfin_read_USB_DMA5ADDRLOW()		bfin_read16(USB_DMA5ADDRLOW)
+#define bfin_write_USB_DMA5ADDRLOW(val)		bfin_write16(USB_DMA5ADDRLOW, val)
+#define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
+#define bfin_write_USB_DMA5ADDRHIGH(val)		bfin_write16(USB_DMA5ADDRHIGH, val)
+#define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
+#define bfin_write_USB_DMA5COUNTLOW(val)	fin_write16(USB_DMA5COUNTLOW, val)
+#define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
+#define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
+
+/* USB Channel 6 Config Registers */
+
+#define bfin_read_USB_DMA6CONTROL()		bfin_read16(USB_DMA6CONTROL)
+#define bfin_write_USB_DMA6CONTROL(val)		bfin_write16(USB_DMA6CONTROL, val)
+#define bfin_read_USB_DMA6ADDRLOW()		bfin_read16(USB_DMA6ADDRLOW)
+#define bfin_write_USB_DMA6ADDRLOW(val)		bfin_write16(USB_DMA6ADDRLOW, val)
+#define bfin_read_USB_DMA6ADDRHIGH()		bfin_read16(USB_DMA6ADDRHIGH)
+#define bfin_write_USB_DMA6ADDRHIGH(val)	bfin_write16(USB_DMA6ADDRHIGH, val)
+#define bfin_read_USB_DMA6COUNTLOW()		bfin_read16(USB_DMA6COUNTLOW)
+#define bfin_write_USB_DMA6COUNTLOW(val)	bfin_write16(USB_DMA6COUNTLOW, val)
+#define bfin_read_USB_DMA6COUNTHIGH()		bfin_read16(USB_DMA6COUNTHIGH)
+#define bfin_write_USB_DMA6COUNTHIGH(val)	bfin_write16(USB_DMA6COUNTHIGH, val)
+
+/* USB Channel 7 Config Registers */
+
+#define bfin_read_USB_DMA7CONTROL()		bfin_read16(USB_DMA7CONTROL)
+#define bfin_write_USB_DMA7CONTROL(val)		bfin_write16(USB_DMA7CONTROL, val)
+#define bfin_read_USB_DMA7ADDRLOW()		bfin_read16(USB_DMA7ADDRLOW)
+#define bfin_write_USB_DMA7ADDRLOW(val)		bfin_write16(USB_DMA7ADDRLOW, val)
+#define bfin_read_USB_DMA7ADDRHIGH()		bfin_read16(USB_DMA7ADDRHIGH)
+#define bfin_write_USB_DMA7ADDRHIGH(val)	bfin_write16(USB_DMA7ADDRHIGH, val)
+#define bfin_read_USB_DMA7COUNTLOW()		bfin_read16(USB_DMA7COUNTLOW)
+#define bfin_write_USB_DMA7COUNTLOW(val)	bfin_write16(USB_DMA7COUNTLOW, val)
+#define bfin_read_USB_DMA7COUNTHIGH()		bfin_read16(USB_DMA7COUNTHIGH)
+#define bfin_write_USB_DMA7COUNTHIGH(val)	bfin_write16(USB_DMA7COUNTHIGH, val)
+
+/* Keybfin_read_()ad Registers */
+
+#define bfin_read_KPAD_CTL()		bfin_read16(KPAD_CTL)
+#define bfin_write_KPAD_CTL(val)	bfin_write16(KPAD_CTL, val)
+#define bfin_read_KPAD_PRESCALE()	bfin_read16(KPAD_PRESCALE)
+#define bfin_write_KPAD_PRESCALE(val)	bfin_write16(KPAD_PRESCALE, val)
+#define bfin_read_KPAD_MSEL()		bfin_read16(KPAD_MSEL)
+#define bfin_write_KPAD_MSEL(val)	bfin_write16(KPAD_MSEL, val)
+#define bfin_read_KPAD_ROWCOL()		bfin_read16(KPAD_ROWCOL)
+#define bfin_write_KPAD_ROWCOL(val)	bfin_write16(KPAD_ROWCOL, val)
+#define bfin_read_KPAD_STAT()		bfin_read16(KPAD_STAT)
+#define bfin_write_KPAD_STAT(val)	bfin_write16(KPAD_STAT, val)
+#define bfin_read_KPAD_SOFTEVAL()	bfin_read16(KPAD_SOFTEVAL)
+#define bfin_write_KPAD_SOFTEVAL(val)	bfin_write16(KPAD_SOFTEVAL, val)
+
+/* Pixel Combfin_read_()ositor (PIXC) Registers */
+
+#define bfin_read_PIXC_CTL()		bfin_read16(PIXC_CTL)
+#define bfin_write_PIXC_CTL(val)	bfin_write16(PIXC_CTL, val)
+#define bfin_read_PIXC_PPL()		bfin_read16(PIXC_PPL)
+#define bfin_write_PIXC_PPL(val)	bfin_write16(PIXC_PPL, val)
+#define bfin_read_PIXC_LPF()		bfin_read16(PIXC_LPF)
+#define bfin_write_PIXC_LPF(val)	bfin_write16(PIXC_LPF, val)
+#define bfin_read_PIXC_AHSTART()	bfin_read16(PIXC_AHSTART)
+#define bfin_write_PIXC_AHSTART(val)	bfin_write16(PIXC_AHSTART, val)
+#define bfin_read_PIXC_AHEND()		bfin_read16(PIXC_AHEND)
+#define bfin_write_PIXC_AHEND(val)	bfin_write16(PIXC_AHEND, val)
+#define bfin_read_PIXC_AVSTART()	bfin_read16(PIXC_AVSTART)
+#define bfin_write_PIXC_AVSTART(val)	bfin_write16(PIXC_AVSTART, val)
+#define bfin_read_PIXC_AVEND()		bfin_read16(PIXC_AVEND)
+#define bfin_write_PIXC_AVEND(val)	bfin_write16(PIXC_AVEND, val)
+#define bfin_read_PIXC_ATRANSP()	bfin_read16(PIXC_ATRANSP)
+#define bfin_write_PIXC_ATRANSP(val)	bfin_write16(PIXC_ATRANSP, val)
+#define bfin_read_PIXC_BHSTART()	bfin_read16(PIXC_BHSTART)
+#define bfin_write_PIXC_BHSTART(val)	bfin_write16(PIXC_BHSTART, val)
+#define bfin_read_PIXC_BHEND()		bfin_read16(PIXC_BHEND)
+#define bfin_write_PIXC_BHEND(val)	bfin_write16(PIXC_BHEND, val)
+#define bfin_read_PIXC_BVSTART()	bfin_read16(PIXC_BVSTART)
+#define bfin_write_PIXC_BVSTART(val)	bfin_write16(PIXC_BVSTART, val)
+#define bfin_read_PIXC_BVEND()		bfin_read16(PIXC_BVEND)
+#define bfin_write_PIXC_BVEND(val)	bfin_write16(PIXC_BVEND, val)
+#define bfin_read_PIXC_BTRANSP()	bfin_read16(PIXC_BTRANSP)
+#define bfin_write_PIXC_BTRANSP(val)	bfin_write16(PIXC_BTRANSP, val)
+#define bfin_read_PIXC_INTRSTAT()	bfin_read16(PIXC_INTRSTAT)
+#define bfin_write_PIXC_INTRSTAT(val)	bfin_write16(PIXC_INTRSTAT, val)
+#define bfin_read_PIXC_RYCON()		bfin_read32(PIXC_RYCON)
+#define bfin_write_PIXC_RYCON(val)	bfin_write32(PIXC_RYCON, val)
+#define bfin_read_PIXC_GUCON()		bfin_read32(PIXC_GUCON)
+#define bfin_write_PIXC_GUCON(val)	bfin_write32(PIXC_GUCON, val)
+#define bfin_read_PIXC_BVCON()		bfin_read32(PIXC_BVCON)
+#define bfin_write_PIXC_BVCON(val)	bfin_write32(PIXC_BVCON, val)
+#define bfin_read_PIXC_CCBIAS()		bfin_read32(PIXC_CCBIAS)
+#define bfin_write_PIXC_CCBIAS(val)	bfin_write32(PIXC_CCBIAS, val)
+#define bfin_read_PIXC_TC()		bfin_read32(PIXC_TC)
+#define bfin_write_PIXC_TC(val)		bfin_write32(PIXC_TC, val)
+
+/* Handshake MDMA 0 Registers */
+
+#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
+#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
+#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
+#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
+#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
+#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
+#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
+#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
+#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
+#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
+#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
+#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
+#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
+#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
+
+/* Handshake MDMA 1 Registers */
+
+#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
+#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
+#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
+#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
+#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
+#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
+#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
+#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
+#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
+#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
+#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
+#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
+#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
+#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
+
+#endif /* _CDEF_BF549_H */
diff --git a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
new file mode 100644
index 0000000..98d35a9
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
@@ -0,0 +1,2752 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/cdefBF54x_base.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF54X_H
+#define _CDEF_BF54X_H
+
+#include "defBF54x_base.h"
+#include <asm/system.h>
+
+/* ************************************************************** */
+/* SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF54x    */
+/* ************************************************************** */
+
+/* PLL Registers */
+
+#define bfin_read_PLL_CTL()		bfin_read16(PLL_CTL)
+#define bfin_write_PLL_CTL(val)		bfin_write16(PLL_CTL, val)
+#define bfin_read_PLL_DIV()		bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val)		bfin_write16(PLL_DIV, val)
+#define bfin_read_VR_CTL()		bfin_read16(VR_CTL)
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1, iwr2;
+
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	iwr2 = bfin_read32(SIC_IWR2);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+	bfin_write32(SIC_IWR2, 0);
+
+	bfin_write16(VR_CTL, val);
+	__builtin_bfin_ssync();
+
+	local_irq_save(flags);
+	asm("IDLE;");
+	local_irq_restore(flags);
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	bfin_write32(SIC_IWR2, iwr2);
+}
+#define bfin_read_PLL_STAT()		bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val)	bfin_write16(PLL_STAT, val)
+#define bfin_read_PLL_LOCKCNT()		bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val)	bfin_write16(PLL_LOCKCNT, val)
+
+/* Debug/MP/Emulation Registers (0xFFC00014 - 0xFFC00014) */
+
+#define bfin_read_CHIPID()		bfin_read32(CHIPID)
+#define bfin_write_CHIPID(val)		bfin_write32(CHIPID, val)
+
+/* System Reset and Interrubfin_read_()t Controller (0xFFC00100 - 0xFFC00104) */
+
+#define bfin_read_SWRST()		bfin_read16(SWRST)
+#define bfin_write_SWRST(val)		bfin_write16(SWRST, val)
+#define bfin_read_SYSCR()		bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val)		bfin_write16(SYSCR, val)
+
+/* SIC Registers */
+
+#define bfin_read_SIC_IMASK0()		bfin_read32(SIC_IMASK0)
+#define bfin_write_SIC_IMASK0(val)	bfin_write32(SIC_IMASK0, val)
+#define bfin_read_SIC_IMASK1()		bfin_read32(SIC_IMASK1)
+#define bfin_write_SIC_IMASK1(val)	bfin_write32(SIC_IMASK1, val)
+#define bfin_read_SIC_IMASK2()		bfin_read32(SIC_IMASK2)
+#define bfin_write_SIC_IMASK2(val)	bfin_write32(SIC_IMASK2, val)
+#define bfin_read_SIC_IMASK(x)		bfin_read32(SIC_IMASK0 + (x << 2))
+#define bfin_write_SIC_IMASK(x, val)	bfin_write32((SIC_IMASK0 + (x << 2)), val)
+
+#define bfin_read_SIC_ISR0()		bfin_read32(SIC_ISR0)
+#define bfin_write_SIC_ISR0(val)	bfin_write32(SIC_ISR0, val)
+#define bfin_read_SIC_ISR1()		bfin_read32(SIC_ISR1)
+#define bfin_write_SIC_ISR1(val)	bfin_write32(SIC_ISR1, val)
+#define bfin_read_SIC_ISR2()		bfin_read32(SIC_ISR2)
+#define bfin_write_SIC_ISR2(val)	bfin_write32(SIC_ISR2, val)
+#define bfin_read_SIC_ISR(x)		bfin_read32(SIC_ISR0 + (x << 2))
+#define bfin_write_SIC_ISR(x, val)	bfin_write32((SIC_ISR0 + (x << 2)), val)
+
+#define bfin_read_SIC_IWR0()		bfin_read32(SIC_IWR0)
+#define bfin_write_SIC_IWR0(val)	bfin_write32(SIC_IWR0, val)
+#define bfin_read_SIC_IWR1()		bfin_read32(SIC_IWR1)
+#define bfin_write_SIC_IWR1(val)	bfin_write32(SIC_IWR1, val)
+#define bfin_read_SIC_IWR2()		bfin_read32(SIC_IWR2)
+#define bfin_write_SIC_IWR2(val)	bfin_write32(SIC_IWR2, val)
+#define bfin_read_SIC_IAR0()		bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val)	bfin_write32(SIC_IAR0, val)
+#define bfin_read_SIC_IAR1()		bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val)	bfin_write32(SIC_IAR1, val)
+#define bfin_read_SIC_IAR2()		bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val)	bfin_write32(SIC_IAR2, val)
+#define bfin_read_SIC_IAR3()		bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val)	bfin_write32(SIC_IAR3, val)
+#define bfin_read_SIC_IAR4()		bfin_read32(SIC_IAR4)
+#define bfin_write_SIC_IAR4(val)	bfin_write32(SIC_IAR4, val)
+#define bfin_read_SIC_IAR5()		bfin_read32(SIC_IAR5)
+#define bfin_write_SIC_IAR5(val)	bfin_write32(SIC_IAR5, val)
+#define bfin_read_SIC_IAR6()		bfin_read32(SIC_IAR6)
+#define bfin_write_SIC_IAR6(val)	bfin_write32(SIC_IAR6, val)
+#define bfin_read_SIC_IAR7()		bfin_read32(SIC_IAR7)
+#define bfin_write_SIC_IAR7(val)	bfin_write32(SIC_IAR7, val)
+#define bfin_read_SIC_IAR8()		bfin_read32(SIC_IAR8)
+#define bfin_write_SIC_IAR8(val)	bfin_write32(SIC_IAR8, val)
+#define bfin_read_SIC_IAR9()		bfin_read32(SIC_IAR9)
+#define bfin_write_SIC_IAR9(val)	bfin_write32(SIC_IAR9, val)
+#define bfin_read_SIC_IAR10()		bfin_read32(SIC_IAR10)
+#define bfin_write_SIC_IAR10(val)	bfin_write32(SIC_IAR10, val)
+#define bfin_read_SIC_IAR11()		bfin_read32(SIC_IAR11)
+#define bfin_write_SIC_IAR11(val)	bfin_write32(SIC_IAR11, val)
+
+/* Watchdog Timer Registers */
+
+#define bfin_read_WDOG_CTL()		bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val)	bfin_write16(WDOG_CTL, val)
+#define bfin_read_WDOG_CNT()		bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val)	bfin_write32(WDOG_CNT, val)
+#define bfin_read_WDOG_STAT()		bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val)	bfin_write32(WDOG_STAT, val)
+
+/* RTC Registers */
+
+#define bfin_read_RTC_STAT()		bfin_read32(RTC_STAT)
+#define bfin_write_RTC_STAT(val)	bfin_write32(RTC_STAT, val)
+#define bfin_read_RTC_ICTL()		bfin_read16(RTC_ICTL)
+#define bfin_write_RTC_ICTL(val)	bfin_write16(RTC_ICTL, val)
+#define bfin_read_RTC_ISTAT()		bfin_read16(RTC_ISTAT)
+#define bfin_write_RTC_ISTAT(val)	bfin_write16(RTC_ISTAT, val)
+#define bfin_read_RTC_SWCNT()		bfin_read16(RTC_SWCNT)
+#define bfin_write_RTC_SWCNT(val)	bfin_write16(RTC_SWCNT, val)
+#define bfin_read_RTC_ALARM()		bfin_read32(RTC_ALARM)
+#define bfin_write_RTC_ALARM(val)	bfin_write32(RTC_ALARM, val)
+#define bfin_read_RTC_PREN()		bfin_read16(RTC_PREN)
+#define bfin_write_RTC_PREN(val)	bfin_write16(RTC_PREN, val)
+
+/* UART0 Registers */
+
+#define bfin_read_UART0_DLL()		bfin_read16(UART0_DLL)
+#define bfin_write_UART0_DLL(val)	bfin_write16(UART0_DLL, val)
+#define bfin_read_UART0_DLH()		bfin_read16(UART0_DLH)
+#define bfin_write_UART0_DLH(val)	bfin_write16(UART0_DLH, val)
+#define bfin_read_UART0_GCTL()		bfin_read16(UART0_GCTL)
+#define bfin_write_UART0_GCTL(val)	bfin_write16(UART0_GCTL, val)
+#define bfin_read_UART0_LCR()		bfin_read16(UART0_LCR)
+#define bfin_write_UART0_LCR(val)	bfin_write16(UART0_LCR, val)
+#define bfin_read_UART0_MCR()		bfin_read16(UART0_MCR)
+#define bfin_write_UART0_MCR(val)	bfin_write16(UART0_MCR, val)
+#define bfin_read_UART0_LSR()		bfin_read16(UART0_LSR)
+#define bfin_write_UART0_LSR(val)	bfin_write16(UART0_LSR, val)
+#define bfin_read_UART0_MSR()		bfin_read16(UART0_MSR)
+#define bfin_write_UART0_MSR(val)	bfin_write16(UART0_MSR, val)
+#define bfin_read_UART0_SCR()		bfin_read16(UART0_SCR)
+#define bfin_write_UART0_SCR(val)	bfin_write16(UART0_SCR, val)
+#define bfin_read_UART0_IER_SET()	bfin_read16(UART0_IER_SET)
+#define bfin_write_UART0_IER_SET(val)	bfin_write16(UART0_IER_SET, val)
+#define bfin_read_UART0_IER_CLEAR()	bfin_read16(UART0_IER_CLEAR)
+#define bfin_write_UART0_IER_CLEAR(val)	bfin_write16(UART0_IER_CLEAR, val)
+#define bfin_read_UART0_THR()		bfin_read16(UART0_THR)
+#define bfin_write_UART0_THR(val)	bfin_write16(UART0_THR, val)
+#define bfin_read_UART0_RBR()		bfin_read16(UART0_RBR)
+#define bfin_write_UART0_RBR(val)	bfin_write16(UART0_RBR, val)
+
+/* SPI0 Registers */
+
+#define bfin_read_SPI0_CTL()		bfin_read16(SPI0_CTL)
+#define bfin_write_SPI0_CTL(val)	bfin_write16(SPI0_CTL, val)
+#define bfin_read_SPI0_FLG()		bfin_read16(SPI0_FLG)
+#define bfin_write_SPI0_FLG(val)	bfin_write16(SPI0_FLG, val)
+#define bfin_read_SPI0_STAT()		bfin_read16(SPI0_STAT)
+#define bfin_write_SPI0_STAT(val)	bfin_write16(SPI0_STAT, val)
+#define bfin_read_SPI0_TDBR()		bfin_read16(SPI0_TDBR)
+#define bfin_write_SPI0_TDBR(val)	bfin_write16(SPI0_TDBR, val)
+#define bfin_read_SPI0_RDBR()		bfin_read16(SPI0_RDBR)
+#define bfin_write_SPI0_RDBR(val)	bfin_write16(SPI0_RDBR, val)
+#define bfin_read_SPI0_BAUD()		bfin_read16(SPI0_BAUD)
+#define bfin_write_SPI0_BAUD(val)	bfin_write16(SPI0_BAUD, val)
+#define bfin_read_SPI0_SHADOW()		bfin_read16(SPI0_SHADOW)
+#define bfin_write_SPI0_SHADOW(val)	bfin_write16(SPI0_SHADOW, val)
+
+/* Timer Groubfin_read_() of 3 registers are not defined in the shared file because they are not available on the ADSP-BF542 processor */
+
+/* Two Wire Interface Registers (TWI0) */
+
+#define bfin_read_TWI0_CLKDIV()			bfin_read16(TWI0_CLKDIV)
+#define bfin_write_TWI0_CLKDIV(val)		bfin_write16(TWI0_CLKDIV, val)
+#define bfin_read_TWI0_CONTROL()		bfin_read16(TWI0_CONTROL)
+#define bfin_write_TWI0_CONTROL(val)		bfin_write16(TWI0_CONTROL, val)
+#define bfin_read_TWI0_SLAVE_CTRL()		bfin_read16(TWI0_SLAVE_CTRL)
+#define bfin_write_TWI0_SLAVE_CTRL(val)		bfin_write16(TWI0_SLAVE_CTRL, val)
+#define bfin_read_TWI0_SLAVE_STAT()		bfin_read16(TWI0_SLAVE_STAT)
+#define bfin_write_TWI0_SLAVE_STAT(val)		bfin_write16(TWI0_SLAVE_STAT, val)
+#define bfin_read_TWI0_SLAVE_ADDR()		bfin_read16(TWI0_SLAVE_ADDR)
+#define bfin_write_TWI0_SLAVE_ADDR(val)		bfin_write16(TWI0_SLAVE_ADDR, val)
+#define bfin_read_TWI0_MASTER_CTRL()		bfin_read16(TWI0_MASTER_CTRL)
+#define bfin_write_TWI0_MASTER_CTRL(val)	bfin_write16(TWI0_MASTER_CTRL, val)
+#define bfin_read_TWI0_MASTER_STAT()		bfin_read16(TWI0_MASTER_STAT)
+#define bfin_write_TWI0_MASTER_STAT(val)	bfin_write16(TWI0_MASTER_STAT, val)
+#define bfin_read_TWI0_MASTER_ADDR()		bfin_read16(TWI0_MASTER_ADDR)
+#define bfin_write_TWI0_MASTER_ADDR(val)	bfin_write16(TWI0_MASTER_ADDR, val)
+#define bfin_read_TWI0_INT_STAT()		bfin_read16(TWI0_INT_STAT)
+#define bfin_write_TWI0_INT_STAT(val)		bfin_write16(TWI0_INT_STAT, val)
+#define bfin_read_TWI0_INT_MASK()		bfin_read16(TWI0_INT_MASK)
+#define bfin_write_TWI0_INT_MASK(val)		bfin_write16(TWI0_INT_MASK, val)
+#define bfin_read_TWI0_FIFO_CTRL()		bfin_read16(TWI0_FIFO_CTRL)
+#define bfin_write_TWI0_FIFO_CTRL(val)		bfin_write16(TWI0_FIFO_CTRL, val)
+#define bfin_read_TWI0_FIFO_STAT()		bfin_read16(TWI0_FIFO_STAT)
+#define bfin_write_TWI0_FIFO_STAT(val)		bfin_write16(TWI0_FIFO_STAT, val)
+#define bfin_read_TWI0_XMT_DATA8()		bfin_read16(TWI0_XMT_DATA8)
+#define bfin_write_TWI0_XMT_DATA8(val)		bfin_write16(TWI0_XMT_DATA8, val)
+#define bfin_read_TWI0_XMT_DATA16()		bfin_read16(TWI0_XMT_DATA16)
+#define bfin_write_TWI0_XMT_DATA16(val)		bfin_write16(TWI0_XMT_DATA16, val)
+#define bfin_read_TWI0_RCV_DATA8()		bfin_read16(TWI0_RCV_DATA8)
+#define bfin_write_TWI0_RCV_DATA8(val)		bfin_write16(TWI0_RCV_DATA8, val)
+#define bfin_read_TWI0_RCV_DATA16()		bfin_read16(TWI0_RCV_DATA16)
+#define bfin_write_TWI0_RCV_DATA16(val)		bfin_write16(TWI0_RCV_DATA16, val)
+
+/* SPORT0 is not defined in the shared file because it is not available on the ADSP-BF542 and ADSP-BF544 bfin_read_()rocessors */
+
+/* SPORT1 Registers */
+
+#define bfin_read_SPORT1_TCR1()		bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val)	bfin_write16(SPORT1_TCR1, val)
+#define bfin_read_SPORT1_TCR2()		bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val)	bfin_write16(SPORT1_TCR2, val)
+#define bfin_read_SPORT1_TCLKDIV()	bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val)	bfin_write16(SPORT1_TCLKDIV, val)
+#define bfin_read_SPORT1_TFSDIV()	bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val)	bfin_write16(SPORT1_TFSDIV, val)
+#define bfin_read_SPORT1_TX()		bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val)	bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX()		bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val)	bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_RCR1()		bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val)	bfin_write16(SPORT1_RCR1, val)
+#define bfin_read_SPORT1_RCR2()		bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val)	bfin_write16(SPORT1_RCR2, val)
+#define bfin_read_SPORT1_RCLKDIV()	bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val)	bfin_write16(SPORT1_RCLKDIV, val)
+#define bfin_read_SPORT1_RFSDIV()	bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val)	bfin_write16(SPORT1_RFSDIV, val)
+#define bfin_read_SPORT1_STAT()		bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val)	bfin_write16(SPORT1_STAT, val)
+#define bfin_read_SPORT1_CHNL()		bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val)	bfin_write16(SPORT1_CHNL, val)
+#define bfin_read_SPORT1_MCMC1()	bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val)	bfin_write16(SPORT1_MCMC1, val)
+#define bfin_read_SPORT1_MCMC2()	bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val)	bfin_write16(SPORT1_MCMC2, val)
+#define bfin_read_SPORT1_MTCS0()	bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val)	bfin_write32(SPORT1_MTCS0, val)
+#define bfin_read_SPORT1_MTCS1()	bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val)	bfin_write32(SPORT1_MTCS1, val)
+#define bfin_read_SPORT1_MTCS2()	bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val)	bfin_write32(SPORT1_MTCS2, val)
+#define bfin_read_SPORT1_MTCS3()	bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val)	bfin_write32(SPORT1_MTCS3, val)
+#define bfin_read_SPORT1_MRCS0()	bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val)	bfin_write32(SPORT1_MRCS0, val)
+#define bfin_read_SPORT1_MRCS1()	bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val)	bfin_write32(SPORT1_MRCS1, val)
+#define bfin_read_SPORT1_MRCS2()	bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val)	bfin_write32(SPORT1_MRCS2, val)
+#define bfin_read_SPORT1_MRCS3()	bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val)	bfin_write32(SPORT1_MRCS3, val)
+
+/* Asynchronous Memory Control Registers */
+
+#define bfin_read_EBIU_AMGCTL()		bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val)	bfin_write16(EBIU_AMGCTL, val)
+#define bfin_read_EBIU_AMBCTL0()	bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val)	bfin_write32(EBIU_AMBCTL0, val)
+#define bfin_read_EBIU_AMBCTL1()	bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val)	bfin_write32(EBIU_AMBCTL1, val)
+#define bfin_read_EBIU_MBSCTL()		bfin_read16(EBIU_MBSCTL)
+#define bfin_write_EBIU_MBSCTL(val)	bfin_write16(EBIU_MBSCTL, val)
+#define bfin_read_EBIU_ARBSTAT()	bfin_read32(EBIU_ARBSTAT)
+#define bfin_write_EBIU_ARBSTAT(val)	bfin_write32(EBIU_ARBSTAT, val)
+#define bfin_read_EBIU_MODE()		bfin_read32(EBIU_MODE)
+#define bfin_write_EBIU_MODE(val)	bfin_write32(EBIU_MODE, val)
+#define bfin_read_EBIU_FCTL()		bfin_read16(EBIU_FCTL)
+#define bfin_write_EBIU_FCTL(val)	bfin_write16(EBIU_FCTL, val)
+
+/* DDR Memory Control Registers */
+
+#define bfin_read_EBIU_DDRCTL0()	bfin_read32(EBIU_DDRCTL0)
+#define bfin_write_EBIU_DDRCTL0(val)	bfin_write32(EBIU_DDRCTL0, val)
+#define bfin_read_EBIU_DDRCTL1()	bfin_read32(EBIU_DDRCTL1)
+#define bfin_write_EBIU_DDRCTL1(val)	bfin_write32(EBIU_DDRCTL1, val)
+#define bfin_read_EBIU_DDRCTL2()	bfin_read32(EBIU_DDRCTL2)
+#define bfin_write_EBIU_DDRCTL2(val)	bfin_write32(EBIU_DDRCTL2, val)
+#define bfin_read_EBIU_DDRCTL3()	bfin_read32(EBIU_DDRCTL3)
+#define bfin_write_EBIU_DDRCTL3(val)	bfin_write32(EBIU_DDRCTL3, val)
+#define bfin_read_EBIU_DDRQUE()		bfin_read32(EBIU_DDRQUE)
+#define bfin_write_EBIU_DDRQUE(val)	bfin_write32(EBIU_DDRQUE, val)
+#define bfin_read_EBIU_ERRADD() 	bfin_read32(EBIU_ERRADD)
+#define bfin_write_EBIU_ERRADD(val) 	bfin_write32(EBIU_ERRADD)
+#define bfin_read_EBIU_ERRMST()		bfin_read16(EBIU_ERRMST)
+#define bfin_write_EBIU_ERRMST(val)	bfin_write16(EBIU_ERRMST, val)
+#define bfin_read_EBIU_RSTCTL()		bfin_read16(EBIU_RSTCTL)
+#define bfin_write_EBIU_RSTCTL(val)	bfin_write16(EBIU_RSTCTL, val)
+
+/* DDR BankRead and Write Count Registers */
+
+#define bfin_read_EBIU_DDRBRC0()	bfin_read32(EBIU_DDRBRC0)
+#define bfin_write_EBIU_DDRBRC0(val)	bfin_write32(EBIU_DDRBRC0, val)
+#define bfin_read_EBIU_DDRBRC1()	bfin_read32(EBIU_DDRBRC1)
+#define bfin_write_EBIU_DDRBRC1(val)	bfin_write32(EBIU_DDRBRC1, val)
+#define bfin_read_EBIU_DDRBRC2()	bfin_read32(EBIU_DDRBRC2)
+#define bfin_write_EBIU_DDRBRC2(val)	bfin_write32(EBIU_DDRBRC2, val)
+#define bfin_read_EBIU_DDRBRC3()	bfin_read32(EBIU_DDRBRC3)
+#define bfin_write_EBIU_DDRBRC3(val)	bfin_write32(EBIU_DDRBRC3, val)
+#define bfin_read_EBIU_DDRBRC4()	bfin_read32(EBIU_DDRBRC4)
+#define bfin_write_EBIU_DDRBRC4(val)	bfin_write32(EBIU_DDRBRC4, val)
+#define bfin_read_EBIU_DDRBRC5()	bfin_read32(EBIU_DDRBRC5)
+#define bfin_write_EBIU_DDRBRC5(val)	bfin_write32(EBIU_DDRBRC5, val)
+#define bfin_read_EBIU_DDRBRC6()	bfin_read32(EBIU_DDRBRC6)
+#define bfin_write_EBIU_DDRBRC6(val)	bfin_write32(EBIU_DDRBRC6, val)
+#define bfin_read_EBIU_DDRBRC7()	bfin_read32(EBIU_DDRBRC7)
+#define bfin_write_EBIU_DDRBRC7(val)	bfin_write32(EBIU_DDRBRC7, val)
+#define bfin_read_EBIU_DDRBWC0()	bfin_read32(EBIU_DDRBWC0)
+#define bfin_write_EBIU_DDRBWC0(val)	bfin_write32(EBIU_DDRBWC0, val)
+#define bfin_read_EBIU_DDRBWC1()	bfin_read32(EBIU_DDRBWC1)
+#define bfin_write_EBIU_DDRBWC1(val)	bfin_write32(EBIU_DDRBWC1, val)
+#define bfin_read_EBIU_DDRBWC2()	bfin_read32(EBIU_DDRBWC2)
+#define bfin_write_EBIU_DDRBWC2(val)	bfin_write32(EBIU_DDRBWC2, val)
+#define bfin_read_EBIU_DDRBWC3()	bfin_read32(EBIU_DDRBWC3)
+#define bfin_write_EBIU_DDRBWC3(val)	bfin_write32(EBIU_DDRBWC3, val)
+#define bfin_read_EBIU_DDRBWC4()	bfin_read32(EBIU_DDRBWC4)
+#define bfin_write_EBIU_DDRBWC4(val)	bfin_write32(EBIU_DDRBWC4, val)
+#define bfin_read_EBIU_DDRBWC5()	bfin_read32(EBIU_DDRBWC5)
+#define bfin_write_EBIU_DDRBWC5(val)	bfin_write32(EBIU_DDRBWC5, val)
+#define bfin_read_EBIU_DDRBWC6()	bfin_read32(EBIU_DDRBWC6)
+#define bfin_write_EBIU_DDRBWC6(val)	bfin_write32(EBIU_DDRBWC6, val)
+#define bfin_read_EBIU_DDRBWC7()	bfin_read32(EBIU_DDRBWC7)
+#define bfin_write_EBIU_DDRBWC7(val)	bfin_write32(EBIU_DDRBWC7, val)
+#define bfin_read_EBIU_DDRACCT()	bfin_read32(EBIU_DDRACCT)
+#define bfin_write_EBIU_DDRACCT(val)	bfin_write32(EBIU_DDRACCT, val)
+#define bfin_read_EBIU_DDRTACT()	bfin_read32(EBIU_DDRTACT)
+#define bfin_write_EBIU_DDRTACT(val)	bfin_write32(EBIU_DDRTACT, val)
+#define bfin_read_EBIU_DDRARCT()	bfin_read32(EBIU_DDRARCT)
+#define bfin_write_EBIU_DDRARCT(val)	bfin_write32(EBIU_DDRARCT, val)
+#define bfin_read_EBIU_DDRGC0()		bfin_read32(EBIU_DDRGC0)
+#define bfin_write_EBIU_DDRGC0(val)	bfin_write32(EBIU_DDRGC0, val)
+#define bfin_read_EBIU_DDRGC1()		bfin_read32(EBIU_DDRGC1)
+#define bfin_write_EBIU_DDRGC1(val)	bfin_write32(EBIU_DDRGC1, val)
+#define bfin_read_EBIU_DDRGC2()		bfin_read32(EBIU_DDRGC2)
+#define bfin_write_EBIU_DDRGC2(val)	bfin_write32(EBIU_DDRGC2, val)
+#define bfin_read_EBIU_DDRGC3()		bfin_read32(EBIU_DDRGC3)
+#define bfin_write_EBIU_DDRGC3(val)	bfin_write32(EBIU_DDRGC3, val)
+#define bfin_read_EBIU_DDRMCEN()	bfin_read32(EBIU_DDRMCEN)
+#define bfin_write_EBIU_DDRMCEN(val)	bfin_write32(EBIU_DDRMCEN, val)
+#define bfin_read_EBIU_DDRMCCL()	bfin_read32(EBIU_DDRMCCL)
+#define bfin_write_EBIU_DDRMCCL(val)	bfin_write32(EBIU_DDRMCCL, val)
+
+/* DMAC0 Registers */
+
+#define bfin_read_DMAC0_TCPER()		bfin_read16(DMAC0_TCPER)
+#define bfin_write_DMAC0_TCPER(val)	bfin_write16(DMAC0_TCPER, val)
+#define bfin_read_DMAC0_TCCNT()		bfin_read16(DMAC0_TCCNT)
+#define bfin_write_DMAC0_TCCNT(val)	bfin_write16(DMAC0_TCCNT, val)
+
+/* DMA Channel 0 Registers */
+
+#define bfin_read_DMA0_NEXT_DESC_PTR() 		bfin_read32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val) 	bfin_write32(DMA0_NEXT_DESC_PTR)
+#define bfin_read_DMA0_START_ADDR() 		bfin_read32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val) 	bfin_write32(DMA0_START_ADDR)
+#define bfin_read_DMA0_CONFIG()			bfin_read16(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val)		bfin_write16(DMA0_CONFIG, val)
+#define bfin_read_DMA0_X_COUNT()		bfin_read16(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val)		bfin_write16(DMA0_X_COUNT, val)
+#define bfin_read_DMA0_X_MODIFY()		bfin_read16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val) 		bfin_write16(DMA0_X_MODIFY)
+#define bfin_read_DMA0_Y_COUNT()		bfin_read16(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val)		bfin_write16(DMA0_Y_COUNT, val)
+#define bfin_read_DMA0_Y_MODIFY()		bfin_read16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val) 		bfin_write16(DMA0_Y_MODIFY)
+#define bfin_read_DMA0_CURR_DESC_PTR() 		bfin_read32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val) 	bfin_write32(DMA0_CURR_DESC_PTR)
+#define bfin_read_DMA0_CURR_ADDR() 		bfin_read32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val) 		bfin_write32(DMA0_CURR_ADDR)
+#define bfin_read_DMA0_IRQ_STATUS()		bfin_read16(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val)		bfin_write16(DMA0_IRQ_STATUS, val)
+#define bfin_read_DMA0_PERIPHERAL_MAP()		bfin_read16(DMA0_PERIPHERAL_MAP)
+#define bfin_write_DMA0_PERIPHERAL_MAP(val)	bfin_write16(DMA0_PERIPHERAL_MAP, val)
+#define bfin_read_DMA0_CURR_X_COUNT()		bfin_read16(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val)	bfin_write16(DMA0_CURR_X_COUNT, val)
+#define bfin_read_DMA0_CURR_Y_COUNT()		bfin_read16(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val)	bfin_write16(DMA0_CURR_Y_COUNT, val)
+
+/* DMA Channel 1 Registers */
+
+#define bfin_read_DMA1_NEXT_DESC_PTR() 		bfin_read32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val) 	bfin_write32(DMA1_NEXT_DESC_PTR)
+#define bfin_read_DMA1_START_ADDR() 		bfin_read32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val) 	bfin_write32(DMA1_START_ADDR)
+#define bfin_read_DMA1_CONFIG()			bfin_read16(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val)		bfin_write16(DMA1_CONFIG, val)
+#define bfin_read_DMA1_X_COUNT()		bfin_read16(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val)		bfin_write16(DMA1_X_COUNT, val)
+#define bfin_read_DMA1_X_MODIFY()		bfin_read16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val) 		bfin_write16(DMA1_X_MODIFY)
+#define bfin_read_DMA1_Y_COUNT()		bfin_read16(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val)		bfin_write16(DMA1_Y_COUNT, val)
+#define bfin_read_DMA1_Y_MODIFY()		bfin_read16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val) 		bfin_write16(DMA1_Y_MODIFY)
+#define bfin_read_DMA1_CURR_DESC_PTR() 		bfin_read32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val) 	bfin_write32(DMA1_CURR_DESC_PTR)
+#define bfin_read_DMA1_CURR_ADDR() 		bfin_read32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val) 		bfin_write32(DMA1_CURR_ADDR)
+#define bfin_read_DMA1_IRQ_STATUS()		bfin_read16(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val)		bfin_write16(DMA1_IRQ_STATUS, val)
+#define bfin_read_DMA1_PERIPHERAL_MAP()		bfin_read16(DMA1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_PERIPHERAL_MAP(val)	bfin_write16(DMA1_PERIPHERAL_MAP, val)
+#define bfin_read_DMA1_CURR_X_COUNT()		bfin_read16(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val)	bfin_write16(DMA1_CURR_X_COUNT, val)
+#define bfin_read_DMA1_CURR_Y_COUNT()		bfin_read16(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val)	bfin_write16(DMA1_CURR_Y_COUNT, val)
+
+/* DMA Channel 2 Registers */
+
+#define bfin_read_DMA2_NEXT_DESC_PTR() 		bfin_read32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val) 	bfin_write32(DMA2_NEXT_DESC_PTR)
+#define bfin_read_DMA2_START_ADDR() 		bfin_read32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val) 	bfin_write32(DMA2_START_ADDR)
+#define bfin_read_DMA2_CONFIG()			bfin_read16(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val)		bfin_write16(DMA2_CONFIG, val)
+#define bfin_read_DMA2_X_COUNT()		bfin_read16(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val)		bfin_write16(DMA2_X_COUNT, val)
+#define bfin_read_DMA2_X_MODIFY()		bfin_read16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val) 		bfin_write16(DMA2_X_MODIFY)
+#define bfin_read_DMA2_Y_COUNT()		bfin_read16(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val)		bfin_write16(DMA2_Y_COUNT, val)
+#define bfin_read_DMA2_Y_MODIFY()		bfin_read16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val) 		bfin_write16(DMA2_Y_MODIFY)
+#define bfin_read_DMA2_CURR_DESC_PTR() 		bfin_read32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val) 	bfin_write32(DMA2_CURR_DESC_PTR)
+#define bfin_read_DMA2_CURR_ADDR() 		bfin_read32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val) 		bfin_write32(DMA2_CURR_ADDR)
+#define bfin_read_DMA2_IRQ_STATUS()		bfin_read16(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val)		bfin_write16(DMA2_IRQ_STATUS, val)
+#define bfin_read_DMA2_PERIPHERAL_MAP()		bfin_read16(DMA2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_PERIPHERAL_MAP(val)	bfin_write16(DMA2_PERIPHERAL_MAP, val)
+#define bfin_read_DMA2_CURR_X_COUNT()		bfin_read16(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val)	bfin_write16(DMA2_CURR_X_COUNT, val)
+#define bfin_read_DMA2_CURR_Y_COUNT()		bfin_read16(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val)	bfin_write16(DMA2_CURR_Y_COUNT, val)
+
+/* DMA Channel 3 Registers */
+
+#define bfin_read_DMA3_NEXT_DESC_PTR() 		bfin_read32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val) 	bfin_write32(DMA3_NEXT_DESC_PTR)
+#define bfin_read_DMA3_START_ADDR() 		bfin_read32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val) 	bfin_write32(DMA3_START_ADDR)
+#define bfin_read_DMA3_CONFIG()			bfin_read16(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val)		bfin_write16(DMA3_CONFIG, val)
+#define bfin_read_DMA3_X_COUNT()		bfin_read16(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val)		bfin_write16(DMA3_X_COUNT, val)
+#define bfin_read_DMA3_X_MODIFY()		bfin_read16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val) 		bfin_write16(DMA3_X_MODIFY)
+#define bfin_read_DMA3_Y_COUNT()		bfin_read16(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val)		bfin_write16(DMA3_Y_COUNT, val)
+#define bfin_read_DMA3_Y_MODIFY()		bfin_read16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val) 		bfin_write16(DMA3_Y_MODIFY)
+#define bfin_read_DMA3_CURR_DESC_PTR() 		bfin_read32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val) 	bfin_write32(DMA3_CURR_DESC_PTR)
+#define bfin_read_DMA3_CURR_ADDR() 		bfin_read32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val) 		bfin_write32(DMA3_CURR_ADDR)
+#define bfin_read_DMA3_IRQ_STATUS()		bfin_read16(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val)		bfin_write16(DMA3_IRQ_STATUS, val)
+#define bfin_read_DMA3_PERIPHERAL_MAP()		bfin_read16(DMA3_PERIPHERAL_MAP)
+#define bfin_write_DMA3_PERIPHERAL_MAP(val)	bfin_write16(DMA3_PERIPHERAL_MAP, val)
+#define bfin_read_DMA3_CURR_X_COUNT()		bfin_read16(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val)	bfin_write16(DMA3_CURR_X_COUNT, val)
+#define bfin_read_DMA3_CURR_Y_COUNT()		bfin_read16(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val)	bfin_write16(DMA3_CURR_Y_COUNT, val)
+
+/* DMA Channel 4 Registers */
+
+#define bfin_read_DMA4_NEXT_DESC_PTR() 		bfin_read32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val) 	bfin_write32(DMA4_NEXT_DESC_PTR)
+#define bfin_read_DMA4_START_ADDR() 		bfin_read32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val) 	bfin_write32(DMA4_START_ADDR)
+#define bfin_read_DMA4_CONFIG()			bfin_read16(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val)		bfin_write16(DMA4_CONFIG, val)
+#define bfin_read_DMA4_X_COUNT()		bfin_read16(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val)		bfin_write16(DMA4_X_COUNT, val)
+#define bfin_read_DMA4_X_MODIFY()		bfin_read16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val) 		bfin_write16(DMA4_X_MODIFY)
+#define bfin_read_DMA4_Y_COUNT()		bfin_read16(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val)		bfin_write16(DMA4_Y_COUNT, val)
+#define bfin_read_DMA4_Y_MODIFY()		bfin_read16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val) 		bfin_write16(DMA4_Y_MODIFY)
+#define bfin_read_DMA4_CURR_DESC_PTR() 		bfin_read32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val) 	bfin_write32(DMA4_CURR_DESC_PTR)
+#define bfin_read_DMA4_CURR_ADDR() 		bfin_read32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val) 		bfin_write32(DMA4_CURR_ADDR)
+#define bfin_read_DMA4_IRQ_STATUS()		bfin_read16(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val)		bfin_write16(DMA4_IRQ_STATUS, val)
+#define bfin_read_DMA4_PERIPHERAL_MAP()		bfin_read16(DMA4_PERIPHERAL_MAP)
+#define bfin_write_DMA4_PERIPHERAL_MAP(val)	bfin_write16(DMA4_PERIPHERAL_MAP, val)
+#define bfin_read_DMA4_CURR_X_COUNT()		bfin_read16(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val)	bfin_write16(DMA4_CURR_X_COUNT, val)
+#define bfin_read_DMA4_CURR_Y_COUNT()		bfin_read16(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val)	bfin_write16(DMA4_CURR_Y_COUNT, val)
+
+/* DMA Channel 5 Registers */
+
+#define bfin_read_DMA5_NEXT_DESC_PTR() 		bfin_read32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val) 	bfin_write32(DMA5_NEXT_DESC_PTR)
+#define bfin_read_DMA5_START_ADDR() 		bfin_read32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val) 	bfin_write32(DMA5_START_ADDR)
+#define bfin_read_DMA5_CONFIG()			bfin_read16(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val)		bfin_write16(DMA5_CONFIG, val)
+#define bfin_read_DMA5_X_COUNT()		bfin_read16(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val)		bfin_write16(DMA5_X_COUNT, val)
+#define bfin_read_DMA5_X_MODIFY()		bfin_read16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val) 		bfin_write16(DMA5_X_MODIFY)
+#define bfin_read_DMA5_Y_COUNT()		bfin_read16(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val)		bfin_write16(DMA5_Y_COUNT, val)
+#define bfin_read_DMA5_Y_MODIFY()		bfin_read16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val) 		bfin_write16(DMA5_Y_MODIFY)
+#define bfin_read_DMA5_CURR_DESC_PTR() 		bfin_read32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val) 	bfin_write32(DMA5_CURR_DESC_PTR)
+#define bfin_read_DMA5_CURR_ADDR() 		bfin_read32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val) 		bfin_write32(DMA5_CURR_ADDR)
+#define bfin_read_DMA5_IRQ_STATUS()		bfin_read16(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val)		bfin_write16(DMA5_IRQ_STATUS, val)
+#define bfin_read_DMA5_PERIPHERAL_MAP()		bfin_read16(DMA5_PERIPHERAL_MAP)
+#define bfin_write_DMA5_PERIPHERAL_MAP(val)	bfin_write16(DMA5_PERIPHERAL_MAP, val)
+#define bfin_read_DMA5_CURR_X_COUNT()		bfin_read16(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val)	bfin_write16(DMA5_CURR_X_COUNT, val)
+#define bfin_read_DMA5_CURR_Y_COUNT()		bfin_read16(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val)	bfin_write16(DMA5_CURR_Y_COUNT, val)
+
+/* DMA Channel 6 Registers */
+
+#define bfin_read_DMA6_NEXT_DESC_PTR() 		bfin_read32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val) 	bfin_write32(DMA6_NEXT_DESC_PTR)
+#define bfin_read_DMA6_START_ADDR() 		bfin_read32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val) 	bfin_write32(DMA6_START_ADDR)
+#define bfin_read_DMA6_CONFIG()			bfin_read16(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val)		bfin_write16(DMA6_CONFIG, val)
+#define bfin_read_DMA6_X_COUNT()		bfin_read16(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val)		bfin_write16(DMA6_X_COUNT, val)
+#define bfin_read_DMA6_X_MODIFY()		bfin_read16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val) 		bfin_write16(DMA6_X_MODIFY)
+#define bfin_read_DMA6_Y_COUNT()		bfin_read16(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val)		bfin_write16(DMA6_Y_COUNT, val)
+#define bfin_read_DMA6_Y_MODIFY()		bfin_read16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val) 		bfin_write16(DMA6_Y_MODIFY)
+#define bfin_read_DMA6_CURR_DESC_PTR() 		bfin_read32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val) 	bfin_write32(DMA6_CURR_DESC_PTR)
+#define bfin_read_DMA6_CURR_ADDR() 		bfin_read32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val) 		bfin_write32(DMA6_CURR_ADDR)
+#define bfin_read_DMA6_IRQ_STATUS()		bfin_read16(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val)		bfin_write16(DMA6_IRQ_STATUS, val)
+#define bfin_read_DMA6_PERIPHERAL_MAP()		bfin_read16(DMA6_PERIPHERAL_MAP)
+#define bfin_write_DMA6_PERIPHERAL_MAP(val)	bfin_write16(DMA6_PERIPHERAL_MAP, val)
+#define bfin_read_DMA6_CURR_X_COUNT()		bfin_read16(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val)	bfin_write16(DMA6_CURR_X_COUNT, val)
+#define bfin_read_DMA6_CURR_Y_COUNT()		bfin_read16(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val)	bfin_write16(DMA6_CURR_Y_COUNT, val)
+
+/* DMA Channel 7 Registers */
+
+#define bfin_read_DMA7_NEXT_DESC_PTR() 		bfin_read32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val) 	bfin_write32(DMA7_NEXT_DESC_PTR)
+#define bfin_read_DMA7_START_ADDR() 		bfin_read32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val) 	bfin_write32(DMA7_START_ADDR)
+#define bfin_read_DMA7_CONFIG()			bfin_read16(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val)		bfin_write16(DMA7_CONFIG, val)
+#define bfin_read_DMA7_X_COUNT()		bfin_read16(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val)		bfin_write16(DMA7_X_COUNT, val)
+#define bfin_read_DMA7_X_MODIFY()		bfin_read16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val) 		bfin_write16(DMA7_X_MODIFY)
+#define bfin_read_DMA7_Y_COUNT()		bfin_read16(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val)		bfin_write16(DMA7_Y_COUNT, val)
+#define bfin_read_DMA7_Y_MODIFY()		bfin_read16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val) 		bfin_write16(DMA7_Y_MODIFY)
+#define bfin_read_DMA7_CURR_DESC_PTR() 		bfin_read32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val) 	bfin_write32(DMA7_CURR_DESC_PTR)
+#define bfin_read_DMA7_CURR_ADDR() 		bfin_read32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val) 		bfin_write32(DMA7_CURR_ADDR)
+#define bfin_read_DMA7_IRQ_STATUS()		bfin_read16(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val)		bfin_write16(DMA7_IRQ_STATUS, val)
+#define bfin_read_DMA7_PERIPHERAL_MAP()		bfin_read16(DMA7_PERIPHERAL_MAP)
+#define bfin_write_DMA7_PERIPHERAL_MAP(val)	bfin_write16(DMA7_PERIPHERAL_MAP, val)
+#define bfin_read_DMA7_CURR_X_COUNT()		bfin_read16(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val)	bfin_write16(DMA7_CURR_X_COUNT, val)
+#define bfin_read_DMA7_CURR_Y_COUNT()		bfin_read16(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val)	bfin_write16(DMA7_CURR_Y_COUNT, val)
+
+/* DMA Channel 8 Registers */
+
+#define bfin_read_DMA8_NEXT_DESC_PTR() 		bfin_read32(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val) 	bfin_write32(DMA8_NEXT_DESC_PTR)
+#define bfin_read_DMA8_START_ADDR() 		bfin_read32(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val) 	bfin_write32(DMA8_START_ADDR)
+#define bfin_read_DMA8_CONFIG()			bfin_read16(DMA8_CONFIG)
+#define bfin_write_DMA8_CONFIG(val)		bfin_write16(DMA8_CONFIG, val)
+#define bfin_read_DMA8_X_COUNT()		bfin_read16(DMA8_X_COUNT)
+#define bfin_write_DMA8_X_COUNT(val)		bfin_write16(DMA8_X_COUNT, val)
+#define bfin_read_DMA8_X_MODIFY()		bfin_read16(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val) 		bfin_write16(DMA8_X_MODIFY)
+#define bfin_read_DMA8_Y_COUNT()		bfin_read16(DMA8_Y_COUNT)
+#define bfin_write_DMA8_Y_COUNT(val)		bfin_write16(DMA8_Y_COUNT, val)
+#define bfin_read_DMA8_Y_MODIFY()		bfin_read16(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val) 		bfin_write16(DMA8_Y_MODIFY)
+#define bfin_read_DMA8_CURR_DESC_PTR() 		bfin_read32(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val) 	bfin_write32(DMA8_CURR_DESC_PTR)
+#define bfin_read_DMA8_CURR_ADDR() 		bfin_read32(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val) 		bfin_write32(DMA8_CURR_ADDR)
+#define bfin_read_DMA8_IRQ_STATUS()		bfin_read16(DMA8_IRQ_STATUS)
+#define bfin_write_DMA8_IRQ_STATUS(val)		bfin_write16(DMA8_IRQ_STATUS, val)
+#define bfin_read_DMA8_PERIPHERAL_MAP()		bfin_read16(DMA8_PERIPHERAL_MAP)
+#define bfin_write_DMA8_PERIPHERAL_MAP(val)	bfin_write16(DMA8_PERIPHERAL_MAP, val)
+#define bfin_read_DMA8_CURR_X_COUNT()		bfin_read16(DMA8_CURR_X_COUNT)
+#define bfin_write_DMA8_CURR_X_COUNT(val)	bfin_write16(DMA8_CURR_X_COUNT, val)
+#define bfin_read_DMA8_CURR_Y_COUNT()		bfin_read16(DMA8_CURR_Y_COUNT)
+#define bfin_write_DMA8_CURR_Y_COUNT(val)	bfin_write16(DMA8_CURR_Y_COUNT, val)
+
+/* DMA Channel 9 Registers */
+
+#define bfin_read_DMA9_NEXT_DESC_PTR() 		bfin_read32(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val) 	bfin_write32(DMA9_NEXT_DESC_PTR)
+#define bfin_read_DMA9_START_ADDR() 		bfin_read32(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val) 	bfin_write32(DMA9_START_ADDR)
+#define bfin_read_DMA9_CONFIG()			bfin_read16(DMA9_CONFIG)
+#define bfin_write_DMA9_CONFIG(val)		bfin_write16(DMA9_CONFIG, val)
+#define bfin_read_DMA9_X_COUNT()		bfin_read16(DMA9_X_COUNT)
+#define bfin_write_DMA9_X_COUNT(val)		bfin_write16(DMA9_X_COUNT, val)
+#define bfin_read_DMA9_X_MODIFY()		bfin_read16(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val) 		bfin_write16(DMA9_X_MODIFY)
+#define bfin_read_DMA9_Y_COUNT()		bfin_read16(DMA9_Y_COUNT)
+#define bfin_write_DMA9_Y_COUNT(val)		bfin_write16(DMA9_Y_COUNT, val)
+#define bfin_read_DMA9_Y_MODIFY()		bfin_read16(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val) 		bfin_write16(DMA9_Y_MODIFY)
+#define bfin_read_DMA9_CURR_DESC_PTR() 		bfin_read32(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val) 	bfin_write32(DMA9_CURR_DESC_PTR)
+#define bfin_read_DMA9_CURR_ADDR() 		bfin_read32(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val) 		bfin_write32(DMA9_CURR_ADDR)
+#define bfin_read_DMA9_IRQ_STATUS()		bfin_read16(DMA9_IRQ_STATUS)
+#define bfin_write_DMA9_IRQ_STATUS(val)		bfin_write16(DMA9_IRQ_STATUS, val)
+#define bfin_read_DMA9_PERIPHERAL_MAP()		bfin_read16(DMA9_PERIPHERAL_MAP)
+#define bfin_write_DMA9_PERIPHERAL_MAP(val)	bfin_write16(DMA9_PERIPHERAL_MAP, val)
+#define bfin_read_DMA9_CURR_X_COUNT()		bfin_read16(DMA9_CURR_X_COUNT)
+#define bfin_write_DMA9_CURR_X_COUNT(val)	bfin_write16(DMA9_CURR_X_COUNT, val)
+#define bfin_read_DMA9_CURR_Y_COUNT()		bfin_read16(DMA9_CURR_Y_COUNT)
+#define bfin_write_DMA9_CURR_Y_COUNT(val)	bfin_write16(DMA9_CURR_Y_COUNT, val)
+
+/* DMA Channel 10 Registers */
+
+#define bfin_read_DMA10_NEXT_DESC_PTR() 	bfin_read32(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val) 	bfin_write32(DMA10_NEXT_DESC_PTR)
+#define bfin_read_DMA10_START_ADDR() 		bfin_read32(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val) 	bfin_write32(DMA10_START_ADDR)
+#define bfin_read_DMA10_CONFIG()		bfin_read16(DMA10_CONFIG)
+#define bfin_write_DMA10_CONFIG(val)		bfin_write16(DMA10_CONFIG, val)
+#define bfin_read_DMA10_X_COUNT()		bfin_read16(DMA10_X_COUNT)
+#define bfin_write_DMA10_X_COUNT(val)		bfin_write16(DMA10_X_COUNT, val)
+#define bfin_read_DMA10_X_MODIFY()		bfin_read16(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val) 		bfin_write16(DMA10_X_MODIFY)
+#define bfin_read_DMA10_Y_COUNT()		bfin_read16(DMA10_Y_COUNT)
+#define bfin_write_DMA10_Y_COUNT(val)		bfin_write16(DMA10_Y_COUNT, val)
+#define bfin_read_DMA10_Y_MODIFY()		bfin_read16(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val) 		bfin_write16(DMA10_Y_MODIFY)
+#define bfin_read_DMA10_CURR_DESC_PTR() 	bfin_read32(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val) 	bfin_write32(DMA10_CURR_DESC_PTR)
+#define bfin_read_DMA10_CURR_ADDR() 		bfin_read32(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val) 	bfin_write32(DMA10_CURR_ADDR)
+#define bfin_read_DMA10_IRQ_STATUS()		bfin_read16(DMA10_IRQ_STATUS)
+#define bfin_write_DMA10_IRQ_STATUS(val)	bfin_write16(DMA10_IRQ_STATUS, val)
+#define bfin_read_DMA10_PERIPHERAL_MAP()	bfin_read16(DMA10_PERIPHERAL_MAP)
+#define bfin_write_DMA10_PERIPHERAL_MAP(val)	bfin_write16(DMA10_PERIPHERAL_MAP, val)
+#define bfin_read_DMA10_CURR_X_COUNT()		bfin_read16(DMA10_CURR_X_COUNT)
+#define bfin_write_DMA10_CURR_X_COUNT(val)	bfin_write16(DMA10_CURR_X_COUNT, val)
+#define bfin_read_DMA10_CURR_Y_COUNT()		bfin_read16(DMA10_CURR_Y_COUNT)
+#define bfin_write_DMA10_CURR_Y_COUNT(val)	bfin_write16(DMA10_CURR_Y_COUNT, val)
+
+/* DMA Channel 11 Registers */
+
+#define bfin_read_DMA11_NEXT_DESC_PTR() 	bfin_read32(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val) 	bfin_write32(DMA11_NEXT_DESC_PTR)
+#define bfin_read_DMA11_START_ADDR() 		bfin_read32(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val) 	bfin_write32(DMA11_START_ADDR)
+#define bfin_read_DMA11_CONFIG()		bfin_read16(DMA11_CONFIG)
+#define bfin_write_DMA11_CONFIG(val)		bfin_write16(DMA11_CONFIG, val)
+#define bfin_read_DMA11_X_COUNT()		bfin_read16(DMA11_X_COUNT)
+#define bfin_write_DMA11_X_COUNT(val)		bfin_write16(DMA11_X_COUNT, val)
+#define bfin_read_DMA11_X_MODIFY()		bfin_read16(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val) 		bfin_write16(DMA11_X_MODIFY)
+#define bfin_read_DMA11_Y_COUNT()		bfin_read16(DMA11_Y_COUNT)
+#define bfin_write_DMA11_Y_COUNT(val)		bfin_write16(DMA11_Y_COUNT, val)
+#define bfin_read_DMA11_Y_MODIFY()		bfin_read16(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val) 		bfin_write16(DMA11_Y_MODIFY)
+#define bfin_read_DMA11_CURR_DESC_PTR() 	bfin_read32(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val) 	bfin_write32(DMA11_CURR_DESC_PTR)
+#define bfin_read_DMA11_CURR_ADDR() 		bfin_read32(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val) 	bfin_write32(DMA11_CURR_ADDR)
+#define bfin_read_DMA11_IRQ_STATUS()		bfin_read16(DMA11_IRQ_STATUS)
+#define bfin_write_DMA11_IRQ_STATUS(val)	bfin_write16(DMA11_IRQ_STATUS, val)
+#define bfin_read_DMA11_PERIPHERAL_MAP()	bfin_read16(DMA11_PERIPHERAL_MAP)
+#define bfin_write_DMA11_PERIPHERAL_MAP(val)	bfin_write16(DMA11_PERIPHERAL_MAP, val)
+#define bfin_read_DMA11_CURR_X_COUNT()		bfin_read16(DMA11_CURR_X_COUNT)
+#define bfin_write_DMA11_CURR_X_COUNT(val)	bfin_write16(DMA11_CURR_X_COUNT, val)
+#define bfin_read_DMA11_CURR_Y_COUNT()		bfin_read16(DMA11_CURR_Y_COUNT)
+#define bfin_write_DMA11_CURR_Y_COUNT(val)	bfin_write16(DMA11_CURR_Y_COUNT, val)
+
+/* MDMA Stream 0 Registers */
+
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR() 	bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) 	bfin_write32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_read_MDMA_D0_START_ADDR() 		bfin_read32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val) 	bfin_write32(MDMA_D0_START_ADDR, val)
+#define bfin_read_MDMA_D0_CONFIG()		bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val)		bfin_write16(MDMA_D0_CONFIG, val)
+#define bfin_read_MDMA_D0_X_COUNT()		bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val)		bfin_write16(MDMA_D0_X_COUNT, val)
+#define bfin_read_MDMA_D0_X_MODIFY()		bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val) 	bfin_write16(MDMA_D0_X_MODIFY, val)
+#define bfin_read_MDMA_D0_Y_COUNT()		bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val)		bfin_write16(MDMA_D0_Y_COUNT, val)
+#define bfin_read_MDMA_D0_Y_MODIFY()		bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val) 	bfin_write16(MDMA_D0_Y_MODIFY, val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR() 	bfin_read32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val) 	bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D0_CURR_ADDR() 		bfin_read32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val) 	bfin_write32(MDMA_D0_CURR_ADDR, val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()		bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val)	bfin_write16(MDMA_D0_IRQ_STATUS, val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP()	bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D0_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT()	bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val)	bfin_write16(MDMA_D0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT()	bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val)	bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR() 	bfin_read32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val) 	bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S0_START_ADDR() 		bfin_read32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val) 	bfin_write32(MDMA_S0_START_ADDR, val)
+#define bfin_read_MDMA_S0_CONFIG()		bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val)		bfin_write16(MDMA_S0_CONFIG, val)
+#define bfin_read_MDMA_S0_X_COUNT()		bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val)		bfin_write16(MDMA_S0_X_COUNT, val)
+#define bfin_read_MDMA_S0_X_MODIFY()		bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val) 	bfin_write16(MDMA_S0_X_MODIFY, val)
+#define bfin_read_MDMA_S0_Y_COUNT()		bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val)		bfin_write16(MDMA_S0_Y_COUNT, val)
+#define bfin_read_MDMA_S0_Y_MODIFY()		bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val) 	bfin_write16(MDMA_S0_Y_MODIFY, val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR() 	bfin_read32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val) 	bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S0_CURR_ADDR() 		bfin_read32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val) 	bfin_write32(MDMA_S0_CURR_ADDR, val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()		bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val)	bfin_write16(MDMA_S0_IRQ_STATUS, val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP()	bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S0_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT()	bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val)	bfin_write16(MDMA_S0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT()	bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val)	bfin_write16(MDMA_S0_CURR_Y_COUNT, val)
+
+/* MDMA Stream 1 Registers */
+
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR() 	bfin_read32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val) 	bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D1_START_ADDR() 		bfin_read32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val) 	bfin_write32(MDMA_D1_START_ADDR, val)
+#define bfin_read_MDMA_D1_CONFIG()		bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val)		bfin_write16(MDMA_D1_CONFIG, val)
+#define bfin_read_MDMA_D1_X_COUNT()		bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val)		bfin_write16(MDMA_D1_X_COUNT, val)
+#define bfin_read_MDMA_D1_X_MODIFY()		bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val) 	bfin_write16(MDMA_D1_X_MODIFY)
+#define bfin_read_MDMA_D1_Y_COUNT()		bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val)		bfin_write16(MDMA_D1_Y_COUNT, val)
+#define bfin_read_MDMA_D1_Y_MODIFY()		bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val) 	bfin_write16(MDMA_D1_Y_MODIFY)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR() 	bfin_read32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val) 	bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D1_CURR_ADDR() 		bfin_read32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val) 	bfin_write32(MDMA_D1_CURR_ADDR, val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()		bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val)	bfin_write16(MDMA_D1_IRQ_STATUS, val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP()	bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D1_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT()	bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val)	bfin_write16(MDMA_D1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT()	bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val)	bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR() 	bfin_read32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val) 	bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S1_START_ADDR() 		bfin_read32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val) 	bfin_write32(MDMA_S1_START_ADDR, val)
+#define bfin_read_MDMA_S1_CONFIG()		bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val)		bfin_write16(MDMA_S1_CONFIG, val)
+#define bfin_read_MDMA_S1_X_COUNT()		bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val)		bfin_write16(MDMA_S1_X_COUNT, val)
+#define bfin_read_MDMA_S1_X_MODIFY()		bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val) 	bfin_write16(MDMA_S1_X_MODIFY)
+#define bfin_read_MDMA_S1_Y_COUNT()		bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val)		bfin_write16(MDMA_S1_Y_COUNT, val)
+#define bfin_read_MDMA_S1_Y_MODIFY()		bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val) 	bfin_write16(MDMA_S1_Y_MODIFY)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR() 	bfin_read32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val) 	bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S1_CURR_ADDR() 		bfin_read32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val) 	bfin_write32(MDMA_S1_CURR_ADDR, val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()		bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val)	bfin_write16(MDMA_S1_IRQ_STATUS, val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP()	bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S1_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT()	bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val)	bfin_write16(MDMA_S1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT()	bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val)	bfin_write16(MDMA_S1_CURR_Y_COUNT, val)
+
+/* EPPI1 Registers */
+
+#define bfin_read_EPPI1_STATUS()		bfin_read16(EPPI1_STATUS)
+#define bfin_write_EPPI1_STATUS(val)		bfin_write16(EPPI1_STATUS, val)
+#define bfin_read_EPPI1_HCOUNT()		bfin_read16(EPPI1_HCOUNT)
+#define bfin_write_EPPI1_HCOUNT(val)		bfin_write16(EPPI1_HCOUNT, val)
+#define bfin_read_EPPI1_HDELAY()		bfin_read16(EPPI1_HDELAY)
+#define bfin_write_EPPI1_HDELAY(val)		bfin_write16(EPPI1_HDELAY, val)
+#define bfin_read_EPPI1_VCOUNT()		bfin_read16(EPPI1_VCOUNT)
+#define bfin_write_EPPI1_VCOUNT(val)		bfin_write16(EPPI1_VCOUNT, val)
+#define bfin_read_EPPI1_VDELAY()		bfin_read16(EPPI1_VDELAY)
+#define bfin_write_EPPI1_VDELAY(val)		bfin_write16(EPPI1_VDELAY, val)
+#define bfin_read_EPPI1_FRAME()			bfin_read16(EPPI1_FRAME)
+#define bfin_write_EPPI1_FRAME(val)		bfin_write16(EPPI1_FRAME, val)
+#define bfin_read_EPPI1_LINE()			bfin_read16(EPPI1_LINE)
+#define bfin_write_EPPI1_LINE(val)		bfin_write16(EPPI1_LINE, val)
+#define bfin_read_EPPI1_CLKDIV()		bfin_read16(EPPI1_CLKDIV)
+#define bfin_write_EPPI1_CLKDIV(val)		bfin_write16(EPPI1_CLKDIV, val)
+#define bfin_read_EPPI1_CONTROL()		bfin_read32(EPPI1_CONTROL)
+#define bfin_write_EPPI1_CONTROL(val)		bfin_write32(EPPI1_CONTROL, val)
+#define bfin_read_EPPI1_FS1W_HBL()		bfin_read32(EPPI1_FS1W_HBL)
+#define bfin_write_EPPI1_FS1W_HBL(val)		bfin_write32(EPPI1_FS1W_HBL, val)
+#define bfin_read_EPPI1_FS1P_AVPL()		bfin_read32(EPPI1_FS1P_AVPL)
+#define bfin_write_EPPI1_FS1P_AVPL(val)		bfin_write32(EPPI1_FS1P_AVPL, val)
+#define bfin_read_EPPI1_FS2W_LVB()		bfin_read32(EPPI1_FS2W_LVB)
+#define bfin_write_EPPI1_FS2W_LVB(val)		bfin_write32(EPPI1_FS2W_LVB, val)
+#define bfin_read_EPPI1_FS2P_LAVF()		bfin_read32(EPPI1_FS2P_LAVF)
+#define bfin_write_EPPI1_FS2P_LAVF(val)		bfin_write32(EPPI1_FS2P_LAVF, val)
+#define bfin_read_EPPI1_CLIP()			bfin_read32(EPPI1_CLIP)
+#define bfin_write_EPPI1_CLIP(val)		bfin_write32(EPPI1_CLIP, val)
+
+/* Port Interrubfin_read_()t 0 Registers (32-bit) */
+
+#define bfin_read_PINT0_MASK_SET()		bfin_read32(PINT0_MASK_SET)
+#define bfin_write_PINT0_MASK_SET(val)		bfin_write32(PINT0_MASK_SET, val)
+#define bfin_read_PINT0_MASK_CLEAR()		bfin_read32(PINT0_MASK_CLEAR)
+#define bfin_write_PINT0_MASK_CLEAR(val)	bfin_write32(PINT0_MASK_CLEAR, val)
+#define bfin_read_PINT0_REQUEST()		bfin_read32(PINT0_REQUEST)
+#define bfin_write_PINT0_REQUEST(val)		bfin_write32(PINT0_REQUEST, val)
+#define bfin_read_PINT0_ASSIGN()		bfin_read32(PINT0_ASSIGN)
+#define bfin_write_PINT0_ASSIGN(val)		bfin_write32(PINT0_ASSIGN, val)
+#define bfin_read_PINT0_EDGE_SET()		bfin_read32(PINT0_EDGE_SET)
+#define bfin_write_PINT0_EDGE_SET(val)		bfin_write32(PINT0_EDGE_SET, val)
+#define bfin_read_PINT0_EDGE_CLEAR()		bfin_read32(PINT0_EDGE_CLEAR)
+#define bfin_write_PINT0_EDGE_CLEAR(val)	bfin_write32(PINT0_EDGE_CLEAR, val)
+#define bfin_read_PINT0_INVERT_SET()		bfin_read32(PINT0_INVERT_SET)
+#define bfin_write_PINT0_INVERT_SET(val)	bfin_write32(PINT0_INVERT_SET, val)
+#define bfin_read_PINT0_INVERT_CLEAR()		bfin_read32(PINT0_INVERT_CLEAR)
+#define bfin_write_PINT0_INVERT_CLEAR(val)	bfin_write32(PINT0_INVERT_CLEAR, val)
+#define bfin_read_PINT0_PINSTATE()		bfin_read32(PINT0_PINSTATE)
+#define bfin_write_PINT0_PINSTATE(val)		bfin_write32(PINT0_PINSTATE, val)
+#define bfin_read_PINT0_LATCH()			bfin_read32(PINT0_LATCH)
+#define bfin_write_PINT0_LATCH(val)		bfin_write32(PINT0_LATCH, val)
+
+/* Port Interrubfin_read_()t 1 Registers (32-bit) */
+
+#define bfin_read_PINT1_MASK_SET()		bfin_read32(PINT1_MASK_SET)
+#define bfin_write_PINT1_MASK_SET(val)		bfin_write32(PINT1_MASK_SET, val)
+#define bfin_read_PINT1_MASK_CLEAR()		bfin_read32(PINT1_MASK_CLEAR)
+#define bfin_write_PINT1_MASK_CLEAR(val)	bfin_write32(PINT1_MASK_CLEAR, val)
+#define bfin_read_PINT1_REQUEST()		bfin_read32(PINT1_REQUEST)
+#define bfin_write_PINT1_REQUEST(val)		bfin_write32(PINT1_REQUEST, val)
+#define bfin_read_PINT1_ASSIGN()		bfin_read32(PINT1_ASSIGN)
+#define bfin_write_PINT1_ASSIGN(val)		bfin_write32(PINT1_ASSIGN, val)
+#define bfin_read_PINT1_EDGE_SET()		bfin_read32(PINT1_EDGE_SET)
+#define bfin_write_PINT1_EDGE_SET(val)		bfin_write32(PINT1_EDGE_SET, val)
+#define bfin_read_PINT1_EDGE_CLEAR()		bfin_read32(PINT1_EDGE_CLEAR)
+#define bfin_write_PINT1_EDGE_CLEAR(val)	bfin_write32(PINT1_EDGE_CLEAR, val)
+#define bfin_read_PINT1_INVERT_SET()		bfin_read32(PINT1_INVERT_SET)
+#define bfin_write_PINT1_INVERT_SET(val)	bfin_write32(PINT1_INVERT_SET, val)
+#define bfin_read_PINT1_INVERT_CLEAR()		bfin_read32(PINT1_INVERT_CLEAR)
+#define bfin_write_PINT1_INVERT_CLEAR(val)	bfin_write32(PINT1_INVERT_CLEAR, val)
+#define bfin_read_PINT1_PINSTATE()		bfin_read32(PINT1_PINSTATE)
+#define bfin_write_PINT1_PINSTATE(val)		bfin_write32(PINT1_PINSTATE, val)
+#define bfin_read_PINT1_LATCH()			bfin_read32(PINT1_LATCH)
+#define bfin_write_PINT1_LATCH(val)		bfin_write32(PINT1_LATCH, val)
+
+/* Port Interrubfin_read_()t 2 Registers (32-bit) */
+
+#define bfin_read_PINT2_MASK_SET()		bfin_read32(PINT2_MASK_SET)
+#define bfin_write_PINT2_MASK_SET(val)		bfin_write32(PINT2_MASK_SET, val)
+#define bfin_read_PINT2_MASK_CLEAR()		bfin_read32(PINT2_MASK_CLEAR)
+#define bfin_write_PINT2_MASK_CLEAR(val)	bfin_write32(PINT2_MASK_CLEAR, val)
+#define bfin_read_PINT2_REQUEST()		bfin_read32(PINT2_REQUEST)
+#define bfin_write_PINT2_REQUEST(val)		bfin_write32(PINT2_REQUEST, val)
+#define bfin_read_PINT2_ASSIGN()		bfin_read32(PINT2_ASSIGN)
+#define bfin_write_PINT2_ASSIGN(val)		bfin_write32(PINT2_ASSIGN, val)
+#define bfin_read_PINT2_EDGE_SET()		bfin_read32(PINT2_EDGE_SET)
+#define bfin_write_PINT2_EDGE_SET(val)		bfin_write32(PINT2_EDGE_SET, val)
+#define bfin_read_PINT2_EDGE_CLEAR()		bfin_read32(PINT2_EDGE_CLEAR)
+#define bfin_write_PINT2_EDGE_CLEAR(val)	bfin_write32(PINT2_EDGE_CLEAR, val)
+#define bfin_read_PINT2_INVERT_SET()		bfin_read32(PINT2_INVERT_SET)
+#define bfin_write_PINT2_INVERT_SET(val)	bfin_write32(PINT2_INVERT_SET, val)
+#define bfin_read_PINT2_INVERT_CLEAR()		bfin_read32(PINT2_INVERT_CLEAR)
+#define bfin_write_PINT2_INVERT_CLEAR(val)	bfin_write32(PINT2_INVERT_CLEAR, val)
+#define bfin_read_PINT2_PINSTATE()		bfin_read32(PINT2_PINSTATE)
+#define bfin_write_PINT2_PINSTATE(val)		bfin_write32(PINT2_PINSTATE, val)
+#define bfin_read_PINT2_LATCH()			bfin_read32(PINT2_LATCH)
+#define bfin_write_PINT2_LATCH(val)		bfin_write32(PINT2_LATCH, val)
+
+/* Port Interrubfin_read_()t 3 Registers (32-bit) */
+
+#define bfin_read_PINT3_MASK_SET()		bfin_read32(PINT3_MASK_SET)
+#define bfin_write_PINT3_MASK_SET(val)		bfin_write32(PINT3_MASK_SET, val)
+#define bfin_read_PINT3_MASK_CLEAR()		bfin_read32(PINT3_MASK_CLEAR)
+#define bfin_write_PINT3_MASK_CLEAR(val)	bfin_write32(PINT3_MASK_CLEAR, val)
+#define bfin_read_PINT3_REQUEST()		bfin_read32(PINT3_REQUEST)
+#define bfin_write_PINT3_REQUEST(val)		bfin_write32(PINT3_REQUEST, val)
+#define bfin_read_PINT3_ASSIGN()		bfin_read32(PINT3_ASSIGN)
+#define bfin_write_PINT3_ASSIGN(val)		bfin_write32(PINT3_ASSIGN, val)
+#define bfin_read_PINT3_EDGE_SET()		bfin_read32(PINT3_EDGE_SET)
+#define bfin_write_PINT3_EDGE_SET(val)		bfin_write32(PINT3_EDGE_SET, val)
+#define bfin_read_PINT3_EDGE_CLEAR()		bfin_read32(PINT3_EDGE_CLEAR)
+#define bfin_write_PINT3_EDGE_CLEAR(val)	bfin_write32(PINT3_EDGE_CLEAR, val)
+#define bfin_read_PINT3_INVERT_SET()		bfin_read32(PINT3_INVERT_SET)
+#define bfin_write_PINT3_INVERT_SET(val)	bfin_write32(PINT3_INVERT_SET, val)
+#define bfin_read_PINT3_INVERT_CLEAR()		bfin_read32(PINT3_INVERT_CLEAR)
+#define bfin_write_PINT3_INVERT_CLEAR(val)	bfin_write32(PINT3_INVERT_CLEAR, val)
+#define bfin_read_PINT3_PINSTATE()		bfin_read32(PINT3_PINSTATE)
+#define bfin_write_PINT3_PINSTATE(val)		bfin_write32(PINT3_PINSTATE, val)
+#define bfin_read_PINT3_LATCH()			bfin_read32(PINT3_LATCH)
+#define bfin_write_PINT3_LATCH(val)		bfin_write32(PINT3_LATCH, val)
+
+/* Port A Registers */
+
+#define bfin_read_PORTA_FER()		bfin_read16(PORTA_FER)
+#define bfin_write_PORTA_FER(val)	bfin_write16(PORTA_FER, val)
+#define bfin_read_PORTA()		bfin_read16(PORTA)
+#define bfin_write_PORTA(val)		bfin_write16(PORTA, val)
+#define bfin_read_PORTA_SET()		bfin_read16(PORTA_SET)
+#define bfin_write_PORTA_SET(val)	bfin_write16(PORTA_SET, val)
+#define bfin_read_PORTA_CLEAR()		bfin_read16(PORTA_CLEAR)
+#define bfin_write_PORTA_CLEAR(val)	bfin_write16(PORTA_CLEAR, val)
+#define bfin_read_PORTA_DIR_SET()	bfin_read16(PORTA_DIR_SET)
+#define bfin_write_PORTA_DIR_SET(val)	bfin_write16(PORTA_DIR_SET, val)
+#define bfin_read_PORTA_DIR_CLEAR()	bfin_read16(PORTA_DIR_CLEAR)
+#define bfin_write_PORTA_DIR_CLEAR(val)	bfin_write16(PORTA_DIR_CLEAR, val)
+#define bfin_read_PORTA_INEN()		bfin_read16(PORTA_INEN)
+#define bfin_write_PORTA_INEN(val)	bfin_write16(PORTA_INEN, val)
+#define bfin_read_PORTA_MUX()		bfin_read32(PORTA_MUX)
+#define bfin_write_PORTA_MUX(val)	bfin_write32(PORTA_MUX, val)
+
+/* Port B Registers */
+
+#define bfin_read_PORTB_FER()		bfin_read16(PORTB_FER)
+#define bfin_write_PORTB_FER(val)	bfin_write16(PORTB_FER, val)
+#define bfin_read_PORTB()		bfin_read16(PORTB)
+#define bfin_write_PORTB(val)		bfin_write16(PORTB, val)
+#define bfin_read_PORTB_SET()		bfin_read16(PORTB_SET)
+#define bfin_write_PORTB_SET(val)	bfin_write16(PORTB_SET, val)
+#define bfin_read_PORTB_CLEAR()		bfin_read16(PORTB_CLEAR)
+#define bfin_write_PORTB_CLEAR(val)	bfin_write16(PORTB_CLEAR, val)
+#define bfin_read_PORTB_DIR_SET()	bfin_read16(PORTB_DIR_SET)
+#define bfin_write_PORTB_DIR_SET(val)	bfin_write16(PORTB_DIR_SET, val)
+#define bfin_read_PORTB_DIR_CLEAR()	bfin_read16(PORTB_DIR_CLEAR)
+#define bfin_write_PORTB_DIR_CLEAR(val)	bfin_write16(PORTB_DIR_CLEAR, val)
+#define bfin_read_PORTB_INEN()		bfin_read16(PORTB_INEN)
+#define bfin_write_PORTB_INEN(val)	bfin_write16(PORTB_INEN, val)
+#define bfin_read_PORTB_MUX()		bfin_read32(PORTB_MUX)
+#define bfin_write_PORTB_MUX(val)	bfin_write32(PORTB_MUX, val)
+
+/* Port C Registers */
+
+#define bfin_read_PORTC_FER()		bfin_read16(PORTC_FER)
+#define bfin_write_PORTC_FER(val)	bfin_write16(PORTC_FER, val)
+#define bfin_read_PORTC()		bfin_read16(PORTC)
+#define bfin_write_PORTC(val)		bfin_write16(PORTC, val)
+#define bfin_read_PORTC_SET()		bfin_read16(PORTC_SET)
+#define bfin_write_PORTC_SET(val)	bfin_write16(PORTC_SET, val)
+#define bfin_read_PORTC_CLEAR()		bfin_read16(PORTC_CLEAR)
+#define bfin_write_PORTC_CLEAR(val)	bfin_write16(PORTC_CLEAR, val)
+#define bfin_read_PORTC_DIR_SET()	bfin_read16(PORTC_DIR_SET)
+#define bfin_write_PORTC_DIR_SET(val)	bfin_write16(PORTC_DIR_SET, val)
+#define bfin_read_PORTC_DIR_CLEAR()	bfin_read16(PORTC_DIR_CLEAR)
+#define bfin_write_PORTC_DIR_CLEAR(val)	bfin_write16(PORTC_DIR_CLEAR, val)
+#define bfin_read_PORTC_INEN()		bfin_read16(PORTC_INEN)
+#define bfin_write_PORTC_INEN(val)	bfin_write16(PORTC_INEN, val)
+#define bfin_read_PORTC_MUX()		bfin_read32(PORTC_MUX)
+#define bfin_write_PORTC_MUX(val)	bfin_write32(PORTC_MUX, val)
+
+/* Port D Registers */
+
+#define bfin_read_PORTD_FER()		bfin_read16(PORTD_FER)
+#define bfin_write_PORTD_FER(val)	bfin_write16(PORTD_FER, val)
+#define bfin_read_PORTD()		bfin_read16(PORTD)
+#define bfin_write_PORTD(val)		bfin_write16(PORTD, val)
+#define bfin_read_PORTD_SET()		bfin_read16(PORTD_SET)
+#define bfin_write_PORTD_SET(val)	bfin_write16(PORTD_SET, val)
+#define bfin_read_PORTD_CLEAR()		bfin_read16(PORTD_CLEAR)
+#define bfin_write_PORTD_CLEAR(val)	bfin_write16(PORTD_CLEAR, val)
+#define bfin_read_PORTD_DIR_SET()	bfin_read16(PORTD_DIR_SET)
+#define bfin_write_PORTD_DIR_SET(val)	bfin_write16(PORTD_DIR_SET, val)
+#define bfin_read_PORTD_DIR_CLEAR()	bfin_read16(PORTD_DIR_CLEAR)
+#define bfin_write_PORTD_DIR_CLEAR(val)	bfin_write16(PORTD_DIR_CLEAR, val)
+#define bfin_read_PORTD_INEN()		bfin_read16(PORTD_INEN)
+#define bfin_write_PORTD_INEN(val)	bfin_write16(PORTD_INEN, val)
+#define bfin_read_PORTD_MUX()		bfin_read32(PORTD_MUX)
+#define bfin_write_PORTD_MUX(val)	bfin_write32(PORTD_MUX, val)
+
+/* Port E Registers */
+
+#define bfin_read_PORTE_FER()		bfin_read16(PORTE_FER)
+#define bfin_write_PORTE_FER(val)	bfin_write16(PORTE_FER, val)
+#define bfin_read_PORTE()		bfin_read16(PORTE)
+#define bfin_write_PORTE(val)		bfin_write16(PORTE, val)
+#define bfin_read_PORTE_SET()		bfin_read16(PORTE_SET)
+#define bfin_write_PORTE_SET(val)	bfin_write16(PORTE_SET, val)
+#define bfin_read_PORTE_CLEAR()		bfin_read16(PORTE_CLEAR)
+#define bfin_write_PORTE_CLEAR(val)	bfin_write16(PORTE_CLEAR, val)
+#define bfin_read_PORTE_DIR_SET()	bfin_read16(PORTE_DIR_SET)
+#define bfin_write_PORTE_DIR_SET(val)	bfin_write16(PORTE_DIR_SET, val)
+#define bfin_read_PORTE_DIR_CLEAR()	bfin_read16(PORTE_DIR_CLEAR)
+#define bfin_write_PORTE_DIR_CLEAR(val)	bfin_write16(PORTE_DIR_CLEAR, val)
+#define bfin_read_PORTE_INEN()		bfin_read16(PORTE_INEN)
+#define bfin_write_PORTE_INEN(val)	bfin_write16(PORTE_INEN, val)
+#define bfin_read_PORTE_MUX()		bfin_read32(PORTE_MUX)
+#define bfin_write_PORTE_MUX(val)	bfin_write32(PORTE_MUX, val)
+
+/* Port F Registers */
+
+#define bfin_read_PORTF_FER()		bfin_read16(PORTF_FER)
+#define bfin_write_PORTF_FER(val)	bfin_write16(PORTF_FER, val)
+#define bfin_read_PORTF()		bfin_read16(PORTF)
+#define bfin_write_PORTF(val)		bfin_write16(PORTF, val)
+#define bfin_read_PORTF_SET()		bfin_read16(PORTF_SET)
+#define bfin_write_PORTF_SET(val)	bfin_write16(PORTF_SET, val)
+#define bfin_read_PORTF_CLEAR()		bfin_read16(PORTF_CLEAR)
+#define bfin_write_PORTF_CLEAR(val)	bfin_write16(PORTF_CLEAR, val)
+#define bfin_read_PORTF_DIR_SET()	bfin_read16(PORTF_DIR_SET)
+#define bfin_write_PORTF_DIR_SET(val)	bfin_write16(PORTF_DIR_SET, val)
+#define bfin_read_PORTF_DIR_CLEAR()	bfin_read16(PORTF_DIR_CLEAR)
+#define bfin_write_PORTF_DIR_CLEAR(val)	bfin_write16(PORTF_DIR_CLEAR, val)
+#define bfin_read_PORTF_INEN()		bfin_read16(PORTF_INEN)
+#define bfin_write_PORTF_INEN(val)	bfin_write16(PORTF_INEN, val)
+#define bfin_read_PORTF_MUX()		bfin_read32(PORTF_MUX)
+#define bfin_write_PORTF_MUX(val)	bfin_write32(PORTF_MUX, val)
+
+/* Port G Registers */
+
+#define bfin_read_PORTG_FER()		bfin_read16(PORTG_FER)
+#define bfin_write_PORTG_FER(val)	bfin_write16(PORTG_FER, val)
+#define bfin_read_PORTG()		bfin_read16(PORTG)
+#define bfin_write_PORTG(val)		bfin_write16(PORTG, val)
+#define bfin_read_PORTG_SET()		bfin_read16(PORTG_SET)
+#define bfin_write_PORTG_SET(val)	bfin_write16(PORTG_SET, val)
+#define bfin_read_PORTG_CLEAR()		bfin_read16(PORTG_CLEAR)
+#define bfin_write_PORTG_CLEAR(val)	bfin_write16(PORTG_CLEAR, val)
+#define bfin_read_PORTG_DIR_SET()	bfin_read16(PORTG_DIR_SET)
+#define bfin_write_PORTG_DIR_SET(val)	bfin_write16(PORTG_DIR_SET, val)
+#define bfin_read_PORTG_DIR_CLEAR()	bfin_read16(PORTG_DIR_CLEAR)
+#define bfin_write_PORTG_DIR_CLEAR(val)	bfin_write16(PORTG_DIR_CLEAR, val)
+#define bfin_read_PORTG_INEN()		bfin_read16(PORTG_INEN)
+#define bfin_write_PORTG_INEN(val)	bfin_write16(PORTG_INEN, val)
+#define bfin_read_PORTG_MUX()		bfin_read32(PORTG_MUX)
+#define bfin_write_PORTG_MUX(val)	bfin_write32(PORTG_MUX, val)
+
+/* Port H Registers */
+
+#define bfin_read_PORTH_FER()		bfin_read16(PORTH_FER)
+#define bfin_write_PORTH_FER(val)	bfin_write16(PORTH_FER, val)
+#define bfin_read_PORTH()		bfin_read16(PORTH)
+#define bfin_write_PORTH(val)		bfin_write16(PORTH, val)
+#define bfin_read_PORTH_SET()		bfin_read16(PORTH_SET)
+#define bfin_write_PORTH_SET(val)	bfin_write16(PORTH_SET, val)
+#define bfin_read_PORTH_CLEAR()		bfin_read16(PORTH_CLEAR)
+#define bfin_write_PORTH_CLEAR(val)	bfin_write16(PORTH_CLEAR, val)
+#define bfin_read_PORTH_DIR_SET()	bfin_read16(PORTH_DIR_SET)
+#define bfin_write_PORTH_DIR_SET(val)	bfin_write16(PORTH_DIR_SET, val)
+#define bfin_read_PORTH_DIR_CLEAR()	bfin_read16(PORTH_DIR_CLEAR)
+#define bfin_write_PORTH_DIR_CLEAR(val)	bfin_write16(PORTH_DIR_CLEAR, val)
+#define bfin_read_PORTH_INEN()		bfin_read16(PORTH_INEN)
+#define bfin_write_PORTH_INEN(val)	bfin_write16(PORTH_INEN, val)
+#define bfin_read_PORTH_MUX()		bfin_read32(PORTH_MUX)
+#define bfin_write_PORTH_MUX(val)	bfin_write32(PORTH_MUX, val)
+
+/* Port I Registers */
+
+#define bfin_read_PORTI_FER()		bfin_read16(PORTI_FER)
+#define bfin_write_PORTI_FER(val)	bfin_write16(PORTI_FER, val)
+#define bfin_read_PORTI()		bfin_read16(PORTI)
+#define bfin_write_PORTI(val)		bfin_write16(PORTI, val)
+#define bfin_read_PORTI_SET()		bfin_read16(PORTI_SET)
+#define bfin_write_PORTI_SET(val)	bfin_write16(PORTI_SET, val)
+#define bfin_read_PORTI_CLEAR()		bfin_read16(PORTI_CLEAR)
+#define bfin_write_PORTI_CLEAR(val)	bfin_write16(PORTI_CLEAR, val)
+#define bfin_read_PORTI_DIR_SET()	bfin_read16(PORTI_DIR_SET)
+#define bfin_write_PORTI_DIR_SET(val)	bfin_write16(PORTI_DIR_SET, val)
+#define bfin_read_PORTI_DIR_CLEAR()	bfin_read16(PORTI_DIR_CLEAR)
+#define bfin_write_PORTI_DIR_CLEAR(val)	bfin_write16(PORTI_DIR_CLEAR, val)
+#define bfin_read_PORTI_INEN()		bfin_read16(PORTI_INEN)
+#define bfin_write_PORTI_INEN(val)	bfin_write16(PORTI_INEN, val)
+#define bfin_read_PORTI_MUX()		bfin_read32(PORTI_MUX)
+#define bfin_write_PORTI_MUX(val)	bfin_write32(PORTI_MUX, val)
+
+/* Port J Registers */
+
+#define bfin_read_PORTJ_FER()		bfin_read16(PORTJ_FER)
+#define bfin_write_PORTJ_FER(val)	bfin_write16(PORTJ_FER, val)
+#define bfin_read_PORTJ()		bfin_read16(PORTJ)
+#define bfin_write_PORTJ(val)		bfin_write16(PORTJ, val)
+#define bfin_read_PORTJ_SET()		bfin_read16(PORTJ_SET)
+#define bfin_write_PORTJ_SET(val)	bfin_write16(PORTJ_SET, val)
+#define bfin_read_PORTJ_CLEAR()		bfin_read16(PORTJ_CLEAR)
+#define bfin_write_PORTJ_CLEAR(val)	bfin_write16(PORTJ_CLEAR, val)
+#define bfin_read_PORTJ_DIR_SET()	bfin_read16(PORTJ_DIR_SET)
+#define bfin_write_PORTJ_DIR_SET(val)	bfin_write16(PORTJ_DIR_SET, val)
+#define bfin_read_PORTJ_DIR_CLEAR()	bfin_read16(PORTJ_DIR_CLEAR)
+#define bfin_write_PORTJ_DIR_CLEAR(val)	bfin_write16(PORTJ_DIR_CLEAR, val)
+#define bfin_read_PORTJ_INEN()		bfin_read16(PORTJ_INEN)
+#define bfin_write_PORTJ_INEN(val)	bfin_write16(PORTJ_INEN, val)
+#define bfin_read_PORTJ_MUX()		bfin_read32(PORTJ_MUX)
+#define bfin_write_PORTJ_MUX(val)	bfin_write32(PORTJ_MUX, val)
+
+/* PWM Timer Registers */
+
+#define bfin_read_TIMER0_CONFIG()		bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val)		bfin_write16(TIMER0_CONFIG, val)
+#define bfin_read_TIMER0_COUNTER()		bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val)		bfin_write32(TIMER0_COUNTER, val)
+#define bfin_read_TIMER0_PERIOD()		bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val)		bfin_write32(TIMER0_PERIOD, val)
+#define bfin_read_TIMER0_WIDTH()		bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val)		bfin_write32(TIMER0_WIDTH, val)
+#define bfin_read_TIMER1_CONFIG()		bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val)		bfin_write16(TIMER1_CONFIG, val)
+#define bfin_read_TIMER1_COUNTER()		bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val)		bfin_write32(TIMER1_COUNTER, val)
+#define bfin_read_TIMER1_PERIOD()		bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val)		bfin_write32(TIMER1_PERIOD, val)
+#define bfin_read_TIMER1_WIDTH()		bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val)		bfin_write32(TIMER1_WIDTH, val)
+#define bfin_read_TIMER2_CONFIG()		bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val)		bfin_write16(TIMER2_CONFIG, val)
+#define bfin_read_TIMER2_COUNTER()		bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val)		bfin_write32(TIMER2_COUNTER, val)
+#define bfin_read_TIMER2_PERIOD()		bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val)		bfin_write32(TIMER2_PERIOD, val)
+#define bfin_read_TIMER2_WIDTH()		bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val)		bfin_write32(TIMER2_WIDTH, val)
+#define bfin_read_TIMER3_CONFIG()		bfin_read16(TIMER3_CONFIG)
+#define bfin_write_TIMER3_CONFIG(val)		bfin_write16(TIMER3_CONFIG, val)
+#define bfin_read_TIMER3_COUNTER()		bfin_read32(TIMER3_COUNTER)
+#define bfin_write_TIMER3_COUNTER(val)		bfin_write32(TIMER3_COUNTER, val)
+#define bfin_read_TIMER3_PERIOD()		bfin_read32(TIMER3_PERIOD)
+#define bfin_write_TIMER3_PERIOD(val)		bfin_write32(TIMER3_PERIOD, val)
+#define bfin_read_TIMER3_WIDTH()		bfin_read32(TIMER3_WIDTH)
+#define bfin_write_TIMER3_WIDTH(val)		bfin_write32(TIMER3_WIDTH, val)
+#define bfin_read_TIMER4_CONFIG()		bfin_read16(TIMER4_CONFIG)
+#define bfin_write_TIMER4_CONFIG(val)		bfin_write16(TIMER4_CONFIG, val)
+#define bfin_read_TIMER4_COUNTER()		bfin_read32(TIMER4_COUNTER)
+#define bfin_write_TIMER4_COUNTER(val)		bfin_write32(TIMER4_COUNTER, val)
+#define bfin_read_TIMER4_PERIOD()		bfin_read32(TIMER4_PERIOD)
+#define bfin_write_TIMER4_PERIOD(val)		bfin_write32(TIMER4_PERIOD, val)
+#define bfin_read_TIMER4_WIDTH()		bfin_read32(TIMER4_WIDTH)
+#define bfin_write_TIMER4_WIDTH(val)		bfin_write32(TIMER4_WIDTH, val)
+#define bfin_read_TIMER5_CONFIG()		bfin_read16(TIMER5_CONFIG)
+#define bfin_write_TIMER5_CONFIG(val)		bfin_write16(TIMER5_CONFIG, val)
+#define bfin_read_TIMER5_COUNTER()		bfin_read32(TIMER5_COUNTER)
+#define bfin_write_TIMER5_COUNTER(val)		bfin_write32(TIMER5_COUNTER, val)
+#define bfin_read_TIMER5_PERIOD()		bfin_read32(TIMER5_PERIOD)
+#define bfin_write_TIMER5_PERIOD(val)		bfin_write32(TIMER5_PERIOD, val)
+#define bfin_read_TIMER5_WIDTH()		bfin_read32(TIMER5_WIDTH)
+#define bfin_write_TIMER5_WIDTH(val)		bfin_write32(TIMER5_WIDTH, val)
+#define bfin_read_TIMER6_CONFIG()		bfin_read16(TIMER6_CONFIG)
+#define bfin_write_TIMER6_CONFIG(val)		bfin_write16(TIMER6_CONFIG, val)
+#define bfin_read_TIMER6_COUNTER()		bfin_read32(TIMER6_COUNTER)
+#define bfin_write_TIMER6_COUNTER(val)		bfin_write32(TIMER6_COUNTER, val)
+#define bfin_read_TIMER6_PERIOD()		bfin_read32(TIMER6_PERIOD)
+#define bfin_write_TIMER6_PERIOD(val)		bfin_write32(TIMER6_PERIOD, val)
+#define bfin_read_TIMER6_WIDTH()		bfin_read32(TIMER6_WIDTH)
+#define bfin_write_TIMER6_WIDTH(val)		bfin_write32(TIMER6_WIDTH, val)
+#define bfin_read_TIMER7_CONFIG()		bfin_read16(TIMER7_CONFIG)
+#define bfin_write_TIMER7_CONFIG(val)		bfin_write16(TIMER7_CONFIG, val)
+#define bfin_read_TIMER7_COUNTER()		bfin_read32(TIMER7_COUNTER)
+#define bfin_write_TIMER7_COUNTER(val)		bfin_write32(TIMER7_COUNTER, val)
+#define bfin_read_TIMER7_PERIOD()		bfin_read32(TIMER7_PERIOD)
+#define bfin_write_TIMER7_PERIOD(val)		bfin_write32(TIMER7_PERIOD, val)
+#define bfin_read_TIMER7_WIDTH()		bfin_read32(TIMER7_WIDTH)
+#define bfin_write_TIMER7_WIDTH(val)		bfin_write32(TIMER7_WIDTH, val)
+
+/* Timer Groubfin_read_() of 8 */
+
+#define bfin_read_TIMER_ENABLE0()		bfin_read16(TIMER_ENABLE0)
+#define bfin_write_TIMER_ENABLE0(val)		bfin_write16(TIMER_ENABLE0, val)
+#define bfin_read_TIMER_DISABLE0()		bfin_read16(TIMER_DISABLE0)
+#define bfin_write_TIMER_DISABLE0(val)		bfin_write16(TIMER_DISABLE0, val)
+#define bfin_read_TIMER_STATUS0()		bfin_read32(TIMER_STATUS0)
+#define bfin_write_TIMER_STATUS0(val)		bfin_write32(TIMER_STATUS0, val)
+
+/* DMAC1 Registers */
+
+#define bfin_read_DMAC1_TCPER()			bfin_read16(DMAC1_TCPER)
+#define bfin_write_DMAC1_TCPER(val)		bfin_write16(DMAC1_TCPER, val)
+#define bfin_read_DMAC1_TCCNT()			bfin_read16(DMAC1_TCCNT)
+#define bfin_write_DMAC1_TCCNT(val)		bfin_write16(DMAC1_TCCNT, val)
+
+/* DMA Channel 12 Registers */
+
+#define bfin_read_DMA12_NEXT_DESC_PTR() 	bfin_read32(DMA12_NEXT_DESC_PTR)
+#define bfin_write_DMA12_NEXT_DESC_PTR(val) 	bfin_write32(DMA12_NEXT_DESC_PTR)
+#define bfin_read_DMA12_START_ADDR() 		bfin_read32(DMA12_START_ADDR)
+#define bfin_write_DMA12_START_ADDR(val) 	bfin_write32(DMA12_START_ADDR)
+#define bfin_read_DMA12_CONFIG()		bfin_read16(DMA12_CONFIG)
+#define bfin_write_DMA12_CONFIG(val)		bfin_write16(DMA12_CONFIG, val)
+#define bfin_read_DMA12_X_COUNT()		bfin_read16(DMA12_X_COUNT)
+#define bfin_write_DMA12_X_COUNT(val)		bfin_write16(DMA12_X_COUNT, val)
+#define bfin_read_DMA12_X_MODIFY()		bfin_read16(DMA12_X_MODIFY)
+#define bfin_write_DMA12_X_MODIFY(val) 		bfin_write16(DMA12_X_MODIFY)
+#define bfin_read_DMA12_Y_COUNT()		bfin_read16(DMA12_Y_COUNT)
+#define bfin_write_DMA12_Y_COUNT(val)		bfin_write16(DMA12_Y_COUNT, val)
+#define bfin_read_DMA12_Y_MODIFY()		bfin_read16(DMA12_Y_MODIFY)
+#define bfin_write_DMA12_Y_MODIFY(val) 		bfin_write16(DMA12_Y_MODIFY)
+#define bfin_read_DMA12_CURR_DESC_PTR() 	bfin_read32(DMA12_CURR_DESC_PTR)
+#define bfin_write_DMA12_CURR_DESC_PTR(val) 	bfin_write32(DMA12_CURR_DESC_PTR)
+#define bfin_read_DMA12_CURR_ADDR() 		bfin_read32(DMA12_CURR_ADDR)
+#define bfin_write_DMA12_CURR_ADDR(val) 	bfin_write32(DMA12_CURR_ADDR)
+#define bfin_read_DMA12_IRQ_STATUS()		bfin_read16(DMA12_IRQ_STATUS)
+#define bfin_write_DMA12_IRQ_STATUS(val)	bfin_write16(DMA12_IRQ_STATUS, val)
+#define bfin_read_DMA12_PERIPHERAL_MAP()	bfin_read16(DMA12_PERIPHERAL_MAP)
+#define bfin_write_DMA12_PERIPHERAL_MAP(val)	bfin_write16(DMA12_PERIPHERAL_MAP, val)
+#define bfin_read_DMA12_CURR_X_COUNT()		bfin_read16(DMA12_CURR_X_COUNT)
+#define bfin_write_DMA12_CURR_X_COUNT(val)	bfin_write16(DMA12_CURR_X_COUNT, val)
+#define bfin_read_DMA12_CURR_Y_COUNT()		bfin_read16(DMA12_CURR_Y_COUNT)
+#define bfin_write_DMA12_CURR_Y_COUNT(val)	bfin_write16(DMA12_CURR_Y_COUNT, val)
+
+/* DMA Channel 13 Registers */
+
+#define bfin_read_DMA13_NEXT_DESC_PTR() 	bfin_read32(DMA13_NEXT_DESC_PTR)
+#define bfin_write_DMA13_NEXT_DESC_PTR(val) 	bfin_write32(DMA13_NEXT_DESC_PTR)
+#define bfin_read_DMA13_START_ADDR() 		bfin_read32(DMA13_START_ADDR)
+#define bfin_write_DMA13_START_ADDR(val) 	bfin_write32(DMA13_START_ADDR)
+#define bfin_read_DMA13_CONFIG()		bfin_read16(DMA13_CONFIG)
+#define bfin_write_DMA13_CONFIG(val)		bfin_write16(DMA13_CONFIG, val)
+#define bfin_read_DMA13_X_COUNT()		bfin_read16(DMA13_X_COUNT)
+#define bfin_write_DMA13_X_COUNT(val)		bfin_write16(DMA13_X_COUNT, val)
+#define bfin_read_DMA13_X_MODIFY()		bfin_read16(DMA13_X_MODIFY)
+#define bfin_write_DMA13_X_MODIFY(val) 		bfin_write16(DMA13_X_MODIFY)
+#define bfin_read_DMA13_Y_COUNT()		bfin_read16(DMA13_Y_COUNT)
+#define bfin_write_DMA13_Y_COUNT(val)		bfin_write16(DMA13_Y_COUNT, val)
+#define bfin_read_DMA13_Y_MODIFY()		bfin_read16(DMA13_Y_MODIFY)
+#define bfin_write_DMA13_Y_MODIFY(val) 		bfin_write16(DMA13_Y_MODIFY)
+#define bfin_read_DMA13_CURR_DESC_PTR() 	bfin_read32(DMA13_CURR_DESC_PTR)
+#define bfin_write_DMA13_CURR_DESC_PTR(val) 	bfin_write32(DMA13_CURR_DESC_PTR)
+#define bfin_read_DMA13_CURR_ADDR() 		bfin_read32(DMA13_CURR_ADDR)
+#define bfin_write_DMA13_CURR_ADDR(val) 	bfin_write32(DMA13_CURR_ADDR)
+#define bfin_read_DMA13_IRQ_STATUS()		bfin_read16(DMA13_IRQ_STATUS)
+#define bfin_write_DMA13_IRQ_STATUS(val)	bfin_write16(DMA13_IRQ_STATUS, val)
+#define bfin_read_DMA13_PERIPHERAL_MAP()	bfin_read16(DMA13_PERIPHERAL_MAP)
+#define bfin_write_DMA13_PERIPHERAL_MAP(val)	bfin_write16(DMA13_PERIPHERAL_MAP, val)
+#define bfin_read_DMA13_CURR_X_COUNT()		bfin_read16(DMA13_CURR_X_COUNT)
+#define bfin_write_DMA13_CURR_X_COUNT(val)	bfin_write16(DMA13_CURR_X_COUNT, val)
+#define bfin_read_DMA13_CURR_Y_COUNT()		bfin_read16(DMA13_CURR_Y_COUNT)
+#define bfin_write_DMA13_CURR_Y_COUNT(val)	bfin_write16(DMA13_CURR_Y_COUNT, val)
+
+/* DMA Channel 14 Registers */
+
+#define bfin_read_DMA14_NEXT_DESC_PTR() 	bfin_read32(DMA14_NEXT_DESC_PTR)
+#define bfin_write_DMA14_NEXT_DESC_PTR(val) 	bfin_write32(DMA14_NEXT_DESC_PTR)
+#define bfin_read_DMA14_START_ADDR() 		bfin_read32(DMA14_START_ADDR)
+#define bfin_write_DMA14_START_ADDR(val) 	bfin_write32(DMA14_START_ADDR)
+#define bfin_read_DMA14_CONFIG()		bfin_read16(DMA14_CONFIG)
+#define bfin_write_DMA14_CONFIG(val)		bfin_write16(DMA14_CONFIG, val)
+#define bfin_read_DMA14_X_COUNT()		bfin_read16(DMA14_X_COUNT)
+#define bfin_write_DMA14_X_COUNT(val)		bfin_write16(DMA14_X_COUNT, val)
+#define bfin_read_DMA14_X_MODIFY()		bfin_read16(DMA14_X_MODIFY)
+#define bfin_write_DMA14_X_MODIFY(val) 		bfin_write16(DMA14_X_MODIFY)
+#define bfin_read_DMA14_Y_COUNT()		bfin_read16(DMA14_Y_COUNT)
+#define bfin_write_DMA14_Y_COUNT(val)		bfin_write16(DMA14_Y_COUNT, val)
+#define bfin_read_DMA14_Y_MODIFY()		bfin_read16(DMA14_Y_MODIFY)
+#define bfin_write_DMA14_Y_MODIFY(val) 		bfin_write16(DMA14_Y_MODIFY)
+#define bfin_read_DMA14_CURR_DESC_PTR() 	bfin_read32(DMA14_CURR_DESC_PTR)
+#define bfin_write_DMA14_CURR_DESC_PTR(val) 	bfin_write32(DMA14_CURR_DESC_PTR)
+#define bfin_read_DMA14_CURR_ADDR() 		bfin_read32(DMA14_CURR_ADDR)
+#define bfin_write_DMA14_CURR_ADDR(val) 	bfin_write32(DMA14_CURR_ADDR)
+#define bfin_read_DMA14_IRQ_STATUS()		bfin_read16(DMA14_IRQ_STATUS)
+#define bfin_write_DMA14_IRQ_STATUS(val)	bfin_write16(DMA14_IRQ_STATUS, val)
+#define bfin_read_DMA14_PERIPHERAL_MAP()	bfin_read16(DMA14_PERIPHERAL_MAP)
+#define bfin_write_DMA14_PERIPHERAL_MAP(val)	bfin_write16(DMA14_PERIPHERAL_MAP, val)
+#define bfin_read_DMA14_CURR_X_COUNT()		bfin_read16(DMA14_CURR_X_COUNT)
+#define bfin_write_DMA14_CURR_X_COUNT(val)	bfin_write16(DMA14_CURR_X_COUNT, val)
+#define bfin_read_DMA14_CURR_Y_COUNT()		bfin_read16(DMA14_CURR_Y_COUNT)
+#define bfin_write_DMA14_CURR_Y_COUNT(val)	bfin_write16(DMA14_CURR_Y_COUNT, val)
+
+/* DMA Channel 15 Registers */
+
+#define bfin_read_DMA15_NEXT_DESC_PTR() 	bfin_read32(DMA15_NEXT_DESC_PTR)
+#define bfin_write_DMA15_NEXT_DESC_PTR(val) 	bfin_write32(DMA15_NEXT_DESC_PTR)
+#define bfin_read_DMA15_START_ADDR() 		bfin_read32(DMA15_START_ADDR)
+#define bfin_write_DMA15_START_ADDR(val) 	bfin_write32(DMA15_START_ADDR)
+#define bfin_read_DMA15_CONFIG()		bfin_read16(DMA15_CONFIG)
+#define bfin_write_DMA15_CONFIG(val)		bfin_write16(DMA15_CONFIG, val)
+#define bfin_read_DMA15_X_COUNT()		bfin_read16(DMA15_X_COUNT)
+#define bfin_write_DMA15_X_COUNT(val)		bfin_write16(DMA15_X_COUNT, val)
+#define bfin_read_DMA15_X_MODIFY()		bfin_read16(DMA15_X_MODIFY)
+#define bfin_write_DMA15_X_MODIFY(val) 		bfin_write16(DMA15_X_MODIFY)
+#define bfin_read_DMA15_Y_COUNT()		bfin_read16(DMA15_Y_COUNT)
+#define bfin_write_DMA15_Y_COUNT(val)		bfin_write16(DMA15_Y_COUNT, val)
+#define bfin_read_DMA15_Y_MODIFY()		bfin_read16(DMA15_Y_MODIFY)
+#define bfin_write_DMA15_Y_MODIFY(val) 		bfin_write16(DMA15_Y_MODIFY)
+#define bfin_read_DMA15_CURR_DESC_PTR() 	bfin_read32(DMA15_CURR_DESC_PTR)
+#define bfin_write_DMA15_CURR_DESC_PTR(val) 	bfin_write32(DMA15_CURR_DESC_PTR)
+#define bfin_read_DMA15_CURR_ADDR() 		bfin_read32(DMA15_CURR_ADDR)
+#define bfin_write_DMA15_CURR_ADDR(val) 	bfin_write32(DMA15_CURR_ADDR)
+#define bfin_read_DMA15_IRQ_STATUS()		bfin_read16(DMA15_IRQ_STATUS)
+#define bfin_write_DMA15_IRQ_STATUS(val)	bfin_write16(DMA15_IRQ_STATUS, val)
+#define bfin_read_DMA15_PERIPHERAL_MAP()	bfin_read16(DMA15_PERIPHERAL_MAP)
+#define bfin_write_DMA15_PERIPHERAL_MAP(val)	bfin_write16(DMA15_PERIPHERAL_MAP, val)
+#define bfin_read_DMA15_CURR_X_COUNT()		bfin_read16(DMA15_CURR_X_COUNT)
+#define bfin_write_DMA15_CURR_X_COUNT(val)	bfin_write16(DMA15_CURR_X_COUNT, val)
+#define bfin_read_DMA15_CURR_Y_COUNT()		bfin_read16(DMA15_CURR_Y_COUNT)
+#define bfin_write_DMA15_CURR_Y_COUNT(val)	bfin_write16(DMA15_CURR_Y_COUNT, val)
+
+/* DMA Channel 16 Registers */
+
+#define bfin_read_DMA16_NEXT_DESC_PTR() 	bfin_read32(DMA16_NEXT_DESC_PTR)
+#define bfin_write_DMA16_NEXT_DESC_PTR(val) 	bfin_write32(DMA16_NEXT_DESC_PTR)
+#define bfin_read_DMA16_START_ADDR() 		bfin_read32(DMA16_START_ADDR)
+#define bfin_write_DMA16_START_ADDR(val) 	bfin_write32(DMA16_START_ADDR)
+#define bfin_read_DMA16_CONFIG()		bfin_read16(DMA16_CONFIG)
+#define bfin_write_DMA16_CONFIG(val)		bfin_write16(DMA16_CONFIG, val)
+#define bfin_read_DMA16_X_COUNT()		bfin_read16(DMA16_X_COUNT)
+#define bfin_write_DMA16_X_COUNT(val)		bfin_write16(DMA16_X_COUNT, val)
+#define bfin_read_DMA16_X_MODIFY()		bfin_read16(DMA16_X_MODIFY)
+#define bfin_write_DMA16_X_MODIFY(val) 		bfin_write16(DMA16_X_MODIFY)
+#define bfin_read_DMA16_Y_COUNT()		bfin_read16(DMA16_Y_COUNT)
+#define bfin_write_DMA16_Y_COUNT(val)		bfin_write16(DMA16_Y_COUNT, val)
+#define bfin_read_DMA16_Y_MODIFY()		bfin_read16(DMA16_Y_MODIFY)
+#define bfin_write_DMA16_Y_MODIFY(val) 		bfin_write16(DMA16_Y_MODIFY)
+#define bfin_read_DMA16_CURR_DESC_PTR() 	bfin_read32(DMA16_CURR_DESC_PTR)
+#define bfin_write_DMA16_CURR_DESC_PTR(val) 	bfin_write32(DMA16_CURR_DESC_PTR)
+#define bfin_read_DMA16_CURR_ADDR() 		bfin_read32(DMA16_CURR_ADDR)
+#define bfin_write_DMA16_CURR_ADDR(val) 	bfin_write32(DMA16_CURR_ADDR)
+#define bfin_read_DMA16_IRQ_STATUS()		bfin_read16(DMA16_IRQ_STATUS)
+#define bfin_write_DMA16_IRQ_STATUS(val)	bfin_write16(DMA16_IRQ_STATUS, val)
+#define bfin_read_DMA16_PERIPHERAL_MAP()	bfin_read16(DMA16_PERIPHERAL_MAP)
+#define bfin_write_DMA16_PERIPHERAL_MAP(val)	bfin_write16(DMA16_PERIPHERAL_MAP, val)
+#define bfin_read_DMA16_CURR_X_COUNT()		bfin_read16(DMA16_CURR_X_COUNT)
+#define bfin_write_DMA16_CURR_X_COUNT(val)	bfin_write16(DMA16_CURR_X_COUNT, val)
+#define bfin_read_DMA16_CURR_Y_COUNT()		bfin_read16(DMA16_CURR_Y_COUNT)
+#define bfin_write_DMA16_CURR_Y_COUNT(val)	bfin_write16(DMA16_CURR_Y_COUNT, val)
+
+/* DMA Channel 17 Registers */
+
+#define bfin_read_DMA17_NEXT_DESC_PTR() 	bfin_read32(DMA17_NEXT_DESC_PTR)
+#define bfin_write_DMA17_NEXT_DESC_PTR(val) 	bfin_write32(DMA17_NEXT_DESC_PTR)
+#define bfin_read_DMA17_START_ADDR() 		bfin_read32(DMA17_START_ADDR)
+#define bfin_write_DMA17_START_ADDR(val) 	bfin_write32(DMA17_START_ADDR)
+#define bfin_read_DMA17_CONFIG()		bfin_read16(DMA17_CONFIG)
+#define bfin_write_DMA17_CONFIG(val)		bfin_write16(DMA17_CONFIG, val)
+#define bfin_read_DMA17_X_COUNT()		bfin_read16(DMA17_X_COUNT)
+#define bfin_write_DMA17_X_COUNT(val)		bfin_write16(DMA17_X_COUNT, val)
+#define bfin_read_DMA17_X_MODIFY()		bfin_read16(DMA17_X_MODIFY)
+#define bfin_write_DMA17_X_MODIFY(val) 		bfin_write16(DMA17_X_MODIFY)
+#define bfin_read_DMA17_Y_COUNT()		bfin_read16(DMA17_Y_COUNT)
+#define bfin_write_DMA17_Y_COUNT(val)		bfin_write16(DMA17_Y_COUNT, val)
+#define bfin_read_DMA17_Y_MODIFY()		bfin_read16(DMA17_Y_MODIFY)
+#define bfin_write_DMA17_Y_MODIFY(val) 		bfin_write16(DMA17_Y_MODIFY)
+#define bfin_read_DMA17_CURR_DESC_PTR() 	bfin_read32(DMA17_CURR_DESC_PTR)
+#define bfin_write_DMA17_CURR_DESC_PTR(val) 	bfin_write32(DMA17_CURR_DESC_PTR)
+#define bfin_read_DMA17_CURR_ADDR() 		bfin_read32(DMA17_CURR_ADDR)
+#define bfin_write_DMA17_CURR_ADDR(val) 	bfin_write32(DMA17_CURR_ADDR)
+#define bfin_read_DMA17_IRQ_STATUS()		bfin_read16(DMA17_IRQ_STATUS)
+#define bfin_write_DMA17_IRQ_STATUS(val)	bfin_write16(DMA17_IRQ_STATUS, val)
+#define bfin_read_DMA17_PERIPHERAL_MAP()	bfin_read16(DMA17_PERIPHERAL_MAP)
+#define bfin_write_DMA17_PERIPHERAL_MAP(val)	bfin_write16(DMA17_PERIPHERAL_MAP, val)
+#define bfin_read_DMA17_CURR_X_COUNT()		bfin_read16(DMA17_CURR_X_COUNT)
+#define bfin_write_DMA17_CURR_X_COUNT(val)	bfin_write16(DMA17_CURR_X_COUNT, val)
+#define bfin_read_DMA17_CURR_Y_COUNT()		bfin_read16(DMA17_CURR_Y_COUNT)
+#define bfin_write_DMA17_CURR_Y_COUNT(val)	bfin_write16(DMA17_CURR_Y_COUNT, val)
+
+/* DMA Channel 18 Registers */
+
+#define bfin_read_DMA18_NEXT_DESC_PTR() 	bfin_read32(DMA18_NEXT_DESC_PTR)
+#define bfin_write_DMA18_NEXT_DESC_PTR(val) 	bfin_write32(DMA18_NEXT_DESC_PTR)
+#define bfin_read_DMA18_START_ADDR() 		bfin_read32(DMA18_START_ADDR)
+#define bfin_write_DMA18_START_ADDR(val) 	bfin_write32(DMA18_START_ADDR)
+#define bfin_read_DMA18_CONFIG()		bfin_read16(DMA18_CONFIG)
+#define bfin_write_DMA18_CONFIG(val)		bfin_write16(DMA18_CONFIG, val)
+#define bfin_read_DMA18_X_COUNT()		bfin_read16(DMA18_X_COUNT)
+#define bfin_write_DMA18_X_COUNT(val)		bfin_write16(DMA18_X_COUNT, val)
+#define bfin_read_DMA18_X_MODIFY()		bfin_read16(DMA18_X_MODIFY)
+#define bfin_write_DMA18_X_MODIFY(val) 		bfin_write16(DMA18_X_MODIFY)
+#define bfin_read_DMA18_Y_COUNT()		bfin_read16(DMA18_Y_COUNT)
+#define bfin_write_DMA18_Y_COUNT(val)		bfin_write16(DMA18_Y_COUNT, val)
+#define bfin_read_DMA18_Y_MODIFY()		bfin_read16(DMA18_Y_MODIFY)
+#define bfin_write_DMA18_Y_MODIFY(val) 		bfin_write16(DMA18_Y_MODIFY)
+#define bfin_read_DMA18_CURR_DESC_PTR() 	bfin_read32(DMA18_CURR_DESC_PTR)
+#define bfin_write_DMA18_CURR_DESC_PTR(val) 	bfin_write32(DMA18_CURR_DESC_PTR)
+#define bfin_read_DMA18_CURR_ADDR() 		bfin_read32(DMA18_CURR_ADDR)
+#define bfin_write_DMA18_CURR_ADDR(val) 	bfin_write32(DMA18_CURR_ADDR)
+#define bfin_read_DMA18_IRQ_STATUS()		bfin_read16(DMA18_IRQ_STATUS)
+#define bfin_write_DMA18_IRQ_STATUS(val)	bfin_write16(DMA18_IRQ_STATUS, val)
+#define bfin_read_DMA18_PERIPHERAL_MAP()	bfin_read16(DMA18_PERIPHERAL_MAP)
+#define bfin_write_DMA18_PERIPHERAL_MAP(val)	bfin_write16(DMA18_PERIPHERAL_MAP, val)
+#define bfin_read_DMA18_CURR_X_COUNT()		bfin_read16(DMA18_CURR_X_COUNT)
+#define bfin_write_DMA18_CURR_X_COUNT(val)	bfin_write16(DMA18_CURR_X_COUNT, val)
+#define bfin_read_DMA18_CURR_Y_COUNT()		bfin_read16(DMA18_CURR_Y_COUNT)
+#define bfin_write_DMA18_CURR_Y_COUNT(val)	bfin_write16(DMA18_CURR_Y_COUNT, val)
+
+/* DMA Channel 19 Registers */
+
+#define bfin_read_DMA19_NEXT_DESC_PTR() 	bfin_read32(DMA19_NEXT_DESC_PTR)
+#define bfin_write_DMA19_NEXT_DESC_PTR(val) 	bfin_write32(DMA19_NEXT_DESC_PTR)
+#define bfin_read_DMA19_START_ADDR() 		bfin_read32(DMA19_START_ADDR)
+#define bfin_write_DMA19_START_ADDR(val) 	bfin_write32(DMA19_START_ADDR)
+#define bfin_read_DMA19_CONFIG()		bfin_read16(DMA19_CONFIG)
+#define bfin_write_DMA19_CONFIG(val)		bfin_write16(DMA19_CONFIG, val)
+#define bfin_read_DMA19_X_COUNT()		bfin_read16(DMA19_X_COUNT)
+#define bfin_write_DMA19_X_COUNT(val)		bfin_write16(DMA19_X_COUNT, val)
+#define bfin_read_DMA19_X_MODIFY()		bfin_read16(DMA19_X_MODIFY)
+#define bfin_write_DMA19_X_MODIFY(val) 		bfin_write16(DMA19_X_MODIFY)
+#define bfin_read_DMA19_Y_COUNT()		bfin_read16(DMA19_Y_COUNT)
+#define bfin_write_DMA19_Y_COUNT(val)		bfin_write16(DMA19_Y_COUNT, val)
+#define bfin_read_DMA19_Y_MODIFY()		bfin_read16(DMA19_Y_MODIFY)
+#define bfin_write_DMA19_Y_MODIFY(val) 		bfin_write16(DMA19_Y_MODIFY)
+#define bfin_read_DMA19_CURR_DESC_PTR() 	bfin_read32(DMA19_CURR_DESC_PTR)
+#define bfin_write_DMA19_CURR_DESC_PTR(val) 	bfin_write32(DMA19_CURR_DESC_PTR)
+#define bfin_read_DMA19_CURR_ADDR() 		bfin_read32(DMA19_CURR_ADDR)
+#define bfin_write_DMA19_CURR_ADDR(val) 	bfin_write32(DMA19_CURR_ADDR)
+#define bfin_read_DMA19_IRQ_STATUS()		bfin_read16(DMA19_IRQ_STATUS)
+#define bfin_write_DMA19_IRQ_STATUS(val)	bfin_write16(DMA19_IRQ_STATUS, val)
+#define bfin_read_DMA19_PERIPHERAL_MAP()	bfin_read16(DMA19_PERIPHERAL_MAP)
+#define bfin_write_DMA19_PERIPHERAL_MAP(val)	bfin_write16(DMA19_PERIPHERAL_MAP, val)
+#define bfin_read_DMA19_CURR_X_COUNT()		bfin_read16(DMA19_CURR_X_COUNT)
+#define bfin_write_DMA19_CURR_X_COUNT(val)	bfin_write16(DMA19_CURR_X_COUNT, val)
+#define bfin_read_DMA19_CURR_Y_COUNT()		bfin_read16(DMA19_CURR_Y_COUNT)
+#define bfin_write_DMA19_CURR_Y_COUNT(val)	bfin_write16(DMA19_CURR_Y_COUNT, val)
+
+/* DMA Channel 20 Registers */
+
+#define bfin_read_DMA20_NEXT_DESC_PTR() 	bfin_read32(DMA20_NEXT_DESC_PTR)
+#define bfin_write_DMA20_NEXT_DESC_PTR(val) 	bfin_write32(DMA20_NEXT_DESC_PTR)
+#define bfin_read_DMA20_START_ADDR() 		bfin_read32(DMA20_START_ADDR)
+#define bfin_write_DMA20_START_ADDR(val) 	bfin_write32(DMA20_START_ADDR)
+#define bfin_read_DMA20_CONFIG()		bfin_read16(DMA20_CONFIG)
+#define bfin_write_DMA20_CONFIG(val)		bfin_write16(DMA20_CONFIG, val)
+#define bfin_read_DMA20_X_COUNT()		bfin_read16(DMA20_X_COUNT)
+#define bfin_write_DMA20_X_COUNT(val)		bfin_write16(DMA20_X_COUNT, val)
+#define bfin_read_DMA20_X_MODIFY()		bfin_read16(DMA20_X_MODIFY)
+#define bfin_write_DMA20_X_MODIFY(val) 		bfin_write16(DMA20_X_MODIFY)
+#define bfin_read_DMA20_Y_COUNT()		bfin_read16(DMA20_Y_COUNT)
+#define bfin_write_DMA20_Y_COUNT(val)		bfin_write16(DMA20_Y_COUNT, val)
+#define bfin_read_DMA20_Y_MODIFY()		bfin_read16(DMA20_Y_MODIFY)
+#define bfin_write_DMA20_Y_MODIFY(val) 		bfin_write16(DMA20_Y_MODIFY)
+#define bfin_read_DMA20_CURR_DESC_PTR() 	bfin_read32(DMA20_CURR_DESC_PTR)
+#define bfin_write_DMA20_CURR_DESC_PTR(val) 	bfin_write32(DMA20_CURR_DESC_PTR)
+#define bfin_read_DMA20_CURR_ADDR() 		bfin_read32(DMA20_CURR_ADDR)
+#define bfin_write_DMA20_CURR_ADDR(val) 	bfin_write32(DMA20_CURR_ADDR)
+#define bfin_read_DMA20_IRQ_STATUS()		bfin_read16(DMA20_IRQ_STATUS)
+#define bfin_write_DMA20_IRQ_STATUS(val)	bfin_write16(DMA20_IRQ_STATUS, val)
+#define bfin_read_DMA20_PERIPHERAL_MAP()	bfin_read16(DMA20_PERIPHERAL_MAP)
+#define bfin_write_DMA20_PERIPHERAL_MAP(val)	bfin_write16(DMA20_PERIPHERAL_MAP, val)
+#define bfin_read_DMA20_CURR_X_COUNT()		bfin_read16(DMA20_CURR_X_COUNT)
+#define bfin_write_DMA20_CURR_X_COUNT(val)	bfin_write16(DMA20_CURR_X_COUNT, val)
+#define bfin_read_DMA20_CURR_Y_COUNT()		bfin_read16(DMA20_CURR_Y_COUNT)
+#define bfin_write_DMA20_CURR_Y_COUNT(val)	bfin_write16(DMA20_CURR_Y_COUNT, val)
+
+/* DMA Channel 21 Registers */
+
+#define bfin_read_DMA21_NEXT_DESC_PTR() 	bfin_read32(DMA21_NEXT_DESC_PTR)
+#define bfin_write_DMA21_NEXT_DESC_PTR(val) 	bfin_write32(DMA21_NEXT_DESC_PTR)
+#define bfin_read_DMA21_START_ADDR() 		bfin_read32(DMA21_START_ADDR)
+#define bfin_write_DMA21_START_ADDR(val) 	bfin_write32(DMA21_START_ADDR)
+#define bfin_read_DMA21_CONFIG()		bfin_read16(DMA21_CONFIG)
+#define bfin_write_DMA21_CONFIG(val)		bfin_write16(DMA21_CONFIG, val)
+#define bfin_read_DMA21_X_COUNT()		bfin_read16(DMA21_X_COUNT)
+#define bfin_write_DMA21_X_COUNT(val)		bfin_write16(DMA21_X_COUNT, val)
+#define bfin_read_DMA21_X_MODIFY()		bfin_read16(DMA21_X_MODIFY)
+#define bfin_write_DMA21_X_MODIFY(val) 		bfin_write16(DMA21_X_MODIFY)
+#define bfin_read_DMA21_Y_COUNT()		bfin_read16(DMA21_Y_COUNT)
+#define bfin_write_DMA21_Y_COUNT(val)		bfin_write16(DMA21_Y_COUNT, val)
+#define bfin_read_DMA21_Y_MODIFY()		bfin_read16(DMA21_Y_MODIFY)
+#define bfin_write_DMA21_Y_MODIFY(val) 		bfin_write16(DMA21_Y_MODIFY)
+#define bfin_read_DMA21_CURR_DESC_PTR() 	bfin_read32(DMA21_CURR_DESC_PTR)
+#define bfin_write_DMA21_CURR_DESC_PTR(val) 	bfin_write32(DMA21_CURR_DESC_PTR)
+#define bfin_read_DMA21_CURR_ADDR() 		bfin_read32(DMA21_CURR_ADDR)
+#define bfin_write_DMA21_CURR_ADDR(val) 	bfin_write32(DMA21_CURR_ADDR)
+#define bfin_read_DMA21_IRQ_STATUS()		bfin_read16(DMA21_IRQ_STATUS)
+#define bfin_write_DMA21_IRQ_STATUS(val)	bfin_write16(DMA21_IRQ_STATUS, val)
+#define bfin_read_DMA21_PERIPHERAL_MAP()	bfin_read16(DMA21_PERIPHERAL_MAP)
+#define bfin_write_DMA21_PERIPHERAL_MAP(val)	bfin_write16(DMA21_PERIPHERAL_MAP, val)
+#define bfin_read_DMA21_CURR_X_COUNT()		bfin_read16(DMA21_CURR_X_COUNT)
+#define bfin_write_DMA21_CURR_X_COUNT(val)	bfin_write16(DMA21_CURR_X_COUNT, val)
+#define bfin_read_DMA21_CURR_Y_COUNT()		bfin_read16(DMA21_CURR_Y_COUNT)
+#define bfin_write_DMA21_CURR_Y_COUNT(val)	bfin_write16(DMA21_CURR_Y_COUNT, val)
+
+/* DMA Channel 22 Registers */
+
+#define bfin_read_DMA22_NEXT_DESC_PTR() 	bfin_read32(DMA22_NEXT_DESC_PTR)
+#define bfin_write_DMA22_NEXT_DESC_PTR(val) 	bfin_write32(DMA22_NEXT_DESC_PTR)
+#define bfin_read_DMA22_START_ADDR() 		bfin_read32(DMA22_START_ADDR)
+#define bfin_write_DMA22_START_ADDR(val) 	bfin_write32(DMA22_START_ADDR)
+#define bfin_read_DMA22_CONFIG()		bfin_read16(DMA22_CONFIG)
+#define bfin_write_DMA22_CONFIG(val)		bfin_write16(DMA22_CONFIG, val)
+#define bfin_read_DMA22_X_COUNT()		bfin_read16(DMA22_X_COUNT)
+#define bfin_write_DMA22_X_COUNT(val)		bfin_write16(DMA22_X_COUNT, val)
+#define bfin_read_DMA22_X_MODIFY()		bfin_read16(DMA22_X_MODIFY)
+#define bfin_write_DMA22_X_MODIFY(val) 		bfin_write16(DMA22_X_MODIFY)
+#define bfin_read_DMA22_Y_COUNT()		bfin_read16(DMA22_Y_COUNT)
+#define bfin_write_DMA22_Y_COUNT(val)		bfin_write16(DMA22_Y_COUNT, val)
+#define bfin_read_DMA22_Y_MODIFY()		bfin_read16(DMA22_Y_MODIFY)
+#define bfin_write_DMA22_Y_MODIFY(val) 		bfin_write16(DMA22_Y_MODIFY)
+#define bfin_read_DMA22_CURR_DESC_PTR() 	bfin_read32(DMA22_CURR_DESC_PTR)
+#define bfin_write_DMA22_CURR_DESC_PTR(val) 	bfin_write32(DMA22_CURR_DESC_PTR)
+#define bfin_read_DMA22_CURR_ADDR() 		bfin_read32(DMA22_CURR_ADDR)
+#define bfin_write_DMA22_CURR_ADDR(val) 	bfin_write32(DMA22_CURR_ADDR)
+#define bfin_read_DMA22_IRQ_STATUS()		bfin_read16(DMA22_IRQ_STATUS)
+#define bfin_write_DMA22_IRQ_STATUS(val)	bfin_write16(DMA22_IRQ_STATUS, val)
+#define bfin_read_DMA22_PERIPHERAL_MAP()	bfin_read16(DMA22_PERIPHERAL_MAP)
+#define bfin_write_DMA22_PERIPHERAL_MAP(val)	bfin_write16(DMA22_PERIPHERAL_MAP, val)
+#define bfin_read_DMA22_CURR_X_COUNT()		bfin_read16(DMA22_CURR_X_COUNT)
+#define bfin_write_DMA22_CURR_X_COUNT(val)	bfin_write16(DMA22_CURR_X_COUNT, val)
+#define bfin_read_DMA22_CURR_Y_COUNT()		bfin_read16(DMA22_CURR_Y_COUNT)
+#define bfin_write_DMA22_CURR_Y_COUNT(val)	bfin_write16(DMA22_CURR_Y_COUNT, val)
+
+/* DMA Channel 23 Registers */
+
+#define bfin_read_DMA23_NEXT_DESC_PTR() 		bfin_read32(DMA23_NEXT_DESC_PTR)
+#define bfin_write_DMA23_NEXT_DESC_PTR(val) 		bfin_write32(DMA23_NEXT_DESC_PTR)
+#define bfin_read_DMA23_START_ADDR() 			bfin_read32(DMA23_START_ADDR)
+#define bfin_write_DMA23_START_ADDR(val) 		bfin_write32(DMA23_START_ADDR)
+#define bfin_read_DMA23_CONFIG()			bfin_read16(DMA23_CONFIG)
+#define bfin_write_DMA23_CONFIG(val)			bfin_write16(DMA23_CONFIG, val)
+#define bfin_read_DMA23_X_COUNT()			bfin_read16(DMA23_X_COUNT)
+#define bfin_write_DMA23_X_COUNT(val)			bfin_write16(DMA23_X_COUNT, val)
+#define bfin_read_DMA23_X_MODIFY()			bfin_read16(DMA23_X_MODIFY)
+#define bfin_write_DMA23_X_MODIFY(val) 			bfin_write16(DMA23_X_MODIFY)
+#define bfin_read_DMA23_Y_COUNT()			bfin_read16(DMA23_Y_COUNT)
+#define bfin_write_DMA23_Y_COUNT(val)			bfin_write16(DMA23_Y_COUNT, val)
+#define bfin_read_DMA23_Y_MODIFY()			bfin_read16(DMA23_Y_MODIFY)
+#define bfin_write_DMA23_Y_MODIFY(val) 			bfin_write16(DMA23_Y_MODIFY)
+#define bfin_read_DMA23_CURR_DESC_PTR() 		bfin_read32(DMA23_CURR_DESC_PTR)
+#define bfin_write_DMA23_CURR_DESC_PTR(val) 		bfin_write32(DMA23_CURR_DESC_PTR)
+#define bfin_read_DMA23_CURR_ADDR() 			bfin_read32(DMA23_CURR_ADDR)
+#define bfin_write_DMA23_CURR_ADDR(val) 		bfin_write32(DMA23_CURR_ADDR)
+#define bfin_read_DMA23_IRQ_STATUS()			bfin_read16(DMA23_IRQ_STATUS)
+#define bfin_write_DMA23_IRQ_STATUS(val)		bfin_write16(DMA23_IRQ_STATUS, val)
+#define bfin_read_DMA23_PERIPHERAL_MAP()		bfin_read16(DMA23_PERIPHERAL_MAP)
+#define bfin_write_DMA23_PERIPHERAL_MAP(val)		bfin_write16(DMA23_PERIPHERAL_MAP, val)
+#define bfin_read_DMA23_CURR_X_COUNT()			bfin_read16(DMA23_CURR_X_COUNT)
+#define bfin_write_DMA23_CURR_X_COUNT(val)		bfin_write16(DMA23_CURR_X_COUNT, val)
+#define bfin_read_DMA23_CURR_Y_COUNT()			bfin_read16(DMA23_CURR_Y_COUNT)
+#define bfin_write_DMA23_CURR_Y_COUNT(val)		bfin_write16(DMA23_CURR_Y_COUNT, val)
+
+/* MDMA Stream 2 Registers */
+
+#define bfin_read_MDMA_D2_NEXT_DESC_PTR() 		bfin_read32(MDMA_D2_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_D2_NEXT_DESC_PTR)
+#define bfin_read_MDMA_D2_START_ADDR() 			bfin_read32(MDMA_D2_START_ADDR)
+#define bfin_write_MDMA_D2_START_ADDR(val) 		bfin_write32(MDMA_D2_START_ADDR)
+#define bfin_read_MDMA_D2_CONFIG()			bfin_read16(MDMA_D2_CONFIG)
+#define bfin_write_MDMA_D2_CONFIG(val)			bfin_write16(MDMA_D2_CONFIG, val)
+#define bfin_read_MDMA_D2_X_COUNT()			bfin_read16(MDMA_D2_X_COUNT)
+#define bfin_write_MDMA_D2_X_COUNT(val)			bfin_write16(MDMA_D2_X_COUNT, val)
+#define bfin_read_MDMA_D2_X_MODIFY()			bfin_read16(MDMA_D2_X_MODIFY)
+#define bfin_write_MDMA_D2_X_MODIFY(val) 		bfin_write16(MDMA_D2_X_MODIFY)
+#define bfin_read_MDMA_D2_Y_COUNT()			bfin_read16(MDMA_D2_Y_COUNT)
+#define bfin_write_MDMA_D2_Y_COUNT(val)			bfin_write16(MDMA_D2_Y_COUNT, val)
+#define bfin_read_MDMA_D2_Y_MODIFY()			bfin_read16(MDMA_D2_Y_MODIFY)
+#define bfin_write_MDMA_D2_Y_MODIFY(val) 		bfin_write16(MDMA_D2_Y_MODIFY)
+#define bfin_read_MDMA_D2_CURR_DESC_PTR() 		bfin_read32(MDMA_D2_CURR_DESC_PTR)
+#define bfin_write_MDMA_D2_CURR_DESC_PTR(val) 		bfin_write32(MDMA_D2_CURR_DESC_PTR)
+#define bfin_read_MDMA_D2_CURR_ADDR() 			bfin_read32(MDMA_D2_CURR_ADDR)
+#define bfin_write_MDMA_D2_CURR_ADDR(val) 		bfin_write32(MDMA_D2_CURR_ADDR)
+#define bfin_read_MDMA_D2_IRQ_STATUS()			bfin_read16(MDMA_D2_IRQ_STATUS)
+#define bfin_write_MDMA_D2_IRQ_STATUS(val)		bfin_write16(MDMA_D2_IRQ_STATUS, val)
+#define bfin_read_MDMA_D2_PERIPHERAL_MAP()		bfin_read16(MDMA_D2_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D2_PERIPHERAL_MAP(val)		bfin_write16(MDMA_D2_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_D2_CURR_X_COUNT()		bfin_read16(MDMA_D2_CURR_X_COUNT)
+#define bfin_write_MDMA_D2_CURR_X_COUNT(val)		bfin_write16(MDMA_D2_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D2_CURR_Y_COUNT()		bfin_read16(MDMA_D2_CURR_Y_COUNT)
+#define bfin_write_MDMA_D2_CURR_Y_COUNT(val)		bfin_write16(MDMA_D2_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S2_NEXT_DESC_PTR() 		bfin_read32(MDMA_S2_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_S2_NEXT_DESC_PTR)
+#define bfin_read_MDMA_S2_START_ADDR() 			bfin_read32(MDMA_S2_START_ADDR)
+#define bfin_write_MDMA_S2_START_ADDR(val) 		bfin_write32(MDMA_S2_START_ADDR)
+#define bfin_read_MDMA_S2_CONFIG()			bfin_read16(MDMA_S2_CONFIG)
+#define bfin_write_MDMA_S2_CONFIG(val)			bfin_write16(MDMA_S2_CONFIG, val)
+#define bfin_read_MDMA_S2_X_COUNT()			bfin_read16(MDMA_S2_X_COUNT)
+#define bfin_write_MDMA_S2_X_COUNT(val)			bfin_write16(MDMA_S2_X_COUNT, val)
+#define bfin_read_MDMA_S2_X_MODIFY()			bfin_read16(MDMA_S2_X_MODIFY)
+#define bfin_write_MDMA_S2_X_MODIFY(val) 		bfin_write16(MDMA_S2_X_MODIFY)
+#define bfin_read_MDMA_S2_Y_COUNT()			bfin_read16(MDMA_S2_Y_COUNT)
+#define bfin_write_MDMA_S2_Y_COUNT(val)			bfin_write16(MDMA_S2_Y_COUNT, val)
+#define bfin_read_MDMA_S2_Y_MODIFY()			bfin_read16(MDMA_S2_Y_MODIFY)
+#define bfin_write_MDMA_S2_Y_MODIFY(val) 		bfin_write16(MDMA_S2_Y_MODIFY)
+#define bfin_read_MDMA_S2_CURR_DESC_PTR() 		bfin_read32(MDMA_S2_CURR_DESC_PTR)
+#define bfin_write_MDMA_S2_CURR_DESC_PTR(val) 		bfin_write32(MDMA_S2_CURR_DESC_PTR)
+#define bfin_read_MDMA_S2_CURR_ADDR() 			bfin_read32(MDMA_S2_CURR_ADDR)
+#define bfin_write_MDMA_S2_CURR_ADDR(val) 		bfin_write32(MDMA_S2_CURR_ADDR)
+#define bfin_read_MDMA_S2_IRQ_STATUS()			bfin_read16(MDMA_S2_IRQ_STATUS)
+#define bfin_write_MDMA_S2_IRQ_STATUS(val)		bfin_write16(MDMA_S2_IRQ_STATUS, val)
+#define bfin_read_MDMA_S2_PERIPHERAL_MAP()		bfin_read16(MDMA_S2_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S2_PERIPHERAL_MAP(val)		bfin_write16(MDMA_S2_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_S2_CURR_X_COUNT()		bfin_read16(MDMA_S2_CURR_X_COUNT)
+#define bfin_write_MDMA_S2_CURR_X_COUNT(val)		bfin_write16(MDMA_S2_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S2_CURR_Y_COUNT()		bfin_read16(MDMA_S2_CURR_Y_COUNT)
+#define bfin_write_MDMA_S2_CURR_Y_COUNT(val)		bfin_write16(MDMA_S2_CURR_Y_COUNT, val)
+
+/* MDMA Stream 3 Registers */
+
+#define bfin_read_MDMA_D3_NEXT_DESC_PTR() 		bfin_read32(MDMA_D3_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_D3_NEXT_DESC_PTR)
+#define bfin_read_MDMA_D3_START_ADDR() 			bfin_read32(MDMA_D3_START_ADDR)
+#define bfin_write_MDMA_D3_START_ADDR(val) 		bfin_write32(MDMA_D3_START_ADDR)
+#define bfin_read_MDMA_D3_CONFIG()			bfin_read16(MDMA_D3_CONFIG)
+#define bfin_write_MDMA_D3_CONFIG(val)			bfin_write16(MDMA_D3_CONFIG, val)
+#define bfin_read_MDMA_D3_X_COUNT()			bfin_read16(MDMA_D3_X_COUNT)
+#define bfin_write_MDMA_D3_X_COUNT(val)			bfin_write16(MDMA_D3_X_COUNT, val)
+#define bfin_read_MDMA_D3_X_MODIFY()			bfin_read16(MDMA_D3_X_MODIFY)
+#define bfin_write_MDMA_D3_X_MODIFY(val) 		bfin_write16(MDMA_D3_X_MODIFY)
+#define bfin_read_MDMA_D3_Y_COUNT()			bfin_read16(MDMA_D3_Y_COUNT)
+#define bfin_write_MDMA_D3_Y_COUNT(val)			bfin_write16(MDMA_D3_Y_COUNT, val)
+#define bfin_read_MDMA_D3_Y_MODIFY()			bfin_read16(MDMA_D3_Y_MODIFY)
+#define bfin_write_MDMA_D3_Y_MODIFY(val) 		bfin_write16(MDMA_D3_Y_MODIFY)
+#define bfin_read_MDMA_D3_CURR_DESC_PTR() 		bfin_read32(MDMA_D3_CURR_DESC_PTR)
+#define bfin_write_MDMA_D3_CURR_DESC_PTR(val) 		bfin_write32(MDMA_D3_CURR_DESC_PTR)
+#define bfin_read_MDMA_D3_CURR_ADDR() 			bfin_read32(MDMA_D3_CURR_ADDR)
+#define bfin_write_MDMA_D3_CURR_ADDR(val) 		bfin_write32(MDMA_D3_CURR_ADDR)
+#define bfin_read_MDMA_D3_IRQ_STATUS()			bfin_read16(MDMA_D3_IRQ_STATUS)
+#define bfin_write_MDMA_D3_IRQ_STATUS(val)		bfin_write16(MDMA_D3_IRQ_STATUS, val)
+#define bfin_read_MDMA_D3_PERIPHERAL_MAP()		bfin_read16(MDMA_D3_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D3_PERIPHERAL_MAP(val)		bfin_write16(MDMA_D3_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_D3_CURR_X_COUNT()		bfin_read16(MDMA_D3_CURR_X_COUNT)
+#define bfin_write_MDMA_D3_CURR_X_COUNT(val)		bfin_write16(MDMA_D3_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D3_CURR_Y_COUNT()		bfin_read16(MDMA_D3_CURR_Y_COUNT)
+#define bfin_write_MDMA_D3_CURR_Y_COUNT(val)		bfin_write16(MDMA_D3_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S3_NEXT_DESC_PTR() 		bfin_read32(MDMA_S3_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_S3_NEXT_DESC_PTR)
+#define bfin_read_MDMA_S3_START_ADDR() 			bfin_read32(MDMA_S3_START_ADDR)
+#define bfin_write_MDMA_S3_START_ADDR(val) 		bfin_write32(MDMA_S3_START_ADDR)
+#define bfin_read_MDMA_S3_CONFIG()			bfin_read16(MDMA_S3_CONFIG)
+#define bfin_write_MDMA_S3_CONFIG(val)			bfin_write16(MDMA_S3_CONFIG, val)
+#define bfin_read_MDMA_S3_X_COUNT()			bfin_read16(MDMA_S3_X_COUNT)
+#define bfin_write_MDMA_S3_X_COUNT(val)			bfin_write16(MDMA_S3_X_COUNT, val)
+#define bfin_read_MDMA_S3_X_MODIFY()			bfin_read16(MDMA_S3_X_MODIFY)
+#define bfin_write_MDMA_S3_X_MODIFY(val) 		bfin_write16(MDMA_S3_X_MODIFY)
+#define bfin_read_MDMA_S3_Y_COUNT()			bfin_read16(MDMA_S3_Y_COUNT)
+#define bfin_write_MDMA_S3_Y_COUNT(val)			bfin_write16(MDMA_S3_Y_COUNT, val)
+#define bfin_read_MDMA_S3_Y_MODIFY()			bfin_read16(MDMA_S3_Y_MODIFY)
+#define bfin_write_MDMA_S3_Y_MODIFY(val) 		bfin_write16(MDMA_S3_Y_MODIFY)
+#define bfin_read_MDMA_S3_CURR_DESC_PTR() 		bfin_read32(MDMA_S3_CURR_DESC_PTR)
+#define bfin_write_MDMA_S3_CURR_DESC_PTR(val) 		bfin_write32(MDMA_S3_CURR_DESC_PTR)
+#define bfin_read_MDMA_S3_CURR_ADDR() 			bfin_read32(MDMA_S3_CURR_ADDR)
+#define bfin_write_MDMA_S3_CURR_ADDR(val) 		bfin_write32(MDMA_S3_CURR_ADDR)
+#define bfin_read_MDMA_S3_IRQ_STATUS()			bfin_read16(MDMA_S3_IRQ_STATUS)
+#define bfin_write_MDMA_S3_IRQ_STATUS(val)		bfin_write16(MDMA_S3_IRQ_STATUS, val)
+#define bfin_read_MDMA_S3_PERIPHERAL_MAP()		bfin_read16(MDMA_S3_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S3_PERIPHERAL_MAP(val)		bfin_write16(MDMA_S3_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_S3_CURR_X_COUNT()		bfin_read16(MDMA_S3_CURR_X_COUNT)
+#define bfin_write_MDMA_S3_CURR_X_COUNT(val)		bfin_write16(MDMA_S3_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S3_CURR_Y_COUNT()		bfin_read16(MDMA_S3_CURR_Y_COUNT)
+#define bfin_write_MDMA_S3_CURR_Y_COUNT(val)		bfin_write16(MDMA_S3_CURR_Y_COUNT, val)
+
+/* UART1 Registers */
+
+#define bfin_read_UART1_DLL()			bfin_read16(UART1_DLL)
+#define bfin_write_UART1_DLL(val)		bfin_write16(UART1_DLL, val)
+#define bfin_read_UART1_DLH()			bfin_read16(UART1_DLH)
+#define bfin_write_UART1_DLH(val)		bfin_write16(UART1_DLH, val)
+#define bfin_read_UART1_GCTL()			bfin_read16(UART1_GCTL)
+#define bfin_write_UART1_GCTL(val)		bfin_write16(UART1_GCTL, val)
+#define bfin_read_UART1_LCR()			bfin_read16(UART1_LCR)
+#define bfin_write_UART1_LCR(val)		bfin_write16(UART1_LCR, val)
+#define bfin_read_UART1_MCR()			bfin_read16(UART1_MCR)
+#define bfin_write_UART1_MCR(val)		bfin_write16(UART1_MCR, val)
+#define bfin_read_UART1_LSR()			bfin_read16(UART1_LSR)
+#define bfin_write_UART1_LSR(val)		bfin_write16(UART1_LSR, val)
+#define bfin_read_UART1_MSR()			bfin_read16(UART1_MSR)
+#define bfin_write_UART1_MSR(val)		bfin_write16(UART1_MSR, val)
+#define bfin_read_UART1_SCR()			bfin_read16(UART1_SCR)
+#define bfin_write_UART1_SCR(val)		bfin_write16(UART1_SCR, val)
+#define bfin_read_UART1_IER_SET()		bfin_read16(UART1_IER_SET)
+#define bfin_write_UART1_IER_SET(val)		bfin_write16(UART1_IER_SET, val)
+#define bfin_read_UART1_IER_CLEAR()		bfin_read16(UART1_IER_CLEAR)
+#define bfin_write_UART1_IER_CLEAR(val)		bfin_write16(UART1_IER_CLEAR, val)
+#define bfin_read_UART1_THR()			bfin_read16(UART1_THR)
+#define bfin_write_UART1_THR(val)		bfin_write16(UART1_THR, val)
+#define bfin_read_UART1_RBR()			bfin_read16(UART1_RBR)
+#define bfin_write_UART1_RBR(val)		bfin_write16(UART1_RBR, val)
+
+/* UART2 is not defined in the shared file because it is not available on the ADSP-BF542 and ADSP-BF544 bfin_read_()rocessors */
+
+/* SPI1 Registers */
+
+#define bfin_read_SPI1_CTL()			bfin_read16(SPI1_CTL)
+#define bfin_write_SPI1_CTL(val)		bfin_write16(SPI1_CTL, val)
+#define bfin_read_SPI1_FLG()			bfin_read16(SPI1_FLG)
+#define bfin_write_SPI1_FLG(val)		bfin_write16(SPI1_FLG, val)
+#define bfin_read_SPI1_STAT()			bfin_read16(SPI1_STAT)
+#define bfin_write_SPI1_STAT(val)		bfin_write16(SPI1_STAT, val)
+#define bfin_read_SPI1_TDBR()			bfin_read16(SPI1_TDBR)
+#define bfin_write_SPI1_TDBR(val)		bfin_write16(SPI1_TDBR, val)
+#define bfin_read_SPI1_RDBR()			bfin_read16(SPI1_RDBR)
+#define bfin_write_SPI1_RDBR(val)		bfin_write16(SPI1_RDBR, val)
+#define bfin_read_SPI1_BAUD()			bfin_read16(SPI1_BAUD)
+#define bfin_write_SPI1_BAUD(val)		bfin_write16(SPI1_BAUD, val)
+#define bfin_read_SPI1_SHADOW()			bfin_read16(SPI1_SHADOW)
+#define bfin_write_SPI1_SHADOW(val)		bfin_write16(SPI1_SHADOW, val)
+
+/* SPORT2 Registers */
+
+#define bfin_read_SPORT2_TCR1()			bfin_read16(SPORT2_TCR1)
+#define bfin_write_SPORT2_TCR1(val)		bfin_write16(SPORT2_TCR1, val)
+#define bfin_read_SPORT2_TCR2()			bfin_read16(SPORT2_TCR2)
+#define bfin_write_SPORT2_TCR2(val)		bfin_write16(SPORT2_TCR2, val)
+#define bfin_read_SPORT2_TCLKDIV()		bfin_read16(SPORT2_TCLKDIV)
+#define bfin_write_SPORT2_TCLKDIV(val)		bfin_write16(SPORT2_TCLKDIV, val)
+#define bfin_read_SPORT2_TFSDIV()		bfin_read16(SPORT2_TFSDIV)
+#define bfin_write_SPORT2_TFSDIV(val)		bfin_write16(SPORT2_TFSDIV, val)
+#define bfin_read_SPORT2_TX()			bfin_read32(SPORT2_TX)
+#define bfin_write_SPORT2_TX(val)		bfin_write32(SPORT2_TX, val)
+#define bfin_read_SPORT2_RX()			bfin_read32(SPORT2_RX)
+#define bfin_write_SPORT2_RX(val)		bfin_write32(SPORT2_RX, val)
+#define bfin_read_SPORT2_RCR1()			bfin_read16(SPORT2_RCR1)
+#define bfin_write_SPORT2_RCR1(val)		bfin_write16(SPORT2_RCR1, val)
+#define bfin_read_SPORT2_RCR2()			bfin_read16(SPORT2_RCR2)
+#define bfin_write_SPORT2_RCR2(val)		bfin_write16(SPORT2_RCR2, val)
+#define bfin_read_SPORT2_RCLKDIV()		bfin_read16(SPORT2_RCLKDIV)
+#define bfin_write_SPORT2_RCLKDIV(val)		bfin_write16(SPORT2_RCLKDIV, val)
+#define bfin_read_SPORT2_RFSDIV()		bfin_read16(SPORT2_RFSDIV)
+#define bfin_write_SPORT2_RFSDIV(val)		bfin_write16(SPORT2_RFSDIV, val)
+#define bfin_read_SPORT2_STAT()			bfin_read16(SPORT2_STAT)
+#define bfin_write_SPORT2_STAT(val)		bfin_write16(SPORT2_STAT, val)
+#define bfin_read_SPORT2_CHNL()			bfin_read16(SPORT2_CHNL)
+#define bfin_write_SPORT2_CHNL(val)		bfin_write16(SPORT2_CHNL, val)
+#define bfin_read_SPORT2_MCMC1()		bfin_read16(SPORT2_MCMC1)
+#define bfin_write_SPORT2_MCMC1(val)		bfin_write16(SPORT2_MCMC1, val)
+#define bfin_read_SPORT2_MCMC2()		bfin_read16(SPORT2_MCMC2)
+#define bfin_write_SPORT2_MCMC2(val)		bfin_write16(SPORT2_MCMC2, val)
+#define bfin_read_SPORT2_MTCS0()		bfin_read32(SPORT2_MTCS0)
+#define bfin_write_SPORT2_MTCS0(val)		bfin_write32(SPORT2_MTCS0, val)
+#define bfin_read_SPORT2_MTCS1()		bfin_read32(SPORT2_MTCS1)
+#define bfin_write_SPORT2_MTCS1(val)		bfin_write32(SPORT2_MTCS1, val)
+#define bfin_read_SPORT2_MTCS2()		bfin_read32(SPORT2_MTCS2)
+#define bfin_write_SPORT2_MTCS2(val)		bfin_write32(SPORT2_MTCS2, val)
+#define bfin_read_SPORT2_MTCS3()		bfin_read32(SPORT2_MTCS3)
+#define bfin_write_SPORT2_MTCS3(val)		bfin_write32(SPORT2_MTCS3, val)
+#define bfin_read_SPORT2_MRCS0()		bfin_read32(SPORT2_MRCS0)
+#define bfin_write_SPORT2_MRCS0(val)		bfin_write32(SPORT2_MRCS0, val)
+#define bfin_read_SPORT2_MRCS1()		bfin_read32(SPORT2_MRCS1)
+#define bfin_write_SPORT2_MRCS1(val)		bfin_write32(SPORT2_MRCS1, val)
+#define bfin_read_SPORT2_MRCS2()		bfin_read32(SPORT2_MRCS2)
+#define bfin_write_SPORT2_MRCS2(val)		bfin_write32(SPORT2_MRCS2, val)
+#define bfin_read_SPORT2_MRCS3()		bfin_read32(SPORT2_MRCS3)
+#define bfin_write_SPORT2_MRCS3(val)		bfin_write32(SPORT2_MRCS3, val)
+
+/* SPORT3 Registers */
+
+#define bfin_read_SPORT3_TCR1()			bfin_read16(SPORT3_TCR1)
+#define bfin_write_SPORT3_TCR1(val)		bfin_write16(SPORT3_TCR1, val)
+#define bfin_read_SPORT3_TCR2()			bfin_read16(SPORT3_TCR2)
+#define bfin_write_SPORT3_TCR2(val)		bfin_write16(SPORT3_TCR2, val)
+#define bfin_read_SPORT3_TCLKDIV()		bfin_read16(SPORT3_TCLKDIV)
+#define bfin_write_SPORT3_TCLKDIV(val)		bfin_write16(SPORT3_TCLKDIV, val)
+#define bfin_read_SPORT3_TFSDIV()		bfin_read16(SPORT3_TFSDIV)
+#define bfin_write_SPORT3_TFSDIV(val)		bfin_write16(SPORT3_TFSDIV, val)
+#define bfin_read_SPORT3_TX()			bfin_read32(SPORT3_TX)
+#define bfin_write_SPORT3_TX(val)		bfin_write32(SPORT3_TX, val)
+#define bfin_read_SPORT3_RX()			bfin_read32(SPORT3_RX)
+#define bfin_write_SPORT3_RX(val)		bfin_write32(SPORT3_RX, val)
+#define bfin_read_SPORT3_RCR1()			bfin_read16(SPORT3_RCR1)
+#define bfin_write_SPORT3_RCR1(val)		bfin_write16(SPORT3_RCR1, val)
+#define bfin_read_SPORT3_RCR2()			bfin_read16(SPORT3_RCR2)
+#define bfin_write_SPORT3_RCR2(val)		bfin_write16(SPORT3_RCR2, val)
+#define bfin_read_SPORT3_RCLKDIV()		bfin_read16(SPORT3_RCLKDIV)
+#define bfin_write_SPORT3_RCLKDIV(val)		bfin_write16(SPORT3_RCLKDIV, val)
+#define bfin_read_SPORT3_RFSDIV()		bfin_read16(SPORT3_RFSDIV)
+#define bfin_write_SPORT3_RFSDIV(val)		bfin_write16(SPORT3_RFSDIV, val)
+#define bfin_read_SPORT3_STAT()			bfin_read16(SPORT3_STAT)
+#define bfin_write_SPORT3_STAT(val)		bfin_write16(SPORT3_STAT, val)
+#define bfin_read_SPORT3_CHNL()			bfin_read16(SPORT3_CHNL)
+#define bfin_write_SPORT3_CHNL(val)		bfin_write16(SPORT3_CHNL, val)
+#define bfin_read_SPORT3_MCMC1()		bfin_read16(SPORT3_MCMC1)
+#define bfin_write_SPORT3_MCMC1(val)		bfin_write16(SPORT3_MCMC1, val)
+#define bfin_read_SPORT3_MCMC2()		bfin_read16(SPORT3_MCMC2)
+#define bfin_write_SPORT3_MCMC2(val)		bfin_write16(SPORT3_MCMC2, val)
+#define bfin_read_SPORT3_MTCS0()		bfin_read32(SPORT3_MTCS0)
+#define bfin_write_SPORT3_MTCS0(val)		bfin_write32(SPORT3_MTCS0, val)
+#define bfin_read_SPORT3_MTCS1()		bfin_read32(SPORT3_MTCS1)
+#define bfin_write_SPORT3_MTCS1(val)		bfin_write32(SPORT3_MTCS1, val)
+#define bfin_read_SPORT3_MTCS2()		bfin_read32(SPORT3_MTCS2)
+#define bfin_write_SPORT3_MTCS2(val)		bfin_write32(SPORT3_MTCS2, val)
+#define bfin_read_SPORT3_MTCS3()		bfin_read32(SPORT3_MTCS3)
+#define bfin_write_SPORT3_MTCS3(val)		bfin_write32(SPORT3_MTCS3, val)
+#define bfin_read_SPORT3_MRCS0()		bfin_read32(SPORT3_MRCS0)
+#define bfin_write_SPORT3_MRCS0(val)		bfin_write32(SPORT3_MRCS0, val)
+#define bfin_read_SPORT3_MRCS1()		bfin_read32(SPORT3_MRCS1)
+#define bfin_write_SPORT3_MRCS1(val)		bfin_write32(SPORT3_MRCS1, val)
+#define bfin_read_SPORT3_MRCS2()		bfin_read32(SPORT3_MRCS2)
+#define bfin_write_SPORT3_MRCS2(val)		bfin_write32(SPORT3_MRCS2, val)
+#define bfin_read_SPORT3_MRCS3()		bfin_read32(SPORT3_MRCS3)
+#define bfin_write_SPORT3_MRCS3(val)		bfin_write32(SPORT3_MRCS3, val)
+
+/* EPPI2 Registers */
+
+#define bfin_read_EPPI2_STATUS()		bfin_read16(EPPI2_STATUS)
+#define bfin_write_EPPI2_STATUS(val)		bfin_write16(EPPI2_STATUS, val)
+#define bfin_read_EPPI2_HCOUNT()		bfin_read16(EPPI2_HCOUNT)
+#define bfin_write_EPPI2_HCOUNT(val)		bfin_write16(EPPI2_HCOUNT, val)
+#define bfin_read_EPPI2_HDELAY()		bfin_read16(EPPI2_HDELAY)
+#define bfin_write_EPPI2_HDELAY(val)		bfin_write16(EPPI2_HDELAY, val)
+#define bfin_read_EPPI2_VCOUNT()		bfin_read16(EPPI2_VCOUNT)
+#define bfin_write_EPPI2_VCOUNT(val)		bfin_write16(EPPI2_VCOUNT, val)
+#define bfin_read_EPPI2_VDELAY()		bfin_read16(EPPI2_VDELAY)
+#define bfin_write_EPPI2_VDELAY(val)		bfin_write16(EPPI2_VDELAY, val)
+#define bfin_read_EPPI2_FRAME()			bfin_read16(EPPI2_FRAME)
+#define bfin_write_EPPI2_FRAME(val)		bfin_write16(EPPI2_FRAME, val)
+#define bfin_read_EPPI2_LINE()			bfin_read16(EPPI2_LINE)
+#define bfin_write_EPPI2_LINE(val)		bfin_write16(EPPI2_LINE, val)
+#define bfin_read_EPPI2_CLKDIV()		bfin_read16(EPPI2_CLKDIV)
+#define bfin_write_EPPI2_CLKDIV(val)		bfin_write16(EPPI2_CLKDIV, val)
+#define bfin_read_EPPI2_CONTROL()		bfin_read32(EPPI2_CONTROL)
+#define bfin_write_EPPI2_CONTROL(val)		bfin_write32(EPPI2_CONTROL, val)
+#define bfin_read_EPPI2_FS1W_HBL()		bfin_read32(EPPI2_FS1W_HBL)
+#define bfin_write_EPPI2_FS1W_HBL(val)		bfin_write32(EPPI2_FS1W_HBL, val)
+#define bfin_read_EPPI2_FS1P_AVPL()		bfin_read32(EPPI2_FS1P_AVPL)
+#define bfin_write_EPPI2_FS1P_AVPL(val)		bfin_write32(EPPI2_FS1P_AVPL, val)
+#define bfin_read_EPPI2_FS2W_LVB()		bfin_read32(EPPI2_FS2W_LVB)
+#define bfin_write_EPPI2_FS2W_LVB(val)		bfin_write32(EPPI2_FS2W_LVB, val)
+#define bfin_read_EPPI2_FS2P_LAVF()		bfin_read32(EPPI2_FS2P_LAVF)
+#define bfin_write_EPPI2_FS2P_LAVF(val)		bfin_write32(EPPI2_FS2P_LAVF, val)
+#define bfin_read_EPPI2_CLIP()			bfin_read32(EPPI2_CLIP)
+#define bfin_write_EPPI2_CLIP(val)		bfin_write32(EPPI2_CLIP, val)
+
+/* CAN Controller 0 Config 1 Registers */
+
+#define bfin_read_CAN0_MC1()		bfin_read16(CAN0_MC1)
+#define bfin_write_CAN0_MC1(val)	bfin_write16(CAN0_MC1, val)
+#define bfin_read_CAN0_MD1()		bfin_read16(CAN0_MD1)
+#define bfin_write_CAN0_MD1(val)	bfin_write16(CAN0_MD1, val)
+#define bfin_read_CAN0_TRS1()		bfin_read16(CAN0_TRS1)
+#define bfin_write_CAN0_TRS1(val)	bfin_write16(CAN0_TRS1, val)
+#define bfin_read_CAN0_TRR1()		bfin_read16(CAN0_TRR1)
+#define bfin_write_CAN0_TRR1(val)	bfin_write16(CAN0_TRR1, val)
+#define bfin_read_CAN0_TA1()		bfin_read16(CAN0_TA1)
+#define bfin_write_CAN0_TA1(val)	bfin_write16(CAN0_TA1, val)
+#define bfin_read_CAN0_AA1()		bfin_read16(CAN0_AA1)
+#define bfin_write_CAN0_AA1(val)	bfin_write16(CAN0_AA1, val)
+#define bfin_read_CAN0_RMP1()		bfin_read16(CAN0_RMP1)
+#define bfin_write_CAN0_RMP1(val)	bfin_write16(CAN0_RMP1, val)
+#define bfin_read_CAN0_RML1()		bfin_read16(CAN0_RML1)
+#define bfin_write_CAN0_RML1(val)	bfin_write16(CAN0_RML1, val)
+#define bfin_read_CAN0_MBTIF1()		bfin_read16(CAN0_MBTIF1)
+#define bfin_write_CAN0_MBTIF1(val)	bfin_write16(CAN0_MBTIF1, val)
+#define bfin_read_CAN0_MBRIF1()		bfin_read16(CAN0_MBRIF1)
+#define bfin_write_CAN0_MBRIF1(val)	bfin_write16(CAN0_MBRIF1, val)
+#define bfin_read_CAN0_MBIM1()		bfin_read16(CAN0_MBIM1)
+#define bfin_write_CAN0_MBIM1(val)	bfin_write16(CAN0_MBIM1, val)
+#define bfin_read_CAN0_RFH1()		bfin_read16(CAN0_RFH1)
+#define bfin_write_CAN0_RFH1(val)	bfin_write16(CAN0_RFH1, val)
+#define bfin_read_CAN0_OPSS1()		bfin_read16(CAN0_OPSS1)
+#define bfin_write_CAN0_OPSS1(val)	bfin_write16(CAN0_OPSS1, val)
+
+/* CAN Controller 0 Config 2 Registers */
+
+#define bfin_read_CAN0_MC2()		bfin_read16(CAN0_MC2)
+#define bfin_write_CAN0_MC2(val)	bfin_write16(CAN0_MC2, val)
+#define bfin_read_CAN0_MD2()		bfin_read16(CAN0_MD2)
+#define bfin_write_CAN0_MD2(val)	bfin_write16(CAN0_MD2, val)
+#define bfin_read_CAN0_TRS2()		bfin_read16(CAN0_TRS2)
+#define bfin_write_CAN0_TRS2(val)	bfin_write16(CAN0_TRS2, val)
+#define bfin_read_CAN0_TRR2()		bfin_read16(CAN0_TRR2)
+#define bfin_write_CAN0_TRR2(val)	bfin_write16(CAN0_TRR2, val)
+#define bfin_read_CAN0_TA2()		bfin_read16(CAN0_TA2)
+#define bfin_write_CAN0_TA2(val)	bfin_write16(CAN0_TA2, val)
+#define bfin_read_CAN0_AA2()		bfin_read16(CAN0_AA2)
+#define bfin_write_CAN0_AA2(val)	bfin_write16(CAN0_AA2, val)
+#define bfin_read_CAN0_RMP2()		bfin_read16(CAN0_RMP2)
+#define bfin_write_CAN0_RMP2(val)	bfin_write16(CAN0_RMP2, val)
+#define bfin_read_CAN0_RML2()		bfin_read16(CAN0_RML2)
+#define bfin_write_CAN0_RML2(val)	bfin_write16(CAN0_RML2, val)
+#define bfin_read_CAN0_MBTIF2()		bfin_read16(CAN0_MBTIF2)
+#define bfin_write_CAN0_MBTIF2(val)	bfin_write16(CAN0_MBTIF2, val)
+#define bfin_read_CAN0_MBRIF2()		bfin_read16(CAN0_MBRIF2)
+#define bfin_write_CAN0_MBRIF2(val)	bfin_write16(CAN0_MBRIF2, val)
+#define bfin_read_CAN0_MBIM2()		bfin_read16(CAN0_MBIM2)
+#define bfin_write_CAN0_MBIM2(val)	bfin_write16(CAN0_MBIM2, val)
+#define bfin_read_CAN0_RFH2()		bfin_read16(CAN0_RFH2)
+#define bfin_write_CAN0_RFH2(val)	bfin_write16(CAN0_RFH2, val)
+#define bfin_read_CAN0_OPSS2()		bfin_read16(CAN0_OPSS2)
+#define bfin_write_CAN0_OPSS2(val)	bfin_write16(CAN0_OPSS2, val)
+
+/* CAN Controller 0 Clock/Interrubfin_read_()t/Counter Registers */
+
+#define bfin_read_CAN0_CLOCK()		bfin_read16(CAN0_CLOCK)
+#define bfin_write_CAN0_CLOCK(val)	bfin_write16(CAN0_CLOCK, val)
+#define bfin_read_CAN0_TIMING()		bfin_read16(CAN0_TIMING)
+#define bfin_write_CAN0_TIMING(val)	bfin_write16(CAN0_TIMING, val)
+#define bfin_read_CAN0_DEBUG()		bfin_read16(CAN0_DEBUG)
+#define bfin_write_CAN0_DEBUG(val)	bfin_write16(CAN0_DEBUG, val)
+#define bfin_read_CAN0_STATUS()		bfin_read16(CAN0_STATUS)
+#define bfin_write_CAN0_STATUS(val)	bfin_write16(CAN0_STATUS, val)
+#define bfin_read_CAN0_CEC()		bfin_read16(CAN0_CEC)
+#define bfin_write_CAN0_CEC(val)	bfin_write16(CAN0_CEC, val)
+#define bfin_read_CAN0_GIS()		bfin_read16(CAN0_GIS)
+#define bfin_write_CAN0_GIS(val)	bfin_write16(CAN0_GIS, val)
+#define bfin_read_CAN0_GIM()		bfin_read16(CAN0_GIM)
+#define bfin_write_CAN0_GIM(val)	bfin_write16(CAN0_GIM, val)
+#define bfin_read_CAN0_GIF()		bfin_read16(CAN0_GIF)
+#define bfin_write_CAN0_GIF(val)	bfin_write16(CAN0_GIF, val)
+#define bfin_read_CAN0_CONTROL()	bfin_read16(CAN0_CONTROL)
+#define bfin_write_CAN0_CONTROL(val)	bfin_write16(CAN0_CONTROL, val)
+#define bfin_read_CAN0_INTR()		bfin_read16(CAN0_INTR)
+#define bfin_write_CAN0_INTR(val)	bfin_write16(CAN0_INTR, val)
+#define bfin_read_CAN0_MBTD()		bfin_read16(CAN0_MBTD)
+#define bfin_write_CAN0_MBTD(val)	bfin_write16(CAN0_MBTD, val)
+#define bfin_read_CAN0_EWR()		bfin_read16(CAN0_EWR)
+#define bfin_write_CAN0_EWR(val)	bfin_write16(CAN0_EWR, val)
+#define bfin_read_CAN0_ESR()		bfin_read16(CAN0_ESR)
+#define bfin_write_CAN0_ESR(val)	bfin_write16(CAN0_ESR, val)
+#define bfin_read_CAN0_UCCNT()		bfin_read16(CAN0_UCCNT)
+#define bfin_write_CAN0_UCCNT(val)	bfin_write16(CAN0_UCCNT, val)
+#define bfin_read_CAN0_UCRC()		bfin_read16(CAN0_UCRC)
+#define bfin_write_CAN0_UCRC(val)	bfin_write16(CAN0_UCRC, val)
+#define bfin_read_CAN0_UCCNF()		bfin_read16(CAN0_UCCNF)
+#define bfin_write_CAN0_UCCNF(val)	bfin_write16(CAN0_UCCNF, val)
+
+/* CAN Controller 0 Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN0_AM00L()		bfin_read16(CAN0_AM00L)
+#define bfin_write_CAN0_AM00L(val)	bfin_write16(CAN0_AM00L, val)
+#define bfin_read_CAN0_AM00H()		bfin_read16(CAN0_AM00H)
+#define bfin_write_CAN0_AM00H(val)	bfin_write16(CAN0_AM00H, val)
+#define bfin_read_CAN0_AM01L()		bfin_read16(CAN0_AM01L)
+#define bfin_write_CAN0_AM01L(val)	bfin_write16(CAN0_AM01L, val)
+#define bfin_read_CAN0_AM01H()		bfin_read16(CAN0_AM01H)
+#define bfin_write_CAN0_AM01H(val)	bfin_write16(CAN0_AM01H, val)
+#define bfin_read_CAN0_AM02L()		bfin_read16(CAN0_AM02L)
+#define bfin_write_CAN0_AM02L(val)	bfin_write16(CAN0_AM02L, val)
+#define bfin_read_CAN0_AM02H()		bfin_read16(CAN0_AM02H)
+#define bfin_write_CAN0_AM02H(val)	bfin_write16(CAN0_AM02H, val)
+#define bfin_read_CAN0_AM03L()		bfin_read16(CAN0_AM03L)
+#define bfin_write_CAN0_AM03L(val)	bfin_write16(CAN0_AM03L, val)
+#define bfin_read_CAN0_AM03H()		bfin_read16(CAN0_AM03H)
+#define bfin_write_CAN0_AM03H(val)	bfin_write16(CAN0_AM03H, val)
+#define bfin_read_CAN0_AM04L()		bfin_read16(CAN0_AM04L)
+#define bfin_write_CAN0_AM04L(val)	bfin_write16(CAN0_AM04L, val)
+#define bfin_read_CAN0_AM04H()		bfin_read16(CAN0_AM04H)
+#define bfin_write_CAN0_AM04H(val)	bfin_write16(CAN0_AM04H, val)
+#define bfin_read_CAN0_AM05L()		bfin_read16(CAN0_AM05L)
+#define bfin_write_CAN0_AM05L(val)	bfin_write16(CAN0_AM05L, val)
+#define bfin_read_CAN0_AM05H()		bfin_read16(CAN0_AM05H)
+#define bfin_write_CAN0_AM05H(val)	bfin_write16(CAN0_AM05H, val)
+#define bfin_read_CAN0_AM06L()		bfin_read16(CAN0_AM06L)
+#define bfin_write_CAN0_AM06L(val)	bfin_write16(CAN0_AM06L, val)
+#define bfin_read_CAN0_AM06H()		bfin_read16(CAN0_AM06H)
+#define bfin_write_CAN0_AM06H(val)	bfin_write16(CAN0_AM06H, val)
+#define bfin_read_CAN0_AM07L()		bfin_read16(CAN0_AM07L)
+#define bfin_write_CAN0_AM07L(val)	bfin_write16(CAN0_AM07L, val)
+#define bfin_read_CAN0_AM07H()		bfin_read16(CAN0_AM07H)
+#define bfin_write_CAN0_AM07H(val)	bfin_write16(CAN0_AM07H, val)
+#define bfin_read_CAN0_AM08L()		bfin_read16(CAN0_AM08L)
+#define bfin_write_CAN0_AM08L(val)	bfin_write16(CAN0_AM08L, val)
+#define bfin_read_CAN0_AM08H()		bfin_read16(CAN0_AM08H)
+#define bfin_write_CAN0_AM08H(val)	bfin_write16(CAN0_AM08H, val)
+#define bfin_read_CAN0_AM09L()		bfin_read16(CAN0_AM09L)
+#define bfin_write_CAN0_AM09L(val)	bfin_write16(CAN0_AM09L, val)
+#define bfin_read_CAN0_AM09H()		bfin_read16(CAN0_AM09H)
+#define bfin_write_CAN0_AM09H(val)	bfin_write16(CAN0_AM09H, val)
+#define bfin_read_CAN0_AM10L()		bfin_read16(CAN0_AM10L)
+#define bfin_write_CAN0_AM10L(val)	bfin_write16(CAN0_AM10L, val)
+#define bfin_read_CAN0_AM10H()		bfin_read16(CAN0_AM10H)
+#define bfin_write_CAN0_AM10H(val)	bfin_write16(CAN0_AM10H, val)
+#define bfin_read_CAN0_AM11L()		bfin_read16(CAN0_AM11L)
+#define bfin_write_CAN0_AM11L(val)	bfin_write16(CAN0_AM11L, val)
+#define bfin_read_CAN0_AM11H()		bfin_read16(CAN0_AM11H)
+#define bfin_write_CAN0_AM11H(val)	bfin_write16(CAN0_AM11H, val)
+#define bfin_read_CAN0_AM12L()		bfin_read16(CAN0_AM12L)
+#define bfin_write_CAN0_AM12L(val)	bfin_write16(CAN0_AM12L, val)
+#define bfin_read_CAN0_AM12H()		bfin_read16(CAN0_AM12H)
+#define bfin_write_CAN0_AM12H(val)	bfin_write16(CAN0_AM12H, val)
+#define bfin_read_CAN0_AM13L()		bfin_read16(CAN0_AM13L)
+#define bfin_write_CAN0_AM13L(val)	bfin_write16(CAN0_AM13L, val)
+#define bfin_read_CAN0_AM13H()		bfin_read16(CAN0_AM13H)
+#define bfin_write_CAN0_AM13H(val)	bfin_write16(CAN0_AM13H, val)
+#define bfin_read_CAN0_AM14L()		bfin_read16(CAN0_AM14L)
+#define bfin_write_CAN0_AM14L(val)	bfin_write16(CAN0_AM14L, val)
+#define bfin_read_CAN0_AM14H()		bfin_read16(CAN0_AM14H)
+#define bfin_write_CAN0_AM14H(val)	bfin_write16(CAN0_AM14H, val)
+#define bfin_read_CAN0_AM15L()		bfin_read16(CAN0_AM15L)
+#define bfin_write_CAN0_AM15L(val)	bfin_write16(CAN0_AM15L, val)
+#define bfin_read_CAN0_AM15H()		bfin_read16(CAN0_AM15H)
+#define bfin_write_CAN0_AM15H(val)	bfin_write16(CAN0_AM15H, val)
+
+/* CAN Controller 0 Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN0_AM16L()		bfin_read16(CAN0_AM16L)
+#define bfin_write_CAN0_AM16L(val)	bfin_write16(CAN0_AM16L, val)
+#define bfin_read_CAN0_AM16H()		bfin_read16(CAN0_AM16H)
+#define bfin_write_CAN0_AM16H(val)	bfin_write16(CAN0_AM16H, val)
+#define bfin_read_CAN0_AM17L()		bfin_read16(CAN0_AM17L)
+#define bfin_write_CAN0_AM17L(val)	bfin_write16(CAN0_AM17L, val)
+#define bfin_read_CAN0_AM17H()		bfin_read16(CAN0_AM17H)
+#define bfin_write_CAN0_AM17H(val)	bfin_write16(CAN0_AM17H, val)
+#define bfin_read_CAN0_AM18L()		bfin_read16(CAN0_AM18L)
+#define bfin_write_CAN0_AM18L(val)	bfin_write16(CAN0_AM18L, val)
+#define bfin_read_CAN0_AM18H()		bfin_read16(CAN0_AM18H)
+#define bfin_write_CAN0_AM18H(val)	bfin_write16(CAN0_AM18H, val)
+#define bfin_read_CAN0_AM19L()		bfin_read16(CAN0_AM19L)
+#define bfin_write_CAN0_AM19L(val)	bfin_write16(CAN0_AM19L, val)
+#define bfin_read_CAN0_AM19H()		bfin_read16(CAN0_AM19H)
+#define bfin_write_CAN0_AM19H(val)	bfin_write16(CAN0_AM19H, val)
+#define bfin_read_CAN0_AM20L()		bfin_read16(CAN0_AM20L)
+#define bfin_write_CAN0_AM20L(val)	bfin_write16(CAN0_AM20L, val)
+#define bfin_read_CAN0_AM20H()		bfin_read16(CAN0_AM20H)
+#define bfin_write_CAN0_AM20H(val)	bfin_write16(CAN0_AM20H, val)
+#define bfin_read_CAN0_AM21L()		bfin_read16(CAN0_AM21L)
+#define bfin_write_CAN0_AM21L(val)	bfin_write16(CAN0_AM21L, val)
+#define bfin_read_CAN0_AM21H()		bfin_read16(CAN0_AM21H)
+#define bfin_write_CAN0_AM21H(val)	bfin_write16(CAN0_AM21H, val)
+#define bfin_read_CAN0_AM22L()		bfin_read16(CAN0_AM22L)
+#define bfin_write_CAN0_AM22L(val)	bfin_write16(CAN0_AM22L, val)
+#define bfin_read_CAN0_AM22H()		bfin_read16(CAN0_AM22H)
+#define bfin_write_CAN0_AM22H(val)	bfin_write16(CAN0_AM22H, val)
+#define bfin_read_CAN0_AM23L()		bfin_read16(CAN0_AM23L)
+#define bfin_write_CAN0_AM23L(val)	bfin_write16(CAN0_AM23L, val)
+#define bfin_read_CAN0_AM23H()		bfin_read16(CAN0_AM23H)
+#define bfin_write_CAN0_AM23H(val)	bfin_write16(CAN0_AM23H, val)
+#define bfin_read_CAN0_AM24L()		bfin_read16(CAN0_AM24L)
+#define bfin_write_CAN0_AM24L(val)	bfin_write16(CAN0_AM24L, val)
+#define bfin_read_CAN0_AM24H()		bfin_read16(CAN0_AM24H)
+#define bfin_write_CAN0_AM24H(val)	bfin_write16(CAN0_AM24H, val)
+#define bfin_read_CAN0_AM25L()		bfin_read16(CAN0_AM25L)
+#define bfin_write_CAN0_AM25L(val)	bfin_write16(CAN0_AM25L, val)
+#define bfin_read_CAN0_AM25H()		bfin_read16(CAN0_AM25H)
+#define bfin_write_CAN0_AM25H(val)	bfin_write16(CAN0_AM25H, val)
+#define bfin_read_CAN0_AM26L()		bfin_read16(CAN0_AM26L)
+#define bfin_write_CAN0_AM26L(val)	bfin_write16(CAN0_AM26L, val)
+#define bfin_read_CAN0_AM26H()		bfin_read16(CAN0_AM26H)
+#define bfin_write_CAN0_AM26H(val)	bfin_write16(CAN0_AM26H, val)
+#define bfin_read_CAN0_AM27L()		bfin_read16(CAN0_AM27L)
+#define bfin_write_CAN0_AM27L(val)	bfin_write16(CAN0_AM27L, val)
+#define bfin_read_CAN0_AM27H()		bfin_read16(CAN0_AM27H)
+#define bfin_write_CAN0_AM27H(val)	bfin_write16(CAN0_AM27H, val)
+#define bfin_read_CAN0_AM28L()		bfin_read16(CAN0_AM28L)
+#define bfin_write_CAN0_AM28L(val)	bfin_write16(CAN0_AM28L, val)
+#define bfin_read_CAN0_AM28H()		bfin_read16(CAN0_AM28H)
+#define bfin_write_CAN0_AM28H(val)	bfin_write16(CAN0_AM28H, val)
+#define bfin_read_CAN0_AM29L()		bfin_read16(CAN0_AM29L)
+#define bfin_write_CAN0_AM29L(val)	bfin_write16(CAN0_AM29L, val)
+#define bfin_read_CAN0_AM29H()		bfin_read16(CAN0_AM29H)
+#define bfin_write_CAN0_AM29H(val)	bfin_write16(CAN0_AM29H, val)
+#define bfin_read_CAN0_AM30L()		bfin_read16(CAN0_AM30L)
+#define bfin_write_CAN0_AM30L(val)	bfin_write16(CAN0_AM30L, val)
+#define bfin_read_CAN0_AM30H()		bfin_read16(CAN0_AM30H)
+#define bfin_write_CAN0_AM30H(val)	bfin_write16(CAN0_AM30H, val)
+#define bfin_read_CAN0_AM31L()		bfin_read16(CAN0_AM31L)
+#define bfin_write_CAN0_AM31L(val)	bfin_write16(CAN0_AM31L, val)
+#define bfin_read_CAN0_AM31H()		bfin_read16(CAN0_AM31H)
+#define bfin_write_CAN0_AM31H(val)	bfin_write16(CAN0_AM31H, val)
+
+/* CAN Controller 0 Mailbox Data Registers */
+
+#define bfin_read_CAN0_MB00_DATA0()		bfin_read16(CAN0_MB00_DATA0)
+#define bfin_write_CAN0_MB00_DATA0(val)		bfin_write16(CAN0_MB00_DATA0, val)
+#define bfin_read_CAN0_MB00_DATA1()		bfin_read16(CAN0_MB00_DATA1)
+#define bfin_write_CAN0_MB00_DATA1(val)		bfin_write16(CAN0_MB00_DATA1, val)
+#define bfin_read_CAN0_MB00_DATA2()		bfin_read16(CAN0_MB00_DATA2)
+#define bfin_write_CAN0_MB00_DATA2(val)		bfin_write16(CAN0_MB00_DATA2, val)
+#define bfin_read_CAN0_MB00_DATA3()		bfin_read16(CAN0_MB00_DATA3)
+#define bfin_write_CAN0_MB00_DATA3(val)		bfin_write16(CAN0_MB00_DATA3, val)
+#define bfin_read_CAN0_MB00_LENGTH()		bfin_read16(CAN0_MB00_LENGTH)
+#define bfin_write_CAN0_MB00_LENGTH(val)	bfin_write16(CAN0_MB00_LENGTH, val)
+#define bfin_read_CAN0_MB00_TIMESTAMP()		bfin_read16(CAN0_MB00_TIMESTAMP)
+#define bfin_write_CAN0_MB00_TIMESTAMP(val)	bfin_write16(CAN0_MB00_TIMESTAMP, val)
+#define bfin_read_CAN0_MB00_ID0()		bfin_read16(CAN0_MB00_ID0)
+#define bfin_write_CAN0_MB00_ID0(val)		bfin_write16(CAN0_MB00_ID0, val)
+#define bfin_read_CAN0_MB00_ID1()		bfin_read16(CAN0_MB00_ID1)
+#define bfin_write_CAN0_MB00_ID1(val)		bfin_write16(CAN0_MB00_ID1, val)
+#define bfin_read_CAN0_MB01_DATA0()		bfin_read16(CAN0_MB01_DATA0)
+#define bfin_write_CAN0_MB01_DATA0(val)		bfin_write16(CAN0_MB01_DATA0, val)
+#define bfin_read_CAN0_MB01_DATA1()		bfin_read16(CAN0_MB01_DATA1)
+#define bfin_write_CAN0_MB01_DATA1(val)		bfin_write16(CAN0_MB01_DATA1, val)
+#define bfin_read_CAN0_MB01_DATA2()		bfin_read16(CAN0_MB01_DATA2)
+#define bfin_write_CAN0_MB01_DATA2(val)		bfin_write16(CAN0_MB01_DATA2, val)
+#define bfin_read_CAN0_MB01_DATA3()		bfin_read16(CAN0_MB01_DATA3)
+#define bfin_write_CAN0_MB01_DATA3(val)		bfin_write16(CAN0_MB01_DATA3, val)
+#define bfin_read_CAN0_MB01_LENGTH()		bfin_read16(CAN0_MB01_LENGTH)
+#define bfin_write_CAN0_MB01_LENGTH(val)	bfin_write16(CAN0_MB01_LENGTH, val)
+#define bfin_read_CAN0_MB01_TIMESTAMP()		bfin_read16(CAN0_MB01_TIMESTAMP)
+#define bfin_write_CAN0_MB01_TIMESTAMP(val)	bfin_write16(CAN0_MB01_TIMESTAMP, val)
+#define bfin_read_CAN0_MB01_ID0()		bfin_read16(CAN0_MB01_ID0)
+#define bfin_write_CAN0_MB01_ID0(val)		bfin_write16(CAN0_MB01_ID0, val)
+#define bfin_read_CAN0_MB01_ID1()		bfin_read16(CAN0_MB01_ID1)
+#define bfin_write_CAN0_MB01_ID1(val)		bfin_write16(CAN0_MB01_ID1, val)
+#define bfin_read_CAN0_MB02_DATA0()		bfin_read16(CAN0_MB02_DATA0)
+#define bfin_write_CAN0_MB02_DATA0(val)		bfin_write16(CAN0_MB02_DATA0, val)
+#define bfin_read_CAN0_MB02_DATA1()		bfin_read16(CAN0_MB02_DATA1)
+#define bfin_write_CAN0_MB02_DATA1(val)		bfin_write16(CAN0_MB02_DATA1, val)
+#define bfin_read_CAN0_MB02_DATA2()		bfin_read16(CAN0_MB02_DATA2)
+#define bfin_write_CAN0_MB02_DATA2(val)		bfin_write16(CAN0_MB02_DATA2, val)
+#define bfin_read_CAN0_MB02_DATA3()		bfin_read16(CAN0_MB02_DATA3)
+#define bfin_write_CAN0_MB02_DATA3(val)		bfin_write16(CAN0_MB02_DATA3, val)
+#define bfin_read_CAN0_MB02_LENGTH()		bfin_read16(CAN0_MB02_LENGTH)
+#define bfin_write_CAN0_MB02_LENGTH(val)	bfin_write16(CAN0_MB02_LENGTH, val)
+#define bfin_read_CAN0_MB02_TIMESTAMP()		bfin_read16(CAN0_MB02_TIMESTAMP)
+#define bfin_write_CAN0_MB02_TIMESTAMP(val)	bfin_write16(CAN0_MB02_TIMESTAMP, val)
+#define bfin_read_CAN0_MB02_ID0()		bfin_read16(CAN0_MB02_ID0)
+#define bfin_write_CAN0_MB02_ID0(val)		bfin_write16(CAN0_MB02_ID0, val)
+#define bfin_read_CAN0_MB02_ID1()		bfin_read16(CAN0_MB02_ID1)
+#define bfin_write_CAN0_MB02_ID1(val)		bfin_write16(CAN0_MB02_ID1, val)
+#define bfin_read_CAN0_MB03_DATA0()		bfin_read16(CAN0_MB03_DATA0)
+#define bfin_write_CAN0_MB03_DATA0(val)		bfin_write16(CAN0_MB03_DATA0, val)
+#define bfin_read_CAN0_MB03_DATA1()		bfin_read16(CAN0_MB03_DATA1)
+#define bfin_write_CAN0_MB03_DATA1(val)		bfin_write16(CAN0_MB03_DATA1, val)
+#define bfin_read_CAN0_MB03_DATA2()		bfin_read16(CAN0_MB03_DATA2)
+#define bfin_write_CAN0_MB03_DATA2(val)		bfin_write16(CAN0_MB03_DATA2, val)
+#define bfin_read_CAN0_MB03_DATA3()		bfin_read16(CAN0_MB03_DATA3)
+#define bfin_write_CAN0_MB03_DATA3(val)		bfin_write16(CAN0_MB03_DATA3, val)
+#define bfin_read_CAN0_MB03_LENGTH()		bfin_read16(CAN0_MB03_LENGTH)
+#define bfin_write_CAN0_MB03_LENGTH(val)	bfin_write16(CAN0_MB03_LENGTH, val)
+#define bfin_read_CAN0_MB03_TIMESTAMP()		bfin_read16(CAN0_MB03_TIMESTAMP)
+#define bfin_write_CAN0_MB03_TIMESTAMP(val)	bfin_write16(CAN0_MB03_TIMESTAMP, val)
+#define bfin_read_CAN0_MB03_ID0()		bfin_read16(CAN0_MB03_ID0)
+#define bfin_write_CAN0_MB03_ID0(val)		bfin_write16(CAN0_MB03_ID0, val)
+#define bfin_read_CAN0_MB03_ID1()		bfin_read16(CAN0_MB03_ID1)
+#define bfin_write_CAN0_MB03_ID1(val)		bfin_write16(CAN0_MB03_ID1, val)
+#define bfin_read_CAN0_MB04_DATA0()		bfin_read16(CAN0_MB04_DATA0)
+#define bfin_write_CAN0_MB04_DATA0(val)		bfin_write16(CAN0_MB04_DATA0, val)
+#define bfin_read_CAN0_MB04_DATA1()		bfin_read16(CAN0_MB04_DATA1)
+#define bfin_write_CAN0_MB04_DATA1(val)		bfin_write16(CAN0_MB04_DATA1, val)
+#define bfin_read_CAN0_MB04_DATA2()		bfin_read16(CAN0_MB04_DATA2)
+#define bfin_write_CAN0_MB04_DATA2(val)		bfin_write16(CAN0_MB04_DATA2, val)
+#define bfin_read_CAN0_MB04_DATA3()		bfin_read16(CAN0_MB04_DATA3)
+#define bfin_write_CAN0_MB04_DATA3(val)		bfin_write16(CAN0_MB04_DATA3, val)
+#define bfin_read_CAN0_MB04_LENGTH()		bfin_read16(CAN0_MB04_LENGTH)
+#define bfin_write_CAN0_MB04_LENGTH(val)	bfin_write16(CAN0_MB04_LENGTH, val)
+#define bfin_read_CAN0_MB04_TIMESTAMP()		bfin_read16(CAN0_MB04_TIMESTAMP)
+#define bfin_write_CAN0_MB04_TIMESTAMP(val)	bfin_write16(CAN0_MB04_TIMESTAMP, val)
+#define bfin_read_CAN0_MB04_ID0()		bfin_read16(CAN0_MB04_ID0)
+#define bfin_write_CAN0_MB04_ID0(val)		bfin_write16(CAN0_MB04_ID0, val)
+#define bfin_read_CAN0_MB04_ID1()		bfin_read16(CAN0_MB04_ID1)
+#define bfin_write_CAN0_MB04_ID1(val)		bfin_write16(CAN0_MB04_ID1, val)
+#define bfin_read_CAN0_MB05_DATA0()		bfin_read16(CAN0_MB05_DATA0)
+#define bfin_write_CAN0_MB05_DATA0(val)		bfin_write16(CAN0_MB05_DATA0, val)
+#define bfin_read_CAN0_MB05_DATA1()		bfin_read16(CAN0_MB05_DATA1)
+#define bfin_write_CAN0_MB05_DATA1(val)		bfin_write16(CAN0_MB05_DATA1, val)
+#define bfin_read_CAN0_MB05_DATA2()		bfin_read16(CAN0_MB05_DATA2)
+#define bfin_write_CAN0_MB05_DATA2(val)		bfin_write16(CAN0_MB05_DATA2, val)
+#define bfin_read_CAN0_MB05_DATA3()		bfin_read16(CAN0_MB05_DATA3)
+#define bfin_write_CAN0_MB05_DATA3(val)		bfin_write16(CAN0_MB05_DATA3, val)
+#define bfin_read_CAN0_MB05_LENGTH()		bfin_read16(CAN0_MB05_LENGTH)
+#define bfin_write_CAN0_MB05_LENGTH(val)	bfin_write16(CAN0_MB05_LENGTH, val)
+#define bfin_read_CAN0_MB05_TIMESTAMP()		bfin_read16(CAN0_MB05_TIMESTAMP)
+#define bfin_write_CAN0_MB05_TIMESTAMP(val)	bfin_write16(CAN0_MB05_TIMESTAMP, val)
+#define bfin_read_CAN0_MB05_ID0()		bfin_read16(CAN0_MB05_ID0)
+#define bfin_write_CAN0_MB05_ID0(val)		bfin_write16(CAN0_MB05_ID0, val)
+#define bfin_read_CAN0_MB05_ID1()		bfin_read16(CAN0_MB05_ID1)
+#define bfin_write_CAN0_MB05_ID1(val)		bfin_write16(CAN0_MB05_ID1, val)
+#define bfin_read_CAN0_MB06_DATA0()		bfin_read16(CAN0_MB06_DATA0)
+#define bfin_write_CAN0_MB06_DATA0(val)		bfin_write16(CAN0_MB06_DATA0, val)
+#define bfin_read_CAN0_MB06_DATA1()		bfin_read16(CAN0_MB06_DATA1)
+#define bfin_write_CAN0_MB06_DATA1(val)		bfin_write16(CAN0_MB06_DATA1, val)
+#define bfin_read_CAN0_MB06_DATA2()		bfin_read16(CAN0_MB06_DATA2)
+#define bfin_write_CAN0_MB06_DATA2(val)		bfin_write16(CAN0_MB06_DATA2, val)
+#define bfin_read_CAN0_MB06_DATA3()		bfin_read16(CAN0_MB06_DATA3)
+#define bfin_write_CAN0_MB06_DATA3(val)		bfin_write16(CAN0_MB06_DATA3, val)
+#define bfin_read_CAN0_MB06_LENGTH()		bfin_read16(CAN0_MB06_LENGTH)
+#define bfin_write_CAN0_MB06_LENGTH(val)	bfin_write16(CAN0_MB06_LENGTH, val)
+#define bfin_read_CAN0_MB06_TIMESTAMP()		bfin_read16(CAN0_MB06_TIMESTAMP)
+#define bfin_write_CAN0_MB06_TIMESTAMP(val)	bfin_write16(CAN0_MB06_TIMESTAMP, val)
+#define bfin_read_CAN0_MB06_ID0()		bfin_read16(CAN0_MB06_ID0)
+#define bfin_write_CAN0_MB06_ID0(val)		bfin_write16(CAN0_MB06_ID0, val)
+#define bfin_read_CAN0_MB06_ID1()		bfin_read16(CAN0_MB06_ID1)
+#define bfin_write_CAN0_MB06_ID1(val)		bfin_write16(CAN0_MB06_ID1, val)
+#define bfin_read_CAN0_MB07_DATA0()		bfin_read16(CAN0_MB07_DATA0)
+#define bfin_write_CAN0_MB07_DATA0(val)		bfin_write16(CAN0_MB07_DATA0, val)
+#define bfin_read_CAN0_MB07_DATA1()		bfin_read16(CAN0_MB07_DATA1)
+#define bfin_write_CAN0_MB07_DATA1(val)		bfin_write16(CAN0_MB07_DATA1, val)
+#define bfin_read_CAN0_MB07_DATA2()		bfin_read16(CAN0_MB07_DATA2)
+#define bfin_write_CAN0_MB07_DATA2(val)		bfin_write16(CAN0_MB07_DATA2, val)
+#define bfin_read_CAN0_MB07_DATA3()		bfin_read16(CAN0_MB07_DATA3)
+#define bfin_write_CAN0_MB07_DATA3(val)		bfin_write16(CAN0_MB07_DATA3, val)
+#define bfin_read_CAN0_MB07_LENGTH()		bfin_read16(CAN0_MB07_LENGTH)
+#define bfin_write_CAN0_MB07_LENGTH(val)	bfin_write16(CAN0_MB07_LENGTH, val)
+#define bfin_read_CAN0_MB07_TIMESTAMP()		bfin_read16(CAN0_MB07_TIMESTAMP)
+#define bfin_write_CAN0_MB07_TIMESTAMP(val)	bfin_write16(CAN0_MB07_TIMESTAMP, val)
+#define bfin_read_CAN0_MB07_ID0()		bfin_read16(CAN0_MB07_ID0)
+#define bfin_write_CAN0_MB07_ID0(val)		bfin_write16(CAN0_MB07_ID0, val)
+#define bfin_read_CAN0_MB07_ID1()		bfin_read16(CAN0_MB07_ID1)
+#define bfin_write_CAN0_MB07_ID1(val)		bfin_write16(CAN0_MB07_ID1, val)
+#define bfin_read_CAN0_MB08_DATA0()		bfin_read16(CAN0_MB08_DATA0)
+#define bfin_write_CAN0_MB08_DATA0(val)		bfin_write16(CAN0_MB08_DATA0, val)
+#define bfin_read_CAN0_MB08_DATA1()		bfin_read16(CAN0_MB08_DATA1)
+#define bfin_write_CAN0_MB08_DATA1(val)		bfin_write16(CAN0_MB08_DATA1, val)
+#define bfin_read_CAN0_MB08_DATA2()		bfin_read16(CAN0_MB08_DATA2)
+#define bfin_write_CAN0_MB08_DATA2(val)		bfin_write16(CAN0_MB08_DATA2, val)
+#define bfin_read_CAN0_MB08_DATA3()		bfin_read16(CAN0_MB08_DATA3)
+#define bfin_write_CAN0_MB08_DATA3(val)		bfin_write16(CAN0_MB08_DATA3, val)
+#define bfin_read_CAN0_MB08_LENGTH()		bfin_read16(CAN0_MB08_LENGTH)
+#define bfin_write_CAN0_MB08_LENGTH(val)	bfin_write16(CAN0_MB08_LENGTH, val)
+#define bfin_read_CAN0_MB08_TIMESTAMP()		bfin_read16(CAN0_MB08_TIMESTAMP)
+#define bfin_write_CAN0_MB08_TIMESTAMP(val)	bfin_write16(CAN0_MB08_TIMESTAMP, val)
+#define bfin_read_CAN0_MB08_ID0()		bfin_read16(CAN0_MB08_ID0)
+#define bfin_write_CAN0_MB08_ID0(val)		bfin_write16(CAN0_MB08_ID0, val)
+#define bfin_read_CAN0_MB08_ID1()		bfin_read16(CAN0_MB08_ID1)
+#define bfin_write_CAN0_MB08_ID1(val)		bfin_write16(CAN0_MB08_ID1, val)
+#define bfin_read_CAN0_MB09_DATA0()		bfin_read16(CAN0_MB09_DATA0)
+#define bfin_write_CAN0_MB09_DATA0(val)		bfin_write16(CAN0_MB09_DATA0, val)
+#define bfin_read_CAN0_MB09_DATA1()		bfin_read16(CAN0_MB09_DATA1)
+#define bfin_write_CAN0_MB09_DATA1(val)		bfin_write16(CAN0_MB09_DATA1, val)
+#define bfin_read_CAN0_MB09_DATA2()		bfin_read16(CAN0_MB09_DATA2)
+#define bfin_write_CAN0_MB09_DATA2(val)		bfin_write16(CAN0_MB09_DATA2, val)
+#define bfin_read_CAN0_MB09_DATA3()		bfin_read16(CAN0_MB09_DATA3)
+#define bfin_write_CAN0_MB09_DATA3(val)		bfin_write16(CAN0_MB09_DATA3, val)
+#define bfin_read_CAN0_MB09_LENGTH()		bfin_read16(CAN0_MB09_LENGTH)
+#define bfin_write_CAN0_MB09_LENGTH(val)	bfin_write16(CAN0_MB09_LENGTH, val)
+#define bfin_read_CAN0_MB09_TIMESTAMP()		bfin_read16(CAN0_MB09_TIMESTAMP)
+#define bfin_write_CAN0_MB09_TIMESTAMP(val)	bfin_write16(CAN0_MB09_TIMESTAMP, val)
+#define bfin_read_CAN0_MB09_ID0()		bfin_read16(CAN0_MB09_ID0)
+#define bfin_write_CAN0_MB09_ID0(val)		bfin_write16(CAN0_MB09_ID0, val)
+#define bfin_read_CAN0_MB09_ID1()		bfin_read16(CAN0_MB09_ID1)
+#define bfin_write_CAN0_MB09_ID1(val)		bfin_write16(CAN0_MB09_ID1, val)
+#define bfin_read_CAN0_MB10_DATA0()		bfin_read16(CAN0_MB10_DATA0)
+#define bfin_write_CAN0_MB10_DATA0(val)		bfin_write16(CAN0_MB10_DATA0, val)
+#define bfin_read_CAN0_MB10_DATA1()		bfin_read16(CAN0_MB10_DATA1)
+#define bfin_write_CAN0_MB10_DATA1(val)		bfin_write16(CAN0_MB10_DATA1, val)
+#define bfin_read_CAN0_MB10_DATA2()		bfin_read16(CAN0_MB10_DATA2)
+#define bfin_write_CAN0_MB10_DATA2(val)		bfin_write16(CAN0_MB10_DATA2, val)
+#define bfin_read_CAN0_MB10_DATA3()		bfin_read16(CAN0_MB10_DATA3)
+#define bfin_write_CAN0_MB10_DATA3(val)		bfin_write16(CAN0_MB10_DATA3, val)
+#define bfin_read_CAN0_MB10_LENGTH()		bfin_read16(CAN0_MB10_LENGTH)
+#define bfin_write_CAN0_MB10_LENGTH(val)	bfin_write16(CAN0_MB10_LENGTH, val)
+#define bfin_read_CAN0_MB10_TIMESTAMP()		bfin_read16(CAN0_MB10_TIMESTAMP)
+#define bfin_write_CAN0_MB10_TIMESTAMP(val)	bfin_write16(CAN0_MB10_TIMESTAMP, val)
+#define bfin_read_CAN0_MB10_ID0()		bfin_read16(CAN0_MB10_ID0)
+#define bfin_write_CAN0_MB10_ID0(val)		bfin_write16(CAN0_MB10_ID0, val)
+#define bfin_read_CAN0_MB10_ID1()		bfin_read16(CAN0_MB10_ID1)
+#define bfin_write_CAN0_MB10_ID1(val)		bfin_write16(CAN0_MB10_ID1, val)
+#define bfin_read_CAN0_MB11_DATA0()		bfin_read16(CAN0_MB11_DATA0)
+#define bfin_write_CAN0_MB11_DATA0(val)		bfin_write16(CAN0_MB11_DATA0, val)
+#define bfin_read_CAN0_MB11_DATA1()		bfin_read16(CAN0_MB11_DATA1)
+#define bfin_write_CAN0_MB11_DATA1(val)		bfin_write16(CAN0_MB11_DATA1, val)
+#define bfin_read_CAN0_MB11_DATA2()		bfin_read16(CAN0_MB11_DATA2)
+#define bfin_write_CAN0_MB11_DATA2(val)		bfin_write16(CAN0_MB11_DATA2, val)
+#define bfin_read_CAN0_MB11_DATA3()		bfin_read16(CAN0_MB11_DATA3)
+#define bfin_write_CAN0_MB11_DATA3(val)		bfin_write16(CAN0_MB11_DATA3, val)
+#define bfin_read_CAN0_MB11_LENGTH()		bfin_read16(CAN0_MB11_LENGTH)
+#define bfin_write_CAN0_MB11_LENGTH(val)	bfin_write16(CAN0_MB11_LENGTH, val)
+#define bfin_read_CAN0_MB11_TIMESTAMP()		bfin_read16(CAN0_MB11_TIMESTAMP)
+#define bfin_write_CAN0_MB11_TIMESTAMP(val)	bfin_write16(CAN0_MB11_TIMESTAMP, val)
+#define bfin_read_CAN0_MB11_ID0()		bfin_read16(CAN0_MB11_ID0)
+#define bfin_write_CAN0_MB11_ID0(val)		bfin_write16(CAN0_MB11_ID0, val)
+#define bfin_read_CAN0_MB11_ID1()		bfin_read16(CAN0_MB11_ID1)
+#define bfin_write_CAN0_MB11_ID1(val)		bfin_write16(CAN0_MB11_ID1, val)
+#define bfin_read_CAN0_MB12_DATA0()		bfin_read16(CAN0_MB12_DATA0)
+#define bfin_write_CAN0_MB12_DATA0(val)		bfin_write16(CAN0_MB12_DATA0, val)
+#define bfin_read_CAN0_MB12_DATA1()		bfin_read16(CAN0_MB12_DATA1)
+#define bfin_write_CAN0_MB12_DATA1(val)		bfin_write16(CAN0_MB12_DATA1, val)
+#define bfin_read_CAN0_MB12_DATA2()		bfin_read16(CAN0_MB12_DATA2)
+#define bfin_write_CAN0_MB12_DATA2(val)		bfin_write16(CAN0_MB12_DATA2, val)
+#define bfin_read_CAN0_MB12_DATA3()		bfin_read16(CAN0_MB12_DATA3)
+#define bfin_write_CAN0_MB12_DATA3(val)		bfin_write16(CAN0_MB12_DATA3, val)
+#define bfin_read_CAN0_MB12_LENGTH()		bfin_read16(CAN0_MB12_LENGTH)
+#define bfin_write_CAN0_MB12_LENGTH(val)	bfin_write16(CAN0_MB12_LENGTH, val)
+#define bfin_read_CAN0_MB12_TIMESTAMP()		bfin_read16(CAN0_MB12_TIMESTAMP)
+#define bfin_write_CAN0_MB12_TIMESTAMP(val)	bfin_write16(CAN0_MB12_TIMESTAMP, val)
+#define bfin_read_CAN0_MB12_ID0()		bfin_read16(CAN0_MB12_ID0)
+#define bfin_write_CAN0_MB12_ID0(val)		bfin_write16(CAN0_MB12_ID0, val)
+#define bfin_read_CAN0_MB12_ID1()		bfin_read16(CAN0_MB12_ID1)
+#define bfin_write_CAN0_MB12_ID1(val)		bfin_write16(CAN0_MB12_ID1, val)
+#define bfin_read_CAN0_MB13_DATA0()		bfin_read16(CAN0_MB13_DATA0)
+#define bfin_write_CAN0_MB13_DATA0(val)		bfin_write16(CAN0_MB13_DATA0, val)
+#define bfin_read_CAN0_MB13_DATA1()		bfin_read16(CAN0_MB13_DATA1)
+#define bfin_write_CAN0_MB13_DATA1(val)		bfin_write16(CAN0_MB13_DATA1, val)
+#define bfin_read_CAN0_MB13_DATA2()		bfin_read16(CAN0_MB13_DATA2)
+#define bfin_write_CAN0_MB13_DATA2(val)		bfin_write16(CAN0_MB13_DATA2, val)
+#define bfin_read_CAN0_MB13_DATA3()		bfin_read16(CAN0_MB13_DATA3)
+#define bfin_write_CAN0_MB13_DATA3(val)		bfin_write16(CAN0_MB13_DATA3, val)
+#define bfin_read_CAN0_MB13_LENGTH()		bfin_read16(CAN0_MB13_LENGTH)
+#define bfin_write_CAN0_MB13_LENGTH(val)	bfin_write16(CAN0_MB13_LENGTH, val)
+#define bfin_read_CAN0_MB13_TIMESTAMP()		bfin_read16(CAN0_MB13_TIMESTAMP)
+#define bfin_write_CAN0_MB13_TIMESTAMP(val)	bfin_write16(CAN0_MB13_TIMESTAMP, val)
+#define bfin_read_CAN0_MB13_ID0()		bfin_read16(CAN0_MB13_ID0)
+#define bfin_write_CAN0_MB13_ID0(val)		bfin_write16(CAN0_MB13_ID0, val)
+#define bfin_read_CAN0_MB13_ID1()		bfin_read16(CAN0_MB13_ID1)
+#define bfin_write_CAN0_MB13_ID1(val)		bfin_write16(CAN0_MB13_ID1, val)
+#define bfin_read_CAN0_MB14_DATA0()		bfin_read16(CAN0_MB14_DATA0)
+#define bfin_write_CAN0_MB14_DATA0(val)		bfin_write16(CAN0_MB14_DATA0, val)
+#define bfin_read_CAN0_MB14_DATA1()		bfin_read16(CAN0_MB14_DATA1)
+#define bfin_write_CAN0_MB14_DATA1(val)		bfin_write16(CAN0_MB14_DATA1, val)
+#define bfin_read_CAN0_MB14_DATA2()		bfin_read16(CAN0_MB14_DATA2)
+#define bfin_write_CAN0_MB14_DATA2(val)		bfin_write16(CAN0_MB14_DATA2, val)
+#define bfin_read_CAN0_MB14_DATA3()		bfin_read16(CAN0_MB14_DATA3)
+#define bfin_write_CAN0_MB14_DATA3(val)		bfin_write16(CAN0_MB14_DATA3, val)
+#define bfin_read_CAN0_MB14_LENGTH()		bfin_read16(CAN0_MB14_LENGTH)
+#define bfin_write_CAN0_MB14_LENGTH(val)	bfin_write16(CAN0_MB14_LENGTH, val)
+#define bfin_read_CAN0_MB14_TIMESTAMP()		bfin_read16(CAN0_MB14_TIMESTAMP)
+#define bfin_write_CAN0_MB14_TIMESTAMP(val)	bfin_write16(CAN0_MB14_TIMESTAMP, val)
+#define bfin_read_CAN0_MB14_ID0()		bfin_read16(CAN0_MB14_ID0)
+#define bfin_write_CAN0_MB14_ID0(val)		bfin_write16(CAN0_MB14_ID0, val)
+#define bfin_read_CAN0_MB14_ID1()		bfin_read16(CAN0_MB14_ID1)
+#define bfin_write_CAN0_MB14_ID1(val)		bfin_write16(CAN0_MB14_ID1, val)
+#define bfin_read_CAN0_MB15_DATA0()		bfin_read16(CAN0_MB15_DATA0)
+#define bfin_write_CAN0_MB15_DATA0(val)		bfin_write16(CAN0_MB15_DATA0, val)
+#define bfin_read_CAN0_MB15_DATA1()		bfin_read16(CAN0_MB15_DATA1)
+#define bfin_write_CAN0_MB15_DATA1(val)		bfin_write16(CAN0_MB15_DATA1, val)
+#define bfin_read_CAN0_MB15_DATA2()		bfin_read16(CAN0_MB15_DATA2)
+#define bfin_write_CAN0_MB15_DATA2(val)		bfin_write16(CAN0_MB15_DATA2, val)
+#define bfin_read_CAN0_MB15_DATA3()		bfin_read16(CAN0_MB15_DATA3)
+#define bfin_write_CAN0_MB15_DATA3(val)		bfin_write16(CAN0_MB15_DATA3, val)
+#define bfin_read_CAN0_MB15_LENGTH()		bfin_read16(CAN0_MB15_LENGTH)
+#define bfin_write_CAN0_MB15_LENGTH(val)	bfin_write16(CAN0_MB15_LENGTH, val)
+#define bfin_read_CAN0_MB15_TIMESTAMP()		bfin_read16(CAN0_MB15_TIMESTAMP)
+#define bfin_write_CAN0_MB15_TIMESTAMP(val)	bfin_write16(CAN0_MB15_TIMESTAMP, val)
+#define bfin_read_CAN0_MB15_ID0()		bfin_read16(CAN0_MB15_ID0)
+#define bfin_write_CAN0_MB15_ID0(val)		bfin_write16(CAN0_MB15_ID0, val)
+#define bfin_read_CAN0_MB15_ID1()		bfin_read16(CAN0_MB15_ID1)
+#define bfin_write_CAN0_MB15_ID1(val)		bfin_write16(CAN0_MB15_ID1, val)
+
+/* CAN Controller 0 Mailbox Data Registers */
+
+#define bfin_read_CAN0_MB16_DATA0()		bfin_read16(CAN0_MB16_DATA0)
+#define bfin_write_CAN0_MB16_DATA0(val)		bfin_write16(CAN0_MB16_DATA0, val)
+#define bfin_read_CAN0_MB16_DATA1()		bfin_read16(CAN0_MB16_DATA1)
+#define bfin_write_CAN0_MB16_DATA1(val)		bfin_write16(CAN0_MB16_DATA1, val)
+#define bfin_read_CAN0_MB16_DATA2()		bfin_read16(CAN0_MB16_DATA2)
+#define bfin_write_CAN0_MB16_DATA2(val)		bfin_write16(CAN0_MB16_DATA2, val)
+#define bfin_read_CAN0_MB16_DATA3()		bfin_read16(CAN0_MB16_DATA3)
+#define bfin_write_CAN0_MB16_DATA3(val)		bfin_write16(CAN0_MB16_DATA3, val)
+#define bfin_read_CAN0_MB16_LENGTH()		bfin_read16(CAN0_MB16_LENGTH)
+#define bfin_write_CAN0_MB16_LENGTH(val)	bfin_write16(CAN0_MB16_LENGTH, val)
+#define bfin_read_CAN0_MB16_TIMESTAMP()		bfin_read16(CAN0_MB16_TIMESTAMP)
+#define bfin_write_CAN0_MB16_TIMESTAMP(val)	bfin_write16(CAN0_MB16_TIMESTAMP, val)
+#define bfin_read_CAN0_MB16_ID0()		bfin_read16(CAN0_MB16_ID0)
+#define bfin_write_CAN0_MB16_ID0(val)		bfin_write16(CAN0_MB16_ID0, val)
+#define bfin_read_CAN0_MB16_ID1()		bfin_read16(CAN0_MB16_ID1)
+#define bfin_write_CAN0_MB16_ID1(val)		bfin_write16(CAN0_MB16_ID1, val)
+#define bfin_read_CAN0_MB17_DATA0()		bfin_read16(CAN0_MB17_DATA0)
+#define bfin_write_CAN0_MB17_DATA0(val)		bfin_write16(CAN0_MB17_DATA0, val)
+#define bfin_read_CAN0_MB17_DATA1()		bfin_read16(CAN0_MB17_DATA1)
+#define bfin_write_CAN0_MB17_DATA1(val)		bfin_write16(CAN0_MB17_DATA1, val)
+#define bfin_read_CAN0_MB17_DATA2()		bfin_read16(CAN0_MB17_DATA2)
+#define bfin_write_CAN0_MB17_DATA2(val)		bfin_write16(CAN0_MB17_DATA2, val)
+#define bfin_read_CAN0_MB17_DATA3()		bfin_read16(CAN0_MB17_DATA3)
+#define bfin_write_CAN0_MB17_DATA3(val)		bfin_write16(CAN0_MB17_DATA3, val)
+#define bfin_read_CAN0_MB17_LENGTH()		bfin_read16(CAN0_MB17_LENGTH)
+#define bfin_write_CAN0_MB17_LENGTH(val)	bfin_write16(CAN0_MB17_LENGTH, val)
+#define bfin_read_CAN0_MB17_TIMESTAMP()		bfin_read16(CAN0_MB17_TIMESTAMP)
+#define bfin_write_CAN0_MB17_TIMESTAMP(val)	bfin_write16(CAN0_MB17_TIMESTAMP, val)
+#define bfin_read_CAN0_MB17_ID0()		bfin_read16(CAN0_MB17_ID0)
+#define bfin_write_CAN0_MB17_ID0(val)		bfin_write16(CAN0_MB17_ID0, val)
+#define bfin_read_CAN0_MB17_ID1()		bfin_read16(CAN0_MB17_ID1)
+#define bfin_write_CAN0_MB17_ID1(val)		bfin_write16(CAN0_MB17_ID1, val)
+#define bfin_read_CAN0_MB18_DATA0()		bfin_read16(CAN0_MB18_DATA0)
+#define bfin_write_CAN0_MB18_DATA0(val)		bfin_write16(CAN0_MB18_DATA0, val)
+#define bfin_read_CAN0_MB18_DATA1()		bfin_read16(CAN0_MB18_DATA1)
+#define bfin_write_CAN0_MB18_DATA1(val)		bfin_write16(CAN0_MB18_DATA1, val)
+#define bfin_read_CAN0_MB18_DATA2()		bfin_read16(CAN0_MB18_DATA2)
+#define bfin_write_CAN0_MB18_DATA2(val)		bfin_write16(CAN0_MB18_DATA2, val)
+#define bfin_read_CAN0_MB18_DATA3()		bfin_read16(CAN0_MB18_DATA3)
+#define bfin_write_CAN0_MB18_DATA3(val)		bfin_write16(CAN0_MB18_DATA3, val)
+#define bfin_read_CAN0_MB18_LENGTH()		bfin_read16(CAN0_MB18_LENGTH)
+#define bfin_write_CAN0_MB18_LENGTH(val)	bfin_write16(CAN0_MB18_LENGTH, val)
+#define bfin_read_CAN0_MB18_TIMESTAMP()		bfin_read16(CAN0_MB18_TIMESTAMP)
+#define bfin_write_CAN0_MB18_TIMESTAMP(val)	bfin_write16(CAN0_MB18_TIMESTAMP, val)
+#define bfin_read_CAN0_MB18_ID0()		bfin_read16(CAN0_MB18_ID0)
+#define bfin_write_CAN0_MB18_ID0(val)		bfin_write16(CAN0_MB18_ID0, val)
+#define bfin_read_CAN0_MB18_ID1()		bfin_read16(CAN0_MB18_ID1)
+#define bfin_write_CAN0_MB18_ID1(val)		bfin_write16(CAN0_MB18_ID1, val)
+#define bfin_read_CAN0_MB19_DATA0()		bfin_read16(CAN0_MB19_DATA0)
+#define bfin_write_CAN0_MB19_DATA0(val)		bfin_write16(CAN0_MB19_DATA0, val)
+#define bfin_read_CAN0_MB19_DATA1()		bfin_read16(CAN0_MB19_DATA1)
+#define bfin_write_CAN0_MB19_DATA1(val)		bfin_write16(CAN0_MB19_DATA1, val)
+#define bfin_read_CAN0_MB19_DATA2()		bfin_read16(CAN0_MB19_DATA2)
+#define bfin_write_CAN0_MB19_DATA2(val)		bfin_write16(CAN0_MB19_DATA2, val)
+#define bfin_read_CAN0_MB19_DATA3()		bfin_read16(CAN0_MB19_DATA3)
+#define bfin_write_CAN0_MB19_DATA3(val)		bfin_write16(CAN0_MB19_DATA3, val)
+#define bfin_read_CAN0_MB19_LENGTH()		bfin_read16(CAN0_MB19_LENGTH)
+#define bfin_write_CAN0_MB19_LENGTH(val)	bfin_write16(CAN0_MB19_LENGTH, val)
+#define bfin_read_CAN0_MB19_TIMESTAMP()		bfin_read16(CAN0_MB19_TIMESTAMP)
+#define bfin_write_CAN0_MB19_TIMESTAMP(val)	bfin_write16(CAN0_MB19_TIMESTAMP, val)
+#define bfin_read_CAN0_MB19_ID0()		bfin_read16(CAN0_MB19_ID0)
+#define bfin_write_CAN0_MB19_ID0(val)		bfin_write16(CAN0_MB19_ID0, val)
+#define bfin_read_CAN0_MB19_ID1()		bfin_read16(CAN0_MB19_ID1)
+#define bfin_write_CAN0_MB19_ID1(val)		bfin_write16(CAN0_MB19_ID1, val)
+#define bfin_read_CAN0_MB20_DATA0()		bfin_read16(CAN0_MB20_DATA0)
+#define bfin_write_CAN0_MB20_DATA0(val)		bfin_write16(CAN0_MB20_DATA0, val)
+#define bfin_read_CAN0_MB20_DATA1()		bfin_read16(CAN0_MB20_DATA1)
+#define bfin_write_CAN0_MB20_DATA1(val)		bfin_write16(CAN0_MB20_DATA1, val)
+#define bfin_read_CAN0_MB20_DATA2()		bfin_read16(CAN0_MB20_DATA2)
+#define bfin_write_CAN0_MB20_DATA2(val)		bfin_write16(CAN0_MB20_DATA2, val)
+#define bfin_read_CAN0_MB20_DATA3()		bfin_read16(CAN0_MB20_DATA3)
+#define bfin_write_CAN0_MB20_DATA3(val)		bfin_write16(CAN0_MB20_DATA3, val)
+#define bfin_read_CAN0_MB20_LENGTH()		bfin_read16(CAN0_MB20_LENGTH)
+#define bfin_write_CAN0_MB20_LENGTH(val)	bfin_write16(CAN0_MB20_LENGTH, val)
+#define bfin_read_CAN0_MB20_TIMESTAMP()		bfin_read16(CAN0_MB20_TIMESTAMP)
+#define bfin_write_CAN0_MB20_TIMESTAMP(val)	bfin_write16(CAN0_MB20_TIMESTAMP, val)
+#define bfin_read_CAN0_MB20_ID0()		bfin_read16(CAN0_MB20_ID0)
+#define bfin_write_CAN0_MB20_ID0(val)		bfin_write16(CAN0_MB20_ID0, val)
+#define bfin_read_CAN0_MB20_ID1()		bfin_read16(CAN0_MB20_ID1)
+#define bfin_write_CAN0_MB20_ID1(val)		bfin_write16(CAN0_MB20_ID1, val)
+#define bfin_read_CAN0_MB21_DATA0()		bfin_read16(CAN0_MB21_DATA0)
+#define bfin_write_CAN0_MB21_DATA0(val)		bfin_write16(CAN0_MB21_DATA0, val)
+#define bfin_read_CAN0_MB21_DATA1()		bfin_read16(CAN0_MB21_DATA1)
+#define bfin_write_CAN0_MB21_DATA1(val)		bfin_write16(CAN0_MB21_DATA1, val)
+#define bfin_read_CAN0_MB21_DATA2()		bfin_read16(CAN0_MB21_DATA2)
+#define bfin_write_CAN0_MB21_DATA2(val)		bfin_write16(CAN0_MB21_DATA2, val)
+#define bfin_read_CAN0_MB21_DATA3()		bfin_read16(CAN0_MB21_DATA3)
+#define bfin_write_CAN0_MB21_DATA3(val)		bfin_write16(CAN0_MB21_DATA3, val)
+#define bfin_read_CAN0_MB21_LENGTH()		bfin_read16(CAN0_MB21_LENGTH)
+#define bfin_write_CAN0_MB21_LENGTH(val)	bfin_write16(CAN0_MB21_LENGTH, val)
+#define bfin_read_CAN0_MB21_TIMESTAMP()		bfin_read16(CAN0_MB21_TIMESTAMP)
+#define bfin_write_CAN0_MB21_TIMESTAMP(val)	bfin_write16(CAN0_MB21_TIMESTAMP, val)
+#define bfin_read_CAN0_MB21_ID0()		bfin_read16(CAN0_MB21_ID0)
+#define bfin_write_CAN0_MB21_ID0(val)		bfin_write16(CAN0_MB21_ID0, val)
+#define bfin_read_CAN0_MB21_ID1()		bfin_read16(CAN0_MB21_ID1)
+#define bfin_write_CAN0_MB21_ID1(val)		bfin_write16(CAN0_MB21_ID1, val)
+#define bfin_read_CAN0_MB22_DATA0()		bfin_read16(CAN0_MB22_DATA0)
+#define bfin_write_CAN0_MB22_DATA0(val)		bfin_write16(CAN0_MB22_DATA0, val)
+#define bfin_read_CAN0_MB22_DATA1()		bfin_read16(CAN0_MB22_DATA1)
+#define bfin_write_CAN0_MB22_DATA1(val)		bfin_write16(CAN0_MB22_DATA1, val)
+#define bfin_read_CAN0_MB22_DATA2()		bfin_read16(CAN0_MB22_DATA2)
+#define bfin_write_CAN0_MB22_DATA2(val)		bfin_write16(CAN0_MB22_DATA2, val)
+#define bfin_read_CAN0_MB22_DATA3()		bfin_read16(CAN0_MB22_DATA3)
+#define bfin_write_CAN0_MB22_DATA3(val)		bfin_write16(CAN0_MB22_DATA3, val)
+#define bfin_read_CAN0_MB22_LENGTH()		bfin_read16(CAN0_MB22_LENGTH)
+#define bfin_write_CAN0_MB22_LENGTH(val)	bfin_write16(CAN0_MB22_LENGTH, val)
+#define bfin_read_CAN0_MB22_TIMESTAMP()		bfin_read16(CAN0_MB22_TIMESTAMP)
+#define bfin_write_CAN0_MB22_TIMESTAMP(val)	bfin_write16(CAN0_MB22_TIMESTAMP, val)
+#define bfin_read_CAN0_MB22_ID0()		bfin_read16(CAN0_MB22_ID0)
+#define bfin_write_CAN0_MB22_ID0(val)		bfin_write16(CAN0_MB22_ID0, val)
+#define bfin_read_CAN0_MB22_ID1()		bfin_read16(CAN0_MB22_ID1)
+#define bfin_write_CAN0_MB22_ID1(val)		bfin_write16(CAN0_MB22_ID1, val)
+#define bfin_read_CAN0_MB23_DATA0()		bfin_read16(CAN0_MB23_DATA0)
+#define bfin_write_CAN0_MB23_DATA0(val)		bfin_write16(CAN0_MB23_DATA0, val)
+#define bfin_read_CAN0_MB23_DATA1()		bfin_read16(CAN0_MB23_DATA1)
+#define bfin_write_CAN0_MB23_DATA1(val)		bfin_write16(CAN0_MB23_DATA1, val)
+#define bfin_read_CAN0_MB23_DATA2()		bfin_read16(CAN0_MB23_DATA2)
+#define bfin_write_CAN0_MB23_DATA2(val)		bfin_write16(CAN0_MB23_DATA2, val)
+#define bfin_read_CAN0_MB23_DATA3()		bfin_read16(CAN0_MB23_DATA3)
+#define bfin_write_CAN0_MB23_DATA3(val)		bfin_write16(CAN0_MB23_DATA3, val)
+#define bfin_read_CAN0_MB23_LENGTH()		bfin_read16(CAN0_MB23_LENGTH)
+#define bfin_write_CAN0_MB23_LENGTH(val)	bfin_write16(CAN0_MB23_LENGTH, val)
+#define bfin_read_CAN0_MB23_TIMESTAMP()		bfin_read16(CAN0_MB23_TIMESTAMP)
+#define bfin_write_CAN0_MB23_TIMESTAMP(val)	bfin_write16(CAN0_MB23_TIMESTAMP, val)
+#define bfin_read_CAN0_MB23_ID0()		bfin_read16(CAN0_MB23_ID0)
+#define bfin_write_CAN0_MB23_ID0(val)		bfin_write16(CAN0_MB23_ID0, val)
+#define bfin_read_CAN0_MB23_ID1()		bfin_read16(CAN0_MB23_ID1)
+#define bfin_write_CAN0_MB23_ID1(val)		bfin_write16(CAN0_MB23_ID1, val)
+#define bfin_read_CAN0_MB24_DATA0()		bfin_read16(CAN0_MB24_DATA0)
+#define bfin_write_CAN0_MB24_DATA0(val)		bfin_write16(CAN0_MB24_DATA0, val)
+#define bfin_read_CAN0_MB24_DATA1()		bfin_read16(CAN0_MB24_DATA1)
+#define bfin_write_CAN0_MB24_DATA1(val)		bfin_write16(CAN0_MB24_DATA1, val)
+#define bfin_read_CAN0_MB24_DATA2()		bfin_read16(CAN0_MB24_DATA2)
+#define bfin_write_CAN0_MB24_DATA2(val)		bfin_write16(CAN0_MB24_DATA2, val)
+#define bfin_read_CAN0_MB24_DATA3()		bfin_read16(CAN0_MB24_DATA3)
+#define bfin_write_CAN0_MB24_DATA3(val)		bfin_write16(CAN0_MB24_DATA3, val)
+#define bfin_read_CAN0_MB24_LENGTH()		bfin_read16(CAN0_MB24_LENGTH)
+#define bfin_write_CAN0_MB24_LENGTH(val)	bfin_write16(CAN0_MB24_LENGTH, val)
+#define bfin_read_CAN0_MB24_TIMESTAMP()		bfin_read16(CAN0_MB24_TIMESTAMP)
+#define bfin_write_CAN0_MB24_TIMESTAMP(val)	bfin_write16(CAN0_MB24_TIMESTAMP, val)
+#define bfin_read_CAN0_MB24_ID0()		bfin_read16(CAN0_MB24_ID0)
+#define bfin_write_CAN0_MB24_ID0(val)		bfin_write16(CAN0_MB24_ID0, val)
+#define bfin_read_CAN0_MB24_ID1()		bfin_read16(CAN0_MB24_ID1)
+#define bfin_write_CAN0_MB24_ID1(val)		bfin_write16(CAN0_MB24_ID1, val)
+#define bfin_read_CAN0_MB25_DATA0()		bfin_read16(CAN0_MB25_DATA0)
+#define bfin_write_CAN0_MB25_DATA0(val)		bfin_write16(CAN0_MB25_DATA0, val)
+#define bfin_read_CAN0_MB25_DATA1()		bfin_read16(CAN0_MB25_DATA1)
+#define bfin_write_CAN0_MB25_DATA1(val)		bfin_write16(CAN0_MB25_DATA1, val)
+#define bfin_read_CAN0_MB25_DATA2()		bfin_read16(CAN0_MB25_DATA2)
+#define bfin_write_CAN0_MB25_DATA2(val)		bfin_write16(CAN0_MB25_DATA2, val)
+#define bfin_read_CAN0_MB25_DATA3()		bfin_read16(CAN0_MB25_DATA3)
+#define bfin_write_CAN0_MB25_DATA3(val)		bfin_write16(CAN0_MB25_DATA3, val)
+#define bfin_read_CAN0_MB25_LENGTH()		bfin_read16(CAN0_MB25_LENGTH)
+#define bfin_write_CAN0_MB25_LENGTH(val)	bfin_write16(CAN0_MB25_LENGTH, val)
+#define bfin_read_CAN0_MB25_TIMESTAMP()		bfin_read16(CAN0_MB25_TIMESTAMP)
+#define bfin_write_CAN0_MB25_TIMESTAMP(val)	bfin_write16(CAN0_MB25_TIMESTAMP, val)
+#define bfin_read_CAN0_MB25_ID0()		bfin_read16(CAN0_MB25_ID0)
+#define bfin_write_CAN0_MB25_ID0(val)		bfin_write16(CAN0_MB25_ID0, val)
+#define bfin_read_CAN0_MB25_ID1()		bfin_read16(CAN0_MB25_ID1)
+#define bfin_write_CAN0_MB25_ID1(val)		bfin_write16(CAN0_MB25_ID1, val)
+#define bfin_read_CAN0_MB26_DATA0()		bfin_read16(CAN0_MB26_DATA0)
+#define bfin_write_CAN0_MB26_DATA0(val)		bfin_write16(CAN0_MB26_DATA0, val)
+#define bfin_read_CAN0_MB26_DATA1()		bfin_read16(CAN0_MB26_DATA1)
+#define bfin_write_CAN0_MB26_DATA1(val)		bfin_write16(CAN0_MB26_DATA1, val)
+#define bfin_read_CAN0_MB26_DATA2()		bfin_read16(CAN0_MB26_DATA2)
+#define bfin_write_CAN0_MB26_DATA2(val)		bfin_write16(CAN0_MB26_DATA2, val)
+#define bfin_read_CAN0_MB26_DATA3()		bfin_read16(CAN0_MB26_DATA3)
+#define bfin_write_CAN0_MB26_DATA3(val)		bfin_write16(CAN0_MB26_DATA3, val)
+#define bfin_read_CAN0_MB26_LENGTH()		bfin_read16(CAN0_MB26_LENGTH)
+#define bfin_write_CAN0_MB26_LENGTH(val)	bfin_write16(CAN0_MB26_LENGTH, val)
+#define bfin_read_CAN0_MB26_TIMESTAMP()		bfin_read16(CAN0_MB26_TIMESTAMP)
+#define bfin_write_CAN0_MB26_TIMESTAMP(val)	bfin_write16(CAN0_MB26_TIMESTAMP, val)
+#define bfin_read_CAN0_MB26_ID0()		bfin_read16(CAN0_MB26_ID0)
+#define bfin_write_CAN0_MB26_ID0(val)		bfin_write16(CAN0_MB26_ID0, val)
+#define bfin_read_CAN0_MB26_ID1()		bfin_read16(CAN0_MB26_ID1)
+#define bfin_write_CAN0_MB26_ID1(val)		bfin_write16(CAN0_MB26_ID1, val)
+#define bfin_read_CAN0_MB27_DATA0()		bfin_read16(CAN0_MB27_DATA0)
+#define bfin_write_CAN0_MB27_DATA0(val)		bfin_write16(CAN0_MB27_DATA0, val)
+#define bfin_read_CAN0_MB27_DATA1()		bfin_read16(CAN0_MB27_DATA1)
+#define bfin_write_CAN0_MB27_DATA1(val)		bfin_write16(CAN0_MB27_DATA1, val)
+#define bfin_read_CAN0_MB27_DATA2()		bfin_read16(CAN0_MB27_DATA2)
+#define bfin_write_CAN0_MB27_DATA2(val)		bfin_write16(CAN0_MB27_DATA2, val)
+#define bfin_read_CAN0_MB27_DATA3()		bfin_read16(CAN0_MB27_DATA3)
+#define bfin_write_CAN0_MB27_DATA3(val)		bfin_write16(CAN0_MB27_DATA3, val)
+#define bfin_read_CAN0_MB27_LENGTH()		bfin_read16(CAN0_MB27_LENGTH)
+#define bfin_write_CAN0_MB27_LENGTH(val)	bfin_write16(CAN0_MB27_LENGTH, val)
+#define bfin_read_CAN0_MB27_TIMESTAMP()		bfin_read16(CAN0_MB27_TIMESTAMP)
+#define bfin_write_CAN0_MB27_TIMESTAMP(val)	bfin_write16(CAN0_MB27_TIMESTAMP, val)
+#define bfin_read_CAN0_MB27_ID0()		bfin_read16(CAN0_MB27_ID0)
+#define bfin_write_CAN0_MB27_ID0(val)		bfin_write16(CAN0_MB27_ID0, val)
+#define bfin_read_CAN0_MB27_ID1()		bfin_read16(CAN0_MB27_ID1)
+#define bfin_write_CAN0_MB27_ID1(val)		bfin_write16(CAN0_MB27_ID1, val)
+#define bfin_read_CAN0_MB28_DATA0()		bfin_read16(CAN0_MB28_DATA0)
+#define bfin_write_CAN0_MB28_DATA0(val)		bfin_write16(CAN0_MB28_DATA0, val)
+#define bfin_read_CAN0_MB28_DATA1()		bfin_read16(CAN0_MB28_DATA1)
+#define bfin_write_CAN0_MB28_DATA1(val)		bfin_write16(CAN0_MB28_DATA1, val)
+#define bfin_read_CAN0_MB28_DATA2()		bfin_read16(CAN0_MB28_DATA2)
+#define bfin_write_CAN0_MB28_DATA2(val)		bfin_write16(CAN0_MB28_DATA2, val)
+#define bfin_read_CAN0_MB28_DATA3()		bfin_read16(CAN0_MB28_DATA3)
+#define bfin_write_CAN0_MB28_DATA3(val)		bfin_write16(CAN0_MB28_DATA3, val)
+#define bfin_read_CAN0_MB28_LENGTH()		bfin_read16(CAN0_MB28_LENGTH)
+#define bfin_write_CAN0_MB28_LENGTH(val)	bfin_write16(CAN0_MB28_LENGTH, val)
+#define bfin_read_CAN0_MB28_TIMESTAMP()		bfin_read16(CAN0_MB28_TIMESTAMP)
+#define bfin_write_CAN0_MB28_TIMESTAMP(val)	bfin_write16(CAN0_MB28_TIMESTAMP, val)
+#define bfin_read_CAN0_MB28_ID0()		bfin_read16(CAN0_MB28_ID0)
+#define bfin_write_CAN0_MB28_ID0(val)		bfin_write16(CAN0_MB28_ID0, val)
+#define bfin_read_CAN0_MB28_ID1()		bfin_read16(CAN0_MB28_ID1)
+#define bfin_write_CAN0_MB28_ID1(val)		bfin_write16(CAN0_MB28_ID1, val)
+#define bfin_read_CAN0_MB29_DATA0()		bfin_read16(CAN0_MB29_DATA0)
+#define bfin_write_CAN0_MB29_DATA0(val)		bfin_write16(CAN0_MB29_DATA0, val)
+#define bfin_read_CAN0_MB29_DATA1()		bfin_read16(CAN0_MB29_DATA1)
+#define bfin_write_CAN0_MB29_DATA1(val)		bfin_write16(CAN0_MB29_DATA1, val)
+#define bfin_read_CAN0_MB29_DATA2()		bfin_read16(CAN0_MB29_DATA2)
+#define bfin_write_CAN0_MB29_DATA2(val)		bfin_write16(CAN0_MB29_DATA2, val)
+#define bfin_read_CAN0_MB29_DATA3()		bfin_read16(CAN0_MB29_DATA3)
+#define bfin_write_CAN0_MB29_DATA3(val)		bfin_write16(CAN0_MB29_DATA3, val)
+#define bfin_read_CAN0_MB29_LENGTH()		bfin_read16(CAN0_MB29_LENGTH)
+#define bfin_write_CAN0_MB29_LENGTH(val)	bfin_write16(CAN0_MB29_LENGTH, val)
+#define bfin_read_CAN0_MB29_TIMESTAMP()		bfin_read16(CAN0_MB29_TIMESTAMP)
+#define bfin_write_CAN0_MB29_TIMESTAMP(val)	bfin_write16(CAN0_MB29_TIMESTAMP, val)
+#define bfin_read_CAN0_MB29_ID0()		bfin_read16(CAN0_MB29_ID0)
+#define bfin_write_CAN0_MB29_ID0(val)		bfin_write16(CAN0_MB29_ID0, val)
+#define bfin_read_CAN0_MB29_ID1()		bfin_read16(CAN0_MB29_ID1)
+#define bfin_write_CAN0_MB29_ID1(val)		bfin_write16(CAN0_MB29_ID1, val)
+#define bfin_read_CAN0_MB30_DATA0()		bfin_read16(CAN0_MB30_DATA0)
+#define bfin_write_CAN0_MB30_DATA0(val)		bfin_write16(CAN0_MB30_DATA0, val)
+#define bfin_read_CAN0_MB30_DATA1()		bfin_read16(CAN0_MB30_DATA1)
+#define bfin_write_CAN0_MB30_DATA1(val)		bfin_write16(CAN0_MB30_DATA1, val)
+#define bfin_read_CAN0_MB30_DATA2()		bfin_read16(CAN0_MB30_DATA2)
+#define bfin_write_CAN0_MB30_DATA2(val)		bfin_write16(CAN0_MB30_DATA2, val)
+#define bfin_read_CAN0_MB30_DATA3()		bfin_read16(CAN0_MB30_DATA3)
+#define bfin_write_CAN0_MB30_DATA3(val)		bfin_write16(CAN0_MB30_DATA3, val)
+#define bfin_read_CAN0_MB30_LENGTH()		bfin_read16(CAN0_MB30_LENGTH)
+#define bfin_write_CAN0_MB30_LENGTH(val)	bfin_write16(CAN0_MB30_LENGTH, val)
+#define bfin_read_CAN0_MB30_TIMESTAMP()		bfin_read16(CAN0_MB30_TIMESTAMP)
+#define bfin_write_CAN0_MB30_TIMESTAMP(val)	bfin_write16(CAN0_MB30_TIMESTAMP, val)
+#define bfin_read_CAN0_MB30_ID0()		bfin_read16(CAN0_MB30_ID0)
+#define bfin_write_CAN0_MB30_ID0(val)		bfin_write16(CAN0_MB30_ID0, val)
+#define bfin_read_CAN0_MB30_ID1()		bfin_read16(CAN0_MB30_ID1)
+#define bfin_write_CAN0_MB30_ID1(val)		bfin_write16(CAN0_MB30_ID1, val)
+#define bfin_read_CAN0_MB31_DATA0()		bfin_read16(CAN0_MB31_DATA0)
+#define bfin_write_CAN0_MB31_DATA0(val)		bfin_write16(CAN0_MB31_DATA0, val)
+#define bfin_read_CAN0_MB31_DATA1()		bfin_read16(CAN0_MB31_DATA1)
+#define bfin_write_CAN0_MB31_DATA1(val)		bfin_write16(CAN0_MB31_DATA1, val)
+#define bfin_read_CAN0_MB31_DATA2()		bfin_read16(CAN0_MB31_DATA2)
+#define bfin_write_CAN0_MB31_DATA2(val)		bfin_write16(CAN0_MB31_DATA2, val)
+#define bfin_read_CAN0_MB31_DATA3()		bfin_read16(CAN0_MB31_DATA3)
+#define bfin_write_CAN0_MB31_DATA3(val)		bfin_write16(CAN0_MB31_DATA3, val)
+#define bfin_read_CAN0_MB31_LENGTH()		bfin_read16(CAN0_MB31_LENGTH)
+#define bfin_write_CAN0_MB31_LENGTH(val)	bfin_write16(CAN0_MB31_LENGTH, val)
+#define bfin_read_CAN0_MB31_TIMESTAMP()		bfin_read16(CAN0_MB31_TIMESTAMP)
+#define bfin_write_CAN0_MB31_TIMESTAMP(val)	bfin_write16(CAN0_MB31_TIMESTAMP, val)
+#define bfin_read_CAN0_MB31_ID0()		bfin_read16(CAN0_MB31_ID0)
+#define bfin_write_CAN0_MB31_ID0(val)		bfin_write16(CAN0_MB31_ID0, val)
+#define bfin_read_CAN0_MB31_ID1()		bfin_read16(CAN0_MB31_ID1)
+#define bfin_write_CAN0_MB31_ID1(val)		bfin_write16(CAN0_MB31_ID1, val)
+
+/* UART3 Registers */
+
+#define bfin_read_UART3_DLL()		bfin_read16(UART3_DLL)
+#define bfin_write_UART3_DLL(val)	bfin_write16(UART3_DLL, val)
+#define bfin_read_UART3_DLH()		bfin_read16(UART3_DLH)
+#define bfin_write_UART3_DLH(val)	bfin_write16(UART3_DLH, val)
+#define bfin_read_UART3_GCTL()		bfin_read16(UART3_GCTL)
+#define bfin_write_UART3_GCTL(val)	bfin_write16(UART3_GCTL, val)
+#define bfin_read_UART3_LCR()		bfin_read16(UART3_LCR)
+#define bfin_write_UART3_LCR(val)	bfin_write16(UART3_LCR, val)
+#define bfin_read_UART3_MCR()		bfin_read16(UART3_MCR)
+#define bfin_write_UART3_MCR(val)	bfin_write16(UART3_MCR, val)
+#define bfin_read_UART3_LSR()		bfin_read16(UART3_LSR)
+#define bfin_write_UART3_LSR(val)	bfin_write16(UART3_LSR, val)
+#define bfin_read_UART3_MSR()		bfin_read16(UART3_MSR)
+#define bfin_write_UART3_MSR(val)	bfin_write16(UART3_MSR, val)
+#define bfin_read_UART3_SCR()		bfin_read16(UART3_SCR)
+#define bfin_write_UART3_SCR(val)	bfin_write16(UART3_SCR, val)
+#define bfin_read_UART3_IER_SET()	bfin_read16(UART3_IER_SET)
+#define bfin_write_UART3_IER_SET(val)	bfin_write16(UART3_IER_SET, val)
+#define bfin_read_UART3_IER_CLEAR()	bfin_read16(UART3_IER_CLEAR)
+#define bfin_write_UART3_IER_CLEAR(val)	bfin_write16(UART3_IER_CLEAR, val)
+#define bfin_read_UART3_THR()		bfin_read16(UART3_THR)
+#define bfin_write_UART3_THR(val)	bfin_write16(UART3_THR, val)
+#define bfin_read_UART3_RBR()		bfin_read16(UART3_RBR)
+#define bfin_write_UART3_RBR(val)	bfin_write16(UART3_RBR, val)
+
+/* NFC Registers */
+
+#define bfin_read_NFC_CTL()		bfin_read16(NFC_CTL)
+#define bfin_write_NFC_CTL(val)		bfin_write16(NFC_CTL, val)
+#define bfin_read_NFC_STAT()		bfin_read16(NFC_STAT)
+#define bfin_write_NFC_STAT(val)	bfin_write16(NFC_STAT, val)
+#define bfin_read_NFC_IRQSTAT()		bfin_read16(NFC_IRQSTAT)
+#define bfin_write_NFC_IRQSTAT(val)	bfin_write16(NFC_IRQSTAT, val)
+#define bfin_read_NFC_IRQMASK()		bfin_read16(NFC_IRQMASK)
+#define bfin_write_NFC_IRQMASK(val)	bfin_write16(NFC_IRQMASK, val)
+#define bfin_read_NFC_ECC0()		bfin_read16(NFC_ECC0)
+#define bfin_write_NFC_ECC0(val)	bfin_write16(NFC_ECC0, val)
+#define bfin_read_NFC_ECC1()		bfin_read16(NFC_ECC1)
+#define bfin_write_NFC_ECC1(val)	bfin_write16(NFC_ECC1, val)
+#define bfin_read_NFC_ECC2()		bfin_read16(NFC_ECC2)
+#define bfin_write_NFC_ECC2(val)	bfin_write16(NFC_ECC2, val)
+#define bfin_read_NFC_ECC3()		bfin_read16(NFC_ECC3)
+#define bfin_write_NFC_ECC3(val)	bfin_write16(NFC_ECC3, val)
+#define bfin_read_NFC_COUNT()		bfin_read16(NFC_COUNT)
+#define bfin_write_NFC_COUNT(val)	bfin_write16(NFC_COUNT, val)
+#define bfin_read_NFC_RST()		bfin_read16(NFC_RST)
+#define bfin_write_NFC_RST(val)		bfin_write16(NFC_RST, val)
+#define bfin_read_NFC_PGCTL()		bfin_read16(NFC_PGCTL)
+#define bfin_write_NFC_PGCTL(val)	bfin_write16(NFC_PGCTL, val)
+#define bfin_read_NFC_READ()		bfin_read16(NFC_READ)
+#define bfin_write_NFC_READ(val)	bfin_write16(NFC_READ, val)
+#define bfin_read_NFC_ADDR()		bfin_read16(NFC_ADDR)
+#define bfin_write_NFC_ADDR(val)	bfin_write16(NFC_ADDR, val)
+#define bfin_read_NFC_CMD()		bfin_read16(NFC_CMD)
+#define bfin_write_NFC_CMD(val)		bfin_write16(NFC_CMD, val)
+#define bfin_read_NFC_DATA_WR()		bfin_read16(NFC_DATA_WR)
+#define bfin_write_NFC_DATA_WR(val)	bfin_write16(NFC_DATA_WR, val)
+#define bfin_read_NFC_DATA_RD()		bfin_read16(NFC_DATA_RD)
+#define bfin_write_NFC_DATA_RD(val)	bfin_write16(NFC_DATA_RD, val)
+
+/* Counter Registers */
+
+#define bfin_read_CNT_CONFIG()		bfin_read16(CNT_CONFIG)
+#define bfin_write_CNT_CONFIG(val)	bfin_write16(CNT_CONFIG, val)
+#define bfin_read_CNT_IMASK()		bfin_read16(CNT_IMASK)
+#define bfin_write_CNT_IMASK(val)	bfin_write16(CNT_IMASK, val)
+#define bfin_read_CNT_STATUS()		bfin_read16(CNT_STATUS)
+#define bfin_write_CNT_STATUS(val)	bfin_write16(CNT_STATUS, val)
+#define bfin_read_CNT_COMMAND()		bfin_read16(CNT_COMMAND)
+#define bfin_write_CNT_COMMAND(val)	bfin_write16(CNT_COMMAND, val)
+#define bfin_read_CNT_DEBOUNCE()	bfin_read16(CNT_DEBOUNCE)
+#define bfin_write_CNT_DEBOUNCE(val)	bfin_write16(CNT_DEBOUNCE, val)
+#define bfin_read_CNT_COUNTER()		bfin_read32(CNT_COUNTER)
+#define bfin_write_CNT_COUNTER(val)	bfin_write32(CNT_COUNTER, val)
+#define bfin_read_CNT_MAX()		bfin_read32(CNT_MAX)
+#define bfin_write_CNT_MAX(val)		bfin_write32(CNT_MAX, val)
+#define bfin_read_CNT_MIN()		bfin_read32(CNT_MIN)
+#define bfin_write_CNT_MIN(val)		bfin_write32(CNT_MIN, val)
+
+/* OTP/FUSE Registers */
+
+#define bfin_read_OTP_CONTROL()		bfin_read16(OTP_CONTROL)
+#define bfin_write_OTP_CONTROL(val)	bfin_write16(OTP_CONTROL, val)
+#define bfin_read_OTP_BEN()		bfin_read16(OTP_BEN)
+#define bfin_write_OTP_BEN(val)		bfin_write16(OTP_BEN, val)
+#define bfin_read_OTP_STATUS()		bfin_read16(OTP_STATUS)
+#define bfin_write_OTP_STATUS(val)	bfin_write16(OTP_STATUS, val)
+#define bfin_read_OTP_TIMING()		bfin_read32(OTP_TIMING)
+#define bfin_write_OTP_TIMING(val)	bfin_write32(OTP_TIMING, val)
+
+/* Security Registers */
+
+#define bfin_read_SECURE_SYSSWT()	bfin_read32(SECURE_SYSSWT)
+#define bfin_write_SECURE_SYSSWT(val)	bfin_write32(SECURE_SYSSWT, val)
+#define bfin_read_SECURE_CONTROL()	bfin_read16(SECURE_CONTROL)
+#define bfin_write_SECURE_CONTROL(val)	bfin_write16(SECURE_CONTROL, val)
+#define bfin_read_SECURE_STATUS()	bfin_read16(SECURE_STATUS)
+#define bfin_write_SECURE_STATUS(val)	bfin_write16(SECURE_STATUS, val)
+
+/* DMA Peribfin_read_()heral Mux Register */
+
+#define bfin_read_DMAC1_PERIMUX()	bfin_read16(DMAC1_PERIMUX)
+#define bfin_write_DMAC1_PERIMUX(val)	bfin_write16(DMAC1_PERIMUX, val)
+
+/* OTP Read/Write Data Buffer Registers */
+
+#define bfin_read_OTP_DATA0()		bfin_read32(OTP_DATA0)
+#define bfin_write_OTP_DATA0(val)	bfin_write32(OTP_DATA0, val)
+#define bfin_read_OTP_DATA1()		bfin_read32(OTP_DATA1)
+#define bfin_write_OTP_DATA1(val)	bfin_write32(OTP_DATA1, val)
+#define bfin_read_OTP_DATA2()		bfin_read32(OTP_DATA2)
+#define bfin_write_OTP_DATA2(val)	bfin_write32(OTP_DATA2, val)
+#define bfin_read_OTP_DATA3()		bfin_read32(OTP_DATA3)
+#define bfin_write_OTP_DATA3(val)	bfin_write32(OTP_DATA3, val)
+
+/* Handshake MDMA is not defined in the shared file because it is not available on the ADSP-BF542 bfin_read_()rocessor */
+
+/* legacy definitions */
+#define bfin_read_EBIU_AMCBCTL0		bfin_read_EBIU_AMBCTL0
+#define bfin_write_EBIU_AMCBCTL0	bfin_write_EBIU_AMBCTL0
+#define bfin_read_EBIU_AMCBCTL1		bfin_read_EBIU_AMBCTL1
+#define bfin_write_EBIU_AMCBCTL1	bfin_write_EBIU_AMBCTL1
+#define bfin_read_PINT0_IRQ		bfin_read_PINT0_REQUEST
+#define bfin_write_PINT0_IRQ		bfin_write_PINT0_REQUEST
+#define bfin_read_PINT1_IRQ		bfin_read_PINT1_REQUEST
+#define bfin_write_PINT1_IRQ		bfin_write_PINT1_REQUEST
+#define bfin_read_PINT2_IRQ		bfin_read_PINT2_REQUEST
+#define bfin_write_PINT2_IRQ		bfin_write_PINT2_REQUEST
+#define bfin_read_PINT3_IRQ		bfin_read_PINT3_REQUEST
+#define bfin_write_PINT3_IRQ		bfin_write_PINT3_REQUEST
+
+#endif /* _CDEF_BF54X_H */
+
diff --git a/include/asm-blackfin/mach-bf548/defBF542.h b/include/asm-blackfin/mach-bf548/defBF542.h
new file mode 100644
index 0000000..32d0713
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/defBF542.h
@@ -0,0 +1,925 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/defBF542.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF542_H
+#define _DEF_BF542_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF542 */
+
+/* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
+#include "defBF54x_base.h"
+
+/* The following are the #defines needed by ADSP-BF542 that are not in the common header */
+
+/* ATAPI Registers */
+
+#define                    ATAPI_CONTROL  0xffc03800   /* ATAPI Control Register */
+#define                     ATAPI_STATUS  0xffc03804   /* ATAPI Status Register */
+#define                   ATAPI_DEV_ADDR  0xffc03808   /* ATAPI Device Register Address */
+#define                  ATAPI_DEV_TXBUF  0xffc0380c   /* ATAPI Device Register Write Data */
+#define                  ATAPI_DEV_RXBUF  0xffc03810   /* ATAPI Device Register Read Data */
+#define                   ATAPI_INT_MASK  0xffc03814   /* ATAPI Interrupt Mask Register */
+#define                 ATAPI_INT_STATUS  0xffc03818   /* ATAPI Interrupt Status Register */
+#define                   ATAPI_XFER_LEN  0xffc0381c   /* ATAPI Length of Transfer */
+#define                ATAPI_LINE_STATUS  0xffc03820   /* ATAPI Line Status */
+#define                   ATAPI_SM_STATE  0xffc03824   /* ATAPI State Machine Status */
+#define                  ATAPI_TERMINATE  0xffc03828   /* ATAPI Host Terminate */
+#define                 ATAPI_PIO_TFRCNT  0xffc0382c   /* ATAPI PIO mode transfer count */
+#define                 ATAPI_DMA_TFRCNT  0xffc03830   /* ATAPI DMA mode transfer count */
+#define               ATAPI_UMAIN_TFRCNT  0xffc03834   /* ATAPI UDMAIN transfer count */
+#define             ATAPI_UDMAOUT_TFRCNT  0xffc03838   /* ATAPI UDMAOUT transfer count */
+#define                  ATAPI_REG_TIM_0  0xffc03840   /* ATAPI Register Transfer Timing 0 */
+#define                  ATAPI_PIO_TIM_0  0xffc03844   /* ATAPI PIO Timing 0 Register */
+#define                  ATAPI_PIO_TIM_1  0xffc03848   /* ATAPI PIO Timing 1 Register */
+#define                ATAPI_MULTI_TIM_0  0xffc03850   /* ATAPI Multi-DMA Timing 0 Register */
+#define                ATAPI_MULTI_TIM_1  0xffc03854   /* ATAPI Multi-DMA Timing 1 Register */
+#define                ATAPI_MULTI_TIM_2  0xffc03858   /* ATAPI Multi-DMA Timing 2 Register */
+#define                ATAPI_ULTRA_TIM_0  0xffc03860   /* ATAPI Ultra-DMA Timing 0 Register */
+#define                ATAPI_ULTRA_TIM_1  0xffc03864   /* ATAPI Ultra-DMA Timing 1 Register */
+#define                ATAPI_ULTRA_TIM_2  0xffc03868   /* ATAPI Ultra-DMA Timing 2 Register */
+#define                ATAPI_ULTRA_TIM_3  0xffc0386c   /* ATAPI Ultra-DMA Timing 3 Register */
+
+/* SDH Registers */
+
+#define                      SDH_PWR_CTL  0xffc03900   /* SDH Power Control */
+#define                      SDH_CLK_CTL  0xffc03904   /* SDH Clock Control */
+#define                     SDH_ARGUMENT  0xffc03908   /* SDH Argument */
+#define                      SDH_COMMAND  0xffc0390c   /* SDH Command */
+#define                     SDH_RESP_CMD  0xffc03910   /* SDH Response Command */
+#define                    SDH_RESPONSE0  0xffc03914   /* SDH Response0 */
+#define                    SDH_RESPONSE1  0xffc03918   /* SDH Response1 */
+#define                    SDH_RESPONSE2  0xffc0391c   /* SDH Response2 */
+#define                    SDH_RESPONSE3  0xffc03920   /* SDH Response3 */
+#define                   SDH_DATA_TIMER  0xffc03924   /* SDH Data Timer */
+#define                    SDH_DATA_LGTH  0xffc03928   /* SDH Data Length */
+#define                     SDH_DATA_CTL  0xffc0392c   /* SDH Data Control */
+#define                     SDH_DATA_CNT  0xffc03930   /* SDH Data Counter */
+#define                       SDH_STATUS  0xffc03934   /* SDH Status */
+#define                   SDH_STATUS_CLR  0xffc03938   /* SDH Status Clear */
+#define                        SDH_MASK0  0xffc0393c   /* SDH Interrupt0 Mask */
+#define                        SDH_MASK1  0xffc03940   /* SDH Interrupt1 Mask */
+#define                     SDH_FIFO_CNT  0xffc03948   /* SDH FIFO Counter */
+#define                         SDH_FIFO  0xffc03980   /* SDH Data FIFO */
+#define                     SDH_E_STATUS  0xffc039c0   /* SDH Exception Status */
+#define                       SDH_E_MASK  0xffc039c4   /* SDH Exception Mask */
+#define                          SDH_CFG  0xffc039c8   /* SDH Configuration */
+#define                   SDH_RD_WAIT_EN  0xffc039cc   /* SDH Read Wait Enable */
+#define                         SDH_PID0  0xffc039d0   /* SDH Peripheral Identification0 */
+#define                         SDH_PID1  0xffc039d4   /* SDH Peripheral Identification1 */
+#define                         SDH_PID2  0xffc039d8   /* SDH Peripheral Identification2 */
+#define                         SDH_PID3  0xffc039dc   /* SDH Peripheral Identification3 */
+#define                         SDH_PID4  0xffc039e0   /* SDH Peripheral Identification4 */
+#define                         SDH_PID5  0xffc039e4   /* SDH Peripheral Identification5 */
+#define                         SDH_PID6  0xffc039e8   /* SDH Peripheral Identification6 */
+#define                         SDH_PID7  0xffc039ec   /* SDH Peripheral Identification7 */
+
+/* USB Control Registers */
+
+#define                        USB_FADDR  0xffc03c00   /* Function address register */
+#define                        USB_POWER  0xffc03c04   /* Power management register */
+#define                       USB_INTRTX  0xffc03c08   /* Interrupt register for endpoint 0 and Tx endpoint 1 to 7 */
+#define                       USB_INTRRX  0xffc03c0c   /* Interrupt register for Rx endpoints 1 to 7 */
+#define                      USB_INTRTXE  0xffc03c10   /* Interrupt enable register for IntrTx */
+#define                      USB_INTRRXE  0xffc03c14   /* Interrupt enable register for IntrRx */
+#define                      USB_INTRUSB  0xffc03c18   /* Interrupt register for common USB interrupts */
+#define                     USB_INTRUSBE  0xffc03c1c   /* Interrupt enable register for IntrUSB */
+#define                        USB_FRAME  0xffc03c20   /* USB frame number */
+#define                        USB_INDEX  0xffc03c24   /* Index register for selecting the indexed endpoint registers */
+#define                     USB_TESTMODE  0xffc03c28   /* Enabled USB 20 test modes */
+#define                     USB_GLOBINTR  0xffc03c2c   /* Global Interrupt Mask register and Wakeup Exception Interrupt */
+#define                   USB_GLOBAL_CTL  0xffc03c30   /* Global Clock Control for the core */
+
+/* USB Packet Control Registers */
+
+#define                USB_TX_MAX_PACKET  0xffc03c40   /* Maximum packet size for Host Tx endpoint */
+#define                         USB_CSR0  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                        USB_TXCSR  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                USB_RX_MAX_PACKET  0xffc03c48   /* Maximum packet size for Host Rx endpoint */
+#define                        USB_RXCSR  0xffc03c4c   /* Control Status register for Host Rx endpoint */
+#define                       USB_COUNT0  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                      USB_RXCOUNT  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                       USB_TXTYPE  0xffc03c54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint */
+#define                    USB_NAKLIMIT0  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                   USB_TXINTERVAL  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                       USB_RXTYPE  0xffc03c5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint */
+#define                   USB_RXINTERVAL  0xffc03c60   /* Sets the polling interval for Interrupt and Isochronous transfers or the NAK response timeout on Bulk transfers */
+#define                      USB_TXCOUNT  0xffc03c68   /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* USB Endpoint FIFO Registers */
+
+#define                     USB_EP0_FIFO  0xffc03c80   /* Endpoint 0 FIFO */
+#define                     USB_EP1_FIFO  0xffc03c88   /* Endpoint 1 FIFO */
+#define                     USB_EP2_FIFO  0xffc03c90   /* Endpoint 2 FIFO */
+#define                     USB_EP3_FIFO  0xffc03c98   /* Endpoint 3 FIFO */
+#define                     USB_EP4_FIFO  0xffc03ca0   /* Endpoint 4 FIFO */
+#define                     USB_EP5_FIFO  0xffc03ca8   /* Endpoint 5 FIFO */
+#define                     USB_EP6_FIFO  0xffc03cb0   /* Endpoint 6 FIFO */
+#define                     USB_EP7_FIFO  0xffc03cb8   /* Endpoint 7 FIFO */
+
+/* USB OTG Control Registers */
+
+#define                  USB_OTG_DEV_CTL  0xffc03d00   /* OTG Device Control Register */
+#define                 USB_OTG_VBUS_IRQ  0xffc03d04   /* OTG VBUS Control Interrupts */
+#define                USB_OTG_VBUS_MASK  0xffc03d08   /* VBUS Control Interrupt Enable */
+
+/* USB Phy Control Registers */
+
+#define                     USB_LINKINFO  0xffc03d48   /* Enables programming of some PHY-side delays */
+#define                        USB_VPLEN  0xffc03d4c   /* Determines duration of VBUS pulse for VBUS charging */
+#define                      USB_HS_EOF1  0xffc03d50   /* Time buffer for High-Speed transactions */
+#define                      USB_FS_EOF1  0xffc03d54   /* Time buffer for Full-Speed transactions */
+#define                      USB_LS_EOF1  0xffc03d58   /* Time buffer for Low-Speed transactions */
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define                   USB_APHY_CNTRL  0xffc03de0   /* Register that increases visibility of Analog PHY */
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define                   USB_APHY_CALIB  0xffc03de4   /* Register used to set some calibration values */
+#define                  USB_APHY_CNTRL2  0xffc03de8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define                     USB_PHY_TEST  0xffc03dec   /* Used for reducing simulation time and simplifies FIFO testability */
+#define                  USB_PLLOSC_CTRL  0xffc03df0   /* Used to program different parameters for USB PLL and Oscillator */
+#define                   USB_SRP_CLKDIV  0xffc03df4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
+
+/* USB Endpoint 0 Control Registers */
+
+#define                USB_EP_NI0_TXMAXP  0xffc03e00   /* Maximum packet size for Host Tx endpoint0 */
+#define                 USB_EP_NI0_TXCSR  0xffc03e04   /* Control Status register for endpoint 0 */
+#define                USB_EP_NI0_RXMAXP  0xffc03e08   /* Maximum packet size for Host Rx endpoint0 */
+#define                 USB_EP_NI0_RXCSR  0xffc03e0c   /* Control Status register for Host Rx endpoint0 */
+#define               USB_EP_NI0_RXCOUNT  0xffc03e10   /* Number of bytes received in endpoint 0 FIFO */
+#define                USB_EP_NI0_TXTYPE  0xffc03e14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint0 */
+#define            USB_EP_NI0_TXINTERVAL  0xffc03e18   /* Sets the NAK response timeout on Endpoint 0 */
+#define                USB_EP_NI0_RXTYPE  0xffc03e1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint0 */
+#define            USB_EP_NI0_RXINTERVAL  0xffc03e20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint0 */
+
+/* USB Endpoint 1 Control Registers */
+
+#define               USB_EP_NI0_TXCOUNT  0xffc03e28   /* Number of bytes to be written to the endpoint0 Tx FIFO */
+#define                USB_EP_NI1_TXMAXP  0xffc03e40   /* Maximum packet size for Host Tx endpoint1 */
+#define                 USB_EP_NI1_TXCSR  0xffc03e44   /* Control Status register for endpoint1 */
+#define                USB_EP_NI1_RXMAXP  0xffc03e48   /* Maximum packet size for Host Rx endpoint1 */
+#define                 USB_EP_NI1_RXCSR  0xffc03e4c   /* Control Status register for Host Rx endpoint1 */
+#define               USB_EP_NI1_RXCOUNT  0xffc03e50   /* Number of bytes received in endpoint1 FIFO */
+#define                USB_EP_NI1_TXTYPE  0xffc03e54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint1 */
+#define            USB_EP_NI1_TXINTERVAL  0xffc03e58   /* Sets the NAK response timeout on Endpoint1 */
+#define                USB_EP_NI1_RXTYPE  0xffc03e5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint1 */
+#define            USB_EP_NI1_RXINTERVAL  0xffc03e60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint1 */
+
+/* USB Endpoint 2 Control Registers */
+
+#define               USB_EP_NI1_TXCOUNT  0xffc03e68   /* Number of bytes to be written to the+H102 endpoint1 Tx FIFO */
+#define                USB_EP_NI2_TXMAXP  0xffc03e80   /* Maximum packet size for Host Tx endpoint2 */
+#define                 USB_EP_NI2_TXCSR  0xffc03e84   /* Control Status register for endpoint2 */
+#define                USB_EP_NI2_RXMAXP  0xffc03e88   /* Maximum packet size for Host Rx endpoint2 */
+#define                 USB_EP_NI2_RXCSR  0xffc03e8c   /* Control Status register for Host Rx endpoint2 */
+#define               USB_EP_NI2_RXCOUNT  0xffc03e90   /* Number of bytes received in endpoint2 FIFO */
+#define                USB_EP_NI2_TXTYPE  0xffc03e94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint2 */
+#define            USB_EP_NI2_TXINTERVAL  0xffc03e98   /* Sets the NAK response timeout on Endpoint2 */
+#define                USB_EP_NI2_RXTYPE  0xffc03e9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint2 */
+#define            USB_EP_NI2_RXINTERVAL  0xffc03ea0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint2 */
+
+/* USB Endpoint 3 Control Registers */
+
+#define               USB_EP_NI2_TXCOUNT  0xffc03ea8   /* Number of bytes to be written to the endpoint2 Tx FIFO */
+#define                USB_EP_NI3_TXMAXP  0xffc03ec0   /* Maximum packet size for Host Tx endpoint3 */
+#define                 USB_EP_NI3_TXCSR  0xffc03ec4   /* Control Status register for endpoint3 */
+#define                USB_EP_NI3_RXMAXP  0xffc03ec8   /* Maximum packet size for Host Rx endpoint3 */
+#define                 USB_EP_NI3_RXCSR  0xffc03ecc   /* Control Status register for Host Rx endpoint3 */
+#define               USB_EP_NI3_RXCOUNT  0xffc03ed0   /* Number of bytes received in endpoint3 FIFO */
+#define                USB_EP_NI3_TXTYPE  0xffc03ed4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint3 */
+#define            USB_EP_NI3_TXINTERVAL  0xffc03ed8   /* Sets the NAK response timeout on Endpoint3 */
+#define                USB_EP_NI3_RXTYPE  0xffc03edc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint3 */
+#define            USB_EP_NI3_RXINTERVAL  0xffc03ee0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint3 */
+
+/* USB Endpoint 4 Control Registers */
+
+#define               USB_EP_NI3_TXCOUNT  0xffc03ee8   /* Number of bytes to be written to the H124endpoint3 Tx FIFO */
+#define                USB_EP_NI4_TXMAXP  0xffc03f00   /* Maximum packet size for Host Tx endpoint4 */
+#define                 USB_EP_NI4_TXCSR  0xffc03f04   /* Control Status register for endpoint4 */
+#define                USB_EP_NI4_RXMAXP  0xffc03f08   /* Maximum packet size for Host Rx endpoint4 */
+#define                 USB_EP_NI4_RXCSR  0xffc03f0c   /* Control Status register for Host Rx endpoint4 */
+#define               USB_EP_NI4_RXCOUNT  0xffc03f10   /* Number of bytes received in endpoint4 FIFO */
+#define                USB_EP_NI4_TXTYPE  0xffc03f14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint4 */
+#define            USB_EP_NI4_TXINTERVAL  0xffc03f18   /* Sets the NAK response timeout on Endpoint4 */
+#define                USB_EP_NI4_RXTYPE  0xffc03f1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint4 */
+#define            USB_EP_NI4_RXINTERVAL  0xffc03f20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint4 */
+
+/* USB Endpoint 5 Control Registers */
+
+#define               USB_EP_NI4_TXCOUNT  0xffc03f28   /* Number of bytes to be written to the endpoint4 Tx FIFO */
+#define                USB_EP_NI5_TXMAXP  0xffc03f40   /* Maximum packet size for Host Tx endpoint5 */
+#define                 USB_EP_NI5_TXCSR  0xffc03f44   /* Control Status register for endpoint5 */
+#define                USB_EP_NI5_RXMAXP  0xffc03f48   /* Maximum packet size for Host Rx endpoint5 */
+#define                 USB_EP_NI5_RXCSR  0xffc03f4c   /* Control Status register for Host Rx endpoint5 */
+#define               USB_EP_NI5_RXCOUNT  0xffc03f50   /* Number of bytes received in endpoint5 FIFO */
+#define                USB_EP_NI5_TXTYPE  0xffc03f54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint5 */
+#define            USB_EP_NI5_TXINTERVAL  0xffc03f58   /* Sets the NAK response timeout on Endpoint5 */
+#define                USB_EP_NI5_RXTYPE  0xffc03f5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint5 */
+#define            USB_EP_NI5_RXINTERVAL  0xffc03f60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint5 */
+
+/* USB Endpoint 6 Control Registers */
+
+#define               USB_EP_NI5_TXCOUNT  0xffc03f68   /* Number of bytes to be written to the H145endpoint5 Tx FIFO */
+#define                USB_EP_NI6_TXMAXP  0xffc03f80   /* Maximum packet size for Host Tx endpoint6 */
+#define                 USB_EP_NI6_TXCSR  0xffc03f84   /* Control Status register for endpoint6 */
+#define                USB_EP_NI6_RXMAXP  0xffc03f88   /* Maximum packet size for Host Rx endpoint6 */
+#define                 USB_EP_NI6_RXCSR  0xffc03f8c   /* Control Status register for Host Rx endpoint6 */
+#define               USB_EP_NI6_RXCOUNT  0xffc03f90   /* Number of bytes received in endpoint6 FIFO */
+#define                USB_EP_NI6_TXTYPE  0xffc03f94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint6 */
+#define            USB_EP_NI6_TXINTERVAL  0xffc03f98   /* Sets the NAK response timeout on Endpoint6 */
+#define                USB_EP_NI6_RXTYPE  0xffc03f9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint6 */
+#define            USB_EP_NI6_RXINTERVAL  0xffc03fa0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint6 */
+
+/* USB Endpoint 7 Control Registers */
+
+#define               USB_EP_NI6_TXCOUNT  0xffc03fa8   /* Number of bytes to be written to the endpoint6 Tx FIFO */
+#define                USB_EP_NI7_TXMAXP  0xffc03fc0   /* Maximum packet size for Host Tx endpoint7 */
+#define                 USB_EP_NI7_TXCSR  0xffc03fc4   /* Control Status register for endpoint7 */
+#define                USB_EP_NI7_RXMAXP  0xffc03fc8   /* Maximum packet size for Host Rx endpoint7 */
+#define                 USB_EP_NI7_RXCSR  0xffc03fcc   /* Control Status register for Host Rx endpoint7 */
+#define               USB_EP_NI7_RXCOUNT  0xffc03fd0   /* Number of bytes received in endpoint7 FIFO */
+#define                USB_EP_NI7_TXTYPE  0xffc03fd4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint7 */
+#define            USB_EP_NI7_TXINTERVAL  0xffc03fd8   /* Sets the NAK response timeout on Endpoint7 */
+#define                USB_EP_NI7_RXTYPE  0xffc03fdc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint7 */
+#define            USB_EP_NI7_RXINTERVAL  0xffc03ff0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint7 */
+#define               USB_EP_NI7_TXCOUNT  0xffc03ff8   /* Number of bytes to be written to the endpoint7 Tx FIFO */
+#define                USB_DMA_INTERRUPT  0xffc04000   /* Indicates pending interrupts for the DMA channels */
+
+/* USB Channel 0 Config Registers */
+
+#define                  USB_DMA0CONTROL  0xffc04004   /* DMA master channel 0 configuration */
+#define                  USB_DMA0ADDRLOW  0xffc04008   /* Lower 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0ADDRHIGH  0xffc0400c   /* Upper 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0COUNTLOW  0xffc04010   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 0 */
+#define                USB_DMA0COUNTHIGH  0xffc04014   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 0 */
+
+/* USB Channel 1 Config Registers */
+
+#define                  USB_DMA1CONTROL  0xffc04024   /* DMA master channel 1 configuration */
+#define                  USB_DMA1ADDRLOW  0xffc04028   /* Lower 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1ADDRHIGH  0xffc0402c   /* Upper 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1COUNTLOW  0xffc04030   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 1 */
+#define                USB_DMA1COUNTHIGH  0xffc04034   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 1 */
+
+/* USB Channel 2 Config Registers */
+
+#define                  USB_DMA2CONTROL  0xffc04044   /* DMA master channel 2 configuration */
+#define                  USB_DMA2ADDRLOW  0xffc04048   /* Lower 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2ADDRHIGH  0xffc0404c   /* Upper 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2COUNTLOW  0xffc04050   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 2 */
+#define                USB_DMA2COUNTHIGH  0xffc04054   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 2 */
+
+/* USB Channel 3 Config Registers */
+
+#define                  USB_DMA3CONTROL  0xffc04064   /* DMA master channel 3 configuration */
+#define                  USB_DMA3ADDRLOW  0xffc04068   /* Lower 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3ADDRHIGH  0xffc0406c   /* Upper 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3COUNTLOW  0xffc04070   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 3 */
+#define                USB_DMA3COUNTHIGH  0xffc04074   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 3 */
+
+/* USB Channel 4 Config Registers */
+
+#define                  USB_DMA4CONTROL  0xffc04084   /* DMA master channel 4 configuration */
+#define                  USB_DMA4ADDRLOW  0xffc04088   /* Lower 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4ADDRHIGH  0xffc0408c   /* Upper 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4COUNTLOW  0xffc04090   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 4 */
+#define                USB_DMA4COUNTHIGH  0xffc04094   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 4 */
+
+/* USB Channel 5 Config Registers */
+
+#define                  USB_DMA5CONTROL  0xffc040a4   /* DMA master channel 5 configuration */
+#define                  USB_DMA5ADDRLOW  0xffc040a8   /* Lower 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5ADDRHIGH  0xffc040ac   /* Upper 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5COUNTLOW  0xffc040b0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 5 */
+#define                USB_DMA5COUNTHIGH  0xffc040b4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 5 */
+
+/* USB Channel 6 Config Registers */
+
+#define                  USB_DMA6CONTROL  0xffc040c4   /* DMA master channel 6 configuration */
+#define                  USB_DMA6ADDRLOW  0xffc040c8   /* Lower 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6ADDRHIGH  0xffc040cc   /* Upper 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6COUNTLOW  0xffc040d0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 6 */
+#define                USB_DMA6COUNTHIGH  0xffc040d4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 6 */
+
+/* USB Channel 7 Config Registers */
+
+#define                  USB_DMA7CONTROL  0xffc040e4   /* DMA master channel 7 configuration */
+#define                  USB_DMA7ADDRLOW  0xffc040e8   /* Lower 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7ADDRHIGH  0xffc040ec   /* Upper 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7COUNTLOW  0xffc040f0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 7 */
+#define                USB_DMA7COUNTHIGH  0xffc040f4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 7 */
+
+/* Keypad Registers */
+
+#define                         KPAD_CTL  0xffc04100   /* Controls keypad module enable and disable */
+#define                    KPAD_PRESCALE  0xffc04104   /* Establish a time base for programing the KPAD_MSEL register */
+#define                        KPAD_MSEL  0xffc04108   /* Selects delay parameters for keypad interface sensitivity */
+#define                      KPAD_ROWCOL  0xffc0410c   /* Captures the row and column output values of the keys pressed */
+#define                        KPAD_STAT  0xffc04110   /* Holds and clears the status of the keypad interface interrupt */
+#define                    KPAD_SOFTEVAL  0xffc04114   /* Lets software force keypad interface to check for keys being pressed */
+
+
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for KPAD_CTL */
+
+#define                   KPAD_EN  0x1        /* Keypad Enable */
+#define              KPAD_IRQMODE  0x6        /* Key Press Interrupt Enable */
+#define                KPAD_ROWEN  0x1c00     /* Row Enable Width */
+#define                KPAD_COLEN  0xe000     /* Column Enable Width */
+
+/* Bit masks for KPAD_PRESCALE */
+
+#define         KPAD_PRESCALE_VAL  0x3f       /* Key Prescale Value */
+
+/* Bit masks for KPAD_MSEL */
+
+#define                DBON_SCALE  0xff       /* Debounce Scale Value */
+#define              COLDRV_SCALE  0xff00     /* Column Driver Scale Value */
+
+/* Bit masks for KPAD_ROWCOL */
+
+#define                  KPAD_ROW  0xff       /* Rows Pressed */
+#define                  KPAD_COL  0xff00     /* Columns Pressed */
+
+/* Bit masks for KPAD_STAT */
+
+#define                  KPAD_IRQ  0x1        /* Keypad Interrupt Status */
+#define              KPAD_MROWCOL  0x6        /* Multiple Row/Column Keypress Status */
+#define              KPAD_PRESSED  0x8        /* Key press current status */
+
+/* Bit masks for KPAD_SOFTEVAL */
+
+#define           KPAD_SOFTEVAL_E  0x2        /* Software Programmable Force Evaluate */
+
+/* Bit masks for SDH_COMMAND */
+
+#define                   CMD_IDX  0x3f       /* Command Index */
+#define                   CMD_RSP  0x40       /* Response */
+#define                 CMD_L_RSP  0x80       /* Long Response */
+#define                 CMD_INT_E  0x100      /* Command Interrupt */
+#define                CMD_PEND_E  0x200      /* Command Pending */
+#define                     CMD_E  0x400      /* Command Enable */
+
+/* Bit masks for SDH_PWR_CTL */
+
+#define                    PWR_ON  0x3        /* Power On */
+#if 0
+#define                       TBD  0x3c       /* TBD */
+#endif
+#define                 SD_CMD_OD  0x40       /* Open Drain Output */
+#define                   ROD_CTL  0x80       /* Rod Control */
+
+/* Bit masks for SDH_CLK_CTL */
+
+#define                    CLKDIV  0xff       /* MC_CLK Divisor */
+#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
+#define                  PWR_SV_E  0x200      /* Power Save Enable */
+#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
+#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
+
+/* Bit masks for SDH_RESP_CMD */
+
+#define                  RESP_CMD  0x3f       /* Response Command */
+
+/* Bit masks for SDH_DATA_CTL */
+
+#define                     DTX_E  0x1        /* Data Transfer Enable */
+#define                   DTX_DIR  0x2        /* Data Transfer Direction */
+#define                  DTX_MODE  0x4        /* Data Transfer Mode */
+#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
+#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
+
+/* Bit masks for SDH_STATUS */
+
+#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
+#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
+#define               CMD_TIMEOUT  0x4        /* CMD Time Out */
+#define               DAT_TIMEOUT  0x8        /* Data Time Out */
+#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
+#define                RX_OVERRUN  0x20       /* Receive Overrun */
+#define              CMD_RESP_END  0x40       /* CMD Response End */
+#define                  CMD_SENT  0x80       /* CMD Sent */
+#define                   DAT_END  0x100      /* Data End */
+#define             START_BIT_ERR  0x200      /* Start Bit Error */
+#define               DAT_BLK_END  0x400      /* Data Block End */
+#define                   CMD_ACT  0x800      /* CMD Active */
+#define                    TX_ACT  0x1000     /* Transmit Active */
+#define                    RX_ACT  0x2000     /* Receive Active */
+#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
+#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
+#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
+#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
+#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
+#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
+#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
+#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
+
+/* Bit masks for SDH_STATUS_CLR */
+
+#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
+#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
+#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
+#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
+#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
+#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
+#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
+#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
+#define              DAT_END_STAT  0x100      /* Data End Status */
+#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
+#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
+
+/* Bit masks for SDH_MASK0 */
+
+#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
+#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
+#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
+#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
+#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
+#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
+#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
+#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
+#define              DAT_END_MASK  0x100      /* Data End Mask */
+#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
+#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
+#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
+#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
+#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
+#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
+#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
+#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
+#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
+#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
+#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
+#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
+#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
+
+/* Bit masks for SDH_FIFO_CNT */
+
+#define                FIFO_COUNT  0x7fff     /* FIFO Count */
+
+/* Bit masks for SDH_E_STATUS */
+
+#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
+#define               SD_CARD_DET  0x10       /* SD Card Detect */
+
+/* Bit masks for SDH_E_MASK */
+
+#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
+#define                   SCD_MSK  0x40       /* Mask Card Detect */
+
+/* Bit masks for SDH_CFG */
+
+#define                   CLKS_EN  0x1        /* Clocks Enable */
+#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
+#define                       MWE  0x8        /* Moving Window Enable */
+#define                    SD_RST  0x10       /* SDMMC Reset */
+#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
+#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
+#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
+
+/* Bit masks for SDH_RD_WAIT_EN */
+
+#define                       RWR  0x1        /* Read Wait Request */
+
+/* Bit masks for ATAPI_CONTROL */
+
+#define                 PIO_START  0x1        /* Start PIO/Reg Op */
+#define               MULTI_START  0x2        /* Start Multi-DMA Op */
+#define               ULTRA_START  0x4        /* Start Ultra-DMA Op */
+#define                  XFER_DIR  0x8        /* Transfer Direction */
+#define                  IORDY_EN  0x10       /* IORDY Enable */
+#define                FIFO_FLUSH  0x20       /* Flush FIFOs */
+#define                  SOFT_RST  0x40       /* Soft Reset */
+#define                   DEV_RST  0x80       /* Device Reset */
+#define                TFRCNT_RST  0x100      /* Trans Count Reset */
+#define               END_ON_TERM  0x200      /* End/Terminate Select */
+#define               PIO_USE_DMA  0x400      /* PIO-DMA Enable */
+#define          UDMAIN_FIFO_THRS  0xf000     /* Ultra DMA-IN FIFO Threshold */
+
+/* Bit masks for ATAPI_STATUS */
+
+#define               PIO_XFER_ON  0x1        /* PIO transfer in progress */
+#define             MULTI_XFER_ON  0x2        /* Multi-word DMA transfer in progress */
+#define             ULTRA_XFER_ON  0x4        /* Ultra DMA transfer in progress */
+#define               ULTRA_IN_FL  0xf0       /* Ultra DMA Input FIFO Level */
+
+/* Bit masks for ATAPI_DEV_ADDR */
+
+#define                  DEV_ADDR  0x1f       /* Device Address */
+
+/* Bit masks for ATAPI_INT_MASK */
+
+#define        ATAPI_DEV_INT_MASK  0x1        /* Device interrupt mask */
+#define             PIO_DONE_MASK  0x2        /* PIO transfer done interrupt mask */
+#define           MULTI_DONE_MASK  0x4        /* Multi-DMA transfer done interrupt mask */
+#define          UDMAIN_DONE_MASK  0x8        /* Ultra-DMA in transfer done interrupt mask */
+#define         UDMAOUT_DONE_MASK  0x10       /* Ultra-DMA out transfer done interrupt mask */
+#define       HOST_TERM_XFER_MASK  0x20       /* Host terminate current transfer interrupt mask */
+#define           MULTI_TERM_MASK  0x40       /* Device terminate Multi-DMA transfer interrupt mask */
+#define          UDMAIN_TERM_MASK  0x80       /* Device terminate Ultra-DMA-in transfer interrupt mask */
+#define         UDMAOUT_TERM_MASK  0x100      /* Device terminate Ultra-DMA-out transfer interrupt mask */
+
+/* Bit masks for ATAPI_INT_STATUS */
+
+#define             ATAPI_DEV_INT  0x1        /* Device interrupt status */
+#define              PIO_DONE_INT  0x2        /* PIO transfer done interrupt status */
+#define            MULTI_DONE_INT  0x4        /* Multi-DMA transfer done interrupt status */
+#define           UDMAIN_DONE_INT  0x8        /* Ultra-DMA in transfer done interrupt status */
+#define          UDMAOUT_DONE_INT  0x10       /* Ultra-DMA out transfer done interrupt status */
+#define        HOST_TERM_XFER_INT  0x20       /* Host terminate current transfer interrupt status */
+#define            MULTI_TERM_INT  0x40       /* Device terminate Multi-DMA transfer interrupt status */
+#define           UDMAIN_TERM_INT  0x80       /* Device terminate Ultra-DMA-in transfer interrupt status */
+#define          UDMAOUT_TERM_INT  0x100      /* Device terminate Ultra-DMA-out transfer interrupt status */
+
+/* Bit masks for ATAPI_LINE_STATUS */
+
+#define                ATAPI_INTR  0x1        /* Device interrupt to host line status */
+#define                ATAPI_DASP  0x2        /* Device dasp to host line status */
+#define                ATAPI_CS0N  0x4        /* ATAPI chip select 0 line status */
+#define                ATAPI_CS1N  0x8        /* ATAPI chip select 1 line status */
+#define                ATAPI_ADDR  0x70       /* ATAPI address line status */
+#define              ATAPI_DMAREQ  0x80       /* ATAPI DMA request line status */
+#define             ATAPI_DMAACKN  0x100      /* ATAPI DMA acknowledge line status */
+#define               ATAPI_DIOWN  0x200      /* ATAPI write line status */
+#define               ATAPI_DIORN  0x400      /* ATAPI read line status */
+#define               ATAPI_IORDY  0x800      /* ATAPI IORDY line status */
+
+/* Bit masks for ATAPI_SM_STATE */
+
+#define                PIO_CSTATE  0xf        /* PIO mode state machine current state */
+#define                DMA_CSTATE  0xf0       /* DMA mode state machine current state */
+#define             UDMAIN_CSTATE  0xf00      /* Ultra DMA-In mode state machine current state */
+#define            UDMAOUT_CSTATE  0xf000     /* ATAPI IORDY line status */
+
+/* Bit masks for ATAPI_TERMINATE */
+
+#define           ATAPI_HOST_TERM  0x1        /* Host terminationation */
+
+/* Bit masks for ATAPI_REG_TIM_0 */
+
+#define                    T2_REG  0xff       /* End of cycle time for register access transfers */
+#define                  TEOC_REG  0xff00     /* Selects DIOR/DIOW pulsewidth */
+
+/* Bit masks for ATAPI_PIO_TIM_0 */
+
+#define                    T1_REG  0xf        /* Time from address valid to DIOR/DIOW */
+#define                T2_REG_PIO  0xff0      /* DIOR/DIOW pulsewidth */
+#define                    T4_REG  0xf000     /* DIOW data hold */
+
+/* Bit masks for ATAPI_PIO_TIM_1 */
+
+#define              TEOC_REG_PIO  0xff       /* End of cycle time for PIO access transfers. */
+
+/* Bit masks for ATAPI_MULTI_TIM_0 */
+
+#define                        TD  0xff       /* DIOR/DIOW asserted pulsewidth */
+#define                        TM  0xff00     /* Time from address valid to DIOR/DIOW */
+
+/* Bit masks for ATAPI_MULTI_TIM_1 */
+
+#define                       TKW  0xff       /* Selects DIOW negated pulsewidth */
+#define                       TKR  0xff00     /* Selects DIOR negated pulsewidth */
+
+/* Bit masks for ATAPI_MULTI_TIM_2 */
+
+#define                        TH  0xff       /* Selects DIOW data hold */
+#define                      TEOC  0xff00     /* Selects end of cycle for DMA */
+
+/* Bit masks for ATAPI_ULTRA_TIM_0 */
+
+#define                      TACK  0xff       /* Selects setup and hold times for TACK */
+#define                      TENV  0xff00     /* Selects envelope time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_1 */
+
+#define                      TDVS  0xff       /* Selects data valid setup time */
+#define                 TCYC_TDVS  0xff00     /* Selects cycle time - TDVS time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_2 */
+
+#define                       TSS  0xff       /* Selects time from STROBE edge to negation of DMARQ or assertion of STOP */
+#define                      TMLI  0xff00     /* Selects interlock time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_3 */
+
+#define                      TZAH  0xff       /* Selects minimum delay required for output */
+#define               READY_PAUSE  0xff00     /* Selects ready to pause */
+
+/* Bit masks for USB_FADDR */
+
+#define          FUNCTION_ADDRESS  0x7f       /* Function address */
+
+/* Bit masks for USB_POWER */
+
+#define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
+#define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
+#define               RESUME_MODE  0x4        /* DMA Mode */
+#define                     RESET  0x8        /* Reset indicator */
+#define                   HS_MODE  0x10       /* High Speed mode indicator */
+#define                 HS_ENABLE  0x20       /* high Speed Enable */
+#define                 SOFT_CONN  0x40       /* Soft connect */
+#define                ISO_UPDATE  0x80       /* Isochronous update */
+
+/* Bit masks for USB_INTRTX */
+
+#define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
+#define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
+#define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
+#define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
+#define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
+#define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
+#define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
+#define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
+
+/* Bit masks for USB_INTRRX */
+
+#define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
+#define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
+#define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
+#define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
+#define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
+#define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
+#define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
+
+/* Bit masks for USB_INTRTXE */
+
+#define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
+#define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
+#define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
+#define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
+#define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
+#define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
+#define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
+#define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
+
+/* Bit masks for USB_INTRRXE */
+
+#define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
+#define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
+#define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
+#define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
+#define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
+#define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
+#define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
+
+/* Bit masks for USB_INTRUSB */
+
+#define                 SUSPEND_B  0x1        /* Suspend indicator */
+#define                  RESUME_B  0x2        /* Resume indicator */
+#define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
+#define                     SOF_B  0x8        /* Start of frame */
+#define                    CONN_B  0x10       /* Connection indicator */
+#define                  DISCON_B  0x20       /* Disconnect indicator */
+#define             SESSION_REQ_B  0x40       /* Session Request */
+#define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
+
+/* Bit masks for USB_INTRUSBE */
+
+#define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
+#define                 RESUME_BE  0x2        /* Resume indicator int enable */
+#define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
+#define                    SOF_BE  0x8        /* Start of frame int enable */
+#define                   CONN_BE  0x10       /* Connection indicator int enable */
+#define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
+#define            SESSION_REQ_BE  0x40       /* Session Request int enable */
+#define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
+
+/* Bit masks for USB_FRAME */
+
+#define              FRAME_NUMBER  0x7ff      /* Frame number */
+
+/* Bit masks for USB_INDEX */
+
+#define         SELECTED_ENDPOINT  0xf        /* selected endpoint */
+
+/* Bit masks for USB_GLOBAL_CTL */
+
+#define                GLOBAL_ENA  0x1        /* enables USB module */
+#define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
+#define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
+#define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
+#define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
+#define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
+#define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
+#define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
+#define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
+#define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
+#define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
+#define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
+#define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
+#define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
+#define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
+
+/* Bit masks for USB_OTG_DEV_CTL */
+
+#define                   SESSION  0x1        /* session indicator */
+#define                  HOST_REQ  0x2        /* Host negotiation request */
+#define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
+#define                     VBUS0  0x8        /* Vbus level indicator[0] */
+#define                     VBUS1  0x10       /* Vbus level indicator[1] */
+#define                     LSDEV  0x20       /* Low-speed indicator */
+#define                     FSDEV  0x40       /* Full or High-speed indicator */
+#define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
+
+/* Bit masks for USB_OTG_VBUS_IRQ */
+
+#define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
+#define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
+#define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
+#define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
+#define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
+#define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
+
+/* Bit masks for USB_OTG_VBUS_MASK */
+
+#define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
+#define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
+#define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
+#define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
+#define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
+#define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
+
+/* Bit masks for USB_CSR0 */
+
+#define                  RXPKTRDY  0x1        /* data packet receive indicator */
+#define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
+#define                STALL_SENT  0x4        /* STALL handshake sent */
+#define                   DATAEND  0x8        /* Data end indicator */
+#define                  SETUPEND  0x10       /* Setup end */
+#define                 SENDSTALL  0x20       /* Send STALL handshake */
+#define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
+#define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
+#define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
+#define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
+#define                SETUPPKT_H  0x8        /* send Setup token host mode */
+#define                   ERROR_H  0x10       /* timeout error indicator host mode */
+#define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
+#define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
+#define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
+
+/* Bit masks for USB_COUNT0 */
+
+#define              EP0_RX_COUNT  0x7f       /* number of received bytes in EP0 FIFO */
+
+/* Bit masks for USB_NAKLIMIT0 */
+
+#define             EP0_NAK_LIMIT  0x1f       /* number of frames/micro frames after which EP0 timeouts */
+
+/* Bit masks for USB_TX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_T  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_RX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_R  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_TXCSR */
+
+#define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
+#define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
+#define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
+#define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
+#define              STALL_SEND_T  0x10       /* issue a Stall handshake */
+#define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
+#define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
+#define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
+#define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
+#define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
+#define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
+#define                     ISO_T  0x4000     /* enable Isochronous transfers */
+#define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
+#define                  ERROR_TH  0x4        /* error condition host mode */
+#define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
+#define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
+
+/* Bit masks for USB_TXCOUNT */
+
+#define                  TX_COUNT  0x1fff     /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* Bit masks for USB_RXCSR */
+
+#define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
+#define               FIFO_FULL_R  0x2        /* FIFO not empty */
+#define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
+#define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
+#define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
+#define              STALL_SEND_R  0x20       /* issue a Stall handshake */
+#define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
+#define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
+#define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
+#define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
+#define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
+#define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
+#define                     ISO_R  0x4000     /* enable Isochronous transfers */
+#define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
+#define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
+#define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
+#define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
+#define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
+#define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
+#define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
+
+/* Bit masks for USB_RXCOUNT */
+
+#define                  RX_COUNT  0x1fff     /* Number of received bytes in the packet in the Rx FIFO */
+
+/* Bit masks for USB_TXTYPE */
+
+#define            TARGET_EP_NO_T  0xf        /* EP number */
+#define                PROTOCOL_T  0xc        /* transfer type */
+
+/* Bit masks for USB_TXINTERVAL */
+
+#define          TX_POLL_INTERVAL  0xff       /* polling interval for selected Tx EP */
+
+/* Bit masks for USB_RXTYPE */
+
+#define            TARGET_EP_NO_R  0xf        /* EP number */
+#define                PROTOCOL_R  0xc        /* transfer type */
+
+/* Bit masks for USB_RXINTERVAL */
+
+#define          RX_POLL_INTERVAL  0xff       /* polling interval for selected Rx EP */
+
+/* Bit masks for USB_DMA_INTERRUPT */
+
+#define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
+#define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
+#define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
+#define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
+#define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
+#define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
+#define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
+#define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
+
+/* Bit masks for USB_DMAxCONTROL */
+
+#define                   DMA_ENA  0x1        /* DMA enable */
+#define                 DIRECTION  0x2        /* direction of DMA transfer */
+#define                      MODE  0x4        /* DMA Bus error */
+#define                   INT_ENA  0x8        /* Interrupt enable */
+#define                     EPNUM  0xf0       /* EP number */
+#define                  BUSERROR  0x100      /* DMA Bus error */
+
+/* Bit masks for USB_DMAxADDRHIGH */
+
+#define             DMA_ADDR_HIGH  0xffff     /* Upper 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxADDRLOW */
+
+#define              DMA_ADDR_LOW  0xffff     /* Lower 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTHIGH */
+
+#define            DMA_COUNT_HIGH  0xffff     /* Upper 16-bits of byte count of DMA transfer for DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTLOW */
+
+#define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
+
+
+/* ******************************************* */
+/*     MULTI BIT MACRO ENUMERATIONS            */
+/* ******************************************* */
+
+
+#endif /* _DEF_BF542_H */
diff --git a/include/asm-blackfin/mach-bf548/defBF544.h b/include/asm-blackfin/mach-bf548/defBF544.h
new file mode 100644
index 0000000..dd955dc
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/defBF544.h
@@ -0,0 +1,706 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/defBF544.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF544_H
+#define _DEF_BF544_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF544 */
+
+/* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
+#include "defBF54x_base.h"
+
+/* The following are the #defines needed by ADSP-BF544 that are not in the common header */
+
+/* Timer Registers */
+
+#define                    TIMER8_CONFIG  0xffc00600   /* Timer 8 Configuration Register */
+#define                   TIMER8_COUNTER  0xffc00604   /* Timer 8 Counter Register */
+#define                    TIMER8_PERIOD  0xffc00608   /* Timer 8 Period Register */
+#define                     TIMER8_WIDTH  0xffc0060c   /* Timer 8 Width Register */
+#define                    TIMER9_CONFIG  0xffc00610   /* Timer 9 Configuration Register */
+#define                   TIMER9_COUNTER  0xffc00614   /* Timer 9 Counter Register */
+#define                    TIMER9_PERIOD  0xffc00618   /* Timer 9 Period Register */
+#define                     TIMER9_WIDTH  0xffc0061c   /* Timer 9 Width Register */
+#define                   TIMER10_CONFIG  0xffc00620   /* Timer 10 Configuration Register */
+#define                  TIMER10_COUNTER  0xffc00624   /* Timer 10 Counter Register */
+#define                   TIMER10_PERIOD  0xffc00628   /* Timer 10 Period Register */
+#define                    TIMER10_WIDTH  0xffc0062c   /* Timer 10 Width Register */
+
+/* Timer Group of 3 Registers */
+
+#define                    TIMER_ENABLE1  0xffc00640   /* Timer Group of 3 Enable Register */
+#define                   TIMER_DISABLE1  0xffc00644   /* Timer Group of 3 Disable Register */
+#define                    TIMER_STATUS1  0xffc00648   /* Timer Group of 3 Status Register */
+
+/* EPPI0 Registers */
+
+#define                     EPPI0_STATUS  0xffc01000   /* EPPI0 Status Register */
+#define                     EPPI0_HCOUNT  0xffc01004   /* EPPI0 Horizontal Transfer Count Register */
+#define                     EPPI0_HDELAY  0xffc01008   /* EPPI0 Horizontal Delay Count Register */
+#define                     EPPI0_VCOUNT  0xffc0100c   /* EPPI0 Vertical Transfer Count Register */
+#define                     EPPI0_VDELAY  0xffc01010   /* EPPI0 Vertical Delay Count Register */
+#define                      EPPI0_FRAME  0xffc01014   /* EPPI0 Lines per Frame Register */
+#define                       EPPI0_LINE  0xffc01018   /* EPPI0 Samples per Line Register */
+#define                     EPPI0_CLKDIV  0xffc0101c   /* EPPI0 Clock Divide Register */
+#define                    EPPI0_CONTROL  0xffc01020   /* EPPI0 Control Register */
+#define                   EPPI0_FS1W_HBL  0xffc01024   /* EPPI0 FS1 Width Register / EPPI0 Horizontal Blanking Samples Per Line Register */
+#define                  EPPI0_FS1P_AVPL  0xffc01028   /* EPPI0 FS1 Period Register / EPPI0 Active Video Samples Per Line Register */
+#define                   EPPI0_FS2W_LVB  0xffc0102c   /* EPPI0 FS2 Width Register / EPPI0 Lines of Vertical Blanking Register */
+#define                  EPPI0_FS2P_LAVF  0xffc01030   /* EPPI0 FS2 Period Register/ EPPI0 Lines of Active Video Per Field Register */
+#define                       EPPI0_CLIP  0xffc01034   /* EPPI0 Clipping Register */
+
+/* Two Wire Interface Registers (TWI1) */
+
+#define                      TWI1_CLKDIV  0xffc02200   /* Clock Divider Register */
+#define                     TWI1_CONTROL  0xffc02204   /* TWI Control Register */
+#define                  TWI1_SLAVE_CTRL  0xffc02208   /* TWI Slave Mode Control Register */
+#define                  TWI1_SLAVE_STAT  0xffc0220c   /* TWI Slave Mode Status Register */
+#define                  TWI1_SLAVE_ADDR  0xffc02210   /* TWI Slave Mode Address Register */
+#define                 TWI1_MASTER_CTRL  0xffc02214   /* TWI Master Mode Control Register */
+#define                 TWI1_MASTER_STAT  0xffc02218   /* TWI Master Mode Status Register */
+#define                 TWI1_MASTER_ADDR  0xffc0221c   /* TWI Master Mode Address Register */
+#define                    TWI1_INT_STAT  0xffc02220   /* TWI Interrupt Status Register */
+#define                    TWI1_INT_MASK  0xffc02224   /* TWI Interrupt Mask Register */
+#define                   TWI1_FIFO_CTRL  0xffc02228   /* TWI FIFO Control Register */
+#define                   TWI1_FIFO_STAT  0xffc0222c   /* TWI FIFO Status Register */
+#define                   TWI1_XMT_DATA8  0xffc02280   /* TWI FIFO Transmit Data Single Byte Register */
+#define                  TWI1_XMT_DATA16  0xffc02284   /* TWI FIFO Transmit Data Double Byte Register */
+#define                   TWI1_RCV_DATA8  0xffc02288   /* TWI FIFO Receive Data Single Byte Register */
+#define                  TWI1_RCV_DATA16  0xffc0228c   /* TWI FIFO Receive Data Double Byte Register */
+
+/* CAN Controller 1 Config 1 Registers */
+
+#define                         CAN1_MC1  0xffc03200   /* CAN Controller 1 Mailbox Configuration Register 1 */
+#define                         CAN1_MD1  0xffc03204   /* CAN Controller 1 Mailbox Direction Register 1 */
+#define                        CAN1_TRS1  0xffc03208   /* CAN Controller 1 Transmit Request Set Register 1 */
+#define                        CAN1_TRR1  0xffc0320c   /* CAN Controller 1 Transmit Request Reset Register 1 */
+#define                         CAN1_TA1  0xffc03210   /* CAN Controller 1 Transmit Acknowledge Register 1 */
+#define                         CAN1_AA1  0xffc03214   /* CAN Controller 1 Abort Acknowledge Register 1 */
+#define                        CAN1_RMP1  0xffc03218   /* CAN Controller 1 Receive Message Pending Register 1 */
+#define                        CAN1_RML1  0xffc0321c   /* CAN Controller 1 Receive Message Lost Register 1 */
+#define                      CAN1_MBTIF1  0xffc03220   /* CAN Controller 1 Mailbox Transmit Interrupt Flag Register 1 */
+#define                      CAN1_MBRIF1  0xffc03224   /* CAN Controller 1 Mailbox Receive Interrupt Flag Register 1 */
+#define                       CAN1_MBIM1  0xffc03228   /* CAN Controller 1 Mailbox Interrupt Mask Register 1 */
+#define                        CAN1_RFH1  0xffc0322c   /* CAN Controller 1 Remote Frame Handling Enable Register 1 */
+#define                       CAN1_OPSS1  0xffc03230   /* CAN Controller 1 Overwrite Protection Single Shot Transmit Register 1 */
+
+/* CAN Controller 1 Config 2 Registers */
+
+#define                         CAN1_MC2  0xffc03240   /* CAN Controller 1 Mailbox Configuration Register 2 */
+#define                         CAN1_MD2  0xffc03244   /* CAN Controller 1 Mailbox Direction Register 2 */
+#define                        CAN1_TRS2  0xffc03248   /* CAN Controller 1 Transmit Request Set Register 2 */
+#define                        CAN1_TRR2  0xffc0324c   /* CAN Controller 1 Transmit Request Reset Register 2 */
+#define                         CAN1_TA2  0xffc03250   /* CAN Controller 1 Transmit Acknowledge Register 2 */
+#define                         CAN1_AA2  0xffc03254   /* CAN Controller 1 Abort Acknowledge Register 2 */
+#define                        CAN1_RMP2  0xffc03258   /* CAN Controller 1 Receive Message Pending Register 2 */
+#define                        CAN1_RML2  0xffc0325c   /* CAN Controller 1 Receive Message Lost Register 2 */
+#define                      CAN1_MBTIF2  0xffc03260   /* CAN Controller 1 Mailbox Transmit Interrupt Flag Register 2 */
+#define                      CAN1_MBRIF2  0xffc03264   /* CAN Controller 1 Mailbox Receive Interrupt Flag Register 2 */
+#define                       CAN1_MBIM2  0xffc03268   /* CAN Controller 1 Mailbox Interrupt Mask Register 2 */
+#define                        CAN1_RFH2  0xffc0326c   /* CAN Controller 1 Remote Frame Handling Enable Register 2 */
+#define                       CAN1_OPSS2  0xffc03270   /* CAN Controller 1 Overwrite Protection Single Shot Transmit Register 2 */
+
+/* CAN Controller 1 Clock/Interrupt/Counter Registers */
+
+#define                       CAN1_CLOCK  0xffc03280   /* CAN Controller 1 Clock Register */
+#define                      CAN1_TIMING  0xffc03284   /* CAN Controller 1 Timing Register */
+#define                       CAN1_DEBUG  0xffc03288   /* CAN Controller 1 Debug Register */
+#define                      CAN1_STATUS  0xffc0328c   /* CAN Controller 1 Global Status Register */
+#define                         CAN1_CEC  0xffc03290   /* CAN Controller 1 Error Counter Register */
+#define                         CAN1_GIS  0xffc03294   /* CAN Controller 1 Global Interrupt Status Register */
+#define                         CAN1_GIM  0xffc03298   /* CAN Controller 1 Global Interrupt Mask Register */
+#define                         CAN1_GIF  0xffc0329c   /* CAN Controller 1 Global Interrupt Flag Register */
+#define                     CAN1_CONTROL  0xffc032a0   /* CAN Controller 1 Master Control Register */
+#define                        CAN1_INTR  0xffc032a4   /* CAN Controller 1 Interrupt Pending Register */
+#define                        CAN1_MBTD  0xffc032ac   /* CAN Controller 1 Mailbox Temporary Disable Register */
+#define                         CAN1_EWR  0xffc032b0   /* CAN Controller 1 Programmable Warning Level Register */
+#define                         CAN1_ESR  0xffc032b4   /* CAN Controller 1 Error Status Register */
+#define                       CAN1_UCCNT  0xffc032c4   /* CAN Controller 1 Universal Counter Register */
+#define                        CAN1_UCRC  0xffc032c8   /* CAN Controller 1 Universal Counter Force Reload Register */
+#define                       CAN1_UCCNF  0xffc032cc   /* CAN Controller 1 Universal Counter Configuration Register */
+
+/* CAN Controller 1 Mailbox Acceptance Registers */
+
+#define                       CAN1_AM00L  0xffc03300   /* CAN Controller 1 Mailbox 0 Acceptance Mask High Register */
+#define                       CAN1_AM00H  0xffc03304   /* CAN Controller 1 Mailbox 0 Acceptance Mask Low Register */
+#define                       CAN1_AM01L  0xffc03308   /* CAN Controller 1 Mailbox 1 Acceptance Mask High Register */
+#define                       CAN1_AM01H  0xffc0330c   /* CAN Controller 1 Mailbox 1 Acceptance Mask Low Register */
+#define                       CAN1_AM02L  0xffc03310   /* CAN Controller 1 Mailbox 2 Acceptance Mask High Register */
+#define                       CAN1_AM02H  0xffc03314   /* CAN Controller 1 Mailbox 2 Acceptance Mask Low Register */
+#define                       CAN1_AM03L  0xffc03318   /* CAN Controller 1 Mailbox 3 Acceptance Mask High Register */
+#define                       CAN1_AM03H  0xffc0331c   /* CAN Controller 1 Mailbox 3 Acceptance Mask Low Register */
+#define                       CAN1_AM04L  0xffc03320   /* CAN Controller 1 Mailbox 4 Acceptance Mask High Register */
+#define                       CAN1_AM04H  0xffc03324   /* CAN Controller 1 Mailbox 4 Acceptance Mask Low Register */
+#define                       CAN1_AM05L  0xffc03328   /* CAN Controller 1 Mailbox 5 Acceptance Mask High Register */
+#define                       CAN1_AM05H  0xffc0332c   /* CAN Controller 1 Mailbox 5 Acceptance Mask Low Register */
+#define                       CAN1_AM06L  0xffc03330   /* CAN Controller 1 Mailbox 6 Acceptance Mask High Register */
+#define                       CAN1_AM06H  0xffc03334   /* CAN Controller 1 Mailbox 6 Acceptance Mask Low Register */
+#define                       CAN1_AM07L  0xffc03338   /* CAN Controller 1 Mailbox 7 Acceptance Mask High Register */
+#define                       CAN1_AM07H  0xffc0333c   /* CAN Controller 1 Mailbox 7 Acceptance Mask Low Register */
+#define                       CAN1_AM08L  0xffc03340   /* CAN Controller 1 Mailbox 8 Acceptance Mask High Register */
+#define                       CAN1_AM08H  0xffc03344   /* CAN Controller 1 Mailbox 8 Acceptance Mask Low Register */
+#define                       CAN1_AM09L  0xffc03348   /* CAN Controller 1 Mailbox 9 Acceptance Mask High Register */
+#define                       CAN1_AM09H  0xffc0334c   /* CAN Controller 1 Mailbox 9 Acceptance Mask Low Register */
+#define                       CAN1_AM10L  0xffc03350   /* CAN Controller 1 Mailbox 10 Acceptance Mask High Register */
+#define                       CAN1_AM10H  0xffc03354   /* CAN Controller 1 Mailbox 10 Acceptance Mask Low Register */
+#define                       CAN1_AM11L  0xffc03358   /* CAN Controller 1 Mailbox 11 Acceptance Mask High Register */
+#define                       CAN1_AM11H  0xffc0335c   /* CAN Controller 1 Mailbox 11 Acceptance Mask Low Register */
+#define                       CAN1_AM12L  0xffc03360   /* CAN Controller 1 Mailbox 12 Acceptance Mask High Register */
+#define                       CAN1_AM12H  0xffc03364   /* CAN Controller 1 Mailbox 12 Acceptance Mask Low Register */
+#define                       CAN1_AM13L  0xffc03368   /* CAN Controller 1 Mailbox 13 Acceptance Mask High Register */
+#define                       CAN1_AM13H  0xffc0336c   /* CAN Controller 1 Mailbox 13 Acceptance Mask Low Register */
+#define                       CAN1_AM14L  0xffc03370   /* CAN Controller 1 Mailbox 14 Acceptance Mask High Register */
+#define                       CAN1_AM14H  0xffc03374   /* CAN Controller 1 Mailbox 14 Acceptance Mask Low Register */
+#define                       CAN1_AM15L  0xffc03378   /* CAN Controller 1 Mailbox 15 Acceptance Mask High Register */
+#define                       CAN1_AM15H  0xffc0337c   /* CAN Controller 1 Mailbox 15 Acceptance Mask Low Register */
+
+/* CAN Controller 1 Mailbox Acceptance Registers */
+
+#define                       CAN1_AM16L  0xffc03380   /* CAN Controller 1 Mailbox 16 Acceptance Mask High Register */
+#define                       CAN1_AM16H  0xffc03384   /* CAN Controller 1 Mailbox 16 Acceptance Mask Low Register */
+#define                       CAN1_AM17L  0xffc03388   /* CAN Controller 1 Mailbox 17 Acceptance Mask High Register */
+#define                       CAN1_AM17H  0xffc0338c   /* CAN Controller 1 Mailbox 17 Acceptance Mask Low Register */
+#define                       CAN1_AM18L  0xffc03390   /* CAN Controller 1 Mailbox 18 Acceptance Mask High Register */
+#define                       CAN1_AM18H  0xffc03394   /* CAN Controller 1 Mailbox 18 Acceptance Mask Low Register */
+#define                       CAN1_AM19L  0xffc03398   /* CAN Controller 1 Mailbox 19 Acceptance Mask High Register */
+#define                       CAN1_AM19H  0xffc0339c   /* CAN Controller 1 Mailbox 19 Acceptance Mask Low Register */
+#define                       CAN1_AM20L  0xffc033a0   /* CAN Controller 1 Mailbox 20 Acceptance Mask High Register */
+#define                       CAN1_AM20H  0xffc033a4   /* CAN Controller 1 Mailbox 20 Acceptance Mask Low Register */
+#define                       CAN1_AM21L  0xffc033a8   /* CAN Controller 1 Mailbox 21 Acceptance Mask High Register */
+#define                       CAN1_AM21H  0xffc033ac   /* CAN Controller 1 Mailbox 21 Acceptance Mask Low Register */
+#define                       CAN1_AM22L  0xffc033b0   /* CAN Controller 1 Mailbox 22 Acceptance Mask High Register */
+#define                       CAN1_AM22H  0xffc033b4   /* CAN Controller 1 Mailbox 22 Acceptance Mask Low Register */
+#define                       CAN1_AM23L  0xffc033b8   /* CAN Controller 1 Mailbox 23 Acceptance Mask High Register */
+#define                       CAN1_AM23H  0xffc033bc   /* CAN Controller 1 Mailbox 23 Acceptance Mask Low Register */
+#define                       CAN1_AM24L  0xffc033c0   /* CAN Controller 1 Mailbox 24 Acceptance Mask High Register */
+#define                       CAN1_AM24H  0xffc033c4   /* CAN Controller 1 Mailbox 24 Acceptance Mask Low Register */
+#define                       CAN1_AM25L  0xffc033c8   /* CAN Controller 1 Mailbox 25 Acceptance Mask High Register */
+#define                       CAN1_AM25H  0xffc033cc   /* CAN Controller 1 Mailbox 25 Acceptance Mask Low Register */
+#define                       CAN1_AM26L  0xffc033d0   /* CAN Controller 1 Mailbox 26 Acceptance Mask High Register */
+#define                       CAN1_AM26H  0xffc033d4   /* CAN Controller 1 Mailbox 26 Acceptance Mask Low Register */
+#define                       CAN1_AM27L  0xffc033d8   /* CAN Controller 1 Mailbox 27 Acceptance Mask High Register */
+#define                       CAN1_AM27H  0xffc033dc   /* CAN Controller 1 Mailbox 27 Acceptance Mask Low Register */
+#define                       CAN1_AM28L  0xffc033e0   /* CAN Controller 1 Mailbox 28 Acceptance Mask High Register */
+#define                       CAN1_AM28H  0xffc033e4   /* CAN Controller 1 Mailbox 28 Acceptance Mask Low Register */
+#define                       CAN1_AM29L  0xffc033e8   /* CAN Controller 1 Mailbox 29 Acceptance Mask High Register */
+#define                       CAN1_AM29H  0xffc033ec   /* CAN Controller 1 Mailbox 29 Acceptance Mask Low Register */
+#define                       CAN1_AM30L  0xffc033f0   /* CAN Controller 1 Mailbox 30 Acceptance Mask High Register */
+#define                       CAN1_AM30H  0xffc033f4   /* CAN Controller 1 Mailbox 30 Acceptance Mask Low Register */
+#define                       CAN1_AM31L  0xffc033f8   /* CAN Controller 1 Mailbox 31 Acceptance Mask High Register */
+#define                       CAN1_AM31H  0xffc033fc   /* CAN Controller 1 Mailbox 31 Acceptance Mask Low Register */
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define                  CAN1_MB00_DATA0  0xffc03400   /* CAN Controller 1 Mailbox 0 Data 0 Register */
+#define                  CAN1_MB00_DATA1  0xffc03404   /* CAN Controller 1 Mailbox 0 Data 1 Register */
+#define                  CAN1_MB00_DATA2  0xffc03408   /* CAN Controller 1 Mailbox 0 Data 2 Register */
+#define                  CAN1_MB00_DATA3  0xffc0340c   /* CAN Controller 1 Mailbox 0 Data 3 Register */
+#define                 CAN1_MB00_LENGTH  0xffc03410   /* CAN Controller 1 Mailbox 0 Length Register */
+#define              CAN1_MB00_TIMESTAMP  0xffc03414   /* CAN Controller 1 Mailbox 0 Timestamp Register */
+#define                    CAN1_MB00_ID0  0xffc03418   /* CAN Controller 1 Mailbox 0 ID0 Register */
+#define                    CAN1_MB00_ID1  0xffc0341c   /* CAN Controller 1 Mailbox 0 ID1 Register */
+#define                  CAN1_MB01_DATA0  0xffc03420   /* CAN Controller 1 Mailbox 1 Data 0 Register */
+#define                  CAN1_MB01_DATA1  0xffc03424   /* CAN Controller 1 Mailbox 1 Data 1 Register */
+#define                  CAN1_MB01_DATA2  0xffc03428   /* CAN Controller 1 Mailbox 1 Data 2 Register */
+#define                  CAN1_MB01_DATA3  0xffc0342c   /* CAN Controller 1 Mailbox 1 Data 3 Register */
+#define                 CAN1_MB01_LENGTH  0xffc03430   /* CAN Controller 1 Mailbox 1 Length Register */
+#define              CAN1_MB01_TIMESTAMP  0xffc03434   /* CAN Controller 1 Mailbox 1 Timestamp Register */
+#define                    CAN1_MB01_ID0  0xffc03438   /* CAN Controller 1 Mailbox 1 ID0 Register */
+#define                    CAN1_MB01_ID1  0xffc0343c   /* CAN Controller 1 Mailbox 1 ID1 Register */
+#define                  CAN1_MB02_DATA0  0xffc03440   /* CAN Controller 1 Mailbox 2 Data 0 Register */
+#define                  CAN1_MB02_DATA1  0xffc03444   /* CAN Controller 1 Mailbox 2 Data 1 Register */
+#define                  CAN1_MB02_DATA2  0xffc03448   /* CAN Controller 1 Mailbox 2 Data 2 Register */
+#define                  CAN1_MB02_DATA3  0xffc0344c   /* CAN Controller 1 Mailbox 2 Data 3 Register */
+#define                 CAN1_MB02_LENGTH  0xffc03450   /* CAN Controller 1 Mailbox 2 Length Register */
+#define              CAN1_MB02_TIMESTAMP  0xffc03454   /* CAN Controller 1 Mailbox 2 Timestamp Register */
+#define                    CAN1_MB02_ID0  0xffc03458   /* CAN Controller 1 Mailbox 2 ID0 Register */
+#define                    CAN1_MB02_ID1  0xffc0345c   /* CAN Controller 1 Mailbox 2 ID1 Register */
+#define                  CAN1_MB03_DATA0  0xffc03460   /* CAN Controller 1 Mailbox 3 Data 0 Register */
+#define                  CAN1_MB03_DATA1  0xffc03464   /* CAN Controller 1 Mailbox 3 Data 1 Register */
+#define                  CAN1_MB03_DATA2  0xffc03468   /* CAN Controller 1 Mailbox 3 Data 2 Register */
+#define                  CAN1_MB03_DATA3  0xffc0346c   /* CAN Controller 1 Mailbox 3 Data 3 Register */
+#define                 CAN1_MB03_LENGTH  0xffc03470   /* CAN Controller 1 Mailbox 3 Length Register */
+#define              CAN1_MB03_TIMESTAMP  0xffc03474   /* CAN Controller 1 Mailbox 3 Timestamp Register */
+#define                    CAN1_MB03_ID0  0xffc03478   /* CAN Controller 1 Mailbox 3 ID0 Register */
+#define                    CAN1_MB03_ID1  0xffc0347c   /* CAN Controller 1 Mailbox 3 ID1 Register */
+#define                  CAN1_MB04_DATA0  0xffc03480   /* CAN Controller 1 Mailbox 4 Data 0 Register */
+#define                  CAN1_MB04_DATA1  0xffc03484   /* CAN Controller 1 Mailbox 4 Data 1 Register */
+#define                  CAN1_MB04_DATA2  0xffc03488   /* CAN Controller 1 Mailbox 4 Data 2 Register */
+#define                  CAN1_MB04_DATA3  0xffc0348c   /* CAN Controller 1 Mailbox 4 Data 3 Register */
+#define                 CAN1_MB04_LENGTH  0xffc03490   /* CAN Controller 1 Mailbox 4 Length Register */
+#define              CAN1_MB04_TIMESTAMP  0xffc03494   /* CAN Controller 1 Mailbox 4 Timestamp Register */
+#define                    CAN1_MB04_ID0  0xffc03498   /* CAN Controller 1 Mailbox 4 ID0 Register */
+#define                    CAN1_MB04_ID1  0xffc0349c   /* CAN Controller 1 Mailbox 4 ID1 Register */
+#define                  CAN1_MB05_DATA0  0xffc034a0   /* CAN Controller 1 Mailbox 5 Data 0 Register */
+#define                  CAN1_MB05_DATA1  0xffc034a4   /* CAN Controller 1 Mailbox 5 Data 1 Register */
+#define                  CAN1_MB05_DATA2  0xffc034a8   /* CAN Controller 1 Mailbox 5 Data 2 Register */
+#define                  CAN1_MB05_DATA3  0xffc034ac   /* CAN Controller 1 Mailbox 5 Data 3 Register */
+#define                 CAN1_MB05_LENGTH  0xffc034b0   /* CAN Controller 1 Mailbox 5 Length Register */
+#define              CAN1_MB05_TIMESTAMP  0xffc034b4   /* CAN Controller 1 Mailbox 5 Timestamp Register */
+#define                    CAN1_MB05_ID0  0xffc034b8   /* CAN Controller 1 Mailbox 5 ID0 Register */
+#define                    CAN1_MB05_ID1  0xffc034bc   /* CAN Controller 1 Mailbox 5 ID1 Register */
+#define                  CAN1_MB06_DATA0  0xffc034c0   /* CAN Controller 1 Mailbox 6 Data 0 Register */
+#define                  CAN1_MB06_DATA1  0xffc034c4   /* CAN Controller 1 Mailbox 6 Data 1 Register */
+#define                  CAN1_MB06_DATA2  0xffc034c8   /* CAN Controller 1 Mailbox 6 Data 2 Register */
+#define                  CAN1_MB06_DATA3  0xffc034cc   /* CAN Controller 1 Mailbox 6 Data 3 Register */
+#define                 CAN1_MB06_LENGTH  0xffc034d0   /* CAN Controller 1 Mailbox 6 Length Register */
+#define              CAN1_MB06_TIMESTAMP  0xffc034d4   /* CAN Controller 1 Mailbox 6 Timestamp Register */
+#define                    CAN1_MB06_ID0  0xffc034d8   /* CAN Controller 1 Mailbox 6 ID0 Register */
+#define                    CAN1_MB06_ID1  0xffc034dc   /* CAN Controller 1 Mailbox 6 ID1 Register */
+#define                  CAN1_MB07_DATA0  0xffc034e0   /* CAN Controller 1 Mailbox 7 Data 0 Register */
+#define                  CAN1_MB07_DATA1  0xffc034e4   /* CAN Controller 1 Mailbox 7 Data 1 Register */
+#define                  CAN1_MB07_DATA2  0xffc034e8   /* CAN Controller 1 Mailbox 7 Data 2 Register */
+#define                  CAN1_MB07_DATA3  0xffc034ec   /* CAN Controller 1 Mailbox 7 Data 3 Register */
+#define                 CAN1_MB07_LENGTH  0xffc034f0   /* CAN Controller 1 Mailbox 7 Length Register */
+#define              CAN1_MB07_TIMESTAMP  0xffc034f4   /* CAN Controller 1 Mailbox 7 Timestamp Register */
+#define                    CAN1_MB07_ID0  0xffc034f8   /* CAN Controller 1 Mailbox 7 ID0 Register */
+#define                    CAN1_MB07_ID1  0xffc034fc   /* CAN Controller 1 Mailbox 7 ID1 Register */
+#define                  CAN1_MB08_DATA0  0xffc03500   /* CAN Controller 1 Mailbox 8 Data 0 Register */
+#define                  CAN1_MB08_DATA1  0xffc03504   /* CAN Controller 1 Mailbox 8 Data 1 Register */
+#define                  CAN1_MB08_DATA2  0xffc03508   /* CAN Controller 1 Mailbox 8 Data 2 Register */
+#define                  CAN1_MB08_DATA3  0xffc0350c   /* CAN Controller 1 Mailbox 8 Data 3 Register */
+#define                 CAN1_MB08_LENGTH  0xffc03510   /* CAN Controller 1 Mailbox 8 Length Register */
+#define              CAN1_MB08_TIMESTAMP  0xffc03514   /* CAN Controller 1 Mailbox 8 Timestamp Register */
+#define                    CAN1_MB08_ID0  0xffc03518   /* CAN Controller 1 Mailbox 8 ID0 Register */
+#define                    CAN1_MB08_ID1  0xffc0351c   /* CAN Controller 1 Mailbox 8 ID1 Register */
+#define                  CAN1_MB09_DATA0  0xffc03520   /* CAN Controller 1 Mailbox 9 Data 0 Register */
+#define                  CAN1_MB09_DATA1  0xffc03524   /* CAN Controller 1 Mailbox 9 Data 1 Register */
+#define                  CAN1_MB09_DATA2  0xffc03528   /* CAN Controller 1 Mailbox 9 Data 2 Register */
+#define                  CAN1_MB09_DATA3  0xffc0352c   /* CAN Controller 1 Mailbox 9 Data 3 Register */
+#define                 CAN1_MB09_LENGTH  0xffc03530   /* CAN Controller 1 Mailbox 9 Length Register */
+#define              CAN1_MB09_TIMESTAMP  0xffc03534   /* CAN Controller 1 Mailbox 9 Timestamp Register */
+#define                    CAN1_MB09_ID0  0xffc03538   /* CAN Controller 1 Mailbox 9 ID0 Register */
+#define                    CAN1_MB09_ID1  0xffc0353c   /* CAN Controller 1 Mailbox 9 ID1 Register */
+#define                  CAN1_MB10_DATA0  0xffc03540   /* CAN Controller 1 Mailbox 10 Data 0 Register */
+#define                  CAN1_MB10_DATA1  0xffc03544   /* CAN Controller 1 Mailbox 10 Data 1 Register */
+#define                  CAN1_MB10_DATA2  0xffc03548   /* CAN Controller 1 Mailbox 10 Data 2 Register */
+#define                  CAN1_MB10_DATA3  0xffc0354c   /* CAN Controller 1 Mailbox 10 Data 3 Register */
+#define                 CAN1_MB10_LENGTH  0xffc03550   /* CAN Controller 1 Mailbox 10 Length Register */
+#define              CAN1_MB10_TIMESTAMP  0xffc03554   /* CAN Controller 1 Mailbox 10 Timestamp Register */
+#define                    CAN1_MB10_ID0  0xffc03558   /* CAN Controller 1 Mailbox 10 ID0 Register */
+#define                    CAN1_MB10_ID1  0xffc0355c   /* CAN Controller 1 Mailbox 10 ID1 Register */
+#define                  CAN1_MB11_DATA0  0xffc03560   /* CAN Controller 1 Mailbox 11 Data 0 Register */
+#define                  CAN1_MB11_DATA1  0xffc03564   /* CAN Controller 1 Mailbox 11 Data 1 Register */
+#define                  CAN1_MB11_DATA2  0xffc03568   /* CAN Controller 1 Mailbox 11 Data 2 Register */
+#define                  CAN1_MB11_DATA3  0xffc0356c   /* CAN Controller 1 Mailbox 11 Data 3 Register */
+#define                 CAN1_MB11_LENGTH  0xffc03570   /* CAN Controller 1 Mailbox 11 Length Register */
+#define              CAN1_MB11_TIMESTAMP  0xffc03574   /* CAN Controller 1 Mailbox 11 Timestamp Register */
+#define                    CAN1_MB11_ID0  0xffc03578   /* CAN Controller 1 Mailbox 11 ID0 Register */
+#define                    CAN1_MB11_ID1  0xffc0357c   /* CAN Controller 1 Mailbox 11 ID1 Register */
+#define                  CAN1_MB12_DATA0  0xffc03580   /* CAN Controller 1 Mailbox 12 Data 0 Register */
+#define                  CAN1_MB12_DATA1  0xffc03584   /* CAN Controller 1 Mailbox 12 Data 1 Register */
+#define                  CAN1_MB12_DATA2  0xffc03588   /* CAN Controller 1 Mailbox 12 Data 2 Register */
+#define                  CAN1_MB12_DATA3  0xffc0358c   /* CAN Controller 1 Mailbox 12 Data 3 Register */
+#define                 CAN1_MB12_LENGTH  0xffc03590   /* CAN Controller 1 Mailbox 12 Length Register */
+#define              CAN1_MB12_TIMESTAMP  0xffc03594   /* CAN Controller 1 Mailbox 12 Timestamp Register */
+#define                    CAN1_MB12_ID0  0xffc03598   /* CAN Controller 1 Mailbox 12 ID0 Register */
+#define                    CAN1_MB12_ID1  0xffc0359c   /* CAN Controller 1 Mailbox 12 ID1 Register */
+#define                  CAN1_MB13_DATA0  0xffc035a0   /* CAN Controller 1 Mailbox 13 Data 0 Register */
+#define                  CAN1_MB13_DATA1  0xffc035a4   /* CAN Controller 1 Mailbox 13 Data 1 Register */
+#define                  CAN1_MB13_DATA2  0xffc035a8   /* CAN Controller 1 Mailbox 13 Data 2 Register */
+#define                  CAN1_MB13_DATA3  0xffc035ac   /* CAN Controller 1 Mailbox 13 Data 3 Register */
+#define                 CAN1_MB13_LENGTH  0xffc035b0   /* CAN Controller 1 Mailbox 13 Length Register */
+#define              CAN1_MB13_TIMESTAMP  0xffc035b4   /* CAN Controller 1 Mailbox 13 Timestamp Register */
+#define                    CAN1_MB13_ID0  0xffc035b8   /* CAN Controller 1 Mailbox 13 ID0 Register */
+#define                    CAN1_MB13_ID1  0xffc035bc   /* CAN Controller 1 Mailbox 13 ID1 Register */
+#define                  CAN1_MB14_DATA0  0xffc035c0   /* CAN Controller 1 Mailbox 14 Data 0 Register */
+#define                  CAN1_MB14_DATA1  0xffc035c4   /* CAN Controller 1 Mailbox 14 Data 1 Register */
+#define                  CAN1_MB14_DATA2  0xffc035c8   /* CAN Controller 1 Mailbox 14 Data 2 Register */
+#define                  CAN1_MB14_DATA3  0xffc035cc   /* CAN Controller 1 Mailbox 14 Data 3 Register */
+#define                 CAN1_MB14_LENGTH  0xffc035d0   /* CAN Controller 1 Mailbox 14 Length Register */
+#define              CAN1_MB14_TIMESTAMP  0xffc035d4   /* CAN Controller 1 Mailbox 14 Timestamp Register */
+#define                    CAN1_MB14_ID0  0xffc035d8   /* CAN Controller 1 Mailbox 14 ID0 Register */
+#define                    CAN1_MB14_ID1  0xffc035dc   /* CAN Controller 1 Mailbox 14 ID1 Register */
+#define                  CAN1_MB15_DATA0  0xffc035e0   /* CAN Controller 1 Mailbox 15 Data 0 Register */
+#define                  CAN1_MB15_DATA1  0xffc035e4   /* CAN Controller 1 Mailbox 15 Data 1 Register */
+#define                  CAN1_MB15_DATA2  0xffc035e8   /* CAN Controller 1 Mailbox 15 Data 2 Register */
+#define                  CAN1_MB15_DATA3  0xffc035ec   /* CAN Controller 1 Mailbox 15 Data 3 Register */
+#define                 CAN1_MB15_LENGTH  0xffc035f0   /* CAN Controller 1 Mailbox 15 Length Register */
+#define              CAN1_MB15_TIMESTAMP  0xffc035f4   /* CAN Controller 1 Mailbox 15 Timestamp Register */
+#define                    CAN1_MB15_ID0  0xffc035f8   /* CAN Controller 1 Mailbox 15 ID0 Register */
+#define                    CAN1_MB15_ID1  0xffc035fc   /* CAN Controller 1 Mailbox 15 ID1 Register */
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define                  CAN1_MB16_DATA0  0xffc03600   /* CAN Controller 1 Mailbox 16 Data 0 Register */
+#define                  CAN1_MB16_DATA1  0xffc03604   /* CAN Controller 1 Mailbox 16 Data 1 Register */
+#define                  CAN1_MB16_DATA2  0xffc03608   /* CAN Controller 1 Mailbox 16 Data 2 Register */
+#define                  CAN1_MB16_DATA3  0xffc0360c   /* CAN Controller 1 Mailbox 16 Data 3 Register */
+#define                 CAN1_MB16_LENGTH  0xffc03610   /* CAN Controller 1 Mailbox 16 Length Register */
+#define              CAN1_MB16_TIMESTAMP  0xffc03614   /* CAN Controller 1 Mailbox 16 Timestamp Register */
+#define                    CAN1_MB16_ID0  0xffc03618   /* CAN Controller 1 Mailbox 16 ID0 Register */
+#define                    CAN1_MB16_ID1  0xffc0361c   /* CAN Controller 1 Mailbox 16 ID1 Register */
+#define                  CAN1_MB17_DATA0  0xffc03620   /* CAN Controller 1 Mailbox 17 Data 0 Register */
+#define                  CAN1_MB17_DATA1  0xffc03624   /* CAN Controller 1 Mailbox 17 Data 1 Register */
+#define                  CAN1_MB17_DATA2  0xffc03628   /* CAN Controller 1 Mailbox 17 Data 2 Register */
+#define                  CAN1_MB17_DATA3  0xffc0362c   /* CAN Controller 1 Mailbox 17 Data 3 Register */
+#define                 CAN1_MB17_LENGTH  0xffc03630   /* CAN Controller 1 Mailbox 17 Length Register */
+#define              CAN1_MB17_TIMESTAMP  0xffc03634   /* CAN Controller 1 Mailbox 17 Timestamp Register */
+#define                    CAN1_MB17_ID0  0xffc03638   /* CAN Controller 1 Mailbox 17 ID0 Register */
+#define                    CAN1_MB17_ID1  0xffc0363c   /* CAN Controller 1 Mailbox 17 ID1 Register */
+#define                  CAN1_MB18_DATA0  0xffc03640   /* CAN Controller 1 Mailbox 18 Data 0 Register */
+#define                  CAN1_MB18_DATA1  0xffc03644   /* CAN Controller 1 Mailbox 18 Data 1 Register */
+#define                  CAN1_MB18_DATA2  0xffc03648   /* CAN Controller 1 Mailbox 18 Data 2 Register */
+#define                  CAN1_MB18_DATA3  0xffc0364c   /* CAN Controller 1 Mailbox 18 Data 3 Register */
+#define                 CAN1_MB18_LENGTH  0xffc03650   /* CAN Controller 1 Mailbox 18 Length Register */
+#define              CAN1_MB18_TIMESTAMP  0xffc03654   /* CAN Controller 1 Mailbox 18 Timestamp Register */
+#define                    CAN1_MB18_ID0  0xffc03658   /* CAN Controller 1 Mailbox 18 ID0 Register */
+#define                    CAN1_MB18_ID1  0xffc0365c   /* CAN Controller 1 Mailbox 18 ID1 Register */
+#define                  CAN1_MB19_DATA0  0xffc03660   /* CAN Controller 1 Mailbox 19 Data 0 Register */
+#define                  CAN1_MB19_DATA1  0xffc03664   /* CAN Controller 1 Mailbox 19 Data 1 Register */
+#define                  CAN1_MB19_DATA2  0xffc03668   /* CAN Controller 1 Mailbox 19 Data 2 Register */
+#define                  CAN1_MB19_DATA3  0xffc0366c   /* CAN Controller 1 Mailbox 19 Data 3 Register */
+#define                 CAN1_MB19_LENGTH  0xffc03670   /* CAN Controller 1 Mailbox 19 Length Register */
+#define              CAN1_MB19_TIMESTAMP  0xffc03674   /* CAN Controller 1 Mailbox 19 Timestamp Register */
+#define                    CAN1_MB19_ID0  0xffc03678   /* CAN Controller 1 Mailbox 19 ID0 Register */
+#define                    CAN1_MB19_ID1  0xffc0367c   /* CAN Controller 1 Mailbox 19 ID1 Register */
+#define                  CAN1_MB20_DATA0  0xffc03680   /* CAN Controller 1 Mailbox 20 Data 0 Register */
+#define                  CAN1_MB20_DATA1  0xffc03684   /* CAN Controller 1 Mailbox 20 Data 1 Register */
+#define                  CAN1_MB20_DATA2  0xffc03688   /* CAN Controller 1 Mailbox 20 Data 2 Register */
+#define                  CAN1_MB20_DATA3  0xffc0368c   /* CAN Controller 1 Mailbox 20 Data 3 Register */
+#define                 CAN1_MB20_LENGTH  0xffc03690   /* CAN Controller 1 Mailbox 20 Length Register */
+#define              CAN1_MB20_TIMESTAMP  0xffc03694   /* CAN Controller 1 Mailbox 20 Timestamp Register */
+#define                    CAN1_MB20_ID0  0xffc03698   /* CAN Controller 1 Mailbox 20 ID0 Register */
+#define                    CAN1_MB20_ID1  0xffc0369c   /* CAN Controller 1 Mailbox 20 ID1 Register */
+#define                  CAN1_MB21_DATA0  0xffc036a0   /* CAN Controller 1 Mailbox 21 Data 0 Register */
+#define                  CAN1_MB21_DATA1  0xffc036a4   /* CAN Controller 1 Mailbox 21 Data 1 Register */
+#define                  CAN1_MB21_DATA2  0xffc036a8   /* CAN Controller 1 Mailbox 21 Data 2 Register */
+#define                  CAN1_MB21_DATA3  0xffc036ac   /* CAN Controller 1 Mailbox 21 Data 3 Register */
+#define                 CAN1_MB21_LENGTH  0xffc036b0   /* CAN Controller 1 Mailbox 21 Length Register */
+#define              CAN1_MB21_TIMESTAMP  0xffc036b4   /* CAN Controller 1 Mailbox 21 Timestamp Register */
+#define                    CAN1_MB21_ID0  0xffc036b8   /* CAN Controller 1 Mailbox 21 ID0 Register */
+#define                    CAN1_MB21_ID1  0xffc036bc   /* CAN Controller 1 Mailbox 21 ID1 Register */
+#define                  CAN1_MB22_DATA0  0xffc036c0   /* CAN Controller 1 Mailbox 22 Data 0 Register */
+#define                  CAN1_MB22_DATA1  0xffc036c4   /* CAN Controller 1 Mailbox 22 Data 1 Register */
+#define                  CAN1_MB22_DATA2  0xffc036c8   /* CAN Controller 1 Mailbox 22 Data 2 Register */
+#define                  CAN1_MB22_DATA3  0xffc036cc   /* CAN Controller 1 Mailbox 22 Data 3 Register */
+#define                 CAN1_MB22_LENGTH  0xffc036d0   /* CAN Controller 1 Mailbox 22 Length Register */
+#define              CAN1_MB22_TIMESTAMP  0xffc036d4   /* CAN Controller 1 Mailbox 22 Timestamp Register */
+#define                    CAN1_MB22_ID0  0xffc036d8   /* CAN Controller 1 Mailbox 22 ID0 Register */
+#define                    CAN1_MB22_ID1  0xffc036dc   /* CAN Controller 1 Mailbox 22 ID1 Register */
+#define                  CAN1_MB23_DATA0  0xffc036e0   /* CAN Controller 1 Mailbox 23 Data 0 Register */
+#define                  CAN1_MB23_DATA1  0xffc036e4   /* CAN Controller 1 Mailbox 23 Data 1 Register */
+#define                  CAN1_MB23_DATA2  0xffc036e8   /* CAN Controller 1 Mailbox 23 Data 2 Register */
+#define                  CAN1_MB23_DATA3  0xffc036ec   /* CAN Controller 1 Mailbox 23 Data 3 Register */
+#define                 CAN1_MB23_LENGTH  0xffc036f0   /* CAN Controller 1 Mailbox 23 Length Register */
+#define              CAN1_MB23_TIMESTAMP  0xffc036f4   /* CAN Controller 1 Mailbox 23 Timestamp Register */
+#define                    CAN1_MB23_ID0  0xffc036f8   /* CAN Controller 1 Mailbox 23 ID0 Register */
+#define                    CAN1_MB23_ID1  0xffc036fc   /* CAN Controller 1 Mailbox 23 ID1 Register */
+#define                  CAN1_MB24_DATA0  0xffc03700   /* CAN Controller 1 Mailbox 24 Data 0 Register */
+#define                  CAN1_MB24_DATA1  0xffc03704   /* CAN Controller 1 Mailbox 24 Data 1 Register */
+#define                  CAN1_MB24_DATA2  0xffc03708   /* CAN Controller 1 Mailbox 24 Data 2 Register */
+#define                  CAN1_MB24_DATA3  0xffc0370c   /* CAN Controller 1 Mailbox 24 Data 3 Register */
+#define                 CAN1_MB24_LENGTH  0xffc03710   /* CAN Controller 1 Mailbox 24 Length Register */
+#define              CAN1_MB24_TIMESTAMP  0xffc03714   /* CAN Controller 1 Mailbox 24 Timestamp Register */
+#define                    CAN1_MB24_ID0  0xffc03718   /* CAN Controller 1 Mailbox 24 ID0 Register */
+#define                    CAN1_MB24_ID1  0xffc0371c   /* CAN Controller 1 Mailbox 24 ID1 Register */
+#define                  CAN1_MB25_DATA0  0xffc03720   /* CAN Controller 1 Mailbox 25 Data 0 Register */
+#define                  CAN1_MB25_DATA1  0xffc03724   /* CAN Controller 1 Mailbox 25 Data 1 Register */
+#define                  CAN1_MB25_DATA2  0xffc03728   /* CAN Controller 1 Mailbox 25 Data 2 Register */
+#define                  CAN1_MB25_DATA3  0xffc0372c   /* CAN Controller 1 Mailbox 25 Data 3 Register */
+#define                 CAN1_MB25_LENGTH  0xffc03730   /* CAN Controller 1 Mailbox 25 Length Register */
+#define              CAN1_MB25_TIMESTAMP  0xffc03734   /* CAN Controller 1 Mailbox 25 Timestamp Register */
+#define                    CAN1_MB25_ID0  0xffc03738   /* CAN Controller 1 Mailbox 25 ID0 Register */
+#define                    CAN1_MB25_ID1  0xffc0373c   /* CAN Controller 1 Mailbox 25 ID1 Register */
+#define                  CAN1_MB26_DATA0  0xffc03740   /* CAN Controller 1 Mailbox 26 Data 0 Register */
+#define                  CAN1_MB26_DATA1  0xffc03744   /* CAN Controller 1 Mailbox 26 Data 1 Register */
+#define                  CAN1_MB26_DATA2  0xffc03748   /* CAN Controller 1 Mailbox 26 Data 2 Register */
+#define                  CAN1_MB26_DATA3  0xffc0374c   /* CAN Controller 1 Mailbox 26 Data 3 Register */
+#define                 CAN1_MB26_LENGTH  0xffc03750   /* CAN Controller 1 Mailbox 26 Length Register */
+#define              CAN1_MB26_TIMESTAMP  0xffc03754   /* CAN Controller 1 Mailbox 26 Timestamp Register */
+#define                    CAN1_MB26_ID0  0xffc03758   /* CAN Controller 1 Mailbox 26 ID0 Register */
+#define                    CAN1_MB26_ID1  0xffc0375c   /* CAN Controller 1 Mailbox 26 ID1 Register */
+#define                  CAN1_MB27_DATA0  0xffc03760   /* CAN Controller 1 Mailbox 27 Data 0 Register */
+#define                  CAN1_MB27_DATA1  0xffc03764   /* CAN Controller 1 Mailbox 27 Data 1 Register */
+#define                  CAN1_MB27_DATA2  0xffc03768   /* CAN Controller 1 Mailbox 27 Data 2 Register */
+#define                  CAN1_MB27_DATA3  0xffc0376c   /* CAN Controller 1 Mailbox 27 Data 3 Register */
+#define                 CAN1_MB27_LENGTH  0xffc03770   /* CAN Controller 1 Mailbox 27 Length Register */
+#define              CAN1_MB27_TIMESTAMP  0xffc03774   /* CAN Controller 1 Mailbox 27 Timestamp Register */
+#define                    CAN1_MB27_ID0  0xffc03778   /* CAN Controller 1 Mailbox 27 ID0 Register */
+#define                    CAN1_MB27_ID1  0xffc0377c   /* CAN Controller 1 Mailbox 27 ID1 Register */
+#define                  CAN1_MB28_DATA0  0xffc03780   /* CAN Controller 1 Mailbox 28 Data 0 Register */
+#define                  CAN1_MB28_DATA1  0xffc03784   /* CAN Controller 1 Mailbox 28 Data 1 Register */
+#define                  CAN1_MB28_DATA2  0xffc03788   /* CAN Controller 1 Mailbox 28 Data 2 Register */
+#define                  CAN1_MB28_DATA3  0xffc0378c   /* CAN Controller 1 Mailbox 28 Data 3 Register */
+#define                 CAN1_MB28_LENGTH  0xffc03790   /* CAN Controller 1 Mailbox 28 Length Register */
+#define              CAN1_MB28_TIMESTAMP  0xffc03794   /* CAN Controller 1 Mailbox 28 Timestamp Register */
+#define                    CAN1_MB28_ID0  0xffc03798   /* CAN Controller 1 Mailbox 28 ID0 Register */
+#define                    CAN1_MB28_ID1  0xffc0379c   /* CAN Controller 1 Mailbox 28 ID1 Register */
+#define                  CAN1_MB29_DATA0  0xffc037a0   /* CAN Controller 1 Mailbox 29 Data 0 Register */
+#define                  CAN1_MB29_DATA1  0xffc037a4   /* CAN Controller 1 Mailbox 29 Data 1 Register */
+#define                  CAN1_MB29_DATA2  0xffc037a8   /* CAN Controller 1 Mailbox 29 Data 2 Register */
+#define                  CAN1_MB29_DATA3  0xffc037ac   /* CAN Controller 1 Mailbox 29 Data 3 Register */
+#define                 CAN1_MB29_LENGTH  0xffc037b0   /* CAN Controller 1 Mailbox 29 Length Register */
+#define              CAN1_MB29_TIMESTAMP  0xffc037b4   /* CAN Controller 1 Mailbox 29 Timestamp Register */
+#define                    CAN1_MB29_ID0  0xffc037b8   /* CAN Controller 1 Mailbox 29 ID0 Register */
+#define                    CAN1_MB29_ID1  0xffc037bc   /* CAN Controller 1 Mailbox 29 ID1 Register */
+#define                  CAN1_MB30_DATA0  0xffc037c0   /* CAN Controller 1 Mailbox 30 Data 0 Register */
+#define                  CAN1_MB30_DATA1  0xffc037c4   /* CAN Controller 1 Mailbox 30 Data 1 Register */
+#define                  CAN1_MB30_DATA2  0xffc037c8   /* CAN Controller 1 Mailbox 30 Data 2 Register */
+#define                  CAN1_MB30_DATA3  0xffc037cc   /* CAN Controller 1 Mailbox 30 Data 3 Register */
+#define                 CAN1_MB30_LENGTH  0xffc037d0   /* CAN Controller 1 Mailbox 30 Length Register */
+#define              CAN1_MB30_TIMESTAMP  0xffc037d4   /* CAN Controller 1 Mailbox 30 Timestamp Register */
+#define                    CAN1_MB30_ID0  0xffc037d8   /* CAN Controller 1 Mailbox 30 ID0 Register */
+#define                    CAN1_MB30_ID1  0xffc037dc   /* CAN Controller 1 Mailbox 30 ID1 Register */
+#define                  CAN1_MB31_DATA0  0xffc037e0   /* CAN Controller 1 Mailbox 31 Data 0 Register */
+#define                  CAN1_MB31_DATA1  0xffc037e4   /* CAN Controller 1 Mailbox 31 Data 1 Register */
+#define                  CAN1_MB31_DATA2  0xffc037e8   /* CAN Controller 1 Mailbox 31 Data 2 Register */
+#define                  CAN1_MB31_DATA3  0xffc037ec   /* CAN Controller 1 Mailbox 31 Data 3 Register */
+#define                 CAN1_MB31_LENGTH  0xffc037f0   /* CAN Controller 1 Mailbox 31 Length Register */
+#define              CAN1_MB31_TIMESTAMP  0xffc037f4   /* CAN Controller 1 Mailbox 31 Timestamp Register */
+#define                    CAN1_MB31_ID0  0xffc037f8   /* CAN Controller 1 Mailbox 31 ID0 Register */
+#define                    CAN1_MB31_ID1  0xffc037fc   /* CAN Controller 1 Mailbox 31 ID1 Register */
+
+/* HOST Port Registers */
+
+#define                     HOST_CONTROL  0xffc03a00   /* HOST Control Register */
+#define                      HOST_STATUS  0xffc03a04   /* HOST Status Register */
+#define                     HOST_TIMEOUT  0xffc03a08   /* HOST Acknowledge Mode Timeout Register */
+
+/* Pixel Compositor (PIXC) Registers */
+
+#define                         PIXC_CTL  0xffc04400   /* Overlay enable, resampling mode, I/O data format, transparency enable, watermark level, FIFO status */
+#define                         PIXC_PPL  0xffc04404   /* Holds the number of pixels per line of the display */
+#define                         PIXC_LPF  0xffc04408   /* Holds the number of lines per frame of the display */
+#define                     PIXC_AHSTART  0xffc0440c   /* Contains horizontal start pixel information of the overlay data (set A) */
+#define                       PIXC_AHEND  0xffc04410   /* Contains horizontal end pixel information of the overlay data (set A) */
+#define                     PIXC_AVSTART  0xffc04414   /* Contains vertical start pixel information of the overlay data (set A) */
+#define                       PIXC_AVEND  0xffc04418   /* Contains vertical end pixel information of the overlay data (set A) */
+#define                     PIXC_ATRANSP  0xffc0441c   /* Contains the transparency ratio (set A) */
+#define                     PIXC_BHSTART  0xffc04420   /* Contains horizontal start pixel information of the overlay data (set B) */
+#define                       PIXC_BHEND  0xffc04424   /* Contains horizontal end pixel information of the overlay data (set B) */
+#define                     PIXC_BVSTART  0xffc04428   /* Contains vertical start pixel information of the overlay data (set B) */
+#define                       PIXC_BVEND  0xffc0442c   /* Contains vertical end pixel information of the overlay data (set B) */
+#define                     PIXC_BTRANSP  0xffc04430   /* Contains the transparency ratio (set B) */
+#define                    PIXC_INTRSTAT  0xffc0443c   /* Overlay interrupt configuration/status */
+#define                       PIXC_RYCON  0xffc04440   /* Color space conversion matrix register. Contains the R/Y conversion coefficients */
+#define                       PIXC_GUCON  0xffc04444   /* Color space conversion matrix register. Contains the G/U conversion coefficients */
+#define                       PIXC_BVCON  0xffc04448   /* Color space conversion matrix register. Contains the B/V conversion coefficients */
+#define                      PIXC_CCBIAS  0xffc0444c   /* Bias values for the color space conversion matrix */
+#define                          PIXC_TC  0xffc04450   /* Holds the transparent color value */
+
+/* Handshake MDMA 0 Registers */
+
+#define                   HMDMA0_CONTROL  0xffc04500   /* Handshake MDMA0 Control Register */
+#define                    HMDMA0_ECINIT  0xffc04504   /* Handshake MDMA0 Initial Edge Count Register */
+#define                    HMDMA0_BCINIT  0xffc04508   /* Handshake MDMA0 Initial Block Count Register */
+#define                  HMDMA0_ECURGENT  0xffc0450c   /* Handshake MDMA0 Urgent Edge Count Threshhold Register */
+#define                HMDMA0_ECOVERFLOW  0xffc04510   /* Handshake MDMA0 Edge Count Overflow Interrupt Register */
+#define                    HMDMA0_ECOUNT  0xffc04514   /* Handshake MDMA0 Current Edge Count Register */
+#define                    HMDMA0_BCOUNT  0xffc04518   /* Handshake MDMA0 Current Block Count Register */
+
+/* Handshake MDMA 1 Registers */
+
+#define                   HMDMA1_CONTROL  0xffc04540   /* Handshake MDMA1 Control Register */
+#define                    HMDMA1_ECINIT  0xffc04544   /* Handshake MDMA1 Initial Edge Count Register */
+#define                    HMDMA1_BCINIT  0xffc04548   /* Handshake MDMA1 Initial Block Count Register */
+#define                  HMDMA1_ECURGENT  0xffc0454c   /* Handshake MDMA1 Urgent Edge Count Threshhold Register */
+#define                HMDMA1_ECOVERFLOW  0xffc04550   /* Handshake MDMA1 Edge Count Overflow Interrupt Register */
+#define                    HMDMA1_ECOUNT  0xffc04554   /* Handshake MDMA1 Current Edge Count Register */
+#define                    HMDMA1_BCOUNT  0xffc04558   /* Handshake MDMA1 Current Block Count Register */
+
+
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for PIXC_CTL */
+
+#define                   PIXC_EN  0x1        /* Pixel Compositor Enable */
+#define                  OVR_A_EN  0x2        /* Overlay A Enable */
+#define                  OVR_B_EN  0x4        /* Overlay B Enable */
+#define                  IMG_FORM  0x8        /* Image Data Format */
+#define                  OVR_FORM  0x10       /* Overlay Data Format */
+#define                  OUT_FORM  0x20       /* Output Data Format */
+#define                   UDS_MOD  0x40       /* Resampling Mode */
+#define                     TC_EN  0x80       /* Transparent Color Enable */
+#define                  IMG_STAT  0x300      /* Image FIFO Status */
+#define                  OVR_STAT  0xc00      /* Overlay FIFO Status */
+#define                    WM_LVL  0x3000     /* FIFO Watermark Level */
+
+/* Bit masks for PIXC_AHSTART */
+
+#define                  A_HSTART  0xfff      /* Horizontal Start Coordinates */
+
+/* Bit masks for PIXC_AHEND */
+
+#define                    A_HEND  0xfff      /* Horizontal End Coordinates */
+
+/* Bit masks for PIXC_AVSTART */
+
+#define                  A_VSTART  0x3ff      /* Vertical Start Coordinates */
+
+/* Bit masks for PIXC_AVEND */
+
+#define                    A_VEND  0x3ff      /* Vertical End Coordinates */
+
+/* Bit masks for PIXC_ATRANSP */
+
+#define                  A_TRANSP  0xf        /* Transparency Value */
+
+/* Bit masks for PIXC_BHSTART */
+
+#define                  B_HSTART  0xfff      /* Horizontal Start Coordinates */
+
+/* Bit masks for PIXC_BHEND */
+
+#define                    B_HEND  0xfff      /* Horizontal End Coordinates */
+
+/* Bit masks for PIXC_BVSTART */
+
+#define                  B_VSTART  0x3ff      /* Vertical Start Coordinates */
+
+/* Bit masks for PIXC_BVEND */
+
+#define                    B_VEND  0x3ff      /* Vertical End Coordinates */
+
+/* Bit masks for PIXC_BTRANSP */
+
+#define                  B_TRANSP  0xf        /* Transparency Value */
+
+/* Bit masks for PIXC_INTRSTAT */
+
+#define                OVR_INT_EN  0x1        /* Interrupt at End of Last Valid Overlay */
+#define                FRM_INT_EN  0x2        /* Interrupt at End of Frame */
+#define              OVR_INT_STAT  0x4        /* Overlay Interrupt Status */
+#define              FRM_INT_STAT  0x8        /* Frame Interrupt Status */
+
+/* Bit masks for PIXC_RYCON */
+
+#define                       A11  0x3ff      /* A11 in the Coefficient Matrix */
+#define                       A12  0xffc00    /* A12 in the Coefficient Matrix */
+#define                       A13  0x3ff00000 /* A13 in the Coefficient Matrix */
+#define                  RY_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_GUCON */
+
+#define                       A21  0x3ff      /* A21 in the Coefficient Matrix */
+#define                       A22  0xffc00    /* A22 in the Coefficient Matrix */
+#define                       A23  0x3ff00000 /* A23 in the Coefficient Matrix */
+#define                  GU_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_BVCON */
+
+#define                       A31  0x3ff      /* A31 in the Coefficient Matrix */
+#define                       A32  0xffc00    /* A32 in the Coefficient Matrix */
+#define                       A33  0x3ff00000 /* A33 in the Coefficient Matrix */
+#define                  BV_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_CCBIAS */
+
+#define                       A14  0x3ff      /* A14 in the Bias Vector */
+#define                       A24  0xffc00    /* A24 in the Bias Vector */
+#define                       A34  0x3ff00000 /* A34 in the Bias Vector */
+
+/* Bit masks for PIXC_TC */
+
+#define                  RY_TRANS  0xff       /* Transparent Color - R/Y Component */
+#define                  GU_TRANS  0xff00     /* Transparent Color - G/U Component */
+#define                  BV_TRANS  0xff0000   /* Transparent Color - B/V Component */
+
+/* Bit masks for HOST_CONTROL */
+
+#define                   HOST_EN  0x1        /* Host Enable */
+#define                  HOST_END  0x2        /* Host Endianess */
+#define                 DATA_SIZE  0x4        /* Data Size */
+#define                  HOST_RST  0x8        /* Host Reset */
+#define                  HRDY_OVR  0x20       /* Host Ready Override */
+#define                  INT_MODE  0x40       /* Interrupt Mode */
+#define                     BT_EN  0x80       /* Bus Timeout Enable */
+#define                       EHW  0x100      /* Enable Host Write */
+#define                       EHR  0x200      /* Enable Host Read */
+#define                       BDR  0x400      /* Burst DMA Requests */
+
+/* Bit masks for HOST_STATUS */
+
+#define                     READY  0x1        /* DMA Ready */
+#define                  FIFOFULL  0x2        /* FIFO Full */
+#define                 FIFOEMPTY  0x4        /* FIFO Empty */
+#define                  COMPLETE  0x8        /* DMA Complete */
+#define                      HSHK  0x10       /* Host Handshake */
+#define                   TIMEOUT  0x20       /* Host Timeout */
+#define                      HIRQ  0x40       /* Host Interrupt Request */
+#define                ALLOW_CNFG  0x80       /* Allow New Configuration */
+#define                   DMA_DIR  0x100      /* DMA Direction */
+#define                       BTE  0x200      /* Bus Timeout Enabled */
+
+/* Bit masks for HOST_TIMEOUT */
+
+#define             COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
+
+/* Bit masks for TIMER_ENABLE1 */
+
+#define                    TIMEN8  0x1        /* Timer 8 Enable */
+#define                    TIMEN9  0x2        /* Timer 9 Enable */
+#define                   TIMEN10  0x4        /* Timer 10 Enable */
+
+/* Bit masks for TIMER_DISABLE1 */
+
+#define                   TIMDIS8  0x1        /* Timer 8 Disable */
+#define                   TIMDIS9  0x2        /* Timer 9 Disable */
+#define                  TIMDIS10  0x4        /* Timer 10 Disable */
+
+/* Bit masks for TIMER_STATUS1 */
+
+#define                    TIMIL8  0x1        /* Timer 8 Interrupt */
+#define                    TIMIL9  0x2        /* Timer 9 Interrupt */
+#define                   TIMIL10  0x4        /* Timer 10 Interrupt */
+#define                 TOVF_ERR8  0x10       /* Timer 8 Counter Overflow */
+#define                 TOVF_ERR9  0x20       /* Timer 9 Counter Overflow */
+#define                TOVF_ERR10  0x40       /* Timer 10 Counter Overflow */
+#define                     TRUN8  0x1000     /* Timer 8 Slave Enable Status */
+#define                     TRUN9  0x2000     /* Timer 9 Slave Enable Status */
+#define                    TRUN10  0x4000     /* Timer 10 Slave Enable Status */
+
+/* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
+
+/* Bit masks for HMDMAx_CONTROL */
+
+#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
+#define                       REP  0x2        /* Handshake MDMA Request Polarity */
+#define                       UTE  0x8        /* Urgency Threshold Enable */
+#define                       OIE  0x10       /* Overflow Interrupt Enable */
+#define                      BDIE  0x20       /* Block Done Interrupt Enable */
+#define                      MBDI  0x40       /* Mask Block Done Interrupt */
+#define                       DRQ  0x300      /* Handshake MDMA Request Type */
+#define                       RBC  0x1000     /* Force Reload of BCOUNT */
+#define                        PS  0x2000     /* Pin Status */
+#define                        OI  0x4000     /* Overflow Interrupt Generated */
+#define                       BDI  0x8000     /* Block Done Interrupt Generated */
+
+/* ******************************************* */
+/*     MULTI BIT MACRO ENUMERATIONS            */
+/* ******************************************* */
+
+#endif /* _DEF_BF544_H */
diff --git a/include/asm-blackfin/mach-bf548/defBF548.h b/include/asm-blackfin/mach-bf548/defBF548.h
new file mode 100644
index 0000000..8d4214e
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/defBF548.h
@@ -0,0 +1,1625 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/defBF548.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF548_H
+#define _DEF_BF548_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF548 */
+
+/* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
+#include "defBF54x_base.h"
+
+/* The following are the #defines needed by ADSP-BF548 that are not in the common header */
+
+/* Timer Registers */
+
+#define                    TIMER8_CONFIG  0xffc00600   /* Timer 8 Configuration Register */
+#define                   TIMER8_COUNTER  0xffc00604   /* Timer 8 Counter Register */
+#define                    TIMER8_PERIOD  0xffc00608   /* Timer 8 Period Register */
+#define                     TIMER8_WIDTH  0xffc0060c   /* Timer 8 Width Register */
+#define                    TIMER9_CONFIG  0xffc00610   /* Timer 9 Configuration Register */
+#define                   TIMER9_COUNTER  0xffc00614   /* Timer 9 Counter Register */
+#define                    TIMER9_PERIOD  0xffc00618   /* Timer 9 Period Register */
+#define                     TIMER9_WIDTH  0xffc0061c   /* Timer 9 Width Register */
+#define                   TIMER10_CONFIG  0xffc00620   /* Timer 10 Configuration Register */
+#define                  TIMER10_COUNTER  0xffc00624   /* Timer 10 Counter Register */
+#define                   TIMER10_PERIOD  0xffc00628   /* Timer 10 Period Register */
+#define                    TIMER10_WIDTH  0xffc0062c   /* Timer 10 Width Register */
+
+/* Timer Group of 3 Registers */
+
+#define                    TIMER_ENABLE1  0xffc00640   /* Timer Group of 3 Enable Register */
+#define                   TIMER_DISABLE1  0xffc00644   /* Timer Group of 3 Disable Register */
+#define                    TIMER_STATUS1  0xffc00648   /* Timer Group of 3 Status Register */
+
+/* SPORT0 Registers */
+
+#define                      SPORT0_TCR1  0xffc00800   /* SPORT0 Transmit Configuration 1 Register */
+#define                      SPORT0_TCR2  0xffc00804   /* SPORT0 Transmit Configuration 2 Register */
+#define                   SPORT0_TCLKDIV  0xffc00808   /* SPORT0 Transmit Serial Clock Divider Register */
+#define                    SPORT0_TFSDIV  0xffc0080c   /* SPORT0 Transmit Frame Sync Divider Register */
+#define                        SPORT0_TX  0xffc00810   /* SPORT0 Transmit Data Register */
+#define                        SPORT0_RX  0xffc00818   /* SPORT0 Receive Data Register */
+#define                      SPORT0_RCR1  0xffc00820   /* SPORT0 Receive Configuration 1 Register */
+#define                      SPORT0_RCR2  0xffc00824   /* SPORT0 Receive Configuration 2 Register */
+#define                   SPORT0_RCLKDIV  0xffc00828   /* SPORT0 Receive Serial Clock Divider Register */
+#define                    SPORT0_RFSDIV  0xffc0082c   /* SPORT0 Receive Frame Sync Divider Register */
+#define                      SPORT0_STAT  0xffc00830   /* SPORT0 Status Register */
+#define                      SPORT0_CHNL  0xffc00834   /* SPORT0 Current Channel Register */
+#define                     SPORT0_MCMC1  0xffc00838   /* SPORT0 Multi channel Configuration Register 1 */
+#define                     SPORT0_MCMC2  0xffc0083c   /* SPORT0 Multi channel Configuration Register 2 */
+#define                     SPORT0_MTCS0  0xffc00840   /* SPORT0 Multi channel Transmit Select Register 0 */
+#define                     SPORT0_MTCS1  0xffc00844   /* SPORT0 Multi channel Transmit Select Register 1 */
+#define                     SPORT0_MTCS2  0xffc00848   /* SPORT0 Multi channel Transmit Select Register 2 */
+#define                     SPORT0_MTCS3  0xffc0084c   /* SPORT0 Multi channel Transmit Select Register 3 */
+#define                     SPORT0_MRCS0  0xffc00850   /* SPORT0 Multi channel Receive Select Register 0 */
+#define                     SPORT0_MRCS1  0xffc00854   /* SPORT0 Multi channel Receive Select Register 1 */
+#define                     SPORT0_MRCS2  0xffc00858   /* SPORT0 Multi channel Receive Select Register 2 */
+#define                     SPORT0_MRCS3  0xffc0085c   /* SPORT0 Multi channel Receive Select Register 3 */
+
+/* EPPI0 Registers */
+
+#define                     EPPI0_STATUS  0xffc01000   /* EPPI0 Status Register */
+#define                     EPPI0_HCOUNT  0xffc01004   /* EPPI0 Horizontal Transfer Count Register */
+#define                     EPPI0_HDELAY  0xffc01008   /* EPPI0 Horizontal Delay Count Register */
+#define                     EPPI0_VCOUNT  0xffc0100c   /* EPPI0 Vertical Transfer Count Register */
+#define                     EPPI0_VDELAY  0xffc01010   /* EPPI0 Vertical Delay Count Register */
+#define                      EPPI0_FRAME  0xffc01014   /* EPPI0 Lines per Frame Register */
+#define                       EPPI0_LINE  0xffc01018   /* EPPI0 Samples per Line Register */
+#define                     EPPI0_CLKDIV  0xffc0101c   /* EPPI0 Clock Divide Register */
+#define                    EPPI0_CONTROL  0xffc01020   /* EPPI0 Control Register */
+#define                   EPPI0_FS1W_HBL  0xffc01024   /* EPPI0 FS1 Width Register / EPPI0 Horizontal Blanking Samples Per Line Register */
+#define                  EPPI0_FS1P_AVPL  0xffc01028   /* EPPI0 FS1 Period Register / EPPI0 Active Video Samples Per Line Register */
+#define                   EPPI0_FS2W_LVB  0xffc0102c   /* EPPI0 FS2 Width Register / EPPI0 Lines of Vertical Blanking Register */
+#define                  EPPI0_FS2P_LAVF  0xffc01030   /* EPPI0 FS2 Period Register/ EPPI0 Lines of Active Video Per Field Register */
+#define                       EPPI0_CLIP  0xffc01034   /* EPPI0 Clipping Register */
+
+/* UART2 Registers */
+
+#define                        UART2_DLL  0xffc02100   /* Divisor Latch Low Byte */
+#define                        UART2_DLH  0xffc02104   /* Divisor Latch High Byte */
+#define                       UART2_GCTL  0xffc02108   /* Global Control Register */
+#define                        UART2_LCR  0xffc0210c   /* Line Control Register */
+#define                        UART2_MCR  0xffc02110   /* Modem Control Register */
+#define                        UART2_LSR  0xffc02114   /* Line Status Register */
+#define                        UART2_MSR  0xffc02118   /* Modem Status Register */
+#define                        UART2_SCR  0xffc0211c   /* Scratch Register */
+#define                    UART2_IER_SET  0xffc02120   /* Interrupt Enable Register Set */
+#define                  UART2_IER_CLEAR  0xffc02124   /* Interrupt Enable Register Clear */
+#define                        UART2_RBR  0xffc0212c   /* Receive Buffer Register */
+
+/* Two Wire Interface Registers (TWI1) */
+
+#define                      TWI1_CLKDIV  0xffc02200   /* Clock Divider Register */
+#define                     TWI1_CONTROL  0xffc02204   /* TWI Control Register */
+#define                  TWI1_SLAVE_CTRL  0xffc02208   /* TWI Slave Mode Control Register */
+#define                  TWI1_SLAVE_STAT  0xffc0220c   /* TWI Slave Mode Status Register */
+#define                  TWI1_SLAVE_ADDR  0xffc02210   /* TWI Slave Mode Address Register */
+#define                 TWI1_MASTER_CTRL  0xffc02214   /* TWI Master Mode Control Register */
+#define                 TWI1_MASTER_STAT  0xffc02218   /* TWI Master Mode Status Register */
+#define                 TWI1_MASTER_ADDR  0xffc0221c   /* TWI Master Mode Address Register */
+#define                    TWI1_INT_STAT  0xffc02220   /* TWI Interrupt Status Register */
+#define                    TWI1_INT_MASK  0xffc02224   /* TWI Interrupt Mask Register */
+#define                   TWI1_FIFO_CTRL  0xffc02228   /* TWI FIFO Control Register */
+#define                   TWI1_FIFO_STAT  0xffc0222c   /* TWI FIFO Status Register */
+#define                   TWI1_XMT_DATA8  0xffc02280   /* TWI FIFO Transmit Data Single Byte Register */
+#define                  TWI1_XMT_DATA16  0xffc02284   /* TWI FIFO Transmit Data Double Byte Register */
+#define                   TWI1_RCV_DATA8  0xffc02288   /* TWI FIFO Receive Data Single Byte Register */
+#define                  TWI1_RCV_DATA16  0xffc0228c   /* TWI FIFO Receive Data Double Byte Register */
+
+/* SPI2  Registers */
+
+#define                         SPI2_CTL  0xffc02400   /* SPI2 Control Register */
+#define                         SPI2_FLG  0xffc02404   /* SPI2 Flag Register */
+#define                        SPI2_STAT  0xffc02408   /* SPI2 Status Register */
+#define                        SPI2_TDBR  0xffc0240c   /* SPI2 Transmit Data Buffer Register */
+#define                        SPI2_RDBR  0xffc02410   /* SPI2 Receive Data Buffer Register */
+#define                        SPI2_BAUD  0xffc02414   /* SPI2 Baud Rate Register */
+#define                      SPI2_SHADOW  0xffc02418   /* SPI2 Receive Data Buffer Shadow Register */
+
+/* CAN Controller 1 Config 1 Registers */
+
+#define                         CAN1_MC1  0xffc03200   /* CAN Controller 1 Mailbox Configuration Register 1 */
+#define                         CAN1_MD1  0xffc03204   /* CAN Controller 1 Mailbox Direction Register 1 */
+#define                        CAN1_TRS1  0xffc03208   /* CAN Controller 1 Transmit Request Set Register 1 */
+#define                        CAN1_TRR1  0xffc0320c   /* CAN Controller 1 Transmit Request Reset Register 1 */
+#define                         CAN1_TA1  0xffc03210   /* CAN Controller 1 Transmit Acknowledge Register 1 */
+#define                         CAN1_AA1  0xffc03214   /* CAN Controller 1 Abort Acknowledge Register 1 */
+#define                        CAN1_RMP1  0xffc03218   /* CAN Controller 1 Receive Message Pending Register 1 */
+#define                        CAN1_RML1  0xffc0321c   /* CAN Controller 1 Receive Message Lost Register 1 */
+#define                      CAN1_MBTIF1  0xffc03220   /* CAN Controller 1 Mailbox Transmit Interrupt Flag Register 1 */
+#define                      CAN1_MBRIF1  0xffc03224   /* CAN Controller 1 Mailbox Receive Interrupt Flag Register 1 */
+#define                       CAN1_MBIM1  0xffc03228   /* CAN Controller 1 Mailbox Interrupt Mask Register 1 */
+#define                        CAN1_RFH1  0xffc0322c   /* CAN Controller 1 Remote Frame Handling Enable Register 1 */
+#define                       CAN1_OPSS1  0xffc03230   /* CAN Controller 1 Overwrite Protection Single Shot Transmit Register 1 */
+
+/* CAN Controller 1 Config 2 Registers */
+
+#define                         CAN1_MC2  0xffc03240   /* CAN Controller 1 Mailbox Configuration Register 2 */
+#define                         CAN1_MD2  0xffc03244   /* CAN Controller 1 Mailbox Direction Register 2 */
+#define                        CAN1_TRS2  0xffc03248   /* CAN Controller 1 Transmit Request Set Register 2 */
+#define                        CAN1_TRR2  0xffc0324c   /* CAN Controller 1 Transmit Request Reset Register 2 */
+#define                         CAN1_TA2  0xffc03250   /* CAN Controller 1 Transmit Acknowledge Register 2 */
+#define                         CAN1_AA2  0xffc03254   /* CAN Controller 1 Abort Acknowledge Register 2 */
+#define                        CAN1_RMP2  0xffc03258   /* CAN Controller 1 Receive Message Pending Register 2 */
+#define                        CAN1_RML2  0xffc0325c   /* CAN Controller 1 Receive Message Lost Register 2 */
+#define                      CAN1_MBTIF2  0xffc03260   /* CAN Controller 1 Mailbox Transmit Interrupt Flag Register 2 */
+#define                      CAN1_MBRIF2  0xffc03264   /* CAN Controller 1 Mailbox Receive Interrupt Flag Register 2 */
+#define                       CAN1_MBIM2  0xffc03268   /* CAN Controller 1 Mailbox Interrupt Mask Register 2 */
+#define                        CAN1_RFH2  0xffc0326c   /* CAN Controller 1 Remote Frame Handling Enable Register 2 */
+#define                       CAN1_OPSS2  0xffc03270   /* CAN Controller 1 Overwrite Protection Single Shot Transmit Register 2 */
+
+/* CAN Controller 1 Clock/Interrupt/Counter Registers */
+
+#define                       CAN1_CLOCK  0xffc03280   /* CAN Controller 1 Clock Register */
+#define                      CAN1_TIMING  0xffc03284   /* CAN Controller 1 Timing Register */
+#define                       CAN1_DEBUG  0xffc03288   /* CAN Controller 1 Debug Register */
+#define                      CAN1_STATUS  0xffc0328c   /* CAN Controller 1 Global Status Register */
+#define                         CAN1_CEC  0xffc03290   /* CAN Controller 1 Error Counter Register */
+#define                         CAN1_GIS  0xffc03294   /* CAN Controller 1 Global Interrupt Status Register */
+#define                         CAN1_GIM  0xffc03298   /* CAN Controller 1 Global Interrupt Mask Register */
+#define                         CAN1_GIF  0xffc0329c   /* CAN Controller 1 Global Interrupt Flag Register */
+#define                     CAN1_CONTROL  0xffc032a0   /* CAN Controller 1 Master Control Register */
+#define                        CAN1_INTR  0xffc032a4   /* CAN Controller 1 Interrupt Pending Register */
+#define                        CAN1_MBTD  0xffc032ac   /* CAN Controller 1 Mailbox Temporary Disable Register */
+#define                         CAN1_EWR  0xffc032b0   /* CAN Controller 1 Programmable Warning Level Register */
+#define                         CAN1_ESR  0xffc032b4   /* CAN Controller 1 Error Status Register */
+#define                       CAN1_UCCNT  0xffc032c4   /* CAN Controller 1 Universal Counter Register */
+#define                        CAN1_UCRC  0xffc032c8   /* CAN Controller 1 Universal Counter Force Reload Register */
+#define                       CAN1_UCCNF  0xffc032cc   /* CAN Controller 1 Universal Counter Configuration Register */
+
+/* CAN Controller 1 Mailbox Acceptance Registers */
+
+#define                       CAN1_AM00L  0xffc03300   /* CAN Controller 1 Mailbox 0 Acceptance Mask High Register */
+#define                       CAN1_AM00H  0xffc03304   /* CAN Controller 1 Mailbox 0 Acceptance Mask Low Register */
+#define                       CAN1_AM01L  0xffc03308   /* CAN Controller 1 Mailbox 1 Acceptance Mask High Register */
+#define                       CAN1_AM01H  0xffc0330c   /* CAN Controller 1 Mailbox 1 Acceptance Mask Low Register */
+#define                       CAN1_AM02L  0xffc03310   /* CAN Controller 1 Mailbox 2 Acceptance Mask High Register */
+#define                       CAN1_AM02H  0xffc03314   /* CAN Controller 1 Mailbox 2 Acceptance Mask Low Register */
+#define                       CAN1_AM03L  0xffc03318   /* CAN Controller 1 Mailbox 3 Acceptance Mask High Register */
+#define                       CAN1_AM03H  0xffc0331c   /* CAN Controller 1 Mailbox 3 Acceptance Mask Low Register */
+#define                       CAN1_AM04L  0xffc03320   /* CAN Controller 1 Mailbox 4 Acceptance Mask High Register */
+#define                       CAN1_AM04H  0xffc03324   /* CAN Controller 1 Mailbox 4 Acceptance Mask Low Register */
+#define                       CAN1_AM05L  0xffc03328   /* CAN Controller 1 Mailbox 5 Acceptance Mask High Register */
+#define                       CAN1_AM05H  0xffc0332c   /* CAN Controller 1 Mailbox 5 Acceptance Mask Low Register */
+#define                       CAN1_AM06L  0xffc03330   /* CAN Controller 1 Mailbox 6 Acceptance Mask High Register */
+#define                       CAN1_AM06H  0xffc03334   /* CAN Controller 1 Mailbox 6 Acceptance Mask Low Register */
+#define                       CAN1_AM07L  0xffc03338   /* CAN Controller 1 Mailbox 7 Acceptance Mask High Register */
+#define                       CAN1_AM07H  0xffc0333c   /* CAN Controller 1 Mailbox 7 Acceptance Mask Low Register */
+#define                       CAN1_AM08L  0xffc03340   /* CAN Controller 1 Mailbox 8 Acceptance Mask High Register */
+#define                       CAN1_AM08H  0xffc03344   /* CAN Controller 1 Mailbox 8 Acceptance Mask Low Register */
+#define                       CAN1_AM09L  0xffc03348   /* CAN Controller 1 Mailbox 9 Acceptance Mask High Register */
+#define                       CAN1_AM09H  0xffc0334c   /* CAN Controller 1 Mailbox 9 Acceptance Mask Low Register */
+#define                       CAN1_AM10L  0xffc03350   /* CAN Controller 1 Mailbox 10 Acceptance Mask High Register */
+#define                       CAN1_AM10H  0xffc03354   /* CAN Controller 1 Mailbox 10 Acceptance Mask Low Register */
+#define                       CAN1_AM11L  0xffc03358   /* CAN Controller 1 Mailbox 11 Acceptance Mask High Register */
+#define                       CAN1_AM11H  0xffc0335c   /* CAN Controller 1 Mailbox 11 Acceptance Mask Low Register */
+#define                       CAN1_AM12L  0xffc03360   /* CAN Controller 1 Mailbox 12 Acceptance Mask High Register */
+#define                       CAN1_AM12H  0xffc03364   /* CAN Controller 1 Mailbox 12 Acceptance Mask Low Register */
+#define                       CAN1_AM13L  0xffc03368   /* CAN Controller 1 Mailbox 13 Acceptance Mask High Register */
+#define                       CAN1_AM13H  0xffc0336c   /* CAN Controller 1 Mailbox 13 Acceptance Mask Low Register */
+#define                       CAN1_AM14L  0xffc03370   /* CAN Controller 1 Mailbox 14 Acceptance Mask High Register */
+#define                       CAN1_AM14H  0xffc03374   /* CAN Controller 1 Mailbox 14 Acceptance Mask Low Register */
+#define                       CAN1_AM15L  0xffc03378   /* CAN Controller 1 Mailbox 15 Acceptance Mask High Register */
+#define                       CAN1_AM15H  0xffc0337c   /* CAN Controller 1 Mailbox 15 Acceptance Mask Low Register */
+
+/* CAN Controller 1 Mailbox Acceptance Registers */
+
+#define                       CAN1_AM16L  0xffc03380   /* CAN Controller 1 Mailbox 16 Acceptance Mask High Register */
+#define                       CAN1_AM16H  0xffc03384   /* CAN Controller 1 Mailbox 16 Acceptance Mask Low Register */
+#define                       CAN1_AM17L  0xffc03388   /* CAN Controller 1 Mailbox 17 Acceptance Mask High Register */
+#define                       CAN1_AM17H  0xffc0338c   /* CAN Controller 1 Mailbox 17 Acceptance Mask Low Register */
+#define                       CAN1_AM18L  0xffc03390   /* CAN Controller 1 Mailbox 18 Acceptance Mask High Register */
+#define                       CAN1_AM18H  0xffc03394   /* CAN Controller 1 Mailbox 18 Acceptance Mask Low Register */
+#define                       CAN1_AM19L  0xffc03398   /* CAN Controller 1 Mailbox 19 Acceptance Mask High Register */
+#define                       CAN1_AM19H  0xffc0339c   /* CAN Controller 1 Mailbox 19 Acceptance Mask Low Register */
+#define                       CAN1_AM20L  0xffc033a0   /* CAN Controller 1 Mailbox 20 Acceptance Mask High Register */
+#define                       CAN1_AM20H  0xffc033a4   /* CAN Controller 1 Mailbox 20 Acceptance Mask Low Register */
+#define                       CAN1_AM21L  0xffc033a8   /* CAN Controller 1 Mailbox 21 Acceptance Mask High Register */
+#define                       CAN1_AM21H  0xffc033ac   /* CAN Controller 1 Mailbox 21 Acceptance Mask Low Register */
+#define                       CAN1_AM22L  0xffc033b0   /* CAN Controller 1 Mailbox 22 Acceptance Mask High Register */
+#define                       CAN1_AM22H  0xffc033b4   /* CAN Controller 1 Mailbox 22 Acceptance Mask Low Register */
+#define                       CAN1_AM23L  0xffc033b8   /* CAN Controller 1 Mailbox 23 Acceptance Mask High Register */
+#define                       CAN1_AM23H  0xffc033bc   /* CAN Controller 1 Mailbox 23 Acceptance Mask Low Register */
+#define                       CAN1_AM24L  0xffc033c0   /* CAN Controller 1 Mailbox 24 Acceptance Mask High Register */
+#define                       CAN1_AM24H  0xffc033c4   /* CAN Controller 1 Mailbox 24 Acceptance Mask Low Register */
+#define                       CAN1_AM25L  0xffc033c8   /* CAN Controller 1 Mailbox 25 Acceptance Mask High Register */
+#define                       CAN1_AM25H  0xffc033cc   /* CAN Controller 1 Mailbox 25 Acceptance Mask Low Register */
+#define                       CAN1_AM26L  0xffc033d0   /* CAN Controller 1 Mailbox 26 Acceptance Mask High Register */
+#define                       CAN1_AM26H  0xffc033d4   /* CAN Controller 1 Mailbox 26 Acceptance Mask Low Register */
+#define                       CAN1_AM27L  0xffc033d8   /* CAN Controller 1 Mailbox 27 Acceptance Mask High Register */
+#define                       CAN1_AM27H  0xffc033dc   /* CAN Controller 1 Mailbox 27 Acceptance Mask Low Register */
+#define                       CAN1_AM28L  0xffc033e0   /* CAN Controller 1 Mailbox 28 Acceptance Mask High Register */
+#define                       CAN1_AM28H  0xffc033e4   /* CAN Controller 1 Mailbox 28 Acceptance Mask Low Register */
+#define                       CAN1_AM29L  0xffc033e8   /* CAN Controller 1 Mailbox 29 Acceptance Mask High Register */
+#define                       CAN1_AM29H  0xffc033ec   /* CAN Controller 1 Mailbox 29 Acceptance Mask Low Register */
+#define                       CAN1_AM30L  0xffc033f0   /* CAN Controller 1 Mailbox 30 Acceptance Mask High Register */
+#define                       CAN1_AM30H  0xffc033f4   /* CAN Controller 1 Mailbox 30 Acceptance Mask Low Register */
+#define                       CAN1_AM31L  0xffc033f8   /* CAN Controller 1 Mailbox 31 Acceptance Mask High Register */
+#define                       CAN1_AM31H  0xffc033fc   /* CAN Controller 1 Mailbox 31 Acceptance Mask Low Register */
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define                  CAN1_MB00_DATA0  0xffc03400   /* CAN Controller 1 Mailbox 0 Data 0 Register */
+#define                  CAN1_MB00_DATA1  0xffc03404   /* CAN Controller 1 Mailbox 0 Data 1 Register */
+#define                  CAN1_MB00_DATA2  0xffc03408   /* CAN Controller 1 Mailbox 0 Data 2 Register */
+#define                  CAN1_MB00_DATA3  0xffc0340c   /* CAN Controller 1 Mailbox 0 Data 3 Register */
+#define                 CAN1_MB00_LENGTH  0xffc03410   /* CAN Controller 1 Mailbox 0 Length Register */
+#define              CAN1_MB00_TIMESTAMP  0xffc03414   /* CAN Controller 1 Mailbox 0 Timestamp Register */
+#define                    CAN1_MB00_ID0  0xffc03418   /* CAN Controller 1 Mailbox 0 ID0 Register */
+#define                    CAN1_MB00_ID1  0xffc0341c   /* CAN Controller 1 Mailbox 0 ID1 Register */
+#define                  CAN1_MB01_DATA0  0xffc03420   /* CAN Controller 1 Mailbox 1 Data 0 Register */
+#define                  CAN1_MB01_DATA1  0xffc03424   /* CAN Controller 1 Mailbox 1 Data 1 Register */
+#define                  CAN1_MB01_DATA2  0xffc03428   /* CAN Controller 1 Mailbox 1 Data 2 Register */
+#define                  CAN1_MB01_DATA3  0xffc0342c   /* CAN Controller 1 Mailbox 1 Data 3 Register */
+#define                 CAN1_MB01_LENGTH  0xffc03430   /* CAN Controller 1 Mailbox 1 Length Register */
+#define              CAN1_MB01_TIMESTAMP  0xffc03434   /* CAN Controller 1 Mailbox 1 Timestamp Register */
+#define                    CAN1_MB01_ID0  0xffc03438   /* CAN Controller 1 Mailbox 1 ID0 Register */
+#define                    CAN1_MB01_ID1  0xffc0343c   /* CAN Controller 1 Mailbox 1 ID1 Register */
+#define                  CAN1_MB02_DATA0  0xffc03440   /* CAN Controller 1 Mailbox 2 Data 0 Register */
+#define                  CAN1_MB02_DATA1  0xffc03444   /* CAN Controller 1 Mailbox 2 Data 1 Register */
+#define                  CAN1_MB02_DATA2  0xffc03448   /* CAN Controller 1 Mailbox 2 Data 2 Register */
+#define                  CAN1_MB02_DATA3  0xffc0344c   /* CAN Controller 1 Mailbox 2 Data 3 Register */
+#define                 CAN1_MB02_LENGTH  0xffc03450   /* CAN Controller 1 Mailbox 2 Length Register */
+#define              CAN1_MB02_TIMESTAMP  0xffc03454   /* CAN Controller 1 Mailbox 2 Timestamp Register */
+#define                    CAN1_MB02_ID0  0xffc03458   /* CAN Controller 1 Mailbox 2 ID0 Register */
+#define                    CAN1_MB02_ID1  0xffc0345c   /* CAN Controller 1 Mailbox 2 ID1 Register */
+#define                  CAN1_MB03_DATA0  0xffc03460   /* CAN Controller 1 Mailbox 3 Data 0 Register */
+#define                  CAN1_MB03_DATA1  0xffc03464   /* CAN Controller 1 Mailbox 3 Data 1 Register */
+#define                  CAN1_MB03_DATA2  0xffc03468   /* CAN Controller 1 Mailbox 3 Data 2 Register */
+#define                  CAN1_MB03_DATA3  0xffc0346c   /* CAN Controller 1 Mailbox 3 Data 3 Register */
+#define                 CAN1_MB03_LENGTH  0xffc03470   /* CAN Controller 1 Mailbox 3 Length Register */
+#define              CAN1_MB03_TIMESTAMP  0xffc03474   /* CAN Controller 1 Mailbox 3 Timestamp Register */
+#define                    CAN1_MB03_ID0  0xffc03478   /* CAN Controller 1 Mailbox 3 ID0 Register */
+#define                    CAN1_MB03_ID1  0xffc0347c   /* CAN Controller 1 Mailbox 3 ID1 Register */
+#define                  CAN1_MB04_DATA0  0xffc03480   /* CAN Controller 1 Mailbox 4 Data 0 Register */
+#define                  CAN1_MB04_DATA1  0xffc03484   /* CAN Controller 1 Mailbox 4 Data 1 Register */
+#define                  CAN1_MB04_DATA2  0xffc03488   /* CAN Controller 1 Mailbox 4 Data 2 Register */
+#define                  CAN1_MB04_DATA3  0xffc0348c   /* CAN Controller 1 Mailbox 4 Data 3 Register */
+#define                 CAN1_MB04_LENGTH  0xffc03490   /* CAN Controller 1 Mailbox 4 Length Register */
+#define              CAN1_MB04_TIMESTAMP  0xffc03494   /* CAN Controller 1 Mailbox 4 Timestamp Register */
+#define                    CAN1_MB04_ID0  0xffc03498   /* CAN Controller 1 Mailbox 4 ID0 Register */
+#define                    CAN1_MB04_ID1  0xffc0349c   /* CAN Controller 1 Mailbox 4 ID1 Register */
+#define                  CAN1_MB05_DATA0  0xffc034a0   /* CAN Controller 1 Mailbox 5 Data 0 Register */
+#define                  CAN1_MB05_DATA1  0xffc034a4   /* CAN Controller 1 Mailbox 5 Data 1 Register */
+#define                  CAN1_MB05_DATA2  0xffc034a8   /* CAN Controller 1 Mailbox 5 Data 2 Register */
+#define                  CAN1_MB05_DATA3  0xffc034ac   /* CAN Controller 1 Mailbox 5 Data 3 Register */
+#define                 CAN1_MB05_LENGTH  0xffc034b0   /* CAN Controller 1 Mailbox 5 Length Register */
+#define              CAN1_MB05_TIMESTAMP  0xffc034b4   /* CAN Controller 1 Mailbox 5 Timestamp Register */
+#define                    CAN1_MB05_ID0  0xffc034b8   /* CAN Controller 1 Mailbox 5 ID0 Register */
+#define                    CAN1_MB05_ID1  0xffc034bc   /* CAN Controller 1 Mailbox 5 ID1 Register */
+#define                  CAN1_MB06_DATA0  0xffc034c0   /* CAN Controller 1 Mailbox 6 Data 0 Register */
+#define                  CAN1_MB06_DATA1  0xffc034c4   /* CAN Controller 1 Mailbox 6 Data 1 Register */
+#define                  CAN1_MB06_DATA2  0xffc034c8   /* CAN Controller 1 Mailbox 6 Data 2 Register */
+#define                  CAN1_MB06_DATA3  0xffc034cc   /* CAN Controller 1 Mailbox 6 Data 3 Register */
+#define                 CAN1_MB06_LENGTH  0xffc034d0   /* CAN Controller 1 Mailbox 6 Length Register */
+#define              CAN1_MB06_TIMESTAMP  0xffc034d4   /* CAN Controller 1 Mailbox 6 Timestamp Register */
+#define                    CAN1_MB06_ID0  0xffc034d8   /* CAN Controller 1 Mailbox 6 ID0 Register */
+#define                    CAN1_MB06_ID1  0xffc034dc   /* CAN Controller 1 Mailbox 6 ID1 Register */
+#define                  CAN1_MB07_DATA0  0xffc034e0   /* CAN Controller 1 Mailbox 7 Data 0 Register */
+#define                  CAN1_MB07_DATA1  0xffc034e4   /* CAN Controller 1 Mailbox 7 Data 1 Register */
+#define                  CAN1_MB07_DATA2  0xffc034e8   /* CAN Controller 1 Mailbox 7 Data 2 Register */
+#define                  CAN1_MB07_DATA3  0xffc034ec   /* CAN Controller 1 Mailbox 7 Data 3 Register */
+#define                 CAN1_MB07_LENGTH  0xffc034f0   /* CAN Controller 1 Mailbox 7 Length Register */
+#define              CAN1_MB07_TIMESTAMP  0xffc034f4   /* CAN Controller 1 Mailbox 7 Timestamp Register */
+#define                    CAN1_MB07_ID0  0xffc034f8   /* CAN Controller 1 Mailbox 7 ID0 Register */
+#define                    CAN1_MB07_ID1  0xffc034fc   /* CAN Controller 1 Mailbox 7 ID1 Register */
+#define                  CAN1_MB08_DATA0  0xffc03500   /* CAN Controller 1 Mailbox 8 Data 0 Register */
+#define                  CAN1_MB08_DATA1  0xffc03504   /* CAN Controller 1 Mailbox 8 Data 1 Register */
+#define                  CAN1_MB08_DATA2  0xffc03508   /* CAN Controller 1 Mailbox 8 Data 2 Register */
+#define                  CAN1_MB08_DATA3  0xffc0350c   /* CAN Controller 1 Mailbox 8 Data 3 Register */
+#define                 CAN1_MB08_LENGTH  0xffc03510   /* CAN Controller 1 Mailbox 8 Length Register */
+#define              CAN1_MB08_TIMESTAMP  0xffc03514   /* CAN Controller 1 Mailbox 8 Timestamp Register */
+#define                    CAN1_MB08_ID0  0xffc03518   /* CAN Controller 1 Mailbox 8 ID0 Register */
+#define                    CAN1_MB08_ID1  0xffc0351c   /* CAN Controller 1 Mailbox 8 ID1 Register */
+#define                  CAN1_MB09_DATA0  0xffc03520   /* CAN Controller 1 Mailbox 9 Data 0 Register */
+#define                  CAN1_MB09_DATA1  0xffc03524   /* CAN Controller 1 Mailbox 9 Data 1 Register */
+#define                  CAN1_MB09_DATA2  0xffc03528   /* CAN Controller 1 Mailbox 9 Data 2 Register */
+#define                  CAN1_MB09_DATA3  0xffc0352c   /* CAN Controller 1 Mailbox 9 Data 3 Register */
+#define                 CAN1_MB09_LENGTH  0xffc03530   /* CAN Controller 1 Mailbox 9 Length Register */
+#define              CAN1_MB09_TIMESTAMP  0xffc03534   /* CAN Controller 1 Mailbox 9 Timestamp Register */
+#define                    CAN1_MB09_ID0  0xffc03538   /* CAN Controller 1 Mailbox 9 ID0 Register */
+#define                    CAN1_MB09_ID1  0xffc0353c   /* CAN Controller 1 Mailbox 9 ID1 Register */
+#define                  CAN1_MB10_DATA0  0xffc03540   /* CAN Controller 1 Mailbox 10 Data 0 Register */
+#define                  CAN1_MB10_DATA1  0xffc03544   /* CAN Controller 1 Mailbox 10 Data 1 Register */
+#define                  CAN1_MB10_DATA2  0xffc03548   /* CAN Controller 1 Mailbox 10 Data 2 Register */
+#define                  CAN1_MB10_DATA3  0xffc0354c   /* CAN Controller 1 Mailbox 10 Data 3 Register */
+#define                 CAN1_MB10_LENGTH  0xffc03550   /* CAN Controller 1 Mailbox 10 Length Register */
+#define              CAN1_MB10_TIMESTAMP  0xffc03554   /* CAN Controller 1 Mailbox 10 Timestamp Register */
+#define                    CAN1_MB10_ID0  0xffc03558   /* CAN Controller 1 Mailbox 10 ID0 Register */
+#define                    CAN1_MB10_ID1  0xffc0355c   /* CAN Controller 1 Mailbox 10 ID1 Register */
+#define                  CAN1_MB11_DATA0  0xffc03560   /* CAN Controller 1 Mailbox 11 Data 0 Register */
+#define                  CAN1_MB11_DATA1  0xffc03564   /* CAN Controller 1 Mailbox 11 Data 1 Register */
+#define                  CAN1_MB11_DATA2  0xffc03568   /* CAN Controller 1 Mailbox 11 Data 2 Register */
+#define                  CAN1_MB11_DATA3  0xffc0356c   /* CAN Controller 1 Mailbox 11 Data 3 Register */
+#define                 CAN1_MB11_LENGTH  0xffc03570   /* CAN Controller 1 Mailbox 11 Length Register */
+#define              CAN1_MB11_TIMESTAMP  0xffc03574   /* CAN Controller 1 Mailbox 11 Timestamp Register */
+#define                    CAN1_MB11_ID0  0xffc03578   /* CAN Controller 1 Mailbox 11 ID0 Register */
+#define                    CAN1_MB11_ID1  0xffc0357c   /* CAN Controller 1 Mailbox 11 ID1 Register */
+#define                  CAN1_MB12_DATA0  0xffc03580   /* CAN Controller 1 Mailbox 12 Data 0 Register */
+#define                  CAN1_MB12_DATA1  0xffc03584   /* CAN Controller 1 Mailbox 12 Data 1 Register */
+#define                  CAN1_MB12_DATA2  0xffc03588   /* CAN Controller 1 Mailbox 12 Data 2 Register */
+#define                  CAN1_MB12_DATA3  0xffc0358c   /* CAN Controller 1 Mailbox 12 Data 3 Register */
+#define                 CAN1_MB12_LENGTH  0xffc03590   /* CAN Controller 1 Mailbox 12 Length Register */
+#define              CAN1_MB12_TIMESTAMP  0xffc03594   /* CAN Controller 1 Mailbox 12 Timestamp Register */
+#define                    CAN1_MB12_ID0  0xffc03598   /* CAN Controller 1 Mailbox 12 ID0 Register */
+#define                    CAN1_MB12_ID1  0xffc0359c   /* CAN Controller 1 Mailbox 12 ID1 Register */
+#define                  CAN1_MB13_DATA0  0xffc035a0   /* CAN Controller 1 Mailbox 13 Data 0 Register */
+#define                  CAN1_MB13_DATA1  0xffc035a4   /* CAN Controller 1 Mailbox 13 Data 1 Register */
+#define                  CAN1_MB13_DATA2  0xffc035a8   /* CAN Controller 1 Mailbox 13 Data 2 Register */
+#define                  CAN1_MB13_DATA3  0xffc035ac   /* CAN Controller 1 Mailbox 13 Data 3 Register */
+#define                 CAN1_MB13_LENGTH  0xffc035b0   /* CAN Controller 1 Mailbox 13 Length Register */
+#define              CAN1_MB13_TIMESTAMP  0xffc035b4   /* CAN Controller 1 Mailbox 13 Timestamp Register */
+#define                    CAN1_MB13_ID0  0xffc035b8   /* CAN Controller 1 Mailbox 13 ID0 Register */
+#define                    CAN1_MB13_ID1  0xffc035bc   /* CAN Controller 1 Mailbox 13 ID1 Register */
+#define                  CAN1_MB14_DATA0  0xffc035c0   /* CAN Controller 1 Mailbox 14 Data 0 Register */
+#define                  CAN1_MB14_DATA1  0xffc035c4   /* CAN Controller 1 Mailbox 14 Data 1 Register */
+#define                  CAN1_MB14_DATA2  0xffc035c8   /* CAN Controller 1 Mailbox 14 Data 2 Register */
+#define                  CAN1_MB14_DATA3  0xffc035cc   /* CAN Controller 1 Mailbox 14 Data 3 Register */
+#define                 CAN1_MB14_LENGTH  0xffc035d0   /* CAN Controller 1 Mailbox 14 Length Register */
+#define              CAN1_MB14_TIMESTAMP  0xffc035d4   /* CAN Controller 1 Mailbox 14 Timestamp Register */
+#define                    CAN1_MB14_ID0  0xffc035d8   /* CAN Controller 1 Mailbox 14 ID0 Register */
+#define                    CAN1_MB14_ID1  0xffc035dc   /* CAN Controller 1 Mailbox 14 ID1 Register */
+#define                  CAN1_MB15_DATA0  0xffc035e0   /* CAN Controller 1 Mailbox 15 Data 0 Register */
+#define                  CAN1_MB15_DATA1  0xffc035e4   /* CAN Controller 1 Mailbox 15 Data 1 Register */
+#define                  CAN1_MB15_DATA2  0xffc035e8   /* CAN Controller 1 Mailbox 15 Data 2 Register */
+#define                  CAN1_MB15_DATA3  0xffc035ec   /* CAN Controller 1 Mailbox 15 Data 3 Register */
+#define                 CAN1_MB15_LENGTH  0xffc035f0   /* CAN Controller 1 Mailbox 15 Length Register */
+#define              CAN1_MB15_TIMESTAMP  0xffc035f4   /* CAN Controller 1 Mailbox 15 Timestamp Register */
+#define                    CAN1_MB15_ID0  0xffc035f8   /* CAN Controller 1 Mailbox 15 ID0 Register */
+#define                    CAN1_MB15_ID1  0xffc035fc   /* CAN Controller 1 Mailbox 15 ID1 Register */
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define                  CAN1_MB16_DATA0  0xffc03600   /* CAN Controller 1 Mailbox 16 Data 0 Register */
+#define                  CAN1_MB16_DATA1  0xffc03604   /* CAN Controller 1 Mailbox 16 Data 1 Register */
+#define                  CAN1_MB16_DATA2  0xffc03608   /* CAN Controller 1 Mailbox 16 Data 2 Register */
+#define                  CAN1_MB16_DATA3  0xffc0360c   /* CAN Controller 1 Mailbox 16 Data 3 Register */
+#define                 CAN1_MB16_LENGTH  0xffc03610   /* CAN Controller 1 Mailbox 16 Length Register */
+#define              CAN1_MB16_TIMESTAMP  0xffc03614   /* CAN Controller 1 Mailbox 16 Timestamp Register */
+#define                    CAN1_MB16_ID0  0xffc03618   /* CAN Controller 1 Mailbox 16 ID0 Register */
+#define                    CAN1_MB16_ID1  0xffc0361c   /* CAN Controller 1 Mailbox 16 ID1 Register */
+#define                  CAN1_MB17_DATA0  0xffc03620   /* CAN Controller 1 Mailbox 17 Data 0 Register */
+#define                  CAN1_MB17_DATA1  0xffc03624   /* CAN Controller 1 Mailbox 17 Data 1 Register */
+#define                  CAN1_MB17_DATA2  0xffc03628   /* CAN Controller 1 Mailbox 17 Data 2 Register */
+#define                  CAN1_MB17_DATA3  0xffc0362c   /* CAN Controller 1 Mailbox 17 Data 3 Register */
+#define                 CAN1_MB17_LENGTH  0xffc03630   /* CAN Controller 1 Mailbox 17 Length Register */
+#define              CAN1_MB17_TIMESTAMP  0xffc03634   /* CAN Controller 1 Mailbox 17 Timestamp Register */
+#define                    CAN1_MB17_ID0  0xffc03638   /* CAN Controller 1 Mailbox 17 ID0 Register */
+#define                    CAN1_MB17_ID1  0xffc0363c   /* CAN Controller 1 Mailbox 17 ID1 Register */
+#define                  CAN1_MB18_DATA0  0xffc03640   /* CAN Controller 1 Mailbox 18 Data 0 Register */
+#define                  CAN1_MB18_DATA1  0xffc03644   /* CAN Controller 1 Mailbox 18 Data 1 Register */
+#define                  CAN1_MB18_DATA2  0xffc03648   /* CAN Controller 1 Mailbox 18 Data 2 Register */
+#define                  CAN1_MB18_DATA3  0xffc0364c   /* CAN Controller 1 Mailbox 18 Data 3 Register */
+#define                 CAN1_MB18_LENGTH  0xffc03650   /* CAN Controller 1 Mailbox 18 Length Register */
+#define              CAN1_MB18_TIMESTAMP  0xffc03654   /* CAN Controller 1 Mailbox 18 Timestamp Register */
+#define                    CAN1_MB18_ID0  0xffc03658   /* CAN Controller 1 Mailbox 18 ID0 Register */
+#define                    CAN1_MB18_ID1  0xffc0365c   /* CAN Controller 1 Mailbox 18 ID1 Register */
+#define                  CAN1_MB19_DATA0  0xffc03660   /* CAN Controller 1 Mailbox 19 Data 0 Register */
+#define                  CAN1_MB19_DATA1  0xffc03664   /* CAN Controller 1 Mailbox 19 Data 1 Register */
+#define                  CAN1_MB19_DATA2  0xffc03668   /* CAN Controller 1 Mailbox 19 Data 2 Register */
+#define                  CAN1_MB19_DATA3  0xffc0366c   /* CAN Controller 1 Mailbox 19 Data 3 Register */
+#define                 CAN1_MB19_LENGTH  0xffc03670   /* CAN Controller 1 Mailbox 19 Length Register */
+#define              CAN1_MB19_TIMESTAMP  0xffc03674   /* CAN Controller 1 Mailbox 19 Timestamp Register */
+#define                    CAN1_MB19_ID0  0xffc03678   /* CAN Controller 1 Mailbox 19 ID0 Register */
+#define                    CAN1_MB19_ID1  0xffc0367c   /* CAN Controller 1 Mailbox 19 ID1 Register */
+#define                  CAN1_MB20_DATA0  0xffc03680   /* CAN Controller 1 Mailbox 20 Data 0 Register */
+#define                  CAN1_MB20_DATA1  0xffc03684   /* CAN Controller 1 Mailbox 20 Data 1 Register */
+#define                  CAN1_MB20_DATA2  0xffc03688   /* CAN Controller 1 Mailbox 20 Data 2 Register */
+#define                  CAN1_MB20_DATA3  0xffc0368c   /* CAN Controller 1 Mailbox 20 Data 3 Register */
+#define                 CAN1_MB20_LENGTH  0xffc03690   /* CAN Controller 1 Mailbox 20 Length Register */
+#define              CAN1_MB20_TIMESTAMP  0xffc03694   /* CAN Controller 1 Mailbox 20 Timestamp Register */
+#define                    CAN1_MB20_ID0  0xffc03698   /* CAN Controller 1 Mailbox 20 ID0 Register */
+#define                    CAN1_MB20_ID1  0xffc0369c   /* CAN Controller 1 Mailbox 20 ID1 Register */
+#define                  CAN1_MB21_DATA0  0xffc036a0   /* CAN Controller 1 Mailbox 21 Data 0 Register */
+#define                  CAN1_MB21_DATA1  0xffc036a4   /* CAN Controller 1 Mailbox 21 Data 1 Register */
+#define                  CAN1_MB21_DATA2  0xffc036a8   /* CAN Controller 1 Mailbox 21 Data 2 Register */
+#define                  CAN1_MB21_DATA3  0xffc036ac   /* CAN Controller 1 Mailbox 21 Data 3 Register */
+#define                 CAN1_MB21_LENGTH  0xffc036b0   /* CAN Controller 1 Mailbox 21 Length Register */
+#define              CAN1_MB21_TIMESTAMP  0xffc036b4   /* CAN Controller 1 Mailbox 21 Timestamp Register */
+#define                    CAN1_MB21_ID0  0xffc036b8   /* CAN Controller 1 Mailbox 21 ID0 Register */
+#define                    CAN1_MB21_ID1  0xffc036bc   /* CAN Controller 1 Mailbox 21 ID1 Register */
+#define                  CAN1_MB22_DATA0  0xffc036c0   /* CAN Controller 1 Mailbox 22 Data 0 Register */
+#define                  CAN1_MB22_DATA1  0xffc036c4   /* CAN Controller 1 Mailbox 22 Data 1 Register */
+#define                  CAN1_MB22_DATA2  0xffc036c8   /* CAN Controller 1 Mailbox 22 Data 2 Register */
+#define                  CAN1_MB22_DATA3  0xffc036cc   /* CAN Controller 1 Mailbox 22 Data 3 Register */
+#define                 CAN1_MB22_LENGTH  0xffc036d0   /* CAN Controller 1 Mailbox 22 Length Register */
+#define              CAN1_MB22_TIMESTAMP  0xffc036d4   /* CAN Controller 1 Mailbox 22 Timestamp Register */
+#define                    CAN1_MB22_ID0  0xffc036d8   /* CAN Controller 1 Mailbox 22 ID0 Register */
+#define                    CAN1_MB22_ID1  0xffc036dc   /* CAN Controller 1 Mailbox 22 ID1 Register */
+#define                  CAN1_MB23_DATA0  0xffc036e0   /* CAN Controller 1 Mailbox 23 Data 0 Register */
+#define                  CAN1_MB23_DATA1  0xffc036e4   /* CAN Controller 1 Mailbox 23 Data 1 Register */
+#define                  CAN1_MB23_DATA2  0xffc036e8   /* CAN Controller 1 Mailbox 23 Data 2 Register */
+#define                  CAN1_MB23_DATA3  0xffc036ec   /* CAN Controller 1 Mailbox 23 Data 3 Register */
+#define                 CAN1_MB23_LENGTH  0xffc036f0   /* CAN Controller 1 Mailbox 23 Length Register */
+#define              CAN1_MB23_TIMESTAMP  0xffc036f4   /* CAN Controller 1 Mailbox 23 Timestamp Register */
+#define                    CAN1_MB23_ID0  0xffc036f8   /* CAN Controller 1 Mailbox 23 ID0 Register */
+#define                    CAN1_MB23_ID1  0xffc036fc   /* CAN Controller 1 Mailbox 23 ID1 Register */
+#define                  CAN1_MB24_DATA0  0xffc03700   /* CAN Controller 1 Mailbox 24 Data 0 Register */
+#define                  CAN1_MB24_DATA1  0xffc03704   /* CAN Controller 1 Mailbox 24 Data 1 Register */
+#define                  CAN1_MB24_DATA2  0xffc03708   /* CAN Controller 1 Mailbox 24 Data 2 Register */
+#define                  CAN1_MB24_DATA3  0xffc0370c   /* CAN Controller 1 Mailbox 24 Data 3 Register */
+#define                 CAN1_MB24_LENGTH  0xffc03710   /* CAN Controller 1 Mailbox 24 Length Register */
+#define              CAN1_MB24_TIMESTAMP  0xffc03714   /* CAN Controller 1 Mailbox 24 Timestamp Register */
+#define                    CAN1_MB24_ID0  0xffc03718   /* CAN Controller 1 Mailbox 24 ID0 Register */
+#define                    CAN1_MB24_ID1  0xffc0371c   /* CAN Controller 1 Mailbox 24 ID1 Register */
+#define                  CAN1_MB25_DATA0  0xffc03720   /* CAN Controller 1 Mailbox 25 Data 0 Register */
+#define                  CAN1_MB25_DATA1  0xffc03724   /* CAN Controller 1 Mailbox 25 Data 1 Register */
+#define                  CAN1_MB25_DATA2  0xffc03728   /* CAN Controller 1 Mailbox 25 Data 2 Register */
+#define                  CAN1_MB25_DATA3  0xffc0372c   /* CAN Controller 1 Mailbox 25 Data 3 Register */
+#define                 CAN1_MB25_LENGTH  0xffc03730   /* CAN Controller 1 Mailbox 25 Length Register */
+#define              CAN1_MB25_TIMESTAMP  0xffc03734   /* CAN Controller 1 Mailbox 25 Timestamp Register */
+#define                    CAN1_MB25_ID0  0xffc03738   /* CAN Controller 1 Mailbox 25 ID0 Register */
+#define                    CAN1_MB25_ID1  0xffc0373c   /* CAN Controller 1 Mailbox 25 ID1 Register */
+#define                  CAN1_MB26_DATA0  0xffc03740   /* CAN Controller 1 Mailbox 26 Data 0 Register */
+#define                  CAN1_MB26_DATA1  0xffc03744   /* CAN Controller 1 Mailbox 26 Data 1 Register */
+#define                  CAN1_MB26_DATA2  0xffc03748   /* CAN Controller 1 Mailbox 26 Data 2 Register */
+#define                  CAN1_MB26_DATA3  0xffc0374c   /* CAN Controller 1 Mailbox 26 Data 3 Register */
+#define                 CAN1_MB26_LENGTH  0xffc03750   /* CAN Controller 1 Mailbox 26 Length Register */
+#define              CAN1_MB26_TIMESTAMP  0xffc03754   /* CAN Controller 1 Mailbox 26 Timestamp Register */
+#define                    CAN1_MB26_ID0  0xffc03758   /* CAN Controller 1 Mailbox 26 ID0 Register */
+#define                    CAN1_MB26_ID1  0xffc0375c   /* CAN Controller 1 Mailbox 26 ID1 Register */
+#define                  CAN1_MB27_DATA0  0xffc03760   /* CAN Controller 1 Mailbox 27 Data 0 Register */
+#define                  CAN1_MB27_DATA1  0xffc03764   /* CAN Controller 1 Mailbox 27 Data 1 Register */
+#define                  CAN1_MB27_DATA2  0xffc03768   /* CAN Controller 1 Mailbox 27 Data 2 Register */
+#define                  CAN1_MB27_DATA3  0xffc0376c   /* CAN Controller 1 Mailbox 27 Data 3 Register */
+#define                 CAN1_MB27_LENGTH  0xffc03770   /* CAN Controller 1 Mailbox 27 Length Register */
+#define              CAN1_MB27_TIMESTAMP  0xffc03774   /* CAN Controller 1 Mailbox 27 Timestamp Register */
+#define                    CAN1_MB27_ID0  0xffc03778   /* CAN Controller 1 Mailbox 27 ID0 Register */
+#define                    CAN1_MB27_ID1  0xffc0377c   /* CAN Controller 1 Mailbox 27 ID1 Register */
+#define                  CAN1_MB28_DATA0  0xffc03780   /* CAN Controller 1 Mailbox 28 Data 0 Register */
+#define                  CAN1_MB28_DATA1  0xffc03784   /* CAN Controller 1 Mailbox 28 Data 1 Register */
+#define                  CAN1_MB28_DATA2  0xffc03788   /* CAN Controller 1 Mailbox 28 Data 2 Register */
+#define                  CAN1_MB28_DATA3  0xffc0378c   /* CAN Controller 1 Mailbox 28 Data 3 Register */
+#define                 CAN1_MB28_LENGTH  0xffc03790   /* CAN Controller 1 Mailbox 28 Length Register */
+#define              CAN1_MB28_TIMESTAMP  0xffc03794   /* CAN Controller 1 Mailbox 28 Timestamp Register */
+#define                    CAN1_MB28_ID0  0xffc03798   /* CAN Controller 1 Mailbox 28 ID0 Register */
+#define                    CAN1_MB28_ID1  0xffc0379c   /* CAN Controller 1 Mailbox 28 ID1 Register */
+#define                  CAN1_MB29_DATA0  0xffc037a0   /* CAN Controller 1 Mailbox 29 Data 0 Register */
+#define                  CAN1_MB29_DATA1  0xffc037a4   /* CAN Controller 1 Mailbox 29 Data 1 Register */
+#define                  CAN1_MB29_DATA2  0xffc037a8   /* CAN Controller 1 Mailbox 29 Data 2 Register */
+#define                  CAN1_MB29_DATA3  0xffc037ac   /* CAN Controller 1 Mailbox 29 Data 3 Register */
+#define                 CAN1_MB29_LENGTH  0xffc037b0   /* CAN Controller 1 Mailbox 29 Length Register */
+#define              CAN1_MB29_TIMESTAMP  0xffc037b4   /* CAN Controller 1 Mailbox 29 Timestamp Register */
+#define                    CAN1_MB29_ID0  0xffc037b8   /* CAN Controller 1 Mailbox 29 ID0 Register */
+#define                    CAN1_MB29_ID1  0xffc037bc   /* CAN Controller 1 Mailbox 29 ID1 Register */
+#define                  CAN1_MB30_DATA0  0xffc037c0   /* CAN Controller 1 Mailbox 30 Data 0 Register */
+#define                  CAN1_MB30_DATA1  0xffc037c4   /* CAN Controller 1 Mailbox 30 Data 1 Register */
+#define                  CAN1_MB30_DATA2  0xffc037c8   /* CAN Controller 1 Mailbox 30 Data 2 Register */
+#define                  CAN1_MB30_DATA3  0xffc037cc   /* CAN Controller 1 Mailbox 30 Data 3 Register */
+#define                 CAN1_MB30_LENGTH  0xffc037d0   /* CAN Controller 1 Mailbox 30 Length Register */
+#define              CAN1_MB30_TIMESTAMP  0xffc037d4   /* CAN Controller 1 Mailbox 30 Timestamp Register */
+#define                    CAN1_MB30_ID0  0xffc037d8   /* CAN Controller 1 Mailbox 30 ID0 Register */
+#define                    CAN1_MB30_ID1  0xffc037dc   /* CAN Controller 1 Mailbox 30 ID1 Register */
+#define                  CAN1_MB31_DATA0  0xffc037e0   /* CAN Controller 1 Mailbox 31 Data 0 Register */
+#define                  CAN1_MB31_DATA1  0xffc037e4   /* CAN Controller 1 Mailbox 31 Data 1 Register */
+#define                  CAN1_MB31_DATA2  0xffc037e8   /* CAN Controller 1 Mailbox 31 Data 2 Register */
+#define                  CAN1_MB31_DATA3  0xffc037ec   /* CAN Controller 1 Mailbox 31 Data 3 Register */
+#define                 CAN1_MB31_LENGTH  0xffc037f0   /* CAN Controller 1 Mailbox 31 Length Register */
+#define              CAN1_MB31_TIMESTAMP  0xffc037f4   /* CAN Controller 1 Mailbox 31 Timestamp Register */
+#define                    CAN1_MB31_ID0  0xffc037f8   /* CAN Controller 1 Mailbox 31 ID0 Register */
+#define                    CAN1_MB31_ID1  0xffc037fc   /* CAN Controller 1 Mailbox 31 ID1 Register */
+
+/* ATAPI Registers */
+
+#define                    ATAPI_CONTROL  0xffc03800   /* ATAPI Control Register */
+#define                     ATAPI_STATUS  0xffc03804   /* ATAPI Status Register */
+#define                   ATAPI_DEV_ADDR  0xffc03808   /* ATAPI Device Register Address */
+#define                  ATAPI_DEV_TXBUF  0xffc0380c   /* ATAPI Device Register Write Data */
+#define                  ATAPI_DEV_RXBUF  0xffc03810   /* ATAPI Device Register Read Data */
+#define                   ATAPI_INT_MASK  0xffc03814   /* ATAPI Interrupt Mask Register */
+#define                 ATAPI_INT_STATUS  0xffc03818   /* ATAPI Interrupt Status Register */
+#define                   ATAPI_XFER_LEN  0xffc0381c   /* ATAPI Length of Transfer */
+#define                ATAPI_LINE_STATUS  0xffc03820   /* ATAPI Line Status */
+#define                   ATAPI_SM_STATE  0xffc03824   /* ATAPI State Machine Status */
+#define                  ATAPI_TERMINATE  0xffc03828   /* ATAPI Host Terminate */
+#define                 ATAPI_PIO_TFRCNT  0xffc0382c   /* ATAPI PIO mode transfer count */
+#define                 ATAPI_DMA_TFRCNT  0xffc03830   /* ATAPI DMA mode transfer count */
+#define               ATAPI_UMAIN_TFRCNT  0xffc03834   /* ATAPI UDMAIN transfer count */
+#define             ATAPI_UDMAOUT_TFRCNT  0xffc03838   /* ATAPI UDMAOUT transfer count */
+#define                  ATAPI_REG_TIM_0  0xffc03840   /* ATAPI Register Transfer Timing 0 */
+#define                  ATAPI_PIO_TIM_0  0xffc03844   /* ATAPI PIO Timing 0 Register */
+#define                  ATAPI_PIO_TIM_1  0xffc03848   /* ATAPI PIO Timing 1 Register */
+#define                ATAPI_MULTI_TIM_0  0xffc03850   /* ATAPI Multi-DMA Timing 0 Register */
+#define                ATAPI_MULTI_TIM_1  0xffc03854   /* ATAPI Multi-DMA Timing 1 Register */
+#define                ATAPI_MULTI_TIM_2  0xffc03858   /* ATAPI Multi-DMA Timing 2 Register */
+#define                ATAPI_ULTRA_TIM_0  0xffc03860   /* ATAPI Ultra-DMA Timing 0 Register */
+#define                ATAPI_ULTRA_TIM_1  0xffc03864   /* ATAPI Ultra-DMA Timing 1 Register */
+#define                ATAPI_ULTRA_TIM_2  0xffc03868   /* ATAPI Ultra-DMA Timing 2 Register */
+#define                ATAPI_ULTRA_TIM_3  0xffc0386c   /* ATAPI Ultra-DMA Timing 3 Register */
+
+/* SDH Registers */
+
+#define                      SDH_PWR_CTL  0xffc03900   /* SDH Power Control */
+#define                      SDH_CLK_CTL  0xffc03904   /* SDH Clock Control */
+#define                     SDH_ARGUMENT  0xffc03908   /* SDH Argument */
+#define                      SDH_COMMAND  0xffc0390c   /* SDH Command */
+#define                     SDH_RESP_CMD  0xffc03910   /* SDH Response Command */
+#define                    SDH_RESPONSE0  0xffc03914   /* SDH Response0 */
+#define                    SDH_RESPONSE1  0xffc03918   /* SDH Response1 */
+#define                    SDH_RESPONSE2  0xffc0391c   /* SDH Response2 */
+#define                    SDH_RESPONSE3  0xffc03920   /* SDH Response3 */
+#define                   SDH_DATA_TIMER  0xffc03924   /* SDH Data Timer */
+#define                    SDH_DATA_LGTH  0xffc03928   /* SDH Data Length */
+#define                     SDH_DATA_CTL  0xffc0392c   /* SDH Data Control */
+#define                     SDH_DATA_CNT  0xffc03930   /* SDH Data Counter */
+#define                       SDH_STATUS  0xffc03934   /* SDH Status */
+#define                   SDH_STATUS_CLR  0xffc03938   /* SDH Status Clear */
+#define                        SDH_MASK0  0xffc0393c   /* SDH Interrupt0 Mask */
+#define                        SDH_MASK1  0xffc03940   /* SDH Interrupt1 Mask */
+#define                     SDH_FIFO_CNT  0xffc03948   /* SDH FIFO Counter */
+#define                         SDH_FIFO  0xffc03980   /* SDH Data FIFO */
+#define                     SDH_E_STATUS  0xffc039c0   /* SDH Exception Status */
+#define                       SDH_E_MASK  0xffc039c4   /* SDH Exception Mask */
+#define                          SDH_CFG  0xffc039c8   /* SDH Configuration */
+#define                   SDH_RD_WAIT_EN  0xffc039cc   /* SDH Read Wait Enable */
+#define                         SDH_PID0  0xffc039d0   /* SDH Peripheral Identification0 */
+#define                         SDH_PID1  0xffc039d4   /* SDH Peripheral Identification1 */
+#define                         SDH_PID2  0xffc039d8   /* SDH Peripheral Identification2 */
+#define                         SDH_PID3  0xffc039dc   /* SDH Peripheral Identification3 */
+#define                         SDH_PID4  0xffc039e0   /* SDH Peripheral Identification4 */
+#define                         SDH_PID5  0xffc039e4   /* SDH Peripheral Identification5 */
+#define                         SDH_PID6  0xffc039e8   /* SDH Peripheral Identification6 */
+#define                         SDH_PID7  0xffc039ec   /* SDH Peripheral Identification7 */
+
+/* HOST Port Registers */
+
+#define                     HOST_CONTROL  0xffc03a00   /* HOST Control Register */
+#define                      HOST_STATUS  0xffc03a04   /* HOST Status Register */
+#define                     HOST_TIMEOUT  0xffc03a08   /* HOST Acknowledge Mode Timeout Register */
+
+/* USB Control Registers */
+
+#define                        USB_FADDR  0xffc03c00   /* Function address register */
+#define                        USB_POWER  0xffc03c04   /* Power management register */
+#define                       USB_INTRTX  0xffc03c08   /* Interrupt register for endpoint 0 and Tx endpoint 1 to 7 */
+#define                       USB_INTRRX  0xffc03c0c   /* Interrupt register for Rx endpoints 1 to 7 */
+#define                      USB_INTRTXE  0xffc03c10   /* Interrupt enable register for IntrTx */
+#define                      USB_INTRRXE  0xffc03c14   /* Interrupt enable register for IntrRx */
+#define                      USB_INTRUSB  0xffc03c18   /* Interrupt register for common USB interrupts */
+#define                     USB_INTRUSBE  0xffc03c1c   /* Interrupt enable register for IntrUSB */
+#define                        USB_FRAME  0xffc03c20   /* USB frame number */
+#define                        USB_INDEX  0xffc03c24   /* Index register for selecting the indexed endpoint registers */
+#define                     USB_TESTMODE  0xffc03c28   /* Enabled USB 20 test modes */
+#define                     USB_GLOBINTR  0xffc03c2c   /* Global Interrupt Mask register and Wakeup Exception Interrupt */
+#define                   USB_GLOBAL_CTL  0xffc03c30   /* Global Clock Control for the core */
+
+/* USB Packet Control Registers */
+
+#define                USB_TX_MAX_PACKET  0xffc03c40   /* Maximum packet size for Host Tx endpoint */
+#define                         USB_CSR0  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                        USB_TXCSR  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                USB_RX_MAX_PACKET  0xffc03c48   /* Maximum packet size for Host Rx endpoint */
+#define                        USB_RXCSR  0xffc03c4c   /* Control Status register for Host Rx endpoint */
+#define                       USB_COUNT0  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                      USB_RXCOUNT  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                       USB_TXTYPE  0xffc03c54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint */
+#define                    USB_NAKLIMIT0  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                   USB_TXINTERVAL  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                       USB_RXTYPE  0xffc03c5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint */
+#define                   USB_RXINTERVAL  0xffc03c60   /* Sets the polling interval for Interrupt and Isochronous transfers or the NAK response timeout on Bulk transfers */
+#define                      USB_TXCOUNT  0xffc03c68   /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* USB Endpoint FIFO Registers */
+
+#define                     USB_EP0_FIFO  0xffc03c80   /* Endpoint 0 FIFO */
+#define                     USB_EP1_FIFO  0xffc03c88   /* Endpoint 1 FIFO */
+#define                     USB_EP2_FIFO  0xffc03c90   /* Endpoint 2 FIFO */
+#define                     USB_EP3_FIFO  0xffc03c98   /* Endpoint 3 FIFO */
+#define                     USB_EP4_FIFO  0xffc03ca0   /* Endpoint 4 FIFO */
+#define                     USB_EP5_FIFO  0xffc03ca8   /* Endpoint 5 FIFO */
+#define                     USB_EP6_FIFO  0xffc03cb0   /* Endpoint 6 FIFO */
+#define                     USB_EP7_FIFO  0xffc03cb8   /* Endpoint 7 FIFO */
+
+/* USB OTG Control Registers */
+
+#define                  USB_OTG_DEV_CTL  0xffc03d00   /* OTG Device Control Register */
+#define                 USB_OTG_VBUS_IRQ  0xffc03d04   /* OTG VBUS Control Interrupts */
+#define                USB_OTG_VBUS_MASK  0xffc03d08   /* VBUS Control Interrupt Enable */
+
+/* USB Phy Control Registers */
+
+#define                     USB_LINKINFO  0xffc03d48   /* Enables programming of some PHY-side delays */
+#define                        USB_VPLEN  0xffc03d4c   /* Determines duration of VBUS pulse for VBUS charging */
+#define                      USB_HS_EOF1  0xffc03d50   /* Time buffer for High-Speed transactions */
+#define                      USB_FS_EOF1  0xffc03d54   /* Time buffer for Full-Speed transactions */
+#define                      USB_LS_EOF1  0xffc03d58   /* Time buffer for Low-Speed transactions */
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define                   USB_APHY_CNTRL  0xffc03de0   /* Register that increases visibility of Analog PHY */
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define                   USB_APHY_CALIB  0xffc03de4   /* Register used to set some calibration values */
+#define                  USB_APHY_CNTRL2  0xffc03de8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define                     USB_PHY_TEST  0xffc03dec   /* Used for reducing simulation time and simplifies FIFO testability */
+#define                  USB_PLLOSC_CTRL  0xffc03df0   /* Used to program different parameters for USB PLL and Oscillator */
+#define                   USB_SRP_CLKDIV  0xffc03df4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
+
+/* USB Endpoint 0 Control Registers */
+
+#define                USB_EP_NI0_TXMAXP  0xffc03e00   /* Maximum packet size for Host Tx endpoint0 */
+#define                 USB_EP_NI0_TXCSR  0xffc03e04   /* Control Status register for endpoint 0 */
+#define                USB_EP_NI0_RXMAXP  0xffc03e08   /* Maximum packet size for Host Rx endpoint0 */
+#define                 USB_EP_NI0_RXCSR  0xffc03e0c   /* Control Status register for Host Rx endpoint0 */
+#define               USB_EP_NI0_RXCOUNT  0xffc03e10   /* Number of bytes received in endpoint 0 FIFO */
+#define                USB_EP_NI0_TXTYPE  0xffc03e14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint0 */
+#define            USB_EP_NI0_TXINTERVAL  0xffc03e18   /* Sets the NAK response timeout on Endpoint 0 */
+#define                USB_EP_NI0_RXTYPE  0xffc03e1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint0 */
+#define            USB_EP_NI0_RXINTERVAL  0xffc03e20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint0 */
+
+/* USB Endpoint 1 Control Registers */
+
+#define               USB_EP_NI0_TXCOUNT  0xffc03e28   /* Number of bytes to be written to the endpoint0 Tx FIFO */
+#define                USB_EP_NI1_TXMAXP  0xffc03e40   /* Maximum packet size for Host Tx endpoint1 */
+#define                 USB_EP_NI1_TXCSR  0xffc03e44   /* Control Status register for endpoint1 */
+#define                USB_EP_NI1_RXMAXP  0xffc03e48   /* Maximum packet size for Host Rx endpoint1 */
+#define                 USB_EP_NI1_RXCSR  0xffc03e4c   /* Control Status register for Host Rx endpoint1 */
+#define               USB_EP_NI1_RXCOUNT  0xffc03e50   /* Number of bytes received in endpoint1 FIFO */
+#define                USB_EP_NI1_TXTYPE  0xffc03e54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint1 */
+#define            USB_EP_NI1_TXINTERVAL  0xffc03e58   /* Sets the NAK response timeout on Endpoint1 */
+#define                USB_EP_NI1_RXTYPE  0xffc03e5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint1 */
+#define            USB_EP_NI1_RXINTERVAL  0xffc03e60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint1 */
+
+/* USB Endpoint 2 Control Registers */
+
+#define               USB_EP_NI1_TXCOUNT  0xffc03e68   /* Number of bytes to be written to the+H102 endpoint1 Tx FIFO */
+#define                USB_EP_NI2_TXMAXP  0xffc03e80   /* Maximum packet size for Host Tx endpoint2 */
+#define                 USB_EP_NI2_TXCSR  0xffc03e84   /* Control Status register for endpoint2 */
+#define                USB_EP_NI2_RXMAXP  0xffc03e88   /* Maximum packet size for Host Rx endpoint2 */
+#define                 USB_EP_NI2_RXCSR  0xffc03e8c   /* Control Status register for Host Rx endpoint2 */
+#define               USB_EP_NI2_RXCOUNT  0xffc03e90   /* Number of bytes received in endpoint2 FIFO */
+#define                USB_EP_NI2_TXTYPE  0xffc03e94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint2 */
+#define            USB_EP_NI2_TXINTERVAL  0xffc03e98   /* Sets the NAK response timeout on Endpoint2 */
+#define                USB_EP_NI2_RXTYPE  0xffc03e9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint2 */
+#define            USB_EP_NI2_RXINTERVAL  0xffc03ea0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint2 */
+
+/* USB Endpoint 3 Control Registers */
+
+#define               USB_EP_NI2_TXCOUNT  0xffc03ea8   /* Number of bytes to be written to the endpoint2 Tx FIFO */
+#define                USB_EP_NI3_TXMAXP  0xffc03ec0   /* Maximum packet size for Host Tx endpoint3 */
+#define                 USB_EP_NI3_TXCSR  0xffc03ec4   /* Control Status register for endpoint3 */
+#define                USB_EP_NI3_RXMAXP  0xffc03ec8   /* Maximum packet size for Host Rx endpoint3 */
+#define                 USB_EP_NI3_RXCSR  0xffc03ecc   /* Control Status register for Host Rx endpoint3 */
+#define               USB_EP_NI3_RXCOUNT  0xffc03ed0   /* Number of bytes received in endpoint3 FIFO */
+#define                USB_EP_NI3_TXTYPE  0xffc03ed4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint3 */
+#define            USB_EP_NI3_TXINTERVAL  0xffc03ed8   /* Sets the NAK response timeout on Endpoint3 */
+#define                USB_EP_NI3_RXTYPE  0xffc03edc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint3 */
+#define            USB_EP_NI3_RXINTERVAL  0xffc03ee0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint3 */
+
+/* USB Endpoint 4 Control Registers */
+
+#define               USB_EP_NI3_TXCOUNT  0xffc03ee8   /* Number of bytes to be written to the H124endpoint3 Tx FIFO */
+#define                USB_EP_NI4_TXMAXP  0xffc03f00   /* Maximum packet size for Host Tx endpoint4 */
+#define                 USB_EP_NI4_TXCSR  0xffc03f04   /* Control Status register for endpoint4 */
+#define                USB_EP_NI4_RXMAXP  0xffc03f08   /* Maximum packet size for Host Rx endpoint4 */
+#define                 USB_EP_NI4_RXCSR  0xffc03f0c   /* Control Status register for Host Rx endpoint4 */
+#define               USB_EP_NI4_RXCOUNT  0xffc03f10   /* Number of bytes received in endpoint4 FIFO */
+#define                USB_EP_NI4_TXTYPE  0xffc03f14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint4 */
+#define            USB_EP_NI4_TXINTERVAL  0xffc03f18   /* Sets the NAK response timeout on Endpoint4 */
+#define                USB_EP_NI4_RXTYPE  0xffc03f1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint4 */
+#define            USB_EP_NI4_RXINTERVAL  0xffc03f20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint4 */
+
+/* USB Endpoint 5 Control Registers */
+
+#define               USB_EP_NI4_TXCOUNT  0xffc03f28   /* Number of bytes to be written to the endpoint4 Tx FIFO */
+#define                USB_EP_NI5_TXMAXP  0xffc03f40   /* Maximum packet size for Host Tx endpoint5 */
+#define                 USB_EP_NI5_TXCSR  0xffc03f44   /* Control Status register for endpoint5 */
+#define                USB_EP_NI5_RXMAXP  0xffc03f48   /* Maximum packet size for Host Rx endpoint5 */
+#define                 USB_EP_NI5_RXCSR  0xffc03f4c   /* Control Status register for Host Rx endpoint5 */
+#define               USB_EP_NI5_RXCOUNT  0xffc03f50   /* Number of bytes received in endpoint5 FIFO */
+#define                USB_EP_NI5_TXTYPE  0xffc03f54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint5 */
+#define            USB_EP_NI5_TXINTERVAL  0xffc03f58   /* Sets the NAK response timeout on Endpoint5 */
+#define                USB_EP_NI5_RXTYPE  0xffc03f5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint5 */
+#define            USB_EP_NI5_RXINTERVAL  0xffc03f60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint5 */
+
+/* USB Endpoint 6 Control Registers */
+
+#define               USB_EP_NI5_TXCOUNT  0xffc03f68   /* Number of bytes to be written to the H145endpoint5 Tx FIFO */
+#define                USB_EP_NI6_TXMAXP  0xffc03f80   /* Maximum packet size for Host Tx endpoint6 */
+#define                 USB_EP_NI6_TXCSR  0xffc03f84   /* Control Status register for endpoint6 */
+#define                USB_EP_NI6_RXMAXP  0xffc03f88   /* Maximum packet size for Host Rx endpoint6 */
+#define                 USB_EP_NI6_RXCSR  0xffc03f8c   /* Control Status register for Host Rx endpoint6 */
+#define               USB_EP_NI6_RXCOUNT  0xffc03f90   /* Number of bytes received in endpoint6 FIFO */
+#define                USB_EP_NI6_TXTYPE  0xffc03f94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint6 */
+#define            USB_EP_NI6_TXINTERVAL  0xffc03f98   /* Sets the NAK response timeout on Endpoint6 */
+#define                USB_EP_NI6_RXTYPE  0xffc03f9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint6 */
+#define            USB_EP_NI6_RXINTERVAL  0xffc03fa0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint6 */
+
+/* USB Endpoint 7 Control Registers */
+
+#define               USB_EP_NI6_TXCOUNT  0xffc03fa8   /* Number of bytes to be written to the endpoint6 Tx FIFO */
+#define                USB_EP_NI7_TXMAXP  0xffc03fc0   /* Maximum packet size for Host Tx endpoint7 */
+#define                 USB_EP_NI7_TXCSR  0xffc03fc4   /* Control Status register for endpoint7 */
+#define                USB_EP_NI7_RXMAXP  0xffc03fc8   /* Maximum packet size for Host Rx endpoint7 */
+#define                 USB_EP_NI7_RXCSR  0xffc03fcc   /* Control Status register for Host Rx endpoint7 */
+#define               USB_EP_NI7_RXCOUNT  0xffc03fd0   /* Number of bytes received in endpoint7 FIFO */
+#define                USB_EP_NI7_TXTYPE  0xffc03fd4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint7 */
+#define            USB_EP_NI7_TXINTERVAL  0xffc03fd8   /* Sets the NAK response timeout on Endpoint7 */
+#define                USB_EP_NI7_RXTYPE  0xffc03fdc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint7 */
+#define            USB_EP_NI7_RXINTERVAL  0xffc03ff0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint7 */
+#define               USB_EP_NI7_TXCOUNT  0xffc03ff8   /* Number of bytes to be written to the endpoint7 Tx FIFO */
+#define                USB_DMA_INTERRUPT  0xffc04000   /* Indicates pending interrupts for the DMA channels */
+
+/* USB Channel 0 Config Registers */
+
+#define                  USB_DMA0CONTROL  0xffc04004   /* DMA master channel 0 configuration */
+#define                  USB_DMA0ADDRLOW  0xffc04008   /* Lower 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0ADDRHIGH  0xffc0400c   /* Upper 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0COUNTLOW  0xffc04010   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 0 */
+#define                USB_DMA0COUNTHIGH  0xffc04014   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 0 */
+
+/* USB Channel 1 Config Registers */
+
+#define                  USB_DMA1CONTROL  0xffc04024   /* DMA master channel 1 configuration */
+#define                  USB_DMA1ADDRLOW  0xffc04028   /* Lower 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1ADDRHIGH  0xffc0402c   /* Upper 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1COUNTLOW  0xffc04030   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 1 */
+#define                USB_DMA1COUNTHIGH  0xffc04034   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 1 */
+
+/* USB Channel 2 Config Registers */
+
+#define                  USB_DMA2CONTROL  0xffc04044   /* DMA master channel 2 configuration */
+#define                  USB_DMA2ADDRLOW  0xffc04048   /* Lower 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2ADDRHIGH  0xffc0404c   /* Upper 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2COUNTLOW  0xffc04050   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 2 */
+#define                USB_DMA2COUNTHIGH  0xffc04054   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 2 */
+
+/* USB Channel 3 Config Registers */
+
+#define                  USB_DMA3CONTROL  0xffc04064   /* DMA master channel 3 configuration */
+#define                  USB_DMA3ADDRLOW  0xffc04068   /* Lower 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3ADDRHIGH  0xffc0406c   /* Upper 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3COUNTLOW  0xffc04070   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 3 */
+#define                USB_DMA3COUNTHIGH  0xffc04074   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 3 */
+
+/* USB Channel 4 Config Registers */
+
+#define                  USB_DMA4CONTROL  0xffc04084   /* DMA master channel 4 configuration */
+#define                  USB_DMA4ADDRLOW  0xffc04088   /* Lower 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4ADDRHIGH  0xffc0408c   /* Upper 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4COUNTLOW  0xffc04090   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 4 */
+#define                USB_DMA4COUNTHIGH  0xffc04094   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 4 */
+
+/* USB Channel 5 Config Registers */
+
+#define                  USB_DMA5CONTROL  0xffc040a4   /* DMA master channel 5 configuration */
+#define                  USB_DMA5ADDRLOW  0xffc040a8   /* Lower 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5ADDRHIGH  0xffc040ac   /* Upper 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5COUNTLOW  0xffc040b0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 5 */
+#define                USB_DMA5COUNTHIGH  0xffc040b4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 5 */
+
+/* USB Channel 6 Config Registers */
+
+#define                  USB_DMA6CONTROL  0xffc040c4   /* DMA master channel 6 configuration */
+#define                  USB_DMA6ADDRLOW  0xffc040c8   /* Lower 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6ADDRHIGH  0xffc040cc   /* Upper 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6COUNTLOW  0xffc040d0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 6 */
+#define                USB_DMA6COUNTHIGH  0xffc040d4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 6 */
+
+/* USB Channel 7 Config Registers */
+
+#define                  USB_DMA7CONTROL  0xffc040e4   /* DMA master channel 7 configuration */
+#define                  USB_DMA7ADDRLOW  0xffc040e8   /* Lower 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7ADDRHIGH  0xffc040ec   /* Upper 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7COUNTLOW  0xffc040f0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 7 */
+#define                USB_DMA7COUNTHIGH  0xffc040f4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 7 */
+
+/* Keypad Registers */
+
+#define                         KPAD_CTL  0xffc04100   /* Controls keypad module enable and disable */
+#define                    KPAD_PRESCALE  0xffc04104   /* Establish a time base for programing the KPAD_MSEL register */
+#define                        KPAD_MSEL  0xffc04108   /* Selects delay parameters for keypad interface sensitivity */
+#define                      KPAD_ROWCOL  0xffc0410c   /* Captures the row and column output values of the keys pressed */
+#define                        KPAD_STAT  0xffc04110   /* Holds and clears the status of the keypad interface interrupt */
+#define                    KPAD_SOFTEVAL  0xffc04114   /* Lets software force keypad interface to check for keys being pressed */
+
+/* Pixel Compositor (PIXC) Registers */
+
+#define                         PIXC_CTL  0xffc04400   /* Overlay enable, resampling mode, I/O data format, transparency enable, watermark level, FIFO status */
+#define                         PIXC_PPL  0xffc04404   /* Holds the number of pixels per line of the display */
+#define                         PIXC_LPF  0xffc04408   /* Holds the number of lines per frame of the display */
+#define                     PIXC_AHSTART  0xffc0440c   /* Contains horizontal start pixel information of the overlay data (set A) */
+#define                       PIXC_AHEND  0xffc04410   /* Contains horizontal end pixel information of the overlay data (set A) */
+#define                     PIXC_AVSTART  0xffc04414   /* Contains vertical start pixel information of the overlay data (set A) */
+#define                       PIXC_AVEND  0xffc04418   /* Contains vertical end pixel information of the overlay data (set A) */
+#define                     PIXC_ATRANSP  0xffc0441c   /* Contains the transparency ratio (set A) */
+#define                     PIXC_BHSTART  0xffc04420   /* Contains horizontal start pixel information of the overlay data (set B) */
+#define                       PIXC_BHEND  0xffc04424   /* Contains horizontal end pixel information of the overlay data (set B) */
+#define                     PIXC_BVSTART  0xffc04428   /* Contains vertical start pixel information of the overlay data (set B) */
+#define                       PIXC_BVEND  0xffc0442c   /* Contains vertical end pixel information of the overlay data (set B) */
+#define                     PIXC_BTRANSP  0xffc04430   /* Contains the transparency ratio (set B) */
+#define                    PIXC_INTRSTAT  0xffc0443c   /* Overlay interrupt configuration/status */
+#define                       PIXC_RYCON  0xffc04440   /* Color space conversion matrix register. Contains the R/Y conversion coefficients */
+#define                       PIXC_GUCON  0xffc04444   /* Color space conversion matrix register. Contains the G/U conversion coefficients */
+#define                       PIXC_BVCON  0xffc04448   /* Color space conversion matrix register. Contains the B/V conversion coefficients */
+#define                      PIXC_CCBIAS  0xffc0444c   /* Bias values for the color space conversion matrix */
+#define                          PIXC_TC  0xffc04450   /* Holds the transparent color value */
+
+/* Handshake MDMA 0 Registers */
+
+#define                   HMDMA0_CONTROL  0xffc04500   /* Handshake MDMA0 Control Register */
+#define                    HMDMA0_ECINIT  0xffc04504   /* Handshake MDMA0 Initial Edge Count Register */
+#define                    HMDMA0_BCINIT  0xffc04508   /* Handshake MDMA0 Initial Block Count Register */
+#define                  HMDMA0_ECURGENT  0xffc0450c   /* Handshake MDMA0 Urgent Edge Count Threshhold Register */
+#define                HMDMA0_ECOVERFLOW  0xffc04510   /* Handshake MDMA0 Edge Count Overflow Interrupt Register */
+#define                    HMDMA0_ECOUNT  0xffc04514   /* Handshake MDMA0 Current Edge Count Register */
+#define                    HMDMA0_BCOUNT  0xffc04518   /* Handshake MDMA0 Current Block Count Register */
+
+/* Handshake MDMA 1 Registers */
+
+#define                   HMDMA1_CONTROL  0xffc04540   /* Handshake MDMA1 Control Register */
+#define                    HMDMA1_ECINIT  0xffc04544   /* Handshake MDMA1 Initial Edge Count Register */
+#define                    HMDMA1_BCINIT  0xffc04548   /* Handshake MDMA1 Initial Block Count Register */
+#define                  HMDMA1_ECURGENT  0xffc0454c   /* Handshake MDMA1 Urgent Edge Count Threshhold Register */
+#define                HMDMA1_ECOVERFLOW  0xffc04550   /* Handshake MDMA1 Edge Count Overflow Interrupt Register */
+#define                    HMDMA1_ECOUNT  0xffc04554   /* Handshake MDMA1 Current Edge Count Register */
+#define                    HMDMA1_BCOUNT  0xffc04558   /* Handshake MDMA1 Current Block Count Register */
+
+
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for PIXC_CTL */
+
+#define                   PIXC_EN  0x1        /* Pixel Compositor Enable */
+#define                  OVR_A_EN  0x2        /* Overlay A Enable */
+#define                  OVR_B_EN  0x4        /* Overlay B Enable */
+#define                  IMG_FORM  0x8        /* Image Data Format */
+#define                  OVR_FORM  0x10       /* Overlay Data Format */
+#define                  OUT_FORM  0x20       /* Output Data Format */
+#define                   UDS_MOD  0x40       /* Resampling Mode */
+#define                     TC_EN  0x80       /* Transparent Color Enable */
+#define                  IMG_STAT  0x300      /* Image FIFO Status */
+#define                  OVR_STAT  0xc00      /* Overlay FIFO Status */
+#define                    WM_LVL  0x3000     /* FIFO Watermark Level */
+
+/* Bit masks for PIXC_AHSTART */
+
+#define                  A_HSTART  0xfff      /* Horizontal Start Coordinates */
+
+/* Bit masks for PIXC_AHEND */
+
+#define                    A_HEND  0xfff      /* Horizontal End Coordinates */
+
+/* Bit masks for PIXC_AVSTART */
+
+#define                  A_VSTART  0x3ff      /* Vertical Start Coordinates */
+
+/* Bit masks for PIXC_AVEND */
+
+#define                    A_VEND  0x3ff      /* Vertical End Coordinates */
+
+/* Bit masks for PIXC_ATRANSP */
+
+#define                  A_TRANSP  0xf        /* Transparency Value */
+
+/* Bit masks for PIXC_BHSTART */
+
+#define                  B_HSTART  0xfff      /* Horizontal Start Coordinates */
+
+/* Bit masks for PIXC_BHEND */
+
+#define                    B_HEND  0xfff      /* Horizontal End Coordinates */
+
+/* Bit masks for PIXC_BVSTART */
+
+#define                  B_VSTART  0x3ff      /* Vertical Start Coordinates */
+
+/* Bit masks for PIXC_BVEND */
+
+#define                    B_VEND  0x3ff      /* Vertical End Coordinates */
+
+/* Bit masks for PIXC_BTRANSP */
+
+#define                  B_TRANSP  0xf        /* Transparency Value */
+
+/* Bit masks for PIXC_INTRSTAT */
+
+#define                OVR_INT_EN  0x1        /* Interrupt at End of Last Valid Overlay */
+#define                FRM_INT_EN  0x2        /* Interrupt at End of Frame */
+#define              OVR_INT_STAT  0x4        /* Overlay Interrupt Status */
+#define              FRM_INT_STAT  0x8        /* Frame Interrupt Status */
+
+/* Bit masks for PIXC_RYCON */
+
+#define                       A11  0x3ff      /* A11 in the Coefficient Matrix */
+#define                       A12  0xffc00    /* A12 in the Coefficient Matrix */
+#define                       A13  0x3ff00000 /* A13 in the Coefficient Matrix */
+#define                  RY_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_GUCON */
+
+#define                       A21  0x3ff      /* A21 in the Coefficient Matrix */
+#define                       A22  0xffc00    /* A22 in the Coefficient Matrix */
+#define                       A23  0x3ff00000 /* A23 in the Coefficient Matrix */
+#define                  GU_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_BVCON */
+
+#define                       A31  0x3ff      /* A31 in the Coefficient Matrix */
+#define                       A32  0xffc00    /* A32 in the Coefficient Matrix */
+#define                       A33  0x3ff00000 /* A33 in the Coefficient Matrix */
+#define                  BV_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_CCBIAS */
+
+#define                       A14  0x3ff      /* A14 in the Bias Vector */
+#define                       A24  0xffc00    /* A24 in the Bias Vector */
+#define                       A34  0x3ff00000 /* A34 in the Bias Vector */
+
+/* Bit masks for PIXC_TC */
+
+#define                  RY_TRANS  0xff       /* Transparent Color - R/Y Component */
+#define                  GU_TRANS  0xff00     /* Transparent Color - G/U Component */
+#define                  BV_TRANS  0xff0000   /* Transparent Color - B/V Component */
+
+/* Bit masks for HOST_CONTROL */
+
+#define                   HOST_EN  0x1        /* Host Enable */
+#define                  HOST_END  0x2        /* Host Endianess */
+#define                 DATA_SIZE  0x4        /* Data Size */
+#define                  HOST_RST  0x8        /* Host Reset */
+#define                  HRDY_OVR  0x20       /* Host Ready Override */
+#define                  INT_MODE  0x40       /* Interrupt Mode */
+#define                     BT_EN  0x80       /* Bus Timeout Enable */
+#define                       EHW  0x100      /* Enable Host Write */
+#define                       EHR  0x200      /* Enable Host Read */
+#define                       BDR  0x400      /* Burst DMA Requests */
+
+/* Bit masks for HOST_STATUS */
+
+#define                     READY  0x1        /* DMA Ready */
+#define                  FIFOFULL  0x2        /* FIFO Full */
+#define                 FIFOEMPTY  0x4        /* FIFO Empty */
+#define                  COMPLETE  0x8        /* DMA Complete */
+#define                      HSHK  0x10       /* Host Handshake */
+#define                   TIMEOUT  0x20       /* Host Timeout */
+#define                      HIRQ  0x40       /* Host Interrupt Request */
+#define                ALLOW_CNFG  0x80       /* Allow New Configuration */
+#define                   DMA_DIR  0x100      /* DMA Direction */
+#define                       BTE  0x200      /* Bus Timeout Enabled */
+
+/* Bit masks for HOST_TIMEOUT */
+
+#define             COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
+
+/* Bit masks for KPAD_CTL */
+
+#define                   KPAD_EN  0x1        /* Keypad Enable */
+#define              KPAD_IRQMODE  0x6        /* Key Press Interrupt Enable */
+#define                KPAD_ROWEN  0x1c00     /* Row Enable Width */
+#define                KPAD_COLEN  0xe000     /* Column Enable Width */
+
+/* Bit masks for KPAD_PRESCALE */
+
+#define         KPAD_PRESCALE_VAL  0x3f       /* Key Prescale Value */
+
+/* Bit masks for KPAD_MSEL */
+
+#define                DBON_SCALE  0xff       /* Debounce Scale Value */
+#define              COLDRV_SCALE  0xff00     /* Column Driver Scale Value */
+
+/* Bit masks for KPAD_ROWCOL */
+
+#define                  KPAD_ROW  0xff       /* Rows Pressed */
+#define                  KPAD_COL  0xff00     /* Columns Pressed */
+
+/* Bit masks for KPAD_STAT */
+
+#define                  KPAD_IRQ  0x1        /* Keypad Interrupt Status */
+#define              KPAD_MROWCOL  0x6        /* Multiple Row/Column Keypress Status */
+#define              KPAD_PRESSED  0x8        /* Key press current status */
+
+/* Bit masks for KPAD_SOFTEVAL */
+
+#define           KPAD_SOFTEVAL_E  0x2        /* Software Programmable Force Evaluate */
+
+/* Bit masks for SDH_COMMAND */
+
+#define                   CMD_IDX  0x3f       /* Command Index */
+#define                   CMD_RSP  0x40       /* Response */
+#define                 CMD_L_RSP  0x80       /* Long Response */
+#define                 CMD_INT_E  0x100      /* Command Interrupt */
+#define                CMD_PEND_E  0x200      /* Command Pending */
+#define                     CMD_E  0x400      /* Command Enable */
+
+/* Bit masks for SDH_PWR_CTL */
+
+#define                    PWR_ON  0x3        /* Power On */
+#if 0
+#define                       TBD  0x3c       /* TBD */
+#endif
+#define                 SD_CMD_OD  0x40       /* Open Drain Output */
+#define                   ROD_CTL  0x80       /* Rod Control */
+
+/* Bit masks for SDH_CLK_CTL */
+
+#define                    CLKDIV  0xff       /* MC_CLK Divisor */
+#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
+#define                  PWR_SV_E  0x200      /* Power Save Enable */
+#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
+#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
+
+/* Bit masks for SDH_RESP_CMD */
+
+#define                  RESP_CMD  0x3f       /* Response Command */
+
+/* Bit masks for SDH_DATA_CTL */
+
+#define                     DTX_E  0x1        /* Data Transfer Enable */
+#define                   DTX_DIR  0x2        /* Data Transfer Direction */
+#define                  DTX_MODE  0x4        /* Data Transfer Mode */
+#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
+#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
+
+/* Bit masks for SDH_STATUS */
+
+#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
+#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
+#define               CMD_TIMEOUT  0x4        /* CMD Time Out */
+#define               DAT_TIMEOUT  0x8        /* Data Time Out */
+#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
+#define                RX_OVERRUN  0x20       /* Receive Overrun */
+#define              CMD_RESP_END  0x40       /* CMD Response End */
+#define                  CMD_SENT  0x80       /* CMD Sent */
+#define                   DAT_END  0x100      /* Data End */
+#define             START_BIT_ERR  0x200      /* Start Bit Error */
+#define               DAT_BLK_END  0x400      /* Data Block End */
+#define                   CMD_ACT  0x800      /* CMD Active */
+#define                    TX_ACT  0x1000     /* Transmit Active */
+#define                    RX_ACT  0x2000     /* Receive Active */
+#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
+#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
+#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
+#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
+#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
+#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
+#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
+#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
+
+/* Bit masks for SDH_STATUS_CLR */
+
+#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
+#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
+#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
+#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
+#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
+#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
+#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
+#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
+#define              DAT_END_STAT  0x100      /* Data End Status */
+#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
+#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
+
+/* Bit masks for SDH_MASK0 */
+
+#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
+#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
+#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
+#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
+#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
+#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
+#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
+#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
+#define              DAT_END_MASK  0x100      /* Data End Mask */
+#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
+#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
+#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
+#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
+#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
+#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
+#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
+#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
+#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
+#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
+#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
+#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
+#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
+
+/* Bit masks for SDH_FIFO_CNT */
+
+#define                FIFO_COUNT  0x7fff     /* FIFO Count */
+
+/* Bit masks for SDH_E_STATUS */
+
+#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
+#define               SD_CARD_DET  0x10       /* SD Card Detect */
+
+/* Bit masks for SDH_E_MASK */
+
+#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
+#define                   SCD_MSK  0x40       /* Mask Card Detect */
+
+/* Bit masks for SDH_CFG */
+
+#define                   CLKS_EN  0x1        /* Clocks Enable */
+#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
+#define                       MWE  0x8        /* Moving Window Enable */
+#define                    SD_RST  0x10       /* SDMMC Reset */
+#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
+#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
+#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
+
+/* Bit masks for SDH_RD_WAIT_EN */
+
+#define                       RWR  0x1        /* Read Wait Request */
+
+/* Bit masks for ATAPI_CONTROL */
+
+#define                 PIO_START  0x1        /* Start PIO/Reg Op */
+#define               MULTI_START  0x2        /* Start Multi-DMA Op */
+#define               ULTRA_START  0x4        /* Start Ultra-DMA Op */
+#define                  XFER_DIR  0x8        /* Transfer Direction */
+#define                  IORDY_EN  0x10       /* IORDY Enable */
+#define                FIFO_FLUSH  0x20       /* Flush FIFOs */
+#define                  SOFT_RST  0x40       /* Soft Reset */
+#define                   DEV_RST  0x80       /* Device Reset */
+#define                TFRCNT_RST  0x100      /* Trans Count Reset */
+#define               END_ON_TERM  0x200      /* End/Terminate Select */
+#define               PIO_USE_DMA  0x400      /* PIO-DMA Enable */
+#define          UDMAIN_FIFO_THRS  0xf000     /* Ultra DMA-IN FIFO Threshold */
+
+/* Bit masks for ATAPI_STATUS */
+
+#define               PIO_XFER_ON  0x1        /* PIO transfer in progress */
+#define             MULTI_XFER_ON  0x2        /* Multi-word DMA transfer in progress */
+#define             ULTRA_XFER_ON  0x4        /* Ultra DMA transfer in progress */
+#define               ULTRA_IN_FL  0xf0       /* Ultra DMA Input FIFO Level */
+
+/* Bit masks for ATAPI_DEV_ADDR */
+
+#define                  DEV_ADDR  0x1f       /* Device Address */
+
+/* Bit masks for ATAPI_INT_MASK */
+
+#define        ATAPI_DEV_INT_MASK  0x1        /* Device interrupt mask */
+#define             PIO_DONE_MASK  0x2        /* PIO transfer done interrupt mask */
+#define           MULTI_DONE_MASK  0x4        /* Multi-DMA transfer done interrupt mask */
+#define          UDMAIN_DONE_MASK  0x8        /* Ultra-DMA in transfer done interrupt mask */
+#define         UDMAOUT_DONE_MASK  0x10       /* Ultra-DMA out transfer done interrupt mask */
+#define       HOST_TERM_XFER_MASK  0x20       /* Host terminate current transfer interrupt mask */
+#define           MULTI_TERM_MASK  0x40       /* Device terminate Multi-DMA transfer interrupt mask */
+#define          UDMAIN_TERM_MASK  0x80       /* Device terminate Ultra-DMA-in transfer interrupt mask */
+#define         UDMAOUT_TERM_MASK  0x100      /* Device terminate Ultra-DMA-out transfer interrupt mask */
+
+/* Bit masks for ATAPI_INT_STATUS */
+
+#define             ATAPI_DEV_INT  0x1        /* Device interrupt status */
+#define              PIO_DONE_INT  0x2        /* PIO transfer done interrupt status */
+#define            MULTI_DONE_INT  0x4        /* Multi-DMA transfer done interrupt status */
+#define           UDMAIN_DONE_INT  0x8        /* Ultra-DMA in transfer done interrupt status */
+#define          UDMAOUT_DONE_INT  0x10       /* Ultra-DMA out transfer done interrupt status */
+#define        HOST_TERM_XFER_INT  0x20       /* Host terminate current transfer interrupt status */
+#define            MULTI_TERM_INT  0x40       /* Device terminate Multi-DMA transfer interrupt status */
+#define           UDMAIN_TERM_INT  0x80       /* Device terminate Ultra-DMA-in transfer interrupt status */
+#define          UDMAOUT_TERM_INT  0x100      /* Device terminate Ultra-DMA-out transfer interrupt status */
+
+/* Bit masks for ATAPI_LINE_STATUS */
+
+#define                ATAPI_INTR  0x1        /* Device interrupt to host line status */
+#define                ATAPI_DASP  0x2        /* Device dasp to host line status */
+#define                ATAPI_CS0N  0x4        /* ATAPI chip select 0 line status */
+#define                ATAPI_CS1N  0x8        /* ATAPI chip select 1 line status */
+#define                ATAPI_ADDR  0x70       /* ATAPI address line status */
+#define              ATAPI_DMAREQ  0x80       /* ATAPI DMA request line status */
+#define             ATAPI_DMAACKN  0x100      /* ATAPI DMA acknowledge line status */
+#define               ATAPI_DIOWN  0x200      /* ATAPI write line status */
+#define               ATAPI_DIORN  0x400      /* ATAPI read line status */
+#define               ATAPI_IORDY  0x800      /* ATAPI IORDY line status */
+
+/* Bit masks for ATAPI_SM_STATE */
+
+#define                PIO_CSTATE  0xf        /* PIO mode state machine current state */
+#define                DMA_CSTATE  0xf0       /* DMA mode state machine current state */
+#define             UDMAIN_CSTATE  0xf00      /* Ultra DMA-In mode state machine current state */
+#define            UDMAOUT_CSTATE  0xf000     /* ATAPI IORDY line status */
+
+/* Bit masks for ATAPI_TERMINATE */
+
+#define           ATAPI_HOST_TERM  0x1        /* Host terminationation */
+
+/* Bit masks for ATAPI_REG_TIM_0 */
+
+#define                    T2_REG  0xff       /* End of cycle time for register access transfers */
+#define                  TEOC_REG  0xff00     /* Selects DIOR/DIOW pulsewidth */
+
+/* Bit masks for ATAPI_PIO_TIM_0 */
+
+#define                    T1_REG  0xf        /* Time from address valid to DIOR/DIOW */
+#define                T2_REG_PIO  0xff0      /* DIOR/DIOW pulsewidth */
+#define                    T4_REG  0xf000     /* DIOW data hold */
+
+/* Bit masks for ATAPI_PIO_TIM_1 */
+
+#define              TEOC_REG_PIO  0xff       /* End of cycle time for PIO access transfers. */
+
+/* Bit masks for ATAPI_MULTI_TIM_0 */
+
+#define                        TD  0xff       /* DIOR/DIOW asserted pulsewidth */
+#define                        TM  0xff00     /* Time from address valid to DIOR/DIOW */
+
+/* Bit masks for ATAPI_MULTI_TIM_1 */
+
+#define                       TKW  0xff       /* Selects DIOW negated pulsewidth */
+#define                       TKR  0xff00     /* Selects DIOR negated pulsewidth */
+
+/* Bit masks for ATAPI_MULTI_TIM_2 */
+
+#define                        TH  0xff       /* Selects DIOW data hold */
+#define                      TEOC  0xff00     /* Selects end of cycle for DMA */
+
+/* Bit masks for ATAPI_ULTRA_TIM_0 */
+
+#define                      TACK  0xff       /* Selects setup and hold times for TACK */
+#define                      TENV  0xff00     /* Selects envelope time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_1 */
+
+#define                      TDVS  0xff       /* Selects data valid setup time */
+#define                 TCYC_TDVS  0xff00     /* Selects cycle time - TDVS time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_2 */
+
+#define                       TSS  0xff       /* Selects time from STROBE edge to negation of DMARQ or assertion of STOP */
+#define                      TMLI  0xff00     /* Selects interlock time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_3 */
+
+#define                      TZAH  0xff       /* Selects minimum delay required for output */
+#define               READY_PAUSE  0xff00     /* Selects ready to pause */
+
+/* Bit masks for TIMER_ENABLE1 */
+
+#define                    TIMEN8  0x1        /* Timer 8 Enable */
+#define                    TIMEN9  0x2        /* Timer 9 Enable */
+#define                   TIMEN10  0x4        /* Timer 10 Enable */
+
+/* Bit masks for TIMER_DISABLE1 */
+
+#define                   TIMDIS8  0x1        /* Timer 8 Disable */
+#define                   TIMDIS9  0x2        /* Timer 9 Disable */
+#define                  TIMDIS10  0x4        /* Timer 10 Disable */
+
+/* Bit masks for TIMER_STATUS1 */
+
+#define                    TIMIL8  0x1        /* Timer 8 Interrupt */
+#define                    TIMIL9  0x2        /* Timer 9 Interrupt */
+#define                   TIMIL10  0x4        /* Timer 10 Interrupt */
+#define                 TOVF_ERR8  0x10       /* Timer 8 Counter Overflow */
+#define                 TOVF_ERR9  0x20       /* Timer 9 Counter Overflow */
+#define                TOVF_ERR10  0x40       /* Timer 10 Counter Overflow */
+#define                     TRUN8  0x1000     /* Timer 8 Slave Enable Status */
+#define                     TRUN9  0x2000     /* Timer 9 Slave Enable Status */
+#define                    TRUN10  0x4000     /* Timer 10 Slave Enable Status */
+
+/* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
+
+/* Bit masks for USB_FADDR */
+
+#define          FUNCTION_ADDRESS  0x7f       /* Function address */
+
+/* Bit masks for USB_POWER */
+
+#define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
+#define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
+#define               RESUME_MODE  0x4        /* DMA Mode */
+#define                     RESET  0x8        /* Reset indicator */
+#define                   HS_MODE  0x10       /* High Speed mode indicator */
+#define                 HS_ENABLE  0x20       /* high Speed Enable */
+#define                 SOFT_CONN  0x40       /* Soft connect */
+#define                ISO_UPDATE  0x80       /* Isochronous update */
+
+/* Bit masks for USB_INTRTX */
+
+#define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
+#define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
+#define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
+#define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
+#define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
+#define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
+#define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
+#define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
+
+/* Bit masks for USB_INTRRX */
+
+#define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
+#define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
+#define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
+#define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
+#define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
+#define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
+#define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
+
+/* Bit masks for USB_INTRTXE */
+
+#define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
+#define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
+#define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
+#define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
+#define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
+#define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
+#define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
+#define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
+
+/* Bit masks for USB_INTRRXE */
+
+#define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
+#define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
+#define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
+#define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
+#define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
+#define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
+#define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
+
+/* Bit masks for USB_INTRUSB */
+
+#define                 SUSPEND_B  0x1        /* Suspend indicator */
+#define                  RESUME_B  0x2        /* Resume indicator */
+#define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
+#define                     SOF_B  0x8        /* Start of frame */
+#define                    CONN_B  0x10       /* Connection indicator */
+#define                  DISCON_B  0x20       /* Disconnect indicator */
+#define             SESSION_REQ_B  0x40       /* Session Request */
+#define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
+
+/* Bit masks for USB_INTRUSBE */
+
+#define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
+#define                 RESUME_BE  0x2        /* Resume indicator int enable */
+#define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
+#define                    SOF_BE  0x8        /* Start of frame int enable */
+#define                   CONN_BE  0x10       /* Connection indicator int enable */
+#define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
+#define            SESSION_REQ_BE  0x40       /* Session Request int enable */
+#define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
+
+/* Bit masks for USB_FRAME */
+
+#define              FRAME_NUMBER  0x7ff      /* Frame number */
+
+/* Bit masks for USB_INDEX */
+
+#define         SELECTED_ENDPOINT  0xf        /* selected endpoint */
+
+/* Bit masks for USB_GLOBAL_CTL */
+
+#define                GLOBAL_ENA  0x1        /* enables USB module */
+#define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
+#define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
+#define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
+#define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
+#define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
+#define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
+#define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
+#define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
+#define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
+#define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
+#define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
+#define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
+#define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
+#define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
+
+/* Bit masks for USB_OTG_DEV_CTL */
+
+#define                   SESSION  0x1        /* session indicator */
+#define                  HOST_REQ  0x2        /* Host negotiation request */
+#define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
+#define                     VBUS0  0x8        /* Vbus level indicator[0] */
+#define                     VBUS1  0x10       /* Vbus level indicator[1] */
+#define                     LSDEV  0x20       /* Low-speed indicator */
+#define                     FSDEV  0x40       /* Full or High-speed indicator */
+#define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
+
+/* Bit masks for USB_OTG_VBUS_IRQ */
+
+#define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
+#define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
+#define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
+#define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
+#define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
+#define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
+
+/* Bit masks for USB_OTG_VBUS_MASK */
+
+#define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
+#define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
+#define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
+#define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
+#define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
+#define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
+
+/* Bit masks for USB_CSR0 */
+
+#define                  RXPKTRDY  0x1        /* data packet receive indicator */
+#define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
+#define                STALL_SENT  0x4        /* STALL handshake sent */
+#define                   DATAEND  0x8        /* Data end indicator */
+#define                  SETUPEND  0x10       /* Setup end */
+#define                 SENDSTALL  0x20       /* Send STALL handshake */
+#define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
+#define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
+#define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
+#define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
+#define                SETUPPKT_H  0x8        /* send Setup token host mode */
+#define                   ERROR_H  0x10       /* timeout error indicator host mode */
+#define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
+#define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
+#define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
+
+/* Bit masks for USB_COUNT0 */
+
+#define              EP0_RX_COUNT  0x7f       /* number of received bytes in EP0 FIFO */
+
+/* Bit masks for USB_NAKLIMIT0 */
+
+#define             EP0_NAK_LIMIT  0x1f       /* number of frames/micro frames after which EP0 timeouts */
+
+/* Bit masks for USB_TX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_T  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_RX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_R  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_TXCSR */
+
+#define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
+#define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
+#define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
+#define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
+#define              STALL_SEND_T  0x10       /* issue a Stall handshake */
+#define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
+#define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
+#define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
+#define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
+#define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
+#define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
+#define                     ISO_T  0x4000     /* enable Isochronous transfers */
+#define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
+#define                  ERROR_TH  0x4        /* error condition host mode */
+#define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
+#define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
+
+/* Bit masks for USB_TXCOUNT */
+
+#define                  TX_COUNT  0x1fff     /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* Bit masks for USB_RXCSR */
+
+#define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
+#define               FIFO_FULL_R  0x2        /* FIFO not empty */
+#define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
+#define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
+#define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
+#define              STALL_SEND_R  0x20       /* issue a Stall handshake */
+#define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
+#define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
+#define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
+#define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
+#define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
+#define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
+#define                     ISO_R  0x4000     /* enable Isochronous transfers */
+#define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
+#define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
+#define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
+#define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
+#define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
+#define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
+#define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
+
+/* Bit masks for USB_RXCOUNT */
+
+#define                  RX_COUNT  0x1fff     /* Number of received bytes in the packet in the Rx FIFO */
+
+/* Bit masks for USB_TXTYPE */
+
+#define            TARGET_EP_NO_T  0xf        /* EP number */
+#define                PROTOCOL_T  0xc        /* transfer type */
+
+/* Bit masks for USB_TXINTERVAL */
+
+#define          TX_POLL_INTERVAL  0xff       /* polling interval for selected Tx EP */
+
+/* Bit masks for USB_RXTYPE */
+
+#define            TARGET_EP_NO_R  0xf        /* EP number */
+#define                PROTOCOL_R  0xc        /* transfer type */
+
+/* Bit masks for USB_RXINTERVAL */
+
+#define          RX_POLL_INTERVAL  0xff       /* polling interval for selected Rx EP */
+
+/* Bit masks for USB_DMA_INTERRUPT */
+
+#define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
+#define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
+#define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
+#define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
+#define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
+#define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
+#define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
+#define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
+
+/* Bit masks for USB_DMAxCONTROL */
+
+#define                   DMA_ENA  0x1        /* DMA enable */
+#define                 DIRECTION  0x2        /* direction of DMA transfer */
+#define                      MODE  0x4        /* DMA Bus error */
+#define                   INT_ENA  0x8        /* Interrupt enable */
+#define                     EPNUM  0xf0       /* EP number */
+#define                  BUSERROR  0x100      /* DMA Bus error */
+
+/* Bit masks for USB_DMAxADDRHIGH */
+
+#define             DMA_ADDR_HIGH  0xffff     /* Upper 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxADDRLOW */
+
+#define              DMA_ADDR_LOW  0xffff     /* Lower 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTHIGH */
+
+#define            DMA_COUNT_HIGH  0xffff     /* Upper 16-bits of byte count of DMA transfer for DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTLOW */
+
+#define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
+
+/* Bit masks for HMDMAx_CONTROL */
+
+#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
+#define                       REP  0x2        /* Handshake MDMA Request Polarity */
+#define                       UTE  0x8        /* Urgency Threshold Enable */
+#define                       OIE  0x10       /* Overflow Interrupt Enable */
+#define                      BDIE  0x20       /* Block Done Interrupt Enable */
+#define                      MBDI  0x40       /* Mask Block Done Interrupt */
+#define                       DRQ  0x300      /* Handshake MDMA Request Type */
+#define                       RBC  0x1000     /* Force Reload of BCOUNT */
+#define                        PS  0x2000     /* Pin Status */
+#define                        OI  0x4000     /* Overflow Interrupt Generated */
+#define                       BDI  0x8000     /* Block Done Interrupt Generated */
+
+/* ******************************************* */
+/*     MULTI BIT MACRO ENUMERATIONS            */
+/* ******************************************* */
+
+
+#endif /* _DEF_BF548_H */
diff --git a/include/asm-blackfin/mach-bf548/defBF549.h b/include/asm-blackfin/mach-bf548/defBF549.h
new file mode 100644
index 0000000..c2f4734
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/defBF549.h
@@ -0,0 +1,2735 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/defBF549.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF549_H
+#define _DEF_BF549_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/mach-common/def_LPBlackfin.h>
+
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF549 */
+
+/* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
+#include "defBF54x_base.h"
+
+/* The following are the #defines needed by ADSP-BF549 that are not in the common header */
+
+/* Timer Registers */
+
+#define                    TIMER8_CONFIG  0xffc00600   /* Timer 8 Configuration Register */
+#define                   TIMER8_COUNTER  0xffc00604   /* Timer 8 Counter Register */
+#define                    TIMER8_PERIOD  0xffc00608   /* Timer 8 Period Register */
+#define                     TIMER8_WIDTH  0xffc0060c   /* Timer 8 Width Register */
+#define                    TIMER9_CONFIG  0xffc00610   /* Timer 9 Configuration Register */
+#define                   TIMER9_COUNTER  0xffc00614   /* Timer 9 Counter Register */
+#define                    TIMER9_PERIOD  0xffc00618   /* Timer 9 Period Register */
+#define                     TIMER9_WIDTH  0xffc0061c   /* Timer 9 Width Register */
+#define                   TIMER10_CONFIG  0xffc00620   /* Timer 10 Configuration Register */
+#define                  TIMER10_COUNTER  0xffc00624   /* Timer 10 Counter Register */
+#define                   TIMER10_PERIOD  0xffc00628   /* Timer 10 Period Register */
+#define                    TIMER10_WIDTH  0xffc0062c   /* Timer 10 Width Register */
+
+/* Timer Group of 3 Registers */
+
+#define                    TIMER_ENABLE1  0xffc00640   /* Timer Group of 3 Enable Register */
+#define                   TIMER_DISABLE1  0xffc00644   /* Timer Group of 3 Disable Register */
+#define                    TIMER_STATUS1  0xffc00648   /* Timer Group of 3 Status Register */
+
+/* SPORT0 Registers */
+
+#define                      SPORT0_TCR1  0xffc00800   /* SPORT0 Transmit Configuration 1 Register */
+#define                      SPORT0_TCR2  0xffc00804   /* SPORT0 Transmit Configuration 2 Register */
+#define                   SPORT0_TCLKDIV  0xffc00808   /* SPORT0 Transmit Serial Clock Divider Register */
+#define                    SPORT0_TFSDIV  0xffc0080c   /* SPORT0 Transmit Frame Sync Divider Register */
+#define                        SPORT0_TX  0xffc00810   /* SPORT0 Transmit Data Register */
+#define                        SPORT0_RX  0xffc00818   /* SPORT0 Receive Data Register */
+#define                      SPORT0_RCR1  0xffc00820   /* SPORT0 Receive Configuration 1 Register */
+#define                      SPORT0_RCR2  0xffc00824   /* SPORT0 Receive Configuration 2 Register */
+#define                   SPORT0_RCLKDIV  0xffc00828   /* SPORT0 Receive Serial Clock Divider Register */
+#define                    SPORT0_RFSDIV  0xffc0082c   /* SPORT0 Receive Frame Sync Divider Register */
+#define                      SPORT0_STAT  0xffc00830   /* SPORT0 Status Register */
+#define                      SPORT0_CHNL  0xffc00834   /* SPORT0 Current Channel Register */
+#define                     SPORT0_MCMC1  0xffc00838   /* SPORT0 Multi channel Configuration Register 1 */
+#define                     SPORT0_MCMC2  0xffc0083c   /* SPORT0 Multi channel Configuration Register 2 */
+#define                     SPORT0_MTCS0  0xffc00840   /* SPORT0 Multi channel Transmit Select Register 0 */
+#define                     SPORT0_MTCS1  0xffc00844   /* SPORT0 Multi channel Transmit Select Register 1 */
+#define                     SPORT0_MTCS2  0xffc00848   /* SPORT0 Multi channel Transmit Select Register 2 */
+#define                     SPORT0_MTCS3  0xffc0084c   /* SPORT0 Multi channel Transmit Select Register 3 */
+#define                     SPORT0_MRCS0  0xffc00850   /* SPORT0 Multi channel Receive Select Register 0 */
+#define                     SPORT0_MRCS1  0xffc00854   /* SPORT0 Multi channel Receive Select Register 1 */
+#define                     SPORT0_MRCS2  0xffc00858   /* SPORT0 Multi channel Receive Select Register 2 */
+#define                     SPORT0_MRCS3  0xffc0085c   /* SPORT0 Multi channel Receive Select Register 3 */
+
+/* EPPI0 Registers */
+
+#define                     EPPI0_STATUS  0xffc01000   /* EPPI0 Status Register */
+#define                     EPPI0_HCOUNT  0xffc01004   /* EPPI0 Horizontal Transfer Count Register */
+#define                     EPPI0_HDELAY  0xffc01008   /* EPPI0 Horizontal Delay Count Register */
+#define                     EPPI0_VCOUNT  0xffc0100c   /* EPPI0 Vertical Transfer Count Register */
+#define                     EPPI0_VDELAY  0xffc01010   /* EPPI0 Vertical Delay Count Register */
+#define                      EPPI0_FRAME  0xffc01014   /* EPPI0 Lines per Frame Register */
+#define                       EPPI0_LINE  0xffc01018   /* EPPI0 Samples per Line Register */
+#define                     EPPI0_CLKDIV  0xffc0101c   /* EPPI0 Clock Divide Register */
+#define                    EPPI0_CONTROL  0xffc01020   /* EPPI0 Control Register */
+#define                   EPPI0_FS1W_HBL  0xffc01024   /* EPPI0 FS1 Width Register / EPPI0 Horizontal Blanking Samples Per Line Register */
+#define                  EPPI0_FS1P_AVPL  0xffc01028   /* EPPI0 FS1 Period Register / EPPI0 Active Video Samples Per Line Register */
+#define                   EPPI0_FS2W_LVB  0xffc0102c   /* EPPI0 FS2 Width Register / EPPI0 Lines of Vertical Blanking Register */
+#define                  EPPI0_FS2P_LAVF  0xffc01030   /* EPPI0 FS2 Period Register/ EPPI0 Lines of Active Video Per Field Register */
+#define                       EPPI0_CLIP  0xffc01034   /* EPPI0 Clipping Register */
+
+/* UART2 Registers */
+
+#define                        UART2_DLL  0xffc02100   /* Divisor Latch Low Byte */
+#define                        UART2_DLH  0xffc02104   /* Divisor Latch High Byte */
+#define                       UART2_GCTL  0xffc02108   /* Global Control Register */
+#define                        UART2_LCR  0xffc0210c   /* Line Control Register */
+#define                        UART2_MCR  0xffc02110   /* Modem Control Register */
+#define                        UART2_LSR  0xffc02114   /* Line Status Register */
+#define                        UART2_MSR  0xffc02118   /* Modem Status Register */
+#define                        UART2_SCR  0xffc0211c   /* Scratch Register */
+#define                    UART2_IER_SET  0xffc02120   /* Interrupt Enable Register Set */
+#define                  UART2_IER_CLEAR  0xffc02124   /* Interrupt Enable Register Clear */
+#define                        UART2_RBR  0xffc0212c   /* Receive Buffer Register */
+
+/* Two Wire Interface Registers (TWI1) */
+
+#define                      TWI1_CLKDIV  0xffc02200   /* Clock Divider Register */
+#define                     TWI1_CONTROL  0xffc02204   /* TWI Control Register */
+#define                  TWI1_SLAVE_CTRL  0xffc02208   /* TWI Slave Mode Control Register */
+#define                  TWI1_SLAVE_STAT  0xffc0220c   /* TWI Slave Mode Status Register */
+#define                  TWI1_SLAVE_ADDR  0xffc02210   /* TWI Slave Mode Address Register */
+#define                 TWI1_MASTER_CTRL  0xffc02214   /* TWI Master Mode Control Register */
+#define                 TWI1_MASTER_STAT  0xffc02218   /* TWI Master Mode Status Register */
+#define                 TWI1_MASTER_ADDR  0xffc0221c   /* TWI Master Mode Address Register */
+#define                    TWI1_INT_STAT  0xffc02220   /* TWI Interrupt Status Register */
+#define                    TWI1_INT_MASK  0xffc02224   /* TWI Interrupt Mask Register */
+#define                   TWI1_FIFO_CTRL  0xffc02228   /* TWI FIFO Control Register */
+#define                   TWI1_FIFO_STAT  0xffc0222c   /* TWI FIFO Status Register */
+#define                   TWI1_XMT_DATA8  0xffc02280   /* TWI FIFO Transmit Data Single Byte Register */
+#define                  TWI1_XMT_DATA16  0xffc02284   /* TWI FIFO Transmit Data Double Byte Register */
+#define                   TWI1_RCV_DATA8  0xffc02288   /* TWI FIFO Receive Data Single Byte Register */
+#define                  TWI1_RCV_DATA16  0xffc0228c   /* TWI FIFO Receive Data Double Byte Register */
+
+/* SPI2  Registers */
+
+#define                         SPI2_CTL  0xffc02400   /* SPI2 Control Register */
+#define                         SPI2_FLG  0xffc02404   /* SPI2 Flag Register */
+#define                        SPI2_STAT  0xffc02408   /* SPI2 Status Register */
+#define                        SPI2_TDBR  0xffc0240c   /* SPI2 Transmit Data Buffer Register */
+#define                        SPI2_RDBR  0xffc02410   /* SPI2 Receive Data Buffer Register */
+#define                        SPI2_BAUD  0xffc02414   /* SPI2 Baud Rate Register */
+#define                      SPI2_SHADOW  0xffc02418   /* SPI2 Receive Data Buffer Shadow Register */
+
+/* MXVR Registers */
+
+#define                      MXVR_CONFIG  0xffc02700   /* MXVR Configuration Register */
+#define                     MXVR_STATE_0  0xffc02708   /* MXVR State Register 0 */
+#define                     MXVR_STATE_1  0xffc0270c   /* MXVR State Register 1 */
+#define                  MXVR_INT_STAT_0  0xffc02710   /* MXVR Interrupt Status Register 0 */
+#define                  MXVR_INT_STAT_1  0xffc02714   /* MXVR Interrupt Status Register 1 */
+#define                    MXVR_INT_EN_0  0xffc02718   /* MXVR Interrupt Enable Register 0 */
+#define                    MXVR_INT_EN_1  0xffc0271c   /* MXVR Interrupt Enable Register 1 */
+#define                    MXVR_POSITION  0xffc02720   /* MXVR Node Position Register */
+#define                MXVR_MAX_POSITION  0xffc02724   /* MXVR Maximum Node Position Register */
+#define                       MXVR_DELAY  0xffc02728   /* MXVR Node Frame Delay Register */
+#define                   MXVR_MAX_DELAY  0xffc0272c   /* MXVR Maximum Node Frame Delay Register */
+#define                       MXVR_LADDR  0xffc02730   /* MXVR Logical Address Register */
+#define                       MXVR_GADDR  0xffc02734   /* MXVR Group Address Register */
+#define                       MXVR_AADDR  0xffc02738   /* MXVR Alternate Address Register */
+
+/* MXVR Allocation Table Registers */
+
+#define                     MXVR_ALLOC_0  0xffc0273c   /* MXVR Allocation Table Register 0 */
+#define                     MXVR_ALLOC_1  0xffc02740   /* MXVR Allocation Table Register 1 */
+#define                     MXVR_ALLOC_2  0xffc02744   /* MXVR Allocation Table Register 2 */
+#define                     MXVR_ALLOC_3  0xffc02748   /* MXVR Allocation Table Register 3 */
+#define                     MXVR_ALLOC_4  0xffc0274c   /* MXVR Allocation Table Register 4 */
+#define                     MXVR_ALLOC_5  0xffc02750   /* MXVR Allocation Table Register 5 */
+#define                     MXVR_ALLOC_6  0xffc02754   /* MXVR Allocation Table Register 6 */
+#define                     MXVR_ALLOC_7  0xffc02758   /* MXVR Allocation Table Register 7 */
+#define                     MXVR_ALLOC_8  0xffc0275c   /* MXVR Allocation Table Register 8 */
+#define                     MXVR_ALLOC_9  0xffc02760   /* MXVR Allocation Table Register 9 */
+#define                    MXVR_ALLOC_10  0xffc02764   /* MXVR Allocation Table Register 10 */
+#define                    MXVR_ALLOC_11  0xffc02768   /* MXVR Allocation Table Register 11 */
+#define                    MXVR_ALLOC_12  0xffc0276c   /* MXVR Allocation Table Register 12 */
+#define                    MXVR_ALLOC_13  0xffc02770   /* MXVR Allocation Table Register 13 */
+#define                    MXVR_ALLOC_14  0xffc02774   /* MXVR Allocation Table Register 14 */
+
+/* MXVR Channel Assign Registers */
+
+#define                MXVR_SYNC_LCHAN_0  0xffc02778   /* MXVR Sync Data Logical Channel Assign Register 0 */
+#define                MXVR_SYNC_LCHAN_1  0xffc0277c   /* MXVR Sync Data Logical Channel Assign Register 1 */
+#define                MXVR_SYNC_LCHAN_2  0xffc02780   /* MXVR Sync Data Logical Channel Assign Register 2 */
+#define                MXVR_SYNC_LCHAN_3  0xffc02784   /* MXVR Sync Data Logical Channel Assign Register 3 */
+#define                MXVR_SYNC_LCHAN_4  0xffc02788   /* MXVR Sync Data Logical Channel Assign Register 4 */
+#define                MXVR_SYNC_LCHAN_5  0xffc0278c   /* MXVR Sync Data Logical Channel Assign Register 5 */
+#define                MXVR_SYNC_LCHAN_6  0xffc02790   /* MXVR Sync Data Logical Channel Assign Register 6 */
+#define                MXVR_SYNC_LCHAN_7  0xffc02794   /* MXVR Sync Data Logical Channel Assign Register 7 */
+
+/* MXVR DMA0 Registers */
+
+#define                 MXVR_DMA0_CONFIG  0xffc02798   /* MXVR Sync Data DMA0 Config Register */
+#define             MXVR_DMA0_START_ADDR  0xffc0279c   /* MXVR Sync Data DMA0 Start Address */
+#define                  MXVR_DMA0_COUNT  0xffc027a0   /* MXVR Sync Data DMA0 Loop Count Register */
+#define              MXVR_DMA0_CURR_ADDR  0xffc027a4   /* MXVR Sync Data DMA0 Current Address */
+#define             MXVR_DMA0_CURR_COUNT  0xffc027a8   /* MXVR Sync Data DMA0 Current Loop Count */
+
+/* MXVR DMA1 Registers */
+
+#define                 MXVR_DMA1_CONFIG  0xffc027ac   /* MXVR Sync Data DMA1 Config Register */
+#define             MXVR_DMA1_START_ADDR  0xffc027b0   /* MXVR Sync Data DMA1 Start Address */
+#define                  MXVR_DMA1_COUNT  0xffc027b4   /* MXVR Sync Data DMA1 Loop Count Register */
+#define              MXVR_DMA1_CURR_ADDR  0xffc027b8   /* MXVR Sync Data DMA1 Current Address */
+#define             MXVR_DMA1_CURR_COUNT  0xffc027bc   /* MXVR Sync Data DMA1 Current Loop Count */
+
+/* MXVR DMA2 Registers */
+
+#define                 MXVR_DMA2_CONFIG  0xffc027c0   /* MXVR Sync Data DMA2 Config Register */
+#define             MXVR_DMA2_START_ADDR  0xffc027c4   /* MXVR Sync Data DMA2 Start Address */
+#define                  MXVR_DMA2_COUNT  0xffc027c8   /* MXVR Sync Data DMA2 Loop Count Register */
+#define              MXVR_DMA2_CURR_ADDR  0xffc027cc   /* MXVR Sync Data DMA2 Current Address */
+#define             MXVR_DMA2_CURR_COUNT  0xffc027d0   /* MXVR Sync Data DMA2 Current Loop Count */
+
+/* MXVR DMA3 Registers */
+
+#define                 MXVR_DMA3_CONFIG  0xffc027d4   /* MXVR Sync Data DMA3 Config Register */
+#define             MXVR_DMA3_START_ADDR  0xffc027d8   /* MXVR Sync Data DMA3 Start Address */
+#define                  MXVR_DMA3_COUNT  0xffc027dc   /* MXVR Sync Data DMA3 Loop Count Register */
+#define              MXVR_DMA3_CURR_ADDR  0xffc027e0   /* MXVR Sync Data DMA3 Current Address */
+#define             MXVR_DMA3_CURR_COUNT  0xffc027e4   /* MXVR Sync Data DMA3 Current Loop Count */
+
+/* MXVR DMA4 Registers */
+
+#define                 MXVR_DMA4_CONFIG  0xffc027e8   /* MXVR Sync Data DMA4 Config Register */
+#define             MXVR_DMA4_START_ADDR  0xffc027ec   /* MXVR Sync Data DMA4 Start Address */
+#define                  MXVR_DMA4_COUNT  0xffc027f0   /* MXVR Sync Data DMA4 Loop Count Register */
+#define              MXVR_DMA4_CURR_ADDR  0xffc027f4   /* MXVR Sync Data DMA4 Current Address */
+#define             MXVR_DMA4_CURR_COUNT  0xffc027f8   /* MXVR Sync Data DMA4 Current Loop Count */
+
+/* MXVR DMA5 Registers */
+
+#define                 MXVR_DMA5_CONFIG  0xffc027fc   /* MXVR Sync Data DMA5 Config Register */
+#define             MXVR_DMA5_START_ADDR  0xffc02800   /* MXVR Sync Data DMA5 Start Address */
+#define                  MXVR_DMA5_COUNT  0xffc02804   /* MXVR Sync Data DMA5 Loop Count Register */
+#define              MXVR_DMA5_CURR_ADDR  0xffc02808   /* MXVR Sync Data DMA5 Current Address */
+#define             MXVR_DMA5_CURR_COUNT  0xffc0280c   /* MXVR Sync Data DMA5 Current Loop Count */
+
+/* MXVR DMA6 Registers */
+
+#define                 MXVR_DMA6_CONFIG  0xffc02810   /* MXVR Sync Data DMA6 Config Register */
+#define             MXVR_DMA6_START_ADDR  0xffc02814   /* MXVR Sync Data DMA6 Start Address */
+#define                  MXVR_DMA6_COUNT  0xffc02818   /* MXVR Sync Data DMA6 Loop Count Register */
+#define              MXVR_DMA6_CURR_ADDR  0xffc0281c   /* MXVR Sync Data DMA6 Current Address */
+#define             MXVR_DMA6_CURR_COUNT  0xffc02820   /* MXVR Sync Data DMA6 Current Loop Count */
+
+/* MXVR DMA7 Registers */
+
+#define                 MXVR_DMA7_CONFIG  0xffc02824   /* MXVR Sync Data DMA7 Config Register */
+#define             MXVR_DMA7_START_ADDR  0xffc02828   /* MXVR Sync Data DMA7 Start Address */
+#define                  MXVR_DMA7_COUNT  0xffc0282c   /* MXVR Sync Data DMA7 Loop Count Register */
+#define              MXVR_DMA7_CURR_ADDR  0xffc02830   /* MXVR Sync Data DMA7 Current Address */
+#define             MXVR_DMA7_CURR_COUNT  0xffc02834   /* MXVR Sync Data DMA7 Current Loop Count */
+
+/* MXVR Asynch Packet Registers */
+
+#define                      MXVR_AP_CTL  0xffc02838   /* MXVR Async Packet Control Register */
+#define             MXVR_APRB_START_ADDR  0xffc0283c   /* MXVR Async Packet RX Buffer Start Addr Register */
+#define              MXVR_APRB_CURR_ADDR  0xffc02840   /* MXVR Async Packet RX Buffer Current Addr Register */
+#define             MXVR_APTB_START_ADDR  0xffc02844   /* MXVR Async Packet TX Buffer Start Addr Register */
+#define              MXVR_APTB_CURR_ADDR  0xffc02848   /* MXVR Async Packet TX Buffer Current Addr Register */
+
+/* MXVR Control Message Registers */
+
+#define                      MXVR_CM_CTL  0xffc0284c   /* MXVR Control Message Control Register */
+#define             MXVR_CMRB_START_ADDR  0xffc02850   /* MXVR Control Message RX Buffer Start Addr Register */
+#define              MXVR_CMRB_CURR_ADDR  0xffc02854   /* MXVR Control Message RX Buffer Current Address */
+#define             MXVR_CMTB_START_ADDR  0xffc02858   /* MXVR Control Message TX Buffer Start Addr Register */
+#define              MXVR_CMTB_CURR_ADDR  0xffc0285c   /* MXVR Control Message TX Buffer Current Address */
+
+/* MXVR Remote Read Registers */
+
+#define             MXVR_RRDB_START_ADDR  0xffc02860   /* MXVR Remote Read Buffer Start Addr Register */
+#define              MXVR_RRDB_CURR_ADDR  0xffc02864   /* MXVR Remote Read Buffer Current Addr Register */
+
+/* MXVR Pattern Data Registers */
+
+#define                  MXVR_PAT_DATA_0  0xffc02868   /* MXVR Pattern Data Register 0 */
+#define                    MXVR_PAT_EN_0  0xffc0286c   /* MXVR Pattern Enable Register 0 */
+#define                  MXVR_PAT_DATA_1  0xffc02870   /* MXVR Pattern Data Register 1 */
+#define                    MXVR_PAT_EN_1  0xffc02874   /* MXVR Pattern Enable Register 1 */
+
+/* MXVR Frame Counter Registers */
+
+#define                 MXVR_FRAME_CNT_0  0xffc02878   /* MXVR Frame Counter 0 */
+#define                 MXVR_FRAME_CNT_1  0xffc0287c   /* MXVR Frame Counter 1 */
+
+/* MXVR Routing Table Registers */
+
+#define                   MXVR_ROUTING_0  0xffc02880   /* MXVR Routing Table Register 0 */
+#define                   MXVR_ROUTING_1  0xffc02884   /* MXVR Routing Table Register 1 */
+#define                   MXVR_ROUTING_2  0xffc02888   /* MXVR Routing Table Register 2 */
+#define                   MXVR_ROUTING_3  0xffc0288c   /* MXVR Routing Table Register 3 */
+#define                   MXVR_ROUTING_4  0xffc02890   /* MXVR Routing Table Register 4 */
+#define                   MXVR_ROUTING_5  0xffc02894   /* MXVR Routing Table Register 5 */
+#define                   MXVR_ROUTING_6  0xffc02898   /* MXVR Routing Table Register 6 */
+#define                   MXVR_ROUTING_7  0xffc0289c   /* MXVR Routing Table Register 7 */
+#define                   MXVR_ROUTING_8  0xffc028a0   /* MXVR Routing Table Register 8 */
+#define                   MXVR_ROUTING_9  0xffc028a4   /* MXVR Routing Table Register 9 */
+#define                  MXVR_ROUTING_10  0xffc028a8   /* MXVR Routing Table Register 10 */
+#define                  MXVR_ROUTING_11  0xffc028ac   /* MXVR Routing Table Register 11 */
+#define                  MXVR_ROUTING_12  0xffc028b0   /* MXVR Routing Table Register 12 */
+#define                  MXVR_ROUTING_13  0xffc028b4   /* MXVR Routing Table Register 13 */
+#define                  MXVR_ROUTING_14  0xffc028b8   /* MXVR Routing Table Register 14 */
+
+/* MXVR Counter-Clock-Control Registers */
+
+#define                   MXVR_BLOCK_CNT  0xffc028c0   /* MXVR Block Counter */
+#define                     MXVR_CLK_CTL  0xffc028d0   /* MXVR Clock Control Register */
+#define                  MXVR_CDRPLL_CTL  0xffc028d4   /* MXVR Clock/Data Recovery PLL Control Register */
+#define                   MXVR_FMPLL_CTL  0xffc028d8   /* MXVR Frequency Multiply PLL Control Register */
+#define                     MXVR_PIN_CTL  0xffc028dc   /* MXVR Pin Control Register */
+#define                    MXVR_SCLK_CNT  0xffc028e0   /* MXVR System Clock Counter Register */
+
+/* CAN Controller 1 Config 1 Registers */
+
+#define                         CAN1_MC1  0xffc03200   /* CAN Controller 1 Mailbox Configuration Register 1 */
+#define                         CAN1_MD1  0xffc03204   /* CAN Controller 1 Mailbox Direction Register 1 */
+#define                        CAN1_TRS1  0xffc03208   /* CAN Controller 1 Transmit Request Set Register 1 */
+#define                        CAN1_TRR1  0xffc0320c   /* CAN Controller 1 Transmit Request Reset Register 1 */
+#define                         CAN1_TA1  0xffc03210   /* CAN Controller 1 Transmit Acknowledge Register 1 */
+#define                         CAN1_AA1  0xffc03214   /* CAN Controller 1 Abort Acknowledge Register 1 */
+#define                        CAN1_RMP1  0xffc03218   /* CAN Controller 1 Receive Message Pending Register 1 */
+#define                        CAN1_RML1  0xffc0321c   /* CAN Controller 1 Receive Message Lost Register 1 */
+#define                      CAN1_MBTIF1  0xffc03220   /* CAN Controller 1 Mailbox Transmit Interrupt Flag Register 1 */
+#define                      CAN1_MBRIF1  0xffc03224   /* CAN Controller 1 Mailbox Receive Interrupt Flag Register 1 */
+#define                       CAN1_MBIM1  0xffc03228   /* CAN Controller 1 Mailbox Interrupt Mask Register 1 */
+#define                        CAN1_RFH1  0xffc0322c   /* CAN Controller 1 Remote Frame Handling Enable Register 1 */
+#define                       CAN1_OPSS1  0xffc03230   /* CAN Controller 1 Overwrite Protection Single Shot Transmit Register 1 */
+
+/* CAN Controller 1 Config 2 Registers */
+
+#define                         CAN1_MC2  0xffc03240   /* CAN Controller 1 Mailbox Configuration Register 2 */
+#define                         CAN1_MD2  0xffc03244   /* CAN Controller 1 Mailbox Direction Register 2 */
+#define                        CAN1_TRS2  0xffc03248   /* CAN Controller 1 Transmit Request Set Register 2 */
+#define                        CAN1_TRR2  0xffc0324c   /* CAN Controller 1 Transmit Request Reset Register 2 */
+#define                         CAN1_TA2  0xffc03250   /* CAN Controller 1 Transmit Acknowledge Register 2 */
+#define                         CAN1_AA2  0xffc03254   /* CAN Controller 1 Abort Acknowledge Register 2 */
+#define                        CAN1_RMP2  0xffc03258   /* CAN Controller 1 Receive Message Pending Register 2 */
+#define                        CAN1_RML2  0xffc0325c   /* CAN Controller 1 Receive Message Lost Register 2 */
+#define                      CAN1_MBTIF2  0xffc03260   /* CAN Controller 1 Mailbox Transmit Interrupt Flag Register 2 */
+#define                      CAN1_MBRIF2  0xffc03264   /* CAN Controller 1 Mailbox Receive Interrupt Flag Register 2 */
+#define                       CAN1_MBIM2  0xffc03268   /* CAN Controller 1 Mailbox Interrupt Mask Register 2 */
+#define                        CAN1_RFH2  0xffc0326c   /* CAN Controller 1 Remote Frame Handling Enable Register 2 */
+#define                       CAN1_OPSS2  0xffc03270   /* CAN Controller 1 Overwrite Protection Single Shot Transmit Register 2 */
+
+/* CAN Controller 1 Clock/Interrupt/Counter Registers */
+
+#define                       CAN1_CLOCK  0xffc03280   /* CAN Controller 1 Clock Register */
+#define                      CAN1_TIMING  0xffc03284   /* CAN Controller 1 Timing Register */
+#define                       CAN1_DEBUG  0xffc03288   /* CAN Controller 1 Debug Register */
+#define                      CAN1_STATUS  0xffc0328c   /* CAN Controller 1 Global Status Register */
+#define                         CAN1_CEC  0xffc03290   /* CAN Controller 1 Error Counter Register */
+#define                         CAN1_GIS  0xffc03294   /* CAN Controller 1 Global Interrupt Status Register */
+#define                         CAN1_GIM  0xffc03298   /* CAN Controller 1 Global Interrupt Mask Register */
+#define                         CAN1_GIF  0xffc0329c   /* CAN Controller 1 Global Interrupt Flag Register */
+#define                     CAN1_CONTROL  0xffc032a0   /* CAN Controller 1 Master Control Register */
+#define                        CAN1_INTR  0xffc032a4   /* CAN Controller 1 Interrupt Pending Register */
+#define                        CAN1_MBTD  0xffc032ac   /* CAN Controller 1 Mailbox Temporary Disable Register */
+#define                         CAN1_EWR  0xffc032b0   /* CAN Controller 1 Programmable Warning Level Register */
+#define                         CAN1_ESR  0xffc032b4   /* CAN Controller 1 Error Status Register */
+#define                       CAN1_UCCNT  0xffc032c4   /* CAN Controller 1 Universal Counter Register */
+#define                        CAN1_UCRC  0xffc032c8   /* CAN Controller 1 Universal Counter Force Reload Register */
+#define                       CAN1_UCCNF  0xffc032cc   /* CAN Controller 1 Universal Counter Configuration Register */
+
+/* CAN Controller 1 Mailbox Acceptance Registers */
+
+#define                       CAN1_AM00L  0xffc03300   /* CAN Controller 1 Mailbox 0 Acceptance Mask High Register */
+#define                       CAN1_AM00H  0xffc03304   /* CAN Controller 1 Mailbox 0 Acceptance Mask Low Register */
+#define                       CAN1_AM01L  0xffc03308   /* CAN Controller 1 Mailbox 1 Acceptance Mask High Register */
+#define                       CAN1_AM01H  0xffc0330c   /* CAN Controller 1 Mailbox 1 Acceptance Mask Low Register */
+#define                       CAN1_AM02L  0xffc03310   /* CAN Controller 1 Mailbox 2 Acceptance Mask High Register */
+#define                       CAN1_AM02H  0xffc03314   /* CAN Controller 1 Mailbox 2 Acceptance Mask Low Register */
+#define                       CAN1_AM03L  0xffc03318   /* CAN Controller 1 Mailbox 3 Acceptance Mask High Register */
+#define                       CAN1_AM03H  0xffc0331c   /* CAN Controller 1 Mailbox 3 Acceptance Mask Low Register */
+#define                       CAN1_AM04L  0xffc03320   /* CAN Controller 1 Mailbox 4 Acceptance Mask High Register */
+#define                       CAN1_AM04H  0xffc03324   /* CAN Controller 1 Mailbox 4 Acceptance Mask Low Register */
+#define                       CAN1_AM05L  0xffc03328   /* CAN Controller 1 Mailbox 5 Acceptance Mask High Register */
+#define                       CAN1_AM05H  0xffc0332c   /* CAN Controller 1 Mailbox 5 Acceptance Mask Low Register */
+#define                       CAN1_AM06L  0xffc03330   /* CAN Controller 1 Mailbox 6 Acceptance Mask High Register */
+#define                       CAN1_AM06H  0xffc03334   /* CAN Controller 1 Mailbox 6 Acceptance Mask Low Register */
+#define                       CAN1_AM07L  0xffc03338   /* CAN Controller 1 Mailbox 7 Acceptance Mask High Register */
+#define                       CAN1_AM07H  0xffc0333c   /* CAN Controller 1 Mailbox 7 Acceptance Mask Low Register */
+#define                       CAN1_AM08L  0xffc03340   /* CAN Controller 1 Mailbox 8 Acceptance Mask High Register */
+#define                       CAN1_AM08H  0xffc03344   /* CAN Controller 1 Mailbox 8 Acceptance Mask Low Register */
+#define                       CAN1_AM09L  0xffc03348   /* CAN Controller 1 Mailbox 9 Acceptance Mask High Register */
+#define                       CAN1_AM09H  0xffc0334c   /* CAN Controller 1 Mailbox 9 Acceptance Mask Low Register */
+#define                       CAN1_AM10L  0xffc03350   /* CAN Controller 1 Mailbox 10 Acceptance Mask High Register */
+#define                       CAN1_AM10H  0xffc03354   /* CAN Controller 1 Mailbox 10 Acceptance Mask Low Register */
+#define                       CAN1_AM11L  0xffc03358   /* CAN Controller 1 Mailbox 11 Acceptance Mask High Register */
+#define                       CAN1_AM11H  0xffc0335c   /* CAN Controller 1 Mailbox 11 Acceptance Mask Low Register */
+#define                       CAN1_AM12L  0xffc03360   /* CAN Controller 1 Mailbox 12 Acceptance Mask High Register */
+#define                       CAN1_AM12H  0xffc03364   /* CAN Controller 1 Mailbox 12 Acceptance Mask Low Register */
+#define                       CAN1_AM13L  0xffc03368   /* CAN Controller 1 Mailbox 13 Acceptance Mask High Register */
+#define                       CAN1_AM13H  0xffc0336c   /* CAN Controller 1 Mailbox 13 Acceptance Mask Low Register */
+#define                       CAN1_AM14L  0xffc03370   /* CAN Controller 1 Mailbox 14 Acceptance Mask High Register */
+#define                       CAN1_AM14H  0xffc03374   /* CAN Controller 1 Mailbox 14 Acceptance Mask Low Register */
+#define                       CAN1_AM15L  0xffc03378   /* CAN Controller 1 Mailbox 15 Acceptance Mask High Register */
+#define                       CAN1_AM15H  0xffc0337c   /* CAN Controller 1 Mailbox 15 Acceptance Mask Low Register */
+
+/* CAN Controller 1 Mailbox Acceptance Registers */
+
+#define                       CAN1_AM16L  0xffc03380   /* CAN Controller 1 Mailbox 16 Acceptance Mask High Register */
+#define                       CAN1_AM16H  0xffc03384   /* CAN Controller 1 Mailbox 16 Acceptance Mask Low Register */
+#define                       CAN1_AM17L  0xffc03388   /* CAN Controller 1 Mailbox 17 Acceptance Mask High Register */
+#define                       CAN1_AM17H  0xffc0338c   /* CAN Controller 1 Mailbox 17 Acceptance Mask Low Register */
+#define                       CAN1_AM18L  0xffc03390   /* CAN Controller 1 Mailbox 18 Acceptance Mask High Register */
+#define                       CAN1_AM18H  0xffc03394   /* CAN Controller 1 Mailbox 18 Acceptance Mask Low Register */
+#define                       CAN1_AM19L  0xffc03398   /* CAN Controller 1 Mailbox 19 Acceptance Mask High Register */
+#define                       CAN1_AM19H  0xffc0339c   /* CAN Controller 1 Mailbox 19 Acceptance Mask Low Register */
+#define                       CAN1_AM20L  0xffc033a0   /* CAN Controller 1 Mailbox 20 Acceptance Mask High Register */
+#define                       CAN1_AM20H  0xffc033a4   /* CAN Controller 1 Mailbox 20 Acceptance Mask Low Register */
+#define                       CAN1_AM21L  0xffc033a8   /* CAN Controller 1 Mailbox 21 Acceptance Mask High Register */
+#define                       CAN1_AM21H  0xffc033ac   /* CAN Controller 1 Mailbox 21 Acceptance Mask Low Register */
+#define                       CAN1_AM22L  0xffc033b0   /* CAN Controller 1 Mailbox 22 Acceptance Mask High Register */
+#define                       CAN1_AM22H  0xffc033b4   /* CAN Controller 1 Mailbox 22 Acceptance Mask Low Register */
+#define                       CAN1_AM23L  0xffc033b8   /* CAN Controller 1 Mailbox 23 Acceptance Mask High Register */
+#define                       CAN1_AM23H  0xffc033bc   /* CAN Controller 1 Mailbox 23 Acceptance Mask Low Register */
+#define                       CAN1_AM24L  0xffc033c0   /* CAN Controller 1 Mailbox 24 Acceptance Mask High Register */
+#define                       CAN1_AM24H  0xffc033c4   /* CAN Controller 1 Mailbox 24 Acceptance Mask Low Register */
+#define                       CAN1_AM25L  0xffc033c8   /* CAN Controller 1 Mailbox 25 Acceptance Mask High Register */
+#define                       CAN1_AM25H  0xffc033cc   /* CAN Controller 1 Mailbox 25 Acceptance Mask Low Register */
+#define                       CAN1_AM26L  0xffc033d0   /* CAN Controller 1 Mailbox 26 Acceptance Mask High Register */
+#define                       CAN1_AM26H  0xffc033d4   /* CAN Controller 1 Mailbox 26 Acceptance Mask Low Register */
+#define                       CAN1_AM27L  0xffc033d8   /* CAN Controller 1 Mailbox 27 Acceptance Mask High Register */
+#define                       CAN1_AM27H  0xffc033dc   /* CAN Controller 1 Mailbox 27 Acceptance Mask Low Register */
+#define                       CAN1_AM28L  0xffc033e0   /* CAN Controller 1 Mailbox 28 Acceptance Mask High Register */
+#define                       CAN1_AM28H  0xffc033e4   /* CAN Controller 1 Mailbox 28 Acceptance Mask Low Register */
+#define                       CAN1_AM29L  0xffc033e8   /* CAN Controller 1 Mailbox 29 Acceptance Mask High Register */
+#define                       CAN1_AM29H  0xffc033ec   /* CAN Controller 1 Mailbox 29 Acceptance Mask Low Register */
+#define                       CAN1_AM30L  0xffc033f0   /* CAN Controller 1 Mailbox 30 Acceptance Mask High Register */
+#define                       CAN1_AM30H  0xffc033f4   /* CAN Controller 1 Mailbox 30 Acceptance Mask Low Register */
+#define                       CAN1_AM31L  0xffc033f8   /* CAN Controller 1 Mailbox 31 Acceptance Mask High Register */
+#define                       CAN1_AM31H  0xffc033fc   /* CAN Controller 1 Mailbox 31 Acceptance Mask Low Register */
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define                  CAN1_MB00_DATA0  0xffc03400   /* CAN Controller 1 Mailbox 0 Data 0 Register */
+#define                  CAN1_MB00_DATA1  0xffc03404   /* CAN Controller 1 Mailbox 0 Data 1 Register */
+#define                  CAN1_MB00_DATA2  0xffc03408   /* CAN Controller 1 Mailbox 0 Data 2 Register */
+#define                  CAN1_MB00_DATA3  0xffc0340c   /* CAN Controller 1 Mailbox 0 Data 3 Register */
+#define                 CAN1_MB00_LENGTH  0xffc03410   /* CAN Controller 1 Mailbox 0 Length Register */
+#define              CAN1_MB00_TIMESTAMP  0xffc03414   /* CAN Controller 1 Mailbox 0 Timestamp Register */
+#define                    CAN1_MB00_ID0  0xffc03418   /* CAN Controller 1 Mailbox 0 ID0 Register */
+#define                    CAN1_MB00_ID1  0xffc0341c   /* CAN Controller 1 Mailbox 0 ID1 Register */
+#define                  CAN1_MB01_DATA0  0xffc03420   /* CAN Controller 1 Mailbox 1 Data 0 Register */
+#define                  CAN1_MB01_DATA1  0xffc03424   /* CAN Controller 1 Mailbox 1 Data 1 Register */
+#define                  CAN1_MB01_DATA2  0xffc03428   /* CAN Controller 1 Mailbox 1 Data 2 Register */
+#define                  CAN1_MB01_DATA3  0xffc0342c   /* CAN Controller 1 Mailbox 1 Data 3 Register */
+#define                 CAN1_MB01_LENGTH  0xffc03430   /* CAN Controller 1 Mailbox 1 Length Register */
+#define              CAN1_MB01_TIMESTAMP  0xffc03434   /* CAN Controller 1 Mailbox 1 Timestamp Register */
+#define                    CAN1_MB01_ID0  0xffc03438   /* CAN Controller 1 Mailbox 1 ID0 Register */
+#define                    CAN1_MB01_ID1  0xffc0343c   /* CAN Controller 1 Mailbox 1 ID1 Register */
+#define                  CAN1_MB02_DATA0  0xffc03440   /* CAN Controller 1 Mailbox 2 Data 0 Register */
+#define                  CAN1_MB02_DATA1  0xffc03444   /* CAN Controller 1 Mailbox 2 Data 1 Register */
+#define                  CAN1_MB02_DATA2  0xffc03448   /* CAN Controller 1 Mailbox 2 Data 2 Register */
+#define                  CAN1_MB02_DATA3  0xffc0344c   /* CAN Controller 1 Mailbox 2 Data 3 Register */
+#define                 CAN1_MB02_LENGTH  0xffc03450   /* CAN Controller 1 Mailbox 2 Length Register */
+#define              CAN1_MB02_TIMESTAMP  0xffc03454   /* CAN Controller 1 Mailbox 2 Timestamp Register */
+#define                    CAN1_MB02_ID0  0xffc03458   /* CAN Controller 1 Mailbox 2 ID0 Register */
+#define                    CAN1_MB02_ID1  0xffc0345c   /* CAN Controller 1 Mailbox 2 ID1 Register */
+#define                  CAN1_MB03_DATA0  0xffc03460   /* CAN Controller 1 Mailbox 3 Data 0 Register */
+#define                  CAN1_MB03_DATA1  0xffc03464   /* CAN Controller 1 Mailbox 3 Data 1 Register */
+#define                  CAN1_MB03_DATA2  0xffc03468   /* CAN Controller 1 Mailbox 3 Data 2 Register */
+#define                  CAN1_MB03_DATA3  0xffc0346c   /* CAN Controller 1 Mailbox 3 Data 3 Register */
+#define                 CAN1_MB03_LENGTH  0xffc03470   /* CAN Controller 1 Mailbox 3 Length Register */
+#define              CAN1_MB03_TIMESTAMP  0xffc03474   /* CAN Controller 1 Mailbox 3 Timestamp Register */
+#define                    CAN1_MB03_ID0  0xffc03478   /* CAN Controller 1 Mailbox 3 ID0 Register */
+#define                    CAN1_MB03_ID1  0xffc0347c   /* CAN Controller 1 Mailbox 3 ID1 Register */
+#define                  CAN1_MB04_DATA0  0xffc03480   /* CAN Controller 1 Mailbox 4 Data 0 Register */
+#define                  CAN1_MB04_DATA1  0xffc03484   /* CAN Controller 1 Mailbox 4 Data 1 Register */
+#define                  CAN1_MB04_DATA2  0xffc03488   /* CAN Controller 1 Mailbox 4 Data 2 Register */
+#define                  CAN1_MB04_DATA3  0xffc0348c   /* CAN Controller 1 Mailbox 4 Data 3 Register */
+#define                 CAN1_MB04_LENGTH  0xffc03490   /* CAN Controller 1 Mailbox 4 Length Register */
+#define              CAN1_MB04_TIMESTAMP  0xffc03494   /* CAN Controller 1 Mailbox 4 Timestamp Register */
+#define                    CAN1_MB04_ID0  0xffc03498   /* CAN Controller 1 Mailbox 4 ID0 Register */
+#define                    CAN1_MB04_ID1  0xffc0349c   /* CAN Controller 1 Mailbox 4 ID1 Register */
+#define                  CAN1_MB05_DATA0  0xffc034a0   /* CAN Controller 1 Mailbox 5 Data 0 Register */
+#define                  CAN1_MB05_DATA1  0xffc034a4   /* CAN Controller 1 Mailbox 5 Data 1 Register */
+#define                  CAN1_MB05_DATA2  0xffc034a8   /* CAN Controller 1 Mailbox 5 Data 2 Register */
+#define                  CAN1_MB05_DATA3  0xffc034ac   /* CAN Controller 1 Mailbox 5 Data 3 Register */
+#define                 CAN1_MB05_LENGTH  0xffc034b0   /* CAN Controller 1 Mailbox 5 Length Register */
+#define              CAN1_MB05_TIMESTAMP  0xffc034b4   /* CAN Controller 1 Mailbox 5 Timestamp Register */
+#define                    CAN1_MB05_ID0  0xffc034b8   /* CAN Controller 1 Mailbox 5 ID0 Register */
+#define                    CAN1_MB05_ID1  0xffc034bc   /* CAN Controller 1 Mailbox 5 ID1 Register */
+#define                  CAN1_MB06_DATA0  0xffc034c0   /* CAN Controller 1 Mailbox 6 Data 0 Register */
+#define                  CAN1_MB06_DATA1  0xffc034c4   /* CAN Controller 1 Mailbox 6 Data 1 Register */
+#define                  CAN1_MB06_DATA2  0xffc034c8   /* CAN Controller 1 Mailbox 6 Data 2 Register */
+#define                  CAN1_MB06_DATA3  0xffc034cc   /* CAN Controller 1 Mailbox 6 Data 3 Register */
+#define                 CAN1_MB06_LENGTH  0xffc034d0   /* CAN Controller 1 Mailbox 6 Length Register */
+#define              CAN1_MB06_TIMESTAMP  0xffc034d4   /* CAN Controller 1 Mailbox 6 Timestamp Register */
+#define                    CAN1_MB06_ID0  0xffc034d8   /* CAN Controller 1 Mailbox 6 ID0 Register */
+#define                    CAN1_MB06_ID1  0xffc034dc   /* CAN Controller 1 Mailbox 6 ID1 Register */
+#define                  CAN1_MB07_DATA0  0xffc034e0   /* CAN Controller 1 Mailbox 7 Data 0 Register */
+#define                  CAN1_MB07_DATA1  0xffc034e4   /* CAN Controller 1 Mailbox 7 Data 1 Register */
+#define                  CAN1_MB07_DATA2  0xffc034e8   /* CAN Controller 1 Mailbox 7 Data 2 Register */
+#define                  CAN1_MB07_DATA3  0xffc034ec   /* CAN Controller 1 Mailbox 7 Data 3 Register */
+#define                 CAN1_MB07_LENGTH  0xffc034f0   /* CAN Controller 1 Mailbox 7 Length Register */
+#define              CAN1_MB07_TIMESTAMP  0xffc034f4   /* CAN Controller 1 Mailbox 7 Timestamp Register */
+#define                    CAN1_MB07_ID0  0xffc034f8   /* CAN Controller 1 Mailbox 7 ID0 Register */
+#define                    CAN1_MB07_ID1  0xffc034fc   /* CAN Controller 1 Mailbox 7 ID1 Register */
+#define                  CAN1_MB08_DATA0  0xffc03500   /* CAN Controller 1 Mailbox 8 Data 0 Register */
+#define                  CAN1_MB08_DATA1  0xffc03504   /* CAN Controller 1 Mailbox 8 Data 1 Register */
+#define                  CAN1_MB08_DATA2  0xffc03508   /* CAN Controller 1 Mailbox 8 Data 2 Register */
+#define                  CAN1_MB08_DATA3  0xffc0350c   /* CAN Controller 1 Mailbox 8 Data 3 Register */
+#define                 CAN1_MB08_LENGTH  0xffc03510   /* CAN Controller 1 Mailbox 8 Length Register */
+#define              CAN1_MB08_TIMESTAMP  0xffc03514   /* CAN Controller 1 Mailbox 8 Timestamp Register */
+#define                    CAN1_MB08_ID0  0xffc03518   /* CAN Controller 1 Mailbox 8 ID0 Register */
+#define                    CAN1_MB08_ID1  0xffc0351c   /* CAN Controller 1 Mailbox 8 ID1 Register */
+#define                  CAN1_MB09_DATA0  0xffc03520   /* CAN Controller 1 Mailbox 9 Data 0 Register */
+#define                  CAN1_MB09_DATA1  0xffc03524   /* CAN Controller 1 Mailbox 9 Data 1 Register */
+#define                  CAN1_MB09_DATA2  0xffc03528   /* CAN Controller 1 Mailbox 9 Data 2 Register */
+#define                  CAN1_MB09_DATA3  0xffc0352c   /* CAN Controller 1 Mailbox 9 Data 3 Register */
+#define                 CAN1_MB09_LENGTH  0xffc03530   /* CAN Controller 1 Mailbox 9 Length Register */
+#define              CAN1_MB09_TIMESTAMP  0xffc03534   /* CAN Controller 1 Mailbox 9 Timestamp Register */
+#define                    CAN1_MB09_ID0  0xffc03538   /* CAN Controller 1 Mailbox 9 ID0 Register */
+#define                    CAN1_MB09_ID1  0xffc0353c   /* CAN Controller 1 Mailbox 9 ID1 Register */
+#define                  CAN1_MB10_DATA0  0xffc03540   /* CAN Controller 1 Mailbox 10 Data 0 Register */
+#define                  CAN1_MB10_DATA1  0xffc03544   /* CAN Controller 1 Mailbox 10 Data 1 Register */
+#define                  CAN1_MB10_DATA2  0xffc03548   /* CAN Controller 1 Mailbox 10 Data 2 Register */
+#define                  CAN1_MB10_DATA3  0xffc0354c   /* CAN Controller 1 Mailbox 10 Data 3 Register */
+#define                 CAN1_MB10_LENGTH  0xffc03550   /* CAN Controller 1 Mailbox 10 Length Register */
+#define              CAN1_MB10_TIMESTAMP  0xffc03554   /* CAN Controller 1 Mailbox 10 Timestamp Register */
+#define                    CAN1_MB10_ID0  0xffc03558   /* CAN Controller 1 Mailbox 10 ID0 Register */
+#define                    CAN1_MB10_ID1  0xffc0355c   /* CAN Controller 1 Mailbox 10 ID1 Register */
+#define                  CAN1_MB11_DATA0  0xffc03560   /* CAN Controller 1 Mailbox 11 Data 0 Register */
+#define                  CAN1_MB11_DATA1  0xffc03564   /* CAN Controller 1 Mailbox 11 Data 1 Register */
+#define                  CAN1_MB11_DATA2  0xffc03568   /* CAN Controller 1 Mailbox 11 Data 2 Register */
+#define                  CAN1_MB11_DATA3  0xffc0356c   /* CAN Controller 1 Mailbox 11 Data 3 Register */
+#define                 CAN1_MB11_LENGTH  0xffc03570   /* CAN Controller 1 Mailbox 11 Length Register */
+#define              CAN1_MB11_TIMESTAMP  0xffc03574   /* CAN Controller 1 Mailbox 11 Timestamp Register */
+#define                    CAN1_MB11_ID0  0xffc03578   /* CAN Controller 1 Mailbox 11 ID0 Register */
+#define                    CAN1_MB11_ID1  0xffc0357c   /* CAN Controller 1 Mailbox 11 ID1 Register */
+#define                  CAN1_MB12_DATA0  0xffc03580   /* CAN Controller 1 Mailbox 12 Data 0 Register */
+#define                  CAN1_MB12_DATA1  0xffc03584   /* CAN Controller 1 Mailbox 12 Data 1 Register */
+#define                  CAN1_MB12_DATA2  0xffc03588   /* CAN Controller 1 Mailbox 12 Data 2 Register */
+#define                  CAN1_MB12_DATA3  0xffc0358c   /* CAN Controller 1 Mailbox 12 Data 3 Register */
+#define                 CAN1_MB12_LENGTH  0xffc03590   /* CAN Controller 1 Mailbox 12 Length Register */
+#define              CAN1_MB12_TIMESTAMP  0xffc03594   /* CAN Controller 1 Mailbox 12 Timestamp Register */
+#define                    CAN1_MB12_ID0  0xffc03598   /* CAN Controller 1 Mailbox 12 ID0 Register */
+#define                    CAN1_MB12_ID1  0xffc0359c   /* CAN Controller 1 Mailbox 12 ID1 Register */
+#define                  CAN1_MB13_DATA0  0xffc035a0   /* CAN Controller 1 Mailbox 13 Data 0 Register */
+#define                  CAN1_MB13_DATA1  0xffc035a4   /* CAN Controller 1 Mailbox 13 Data 1 Register */
+#define                  CAN1_MB13_DATA2  0xffc035a8   /* CAN Controller 1 Mailbox 13 Data 2 Register */
+#define                  CAN1_MB13_DATA3  0xffc035ac   /* CAN Controller 1 Mailbox 13 Data 3 Register */
+#define                 CAN1_MB13_LENGTH  0xffc035b0   /* CAN Controller 1 Mailbox 13 Length Register */
+#define              CAN1_MB13_TIMESTAMP  0xffc035b4   /* CAN Controller 1 Mailbox 13 Timestamp Register */
+#define                    CAN1_MB13_ID0  0xffc035b8   /* CAN Controller 1 Mailbox 13 ID0 Register */
+#define                    CAN1_MB13_ID1  0xffc035bc   /* CAN Controller 1 Mailbox 13 ID1 Register */
+#define                  CAN1_MB14_DATA0  0xffc035c0   /* CAN Controller 1 Mailbox 14 Data 0 Register */
+#define                  CAN1_MB14_DATA1  0xffc035c4   /* CAN Controller 1 Mailbox 14 Data 1 Register */
+#define                  CAN1_MB14_DATA2  0xffc035c8   /* CAN Controller 1 Mailbox 14 Data 2 Register */
+#define                  CAN1_MB14_DATA3  0xffc035cc   /* CAN Controller 1 Mailbox 14 Data 3 Register */
+#define                 CAN1_MB14_LENGTH  0xffc035d0   /* CAN Controller 1 Mailbox 14 Length Register */
+#define              CAN1_MB14_TIMESTAMP  0xffc035d4   /* CAN Controller 1 Mailbox 14 Timestamp Register */
+#define                    CAN1_MB14_ID0  0xffc035d8   /* CAN Controller 1 Mailbox 14 ID0 Register */
+#define                    CAN1_MB14_ID1  0xffc035dc   /* CAN Controller 1 Mailbox 14 ID1 Register */
+#define                  CAN1_MB15_DATA0  0xffc035e0   /* CAN Controller 1 Mailbox 15 Data 0 Register */
+#define                  CAN1_MB15_DATA1  0xffc035e4   /* CAN Controller 1 Mailbox 15 Data 1 Register */
+#define                  CAN1_MB15_DATA2  0xffc035e8   /* CAN Controller 1 Mailbox 15 Data 2 Register */
+#define                  CAN1_MB15_DATA3  0xffc035ec   /* CAN Controller 1 Mailbox 15 Data 3 Register */
+#define                 CAN1_MB15_LENGTH  0xffc035f0   /* CAN Controller 1 Mailbox 15 Length Register */
+#define              CAN1_MB15_TIMESTAMP  0xffc035f4   /* CAN Controller 1 Mailbox 15 Timestamp Register */
+#define                    CAN1_MB15_ID0  0xffc035f8   /* CAN Controller 1 Mailbox 15 ID0 Register */
+#define                    CAN1_MB15_ID1  0xffc035fc   /* CAN Controller 1 Mailbox 15 ID1 Register */
+
+/* CAN Controller 1 Mailbox Data Registers */
+
+#define                  CAN1_MB16_DATA0  0xffc03600   /* CAN Controller 1 Mailbox 16 Data 0 Register */
+#define                  CAN1_MB16_DATA1  0xffc03604   /* CAN Controller 1 Mailbox 16 Data 1 Register */
+#define                  CAN1_MB16_DATA2  0xffc03608   /* CAN Controller 1 Mailbox 16 Data 2 Register */
+#define                  CAN1_MB16_DATA3  0xffc0360c   /* CAN Controller 1 Mailbox 16 Data 3 Register */
+#define                 CAN1_MB16_LENGTH  0xffc03610   /* CAN Controller 1 Mailbox 16 Length Register */
+#define              CAN1_MB16_TIMESTAMP  0xffc03614   /* CAN Controller 1 Mailbox 16 Timestamp Register */
+#define                    CAN1_MB16_ID0  0xffc03618   /* CAN Controller 1 Mailbox 16 ID0 Register */
+#define                    CAN1_MB16_ID1  0xffc0361c   /* CAN Controller 1 Mailbox 16 ID1 Register */
+#define                  CAN1_MB17_DATA0  0xffc03620   /* CAN Controller 1 Mailbox 17 Data 0 Register */
+#define                  CAN1_MB17_DATA1  0xffc03624   /* CAN Controller 1 Mailbox 17 Data 1 Register */
+#define                  CAN1_MB17_DATA2  0xffc03628   /* CAN Controller 1 Mailbox 17 Data 2 Register */
+#define                  CAN1_MB17_DATA3  0xffc0362c   /* CAN Controller 1 Mailbox 17 Data 3 Register */
+#define                 CAN1_MB17_LENGTH  0xffc03630   /* CAN Controller 1 Mailbox 17 Length Register */
+#define              CAN1_MB17_TIMESTAMP  0xffc03634   /* CAN Controller 1 Mailbox 17 Timestamp Register */
+#define                    CAN1_MB17_ID0  0xffc03638   /* CAN Controller 1 Mailbox 17 ID0 Register */
+#define                    CAN1_MB17_ID1  0xffc0363c   /* CAN Controller 1 Mailbox 17 ID1 Register */
+#define                  CAN1_MB18_DATA0  0xffc03640   /* CAN Controller 1 Mailbox 18 Data 0 Register */
+#define                  CAN1_MB18_DATA1  0xffc03644   /* CAN Controller 1 Mailbox 18 Data 1 Register */
+#define                  CAN1_MB18_DATA2  0xffc03648   /* CAN Controller 1 Mailbox 18 Data 2 Register */
+#define                  CAN1_MB18_DATA3  0xffc0364c   /* CAN Controller 1 Mailbox 18 Data 3 Register */
+#define                 CAN1_MB18_LENGTH  0xffc03650   /* CAN Controller 1 Mailbox 18 Length Register */
+#define              CAN1_MB18_TIMESTAMP  0xffc03654   /* CAN Controller 1 Mailbox 18 Timestamp Register */
+#define                    CAN1_MB18_ID0  0xffc03658   /* CAN Controller 1 Mailbox 18 ID0 Register */
+#define                    CAN1_MB18_ID1  0xffc0365c   /* CAN Controller 1 Mailbox 18 ID1 Register */
+#define                  CAN1_MB19_DATA0  0xffc03660   /* CAN Controller 1 Mailbox 19 Data 0 Register */
+#define                  CAN1_MB19_DATA1  0xffc03664   /* CAN Controller 1 Mailbox 19 Data 1 Register */
+#define                  CAN1_MB19_DATA2  0xffc03668   /* CAN Controller 1 Mailbox 19 Data 2 Register */
+#define                  CAN1_MB19_DATA3  0xffc0366c   /* CAN Controller 1 Mailbox 19 Data 3 Register */
+#define                 CAN1_MB19_LENGTH  0xffc03670   /* CAN Controller 1 Mailbox 19 Length Register */
+#define              CAN1_MB19_TIMESTAMP  0xffc03674   /* CAN Controller 1 Mailbox 19 Timestamp Register */
+#define                    CAN1_MB19_ID0  0xffc03678   /* CAN Controller 1 Mailbox 19 ID0 Register */
+#define                    CAN1_MB19_ID1  0xffc0367c   /* CAN Controller 1 Mailbox 19 ID1 Register */
+#define                  CAN1_MB20_DATA0  0xffc03680   /* CAN Controller 1 Mailbox 20 Data 0 Register */
+#define                  CAN1_MB20_DATA1  0xffc03684   /* CAN Controller 1 Mailbox 20 Data 1 Register */
+#define                  CAN1_MB20_DATA2  0xffc03688   /* CAN Controller 1 Mailbox 20 Data 2 Register */
+#define                  CAN1_MB20_DATA3  0xffc0368c   /* CAN Controller 1 Mailbox 20 Data 3 Register */
+#define                 CAN1_MB20_LENGTH  0xffc03690   /* CAN Controller 1 Mailbox 20 Length Register */
+#define              CAN1_MB20_TIMESTAMP  0xffc03694   /* CAN Controller 1 Mailbox 20 Timestamp Register */
+#define                    CAN1_MB20_ID0  0xffc03698   /* CAN Controller 1 Mailbox 20 ID0 Register */
+#define                    CAN1_MB20_ID1  0xffc0369c   /* CAN Controller 1 Mailbox 20 ID1 Register */
+#define                  CAN1_MB21_DATA0  0xffc036a0   /* CAN Controller 1 Mailbox 21 Data 0 Register */
+#define                  CAN1_MB21_DATA1  0xffc036a4   /* CAN Controller 1 Mailbox 21 Data 1 Register */
+#define                  CAN1_MB21_DATA2  0xffc036a8   /* CAN Controller 1 Mailbox 21 Data 2 Register */
+#define                  CAN1_MB21_DATA3  0xffc036ac   /* CAN Controller 1 Mailbox 21 Data 3 Register */
+#define                 CAN1_MB21_LENGTH  0xffc036b0   /* CAN Controller 1 Mailbox 21 Length Register */
+#define              CAN1_MB21_TIMESTAMP  0xffc036b4   /* CAN Controller 1 Mailbox 21 Timestamp Register */
+#define                    CAN1_MB21_ID0  0xffc036b8   /* CAN Controller 1 Mailbox 21 ID0 Register */
+#define                    CAN1_MB21_ID1  0xffc036bc   /* CAN Controller 1 Mailbox 21 ID1 Register */
+#define                  CAN1_MB22_DATA0  0xffc036c0   /* CAN Controller 1 Mailbox 22 Data 0 Register */
+#define                  CAN1_MB22_DATA1  0xffc036c4   /* CAN Controller 1 Mailbox 22 Data 1 Register */
+#define                  CAN1_MB22_DATA2  0xffc036c8   /* CAN Controller 1 Mailbox 22 Data 2 Register */
+#define                  CAN1_MB22_DATA3  0xffc036cc   /* CAN Controller 1 Mailbox 22 Data 3 Register */
+#define                 CAN1_MB22_LENGTH  0xffc036d0   /* CAN Controller 1 Mailbox 22 Length Register */
+#define              CAN1_MB22_TIMESTAMP  0xffc036d4   /* CAN Controller 1 Mailbox 22 Timestamp Register */
+#define                    CAN1_MB22_ID0  0xffc036d8   /* CAN Controller 1 Mailbox 22 ID0 Register */
+#define                    CAN1_MB22_ID1  0xffc036dc   /* CAN Controller 1 Mailbox 22 ID1 Register */
+#define                  CAN1_MB23_DATA0  0xffc036e0   /* CAN Controller 1 Mailbox 23 Data 0 Register */
+#define                  CAN1_MB23_DATA1  0xffc036e4   /* CAN Controller 1 Mailbox 23 Data 1 Register */
+#define                  CAN1_MB23_DATA2  0xffc036e8   /* CAN Controller 1 Mailbox 23 Data 2 Register */
+#define                  CAN1_MB23_DATA3  0xffc036ec   /* CAN Controller 1 Mailbox 23 Data 3 Register */
+#define                 CAN1_MB23_LENGTH  0xffc036f0   /* CAN Controller 1 Mailbox 23 Length Register */
+#define              CAN1_MB23_TIMESTAMP  0xffc036f4   /* CAN Controller 1 Mailbox 23 Timestamp Register */
+#define                    CAN1_MB23_ID0  0xffc036f8   /* CAN Controller 1 Mailbox 23 ID0 Register */
+#define                    CAN1_MB23_ID1  0xffc036fc   /* CAN Controller 1 Mailbox 23 ID1 Register */
+#define                  CAN1_MB24_DATA0  0xffc03700   /* CAN Controller 1 Mailbox 24 Data 0 Register */
+#define                  CAN1_MB24_DATA1  0xffc03704   /* CAN Controller 1 Mailbox 24 Data 1 Register */
+#define                  CAN1_MB24_DATA2  0xffc03708   /* CAN Controller 1 Mailbox 24 Data 2 Register */
+#define                  CAN1_MB24_DATA3  0xffc0370c   /* CAN Controller 1 Mailbox 24 Data 3 Register */
+#define                 CAN1_MB24_LENGTH  0xffc03710   /* CAN Controller 1 Mailbox 24 Length Register */
+#define              CAN1_MB24_TIMESTAMP  0xffc03714   /* CAN Controller 1 Mailbox 24 Timestamp Register */
+#define                    CAN1_MB24_ID0  0xffc03718   /* CAN Controller 1 Mailbox 24 ID0 Register */
+#define                    CAN1_MB24_ID1  0xffc0371c   /* CAN Controller 1 Mailbox 24 ID1 Register */
+#define                  CAN1_MB25_DATA0  0xffc03720   /* CAN Controller 1 Mailbox 25 Data 0 Register */
+#define                  CAN1_MB25_DATA1  0xffc03724   /* CAN Controller 1 Mailbox 25 Data 1 Register */
+#define                  CAN1_MB25_DATA2  0xffc03728   /* CAN Controller 1 Mailbox 25 Data 2 Register */
+#define                  CAN1_MB25_DATA3  0xffc0372c   /* CAN Controller 1 Mailbox 25 Data 3 Register */
+#define                 CAN1_MB25_LENGTH  0xffc03730   /* CAN Controller 1 Mailbox 25 Length Register */
+#define              CAN1_MB25_TIMESTAMP  0xffc03734   /* CAN Controller 1 Mailbox 25 Timestamp Register */
+#define                    CAN1_MB25_ID0  0xffc03738   /* CAN Controller 1 Mailbox 25 ID0 Register */
+#define                    CAN1_MB25_ID1  0xffc0373c   /* CAN Controller 1 Mailbox 25 ID1 Register */
+#define                  CAN1_MB26_DATA0  0xffc03740   /* CAN Controller 1 Mailbox 26 Data 0 Register */
+#define                  CAN1_MB26_DATA1  0xffc03744   /* CAN Controller 1 Mailbox 26 Data 1 Register */
+#define                  CAN1_MB26_DATA2  0xffc03748   /* CAN Controller 1 Mailbox 26 Data 2 Register */
+#define                  CAN1_MB26_DATA3  0xffc0374c   /* CAN Controller 1 Mailbox 26 Data 3 Register */
+#define                 CAN1_MB26_LENGTH  0xffc03750   /* CAN Controller 1 Mailbox 26 Length Register */
+#define              CAN1_MB26_TIMESTAMP  0xffc03754   /* CAN Controller 1 Mailbox 26 Timestamp Register */
+#define                    CAN1_MB26_ID0  0xffc03758   /* CAN Controller 1 Mailbox 26 ID0 Register */
+#define                    CAN1_MB26_ID1  0xffc0375c   /* CAN Controller 1 Mailbox 26 ID1 Register */
+#define                  CAN1_MB27_DATA0  0xffc03760   /* CAN Controller 1 Mailbox 27 Data 0 Register */
+#define                  CAN1_MB27_DATA1  0xffc03764   /* CAN Controller 1 Mailbox 27 Data 1 Register */
+#define                  CAN1_MB27_DATA2  0xffc03768   /* CAN Controller 1 Mailbox 27 Data 2 Register */
+#define                  CAN1_MB27_DATA3  0xffc0376c   /* CAN Controller 1 Mailbox 27 Data 3 Register */
+#define                 CAN1_MB27_LENGTH  0xffc03770   /* CAN Controller 1 Mailbox 27 Length Register */
+#define              CAN1_MB27_TIMESTAMP  0xffc03774   /* CAN Controller 1 Mailbox 27 Timestamp Register */
+#define                    CAN1_MB27_ID0  0xffc03778   /* CAN Controller 1 Mailbox 27 ID0 Register */
+#define                    CAN1_MB27_ID1  0xffc0377c   /* CAN Controller 1 Mailbox 27 ID1 Register */
+#define                  CAN1_MB28_DATA0  0xffc03780   /* CAN Controller 1 Mailbox 28 Data 0 Register */
+#define                  CAN1_MB28_DATA1  0xffc03784   /* CAN Controller 1 Mailbox 28 Data 1 Register */
+#define                  CAN1_MB28_DATA2  0xffc03788   /* CAN Controller 1 Mailbox 28 Data 2 Register */
+#define                  CAN1_MB28_DATA3  0xffc0378c   /* CAN Controller 1 Mailbox 28 Data 3 Register */
+#define                 CAN1_MB28_LENGTH  0xffc03790   /* CAN Controller 1 Mailbox 28 Length Register */
+#define              CAN1_MB28_TIMESTAMP  0xffc03794   /* CAN Controller 1 Mailbox 28 Timestamp Register */
+#define                    CAN1_MB28_ID0  0xffc03798   /* CAN Controller 1 Mailbox 28 ID0 Register */
+#define                    CAN1_MB28_ID1  0xffc0379c   /* CAN Controller 1 Mailbox 28 ID1 Register */
+#define                  CAN1_MB29_DATA0  0xffc037a0   /* CAN Controller 1 Mailbox 29 Data 0 Register */
+#define                  CAN1_MB29_DATA1  0xffc037a4   /* CAN Controller 1 Mailbox 29 Data 1 Register */
+#define                  CAN1_MB29_DATA2  0xffc037a8   /* CAN Controller 1 Mailbox 29 Data 2 Register */
+#define                  CAN1_MB29_DATA3  0xffc037ac   /* CAN Controller 1 Mailbox 29 Data 3 Register */
+#define                 CAN1_MB29_LENGTH  0xffc037b0   /* CAN Controller 1 Mailbox 29 Length Register */
+#define              CAN1_MB29_TIMESTAMP  0xffc037b4   /* CAN Controller 1 Mailbox 29 Timestamp Register */
+#define                    CAN1_MB29_ID0  0xffc037b8   /* CAN Controller 1 Mailbox 29 ID0 Register */
+#define                    CAN1_MB29_ID1  0xffc037bc   /* CAN Controller 1 Mailbox 29 ID1 Register */
+#define                  CAN1_MB30_DATA0  0xffc037c0   /* CAN Controller 1 Mailbox 30 Data 0 Register */
+#define                  CAN1_MB30_DATA1  0xffc037c4   /* CAN Controller 1 Mailbox 30 Data 1 Register */
+#define                  CAN1_MB30_DATA2  0xffc037c8   /* CAN Controller 1 Mailbox 30 Data 2 Register */
+#define                  CAN1_MB30_DATA3  0xffc037cc   /* CAN Controller 1 Mailbox 30 Data 3 Register */
+#define                 CAN1_MB30_LENGTH  0xffc037d0   /* CAN Controller 1 Mailbox 30 Length Register */
+#define              CAN1_MB30_TIMESTAMP  0xffc037d4   /* CAN Controller 1 Mailbox 30 Timestamp Register */
+#define                    CAN1_MB30_ID0  0xffc037d8   /* CAN Controller 1 Mailbox 30 ID0 Register */
+#define                    CAN1_MB30_ID1  0xffc037dc   /* CAN Controller 1 Mailbox 30 ID1 Register */
+#define                  CAN1_MB31_DATA0  0xffc037e0   /* CAN Controller 1 Mailbox 31 Data 0 Register */
+#define                  CAN1_MB31_DATA1  0xffc037e4   /* CAN Controller 1 Mailbox 31 Data 1 Register */
+#define                  CAN1_MB31_DATA2  0xffc037e8   /* CAN Controller 1 Mailbox 31 Data 2 Register */
+#define                  CAN1_MB31_DATA3  0xffc037ec   /* CAN Controller 1 Mailbox 31 Data 3 Register */
+#define                 CAN1_MB31_LENGTH  0xffc037f0   /* CAN Controller 1 Mailbox 31 Length Register */
+#define              CAN1_MB31_TIMESTAMP  0xffc037f4   /* CAN Controller 1 Mailbox 31 Timestamp Register */
+#define                    CAN1_MB31_ID0  0xffc037f8   /* CAN Controller 1 Mailbox 31 ID0 Register */
+#define                    CAN1_MB31_ID1  0xffc037fc   /* CAN Controller 1 Mailbox 31 ID1 Register */
+
+/* ATAPI Registers */
+
+#define                    ATAPI_CONTROL  0xffc03800   /* ATAPI Control Register */
+#define                     ATAPI_STATUS  0xffc03804   /* ATAPI Status Register */
+#define                   ATAPI_DEV_ADDR  0xffc03808   /* ATAPI Device Register Address */
+#define                  ATAPI_DEV_TXBUF  0xffc0380c   /* ATAPI Device Register Write Data */
+#define                  ATAPI_DEV_RXBUF  0xffc03810   /* ATAPI Device Register Read Data */
+#define                   ATAPI_INT_MASK  0xffc03814   /* ATAPI Interrupt Mask Register */
+#define                 ATAPI_INT_STATUS  0xffc03818   /* ATAPI Interrupt Status Register */
+#define                   ATAPI_XFER_LEN  0xffc0381c   /* ATAPI Length of Transfer */
+#define                ATAPI_LINE_STATUS  0xffc03820   /* ATAPI Line Status */
+#define                   ATAPI_SM_STATE  0xffc03824   /* ATAPI State Machine Status */
+#define                  ATAPI_TERMINATE  0xffc03828   /* ATAPI Host Terminate */
+#define                 ATAPI_PIO_TFRCNT  0xffc0382c   /* ATAPI PIO mode transfer count */
+#define                 ATAPI_DMA_TFRCNT  0xffc03830   /* ATAPI DMA mode transfer count */
+#define               ATAPI_UMAIN_TFRCNT  0xffc03834   /* ATAPI UDMAIN transfer count */
+#define             ATAPI_UDMAOUT_TFRCNT  0xffc03838   /* ATAPI UDMAOUT transfer count */
+#define                  ATAPI_REG_TIM_0  0xffc03840   /* ATAPI Register Transfer Timing 0 */
+#define                  ATAPI_PIO_TIM_0  0xffc03844   /* ATAPI PIO Timing 0 Register */
+#define                  ATAPI_PIO_TIM_1  0xffc03848   /* ATAPI PIO Timing 1 Register */
+#define                ATAPI_MULTI_TIM_0  0xffc03850   /* ATAPI Multi-DMA Timing 0 Register */
+#define                ATAPI_MULTI_TIM_1  0xffc03854   /* ATAPI Multi-DMA Timing 1 Register */
+#define                ATAPI_MULTI_TIM_2  0xffc03858   /* ATAPI Multi-DMA Timing 2 Register */
+#define                ATAPI_ULTRA_TIM_0  0xffc03860   /* ATAPI Ultra-DMA Timing 0 Register */
+#define                ATAPI_ULTRA_TIM_1  0xffc03864   /* ATAPI Ultra-DMA Timing 1 Register */
+#define                ATAPI_ULTRA_TIM_2  0xffc03868   /* ATAPI Ultra-DMA Timing 2 Register */
+#define                ATAPI_ULTRA_TIM_3  0xffc0386c   /* ATAPI Ultra-DMA Timing 3 Register */
+
+/* SDH Registers */
+
+#define                      SDH_PWR_CTL  0xffc03900   /* SDH Power Control */
+#define                      SDH_CLK_CTL  0xffc03904   /* SDH Clock Control */
+#define                     SDH_ARGUMENT  0xffc03908   /* SDH Argument */
+#define                      SDH_COMMAND  0xffc0390c   /* SDH Command */
+#define                     SDH_RESP_CMD  0xffc03910   /* SDH Response Command */
+#define                    SDH_RESPONSE0  0xffc03914   /* SDH Response0 */
+#define                    SDH_RESPONSE1  0xffc03918   /* SDH Response1 */
+#define                    SDH_RESPONSE2  0xffc0391c   /* SDH Response2 */
+#define                    SDH_RESPONSE3  0xffc03920   /* SDH Response3 */
+#define                   SDH_DATA_TIMER  0xffc03924   /* SDH Data Timer */
+#define                    SDH_DATA_LGTH  0xffc03928   /* SDH Data Length */
+#define                     SDH_DATA_CTL  0xffc0392c   /* SDH Data Control */
+#define                     SDH_DATA_CNT  0xffc03930   /* SDH Data Counter */
+#define                       SDH_STATUS  0xffc03934   /* SDH Status */
+#define                   SDH_STATUS_CLR  0xffc03938   /* SDH Status Clear */
+#define                        SDH_MASK0  0xffc0393c   /* SDH Interrupt0 Mask */
+#define                        SDH_MASK1  0xffc03940   /* SDH Interrupt1 Mask */
+#define                     SDH_FIFO_CNT  0xffc03948   /* SDH FIFO Counter */
+#define                         SDH_FIFO  0xffc03980   /* SDH Data FIFO */
+#define                     SDH_E_STATUS  0xffc039c0   /* SDH Exception Status */
+#define                       SDH_E_MASK  0xffc039c4   /* SDH Exception Mask */
+#define                          SDH_CFG  0xffc039c8   /* SDH Configuration */
+#define                   SDH_RD_WAIT_EN  0xffc039cc   /* SDH Read Wait Enable */
+#define                         SDH_PID0  0xffc039d0   /* SDH Peripheral Identification0 */
+#define                         SDH_PID1  0xffc039d4   /* SDH Peripheral Identification1 */
+#define                         SDH_PID2  0xffc039d8   /* SDH Peripheral Identification2 */
+#define                         SDH_PID3  0xffc039dc   /* SDH Peripheral Identification3 */
+#define                         SDH_PID4  0xffc039e0   /* SDH Peripheral Identification4 */
+#define                         SDH_PID5  0xffc039e4   /* SDH Peripheral Identification5 */
+#define                         SDH_PID6  0xffc039e8   /* SDH Peripheral Identification6 */
+#define                         SDH_PID7  0xffc039ec   /* SDH Peripheral Identification7 */
+
+/* HOST Port Registers */
+
+#define                     HOST_CONTROL  0xffc03a00   /* HOST Control Register */
+#define                      HOST_STATUS  0xffc03a04   /* HOST Status Register */
+#define                     HOST_TIMEOUT  0xffc03a08   /* HOST Acknowledge Mode Timeout Register */
+
+/* USB Control Registers */
+
+#define                        USB_FADDR  0xffc03c00   /* Function address register */
+#define                        USB_POWER  0xffc03c04   /* Power management register */
+#define                       USB_INTRTX  0xffc03c08   /* Interrupt register for endpoint 0 and Tx endpoint 1 to 7 */
+#define                       USB_INTRRX  0xffc03c0c   /* Interrupt register for Rx endpoints 1 to 7 */
+#define                      USB_INTRTXE  0xffc03c10   /* Interrupt enable register for IntrTx */
+#define                      USB_INTRRXE  0xffc03c14   /* Interrupt enable register for IntrRx */
+#define                      USB_INTRUSB  0xffc03c18   /* Interrupt register for common USB interrupts */
+#define                     USB_INTRUSBE  0xffc03c1c   /* Interrupt enable register for IntrUSB */
+#define                        USB_FRAME  0xffc03c20   /* USB frame number */
+#define                        USB_INDEX  0xffc03c24   /* Index register for selecting the indexed endpoint registers */
+#define                     USB_TESTMODE  0xffc03c28   /* Enabled USB 20 test modes */
+#define                     USB_GLOBINTR  0xffc03c2c   /* Global Interrupt Mask register and Wakeup Exception Interrupt */
+#define                   USB_GLOBAL_CTL  0xffc03c30   /* Global Clock Control for the core */
+
+/* USB Packet Control Registers */
+
+#define                USB_TX_MAX_PACKET  0xffc03c40   /* Maximum packet size for Host Tx endpoint */
+#define                         USB_CSR0  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                        USB_TXCSR  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
+#define                USB_RX_MAX_PACKET  0xffc03c48   /* Maximum packet size for Host Rx endpoint */
+#define                        USB_RXCSR  0xffc03c4c   /* Control Status register for Host Rx endpoint */
+#define                       USB_COUNT0  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                      USB_RXCOUNT  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
+#define                       USB_TXTYPE  0xffc03c54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint */
+#define                    USB_NAKLIMIT0  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                   USB_TXINTERVAL  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
+#define                       USB_RXTYPE  0xffc03c5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint */
+#define                   USB_RXINTERVAL  0xffc03c60   /* Sets the polling interval for Interrupt and Isochronous transfers or the NAK response timeout on Bulk transfers */
+#define                      USB_TXCOUNT  0xffc03c68   /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* USB Endpoint FIFO Registers */
+
+#define                     USB_EP0_FIFO  0xffc03c80   /* Endpoint 0 FIFO */
+#define                     USB_EP1_FIFO  0xffc03c88   /* Endpoint 1 FIFO */
+#define                     USB_EP2_FIFO  0xffc03c90   /* Endpoint 2 FIFO */
+#define                     USB_EP3_FIFO  0xffc03c98   /* Endpoint 3 FIFO */
+#define                     USB_EP4_FIFO  0xffc03ca0   /* Endpoint 4 FIFO */
+#define                     USB_EP5_FIFO  0xffc03ca8   /* Endpoint 5 FIFO */
+#define                     USB_EP6_FIFO  0xffc03cb0   /* Endpoint 6 FIFO */
+#define                     USB_EP7_FIFO  0xffc03cb8   /* Endpoint 7 FIFO */
+
+/* USB OTG Control Registers */
+
+#define                  USB_OTG_DEV_CTL  0xffc03d00   /* OTG Device Control Register */
+#define                 USB_OTG_VBUS_IRQ  0xffc03d04   /* OTG VBUS Control Interrupts */
+#define                USB_OTG_VBUS_MASK  0xffc03d08   /* VBUS Control Interrupt Enable */
+
+/* USB Phy Control Registers */
+
+#define                     USB_LINKINFO  0xffc03d48   /* Enables programming of some PHY-side delays */
+#define                        USB_VPLEN  0xffc03d4c   /* Determines duration of VBUS pulse for VBUS charging */
+#define                      USB_HS_EOF1  0xffc03d50   /* Time buffer for High-Speed transactions */
+#define                      USB_FS_EOF1  0xffc03d54   /* Time buffer for Full-Speed transactions */
+#define                      USB_LS_EOF1  0xffc03d58   /* Time buffer for Low-Speed transactions */
+
+/* (APHY_CNTRL is for ADI usage only) */
+
+#define                   USB_APHY_CNTRL  0xffc03de0   /* Register that increases visibility of Analog PHY */
+
+/* (APHY_CALIB is for ADI usage only) */
+
+#define                   USB_APHY_CALIB  0xffc03de4   /* Register used to set some calibration values */
+#define                  USB_APHY_CNTRL2  0xffc03de8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
+
+/* (PHY_TEST is for ADI usage only) */
+
+#define                     USB_PHY_TEST  0xffc03dec   /* Used for reducing simulation time and simplifies FIFO testability */
+#define                  USB_PLLOSC_CTRL  0xffc03df0   /* Used to program different parameters for USB PLL and Oscillator */
+#define                   USB_SRP_CLKDIV  0xffc03df4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
+
+/* USB Endpoint 0 Control Registers */
+
+#define                USB_EP_NI0_TXMAXP  0xffc03e00   /* Maximum packet size for Host Tx endpoint0 */
+#define                 USB_EP_NI0_TXCSR  0xffc03e04   /* Control Status register for endpoint 0 */
+#define                USB_EP_NI0_RXMAXP  0xffc03e08   /* Maximum packet size for Host Rx endpoint0 */
+#define                 USB_EP_NI0_RXCSR  0xffc03e0c   /* Control Status register for Host Rx endpoint0 */
+#define               USB_EP_NI0_RXCOUNT  0xffc03e10   /* Number of bytes received in endpoint 0 FIFO */
+#define                USB_EP_NI0_TXTYPE  0xffc03e14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint0 */
+#define            USB_EP_NI0_TXINTERVAL  0xffc03e18   /* Sets the NAK response timeout on Endpoint 0 */
+#define                USB_EP_NI0_RXTYPE  0xffc03e1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint0 */
+#define            USB_EP_NI0_RXINTERVAL  0xffc03e20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint0 */
+
+/* USB Endpoint 1 Control Registers */
+
+#define               USB_EP_NI0_TXCOUNT  0xffc03e28   /* Number of bytes to be written to the endpoint0 Tx FIFO */
+#define                USB_EP_NI1_TXMAXP  0xffc03e40   /* Maximum packet size for Host Tx endpoint1 */
+#define                 USB_EP_NI1_TXCSR  0xffc03e44   /* Control Status register for endpoint1 */
+#define                USB_EP_NI1_RXMAXP  0xffc03e48   /* Maximum packet size for Host Rx endpoint1 */
+#define                 USB_EP_NI1_RXCSR  0xffc03e4c   /* Control Status register for Host Rx endpoint1 */
+#define               USB_EP_NI1_RXCOUNT  0xffc03e50   /* Number of bytes received in endpoint1 FIFO */
+#define                USB_EP_NI1_TXTYPE  0xffc03e54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint1 */
+#define            USB_EP_NI1_TXINTERVAL  0xffc03e58   /* Sets the NAK response timeout on Endpoint1 */
+#define                USB_EP_NI1_RXTYPE  0xffc03e5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint1 */
+#define            USB_EP_NI1_RXINTERVAL  0xffc03e60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint1 */
+
+/* USB Endpoint 2 Control Registers */
+
+#define               USB_EP_NI1_TXCOUNT  0xffc03e68   /* Number of bytes to be written to the+H102 endpoint1 Tx FIFO */
+#define                USB_EP_NI2_TXMAXP  0xffc03e80   /* Maximum packet size for Host Tx endpoint2 */
+#define                 USB_EP_NI2_TXCSR  0xffc03e84   /* Control Status register for endpoint2 */
+#define                USB_EP_NI2_RXMAXP  0xffc03e88   /* Maximum packet size for Host Rx endpoint2 */
+#define                 USB_EP_NI2_RXCSR  0xffc03e8c   /* Control Status register for Host Rx endpoint2 */
+#define               USB_EP_NI2_RXCOUNT  0xffc03e90   /* Number of bytes received in endpoint2 FIFO */
+#define                USB_EP_NI2_TXTYPE  0xffc03e94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint2 */
+#define            USB_EP_NI2_TXINTERVAL  0xffc03e98   /* Sets the NAK response timeout on Endpoint2 */
+#define                USB_EP_NI2_RXTYPE  0xffc03e9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint2 */
+#define            USB_EP_NI2_RXINTERVAL  0xffc03ea0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint2 */
+
+/* USB Endpoint 3 Control Registers */
+
+#define               USB_EP_NI2_TXCOUNT  0xffc03ea8   /* Number of bytes to be written to the endpoint2 Tx FIFO */
+#define                USB_EP_NI3_TXMAXP  0xffc03ec0   /* Maximum packet size for Host Tx endpoint3 */
+#define                 USB_EP_NI3_TXCSR  0xffc03ec4   /* Control Status register for endpoint3 */
+#define                USB_EP_NI3_RXMAXP  0xffc03ec8   /* Maximum packet size for Host Rx endpoint3 */
+#define                 USB_EP_NI3_RXCSR  0xffc03ecc   /* Control Status register for Host Rx endpoint3 */
+#define               USB_EP_NI3_RXCOUNT  0xffc03ed0   /* Number of bytes received in endpoint3 FIFO */
+#define                USB_EP_NI3_TXTYPE  0xffc03ed4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint3 */
+#define            USB_EP_NI3_TXINTERVAL  0xffc03ed8   /* Sets the NAK response timeout on Endpoint3 */
+#define                USB_EP_NI3_RXTYPE  0xffc03edc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint3 */
+#define            USB_EP_NI3_RXINTERVAL  0xffc03ee0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint3 */
+
+/* USB Endpoint 4 Control Registers */
+
+#define               USB_EP_NI3_TXCOUNT  0xffc03ee8   /* Number of bytes to be written to the H124endpoint3 Tx FIFO */
+#define                USB_EP_NI4_TXMAXP  0xffc03f00   /* Maximum packet size for Host Tx endpoint4 */
+#define                 USB_EP_NI4_TXCSR  0xffc03f04   /* Control Status register for endpoint4 */
+#define                USB_EP_NI4_RXMAXP  0xffc03f08   /* Maximum packet size for Host Rx endpoint4 */
+#define                 USB_EP_NI4_RXCSR  0xffc03f0c   /* Control Status register for Host Rx endpoint4 */
+#define               USB_EP_NI4_RXCOUNT  0xffc03f10   /* Number of bytes received in endpoint4 FIFO */
+#define                USB_EP_NI4_TXTYPE  0xffc03f14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint4 */
+#define            USB_EP_NI4_TXINTERVAL  0xffc03f18   /* Sets the NAK response timeout on Endpoint4 */
+#define                USB_EP_NI4_RXTYPE  0xffc03f1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint4 */
+#define            USB_EP_NI4_RXINTERVAL  0xffc03f20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint4 */
+
+/* USB Endpoint 5 Control Registers */
+
+#define               USB_EP_NI4_TXCOUNT  0xffc03f28   /* Number of bytes to be written to the endpoint4 Tx FIFO */
+#define                USB_EP_NI5_TXMAXP  0xffc03f40   /* Maximum packet size for Host Tx endpoint5 */
+#define                 USB_EP_NI5_TXCSR  0xffc03f44   /* Control Status register for endpoint5 */
+#define                USB_EP_NI5_RXMAXP  0xffc03f48   /* Maximum packet size for Host Rx endpoint5 */
+#define                 USB_EP_NI5_RXCSR  0xffc03f4c   /* Control Status register for Host Rx endpoint5 */
+#define               USB_EP_NI5_RXCOUNT  0xffc03f50   /* Number of bytes received in endpoint5 FIFO */
+#define                USB_EP_NI5_TXTYPE  0xffc03f54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint5 */
+#define            USB_EP_NI5_TXINTERVAL  0xffc03f58   /* Sets the NAK response timeout on Endpoint5 */
+#define                USB_EP_NI5_RXTYPE  0xffc03f5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint5 */
+#define            USB_EP_NI5_RXINTERVAL  0xffc03f60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint5 */
+
+/* USB Endpoint 6 Control Registers */
+
+#define               USB_EP_NI5_TXCOUNT  0xffc03f68   /* Number of bytes to be written to the H145endpoint5 Tx FIFO */
+#define                USB_EP_NI6_TXMAXP  0xffc03f80   /* Maximum packet size for Host Tx endpoint6 */
+#define                 USB_EP_NI6_TXCSR  0xffc03f84   /* Control Status register for endpoint6 */
+#define                USB_EP_NI6_RXMAXP  0xffc03f88   /* Maximum packet size for Host Rx endpoint6 */
+#define                 USB_EP_NI6_RXCSR  0xffc03f8c   /* Control Status register for Host Rx endpoint6 */
+#define               USB_EP_NI6_RXCOUNT  0xffc03f90   /* Number of bytes received in endpoint6 FIFO */
+#define                USB_EP_NI6_TXTYPE  0xffc03f94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint6 */
+#define            USB_EP_NI6_TXINTERVAL  0xffc03f98   /* Sets the NAK response timeout on Endpoint6 */
+#define                USB_EP_NI6_RXTYPE  0xffc03f9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint6 */
+#define            USB_EP_NI6_RXINTERVAL  0xffc03fa0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint6 */
+
+/* USB Endpoint 7 Control Registers */
+
+#define               USB_EP_NI6_TXCOUNT  0xffc03fa8   /* Number of bytes to be written to the endpoint6 Tx FIFO */
+#define                USB_EP_NI7_TXMAXP  0xffc03fc0   /* Maximum packet size for Host Tx endpoint7 */
+#define                 USB_EP_NI7_TXCSR  0xffc03fc4   /* Control Status register for endpoint7 */
+#define                USB_EP_NI7_RXMAXP  0xffc03fc8   /* Maximum packet size for Host Rx endpoint7 */
+#define                 USB_EP_NI7_RXCSR  0xffc03fcc   /* Control Status register for Host Rx endpoint7 */
+#define               USB_EP_NI7_RXCOUNT  0xffc03fd0   /* Number of bytes received in endpoint7 FIFO */
+#define                USB_EP_NI7_TXTYPE  0xffc03fd4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint7 */
+#define            USB_EP_NI7_TXINTERVAL  0xffc03fd8   /* Sets the NAK response timeout on Endpoint7 */
+#define                USB_EP_NI7_RXTYPE  0xffc03fdc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint7 */
+#define            USB_EP_NI7_RXINTERVAL  0xffc03ff0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint7 */
+#define               USB_EP_NI7_TXCOUNT  0xffc03ff8   /* Number of bytes to be written to the endpoint7 Tx FIFO */
+#define                USB_DMA_INTERRUPT  0xffc04000   /* Indicates pending interrupts for the DMA channels */
+
+/* USB Channel 0 Config Registers */
+
+#define                  USB_DMA0CONTROL  0xffc04004   /* DMA master channel 0 configuration */
+#define                  USB_DMA0ADDRLOW  0xffc04008   /* Lower 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0ADDRHIGH  0xffc0400c   /* Upper 16-bits of memory source/destination address for DMA master channel 0 */
+#define                 USB_DMA0COUNTLOW  0xffc04010   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 0 */
+#define                USB_DMA0COUNTHIGH  0xffc04014   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 0 */
+
+/* USB Channel 1 Config Registers */
+
+#define                  USB_DMA1CONTROL  0xffc04024   /* DMA master channel 1 configuration */
+#define                  USB_DMA1ADDRLOW  0xffc04028   /* Lower 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1ADDRHIGH  0xffc0402c   /* Upper 16-bits of memory source/destination address for DMA master channel 1 */
+#define                 USB_DMA1COUNTLOW  0xffc04030   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 1 */
+#define                USB_DMA1COUNTHIGH  0xffc04034   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 1 */
+
+/* USB Channel 2 Config Registers */
+
+#define                  USB_DMA2CONTROL  0xffc04044   /* DMA master channel 2 configuration */
+#define                  USB_DMA2ADDRLOW  0xffc04048   /* Lower 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2ADDRHIGH  0xffc0404c   /* Upper 16-bits of memory source/destination address for DMA master channel 2 */
+#define                 USB_DMA2COUNTLOW  0xffc04050   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 2 */
+#define                USB_DMA2COUNTHIGH  0xffc04054   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 2 */
+
+/* USB Channel 3 Config Registers */
+
+#define                  USB_DMA3CONTROL  0xffc04064   /* DMA master channel 3 configuration */
+#define                  USB_DMA3ADDRLOW  0xffc04068   /* Lower 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3ADDRHIGH  0xffc0406c   /* Upper 16-bits of memory source/destination address for DMA master channel 3 */
+#define                 USB_DMA3COUNTLOW  0xffc04070   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 3 */
+#define                USB_DMA3COUNTHIGH  0xffc04074   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 3 */
+
+/* USB Channel 4 Config Registers */
+
+#define                  USB_DMA4CONTROL  0xffc04084   /* DMA master channel 4 configuration */
+#define                  USB_DMA4ADDRLOW  0xffc04088   /* Lower 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4ADDRHIGH  0xffc0408c   /* Upper 16-bits of memory source/destination address for DMA master channel 4 */
+#define                 USB_DMA4COUNTLOW  0xffc04090   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 4 */
+#define                USB_DMA4COUNTHIGH  0xffc04094   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 4 */
+
+/* USB Channel 5 Config Registers */
+
+#define                  USB_DMA5CONTROL  0xffc040a4   /* DMA master channel 5 configuration */
+#define                  USB_DMA5ADDRLOW  0xffc040a8   /* Lower 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5ADDRHIGH  0xffc040ac   /* Upper 16-bits of memory source/destination address for DMA master channel 5 */
+#define                 USB_DMA5COUNTLOW  0xffc040b0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 5 */
+#define                USB_DMA5COUNTHIGH  0xffc040b4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 5 */
+
+/* USB Channel 6 Config Registers */
+
+#define                  USB_DMA6CONTROL  0xffc040c4   /* DMA master channel 6 configuration */
+#define                  USB_DMA6ADDRLOW  0xffc040c8   /* Lower 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6ADDRHIGH  0xffc040cc   /* Upper 16-bits of memory source/destination address for DMA master channel 6 */
+#define                 USB_DMA6COUNTLOW  0xffc040d0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 6 */
+#define                USB_DMA6COUNTHIGH  0xffc040d4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 6 */
+
+/* USB Channel 7 Config Registers */
+
+#define                  USB_DMA7CONTROL  0xffc040e4   /* DMA master channel 7 configuration */
+#define                  USB_DMA7ADDRLOW  0xffc040e8   /* Lower 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7ADDRHIGH  0xffc040ec   /* Upper 16-bits of memory source/destination address for DMA master channel 7 */
+#define                 USB_DMA7COUNTLOW  0xffc040f0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 7 */
+#define                USB_DMA7COUNTHIGH  0xffc040f4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 7 */
+
+/* Keypad Registers */
+
+#define                         KPAD_CTL  0xffc04100   /* Controls keypad module enable and disable */
+#define                    KPAD_PRESCALE  0xffc04104   /* Establish a time base for programing the KPAD_MSEL register */
+#define                        KPAD_MSEL  0xffc04108   /* Selects delay parameters for keypad interface sensitivity */
+#define                      KPAD_ROWCOL  0xffc0410c   /* Captures the row and column output values of the keys pressed */
+#define                        KPAD_STAT  0xffc04110   /* Holds and clears the status of the keypad interface interrupt */
+#define                    KPAD_SOFTEVAL  0xffc04114   /* Lets software force keypad interface to check for keys being pressed */
+
+/* Pixel Compositor (PIXC) Registers */
+
+#define                         PIXC_CTL  0xffc04400   /* Overlay enable, resampling mode, I/O data format, transparency enable, watermark level, FIFO status */
+#define                         PIXC_PPL  0xffc04404   /* Holds the number of pixels per line of the display */
+#define                         PIXC_LPF  0xffc04408   /* Holds the number of lines per frame of the display */
+#define                     PIXC_AHSTART  0xffc0440c   /* Contains horizontal start pixel information of the overlay data (set A) */
+#define                       PIXC_AHEND  0xffc04410   /* Contains horizontal end pixel information of the overlay data (set A) */
+#define                     PIXC_AVSTART  0xffc04414   /* Contains vertical start pixel information of the overlay data (set A) */
+#define                       PIXC_AVEND  0xffc04418   /* Contains vertical end pixel information of the overlay data (set A) */
+#define                     PIXC_ATRANSP  0xffc0441c   /* Contains the transparency ratio (set A) */
+#define                     PIXC_BHSTART  0xffc04420   /* Contains horizontal start pixel information of the overlay data (set B) */
+#define                       PIXC_BHEND  0xffc04424   /* Contains horizontal end pixel information of the overlay data (set B) */
+#define                     PIXC_BVSTART  0xffc04428   /* Contains vertical start pixel information of the overlay data (set B) */
+#define                       PIXC_BVEND  0xffc0442c   /* Contains vertical end pixel information of the overlay data (set B) */
+#define                     PIXC_BTRANSP  0xffc04430   /* Contains the transparency ratio (set B) */
+#define                    PIXC_INTRSTAT  0xffc0443c   /* Overlay interrupt configuration/status */
+#define                       PIXC_RYCON  0xffc04440   /* Color space conversion matrix register. Contains the R/Y conversion coefficients */
+#define                       PIXC_GUCON  0xffc04444   /* Color space conversion matrix register. Contains the G/U conversion coefficients */
+#define                       PIXC_BVCON  0xffc04448   /* Color space conversion matrix register. Contains the B/V conversion coefficients */
+#define                      PIXC_CCBIAS  0xffc0444c   /* Bias values for the color space conversion matrix */
+#define                          PIXC_TC  0xffc04450   /* Holds the transparent color value */
+
+/* Handshake MDMA 0 Registers */
+
+#define                   HMDMA0_CONTROL  0xffc04500   /* Handshake MDMA0 Control Register */
+#define                    HMDMA0_ECINIT  0xffc04504   /* Handshake MDMA0 Initial Edge Count Register */
+#define                    HMDMA0_BCINIT  0xffc04508   /* Handshake MDMA0 Initial Block Count Register */
+#define                  HMDMA0_ECURGENT  0xffc0450c   /* Handshake MDMA0 Urgent Edge Count Threshhold Register */
+#define                HMDMA0_ECOVERFLOW  0xffc04510   /* Handshake MDMA0 Edge Count Overflow Interrupt Register */
+#define                    HMDMA0_ECOUNT  0xffc04514   /* Handshake MDMA0 Current Edge Count Register */
+#define                    HMDMA0_BCOUNT  0xffc04518   /* Handshake MDMA0 Current Block Count Register */
+
+/* Handshake MDMA 1 Registers */
+
+#define                   HMDMA1_CONTROL  0xffc04540   /* Handshake MDMA1 Control Register */
+#define                    HMDMA1_ECINIT  0xffc04544   /* Handshake MDMA1 Initial Edge Count Register */
+#define                    HMDMA1_BCINIT  0xffc04548   /* Handshake MDMA1 Initial Block Count Register */
+#define                  HMDMA1_ECURGENT  0xffc0454c   /* Handshake MDMA1 Urgent Edge Count Threshhold Register */
+#define                HMDMA1_ECOVERFLOW  0xffc04550   /* Handshake MDMA1 Edge Count Overflow Interrupt Register */
+#define                    HMDMA1_ECOUNT  0xffc04554   /* Handshake MDMA1 Current Edge Count Register */
+#define                    HMDMA1_BCOUNT  0xffc04558   /* Handshake MDMA1 Current Block Count Register */
+
+
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for PIXC_CTL */
+
+#define                   PIXC_EN  0x1        /* Pixel Compositor Enable */
+#define                  OVR_A_EN  0x2        /* Overlay A Enable */
+#define                  OVR_B_EN  0x4        /* Overlay B Enable */
+#define                  IMG_FORM  0x8        /* Image Data Format */
+#define                  OVR_FORM  0x10       /* Overlay Data Format */
+#define                  OUT_FORM  0x20       /* Output Data Format */
+#define                   UDS_MOD  0x40       /* Resampling Mode */
+#define                     TC_EN  0x80       /* Transparent Color Enable */
+#define                  IMG_STAT  0x300      /* Image FIFO Status */
+#define                  OVR_STAT  0xc00      /* Overlay FIFO Status */
+#define                    WM_LVL  0x3000     /* FIFO Watermark Level */
+
+/* Bit masks for PIXC_AHSTART */
+
+#define                  A_HSTART  0xfff      /* Horizontal Start Coordinates */
+
+/* Bit masks for PIXC_AHEND */
+
+#define                    A_HEND  0xfff      /* Horizontal End Coordinates */
+
+/* Bit masks for PIXC_AVSTART */
+
+#define                  A_VSTART  0x3ff      /* Vertical Start Coordinates */
+
+/* Bit masks for PIXC_AVEND */
+
+#define                    A_VEND  0x3ff      /* Vertical End Coordinates */
+
+/* Bit masks for PIXC_ATRANSP */
+
+#define                  A_TRANSP  0xf        /* Transparency Value */
+
+/* Bit masks for PIXC_BHSTART */
+
+#define                  B_HSTART  0xfff      /* Horizontal Start Coordinates */
+
+/* Bit masks for PIXC_BHEND */
+
+#define                    B_HEND  0xfff      /* Horizontal End Coordinates */
+
+/* Bit masks for PIXC_BVSTART */
+
+#define                  B_VSTART  0x3ff      /* Vertical Start Coordinates */
+
+/* Bit masks for PIXC_BVEND */
+
+#define                    B_VEND  0x3ff      /* Vertical End Coordinates */
+
+/* Bit masks for PIXC_BTRANSP */
+
+#define                  B_TRANSP  0xf        /* Transparency Value */
+
+/* Bit masks for PIXC_INTRSTAT */
+
+#define                OVR_INT_EN  0x1        /* Interrupt at End of Last Valid Overlay */
+#define                FRM_INT_EN  0x2        /* Interrupt at End of Frame */
+#define              OVR_INT_STAT  0x4        /* Overlay Interrupt Status */
+#define              FRM_INT_STAT  0x8        /* Frame Interrupt Status */
+
+/* Bit masks for PIXC_RYCON */
+
+#define                       A11  0x3ff      /* A11 in the Coefficient Matrix */
+#define                       A12  0xffc00    /* A12 in the Coefficient Matrix */
+#define                       A13  0x3ff00000 /* A13 in the Coefficient Matrix */
+#define                  RY_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_GUCON */
+
+#define                       A21  0x3ff      /* A21 in the Coefficient Matrix */
+#define                       A22  0xffc00    /* A22 in the Coefficient Matrix */
+#define                       A23  0x3ff00000 /* A23 in the Coefficient Matrix */
+#define                  GU_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_BVCON */
+
+#define                       A31  0x3ff      /* A31 in the Coefficient Matrix */
+#define                       A32  0xffc00    /* A32 in the Coefficient Matrix */
+#define                       A33  0x3ff00000 /* A33 in the Coefficient Matrix */
+#define                  BV_MULT4  0x40000000 /* Multiply Row by 4 */
+
+/* Bit masks for PIXC_CCBIAS */
+
+#define                       A14  0x3ff      /* A14 in the Bias Vector */
+#define                       A24  0xffc00    /* A24 in the Bias Vector */
+#define                       A34  0x3ff00000 /* A34 in the Bias Vector */
+
+/* Bit masks for PIXC_TC */
+
+#define                  RY_TRANS  0xff       /* Transparent Color - R/Y Component */
+#define                  GU_TRANS  0xff00     /* Transparent Color - G/U Component */
+#define                  BV_TRANS  0xff0000   /* Transparent Color - B/V Component */
+
+/* Bit masks for HOST_CONTROL */
+
+#define                   HOST_EN  0x1        /* Host Enable */
+#define                  HOST_END  0x2        /* Host Endianess */
+#define                 DATA_SIZE  0x4        /* Data Size */
+#define                  HOST_RST  0x8        /* Host Reset */
+#define                  HRDY_OVR  0x20       /* Host Ready Override */
+#define                  INT_MODE  0x40       /* Interrupt Mode */
+#define                     BT_EN  0x80       /* Bus Timeout Enable */
+#define                       EHW  0x100      /* Enable Host Write */
+#define                       EHR  0x200      /* Enable Host Read */
+#define                       BDR  0x400      /* Burst DMA Requests */
+
+/* Bit masks for HOST_STATUS */
+
+#define                     READY  0x1        /* DMA Ready */
+#define                  FIFOFULL  0x2        /* FIFO Full */
+#define                 FIFOEMPTY  0x4        /* FIFO Empty */
+#define              DMA_COMPLETE  0x8        /* DMA Complete */
+#define                      HSHK  0x10       /* Host Handshake */
+#define                   TIMEOUT  0x20       /* Host Timeout */
+#define                      HIRQ  0x40       /* Host Interrupt Request */
+#define                ALLOW_CNFG  0x80       /* Allow New Configuration */
+#define                   DMA_DIR  0x100      /* DMA Direction */
+#define                       BTE  0x200      /* Bus Timeout Enabled */
+
+/* Bit masks for HOST_TIMEOUT */
+
+#define             COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
+
+/* Bit masks for MXVR_CONFIG */
+
+#define                    MXVREN  0x1        /* MXVR Enable */
+#define                      MMSM  0x2        /* MXVR Master/Slave Mode Select */
+#define                    ACTIVE  0x4        /* Active Mode */
+#define                    SDELAY  0x8        /* Synchronous Data Delay */
+#define                   NCMRXEN  0x10       /* Normal Control Message Receive Enable */
+#define                   RWRRXEN  0x20       /* Remote Write Receive Enable */
+#define                     MTXEN  0x40       /* MXVR Transmit Data Enable */
+#define                    MTXONB  0x80       /* MXVR Phy Transmitter On */
+#define                   EPARITY  0x100      /* Even Parity Select */
+#define                       MSB  0x1e00     /* Master Synchronous Boundary */
+#define                    APRXEN  0x2000     /* Asynchronous Packet Receive Enable */
+#define                    WAKEUP  0x4000     /* Wake-Up */
+#define                     LMECH  0x8000     /* Lock Mechanism Select */
+
+/* Bit masks for MXVR_STATE_0 */
+
+#define                      NACT  0x1        /* Network Activity */
+#define                    SBLOCK  0x2        /* Super Block Lock */
+#define                   FMPLLST  0xc        /* Frequency Multiply PLL SM State */
+#define                  CDRPLLST  0xe0       /* Clock/Data Recovery PLL SM State */
+#define                     APBSY  0x100      /* Asynchronous Packet Transmit Buffer Busy */
+#define                     APARB  0x200      /* Asynchronous Packet Arbitrating */
+#define                      APTX  0x400      /* Asynchronous Packet Transmitting */
+#define                      APRX  0x800      /* Receiving Asynchronous Packet */
+#define                     CMBSY  0x1000     /* Control Message Transmit Buffer Busy */
+#define                     CMARB  0x2000     /* Control Message Arbitrating */
+#define                      CMTX  0x4000     /* Control Message Transmitting */
+#define                      CMRX  0x8000     /* Receiving Control Message */
+#define                    MRXONB  0x10000    /* MRXONB Pin State */
+#define                     RGSIP  0x20000    /* Remote Get Source In Progress */
+#define                     DALIP  0x40000    /* Resource Deallocate In Progress */
+#define                      ALIP  0x80000    /* Resource Allocate In Progress */
+#define                     RRDIP  0x100000   /* Remote Read In Progress */
+#define                     RWRIP  0x200000   /* Remote Write In Progress */
+#define                     FLOCK  0x400000   /* Frame Lock */
+#define                     BLOCK  0x800000   /* Block Lock */
+#define                       RSB  0xf000000  /* Received Synchronous Boundary */
+#define                   DERRNUM  0xf0000000 /* DMA Error Channel Number */
+
+/* Bit masks for MXVR_STATE_1 */
+
+#define                   SRXNUMB  0xf        /* Synchronous Receive FIFO Number of Bytes */
+#define                   STXNUMB  0xf0       /* Synchronous Transmit FIFO Number of Bytes */
+#define                    APCONT  0x100      /* Asynchronous Packet Continuation */
+#define                  OBERRNUM  0xe00      /* DMA Out of Bounds Error Channel Number */
+#define                DMAACTIVE0  0x10000    /* DMA0 Active */
+#define                DMAACTIVE1  0x20000    /* DMA1 Active */
+#define                DMAACTIVE2  0x40000    /* DMA2 Active */
+#define                DMAACTIVE3  0x80000    /* DMA3 Active */
+#define                DMAACTIVE4  0x100000   /* DMA4 Active */
+#define                DMAACTIVE5  0x200000   /* DMA5 Active */
+#define                DMAACTIVE6  0x400000   /* DMA6 Active */
+#define                DMAACTIVE7  0x800000   /* DMA7 Active */
+#define                  DMAPMEN0  0x1000000  /* DMA0 Pattern Matching Enabled */
+#define                  DMAPMEN1  0x2000000  /* DMA1 Pattern Matching Enabled */
+#define                  DMAPMEN2  0x4000000  /* DMA2 Pattern Matching Enabled */
+#define                  DMAPMEN3  0x8000000  /* DMA3 Pattern Matching Enabled */
+#define                  DMAPMEN4  0x10000000 /* DMA4 Pattern Matching Enabled */
+#define                  DMAPMEN5  0x20000000 /* DMA5 Pattern Matching Enabled */
+#define                  DMAPMEN6  0x40000000 /* DMA6 Pattern Matching Enabled */
+#define                  DMAPMEN7  0x80000000 /* DMA7 Pattern Matching Enabled */
+
+/* Bit masks for MXVR_INT_STAT_0 */
+
+#define                      NI2A  0x1        /* Network Inactive to Active */
+#define                      NA2I  0x2        /* Network Active to Inactive */
+#define                     SBU2L  0x4        /* Super Block Unlock to Lock */
+#define                     SBL2U  0x8        /* Super Block Lock to Unlock */
+#define                       PRU  0x10       /* Position Register Updated */
+#define                      MPRU  0x20       /* Maximum Position Register Updated */
+#define                       DRU  0x40       /* Delay Register Updated */
+#define                      MDRU  0x80       /* Maximum Delay Register Updated */
+#define                       SBU  0x100      /* Synchronous Boundary Updated */
+#define                       ATU  0x200      /* Allocation Table Updated */
+#define                      FCZ0  0x400      /* Frame Counter 0 Zero */
+#define                      FCZ1  0x800      /* Frame Counter 1 Zero */
+#define                      PERR  0x1000     /* Parity Error */
+#define                      MH2L  0x2000     /* MRXONB High to Low */
+#define                      ML2H  0x4000     /* MRXONB Low to High */
+#define                       WUP  0x8000     /* Wake-Up Preamble Received */
+#define                      FU2L  0x10000    /* Frame Unlock to Lock */
+#define                      FL2U  0x20000    /* Frame Lock to Unlock */
+#define                      BU2L  0x40000    /* Block Unlock to Lock */
+#define                      BL2U  0x80000    /* Block Lock to Unlock */
+#define                     OBERR  0x100000   /* DMA Out of Bounds Error */
+#define                       PFL  0x200000   /* PLL Frequency Locked */
+#define                       SCZ  0x400000   /* System Clock Counter Zero */
+#define                      FERR  0x800000   /* FIFO Error */
+#define                       CMR  0x1000000  /* Control Message Received */
+#define                     CMROF  0x2000000  /* Control Message Receive Buffer Overflow */
+#define                      CMTS  0x4000000  /* Control Message Transmit Buffer Successfully Sent */
+#define                      CMTC  0x8000000  /* Control Message Transmit Buffer Successfully Cancelled */
+#define                      RWRC  0x10000000 /* Remote Write Control Message Completed */
+#define                       BCZ  0x20000000 /* Block Counter Zero */
+#define                     BMERR  0x40000000 /* Biphase Mark Coding Error */
+#define                      DERR  0x80000000 /* DMA Error */
+
+/* Bit masks for MXVR_INT_STAT_1 */
+
+#define                    HDONE0  0x1        /* DMA0 Half Done */
+#define                     DONE0  0x2        /* DMA0 Done */
+#define                       APR  0x4        /* Asynchronous Packet Received */
+#define                     APROF  0x8        /* Asynchronous Packet Receive Buffer Overflow */
+#define                    HDONE1  0x10       /* DMA1 Half Done */
+#define                     DONE1  0x20       /* DMA1 Done */
+#define                      APTS  0x40       /* Asynchronous Packet Transmit Buffer Successfully Sent */
+#define                      APTC  0x80       /* Asynchronous Packet Transmit Buffer Successfully Cancelled */
+#define                    HDONE2  0x100      /* DMA2 Half Done */
+#define                     DONE2  0x200      /* DMA2 Done */
+#define                     APRCE  0x400      /* Asynchronous Packet Receive CRC Error */
+#define                     APRPE  0x800      /* Asynchronous Packet Receive Packet Error */
+#define                    HDONE3  0x1000     /* DMA3 Half Done */
+#define                     DONE3  0x2000     /* DMA3 Done */
+#define                    HDONE4  0x10000    /* DMA4 Half Done */
+#define                     DONE4  0x20000    /* DMA4 Done */
+#define                    HDONE5  0x100000   /* DMA5 Half Done */
+#define                     DONE5  0x200000   /* DMA5 Done */
+#define                    HDONE6  0x1000000  /* DMA6 Half Done */
+#define                     DONE6  0x2000000  /* DMA6 Done */
+#define                    HDONE7  0x10000000 /* DMA7 Half Done */
+#define                     DONE7  0x20000000 /* DMA7 Done */
+
+/* Bit masks for MXVR_INT_EN_0 */
+
+#define                    NI2AEN  0x1        /* Network Inactive to Active Interrupt Enable */
+#define                    NA2IEN  0x2        /* Network Active to Inactive Interrupt Enable */
+#define                   SBU2LEN  0x4        /* Super Block Unlock to Lock Interrupt Enable */
+#define                   SBL2UEN  0x8        /* Super Block Lock to Unlock Interrupt Enable */
+#define                     PRUEN  0x10       /* Position Register Updated Interrupt Enable */
+#define                    MPRUEN  0x20       /* Maximum Position Register Updated Interrupt Enable */
+#define                     DRUEN  0x40       /* Delay Register Updated Interrupt Enable */
+#define                    MDRUEN  0x80       /* Maximum Delay Register Updated Interrupt Enable */
+#define                     SBUEN  0x100      /* Synchronous Boundary Updated Interrupt Enable */
+#define                     ATUEN  0x200      /* Allocation Table Updated Interrupt Enable */
+#define                    FCZ0EN  0x400      /* Frame Counter 0 Zero Interrupt Enable */
+#define                    FCZ1EN  0x800      /* Frame Counter 1 Zero Interrupt Enable */
+#define                    PERREN  0x1000     /* Parity Error Interrupt Enable */
+#define                    MH2LEN  0x2000     /* MRXONB High to Low Interrupt Enable */
+#define                    ML2HEN  0x4000     /* MRXONB Low to High Interrupt Enable */
+#define                     WUPEN  0x8000     /* Wake-Up Preamble Received Interrupt Enable */
+#define                    FU2LEN  0x10000    /* Frame Unlock to Lock Interrupt Enable */
+#define                    FL2UEN  0x20000    /* Frame Lock to Unlock Interrupt Enable */
+#define                    BU2LEN  0x40000    /* Block Unlock to Lock Interrupt Enable */
+#define                    BL2UEN  0x80000    /* Block Lock to Unlock Interrupt Enable */
+#define                   OBERREN  0x100000   /* DMA Out of Bounds Error Interrupt Enable */
+#define                     PFLEN  0x200000   /* PLL Frequency Locked Interrupt Enable */
+#define                     SCZEN  0x400000   /* System Clock Counter Zero Interrupt Enable */
+#define                    FERREN  0x800000   /* FIFO Error Interrupt Enable */
+#define                     CMREN  0x1000000  /* Control Message Received Interrupt Enable */
+#define                   CMROFEN  0x2000000  /* Control Message Receive Buffer Overflow Interrupt Enable */
+#define                    CMTSEN  0x4000000  /* Control Message Transmit Buffer Successfully Sent Interrupt Enable */
+#define                    CMTCEN  0x8000000  /* Control Message Transmit Buffer Successfully Cancelled Interrupt Enable */
+#define                    RWRCEN  0x10000000 /* Remote Write Control Message Completed Interrupt Enable */
+#define                     BCZEN  0x20000000 /* Block Counter Zero Interrupt Enable */
+#define                   BMERREN  0x40000000 /* Biphase Mark Coding Error Interrupt Enable */
+#define                    DERREN  0x80000000 /* DMA Error Interrupt Enable */
+
+/* Bit masks for MXVR_INT_EN_1 */
+
+#define                  HDONEEN0  0x1        /* DMA0 Half Done Interrupt Enable */
+#define                   DONEEN0  0x2        /* DMA0 Done Interrupt Enable */
+#define                     APREN  0x4        /* Asynchronous Packet Received Interrupt Enable */
+#define                   APROFEN  0x8        /* Asynchronous Packet Receive Buffer Overflow Interrupt Enable */
+#define                  HDONEEN1  0x10       /* DMA1 Half Done Interrupt Enable */
+#define                   DONEEN1  0x20       /* DMA1 Done Interrupt Enable */
+#define                    APTSEN  0x40       /* Asynchronous Packet Transmit Buffer Successfully Sent Interrupt Enable */
+#define                    APTCEN  0x80       /* Asynchronous Packet Transmit Buffer Successfully Cancelled Interrupt Enable */
+#define                  HDONEEN2  0x100      /* DMA2 Half Done Interrupt Enable */
+#define                   DONEEN2  0x200      /* DMA2 Done Interrupt Enable */
+#define                   APRCEEN  0x400      /* Asynchronous Packet Receive CRC Error Interrupt Enable */
+#define                   APRPEEN  0x800      /* Asynchronous Packet Receive Packet Error Interrupt Enable */
+#define                  HDONEEN3  0x1000     /* DMA3 Half Done Interrupt Enable */
+#define                   DONEEN3  0x2000     /* DMA3 Done Interrupt Enable */
+#define                  HDONEEN4  0x10000    /* DMA4 Half Done Interrupt Enable */
+#define                   DONEEN4  0x20000    /* DMA4 Done Interrupt Enable */
+#define                  HDONEEN5  0x100000   /* DMA5 Half Done Interrupt Enable */
+#define                   DONEEN5  0x200000   /* DMA5 Done Interrupt Enable */
+#define                  HDONEEN6  0x1000000  /* DMA6 Half Done Interrupt Enable */
+#define                   DONEEN6  0x2000000  /* DMA6 Done Interrupt Enable */
+#define                  HDONEEN7  0x10000000 /* DMA7 Half Done Interrupt Enable */
+#define                   DONEEN7  0x20000000 /* DMA7 Done Interrupt Enable */
+
+/* Bit masks for MXVR_POSITION */
+
+#define                  POSITION  0x3f       /* Node Position */
+#define                    PVALID  0x8000     /* Node Position Valid */
+
+/* Bit masks for MXVR_MAX_POSITION */
+
+#define                 MPOSITION  0x3f       /* Maximum Node Position */
+#define                   MPVALID  0x8000     /* Maximum Node Position Valid */
+
+/* Bit masks for MXVR_DELAY */
+
+#define                     DELAY  0x3f       /* Node Frame Delay */
+#define                    DVALID  0x8000     /* Node Frame Delay Valid */
+
+/* Bit masks for MXVR_MAX_DELAY */
+
+#define                    MDELAY  0x3f       /* Maximum Node Frame Delay */
+#define                   MDVALID  0x8000     /* Maximum Node Frame Delay Valid */
+
+/* Bit masks for MXVR_LADDR */
+
+#define                     LADDR  0xffff     /* Logical Address */
+#define                    LVALID  0x80000000 /* Logical Address Valid */
+
+/* Bit masks for MXVR_GADDR */
+
+#define                    GADDRL  0xff       /* Group Address Lower Byte */
+#define                    GVALID  0x8000     /* Group Address Valid */
+
+/* Bit masks for MXVR_AADDR */
+
+#define                     AADDR  0xffff     /* Alternate Address */
+#define                    AVALID  0x80000000 /* Alternate Address Valid */
+
+/* Bit masks for MXVR_ALLOC_0 */
+
+#define                       CL0  0x7f       /* Channel 0 Connection Label */
+#define                      CIU0  0x80       /* Channel 0 In Use */
+#define                       CL1  0x7f00     /* Channel 0 Connection Label */
+#define                      CIU1  0x8000     /* Channel 0 In Use */
+#define                       CL2  0x7f0000   /* Channel 0 Connection Label */
+#define                      CIU2  0x800000   /* Channel 0 In Use */
+#define                       CL3  0x7f000000 /* Channel 0 Connection Label */
+#define                      CIU3  0x80000000 /* Channel 0 In Use */
+
+/* Bit masks for MXVR_ALLOC_1 */
+
+#define                       CL4  0x7f       /* Channel 4 Connection Label */
+#define                      CIU4  0x80       /* Channel 4 In Use */
+#define                       CL5  0x7f00     /* Channel 5 Connection Label */
+#define                      CIU5  0x8000     /* Channel 5 In Use */
+#define                       CL6  0x7f0000   /* Channel 6 Connection Label */
+#define                      CIU6  0x800000   /* Channel 6 In Use */
+#define                       CL7  0x7f000000 /* Channel 7 Connection Label */
+#define                      CIU7  0x80000000 /* Channel 7 In Use */
+
+/* Bit masks for MXVR_ALLOC_2 */
+
+#define                       CL8  0x7f       /* Channel 8 Connection Label */
+#define                      CIU8  0x80       /* Channel 8 In Use */
+#define                       CL9  0x7f00     /* Channel 9 Connection Label */
+#define                      CIU9  0x8000     /* Channel 9 In Use */
+#define                      CL10  0x7f0000   /* Channel 10 Connection Label */
+#define                     CIU10  0x800000   /* Channel 10 In Use */
+#define                      CL11  0x7f000000 /* Channel 11 Connection Label */
+#define                     CIU11  0x80000000 /* Channel 11 In Use */
+
+/* Bit masks for MXVR_ALLOC_3 */
+
+#define                      CL12  0x7f       /* Channel 12 Connection Label */
+#define                     CIU12  0x80       /* Channel 12 In Use */
+#define                      CL13  0x7f00     /* Channel 13 Connection Label */
+#define                     CIU13  0x8000     /* Channel 13 In Use */
+#define                      CL14  0x7f0000   /* Channel 14 Connection Label */
+#define                     CIU14  0x800000   /* Channel 14 In Use */
+#define                      CL15  0x7f000000 /* Channel 15 Connection Label */
+#define                     CIU15  0x80000000 /* Channel 15 In Use */
+
+/* Bit masks for MXVR_ALLOC_4 */
+
+#define                      CL16  0x7f       /* Channel 16 Connection Label */
+#define                     CIU16  0x80       /* Channel 16 In Use */
+#define                      CL17  0x7f00     /* Channel 17 Connection Label */
+#define                     CIU17  0x8000     /* Channel 17 In Use */
+#define                      CL18  0x7f0000   /* Channel 18 Connection Label */
+#define                     CIU18  0x800000   /* Channel 18 In Use */
+#define                      CL19  0x7f000000 /* Channel 19 Connection Label */
+#define                     CIU19  0x80000000 /* Channel 19 In Use */
+
+/* Bit masks for MXVR_ALLOC_5 */
+
+#define                      CL20  0x7f       /* Channel 20 Connection Label */
+#define                     CIU20  0x80       /* Channel 20 In Use */
+#define                      CL21  0x7f00     /* Channel 21 Connection Label */
+#define                     CIU21  0x8000     /* Channel 21 In Use */
+#define                      CL22  0x7f0000   /* Channel 22 Connection Label */
+#define                     CIU22  0x800000   /* Channel 22 In Use */
+#define                      CL23  0x7f000000 /* Channel 23 Connection Label */
+#define                     CIU23  0x80000000 /* Channel 23 In Use */
+
+/* Bit masks for MXVR_ALLOC_6 */
+
+#define                      CL24  0x7f       /* Channel 24 Connection Label */
+#define                     CIU24  0x80       /* Channel 24 In Use */
+#define                      CL25  0x7f00     /* Channel 25 Connection Label */
+#define                     CIU25  0x8000     /* Channel 25 In Use */
+#define                      CL26  0x7f0000   /* Channel 26 Connection Label */
+#define                     CIU26  0x800000   /* Channel 26 In Use */
+#define                      CL27  0x7f000000 /* Channel 27 Connection Label */
+#define                     CIU27  0x80000000 /* Channel 27 In Use */
+
+/* Bit masks for MXVR_ALLOC_7 */
+
+#define                      CL28  0x7f       /* Channel 28 Connection Label */
+#define                     CIU28  0x80       /* Channel 28 In Use */
+#define                      CL29  0x7f00     /* Channel 29 Connection Label */
+#define                     CIU29  0x8000     /* Channel 29 In Use */
+#define                      CL30  0x7f0000   /* Channel 30 Connection Label */
+#define                     CIU30  0x800000   /* Channel 30 In Use */
+#define                      CL31  0x7f000000 /* Channel 31 Connection Label */
+#define                     CIU31  0x80000000 /* Channel 31 In Use */
+
+/* Bit masks for MXVR_ALLOC_8 */
+
+#define                      CL32  0x7f       /* Channel 32 Connection Label */
+#define                     CIU32  0x80       /* Channel 32 In Use */
+#define                      CL33  0x7f00     /* Channel 33 Connection Label */
+#define                     CIU33  0x8000     /* Channel 33 In Use */
+#define                      CL34  0x7f0000   /* Channel 34 Connection Label */
+#define                     CIU34  0x800000   /* Channel 34 In Use */
+#define                      CL35  0x7f000000 /* Channel 35 Connection Label */
+#define                     CIU35  0x80000000 /* Channel 35 In Use */
+
+/* Bit masks for MXVR_ALLOC_9 */
+
+#define                      CL36  0x7f       /* Channel 36 Connection Label */
+#define                     CIU36  0x80       /* Channel 36 In Use */
+#define                      CL37  0x7f00     /* Channel 37 Connection Label */
+#define                     CIU37  0x8000     /* Channel 37 In Use */
+#define                      CL38  0x7f0000   /* Channel 38 Connection Label */
+#define                     CIU38  0x800000   /* Channel 38 In Use */
+#define                      CL39  0x7f000000 /* Channel 39 Connection Label */
+#define                     CIU39  0x80000000 /* Channel 39 In Use */
+
+/* Bit masks for MXVR_ALLOC_10 */
+
+#define                      CL40  0x7f       /* Channel 40 Connection Label */
+#define                     CIU40  0x80       /* Channel 40 In Use */
+#define                      CL41  0x7f00     /* Channel 41 Connection Label */
+#define                     CIU41  0x8000     /* Channel 41 In Use */
+#define                      CL42  0x7f0000   /* Channel 42 Connection Label */
+#define                     CIU42  0x800000   /* Channel 42 In Use */
+#define                      CL43  0x7f000000 /* Channel 43 Connection Label */
+#define                     CIU43  0x80000000 /* Channel 43 In Use */
+
+/* Bit masks for MXVR_ALLOC_11 */
+
+#define                      CL44  0x7f       /* Channel 44 Connection Label */
+#define                     CIU44  0x80       /* Channel 44 In Use */
+#define                      CL45  0x7f00     /* Channel 45 Connection Label */
+#define                     CIU45  0x8000     /* Channel 45 In Use */
+#define                      CL46  0x7f0000   /* Channel 46 Connection Label */
+#define                     CIU46  0x800000   /* Channel 46 In Use */
+#define                      CL47  0x7f000000 /* Channel 47 Connection Label */
+#define                     CIU47  0x80000000 /* Channel 47 In Use */
+
+/* Bit masks for MXVR_ALLOC_12 */
+
+#define                      CL48  0x7f       /* Channel 48 Connection Label */
+#define                     CIU48  0x80       /* Channel 48 In Use */
+#define                      CL49  0x7f00     /* Channel 49 Connection Label */
+#define                     CIU49  0x8000     /* Channel 49 In Use */
+#define                      CL50  0x7f0000   /* Channel 50 Connection Label */
+#define                     CIU50  0x800000   /* Channel 50 In Use */
+#define                      CL51  0x7f000000 /* Channel 51 Connection Label */
+#define                     CIU51  0x80000000 /* Channel 51 In Use */
+
+/* Bit masks for MXVR_ALLOC_13 */
+
+#define                      CL52  0x7f       /* Channel 52 Connection Label */
+#define                     CIU52  0x80       /* Channel 52 In Use */
+#define                      CL53  0x7f00     /* Channel 53 Connection Label */
+#define                     CIU53  0x8000     /* Channel 53 In Use */
+#define                      CL54  0x7f0000   /* Channel 54 Connection Label */
+#define                     CIU54  0x800000   /* Channel 54 In Use */
+#define                      CL55  0x7f000000 /* Channel 55 Connection Label */
+#define                     CIU55  0x80000000 /* Channel 55 In Use */
+
+/* Bit masks for MXVR_ALLOC_14 */
+
+#define                      CL56  0x7f       /* Channel 56 Connection Label */
+#define                     CIU56  0x80       /* Channel 56 In Use */
+#define                      CL57  0x7f00     /* Channel 57 Connection Label */
+#define                     CIU57  0x8000     /* Channel 57 In Use */
+#define                      CL58  0x7f0000   /* Channel 58 Connection Label */
+#define                     CIU58  0x800000   /* Channel 58 In Use */
+#define                      CL59  0x7f000000 /* Channel 59 Connection Label */
+#define                     CIU59  0x80000000 /* Channel 59 In Use */
+
+/* MXVR_SYNC_LCHAN_0 Masks */
+
+#define LCHANPC0     0x0000000Flu
+#define LCHANPC1     0x000000F0lu
+#define LCHANPC2     0x00000F00lu
+#define LCHANPC3     0x0000F000lu
+#define LCHANPC4     0x000F0000lu
+#define LCHANPC5     0x00F00000lu
+#define LCHANPC6     0x0F000000lu
+#define LCHANPC7     0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_1 Masks */
+
+#define LCHANPC8     0x0000000Flu
+#define LCHANPC9     0x000000F0lu
+#define LCHANPC10    0x00000F00lu
+#define LCHANPC11    0x0000F000lu
+#define LCHANPC12    0x000F0000lu
+#define LCHANPC13    0x00F00000lu
+#define LCHANPC14    0x0F000000lu
+#define LCHANPC15    0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_2 Masks */
+
+#define LCHANPC16    0x0000000Flu
+#define LCHANPC17    0x000000F0lu
+#define LCHANPC18    0x00000F00lu
+#define LCHANPC19    0x0000F000lu
+#define LCHANPC20    0x000F0000lu
+#define LCHANPC21    0x00F00000lu
+#define LCHANPC22    0x0F000000lu
+#define LCHANPC23    0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_3 Masks */
+
+#define LCHANPC24    0x0000000Flu
+#define LCHANPC25    0x000000F0lu
+#define LCHANPC26    0x00000F00lu
+#define LCHANPC27    0x0000F000lu
+#define LCHANPC28    0x000F0000lu
+#define LCHANPC29    0x00F00000lu
+#define LCHANPC30    0x0F000000lu
+#define LCHANPC31    0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_4 Masks */
+
+#define LCHANPC32    0x0000000Flu
+#define LCHANPC33    0x000000F0lu
+#define LCHANPC34    0x00000F00lu
+#define LCHANPC35    0x0000F000lu
+#define LCHANPC36    0x000F0000lu
+#define LCHANPC37    0x00F00000lu
+#define LCHANPC38    0x0F000000lu
+#define LCHANPC39    0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_5 Masks */
+
+#define LCHANPC40    0x0000000Flu
+#define LCHANPC41    0x000000F0lu
+#define LCHANPC42    0x00000F00lu
+#define LCHANPC43    0x0000F000lu
+#define LCHANPC44    0x000F0000lu
+#define LCHANPC45    0x00F00000lu
+#define LCHANPC46    0x0F000000lu
+#define LCHANPC47    0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_6 Masks */
+
+#define LCHANPC48    0x0000000Flu
+#define LCHANPC49    0x000000F0lu
+#define LCHANPC50    0x00000F00lu
+#define LCHANPC51    0x0000F000lu
+#define LCHANPC52    0x000F0000lu
+#define LCHANPC53    0x00F00000lu
+#define LCHANPC54    0x0F000000lu
+#define LCHANPC55    0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_7 Masks */
+
+#define LCHANPC56    0x0000000Flu
+#define LCHANPC57    0x000000F0lu
+#define LCHANPC58    0x00000F00lu
+#define LCHANPC59    0x0000F000lu
+
+/* Bit masks for MXVR_DMAx_CONFIG */
+
+#define                    MDMAEN  0x1        /* DMA Channel Enable */
+#define                        DD  0x2        /* DMA Channel Direction */
+#define                 BY4SWAPEN  0x20       /* DMA Channel Four Byte Swap Enable */
+#define                     LCHAN  0x3c0      /* DMA Channel Logical Channel */
+#define                 BITSWAPEN  0x400      /* DMA Channel Bit Swap Enable */
+#define                 BY2SWAPEN  0x800      /* DMA Channel Two Byte Swap Enable */
+#define                     MFLOW  0x7000     /* DMA Channel Operation Flow */
+#define                   FIXEDPM  0x80000    /* DMA Channel Fixed Pattern Matching Select */
+#define                  STARTPAT  0x300000   /* DMA Channel Start Pattern Select */
+#define                   STOPPAT  0xc00000   /* DMA Channel Stop Pattern Select */
+#define                  COUNTPOS  0x1c000000 /* DMA Channel Count Position */
+
+/* Bit masks for MXVR_AP_CTL */
+
+#define                   STARTAP  0x1        /* Start Asynchronous Packet Transmission */
+#define                  CANCELAP  0x2        /* Cancel Asynchronous Packet Transmission */
+#define                   RESETAP  0x4        /* Reset Asynchronous Packet Arbitration */
+#define                    APRBE0  0x4000     /* Asynchronous Packet Receive Buffer Entry 0 */
+#define                    APRBE1  0x8000     /* Asynchronous Packet Receive Buffer Entry 1 */
+
+/* Bit masks for MXVR_APRB_START_ADDR */
+
+#define      MXVR_APRB_START_ADDR_MASK  0x1fffffe  /* Asynchronous Packet Receive Buffer Start Address */
+
+/* Bit masks for MXVR_APRB_CURR_ADDR */
+
+#define       MXVR_APRB_CURR_ADDR_MASK  0xffffffff /* Asynchronous Packet Receive Buffer Current Address */
+
+/* Bit masks for MXVR_APTB_START_ADDR */
+
+#define       MXVR_APTB_START_ADDR_MASK  0x1fffffe  /* Asynchronous Packet Transmit Buffer Start Address */
+
+/* Bit masks for MXVR_APTB_CURR_ADDR */
+
+#define        MXVR_APTB_CURR_ADDR_MASK  0xffffffff /* Asynchronous Packet Transmit Buffer Current Address */
+
+/* Bit masks for MXVR_CM_CTL */
+
+#define                   STARTCM  0x1        /* Start Control Message Transmission */
+#define                  CANCELCM  0x2        /* Cancel Control Message Transmission */
+#define                    CMRBE0  0x10000    /* Control Message Receive Buffer Entry 0 */
+#define                    CMRBE1  0x20000    /* Control Message Receive Buffer Entry 1 */
+#define                    CMRBE2  0x40000    /* Control Message Receive Buffer Entry 2 */
+#define                    CMRBE3  0x80000    /* Control Message Receive Buffer Entry 3 */
+#define                    CMRBE4  0x100000   /* Control Message Receive Buffer Entry 4 */
+#define                    CMRBE5  0x200000   /* Control Message Receive Buffer Entry 5 */
+#define                    CMRBE6  0x400000   /* Control Message Receive Buffer Entry 6 */
+#define                    CMRBE7  0x800000   /* Control Message Receive Buffer Entry 7 */
+#define                    CMRBE8  0x1000000  /* Control Message Receive Buffer Entry 8 */
+#define                    CMRBE9  0x2000000  /* Control Message Receive Buffer Entry 9 */
+#define                   CMRBE10  0x4000000  /* Control Message Receive Buffer Entry 10 */
+#define                   CMRBE11  0x8000000  /* Control Message Receive Buffer Entry 11 */
+#define                   CMRBE12  0x10000000 /* Control Message Receive Buffer Entry 12 */
+#define                   CMRBE13  0x20000000 /* Control Message Receive Buffer Entry 13 */
+#define                   CMRBE14  0x40000000 /* Control Message Receive Buffer Entry 14 */
+#define                   CMRBE15  0x80000000 /* Control Message Receive Buffer Entry 15 */
+
+/* Bit masks for MXVR_CMRB_START_ADDR */
+
+#define      MXVR_CMRB_START_ADDR_MASK  0x1fffffe  /* Control Message Receive Buffer Start Address */
+
+/* Bit masks for MXVR_CMRB_CURR_ADDR */
+
+#define       MXVR_CMRB_CURR_ADDR_MASK  0xffffffff /* Control Message Receive Buffer Current Address */
+
+/* Bit masks for MXVR_CMTB_START_ADDR */
+
+#define      MXVR_CMTB_START_ADDR_MASK  0x1fffffe  /* Control Message Transmit Buffer Start Address */
+
+/* Bit masks for MXVR_CMTB_CURR_ADDR */
+
+#define       MXVR_CMTB_CURR_ADDR_MASK  0xffffffff /* Control Message Transmit Buffer Current Address */
+
+/* Bit masks for MXVR_RRDB_START_ADDR */
+
+#define      MXVR_RRDB_START_ADDR_MASK  0x1fffffe  /* Remote Read Buffer Start Address */
+
+/* Bit masks for MXVR_RRDB_CURR_ADDR */
+
+#define       MXVR_RRDB_CURR_ADDR_MASK  0xffffffff /* Remote Read Buffer Current Address */
+
+/* Bit masks for MXVR_PAT_DATAx */
+
+#define              MATCH_DATA_0  0xff       /* Pattern Match Data Byte 0 */
+#define              MATCH_DATA_1  0xff00     /* Pattern Match Data Byte 1 */
+#define              MATCH_DATA_2  0xff0000   /* Pattern Match Data Byte 2 */
+#define              MATCH_DATA_3  0xff000000 /* Pattern Match Data Byte 3 */
+
+/* Bit masks for MXVR_PAT_EN_0 */
+
+#define              MATCH_EN_0_0  0x1        /* Pattern Match Enable Byte 0 Bit 0 */
+#define              MATCH_EN_0_1  0x2        /* Pattern Match Enable Byte 0 Bit 1 */
+#define              MATCH_EN_0_2  0x4        /* Pattern Match Enable Byte 0 Bit 2 */
+#define              MATCH_EN_0_3  0x8        /* Pattern Match Enable Byte 0 Bit 3 */
+#define              MATCH_EN_0_4  0x10       /* Pattern Match Enable Byte 0 Bit 4 */
+#define              MATCH_EN_0_5  0x20       /* Pattern Match Enable Byte 0 Bit 5 */
+#define              MATCH_EN_0_6  0x40       /* Pattern Match Enable Byte 0 Bit 6 */
+#define              MATCH_EN_0_7  0x80       /* Pattern Match Enable Byte 0 Bit 7 */
+#define              MATCH_EN_1_0  0x100      /* Pattern Match Enable Byte 1 Bit 0 */
+#define              MATCH_EN_1_1  0x200      /* Pattern Match Enable Byte 1 Bit 1 */
+#define              MATCH_EN_1_2  0x400      /* Pattern Match Enable Byte 1 Bit 2 */
+#define              MATCH_EN_1_3  0x800      /* Pattern Match Enable Byte 1 Bit 3 */
+#define              MATCH_EN_1_4  0x1000     /* Pattern Match Enable Byte 1 Bit 4 */
+#define              MATCH_EN_1_5  0x2000     /* Pattern Match Enable Byte 1 Bit 5 */
+#define              MATCH_EN_1_6  0x4000     /* Pattern Match Enable Byte 1 Bit 6 */
+#define              MATCH_EN_1_7  0x8000     /* Pattern Match Enable Byte 1 Bit 7 */
+#define              MATCH_EN_2_0  0x10000    /* Pattern Match Enable Byte 2 Bit 0 */
+#define              MATCH_EN_2_1  0x20000    /* Pattern Match Enable Byte 2 Bit 1 */
+#define              MATCH_EN_2_2  0x40000    /* Pattern Match Enable Byte 2 Bit 2 */
+#define              MATCH_EN_2_3  0x80000    /* Pattern Match Enable Byte 2 Bit 3 */
+#define              MATCH_EN_2_4  0x100000   /* Pattern Match Enable Byte 2 Bit 4 */
+#define              MATCH_EN_2_5  0x200000   /* Pattern Match Enable Byte 2 Bit 5 */
+#define              MATCH_EN_2_6  0x400000   /* Pattern Match Enable Byte 2 Bit 6 */
+#define              MATCH_EN_2_7  0x800000   /* Pattern Match Enable Byte 2 Bit 7 */
+#define              MATCH_EN_3_0  0x1000000  /* Pattern Match Enable Byte 3 Bit 0 */
+#define              MATCH_EN_3_1  0x2000000  /* Pattern Match Enable Byte 3 Bit 1 */
+#define              MATCH_EN_3_2  0x4000000  /* Pattern Match Enable Byte 3 Bit 2 */
+#define              MATCH_EN_3_3  0x8000000  /* Pattern Match Enable Byte 3 Bit 3 */
+#define              MATCH_EN_3_4  0x10000000 /* Pattern Match Enable Byte 3 Bit 4 */
+#define              MATCH_EN_3_5  0x20000000 /* Pattern Match Enable Byte 3 Bit 5 */
+#define              MATCH_EN_3_6  0x40000000 /* Pattern Match Enable Byte 3 Bit 6 */
+#define              MATCH_EN_3_7  0x80000000 /* Pattern Match Enable Byte 3 Bit 7 */
+
+/* Bit masks for MXVR_PAT_EN_1 */
+
+#define              MATCH_EN_0_0  0x1        /* Pattern Match Enable Byte 0 Bit 0 */
+#define              MATCH_EN_0_1  0x2        /* Pattern Match Enable Byte 0 Bit 1 */
+#define              MATCH_EN_0_2  0x4        /* Pattern Match Enable Byte 0 Bit 2 */
+#define              MATCH_EN_0_3  0x8        /* Pattern Match Enable Byte 0 Bit 3 */
+#define              MATCH_EN_0_4  0x10       /* Pattern Match Enable Byte 0 Bit 4 */
+#define              MATCH_EN_0_5  0x20       /* Pattern Match Enable Byte 0 Bit 5 */
+#define              MATCH_EN_0_6  0x40       /* Pattern Match Enable Byte 0 Bit 6 */
+#define              MATCH_EN_0_7  0x80       /* Pattern Match Enable Byte 0 Bit 7 */
+#define              MATCH_EN_1_0  0x100      /* Pattern Match Enable Byte 1 Bit 0 */
+#define              MATCH_EN_1_1  0x200      /* Pattern Match Enable Byte 1 Bit 1 */
+#define              MATCH_EN_1_2  0x400      /* Pattern Match Enable Byte 1 Bit 2 */
+#define              MATCH_EN_1_3  0x800      /* Pattern Match Enable Byte 1 Bit 3 */
+#define              MATCH_EN_1_4  0x1000     /* Pattern Match Enable Byte 1 Bit 4 */
+#define              MATCH_EN_1_5  0x2000     /* Pattern Match Enable Byte 1 Bit 5 */
+#define              MATCH_EN_1_6  0x4000     /* Pattern Match Enable Byte 1 Bit 6 */
+#define              MATCH_EN_1_7  0x8000     /* Pattern Match Enable Byte 1 Bit 7 */
+#define              MATCH_EN_2_0  0x10000    /* Pattern Match Enable Byte 2 Bit 0 */
+#define              MATCH_EN_2_1  0x20000    /* Pattern Match Enable Byte 2 Bit 1 */
+#define              MATCH_EN_2_2  0x40000    /* Pattern Match Enable Byte 2 Bit 2 */
+#define              MATCH_EN_2_3  0x80000    /* Pattern Match Enable Byte 2 Bit 3 */
+#define              MATCH_EN_2_4  0x100000   /* Pattern Match Enable Byte 2 Bit 4 */
+#define              MATCH_EN_2_5  0x200000   /* Pattern Match Enable Byte 2 Bit 5 */
+#define              MATCH_EN_2_6  0x400000   /* Pattern Match Enable Byte 2 Bit 6 */
+#define              MATCH_EN_2_7  0x800000   /* Pattern Match Enable Byte 2 Bit 7 */
+#define              MATCH_EN_3_0  0x1000000  /* Pattern Match Enable Byte 3 Bit 0 */
+#define              MATCH_EN_3_1  0x2000000  /* Pattern Match Enable Byte 3 Bit 1 */
+#define              MATCH_EN_3_2  0x4000000  /* Pattern Match Enable Byte 3 Bit 2 */
+#define              MATCH_EN_3_3  0x8000000  /* Pattern Match Enable Byte 3 Bit 3 */
+#define              MATCH_EN_3_4  0x10000000 /* Pattern Match Enable Byte 3 Bit 4 */
+#define              MATCH_EN_3_5  0x20000000 /* Pattern Match Enable Byte 3 Bit 5 */
+#define              MATCH_EN_3_6  0x40000000 /* Pattern Match Enable Byte 3 Bit 6 */
+#define              MATCH_EN_3_7  0x80000000 /* Pattern Match Enable Byte 3 Bit 7 */
+
+/* Bit masks for MXVR_FRAME_CNT_0 */
+
+#define                      FCNT  0xffff     /* Frame Count */
+
+/* Bit masks for MXVR_FRAME_CNT_1 */
+
+#define                      FCNT  0xffff     /* Frame Count */
+
+/* Bit masks for MXVR_ROUTING_0 */
+
+#define                    TX_CH0  0x3f       /* Transmit Channel 0 */
+#define                  MUTE_CH0  0x80       /* Mute Channel 0 */
+#define                    TX_CH1  0x3f00     /* Transmit Channel 0 */
+#define                  MUTE_CH1  0x8000     /* Mute Channel 0 */
+#define                    TX_CH2  0x3f0000   /* Transmit Channel 0 */
+#define                  MUTE_CH2  0x800000   /* Mute Channel 0 */
+#define                    TX_CH3  0x3f000000 /* Transmit Channel 0 */
+#define                  MUTE_CH3  0x80000000 /* Mute Channel 0 */
+
+/* Bit masks for MXVR_ROUTING_1 */
+
+#define                    TX_CH4  0x3f       /* Transmit Channel 4 */
+#define                  MUTE_CH4  0x80       /* Mute Channel 4 */
+#define                    TX_CH5  0x3f00     /* Transmit Channel 5 */
+#define                  MUTE_CH5  0x8000     /* Mute Channel 5 */
+#define                    TX_CH6  0x3f0000   /* Transmit Channel 6 */
+#define                  MUTE_CH6  0x800000   /* Mute Channel 6 */
+#define                    TX_CH7  0x3f000000 /* Transmit Channel 7 */
+#define                  MUTE_CH7  0x80000000 /* Mute Channel 7 */
+
+/* Bit masks for MXVR_ROUTING_2 */
+
+#define                    TX_CH8  0x3f       /* Transmit Channel 8 */
+#define                  MUTE_CH8  0x80       /* Mute Channel 8 */
+#define                    TX_CH9  0x3f00     /* Transmit Channel 9 */
+#define                  MUTE_CH9  0x8000     /* Mute Channel 9 */
+#define                   TX_CH10  0x3f0000   /* Transmit Channel 10 */
+#define                 MUTE_CH10  0x800000   /* Mute Channel 10 */
+#define                   TX_CH11  0x3f000000 /* Transmit Channel 11 */
+#define                 MUTE_CH11  0x80000000 /* Mute Channel 11 */
+
+/* Bit masks for MXVR_ROUTING_3 */
+
+#define                   TX_CH12  0x3f       /* Transmit Channel 12 */
+#define                 MUTE_CH12  0x80       /* Mute Channel 12 */
+#define                   TX_CH13  0x3f00     /* Transmit Channel 13 */
+#define                 MUTE_CH13  0x8000     /* Mute Channel 13 */
+#define                   TX_CH14  0x3f0000   /* Transmit Channel 14 */
+#define                 MUTE_CH14  0x800000   /* Mute Channel 14 */
+#define                   TX_CH15  0x3f000000 /* Transmit Channel 15 */
+#define                 MUTE_CH15  0x80000000 /* Mute Channel 15 */
+
+/* Bit masks for MXVR_ROUTING_4 */
+
+#define                   TX_CH16  0x3f       /* Transmit Channel 16 */
+#define                 MUTE_CH16  0x80       /* Mute Channel 16 */
+#define                   TX_CH17  0x3f00     /* Transmit Channel 17 */
+#define                 MUTE_CH17  0x8000     /* Mute Channel 17 */
+#define                   TX_CH18  0x3f0000   /* Transmit Channel 18 */
+#define                 MUTE_CH18  0x800000   /* Mute Channel 18 */
+#define                   TX_CH19  0x3f000000 /* Transmit Channel 19 */
+#define                 MUTE_CH19  0x80000000 /* Mute Channel 19 */
+
+/* Bit masks for MXVR_ROUTING_5 */
+
+#define                   TX_CH20  0x3f       /* Transmit Channel 20 */
+#define                 MUTE_CH20  0x80       /* Mute Channel 20 */
+#define                   TX_CH21  0x3f00     /* Transmit Channel 21 */
+#define                 MUTE_CH21  0x8000     /* Mute Channel 21 */
+#define                   TX_CH22  0x3f0000   /* Transmit Channel 22 */
+#define                 MUTE_CH22  0x800000   /* Mute Channel 22 */
+#define                   TX_CH23  0x3f000000 /* Transmit Channel 23 */
+#define                 MUTE_CH23  0x80000000 /* Mute Channel 23 */
+
+/* Bit masks for MXVR_ROUTING_6 */
+
+#define                   TX_CH24  0x3f       /* Transmit Channel 24 */
+#define                 MUTE_CH24  0x80       /* Mute Channel 24 */
+#define                   TX_CH25  0x3f00     /* Transmit Channel 25 */
+#define                 MUTE_CH25  0x8000     /* Mute Channel 25 */
+#define                   TX_CH26  0x3f0000   /* Transmit Channel 26 */
+#define                 MUTE_CH26  0x800000   /* Mute Channel 26 */
+#define                   TX_CH27  0x3f000000 /* Transmit Channel 27 */
+#define                 MUTE_CH27  0x80000000 /* Mute Channel 27 */
+
+/* Bit masks for MXVR_ROUTING_7 */
+
+#define                   TX_CH28  0x3f       /* Transmit Channel 28 */
+#define                 MUTE_CH28  0x80       /* Mute Channel 28 */
+#define                   TX_CH29  0x3f00     /* Transmit Channel 29 */
+#define                 MUTE_CH29  0x8000     /* Mute Channel 29 */
+#define                   TX_CH30  0x3f0000   /* Transmit Channel 30 */
+#define                 MUTE_CH30  0x800000   /* Mute Channel 30 */
+#define                   TX_CH31  0x3f000000 /* Transmit Channel 31 */
+#define                 MUTE_CH31  0x80000000 /* Mute Channel 31 */
+
+/* Bit masks for MXVR_ROUTING_8 */
+
+#define                   TX_CH32  0x3f       /* Transmit Channel 32 */
+#define                 MUTE_CH32  0x80       /* Mute Channel 32 */
+#define                   TX_CH33  0x3f00     /* Transmit Channel 33 */
+#define                 MUTE_CH33  0x8000     /* Mute Channel 33 */
+#define                   TX_CH34  0x3f0000   /* Transmit Channel 34 */
+#define                 MUTE_CH34  0x800000   /* Mute Channel 34 */
+#define                   TX_CH35  0x3f000000 /* Transmit Channel 35 */
+#define                 MUTE_CH35  0x80000000 /* Mute Channel 35 */
+
+/* Bit masks for MXVR_ROUTING_9 */
+
+#define                   TX_CH36  0x3f       /* Transmit Channel 36 */
+#define                 MUTE_CH36  0x80       /* Mute Channel 36 */
+#define                   TX_CH37  0x3f00     /* Transmit Channel 37 */
+#define                 MUTE_CH37  0x8000     /* Mute Channel 37 */
+#define                   TX_CH38  0x3f0000   /* Transmit Channel 38 */
+#define                 MUTE_CH38  0x800000   /* Mute Channel 38 */
+#define                   TX_CH39  0x3f000000 /* Transmit Channel 39 */
+#define                 MUTE_CH39  0x80000000 /* Mute Channel 39 */
+
+/* Bit masks for MXVR_ROUTING_10 */
+
+#define                   TX_CH40  0x3f       /* Transmit Channel 40 */
+#define                 MUTE_CH40  0x80       /* Mute Channel 40 */
+#define                   TX_CH41  0x3f00     /* Transmit Channel 41 */
+#define                 MUTE_CH41  0x8000     /* Mute Channel 41 */
+#define                   TX_CH42  0x3f0000   /* Transmit Channel 42 */
+#define                 MUTE_CH42  0x800000   /* Mute Channel 42 */
+#define                   TX_CH43  0x3f000000 /* Transmit Channel 43 */
+#define                 MUTE_CH43  0x80000000 /* Mute Channel 43 */
+
+/* Bit masks for MXVR_ROUTING_11 */
+
+#define                   TX_CH44  0x3f       /* Transmit Channel 44 */
+#define                 MUTE_CH44  0x80       /* Mute Channel 44 */
+#define                   TX_CH45  0x3f00     /* Transmit Channel 45 */
+#define                 MUTE_CH45  0x8000     /* Mute Channel 45 */
+#define                   TX_CH46  0x3f0000   /* Transmit Channel 46 */
+#define                 MUTE_CH46  0x800000   /* Mute Channel 46 */
+#define                   TX_CH47  0x3f000000 /* Transmit Channel 47 */
+#define                 MUTE_CH47  0x80000000 /* Mute Channel 47 */
+
+/* Bit masks for MXVR_ROUTING_12 */
+
+#define                   TX_CH48  0x3f       /* Transmit Channel 48 */
+#define                 MUTE_CH48  0x80       /* Mute Channel 48 */
+#define                   TX_CH49  0x3f00     /* Transmit Channel 49 */
+#define                 MUTE_CH49  0x8000     /* Mute Channel 49 */
+#define                   TX_CH50  0x3f0000   /* Transmit Channel 50 */
+#define                 MUTE_CH50  0x800000   /* Mute Channel 50 */
+#define                   TX_CH51  0x3f000000 /* Transmit Channel 51 */
+#define                 MUTE_CH51  0x80000000 /* Mute Channel 51 */
+
+/* Bit masks for MXVR_ROUTING_13 */
+
+#define                   TX_CH52  0x3f       /* Transmit Channel 52 */
+#define                 MUTE_CH52  0x80       /* Mute Channel 52 */
+#define                   TX_CH53  0x3f00     /* Transmit Channel 53 */
+#define                 MUTE_CH53  0x8000     /* Mute Channel 53 */
+#define                   TX_CH54  0x3f0000   /* Transmit Channel 54 */
+#define                 MUTE_CH54  0x800000   /* Mute Channel 54 */
+#define                   TX_CH55  0x3f000000 /* Transmit Channel 55 */
+#define                 MUTE_CH55  0x80000000 /* Mute Channel 55 */
+
+/* Bit masks for MXVR_ROUTING_14 */
+
+#define                   TX_CH56  0x3f       /* Transmit Channel 56 */
+#define                 MUTE_CH56  0x80       /* Mute Channel 56 */
+#define                   TX_CH57  0x3f00     /* Transmit Channel 57 */
+#define                 MUTE_CH57  0x8000     /* Mute Channel 57 */
+#define                   TX_CH58  0x3f0000   /* Transmit Channel 58 */
+#define                 MUTE_CH58  0x800000   /* Mute Channel 58 */
+#define                   TX_CH59  0x3f000000 /* Transmit Channel 59 */
+#define                 MUTE_CH59  0x80000000 /* Mute Channel 59 */
+
+/* Bit masks for MXVR_BLOCK_CNT */
+
+#define                      BCNT  0xffff     /* Block Count */
+
+/* Bit masks for MXVR_CLK_CTL */
+
+#define                  MXTALCEN  0x1        /* MXVR Crystal Oscillator Clock Enable */
+#define                  MXTALFEN  0x2        /* MXVR Crystal Oscillator Feedback Enable */
+#define                  MXTALMUL  0x30       /* MXVR Crystal Multiplier */
+#define                  CLKX3SEL  0x80       /* Clock Generation Source Select */
+#define                   MMCLKEN  0x100      /* Master Clock Enable */
+#define                  MMCLKMUL  0x1e00     /* Master Clock Multiplication Factor */
+#define                   PLLSMPS  0xe000     /* MXVR PLL State Machine Prescaler */
+#define                   MBCLKEN  0x10000    /* Bit Clock Enable */
+#define                  MBCLKDIV  0x1e0000   /* Bit Clock Divide Factor */
+#define                     INVRX  0x800000   /* Invert Receive Data */
+#define                     MFSEN  0x1000000  /* Frame Sync Enable */
+#define                    MFSDIV  0x1e000000 /* Frame Sync Divide Factor */
+#define                    MFSSEL  0x60000000 /* Frame Sync Select */
+#define                   MFSSYNC  0x80000000 /* Frame Sync Synchronization Select */
+
+/* Bit masks for MXVR_CDRPLL_CTL */
+
+#define                   CDRSMEN  0x1        /* MXVR CDRPLL State Machine Enable */
+#define                   CDRRSTB  0x2        /* MXVR CDRPLL Reset */
+#define                   CDRSVCO  0x4        /* MXVR CDRPLL Start VCO */
+#define                   CDRMODE  0x8        /* MXVR CDRPLL CDR Mode Select */
+#define                   CDRSCNT  0x3f0      /* MXVR CDRPLL Start Counter */
+#define                   CDRLCNT  0xfc00     /* MXVR CDRPLL Lock Counter */
+#define                 CDRSHPSEL  0x3f0000   /* MXVR CDRPLL Shaper Select */
+#define                  CDRSHPEN  0x800000   /* MXVR CDRPLL Shaper Enable */
+#define                  CDRCPSEL  0xff000000 /* MXVR CDRPLL Charge Pump Current Select */
+
+/* Bit masks for MXVR_FMPLL_CTL */
+
+#define                    FMSMEN  0x1        /* MXVR FMPLL State Machine Enable */
+#define                    FMRSTB  0x2        /* MXVR FMPLL Reset */
+#define                    FMSVCO  0x4        /* MXVR FMPLL Start VCO */
+#define                    FMSCNT  0x3f0      /* MXVR FMPLL Start Counter */
+#define                    FMLCNT  0xfc00     /* MXVR FMPLL Lock Counter */
+#define                   FMCPSEL  0xff000000 /* MXVR FMPLL Charge Pump Current Select */
+
+/* Bit masks for MXVR_PIN_CTL */
+
+#define                  MTXONBOD  0x1        /* MTXONB Open Drain Select */
+#define                   MTXONBG  0x2        /* MTXONB Gates MTX Select */
+#define                     MFSOE  0x10       /* MFS Output Enable */
+#define                  MFSGPSEL  0x20       /* MFS General Purpose Output Select */
+#define                  MFSGPDAT  0x40       /* MFS General Purpose Output Data */
+
+/* Bit masks for MXVR_SCLK_CNT */
+
+#define                      SCNT  0xffff     /* System Clock Count */
+
+/* Bit masks for KPAD_CTL */
+
+#define                   KPAD_EN  0x1        /* Keypad Enable */
+#define              KPAD_IRQMODE  0x6        /* Key Press Interrupt Enable */
+#define                KPAD_ROWEN  0x1c00     /* Row Enable Width */
+#define                KPAD_COLEN  0xe000     /* Column Enable Width */
+
+/* Bit masks for KPAD_PRESCALE */
+
+#define         KPAD_PRESCALE_VAL  0x3f       /* Key Prescale Value */
+
+/* Bit masks for KPAD_MSEL */
+
+#define                DBON_SCALE  0xff       /* Debounce Scale Value */
+#define              COLDRV_SCALE  0xff00     /* Column Driver Scale Value */
+
+/* Bit masks for KPAD_ROWCOL */
+
+#define                  KPAD_ROW  0xff       /* Rows Pressed */
+#define                  KPAD_COL  0xff00     /* Columns Pressed */
+
+/* Bit masks for KPAD_STAT */
+
+#define                  KPAD_IRQ  0x1        /* Keypad Interrupt Status */
+#define              KPAD_MROWCOL  0x6        /* Multiple Row/Column Keypress Status */
+#define              KPAD_PRESSED  0x8        /* Key press current status */
+
+/* Bit masks for KPAD_SOFTEVAL */
+
+#define           KPAD_SOFTEVAL_E  0x2        /* Software Programmable Force Evaluate */
+
+/* Bit masks for SDH_COMMAND */
+
+#define                   CMD_IDX  0x3f       /* Command Index */
+#define                   CMD_RSP  0x40       /* Response */
+#define                 CMD_L_RSP  0x80       /* Long Response */
+#define                 CMD_INT_E  0x100      /* Command Interrupt */
+#define                CMD_PEND_E  0x200      /* Command Pending */
+#define                     CMD_E  0x400      /* Command Enable */
+
+/* Bit masks for SDH_PWR_CTL */
+
+#define                    PWR_ON  0x3        /* Power On */
+#if 0
+#define                       TBD  0x3c       /* TBD */
+#endif
+#define                 SD_CMD_OD  0x40       /* Open Drain Output */
+#define                   ROD_CTL  0x80       /* Rod Control */
+
+/* Bit masks for SDH_CLK_CTL */
+
+#define                    CLKDIV  0xff       /* MC_CLK Divisor */
+#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
+#define                  PWR_SV_E  0x200      /* Power Save Enable */
+#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
+#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
+
+/* Bit masks for SDH_RESP_CMD */
+
+#define                  RESP_CMD  0x3f       /* Response Command */
+
+/* Bit masks for SDH_DATA_CTL */
+
+#define                     DTX_E  0x1        /* Data Transfer Enable */
+#define                   DTX_DIR  0x2        /* Data Transfer Direction */
+#define                  DTX_MODE  0x4        /* Data Transfer Mode */
+#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
+#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
+
+/* Bit masks for SDH_STATUS */
+
+#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
+#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
+#define               CMD_TIME_OUT  0x4        /* CMD Time Out */
+#define               DAT_TIME_OUT  0x8        /* Data Time Out */
+#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
+#define                RX_OVERRUN  0x20       /* Receive Overrun */
+#define              CMD_RESP_END  0x40       /* CMD Response End */
+#define                  CMD_SENT  0x80       /* CMD Sent */
+#define                   DAT_END  0x100      /* Data End */
+#define             START_BIT_ERR  0x200      /* Start Bit Error */
+#define               DAT_BLK_END  0x400      /* Data Block End */
+#define                   CMD_ACT  0x800      /* CMD Active */
+#define                    TX_ACT  0x1000     /* Transmit Active */
+#define                    RX_ACT  0x2000     /* Receive Active */
+#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
+#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
+#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
+#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
+#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
+#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
+#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
+#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
+
+/* Bit masks for SDH_STATUS_CLR */
+
+#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
+#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
+#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
+#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
+#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
+#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
+#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
+#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
+#define              DAT_END_STAT  0x100      /* Data End Status */
+#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
+#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
+
+/* Bit masks for SDH_MASK0 */
+
+#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
+#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
+#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
+#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
+#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
+#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
+#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
+#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
+#define              DAT_END_MASK  0x100      /* Data End Mask */
+#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
+#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
+#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
+#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
+#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
+#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
+#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
+#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
+#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
+#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
+#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
+#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
+#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
+
+/* Bit masks for SDH_FIFO_CNT */
+
+#define                FIFO_COUNT  0x7fff     /* FIFO Count */
+
+/* Bit masks for SDH_E_STATUS */
+
+#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
+#define               SD_CARD_DET  0x10       /* SD Card Detect */
+
+/* Bit masks for SDH_E_MASK */
+
+#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
+#define                   SCD_MSK  0x40       /* Mask Card Detect */
+
+/* Bit masks for SDH_CFG */
+
+#define                   CLKS_EN  0x1        /* Clocks Enable */
+#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
+#define                       MWE  0x8        /* Moving Window Enable */
+#define                    SD_RST  0x10       /* SDMMC Reset */
+#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
+#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
+#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
+
+/* Bit masks for SDH_RD_WAIT_EN */
+
+#define                       RWR  0x1        /* Read Wait Request */
+
+/* Bit masks for ATAPI_CONTROL */
+
+#define                 PIO_START  0x1        /* Start PIO/Reg Op */
+#define               MULTI_START  0x2        /* Start Multi-DMA Op */
+#define               ULTRA_START  0x4        /* Start Ultra-DMA Op */
+#define                  XFER_DIR  0x8        /* Transfer Direction */
+#define                  IORDY_EN  0x10       /* IORDY Enable */
+#define                FIFO_FLUSH  0x20       /* Flush FIFOs */
+#define                  SOFT_RST  0x40       /* Soft Reset */
+#define                   DEV_RST  0x80       /* Device Reset */
+#define                TFRCNT_RST  0x100      /* Trans Count Reset */
+#define               END_ON_TERM  0x200      /* End/Terminate Select */
+#define               PIO_USE_DMA  0x400      /* PIO-DMA Enable */
+#define          UDMAIN_FIFO_THRS  0xf000     /* Ultra DMA-IN FIFO Threshold */
+
+/* Bit masks for ATAPI_STATUS */
+
+#define               PIO_XFER_ON  0x1        /* PIO transfer in progress */
+#define             MULTI_XFER_ON  0x2        /* Multi-word DMA transfer in progress */
+#define             ULTRA_XFER_ON  0x4        /* Ultra DMA transfer in progress */
+#define               ULTRA_IN_FL  0xf0       /* Ultra DMA Input FIFO Level */
+
+/* Bit masks for ATAPI_DEV_ADDR */
+
+#define                  DEV_ADDR  0x1f       /* Device Address */
+
+/* Bit masks for ATAPI_INT_MASK */
+
+#define        ATAPI_DEV_INT_MASK  0x1        /* Device interrupt mask */
+#define             PIO_DONE_MASK  0x2        /* PIO transfer done interrupt mask */
+#define           MULTI_DONE_MASK  0x4        /* Multi-DMA transfer done interrupt mask */
+#define          UDMAIN_DONE_MASK  0x8        /* Ultra-DMA in transfer done interrupt mask */
+#define         UDMAOUT_DONE_MASK  0x10       /* Ultra-DMA out transfer done interrupt mask */
+#define       HOST_TERM_XFER_MASK  0x20       /* Host terminate current transfer interrupt mask */
+#define           MULTI_TERM_MASK  0x40       /* Device terminate Multi-DMA transfer interrupt mask */
+#define          UDMAIN_TERM_MASK  0x80       /* Device terminate Ultra-DMA-in transfer interrupt mask */
+#define         UDMAOUT_TERM_MASK  0x100      /* Device terminate Ultra-DMA-out transfer interrupt mask */
+
+/* Bit masks for ATAPI_INT_STATUS */
+
+#define             ATAPI_DEV_INT  0x1        /* Device interrupt status */
+#define              PIO_DONE_INT  0x2        /* PIO transfer done interrupt status */
+#define            MULTI_DONE_INT  0x4        /* Multi-DMA transfer done interrupt status */
+#define           UDMAIN_DONE_INT  0x8        /* Ultra-DMA in transfer done interrupt status */
+#define          UDMAOUT_DONE_INT  0x10       /* Ultra-DMA out transfer done interrupt status */
+#define        HOST_TERM_XFER_INT  0x20       /* Host terminate current transfer interrupt status */
+#define            MULTI_TERM_INT  0x40       /* Device terminate Multi-DMA transfer interrupt status */
+#define           UDMAIN_TERM_INT  0x80       /* Device terminate Ultra-DMA-in transfer interrupt status */
+#define          UDMAOUT_TERM_INT  0x100      /* Device terminate Ultra-DMA-out transfer interrupt status */
+
+/* Bit masks for ATAPI_LINE_STATUS */
+
+#define                ATAPI_INTR  0x1        /* Device interrupt to host line status */
+#define                ATAPI_DASP  0x2        /* Device dasp to host line status */
+#define                ATAPI_CS0N  0x4        /* ATAPI chip select 0 line status */
+#define                ATAPI_CS1N  0x8        /* ATAPI chip select 1 line status */
+#define                ATAPI_ADDR  0x70       /* ATAPI address line status */
+#define              ATAPI_DMAREQ  0x80       /* ATAPI DMA request line status */
+#define             ATAPI_DMAACKN  0x100      /* ATAPI DMA acknowledge line status */
+#define               ATAPI_DIOWN  0x200      /* ATAPI write line status */
+#define               ATAPI_DIORN  0x400      /* ATAPI read line status */
+#define               ATAPI_IORDY  0x800      /* ATAPI IORDY line status */
+
+/* Bit masks for ATAPI_SM_STATE */
+
+#define                PIO_CSTATE  0xf        /* PIO mode state machine current state */
+#define                DMA_CSTATE  0xf0       /* DMA mode state machine current state */
+#define             UDMAIN_CSTATE  0xf00      /* Ultra DMA-In mode state machine current state */
+#define            UDMAOUT_CSTATE  0xf000     /* ATAPI IORDY line status */
+
+/* Bit masks for ATAPI_TERMINATE */
+
+#define           ATAPI_HOST_TERM  0x1        /* Host terminationation */
+
+/* Bit masks for ATAPI_REG_TIM_0 */
+
+#define                    T2_REG  0xff       /* End of cycle time for register access transfers */
+#define                  TEOC_REG  0xff00     /* Selects DIOR/DIOW pulsewidth */
+
+/* Bit masks for ATAPI_PIO_TIM_0 */
+
+#define                    T1_REG  0xf        /* Time from address valid to DIOR/DIOW */
+#define                T2_REG_PIO  0xff0      /* DIOR/DIOW pulsewidth */
+#define                    T4_REG  0xf000     /* DIOW data hold */
+
+/* Bit masks for ATAPI_PIO_TIM_1 */
+
+#define              TEOC_REG_PIO  0xff       /* End of cycle time for PIO access transfers. */
+
+/* Bit masks for ATAPI_MULTI_TIM_0 */
+
+#define                        TD  0xff       /* DIOR/DIOW asserted pulsewidth */
+#define                        TM  0xff00     /* Time from address valid to DIOR/DIOW */
+
+/* Bit masks for ATAPI_MULTI_TIM_1 */
+
+#define                       TKW  0xff       /* Selects DIOW negated pulsewidth */
+#define                       TKR  0xff00     /* Selects DIOR negated pulsewidth */
+
+/* Bit masks for ATAPI_MULTI_TIM_2 */
+
+#define                        TH  0xff       /* Selects DIOW data hold */
+#define                      TEOC  0xff00     /* Selects end of cycle for DMA */
+
+/* Bit masks for ATAPI_ULTRA_TIM_0 */
+
+#define                      TACK  0xff       /* Selects setup and hold times for TACK */
+#define                      TENV  0xff00     /* Selects envelope time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_1 */
+
+#define                      TDVS  0xff       /* Selects data valid setup time */
+#define                 TCYC_TDVS  0xff00     /* Selects cycle time - TDVS time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_2 */
+
+#define                       TSS  0xff       /* Selects time from STROBE edge to negation of DMARQ or assertion of STOP */
+#define                      TMLI  0xff00     /* Selects interlock time */
+
+/* Bit masks for ATAPI_ULTRA_TIM_3 */
+
+#define                      TZAH  0xff       /* Selects minimum delay required for output */
+#define               READY_PAUSE  0xff00     /* Selects ready to pause */
+
+/* Bit masks for TIMER_ENABLE1 */
+
+#define                    TIMEN8  0x1        /* Timer 8 Enable */
+#define                    TIMEN9  0x2        /* Timer 9 Enable */
+#define                   TIMEN10  0x4        /* Timer 10 Enable */
+
+/* Bit masks for TIMER_DISABLE1 */
+
+#define                   TIMDIS8  0x1        /* Timer 8 Disable */
+#define                   TIMDIS9  0x2        /* Timer 9 Disable */
+#define                  TIMDIS10  0x4        /* Timer 10 Disable */
+
+/* Bit masks for TIMER_STATUS1 */
+
+#define                    TIMIL8  0x1        /* Timer 8 Interrupt */
+#define                    TIMIL9  0x2        /* Timer 9 Interrupt */
+#define                   TIMIL10  0x4        /* Timer 10 Interrupt */
+#define                 TOVF_ERR8  0x10       /* Timer 8 Counter Overflow */
+#define                 TOVF_ERR9  0x20       /* Timer 9 Counter Overflow */
+#define                TOVF_ERR10  0x40       /* Timer 10 Counter Overflow */
+#define                     TRUN8  0x1000     /* Timer 8 Slave Enable Status */
+#define                     TRUN9  0x2000     /* Timer 9 Slave Enable Status */
+#define                    TRUN10  0x4000     /* Timer 10 Slave Enable Status */
+
+/* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
+
+/* Bit masks for USB_FADDR */
+
+#define          FUNCTION_ADDRESS  0x7f       /* Function address */
+
+/* Bit masks for USB_POWER */
+
+#define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
+#define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
+#define               RESUME_MODE  0x4        /* DMA Mode */
+#define                     RESET  0x8        /* Reset indicator */
+#define                   HS_MODE  0x10       /* High Speed mode indicator */
+#define                 HS_ENABLE  0x20       /* high Speed Enable */
+#define                 SOFT_CONN  0x40       /* Soft connect */
+#define                ISO_UPDATE  0x80       /* Isochronous update */
+
+/* Bit masks for USB_INTRTX */
+
+#define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
+#define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
+#define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
+#define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
+#define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
+#define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
+#define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
+#define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
+
+/* Bit masks for USB_INTRRX */
+
+#define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
+#define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
+#define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
+#define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
+#define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
+#define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
+#define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
+
+/* Bit masks for USB_INTRTXE */
+
+#define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
+#define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
+#define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
+#define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
+#define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
+#define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
+#define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
+#define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
+
+/* Bit masks for USB_INTRRXE */
+
+#define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
+#define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
+#define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
+#define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
+#define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
+#define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
+#define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
+
+/* Bit masks for USB_INTRUSB */
+
+#define                 SUSPEND_B  0x1        /* Suspend indicator */
+#define                  RESUME_B  0x2        /* Resume indicator */
+#define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
+#define                     SOF_B  0x8        /* Start of frame */
+#define                    CONN_B  0x10       /* Connection indicator */
+#define                  DISCON_B  0x20       /* Disconnect indicator */
+#define             SESSION_REQ_B  0x40       /* Session Request */
+#define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
+
+/* Bit masks for USB_INTRUSBE */
+
+#define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
+#define                 RESUME_BE  0x2        /* Resume indicator int enable */
+#define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
+#define                    SOF_BE  0x8        /* Start of frame int enable */
+#define                   CONN_BE  0x10       /* Connection indicator int enable */
+#define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
+#define            SESSION_REQ_BE  0x40       /* Session Request int enable */
+#define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
+
+/* Bit masks for USB_FRAME */
+
+#define              FRAME_NUMBER  0x7ff      /* Frame number */
+
+/* Bit masks for USB_INDEX */
+
+#define         SELECTED_ENDPOINT  0xf        /* selected endpoint */
+
+/* Bit masks for USB_GLOBAL_CTL */
+
+#define                GLOBAL_ENA  0x1        /* enables USB module */
+#define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
+#define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
+#define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
+#define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
+#define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
+#define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
+#define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
+#define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
+#define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
+#define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
+#define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
+#define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
+#define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
+#define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
+
+/* Bit masks for USB_OTG_DEV_CTL */
+
+#define                   SESSION  0x1        /* session indicator */
+#define                  HOST_REQ  0x2        /* Host negotiation request */
+#define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
+#define                     VBUS0  0x8        /* Vbus level indicator[0] */
+#define                     VBUS1  0x10       /* Vbus level indicator[1] */
+#define                     LSDEV  0x20       /* Low-speed indicator */
+#define                     FSDEV  0x40       /* Full or High-speed indicator */
+#define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
+
+/* Bit masks for USB_OTG_VBUS_IRQ */
+
+#define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
+#define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
+#define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
+#define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
+#define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
+#define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
+
+/* Bit masks for USB_OTG_VBUS_MASK */
+
+#define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
+#define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
+#define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
+#define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
+#define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
+#define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
+
+/* Bit masks for USB_CSR0 */
+
+#define                  RXPKTRDY  0x1        /* data packet receive indicator */
+#define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
+#define                STALL_SENT  0x4        /* STALL handshake sent */
+#define                   DATAEND  0x8        /* Data end indicator */
+#define                  SETUPEND  0x10       /* Setup end */
+#define                 SENDSTALL  0x20       /* Send STALL handshake */
+#define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
+#define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
+#define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
+#define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
+#define                SETUPPKT_H  0x8        /* send Setup token host mode */
+#define                   ERROR_H  0x10       /* timeout error indicator host mode */
+#define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
+#define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
+#define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
+
+/* Bit masks for USB_COUNT0 */
+
+#define              EP0_RX_COUNT  0x7f       /* number of received bytes in EP0 FIFO */
+
+/* Bit masks for USB_NAKLIMIT0 */
+
+#define             EP0_NAK_LIMIT  0x1f       /* number of frames/micro frames after which EP0 timeouts */
+
+/* Bit masks for USB_TX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_T  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_RX_MAX_PACKET */
+
+#define         MAX_PACKET_SIZE_R  0x7ff      /* maximum data pay load in a frame */
+
+/* Bit masks for USB_TXCSR */
+
+#define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
+#define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
+#define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
+#define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
+#define              STALL_SEND_T  0x10       /* issue a Stall handshake */
+#define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
+#define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
+#define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
+#define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
+#define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
+#define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
+#define                     ISO_T  0x4000     /* enable Isochronous transfers */
+#define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
+#define                  ERROR_TH  0x4        /* error condition host mode */
+#define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
+#define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
+
+/* Bit masks for USB_TXCOUNT */
+
+#define                  TX_COUNT  0x1fff     /* Number of bytes to be written to the selected endpoint Tx FIFO */
+
+/* Bit masks for USB_RXCSR */
+
+#define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
+#define               FIFO_FULL_R  0x2        /* FIFO not empty */
+#define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
+#define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
+#define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
+#define              STALL_SEND_R  0x20       /* issue a Stall handshake */
+#define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
+#define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
+#define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
+#define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
+#define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
+#define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
+#define                     ISO_R  0x4000     /* enable Isochronous transfers */
+#define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
+#define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
+#define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
+#define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
+#define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
+#define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
+#define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
+
+/* Bit masks for USB_RXCOUNT */
+
+#define                  RX_COUNT  0x1fff     /* Number of received bytes in the packet in the Rx FIFO */
+
+/* Bit masks for USB_TXTYPE */
+
+#define            TARGET_EP_NO_T  0xf        /* EP number */
+#define                PROTOCOL_T  0xc        /* transfer type */
+
+/* Bit masks for USB_TXINTERVAL */
+
+#define          TX_POLL_INTERVAL  0xff       /* polling interval for selected Tx EP */
+
+/* Bit masks for USB_RXTYPE */
+
+#define            TARGET_EP_NO_R  0xf        /* EP number */
+#define                PROTOCOL_R  0xc        /* transfer type */
+
+/* Bit masks for USB_RXINTERVAL */
+
+#define          RX_POLL_INTERVAL  0xff       /* polling interval for selected Rx EP */
+
+/* Bit masks for USB_DMA_INTERRUPT */
+
+#define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
+#define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
+#define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
+#define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
+#define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
+#define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
+#define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
+#define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
+
+/* Bit masks for USB_DMAxCONTROL */
+
+#define                   DMA_ENA  0x1        /* DMA enable */
+#define                 DIRECTION  0x2        /* direction of DMA transfer */
+#define                      MODE  0x4        /* DMA Bus error */
+#define                   INT_ENA  0x8        /* Interrupt enable */
+#define                     EPNUM  0xf0       /* EP number */
+#define                  BUSERROR  0x100      /* DMA Bus error */
+
+/* Bit masks for USB_DMAxADDRHIGH */
+
+#define             DMA_ADDR_HIGH  0xffff     /* Upper 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxADDRLOW */
+
+#define              DMA_ADDR_LOW  0xffff     /* Lower 16-bits of memory source/destination address for the DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTHIGH */
+
+#define            DMA_COUNT_HIGH  0xffff     /* Upper 16-bits of byte count of DMA transfer for DMA master channel */
+
+/* Bit masks for USB_DMAxCOUNTLOW */
+
+#define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
+
+/* Bit masks for HMDMAx_CONTROL */
+
+#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
+#define                       REP  0x2        /* Handshake MDMA Request Polarity */
+#define                       UTE  0x8        /* Urgency Threshold Enable */
+#define                       OIE  0x10       /* Overflow Interrupt Enable */
+#define                      BDIE  0x20       /* Block Done Interrupt Enable */
+#define                      MBDI  0x40       /* Mask Block Done Interrupt */
+#define                       DRQ  0x300      /* Handshake MDMA Request Type */
+#define                       RBC  0x1000     /* Force Reload of BCOUNT */
+#define                        PS  0x2000     /* Pin Status */
+#define                        OI  0x4000     /* Overflow Interrupt Generated */
+#define                       BDI  0x8000     /* Block Done Interrupt Generated */
+
+/* ******************************************* */
+/*     MULTI BIT MACRO ENUMERATIONS            */
+/* ******************************************* */
+
+/* ************************ */
+/*   MXVR Address Offsets   */
+/* ************************ */
+
+/* Control Message Receive Buffer (CMRB) Address Offsets */
+
+#define CMRB_STRIDE       0x00000016lu
+
+#define CMRB_DST_OFFSET   0x00000000lu
+#define CMRB_SRC_OFFSET   0x00000002lu
+#define CMRB_DATA_OFFSET  0x00000005lu
+
+/* Control Message Transmit Buffer (CMTB) Address Offsets */
+
+#define CMTB_PRIO_OFFSET    0x00000000lu
+#define CMTB_DST_OFFSET     0x00000002lu
+#define CMTB_SRC_OFFSET     0x00000004lu
+#define CMTB_TYPE_OFFSET    0x00000006lu
+#define CMTB_DATA_OFFSET    0x00000007lu
+
+#define CMTB_ANSWER_OFFSET  0x0000000Alu
+
+#define CMTB_STAT_N_OFFSET  0x00000018lu
+#define CMTB_STAT_A_OFFSET  0x00000016lu
+#define CMTB_STAT_D_OFFSET  0x0000000Elu
+#define CMTB_STAT_R_OFFSET  0x00000014lu
+#define CMTB_STAT_W_OFFSET  0x00000014lu
+#define CMTB_STAT_G_OFFSET  0x00000014lu
+
+/* Asynchronous Packet Receive Buffer (APRB) Address Offsets */
+
+#define APRB_STRIDE       0x00000400lu
+
+#define APRB_DST_OFFSET   0x00000000lu
+#define APRB_LEN_OFFSET   0x00000002lu
+#define APRB_SRC_OFFSET   0x00000004lu
+#define APRB_DATA_OFFSET  0x00000006lu
+
+/* Asynchronous Packet Transmit Buffer (APTB) Address Offsets */
+
+#define APTB_PRIO_OFFSET  0x00000000lu
+#define APTB_DST_OFFSET   0x00000002lu
+#define APTB_LEN_OFFSET   0x00000004lu
+#define APTB_SRC_OFFSET   0x00000006lu
+#define APTB_DATA_OFFSET  0x00000008lu
+
+/* Remote Read Buffer (RRDB) Address Offsets */
+
+#define RRDB_WADDR_OFFSET 0x00000100lu
+#define RRDB_WLEN_OFFSET  0x00000101lu
+
+/* **************** */
+/*   MXVR Macros    */
+/* **************** */
+
+/* MXVR_CONFIG Macros */
+
+#define SET_MSB(x)       ( ( (x) & 0xF  ) << 9)
+
+/* MXVR_INT_STAT_1 Macros */
+
+#define DONEX(x)         (0x00000002 << (4 * (x)))
+#define HDONEX(x)        (0x00000001 << (4 * (x)))
+
+/* MXVR_INT_EN_1 Macros */
+
+#define DONEENX(x)       (0x00000002 << (4 * (x)))
+#define HDONEENX(x)      (0x00000001 << (4 * (x)))
+
+/* MXVR_CDRPLL_CTL Macros */
+
+#define SET_CDRSHPSEL(x) ( ( (x) & 0x3F ) << 16)
+
+/* MXVR_FMPLL_CTL Macros */
+
+#define SET_CDRCPSEL(x)  ( ( (x) & 0xFF ) << 24)
+#define SET_FMCPSEL(x)   ( ( (x) & 0xFF ) << 24)
+
+#endif /* _DEF_BF549_H */
diff --git a/include/asm-blackfin/mach-bf548/defBF54x_base.h b/include/asm-blackfin/mach-bf548/defBF54x_base.h
new file mode 100644
index 0000000..895ddd4
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/defBF54x_base.h
@@ -0,0 +1,3878 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/defBF54x_base.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF54X_H
+#define _DEF_BF54X_H
+
+
+/* ************************************************************** */
+/*   SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF54x    */
+/* ************************************************************** */
+
+/* PLL Registers */
+
+#define                          PLL_CTL  0xffc00000   /* PLL Control Register */
+#define                          PLL_DIV  0xffc00004   /* PLL Divisor Register */
+#define                           VR_CTL  0xffc00008   /* Voltage Regulator Control Register */
+#define                         PLL_STAT  0xffc0000c   /* PLL Status Register */
+#define                      PLL_LOCKCNT  0xffc00010   /* PLL Lock Count Register */
+
+/* Debug/MP/Emulation Registers (0xFFC00014 - 0xFFC00014) */
+
+#define                           CHIPID  0xffc00014
+
+/* System Reset and Interrupt Controller (0xFFC00100 - 0xFFC00104) */
+
+#define                            SWRST  0xffc00100   /* Software Reset Register */
+#define                            SYSCR  0xffc00104   /* System Configuration register */
+
+/* SIC Registers */
+
+#define                       SIC_IMASK0  0xffc0010c   /* System Interrupt Mask Register 0 */
+#define                       SIC_IMASK1  0xffc00110   /* System Interrupt Mask Register 1 */
+#define                       SIC_IMASK2  0xffc00114   /* System Interrupt Mask Register 2 */
+#define                         SIC_ISR0  0xffc00118   /* System Interrupt Status Register 0 */
+#define                         SIC_ISR1  0xffc0011c   /* System Interrupt Status Register 1 */
+#define                         SIC_ISR2  0xffc00120   /* System Interrupt Status Register 2 */
+#define                         SIC_IWR0  0xffc00124   /* System Interrupt Wakeup Register 0 */
+#define                         SIC_IWR1  0xffc00128   /* System Interrupt Wakeup Register 1 */
+#define                         SIC_IWR2  0xffc0012c   /* System Interrupt Wakeup Register 2 */
+#define                         SIC_IAR0  0xffc00130   /* System Interrupt Assignment Register 0 */
+#define                         SIC_IAR1  0xffc00134   /* System Interrupt Assignment Register 1 */
+#define                         SIC_IAR2  0xffc00138   /* System Interrupt Assignment Register 2 */
+#define                         SIC_IAR3  0xffc0013c   /* System Interrupt Assignment Register 3 */
+#define                         SIC_IAR4  0xffc00140   /* System Interrupt Assignment Register 4 */
+#define                         SIC_IAR5  0xffc00144   /* System Interrupt Assignment Register 5 */
+#define                         SIC_IAR6  0xffc00148   /* System Interrupt Assignment Register 6 */
+#define                         SIC_IAR7  0xffc0014c   /* System Interrupt Assignment Register 7 */
+#define                         SIC_IAR8  0xffc00150   /* System Interrupt Assignment Register 8 */
+#define                         SIC_IAR9  0xffc00154   /* System Interrupt Assignment Register 9 */
+#define                        SIC_IAR10  0xffc00158   /* System Interrupt Assignment Register 10 */
+#define                        SIC_IAR11  0xffc0015c   /* System Interrupt Assignment Register 11 */
+
+/* Watchdog Timer Registers */
+
+#define                         WDOG_CTL  0xffc00200   /* Watchdog Control Register */
+#define                         WDOG_CNT  0xffc00204   /* Watchdog Count Register */
+#define                        WDOG_STAT  0xffc00208   /* Watchdog Status Register */
+
+/* RTC Registers */
+
+#define                         RTC_STAT  0xffc00300   /* RTC Status Register */
+#define                         RTC_ICTL  0xffc00304   /* RTC Interrupt Control Register */
+#define                        RTC_ISTAT  0xffc00308   /* RTC Interrupt Status Register */
+#define                        RTC_SWCNT  0xffc0030c   /* RTC Stopwatch Count Register */
+#define                        RTC_ALARM  0xffc00310   /* RTC Alarm Register */
+#define                         RTC_PREN  0xffc00314   /* RTC Prescaler Enable Register */
+
+/* UART0 Registers */
+
+#define                        UART0_DLL  0xffc00400   /* Divisor Latch Low Byte */
+#define                        UART0_DLH  0xffc00404   /* Divisor Latch High Byte */
+#define                       UART0_GCTL  0xffc00408   /* Global Control Register */
+#define                        UART0_LCR  0xffc0040c   /* Line Control Register */
+#define                        UART0_MCR  0xffc00410   /* Modem Control Register */
+#define                        UART0_LSR  0xffc00414   /* Line Status Register */
+#define                        UART0_MSR  0xffc00418   /* Modem Status Register */
+#define                        UART0_SCR  0xffc0041c   /* Scratch Register */
+#define                    UART0_IER_SET  0xffc00420   /* Interrupt Enable Register Set */
+#define                  UART0_IER_CLEAR  0xffc00424   /* Interrupt Enable Register Clear */
+#define                        UART0_THR  0xffc00428   /* Transmit Hold Register */
+#define                        UART0_RBR  0xffc0042c   /* Receive Buffer Register */
+
+/* SPI0 Registers */
+
+#define                         SPI0_CTL  0xffc00500   /* SPI0 Control Register */
+#define                         SPI0_FLG  0xffc00504   /* SPI0 Flag Register */
+#define                        SPI0_STAT  0xffc00508   /* SPI0 Status Register */
+#define                        SPI0_TDBR  0xffc0050c   /* SPI0 Transmit Data Buffer Register */
+#define                        SPI0_RDBR  0xffc00510   /* SPI0 Receive Data Buffer Register */
+#define                        SPI0_BAUD  0xffc00514   /* SPI0 Baud Rate Register */
+#define                      SPI0_SHADOW  0xffc00518   /* SPI0 Receive Data Buffer Shadow Register */
+
+/* Timer Group of 3 registers are not defined in the shared file because they are not available on the ADSP-BF542 processor */
+
+/* Two Wire Interface Registers (TWI0) */
+
+#define                      TWI0_CLKDIV  0xffc00700   /* Clock Divider Register */
+#define                     TWI0_CONTROL  0xffc00704   /* TWI Control Register */
+#define                  TWI0_SLAVE_CTRL  0xffc00708   /* TWI Slave Mode Control Register */
+#define                  TWI0_SLAVE_STAT  0xffc0070c   /* TWI Slave Mode Status Register */
+#define                  TWI0_SLAVE_ADDR  0xffc00710   /* TWI Slave Mode Address Register */
+#define                 TWI0_MASTER_CTRL  0xffc00714   /* TWI Master Mode Control Register */
+#define                 TWI0_MASTER_STAT  0xffc00718   /* TWI Master Mode Status Register */
+#define                 TWI0_MASTER_ADDR  0xffc0071c   /* TWI Master Mode Address Register */
+#define                    TWI0_INT_STAT  0xffc00720   /* TWI Interrupt Status Register */
+#define                    TWI0_INT_MASK  0xffc00724   /* TWI Interrupt Mask Register */
+#define                   TWI0_FIFO_CTRL  0xffc00728   /* TWI FIFO Control Register */
+#define                   TWI0_FIFO_STAT  0xffc0072c   /* TWI FIFO Status Register */
+#define                   TWI0_XMT_DATA8  0xffc00780   /* TWI FIFO Transmit Data Single Byte Register */
+#define                  TWI0_XMT_DATA16  0xffc00784   /* TWI FIFO Transmit Data Double Byte Register */
+#define                   TWI0_RCV_DATA8  0xffc00788   /* TWI FIFO Receive Data Single Byte Register */
+#define                  TWI0_RCV_DATA16  0xffc0078c   /* TWI FIFO Receive Data Double Byte Register */
+
+/* SPORT0 is not defined in the shared file because it is not available on the ADSP-BF542 and ADSP-BF544 processors */
+
+/* SPORT1 Registers */
+
+#define                      SPORT1_TCR1  0xffc00900   /* SPORT1 Transmit Configuration 1 Register */
+#define                      SPORT1_TCR2  0xffc00904   /* SPORT1 Transmit Configuration 2 Register */
+#define                   SPORT1_TCLKDIV  0xffc00908   /* SPORT1 Transmit Serial Clock Divider Register */
+#define                    SPORT1_TFSDIV  0xffc0090c   /* SPORT1 Transmit Frame Sync Divider Register */
+#define                        SPORT1_TX  0xffc00910   /* SPORT1 Transmit Data Register */
+#define                        SPORT1_RX  0xffc00918   /* SPORT1 Receive Data Register */
+#define                      SPORT1_RCR1  0xffc00920   /* SPORT1 Receive Configuration 1 Register */
+#define                      SPORT1_RCR2  0xffc00924   /* SPORT1 Receive Configuration 2 Register */
+#define                   SPORT1_RCLKDIV  0xffc00928   /* SPORT1 Receive Serial Clock Divider Register */
+#define                    SPORT1_RFSDIV  0xffc0092c   /* SPORT1 Receive Frame Sync Divider Register */
+#define                      SPORT1_STAT  0xffc00930   /* SPORT1 Status Register */
+#define                      SPORT1_CHNL  0xffc00934   /* SPORT1 Current Channel Register */
+#define                     SPORT1_MCMC1  0xffc00938   /* SPORT1 Multi channel Configuration Register 1 */
+#define                     SPORT1_MCMC2  0xffc0093c   /* SPORT1 Multi channel Configuration Register 2 */
+#define                     SPORT1_MTCS0  0xffc00940   /* SPORT1 Multi channel Transmit Select Register 0 */
+#define                     SPORT1_MTCS1  0xffc00944   /* SPORT1 Multi channel Transmit Select Register 1 */
+#define                     SPORT1_MTCS2  0xffc00948   /* SPORT1 Multi channel Transmit Select Register 2 */
+#define                     SPORT1_MTCS3  0xffc0094c   /* SPORT1 Multi channel Transmit Select Register 3 */
+#define                     SPORT1_MRCS0  0xffc00950   /* SPORT1 Multi channel Receive Select Register 0 */
+#define                     SPORT1_MRCS1  0xffc00954   /* SPORT1 Multi channel Receive Select Register 1 */
+#define                     SPORT1_MRCS2  0xffc00958   /* SPORT1 Multi channel Receive Select Register 2 */
+#define                     SPORT1_MRCS3  0xffc0095c   /* SPORT1 Multi channel Receive Select Register 3 */
+
+/* Asynchronous Memory Control Registers */
+
+#define                      EBIU_AMGCTL  0xffc00a00   /* Asynchronous Memory Global Control Register */
+#define                    EBIU_AMBCTL0   0xffc00a04   /* Asynchronous Memory Bank Control Register */
+#define                    EBIU_AMBCTL1   0xffc00a08   /* Asynchronous Memory Bank Control Register */
+#define                      EBIU_MBSCTL  0xffc00a0c   /* Asynchronous Memory Bank Select Control Register */
+#define                     EBIU_ARBSTAT  0xffc00a10   /* Asynchronous Memory Arbiter Status Register */
+#define                        EBIU_MODE  0xffc00a14   /* Asynchronous Mode Control Register */
+#define                        EBIU_FCTL  0xffc00a18   /* Asynchronous Memory Flash Control Register */
+
+/* DDR Memory Control Registers */
+
+#define                     EBIU_DDRCTL0  0xffc00a20   /* DDR Memory Control 0 Register */
+#define                     EBIU_DDRCTL1  0xffc00a24   /* DDR Memory Control 1 Register */
+#define                     EBIU_DDRCTL2  0xffc00a28   /* DDR Memory Control 2 Register */
+#define                     EBIU_DDRCTL3  0xffc00a2c   /* DDR Memory Control 3 Register */
+#define                      EBIU_DDRQUE  0xffc00a30   /* DDR Queue Configuration Register */
+#define                      EBIU_ERRADD  0xffc00a34   /* DDR Error Address Register */
+#define                      EBIU_ERRMST  0xffc00a38   /* DDR Error Master Register */
+#define                      EBIU_RSTCTL  0xffc00a3c   /* DDR Reset Control Register */
+
+/* DDR BankRead and Write Count Registers */
+
+#define                     EBIU_DDRBRC0  0xffc00a60   /* DDR Bank0 Read Count Register */
+#define                     EBIU_DDRBRC1  0xffc00a64   /* DDR Bank1 Read Count Register */
+#define                     EBIU_DDRBRC2  0xffc00a68   /* DDR Bank2 Read Count Register */
+#define                     EBIU_DDRBRC3  0xffc00a6c   /* DDR Bank3 Read Count Register */
+#define                     EBIU_DDRBRC4  0xffc00a70   /* DDR Bank4 Read Count Register */
+#define                     EBIU_DDRBRC5  0xffc00a74   /* DDR Bank5 Read Count Register */
+#define                     EBIU_DDRBRC6  0xffc00a78   /* DDR Bank6 Read Count Register */
+#define                     EBIU_DDRBRC7  0xffc00a7c   /* DDR Bank7 Read Count Register */
+#define                     EBIU_DDRBWC0  0xffc00a80   /* DDR Bank0 Write Count Register */
+#define                     EBIU_DDRBWC1  0xffc00a84   /* DDR Bank1 Write Count Register */
+#define                     EBIU_DDRBWC2  0xffc00a88   /* DDR Bank2 Write Count Register */
+#define                     EBIU_DDRBWC3  0xffc00a8c   /* DDR Bank3 Write Count Register */
+#define                     EBIU_DDRBWC4  0xffc00a90   /* DDR Bank4 Write Count Register */
+#define                     EBIU_DDRBWC5  0xffc00a94   /* DDR Bank5 Write Count Register */
+#define                     EBIU_DDRBWC6  0xffc00a98   /* DDR Bank6 Write Count Register */
+#define                     EBIU_DDRBWC7  0xffc00a9c   /* DDR Bank7 Write Count Register */
+#define                     EBIU_DDRACCT  0xffc00aa0   /* DDR Activation Count Register */
+#define                     EBIU_DDRTACT  0xffc00aa8   /* DDR Turn Around Count Register */
+#define                     EBIU_DDRARCT  0xffc00aac   /* DDR Auto-refresh Count Register */
+#define                      EBIU_DDRGC0  0xffc00ab0   /* DDR Grant Count 0 Register */
+#define                      EBIU_DDRGC1  0xffc00ab4   /* DDR Grant Count 1 Register */
+#define                      EBIU_DDRGC2  0xffc00ab8   /* DDR Grant Count 2 Register */
+#define                      EBIU_DDRGC3  0xffc00abc   /* DDR Grant Count 3 Register */
+#define                     EBIU_DDRMCEN  0xffc00ac0   /* DDR Metrics Counter Enable Register */
+#define                     EBIU_DDRMCCL  0xffc00ac4   /* DDR Metrics Counter Clear Register */
+
+/* DMAC0 Registers */
+
+#define                      DMAC0_TCPER  0xffc00b0c   /* DMA Controller 0 Traffic Control Periods Register */
+#define                      DMAC0_TCCNT  0xffc00b10   /* DMA Controller 0 Current Counts Register */
+
+/* DMA Channel 0 Registers */
+
+#define               DMA0_NEXT_DESC_PTR  0xffc00c00   /* DMA Channel 0 Next Descriptor Pointer Register */
+#define                  DMA0_START_ADDR  0xffc00c04   /* DMA Channel 0 Start Address Register */
+#define                      DMA0_CONFIG  0xffc00c08   /* DMA Channel 0 Configuration Register */
+#define                     DMA0_X_COUNT  0xffc00c10   /* DMA Channel 0 X Count Register */
+#define                    DMA0_X_MODIFY  0xffc00c14   /* DMA Channel 0 X Modify Register */
+#define                     DMA0_Y_COUNT  0xffc00c18   /* DMA Channel 0 Y Count Register */
+#define                    DMA0_Y_MODIFY  0xffc00c1c   /* DMA Channel 0 Y Modify Register */
+#define               DMA0_CURR_DESC_PTR  0xffc00c20   /* DMA Channel 0 Current Descriptor Pointer Register */
+#define                   DMA0_CURR_ADDR  0xffc00c24   /* DMA Channel 0 Current Address Register */
+#define                  DMA0_IRQ_STATUS  0xffc00c28   /* DMA Channel 0 Interrupt/Status Register */
+#define              DMA0_PERIPHERAL_MAP  0xffc00c2c   /* DMA Channel 0 Peripheral Map Register */
+#define                DMA0_CURR_X_COUNT  0xffc00c30   /* DMA Channel 0 Current X Count Register */
+#define                DMA0_CURR_Y_COUNT  0xffc00c38   /* DMA Channel 0 Current Y Count Register */
+
+/* DMA Channel 1 Registers */
+
+#define               DMA1_NEXT_DESC_PTR  0xffc00c40   /* DMA Channel 1 Next Descriptor Pointer Register */
+#define                  DMA1_START_ADDR  0xffc00c44   /* DMA Channel 1 Start Address Register */
+#define                      DMA1_CONFIG  0xffc00c48   /* DMA Channel 1 Configuration Register */
+#define                     DMA1_X_COUNT  0xffc00c50   /* DMA Channel 1 X Count Register */
+#define                    DMA1_X_MODIFY  0xffc00c54   /* DMA Channel 1 X Modify Register */
+#define                     DMA1_Y_COUNT  0xffc00c58   /* DMA Channel 1 Y Count Register */
+#define                    DMA1_Y_MODIFY  0xffc00c5c   /* DMA Channel 1 Y Modify Register */
+#define               DMA1_CURR_DESC_PTR  0xffc00c60   /* DMA Channel 1 Current Descriptor Pointer Register */
+#define                   DMA1_CURR_ADDR  0xffc00c64   /* DMA Channel 1 Current Address Register */
+#define                  DMA1_IRQ_STATUS  0xffc00c68   /* DMA Channel 1 Interrupt/Status Register */
+#define              DMA1_PERIPHERAL_MAP  0xffc00c6c   /* DMA Channel 1 Peripheral Map Register */
+#define                DMA1_CURR_X_COUNT  0xffc00c70   /* DMA Channel 1 Current X Count Register */
+#define                DMA1_CURR_Y_COUNT  0xffc00c78   /* DMA Channel 1 Current Y Count Register */
+
+/* DMA Channel 2 Registers */
+
+#define               DMA2_NEXT_DESC_PTR  0xffc00c80   /* DMA Channel 2 Next Descriptor Pointer Register */
+#define                  DMA2_START_ADDR  0xffc00c84   /* DMA Channel 2 Start Address Register */
+#define                      DMA2_CONFIG  0xffc00c88   /* DMA Channel 2 Configuration Register */
+#define                     DMA2_X_COUNT  0xffc00c90   /* DMA Channel 2 X Count Register */
+#define                    DMA2_X_MODIFY  0xffc00c94   /* DMA Channel 2 X Modify Register */
+#define                     DMA2_Y_COUNT  0xffc00c98   /* DMA Channel 2 Y Count Register */
+#define                    DMA2_Y_MODIFY  0xffc00c9c   /* DMA Channel 2 Y Modify Register */
+#define               DMA2_CURR_DESC_PTR  0xffc00ca0   /* DMA Channel 2 Current Descriptor Pointer Register */
+#define                   DMA2_CURR_ADDR  0xffc00ca4   /* DMA Channel 2 Current Address Register */
+#define                  DMA2_IRQ_STATUS  0xffc00ca8   /* DMA Channel 2 Interrupt/Status Register */
+#define              DMA2_PERIPHERAL_MAP  0xffc00cac   /* DMA Channel 2 Peripheral Map Register */
+#define                DMA2_CURR_X_COUNT  0xffc00cb0   /* DMA Channel 2 Current X Count Register */
+#define                DMA2_CURR_Y_COUNT  0xffc00cb8   /* DMA Channel 2 Current Y Count Register */
+
+/* DMA Channel 3 Registers */
+
+#define               DMA3_NEXT_DESC_PTR  0xffc00cc0   /* DMA Channel 3 Next Descriptor Pointer Register */
+#define                  DMA3_START_ADDR  0xffc00cc4   /* DMA Channel 3 Start Address Register */
+#define                      DMA3_CONFIG  0xffc00cc8   /* DMA Channel 3 Configuration Register */
+#define                     DMA3_X_COUNT  0xffc00cd0   /* DMA Channel 3 X Count Register */
+#define                    DMA3_X_MODIFY  0xffc00cd4   /* DMA Channel 3 X Modify Register */
+#define                     DMA3_Y_COUNT  0xffc00cd8   /* DMA Channel 3 Y Count Register */
+#define                    DMA3_Y_MODIFY  0xffc00cdc   /* DMA Channel 3 Y Modify Register */
+#define               DMA3_CURR_DESC_PTR  0xffc00ce0   /* DMA Channel 3 Current Descriptor Pointer Register */
+#define                   DMA3_CURR_ADDR  0xffc00ce4   /* DMA Channel 3 Current Address Register */
+#define                  DMA3_IRQ_STATUS  0xffc00ce8   /* DMA Channel 3 Interrupt/Status Register */
+#define              DMA3_PERIPHERAL_MAP  0xffc00cec   /* DMA Channel 3 Peripheral Map Register */
+#define                DMA3_CURR_X_COUNT  0xffc00cf0   /* DMA Channel 3 Current X Count Register */
+#define                DMA3_CURR_Y_COUNT  0xffc00cf8   /* DMA Channel 3 Current Y Count Register */
+
+/* DMA Channel 4 Registers */
+
+#define               DMA4_NEXT_DESC_PTR  0xffc00d00   /* DMA Channel 4 Next Descriptor Pointer Register */
+#define                  DMA4_START_ADDR  0xffc00d04   /* DMA Channel 4 Start Address Register */
+#define                      DMA4_CONFIG  0xffc00d08   /* DMA Channel 4 Configuration Register */
+#define                     DMA4_X_COUNT  0xffc00d10   /* DMA Channel 4 X Count Register */
+#define                    DMA4_X_MODIFY  0xffc00d14   /* DMA Channel 4 X Modify Register */
+#define                     DMA4_Y_COUNT  0xffc00d18   /* DMA Channel 4 Y Count Register */
+#define                    DMA4_Y_MODIFY  0xffc00d1c   /* DMA Channel 4 Y Modify Register */
+#define               DMA4_CURR_DESC_PTR  0xffc00d20   /* DMA Channel 4 Current Descriptor Pointer Register */
+#define                   DMA4_CURR_ADDR  0xffc00d24   /* DMA Channel 4 Current Address Register */
+#define                  DMA4_IRQ_STATUS  0xffc00d28   /* DMA Channel 4 Interrupt/Status Register */
+#define              DMA4_PERIPHERAL_MAP  0xffc00d2c   /* DMA Channel 4 Peripheral Map Register */
+#define                DMA4_CURR_X_COUNT  0xffc00d30   /* DMA Channel 4 Current X Count Register */
+#define                DMA4_CURR_Y_COUNT  0xffc00d38   /* DMA Channel 4 Current Y Count Register */
+
+/* DMA Channel 5 Registers */
+
+#define               DMA5_NEXT_DESC_PTR  0xffc00d40   /* DMA Channel 5 Next Descriptor Pointer Register */
+#define                  DMA5_START_ADDR  0xffc00d44   /* DMA Channel 5 Start Address Register */
+#define                      DMA5_CONFIG  0xffc00d48   /* DMA Channel 5 Configuration Register */
+#define                     DMA5_X_COUNT  0xffc00d50   /* DMA Channel 5 X Count Register */
+#define                    DMA5_X_MODIFY  0xffc00d54   /* DMA Channel 5 X Modify Register */
+#define                     DMA5_Y_COUNT  0xffc00d58   /* DMA Channel 5 Y Count Register */
+#define                    DMA5_Y_MODIFY  0xffc00d5c   /* DMA Channel 5 Y Modify Register */
+#define               DMA5_CURR_DESC_PTR  0xffc00d60   /* DMA Channel 5 Current Descriptor Pointer Register */
+#define                   DMA5_CURR_ADDR  0xffc00d64   /* DMA Channel 5 Current Address Register */
+#define                  DMA5_IRQ_STATUS  0xffc00d68   /* DMA Channel 5 Interrupt/Status Register */
+#define              DMA5_PERIPHERAL_MAP  0xffc00d6c   /* DMA Channel 5 Peripheral Map Register */
+#define                DMA5_CURR_X_COUNT  0xffc00d70   /* DMA Channel 5 Current X Count Register */
+#define                DMA5_CURR_Y_COUNT  0xffc00d78   /* DMA Channel 5 Current Y Count Register */
+
+/* DMA Channel 6 Registers */
+
+#define               DMA6_NEXT_DESC_PTR  0xffc00d80   /* DMA Channel 6 Next Descriptor Pointer Register */
+#define                  DMA6_START_ADDR  0xffc00d84   /* DMA Channel 6 Start Address Register */
+#define                      DMA6_CONFIG  0xffc00d88   /* DMA Channel 6 Configuration Register */
+#define                     DMA6_X_COUNT  0xffc00d90   /* DMA Channel 6 X Count Register */
+#define                    DMA6_X_MODIFY  0xffc00d94   /* DMA Channel 6 X Modify Register */
+#define                     DMA6_Y_COUNT  0xffc00d98   /* DMA Channel 6 Y Count Register */
+#define                    DMA6_Y_MODIFY  0xffc00d9c   /* DMA Channel 6 Y Modify Register */
+#define               DMA6_CURR_DESC_PTR  0xffc00da0   /* DMA Channel 6 Current Descriptor Pointer Register */
+#define                   DMA6_CURR_ADDR  0xffc00da4   /* DMA Channel 6 Current Address Register */
+#define                  DMA6_IRQ_STATUS  0xffc00da8   /* DMA Channel 6 Interrupt/Status Register */
+#define              DMA6_PERIPHERAL_MAP  0xffc00dac   /* DMA Channel 6 Peripheral Map Register */
+#define                DMA6_CURR_X_COUNT  0xffc00db0   /* DMA Channel 6 Current X Count Register */
+#define                DMA6_CURR_Y_COUNT  0xffc00db8   /* DMA Channel 6 Current Y Count Register */
+
+/* DMA Channel 7 Registers */
+
+#define               DMA7_NEXT_DESC_PTR  0xffc00dc0   /* DMA Channel 7 Next Descriptor Pointer Register */
+#define                  DMA7_START_ADDR  0xffc00dc4   /* DMA Channel 7 Start Address Register */
+#define                      DMA7_CONFIG  0xffc00dc8   /* DMA Channel 7 Configuration Register */
+#define                     DMA7_X_COUNT  0xffc00dd0   /* DMA Channel 7 X Count Register */
+#define                    DMA7_X_MODIFY  0xffc00dd4   /* DMA Channel 7 X Modify Register */
+#define                     DMA7_Y_COUNT  0xffc00dd8   /* DMA Channel 7 Y Count Register */
+#define                    DMA7_Y_MODIFY  0xffc00ddc   /* DMA Channel 7 Y Modify Register */
+#define               DMA7_CURR_DESC_PTR  0xffc00de0   /* DMA Channel 7 Current Descriptor Pointer Register */
+#define                   DMA7_CURR_ADDR  0xffc00de4   /* DMA Channel 7 Current Address Register */
+#define                  DMA7_IRQ_STATUS  0xffc00de8   /* DMA Channel 7 Interrupt/Status Register */
+#define              DMA7_PERIPHERAL_MAP  0xffc00dec   /* DMA Channel 7 Peripheral Map Register */
+#define                DMA7_CURR_X_COUNT  0xffc00df0   /* DMA Channel 7 Current X Count Register */
+#define                DMA7_CURR_Y_COUNT  0xffc00df8   /* DMA Channel 7 Current Y Count Register */
+
+/* DMA Channel 8 Registers */
+
+#define               DMA8_NEXT_DESC_PTR  0xffc00e00   /* DMA Channel 8 Next Descriptor Pointer Register */
+#define                  DMA8_START_ADDR  0xffc00e04   /* DMA Channel 8 Start Address Register */
+#define                      DMA8_CONFIG  0xffc00e08   /* DMA Channel 8 Configuration Register */
+#define                     DMA8_X_COUNT  0xffc00e10   /* DMA Channel 8 X Count Register */
+#define                    DMA8_X_MODIFY  0xffc00e14   /* DMA Channel 8 X Modify Register */
+#define                     DMA8_Y_COUNT  0xffc00e18   /* DMA Channel 8 Y Count Register */
+#define                    DMA8_Y_MODIFY  0xffc00e1c   /* DMA Channel 8 Y Modify Register */
+#define               DMA8_CURR_DESC_PTR  0xffc00e20   /* DMA Channel 8 Current Descriptor Pointer Register */
+#define                   DMA8_CURR_ADDR  0xffc00e24   /* DMA Channel 8 Current Address Register */
+#define                  DMA8_IRQ_STATUS  0xffc00e28   /* DMA Channel 8 Interrupt/Status Register */
+#define              DMA8_PERIPHERAL_MAP  0xffc00e2c   /* DMA Channel 8 Peripheral Map Register */
+#define                DMA8_CURR_X_COUNT  0xffc00e30   /* DMA Channel 8 Current X Count Register */
+#define                DMA8_CURR_Y_COUNT  0xffc00e38   /* DMA Channel 8 Current Y Count Register */
+
+/* DMA Channel 9 Registers */
+
+#define               DMA9_NEXT_DESC_PTR  0xffc00e40   /* DMA Channel 9 Next Descriptor Pointer Register */
+#define                  DMA9_START_ADDR  0xffc00e44   /* DMA Channel 9 Start Address Register */
+#define                      DMA9_CONFIG  0xffc00e48   /* DMA Channel 9 Configuration Register */
+#define                     DMA9_X_COUNT  0xffc00e50   /* DMA Channel 9 X Count Register */
+#define                    DMA9_X_MODIFY  0xffc00e54   /* DMA Channel 9 X Modify Register */
+#define                     DMA9_Y_COUNT  0xffc00e58   /* DMA Channel 9 Y Count Register */
+#define                    DMA9_Y_MODIFY  0xffc00e5c   /* DMA Channel 9 Y Modify Register */
+#define               DMA9_CURR_DESC_PTR  0xffc00e60   /* DMA Channel 9 Current Descriptor Pointer Register */
+#define                   DMA9_CURR_ADDR  0xffc00e64   /* DMA Channel 9 Current Address Register */
+#define                  DMA9_IRQ_STATUS  0xffc00e68   /* DMA Channel 9 Interrupt/Status Register */
+#define              DMA9_PERIPHERAL_MAP  0xffc00e6c   /* DMA Channel 9 Peripheral Map Register */
+#define                DMA9_CURR_X_COUNT  0xffc00e70   /* DMA Channel 9 Current X Count Register */
+#define                DMA9_CURR_Y_COUNT  0xffc00e78   /* DMA Channel 9 Current Y Count Register */
+
+/* DMA Channel 10 Registers */
+
+#define              DMA10_NEXT_DESC_PTR  0xffc00e80   /* DMA Channel 10 Next Descriptor Pointer Register */
+#define                 DMA10_START_ADDR  0xffc00e84   /* DMA Channel 10 Start Address Register */
+#define                     DMA10_CONFIG  0xffc00e88   /* DMA Channel 10 Configuration Register */
+#define                    DMA10_X_COUNT  0xffc00e90   /* DMA Channel 10 X Count Register */
+#define                   DMA10_X_MODIFY  0xffc00e94   /* DMA Channel 10 X Modify Register */
+#define                    DMA10_Y_COUNT  0xffc00e98   /* DMA Channel 10 Y Count Register */
+#define                   DMA10_Y_MODIFY  0xffc00e9c   /* DMA Channel 10 Y Modify Register */
+#define              DMA10_CURR_DESC_PTR  0xffc00ea0   /* DMA Channel 10 Current Descriptor Pointer Register */
+#define                  DMA10_CURR_ADDR  0xffc00ea4   /* DMA Channel 10 Current Address Register */
+#define                 DMA10_IRQ_STATUS  0xffc00ea8   /* DMA Channel 10 Interrupt/Status Register */
+#define             DMA10_PERIPHERAL_MAP  0xffc00eac   /* DMA Channel 10 Peripheral Map Register */
+#define               DMA10_CURR_X_COUNT  0xffc00eb0   /* DMA Channel 10 Current X Count Register */
+#define               DMA10_CURR_Y_COUNT  0xffc00eb8   /* DMA Channel 10 Current Y Count Register */
+
+/* DMA Channel 11 Registers */
+
+#define              DMA11_NEXT_DESC_PTR  0xffc00ec0   /* DMA Channel 11 Next Descriptor Pointer Register */
+#define                 DMA11_START_ADDR  0xffc00ec4   /* DMA Channel 11 Start Address Register */
+#define                     DMA11_CONFIG  0xffc00ec8   /* DMA Channel 11 Configuration Register */
+#define                    DMA11_X_COUNT  0xffc00ed0   /* DMA Channel 11 X Count Register */
+#define                   DMA11_X_MODIFY  0xffc00ed4   /* DMA Channel 11 X Modify Register */
+#define                    DMA11_Y_COUNT  0xffc00ed8   /* DMA Channel 11 Y Count Register */
+#define                   DMA11_Y_MODIFY  0xffc00edc   /* DMA Channel 11 Y Modify Register */
+#define              DMA11_CURR_DESC_PTR  0xffc00ee0   /* DMA Channel 11 Current Descriptor Pointer Register */
+#define                  DMA11_CURR_ADDR  0xffc00ee4   /* DMA Channel 11 Current Address Register */
+#define                 DMA11_IRQ_STATUS  0xffc00ee8   /* DMA Channel 11 Interrupt/Status Register */
+#define             DMA11_PERIPHERAL_MAP  0xffc00eec   /* DMA Channel 11 Peripheral Map Register */
+#define               DMA11_CURR_X_COUNT  0xffc00ef0   /* DMA Channel 11 Current X Count Register */
+#define               DMA11_CURR_Y_COUNT  0xffc00ef8   /* DMA Channel 11 Current Y Count Register */
+
+/* MDMA Stream 0 Registers */
+
+#define            MDMA_D0_NEXT_DESC_PTR  0xffc00f00   /* Memory DMA Stream 0 Destination Next Descriptor Pointer Register */
+#define               MDMA_D0_START_ADDR  0xffc00f04   /* Memory DMA Stream 0 Destination Start Address Register */
+#define                   MDMA_D0_CONFIG  0xffc00f08   /* Memory DMA Stream 0 Destination Configuration Register */
+#define                  MDMA_D0_X_COUNT  0xffc00f10   /* Memory DMA Stream 0 Destination X Count Register */
+#define                 MDMA_D0_X_MODIFY  0xffc00f14   /* Memory DMA Stream 0 Destination X Modify Register */
+#define                  MDMA_D0_Y_COUNT  0xffc00f18   /* Memory DMA Stream 0 Destination Y Count Register */
+#define                 MDMA_D0_Y_MODIFY  0xffc00f1c   /* Memory DMA Stream 0 Destination Y Modify Register */
+#define            MDMA_D0_CURR_DESC_PTR  0xffc00f20   /* Memory DMA Stream 0 Destination Current Descriptor Pointer Register */
+#define                MDMA_D0_CURR_ADDR  0xffc00f24   /* Memory DMA Stream 0 Destination Current Address Register */
+#define               MDMA_D0_IRQ_STATUS  0xffc00f28   /* Memory DMA Stream 0 Destination Interrupt/Status Register */
+#define           MDMA_D0_PERIPHERAL_MAP  0xffc00f2c   /* Memory DMA Stream 0 Destination Peripheral Map Register */
+#define             MDMA_D0_CURR_X_COUNT  0xffc00f30   /* Memory DMA Stream 0 Destination Current X Count Register */
+#define             MDMA_D0_CURR_Y_COUNT  0xffc00f38   /* Memory DMA Stream 0 Destination Current Y Count Register */
+#define            MDMA_S0_NEXT_DESC_PTR  0xffc00f40   /* Memory DMA Stream 0 Source Next Descriptor Pointer Register */
+#define               MDMA_S0_START_ADDR  0xffc00f44   /* Memory DMA Stream 0 Source Start Address Register */
+#define                   MDMA_S0_CONFIG  0xffc00f48   /* Memory DMA Stream 0 Source Configuration Register */
+#define                  MDMA_S0_X_COUNT  0xffc00f50   /* Memory DMA Stream 0 Source X Count Register */
+#define                 MDMA_S0_X_MODIFY  0xffc00f54   /* Memory DMA Stream 0 Source X Modify Register */
+#define                  MDMA_S0_Y_COUNT  0xffc00f58   /* Memory DMA Stream 0 Source Y Count Register */
+#define                 MDMA_S0_Y_MODIFY  0xffc00f5c   /* Memory DMA Stream 0 Source Y Modify Register */
+#define            MDMA_S0_CURR_DESC_PTR  0xffc00f60   /* Memory DMA Stream 0 Source Current Descriptor Pointer Register */
+#define                MDMA_S0_CURR_ADDR  0xffc00f64   /* Memory DMA Stream 0 Source Current Address Register */
+#define               MDMA_S0_IRQ_STATUS  0xffc00f68   /* Memory DMA Stream 0 Source Interrupt/Status Register */
+#define           MDMA_S0_PERIPHERAL_MAP  0xffc00f6c   /* Memory DMA Stream 0 Source Peripheral Map Register */
+#define             MDMA_S0_CURR_X_COUNT  0xffc00f70   /* Memory DMA Stream 0 Source Current X Count Register */
+#define             MDMA_S0_CURR_Y_COUNT  0xffc00f78   /* Memory DMA Stream 0 Source Current Y Count Register */
+
+/* MDMA Stream 1 Registers */
+
+#define            MDMA_D1_NEXT_DESC_PTR  0xffc00f80   /* Memory DMA Stream 1 Destination Next Descriptor Pointer Register */
+#define               MDMA_D1_START_ADDR  0xffc00f84   /* Memory DMA Stream 1 Destination Start Address Register */
+#define                   MDMA_D1_CONFIG  0xffc00f88   /* Memory DMA Stream 1 Destination Configuration Register */
+#define                  MDMA_D1_X_COUNT  0xffc00f90   /* Memory DMA Stream 1 Destination X Count Register */
+#define                 MDMA_D1_X_MODIFY  0xffc00f94   /* Memory DMA Stream 1 Destination X Modify Register */
+#define                  MDMA_D1_Y_COUNT  0xffc00f98   /* Memory DMA Stream 1 Destination Y Count Register */
+#define                 MDMA_D1_Y_MODIFY  0xffc00f9c   /* Memory DMA Stream 1 Destination Y Modify Register */
+#define            MDMA_D1_CURR_DESC_PTR  0xffc00fa0   /* Memory DMA Stream 1 Destination Current Descriptor Pointer Register */
+#define                MDMA_D1_CURR_ADDR  0xffc00fa4   /* Memory DMA Stream 1 Destination Current Address Register */
+#define               MDMA_D1_IRQ_STATUS  0xffc00fa8   /* Memory DMA Stream 1 Destination Interrupt/Status Register */
+#define           MDMA_D1_PERIPHERAL_MAP  0xffc00fac   /* Memory DMA Stream 1 Destination Peripheral Map Register */
+#define             MDMA_D1_CURR_X_COUNT  0xffc00fb0   /* Memory DMA Stream 1 Destination Current X Count Register */
+#define             MDMA_D1_CURR_Y_COUNT  0xffc00fb8   /* Memory DMA Stream 1 Destination Current Y Count Register */
+#define            MDMA_S1_NEXT_DESC_PTR  0xffc00fc0   /* Memory DMA Stream 1 Source Next Descriptor Pointer Register */
+#define               MDMA_S1_START_ADDR  0xffc00fc4   /* Memory DMA Stream 1 Source Start Address Register */
+#define                   MDMA_S1_CONFIG  0xffc00fc8   /* Memory DMA Stream 1 Source Configuration Register */
+#define                  MDMA_S1_X_COUNT  0xffc00fd0   /* Memory DMA Stream 1 Source X Count Register */
+#define                 MDMA_S1_X_MODIFY  0xffc00fd4   /* Memory DMA Stream 1 Source X Modify Register */
+#define                  MDMA_S1_Y_COUNT  0xffc00fd8   /* Memory DMA Stream 1 Source Y Count Register */
+#define                 MDMA_S1_Y_MODIFY  0xffc00fdc   /* Memory DMA Stream 1 Source Y Modify Register */
+#define            MDMA_S1_CURR_DESC_PTR  0xffc00fe0   /* Memory DMA Stream 1 Source Current Descriptor Pointer Register */
+#define                MDMA_S1_CURR_ADDR  0xffc00fe4   /* Memory DMA Stream 1 Source Current Address Register */
+#define               MDMA_S1_IRQ_STATUS  0xffc00fe8   /* Memory DMA Stream 1 Source Interrupt/Status Register */
+#define           MDMA_S1_PERIPHERAL_MAP  0xffc00fec   /* Memory DMA Stream 1 Source Peripheral Map Register */
+#define             MDMA_S1_CURR_X_COUNT  0xffc00ff0   /* Memory DMA Stream 1 Source Current X Count Register */
+#define             MDMA_S1_CURR_Y_COUNT  0xffc00ff8   /* Memory DMA Stream 1 Source Current Y Count Register */
+
+/* UART3 Registers */
+
+#define                        UART3_DLL  0xffc03100   /* Divisor Latch Low Byte */
+#define                        UART3_DLH  0xffc03104   /* Divisor Latch High Byte */
+#define                       UART3_GCTL  0xffc03108   /* Global Control Register */
+#define                        UART3_LCR  0xffc0310c   /* Line Control Register */
+#define                        UART3_MCR  0xffc03110   /* Modem Control Register */
+#define                        UART3_LSR  0xffc03114   /* Line Status Register */
+#define                        UART3_MSR  0xffc03118   /* Modem Status Register */
+#define                        UART3_SCR  0xffc0311c   /* Scratch Register */
+#define                    UART3_IER_SET  0xffc03120   /* Interrupt Enable Register Set */
+#define                  UART3_IER_CLEAR  0xffc03124   /* Interrupt Enable Register Clear */
+#define                        UART3_THR  0xffc03128   /* Transmit Hold Register */
+#define                        UART3_RBR  0xffc0312c   /* Receive Buffer Register */
+
+/* EPPI1 Registers */
+
+#define                     EPPI1_STATUS  0xffc01300   /* EPPI1 Status Register */
+#define                     EPPI1_HCOUNT  0xffc01304   /* EPPI1 Horizontal Transfer Count Register */
+#define                     EPPI1_HDELAY  0xffc01308   /* EPPI1 Horizontal Delay Count Register */
+#define                     EPPI1_VCOUNT  0xffc0130c   /* EPPI1 Vertical Transfer Count Register */
+#define                     EPPI1_VDELAY  0xffc01310   /* EPPI1 Vertical Delay Count Register */
+#define                      EPPI1_FRAME  0xffc01314   /* EPPI1 Lines per Frame Register */
+#define                       EPPI1_LINE  0xffc01318   /* EPPI1 Samples per Line Register */
+#define                     EPPI1_CLKDIV  0xffc0131c   /* EPPI1 Clock Divide Register */
+#define                    EPPI1_CONTROL  0xffc01320   /* EPPI1 Control Register */
+#define                   EPPI1_FS1W_HBL  0xffc01324   /* EPPI1 FS1 Width Register / EPPI1 Horizontal Blanking Samples Per Line Register */
+#define                  EPPI1_FS1P_AVPL  0xffc01328   /* EPPI1 FS1 Period Register / EPPI1 Active Video Samples Per Line Register */
+#define                   EPPI1_FS2W_LVB  0xffc0132c   /* EPPI1 FS2 Width Register / EPPI1 Lines of Vertical Blanking Register */
+#define                  EPPI1_FS2P_LAVF  0xffc01330   /* EPPI1 FS2 Period Register/ EPPI1 Lines of Active Video Per Field Register */
+#define                       EPPI1_CLIP  0xffc01334   /* EPPI1 Clipping Register */
+
+/* Port Interrupt 0 Registers (32-bit) */
+
+#define                   PINT0_MASK_SET  0xffc01400   /* Pin Interrupt 0 Mask Set Register */
+#define                 PINT0_MASK_CLEAR  0xffc01404   /* Pin Interrupt 0 Mask Clear Register */
+#define                    PINT0_REQUEST  0xffc01408   /* Pin Interrupt 0 Interrupt Request Register */
+#define                     PINT0_ASSIGN  0xffc0140c   /* Pin Interrupt 0 Port Assign Register */
+#define                   PINT0_EDGE_SET  0xffc01410   /* Pin Interrupt 0 Edge-sensitivity Set Register */
+#define                 PINT0_EDGE_CLEAR  0xffc01414   /* Pin Interrupt 0 Edge-sensitivity Clear Register */
+#define                 PINT0_INVERT_SET  0xffc01418   /* Pin Interrupt 0 Inversion Set Register */
+#define               PINT0_INVERT_CLEAR  0xffc0141c   /* Pin Interrupt 0 Inversion Clear Register */
+#define                   PINT0_PINSTATE  0xffc01420   /* Pin Interrupt 0 Pin Status Register */
+#define                      PINT0_LATCH  0xffc01424   /* Pin Interrupt 0 Latch Register */
+
+/* Port Interrupt 1 Registers (32-bit) */
+
+#define                   PINT1_MASK_SET  0xffc01430   /* Pin Interrupt 1 Mask Set Register */
+#define                 PINT1_MASK_CLEAR  0xffc01434   /* Pin Interrupt 1 Mask Clear Register */
+#define                    PINT1_REQUEST  0xffc01438   /* Pin Interrupt 1 Interrupt Request Register */
+#define                     PINT1_ASSIGN  0xffc0143c   /* Pin Interrupt 1 Port Assign Register */
+#define                   PINT1_EDGE_SET  0xffc01440   /* Pin Interrupt 1 Edge-sensitivity Set Register */
+#define                 PINT1_EDGE_CLEAR  0xffc01444   /* Pin Interrupt 1 Edge-sensitivity Clear Register */
+#define                 PINT1_INVERT_SET  0xffc01448   /* Pin Interrupt 1 Inversion Set Register */
+#define               PINT1_INVERT_CLEAR  0xffc0144c   /* Pin Interrupt 1 Inversion Clear Register */
+#define                   PINT1_PINSTATE  0xffc01450   /* Pin Interrupt 1 Pin Status Register */
+#define                      PINT1_LATCH  0xffc01454   /* Pin Interrupt 1 Latch Register */
+
+/* Port Interrupt 2 Registers (32-bit) */
+
+#define                   PINT2_MASK_SET  0xffc01460   /* Pin Interrupt 2 Mask Set Register */
+#define                 PINT2_MASK_CLEAR  0xffc01464   /* Pin Interrupt 2 Mask Clear Register */
+#define                    PINT2_REQUEST  0xffc01468   /* Pin Interrupt 2 Interrupt Request Register */
+#define                     PINT2_ASSIGN  0xffc0146c   /* Pin Interrupt 2 Port Assign Register */
+#define                   PINT2_EDGE_SET  0xffc01470   /* Pin Interrupt 2 Edge-sensitivity Set Register */
+#define                 PINT2_EDGE_CLEAR  0xffc01474   /* Pin Interrupt 2 Edge-sensitivity Clear Register */
+#define                 PINT2_INVERT_SET  0xffc01478   /* Pin Interrupt 2 Inversion Set Register */
+#define               PINT2_INVERT_CLEAR  0xffc0147c   /* Pin Interrupt 2 Inversion Clear Register */
+#define                   PINT2_PINSTATE  0xffc01480   /* Pin Interrupt 2 Pin Status Register */
+#define                      PINT2_LATCH  0xffc01484   /* Pin Interrupt 2 Latch Register */
+
+/* Port Interrupt 3 Registers (32-bit) */
+
+#define                   PINT3_MASK_SET  0xffc01490   /* Pin Interrupt 3 Mask Set Register */
+#define                 PINT3_MASK_CLEAR  0xffc01494   /* Pin Interrupt 3 Mask Clear Register */
+#define                    PINT3_REQUEST  0xffc01498   /* Pin Interrupt 3 Interrupt Request Register */
+#define                     PINT3_ASSIGN  0xffc0149c   /* Pin Interrupt 3 Port Assign Register */
+#define                   PINT3_EDGE_SET  0xffc014a0   /* Pin Interrupt 3 Edge-sensitivity Set Register */
+#define                 PINT3_EDGE_CLEAR  0xffc014a4   /* Pin Interrupt 3 Edge-sensitivity Clear Register */
+#define                 PINT3_INVERT_SET  0xffc014a8   /* Pin Interrupt 3 Inversion Set Register */
+#define               PINT3_INVERT_CLEAR  0xffc014ac   /* Pin Interrupt 3 Inversion Clear Register */
+#define                   PINT3_PINSTATE  0xffc014b0   /* Pin Interrupt 3 Pin Status Register */
+#define                      PINT3_LATCH  0xffc014b4   /* Pin Interrupt 3 Latch Register */
+
+/* Port A Registers */
+
+#define                        PORTA_FER  0xffc014c0   /* Function Enable Register */
+#define                            PORTA  0xffc014c4   /* GPIO Data Register */
+#define                        PORTA_SET  0xffc014c8   /* GPIO Data Set Register */
+#define                      PORTA_CLEAR  0xffc014cc   /* GPIO Data Clear Register */
+#define                    PORTA_DIR_SET  0xffc014d0   /* GPIO Direction Set Register */
+#define                  PORTA_DIR_CLEAR  0xffc014d4   /* GPIO Direction Clear Register */
+#define                       PORTA_INEN  0xffc014d8   /* GPIO Input Enable Register */
+#define                        PORTA_MUX  0xffc014dc   /* Multiplexer Control Register */
+
+/* Port B Registers */
+
+#define                        PORTB_FER  0xffc014e0   /* Function Enable Register */
+#define                            PORTB  0xffc014e4   /* GPIO Data Register */
+#define                        PORTB_SET  0xffc014e8   /* GPIO Data Set Register */
+#define                      PORTB_CLEAR  0xffc014ec   /* GPIO Data Clear Register */
+#define                    PORTB_DIR_SET  0xffc014f0   /* GPIO Direction Set Register */
+#define                  PORTB_DIR_CLEAR  0xffc014f4   /* GPIO Direction Clear Register */
+#define                       PORTB_INEN  0xffc014f8   /* GPIO Input Enable Register */
+#define                        PORTB_MUX  0xffc014fc   /* Multiplexer Control Register */
+
+/* Port C Registers */
+
+#define                        PORTC_FER  0xffc01500   /* Function Enable Register */
+#define                            PORTC  0xffc01504   /* GPIO Data Register */
+#define                        PORTC_SET  0xffc01508   /* GPIO Data Set Register */
+#define                      PORTC_CLEAR  0xffc0150c   /* GPIO Data Clear Register */
+#define                    PORTC_DIR_SET  0xffc01510   /* GPIO Direction Set Register */
+#define                  PORTC_DIR_CLEAR  0xffc01514   /* GPIO Direction Clear Register */
+#define                       PORTC_INEN  0xffc01518   /* GPIO Input Enable Register */
+#define                        PORTC_MUX  0xffc0151c   /* Multiplexer Control Register */
+
+/* Port D Registers */
+
+#define                        PORTD_FER  0xffc01520   /* Function Enable Register */
+#define                            PORTD  0xffc01524   /* GPIO Data Register */
+#define                        PORTD_SET  0xffc01528   /* GPIO Data Set Register */
+#define                      PORTD_CLEAR  0xffc0152c   /* GPIO Data Clear Register */
+#define                    PORTD_DIR_SET  0xffc01530   /* GPIO Direction Set Register */
+#define                  PORTD_DIR_CLEAR  0xffc01534   /* GPIO Direction Clear Register */
+#define                       PORTD_INEN  0xffc01538   /* GPIO Input Enable Register */
+#define                        PORTD_MUX  0xffc0153c   /* Multiplexer Control Register */
+
+/* Port E Registers */
+
+#define                        PORTE_FER  0xffc01540   /* Function Enable Register */
+#define                            PORTE  0xffc01544   /* GPIO Data Register */
+#define                        PORTE_SET  0xffc01548   /* GPIO Data Set Register */
+#define                      PORTE_CLEAR  0xffc0154c   /* GPIO Data Clear Register */
+#define                    PORTE_DIR_SET  0xffc01550   /* GPIO Direction Set Register */
+#define                  PORTE_DIR_CLEAR  0xffc01554   /* GPIO Direction Clear Register */
+#define                       PORTE_INEN  0xffc01558   /* GPIO Input Enable Register */
+#define                        PORTE_MUX  0xffc0155c   /* Multiplexer Control Register */
+
+/* Port F Registers */
+
+#define                        PORTF_FER  0xffc01560   /* Function Enable Register */
+#define                            PORTF  0xffc01564   /* GPIO Data Register */
+#define                        PORTF_SET  0xffc01568   /* GPIO Data Set Register */
+#define                      PORTF_CLEAR  0xffc0156c   /* GPIO Data Clear Register */
+#define                    PORTF_DIR_SET  0xffc01570   /* GPIO Direction Set Register */
+#define                  PORTF_DIR_CLEAR  0xffc01574   /* GPIO Direction Clear Register */
+#define                       PORTF_INEN  0xffc01578   /* GPIO Input Enable Register */
+#define                        PORTF_MUX  0xffc0157c   /* Multiplexer Control Register */
+
+/* Port G Registers */
+
+#define                        PORTG_FER  0xffc01580   /* Function Enable Register */
+#define                            PORTG  0xffc01584   /* GPIO Data Register */
+#define                        PORTG_SET  0xffc01588   /* GPIO Data Set Register */
+#define                      PORTG_CLEAR  0xffc0158c   /* GPIO Data Clear Register */
+#define                    PORTG_DIR_SET  0xffc01590   /* GPIO Direction Set Register */
+#define                  PORTG_DIR_CLEAR  0xffc01594   /* GPIO Direction Clear Register */
+#define                       PORTG_INEN  0xffc01598   /* GPIO Input Enable Register */
+#define                        PORTG_MUX  0xffc0159c   /* Multiplexer Control Register */
+
+/* Port H Registers */
+
+#define                        PORTH_FER  0xffc015a0   /* Function Enable Register */
+#define                            PORTH  0xffc015a4   /* GPIO Data Register */
+#define                        PORTH_SET  0xffc015a8   /* GPIO Data Set Register */
+#define                      PORTH_CLEAR  0xffc015ac   /* GPIO Data Clear Register */
+#define                    PORTH_DIR_SET  0xffc015b0   /* GPIO Direction Set Register */
+#define                  PORTH_DIR_CLEAR  0xffc015b4   /* GPIO Direction Clear Register */
+#define                       PORTH_INEN  0xffc015b8   /* GPIO Input Enable Register */
+#define                        PORTH_MUX  0xffc015bc   /* Multiplexer Control Register */
+
+/* Port I Registers */
+
+#define                        PORTI_FER  0xffc015c0   /* Function Enable Register */
+#define                            PORTI  0xffc015c4   /* GPIO Data Register */
+#define                        PORTI_SET  0xffc015c8   /* GPIO Data Set Register */
+#define                      PORTI_CLEAR  0xffc015cc   /* GPIO Data Clear Register */
+#define                    PORTI_DIR_SET  0xffc015d0   /* GPIO Direction Set Register */
+#define                  PORTI_DIR_CLEAR  0xffc015d4   /* GPIO Direction Clear Register */
+#define                       PORTI_INEN  0xffc015d8   /* GPIO Input Enable Register */
+#define                        PORTI_MUX  0xffc015dc   /* Multiplexer Control Register */
+
+/* Port J Registers */
+
+#define                        PORTJ_FER  0xffc015e0   /* Function Enable Register */
+#define                            PORTJ  0xffc015e4   /* GPIO Data Register */
+#define                        PORTJ_SET  0xffc015e8   /* GPIO Data Set Register */
+#define                      PORTJ_CLEAR  0xffc015ec   /* GPIO Data Clear Register */
+#define                    PORTJ_DIR_SET  0xffc015f0   /* GPIO Direction Set Register */
+#define                  PORTJ_DIR_CLEAR  0xffc015f4   /* GPIO Direction Clear Register */
+#define                       PORTJ_INEN  0xffc015f8   /* GPIO Input Enable Register */
+#define                        PORTJ_MUX  0xffc015fc   /* Multiplexer Control Register */
+
+/* PWM Timer Registers */
+
+#define                    TIMER0_CONFIG  0xffc01600   /* Timer 0 Configuration Register */
+#define                   TIMER0_COUNTER  0xffc01604   /* Timer 0 Counter Register */
+#define                    TIMER0_PERIOD  0xffc01608   /* Timer 0 Period Register */
+#define                     TIMER0_WIDTH  0xffc0160c   /* Timer 0 Width Register */
+#define                    TIMER1_CONFIG  0xffc01610   /* Timer 1 Configuration Register */
+#define                   TIMER1_COUNTER  0xffc01614   /* Timer 1 Counter Register */
+#define                    TIMER1_PERIOD  0xffc01618   /* Timer 1 Period Register */
+#define                     TIMER1_WIDTH  0xffc0161c   /* Timer 1 Width Register */
+#define                    TIMER2_CONFIG  0xffc01620   /* Timer 2 Configuration Register */
+#define                   TIMER2_COUNTER  0xffc01624   /* Timer 2 Counter Register */
+#define                    TIMER2_PERIOD  0xffc01628   /* Timer 2 Period Register */
+#define                     TIMER2_WIDTH  0xffc0162c   /* Timer 2 Width Register */
+#define                    TIMER3_CONFIG  0xffc01630   /* Timer 3 Configuration Register */
+#define                   TIMER3_COUNTER  0xffc01634   /* Timer 3 Counter Register */
+#define                    TIMER3_PERIOD  0xffc01638   /* Timer 3 Period Register */
+#define                     TIMER3_WIDTH  0xffc0163c   /* Timer 3 Width Register */
+#define                    TIMER4_CONFIG  0xffc01640   /* Timer 4 Configuration Register */
+#define                   TIMER4_COUNTER  0xffc01644   /* Timer 4 Counter Register */
+#define                    TIMER4_PERIOD  0xffc01648   /* Timer 4 Period Register */
+#define                     TIMER4_WIDTH  0xffc0164c   /* Timer 4 Width Register */
+#define                    TIMER5_CONFIG  0xffc01650   /* Timer 5 Configuration Register */
+#define                   TIMER5_COUNTER  0xffc01654   /* Timer 5 Counter Register */
+#define                    TIMER5_PERIOD  0xffc01658   /* Timer 5 Period Register */
+#define                     TIMER5_WIDTH  0xffc0165c   /* Timer 5 Width Register */
+#define                    TIMER6_CONFIG  0xffc01660   /* Timer 6 Configuration Register */
+#define                   TIMER6_COUNTER  0xffc01664   /* Timer 6 Counter Register */
+#define                    TIMER6_PERIOD  0xffc01668   /* Timer 6 Period Register */
+#define                     TIMER6_WIDTH  0xffc0166c   /* Timer 6 Width Register */
+#define                    TIMER7_CONFIG  0xffc01670   /* Timer 7 Configuration Register */
+#define                   TIMER7_COUNTER  0xffc01674   /* Timer 7 Counter Register */
+#define                    TIMER7_PERIOD  0xffc01678   /* Timer 7 Period Register */
+#define                     TIMER7_WIDTH  0xffc0167c   /* Timer 7 Width Register */
+
+/* Timer Group of 8 */
+
+#define                    TIMER_ENABLE0  0xffc01680   /* Timer Group of 8 Enable Register */
+#define                   TIMER_DISABLE0  0xffc01684   /* Timer Group of 8 Disable Register */
+#define                    TIMER_STATUS0  0xffc01688   /* Timer Group of 8 Status Register */
+
+/* DMAC1 Registers */
+
+#define                      DMAC1_TCPER  0xffc01b0c   /* DMA Controller 1 Traffic Control Periods Register */
+#define                      DMAC1_TCCNT  0xffc01b10   /* DMA Controller 1 Current Counts Register */
+
+/* DMA Channel 12 Registers */
+
+#define              DMA12_NEXT_DESC_PTR  0xffc01c00   /* DMA Channel 12 Next Descriptor Pointer Register */
+#define                 DMA12_START_ADDR  0xffc01c04   /* DMA Channel 12 Start Address Register */
+#define                     DMA12_CONFIG  0xffc01c08   /* DMA Channel 12 Configuration Register */
+#define                    DMA12_X_COUNT  0xffc01c10   /* DMA Channel 12 X Count Register */
+#define                   DMA12_X_MODIFY  0xffc01c14   /* DMA Channel 12 X Modify Register */
+#define                    DMA12_Y_COUNT  0xffc01c18   /* DMA Channel 12 Y Count Register */
+#define                   DMA12_Y_MODIFY  0xffc01c1c   /* DMA Channel 12 Y Modify Register */
+#define              DMA12_CURR_DESC_PTR  0xffc01c20   /* DMA Channel 12 Current Descriptor Pointer Register */
+#define                  DMA12_CURR_ADDR  0xffc01c24   /* DMA Channel 12 Current Address Register */
+#define                 DMA12_IRQ_STATUS  0xffc01c28   /* DMA Channel 12 Interrupt/Status Register */
+#define             DMA12_PERIPHERAL_MAP  0xffc01c2c   /* DMA Channel 12 Peripheral Map Register */
+#define               DMA12_CURR_X_COUNT  0xffc01c30   /* DMA Channel 12 Current X Count Register */
+#define               DMA12_CURR_Y_COUNT  0xffc01c38   /* DMA Channel 12 Current Y Count Register */
+
+/* DMA Channel 13 Registers */
+
+#define              DMA13_NEXT_DESC_PTR  0xffc01c40   /* DMA Channel 13 Next Descriptor Pointer Register */
+#define                 DMA13_START_ADDR  0xffc01c44   /* DMA Channel 13 Start Address Register */
+#define                     DMA13_CONFIG  0xffc01c48   /* DMA Channel 13 Configuration Register */
+#define                    DMA13_X_COUNT  0xffc01c50   /* DMA Channel 13 X Count Register */
+#define                   DMA13_X_MODIFY  0xffc01c54   /* DMA Channel 13 X Modify Register */
+#define                    DMA13_Y_COUNT  0xffc01c58   /* DMA Channel 13 Y Count Register */
+#define                   DMA13_Y_MODIFY  0xffc01c5c   /* DMA Channel 13 Y Modify Register */
+#define              DMA13_CURR_DESC_PTR  0xffc01c60   /* DMA Channel 13 Current Descriptor Pointer Register */
+#define                  DMA13_CURR_ADDR  0xffc01c64   /* DMA Channel 13 Current Address Register */
+#define                 DMA13_IRQ_STATUS  0xffc01c68   /* DMA Channel 13 Interrupt/Status Register */
+#define             DMA13_PERIPHERAL_MAP  0xffc01c6c   /* DMA Channel 13 Peripheral Map Register */
+#define               DMA13_CURR_X_COUNT  0xffc01c70   /* DMA Channel 13 Current X Count Register */
+#define               DMA13_CURR_Y_COUNT  0xffc01c78   /* DMA Channel 13 Current Y Count Register */
+
+/* DMA Channel 14 Registers */
+
+#define              DMA14_NEXT_DESC_PTR  0xffc01c80   /* DMA Channel 14 Next Descriptor Pointer Register */
+#define                 DMA14_START_ADDR  0xffc01c84   /* DMA Channel 14 Start Address Register */
+#define                     DMA14_CONFIG  0xffc01c88   /* DMA Channel 14 Configuration Register */
+#define                    DMA14_X_COUNT  0xffc01c90   /* DMA Channel 14 X Count Register */
+#define                   DMA14_X_MODIFY  0xffc01c94   /* DMA Channel 14 X Modify Register */
+#define                    DMA14_Y_COUNT  0xffc01c98   /* DMA Channel 14 Y Count Register */
+#define                   DMA14_Y_MODIFY  0xffc01c9c   /* DMA Channel 14 Y Modify Register */
+#define              DMA14_CURR_DESC_PTR  0xffc01ca0   /* DMA Channel 14 Current Descriptor Pointer Register */
+#define                  DMA14_CURR_ADDR  0xffc01ca4   /* DMA Channel 14 Current Address Register */
+#define                 DMA14_IRQ_STATUS  0xffc01ca8   /* DMA Channel 14 Interrupt/Status Register */
+#define             DMA14_PERIPHERAL_MAP  0xffc01cac   /* DMA Channel 14 Peripheral Map Register */
+#define               DMA14_CURR_X_COUNT  0xffc01cb0   /* DMA Channel 14 Current X Count Register */
+#define               DMA14_CURR_Y_COUNT  0xffc01cb8   /* DMA Channel 14 Current Y Count Register */
+
+/* DMA Channel 15 Registers */
+
+#define              DMA15_NEXT_DESC_PTR  0xffc01cc0   /* DMA Channel 15 Next Descriptor Pointer Register */
+#define                 DMA15_START_ADDR  0xffc01cc4   /* DMA Channel 15 Start Address Register */
+#define                     DMA15_CONFIG  0xffc01cc8   /* DMA Channel 15 Configuration Register */
+#define                    DMA15_X_COUNT  0xffc01cd0   /* DMA Channel 15 X Count Register */
+#define                   DMA15_X_MODIFY  0xffc01cd4   /* DMA Channel 15 X Modify Register */
+#define                    DMA15_Y_COUNT  0xffc01cd8   /* DMA Channel 15 Y Count Register */
+#define                   DMA15_Y_MODIFY  0xffc01cdc   /* DMA Channel 15 Y Modify Register */
+#define              DMA15_CURR_DESC_PTR  0xffc01ce0   /* DMA Channel 15 Current Descriptor Pointer Register */
+#define                  DMA15_CURR_ADDR  0xffc01ce4   /* DMA Channel 15 Current Address Register */
+#define                 DMA15_IRQ_STATUS  0xffc01ce8   /* DMA Channel 15 Interrupt/Status Register */
+#define             DMA15_PERIPHERAL_MAP  0xffc01cec   /* DMA Channel 15 Peripheral Map Register */
+#define               DMA15_CURR_X_COUNT  0xffc01cf0   /* DMA Channel 15 Current X Count Register */
+#define               DMA15_CURR_Y_COUNT  0xffc01cf8   /* DMA Channel 15 Current Y Count Register */
+
+/* DMA Channel 16 Registers */
+
+#define              DMA16_NEXT_DESC_PTR  0xffc01d00   /* DMA Channel 16 Next Descriptor Pointer Register */
+#define                 DMA16_START_ADDR  0xffc01d04   /* DMA Channel 16 Start Address Register */
+#define                     DMA16_CONFIG  0xffc01d08   /* DMA Channel 16 Configuration Register */
+#define                    DMA16_X_COUNT  0xffc01d10   /* DMA Channel 16 X Count Register */
+#define                   DMA16_X_MODIFY  0xffc01d14   /* DMA Channel 16 X Modify Register */
+#define                    DMA16_Y_COUNT  0xffc01d18   /* DMA Channel 16 Y Count Register */
+#define                   DMA16_Y_MODIFY  0xffc01d1c   /* DMA Channel 16 Y Modify Register */
+#define              DMA16_CURR_DESC_PTR  0xffc01d20   /* DMA Channel 16 Current Descriptor Pointer Register */
+#define                  DMA16_CURR_ADDR  0xffc01d24   /* DMA Channel 16 Current Address Register */
+#define                 DMA16_IRQ_STATUS  0xffc01d28   /* DMA Channel 16 Interrupt/Status Register */
+#define             DMA16_PERIPHERAL_MAP  0xffc01d2c   /* DMA Channel 16 Peripheral Map Register */
+#define               DMA16_CURR_X_COUNT  0xffc01d30   /* DMA Channel 16 Current X Count Register */
+#define               DMA16_CURR_Y_COUNT  0xffc01d38   /* DMA Channel 16 Current Y Count Register */
+
+/* DMA Channel 17 Registers */
+
+#define              DMA17_NEXT_DESC_PTR  0xffc01d40   /* DMA Channel 17 Next Descriptor Pointer Register */
+#define                 DMA17_START_ADDR  0xffc01d44   /* DMA Channel 17 Start Address Register */
+#define                     DMA17_CONFIG  0xffc01d48   /* DMA Channel 17 Configuration Register */
+#define                    DMA17_X_COUNT  0xffc01d50   /* DMA Channel 17 X Count Register */
+#define                   DMA17_X_MODIFY  0xffc01d54   /* DMA Channel 17 X Modify Register */
+#define                    DMA17_Y_COUNT  0xffc01d58   /* DMA Channel 17 Y Count Register */
+#define                   DMA17_Y_MODIFY  0xffc01d5c   /* DMA Channel 17 Y Modify Register */
+#define              DMA17_CURR_DESC_PTR  0xffc01d60   /* DMA Channel 17 Current Descriptor Pointer Register */
+#define                  DMA17_CURR_ADDR  0xffc01d64   /* DMA Channel 17 Current Address Register */
+#define                 DMA17_IRQ_STATUS  0xffc01d68   /* DMA Channel 17 Interrupt/Status Register */
+#define             DMA17_PERIPHERAL_MAP  0xffc01d6c   /* DMA Channel 17 Peripheral Map Register */
+#define               DMA17_CURR_X_COUNT  0xffc01d70   /* DMA Channel 17 Current X Count Register */
+#define               DMA17_CURR_Y_COUNT  0xffc01d78   /* DMA Channel 17 Current Y Count Register */
+
+/* DMA Channel 18 Registers */
+
+#define              DMA18_NEXT_DESC_PTR  0xffc01d80   /* DMA Channel 18 Next Descriptor Pointer Register */
+#define                 DMA18_START_ADDR  0xffc01d84   /* DMA Channel 18 Start Address Register */
+#define                     DMA18_CONFIG  0xffc01d88   /* DMA Channel 18 Configuration Register */
+#define                    DMA18_X_COUNT  0xffc01d90   /* DMA Channel 18 X Count Register */
+#define                   DMA18_X_MODIFY  0xffc01d94   /* DMA Channel 18 X Modify Register */
+#define                    DMA18_Y_COUNT  0xffc01d98   /* DMA Channel 18 Y Count Register */
+#define                   DMA18_Y_MODIFY  0xffc01d9c   /* DMA Channel 18 Y Modify Register */
+#define              DMA18_CURR_DESC_PTR  0xffc01da0   /* DMA Channel 18 Current Descriptor Pointer Register */
+#define                  DMA18_CURR_ADDR  0xffc01da4   /* DMA Channel 18 Current Address Register */
+#define                 DMA18_IRQ_STATUS  0xffc01da8   /* DMA Channel 18 Interrupt/Status Register */
+#define             DMA18_PERIPHERAL_MAP  0xffc01dac   /* DMA Channel 18 Peripheral Map Register */
+#define               DMA18_CURR_X_COUNT  0xffc01db0   /* DMA Channel 18 Current X Count Register */
+#define               DMA18_CURR_Y_COUNT  0xffc01db8   /* DMA Channel 18 Current Y Count Register */
+
+/* DMA Channel 19 Registers */
+
+#define              DMA19_NEXT_DESC_PTR  0xffc01dc0   /* DMA Channel 19 Next Descriptor Pointer Register */
+#define                 DMA19_START_ADDR  0xffc01dc4   /* DMA Channel 19 Start Address Register */
+#define                     DMA19_CONFIG  0xffc01dc8   /* DMA Channel 19 Configuration Register */
+#define                    DMA19_X_COUNT  0xffc01dd0   /* DMA Channel 19 X Count Register */
+#define                   DMA19_X_MODIFY  0xffc01dd4   /* DMA Channel 19 X Modify Register */
+#define                    DMA19_Y_COUNT  0xffc01dd8   /* DMA Channel 19 Y Count Register */
+#define                   DMA19_Y_MODIFY  0xffc01ddc   /* DMA Channel 19 Y Modify Register */
+#define              DMA19_CURR_DESC_PTR  0xffc01de0   /* DMA Channel 19 Current Descriptor Pointer Register */
+#define                  DMA19_CURR_ADDR  0xffc01de4   /* DMA Channel 19 Current Address Register */
+#define                 DMA19_IRQ_STATUS  0xffc01de8   /* DMA Channel 19 Interrupt/Status Register */
+#define             DMA19_PERIPHERAL_MAP  0xffc01dec   /* DMA Channel 19 Peripheral Map Register */
+#define               DMA19_CURR_X_COUNT  0xffc01df0   /* DMA Channel 19 Current X Count Register */
+#define               DMA19_CURR_Y_COUNT  0xffc01df8   /* DMA Channel 19 Current Y Count Register */
+
+/* DMA Channel 20 Registers */
+
+#define              DMA20_NEXT_DESC_PTR  0xffc01e00   /* DMA Channel 20 Next Descriptor Pointer Register */
+#define                 DMA20_START_ADDR  0xffc01e04   /* DMA Channel 20 Start Address Register */
+#define                     DMA20_CONFIG  0xffc01e08   /* DMA Channel 20 Configuration Register */
+#define                    DMA20_X_COUNT  0xffc01e10   /* DMA Channel 20 X Count Register */
+#define                   DMA20_X_MODIFY  0xffc01e14   /* DMA Channel 20 X Modify Register */
+#define                    DMA20_Y_COUNT  0xffc01e18   /* DMA Channel 20 Y Count Register */
+#define                   DMA20_Y_MODIFY  0xffc01e1c   /* DMA Channel 20 Y Modify Register */
+#define              DMA20_CURR_DESC_PTR  0xffc01e20   /* DMA Channel 20 Current Descriptor Pointer Register */
+#define                  DMA20_CURR_ADDR  0xffc01e24   /* DMA Channel 20 Current Address Register */
+#define                 DMA20_IRQ_STATUS  0xffc01e28   /* DMA Channel 20 Interrupt/Status Register */
+#define             DMA20_PERIPHERAL_MAP  0xffc01e2c   /* DMA Channel 20 Peripheral Map Register */
+#define               DMA20_CURR_X_COUNT  0xffc01e30   /* DMA Channel 20 Current X Count Register */
+#define               DMA20_CURR_Y_COUNT  0xffc01e38   /* DMA Channel 20 Current Y Count Register */
+
+/* DMA Channel 21 Registers */
+
+#define              DMA21_NEXT_DESC_PTR  0xffc01e40   /* DMA Channel 21 Next Descriptor Pointer Register */
+#define                 DMA21_START_ADDR  0xffc01e44   /* DMA Channel 21 Start Address Register */
+#define                     DMA21_CONFIG  0xffc01e48   /* DMA Channel 21 Configuration Register */
+#define                    DMA21_X_COUNT  0xffc01e50   /* DMA Channel 21 X Count Register */
+#define                   DMA21_X_MODIFY  0xffc01e54   /* DMA Channel 21 X Modify Register */
+#define                    DMA21_Y_COUNT  0xffc01e58   /* DMA Channel 21 Y Count Register */
+#define                   DMA21_Y_MODIFY  0xffc01e5c   /* DMA Channel 21 Y Modify Register */
+#define              DMA21_CURR_DESC_PTR  0xffc01e60   /* DMA Channel 21 Current Descriptor Pointer Register */
+#define                  DMA21_CURR_ADDR  0xffc01e64   /* DMA Channel 21 Current Address Register */
+#define                 DMA21_IRQ_STATUS  0xffc01e68   /* DMA Channel 21 Interrupt/Status Register */
+#define             DMA21_PERIPHERAL_MAP  0xffc01e6c   /* DMA Channel 21 Peripheral Map Register */
+#define               DMA21_CURR_X_COUNT  0xffc01e70   /* DMA Channel 21 Current X Count Register */
+#define               DMA21_CURR_Y_COUNT  0xffc01e78   /* DMA Channel 21 Current Y Count Register */
+
+/* DMA Channel 22 Registers */
+
+#define              DMA22_NEXT_DESC_PTR  0xffc01e80   /* DMA Channel 22 Next Descriptor Pointer Register */
+#define                 DMA22_START_ADDR  0xffc01e84   /* DMA Channel 22 Start Address Register */
+#define                     DMA22_CONFIG  0xffc01e88   /* DMA Channel 22 Configuration Register */
+#define                    DMA22_X_COUNT  0xffc01e90   /* DMA Channel 22 X Count Register */
+#define                   DMA22_X_MODIFY  0xffc01e94   /* DMA Channel 22 X Modify Register */
+#define                    DMA22_Y_COUNT  0xffc01e98   /* DMA Channel 22 Y Count Register */
+#define                   DMA22_Y_MODIFY  0xffc01e9c   /* DMA Channel 22 Y Modify Register */
+#define              DMA22_CURR_DESC_PTR  0xffc01ea0   /* DMA Channel 22 Current Descriptor Pointer Register */
+#define                  DMA22_CURR_ADDR  0xffc01ea4   /* DMA Channel 22 Current Address Register */
+#define                 DMA22_IRQ_STATUS  0xffc01ea8   /* DMA Channel 22 Interrupt/Status Register */
+#define             DMA22_PERIPHERAL_MAP  0xffc01eac   /* DMA Channel 22 Peripheral Map Register */
+#define               DMA22_CURR_X_COUNT  0xffc01eb0   /* DMA Channel 22 Current X Count Register */
+#define               DMA22_CURR_Y_COUNT  0xffc01eb8   /* DMA Channel 22 Current Y Count Register */
+
+/* DMA Channel 23 Registers */
+
+#define              DMA23_NEXT_DESC_PTR  0xffc01ec0   /* DMA Channel 23 Next Descriptor Pointer Register */
+#define                 DMA23_START_ADDR  0xffc01ec4   /* DMA Channel 23 Start Address Register */
+#define                     DMA23_CONFIG  0xffc01ec8   /* DMA Channel 23 Configuration Register */
+#define                    DMA23_X_COUNT  0xffc01ed0   /* DMA Channel 23 X Count Register */
+#define                   DMA23_X_MODIFY  0xffc01ed4   /* DMA Channel 23 X Modify Register */
+#define                    DMA23_Y_COUNT  0xffc01ed8   /* DMA Channel 23 Y Count Register */
+#define                   DMA23_Y_MODIFY  0xffc01edc   /* DMA Channel 23 Y Modify Register */
+#define              DMA23_CURR_DESC_PTR  0xffc01ee0   /* DMA Channel 23 Current Descriptor Pointer Register */
+#define                  DMA23_CURR_ADDR  0xffc01ee4   /* DMA Channel 23 Current Address Register */
+#define                 DMA23_IRQ_STATUS  0xffc01ee8   /* DMA Channel 23 Interrupt/Status Register */
+#define             DMA23_PERIPHERAL_MAP  0xffc01eec   /* DMA Channel 23 Peripheral Map Register */
+#define               DMA23_CURR_X_COUNT  0xffc01ef0   /* DMA Channel 23 Current X Count Register */
+#define               DMA23_CURR_Y_COUNT  0xffc01ef8   /* DMA Channel 23 Current Y Count Register */
+
+/* MDMA Stream 2 Registers */
+
+#define            MDMA_D2_NEXT_DESC_PTR  0xffc01f00   /* Memory DMA Stream 2 Destination Next Descriptor Pointer Register */
+#define               MDMA_D2_START_ADDR  0xffc01f04   /* Memory DMA Stream 2 Destination Start Address Register */
+#define                   MDMA_D2_CONFIG  0xffc01f08   /* Memory DMA Stream 2 Destination Configuration Register */
+#define                  MDMA_D2_X_COUNT  0xffc01f10   /* Memory DMA Stream 2 Destination X Count Register */
+#define                 MDMA_D2_X_MODIFY  0xffc01f14   /* Memory DMA Stream 2 Destination X Modify Register */
+#define                  MDMA_D2_Y_COUNT  0xffc01f18   /* Memory DMA Stream 2 Destination Y Count Register */
+#define                 MDMA_D2_Y_MODIFY  0xffc01f1c   /* Memory DMA Stream 2 Destination Y Modify Register */
+#define            MDMA_D2_CURR_DESC_PTR  0xffc01f20   /* Memory DMA Stream 2 Destination Current Descriptor Pointer Register */
+#define                MDMA_D2_CURR_ADDR  0xffc01f24   /* Memory DMA Stream 2 Destination Current Address Register */
+#define               MDMA_D2_IRQ_STATUS  0xffc01f28   /* Memory DMA Stream 2 Destination Interrupt/Status Register */
+#define           MDMA_D2_PERIPHERAL_MAP  0xffc01f2c   /* Memory DMA Stream 2 Destination Peripheral Map Register */
+#define             MDMA_D2_CURR_X_COUNT  0xffc01f30   /* Memory DMA Stream 2 Destination Current X Count Register */
+#define             MDMA_D2_CURR_Y_COUNT  0xffc01f38   /* Memory DMA Stream 2 Destination Current Y Count Register */
+#define            MDMA_S2_NEXT_DESC_PTR  0xffc01f40   /* Memory DMA Stream 2 Source Next Descriptor Pointer Register */
+#define               MDMA_S2_START_ADDR  0xffc01f44   /* Memory DMA Stream 2 Source Start Address Register */
+#define                   MDMA_S2_CONFIG  0xffc01f48   /* Memory DMA Stream 2 Source Configuration Register */
+#define                  MDMA_S2_X_COUNT  0xffc01f50   /* Memory DMA Stream 2 Source X Count Register */
+#define                 MDMA_S2_X_MODIFY  0xffc01f54   /* Memory DMA Stream 2 Source X Modify Register */
+#define                  MDMA_S2_Y_COUNT  0xffc01f58   /* Memory DMA Stream 2 Source Y Count Register */
+#define                 MDMA_S2_Y_MODIFY  0xffc01f5c   /* Memory DMA Stream 2 Source Y Modify Register */
+#define            MDMA_S2_CURR_DESC_PTR  0xffc01f60   /* Memory DMA Stream 2 Source Current Descriptor Pointer Register */
+#define                MDMA_S2_CURR_ADDR  0xffc01f64   /* Memory DMA Stream 2 Source Current Address Register */
+#define               MDMA_S2_IRQ_STATUS  0xffc01f68   /* Memory DMA Stream 2 Source Interrupt/Status Register */
+#define           MDMA_S2_PERIPHERAL_MAP  0xffc01f6c   /* Memory DMA Stream 2 Source Peripheral Map Register */
+#define             MDMA_S2_CURR_X_COUNT  0xffc01f70   /* Memory DMA Stream 2 Source Current X Count Register */
+#define             MDMA_S2_CURR_Y_COUNT  0xffc01f78   /* Memory DMA Stream 2 Source Current Y Count Register */
+
+/* MDMA Stream 3 Registers */
+
+#define            MDMA_D3_NEXT_DESC_PTR  0xffc01f80   /* Memory DMA Stream 3 Destination Next Descriptor Pointer Register */
+#define               MDMA_D3_START_ADDR  0xffc01f84   /* Memory DMA Stream 3 Destination Start Address Register */
+#define                   MDMA_D3_CONFIG  0xffc01f88   /* Memory DMA Stream 3 Destination Configuration Register */
+#define                  MDMA_D3_X_COUNT  0xffc01f90   /* Memory DMA Stream 3 Destination X Count Register */
+#define                 MDMA_D3_X_MODIFY  0xffc01f94   /* Memory DMA Stream 3 Destination X Modify Register */
+#define                  MDMA_D3_Y_COUNT  0xffc01f98   /* Memory DMA Stream 3 Destination Y Count Register */
+#define                 MDMA_D3_Y_MODIFY  0xffc01f9c   /* Memory DMA Stream 3 Destination Y Modify Register */
+#define            MDMA_D3_CURR_DESC_PTR  0xffc01fa0   /* Memory DMA Stream 3 Destination Current Descriptor Pointer Register */
+#define                MDMA_D3_CURR_ADDR  0xffc01fa4   /* Memory DMA Stream 3 Destination Current Address Register */
+#define               MDMA_D3_IRQ_STATUS  0xffc01fa8   /* Memory DMA Stream 3 Destination Interrupt/Status Register */
+#define           MDMA_D3_PERIPHERAL_MAP  0xffc01fac   /* Memory DMA Stream 3 Destination Peripheral Map Register */
+#define             MDMA_D3_CURR_X_COUNT  0xffc01fb0   /* Memory DMA Stream 3 Destination Current X Count Register */
+#define             MDMA_D3_CURR_Y_COUNT  0xffc01fb8   /* Memory DMA Stream 3 Destination Current Y Count Register */
+#define            MDMA_S3_NEXT_DESC_PTR  0xffc01fc0   /* Memory DMA Stream 3 Source Next Descriptor Pointer Register */
+#define               MDMA_S3_START_ADDR  0xffc01fc4   /* Memory DMA Stream 3 Source Start Address Register */
+#define                   MDMA_S3_CONFIG  0xffc01fc8   /* Memory DMA Stream 3 Source Configuration Register */
+#define                  MDMA_S3_X_COUNT  0xffc01fd0   /* Memory DMA Stream 3 Source X Count Register */
+#define                 MDMA_S3_X_MODIFY  0xffc01fd4   /* Memory DMA Stream 3 Source X Modify Register */
+#define                  MDMA_S3_Y_COUNT  0xffc01fd8   /* Memory DMA Stream 3 Source Y Count Register */
+#define                 MDMA_S3_Y_MODIFY  0xffc01fdc   /* Memory DMA Stream 3 Source Y Modify Register */
+#define            MDMA_S3_CURR_DESC_PTR  0xffc01fe0   /* Memory DMA Stream 3 Source Current Descriptor Pointer Register */
+#define                MDMA_S3_CURR_ADDR  0xffc01fe4   /* Memory DMA Stream 3 Source Current Address Register */
+#define               MDMA_S3_IRQ_STATUS  0xffc01fe8   /* Memory DMA Stream 3 Source Interrupt/Status Register */
+#define           MDMA_S3_PERIPHERAL_MAP  0xffc01fec   /* Memory DMA Stream 3 Source Peripheral Map Register */
+#define             MDMA_S3_CURR_X_COUNT  0xffc01ff0   /* Memory DMA Stream 3 Source Current X Count Register */
+#define             MDMA_S3_CURR_Y_COUNT  0xffc01ff8   /* Memory DMA Stream 3 Source Current Y Count Register */
+
+/* UART1 Registers */
+
+#define                        UART1_DLL  0xffc02000   /* Divisor Latch Low Byte */
+#define                        UART1_DLH  0xffc02004   /* Divisor Latch High Byte */
+#define                       UART1_GCTL  0xffc02008   /* Global Control Register */
+#define                        UART1_LCR  0xffc0200c   /* Line Control Register */
+#define                        UART1_MCR  0xffc02010   /* Modem Control Register */
+#define                        UART1_LSR  0xffc02014   /* Line Status Register */
+#define                        UART1_MSR  0xffc02018   /* Modem Status Register */
+#define                        UART1_SCR  0xffc0201c   /* Scratch Register */
+#define                    UART1_IER_SET  0xffc02020   /* Interrupt Enable Register Set */
+#define                  UART1_IER_CLEAR  0xffc02024   /* Interrupt Enable Register Clear */
+#define                        UART1_THR  0xffc02028   /* Transmit Hold Register */
+#define                        UART1_RBR  0xffc0202c   /* Receive Buffer Register */
+
+/* UART2 is not defined in the shared file because it is not available on the ADSP-BF542 and ADSP-BF544 processors */
+
+/* SPI1 Registers */
+
+#define                         SPI1_CTL  0xffc02300   /* SPI1 Control Register */
+#define                         SPI1_FLG  0xffc02304   /* SPI1 Flag Register */
+#define                        SPI1_STAT  0xffc02308   /* SPI1 Status Register */
+#define                        SPI1_TDBR  0xffc0230c   /* SPI1 Transmit Data Buffer Register */
+#define                        SPI1_RDBR  0xffc02310   /* SPI1 Receive Data Buffer Register */
+#define                        SPI1_BAUD  0xffc02314   /* SPI1 Baud Rate Register */
+#define                      SPI1_SHADOW  0xffc02318   /* SPI1 Receive Data Buffer Shadow Register */
+
+/* SPORT2 Registers */
+
+#define                      SPORT2_TCR1  0xffc02500   /* SPORT2 Transmit Configuration 1 Register */
+#define                      SPORT2_TCR2  0xffc02504   /* SPORT2 Transmit Configuration 2 Register */
+#define                   SPORT2_TCLKDIV  0xffc02508   /* SPORT2 Transmit Serial Clock Divider Register */
+#define                    SPORT2_TFSDIV  0xffc0250c   /* SPORT2 Transmit Frame Sync Divider Register */
+#define                        SPORT2_TX  0xffc02510   /* SPORT2 Transmit Data Register */
+#define                        SPORT2_RX  0xffc02518   /* SPORT2 Receive Data Register */
+#define                      SPORT2_RCR1  0xffc02520   /* SPORT2 Receive Configuration 1 Register */
+#define                      SPORT2_RCR2  0xffc02524   /* SPORT2 Receive Configuration 2 Register */
+#define                   SPORT2_RCLKDIV  0xffc02528   /* SPORT2 Receive Serial Clock Divider Register */
+#define                    SPORT2_RFSDIV  0xffc0252c   /* SPORT2 Receive Frame Sync Divider Register */
+#define                      SPORT2_STAT  0xffc02530   /* SPORT2 Status Register */
+#define                      SPORT2_CHNL  0xffc02534   /* SPORT2 Current Channel Register */
+#define                     SPORT2_MCMC1  0xffc02538   /* SPORT2 Multi channel Configuration Register 1 */
+#define                     SPORT2_MCMC2  0xffc0253c   /* SPORT2 Multi channel Configuration Register 2 */
+#define                     SPORT2_MTCS0  0xffc02540   /* SPORT2 Multi channel Transmit Select Register 0 */
+#define                     SPORT2_MTCS1  0xffc02544   /* SPORT2 Multi channel Transmit Select Register 1 */
+#define                     SPORT2_MTCS2  0xffc02548   /* SPORT2 Multi channel Transmit Select Register 2 */
+#define                     SPORT2_MTCS3  0xffc0254c   /* SPORT2 Multi channel Transmit Select Register 3 */
+#define                     SPORT2_MRCS0  0xffc02550   /* SPORT2 Multi channel Receive Select Register 0 */
+#define                     SPORT2_MRCS1  0xffc02554   /* SPORT2 Multi channel Receive Select Register 1 */
+#define                     SPORT2_MRCS2  0xffc02558   /* SPORT2 Multi channel Receive Select Register 2 */
+#define                     SPORT2_MRCS3  0xffc0255c   /* SPORT2 Multi channel Receive Select Register 3 */
+
+/* SPORT3 Registers */
+
+#define                      SPORT3_TCR1  0xffc02600   /* SPORT3 Transmit Configuration 1 Register */
+#define                      SPORT3_TCR2  0xffc02604   /* SPORT3 Transmit Configuration 2 Register */
+#define                   SPORT3_TCLKDIV  0xffc02608   /* SPORT3 Transmit Serial Clock Divider Register */
+#define                    SPORT3_TFSDIV  0xffc0260c   /* SPORT3 Transmit Frame Sync Divider Register */
+#define                        SPORT3_TX  0xffc02610   /* SPORT3 Transmit Data Register */
+#define                        SPORT3_RX  0xffc02618   /* SPORT3 Receive Data Register */
+#define                      SPORT3_RCR1  0xffc02620   /* SPORT3 Receive Configuration 1 Register */
+#define                      SPORT3_RCR2  0xffc02624   /* SPORT3 Receive Configuration 2 Register */
+#define                   SPORT3_RCLKDIV  0xffc02628   /* SPORT3 Receive Serial Clock Divider Register */
+#define                    SPORT3_RFSDIV  0xffc0262c   /* SPORT3 Receive Frame Sync Divider Register */
+#define                      SPORT3_STAT  0xffc02630   /* SPORT3 Status Register */
+#define                      SPORT3_CHNL  0xffc02634   /* SPORT3 Current Channel Register */
+#define                     SPORT3_MCMC1  0xffc02638   /* SPORT3 Multi channel Configuration Register 1 */
+#define                     SPORT3_MCMC2  0xffc0263c   /* SPORT3 Multi channel Configuration Register 2 */
+#define                     SPORT3_MTCS0  0xffc02640   /* SPORT3 Multi channel Transmit Select Register 0 */
+#define                     SPORT3_MTCS1  0xffc02644   /* SPORT3 Multi channel Transmit Select Register 1 */
+#define                     SPORT3_MTCS2  0xffc02648   /* SPORT3 Multi channel Transmit Select Register 2 */
+#define                     SPORT3_MTCS3  0xffc0264c   /* SPORT3 Multi channel Transmit Select Register 3 */
+#define                     SPORT3_MRCS0  0xffc02650   /* SPORT3 Multi channel Receive Select Register 0 */
+#define                     SPORT3_MRCS1  0xffc02654   /* SPORT3 Multi channel Receive Select Register 1 */
+#define                     SPORT3_MRCS2  0xffc02658   /* SPORT3 Multi channel Receive Select Register 2 */
+#define                     SPORT3_MRCS3  0xffc0265c   /* SPORT3 Multi channel Receive Select Register 3 */
+
+/* EPPI2 Registers */
+
+#define                     EPPI2_STATUS  0xffc02900   /* EPPI2 Status Register */
+#define                     EPPI2_HCOUNT  0xffc02904   /* EPPI2 Horizontal Transfer Count Register */
+#define                     EPPI2_HDELAY  0xffc02908   /* EPPI2 Horizontal Delay Count Register */
+#define                     EPPI2_VCOUNT  0xffc0290c   /* EPPI2 Vertical Transfer Count Register */
+#define                     EPPI2_VDELAY  0xffc02910   /* EPPI2 Vertical Delay Count Register */
+#define                      EPPI2_FRAME  0xffc02914   /* EPPI2 Lines per Frame Register */
+#define                       EPPI2_LINE  0xffc02918   /* EPPI2 Samples per Line Register */
+#define                     EPPI2_CLKDIV  0xffc0291c   /* EPPI2 Clock Divide Register */
+#define                    EPPI2_CONTROL  0xffc02920   /* EPPI2 Control Register */
+#define                   EPPI2_FS1W_HBL  0xffc02924   /* EPPI2 FS1 Width Register / EPPI2 Horizontal Blanking Samples Per Line Register */
+#define                  EPPI2_FS1P_AVPL  0xffc02928   /* EPPI2 FS1 Period Register / EPPI2 Active Video Samples Per Line Register */
+#define                   EPPI2_FS2W_LVB  0xffc0292c   /* EPPI2 FS2 Width Register / EPPI2 Lines of Vertical Blanking Register */
+#define                  EPPI2_FS2P_LAVF  0xffc02930   /* EPPI2 FS2 Period Register/ EPPI2 Lines of Active Video Per Field Register */
+#define                       EPPI2_CLIP  0xffc02934   /* EPPI2 Clipping Register */
+
+/* CAN Controller 0 Config 1 Registers */
+
+#define                         CAN0_MC1  0xffc02a00   /* CAN Controller 0 Mailbox Configuration Register 1 */
+#define                         CAN0_MD1  0xffc02a04   /* CAN Controller 0 Mailbox Direction Register 1 */
+#define                        CAN0_TRS1  0xffc02a08   /* CAN Controller 0 Transmit Request Set Register 1 */
+#define                        CAN0_TRR1  0xffc02a0c   /* CAN Controller 0 Transmit Request Reset Register 1 */
+#define                         CAN0_TA1  0xffc02a10   /* CAN Controller 0 Transmit Acknowledge Register 1 */
+#define                         CAN0_AA1  0xffc02a14   /* CAN Controller 0 Abort Acknowledge Register 1 */
+#define                        CAN0_RMP1  0xffc02a18   /* CAN Controller 0 Receive Message Pending Register 1 */
+#define                        CAN0_RML1  0xffc02a1c   /* CAN Controller 0 Receive Message Lost Register 1 */
+#define                      CAN0_MBTIF1  0xffc02a20   /* CAN Controller 0 Mailbox Transmit Interrupt Flag Register 1 */
+#define                      CAN0_MBRIF1  0xffc02a24   /* CAN Controller 0 Mailbox Receive Interrupt Flag Register 1 */
+#define                       CAN0_MBIM1  0xffc02a28   /* CAN Controller 0 Mailbox Interrupt Mask Register 1 */
+#define                        CAN0_RFH1  0xffc02a2c   /* CAN Controller 0 Remote Frame Handling Enable Register 1 */
+#define                       CAN0_OPSS1  0xffc02a30   /* CAN Controller 0 Overwrite Protection Single Shot Transmit Register 1 */
+
+/* CAN Controller 0 Config 2 Registers */
+
+#define                         CAN0_MC2  0xffc02a40   /* CAN Controller 0 Mailbox Configuration Register 2 */
+#define                         CAN0_MD2  0xffc02a44   /* CAN Controller 0 Mailbox Direction Register 2 */
+#define                        CAN0_TRS2  0xffc02a48   /* CAN Controller 0 Transmit Request Set Register 2 */
+#define                        CAN0_TRR2  0xffc02a4c   /* CAN Controller 0 Transmit Request Reset Register 2 */
+#define                         CAN0_TA2  0xffc02a50   /* CAN Controller 0 Transmit Acknowledge Register 2 */
+#define                         CAN0_AA2  0xffc02a54   /* CAN Controller 0 Abort Acknowledge Register 2 */
+#define                        CAN0_RMP2  0xffc02a58   /* CAN Controller 0 Receive Message Pending Register 2 */
+#define                        CAN0_RML2  0xffc02a5c   /* CAN Controller 0 Receive Message Lost Register 2 */
+#define                      CAN0_MBTIF2  0xffc02a60   /* CAN Controller 0 Mailbox Transmit Interrupt Flag Register 2 */
+#define                      CAN0_MBRIF2  0xffc02a64   /* CAN Controller 0 Mailbox Receive Interrupt Flag Register 2 */
+#define                       CAN0_MBIM2  0xffc02a68   /* CAN Controller 0 Mailbox Interrupt Mask Register 2 */
+#define                        CAN0_RFH2  0xffc02a6c   /* CAN Controller 0 Remote Frame Handling Enable Register 2 */
+#define                       CAN0_OPSS2  0xffc02a70   /* CAN Controller 0 Overwrite Protection Single Shot Transmit Register 2 */
+
+/* CAN Controller 0 Clock/Interrupt/Counter Registers */
+
+#define                       CAN0_CLOCK  0xffc02a80   /* CAN Controller 0 Clock Register */
+#define                      CAN0_TIMING  0xffc02a84   /* CAN Controller 0 Timing Register */
+#define                       CAN0_DEBUG  0xffc02a88   /* CAN Controller 0 Debug Register */
+#define                      CAN0_STATUS  0xffc02a8c   /* CAN Controller 0 Global Status Register */
+#define                         CAN0_CEC  0xffc02a90   /* CAN Controller 0 Error Counter Register */
+#define                         CAN0_GIS  0xffc02a94   /* CAN Controller 0 Global Interrupt Status Register */
+#define                         CAN0_GIM  0xffc02a98   /* CAN Controller 0 Global Interrupt Mask Register */
+#define                         CAN0_GIF  0xffc02a9c   /* CAN Controller 0 Global Interrupt Flag Register */
+#define                     CAN0_CONTROL  0xffc02aa0   /* CAN Controller 0 Master Control Register */
+#define                        CAN0_INTR  0xffc02aa4   /* CAN Controller 0 Interrupt Pending Register */
+#define                        CAN0_MBTD  0xffc02aac   /* CAN Controller 0 Mailbox Temporary Disable Register */
+#define                         CAN0_EWR  0xffc02ab0   /* CAN Controller 0 Programmable Warning Level Register */
+#define                         CAN0_ESR  0xffc02ab4   /* CAN Controller 0 Error Status Register */
+#define                       CAN0_UCCNT  0xffc02ac4   /* CAN Controller 0 Universal Counter Register */
+#define                        CAN0_UCRC  0xffc02ac8   /* CAN Controller 0 Universal Counter Force Reload Register */
+#define                       CAN0_UCCNF  0xffc02acc   /* CAN Controller 0 Universal Counter Configuration Register */
+
+/* CAN Controller 0 Acceptance Registers */
+
+#define                       CAN0_AM00L  0xffc02b00   /* CAN Controller 0 Mailbox 0 Acceptance Mask High Register */
+#define                       CAN0_AM00H  0xffc02b04   /* CAN Controller 0 Mailbox 0 Acceptance Mask Low Register */
+#define                       CAN0_AM01L  0xffc02b08   /* CAN Controller 0 Mailbox 1 Acceptance Mask High Register */
+#define                       CAN0_AM01H  0xffc02b0c   /* CAN Controller 0 Mailbox 1 Acceptance Mask Low Register */
+#define                       CAN0_AM02L  0xffc02b10   /* CAN Controller 0 Mailbox 2 Acceptance Mask High Register */
+#define                       CAN0_AM02H  0xffc02b14   /* CAN Controller 0 Mailbox 2 Acceptance Mask Low Register */
+#define                       CAN0_AM03L  0xffc02b18   /* CAN Controller 0 Mailbox 3 Acceptance Mask High Register */
+#define                       CAN0_AM03H  0xffc02b1c   /* CAN Controller 0 Mailbox 3 Acceptance Mask Low Register */
+#define                       CAN0_AM04L  0xffc02b20   /* CAN Controller 0 Mailbox 4 Acceptance Mask High Register */
+#define                       CAN0_AM04H  0xffc02b24   /* CAN Controller 0 Mailbox 4 Acceptance Mask Low Register */
+#define                       CAN0_AM05L  0xffc02b28   /* CAN Controller 0 Mailbox 5 Acceptance Mask High Register */
+#define                       CAN0_AM05H  0xffc02b2c   /* CAN Controller 0 Mailbox 5 Acceptance Mask Low Register */
+#define                       CAN0_AM06L  0xffc02b30   /* CAN Controller 0 Mailbox 6 Acceptance Mask High Register */
+#define                       CAN0_AM06H  0xffc02b34   /* CAN Controller 0 Mailbox 6 Acceptance Mask Low Register */
+#define                       CAN0_AM07L  0xffc02b38   /* CAN Controller 0 Mailbox 7 Acceptance Mask High Register */
+#define                       CAN0_AM07H  0xffc02b3c   /* CAN Controller 0 Mailbox 7 Acceptance Mask Low Register */
+#define                       CAN0_AM08L  0xffc02b40   /* CAN Controller 0 Mailbox 8 Acceptance Mask High Register */
+#define                       CAN0_AM08H  0xffc02b44   /* CAN Controller 0 Mailbox 8 Acceptance Mask Low Register */
+#define                       CAN0_AM09L  0xffc02b48   /* CAN Controller 0 Mailbox 9 Acceptance Mask High Register */
+#define                       CAN0_AM09H  0xffc02b4c   /* CAN Controller 0 Mailbox 9 Acceptance Mask Low Register */
+#define                       CAN0_AM10L  0xffc02b50   /* CAN Controller 0 Mailbox 10 Acceptance Mask High Register */
+#define                       CAN0_AM10H  0xffc02b54   /* CAN Controller 0 Mailbox 10 Acceptance Mask Low Register */
+#define                       CAN0_AM11L  0xffc02b58   /* CAN Controller 0 Mailbox 11 Acceptance Mask High Register */
+#define                       CAN0_AM11H  0xffc02b5c   /* CAN Controller 0 Mailbox 11 Acceptance Mask Low Register */
+#define                       CAN0_AM12L  0xffc02b60   /* CAN Controller 0 Mailbox 12 Acceptance Mask High Register */
+#define                       CAN0_AM12H  0xffc02b64   /* CAN Controller 0 Mailbox 12 Acceptance Mask Low Register */
+#define                       CAN0_AM13L  0xffc02b68   /* CAN Controller 0 Mailbox 13 Acceptance Mask High Register */
+#define                       CAN0_AM13H  0xffc02b6c   /* CAN Controller 0 Mailbox 13 Acceptance Mask Low Register */
+#define                       CAN0_AM14L  0xffc02b70   /* CAN Controller 0 Mailbox 14 Acceptance Mask High Register */
+#define                       CAN0_AM14H  0xffc02b74   /* CAN Controller 0 Mailbox 14 Acceptance Mask Low Register */
+#define                       CAN0_AM15L  0xffc02b78   /* CAN Controller 0 Mailbox 15 Acceptance Mask High Register */
+#define                       CAN0_AM15H  0xffc02b7c   /* CAN Controller 0 Mailbox 15 Acceptance Mask Low Register */
+
+/* CAN Controller 0 Acceptance Registers */
+
+#define                       CAN0_AM16L  0xffc02b80   /* CAN Controller 0 Mailbox 16 Acceptance Mask High Register */
+#define                       CAN0_AM16H  0xffc02b84   /* CAN Controller 0 Mailbox 16 Acceptance Mask Low Register */
+#define                       CAN0_AM17L  0xffc02b88   /* CAN Controller 0 Mailbox 17 Acceptance Mask High Register */
+#define                       CAN0_AM17H  0xffc02b8c   /* CAN Controller 0 Mailbox 17 Acceptance Mask Low Register */
+#define                       CAN0_AM18L  0xffc02b90   /* CAN Controller 0 Mailbox 18 Acceptance Mask High Register */
+#define                       CAN0_AM18H  0xffc02b94   /* CAN Controller 0 Mailbox 18 Acceptance Mask Low Register */
+#define                       CAN0_AM19L  0xffc02b98   /* CAN Controller 0 Mailbox 19 Acceptance Mask High Register */
+#define                       CAN0_AM19H  0xffc02b9c   /* CAN Controller 0 Mailbox 19 Acceptance Mask Low Register */
+#define                       CAN0_AM20L  0xffc02ba0   /* CAN Controller 0 Mailbox 20 Acceptance Mask High Register */
+#define                       CAN0_AM20H  0xffc02ba4   /* CAN Controller 0 Mailbox 20 Acceptance Mask Low Register */
+#define                       CAN0_AM21L  0xffc02ba8   /* CAN Controller 0 Mailbox 21 Acceptance Mask High Register */
+#define                       CAN0_AM21H  0xffc02bac   /* CAN Controller 0 Mailbox 21 Acceptance Mask Low Register */
+#define                       CAN0_AM22L  0xffc02bb0   /* CAN Controller 0 Mailbox 22 Acceptance Mask High Register */
+#define                       CAN0_AM22H  0xffc02bb4   /* CAN Controller 0 Mailbox 22 Acceptance Mask Low Register */
+#define                       CAN0_AM23L  0xffc02bb8   /* CAN Controller 0 Mailbox 23 Acceptance Mask High Register */
+#define                       CAN0_AM23H  0xffc02bbc   /* CAN Controller 0 Mailbox 23 Acceptance Mask Low Register */
+#define                       CAN0_AM24L  0xffc02bc0   /* CAN Controller 0 Mailbox 24 Acceptance Mask High Register */
+#define                       CAN0_AM24H  0xffc02bc4   /* CAN Controller 0 Mailbox 24 Acceptance Mask Low Register */
+#define                       CAN0_AM25L  0xffc02bc8   /* CAN Controller 0 Mailbox 25 Acceptance Mask High Register */
+#define                       CAN0_AM25H  0xffc02bcc   /* CAN Controller 0 Mailbox 25 Acceptance Mask Low Register */
+#define                       CAN0_AM26L  0xffc02bd0   /* CAN Controller 0 Mailbox 26 Acceptance Mask High Register */
+#define                       CAN0_AM26H  0xffc02bd4   /* CAN Controller 0 Mailbox 26 Acceptance Mask Low Register */
+#define                       CAN0_AM27L  0xffc02bd8   /* CAN Controller 0 Mailbox 27 Acceptance Mask High Register */
+#define                       CAN0_AM27H  0xffc02bdc   /* CAN Controller 0 Mailbox 27 Acceptance Mask Low Register */
+#define                       CAN0_AM28L  0xffc02be0   /* CAN Controller 0 Mailbox 28 Acceptance Mask High Register */
+#define                       CAN0_AM28H  0xffc02be4   /* CAN Controller 0 Mailbox 28 Acceptance Mask Low Register */
+#define                       CAN0_AM29L  0xffc02be8   /* CAN Controller 0 Mailbox 29 Acceptance Mask High Register */
+#define                       CAN0_AM29H  0xffc02bec   /* CAN Controller 0 Mailbox 29 Acceptance Mask Low Register */
+#define                       CAN0_AM30L  0xffc02bf0   /* CAN Controller 0 Mailbox 30 Acceptance Mask High Register */
+#define                       CAN0_AM30H  0xffc02bf4   /* CAN Controller 0 Mailbox 30 Acceptance Mask Low Register */
+#define                       CAN0_AM31L  0xffc02bf8   /* CAN Controller 0 Mailbox 31 Acceptance Mask High Register */
+#define                       CAN0_AM31H  0xffc02bfc   /* CAN Controller 0 Mailbox 31 Acceptance Mask Low Register */
+
+/* CAN Controller 0 Mailbox Data Registers */
+
+#define                  CAN0_MB00_DATA0  0xffc02c00   /* CAN Controller 0 Mailbox 0 Data 0 Register */
+#define                  CAN0_MB00_DATA1  0xffc02c04   /* CAN Controller 0 Mailbox 0 Data 1 Register */
+#define                  CAN0_MB00_DATA2  0xffc02c08   /* CAN Controller 0 Mailbox 0 Data 2 Register */
+#define                  CAN0_MB00_DATA3  0xffc02c0c   /* CAN Controller 0 Mailbox 0 Data 3 Register */
+#define                 CAN0_MB00_LENGTH  0xffc02c10   /* CAN Controller 0 Mailbox 0 Length Register */
+#define              CAN0_MB00_TIMESTAMP  0xffc02c14   /* CAN Controller 0 Mailbox 0 Timestamp Register */
+#define                    CAN0_MB00_ID0  0xffc02c18   /* CAN Controller 0 Mailbox 0 ID0 Register */
+#define                    CAN0_MB00_ID1  0xffc02c1c   /* CAN Controller 0 Mailbox 0 ID1 Register */
+#define                  CAN0_MB01_DATA0  0xffc02c20   /* CAN Controller 0 Mailbox 1 Data 0 Register */
+#define                  CAN0_MB01_DATA1  0xffc02c24   /* CAN Controller 0 Mailbox 1 Data 1 Register */
+#define                  CAN0_MB01_DATA2  0xffc02c28   /* CAN Controller 0 Mailbox 1 Data 2 Register */
+#define                  CAN0_MB01_DATA3  0xffc02c2c   /* CAN Controller 0 Mailbox 1 Data 3 Register */
+#define                 CAN0_MB01_LENGTH  0xffc02c30   /* CAN Controller 0 Mailbox 1 Length Register */
+#define              CAN0_MB01_TIMESTAMP  0xffc02c34   /* CAN Controller 0 Mailbox 1 Timestamp Register */
+#define                    CAN0_MB01_ID0  0xffc02c38   /* CAN Controller 0 Mailbox 1 ID0 Register */
+#define                    CAN0_MB01_ID1  0xffc02c3c   /* CAN Controller 0 Mailbox 1 ID1 Register */
+#define                  CAN0_MB02_DATA0  0xffc02c40   /* CAN Controller 0 Mailbox 2 Data 0 Register */
+#define                  CAN0_MB02_DATA1  0xffc02c44   /* CAN Controller 0 Mailbox 2 Data 1 Register */
+#define                  CAN0_MB02_DATA2  0xffc02c48   /* CAN Controller 0 Mailbox 2 Data 2 Register */
+#define                  CAN0_MB02_DATA3  0xffc02c4c   /* CAN Controller 0 Mailbox 2 Data 3 Register */
+#define                 CAN0_MB02_LENGTH  0xffc02c50   /* CAN Controller 0 Mailbox 2 Length Register */
+#define              CAN0_MB02_TIMESTAMP  0xffc02c54   /* CAN Controller 0 Mailbox 2 Timestamp Register */
+#define                    CAN0_MB02_ID0  0xffc02c58   /* CAN Controller 0 Mailbox 2 ID0 Register */
+#define                    CAN0_MB02_ID1  0xffc02c5c   /* CAN Controller 0 Mailbox 2 ID1 Register */
+#define                  CAN0_MB03_DATA0  0xffc02c60   /* CAN Controller 0 Mailbox 3 Data 0 Register */
+#define                  CAN0_MB03_DATA1  0xffc02c64   /* CAN Controller 0 Mailbox 3 Data 1 Register */
+#define                  CAN0_MB03_DATA2  0xffc02c68   /* CAN Controller 0 Mailbox 3 Data 2 Register */
+#define                  CAN0_MB03_DATA3  0xffc02c6c   /* CAN Controller 0 Mailbox 3 Data 3 Register */
+#define                 CAN0_MB03_LENGTH  0xffc02c70   /* CAN Controller 0 Mailbox 3 Length Register */
+#define              CAN0_MB03_TIMESTAMP  0xffc02c74   /* CAN Controller 0 Mailbox 3 Timestamp Register */
+#define                    CAN0_MB03_ID0  0xffc02c78   /* CAN Controller 0 Mailbox 3 ID0 Register */
+#define                    CAN0_MB03_ID1  0xffc02c7c   /* CAN Controller 0 Mailbox 3 ID1 Register */
+#define                  CAN0_MB04_DATA0  0xffc02c80   /* CAN Controller 0 Mailbox 4 Data 0 Register */
+#define                  CAN0_MB04_DATA1  0xffc02c84   /* CAN Controller 0 Mailbox 4 Data 1 Register */
+#define                  CAN0_MB04_DATA2  0xffc02c88   /* CAN Controller 0 Mailbox 4 Data 2 Register */
+#define                  CAN0_MB04_DATA3  0xffc02c8c   /* CAN Controller 0 Mailbox 4 Data 3 Register */
+#define                 CAN0_MB04_LENGTH  0xffc02c90   /* CAN Controller 0 Mailbox 4 Length Register */
+#define              CAN0_MB04_TIMESTAMP  0xffc02c94   /* CAN Controller 0 Mailbox 4 Timestamp Register */
+#define                    CAN0_MB04_ID0  0xffc02c98   /* CAN Controller 0 Mailbox 4 ID0 Register */
+#define                    CAN0_MB04_ID1  0xffc02c9c   /* CAN Controller 0 Mailbox 4 ID1 Register */
+#define                  CAN0_MB05_DATA0  0xffc02ca0   /* CAN Controller 0 Mailbox 5 Data 0 Register */
+#define                  CAN0_MB05_DATA1  0xffc02ca4   /* CAN Controller 0 Mailbox 5 Data 1 Register */
+#define                  CAN0_MB05_DATA2  0xffc02ca8   /* CAN Controller 0 Mailbox 5 Data 2 Register */
+#define                  CAN0_MB05_DATA3  0xffc02cac   /* CAN Controller 0 Mailbox 5 Data 3 Register */
+#define                 CAN0_MB05_LENGTH  0xffc02cb0   /* CAN Controller 0 Mailbox 5 Length Register */
+#define              CAN0_MB05_TIMESTAMP  0xffc02cb4   /* CAN Controller 0 Mailbox 5 Timestamp Register */
+#define                    CAN0_MB05_ID0  0xffc02cb8   /* CAN Controller 0 Mailbox 5 ID0 Register */
+#define                    CAN0_MB05_ID1  0xffc02cbc   /* CAN Controller 0 Mailbox 5 ID1 Register */
+#define                  CAN0_MB06_DATA0  0xffc02cc0   /* CAN Controller 0 Mailbox 6 Data 0 Register */
+#define                  CAN0_MB06_DATA1  0xffc02cc4   /* CAN Controller 0 Mailbox 6 Data 1 Register */
+#define                  CAN0_MB06_DATA2  0xffc02cc8   /* CAN Controller 0 Mailbox 6 Data 2 Register */
+#define                  CAN0_MB06_DATA3  0xffc02ccc   /* CAN Controller 0 Mailbox 6 Data 3 Register */
+#define                 CAN0_MB06_LENGTH  0xffc02cd0   /* CAN Controller 0 Mailbox 6 Length Register */
+#define              CAN0_MB06_TIMESTAMP  0xffc02cd4   /* CAN Controller 0 Mailbox 6 Timestamp Register */
+#define                    CAN0_MB06_ID0  0xffc02cd8   /* CAN Controller 0 Mailbox 6 ID0 Register */
+#define                    CAN0_MB06_ID1  0xffc02cdc   /* CAN Controller 0 Mailbox 6 ID1 Register */
+#define                  CAN0_MB07_DATA0  0xffc02ce0   /* CAN Controller 0 Mailbox 7 Data 0 Register */
+#define                  CAN0_MB07_DATA1  0xffc02ce4   /* CAN Controller 0 Mailbox 7 Data 1 Register */
+#define                  CAN0_MB07_DATA2  0xffc02ce8   /* CAN Controller 0 Mailbox 7 Data 2 Register */
+#define                  CAN0_MB07_DATA3  0xffc02cec   /* CAN Controller 0 Mailbox 7 Data 3 Register */
+#define                 CAN0_MB07_LENGTH  0xffc02cf0   /* CAN Controller 0 Mailbox 7 Length Register */
+#define              CAN0_MB07_TIMESTAMP  0xffc02cf4   /* CAN Controller 0 Mailbox 7 Timestamp Register */
+#define                    CAN0_MB07_ID0  0xffc02cf8   /* CAN Controller 0 Mailbox 7 ID0 Register */
+#define                    CAN0_MB07_ID1  0xffc02cfc   /* CAN Controller 0 Mailbox 7 ID1 Register */
+#define                  CAN0_MB08_DATA0  0xffc02d00   /* CAN Controller 0 Mailbox 8 Data 0 Register */
+#define                  CAN0_MB08_DATA1  0xffc02d04   /* CAN Controller 0 Mailbox 8 Data 1 Register */
+#define                  CAN0_MB08_DATA2  0xffc02d08   /* CAN Controller 0 Mailbox 8 Data 2 Register */
+#define                  CAN0_MB08_DATA3  0xffc02d0c   /* CAN Controller 0 Mailbox 8 Data 3 Register */
+#define                 CAN0_MB08_LENGTH  0xffc02d10   /* CAN Controller 0 Mailbox 8 Length Register */
+#define              CAN0_MB08_TIMESTAMP  0xffc02d14   /* CAN Controller 0 Mailbox 8 Timestamp Register */
+#define                    CAN0_MB08_ID0  0xffc02d18   /* CAN Controller 0 Mailbox 8 ID0 Register */
+#define                    CAN0_MB08_ID1  0xffc02d1c   /* CAN Controller 0 Mailbox 8 ID1 Register */
+#define                  CAN0_MB09_DATA0  0xffc02d20   /* CAN Controller 0 Mailbox 9 Data 0 Register */
+#define                  CAN0_MB09_DATA1  0xffc02d24   /* CAN Controller 0 Mailbox 9 Data 1 Register */
+#define                  CAN0_MB09_DATA2  0xffc02d28   /* CAN Controller 0 Mailbox 9 Data 2 Register */
+#define                  CAN0_MB09_DATA3  0xffc02d2c   /* CAN Controller 0 Mailbox 9 Data 3 Register */
+#define                 CAN0_MB09_LENGTH  0xffc02d30   /* CAN Controller 0 Mailbox 9 Length Register */
+#define              CAN0_MB09_TIMESTAMP  0xffc02d34   /* CAN Controller 0 Mailbox 9 Timestamp Register */
+#define                    CAN0_MB09_ID0  0xffc02d38   /* CAN Controller 0 Mailbox 9 ID0 Register */
+#define                    CAN0_MB09_ID1  0xffc02d3c   /* CAN Controller 0 Mailbox 9 ID1 Register */
+#define                  CAN0_MB10_DATA0  0xffc02d40   /* CAN Controller 0 Mailbox 10 Data 0 Register */
+#define                  CAN0_MB10_DATA1  0xffc02d44   /* CAN Controller 0 Mailbox 10 Data 1 Register */
+#define                  CAN0_MB10_DATA2  0xffc02d48   /* CAN Controller 0 Mailbox 10 Data 2 Register */
+#define                  CAN0_MB10_DATA3  0xffc02d4c   /* CAN Controller 0 Mailbox 10 Data 3 Register */
+#define                 CAN0_MB10_LENGTH  0xffc02d50   /* CAN Controller 0 Mailbox 10 Length Register */
+#define              CAN0_MB10_TIMESTAMP  0xffc02d54   /* CAN Controller 0 Mailbox 10 Timestamp Register */
+#define                    CAN0_MB10_ID0  0xffc02d58   /* CAN Controller 0 Mailbox 10 ID0 Register */
+#define                    CAN0_MB10_ID1  0xffc02d5c   /* CAN Controller 0 Mailbox 10 ID1 Register */
+#define                  CAN0_MB11_DATA0  0xffc02d60   /* CAN Controller 0 Mailbox 11 Data 0 Register */
+#define                  CAN0_MB11_DATA1  0xffc02d64   /* CAN Controller 0 Mailbox 11 Data 1 Register */
+#define                  CAN0_MB11_DATA2  0xffc02d68   /* CAN Controller 0 Mailbox 11 Data 2 Register */
+#define                  CAN0_MB11_DATA3  0xffc02d6c   /* CAN Controller 0 Mailbox 11 Data 3 Register */
+#define                 CAN0_MB11_LENGTH  0xffc02d70   /* CAN Controller 0 Mailbox 11 Length Register */
+#define              CAN0_MB11_TIMESTAMP  0xffc02d74   /* CAN Controller 0 Mailbox 11 Timestamp Register */
+#define                    CAN0_MB11_ID0  0xffc02d78   /* CAN Controller 0 Mailbox 11 ID0 Register */
+#define                    CAN0_MB11_ID1  0xffc02d7c   /* CAN Controller 0 Mailbox 11 ID1 Register */
+#define                  CAN0_MB12_DATA0  0xffc02d80   /* CAN Controller 0 Mailbox 12 Data 0 Register */
+#define                  CAN0_MB12_DATA1  0xffc02d84   /* CAN Controller 0 Mailbox 12 Data 1 Register */
+#define                  CAN0_MB12_DATA2  0xffc02d88   /* CAN Controller 0 Mailbox 12 Data 2 Register */
+#define                  CAN0_MB12_DATA3  0xffc02d8c   /* CAN Controller 0 Mailbox 12 Data 3 Register */
+#define                 CAN0_MB12_LENGTH  0xffc02d90   /* CAN Controller 0 Mailbox 12 Length Register */
+#define              CAN0_MB12_TIMESTAMP  0xffc02d94   /* CAN Controller 0 Mailbox 12 Timestamp Register */
+#define                    CAN0_MB12_ID0  0xffc02d98   /* CAN Controller 0 Mailbox 12 ID0 Register */
+#define                    CAN0_MB12_ID1  0xffc02d9c   /* CAN Controller 0 Mailbox 12 ID1 Register */
+#define                  CAN0_MB13_DATA0  0xffc02da0   /* CAN Controller 0 Mailbox 13 Data 0 Register */
+#define                  CAN0_MB13_DATA1  0xffc02da4   /* CAN Controller 0 Mailbox 13 Data 1 Register */
+#define                  CAN0_MB13_DATA2  0xffc02da8   /* CAN Controller 0 Mailbox 13 Data 2 Register */
+#define                  CAN0_MB13_DATA3  0xffc02dac   /* CAN Controller 0 Mailbox 13 Data 3 Register */
+#define                 CAN0_MB13_LENGTH  0xffc02db0   /* CAN Controller 0 Mailbox 13 Length Register */
+#define              CAN0_MB13_TIMESTAMP  0xffc02db4   /* CAN Controller 0 Mailbox 13 Timestamp Register */
+#define                    CAN0_MB13_ID0  0xffc02db8   /* CAN Controller 0 Mailbox 13 ID0 Register */
+#define                    CAN0_MB13_ID1  0xffc02dbc   /* CAN Controller 0 Mailbox 13 ID1 Register */
+#define                  CAN0_MB14_DATA0  0xffc02dc0   /* CAN Controller 0 Mailbox 14 Data 0 Register */
+#define                  CAN0_MB14_DATA1  0xffc02dc4   /* CAN Controller 0 Mailbox 14 Data 1 Register */
+#define                  CAN0_MB14_DATA2  0xffc02dc8   /* CAN Controller 0 Mailbox 14 Data 2 Register */
+#define                  CAN0_MB14_DATA3  0xffc02dcc   /* CAN Controller 0 Mailbox 14 Data 3 Register */
+#define                 CAN0_MB14_LENGTH  0xffc02dd0   /* CAN Controller 0 Mailbox 14 Length Register */
+#define              CAN0_MB14_TIMESTAMP  0xffc02dd4   /* CAN Controller 0 Mailbox 14 Timestamp Register */
+#define                    CAN0_MB14_ID0  0xffc02dd8   /* CAN Controller 0 Mailbox 14 ID0 Register */
+#define                    CAN0_MB14_ID1  0xffc02ddc   /* CAN Controller 0 Mailbox 14 ID1 Register */
+#define                  CAN0_MB15_DATA0  0xffc02de0   /* CAN Controller 0 Mailbox 15 Data 0 Register */
+#define                  CAN0_MB15_DATA1  0xffc02de4   /* CAN Controller 0 Mailbox 15 Data 1 Register */
+#define                  CAN0_MB15_DATA2  0xffc02de8   /* CAN Controller 0 Mailbox 15 Data 2 Register */
+#define                  CAN0_MB15_DATA3  0xffc02dec   /* CAN Controller 0 Mailbox 15 Data 3 Register */
+#define                 CAN0_MB15_LENGTH  0xffc02df0   /* CAN Controller 0 Mailbox 15 Length Register */
+#define              CAN0_MB15_TIMESTAMP  0xffc02df4   /* CAN Controller 0 Mailbox 15 Timestamp Register */
+#define                    CAN0_MB15_ID0  0xffc02df8   /* CAN Controller 0 Mailbox 15 ID0 Register */
+#define                    CAN0_MB15_ID1  0xffc02dfc   /* CAN Controller 0 Mailbox 15 ID1 Register */
+
+/* CAN Controller 0 Mailbox Data Registers */
+
+#define                  CAN0_MB16_DATA0  0xffc02e00   /* CAN Controller 0 Mailbox 16 Data 0 Register */
+#define                  CAN0_MB16_DATA1  0xffc02e04   /* CAN Controller 0 Mailbox 16 Data 1 Register */
+#define                  CAN0_MB16_DATA2  0xffc02e08   /* CAN Controller 0 Mailbox 16 Data 2 Register */
+#define                  CAN0_MB16_DATA3  0xffc02e0c   /* CAN Controller 0 Mailbox 16 Data 3 Register */
+#define                 CAN0_MB16_LENGTH  0xffc02e10   /* CAN Controller 0 Mailbox 16 Length Register */
+#define              CAN0_MB16_TIMESTAMP  0xffc02e14   /* CAN Controller 0 Mailbox 16 Timestamp Register */
+#define                    CAN0_MB16_ID0  0xffc02e18   /* CAN Controller 0 Mailbox 16 ID0 Register */
+#define                    CAN0_MB16_ID1  0xffc02e1c   /* CAN Controller 0 Mailbox 16 ID1 Register */
+#define                  CAN0_MB17_DATA0  0xffc02e20   /* CAN Controller 0 Mailbox 17 Data 0 Register */
+#define                  CAN0_MB17_DATA1  0xffc02e24   /* CAN Controller 0 Mailbox 17 Data 1 Register */
+#define                  CAN0_MB17_DATA2  0xffc02e28   /* CAN Controller 0 Mailbox 17 Data 2 Register */
+#define                  CAN0_MB17_DATA3  0xffc02e2c   /* CAN Controller 0 Mailbox 17 Data 3 Register */
+#define                 CAN0_MB17_LENGTH  0xffc02e30   /* CAN Controller 0 Mailbox 17 Length Register */
+#define              CAN0_MB17_TIMESTAMP  0xffc02e34   /* CAN Controller 0 Mailbox 17 Timestamp Register */
+#define                    CAN0_MB17_ID0  0xffc02e38   /* CAN Controller 0 Mailbox 17 ID0 Register */
+#define                    CAN0_MB17_ID1  0xffc02e3c   /* CAN Controller 0 Mailbox 17 ID1 Register */
+#define                  CAN0_MB18_DATA0  0xffc02e40   /* CAN Controller 0 Mailbox 18 Data 0 Register */
+#define                  CAN0_MB18_DATA1  0xffc02e44   /* CAN Controller 0 Mailbox 18 Data 1 Register */
+#define                  CAN0_MB18_DATA2  0xffc02e48   /* CAN Controller 0 Mailbox 18 Data 2 Register */
+#define                  CAN0_MB18_DATA3  0xffc02e4c   /* CAN Controller 0 Mailbox 18 Data 3 Register */
+#define                 CAN0_MB18_LENGTH  0xffc02e50   /* CAN Controller 0 Mailbox 18 Length Register */
+#define              CAN0_MB18_TIMESTAMP  0xffc02e54   /* CAN Controller 0 Mailbox 18 Timestamp Register */
+#define                    CAN0_MB18_ID0  0xffc02e58   /* CAN Controller 0 Mailbox 18 ID0 Register */
+#define                    CAN0_MB18_ID1  0xffc02e5c   /* CAN Controller 0 Mailbox 18 ID1 Register */
+#define                  CAN0_MB19_DATA0  0xffc02e60   /* CAN Controller 0 Mailbox 19 Data 0 Register */
+#define                  CAN0_MB19_DATA1  0xffc02e64   /* CAN Controller 0 Mailbox 19 Data 1 Register */
+#define                  CAN0_MB19_DATA2  0xffc02e68   /* CAN Controller 0 Mailbox 19 Data 2 Register */
+#define                  CAN0_MB19_DATA3  0xffc02e6c   /* CAN Controller 0 Mailbox 19 Data 3 Register */
+#define                 CAN0_MB19_LENGTH  0xffc02e70   /* CAN Controller 0 Mailbox 19 Length Register */
+#define              CAN0_MB19_TIMESTAMP  0xffc02e74   /* CAN Controller 0 Mailbox 19 Timestamp Register */
+#define                    CAN0_MB19_ID0  0xffc02e78   /* CAN Controller 0 Mailbox 19 ID0 Register */
+#define                    CAN0_MB19_ID1  0xffc02e7c   /* CAN Controller 0 Mailbox 19 ID1 Register */
+#define                  CAN0_MB20_DATA0  0xffc02e80   /* CAN Controller 0 Mailbox 20 Data 0 Register */
+#define                  CAN0_MB20_DATA1  0xffc02e84   /* CAN Controller 0 Mailbox 20 Data 1 Register */
+#define                  CAN0_MB20_DATA2  0xffc02e88   /* CAN Controller 0 Mailbox 20 Data 2 Register */
+#define                  CAN0_MB20_DATA3  0xffc02e8c   /* CAN Controller 0 Mailbox 20 Data 3 Register */
+#define                 CAN0_MB20_LENGTH  0xffc02e90   /* CAN Controller 0 Mailbox 20 Length Register */
+#define              CAN0_MB20_TIMESTAMP  0xffc02e94   /* CAN Controller 0 Mailbox 20 Timestamp Register */
+#define                    CAN0_MB20_ID0  0xffc02e98   /* CAN Controller 0 Mailbox 20 ID0 Register */
+#define                    CAN0_MB20_ID1  0xffc02e9c   /* CAN Controller 0 Mailbox 20 ID1 Register */
+#define                  CAN0_MB21_DATA0  0xffc02ea0   /* CAN Controller 0 Mailbox 21 Data 0 Register */
+#define                  CAN0_MB21_DATA1  0xffc02ea4   /* CAN Controller 0 Mailbox 21 Data 1 Register */
+#define                  CAN0_MB21_DATA2  0xffc02ea8   /* CAN Controller 0 Mailbox 21 Data 2 Register */
+#define                  CAN0_MB21_DATA3  0xffc02eac   /* CAN Controller 0 Mailbox 21 Data 3 Register */
+#define                 CAN0_MB21_LENGTH  0xffc02eb0   /* CAN Controller 0 Mailbox 21 Length Register */
+#define              CAN0_MB21_TIMESTAMP  0xffc02eb4   /* CAN Controller 0 Mailbox 21 Timestamp Register */
+#define                    CAN0_MB21_ID0  0xffc02eb8   /* CAN Controller 0 Mailbox 21 ID0 Register */
+#define                    CAN0_MB21_ID1  0xffc02ebc   /* CAN Controller 0 Mailbox 21 ID1 Register */
+#define                  CAN0_MB22_DATA0  0xffc02ec0   /* CAN Controller 0 Mailbox 22 Data 0 Register */
+#define                  CAN0_MB22_DATA1  0xffc02ec4   /* CAN Controller 0 Mailbox 22 Data 1 Register */
+#define                  CAN0_MB22_DATA2  0xffc02ec8   /* CAN Controller 0 Mailbox 22 Data 2 Register */
+#define                  CAN0_MB22_DATA3  0xffc02ecc   /* CAN Controller 0 Mailbox 22 Data 3 Register */
+#define                 CAN0_MB22_LENGTH  0xffc02ed0   /* CAN Controller 0 Mailbox 22 Length Register */
+#define              CAN0_MB22_TIMESTAMP  0xffc02ed4   /* CAN Controller 0 Mailbox 22 Timestamp Register */
+#define                    CAN0_MB22_ID0  0xffc02ed8   /* CAN Controller 0 Mailbox 22 ID0 Register */
+#define                    CAN0_MB22_ID1  0xffc02edc   /* CAN Controller 0 Mailbox 22 ID1 Register */
+#define                  CAN0_MB23_DATA0  0xffc02ee0   /* CAN Controller 0 Mailbox 23 Data 0 Register */
+#define                  CAN0_MB23_DATA1  0xffc02ee4   /* CAN Controller 0 Mailbox 23 Data 1 Register */
+#define                  CAN0_MB23_DATA2  0xffc02ee8   /* CAN Controller 0 Mailbox 23 Data 2 Register */
+#define                  CAN0_MB23_DATA3  0xffc02eec   /* CAN Controller 0 Mailbox 23 Data 3 Register */
+#define                 CAN0_MB23_LENGTH  0xffc02ef0   /* CAN Controller 0 Mailbox 23 Length Register */
+#define              CAN0_MB23_TIMESTAMP  0xffc02ef4   /* CAN Controller 0 Mailbox 23 Timestamp Register */
+#define                    CAN0_MB23_ID0  0xffc02ef8   /* CAN Controller 0 Mailbox 23 ID0 Register */
+#define                    CAN0_MB23_ID1  0xffc02efc   /* CAN Controller 0 Mailbox 23 ID1 Register */
+#define                  CAN0_MB24_DATA0  0xffc02f00   /* CAN Controller 0 Mailbox 24 Data 0 Register */
+#define                  CAN0_MB24_DATA1  0xffc02f04   /* CAN Controller 0 Mailbox 24 Data 1 Register */
+#define                  CAN0_MB24_DATA2  0xffc02f08   /* CAN Controller 0 Mailbox 24 Data 2 Register */
+#define                  CAN0_MB24_DATA3  0xffc02f0c   /* CAN Controller 0 Mailbox 24 Data 3 Register */
+#define                 CAN0_MB24_LENGTH  0xffc02f10   /* CAN Controller 0 Mailbox 24 Length Register */
+#define              CAN0_MB24_TIMESTAMP  0xffc02f14   /* CAN Controller 0 Mailbox 24 Timestamp Register */
+#define                    CAN0_MB24_ID0  0xffc02f18   /* CAN Controller 0 Mailbox 24 ID0 Register */
+#define                    CAN0_MB24_ID1  0xffc02f1c   /* CAN Controller 0 Mailbox 24 ID1 Register */
+#define                  CAN0_MB25_DATA0  0xffc02f20   /* CAN Controller 0 Mailbox 25 Data 0 Register */
+#define                  CAN0_MB25_DATA1  0xffc02f24   /* CAN Controller 0 Mailbox 25 Data 1 Register */
+#define                  CAN0_MB25_DATA2  0xffc02f28   /* CAN Controller 0 Mailbox 25 Data 2 Register */
+#define                  CAN0_MB25_DATA3  0xffc02f2c   /* CAN Controller 0 Mailbox 25 Data 3 Register */
+#define                 CAN0_MB25_LENGTH  0xffc02f30   /* CAN Controller 0 Mailbox 25 Length Register */
+#define              CAN0_MB25_TIMESTAMP  0xffc02f34   /* CAN Controller 0 Mailbox 25 Timestamp Register */
+#define                    CAN0_MB25_ID0  0xffc02f38   /* CAN Controller 0 Mailbox 25 ID0 Register */
+#define                    CAN0_MB25_ID1  0xffc02f3c   /* CAN Controller 0 Mailbox 25 ID1 Register */
+#define                  CAN0_MB26_DATA0  0xffc02f40   /* CAN Controller 0 Mailbox 26 Data 0 Register */
+#define                  CAN0_MB26_DATA1  0xffc02f44   /* CAN Controller 0 Mailbox 26 Data 1 Register */
+#define                  CAN0_MB26_DATA2  0xffc02f48   /* CAN Controller 0 Mailbox 26 Data 2 Register */
+#define                  CAN0_MB26_DATA3  0xffc02f4c   /* CAN Controller 0 Mailbox 26 Data 3 Register */
+#define                 CAN0_MB26_LENGTH  0xffc02f50   /* CAN Controller 0 Mailbox 26 Length Register */
+#define              CAN0_MB26_TIMESTAMP  0xffc02f54   /* CAN Controller 0 Mailbox 26 Timestamp Register */
+#define                    CAN0_MB26_ID0  0xffc02f58   /* CAN Controller 0 Mailbox 26 ID0 Register */
+#define                    CAN0_MB26_ID1  0xffc02f5c   /* CAN Controller 0 Mailbox 26 ID1 Register */
+#define                  CAN0_MB27_DATA0  0xffc02f60   /* CAN Controller 0 Mailbox 27 Data 0 Register */
+#define                  CAN0_MB27_DATA1  0xffc02f64   /* CAN Controller 0 Mailbox 27 Data 1 Register */
+#define                  CAN0_MB27_DATA2  0xffc02f68   /* CAN Controller 0 Mailbox 27 Data 2 Register */
+#define                  CAN0_MB27_DATA3  0xffc02f6c   /* CAN Controller 0 Mailbox 27 Data 3 Register */
+#define                 CAN0_MB27_LENGTH  0xffc02f70   /* CAN Controller 0 Mailbox 27 Length Register */
+#define              CAN0_MB27_TIMESTAMP  0xffc02f74   /* CAN Controller 0 Mailbox 27 Timestamp Register */
+#define                    CAN0_MB27_ID0  0xffc02f78   /* CAN Controller 0 Mailbox 27 ID0 Register */
+#define                    CAN0_MB27_ID1  0xffc02f7c   /* CAN Controller 0 Mailbox 27 ID1 Register */
+#define                  CAN0_MB28_DATA0  0xffc02f80   /* CAN Controller 0 Mailbox 28 Data 0 Register */
+#define                  CAN0_MB28_DATA1  0xffc02f84   /* CAN Controller 0 Mailbox 28 Data 1 Register */
+#define                  CAN0_MB28_DATA2  0xffc02f88   /* CAN Controller 0 Mailbox 28 Data 2 Register */
+#define                  CAN0_MB28_DATA3  0xffc02f8c   /* CAN Controller 0 Mailbox 28 Data 3 Register */
+#define                 CAN0_MB28_LENGTH  0xffc02f90   /* CAN Controller 0 Mailbox 28 Length Register */
+#define              CAN0_MB28_TIMESTAMP  0xffc02f94   /* CAN Controller 0 Mailbox 28 Timestamp Register */
+#define                    CAN0_MB28_ID0  0xffc02f98   /* CAN Controller 0 Mailbox 28 ID0 Register */
+#define                    CAN0_MB28_ID1  0xffc02f9c   /* CAN Controller 0 Mailbox 28 ID1 Register */
+#define                  CAN0_MB29_DATA0  0xffc02fa0   /* CAN Controller 0 Mailbox 29 Data 0 Register */
+#define                  CAN0_MB29_DATA1  0xffc02fa4   /* CAN Controller 0 Mailbox 29 Data 1 Register */
+#define                  CAN0_MB29_DATA2  0xffc02fa8   /* CAN Controller 0 Mailbox 29 Data 2 Register */
+#define                  CAN0_MB29_DATA3  0xffc02fac   /* CAN Controller 0 Mailbox 29 Data 3 Register */
+#define                 CAN0_MB29_LENGTH  0xffc02fb0   /* CAN Controller 0 Mailbox 29 Length Register */
+#define              CAN0_MB29_TIMESTAMP  0xffc02fb4   /* CAN Controller 0 Mailbox 29 Timestamp Register */
+#define                    CAN0_MB29_ID0  0xffc02fb8   /* CAN Controller 0 Mailbox 29 ID0 Register */
+#define                    CAN0_MB29_ID1  0xffc02fbc   /* CAN Controller 0 Mailbox 29 ID1 Register */
+#define                  CAN0_MB30_DATA0  0xffc02fc0   /* CAN Controller 0 Mailbox 30 Data 0 Register */
+#define                  CAN0_MB30_DATA1  0xffc02fc4   /* CAN Controller 0 Mailbox 30 Data 1 Register */
+#define                  CAN0_MB30_DATA2  0xffc02fc8   /* CAN Controller 0 Mailbox 30 Data 2 Register */
+#define                  CAN0_MB30_DATA3  0xffc02fcc   /* CAN Controller 0 Mailbox 30 Data 3 Register */
+#define                 CAN0_MB30_LENGTH  0xffc02fd0   /* CAN Controller 0 Mailbox 30 Length Register */
+#define              CAN0_MB30_TIMESTAMP  0xffc02fd4   /* CAN Controller 0 Mailbox 30 Timestamp Register */
+#define                    CAN0_MB30_ID0  0xffc02fd8   /* CAN Controller 0 Mailbox 30 ID0 Register */
+#define                    CAN0_MB30_ID1  0xffc02fdc   /* CAN Controller 0 Mailbox 30 ID1 Register */
+#define                  CAN0_MB31_DATA0  0xffc02fe0   /* CAN Controller 0 Mailbox 31 Data 0 Register */
+#define                  CAN0_MB31_DATA1  0xffc02fe4   /* CAN Controller 0 Mailbox 31 Data 1 Register */
+#define                  CAN0_MB31_DATA2  0xffc02fe8   /* CAN Controller 0 Mailbox 31 Data 2 Register */
+#define                  CAN0_MB31_DATA3  0xffc02fec   /* CAN Controller 0 Mailbox 31 Data 3 Register */
+#define                 CAN0_MB31_LENGTH  0xffc02ff0   /* CAN Controller 0 Mailbox 31 Length Register */
+#define              CAN0_MB31_TIMESTAMP  0xffc02ff4   /* CAN Controller 0 Mailbox 31 Timestamp Register */
+#define                    CAN0_MB31_ID0  0xffc02ff8   /* CAN Controller 0 Mailbox 31 ID0 Register */
+#define                    CAN0_MB31_ID1  0xffc02ffc   /* CAN Controller 0 Mailbox 31 ID1 Register */
+
+/* UART3 Registers */
+
+#define                        UART3_DLL  0xffc03100   /* Divisor Latch Low Byte */
+#define                        UART3_DLH  0xffc03104   /* Divisor Latch High Byte */
+#define                       UART3_GCTL  0xffc03108   /* Global Control Register */
+#define                        UART3_LCR  0xffc0310c   /* Line Control Register */
+#define                        UART3_MCR  0xffc03110   /* Modem Control Register */
+#define                        UART3_LSR  0xffc03114   /* Line Status Register */
+#define                        UART3_MSR  0xffc03118   /* Modem Status Register */
+#define                        UART3_SCR  0xffc0311c   /* Scratch Register */
+#define                    UART3_IER_SET  0xffc03120   /* Interrupt Enable Register Set */
+#define                  UART3_IER_CLEAR  0xffc03124   /* Interrupt Enable Register Clear */
+#define                        UART3_THR  0xffc03128   /* Transmit Hold Register */
+#define                        UART3_RBR  0xffc0312c   /* Receive Buffer Register */
+
+/* NFC Registers */
+
+#define                          NFC_CTL  0xffc03b00   /* NAND Control Register */
+#define                         NFC_STAT  0xffc03b04   /* NAND Status Register */
+#define                      NFC_IRQSTAT  0xffc03b08   /* NAND Interrupt Status Register */
+#define                      NFC_IRQMASK  0xffc03b0c   /* NAND Interrupt Mask Register */
+#define                         NFC_ECC0  0xffc03b10   /* NAND ECC Register 0 */
+#define                         NFC_ECC1  0xffc03b14   /* NAND ECC Register 1 */
+#define                         NFC_ECC2  0xffc03b18   /* NAND ECC Register 2 */
+#define                         NFC_ECC3  0xffc03b1c   /* NAND ECC Register 3 */
+#define                        NFC_COUNT  0xffc03b20   /* NAND ECC Count Register */
+#define                          NFC_RST  0xffc03b24   /* NAND ECC Reset Register */
+#define                        NFC_PGCTL  0xffc03b28   /* NAND Page Control Register */
+#define                         NFC_READ  0xffc03b2c   /* NAND Read Data Register */
+#define                         NFC_ADDR  0xffc03b40   /* NAND Address Register */
+#define                          NFC_CMD  0xffc03b44   /* NAND Command Register */
+#define                      NFC_DATA_WR  0xffc03b48   /* NAND Data Write Register */
+#define                      NFC_DATA_RD  0xffc03b4c   /* NAND Data Read Register */
+
+/* Counter Registers */
+
+#define                       CNT_CONFIG  0xffc04200   /* Configuration Register */
+#define                        CNT_IMASK  0xffc04204   /* Interrupt Mask Register */
+#define                       CNT_STATUS  0xffc04208   /* Status Register */
+#define                      CNT_COMMAND  0xffc0420c   /* Command Register */
+#define                     CNT_DEBOUNCE  0xffc04210   /* Debounce Register */
+#define                      CNT_COUNTER  0xffc04214   /* Counter Register */
+#define                          CNT_MAX  0xffc04218   /* Maximal Count Register */
+#define                          CNT_MIN  0xffc0421c   /* Minimal Count Register */
+
+/* OTP/FUSE Registers */
+
+#define                      OTP_CONTROL  0xffc04300   /* OTP/Fuse Control Register */
+#define                          OTP_BEN  0xffc04304   /* OTP/Fuse Byte Enable */
+#define                       OTP_STATUS  0xffc04308   /* OTP/Fuse Status */
+#define                       OTP_TIMING  0xffc0430c   /* OTP/Fuse Access Timing */
+
+/* Security Registers */
+
+#define                    SECURE_SYSSWT  0xffc04320   /* Secure System Switches */
+#define                   SECURE_CONTROL  0xffc04324   /* Secure Control */
+#define                    SECURE_STATUS  0xffc04328   /* Secure Status */
+
+/* DMA Peripheral Mux Register */
+
+#define                    DMAC1_PERIMUX  0xffc04340   /* DMA Controller 1 Peripheral Multiplexer Register */
+
+/* OTP Read/Write Data Buffer Registers */
+
+#define                        OTP_DATA0  0xffc04380   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA1  0xffc04384   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA2  0xffc04388   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA3  0xffc0438c   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+
+/* Handshake MDMA is not defined in the shared file because it is not available on the ADSP-BF542 processor */
+
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* SIC_IMASK Masks */
+#define SIC_UNMASK_ALL         0x00000000	/* Unmask all peripheral interrupts */
+#define SIC_MASK_ALL           0xFFFFFFFF	/* Mask all peripheral interrupts */
+#define SIC_MASK(x)	       (1 << (x))	/* Mask Peripheral #x interrupt */
+#define SIC_UNMASK(x) (0xFFFFFFFF ^ (1 << (x)))	/* Unmask Peripheral #x interrupt */
+
+/* SIC_IWR Masks */
+#define IWR_DISABLE_ALL        0x00000000	/* Wakeup Disable all peripherals */
+#define IWR_ENABLE_ALL         0xFFFFFFFF	/* Wakeup Enable all peripherals */
+#define IWR_ENABLE(x)	       (1 << (x))	/* Wakeup Enable Peripheral #x */
+#define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x)))	/* Wakeup Disable Peripheral #x */
+
+/* Bit masks for SIC_IAR0 */
+
+#define            PLL_WAKEUP  0x1        /* PLL Wakeup */
+
+/* Bit masks for SIC_IWR0, SIC_IMASK0, SIC_ISR0 */
+
+#define              DMA0_ERR  0x2        /* DMA Controller 0 Error */
+#define             EPPI0_ERR  0x4        /* EPPI0 Error */
+#define            SPORT0_ERR  0x8        /* SPORT0 Error */
+#define            SPORT1_ERR  0x10       /* SPORT1 Error */
+#define              SPI0_ERR  0x20       /* SPI0 Error */
+#define             UART0_ERR  0x40       /* UART0 Error */
+#define                   RTC  0x80       /* Real-Time Clock */
+#define                 DMA12  0x100      /* DMA Channel 12 */
+#define                  DMA0  0x200      /* DMA Channel 0 */
+#define                  DMA1  0x400      /* DMA Channel 1 */
+#define                  DMA2  0x800      /* DMA Channel 2 */
+#define                  DMA3  0x1000     /* DMA Channel 3 */
+#define                  DMA4  0x2000     /* DMA Channel 4 */
+#define                  DMA6  0x4000     /* DMA Channel 6 */
+#define                  DMA7  0x8000     /* DMA Channel 7 */
+#define                 PINT0  0x80000    /* Pin Interrupt 0 */
+#define                 PINT1  0x100000   /* Pin Interrupt 1 */
+#define                 MDMA0  0x200000   /* Memory DMA Stream 0 */
+#define                 MDMA1  0x400000   /* Memory DMA Stream 1 */
+#define                  WDOG  0x800000   /* Watchdog Timer */
+#define              DMA1_ERR  0x1000000  /* DMA Controller 1 Error */
+#define            SPORT2_ERR  0x2000000  /* SPORT2 Error */
+#define            SPORT3_ERR  0x4000000  /* SPORT3 Error */
+#define               MXVR_SD  0x8000000  /* MXVR Synchronous Data */
+#define              SPI1_ERR  0x10000000 /* SPI1 Error */
+#define              SPI2_ERR  0x20000000 /* SPI2 Error */
+#define             UART1_ERR  0x40000000 /* UART1 Error */
+#define             UART2_ERR  0x80000000 /* UART2 Error */
+
+/* Bit masks for SIC_IWR1, SIC_IMASK1, SIC_ISR1 */
+
+#define              CAN0_ERR  0x1        /* CAN0 Error */
+#define                 DMA18  0x2        /* DMA Channel 18 */
+#define                 DMA19  0x4        /* DMA Channel 19 */
+#define                 DMA20  0x8        /* DMA Channel 20 */
+#define                 DMA21  0x10       /* DMA Channel 21 */
+#define                 DMA13  0x20       /* DMA Channel 13 */
+#define                 DMA14  0x40       /* DMA Channel 14 */
+#define                  DMA5  0x80       /* DMA Channel 5 */
+#define                 DMA23  0x100      /* DMA Channel 23 */
+#define                  DMA8  0x200      /* DMA Channel 8 */
+#define                  DMA9  0x400      /* DMA Channel 9 */
+#define                 DMA10  0x800      /* DMA Channel 10 */
+#define                 DMA11  0x1000     /* DMA Channel 11 */
+#define                  TWI0  0x2000     /* TWI0 */
+#define                  TWI1  0x4000     /* TWI1 */
+#define               CAN0_RX  0x8000     /* CAN0 Receive */
+#define               CAN0_TX  0x10000    /* CAN0 Transmit */
+#define                 MDMA2  0x20000    /* Memory DMA Stream 0 */
+#define                 MDMA3  0x40000    /* Memory DMA Stream 1 */
+#define             MXVR_STAT  0x80000    /* MXVR Status */
+#define               MXVR_CM  0x100000   /* MXVR Control Message */
+#define               MXVR_AP  0x200000   /* MXVR Asynchronous Packet */
+#define             EPPI1_ERR  0x400000   /* EPPI1 Error */
+#define             EPPI2_ERR  0x800000   /* EPPI2 Error */
+#define             UART3_ERR  0x1000000  /* UART3 Error */
+#define              HOST_ERR  0x2000000  /* Host DMA Port Error */
+#define               USB_ERR  0x4000000  /* USB Error */
+#define              PIXC_ERR  0x8000000  /* Pixel Compositor Error */
+#define               NFC_ERR  0x10000000 /* Nand Flash Controller Error */
+#define             ATAPI_ERR  0x20000000 /* ATAPI Error */
+#define              CAN1_ERR  0x40000000 /* CAN1 Error */
+#define             DMAR0_ERR  0x80000000 /* DMAR0 Overflow Error */
+#define             DMAR1_ERR  0x80000000 /* DMAR1 Overflow Error */
+#define                 DMAR0  0x80000000 /* DMAR0 Block */
+#define                 DMAR1  0x80000000 /* DMAR1 Block */
+
+/* Bit masks for SIC_IWR2, SIC_IMASK2, SIC_ISR2 */
+
+#define                 DMA15  0x1        /* DMA Channel 15 */
+#define                 DMA16  0x2        /* DMA Channel 16 */
+#define                 DMA17  0x4        /* DMA Channel 17 */
+#define                 DMA22  0x8        /* DMA Channel 22 */
+#define                   CNT  0x10       /* Counter */
+#define                   KEY  0x20       /* Keypad */
+#define               CAN1_RX  0x40       /* CAN1 Receive */
+#define               CAN1_TX  0x80       /* CAN1 Transmit */
+#define             SDH_INT_MASK0  0x100      /* SDH Mask 0 */
+#define             SDH_INT_MASK1  0x200      /* SDH Mask 1 */
+#define              USB_EINT  0x400      /* USB Exception */
+#define              USB_INT0  0x800      /* USB Interrupt 0 */
+#define              USB_INT1  0x1000     /* USB Interrupt 1 */
+#define              USB_INT2  0x2000     /* USB Interrupt 2 */
+#define            USB_DMAINT  0x4000     /* USB DMA */
+#define                OTPSEC  0x8000     /* OTP Access Complete */
+#define                TIMER0  0x400000   /* Timer 0 */
+#define                TIMER1  0x800000   /* Timer 1 */
+#define                TIMER2  0x1000000  /* Timer 2 */
+#define                TIMER3  0x2000000  /* Timer 3 */
+#define                TIMER4  0x4000000  /* Timer 4 */
+#define                TIMER5  0x8000000  /* Timer 5 */
+#define                TIMER6  0x10000000 /* Timer 6 */
+#define                TIMER7  0x20000000 /* Timer 7 */
+#define                 PINT2  0x40000000 /* Pin Interrupt 2 */
+#define                 PINT3  0x80000000 /* Pin Interrupt 3 */
+
+/* Bit masks for DMAx_CONFIG, MDMA_Sx_CONFIG, MDMA_Dx_CONFIG */
+
+#define                     DMAEN  0x1        /* DMA Channel Enable */
+#define                       WNR  0x2        /* DMA Direction */
+#define                  WDSIZE_8  0x0        /* Transfer Word Size = 8 */
+#define                 WDSIZE_16  0x4        /* Transfer Word Size = 16 */
+#define                 WDSIZE_32  0x8        /* Transfer Word Size = 32 */
+#define                     DMA2D  0x10       /* DMA Mode */
+#define                   RESTART  0x20       /* Work Unit Transitions */
+#define                    DI_SEL  0x40       /* Data Interrupt Timing Select */
+#define                     DI_EN  0x80       /* Data Interrupt Enable */
+#define                    NDSIZE  0xf00      /* Flex Descriptor Size */
+#define                   DMAFLOW  0xf000     /* Next Operation */
+
+/* Bit masks for DMAx_IRQ_STATUS, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */
+
+#define                  DMA_DONE  0x1        /* DMA Completion Interrupt Status */
+#define                   DMA_ERR  0x2        /* DMA Error Interrupt Status */
+#define                    DFETCH  0x4        /* DMA Descriptor Fetch */
+#define                   DMA_RUN  0x8        /* DMA Channel Running */
+
+/* Bit masks for DMAx_PERIPHERAL_MAP, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */
+
+#define                     CTYPE  0x40       /* DMA Channel Type */
+#define                      PMAP  0xf000     /* Peripheral Mapped To This Channel */
+
+/* Bit masks for DMACx_TCPER */
+
+#define        DCB_TRAFFIC_PERIOD  0xf        /* DCB Traffic Control Period */
+#define        DEB_TRAFFIC_PERIOD  0xf0       /* DEB Traffic Control Period */
+#define        DAB_TRAFFIC_PERIOD  0x700      /* DAB Traffic Control Period */
+#define   MDMA_ROUND_ROBIN_PERIOD  0xf800     /* MDMA Round Robin Period */
+
+/* Bit masks for DMACx_TCCNT */
+
+#define         DCB_TRAFFIC_COUNT  0xf        /* DCB Traffic Control Count */
+#define         DEB_TRAFFIC_COUNT  0xf0       /* DEB Traffic Control Count */
+#define         DAB_TRAFFIC_COUNT  0x700      /* DAB Traffic Control Count */
+#define    MDMA_ROUND_ROBIN_COUNT  0xf800     /* MDMA Round Robin Count */
+
+/* Bit masks for DMAC1_PERIMUX */
+
+#define                   PMUXSDH  0x1        /* Peripheral Select for DMA22 channel */
+
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
+/* EBIU_AMGCTL Masks																	*/
+#define AMCKEN			0x0001		/* Enable CLKOUT									*/
+#define	AMBEN_NONE		0x0000		/* All Banks Disabled								*/
+#define AMBEN_B0		0x0002		/* Enable Async Memory Bank 0 only					*/
+#define AMBEN_B0_B1		0x0004		/* Enable Async Memory Banks 0 & 1 only				*/
+#define AMBEN_B0_B1_B2	0x0006		/* Enable Async Memory Banks 0, 1, and 2			*/
+#define AMBEN_ALL		0x0008		/* Enable Async Memory Banks (all) 0, 1, 2, and 3	*/
+
+
+/* Bit masks for EBIU_AMBCTL0 */
+
+#define                   B0RDYEN  0x1        /* Bank 0 ARDY Enable */
+#define                  B0RDYPOL  0x2        /* Bank 0 ARDY Polarity */
+#define                      B0TT  0xc        /* Bank 0 transition time */
+#define                      B0ST  0x30       /* Bank 0 Setup time */
+#define                      B0HT  0xc0       /* Bank 0 Hold time */
+#define                     B0RAT  0xf00      /* Bank 0 Read access time */
+#define                     B0WAT  0xf000     /* Bank 0 write access time */
+#define                   B1RDYEN  0x10000    /* Bank 1 ARDY Enable */
+#define                  B1RDYPOL  0x20000    /* Bank 1 ARDY Polarity */
+#define                      B1TT  0xc0000    /* Bank 1 transition time */
+#define                      B1ST  0x300000   /* Bank 1 Setup time */
+#define                      B1HT  0xc00000   /* Bank 1 Hold time */
+#define                     B1RAT  0xf000000  /* Bank 1 Read access time */
+#define                     B1WAT  0xf0000000 /* Bank 1 write access time */
+
+/* Bit masks for EBIU_AMBCTL1 */
+
+#define                   B2RDYEN  0x1        /* Bank 2 ARDY Enable */
+#define                  B2RDYPOL  0x2        /* Bank 2 ARDY Polarity */
+#define                      B2TT  0xc        /* Bank 2 transition time */
+#define                      B2ST  0x30       /* Bank 2 Setup time */
+#define                      B2HT  0xc0       /* Bank 2 Hold time */
+#define                     B2RAT  0xf00      /* Bank 2 Read access time */
+#define                     B2WAT  0xf000     /* Bank 2 write access time */
+#define                   B3RDYEN  0x10000    /* Bank 3 ARDY Enable */
+#define                  B3RDYPOL  0x20000    /* Bank 3 ARDY Polarity */
+#define                      B3TT  0xc0000    /* Bank 3 transition time */
+#define                      B3ST  0x300000   /* Bank 3 Setup time */
+#define                      B3HT  0xc00000   /* Bank 3 Hold time */
+#define                     B3RAT  0xf000000  /* Bank 3 Read access time */
+#define                     B3WAT  0xf0000000 /* Bank 3 write access time */
+
+/* Bit masks for EBIU_MBSCTL */
+
+#define                  AMSB0CTL  0x3        /* Async Memory Bank 0 select */
+#define                  AMSB1CTL  0xc        /* Async Memory Bank 1 select */
+#define                  AMSB2CTL  0x30       /* Async Memory Bank 2 select */
+#define                  AMSB3CTL  0xc0       /* Async Memory Bank 3 select */
+
+/* Bit masks for EBIU_MODE */
+
+#define                    B0MODE  0x3        /* Async Memory Bank 0 Access Mode */
+#define                    B1MODE  0xc        /* Async Memory Bank 1 Access Mode */
+#define                    B2MODE  0x30       /* Async Memory Bank 2 Access Mode */
+#define                    B3MODE  0xc0       /* Async Memory Bank 3 Access Mode */
+
+/* Bit masks for EBIU_FCTL */
+
+#define               TESTSETLOCK  0x1        /* Test set lock */
+#define                      BCLK  0x6        /* Burst clock frequency */
+#define                      PGWS  0x38       /* Page wait states */
+#define                      PGSZ  0x40       /* Page size */
+#define                      RDDL  0x380      /* Read data delay */
+
+/* Bit masks for EBIU_ARBSTAT */
+
+#define                   ARBSTAT  0x1        /* Arbitration status */
+#define                    BGSTAT  0x2        /* Bus grant status */
+
+/* Bit masks for EBIU_DDRCTL0 */
+
+#define                     TREFI  0x3fff     /* Refresh Interval */
+#define                      TRFC  0x3c000    /* Auto-refresh command period */
+#define                       TRP  0x3c0000   /* Pre charge-to-active command period */
+#define                      TRAS  0x3c00000  /* Min Active-to-pre charge time */
+#define                       TRC  0x3c000000 /* Active-to-active time */
+
+/* Bit masks for EBIU_DDRCTL1 */
+
+#define                      TRCD  0xf        /* Active-to-Read/write delay */
+#define                       MRD  0xf0       /* Mode register set to active */
+#define                       TWR  0x300      /* Write Recovery time */
+#define               DDRDATWIDTH  0x3000     /* DDR data width */
+#define                  EXTBANKS  0xc000     /* External banks */
+#define               DDRDEVWIDTH  0x30000    /* DDR device width */
+#define                DDRDEVSIZE  0xc0000    /* DDR device size */
+#define                     TWWTR  0xf0000000 /* Write-to-read delay */
+
+/* Bit masks for EBIU_DDRCTL2 */
+
+#define               BURSTLENGTH  0x7        /* Burst length */
+#define                CASLATENCY  0x70       /* CAS latency */
+#define                  DLLRESET  0x100      /* DLL Reset */
+#define                      REGE  0x1000     /* Register mode enable */
+
+/* Bit masks for EBIU_DDRCTL3 */
+
+#define                      PASR  0x7        /* Partial array self-refresh */
+
+/* Bit masks for EBIU_DDRQUE */
+
+#define                DEB1_PFLEN  0x3        /* Pre fetch length for DEB1 accesses */
+#define                DEB2_PFLEN  0xc        /* Pre fetch length for DEB2 accesses */
+#define                DEB3_PFLEN  0x30       /* Pre fetch length for DEB3 accesses */
+#define          DEB_ARB_PRIORITY  0x700      /* Arbitration between DEB busses */
+#define               DEB1_URGENT  0x1000     /* DEB1 Urgent */
+#define               DEB2_URGENT  0x2000     /* DEB2 Urgent */
+#define               DEB3_URGENT  0x4000     /* DEB3 Urgent */
+
+/* Bit masks for EBIU_ERRMST */
+
+#define                DEB1_ERROR  0x1        /* DEB1 Error */
+#define                DEB2_ERROR  0x2        /* DEB2 Error */
+#define                DEB3_ERROR  0x4        /* DEB3 Error */
+#define                CORE_ERROR  0x8        /* Core error */
+#define                DEB_MERROR  0x10       /* DEB1 Error (2nd) */
+#define               DEB2_MERROR  0x20       /* DEB2 Error (2nd) */
+#define               DEB3_MERROR  0x40       /* DEB3 Error (2nd) */
+#define               CORE_MERROR  0x80       /* Core Error (2nd) */
+
+/* Bit masks for EBIU_ERRADD */
+
+#define             ERROR_ADDRESS  0xffffffff /* Error Address */
+
+/* Bit masks for EBIU_RSTCTL */
+
+#define                 DDRSRESET  0x1        /* DDR soft reset */
+#define               PFTCHSRESET  0x4        /* DDR prefetch reset */
+#define                     SRREQ  0x8        /* Self-refresh request */
+#define                     SRACK  0x10       /* Self-refresh acknowledge */
+#define                MDDRENABLE  0x20       /* Mobile DDR enable */
+
+/* Bit masks for EBIU_DDRBRC0 */
+
+#define                      BRC0  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBRC1 */
+
+#define                      BRC1  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBRC2 */
+
+#define                      BRC2  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBRC3 */
+
+#define                      BRC3  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBRC4 */
+
+#define                      BRC4  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBRC5 */
+
+#define                      BRC5  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBRC6 */
+
+#define                      BRC6  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBRC7 */
+
+#define                      BRC7  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBWC0 */
+
+#define                      BWC0  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBWC1 */
+
+#define                      BWC1  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBWC2 */
+
+#define                      BWC2  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBWC3 */
+
+#define                      BWC3  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBWC4 */
+
+#define                      BWC4  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBWC5 */
+
+#define                      BWC5  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBWC6 */
+
+#define                      BWC6  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRBWC7 */
+
+#define                      BWC7  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRACCT */
+
+#define                      ACCT  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRTACT */
+
+#define                      TECT  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRARCT */
+
+#define                      ARCT  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRGC0 */
+
+#define                       GC0  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRGC1 */
+
+#define                       GC1  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRGC2 */
+
+#define                       GC2  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRGC3 */
+
+#define                       GC3  0xffffffff /* Count */
+
+/* Bit masks for EBIU_DDRMCEN */
+
+#define                B0WCENABLE  0x1        /* Bank 0 write count enable */
+#define                B1WCENABLE  0x2        /* Bank 1 write count enable */
+#define                B2WCENABLE  0x4        /* Bank 2 write count enable */
+#define                B3WCENABLE  0x8        /* Bank 3 write count enable */
+#define                B4WCENABLE  0x10       /* Bank 4 write count enable */
+#define                B5WCENABLE  0x20       /* Bank 5 write count enable */
+#define                B6WCENABLE  0x40       /* Bank 6 write count enable */
+#define                B7WCENABLE  0x80       /* Bank 7 write count enable */
+#define                B0RCENABLE  0x100      /* Bank 0 read count enable */
+#define                B1RCENABLE  0x200      /* Bank 1 read count enable */
+#define                B2RCENABLE  0x400      /* Bank 2 read count enable */
+#define                B3RCENABLE  0x800      /* Bank 3 read count enable */
+#define                B4RCENABLE  0x1000     /* Bank 4 read count enable */
+#define                B5RCENABLE  0x2000     /* Bank 5 read count enable */
+#define                B6RCENABLE  0x4000     /* Bank 6 read count enable */
+#define                B7RCENABLE  0x8000     /* Bank 7 read count enable */
+#define             ROWACTCENABLE  0x10000    /* DDR Row activate count enable */
+#define                RWTCENABLE  0x20000    /* DDR R/W Turn around count enable */
+#define                 ARCENABLE  0x40000    /* DDR Auto-refresh count enable */
+#define                 GC0ENABLE  0x100000   /* DDR Grant count 0 enable */
+#define                 GC1ENABLE  0x200000   /* DDR Grant count 1 enable */
+#define                 GC2ENABLE  0x400000   /* DDR Grant count 2 enable */
+#define                 GC3ENABLE  0x800000   /* DDR Grant count 3 enable */
+#define                 GCCONTROL  0x3000000  /* DDR Grant Count Control */
+
+/* Bit masks for EBIU_DDRMCCL */
+
+#define                 CB0WCOUNT  0x1        /* Clear write count 0 */
+#define                 CB1WCOUNT  0x2        /* Clear write count 1 */
+#define                 CB2WCOUNT  0x4        /* Clear write count 2 */
+#define                 CB3WCOUNT  0x8        /* Clear write count 3 */
+#define                 CB4WCOUNT  0x10       /* Clear write count 4 */
+#define                 CB5WCOUNT  0x20       /* Clear write count 5 */
+#define                 CB6WCOUNT  0x40       /* Clear write count 6 */
+#define                 CB7WCOUNT  0x80       /* Clear write count 7 */
+#define                  CBRCOUNT  0x100      /* Clear read count 0 */
+#define                 CB1RCOUNT  0x200      /* Clear read count 1 */
+#define                 CB2RCOUNT  0x400      /* Clear read count 2 */
+#define                 CB3RCOUNT  0x800      /* Clear read count 3 */
+#define                 CB4RCOUNT  0x1000     /* Clear read count 4 */
+#define                 CB5RCOUNT  0x2000     /* Clear read count 5 */
+#define                 CB6RCOUNT  0x4000     /* Clear read count 6 */
+#define                 CB7RCOUNT  0x8000     /* Clear read count 7 */
+#define                  CRACOUNT  0x10000    /* Clear row activation count */
+#define                CRWTACOUNT  0x20000    /* Clear R/W turn-around count */
+#define                  CARCOUNT  0x40000    /* Clear auto-refresh count */
+#define                  CG0COUNT  0x100000   /* Clear grant count 0 */
+#define                  CG1COUNT  0x200000   /* Clear grant count 1 */
+#define                  CG2COUNT  0x400000   /* Clear grant count 2 */
+#define                  CG3COUNT  0x800000   /* Clear grant count 3 */
+
+/* Bit masks for (PORTx is PORTA - PORTJ) includes PORTx_FER, PORTx_SET, PORTx_CLEAR, PORTx_DIR_SET, PORTx_DIR_CLEAR, PORTx_INEN */
+
+#define                       Px0  0x1        /* GPIO 0 */
+#define                       Px1  0x2        /* GPIO 1 */
+#define                       Px2  0x4        /* GPIO 2 */
+#define                       Px3  0x8        /* GPIO 3 */
+#define                       Px4  0x10       /* GPIO 4 */
+#define                       Px5  0x20       /* GPIO 5 */
+#define                       Px6  0x40       /* GPIO 6 */
+#define                       Px7  0x80       /* GPIO 7 */
+#define                       Px8  0x100      /* GPIO 8 */
+#define                       Px9  0x200      /* GPIO 9 */
+#define                      Px10  0x400      /* GPIO 10 */
+#define                      Px11  0x800      /* GPIO 11 */
+#define                      Px12  0x1000     /* GPIO 12 */
+#define                      Px13  0x2000     /* GPIO 13 */
+#define                      Px14  0x4000     /* GPIO 14 */
+#define                      Px15  0x8000     /* GPIO 15 */
+
+/* Bit masks for PORTA_MUX - PORTJ_MUX */
+
+#define                      PxM0  0x3        /* GPIO Mux 0 */
+#define                      PxM1  0xc        /* GPIO Mux 1 */
+#define                      PxM2  0x30       /* GPIO Mux 2 */
+#define                      PxM3  0xc0       /* GPIO Mux 3 */
+#define                      PxM4  0x300      /* GPIO Mux 4 */
+#define                      PxM5  0xc00      /* GPIO Mux 5 */
+#define                      PxM6  0x3000     /* GPIO Mux 6 */
+#define                      PxM7  0xc000     /* GPIO Mux 7 */
+#define                      PxM8  0x30000    /* GPIO Mux 8 */
+#define                      PxM9  0xc0000    /* GPIO Mux 9 */
+#define                     PxM10  0x300000   /* GPIO Mux 10 */
+#define                     PxM11  0xc00000   /* GPIO Mux 11 */
+#define                     PxM12  0x3000000  /* GPIO Mux 12 */
+#define                     PxM13  0xc000000  /* GPIO Mux 13 */
+#define                     PxM14  0x30000000 /* GPIO Mux 14 */
+#define                     PxM15  0xc0000000 /* GPIO Mux 15 */
+
+
+/* Bit masks for PINTx_MASK_SET/CLEAR, PINTx_REQUEST, PINTx_LATCH, PINTx_EDGE_SET/CLEAR, PINTx_INVERT_SET/CLEAR, PINTx_PINTSTATE */
+
+#define                       IB0  0x1        /* Interrupt Bit 0 */
+#define                       IB1  0x2        /* Interrupt Bit 1 */
+#define                       IB2  0x4        /* Interrupt Bit 2 */
+#define                       IB3  0x8        /* Interrupt Bit 3 */
+#define                       IB4  0x10       /* Interrupt Bit 4 */
+#define                       IB5  0x20       /* Interrupt Bit 5 */
+#define                       IB6  0x40       /* Interrupt Bit 6 */
+#define                       IB7  0x80       /* Interrupt Bit 7 */
+#define                       IB8  0x100      /* Interrupt Bit 8 */
+#define                       IB9  0x200      /* Interrupt Bit 9 */
+#define                      IB10  0x400      /* Interrupt Bit 10 */
+#define                      IB11  0x800      /* Interrupt Bit 11 */
+#define                      IB12  0x1000     /* Interrupt Bit 12 */
+#define                      IB13  0x2000     /* Interrupt Bit 13 */
+#define                      IB14  0x4000     /* Interrupt Bit 14 */
+#define                      IB15  0x8000     /* Interrupt Bit 15 */
+
+/* Bit masks for TIMERx_CONFIG */
+
+#define                     TMODE  0x3        /* Timer Mode */
+#define                  PULSE_HI  0x4        /* Pulse Polarity */
+#define                PERIOD_CNT  0x8        /* Period Count */
+#define                   IRQ_ENA  0x10       /* Interrupt Request Enable */
+#define                   TIN_SEL  0x20       /* Timer Input Select */
+#define                   OUT_DIS  0x40       /* Output Pad Disable */
+#define                   CLK_SEL  0x80       /* Timer Clock Select */
+#define                 TOGGLE_HI  0x100      /* Toggle Mode */
+#define                   EMU_RUN  0x200      /* Emulation Behavior Select */
+#define                   ERR_TYP  0xc000     /* Error Type */
+
+/* Bit masks for TIMER_ENABLE0 */
+
+#define                    TIMEN0  0x1        /* Timer 0 Enable */
+#define                    TIMEN1  0x2        /* Timer 1 Enable */
+#define                    TIMEN2  0x4        /* Timer 2 Enable */
+#define                    TIMEN3  0x8        /* Timer 3 Enable */
+#define                    TIMEN4  0x10       /* Timer 4 Enable */
+#define                    TIMEN5  0x20       /* Timer 5 Enable */
+#define                    TIMEN6  0x40       /* Timer 6 Enable */
+#define                    TIMEN7  0x80       /* Timer 7 Enable */
+
+/* Bit masks for TIMER_DISABLE0 */
+
+#define                   TIMDIS0  0x1        /* Timer 0 Disable */
+#define                   TIMDIS1  0x2        /* Timer 1 Disable */
+#define                   TIMDIS2  0x4        /* Timer 2 Disable */
+#define                   TIMDIS3  0x8        /* Timer 3 Disable */
+#define                   TIMDIS4  0x10       /* Timer 4 Disable */
+#define                   TIMDIS5  0x20       /* Timer 5 Disable */
+#define                   TIMDIS6  0x40       /* Timer 6 Disable */
+#define                   TIMDIS7  0x80       /* Timer 7 Disable */
+
+/* Bit masks for TIMER_STATUS0 */
+
+#define                    TIMIL0  0x1        /* Timer 0 Interrupt */
+#define                    TIMIL1  0x2        /* Timer 1 Interrupt */
+#define                    TIMIL2  0x4        /* Timer 2 Interrupt */
+#define                    TIMIL3  0x8        /* Timer 3 Interrupt */
+#define                 TOVF_ERR0  0x10       /* Timer 0 Counter Overflow */
+#define                 TOVF_ERR1  0x20       /* Timer 1 Counter Overflow */
+#define                 TOVF_ERR2  0x40       /* Timer 2 Counter Overflow */
+#define                 TOVF_ERR3  0x80       /* Timer 3 Counter Overflow */
+#define                     TRUN0  0x1000     /* Timer 0 Slave Enable Status */
+#define                     TRUN1  0x2000     /* Timer 1 Slave Enable Status */
+#define                     TRUN2  0x4000     /* Timer 2 Slave Enable Status */
+#define                     TRUN3  0x8000     /* Timer 3 Slave Enable Status */
+#define                    TIMIL4  0x10000    /* Timer 4 Interrupt */
+#define                    TIMIL5  0x20000    /* Timer 5 Interrupt */
+#define                    TIMIL6  0x40000    /* Timer 6 Interrupt */
+#define                    TIMIL7  0x80000    /* Timer 7 Interrupt */
+#define                 TOVF_ERR4  0x100000   /* Timer 4 Counter Overflow */
+#define                 TOVF_ERR5  0x200000   /* Timer 5 Counter Overflow */
+#define                 TOVF_ERR6  0x400000   /* Timer 6 Counter Overflow */
+#define                 TOVF_ERR7  0x800000   /* Timer 7 Counter Overflow */
+#define                     TRUN4  0x10000000 /* Timer 4 Slave Enable Status */
+#define                     TRUN5  0x20000000 /* Timer 5 Slave Enable Status */
+#define                     TRUN6  0x40000000 /* Timer 6 Slave Enable Status */
+#define                     TRUN7  0x80000000 /* Timer 7 Slave Enable Status */
+
+/* Bit masks for WDOG_CTL */
+
+#define                      WDEV  0x6        /* Watchdog Event */
+#define                      WDEN  0xff0      /* Watchdog Enable */
+#define                      WDRO  0x8000     /* Watchdog Rolled Over */
+
+/* Bit masks for CNT_CONFIG */
+
+#define                      CNTE  0x1        /* Counter Enable */
+#define                      DEBE  0x2        /* Debounce Enable */
+#define                    CDGINV  0x10       /* CDG Pin Polarity Invert */
+#define                    CUDINV  0x20       /* CUD Pin Polarity Invert */
+#define                    CZMINV  0x40       /* CZM Pin Polarity Invert */
+#define                   CNTMODE  0x700      /* Counter Operating Mode */
+#define                      ZMZC  0x800      /* CZM Zeroes Counter Enable */
+#define                   BNDMODE  0x3000     /* Boundary register Mode */
+#define                    INPDIS  0x8000     /* CUG and CDG Input Disable */
+
+/* Bit masks for CNT_IMASK */
+
+#define                      ICIE  0x1        /* Illegal Gray/Binary Code Interrupt Enable */
+#define                      UCIE  0x2        /* Up count Interrupt Enable */
+#define                      DCIE  0x4        /* Down count Interrupt Enable */
+#define                    MINCIE  0x8        /* Min Count Interrupt Enable */
+#define                    MAXCIE  0x10       /* Max Count Interrupt Enable */
+#define                   COV31IE  0x20       /* Bit 31 Overflow Interrupt Enable */
+#define                   COV15IE  0x40       /* Bit 15 Overflow Interrupt Enable */
+#define                   CZEROIE  0x80       /* Count to Zero Interrupt Enable */
+#define                     CZMIE  0x100      /* CZM Pin Interrupt Enable */
+#define                    CZMEIE  0x200      /* CZM Error Interrupt Enable */
+#define                    CZMZIE  0x400      /* CZM Zeroes Counter Interrupt Enable */
+
+/* Bit masks for CNT_STATUS */
+
+#define                      ICII  0x1        /* Illegal Gray/Binary Code Interrupt Identifier */
+#define                      UCII  0x2        /* Up count Interrupt Identifier */
+#define                      DCII  0x4        /* Down count Interrupt Identifier */
+#define                    MINCII  0x8        /* Min Count Interrupt Identifier */
+#define                    MAXCII  0x10       /* Max Count Interrupt Identifier */
+#define                   COV31II  0x20       /* Bit 31 Overflow Interrupt Identifier */
+#define                   COV15II  0x40       /* Bit 15 Overflow Interrupt Identifier */
+#define                   CZEROII  0x80       /* Count to Zero Interrupt Identifier */
+#define                     CZMII  0x100      /* CZM Pin Interrupt Identifier */
+#define                    CZMEII  0x200      /* CZM Error Interrupt Identifier */
+#define                    CZMZII  0x400      /* CZM Zeroes Counter Interrupt Identifier */
+
+/* Bit masks for CNT_COMMAND */
+
+#define                    W1LCNT  0xf        /* Load Counter Register */
+#define                    W1LMIN  0xf0       /* Load Min Register */
+#define                    W1LMAX  0xf00      /* Load Max Register */
+#define                  W1ZMONCE  0x1000     /* Enable CZM Clear Counter Once */
+
+/* Bit masks for CNT_DEBOUNCE */
+
+#define                 DPRESCALE  0xf        /* Load Counter Register */
+
+/* Bit masks for RTC_STAT */
+
+#define                   SECONDS  0x3f       /* Seconds */
+#define                   MINUTES  0xfc0      /* Minutes */
+#define                     HOURS  0x1f000    /* Hours */
+#define               DAY_COUNTER  0xfffe0000 /* Day Counter */
+
+/* Bit masks for RTC_ICTL */
+
+#define STOPWATCH_INTERRUPT_ENABLE  0x1        /* Stopwatch Interrupt Enable */
+#define    ALARM_INTERRUPT_ENABLE  0x2        /* Alarm Interrupt Enable */
+#define  SECONDS_INTERRUPT_ENABLE  0x4        /* Seconds Interrupt Enable */
+#define  MINUTES_INTERRUPT_ENABLE  0x8        /* Minutes Interrupt Enable */
+#define    HOURS_INTERRUPT_ENABLE  0x10       /* Hours Interrupt Enable */
+#define TWENTY_FOUR_HOURS_INTERRUPT_ENABLE  0x20       /* 24 Hours Interrupt Enable */
+#define DAY_ALARM_INTERRUPT_ENABLE  0x40       /* Day Alarm Interrupt Enable */
+#define WRITE_COMPLETE_INTERRUPT_ENABLE  0x8000     /* Write Complete Interrupt Enable */
+
+/* Bit masks for RTC_ISTAT */
+
+#define      STOPWATCH_EVENT_FLAG  0x1        /* Stopwatch Event Flag */
+#define          ALARM_EVENT_FLAG  0x2        /* Alarm Event Flag */
+#define        SECONDS_EVENT_FLAG  0x4        /* Seconds Event Flag */
+#define        MINUTES_EVENT_FLAG  0x8        /* Minutes Event Flag */
+#define          HOURS_EVENT_FLAG  0x10       /* Hours Event Flag */
+#define TWENTY_FOUR_HOURS_EVENT_FLAG  0x20       /* 24 Hours Event Flag */
+#define      DAY_ALARM_EVENT_FLAG  0x40       /* Day Alarm Event Flag */
+#define     WRITE_PENDING__STATUS  0x4000     /* Write Pending  Status */
+#define            WRITE_COMPLETE  0x8000     /* Write Complete */
+
+/* Bit masks for RTC_SWCNT */
+
+#define           STOPWATCH_COUNT  0xffff     /* Stopwatch Count */
+
+/* Bit masks for RTC_ALARM */
+
+#define                   SECONDS  0x3f       /* Seconds */
+#define                   MINUTES  0xfc0      /* Minutes */
+#define                     HOURS  0x1f000    /* Hours */
+#define                       DAY  0xfffe0000 /* Day */
+
+/* Bit masks for RTC_PREN */
+
+#define                      PREN  0x1        /* Prescaler Enable */
+
+/* Bit masks for OTP_CONTROL */
+
+#define                FUSE_FADDR  0x1ff      /* OTP/Fuse Address */
+#define                      FIEN  0x800      /* OTP/Fuse Interrupt Enable */
+#define                  FTESTDEC  0x1000     /* OTP/Fuse Test Decoder */
+#define                   FWRTEST  0x2000     /* OTP/Fuse Write Test */
+#define                     FRDEN  0x4000     /* OTP/Fuse Read Enable */
+#define                     FWREN  0x8000     /* OTP/Fuse Write Enable */
+
+/* Bit masks for OTP_BEN */
+
+#define                      FBEN  0xffff     /* OTP/Fuse Byte Enable */
+
+/* Bit masks for OTP_STATUS */
+
+#define                     FCOMP  0x1        /* OTP/Fuse Access Complete */
+#define                    FERROR  0x2        /* OTP/Fuse Access Error */
+#define                  MMRGLOAD  0x10       /* Memory Mapped Register Gasket Load */
+#define                  MMRGLOCK  0x20       /* Memory Mapped Register Gasket Lock */
+#define                    FPGMEN  0x40       /* OTP/Fuse Program Enable */
+
+/* Bit masks for OTP_TIMING */
+
+#define                   USECDIV  0xff       /* Micro Second Divider */
+#define                   READACC  0x7f00     /* Read Access Time */
+#define                   CPUMPRL  0x38000    /* Charge Pump Release Time */
+#define                   CPUMPSU  0xc0000    /* Charge Pump Setup Time */
+#define                   CPUMPHD  0xf00000   /* Charge Pump Hold Time */
+#define                   PGMTIME  0xff000000 /* Program Time */
+
+/* Bit masks for SECURE_SYSSWT */
+
+#define                   EMUDABL  0x1        /* Emulation Disable. */
+#define                   RSTDABL  0x2        /* Reset Disable */
+#define                   L1IDABL  0x1c       /* L1 Instruction Memory Disable. */
+#define                  L1DADABL  0xe0       /* L1 Data Bank A Memory Disable. */
+#define                  L1DBDABL  0x700      /* L1 Data Bank B Memory Disable. */
+#define                   DMA0OVR  0x800      /* DMA0 Memory Access Override */
+#define                   DMA1OVR  0x1000     /* DMA1 Memory Access Override */
+#define                    EMUOVR  0x4000     /* Emulation Override */
+#define                    OTPSEN  0x8000     /* OTP Secrets Enable. */
+#define                    L2DABL  0x70000    /* L2 Memory Disable. */
+
+/* Bit masks for SECURE_CONTROL */
+
+#define                   SECURE0  0x1        /* SECURE 0 */
+#define                   SECURE1  0x2        /* SECURE 1 */
+#define                   SECURE2  0x4        /* SECURE 2 */
+#define                   SECURE3  0x8        /* SECURE 3 */
+
+/* Bit masks for SECURE_STATUS */
+
+#define                   SECMODE  0x3        /* Secured Mode Control State */
+#define                       NMI  0x4        /* Non Maskable Interrupt */
+#define                   AFVALID  0x8        /* Authentication Firmware Valid */
+#define                    AFEXIT  0x10       /* Authentication Firmware Exit */
+#define                   SECSTAT  0xe0       /* Secure Status */
+
+/* Bit masks for PLL_DIV */
+
+#define                      CSEL  0x30       /* Core Select */
+#define                      SSEL  0xf        /* System Select */
+
+/* Bit masks for PLL_CTL */
+
+#define                      MSEL  0x7e00     /* Multiplier Select */
+#define                    BYPASS  0x100      /* PLL Bypass Enable */
+#define              OUTPUT_DELAY  0x80       /* External Memory Output Delay Enable */
+#define               INPUT_DELAY  0x40       /* External Memory Input Delay Enable */
+#define                      PDWN  0x20       /* Power Down */
+#define                    STOPCK  0x8        /* Stop Clock */
+#define                   PLL_OFF  0x2        /* Disable PLL */
+#define                        DF  0x1        /* Divide Frequency */
+
+/* Bit masks for PLL_STAT */
+
+#define                PLL_LOCKED  0x20       /* PLL Locked Status */
+#define        ACTIVE_PLLDISABLED  0x4        /* Active Mode With PLL Disabled */
+#define                   FULL_ON  0x2        /* Full-On Mode */
+#define         ACTIVE_PLLENABLED  0x1        /* Active Mode With PLL Enabled */
+#define                     RTCWS  0x400      /* RTC/Reset Wake-Up Status */
+#define                     CANWS  0x800      /* CAN Wake-Up Status */
+#define                     USBWS  0x2000     /* USB Wake-Up Status */
+#define                    KPADWS  0x4000     /* Keypad Wake-Up Status */
+#define                     ROTWS  0x8000     /* Rotary Wake-Up Status */
+#define                      GPWS  0x1000     /* General-Purpose Wake-Up Status */
+
+/* Bit masks for VR_CTL */
+
+#define                      FREQ  0x3        /* Regulator Switching Frequency */
+#define                      GAIN  0xc        /* Voltage Output Level Gain */
+#define                      VLEV  0xf0       /* Internal Voltage Level */
+#define                   SCKELOW  0x8000     /* Drive SCKE Low During Reset Enable */
+#define                      WAKE  0x100      /* RTC/Reset Wake-Up Enable */
+#define                     CANWE  0x200      /* CAN0/1 Wake-Up Enable */
+#define                      GPWE  0x400      /* General-Purpose Wake-Up Enable */
+#define                     USBWE  0x800      /* USB Wake-Up Enable */
+#define                    KPADWE  0x1000     /* Keypad Wake-Up Enable */
+#define                     ROTWE  0x2000     /* Rotary Wake-Up Enable */
+
+/* Bit masks for NFC_CTL */
+
+#define                    WR_DLY  0xf        /* Write Strobe Delay */
+#define                    RD_DLY  0xf0       /* Read Strobe Delay */
+#define                    NWIDTH  0x100      /* NAND Data Width */
+#define                   PG_SIZE  0x200      /* Page Size */
+
+/* Bit masks for NFC_STAT */
+
+#define                     NBUSY  0x1        /* Not Busy */
+#define                   WB_FULL  0x2        /* Write Buffer Full */
+#define                PG_WR_STAT  0x4        /* Page Write Pending */
+#define                PG_RD_STAT  0x8        /* Page Read Pending */
+#define                  WB_EMPTY  0x10       /* Write Buffer Empty */
+
+/* Bit masks for NFC_IRQSTAT */
+
+#define                  NBUSYIRQ  0x1        /* Not Busy IRQ */
+#define                    WB_OVF  0x2        /* Write Buffer Overflow */
+#define                   WB_EDGE  0x4        /* Write Buffer Edge Detect */
+#define                    RD_RDY  0x8        /* Read Data Ready */
+#define                   WR_DONE  0x10       /* Page Write Done */
+
+/* Bit masks for NFC_IRQMASK */
+
+#define              MASK_BUSYIRQ  0x1        /* Mask Not Busy IRQ */
+#define                MASK_WBOVF  0x2        /* Mask Write Buffer Overflow */
+#define              MASK_WBEMPTY  0x4        /* Mask Write Buffer Empty */
+#define                MASK_RDRDY  0x8        /* Mask Read Data Ready */
+#define               MASK_WRDONE  0x10       /* Mask Write Done */
+
+/* Bit masks for NFC_RST */
+
+#define                   ECC_RST  0x1        /* ECC (and NFC counters) Reset */
+
+/* Bit masks for NFC_PGCTL */
+
+#define               PG_RD_START  0x1        /* Page Read Start */
+#define               PG_WR_START  0x2        /* Page Write Start */
+
+/* Bit masks for NFC_ECC0 */
+
+#define                      ECC0  0x7ff      /* Parity Calculation Result0 */
+
+/* Bit masks for NFC_ECC1 */
+
+#define                      ECC1  0x7ff      /* Parity Calculation Result1 */
+
+/* Bit masks for NFC_ECC2 */
+
+#define                      ECC2  0x7ff      /* Parity Calculation Result2 */
+
+/* Bit masks for NFC_ECC3 */
+
+#define                      ECC3  0x7ff      /* Parity Calculation Result3 */
+
+/* Bit masks for NFC_COUNT */
+
+#define                    ECCCNT  0x3ff      /* Transfer Count */
+
+/* Bit masks for CAN0_CONTROL */
+
+#define                       SRS  0x1        /* Software Reset */
+#define                       DNM  0x2        /* DeviceNet Mode */
+#define                       ABO  0x4        /* Auto Bus On */
+#define                       WBA  0x10       /* Wakeup On CAN Bus Activity */
+#define                       SMR  0x20       /* Sleep Mode Request */
+#define                       CSR  0x40       /* CAN Suspend Mode Request */
+#define                       CCR  0x80       /* CAN Configuration Mode Request */
+
+/* Bit masks for CAN0_STATUS */
+
+#define                        WT  0x1        /* CAN Transmit Warning Flag */
+#define                        WR  0x2        /* CAN Receive Warning Flag */
+#define                        EP  0x4        /* CAN Error Passive Mode */
+#define                       EBO  0x8        /* CAN Error Bus Off Mode */
+#define                       CSA  0x40       /* CAN Suspend Mode Acknowledge */
+#define                       CCA  0x80       /* CAN Configuration Mode Acknowledge */
+#define                     MBPTR  0x1f00     /* Mailbox Pointer */
+#define                       TRM  0x4000     /* Transmit Mode Status */
+#define                       REC  0x8000     /* Receive Mode Status */
+
+/* Bit masks for CAN0_DEBUG */
+
+#define                       DEC  0x1        /* Disable Transmit/Receive Error Counters */
+#define                       DRI  0x2        /* Disable CANRX Input Pin */
+#define                       DTO  0x4        /* Disable CANTX Output Pin */
+#define                       DIL  0x8        /* Disable Internal Loop */
+#define                       MAA  0x10       /* Mode Auto-Acknowledge */
+#define                       MRB  0x20       /* Mode Read Back */
+#define                       CDE  0x8000     /* CAN Debug Mode Enable */
+
+/* Bit masks for CAN0_CLOCK */
+
+#define                       BRP  0x3ff      /* CAN Bit Rate Prescaler */
+
+/* Bit masks for CAN0_TIMING */
+
+#define                       SJW  0x300      /* Synchronization Jump Width */
+#define                       SAM  0x80       /* Sampling */
+#define                     TSEG2  0x70       /* Time Segment 2 */
+#define                     TSEG1  0xf        /* Time Segment 1 */
+
+/* Bit masks for CAN0_INTR */
+
+#define                     CANRX  0x80       /* Serial Input From Transceiver */
+#define                     CANTX  0x40       /* Serial Output To Transceiver */
+#define                     SMACK  0x8        /* Sleep Mode Acknowledge */
+#define                      GIRQ  0x4        /* Global Interrupt Request Status */
+#define                    MBTIRQ  0x2        /* Mailbox Transmit Interrupt Request */
+#define                    MBRIRQ  0x1        /* Mailbox Receive Interrupt Request */
+
+/* Bit masks for CAN0_GIM */
+
+#define                     EWTIM  0x1        /* Error Warning Transmit Interrupt Mask */
+#define                     EWRIM  0x2        /* Error Warning Receive Interrupt Mask */
+#define                      EPIM  0x4        /* Error Passive Interrupt Mask */
+#define                      BOIM  0x8        /* Bus Off Interrupt Mask */
+#define                      WUIM  0x10       /* Wakeup Interrupt Mask */
+#define                     UIAIM  0x20       /* Unimplemented Address Interrupt Mask */
+#define                      AAIM  0x40       /* Abort Acknowledge Interrupt Mask */
+#define                     RMLIM  0x80       /* Receive Message Lost Interrupt Mask */
+#define                     UCEIM  0x100      /* Universal Counter Exceeded Interrupt Mask */
+#define                      ADIM  0x400      /* Access Denied Interrupt Mask */
+
+/* Bit masks for CAN0_GIS */
+
+#define                     EWTIS  0x1        /* Error Warning Transmit Interrupt Status */
+#define                     EWRIS  0x2        /* Error Warning Receive Interrupt Status */
+#define                      EPIS  0x4        /* Error Passive Interrupt Status */
+#define                      BOIS  0x8        /* Bus Off Interrupt Status */
+#define                      WUIS  0x10       /* Wakeup Interrupt Status */
+#define                     UIAIS  0x20       /* Unimplemented Address Interrupt Status */
+#define                      AAIS  0x40       /* Abort Acknowledge Interrupt Status */
+#define                     RMLIS  0x80       /* Receive Message Lost Interrupt Status */
+#define                     UCEIS  0x100      /* Universal Counter Exceeded Interrupt Status */
+#define                      ADIS  0x400      /* Access Denied Interrupt Status */
+
+/* Bit masks for CAN0_GIF */
+
+#define                     EWTIF  0x1        /* Error Warning Transmit Interrupt Flag */
+#define                     EWRIF  0x2        /* Error Warning Receive Interrupt Flag */
+#define                      EPIF  0x4        /* Error Passive Interrupt Flag */
+#define                      BOIF  0x8        /* Bus Off Interrupt Flag */
+#define                      WUIF  0x10       /* Wakeup Interrupt Flag */
+#define                     UIAIF  0x20       /* Unimplemented Address Interrupt Flag */
+#define                      AAIF  0x40       /* Abort Acknowledge Interrupt Flag */
+#define                     RMLIF  0x80       /* Receive Message Lost Interrupt Flag */
+#define                     UCEIF  0x100      /* Universal Counter Exceeded Interrupt Flag */
+#define                      ADIF  0x400      /* Access Denied Interrupt Flag */
+
+/* Bit masks for CAN0_MBTD */
+
+#define                       TDR  0x80       /* Temporary Disable Request */
+#define                       TDA  0x40       /* Temporary Disable Acknowledge */
+#define                     TDPTR  0x1f       /* Temporary Disable Pointer */
+
+/* Bit masks for CAN0_UCCNF */
+
+#define                     UCCNF  0xf        /* Universal Counter Configuration */
+#define                      UCRC  0x20       /* Universal Counter Reload/Clear */
+#define                      UCCT  0x40       /* Universal Counter CAN Trigger */
+#define                       UCE  0x80       /* Universal Counter Enable */
+
+/* Bit masks for CAN0_UCCNT */
+
+#define                     UCCNT  0xffff     /* Universal Counter Count Value */
+
+/* Bit masks for CAN0_UCRC */
+
+#define                     UCVAL  0xffff     /* Universal Counter Reload/Capture Value */
+
+/* Bit masks for CAN0_CEC */
+
+#define                    RXECNT  0xff       /* Receive Error Counter */
+#define                    TXECNT  0xff00     /* Transmit Error Counter */
+
+/* Bit masks for CAN0_ESR */
+
+#define                       FER  0x80       /* Form Error */
+#define                       BEF  0x40       /* Bit Error Flag */
+#define                       SA0  0x20       /* Stuck At Dominant */
+#define                      CRCE  0x10       /* CRC Error */
+#define                       SER  0x8        /* Stuff Bit Error */
+#define                      ACKE  0x4        /* Acknowledge Error */
+
+/* Bit masks for CAN0_EWR */
+
+#define                    EWLTEC  0xff00     /* Transmit Error Warning Limit */
+#define                    EWLREC  0xff       /* Receive Error Warning Limit */
+
+/* Bit masks for CAN0_AMxx_H */
+
+#define                       FDF  0x8000     /* Filter On Data Field */
+#define                       FMD  0x4000     /* Full Mask Data */
+#define                     AMIDE  0x2000     /* Acceptance Mask Identifier Extension */
+#define                    BASEID  0x1ffc     /* Base Identifier */
+#define                  EXTID_HI  0x3        /* Extended Identifier High Bits */
+
+/* Bit masks for CAN0_AMxx_L */
+
+#define                  EXTID_LO  0xffff     /* Extended Identifier Low Bits */
+#define                       DFM  0xffff     /* Data Field Mask */
+
+/* Bit masks for CAN0_MBxx_ID1 */
+
+#define                       AME  0x8000     /* Acceptance Mask Enable */
+#define                       RTR  0x4000     /* Remote Transmission Request */
+#define                       IDE  0x2000     /* Identifier Extension */
+#define                    BASEID  0x1ffc     /* Base Identifier */
+#define                  EXTID_HI  0x3        /* Extended Identifier High Bits */
+
+/* Bit masks for CAN0_MBxx_ID0 */
+
+#define                  EXTID_LO  0xffff     /* Extended Identifier Low Bits */
+#define                       DFM  0xffff     /* Data Field Mask */
+
+/* Bit masks for CAN0_MBxx_TIMESTAMP */
+
+#define                       TSV  0xffff     /* Time Stamp Value */
+
+/* Bit masks for CAN0_MBxx_LENGTH */
+
+#define                       DLC  0xf        /* Data Length Code */
+
+/* Bit masks for CAN0_MBxx_DATA3 */
+
+#define                 CAN_BYTE0  0xff00     /* Data Field Byte 0 */
+#define                 CAN_BYTE1  0xff       /* Data Field Byte 1 */
+
+/* Bit masks for CAN0_MBxx_DATA2 */
+
+#define                 CAN_BYTE2  0xff00     /* Data Field Byte 2 */
+#define                 CAN_BYTE3  0xff       /* Data Field Byte 3 */
+
+/* Bit masks for CAN0_MBxx_DATA1 */
+
+#define                 CAN_BYTE4  0xff00     /* Data Field Byte 4 */
+#define                 CAN_BYTE5  0xff       /* Data Field Byte 5 */
+
+/* Bit masks for CAN0_MBxx_DATA0 */
+
+#define                 CAN_BYTE6  0xff00     /* Data Field Byte 6 */
+#define                 CAN_BYTE7  0xff       /* Data Field Byte 7 */
+
+/* Bit masks for CAN0_MC1 */
+
+#define                       MC0  0x1        /* Mailbox 0 Enable */
+#define                       MC1  0x2        /* Mailbox 1 Enable */
+#define                       MC2  0x4        /* Mailbox 2 Enable */
+#define                       MC3  0x8        /* Mailbox 3 Enable */
+#define                       MC4  0x10       /* Mailbox 4 Enable */
+#define                       MC5  0x20       /* Mailbox 5 Enable */
+#define                       MC6  0x40       /* Mailbox 6 Enable */
+#define                       MC7  0x80       /* Mailbox 7 Enable */
+#define                       MC8  0x100      /* Mailbox 8 Enable */
+#define                       MC9  0x200      /* Mailbox 9 Enable */
+#define                      MC10  0x400      /* Mailbox 10 Enable */
+#define                      MC11  0x800      /* Mailbox 11 Enable */
+#define                      MC12  0x1000     /* Mailbox 12 Enable */
+#define                      MC13  0x2000     /* Mailbox 13 Enable */
+#define                      MC14  0x4000     /* Mailbox 14 Enable */
+#define                      MC15  0x8000     /* Mailbox 15 Enable */
+
+/* Bit masks for CAN0_MC2 */
+
+#define                      MC16  0x1        /* Mailbox 16 Enable */
+#define                      MC17  0x2        /* Mailbox 17 Enable */
+#define                      MC18  0x4        /* Mailbox 18 Enable */
+#define                      MC19  0x8        /* Mailbox 19 Enable */
+#define                      MC20  0x10       /* Mailbox 20 Enable */
+#define                      MC21  0x20       /* Mailbox 21 Enable */
+#define                      MC22  0x40       /* Mailbox 22 Enable */
+#define                      MC23  0x80       /* Mailbox 23 Enable */
+#define                      MC24  0x100      /* Mailbox 24 Enable */
+#define                      MC25  0x200      /* Mailbox 25 Enable */
+#define                      MC26  0x400      /* Mailbox 26 Enable */
+#define                      MC27  0x800      /* Mailbox 27 Enable */
+#define                      MC28  0x1000     /* Mailbox 28 Enable */
+#define                      MC29  0x2000     /* Mailbox 29 Enable */
+#define                      MC30  0x4000     /* Mailbox 30 Enable */
+#define                      MC31  0x8000     /* Mailbox 31 Enable */
+
+/* Bit masks for CAN0_MD1 */
+
+#define                       MD0  0x1        /* Mailbox 0 Receive Enable */
+#define                       MD1  0x2        /* Mailbox 1 Receive Enable */
+#define                       MD2  0x4        /* Mailbox 2 Receive Enable */
+#define                       MD3  0x8        /* Mailbox 3 Receive Enable */
+#define                       MD4  0x10       /* Mailbox 4 Receive Enable */
+#define                       MD5  0x20       /* Mailbox 5 Receive Enable */
+#define                       MD6  0x40       /* Mailbox 6 Receive Enable */
+#define                       MD7  0x80       /* Mailbox 7 Receive Enable */
+#define                       MD8  0x100      /* Mailbox 8 Receive Enable */
+#define                       MD9  0x200      /* Mailbox 9 Receive Enable */
+#define                      MD10  0x400      /* Mailbox 10 Receive Enable */
+#define                      MD11  0x800      /* Mailbox 11 Receive Enable */
+#define                      MD12  0x1000     /* Mailbox 12 Receive Enable */
+#define                      MD13  0x2000     /* Mailbox 13 Receive Enable */
+#define                      MD14  0x4000     /* Mailbox 14 Receive Enable */
+#define                      MD15  0x8000     /* Mailbox 15 Receive Enable */
+
+/* Bit masks for CAN0_MD2 */
+
+#define                      MD16  0x1        /* Mailbox 16 Receive Enable */
+#define                      MD17  0x2        /* Mailbox 17 Receive Enable */
+#define                      MD18  0x4        /* Mailbox 18 Receive Enable */
+#define                      MD19  0x8        /* Mailbox 19 Receive Enable */
+#define                      MD20  0x10       /* Mailbox 20 Receive Enable */
+#define                      MD21  0x20       /* Mailbox 21 Receive Enable */
+#define                      MD22  0x40       /* Mailbox 22 Receive Enable */
+#define                      MD23  0x80       /* Mailbox 23 Receive Enable */
+#define                      MD24  0x100      /* Mailbox 24 Receive Enable */
+#define                      MD25  0x200      /* Mailbox 25 Receive Enable */
+#define                      MD26  0x400      /* Mailbox 26 Receive Enable */
+#define                      MD27  0x800      /* Mailbox 27 Receive Enable */
+#define                      MD28  0x1000     /* Mailbox 28 Receive Enable */
+#define                      MD29  0x2000     /* Mailbox 29 Receive Enable */
+#define                      MD30  0x4000     /* Mailbox 30 Receive Enable */
+#define                      MD31  0x8000     /* Mailbox 31 Receive Enable */
+
+/* Bit masks for CAN0_RMP1 */
+
+#define                      RMP0  0x1        /* Mailbox 0 Receive Message Pending */
+#define                      RMP1  0x2        /* Mailbox 1 Receive Message Pending */
+#define                      RMP2  0x4        /* Mailbox 2 Receive Message Pending */
+#define                      RMP3  0x8        /* Mailbox 3 Receive Message Pending */
+#define                      RMP4  0x10       /* Mailbox 4 Receive Message Pending */
+#define                      RMP5  0x20       /* Mailbox 5 Receive Message Pending */
+#define                      RMP6  0x40       /* Mailbox 6 Receive Message Pending */
+#define                      RMP7  0x80       /* Mailbox 7 Receive Message Pending */
+#define                      RMP8  0x100      /* Mailbox 8 Receive Message Pending */
+#define                      RMP9  0x200      /* Mailbox 9 Receive Message Pending */
+#define                     RMP10  0x400      /* Mailbox 10 Receive Message Pending */
+#define                     RMP11  0x800      /* Mailbox 11 Receive Message Pending */
+#define                     RMP12  0x1000     /* Mailbox 12 Receive Message Pending */
+#define                     RMP13  0x2000     /* Mailbox 13 Receive Message Pending */
+#define                     RMP14  0x4000     /* Mailbox 14 Receive Message Pending */
+#define                     RMP15  0x8000     /* Mailbox 15 Receive Message Pending */
+
+/* Bit masks for CAN0_RMP2 */
+
+#define                     RMP16  0x1        /* Mailbox 16 Receive Message Pending */
+#define                     RMP17  0x2        /* Mailbox 17 Receive Message Pending */
+#define                     RMP18  0x4        /* Mailbox 18 Receive Message Pending */
+#define                     RMP19  0x8        /* Mailbox 19 Receive Message Pending */
+#define                     RMP20  0x10       /* Mailbox 20 Receive Message Pending */
+#define                     RMP21  0x20       /* Mailbox 21 Receive Message Pending */
+#define                     RMP22  0x40       /* Mailbox 22 Receive Message Pending */
+#define                     RMP23  0x80       /* Mailbox 23 Receive Message Pending */
+#define                     RMP24  0x100      /* Mailbox 24 Receive Message Pending */
+#define                     RMP25  0x200      /* Mailbox 25 Receive Message Pending */
+#define                     RMP26  0x400      /* Mailbox 26 Receive Message Pending */
+#define                     RMP27  0x800      /* Mailbox 27 Receive Message Pending */
+#define                     RMP28  0x1000     /* Mailbox 28 Receive Message Pending */
+#define                     RMP29  0x2000     /* Mailbox 29 Receive Message Pending */
+#define                     RMP30  0x4000     /* Mailbox 30 Receive Message Pending */
+#define                     RMP31  0x8000     /* Mailbox 31 Receive Message Pending */
+
+/* Bit masks for CAN0_RML1 */
+
+#define                      RML0  0x1        /* Mailbox 0 Receive Message Lost */
+#define                      RML1  0x2        /* Mailbox 1 Receive Message Lost */
+#define                      RML2  0x4        /* Mailbox 2 Receive Message Lost */
+#define                      RML3  0x8        /* Mailbox 3 Receive Message Lost */
+#define                      RML4  0x10       /* Mailbox 4 Receive Message Lost */
+#define                      RML5  0x20       /* Mailbox 5 Receive Message Lost */
+#define                      RML6  0x40       /* Mailbox 6 Receive Message Lost */
+#define                      RML7  0x80       /* Mailbox 7 Receive Message Lost */
+#define                      RML8  0x100      /* Mailbox 8 Receive Message Lost */
+#define                      RML9  0x200      /* Mailbox 9 Receive Message Lost */
+#define                     RML10  0x400      /* Mailbox 10 Receive Message Lost */
+#define                     RML11  0x800      /* Mailbox 11 Receive Message Lost */
+#define                     RML12  0x1000     /* Mailbox 12 Receive Message Lost */
+#define                     RML13  0x2000     /* Mailbox 13 Receive Message Lost */
+#define                     RML14  0x4000     /* Mailbox 14 Receive Message Lost */
+#define                     RML15  0x8000     /* Mailbox 15 Receive Message Lost */
+
+/* Bit masks for CAN0_RML2 */
+
+#define                     RML16  0x1        /* Mailbox 16 Receive Message Lost */
+#define                     RML17  0x2        /* Mailbox 17 Receive Message Lost */
+#define                     RML18  0x4        /* Mailbox 18 Receive Message Lost */
+#define                     RML19  0x8        /* Mailbox 19 Receive Message Lost */
+#define                     RML20  0x10       /* Mailbox 20 Receive Message Lost */
+#define                     RML21  0x20       /* Mailbox 21 Receive Message Lost */
+#define                     RML22  0x40       /* Mailbox 22 Receive Message Lost */
+#define                     RML23  0x80       /* Mailbox 23 Receive Message Lost */
+#define                     RML24  0x100      /* Mailbox 24 Receive Message Lost */
+#define                     RML25  0x200      /* Mailbox 25 Receive Message Lost */
+#define                     RML26  0x400      /* Mailbox 26 Receive Message Lost */
+#define                     RML27  0x800      /* Mailbox 27 Receive Message Lost */
+#define                     RML28  0x1000     /* Mailbox 28 Receive Message Lost */
+#define                     RML29  0x2000     /* Mailbox 29 Receive Message Lost */
+#define                     RML30  0x4000     /* Mailbox 30 Receive Message Lost */
+#define                     RML31  0x8000     /* Mailbox 31 Receive Message Lost */
+
+/* Bit masks for CAN0_OPSS1 */
+
+#define                     OPSS0  0x1        /* Mailbox 0 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS1  0x2        /* Mailbox 1 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS2  0x4        /* Mailbox 2 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS3  0x8        /* Mailbox 3 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS4  0x10       /* Mailbox 4 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS5  0x20       /* Mailbox 5 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS6  0x40       /* Mailbox 6 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS7  0x80       /* Mailbox 7 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS8  0x100      /* Mailbox 8 Overwrite Protection/Single-Shot Transmission Enable */
+#define                     OPSS9  0x200      /* Mailbox 9 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS10  0x400      /* Mailbox 10 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS11  0x800      /* Mailbox 11 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS12  0x1000     /* Mailbox 12 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS13  0x2000     /* Mailbox 13 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS14  0x4000     /* Mailbox 14 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS15  0x8000     /* Mailbox 15 Overwrite Protection/Single-Shot Transmission Enable */
+
+/* Bit masks for CAN0_OPSS2 */
+
+#define                    OPSS16  0x1        /* Mailbox 16 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS17  0x2        /* Mailbox 17 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS18  0x4        /* Mailbox 18 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS19  0x8        /* Mailbox 19 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS20  0x10       /* Mailbox 20 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS21  0x20       /* Mailbox 21 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS22  0x40       /* Mailbox 22 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS23  0x80       /* Mailbox 23 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS24  0x100      /* Mailbox 24 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS25  0x200      /* Mailbox 25 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS26  0x400      /* Mailbox 26 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS27  0x800      /* Mailbox 27 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS28  0x1000     /* Mailbox 28 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS29  0x2000     /* Mailbox 29 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS30  0x4000     /* Mailbox 30 Overwrite Protection/Single-Shot Transmission Enable */
+#define                    OPSS31  0x8000     /* Mailbox 31 Overwrite Protection/Single-Shot Transmission Enable */
+
+/* Bit masks for CAN0_TRS1 */
+
+#define                      TRS0  0x1        /* Mailbox 0 Transmit Request Set */
+#define                      TRS1  0x2        /* Mailbox 1 Transmit Request Set */
+#define                      TRS2  0x4        /* Mailbox 2 Transmit Request Set */
+#define                      TRS3  0x8        /* Mailbox 3 Transmit Request Set */
+#define                      TRS4  0x10       /* Mailbox 4 Transmit Request Set */
+#define                      TRS5  0x20       /* Mailbox 5 Transmit Request Set */
+#define                      TRS6  0x40       /* Mailbox 6 Transmit Request Set */
+#define                      TRS7  0x80       /* Mailbox 7 Transmit Request Set */
+#define                      TRS8  0x100      /* Mailbox 8 Transmit Request Set */
+#define                      TRS9  0x200      /* Mailbox 9 Transmit Request Set */
+#define                     TRS10  0x400      /* Mailbox 10 Transmit Request Set */
+#define                     TRS11  0x800      /* Mailbox 11 Transmit Request Set */
+#define                     TRS12  0x1000     /* Mailbox 12 Transmit Request Set */
+#define                     TRS13  0x2000     /* Mailbox 13 Transmit Request Set */
+#define                     TRS14  0x4000     /* Mailbox 14 Transmit Request Set */
+#define                     TRS15  0x8000     /* Mailbox 15 Transmit Request Set */
+
+/* Bit masks for CAN0_TRS2 */
+
+#define                     TRS16  0x1        /* Mailbox 16 Transmit Request Set */
+#define                     TRS17  0x2        /* Mailbox 17 Transmit Request Set */
+#define                     TRS18  0x4        /* Mailbox 18 Transmit Request Set */
+#define                     TRS19  0x8        /* Mailbox 19 Transmit Request Set */
+#define                     TRS20  0x10       /* Mailbox 20 Transmit Request Set */
+#define                     TRS21  0x20       /* Mailbox 21 Transmit Request Set */
+#define                     TRS22  0x40       /* Mailbox 22 Transmit Request Set */
+#define                     TRS23  0x80       /* Mailbox 23 Transmit Request Set */
+#define                     TRS24  0x100      /* Mailbox 24 Transmit Request Set */
+#define                     TRS25  0x200      /* Mailbox 25 Transmit Request Set */
+#define                     TRS26  0x400      /* Mailbox 26 Transmit Request Set */
+#define                     TRS27  0x800      /* Mailbox 27 Transmit Request Set */
+#define                     TRS28  0x1000     /* Mailbox 28 Transmit Request Set */
+#define                     TRS29  0x2000     /* Mailbox 29 Transmit Request Set */
+#define                     TRS30  0x4000     /* Mailbox 30 Transmit Request Set */
+#define                     TRS31  0x8000     /* Mailbox 31 Transmit Request Set */
+
+/* Bit masks for CAN0_TRR1 */
+
+#define                      TRR0  0x1        /* Mailbox 0 Transmit Request Reset */
+#define                      TRR1  0x2        /* Mailbox 1 Transmit Request Reset */
+#define                      TRR2  0x4        /* Mailbox 2 Transmit Request Reset */
+#define                      TRR3  0x8        /* Mailbox 3 Transmit Request Reset */
+#define                      TRR4  0x10       /* Mailbox 4 Transmit Request Reset */
+#define                      TRR5  0x20       /* Mailbox 5 Transmit Request Reset */
+#define                      TRR6  0x40       /* Mailbox 6 Transmit Request Reset */
+#define                      TRR7  0x80       /* Mailbox 7 Transmit Request Reset */
+#define                      TRR8  0x100      /* Mailbox 8 Transmit Request Reset */
+#define                      TRR9  0x200      /* Mailbox 9 Transmit Request Reset */
+#define                     TRR10  0x400      /* Mailbox 10 Transmit Request Reset */
+#define                     TRR11  0x800      /* Mailbox 11 Transmit Request Reset */
+#define                     TRR12  0x1000     /* Mailbox 12 Transmit Request Reset */
+#define                     TRR13  0x2000     /* Mailbox 13 Transmit Request Reset */
+#define                     TRR14  0x4000     /* Mailbox 14 Transmit Request Reset */
+#define                     TRR15  0x8000     /* Mailbox 15 Transmit Request Reset */
+
+/* Bit masks for CAN0_TRR2 */
+
+#define                     TRR16  0x1        /* Mailbox 16 Transmit Request Reset */
+#define                     TRR17  0x2        /* Mailbox 17 Transmit Request Reset */
+#define                     TRR18  0x4        /* Mailbox 18 Transmit Request Reset */
+#define                     TRR19  0x8        /* Mailbox 19 Transmit Request Reset */
+#define                     TRR20  0x10       /* Mailbox 20 Transmit Request Reset */
+#define                     TRR21  0x20       /* Mailbox 21 Transmit Request Reset */
+#define                     TRR22  0x40       /* Mailbox 22 Transmit Request Reset */
+#define                     TRR23  0x80       /* Mailbox 23 Transmit Request Reset */
+#define                     TRR24  0x100      /* Mailbox 24 Transmit Request Reset */
+#define                     TRR25  0x200      /* Mailbox 25 Transmit Request Reset */
+#define                     TRR26  0x400      /* Mailbox 26 Transmit Request Reset */
+#define                     TRR27  0x800      /* Mailbox 27 Transmit Request Reset */
+#define                     TRR28  0x1000     /* Mailbox 28 Transmit Request Reset */
+#define                     TRR29  0x2000     /* Mailbox 29 Transmit Request Reset */
+#define                     TRR30  0x4000     /* Mailbox 30 Transmit Request Reset */
+#define                     TRR31  0x8000     /* Mailbox 31 Transmit Request Reset */
+
+/* Bit masks for CAN0_AA1 */
+
+#define                       AA0  0x1        /* Mailbox 0 Abort Acknowledge */
+#define                       AA1  0x2        /* Mailbox 1 Abort Acknowledge */
+#define                       AA2  0x4        /* Mailbox 2 Abort Acknowledge */
+#define                       AA3  0x8        /* Mailbox 3 Abort Acknowledge */
+#define                       AA4  0x10       /* Mailbox 4 Abort Acknowledge */
+#define                       AA5  0x20       /* Mailbox 5 Abort Acknowledge */
+#define                       AA6  0x40       /* Mailbox 6 Abort Acknowledge */
+#define                       AA7  0x80       /* Mailbox 7 Abort Acknowledge */
+#define                       AA8  0x100      /* Mailbox 8 Abort Acknowledge */
+#define                       AA9  0x200      /* Mailbox 9 Abort Acknowledge */
+#define                      AA10  0x400      /* Mailbox 10 Abort Acknowledge */
+#define                      AA11  0x800      /* Mailbox 11 Abort Acknowledge */
+#define                      AA12  0x1000     /* Mailbox 12 Abort Acknowledge */
+#define                      AA13  0x2000     /* Mailbox 13 Abort Acknowledge */
+#define                      AA14  0x4000     /* Mailbox 14 Abort Acknowledge */
+#define                      AA15  0x8000     /* Mailbox 15 Abort Acknowledge */
+
+/* Bit masks for CAN0_AA2 */
+
+#define                      AA16  0x1        /* Mailbox 16 Abort Acknowledge */
+#define                      AA17  0x2        /* Mailbox 17 Abort Acknowledge */
+#define                      AA18  0x4        /* Mailbox 18 Abort Acknowledge */
+#define                      AA19  0x8        /* Mailbox 19 Abort Acknowledge */
+#define                      AA20  0x10       /* Mailbox 20 Abort Acknowledge */
+#define                      AA21  0x20       /* Mailbox 21 Abort Acknowledge */
+#define                      AA22  0x40       /* Mailbox 22 Abort Acknowledge */
+#define                      AA23  0x80       /* Mailbox 23 Abort Acknowledge */
+#define                      AA24  0x100      /* Mailbox 24 Abort Acknowledge */
+#define                      AA25  0x200      /* Mailbox 25 Abort Acknowledge */
+#define                      AA26  0x400      /* Mailbox 26 Abort Acknowledge */
+#define                      AA27  0x800      /* Mailbox 27 Abort Acknowledge */
+#define                      AA28  0x1000     /* Mailbox 28 Abort Acknowledge */
+#define                      AA29  0x2000     /* Mailbox 29 Abort Acknowledge */
+#define                      AA30  0x4000     /* Mailbox 30 Abort Acknowledge */
+#define                      AA31  0x8000     /* Mailbox 31 Abort Acknowledge */
+
+/* Bit masks for CAN0_TA1 */
+
+#define                       TA0  0x1        /* Mailbox 0 Transmit Acknowledge */
+#define                       TA1  0x2        /* Mailbox 1 Transmit Acknowledge */
+#define                       TA2  0x4        /* Mailbox 2 Transmit Acknowledge */
+#define                       TA3  0x8        /* Mailbox 3 Transmit Acknowledge */
+#define                       TA4  0x10       /* Mailbox 4 Transmit Acknowledge */
+#define                       TA5  0x20       /* Mailbox 5 Transmit Acknowledge */
+#define                       TA6  0x40       /* Mailbox 6 Transmit Acknowledge */
+#define                       TA7  0x80       /* Mailbox 7 Transmit Acknowledge */
+#define                       TA8  0x100      /* Mailbox 8 Transmit Acknowledge */
+#define                       TA9  0x200      /* Mailbox 9 Transmit Acknowledge */
+#define                      TA10  0x400      /* Mailbox 10 Transmit Acknowledge */
+#define                      TA11  0x800      /* Mailbox 11 Transmit Acknowledge */
+#define                      TA12  0x1000     /* Mailbox 12 Transmit Acknowledge */
+#define                      TA13  0x2000     /* Mailbox 13 Transmit Acknowledge */
+#define                      TA14  0x4000     /* Mailbox 14 Transmit Acknowledge */
+#define                      TA15  0x8000     /* Mailbox 15 Transmit Acknowledge */
+
+/* Bit masks for CAN0_TA2 */
+
+#define                      TA16  0x1        /* Mailbox 16 Transmit Acknowledge */
+#define                      TA17  0x2        /* Mailbox 17 Transmit Acknowledge */
+#define                      TA18  0x4        /* Mailbox 18 Transmit Acknowledge */
+#define                      TA19  0x8        /* Mailbox 19 Transmit Acknowledge */
+#define                      TA20  0x10       /* Mailbox 20 Transmit Acknowledge */
+#define                      TA21  0x20       /* Mailbox 21 Transmit Acknowledge */
+#define                      TA22  0x40       /* Mailbox 22 Transmit Acknowledge */
+#define                      TA23  0x80       /* Mailbox 23 Transmit Acknowledge */
+#define                      TA24  0x100      /* Mailbox 24 Transmit Acknowledge */
+#define                      TA25  0x200      /* Mailbox 25 Transmit Acknowledge */
+#define                      TA26  0x400      /* Mailbox 26 Transmit Acknowledge */
+#define                      TA27  0x800      /* Mailbox 27 Transmit Acknowledge */
+#define                      TA28  0x1000     /* Mailbox 28 Transmit Acknowledge */
+#define                      TA29  0x2000     /* Mailbox 29 Transmit Acknowledge */
+#define                      TA30  0x4000     /* Mailbox 30 Transmit Acknowledge */
+#define                      TA31  0x8000     /* Mailbox 31 Transmit Acknowledge */
+
+/* Bit masks for CAN0_RFH1 */
+
+#define                      RFH0  0x1        /* Mailbox 0 Remote Frame Handling Enable */
+#define                      RFH1  0x2        /* Mailbox 1 Remote Frame Handling Enable */
+#define                      RFH2  0x4        /* Mailbox 2 Remote Frame Handling Enable */
+#define                      RFH3  0x8        /* Mailbox 3 Remote Frame Handling Enable */
+#define                      RFH4  0x10       /* Mailbox 4 Remote Frame Handling Enable */
+#define                      RFH5  0x20       /* Mailbox 5 Remote Frame Handling Enable */
+#define                      RFH6  0x40       /* Mailbox 6 Remote Frame Handling Enable */
+#define                      RFH7  0x80       /* Mailbox 7 Remote Frame Handling Enable */
+#define                      RFH8  0x100      /* Mailbox 8 Remote Frame Handling Enable */
+#define                      RFH9  0x200      /* Mailbox 9 Remote Frame Handling Enable */
+#define                     RFH10  0x400      /* Mailbox 10 Remote Frame Handling Enable */
+#define                     RFH11  0x800      /* Mailbox 11 Remote Frame Handling Enable */
+#define                     RFH12  0x1000     /* Mailbox 12 Remote Frame Handling Enable */
+#define                     RFH13  0x2000     /* Mailbox 13 Remote Frame Handling Enable */
+#define                     RFH14  0x4000     /* Mailbox 14 Remote Frame Handling Enable */
+#define                     RFH15  0x8000     /* Mailbox 15 Remote Frame Handling Enable */
+
+/* Bit masks for CAN0_RFH2 */
+
+#define                     RFH16  0x1        /* Mailbox 16 Remote Frame Handling Enable */
+#define                     RFH17  0x2        /* Mailbox 17 Remote Frame Handling Enable */
+#define                     RFH18  0x4        /* Mailbox 18 Remote Frame Handling Enable */
+#define                     RFH19  0x8        /* Mailbox 19 Remote Frame Handling Enable */
+#define                     RFH20  0x10       /* Mailbox 20 Remote Frame Handling Enable */
+#define                     RFH21  0x20       /* Mailbox 21 Remote Frame Handling Enable */
+#define                     RFH22  0x40       /* Mailbox 22 Remote Frame Handling Enable */
+#define                     RFH23  0x80       /* Mailbox 23 Remote Frame Handling Enable */
+#define                     RFH24  0x100      /* Mailbox 24 Remote Frame Handling Enable */
+#define                     RFH25  0x200      /* Mailbox 25 Remote Frame Handling Enable */
+#define                     RFH26  0x400      /* Mailbox 26 Remote Frame Handling Enable */
+#define                     RFH27  0x800      /* Mailbox 27 Remote Frame Handling Enable */
+#define                     RFH28  0x1000     /* Mailbox 28 Remote Frame Handling Enable */
+#define                     RFH29  0x2000     /* Mailbox 29 Remote Frame Handling Enable */
+#define                     RFH30  0x4000     /* Mailbox 30 Remote Frame Handling Enable */
+#define                     RFH31  0x8000     /* Mailbox 31 Remote Frame Handling Enable */
+
+/* Bit masks for CAN0_MBIM1 */
+
+#define                     MBIM0  0x1        /* Mailbox 0 Mailbox Interrupt Mask */
+#define                     MBIM1  0x2        /* Mailbox 1 Mailbox Interrupt Mask */
+#define                     MBIM2  0x4        /* Mailbox 2 Mailbox Interrupt Mask */
+#define                     MBIM3  0x8        /* Mailbox 3 Mailbox Interrupt Mask */
+#define                     MBIM4  0x10       /* Mailbox 4 Mailbox Interrupt Mask */
+#define                     MBIM5  0x20       /* Mailbox 5 Mailbox Interrupt Mask */
+#define                     MBIM6  0x40       /* Mailbox 6 Mailbox Interrupt Mask */
+#define                     MBIM7  0x80       /* Mailbox 7 Mailbox Interrupt Mask */
+#define                     MBIM8  0x100      /* Mailbox 8 Mailbox Interrupt Mask */
+#define                     MBIM9  0x200      /* Mailbox 9 Mailbox Interrupt Mask */
+#define                    MBIM10  0x400      /* Mailbox 10 Mailbox Interrupt Mask */
+#define                    MBIM11  0x800      /* Mailbox 11 Mailbox Interrupt Mask */
+#define                    MBIM12  0x1000     /* Mailbox 12 Mailbox Interrupt Mask */
+#define                    MBIM13  0x2000     /* Mailbox 13 Mailbox Interrupt Mask */
+#define                    MBIM14  0x4000     /* Mailbox 14 Mailbox Interrupt Mask */
+#define                    MBIM15  0x8000     /* Mailbox 15 Mailbox Interrupt Mask */
+
+/* Bit masks for CAN0_MBIM2 */
+
+#define                    MBIM16  0x1        /* Mailbox 16 Mailbox Interrupt Mask */
+#define                    MBIM17  0x2        /* Mailbox 17 Mailbox Interrupt Mask */
+#define                    MBIM18  0x4        /* Mailbox 18 Mailbox Interrupt Mask */
+#define                    MBIM19  0x8        /* Mailbox 19 Mailbox Interrupt Mask */
+#define                    MBIM20  0x10       /* Mailbox 20 Mailbox Interrupt Mask */
+#define                    MBIM21  0x20       /* Mailbox 21 Mailbox Interrupt Mask */
+#define                    MBIM22  0x40       /* Mailbox 22 Mailbox Interrupt Mask */
+#define                    MBIM23  0x80       /* Mailbox 23 Mailbox Interrupt Mask */
+#define                    MBIM24  0x100      /* Mailbox 24 Mailbox Interrupt Mask */
+#define                    MBIM25  0x200      /* Mailbox 25 Mailbox Interrupt Mask */
+#define                    MBIM26  0x400      /* Mailbox 26 Mailbox Interrupt Mask */
+#define                    MBIM27  0x800      /* Mailbox 27 Mailbox Interrupt Mask */
+#define                    MBIM28  0x1000     /* Mailbox 28 Mailbox Interrupt Mask */
+#define                    MBIM29  0x2000     /* Mailbox 29 Mailbox Interrupt Mask */
+#define                    MBIM30  0x4000     /* Mailbox 30 Mailbox Interrupt Mask */
+#define                    MBIM31  0x8000     /* Mailbox 31 Mailbox Interrupt Mask */
+
+/* Bit masks for CAN0_MBTIF1 */
+
+#define                    MBTIF0  0x1        /* Mailbox 0 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF1  0x2        /* Mailbox 1 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF2  0x4        /* Mailbox 2 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF3  0x8        /* Mailbox 3 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF4  0x10       /* Mailbox 4 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF5  0x20       /* Mailbox 5 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF6  0x40       /* Mailbox 6 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF7  0x80       /* Mailbox 7 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF8  0x100      /* Mailbox 8 Mailbox Transmit Interrupt Flag */
+#define                    MBTIF9  0x200      /* Mailbox 9 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF10  0x400      /* Mailbox 10 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF11  0x800      /* Mailbox 11 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF12  0x1000     /* Mailbox 12 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF13  0x2000     /* Mailbox 13 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF14  0x4000     /* Mailbox 14 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF15  0x8000     /* Mailbox 15 Mailbox Transmit Interrupt Flag */
+
+/* Bit masks for CAN0_MBTIF2 */
+
+#define                   MBTIF16  0x1        /* Mailbox 16 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF17  0x2        /* Mailbox 17 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF18  0x4        /* Mailbox 18 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF19  0x8        /* Mailbox 19 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF20  0x10       /* Mailbox 20 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF21  0x20       /* Mailbox 21 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF22  0x40       /* Mailbox 22 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF23  0x80       /* Mailbox 23 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF24  0x100      /* Mailbox 24 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF25  0x200      /* Mailbox 25 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF26  0x400      /* Mailbox 26 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF27  0x800      /* Mailbox 27 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF28  0x1000     /* Mailbox 28 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF29  0x2000     /* Mailbox 29 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF30  0x4000     /* Mailbox 30 Mailbox Transmit Interrupt Flag */
+#define                   MBTIF31  0x8000     /* Mailbox 31 Mailbox Transmit Interrupt Flag */
+
+/* Bit masks for CAN0_MBRIF1 */
+
+#define                    MBRIF0  0x1        /* Mailbox 0 Mailbox Receive Interrupt Flag */
+#define                    MBRIF1  0x2        /* Mailbox 1 Mailbox Receive Interrupt Flag */
+#define                    MBRIF2  0x4        /* Mailbox 2 Mailbox Receive Interrupt Flag */
+#define                    MBRIF3  0x8        /* Mailbox 3 Mailbox Receive Interrupt Flag */
+#define                    MBRIF4  0x10       /* Mailbox 4 Mailbox Receive Interrupt Flag */
+#define                    MBRIF5  0x20       /* Mailbox 5 Mailbox Receive Interrupt Flag */
+#define                    MBRIF6  0x40       /* Mailbox 6 Mailbox Receive Interrupt Flag */
+#define                    MBRIF7  0x80       /* Mailbox 7 Mailbox Receive Interrupt Flag */
+#define                    MBRIF8  0x100      /* Mailbox 8 Mailbox Receive Interrupt Flag */
+#define                    MBRIF9  0x200      /* Mailbox 9 Mailbox Receive Interrupt Flag */
+#define                   MBRIF10  0x400      /* Mailbox 10 Mailbox Receive Interrupt Flag */
+#define                   MBRIF11  0x800      /* Mailbox 11 Mailbox Receive Interrupt Flag */
+#define                   MBRIF12  0x1000     /* Mailbox 12 Mailbox Receive Interrupt Flag */
+#define                   MBRIF13  0x2000     /* Mailbox 13 Mailbox Receive Interrupt Flag */
+#define                   MBRIF14  0x4000     /* Mailbox 14 Mailbox Receive Interrupt Flag */
+#define                   MBRIF15  0x8000     /* Mailbox 15 Mailbox Receive Interrupt Flag */
+
+/* Bit masks for CAN0_MBRIF2 */
+
+#define                   MBRIF16  0x1        /* Mailbox 16 Mailbox Receive Interrupt Flag */
+#define                   MBRIF17  0x2        /* Mailbox 17 Mailbox Receive Interrupt Flag */
+#define                   MBRIF18  0x4        /* Mailbox 18 Mailbox Receive Interrupt Flag */
+#define                   MBRIF19  0x8        /* Mailbox 19 Mailbox Receive Interrupt Flag */
+#define                   MBRIF20  0x10       /* Mailbox 20 Mailbox Receive Interrupt Flag */
+#define                   MBRIF21  0x20       /* Mailbox 21 Mailbox Receive Interrupt Flag */
+#define                   MBRIF22  0x40       /* Mailbox 22 Mailbox Receive Interrupt Flag */
+#define                   MBRIF23  0x80       /* Mailbox 23 Mailbox Receive Interrupt Flag */
+#define                   MBRIF24  0x100      /* Mailbox 24 Mailbox Receive Interrupt Flag */
+#define                   MBRIF25  0x200      /* Mailbox 25 Mailbox Receive Interrupt Flag */
+#define                   MBRIF26  0x400      /* Mailbox 26 Mailbox Receive Interrupt Flag */
+#define                   MBRIF27  0x800      /* Mailbox 27 Mailbox Receive Interrupt Flag */
+#define                   MBRIF28  0x1000     /* Mailbox 28 Mailbox Receive Interrupt Flag */
+#define                   MBRIF29  0x2000     /* Mailbox 29 Mailbox Receive Interrupt Flag */
+#define                   MBRIF30  0x4000     /* Mailbox 30 Mailbox Receive Interrupt Flag */
+#define                   MBRIF31  0x8000     /* Mailbox 31 Mailbox Receive Interrupt Flag */
+
+/* Bit masks for EPPIx_STATUS */
+
+#define                 CFIFO_ERR  0x1        /* Chroma FIFO Error */
+#define                 YFIFO_ERR  0x2        /* Luma FIFO Error */
+#define                 LTERR_OVR  0x4        /* Line Track Overflow */
+#define                LTERR_UNDR  0x8        /* Line Track Underflow */
+#define                 FTERR_OVR  0x10       /* Frame Track Overflow */
+#define                FTERR_UNDR  0x20       /* Frame Track Underflow */
+#define                  ERR_NCOR  0x40       /* Preamble Error Not Corrected */
+#define                   DMA1URQ  0x80       /* DMA1 Urgent Request */
+#define                   DMA0URQ  0x100      /* DMA0 Urgent Request */
+#define                   ERR_DET  0x4000     /* Preamble Error Detected */
+#define                       FLD  0x8000     /* Field */
+
+/* Bit masks for EPPIx_CONTROL */
+
+#define                   EPPI_EN  0x1        /* Enable */
+#define                  EPPI_DIR  0x2        /* Direction */
+#define                  XFR_TYPE  0xc        /* Operating Mode */
+#define                    FS_CFG  0x30       /* Frame Sync Configuration */
+#define                   FLD_SEL  0x40       /* Field Select/Trigger */
+#define                  ITU_TYPE  0x80       /* ITU Interlaced or Progressive */
+#define                  BLANKGEN  0x100      /* ITU Output Mode with Internal Blanking Generation */
+#define                   ICLKGEN  0x200      /* Internal Clock Generation */
+#define                    IFSGEN  0x400      /* Internal Frame Sync Generation */
+#define                      POLC  0x1800     /* Frame Sync and Data Driving/Sampling Edges */
+#define                      POLS  0x6000     /* Frame Sync Polarity */
+#define                   DLENGTH  0x38000    /* Data Length */
+#define                   SKIP_EN  0x40000    /* Skip Enable */
+#define                   SKIP_EO  0x80000    /* Skip Even or Odd */
+#define                    PACKEN  0x100000   /* Packing/Unpacking Enable */
+#define                    SWAPEN  0x200000   /* Swap Enable */
+#define                  SIGN_EXT  0x400000   /* Sign Extension or Zero-filled / Data Split Format */
+#define             SPLT_EVEN_ODD  0x800000   /* Split Even and Odd Data Samples */
+#define               SUBSPLT_ODD  0x1000000  /* Sub-split Odd Samples */
+#define                    DMACFG  0x2000000  /* One or Two DMA Channels Mode */
+#define                RGB_FMT_EN  0x4000000  /* RGB Formatting Enable */
+#define                  FIFO_RWM  0x18000000 /* FIFO Regular Watermarks */
+#define                  FIFO_UWM  0x60000000 /* FIFO Urgent Watermarks */
+
+#define DLEN_8		(0 << 15) /* 000 - 8 bits */
+#define DLEN_10		(1 << 15) /* 001 - 10 bits */
+#define DLEN_12		(2 << 15) /* 010 - 12 bits */
+#define DLEN_14		(3 << 15) /* 011 - 14 bits */
+#define DLEN_16		(4 << 15) /* 100 - 16 bits */
+#define DLEN_18		(5 << 15) /* 101 - 18 bits */
+#define DLEN_24		(6 << 15) /* 110 - 24 bits */
+
+
+/* Bit masks for EPPIx_FS2W_LVB */
+
+#define                   F1VB_BD  0xff       /* Vertical Blanking before Field 1 Active Data */
+#define                   F1VB_AD  0xff00     /* Vertical Blanking after Field 1 Active Data */
+#define                   F2VB_BD  0xff0000   /* Vertical Blanking before Field 2 Active Data */
+#define                   F2VB_AD  0xff000000 /* Vertical Blanking after Field 2 Active Data */
+
+/* Bit masks for EPPIx_FS2W_LAVF */
+
+#define                    F1_ACT  0xffff     /* Number of Lines of Active Data in Field 1 */
+#define                    F2_ACT  0xffff0000 /* Number of Lines of Active Data in Field 2 */
+
+/* Bit masks for EPPIx_CLIP */
+
+#define                   LOW_ODD  0xff       /* Lower Limit for Odd Bytes (Chroma) */
+#define                  HIGH_ODD  0xff00     /* Upper Limit for Odd Bytes (Chroma) */
+#define                  LOW_EVEN  0xff0000   /* Lower Limit for Even Bytes (Luma) */
+#define                 HIGH_EVEN  0xff000000 /* Upper Limit for Even Bytes (Luma) */
+
+/* Bit masks for SPIx_BAUD */
+
+#define                  SPI_BAUD  0xffff     /* Baud Rate */
+
+/* Bit masks for SPIx_CTL */
+
+#define                       SPE  0x4000     /* SPI Enable */
+#define                       WOM  0x2000     /* Write Open Drain Master */
+#define                      MSTR  0x1000     /* Master Mode */
+#define                      CPOL  0x800      /* Clock Polarity */
+#define                      CPHA  0x400      /* Clock Phase */
+#define                      LSBF  0x200      /* LSB First */
+#define                      SIZE  0x100      /* Size of Words */
+#define                     EMISO  0x20       /* Enable MISO Output */
+#define                      PSSE  0x10       /* Slave-Select Enable */
+#define                        GM  0x8        /* Get More Data */
+#define                        SZ  0x4        /* Send Zero */
+#define                     TIMOD  0x3        /* Transfer Initiation Mode */
+
+/* Bit masks for SPIx_FLG */
+
+#define                      FLS1  0x2        /* Slave Select Enable 1 */
+#define                      FLS2  0x4        /* Slave Select Enable 2 */
+#define                      FLS3  0x8        /* Slave Select Enable 3 */
+#define                      FLG1  0x200      /* Slave Select Value 1 */
+#define                      FLG2  0x400      /* Slave Select Value 2 */
+#define                      FLG3  0x800      /* Slave Select Value 3 */
+
+/* Bit masks for SPIx_STAT */
+
+#define                     TXCOL  0x40       /* Transmit Collision Error */
+#define                       RXS  0x20       /* RDBR Data Buffer Status */
+#define                      RBSY  0x10       /* Receive Error */
+#define                       TXS  0x8        /* TDBR Data Buffer Status */
+#define                       TXE  0x4        /* Transmission Error */
+#define                      MODF  0x2        /* Mode Fault Error */
+#define                      SPIF  0x1        /* SPI Finished */
+
+/* Bit masks for SPIx_TDBR */
+
+#define                      TDBR  0xffff     /* Transmit Data Buffer */
+
+/* Bit masks for SPIx_RDBR */
+
+#define                      RDBR  0xffff     /* Receive Data Buffer */
+
+/* Bit masks for SPIx_SHADOW */
+
+#define                    SHADOW  0xffff     /* RDBR Shadow */
+
+/* ************************************************ */
+/* The TWI bit masks fields are from the ADSP-BF538 */
+/* and they have not been verified as the final     */
+/* ones for the Moab processors ... bz 1/19/2007    */
+/* ************************************************ */
+
+/* Bit masks for TWIx_CONTROL */
+
+#define                  PRESCALE  0x7f       /* Prescale Value */
+#define                   TWI_ENA  0x80       /* TWI Enable */
+#define                      SCCB  0x200      /* Serial Camera Control Bus */
+
+/* Bit maskes for TWIx_CLKDIV */
+
+#define                    CLKLOW  0xff       /* Clock Low */
+#define                     CLKHI  0xff00     /* Clock High */
+
+/* Bit maskes for TWIx_SLAVE_CTL */
+
+#define                       SEN  0x1        /* Slave Enable */
+#define                    STDVAL  0x4        /* Slave Transmit Data Valid */
+#define                       NAK  0x8        /* Not Acknowledge */
+#define                       GEN  0x10       /* General Call Enable */
+
+/* Bit maskes for TWIx_SLAVE_ADDR */
+
+#define                     SADDR  0x7f       /* Slave Mode Address */
+
+/* Bit maskes for TWIx_SLAVE_STAT */
+
+#define                      SDIR  0x1        /* Slave Transfer Direction */
+#define                     GCALL  0x2        /* General Call */
+
+/* Bit maskes for TWIx_MASTER_CTL */
+
+#define                       MEN  0x1        /* Master Mode Enable */
+#define                      MDIR  0x4        /* Master Transfer Direction */
+#define                      FAST  0x8        /* Fast Mode */
+#define                      STOP  0x10       /* Issue Stop Condition */
+#define                    RSTART  0x20       /* Repeat Start */
+#define                      DCNT  0x3fc0     /* Data Transfer Count */
+#define                    SDAOVR  0x4000     /* Serial Data Override */
+#define                    SCLOVR  0x8000     /* Serial Clock Override */
+
+/* Bit maskes for TWIx_MASTER_ADDR */
+
+#define                     MADDR  0x7f       /* Master Mode Address */
+
+/* Bit maskes for TWIx_MASTER_STAT */
+
+#define                     MPROG  0x1        /* Master Transfer in Progress */
+#define                   LOSTARB  0x2        /* Lost Arbitration */
+#define                      ANAK  0x4        /* Address Not Acknowledged */
+#define                      DNAK  0x8        /* Data Not Acknowledged */
+#define                  BUFRDERR  0x10       /* Buffer Read Error */
+#define                  BUFWRERR  0x20       /* Buffer Write Error */
+#define                    SDASEN  0x40       /* Serial Data Sense */
+#define                    SCLSEN  0x80       /* Serial Clock Sense */
+#define                   BUSBUSY  0x100      /* Bus Busy */
+
+/* Bit maskes for TWIx_FIFO_CTL */
+
+#define                  XMTFLUSH  0x1        /* Transmit Buffer Flush */
+#define                  RCVFLUSH  0x2        /* Receive Buffer Flush */
+#define                 XMTINTLEN  0x4        /* Transmit Buffer Interrupt Length */
+#define                 RCVINTLEN  0x8        /* Receive Buffer Interrupt Length */
+
+/* Bit maskes for TWIx_FIFO_STAT */
+
+#define                   XMTSTAT  0x3        /* Transmit FIFO Status */
+#define                   RCVSTAT  0xc        /* Receive FIFO Status */
+
+/* Bit maskes for TWIx_INT_MASK */
+
+#define                    SINITM  0x1        /* Slave Transfer Initiated Interrupt Mask */
+#define                    SCOMPM  0x2        /* Slave Transfer Complete Interrupt Mask */
+#define                     SERRM  0x4        /* Slave Transfer Error Interrupt Mask */
+#define                     SOVFM  0x8        /* Slave Overflow Interrupt Mask */
+#define                    MCOMPM  0x10       /* Master Transfer Complete Interrupt Mask */
+#define                     MERRM  0x20       /* Master Transfer Error Interrupt Mask */
+#define                  XMTSERVM  0x40       /* Transmit FIFO Service Interrupt Mask */
+#define                  RCVSERVM  0x80       /* Receive FIFO Service Interrupt Mask */
+
+/* Bit maskes for TWIx_INT_STAT */
+
+#define                     SINIT  0x1        /* Slave Transfer Initiated */
+#define                     SCOMP  0x2        /* Slave Transfer Complete */
+#define                      SERR  0x4        /* Slave Transfer Error */
+#define                      SOVF  0x8        /* Slave Overflow */
+#define                     MCOMP  0x10       /* Master Transfer Complete */
+#define                      MERR  0x20       /* Master Transfer Error */
+#define                   XMTSERV  0x40       /* Transmit FIFO Service */
+#define                   RCVSERV  0x80       /* Receive FIFO Service */
+
+/* Bit maskes for TWIx_XMT_DATA8 */
+
+#define                  XMTDATA8  0xff       /* Transmit FIFO 8-Bit Data */
+
+/* Bit maskes for TWIx_XMT_DATA16 */
+
+#define                 XMTDATA16  0xffff     /* Transmit FIFO 16-Bit Data */
+
+/* Bit maskes for TWIx_RCV_DATA8 */
+
+#define                  RCVDATA8  0xff       /* Receive FIFO 8-Bit Data */
+
+/* Bit maskes for TWIx_RCV_DATA16 */
+
+#define                 RCVDATA16  0xffff     /* Receive FIFO 16-Bit Data */
+
+/* Bit masks for SPORTx_TCR1 */
+
+#define                     TCKFE  0x4000     /* Clock Falling Edge Select */
+#define                     LATFS  0x2000     /* Late Transmit Frame Sync */
+#define                      LTFS  0x1000     /* Low Transmit Frame Sync Select */
+#define                     DITFS  0x800      /* Data-Independent Transmit Frame Sync Select */
+#define                      TFSR  0x400      /* Transmit Frame Sync Required Select */
+#define                      ITFS  0x200      /* Internal Transmit Frame Sync Select */
+#define                    TLSBIT  0x10       /* Transmit Bit Order */
+#define                    TDTYPE  0xc        /* Data Formatting Type Select */
+#define                     ITCLK  0x2        /* Internal Transmit Clock Select */
+#define                     TSPEN  0x1        /* Transmit Enable */
+
+/* Bit masks for SPORTx_TCR2 */
+
+#define                     TRFST  0x400      /* Left/Right Order */
+#define                     TSFSE  0x200      /* Transmit Stereo Frame Sync Enable */
+#define                      TXSE  0x100      /* TxSEC Enable */
+#define                    SLEN_T  0x1f       /* SPORT Word Length */
+
+/* Bit masks for SPORTx_RCR1 */
+
+#define                     RCKFE  0x4000     /* Clock Falling Edge Select */
+#define                     LARFS  0x2000     /* Late Receive Frame Sync */
+#define                      LRFS  0x1000     /* Low Receive Frame Sync Select */
+#define                      RFSR  0x400      /* Receive Frame Sync Required Select */
+#define                      IRFS  0x200      /* Internal Receive Frame Sync Select */
+#define                    RLSBIT  0x10       /* Receive Bit Order */
+#define                    RDTYPE  0xc        /* Data Formatting Type Select */
+#define                     IRCLK  0x2        /* Internal Receive Clock Select */
+#define                     RSPEN  0x1        /* Receive Enable */
+
+/* Bit masks for SPORTx_RCR2 */
+
+#define                     RRFST  0x400      /* Left/Right Order */
+#define                     RSFSE  0x200      /* Receive Stereo Frame Sync Enable */
+#define                      RXSE  0x100      /* RxSEC Enable */
+#define                    SLEN_R  0x1f       /* SPORT Word Length */
+
+/* Bit masks for SPORTx_STAT */
+
+#define                     TXHRE  0x40       /* Transmit Hold Register Empty */
+#define                      TOVF  0x20       /* Sticky Transmit Overflow Status */
+#define                      TUVF  0x10       /* Sticky Transmit Underflow Status */
+#define                       TXF  0x8        /* Transmit FIFO Full Status */
+#define                      ROVF  0x4        /* Sticky Receive Overflow Status */
+#define                      RUVF  0x2        /* Sticky Receive Underflow Status */
+#define                      RXNE  0x1        /* Receive FIFO Not Empty Status */
+
+/* Bit masks for SPORTx_MCMC1 */
+
+#define                  SP_WSIZE  0xf000     /* Window Size */
+#define                   SP_WOFF  0x3ff      /* Windows Offset */
+
+/* Bit masks for SPORTx_MCMC2 */
+
+#define                       MFD  0xf000     /* Multi channel Frame Delay */
+#define                      FSDR  0x80       /* Frame Sync to Data Relationship */
+#define                     MCMEM  0x10       /* Multi channel Frame Mode Enable */
+#define                   MCDRXPE  0x8        /* Multi channel DMA Receive Packing */
+#define                   MCDTXPE  0x4        /* Multi channel DMA Transmit Packing */
+#define                     MCCRM  0x3        /* 2X Clock Recovery Mode */
+
+/* Bit masks for SPORTx_CHNL */
+
+#define                  CUR_CHNL  0x3ff      /* Current Channel Indicator */
+
+/* Bit masks for UARTx_LCR */
+
+#if 0
+/* conflicts with legacy one in last section */
+#define                       WLS  0x3        /* Word Length Select */
+#endif
+#define                       STB  0x4        /* Stop Bits */
+#define                       PEN  0x8        /* Parity Enable */
+#define                       EPS  0x10       /* Even Parity Select */
+#define                       STP  0x20       /* Sticky Parity */
+#define                        SB  0x40       /* Set Break */
+
+/* Bit masks for UARTx_MCR */
+
+#define                      XOFF  0x1        /* Transmitter Off */
+#define                      MRTS  0x2        /* Manual Request To Send */
+#define                      RFIT  0x4        /* Receive FIFO IRQ Threshold */
+#define                      RFRT  0x8        /* Receive FIFO RTS Threshold */
+#define                  LOOP_ENA  0x10       /* Loopback Mode Enable */
+#define                     FCPOL  0x20       /* Flow Control Pin Polarity */
+#define                      ARTS  0x40       /* Automatic Request To Send */
+#define                      ACTS  0x80       /* Automatic Clear To Send */
+
+/* Bit masks for UARTx_LSR */
+
+#define                        DR  0x1        /* Data Ready */
+#define                        OE  0x2        /* Overrun Error */
+#define                        PE  0x4        /* Parity Error */
+#define                        FE  0x8        /* Framing Error */
+#define                        BI  0x10       /* Break Interrupt */
+#define                      THRE  0x20       /* THR Empty */
+#define                      TEMT  0x40       /* Transmitter Empty */
+#define                       TFI  0x80       /* Transmission Finished Indicator */
+
+/* Bit masks for UARTx_MSR */
+
+#define                      SCTS  0x1        /* Sticky CTS */
+#define                       CTS  0x10       /* Clear To Send */
+#define                      RFCS  0x20       /* Receive FIFO Count Status */
+
+/* Bit masks for UARTx_IER_SET & UARTx_IER_CLEAR */
+
+#define                   ERBFI  0x1        /* Enable Receive Buffer Full Interrupt */
+#define                   ETBEI  0x2        /* Enable Transmit Buffer Empty Interrupt */
+#define                    ELSI  0x4        /* Enable Receive Status Interrupt */
+#define                   EDSSI  0x8        /* Enable Modem Status Interrupt */
+#define                  EDTPTI  0x10       /* Enable DMA Transmit PIRQ Interrupt */
+#define                    ETFI  0x20       /* Enable Transmission Finished Interrupt */
+#define                   ERFCI  0x40       /* Enable Receive FIFO Count Interrupt */
+
+/* Bit masks for UARTx_GCTL */
+
+#define                      UCEN  0x1        /* UART Enable */
+#define                      IREN  0x2        /* IrDA Mode Enable */
+#define                     TPOLC  0x4        /* IrDA TX Polarity Change */
+#define                     RPOLC  0x8        /* IrDA RX Polarity Change */
+#define                       FPE  0x10       /* Force Parity Error */
+#define                       FFE  0x20       /* Force Framing Error */
+#define                      EDBO  0x40       /* Enable Divide-by-One */
+#define                     EGLSI  0x80       /* Enable Global LS Interrupt */
+
+
+/* ******************************************* */
+/*     MULTI BIT MACRO ENUMERATIONS            */
+/* ******************************************* */
+
+/* BCODE bit field options (SYSCFG register) */
+
+#define BCODE_WAKEUP    0x0000  /* boot according to wake-up condition */
+#define BCODE_FULLBOOT  0x0010  /* always perform full boot */
+#define BCODE_QUICKBOOT 0x0020  /* always perform quick boot */
+#define BCODE_NOBOOT    0x0030  /* always perform full boot */
+
+/* CNT_COMMAND bit field options */
+
+#define W1LCNT_ZERO   0x0001   /* write 1 to load CNT_COUNTER with zero */
+#define W1LCNT_MIN    0x0004   /* write 1 to load CNT_COUNTER from CNT_MIN */
+#define W1LCNT_MAX    0x0008   /* write 1 to load CNT_COUNTER from CNT_MAX */
+
+#define W1LMIN_ZERO   0x0010   /* write 1 to load CNT_MIN with zero */
+#define W1LMIN_CNT    0x0020   /* write 1 to load CNT_MIN from CNT_COUNTER */
+#define W1LMIN_MAX    0x0080   /* write 1 to load CNT_MIN from CNT_MAX */
+
+#define W1LMAX_ZERO   0x0100   /* write 1 to load CNT_MAX with zero */
+#define W1LMAX_CNT    0x0200   /* write 1 to load CNT_MAX from CNT_COUNTER */
+#define W1LMAX_MIN    0x0400   /* write 1 to load CNT_MAX from CNT_MIN */
+
+/* CNT_CONFIG bit field options */
+
+#define CNTMODE_QUADENC  0x0000  /* quadrature encoder mode */
+#define CNTMODE_BINENC   0x0100  /* binary encoder mode */
+#define CNTMODE_UDCNT    0x0200  /* up/down counter mode */
+#define CNTMODE_DIRCNT   0x0400  /* direction counter mode */
+#define CNTMODE_DIRTMR   0x0500  /* direction timer mode */
+
+#define BNDMODE_COMP     0x0000  /* boundary compare mode */
+#define BNDMODE_ZERO     0x1000  /* boundary compare and zero mode */
+#define BNDMODE_CAPT     0x2000  /* boundary capture mode */
+#define BNDMODE_AEXT     0x3000  /* boundary auto-extend mode */
+
+/* TMODE in TIMERx_CONFIG bit field options */
+
+#define PWM_OUT  0x0001
+#define WDTH_CAP 0x0002
+#define EXT_CLK  0x0003
+
+/* UARTx_LCR bit field options */
+
+#define WLS_5   0x0000    /* 5 data bits */
+#define WLS_6   0x0001    /* 6 data bits */
+#define WLS_7   0x0002    /* 7 data bits */
+#define WLS_8   0x0003    /* 8 data bits */
+
+/* PINTx Register Bit Definitions */
+
+#define PIQ0 0x00000001
+#define PIQ1 0x00000002
+#define PIQ2 0x00000004
+#define PIQ3 0x00000008
+
+#define PIQ4 0x00000010
+#define PIQ5 0x00000020
+#define PIQ6 0x00000040
+#define PIQ7 0x00000080
+
+#define PIQ8 0x00000100
+#define PIQ9 0x00000200
+#define PIQ10 0x00000400
+#define PIQ11 0x00000800
+
+#define PIQ12 0x00001000
+#define PIQ13 0x00002000
+#define PIQ14 0x00004000
+#define PIQ15 0x00008000
+
+#define PIQ16 0x00010000
+#define PIQ17 0x00020000
+#define PIQ18 0x00040000
+#define PIQ19 0x00080000
+
+#define PIQ20 0x00100000
+#define PIQ21 0x00200000
+#define PIQ22 0x00400000
+#define PIQ23 0x00800000
+
+#define PIQ24 0x01000000
+#define PIQ25 0x02000000
+#define PIQ26 0x04000000
+#define PIQ27 0x08000000
+
+#define PIQ28 0x10000000
+#define PIQ29 0x20000000
+#define PIQ30 0x40000000
+#define PIQ31 0x80000000
+
+/* PORT A Bit Definitions for the registers
+PORTA, PORTA_SET, PORTA_CLEAR,
+PORTA_DIR_SET, PORTA_DIR_CLEAR, PORTA_INEN,
+PORTA_FER registers
+*/
+
+#define PA0 0x0001
+#define PA1 0x0002
+#define PA2 0x0004
+#define PA3 0x0008
+#define PA4 0x0010
+#define PA5 0x0020
+#define PA6 0x0040
+#define PA7 0x0080
+#define PA8 0x0100
+#define PA9 0x0200
+#define PA10 0x0400
+#define PA11 0x0800
+#define PA12 0x1000
+#define PA13 0x2000
+#define PA14 0x4000
+#define PA15 0x8000
+
+/* PORT B Bit Definitions for the registers
+PORTB, PORTB_SET, PORTB_CLEAR,
+PORTB_DIR_SET, PORTB_DIR_CLEAR, PORTB_INEN,
+PORTB_FER registers
+*/
+
+#define PB0 0x0001
+#define PB1 0x0002
+#define PB2 0x0004
+#define PB3 0x0008
+#define PB4 0x0010
+#define PB5 0x0020
+#define PB6 0x0040
+#define PB7 0x0080
+#define PB8 0x0100
+#define PB9 0x0200
+#define PB10 0x0400
+#define PB11 0x0800
+#define PB12 0x1000
+#define PB13 0x2000
+#define PB14 0x4000
+
+
+/* PORT C Bit Definitions for the registers
+PORTC, PORTC_SET, PORTC_CLEAR,
+PORTC_DIR_SET, PORTC_DIR_CLEAR, PORTC_INEN,
+PORTC_FER registers
+*/
+
+
+#define PC0 0x0001
+#define PC1 0x0002
+#define PC2 0x0004
+#define PC3 0x0008
+#define PC4 0x0010
+#define PC5 0x0020
+#define PC6 0x0040
+#define PC7 0x0080
+#define PC8 0x0100
+#define PC9 0x0200
+#define PC10 0x0400
+#define PC11 0x0800
+#define PC12 0x1000
+#define PC13 0x2000
+
+
+/* PORT D Bit Definitions for the registers
+PORTD, PORTD_SET, PORTD_CLEAR,
+PORTD_DIR_SET, PORTD_DIR_CLEAR, PORTD_INEN,
+PORTD_FER registers
+*/
+
+#define PD0 0x0001
+#define PD1 0x0002
+#define PD2 0x0004
+#define PD3 0x0008
+#define PD4 0x0010
+#define PD5 0x0020
+#define PD6 0x0040
+#define PD7 0x0080
+#define PD8 0x0100
+#define PD9 0x0200
+#define PD10 0x0400
+#define PD11 0x0800
+#define PD12 0x1000
+#define PD13 0x2000
+#define PD14 0x4000
+#define PD15 0x8000
+
+/* PORT E Bit Definitions for the registers
+PORTE, PORTE_SET, PORTE_CLEAR,
+PORTE_DIR_SET, PORTE_DIR_CLEAR, PORTE_INEN,
+PORTE_FER registers
+*/
+
+
+#define PE0 0x0001
+#define PE1 0x0002
+#define PE2 0x0004
+#define PE3 0x0008
+#define PE4 0x0010
+#define PE5 0x0020
+#define PE6 0x0040
+#define PE7 0x0080
+#define PE8 0x0100
+#define PE9 0x0200
+#define PE10 0x0400
+#define PE11 0x0800
+#define PE12 0x1000
+#define PE13 0x2000
+#define PE14 0x4000
+#define PE15 0x8000
+
+/* PORT F Bit Definitions for the registers
+PORTF, PORTF_SET, PORTF_CLEAR,
+PORTF_DIR_SET, PORTF_DIR_CLEAR, PORTF_INEN,
+PORTF_FER registers
+*/
+
+
+#define PF0 0x0001
+#define PF1 0x0002
+#define PF2 0x0004
+#define PF3 0x0008
+#define PF4 0x0010
+#define PF5 0x0020
+#define PF6 0x0040
+#define PF7 0x0080
+#define PF8 0x0100
+#define PF9 0x0200
+#define PF10 0x0400
+#define PF11 0x0800
+#define PF12 0x1000
+#define PF13 0x2000
+#define PF14 0x4000
+#define PF15 0x8000
+
+/* PORT G Bit Definitions for the registers
+PORTG, PORTG_SET, PORTG_CLEAR,
+PORTG_DIR_SET, PORTG_DIR_CLEAR, PORTG_INEN,
+PORTG_FER registers
+*/
+
+
+#define PG0 0x0001
+#define PG1 0x0002
+#define PG2 0x0004
+#define PG3 0x0008
+#define PG4 0x0010
+#define PG5 0x0020
+#define PG6 0x0040
+#define PG7 0x0080
+#define PG8 0x0100
+#define PG9 0x0200
+#define PG10 0x0400
+#define PG11 0x0800
+#define PG12 0x1000
+#define PG13 0x2000
+#define PG14 0x4000
+#define PG15 0x8000
+
+/* PORT H Bit Definitions for the registers
+PORTH, PORTH_SET, PORTH_CLEAR,
+PORTH_DIR_SET, PORTH_DIR_CLEAR, PORTH_INEN,
+PORTH_FER registers
+*/
+
+
+#define PH0 0x0001
+#define PH1 0x0002
+#define PH2 0x0004
+#define PH3 0x0008
+#define PH4 0x0010
+#define PH5 0x0020
+#define PH6 0x0040
+#define PH7 0x0080
+#define PH8 0x0100
+#define PH9 0x0200
+#define PH10 0x0400
+#define PH11 0x0800
+#define PH12 0x1000
+#define PH13 0x2000
+
+
+/* PORT I Bit Definitions for the registers
+PORTI, PORTI_SET, PORTI_CLEAR,
+PORTI_DIR_SET, PORTI_DIR_CLEAR, PORTI_INEN,
+PORTI_FER registers
+*/
+
+
+#define PI0 0x0001
+#define PI1 0x0002
+#define PI2 0x0004
+#define PI3 0x0008
+#define PI4 0x0010
+#define PI5 0x0020
+#define PI6 0x0040
+#define PI7 0x0080
+#define PI8 0x0100
+#define PI9 0x0200
+#define PI10 0x0400
+#define PI11 0x0800
+#define PI12 0x1000
+#define PI13 0x2000
+#define PI14 0x4000
+#define PI15 0x8000
+
+/* PORT J Bit Definitions for the registers
+PORTJ, PORTJ_SET, PORTJ_CLEAR,
+PORTJ_DIR_SET, PORTJ_DIR_CLEAR, PORTJ_INEN,
+PORTJ_FER registers
+*/
+
+
+#define PJ0 0x0001
+#define PJ1 0x0002
+#define PJ2 0x0004
+#define PJ3 0x0008
+#define PJ4 0x0010
+#define PJ5 0x0020
+#define PJ6 0x0040
+#define PJ7 0x0080
+#define PJ8 0x0100
+#define PJ9 0x0200
+#define PJ10 0x0400
+#define PJ11 0x0800
+#define PJ12 0x1000
+#define PJ13 0x2000
+
+
+/* Port Muxing Bit Fields for PORTx_MUX Registers */
+
+#define MUX0 0x00000003
+#define MUX0_0 0x00000000
+#define MUX0_1 0x00000001
+#define MUX0_2 0x00000002
+#define MUX0_3 0x00000003
+
+#define MUX1 0x0000000C
+#define MUX1_0 0x00000000
+#define MUX1_1 0x00000004
+#define MUX1_2 0x00000008
+#define MUX1_3 0x0000000C
+
+#define MUX2 0x00000030
+#define MUX2_0 0x00000000
+#define MUX2_1 0x00000010
+#define MUX2_2 0x00000020
+#define MUX2_3 0x00000030
+
+#define MUX3 0x000000C0
+#define MUX3_0 0x00000000
+#define MUX3_1 0x00000040
+#define MUX3_2 0x00000080
+#define MUX3_3 0x000000C0
+
+#define MUX4 0x00000300
+#define MUX4_0 0x00000000
+#define MUX4_1 0x00000100
+#define MUX4_2 0x00000200
+#define MUX4_3 0x00000300
+
+#define MUX5 0x00000C00
+#define MUX5_0 0x00000000
+#define MUX5_1 0x00000400
+#define MUX5_2 0x00000800
+#define MUX5_3 0x00000C00
+
+#define MUX6 0x00003000
+#define MUX6_0 0x00000000
+#define MUX6_1 0x00001000
+#define MUX6_2 0x00002000
+#define MUX6_3 0x00003000
+
+#define MUX7 0x0000C000
+#define MUX7_0 0x00000000
+#define MUX7_1 0x00004000
+#define MUX7_2 0x00008000
+#define MUX7_3 0x0000C000
+
+#define MUX8 0x00030000
+#define MUX8_0 0x00000000
+#define MUX8_1 0x00010000
+#define MUX8_2 0x00020000
+#define MUX8_3 0x00030000
+
+#define MUX9 0x000C0000
+#define MUX9_0 0x00000000
+#define MUX9_1 0x00040000
+#define MUX9_2 0x00080000
+#define MUX9_3 0x000C0000
+
+#define MUX10 0x00300000
+#define MUX10_0 0x00000000
+#define MUX10_1 0x00100000
+#define MUX10_2 0x00200000
+#define MUX10_3 0x00300000
+
+#define MUX11 0x00C00000
+#define MUX11_0 0x00000000
+#define MUX11_1 0x00400000
+#define MUX11_2 0x00800000
+#define MUX11_3 0x00C00000
+
+#define MUX12 0x03000000
+#define MUX12_0 0x00000000
+#define MUX12_1 0x01000000
+#define MUX12_2 0x02000000
+#define MUX12_3 0x03000000
+
+#define MUX13 0x0C000000
+#define MUX13_0 0x00000000
+#define MUX13_1 0x04000000
+#define MUX13_2 0x08000000
+#define MUX13_3 0x0C000000
+
+#define MUX14 0x30000000
+#define MUX14_0 0x00000000
+#define MUX14_1 0x10000000
+#define MUX14_2 0x20000000
+#define MUX14_3 0x30000000
+
+#define MUX15 0xC0000000
+#define MUX15_0 0x00000000
+#define MUX15_1 0x40000000
+#define MUX15_2 0x80000000
+#define MUX15_3 0xC0000000
+
+#define MUX(b15,b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0) \
+    ((((b15)&3) << 30) | \
+     (((b14)&3) << 28) | \
+     (((b13)&3) << 26) | \
+     (((b12)&3) << 24) | \
+     (((b11)&3) << 22) | \
+     (((b10)&3) << 20) | \
+     (((b9) &3) << 18) | \
+     (((b8) &3) << 16) | \
+     (((b7) &3) << 14) | \
+     (((b6) &3) << 12) | \
+     (((b5) &3) << 10) | \
+     (((b4) &3) << 8)  | \
+     (((b3) &3) << 6)  | \
+     (((b2) &3) << 4)  | \
+     (((b1) &3) << 2)  | \
+     (((b0) &3)))
+
+/* Bit fields for PINT0_ASSIGN and PINT1_ASSIGN registers */
+
+#define B0MAP 0x000000FF     /* Byte 0 Lower Half Port Mapping */
+#define B0MAP_PAL 0x00000000 /* Map Port A Low to Byte 0 */
+#define B0MAP_PBL 0x00000001 /* Map Port B Low to Byte 0 */
+#define B1MAP 0x0000FF00     /* Byte 1 Upper Half Port Mapping */
+#define B1MAP_PAH 0x00000000 /* Map Port A High to Byte 1 */
+#define B1MAP_PBH 0x00000100 /* Map Port B High to Byte 1 */
+#define B2MAP 0x00FF0000     /* Byte 2 Lower Half Port Mapping */
+#define B2MAP_PAL 0x00000000 /* Map Port A Low to Byte 2 */
+#define B2MAP_PBL 0x00010000 /* Map Port B Low to Byte 2 */
+#define B3MAP 0xFF000000     /* Byte 3 Upper Half Port Mapping */
+#define B3MAP_PAH 0x00000000 /* Map Port A High to Byte 3 */
+#define B3MAP_PBH 0x01000000 /* Map Port B High to Byte 3 */
+
+/* Bit fields for PINT2_ASSIGN and PINT3_ASSIGN registers */
+
+#define B0MAP_PCL 0x00000000 /* Map Port C Low to Byte 0 */
+#define B0MAP_PDL 0x00000001 /* Map Port D Low to Byte 0 */
+#define B0MAP_PEL 0x00000002 /* Map Port E Low to Byte 0 */
+#define B0MAP_PFL 0x00000003 /* Map Port F Low to Byte 0 */
+#define B0MAP_PGL 0x00000004 /* Map Port G Low to Byte 0 */
+#define B0MAP_PHL 0x00000005 /* Map Port H Low to Byte 0 */
+#define B0MAP_PIL 0x00000006 /* Map Port I Low to Byte 0 */
+#define B0MAP_PJL 0x00000007 /* Map Port J Low to Byte 0 */
+
+#define B1MAP_PCH 0x00000000 /* Map Port C High to Byte 1 */
+#define B1MAP_PDH 0x00000100 /* Map Port D High to Byte 1 */
+#define B1MAP_PEH 0x00000200 /* Map Port E High to Byte 1 */
+#define B1MAP_PFH 0x00000300 /* Map Port F High to Byte 1 */
+#define B1MAP_PGH 0x00000400 /* Map Port G High to Byte 1 */
+#define B1MAP_PHH 0x00000500 /* Map Port H High to Byte 1 */
+#define B1MAP_PIH 0x00000600 /* Map Port I High to Byte 1 */
+#define B1MAP_PJH 0x00000700 /* Map Port J High to Byte 1 */
+
+#define B2MAP_PCL 0x00000000 /* Map Port C Low to Byte 2 */
+#define B2MAP_PDL 0x00010000 /* Map Port D Low to Byte 2 */
+#define B2MAP_PEL 0x00020000 /* Map Port E Low to Byte 2 */
+#define B2MAP_PFL 0x00030000 /* Map Port F Low to Byte 2 */
+#define B2MAP_PGL 0x00040000 /* Map Port G Low to Byte 2 */
+#define B2MAP_PHL 0x00050000 /* Map Port H Low to Byte 2 */
+#define B2MAP_PIL 0x00060000 /* Map Port I Low to Byte 2 */
+#define B2MAP_PJL 0x00070000 /* Map Port J Low to Byte 2 */
+
+#define B3MAP_PCH 0x00000000 /* Map Port C High to Byte 3 */
+#define B3MAP_PDH 0x01000000 /* Map Port D High to Byte 3 */
+#define B3MAP_PEH 0x02000000 /* Map Port E High to Byte 3 */
+#define B3MAP_PFH 0x03000000 /* Map Port F High to Byte 3 */
+#define B3MAP_PGH 0x04000000 /* Map Port G High to Byte 3 */
+#define B3MAP_PHH 0x05000000 /* Map Port H High to Byte 3 */
+#define B3MAP_PIH 0x06000000 /* Map Port I High to Byte 3 */
+#define B3MAP_PJH 0x07000000 /* Map Port J High to Byte 3 */
+
+
+/* for legacy compatibility */
+
+#define WLS(x)  (((x)-5) & 0x03) /* Word Length Select */
+#define W1LMAX_MAX W1LMAX_MIN
+#define EBIU_AMCBCTL0 EBIU_AMBCTL0
+#define EBIU_AMCBCTL1 EBIU_AMBCTL1
+#define PINT0_IRQ PINT0_REQUEST
+#define PINT1_IRQ PINT1_REQUEST
+#define PINT2_IRQ PINT2_REQUEST
+#define PINT3_IRQ PINT3_REQUEST
+
+#endif /* _DEF_BF54X_H */
diff --git a/include/asm-blackfin/mach-bf548/dma.h b/include/asm-blackfin/mach-bf548/dma.h
new file mode 100644
index 0000000..fcc8b4c
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/dma.h
@@ -0,0 +1,73 @@
+/*
+ * file:         include/asm-blackfin/mach-bf548/dma.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *	system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose.  see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define CH_SPORT0_RX		0
+#define CH_SPORT0_TX		1
+#define CH_SPORT1_RX		2
+#define CH_SPORT1_TX		3
+#define CH_SPI0			4
+#define CH_SPI1			5
+#define CH_UART0_RX 		6
+#define CH_UART0_TX 		7
+#define CH_UART1_RX 		8
+#define CH_UART1_TX 		9
+#define CH_ATAPI_RX		10
+#define CH_ATAPI_TX		11
+#define CH_EPPI0		12
+#define CH_EPPI1		13
+#define CH_EPPI2		14
+#define CH_PIXC_IMAGE		15
+#define CH_PIXC_OVERLAY		16
+#define CH_PIXC_OUTPUT		17
+#define CH_SPORT2_RX		18
+#define CH_SPORT2_TX		19
+#define CH_SPORT3_RX		20
+#define CH_SPORT3_TX		21
+#define CH_SDH			22
+#define CH_SPI2			23
+
+#define CH_MEM_STREAM0_DEST	24
+#define CH_MEM_STREAM0_SRC	25
+#define CH_MEM_STREAM1_DEST	26
+#define CH_MEM_STREAM1_SRC	27
+#define CH_MEM_STREAM2_DEST	28
+#define CH_MEM_STREAM2_SRC	29
+#define CH_MEM_STREAM3_DEST	30
+#define CH_MEM_STREAM3_SRC	31
+
+#define MAX_BLACKFIN_DMA_CHANNEL 32
+
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+#endif
diff --git a/include/asm-blackfin/mach-bf548/gpio.h b/include/asm-blackfin/mach-bf548/gpio.h
new file mode 100644
index 0000000..dbf66bc
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/gpio.h
@@ -0,0 +1,216 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/gpio.h
+ * Based on:
+ * Author:	 Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+#define GPIO_PA0	0
+#define GPIO_PA1	1
+#define GPIO_PA2	2
+#define GPIO_PA3	3
+#define GPIO_PA4	4
+#define GPIO_PA5	5
+#define GPIO_PA6	6
+#define GPIO_PA7	7
+#define GPIO_PA8	8
+#define GPIO_PA9	9
+#define GPIO_PA10	10
+#define GPIO_PA11	11
+#define GPIO_PA12	12
+#define GPIO_PA13	13
+#define GPIO_PA14	14
+#define GPIO_PA15	15
+#define GPIO_PB0	16
+#define GPIO_PB1	17
+#define GPIO_PB2	18
+#define GPIO_PB3	19
+#define GPIO_PB4	20
+#define GPIO_PB5	21
+#define GPIO_PB6	22
+#define GPIO_PB7	23
+#define GPIO_PB8	24
+#define GPIO_PB9	25
+#define GPIO_PB10	26
+#define GPIO_PB11	27
+#define GPIO_PB12	28
+#define GPIO_PB13	29
+#define GPIO_PB14	30
+#define GPIO_PB15	31	/* N/A */
+#define GPIO_PC0	32
+#define GPIO_PC1	33
+#define GPIO_PC2	34
+#define GPIO_PC3	35
+#define GPIO_PC4	36
+#define GPIO_PC5	37
+#define GPIO_PC6	38
+#define GPIO_PC7	39
+#define GPIO_PC8	40
+#define GPIO_PC9	41
+#define GPIO_PC10	42
+#define GPIO_PC11	43
+#define GPIO_PC12	44
+#define GPIO_PC13	45
+#define GPIO_PC14	46	/* N/A */
+#define GPIO_PC15	47	/* N/A */
+#define GPIO_PD0	48
+#define GPIO_PD1	49
+#define GPIO_PD2	50
+#define GPIO_PD3	51
+#define GPIO_PD4	52
+#define GPIO_PD5	53
+#define GPIO_PD6	54
+#define GPIO_PD7	55
+#define GPIO_PD8	56
+#define GPIO_PD9	57
+#define GPIO_PD10	58
+#define GPIO_PD11	59
+#define GPIO_PD12	60
+#define GPIO_PD13	61
+#define GPIO_PD14	62
+#define GPIO_PD15	63
+#define GPIO_PE0	64
+#define GPIO_PE1	65
+#define GPIO_PE2	66
+#define GPIO_PE3	67
+#define GPIO_PE4	68
+#define GPIO_PE5	69
+#define GPIO_PE6	70
+#define GPIO_PE7	71
+#define GPIO_PE8	72
+#define GPIO_PE9	73
+#define GPIO_PE10	74
+#define GPIO_PE11	75
+#define GPIO_PE12	76
+#define GPIO_PE13	77
+#define GPIO_PE14	78
+#define GPIO_PE15	79
+#define GPIO_PF0	80
+#define GPIO_PF1	81
+#define GPIO_PF2	82
+#define GPIO_PF3	83
+#define GPIO_PF4	84
+#define GPIO_PF5	85
+#define GPIO_PF6	86
+#define GPIO_PF7	87
+#define GPIO_PF8	88
+#define GPIO_PF9	89
+#define GPIO_PF10	90
+#define GPIO_PF11	91
+#define GPIO_PF12	92
+#define GPIO_PF13	93
+#define GPIO_PF14	94
+#define GPIO_PF15	95
+#define GPIO_PG0	96
+#define GPIO_PG1	97
+#define GPIO_PG2	98
+#define GPIO_PG3	99
+#define GPIO_PG4	100
+#define GPIO_PG5	101
+#define GPIO_PG6	102
+#define GPIO_PG7	103
+#define GPIO_PG8	104
+#define GPIO_PG9	105
+#define GPIO_PG10	106
+#define GPIO_PG11	107
+#define GPIO_PG12	108
+#define GPIO_PG13	109
+#define GPIO_PG14	110
+#define GPIO_PG15	111
+#define GPIO_PH0	112
+#define GPIO_PH1	113
+#define GPIO_PH2	114
+#define GPIO_PH3	115
+#define GPIO_PH4	116
+#define GPIO_PH5	117
+#define GPIO_PH6	118
+#define GPIO_PH7	119
+#define GPIO_PH8	120
+#define GPIO_PH9	121
+#define GPIO_PH10	122
+#define GPIO_PH11	123
+#define GPIO_PH12	124
+#define GPIO_PH13	125
+#define GPIO_PH14	126	/* N/A */
+#define GPIO_PH15	127	/* N/A */
+#define GPIO_PI0	128
+#define GPIO_PI1	129
+#define GPIO_PI2	130
+#define GPIO_PI3	131
+#define GPIO_PI4	132
+#define GPIO_PI5	133
+#define GPIO_PI6	134
+#define GPIO_PI7	135
+#define GPIO_PI8	136
+#define GPIO_PI9	137
+#define GPIO_PI10	138
+#define GPIO_PI11	139
+#define GPIO_PI12	140
+#define GPIO_PI13	141
+#define GPIO_PI14	142
+#define GPIO_PI15	143
+#define GPIO_PJ0	144
+#define GPIO_PJ1	145
+#define GPIO_PJ2	146
+#define GPIO_PJ3	147
+#define GPIO_PJ4	148
+#define GPIO_PJ5	149
+#define GPIO_PJ6	150
+#define GPIO_PJ7	151
+#define GPIO_PJ8	152
+#define GPIO_PJ9	153
+#define GPIO_PJ10	154
+#define GPIO_PJ11	155
+#define GPIO_PJ12	156
+#define GPIO_PJ13	157
+#define GPIO_PJ14	158	/* N/A */
+#define GPIO_PJ15	159	/* N/A */
+
+#define MAX_BLACKFIN_GPIOS 160
+
+struct gpio_port_t {
+	unsigned short port_fer;
+	unsigned short dummy1;
+	unsigned short port_data;
+	unsigned short dummy2;
+	unsigned short port_set;
+	unsigned short dummy3;
+	unsigned short port_clear;
+	unsigned short dummy4;
+	unsigned short port_dir_set;
+	unsigned short dummy5;
+	unsigned short port_dir_clear;
+	unsigned short dummy6;
+	unsigned short port_inen;
+	unsigned short dummy7;
+	unsigned int port_mux;
+};
+
+int gpio_request(unsigned short gpio, const char *label);
+void peripheral_free(unsigned short per);
+int peripheral_request_list(unsigned short per[], const char *label);
+void peripheral_free_list(unsigned short per[]);
diff --git a/include/asm-blackfin/mach-bf548/irq.h b/include/asm-blackfin/mach-bf548/irq.h
new file mode 100644
index 0000000..0b3325b
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/irq.h
@@ -0,0 +1,467 @@
+/*
+ * file:	include/asm-blackfin/mach-bf548/irq.h
+ * based on:	include/asm-blackfin/mach-bf537/irq.h
+ * author:	Roy Huang (roy.huang@analog.com)
+ *
+ * created:
+ * description:
+ *	system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose.  see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _BF548_IRQ_H_
+#define _BF548_IRQ_H_
+
+/*
+ * Interrupt source definitions
+            Event Source    Core Event Name
+Core        Emulation               **
+Events         (highest priority)  EMU         0
+            Reset                   RST         1
+            NMI                     NMI         2
+            Exception               EVX         3
+            Reserved                --          4
+            Hardware Error          IVHW        5
+            Core Timer              IVTMR       6 *
+
+.....
+
+            Software Interrupt 1    IVG14       31
+            Software Interrupt 2    --
+                 (lowest priority)  IVG15       32 *
+ */
+
+#define NR_PERI_INTS    (32 * 3)
+
+/* The ABSTRACT IRQ definitions */
+/** the first seven of the following are fixed, the rest you change if you need to **/
+#define IRQ_EMU		0	/* Emulation */
+#define IRQ_RST		1	/* reset */
+#define IRQ_NMI		2	/* Non Maskable */
+#define IRQ_EVX		3	/* Exception */
+#define IRQ_UNUSED	4	/* - unused interrupt*/
+#define IRQ_HWERR	5	/* Hardware Error */
+#define IRQ_CORETMR	6	/* Core timer */
+
+#define BFIN_IRQ(x)	((x) + 7)
+
+#define IRQ_PLL_WAKEUP	BFIN_IRQ(0)	/* PLL Wakeup Interrupt */
+#define IRQ_DMAC0_ERR	BFIN_IRQ(1)	/* DMAC0 Status Interrupt */
+#define IRQ_EPPI0_ERR	BFIN_IRQ(2)	/* EPPI0 Error Interrupt */
+#define IRQ_SPORT0_ERR	BFIN_IRQ(3)	/* SPORT0 Error Interrupt */
+#define IRQ_SPORT1_ERR	BFIN_IRQ(4)	/* SPORT1 Error Interrupt */
+#define IRQ_SPI0_ERR	BFIN_IRQ(5)	/* SPI0 Status(Error) Interrupt */
+#define IRQ_UART0_ERR	BFIN_IRQ(6)	/* UART0 Status(Error) Interrupt */
+#define IRQ_RTC		BFIN_IRQ(7)	/* RTC Interrupt */
+#define IRQ_EPPI0	BFIN_IRQ(8)	/* EPPI0 Interrupt (DMA12) */
+#define IRQ_SPORT0_RX	BFIN_IRQ(9)	/* SPORT0 RX Interrupt (DMA0) */
+#define IRQ_SPORT0_TX	BFIN_IRQ(10)	/* SPORT0 TX Interrupt (DMA1) */
+#define IRQ_SPORT1_RX	BFIN_IRQ(11)	/* SPORT1 RX Interrupt (DMA2) */
+#define IRQ_SPORT1_TX	BFIN_IRQ(12)	/* SPORT1 TX Interrupt (DMA3) */
+#define IRQ_SPI0	BFIN_IRQ(13)	/* SPI0 Interrupt (DMA4) */
+#define IRQ_UART0_RX	BFIN_IRQ(14)	/* UART0 RX Interrupt (DMA6) */
+#define IRQ_UART0_TX	BFIN_IRQ(15)	/* UART0 TX Interrupt (DMA7) */
+#define IRQ_TIMER8	BFIN_IRQ(16)	/* TIMER 8 Interrupt */
+#define IRQ_TIMER9	BFIN_IRQ(17)	/* TIMER 9 Interrupt */
+#define IRQ_TIMER10	BFIN_IRQ(18)	/* TIMER 10 Interrupt */
+#define IRQ_PINT0	BFIN_IRQ(19)	/* PINT0 Interrupt */
+#define IRQ_PINT1	BFIN_IRQ(20)	/* PINT1 Interrupt */
+#define IRQ_MDMAS0	BFIN_IRQ(21)	/* MDMA Stream 0 Interrupt */
+#define IRQ_MDMAS1	BFIN_IRQ(22)	/* MDMA Stream 1 Interrupt */
+#define IRQ_WATCHDOG	BFIN_IRQ(23)	/* Watchdog Interrupt */
+#define IRQ_DMAC1_ERR	BFIN_IRQ(24)	/* DMAC1 Status (Error) Interrupt */
+#define IRQ_SPORT2_ERR	BFIN_IRQ(25)	/* SPORT2 Error Interrupt */
+#define IRQ_SPORT3_ERR	BFIN_IRQ(26)	/* SPORT3 Error Interrupt */
+#define IRQ_MXVR_DATA	BFIN_IRQ(27)	/* MXVR Data Interrupt */
+#define IRQ_SPI1_ERR	BFIN_IRQ(28)	/* SPI1 Status (Error) Interrupt */
+#define IRQ_SPI2_ERR	BFIN_IRQ(29)	/* SPI2 Status (Error) Interrupt */
+#define IRQ_UART1_ERR	BFIN_IRQ(30)	/* UART1 Status (Error) Interrupt */
+#define IRQ_UART2_ERR	BFIN_IRQ(31)	/* UART2 Status (Error) Interrupt */
+#define IRQ_CAN0_ERR	BFIN_IRQ(32)	/* CAN0 Status (Error) Interrupt */
+#define IRQ_SPORT2_RX	BFIN_IRQ(33)	/* SPORT2 RX (DMA18) Interrupt */
+#define IRQ_SPORT2_TX	BFIN_IRQ(34)	/* SPORT2 TX (DMA19) Interrupt */
+#define IRQ_SPORT3_RX	BFIN_IRQ(35)	/* SPORT3 RX (DMA20) Interrupt */
+#define IRQ_SPORT3_TX	BFIN_IRQ(36)	/* SPORT3 TX (DMA21) Interrupt */
+#define IRQ_EPPI1	BFIN_IRQ(37)	/* EPP1 (DMA13) Interrupt */
+#define IRQ_EPPI2	BFIN_IRQ(38)	/* EPP2 (DMA14) Interrupt */
+#define IRQ_SPI1	BFIN_IRQ(39)	/* SPI1 (DMA5) Interrupt */
+#define IRQ_SPI2	BFIN_IRQ(40)	/* SPI2 (DMA23) Interrupt */
+#define IRQ_UART1_RX	BFIN_IRQ(41)	/* UART1 RX (DMA8) Interrupt */
+#define IRQ_UART1_TX	BFIN_IRQ(42)	/* UART1 TX (DMA9) Interrupt */
+#define IRQ_ATAPI_RX	BFIN_IRQ(43)	/* ATAPI RX (DMA10) Interrupt */
+#define IRQ_ATAPI_TX	BFIN_IRQ(44)	/* ATAPI TX (DMA11) Interrupt */
+#define IRQ_TWI0	BFIN_IRQ(45)	/* TWI0 Interrupt */
+#define IRQ_TWI1	BFIN_IRQ(46)	/* TWI1 Interrupt */
+#define IRQ_CAN0_RX	BFIN_IRQ(47)	/* CAN0 Receive Interrupt */
+#define IRQ_CAN0_TX	BFIN_IRQ(48)	/* CAN0 Transmit Interrupt */
+#define IRQ_MDMAS2	BFIN_IRQ(49)	/* MDMA Stream 2 Interrupt */
+#define IRQ_MDMAS3	BFIN_IRQ(50)	/* MDMA Stream 3 Interrupt */
+#define IRQ_MXVR_ERR	BFIN_IRQ(51)	/* MXVR Status (Error) Interrupt */
+#define IRQ_MXVR_MSG	BFIN_IRQ(52)	/* MXVR Message Interrupt */
+#define IRQ_MXVR_PKT	BFIN_IRQ(53)	/* MXVR Packet Interrupt */
+#define IRQ_EPP1_ERR	BFIN_IRQ(54)	/* EPPI1 Error Interrupt */
+#define IRQ_EPP2_ERR	BFIN_IRQ(55)	/* EPPI2 Error Interrupt */
+#define IRQ_UART3_ERR	BFIN_IRQ(56)	/* UART3 Status (Error) Interrupt */
+#define IRQ_HOST_ERR	BFIN_IRQ(57)	/* HOST Status (Error) Interrupt */
+#define IRQ_PIXC_ERR	BFIN_IRQ(59)	/* PIXC Status (Error) Interrupt */
+#define IRQ_NFC_ERR	BFIN_IRQ(60)	/* NFC Error Interrupt */
+#define IRQ_ATAPI_ERR	BFIN_IRQ(61)	/* ATAPI Error Interrupt */
+#define IRQ_CAN1_ERR	BFIN_IRQ(62)	/* CAN1 Status (Error) Interrupt */
+#define IRQ_HS_DMA_ERR	BFIN_IRQ(63)	/* Handshake DMA Status Interrupt */
+#define IRQ_PIXC_IN0	BFIN_IRQ(64)	/* PIXC IN0 (DMA15) Interrupt */
+#define IRQ_PIXC_IN1	BFIN_IRQ(65)	/* PIXC IN1 (DMA16) Interrupt */
+#define IRQ_PIXC_OUT	BFIN_IRQ(66)	/* PIXC OUT (DMA17) Interrupt */
+#define IRQ_SDH		BFIN_IRQ(67)	/* SDH/NFC (DMA22) Interrupt */
+#define IRQ_CNT		BFIN_IRQ(68)	/* CNT Interrupt */
+#define IRQ_KEY		BFIN_IRQ(69)	/* KEY Interrupt */
+#define IRQ_CAN1_RX	BFIN_IRQ(70)	/* CAN1 RX Interrupt */
+#define IRQ_CAN1_TX	BFIN_IRQ(71)	/* CAN1 TX Interrupt */
+#define IRQ_SDH_MASK0	BFIN_IRQ(72)	/* SDH Mask 0 Interrupt */
+#define IRQ_SDH_MASK1	BFIN_IRQ(73)	/* SDH Mask 1 Interrupt */
+#define IRQ_USB_INT0	BFIN_IRQ(75)	/* USB INT0 Interrupt */
+#define IRQ_USB_INT1	BFIN_IRQ(76)	/* USB INT1 Interrupt */
+#define IRQ_USB_INT2	BFIN_IRQ(77)	/* USB INT2 Interrupt */
+#define IRQ_USB_DMA	BFIN_IRQ(78)	/* USB DMA Interrupt */
+#define IRQ_OPTSEC	BFIN_IRQ(79)	/* OTPSEC Interrupt */
+#define IRQ_TIMER0	BFIN_IRQ(86)	/* Timer 0 Interrupt */
+#define IRQ_TIMER1	BFIN_IRQ(87)	/* Timer 1 Interrupt */
+#define IRQ_TIMER2	BFIN_IRQ(88)	/* Timer 2 Interrupt */
+#define IRQ_TIMER3	BFIN_IRQ(89)	/* Timer 3 Interrupt */
+#define IRQ_TIMER4	BFIN_IRQ(90)	/* Timer 4 Interrupt */
+#define IRQ_TIMER5	BFIN_IRQ(91)	/* Timer 5 Interrupt */
+#define IRQ_TIMER6	BFIN_IRQ(92)	/* Timer 6 Interrupt */
+#define IRQ_TIMER7	BFIN_IRQ(93)	/* Timer 7 Interrupt */
+#define IRQ_PINT2	BFIN_IRQ(94)	/* PINT2 Interrupt */
+#define IRQ_PINT3	BFIN_IRQ(95)	/* PINT3 Interrupt */
+
+#define SYS_IRQS        IRQ_PINT3
+
+#define BFIN_PA_IRQ(x)	((x) + SYS_IRQS + 1)
+#define IRQ_PA0		BFIN_PA_IRQ(0)
+#define IRQ_PA1		BFIN_PA_IRQ(1)
+#define IRQ_PA2		BFIN_PA_IRQ(2)
+#define IRQ_PA3		BFIN_PA_IRQ(3)
+#define IRQ_PA4		BFIN_PA_IRQ(4)
+#define IRQ_PA5		BFIN_PA_IRQ(5)
+#define IRQ_PA6		BFIN_PA_IRQ(6)
+#define IRQ_PA7		BFIN_PA_IRQ(7)
+#define IRQ_PA8		BFIN_PA_IRQ(8)
+#define IRQ_PA9		BFIN_PA_IRQ(9)
+#define IRQ_PA10	BFIN_PA_IRQ(10)
+#define IRQ_PA11	BFIN_PA_IRQ(11)
+#define IRQ_PA12	BFIN_PA_IRQ(12)
+#define IRQ_PA13	BFIN_PA_IRQ(13)
+#define IRQ_PA14	BFIN_PA_IRQ(14)
+#define IRQ_PA15	BFIN_PA_IRQ(15)
+
+#define BFIN_PB_IRQ(x)	((x) + IRQ_PA15 + 1)
+#define IRQ_PB0		BFIN_PB_IRQ(0)
+#define IRQ_PB1		BFIN_PB_IRQ(1)
+#define IRQ_PB2		BFIN_PB_IRQ(2)
+#define IRQ_PB3		BFIN_PB_IRQ(3)
+#define IRQ_PB4		BFIN_PB_IRQ(4)
+#define IRQ_PB5		BFIN_PB_IRQ(5)
+#define IRQ_PB6		BFIN_PB_IRQ(6)
+#define IRQ_PB7		BFIN_PB_IRQ(7)
+#define IRQ_PB8		BFIN_PB_IRQ(8)
+#define IRQ_PB9		BFIN_PB_IRQ(9)
+#define IRQ_PB10	BFIN_PB_IRQ(10)
+#define IRQ_PB11	BFIN_PB_IRQ(11)
+#define IRQ_PB12	BFIN_PB_IRQ(12)
+#define IRQ_PB13	BFIN_PB_IRQ(13)
+#define IRQ_PB14	BFIN_PB_IRQ(14)
+#define IRQ_PB15	BFIN_PB_IRQ(15)		/* N/A */
+
+#define BFIN_PC_IRQ(x)	((x) + IRQ_PB15 + 1)
+#define IRQ_PC0		BFIN_PC_IRQ(0)
+#define IRQ_PC1		BFIN_PC_IRQ(1)
+#define IRQ_PC2		BFIN_PC_IRQ(2)
+#define IRQ_PC3		BFIN_PC_IRQ(3)
+#define IRQ_PC4		BFIN_PC_IRQ(4)
+#define IRQ_PC5		BFIN_PC_IRQ(5)
+#define IRQ_PC6		BFIN_PC_IRQ(6)
+#define IRQ_PC7		BFIN_PC_IRQ(7)
+#define IRQ_PC8		BFIN_PC_IRQ(8)
+#define IRQ_PC9		BFIN_PC_IRQ(9)
+#define IRQ_PC10	BFIN_PC_IRQ(10)
+#define IRQ_PC11	BFIN_PC_IRQ(11)
+#define IRQ_PC12	BFIN_PC_IRQ(12)
+#define IRQ_PC13	BFIN_PC_IRQ(13)
+#define IRQ_PC14	BFIN_PC_IRQ(14)		/* N/A */
+#define IRQ_PC15	BFIN_PC_IRQ(15)		/* N/A */
+
+#define BFIN_PD_IRQ(x)	((x) + IRQ_PC15 + 1)
+#define IRQ_PD0		BFIN_PD_IRQ(0)
+#define IRQ_PD1		BFIN_PD_IRQ(1)
+#define IRQ_PD2		BFIN_PD_IRQ(2)
+#define IRQ_PD3		BFIN_PD_IRQ(3)
+#define IRQ_PD4		BFIN_PD_IRQ(4)
+#define IRQ_PD5		BFIN_PD_IRQ(5)
+#define IRQ_PD6		BFIN_PD_IRQ(6)
+#define IRQ_PD7		BFIN_PD_IRQ(7)
+#define IRQ_PD8		BFIN_PD_IRQ(8)
+#define IRQ_PD9		BFIN_PD_IRQ(9)
+#define IRQ_PD10	BFIN_PD_IRQ(10)
+#define IRQ_PD11	BFIN_PD_IRQ(11)
+#define IRQ_PD12	BFIN_PD_IRQ(12)
+#define IRQ_PD13	BFIN_PD_IRQ(13)
+#define IRQ_PD14	BFIN_PD_IRQ(14)
+#define IRQ_PD15	BFIN_PD_IRQ(15)
+
+#define BFIN_PE_IRQ(x)	((x) + IRQ_PD15 + 1)
+#define IRQ_PE0		BFIN_PE_IRQ(0)
+#define IRQ_PE1		BFIN_PE_IRQ(1)
+#define IRQ_PE2		BFIN_PE_IRQ(2)
+#define IRQ_PE3		BFIN_PE_IRQ(3)
+#define IRQ_PE4		BFIN_PE_IRQ(4)
+#define IRQ_PE5		BFIN_PE_IRQ(5)
+#define IRQ_PE6		BFIN_PE_IRQ(6)
+#define IRQ_PE7		BFIN_PE_IRQ(7)
+#define IRQ_PE8		BFIN_PE_IRQ(8)
+#define IRQ_PE9		BFIN_PE_IRQ(9)
+#define IRQ_PE10	BFIN_PE_IRQ(10)
+#define IRQ_PE11	BFIN_PE_IRQ(11)
+#define IRQ_PE12	BFIN_PE_IRQ(12)
+#define IRQ_PE13	BFIN_PE_IRQ(13)
+#define IRQ_PE14	BFIN_PE_IRQ(14)
+#define IRQ_PE15	BFIN_PE_IRQ(15)
+
+#define BFIN_PF_IRQ(x)	((x) + IRQ_PE15 + 1)
+#define IRQ_PF0		BFIN_PF_IRQ(0)
+#define IRQ_PF1		BFIN_PF_IRQ(1)
+#define IRQ_PF2		BFIN_PF_IRQ(2)
+#define IRQ_PF3		BFIN_PF_IRQ(3)
+#define IRQ_PF4		BFIN_PF_IRQ(4)
+#define IRQ_PF5		BFIN_PF_IRQ(5)
+#define IRQ_PF6		BFIN_PF_IRQ(6)
+#define IRQ_PF7		BFIN_PF_IRQ(7)
+#define IRQ_PF8		BFIN_PF_IRQ(8)
+#define IRQ_PF9		BFIN_PF_IRQ(9)
+#define IRQ_PF10	BFIN_PF_IRQ(10)
+#define IRQ_PF11	BFIN_PF_IRQ(11)
+#define IRQ_PF12	BFIN_PF_IRQ(12)
+#define IRQ_PF13	BFIN_PF_IRQ(13)
+#define IRQ_PF14	BFIN_PF_IRQ(14)
+#define IRQ_PF15	BFIN_PF_IRQ(15)
+
+#define BFIN_PG_IRQ(x)	((x) + IRQ_PF15 + 1)
+#define IRQ_PG0		BFIN_PG_IRQ(0)
+#define IRQ_PG1		BFIN_PG_IRQ(1)
+#define IRQ_PG2		BFIN_PG_IRQ(2)
+#define IRQ_PG3		BFIN_PG_IRQ(3)
+#define IRQ_PG4		BFIN_PG_IRQ(4)
+#define IRQ_PG5		BFIN_PG_IRQ(5)
+#define IRQ_PG6		BFIN_PG_IRQ(6)
+#define IRQ_PG7		BFIN_PG_IRQ(7)
+#define IRQ_PG8		BFIN_PG_IRQ(8)
+#define IRQ_PG9		BFIN_PG_IRQ(9)
+#define IRQ_PG10	BFIN_PG_IRQ(10)
+#define IRQ_PG11	BFIN_PG_IRQ(11)
+#define IRQ_PG12	BFIN_PG_IRQ(12)
+#define IRQ_PG13	BFIN_PG_IRQ(13)
+#define IRQ_PG14	BFIN_PG_IRQ(14)
+#define IRQ_PG15	BFIN_PG_IRQ(15)
+
+#define BFIN_PH_IRQ(x)	((x) + IRQ_PG15 + 1)
+#define IRQ_PH0		BFIN_PH_IRQ(0)
+#define IRQ_PH1		BFIN_PH_IRQ(1)
+#define IRQ_PH2		BFIN_PH_IRQ(2)
+#define IRQ_PH3		BFIN_PH_IRQ(3)
+#define IRQ_PH4		BFIN_PH_IRQ(4)
+#define IRQ_PH5		BFIN_PH_IRQ(5)
+#define IRQ_PH6		BFIN_PH_IRQ(6)
+#define IRQ_PH7		BFIN_PH_IRQ(7)
+#define IRQ_PH8		BFIN_PH_IRQ(8)
+#define IRQ_PH9		BFIN_PH_IRQ(9)
+#define IRQ_PH10	BFIN_PH_IRQ(10)
+#define IRQ_PH11	BFIN_PH_IRQ(11)
+#define IRQ_PH12	BFIN_PH_IRQ(12)
+#define IRQ_PH13	BFIN_PH_IRQ(13)
+#define IRQ_PH14	BFIN_PH_IRQ(14)		/* N/A */
+#define IRQ_PH15	BFIN_PH_IRQ(15)		/* N/A */
+
+#define BFIN_PI_IRQ(x)	((x) + IRQ_PH15 + 1)
+#define IRQ_PI0		BFIN_PI_IRQ(0)
+#define IRQ_PI1		BFIN_PI_IRQ(1)
+#define IRQ_PI2		BFIN_PI_IRQ(2)
+#define IRQ_PI3		BFIN_PI_IRQ(3)
+#define IRQ_PI4		BFIN_PI_IRQ(4)
+#define IRQ_PI5		BFIN_PI_IRQ(5)
+#define IRQ_PI6		BFIN_PI_IRQ(6)
+#define IRQ_PI7		BFIN_PI_IRQ(7)
+#define IRQ_PI8		BFIN_PI_IRQ(8)
+#define IRQ_PI9		BFIN_PI_IRQ(9)
+#define IRQ_PI10	BFIN_PI_IRQ(10)
+#define IRQ_PI11	BFIN_PI_IRQ(11)
+#define IRQ_PI12	BFIN_PI_IRQ(12)
+#define IRQ_PI13	BFIN_PI_IRQ(13)
+#define IRQ_PI14	BFIN_PI_IRQ(14)
+#define IRQ_PI15	BFIN_PI_IRQ(15)
+
+#define BFIN_PJ_IRQ(x)	((x) + IRQ_PI15 + 1)
+#define IRQ_PJ0		BFIN_PJ_IRQ(0)
+#define IRQ_PJ1		BFIN_PJ_IRQ(1)
+#define IRQ_PJ2		BFIN_PJ_IRQ(2)
+#define IRQ_PJ3		BFIN_PJ_IRQ(3)
+#define IRQ_PJ4		BFIN_PJ_IRQ(4)
+#define IRQ_PJ5		BFIN_PJ_IRQ(5)
+#define IRQ_PJ6		BFIN_PJ_IRQ(6)
+#define IRQ_PJ7		BFIN_PJ_IRQ(7)
+#define IRQ_PJ8		BFIN_PJ_IRQ(8)
+#define IRQ_PJ9		BFIN_PJ_IRQ(9)
+#define IRQ_PJ10	BFIN_PJ_IRQ(10)
+#define IRQ_PJ11	BFIN_PJ_IRQ(11)
+#define IRQ_PJ12	BFIN_PJ_IRQ(12)
+#define IRQ_PJ13	BFIN_PJ_IRQ(13)
+#define IRQ_PJ14	BFIN_PJ_IRQ(14)		/* N/A */
+#define IRQ_PJ15	BFIN_PJ_IRQ(15)		/* N/A */
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#define NR_IRQS     (IRQ_PJ15+1)
+#else
+#define NR_IRQS     (SYS_IRQS+1)
+#endif
+
+#define IVG7            7
+#define IVG8            8
+#define IVG9            9
+#define IVG10           10
+#define IVG11           11
+#define IVG12           12
+#define IVG13           13
+#define IVG14           14
+#define IVG15           15
+
+/* IAR0 BIT FIELDS */
+#define IRQ_PLL_WAKEUP_POS	0
+#define IRQ_DMAC0_ERR_POS	4
+#define IRQ_EPPI0_ERR_POS	8
+#define IRQ_SPORT0_ERR_POS	12
+#define IRQ_SPORT1_ERR_POS	16
+#define IRQ_SPI0_ERR_POS	20
+#define IRQ_UART0_ERR_POS	24
+#define IRQ_RTC_POS		28
+
+/* IAR1 BIT FIELDS */
+#define IRQ_EPPI0_POS		0
+#define IRQ_SPORT0_RX_POS	4
+#define IRQ_SPORT0_TX_POS	8
+#define IRQ_SPORT1_RX_POS	12
+#define IRQ_SPORT1_TX_POS	16
+#define IRQ_SPI0_POS		20
+#define IRQ_UART0_RX_POS	24
+#define IRQ_UART0_TX_POS	28
+
+/* IAR2 BIT FIELDS */
+#define IRQ_TIMER8_POS		0
+#define IRQ_TIMER9_POS		4
+#define IRQ_TIMER10_POS		8
+#define IRQ_PINT0_POS		12
+#define IRQ_PINT1_POS		16
+#define IRQ_MDMAS0_POS		20
+#define IRQ_MDMAS1_POS		24
+#define IRQ_WATCHDOG_POS	28
+
+/* IAR3 BIT FIELDS */
+#define IRQ_DMAC1_ERR_POS	0
+#define IRQ_SPORT2_ERR_POS	4
+#define IRQ_SPORT3_ERR_POS	8
+#define IRQ_MXVR_DATA_POS	12
+#define IRQ_SPI1_ERR_POS	16
+#define IRQ_SPI2_ERR_POS	20
+#define IRQ_UART1_ERR_POS	24
+#define IRQ_UART2_ERR_POS	28
+
+/* IAR4 BIT FILEDS */
+#define IRQ_CAN0_ERR_POS	0
+#define IRQ_SPORT2_RX_POS	4
+#define IRQ_SPORT2_TX_POS	8
+#define IRQ_SPORT3_RX_POS	12
+#define IRQ_SPORT3_TX_POS	16
+#define IRQ_EPPI1_POS		20
+#define IRQ_EPPI2_POS		24
+#define IRQ_SPI1_POS		28
+
+/* IAR5 BIT FIELDS */
+#define IRQ_SPI2_POS		0
+#define IRQ_UART1_RX_POS	4
+#define IRQ_UART1_TX_POS	8
+#define IRQ_ATAPI_RX_POS	12
+#define IRQ_ATAPI_TX_POS	16
+#define IRQ_TWI0_POS		20
+#define IRQ_TWI1_POS		24
+#define IRQ_CAN0_RX_POS		28
+
+/* IAR6 BIT FIELDS */
+#define IRQ_CAN0_TX_POS		0
+#define IRQ_MDMAS2_POS		4
+#define IRQ_MDMAS3_POS		8
+#define IRQ_MXVR_ERR_POS	12
+#define IRQ_MXVR_MSG_POS	16
+#define IRQ_MXVR_PKT_POS	20
+#define IRQ_EPPI1_ERR_POS	24
+#define IRQ_EPPI2_ERR_POS	28
+
+/* IAR7 BIT FIELDS */
+#define IRQ_UART3_ERR_POS	0
+#define IRQ_HOST_ERR_POS	4
+#define IRQ_PIXC_ERR_POS	12
+#define IRQ_NFC_ERR_POS		16
+#define IRQ_ATAPI_ERR_POS	20
+#define IRQ_CAN1_ERR_POS	24
+#define IRQ_HS_DMA_ERR_POS	28
+
+/* IAR8 BIT FIELDS */
+#define IRQ_PIXC_IN0_POS	0
+#define IRQ_PIXC_IN1_POS	4
+#define IRQ_PIXC_OUT_POS	8
+#define IRQ_SDH_POS		12
+#define IRQ_CNT_POS		16
+#define IRQ_KEY_POS		20
+#define IRQ_CAN1_RX_POS		24
+#define IRQ_CAN1_TX_POS		28
+
+/* IAR9 BIT FIELDS */
+#define IRQ_SDH_MASK0_POS	0
+#define IRQ_SDH_MASK1_POS	4
+#define IRQ_USB_INT0_POS	12
+#define IRQ_USB_INT1_POS	16
+#define IRQ_USB_INT2_POS	20
+#define IRQ_USB_DMA_POS		24
+#define IRQ_OTPSEC_POS		28
+
+/* IAR10 BIT FIELDS */
+#define IRQ_TIMER0_POS		24
+#define IRQ_TIMER1_POS		28
+
+/* IAR11 BIT FIELDS */
+#define IRQ_TIMER2_POS		0
+#define IRQ_TIMER3_POS		4
+#define IRQ_TIMER4_POS		8
+#define IRQ_TIMER5_POS		12
+#define IRQ_TIMER6_POS		16
+#define IRQ_TIMER7_POS		20
+#define IRQ_PINT2_POS		24
+#define IRQ_PINT3_POS		28
+
+#endif /* _BF548_IRQ_H_ */
diff --git a/include/asm-blackfin/mach-bf548/mem_init.h b/include/asm-blackfin/mach-bf548/mem_init.h
new file mode 100644
index 0000000..0cb279e
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/mem_init.h
@@ -0,0 +1,189 @@
+/*
+ * File:         include/asm-blackfin/mach-bf548/mem_init.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#if (CONFIG_MEM_MT46V32M16)
+
+#if defined CONFIG_CLKIN_HALF
+#define CLKIN_HALF       1
+#else
+#define CLKIN_HALF       0
+#endif
+
+#if defined CONFIG_PLL_BYPASS
+#define PLL_BYPASS      1
+#else
+#define PLL_BYPASS       0
+#endif
+
+/***************************************Currently Not Being Used *********************************/
+#define flash_EBIU_AMBCTL_WAT  ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_RAT  ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_HT   ((CONFIG_FLASH_SPEED_BHT  * 4) / (4000000000 / CONFIG_SCLK_HZ))
+#define flash_EBIU_AMBCTL_ST   ((CONFIG_FLASH_SPEED_BST  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_TT   ((CONFIG_FLASH_SPEED_BTT  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+
+#if (flash_EBIU_AMBCTL_TT > 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_4
+#endif
+#if (flash_EBIU_AMBCTL_TT == 3)
+#define flash_EBIU_AMBCTL0_TT   B0TT_3
+#endif
+#if (flash_EBIU_AMBCTL_TT == 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_2
+#endif
+#if (flash_EBIU_AMBCTL_TT < 2)
+#define flash_EBIU_AMBCTL0_TT   B0TT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_ST > 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_4
+#endif
+#if (flash_EBIU_AMBCTL_ST == 3)
+#define flash_EBIU_AMBCTL0_ST   B0ST_3
+#endif
+#if (flash_EBIU_AMBCTL_ST == 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_2
+#endif
+#if (flash_EBIU_AMBCTL_ST < 2)
+#define flash_EBIU_AMBCTL0_ST   B0ST_1
+#endif
+
+#if (flash_EBIU_AMBCTL_HT > 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_3
+#endif
+#if (flash_EBIU_AMBCTL_HT == 2)
+#define flash_EBIU_AMBCTL0_HT   B0HT_2
+#endif
+#if (flash_EBIU_AMBCTL_HT == 1)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_0
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
+#define flash_EBIU_AMBCTL0_HT   B0HT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_WAT > 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_15
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 14)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_14
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 13)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_13
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 12)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_12
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 11)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_11
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 10)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_10
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 9)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_9
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 8)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_8
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 7)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_7
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 6)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_6
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 5)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_5
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 4)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_4
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 3)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_3
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 2)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_2
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 1)
+#define flash_EBIU_AMBCTL0_WAT  B0WAT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_RAT > 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_15
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 14)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_14
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 13)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_13
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 12)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_12
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 11)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_11
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 10)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_10
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 9)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_9
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 8)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_8
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 7)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_7
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 6)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_6
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 5)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_5
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 4)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_4
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 3)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_3
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 2)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_2
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 1)
+#define flash_EBIU_AMBCTL0_RAT  B0RAT_1
+#endif
+
+#define flash_EBIU_AMBCTL0  \
+	(flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
+	 flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/include/asm-blackfin/mach-bf548/mem_map.h b/include/asm-blackfin/mach-bf548/mem_map.h
new file mode 100644
index 0000000..72d80e8
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/mem_map.h
@@ -0,0 +1,97 @@
+/*
+ * file:         include/asm-blackfin/mach-bf548/mem_map.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *	Memory MAP Common header file for blackfin BF537/6/4 of processors.
+ * rev:
+ *
+ * modified:
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose.  see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MEM_MAP_548_H_
+#define _MEM_MAP_548_H_
+
+#define COREMMR_BASE           0xFFE00000	 /* Core MMRs */
+#define SYSMMR_BASE            0xFFC00000	 /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE	0x2C000000	 /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE	0x04000000	/* 64M */
+#define ASYNC_BANK2_BASE	0x28000000	 /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE	0x04000000	/* 64M */
+#define ASYNC_BANK1_BASE	0x24000000	 /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE	0x04000000	/* 64M */
+#define ASYNC_BANK0_BASE	0x20000000	 /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE	0x04000000	/* 64M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START		0xEF000000
+
+/* Level 1 Memory */
+
+/* Memory Map for ADSP-BF548 processors */
+#ifdef CONFIG_BLKFIN_ICACHE
+#define BLKFIN_ICACHESIZE	(16*1024)
+#else
+#define BLKFIN_ICACHESIZE	(0*1024)
+#endif
+
+#define L1_CODE_START       0xFFA00000
+#define L1_DATA_A_START     0xFF800000
+#define L1_DATA_B_START     0xFF900000
+
+#define L1_CODE_LENGTH      0xC000
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE	(16*1024)
+#define BLKFIN_DSUPBANKS	1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH      (0x8000 - 0x4000)
+#define BLKFIN_DCACHESIZE	(32*1024)
+#define BLKFIN_DSUPBANKS	2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH      0x8000
+#define L1_DATA_B_LENGTH      0x8000
+#define BLKFIN_DCACHESIZE	(0*1024)
+#define BLKFIN_DSUPBANKS	0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+
+/* Scratch Pad Memory */
+
+#if defined(CONFIG_BF54x)
+#define L1_SCRATCH_START	0xFFB00000
+#define L1_SCRATCH_LENGTH	0x1000
+#endif
+
+#endif/* _MEM_MAP_548_H_ */
diff --git a/include/asm-blackfin/mach-bf548/portmux.h b/include/asm-blackfin/mach-bf548/portmux.h
new file mode 100644
index 0000000..b382deb
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/portmux.h
@@ -0,0 +1,270 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_SPORT2_TFS	(P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(0))
+#define P_SPORT2_DTSEC	(P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(0))
+#define P_SPORT2_DTPRI	(P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(0))
+#define P_SPORT2_TSCLK	(P_DEFINED | P_IDENT(GPIO_PA3) | P_FUNCT(0))
+#define P_SPORT2_RFS	(P_DEFINED | P_IDENT(GPIO_PA4) | P_FUNCT(0))
+#define P_SPORT2_DRSEC	(P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(0))
+#define P_SPORT2_DRPRI	(P_DEFINED | P_IDENT(GPIO_PA6) | P_FUNCT(0))
+#define P_SPORT2_RSCLK	(P_DEFINED | P_IDENT(GPIO_PA7) | P_FUNCT(0))
+#define P_SPORT3_TFS	(P_DEFINED | P_IDENT(GPIO_PA8) | P_FUNCT(0))
+#define P_SPORT3_DTSEC	(P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(0))
+#define P_SPORT3_DTPRI	(P_DEFINED | P_IDENT(GPIO_PA10) | P_FUNCT(0))
+#define P_SPORT3_TSCLK	(P_DEFINED | P_IDENT(GPIO_PA11) | P_FUNCT(0))
+#define P_SPORT3_RFS	(P_DEFINED | P_IDENT(GPIO_PA12) | P_FUNCT(0))
+#define P_SPORT3_DRSEC	(P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(0))
+#define P_SPORT3_DRPRI	(P_DEFINED | P_IDENT(GPIO_PA14) | P_FUNCT(0))
+#define P_SPORT3_RSCLK	(P_DEFINED | P_IDENT(GPIO_PA15) | P_FUNCT(0))
+#define P_TMR4	(P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(1))
+#define P_TMR5	(P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(1))
+#define P_TMR6	(P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(1))
+#define P_TMR7	(P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(1))
+
+#define P_TWI1_SCL	(P_DEFINED | P_IDENT(GPIO_PB0) | P_FUNCT(0))
+#define P_TWI1_SDA	(P_DEFINED | P_IDENT(GPIO_PB1) | P_FUNCT(0))
+#define P_UART3_RTS	(P_DEFINED | P_IDENT(GPIO_PB2) | P_FUNCT(0))
+#define P_UART3_CTS	(P_DEFINED | P_IDENT(GPIO_PB3) | P_FUNCT(0))
+#define P_UART2_TX	(P_DEFINED | P_IDENT(GPIO_PB4) | P_FUNCT(0))
+#define P_UART2_RX	(P_DEFINED | P_IDENT(GPIO_PB5) | P_FUNCT(0))
+#define P_UART3_TX	(P_DEFINED | P_IDENT(GPIO_PB6) | P_FUNCT(0))
+#define P_UART3_RX	(P_DEFINED | P_IDENT(GPIO_PB7) | P_FUNCT(0))
+#define P_SPI2_SS	(P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(0))
+#define P_SPI2_SSEL1	(P_DEFINED | P_IDENT(GPIO_PB9) | P_FUNCT(0))
+#define P_SPI2_SSEL2	(P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(0))
+#define P_SPI2_SSEL3	(P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(0))
+#define P_SPI2_SCK	(P_DEFINED | P_IDENT(GPIO_PB12) | P_FUNCT(0))
+#define P_SPI2_MOSI	(P_DEFINED | P_IDENT(GPIO_PB13) | P_FUNCT(0))
+#define P_SPI2_MISO	(P_DEFINED | P_IDENT(GPIO_PB14) | P_FUNCT(0))
+#define P_TMR0	(P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(1))
+#define P_TMR1	(P_DEFINED | P_IDENT(GPIO_PB9) | P_FUNCT(1))
+#define P_TMR2	(P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(1))
+#define P_TMR3	(P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(1))
+
+#define P_SPORT0_TFS	(P_DEFINED | P_IDENT(GPIO_PC0) | P_FUNCT(0))
+#define P_SPORT0_DTSEC	(P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(0))
+#define P_SPORT0_DTPRI	(P_DEFINED | P_IDENT(GPIO_PC2) | P_FUNCT(0))
+#define P_SPORT0_TSCLK	(P_DEFINED | P_IDENT(GPIO_PC3) | P_FUNCT(0))
+#define P_SPORT0_RFS	(P_DEFINED | P_IDENT(GPIO_PC4) | P_FUNCT(0))
+#define P_SPORT0_DRSEC	(P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(0))
+#define P_SPORT0_DRPRI	(P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(0))
+#define P_SPORT0_RSCLK	(P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(0))
+#define P_SD_D0	(P_DEFINED | P_IDENT(GPIO_PC8) | P_FUNCT(0))
+#define P_SD_D1	(P_DEFINED | P_IDENT(GPIO_PC9) | P_FUNCT(0))
+#define P_SD_D2	(P_DEFINED | P_IDENT(GPIO_PC10) | P_FUNCT(0))
+#define P_SD_D3	(P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(0))
+#define P_SD_CLK	(P_DEFINED | P_IDENT(GPIO_PC12) | P_FUNCT(0))
+#define P_SD_CMD	(P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(0))
+#define P_MMCLK	(P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(1))
+#define P_MBCLK	(P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(1))
+
+#define P_PPI1_D0	(P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(0))
+#define P_PPI1_D1	(P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(0))
+#define P_PPI1_D2	(P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(0))
+#define P_PPI1_D3	(P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(0))
+#define P_PPI1_D4	(P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(0))
+#define P_PPI1_D5	(P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(0))
+#define P_PPI1_D6	(P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(0))
+#define P_PPI1_D7	(P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(0))
+#define P_PPI1_D8	(P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(0))
+#define P_PPI1_D9	(P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(0))
+#define P_PPI1_D10	(P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(0))
+#define P_PPI1_D11	(P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(0))
+#define P_PPI1_D12	(P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(0))
+#define P_PPI1_D13	(P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(0))
+#define P_PPI1_D14	(P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(0))
+#define P_PPI1_D15	(P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(0))
+
+#define P_HOST_D8	(P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(1))
+#define P_HOST_D9	(P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(1))
+#define P_HOST_D10	(P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(1))
+#define P_HOST_D11	(P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(1))
+#define P_HOST_D12	(P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(1))
+#define P_HOST_D13	(P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(1))
+#define P_HOST_D14	(P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(1))
+#define P_HOST_D15	(P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(1))
+#define P_HOST_D0	(P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(1))
+#define P_HOST_D1	(P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(1))
+#define P_HOST_D2	(P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(1))
+#define P_HOST_D3	(P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(1))
+#define P_HOST_D4	(P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(1))
+#define P_HOST_D5	(P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(1))
+#define P_HOST_D6	(P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(1))
+#define P_HOST_D7	(P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(1))
+#define P_SPORT1_TFS	(P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(2))
+#define P_SPORT1_DTSEC	(P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(2))
+#define P_SPORT1_DTPRI	(P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(2))
+#define P_SPORT1_TSCLK	(P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(2))
+#define P_SPORT1_RFS	(P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(2))
+#define P_SPORT1_DRSEC	(P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(2))
+#define P_SPORT1_DRPRI	(P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(2))
+#define P_SPORT1_RSCLK	(P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(2))
+#define P_PPI2_D0	(P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(2))
+#define P_PPI2_D1	(P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(2))
+#define P_PPI2_D2	(P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(2))
+#define P_PPI2_D3	(P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(2))
+#define P_PPI2_D4	(P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(2))
+#define P_PPI2_D5	(P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(2))
+#define P_PPI2_D6	(P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(2))
+#define P_PPI2_D7	(P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(2))
+#define P_PPI0_D18	(P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(3))
+#define P_PPI0_D19	(P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(3))
+#define P_PPI0_D20	(P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(3))
+#define P_PPI0_D21	(P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(3))
+#define P_PPI0_D22	(P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(3))
+#define P_PPI0_D23	(P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(3))
+#define P_KEY_ROW0	(P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(3))
+#define P_KEY_ROW1	(P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(3))
+#define P_KEY_ROW2	(P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(3))
+#define P_KEY_ROW3	(P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(3))
+#define P_KEY_COL0	(P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(3))
+#define P_KEY_COL1	(P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(3))
+#define P_KEY_COL2	(P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(3))
+#define P_KEY_COL3	(P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(3))
+
+#define P_SPI0_SCK	(P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0))
+#define P_SPI0_MISO	(P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0))
+#define P_SPI0_MOSI	(P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0))
+#define P_SPI0_SS	(P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(0))
+#define P_SPI0_SSEL1	(P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(0))
+#define P_SPI0_SSEL2	(P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(0))
+#define P_SPI0_SSEL3	(P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(0))
+#define P_UART0_TX	(P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(0))
+#define P_UART0_RX	(P_DEFINED | P_IDENT(GPIO_PE8) | P_FUNCT(0))
+#define P_UART1_RTS	(P_DEFINED | P_IDENT(GPIO_PE9) | P_FUNCT(0))
+#define P_UART1_CTS	(P_DEFINED | P_IDENT(GPIO_PE10) | P_FUNCT(0))
+#define P_PPI1_CLK	(P_DEFINED | P_IDENT(GPIO_PE11) | P_FUNCT(0))
+#define P_PPI1_FS1	(P_DEFINED | P_IDENT(GPIO_PE12) | P_FUNCT(0))
+#define P_PPI1_FS2	(P_DEFINED | P_IDENT(GPIO_PE13) | P_FUNCT(0))
+#define P_TWI0_SCL	(P_DEFINED | P_IDENT(GPIO_PE14) | P_FUNCT(0))
+#define P_TWI0_SDA	(P_DEFINED | P_IDENT(GPIO_PE15) | P_FUNCT(0))
+#define P_KEY_COL7	(P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(1))
+#define P_KEY_ROW6	(P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(1))
+#define P_KEY_COL6	(P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(1))
+#define P_KEY_ROW5	(P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(1))
+#define P_KEY_COL5	(P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(1))
+#define P_KEY_ROW4	(P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(1))
+#define P_KEY_COL4	(P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(1))
+#define P_KEY_ROW7	(P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(1))
+
+#define P_PPI0_D0	(P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0))
+#define P_PPI0_D1	(P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0))
+#define P_PPI0_D2	(P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0))
+#define P_PPI0_D3	(P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0))
+#define P_PPI0_D4	(P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0))
+#define P_PPI0_D5	(P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0))
+#define P_PPI0_D6	(P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0))
+#define P_PPI0_D7	(P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0))
+#define P_PPI0_D8	(P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_PPI0_D9	(P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_PPI0_D10	(P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0))
+#define P_PPI0_D11	(P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0))
+#define P_PPI0_D12	(P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0))
+#define P_PPI0_D13	(P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
+#define P_PPI0_D14	(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
+#define P_PPI0_D15	(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
+#define P_ATAPI_D0A	(P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_ATAPI_D1A	(P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_ATAPI_D2A	(P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_ATAPI_D3A	(P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_ATAPI_D4A	(P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_ATAPI_D5A	(P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_ATAPI_D6A	(P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_ATAPI_D7A	(P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#define P_ATAPI_D8A	(P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_ATAPI_D9A	(P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_ATAPI_D10A	(P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1))
+#define P_ATAPI_D11A	(P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1))
+#define P_ATAPI_D12A	(P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1))
+#define P_ATAPI_D13A	(P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1))
+#define P_ATAPI_D14A	(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_ATAPI_D15A	(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#define P_PPI0_CLK	(P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
+#define P_PPI0_FS1	(P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_PPI0_FS2	(P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0))
+#define P_PPI0_D16	(P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
+#define P_PPI0_D17	(P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
+#define P_SPI1_SSEL1	(P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_SPI1_SSEL2	(P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+#define P_SPI1_SSEL3	(P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_SPI1_SCK	(P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_SPI1_MISO	(P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_SPI1_MOSI	(P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+#define P_SPI1_SS	(P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0))
+#define P_CAN0_TX	(P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_CAN0_RX	(P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+#define P_CAN1_TX	(P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+#define P_CAN1_RX	(P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#define P_ATAPI_A0A	(P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(1))
+#define P_ATAPI_A1A	(P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
+#define P_ATAPI_A2A	(P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1))
+#define P_HOST_CE	(P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1))
+#define P_HOST_RD	(P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
+#define P_HOST_WR	(P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
+#define P_MTXONB	(P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_PPI2_FS2	(P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(2))
+#define P_PPI2_FS1	(P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2))
+#define P_PPI2_CLK	(P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(2))
+#define P_CNT_CZM	(P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(3))
+
+#define P_UART1_TX	(P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0))
+#define P_UART1_RX	(P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0))
+#define P_ATAPI_RESET	(P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0))
+#define P_HOST_ADDR	(P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0))
+#define P_HOST_ACK	(P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0))
+#define P_MTX	(P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0))
+#define P_MRX	(P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0))
+#define P_MRXONB	(P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0))
+#define P_A4	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(0))
+#define P_A5	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(0))
+#define P_A6	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(0))
+#define P_A7	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(0))
+#define P_A8	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(0))
+#define P_A9	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(0))
+#define P_PPI1_FS3	(P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(1))
+#define P_PPI2_FS3	(P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(1))
+#define P_TMR8	(P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(1))
+#define P_TMR9	(P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(1))
+#define P_TMR10	(P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(1))
+#define P_DMAR0	(P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(1))
+#define P_DMAR1	(P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1))
+#define P_PPI0_FS3	(P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(2))
+#define P_CNT_CDG	(P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(2))
+#define P_CNT_CUD	(P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(2))
+
+#define P_A10	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI0) | P_FUNCT(0))
+#define P_A11	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI1) | P_FUNCT(0))
+#define P_A12	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI2) | P_FUNCT(0))
+#define P_A13	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI3) | P_FUNCT(0))
+#define P_A14	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI4) | P_FUNCT(0))
+#define P_A15	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI5) | P_FUNCT(0))
+#define P_A16	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI6) | P_FUNCT(0))
+#define P_A17	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI7) | P_FUNCT(0))
+#define P_A18	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI8) | P_FUNCT(0))
+#define P_A19	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI9) | P_FUNCT(0))
+#define P_A20	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI10) | P_FUNCT(0))
+#define P_A21	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI11) | P_FUNCT(0))
+#define P_A22	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI12) | P_FUNCT(0))
+#define P_A23	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI13) | P_FUNCT(0))
+#define P_A24	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI14) | P_FUNCT(0))
+#define P_A25	(P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI15) | P_FUNCT(0))
+#define P_NOR_CLK	(P_DEFINED | P_IDENT(GPIO_PI15) | P_FUNCT(1))
+
+#define P_AMC_ARDY_NOR_WAIT	(P_DEFINED | P_IDENT(GPIO_PJ0) | P_FUNCT(0))
+#define P_NAND_CE	(P_DEFINED | P_IDENT(GPIO_PJ1) | P_FUNCT(0))
+#define P_NAND_RB	(P_DEFINED | P_IDENT(GPIO_PJ2) | P_FUNCT(0))
+#define P_ATAPI_DIOR	(P_DEFINED | P_IDENT(GPIO_PJ3) | P_FUNCT(0))
+#define P_ATAPI_DIOW	(P_DEFINED | P_IDENT(GPIO_PJ4) | P_FUNCT(0))
+#define P_ATAPI_CS0	(P_DEFINED | P_IDENT(GPIO_PJ5) | P_FUNCT(0))
+#define P_ATAPI_CS1	(P_DEFINED | P_IDENT(GPIO_PJ6) | P_FUNCT(0))
+#define P_ATAPI_DMACK	(P_DEFINED | P_IDENT(GPIO_PJ7) | P_FUNCT(0))
+#define P_ATAPI_DMARQ	(P_DEFINED | P_IDENT(GPIO_PJ8) | P_FUNCT(0))
+#define P_ATAPI_INTRQ	(P_DEFINED | P_IDENT(GPIO_PJ9) | P_FUNCT(0))
+#define P_ATAPI_IORDY	(P_DEFINED | P_IDENT(GPIO_PJ10) | P_FUNCT(0))
+#define P_AMC_BR	(P_DEFINED | P_IDENT(GPIO_PJ11) | P_FUNCT(0))
+#define P_AMC_BG	(P_DEFINED | P_IDENT(GPIO_PJ12) | P_FUNCT(0))
+#define P_AMC_BGH	(P_DEFINED | P_IDENT(GPIO_PJ13) | P_FUNCT(0))
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
index 23bf76a..e043caf 100644
--- a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
@@ -78,6 +78,7 @@
 };
 
 struct bfin_serial_res bfin_serial_resource[] = {
+	{
 	0xFFC00400,
 	IRQ_UART_RX,
 #ifdef CONFIG_SERIAL_BFIN_DMA
@@ -88,6 +89,7 @@
 	CONFIG_UART0_CTS_PIN,
 	CONFIG_UART0_RTS_PIN,
 #endif
+	}
 };
 
 
diff --git a/include/asm-blackfin/mach-bf561/cdefBF561.h b/include/asm-blackfin/mach-bf561/cdefBF561.h
index 5dc0ed8..1a8ec9e 100644
--- a/include/asm-blackfin/mach-bf561/cdefBF561.h
+++ b/include/asm-blackfin/mach-bf561/cdefBF561.h
@@ -57,18 +57,23 @@
 /* Writing to VR_CTL initiates a PLL relock sequence. */
 static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
-	unsigned long flags, iwr;
+	unsigned long flags, iwr0, iwr1;
+
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SICA_IWR0);
+	iwr1 = bfin_read32(SICA_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+	bfin_write32(SICA_IWR1, 0);
 
 	bfin_write16(VR_CTL, val);
 	__builtin_bfin_ssync();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SICA_IWR0);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+
 	local_irq_save(flags);
 	asm("IDLE;");
 	local_irq_restore(flags);
-	bfin_write32(SICA_IWR0, iwr);
+	bfin_write32(SICA_IWR0, iwr0);
+	bfin_write32(SICA_IWR1, iwr1);
 }
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
diff --git a/include/asm-blackfin/mach-bf561/defBF561.h b/include/asm-blackfin/mach-bf561/defBF561.h
index a6de4c6..89150ec 100644
--- a/include/asm-blackfin/mach-bf561/defBF561.h
+++ b/include/asm-blackfin/mach-bf561/defBF561.h
@@ -904,23 +904,6 @@
 #define IWR_ENABLE(x)	       (1 << (x))	/* Wakeup Enable Peripheral #x */
 #define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x)))	/* Wakeup Disable Peripheral #x */
 
-/* *********  WATCHDOG TIMER MASKS  ********************8 */
-
-/* Watchdog Timer WDOG_CTL Register */
-#define ICTL(x) ((x<<1) & 0x0006)
-#define ENABLE_RESET     0x00000000	/* Set Watchdog Timer to generate reset */
-#define ENABLE_NMI       0x00000002	/* Set Watchdog Timer to generate non-maskable interrupt */
-#define ENABLE_GPI       0x00000004	/* Set Watchdog Timer to generate general-purpose interrupt */
-#define DISABLE_EVT      0x00000006	/* Disable Watchdog Timer interrupts */
-
-#define TMR_EN		0x0000
-#define TMR_DIS		0x0AD0
-#define TRO		0x8000
-
-#define ICTL_P0		0x01
-#define ICTL_P1		0x02
-#define TRO_P		0x0F
-
 /* ***************************** UART CONTROLLER MASKS ********************** */
 
 /* UART_LCR Register */
@@ -1214,18 +1197,18 @@
 #define TIMIL9		0x0002
 #define TIMIL10		0x0004
 #define TIMIL11		0x0008
-#define TOVL_ERR0	0x00000010
-#define TOVL_ERR1	0x00000020
-#define TOVL_ERR2	0x00000040
-#define TOVL_ERR3	0x00000080
-#define TOVL_ERR4	0x00100000
-#define TOVL_ERR5	0x00200000
-#define TOVL_ERR6	0x00400000
-#define TOVL_ERR7	0x00800000
-#define TOVL_ERR8	0x0010
-#define TOVL_ERR9	0x0020
-#define TOVL_ERR10	0x0040
-#define TOVL_ERR11	0x0080
+#define TOVF_ERR0	0x00000010
+#define TOVF_ERR1	0x00000020
+#define TOVF_ERR2	0x00000040
+#define TOVF_ERR3	0x00000080
+#define TOVF_ERR4	0x00100000
+#define TOVF_ERR5	0x00200000
+#define TOVF_ERR6	0x00400000
+#define TOVF_ERR7	0x00800000
+#define TOVF_ERR8	0x0010
+#define TOVF_ERR9	0x0020
+#define TOVF_ERR10	0x0040
+#define TOVF_ERR11	0x0080
 #define TRUN0		0x00001000
 #define TRUN1		0x00002000
 #define TRUN2		0x00004000
@@ -1251,18 +1234,18 @@
 #define TIMIL9_P	0x01
 #define TIMIL10_P	0x02
 #define TIMIL11_P	0x03
-#define TOVL_ERR0_P	0x04
-#define TOVL_ERR1_P	0x05
-#define TOVL_ERR2_P	0x06
-#define TOVL_ERR3_P	0x07
-#define TOVL_ERR4_P	0x14
-#define TOVL_ERR5_P	0x15
-#define TOVL_ERR6_P	0x16
-#define TOVL_ERR7_P	0x17
-#define TOVL_ERR8_P	0x04
-#define TOVL_ERR9_P	0x05
-#define TOVL_ERR10_P	0x06
-#define TOVL_ERR11_P	0x07
+#define TOVF_ERR0_P	0x04
+#define TOVF_ERR1_P	0x05
+#define TOVF_ERR2_P	0x06
+#define TOVF_ERR3_P	0x07
+#define TOVF_ERR4_P	0x14
+#define TOVF_ERR5_P	0x15
+#define TOVF_ERR6_P	0x16
+#define TOVF_ERR7_P	0x17
+#define TOVF_ERR8_P	0x04
+#define TOVF_ERR9_P	0x05
+#define TOVF_ERR10_P	0x06
+#define TOVF_ERR11_P	0x07
 #define TRUN0_P		0x0C
 #define TRUN1_P		0x0D
 #define TRUN2_P		0x0E
@@ -1276,6 +1259,32 @@
 #define TRUN10_P	0x0E
 #define TRUN11_P	0x0F
 
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define TOVL_ERR0 TOVF_ERR0
+#define TOVL_ERR1 TOVF_ERR1
+#define TOVL_ERR2 TOVF_ERR2
+#define TOVL_ERR3 TOVF_ERR3
+#define TOVL_ERR4 TOVF_ERR4
+#define TOVL_ERR5 TOVF_ERR5
+#define TOVL_ERR6 TOVF_ERR6
+#define TOVL_ERR7 TOVF_ERR7
+#define TOVL_ERR8 TOVF_ERR8
+#define TOVL_ERR9 TOVF_ERR9
+#define TOVL_ERR10 TOVF_ERR10
+#define TOVL_ERR11 TOVF_ERR11
+#define TOVL_ERR0_P TOVF_ERR0_P
+#define TOVL_ERR1_P TOVF_ERR1_P
+#define TOVL_ERR2_P TOVF_ERR2_P
+#define TOVL_ERR3_P TOVF_ERR3_P
+#define TOVL_ERR4_P TOVF_ERR4_P
+#define TOVL_ERR5_P TOVF_ERR5_P
+#define TOVL_ERR6_P TOVF_ERR6_P
+#define TOVL_ERR7_P TOVF_ERR7_P
+#define TOVL_ERR8_P TOVF_ERR8_P
+#define TOVL_ERR9_P TOVF_ERR9_P
+#define TOVL_ERR10_P TOVF_ERR10_P
+#define TOVL_ERR11_P TOVF_ERR11_P
+
 /* TIMERx_CONFIG Registers */
 #define PWM_OUT		0x0001
 #define WDTH_CAP	0x0002
@@ -1700,18 +1709,4 @@
 #define SDEASE		    0x00000010	/* SDRAM EAB sticky error status - W1C */
 #define BGSTAT			0x00000020	/* Bus granted */
 
-/*VR_CTL Masks*/
-#define WAKE                    0x100
-#define VLEV_6                  0x60
-#define VLEV_7                  0x70
-#define VLEV_8                  0x80
-#define VLEV_9                  0x90
-#define VLEV_10                 0xA0
-#define VLEV_11                 0xB0
-#define VLEV_12                 0xC0
-#define VLEV_13                 0xD0
-#define VLEV_14                 0xE0
-#define VLEV_15                 0xF0
-#define FREQ_3                  0x03
-
 #endif				/* _DEF_BF561_H */
diff --git a/include/asm-blackfin/mach-bf561/dma.h b/include/asm-blackfin/mach-bf561/dma.h
index 21d9820..766334b 100644
--- a/include/asm-blackfin/mach-bf561/dma.h
+++ b/include/asm-blackfin/mach-bf561/dma.h
@@ -32,4 +32,7 @@
 #define CH_IMEM_STREAM1_SRC	34
 #define CH_IMEM_STREAM1_DEST	35
 
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
 #endif
diff --git a/include/asm-blackfin/mach-bf561/portmux.h b/include/asm-blackfin/mach-bf561/portmux.h
new file mode 100644
index 0000000..10d11d5
--- /dev/null
+++ b/include/asm-blackfin/mach-bf561/portmux.h
@@ -0,0 +1,87 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_PPI0_CLK	(P_DONTCARE)
+#define P_PPI0_FS1	(P_DONTCARE)
+#define P_PPI0_FS2	(P_DONTCARE)
+#define P_PPI0_FS3	(P_DONTCARE)
+#define P_PPI0_D15	(P_DEFINED | P_IDENT(GPIO_PF47))
+#define P_PPI0_D14	(P_DEFINED | P_IDENT(GPIO_PF46))
+#define P_PPI0_D13	(P_DEFINED | P_IDENT(GPIO_PF45))
+#define P_PPI0_D12	(P_DEFINED | P_IDENT(GPIO_PF44))
+#define P_PPI0_D11	(P_DEFINED | P_IDENT(GPIO_PF43))
+#define P_PPI0_D10	(P_DEFINED | P_IDENT(GPIO_PF42))
+#define P_PPI0_D9	(P_DEFINED | P_IDENT(GPIO_PF41))
+#define P_PPI0_D8	(P_DEFINED | P_IDENT(GPIO_PF40))
+#define P_PPI0_D0	(P_DONTCARE)
+#define P_PPI0_D1	(P_DONTCARE)
+#define P_PPI0_D2	(P_DONTCARE)
+#define P_PPI0_D3	(P_DONTCARE)
+#define P_PPI0_D4	(P_DONTCARE)
+#define P_PPI0_D5	(P_DONTCARE)
+#define P_PPI0_D6	(P_DONTCARE)
+#define P_PPI0_D7	(P_DONTCARE)
+#define P_PPI1_CLK	(P_DONTCARE)
+#define P_PPI1_FS1	(P_DONTCARE)
+#define P_PPI1_FS2	(P_DONTCARE)
+#define P_PPI1_FS3	(P_DONTCARE)
+#define P_PPI1_D15	(P_DEFINED | P_IDENT(GPIO_PF39))
+#define P_PPI1_D14	(P_DEFINED | P_IDENT(GPIO_PF38))
+#define P_PPI1_D13	(P_DEFINED | P_IDENT(GPIO_PF37))
+#define P_PPI1_D12	(P_DEFINED | P_IDENT(GPIO_PF36))
+#define P_PPI1_D11	(P_DEFINED | P_IDENT(GPIO_PF35))
+#define P_PPI1_D10	(P_DEFINED | P_IDENT(GPIO_PF34))
+#define P_PPI1_D9	(P_DEFINED | P_IDENT(GPIO_PF33))
+#define P_PPI1_D8	(P_DEFINED | P_IDENT(GPIO_PF32))
+#define P_PPI1_D0	(P_DONTCARE)
+#define P_PPI1_D1	(P_DONTCARE)
+#define P_PPI1_D2	(P_DONTCARE)
+#define P_PPI1_D3	(P_DONTCARE)
+#define P_PPI1_D4	(P_DONTCARE)
+#define P_PPI1_D5	(P_DONTCARE)
+#define P_PPI1_D6	(P_DONTCARE)
+#define P_PPI1_D7	(P_DONTCARE)
+#define P_SPORT1_TSCLK	(P_DEFINED | P_IDENT(GPIO_PF31))
+#define P_SPORT1_RSCLK	(P_DEFINED | P_IDENT(GPIO_PF30))
+#define P_SPORT0_TSCLK	(P_DEFINED | P_IDENT(GPIO_PF29))
+#define P_SPORT0_RSCLK	(P_DEFINED | P_IDENT(GPIO_PF28))
+#define P_UART0_RX	(P_DEFINED | P_IDENT(GPIO_PF27))
+#define P_UART0_TX	(P_DEFINED | P_IDENT(GPIO_PF26))
+#define P_SPORT1_DRSEC	(P_DEFINED | P_IDENT(GPIO_PF25))
+#define P_SPORT1_RFS	(P_DEFINED | P_IDENT(GPIO_PF24))
+#define P_SPORT1_DTPRI	(P_DEFINED | P_IDENT(GPIO_PF23))
+#define P_SPORT1_DTSEC	(P_DEFINED | P_IDENT(GPIO_PF22))
+#define P_SPORT1_TFS	(P_DEFINED | P_IDENT(GPIO_PF21))
+#define P_SPORT1_DRPRI	(P_DONTCARE)
+#define P_SPORT0_DRSEC	(P_DEFINED | P_IDENT(GPIO_PF20))
+#define P_SPORT0_RFS	(P_DEFINED | P_IDENT(GPIO_PF19))
+#define P_SPORT0_DTPRI	(P_DEFINED | P_IDENT(GPIO_PF18))
+#define P_SPORT0_DTSEC	(P_DEFINED | P_IDENT(GPIO_PF17))
+#define P_SPORT0_TFS	(P_DEFINED | P_IDENT(GPIO_PF16))
+#define P_SPORT0_DRPRI	(P_DONTCARE)
+#define P_TMRCLK	(P_DEFINED | P_IDENT(GPIO_PF15))
+#define P_SPI0_SSEL7	(P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_SPI0_SSEL6	(P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_SPI0_SSEL5	(P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_SPI0_SSEL4	(P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_SPI0_SSEL3	(P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_SPI0_SSEL2	(P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_SPI0_SSEL1	(P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_SPI0_SS	(P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_TMR11		(P_DONTCARE)
+#define P_TMR10		(P_DONTCARE)
+#define P_TMR9		(P_DONTCARE)
+#define P_TMR8		(P_DONTCARE)
+#define P_TMR7		(P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_TMR6		(P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_TMR5		(P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_TMR4		(P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_TMR3		(P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_TMR2		(P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_TMR1		(P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_TMR0		(P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_SPI0_MOSI	(P_DONTCARE)
+#define P_SPI0_MIS0	(P_DONTCARE)
+#define P_SPI0_SCK	(P_DONTCARE)
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-common/cdef_LPBlackfin.h b/include/asm-blackfin/mach-common/cdef_LPBlackfin.h
index 22aa5e6..94ed381 100644
--- a/include/asm-blackfin/mach-common/cdef_LPBlackfin.h
+++ b/include/asm-blackfin/mach-common/cdef_LPBlackfin.h
@@ -36,417 +36,296 @@
 #include <asm/mach-common/def_LPBlackfin.h>
 
 /*Cache & SRAM Memory*/
-#define pSRAM_BASE_ADDRESS ((volatile void **)SRAM_BASE_ADDRESS)
 #define bfin_read_SRAM_BASE_ADDRESS()        bfin_read32(SRAM_BASE_ADDRESS)
 #define bfin_write_SRAM_BASE_ADDRESS(val)    bfin_write32(SRAM_BASE_ADDRESS,val)
-#define pDMEM_CONTROL ((volatile unsigned long *)DMEM_CONTROL)
 #define bfin_read_DMEM_CONTROL()             bfin_read32(DMEM_CONTROL)
+#ifdef ANOMALY_05000125
+extern void bfin_write_DMEM_CONTROL(unsigned int val);
+#else
 #define bfin_write_DMEM_CONTROL(val)         bfin_write32(DMEM_CONTROL,val)
-#define pDCPLB_STATUS ((volatile unsigned long *)DCPLB_STATUS)
+#endif
 #define bfin_read_DCPLB_STATUS()             bfin_read32(DCPLB_STATUS)
 #define bfin_write_DCPLB_STATUS(val)         bfin_write32(DCPLB_STATUS,val)
-#define pDCPLB_FAULT_ADDR ((volatile void **)DCPLB_FAULT_ADDR)
 #define bfin_read_DCPLB_FAULT_ADDR()         bfin_read32(DCPLB_FAULT_ADDR)
 #define bfin_write_DCPLB_FAULT_ADDR(val)     bfin_write32(DCPLB_FAULT_ADDR,val)
 /*
 #define MMR_TIMEOUT            0xFFE00010
 */
-#define pDCPLB_ADDR0 ((volatile void **)DCPLB_ADDR0)
 #define bfin_read_DCPLB_ADDR0()              bfin_read32(DCPLB_ADDR0)
 #define bfin_write_DCPLB_ADDR0(val)          bfin_write32(DCPLB_ADDR0,val)
-#define pDCPLB_ADDR1 ((volatile void **)DCPLB_ADDR1)
 #define bfin_read_DCPLB_ADDR1()              bfin_read32(DCPLB_ADDR1)
 #define bfin_write_DCPLB_ADDR1(val)          bfin_write32(DCPLB_ADDR1,val)
-#define pDCPLB_ADDR2 ((volatile void **)DCPLB_ADDR2)
 #define bfin_read_DCPLB_ADDR2()              bfin_read32(DCPLB_ADDR2)
 #define bfin_write_DCPLB_ADDR2(val)          bfin_write32(DCPLB_ADDR2,val)
-#define pDCPLB_ADDR3 ((volatile void **)DCPLB_ADDR3)
 #define bfin_read_DCPLB_ADDR3()              bfin_read32(DCPLB_ADDR3)
 #define bfin_write_DCPLB_ADDR3(val)          bfin_write32(DCPLB_ADDR3,val)
-#define pDCPLB_ADDR4 ((volatile void **)DCPLB_ADDR4)
 #define bfin_read_DCPLB_ADDR4()              bfin_read32(DCPLB_ADDR4)
 #define bfin_write_DCPLB_ADDR4(val)          bfin_write32(DCPLB_ADDR4,val)
-#define pDCPLB_ADDR5 ((volatile void **)DCPLB_ADDR5)
 #define bfin_read_DCPLB_ADDR5()              bfin_read32(DCPLB_ADDR5)
 #define bfin_write_DCPLB_ADDR5(val)          bfin_write32(DCPLB_ADDR5,val)
-#define pDCPLB_ADDR6 ((volatile void **)DCPLB_ADDR6)
 #define bfin_read_DCPLB_ADDR6()              bfin_read32(DCPLB_ADDR6)
 #define bfin_write_DCPLB_ADDR6(val)          bfin_write32(DCPLB_ADDR6,val)
-#define pDCPLB_ADDR7 ((volatile void **)DCPLB_ADDR7)
 #define bfin_read_DCPLB_ADDR7()              bfin_read32(DCPLB_ADDR7)
 #define bfin_write_DCPLB_ADDR7(val)          bfin_write32(DCPLB_ADDR7,val)
-#define pDCPLB_ADDR8 ((volatile void **)DCPLB_ADDR8)
 #define bfin_read_DCPLB_ADDR8()              bfin_read32(DCPLB_ADDR8)
 #define bfin_write_DCPLB_ADDR8(val)          bfin_write32(DCPLB_ADDR8,val)
-#define pDCPLB_ADDR9 ((volatile void **)DCPLB_ADDR9)
 #define bfin_read_DCPLB_ADDR9()              bfin_read32(DCPLB_ADDR9)
 #define bfin_write_DCPLB_ADDR9(val)          bfin_write32(DCPLB_ADDR9,val)
-#define pDCPLB_ADDR10 ((volatile void **)DCPLB_ADDR10)
 #define bfin_read_DCPLB_ADDR10()             bfin_read32(DCPLB_ADDR10)
 #define bfin_write_DCPLB_ADDR10(val)         bfin_write32(DCPLB_ADDR10,val)
-#define pDCPLB_ADDR11 ((volatile void **)DCPLB_ADDR11)
 #define bfin_read_DCPLB_ADDR11()             bfin_read32(DCPLB_ADDR11)
 #define bfin_write_DCPLB_ADDR11(val)         bfin_write32(DCPLB_ADDR11,val)
-#define pDCPLB_ADDR12 ((volatile void **)DCPLB_ADDR12)
 #define bfin_read_DCPLB_ADDR12()             bfin_read32(DCPLB_ADDR12)
 #define bfin_write_DCPLB_ADDR12(val)         bfin_write32(DCPLB_ADDR12,val)
-#define pDCPLB_ADDR13 ((volatile void **)DCPLB_ADDR13)
 #define bfin_read_DCPLB_ADDR13()             bfin_read32(DCPLB_ADDR13)
 #define bfin_write_DCPLB_ADDR13(val)         bfin_write32(DCPLB_ADDR13,val)
-#define pDCPLB_ADDR14 ((volatile void **)DCPLB_ADDR14)
 #define bfin_read_DCPLB_ADDR14()             bfin_read32(DCPLB_ADDR14)
 #define bfin_write_DCPLB_ADDR14(val)         bfin_write32(DCPLB_ADDR14,val)
-#define pDCPLB_ADDR15 ((volatile void **)DCPLB_ADDR15)
 #define bfin_read_DCPLB_ADDR15()             bfin_read32(DCPLB_ADDR15)
 #define bfin_write_DCPLB_ADDR15(val)         bfin_write32(DCPLB_ADDR15,val)
-#define pDCPLB_DATA0 ((volatile unsigned long *)DCPLB_DATA0)
 #define bfin_read_DCPLB_DATA0()              bfin_read32(DCPLB_DATA0)
 #define bfin_write_DCPLB_DATA0(val)          bfin_write32(DCPLB_DATA0,val)
-#define pDCPLB_DATA1 ((volatile unsigned long *)DCPLB_DATA1)
 #define bfin_read_DCPLB_DATA1()              bfin_read32(DCPLB_DATA1)
 #define bfin_write_DCPLB_DATA1(val)          bfin_write32(DCPLB_DATA1,val)
-#define pDCPLB_DATA2 ((volatile unsigned long *)DCPLB_DATA2)
 #define bfin_read_DCPLB_DATA2()              bfin_read32(DCPLB_DATA2)
 #define bfin_write_DCPLB_DATA2(val)          bfin_write32(DCPLB_DATA2,val)
-#define pDCPLB_DATA3 ((volatile unsigned long *)DCPLB_DATA3)
 #define bfin_read_DCPLB_DATA3()              bfin_read32(DCPLB_DATA3)
 #define bfin_write_DCPLB_DATA3(val)          bfin_write32(DCPLB_DATA3,val)
-#define pDCPLB_DATA4 ((volatile unsigned long *)DCPLB_DATA4)
 #define bfin_read_DCPLB_DATA4()              bfin_read32(DCPLB_DATA4)
 #define bfin_write_DCPLB_DATA4(val)          bfin_write32(DCPLB_DATA4,val)
-#define pDCPLB_DATA5 ((volatile unsigned long *)DCPLB_DATA5)
 #define bfin_read_DCPLB_DATA5()              bfin_read32(DCPLB_DATA5)
 #define bfin_write_DCPLB_DATA5(val)          bfin_write32(DCPLB_DATA5,val)
-#define pDCPLB_DATA6 ((volatile unsigned long *)DCPLB_DATA6)
 #define bfin_read_DCPLB_DATA6()              bfin_read32(DCPLB_DATA6)
 #define bfin_write_DCPLB_DATA6(val)          bfin_write32(DCPLB_DATA6,val)
-#define pDCPLB_DATA7 ((volatile unsigned long *)DCPLB_DATA7)
 #define bfin_read_DCPLB_DATA7()              bfin_read32(DCPLB_DATA7)
 #define bfin_write_DCPLB_DATA7(val)          bfin_write32(DCPLB_DATA7,val)
-#define pDCPLB_DATA8 ((volatile unsigned long *)DCPLB_DATA8)
 #define bfin_read_DCPLB_DATA8()              bfin_read32(DCPLB_DATA8)
 #define bfin_write_DCPLB_DATA8(val)          bfin_write32(DCPLB_DATA8,val)
-#define pDCPLB_DATA9 ((volatile unsigned long *)DCPLB_DATA9)
 #define bfin_read_DCPLB_DATA9()              bfin_read32(DCPLB_DATA9)
 #define bfin_write_DCPLB_DATA9(val)          bfin_write32(DCPLB_DATA9,val)
-#define pDCPLB_DATA10 ((volatile unsigned long *)DCPLB_DATA10)
 #define bfin_read_DCPLB_DATA10()             bfin_read32(DCPLB_DATA10)
 #define bfin_write_DCPLB_DATA10(val)         bfin_write32(DCPLB_DATA10,val)
-#define pDCPLB_DATA11 ((volatile unsigned long *)DCPLB_DATA11)
 #define bfin_read_DCPLB_DATA11()             bfin_read32(DCPLB_DATA11)
 #define bfin_write_DCPLB_DATA11(val)         bfin_write32(DCPLB_DATA11,val)
-#define pDCPLB_DATA12 ((volatile unsigned long *)DCPLB_DATA12)
 #define bfin_read_DCPLB_DATA12()             bfin_read32(DCPLB_DATA12)
 #define bfin_write_DCPLB_DATA12(val)         bfin_write32(DCPLB_DATA12,val)
-#define pDCPLB_DATA13 ((volatile unsigned long *)DCPLB_DATA13)
 #define bfin_read_DCPLB_DATA13()             bfin_read32(DCPLB_DATA13)
 #define bfin_write_DCPLB_DATA13(val)         bfin_write32(DCPLB_DATA13,val)
-#define pDCPLB_DATA14 ((volatile unsigned long *)DCPLB_DATA14)
 #define bfin_read_DCPLB_DATA14()             bfin_read32(DCPLB_DATA14)
 #define bfin_write_DCPLB_DATA14(val)         bfin_write32(DCPLB_DATA14,val)
-#define pDCPLB_DATA15 ((volatile unsigned long *)DCPLB_DATA15)
 #define bfin_read_DCPLB_DATA15()             bfin_read32(DCPLB_DATA15)
 #define bfin_write_DCPLB_DATA15(val)         bfin_write32(DCPLB_DATA15,val)
-#define pDTEST_COMMAND ((volatile unsigned long *)DTEST_COMMAND)
 #define bfin_read_DTEST_COMMAND()            bfin_read32(DTEST_COMMAND)
 #define bfin_write_DTEST_COMMAND(val)        bfin_write32(DTEST_COMMAND,val)
 /*
 #define DTEST_INDEX            0xFFE00304
 */
-#define pDTEST_DATA0 ((volatile unsigned long *)DTEST_DATA0)
 #define bfin_read_DTEST_DATA0()              bfin_read32(DTEST_DATA0)
 #define bfin_write_DTEST_DATA0(val)          bfin_write32(DTEST_DATA0,val)
-#define pDTEST_DATA1 ((volatile unsigned long *)DTEST_DATA1)
 #define bfin_read_DTEST_DATA1()              bfin_read32(DTEST_DATA1)
 #define bfin_write_DTEST_DATA1(val)          bfin_write32(DTEST_DATA1,val)
 /*
 #define DTEST_DATA2            0xFFE00408
 #define DTEST_DATA3            0xFFE0040C
 */
-#define pIMEM_CONTROL ((volatile unsigned long *)IMEM_CONTROL)
 #define bfin_read_IMEM_CONTROL()             bfin_read32(IMEM_CONTROL)
+#ifdef ANOMALY_05000125
+extern void bfin_write_IMEM_CONTROL(unsigned int val);
+#else
 #define bfin_write_IMEM_CONTROL(val)         bfin_write32(IMEM_CONTROL,val)
-#define pICPLB_STATUS ((volatile unsigned long *)ICPLB_STATUS)
+#endif
 #define bfin_read_ICPLB_STATUS()             bfin_read32(ICPLB_STATUS)
 #define bfin_write_ICPLB_STATUS(val)         bfin_write32(ICPLB_STATUS,val)
-#define pICPLB_FAULT_ADDR ((volatile void **)ICPLB_FAULT_ADDR)
 #define bfin_read_ICPLB_FAULT_ADDR()         bfin_read32(ICPLB_FAULT_ADDR)
 #define bfin_write_ICPLB_FAULT_ADDR(val)     bfin_write32(ICPLB_FAULT_ADDR,val)
-#define pICPLB_ADDR0 ((volatile void **)ICPLB_ADDR0)
 #define bfin_read_ICPLB_ADDR0()              bfin_read32(ICPLB_ADDR0)
 #define bfin_write_ICPLB_ADDR0(val)          bfin_write32(ICPLB_ADDR0,val)
-#define pICPLB_ADDR1 ((volatile void **)ICPLB_ADDR1)
 #define bfin_read_ICPLB_ADDR1()              bfin_read32(ICPLB_ADDR1)
 #define bfin_write_ICPLB_ADDR1(val)          bfin_write32(ICPLB_ADDR1,val)
-#define pICPLB_ADDR2 ((volatile void **)ICPLB_ADDR2)
 #define bfin_read_ICPLB_ADDR2()              bfin_read32(ICPLB_ADDR2)
 #define bfin_write_ICPLB_ADDR2(val)          bfin_write32(ICPLB_ADDR2,val)
-#define pICPLB_ADDR3 ((volatile void **)ICPLB_ADDR3)
 #define bfin_read_ICPLB_ADDR3()              bfin_read32(ICPLB_ADDR3)
 #define bfin_write_ICPLB_ADDR3(val)          bfin_write32(ICPLB_ADDR3,val)
-#define pICPLB_ADDR4 ((volatile void **)ICPLB_ADDR4)
 #define bfin_read_ICPLB_ADDR4()              bfin_read32(ICPLB_ADDR4)
 #define bfin_write_ICPLB_ADDR4(val)          bfin_write32(ICPLB_ADDR4,val)
-#define pICPLB_ADDR5 ((volatile void **)ICPLB_ADDR5)
 #define bfin_read_ICPLB_ADDR5()              bfin_read32(ICPLB_ADDR5)
 #define bfin_write_ICPLB_ADDR5(val)          bfin_write32(ICPLB_ADDR5,val)
-#define pICPLB_ADDR6 ((volatile void **)ICPLB_ADDR6)
 #define bfin_read_ICPLB_ADDR6()              bfin_read32(ICPLB_ADDR6)
 #define bfin_write_ICPLB_ADDR6(val)          bfin_write32(ICPLB_ADDR6,val)
-#define pICPLB_ADDR7 ((volatile void **)ICPLB_ADDR7)
 #define bfin_read_ICPLB_ADDR7()              bfin_read32(ICPLB_ADDR7)
 #define bfin_write_ICPLB_ADDR7(val)          bfin_write32(ICPLB_ADDR7,val)
-#define pICPLB_ADDR8 ((volatile void **)ICPLB_ADDR8)
 #define bfin_read_ICPLB_ADDR8()              bfin_read32(ICPLB_ADDR8)
 #define bfin_write_ICPLB_ADDR8(val)          bfin_write32(ICPLB_ADDR8,val)
-#define pICPLB_ADDR9 ((volatile void **)ICPLB_ADDR9)
 #define bfin_read_ICPLB_ADDR9()              bfin_read32(ICPLB_ADDR9)
 #define bfin_write_ICPLB_ADDR9(val)          bfin_write32(ICPLB_ADDR9,val)
-#define pICPLB_ADDR10 ((volatile void **)ICPLB_ADDR10)
 #define bfin_read_ICPLB_ADDR10()             bfin_read32(ICPLB_ADDR10)
 #define bfin_write_ICPLB_ADDR10(val)         bfin_write32(ICPLB_ADDR10,val)
-#define pICPLB_ADDR11 ((volatile void **)ICPLB_ADDR11)
 #define bfin_read_ICPLB_ADDR11()             bfin_read32(ICPLB_ADDR11)
 #define bfin_write_ICPLB_ADDR11(val)         bfin_write32(ICPLB_ADDR11,val)
-#define pICPLB_ADDR12 ((volatile void **)ICPLB_ADDR12)
 #define bfin_read_ICPLB_ADDR12()             bfin_read32(ICPLB_ADDR12)
 #define bfin_write_ICPLB_ADDR12(val)         bfin_write32(ICPLB_ADDR12,val)
-#define pICPLB_ADDR13 ((volatile void **)ICPLB_ADDR13)
 #define bfin_read_ICPLB_ADDR13()             bfin_read32(ICPLB_ADDR13)
 #define bfin_write_ICPLB_ADDR13(val)         bfin_write32(ICPLB_ADDR13,val)
-#define pICPLB_ADDR14 ((volatile void **)ICPLB_ADDR14)
 #define bfin_read_ICPLB_ADDR14()             bfin_read32(ICPLB_ADDR14)
 #define bfin_write_ICPLB_ADDR14(val)         bfin_write32(ICPLB_ADDR14,val)
-#define pICPLB_ADDR15 ((volatile void **)ICPLB_ADDR15)
 #define bfin_read_ICPLB_ADDR15()             bfin_read32(ICPLB_ADDR15)
 #define bfin_write_ICPLB_ADDR15(val)         bfin_write32(ICPLB_ADDR15,val)
-#define pICPLB_DATA0 ((volatile unsigned long *)ICPLB_DATA0)
 #define bfin_read_ICPLB_DATA0()              bfin_read32(ICPLB_DATA0)
 #define bfin_write_ICPLB_DATA0(val)          bfin_write32(ICPLB_DATA0,val)
-#define pICPLB_DATA1 ((volatile unsigned long *)ICPLB_DATA1)
 #define bfin_read_ICPLB_DATA1()              bfin_read32(ICPLB_DATA1)
 #define bfin_write_ICPLB_DATA1(val)          bfin_write32(ICPLB_DATA1,val)
-#define pICPLB_DATA2 ((volatile unsigned long *)ICPLB_DATA2)
 #define bfin_read_ICPLB_DATA2()              bfin_read32(ICPLB_DATA2)
 #define bfin_write_ICPLB_DATA2(val)          bfin_write32(ICPLB_DATA2,val)
-#define pICPLB_DATA3 ((volatile unsigned long *)ICPLB_DATA3)
 #define bfin_read_ICPLB_DATA3()              bfin_read32(ICPLB_DATA3)
 #define bfin_write_ICPLB_DATA3(val)          bfin_write32(ICPLB_DATA3,val)
-#define pICPLB_DATA4 ((volatile unsigned long *)ICPLB_DATA4)
 #define bfin_read_ICPLB_DATA4()              bfin_read32(ICPLB_DATA4)
 #define bfin_write_ICPLB_DATA4(val)          bfin_write32(ICPLB_DATA4,val)
-#define pICPLB_DATA5 ((volatile unsigned long *)ICPLB_DATA5)
 #define bfin_read_ICPLB_DATA5()              bfin_read32(ICPLB_DATA5)
 #define bfin_write_ICPLB_DATA5(val)          bfin_write32(ICPLB_DATA5,val)
-#define pICPLB_DATA6 ((volatile unsigned long *)ICPLB_DATA6)
 #define bfin_read_ICPLB_DATA6()              bfin_read32(ICPLB_DATA6)
 #define bfin_write_ICPLB_DATA6(val)          bfin_write32(ICPLB_DATA6,val)
-#define pICPLB_DATA7 ((volatile unsigned long *)ICPLB_DATA7)
 #define bfin_read_ICPLB_DATA7()              bfin_read32(ICPLB_DATA7)
 #define bfin_write_ICPLB_DATA7(val)          bfin_write32(ICPLB_DATA7,val)
-#define pICPLB_DATA8 ((volatile unsigned long *)ICPLB_DATA8)
 #define bfin_read_ICPLB_DATA8()              bfin_read32(ICPLB_DATA8)
 #define bfin_write_ICPLB_DATA8(val)          bfin_write32(ICPLB_DATA8,val)
-#define pICPLB_DATA9 ((volatile unsigned long *)ICPLB_DATA9)
 #define bfin_read_ICPLB_DATA9()              bfin_read32(ICPLB_DATA9)
 #define bfin_write_ICPLB_DATA9(val)          bfin_write32(ICPLB_DATA9,val)
-#define pICPLB_DATA10 ((volatile unsigned long *)ICPLB_DATA10)
 #define bfin_read_ICPLB_DATA10()             bfin_read32(ICPLB_DATA10)
 #define bfin_write_ICPLB_DATA10(val)         bfin_write32(ICPLB_DATA10,val)
-#define pICPLB_DATA11 ((volatile unsigned long *)ICPLB_DATA11)
 #define bfin_read_ICPLB_DATA11()             bfin_read32(ICPLB_DATA11)
 #define bfin_write_ICPLB_DATA11(val)         bfin_write32(ICPLB_DATA11,val)
-#define pICPLB_DATA12 ((volatile unsigned long *)ICPLB_DATA12)
 #define bfin_read_ICPLB_DATA12()             bfin_read32(ICPLB_DATA12)
 #define bfin_write_ICPLB_DATA12(val)         bfin_write32(ICPLB_DATA12,val)
-#define pICPLB_DATA13 ((volatile unsigned long *)ICPLB_DATA13)
 #define bfin_read_ICPLB_DATA13()             bfin_read32(ICPLB_DATA13)
 #define bfin_write_ICPLB_DATA13(val)         bfin_write32(ICPLB_DATA13,val)
-#define pICPLB_DATA14 ((volatile unsigned long *)ICPLB_DATA14)
 #define bfin_read_ICPLB_DATA14()             bfin_read32(ICPLB_DATA14)
 #define bfin_write_ICPLB_DATA14(val)         bfin_write32(ICPLB_DATA14,val)
-#define pICPLB_DATA15 ((volatile unsigned long *)ICPLB_DATA15)
 #define bfin_read_ICPLB_DATA15()             bfin_read32(ICPLB_DATA15)
 #define bfin_write_ICPLB_DATA15(val)         bfin_write32(ICPLB_DATA15,val)
-#define pITEST_COMMAND ((volatile unsigned long *)ITEST_COMMAND)
 #define bfin_read_ITEST_COMMAND()            bfin_read32(ITEST_COMMAND)
 #define bfin_write_ITEST_COMMAND(val)        bfin_write32(ITEST_COMMAND,val)
 #if 0
 #define ITEST_INDEX            0xFFE01304   /* Instruction Test Index Register */
 #endif
-#define pITEST_DATA0 ((volatile unsigned long *)ITEST_DATA0)
 #define bfin_read_ITEST_DATA0()              bfin_read32(ITEST_DATA0)
 #define bfin_write_ITEST_DATA0(val)          bfin_write32(ITEST_DATA0,val)
-#define pITEST_DATA1 ((volatile unsigned long *)ITEST_DATA1)
 #define bfin_read_ITEST_DATA1()              bfin_read32(ITEST_DATA1)
 #define bfin_write_ITEST_DATA1(val)          bfin_write32(ITEST_DATA1,val)
 
 /* Event/Interrupt Registers*/
 
-#define pEVT0 ((volatile void **)EVT0)
 #define bfin_read_EVT0()                     bfin_read32(EVT0)
 #define bfin_write_EVT0(val)                 bfin_write32(EVT0,val)
-#define pEVT1 ((volatile void **)EVT1)
 #define bfin_read_EVT1()                     bfin_read32(EVT1)
 #define bfin_write_EVT1(val)                 bfin_write32(EVT1,val)
-#define pEVT2 ((volatile void **)EVT2)
 #define bfin_read_EVT2()                     bfin_read32(EVT2)
 #define bfin_write_EVT2(val)                 bfin_write32(EVT2,val)
-#define pEVT3 ((volatile void **)EVT3)
 #define bfin_read_EVT3()                     bfin_read32(EVT3)
 #define bfin_write_EVT3(val)                 bfin_write32(EVT3,val)
-#define pEVT4 ((volatile void **)EVT4)
 #define bfin_read_EVT4()                     bfin_read32(EVT4)
 #define bfin_write_EVT4(val)                 bfin_write32(EVT4,val)
-#define pEVT5 ((volatile void **)EVT5)
 #define bfin_read_EVT5()                     bfin_read32(EVT5)
 #define bfin_write_EVT5(val)                 bfin_write32(EVT5,val)
-#define pEVT6 ((volatile void **)EVT6)
 #define bfin_read_EVT6()                     bfin_read32(EVT6)
 #define bfin_write_EVT6(val)                 bfin_write32(EVT6,val)
-#define pEVT7 ((volatile void **)EVT7)
 #define bfin_read_EVT7()                     bfin_read32(EVT7)
 #define bfin_write_EVT7(val)                 bfin_write32(EVT7,val)
-#define pEVT8 ((volatile void **)EVT8)
 #define bfin_read_EVT8()                     bfin_read32(EVT8)
 #define bfin_write_EVT8(val)                 bfin_write32(EVT8,val)
-#define pEVT9 ((volatile void **)EVT9)
 #define bfin_read_EVT9()                     bfin_read32(EVT9)
 #define bfin_write_EVT9(val)                 bfin_write32(EVT9,val)
-#define pEVT10 ((volatile void **)EVT10)
 #define bfin_read_EVT10()                    bfin_read32(EVT10)
 #define bfin_write_EVT10(val)                bfin_write32(EVT10,val)
-#define pEVT11 ((volatile void **)EVT11)
 #define bfin_read_EVT11()                    bfin_read32(EVT11)
 #define bfin_write_EVT11(val)                bfin_write32(EVT11,val)
-#define pEVT12 ((volatile void **)EVT12)
 #define bfin_read_EVT12()                    bfin_read32(EVT12)
 #define bfin_write_EVT12(val)                bfin_write32(EVT12,val)
-#define pEVT13 ((volatile void **)EVT13)
 #define bfin_read_EVT13()                    bfin_read32(EVT13)
 #define bfin_write_EVT13(val)                bfin_write32(EVT13,val)
-#define pEVT14 ((volatile void **)EVT14)
 #define bfin_read_EVT14()                    bfin_read32(EVT14)
 #define bfin_write_EVT14(val)                bfin_write32(EVT14,val)
-#define pEVT15 ((volatile void **)EVT15)
 #define bfin_read_EVT15()                    bfin_read32(EVT15)
 #define bfin_write_EVT15(val)                bfin_write32(EVT15,val)
-#define pIMASK ((volatile unsigned long *)IMASK)
 #define bfin_read_IMASK()                    bfin_read32(IMASK)
 #define bfin_write_IMASK(val)                bfin_write32(IMASK,val)
-#define pIPEND ((volatile unsigned long *)IPEND)
 #define bfin_read_IPEND()                    bfin_read32(IPEND)
 #define bfin_write_IPEND(val)                bfin_write32(IPEND,val)
-#define pILAT ((volatile unsigned long *)ILAT)
 #define bfin_read_ILAT()                     bfin_read32(ILAT)
 #define bfin_write_ILAT(val)                 bfin_write32(ILAT,val)
 
 /*Core Timer Registers*/
-#define pTCNTL ((volatile unsigned long *)TCNTL)
 #define bfin_read_TCNTL()                    bfin_read32(TCNTL)
 #define bfin_write_TCNTL(val)                bfin_write32(TCNTL,val)
-#define pTPERIOD ((volatile unsigned long *)TPERIOD)
 #define bfin_read_TPERIOD()                  bfin_read32(TPERIOD)
 #define bfin_write_TPERIOD(val)              bfin_write32(TPERIOD,val)
-#define pTSCALE ((volatile unsigned long *)TSCALE)
 #define bfin_read_TSCALE()                   bfin_read32(TSCALE)
 #define bfin_write_TSCALE(val)               bfin_write32(TSCALE,val)
-#define pTCOUNT ((volatile unsigned long *)TCOUNT)
 #define bfin_read_TCOUNT()                   bfin_read32(TCOUNT)
 #define bfin_write_TCOUNT(val)               bfin_write32(TCOUNT,val)
 
 /*Debug/MP/Emulation Registers*/
-#define pDSPID ((volatile unsigned long *)DSPID)
 #define bfin_read_DSPID()                    bfin_read32(DSPID)
 #define bfin_write_DSPID(val)                bfin_write32(DSPID,val)
-#define pDBGCTL ((volatile unsigned long *)DBGCTL)
 #define bfin_read_DBGCTL()                   bfin_read32(DBGCTL)
 #define bfin_write_DBGCTL(val)               bfin_write32(DBGCTL,val)
-#define pDBGSTAT ((volatile unsigned long *)DBGSTAT)
 #define bfin_read_DBGSTAT()                  bfin_read32(DBGSTAT)
 #define bfin_write_DBGSTAT(val)              bfin_write32(DBGSTAT,val)
-#define pEMUDAT ((volatile unsigned long *)EMUDAT)
 #define bfin_read_EMUDAT()                   bfin_read32(EMUDAT)
 #define bfin_write_EMUDAT(val)               bfin_write32(EMUDAT,val)
 
 /*Trace Buffer Registers*/
-#define pTBUFCTL ((volatile unsigned long *)TBUFCTL)
 #define bfin_read_TBUFCTL()                  bfin_read32(TBUFCTL)
 #define bfin_write_TBUFCTL(val)              bfin_write32(TBUFCTL,val)
-#define pTBUFSTAT ((volatile unsigned long *)TBUFSTAT)
 #define bfin_read_TBUFSTAT()                 bfin_read32(TBUFSTAT)
 #define bfin_write_TBUFSTAT(val)             bfin_write32(TBUFSTAT,val)
-#define pTBUF ((volatile void **)TBUF)
 #define bfin_read_TBUF()                     bfin_read32(TBUF)
 #define bfin_write_TBUF(val)                 bfin_write32(TBUF,val)
 
 /*Watch Point Control Registers*/
-#define pWPIACTL ((volatile unsigned long *)WPIACTL)
 #define bfin_read_WPIACTL()                  bfin_read32(WPIACTL)
 #define bfin_write_WPIACTL(val)              bfin_write32(WPIACTL,val)
-#define pWPIA0 ((volatile void **)WPIA0)
 #define bfin_read_WPIA0()                    bfin_read32(WPIA0)
 #define bfin_write_WPIA0(val)                bfin_write32(WPIA0,val)
-#define pWPIA1 ((volatile void **)WPIA1)
 #define bfin_read_WPIA1()                    bfin_read32(WPIA1)
 #define bfin_write_WPIA1(val)                bfin_write32(WPIA1,val)
-#define pWPIA2 ((volatile void **)WPIA2)
 #define bfin_read_WPIA2()                    bfin_read32(WPIA2)
 #define bfin_write_WPIA2(val)                bfin_write32(WPIA2,val)
-#define pWPIA3 ((volatile void **)WPIA3)
 #define bfin_read_WPIA3()                    bfin_read32(WPIA3)
 #define bfin_write_WPIA3(val)                bfin_write32(WPIA3,val)
-#define pWPIA4 ((volatile void **)WPIA4)
 #define bfin_read_WPIA4()                    bfin_read32(WPIA4)
 #define bfin_write_WPIA4(val)                bfin_write32(WPIA4,val)
-#define pWPIA5 ((volatile void **)WPIA5)
 #define bfin_read_WPIA5()                    bfin_read32(WPIA5)
 #define bfin_write_WPIA5(val)                bfin_write32(WPIA5,val)
-#define pWPIACNT0 ((volatile unsigned long *)WPIACNT0)
 #define bfin_read_WPIACNT0()                 bfin_read32(WPIACNT0)
 #define bfin_write_WPIACNT0(val)             bfin_write32(WPIACNT0,val)
-#define pWPIACNT1 ((volatile unsigned long *)WPIACNT1)
 #define bfin_read_WPIACNT1()                 bfin_read32(WPIACNT1)
 #define bfin_write_WPIACNT1(val)             bfin_write32(WPIACNT1,val)
-#define pWPIACNT2 ((volatile unsigned long *)WPIACNT2)
 #define bfin_read_WPIACNT2()                 bfin_read32(WPIACNT2)
 #define bfin_write_WPIACNT2(val)             bfin_write32(WPIACNT2,val)
-#define pWPIACNT3 ((volatile unsigned long *)WPIACNT3)
 #define bfin_read_WPIACNT3()                 bfin_read32(WPIACNT3)
 #define bfin_write_WPIACNT3(val)             bfin_write32(WPIACNT3,val)
-#define pWPIACNT4 ((volatile unsigned long *)WPIACNT4)
 #define bfin_read_WPIACNT4()                 bfin_read32(WPIACNT4)
 #define bfin_write_WPIACNT4(val)             bfin_write32(WPIACNT4,val)
-#define pWPIACNT5 ((volatile unsigned long *)WPIACNT5)
 #define bfin_read_WPIACNT5()                 bfin_read32(WPIACNT5)
 #define bfin_write_WPIACNT5(val)             bfin_write32(WPIACNT5,val)
-#define pWPDACTL ((volatile unsigned long *)WPDACTL)
 #define bfin_read_WPDACTL()                  bfin_read32(WPDACTL)
 #define bfin_write_WPDACTL(val)              bfin_write32(WPDACTL,val)
-#define pWPDA0 ((volatile void **)WPDA0)
 #define bfin_read_WPDA0()                    bfin_read32(WPDA0)
 #define bfin_write_WPDA0(val)                bfin_write32(WPDA0,val)
-#define pWPDA1 ((volatile void **)WPDA1)
 #define bfin_read_WPDA1()                    bfin_read32(WPDA1)
 #define bfin_write_WPDA1(val)                bfin_write32(WPDA1,val)
-#define pWPDACNT0 ((volatile unsigned long *)WPDACNT0)
 #define bfin_read_WPDACNT0()                 bfin_read32(WPDACNT0)
 #define bfin_write_WPDACNT0(val)             bfin_write32(WPDACNT0,val)
-#define pWPDACNT1 ((volatile unsigned long *)WPDACNT1)
 #define bfin_read_WPDACNT1()                 bfin_read32(WPDACNT1)
 #define bfin_write_WPDACNT1(val)             bfin_write32(WPDACNT1,val)
-#define pWPSTAT ((volatile unsigned long *)WPSTAT)
 #define bfin_read_WPSTAT()                   bfin_read32(WPSTAT)
 #define bfin_write_WPSTAT(val)               bfin_write32(WPSTAT,val)
 
 /*Performance Monitor Registers*/
-#define pPFCTL ((volatile unsigned long *)PFCTL)
 #define bfin_read_PFCTL()                    bfin_read32(PFCTL)
 #define bfin_write_PFCTL(val)                bfin_write32(PFCTL,val)
-#define pPFCNTR0 ((volatile unsigned long *)PFCNTR0)
 #define bfin_read_PFCNTR0()                  bfin_read32(PFCNTR0)
 #define bfin_write_PFCNTR0(val)              bfin_write32(PFCNTR0,val)
-#define pPFCNTR1 ((volatile unsigned long *)PFCNTR1)
 #define bfin_read_PFCNTR1()                  bfin_read32(PFCNTR1)
 #define bfin_write_PFCNTR1(val)              bfin_write32(PFCNTR1,val)
 
@@ -454,18 +333,4 @@
 #define IPRIO                  0xFFE02110
 */
 
-#if defined(CONFIG_BFIN_ALIVE_LED)
-#define pCONFIG_BFIN_ALIVE_LED_DPORT \
-	(volatile unsigned short *)CONFIG_BFIN_ALIVE_LED_DPORT
-#define pCONFIG_BFIN_ALIVE_LED_PORT \
-	(volatile unsigned short *)CONFIG_BFIN_ALIVE_LED_PORT
-#endif
-
-#if defined(CONFIG_BFIN_IDLE_LED)
-#define pCONFIG_BFIN_IDLE_LED_DPORT \
-	(volatile unsigned short *)CONFIG_BFIN_IDLE_LED_DPORT
-#define pCONFIG_BFIN_IDLE_LED_PORT \
-	(volatile unsigned short *)CONFIG_BFIN_IDLE_LED_PORT
-#endif
-
 #endif				/* _CDEF_LPBLACKFIN_H */
diff --git a/include/asm-blackfin/mach-common/def_LPBlackfin.h b/include/asm-blackfin/mach-common/def_LPBlackfin.h
index 7610352..be1ece8 100644
--- a/include/asm-blackfin/mach-common/def_LPBlackfin.h
+++ b/include/asm-blackfin/mach-common/def_LPBlackfin.h
@@ -42,6 +42,12 @@
 
 #if defined(ANOMALY_05000198)
 
+#define bfin_read8(addr) ({ unsigned char __v; \
+		__asm__ __volatile__ ("NOP;\n\t" \
+			"%0 = b[%1] (z);\n\t" \
+			: "=d"(__v) : "a"(addr)); \
+		__v; })
+
 #define bfin_read16(addr) ({ unsigned __v; \
                        __asm__ __volatile__ ("NOP;\n\t"\
 	         			     			"%0 = w[%1] (z);\n\t"\
@@ -52,6 +58,11 @@
                                             "%0 = [%1];\n\t"\
   : "=d"(__v) : "a"(addr)); __v; })
 
+#define bfin_write8(addr, val) ({ \
+		__asm__ __volatile__ ("NOP;\n\t" \
+			"b[%0] = %1;\n\t" \
+			: : "a"(addr), "d"(val) : "memory");})
+
 #define bfin_write16(addr,val) ({\
                       __asm__ __volatile__ ("NOP;\n\t"\
                                             "w[%0] = %1;\n\t"\
@@ -64,6 +75,12 @@
 
 #else
 
+#define bfin_read8(addr) ({ unsigned char __v; \
+		__asm__ __volatile__ ( \
+			"%0 = b[%1] (z);\n\t" \
+			:"=d"(__v) : "a"(addr)); \
+		__v; })
+
 #define bfin_read16(addr) ({ unsigned __v; \
                        __asm__ __volatile__ (\
 	         			     			"%0 = w[%1] (z);\n\t"\
@@ -74,6 +91,11 @@
                                             "%0 = [%1];\n\t"\
   : "=d"(__v) : "a"(addr)); __v; })
 
+#define bfin_write8(addr, val) ({ \
+		__asm__ __volatile__ ( \
+			"b[%0] = %1; \n\t" \
+			::"a"(addr), "d"(val) : "memory");})
+
 #define bfin_write16(addr,val) ({\
                       __asm__ __volatile__ (\
                                             "w[%0] = %1;\n\t"\
diff --git a/include/asm-blackfin/macros.h b/include/asm-blackfin/macros.h
deleted file mode 100644
index c0c04a2..0000000
--- a/include/asm-blackfin/macros.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/************************************************************************
- *
- * macros.h
- *
- * (c) Copyright 2001-2003 Analog Devices, Inc.  All rights reserved.
- *
- ************************************************************************/
-
-/* Defines various assembly macros. */
-
-#ifndef _MACROS_H
-#define _MACROS_H
-
-#define LO(con32) ((con32) & 0xFFFF)
-#define lo(con32) ((con32) & 0xFFFF)
-#define HI(con32) (((con32) >> 16) & 0xFFFF)
-#define hi(con32) (((con32) >> 16) & 0xFFFF)
-
-/*
- * Set the corresponding bits in a System Register (SR);
- * All bits set in "mask" will be set in the system register
- * specified by "sys_reg" bitset_SR(sys_reg, mask), where
- * sys_reg is the system register and mask are the bits to be set.
- */
-#define bitset_SR(sys_reg, mask)\
-		[--SP] = (R7:6);\
-		r7 = sys_reg;\
-		r6.l = (mask) & 0xffff;\
-		r6.h = (mask) >> 16;\
-		r7 = r7 | r6;\
-		sys_reg = r7;\
-		csync;\
-		(R7:6) = [SP++]
-
-/*
- * Clear the corresponding bits in a System Register (SR);
- * All bits set in "mask" will be cleared in the SR
- * specified by "sys_reg" bitclr_SR(sys_reg, mask), where
- * sys_reg is the SR and mask are the bits to be cleared.
- */
-#define bitclr_SR(sys_reg, mask)\
-		[--SP] = (R7:6);\
-		r7 = sys_reg;\
-		r7 =~ r7;\
-		r6.l = (mask) & 0xffff;\
-		r6.h = (mask) >> 16;\
-		r7 = r7 | r6;\
-		r7 =~ r7;\
-		sys_reg = r7;\
-		csync;\
-		(R7:6) = [SP++]
-
-/*
- * Set the corresponding bits in a Memory Mapped Register (MMR);
- * All bits set in "mask" will be set in the MMR specified by "mmr_reg"
- * bitset_MMR(mmr_reg, mask), where mmr_reg is the MMR and mask are
- * the bits to be set.
- */
-#define bitset_MMR(mmr_reg, mask)\
-		[--SP] = (R7:6);\
-		[--SP] = P5;\
-		p5.l = mmr_reg & 0xffff;\
-		p5.h = mmr_reg >> 16;\
-		r7 = [p5];\
-		r6.l = (mask) & 0xffff;\
-		r6.h = (mask) >> 16;\
-		r7 = r7 | r6;\
-		[p5] = r7;\
-		csync;\
-		p5 = [SP++];\
-		(R7:6) = [SP++]
-
-/*
- * Clear the corresponding bits in a Memory Mapped Register (MMR);
- * All bits set in "mask" will be cleared in the MMR specified by "mmr_reg"
- * bitclr_MMRreg(mmr_reg, mask), where sys_reg is the MMR and mask are
- * the bits to be cleared.
- */
-#define bitclr_MMR(mmr_reg, mask)\
-		[--SP] = (R7:6);\
-		[--SP] = P5;\
-		p5.l = mmr_reg & 0xffff;\
-		p5.h = mmr_reg >> 16;\
-		r7 = [p5];\
-		r7 =~ r7;\
-		r6.l = (mask) & 0xffff;\
-		r6.h = (mask) >> 16;\
-		r7 = r7 | r6;\
-		r7 =~ r7;\
-		[p5] = r7;\
-		csync;\
-		p5 = [SP++];\
-		(R7:6) = [SP++]
-
-#endif				/* _MACROS_H */
diff --git a/include/asm-blackfin/mman.h b/include/asm-blackfin/mman.h
index 4d504f9..b58f5ad 100644
--- a/include/asm-blackfin/mman.h
+++ b/include/asm-blackfin/mman.h
@@ -22,8 +22,6 @@
 #define MAP_NORESERVE	0x4000	/* don't check for reservations */
 #define MAP_POPULATE	0x8000	/* populate (prefault) pagetables */
 #define MAP_NONBLOCK	0x10000	/* do not block on IO */
-#define MAP_UNINITIALIZE 0x4000000  /* For anonymous mmap, memory could
-                                    be uninitialized. */
 
 #define MS_ASYNC	1	/* sync memory asynchronously */
 #define MS_INVALIDATE	2	/* invalidate the caches */
diff --git a/include/asm-blackfin/page.h b/include/asm-blackfin/page.h
index ffad947..8bc8671 100644
--- a/include/asm-blackfin/page.h
+++ b/include/asm-blackfin/page.h
@@ -4,7 +4,11 @@
 /* PAGE_SHIFT determines the page size */
 
 #define PAGE_SHIFT	12
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE	(1 << PAGE_SHIFT)
+#else
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#endif
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #ifdef __KERNEL__
diff --git a/include/asm-blackfin/portmux.h b/include/asm-blackfin/portmux.h
new file mode 100644
index 0000000..9d3681e
--- /dev/null
+++ b/include/asm-blackfin/portmux.h
@@ -0,0 +1,1133 @@
+/*
+ * Common header file for blackfin family of processors.
+ *
+ */
+
+#ifndef _PORTMUX_H_
+#define _PORTMUX_H_
+
+#define P_IDENT(x)	((x) & 0x1FF)
+#define P_FUNCT(x)	(((x) & 0x3) << 9)
+#define P_FUNCT2MUX(x)	(((x) >> 9) & 0x3)
+#define P_DEFINED	0x8000
+#define P_UNDEF		0x4000
+#define P_MAYSHARE	0x2000
+#define P_DONTCARE	0x1000
+
+#include <asm/gpio.h>
+#include <asm/mach/portmux.h>
+
+#ifndef P_SPORT2_TFS
+#define P_SPORT2_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DTSEC
+#define P_SPORT2_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DTPRI
+#define P_SPORT2_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT2_TSCLK
+#define P_SPORT2_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT2_RFS
+#define P_SPORT2_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DRSEC
+#define P_SPORT2_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DRPRI
+#define P_SPORT2_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT2_RSCLK
+#define P_SPORT2_RSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT3_TFS
+#define P_SPORT3_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DTSEC
+#define P_SPORT3_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DTPRI
+#define P_SPORT3_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT3_TSCLK
+#define P_SPORT3_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT3_RFS
+#define P_SPORT3_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DRSEC
+#define P_SPORT3_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DRPRI
+#define P_SPORT3_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT3_RSCLK
+#define P_SPORT3_RSCLK P_UNDEF
+#endif
+
+#ifndef P_TMR4
+#define P_TMR4 P_UNDEF
+#endif
+
+#ifndef P_TMR5
+#define P_TMR5 P_UNDEF
+#endif
+
+#ifndef P_TMR6
+#define P_TMR6 P_UNDEF
+#endif
+
+#ifndef P_TMR7
+#define P_TMR7 P_UNDEF
+#endif
+
+#ifndef P_TWI1_SCL
+#define P_TWI1_SCL P_UNDEF
+#endif
+
+#ifndef P_TWI1_SDA
+#define P_TWI1_SDA P_UNDEF
+#endif
+
+#ifndef P_UART3_RTS
+#define P_UART3_RTS P_UNDEF
+#endif
+
+#ifndef P_UART3_CTS
+#define P_UART3_CTS P_UNDEF
+#endif
+
+#ifndef P_UART2_TX
+#define P_UART2_TX P_UNDEF
+#endif
+
+#ifndef P_UART2_RX
+#define P_UART2_RX P_UNDEF
+#endif
+
+#ifndef P_UART3_TX
+#define P_UART3_TX P_UNDEF
+#endif
+
+#ifndef P_UART3_RX
+#define P_UART3_RX P_UNDEF
+#endif
+
+#ifndef P_SPI2_SS
+#define P_SPI2_SS P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL1
+#define P_SPI2_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL2
+#define P_SPI2_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL3
+#define P_SPI2_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SCK
+#define P_SPI2_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI2_MOSI
+#define P_SPI2_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI2_MISO
+#define P_SPI2_MISO P_UNDEF
+#endif
+
+#ifndef P_TMR0
+#define P_TMR0 P_UNDEF
+#endif
+
+#ifndef P_TMR1
+#define P_TMR1 P_UNDEF
+#endif
+
+#ifndef P_TMR2
+#define P_TMR2 P_UNDEF
+#endif
+
+#ifndef P_TMR3
+#define P_TMR3 P_UNDEF
+#endif
+
+#ifndef P_SPORT0_TFS
+#define P_SPORT0_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DTSEC
+#define P_SPORT0_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DTPRI
+#define P_SPORT0_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT0_TSCLK
+#define P_SPORT0_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT0_RFS
+#define P_SPORT0_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DRSEC
+#define P_SPORT0_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DRPRI
+#define P_SPORT0_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT0_RSCLK
+#define P_SPORT0_RSCLK P_UNDEF
+#endif
+
+#ifndef P_SD_D0
+#define P_SD_D0 P_UNDEF
+#endif
+
+#ifndef P_SD_D1
+#define P_SD_D1 P_UNDEF
+#endif
+
+#ifndef P_SD_D2
+#define P_SD_D2 P_UNDEF
+#endif
+
+#ifndef P_SD_D3
+#define P_SD_D3 P_UNDEF
+#endif
+
+#ifndef P_SD_CLK
+#define P_SD_CLK P_UNDEF
+#endif
+
+#ifndef P_SD_CMD
+#define P_SD_CMD P_UNDEF
+#endif
+
+#ifndef P_MMCLK
+#define P_MMCLK P_UNDEF
+#endif
+
+#ifndef P_MBCLK
+#define P_MBCLK P_UNDEF
+#endif
+
+#ifndef P_PPI1_D0
+#define P_PPI1_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D1
+#define P_PPI1_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D2
+#define P_PPI1_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D3
+#define P_PPI1_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D4
+#define P_PPI1_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D5
+#define P_PPI1_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D6
+#define P_PPI1_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D7
+#define P_PPI1_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D8
+#define P_PPI1_D8 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D9
+#define P_PPI1_D9 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D10
+#define P_PPI1_D10 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D11
+#define P_PPI1_D11 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D12
+#define P_PPI1_D12 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D13
+#define P_PPI1_D13 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D14
+#define P_PPI1_D14 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D15
+#define P_PPI1_D15 P_UNDEF
+#endif
+
+#ifndef P_HOST_D8
+#define P_HOST_D8 P_UNDEF
+#endif
+
+#ifndef P_HOST_D9
+#define P_HOST_D9 P_UNDEF
+#endif
+
+#ifndef P_HOST_D10
+#define P_HOST_D10 P_UNDEF
+#endif
+
+#ifndef P_HOST_D11
+#define P_HOST_D11 P_UNDEF
+#endif
+
+#ifndef P_HOST_D12
+#define P_HOST_D12 P_UNDEF
+#endif
+
+#ifndef P_HOST_D13
+#define P_HOST_D13 P_UNDEF
+#endif
+
+#ifndef P_HOST_D14
+#define P_HOST_D14 P_UNDEF
+#endif
+
+#ifndef P_HOST_D15
+#define P_HOST_D15 P_UNDEF
+#endif
+
+#ifndef P_HOST_D0
+#define P_HOST_D0 P_UNDEF
+#endif
+
+#ifndef P_HOST_D1
+#define P_HOST_D1 P_UNDEF
+#endif
+
+#ifndef P_HOST_D2
+#define P_HOST_D2 P_UNDEF
+#endif
+
+#ifndef P_HOST_D3
+#define P_HOST_D3 P_UNDEF
+#endif
+
+#ifndef P_HOST_D4
+#define P_HOST_D4 P_UNDEF
+#endif
+
+#ifndef P_HOST_D5
+#define P_HOST_D5 P_UNDEF
+#endif
+
+#ifndef P_HOST_D6
+#define P_HOST_D6 P_UNDEF
+#endif
+
+#ifndef P_HOST_D7
+#define P_HOST_D7 P_UNDEF
+#endif
+
+#ifndef P_SPORT1_TFS
+#define P_SPORT1_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DTSEC
+#define P_SPORT1_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DTPRI
+#define P_SPORT1_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT1_TSCLK
+#define P_SPORT1_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT1_RFS
+#define P_SPORT1_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DRSEC
+#define P_SPORT1_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DRPRI
+#define P_SPORT1_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT1_RSCLK
+#define P_SPORT1_RSCLK P_UNDEF
+#endif
+
+#ifndef P_PPI2_D0
+#define P_PPI2_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D1
+#define P_PPI2_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D2
+#define P_PPI2_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D3
+#define P_PPI2_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D4
+#define P_PPI2_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D5
+#define P_PPI2_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D6
+#define P_PPI2_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D7
+#define P_PPI2_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D18
+#define P_PPI0_D18 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D19
+#define P_PPI0_D19 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D20
+#define P_PPI0_D20 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D21
+#define P_PPI0_D21 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D22
+#define P_PPI0_D22 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D23
+#define P_PPI0_D23 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW0
+#define P_KEY_ROW0 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW1
+#define P_KEY_ROW1 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW2
+#define P_KEY_ROW2 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW3
+#define P_KEY_ROW3 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL0
+#define P_KEY_COL0 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL1
+#define P_KEY_COL1 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL2
+#define P_KEY_COL2 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL3
+#define P_KEY_COL3 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SCK
+#define P_SPI0_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI0_MISO
+#define P_SPI0_MISO P_UNDEF
+#endif
+
+#ifndef P_SPI0_MOSI
+#define P_SPI0_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI0_SS
+#define P_SPI0_SS P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL1
+#define P_SPI0_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL2
+#define P_SPI0_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL3
+#define P_SPI0_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_UART0_TX
+#define P_UART0_TX P_UNDEF
+#endif
+
+#ifndef P_UART0_RX
+#define P_UART0_RX P_UNDEF
+#endif
+
+#ifndef P_UART1_RTS
+#define P_UART1_RTS P_UNDEF
+#endif
+
+#ifndef P_UART1_CTS
+#define P_UART1_CTS P_UNDEF
+#endif
+
+#ifndef P_PPI1_CLK
+#define P_PPI1_CLK P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS1
+#define P_PPI1_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS2
+#define P_PPI1_FS2 P_UNDEF
+#endif
+
+#ifndef P_TWI0_SCL
+#define P_TWI0_SCL P_UNDEF
+#endif
+
+#ifndef P_TWI0_SDA
+#define P_TWI0_SDA P_UNDEF
+#endif
+
+#ifndef P_KEY_COL7
+#define P_KEY_COL7 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW6
+#define P_KEY_ROW6 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL6
+#define P_KEY_COL6 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW5
+#define P_KEY_ROW5 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL5
+#define P_KEY_COL5 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW4
+#define P_KEY_ROW4 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL4
+#define P_KEY_COL4 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW7
+#define P_KEY_ROW7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D0
+#define P_PPI0_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D1
+#define P_PPI0_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D2
+#define P_PPI0_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D3
+#define P_PPI0_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D4
+#define P_PPI0_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D5
+#define P_PPI0_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D6
+#define P_PPI0_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D7
+#define P_PPI0_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D8
+#define P_PPI0_D8 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D9
+#define P_PPI0_D9 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D10
+#define P_PPI0_D10 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D11
+#define P_PPI0_D11 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D12
+#define P_PPI0_D12 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D13
+#define P_PPI0_D13 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D14
+#define P_PPI0_D14 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D15
+#define P_PPI0_D15 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D0A
+#define P_ATAPI_D0A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D1A
+#define P_ATAPI_D1A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D2A
+#define P_ATAPI_D2A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D3A
+#define P_ATAPI_D3A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D4A
+#define P_ATAPI_D4A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D5A
+#define P_ATAPI_D5A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D6A
+#define P_ATAPI_D6A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D7A
+#define P_ATAPI_D7A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D8A
+#define P_ATAPI_D8A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D9A
+#define P_ATAPI_D9A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D10A
+#define P_ATAPI_D10A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D11A
+#define P_ATAPI_D11A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D12A
+#define P_ATAPI_D12A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D13A
+#define P_ATAPI_D13A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D14A
+#define P_ATAPI_D14A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D15A
+#define P_ATAPI_D15A P_UNDEF
+#endif
+
+#ifndef P_PPI0_CLK
+#define P_PPI0_CLK P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS1
+#define P_PPI0_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS2
+#define P_PPI0_FS2 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D16
+#define P_PPI0_D16 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D17
+#define P_PPI0_D17 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL1
+#define P_SPI1_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL2
+#define P_SPI1_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL3
+#define P_SPI1_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SCK
+#define P_SPI1_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI1_MISO
+#define P_SPI1_MISO P_UNDEF
+#endif
+
+#ifndef P_SPI1_MOSI
+#define P_SPI1_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI1_SS
+#define P_SPI1_SS P_UNDEF
+#endif
+
+#ifndef P_CAN0_TX
+#define P_CAN0_TX P_UNDEF
+#endif
+
+#ifndef P_CAN0_RX
+#define P_CAN0_RX P_UNDEF
+#endif
+
+#ifndef P_CAN1_TX
+#define P_CAN1_TX P_UNDEF
+#endif
+
+#ifndef P_CAN1_RX
+#define P_CAN1_RX P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A0A
+#define P_ATAPI_A0A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A1A
+#define P_ATAPI_A1A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A2A
+#define P_ATAPI_A2A P_UNDEF
+#endif
+
+#ifndef P_HOST_CE
+#define P_HOST_CE P_UNDEF
+#endif
+
+#ifndef P_HOST_RD
+#define P_HOST_RD P_UNDEF
+#endif
+
+#ifndef P_HOST_WR
+#define P_HOST_WR P_UNDEF
+#endif
+
+#ifndef P_MTXONB
+#define P_MTXONB P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS2
+#define P_PPI2_FS2 P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS1
+#define P_PPI2_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI2_CLK
+#define P_PPI2_CLK P_UNDEF
+#endif
+
+#ifndef P_CNT_CZM
+#define P_CNT_CZM P_UNDEF
+#endif
+
+#ifndef P_UART1_TX
+#define P_UART1_TX P_UNDEF
+#endif
+
+#ifndef P_UART1_RX
+#define P_UART1_RX P_UNDEF
+#endif
+
+#ifndef P_ATAPI_RESET
+#define P_ATAPI_RESET P_UNDEF
+#endif
+
+#ifndef P_HOST_ADDR
+#define P_HOST_ADDR P_UNDEF
+#endif
+
+#ifndef P_HOST_ACK
+#define P_HOST_ACK P_UNDEF
+#endif
+
+#ifndef P_MTX
+#define P_MTX P_UNDEF
+#endif
+
+#ifndef P_MRX
+#define P_MRX P_UNDEF
+#endif
+
+#ifndef P_MRXONB
+#define P_MRXONB P_UNDEF
+#endif
+
+#ifndef P_A4
+#define P_A4 P_UNDEF
+#endif
+
+#ifndef P_A5
+#define P_A5 P_UNDEF
+#endif
+
+#ifndef P_A6
+#define P_A6 P_UNDEF
+#endif
+
+#ifndef P_A7
+#define P_A7 P_UNDEF
+#endif
+
+#ifndef P_A8
+#define P_A8 P_UNDEF
+#endif
+
+#ifndef P_A9
+#define P_A9 P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS3
+#define P_PPI1_FS3 P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS3
+#define P_PPI2_FS3 P_UNDEF
+#endif
+
+#ifndef P_TMR8
+#define P_TMR8 P_UNDEF
+#endif
+
+#ifndef P_TMR9
+#define P_TMR9 P_UNDEF
+#endif
+
+#ifndef P_TMR10
+#define P_TMR10 P_UNDEF
+#endif
+#ifndef P_TMR11
+#define P_TMR11 P_UNDEF
+#endif
+
+#ifndef P_DMAR0
+#define P_DMAR0 P_UNDEF
+#endif
+
+#ifndef P_DMAR1
+#define P_DMAR1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS3
+#define P_PPI0_FS3 P_UNDEF
+#endif
+
+#ifndef P_CNT_CDG
+#define P_CNT_CDG P_UNDEF
+#endif
+
+#ifndef P_CNT_CUD
+#define P_CNT_CUD P_UNDEF
+#endif
+
+#ifndef P_A10
+#define P_A10 P_UNDEF
+#endif
+
+#ifndef P_A11
+#define P_A11 P_UNDEF
+#endif
+
+#ifndef P_A12
+#define P_A12 P_UNDEF
+#endif
+
+#ifndef P_A13
+#define P_A13 P_UNDEF
+#endif
+
+#ifndef P_A14
+#define P_A14 P_UNDEF
+#endif
+
+#ifndef P_A15
+#define P_A15 P_UNDEF
+#endif
+
+#ifndef P_A16
+#define P_A16 P_UNDEF
+#endif
+
+#ifndef P_A17
+#define P_A17 P_UNDEF
+#endif
+
+#ifndef P_A18
+#define P_A18 P_UNDEF
+#endif
+
+#ifndef P_A19
+#define P_A19 P_UNDEF
+#endif
+
+#ifndef P_A20
+#define P_A20 P_UNDEF
+#endif
+
+#ifndef P_A21
+#define P_A21 P_UNDEF
+#endif
+
+#ifndef P_A22
+#define P_A22 P_UNDEF
+#endif
+
+#ifndef P_A23
+#define P_A23 P_UNDEF
+#endif
+
+#ifndef P_A24
+#define P_A24 P_UNDEF
+#endif
+
+#ifndef P_A25
+#define P_A25 P_UNDEF
+#endif
+
+#ifndef P_NOR_CLK
+#define P_NOR_CLK P_UNDEF
+#endif
+
+#ifndef  P_TMRCLK
+#define  P_TMRCLK P_UNDEF
+#endif
+
+#ifndef P_AMC_ARDY_NOR_WAIT
+#define P_AMC_ARDY_NOR_WAIT P_UNDEF
+#endif
+
+#ifndef P_NAND_CE
+#define P_NAND_CE P_UNDEF
+#endif
+
+#ifndef P_NAND_RB
+#define P_NAND_RB P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DIOR
+#define P_ATAPI_DIOR P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DIOW
+#define P_ATAPI_DIOW P_UNDEF
+#endif
+
+#ifndef P_ATAPI_CS0
+#define P_ATAPI_CS0 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_CS1
+#define P_ATAPI_CS1 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DMACK
+#define P_ATAPI_DMACK P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DMARQ
+#define P_ATAPI_DMARQ P_UNDEF
+#endif
+
+#ifndef P_ATAPI_INTRQ
+#define P_ATAPI_INTRQ P_UNDEF
+#endif
+
+#ifndef P_ATAPI_IORDY
+#define P_ATAPI_IORDY P_UNDEF
+#endif
+
+#ifndef P_AMC_BR
+#define P_AMC_BR P_UNDEF
+#endif
+
+#ifndef P_AMC_BG
+#define P_AMC_BG P_UNDEF
+#endif
+
+#ifndef P_AMC_BGH
+#define P_AMC_BGH P_UNDEF
+#endif
+
+/* EMAC */
+
+#ifndef P_MII0_ETxD0
+#define P_MII0_ETxD0 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD1
+#define P_MII0_ETxD1 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD2
+#define P_MII0_ETxD2 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD3
+#define P_MII0_ETxD3 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxEN
+#define P_MII0_ETxEN P_UNDEF
+#endif
+
+#ifndef P_MII0_TxCLK
+#define P_MII0_TxCLK P_UNDEF
+#endif
+
+#ifndef P_MII0_PHYINT
+#define P_MII0_PHYINT P_UNDEF
+#endif
+
+#ifndef P_MII0_COL
+#define P_MII0_COL P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD0
+#define P_MII0_ERxD0 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD1
+#define P_MII0_ERxD1 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD2
+#define P_MII0_ERxD2 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD3
+#define P_MII0_ERxD3 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxDV
+#define P_MII0_ERxDV P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxCLK
+#define P_MII0_ERxCLK P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxER
+#define P_MII0_ERxER P_UNDEF
+#endif
+
+#ifndef P_MII0_CRS
+#define P_MII0_CRS P_UNDEF
+#endif
+
+#ifndef P_RMII0_REF_CLK
+#define P_RMII0_REF_CLK P_UNDEF
+#endif
+
+#ifndef P_RMII0_MDINT
+#define P_RMII0_MDINT P_UNDEF
+#endif
+
+#ifndef P_RMII0_CRS_DV
+#define P_RMII0_CRS_DV P_UNDEF
+#endif
+
+#ifndef P_MDC
+#define P_MDC P_UNDEF
+#endif
+
+#ifndef P_MDIO
+#define P_MDIO P_UNDEF
+#endif
+
+#endif				/* _PORTMUX_H_ */
diff --git a/include/asm-blackfin/processor.h b/include/asm-blackfin/processor.h
index 0336ff1..6bb3e0d 100644
--- a/include/asm-blackfin/processor.h
+++ b/include/asm-blackfin/processor.h
@@ -104,13 +104,13 @@
 #define cpu_relax()    	barrier()
 
 /* Get the Silicon Revision of the chip */
-static inline uint32_t bfin_revid(void)
+static inline __attribute_pure__ uint32_t bfin_revid(void)
 {
 	/* stored in the upper 4 bits */
 	return bfin_read_CHIPID() >> 28;
 }
 
-static inline uint32_t bfin_compiled_revid(void)
+static inline __attribute_pure__ uint32_t bfin_compiled_revid(void)
 {
 #if defined(CONFIG_BF_REV_0_0)
 	return 0;
@@ -124,6 +124,10 @@
 	return 4;
 #elif defined(CONFIG_BF_REV_0_5)
 	return 5;
+#elif defined(CONFIG_BF_REV_ANY)
+	return 0xffff;
+#else
+	return -1;
 #endif
 }
 
diff --git a/include/asm-blackfin/termbits.h b/include/asm-blackfin/termbits.h
index 2fd9dab..4eac38d 100644
--- a/include/asm-blackfin/termbits.h
+++ b/include/asm-blackfin/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];	/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;               /* input mode flags */
+	tcflag_t c_oflag;               /* output mode flags */
+	tcflag_t c_cflag;               /* control mode flags */
+	tcflag_t c_lflag;               /* local mode flags */
+	cc_t c_line;                    /* line discipline */
+	cc_t c_cc[NCCS];                /* control characters */
+	speed_t c_ispeed;               /* input speed */
+	speed_t c_ospeed;               /* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;               /* input mode flags */
 	tcflag_t c_oflag;               /* output mode flags */
diff --git a/include/asm-blackfin/trace.h b/include/asm-blackfin/trace.h
new file mode 100644
index 0000000..9c2474c
--- /dev/null
+++ b/include/asm-blackfin/trace.h
@@ -0,0 +1,52 @@
+/*
+ * Common header file for blackfin family of processors.
+ *
+ */
+
+#ifndef _BLACKFIN_TRACE_
+#define _BLACKFIN_TRACE_
+
+#ifndef __ASSEMBLY__
+/* Trace Macros for C files */
+
+#define trace_buffer_save(x) \
+        do { \
+                (x) = bfin_read_TBUFCTL(); \
+                bfin_write_TBUFCTL((x) & ~TBUFEN); \
+        } while (0)
+
+#define trace_buffer_restore(x) \
+        do { \
+                bfin_write_TBUFCTL((x));        \
+        } while (0)
+
+#else
+/* Trace Macros for Assembly files */
+
+#define TRACE_BUFFER_START(preg, dreg) trace_buffer_start(preg, dreg)
+#define TRACE_BUFFER_STOP(preg, dreg)  trace_buffer_stop(preg, dreg)
+
+#define trace_buffer_stop(preg, dreg)	\
+	preg.L = LO(TBUFCTL);		\
+	preg.H = HI(TBUFCTL);		\
+	dreg = 0x1;			\
+	[preg] = dreg;
+
+#define trace_buffer_start(preg, dreg) \
+	preg.L = LO(TBUFCTL);		\
+	preg.H = HI(TBUFCTL);		\
+	dreg = 0x13;			\
+	[preg] = dreg;
+
+#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
+# define DEBUG_START_HWTRACE(preg, dreg) trace_buffer_start(preg, dreg)
+# define DEBUG_STOP_HWTRACE(preg, dreg) trace_buffer_stop(preg, dreg)
+
+#else
+# define DEBUG_START_HWTRACE(preg, dreg)
+# define DEBUG_STOP_HWTRACE(preg, dreg)
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif				/* _BLACKFIN_TRACE_ */
diff --git a/include/asm-blackfin/uaccess.h b/include/asm-blackfin/uaccess.h
index bfcb679..2233f8f 100644
--- a/include/asm-blackfin/uaccess.h
+++ b/include/asm-blackfin/uaccess.h
@@ -14,7 +14,7 @@
 #include <linux/string.h>
 
 #include <asm/segment.h>
-#ifndef CONFIG_NO_ACCESS_CHECK
+#ifdef CONFIG_ACCESS_CHECK
 # include <asm/bfin-global.h>
 #endif
 
@@ -56,7 +56,7 @@
  * get_fs() == KERNEL_DS, checking is bypassed.
  */
 
-#ifdef CONFIG_NO_ACCESS_CHECK
+#ifndef CONFIG_ACCESS_CHECK
 static inline int _access_ok(unsigned long addr, unsigned long size) { return 1; }
 #else
 #ifdef CONFIG_ACCESS_OK_L1
diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h
index 4df8790..0df9f2d 100644
--- a/include/asm-blackfin/unistd.h
+++ b/include/asm-blackfin/unistd.h
@@ -369,7 +369,6 @@
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#endif
 
 /*
  * "Conditional" syscalls
@@ -379,4 +378,6 @@
  */
 #define cond_syscall(x) asm(".weak\t_" #x "\n\t.set\t_" #x ",_sys_ni_syscall");
 
+#endif	/* __KERNEL__ */
+
 #endif				/* __ASM_BFIN_UNISTD_H */
diff --git a/include/asm-cris/fb.h b/include/asm-cris/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-cris/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-cris/ioctls.h b/include/asm-cris/ioctls.h
index 97787c3..4f4e525 100644
--- a/include/asm-cris/ioctls.h
+++ b/include/asm-cris/ioctls.h
@@ -48,6 +48,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index 9f13c32..0648e31 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -20,7 +20,8 @@
 #define clear_user_page(page, vaddr, pg)    clear_page(page)
 #define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-cris/pci.h b/include/asm-cris/pci.h
index b2ac8a3..730ce40 100644
--- a/include/asm-cris/pci.h
+++ b/include/asm-cris/pci.h
@@ -52,47 +52,11 @@
 #define pci_unmap_len(PTR, LEN_NAME)		(0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)	(1)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
-	return ((dma64_addr_t) page_to_phys(page) +
-		(dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	return pfn_to_page(dma_addr >> PAGE_SHIFT);
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 			       enum pci_mmap_state mmap_state, int write_combine);
 
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
index c94a710..417f711 100644
--- a/include/asm-cris/pgtable.h
+++ b/include/asm-cris/pgtable.h
@@ -111,9 +111,7 @@
  * Undefined behaviour if not..
  */
 
-static inline int pte_read(pte_t pte)           { return pte_val(pte) & _PAGE_READ; }
 static inline int pte_write(pte_t pte)          { return pte_val(pte) & _PAGE_WRITE; }
-static inline int pte_exec(pte_t pte)           { return pte_val(pte) & _PAGE_READ; }
 static inline int pte_dirty(pte_t pte)          { return pte_val(pte) & _PAGE_MODIFIED; }
 static inline int pte_young(pte_t pte)          { return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)           { return pte_val(pte) & _PAGE_FILE; }
@@ -124,18 +122,6 @@
         return pte;
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-        pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-	return pte;
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{
-        pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-	return pte;
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); 
@@ -156,22 +142,6 @@
         return pte;
 }
 
-static inline pte_t pte_mkread(pte_t pte)
-{
-        pte_val(pte) |= _PAGE_READ;
-        if (pte_val(pte) & _PAGE_ACCESSED)
-                pte_val(pte) |= _PAGE_SILENT_READ;
-        return pte;
-}
-
-static inline pte_t pte_mkexec(pte_t pte)
-{
-        pte_val(pte) |= _PAGE_READ;
-        if (pte_val(pte) & _PAGE_ACCESSED)
-                pte_val(pte) |= _PAGE_SILENT_READ;
-        return pte;
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 {
         pte_val(pte) |= _PAGE_MODIFIED;
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index 8d8cec2..71c1b36 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -19,6 +19,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
@@ -155,6 +166,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define  BOTHER  0010000
 #define  B57600  0010001
 #define  B115200 0010002
 #define  B230400 0010003
diff --git a/include/asm-cris/termios.h b/include/asm-cris/termios.h
index c9dbd4d..b0124e6c 100644
--- a/include/asm-cris/termios.h
+++ b/include/asm-cris/termios.h
@@ -81,8 +81,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-frv/fb.h b/include/asm-frv/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-frv/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-frv/pci.h b/include/asm-frv/pci.h
index f35a451..585d9b4 100644
--- a/include/asm-frv/pci.h
+++ b/include/asm-frv/pci.h
@@ -22,10 +22,6 @@
 
 #define pcibios_assign_all_busses()	0
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 extern void pcibios_set_master(struct pci_dev *dev);
 
 extern void pcibios_penalize_isa_irq(int irq);
@@ -44,9 +40,6 @@
 extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
 				void *vaddr, dma_addr_t dma_handle);
 
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)	(1)
-
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)	(0)
 
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index 2687c77..147e995 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
-struct mm_struct;
+#include <linux/sched.h>
 struct vm_area_struct;
 #endif
 
@@ -377,30 +377,17 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)		{ return !((pte).pte & _PAGE_SUPER); }
-static inline int pte_exec(pte_t pte)		{ return !((pte).pte & _PAGE_SUPER); }
 static inline int pte_dirty(pte_t pte)		{ return (pte).pte & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return (pte).pte & _PAGE_ACCESSED; }
 static inline int pte_write(pte_t pte)		{ return !((pte).pte & _PAGE_WP); }
 
-static inline pte_t pte_rdprotect(pte_t pte)	{ (pte).pte |= _PAGE_SUPER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ (pte).pte |= _PAGE_SUPER; return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte &= ~_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte |= _PAGE_WP; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ (pte).pte &= ~_PAGE_SUPER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ (pte).pte &= ~_PAGE_SUPER; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte &= ~_PAGE_WP; return pte; }
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-	int i = test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
-	asm volatile("dcf %M0" :: "U"(*ptep));
-	return i;
-}
-
 static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	int i = test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
@@ -510,7 +497,6 @@
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index be303b3..6931af5 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -12,6 +12,7 @@
 #ifndef _ASM_SYSTEM_H
 #define _ASM_SYSTEM_H
 
+#include <linux/types.h>
 #include <linux/linkage.h>
 
 struct thread_struct;
diff --git a/include/asm-frv/termbits.h b/include/asm-frv/termbits.h
index 2d6d389..74851b4 100644
--- a/include/asm-frv/termbits.h
+++ b/include/asm-frv/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-frv/uaccess.h b/include/asm-frv/uaccess.h
index 3d90e10..53650c9 100644
--- a/include/asm-frv/uaccess.h
+++ b/include/asm-frv/uaccess.h
@@ -277,6 +277,8 @@
 
 #endif
 
+#define __clear_user clear_user
+
 static inline unsigned long __must_check
 __copy_to_user(void __user *to, const void *from, unsigned long n)
 {
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index d0ea678..7306c71 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -326,10 +326,14 @@
 #define __NR_move_pages		317
 #define __NR_getcpu		318
 #define __NR_epoll_pwait	319
+#define __NR_utimensat		320
+#define __NR_signalfd		321
+#define __NR_timerfd		322
+#define __NR_eventfd		323
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 320
+#define NR_syscalls 324
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 /* #define __ARCH_WANT_OLD_READDIR */
diff --git a/include/asm-generic/bitops/sched.h b/include/asm-generic/bitops/sched.h
index 815bb01..604fab7 100644
--- a/include/asm-generic/bitops/sched.h
+++ b/include/asm-generic/bitops/sched.h
@@ -6,28 +6,23 @@
 
 /*
  * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
+ * way of searching a 100-bit bitmap.  It's guaranteed that at least
+ * one of the 100 bits is cleared.
  */
 static inline int sched_find_first_bit(const unsigned long *b)
 {
 #if BITS_PER_LONG == 64
-	if (unlikely(b[0]))
+	if (b[0])
 		return __ffs(b[0]);
-	if (likely(b[1]))
-		return __ffs(b[1]) + 64;
-	return __ffs(b[2]) + 128;
+	return __ffs(b[1]) + 64;
 #elif BITS_PER_LONG == 32
-	if (unlikely(b[0]))
+	if (b[0])
 		return __ffs(b[0]);
-	if (unlikely(b[1]))
+	if (b[1])
 		return __ffs(b[1]) + 32;
-	if (unlikely(b[2]))
+	if (b[2])
 		return __ffs(b[2]) + 64;
-	if (b[3])
-		return __ffs(b[3]) + 96;
-	return __ffs(b[4]) + 128;
+	return __ffs(b[3]) + 96;
 #else
 #error BITS_PER_LONG not defined
 #endif
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 14fae1f..344e309 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -28,14 +28,14 @@
 #endif
 
 #ifndef HAVE_ARCH_BUG_ON
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
 #endif
 
 #ifndef HAVE_ARCH_WARN_ON
 #define WARN_ON(condition) ({						\
 	typeof(condition) __ret_warn_on = (condition);			\
 	if (unlikely(__ret_warn_on)) {					\
-		printk("BUG: at %s:%d %s()\n", __FILE__,		\
+		printk("WARNING: at %s:%d %s()\n", __FILE__,		\
 			__LINE__, __FUNCTION__);			\
 		dump_stack();						\
 	}								\
diff --git a/include/asm-generic/dma-mapping-broken.h b/include/asm-generic/dma-mapping-broken.h
index 29413d3..e2468f8 100644
--- a/include/asm-generic/dma-mapping-broken.h
+++ b/include/asm-generic/dma-mapping-broken.h
@@ -1,24 +1,82 @@
 #ifndef _ASM_GENERIC_DMA_MAPPING_H
 #define _ASM_GENERIC_DMA_MAPPING_H
 
-/* This is used for archs that do not support DMA */
+/* define the dma api to allow compilation but not linking of
+ * dma dependent code.  Code that depends on the dma-mapping
+ * API needs to set 'depends on HAS_DMA' in its Kconfig
+ */
 
-static inline void *
+struct scatterlist;
+
+extern void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   gfp_t flag)
-{
-	BUG();
-	return NULL;
-}
+		   gfp_t flag);
 
-static inline void
+extern void
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
-		    dma_addr_t dma_handle)
-{
-	BUG();
-}
+		    dma_addr_t dma_handle);
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+extern dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+	       enum dma_data_direction direction);
+
+extern void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction);
+
+extern int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction);
+
+extern void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction);
+
+extern dma_addr_t
+dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+	     size_t size, enum dma_data_direction direction);
+
+extern void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction);
+
+extern void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+			enum dma_data_direction direction);
+
+extern void
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			      unsigned long offset, size_t size,
+			      enum dma_data_direction direction);
+
+extern void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+		    enum dma_data_direction direction);
+
+#define dma_sync_single_for_device dma_sync_single_for_cpu
+#define dma_sync_single_range_for_device dma_sync_single_range_for_cpu
+#define dma_sync_sg_for_device dma_sync_sg_for_cpu
+
+extern int
+dma_mapping_error(dma_addr_t dma_addr);
+
+extern int
+dma_supported(struct device *dev, u64 mask);
+
+extern int
+dma_set_mask(struct device *dev, u64 mask);
+
+extern int
+dma_get_cache_alignment(void);
+
+extern int
+dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+
+extern void
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+	       enum dma_data_direction direction);
+
 #endif /* _ASM_GENERIC_DMA_MAPPING_H */
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index c154b9d..b847741 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -48,6 +48,9 @@
 #ifndef O_NOATIME
 #define O_NOATIME	01000000
 #endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC	02000000	/* set close_on_exec */
+#endif
 #ifndef O_NDELAY
 #define O_NDELAY	O_NONBLOCK
 #endif
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index dc8f99e..f605e8d 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -3,37 +3,25 @@
 
 #ifndef __ASSEMBLY__
 
-#ifndef __HAVE_ARCH_PTEP_ESTABLISH
-/*
- * Establish a new mapping:
- *  - flush the old one
- *  - update the page tables
- *  - inform the TLB about the new one
- *
- * We hold the mm semaphore for reading, and the pte lock.
- *
- * Note: the old pte is known to not be writable, so we don't need to
- * worry about dirty bits etc getting lost.
- */
-#define ptep_establish(__vma, __address, __ptep, __entry)		\
-do {				  					\
-	set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry);	\
-	flush_tlb_page(__vma, __address);				\
-} while (0)
-#endif
-
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 /*
  * Largely same as above, but only sets the access flags (dirty,
  * accessed, and writable). Furthermore, we know it always gets set
  * to a "more permissive" setting, which allows most architectures
- * to optimize this.
+ * to optimize this. We return whether the PTE actually changed, which
+ * in turn instructs the caller to do things like update__mmu_cache.
+ * This used to be done in the caller, but sparc needs minor faults to
+ * force that call on sun4c so we changed this macro slightly
  */
 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-do {				  					  \
-	set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry);	  \
-	flush_tlb_page(__vma, __address);				  \
-} while (0)
+({									  \
+	int __changed = !pte_same(*(__ptep), __entry);			  \
+	if (__changed) {						  \
+		set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+		flush_tlb_page(__vma, __address);			  \
+	}								  \
+	__changed;							  \
+})
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -61,31 +49,6 @@
 })
 #endif
 
-#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(__vma, __address, __ptep)		\
-({									\
-	pte_t __pte = *__ptep;						\
-	int r = 1;							\
-	if (!pte_dirty(__pte))						\
-		r = 0;							\
-	else								\
-		set_pte_at((__vma)->vm_mm, (__address), (__ptep),	\
-			   pte_mkclean(__pte));				\
-	r;								\
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(__vma, __address, __ptep)		\
-({									\
-	int __dirty;							\
-	__dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep);	\
-	if (__dirty)							\
-		flush_tlb_page(__vma, __address);			\
-	__dirty;							\
-})
-#endif
-
 #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define ptep_get_and_clear(__mm, __address, __ptep)			\
 ({									\
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index 09ec447..16a466e 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -18,7 +18,8 @@
 #define get_unaligned(ptr) \
 	__get_unaligned((ptr), sizeof(*(ptr)))
 #define put_unaligned(x,ptr) \
-	__put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
+	((void)sizeof(*(ptr)=(x)),\
+	__put_unaligned((__force __u64)(x), (ptr), sizeof(*(ptr))))
 
 /*
  * This function doesn't actually exist.  The idea is that when
@@ -95,21 +96,21 @@
 	default:				\
 		bad_unaligned_access_length();	\
 	};					\
-	(__typeof__(*(ptr)))val;		\
+	(__force __typeof__(*(ptr)))val;	\
 })
 
 #define __put_unaligned(val, ptr, size)		\
-do {						\
+({						\
 	void *__gu_p = ptr;			\
 	switch (size) {				\
 	case 1:					\
-		*(__u8 *)__gu_p = val;		\
+		*(__u8 *)__gu_p = (__force __u8)val;		\
 	        break;				\
 	case 2:					\
-		__ustw(val, __gu_p);		\
+		__ustw((__force __u16)val, __gu_p);		\
 		break;				\
 	case 4:					\
-		__ustl(val, __gu_p);		\
+		__ustl((__force __u32)val, __gu_p);		\
 		break;				\
 	case 8:					\
 		__ustq(val, __gu_p);		\
@@ -117,6 +118,7 @@
 	default:				\
 	    	bad_unaligned_access_length();	\
 	};					\
-} while(0)
+	(void)0;				\
+})
 
 #endif /* _ASM_GENERIC_UNALIGNED_H */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index f3806a74..84155eb 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -9,8 +9,13 @@
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
 
-#define RODATA								\
-	. = ALIGN(4096);						\
+/* .data section */
+#define DATA_DATA							\
+	*(.data)							\
+	*(.data.init.refok)
+
+#define RO_DATA(align)							\
+	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata) *(.rodata.*)					\
@@ -130,7 +135,11 @@
 		VMLINUX_SYMBOL(__end_rodata) = .;			\
 	}								\
 									\
-	. = ALIGN(4096);
+	. = ALIGN((align));
+
+/* RODATA provided for backward compatibility.
+ * All archs are supposed to use RO_DATA() */
+#define RODATA RO_DATA(4096)
 
 #define SECURITY_INIT							\
 	.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
@@ -139,6 +148,13 @@
 		VMLINUX_SYMBOL(__security_initcall_end) = .;		\
 	}
 
+/* .text section. Map to function alignment to avoid address changes
+ * during second ld run in second ld pass when generating System.map */
+#define TEXT_TEXT							\
+		ALIGN_FUNCTION();					\
+		*(.text)						\
+		*(.text.init.refok)
+
 /* sched.text is aling to function alignment to secure we have same
  * address even at second ld pass when generating System.map */
 #define SCHED_TEXT							\
diff --git a/include/asm-h8300/dma-mapping.h b/include/asm-h8300/dma-mapping.h
deleted file mode 100644
index d00e400..0000000
--- a/include/asm-h8300/dma-mapping.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/dma-mapping-broken.h>
diff --git a/include/asm-h8300/fb.h b/include/asm-h8300/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-h8300/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-h8300/ioctls.h b/include/asm-h8300/ioctls.h
index ac20457..98a53d0 100644
--- a/include/asm-h8300/ioctls.h
+++ b/include/asm-h8300/ioctls.h
@@ -47,6 +47,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index 3b4f290..c8cc81a 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -22,7 +22,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-h8300/pci.h b/include/asm-h8300/pci.h
index 0c771b0..97389b3 100644
--- a/include/asm-h8300/pci.h
+++ b/include/asm-h8300/pci.h
@@ -22,8 +22,4 @@
 
 #define PCI_DMA_BUS_IS_PHYS	(1)
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* _ASM_H8300_PCI_H */
diff --git a/include/asm-h8300/processor.h b/include/asm-h8300/processor.h
index 99b664a..49fc886 100644
--- a/include/asm-h8300/processor.h
+++ b/include/asm-h8300/processor.h
@@ -78,7 +78,7 @@
 do {							        \
 	set_fs(USER_DS);           /* reads from user space */  \
   	(_regs)->pc = (_pc);				        \
-	(_regs)->ccr &= 0x00;	   /* clear kernel flag */      \
+	(_regs)->ccr = 0x00;	   /* clear all flags */        \
 	(_regs)->er5 = current->mm->start_data;	/* GOT base */  \
 	wrusp((unsigned long)(_usp) - sizeof(unsigned long)*3);	\
 } while(0)
diff --git a/include/asm-h8300/termbits.h b/include/asm-h8300/termbits.h
index 6a1f4d3..31eca81 100644
--- a/include/asm-h8300/termbits.h
+++ b/include/asm-h8300/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
@@ -130,6 +141,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -145,10 +157,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define IBSHIFT	  16			/* shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-h8300/termios.h b/include/asm-h8300/termios.h
index fb2925d..70eea64 100644
--- a/include/asm-h8300/termios.h
+++ b/include/asm-h8300/termios.h
@@ -82,8 +82,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h
index 45f09dc..aee4009 100644
--- a/include/asm-h8300/thread_info.h
+++ b/include/asm-h8300/thread_info.h
@@ -92,6 +92,7 @@
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -99,6 +100,7 @@
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
index 0baa2f8..437aac8 100644
--- a/include/asm-i386/atomic.h
+++ b/include/asm-i386/atomic.h
@@ -182,7 +182,7 @@
 	int __i;
 #ifdef CONFIG_M386
 	unsigned long flags;
-	if(unlikely(boot_cpu_data.x86==3))
+	if(unlikely(boot_cpu_data.x86 <= 3))
 		goto no_xadd;
 #endif
 	/* Modern 486+ processor */
diff --git a/include/asm-i386/boot.h b/include/asm-i386/boot.h
index bd024ab..ed8affb 100644
--- a/include/asm-i386/boot.h
+++ b/include/asm-i386/boot.h
@@ -1,5 +1,5 @@
-#ifndef _LINUX_BOOT_H
-#define _LINUX_BOOT_H
+#ifndef _ASM_BOOT_H
+#define _ASM_BOOT_H
 
 /* Don't touch these, unless you really know what you're doing. */
 #define DEF_INITSEG	0x9000
@@ -17,4 +17,4 @@
 				+ (CONFIG_PHYSICAL_ALIGN - 1)) \
 				& ~(CONFIG_PHYSICAL_ALIGN - 1))
 
-#endif /* _LINUX_BOOT_H */
+#endif /* _ASM_BOOT_H */
diff --git a/include/asm-i386/bootparam.h b/include/asm-i386/bootparam.h
new file mode 100644
index 0000000..427d865
--- /dev/null
+++ b/include/asm-i386/bootparam.h
@@ -0,0 +1,85 @@
+#ifndef _ASM_BOOTPARAM_H
+#define _ASM_BOOTPARAM_H
+
+#include <linux/types.h>
+#include <linux/screen_info.h>
+#include <linux/apm_bios.h>
+#include <asm/e820.h>
+#include <linux/edd.h>
+#include <video/edid.h>
+
+struct setup_header {
+	u8	setup_sects;
+	u16	root_flags;
+	u32	syssize;
+	u16	ram_size;
+	u16	vid_mode;
+	u16	root_dev;
+	u16	boot_flag;
+	u16	jump;
+	u32	header;
+	u16	version;
+	u32	realmode_swtch;
+	u16	start_sys;
+	u16	kernel_version;
+	u8	type_of_loader;
+	u8	loadflags;
+#define LOADED_HIGH	0x01
+#define CAN_USE_HEAP	0x80
+	u16	setup_move_size;
+	u32	code32_start;
+	u32	ramdisk_image;
+	u32	ramdisk_size;
+	u32	bootsect_kludge;
+	u16	heap_end_ptr;
+	u16	_pad1;
+	u32	cmd_line_ptr;
+	u32	initrd_addr_max;
+	u32	kernel_alignment;
+	u8	relocatable_kernel;
+} __attribute__((packed));
+
+struct sys_desc_table {
+	u16 length;
+	u8  table[14];
+};
+
+struct efi_info {
+	u32 _pad1;
+	u32 efi_systab;
+	u32 efi_memdesc_size;
+	u32 efi_memdec_version;
+	u32 efi_memmap;
+	u32 fi_memmap_size;
+	u32 _pad2[2];
+};
+
+/* The so-called "zeropage" */
+struct boot_params {
+	struct screen_info screen_info;			/* 0x000 */
+	struct apm_bios_info apm_bios_info;		/* 0x040 */
+	u8  _pad2[12];					/* 0x054 */
+	u32 speedstep_info[4];				/* 0x060 */
+	u8  _pad3[16];					/* 0x070 */
+	u8  hd0_info[16];	/* obsolete! */		/* 0x080 */
+	u8  hd1_info[16];	/* obsolete! */		/* 0x090 */
+	struct sys_desc_table sys_desc_table;		/* 0x0a0 */
+	u8  _pad4[144];					/* 0x0b0 */
+	struct edid_info edid_info;			/* 0x140 */
+	struct efi_info efi_info;			/* 0x1c0 */
+	u32 alt_mem_k;					/* 0x1e0 */
+	u32 scratch;		/* Scratch field! */	/* 0x1e4 */
+	u8  e820_entries;				/* 0x1e8 */
+	u8  eddbuf_entries;				/* 0x1e9 */
+	u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
+	u8  _pad6[6];					/* 0x1eb */
+	struct setup_header hdr;    /* setup header */	/* 0x1f1 */
+	u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
+	u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];	/* 0x290 */
+	struct e820entry e820_map[E820MAX];		/* 0x2d0 */
+	u8  _pad8[48];					/* 0xcd0 */
+	struct edd_info eddbuf[EDDMAXNR];		/* 0xd00 */
+	u8  _pad9[276];					/* 0xeec */
+} __attribute__((packed));
+
+#endif /* _ASM_BOOTPARAM_H */
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index f514e90..c961c03 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -12,7 +12,7 @@
 #endif
 #include <asm/required-features.h>
 
-#define NCAPINTS	7	/* N 32-bit words worth of info */
+#define NCAPINTS	8	/* N 32-bit words worth of info */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
 #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
@@ -81,6 +81,7 @@
 #define X86_FEATURE_BTS		(3*32+13)  /* Branch Trace Store */
 #define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14) /* lapic timer broken in C1 */
 #define X86_FEATURE_SYNC_RDTSC	(3*32+15)  /* RDTSC synchronizes the CPU */
+#define X86_FEATURE_REP_GOOD   (3*32+16) /* rep microcode works well on this CPU */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
@@ -108,11 +109,24 @@
 #define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
 #define X86_FEATURE_CMP_LEGACY	(6*32+ 1) /* If yes HyperThreading not valid */
 
-#define cpu_has(c, bit)					\
-	((__builtin_constant_p(bit) && (bit) < 32 && 	\
-		(1UL << (bit)) & REQUIRED_MASK1) ?	\
-		1 : 					\
-	test_bit(bit, (c)->x86_capability))
+/*
+ * Auxiliary flags: Linux defined - For features scattered in various
+ * CPUID levels like 0x6, 0xA etc
+ */
+#define X86_FEATURE_IDA		(7*32+ 0) /* Intel Dynamic Acceleration */
+
+#define cpu_has(c, bit)							\
+	(__builtin_constant_p(bit) &&					\
+	 ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) ||	\
+	   (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) ||	\
+	   (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) ||	\
+	   (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) ||	\
+	   (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) ||	\
+	   (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) ||	\
+	   (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) ||	\
+	   (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) )	\
+	  ? 1 :								\
+	  test_bit(bit, (c)->x86_capability))
 #define boot_cpu_has(bit)	cpu_has(&boot_cpu_data, bit)
 
 #define cpu_has_fpu		boot_cpu_has(X86_FEATURE_FPU)
diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h
index 183eebe..f1d72d1 100644
--- a/include/asm-i386/dma-mapping.h
+++ b/include/asm-i386/dma-mapping.h
@@ -123,6 +123,8 @@
 	return 0;
 }
 
+extern int forbid_dac;
+
 static inline int
 dma_supported(struct device *dev, u64 mask)
 {
@@ -134,6 +136,10 @@
         if(mask < 0x00ffffff)
                 return 0;
 
+	/* Work around chipset bugs */
+	if (forbid_dac > 0 && mask > 0xffffffffULL)
+		return 0;
+
 	return 1;
 }
 
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h
index 096a2a8..c03290c 100644
--- a/include/asm-i386/e820.h
+++ b/include/asm-i386/e820.h
@@ -25,13 +25,15 @@
 
 #ifndef __ASSEMBLY__
 
+struct e820entry {
+	u64 addr;	/* start of memory segment */
+	u64 size;	/* size of memory segment */
+	u32 type;	/* type of memory segment */
+} __attribute__((packed));
+
 struct e820map {
-    int nr_map;
-    struct e820entry {
-	unsigned long long addr;	/* start of memory segment */
-	unsigned long long size;	/* size of memory segment */
-	unsigned long type;		/* type of memory segment */
-    } map[E820MAX];
+	u32 nr_map;
+	struct e820entry map[E820MAX];
 };
 
 extern struct e820map e820;
diff --git a/include/asm-i386/fb.h b/include/asm-i386/fb.h
new file mode 100644
index 0000000..d1c6297
--- /dev/null
+++ b/include/asm-i386/fb.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+extern int fb_is_primary_device(struct fb_info *info);
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	if (boot_cpu_data.x86 > 3)
+		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 80ea052..249e753 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -54,6 +54,8 @@
 enum fixed_addresses {
 	FIX_HOLE,
 	FIX_VDSO,
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
diff --git a/include/asm-i386/ide.h b/include/asm-i386/ide.h
index 0fc240c..e7817a3 100644
--- a/include/asm-i386/ide.h
+++ b/include/asm-i386/ide.h
@@ -40,14 +40,13 @@
 
 static __inline__ unsigned long ide_default_io_base(int index)
 {
-	struct pci_dev *pdev;
 	/*
 	 *	If PCI is present then it is not safe to poke around
 	 *	the other legacy IDE ports. Only 0x1f0 and 0x170 are
 	 *	defined compatibility mode ports for PCI. A user can 
 	 *	override this using ide= but we must default safe.
 	 */
-	if ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL)) == NULL) {
+	if (no_pci_devices()) {
 		switch(index) {
 			case 2: return 0x1e8;
 			case 3: return 0x168;
@@ -55,7 +54,6 @@
 			case 5: return 0x160;
 		}
 	}
-	pci_dev_put(pdev);
 	switch (index) {
 		case 0:	return 0x1f0;
 		case 1:	return 0x170;
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index e797586..7b65b5b 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -129,6 +129,7 @@
  */
 extern void *bt_ioremap(unsigned long offset, unsigned long size);
 extern void bt_iounmap(void *addr, unsigned long size);
+extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
 /* Use early IO mappings for DMI because it's initialized early */
 #define dmi_ioremap bt_ioremap
diff --git a/include/asm-i386/local.h b/include/asm-i386/local.h
index e13d3e9..6e85975 100644
--- a/include/asm-i386/local.h
+++ b/include/asm-i386/local.h
@@ -135,7 +135,7 @@
 	long __i;
 #ifdef CONFIG_M386
 	unsigned long flags;
-	if(unlikely(boot_cpu_data.x86==3))
+	if(unlikely(boot_cpu_data.x86 <= 3))
 		goto no_xadd;
 #endif
 	/* Modern 486+ processor */
diff --git a/include/asm-i386/mach-es7000/mach_apic.h b/include/asm-i386/mach-es7000/mach_apic.h
index 2d97892..caec64b 100644
--- a/include/asm-i386/mach-es7000/mach_apic.h
+++ b/include/asm-i386/mach-es7000/mach_apic.h
@@ -73,6 +73,10 @@
 	apic_write_around(APIC_LDR, val);
 }
 
+#ifndef CONFIG_X86_GENERICARCH
+extern void enable_apic_mode(void);
+#endif
+
 extern int apic_version [MAX_APICS];
 static inline void setup_apic_routing(void)
 {
diff --git a/include/asm-i386/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h
index b9fb784..8aa1054 100644
--- a/include/asm-i386/mach-es7000/mach_mpparse.h
+++ b/include/asm-i386/mach-es7000/mach_mpparse.h
@@ -18,6 +18,12 @@
 extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
 extern void setup_unisys(void);
 
+#ifndef CONFIG_X86_GENERICARCH
+extern int acpi_madt_oem_check(char *oem_id, char *oem_table_id);
+extern int mps_oem_check(struct mp_config_table *mpc, char *oem,
+				char *productid);
+#endif
+
 #ifdef CONFIG_ACPI
 
 static inline int es7000_check_dsdt(void)
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 818ac8b..99cf5d3 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -34,7 +34,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-i386/paravirt.h b/include/asm-i386/paravirt.h
index d7a0512..7f846a7 100644
--- a/include/asm-i386/paravirt.h
+++ b/include/asm-i386/paravirt.h
@@ -539,7 +539,7 @@
 	val = paravirt_read_msr(msr, &_err);	\
 } while(0)
 
-#define wrmsrl(msr,val)		((void)paravirt_write_msr(msr, val, 0))
+#define wrmsrl(msr,val)		wrmsr(msr, (u32)((u64)(val)), ((u64)(val))>>32)
 #define wrmsr_safe(msr,a,b)	paravirt_write_msr(msr, a, b)
 
 /* rdmsr with exception handling */
diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h
index 64b6d0b..392d3fe 100644
--- a/include/asm-i386/pci.h
+++ b/include/asm-i386/pci.h
@@ -56,48 +56,11 @@
 #define pci_unmap_len(PTR, LEN_NAME)		(0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)	(1)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
-	return ((dma64_addr_t) page_to_phys(page) +
-		(dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	return pfn_to_page(dma_addr >> PAGE_SHIFT);
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-	flush_write_buffers();
-}
-
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 			       enum pci_mmap_state mmap_state, int write_combine);
 
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index a50fd17..84b03cf 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -57,14 +57,6 @@
 #define pfn_pmd(pfn, prot)	__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
 /*
- * All present user pages are user-executable:
- */
-static inline int pte_exec(pte_t pte)
-{
-	return pte_user(pte);
-}
-
-/*
  * All present pages are kernel-executable:
  */
 static inline int pte_exec_kernel(pte_t pte)
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index eb0f1d7..948a334 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -20,26 +20,11 @@
 #define pud_present(pud)			1
 
 /*
- * Is the pte executable?
- */
-static inline int pte_x(pte_t pte)
-{
-	return !(pte_val(pte) & _PAGE_NX);
-}
-
-/*
- * All present user-pages with !NX bit are user-executable:
- */
-static inline int pte_exec(pte_t pte)
-{
-	return pte_user(pte) && pte_x(pte);
-}
-/*
  * All present pages with !NX bit are kernel-executable:
  */
 static inline int pte_exec_kernel(pte_t pte)
 {
-	return pte_x(pte);
+	return !(pte_val(pte) & _PAGE_NX);
 }
 
 /* Rules for using set_pte: the pte being assigned *must* be
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 2394589..c7fefa6 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -79,7 +79,7 @@
  * area for the same reason. ;)
  */
 #define VMALLOC_OFFSET	(8*1024*1024)
-#define VMALLOC_START	(((unsigned long) high_memory + vmalloc_earlyreserve + \
+#define VMALLOC_START	(((unsigned long) high_memory + \
 			2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
 #ifdef CONFIG_HIGHMEM
 # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
@@ -218,8 +218,6 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_user(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
-static inline int pte_read(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
 static inline int pte_dirty(pte_t pte)		{ return (pte).pte_low & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return (pte).pte_low & _PAGE_ACCESSED; }
 static inline int pte_write(pte_t pte)		{ return (pte).pte_low & _PAGE_RW; }
@@ -230,13 +228,9 @@
  */
 static inline int pte_file(pte_t pte)		{ return (pte).pte_low & _PAGE_FILE; }
 
-static inline pte_t pte_rdprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte_low &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte_low &= ~_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_RW; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte_low |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
@@ -285,53 +279,25 @@
  */
 #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
-do {									\
-	if (dirty) {							\
+({									\
+	int __changed = !pte_same(*(ptep), entry);			\
+	if (__changed && dirty) {					\
 		(ptep)->pte_low = (entry).pte_low;			\
 		pte_update_defer((vma)->vm_mm, (address), (ptep));	\
 		flush_tlb_page(vma, address);				\
 	}								\
-} while (0)
-
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(vma, addr, ptep) ({			\
-	int ret = 0;							\
-	if (pte_dirty(*ptep))						\
-		ret = test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); \
-	if (ret)							\
-		pte_update_defer(vma->vm_mm, addr, ptep);		\
-	ret;								\
+	__changed;							\
 })
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define ptep_test_and_clear_young(vma, addr, ptep) ({			\
-	int ret = 0;							\
-	if (pte_young(*ptep))						\
-		ret = test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); \
-	if (ret)							\
-		pte_update_defer(vma->vm_mm, addr, ptep);		\
-	ret;								\
-})
-
-/*
- * Rules for using ptep_establish: the pte MUST be a user pte, and
- * must be a present->present transition.
- */
-#define __HAVE_ARCH_PTEP_ESTABLISH
-#define ptep_establish(vma, address, ptep, pteval)			\
-do {									\
-	set_pte_present((vma)->vm_mm, address, ptep, pteval);		\
-	flush_tlb_page(vma, address);					\
-} while (0)
-
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(vma, address, ptep)			\
-({									\
-	int __dirty;							\
-	__dirty = ptep_test_and_clear_dirty((vma), (address), (ptep));	\
-	if (__dirty)							\
-		flush_tlb_page(vma, address);				\
-	__dirty;							\
+	int __ret = 0;							\
+	if (pte_young(*(ptep)))						\
+		__ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,		\
+						&(ptep)->pte_low);	\
+	if (__ret)							\
+		pte_update((vma)->vm_mm, addr, ptep);			\
+	__ret;								\
 })
 
 #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 338668b..422cffe 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -119,6 +119,7 @@
 extern void identify_boot_cpu(void);
 extern void identify_secondary_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
+extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern unsigned short num_cache_leaves;
 
@@ -227,6 +228,10 @@
 
 #define HAVE_ARCH_PICK_MMAP_LAYOUT
 
+extern void hard_disable_TSC(void);
+extern void disable_TSC(void);
+extern void hard_enable_TSC(void);
+
 /*
  * Size of io_bitmap.
  */
diff --git a/include/asm-i386/required-features.h b/include/asm-i386/required-features.h
index 9db866c..65848a0 100644
--- a/include/asm-i386/required-features.h
+++ b/include/asm-i386/required-features.h
@@ -3,32 +3,53 @@
 
 /* Define minimum CPUID feature set for kernel These bits are checked
    really early to actually display a visible error message before the
-   kernel dies.  Only add word 0 bits here
+   kernel dies.  Make sure to assign features to the proper mask!
 
    Some requirements that are not in CPUID yet are also in the
-   CONFIG_X86_MINIMUM_CPU mode which is checked too.
+   CONFIG_X86_MINIMUM_CPU_FAMILY which is checked too.
 
    The real information is in arch/i386/Kconfig.cpu, this just converts
    the CONFIGs into a bitmask */
 
-#ifdef CONFIG_X86_PAE
-#define NEED_PAE	(1<<X86_FEATURE_PAE)
+#ifndef CONFIG_MATH_EMULATION
+# define NEED_FPU	(1<<(X86_FEATURE_FPU & 31))
 #else
-#define NEED_PAE	0
+# define NEED_FPU	0
+#endif
+
+#ifdef CONFIG_X86_PAE
+# define NEED_PAE	(1<<(X86_FEATURE_PAE & 31))
+#else
+# define NEED_PAE	0
 #endif
 
 #ifdef CONFIG_X86_CMOV
-#define NEED_CMOV	(1<<X86_FEATURE_CMOV)
+# define NEED_CMOV	(1<<(X86_FEATURE_CMOV & 31))
 #else
-#define NEED_CMOV	0
+# define NEED_CMOV	0
 #endif
 
 #ifdef CONFIG_X86_CMPXCHG64
-#define NEED_CMPXCHG64  (1<<X86_FEATURE_CX8)
+# define NEED_CX8	(1<<(X86_FEATURE_CX8 & 31))
 #else
-#define NEED_CMPXCHG64  0
+# define NEED_CX8	0
 #endif
 
-#define REQUIRED_MASK1	(NEED_PAE|NEED_CMOV|NEED_CMPXCHG64)
+#define REQUIRED_MASK0	(NEED_FPU|NEED_PAE|NEED_CMOV|NEED_CX8)
+
+#ifdef CONFIG_X86_USE_3DNOW
+# define NEED_3DNOW	(1<<(X86_FEATURE_3DNOW & 31))
+#else
+# define NEED_3DNOW	0
+#endif
+
+#define REQUIRED_MASK1	(NEED_3DNOW)
+
+#define REQUIRED_MASK2	0
+#define REQUIRED_MASK3	0
+#define REQUIRED_MASK4	0
+#define REQUIRED_MASK5	0
+#define REQUIRED_MASK6	0
+#define REQUIRED_MASK7	0
 
 #endif
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 0e8077c..0d5bff9 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -26,12 +26,15 @@
 #define NEW_CL_POINTER		0x228	/* Relative to real mode data */
 
 #ifndef __ASSEMBLY__
+
+#include <asm/bootparam.h>
+
 /*
  * This is set up by the setup-routine at boot-time
  */
-extern unsigned char boot_params[PARAM_SIZE];
+extern struct boot_params boot_params;
 
-#define PARAM	(boot_params)
+#define PARAM	((char *)&boot_params)
 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
 #define EXT_MEM_K (*(unsigned short *) (PARAM+2))
 #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
@@ -39,8 +42,7 @@
 #define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))
 #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
 #define IST_INFO   (*(struct ist_info *) (PARAM+0x60))
-#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
-#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
+#define SYS_DESC_TABLE (*(struct sys_desc_table *)(PARAM+0xa0))
 #define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
 #define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
 #define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 4cb0f91..54424e0 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -137,6 +137,7 @@
 #define TIF_DEBUG		17	/* uses debug registers */
 #define TIF_IO_BITMAP		18	/* uses I/O bitmap */
 #define TIF_FREEZE		19	/* is freezing for suspend */
+#define TIF_NOTSC		20	/* TSC is not accessible in userland */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -151,6 +152,7 @@
 #define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
+#define _TIF_NOTSC		(1<<TIF_NOTSC)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
@@ -160,7 +162,8 @@
 #define _TIF_ALLWORK_MASK	(0x0000FFFF & ~_TIF_SECCOMP)
 
 /* flags to check in __switch_to() */
-#define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP)
+#define _TIF_WORK_CTXSW_NEXT (_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUG)
+#define _TIF_WORK_CTXSW_PREV (_TIF_IO_BITMAP | _TIF_NOTSC)
 
 /*
  * Thread-synchronous status.
diff --git a/include/asm-i386/tlbflush.h b/include/asm-i386/tlbflush.h
index db7f77e..fc525c5 100644
--- a/include/asm-i386/tlbflush.h
+++ b/include/asm-i386/tlbflush.h
@@ -90,6 +90,8 @@
 
 #ifndef CONFIG_SMP
 
+#include <linux/sched.h>
+
 #define flush_tlb() __flush_tlb()
 #define flush_tlb_all() __flush_tlb_all()
 #define local_flush_tlb() __flush_tlb()
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index 5d03792..5b52635 100644
--- a/include/asm-ia64/acpi.h
+++ b/include/asm-ia64/acpi.h
@@ -30,6 +30,8 @@
 
 #ifdef __KERNEL__
 
+#include <acpi/pdc_intel.h>
+
 #include <linux/init.h>
 #include <linux/numa.h>
 #include <asm/system.h>
@@ -119,11 +121,6 @@
 extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
 #endif
 
-/*
- * Refer Intel ACPI _PDC support document for bit definitions
- */
-#define ACPI_PDC_EST_CAPABILITY_SMP     0x8
-
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index 40d01d8..0f6e526 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -31,8 +31,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64 __attribute__((aligned(4))) compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64 __attribute__((aligned(4))) compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-ia64/fb.h b/include/asm-ia64/fb.h
new file mode 100644
index 0000000..89a397c
--- /dev/null
+++ b/include/asm-ia64/fb.h
@@ -0,0 +1,23 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <linux/efi.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	else
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-ia64/ioctls.h b/include/asm-ia64/ioctls.h
index 31ee521..f41b636 100644
--- a/include/asm-ia64/ioctls.h
+++ b/include/asm-ia64/ioctls.h
@@ -53,6 +53,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index 41098f4..edd5d01 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -48,6 +48,7 @@
 	IA64_MCA_RENDEZ_CHECKIN_NOTDONE	=	0x0,
 	IA64_MCA_RENDEZ_CHECKIN_DONE	=	0x1,
 	IA64_MCA_RENDEZ_CHECKIN_INIT	=	0x2,
+	IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA	=	0x3,
 };
 
 /* Information maintained by the MC infrastructure */
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 485759b..d634546 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -87,12 +87,13 @@
 } while (0)
 
 
-#define alloc_zeroed_user_highpage(vma, vaddr) \
-({						\
-	struct page *page = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr); \
-	if (page)				\
- 		flush_dcache_page(page);	\
-	page;					\
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr)		\
+({									\
+	struct page *page = alloc_page_vma(				\
+		GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr);	\
+	if (page)							\
+ 		flush_dcache_page(page);				\
+	page;								\
 })
 
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
index 5a5d1c2..0149097 100644
--- a/include/asm-ia64/pci.h
+++ b/include/asm-ia64/pci.h
@@ -71,14 +71,6 @@
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
-/* The ia64 platform always supports 64-bit addressing. */
-#define pci_dac_dma_supported(pci_dev, mask)		(1)
-#define pci_dac_page_to_dma(dev,pg,off,dir)		((dma_addr_t) page_to_bus(pg) + (off))
-#define pci_dac_dma_to_page(dev,dma_addr)		(virt_to_page(bus_to_virt(dma_addr)))
-#define pci_dac_dma_to_offset(dev,dma_addr)		offset_in_page(dma_addr)
-#define pci_dac_dma_sync_single_for_cpu(dev,dma_addr,len,dir)	do { } while (0)
-#define pci_dac_dma_sync_single_for_device(dev,dma_addr,len,dir)	do { mb(); } while (0)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
@@ -104,10 +96,12 @@
 #define HAVE_PCI_LEGACY
 extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
 				      struct vm_area_struct *vma);
-extern ssize_t pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off,
-				  size_t count);
-extern ssize_t pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off,
-				   size_t count);
+extern ssize_t pci_read_legacy_io(struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
+				  char *buf, loff_t off, size_t count);
+extern ssize_t pci_write_legacy_io(struct kobject *kobj,
+				   struct bin_attribute *bin_attr,
+				   char *buf, loff_t off, size_t count);
 extern int pci_mmap_legacy_mem(struct kobject *kobj,
 			       struct bin_attribute *attr,
 			       struct vm_area_struct *vma);
@@ -143,10 +137,6 @@
 	return (pci_domain_nr(bus) != 0);
 }
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 extern void pcibios_resource_to_bus(struct pci_dev *dev,
 		struct pci_bus_region *region, struct resource *res);
 
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 670b706..de6d01e 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -297,8 +297,6 @@
 /*
  * The following have defined behavior only work if pte_present() is true.
  */
-#define pte_user(pte)		((pte_val(pte) & _PAGE_PL_MASK) == _PAGE_PL_3)
-#define pte_read(pte)		(((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) < 6)
 #define pte_write(pte)	((unsigned) (((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) - 2) <= 4)
 #define pte_exec(pte)		((pte_val(pte) & _PAGE_AR_RX) != 0)
 #define pte_dirty(pte)		((pte_val(pte) & _PAGE_D) != 0)
@@ -310,7 +308,6 @@
  */
 #define pte_wrprotect(pte)	(__pte(pte_val(pte) & ~_PAGE_AR_RW))
 #define pte_mkwrite(pte)	(__pte(pte_val(pte) | _PAGE_AR_RW))
-#define pte_mkexec(pte)		(__pte(pte_val(pte) | _PAGE_AR_RX))
 #define pte_mkold(pte)		(__pte(pte_val(pte) & ~_PAGE_A))
 #define pte_mkyoung(pte)	(__pte(pte_val(pte) | _PAGE_A))
 #define pte_mkclean(pte)	(__pte(pte_val(pte) & ~_PAGE_D))
@@ -398,22 +395,6 @@
 #endif
 }
 
-static inline int
-ptep_test_and_clear_dirty (struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
-	if (!pte_dirty(*ptep))
-		return 0;
-	return test_and_clear_bit(_PAGE_D_BIT, ptep);
-#else
-	pte_t pte = *ptep;
-	if (!pte_dirty(pte))
-		return 0;
-	set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
-	return 1;
-#endif
-}
-
 static inline pte_t
 ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -533,16 +514,25 @@
  * daccess_bit in ivt.S).
  */
 #ifdef CONFIG_SMP
-# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable)	\
-do {											\
-	if (__safely_writable) {							\
-		set_pte(__ptep, __entry);						\
-		flush_tlb_page(__vma, __addr);						\
-	}										\
-} while (0)
+# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
+({									\
+	int __changed = !pte_same(*(__ptep), __entry);			\
+	if (__changed && __safely_writable) {				\
+		set_pte(__ptep, __entry);				\
+		flush_tlb_page(__vma, __addr);				\
+	}								\
+	__changed;							\
+})
 #else
-# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable)	\
-	ptep_establish(__vma, __addr, __ptep, __entry)
+# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
+({									\
+	int __changed = !pte_same(*(__ptep), __entry);			\
+	if (__changed) {						\
+		set_pte_at((__vma)->vm_mm, (__addr), __ptep, __entry);	\
+		flush_tlb_page(__vma, __addr);				\
+	}								\
+	__changed;							\
+})
 #endif
 
 #  ifdef CONFIG_VIRTUAL_MEM_MAP
@@ -584,7 +574,6 @@
 #endif
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 291e8ce..676b31a 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -32,6 +32,7 @@
 #define  SN_SAL_NO_FAULT_ZONE_VIRTUAL		   0x02000010
 #define  SN_SAL_NO_FAULT_ZONE_PHYSICAL		   0x02000011
 #define  SN_SAL_PRINT_ERROR			   0x02000012
+#define  SN_SAL_REGISTER_PMI_HANDLER		   0x02000014
 #define  SN_SAL_SET_ERROR_HANDLING_FEATURES	   0x0200001a	// reentrant
 #define  SN_SAL_GET_FIT_COMPT			   0x0200001b	// reentrant
 #define  SN_SAL_GET_SAPIC_INFO                     0x0200001d
@@ -680,6 +681,25 @@
 }
 
 /*
+ * Register or unregister a function to handle a PMI received by a CPU.
+ * Before calling the registered handler, SAL sets r1 to the value that
+ * was passed in as the global_pointer.
+ *
+ * If the handler pointer is NULL, then the currently registered handler
+ * will be unregistered.
+ *
+ * Returns 0 on success, or a negative value if an error occurred.
+ */
+static inline int
+sn_register_pmi_handler(u64 handler, u64 global_pointer)
+{
+	struct ia64_sal_retval ret_stuff;
+	ia64_sal_oemcall(&ret_stuff, SN_SAL_REGISTER_PMI_HANDLER, handler,
+			 global_pointer, 0, 0, 0, 0, 0);
+	return ret_stuff.status;
+}
+
+/*
  * Change or query the coherence domain for this partition. Each cpu-based
  * nasid is represented by a bit in an array of 64-bit words:
  *      0 = not in this partition's coherency domain
@@ -696,8 +716,8 @@
 sn_change_coherence(u64 *new_domain, u64 *old_domain)
 {
 	struct ia64_sal_retval ret_stuff;
-	ia64_sal_oemcall(&ret_stuff, SN_SAL_COHERENCE, (u64)new_domain,
-			 (u64)old_domain, 0, 0, 0, 0, 0);
+	ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_COHERENCE, (u64)new_domain,
+				(u64)old_domain, 0, 0, 0, 0, 0);
 	return ret_stuff.status;
 }
 
diff --git a/include/asm-ia64/termbits.h b/include/asm-ia64/termbits.h
index 4531a51..9f162e0 100644
--- a/include/asm-ia64/termbits.h
+++ b/include/asm-ia64/termbits.h
@@ -26,6 +26,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
@@ -138,6 +149,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -153,10 +165,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define IBSHIFT	16		/* Shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-ia64/termios.h b/include/asm-ia64/termios.h
index 08750c2..689d218 100644
--- a/include/asm-ia64/termios.h
+++ b/include/asm-ia64/termios.h
@@ -87,8 +87,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC);	\
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 # endif /* __KERNEL__ */
 
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index d7781a2..441c9e0 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -305,6 +305,19 @@
 
 #define NR_syscalls			286 /* length of syscall table */
 
+/*
+ * The following defines stop scripts/checksyscalls.sh from complaining about
+ * unimplemented system calls.  Glibc provides for each of these by using
+ * more modern equivalent system calls.
+ */
+#define __IGNORE_fork		/* clone() */
+#define __IGNORE_time		/* gettimeofday() */
+#define __IGNORE_alarm		/* setitimer(ITIMER_REAL, ... */
+#define __IGNORE_pause		/* rt_sigprocmask(), rt_sigsuspend() */
+#define __IGNORE_utime		/* utimes() */
+#define __IGNORE_getpgrp	/* getpgid() */
+#define __IGNORE_vfork		/* clone() */
+
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
diff --git a/include/asm-m32r/dma-mapping.h b/include/asm-m32r/dma-mapping.h
deleted file mode 100644
index f9b58eb..0000000
--- a/include/asm-m32r/dma-mapping.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_M32R_DMA_MAPPING_H
-#define _ASM_M32R_DMA_MAPPING_H
-
-#include <asm-generic/dma-mapping-broken.h>
-
-#endif /* _ASM_M32R_DMA_MAPPING_H */
diff --git a/include/asm-m32r/fb.h b/include/asm-m32r/fb.h
new file mode 100644
index 0000000..d92e99c
--- /dev/null
+++ b/include/asm-m32r/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m32r/ioctls.h b/include/asm-m32r/ioctls.h
index d23cfc4..b9f54bb 100644
--- a/include/asm-m32r/ioctls.h
+++ b/include/asm-m32r/ioctls.h
@@ -47,6 +47,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 6f6ecf7..04fd183 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -15,7 +15,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 6604303..92d7266 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -191,16 +191,6 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_READ;
-}
-
-static inline int pte_exec(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_EXEC;
-}
-
 static inline int pte_dirty(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_DIRTY;
@@ -224,18 +214,6 @@
 	return pte_val(pte) & _PAGE_FILE;
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-	pte_val(pte) &= ~_PAGE_READ;
-	return pte;
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{
-	pte_val(pte) &= ~_PAGE_EXEC;
-	return pte;
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte_val(pte) &= ~_PAGE_DIRTY;
@@ -254,18 +232,6 @@
 	return pte;
 }
 
-static inline pte_t pte_mkread(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_READ;
-	return pte;
-}
-
-static inline pte_t pte_mkexec(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_EXEC;
-	return pte;
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_DIRTY;
@@ -284,11 +250,6 @@
 	return pte;
 }
 
-static inline  int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-	return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
-}
-
 static inline  int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
@@ -382,7 +343,6 @@
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
index e402641df..bc10400 100644
--- a/include/asm-m32r/termbits.h
+++ b/include/asm-m32r/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
@@ -129,6 +140,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -144,11 +156,13 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/** input baud rate */
 #define CTVB	  004000000000		/* VisioBraille Terminal flow control */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define	IBSHIFT	16			/* Shift from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-m32r/termios.h b/include/asm-m32r/termios.h
index 4943dd8..93ce79f 100644
--- a/include/asm-m32r/termios.h
+++ b/include/asm-m32r/termios.h
@@ -81,8 +81,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-m68k/atari_SLM.h b/include/asm-m68k/atari_SLM.h
deleted file mode 100644
index 42f4fcdd..0000000
--- a/include/asm-m68k/atari_SLM.h
+++ /dev/null
@@ -1,28 +0,0 @@
-
-#ifndef _ATARI_SLM_H
-#define _ATARI_SLM_H
-
-/* Atari SLM laser printer specific ioctls */
-
-#define	SLMIOGSTAT	0xa100
-#define	SLMIOGPSIZE	0xa101
-#define	SLMIOGMFEED	0xa102
-
-#define	SLMIORESET	0xa140
-
-#define	SLMIOSPSIZE	0xa181
-#define	SLMIOSMFEED	0xa182
-
-/* Status returning structure (SLMIOGSTAT) */
-struct SLM_status {
-	int		stat;		/* numeric status code */
-	char	str[40];	/* status string */
-};
-
-/* Paper size structure (SLMIO[GS]PSIZE) */
-struct SLM_paper_size {
-	int		width;
-	int		height;
-};
-
-#endif /* _ATARI_SLM_H */
diff --git a/include/asm-m68k/atari_acsi.h b/include/asm-m68k/atari_acsi.h
deleted file mode 100644
index 10fea68..0000000
--- a/include/asm-m68k/atari_acsi.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _ASM_ATARI_ACSI_H
-#define _ASM_ATARI_ACSI_H
-
-/* Functions exported by drivers/block/acsi.c */
-
-void acsi_delay_start( void );
-void acsi_delay_end( long usec );
-int acsi_wait_for_IRQ( unsigned timeout );
-int acsi_wait_for_noIRQ( unsigned timeout );
-int acsicmd_nodma( const char *cmd, int enable);
-int acsi_getstatus( void );
-int acsi_extstatus( char *buffer, int cnt );
-void acsi_end_extstatus( void );
-int acsi_extcmd( unsigned char *buffer, int cnt );
-
-/* The ACSI buffer is guarantueed to reside in ST-RAM and may be used by other
- * drivers that work on the ACSI bus, too. It's data are valid only as long as
- * the ST-DMA is locked. */
-extern char *acsi_buffer;
-extern unsigned long phys_acsi_buffer;
-
-/* Utility macros */
-
-/* Send one data byte over the bus and set mode for next operation
- * with one move.l -- Atari recommends this...
- */
-
-#define DMA_LONG_WRITE(data,mode)							\
-    do {													\
-		*((unsigned long *)&dma_wd.fdc_acces_seccount) =	\
-			((data)<<16) | (mode);							\
-	} while(0)
-
-#define ENABLE_IRQ()	atari_turnon_irq( IRQ_MFP_ACSI )
-#define DISABLE_IRQ()	atari_turnoff_irq( IRQ_MFP_ACSI )
-
-#endif /* _ASM_ATARI_ACSI_H */
diff --git a/include/asm-m68k/fb.h b/include/asm-m68k/fb.h
new file mode 100644
index 0000000..380b97a
--- /dev/null
+++ b/include/asm-m68k/fb.h
@@ -0,0 +1,34 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+#ifdef CONFIG_SUN3
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
+}
+#else
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	if (CPU_IS_020_OR_030)
+		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
+	if (CPU_IS_040_OR_060) {
+		pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
+		/* Use no-cache mode, serialized */
+		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
+	}
+}
+#endif /* CONFIG_SUN3 */
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m68k/mmzone.h b/include/asm-m68k/mmzone.h
new file mode 100644
index 0000000..e1f1ec7
--- /dev/null
+++ b/include/asm-m68k/mmzone.h
@@ -0,0 +1,9 @@
+#ifndef _ASM_M68K_MMZONE_H_
+#define _ASM_M68K_MMZONE_H_
+
+extern pg_data_t pg_data_map[];
+
+#define NODE_DATA(nid)		(&pg_data_map[nid])
+#define NODE_MEM_MAP(nid)	(NODE_DATA(nid)->node_mem_map)
+
+#endif /* _ASM_M68K_MMZONE_H_ */
diff --git a/include/asm-m68k/module.h b/include/asm-m68k/module.h
index c6d75af..382d20a 100644
--- a/include/asm-m68k/module.h
+++ b/include/asm-m68k/module.h
@@ -1,7 +1,39 @@
 #ifndef _ASM_M68K_MODULE_H
 #define _ASM_M68K_MODULE_H
-struct mod_arch_specific { };
+
+struct mod_arch_specific {
+	struct m68k_fixup_info *fixup_start, *fixup_end;
+};
+
+#define MODULE_ARCH_INIT {				\
+	.fixup_start		= __start_fixup,	\
+	.fixup_end		= __stop_fixup,		\
+}
+
 #define Elf_Shdr Elf32_Shdr
 #define Elf_Sym Elf32_Sym
 #define Elf_Ehdr Elf32_Ehdr
+
+
+enum m68k_fixup_type {
+	m68k_fixup_memoffset,
+	m68k_fixup_vnode_shift,
+};
+
+struct m68k_fixup_info {
+	enum m68k_fixup_type type;
+	void *addr;
+};
+
+#define m68k_fixup(type, addr)			\
+	"	.section \".m68k_fixup\",\"aw\"\n"	\
+	"	.long " #type "," #addr "\n"	\
+	"	.previous\n"
+
+extern struct m68k_fixup_info __start_fixup[], __stop_fixup[];
+
+struct module;
+extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+			 struct m68k_fixup_info *end);
+
 #endif /* _ASM_M68K_MODULE_H */
diff --git a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
index 61e4406..d029b75 100644
--- a/include/asm-m68k/motorola_pgtable.h
+++ b/include/asm-m68k/motorola_pgtable.h
@@ -130,7 +130,7 @@
 #define pte_present(pte)	(pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE))
 #define pte_clear(mm,addr,ptep)		({ pte_val(*(ptep)) = 0; })
 
-#define pte_page(pte)		(mem_map + ((unsigned long)(__va(pte_val(pte)) - PAGE_OFFSET) >> PAGE_SHIFT))
+#define pte_page(pte)		virt_to_page(__va(pte_val(pte)))
 #define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
@@ -143,7 +143,7 @@
 	while (--__i >= 0)			\
 		*__ptr++ = 0;			\
 })
-#define pmd_page(pmd)		(mem_map + ((unsigned long)(__va(pmd_val(pmd)) - PAGE_OFFSET) >> PAGE_SHIFT))
+#define pmd_page(pmd)		virt_to_page(__va(pmd_val(pmd)))
 
 
 #define pgd_none(pgd)		(!pgd_val(pgd))
@@ -164,21 +164,15 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)		{ return 1; }
 static inline int pte_write(pte_t pte)		{ return !(pte_val(pte) & _PAGE_RONLY); }
-static inline int pte_exec(pte_t pte)		{ return 1; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
 
 static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_RONLY; return pte; }
-static inline pte_t pte_rdprotect(pte_t pte)	{ return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) &= ~_PAGE_RONLY; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mknocache(pte_t pte)
@@ -223,10 +217,10 @@
 	return (pte_t *)__pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
 }
 
-#define pte_offset_map(pmdp,address) ((pte_t *)kmap(pmd_page(*pmdp)) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+#define pte_offset_map(pmdp,address) ((pte_t *)__pmd_page(*pmdp) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
 #define pte_offset_map_nested(pmdp, address) pte_offset_map(pmdp, address)
-#define pte_unmap(pte) kunmap(pte)
-#define pte_unmap_nested(pte) kunmap(pte)
+#define pte_unmap(pte)		((void)0)
+#define pte_unmap_nested(pte)	((void)0)
 
 /*
  * Allocate and free page tables. The xxx_kernel() versions are
diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h
index fcc165d..9e6d0d6 100644
--- a/include/asm-m68k/page.h
+++ b/include/asm-m68k/page.h
@@ -27,6 +27,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/module.h>
+
 #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
 #define free_user_page(page, addr)	free_page(addr)
 
@@ -114,18 +116,33 @@
 
 #ifndef __ASSEMBLY__
 
+extern unsigned long m68k_memoffset;
+
 #ifndef CONFIG_SUN3
 
 #define WANT_PAGE_VIRTUAL
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
-extern unsigned long m68k_memoffset;
 
-#define __pa(vaddr)		((unsigned long)(vaddr)+m68k_memoffset)
-#define __va(paddr)		((void *)((unsigned long)(paddr)-m68k_memoffset))
-#else
-#define __pa(vaddr)		virt_to_phys((void *)(vaddr))
-#define __va(paddr)		phys_to_virt((unsigned long)(paddr))
-#endif
+static inline unsigned long ___pa(void *vaddr)
+{
+	unsigned long paddr;
+	asm (
+		"1:	addl #0,%0\n"
+		m68k_fixup(%c2, 1b+2)
+		: "=r" (paddr)
+		: "0" (vaddr), "i" (m68k_fixup_memoffset));
+	return paddr;
+}
+#define __pa(vaddr)	___pa((void *)(vaddr))
+static inline void *__va(unsigned long paddr)
+{
+	void *vaddr;
+	asm (
+		"1:	subl #0,%0\n"
+		m68k_fixup(%c2, 1b+2)
+		: "=r" (vaddr)
+		: "0" (paddr), "i" (m68k_fixup_memoffset));
+	return vaddr;
+}
 
 #else	/* !CONFIG_SUN3 */
 /* This #define is a horrible hack to suppress lots of warnings. --m */
@@ -161,11 +178,47 @@
 #define virt_to_pfn(kaddr)	(__pa(kaddr) >> PAGE_SHIFT)
 #define pfn_to_virt(pfn)	__va((pfn) << PAGE_SHIFT)
 
-#define virt_to_page(kaddr)	(mem_map + (((unsigned long)(kaddr)-PAGE_OFFSET) >> PAGE_SHIFT))
-#define page_to_virt(page)	((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
+extern int m68k_virt_to_node_shift;
 
-#define pfn_to_page(pfn)	virt_to_page(pfn_to_virt(pfn))
-#define page_to_pfn(page)	virt_to_pfn(page_to_virt(page))
+#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+#define __virt_to_node(addr)	(&pg_data_map[0])
+#else
+extern struct pglist_data *pg_data_table[];
+
+static inline __attribute_const__ int __virt_to_node_shift(void)
+{
+	int shift;
+
+	asm (
+		"1:	moveq	#0,%0\n"
+		m68k_fixup(%c1, 1b)
+		: "=d" (shift)
+		: "i" (m68k_fixup_vnode_shift));
+	return shift;
+}
+
+#define __virt_to_node(addr)	(pg_data_table[(unsigned long)(addr) >> __virt_to_node_shift()])
+#endif
+
+#define virt_to_page(addr) ({						\
+	pfn_to_page(virt_to_pfn(addr));					\
+})
+#define page_to_virt(page) ({						\
+	pfn_to_virt(page_to_pfn(page));					\
+})
+
+#define pfn_to_page(pfn) ({						\
+	unsigned long __pfn = (pfn);					\
+	struct pglist_data *pgdat;					\
+	pgdat = __virt_to_node((unsigned long)pfn_to_virt(__pfn));	\
+	pgdat->node_mem_map + (__pfn - pgdat->node_start_pfn);		\
+})
+#define page_to_pfn(_page) ({						\
+	struct page *__p = (_page);					\
+	struct pglist_data *pgdat;					\
+	pgdat = &pg_data_map[page_to_nid(__p)];				\
+	((__p) - pgdat->node_mem_map) + pgdat->node_start_pfn;		\
+})
 
 #define virt_addr_valid(kaddr)	((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < high_memory)
 #define pfn_valid(pfn)		virt_addr_valid(pfn_to_virt(pfn))
diff --git a/include/asm-m68k/pci.h b/include/asm-m68k/pci.h
index 9d2c07a..678cb0b 100644
--- a/include/asm-m68k/pci.h
+++ b/include/asm-m68k/pci.h
@@ -54,8 +54,4 @@
  */
 #define PCI_DMA_BUS_IS_PHYS	(1)
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* _ASM_M68K_PCI_H */
diff --git a/include/asm-m68k/pgalloc.h b/include/asm-m68k/pgalloc.h
index a9cfb4b..4cb1a57 100644
--- a/include/asm-m68k/pgalloc.h
+++ b/include/asm-m68k/pgalloc.h
@@ -8,11 +8,12 @@
 #include <asm/virtconvert.h>
 
 
-
 #ifdef CONFIG_SUN3
 #include <asm/sun3_pgalloc.h>
 #else
 #include <asm/motorola_pgalloc.h>
 #endif
 
+extern void m68k_setup_node(int node);
+
 #endif /* M68K_PGALLOC_H */
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 555b87a..778a4c5 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -107,22 +107,7 @@
 /* 64-bit machines, beware!  SRB. */
 #define SIZEOF_PTR_LOG2			       2
 
-/*
- * Check if the addr/len goes up to the end of a physical
- * memory chunk.  Used for DMA functions.
- */
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
-/*
- * It makes no sense to consider whether we cross a memory boundary if
- * we support just one physical chunk of memory.
- */
-static inline int mm_end_of_chunk(unsigned long addr, int len)
-{
-	return 0;
-}
-#else
-int mm_end_of_chunk (unsigned long addr, int len);
-#endif
+#define mm_end_of_chunk(addr, len)	0
 
 extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);
 
diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
index 5156a28..b766fc2 100644
--- a/include/asm-m68k/sun3_pgtable.h
+++ b/include/asm-m68k/sun3_pgtable.h
@@ -132,8 +132,8 @@
 #define pfn_pte(pfn, pgprot) \
 ({ pte_t __pte; pte_val(__pte) = pfn | pgprot_val(pgprot); __pte; })
 
-#define pte_page(pte)		(mem_map+((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT))
-#define pmd_page(pmd)		(mem_map+((__pmd_page(pmd) - PAGE_OFFSET) >> PAGE_SHIFT))
+#define pte_page(pte)		virt_to_page(__pte_page(pte))
+#define pmd_page(pmd)		virt_to_page(__pmd_page(pmd))
 
 
 static inline int pmd_none2 (pmd_t *pmd) { return !pmd_val (*pmd); }
@@ -165,21 +165,15 @@
  * Undefined behaviour if not...
  * [we have the full set here even if they don't change from m68k]
  */
-static inline int pte_read(pte_t pte)		{ return 1; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_WRITEABLE; }
-static inline int pte_exec(pte_t pte)		{ return 1; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_MODIFIED; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & SUN3_PAGE_ACCESSED; }
 
 static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_WRITEABLE; return pte; }
-static inline pte_t pte_rdprotect(pte_t pte)	{ return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_MODIFIED; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~SUN3_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_WRITEABLE; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_MODIFIED; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mknocache(pte_t pte)	{ pte_val(pte) |= SUN3_PAGE_NOCACHE; return pte; }
diff --git a/include/asm-m68k/termbits.h b/include/asm-m68k/termbits.h
index a194092..0e520f3 100644
--- a/include/asm-m68k/termbits.h
+++ b/include/asm-m68k/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-m68k/virtconvert.h b/include/asm-m68k/virtconvert.h
index 83a87c9..dea32fb 100644
--- a/include/asm-m68k/virtconvert.h
+++ b/include/asm-m68k/virtconvert.h
@@ -8,56 +8,35 @@
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
+#include <linux/mmzone.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#endif
-
 /*
  * Change virtual addresses to physical addresses and vv.
  */
-#ifndef CONFIG_SUN3
-extern unsigned long mm_vtop(unsigned long addr) __attribute_const__;
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-#else
-static inline unsigned long mm_vtop(unsigned long vaddr)
-{
-	return __pa(vaddr);
-}
-
-static inline unsigned long mm_ptov(unsigned long paddr)
-{
-	return (unsigned long)__va(paddr);
-}
-#endif
-
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
-static inline unsigned long virt_to_phys(void *vaddr)
-{
-	return (unsigned long)vaddr - PAGE_OFFSET + m68k_memory[0].addr;
-}
-
-static inline void * phys_to_virt(unsigned long paddr)
-{
-	return (void *)(paddr - m68k_memory[0].addr + PAGE_OFFSET);
-}
-#else
 static inline unsigned long virt_to_phys(void *address)
 {
-	return mm_vtop((unsigned long)address);
+	return __pa(address);
 }
 
 static inline void *phys_to_virt(unsigned long address)
 {
-	return (void *) mm_ptov(address);
+	return __va(address);
 }
-#endif
 
 /* Permanent address of a page. */
-#define __page_address(page)	(PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
-#define page_to_phys(page)	virt_to_phys((void *)__page_address(page))
+#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+#define page_to_phys(page) \
+	__pa(PAGE_OFFSET + (((page) - pg_data_map[0].node_mem_map) << PAGE_SHIFT))
+#else
+#define page_to_phys(_page) ({						\
+	struct page *__page = _page;					\
+	struct pglist_data *pgdat;					\
+	pgdat = pg_data_table[page_to_nid(__page)];			\
+	page_to_pfn(__page) << PAGE_SHIFT;				\
+})
+#endif
 
 /*
  * IO bus memory addresses are 1:1 with the physical address,
diff --git a/include/asm-m68knommu/fb.h b/include/asm-m68knommu/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-m68knommu/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
index 2a1b8bd..9efa0a9 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -22,7 +22,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-m68knommu/pci.h b/include/asm-m68knommu/pci.h
index e04c77e..a13f3cc 100644
--- a/include/asm-m68knommu/pci.h
+++ b/include/asm-m68knommu/pci.h
@@ -24,16 +24,6 @@
 	return 1;
 }
 
-/*
- * Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function.  Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* CONFIG_COMEMPCI */
 
 #endif /* M68KNOMMU_PCI_H */
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index c627508..0b3ff9c 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -129,28 +129,12 @@
 #define PHYS_TO_XKPHYS(cm,a)		(_CONST64_(0x8000000000000000) | \
 					 ((cm)<<59) | (a))
 
-#if defined (CONFIG_CPU_R4300)						\
-    || defined (CONFIG_CPU_R4X00)					\
-    || defined (CONFIG_CPU_R5000)					\
-    || defined (CONFIG_CPU_RM7000)					\
-    || defined (CONFIG_CPU_NEVADA)					\
-    || defined (CONFIG_CPU_TX49XX)					\
-    || defined (CONFIG_CPU_MIPS64)
-#define TO_PHYS_MASK	_CONST64_(0x0000000fffffffff)	/* 2^^36 - 1 */
-#endif
-
-#if defined (CONFIG_CPU_R8000)
-/* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */
-#define TO_PHYS_MASK	_CONST64_(0x000000ffffffffff)	/* 2^^40 - 1 */
-#endif
-
-#if defined (CONFIG_CPU_R10000)
-#define TO_PHYS_MASK	_CONST64_(0x000000ffffffffff)	/* 2^^40 - 1 */
-#endif
-
-#if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A)
-#define TO_PHYS_MASK	_CONST64_(0x00000fffffffffff)	/* 2^^44 - 1 */
-#endif
+/*
+ * The ultimate limited of the 64-bit MIPS architecture:  2 bits for selecting
+ * the region, 3 bits for the CCA mode.  This leaves 59 bits of which the
+ * R8000 implements most with its 48-bit physical address space.
+ */
+#define TO_PHYS_MASK	_CONST64_(0x07ffffffffffffff)	/* 2^^59 - 1 */
 
 #ifndef CONFIG_CPU_R8000
 
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index 92e62ef..c5f20df 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -52,21 +52,6 @@
 	.endm
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-#ifdef CONFIG_CPU_SB1
-	.macro	fpu_enable_hazard
-	.set	push
-	.set	noreorder
-	.set	mips2
-	SSNOP
-	bnezl	$0, .+4
-	 SSNOP
-	.set	pop
-	.endm
-#else
-	.macro	fpu_enable_hazard
-	.endm
-#endif
-
 /*
  * Temporary until all gas have MT ASE support
  */
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index d995413..d9e81af 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -238,10 +238,11 @@
 	volatile unsigned long *addr)
 {
 	unsigned short bit = nr & SZLONG_MASK;
+	unsigned long res;
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-		unsigned long temp, res;
+		unsigned long temp;
 
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
@@ -254,11 +255,9 @@
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << bit), "m" (*m)
 		: "memory");
-
-		return res != 0;
 	} else if (cpu_has_llsc) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-		unsigned long temp, res;
+		unsigned long temp;
 
 		__asm__ __volatile__(
 		"	.set	push					\n"
@@ -277,25 +276,22 @@
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << bit), "m" (*m)
 		: "memory");
-
-		return res != 0;
 	} else {
 		volatile unsigned long *a = addr;
 		unsigned long mask;
-		int retval;
 		unsigned long flags;
 
 		a += nr >> SZLONG_LOG;
 		mask = 1UL << bit;
 		raw_local_irq_save(flags);
-		retval = (mask & *a) != 0;
+		res = (mask & *a);
 		*a |= mask;
 		raw_local_irq_restore(flags);
-
-		return retval;
 	}
 
 	smp_mb();
+
+	return res != 0;
 }
 
 /*
@@ -310,10 +306,11 @@
 	volatile unsigned long *addr)
 {
 	unsigned short bit = nr & SZLONG_MASK;
+	unsigned long res;
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-		unsigned long temp, res;
+		unsigned long temp;
 
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
@@ -327,12 +324,10 @@
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << bit), "m" (*m)
 		: "memory");
-
-		return res != 0;
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (__builtin_constant_p(nr)) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-		unsigned long temp, res;
+		unsigned long temp;
 
 		__asm__ __volatile__(
 		"1:	" __LL	"%0, %1		# test_and_clear_bit	\n"
@@ -346,12 +341,10 @@
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "ri" (bit), "m" (*m)
 		: "memory");
-
-		return res;
 #endif
 	} else if (cpu_has_llsc) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-		unsigned long temp, res;
+		unsigned long temp;
 
 		__asm__ __volatile__(
 		"	.set	push					\n"
@@ -371,25 +364,22 @@
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << bit), "m" (*m)
 		: "memory");
-
-		return res != 0;
 	} else {
 		volatile unsigned long *a = addr;
 		unsigned long mask;
-		int retval;
 		unsigned long flags;
 
 		a += nr >> SZLONG_LOG;
 		mask = 1UL << bit;
 		raw_local_irq_save(flags);
-		retval = (mask & *a) != 0;
+		res = (mask & *a);
 		*a &= ~mask;
 		raw_local_irq_restore(flags);
-
-		return retval;
 	}
 
 	smp_mb();
+
+	return res != 0;
 }
 
 /*
@@ -404,10 +394,11 @@
 	volatile unsigned long *addr)
 {
 	unsigned short bit = nr & SZLONG_MASK;
+	unsigned long res;
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-		unsigned long temp, res;
+		unsigned long temp;
 
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
@@ -420,11 +411,9 @@
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << bit), "m" (*m)
 		: "memory");
-
-		return res != 0;
 	} else if (cpu_has_llsc) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-		unsigned long temp, res;
+		unsigned long temp;
 
 		__asm__ __volatile__(
 		"	.set	push					\n"
@@ -443,24 +432,22 @@
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << bit), "m" (*m)
 		: "memory");
-
-		return res != 0;
 	} else {
 		volatile unsigned long *a = addr;
-		unsigned long mask, retval;
+		unsigned long mask;
 		unsigned long flags;
 
 		a += nr >> SZLONG_LOG;
 		mask = 1UL << bit;
 		raw_local_irq_save(flags);
-		retval = (mask & *a) != 0;
+		res = (mask & *a);
 		*a ^= mask;
 		raw_local_irq_restore(flags);
-
-		return retval;
 	}
 
 	smp_mb();
+
+	return res != 0;
 }
 
 #include <asm-generic/bitops/non-atomic.h>
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index b0c3297..087126a 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -109,18 +109,12 @@
 #define  MACH_COSINE_ORION	0
 
 /*
- * Valid machtype for group GALILEO
- */
-#define MACH_GROUP_GALILEO     11	/* Galileo Eval Boards		*/
-#define  MACH_EV64120A		0	/* EV64120A */
-
-/*
  * Valid machtype for group MOMENCO
  */
 #define MACH_GROUP_MOMENCO	12	/* Momentum Boards		*/
 #define  MACH_MOMENCO_OCELOT	0
 #define  MACH_MOMENCO_OCELOT_G	1	/* no more supported (may 2007) */
-#define  MACH_MOMENCO_OCELOT_C	2
+#define  MACH_MOMENCO_OCELOT_C	2	/* no more supported (jun 2007) */
 #define  MACH_MOMENCO_JAGUAR_ATX 3	/* no more supported (may 2007) */
 #define  MACH_MOMENCO_OCELOT_3	4
 
@@ -194,13 +188,6 @@
 #define  MACH_HP_LASERJET	1
 
 /*
- * Valid machtype for group LASAT
- */
-#define MACH_GROUP_LASAT       21
-#define  MACH_LASAT_100		0	/* Masquerade II/SP100/SP50/SP25 */
-#define  MACH_LASAT_200		1	/* Masquerade PRO/SP200 */
-
-/*
  * Valid machtype for group TITAN
  */
 #define MACH_GROUP_TITAN       22	/* PMC-Sierra Titan		*/
@@ -213,6 +200,27 @@
 #define MACH_GROUP_NEC_EMMA2RH 25	/* NEC EMMA2RH (was 23)		*/
 #define  MACH_NEC_MARKEINS	0	/* NEC EMMA2RH Mark-eins	*/
 
+/*
+ * Valid machtype for group LEMOTE
+ */
+#define MACH_GROUP_LEMOTE          27
+#define  MACH_LEMOTE_FULONG        0
+
+/*
+ * Valid machtype for group PMC-MSP
+ */
+#define MACH_GROUP_MSP         26	/* PMC-Sierra MSP boards/CPUs    */
+#define MACH_MSP4200_EVAL       0	/* PMC-Sierra MSP4200 Evaluation */
+#define MACH_MSP4200_GW         1	/* PMC-Sierra MSP4200 Gateway demo */
+#define MACH_MSP4200_FPGA       2	/* PMC-Sierra MSP4200 Emulation */
+#define MACH_MSP7120_EVAL       3	/* PMC-Sierra MSP7120 Evaluation */
+#define MACH_MSP7120_GW         4	/* PMC-Sierra MSP7120 Residential GW */
+#define MACH_MSP7120_FPGA       5	/* PMC-Sierra MSP7120 Emulation */
+#define MACH_MSP_OTHER        255	/* PMC-Sierra unknown board type */
+
+#define MACH_GROUP_WINDRIVER   28	/* Windriver boards */
+#define MACH_WRPPMC             1
+
 #define CL_SIZE			COMMAND_LINE_SIZE
 
 const char *get_system_type(void);
diff --git a/include/asm-mips/cacheops.h b/include/asm-mips/cacheops.h
index c4a1ec3..df7f2de 100644
--- a/include/asm-mips/cacheops.h
+++ b/include/asm-mips/cacheops.h
@@ -20,7 +20,11 @@
 #define Index_Load_Tag_D	0x05
 #define Index_Store_Tag_I	0x08
 #define Index_Store_Tag_D	0x09
+#if defined(CONFIG_CPU_LOONGSON2)
+#define Hit_Invalidate_I    	0x00
+#else
 #define Hit_Invalidate_I	0x10
+#endif
 #define Hit_Invalidate_D	0x11
 #define Hit_Writeback_Inv_D	0x15
 
diff --git a/include/asm-mips/compat-signal.h b/include/asm-mips/compat-signal.h
index 6599a90..368a99e 100644
--- a/include/asm-mips/compat-signal.h
+++ b/include/asm-mips/compat-signal.h
@@ -10,6 +10,68 @@
 
 #include <asm/uaccess.h>
 
+#define SI_PAD_SIZE32   ((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct compat_siginfo {
+	int si_signo;
+	int si_code;
+	int si_errno;
+
+	union {
+		int _pad[SI_PAD_SIZE32];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;	/* sender's pid */
+			compat_uid_t _uid;	/* sender's uid */
+		} _kill;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;	/* which child */
+			compat_uid_t _uid;	/* sender's uid */
+			int _status;		/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* IRIX SIGCHLD */
+		struct {
+			compat_pid_t _pid;	/* which child */
+			compat_clock_t _utime;
+			int _status;		/* exit code */
+			compat_clock_t _stime;
+		} _irix_sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			s32 _addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL, SIGXFSZ (To do ...)  */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+
+		/* POSIX.1b timers */
+		struct {
+			timer_t _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			compat_sigval_t _sigval;/* same as below */
+			int _sys_private;       /* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;	/* sender's pid */
+			compat_uid_t _uid;	/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+	} _sifields;
+} compat_siginfo_t;
+
 static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
 	const sigset_t *s)
 {
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 432653d..568c76c 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -37,8 +37,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
@@ -132,7 +134,8 @@
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
-	return (void __user *)(long)uptr;
+	/* cast to a __user pointer via "unsigned long" makes sparse happy */
+	return (void __user *)(unsigned long)(long)uptr;
 }
 
 static inline compat_uptr_t ptr_to_compat(void __user *uptr)
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 5e4bed1..d95a83e 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -150,6 +150,10 @@
 #define cpu_has_mipsmt		(cpu_data[0].ases & MIPS_ASE_MIPSMT)
 #endif
 
+#ifndef cpu_has_userlocal
+#define cpu_has_userlocal	(cpu_data[0].options & MIPS_CPU_ULRI)
+#endif
+
 #ifdef CONFIG_32BIT
 # ifndef cpu_has_nofpuex
 # define cpu_has_nofpuex	(cpu_data[0].options & MIPS_CPU_NOFPUEX)
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index d38fdbf..3857358 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -89,6 +89,8 @@
 #define PRID_IMP_34K		0x9500
 #define PRID_IMP_24KE		0x9600
 #define PRID_IMP_74K		0x9700
+#define PRID_IMP_LOONGSON1      0x4200
+#define PRID_IMP_LOONGSON2      0x6300
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -107,6 +109,7 @@
  * Definitions for 7:0 on legacy processors
  */
 
+#define PRID_REV_MASK		0x00ff
 
 #define PRID_REV_TX4927		0x0022
 #define PRID_REV_TX4937		0x0030
@@ -123,6 +126,18 @@
 #define PRID_REV_VR4122		0x0070
 #define PRID_REV_VR4181A	0x0070	/* Same as VR4122 */
 #define PRID_REV_VR4130		0x0080
+#define PRID_REV_34K_V1_0_2	0x0022
+
+/*
+ * Older processors used to encode processor version and revision in two
+ * 4-bit bitfields, the 4K seems to simply count up and even newer MTI cores
+ * have switched to use the 8-bits as 3:3:2 bitfield with the last field as
+ * the patch number.  *ARGH*
+ */
+#define PRID_REV_ENCODE_44(ver, rev)					\
+	((ver) << 4 | (rev))
+#define PRID_REV_ENCODE_332(ver, rev, patch)				\
+	((ver) << 5 | (rev) << 2 | (patch))
 
 /*
  * FPU implementation/revision register (CP1 control register 0).
@@ -200,7 +215,10 @@
 #define CPU_SB1A		62
 #define CPU_74K			63
 #define CPU_R14000		64
-#define CPU_LAST		64
+#define CPU_LOONGSON1           65
+#define CPU_LOONGSON2           66
+
+#define CPU_LAST		66
 
 /*
  * ISA Level encodings
@@ -246,6 +264,7 @@
 #define MIPS_CPU_PREFETCH	0x00080000 /* CPU has usable prefetch */
 #define MIPS_CPU_VINT		0x00100000 /* CPU supports MIPSR2 vectored interrupts */
 #define MIPS_CPU_VEIC		0x00200000 /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI		0x00400000 /* CPU has ULRI feature */
 
 /*
  * CPU ASE encodings
diff --git a/include/asm-mips/div64.h b/include/asm-mips/div64.h
index 66189f5..716371b 100644
--- a/include/asm-mips/div64.h
+++ b/include/asm-mips/div64.h
@@ -20,7 +20,7 @@
  */
 
 #define do_div64_32(res, high, low, base) ({ \
-	unsigned long __quot, __mod; \
+	unsigned long __quot32, __mod32; \
 	unsigned long __cf, __tmp, __tmp2, __i; \
 	\
 	__asm__(".set	push\n\t" \
@@ -48,12 +48,13 @@
 		"bnez	%4, 0b\n\t" \
 		" srl	%5, %1, 0x1f\n\t" \
 		".set	pop" \
-		: "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
+		: "=&r" (__mod32), "=&r" (__tmp), \
+		  "=&r" (__quot32), "=&r" (__cf), \
 		  "=&r" (__i), "=&r" (__tmp2) \
 		: "Jr" (base), "0" (high), "1" (low)); \
 	\
-	(res) = __quot; \
-	__mod; })
+	(res) = __quot32; \
+	__mod32; })
 
 #define do_div(n, base) ({ \
 	unsigned long long __quot; \
diff --git a/include/asm-mips/fb.h b/include/asm-mips/fb.h
new file mode 100644
index 0000000..bd3f68c
--- /dev/null
+++ b/include/asm-mips/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-mips/gpio.h b/include/asm-mips/gpio.h
new file mode 100644
index 0000000..06e46fa
--- /dev/null
+++ b/include/asm-mips/gpio.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MIPS_GPIO_H
+#define __ASM_MIPS_GPIO_H
+
+#include <gpio.h>
+
+#endif /* __ASM_MIPS_GPIO_H */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 92ec261..7ba9289 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -178,6 +178,11 @@
 static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
 	unsigned long flags)
 {
+	void __iomem *addr = plat_ioremap(offset, size, flags);
+
+	if (addr)
+		return addr;
+
 #define __IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
 
 	if (cpu_has_64bit_addresses) {
@@ -207,7 +212,8 @@
 		 */
 		if (__IS_LOW512(phys_addr) && __IS_LOW512(last_addr) &&
 		    flags == _CACHE_UNCACHED)
-			return (void __iomem *)CKSEG1ADDR(phys_addr);
+			return (void __iomem *)
+				(unsigned long)CKSEG1ADDR(phys_addr);
 	}
 
 	return __ioremap(offset, size, flags);
@@ -282,6 +288,9 @@
 
 static inline void iounmap(const volatile void __iomem *addr)
 {
+	if (plat_iounmap(addr))
+		return;
+
 #define __IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1)
 
 	if (cpu_has_64bit_addresses ||
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 91803ba..97102eb 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -24,7 +24,7 @@
 #define irq_canonicalize(irq) (irq)	/* Sane hardware, sane code ... */
 #endif
 
-#ifdef CONFIG_MIPS_MT_SMTC
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 /*
  * Clear interrupt mask handling "backstop" if irq_hwmask
  * entry so indicates. This implies that the ack() or end()
@@ -72,4 +72,13 @@
 extern void alloc_legacy_irqno(void);
 extern void free_irqno(unsigned int irq);
 
+/*
+ * Before R2 the timer and performance counter interrupts were both fixed to
+ * IE7.  Since R2 their number has to be read from the c0_intctl register.
+ */
+#define CP0_LEGACY_COMPARE_IRQ 7
+
+extern int cp0_compare_irq;
+extern int cp0_perfcount_irq;
+
 #endif /* _ASM_IRQ_H */
diff --git a/include/asm-mips/lasat/ds1603.h b/include/asm-mips/lasat/ds1603.h
deleted file mode 100644
index edcd754..0000000
--- a/include/asm-mips/lasat/ds1603.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <asm/addrspace.h>
-
-/* Lasat 100	*/
-#define DS1603_REG_100		(KSEG1ADDR(0x1c810000))
-#define DS1603_RST_100		(1 << 2)
-#define DS1603_CLK_100		(1 << 0)
-#define DS1603_DATA_SHIFT_100	1
-#define DS1603_DATA_100		(1 << DS1603_DATA_SHIFT_100)
-
-/* Lasat 200	*/
-#define DS1603_REG_200		(KSEG1ADDR(0x11000000))
-#define DS1603_RST_200		(1 << 3)
-#define DS1603_CLK_200		(1 << 4)
-#define DS1603_DATA_200		(1 << 5)
-
-#define DS1603_DATA_REG_200		(DS1603_REG_200 + 0x10000)
-#define DS1603_DATA_READ_SHIFT_200	9
-#define DS1603_DATA_READ_200	(1 << DS1603_DATA_READ_SHIFT_200)
diff --git a/include/asm-mips/lasat/eeprom.h b/include/asm-mips/lasat/eeprom.h
deleted file mode 100644
index 7b53edd..0000000
--- a/include/asm-mips/lasat/eeprom.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <asm/addrspace.h>
-
-/* lasat 100 */
-#define AT93C_REG_100               KSEG1ADDR(0x1c810000)
-#define AT93C_RDATA_REG_100         AT93C_REG_100
-#define AT93C_RDATA_SHIFT_100       4
-#define AT93C_WDATA_SHIFT_100       4
-#define AT93C_CS_M_100              ( 1 << 5 )
-#define AT93C_CLK_M_100             ( 1 << 3 )
-
-/* lasat 200 */
-#define AT93C_REG_200		KSEG1ADDR(0x11000000)
-#define AT93C_RDATA_REG_200	(AT93C_REG_200+0x10000)
-#define AT93C_RDATA_SHIFT_200	8
-#define AT93C_WDATA_SHIFT_200	2
-#define AT93C_CS_M_200		( 1 << 0 )
-#define AT93C_CLK_M_200		( 1 << 1 )
diff --git a/include/asm-mips/lasat/head.h b/include/asm-mips/lasat/head.h
deleted file mode 100644
index f5589f3..0000000
--- a/include/asm-mips/lasat/head.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Image header stuff
- */
-#ifndef _HEAD_H
-#define _HEAD_H
-
-#define LASAT_K_MAGIC0_VAL	0xfedeabba
-#define LASAT_K_MAGIC1_VAL	0x00bedead
-
-#ifndef _LANGUAGE_ASSEMBLY
-#include <linux/types.h>
-struct bootloader_header {
-	u32 magic[2];
-	u32 version;
-	u32 image_start;
-	u32 image_size;
-	u32 kernel_start;
-	u32 kernel_entry;
-};
-#endif
-
-#endif /* _HEAD_H */
diff --git a/include/asm-mips/lasat/lasat.h b/include/asm-mips/lasat/lasat.h
deleted file mode 100644
index 42077e3..0000000
--- a/include/asm-mips/lasat/lasat.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * lasat.h
- *
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Configuration for LASAT boards, loads the appropriate include files.
- */
-#ifndef _LASAT_H
-#define _LASAT_H
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-extern struct lasat_misc {
-	volatile u32 *reset_reg;
-	volatile u32 *flash_wp_reg;
-	u32 flash_wp_bit;
-} *lasat_misc;
-
-enum lasat_mtdparts {
-	LASAT_MTD_BOOTLOADER,
-	LASAT_MTD_SERVICE,
-	LASAT_MTD_NORMAL,
-	LASAT_MTD_CONFIG,
-	LASAT_MTD_FS,
-	LASAT_MTD_LAST
-};
-
-/*
- * The format of the data record in the EEPROM.
- * See Documentation/LASAT/eeprom.txt for a detailed description
- * of the fields in this struct, and the LASAT Hardware Configuration
- * field specification for a detailed description of the config
- * field.
- */
-#include <linux/types.h>
-
-#define LASAT_EEPROM_VERSION 7
-struct lasat_eeprom_struct {
-	unsigned int  version;
-	unsigned int  cfg[3];
-	unsigned char hwaddr[6];
-	unsigned char print_partno[12];
-	unsigned char term0;
-	unsigned char print_serial[14];
-	unsigned char term1;
-	unsigned char prod_partno[12];
-	unsigned char term2;
-	unsigned char prod_serial[14];
-	unsigned char term3;
-	unsigned char passwd_hash[16];
-	unsigned char pwdnull;
-	unsigned char vendid;
-	unsigned char ts_ref;
-	unsigned char ts_signoff;
-	unsigned char reserved[11];
-	unsigned char debugaccess;
-	unsigned short prid;
-	unsigned int  serviceflag;
-	unsigned int  ipaddr;
-	unsigned int  netmask;
-	unsigned int  crc32;
-};
-
-struct lasat_eeprom_struct_pre7 {
-	unsigned int  version;
-	unsigned int  flags[3];
-	unsigned char hwaddr0[6];
-	unsigned char hwaddr1[6];
-	unsigned char print_partno[9];
-	unsigned char term0;
-	unsigned char print_serial[14];
-	unsigned char term1;
-	unsigned char prod_partno[9];
-	unsigned char term2;
-	unsigned char prod_serial[14];
-	unsigned char term3;
-	unsigned char passwd_hash[24];
-	unsigned char pwdnull;
-	unsigned char vendor;
-	unsigned char ts_ref;
-	unsigned char ts_signoff;
-	unsigned char reserved[6];
-	unsigned int  writecount;
-	unsigned int  ipaddr;
-	unsigned int  netmask;
-	unsigned int  crc32;
-};
-
-/* Configuration descriptor encoding - see the doc for details */
-
-#define LASAT_W0_DSCTYPE(v)		( ( (v)         ) & 0xf )
-#define LASAT_W0_BMID(v)		( ( (v) >> 0x04 ) & 0xf )
-#define LASAT_W0_CPUTYPE(v)		( ( (v) >> 0x08 ) & 0xf )
-#define LASAT_W0_BUSSPEED(v)		( ( (v) >> 0x0c ) & 0xf )
-#define LASAT_W0_CPUCLK(v)		( ( (v) >> 0x10 ) & 0xf )
-#define LASAT_W0_SDRAMBANKSZ(v)		( ( (v) >> 0x14 ) & 0xf )
-#define LASAT_W0_SDRAMBANKS(v)		( ( (v) >> 0x18 ) & 0xf )
-#define LASAT_W0_L2CACHE(v)		( ( (v) >> 0x1c ) & 0xf )
-
-#define LASAT_W1_EDHAC(v)		( ( (v)         ) & 0xf )
-#define LASAT_W1_HIFN(v)		( ( (v) >> 0x04 ) & 0x1 )
-#define LASAT_W1_ISDN(v)		( ( (v) >> 0x05 ) & 0x1 )
-#define LASAT_W1_IDE(v)			( ( (v) >> 0x06 ) & 0x1 )
-#define LASAT_W1_HDLC(v)		( ( (v) >> 0x07 ) & 0x1 )
-#define LASAT_W1_USVERSION(v)		( ( (v) >> 0x08 ) & 0x1 )
-#define LASAT_W1_4MACS(v)		( ( (v) >> 0x09 ) & 0x1 )
-#define LASAT_W1_EXTSERIAL(v)		( ( (v) >> 0x0a ) & 0x1 )
-#define LASAT_W1_FLASHSIZE(v)		( ( (v) >> 0x0c ) & 0xf )
-#define LASAT_W1_PCISLOTS(v)		( ( (v) >> 0x10 ) & 0xf )
-#define LASAT_W1_PCI1OPT(v)		( ( (v) >> 0x14 ) & 0xf )
-#define LASAT_W1_PCI2OPT(v)		( ( (v) >> 0x18 ) & 0xf )
-#define LASAT_W1_PCI3OPT(v)		( ( (v) >> 0x1c ) & 0xf )
-
-/* Routines specific to LASAT boards */
-
-#define LASAT_BMID_MASQUERADE2		0
-#define LASAT_BMID_MASQUERADEPRO	1
-#define LASAT_BMID_SAFEPIPE25			2
-#define LASAT_BMID_SAFEPIPE50			3
-#define LASAT_BMID_SAFEPIPE100		4
-#define LASAT_BMID_SAFEPIPE5000		5
-#define LASAT_BMID_SAFEPIPE7000		6
-#define LASAT_BMID_SAFEPIPE1000		7
-//#define LASAT_BMID_SAFEPIPE30		7
-//#define LASAT_BMID_SAFEPIPE5100	8
-//#define LASAT_BMID_SAFEPIPE7100	9
-#define LASAT_BMID_UNKNOWN				0xf
-#define LASAT_MAX_BMID_NAMES			9   // no larger than 15!
-
-#define LASAT_HAS_EDHAC			( 1 << 0 )
-#define LASAT_EDHAC_FAST		( 1 << 1 )
-#define LASAT_HAS_EADI			( 1 << 2 )
-#define LASAT_HAS_HIFN			( 1 << 3 )
-#define LASAT_HAS_ISDN			( 1 << 4 )
-#define LASAT_HAS_LEASEDLINE_IF		( 1 << 5 )
-#define LASAT_HAS_HDC			( 1 << 6 )
-
-#define LASAT_PRID_MASQUERADE2		0
-#define LASAT_PRID_MASQUERADEPRO	1
-#define LASAT_PRID_SAFEPIPE25			2
-#define LASAT_PRID_SAFEPIPE50			3
-#define LASAT_PRID_SAFEPIPE100		4
-#define LASAT_PRID_SAFEPIPE5000		5
-#define LASAT_PRID_SAFEPIPE7000		6
-#define LASAT_PRID_SAFEPIPE30			7
-#define LASAT_PRID_SAFEPIPE5100		8
-#define LASAT_PRID_SAFEPIPE7100		9
-
-#define LASAT_PRID_SAFEPIPE1110		10
-#define LASAT_PRID_SAFEPIPE3020		11
-#define LASAT_PRID_SAFEPIPE3030		12
-#define LASAT_PRID_SAFEPIPE5020		13
-#define LASAT_PRID_SAFEPIPE5030		14
-#define LASAT_PRID_SAFEPIPE1120		15
-#define LASAT_PRID_SAFEPIPE1130		16
-#define LASAT_PRID_SAFEPIPE6010		17
-#define LASAT_PRID_SAFEPIPE6110		18
-#define LASAT_PRID_SAFEPIPE6210		19
-#define LASAT_PRID_SAFEPIPE1020		20
-#define LASAT_PRID_SAFEPIPE1040		21
-#define LASAT_PRID_SAFEPIPE1060		22
-
-struct lasat_info {
-	unsigned int  li_cpu_hz;
-	unsigned int  li_bus_hz;
-	unsigned int  li_bmid;
-	unsigned int  li_memsize;
-	unsigned int  li_flash_size;
-	unsigned int  li_prid;
-	unsigned char li_bmstr[16];
-	unsigned char li_namestr[32];
-	unsigned char li_typestr[16];
-	/* Info on the Flash layout */
-	unsigned int  li_flash_base;
-	unsigned long li_flashpart_base[LASAT_MTD_LAST];
-	unsigned long li_flashpart_size[LASAT_MTD_LAST];
-	struct lasat_eeprom_struct li_eeprom_info;
-	unsigned int  li_eeprom_upgrade_version;
-	unsigned int  li_debugaccess;
-};
-
-extern struct lasat_info lasat_board_info;
-
-static inline unsigned long lasat_flash_partition_start(int partno)
-{
-	if (partno < 0 || partno >= LASAT_MTD_LAST)
-		return 0;
-
-	return lasat_board_info.li_flashpart_base[partno];
-}
-
-static inline unsigned long lasat_flash_partition_size(int partno)
-{
-	if (partno < 0 || partno >= LASAT_MTD_LAST)
-		return 0;
-
-	return lasat_board_info.li_flashpart_size[partno];
-}
-
-/* Called from setup() to initialize the global board_info struct */
-extern int lasat_init_board_info(void);
-
-/* Write the modified EEPROM info struct */
-extern void lasat_write_eeprom_info(void);
-
-#define N_MACHTYPES		2
-/* for calibration of delays */
-
-/* the lasat_ndelay function is necessary because it is used at an
- * early stage of the boot process where ndelay is not calibrated.
- * It is used for the bit-banging rtc and eeprom drivers */
-
-#include <asm/delay.h>
-/* calculating with the slowest board with 100 MHz clock */
-#define LASAT_100_DIVIDER 20
-/* All 200's run at 250 MHz clock */
-#define LASAT_200_DIVIDER 8
-
-extern unsigned int lasat_ndelay_divider;
-
-static inline void lasat_ndelay(unsigned int ns)
-{
-            __delay(ns / lasat_ndelay_divider);
-}
-
-#endif /* !defined (_LANGUAGE_ASSEMBLY) */
-
-#define LASAT_SERVICEMODE_MAGIC_1     0xdeadbeef
-#define LASAT_SERVICEMODE_MAGIC_2     0xfedeabba
-
-/* Lasat 100 boards */
-#define LASAT_GT_BASE           (KSEG1ADDR(0x14000000))
-
-/* Lasat 200 boards */
-#define Vrc5074_PHYS_BASE       0x1fa00000
-#define Vrc5074_BASE            (KSEG1ADDR(Vrc5074_PHYS_BASE))
-#define PCI_WINDOW1             0x1a000000
-
-#endif /* _LASAT_H */
diff --git a/include/asm-mips/lasat/lasatint.h b/include/asm-mips/lasat/lasatint.h
deleted file mode 100644
index 065474f..0000000
--- a/include/asm-mips/lasat/lasatint.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#define LASATINT_END 16
-
-/* lasat 100 */
-#define LASAT_INT_STATUS_REG_100	(KSEG1ADDR(0x1c880000))
-#define LASAT_INT_MASK_REG_100		(KSEG1ADDR(0x1c890000))
-#define LASATINT_MASK_SHIFT_100		0
-
-/* lasat 200 */
-#define LASAT_INT_STATUS_REG_200	(KSEG1ADDR(0x1104003c))
-#define LASAT_INT_MASK_REG_200		(KSEG1ADDR(0x1104003c))
-#define LASATINT_MASK_SHIFT_200		16
-
diff --git a/include/asm-mips/lasat/picvue.h b/include/asm-mips/lasat/picvue.h
deleted file mode 100644
index 42a492e..0000000
--- a/include/asm-mips/lasat/picvue.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Lasat 100 */
-#define PVC_REG_100		KSEG1ADDR(0x1c820000)
-#define PVC_DATA_SHIFT_100	0
-#define PVC_DATA_M_100		0xFF
-#define PVC_E_100		(1 << 8)
-#define PVC_RW_100		(1 << 9)
-#define PVC_RS_100		(1 << 10)
-
-/* Lasat 200 */
-#define PVC_REG_200		KSEG1ADDR(0x11000000)
-#define PVC_DATA_SHIFT_200	24
-#define PVC_DATA_M_200		(0xFF << PVC_DATA_SHIFT_200)
-#define PVC_E_200		(1 << 16)
-#define PVC_RW_200		(1 << 17)
-#define PVC_RS_200		(1 << 18)
diff --git a/include/asm-mips/lasat/serial.h b/include/asm-mips/lasat/serial.h
deleted file mode 100644
index 9e88c76..0000000
--- a/include/asm-mips/lasat/serial.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <asm/lasat/lasat.h>
-
-/* Lasat 100 boards serial configuration */
-#define LASAT_BASE_BAUD_100 		( 7372800 / 16 )
-#define LASAT_UART_REGS_BASE_100	0x1c8b0000
-#define LASAT_UART_REGS_SHIFT_100	2
-#define LASATINT_UART_100		8
-
-/* * LASAT 200 boards serial configuration */
-#define LASAT_BASE_BAUD_200		(100000000 / 16 / 12)
-#define LASAT_UART_REGS_BASE_200	(Vrc5074_PHYS_BASE + 0x0300)
-#define LASAT_UART_REGS_SHIFT_200	3
-#define LASATINT_UART_200		13
diff --git a/include/asm-mips/mach-au1x00/au1xxx_gpio.h b/include/asm-mips/mach-au1x00/au1xxx_gpio.h
deleted file mode 100644
index 27911e0..0000000
--- a/include/asm-mips/mach-au1x00/au1xxx_gpio.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __AU1XXX_GPIO_H
-#define __AU1XXX_GPIO_H
-
-void au1xxx_gpio1_set_inputs(void);
-void au1xxx_gpio_tristate(int signal);
-void au1xxx_gpio_write(int signal, int value);
-int  au1xxx_gpio_read(int signal);
-
-typedef volatile struct
-{
-	u32 dir;
-	u32 reserved;
-	u32 output;
-	u32 pinstate;
-	u32 inten;
-	u32 enable;
-
-} AU1X00_GPIO2;
-
-#endif //__AU1XXX_GPIO_H
diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
index 8fcae21..4663e8b 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_ide.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
@@ -88,26 +88,26 @@
 /*
  * Hitachi
  */
-        { "HITACHI_DK14FA-20"    ,       "ALL"           },
-        { "HTS726060M9AT00"      ,       "ALL"           },
+        { "HITACHI_DK14FA-20"    ,       NULL            },
+        { "HTS726060M9AT00"      ,       NULL            },
 /*
  * Maxtor
  */
-        { "Maxtor 6E040L0"      ,       "ALL"           },
-        { "Maxtor 6Y080P0"      ,       "ALL"           },
-        { "Maxtor 6Y160P0"      ,       "ALL"           },
+        { "Maxtor 6E040L0"      ,       NULL            },
+        { "Maxtor 6Y080P0"      ,       NULL            },
+        { "Maxtor 6Y160P0"      ,       NULL            },
 /*
  * Seagate
  */
-        { "ST3120026A"          ,       "ALL"           },
-        { "ST320014A"           ,       "ALL"           },
-        { "ST94011A"            ,       "ALL"           },
-        { "ST340016A"           ,       "ALL"           },
+        { "ST3120026A"          ,       NULL            },
+        { "ST320014A"           ,       NULL            },
+        { "ST94011A"            ,       NULL            },
+        { "ST340016A"           ,       NULL            },
 /*
  * Western Digital
  */
-        { "WDC WD400UE-00HCT0"  ,       "ALL"           },
-        { "WDC WD400JB-00JJC0"  ,       "ALL"           },
+        { "WDC WD400UE-00HCT0"  ,       NULL            },
+        { "WDC WD400JB-00JJC0"  ,       NULL            },
         { NULL                  ,       NULL            }
 };
 
@@ -116,9 +116,9 @@
 /*
  * Western Digital
  */
-        { "WDC WD100EB-00CGH0"  ,       "ALL"           },
-        { "WDC WD200BB-00AUA1"  ,       "ALL"           },
-        { "WDC AC24300L"        ,       "ALL"           },
+        { "WDC WD100EB-00CGH0"  ,       NULL            },
+        { "WDC WD200BB-00AUA1"  ,       NULL            },
+        { "WDC AC24300L"        ,       NULL            },
         { NULL                  ,       NULL            }
 };
 #endif
diff --git a/include/asm-mips/mach-au1x00/gpio.h b/include/asm-mips/mach-au1x00/gpio.h
new file mode 100644
index 0000000..2dc61e0
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/gpio.h
@@ -0,0 +1,69 @@
+#ifndef _AU1XXX_GPIO_H_
+#define _AU1XXX_GPIO_H_
+
+#include <linux/types.h>
+
+#define AU1XXX_GPIO_BASE	200
+
+struct au1x00_gpio2 {
+	u32	dir;
+	u32	reserved;
+	u32	output;
+	u32	pinstate;
+	u32	inten;
+	u32	enable;
+};
+
+extern int au1xxx_gpio_get_value(unsigned gpio);
+extern void au1xxx_gpio_set_value(unsigned gpio, int value);
+extern int au1xxx_gpio_direction_input(unsigned gpio);
+extern int au1xxx_gpio_direction_output(unsigned gpio, int value);
+
+
+/* Wrappers for the arch-neutral GPIO API */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	/* Not yet implemented */
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	/* Not yet implemented */
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	return au1xxx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+	return au1xxx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return au1xxx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	au1xxx_gpio_set_value(gpio, value);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return irq;
+}
+
+/* For cansleep */
+#include <asm-generic/gpio.h>
+
+#endif /* _AU1XXX_GPIO_H_ */
diff --git a/include/asm-mips/mach-au1x00/ioremap.h b/include/asm-mips/mach-au1x00/ioremap.h
index 098fca4..364cea2 100644
--- a/include/asm-mips/mach-au1x00/ioremap.h
+++ b/include/asm-mips/mach-au1x00/ioremap.h
@@ -28,4 +28,15 @@
 	return __fixup_bigphys_addr(phys_addr, size);
 }
 
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return 0;
+}
+
 #endif /* __ASM_MACH_AU1X00_IOREMAP_H */
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
index 684a501..9c9d2b9 100644
--- a/include/asm-mips/mach-cobalt/cobalt.h
+++ b/include/asm-mips/mach-cobalt/cobalt.h
@@ -30,7 +30,6 @@
 #define COBALT_CPU_IRQ		MIPS_CPU_IRQ_BASE
 
 #define COBALT_GALILEO_IRQ	(COBALT_CPU_IRQ + 2)
-#define COBALT_SCC_IRQ          (COBALT_CPU_IRQ + 3)	/* pre-production has 85C30 */
 #define COBALT_RAQ_SCSI_IRQ	(COBALT_CPU_IRQ + 3)
 #define COBALT_ETH0_IRQ		(COBALT_CPU_IRQ + 3)
 #define COBALT_QUBE1_ETH0_IRQ	(COBALT_CPU_IRQ + 4)
@@ -71,10 +70,6 @@
 
 extern int cobalt_board_id;
 
-#define PCI_CFG_SET(devfn,where)					\
-	GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) |		\
-		(PCI_FUNC (devfn) << 8) | (where)))
-
 #define COBALT_LED_PORT		(*(volatile unsigned char *) CKSEG1ADDR(0x1c000000))
 # define COBALT_LED_BAR_LEFT	(1 << 0)	/* Qube */
 # define COBALT_LED_BAR_RIGHT	(1 << 1)	/* Qube */
diff --git a/include/asm-mips/mach-ev64120/mach-gt64120.h b/include/asm-mips/mach-ev64120/mach-gt64120.h
deleted file mode 100644
index 7e272ce5..0000000
--- a/include/asm-mips/mach-ev64120/mach-gt64120.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  This is a direct copy of the ev96100.h file, with a global
- * search and replace.  The numbers are the same.
- *
- *  The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef __ASM_GALILEO_BOARDS_MIPS_EV64120_H
-#define __ASM_GALILEO_BOARDS_MIPS_EV64120_H
-
-/*
- *   GT64120 config space base address
- */
-extern unsigned long gt64120_base;
-
-#define GT64120_BASE	(gt64120_base)
-
-/*
- *   PCI Bus allocation
- */
-#define GT_PCI_MEM_BASE	0x12000000UL
-#define GT_PCI_MEM_SIZE	0x02000000UL
-#define GT_PCI_IO_BASE	0x10000000UL
-#define GT_PCI_IO_SIZE	0x02000000UL
-#define GT_ISA_IO_BASE	PCI_IO_BASE
-
-/*
- *   Duart I/O ports.
- */
-#define EV64120_COM1_BASE_ADDR	(0x1d000000 + 0x20)
-#define EV64120_COM2_BASE_ADDR	(0x1d000000 + 0x00)
-
-
-/*
- *   EV64120 interrupt controller register base.
- */
-#define EV64120_ICTRL_REGS_BASE	(KSEG1ADDR(0x1f000000))
-
-/*
- *   EV64120 UART register base.
- */
-#define EV64120_UART0_REGS_BASE	(KSEG1ADDR(EV64120_COM1_BASE_ADDR))
-#define EV64120_UART1_REGS_BASE	(KSEG1ADDR(EV64120_COM2_BASE_ADDR))
-#define EV64120_BASE_BAUD ( 3686400 / 16 )
-#define EV64120_UART_IRQ	6
-
-/*
- * PCI interrupts will come in on either the INTA or INTD interrups lines,
- * which are mapped to the #2 and #5 interrupt pins of the MIPS.  On our
- * boards, they all either come in on IntD or they all come in on IntA, they
- * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
- * "requested" interrupt numbers and go through the list whenever we get an
- * IntA/D.
- *
- * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and
- * INTD is 11.
- */
-#define GT_TIMER	4
-#define GT_INTA		2
-#define GT_INTD		5
-
-#endif /* __ASM_GALILEO_BOARDS_MIPS_EV64120_H */
diff --git a/include/asm-mips/mach-generic/gpio.h b/include/asm-mips/mach-generic/gpio.h
new file mode 100644
index 0000000..6eaf5ef
--- /dev/null
+++ b/include/asm-mips/mach-generic/gpio.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_MACH_GENERIC_GPIO_H
+#define __ASM_MACH_GENERIC_GPIO_H
+
+int gpio_request(unsigned gpio, const char *label);
+void gpio_free(unsigned gpio);
+int gpio_direction_input(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+int gpio_to_irq(unsigned gpio);
+int irq_to_gpio(unsigned irq);
+
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/include/asm-mips/mach-generic/ioremap.h b/include/asm-mips/mach-generic/ioremap.h
index 9b64ff6..b379938 100644
--- a/include/asm-mips/mach-generic/ioremap.h
+++ b/include/asm-mips/mach-generic/ioremap.h
@@ -20,4 +20,15 @@
 	return phys_addr;
 }
 
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return 0;
+}
+
 #endif /* __ASM_MACH_GENERIC_IOREMAP_H */
diff --git a/include/asm-mips/mach-generic/spaces.h b/include/asm-mips/mach-generic/spaces.h
index 0ae9997..c9fa4b1 100644
--- a/include/asm-mips/mach-generic/spaces.h
+++ b/include/asm-mips/mach-generic/spaces.h
@@ -10,38 +10,54 @@
 #ifndef _ASM_MACH_GENERIC_SPACES_H
 #define _ASM_MACH_GENERIC_SPACES_H
 
+#include <linux/const.h>
+
+/*
+ * This gives the physical RAM offset.
+ */
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET		_AC(0, UL)
+#endif
 
 #ifdef CONFIG_32BIT
 
-#define CAC_BASE		0x80000000
-#define IO_BASE			0xa0000000
-#define UNCAC_BASE		0xa0000000
-#define MAP_BASE		0xc0000000
+#define CAC_BASE		_AC(0x80000000, UL)
+#define IO_BASE			_AC(0xa0000000, UL)
+#define UNCAC_BASE		_AC(0xa0000000, UL)
 
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET		0x80000000UL
+#ifndef MAP_BASE
+#define MAP_BASE		_AC(0xc0000000, UL)
+#endif
 
 /*
  * Memory above this physical address will be considered highmem.
  */
 #ifndef HIGHMEM_START
-#define HIGHMEM_START		0x20000000UL
+#define HIGHMEM_START		_AC(0x20000000, UL)
 #endif
 
 #endif /* CONFIG_32BIT */
 
 #ifdef CONFIG_64BIT
 
-/*
- * This handles the memory map.
- */
+#ifndef CAC_BASE
 #ifdef CONFIG_DMA_NONCOHERENT
-#define PAGE_OFFSET	0x9800000000000000UL
+#define CAC_BASE		_AC(0x9800000000000000, UL)
 #else
-#define PAGE_OFFSET	0xa800000000000000UL
+#define CAC_BASE		_AC(0xa800000000000000, UL)
+#endif
+#endif
+
+#ifndef IO_BASE
+#define IO_BASE			_AC(0x9000000000000000, UL)
+#endif
+
+#ifndef UNCAC_BASE
+#define UNCAC_BASE		_AC(0x9000000000000000, UL)
+#endif
+
+#ifndef MAP_BASE
+#define MAP_BASE		_AC(0xc000000000000000, UL)
 #endif
 
 /*
@@ -50,22 +66,20 @@
  * in the distant future.  Nobody will care for a few years :-)
  */
 #ifndef HIGHMEM_START
-#define HIGHMEM_START		(1UL << 59UL)
+#define HIGHMEM_START		(_AC(1, UL) << _AC(59, UL))
 #endif
 
-#ifdef CONFIG_DMA_NONCOHERENT
-#define CAC_BASE		0x9800000000000000UL
-#else
-#define CAC_BASE		0xa800000000000000UL
-#endif
-#define IO_BASE			0x9000000000000000UL
-#define UNCAC_BASE		0x9000000000000000UL
-#define MAP_BASE		0xc000000000000000UL
-
 #define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
 #define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
 #define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
 
 #endif /* CONFIG_64BIT */
 
+/*
+ * This handles the memory map.
+ */
+#ifndef PAGE_OFFSET
+#define PAGE_OFFSET		(CAC_BASE + PHYS_OFFSET)
+#endif
+
 #endif /* __ASM_MACH_GENERIC_SPACES_H */
diff --git a/include/asm-mips/mach-ip22/spaces.h b/include/asm-mips/mach-ip22/spaces.h
index ab20c02..7f9fa6f 100644
--- a/include/asm-mips/mach-ip22/spaces.h
+++ b/include/asm-mips/mach-ip22/spaces.h
@@ -11,44 +11,17 @@
 #define _ASM_MACH_IP22_SPACES_H
 
 
-#ifdef CONFIG_32BIT
-
-#define CAC_BASE		0x80000000
-#define IO_BASE			0xa0000000
-#define UNCAC_BASE		0xa0000000
-#define MAP_BASE		0xc0000000
-
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET		0x80000000UL
-
-/*
- * Memory above this physical address will be considered highmem.
- */
-#ifndef HIGHMEM_START
-#define HIGHMEM_START		0x20000000UL
-#endif
-
-#endif /* CONFIG_32BIT */
-
 #ifdef CONFIG_64BIT
-#define PAGE_OFFSET		0xffffffff80000000UL
 
-#ifndef HIGHMEM_START
-#define HIGHMEM_START		(1UL << 59UL)
-#endif
+#define PAGE_OFFSET		0xffffffff80000000UL
 
 #define CAC_BASE		0xffffffff80000000
 #define IO_BASE			0xffffffffa0000000
 #define UNCAC_BASE		0xffffffffa0000000
 #define MAP_BASE		0xc000000000000000
 
-#define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
-#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
-
 #endif /* CONFIG_64BIT */
 
+#include <asm/mach-generic/spaces.h>
+
 #endif /* __ASM_MACH_IP22_SPACES_H */
diff --git a/include/asm-mips/mach-ip27/spaces.h b/include/asm-mips/mach-ip27/spaces.h
index 45e6178..b18802a 100644
--- a/include/asm-mips/mach-ip27/spaces.h
+++ b/include/asm-mips/mach-ip27/spaces.h
@@ -14,22 +14,17 @@
  * IP27 uses the R10000's uncached attribute feature.  Attribute 3 selects
  * uncached memory addressing.
  */
-#define CAC_BASE		0xa800000000000000
 
 #define HSPEC_BASE		0x9000000000000000
 #define IO_BASE			0x9200000000000000
 #define MSPEC_BASE		0x9400000000000000
 #define UNCAC_BASE		0x9600000000000000
-#define MAP_BASE		0xc000000000000000
 
-#define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
-#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
 #define TO_MSPEC(x)		(MSPEC_BASE | ((x) & TO_PHYS_MASK))
 #define TO_HSPEC(x)		(HSPEC_BASE | ((x) & TO_PHYS_MASK))
 
-#define PAGE_OFFSET		CAC_BASE
-
 #define HIGHMEM_START		(~0UL)
 
+#include <asm/mach-generic/spaces.h>
+
 #endif /* _ASM_MACH_IP27_SPACES_H */
diff --git a/include/asm-mips/mach-ip32/dma-coherence.h b/include/asm-mips/mach-ip32/dma-coherence.h
index c3f9a6a..a5511eb 100644
--- a/include/asm-mips/mach-ip32/dma-coherence.h
+++ b/include/asm-mips/mach-ip32/dma-coherence.h
@@ -6,8 +6,8 @@
  * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
  *
  */
-#ifndef __ASM_MACH_IP35_DMA_COHERENCE_H
-#define __ASM_MACH_IP35_DMA_COHERENCE_H
+#ifndef __ASM_MACH_IP32_DMA_COHERENCE_H
+#define __ASM_MACH_IP32_DMA_COHERENCE_H
 
 #include <asm/ip32/crime.h>
 
@@ -69,4 +69,4 @@
 	return 0;		/* IP32 is non-cohernet */
 }
 
-#endif /* __ASM_MACH_IP35_DMA_COHERENCE_H */
+#endif /* __ASM_MACH_IP32_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-ip32/spaces.h b/include/asm-mips/mach-ip32/spaces.h
deleted file mode 100644
index 44abe5c..0000000
--- a/include/asm-mips/mach-ip32/spaces.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1999, 2000, 03, 04, 05 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2000, 2002  Maciej W. Rozycki
- * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef _ASM_MACH_IP32_SPACES_H
-#define _ASM_MACH_IP32_SPACES_H
-
-/*
- * Memory above this physical address will be considered highmem.
- * Fixme: 59 bits is a fictive number and makes assumptions about processors
- * in the distant future.  Nobody will care for a few years :-)
- */
-#ifndef HIGHMEM_START
-#define HIGHMEM_START		(1UL << 59UL)
-#endif
-
-#define CAC_BASE		0x9800000000000000UL
-#define IO_BASE			0x9000000000000000UL
-#define UNCAC_BASE		0x9000000000000000UL
-#define MAP_BASE		0xc000000000000000UL
-
-#define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
-#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
-
-/*
- * This handles the memory map.
- */
-#define PAGE_OFFSET		CAC_BASE
-
-#endif /* __ASM_MACH_IP32_SPACES_H */
diff --git a/include/asm-mips/mach-jmr3927/ioremap.h b/include/asm-mips/mach-jmr3927/ioremap.h
new file mode 100644
index 0000000..aa131ad
--- /dev/null
+++ b/include/asm-mips/mach-jmr3927/ioremap.h
@@ -0,0 +1,38 @@
+/*
+ *	include/asm-mips/mach-jmr3927/ioremap.h
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_JMR3927_IOREMAP_H
+#define __ASM_MACH_JMR3927_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+#define TXX9_DIRECTMAP_BASE	0xff000000ul
+	if (offset >= TXX9_DIRECTMAP_BASE &&
+	    offset < TXX9_DIRECTMAP_BASE + 0xf0000)
+		return (void __iomem *)offset;
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= TXX9_DIRECTMAP_BASE;
+}
+
+#endif /* __ASM_MACH_JMR3927_IOREMAP_H */
diff --git a/include/asm-mips/mach-lasat/mach-gt64120.h b/include/asm-mips/mach-lasat/mach-gt64120.h
deleted file mode 100644
index 1a9ad45..0000000
--- a/include/asm-mips/mach-lasat/mach-gt64120.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  This is a direct copy of the ev96100.h file, with a global
- * search and replace.  The numbers are the same.
- *
- *  The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef _ASM_GT64120_LASAT_GT64120_DEP_H
-#define _ASM_GT64120_LASAT_GT64120_DEP_H
-
-/*
- *   GT64120 config space base address on Lasat 100
- */
-#define GT64120_BASE	(KSEG1ADDR(0x14000000))
-
-/*
- *   PCI Bus allocation
- *
- *   (Guessing ...)
- */
-#define GT_PCI_MEM_BASE	0x12000000UL
-#define GT_PCI_MEM_SIZE	0x02000000UL
-#define GT_PCI_IO_BASE	0x10000000UL
-#define GT_PCI_IO_SIZE	0x02000000UL
-#define GT_ISA_IO_BASE	PCI_IO_BASE
-
-#endif /* _ASM_GT64120_LASAT_GT64120_DEP_H */
diff --git a/include/asm-mips/mach-lemote/dma-coherence.h b/include/asm-mips/mach-lemote/dma-coherence.h
new file mode 100644
index 0000000..7e91477
--- /dev/null
+++ b/include/asm-mips/mach-lemote/dma-coherence.h
@@ -0,0 +1,42 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006, 07  Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ */
+#ifndef __ASM_MACH_LEMOTE_DMA_COHERENCE_H
+#define __ASM_MACH_LEMOTE_DMA_COHERENCE_H
+
+struct device;
+
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
+					  size_t size)
+{
+	return virt_to_phys(addr) | 0x80000000;
+}
+
+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
+					       struct page *page)
+{
+	return page_to_phys(page) | 0x80000000;
+}
+
+static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+	return dma_addr & 0x7fffffff;
+}
+
+static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+	return 0;
+}
+
+#endif /* __ASM_MACH_LEMOTE_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-lemote/mc146818rtc.h b/include/asm-mips/mach-lemote/mc146818rtc.h
new file mode 100644
index 0000000..ed5147e
--- /dev/null
+++ b/include/asm-mips/mach-lemote/mc146818rtc.h
@@ -0,0 +1,36 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03, 07 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * RTC routines for PC style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_LEMOTE_MC146818RTC_H
+#define __ASM_MACH_LEMOTE_MC146818RTC_H
+
+#include <linux/io.h>
+
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_IRQ		8
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	return inb_p(RTC_PORT(1));
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	outb_p(data, RTC_PORT(1));
+}
+
+#define RTC_ALWAYS_BCD	0
+
+#ifndef mc146818_decode_year
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
+#endif
+
+#endif /* __ASM_MACH_LEMOTE_MC146818RTC_H */
diff --git a/include/asm-mips/mach-mips/kernel-entry-init.h b/include/asm-mips/mach-mips/kernel-entry-init.h
new file mode 100644
index 0000000..0b793e7
--- /dev/null
+++ b/include/asm-mips/mach-mips/kernel-entry-init.h
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Chris Dearman (chris@mips.com)
+ * Copyright (C) 2007 Mips Technologies, Inc.
+ */
+#ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+
+	.macro	kernel_entry_setup
+#ifdef CONFIG_MIPS_MT_SMTC
+	mfc0	t0, CP0_CONFIG
+	bgez	t0, 9f
+	mfc0	t0, CP0_CONFIG, 1
+	bgez	t0, 9f
+	mfc0	t0, CP0_CONFIG, 2
+	bgez	t0, 9f
+	mfc0	t0, CP0_CONFIG, 3
+	and	t0, 1<<2
+	bnez	t0, 0f
+9:
+	/* Assume we came from YAMON... */
+	PTR_LA	v0, 0x9fc00534	/* YAMON print */
+	lw	v0, (v0)
+	move	a0, zero
+	PTR_LA	a1, nonmt_processor
+	jal	v0
+
+	PTR_LA	v0, 0x9fc00520	/* YAMON exit */
+	lw	v0, (v0)
+	li	a0, 1
+	jal	v0
+
+1:	b	1b
+
+	__INITDATA
+nonmt_processor:
+	.asciz	"SMTC kernel requires the MT ASE to run\n"
+	__FINIT
+0:
+#endif
+	.endm
+
+/*
+ * Do SMP slave processor setup necessary before we can safely execute C code.
+ */
+	.macro	smp_slave_setup
+	.endm
+
+#endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */
diff --git a/include/asm-mips/mach-sim/cpu-feature-overrides.h b/include/asm-mips/mach-mipssim/cpu-feature-overrides.h
similarity index 100%
rename from include/asm-mips/mach-sim/cpu-feature-overrides.h
rename to include/asm-mips/mach-mipssim/cpu-feature-overrides.h
diff --git a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
deleted file mode 100644
index 57a12de..0000000
--- a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- * Copyright (C) 2004 Ralf Baechle
- */
-#ifndef __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Momentum Ocelot-3 is based on Rm7900 processor which
- * is based on the E9000 core.
- */
-#define cpu_has_watch		1
-#define cpu_has_mips16		0
-#define cpu_has_divec		0
-#define cpu_has_vce		0
-#define cpu_has_cache_cdex_p	0
-#define cpu_has_cache_cdex_s	0
-#define cpu_has_prefetch	1
-#define cpu_has_mcheck		0
-#define cpu_has_ejtag		0
-
-#define cpu_has_llsc		1
-#define cpu_has_vtag_icache	0
-#define cpu_has_dc_aliases	0
-#define cpu_has_ic_fills_f_dc	0
-#define cpu_has_dsp		0
-#define cpu_icache_snoops_remote_store	0
-
-#define cpu_has_nofpuex 	0
-#define cpu_has_64bits		1
-
-#define cpu_has_inclusive_pcaches	0
-
-#define cpu_dcache_line_size()	32
-#define cpu_icache_line_size()	32
-#define cpu_scache_line_size()	32
-
-#define cpu_has_mips32r1	0
-#define cpu_has_mips32r2	0
-#define cpu_has_mips64r1	0
-#define cpu_has_mips64r2	0
-
-#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-tx49xx/ioremap.h b/include/asm-mips/mach-tx49xx/ioremap.h
new file mode 100644
index 0000000..1e7beae
--- /dev/null
+++ b/include/asm-mips/mach-tx49xx/ioremap.h
@@ -0,0 +1,43 @@
+/*
+ *	include/asm-mips/mach-tx49xx/ioremap.h
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_TX49XX_IOREMAP_H
+#define __ASM_MACH_TX49XX_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+#ifdef CONFIG_64BIT
+#define TXX9_DIRECTMAP_BASE	0xfff000000ul
+#else
+#define TXX9_DIRECTMAP_BASE	0xff000000ul
+#endif
+	if (offset >= TXX9_DIRECTMAP_BASE &&
+	    offset < TXX9_DIRECTMAP_BASE + 0x400000)
+		return (void __iomem *)(unsigned long)(int)offset;
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >=
+		(unsigned long)(int)(TXX9_DIRECTMAP_BASE & 0xffffffff);
+}
+
+#endif /* __ASM_MACH_TX49XX_IOREMAP_H */
diff --git a/include/asm-mips/mips-boards/atlasint.h b/include/asm-mips/mips-boards/atlasint.h
index 76add42..93ba1c1 100644
--- a/include/asm-mips/mips-boards/atlasint.h
+++ b/include/asm-mips/mips-boards/atlasint.h
@@ -28,11 +28,6 @@
 
 #include <irq.h>
 
-/*
- * Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode)
- */
-#define MIPSCPU_INT_BASE	MIPS_CPU_IRQ_BASE
-
 /* CPU interrupt offsets */
 #define MIPSCPU_INT_SW0		0
 #define MIPSCPU_INT_SW1		1
@@ -42,7 +37,6 @@
 #define MIPSCPU_INT_MB2		4
 #define MIPSCPU_INT_MB3		5
 #define MIPSCPU_INT_MB4		6
-#define MIPSCPU_INT_CPUCTR	7
 
 /*
  * Interrupts 8..39 are used for Atlas interrupt controller interrupts
diff --git a/include/asm-mips/mips-boards/bonito64.h b/include/asm-mips/mips-boards/bonito64.h
index cd71256..dc3fc32 100644
--- a/include/asm-mips/mips-boards/bonito64.h
+++ b/include/asm-mips/mips-boards/bonito64.h
@@ -26,7 +26,12 @@
 /* offsets from base register */
 #define BONITO(x)	(x)
 
-#else /* !__ASSEMBLY__ */
+#elif defined(CONFIG_LEMOTE_FULONG)
+
+#define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x)))
+#define BONITO_IRQ_BASE   32
+
+#else
 
 /*
  * Algorithmics Bonito64 system controller register base.
diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
index b98f165..c8ebcc3 100644
--- a/include/asm-mips/mips-boards/generic.h
+++ b/include/asm-mips/mips-boards/generic.h
@@ -73,12 +73,28 @@
  *  CoreEMUL with   Bonito   System Controller is treated like a Core20K
  *  CoreEMUL with SOC-it 101 System Controller is treated like a CoreMSC
  */
-#define MIPS_REVISION_CORID_CORE_EMUL_BON  0x63
-#define MIPS_REVISION_CORID_CORE_EMUL_MSC  0x65
+#define MIPS_REVISION_CORID_CORE_EMUL_BON  -1
+#define MIPS_REVISION_CORID_CORE_EMUL_MSC  -2
 
 #define MIPS_REVISION_CORID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 10) & 0x3f)
 
-extern unsigned int mips_revision_corid;
+extern int mips_revision_corid;
+
+#define MIPS_REVISION_SCON_OTHER	   0
+#define MIPS_REVISION_SCON_SOCITSC	   1
+#define MIPS_REVISION_SCON_SOCITSCP	   2
+
+/* Artificial SCON defines for MIPS_REVISION_SCON_OTHER */
+#define MIPS_REVISION_SCON_UNKNOWN	   -1
+#define MIPS_REVISION_SCON_GT64120	   -2
+#define MIPS_REVISION_SCON_BONITO	   -3
+#define MIPS_REVISION_SCON_BRTL		   -4
+#define MIPS_REVISION_SCON_SOCIT	   -5
+#define MIPS_REVISION_SCON_ROCIT	   -6
+
+#define MIPS_REVISION_SCONID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 24) & 0xff)
+
+extern int mips_revision_sconid;
 
 #ifdef CONFIG_PCI
 extern void mips_pcibios_init(void);
diff --git a/include/asm-mips/mips-boards/maltaint.h b/include/asm-mips/mips-boards/maltaint.h
index 9180d64..7461318 100644
--- a/include/asm-mips/mips-boards/maltaint.h
+++ b/include/asm-mips/mips-boards/maltaint.h
@@ -32,11 +32,6 @@
  */
 #define MALTA_INT_BASE		0
 
-/*
- * Interrupts 16..23 are used for Malta CPU interrupts (nonEIC mode)
- */
-#define MIPSCPU_INT_BASE	MIPS_CPU_IRQ_BASE
-
 /* CPU interrupt offsets */
 #define MIPSCPU_INT_SW0		0
 #define MIPSCPU_INT_SW1		1
@@ -49,7 +44,6 @@
 #define MIPSCPU_INT_COREHI	MIPSCPU_INT_MB3
 #define MIPSCPU_INT_MB4		6
 #define MIPSCPU_INT_CORELO	MIPSCPU_INT_MB4
-#define MIPSCPU_INT_CPUCTR	7
 
 /*
  * Interrupts 64..127 are used for Soc-it Classic interrupts
diff --git a/include/asm-mips/mips-boards/msc01_pci.h b/include/asm-mips/mips-boards/msc01_pci.h
index 8eaefb8..e036b7d 100644
--- a/include/asm-mips/mips-boards/msc01_pci.h
+++ b/include/asm-mips/mips-boards/msc01_pci.h
@@ -208,6 +208,7 @@
  * latter, they should be moved elsewhere.
  */
 #define MIPS_MSC01_PCI_REG_BASE		0x1bd00000
+#define MIPS_SOCITSC_PCI_REG_BASE	0x1ff10000
 
 extern unsigned long _pcictrl_msc;
 
diff --git a/include/asm-mips/mips-boards/prom.h b/include/asm-mips/mips-boards/prom.h
index daaf9f98..a9db576 100644
--- a/include/asm-mips/mips-boards/prom.h
+++ b/include/asm-mips/mips-boards/prom.h
@@ -33,6 +33,7 @@
 extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
 extern void mips_display_message(const char *str);
 extern void mips_display_word(unsigned int num);
+extern void mips_scroll_message(void);
 extern int get_ethernet_addr(char *ethernet_addr);
 
 /* Memory descriptor management. */
diff --git a/include/asm-mips/mips-boards/seadint.h b/include/asm-mips/mips-boards/seadint.h
index 4f6a393..e710bae 100644
--- a/include/asm-mips/mips-boards/seadint.h
+++ b/include/asm-mips/mips-boards/seadint.h
@@ -22,14 +22,7 @@
 
 #include <irq.h>
 
-/*
- * Interrupts 0..7 are used for SEAD CPU interrupts
- */
-#define MIPSCPU_INT_BASE	MIPS_CPU_IRQ_BASE
-
 #define MIPSCPU_INT_UART0	2
 #define MIPSCPU_INT_UART1	3
 
-#define MIPSCPU_INT_CPUCTR	7
-
 #endif /* !(_MIPS_SEADINT_H) */
diff --git a/include/asm-mips/mips-boards/simint.h b/include/asm-mips/mips-boards/simint.h
index 54f2fe6..8ef6db7 100644
--- a/include/asm-mips/mips-boards/simint.h
+++ b/include/asm-mips/mips-boards/simint.h
@@ -21,15 +21,11 @@
 
 #define SIM_INT_BASE		0
 #define MIPSCPU_INT_MB0		2
-#define MIPSCPU_INT_BASE	MIPS_CPU_IRQ_BASE
 #define MIPS_CPU_TIMER_IRQ	7
 
 
-#define MIPSCPU_INT_CPUCTR	7
-
 #define MSC01E_INT_BASE		64
 
-#define MIPSCPU_INT_CPUCTR	7
 #define MSC01E_INT_CPUCTR	11
 
 #endif
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 9985cb7..18f47f1 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -7,7 +7,7 @@
  * Copyright (C) 2000 Silicon Graphics, Inc.
  * Modified for further R[236]000 support by Paul M. Antoine, 1996.
  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2000, 07 MIPS Technologies, Inc.
  * Copyright (C) 2003, 2004  Maciej W. Rozycki
  */
 #ifndef _ASM_MIPSREGS_H
@@ -15,6 +15,7 @@
 
 #include <linux/linkage.h>
 #include <asm/hazards.h>
+#include <asm/war.h>
 
 /*
  * The following macros are especially useful for __asm__
@@ -533,6 +534,12 @@
 #define MIPS_CONF3_VEIC		(_ULCAST_(1) <<  6)
 #define MIPS_CONF3_LPA		(_ULCAST_(1) <<  7)
 #define MIPS_CONF3_DSP		(_ULCAST_(1) << 10)
+#define MIPS_CONF3_ULRI		(_ULCAST_(1) << 13)
+
+#define MIPS_CONF7_WII		(_ULCAST_(1) << 31)
+
+#define MIPS_CONF7_RPS		(_ULCAST_(1) << 2)
+
 
 /*
  * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
@@ -700,10 +707,10 @@
  */
 #define __read_64bit_c0_split(source, sel)				\
 ({									\
-	unsigned long long val;						\
-	unsigned long flags;						\
+	unsigned long long __val;					\
+	unsigned long __flags;						\
 									\
-	local_irq_save(flags);						\
+	local_irq_save(__flags);					\
 	if (sel == 0)							\
 		__asm__ __volatile__(					\
 			".set\tmips64\n\t"				\
@@ -712,7 +719,7 @@
 			"dsrl\t%M0, %M0, 32\n\t"			\
 			"dsrl\t%L0, %L0, 32\n\t"			\
 			".set\tmips0"					\
-			: "=r" (val));					\
+			: "=r" (__val));				\
 	else								\
 		__asm__ __volatile__(					\
 			".set\tmips64\n\t"				\
@@ -721,17 +728,17 @@
 			"dsrl\t%M0, %M0, 32\n\t"			\
 			"dsrl\t%L0, %L0, 32\n\t"			\
 			".set\tmips0"					\
-			: "=r" (val));					\
-	local_irq_restore(flags);					\
+			: "=r" (__val));				\
+	local_irq_restore(__flags);					\
 									\
-	val;								\
+	__val;								\
 })
 
 #define __write_64bit_c0_split(source, sel, val)			\
 do {									\
-	unsigned long flags;						\
+	unsigned long __flags;						\
 									\
-	local_irq_save(flags);						\
+	local_irq_save(__flags);					\
 	if (sel == 0)							\
 		__asm__ __volatile__(					\
 			".set\tmips64\n\t"				\
@@ -752,7 +759,7 @@
 			"dmtc0\t%L0, " #source ", " #sel "\n\t"		\
 			".set\tmips0"					\
 			: : "r" (val));					\
-	local_irq_restore(flags);					\
+	local_irq_restore(__flags);					\
 } while (0)
 
 #define read_c0_index()		__read_32bit_c0_register($0, 0)
@@ -770,6 +777,9 @@
 #define read_c0_context()	__read_ulong_c0_register($4, 0)
 #define write_c0_context(val)	__write_ulong_c0_register($4, 0, val)
 
+#define read_c0_userlocal()	__read_ulong_c0_register($4, 2)
+#define write_c0_userlocal(val)	__write_ulong_c0_register($4, 2, val)
+
 #define read_c0_pagemask()	__read_32bit_c0_register($5, 0)
 #define write_c0_pagemask(val)	__write_32bit_c0_register($5, 0, val)
 
@@ -1292,10 +1302,39 @@
 
 static inline void tlb_read(void)
 {
+#if MIPS34K_MISSED_ITLB_WAR
+	int res = 0;
+
+	__asm__ __volatile__(
+	"	.set	push					\n"
+	"	.set	noreorder				\n"
+	"	.set	noat					\n"
+	"	.set	mips32r2				\n"
+	"	.word	0x41610001		# dvpe $1	\n"
+	"	move	%0, $1					\n"
+	"	ehb						\n"
+	"	.set	pop					\n"
+	: "=r" (res));
+
+	instruction_hazard();
+#endif
+
 	__asm__ __volatile__(
 		".set noreorder\n\t"
 		"tlbr\n\t"
 		".set reorder");
+
+#if MIPS34K_MISSED_ITLB_WAR
+	if ((res & _ULCAST_(1)))
+		__asm__ __volatile__(
+		"	.set	push				\n"
+		"	.set	noreorder			\n"
+		"	.set	noat				\n"
+		"	.set	mips32r2			\n"
+		"	.word	0x41600021	# evpe		\n"
+		"	ehb					\n"
+		"	.set	pop				\n");
+#endif
 }
 
 static inline void tlb_write_indexed(void)
diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h
index 399d03f..de6d09e 100644
--- a/include/asm-mips/module.h
+++ b/include/asm-mips/module.h
@@ -112,6 +112,8 @@
 #define MODULE_PROC_FAMILY "RM9000 "
 #elif defined CONFIG_CPU_SB1
 #define MODULE_PROC_FAMILY "SB1 "
+#elif defined CONFIG_CPU_LOONGSON2
+#define MODULE_PROC_FAMILY "LOONGSON2 "
 #else
 #error MODULE_PROC_FAMILY undefined for your processor configuration
 #endif
@@ -122,6 +124,13 @@
 #define MODULE_KERNEL_TYPE "64BIT "
 #endif
 
-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_KERNEL_TYPE
+#ifdef CONFIG_MIPS_MT_SMTC
+#define MODULE_KERNEL_SMTC "MT_SMTC "
+#else
+#define MODULE_KERNEL_SMTC ""
+#endif
+
+#define MODULE_ARCH_VERMAGIC \
+	MODULE_PROC_FAMILY MODULE_KERNEL_TYPE MODULE_KERNEL_SMTC
 
 #endif /* _ASM_MODULE_H */
diff --git a/include/asm-mips/nile4.h b/include/asm-mips/nile4.h
deleted file mode 100644
index c3ca959..0000000
--- a/include/asm-mips/nile4.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- *  asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  This file is based on the following documentation:
- *
- *	NEC Vrc 5074 System Controller Data Sheet, June 1998
- */
-
-#ifndef _ASM_NILE4_H
-#define _ASM_NILE4_H
-
-#define NILE4_BASE		0xbfa00000
-#define NILE4_SIZE		0x00200000		/* 2 MB */
-
-
-    /*
-     *  Physical Device Address Registers (PDARs)
-     */
-
-#define NILE4_SDRAM0	0x0000	/* SDRAM Bank 0 [R/W] */
-#define NILE4_SDRAM1	0x0008	/* SDRAM Bank 1 [R/W] */
-#define NILE4_DCS2	0x0010	/* Device Chip-Select 2 [R/W] */
-#define NILE4_DCS3	0x0018	/* Device Chip-Select 3 [R/W] */
-#define NILE4_DCS4	0x0020	/* Device Chip-Select 4 [R/W] */
-#define NILE4_DCS5	0x0028	/* Device Chip-Select 5 [R/W] */
-#define NILE4_DCS6	0x0030	/* Device Chip-Select 6 [R/W] */
-#define NILE4_DCS7	0x0038	/* Device Chip-Select 7 [R/W] */
-#define NILE4_DCS8	0x0040	/* Device Chip-Select 8 [R/W] */
-#define NILE4_PCIW0	0x0060	/* PCI Address Window 0 [R/W] */
-#define NILE4_PCIW1	0x0068	/* PCI Address Window 1 [R/W] */
-#define NILE4_INTCS	0x0070	/* Controller Internal Registers and Devices */
-				/* [R/W] */
-#define NILE4_BOOTCS	0x0078	/* Boot ROM Chip-Select [R/W] */
-
-
-    /*
-     *  CPU Interface Registers
-     */
-
-#define NILE4_CPUSTAT	0x0080	/* CPU Status [R/W] */
-#define NILE4_INTCTRL	0x0088	/* Interrupt Control [R/W] */
-#define NILE4_INTSTAT0	0x0090	/* Interrupt Status 0 [R] */
-#define NILE4_INTSTAT1	0x0098	/* Interrupt Status 1 and CPU Interrupt */
-				/* Enable [R/W] */
-#define NILE4_INTCLR	0x00A0	/* Interrupt Clear [R/W] */
-#define NILE4_INTPPES	0x00A8	/* PCI Interrupt Control [R/W] */
-
-
-    /*
-     *  Memory-Interface Registers
-     */
-
-#define NILE4_MEMCTRL	0x00C0	/* Memory Control */
-#define NILE4_ACSTIME	0x00C8	/* Memory Access Timing [R/W] */
-#define NILE4_CHKERR	0x00D0	/* Memory Check Error Status [R] */
-
-
-    /*
-     *  PCI-Bus Registers
-     */
-
-#define NILE4_PCICTRL	0x00E0	/* PCI Control [R/W] */
-#define NILE4_PCIARB	0x00E8	/* PCI Arbiter [R/W] */
-#define NILE4_PCIINIT0	0x00F0	/* PCI Master (Initiator) 0 [R/W] */
-#define NILE4_PCIINIT1	0x00F8	/* PCI Master (Initiator) 1 [R/W] */
-#define NILE4_PCIERR	0x00B8	/* PCI Error [R/W] */
-
-
-    /*
-     *  Local-Bus Registers
-     */
-
-#define NILE4_LCNFG	0x0100	/* Local Bus Configuration [R/W] */
-#define NILE4_LCST2	0x0110	/* Local Bus Chip-Select Timing 2 [R/W] */
-#define NILE4_LCST3	0x0118	/* Local Bus Chip-Select Timing 3 [R/W] */
-#define NILE4_LCST4	0x0120	/* Local Bus Chip-Select Timing 4 [R/W] */
-#define NILE4_LCST5	0x0128	/* Local Bus Chip-Select Timing 5 [R/W] */
-#define NILE4_LCST6	0x0130	/* Local Bus Chip-Select Timing 6 [R/W] */
-#define NILE4_LCST7	0x0138	/* Local Bus Chip-Select Timing 7 [R/W] */
-#define NILE4_LCST8	0x0140	/* Local Bus Chip-Select Timing 8 [R/W] */
-#define NILE4_DCSFN	0x0150	/* Device Chip-Select Muxing and Output */
-				/* Enables [R/W] */
-#define NILE4_DCSIO	0x0158	/* Device Chip-Selects As I/O Bits [R/W] */
-#define NILE4_BCST	0x0178	/* Local Boot Chip-Select Timing [R/W] */
-
-
-    /*
-     *  DMA Registers
-     */
-
-#define NILE4_DMACTRL0	0x0180	/* DMA Control 0 [R/W] */
-#define NILE4_DMASRCA0	0x0188	/* DMA Source Address 0 [R/W] */
-#define NILE4_DMADESA0	0x0190	/* DMA Destination Address 0 [R/W] */
-#define NILE4_DMACTRL1	0x0198	/* DMA Control 1 [R/W] */
-#define NILE4_DMASRCA1	0x01A0	/* DMA Source Address 1 [R/W] */
-#define NILE4_DMADESA1	0x01A8	/* DMA Destination Address 1 [R/W] */
-
-
-    /*
-     *  Timer Registers
-     */
-
-#define NILE4_T0CTRL	0x01C0	/* SDRAM Refresh Control [R/W] */
-#define NILE4_T0CNTR	0x01C8	/* SDRAM Refresh Counter [R/W] */
-#define NILE4_T1CTRL	0x01D0	/* CPU-Bus Read Time-Out Control [R/W] */
-#define NILE4_T1CNTR	0x01D8	/* CPU-Bus Read Time-Out Counter [R/W] */
-#define NILE4_T2CTRL	0x01E0	/* General-Purpose Timer Control [R/W] */
-#define NILE4_T2CNTR	0x01E8	/* General-Purpose Timer Counter [R/W] */
-#define NILE4_T3CTRL	0x01F0	/* Watchdog Timer Control [R/W] */
-#define NILE4_T3CNTR	0x01F8	/* Watchdog Timer Counter [R/W] */
-
-
-    /*
-     *  PCI Configuration Space Registers
-     */
-
-#define NILE4_PCI_BASE	0x0200
-
-#define NILE4_VID	0x0200	/* PCI Vendor ID [R] */
-#define NILE4_DID	0x0202	/* PCI Device ID [R] */
-#define NILE4_PCICMD	0x0204	/* PCI Command [R/W] */
-#define NILE4_PCISTS	0x0206	/* PCI Status [R/W] */
-#define NILE4_REVID	0x0208	/* PCI Revision ID [R] */
-#define NILE4_CLASS	0x0209	/* PCI Class Code [R] */
-#define NILE4_CLSIZ	0x020C	/* PCI Cache Line Size [R/W] */
-#define NILE4_MLTIM	0x020D	/* PCI Latency Timer [R/W] */
-#define NILE4_HTYPE	0x020E	/* PCI Header Type [R] */
-#define NILE4_BIST	0x020F	/* BIST [R] (unimplemented) */
-#define NILE4_BARC	0x0210	/* PCI Base Address Register Control [R/W] */
-#define NILE4_BAR0	0x0218	/* PCI Base Address Register 0 [R/W] */
-#define NILE4_BAR1	0x0220	/* PCI Base Address Register 1 [R/W] */
-#define NILE4_CIS	0x0228	/* PCI Cardbus CIS Pointer [R] */
-				/* (unimplemented) */
-#define NILE4_SSVID	0x022C	/* PCI Sub-System Vendor ID [R/W] */
-#define NILE4_SSID	0x022E	/* PCI Sub-System ID [R/W] */
-#define NILE4_ROM	0x0230	/* Expansion ROM Base Address [R] */
-				/* (unimplemented) */
-#define NILE4_INTLIN	0x023C	/* PCI Interrupt Line [R/W] */
-#define NILE4_INTPIN	0x023D	/* PCI Interrupt Pin [R] */
-#define NILE4_MINGNT	0x023E	/* PCI Min_Gnt [R] (unimplemented) */
-#define NILE4_MAXLAT	0x023F	/* PCI Max_Lat [R] (unimplemented) */
-#define NILE4_BAR2	0x0240	/* PCI Base Address Register 2 [R/W] */
-#define NILE4_BAR3	0x0248	/* PCI Base Address Register 3 [R/W] */
-#define NILE4_BAR4	0x0250	/* PCI Base Address Register 4 [R/W] */
-#define NILE4_BAR5	0x0258	/* PCI Base Address Register 5 [R/W] */
-#define NILE4_BAR6	0x0260	/* PCI Base Address Register 6 [R/W] */
-#define NILE4_BAR7	0x0268	/* PCI Base Address Register 7 [R/W] */
-#define NILE4_BAR8	0x0270	/* PCI Base Address Register 8 [R/W] */
-#define NILE4_BARB	0x0278	/* PCI Base Address Register BOOT [R/W] */
-
-
-    /*
-     *  Serial-Port Registers
-     */
-
-#define NILE4_UART_BASE	0x0300
-
-#define NILE4_UARTRBR	0x0300	/* UART Receiver Data Buffer [R] */
-#define NILE4_UARTTHR	0x0300	/* UART Transmitter Data Holding [W] */
-#define NILE4_UARTIER	0x0308	/* UART Interrupt Enable [R/W] */
-#define NILE4_UARTDLL	0x0300	/* UART Divisor Latch LSB [R/W] */
-#define NILE4_UARTDLM	0x0308	/* UART Divisor Latch MSB [R/W] */
-#define NILE4_UARTIIR	0x0310	/* UART Interrupt ID [R] */
-#define NILE4_UARTFCR	0x0310	/* UART FIFO Control [W] */
-#define NILE4_UARTLCR	0x0318	/* UART Line Control [R/W] */
-#define NILE4_UARTMCR	0x0320	/* UART Modem Control [R/W] */
-#define NILE4_UARTLSR	0x0328	/* UART Line Status [R/W] */
-#define NILE4_UARTMSR	0x0330	/* UART Modem Status [R/W] */
-#define NILE4_UARTSCR	0x0338	/* UART Scratch [R/W] */
-
-#define NILE4_UART_BASE_BAUD	520833	/* 100 MHz / 12 / 16 */
-
-
-    /*
-     *  Interrupt Lines
-     */
-
-#define NILE4_INT_CPCE	0	/* CPU-Interface Parity-Error Interrupt */
-#define NILE4_INT_CNTD	1	/* CPU No-Target Decode Interrupt */
-#define NILE4_INT_MCE	2	/* Memory-Check Error Interrupt */
-#define NILE4_INT_DMA	3	/* DMA Controller Interrupt */
-#define NILE4_INT_UART	4	/* UART Interrupt */
-#define NILE4_INT_WDOG	5	/* Watchdog Timer Interrupt */
-#define NILE4_INT_GPT	6	/* General-Purpose Timer Interrupt */
-#define NILE4_INT_LBRTD	7	/* Local-Bus Ready Timer Interrupt */
-#define NILE4_INT_INTA	8	/* PCI Interrupt Signal INTA# */
-#define NILE4_INT_INTB	9	/* PCI Interrupt Signal INTB# */
-#define NILE4_INT_INTC	10	/* PCI Interrupt Signal INTC# */
-#define NILE4_INT_INTD	11	/* PCI Interrupt Signal INTD# */
-#define NILE4_INT_INTE	12	/* PCI Interrupt Signal INTE# (ISA cascade) */
-#define NILE4_INT_RESV	13	/* Reserved */
-#define NILE4_INT_PCIS	14	/* PCI SERR# Interrupt */
-#define NILE4_INT_PCIE	15	/* PCI Internal Error Interrupt */
-
-
-    /*
-     *  Nile 4 Register Access
-     */
-
-static inline void nile4_sync(void)
-{
-    volatile u32 *p = (volatile u32 *)0xbfc00000;
-    (void)(*p);
-}
-
-static inline void nile4_out32(u32 offset, u32 val)
-{
-    *(volatile u32 *)(NILE4_BASE+offset) = val;
-    nile4_sync();
-}
-
-static inline u32 nile4_in32(u32 offset)
-{
-    u32 val = *(volatile u32 *)(NILE4_BASE+offset);
-    nile4_sync();
-    return val;
-}
-
-static inline void nile4_out16(u32 offset, u16 val)
-{
-    *(volatile u16 *)(NILE4_BASE+offset) = val;
-    nile4_sync();
-}
-
-static inline u16 nile4_in16(u32 offset)
-{
-    u16 val = *(volatile u16 *)(NILE4_BASE+offset);
-    nile4_sync();
-    return val;
-}
-
-static inline void nile4_out8(u32 offset, u8 val)
-{
-    *(volatile u8 *)(NILE4_BASE+offset) = val;
-    nile4_sync();
-}
-
-static inline u8 nile4_in8(u32 offset)
-{
-    u8 val = *(volatile u8 *)(NILE4_BASE+offset);
-    nile4_sync();
-    return val;
-}
-
-
-    /*
-     *  Physical Device Address Registers
-     */
-
-extern void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
-			   int on_memory_bus, int visible);
-
-
-    /*
-     *  PCI Master Registers
-     */
-
-#define NILE4_PCICMD_IACK	0	/* PCI Interrupt Acknowledge */
-#define NILE4_PCICMD_IO		1	/* PCI I/O Space */
-#define NILE4_PCICMD_MEM	3	/* PCI Memory Space */
-#define NILE4_PCICMD_CFG	5	/* PCI Configuration Space */
-
-
-    /*
-     *  PCI Address Spaces
-     *
-     *  Note that these are multiplexed using PCIINIT[01]!
-     */
-
-#define NILE4_PCI_IO_BASE	0xa6000000
-#define NILE4_PCI_MEM_BASE	0xa8000000
-#define NILE4_PCI_CFG_BASE	NILE4_PCI_MEM_BASE
-#define NILE4_PCI_IACK_BASE	NILE4_PCI_IO_BASE
-
-
-extern void nile4_set_pmr(u32 pmr, u32 type, u32 addr);
-
-
-    /*
-     *  Interrupt Programming
-     */
-
-#define NUM_I8259_INTERRUPTS	16
-#define NUM_NILE4_INTERRUPTS	16
-
-#define IRQ_I8259_CASCADE	NILE4_INT_INTE
-#define is_i8259_irq(irq)	((irq) < NUM_I8259_INTERRUPTS)
-#define nile4_to_irq(n)		((n)+NUM_I8259_INTERRUPTS)
-#define irq_to_nile4(n)		((n)-NUM_I8259_INTERRUPTS)
-
-extern void nile4_map_irq(int nile4_irq, int cpu_irq);
-extern void nile4_map_irq_all(int cpu_irq);
-extern void nile4_enable_irq(unsigned int nile4_irq);
-extern void nile4_disable_irq(unsigned int nile4_irq);
-extern void nile4_disable_irq_all(void);
-extern u16 nile4_get_irq_stat(int cpu_irq);
-extern void nile4_enable_irq_output(int cpu_irq);
-extern void nile4_disable_irq_output(int cpu_irq);
-extern void nile4_set_pci_irq_polarity(int pci_irq, int high);
-extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level);
-extern void nile4_clear_irq(int nile4_irq);
-extern void nile4_clear_irq_mask(u32 mask);
-extern u8 nile4_i8259_iack(void);
-extern void nile4_dump_irq_status(void);	/* Debug */
-
-#endif
-
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 5c3239d..b92dd8c 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -34,12 +34,8 @@
 
 #ifndef __ASSEMBLY__
 
-/*
- * This gives the physical RAM offset.
- */
-#ifndef PHYS_OFFSET
-#define PHYS_OFFSET		0UL
-#endif
+#include <linux/pfn.h>
+#include <asm/io.h>
 
 /*
  * It's normally defined only for FLATMEM config but it's
@@ -48,9 +44,6 @@
  */
 #define ARCH_PFN_OFFSET		PFN_UP(PHYS_OFFSET)
 
-#include <linux/pfn.h>
-#include <asm/io.h>
-
 extern void clear_page(void * page);
 extern void copy_page(void * to, void * from);
 
@@ -150,11 +143,15 @@
  * __pa()/__va() should be used only during mem init.
  */
 #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
-#define __pa_page_offset(x)	((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0)
+#define __pa(x)								\
+({									\
+    unsigned long __x = (unsigned long)(x);				\
+    __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x);			\
+})
 #else
-#define __pa_page_offset(x)	PAGE_OFFSET
+#define __pa(x)								\
+    ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
 #endif
-#define __pa(x)		((unsigned long)(x) - __pa_page_offset(x) + PHYS_OFFSET)
 #define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
 #define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x),0))
 
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 3eea3ba..4fcc185 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -56,7 +56,7 @@
 /*
  * board supplied pci irq fixup routine
  */
-extern int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
+extern int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
 
 /* Can be used to override the logic in pci_scan_bus for skipping
@@ -121,20 +121,6 @@
 
 #endif /* CONFIG_DMA_NEED_PCI_MAP_STATE  */
 
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)	(1)
-
-extern dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-	struct page *page, unsigned long offset, int direction);
-extern struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-	dma64_addr_t dma_addr);
-extern unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-	dma64_addr_t dma_addr);
-extern void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction);
-extern void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction);
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
@@ -181,10 +167,6 @@
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 /* Do platform specific device initialization at pci_enable_device() time */
 extern int pcibios_plat_dev_init(struct pci_dev *dev);
 
diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
index 5685d4f..9fb57c0 100644
--- a/include/asm-mips/pgalloc.h
+++ b/include/asm-mips/pgalloc.h
@@ -11,6 +11,7 @@
 
 #include <linux/highmem.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
 	pte_t *pte)
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 27d77d9..2e2d70d 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -178,9 +178,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_user(pte_t pte)	{ BUG(); return 0; }
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
-static inline int pte_read(pte_t pte)	{ return pte.pte_low & _PAGE_READ; }
 static inline int pte_write(pte_t pte)	{ return pte.pte_low & _PAGE_WRITE; }
 static inline int pte_dirty(pte_t pte)	{ return pte.pte_low & _PAGE_MODIFIED; }
 static inline int pte_young(pte_t pte)	{ return pte.pte_low & _PAGE_ACCESSED; }
@@ -193,13 +191,6 @@
 	return pte;
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-	pte.pte_low  &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-	pte.pte_high &= ~_PAGE_SILENT_READ;
-	return pte;
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte.pte_low  &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
@@ -224,16 +215,6 @@
 	return pte;
 }
 
-static inline pte_t pte_mkread(pte_t pte)
-{
-	pte.pte_low |= _PAGE_READ;
-	if (pte.pte_low & _PAGE_ACCESSED) {
-		pte.pte_low  |= _PAGE_SILENT_READ;
-		pte.pte_high |= _PAGE_SILENT_READ;
-	}
-	return pte;
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	pte.pte_low |= _PAGE_MODIFIED;
@@ -253,7 +234,6 @@
 	return pte;
 }
 #else
-static inline int pte_read(pte_t pte)	{ return pte_val(pte) & _PAGE_READ; }
 static inline int pte_write(pte_t pte)	{ return pte_val(pte) & _PAGE_WRITE; }
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_MODIFIED; }
 static inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
@@ -265,12 +245,6 @@
 	return pte;
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{
-	pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-	return pte;
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
@@ -291,14 +265,6 @@
 	return pte;
 }
 
-static inline pte_t pte_mkread(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_READ;
-	if (pte_val(pte) & _PAGE_ACCESSED)
-		pte_val(pte) |= _PAGE_SILENT_READ;
-	return pte;
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_MODIFIED;
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h
new file mode 100644
index 0000000..c84bcf9
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h
@@ -0,0 +1,151 @@
+/*
+ * Defines for the MSP interrupt controller.
+ *
+ * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_CIC_INT_H
+#define _MSP_CIC_INT_H
+
+/*
+ * The PMC-Sierra CIC interrupts are all centrally managed by the
+ * CIC sub-system.
+ * We attempt to keep the interrupt numbers as consistent as possible
+ * across all of the MSP devices, but some differences will creep in ...
+ * The interrupts which are directly forwarded to the MIPS core interrupts
+ * are assigned interrupts in the range 0-7, interrupts cascaded through
+ * the CIC are assigned interrupts 8-39.  The cascade occurs on C_IRQ4
+ * (MSP_INT_CIC).  Currently we don't really distinguish between VPE1
+ * and VPE0 (or thread contexts for that matter).  Will have to fix.
+ * The PER interrupts are assigned interrupts in the range 40-71.
+*/
+
+
+/*
+ * IRQs directly forwarded to the CPU
+ */
+#define MSP_MIPS_INTBASE	0
+#define MSP_INT_SW0		0	/* IRQ for swint0,       C_SW0  */
+#define MSP_INT_SW1		1	/* IRQ for swint1,       C_SW1  */
+#define MSP_INT_MAC0		2	/* IRQ for MAC 0,        C_IRQ0 */
+#define MSP_INT_MAC1		3	/* IRQ for MAC 1,        C_IRQ1 */
+#define MSP_INT_USB		4	/* IRQ for USB,          C_IRQ2 */
+#define MSP_INT_SAR		5	/* IRQ for ADSL2+ SAR,   C_IRQ3 */
+#define MSP_INT_CIC		6	/* IRQ for CIC block,    C_IRQ4 */
+#define MSP_INT_SEC		7	/* IRQ for Sec engine,   C_IRQ5 */
+
+/*
+ * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4)
+ * These defines should be tied to the register definitions for the CIC
+ * interrupt routine.  For now, just use hard-coded values.
+ */
+#define MSP_CIC_INTBASE		(MSP_MIPS_INTBASE + 8)
+#define MSP_INT_EXT0		(MSP_CIC_INTBASE + 0)
+					/* External interrupt 0         */
+#define MSP_INT_EXT1		(MSP_CIC_INTBASE + 1)
+					/* External interrupt 1         */
+#define MSP_INT_EXT2		(MSP_CIC_INTBASE + 2)
+					/* External interrupt 2         */
+#define MSP_INT_EXT3		(MSP_CIC_INTBASE + 3)
+					/* External interrupt 3         */
+#define MSP_INT_CPUIF		(MSP_CIC_INTBASE + 4)
+					/* CPU interface interrupt      */
+#define MSP_INT_EXT4		(MSP_CIC_INTBASE + 5)
+					/* External interrupt 4         */
+#define MSP_INT_CIC_USB		(MSP_CIC_INTBASE + 6)
+					/* Cascaded IRQ for USB         */
+#define MSP_INT_MBOX		(MSP_CIC_INTBASE + 7)
+					/* Sec engine mailbox IRQ       */
+#define MSP_INT_EXT5		(MSP_CIC_INTBASE + 8)
+					/* External interrupt 5         */
+#define MSP_INT_TDM		(MSP_CIC_INTBASE + 9)
+					/* TDM interrupt                */
+#define MSP_INT_CIC_MAC0	(MSP_CIC_INTBASE + 10)
+					/* Cascaded IRQ for MAC 0       */
+#define MSP_INT_CIC_MAC1	(MSP_CIC_INTBASE + 11)
+					/* Cascaded IRQ for MAC 1       */
+#define MSP_INT_CIC_SEC		(MSP_CIC_INTBASE + 12)
+					/* Cascaded IRQ for sec engine  */
+#define	MSP_INT_PER		(MSP_CIC_INTBASE + 13)
+					/* Peripheral interrupt         */
+#define	MSP_INT_TIMER0		(MSP_CIC_INTBASE + 14)
+					/* SLP timer 0                  */
+#define	MSP_INT_TIMER1		(MSP_CIC_INTBASE + 15)
+					/* SLP timer 1                  */
+#define	MSP_INT_TIMER2		(MSP_CIC_INTBASE + 16)
+					/* SLP timer 2                  */
+#define	MSP_INT_VPE0_TIMER	(MSP_CIC_INTBASE + 17)
+					/* VPE0 MIPS timer              */
+#define MSP_INT_BLKCP		(MSP_CIC_INTBASE + 18)
+					/* Block Copy                   */
+#define MSP_INT_UART0		(MSP_CIC_INTBASE + 19)
+					/* UART 0                       */
+#define MSP_INT_PCI		(MSP_CIC_INTBASE + 20)
+					/* PCI subsystem                */
+#define MSP_INT_EXT6		(MSP_CIC_INTBASE + 21)
+					/* External interrupt 5         */
+#define MSP_INT_PCI_MSI		(MSP_CIC_INTBASE + 22)
+					/* PCI Message Signal           */
+#define MSP_INT_CIC_SAR		(MSP_CIC_INTBASE + 23)
+					/* Cascaded ADSL2+ SAR IRQ      */
+#define MSP_INT_DSL		(MSP_CIC_INTBASE + 24)
+					/* ADSL2+ IRQ                   */
+#define MSP_INT_CIC_ERR		(MSP_CIC_INTBASE + 25)
+					/* SLP error condition          */
+#define MSP_INT_VPE1_TIMER	(MSP_CIC_INTBASE + 26)
+					/* VPE1 MIPS timer              */
+#define MSP_INT_VPE0_PC		(MSP_CIC_INTBASE + 27)
+					/* VPE0 Performance counter     */
+#define MSP_INT_VPE1_PC		(MSP_CIC_INTBASE + 28)
+					/* VPE1 Performance counter     */
+#define MSP_INT_EXT7		(MSP_CIC_INTBASE + 29)
+					/* External interrupt 5         */
+#define MSP_INT_VPE0_SW		(MSP_CIC_INTBASE + 30)
+					/* VPE0 Software interrupt      */
+#define MSP_INT_VPE1_SW		(MSP_CIC_INTBASE + 31)
+					/* VPE0 Software interrupt      */
+
+/*
+ * IRQs cascaded on CIC PER interrupt (MSP_INT_PER)
+ */
+#define MSP_PER_INTBASE		(MSP_CIC_INTBASE + 32)
+/* Reserved					   0-1                  */
+#define MSP_INT_UART1		(MSP_PER_INTBASE + 2)
+					/* UART 1                       */
+/* Reserved					   3-5                  */
+#define MSP_INT_2WIRE		(MSP_PER_INTBASE + 6)
+					/* 2-wire                       */
+#define MSP_INT_TM0		(MSP_PER_INTBASE + 7)
+					/* Peripheral timer block out 0 */
+#define MSP_INT_TM1		(MSP_PER_INTBASE + 8)
+					/* Peripheral timer block out 1 */
+/* Reserved					   9                    */
+#define MSP_INT_SPRX		(MSP_PER_INTBASE + 10)
+					/* SPI RX complete              */
+#define MSP_INT_SPTX		(MSP_PER_INTBASE + 11)
+					/* SPI TX complete              */
+#define MSP_INT_GPIO		(MSP_PER_INTBASE + 12)
+					/* GPIO                         */
+#define MSP_INT_PER_ERR		(MSP_PER_INTBASE + 13)
+					/* Peripheral error             */
+/* Reserved					   14-31                */
+
+#endif /* !_MSP_CIC_INT_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_int.h
new file mode 100644
index 0000000..1d9f054
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_int.h
@@ -0,0 +1,43 @@
+/*
+ * Defines for the MSP interrupt handlers.
+ *
+ * Copyright (C) 2005, PMC-Sierra, Inc.  All rights reserved.
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_INT_H
+#define _MSP_INT_H
+
+/*
+ * The PMC-Sierra MSP product line has at least two different interrupt
+ * controllers, the SLP register based scheme and the CIC interrupt
+ * controller block mechanism.  This file distinguishes between them
+ * so that devices see a uniform interface.
+ */
+
+#if defined(CONFIG_IRQ_MSP_SLP)
+	#include "msp_slp_int.h"
+#elif defined(CONFIG_IRQ_MSP_CIC)
+	#include "msp_cic_int.h"
+#else
+	#error "What sort of interrupt controller does *your* MSP have?"
+#endif
+
+#endif /* !_MSP_INT_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h b/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h
new file mode 100644
index 0000000..4156069
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2000-2006 PMC-Sierra INC.
+ *
+ *     This program is free software; you can redistribute it
+ *     and/or modify it under the terms of the GNU General
+ *     Public License as published by the Free Software
+ *     Foundation; either version 2 of the License, or (at your
+ *     option) any later version.
+ *
+ *     This program is distributed in the hope that it will be
+ *     useful, but WITHOUT ANY WARRANTY; without even the implied
+ *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *     PURPOSE.  See the GNU General Public License for more
+ *     details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this program; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ *     02139, USA.
+ *
+ * PMC-SIERRA INC. DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _MSP_PCI_H_
+#define _MSP_PCI_H_
+
+#define MSP_HAS_PCI(ID)	(((u32)(ID) <= 0x4236) && ((u32)(ID) >= 0x4220))
+
+/*
+ * It is convenient to program the OATRAN register so that
+ * Athena virtual address space and PCI address space are
+ * the same. This is not a requirement, just a convenience.
+ *
+ * The only hard restrictions on the value of OATRAN is that
+ * OATRAN must not be programmed to allow translated memory
+ * addresses to fall within the lowest 512MB of
+ * PCI address space. This region is hardcoded
+ * for use as Athena PCI Host Controller target
+ * access memory space to the Athena's SDRAM.
+ *
+ * Note that OATRAN applies only to memory accesses, not
+ * to I/O accesses.
+ *
+ * To program OATRAN to make Athena virtual address space
+ * and PCI address space have the same values, OATRAN
+ * is to be programmed to 0xB8000000. The top seven
+ * bits of the value mimic the seven bits clipped off
+ * by the PCI Host controller.
+ *
+ * With OATRAN at the said value, when the CPU does
+ * an access to its virtual address at, say 0xB900_5000,
+ * the address appearing on the PCI bus will be
+ * 0xB900_5000.
+ *    - Michael Penner
+ */
+#define MSP_PCI_OATRAN		0xB8000000UL
+
+#define MSP_PCI_SPACE_BASE	(MSP_PCI_OATRAN + 0x1002000UL)
+#define MSP_PCI_SPACE_SIZE	(0x3000000UL - 0x2000)
+#define MSP_PCI_SPACE_END \
+		(MSP_PCI_SPACE_BASE + MSP_PCI_SPACE_SIZE - 1)
+#define MSP_PCI_IOSPACE_BASE	(MSP_PCI_OATRAN + 0x1001000UL)
+#define MSP_PCI_IOSPACE_SIZE	0x1000
+#define MSP_PCI_IOSPACE_END  \
+		(MSP_PCI_IOSPACE_BASE + MSP_PCI_IOSPACE_SIZE - 1)
+
+/* IRQ for PCI status interrupts */
+#define PCI_STAT_IRQ	20
+
+#define QFLUSH_REG_1	0xB7F40000
+
+typedef volatile unsigned int pcireg;
+typedef void * volatile ppcireg;
+
+struct pci_block_copy
+{
+    pcireg   unused1; /* +0x00 */
+    pcireg   unused2; /* +0x04 */
+    ppcireg  unused3; /* +0x08 */
+    ppcireg  unused4; /* +0x0C */
+    pcireg   unused5; /* +0x10 */
+    pcireg   unused6; /* +0x14 */
+    pcireg   unused7; /* +0x18 */
+    ppcireg  unused8; /* +0x1C */
+    ppcireg  unused9; /* +0x20 */
+    pcireg   unusedA; /* +0x24 */
+    ppcireg  unusedB; /* +0x28 */
+    ppcireg  unusedC; /* +0x2C */
+};
+
+enum
+{
+    config_device_vendor,  /* 0 */
+    config_status_command, /* 1 */
+    config_class_revision, /* 2 */
+    config_BIST_header_latency_cache, /* 3 */
+    config_BAR0,           /* 4 */
+    config_BAR1,           /* 5 */
+    config_BAR2,           /* 6 */
+    config_not_used7,      /* 7 */
+    config_not_used8,      /* 8 */
+    config_not_used9,      /* 9 */
+    config_CIS,            /* 10 */
+    config_subsystem,      /* 11 */
+    config_not_used12,     /* 12 */
+    config_capabilities,   /* 13 */
+    config_not_used14,     /* 14 */
+    config_lat_grant_irq,  /* 15 */
+    config_message_control,/* 16 */
+    config_message_addr,   /* 17 */
+    config_message_data,   /* 18 */
+    config_VPD_addr,       /* 19 */
+    config_VPD_data,       /* 20 */
+    config_maxregs         /* 21 - number of registers */
+};
+
+struct msp_pci_regs
+{
+    pcireg hop_unused_00; /* +0x00 */
+    pcireg hop_unused_04; /* +0x04 */
+    pcireg hop_unused_08; /* +0x08 */
+    pcireg hop_unused_0C; /* +0x0C */
+    pcireg hop_unused_10; /* +0x10 */
+    pcireg hop_unused_14; /* +0x14 */
+    pcireg hop_unused_18; /* +0x18 */
+    pcireg hop_unused_1C; /* +0x1C */
+    pcireg hop_unused_20; /* +0x20 */
+    pcireg hop_unused_24; /* +0x24 */
+    pcireg hop_unused_28; /* +0x28 */
+    pcireg hop_unused_2C; /* +0x2C */
+    pcireg hop_unused_30; /* +0x30 */
+    pcireg hop_unused_34; /* +0x34 */
+    pcireg if_control;    /* +0x38 */
+    pcireg oatran;        /* +0x3C */
+    pcireg reset_ctl;     /* +0x40 */
+    pcireg config_addr;   /* +0x44 */
+    pcireg hop_unused_48; /* +0x48 */
+    pcireg msg_signaled_int_status; /* +0x4C */
+    pcireg msg_signaled_int_mask;   /* +0x50 */
+    pcireg if_status;     /* +0x54 */
+    pcireg if_mask;       /* +0x58 */
+    pcireg hop_unused_5C; /* +0x5C */
+    pcireg hop_unused_60; /* +0x60 */
+    pcireg hop_unused_64; /* +0x64 */
+    pcireg hop_unused_68; /* +0x68 */
+    pcireg hop_unused_6C; /* +0x6C */
+    pcireg hop_unused_70; /* +0x70 */
+
+    struct pci_block_copy pci_bc[2] __attribute__((aligned(64)));
+
+    pcireg error_hdr1; /* +0xE0 */
+    pcireg error_hdr2; /* +0xE4 */
+
+    pcireg config[config_maxregs] __attribute__((aligned(256)));
+
+};
+
+#define BPCI_CFGADDR_BUSNUM_SHF 16
+#define BPCI_CFGADDR_FUNCTNUM_SHF 8
+#define BPCI_CFGADDR_REGNUM_SHF 2
+#define BPCI_CFGADDR_ENABLE (1<<31)
+
+#define BPCI_IFCONTROL_RTO (1<<20) /* Retry timeout */
+#define BPCI_IFCONTROL_HCE (1<<16) /* Host configuration enable */
+#define BPCI_IFCONTROL_CTO_SHF 12  /* Shift count for CTO bits */
+#define BPCI_IFCONTROL_SE  (1<<5)  /* Enable exceptions on errors */
+#define BPCI_IFCONTROL_BIST (1<<4) /* Use BIST in per. mode */
+#define BPCI_IFCONTROL_CAP (1<<3)  /* Enable capabilities */
+#define BPCI_IFCONTROL_MMC_SHF 0   /* Shift count for MMC bits */
+
+#define BPCI_IFSTATUS_MGT  (1<<8)  /* Master Grant timeout */
+#define BPCI_IFSTATUS_MTT  (1<<9)  /* Master TRDY timeout */
+#define BPCI_IFSTATUS_MRT  (1<<10) /* Master retry timeout */
+#define BPCI_IFSTATUS_BC0F (1<<13) /* Block copy 0 fault */
+#define BPCI_IFSTATUS_BC1F (1<<14) /* Block copy 1 fault */
+#define BPCI_IFSTATUS_PCIU (1<<15) /* PCI unable to respond */
+#define BPCI_IFSTATUS_BSIZ (1<<16) /* PCI access with illegal size */
+#define BPCI_IFSTATUS_BADD (1<<17) /* PCI access with illegal addr */
+#define BPCI_IFSTATUS_RTO  (1<<18) /* Retry time out */
+#define BPCI_IFSTATUS_SER  (1<<19) /* System error */
+#define BPCI_IFSTATUS_PER  (1<<20) /* Parity error */
+#define BPCI_IFSTATUS_LCA  (1<<21) /* Local CPU abort */
+#define BPCI_IFSTATUS_MEM  (1<<22) /* Memory prot. violation */
+#define BPCI_IFSTATUS_ARB  (1<<23) /* Arbiter timed out */
+#define BPCI_IFSTATUS_STA  (1<<27) /* Signaled target abort */
+#define BPCI_IFSTATUS_TA   (1<<28) /* Target abort */
+#define BPCI_IFSTATUS_MA   (1<<29) /* Master abort */
+#define BPCI_IFSTATUS_PEI  (1<<30) /* Parity error as initiator */
+#define BPCI_IFSTATUS_PET  (1<<31) /* Parity error as target */
+
+#define BPCI_RESETCTL_PR (1<<0)    /* True if reset asserted */
+#define BPCI_RESETCTL_RT (1<<4)    /* Release time */
+#define BPCI_RESETCTL_CT (1<<8)    /* Config time */
+#define BPCI_RESETCTL_PE (1<<12)   /* PCI enabled */
+#define BPCI_RESETCTL_HM (1<<13)   /* PCI host mode */
+#define BPCI_RESETCTL_RI (1<<14)   /* PCI reset in */
+
+extern struct msp_pci_regs msp_pci_regs
+			__attribute__((section(".register")));
+extern unsigned long msp_pci_config_space
+			__attribute__((section(".register")));
+
+#endif /* !_MSP_PCI_H_ */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h b/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h
new file mode 100644
index 0000000..14ca7dc
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h
@@ -0,0 +1,176 @@
+/*
+ * MIPS boards bootprom interface for the Linux kernel.
+ *
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _ASM_MSP_PROM_H
+#define _ASM_MSP_PROM_H
+
+#include <linux/types.h>
+
+#define DEVICEID			"deviceid"
+#define FEATURES			"features"
+#define PROM_ENV			"prom_env"
+#define PROM_ENV_FILE			"/proc/"PROM_ENV
+#define PROM_ENV_SIZE			256
+
+#define CPU_DEVID_FAMILY		0x0000ff00
+#define CPU_DEVID_REVISION		0x000000ff
+
+#define FPGA_IS_POLO(revision) \
+		(((revision >= 0xb0) && (revision < 0xd0)))
+#define FPGA_IS_5000(revision) \
+		((revision >= 0x80) && (revision <= 0x90))
+#define	FPGA_IS_ZEUS(revision)		((revision < 0x7f))
+#define FPGA_IS_DUET(revision) \
+		(((revision >= 0xa0) && (revision < 0xb0)))
+#define FPGA_IS_MSP4200(revision)	((revision >= 0xd0))
+#define FPGA_IS_MSP7100(revision)	((revision >= 0xd0))
+
+#define MACHINE_TYPE_POLO		"POLO"
+#define MACHINE_TYPE_DUET		"DUET"
+#define	MACHINE_TYPE_ZEUS		"ZEUS"
+#define MACHINE_TYPE_MSP2000REVB	"MSP2000REVB"
+#define MACHINE_TYPE_MSP5000		"MSP5000"
+#define MACHINE_TYPE_MSP4200		"MSP4200"
+#define MACHINE_TYPE_MSP7120		"MSP7120"
+#define MACHINE_TYPE_MSP7130		"MSP7130"
+#define MACHINE_TYPE_OTHER		"OTHER"
+
+#define MACHINE_TYPE_POLO_FPGA		"POLO-FPGA"
+#define MACHINE_TYPE_DUET_FPGA		"DUET-FPGA"
+#define	MACHINE_TYPE_ZEUS_FPGA		"ZEUS_FPGA"
+#define MACHINE_TYPE_MSP2000REVB_FPGA	"MSP2000REVB-FPGA"
+#define MACHINE_TYPE_MSP5000_FPGA	"MSP5000-FPGA"
+#define MACHINE_TYPE_MSP4200_FPGA	"MSP4200-FPGA"
+#define MACHINE_TYPE_MSP7100_FPGA	"MSP7100-FPGA"
+#define MACHINE_TYPE_OTHER_FPGA		"OTHER-FPGA"
+
+/* Device Family definitions */
+#define FAMILY_FPGA			0x0000
+#define FAMILY_ZEUS			0x1000
+#define FAMILY_POLO			0x2000
+#define FAMILY_DUET			0x4000
+#define FAMILY_TRIAD			0x5000
+#define FAMILY_MSP4200			0x4200
+#define FAMILY_MSP4200_FPGA		0x4f00
+#define FAMILY_MSP7100			0x7100
+#define FAMILY_MSP7100_FPGA		0x7f00
+
+/* Device Type definitions */
+#define TYPE_MSP7120			0x7120
+#define TYPE_MSP7130			0x7130
+
+#define ENET_KEY		'E'
+#define ENETTXD_KEY		'e'
+#define PCI_KEY			'P'
+#define PCIMUX_KEY		'p'
+#define SEC_KEY			'S'
+#define SPAD_KEY		'D'
+#define TDM_KEY			'T'
+#define ZSP_KEY			'Z'
+
+#define FEATURE_NOEXIST		'-'
+#define FEATURE_EXIST		'+'
+
+#define ENET_MII		'M'
+#define ENET_RMII		'R'
+
+#define	ENETTXD_FALLING		'F'
+#define ENETTXD_RISING		'R'
+
+#define PCI_HOST		'H'
+#define PCI_PERIPHERAL		'P'
+
+#define PCIMUX_FULL		'F'
+#define PCIMUX_SINGLE		'S'
+
+#define SEC_DUET		'D'
+#define SEC_POLO		'P'
+#define SEC_SLOW		'S'
+#define SEC_TRIAD		'T'
+
+#define SPAD_POLO		'P'
+
+#define TDM_DUET		'D'	/* DUET TDMs might exist */
+#define TDM_POLO		'P'	/* POLO TDMs might exist */
+#define TDM_TRIAD		'T'	/* TRIAD TDMs might exist */
+
+#define ZSP_DUET		'D'	/* one DUET zsp engine */
+#define ZSP_TRIAD		'T'	/* two TRIAD zsp engines */
+
+extern char *prom_getcmdline(void);
+extern char *prom_getenv(char *name);
+extern void prom_init_cmdline(void);
+extern void prom_meminit(void);
+extern void prom_fixup_mem_map(unsigned long start_mem,
+			       unsigned long end_mem);
+
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+extern bool get_ramroot(void **start, unsigned long *size);
+#endif
+
+extern int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr);
+extern unsigned long get_deviceid(void);
+extern char identify_enet(unsigned long interface_num);
+extern char identify_enetTxD(unsigned long interface_num);
+extern char identify_pci(void);
+extern char identify_sec(void);
+extern char identify_spad(void);
+extern char identify_sec(void);
+extern char identify_tdm(void);
+extern char identify_zsp(void);
+extern unsigned long identify_family(void);
+extern unsigned long identify_revision(void);
+
+/*
+ * The following macro calls prom_printf and puts the format string
+ * into an init section so it can be reclaimed.
+ */
+#define ppfinit(f, x...) \
+	do { \
+		static char _f[] __initdata = KERN_INFO f; \
+		printk(_f, ## x); \
+	} while (0)
+
+/* Memory descriptor management. */
+#define PROM_MAX_PMEMBLOCKS    7	/* 6 used */
+
+enum yamon_memtypes {
+	yamon_dontuse,
+	yamon_prom,
+	yamon_free,
+};
+
+struct prom_pmemblock {
+	unsigned long base; /* Within KSEG0. */
+	unsigned int size;  /* In bytes. */
+	unsigned int type;  /* free or prom memory */
+};
+
+extern int prom_argc;
+extern char **prom_argv;
+extern char **prom_envp;
+extern int *prom_vec;
+extern struct prom_pmemblock *prom_getmdesc(void);
+
+#endif /* !_ASM_MSP_PROM_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h
new file mode 100644
index 0000000..60a5a38
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h
@@ -0,0 +1,236 @@
+/*
+ * SMP/VPE-safe functions to access "registers" (see note).
+ *
+ * NOTES:
+* - These macros use ll/sc instructions, so it is your responsibility to
+ * ensure these are available on your platform before including this file.
+ * - The MIPS32 spec states that ll/sc results are undefined for uncached
+ * accesses. This means they can't be used on HW registers accessed
+ * through kseg1. Code which requires these macros for this purpose must
+ * front-end the registers with cached memory "registers" and have a single
+ * thread update the actual HW registers.
+ * - A maximum of 2k of code can be inserted between ll and sc. Every
+ * memory accesses between the instructions will increase the chance of
+ * sc failing and having to loop.
+ * - When using custom_read_reg32/custom_write_reg32 only perform the
+ * necessary logical operations on the register value in between these
+ * two calls. All other logic should be performed before the first call.
+  * - There is a bug on the R10000 chips which has a workaround. If you
+ * are affected by this bug, make sure to define the symbol 'R10000_LLSC_WAR'
+ * to be non-zero.  If you are using this header from within linux, you may
+ * include <asm/war.h> before including this file to have this defined
+ * appropriately for you.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
+ *  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF USE,
+ *  DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc., 675
+ *  Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_REGOPS_H__
+#define __ASM_REGOPS_H__
+
+#include <linux/types.h>
+
+#include <asm/war.h>
+
+#ifndef R10000_LLSC_WAR
+#define R10000_LLSC_WAR 0
+#endif
+
+#if R10000_LLSC_WAR == 1
+#define __beqz	"beqzl	"
+#else
+#define __beqz	"beqz	"
+#endif
+
+#ifndef _LINUX_TYPES_H
+typedef unsigned int u32;
+#endif
+
+/*
+ * Sets all the masked bits to the corresponding value bits
+ */
+static inline void set_value_reg32(volatile u32 *const addr,
+					u32 const mask,
+					u32 const value)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	mips3				\n"
+	"1:	ll	%0, %1	# set_value_reg32	\n"
+	"	and	%0, %2				\n"
+	"	or	%0, %3				\n"
+	"	sc	%0, %1				\n"
+	"	"__beqz"%0, 1b				\n"
+	"	nop					\n"
+	"	.set	pop				\n"
+	: "=&r" (temp), "=m" (*addr)
+	: "ir" (~mask), "ir" (value), "m" (*addr));
+}
+
+/*
+ * Sets all the masked bits to '1'
+ */
+static inline void set_reg32(volatile u32 *const addr,
+				u32 const mask)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	mips3				\n"
+	"1:	ll	%0, %1		# set_reg32	\n"
+	"	or	%0, %2				\n"
+	"	sc	%0, %1				\n"
+	"	"__beqz"%0, 1b				\n"
+	"	nop					\n"
+	"	.set	pop				\n"
+	: "=&r" (temp), "=m" (*addr)
+	: "ir" (mask), "m" (*addr));
+}
+
+/*
+ * Sets all the masked bits to '0'
+ */
+static inline void clear_reg32(volatile u32 *const addr,
+				u32 const mask)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	mips3				\n"
+	"1:	ll	%0, %1		# clear_reg32	\n"
+	"	and	%0, %2				\n"
+	"	sc	%0, %1				\n"
+	"	"__beqz"%0, 1b				\n"
+	"	nop					\n"
+	"	.set	pop				\n"
+	: "=&r" (temp), "=m" (*addr)
+	: "ir" (~mask), "m" (*addr));
+}
+
+/*
+ * Toggles all masked bits from '0' to '1' and '1' to '0'
+ */
+static inline void toggle_reg32(volatile u32 *const addr,
+				u32 const mask)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	mips3				\n"
+	"1:	ll	%0, %1		# toggle_reg32	\n"
+	"	xor	%0, %2				\n"
+	"	sc	%0, %1				\n"
+	"	"__beqz"%0, 1b				\n"
+	"	nop					\n"
+	"	.set	pop				\n"
+	: "=&r" (temp), "=m" (*addr)
+	: "ir" (mask), "m" (*addr));
+}
+
+/*
+ * Read all masked bits others are returned as '0'
+ */
+static inline u32 read_reg32(volatile u32 *const addr,
+				u32 const mask)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	noreorder			\n"
+	"	lw	%0, %1		# read		\n"
+	"	and	%0, %2		# mask		\n"
+	"	.set	pop				\n"
+	: "=&r" (temp)
+	: "m" (*addr), "ir" (mask));
+
+	return temp;
+}
+
+/*
+ * blocking_read_reg32 - Read address with blocking load
+ *
+ * Uncached writes need to be read back to ensure they reach RAM.
+ * The returned value must be 'used' to prevent from becoming a
+ * non-blocking load.
+ */
+static inline u32 blocking_read_reg32(volatile u32 *const addr)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	noreorder			\n"
+	"	lw	%0, %1		# read		\n"
+	"	move	%0, %0		# block		\n"
+	"	.set	pop				\n"
+	: "=&r" (temp)
+	: "m" (*addr));
+
+	return temp;
+}
+
+/*
+ * For special strange cases only:
+ *
+ * If you need custom processing within a ll/sc loop, use the following macros
+ * VERY CAREFULLY:
+ *
+ *   u32 tmp;				<-- Define a variable to hold the data
+ *
+ *   custom_read_reg32(address, tmp);	<-- Reads the address and put the value
+ *						in the 'tmp' variable given
+ *
+ *	From here on out, you are (basicly) atomic, so don't do anything too
+ *	fancy!
+ *	Also, this code may loop if the end of this block fails to write
+ *	everything back safely due do the other CPU, so do NOT do anything
+ *	with side-effects!
+ *
+ *   custom_write_reg32(address, tmp);	<-- Writes back 'tmp' safely.
+ */
+#define custom_read_reg32(address, tmp)				\
+	__asm__ __volatile__(					\
+	"	.set	push				\n"	\
+	"	.set	mips3				\n"	\
+	"1:	ll	%0, %1	#custom_read_reg32	\n"	\
+	"	.set	pop				\n"	\
+	: "=r" (tmp), "=m" (*address)				\
+	: "m" (*address))
+
+#define custom_write_reg32(address, tmp)			\
+	__asm__ __volatile__(					\
+	"	.set	push				\n"	\
+	"	.set	mips3				\n"	\
+	"	sc	%0, %1	#custom_write_reg32	\n"	\
+	"	"__beqz"%0, 1b				\n"	\
+	"	nop					\n"	\
+	"	.set	pop				\n"	\
+	: "=&r" (tmp), "=m" (*address)				\
+	: "0" (tmp), "m" (*address))
+
+#endif  /* __ASM_REGOPS_H__ */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
new file mode 100644
index 0000000..0b56f55
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
@@ -0,0 +1,667 @@
+/*
+ * Defines for the address space, registers and register configuration
+ * (bit masks, access macros etc) for the PMC-Sierra line of MSP products.
+ * This file contains addess maps for all the devices in the line of
+ * products but only has register definitions and configuration masks for
+ * registers which aren't definitely associated with any device.  Things
+ * like clock settings, reset access, the ELB etc.  Individual device
+ * drivers will reference the appropriate XXX_BASE value defined here
+ * and have individual registers offset from that.
+ *
+ * Copyright (C) 2005-2007 PMC-Sierra, Inc.  All rights reserved.
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#include <asm/addrspace.h>
+#include <linux/types.h>
+
+#ifndef _ASM_MSP_REGS_H
+#define _ASM_MSP_REGS_H
+
+/*
+ ########################################################################
+ #  Address space and device base definitions                           #
+ ########################################################################
+ */
+
+/*
+ ***************************************************************************
+ * System Logic and Peripherals (ELB, UART0, etc) device address space     *
+ ***************************************************************************
+ */
+#define MSP_SLP_BASE		0x1c000000
+					/* System Logic and Peripherals */
+#define MSP_RST_BASE		(MSP_SLP_BASE + 0x10)
+					/* System reset register base	*/
+#define MSP_RST_SIZE		0x0C	/* System reset register space	*/
+
+#define MSP_WTIMER_BASE		(MSP_SLP_BASE + 0x04C)
+					/* watchdog timer base          */
+#define MSP_ITIMER_BASE		(MSP_SLP_BASE + 0x054)
+					/* internal timer base          */
+#define MSP_UART0_BASE		(MSP_SLP_BASE + 0x100)
+					/* UART0 controller base        */
+#define MSP_BCPY_CTRL_BASE	(MSP_SLP_BASE + 0x120)
+					/* Block Copy controller base   */
+#define MSP_BCPY_DESC_BASE	(MSP_SLP_BASE + 0x160)
+					/* Block Copy descriptor base   */
+
+/*
+ ***************************************************************************
+ * PCI address space                                                       *
+ ***************************************************************************
+ */
+#define MSP_PCI_BASE		0x19000000
+
+/*
+ ***************************************************************************
+ * MSbus device address space                                              *
+ ***************************************************************************
+ */
+#define MSP_MSB_BASE		0x18000000
+					/* MSbus address start          */
+#define MSP_PER_BASE		(MSP_MSB_BASE + 0x400000)
+					/* Peripheral device registers  */
+#define MSP_MAC0_BASE		(MSP_MSB_BASE + 0x600000)
+					/* MAC A device registers       */
+#define MSP_MAC1_BASE		(MSP_MSB_BASE + 0x700000)
+					/* MAC B device registers       */
+#define MSP_MAC_SIZE		0xE0	/* MAC register space		*/
+
+#define MSP_SEC_BASE		(MSP_MSB_BASE + 0x800000)
+					/* Security Engine registers    */
+#define MSP_MAC2_BASE		(MSP_MSB_BASE + 0x900000)
+					/* MAC C device registers       */
+#define MSP_ADSL2_BASE		(MSP_MSB_BASE + 0xA80000)
+					/* ADSL2 device registers       */
+#define MSP_USB_BASE		(MSP_MSB_BASE + 0xB40000)
+					/* USB device registers         */
+#define MSP_USB_BASE_START	(MSP_MSB_BASE + 0xB40100)
+					/* USB device registers         */
+#define MSP_USB_BASE_END	(MSP_MSB_BASE + 0xB401FF)
+					/* USB device registers         */
+#define MSP_CPUIF_BASE		(MSP_MSB_BASE + 0xC00000)
+					/* CPU interface registers      */
+
+/* Devices within the MSbus peripheral block */
+#define MSP_UART1_BASE		(MSP_PER_BASE + 0x030)
+					/* UART1 controller base        */
+#define MSP_SPI_BASE		(MSP_PER_BASE + 0x058)
+					/* SPI/MPI control registers    */
+#define MSP_TWI_BASE		(MSP_PER_BASE + 0x090)
+					/* Two-wire control registers   */
+#define MSP_PTIMER_BASE		(MSP_PER_BASE + 0x0F0)
+					/* Programmable timer control   */
+
+/*
+ ***************************************************************************
+ * Physical Memory configuration address space                             *
+ ***************************************************************************
+ */
+#define MSP_MEM_CFG_BASE	0x17f00000
+
+#define MSP_MEM_INDIRECT_CTL_10	0x10
+
+/*
+ * Notes:
+ *  1) The SPI registers are split into two blocks, one offset from the
+ *     MSP_SPI_BASE by 0x00 and the other offset from the MSP_SPI_BASE by
+ *     0x68.  The SPI driver definitions for the register must be aware
+ *     of this.
+ *  2) The block copy engine register are divided into two regions, one
+ *     for the control/configuration of the engine proper and one for the
+ *     values of the descriptors used in the copy process.  These have
+ *     different base defines (CTRL_BASE vs DESC_BASE)
+ *  3) These constants are for physical addresses which means that they
+ *     work correctly with "ioremap" and friends.  This means that device
+ *     drivers will need to remap these addresses using ioremap and perhaps
+ *     the readw/writew macros.  Or they could use the regptr() macro
+ *     defined below, but the readw/writew calls are the correct thing.
+ *  4) The UARTs have an additional status register offset from the base
+ *     address.  This register isn't used in the standard 8250 driver but
+ *     may be used in other software.  Consult the hardware datasheet for
+ *     offset details.
+ *  5) For some unknown reason the security engine (MSP_SEC_BASE) registers
+ *     start at an offset of 0x84 from the base address but the block of
+ *     registers before this is reserved for the security engine.  The
+ *     driver will have to be aware of this but it makes the register
+ *     definitions line up better with the documentation.
+ */
+
+/*
+ ########################################################################
+ #  System register definitions.  Not associated with a specific device #
+ ########################################################################
+ */
+
+/*
+ * This macro maps the physical register number into uncached space
+ * and (for C code) casts it into a u32 pointer so it can be dereferenced
+ * Normally these would be accessed with ioremap and readX/writeX, but
+ * these are convenient for a lot of internal kernel code.
+ */
+#ifdef __ASSEMBLER__
+	#define regptr(addr) (KSEG1ADDR(addr))
+#else
+	#define regptr(addr) ((volatile u32 *const)(KSEG1ADDR(addr)))
+#endif
+
+/*
+ ***************************************************************************
+ * System Logic and Peripherals (RESET, ELB, etc) registers                *
+ ***************************************************************************
+ */
+
+/* System Control register definitions */
+#define	DEV_ID_REG	regptr(MSP_SLP_BASE + 0x00)
+					/* Device-ID                 RO */
+#define	FWR_ID_REG	regptr(MSP_SLP_BASE + 0x04)
+					/* Firmware-ID Register      RW */
+#define	SYS_ID_REG0	regptr(MSP_SLP_BASE + 0x08)
+					/* System-ID Register-0      RW */
+#define	SYS_ID_REG1	regptr(MSP_SLP_BASE + 0x0C)
+					/* System-ID Register-1      RW */
+
+/* System Reset register definitions */
+#define	RST_STS_REG	regptr(MSP_SLP_BASE + 0x10)
+					/* System Reset Status       RO */
+#define	RST_SET_REG	regptr(MSP_SLP_BASE + 0x14)
+					/* System Set Reset          WO */
+#define	RST_CLR_REG	regptr(MSP_SLP_BASE + 0x18)
+					/* System Clear Reset        WO */
+
+/* System Clock Registers */
+#define PCI_SLP_REG	regptr(MSP_SLP_BASE + 0x1C)
+					/* PCI clock generator       RW */
+#define URT_SLP_REG	regptr(MSP_SLP_BASE + 0x20)
+					/* UART clock generator      RW */
+/* reserved		      (MSP_SLP_BASE + 0x24)                     */
+/* reserved		      (MSP_SLP_BASE + 0x28)                     */
+#define PLL1_SLP_REG	regptr(MSP_SLP_BASE + 0x2C)
+					/* PLL1 clock generator      RW */
+#define PLL0_SLP_REG	regptr(MSP_SLP_BASE + 0x30)
+					/* PLL0 clock generator      RW */
+#define MIPS_SLP_REG	regptr(MSP_SLP_BASE + 0x34)
+					/* MIPS clock generator      RW */
+#define	VE_SLP_REG	regptr(MSP_SLP_BASE + 0x38)
+					/* Voice Eng clock generator RW */
+/* reserved		      (MSP_SLP_BASE + 0x3C)                     */
+#define MSB_SLP_REG	regptr(MSP_SLP_BASE + 0x40)
+					/* MS-Bus clock generator    RW */
+#define SMAC_SLP_REG	regptr(MSP_SLP_BASE + 0x44)
+					/* Sec & MAC clock generator RW */
+#define PERF_SLP_REG	regptr(MSP_SLP_BASE + 0x48)
+					/* Per & TDM clock generator RW */
+
+/* Interrupt Controller Registers */
+#define SLP_INT_STS_REG regptr(MSP_SLP_BASE + 0x70)
+					/* Interrupt status register RW */
+#define SLP_INT_MSK_REG regptr(MSP_SLP_BASE + 0x74)
+					/* Interrupt enable/mask     RW */
+#define SE_MBOX_REG	regptr(MSP_SLP_BASE + 0x78)
+					/* Security Engine mailbox   RW */
+#define VE_MBOX_REG	regptr(MSP_SLP_BASE + 0x7C)
+					/* Voice Engine mailbox      RW */
+
+/* ELB Controller Registers */
+#define CS0_CNFG_REG	regptr(MSP_SLP_BASE + 0x80)
+					/* ELB CS0 Configuration Reg    */
+#define CS0_ADDR_REG	regptr(MSP_SLP_BASE + 0x84)
+					/* ELB CS0 Base Address Reg     */
+#define CS0_MASK_REG	regptr(MSP_SLP_BASE + 0x88)
+					/* ELB CS0 Mask Register        */
+#define CS0_ACCESS_REG	regptr(MSP_SLP_BASE + 0x8C)
+					/* ELB CS0 access register      */
+
+#define CS1_CNFG_REG	regptr(MSP_SLP_BASE + 0x90)
+					/* ELB CS1 Configuration Reg    */
+#define CS1_ADDR_REG	regptr(MSP_SLP_BASE + 0x94)
+					/* ELB CS1 Base Address Reg     */
+#define CS1_MASK_REG	regptr(MSP_SLP_BASE + 0x98)
+					/* ELB CS1 Mask Register        */
+#define CS1_ACCESS_REG	regptr(MSP_SLP_BASE + 0x9C)
+					/* ELB CS1 access register      */
+
+#define CS2_CNFG_REG	regptr(MSP_SLP_BASE + 0xA0)
+					/* ELB CS2 Configuration Reg    */
+#define CS2_ADDR_REG	regptr(MSP_SLP_BASE + 0xA4)
+					/* ELB CS2 Base Address Reg     */
+#define CS2_MASK_REG	regptr(MSP_SLP_BASE + 0xA8)
+					/* ELB CS2 Mask Register        */
+#define CS2_ACCESS_REG	regptr(MSP_SLP_BASE + 0xAC)
+					/* ELB CS2 access register      */
+
+#define CS3_CNFG_REG	regptr(MSP_SLP_BASE + 0xB0)
+					/* ELB CS3 Configuration Reg    */
+#define CS3_ADDR_REG	regptr(MSP_SLP_BASE + 0xB4)
+					/* ELB CS3 Base Address Reg     */
+#define CS3_MASK_REG	regptr(MSP_SLP_BASE + 0xB8)
+					/* ELB CS3 Mask Register        */
+#define CS3_ACCESS_REG	regptr(MSP_SLP_BASE + 0xBC)
+					/* ELB CS3 access register      */
+
+#define CS4_CNFG_REG	regptr(MSP_SLP_BASE + 0xC0)
+					/* ELB CS4 Configuration Reg    */
+#define CS4_ADDR_REG	regptr(MSP_SLP_BASE + 0xC4)
+					/* ELB CS4 Base Address Reg     */
+#define CS4_MASK_REG	regptr(MSP_SLP_BASE + 0xC8)
+					/* ELB CS4 Mask Register        */
+#define CS4_ACCESS_REG	regptr(MSP_SLP_BASE + 0xCC)
+					/* ELB CS4 access register      */
+
+#define CS5_CNFG_REG	regptr(MSP_SLP_BASE + 0xD0)
+					/* ELB CS5 Configuration Reg    */
+#define CS5_ADDR_REG	regptr(MSP_SLP_BASE + 0xD4)
+					/* ELB CS5 Base Address Reg     */
+#define CS5_MASK_REG	regptr(MSP_SLP_BASE + 0xD8)
+					/* ELB CS5 Mask Register        */
+#define CS5_ACCESS_REG	regptr(MSP_SLP_BASE + 0xDC)
+					/* ELB CS5 access register      */
+
+/* reserved			       0xE0 - 0xE8                      */
+#define ELB_1PC_EN_REG	regptr(MSP_SLP_BASE + 0xEC)
+					/* ELB single PC card detect    */
+
+/* reserved			       0xF0 - 0xF8                      */
+#define ELB_CLK_CFG_REG	regptr(MSP_SLP_BASE + 0xFC)
+					/* SDRAM read/ELB timing Reg    */
+
+/* Extended UART status registers */
+#define UART0_STATUS_REG	regptr(MSP_UART0_BASE + 0x0c0)
+					/* UART Status Register 0       */
+#define UART1_STATUS_REG	regptr(MSP_UART1_BASE + 0x170)
+					/* UART Status Register 1       */
+
+/* Performance monitoring registers */
+#define PERF_MON_CTRL_REG	regptr(MSP_SLP_BASE + 0x140)
+					/* Performance monitor control  */
+#define PERF_MON_CLR_REG	regptr(MSP_SLP_BASE + 0x144)
+					/* Performance monitor clear    */
+#define PERF_MON_CNTH_REG	regptr(MSP_SLP_BASE + 0x148)
+					/* Perf monitor counter high    */
+#define PERF_MON_CNTL_REG	regptr(MSP_SLP_BASE + 0x14C)
+					/* Perf monitor counter low     */
+
+/* System control registers */
+#define SYS_CTRL_REG		regptr(MSP_SLP_BASE + 0x150)
+					/* System control register      */
+#define SYS_ERR1_REG		regptr(MSP_SLP_BASE + 0x154)
+					/* System Error status 1        */
+#define SYS_ERR2_REG		regptr(MSP_SLP_BASE + 0x158)
+					/* System Error status 2        */
+#define SYS_INT_CFG_REG		regptr(MSP_SLP_BASE + 0x15C)
+					/* System Interrupt config      */
+
+/* Voice Engine Memory configuration */
+#define VE_MEM_REG		regptr(MSP_SLP_BASE + 0x17C)
+					/* Voice engine memory config   */
+
+/* CPU/SLP Error Status registers */
+#define CPU_ERR1_REG		regptr(MSP_SLP_BASE + 0x180)
+					/* CPU/SLP Error status 1       */
+#define CPU_ERR2_REG		regptr(MSP_SLP_BASE + 0x184)
+					/* CPU/SLP Error status 1       */
+
+#define EXTENDED_GPIO_REG	regptr(MSP_SLP_BASE + 0x188)
+					/* Extended GPIO register       */
+
+/* System Error registers */
+#define SLP_ERR_STS_REG		regptr(MSP_SLP_BASE + 0x190)
+					/* Int status for SLP errors    */
+#define SLP_ERR_MSK_REG		regptr(MSP_SLP_BASE + 0x194)
+					/* Int mask for SLP errors      */
+#define SLP_ELB_ERST_REG	regptr(MSP_SLP_BASE + 0x198)
+					/* External ELB reset           */
+#define SLP_BOOT_STS_REG	regptr(MSP_SLP_BASE + 0x19C)
+					/* Boot Status                  */
+
+/* Extended ELB addressing */
+#define CS0_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1A0)
+					/* CS0 Extended address         */
+#define CS1_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1A4)
+					/* CS1 Extended address         */
+#define CS2_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1A8)
+					/* CS2 Extended address         */
+#define CS3_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1AC)
+					/* CS3 Extended address         */
+/* reserved					      0x1B0             */
+#define CS5_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1B4)
+					/* CS5 Extended address         */
+
+/* PLL Adjustment registers */
+#define PLL_LOCK_REG		regptr(MSP_SLP_BASE + 0x200)
+					/* PLL0 lock status             */
+#define PLL_ARST_REG		regptr(MSP_SLP_BASE + 0x204)
+					/* PLL Analog reset status      */
+#define PLL0_ADJ_REG		regptr(MSP_SLP_BASE + 0x208)
+					/* PLL0 Adjustment value        */
+#define PLL1_ADJ_REG		regptr(MSP_SLP_BASE + 0x20C)
+					/* PLL1 Adjustment value        */
+
+/*
+ ***************************************************************************
+ * Peripheral Register definitions                                         *
+ ***************************************************************************
+ */
+
+/* Peripheral status */
+#define PER_CTRL_REG		regptr(MSP_PER_BASE + 0x50)
+					/* Peripheral control register  */
+#define PER_STS_REG		regptr(MSP_PER_BASE + 0x54)
+					/* Peripheral status register   */
+
+/* SPI/MPI Registers */
+#define SMPI_TX_SZ_REG		regptr(MSP_PER_BASE + 0x58)
+					/* SPI/MPI Tx Size register     */
+#define SMPI_RX_SZ_REG		regptr(MSP_PER_BASE + 0x5C)
+					/* SPI/MPI Rx Size register     */
+#define SMPI_CTL_REG		regptr(MSP_PER_BASE + 0x60)
+					/* SPI/MPI Control register     */
+#define SMPI_MS_REG		regptr(MSP_PER_BASE + 0x64)
+					/* SPI/MPI Chip Select reg      */
+#define SMPI_CORE_DATA_REG	regptr(MSP_PER_BASE + 0xC0)
+					/* SPI/MPI Core Data reg        */
+#define SMPI_CORE_CTRL_REG	regptr(MSP_PER_BASE + 0xC4)
+					/* SPI/MPI Core Control reg     */
+#define SMPI_CORE_STAT_REG	regptr(MSP_PER_BASE + 0xC8)
+					/* SPI/MPI Core Status reg      */
+#define SMPI_CORE_SSEL_REG	regptr(MSP_PER_BASE + 0xCC)
+					/* SPI/MPI Core Ssel reg        */
+#define SMPI_FIFO_REG		regptr(MSP_PER_BASE + 0xD0)
+					/* SPI/MPI Data FIFO reg        */
+
+/* Peripheral Block Error Registers           */
+#define PER_ERR_STS_REG		regptr(MSP_PER_BASE + 0x70)
+					/* Error Bit Status Register    */
+#define PER_ERR_MSK_REG		regptr(MSP_PER_BASE + 0x74)
+					/* Error Bit Mask Register      */
+#define PER_HDR1_REG		regptr(MSP_PER_BASE + 0x78)
+					/* Error Header 1 Register      */
+#define PER_HDR2_REG		regptr(MSP_PER_BASE + 0x7C)
+					/* Error Header 2 Register      */
+
+/* Peripheral Block Interrupt Registers       */
+#define PER_INT_STS_REG		regptr(MSP_PER_BASE + 0x80)
+					/* Interrupt status register    */
+#define PER_INT_MSK_REG		regptr(MSP_PER_BASE + 0x84)
+					/* Interrupt Mask Register      */
+#define GPIO_INT_STS_REG	regptr(MSP_PER_BASE + 0x88)
+					/* GPIO interrupt status reg    */
+#define GPIO_INT_MSK_REG	regptr(MSP_PER_BASE + 0x8C)
+					/* GPIO interrupt MASK Reg      */
+
+/* POLO GPIO registers                        */
+#define POLO_GPIO_DAT1_REG	regptr(MSP_PER_BASE + 0x0E0)
+					/* Polo GPIO[8:0]  data reg     */
+#define POLO_GPIO_CFG1_REG	regptr(MSP_PER_BASE + 0x0E4)
+					/* Polo GPIO[7:0]  config reg   */
+#define POLO_GPIO_CFG2_REG	regptr(MSP_PER_BASE + 0x0E8)
+					/* Polo GPIO[15:8] config reg   */
+#define POLO_GPIO_OD1_REG	regptr(MSP_PER_BASE + 0x0EC)
+					/* Polo GPIO[31:0] output drive */
+#define POLO_GPIO_CFG3_REG	regptr(MSP_PER_BASE + 0x170)
+					/* Polo GPIO[23:16] config reg  */
+#define POLO_GPIO_DAT2_REG	regptr(MSP_PER_BASE + 0x174)
+					/* Polo GPIO[15:9]  data reg    */
+#define POLO_GPIO_DAT3_REG	regptr(MSP_PER_BASE + 0x178)
+					/* Polo GPIO[23:16]  data reg   */
+#define POLO_GPIO_DAT4_REG	regptr(MSP_PER_BASE + 0x17C)
+					/* Polo GPIO[31:24]  data reg   */
+#define POLO_GPIO_DAT5_REG	regptr(MSP_PER_BASE + 0x180)
+					/* Polo GPIO[39:32]  data reg   */
+#define POLO_GPIO_DAT6_REG	regptr(MSP_PER_BASE + 0x184)
+					/* Polo GPIO[47:40]  data reg   */
+#define POLO_GPIO_DAT7_REG	regptr(MSP_PER_BASE + 0x188)
+					/* Polo GPIO[54:48]  data reg   */
+#define POLO_GPIO_CFG4_REG	regptr(MSP_PER_BASE + 0x18C)
+					/* Polo GPIO[31:24] config reg  */
+#define POLO_GPIO_CFG5_REG	regptr(MSP_PER_BASE + 0x190)
+					/* Polo GPIO[39:32] config reg  */
+#define POLO_GPIO_CFG6_REG	regptr(MSP_PER_BASE + 0x194)
+					/* Polo GPIO[47:40] config reg  */
+#define POLO_GPIO_CFG7_REG	regptr(MSP_PER_BASE + 0x198)
+					/* Polo GPIO[54:48] config reg  */
+#define POLO_GPIO_OD2_REG	regptr(MSP_PER_BASE + 0x19C)
+					/* Polo GPIO[54:32] output drive */
+
+/* Generic GPIO registers                     */
+#define GPIO_DATA1_REG		regptr(MSP_PER_BASE + 0x170)
+					/* GPIO[1:0] data register      */
+#define GPIO_DATA2_REG		regptr(MSP_PER_BASE + 0x174)
+					/* GPIO[5:2] data register      */
+#define GPIO_DATA3_REG		regptr(MSP_PER_BASE + 0x178)
+					/* GPIO[9:6] data register      */
+#define GPIO_DATA4_REG		regptr(MSP_PER_BASE + 0x17C)
+					/* GPIO[15:10] data register    */
+#define GPIO_CFG1_REG		regptr(MSP_PER_BASE + 0x180)
+					/* GPIO[1:0] config register    */
+#define GPIO_CFG2_REG		regptr(MSP_PER_BASE + 0x184)
+					/* GPIO[5:2] config register    */
+#define GPIO_CFG3_REG		regptr(MSP_PER_BASE + 0x188)
+					/* GPIO[9:6] config register    */
+#define GPIO_CFG4_REG		regptr(MSP_PER_BASE + 0x18C)
+					/* GPIO[15:10] config register  */
+#define GPIO_OD_REG		regptr(MSP_PER_BASE + 0x190)
+					/* GPIO[15:0] output drive      */
+
+/*
+ ***************************************************************************
+ * CPU Interface register definitions                                      *
+ ***************************************************************************
+ */
+#define PCI_FLUSH_REG		regptr(MSP_CPUIF_BASE + 0x00)
+					/* PCI-SDRAM queue flush trigger */
+#define OCP_ERR1_REG		regptr(MSP_CPUIF_BASE + 0x04)
+					/* OCP Error Attribute 1        */
+#define OCP_ERR2_REG		regptr(MSP_CPUIF_BASE + 0x08)
+					/* OCP Error Attribute 2        */
+#define OCP_STS_REG		regptr(MSP_CPUIF_BASE + 0x0C)
+					/* OCP Error Status             */
+#define CPUIF_PM_REG		regptr(MSP_CPUIF_BASE + 0x10)
+					/* CPU policy configuration     */
+#define CPUIF_CFG_REG		regptr(MSP_CPUIF_BASE + 0x10)
+					/* Misc configuration options   */
+
+/* Central Interrupt Controller Registers */
+#define MSP_CIC_BASE		(MSP_CPUIF_BASE + 0x8000)
+					/* Central Interrupt registers  */
+#define CIC_EXT_CFG_REG		regptr(MSP_CIC_BASE + 0x00)
+					/* External interrupt config    */
+#define CIC_STS_REG		regptr(MSP_CIC_BASE + 0x04)
+					/* CIC Interrupt Status         */
+#define CIC_VPE0_MSK_REG	regptr(MSP_CIC_BASE + 0x08)
+					/* VPE0 Interrupt Mask          */
+#define CIC_VPE1_MSK_REG	regptr(MSP_CIC_BASE + 0x0C)
+					/* VPE1 Interrupt Mask          */
+#define CIC_TC0_MSK_REG		regptr(MSP_CIC_BASE + 0x10)
+					/* Thread Context 0 Int Mask    */
+#define CIC_TC1_MSK_REG		regptr(MSP_CIC_BASE + 0x14)
+					/* Thread Context 1 Int Mask    */
+#define CIC_TC2_MSK_REG		regptr(MSP_CIC_BASE + 0x18)
+					/* Thread Context 2 Int Mask    */
+#define CIC_TC3_MSK_REG		regptr(MSP_CIC_BASE + 0x18)
+					/* Thread Context 3 Int Mask    */
+#define CIC_TC4_MSK_REG		regptr(MSP_CIC_BASE + 0x18)
+					/* Thread Context 4 Int Mask    */
+#define CIC_PCIMSI_STS_REG	regptr(MSP_CIC_BASE + 0x18)
+#define CIC_PCIMSI_MSK_REG	regptr(MSP_CIC_BASE + 0x18)
+#define CIC_PCIFLSH_REG		regptr(MSP_CIC_BASE + 0x18)
+#define CIC_VPE0_SWINT_REG	regptr(MSP_CIC_BASE + 0x08)
+
+
+/*
+ ***************************************************************************
+ * Memory controller registers                                             *
+ ***************************************************************************
+ */
+#define MEM_CFG1_REG		regptr(MSP_MEM_CFG_BASE + 0x00)
+#define MEM_SS_ADDR		regptr(MSP_MEM_CFG_BASE + 0x00)
+#define MEM_SS_DATA		regptr(MSP_MEM_CFG_BASE + 0x04)
+#define MEM_SS_WRITE		regptr(MSP_MEM_CFG_BASE + 0x08)
+
+/*
+ ***************************************************************************
+ * PCI controller registers                                                *
+ ***************************************************************************
+ */
+#define PCI_BASE_REG		regptr(MSP_PCI_BASE + 0x00)
+#define PCI_CONFIG_SPACE_REG	regptr(MSP_PCI_BASE + 0x800)
+#define PCI_JTAG_DEVID_REG	regptr(MSP_SLP_BASE + 0x13c)
+
+/*
+ ########################################################################
+ #  Register content & macro definitions                                #
+ ########################################################################
+ */
+
+/*
+ ***************************************************************************
+ * DEV_ID defines                                                          *
+ ***************************************************************************
+ */
+#define DEV_ID_PCI_DIS		(1 << 26)       /* Set if PCI disabled */
+#define DEV_ID_PCI_HOST		(1 << 20)       /* Set if PCI host */
+#define DEV_ID_SINGLE_PC	(1 << 19)       /* Set if single PC Card */
+#define DEV_ID_FAMILY		(0xff << 8)     /* family ID code */
+#define POLO_ZEUS_SUB_FAMILY	(0x7  << 16)    /* sub family for Polo/Zeus */
+
+#define MSPFPGA_ID		(0x00  << 8)    /* you are on your own here */
+#define MSP5000_ID		(0x50  << 8)
+#define MSP4F00_ID		(0x4f  << 8)    /* FPGA version of MSP4200 */
+#define MSP4E00_ID		(0x4f  << 8)    /* FPGA version of MSP7120 */
+#define MSP4200_ID		(0x42  << 8)
+#define MSP4000_ID		(0x40  << 8)
+#define MSP2XXX_ID		(0x20  << 8)
+#define MSPZEUS_ID		(0x10  << 8)
+
+#define MSP2004_SUB_ID		(0x0   << 16)
+#define MSP2005_SUB_ID		(0x1   << 16)
+#define MSP2006_SUB_ID		(0x1   << 16)
+#define MSP2007_SUB_ID		(0x2   << 16)
+#define MSP2010_SUB_ID		(0x3   << 16)
+#define MSP2015_SUB_ID		(0x4   << 16)
+#define MSP2020_SUB_ID		(0x5   << 16)
+#define MSP2100_SUB_ID		(0x6   << 16)
+
+/*
+ ***************************************************************************
+ * RESET defines                                                           *
+ ***************************************************************************
+ */
+#define MSP_GR_RST		(0x01 << 0)     /* Global reset bit     */
+#define MSP_MR_RST		(0x01 << 1)     /* MIPS reset bit       */
+#define MSP_PD_RST		(0x01 << 2)     /* PVC DMA reset bit    */
+#define MSP_PP_RST		(0x01 << 3)     /* PVC reset bit        */
+/* reserved                                                             */
+#define MSP_EA_RST		(0x01 << 6)     /* Mac A reset bit      */
+#define MSP_EB_RST		(0x01 << 7)     /* Mac B reset bit      */
+#define MSP_SE_RST		(0x01 << 8)     /* Security Eng reset bit */
+#define MSP_PB_RST		(0x01 << 9)     /* Per block reset bit  */
+#define MSP_EC_RST		(0x01 << 10)    /* Mac C reset bit      */
+#define MSP_TW_RST		(0x01 << 11)    /* TWI reset bit        */
+#define MSP_SPI_RST		(0x01 << 12)    /* SPI/MPI reset bit    */
+#define MSP_U1_RST		(0x01 << 13)    /* UART1 reset bit      */
+#define MSP_U0_RST		(0x01 << 14)    /* UART0 reset bit      */
+
+/*
+ ***************************************************************************
+ * UART defines                                                            *
+ ***************************************************************************
+ */
+#ifndef CONFIG_MSP_FPGA
+#define MSP_BASE_BAUD		25000000
+#else
+#define MSP_BASE_BAUD		6000000
+#endif
+#define MSP_UART_REG_LEN	0x20
+
+/*
+ ***************************************************************************
+ * ELB defines                                                             *
+ ***************************************************************************
+ */
+#define PCCARD_32		0x02    /* Set if is PCCARD 32 (Cardbus) */
+#define SINGLE_PCCARD		0x01    /* Set to enable single PC card */
+
+/*
+ ***************************************************************************
+ * CIC defines                                                             *
+ ***************************************************************************
+ */
+
+/* CIC_EXT_CFG_REG */
+#define EXT_INT_POL(eirq)			(1 << (eirq + 8))
+#define EXT_INT_EDGE(eirq)			(1 << eirq)
+
+#define CIC_EXT_SET_TRIGGER_LEVEL(reg, eirq)	(reg &= ~EXT_INT_EDGE(eirq))
+#define CIC_EXT_SET_TRIGGER_EDGE(reg, eirq)	(reg |= EXT_INT_EDGE(eirq))
+#define CIC_EXT_SET_ACTIVE_HI(reg, eirq)	(reg |= EXT_INT_POL(eirq))
+#define CIC_EXT_SET_ACTIVE_LO(reg, eirq)	(reg &= ~EXT_INT_POL(eirq))
+#define CIC_EXT_SET_ACTIVE_RISING		CIC_EXT_SET_ACTIVE_HI
+#define CIC_EXT_SET_ACTIVE_FALLING		CIC_EXT_SET_ACTIVE_LO
+
+#define CIC_EXT_IS_TRIGGER_LEVEL(reg, eirq) \
+				((reg & EXT_INT_EDGE(eirq)) == 0)
+#define CIC_EXT_IS_TRIGGER_EDGE(reg, eirq)	(reg & EXT_INT_EDGE(eirq))
+#define CIC_EXT_IS_ACTIVE_HI(reg, eirq)		(reg & EXT_INT_POL(eirq))
+#define CIC_EXT_IS_ACTIVE_LO(reg, eirq) \
+				((reg & EXT_INT_POL(eirq)) == 0)
+#define CIC_EXT_IS_ACTIVE_RISING		CIC_EXT_IS_ACTIVE_HI
+#define CIC_EXT_IS_ACTIVE_FALLING		CIC_EXT_IS_ACTIVE_LO
+
+/*
+ ***************************************************************************
+ * Memory Controller defines                                               *
+ ***************************************************************************
+ */
+
+/* Indirect memory controller registers */
+#define DDRC_CFG(n)		(n)
+#define DDRC_DEBUG(n)		(0x04 + n)
+#define DDRC_CTL(n)		(0x40 + n)
+
+/* Macro to perform DDRC indirect write */
+#define DDRC_INDIRECT_WRITE(reg, mask, value) \
+({ \
+	*MEM_SS_ADDR = (((mask) & 0xf) << 8) | ((reg) & 0xff); \
+	*MEM_SS_DATA = (value); \
+	*MEM_SS_WRITE = 1; \
+})
+
+/*
+ ***************************************************************************
+ * SPI/MPI Mode                                                            *
+ ***************************************************************************
+ */
+#define SPI_MPI_RX_BUSY		0x00008000	/* SPI/MPI Receive Busy */
+#define SPI_MPI_FIFO_EMPTY	0x00004000	/* SPI/MPI Fifo Empty   */
+#define SPI_MPI_TX_BUSY		0x00002000	/* SPI/MPI Transmit Busy */
+#define SPI_MPI_FIFO_FULL	0x00001000	/* SPI/MPU FIFO full    */
+
+/*
+ ***************************************************************************
+ * SPI/MPI Control Register                                                *
+ ***************************************************************************
+ */
+#define SPI_MPI_RX_START	0x00000004	/* Start receive command */
+#define SPI_MPI_FLUSH_Q		0x00000002	/* Flush SPI/MPI Queue */
+#define SPI_MPI_TX_START	0x00000001	/* Start Transmit Command */
+
+#endif /* !_ASM_MSP_REGS_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h
new file mode 100644
index 0000000..96d4c8c
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h
@@ -0,0 +1,141 @@
+/*
+ * Defines for the MSP interrupt controller.
+ *
+ * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_SLP_INT_H
+#define _MSP_SLP_INT_H
+
+/*
+ * The PMC-Sierra SLP interrupts are arranged in a 3 level cascaded
+ * hierarchical system.  The first level are the direct MIPS interrupts
+ * and are assigned the interrupt range 0-7.  The second level is the SLM
+ * interrupt controller and is assigned the range 8-39.  The third level
+ * comprises the Peripherial block, the PCI block, the PCI MSI block and
+ * the SLP.  The PCI interrupts and the SLP errors are handled by the
+ * relevant subsystems so the core interrupt code needs only concern
+ * itself with the Peripheral block.  These are assigned interrupts in
+ * the range 40-71.
+ */
+
+/*
+ * IRQs directly connected to CPU
+ */
+#define MSP_MIPS_INTBASE	0
+#define MSP_INT_SW0		0  /* IRQ for swint0,         C_SW0  */
+#define MSP_INT_SW1		1  /* IRQ for swint1,         C_SW1  */
+#define MSP_INT_MAC0 		2  /* IRQ for MAC 0,          C_IRQ0 */
+#define MSP_INT_MAC1		3  /* IRQ for MAC 1,          C_IRQ1 */
+#define MSP_INT_C_IRQ2		4  /* Wired off,              C_IRQ2 */
+#define MSP_INT_VE		5  /* IRQ for Voice Engine,   C_IRQ3 */
+#define MSP_INT_SLP		6  /* IRQ for SLM block,      C_IRQ4 */
+#define MSP_INT_TIMER		7  /* IRQ for the MIPS timer, C_IRQ5 */
+
+/*
+ * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4)
+ * These defines should be tied to the register definition for the SLM
+ * interrupt routine.  For now, just use hard-coded values.
+ */
+#define MSP_SLP_INTBASE		(MSP_MIPS_INTBASE + 8)
+#define MSP_INT_EXT0		(MSP_SLP_INTBASE + 0)
+					/* External interrupt 0         */
+#define MSP_INT_EXT1		(MSP_SLP_INTBASE + 1)
+					/* External interrupt 1         */
+#define MSP_INT_EXT2		(MSP_SLP_INTBASE + 2)
+					/* External interrupt 2         */
+#define MSP_INT_EXT3		(MSP_SLP_INTBASE + 3)
+					/* External interrupt 3         */
+/* Reserved					   4-7                  */
+
+/*
+ *************************************************************************
+ * DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER *
+ * Some MSP produces have this interrupt labelled as Voice and some are  *
+ * SEC mbox ...                                                          *
+ *************************************************************************
+ */
+#define MSP_INT_SLP_VE		(MSP_SLP_INTBASE + 8)
+					/* Cascaded IRQ for Voice Engine*/
+#define MSP_INT_SLP_TDM		(MSP_SLP_INTBASE + 9)
+					/* TDM interrupt                */
+#define MSP_INT_SLP_MAC0	(MSP_SLP_INTBASE + 10)
+					/* Cascaded IRQ for MAC 0       */
+#define MSP_INT_SLP_MAC1	(MSP_SLP_INTBASE + 11)
+					/* Cascaded IRQ for MAC 1       */
+#define MSP_INT_SEC		(MSP_SLP_INTBASE + 12)
+					/* IRQ for security engine      */
+#define	MSP_INT_PER		(MSP_SLP_INTBASE + 13)
+					/* Peripheral interrupt         */
+#define	MSP_INT_TIMER0		(MSP_SLP_INTBASE + 14)
+					/* SLP timer 0                  */
+#define	MSP_INT_TIMER1		(MSP_SLP_INTBASE + 15)
+					/* SLP timer 1                  */
+#define	MSP_INT_TIMER2		(MSP_SLP_INTBASE + 16)
+					/* SLP timer 2                  */
+#define	MSP_INT_SLP_TIMER	(MSP_SLP_INTBASE + 17)
+					/* Cascaded MIPS timer          */
+#define MSP_INT_BLKCP		(MSP_SLP_INTBASE + 18)
+					/* Block Copy                   */
+#define MSP_INT_UART0		(MSP_SLP_INTBASE + 19)
+					/* UART 0                       */
+#define MSP_INT_PCI		(MSP_SLP_INTBASE + 20)
+					/* PCI subsystem                */
+#define MSP_INT_PCI_DBELL	(MSP_SLP_INTBASE + 21)
+					/* PCI doorbell                 */
+#define MSP_INT_PCI_MSI		(MSP_SLP_INTBASE + 22)
+					/* PCI Message Signal           */
+#define MSP_INT_PCI_BC0		(MSP_SLP_INTBASE + 23)
+					/* PCI Block Copy 0             */
+#define MSP_INT_PCI_BC1		(MSP_SLP_INTBASE + 24)
+					/* PCI Block Copy 1             */
+#define MSP_INT_SLP_ERR		(MSP_SLP_INTBASE + 25)
+					/* SLP error condition          */
+#define MSP_INT_MAC2		(MSP_SLP_INTBASE + 26)
+					/* IRQ for MAC2                 */
+/* Reserved					   26-31                */
+
+/*
+ * IRQs cascaded on SLP PER interrupt (MSP_INT_PER)
+ */
+#define MSP_PER_INTBASE		(MSP_SLP_INTBASE + 32)
+/* Reserved					   0-1                  */
+#define MSP_INT_UART1		(MSP_PER_INTBASE + 2)
+					/* UART 1                       */
+/* Reserved					   3-5                  */
+#define MSP_INT_2WIRE		(MSP_PER_INTBASE + 6)
+					/* 2-wire                       */
+#define MSP_INT_TM0		(MSP_PER_INTBASE + 7)
+					/* Peripheral timer block out 0 */
+#define MSP_INT_TM1		(MSP_PER_INTBASE + 8)
+					/* Peripheral timer block out 1 */
+/* Reserved					   9                    */
+#define MSP_INT_SPRX		(MSP_PER_INTBASE + 10)
+					/* SPI RX complete              */
+#define MSP_INT_SPTX		(MSP_PER_INTBASE + 11)
+					/* SPI TX complete              */
+#define MSP_INT_GPIO		(MSP_PER_INTBASE + 12)
+					/* GPIO                         */
+#define MSP_INT_PER_ERR		(MSP_PER_INTBASE + 13)
+					/* Peripheral error             */
+/* Reserved					   14-31                */
+
+#endif /* !_MSP_SLP_INT_H */
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 5f80ba7..1d8b9a8 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -82,10 +82,6 @@
 	unsigned int	fcr31;
 };
 
-#define INIT_FPU { \
-	{0,} \
-}
-
 #define NUM_DSP_REGS   6
 
 typedef __u32 dspreg_t;
@@ -95,8 +91,6 @@
 	unsigned int    dspcontrol;
 };
 
-#define INIT_DSP {{0,},}
-
 #define INIT_CPUMASK { \
 	{0,} \
 }
@@ -155,41 +149,63 @@
 #define MF_N64		0
 
 #ifdef CONFIG_MIPS_MT_FPAFF
-#define FPAFF_INIT 0, INIT_CPUMASK,
+#define FPAFF_INIT						\
+	.emulated_fp			= 0,			\
+	.user_cpus_allowed		= INIT_CPUMASK,
 #else
 #define FPAFF_INIT
 #endif /* CONFIG_MIPS_MT_FPAFF */
 
-#define INIT_THREAD  { \
-        /* \
-         * saved main processor registers \
-         */ \
-	0, 0, 0, 0, 0, 0, 0, 0, \
-	               0, 0, 0, \
-	/* \
-	 * saved cp0 stuff \
-	 */ \
-	0, \
-	/* \
-	 * saved fpu/fpu emulator stuff \
-	 */ \
-	INIT_FPU, \
-	/* \
-	 * fpu affinity state (null if not FPAFF) \
-	 */ \
-	FPAFF_INIT \
-	/* \
-	 * saved dsp/dsp emulator stuff \
-	 */ \
-	INIT_DSP, \
-	/* \
-	 * Other stuff associated with the process \
-	 */ \
-	0, 0, 0, 0, \
-	/* \
-	 * For now the default is to fix address errors \
-	 */ \
-	MF_FIXADE, 0, 0 \
+#define INIT_THREAD  {						\
+        /*							\
+         * Saved main processor registers			\
+         */							\
+	.reg16			= 0,				\
+	.reg17			= 0,				\
+	.reg18			= 0,				\
+	.reg19			= 0,				\
+	.reg20			= 0,				\
+	.reg21			= 0,				\
+	.reg22			= 0,				\
+	.reg23			= 0,				\
+	.reg29			= 0,				\
+	.reg30			= 0,				\
+	.reg31			= 0,				\
+	/*							\
+	 * Saved cp0 stuff					\
+	 */							\
+	.cp0_status		= 0,				\
+	/*							\
+	 * Saved FPU/FPU emulator stuff				\
+	 */							\
+	.fpu			= {				\
+		.fpr		= {0,},				\
+		.fcr31		= 0,				\
+	},							\
+	/*							\
+	 * FPU affinity state (null if not FPAFF)		\
+	 */							\
+	FPAFF_INIT						\
+	/*							\
+	 * Saved DSP stuff					\
+	 */							\
+	.dsp			= {				\
+		.dspr		= {0, },			\
+		.dspcontrol	= 0,				\
+	},							\
+	/*							\
+	 * Other stuff associated with the process		\
+	 */							\
+	.cp0_badvaddr		= 0,				\
+	.cp0_baduaddr		= 0,				\
+	.error_code		= 0,				\
+	.trap_no		= 0,				\
+	/*							\
+	 * For now the default is to fix address errors		\
+	 */							\
+	.mflags			= MF_FIXADE,			\
+	.irix_trampoline	= 0,				\
+	.irix_oldctx		= 0,				\
 }
 
 struct task_struct;
@@ -237,7 +253,7 @@
 
 #define ARCH_HAS_PREFETCH
 
-extern inline void prefetch(const void *addr)
+static inline void prefetch(const void *addr)
 {
 	__asm__ __volatile__(
 	"	.set	mips4		\n"
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 1906938..85b4436 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -86,7 +86,7 @@
 
 extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit);
 
-extern NORET_TYPE void die(const char *, struct pt_regs *);
+extern NORET_TYPE void die(const char *, struct pt_regs *) ATTRIB_NORET;
 
 static inline void die_if_kernel(const char *str, struct pt_regs *regs)
 {
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h
deleted file mode 100644
index 82ad401..0000000
--- a/include/asm-mips/rtc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * include/asm-mips/rtc.h
- *
- * (Really an interface for drivers/char/genrtc.c)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * Please read the COPYING file for all license details.
- */
-
-#ifndef _MIPS_RTC_H
-#define _MIPS_RTC_H
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-#include <asm/time.h>
-
-#define RTC_PIE 0x40            /* periodic interrupt enable */
-#define RTC_AIE 0x20            /* alarm interrupt enable */
-#define RTC_UIE 0x10            /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100      /* battery bad */
-#define RTC_SQWE 0x08           /* enable square-wave output */
-#define RTC_DM_BINARY 0x04      /* all time/date values are BCD if clear */
-#define RTC_24H 0x02            /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01         /* auto switch DST - works f. USA only */
-
-static inline unsigned int get_rtc_time(struct rtc_time *time)
-{
-	unsigned long nowtime;
-
-	nowtime = rtc_mips_get_time();
-	to_tm(nowtime, time);
-	time->tm_year -= 1900;
-
-	return RTC_24H;
-}
-
-static inline int set_rtc_time(struct rtc_time *time)
-{
-	unsigned long nowtime;
-	int ret;
-
-	nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
-			time->tm_mday, time->tm_hour, time->tm_min,
-			time->tm_sec);
-	ret = rtc_mips_set_time(nowtime);
-
-	return ret;
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
-	struct rtc_time h;
-
-	get_rtc_time(&h);
-	return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
-	return -EINVAL;
-}
-
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
-	return -EINVAL;
-}
-#endif
-#endif
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index ce51213..c07ebd8 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -19,159 +19,4 @@
  */
 #define BASE_BAUD (1843200 / 16)
 
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#ifdef CONFIG_MACH_JAZZ
-#include <asm/jazz.h>
-
-#ifndef CONFIG_OLIVETTI_M700
-   /* Some Jazz machines seem to have an 8MHz crystal clock but I don't know
-      exactly which ones ... XXX */
-#define JAZZ_BASE_BAUD ( 8000000 / 16 ) /* ( 3072000 / 16) */
-#else
-/* but the M700 isn't such a strange beast */
-#define JAZZ_BASE_BAUD BASE_BAUD
-#endif
-
-#define _JAZZ_SERIAL_INIT(int, base)					\
-	{ .baud_base = JAZZ_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,	\
-	  .iomem_base = (u8 *) base, .iomem_reg_shift = 0,			\
-	  .io_type = SERIAL_IO_MEM }
-#define JAZZ_SERIAL_PORT_DEFNS						\
-	_JAZZ_SERIAL_INIT(JAZZ_SERIAL1_IRQ, JAZZ_SERIAL1_BASE),		\
-	_JAZZ_SERIAL_INIT(JAZZ_SERIAL2_IRQ, JAZZ_SERIAL2_BASE),
-#else
-#define JAZZ_SERIAL_PORT_DEFNS
-#endif
-
-/*
- * Galileo EV64120 evaluation board
- */
-#ifdef CONFIG_MIPS_EV64120
-#include <mach-gt64120.h>
-#define EV64120_SERIAL_PORT_DEFNS                                  \
-    { .baud_base = EV64120_BASE_BAUD, .irq = EV64120_UART_IRQ, \
-      .flags = STD_COM_FLAGS,  \
-      .iomem_base = EV64120_UART0_REGS_BASE, .iomem_reg_shift = 2, \
-      .io_type = SERIAL_IO_MEM }, \
-    { .baud_base = EV64120_BASE_BAUD, .irq = EV64120_UART_IRQ, \
-      .flags = STD_COM_FLAGS, \
-      .iomem_base = EV64120_UART1_REGS_BASE, .iomem_reg_shift = 2, \
-      .io_type = SERIAL_IO_MEM },
-#else
-#define EV64120_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
-#define STD_SERIAL_PORT_DEFNS			\
-	/* UART CLK   PORT IRQ     FLAGS        */			\
-	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
-	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
-	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
-	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
-
-#else /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-#define STD_SERIAL_PORT_DEFNS
-#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-
-#ifdef CONFIG_MOMENCO_OCELOT_3
-#define OCELOT_3_BASE_BAUD	( 20000000 / 16 )
-#define OCELOT_3_SERIAL_IRQ	6
-#define OCELOT_3_SERIAL_BASE	(signed)0xfd000020
-
-#define _OCELOT_3_SERIAL_INIT(int, base)				\
-	{ .baud_base = OCELOT_3_BASE_BAUD, irq: int, 			\
-	  .flags = STD_COM_FLAGS,						\
-	  .iomem_base = (u8 *) base, iomem_reg_shift: 2,			\
-	  io_type: SERIAL_IO_MEM }
-
-#define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS				\
-	_OCELOT_3_SERIAL_INIT(OCELOT_3_SERIAL_IRQ, OCELOT_3_SERIAL_BASE)
-#else
-#define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MOMENCO_OCELOT
-/* Ordinary NS16552 duart with a 20MHz crystal.  */
-#define OCELOT_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_SERIAL1_IRQ	4
-#define OCELOT_SERIAL1_BASE	0xe0001020
-
-#define _OCELOT_SERIAL_INIT(int, base)					\
-	{ .baud_base = OCELOT_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,	\
-	  .iomem_base = (u8 *) base, .iomem_reg_shift = 2,			\
-	  .io_type = SERIAL_IO_MEM }
-#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS				\
-	_OCELOT_SERIAL_INIT(OCELOT_SERIAL1_IRQ, OCELOT_SERIAL1_BASE)
-#else
-#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MOMENCO_OCELOT_C
-/* Ordinary NS16552 duart with a 20MHz crystal.  */
-#define OCELOT_C_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_C_SERIAL1_IRQ	80
-#define OCELOT_C_SERIAL1_BASE	0xfd000020
-
-#define OCELOT_C_SERIAL2_IRQ	81
-#define OCELOT_C_SERIAL2_BASE	0xfd000000
-
-#define _OCELOT_C_SERIAL_INIT(int, base)				\
-	{ .baud_base		= OCELOT_C_BASE_BAUD,			\
-	  .irq			= (int),				\
-	  .flags		= STD_COM_FLAGS,			\
-	  .iomem_base		= (u8 *) base,				\
-	  .iomem_reg_shift	= 2,					\
-	  .io_type		= SERIAL_IO_MEM				\
-	 }
-#define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS				\
-	_OCELOT_C_SERIAL_INIT(OCELOT_C_SERIAL1_IRQ, OCELOT_C_SERIAL1_BASE), \
-	_OCELOT_C_SERIAL_INIT(OCELOT_C_SERIAL2_IRQ, OCELOT_C_SERIAL2_BASE)
-#else
-#define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_DDB5477
-#include <asm/ddb5xxx/ddb5477.h>
-#define DDB5477_SERIAL_PORT_DEFNS                                       \
-        { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART0, 		\
-	  .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04200, 	\
-	  .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM},		\
-        { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART1, 		\
-	  .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04240, 	\
-	  .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM},
-#else
-#define DDB5477_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_SGI_IP32
-/*
- * The IP32 (SGI O2) has standard serial ports (UART 16550A) mapped in memory
- * They are initialized in ip32_setup
- */
-#define IP32_SERIAL_PORT_DEFNS				\
-        {},{},
-#else
-#define IP32_SERIAL_PORT_DEFNS
-#endif /* CONFIG_SGI_IP32 */
-
-#define SERIAL_PORT_DFNS				\
-	DDB5477_SERIAL_PORT_DEFNS			\
-	EV64120_SERIAL_PORT_DEFNS			\
-	IP32_SERIAL_PORT_DEFNS                          \
-	JAZZ_SERIAL_PORT_DEFNS				\
-	STD_SERIAL_PORT_DEFNS				\
-	MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS		\
-	MOMENCO_OCELOT_SERIAL_PORT_DEFNS		\
-	MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
-
 #endif /* _ASM_SERIAL_H */
diff --git a/include/asm-mips/sibyte/bcm1480_regs.h b/include/asm-mips/sibyte/bcm1480_regs.h
index bda391d..2738c13 100644
--- a/include/asm-mips/sibyte/bcm1480_regs.h
+++ b/include/asm-mips/sibyte/bcm1480_regs.h
@@ -220,17 +220,25 @@
 #define A_BCM1480_DUART(chan)               ((((chan)&2) == 0)? A_BCM1480_DUART0 : A_BCM1480_DUART1)
 
 #define BCM1480_DUART_CHANREG_SPACING       0x100
-#define A_BCM1480_DUART_CHANREG(chan,reg)   (A_BCM1480_DUART(chan) \
-                                     + BCM1480_DUART_CHANREG_SPACING*((chan)&1) \
-                                     + (reg))
-#define R_BCM1480_DUART_CHANREG(chan,reg)   (BCM1480_DUART_CHANREG_SPACING*((chan)&1) + (reg))
+#define A_BCM1480_DUART_CHANREG(chan, reg)				\
+	(A_BCM1480_DUART(chan) +					\
+	 BCM1480_DUART_CHANREG_SPACING * (((chan) & 1) + 1) + (reg))
+#define A_BCM1480_DUART_CTRLREG(chan, reg)				\
+	(A_BCM1480_DUART(chan) +					\
+	 BCM1480_DUART_CHANREG_SPACING * 3 + (reg))
 
-#define R_BCM1480_DUART_IMRREG(chan)	    (R_DUART_IMR_A + ((chan)&1)*DUART_IMRISR_SPACING)
-#define R_BCM1480_DUART_ISRREG(chan)	    (R_DUART_ISR_A + ((chan)&1)*DUART_IMRISR_SPACING)
+#define R_BCM1480_DUART_IMRREG(chan)					\
+	(R_DUART_IMR_A + ((chan) & 1) * DUART_IMRISR_SPACING)
+#define R_BCM1480_DUART_ISRREG(chan)					\
+	(R_DUART_ISR_A + ((chan) & 1) * DUART_IMRISR_SPACING)
 
-#define A_BCM1480_DUART_IMRREG(chan)	    (A_BCM1480_DUART(chan) + R_BCM1480_DUART_IMRREG(chan))
-#define A_BCM1480_DUART_ISRREG(chan)	    (A_BCM1480_DUART(chan) + R_BCM1480_DUART_ISRREG(chan))
-#define A_BCM1480_DUART_IN_PORT(chan)       (A_BCM1480_DUART(chan) + R_DUART_INP_ORT)
+#define A_BCM1480_DUART_IMRREG(chan)					\
+	(A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_IMRREG(chan)))
+#define A_BCM1480_DUART_ISRREG(chan)					\
+	(A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_ISRREG(chan)))
+
+#define A_BCM1480_DUART_IN_PORT(chan)					\
+	(A_BCM1480_DUART_CTRLREG((chan), R_DUART_IN_PORT))
 
 /*
  * These constants are the absolute addresses.
diff --git a/include/asm-mips/sibyte/sb1250_regs.h b/include/asm-mips/sibyte/sb1250_regs.h
index da7c188..220b7e9 100644
--- a/include/asm-mips/sibyte/sb1250_regs.h
+++ b/include/asm-mips/sibyte/sb1250_regs.h
@@ -272,59 +272,69 @@
     ********************************************************************* */
 
 
-#if SIBYTE_HDR_FEATURE_1250_112x		/* This MC only on 1250 & 112x */
+#if SIBYTE_HDR_FEATURE_1250_112x    /* This MC only on 1250 & 112x */
 #define R_DUART_NUM_PORTS           2
 
 #define A_DUART                     0x0010060000
 
 #define DUART_CHANREG_SPACING       0x100
-#define A_DUART_CHANREG(chan,reg)   (A_DUART + DUART_CHANREG_SPACING*(chan) + (reg))
-#define R_DUART_CHANREG(chan,reg)   (DUART_CHANREG_SPACING*(chan) + (reg))
+
+#define A_DUART_CHANREG(chan, reg)					\
+	(A_DUART + DUART_CHANREG_SPACING * ((chan) + 1) + (reg))
 #endif	/* 1250 & 112x */
 
-#define R_DUART_MODE_REG_1	    0x100
-#define R_DUART_MODE_REG_2	    0x110
-#define R_DUART_STATUS              0x120
-#define R_DUART_CLK_SEL             0x130
-#define R_DUART_CMD                 0x150
-#define R_DUART_RX_HOLD             0x160
-#define R_DUART_TX_HOLD             0x170
+#define R_DUART_MODE_REG_1	    0x000
+#define R_DUART_MODE_REG_2	    0x010
+#define R_DUART_STATUS		    0x020
+#define R_DUART_CLK_SEL		    0x030
+#define R_DUART_CMD		    0x050
+#define R_DUART_RX_HOLD		    0x060
+#define R_DUART_TX_HOLD		    0x070
 
 #if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
-#define R_DUART_FULL_CTL	    0x140
-#define R_DUART_OPCR_X		    0x180
-#define R_DUART_AUXCTL_X	    0x190
-#endif /* 1250 PASS2 || 112x PASS1 || 1480*/
+#define R_DUART_FULL_CTL	    0x040
+#define R_DUART_OPCR_X		    0x080
+#define R_DUART_AUXCTL_X	    0x090
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
 
 /*
  * The IMR and ISR can't be addressed with A_DUART_CHANREG,
- * so use this macro instead.
+ * so use these macros instead.
  */
 
-#define R_DUART_AUX_CTRL            0x310
-#define R_DUART_ISR_A               0x320
-#define R_DUART_IMR_A               0x330
-#define R_DUART_ISR_B               0x340
-#define R_DUART_IMR_B               0x350
-#define R_DUART_OUT_PORT            0x360
-#define R_DUART_OPCR                0x370
-#define R_DUART_IN_PORT             0x380
+#if SIBYTE_HDR_FEATURE_1250_112x    /* This MC only on 1250 & 112x */
+#define DUART_IMRISR_SPACING	    0x20
+#define DUART_INCHNG_SPACING	    0x10
 
-#define R_DUART_SET_OPR		    0x3B0
-#define R_DUART_CLEAR_OPR	    0x3C0
+#define A_DUART_CTRLREG(reg)						\
+	(A_DUART + DUART_CHANREG_SPACING * 3 + (reg))
 
-#define DUART_IMRISR_SPACING        0x20
+#define R_DUART_IMRREG(chan)						\
+	(R_DUART_IMR_A + (chan) * DUART_IMRISR_SPACING)
+#define R_DUART_ISRREG(chan)						\
+	(R_DUART_ISR_A + (chan) * DUART_IMRISR_SPACING)
+#define R_DUART_INCHREG(chan)						\
+	(R_DUART_IN_CHNG_A + (chan) * DUART_INCHNG_SPACING)
 
-#if SIBYTE_HDR_FEATURE_1250_112x		/* This MC only on 1250 & 112x */
-#define R_DUART_IMRREG(chan)	    (R_DUART_IMR_A + (chan)*DUART_IMRISR_SPACING)
-#define R_DUART_ISRREG(chan)	    (R_DUART_ISR_A + (chan)*DUART_IMRISR_SPACING)
-
-#define A_DUART_IMRREG(chan)	    (A_DUART + R_DUART_IMRREG(chan))
-#define A_DUART_ISRREG(chan)	    (A_DUART + R_DUART_ISRREG(chan))
+#define A_DUART_IMRREG(chan)	    A_DUART_CTRLREG(R_DUART_IMRREG(chan))
+#define A_DUART_ISRREG(chan)	    A_DUART_CTRLREG(R_DUART_ISRREG(chan))
+#define A_DUART_INCHREG(chan)	    A_DUART_CTRLREG(R_DUART_INCHREG(chan))
 #endif	/* 1250 & 112x */
 
+#define R_DUART_AUX_CTRL	    0x010
+#define R_DUART_ISR_A		    0x020
+#define R_DUART_IMR_A		    0x030
+#define R_DUART_ISR_B		    0x040
+#define R_DUART_IMR_B		    0x050
+#define R_DUART_OUT_PORT	    0x060
+#define R_DUART_OPCR		    0x070
+#define R_DUART_IN_PORT		    0x080
 
+#define R_DUART_SET_OPR		    0x0B0
+#define R_DUART_CLEAR_OPR	    0x0C0
+#define R_DUART_IN_CHNG_A	    0x0D0
+#define R_DUART_IN_CHNG_B	    0x0E0
 
 
 /*
diff --git a/include/asm-mips/sibyte/sb1250_uart.h b/include/asm-mips/sibyte/sb1250_uart.h
index e87045e..cf74fed 100644
--- a/include/asm-mips/sibyte/sb1250_uart.h
+++ b/include/asm-mips/sibyte/sb1250_uart.h
@@ -75,7 +75,8 @@
 #define V_DUART_PARITY_MODE_ADD_FIXED V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_ADD_FIXED)
 #define V_DUART_PARITY_MODE_NONE      V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_NONE)
 
-#define M_DUART_ERR_MODE            _SB_MAKEMASK1(5)    /* must be zero */
+#define M_DUART_TX_IRQ_SEL_TXRDY    0
+#define M_DUART_TX_IRQ_SEL_TXEMPT   _SB_MAKEMASK1(5)
 
 #define M_DUART_RX_IRQ_SEL_RXRDY    0
 #define M_DUART_RX_IRQ_SEL_RXFULL   _SB_MAKEMASK1(6)
@@ -246,10 +247,13 @@
 
 #define M_DUART_ISR_BRK_A           _SB_MAKEMASK1(2)
 #define M_DUART_ISR_IN_A            _SB_MAKEMASK1(3)
+#define M_DUART_ISR_ALL_A	    _SB_MAKEMASK(4,0)
+
 #define M_DUART_ISR_TX_B            _SB_MAKEMASK1(4)
 #define M_DUART_ISR_RX_B            _SB_MAKEMASK1(5)
 #define M_DUART_ISR_BRK_B           _SB_MAKEMASK1(6)
 #define M_DUART_ISR_IN_B            _SB_MAKEMASK1(7)
+#define M_DUART_ISR_ALL_B	    _SB_MAKEMASK(4,4)
 
 /*
  * DUART Channel A Interrupt Status Register (Table 10-17)
@@ -262,6 +266,7 @@
 #define M_DUART_ISR_RX              _SB_MAKEMASK1(1)
 #define M_DUART_ISR_BRK             _SB_MAKEMASK1(2)
 #define M_DUART_ISR_IN              _SB_MAKEMASK1(3)
+#define M_DUART_ISR_ALL		    _SB_MAKEMASK(4,0)
 #define M_DUART_ISR_RESERVED        _SB_MAKEMASK(4,4)
 
 /*
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index 1608fd7..13aef6a 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -49,13 +49,6 @@
 extern cpumask_t phys_cpu_present_map;
 #define cpu_possible_map	phys_cpu_present_map
 
-extern cpumask_t cpu_callout_map;
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
-static inline int num_booting_cpus(void)
-{
-	return cpus_weight(cpu_callout_map);
-}
-
 /*
  * These are defined by the board-specific code.
  */
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
index f257509..ddaf36a 100644
--- a/include/asm-mips/sni.h
+++ b/include/asm-mips/sni.h
@@ -146,9 +146,6 @@
 #define SNI_A20R_IRQ_BASE       MIPS_CPU_IRQ_BASE
 #define SNI_A20R_IRQ_TIMER      (SNI_A20R_IRQ_BASE+5)
 
-#define SNI_DS1216_A20R_BASE    0xbc081ffc
-#define SNI_DS1216_RM200_BASE   0xbcd41ffc
-
 #define SNI_PCIT_INT_REG        0xbfff000c
 
 #define SNI_PCIT_INT_START      24
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 7afa1fd..ed33366b 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -17,6 +17,18 @@
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
 
+/*
+ * For SMTC kernel, global IE should be left set, and interrupts
+ * controlled exclusively via IXMT.
+ */
+#ifdef CONFIG_MIPS_MT_SMTC
+#define STATMASK 0x1e
+#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+#define STATMASK 0x3f
+#else
+#define STATMASK 0x1f
+#endif
+
 #ifdef CONFIG_MIPS_MT_SMTC
 #include <asm/mipsmtregs.h>
 #endif /* CONFIG_MIPS_MT_SMTC */
@@ -236,10 +248,10 @@
 		.set	reorder
 		.set	noat
 		mfc0	a0, CP0_STATUS
-		ori	a0, 0x1f
-		xori	a0, 0x1f
-		mtc0	a0, CP0_STATUS
 		li	v1, 0xff00
+		ori	a0, STATMASK
+		xori	a0, STATMASK
+		mtc0	a0, CP0_STATUS
 		and	a0, v1
 		LONG_L	v0, PT_STATUS(sp)
 		nor	v1, $0, v1
@@ -249,10 +261,6 @@
 		LONG_L	$31, PT_R31(sp)
 		LONG_L	$28, PT_R28(sp)
 		LONG_L	$25, PT_R25(sp)
-#ifdef CONFIG_64BIT
-		LONG_L	$8, PT_R8(sp)
-		LONG_L	$9, PT_R9(sp)
-#endif
 		LONG_L	$7,  PT_R7(sp)
 		LONG_L	$6,  PT_R6(sp)
 		LONG_L	$5,  PT_R5(sp)
@@ -273,16 +281,6 @@
 		.endm
 
 #else
-/*
- * For SMTC kernel, global IE should be left set, and interrupts
- * controlled exclusively via IXMT.
- */
-
-#ifdef CONFIG_MIPS_MT_SMTC
-#define STATMASK 0x1e
-#else
-#define STATMASK 0x1f
-#endif
 		.macro	RESTORE_SOME
 		.set	push
 		.set	reorder
@@ -385,9 +383,9 @@
 		.macro	CLI
 #if !defined(CONFIG_MIPS_MT_SMTC)
 		mfc0	t0, CP0_STATUS
-		li	t1, ST0_CU0 | 0x1f
+		li	t1, ST0_CU0 | STATMASK
 		or	t0, t1
-		xori	t0, 0x1f
+		xori	t0, STATMASK
 		mtc0	t0, CP0_STATUS
 #else /* CONFIG_MIPS_MT_SMTC */
 		/*
@@ -420,9 +418,9 @@
 		.macro	STI
 #if !defined(CONFIG_MIPS_MT_SMTC)
 		mfc0	t0, CP0_STATUS
-		li	t1, ST0_CU0 | 0x1f
+		li	t1, ST0_CU0 | STATMASK
 		or	t0, t1
-		xori	t0, 0x1e
+		xori	t0, STATMASK & ~1
 		mtc0	t0, CP0_STATUS
 #else /* CONFIG_MIPS_MT_SMTC */
 		/*
@@ -451,7 +449,8 @@
 		.endm
 
 /*
- * Just move to kernel mode and leave interrupts as they are.
+ * Just move to kernel mode and leave interrupts as they are.  Note
+ * for the R3000 this means copying the previous enable from IEp.
  * Set cp0 enable bit as sign that we're running on the kernel stack
  */
 		.macro	KMODE
@@ -482,9 +481,14 @@
 		move	ra, t0
 #endif /* CONFIG_MIPS_MT_SMTC */
 		mfc0	t0, CP0_STATUS
-		li	t1, ST0_CU0 | 0x1e
+		li	t1, ST0_CU0 | (STATMASK & ~1)
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+		andi	t2, t0, ST0_IEP
+		srl	t2, 2
+		or	t0, t2
+#endif
 		or	t0, t1
-		xori	t0, 0x1e
+		xori	t0, STATMASK & ~1
 		mtc0	t0, CP0_STATUS
 #ifdef CONFIG_MIPS_MT_SMTC
 		_ehb
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index bb0b289..46bdb3f 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -44,7 +44,7 @@
  * different thread.
  */
 
-#define switch_to(prev,next,last)					\
+#define __mips_mt_fpaff_switch_to(prev)					\
 do {									\
 	if (cpu_has_fpu &&						\
 	    (prev->thread.mflags & MF_FPUBOUND) &&			\
@@ -52,24 +52,24 @@
 		prev->thread.mflags &= ~MF_FPUBOUND;			\
 		prev->cpus_allowed = prev->thread.user_cpus_allowed;	\
 	}								\
-	if (cpu_has_dsp)						\
-		__save_dsp(prev);					\
 	next->thread.emulated_fp = 0;					\
-	(last) = resume(prev, next, task_thread_info(next));		\
-	if (cpu_has_dsp)						\
-		__restore_dsp(current);					\
 } while(0)
 
 #else
+#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
+#endif
+
 #define switch_to(prev,next,last)					\
 do {									\
+	__mips_mt_fpaff_switch_to(prev);				\
 	if (cpu_has_dsp)						\
 		__save_dsp(prev);					\
 	(last) = resume(prev, next, task_thread_info(next));		\
 	if (cpu_has_dsp)						\
 		__restore_dsp(current);					\
+	if (cpu_has_userlocal)						\
+		write_c0_userlocal(task_thread_info(current)->tp_value);\
 } while(0)
-#endif
 
 /*
  * On SMP systems, when the scheduler does migration-cost autodetection,
diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h
index 0bbe07b..5bfdc3b 100644
--- a/include/asm-mips/termbits.h
+++ b/include/asm-mips/termbits.h
@@ -30,6 +30,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-mips/tlbdebug.h b/include/asm-mips/tlbdebug.h
index fff7a73..bb8f5c2 100644
--- a/include/asm-mips/tlbdebug.h
+++ b/include/asm-mips/tlbdebug.h
@@ -11,10 +11,6 @@
 /*
  * TLB debugging functions:
  */
-extern void dump_tlb(int first, int last);
 extern void dump_tlb_all(void);
-extern void dump_tlb_wired(void);
-extern void dump_tlb_addr(unsigned long addr);
-extern void dump_tlb_nonwired(void);
 
 #endif /* __ASM_TLBDEBUG_H */
diff --git a/include/asm-mips/tx4938/rbtx4938.h b/include/asm-mips/tx4938/rbtx4938.h
index 0fbedaf..74e7d80 100644
--- a/include/asm-mips/tx4938/rbtx4938.h
+++ b/include/asm-mips/tx4938/rbtx4938.h
@@ -105,12 +105,6 @@
 #define rbtx4938_pcireset_ptr	\
 	((volatile unsigned char *)RBTX4938_PCIRESET_ADDR)
 
-/* SPI */
-#define RBTX4938_SEEPROM1_CHIPID	0
-#define RBTX4938_SEEPROM2_CHIPID	1
-#define RBTX4938_SEEPROM3_CHIPID	2
-#define RBTX4938_SRTC_CHIPID	3
-
 /*
  * IRQ mappings
  */
diff --git a/include/asm-mips/tx4938/spi.h b/include/asm-mips/tx4938/spi.h
index 0dbbab8..6a60c83 100644
--- a/include/asm-mips/tx4938/spi.h
+++ b/include/asm-mips/tx4938/spi.h
@@ -14,61 +14,7 @@
 #ifndef __ASM_TX_BOARDS_TX4938_SPI_H
 #define __ASM_TX_BOARDS_TX4938_SPI_H
 
-/* SPI */
-struct spi_dev_desc {
-	unsigned int baud;
-	unsigned short tcss, tcsh, tcsr; /* CS setup/hold/recovery time */
-	unsigned int byteorder:1;	/* 0:LSB-First, 1:MSB-First */
-	unsigned int polarity:1;	/* 0:High-Active */
-	unsigned int phase:1;		/* 0:Sample-Then-Shift */
-};
-
-extern void txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on)) __init;
-extern void txx9_spi_irqinit(int irc_irq) __init;
-extern int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
-		       unsigned char **inbufs, unsigned int *incounts,
-		       unsigned char **outbufs, unsigned int *outcounts,
-		       int cansleep);
-extern int spi_eeprom_write_enable(int chipid, int enable);
-extern int spi_eeprom_read_status(int chipid);
+extern int spi_eeprom_register(int chipid);
 extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
-extern int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len);
-extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid) __init;
-
-#define TXX9_IMCLK     (txx9_gbus_clock / 2)
-
-/*
-* SPI
-*/
-
-/* SPMCR : SPI Master Control */
-#define TXx9_SPMCR_OPMODE	0xc0
-#define TXx9_SPMCR_CONFIG	0x40
-#define TXx9_SPMCR_ACTIVE	0x80
-#define TXx9_SPMCR_SPSTP	0x02
-#define TXx9_SPMCR_BCLR	0x01
-
-/* SPCR0 : SPI Status */
-#define TXx9_SPCR0_TXIFL_MASK	0xc000
-#define TXx9_SPCR0_RXIFL_MASK	0x3000
-#define TXx9_SPCR0_SIDIE	0x0800
-#define TXx9_SPCR0_SOEIE	0x0400
-#define TXx9_SPCR0_RBSIE	0x0200
-#define TXx9_SPCR0_TBSIE	0x0100
-#define TXx9_SPCR0_IFSPSE	0x0010
-#define TXx9_SPCR0_SBOS	0x0004
-#define TXx9_SPCR0_SPHA	0x0002
-#define TXx9_SPCR0_SPOL	0x0001
-
-/* SPSR : SPI Status */
-#define TXx9_SPSR_TBSI	0x8000
-#define TXx9_SPSR_RBSI	0x4000
-#define TXx9_SPSR_TBS_MASK	0x3800
-#define TXx9_SPSR_RBS_MASK	0x0700
-#define TXx9_SPSR_SPOE	0x0080
-#define TXx9_SPSR_IFSD	0x0008
-#define TXx9_SPSR_SIDLE	0x0004
-#define TXx9_SPSR_STRDY	0x0002
-#define TXx9_SPSR_SRRDY	0x0001
 
 #endif /* __ASM_TX_BOARDS_TX4938_SPI_H */
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 2f1087b..ed16de0 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -336,16 +336,20 @@
 #define __NR_epoll_pwait		(__NR_Linux + 313)
 #define __NR_ioprio_set			(__NR_Linux + 314)
 #define __NR_ioprio_get			(__NR_Linux + 315)
+#define __NR_utimensat			(__NR_Linux + 316)
+#define __NR_signalfd			(__NR_Linux + 317)
+#define __NR_timerfd			(__NR_Linux + 318)
+#define __NR_eventfd			(__NR_Linux + 319)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		315
+#define __NR_Linux_syscalls		319
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		315
+#define __NR_O32_Linux_syscalls		319
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -628,16 +632,20 @@
 #define __NR_epoll_pwait		(__NR_Linux + 272)
 #define __NR_ioprio_set			(__NR_Linux + 273)
 #define __NR_ioprio_get			(__NR_Linux + 274)
+#define __NR_utimensat			(__NR_Linux + 275)
+#define __NR_signalfd			(__NR_Linux + 276)
+#define __NR_timerfd			(__NR_Linux + 277)
+#define __NR_eventfd			(__NR_Linux + 278)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		274
+#define __NR_Linux_syscalls		278
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		274
+#define __NR_64_Linux_syscalls		278
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -924,16 +932,20 @@
 #define __NR_epoll_pwait		(__NR_Linux + 276)
 #define __NR_ioprio_set			(__NR_Linux + 277)
 #define __NR_ioprio_get			(__NR_Linux + 278)
+#define __NR_utimensat			(__NR_Linux + 279)
+#define __NR_signalfd			(__NR_Linux + 280)
+#define __NR_timerfd			(__NR_Linux + 281)
+#define __NR_eventfd			(__NR_Linux + 282)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		278
+#define __NR_Linux_syscalls		282
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		278
+#define __NR_N32_Linux_syscalls		282
 
 #ifdef __KERNEL__
 
@@ -949,7 +961,6 @@
 #define __ARCH_WANT_SYS_UTIME
 #define __ARCH_WANT_SYS_WAITPID
 #define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
 #define __ARCH_WANT_SYS_GETPGRP
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
@@ -966,6 +977,22 @@
 #  define __ARCH_WANT_COMPAT_SYS_TIME
 # endif
 
+/* whitelists for checksyscalls */
+#define __IGNORE_select
+#define __IGNORE_vfork
+#define __IGNORE_time
+#define __IGNORE_uselib
+#define __IGNORE_fadvise64_64
+#define __IGNORE_getdents64
+#if _MIPS_SIM == _MIPS_SIM_NABI32
+#define __IGNORE_truncate64
+#define __IGNORE_ftruncate64
+#define __IGNORE_stat64
+#define __IGNORE_lstat64
+#define __IGNORE_fstat64
+#define __IGNORE_fstatat64
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 /*
diff --git a/include/asm-mips/vr41xx/giu.h b/include/asm-mips/vr41xx/giu.h
index 8109cda..0bcdd3a 100644
--- a/include/asm-mips/vr41xx/giu.h
+++ b/include/asm-mips/vr41xx/giu.h
@@ -20,6 +20,15 @@
 #ifndef __NEC_VR41XX_GIU_H
 #define __NEC_VR41XX_GIU_H
 
+/*
+ * NEC VR4100 series GIU platform device IDs.
+ */
+enum {
+	GPIO_50PINS_PULLUPDOWN,
+	GPIO_36PINS,
+	GPIO_48PINS_EDGE_SELECT,
+};
+
 typedef enum {
 	IRQ_TRIGGER_LEVEL,
 	IRQ_TRIGGER_EDGE,
diff --git a/include/asm-mips/vr41xx/siu.h b/include/asm-mips/vr41xx/siu.h
index 1fcf6e8..98cdb40 100644
--- a/include/asm-mips/vr41xx/siu.h
+++ b/include/asm-mips/vr41xx/siu.h
@@ -20,6 +20,8 @@
 #ifndef __NEC_VR41XX_SIU_H
 #define __NEC_VR41XX_SIU_H
 
+#define SIU_PORTS_MAX 2
+
 typedef enum {
 	SIU_INTERFACE_RS232C,
 	SIU_INTERFACE_IRDA,
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index 13a3502..9de52a5 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -169,26 +169,28 @@
 
 /*
  * On the RM9000 there is a problem which makes the CreateDirtyExclusive
- * cache operation unusable on SMP systems.
+ * eache operation unusable on SMP systems.
  */
-#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE) || \
-    defined(CONFIG_BASLER_EXCITE)
+#if defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE)
 #define  RM9000_CDEX_SMP_WAR		1
 #endif
 
 /*
- * The RM9000 has a bug (though PMC-Sierra opposes it being called that)
- * where invalid instructions in the same I-cache line worth of instructions
- * being fetched may case spurious exceptions.
+ * The RM7000 processors and the E9000 cores have a bug (though PMC-Sierra
+ * opposes it being called that) where invalid instructions in the same
+ * I-cache line worth of instructions being fetched may case spurious
+ * exceptions.
  */
-#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
-    defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE)
+#if defined(CONFIG_BASLER_EXCITE) || defined(CONFIG_MIPS_ATLAS) || \
+    defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MOMENCO_OCELOT) || \
+    defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_SGI_IP32) || \
+    defined(CONFIG_WR_PPMC)
 #define ICACHE_REFILLS_WORKAROUND_WAR	1
 #endif
 
 
 /*
- * ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
+ * On the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
  * may cause ll / sc and lld / scd sequences to execute non-atomically.
  */
 #ifdef CONFIG_SGI_IP27
@@ -196,6 +198,14 @@
 #endif
 
 /*
+ * 34K core erratum: "Problems Executing the TLBR Instruction"
+ */
+#if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \
+	defined(CONFIG_PMC_MSP7120_FPGA)
+#define MIPS34K_MISSED_ITLB_WAR		1
+#endif
+
+/*
  * Workarounds default to off
  */
 #ifndef ICACHE_REFILLS_WORKAROUND_WAR
@@ -234,5 +244,8 @@
 #ifndef R10000_LLSC_WAR
 #define R10000_LLSC_WAR			0
 #endif
+#ifndef MIPS34K_MISSED_ITLB_WAR
+#define MIPS34K_MISSED_ITLB_WAR		0
+#endif
 
 #endif /* _ASM_WAR_H */
diff --git a/include/asm-mips/watch.h b/include/asm-mips/watch.h
deleted file mode 100644
index 6aa90ca..0000000
--- a/include/asm-mips/watch.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997, 1998, 2000, 2001 by Ralf Baechle
- */
-#ifndef _ASM_WATCH_H
-#define _ASM_WATCH_H
-
-#include <linux/linkage.h>
-
-/*
- * Types of reference for watch_set()
- */
-enum wref_type {
-	wr_save = 1,
-	wr_load = 2
-};
-
-extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref);
-extern asmlinkage void __watch_clear(void);
-extern asmlinkage void __watch_reenable(void);
-
-#define watch_set(addr, ref)					\
-	if (cpu_has_watch)					\
-		__watch_set(addr, ref)
-#define watch_clear()						\
-	if (cpu_has_watch)					\
-		__watch_clear()
-#define watch_reenable()					\
-	if (cpu_has_watch)					\
-		__watch_reenable()
-
-#endif /* _ASM_WATCH_H */
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index 11f4222..5a85d1b 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -31,8 +31,10 @@
 
 typedef s32	compat_int_t;
 typedef s32	compat_long_t;
+typedef s64	compat_s64;
 typedef u32	compat_uint_t;
 typedef u32	compat_ulong_t;
+typedef u64	compat_u64;
 
 struct compat_timespec {
 	compat_time_t		tv_sec;
diff --git a/include/asm-parisc/fb.h b/include/asm-parisc/fb.h
new file mode 100644
index 0000000..4d503a0
--- /dev/null
+++ b/include/asm-parisc/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-parisc/fcntl.h b/include/asm-parisc/fcntl.h
index 317851f..1e1c824 100644
--- a/include/asm-parisc/fcntl.h
+++ b/include/asm-parisc/fcntl.h
@@ -3,21 +3,22 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_APPEND	00000010
-#define O_BLKSEEK	00000100 /* HPUX only */
-#define O_CREAT		00000400 /* not fcntl */
-#define O_EXCL		00002000 /* not fcntl */
-#define O_LARGEFILE	00004000
-#define O_SYNC		00100000
-#define O_NONBLOCK	00200004 /* HPUX has separate NDELAY & NONBLOCK */
-#define O_NOCTTY	00400000 /* not fcntl */
-#define O_DSYNC		01000000 /* HPUX only */
-#define O_RSYNC		02000000 /* HPUX only */
-#define O_NOATIME	04000000
+#define O_APPEND	000000010
+#define O_BLKSEEK	000000100 /* HPUX only */
+#define O_CREAT		000000400 /* not fcntl */
+#define O_EXCL		000002000 /* not fcntl */
+#define O_LARGEFILE	000004000
+#define O_SYNC		000100000
+#define O_NONBLOCK	000200004 /* HPUX has separate NDELAY & NONBLOCK */
+#define O_NOCTTY	000400000 /* not fcntl */
+#define O_DSYNC		001000000 /* HPUX only */
+#define O_RSYNC		002000000 /* HPUX only */
+#define O_NOATIME	004000000
+#define O_CLOEXEC	010000000 /* set close_on_exec */
 
-#define O_DIRECTORY	00010000 /* must be a directory */
-#define O_NOFOLLOW	00000200 /* don't follow links */
-#define O_INVISIBLE	04000000 /* invisible I/O, for DMAPI/XDSM */
+#define O_DIRECTORY	000010000 /* must be a directory */
+#define O_NOFOLLOW	000000200 /* don't follow links */
+#define O_INVISIBLE	004000000 /* invisible I/O, for DMAPI/XDSM */
 
 #define F_GETLK64	8
 #define F_SETLK64	9
diff --git a/include/asm-parisc/hardware.h b/include/asm-parisc/hardware.h
index 76d880d..4e96268 100644
--- a/include/asm-parisc/hardware.h
+++ b/include/asm-parisc/hardware.h
@@ -31,10 +31,11 @@
 	pcxw	= 8, /* pa8500		pa 2.0  */
 	pcxw_	= 9, /* pa8600	(w+)	pa 2.0  */
 	pcxw2	= 10, /* pa8700		pa 2.0  */
-	mako	= 11  /* pa8800		pa 2.0  */
+	mako	= 11, /* pa8800		pa 2.0  */
+	mako2	= 12  /* pa8900		pa 2.0  */
 };
 
-extern char *cpu_name_version[][2]; /* mapping from enum cpu_type to strings */
+extern const char * const cpu_name_version[][2]; /* mapping from enum cpu_type to strings */
 
 struct parisc_driver;
 
diff --git a/include/asm-parisc/linkage.h b/include/asm-parisc/linkage.h
index 7a09d91..ad8cd0d0 100644
--- a/include/asm-parisc/linkage.h
+++ b/include/asm-parisc/linkage.h
@@ -8,8 +8,10 @@
 
 /*
  * In parisc assembly a semicolon marks a comment while a
- * exclamation mark is used to seperate independend lines.
+ * exclamation mark is used to seperate independent lines.
  */
+#ifdef __ASSEMBLY__
+
 #define ENTRY(name) \
 	.export name !\
 	ALIGN !\
@@ -24,5 +26,6 @@
 	END(name)
 #endif
 
+#endif /* __ASSEMBLY__ */
 
 #endif  /* __ASM_PARISC_LINKAGE_H */
diff --git a/include/asm-parisc/mmu_context.h b/include/asm-parisc/mmu_context.h
index bad6902..85856c7 100644
--- a/include/asm-parisc/mmu_context.h
+++ b/include/asm-parisc/mmu_context.h
@@ -2,6 +2,7 @@
 #define __PARISC_MMU_CONTEXT_H
 
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index 7b3be9a..61fbd57 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -238,9 +238,6 @@
 #define PCIBIOS_MIN_IO          0x10
 #define PCIBIOS_MIN_MEM         0x1000 /* NBPG - but pci/setup-res.c dies */
 
-/* Don't support DAC yet. */
-#define pci_dac_dma_supported(pci_dev, mask)   (0)
-
 /* export the pci_ DMA API in terms of the dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
@@ -284,10 +281,6 @@
 	return root;
 }
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 static inline void pcibios_penalize_isa_irq(int irq, int active)
 {
 	/* We don't need to penalize isa irq's */
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index beb2adb..e88cacd 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -335,18 +335,14 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-extern inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_READ; }
 extern inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 extern inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 extern inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_WRITE; }
 extern inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
-extern inline int pte_user(pte_t pte) 		{ return pte_val(pte) & _PAGE_USER; }
 
-extern inline pte_t pte_rdprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_READ; return pte; }
 extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
 extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 extern inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_WRITE; return pte; }
-extern inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_READ; return pte; }
 extern inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 extern inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_WRITE; return pte; }
@@ -451,21 +447,6 @@
 #endif
 }
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
-	if (!pte_dirty(*ptep))
-		return 0;
-	return test_and_clear_bit(xlate_pabit(_PAGE_DIRTY_BIT), &pte_val(*ptep));
-#else
-	pte_t pte = *ptep;
-	if (!pte_dirty(pte))
-		return 0;
-	set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
-	return 1;
-#endif
-}
-
 extern spinlock_t pa_dbit_lock;
 
 struct mm_struct;
@@ -533,7 +514,6 @@
 #define HAVE_ARCH_UNMAPPED_AREA
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
index d2f3967..6b294fb 100644
--- a/include/asm-parisc/processor.h
+++ b/include/asm-parisc/processor.h
@@ -69,8 +69,8 @@
 		char   sys_model_name[81]; /* PDC-ROM returnes this model name */
 	} pdc;
 
-	char		*cpu_name;	/* e.g. "PA7300LC (PCX-L2)" */
-	char		*family_name;	/* e.g. "1.1e" */
+	const char	*cpu_name;	/* e.g. "PA7300LC (PCX-L2)" */
+	const char	*family_name;	/* e.g. "1.1e" */
 };
 
 
@@ -334,8 +334,8 @@
 static inline int parisc_requires_coherency(void)
 {
 #ifdef CONFIG_PA8X00
-	/* FIXME: also pa8900 - when we see one */
-	return boot_cpu_data.cpu_type == mako;
+	return (boot_cpu_data.cpu_type == mako) ||
+		(boot_cpu_data.cpu_type == mako2);
 #else
 	return 0;
 #endif
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h
index 7e9afa7..21fbfc5 100644
--- a/include/asm-parisc/system.h
+++ b/include/asm-parisc/system.h
@@ -188,7 +188,6 @@
 # define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
 #endif
 
-#define KERNEL_START (0x10100000 - 0x1000)
 #define arch_align_stack(x) (x)
 
 #endif
diff --git a/include/asm-parisc/termbits.h b/include/asm-parisc/termbits.h
index a46e299..e847fe9 100644
--- a/include/asm-parisc/termbits.h
+++ b/include/asm-parisc/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-parisc/tlbflush.h b/include/asm-parisc/tlbflush.h
index 3313da9..270cf30 100644
--- a/include/asm-parisc/tlbflush.h
+++ b/include/asm-parisc/tlbflush.h
@@ -4,6 +4,7 @@
 /* TLB flushing routines.... */
 
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <asm/mmu_context.h>
 
 
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index 2f7c408..f74099b 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -792,8 +792,19 @@
 #define __NR_epoll_pwait	(__NR_Linux + 297)
 #define __NR_statfs64		(__NR_Linux + 298)
 #define __NR_fstatfs64		(__NR_Linux + 299)
+#define __NR_kexec_load		(__NR_Linux + 300)
+#define __NR_utimensat		(__NR_Linux + 301)
+#define __NR_signalfd		(__NR_Linux + 302)
+#define __NR_timerfd		(__NR_Linux + 303)
+#define __NR_eventfd		(__NR_Linux + 304)
 
-#define __NR_Linux_syscalls     (__NR_fstatfs64 + 1)
+#define __NR_Linux_syscalls	(__NR_eventfd + 1)
+
+
+#define __IGNORE_select		/* newselect */
+#define __IGNORE_fadvise64	/* fadvise64_64 */
+#define __IGNORE_utimes		/* utime */
+
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h
index 642be62..5350704 100644
--- a/include/asm-powerpc/cache.h
+++ b/include/asm-powerpc/cache.h
@@ -34,5 +34,9 @@
 extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
+#if !defined(__ASSEMBLY__)
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_CACHE_H */
diff --git a/include/asm-powerpc/compat.h b/include/asm-powerpc/compat.h
index aacaabd..64ab1dd 100644
--- a/include/asm-powerpc/compat.h
+++ b/include/asm-powerpc/compat.h
@@ -33,8 +33,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 82d595a..3dc8e2d 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -111,7 +111,7 @@
 /* CPU kernel features */
 
 /* Retain the 32b definitions all use bottom half of word */
-#define CPU_FTR_SPLIT_ID_CACHE		ASM_CONST(0x0000000000000001)
+#define CPU_FTR_COHERENT_ICACHE		ASM_CONST(0x0000000000000001)
 #define CPU_FTR_L2CR			ASM_CONST(0x0000000000000002)
 #define CPU_FTR_SPEC7450		ASM_CONST(0x0000000000000004)
 #define CPU_FTR_ALTIVEC			ASM_CONST(0x0000000000000008)
@@ -135,6 +135,7 @@
 #define CPU_FTR_PPC_LE			ASM_CONST(0x0000000000200000)
 #define CPU_FTR_REAL_LE			ASM_CONST(0x0000000000400000)
 #define CPU_FTR_FPU_UNAVAILABLE		ASM_CONST(0x0000000000800000)
+#define CPU_FTR_UNIFIED_ID_CACHE	ASM_CONST(0x0000000001000000)
 
 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -154,7 +155,6 @@
 #define CPU_FTR_MMCRA			LONG_ASM_CONST(0x0000004000000000)
 #define CPU_FTR_CTRL			LONG_ASM_CONST(0x0000008000000000)
 #define CPU_FTR_SMT			LONG_ASM_CONST(0x0000010000000000)
-#define CPU_FTR_COHERENT_ICACHE		LONG_ASM_CONST(0x0000020000000000)
 #define CPU_FTR_LOCKLESS_TLBIE		LONG_ASM_CONST(0x0000040000000000)
 #define CPU_FTR_CI_LARGE_PAGE		LONG_ASM_CONST(0x0000100000000000)
 #define CPU_FTR_PAUSE_ZERO		LONG_ASM_CONST(0x0000200000000000)
@@ -206,164 +206,149 @@
 		     !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
 		     !defined(CONFIG_BOOKE))
 
-#define CPU_FTRS_PPC601	(CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_603	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_PPC601	(CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE | \
+	CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+#define CPU_FTRS_603	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_604	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_604	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
 	    CPU_FTR_PPC_LE)
-#define CPU_FTRS_740_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_740_NOTAU	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_740	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_740	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
 	    CPU_FTR_PPC_LE)
-#define CPU_FTRS_750	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_750	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
 	    CPU_FTR_PPC_LE)
-#define CPU_FTRS_750CL	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX2	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750GX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7400_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_750CL	(CPU_FTRS_750 | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750FX1	(CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX2	(CPU_FTRS_750 | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX	(CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | \
+		CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750GX	(CPU_FTRS_750FX)
+#define CPU_FTRS_7400_NOTAU	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7400	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7400	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_20	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_21	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_21	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
 	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_23	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_23	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455_1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455_1	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455_20	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
 	    CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447_10	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447_10	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447A	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447A	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7448	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7448	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_PPC_LE)
-#define CPU_FTRS_82XX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_82XX	(CPU_FTR_COMMON | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
-#define CPU_FTRS_G2_LE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_G2_LE	(CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS)
-#define CPU_FTRS_E300	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_E300	(CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_COMMON)
-#define CPU_FTRS_E300C2	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_E300C2	(CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
 	    CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
-#define CPU_FTRS_CLASSIC32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_CLASSIC32	(CPU_FTR_COMMON | \
 	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_8XX	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
-#define CPU_FTRS_40X	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-	    CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_44X	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-	    CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E200	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E500	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-	    CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E500_2	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_8XX	(CPU_FTR_USE_TB)
+#define CPU_FTRS_40X	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_44X	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E200	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
+	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+#define CPU_FTRS_E500	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E500_2	(CPU_FTR_USE_TB | \
 	    CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
-#define CPU_FTRS_POWER3	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
-#define CPU_FTRS_RS64	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
 	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
-#define CPU_FTRS_POWER4	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA)
-#define CPU_FTRS_PPC970	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
-#define CPU_FTRS_POWER5	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR)
-#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
 	    CPU_FTR_DSCR)
-#define CPU_FTRS_CELL	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_CELL	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
-#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
 	    CPU_FTR_PURR | CPU_FTR_REAL_LE)
-#define CPU_FTRS_COMPATIBLE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_COMPATIBLE	(CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
 
 #ifdef __powerpc64__
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index a19a6f1..f6bd804 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -61,7 +61,6 @@
 	void		(*unmap_sg)(struct device *dev, struct scatterlist *sg,
 				int nents, enum dma_data_direction direction);
 	int		(*dma_supported)(struct device *dev, u64 mask);
-	int		(*dac_dma_supported)(struct device *dev, u64 mask);
 	int		(*set_dma_mask)(struct device *dev, u64 dma_mask);
 };
 
diff --git a/include/asm-powerpc/fb.h b/include/asm-powerpc/fb.h
new file mode 100644
index 0000000..411af8d
--- /dev/null
+++ b/include/asm-powerpc/fb.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT,
+						 vma->vm_end - vma->vm_start,
+						 vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index afa700d..34146f0 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -29,7 +29,7 @@
 #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
 
 #include <linux/pci.h>
-#include <asm/ppc-pci.h>	/* for ppc64_isabridge_dev */
+#include <asm/ppc-pci.h>	/* for isa_bridge_pcidev */
 
 #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
 
@@ -139,12 +139,12 @@
 	if (bus_addr 
 	    && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
 		/* different from last time -- unmap prev */
-		pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
+		pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir);
 		bus_addr = 0;
 	}
 
 	if (!bus_addr)	/* need to map it */
-		bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
+		bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir);
 
 	/* remember this one as prev */
 	prev_addr = addr;
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 62efd9d..bf6cd7c 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -206,6 +206,7 @@
 #define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
 #define H_QUERY_INT_STATE       0x1E4
 #define H_POLL_PENDING		0x1D8
+#define H_ILLAN_ATTRIBUTES	0x244
 #define H_JOIN			0x298
 #define H_VASI_STATE            0x2A4
 #define H_ENABLE_CRQ		0x2B0
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 350c9bd..bb8d965 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -607,9 +607,9 @@
  *
  * * iounmap undoes such a mapping and can be hooked
  *
- * * __ioremap_explicit (and the pending __iounmap_explicit) are low level
- *   functions to create hand-made mappings for use only by the PCI code
- *   and cannot currently be hooked.
+ * * __ioremap_at (and the pending __iounmap_at) are low level functions to
+ *   create hand-made mappings for use only by the PCI code and cannot
+ *   currently be hooked. Must be page aligned.
  *
  * * __ioremap is the low level implementation used by ioremap and
  *   ioremap_flags and cannot be hooked (but can be used by a hook on one
@@ -629,19 +629,9 @@
 			       unsigned long flags);
 extern void __iounmap(volatile void __iomem *addr);
 
-extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr,
-		     	      unsigned long size, unsigned long flags);
-extern int __iounmap_explicit(volatile void __iomem *start,
-			      unsigned long size);
-
-extern void __iomem * reserve_phb_iospace(unsigned long size);
-
-/* Those are more 32 bits only functions */
-extern unsigned long iopa(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
-			     unsigned int size, int flags);
-
+extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
+				   unsigned long size, unsigned long flags);
+extern void __iounmap_at(void *ea, unsigned long size);
 
 /*
  * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation
@@ -651,8 +641,8 @@
  */
 #define HAVE_ARCH_PIO_SIZE		1
 #define PIO_OFFSET			0x00000000UL
-#define PIO_MASK			0x3fffffffUL
-#define PIO_RESERVED			0x40000000UL
+#define PIO_MASK			(FULL_IO_SIZE - 1)
+#define PIO_RESERVED			(FULL_IO_SIZE)
 
 #define mmio_read16be(addr)		readw_be(addr)
 #define mmio_read32be(addr)		readl_be(addr)
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 4734cc1..0485c53 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -138,10 +138,7 @@
 
 extern struct irq_map_entry irq_map[NR_IRQS];
 
-static inline irq_hw_number_t virq_to_hw(unsigned int virq)
-{
-	return irq_map[virq].hwirq;
-}
+extern irq_hw_number_t virq_to_hw(unsigned int virq);
 
 /**
  * irq_alloc_host - Allocate a new irq_host data structure
@@ -226,6 +223,15 @@
 extern unsigned int irq_find_mapping(struct irq_host *host,
 				     irq_hw_number_t hwirq);
 
+/**
+ * irq_create_direct_mapping - Allocate a virq for direct mapping
+ * @host: host to allocate the virq for or NULL for default host
+ *
+ * This routine is used for irq controllers which can choose the hardware
+ * interrupt numbers they generate. In such a case it's simplest to use
+ * the linux virq as the hardware interrupt number.
+ */
+extern unsigned int irq_create_direct_mapping(struct irq_host *host);
 
 /**
  * irq_radix_revmap - Find a linux virq from a hw irq number.
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index b0e40ff..9537fda 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -65,10 +65,10 @@
 		} else if (name[0] != '.')				\
 			addr = *(kprobe_opcode_t **)addr;		\
 	} else {							\
-		char dot_name[KSYM_NAME_LEN+1];				\
+		char dot_name[KSYM_NAME_LEN];				\
 		dot_name[0] = '.';					\
 		dot_name[1] = '\0';					\
-		strncat(dot_name, name, KSYM_NAME_LEN);			\
+		strncat(dot_name, name, KSYM_NAME_LEN - 2);		\
 		addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
 	}								\
 }
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h
index 821ea0c..567ed92 100644
--- a/include/asm-powerpc/lppaca.h
+++ b/include/asm-powerpc/lppaca.h
@@ -98,7 +98,7 @@
 	u64	saved_gpr5;		// Saved GPR5                   x30-x37
 
 	u8	reserved4;		// Reserved			x38-x38
-	u8	cpuctls_task_attrs;	// Task attributes for cpuctls  x39-x39
+	u8	donate_dedicated_cpu;	// Donate dedicated CPU cycles  x39-x39
 	u8	fpregs_in_use;		// FP regs in use               x3A-x3A
 	u8	pmcregs_in_use;		// PMC regs in use              x3B-x3B
 	volatile u32 saved_decr;	// Saved Decr Value             x3C-x3F
diff --git a/include/asm-powerpc/lv1call.h b/include/asm-powerpc/lv1call.h
index f733bee..81713ac 100644
--- a/include/asm-powerpc/lv1call.h
+++ b/include/asm-powerpc/lv1call.h
@@ -238,6 +238,7 @@
 LV1_CALL(configure_irq_state_bitmap,                    3, 0,  11 )
 LV1_CALL(connect_irq_plug_ext,                          5, 0,  12 )
 LV1_CALL(release_memory,                                1, 0,  13 )
+LV1_CALL(put_iopte,                                     5, 0,  15 )
 LV1_CALL(disconnect_irq_plug_ext,                       3, 0,  17 )
 LV1_CALL(construct_event_receive_port,                  0, 1,  18 )
 LV1_CALL(destruct_event_receive_port,                   1, 0,  19 )
@@ -268,6 +269,8 @@
 LV1_CALL(read_htab_entries,                             2, 5,  95 )
 LV1_CALL(set_dabr,                                      2, 0,  96 )
 LV1_CALL(get_total_execution_time,                      2, 1, 103 )
+LV1_CALL(allocate_io_segment,                           3, 1, 116 )
+LV1_CALL(release_io_segment,                            2, 0, 117 )
 LV1_CALL(construct_io_irq_outlet,                       1, 1, 120 )
 LV1_CALL(destruct_io_irq_outlet,                        1, 0, 121 )
 LV1_CALL(map_htab,                                      1, 1, 122 )
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 6cf1a83..71c6e7e 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -218,7 +218,7 @@
 	int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
 
 	/* Called in indirect_* to avoid touching devices */
-	int (*pci_exclude_device)(unsigned char, unsigned char);
+	int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
 
 	/* Called at then very end of pcibios_init() */
 	void (*pcibios_after_init)(void);
diff --git a/include/asm-powerpc/mmu-8xx.h b/include/asm-powerpc/mmu-8xx.h
new file mode 100644
index 0000000..952bd88
--- /dev/null
+++ b/include/asm-powerpc/mmu-8xx.h
@@ -0,0 +1,147 @@
+#ifndef _ASM_POWERPC_MMU_8XX_H_
+#define _ASM_POWERPC_MMU_8XX_H_
+/*
+ * PPC8xx support
+ */
+
+/* Control/status registers for the MPC8xx.
+ * A write operation to these registers causes serialized access.
+ * During software tablewalk, the registers used perform mask/shift-add
+ * operations when written/read.  A TLB entry is created when the Mx_RPN
+ * is written, and the contents of several registers are used to
+ * create the entry.
+ */
+#define SPRN_MI_CTR	784	/* Instruction TLB control register */
+#define MI_GPM		0x80000000	/* Set domain manager mode */
+#define MI_PPM		0x40000000	/* Set subpage protection */
+#define MI_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
+#define MI_RSV4I	0x08000000	/* Reserve 4 TLB entries */
+#define MI_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
+#define MI_IDXMASK	0x00001f00	/* TLB index to be loaded */
+#define MI_RESETVAL	0x00000000	/* Value of register at reset */
+
+/* These are the Ks and Kp from the PowerPC books.  For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define SPRN_MI_AP	786
+#define MI_Ks		0x80000000	/* Should not be set */
+#define MI_Kp		0x40000000	/* Should always be set */
+
+/* The effective page number register.  When read, contains the information
+ * about the last instruction TLB miss.  When MI_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define SPRN_MI_EPN	787
+#define MI_EPNMASK	0xfffff000	/* Effective page number for entry */
+#define MI_EVALID	0x00000200	/* Entry is valid */
+#define MI_ASIDMASK	0x0000000f	/* ASID match value */
+					/* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the instruction TLB, it contains bits that get loaded into the
+ * TLB entry when the MI_RPN is written.
+ */
+#define SPRN_MI_TWC	789
+#define MI_APG		0x000001e0	/* Access protection group (0) */
+#define MI_GUARDED	0x00000010	/* Guarded storage */
+#define MI_PSMASK	0x0000000c	/* Mask of page size bits */
+#define MI_PS8MEG	0x0000000c	/* 8M page size */
+#define MI_PS512K	0x00000004	/* 512K page size */
+#define MI_PS4K_16K	0x00000000	/* 4K or 16K page size */
+#define MI_SVALID	0x00000001	/* Segment entry is valid */
+					/* Reset value is undefined */
+
+/* Real page number.  Defined by the pte.  Writing this register
+ * causes a TLB entry to be created for the instruction TLB, using
+ * additional information from the MI_EPN, and MI_TWC registers.
+ */
+#define SPRN_MI_RPN	790
+
+/* Define an RPN value for mapping kernel memory to large virtual
+ * pages for boot initialization.  This has real page number of 0,
+ * large page size, shared page, cache enabled, and valid.
+ * Also mark all subpages valid and write access.
+ */
+#define MI_BOOTINIT	0x000001fd
+
+#define SPRN_MD_CTR	792	/* Data TLB control register */
+#define MD_GPM		0x80000000	/* Set domain manager mode */
+#define MD_PPM		0x40000000	/* Set subpage protection */
+#define MD_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
+#define MD_WTDEF	0x10000000	/* Set writethrough when MMU dis */
+#define MD_RSV4I	0x08000000	/* Reserve 4 TLB entries */
+#define MD_TWAM		0x04000000	/* Use 4K page hardware assist */
+#define MD_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
+#define MD_IDXMASK	0x00001f00	/* TLB index to be loaded */
+#define MD_RESETVAL	0x04000000	/* Value of register at reset */
+
+#define SPRN_M_CASID	793	/* Address space ID (context) to match */
+#define MC_ASIDMASK	0x0000000f	/* Bits used for ASID value */
+
+
+/* These are the Ks and Kp from the PowerPC books.  For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define SPRN_MD_AP	794
+#define MD_Ks		0x80000000	/* Should not be set */
+#define MD_Kp		0x40000000	/* Should always be set */
+
+/* The effective page number register.  When read, contains the information
+ * about the last instruction TLB miss.  When MD_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define SPRN_MD_EPN	795
+#define MD_EPNMASK	0xfffff000	/* Effective page number for entry */
+#define MD_EVALID	0x00000200	/* Entry is valid */
+#define MD_ASIDMASK	0x0000000f	/* ASID match value */
+					/* Reset value is undefined */
+
+/* The pointer to the base address of the first level page table.
+ * During a software tablewalk, reading this register provides the address
+ * of the entry associated with MD_EPN.
+ */
+#define SPRN_M_TWB	796
+#define	M_L1TB		0xfffff000	/* Level 1 table base address */
+#define M_L1INDX	0x00000ffc	/* Level 1 index, when read */
+					/* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the data TLB, it contains bits that get loaded into the TLB entry
+ * when the MD_RPN is written.  It is also provides the hardware assist
+ * for finding the PTE address during software tablewalk.
+ */
+#define SPRN_MD_TWC	797
+#define MD_L2TB		0xfffff000	/* Level 2 table base address */
+#define MD_L2INDX	0xfffffe00	/* Level 2 index (*pte), when read */
+#define MD_APG		0x000001e0	/* Access protection group (0) */
+#define MD_GUARDED	0x00000010	/* Guarded storage */
+#define MD_PSMASK	0x0000000c	/* Mask of page size bits */
+#define MD_PS8MEG	0x0000000c	/* 8M page size */
+#define MD_PS512K	0x00000004	/* 512K page size */
+#define MD_PS4K_16K	0x00000000	/* 4K or 16K page size */
+#define MD_WT		0x00000002	/* Use writethrough page attribute */
+#define MD_SVALID	0x00000001	/* Segment entry is valid */
+					/* Reset value is undefined */
+
+
+/* Real page number.  Defined by the pte.  Writing this register
+ * causes a TLB entry to be created for the data TLB, using
+ * additional information from the MD_EPN, and MD_TWC registers.
+ */
+#define SPRN_MD_RPN	798
+
+/* This is a temporary storage register that could be used to save
+ * a processor working register during a tablewalk.
+ */
+#define SPRN_M_TW	799
+
+#ifndef __ASSEMBLY__
+typedef unsigned long phys_addr_t;
+
+typedef struct {
+	unsigned long id;
+	unsigned long vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_8XX_H_ */
diff --git a/include/asm-powerpc/mmu-fsl-booke.h b/include/asm-powerpc/mmu-fsl-booke.h
new file mode 100644
index 0000000..3758000
--- /dev/null
+++ b/include/asm-powerpc/mmu-fsl-booke.h
@@ -0,0 +1,88 @@
+#ifndef _ASM_POWERPC_MMU_FSL_BOOKE_H_
+#define _ASM_POWERPC_MMU_FSL_BOOKE_H_
+/*
+ * Freescale Book-E MMU support
+ */
+
+/* Book-E defined page sizes */
+#define BOOKE_PAGESZ_1K		0
+#define BOOKE_PAGESZ_4K		1
+#define BOOKE_PAGESZ_16K	2
+#define BOOKE_PAGESZ_64K	3
+#define BOOKE_PAGESZ_256K	4
+#define BOOKE_PAGESZ_1M		5
+#define BOOKE_PAGESZ_4M		6
+#define BOOKE_PAGESZ_16M	7
+#define BOOKE_PAGESZ_64M	8
+#define BOOKE_PAGESZ_256M	9
+#define BOOKE_PAGESZ_1GB	10
+#define BOOKE_PAGESZ_4GB	11
+#define BOOKE_PAGESZ_16GB	12
+#define BOOKE_PAGESZ_64GB	13
+#define BOOKE_PAGESZ_256GB	14
+#define BOOKE_PAGESZ_1TB	15
+
+#define MAS0_TLBSEL(x)	((x << 28) & 0x30000000)
+#define MAS0_ESEL(x)	((x << 16) & 0x0FFF0000)
+#define MAS0_NV(x)	((x) & 0x00000FFF)
+
+#define MAS1_VALID 	0x80000000
+#define MAS1_IPROT	0x40000000
+#define MAS1_TID(x)	((x << 16) & 0x3FFF0000)
+#define MAS1_TS		0x00001000
+#define MAS1_TSIZE(x)	((x << 8) & 0x00000F00)
+
+#define MAS2_EPN	0xFFFFF000
+#define MAS2_X0		0x00000040
+#define MAS2_X1		0x00000020
+#define MAS2_W		0x00000010
+#define MAS2_I		0x00000008
+#define MAS2_M		0x00000004
+#define MAS2_G		0x00000002
+#define MAS2_E		0x00000001
+
+#define MAS3_RPN	0xFFFFF000
+#define MAS3_U0		0x00000200
+#define MAS3_U1		0x00000100
+#define MAS3_U2		0x00000080
+#define MAS3_U3		0x00000040
+#define MAS3_UX		0x00000020
+#define MAS3_SX		0x00000010
+#define MAS3_UW		0x00000008
+#define MAS3_SW		0x00000004
+#define MAS3_UR		0x00000002
+#define MAS3_SR		0x00000001
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_TIDDSEL	0x000F0000
+#define MAS4_TSIZED(x)	MAS1_TSIZE(x)
+#define MAS4_X0D	0x00000040
+#define MAS4_X1D	0x00000020
+#define MAS4_WD		0x00000010
+#define MAS4_ID		0x00000008
+#define MAS4_MD		0x00000004
+#define MAS4_GD		0x00000002
+#define MAS4_ED		0x00000001
+
+#define MAS6_SPID0	0x3FFF0000
+#define MAS6_SPID1	0x00007FFE
+#define MAS6_SAS	0x00000001
+#define MAS6_SPID	MAS6_SPID0
+
+#define MAS7_RPN	0xFFFFFFFF
+
+#ifndef __ASSEMBLY__
+
+#ifndef CONFIG_PHYS_64BIT
+typedef unsigned long phys_addr_t;
+#else
+typedef unsigned long long phys_addr_t;
+#endif
+
+typedef struct {
+	unsigned long id;
+	unsigned long vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_FSL_BOOKE_H_ */
diff --git a/include/asm-powerpc/mmu-hash32.h b/include/asm-powerpc/mmu-hash32.h
new file mode 100644
index 0000000..4bd735b
--- /dev/null
+++ b/include/asm-powerpc/mmu-hash32.h
@@ -0,0 +1,91 @@
+#ifndef _ASM_POWERPC_MMU_HASH32_H_
+#define _ASM_POWERPC_MMU_HASH32_H_
+/*
+ * 32-bit hash table MMU support
+ */
+
+/*
+ * BATs
+ */
+
+/* Block size masks */
+#define BL_128K	0x000
+#define BL_256K 0x001
+#define BL_512K 0x003
+#define BL_1M   0x007
+#define BL_2M   0x00F
+#define BL_4M   0x01F
+#define BL_8M   0x03F
+#define BL_16M  0x07F
+#define BL_32M  0x0FF
+#define BL_64M  0x1FF
+#define BL_128M 0x3FF
+#define BL_256M 0x7FF
+
+/* BAT Access Protection */
+#define BPP_XX	0x00		/* No access */
+#define BPP_RX	0x01		/* Read only */
+#define BPP_RW	0x02		/* Read/write */
+
+#ifndef __ASSEMBLY__
+struct ppc_bat {
+	struct {
+		unsigned long bepi:15;	/* Effective page index (virtual address) */
+		unsigned long :4;	/* Unused */
+		unsigned long bl:11;	/* Block size mask */
+		unsigned long vs:1;	/* Supervisor valid */
+		unsigned long vp:1;	/* User valid */
+	} batu; 		/* Upper register */
+	struct {
+		unsigned long brpn:15;	/* Real page index (physical address) */
+		unsigned long :10;	/* Unused */
+		unsigned long w:1;	/* Write-thru cache */
+		unsigned long i:1;	/* Cache inhibit */
+		unsigned long m:1;	/* Memory coherence */
+		unsigned long g:1;	/* Guarded (MBZ in IBAT) */
+		unsigned long :1;	/* Unused */
+		unsigned long pp:2;	/* Page access protections */
+	} batl;			/* Lower register */
+};
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * Hash table
+ */
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX	0	/* Supervisor read/write, User none */
+#define PP_RWRX 1	/* Supervisor read/write, User read */
+#define PP_RWRW 2	/* Supervisor read/write, User read/write */
+#define PP_RXRX 3	/* Supervisor read,       User read */
+
+#ifndef __ASSEMBLY__
+
+/* Hardware Page Table Entry */
+struct hash_pte {
+	unsigned long v:1;	/* Entry is valid */
+	unsigned long vsid:24;	/* Virtual segment identifier */
+	unsigned long h:1;	/* Hash algorithm indicator */
+	unsigned long api:6;	/* Abbreviated page index */
+	unsigned long rpn:20;	/* Real (physical) page number */
+	unsigned long    :3;	/* Unused */
+	unsigned long r:1;	/* Referenced */
+	unsigned long c:1;	/* Changed */
+	unsigned long w:1;	/* Write-thru cache mode */
+	unsigned long i:1;	/* Cache inhibited */
+	unsigned long m:1;	/* Memory coherence */
+	unsigned long g:1;	/* Guarded */
+	unsigned long  :1;	/* Unused */
+	unsigned long pp:2;	/* Page protection */
+};
+
+typedef struct {
+	unsigned long id;
+	unsigned long vdso_base;
+} mm_context_t;
+
+typedef unsigned long phys_addr_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
index b8dca30..695962f 100644
--- a/include/asm-powerpc/mmu-hash64.h
+++ b/include/asm-powerpc/mmu-hash64.h
@@ -94,6 +94,9 @@
 #define HPTE_R_C		ASM_CONST(0x0000000000000080)
 #define HPTE_R_R		ASM_CONST(0x0000000000000100)
 
+#define HPTE_V_1TB_SEG		ASM_CONST(0x4000000000000000)
+#define HPTE_V_VRMA_MASK	ASM_CONST(0x4001ffffff000000)
+
 /* Values for PP (assumes Ks=0, Kp=1) */
 /* pp0 will always be 0 for linux     */
 #define PP_RWXX	0	/* Supervisor read/write, User none */
@@ -103,12 +106,12 @@
 
 #ifndef __ASSEMBLY__
 
-typedef struct {
+struct hash_pte {
 	unsigned long v;
 	unsigned long r;
-} hpte_t;
+};
 
-extern hpte_t *htab_address;
+extern struct hash_pte *htab_address;
 extern unsigned long htab_size_bytes;
 extern unsigned long htab_hash_mask;
 
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h
index fe510ff..d44d211 100644
--- a/include/asm-powerpc/mmu.h
+++ b/include/asm-powerpc/mmu.h
@@ -5,13 +5,18 @@
 #ifdef CONFIG_PPC64
 /* 64-bit classic hash table MMU */
 #  include <asm/mmu-hash64.h>
+#elif defined(CONFIG_PPC_STD_MMU)
+/* 32-bit classic hash table MMU */
+#  include <asm/mmu-hash32.h>
 #elif defined(CONFIG_44x)
 /* 44x-style software loaded TLB */
 #  include <asm/mmu-44x.h>
-#else
-/* Other 32-bit.  FIXME: split up the other 32-bit MMU types, and
- * revise for arch/powerpc */
-#  include <asm-ppc/mmu.h>
+#elif defined(CONFIG_FSL_BOOKE)
+/* Freescale Book-E software loaded TLB */
+#  include <asm/mmu-fsl-booke.h>
+#elif defined (CONFIG_PPC_8xx)
+/* Motorola/Freescale 8xx software loaded TLB */
+#  include <asm/mmu-8xx.h>
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h
index c0d7795..f863ac2 100644
--- a/include/asm-powerpc/mmu_context.h
+++ b/include/asm-powerpc/mmu_context.h
@@ -2,15 +2,210 @@
 #define __ASM_POWERPC_MMU_CONTEXT_H
 #ifdef __KERNEL__
 
+#include <asm/mmu.h>	
+#include <asm/cputable.h>
+#include <asm-generic/mm_hooks.h>
+
 #ifndef CONFIG_PPC64
-#include <asm-ppc/mmu_context.h>
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+
+/*
+ * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
+ * (virtual segment identifiers) for each context.  Although the
+ * hardware supports 24-bit VSIDs, and thus >1 million contexts,
+ * we only use 32,768 of them.  That is ample, since there can be
+ * at most around 30,000 tasks in the system anyway, and it means
+ * that we can use a bitmap to indicate which contexts are in use.
+ * Using a bitmap means that we entirely avoid all of the problems
+ * that we used to have when the context number overflowed,
+ * particularly on SMP systems.
+ *  -- paulus.
+ */
+
+/*
+ * This function defines the mapping from contexts to VSIDs (virtual
+ * segment IDs).  We use a skew on both the context and the high 4 bits
+ * of the 32-bit virtual address (the "effective segment ID") in order
+ * to spread out the entries in the MMU hash table.  Note, if this
+ * function is changed then arch/ppc/mm/hashtable.S will have to be
+ * changed to correspond.
+ */
+#define CTX_TO_VSID(ctx, va)	(((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
+				 & 0xffffff)
+
+/*
+   The MPC8xx has only 16 contexts.  We rotate through them on each
+   task switch.  A better way would be to keep track of tasks that
+   own contexts, and implement an LRU usage.  That way very active
+   tasks don't always have to pay the TLB reload overhead.  The
+   kernel pages are mapped shared, so the kernel can run on behalf
+   of any task that makes a kernel entry.  Shared does not mean they
+   are not protected, just that the ASID comparison is not performed.
+        -- Dan
+
+   The IBM4xx has 256 contexts, so we can just rotate through these
+   as a way of "switching" contexts.  If the TID of the TLB is zero,
+   the PID/TID comparison is disabled, so we can use a TID of zero
+   to represent all kernel pages as shared among all contexts.
+   	-- Dan
+ */
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+#ifdef CONFIG_8xx
+#define NO_CONTEXT      	16
+#define LAST_CONTEXT    	15
+#define FIRST_CONTEXT    	0
+
+#elif defined(CONFIG_4xx)
+#define NO_CONTEXT      	256
+#define LAST_CONTEXT    	255
+#define FIRST_CONTEXT    	1
+
+#elif defined(CONFIG_E200) || defined(CONFIG_E500)
+#define NO_CONTEXT      	256
+#define LAST_CONTEXT    	255
+#define FIRST_CONTEXT    	1
+
+#else
+
+/* PPC 6xx, 7xx CPUs */
+#define NO_CONTEXT      	((unsigned long) -1)
+#define LAST_CONTEXT    	32767
+#define FIRST_CONTEXT    	1
+#endif
+
+/*
+ * Set the current MMU context.
+ * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by
+ * loading up the segment registers for the user part of the address space.
+ *
+ * Since the PGD is immediately available, it is much faster to simply
+ * pass this along as a second parameter, which is required for 8xx and
+ * can be used for debugging on all processors (if you happen to have
+ * an Abatron).
+ */
+extern void set_context(unsigned long contextid, pgd_t *pgd);
+
+/*
+ * Bitmap of contexts in use.
+ * The size of this bitmap is LAST_CONTEXT + 1 bits.
+ */
+extern unsigned long context_map[];
+
+/*
+ * This caches the next context number that we expect to be free.
+ * Its use is an optimization only, we can't rely on this context
+ * number to be free, but it usually will be.
+ */
+extern unsigned long next_mmu_context;
+
+/*
+ * If we don't have sufficient contexts to give one to every task
+ * that could be in the system, we need to be able to steal contexts.
+ * These variables support that.
+ */
+#if LAST_CONTEXT < 30000
+#define FEW_CONTEXTS	1
+extern atomic_t nr_free_contexts;
+extern struct mm_struct *context_mm[LAST_CONTEXT+1];
+extern void steal_context(void);
+#endif
+
+/*
+ * Get a new mmu context for the address space described by `mm'.
+ */
+static inline void get_mmu_context(struct mm_struct *mm)
+{
+	unsigned long ctx;
+
+	if (mm->context.id != NO_CONTEXT)
+		return;
+#ifdef FEW_CONTEXTS
+	while (atomic_dec_if_positive(&nr_free_contexts) < 0)
+		steal_context();
+#endif
+	ctx = next_mmu_context;
+	while (test_and_set_bit(ctx, context_map)) {
+		ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
+		if (ctx > LAST_CONTEXT)
+			ctx = 0;
+	}
+	next_mmu_context = (ctx + 1) & LAST_CONTEXT;
+	mm->context.id = ctx;
+#ifdef FEW_CONTEXTS
+	context_mm[ctx] = mm;
+#endif
+}
+
+/*
+ * Set up the context for a new address space.
+ */
+static inline int init_new_context(struct task_struct *t, struct mm_struct *mm)
+{
+	mm->context.id = NO_CONTEXT;
+	mm->context.vdso_base = 0;
+	return 0;
+}
+
+/*
+ * We're finished using the context for an address space.
+ */
+static inline void destroy_context(struct mm_struct *mm)
+{
+	preempt_disable();
+	if (mm->context.id != NO_CONTEXT) {
+		clear_bit(mm->context.id, context_map);
+		mm->context.id = NO_CONTEXT;
+#ifdef FEW_CONTEXTS
+		atomic_inc(&nr_free_contexts);
+#endif
+	}
+	preempt_enable();
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk)
+{
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+	asm volatile ("dssall;\n"
+#ifndef CONFIG_POWER4
+	 "sync;\n" /* G4 needs a sync here, G5 apparently not */
+#endif
+	 : : );
+#endif /* CONFIG_ALTIVEC */
+
+	tsk->thread.pgdir = next->pgd;
+
+	/* No need to flush userspace segments if the mm doesnt change */
+	if (prev == next)
+		return;
+
+	/* Setup new userspace context */
+	get_mmu_context(next);
+	set_context(next->context.id, next->pgd);
+}
+
+#define deactivate_mm(tsk,mm)	do { } while (0)
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+#define activate_mm(active_mm, mm)   switch_mm(active_mm, mm, current)
+
+extern void mmu_context_init(void);
+
+
 #else
 
 #include <linux/kernel.h>	
 #include <linux/mm.h>	
-#include <asm/mmu.h>	
-#include <asm/cputable.h>
-#include <asm-generic/mm_hooks.h>
+#include <linux/sched.h>
 
 /*
  * Copyright (C) 2001 PPC 64 Team, IBM Corp
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h
index b85df45..15f650f 100644
--- a/include/asm-powerpc/mpc86xx.h
+++ b/include/asm-powerpc/mpc86xx.h
@@ -19,12 +19,6 @@
 
 #ifdef CONFIG_PPC_86xx
 
-#define _IO_BASE        isa_io_base
-#define _ISA_MEM_BASE   isa_mem_base
-#ifdef CONFIG_PCI
-#define PCI_DRAM_OFFSET pci_dram_offset
-#endif
-
 #define CPU0_BOOT_RELEASE 0x01000000
 #define CPU1_BOOT_RELEASE 0x02000000
 #define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE)
diff --git a/include/asm-powerpc/mpc8xx.h b/include/asm-powerpc/mpc8xx.h
index 5803711..2be014b 100644
--- a/include/asm-powerpc/mpc8xx.h
+++ b/include/asm-powerpc/mpc8xx.h
@@ -23,6 +23,10 @@
 #include <platforms/8xx/mpc885ads.h>
 #endif
 
+#ifdef CONFIG_PCMCIA_M8XX
+extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
+#endif
+
 #endif /* CONFIG_8xx */
 #endif /* __CONFIG_8xx_DEFS */
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index d9bf5ab..e72c2a6 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -2,12 +2,91 @@
 #define _ASM_POWERPC_PCI_BRIDGE_H
 #ifdef __KERNEL__
 
-#ifndef CONFIG_PPC64
-#include <asm-ppc/pci-bridge.h>
-#else
-
 #include <linux/pci.h>
 #include <linux/list.h>
+#include <linux/ioport.h>
+
+#ifndef CONFIG_PPC64
+
+struct device_node;
+struct pci_controller;
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+struct pci_controller {
+	struct pci_bus *bus;
+	char is_dynamic;
+	void *arch_data;
+	struct list_head list_node;
+	struct device *parent;
+
+	int first_busno;
+	int last_busno;
+	int self_busno;
+
+	void __iomem *io_base_virt;
+	resource_size_t io_base_phys;
+
+	/* Some machines (PReP) have a non 1:1 mapping of
+	 * the PCI memory space in the CPU bus space
+	 */
+	resource_size_t pci_mem_offset;
+
+	struct pci_ops *ops;
+	volatile unsigned int __iomem *cfg_addr;
+	volatile void __iomem *cfg_data;
+
+	/*
+	 * Used for variants of PCI indirect handling and possible quirks:
+	 *  SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
+	 *  EXT_REG - provides access to PCI-e extended registers
+	 *  SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS
+	 *   on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS
+	 *   to determine which bus number to match on when generating type0
+	 *   config cycles
+	 */
+#define PPC_INDIRECT_TYPE_SET_CFG_TYPE		(0x00000001)
+#define PPC_INDIRECT_TYPE_EXT_REG		(0x00000002)
+#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS	(0x00000004)
+	u32 indirect_type;
+
+	/* Currently, we limit ourselves to 1 IO range and 3 mem
+	 * ranges since the common pci_bus structure can't handle more
+	 */
+	struct resource	io_resource;
+	struct resource mem_resources[3];
+	int global_number;		/* PCI domain number */
+};
+
+static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
+{
+	return bus->sysdata;
+}
+
+/* These are used for config access before all the PCI probing
+   has been done. */
+int early_read_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+			   int where, u8 *val);
+int early_read_config_word(struct pci_controller *hose, int bus, int dev_fn,
+			   int where, u16 *val);
+int early_read_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u32 *val);
+int early_write_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u8 val);
+int early_write_config_word(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u16 val);
+int early_write_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+			     int where, u32 val);
+
+extern void setup_indirect_pci_nomap(struct pci_controller* hose,
+			       void __iomem *cfg_addr, void __iomem *cfg_data);
+extern void setup_indirect_pci(struct pci_controller* hose,
+			       u32 cfg_addr, u32 cfg_data);
+extern void setup_grackle(struct pci_controller *hose);
+
+#else
+
 
 /*
  * This program is free software; you can redistribute it and/or
@@ -31,6 +110,7 @@
 	int last_busno;
 
 	void __iomem *io_base_virt;
+	void *io_base_alloc;
 	resource_size_t io_base_phys;
 
 	/* Some machines have a non 1:1 mapping of
@@ -48,8 +128,7 @@
 	 */
 	struct resource io_resource;
 	struct resource mem_resources[3];
-	int global_number;		
-	int local_number;		
+	int global_number;
 	unsigned long buid;
 	unsigned long dma_window_base_cur;
 	unsigned long dma_window_size;
@@ -70,19 +149,22 @@
 	int	devfn;			/* pci device and function number */
 	int	class_code;		/* pci device class */
 
-#ifdef CONFIG_PPC_PSERIES
+	struct  pci_controller *phb;	/* for pci devices */
+	struct	iommu_table *iommu_table;	/* for phb's or bridges */
+	struct	pci_dev *pcidev;	/* back-pointer to the pci device */
+	struct	device_node *node;	/* back-pointer to the device_node */
+
+	int	pci_ext_config_space;	/* for pci devices */
+
+#ifdef CONFIG_EEH
 	int	eeh_mode;		/* See eeh.h for possible EEH_MODEs */
 	int	eeh_config_addr;
 	int	eeh_pe_config_addr; /* new-style partition endpoint address */
 	int 	eeh_check_count;	/* # times driver ignored error */
 	int 	eeh_freeze_count;	/* # times this device froze up. */
-#endif
-	int	pci_ext_config_space;	/* for pci devices */
-	struct  pci_controller *phb;	/* for pci devices */
-	struct	iommu_table *iommu_table;	/* for phb's or bridges */
-	struct	pci_dev *pcidev;	/* back-pointer to the pci device */
-	struct	device_node *node;	/* back-pointer to the device_node */
+	int 	eeh_false_positives;	/* # times this device reported #ff's */
 	u32	config_space[16];	/* saved PCI config space */
+#endif
 };
 
 /* Get the pointer to a device_node's pci_dn */
@@ -128,9 +210,6 @@
 /** Find the bus corresponding to the indicated device node */
 struct pci_bus * pcibios_find_pci_bus(struct device_node *dn);
 
-extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
-					 struct device_node *dev, int primary);
-
 /** Remove all of the PCI devices under this bus */
 void pcibios_remove_pci_devices(struct pci_bus *bus);
 
@@ -148,21 +227,12 @@
 	return PCI_DN(busdn)->phb;
 }
 
-extern struct pci_controller*
-pci_find_hose_for_OF_device(struct device_node* node);
-
-extern struct pci_controller *
-pcibios_alloc_controller(struct device_node *dev);
 extern void pcibios_free_controller(struct pci_controller *phb);
 
-#ifdef CONFIG_PCI
-extern unsigned long pci_address_to_pio(phys_addr_t address);
-#else
-static inline unsigned long pci_address_to_pio(phys_addr_t address)
-{
-	return (unsigned long)-1;
-}
-#endif
+extern void isa_bridge_find_early(struct pci_controller *hose);
+
+extern int pcibios_unmap_io_space(struct pci_bus *bus);
+extern int pcibios_map_io_space(struct pci_bus *bus);
 
 /* Return values for ppc_md.pci_probe_mode function */
 #define PCI_PROBE_NONE		-1	/* Don't look at this bus at all */
@@ -176,5 +246,29 @@
 #endif
 
 #endif /* CONFIG_PPC64 */
+
+/* Get the PCI host controller for an OF device */
+extern struct pci_controller*
+pci_find_hose_for_OF_device(struct device_node* node);
+
+/* Fill up host controller resources from the OF node */
+extern void
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+			   struct device_node *dev, int primary);
+
+/* Allocate a new PCI host bridge structure */
+extern struct pci_controller *
+pcibios_alloc_controller(struct device_node *dev);
+#ifdef CONFIG_PCI
+extern unsigned long pci_address_to_pio(phys_addr_t address);
+#else
+static inline unsigned long pci_address_to_pio(phys_addr_t address)
+{
+	return (unsigned long)-1;
+}
+#endif
+
+
+
 #endif /* __KERNEL__ */
 #endif
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index ce0f13e..7b11765 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -74,18 +74,6 @@
 extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops);
 extern struct dma_mapping_ops *get_pci_dma_ops(void);
 
-/* For DAC DMA, we currently don't support it by default, but
- * we let 64-bit platforms override this.
- */
-static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask)
-{
-	struct dma_mapping_ops *d = get_pci_dma_ops();
-
-	if (d && d->dac_dma_supported)
-		return d->dac_dma_supported(&hwdev->dev, mask);
-	return 0;
-}
-
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
 					unsigned long *strategy_parameter)
@@ -107,8 +95,6 @@
 #define get_pci_dma_ops()	NULL
 #endif
 
-extern int pci_domain_nr(struct pci_bus *bus);
-
 /* Decide whether to display the domain number in /proc */
 extern int pci_proc_domain(struct pci_bus *bus);
 
@@ -124,15 +110,6 @@
 }
 #endif
 
-/*
- * At present there are very few 32-bit PPC machines that can have
- * memory above the 4GB point, and we don't support that.
- */
-#define pci_dac_dma_supported(pci_dev, mask)	(0)
-
-/* Return the index of the PCI controller for device PDEV. */
-#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
-
 /* Set the name of the bus as it appears in /proc/bus/pci */
 static inline int pci_proc_domain(struct pci_bus *bus)
 {
@@ -141,6 +118,8 @@
 
 #endif /* CONFIG_PPC64 */
 
+extern int pci_domain_nr(struct pci_bus *bus);
+
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
@@ -220,10 +199,6 @@
 	return root;
 }
 
-extern int unmap_bus_range(struct pci_bus *bus);
-
-extern int remap_bus_range(struct pci_bus *bus);
-
 extern void pcibios_fixup_device_resources(struct pci_dev *dev,
 			struct pci_bus *bus);
 
@@ -243,8 +218,6 @@
 
 extern int pci_read_irq_line(struct pci_dev *dev);
 
-extern void pcibios_add_platform_entries(struct pci_dev *dev);
-
 struct file;
 extern pgprot_t	pci_phys_mem_access_prot(struct file *file,
 					 unsigned long pfn,
diff --git a/include/asm-powerpc/pgalloc-64.h b/include/asm-powerpc/pgalloc-64.h
index d9a3a8c..94d0294 100644
--- a/include/asm-powerpc/pgalloc-64.h
+++ b/include/asm-powerpc/pgalloc-64.h
@@ -90,7 +90,8 @@
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
 					 unsigned long address)
 {
-	return virt_to_page(pte_alloc_one_kernel(mm, address));
+	pte_t *pte = pte_alloc_one_kernel(mm, address);
+	return pte ? virt_to_page(pte) : NULL;
 }
 
 static inline void pte_free_kernel(pte_t *pte)
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index c863bdb..86a54a4a 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -6,11 +6,7 @@
 #ifndef __ASSEMBLY__
 #include <linux/sched.h>
 #include <linux/threads.h>
-#include <asm/processor.h>		/* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
 #include <asm/io.h>			/* For sub-arch specific PPC_PIN_SIZE */
-struct mm_struct;
 
 extern unsigned long va_to_phys(unsigned long address);
 extern pte_t *va_to_pte(unsigned long address);
@@ -488,14 +484,6 @@
 #define pfn_pte(pfn, prot)	__pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\
 					pgprot_val(prot))
 #define mk_pte(page, prot)	pfn_pte(page_to_pfn(page), prot)
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[1024];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-
 #endif /* __ASSEMBLY__ */
 
 #define pte_none(pte)		((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
@@ -512,9 +500,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
-static inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_EXEC; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
@@ -522,21 +508,13 @@
 static inline void pte_uncache(pte_t pte)       { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)         { pte_val(pte) &= ~_PAGE_NO_CACHE; }
 
-static inline pte_t pte_rdprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_EXEC; return pte; }
 static inline pte_t pte_mkclean(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
 static inline pte_t pte_mkold(pte_t pte) {
 	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 
-static inline pte_t pte_mkread(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte) {
 	pte_val(pte) |= _PAGE_RW; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte) {
@@ -643,13 +621,6 @@
 #define ptep_test_and_clear_young(__vma, __addr, __ptep) \
 	__ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep)
 
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
-					    unsigned long addr, pte_t *ptep)
-{
-	return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
-}
-
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 				       pte_t *ptep)
@@ -673,10 +644,14 @@
 }
 
 #define  ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-	do {								   \
-		__ptep_set_access_flags(__ptep, __entry, __dirty);	   \
-		flush_tlb_page_nohash(__vma, __address);	       	   \
-	} while(0)
+({									   \
+	int __changed = !pte_same(*(__ptep), __entry);			   \
+	if (__changed) {						   \
+		__ptep_set_access_flags(__ptep, __entry, __dirty);    	   \
+		flush_tlb_page_nohash(__vma, __address);		   \
+	}								   \
+	__changed;							   \
+})
 
 /*
  * Macro to mark a page protection value as "uncacheable".
@@ -730,10 +705,6 @@
 #define pte_unmap(pte)		kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte)	kunmap_atomic(pte, KM_PTE1)
 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
-extern void paging_init(void);
-
 /*
  * Encode and decode a swap entry.
  * Note that the bits we use in a PTE for representing a swap entry
@@ -751,40 +722,6 @@
 #define pte_to_pgoff(pte)	(pte_val(pte) >> 3)
 #define pgoff_to_pte(off)	((pte_t) { ((off) << 3) | _PAGE_FILE })
 
-/* CONFIG_APUS */
-/* For virtual address to physical address conversion */
-extern void cache_clear(__u32 addr, int length);
-extern void cache_push(__u32 addr, int length);
-extern int mm_end_of_chunk (unsigned long addr, int len);
-extern unsigned long iopa(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-
-/* Values for nocacheflag and cmode */
-/* These are not used by the APUS kernel_map, but prevents
-   compilation errors. */
-#define	KERNELMAP_FULL_CACHING		0
-#define	KERNELMAP_NOCACHE_SER		1
-#define	KERNELMAP_NOCACHE_NONSER	2
-#define	KERNELMAP_NO_COPYBACK		3
-
-/*
- * Map some physical address range into the kernel address space.
- */
-extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
-				int nocacheflag, unsigned long *memavailp );
-
-/*
- * Set cache mode of (kernel space) address range.
- */
-extern void kernel_set_cachemode (unsigned long address, unsigned long size,
-                                 unsigned int cmode);
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr)	(1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
-		remap_pfn_range(vma, vaddr, pfn, size, prot)
-
 /*
  * No page table caches to initialise
  */
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
index 704c4e6..300f9a1 100644
--- a/include/asm-powerpc/pgtable-ppc64.h
+++ b/include/asm-powerpc/pgtable-ppc64.h
@@ -7,11 +7,7 @@
 
 #ifndef __ASSEMBLY__
 #include <linux/stddef.h>
-#include <asm/processor.h>		/* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
 #include <asm/tlbflush.h>
-struct mm_struct;
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC_64K_PAGES
@@ -27,7 +23,7 @@
  */
 #define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
                 	    PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
-#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
+#define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
 
 #if TASK_SIZE_USER64 > PGTABLE_RANGE
 #error TASK_SIZE_USER64 exceeds pagetable range
@@ -37,19 +33,28 @@
 #error TASK_SIZE_USER64 exceeds user VSID range
 #endif
 
+
 /*
  * Define the address range of the vmalloc VM area.
  */
 #define VMALLOC_START ASM_CONST(0xD000000000000000)
-#define VMALLOC_SIZE  ASM_CONST(0x80000000000)
+#define VMALLOC_SIZE  (PGTABLE_RANGE >> 1)
 #define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
 
 /*
- * Define the address range of the imalloc VM area.
+ * Define the address ranges for MMIO and IO space :
+ *
+ *  ISA_IO_BASE = VMALLOC_END, 64K reserved area
+ *  PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
+ * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
  */
-#define PHBS_IO_BASE	VMALLOC_END
-#define IMALLOC_BASE	(PHBS_IO_BASE + 0x80000000ul)	/* Reserve 2 gigs for PHBs */
-#define IMALLOC_END	(VMALLOC_START + PGTABLE_RANGE)
+#define FULL_IO_SIZE	0x80000000ul
+#define  ISA_IO_BASE	(VMALLOC_END)
+#define  ISA_IO_END	(VMALLOC_END + 0x10000ul)
+#define  PHB_IO_BASE	(ISA_IO_END)
+#define  PHB_IO_END	(VMALLOC_END + FULL_IO_SIZE)
+#define IOREMAP_BASE	(PHB_IO_END)
+#define IOREMAP_END	(VMALLOC_START + PGTABLE_RANGE)
 
 /*
  * Region IDs
@@ -134,16 +139,6 @@
 #define __S110	PAGE_SHARED_X
 #define __S111	PAGE_SHARED_X
 
-#ifndef __ASSEMBLY__
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-#endif /* __ASSEMBLY__ */
-
 #ifdef CONFIG_HUGETLB_PAGE
 
 #define HAVE_ARCH_UNMAPPED_AREA
@@ -232,9 +227,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER;}
 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
-static inline int pte_exec(pte_t pte)  { return pte_val(pte) & _PAGE_EXEC;}
 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
 static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
@@ -242,20 +235,12 @@
 static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
 
-static inline pte_t pte_rdprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_USER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_EXEC; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_RW); return pte; }
 static inline pte_t pte_mkclean(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_DIRTY); return pte; }
 static inline pte_t pte_mkold(pte_t pte) {
 	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte) {
 	pte_val(pte) |= _PAGE_RW; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte) {
@@ -307,29 +292,6 @@
 	__r;								   \
 })
 
-/*
- * On RW/DIRTY bit transitions we can avoid flushing the hpte. For the
- * moment we always flush but we need to fix hpte_update and test if the
- * optimisation is worth it.
- */
-static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm,
-					      unsigned long addr, pte_t *ptep)
-{
-	unsigned long old;
-
-       	if ((pte_val(*ptep) & _PAGE_DIRTY) == 0)
-		return 0;
-	old = pte_update(mm, addr, ptep, _PAGE_DIRTY, 0);
-	return (old & _PAGE_DIRTY) != 0;
-}
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(__vma, __addr, __ptep)		   \
-({									   \
-	int __r;							   \
-	__r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \
-	__r;								   \
-})
-
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
 				      pte_t *ptep)
@@ -357,14 +319,6 @@
 	__young;							\
 })
 
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(__vma, __address, __ptep)		\
-({									\
-	int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \
-						  __ptep); 		\
-	__dirty;							\
-})
-
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 				       unsigned long addr, pte_t *ptep)
@@ -413,10 +367,14 @@
 	:"cc");
 }
 #define  ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-	do {								   \
-		__ptep_set_access_flags(__ptep, __entry, __dirty);	   \
-		flush_tlb_page_nohash(__vma, __address);	       	   \
-	} while(0)
+({									   \
+	int __changed = !pte_same(*(__ptep), __entry);			   \
+	if (__changed) {						   \
+		__ptep_set_access_flags(__ptep, __entry, __dirty);    	   \
+		flush_tlb_page_nohash(__vma, __address);		   \
+	}								   \
+	__changed;							   \
+})
 
 /*
  * Macro to mark a page protection value as "uncacheable".
@@ -438,10 +396,6 @@
 #define pgd_ERROR(e) \
 	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
-extern pgd_t swapper_pg_dir[];
-
-extern void paging_init(void);
-
 /* Encode and de-code a swap entry */
 #define __swp_type(entry)	(((entry).val >> 1) & 0x3f)
 #define __swp_offset(entry)	((entry).val >> 8)
@@ -452,17 +406,6 @@
 #define pgoff_to_pte(off)	((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
 #define PTE_FILE_MAX_BITS	(BITS_PER_LONG - PTE_RPN_SHIFT)
 
-/*
- * kern_addr_valid is intended to indicate whether an address is a valid
- * kernel address.  Most 32-bit archs define it as always true (like this)
- * but most 64-bit archs actually perform a test.  What should we do here?
- * The only use is in fs/ncpfs/dir.c
- */
-#define kern_addr_valid(addr)	(1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
-		remap_pfn_range(vma, vaddr, pfn, size, prot)
-
 void pgtable_cache_init(void);
 
 /*
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h
index 78bf4ae..d18ffe7 100644
--- a/include/asm-powerpc/pgtable.h
+++ b/include/asm-powerpc/pgtable.h
@@ -2,6 +2,13 @@
 #define _ASM_POWERPC_PGTABLE_H
 #ifdef __KERNEL__
 
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>		/* For TASK_SIZE */
+#include <asm/mmu.h>
+#include <asm/page.h>
+struct mm_struct;
+#endif /* !__ASSEMBLY__ */
+
 #if defined(CONFIG_PPC64)
 #  include <asm/pgtable-ppc64.h>
 #else
@@ -9,6 +16,27 @@
 #endif
 
 #ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern pgd_t swapper_pg_dir[];
+
+extern void paging_init(void);
+
+/*
+ * kern_addr_valid is intended to indicate whether an address is a valid
+ * kernel address.  Most 32-bit archs define it as always true (like this)
+ * but most 64-bit archs actually perform a test.  What should we do here?
+ */
+#define kern_addr_valid(addr)	(1)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+		remap_pfn_range(vma, vaddr, pfn, size, prot)
+
 #include <asm-generic/pgtable.h>
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index 8e20051..b847aa1 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -26,7 +26,7 @@
 
 extern void find_and_init_phbs(void);
 
-extern struct pci_dev *ppc64_isabridge_dev;	/* may be NULL if no ISA bus */
+extern struct pci_dev *isa_bridge_pcidev;	/* may be NULL if no ISA bus */
 
 /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
 #define BUID_HI(buid) ((buid) >> 32)
@@ -47,8 +47,8 @@
 extern unsigned long get_phb_buid (struct device_node *);
 extern int rtas_setup_phb(struct pci_controller *phb);
 
-/* From pSeries_pci.h */
-extern void pSeries_final_fixup(void);
+/* From iSeries PCI */
+extern void iSeries_pcibios_init(void);
 
 extern unsigned long pci_probe_only;
 
@@ -139,6 +139,9 @@
  */
 struct device_node * find_device_pe(struct device_node *dn);
 
+void eeh_sysfs_add_device(struct pci_dev *pdev);
+void eeh_sysfs_remove_device(struct pci_dev *pdev);
+
 #endif /* CONFIG_EEH */
 
 #else /* CONFIG_PCI */
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index d947b16..e28b108 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -43,14 +43,6 @@
 /* what kind of prep workstation we are */
 extern int _prep_type;
 
-/*
- * This is used to identify the board type from a given PReP board
- * vendor. Board revision is also made available. This will be moved
- * elsewhere soon
- */
-extern unsigned char ucBoardRev;
-extern unsigned char ucBoardRevMaj, ucBoardRevMin;
-
 #endif /* CONFIG_PPC_PREP */
 
 #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 6845af9..1632baa 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -98,10 +98,19 @@
 extern struct device_node *of_chosen;
 
 /* flag descriptions */
-#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+#define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
+#define OF_DETACHED	2 /* node has been detached from the device tree */
 
-#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
-#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
+static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
+{
+	return test_bit(flag, &n->_flags);
+}
+
+static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
+{
+	set_bit(flag, &n->_flags);
+}
+
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
@@ -124,6 +133,9 @@
 	     dn = of_find_node_by_type(dn, type))
 extern struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compat);
+#define for_each_compatible_node(dn, type, compatible) \
+	for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
+	     dn = of_find_compatible_node(dn, type, compatible))
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_find_all_nodes(struct device_node *prev);
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 1e04651..a6f3f5e 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -35,7 +35,8 @@
 	};
 };
 
-int ps3_get_firmware_version(union ps3_firmware_version *v);
+void ps3_get_firmware_version(union ps3_firmware_version *v);
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev);
 
 /* 'Other OS' area */
 
@@ -48,18 +49,6 @@
 
 enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void);
 
-/**
- * struct ps3_device_id - HV bus device identifier from the system repository
- * @bus_id: HV bus id, {1..} (zero invalid)
- * @dev_id: HV device id, {0..}
- */
-
-struct ps3_device_id {
-	unsigned int bus_id;
-	unsigned int dev_id;
-};
-
-
 /* dma routines */
 
 enum ps3_dma_page_size {
@@ -74,6 +63,8 @@
 	PS3_DMA_INTERNAL = 2,
 };
 
+struct ps3_dma_region_ops;
+
 /**
  * struct ps3_dma_region - A per device dma state variables structure
  * @did: The HV device id.
@@ -81,21 +72,42 @@
  * @region_type: The HV region type.
  * @bus_addr: The 'translated' bus address of the region.
  * @len: The length in bytes of the region.
+ * @offset: The offset from the start of memory of the region.
+ * @ioid: The IOID of the device who owns this region
  * @chunk_list: Opaque variable used by the ioc page manager.
+ * @region_ops: struct ps3_dma_region_ops - dma region operations
  */
 
 struct ps3_dma_region {
-	struct ps3_device_id did;
+	struct ps3_system_bus_device *dev;
+	/* device variables */
+	const struct ps3_dma_region_ops *region_ops;
+	unsigned char ioid;
 	enum ps3_dma_page_size page_size;
 	enum ps3_dma_region_type region_type;
-	unsigned long bus_addr;
 	unsigned long len;
+	unsigned long offset;
+
+	/* driver variables  (set by ps3_dma_region_create) */
+	unsigned long bus_addr;
 	struct {
 		spinlock_t lock;
 		struct list_head head;
 	} chunk_list;
 };
 
+struct ps3_dma_region_ops {
+	int (*create)(struct ps3_dma_region *);
+	int (*free)(struct ps3_dma_region *);
+	int (*map)(struct ps3_dma_region *,
+		   unsigned long virt_addr,
+		   unsigned long len,
+		   unsigned long *bus_addr,
+		   u64 iopte_pp);
+	int (*unmap)(struct ps3_dma_region *,
+		     unsigned long bus_addr,
+		     unsigned long len);
+};
 /**
  * struct ps3_dma_region_init - Helper to initialize structure variables
  *
@@ -103,18 +115,16 @@
  * ps3_system_bus_device_register.
  */
 
-static inline void ps3_dma_region_init(struct ps3_dma_region *r,
-	const struct ps3_device_id* did, enum ps3_dma_page_size page_size,
-	enum ps3_dma_region_type region_type)
-{
-	r->did = *did;
-	r->page_size = page_size;
-	r->region_type = region_type;
-}
+struct ps3_system_bus_device;
+
+int ps3_dma_region_init(struct ps3_system_bus_device *dev,
+	struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
+	enum ps3_dma_region_type region_type, void *addr, unsigned long len);
 int ps3_dma_region_create(struct ps3_dma_region *r);
 int ps3_dma_region_free(struct ps3_dma_region *r);
 int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
-	unsigned long len, unsigned long *bus_addr);
+	unsigned long len, unsigned long *bus_addr,
+	u64 iopte_pp);
 int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
 	unsigned long len);
 
@@ -125,6 +135,7 @@
 	PS3_MMIO_64K = 16U
 };
 
+struct ps3_mmio_region_ops;
 /**
  * struct ps3_mmio_region - a per device mmio state variables structure
  *
@@ -132,13 +143,18 @@
  */
 
 struct ps3_mmio_region {
-	struct ps3_device_id did;
+	struct ps3_system_bus_device *dev;
+	const struct ps3_mmio_region_ops *mmio_ops;
 	unsigned long bus_addr;
 	unsigned long len;
 	enum ps3_mmio_page_size page_size;
 	unsigned long lpar_addr;
 };
 
+struct ps3_mmio_region_ops {
+	int (*create)(struct ps3_mmio_region *);
+	int (*free)(struct ps3_mmio_region *);
+};
 /**
  * struct ps3_mmio_region_init - Helper to initialize structure variables
  *
@@ -146,15 +162,9 @@
  * ps3_system_bus_device_register.
  */
 
-static inline void ps3_mmio_region_init(struct ps3_mmio_region *r,
-	const struct ps3_device_id* did, unsigned long bus_addr,
-	unsigned long len, enum ps3_mmio_page_size page_size)
-{
-	r->did = *did;
-	r->bus_addr = bus_addr;
-	r->len = len;
-	r->page_size = page_size;
-}
+int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
+	struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len,
+	enum ps3_mmio_page_size page_size);
 int ps3_mmio_region_create(struct ps3_mmio_region *r);
 int ps3_free_mmio_region(struct ps3_mmio_region *r);
 unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr);
@@ -187,11 +197,10 @@
 	unsigned int class, unsigned int *virq);
 int ps3_spe_irq_destroy(unsigned int virq);
 
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
-	const struct ps3_device_id *did, unsigned int interrupt_id,
-	unsigned int *virq);
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
-	unsigned int interrupt_id, unsigned int virq);
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+	enum ps3_cpu_binding cpu, unsigned int *virq);
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+	unsigned int virq);
 
 /* lv1 result codes */
 
@@ -289,11 +298,33 @@
 /* system bus routines */
 
 enum ps3_match_id {
-	PS3_MATCH_ID_EHCI = 1,
-	PS3_MATCH_ID_OHCI,
-	PS3_MATCH_ID_GELIC,
-	PS3_MATCH_ID_AV_SETTINGS,
-	PS3_MATCH_ID_SYSTEM_MANAGER,
+	PS3_MATCH_ID_EHCI           = 1,
+	PS3_MATCH_ID_OHCI           = 2,
+	PS3_MATCH_ID_GELIC          = 3,
+	PS3_MATCH_ID_AV_SETTINGS    = 4,
+	PS3_MATCH_ID_SYSTEM_MANAGER = 5,
+	PS3_MATCH_ID_STOR_DISK      = 6,
+	PS3_MATCH_ID_STOR_ROM       = 7,
+	PS3_MATCH_ID_STOR_FLASH     = 8,
+	PS3_MATCH_ID_SOUND          = 9,
+	PS3_MATCH_ID_GRAPHICS       = 10,
+};
+
+#define PS3_MODULE_ALIAS_EHCI           "ps3:1"
+#define PS3_MODULE_ALIAS_OHCI           "ps3:2"
+#define PS3_MODULE_ALIAS_GELIC          "ps3:3"
+#define PS3_MODULE_ALIAS_AV_SETTINGS    "ps3:4"
+#define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5"
+#define PS3_MODULE_ALIAS_STOR_DISK      "ps3:6"
+#define PS3_MODULE_ALIAS_STOR_ROM       "ps3:7"
+#define PS3_MODULE_ALIAS_STOR_FLASH     "ps3:8"
+#define PS3_MODULE_ALIAS_SOUND          "ps3:9"
+#define PS3_MODULE_ALIAS_GRAPHICS       "ps3:10"
+
+enum ps3_system_bus_device_type {
+	PS3_DEVICE_TYPE_IOC0 = 1,
+	PS3_DEVICE_TYPE_SB,
+	PS3_DEVICE_TYPE_VUART,
 };
 
 /**
@@ -302,14 +333,23 @@
 
 struct ps3_system_bus_device {
 	enum ps3_match_id match_id;
-	struct ps3_device_id did;
-	unsigned int interrupt_id;
-/*	struct iommu_table *iommu_table; -- waiting for Ben's cleanups */
-	struct ps3_dma_region *d_region;
-	struct ps3_mmio_region *m_region;
+	enum ps3_system_bus_device_type dev_type;
+
+	unsigned int bus_id;              /* SB */
+	unsigned int dev_id;              /* SB */
+	unsigned int interrupt_id;        /* SB */
+	struct ps3_dma_region *d_region;  /* SB, IOC0 */
+	struct ps3_mmio_region *m_region; /* SB, IOC0*/
+	unsigned int port_number;         /* VUART */
+
+/*	struct iommu_table *iommu_table; -- waiting for BenH's cleanups */
 	struct device core;
+	void *driver_priv; /* private driver variables */
 };
 
+int ps3_open_hv_device(struct ps3_system_bus_device *dev);
+int ps3_close_hv_device(struct ps3_system_bus_device *dev);
+
 /**
  * struct ps3_system_bus_driver - a driver for a device on the system bus
  */
@@ -319,6 +359,7 @@
 	struct device_driver core;
 	int (*probe)(struct ps3_system_bus_device *);
 	int (*remove)(struct ps3_system_bus_device *);
+	int (*shutdown)(struct ps3_system_bus_device *);
 /*	int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
 /*	int (*resume)(struct ps3_system_bus_device *); */
 };
@@ -326,16 +367,24 @@
 int ps3_system_bus_device_register(struct ps3_system_bus_device *dev);
 int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv);
 void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv);
-static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver(
+
+static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv(
 	struct device_driver *_drv)
 {
 	return container_of(_drv, struct ps3_system_bus_driver, core);
 }
-static inline struct ps3_system_bus_device *to_ps3_system_bus_device(
+static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev(
 	struct device *_dev)
 {
 	return container_of(_dev, struct ps3_system_bus_device, core);
 }
+static inline struct ps3_system_bus_driver *
+	ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev)
+{
+	BUG_ON(!_dev);
+	BUG_ON(!_dev->core.driver);
+	return ps3_drv_to_system_bus_drv(_dev->core.driver);
+}
 
 /**
  * ps3_system_bus_set_drvdata -
@@ -358,32 +407,17 @@
 
 extern struct bus_type ps3_system_bus_type;
 
-/* vuart routines */
-
-struct ps3_vuart_port_priv;
-
-/**
- * struct ps3_vuart_port_device - a device on a vuart port
- */
-
-struct ps3_vuart_port_device {
-	enum ps3_match_id match_id;
-	struct device core;
-	struct ps3_vuart_port_priv* priv; /* private driver variables */
-
-};
-
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
-
 /* system manager */
 
-#ifdef CONFIG_PS3_SYS_MANAGER
-void ps3_sys_manager_restart(void);
+struct ps3_sys_manager_ops {
+	struct ps3_system_bus_device *dev;
+	void (*power_off)(struct ps3_system_bus_device *dev);
+	void (*restart)(struct ps3_system_bus_device *dev);
+};
+
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops);
 void ps3_sys_manager_power_off(void);
-#else
-static inline void ps3_sys_manager_restart(void) {}
-static inline void ps3_sys_manager_power_off(void) {}
-#endif
+void ps3_sys_manager_restart(void);
 
 struct ps3_prealloc {
     const char *name;
@@ -393,5 +427,7 @@
 };
 
 extern struct ps3_prealloc ps3fb_videomemory;
+extern struct ps3_prealloc ps3flash_bounce_buffer;
+
 
 #endif
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
index 9efc40f..7df4250 100644
--- a/include/asm-powerpc/ps3av.h
+++ b/include/asm-powerpc/ps3av.h
@@ -1,20 +1,23 @@
 /*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ *  PS3 AV backend support.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
  *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
 #ifndef _ASM_POWERPC_PS3AV_H_
 #define _ASM_POWERPC_PS3AV_H_
 
@@ -159,6 +162,9 @@
 #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8			0x0000
 /* video_out_format */
 #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT		0x0000
+/* video_cl_cnv */
+#define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT		0x0000
+#define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT		0x0010
 /* video_sync */
 #define PS3AV_CMD_VIDEO_SYNC_VSYNC			0x0001
 #define PS3AV_CMD_VIDEO_SYNC_CSYNC			0x0004
@@ -311,6 +317,8 @@
 #define PS3AV_MODE_MASK				0x000F
 #define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
 #define PS3AV_MODE_DITHER			0x0800
+#define PS3AV_MODE_COLOR			0x0400
+#define PS3AV_MODE_WHITE			0x0200
 #define PS3AV_MODE_FULL				0x0080
 #define PS3AV_MODE_DVI				0x0040
 #define PS3AV_MODE_RGB				0x0020
@@ -529,9 +537,9 @@
 	u32 video_out_format;	/* in: out format */
 	u32 video_format;	/* in: input frame buffer format */
 	u8 reserved3;
-	u8 reserved4;
+	u8 video_cl_cnv;	/* in: color conversion */
 	u16 video_order;	/* in: input RGB order */
-	u32 reserved5;
+	u32 reserved4;
 };
 
 /* video: format */
@@ -539,7 +547,8 @@
 	struct ps3av_send_hdr send_hdr;
 	u32 video_head;		/* in: head */
 	u32 video_format;	/* in: frame buffer format */
-	u16 reserved;
+	u8 reserved;
+	u8 video_cl_cnv;	/* in: color conversion */
 	u16 video_order;	/* in: input RGB order */
 };
 
@@ -698,12 +707,6 @@
 extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
 					    u32);
 
-struct ps3_vuart_port_device;
-extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
-			     const void *buf, unsigned long size);
-extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
-			    unsigned long size, int timeout);
-
 extern int ps3av_set_video_mode(u32, int);
 extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
 extern int ps3av_get_auto_mode(int);
@@ -716,5 +719,8 @@
 extern int ps3av_audio_mute(int);
 extern int ps3av_dev_open(void);
 extern int ps3av_dev_close(void);
+extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+				    void *flip_data);
+extern void ps3av_flip_ctl(int on);
 
 #endif	/* _ASM_POWERPC_PS3AV_H_ */
diff --git a/include/asm-powerpc/ps3fb.h b/include/asm-powerpc/ps3fb.h
index ad81cf4..3f121fe 100644
--- a/include/asm-powerpc/ps3fb.h
+++ b/include/asm-powerpc/ps3fb.h
@@ -41,16 +41,4 @@
 	__u32 num_frames; /* num of frame buffers */
 };
 
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FB_PS3
-extern void ps3fb_flip_ctl(int on);
-extern void ps3fb_cleanup(void);
-#else
-static inline void ps3fb_flip_ctl(int on) {}
-static inline void ps3fb_cleanup(void) {}
-#endif
-
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_POWERPC_PS3FB_H_ */
diff --git a/include/asm-powerpc/ps3stor.h b/include/asm-powerpc/ps3stor.h
new file mode 100644
index 0000000..6fcaf71
--- /dev/null
+++ b/include/asm-powerpc/ps3stor.h
@@ -0,0 +1,71 @@
+/*
+ * PS3 Storage Devices
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _ASM_POWERPC_PS3STOR_H_
+#define _ASM_POWERPC_PS3STOR_H_
+
+#include <linux/interrupt.h>
+
+#include <asm/ps3.h>
+
+
+struct ps3_storage_region {
+	unsigned int id;
+	u64 start;
+	u64 size;
+};
+
+struct ps3_storage_device {
+	struct ps3_system_bus_device sbd;
+
+	struct ps3_dma_region dma_region;
+	unsigned int irq;
+	u64 blk_size;
+
+	u64 tag;
+	u64 lv1_status;
+	struct completion done;
+
+	unsigned long bounce_size;
+	void *bounce_buf;
+	u64 bounce_lpar;
+	dma_addr_t bounce_dma;
+
+	unsigned int num_regions;
+	unsigned long accessible_regions;
+	unsigned int region_idx;		/* first accessible region */
+	struct ps3_storage_region regions[0];	/* Must be last */
+};
+
+static inline struct ps3_storage_device *to_ps3_storage_device(struct device *dev)
+{
+	return container_of(dev, struct ps3_storage_device, sbd.core);
+}
+
+extern int ps3stor_setup(struct ps3_storage_device *dev,
+			 irq_handler_t handler);
+extern void ps3stor_teardown(struct ps3_storage_device *dev);
+extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+				      u64 start_sector, u64 sectors,
+				      int write);
+extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd,
+				u64 arg1, u64 arg2, u64 arg3, u64 arg4);
+
+#endif /* _ASM_POWERPC_PS3STOR_H_ */
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h
index 4ad77a1..13fccc5 100644
--- a/include/asm-powerpc/ptrace.h
+++ b/include/asm-powerpc/ptrace.h
@@ -92,6 +92,11 @@
 		set_thread_flag(TIF_NOERROR); \
 	} while(0)
 
+struct task_struct;
+extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
+extern int ptrace_put_reg(struct task_struct *task, int regno,
+			  unsigned long data);
+
 /*
  * We use the least-significant bit of the trap field to indicate
  * whether we have saved the full set of registers, or only a
@@ -158,9 +163,7 @@
 
 #define PT_NIP	32
 #define PT_MSR	33
-#ifdef __KERNEL__
 #define PT_ORIG_R3 34
-#endif
 #define PT_CTR	35
 #define PT_LNK	36
 #define PT_XER	37
@@ -169,11 +172,12 @@
 #define PT_MQ	39
 #else
 #define PT_SOFTE 39
+#endif
 #define PT_TRAP	40
 #define PT_DAR	41
 #define PT_DSISR 42
 #define PT_RESULT 43
-#endif
+#define PT_REGS_COUNT 44
 
 #define PT_FPR0	48	/* each FP reg occupies 2 slots in this space */
 
@@ -229,7 +233,17 @@
 #define PTRACE_GET_DEBUGREG	25
 #define PTRACE_SET_DEBUGREG	26
 
-/* Additional PTRACE requests implemented on PowerPC. */
+/* (new) PTRACE requests using the same numbers as x86 and the same
+ * argument ordering. Additionally, they support more registers too
+ */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_GETREGS64	  22
+#define PTRACE_SETREGS64	  23
+
+/* (old) PTRACE requests with inverted arguments */
 #define PPC_PTRACE_GETREGS	0x99	/* Get GPRs 0 - 31 */
 #define PPC_PTRACE_SETREGS	0x98	/* Set GPRs 0 - 31 */
 #define PPC_PTRACE_GETFPREGS	0x97	/* Get FPRs 0 - 31 */
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 749c7f9..281011e 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -453,6 +453,8 @@
 #define SPRN_MMCRA	0x312
 #define   MMCRA_SIHV	0x10000000UL /* state of MSR HV when SIAR set */
 #define   MMCRA_SIPR	0x08000000UL /* state of MSR PR when SIAR set */
+#define   MMCRA_SLOT	0x07000000UL /* SLOT bits (37-39) */
+#define   MMCRA_SLOT_SHIFT	24
 #define   MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
 #define   POWER6_MMCRA_SIHV   0x0000040000000000ULL
 #define   POWER6_MMCRA_SIPR   0x0000020000000000ULL
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 31d5054..eedc828 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -106,6 +106,14 @@
 struct spu_runqueue;
 struct device_node;
 
+enum spu_utilization_state {
+	SPU_UTIL_SYSTEM,
+	SPU_UTIL_USER,
+	SPU_UTIL_IOWAIT,
+	SPU_UTIL_IDLE,
+	SPU_UTIL_MAX
+};
+
 struct spu {
 	const char *name;
 	unsigned long local_store_phys;
@@ -156,6 +164,21 @@
 	u64 shadow_int_mask_RW[3];
 
 	struct sys_device sysdev;
+
+	struct {
+		/* protected by interrupt reentrancy */
+		enum spu_utilization_state utilization_state;
+		unsigned long tstamp;		/* time of last ctx switch */
+		unsigned long times[SPU_UTIL_MAX];
+		unsigned long long vol_ctx_switch;
+		unsigned long long invol_ctx_switch;
+		unsigned long long min_flt;
+		unsigned long long maj_flt;
+		unsigned long long hash_flt;
+		unsigned long long slb_flt;
+		unsigned long long class2_intr;
+		unsigned long long libassist;
+	} stats;
 };
 
 struct spu *spu_alloc(void);
@@ -448,6 +471,7 @@
 #define MFC_STATE1_PROBLEM_STATE_MASK		0x08ull
 #define MFC_STATE1_RELOCATE_MASK		0x10ull
 #define MFC_STATE1_MASTER_RUN_CONTROL_MASK	0x20ull
+#define MFC_STATE1_TABLE_SEARCH_MASK		0x40ull
 	u64 mfc_lpid_RW;					/* 0x008 */
 	u64 spu_idr_RW;						/* 0x010 */
 	u64 mfc_vr_RO;						/* 0x018 */
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h
index c2fe79d..b3ca41f 100644
--- a/include/asm-powerpc/syscalls.h
+++ b/include/asm-powerpc/syscalls.h
@@ -43,16 +43,9 @@
 
 asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
 		size_t sigsetsize);
-
-#ifndef __powerpc64__
-asmlinkage long sys_sigaltstack(const stack_t __user *uss,
-		stack_t __user *uoss, int r5, int r6, int r7, int r8,
-		struct pt_regs *regs);
-#else /* __powerpc64__ */
 asmlinkage long sys_sigaltstack(const stack_t __user *uss,
 		stack_t __user *uoss, unsigned long r5, unsigned long r6,
 		unsigned long r7, unsigned long r8, struct pt_regs *regs);
-#endif /* __powerpc64__ */
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_POWERPC_SYSCALLS_H */
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
index 700ca59..1cc3f9c 100644
--- a/include/asm-powerpc/systbl.h
+++ b/include/asm-powerpc/systbl.h
@@ -311,3 +311,4 @@
 COMPAT_SYS_SPU(signalfd)
 COMPAT_SYS_SPU(timerfd)
 SYSCALL_SPU(eventfd)
+COMPAT_SYS_SPU(sync_file_range2)
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 09621f6..32aa42b 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -43,7 +43,7 @@
 #ifdef CONFIG_SMP
 #define smp_mb()	mb()
 #define smp_rmb()	rmb()
-#define smp_wmb()	__asm__ __volatile__ ("eieio" : : : "memory")
+#define smp_wmb()	eieio()
 #define smp_read_barrier_depends()	read_barrier_depends()
 #else
 #define smp_mb()	barrier()
@@ -559,5 +559,7 @@
 extern void account_system_vtime(struct task_struct *);
 #endif
 
+extern struct dentry *powerpc_debugfs_root;
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SYSTEM_H */
diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h
index 5e79198..6698188 100644
--- a/include/asm-powerpc/termbits.h
+++ b/include/asm-powerpc/termbits.h
@@ -152,6 +152,10 @@
 #define B3000000  00034
 #define B3500000  00035
 #define B4000000  00036
+#define   BOTHER  00037
+
+#define CIBAUD	077600000
+#define IBSHIFT	16		/* Shift from CBAUD to CIBAUD */
 
 #define CSIZE	00001400
 #define   CS5	00000000
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index 3f32ca8..9d9aeca 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -113,8 +113,8 @@
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_32BIT		5	/* 32 bit binary */
-#define TIF_RUNLATCH		6	/* Is the runlatch enabled? */
-#define TIF_ABI_PENDING		7	/* 32/64 bit switch needed */
+#define TIF_PERFMON_WORK	6	/* work for pfm_handle_work() */
+#define TIF_PERFMON_CTXSW	7	/* perfmon needs ctxsw calls */
 #define TIF_SYSCALL_AUDIT	8	/* syscall auditing active */
 #define TIF_SINGLESTEP		9	/* singlestepping active */
 #define TIF_MEMDIE		10
@@ -123,6 +123,8 @@
 #define TIF_NOERROR		14	/* Force successful syscall return */
 #define TIF_RESTORE_SIGMASK	15	/* Restore signal mask in do_signal */
 #define TIF_FREEZE		16	/* Freezing for suspend */
+#define TIF_RUNLATCH		17	/* Is the runlatch enabled? */
+#define TIF_ABI_PENDING		18	/* 32/64 bit switch needed */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -131,8 +133,8 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_32BIT		(1<<TIF_32BIT)
-#define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
-#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
+#define _TIF_PERFMON_WORK	(1<<TIF_PERFMON_WORK)
+#define _TIF_PERFMON_CTXSW	(1<<TIF_PERFMON_CTXSW)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
@@ -140,6 +142,8 @@
 #define _TIF_NOERROR		(1<<TIF_NOERROR)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
+#define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
+#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index 3fd57c0..d7f5ddf 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -232,7 +232,7 @@
 #define account_process_vtime(tsk)		do { } while (0)
 #endif
 
-#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING)
 extern void calculate_steal_time(void);
 extern void snapshot_timebases(void);
 #else
@@ -240,5 +240,7 @@
 #define snapshot_timebases()			do { } while (0)
 #endif
 
+extern void iSeries_time_init_early(void);
+
 #endif /* __KERNEL__ */
 #endif /* __POWERPC_TIME_H */
diff --git a/include/asm-powerpc/tlb.h b/include/asm-powerpc/tlb.h
index 0a17682..6671404 100644
--- a/include/asm-powerpc/tlb.h
+++ b/include/asm-powerpc/tlb.h
@@ -38,6 +38,15 @@
 
 static inline void tlb_flush(struct mmu_gather *tlb)
 {
+	struct ppc64_tlb_batch *tlbbatch = &__get_cpu_var(ppc64_tlb_batch);
+
+	/* If there's a TLB batch pending, then we must flush it because the
+	 * pages are going to be freed and we really don't want to have a CPU
+	 * access a freed page because it has a stale TLB
+	 */
+	if (tlbbatch->index)
+		__flush_tlb_pending(tlbbatch);
+
 	pte_free_finish();
 }
 
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
index 86e6266..99a0439 100644
--- a/include/asm-powerpc/tlbflush.h
+++ b/include/asm-powerpc/tlbflush.h
@@ -155,6 +155,11 @@
 {
 }
 
+/* Private function for use by PCI IO mapping code */
+extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+				     unsigned long end);
+
+
 #endif
 
 /*
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index e3c28dc..f71c606 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -330,10 +330,11 @@
 #define __NR_signalfd		305
 #define __NR_timerfd		306
 #define __NR_eventfd		307
+#define __NR_sync_file_range2	308
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls		308
+#define __NR_syscalls		309
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
index 9d16202..d2442cd 100644
--- a/include/asm-ppc/pci.h
+++ b/include/asm-ppc/pci.h
@@ -102,12 +102,6 @@
 }
 #endif
 
-/*
- * At present there are very few 32-bit PPC machines that can have
- * memory above the 4GB point, and we don't support that.
- */
-#define pci_dac_dma_supported(pci_dev, mask)	(0)
-
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
@@ -145,8 +139,6 @@
 	return root;
 }
 
-extern void pcibios_add_platform_entries(struct pci_dev *dev);
-
 struct file;
 extern pgprot_t	pci_phys_mem_access_prot(struct file *file,
 					 unsigned long pfn,
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index bed452d..c159315 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -533,9 +533,7 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
-static inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_EXEC; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
@@ -543,21 +541,13 @@
 static inline void pte_uncache(pte_t pte)       { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)         { pte_val(pte) &= ~_PAGE_NO_CACHE; }
 
-static inline pte_t pte_rdprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_EXEC; return pte; }
 static inline pte_t pte_mkclean(pte_t pte) {
 	pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
 static inline pte_t pte_mkold(pte_t pte) {
 	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 
-static inline pte_t pte_mkread(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte) {
 	pte_val(pte) |= _PAGE_RW; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte) {
@@ -664,13 +654,6 @@
 #define ptep_test_and_clear_young(__vma, __addr, __ptep) \
 	__ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep)
 
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
-					    unsigned long addr, pte_t *ptep)
-{
-	return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
-}
-
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 				       pte_t *ptep)
@@ -694,10 +677,14 @@
 }
 
 #define  ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-	do {								   \
-		__ptep_set_access_flags(__ptep, __entry, __dirty);	   \
-		flush_tlb_page_nohash(__vma, __address);	       	   \
-	} while(0)
+({									   \
+	int __changed = !pte_same(*(__ptep), __entry);			   \
+	if (__changed) {						   \
+		__ptep_set_access_flags(__ptep, __entry, __dirty);    	   \
+		flush_tlb_page_nohash(__vma, __address);		   \
+	}								   \
+	__changed;							   \
+})
 
 /*
  * Macro to mark a page protection value as "uncacheable".
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index c17bdbf..ea48695 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -24,7 +24,7 @@
  */
 
 typedef struct {
-	volatile int counter;
+	int counter;
 } __attribute__ ((aligned (4))) atomic_t;
 #define ATOMIC_INIT(i)  { (i) }
 
@@ -141,7 +141,7 @@
 
 #ifdef __s390x__
 typedef struct {
-	volatile long long counter;
+	long long counter;
 } __attribute__ ((aligned (8))) atomic64_t;
 #define ATOMIC64_INIT(i)  { (i) }
 
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h
index 241756f..021e7c3 100644
--- a/include/asm-s390/cmb.h
+++ b/include/asm-s390/cmb.h
@@ -88,7 +88,6 @@
  *    any
  **/
 extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data);
-extern void cmf_reset(struct ccw_device *cdev);
 
 #endif /* __KERNEL__ */
 #endif /* S390_CMB_H */
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h
index 296f4f1..7f4ad62 100644
--- a/include/asm-s390/compat.h
+++ b/include/asm-s390/compat.h
@@ -60,8 +60,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-s390/dma-mapping.h b/include/asm-s390/dma-mapping.h
deleted file mode 100644
index 3f8c12f..0000000
--- a/include/asm-s390/dma-mapping.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- *  include/asm-s390/dma-mapping.h
- *
- *  S390 version
- *
- *  This file exists so that #include <dma-mapping.h> doesn't break anything.
- */
-
-#ifndef _ASM_DMA_MAPPING_H
-#define _ASM_DMA_MAPPING_H
-
-#endif /* _ASM_DMA_MAPPING_H */
diff --git a/include/asm-s390/fb.h b/include/asm-s390/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-s390/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 05ea6f1..f326451 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -64,7 +64,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
 /*
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 8fe8d42..3208dc6 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -530,14 +530,6 @@
 	return 0;
 }
 
-static inline int pte_read(pte_t pte)
-{
-	/* All pages are readable since we don't use the fetch
-	 * protection bit in the storage key.
-	 */
-	return 1;
-}
-
 /*
  * pgd/pmd/pte modification functions
  */
@@ -677,19 +669,6 @@
 	return ptep_test_and_clear_young(vma, address, ptep);
 }
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-	return 0;
-}
-
-static inline int
-ptep_clear_flush_dirty(struct vm_area_struct *vma,
-			unsigned long address, pte_t *ptep)
-{
-	/* No need to flush TLB; bits are in storage key */
-	return ptep_test_and_clear_dirty(vma, address, ptep);
-}
-
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t pte = *ptep;
@@ -715,16 +694,19 @@
 	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
 }
 
-static inline pte_t
-ptep_clear_flush(struct vm_area_struct *vma,
-		 unsigned long address, pte_t *ptep)
+static inline void ptep_invalidate(unsigned long address, pte_t *ptep)
+{
+	__ptep_ipte(address, ptep);
+	ptep = get_shadow_pte(ptep);
+	if (ptep)
+		__ptep_ipte(address, ptep);
+}
+
+static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
+				     unsigned long address, pte_t *ptep)
 {
 	pte_t pte = *ptep;
-	pte_t *shadow_pte = get_shadow_pte(ptep);
-
-	__ptep_ipte(address, ptep);
-	if (shadow_pte)
-		__ptep_ipte(address, shadow_pte);
+	ptep_invalidate(address, ptep);
 	return pte;
 }
 
@@ -734,17 +716,15 @@
 	set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
 }
 
-static inline void
-ptep_establish(struct vm_area_struct *vma, 
-	       unsigned long address, pte_t *ptep,
-	       pte_t entry)
-{
-	ptep_clear_flush(vma, address, ptep);
-	set_pte(ptep, entry);
-}
-
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-	ptep_establish(__vma, __address, __ptep, __entry)
+#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty)	\
+({									\
+	int __changed = !pte_same(*(__ptep), __entry);			\
+	if (__changed) {						\
+		ptep_invalidate(__addr, __ptep);			\
+		set_pte_at((__vma)->vm_mm, __addr, __ptep, __entry);	\
+	}								\
+	__changed;							\
+})
 
 /*
  * Test and clear dirty bit in storage key.
@@ -943,12 +923,9 @@
 #define __HAVE_ARCH_MEMMAP_INIT
 extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
 
-#define __HAVE_ARCH_PTEP_ESTABLISH
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index e0fcea8..3b972d4 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -216,6 +216,11 @@
 	barrier();
 }
 
+static inline void psw_set_key(unsigned int key)
+{
+	asm volatile("spka 0(%0)" : : "d" (key));
+}
+
 /*
  * Set PSW to specified value.
  */
@@ -352,8 +357,8 @@
 /*
  * CPU idle notifier chain.
  */
-#define CPU_IDLE	0
-#define CPU_NOT_IDLE	1
+#define S390_CPU_IDLE		0
+#define S390_CPU_NOT_IDLE	1
 
 struct notifier_block;
 int register_idle_notifier(struct notifier_block *nb);
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index fa6ca87..332ee73 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -470,14 +470,7 @@
 #define regs_return_value(regs)((regs)->gprs[2])
 #define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs * regs);
-#endif
-
-static inline void
-psw_set_key(unsigned int key)
-{
-	asm volatile("spka 0(%0)" : : "d" (key));
-}
-
+#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 
 #endif /* _S390_PTRACE_H */
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h
index 21ed647..cb9faf1 100644
--- a/include/asm-s390/sclp.h
+++ b/include/asm-s390/sclp.h
@@ -11,29 +11,6 @@
 #include <linux/types.h>
 #include <asm/chpid.h>
 
-struct sccb_header {
-	u16	length;
-	u8	function_code;
-	u8	control_mask[3];
-	u16	response_code;
-} __attribute__((packed));
-
-#define LOADPARM_LEN 8
-
-struct sclp_readinfo_sccb {
-	struct	sccb_header header;	/* 0-7 */
-	u16	rnmax;			/* 8-9 */
-	u8	rnsize;			/* 10 */
-	u8	_reserved0[24 - 11];	/* 11-23 */
-	u8	loadparm[LOADPARM_LEN];	/* 24-31 */
-	u8	_reserved1[91 - 32];	/* 32-90 */
-	u8	flags;			/* 91 */
-	u8	_reserved2[100 - 92];	/* 92-99 */
-	u32	rnsize2;		/* 100-103 */
-	u64	rnmax2;			/* 104-111 */
-	u8	_reserved3[4096 - 112];	/* 112-4095 */
-} __attribute__((packed, aligned(4096)));
-
 #define SCLP_CHP_INFO_MASK_SIZE		32
 
 struct sclp_chp_info {
@@ -42,12 +19,22 @@
 	u8 configured[SCLP_CHP_INFO_MASK_SIZE];
 };
 
-extern struct sclp_readinfo_sccb s390_readinfo_sccb;
-extern void sclp_readinfo_early(void);
-extern int sclp_sdias_blk_count(void);
-extern int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
-extern int sclp_chp_configure(struct chp_id chpid);
-extern int sclp_chp_deconfigure(struct chp_id chpid);
-extern int sclp_chp_read_info(struct sclp_chp_info *info);
+#define LOADPARM_LEN 8
+
+struct sclp_ipl_info {
+	int is_valid;
+	int has_dump;
+	char loadparm[LOADPARM_LEN];
+};
+
+void sclp_readinfo_early(void);
+void sclp_facilities_detect(void);
+unsigned long long sclp_memory_detect(void);
+int sclp_sdias_blk_count(void);
+int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
+int sclp_chp_configure(struct chp_id chpid);
+int sclp_chp_deconfigure(struct chp_id chpid);
+int sclp_chp_read_info(struct sclp_chp_info *info);
+void sclp_get_ipl_info(struct sclp_ipl_info *info);
 
 #endif /* _ASM_S390_SCLP_H */
diff --git a/include/asm-s390/sfp-machine.h b/include/asm-s390/sfp-machine.h
index 8ca8c77..4e16aed 100644
--- a/include/asm-s390/sfp-machine.h
+++ b/include/asm-s390/sfp-machine.h
@@ -27,9 +27,9 @@
    
 
 #define _FP_W_TYPE_SIZE		32
-#define _FP_W_TYPE		unsigned long
-#define _FP_WS_TYPE		signed long
-#define _FP_I_TYPE		long
+#define _FP_W_TYPE		unsigned int
+#define _FP_WS_TYPE		signed int
+#define _FP_I_TYPE		int
 
 #define _FP_MUL_MEAT_S(R,X,Y)					\
   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
diff --git a/include/asm-s390/sfp-util.h b/include/asm-s390/sfp-util.h
index 8cabcd2..0addc64 100644
--- a/include/asm-s390/sfp-util.h
+++ b/include/asm-s390/sfp-util.h
@@ -51,6 +51,16 @@
 	wl = __wl;					\
 })
 
+#ifdef __s390x__
+#define udiv_qrnnd(q, r, n1, n0, d)			\
+  do { unsigned long __n;				\
+       unsigned int __r, __d;				\
+    __n = ((unsigned long)(n1) << 32) + n0;		\
+    __d = (d);						\
+    (q) = __n / __d;					\
+    (r) = __n % __d;					\
+  } while (0)
+#else
 #define udiv_qrnnd(q, r, n1, n0, d)			\
   do { unsigned int __r;				\
     (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));		\
@@ -58,6 +68,7 @@
   } while (0)
 extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
 				   unsigned int , unsigned int);
+#endif
 
 #define UDIV_NEEDS_NORMALIZATION 0
 
diff --git a/include/asm-s390/termbits.h b/include/asm-s390/termbits.h
index 585c78a..811b9a9 100644
--- a/include/asm-s390/termbits.h
+++ b/include/asm-s390/termbits.h
@@ -25,6 +25,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index 5c6f00d..790c1c5 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -251,8 +251,12 @@
 #define __NR_getcpu		311
 #define __NR_epoll_pwait	312
 #define __NR_utimes		313
-
-#define NR_syscalls 314
+/* Number 314 is reserved for new sys_fallocate */
+#define __NR_utimensat		315
+#define __NR_signalfd		316
+#define __NR_timerfd		317
+#define __NR_eventfd		318
+#define NR_syscalls 319
 
 /* 
  * There are some system calls that are not present on 64 bit, some
@@ -346,6 +350,19 @@
 
 #ifdef __KERNEL__
 
+#ifndef CONFIG_64BIT
+#define __IGNORE_select
+#else
+#define __IGNORE_time
+#endif
+
+/* Ignore NUMA system calls. Not wired up on s390. */
+#define __IGNORE_mbind
+#define __IGNORE_get_mempolicy
+#define __IGNORE_set_mempolicy
+#define __IGNORE_migrate_pages
+#define __IGNORE_move_pages
+
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
index 5a117ec..aeee8da 100644
--- a/include/asm-sh/bugs.h
+++ b/include/asm-sh/bugs.h
@@ -22,7 +22,7 @@
 	current_cpu_data.loops_per_jiffy = loops_per_jiffy;
 
 	switch (current_cpu_data.type) {
-	case CPU_SH7604 ... CPU_SH7619:
+	case CPU_SH7619:
 		*p++ = '2';
 		break;
 	case CPU_SH7206:
@@ -35,7 +35,7 @@
 	case CPU_SH7750 ... CPU_SH4_501:
 		*p++ = '4';
 		break;
-	case CPU_SH7770 ... CPU_SH7785:
+	case CPU_SH7770 ... CPU_SHX3:
 		*p++ = '4';
 		*p++ = 'a';
 		break;
diff --git a/include/asm-sh/cache.h b/include/asm-sh/cache.h
index 9a3cb6b..7a18649 100644
--- a/include/asm-sh/cache.h
+++ b/include/asm-sh/cache.h
@@ -9,6 +9,7 @@
 #define __ASM_SH_CACHE_H
 #ifdef __KERNEL__
 
+#include <linux/init.h>
 #include <asm/cpu/cache.h>
 
 #define SH_CACHE_VALID		1
@@ -48,6 +49,9 @@
 
 	unsigned long flags;
 };
+
+int __init detect_cpu_and_cache_system(void);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHE_H */
diff --git a/include/asm-sh/cpu-sh2/cache.h b/include/asm-sh/cpu-sh2/cache.h
index 20b9796..f02ba7a 100644
--- a/include/asm-sh/cpu-sh2/cache.h
+++ b/include/asm-sh/cpu-sh2/cache.h
@@ -12,23 +12,7 @@
 
 #define L1_CACHE_SHIFT	4
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7604)
-#define CCR		0xfffffe92	/* Address of Cache Control Register */
-
-#define CCR_CACHE_CE	0x01	/* Cache enable */
-#define CCR_CACHE_ID	0x02	/* Instruction Replacement disable */
-#define CCR_CACHE_OD	0x04	/* Data Replacement disable */
-#define CCR_CACHE_TW	0x08	/* Two-way mode */
-#define CCR_CACHE_CP	0x10	/* Cache purge */
-
-#define CACHE_OC_ADDRESS_ARRAY	0x60000000
-
-#define CCR_CACHE_ENABLE	CCR_CACHE_CE
-#define CCR_CACHE_INVALIDATE	CCR_CACHE_CP
-#define CCR_CACHE_ORA		CCR_CACHE_TW
-#define CCR_CACHE_WT		0x00	/* SH-2 is _always_ write-through */
-
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+#if defined(CONFIG_CPU_SUBTYPE_SH7619)
 #define CCR1		0xffffffec
 #define CCR		CCR1
 
@@ -49,5 +33,5 @@
 #define CCR_CACHE_ENABLE	CCR_CACHE_CE
 #define CCR_CACHE_INVALIDATE	CCR_CACHE_CF
 #endif
-#endif /* __ASM_CPU_SH2_CACHE_H */
 
+#endif /* __ASM_CPU_SH2_CACHE_H */
diff --git a/include/asm-sh/cpu-sh3/timer.h b/include/asm-sh/cpu-sh3/timer.h
index b2394cf..4928b08 100644
--- a/include/asm-sh/cpu-sh3/timer.h
+++ b/include/asm-sh/cpu-sh3/timer.h
@@ -29,7 +29,7 @@
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
-#define TMU_TSTR	0xa412fe92	/* Byte access */
+#define TMU_012_TSTR	0xa412fe92	/* Byte access */
 
 #define TMU0_TCOR	0xa412fe94	/* Long access */
 #define TMU0_TCNT	0xa412fe98	/* Long access */
@@ -44,7 +44,7 @@
 #define TMU2_TCR	0xa412feb4	/* Word access */
 
 #else
-#define TMU_TSTR	0xfffffe92	/* Byte access */
+#define TMU_012_TSTR	0xfffffe92	/* Byte access */
 
 #define TMU0_TCOR	0xfffffe94	/* Long access */
 #define TMU0_TCNT	0xfffffe98	/* Long access */
diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
index 86564e7..026025b 100644
--- a/include/asm-sh/cpu-sh4/freq.h
+++ b/include/asm-sh/cpu-sh4/freq.h
@@ -22,8 +22,13 @@
 #define FRQCR0			0xffc80000
 #define FRQCR1			0xffc80004
 #define FRQMR1			0xffc80014
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+#define FRQCR			0xffc00014
 #else
 #define FRQCR			0xffc00000
+#define FRQCR_PSTBY		0x0200
+#define FRQCR_PLLEN		0x0400
+#define FRQCR_CKOEN		0x0800
 #endif
 #define MIN_DIVISOR_NR		0
 #define MAX_DIVISOR_NR		3
diff --git a/include/asm-sh/cpu-sh4/timer.h b/include/asm-sh/cpu-sh4/timer.h
index 8a4af126c..d1e796b 100644
--- a/include/asm-sh/cpu-sh4/timer.h
+++ b/include/asm-sh/cpu-sh4/timer.h
@@ -1,7 +1,7 @@
 /*
  * include/asm-sh/cpu-sh4/timer.h
  *
- * Copyright (C) 2004 Lineo Solutions, Inc. 
+ * Copyright (C) 2004 Lineo Solutions, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -16,36 +16,45 @@
  *	SH7750S/SH7750R
  *	SH7751/SH7751R
  *	SH7760
+ *	SH-X3
  * ---------------------------------------------------------------------------
  */
-
-#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define TMU_TOCR        0xffd80000      /* Byte access */
+#ifdef CONFIG_CPU_SUBTYPE_SHX3
+#define TMU_012_BASE	0xffc10000
+#define TMU_345_BASE	0xffc20000
+#else
+#define TMU_012_BASE	0xffd80000
+#define TMU_345_BASE	0xfe100000
 #endif
-#define TMU_TSTR        0xffd80004      /* Byte access */
 
-#define TMU0_TCOR       0xffd80008      /* Long access */
-#define TMU0_TCNT       0xffd8000c      /* Long access */
-#define TMU0_TCR        0xffd80010      /* Word access */
+#define TMU_TOCR	TMU_012_BASE	/* Not supported on all CPUs */
 
-#define TMU1_TCOR       0xffd80014      /* Long access */
-#define TMU1_TCNT       0xffd80018      /* Long access */
-#define TMU1_TCR        0xffd8001c      /* Word access */
+#define TMU_012_TSTR	(TMU_012_BASE + 0x04)
+#define TMU_345_TSTR	(TMU_345_BASE + 0x04)
 
-#define TMU2_TCOR       0xffd80020      /* Long access */
-#define TMU2_TCNT       0xffd80024      /* Long access */
-#define TMU2_TCR        0xffd80028      /* Word access */
-#define TMU2_TCPR	0xffd8002c	/* Long access */
+#define TMU0_TCOR	(TMU_012_BASE + 0x08)
+#define TMU0_TCNT	(TMU_012_BASE + 0x0c)
+#define TMU0_TCR	(TMU_012_BASE + 0x10)
 
-#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define TMU3_TCOR       0xfe100008      /* Long access */
-#define TMU3_TCNT       0xfe10000c      /* Long access */
-#define TMU3_TCR        0xfe100010      /* Word access */
+#define TMU1_TCOR       (TMU_012_BASE + 0x14)
+#define TMU1_TCNT       (TMU_012_BASE + 0x18)
+#define TMU1_TCR        (TMU_012_BASE + 0x1c)
 
-#define TMU4_TCOR       0xfe100014      /* Long access */
-#define TMU4_TCNT       0xfe100018      /* Long access */
-#define TMU4_TCR        0xfe10001c      /* Word access */
-#endif
+#define TMU2_TCOR       (TMU_012_BASE + 0x20)
+#define TMU2_TCNT       (TMU_012_BASE + 0x24)
+#define TMU2_TCR	(TMU_012_BASE + 0x28)
+#define TMU2_TCPR	(TMU_012_BASE + 0x2c)
+
+#define TMU3_TCOR	(TMU_345_BASE + 0x08)
+#define TMU3_TCNT	(TMU_345_BASE + 0x0c)
+#define TMU3_TCR	(TMU_345_BASE + 0x10)
+
+#define TMU4_TCOR	(TMU_345_BASE + 0x14)
+#define TMU4_TCNT	(TMU_345_BASE + 0x18)
+#define TMU4_TCR	(TMU_345_BASE + 0x1c)
+
+#define TMU5_TCOR	(TMU_345_BASE + 0x20)
+#define TMU5_TCNT	(TMU_345_BASE + 0x24)
+#define TMU5_TCR	(TMU_345_BASE + 0x28)
 
 #endif /* __ASM_CPU_SH4_TIMER_H */
-
diff --git a/include/asm-sh/dma.h b/include/asm-sh/dma.h
index faf3051..6034d4a 100644
--- a/include/asm-sh/dma.h
+++ b/include/asm-sh/dma.h
@@ -13,6 +13,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/wait.h>
+#include <linux/sched.h>
 #include <linux/sysdev.h>
 #include <asm/cpu/dma.h>
 
diff --git a/include/asm-sh/dreamcast/sysasic.h b/include/asm-sh/dreamcast/sysasic.h
index 7874e3d..f334266 100644
--- a/include/asm-sh/dreamcast/sysasic.h
+++ b/include/asm-sh/dreamcast/sysasic.h
@@ -23,7 +23,7 @@
    takes.
 */
 
-#define HW_EVENT_IRQ_BASE  OFFCHIP_IRQ_BASE /* 48 */
+#define HW_EVENT_IRQ_BASE  48
 
 /* IRQ 13 */
 #define HW_EVENT_VSYNC     (HW_EVENT_IRQ_BASE +  5) /* VSync */
diff --git a/include/asm-sh/fb.h b/include/asm-sh/fb.h
new file mode 100644
index 0000000..d92e99c
--- /dev/null
+++ b/include/asm-sh/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sh/futex-irq.h b/include/asm-sh/futex-irq.h
new file mode 100644
index 0000000..a9f16a7
--- /dev/null
+++ b/include/asm-sh/futex-irq.h
@@ -0,0 +1,111 @@
+#ifndef __ASM_SH_FUTEX_IRQ_H
+#define __ASM_SH_FUTEX_IRQ_H
+
+#include <asm/system.h>
+
+static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
+					   int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
+					   int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(*oldval + oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
+					  int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(*oldval | oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
+					   int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(*oldval & oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
+					   int *oldval)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+
+	ret = get_user(*oldval, uaddr);
+	if (!ret)
+		ret = put_user(*oldval ^ oparg, uaddr);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
+						   int oldval, int newval)
+{
+	unsigned long flags;
+	int ret, prev = 0;
+
+	local_irq_save(flags);
+
+	ret = get_user(prev, uaddr);
+	if (!ret && oldval == prev)
+		ret = put_user(newval, uaddr);
+
+	local_irq_restore(flags);
+
+	if (ret)
+		return ret;
+
+	return prev;
+}
+
+#endif /* __ASM_SH_FUTEX_IRQ_H */
diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h
index 6a332a9..74ed368 100644
--- a/include/asm-sh/futex.h
+++ b/include/asm-sh/futex.h
@@ -1,6 +1,77 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef __ASM_SH_FUTEX_H
+#define __ASM_SH_FUTEX_H
 
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
 
-#endif
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+/* XXX: UP variants, fix for SH-4A and SMP.. */
+#include <asm/futex-irq.h>
+
+static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, ret;
+
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	pagefault_disable();
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval);
+		break;
+	case FUTEX_OP_ADD:
+		ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval);
+		break;
+	case FUTEX_OP_OR:
+		ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval);
+		break;
+	case FUTEX_OP_ANDN:
+		ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval);
+		break;
+	case FUTEX_OP_XOR:
+		ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+
+	pagefault_enable();
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+		default: ret = -ENOSYS;
+		}
+	}
+
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_FUTEX_H */
diff --git a/include/asm-sh/hd64461.h b/include/asm-sh/hd64461.h
index 27e5c34..4dd8592 100644
--- a/include/asm-sh/hd64461.h
+++ b/include/asm-sh/hd64461.h
@@ -1,200 +1,241 @@
 #ifndef __ASM_SH_HD64461
 #define __ASM_SH_HD64461
 /*
- *	$Id: hd64461.h,v 1.5 2004/03/16 00:07:51 lethal Exp $
+ *	Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
+ *	Copyright (C) 2004 Paul Mundt
  *	Copyright (C) 2000 YAEGASHI Takeshi
- *	Hitachi HD64461 companion chip support
+ *
+ *		Hitachi HD64461 companion chip support
+ *	(please note manual reference 0x10000000 = 0xb0000000)
  */
 
 /* Constants for PCMCIA mappings */
-#define HD64461_PCC_WINDOW	0x01000000
+#define	HD64461_PCC_WINDOW	0x01000000
 
-#define HD64461_PCC0_BASE	0xb8000000	/* area 6 */
-#define HD64461_PCC0_ATTR	(HD64461_PCC0_BASE)
-#define HD64461_PCC0_COMM	(HD64461_PCC0_BASE+HD64461_PCC_WINDOW)
-#define HD64461_PCC0_IO		(HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW)
+/* Area 6 - Slot 0 - memory and/or IO card */
+#define	HD64461_PCC0_BASE	(CONFIG_HD64461_IOBASE + 0x8000000)
+#define	HD64461_PCC0_ATTR	(HD64461_PCC0_BASE)				/* 0xb80000000 */
+#define	HD64461_PCC0_COMM	(HD64461_PCC0_BASE+HD64461_PCC_WINDOW)		/* 0xb90000000 */
+#define	HD64461_PCC0_IO		(HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW)	/* 0xba0000000 */
 
-#define HD64461_PCC1_BASE	0xb4000000	/* area 5 */
-#define HD64461_PCC1_ATTR	(HD64461_PCC1_BASE)
-#define HD64461_PCC1_COMM	(HD64461_PCC1_BASE+HD64461_PCC_WINDOW)
+/* Area 5 - Slot 1 - memory card only */
+#define	HD64461_PCC1_BASE	(CONFIG_HD64461_IOBASE + 0x4000000)
+#define	HD64461_PCC1_ATTR	(HD64461_PCC1_BASE)				/* 0xb4000000 */
+#define	HD64461_PCC1_COMM	(HD64461_PCC1_BASE+HD64461_PCC_WINDOW)		/* 0xb5000000 */
 
-#define HD64461_STBCR	0x10000
-#define HD64461_STBCR_CKIO_STBY			0x2000
-#define HD64461_STBCR_SAFECKE_IST		0x1000
-#define HD64461_STBCR_SLCKE_IST			0x0800
-#define HD64461_STBCR_SAFECKE_OST		0x0400
-#define HD64461_STBCR_SLCKE_OST			0x0200
-#define HD64461_STBCR_SMIAST			0x0100
-#define HD64461_STBCR_SLCDST			0x0080
-#define HD64461_STBCR_SPC0ST			0x0040
-#define HD64461_STBCR_SPC1ST			0x0020
-#define HD64461_STBCR_SAFEST			0x0010
-#define HD64461_STBCR_STM0ST			0x0008
-#define HD64461_STBCR_STM1ST			0x0004
-#define HD64461_STBCR_SIRST				0x0002
-#define HD64461_STBCR_SURTST			0x0001
+/* Standby Control Register for HD64461 */
+#define	HD64461_STBCR			CONFIG_HD64461_IOBASE
+#define	HD64461_STBCR_CKIO_STBY		0x2000
+#define	HD64461_STBCR_SAFECKE_IST	0x1000
+#define	HD64461_STBCR_SLCKE_IST		0x0800
+#define	HD64461_STBCR_SAFECKE_OST	0x0400
+#define	HD64461_STBCR_SLCKE_OST		0x0200
+#define	HD64461_STBCR_SMIAST		0x0100
+#define	HD64461_STBCR_SLCDST		0x0080
+#define	HD64461_STBCR_SPC0ST		0x0040
+#define	HD64461_STBCR_SPC1ST		0x0020
+#define	HD64461_STBCR_SAFEST		0x0010
+#define	HD64461_STBCR_STM0ST		0x0008
+#define	HD64461_STBCR_STM1ST		0x0004
+#define	HD64461_STBCR_SIRST		0x0002
+#define	HD64461_STBCR_SURTST		0x0001
 
-#define HD64461_SYSCR	0x10002
-#define HD64461_SCPUCR	0x10004
+/* System Configuration Register */
+#define	HD64461_SYSCR		(CONFIG_HD64461_IOBASE + 0x02)
 
-#define HD64461_LCDCBAR		0x11000
-#define HD64461_LCDCLOR		0x11002
-#define HD64461_LCDCCR		0x11004
-#define HD64461_LCDCCR_STBACK	0x0400
-#define HD64461_LCDCCR_STREQ	0x0100
-#define HD64461_LCDCCR_MOFF	0x0080
-#define HD64461_LCDCCR_REFSEL	0x0040
-#define HD64461_LCDCCR_EPON	0x0020
-#define HD64461_LCDCCR_SPON	0x0010
+/* CPU Data Bus Control Register */
+#define	HD64461_SCPUCR		(CONFIG_HD64461_IOBASE + 0x04)
 
-#define	HD64461_LDR1		0x11010
-#define	HD64461_LDR1_DON	0x01
-#define	HD64461_LDR1_DINV	0x80
+/* Base Adress Register */
+#define	HD64461_LCDCBAR		(CONFIG_HD64461_IOBASE + 0x1000)
 
-#define	HD64461_LDR2		0x11012
-#define	HD64461_LDHNCR		0x11014
-#define	HD64461_LDHNSR		0x11016
-#define HD64461_LDVNTR		0x11018
-#define HD64461_LDVNDR		0x1101a
-#define HD64461_LDVSPR		0x1101c
-#define HD64461_LDR3		0x1101e
+/* Line increment adress */
+#define	HD64461_LCDCLOR		(CONFIG_HD64461_IOBASE + 0x1002)
 
-#define HD64461_CPTWAR		0x11030
-#define HD64461_CPTWDR		0x11032
-#define HD64461_CPTRAR		0x11034
-#define HD64461_CPTRDR		0x11036
+/* Controls LCD controller */
+#define	HD64461_LCDCCR		(CONFIG_HD64461_IOBASE + 0x1004)
 
-#define HD64461_GRDOR		0x11040
-#define HD64461_GRSCR		0x11042
-#define HD64461_GRCFGR		0x11044
-#define HD64461_GRCFGR_ACCSTATUS		0x10
-#define HD64461_GRCFGR_ACCRESET			0x08
-#define HD64461_GRCFGR_ACCSTART_BITBLT	0x06
-#define HD64461_GRCFGR_ACCSTART_LINE	0x04
-#define HD64461_GRCFGR_COLORDEPTH16		0x01
+/* LCCDR control bits */
+#define	HD64461_LCDCCR_STBACK	0x0400	/* Standby Back */
+#define	HD64461_LCDCCR_STREQ	0x0100	/* Standby Request */
+#define	HD64461_LCDCCR_MOFF	0x0080	/* Memory Off */
+#define	HD64461_LCDCCR_REFSEL	0x0040	/* Refresh Select */
+#define	HD64461_LCDCCR_EPON	0x0020	/* End Power On */
+#define	HD64461_LCDCCR_SPON	0x0010	/* Start Power On */
 
-#define HD64461_LNSARH		0x11046
-#define HD64461_LNSARL		0x11048
-#define HD64461_LNAXLR		0x1104a
-#define HD64461_LNDGR		0x1104c
-#define HD64461_LNAXR		0x1104e
-#define HD64461_LNERTR		0x11050
-#define HD64461_LNMDR		0x11052
-#define HD64461_BBTSSARH	0x11054
-#define HD64461_BBTSSARL	0x11056
-#define HD64461_BBTDSARH	0x11058
-#define HD64461_BBTDSARL	0x1105a
-#define HD64461_BBTDWR		0x1105c
-#define HD64461_BBTDHR		0x1105e
-#define HD64461_BBTPARH		0x11060
-#define HD64461_BBTPARL		0x11062
-#define HD64461_BBTMARH		0x11064
-#define HD64461_BBTMARL		0x11066
-#define HD64461_BBTROPR		0x11068
-#define HD64461_BBTMDR		0x1106a
+/* Controls LCD (1) */
+#define	HD64461_LDR1		(CONFIG_HD64461_IOBASE + 0x1010)
+#define	HD64461_LDR1_DON	0x01	/* Display On */
+#define	HD64461_LDR1_DINV	0x80	/* Display Invert */
+
+/* Controls LCD (2) */
+#define	HD64461_LDR2		(CONFIG_HD64461_IOBASE + 0x1012)
+#define	HD64461_LDHNCR		(CONFIG_HD64461_IOBASE + 0x1014)	/* Number of horizontal characters */
+#define	HD64461_LDHNSR		(CONFIG_HD64461_IOBASE + 0x1016)	/* Specify output start position + width of CL1 */
+#define	HD64461_LDVNTR		(CONFIG_HD64461_IOBASE + 0x1018)	/* Specify total vertical lines */
+#define	HD64461_LDVNDR		(CONFIG_HD64461_IOBASE + 0x101a)	/* specify number of display vertical lines */
+#define	HD64461_LDVSPR		(CONFIG_HD64461_IOBASE + 0x101c)	/* specify vertical synchronization pos and AC nr */
+
+/* Controls LCD (3) */
+#define	HD64461_LDR3		(CONFIG_HD64461_IOBASE + 0x101e)
+
+/* Palette Registers */
+#define	HD64461_CPTWAR		(CONFIG_HD64461_IOBASE + 0x1030)	/* Color Palette Write Adress Register */
+#define	HD64461_CPTWDR		(CONFIG_HD64461_IOBASE + 0x1032)	/* Color Palette Write Data Register */
+#define	HD64461_CPTRAR		(CONFIG_HD64461_IOBASE + 0x1034)	/* Color Palette Read Adress Register */
+#define	HD64461_CPTRDR		(CONFIG_HD64461_IOBASE + 0x1036)	/* Color Palette Read Data Register */
+
+#define	HD64461_GRDOR		(CONFIG_HD64461_IOBASE + 0x1040)	/* Display Resolution Offset Register */
+#define	HD64461_GRSCR		(CONFIG_HD64461_IOBASE + 0x1042)	/* Solid Color Register */
+#define	HD64461_GRCFGR		(CONFIG_HD64461_IOBASE + 0x1044)	/* Accelerator Configuration Register */
+
+#define	HD64461_GRCFGR_ACCSTATUS	0x10	/* Accelerator Status */
+#define	HD64461_GRCFGR_ACCRESET		0x08	/* Accelerator Reset */
+#define	HD64461_GRCFGR_ACCSTART_BITBLT	0x06	/* Accelerator Start BITBLT */
+#define	HD64461_GRCFGR_ACCSTART_LINE	0x04	/* Accelerator Start Line Drawing */
+#define	HD64461_GRCFGR_COLORDEPTH16	0x01	/* Sets Colordepth 16 for Accelerator */
+#define	HD64461_GRCFGR_COLORDEPTH8	0x01	/* Sets Colordepth 8 for Accelerator */
+
+/* Line Drawing Registers */
+#define	HD64461_LNSARH		(CONFIG_HD64461_IOBASE + 0x1046)	/* Line Start Adress Register (H) */
+#define	HD64461_LNSARL		(CONFIG_HD64461_IOBASE + 0x1048)	/* Line Start Adress Register (L) */
+#define	HD64461_LNAXLR		(CONFIG_HD64461_IOBASE + 0x104a)	/* Axis Pixel Length Register */
+#define	HD64461_LNDGR		(CONFIG_HD64461_IOBASE + 0x104c)	/* Diagonal Register */
+#define	HD64461_LNAXR		(CONFIG_HD64461_IOBASE + 0x104e)	/* Axial Register */
+#define	HD64461_LNERTR		(CONFIG_HD64461_IOBASE + 0x1050)	/* Start Error Term Register */
+#define	HD64461_LNMDR		(CONFIG_HD64461_IOBASE + 0x1052)	/* Line Mode Register */
+
+/* BitBLT Registers */
+#define	HD64461_BBTSSARH	(CONFIG_HD64461_IOBASE + 0x1054)	/* Source Start Adress Register (H) */
+#define	HD64461_BBTSSARL	(CONFIG_HD64461_IOBASE + 0x1056)	/* Source Start Adress Register (L) */
+#define	HD64461_BBTDSARH	(CONFIG_HD64461_IOBASE + 0x1058)	/* Destination Start Adress Register (H) */
+#define	HD64461_BBTDSARL	(CONFIG_HD64461_IOBASE + 0x105a)	/* Destination Start Adress Register (L) */
+#define	HD64461_BBTDWR		(CONFIG_HD64461_IOBASE + 0x105c)	/* Destination Block Width Register */
+#define	HD64461_BBTDHR		(CONFIG_HD64461_IOBASE + 0x105e)	/* Destination Block Height Register */
+#define	HD64461_BBTPARH		(CONFIG_HD64461_IOBASE + 0x1060)	/* Pattern Start Adress Register (H) */
+#define	HD64461_BBTPARL		(CONFIG_HD64461_IOBASE + 0x1062)	/* Pattern Start Adress Register (L) */
+#define	HD64461_BBTMARH		(CONFIG_HD64461_IOBASE + 0x1064)	/* Mask Start Adress Register (H) */
+#define	HD64461_BBTMARL		(CONFIG_HD64461_IOBASE + 0x1066)	/* Mask Start Adress Register (L) */
+#define	HD64461_BBTROPR		(CONFIG_HD64461_IOBASE + 0x1068)	/* ROP Register */
+#define	HD64461_BBTMDR		(CONFIG_HD64461_IOBASE + 0x106a)	/* BitBLT Mode Register */
 
 /* PC Card Controller Registers */
-#define HD64461_PCC0ISR         0x12000 /* socket 0 interface status */
-#define HD64461_PCC0GCR         0x12002 /* socket 0 general control */
-#define HD64461_PCC0CSCR        0x12004 /* socket 0 card status change */
-#define HD64461_PCC0CSCIER      0x12006 /* socket 0 card status change interrupt enable */
-#define HD64461_PCC0SCR         0x12008 /* socket 0 software control */
-#define HD64461_PCC1ISR         0x12010 /* socket 1 interface status */
-#define HD64461_PCC1GCR         0x12012 /* socket 1 general control */
-#define HD64461_PCC1CSCR        0x12014 /* socket 1 card status change */
-#define HD64461_PCC1CSCIER      0x12016 /* socket 1 card status change interrupt enable */
-#define HD64461_PCC1SCR         0x12018 /* socket 1 software control */
+/* Maps to Physical Area 6 */
+#define	HD64461_PCC0ISR		(CONFIG_HD64461_IOBASE + 0x2000)	/* socket 0 interface status */
+#define	HD64461_PCC0GCR		(CONFIG_HD64461_IOBASE + 0x2002)	/* socket 0 general control */
+#define	HD64461_PCC0CSCR	(CONFIG_HD64461_IOBASE + 0x2004)	/* socket 0 card status change */
+#define	HD64461_PCC0CSCIER	(CONFIG_HD64461_IOBASE + 0x2006)	/* socket 0 card status change interrupt enable */
+#define	HD64461_PCC0SCR		(CONFIG_HD64461_IOBASE + 0x2008)	/* socket 0 software control */
+/* Maps to Physical Area 5 */
+#define	HD64461_PCC1ISR		(CONFIG_HD64461_IOBASE + 0x2010)	/* socket 1 interface status */
+#define	HD64461_PCC1GCR		(CONFIG_HD64461_IOBASE + 0x2012)	/* socket 1 general control */
+#define	HD64461_PCC1CSCR	(CONFIG_HD64461_IOBASE + 0x2014)	/* socket 1 card status change */
+#define	HD64461_PCC1CSCIER	(CONFIG_HD64461_IOBASE + 0x2016)	/* socket 1 card status change interrupt enable */
+#define	HD64461_PCC1SCR		(CONFIG_HD64461_IOBASE + 0x2018)	/* socket 1 software control */
 
 /* PCC Interface Status Register */
-#define HD64461_PCCISR_READY		0x80	/* card ready */
-#define HD64461_PCCISR_MWP		0x40	/* card write-protected */
-#define HD64461_PCCISR_VS2		0x20	/* voltage select pin 2 */
-#define HD64461_PCCISR_VS1		0x10	/* voltage select pin 1 */
-#define HD64461_PCCISR_CD2		0x08	/* card detect 2 */
-#define HD64461_PCCISR_CD1		0x04	/* card detect 1 */
-#define HD64461_PCCISR_BVD2		0x02	/* battery 1 */
-#define HD64461_PCCISR_BVD1		0x01	/* battery 1 */
+#define	HD64461_PCCISR_READY		0x80	/* card ready */
+#define	HD64461_PCCISR_MWP		0x40	/* card write-protected */
+#define	HD64461_PCCISR_VS2		0x20	/* voltage select pin 2 */
+#define	HD64461_PCCISR_VS1		0x10	/* voltage select pin 1 */
+#define	HD64461_PCCISR_CD2		0x08	/* card detect 2 */
+#define	HD64461_PCCISR_CD1		0x04	/* card detect 1 */
+#define	HD64461_PCCISR_BVD2		0x02	/* battery 1 */
+#define	HD64461_PCCISR_BVD1		0x01	/* battery 1 */
 
-#define HD64461_PCCISR_PCD_MASK		0x0c    /* card detect */
-#define HD64461_PCCISR_BVD_MASK		0x03    /* battery voltage */
-#define HD64461_PCCISR_BVD_BATGOOD	0x03    /* battery good */
-#define HD64461_PCCISR_BVD_BATWARN	0x01    /* battery low warning */
-#define HD64461_PCCISR_BVD_BATDEAD1	0x02    /* battery dead */
-#define HD64461_PCCISR_BVD_BATDEAD2	0x00    /* battery dead */
+#define	HD64461_PCCISR_PCD_MASK		0x0c	/* card detect */
+#define	HD64461_PCCISR_BVD_MASK		0x03	/* battery voltage */
+#define	HD64461_PCCISR_BVD_BATGOOD	0x03	/* battery good */
+#define	HD64461_PCCISR_BVD_BATWARN	0x01	/* battery low warning */
+#define	HD64461_PCCISR_BVD_BATDEAD1	0x02	/* battery dead */
+#define	HD64461_PCCISR_BVD_BATDEAD2	0x00	/* battery dead */
 
 /* PCC General Control Register */
-#define HD64461_PCCGCR_DRVE		0x80    /* output drive */
-#define HD64461_PCCGCR_PCCR		0x40    /* PC card reset */
-#define HD64461_PCCGCR_PCCT		0x20    /* PC card type, 1=IO&mem, 0=mem */
-#define HD64461_PCCGCR_VCC0		0x10    /* voltage control pin VCC0SEL0 */
-#define HD64461_PCCGCR_PMMOD		0x08    /* memory mode */
-#define HD64461_PCCGCR_PA25		0x04    /* pin A25 */
-#define HD64461_PCCGCR_PA24		0x02    /* pin A24 */
-#define HD64461_PCCGCR_REG		0x01    /* pin PCC0REG# */
+#define	HD64461_PCCGCR_DRVE		0x80	/* output drive */
+#define	HD64461_PCCGCR_PCCR		0x40	/* PC card reset */
+#define	HD64461_PCCGCR_PCCT		0x20	/* PC card type, 1=IO&mem, 0=mem */
+#define	HD64461_PCCGCR_VCC0		0x10	/* voltage control pin VCC0SEL0 */
+#define	HD64461_PCCGCR_PMMOD		0x08	/* memory mode */
+#define	HD64461_PCCGCR_PA25		0x04	/* pin A25 */
+#define	HD64461_PCCGCR_PA24		0x02	/* pin A24 */
+#define	HD64461_PCCGCR_REG		0x01	/* pin PCC0REG# */
 
 /* PCC Card Status Change Register */
-#define HD64461_PCCCSCR_SCDI		0x80    /* sw card detect intr */
-#define HD64461_PCCCSCR_SRV1		0x40    /* reserved */
-#define HD64461_PCCCSCR_IREQ		0x20    /* IREQ intr req */
-#define HD64461_PCCCSCR_SC		0x10    /* STSCHG (status change) pin */
-#define HD64461_PCCCSCR_CDC		0x08    /* CD (card detect) change */
-#define HD64461_PCCCSCR_RC		0x04    /* READY change */
-#define HD64461_PCCCSCR_BW		0x02    /* battery warning change */
-#define HD64461_PCCCSCR_BD		0x01    /* battery dead change */
+#define	HD64461_PCCCSCR_SCDI		0x80	/* sw card detect intr */
+#define	HD64461_PCCCSCR_SRV1		0x40	/* reserved */
+#define	HD64461_PCCCSCR_IREQ		0x20	/* IREQ intr req */
+#define	HD64461_PCCCSCR_SC		0x10	/* STSCHG (status change) pin */
+#define	HD64461_PCCCSCR_CDC		0x08	/* CD (card detect) change */
+#define	HD64461_PCCCSCR_RC		0x04	/* READY change */
+#define	HD64461_PCCCSCR_BW		0x02	/* battery warning change */
+#define	HD64461_PCCCSCR_BD		0x01	/* battery dead change */
 
 /* PCC Card Status Change Interrupt Enable Register */
-#define HD64461_PCCCSCIER_CRE		0x80    /* change reset enable */
-#define HD64461_PCCCSCIER_IREQE_MASK	0x60   /* IREQ enable */
-#define HD64461_PCCCSCIER_IREQE_DISABLED	0x00   /* IREQ disabled */
-#define HD64461_PCCCSCIER_IREQE_LEVEL	0x20   /* IREQ level-triggered */
-#define HD64461_PCCCSCIER_IREQE_FALLING	0x40   /* IREQ falling-edge-trig */
-#define HD64461_PCCCSCIER_IREQE_RISING	0x60   /* IREQ rising-edge-trig */
+#define	HD64461_PCCCSCIER_CRE		0x80	/* change reset enable */
+#define	HD64461_PCCCSCIER_IREQE_MASK	0x60	/* IREQ enable */
+#define	HD64461_PCCCSCIER_IREQE_DISABLED 0x00	/* IREQ disabled */
+#define	HD64461_PCCCSCIER_IREQE_LEVEL	0x20	/* IREQ level-triggered */
+#define	HD64461_PCCCSCIER_IREQE_FALLING	0x40	/* IREQ falling-edge-trig */
+#define	HD64461_PCCCSCIER_IREQE_RISING	0x60	/* IREQ rising-edge-trig */
 
-#define HD64461_PCCCSCIER_SCE		0x10    /* status change enable */
-#define HD64461_PCCCSCIER_CDE		0x08    /* card detect change enable */
-#define HD64461_PCCCSCIER_RE		0x04    /* ready change enable */
-#define HD64461_PCCCSCIER_BWE		0x02    /* battery warn change enable */
-#define HD64461_PCCCSCIER_BDE		0x01    /* battery dead change enable*/
+#define	HD64461_PCCCSCIER_SCE		0x10	/* status change enable */
+#define	HD64461_PCCCSCIER_CDE		0x08	/* card detect change enable */
+#define	HD64461_PCCCSCIER_RE		0x04	/* ready change enable */
+#define	HD64461_PCCCSCIER_BWE		0x02	/* battery warn change enable */
+#define	HD64461_PCCCSCIER_BDE		0x01	/* battery dead change enable*/
 
 /* PCC Software Control Register */
-#define HD64461_PCCSCR_VCC1		0x02	/* voltage control pin 1 */
-#define HD64461_PCCSCR_SWP		0x01    /* write protect */
+#define	HD64461_PCCSCR_VCC1		0x02	/* voltage control pin 1 */
+#define	HD64461_PCCSCR_SWP		0x01	/* write protect */
 
-#define HD64461_P0OCR           0x1202a
-#define HD64461_P1OCR           0x1202c
-#define HD64461_PGCR            0x1202e
+/* PCC0 Output Pins Control Register */
+#define	HD64461_P0OCR		(CONFIG_HD64461_IOBASE + 0x202a)
 
-#define HD64461_GPACR		0x14000
-#define HD64461_GPBCR		0x14002
-#define HD64461_GPCCR		0x14004
-#define HD64461_GPDCR		0x14006
-#define HD64461_GPADR		0x14010
-#define HD64461_GPBDR		0x14012
-#define HD64461_GPCDR		0x14014
-#define HD64461_GPDDR		0x14016
-#define HD64461_GPAICR		0x14020
-#define HD64461_GPBICR		0x14022
-#define HD64461_GPCICR		0x14024
-#define HD64461_GPDICR		0x14026
-#define HD64461_GPAISR		0x14040
-#define HD64461_GPBISR		0x14042
-#define HD64461_GPCISR		0x14044
-#define HD64461_GPDISR		0x14046
+/* PCC1 Output Pins Control Register */
+#define	HD64461_P1OCR		(CONFIG_HD64461_IOBASE + 0x202c)
 
-#define HD64461_NIRR		0x15000
-#define HD64461_NIMR		0x15002
+/* PC Card General Control Register */
+#define	HD64461_PGCR		(CONFIG_HD64461_IOBASE + 0x202e)
 
-#define HD64461_IRQBASE		OFFCHIP_IRQ_BASE
-#define HD64461_IRQ_NUM		16
+/* Port Control Registers */
+#define	HD64461_GPACR		(CONFIG_HD64461_IOBASE + 0x4000)	/* Port A - Handles IRDA/TIMER */
+#define	HD64461_GPBCR		(CONFIG_HD64461_IOBASE + 0x4002)	/* Port B - Handles UART */
+#define	HD64461_GPCCR		(CONFIG_HD64461_IOBASE + 0x4004)	/* Port C - Handles PCMCIA 1 */
+#define	HD64461_GPDCR		(CONFIG_HD64461_IOBASE + 0x4006)	/* Port D - Handles PCMCIA 1 */
 
-#define HD64461_IRQ_UART	(HD64461_IRQBASE+5)
-#define HD64461_IRQ_IRDA	(HD64461_IRQBASE+6)
-#define HD64461_IRQ_TMU1	(HD64461_IRQBASE+9)
-#define HD64461_IRQ_TMU0	(HD64461_IRQBASE+10)
-#define HD64461_IRQ_GPIO	(HD64461_IRQBASE+11)
-#define HD64461_IRQ_AFE		(HD64461_IRQBASE+12)
-#define HD64461_IRQ_PCC1	(HD64461_IRQBASE+13)
-#define HD64461_IRQ_PCC0	(HD64461_IRQBASE+14)
+/* Port Control Data Registers */
+#define	HD64461_GPADR		(CONFIG_HD64461_IOBASE + 0x4010)	/* A */
+#define	HD64461_GPBDR		(CONFIG_HD64461_IOBASE + 0x4012)	/* B */
+#define	HD64461_GPCDR		(CONFIG_HD64461_IOBASE + 0x4014)	/* C */
+#define	HD64461_GPDDR		(CONFIG_HD64461_IOBASE + 0x4016)	/* D */
+
+/* Interrupt Control Registers */
+#define	HD64461_GPAICR		(CONFIG_HD64461_IOBASE + 0x4020)	/* A */
+#define	HD64461_GPBICR		(CONFIG_HD64461_IOBASE + 0x4022)	/* B */
+#define	HD64461_GPCICR		(CONFIG_HD64461_IOBASE + 0x4024)	/* C */
+#define	HD64461_GPDICR		(CONFIG_HD64461_IOBASE + 0x4026)	/* D */
+
+/* Interrupt Status Registers */
+#define	HD64461_GPAISR		(CONFIG_HD64461_IOBASE + 0x4040)	/* A */
+#define	HD64461_GPBISR		(CONFIG_HD64461_IOBASE + 0x4042)	/* B */
+#define	HD64461_GPCISR		(CONFIG_HD64461_IOBASE + 0x4044)	/* C */
+#define	HD64461_GPDISR		(CONFIG_HD64461_IOBASE + 0x4046)	/* D */
+
+/* Interrupt Request Register & Interrupt Mask Register */
+#define	HD64461_NIRR		(CONFIG_HD64461_IOBASE + 0x5000)
+#define	HD64461_NIMR		(CONFIG_HD64461_IOBASE + 0x5002)
+
+#define	HD64461_IRQBASE		OFFCHIP_IRQ_BASE
+#define	HD64461_IRQ_NUM		16
+
+#define	HD64461_IRQ_UART	(HD64461_IRQBASE+5)
+#define	HD64461_IRQ_IRDA	(HD64461_IRQBASE+6)
+#define	HD64461_IRQ_TMU1	(HD64461_IRQBASE+9)
+#define	HD64461_IRQ_TMU0	(HD64461_IRQBASE+10)
+#define	HD64461_IRQ_GPIO	(HD64461_IRQBASE+11)
+#define	HD64461_IRQ_AFE		(HD64461_IRQBASE+12)
+#define	HD64461_IRQ_PCC1	(HD64461_IRQBASE+13)
+#define	HD64461_IRQ_PCC0	(HD64461_IRQBASE+14)
 
 #define __IO_PREFIX	hd64461
 #include <asm/io_generic.h>
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index 80ee1cd..4ca3f76 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -5,4 +5,46 @@
 
 extern atomic_t irq_err_count;
 
+struct intc2_data {
+	unsigned short irq;
+	unsigned char ipr_offset, ipr_shift;
+	unsigned char msk_offset, msk_shift;
+	unsigned char priority;
+};
+
+struct intc2_desc {
+	unsigned long prio_base;
+	unsigned long msk_base;
+	unsigned long mskclr_base;
+	struct intc2_data *intc2_data;
+	unsigned int nr_irqs;
+	struct irq_chip chip;
+};
+
+void register_intc2_controller(struct intc2_desc *);
+void init_IRQ_intc2(void);
+
+struct ipr_data {
+	unsigned char irq;
+	unsigned char ipr_idx;		/* Index for the IPR registered */
+	unsigned char shift;		/* Number of bits to shift the data */
+	unsigned char priority;		/* The priority */
+};
+
+struct ipr_desc {
+	unsigned long *ipr_offsets;
+	unsigned int nr_offsets;
+	struct ipr_data *ipr_data;
+	unsigned int nr_irqs;
+	struct irq_chip chip;
+};
+
+void register_ipr_controller(struct ipr_desc *);
+void init_IRQ_ipr(void);
+
+/*
+ * Enable individual interrupt mode for external IPR IRQs.
+ */
+void ipr_irq_enable_irlm(void);
+
 #endif /* __ASM_SH_HW_IRQ_H */
diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h
index a0e55b0..aa80930 100644
--- a/include/asm-sh/io.h
+++ b/include/asm-sh/io.h
@@ -116,13 +116,13 @@
  * redefined by userlevel programs.
  */
 #ifdef __readb
-# define readb(a)	({ unsigned long r_ = __raw_readb(a); mb(); r_; })
+# define readb(a)	({ unsigned int r_ = __raw_readb(a); mb(); r_; })
 #endif
 #ifdef __raw_readw
-# define readw(a)	({ unsigned long r_ = __raw_readw(a); mb(); r_; })
+# define readw(a)	({ unsigned int r_ = __raw_readw(a); mb(); r_; })
 #endif
 #ifdef __raw_readl
-# define readl(a)	({ unsigned long r_ = __raw_readl(a); mb(); r_; })
+# define readl(a)	({ unsigned int r_ = __raw_readl(a); mb(); r_; })
 #endif
 
 #ifdef __raw_writeb
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index e81bf21..c61d902 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -31,47 +31,7 @@
  * PINT IRQs
  */
 void init_IRQ_pint(void);
-
-/*
- * The shift value is now the number of bits to shift, not the number of
- * bits/4. This is to make it easier to read the value directly from the
- * datasheets. The IPR address, addr, will be set from ipr_idx via the
- * map_ipridx_to_addr function.
- */
-struct ipr_data {
-	unsigned int irq;
-	int ipr_idx;		/* Index for the IPR registered */
-	int shift;		/* Number of bits to shift the data */
-	int priority;		/* The priority */
-	unsigned int addr;	/* Address of Interrupt Priority Register */
-};
-
-/*
- * Given an IPR IDX, map the value to an IPR register address.
- */
-unsigned int map_ipridx_to_addr(int idx);
-
-/*
- * Enable individual interrupt mode for external IPR IRQs.
- */
-void ipr_irq_enable_irlm(void);
-
-/*
- * Function for "on chip support modules".
- */
-void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs);
 void make_imask_irq(unsigned int irq);
-void init_IRQ_ipr(void);
-
-struct intc2_data {
-	unsigned short irq;
-	unsigned char ipr_offset, ipr_shift;
-	unsigned char msk_offset, msk_shift;
-	unsigned char priority;
-};
-
-void make_intc2_irq(struct intc2_data *, unsigned int nr_irqs);
-void init_IRQ_intc2(void);
 
 static inline int generic_irq_demux(int irq)
 {
diff --git a/include/asm-sh/kdebug.h b/include/asm-sh/kdebug.h
index 16578b7..382cfc7 100644
--- a/include/asm-sh/kdebug.h
+++ b/include/asm-sh/kdebug.h
@@ -6,10 +6,6 @@
 /* Grossly misnamed. */
 enum die_val {
 	DIE_TRAP,
-	DIE_PAGE_FAULT,
 };
 
-int register_page_fault_notifier(struct notifier_block *nb);
-int unregister_page_fault_notifier(struct notifier_block *nb);
-
 #endif /* __ASM_SH_KDEBUG_H */
diff --git a/include/asm-sh/landisk/gio.h b/include/asm-sh/landisk/gio.h
index 3fce4c4..35d7368 100644
--- a/include/asm-sh/landisk/gio.h
+++ b/include/asm-sh/landisk/gio.h
@@ -29,16 +29,8 @@
 #define GIODRV_IOCGGIODATA4   _IOR(GIODRV_IOC_MAGIC,  6, unsigned long *)
 #define GIODRV_IOCSGIOSETADDR _IOW(GIODRV_IOC_MAGIC,  7, unsigned long *)
 #define GIODRV_IOCHARDRESET   _IO(GIODRV_IOC_MAGIC, 8) /* debugging tool */
-
-#define GIODRV_IOCSGIO_LED    _IOW(GIODRV_IOC_MAGIC,  9, unsigned long *)
-#define GIODRV_IOCGGIO_LED    _IOR(GIODRV_IOC_MAGIC,  10, unsigned long *)
-#define GIODRV_IOCSGIO_BUZZER _IOW(GIODRV_IOC_MAGIC,  11, unsigned long *)
-#define GIODRV_IOCGGIO_LANDISK _IOR(GIODRV_IOC_MAGIC,  14, unsigned long *)
-#define GIODRV_IOCGGIO_BTN _IOR(GIODRV_IOC_MAGIC,  22, unsigned long *)
-#define GIODRV_IOCSGIO_BTNPID _IOW(GIODRV_IOC_MAGIC,  23, unsigned long *)
-#define GIODRV_IOCGGIO_BTNPID _IOR(GIODRV_IOC_MAGIC,  24, unsigned long *)
-
 #define GIODRV_IOC_MAXNR 8
+
 #define GIO_READ 0x00000000
 #define GIO_WRITE 0x00000001
 
diff --git a/include/asm-sh/landisk/iodata_landisk.h b/include/asm-sh/landisk/iodata_landisk.h
index c74d3c7..6fb04ab 100644
--- a/include/asm-sh/landisk/iodata_landisk.h
+++ b/include/asm-sh/landisk/iodata_landisk.h
@@ -22,16 +22,6 @@
 /* 2003.10.31 I-O DATA NSD NWG	add.	for shutdown port clear */
 #define PA_PWRINT_CLR	0xb0000006	/* Shutdown Interrupt clear Register */
 
-#define PA_LCD_CLRDSP	0x00		/* LCD Clear Display Offset */
-#define PA_LCD_RTNHOME	0x00		/* LCD Return Home Offset */
-#define PA_LCD_ENTMODE	0x00		/* LCD Entry Mode Offset */
-#define PA_LCD_DSPCTL	0x00		/* LCD Display ON/OFF Control Offset */
-#define PA_LCD_FUNC	0x00		/* LCD Function Set Offset */
-#define PA_LCD_CGRAM	0x00		/* LCD Set CGRAM Address Offset */
-#define PA_LCD_DDRAM	0x00		/* LCD Set DDRAM Address Offset */
-#define PA_LCD_RDFLAG	0x01		/* LCD Read Busy Flag Offset */
-#define PA_LCD_WTDATA	0x02		/* LCD Write Datat to RAM Offset */
-#define PA_LCD_RDDATA	0x03		/* LCD Read Data from RAM Offset */
 #define PA_PIDE_OFFSET	0x40		/* CF IDE Offset */
 #define PA_SIDE_OFFSET	0x40		/* HDD IDE Offset */
 
@@ -45,33 +35,6 @@
 #define IRQ_BUTTON	12		/* USL-5P Button IRQ */
 #define IRQ_FAULT	13		/* USL-5P Fault  IRQ */
 
-#define SHUTDOWN_BTN_MAJOR	99	/* Shutdown button device major no. */
-
-#define SHUTDOWN_LOOP_CNT	5	/* Shutdown button Detection loop */
-#define SHUTDOWN_DELAY		200	/* Shutdown button delay value(ms) */
-
-
-/* added by kogiidena */
-/*
- *  landisk_ledparam
- *
- * led  ------10 -6543210 -6543210 -6543210
- *     |000000..|0.......|0.......|U.......|
- *     |  HARD  |fastblik| blink  |   on   |
- *
- *   led0: power       U:update flag
- *   led1: error
- *   led2: usb1
- *   led3: usb2
- *   led4: usb3
- *   led5: usb4
- *   led6: usb5
- *
- */
-extern int landisk_ledparam;    /* from setup.c */
-extern int landisk_buzzerparam; /* from setup.c */
-extern int landisk_arch;        /* from setup.c */
-
 #define __IO_PREFIX landisk
 #include <asm/io_generic.h>
 
diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h
index 70389b7..088698b 100644
--- a/include/asm-sh/machvec.h
+++ b/include/asm-sh/machvec.h
@@ -13,7 +13,6 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <asm/machtypes.h>
-#include <asm/machvec_init.h>
 
 struct device;
 
@@ -68,4 +67,7 @@
 
 #define get_system_type()	sh_mv.mv_name
 
+#define __initmv \
+	__attribute_used__ __attribute__((__section__ (".machvec.init")))
+
 #endif /* _ASM_SH_MACHVEC_H */
diff --git a/include/asm-sh/machvec_init.h b/include/asm-sh/machvec_init.h
deleted file mode 100644
index e397798..0000000
--- a/include/asm-sh/machvec_init.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * include/asm-sh/machvec_init.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file has goodies to help simplify instantiation of machine vectors.
- */
-
-#ifndef __SH_MACHVEC_INIT_H
-#define __SH_MACHVEC_INIT_H
-
-
-/*
- * In a GENERIC kernel, we have lots of these vectors floating about,
- * all but one of which we want to go away.  In a non-GENERIC kernel,
- * we want only one, ever.
- *
- * Accomplish this in the GENERIC kernel by puting all of the vectors
- * in the .init.data section where they'll go away.  We'll copy the
- * one we want to the real alpha_mv vector in setup_arch.
- *
- * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
- * one of the vectors, which will not reside in .init.data.  We then
- * alias this one vector to alpha_mv, so no copy is needed.
- *
- * Upshot: set __initdata to nothing for non-GENERIC kernels.
- *
- * Note we do the same thing for the UNKNOWN kernel, as we need to write
- * to the machine vector while setting it up.
- */
-
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
-#define __initmv __attribute__((unused,__section__ (".machvec.init")))
-#define ALIAS_MV(x)
-#else
-#define __initmv
-
-/* GCC actually has a syntax for defining aliases, but is under some
-   delusion that you shouldn't be able to declare it extern somewhere
-   else beforehand.  Fine.  We'll do it ourselves.  */
-#if 0
-#define ALIAS_MV(system) \
-  struct sh_machine_vector sh_mv __attribute__((alias("mv_"#system)));
-#else
-#define ALIAS_MV(system) \
-  asm(".global sh_mv\nsh_mv = mv_"#system );
-#endif
-#endif /* GENERIC */
-
-#endif /* __SH_MACHVEC_INIT_H */
diff --git a/include/asm-sh/mmzone.h b/include/asm-sh/mmzone.h
new file mode 100644
index 0000000..7969f38
--- /dev/null
+++ b/include/asm-sh/mmzone.h
@@ -0,0 +1,46 @@
+#ifndef __ASM_SH_MMZONE_H
+#define __ASM_SH_MMZONE_H
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid)		(node_data[nid])
+
+#define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
+#define node_end_pfn(nid)	(NODE_DATA(nid)->node_start_pfn + \
+				 NODE_DATA(nid)->node_spanned_pages)
+
+static inline int pfn_to_nid(unsigned long pfn)
+{
+	int nid;
+
+	for (nid = 0; nid < MAX_NUMNODES; nid++)
+		if (pfn >= node_start_pfn(nid) && pfn <= node_end_pfn(nid))
+			break;
+
+	return nid;
+}
+
+static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+	return NODE_DATA(pfn_to_nid(pfn));
+}
+
+/* arch/sh/mm/numa.c */
+void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end);
+#else
+static inline void
+setup_bootmem_node(int nid, unsigned long start, unsigned long end)
+{
+}
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+/* Platform specific mem init */
+void __init plat_mem_setup(void);
+
+/* arch/sh/kernel/setup.c */
+void __init setup_bootmem_allocator(unsigned long start_pfn);
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_MMZONE_H */
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 7464de4..6bc9bba 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -60,6 +60,7 @@
 
 extern unsigned long shm_align_mask;
 extern unsigned long max_low_pfn, min_low_pfn;
+extern unsigned long memory_start, memory_end;
 
 #ifdef CONFIG_MMU
 extern void clear_page_slow(void *to);
@@ -134,7 +135,9 @@
 #define PFN_START		(__MEMORY_START >> PAGE_SHIFT)
 #define ARCH_PFN_OFFSET		(PFN_START)
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#ifdef CONFIG_FLATMEM
 #define pfn_valid(pfn)		((pfn) >= min_low_pfn && (pfn) < max_low_pfn)
+#endif
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
@@ -148,5 +151,12 @@
 #define __HAVE_ARCH_GATE_AREA
 #endif
 
+/*
+ * Slub defaults to 8-byte alignment, we're only interested in 4.
+ * Slab defaults to BYTES_PER_WORD, which ends up being the same anyways.
+ */
+#define ARCH_KMALLOC_MINALIGN	4
+#define ARCH_SLAB_MINALIGN	4
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PAGE_H */
diff --git a/include/asm-sh/parport.h b/include/asm-sh/parport.h
new file mode 100644
index 0000000..f67ba60
--- /dev/null
+++ b/include/asm-sh/parport.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
+ *
+ * This file should only be included by drivers/parport/parport_pc.c.
+ */
+#ifndef __ASM_SH_PARPORT_H
+#define __ASM_SH_PARPORT_H
+
+static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma);
+
+static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
+{
+	return parport_pc_find_isa_ports(autoirq, autodma);
+}
+
+#endif /* __ASM_SH_PARPORT_H */
diff --git a/include/asm-sh/pci.h b/include/asm-sh/pci.h
index b1f9a9e..2757ce0 100644
--- a/include/asm-sh/pci.h
+++ b/include/asm-sh/pci.h
@@ -110,11 +110,6 @@
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 #endif
 
-/* Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function.  Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
@@ -134,10 +129,6 @@
 int pciauto_assign_resources(int busno, struct pci_channel *hose);
 #endif
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* generic pci stuff */
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index 5b523c7..22efffe 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -402,12 +402,8 @@
 #define pte_file(pte)		(pte_val(pte) & _PAGE_FILE)
 
 #ifdef CONFIG_X2TLB
-#define pte_read(pte)		((pte).pte_high & _PAGE_EXT_USER_READ)
-#define pte_exec(pte)		((pte).pte_high & _PAGE_EXT_USER_EXEC)
 #define pte_write(pte)		((pte).pte_high & _PAGE_EXT_USER_WRITE)
 #else
-#define pte_read(pte)		(pte_val(pte) & _PAGE_USER)
-#define pte_exec(pte)		(pte_val(pte) & _PAGE_USER)
 #define pte_write(pte)		(pte_val(pte) & _PAGE_RW)
 #endif
 
@@ -420,20 +416,12 @@
  * individually toggled (and user permissions are entirely decoupled from
  * kernel permissions), we attempt to couple them a bit more sanely here.
  */
-PTE_BIT_FUNC(high, rdprotect, &= ~_PAGE_EXT_USER_READ);
-PTE_BIT_FUNC(high, mkread, |= _PAGE_EXT_USER_READ | _PAGE_EXT_KERN_READ);
 PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE);
 PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE);
-PTE_BIT_FUNC(high, exprotect, &= ~_PAGE_EXT_USER_EXEC);
-PTE_BIT_FUNC(high, mkexec, |= _PAGE_EXT_USER_EXEC | _PAGE_EXT_KERN_EXEC);
 PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE);
 #else
-PTE_BIT_FUNC(low, rdprotect, &= ~_PAGE_USER);
-PTE_BIT_FUNC(low, mkread, |= _PAGE_USER);
 PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW);
 PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW);
-PTE_BIT_FUNC(low, exprotect, &= ~_PAGE_USER);
-PTE_BIT_FUNC(low, mkexec, |= _PAGE_USER);
 PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE);
 #endif
 
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index d42f68e..2252e75 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -36,7 +36,7 @@
  */
 enum cpu_type {
 	/* SH-2 types */
-	CPU_SH7604, CPU_SH7619,
+	CPU_SH7619,
 
 	/* SH-2A types */
 	CPU_SH7206,
@@ -52,7 +52,7 @@
 	CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
 
 	/* SH-4A types */
-	CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
+	CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3,
 
 	/* SH4AL-DSP types */
 	CPU_SH73180, CPU_SH7343, CPU_SH7722,
@@ -228,11 +228,7 @@
 	regs->sr &= ~SR_FD;
 }
 
-#ifdef CONFIG_CPU_SH4
 extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs);
-#else
-#define save_fpu(tsk)	do { } while (0)
-#endif
 
 #define unlazy_fpu(tsk, regs) do {			\
 	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {	\
diff --git a/include/asm-sh/rwsem.h b/include/asm-sh/rwsem.h
index 4931ba8..1987f3e 100644
--- a/include/asm-sh/rwsem.h
+++ b/include/asm-sh/rwsem.h
@@ -1,11 +1,15 @@
 /*
- * include/asm-ppc/rwsem.h: R/W semaphores for SH using the stuff
+ * include/asm-sh/rwsem.h: R/W semaphores for SH using the stuff
  * in lib/rwsem.c.
  */
 
 #ifndef _ASM_SH_RWSEM_H
 #define _ASM_SH_RWSEM_H
 
+#ifndef _LINUX_RWSEM_H
+#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
+#endif
+
 #ifdef __KERNEL__
 #include <linux/list.h>
 #include <linux/spinlock.h>
diff --git a/include/asm-sh/saturn/io.h b/include/asm-sh/saturn/io.h
deleted file mode 100644
index f1b9b5d..0000000
--- a/include/asm-sh/saturn/io.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * include/asm-sh/saturn/io.h
- *
- * I/O functions for use on the Sega Saturn.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#ifndef __ASM_SH_SATURN_IO_H
-#define __ASM_SH_SATURN_IO_H
-
-/* arch/sh/boards/saturn/io.c */
-extern unsigned long saturn_isa_port2addr(unsigned long offset);
-extern void *saturn_ioremap(unsigned long offset, unsigned long size);
-extern void saturn_iounmap(void *addr);
-
-#endif /* __ASM_SH_SATURN_IO_H */
-
diff --git a/include/asm-sh/saturn/smpc.h b/include/asm-sh/saturn/smpc.h
deleted file mode 100644
index 5de5c12..0000000
--- a/include/asm-sh/saturn/smpc.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * include/asm-sh/saturn/smpc.h
- *
- * System Manager / Peripheral Control definitions.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#ifndef __ASM_SH_SATURN_SMPC_H
-#define __ASM_SH_SATURN_SMPC_H
-
-#include <asm/io.h>
-
-#define SMPC_COMMAND	0x2010001f	/* SMPC command register */
-#define SMPC_RESULT	0x2010005f	/* SMPC result register */
-#define SMPC_STATUS	0x20100063	/* SMPC status register */
-
-#define SMPC_CMD_MSHON	0x0001		/* Master SH On */
-#define SMPC_CMD_SSHON	0x0002		/* Slave SH On */
-#define SMPC_CMD_SSHOFF	0x0003		/* Slave SH Off */
-#define SMPC_CMD_SNDON	0x0004		/* Sound On */
-#define SMPC_CMD_SNDOFF	0x0005		/* Sound Off */
-#define SMPC_CMD_CDON	0x0006		/* CD On */
-#define SMPC_CMD_CDOFF	0x0007		/* CD Off */
-
-static inline void smpc_barrier(void)
-{
-	while ((ctrl_inb(SMPC_STATUS) & 0x0001) == 0x0001)
-		;
-}
-
-#endif /* __ASM_SH_SATURN_SMPC_H */
-
diff --git a/include/asm-sh/se73180.h b/include/asm-sh/se73180.h
index 3a4acb3..907c062 100644
--- a/include/asm-sh/se73180.h
+++ b/include/asm-sh/se73180.h
@@ -1,9 +1,7 @@
-#ifndef __ASM_SH_HITACHI_SE73180_H
-#define __ASM_SH_HITACHI_SE73180_H
+#ifndef __ASM_SH_SE73180_H
+#define __ASM_SH_SE73180_H
 
 /*
- * include/asm-sh/se/se73180.h
- *
  * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
  *
  * SH-Mobile SolutionEngine 73180 support
@@ -62,4 +60,7 @@
 #define __IO_PREFIX	sh73180se
 #include <asm/io_generic.h>
 
-#endif  /* __ASM_SH_HITACHI_SE73180_H */
+/* arch/sh/boards/se/73180/irq.c */
+int shmse_irq_demux(int irq);
+
+#endif  /* __ASM_SH_SE73180_H */
diff --git a/include/asm-sh/sections.h b/include/asm-sh/sections.h
index 57abd70..2a696b8 100644
--- a/include/asm-sh/sections.h
+++ b/include/asm-sh/sections.h
@@ -3,7 +3,7 @@
 
 #include <asm-generic/sections.h>
 
-extern char _end[];
+extern long __machvec_start, __machvec_end;
 
 #endif /* __ASM_SH_SECTIONS_H */
 
diff --git a/include/asm-sh/setup.h b/include/asm-sh/setup.h
index 1583c6b..586a971 100644
--- a/include/asm-sh/setup.h
+++ b/include/asm-sh/setup.h
@@ -6,6 +6,7 @@
 #ifdef __KERNEL__
 
 int setup_early_printk(char *);
+void sh_mv_setup(void);
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-sh/sh03/io.h b/include/asm-sh/sh03/io.h
index df3b187..4ff1eb9 100644
--- a/include/asm-sh/sh03/io.h
+++ b/include/asm-sh/sh03/io.h
@@ -14,22 +14,18 @@
 #define INTC_IPRD	0xffd00010UL
 
 #define IRL0_IRQ	2
-#define IRL0_IPR_ADDR	INTC_IPRD
 #define IRL0_IPR_POS	3
 #define IRL0_PRIORITY	13
 
 #define IRL1_IRQ	5
-#define IRL1_IPR_ADDR	INTC_IPRD
 #define IRL1_IPR_POS	2
 #define IRL1_PRIORITY	10
 
 #define IRL2_IRQ	8
-#define IRL2_IPR_ADDR	INTC_IPRD
 #define IRL2_IPR_POS	1
 #define IRL2_PRIORITY	7
 
 #define IRL3_IRQ	11
-#define IRL3_IPR_ADDR	INTC_IPRD
 #define IRL3_IPR_POS	0
 #define IRL3_PRIORITY	4
 
diff --git a/include/asm-sh/smp.h b/include/asm-sh/smp.h
index 71ecddf..b99ca78 100644
--- a/include/asm-sh/smp.h
+++ b/include/asm-sh/smp.h
@@ -15,7 +15,7 @@
 
 #ifdef CONFIG_SMP
 
-#include <asm/spinlock.h>
+#include <linux/spinlock.h>
 #include <asm/atomic.h>
 #include <asm/current.h>
 
@@ -39,4 +39,6 @@
 
 #endif /* CONFIG_SMP */
 
+#define hard_smp_processor_id()	(0)
+
 #endif /* __ASM_SH_SMP_H */
diff --git a/include/asm-sh/snapgear.h b/include/asm-sh/snapgear.h
index 2d712e7..3554e3a 100644
--- a/include/asm-sh/snapgear.h
+++ b/include/asm-sh/snapgear.h
@@ -20,22 +20,18 @@
  */
 
 #define IRL0_IRQ		2
-#define IRL0_IPR_ADDR	INTC_IPRD
 #define IRL0_IPR_POS	3
 #define IRL0_PRIORITY	13
 
 #define IRL1_IRQ		5
-#define IRL1_IPR_ADDR	INTC_IPRD
 #define IRL1_IPR_POS	2
 #define IRL1_PRIORITY	10
 
 #define IRL2_IRQ		8
-#define IRL2_IPR_ADDR	INTC_IPRD
 #define IRL2_IPR_POS	1
 #define IRL2_PRIORITY	7
 
 #define IRL3_IRQ		11
-#define IRL3_IPR_ADDR	INTC_IPRD
 #define IRL3_IPR_POS	0
 #define IRL3_PRIORITY	4
 #endif
diff --git a/include/asm-sh/sparsemem.h b/include/asm-sh/sparsemem.h
new file mode 100644
index 0000000..547a540
--- /dev/null
+++ b/include/asm-sh/sparsemem.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_SH_SPARSEMEM_H
+#define __ASM_SH_SPARSEMEM_H
+
+#ifdef __KERNEL__
+/*
+ * SECTION_SIZE_BITS		2^N: how big each section will be
+ * MAX_PHYSADDR_BITS		2^N: how much physical address space we have
+ * MAX_PHYSMEM_BITS		2^N: how much memory we can have in that space
+ */
+#define SECTION_SIZE_BITS	26
+#define MAX_PHYSADDR_BITS	32
+#define MAX_PHYSMEM_BITS	32
+
+#endif
+
+#endif /* __ASM_SH_SPARSEMEM_H */
diff --git a/include/asm-sh/spinlock.h b/include/asm-sh/spinlock.h
index 2586eef..92f6e20 100644
--- a/include/asm-sh/spinlock.h
+++ b/include/asm-sh/spinlock.h
@@ -11,6 +11,7 @@
 #define __ASM_SH_SPINLOCK_H
 
 #include <asm/atomic.h>
+#include <asm/spinlock_types.h>
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
@@ -42,7 +43,7 @@
 
 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
-	assert_spin_locked(lock);
+	//assert_spin_locked(lock);
 
 	lock->lock = 0;
 }
@@ -88,6 +89,11 @@
 	__raw_spin_unlock(&rw->lock);
 }
 
+static inline int __raw_write_can_lock(raw_rwlock_t *rw)
+{
+	return (atomic_read(&rw->counter) == RW_LOCK_BIAS);
+}
+
 static inline int __raw_read_trylock(raw_rwlock_t *lock)
 {
 	atomic_t *count = (atomic_t*)lock;
diff --git a/include/asm-sh/spinlock_types.h b/include/asm-sh/spinlock_types.h
index 8c41b6c..5c58134 100644
--- a/include/asm-sh/spinlock_types.h
+++ b/include/asm-sh/spinlock_types.h
@@ -9,7 +9,9 @@
 	volatile unsigned long lock;
 } raw_spinlock_t;
 
-#define __SPIN_LOCK_UNLOCKED		{ 0 }
+#define __RAW_SPIN_LOCK_UNLOCKED	{ 1 }
+
+#include <asm/atomic.h>
 
 typedef struct {
 	raw_spinlock_t lock;
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 82f3e22..7c75045 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -8,9 +8,13 @@
 
 #include <linux/irqflags.h>
 #include <linux/compiler.h>
+#include <linux/linkage.h>
 #include <asm/types.h>
 #include <asm/ptrace.h>
 
+struct task_struct *__switch_to(struct task_struct *prev,
+				struct task_struct *next);
+
 /*
  *	switch_to() should switch tasks to task nr n, first
  */
@@ -122,7 +126,7 @@
 #define smp_read_barrier_depends()	do { } while(0)
 #endif
 
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
 
 /*
  * Jump to P2 area.
@@ -271,6 +275,16 @@
 void disable_hlt(void);
 void enable_hlt(void);
 
+void default_idle(void);
+
+asmlinkage void break_point_trap(void);
+asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
+				   unsigned long r6, unsigned long r7,
+				   struct pt_regs __regs);
+asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
+				 unsigned long r6, unsigned long r7,
+				 struct pt_regs __regs);
+
 #define arch_align_stack(x) (x)
 
 #endif
diff --git a/include/asm-sh/termbits.h b/include/asm-sh/termbits.h
index f1b7b46..7ee1b42 100644
--- a/include/asm-sh/termbits.h
+++ b/include/asm-sh/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-sh/topology.h b/include/asm-sh/topology.h
index cff001c..f402a3b 100644
--- a/include/asm-sh/topology.h
+++ b/include/asm-sh/topology.h
@@ -1,6 +1,36 @@
 #ifndef _ASM_SH_TOPOLOGY_H
 #define _ASM_SH_TOPOLOGY_H
 
+#ifdef CONFIG_NUMA
+
+/* sched_domains SD_NODE_INIT for sh machines */
+#define SD_NODE_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.child			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 8,			\
+	.max_interval		= 32,			\
+	.busy_factor		= 32,			\
+	.imbalance_pct		= 125,			\
+	.cache_nice_tries	= 2,			\
+	.busy_idx		= 3,			\
+	.idle_idx		= 2,			\
+	.newidle_idx		= 0,			\
+	.wake_idx		= 1,			\
+	.forkexec_idx		= 1,			\
+	.flags			= SD_LOAD_BALANCE	\
+				| SD_BALANCE_FORK	\
+				| SD_BALANCE_EXEC	\
+				| SD_SERIALIZE		\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+
+#endif
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_SH_TOPOLOGY_H */
diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h
index 5c49ed6..f18a1a5 100644
--- a/include/asm-sh/uaccess.h
+++ b/include/asm-sh/uaccess.h
@@ -61,8 +61,6 @@
  */
 static inline int __access_ok(unsigned long addr, unsigned long size)
 {
-	extern unsigned long memory_start, memory_end;
-
 	return ((addr >= memory_start) && ((addr + size) < memory_end));
 }
 #else /* CONFIG_MMU */
@@ -76,7 +74,7 @@
  * __access_ok: Check if address with size is OK or not.
  *
  * We do three checks:
- * (1) is it user space? 
+ * (1) is it user space?
  * (2) addr + size --> carry?
  * (3) addr + size >= 0x80000000  (PAGE_OFFSET)
  *
@@ -142,11 +140,12 @@
   __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
 
 struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
+#define __m(x) (*(struct __large_struct __user *)(x))
 
 #define __get_user_size(x,ptr,size,retval)			\
 do {								\
 	retval = 0;						\
+	__chk_user_ptr(ptr);					\
 	switch (size) {						\
 	case 1:							\
 		__get_user_asm(x, ptr, retval, "b");		\
@@ -175,6 +174,7 @@
 #define __get_user_check(x,ptr,size)				\
 ({								\
 	long __gu_err, __gu_val;				\
+	__chk_user_ptr(ptr);					\
 	switch (size) {						\
 	case 1:							\
 		__get_user_1(__gu_val, (ptr), __gu_err);	\
@@ -300,6 +300,7 @@
 #define __put_user_size(x,ptr,size,retval)		\
 do {							\
 	retval = 0;					\
+	__chk_user_ptr(ptr);				\
 	switch (size) {					\
 	case 1:						\
 		__put_user_asm(x, ptr, retval, "b");	\
@@ -328,7 +329,7 @@
 #define __put_user_check(x,ptr,size)				\
 ({								\
 	long __pu_err = -EFAULT;				\
-	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
+	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
 								\
 	if (__access_ok((unsigned long)__pu_addr,size))		\
 		__put_user_size((x),__pu_addr,(size),__pu_err);	\
@@ -406,10 +407,10 @@
 #endif
 
 extern void __put_user_unknown(void);
-
+
 /* Generic arbitrary sized copy.  */
 /* Return the number of bytes NOT copied */
-extern __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
+__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
 
 #define copy_to_user(to,from,n) ({ \
 void *__copy_to = (void *) (to); \
@@ -420,14 +421,6 @@
 } else __copy_res = __copy_size; \
 __copy_res; })
 
-#define __copy_to_user(to,from,n)		\
-	__copy_user((void *)(to),		\
-		    (void *)(from), n)
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-
 #define copy_from_user(to,from,n) ({ \
 void *__copy_to = (void *) (to); \
 void *__copy_from = (void *) (from); \
@@ -438,9 +431,20 @@
 } else __copy_res = __copy_size; \
 __copy_res; })
 
-#define __copy_from_user(to,from,n)		\
-	__copy_user((void *)(to),		\
-		    (void *)(from), n)
+static __always_inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	return __copy_user(to, (__force void *)from, n);
+}
+
+static __always_inline unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	return __copy_user((__force void *)to, from, n);
+}
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 /*
  * Clear the area and return remaining number of bytes
diff --git a/include/asm-sh/ubc.h b/include/asm-sh/ubc.h
index ae9bbde..38d46e0 100644
--- a/include/asm-sh/ubc.h
+++ b/include/asm-sh/ubc.h
@@ -51,9 +51,14 @@
 #define BRCR_UBDE		(1 << 0)
 
 #ifndef __ASSEMBLY__
-/* arch/sh/kernel/ubc.S */
-extern void ubc_wakeup(void);
+/* arch/sh/kernel/cpu/ubc.S */
 extern void ubc_sleep(void);
+
+#ifdef CONFIG_UBC_WAKEUP
+extern void ubc_wakeup(void);
+#else
+#define ubc_wakeup()	do { } while (0)
+#endif
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index af71e37..77bcb09 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -329,8 +329,11 @@
 #define __NR_getcpu		318
 #define __NR_epoll_pwait	319
 #define __NR_utimensat		320
+#define __NR_signalfd		321
+#define __NR_timerfd		322
+#define __NR_eventfd		323
 
-#define NR_syscalls 321
+#define NR_syscalls 324
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-sh64/fb.h b/include/asm-sh64/fb.h
new file mode 100644
index 0000000..d92e99c
--- /dev/null
+++ b/include/asm-sh64/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sh64/pci.h b/include/asm-sh64/pci.h
index aa80430..57a67cf 100644
--- a/include/asm-sh64/pci.h
+++ b/include/asm-sh64/pci.h
@@ -72,11 +72,6 @@
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 #endif
 
-/* Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function.  Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
 /* These macros should be used after a pci_map_sg call has been done
  * to get bus addresses of each of the SG entries and their lengths.
  * You should only work with the number of sg entries pci_map_sg
@@ -104,10 +99,6 @@
 extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
 #endif
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* generic pci stuff */
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index b875482..3488fe3 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -415,22 +415,15 @@
 /*
  * The following have defined behavior only work if pte_present() is true.
  */
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXECUTE; }
 static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
 static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; }
 
-static inline pte_t pte_rdprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_READ)); return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE)); return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
-
-static inline pte_t pte_mkread(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_READ)); return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; }
-static inline pte_t pte_mkexec(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 static inline pte_t pte_mkhuge(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h
index 731fa56..bdca541 100644
--- a/include/asm-sparc/atomic.h
+++ b/include/asm-sparc/atomic.h
@@ -2,6 +2,7 @@
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
  *
  * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
  * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
@@ -10,11 +11,48 @@
 #ifndef __ARCH_SPARC_ATOMIC__
 #define __ARCH_SPARC_ATOMIC__
 
+#include <linux/types.h>
 
 typedef struct { volatile int counter; } atomic_t;
 
 #ifdef __KERNEL__
 
+/* Emulate cmpxchg() the same way we emulate atomics,
+ * by hashing the object address and indexing into an array
+ * of spinlocks to get a bit of performance...
+ *
+ * See arch/sparc/lib/atomic32.c for implementation.
+ *
+ * Cribbed from <asm-parisc/atomic.h>
+ */
+#define __HAVE_ARCH_CMPXCHG	1
+
+/* bug catcher for when unsupported size is used - won't link */
+extern void __cmpxchg_called_with_bad_pointer(void);
+/* we only need to support cmpxchg of a u32 on sparc */
+extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
+
+/* don't worry...optimizer will get rid of most of this */
+static __inline__ unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
+{
+	switch(size) {
+	case 4:
+		return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
+	default:
+		__cmpxchg_called_with_bad_pointer();
+		break;
+	}
+	return old;
+}
+
+#define cmpxchg(ptr,o,n) ({						\
+	__typeof__(*(ptr)) _o_ = (o);					\
+	__typeof__(*(ptr)) _n_ = (n);					\
+	(__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,	\
+			(unsigned long)_n_, sizeof(*(ptr)));		\
+})
+
 #define ATOMIC_INIT(i)  { (i) }
 
 extern int __atomic_add_return(int, atomic_t *);
diff --git a/include/asm-sparc/fb.h b/include/asm-sparc/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-sparc/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sparc/pci.h b/include/asm-sparc/pci.h
index a750c688..b93b6c7 100644
--- a/include/asm-sparc/pci.h
+++ b/include/asm-sparc/pci.h
@@ -142,8 +142,6 @@
 	return 1;
 }
 
-#define pci_dac_dma_supported(dev, mask)	(0)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
@@ -154,10 +152,6 @@
 }
 #endif
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #define PCI_DMA_ERROR_CODE      (~(dma_addr_t)0x0)
 
 static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index 4f0a5ba..a55f4c3 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -151,7 +151,6 @@
 BTFIXUPDEF_SETHI(none_mask)
 BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t)
 BTFIXUPDEF_CALL(void, pte_clear, pte_t *)
-BTFIXUPDEF_CALL(int, pte_read, pte_t)
 
 static inline int pte_none(pte_t pte)
 {
@@ -160,7 +159,6 @@
 
 #define pte_present(pte) BTFIXUP_CALL(pte_present)(pte)
 #define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte)
-#define pte_read(pte) BTFIXUP_CALL(pte_read)(pte)
 
 BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t)
 BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t)
@@ -446,6 +444,17 @@
 #define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)			(pfn & 0x0fffffffUL)
 
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+({									  \
+	int __changed = !pte_same(*(__ptep), __entry);			  \
+	if (__changed) {						  \
+		set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+		flush_tlb_page(__vma, __address);			  \
+	}								  \
+	(sparc_cpu_model == sun4c) || __changed;			  \
+})
+
 #include <asm-generic/pgtable.h>
 
 #endif /* !(__ASSEMBLY__) */
diff --git a/include/asm-sparc64/bugs.h b/include/asm-sparc64/bugs.h
index 120422f..11ade68 100644
--- a/include/asm-sparc64/bugs.h
+++ b/include/asm-sparc64/bugs.h
@@ -1,15 +1,10 @@
-/*  $Id: bugs.h,v 1.1 1996/12/26 13:25:20 davem Exp $
- *  include/asm-sparc64/bugs.h:  Sparc probes for various bugs.
+/* bugs.h: Sparc64 probes for various bugs.
  *
- *  Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
  */
-
-
-extern unsigned long loops_per_jiffy;
+#include <asm/sstate.h>
 
 static void __init check_bugs(void)
 {
-#ifndef CONFIG_SMP
-	cpu_data(0).udelay_val = loops_per_jiffy;
-#endif
+	sstate_running();
 }
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index 36511ca..01fe668 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -31,8 +31,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
index e89922d..98a6e60 100644
--- a/include/asm-sparc64/cpudata.h
+++ b/include/asm-sparc64/cpudata.h
@@ -17,11 +17,11 @@
 typedef struct {
 	/* Dcache line 1 */
 	unsigned int	__softirq_pending; /* must be 1st, see rtrap.S */
-	unsigned int	__pad0_1;
-	unsigned int	__pad0_2;
-	unsigned int	__pad1;
+	unsigned int	__pad0;
 	unsigned long	clock_tick;	/* %tick's per second */
-	unsigned long	udelay_val;
+	unsigned long	__pad;
+	unsigned int	__pad1;
+	unsigned int	__pad2;
 
 	/* Dcache line 2, rarely used */
 	unsigned int	dcache_size;
@@ -30,8 +30,8 @@
 	unsigned int	icache_line_size;
 	unsigned int	ecache_size;
 	unsigned int	ecache_line_size;
-	unsigned int	__pad3;
-	unsigned int	__pad4;
+	int		core_id;
+	int		proc_id;
 } cpuinfo_sparc;
 
 DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
@@ -76,12 +76,19 @@
 
 /* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size.  */
 	unsigned int		irq_worklist;
-	unsigned int		__pad1;
-	unsigned long		__pad2[3];
+	unsigned int		cpu_mondo_qmask;
+	unsigned int		dev_mondo_qmask;
+	unsigned int		resum_qmask;
+	unsigned int		nonresum_qmask;
+	unsigned int		__pad2[1];
+	void			*hdesc;
 } __attribute__((aligned(64)));
 extern struct trap_per_cpu trap_block[NR_CPUS];
 extern void init_cur_cpu_trap(struct thread_info *);
 extern void setup_tba(void);
+extern int ncpus_probed;
+
+extern unsigned long real_hard_smp_processor_id(void);
 
 struct cpuid_patch_entry {
 	unsigned int	addr;
@@ -122,6 +129,10 @@
 #define TRAP_PER_CPU_TSB_HUGE		0xd0
 #define TRAP_PER_CPU_TSB_HUGE_TEMP	0xd8
 #define TRAP_PER_CPU_IRQ_WORKLIST	0xe0
+#define TRAP_PER_CPU_CPU_MONDO_QMASK	0xe4
+#define TRAP_PER_CPU_DEV_MONDO_QMASK	0xe8
+#define TRAP_PER_CPU_RESUM_QMASK	0xec
+#define TRAP_PER_CPU_NONRESUM_QMASK	0xf0
 
 #define TRAP_BLOCK_SZ_SHIFT		8
 
@@ -192,7 +203,7 @@
  * the calculations done by the macro mid-stream.
  */
 #define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)	\
-	ldub	[THR + TI_CPU], REG1;			\
+	lduh	[THR + TI_CPU], REG1;			\
 	sethi	%hi(__per_cpu_shift), REG3;		\
 	sethi	%hi(__per_cpu_base), REG2;		\
 	ldx	[REG3 + %lo(__per_cpu_shift)], REG3;	\
diff --git a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
index a4aae6f..a77aa62 100644
--- a/include/asm-sparc64/delay.h
+++ b/include/asm-sparc64/delay.h
@@ -1,37 +1,17 @@
 /* delay.h: Linux delay routines on sparc64.
  *
- * Copyright (C) 1996, 2004 David S. Miller (davem@davemloft.net).
- *
- * Based heavily upon x86 variant which is:
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/sparc64/lib/delay.c
+ * Copyright (C) 1996, 2004, 2007 David S. Miller (davem@davemloft.net).
  */
 
-#ifndef __SPARC64_DELAY_H
-#define __SPARC64_DELAY_H
-
-#include <linux/param.h>
-#include <asm/cpudata.h>
+#ifndef _SPARC64_DELAY_H
+#define _SPARC64_DELAY_H
 
 #ifndef __ASSEMBLY__
 
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
-	__udelay(n))
-	
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
+extern void udelay(unsigned long usecs);
+#define mdelay(n)	udelay((n) * 1000)
 
 #endif /* !__ASSEMBLY__ */
 
-#endif /* defined(__SPARC64_DELAY_H) */
+#endif /* _SPARC64_DELAY_H */
diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h
index 9329429..c58ec16 100644
--- a/include/asm-sparc64/dma-mapping.h
+++ b/include/asm-sparc64/dma-mapping.h
@@ -15,8 +15,7 @@
 static inline int
 dma_supported(struct device *dev, u64 mask)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	return pci_dma_supported(to_pci_dev(dev), mask);
 }
@@ -24,8 +23,7 @@
 static inline int
 dma_set_mask(struct device *dev, u64 dma_mask)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
 }
@@ -34,8 +32,7 @@
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		   gfp_t flag)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	return pci_iommu_ops->alloc_consistent(to_pci_dev(dev), size, dma_handle, flag);
 }
@@ -44,8 +41,7 @@
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 		    dma_addr_t dma_handle)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
 }
@@ -54,8 +50,7 @@
 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
 	       enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
 }
@@ -64,8 +59,7 @@
 dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		 enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
 }
@@ -75,8 +69,7 @@
 	     unsigned long offset, size_t size,
 	     enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
 }
@@ -85,8 +78,7 @@
 dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
 	       enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
 }
@@ -95,8 +87,7 @@
 dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 	   enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
 }
@@ -105,8 +96,7 @@
 dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 	     enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
 }
@@ -115,8 +105,7 @@
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
 			enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
 				    size, (int)direction);
@@ -126,8 +115,7 @@
 dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
 			   enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
 				       size, (int)direction);
@@ -137,8 +125,7 @@
 dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 		    enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
 }
@@ -147,8 +134,7 @@
 dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
 		       enum dma_data_direction direction)
 {
-	BUG_ON(dev->bus != &pci_bus_type &&
-	       dev->bus != &ebus_bus_type);
+	BUG_ON(dev->bus != &pci_bus_type);
 
 	pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
 }
@@ -162,6 +148,22 @@
 #else
 
 struct device;
+struct page;
+struct scatterlist;
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+	BUG();
+	return 0;
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	BUG();
+	return 0;
+}
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
 			 dma_addr_t *dma_handle, gfp_t flag)
@@ -176,6 +178,52 @@
 	BUG();
 }
 
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+	return 0;
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+	     unsigned long offset, size_t size,
+	     enum dma_data_direction direction)
+{
+	BUG();
+	return 0;
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction)
+{
+	BUG();
+	return 0;
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction)
+{
+	BUG();
+}
+
 static inline void
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
 			enum dma_data_direction direction)
@@ -190,6 +238,27 @@
 	BUG();
 }
 
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+		    enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+		       enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline int
+dma_mapping_error(dma_addr_t dma_addr)
+{
+	BUG();
+	return 0;
+}
+
 #endif /* PCI */
 
 
diff --git a/include/asm-sparc64/fb.h b/include/asm-sparc64/fb.h
new file mode 100644
index 0000000..d6cd3a1
--- /dev/null
+++ b/include/asm-sparc64/fb.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sparc64/hvtramp.h b/include/asm-sparc64/hvtramp.h
new file mode 100644
index 0000000..c7dd6ad
--- /dev/null
+++ b/include/asm-sparc64/hvtramp.h
@@ -0,0 +1,37 @@
+#ifndef _SPARC64_HVTRAP_H
+#define _SPARC64_HVTRAP_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct hvtramp_mapping {
+	__u64		vaddr;
+	__u64		tte;
+};
+
+struct hvtramp_descr {
+	__u32			cpu;
+	__u32			num_mappings;
+	__u64			fault_info_va;
+	__u64			fault_info_pa;
+	__u64			thread_reg;
+	struct hvtramp_mapping	maps[2];
+};
+
+extern void hv_cpu_startup(unsigned long hvdescr_pa);
+
+#endif
+
+#define HVTRAMP_DESCR_CPU		0x00
+#define HVTRAMP_DESCR_NUM_MAPPINGS	0x04
+#define HVTRAMP_DESCR_FAULT_INFO_VA	0x08
+#define HVTRAMP_DESCR_FAULT_INFO_PA	0x10
+#define HVTRAMP_DESCR_THREAD_REG	0x18
+#define HVTRAMP_DESCR_MAPS		0x20
+
+#define HVTRAMP_MAPPING_VADDR		0x00
+#define HVTRAMP_MAPPING_TTE		0x08
+#define HVTRAMP_MAPPING_SIZE		0x10
+
+#endif /* _SPARC64_HVTRAP_H */
diff --git a/include/asm-sparc64/hypervisor.h b/include/asm-sparc64/hypervisor.h
index a5558c8..524d498 100644
--- a/include/asm-sparc64/hypervisor.h
+++ b/include/asm-sparc64/hypervisor.h
@@ -73,6 +73,8 @@
 #define HV_ENOTSUPPORTED		13 /* Function not supported       */
 #define HV_ENOMAP			14 /* No mapping found             */
 #define HV_ETOOMANY			15 /* Too many items specified     */
+#define HV_ECHANNEL			16 /* Invalid LDC channel          */
+#define HV_EBUSY			17 /* Resource busy                */
 
 /* mach_exit()
  * TRAP:	HV_FAST_TRAP
@@ -95,6 +97,10 @@
  */
 #define HV_FAST_MACH_EXIT		0x00
 
+#ifndef __ASSEMBLY__
+extern void sun4v_mach_exit(unsigned long exit_code);
+#endif
+
 /* Domain services.  */
 
 /* mach_desc()
@@ -120,7 +126,13 @@
  */
 #define HV_FAST_MACH_DESC		0x01
 
-/* mach_exit()
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mach_desc(unsigned long buffer_pa,
+				     unsigned long buf_len,
+				     unsigned long *real_buf_len);
+#endif
+
+/* mach_sir()
  * TRAP:	HV_FAST_TRAP
  * FUNCTION:	HV_FAST_MACH_SIR
  * ERRORS:	This service does not return.
@@ -135,53 +147,66 @@
  */
 #define HV_FAST_MACH_SIR		0x02
 
-/* mach_set_soft_state()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MACH_SET_SOFT_STATE
- * ARG0:	software state
- * ARG1:	software state description pointer
- * RET0:	status
- * ERRORS:	EINVAL		software state not valid or software state
- *				description is not NULL terminated
- *		ENORADDR	software state description pointer is not a
- *				valid real address
- *		EBADALIGNED	software state description is not correctly
- *				aligned
- *
- * This allows the guest to report it's soft state to the hypervisor.  There
- * are two primary components to this state.  The first part states whether
- * the guest software is running or not.  The second containts optional
- * details specific to the software.
- *
- * The software state argument is defined below in HV_SOFT_STATE_*, and
- * indicates whether the guest is operating normally or in a transitional
- * state.
- *
- * The software state description argument is a real address of a data buffer
- * of size 32-bytes aligned on a 32-byte boundary.  It is treated as a NULL
- * terminated 7-bit ASCII string of up to 31 characters not including the
- * NULL termination.
- */
-#define HV_FAST_MACH_SET_SOFT_STATE	0x03
-#define  HV_SOFT_STATE_NORMAL		 0x01
-#define  HV_SOFT_STATE_TRANSITION	 0x02
+#ifndef __ASSEMBLY__
+extern void sun4v_mach_sir(void);
+#endif
 
-/* mach_get_soft_state()
+/* mach_set_watchdog()
  * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MACH_GET_SOFT_STATE
- * ARG0:	software state description pointer
+ * FUNCTION:	HV_FAST_MACH_SET_WATCHDOG
+ * ARG0:	timeout in milliseconds
  * RET0:	status
- * RET1:	software state
- * ERRORS:	ENORADDR	software state description pointer is not a
- *				valid real address
- *		EBADALIGNED	software state description is not correctly
- *				aligned
+ * RET1:	time remaining in milliseconds
  *
- * Retrieve the current value of the guest's software state.  The rules
- * for the software state pointer are the same as for mach_set_soft_state()
- * above.
+ * A guest uses this API to set a watchdog timer.  Once the gues has set
+ * the timer, it must call the timer service again either to disable or
+ * postpone the expiration.  If the timer expires before being reset or
+ * disabled, then the hypervisor take a platform specific action leading
+ * to guest termination within a bounded time period.  The platform action
+ * may include recovery actions such as reporting the expiration to a
+ * Service Processor, and/or automatically restarting the gues.
+ *
+ * The 'timeout' parameter is specified in milliseconds, however the
+ * implementated granularity is given by the 'watchdog-resolution'
+ * property in the 'platform' node of the guest's machine description.
+ * The largest allowed timeout value is specified by the
+ * 'watchdog-max-timeout' property of the 'platform' node.
+ *
+ * If the 'timeout' argument is not zero, the watchdog timer is set to
+ * expire after a minimum of 'timeout' milliseconds.
+ *
+ * If the 'timeout' argument is zero, the watchdog timer is disabled.
+ *
+ * If the 'timeout' value exceeds the value of the 'max-watchdog-timeout'
+ * property, the hypervisor leaves the watchdog timer state unchanged,
+ * and returns a status of EINVAL.
+ *
+ * The 'time remaining' return value is valid regardless of whether the
+ * return status is EOK or EINVAL.  A non-zero return value indicates the
+ * number of milliseconds that were remaining until the timer was to expire.
+ * If less than one millisecond remains, the return value is '1'.  If the
+ * watchdog timer was disabled at the time of the call, the return value is
+ * zero.
+ *
+ * If the hypervisor cannot support the exact timeout value requested, but
+ * can support a larger timeout value, the hypervisor may round the actual
+ * timeout to a value larger than the requested timeout, consequently the
+ * 'time remaining' return value may be larger than the previously requested
+ * timeout value.
+ *
+ * Any guest OS debugger should be aware that the watchdog service may be in
+ * use.  Consequently, it is recommended that the watchdog service is
+ * disabled upon debugger entry (e.g. reaching a breakpoint), and then
+ * re-enabled upon returning to normal execution.  The API has been designed
+ * with this in mind, and the 'time remaining' result of the disable call may
+ * be used directly as the timeout argument of the re-enable call.
  */
-#define HV_FAST_MACH_GET_SOFT_STATE	0x04
+#define HV_FAST_MACH_SET_WATCHDOG	0x05
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mach_set_watchdog(unsigned long timeout,
+					     unsigned long *orig_timeout);
+#endif
 
 /* CPU services.
  *
@@ -206,8 +231,8 @@
  * FUNCTION:	HV_FAST_CPU_START
  * ARG0:	CPU ID
  * ARG1:	PC
- * ARG1:	RTBA
- * ARG1:	target ARG0
+ * ARG2:	RTBA
+ * ARG3:	target ARG0
  * RET0:	status
  * ERRORS:	ENOCPU		Invalid CPU ID
  *		EINVAL		Target CPU ID is not in the stopped state
@@ -224,6 +249,13 @@
  */
 #define HV_FAST_CPU_START		0x10
 
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_cpu_start(unsigned long cpuid,
+				     unsigned long pc,
+				     unsigned long rtba,
+				     unsigned long arg0);
+#endif
+
 /* cpu_stop()
  * TRAP:	HV_FAST_TRAP
  * FUNCTION:	HV_FAST_CPU_STOP
@@ -245,6 +277,10 @@
  */
 #define HV_FAST_CPU_STOP		0x11
 
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_cpu_stop(unsigned long cpuid);
+#endif
+
 /* cpu_yield()
  * TRAP:	HV_FAST_TRAP
  * FUNCTION:	HV_FAST_CPU_YIELD
@@ -588,6 +624,11 @@
  */
 #define HV_FAST_MMU_TSB_CTX0		0x20
 
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mmu_tsb_ctx0(unsigned long num_descriptions,
+					unsigned long tsb_desc_ra);
+#endif
+
 /* mmu_tsb_ctxnon0()
  * TRAP:	HV_FAST_TRAP
  * FUNCTION:	HV_FAST_MMU_TSB_CTXNON0
@@ -694,6 +735,13 @@
  */
 #define HV_FAST_MMU_MAP_PERM_ADDR	0x25
 
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mmu_map_perm_addr(unsigned long vaddr,
+					     unsigned long set_to_zero,
+					     unsigned long tte,
+					     unsigned long flags);
+#endif
+
 /* mmu_fault_area_conf()
  * TRAP:	HV_FAST_TRAP
  * FUNCTION:	HV_FAST_MMU_FAULT_AREA_CONF
@@ -892,6 +940,10 @@
  */
 #define HV_FAST_TOD_GET			0x50
 
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_tod_get(unsigned long *time);
+#endif
+
 /* tod_set()
  * TRAP:	HV_FAST_TRAP
  * FUNCTION:	HV_FAST_TOD_SET
@@ -905,6 +957,10 @@
  */
 #define HV_FAST_TOD_SET			0x51
 
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_tod_set(unsigned long time);
+#endif
+
 /* Console services */
 
 /* con_getchar()
@@ -988,6 +1044,133 @@
 				     unsigned long *bytes_written);
 #endif
 
+/* mach_set_soft_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MACH_SET_SOFT_STATE
+ * ARG0:	software state
+ * ARG1:	software state description pointer
+ * RET0:	status
+ * ERRORS:	EINVAL		software state not valid or software state
+ *				description is not NULL terminated
+ *		ENORADDR	software state description pointer is not a
+ *				valid real address
+ *		EBADALIGNED	software state description is not correctly
+ *				aligned
+ *
+ * This allows the guest to report it's soft state to the hypervisor.  There
+ * are two primary components to this state.  The first part states whether
+ * the guest software is running or not.  The second containts optional
+ * details specific to the software.
+ *
+ * The software state argument is defined below in HV_SOFT_STATE_*, and
+ * indicates whether the guest is operating normally or in a transitional
+ * state.
+ *
+ * The software state description argument is a real address of a data buffer
+ * of size 32-bytes aligned on a 32-byte boundary.  It is treated as a NULL
+ * terminated 7-bit ASCII string of up to 31 characters not including the
+ * NULL termination.
+ */
+#define HV_FAST_MACH_SET_SOFT_STATE	0x70
+#define  HV_SOFT_STATE_NORMAL		 0x01
+#define  HV_SOFT_STATE_TRANSITION	 0x02
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mach_set_soft_state(unsigned long soft_state,
+					       unsigned long msg_string_ra);
+#endif
+
+/* mach_get_soft_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MACH_GET_SOFT_STATE
+ * ARG0:	software state description pointer
+ * RET0:	status
+ * RET1:	software state
+ * ERRORS:	ENORADDR	software state description pointer is not a
+ *				valid real address
+ *		EBADALIGNED	software state description is not correctly
+ *				aligned
+ *
+ * Retrieve the current value of the guest's software state.  The rules
+ * for the software state pointer are the same as for mach_set_soft_state()
+ * above.
+ */
+#define HV_FAST_MACH_GET_SOFT_STATE	0x71
+
+/* svc_send()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_SEND
+ * ARG0:	service ID
+ * ARG1:	buffer real address
+ * ARG2:	buffer size
+ * RET0:	STATUS
+ * RET1:	sent_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_SEND		0x80
+
+/* svc_recv()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_RECV
+ * ARG0:	service ID
+ * ARG1:	buffer real address
+ * ARG2:	buffer size
+ * RET0:	STATUS
+ * RET1:	recv_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_RECV		0x81
+
+/* svc_getstatus()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_GETSTATUS
+ * ARG0:	service ID
+ * RET0:	STATUS
+ * RET1:	status bits
+ */
+#define HV_FAST_SVC_GETSTATUS		0x82
+
+/* svc_setstatus()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_SETSTATUS
+ * ARG0:	service ID
+ * ARG1:	bits to set
+ * RET0:	STATUS
+ */
+#define HV_FAST_SVC_SETSTATUS		0x83
+
+/* svc_clrstatus()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_CLRSTATUS
+ * ARG0:	service ID
+ * ARG1:	bits to clear
+ * RET0:	STATUS
+ */
+#define HV_FAST_SVC_CLRSTATUS		0x84
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_svc_send(unsigned long svc_id,
+				    unsigned long buffer,
+				    unsigned long buffer_size,
+				    unsigned long *sent_bytes);
+extern unsigned long sun4v_svc_recv(unsigned long svc_id,
+				    unsigned long buffer,
+				    unsigned long buffer_size,
+				    unsigned long *recv_bytes);
+extern unsigned long sun4v_svc_getstatus(unsigned long svc_id,
+					 unsigned long *status_bits);
+extern unsigned long sun4v_svc_setstatus(unsigned long svc_id,
+					 unsigned long status_bits);
+extern unsigned long sun4v_svc_clrstatus(unsigned long svc_id,
+					 unsigned long status_bits);
+#endif
+
 /* Trap trace services.
  *
  * The hypervisor provides a trap tracing capability for privileged
@@ -1379,6 +1562,113 @@
 extern unsigned long sun4v_intr_settarget(unsigned long sysino, unsigned long cpuid);
 #endif
 
+/* vintr_get_cookie()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_GET_COOKIE
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * RET0:	status
+ * RET1:	cookie
+ */
+#define HV_FAST_VINTR_GET_COOKIE	0xa7
+
+/* vintr_set_cookie()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_SET_COOKIE
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * ARG2:	cookie
+ * RET0:	status
+ */
+#define HV_FAST_VINTR_SET_COOKIE	0xa8
+
+/* vintr_get_valid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_GET_VALID
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * RET0:	status
+ * RET1:	valid state
+ */
+#define HV_FAST_VINTR_GET_VALID		0xa9
+
+/* vintr_set_valid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_SET_VALID
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * ARG2:	valid state
+ * RET0:	status
+ */
+#define HV_FAST_VINTR_SET_VALID		0xaa
+
+/* vintr_get_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_GET_STATE
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * RET0:	status
+ * RET1:	state
+ */
+#define HV_FAST_VINTR_GET_STATE		0xab
+
+/* vintr_set_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_SET_STATE
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * ARG2:	state
+ * RET0:	status
+ */
+#define HV_FAST_VINTR_SET_STATE		0xac
+
+/* vintr_get_target()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_GET_TARGET
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * RET0:	status
+ * RET1:	cpuid
+ */
+#define HV_FAST_VINTR_GET_TARGET	0xad
+
+/* vintr_set_target()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_SET_TARGET
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * ARG2:	cpuid
+ * RET0:	status
+ */
+#define HV_FAST_VINTR_SET_TARGET	0xae
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_vintr_get_cookie(unsigned long dev_handle,
+					    unsigned long dev_ino,
+					    unsigned long *cookie);
+extern unsigned long sun4v_vintr_set_cookie(unsigned long dev_handle,
+					    unsigned long dev_ino,
+					    unsigned long cookie);
+extern unsigned long sun4v_vintr_get_valid(unsigned long dev_handle,
+					   unsigned long dev_ino,
+					   unsigned long *valid);
+extern unsigned long sun4v_vintr_set_valid(unsigned long dev_handle,
+					   unsigned long dev_ino,
+					   unsigned long valid);
+extern unsigned long sun4v_vintr_get_state(unsigned long dev_handle,
+					   unsigned long dev_ino,
+					   unsigned long *state);
+extern unsigned long sun4v_vintr_set_state(unsigned long dev_handle,
+					   unsigned long dev_ino,
+					   unsigned long state);
+extern unsigned long sun4v_vintr_get_target(unsigned long dev_handle,
+					    unsigned long dev_ino,
+					    unsigned long *cpuid);
+extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle,
+					    unsigned long dev_ino,
+					    unsigned long cpuid);
+#endif
+
 /* PCI IO services.
  *
  * See the terminology descriptions in the device interrupt services
@@ -2037,6 +2327,348 @@
  */
 #define HV_FAST_PCI_MSG_SETVALID	0xd3
 
+/* Logical Domain Channel services.  */
+
+#define LDC_CHANNEL_DOWN		0
+#define LDC_CHANNEL_UP			1
+#define LDC_CHANNEL_RESETTING		2
+
+/* ldc_tx_qconf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_TX_QCONF
+ * ARG0:	channel ID
+ * ARG1:	real address base of queue
+ * ARG2:	num entries in queue
+ * RET0:	status
+ *
+ * Configure transmit queue for the LDC endpoint specified by the
+ * given channel ID, to be placed at the given real address, and
+ * be of the given num entries.  Num entries must be a power of two.
+ * The real address base of the queue must be aligned on the queue
+ * size.  Each queue entry is 64-bytes, so for example, a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.
+ *
+ * Upon configuration of a valid transmit queue the head and tail
+ * pointers are set to a hypervisor specific identical value indicating
+ * that the queue initially is empty.
+ *
+ * The endpoint's transmit queue is un-configured if num entries is zero.
+ *
+ * The maximum number of entries for each queue for a specific cpu may be
+ * determined from the machine description.  A transmit queue may be
+ * specified even in the event that the LDC is down (peer endpoint has no
+ * receive queue specified).  Transmission will begin as soon as the peer
+ * endpoint defines a receive queue.
+ *
+ * It is recommended that a guest wait for a transmit queue to empty prior
+ * to reconfiguring it, or un-configuring it.  Re or un-configuring of a
+ * non-empty transmit queue behaves exactly as defined above, however it
+ * is undefined as to how many of the pending entries in the original queue
+ * will be delivered prior to the re-configuration taking effect.
+ * Furthermore, as the queue configuration causes a reset of the head and
+ * tail pointers there is no way for a guest to determine how many entries
+ * have been sent after the configuration operation.
+ */
+#define HV_FAST_LDC_TX_QCONF		0xe0
+
+/* ldc_tx_qinfo()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_TX_QINFO
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	real address base of queue
+ * RET2:	num entries in queue
+ *
+ * Return the configuration info for the transmit queue of LDC endpoint
+ * defined by the given channel ID.  The real address is the currently
+ * defined real address base of the defined queue, and num entries is the
+ * size of the queue in terms of number of entries.
+ *
+ * If the specified channel ID is a valid endpoint number, but no transmit
+ * queue has been defined this service will return success, but with num
+ * entries set to zero and the real address will have an undefined value.
+ */
+#define HV_FAST_LDC_TX_QINFO		0xe1
+
+/* ldc_tx_get_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_TX_GET_STATE
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	head offset
+ * RET2:	tail offset
+ * RET3:	channel state
+ *
+ * Return the transmit state, and the head and tail queue pointers, for
+ * the transmit queue of the LDC endpoint defined by the given channel ID.
+ * The head and tail values are the byte offset of the head and tail
+ * positions of the transmit queue for the specified endpoint.
+ */
+#define HV_FAST_LDC_TX_GET_STATE	0xe2
+
+/* ldc_tx_set_qtail()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_TX_SET_QTAIL
+ * ARG0:	channel ID
+ * ARG1:	tail offset
+ * RET0:	status
+ *
+ * Update the tail pointer for the transmit queue associated with the LDC
+ * endpoint defined by the given channel ID.  The tail offset specified
+ * must be aligned on a 64 byte boundary, and calculated so as to increase
+ * the number of pending entries on the transmit queue.  Any attempt to
+ * decrease the number of pending transmit queue entires is considered
+ * an invalid tail offset and will result in an EINVAL error.
+ *
+ * Since the tail of the transmit queue may not be moved backwards, the
+ * transmit queue may be flushed by configuring a new transmit queue,
+ * whereupon the hypervisor will configure the initial transmit head and
+ * tail pointers to be equal.
+ */
+#define HV_FAST_LDC_TX_SET_QTAIL	0xe3
+
+/* ldc_rx_qconf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_RX_QCONF
+ * ARG0:	channel ID
+ * ARG1:	real address base of queue
+ * ARG2:	num entries in queue
+ * RET0:	status
+ *
+ * Configure receive queue for the LDC endpoint specified by the
+ * given channel ID, to be placed at the given real address, and
+ * be of the given num entries.  Num entries must be a power of two.
+ * The real address base of the queue must be aligned on the queue
+ * size.  Each queue entry is 64-bytes, so for example, a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.
+ *
+ * The endpoint's transmit queue is un-configured if num entries is zero.
+ *
+ * If a valid receive queue is specified for a local endpoint the LDC is
+ * in the up state for the purpose of transmission to this endpoint.
+ *
+ * The maximum number of entries for each queue for a specific cpu may be
+ * determined from the machine description.
+ *
+ * As receive queue configuration causes a reset of the queue's head and
+ * tail pointers there is no way for a gues to determine how many entries
+ * have been received between a preceeding ldc_get_rx_state() API call
+ * and the completion of the configuration operation.  It should be noted
+ * that datagram delivery is not guarenteed via domain channels anyway,
+ * and therefore any higher protocol should be resilient to datagram
+ * loss if necessary.  However, to overcome this specific race potential
+ * it is recommended, for example, that a higher level protocol be employed
+ * to ensure either retransmission, or ensure that no datagrams are pending
+ * on the peer endpoint's transmit queue prior to the configuration process.
+ */
+#define HV_FAST_LDC_RX_QCONF		0xe4
+
+/* ldc_rx_qinfo()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_RX_QINFO
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	real address base of queue
+ * RET2:	num entries in queue
+ *
+ * Return the configuration info for the receive queue of LDC endpoint
+ * defined by the given channel ID.  The real address is the currently
+ * defined real address base of the defined queue, and num entries is the
+ * size of the queue in terms of number of entries.
+ *
+ * If the specified channel ID is a valid endpoint number, but no receive
+ * queue has been defined this service will return success, but with num
+ * entries set to zero and the real address will have an undefined value.
+ */
+#define HV_FAST_LDC_RX_QINFO		0xe5
+
+/* ldc_rx_get_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_RX_GET_STATE
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	head offset
+ * RET2:	tail offset
+ * RET3:	channel state
+ *
+ * Return the receive state, and the head and tail queue pointers, for
+ * the receive queue of the LDC endpoint defined by the given channel ID.
+ * The head and tail values are the byte offset of the head and tail
+ * positions of the receive queue for the specified endpoint.
+ */
+#define HV_FAST_LDC_RX_GET_STATE	0xe6
+
+/* ldc_rx_set_qhead()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_RX_SET_QHEAD
+ * ARG0:	channel ID
+ * ARG1:	head offset
+ * RET0:	status
+ *
+ * Update the head pointer for the receive queue associated with the LDC
+ * endpoint defined by the given channel ID.  The head offset specified
+ * must be aligned on a 64 byte boundary, and calculated so as to decrease
+ * the number of pending entries on the receive queue.  Any attempt to
+ * increase the number of pending receive queue entires is considered
+ * an invalid head offset and will result in an EINVAL error.
+ *
+ * The receive queue may be flushed by setting the head offset equal
+ * to the current tail offset.
+ */
+#define HV_FAST_LDC_RX_SET_QHEAD	0xe7
+
+/* LDC Map Table Entry.  Each slot is defined by a translation table
+ * entry, as specified by the LDC_MTE_* bits below, and a 64-bit
+ * hypervisor invalidation cookie.
+ */
+#define LDC_MTE_PADDR	0x0fffffffffffe000 /* pa[55:13]          */
+#define LDC_MTE_COPY_W	0x0000000000000400 /* copy write access  */
+#define LDC_MTE_COPY_R	0x0000000000000200 /* copy read access   */
+#define LDC_MTE_IOMMU_W	0x0000000000000100 /* IOMMU write access */
+#define LDC_MTE_IOMMU_R	0x0000000000000080 /* IOMMU read access  */
+#define LDC_MTE_EXEC	0x0000000000000040 /* execute            */
+#define LDC_MTE_WRITE	0x0000000000000020 /* read               */
+#define LDC_MTE_READ	0x0000000000000010 /* write              */
+#define LDC_MTE_SZALL	0x000000000000000f /* page size bits     */
+#define LDC_MTE_SZ16GB	0x0000000000000007 /* 16GB page          */
+#define LDC_MTE_SZ2GB	0x0000000000000006 /* 2GB page           */
+#define LDC_MTE_SZ256MB	0x0000000000000005 /* 256MB page         */
+#define LDC_MTE_SZ32MB	0x0000000000000004 /* 32MB page          */
+#define LDC_MTE_SZ4MB	0x0000000000000003 /* 4MB page           */
+#define LDC_MTE_SZ512K	0x0000000000000002 /* 512K page          */
+#define LDC_MTE_SZ64K	0x0000000000000001 /* 64K page           */
+#define LDC_MTE_SZ8K	0x0000000000000000 /* 8K page            */
+
+#ifndef __ASSEMBLY__
+struct ldc_mtable_entry {
+	unsigned long	mte;
+	unsigned long	cookie;
+};
+#endif
+
+/* ldc_set_map_table()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_SET_MAP_TABLE
+ * ARG0:	channel ID
+ * ARG1:	table real address
+ * ARG2:	num entries
+ * RET0:	status
+ *
+ * Register the MTE table at the given table real address, with the
+ * specified num entries, for the LDC indicated by the given channel
+ * ID.
+ */
+#define HV_FAST_LDC_SET_MAP_TABLE	0xea
+
+/* ldc_get_map_table()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_GET_MAP_TABLE
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	table real address
+ * RET2:	num entries
+ *
+ * Return the configuration of the current mapping table registered
+ * for the given channel ID.
+ */
+#define HV_FAST_LDC_GET_MAP_TABLE	0xeb
+
+#define LDC_COPY_IN	0
+#define LDC_COPY_OUT	1
+
+/* ldc_copy()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_COPY
+ * ARG0:	channel ID
+ * ARG1:	LDC_COPY_* direction code
+ * ARG2:	target real address
+ * ARG3:	local real address
+ * ARG4:	length in bytes
+ * RET0:	status
+ * RET1:	actual length in bytes
+ */
+#define HV_FAST_LDC_COPY		0xec
+
+#define LDC_MEM_READ	1
+#define LDC_MEM_WRITE	2
+#define LDC_MEM_EXEC	4
+
+/* ldc_mapin()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_MAPIN
+ * ARG0:	channel ID
+ * ARG1:	cookie
+ * RET0:	status
+ * RET1:	real address
+ * RET2:	LDC_MEM_* permissions
+ */
+#define HV_FAST_LDC_MAPIN		0xed
+
+/* ldc_unmap()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_UNMAP
+ * ARG0:	real address
+ * RET0:	status
+ */
+#define HV_FAST_LDC_UNMAP		0xee
+
+/* ldc_revoke()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_REVOKE
+ * ARG0:	channel ID
+ * ARG1:	cookie
+ * ARG2:	ldc_mtable_entry cookie
+ * RET0:	status
+ */
+#define HV_FAST_LDC_REVOKE		0xef
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_ldc_tx_qconf(unsigned long channel,
+					unsigned long ra,
+					unsigned long num_entries);
+extern unsigned long sun4v_ldc_tx_qinfo(unsigned long channel,
+					unsigned long *ra,
+					unsigned long *num_entries);
+extern unsigned long sun4v_ldc_tx_get_state(unsigned long channel,
+					    unsigned long *head_off,
+					    unsigned long *tail_off,
+					    unsigned long *chan_state);
+extern unsigned long sun4v_ldc_tx_set_qtail(unsigned long channel,
+					    unsigned long tail_off);
+extern unsigned long sun4v_ldc_rx_qconf(unsigned long channel,
+					unsigned long ra,
+					unsigned long num_entries);
+extern unsigned long sun4v_ldc_rx_qinfo(unsigned long channel,
+					unsigned long *ra,
+					unsigned long *num_entries);
+extern unsigned long sun4v_ldc_rx_get_state(unsigned long channel,
+					    unsigned long *head_off,
+					    unsigned long *tail_off,
+					    unsigned long *chan_state);
+extern unsigned long sun4v_ldc_rx_set_qhead(unsigned long channel,
+					    unsigned long head_off);
+extern unsigned long sun4v_ldc_set_map_table(unsigned long channel,
+					     unsigned long ra,
+					     unsigned long num_entries);
+extern unsigned long sun4v_ldc_get_map_table(unsigned long channel,
+					     unsigned long *ra,
+					     unsigned long *num_entries);
+extern unsigned long sun4v_ldc_copy(unsigned long channel,
+				    unsigned long dir_code,
+				    unsigned long tgt_raddr,
+				    unsigned long lcl_raddr,
+				    unsigned long len,
+				    unsigned long *actual_len);
+extern unsigned long sun4v_ldc_mapin(unsigned long channel,
+				     unsigned long cookie,
+				     unsigned long *ra,
+				     unsigned long *perm);
+extern unsigned long sun4v_ldc_unmap(unsigned long ra);
+extern unsigned long sun4v_ldc_revoke(unsigned long channel,
+				      unsigned long cookie,
+				      unsigned long mte_cookie);
+#endif
+
 /* Performance counter services.  */
 
 #define HV_PERF_JBUS_PERF_CTRL_REG	0x00
@@ -2168,6 +2800,105 @@
  */
 #define HV_FAST_MMUSTAT_INFO		0x103
 
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mmustat_conf(unsigned long ra, unsigned long *orig_ra);
+extern unsigned long sun4v_mmustat_info(unsigned long *ra);
+#endif
+
+/* NCS crypto services  */
+
+/* ncs_request() sub-function numbers */
+#define HV_NCS_QCONF			0x01
+#define HV_NCS_QTAIL_UPDATE		0x02
+
+#ifndef __ASSEMBLY__
+struct hv_ncs_queue_entry {
+	/* MAU Control Register */
+	unsigned long	mau_control;
+#define MAU_CONTROL_INV_PARITY	0x0000000000002000
+#define MAU_CONTROL_STRAND	0x0000000000001800
+#define MAU_CONTROL_BUSY	0x0000000000000400
+#define MAU_CONTROL_INT		0x0000000000000200
+#define MAU_CONTROL_OP		0x00000000000001c0
+#define MAU_CONTROL_OP_SHIFT	6
+#define MAU_OP_LOAD_MA_MEMORY	0x0
+#define MAU_OP_STORE_MA_MEMORY	0x1
+#define MAU_OP_MODULAR_MULT	0x2
+#define MAU_OP_MODULAR_REDUCE	0x3
+#define MAU_OP_MODULAR_EXP_LOOP	0x4
+#define MAU_CONTROL_LEN		0x000000000000003f
+#define MAU_CONTROL_LEN_SHIFT	0
+
+	/* Real address of bytes to load or store bytes
+	 * into/out-of the MAU.
+	 */
+	unsigned long	mau_mpa;
+
+	/* Modular Arithmetic MA Offset Register.  */
+	unsigned long	mau_ma;
+
+	/* Modular Arithmetic N Prime Register.  */
+	unsigned long	mau_np;
+};
+
+struct hv_ncs_qconf_arg {
+	unsigned long	mid;      /* MAU ID, 1 per core on Niagara */
+	unsigned long	base;     /* Real address base of queue */
+	unsigned long	end;	  /* Real address end of queue */
+	unsigned long	num_ents; /* Number of entries in queue */
+};
+
+struct hv_ncs_qtail_update_arg {
+	unsigned long	mid;      /* MAU ID, 1 per core on Niagara */
+	unsigned long	tail;     /* New tail index to use */
+	unsigned long	syncflag; /* only SYNCFLAG_SYNC is implemented */
+#define HV_NCS_SYNCFLAG_SYNC	0x00
+#define HV_NCS_SYNCFLAG_ASYNC	0x01
+};
+#endif
+
+/* ncs_request()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_NCS_REQUEST
+ * ARG0:	NCS sub-function
+ * ARG1:	sub-function argument real address
+ * ARG2:	size in bytes of sub-function argument
+ * RET0:	status
+ *
+ * The MAU chip of the Niagara processor is not directly accessible
+ * to privileged code, instead it is programmed indirectly via this
+ * hypervisor API.
+ *
+ * The interfaces defines a queue of MAU operations to perform.
+ * Privileged code registers a queue with the hypervisor by invoking
+ * this HVAPI with the HV_NCS_QCONF sub-function, which defines the
+ * base, end, and number of entries of the queue.  Each queue entry
+ * contains a MAU register struct block.
+ *
+ * The privileged code then proceeds to add entries to the queue and
+ * then invoke the HV_NCS_QTAIL_UPDATE sub-function.  Since only
+ * synchronous operations are supported by the current hypervisor,
+ * HV_NCS_QTAIL_UPDATE will run all the pending queue entries to
+ * completion and return HV_EOK, or return an error code.
+ *
+ * The real address of the sub-function argument must be aligned on at
+ * least an 8-byte boundary.
+ *
+ * The tail argument of HV_NCS_QTAIL_UPDATE is an index, not a byte
+ * offset, into the queue and must be less than or equal the 'num_ents'
+ * argument given in the HV_NCS_QCONF call.
+ */
+#define HV_FAST_NCS_REQUEST		0x110
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_ncs_request(unsigned long request,
+				       unsigned long arg_ra,
+				       unsigned long arg_size);
+#endif
+
+#define HV_FAST_FIRE_GET_PERFREG	0x120
+#define HV_FAST_FIRE_SET_PERFREG	0x121
+
 /* Function numbers for HV_CORE_TRAP.  */
 #define HV_CORE_SET_VER			0x00
 #define HV_CORE_PUTCHAR			0x01
@@ -2204,6 +2935,7 @@
 extern int sun4v_hvapi_get(unsigned long group,
 			   unsigned long *major,
 			   unsigned long *minor);
+extern void sun4v_hvapi_init(void);
 #endif
 
 #endif /* !(_SPARC64_HYPERVISOR_H) */
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index 5d233b4..e6c436e 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -46,12 +46,15 @@
 #define irq_canonicalize(irq)	(irq)
 extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
 extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
+extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino);
 extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
 				    unsigned int msi_devino_start,
 				    unsigned int msi_devino_end);
 extern void sun4v_destroy_msi(unsigned int virt_irq);
 extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
 
+extern void fixup_irqs(void);
+
 static __inline__ void set_softint(unsigned long bits)
 {
 	__asm__ __volatile__("wr	%0, 0x0, %%set_softint"
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index 627e339..9974c7b 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -32,7 +32,6 @@
 	DIE_TRAP,
 	DIE_TRAP_TL1,
 	DIE_CALL,
-	DIE_PAGE_FAULT,
 };
 
 #endif
diff --git a/include/asm-sparc64/ldc.h b/include/asm-sparc64/ldc.h
new file mode 100644
index 0000000..bdb524a
--- /dev/null
+++ b/include/asm-sparc64/ldc.h
@@ -0,0 +1,138 @@
+#ifndef _SPARC64_LDC_H
+#define _SPARC64_LDC_H
+
+#include <asm/hypervisor.h>
+
+extern int ldom_domaining_enabled;
+extern void ldom_set_var(const char *var, const char *value);
+extern void ldom_reboot(const char *boot_command);
+extern void ldom_power_off(void);
+
+/* The event handler will be evoked when link state changes
+ * or data becomes available on the receive side.
+ *
+ * For non-RAW links, if the LDC_EVENT_RESET event arrives the
+ * driver should reset all of it's internal state and reinvoke
+ * ldc_connect() to try and bring the link up again.
+ *
+ * For RAW links, ldc_connect() is not used.  Instead the driver
+ * just waits for the LDC_EVENT_UP event.
+ */
+struct ldc_channel_config {
+	void (*event)(void *arg, int event);
+
+	u32			mtu;
+	unsigned int		rx_irq;
+	unsigned int		tx_irq;
+	u8			mode;
+#define LDC_MODE_RAW		0x00
+#define LDC_MODE_UNRELIABLE	0x01
+#define LDC_MODE_RESERVED	0x02
+#define LDC_MODE_STREAM		0x03
+
+	u8			debug;
+#define LDC_DEBUG_HS		0x01
+#define LDC_DEBUG_STATE		0x02
+#define LDC_DEBUG_RX		0x04
+#define LDC_DEBUG_TX		0x08
+#define LDC_DEBUG_DATA		0x10
+};
+
+#define LDC_EVENT_RESET		0x01
+#define LDC_EVENT_UP		0x02
+#define LDC_EVENT_DATA_READY	0x04
+
+#define LDC_STATE_INVALID	0x00
+#define LDC_STATE_INIT		0x01
+#define LDC_STATE_BOUND		0x02
+#define LDC_STATE_READY		0x03
+#define LDC_STATE_CONNECTED	0x04
+
+struct ldc_channel;
+
+/* Allocate state for a channel.  */
+extern struct ldc_channel *ldc_alloc(unsigned long id,
+				     const struct ldc_channel_config *cfgp,
+				     void *event_arg);
+
+/* Shut down and free state for a channel.  */
+extern void ldc_free(struct ldc_channel *lp);
+
+/* Register TX and RX queues of the link with the hypervisor.  */
+extern int ldc_bind(struct ldc_channel *lp, const char *name);
+
+/* For non-RAW protocols we need to complete a handshake before
+ * communication can proceed.  ldc_connect() does that, if the
+ * handshake completes successfully, an LDC_EVENT_UP event will
+ * be sent up to the driver.
+ */
+extern int ldc_connect(struct ldc_channel *lp);
+extern int ldc_disconnect(struct ldc_channel *lp);
+
+extern int ldc_state(struct ldc_channel *lp);
+
+/* Read and write operations.  Only valid when the link is up.  */
+extern int ldc_write(struct ldc_channel *lp, const void *buf,
+		     unsigned int size);
+extern int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size);
+
+#define LDC_MAP_SHADOW	0x01
+#define LDC_MAP_DIRECT	0x02
+#define LDC_MAP_IO	0x04
+#define LDC_MAP_R	0x08
+#define LDC_MAP_W	0x10
+#define LDC_MAP_X	0x20
+#define LDC_MAP_RW	(LDC_MAP_R | LDC_MAP_W)
+#define LDC_MAP_RWX	(LDC_MAP_R | LDC_MAP_W | LDC_MAP_X)
+#define LDC_MAP_ALL	0x03f
+
+struct ldc_trans_cookie {
+	u64			cookie_addr;
+	u64			cookie_size;
+};
+
+struct scatterlist;
+extern int ldc_map_sg(struct ldc_channel *lp,
+		      struct scatterlist *sg, int num_sg,
+		      struct ldc_trans_cookie *cookies, int ncookies,
+		      unsigned int map_perm);
+
+extern int ldc_map_single(struct ldc_channel *lp,
+			  void *buf, unsigned int len,
+			  struct ldc_trans_cookie *cookies, int ncookies,
+			  unsigned int map_perm);
+
+extern void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+		      int ncookies);
+
+extern int ldc_copy(struct ldc_channel *lp, int copy_dir,
+		    void *buf, unsigned int len, unsigned long offset,
+		    struct ldc_trans_cookie *cookies, int ncookies);
+
+static inline int ldc_get_dring_entry(struct ldc_channel *lp,
+				      void *buf, unsigned int len,
+				      unsigned long offset,
+				      struct ldc_trans_cookie *cookies,
+				      int ncookies)
+{
+	return ldc_copy(lp, LDC_COPY_IN, buf, len, offset, cookies, ncookies);
+}
+
+static inline int ldc_put_dring_entry(struct ldc_channel *lp,
+				      void *buf, unsigned int len,
+				      unsigned long offset,
+				      struct ldc_trans_cookie *cookies,
+				      int ncookies)
+{
+	return ldc_copy(lp, LDC_COPY_OUT, buf, len, offset, cookies, ncookies);
+}
+
+extern void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+				 struct ldc_trans_cookie *cookies,
+				 int *ncookies, unsigned int map_perm);
+
+extern void ldc_free_exp_dring(struct ldc_channel *lp, void *buf,
+			       unsigned int len,
+			       struct ldc_trans_cookie *cookies, int ncookies);
+
+#endif /* _SPARC64_LDC_H */
diff --git a/include/asm-sparc64/mdesc.h b/include/asm-sparc64/mdesc.h
new file mode 100644
index 0000000..e97c431
--- /dev/null
+++ b/include/asm-sparc64/mdesc.h
@@ -0,0 +1,68 @@
+#ifndef _SPARC64_MDESC_H
+#define _SPARC64_MDESC_H
+
+#include <linux/types.h>
+#include <linux/cpumask.h>
+#include <asm/prom.h>
+
+struct mdesc_handle;
+
+/* Machine description operations are to be surrounded by grab and
+ * release calls.  The mdesc_handle returned from the grab is
+ * the first argument to all of the operational calls that work
+ * on mdescs.
+ */
+extern struct mdesc_handle *mdesc_grab(void);
+extern void mdesc_release(struct mdesc_handle *);
+
+#define MDESC_NODE_NULL		(~(u64)0)
+
+extern u64 mdesc_node_by_name(struct mdesc_handle *handle,
+			      u64 from_node, const char *name);
+#define mdesc_for_each_node_by_name(__hdl, __node, __name) \
+	for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \
+	     (__node) != MDESC_NODE_NULL; \
+	     __node = mdesc_node_by_name(__hdl, __node, __name))
+
+/* Access to property values returned from mdesc_get_property() are
+ * only valid inside of a mdesc_grab()/mdesc_release() sequence.
+ * Once mdesc_release() is called, the memory backed up by these
+ * pointers may reference freed up memory.
+ *
+ * Therefore callers must make copies of any property values
+ * they need.
+ *
+ * These same rules apply to mdesc_node_name().
+ */
+extern const void *mdesc_get_property(struct mdesc_handle *handle,
+				      u64 node, const char *name, int *lenp);
+extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
+
+/* MD arc iteration, the standard sequence is:
+ *
+ *	unsigned long arc;
+ *	mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
+ *		unsigned long target = mdesc_arc_target(handle, arc);
+ *		...
+ *	}
+ */
+
+#define MDESC_ARC_TYPE_FWD	"fwd"
+#define MDESC_ARC_TYPE_BACK	"back"
+
+extern u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from,
+			  const char *arc_type);
+#define mdesc_for_each_arc(__arc, __hdl, __node, __type) \
+	for (__arc = mdesc_next_arc(__hdl, __node, __type); \
+	     (__arc) != MDESC_NODE_NULL; \
+	     __arc = mdesc_next_arc(__hdl, __arc, __type))
+
+extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
+
+extern void mdesc_update(void);
+
+extern void mdesc_fill_in_cpu_data(cpumask_t mask);
+
+extern void sun4v_mdesc_init(void);
+
+#endif
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
index 8d12903..9fc225e 100644
--- a/include/asm-sparc64/mmu_context.h
+++ b/include/asm-sparc64/mmu_context.h
@@ -76,6 +76,9 @@
 	unsigned long ctx_valid, flags;
 	int cpu;
 
+	if (unlikely(mm == &init_mm))
+		return;
+
 	spin_lock_irqsave(&mm->context.lock, flags);
 	ctx_valid = CTX_VALID(mm->context);
 	if (!ctx_valid)
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index 6a0da3b..992f9f7 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -316,11 +316,8 @@
 			
 extern int prom_pathtoinode(const char *path);
 extern int prom_inst2pkg(int);
-
-/* CPU probing helpers.  */
-struct device_node;
-int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid);
-int cpu_find_by_mid(int mid, struct device_node **prom_node);
+extern int prom_service_exists(const char *service_name);
+extern void prom_sun4v_guest_soft_state(void);
 
 /* Client interface level routines. */
 extern void prom_set_trap_table(unsigned long tba);
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
index 6340a52..23cc63f 100644
--- a/include/asm-sparc64/parport.h
+++ b/include/asm-sparc64/parport.h
@@ -145,7 +145,7 @@
 			 */
 			if (parport_pc_probe_port(base, base + 0x400,
 						  child->irq, PARPORT_DMA_NOFIFO,
-						  child->bus->self))
+						  &child->bus->self->dev))
 				count++;
 		}
 	}
@@ -199,7 +199,8 @@
 
 				if (parport_pc_probe_port(base, base + 0x400,
 							  edev->irqs[0],
-							  count, ebus->self))
+							  count,
+							  &ebus->self->dev))
 					count++;
 			}
 		}
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
index 47cea16..e11ac10 100644
--- a/include/asm-sparc64/pci.h
+++ b/include/asm-sparc64/pci.h
@@ -206,49 +206,6 @@
 #define PCI64_REQUIRED_MASK	(~(dma64_addr_t)0)
 #define PCI64_ADDR_BASE		0xfffc000000000000UL
 
-/* Usage of the pci_dac_foo interfaces is only valid if this
- * test passes.
- */
-#define pci_dac_dma_supported(pci_dev, mask) \
-	((((mask) & PCI64_REQUIRED_MASK) == PCI64_REQUIRED_MASK) ? 1 : 0)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
-	return (PCI64_ADDR_BASE +
-		__pa(page_address(page)) + offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	unsigned long paddr = (dma_addr & PAGE_MASK) - PCI64_ADDR_BASE;
-
-	return virt_to_page(__va(paddr));
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-	/* DAC cycle addressing does not make use of the
-	 * PCI controller's streaming cache, so nothing to do.
-	 */
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-	/* DAC cycle addressing does not make use of the
-	 * PCI controller's streaming cache, so nothing to do.
-	 */
-}
-
 #define PCI_DMA_ERROR_CODE	(~(dma_addr_t)0x0)
 
 static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
@@ -303,10 +260,6 @@
 
 extern struct resource *pcibios_select_root(struct pci_dev *, struct resource *);
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
 	return PCI_IRQ_NONE;
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index ced8cbd..88db872 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -5,7 +5,8 @@
 
 #ifdef CONFIG_SMP
 
-extern void setup_per_cpu_areas(void);
+#define setup_per_cpu_areas()			do { } while (0)
+extern void real_setup_per_cpu_areas(void);
 
 extern unsigned long __per_cpu_base;
 extern unsigned long __per_cpu_shift;
@@ -34,6 +35,7 @@
 } while (0)
 #else /* ! SMP */
 
+#define real_setup_per_cpu_areas()		do { } while (0)
 #define DEFINE_PER_CPU(type, name) \
     __typeof__(type) per_cpu__##name
 
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 9e80ad4..0393380 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -573,24 +573,6 @@
 	return (pte_val(pte) & mask);
 }
 
-static inline unsigned long pte_read(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	mov		%1, %0\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%2), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_READ_4U), "i" (_PAGE_READ_4V));
-
-	return (pte_val(pte) & mask);
-}
-
 static inline unsigned long pte_file(pte_t pte)
 {
 	unsigned long val = pte_val(pte);
diff --git a/include/asm-sparc64/power.h b/include/asm-sparc64/power.h
new file mode 100644
index 0000000..94495c1
--- /dev/null
+++ b/include/asm-sparc64/power.h
@@ -0,0 +1,7 @@
+#ifndef _SPARC64_POWER_H
+#define _SPARC64_POWER_H
+
+extern void wake_up_powerd(void);
+extern int start_powerd(void);
+
+#endif /* !(_SPARC64_POWER_H) */
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h
index ddad5f9..b4df304 100644
--- a/include/asm-sparc64/prom.h
+++ b/include/asm-sparc64/prom.h
@@ -90,6 +90,7 @@
 	const char *type, const char *compat);
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
+extern struct device_node *of_find_node_by_cpuid(int cpuid);
 extern struct device_node *of_get_parent(const struct device_node *node);
 extern struct device_node *of_get_next_child(const struct device_node *node,
 					     struct device_node *prev);
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index 869d16f..e8a96a3 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -29,10 +29,9 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-extern cpumask_t phys_cpu_present_map;
-#define cpu_possible_map phys_cpu_present_map
-
 extern cpumask_t cpu_sibling_map[NR_CPUS];
+extern cpumask_t cpu_core_map[NR_CPUS];
+extern int sparc64_multi_core;
 
 /*
  *	General functions that each host system must provide.
@@ -41,16 +40,20 @@
 extern int hard_smp_processor_id(void);
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
-extern void smp_setup_cpu_possible_map(void);
-extern unsigned char boot_cpu_id;
+extern void smp_fill_in_sib_core_maps(void);
+extern void cpu_play_dead(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
+#endif
 
 #endif /* !(__ASSEMBLY__) */
 
 #else
 
 #define hard_smp_processor_id()		0
-#define smp_setup_cpu_possible_map() do { } while (0)
-#define boot_cpu_id	(0)
+#define smp_fill_in_sib_core_maps() do { } while (0)
 
 #endif /* !(CONFIG_SMP) */
 
diff --git a/include/asm-sparc64/sstate.h b/include/asm-sparc64/sstate.h
new file mode 100644
index 0000000..a7c35db
--- /dev/null
+++ b/include/asm-sparc64/sstate.h
@@ -0,0 +1,13 @@
+#ifndef _SPARC64_SSTATE_H
+#define _SPARC64_SSTATE_H
+
+extern void sstate_booting(void);
+extern void sstate_running(void);
+extern void sstate_halt(void);
+extern void sstate_poweroff(void);
+extern void sstate_panic(void);
+extern void sstate_reboot(void);
+
+extern void sun4v_sstate_init(void);
+
+#endif /* _SPARC64_SSTATE_H */
diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
index 2ebf7f2..98252cd 100644
--- a/include/asm-sparc64/thread_info.h
+++ b/include/asm-sparc64/thread_info.h
@@ -38,8 +38,8 @@
 	/* D$ line 1 */
 	struct task_struct	*task;
 	unsigned long		flags;
-	__u8			cpu;
 	__u8			fpsaved[7];
+	__u8			pad;
 	unsigned long		ksp;
 
 	/* D$ line 2 */
@@ -49,7 +49,7 @@
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	__u8			new_child;
 	__u8			syscall_noerror;
-	__u16			__pad;
+	__u16			cpu;
 
 	unsigned long		*utraps;
 
@@ -83,8 +83,7 @@
 #define TI_CURRENT_DS	(TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
 #define TI_FPDEPTH	(TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
 #define TI_WSAVED	(TI_FLAGS + TI_FLAG_BYTE_WSAVED)
-#define TI_CPU		0x00000010
-#define TI_FPSAVED	0x00000011
+#define TI_FPSAVED	0x00000010
 #define TI_KSP		0x00000018
 #define TI_FAULT_ADDR	0x00000020
 #define TI_KREGS	0x00000028
@@ -92,6 +91,7 @@
 #define TI_PRE_COUNT	0x00000038
 #define TI_NEW_CHILD	0x0000003c
 #define TI_SYS_NOERROR	0x0000003d
+#define TI_CPU		0x0000003e
 #define TI_UTRAPS	0x00000040
 #define TI_REG_WINDOW	0x00000048
 #define TI_RWIN_SPTRS	0x000003c8	
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
index 7af1e11..349d1d3 100644
--- a/include/asm-sparc64/tlb.h
+++ b/include/asm-sparc64/tlb.h
@@ -2,6 +2,7 @@
 #define _SPARC64_TLB_H
 
 #include <linux/swap.h>
+#include <linux/pagemap.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
index 98a6c61..290ac75 100644
--- a/include/asm-sparc64/topology.h
+++ b/include/asm-sparc64/topology.h
@@ -1,9 +1,17 @@
 #ifndef _ASM_SPARC64_TOPOLOGY_H
 #define _ASM_SPARC64_TOPOLOGY_H
 
-#include <asm/spitfire.h>
-#define smt_capable()	(tlb_type == hypervisor)
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu)	(cpu_data(cpu).proc_id)
+#define topology_core_id(cpu)			(cpu_data(cpu).core_id)
+#define topology_core_siblings(cpu)		(cpu_core_map[cpu])
+#define topology_thread_siblings(cpu)		(cpu_sibling_map[cpu])
+#define mc_capable()				(sparc64_multi_core)
+#define smt_capable()				(sparc64_multi_core)
+#endif /* CONFIG_SMP */
 
 #include <asm-generic/topology.h>
 
+#define cpu_coregroup_map(cpu)			(cpu_core_map[cpu])
+
 #endif /* _ASM_SPARC64_TOPOLOGY_H */
diff --git a/include/asm-sparc64/tsb.h b/include/asm-sparc64/tsb.h
index ab55ffc..76e4299 100644
--- a/include/asm-sparc64/tsb.h
+++ b/include/asm-sparc64/tsb.h
@@ -271,7 +271,7 @@
 #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
 	sethi		%hi(swapper_4m_tsb), REG1; \
 	or		REG1, %lo(swapper_4m_tsb), REG1; \
-	and		TAG, (KERNEL_TSB_NENTRIES - 1), REG2; \
+	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \
 	add		REG1, REG2, REG2; \
 	KTSB_LOAD_QUAD(REG2, REG3); \
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
new file mode 100644
index 0000000..83c9642
--- /dev/null
+++ b/include/asm-sparc64/vio.h
@@ -0,0 +1,404 @@
+#ifndef _SPARC64_VIO_H
+#define _SPARC64_VIO_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+
+#include <asm/ldc.h>
+#include <asm/mdesc.h>
+
+struct vio_msg_tag {
+	u8			type;
+#define VIO_TYPE_CTRL		0x01
+#define VIO_TYPE_DATA		0x02
+#define VIO_TYPE_ERR		0x04
+
+	u8			stype;
+#define VIO_SUBTYPE_INFO	0x01
+#define VIO_SUBTYPE_ACK		0x02
+#define VIO_SUBTYPE_NACK	0x04
+
+	u16			stype_env;
+#define VIO_VER_INFO		0x0001
+#define VIO_ATTR_INFO		0x0002
+#define VIO_DRING_REG		0x0003
+#define VIO_DRING_UNREG		0x0004
+#define VIO_RDX			0x0005
+#define VIO_PKT_DATA		0x0040
+#define VIO_DESC_DATA		0x0041
+#define VIO_DRING_DATA		0x0042
+#define VNET_MCAST_INFO		0x0101
+
+	u32		sid;
+};
+
+struct vio_rdx {
+	struct vio_msg_tag	tag;
+	u64			resv[6];
+};
+
+struct vio_ver_info {
+	struct vio_msg_tag	tag;
+	u16			major;
+	u16			minor;
+	u8			dev_class;
+#define VDEV_NETWORK		0x01
+#define VDEV_NETWORK_SWITCH	0x02
+#define VDEV_DISK		0x03
+#define VDEV_DISK_SERVER	0x04
+
+	u8			resv1[3];
+	u64			resv2[5];
+};
+
+struct vio_dring_register {
+	struct vio_msg_tag	tag;
+	u64			dring_ident;
+	u32			num_descr;
+	u32			descr_size;
+	u16			options;
+#define VIO_TX_DRING		0x0001
+#define VIO_RX_DRING		0x0002
+	u16			resv;
+	u32			num_cookies;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+struct vio_dring_unregister {
+	struct vio_msg_tag	tag;
+	u64			dring_ident;
+	u64			resv[5];
+};
+
+/* Data transfer modes */
+#define VIO_PKT_MODE		0x01 /* Packet based transfer	*/
+#define VIO_DESC_MODE		0x02 /* In-band descriptors	*/
+#define VIO_DRING_MODE		0x03 /* Descriptor rings	*/
+
+struct vio_dring_data {
+	struct vio_msg_tag	tag;
+	u64			seq;
+	u64			dring_ident;
+	u32			start_idx;
+	u32			end_idx;
+	u8			state;
+#define VIO_DRING_ACTIVE	0x01
+#define VIO_DRING_STOPPED	0x02
+
+	u8			__pad1;
+	u16			__pad2;
+	u32			__pad3;
+	u64			__par4[2];
+};
+
+struct vio_dring_hdr {
+	u8			state;
+#define VIO_DESC_FREE		0x01
+#define VIO_DESC_READY		0x02
+#define VIO_DESC_ACCEPTED	0x03
+#define VIO_DESC_DONE		0x04
+	u8			ack;
+#define VIO_ACK_ENABLE		0x01
+#define VIO_ACK_DISABLE		0x00
+
+	u16			__pad1;
+	u32			__pad2;
+};
+
+/* VIO disk specific structures and defines */
+struct vio_disk_attr_info {
+	struct vio_msg_tag	tag;
+	u8			xfer_mode;
+	u8			vdisk_type;
+#define VD_DISK_TYPE_SLICE	0x01 /* Slice in block device	*/
+#define VD_DISK_TYPE_DISK	0x02 /* Entire block device	*/
+	u16			resv1;
+	u32			vdisk_block_size;
+	u64			operations;
+	u64			vdisk_size;
+	u64			max_xfer_size;
+	u64			resv2[2];
+};
+
+struct vio_disk_desc {
+	struct vio_dring_hdr	hdr;
+	u64			req_id;
+	u8			operation;
+#define VD_OP_BREAD		0x01 /* Block read			*/
+#define VD_OP_BWRITE		0x02 /* Block write			*/
+#define VD_OP_FLUSH		0x03 /* Flush disk contents		*/
+#define VD_OP_GET_WCE		0x04 /* Get write-cache status		*/
+#define VD_OP_SET_WCE		0x05 /* Enable/disable write-cache	*/
+#define VD_OP_GET_VTOC		0x06 /* Get VTOC			*/
+#define VD_OP_SET_VTOC		0x07 /* Set VTOC			*/
+#define VD_OP_GET_DISKGEOM	0x08 /* Get disk geometry		*/
+#define VD_OP_SET_DISKGEOM	0x09 /* Set disk geometry		*/
+#define VD_OP_SCSICMD		0x0a /* SCSI control command		*/
+#define VD_OP_GET_DEVID		0x0b /* Get device ID			*/
+#define VD_OP_GET_EFI		0x0c /* Get EFI				*/
+#define VD_OP_SET_EFI		0x0d /* Set EFI				*/
+	u8			slice;
+	u16			resv1;
+	u32			status;
+	u64			offset;
+	u64			size;
+	u32			ncookies;
+	u32			resv2;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+#define VIO_DISK_VNAME_LEN	8
+#define VIO_DISK_ALABEL_LEN	128
+#define VIO_DISK_NUM_PART	8
+
+struct vio_disk_vtoc {
+	u8			volume_name[VIO_DISK_VNAME_LEN];
+	u16			sector_size;
+	u16			num_partitions;
+	u8			ascii_label[VIO_DISK_ALABEL_LEN];
+	struct {
+		u16		id;
+		u16		perm_flags;
+		u32		resv;
+		u64		start_block;
+		u64		num_blocks;
+	} partitions[VIO_DISK_NUM_PART];
+};
+
+struct vio_disk_geom {
+	u16			num_cyl; /* Num data cylinders		*/
+	u16			alt_cyl; /* Num alternate cylinders	*/
+	u16			beg_cyl; /* Cyl off of fixed head area	*/
+	u16			num_hd;  /* Num heads			*/
+	u16			num_sec; /* Num sectors			*/
+	u16			ifact;   /* Interleave factor		*/
+	u16			apc;     /* Alts per cylinder (SCSI)	*/
+	u16			rpm;	 /* Revolutions per minute	*/
+	u16			phy_cyl; /* Num physical cylinders	*/
+	u16			wr_skip; /* Num sects to skip, writes	*/
+	u16			rd_skip; /* Num sects to skip, writes	*/
+};
+
+struct vio_disk_devid {
+	u16			resv;
+	u16			type;
+	u32			len;
+	char			id[0];
+};
+
+struct vio_disk_efi {
+	u64			lba;
+	u64			len;
+	char			data[0];
+};
+
+/* VIO net specific structures and defines */
+struct vio_net_attr_info {
+	struct vio_msg_tag	tag;
+	u8			xfer_mode;
+	u8			addr_type;
+#define VNET_ADDR_ETHERMAC	0x01
+	u16			ack_freq;
+	u32			resv1;
+	u64			addr;
+	u64			mtu;
+	u64			resv2[3];
+};
+
+#define VNET_NUM_MCAST		7
+
+struct vio_net_mcast_info {
+	struct vio_msg_tag	tag;
+	u8			set;
+	u8			count;
+	u8			mcast_addr[VNET_NUM_MCAST * 6];
+	u32			resv;
+};
+
+struct vio_net_desc {
+	struct vio_dring_hdr	hdr;
+	u32			size;
+	u32			ncookies;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+#define VIO_MAX_RING_COOKIES	24
+
+struct vio_dring_state {
+	u64			ident;
+	void			*base;
+	u64			snd_nxt;
+	u64			rcv_nxt;
+	u32			entry_size;
+	u32			num_entries;
+	u32			prod;
+	u32			cons;
+	u32			pending;
+	int			ncookies;
+	struct ldc_trans_cookie	cookies[VIO_MAX_RING_COOKIES];
+};
+
+static inline void *vio_dring_cur(struct vio_dring_state *dr)
+{
+	return dr->base + (dr->entry_size * dr->prod);
+}
+
+static inline void *vio_dring_entry(struct vio_dring_state *dr,
+				    unsigned int index)
+{
+	return dr->base + (dr->entry_size * index);
+}
+
+static inline u32 vio_dring_avail(struct vio_dring_state *dr,
+				  unsigned int ring_size)
+{
+	/* Ensure build-time power-of-2.  */
+	BUILD_BUG_ON(ring_size & (ring_size - 1));
+
+	return (dr->pending -
+		((dr->prod - dr->cons) & (ring_size - 1)));
+}
+
+#define VIO_MAX_TYPE_LEN	64
+#define VIO_MAX_COMPAT_LEN	64
+
+struct vio_dev {
+	u64			mp;
+	struct device_node	*dp;
+
+	char			type[VIO_MAX_TYPE_LEN];
+	char			compat[VIO_MAX_COMPAT_LEN];
+	int			compat_len;
+
+	unsigned long		channel_id;
+
+	unsigned int		tx_irq;
+	unsigned int		rx_irq;
+
+	struct device		dev;
+};
+
+struct vio_driver {
+	struct list_head		node;
+	const struct vio_device_id	*id_table;
+	int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
+	int (*remove)(struct vio_dev *dev);
+	void (*shutdown)(struct vio_dev *dev);
+	unsigned long			driver_data;
+	struct device_driver		driver;
+};
+
+struct vio_version {
+	u16		major;
+	u16		minor;
+};
+
+struct vio_driver_state;
+struct vio_driver_ops {
+	int	(*send_attr)(struct vio_driver_state *vio);
+	int	(*handle_attr)(struct vio_driver_state *vio, void *pkt);
+	void	(*handshake_complete)(struct vio_driver_state *vio);
+};
+
+struct vio_completion {
+	struct completion	com;
+	int			err;
+	int			waiting_for;
+};
+
+struct vio_driver_state {
+	/* Protects VIO handshake and, optionally, driver private state.  */
+	spinlock_t		lock;
+
+	struct ldc_channel	*lp;
+
+	u32			_peer_sid;
+	u32			_local_sid;
+	struct vio_dring_state	drings[2];
+#define VIO_DRIVER_TX_RING	0
+#define VIO_DRIVER_RX_RING	1
+
+	u8			hs_state;
+#define VIO_HS_INVALID		0x00
+#define VIO_HS_GOTVERS		0x01
+#define VIO_HS_GOT_ATTR		0x04
+#define VIO_HS_SENT_DREG	0x08
+#define VIO_HS_SENT_RDX		0x10
+#define VIO_HS_GOT_RDX_ACK	0x20
+#define VIO_HS_GOT_RDX		0x40
+#define VIO_HS_SENT_RDX_ACK	0x80
+#define VIO_HS_COMPLETE		(VIO_HS_GOT_RDX_ACK | VIO_HS_SENT_RDX_ACK)
+
+	u8			dev_class;
+
+	u8			dr_state;
+#define VIO_DR_STATE_TXREG	0x01
+#define VIO_DR_STATE_RXREG	0x02
+#define VIO_DR_STATE_TXREQ	0x10
+#define VIO_DR_STATE_RXREQ	0x20
+
+	u8			debug;
+#define VIO_DEBUG_HS		0x01
+#define VIO_DEBUG_DATA		0x02
+
+	void			*desc_buf;
+	unsigned int		desc_buf_len;
+
+	struct vio_completion	*cmp;
+
+	struct vio_dev		*vdev;
+
+	struct timer_list	timer;
+
+	struct vio_version	ver;
+
+	struct vio_version	*ver_table;
+	int			ver_table_entries;
+
+	char			*name;
+
+	struct vio_driver_ops	*ops;
+};
+
+#define viodbg(TYPE, f, a...) \
+do {	if (vio->debug & VIO_DEBUG_##TYPE) \
+		printk(KERN_INFO "vio: ID[%lu] " f, \
+		       vio->vdev->channel_id, ## a); \
+} while (0)
+
+extern int vio_register_driver(struct vio_driver *drv);
+extern void vio_unregister_driver(struct vio_driver *drv);
+
+static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
+{
+	return container_of(drv, struct vio_driver, driver);
+}
+
+static inline struct vio_dev *to_vio_dev(struct device *dev)
+{
+	return container_of(dev, struct vio_dev, dev);
+}
+
+extern int vio_ldc_send(struct vio_driver_state *vio, void *data, int len);
+extern void vio_link_state_change(struct vio_driver_state *vio, int event);
+extern void vio_conn_reset(struct vio_driver_state *vio);
+extern int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt);
+extern int vio_validate_sid(struct vio_driver_state *vio,
+			    struct vio_msg_tag *tp);
+extern u32 vio_send_sid(struct vio_driver_state *vio);
+extern int vio_ldc_alloc(struct vio_driver_state *vio,
+			 struct ldc_channel_config *base_cfg, void *event_arg);
+extern void vio_ldc_free(struct vio_driver_state *vio);
+extern int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
+			   u8 dev_class, struct vio_version *ver_table,
+			   int ver_table_size, struct vio_driver_ops *ops,
+			   char *name);
+
+extern void vio_port_up(struct vio_driver_state *vio);
+
+#endif /* _SPARC64_VIO_H */
diff --git a/include/asm-um/a.out.h b/include/asm-um/a.out.h
index 50cee7b..7016b89 100644
--- a/include/asm-um/a.out.h
+++ b/include/asm-um/a.out.h
@@ -5,6 +5,7 @@
 #include "choose-mode.h"
 
 #undef STACK_TOP
+#undef STACK_TOP_MAX
 
 extern unsigned long stacksizelim;
 
diff --git a/include/asm-um/bug.h b/include/asm-um/bug.h
index 3357c5e..9e33b86 100644
--- a/include/asm-um/bug.h
+++ b/include/asm-um/bug.h
@@ -1,6 +1,6 @@
 #ifndef __UM_BUG_H
 #define __UM_BUG_H
 
-#include <asm/arch/bug.h>
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S
index f5de80c..e3f010b 100644
--- a/include/asm-um/common.lds.S
+++ b/include/asm-um/common.lds.S
@@ -20,6 +20,8 @@
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
 
+  BUG_TABLE
+
   __uml_setup_start = .;
   .uml.setup.init : { *(.uml.setup.init) }
   __uml_setup_end = .;
diff --git a/include/asm-um/paravirt.h b/include/asm-um/paravirt.h
new file mode 100644
index 0000000..9d6aaad
--- /dev/null
+++ b/include/asm-um/paravirt.h
@@ -0,0 +1,6 @@
+#ifndef __UM_PARAVIRT_H
+#define __UM_PARAVIRT_H
+
+#include "asm/arch/paravirt.h"
+
+#endif
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 1b1090a..830fc6e 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -175,12 +175,6 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_user(pte_t pte)
-{
-	return((pte_get_bits(pte, _PAGE_USER)) &&
-	       !(pte_get_bits(pte, _PAGE_PROTNONE)));
-}
-
 static inline int pte_read(pte_t pte)
 { 
 	return((pte_get_bits(pte, _PAGE_USER)) &&
@@ -238,18 +232,6 @@
 	return(pte);
 }
 
-static inline pte_t pte_rdprotect(pte_t pte)
-{ 
-	pte_clear_bits(pte, _PAGE_USER);
-	return(pte_mknewprot(pte));
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{ 
-	pte_clear_bits(pte, _PAGE_USER);
-	return(pte_mknewprot(pte));
-}
-
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte_clear_bits(pte, _PAGE_DIRTY);
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 18a13ba..6e5fd5c 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -52,10 +52,21 @@
 	return ti;
 }
 
+#ifdef CONFIG_DEBUG_STACK_USAGE
+
+#define alloc_thread_info(tsk) \
+	((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \
+						 CONFIG_KERNEL_STACK_ORDER))
+#else
+
 /* thread information allocation */
 #define alloc_thread_info(tsk) \
-	((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
-#define free_thread_info(ti) kfree(ti)
+	((struct thread_info *) __get_free_pages(GFP_KERNEL, \
+						 CONFIG_KERNEL_STACK_ORDER))
+#endif
+
+#define free_thread_info(ti) \
+	free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
 
 #endif
 
diff --git a/include/asm-v850/fb.h b/include/asm-v850/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-v850/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-v850/ioctls.h b/include/asm-v850/ioctls.h
index 05c0dc9..5313abd 100644
--- a/include/asm-v850/ioctls.h
+++ b/include/asm-v850/ioctls.h
@@ -46,6 +46,10 @@
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff --git a/include/asm-v850/pci.h b/include/asm-v850/pci.h
index 4581826..de2a7d0 100644
--- a/include/asm-v850/pci.h
+++ b/include/asm-v850/pci.h
@@ -116,8 +116,4 @@
 extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
 extern void pci_iounmap (struct pci_dev *dev, void __iomem *addr);
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __V850_PCI_H__ */
diff --git a/include/asm-v850/rte_cb.h b/include/asm-v850/rte_cb.h
index 9f7f02c..e85d261 100644
--- a/include/asm-v850/rte_cb.h
+++ b/include/asm-v850/rte_cb.h
@@ -64,7 +64,6 @@
 /* As we don't really support PCI DMA to cpu memory, and use bounce-buffers
    instead, perversely enough, this becomes always true! */
 # define pci_dma_supported(dev, mask)		1
-# define pci_dac_dma_supported(dev, mask)	0
 # define pcibios_assign_all_busses()		1
 
 #endif /* CONFIG_RTE_MB_A_PCI */
diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h
index f3b4330..295d7bf 100644
--- a/include/asm-v850/termbits.h
+++ b/include/asm-v850/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
@@ -130,6 +141,7 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
+#define    BOTHER 0010000
 #define    B57600 0010001
 #define   B115200 0010002
 #define   B230400 0010003
@@ -145,10 +157,12 @@
 #define  B3000000 0010015
 #define  B3500000 0010016
 #define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CIBAUD	  002003600000		/* input baud rate */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
+#define	IBSHIFT	16		/* Shifr from CBAUD to CIBAUD */
+
 /* c_lflag bits */
 #define ISIG	0000001
 #define ICANON	0000002
diff --git a/include/asm-v850/termios.h b/include/asm-v850/termios.h
index c2c2b1d..fcd1718 100644
--- a/include/asm-v850/termios.h
+++ b/include/asm-v850/termios.h
@@ -80,8 +80,10 @@
 	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 })
 
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h
index a094276..eea7aec 100644
--- a/include/asm-x86_64/alternative.h
+++ b/include/asm-x86_64/alternative.h
@@ -5,6 +5,41 @@
 
 #include <linux/types.h>
 #include <linux/stddef.h>
+
+/*
+ * Alternative inline assembly for SMP.
+ *
+ * The LOCK_PREFIX macro defined here replaces the LOCK and
+ * LOCK_PREFIX macros used everywhere in the source tree.
+ *
+ * SMP alternatives use the same data structures as the other
+ * alternatives and the X86_FEATURE_UP flag to indicate the case of a
+ * UP system running a SMP kernel.  The existing apply_alternatives()
+ * works fine for patching a SMP kernel for UP.
+ *
+ * The SMP alternative tables can be kept after boot and contain both
+ * UP and SMP versions of the instructions to allow switching back to
+ * SMP at runtime, when hotplugging in a new CPU, which is especially
+ * useful in virtualized environments.
+ *
+ * The very common lock prefix is handled as special case in a
+ * separate table which is a pure address list without replacement ptr
+ * and size information.  That keeps the table sizes small.
+ */
+
+#ifdef CONFIG_SMP
+#define LOCK_PREFIX \
+		".section .smp_locks,\"a\"\n"	\
+		"  .align 8\n"			\
+		"  .quad 661f\n" /* address */	\
+		".previous\n"			\
+	       	"661:\n\tlock; "
+
+#else /* ! CONFIG_SMP */
+#define LOCK_PREFIX ""
+#endif
+
+/* This must be included *after* the definition of LOCK_PREFIX */
 #include <asm/cpufeature.h>
 
 struct alt_instr {
@@ -108,39 +143,6 @@
  */
 #define ASM_OUTPUT2(a, b) a, b
 
-/*
- * Alternative inline assembly for SMP.
- *
- * The LOCK_PREFIX macro defined here replaces the LOCK and
- * LOCK_PREFIX macros used everywhere in the source tree.
- *
- * SMP alternatives use the same data structures as the other
- * alternatives and the X86_FEATURE_UP flag to indicate the case of a
- * UP system running a SMP kernel.  The existing apply_alternatives()
- * works fine for patching a SMP kernel for UP.
- *
- * The SMP alternative tables can be kept after boot and contain both
- * UP and SMP versions of the instructions to allow switching back to
- * SMP at runtime, when hotplugging in a new CPU, which is especially
- * useful in virtualized environments.
- *
- * The very common lock prefix is handled as special case in a
- * separate table which is a pure address list without replacement ptr
- * and size information.  That keeps the table sizes small.
- */
-
-#ifdef CONFIG_SMP
-#define LOCK_PREFIX \
-		".section .smp_locks,\"a\"\n"	\
-		"  .align 8\n"			\
-		"  .quad 661f\n" /* address */	\
-		".previous\n"			\
-	       	"661:\n\tlock; "
-
-#else /* ! CONFIG_SMP */
-#define LOCK_PREFIX ""
-#endif
-
 struct paravirt_patch;
 #ifdef CONFIG_PARAVIRT
 void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
diff --git a/include/asm-x86_64/boot.h b/include/asm-x86_64/boot.h
index 96b228e..3c46cea 100644
--- a/include/asm-x86_64/boot.h
+++ b/include/asm-x86_64/boot.h
@@ -1,15 +1 @@
-#ifndef _LINUX_BOOT_H
-#define _LINUX_BOOT_H
-
-/* Don't touch these, unless you really know what you're doing. */
-#define DEF_INITSEG	0x9000
-#define DEF_SYSSEG	0x1000
-#define DEF_SETUPSEG	0x9020
-#define DEF_SYSSIZE	0x7F00
-
-/* Internal svga startup constants */
-#define NORMAL_VGA	0xffff		/* 80x25 mode */
-#define EXTENDED_VGA	0xfffe		/* 80x50 mode */
-#define ASK_VGA		0xfffd		/* ask for it at bootup */
-
-#endif
+#include <asm-i386/boot.h>
diff --git a/include/asm-x86_64/bootparam.h b/include/asm-x86_64/bootparam.h
new file mode 100644
index 0000000..aa82e52
--- /dev/null
+++ b/include/asm-x86_64/bootparam.h
@@ -0,0 +1 @@
+#include <asm-i386/bootparam.h>
diff --git a/include/asm-x86_64/calgary.h b/include/asm-x86_64/calgary.h
index 7ee9006..4d5747a 100644
--- a/include/asm-x86_64/calgary.h
+++ b/include/asm-x86_64/calgary.h
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/timer.h>
 #include <asm/types.h>
 
 struct iommu_table {
diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h
index b37ab82..53cb96b 100644
--- a/include/asm-x86_64/compat.h
+++ b/include/asm-x86_64/compat.h
@@ -33,8 +33,10 @@
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
+typedef s64 __attribute__((aligned(4))) compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
+typedef u64 __attribute__((aligned(4))) compat_u64;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index 0b3c686..8baefc3 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -7,115 +7,24 @@
 #ifndef __ASM_X8664_CPUFEATURE_H
 #define __ASM_X8664_CPUFEATURE_H
 
-#define NCAPINTS	7	/* N 32-bit words worth of info */
+#include <asm-i386/cpufeature.h>
 
-/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
-#define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
-#define X86_FEATURE_VME		(0*32+ 1) /* Virtual Mode Extensions */
-#define X86_FEATURE_DE		(0*32+ 2) /* Debugging Extensions */
-#define X86_FEATURE_PSE 	(0*32+ 3) /* Page Size Extensions */
-#define X86_FEATURE_TSC		(0*32+ 4) /* Time Stamp Counter */
-#define X86_FEATURE_MSR		(0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */
-#define X86_FEATURE_PAE		(0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE		(0*32+ 7) /* Machine Check Architecture */
-#define X86_FEATURE_CX8		(0*32+ 8) /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC	(0*32+ 9) /* Onboard APIC */
-#define X86_FEATURE_SEP		(0*32+11) /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR	(0*32+12) /* Memory Type Range Registers */
-#define X86_FEATURE_PGE		(0*32+13) /* Page Global Enable */
-#define X86_FEATURE_MCA		(0*32+14) /* Machine Check Architecture */
-#define X86_FEATURE_CMOV	(0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
-#define X86_FEATURE_PAT		(0*32+16) /* Page Attribute Table */
-#define X86_FEATURE_PSE36	(0*32+17) /* 36-bit PSEs */
-#define X86_FEATURE_PN		(0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLSH	(0*32+19) /* Supports the CLFLUSH instruction */
-#define X86_FEATURE_DS		(0*32+21) /* Debug Store */
-#define X86_FEATURE_ACPI	(0*32+22) /* ACPI via MSR */
-#define X86_FEATURE_MMX		(0*32+23) /* Multimedia Extensions */
-#define X86_FEATURE_FXSR	(0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
-				          /* of FPU context), and CR4.OSFXSR available */
-#define X86_FEATURE_XMM		(0*32+25) /* Streaming SIMD Extensions */
-#define X86_FEATURE_XMM2	(0*32+26) /* Streaming SIMD Extensions-2 */
-#define X86_FEATURE_SELFSNOOP	(0*32+27) /* CPU self snoop */
-#define X86_FEATURE_HT		(0*32+28) /* Hyper-Threading */
-#define X86_FEATURE_ACC		(0*32+29) /* Automatic clock control */
-#define X86_FEATURE_IA64	(0*32+30) /* IA-64 processor */
-
-/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
-/* Don't duplicate feature flags which are redundant with Intel! */
-#define X86_FEATURE_SYSCALL	(1*32+11) /* SYSCALL/SYSRET */
-#define X86_FEATURE_MMXEXT	(1*32+22) /* AMD MMX extensions */
-#define X86_FEATURE_FXSR_OPT	(1*32+25) /* FXSR optimizations */
-#define X86_FEATURE_RDTSCP	(1*32+27) /* RDTSCP */
-#define X86_FEATURE_LM		(1*32+29) /* Long Mode (x86-64) */
-#define X86_FEATURE_3DNOWEXT	(1*32+30) /* AMD 3DNow! extensions */
-#define X86_FEATURE_3DNOW	(1*32+31) /* 3DNow! */
-
-/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY	(2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN	(2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI	(2*32+ 3) /* LongRun table interface */
-
-/* Other features, Linux-defined mapping, word 3 */
-/* This range is used for feature bits which conflict or are synthesized */
-#define X86_FEATURE_CXMMX	(3*32+ 0) /* Cyrix MMX extensions */
-#define X86_FEATURE_K6_MTRR	(3*32+ 1) /* AMD K6 nonstandard MTRRs */
-#define X86_FEATURE_CYRIX_ARR	(3*32+ 2) /* Cyrix ARRs (= MTRRs) */
-#define X86_FEATURE_CENTAUR_MCR	(3*32+ 3) /* Centaur MCRs (= MTRRs) */
-#define X86_FEATURE_REP_GOOD	(3*32+ 4) /* rep microcode works well on this CPU */
-#define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
-#define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
-#define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
-#define X86_FEATURE_UP		(3*32+8) /* SMP kernel running on UP */
-#define X86_FEATURE_ARCH_PERFMON (3*32+9) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS	(3*32+10) /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS		(3*32+11) /* Branch Trace Store */
-
-/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
-#define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
-#define X86_FEATURE_DSCPL	(4*32+ 4) /* CPL Qualified Debug Store */
-#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
-#define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
-#define X86_FEATURE_CID		(4*32+10) /* Context ID */
-#define X86_FEATURE_CX16	(4*32+13) /* CMPXCHG16B */
-#define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
-
-/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
-#define X86_FEATURE_XSTORE	(5*32+ 2) /* on-CPU RNG present (xstore insn) */
-#define X86_FEATURE_XSTORE_EN	(5*32+ 3) /* on-CPU RNG enabled */
-#define X86_FEATURE_XCRYPT	(5*32+ 6) /* on-CPU crypto (xcrypt insn) */
-#define X86_FEATURE_XCRYPT_EN	(5*32+ 7) /* on-CPU crypto enabled */
-
-/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
-#define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY	(6*32+ 1) /* If yes HyperThreading not valid */
-
-#define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
-#define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
-
-#define cpu_has_fpu            1
+#undef  cpu_has_vme
 #define cpu_has_vme            0
-#define cpu_has_de             1
-#define cpu_has_pse            1
-#define cpu_has_tsc            1
+
+#undef  cpu_has_pae
 #define cpu_has_pae            ___BUG___
-#define cpu_has_pge            1
-#define cpu_has_apic           boot_cpu_has(X86_FEATURE_APIC)
-#define cpu_has_mtrr           1
-#define cpu_has_mmx            1
-#define cpu_has_fxsr           1
-#define cpu_has_xmm            1
-#define cpu_has_xmm2           1
-#define cpu_has_xmm3           boot_cpu_has(X86_FEATURE_XMM3)
-#define cpu_has_ht             boot_cpu_has(X86_FEATURE_HT)
+
+#undef  cpu_has_mp
 #define cpu_has_mp             1 /* XXX */
+
+#undef  cpu_has_k6_mtrr
 #define cpu_has_k6_mtrr        0
+
+#undef  cpu_has_cyrix_arr
 #define cpu_has_cyrix_arr      0
+
+#undef  cpu_has_centaur_mcr
 #define cpu_has_centaur_mcr    0
-#define cpu_has_clflush	       boot_cpu_has(X86_FEATURE_CLFLSH)
-#define cpu_has_ds 	       boot_cpu_has(X86_FEATURE_DS)
-#define cpu_has_pebs 	       boot_cpu_has(X86_FEATURE_PEBS)
-#define cpu_has_bts 	       boot_cpu_has(X86_FEATURE_BTS)
 
 #endif /* __ASM_X8664_CPUFEATURE_H */
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index 6216fa3..3486e70 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -11,8 +11,6 @@
 #ifndef __E820_HEADER
 #define __E820_HEADER
 
-#include <linux/mmzone.h>
-
 #define E820MAP	0x2d0		/* our map */
 #define E820MAX	128		/* number of entries in E820MAP */
 #define E820NR	0x1e8		/* # entries in E820MAP */
@@ -30,7 +28,7 @@
 } __attribute__((packed));
 
 struct e820map {
-    int nr_map;
+	u32 nr_map;
 	struct e820entry map[E820MAX];
 };
 
diff --git a/include/asm-x86_64/fb.h b/include/asm-x86_64/fb.h
new file mode 100644
index 0000000..60548e6
--- /dev/null
+++ b/include/asm-x86_64/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	if (boot_cpu_data.x86 > 3)
+		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index e90e167..2acb9b7 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -35,6 +35,8 @@
 	VSYSCALL_LAST_PAGE,
 	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
 	VSYSCALL_HPET,
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
 	FIX_HPET_BASE,
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 	FIX_IO_APIC_BASE_0,
@@ -84,7 +86,7 @@
 	if (idx >= __end_of_fixed_addresses)
 		__this_fixmap_does_not_exist();
 
-        return __fix_to_virt(idx);
+	return __fix_to_virt(idx);
 }
 
 #endif
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index de2cd9a..7475095 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -144,6 +144,7 @@
  */
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap(volatile void __iomem *addr);
+extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index e327c83..88adf1a 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -48,7 +48,8 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 /*
  * These are used to make use of C type-checking..
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index 49c5e92..bda94fd 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -54,14 +54,6 @@
 
 #if defined(CONFIG_IOMMU) || defined(CONFIG_CALGARY_IOMMU)
 
-/*
- * x86-64 always supports DAC, but sometimes it is useful to force
- * devices through the IOMMU to get automatic sg list merging.
- * Optional right now.
- */
-extern int iommu_sac_force;
-#define pci_dac_dma_supported(pci_dev, mask)	(!iommu_sac_force)
-
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
@@ -78,8 +70,6 @@
 #else
 /* No IOMMU */
 
-#define pci_dac_dma_supported(pci_dev, mask)    1
-
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
 #define pci_unmap_addr(PTR, ADDR_NAME)		(0)
@@ -91,36 +81,6 @@
 
 #include <asm-generic/pci-dma-compat.h>
 
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
-	return ((dma64_addr_t) page_to_phys(page) +
-		(dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	return virt_to_page(__va(dma_addr)); 	
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
-	return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-	flush_write_buffers();
-}
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
@@ -135,10 +95,6 @@
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 			       enum pci_mmap_state mmap_state, int write_combine);
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* generic pci stuff */
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 08b9831..3ba5309 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -266,21 +266,15 @@
  * Undefined behaviour if not..
  */
 #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
-static inline int pte_user(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
-static inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
-static inline int pte_exec(pte_t pte)		{ return !(pte_val(pte) & _PAGE_NX); }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
 static inline int pte_huge(pte_t pte)		{ return pte_val(pte) & _PAGE_PSE; }
 
-static inline pte_t pte_rdprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
-static inline pte_t pte_exprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
 static inline pte_t pte_mkexec(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX)); return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
@@ -290,13 +284,6 @@
 
 struct vm_area_struct;
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-	if (!pte_dirty(*ptep))
-		return 0;
-	return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte);
-}
-
 static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	if (!pte_young(*ptep))
@@ -395,12 +382,14 @@
  * bit at the same time. */
 #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-	do {								  \
-		if (__dirty) {						  \
-			set_pte(__ptep, __entry);			  \
-			flush_tlb_page(__vma, __address);		  \
-		}							  \
-	} while (0)
+({									  \
+	int __changed = !pte_same(*(__ptep), __entry);			  \
+	if (__changed && __dirty) {					  \
+		set_pte(__ptep, __entry);			  	  \
+		flush_tlb_page(__vma, __address);		  	  \
+	}								  \
+	__changed;							  \
+})
 
 /* Encode and de-code a swap entry */
 #define __swp_type(x)			(((x).val >> 1) & 0x3f)
@@ -431,7 +420,6 @@
    (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 461ffe4..efc87a5 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -100,6 +100,7 @@
 
 extern void identify_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
+extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern unsigned short num_cache_leaves;
 
@@ -368,8 +369,6 @@
 	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
 } 
 
-#define cpu_has_fpu 1
-
 #define ARCH_HAS_PREFETCH
 static inline void prefetch(void *x) 
 { 
diff --git a/include/asm-x86_64/required-features.h b/include/asm-x86_64/required-features.h
new file mode 100644
index 0000000..e80d576
--- /dev/null
+++ b/include/asm-x86_64/required-features.h
@@ -0,0 +1,46 @@
+#ifndef _ASM_REQUIRED_FEATURES_H
+#define _ASM_REQUIRED_FEATURES_H 1
+
+/* Define minimum CPUID feature set for kernel These bits are checked
+   really early to actually display a visible error message before the
+   kernel dies.  Make sure to assign features to the proper mask!
+
+   The real information is in arch/x86_64/Kconfig.cpu, this just converts
+   the CONFIGs into a bitmask */
+
+/* x86-64 baseline features */
+#define NEED_FPU	(1<<(X86_FEATURE_FPU & 31))
+#define NEED_PSE	(1<<(X86_FEATURE_PSE & 31))
+#define NEED_MSR	(1<<(X86_FEATURE_MSR & 31))
+#define NEED_PAE	(1<<(X86_FEATURE_PAE & 31))
+#define NEED_CX8	(1<<(X86_FEATURE_CX8 & 31))
+#define NEED_PGE	(1<<(X86_FEATURE_PGE & 31))
+#define NEED_FXSR	(1<<(X86_FEATURE_FXSR & 31))
+#define NEED_CMOV	(1<<(X86_FEATURE_CMOV & 31))
+#define NEED_XMM	(1<<(X86_FEATURE_XMM & 31))
+#define NEED_XMM2	(1<<(X86_FEATURE_XMM2 & 31))
+
+#define REQUIRED_MASK0	(NEED_FPU|NEED_PSE|NEED_MSR|NEED_PAE|\
+			 NEED_CX8|NEED_PGE|NEED_FXSR|NEED_CMOV|\
+			 NEED_XMM|NEED_XMM2)
+#define SSE_MASK	(NEED_XMM|NEED_XMM2)
+
+/* x86-64 baseline features */
+#define NEED_LM		(1<<(X86_FEATURE_LM & 31))
+
+#ifdef CONFIG_X86_USE_3DNOW
+# define NEED_3DNOW	(1<<(X86_FEATURE_3DNOW & 31))
+#else
+# define NEED_3DNOW	0
+#endif
+
+#define REQUIRED_MASK1	(NEED_LM|NEED_3DNOW)
+
+#define REQUIRED_MASK2	0
+#define REQUIRED_MASK3	0
+#define REQUIRED_MASK4	0
+#define REQUIRED_MASK5	0
+#define REQUIRED_MASK6	0
+#define REQUIRED_MASK7	0
+
+#endif
diff --git a/include/asm-x86_64/segment.h b/include/asm-x86_64/segment.h
index adf2bf1..04b8ab2 100644
--- a/include/asm-x86_64/segment.h
+++ b/include/asm-x86_64/segment.h
@@ -3,6 +3,14 @@
 
 #include <asm/cache.h>
 
+/* Simple and small GDT entries for booting only */
+
+#define GDT_ENTRY_BOOT_CS		2
+#define __BOOT_CS	(GDT_ENTRY_BOOT_CS * 8)
+
+#define GDT_ENTRY_BOOT_DS		(GDT_ENTRY_BOOT_CS + 1)
+#define __BOOT_DS	(GDT_ENTRY_BOOT_DS * 8)
+
 #define __KERNEL_CS	0x10
 #define __KERNEL_DS	0x18
 
diff --git a/include/asm-x86_64/tlbflush.h b/include/asm-x86_64/tlbflush.h
index 512401b..8516225 100644
--- a/include/asm-x86_64/tlbflush.h
+++ b/include/asm-x86_64/tlbflush.h
@@ -2,6 +2,7 @@
 #define _X8664_TLBFLUSH_H
 
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index ae1ed05..8696f8a 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -626,9 +626,9 @@
 __SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
 #define __NR_signalfd		282
 __SYSCALL(__NR_signalfd, sys_signalfd)
-#define __NR_timerfd		282
+#define __NR_timerfd		283
 __SYSCALL(__NR_timerfd, sys_timerfd)
-#define __NR_eventfd		283
+#define __NR_eventfd		284
 __SYSCALL(__NR_eventfd, sys_eventfd)
 
 #ifndef __NO_STUBS
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
index d815649..1c1e0d9 100644
--- a/include/asm-xtensa/bitops.h
+++ b/include/asm-xtensa/bitops.h
@@ -7,7 +7,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
  */
 
 #ifndef _XTENSA_BITOPS_H
@@ -31,53 +31,30 @@
 
 #if XCHAL_HAVE_NSA
 
-static __inline__ int __cntlz (unsigned long x)
+static inline unsigned long __cntlz (unsigned long x)
 {
 	int lz;
 	asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
-	return 31 - lz;
+	return lz;
 }
 
-#else
-
-static __inline__ int __cntlz (unsigned long x)
-{
-	unsigned long sum, x1, x2, x4, x8, x16;
-	x1  = x & 0xAAAAAAAA;
-	x2  = x & 0xCCCCCCCC;
-	x4  = x & 0xF0F0F0F0;
-	x8  = x & 0xFF00FF00;
-	x16 = x & 0xFFFF0000;
-	sum = x2 ? 2 : 0;
-	sum += (x16 != 0) * 16;
-	sum += (x8 != 0) * 8;
-	sum += (x4 != 0) * 4;
-	sum += (x1 != 0);
-
-	return sum;
-}
-
-#endif
-
 /*
  * ffz: Find first zero in word. Undefined if no zero exists.
  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  */
 
-static __inline__ int ffz(unsigned long x)
+static inline int ffz(unsigned long x)
 {
-	if ((x = ~x) == 0)
-		return 32;
-	return __cntlz(x & -x);
+	return 31 - __cntlz(~x & -~x);
 }
 
 /*
  * __ffs: Find first bit set in word. Return 0 for bit 0
  */
 
-static __inline__ int __ffs(unsigned long x)
+static inline int __ffs(unsigned long x)
 {
-	return __cntlz(x & -x);
+	return 31 - __cntlz(x & -x);
 }
 
 /*
@@ -86,9 +63,9 @@
  * differs in spirit from the above ffz (man ffs).
  */
 
-static __inline__ int ffs(unsigned long x)
+static inline int ffs(unsigned long x)
 {
-	return __cntlz(x & -x) + 1;
+	return 32 - __cntlz(x & -x);
 }
 
 /*
@@ -96,20 +73,36 @@
  * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
  */
 
-static __inline__ int fls (unsigned int x)
+static inline int fls (unsigned int x)
 {
-	return __cntlz(x);
+	return 32 - __cntlz(x);
 }
+
+#else
+
+/* Use the generic implementation if we don't have the nsa/nsau instructions. */
+
+# include <asm-generic/bitops/ffs.h>
+# include <asm-generic/bitops/__ffs.h>
+# include <asm-generic/bitops/ffz.h>
+# include <asm-generic/bitops/fls.h>
+
+#endif
+
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ext2-non-atomic.h>
 
 #ifdef __XTENSA_EL__
-# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr),(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr),(addr))
+# define ext2_set_bit_atomic(lock,nr,addr)				\
+	test_and_set_bit((nr), (unsigned long*)(addr))
+# define ext2_clear_bit_atomic(lock,nr,addr)				\
+	test_and_clear_bit((nr), (unsigned long*)(addr))
 #elif defined(__XTENSA_EB__)
-# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr) ^ 0x18, (addr))
-# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr)^0x18,(addr))
+# define ext2_set_bit_atomic(lock,nr,addr)				\
+	test_and_set_bit((nr) ^ 0x18, (unsigned long*)(addr))
+# define ext2_clear_bit_atomic(lock,nr,addr)				\
+	test_and_clear_bit((nr) ^ 0x18, (unsigned long*)(addr))
 #else
 # error processor byte order undefined!
 #endif
diff --git a/include/asm-xtensa/byteorder.h b/include/asm-xtensa/byteorder.h
index 0f540a5..765edf1 100644
--- a/include/asm-xtensa/byteorder.h
+++ b/include/asm-xtensa/byteorder.h
@@ -12,6 +12,7 @@
 #define _XTENSA_BYTEORDER_H
 
 #include <asm/types.h>
+#include <linux/compiler.h>
 
 static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
 {
@@ -78,4 +79,4 @@
 # error processor byte order undefined!
 #endif
 
-#endif /* __ASM_XTENSA_BYTEORDER_H */
+#endif /* _XTENSA_BYTEORDER_H */
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h
index bd09ec0..aa21210 100644
--- a/include/asm-xtensa/coprocessor.h
+++ b/include/asm-xtensa/coprocessor.h
@@ -64,6 +64,7 @@
 #  define COPROCESSOR_INFO_SIZE 8
 # endif
 #endif
+#endif	/* XCHAL_HAVE_CP */
 
 
 #ifndef __ASSEMBLY__
@@ -74,8 +75,11 @@
 # else
 #  define release_coprocessors(task)
 # endif
-#endif
 
-#endif
+typedef unsigned char cp_state_t[XTENSA_CP_EXTRA_SIZE]
+	__attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
+
+#endif	/* !__ASSEMBLY__ */
+
 
 #endif	/* _XTENSA_COPROCESSOR_H */
diff --git a/include/asm-xtensa/div64.h b/include/asm-xtensa/div64.h
index 20965e3..f35678c 100644
--- a/include/asm-xtensa/div64.h
+++ b/include/asm-xtensa/div64.h
@@ -5,21 +5,12 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
  */
 
 #ifndef _XTENSA_DIV64_H
 #define _XTENSA_DIV64_H
 
-#include <linux/types.h>
+#include <asm-generic/div64.h>
 
-#define do_div(n,base) ({ \
-	int __res = n % ((unsigned int) base); \
-	n /= (unsigned int) base; \
-	__res; })
-
-static inline uint64_t div64_64(uint64_t dividend, uint64_t divisor)
-{
-	return dividend / divisor;
-}
-#endif
+#endif /* _XTENSA_DIV64_H */
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index f0f9fd8..1569b53 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -13,7 +13,6 @@
 #ifndef _XTENSA_ELF_H
 #define _XTENSA_ELF_H
 
-#include <asm/variant/core.h>
 #include <asm/ptrace.h>
 
 /* Xtensa processor ELF architecture-magic number */
@@ -49,7 +48,7 @@
 	elf_greg_t lcount;
 	elf_greg_t sar;
 	elf_greg_t syscall;
-	elf_greg_t ar[XCHAL_NUM_AREGS];
+	elf_greg_t ar[64];
 } xtensa_gregset_t;
 
 #define ELF_NGREG	(sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
diff --git a/include/asm-xtensa/fb.h b/include/asm-xtensa/fb.h
new file mode 100644
index 0000000..c7df380
--- /dev/null
+++ b/include/asm-xtensa/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h
index 0609fc6..46ab12d 100644
--- a/include/asm-xtensa/fcntl.h
+++ b/include/asm-xtensa/fcntl.h
@@ -1,99 +1 @@
-/*
- * include/asm-xtensa/fcntl.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_FCNTL_H
-#define _XTENSA_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_ACCMODE	   0003
-#define O_RDONLY	     00
-#define O_WRONLY	     01
-#define O_RDWR		     02
-#define O_CREAT		   0100	/* not fcntl */
-#define O_EXCL		   0200	/* not fcntl */
-#define O_NOCTTY	   0400	/* not fcntl */
-#define O_TRUNC		  01000	/* not fcntl */
-#define O_APPEND	  02000
-#define O_NONBLOCK	  04000
-#define O_NDELAY	O_NONBLOCK
-#define O_SYNC		 010000
-#define FASYNC		 020000	/* fcntl, for BSD compatibility */
-#define O_DIRECT	 040000	/* direct disk access hint */
-#define O_LARGEFILE	0100000
-#define O_DIRECTORY	0200000	/* must be a directory */
-#define O_NOFOLLOW	0400000 /* don't follow links */
-#define O_NOATIME	01000000
-
-#define F_DUPFD		0	/* dup */
-#define F_GETFD		1	/* get close_on_exec */
-#define F_SETFD		2	/* set/clear close_on_exec */
-#define F_GETFL		3	/* get file->f_flags */
-#define F_SETFL		4	/* set file->f_flags */
-#define F_GETLK		5
-#define F_SETLK		6
-#define F_SETLKW	7
-
-#define F_SETOWN	8	/*  for sockets. */
-#define F_GETOWN	9	/*  for sockets. */
-#define F_SETSIG	10	/*  for sockets. */
-#define F_GETSIG	11	/*  for sockets. */
-
-#define F_GETLK64	12	/*  using 'struct flock64' */
-#define F_SETLK64	13
-#define F_SETLKW64	14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK		0
-#define F_WRLCK		1
-#define F_UNLCK		2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK		4	/* or 3 */
-#define F_SHLCK		8	/* or 4 */
-
-/* for leases */
-#define F_INPROGRESS	16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH		1	/* shared lock */
-#define LOCK_EX		2	/* exclusive lock */
-#define LOCK_NB		4	/* or'd with one of the above to prevent
-				   blocking */
-#define LOCK_UN		8	/* remove lock */
-
-#define LOCK_MAND	32	/* This is a mandatory flock */
-#define LOCK_READ	64	/* ... Which allows concurrent read operations */
-#define LOCK_WRITE	128	/* ... Which allows concurrent write operations */
-#define LOCK_RW		192	/* ... Which allows concurrent read & write ops */
-
-struct flock {
-	short l_type;
-	short l_whence;
-	off_t l_start;
-	off_t l_len;
-	pid_t l_pid;
-};
-
-struct flock64 {
-	short  l_type;
-	short  l_whence;
-	loff_t l_start;
-	loff_t l_len;
-	pid_t  l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE	1024
-
-#endif /* _XTENSA_FCNTL_H */
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
index 92f9483..c0fd8e5 100644
--- a/include/asm-xtensa/mmu_context.h
+++ b/include/asm-xtensa/mmu_context.h
@@ -14,6 +14,7 @@
 #define _XTENSA_MMU_CONTEXT_H
 
 #include <linux/stringify.h>
+#include <linux/sched.h>
 
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index c631d00..1213cde 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -131,6 +131,6 @@
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#endif /* __KERNEL__ */
 #include <asm-generic/memory_model.h>
+#endif /* __KERNEL__ */
 #endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h
index 6f28139..ce3a336 100644
--- a/include/asm-xtensa/param.h
+++ b/include/asm-xtensa/param.h
@@ -11,15 +11,13 @@
 #ifndef _XTENSA_PARAM_H
 #define _XTENSA_PARAM_H
 
-#include <asm/variant/core.h>
-
 #ifdef __KERNEL__
 # define HZ		100		/* internal timer frequency */
 # define USER_HZ	100		/* for user interfaces in "ticks" */
 # define CLOCKS_PER_SEC (USER_HZ)	/* frequnzy at which times() counts */
 #endif
 
-#define EXEC_PAGESIZE	(1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE)
+#define EXEC_PAGESIZE	4096
 
 #ifndef NGROUPS
 #define NGROUPS		32
diff --git a/include/asm-xtensa/pci.h b/include/asm-xtensa/pci.h
index 24eb7fc..66410ac 100644
--- a/include/asm-xtensa/pci.h
+++ b/include/asm-xtensa/pci.h
@@ -64,9 +64,6 @@
 #define pci_ubnmap_len(PTR, LEN_NAME)		(0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
-/* We cannot access memory above 4GB */
-#define pci_dac_dma_supported(pci_dev, mask)	(0)
-
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
                         enum pci_mmap_state mmap_state, int write_combine);
@@ -74,10 +71,6 @@
 /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
 #define HAVE_PCI_MMAP	1
 
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
 #endif /* __KERNEL__ */
 
 /* Implement the pci_ DMA API in terms of the generic device dma_ one */
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
index 2d4b5db..06850f3 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/include/asm-xtensa/pgtable.h
@@ -197,16 +197,13 @@
 
 /* Note: We use the _PAGE_USER bit to indicate write-protect kernel memory */
 
-static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER; }
 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)  { return pte_val(pte) & _PAGE_FILE; }
 static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~(_PAGE_RW | _PAGE_WRENABLE); return pte; }
-static inline pte_t pte_rdprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_RW; return pte; }
@@ -270,17 +267,6 @@
 	return 1;
 }
 
-static inline int
-ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr,
-   			  pte_t *ptep)
-{
-	pte_t pte = *ptep;
-	if (!pte_dirty(pte))
-		return 0;
-	update_pte(ptep, pte_mkclean(pte));
-	return 1;
-}
-
 static inline pte_t
 ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -421,7 +407,6 @@
 #endif /* !defined (__ASSEMBLY__) */
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTEP_MKDIRTY
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
index 1b7fe36..77ff02d 100644
--- a/include/asm-xtensa/ptrace.h
+++ b/include/asm-xtensa/ptrace.h
@@ -11,8 +11,6 @@
 #ifndef _XTENSA_PTRACE_H
 #define _XTENSA_PTRACE_H
 
-#include <asm/variant/core.h>
-
 /*
  * Kernel stack
  *
@@ -101,7 +99,8 @@
 	unsigned long windowbase;	/*  48 */
 	unsigned long windowstart;	/*  52 */
 	unsigned long syscall;		/*  56 */
-	int reserved[2];		/*  64 */
+	unsigned long icountlevel;	/*  60 */
+	int reserved[1];		/*  64 */
 
 	/* Make sure the areg field is 16 bytes aligned. */
 	int align[0] __attribute__ ((aligned(16)));
@@ -113,6 +112,9 @@
 };
 
 #ifdef __KERNEL__
+
+#include <asm/variant/core.h>
+
 # define task_pt_regs(tsk) ((struct pt_regs*) \
   (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
 # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
diff --git a/include/asm-xtensa/shmparam.h b/include/asm-xtensa/shmparam.h
index d3b65bf..c8cc16c 100644
--- a/include/asm-xtensa/shmparam.h
+++ b/include/asm-xtensa/shmparam.h
@@ -9,8 +9,6 @@
 #ifndef _XTENSA_SHMPARAM_H
 #define _XTENSA_SHMPARAM_H
 
-#include <asm/processor.h>
-
 /*
  * Xtensa can have variable size caches, and if
  * the size of single way is larger than the page size,
diff --git a/include/asm-xtensa/sigcontext.h b/include/asm-xtensa/sigcontext.h
index a751772..e3381ce 100644
--- a/include/asm-xtensa/sigcontext.h
+++ b/include/asm-xtensa/sigcontext.h
@@ -5,21 +5,12 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2003 Tensilica Inc.
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
  */
 
 #ifndef _XTENSA_SIGCONTEXT_H
 #define _XTENSA_SIGCONTEXT_H
 
-#define _ASMLANGUAGE
-#include <asm/processor.h>
-#include <asm/coprocessor.h>
-
-
-struct _cpstate {
-	unsigned char _cpstate[XTENSA_CP_EXTRA_SIZE];
-} __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
-
 
 struct sigcontext {
 	unsigned long	oldmask;
@@ -27,18 +18,13 @@
 	/* CPU registers */
 	unsigned long sc_pc;
 	unsigned long sc_ps;
-	unsigned long sc_wmask;
-	unsigned long sc_windowbase;
-	unsigned long sc_windowstart;
 	unsigned long sc_lbeg;
 	unsigned long sc_lend;
 	unsigned long sc_lcount;
 	unsigned long sc_sar;
-	unsigned long sc_depc;
-	unsigned long sc_dareg0;
-	unsigned long sc_treg[4];
-	unsigned long sc_areg[XCHAL_NUM_AREGS];
-	struct _cpstate *sc_cpstate;
+	unsigned long sc_acclo;
+	unsigned long sc_acchi;
+	unsigned long sc_a[16];
 };
 
-#endif /* __ASM_XTENSA_SIGCONTEXT_H */
+#endif /* _XTENSA_SIGCONTEXT_H */
diff --git a/include/asm-xtensa/termbits.h b/include/asm-xtensa/termbits.h
index 057b9a3..9972c25 100644
--- a/include/asm-xtensa/termbits.h
+++ b/include/asm-xtensa/termbits.h
@@ -30,6 +30,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h
index 5ae34ab..3fa29799 100644
--- a/include/asm-xtensa/thread_info.h
+++ b/include/asm-xtensa/thread_info.h
@@ -116,6 +116,7 @@
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
 #define TIF_MEMDIE		6
+#define TIF_RESTORE_SIGMASK	7	/* restore signal mask in do_signal() */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -125,6 +126,7 @@
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h
index 8a7fb69..9bd3402 100644
--- a/include/asm-xtensa/unistd.h
+++ b/include/asm-xtensa/unistd.h
@@ -485,8 +485,8 @@
 __SYSCALL(218, sys_sched_rr_get_interval, 2)
 #define __NR_sched_yield 			219
 __SYSCALL(219, sys_sched_yield, 0)
-#define __NR_sigreturn	 			222
-__SYSCALL(222, xtensa_sigreturn, 0)
+#define __NR_available222 			222
+__SYSCALL(222, sys_ni_syscall, 0)
 
 /* Signal Handling */
 
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index bcd01f2..bcf875e 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -49,6 +49,7 @@
 header-y += const.h
 header-y += cycx_cfm.h
 header-y += dlm_device.h
+header-y += dlm_netlink.h
 header-y += dm-ioctl.h
 header-y += dn.h
 header-y += dqblk_v1.h
@@ -62,6 +63,8 @@
 header-y += fd.h
 header-y += fdreg.h
 header-y += fib_rules.h
+header-y += firewire-cdev.h
+header-y += firewire-constants.h
 header-y += fuse.h
 header-y += genetlink.h
 header-y += gen_stats.h
@@ -88,7 +91,6 @@
 header-y += in_route.h
 header-y += ioctl.h
 header-y += ipmi_msgdefs.h
-header-y += ip_mp_alg.h
 header-y += ipsec.h
 header-y += ipx.h
 header-y += irda.h
@@ -223,6 +225,7 @@
 unifdef-y += if_frad.h
 unifdef-y += if_ltalk.h
 unifdef-y += if_link.h
+unifdef-y += if_pppol2tp.h
 unifdef-y += if_pppox.h
 unifdef-y += if_shaper.h
 unifdef-y += if_tr.h
@@ -239,11 +242,11 @@
 unifdef-y += ipmi.h
 unifdef-y += ipv6.h
 unifdef-y += ipv6_route.h
+unifdef-y += ip6_tunnel.h
 unifdef-y += isdn.h
 unifdef-y += isdnif.h
 unifdef-y += isdn_divertif.h
 unifdef-y += isdn_ppp.h
-unifdef-y += isicom.h
 unifdef-y += jbd.h
 unifdef-y += joystick.h
 unifdef-y += kdev_t.h
diff --git a/include/linux/aer.h b/include/linux/aer.h
index 402e178..5096562 100644
--- a/include/linux/aer.h
+++ b/include/linux/aer.h
@@ -13,11 +13,13 @@
 extern int pci_find_aer_capability(struct pci_dev *dev);
 extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
 extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+extern int pci_cleanup_aer_correct_error_status(struct pci_dev *dev);
 #else
-#define pci_enable_pcie_error_reporting(dev)		do { } while (0)
-#define pci_find_aer_capability(dev)			do { } while (0)
-#define pci_disable_pcie_error_reporting(dev)		do { } while (0)
-#define pci_cleanup_aer_uncorrect_error_status(dev)	do { } while (0)
+#define pci_enable_pcie_error_reporting(dev)		(-EINVAL)
+#define pci_find_aer_capability(dev)			(0)
+#define pci_disable_pcie_error_reporting(dev)		(-EINVAL)
+#define pci_cleanup_aer_uncorrect_error_status(dev)	(-EINVAL)
+#define pci_cleanup_aer_correct_error_status(dev)	(-EINVAL)
 #endif
 
 #endif //_AER_H_
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h
new file mode 100644
index 0000000..ff12550
--- /dev/null
+++ b/include/linux/async_tx.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _ASYNC_TX_H_
+#define _ASYNC_TX_H_
+#include <linux/dmaengine.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+/**
+ * dma_chan_ref - object used to manage dma channels received from the
+ *   dmaengine core.
+ * @chan - the channel being tracked
+ * @node - node for the channel to be placed on async_tx_master_list
+ * @rcu - for list_del_rcu
+ * @count - number of times this channel is listed in the pool
+ *	(for channels with multiple capabiities)
+ */
+struct dma_chan_ref {
+	struct dma_chan *chan;
+	struct list_head node;
+	struct rcu_head rcu;
+	atomic_t count;
+};
+
+/**
+ * async_tx_flags - modifiers for the async_* calls
+ * @ASYNC_TX_XOR_ZERO_DST: this flag must be used for xor operations where the
+ * the destination address is not a source.  The asynchronous case handles this
+ * implicitly, the synchronous case needs to zero the destination block.
+ * @ASYNC_TX_XOR_DROP_DST: this flag must be used if the destination address is
+ * also one of the source addresses.  In the synchronous case the destination
+ * address is an implied source, whereas the asynchronous case it must be listed
+ * as a source.  The destination address must be the first address in the source
+ * array.
+ * @ASYNC_TX_ASSUME_COHERENT: skip cache maintenance operations
+ * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
+ * dependency chain
+ * @ASYNC_TX_DEP_ACK: ack the dependency descriptor.  Useful for chaining.
+ * @ASYNC_TX_KMAP_SRC: if the transaction is to be performed synchronously
+ * take an atomic mapping (KM_USER0) on the source page(s)
+ * @ASYNC_TX_KMAP_DST: if the transaction is to be performed synchronously
+ * take an atomic mapping (KM_USER0) on the dest page(s)
+ */
+enum async_tx_flags {
+	ASYNC_TX_XOR_ZERO_DST	 = (1 << 0),
+	ASYNC_TX_XOR_DROP_DST	 = (1 << 1),
+	ASYNC_TX_ASSUME_COHERENT = (1 << 2),
+	ASYNC_TX_ACK		 = (1 << 3),
+	ASYNC_TX_DEP_ACK	 = (1 << 4),
+	ASYNC_TX_KMAP_SRC	 = (1 << 5),
+	ASYNC_TX_KMAP_DST	 = (1 << 6),
+};
+
+#ifdef CONFIG_DMA_ENGINE
+void async_tx_issue_pending_all(void);
+enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
+void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx);
+struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+	enum dma_transaction_type tx_type);
+#else
+static inline void async_tx_issue_pending_all(void)
+{
+	do { } while (0);
+}
+
+static inline enum dma_status
+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+{
+	return DMA_SUCCESS;
+}
+
+static inline void
+async_tx_run_dependencies(struct dma_async_tx_descriptor *tx,
+	struct dma_chan *host_chan)
+{
+	do { } while (0);
+}
+
+static inline struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+	enum dma_transaction_type tx_type)
+{
+	return NULL;
+}
+#endif
+
+/**
+ * async_tx_sync_epilog - actions to take if an operation is run synchronously
+ * @flags: async_tx flags
+ * @depend_tx: transaction depends on depend_tx
+ * @cb_fn: function to call when the transaction completes
+ * @cb_fn_param: parameter to pass to the callback routine
+ */
+static inline void
+async_tx_sync_epilog(unsigned long flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_fn_param)
+{
+	if (cb_fn)
+		cb_fn(cb_fn_param);
+
+	if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
+		async_tx_ack(depend_tx);
+}
+
+void
+async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+	enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+	int src_cnt, size_t len, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_xor_zero_sum(struct page *dest, struct page **src_list,
+	unsigned int offset, int src_cnt, size_t len,
+	u32 *result, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+	unsigned int src_offset, size_t len, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_memset(struct page *dest, int val, unsigned int offset,
+	size_t len, enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_trigger_callback(enum async_tx_flags flags,
+	struct dma_async_tx_descriptor *depend_tx,
+	dma_async_tx_callback cb_fn, void *cb_fn_param);
+#endif /* _ASYNC_TX_H_ */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index edb31bf..b5a2016 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -126,6 +126,7 @@
 	ATA_REG_IRQ		= ATA_REG_NSECT,
 
 	/* ATA device commands */
+	ATA_CMD_DEV_RESET	= 0x08, /* ATAPI device reset */
 	ATA_CMD_CHK_POWER	= 0xE5, /* check power mode */
 	ATA_CMD_STANDBY		= 0xE2, /* place in standby power mode */
 	ATA_CMD_IDLE		= 0xE3, /* place in idle power mode */
@@ -151,6 +152,7 @@
 	ATA_CMD_WRITE_MULTI_EXT	= 0x39,
 	ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
 	ATA_CMD_SET_FEATURES	= 0xEF,
+	ATA_CMD_SET_MULTI	= 0xC6,
 	ATA_CMD_PACKET		= 0xA0,
 	ATA_CMD_VERIFY		= 0x40,
 	ATA_CMD_VERIFY_EXT	= 0x42,
@@ -162,6 +164,8 @@
 	ATA_CMD_SET_MAX		= 0xF9,
 	ATA_CMD_SET_MAX_EXT	= 0x37,
 	ATA_CMD_READ_LOG_EXT	= 0x2f,
+	ATA_CMD_PMP_READ	= 0xE4,
+	ATA_CMD_PMP_WRITE	= 0xE8,
 
 	/* READ_LOG_EXT pages */
 	ATA_LOG_SATA_NCQ	= 0x10,
@@ -210,6 +214,28 @@
 						   0=to device, 1=to host */
 	ATAPI_CDB_LEN		= 16,
 
+	/* PMP stuff */
+	SATA_PMP_MAX_PORTS	= 15,
+	SATA_PMP_CTRL_PORT	= 15,
+
+	SATA_PMP_GSCR_DWORDS	= 128,
+	SATA_PMP_GSCR_PROD_ID	= 0,
+	SATA_PMP_GSCR_REV	= 1,
+	SATA_PMP_GSCR_PORT_INFO	= 2,
+	SATA_PMP_GSCR_ERROR	= 32,
+	SATA_PMP_GSCR_ERROR_EN	= 33,
+	SATA_PMP_GSCR_FEAT	= 64,
+	SATA_PMP_GSCR_FEAT_EN	= 96,
+
+	SATA_PMP_PSCR_STATUS	= 0,
+	SATA_PMP_PSCR_ERROR	= 1,
+	SATA_PMP_PSCR_CONTROL	= 2,
+
+	SATA_PMP_FEAT_BIST	= (1 << 0),
+	SATA_PMP_FEAT_PMREQ	= (1 << 1),
+	SATA_PMP_FEAT_DYNSSC	= (1 << 2),
+	SATA_PMP_FEAT_NOTIFY	= (1 << 3),
+
 	/* cable types */
 	ATA_CBL_NONE		= 0,
 	ATA_CBL_PATA40		= 1,
@@ -249,7 +275,7 @@
 	/* ATA taskfile protocols */
 	ATA_PROT_UNKNOWN,	/* unknown/invalid */
 	ATA_PROT_NODATA,	/* no data */
-	ATA_PROT_PIO,		/* PIO single sector */
+	ATA_PROT_PIO,		/* PIO data xfer */
 	ATA_PROT_DMA,		/* DMA */
 	ATA_PROT_NCQ,		/* NCQ */
 	ATA_PROT_ATAPI,		/* packet command, PIO data xfer*/
@@ -416,4 +442,9 @@
 	return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
 }
 
+#define sata_pmp_gscr_vendor(gscr)	((gscr)[SATA_PMP_GSCR_PROD_ID] & 0xffff)
+#define sata_pmp_gscr_devid(gscr)	((gscr)[SATA_PMP_GSCR_PROD_ID] >> 16)
+#define sata_pmp_gscr_rev(gscr)		(((gscr)[SATA_PMP_GSCR_REV] >> 8) & 0xff)
+#define sata_pmp_gscr_ports(gscr)	((gscr)[SATA_PMP_GSCR_PORT_INFO] & 0xf)
+
 #endif /* __LINUX_ATA_H__ */
diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
index 93bfb0b..8ff2749 100644
--- a/include/linux/attribute_container.h
+++ b/include/linux/attribute_container.h
@@ -12,7 +12,6 @@
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/klist.h>
-#include <linux/spinlock.h>
 
 struct attribute_container {
 	struct list_head	node;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index fccc6e5..8ca7ca0 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -63,9 +63,12 @@
 #define AUDIT_ADD_RULE		1011	/* Add syscall filtering rule */
 #define AUDIT_DEL_RULE		1012	/* Delete syscall filtering rule */
 #define AUDIT_LIST_RULES	1013	/* List syscall filtering rules */
+#define AUDIT_TTY_GET		1014	/* Get TTY auditing status */
+#define AUDIT_TTY_SET		1015	/* Set TTY auditing status */
 
 #define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages mostly uninteresting to kernel */
 #define AUDIT_USER_AVC		1107	/* We filter this differently */
+#define AUDIT_USER_TTY		1124	/* Non-ICANON TTY input meaning */
 #define AUDIT_LAST_USER_MSG	1199
 #define AUDIT_FIRST_USER_MSG2	2100	/* More user space messages */
 #define AUDIT_LAST_USER_MSG2	2999
@@ -92,6 +95,7 @@
 #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
 #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
 #define AUDIT_OBJ_PID		1318	/* ptrace target */
+#define AUDIT_TTY		1319	/* Input on an administrative TTY */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -289,6 +293,10 @@
 	__u32		backlog;	/* messages waiting in queue */
 };
 
+struct audit_tty_status {
+	__u32		enabled; /* 1 = enabled, 0 = disabled */
+};
+
 /* audit_rule_data supports filter rules with both integer and string
  * fields.  It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
  * AUDIT_LIST_RULES requests.
@@ -515,11 +523,13 @@
 					     const char *prefix,
 					     struct dentry *dentry,
 					     struct vfsmount *vfsmnt);
+extern void		    audit_log_lost(const char *message);
 				/* Private API (for audit.c only) */
 extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
 extern int audit_filter_type(int type);
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
 			 void *data, size_t datasz, uid_t loginuid, u32 sid);
+extern int audit_enabled;
 #else
 #define audit_log(c,g,t,f,...) do { ; } while (0)
 #define audit_log_start(c,g,t) ({ NULL; })
@@ -530,6 +540,7 @@
 #define audit_log_untrustedstring(a,s) do { ; } while (0)
 #define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
 #define audit_log_d_path(b,p,d,v) do { ; } while (0)
+#define audit_enabled 0
 #endif
 #endif
 #endif
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index f2542c2..7011d625 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -93,7 +93,6 @@
 void clear_bdi_congested(struct backing_dev_info *bdi, int rw);
 void set_bdi_congested(struct backing_dev_info *bdi, int rw);
 long congestion_wait(int rw, long timeout);
-long congestion_wait_interruptible(int rw, long timeout);
 void congestion_end(int rw);
 
 #define bdi_cap_writeback_dirty(bdi) \
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index db5b00a..f78965f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -14,6 +14,7 @@
 #include <linux/bio.h>
 #include <linux/module.h>
 #include <linux/stringify.h>
+#include <linux/bsg.h>
 
 #include <asm/scatterlist.h>
 
@@ -41,6 +42,8 @@
 typedef struct elevator_queue elevator_t;
 struct request_pm_state;
 struct blk_trace;
+struct request;
+struct sg_io_hdr;
 
 #define BLKDEV_MIN_RQ	4
 #define BLKDEV_MAX_RQ	128	/* Default maximum */
@@ -314,6 +317,9 @@
 	 */
 	rq_end_io_fn *end_io;
 	void *end_io_data;
+
+	/* for bidi */
+	struct request *next_rq;
 };
 
 /*
@@ -468,6 +474,10 @@
 	unsigned int		bi_size;
 
 	struct mutex		sysfs_lock;
+
+#if defined(CONFIG_BLK_DEV_BSG)
+	struct bsg_class_device bsg_dev;
+#endif
 };
 
 #define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */
@@ -479,6 +489,7 @@
 #define QUEUE_FLAG_REENTER	6	/* Re-entrancy avoidance */
 #define QUEUE_FLAG_PLUGGED	7	/* queue is plugged */
 #define QUEUE_FLAG_ELVSWITCH	8	/* don't use elevator, just do FIFO */
+#define QUEUE_FLAG_BIDI		9	/* queue supports bidi requests */
 
 enum {
 	/*
@@ -543,6 +554,7 @@
 #define blk_sorted_rq(rq)	((rq)->cmd_flags & REQ_SORTED)
 #define blk_barrier_rq(rq)	((rq)->cmd_flags & REQ_HARDBARRIER)
 #define blk_fua_rq(rq)		((rq)->cmd_flags & REQ_FUA)
+#define blk_bidi_rq(rq)		((rq)->next_rq != NULL)
 
 #define list_entry_rq(ptr)	list_entry((ptr), struct request, queuelist)
 
@@ -607,7 +619,12 @@
 #define BLK_BOUNCE_ANY		((u64)blk_max_pfn << PAGE_SHIFT)
 #define BLK_BOUNCE_ISA		(ISA_DMA_THRESHOLD)
 
-#ifdef CONFIG_MMU
+/*
+ * default timeout for SG_IO if none specified
+ */
+#define BLK_DEFAULT_SG_TIMEOUT	(60 * HZ)
+
+#ifdef CONFIG_BOUNCE
 extern int init_emergency_isa_pool(void);
 extern void blk_queue_bounce(request_queue_t *q, struct bio **bio);
 #else
@@ -637,7 +654,8 @@
 extern void blk_plug_device(request_queue_t *);
 extern int blk_remove_plug(request_queue_t *);
 extern void blk_recount_segments(request_queue_t *, struct bio *);
-extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
+extern int scsi_cmd_ioctl(struct file *, struct request_queue *,
+			  struct gendisk *, unsigned int, void __user *);
 extern int sg_scsi_ioctl(struct file *, struct request_queue *,
 		struct gendisk *, struct scsi_ioctl_command __user *);
 
@@ -680,6 +698,12 @@
 			  struct request *, int);
 extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
 				  struct request *, int, rq_end_io_fn *);
+extern int blk_fill_sghdr_rq(request_queue_t *, struct request *,
+		      struct sg_io_hdr *, int);
+extern int blk_unmap_sghdr_rq(struct request *, struct sg_io_hdr *);
+extern int blk_complete_sghdr_rq(struct request *, struct sg_io_hdr *,
+			  struct bio *);
+extern int blk_verify_command(unsigned char *, int);
 
 static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
 {
@@ -868,11 +892,6 @@
  */
 #define buffer_heads_over_limit 0
 
-static inline long blk_congestion_wait(int rw, long timeout)
-{
-	return io_schedule_timeout(timeout);
-}
-
 static inline long nr_blockdev_pages(void)
 {
 	return 0;
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 0365ec9..c83534e 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -59,6 +59,7 @@
 				  unsigned long align,
 				  unsigned long goal,
 				  unsigned long limit);
+extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size);
 
 #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
 extern void reserve_bootmem(unsigned long addr, unsigned long size);
diff --git a/include/linux/bsg.h b/include/linux/bsg.h
new file mode 100644
index 0000000..8547b10
--- /dev/null
+++ b/include/linux/bsg.h
@@ -0,0 +1,69 @@
+#ifndef BSG_H
+#define BSG_H
+
+#define BSG_PROTOCOL_SCSI		0
+
+#define BSG_SUB_PROTOCOL_SCSI_CMD	0
+#define BSG_SUB_PROTOCOL_SCSI_TMF	1
+#define BSG_SUB_PROTOCOL_SCSI_TRANSPORT	2
+
+struct sg_io_v4 {
+	__s32 guard;		/* [i] 'Q' to differentiate from v3 */
+	__u32 protocol;		/* [i] 0 -> SCSI , .... */
+	__u32 subprotocol;	/* [i] 0 -> SCSI command, 1 -> SCSI task
+				   management function, .... */
+
+	__u32 request_len;	/* [i] in bytes */
+	__u64 request;		/* [i], [*i] {SCSI: cdb} */
+	__u32 request_attr;	/* [i] {SCSI: task attribute} */
+	__u32 request_tag;	/* [i] {SCSI: task tag (only if flagged)} */
+	__u32 request_priority;	/* [i] {SCSI: task priority} */
+	__u32 max_response_len;	/* [i] in bytes */
+	__u64 response;		/* [i], [*o] {SCSI: (auto)sense data} */
+
+	/* "din_" for data in (from device); "dout_" for data out (to device) */
+	__u32 dout_xfer_len;	/* [i] bytes to be transferred to device */
+	__u32 din_xfer_len;	/* [i] bytes to be transferred from device */
+	__u64 dout_xferp;	/* [i], [*i] */
+	__u64 din_xferp;	/* [i], [*o] */
+
+	__u32 timeout;		/* [i] units: millisecond */
+	__u32 flags;		/* [i] bit mask */
+	__u64 usr_ptr;		/* [i->o] unused internally */
+	__u32 spare_in;		/* [i] */
+
+	__u32 driver_status;	/* [o] 0 -> ok */
+	__u32 transport_status;	/* [o] 0 -> ok */
+	__u32 device_status;	/* [o] {SCSI: command completion status} */
+	__u32 retry_delay;	/* [o] {SCSI: status auxiliary information} */
+	__u32 info;		/* [o] additional information */
+	__u32 duration;		/* [o] time to complete, in milliseconds */
+	__u32 response_len;	/* [o] bytes of response actually written */
+	__s32 din_resid;	/* [o] actual_din_xfer_len - din_xfer_len */
+	__u32 generated_tag;	/* [o] {SCSI: task tag that transport chose} */
+	__u32 spare_out;	/* [o] */
+
+	__u32 padding;
+};
+
+#ifdef __KERNEL__
+
+#if defined(CONFIG_BLK_DEV_BSG)
+struct bsg_class_device {
+	struct class_device *class_dev;
+	struct device *dev;
+	int minor;
+	struct list_head list;
+	struct request_queue *queue;
+};
+
+extern int bsg_register_queue(struct request_queue *, const char *);
+extern void bsg_unregister_queue(struct request_queue *);
+#else
+#define bsg_register_queue(disk, name)		(0)
+#define bsg_unregister_queue(disk)	do { } while (0)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/linux/bug.h b/include/linux/bug.h
index 42aa0a5..54398d2 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -10,6 +10,8 @@
 	BUG_TRAP_TYPE_BUG = 2,
 };
 
+struct pt_regs;
+
 #ifdef CONFIG_GENERIC_BUG
 #include <asm-generic/bug.h>
 
@@ -20,7 +22,7 @@
 
 const struct bug_entry *find_bug(unsigned long bugaddr);
 
-enum bug_trap_type report_bug(unsigned long bug_addr);
+enum bug_trap_type report_bug(unsigned long bug_addr, struct pt_regs *regs);
 
 int  module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
 			 struct module *);
@@ -31,7 +33,8 @@
 
 #else	/* !CONFIG_GENERIC_BUG */
 
-static inline enum bug_trap_type report_bug(unsigned long bug_addr)
+static inline enum bug_trap_type report_bug(unsigned long bug_addr,
+					    struct pt_regs *regs)
 {
 	return BUG_TRAP_TYPE_BUG;
 }
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 6548b35..2dfa585 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -16,6 +16,8 @@
 #include <linux/types.h>
 #include <linux/compiler.h>
 
+struct task_struct;
+
 /* User-level do most of the mapping between kernel and user
    capabilities based on the version tag given by the kernel. The
    kernel might be somewhat backwards compatible, but don't bet on
@@ -42,7 +44,6 @@
   
 #ifdef __KERNEL__
 
-#include <linux/spinlock.h>
 #include <asm/current.h>
 
 /* #define STRICT_CAP_T_TYPECHECKS */
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index f50f04b..2b641b1 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -414,8 +414,8 @@
 #define CDO_CHECK_TYPE		0x10    /* check type on open for data */
 
 /* Special codes used when specifying changer slots. */
-#define CDSL_NONE       	((int) (~0U>>1)-1)
-#define CDSL_CURRENT    	((int) (~0U>>1))
+#define CDSL_NONE       	(INT_MAX-1)
+#define CDSL_CURRENT    	INT_MAX
 
 /* For partition based multisession access. IDE can handle 64 partitions
  * per drive - SCSI CD-ROM's use minors to differentiate between the
diff --git a/include/linux/cobalt-nvram.h b/include/linux/cobalt-nvram.h
deleted file mode 100644
index ea42956..0000000
--- a/include/linux/cobalt-nvram.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * $Id: cobalt-nvram.h,v 1.20 2001/10/17 23:16:55 thockin Exp $
- * cobalt-nvram.h : defines for the various fields in the cobalt NVRAM
- *
- * Copyright 2001,2002 Sun Microsystems, Inc.
- */
-
-#ifndef COBALT_NVRAM_H
-#define COBALT_NVRAM_H
-
-#include <linux/nvram.h>
-
-#define COBT_CMOS_INFO_MAX		0x7f	/* top address allowed */
-#define COBT_CMOS_BIOS_DRIVE_INFO	0x12	/* drive info would go here */
-
-#define COBT_CMOS_CKS_START		NVRAM_OFFSET(0x0e)
-#define COBT_CMOS_CKS_END		NVRAM_OFFSET(0x7f)
-
-/* flag bytes - 16 flags for now, leave room for more */
-#define COBT_CMOS_FLAG_BYTE_0		NVRAM_OFFSET(0x10)
-#define COBT_CMOS_FLAG_BYTE_1		NVRAM_OFFSET(0x11)
-
-/* flags in flag bytes - up to 16 */
-#define COBT_CMOS_FLAG_MIN		0x0001
-#define COBT_CMOS_CONSOLE_FLAG		0x0001 /* console on/off */
-#define COBT_CMOS_DEBUG_FLAG		0x0002 /* ROM debug messages */
-#define COBT_CMOS_AUTO_PROMPT_FLAG	0x0004 /* boot to ROM prompt? */
-#define COBT_CMOS_CLEAN_BOOT_FLAG	0x0008 /* set by a clean shutdown */
-#define COBT_CMOS_HW_NOPROBE_FLAG	0x0010 /* go easy on the probing */
-#define COBT_CMOS_SYSFAULT_FLAG		0x0020 /* system fault detected */
-#define COBT_CMOS_OOPSPANIC_FLAG	0x0040 /* panic on oops */
-#define COBT_CMOS_DELAY_CACHE_FLAG	0x0080 /* delay cache initialization */
-#define COBT_CMOS_NOLOGO_FLAG		0x0100 /* hide "C" logo @ boot */
-#define COBT_CMOS_VERSION_FLAG		0x0200 /* the version field is valid */
-#define COBT_CMOS_FLAG_MAX		0x0200
-
-/* leave byte 0x12 blank - Linux looks for drive info here */
-
-/* CMOS structure version, valid if COBT_CMOS_VERSION_FLAG is true */
-#define COBT_CMOS_VERSION		NVRAM_OFFSET(0x13)
-#define COBT_CMOS_VER_BTOCODE		1 /* min. version needed for btocode */
-
-/* index of default boot method */
-#define COBT_CMOS_BOOT_METHOD		NVRAM_OFFSET(0x20)
-#define COBT_CMOS_BOOT_METHOD_DISK	0
-#define COBT_CMOS_BOOT_METHOD_ROM	1
-#define COBT_CMOS_BOOT_METHOD_NET	2
-
-#define COBT_CMOS_BOOT_DEV_MIN		NVRAM_OFFSET(0x21)
-/* major #, minor # of first through fourth boot device */
-#define COBT_CMOS_BOOT_DEV0_MAJ		NVRAM_OFFSET(0x21)
-#define COBT_CMOS_BOOT_DEV0_MIN		NVRAM_OFFSET(0x22)
-#define COBT_CMOS_BOOT_DEV1_MAJ		NVRAM_OFFSET(0x23)
-#define COBT_CMOS_BOOT_DEV1_MIN		NVRAM_OFFSET(0x24)
-#define COBT_CMOS_BOOT_DEV2_MAJ		NVRAM_OFFSET(0x25)
-#define COBT_CMOS_BOOT_DEV2_MIN		NVRAM_OFFSET(0x26)
-#define COBT_CMOS_BOOT_DEV3_MAJ		NVRAM_OFFSET(0x27)
-#define COBT_CMOS_BOOT_DEV3_MIN		NVRAM_OFFSET(0x28)
-#define COBT_CMOS_BOOT_DEV_MAX		NVRAM_OFFSET(0x28)
-
-/* checksum of bytes 0xe-0x7f */
-#define COBT_CMOS_CHECKSUM		NVRAM_OFFSET(0x2e)
-
-/* running uptime counter, units of 5 minutes (32 bits =~ 41000 years) */
-#define COBT_CMOS_UPTIME_0		NVRAM_OFFSET(0x30)
-#define COBT_CMOS_UPTIME_1		NVRAM_OFFSET(0x31)
-#define COBT_CMOS_UPTIME_2		NVRAM_OFFSET(0x32)
-#define COBT_CMOS_UPTIME_3		NVRAM_OFFSET(0x33)
-
-/* count of successful boots (32 bits) */
-#define COBT_CMOS_BOOTCOUNT_0		NVRAM_OFFSET(0x38)
-#define COBT_CMOS_BOOTCOUNT_1		NVRAM_OFFSET(0x39)
-#define COBT_CMOS_BOOTCOUNT_2		NVRAM_OFFSET(0x3a)
-#define COBT_CMOS_BOOTCOUNT_3		NVRAM_OFFSET(0x3b)
-
-/* 13 bytes: system serial number, same as on the back of the system */
-#define COBT_CMOS_SYS_SERNUM_LEN	13
-#define COBT_CMOS_SYS_SERNUM_0		NVRAM_OFFSET(0x40)
-#define COBT_CMOS_SYS_SERNUM_1		NVRAM_OFFSET(0x41)
-#define COBT_CMOS_SYS_SERNUM_2		NVRAM_OFFSET(0x42)
-#define COBT_CMOS_SYS_SERNUM_3		NVRAM_OFFSET(0x43)
-#define COBT_CMOS_SYS_SERNUM_4		NVRAM_OFFSET(0x44)
-#define COBT_CMOS_SYS_SERNUM_5		NVRAM_OFFSET(0x45)
-#define COBT_CMOS_SYS_SERNUM_6		NVRAM_OFFSET(0x46)
-#define COBT_CMOS_SYS_SERNUM_7		NVRAM_OFFSET(0x47)
-#define COBT_CMOS_SYS_SERNUM_8		NVRAM_OFFSET(0x48)
-#define COBT_CMOS_SYS_SERNUM_9		NVRAM_OFFSET(0x49)
-#define COBT_CMOS_SYS_SERNUM_10		NVRAM_OFFSET(0x4a)
-#define COBT_CMOS_SYS_SERNUM_11		NVRAM_OFFSET(0x4b)
-#define COBT_CMOS_SYS_SERNUM_12		NVRAM_OFFSET(0x4c)
-/* checksum for serial num - 1 byte */
-#define COBT_CMOS_SYS_SERNUM_CSUM	NVRAM_OFFSET(0x4f)
-
-#define COBT_CMOS_ROM_REV_MAJ		NVRAM_OFFSET(0x50)
-#define COBT_CMOS_ROM_REV_MIN		NVRAM_OFFSET(0x51)
-#define COBT_CMOS_ROM_REV_REV		NVRAM_OFFSET(0x52)
-
-#define COBT_CMOS_BTO_CODE_0		NVRAM_OFFSET(0x53)
-#define COBT_CMOS_BTO_CODE_1		NVRAM_OFFSET(0x54)
-#define COBT_CMOS_BTO_CODE_2		NVRAM_OFFSET(0x55)
-#define COBT_CMOS_BTO_CODE_3		NVRAM_OFFSET(0x56)
-
-#define COBT_CMOS_BTO_IP_CSUM		NVRAM_OFFSET(0x57)
-#define COBT_CMOS_BTO_IP_0		NVRAM_OFFSET(0x58)
-#define COBT_CMOS_BTO_IP_1		NVRAM_OFFSET(0x59)
-#define COBT_CMOS_BTO_IP_2		NVRAM_OFFSET(0x5a)
-#define COBT_CMOS_BTO_IP_3		NVRAM_OFFSET(0x5b)
-
-#endif /* COBALT_NVRAM_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 498c3592..8287a72 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -36,9 +36,7 @@
 
 #ifdef __KERNEL__
 
-#if __GNUC__ > 4
-#error no compiler-gcc.h file for this gcc version
-#elif __GNUC__ == 4
+#if __GNUC__ >= 4
 # include <linux/compiler-gcc4.h>
 #elif __GNUC__ == 3 && __GNUC_MINOR__ >= 2
 # include <linux/compiler-gcc3.h>
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index fef6f3d..8c6967f 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -40,9 +40,9 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/kref.h>
+#include <linux/mutex.h>
 
 #include <asm/atomic.h>
-#include <asm/semaphore.h>
 
 #define CONFIGFS_ITEM_NAME_LEN	20
 
@@ -75,7 +75,6 @@
 extern void config_item_init_type_name(struct config_item *item,
 				       const char *name,
 				       struct config_item_type *type);
-extern void config_item_cleanup(struct config_item *);
 
 extern struct config_item * config_item_get(struct config_item *);
 extern void config_item_put(struct config_item *);
@@ -87,12 +86,10 @@
 	struct configfs_attribute		**ct_attrs;
 };
 
-
 /**
  *	group - a group of config_items of a specific type, belonging
  *	to a specific subsystem.
  */
-
 struct config_group {
 	struct config_item		cg_item;
 	struct list_head		cg_children;
@@ -100,13 +97,11 @@
 	struct config_group		**default_groups;
 };
 
-
 extern void config_group_init(struct config_group *group);
 extern void config_group_init_type_name(struct config_group *group,
 					const char *name,
 					struct config_item_type *type);
 
-
 static inline struct config_group *to_config_group(struct config_item *item)
 {
 	return item ? container_of(item,struct config_group,cg_item) : NULL;
@@ -122,7 +117,8 @@
 	config_item_put(&group->cg_item);
 }
 
-extern struct config_item *config_group_find_obj(struct config_group *, const char *);
+extern struct config_item *config_group_find_item(struct config_group *,
+						  const char *);
 
 
 struct configfs_attribute {
@@ -131,6 +127,22 @@
 	mode_t			ca_mode;
 };
 
+/*
+ * Users often need to create attribute structures for their configurable
+ * attributes, containing a configfs_attribute member and function pointers
+ * for the show() and store() operations on that attribute. They can use
+ * this macro (similar to sysfs' __ATTR) to make defining attributes easier.
+ */
+#define __CONFIGFS_ATTR(_name, _mode, _show, _store)			\
+{									\
+	.attr	= {							\
+			.ca_name = __stringify(_name),			\
+			.ca_mode = _mode,				\
+			.ca_owner = THIS_MODULE,			\
+	},								\
+	.show	= _show,						\
+	.store	= _store,						\
+}
 
 /*
  * If allow_link() exists, the item can symlink(2) out to other
@@ -157,12 +169,13 @@
 	struct config_item *(*make_item)(struct config_group *group, const char *name);
 	struct config_group *(*make_group)(struct config_group *group, const char *name);
 	int (*commit_item)(struct config_item *item);
+	void (*disconnect_notify)(struct config_group *group, struct config_item *item);
 	void (*drop_item)(struct config_group *group, struct config_item *item);
 };
 
 struct configfs_subsystem {
 	struct config_group	su_group;
-	struct semaphore	su_sem;
+	struct mutex		su_mutex;
 };
 
 static inline struct configfs_subsystem *to_configfs_subsystem(struct config_group *group)
@@ -175,6 +188,11 @@
 int configfs_register_subsystem(struct configfs_subsystem *subsys);
 void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
 
+/* These functions can sleep and can alloc with GFP_KERNEL */
+/* WARNING: These cannot be called underneath configfs callbacks!! */
+int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
+void configfs_undepend_item(struct configfs_subsystem *subsys, struct config_item *target);
+
 #endif  /* __KERNEL__ */
 
 #endif /* _CONFIGFS_H_ */
diff --git a/include/linux/console.h b/include/linux/console.h
index 62ef6e1..56a7bcd 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -15,7 +15,6 @@
 #define _LINUX_CONSOLE_H_ 1
 
 #include <linux/types.h>
-#include <linux/spinlock.h>
 
 struct vc_data;
 struct console_font_op;
@@ -99,6 +98,7 @@
 	struct tty_driver *(*device)(struct console *, int *);
 	void	(*unblank)(void);
 	int	(*setup)(struct console *, char *);
+	int	(*early_setup)(void);
 	short	flags;
 	short	index;
 	int	cflag;
@@ -107,6 +107,7 @@
 };
 
 extern int add_preferred_console(char *name, int idx, char *options);
+extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
 extern void register_console(struct console *);
 extern int unregister_console(struct console *);
 extern struct console *console_drivers;
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index a461f76..dc77fed 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -9,6 +9,9 @@
  * to achieve effects such as fast scrolling by changing the origin.
  */
 
+#ifndef _LINUX_CONSOLE_STRUCT_H
+#define _LINUX_CONSOLE_STRUCT_H
+
 #include <linux/wait.h>
 #include <linux/vt.h>
 #include <linux/workqueue.h>
@@ -130,3 +133,5 @@
 #define CUR_DEFAULT CUR_UNDERLINE
 
 #define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
+
+#endif /* _LINUX_CONSOLE_STRUCT_H */
diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h
index 82c9a1f..06b2768 100644
--- a/include/linux/consolemap.h
+++ b/include/linux/consolemap.h
@@ -8,9 +8,12 @@
 #define IBMPC_MAP 2
 #define USER_MAP 3
 
+#include <linux/types.h>
+
 struct vc_data;
 
-extern unsigned char inverse_translate(struct vc_data *conp, int glyph);
+extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode);
 extern unsigned short *set_translate(int m, struct vc_data *vc);
 extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
+extern u32 conv_8bit_to_uni(unsigned char c);
 void console_map_init(void);
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 3b2df25..c2236bb 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -120,7 +120,6 @@
 
 #define lock_cpu_hotplug()	do { } while (0)
 #define unlock_cpu_hotplug()	do { } while (0)
-#define lock_cpu_hotplug_interruptible() 0
 #define hotcpu_notifier(fn, pri)	do { (void)(fn); } while (0)
 #define register_hotcpu_notifier(nb)	do { (void)(nb); } while (0)
 #define unregister_hotcpu_notifier(nb)	do { (void)(nb); } while (0)
diff --git a/include/linux/crc7.h b/include/linux/crc7.h
new file mode 100644
index 0000000..1786e77
--- /dev/null
+++ b/include/linux/crc7.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_CRC7_H
+#define _LINUX_CRC7_H
+#include <linux/types.h>
+
+extern const u8 crc7_syndrome_table[256];
+
+static inline u8 crc7_byte(u8 crc, u8 data)
+{
+	return crc7_syndrome_table[(crc << 1) ^ data];
+}
+
+extern u8 crc7(u8 crc, const u8 *buffer, size_t len);
+
+#endif
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 0de7e2a..357e8cf 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -295,28 +295,8 @@
 };
 
 struct cipher_tfm {
-	void *cit_iv;
-	unsigned int cit_ivsize;
-	u32 cit_mode;
 	int (*cit_setkey)(struct crypto_tfm *tfm,
 	                  const u8 *key, unsigned int keylen);
-	int (*cit_encrypt)(struct crypto_tfm *tfm,
-			   struct scatterlist *dst,
-			   struct scatterlist *src,
-			   unsigned int nbytes);
-	int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
-	                      struct scatterlist *dst,
-	                      struct scatterlist *src,
-	                      unsigned int nbytes, u8 *iv);
-	int (*cit_decrypt)(struct crypto_tfm *tfm,
-			   struct scatterlist *dst,
-			   struct scatterlist *src,
-			   unsigned int nbytes);
-	int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
-			   struct scatterlist *dst,
-			   struct scatterlist *src,
-			   unsigned int nbytes, u8 *iv);
-	void (*cit_xor_block)(u8 *dst, const u8 *src);
 	void (*cit_encrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 	void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 };
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 5a9c495..104e51e 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -38,6 +38,9 @@
 
 void debugfs_remove(struct dentry *dentry);
 
+struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+                struct dentry *new_dir, const char *new_name);
+
 struct dentry *debugfs_create_u8(const char *name, mode_t mode,
 				 struct dentry *parent, u8 *value);
 struct dentry *debugfs_create_u16(const char *name, mode_t mode,
@@ -85,6 +88,12 @@
 static inline void debugfs_remove(struct dentry *dentry)
 { }
 
+static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+                struct dentry *new_dir, char *new_name)
+{
+	return ERR_PTR(-ENODEV);
+}
+
 static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode,
 					       struct dentry *parent,
 					       u8 *value)
diff --git a/include/linux/device.h b/include/linux/device.h
index 2e1a298..be2debe 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -238,7 +238,6 @@
  * @devt: for internal use by the driver core only.
  * @node: for internal use by the driver core only.
  * @kobj: for internal use by the driver core only.
- * @devt_attr: for internal use by the driver core only.
  * @groups: optional additional groups to be created
  * @dev: if set, a symlink to the struct device is created in the sysfs
  * directory for this struct class device.
@@ -263,8 +262,6 @@
 	struct kobject		kobj;
 	struct class		* class;	/* required */
 	dev_t			devt;		/* dev_t, creates the sysfs "dev" */
-	struct class_device_attribute *devt_attr;
-	struct class_device_attribute uevent_attr;
 	struct device		* dev;		/* not necessary, but nice to have */
 	void			* class_data;	/* class-specific data */
 	struct class_device	*parent;	/* parent of this child device, if there is one */
@@ -419,8 +416,6 @@
 	struct device_type	*type;
 	unsigned		is_registered:1;
 	unsigned		uevent_suppress:1;
-	struct device_attribute uevent_attr;
-	struct device_attribute *devt_attr;
 
 	struct semaphore	sem;	/* semaphore to synchronize calls to
 					 * its driver.
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 1b1dcb9..be9d278 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -85,7 +85,11 @@
  * Only relevant to locks originating in userspace.  A persistent lock will not
  * be removed if the process holding the lock exits.
  *
- * DLM_LKF_NODLKWT
+ * DLM_LKF_NODLCKWT
+ *
+ * Do not cancel the lock if it gets into conversion deadlock.
+ * Exclude this lock from being monitored due to DLM_LSFL_TIMEWARN.
+ *
  * DLM_LKF_NODLCKBLK
  *
  * net yet implemented
@@ -149,6 +153,7 @@
 #define DLM_LKF_ALTPR		0x00008000
 #define DLM_LKF_ALTCW		0x00010000
 #define DLM_LKF_FORCEUNLOCK	0x00020000
+#define DLM_LKF_TIMEOUT		0x00040000
 
 /*
  * Some return codes that are not in errno.h
@@ -199,11 +204,12 @@
 	char *	 sb_lvbptr;
 };
 
+#define DLM_LSFL_NODIR		0x00000001
+#define DLM_LSFL_TIMEWARN	0x00000002
+#define DLM_LSFL_FS     	0x00000004
 
 #ifdef __KERNEL__
 
-#define DLM_LSFL_NODIR		0x00000001
-
 /*
  * dlm_new_lockspace
  *
diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
index c2735ca..9642277 100644
--- a/include/linux/dlm_device.h
+++ b/include/linux/dlm_device.h
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -18,21 +18,24 @@
 #define DLM_USER_LVB_LEN	32
 
 /* Version of the device interface */
-#define DLM_DEVICE_VERSION_MAJOR 5
-#define DLM_DEVICE_VERSION_MINOR 1
+#define DLM_DEVICE_VERSION_MAJOR 6
+#define DLM_DEVICE_VERSION_MINOR 0
 #define DLM_DEVICE_VERSION_PATCH 0
 
 /* struct passed to the lock write */
 struct dlm_lock_params {
 	__u8 mode;
 	__u8 namelen;
-	__u16 flags;
+	__u16 unused;
+	__u32 flags;
 	__u32 lkid;
 	__u32 parent;
-        void __user *castparam;
+	__u64 xid;
+	__u64 timeout;
+	void __user *castparam;
 	void __user *castaddr;
 	void __user *bastparam;
-        void __user *bastaddr;
+	void __user *bastaddr;
 	struct dlm_lksb __user *lksb;
 	char lvb[DLM_USER_LVB_LEN];
 	char name[0];
@@ -62,9 +65,15 @@
 	} i;
 };
 
+struct dlm_device_version {
+	__u32 version[3];
+};
+
 /* struct read from the "device" fd,
    consists mainly of userspace pointers for the library to use */
+
 struct dlm_lock_result {
+	__u32 version[3];
 	__u32 length;
 	void __user * user_astaddr;
 	void __user * user_astparam;
@@ -83,6 +92,7 @@
 #define DLM_USER_CREATE_LOCKSPACE  4
 #define DLM_USER_REMOVE_LOCKSPACE  5
 #define DLM_USER_PURGE        6
+#define DLM_USER_DEADLOCK     7
 
 /* Arbitrary length restriction */
 #define MAX_LS_NAME_LEN 64
diff --git a/include/linux/dlm_netlink.h b/include/linux/dlm_netlink.h
new file mode 100644
index 0000000..1927633
--- /dev/null
+++ b/include/linux/dlm_netlink.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc.  All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#ifndef _DLM_NETLINK_H
+#define _DLM_NETLINK_H
+
+enum {
+	DLM_STATUS_WAITING = 1,
+	DLM_STATUS_GRANTED = 2,
+	DLM_STATUS_CONVERT = 3,
+};
+
+#define DLM_LOCK_DATA_VERSION 1
+
+struct dlm_lock_data {
+	uint16_t version;
+	uint32_t lockspace_id;
+	int nodeid;
+	int ownpid;
+	uint32_t id;
+	uint32_t remid;
+	uint64_t xid;
+	int8_t status;
+	int8_t grmode;
+	int8_t rqmode;
+	unsigned long timestamp;
+	int resource_namelen;
+	char resource_name[DLM_RESNAME_MAXLEN];
+};
+
+enum {
+	DLM_CMD_UNSPEC = 0,
+	DLM_CMD_HELLO,		/* user->kernel */
+	DLM_CMD_TIMEOUT,	/* kernel->user */
+	__DLM_CMD_MAX,
+};
+
+#define DLM_CMD_MAX (__DLM_CMD_MAX - 1)
+
+enum {
+	DLM_TYPE_UNSPEC = 0,
+	DLM_TYPE_LOCK,
+	__DLM_TYPE_MAX,
+};
+
+#define DLM_TYPE_MAX (__DLM_TYPE_MAX - 1)
+
+#define DLM_GENL_VERSION 0x1
+#define DLM_GENL_NAME "DLM"
+
+#endif /* _DLM_NETLINK_H */
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 9a663c6..2dc21cb 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -31,7 +31,11 @@
 		(dma_direction == DMA_FROM_DEVICE));
 }
 
+#ifdef CONFIG_HAS_DMA
 #include <asm/dma-mapping.h>
+#else
+#include <asm-generic/dma-mapping-broken.h>
+#endif
 
 /* Backwards compat, remove in 2.7.x */
 #define dma_sync_single		dma_sync_single_for_cpu
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index c94d8f1..a3b6035 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -21,29 +21,40 @@
 #ifndef DMAENGINE_H
 #define DMAENGINE_H
 
-#ifdef CONFIG_DMA_ENGINE
-
 #include <linux/device.h>
 #include <linux/uio.h>
 #include <linux/kref.h>
 #include <linux/completion.h>
 #include <linux/rcupdate.h>
+#include <linux/dma-mapping.h>
 
 /**
- * enum dma_event - resource PNP/power managment events
+ * enum dma_state - resource PNP/power managment state
  * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
  * @DMA_RESOURCE_RESUME: DMA device returning to full power
- * @DMA_RESOURCE_ADDED: DMA device added to the system
+ * @DMA_RESOURCE_AVAILABLE: DMA device available to the system
  * @DMA_RESOURCE_REMOVED: DMA device removed from the system
  */
-enum dma_event {
+enum dma_state {
 	DMA_RESOURCE_SUSPEND,
 	DMA_RESOURCE_RESUME,
-	DMA_RESOURCE_ADDED,
+	DMA_RESOURCE_AVAILABLE,
 	DMA_RESOURCE_REMOVED,
 };
 
 /**
+ * enum dma_state_client - state of the channel in the client
+ * @DMA_ACK: client would like to use, or was using this channel
+ * @DMA_DUP: client has already seen this channel, or is not using this channel
+ * @DMA_NAK: client does not want to see any more channels
+ */
+enum dma_state_client {
+	DMA_ACK,
+	DMA_DUP,
+	DMA_NAK,
+};
+
+/**
  * typedef dma_cookie_t - an opaque DMA cookie
  *
  * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
@@ -65,6 +76,31 @@
 };
 
 /**
+ * enum dma_transaction_type - DMA transaction types/indexes
+ */
+enum dma_transaction_type {
+	DMA_MEMCPY,
+	DMA_XOR,
+	DMA_PQ_XOR,
+	DMA_DUAL_XOR,
+	DMA_PQ_UPDATE,
+	DMA_ZERO_SUM,
+	DMA_PQ_ZERO_SUM,
+	DMA_MEMSET,
+	DMA_MEMCPY_CRC32C,
+	DMA_INTERRUPT,
+};
+
+/* last transaction type for creation of the capabilities mask */
+#define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+
+/**
+ * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t.
+ * See linux/cpumask.h
+ */
+typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
+
+/**
  * struct dma_chan_percpu - the per-CPU part of struct dma_chan
  * @refcount: local_t used for open-coded "bigref" counting
  * @memcpy_count: transaction counter
@@ -80,7 +116,6 @@
 
 /**
  * struct dma_chan - devices supply DMA channels, clients use them
- * @client: ptr to the client user of this chan, will be %NULL when unused
  * @device: ptr to the dma device who supplies this channel, always !%NULL
  * @cookie: last cookie value returned to client
  * @chan_id: channel ID for sysfs
@@ -88,12 +123,10 @@
  * @refcount: kref, used in "bigref" slow-mode
  * @slow_ref: indicates that the DMA channel is free
  * @rcu: the DMA channel's RCU head
- * @client_node: used to add this to the client chan list
  * @device_node: used to add this to the device chan list
  * @local: per-cpu pointer to a struct dma_chan_percpu
  */
 struct dma_chan {
-	struct dma_client *client;
 	struct dma_device *device;
 	dma_cookie_t cookie;
 
@@ -105,11 +138,11 @@
 	int slow_ref;
 	struct rcu_head rcu;
 
-	struct list_head client_node;
 	struct list_head device_node;
 	struct dma_chan_percpu *local;
 };
 
+
 void dma_chan_cleanup(struct kref *kref);
 
 static inline void dma_chan_get(struct dma_chan *chan)
@@ -134,169 +167,206 @@
 
 /*
  * typedef dma_event_callback - function pointer to a DMA event callback
+ * For each channel added to the system this routine is called for each client.
+ * If the client would like to use the channel it returns '1' to signal (ack)
+ * the dmaengine core to take out a reference on the channel and its
+ * corresponding device.  A client must not 'ack' an available channel more
+ * than once.  When a channel is removed all clients are notified.  If a client
+ * is using the channel it must 'ack' the removal.  A client must not 'ack' a
+ * removed channel more than once.
+ * @client - 'this' pointer for the client context
+ * @chan - channel to be acted upon
+ * @state - available or removed
  */
-typedef void (*dma_event_callback) (struct dma_client *client,
-		struct dma_chan *chan, enum dma_event event);
+struct dma_client;
+typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client,
+		struct dma_chan *chan, enum dma_state state);
 
 /**
  * struct dma_client - info on the entity making use of DMA services
  * @event_callback: func ptr to call when something happens
- * @chan_count: number of chans allocated
- * @chans_desired: number of chans requested. Can be +/- chan_count
- * @lock: protects access to the channels list
- * @channels: the list of DMA channels allocated
+ * @cap_mask: only return channels that satisfy the requested capabilities
+ *  a value of zero corresponds to any capability
  * @global_node: list_head for global dma_client_list
  */
 struct dma_client {
 	dma_event_callback	event_callback;
-	unsigned int		chan_count;
-	unsigned int		chans_desired;
-
-	spinlock_t		lock;
-	struct list_head	channels;
+	dma_cap_mask_t		cap_mask;
 	struct list_head	global_node;
 };
 
+typedef void (*dma_async_tx_callback)(void *dma_async_param);
+/**
+ * struct dma_async_tx_descriptor - async transaction descriptor
+ * ---dma generic offload fields---
+ * @cookie: tracking cookie for this transaction, set to -EBUSY if
+ *	this tx is sitting on a dependency list
+ * @ack: the descriptor can not be reused until the client acknowledges
+ *	receipt, i.e. has has a chance to establish any dependency chains
+ * @phys: physical address of the descriptor
+ * @tx_list: driver common field for operations that require multiple
+ *	descriptors
+ * @chan: target channel for this operation
+ * @tx_submit: set the prepared descriptor(s) to be executed by the engine
+ * @tx_set_dest: set a destination address in a hardware descriptor
+ * @tx_set_src: set a source address in a hardware descriptor
+ * @callback: routine to call after this operation is complete
+ * @callback_param: general parameter to pass to the callback routine
+ * ---async_tx api specific fields---
+ * @depend_list: at completion this list of transactions are submitted
+ * @depend_node: allow this transaction to be executed after another
+ *	transaction has completed, possibly on another channel
+ * @parent: pointer to the next level up in the dependency chain
+ * @lock: protect the dependency list
+ */
+struct dma_async_tx_descriptor {
+	dma_cookie_t cookie;
+	int ack;
+	dma_addr_t phys;
+	struct list_head tx_list;
+	struct dma_chan *chan;
+	dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
+	void (*tx_set_dest)(dma_addr_t addr,
+		struct dma_async_tx_descriptor *tx, int index);
+	void (*tx_set_src)(dma_addr_t addr,
+		struct dma_async_tx_descriptor *tx, int index);
+	dma_async_tx_callback callback;
+	void *callback_param;
+	struct list_head depend_list;
+	struct list_head depend_node;
+	struct dma_async_tx_descriptor *parent;
+	spinlock_t lock;
+};
+
 /**
  * struct dma_device - info on the entity supplying DMA services
  * @chancnt: how many DMA channels are supported
  * @channels: the list of struct dma_chan
  * @global_node: list_head for global dma_device_list
+ * @cap_mask: one or more dma_capability flags
+ * @max_xor: maximum number of xor sources, 0 if no capability
  * @refcount: reference count
  * @done: IO completion struct
  * @dev_id: unique device ID
+ * @dev: struct device reference for dma mapping api
  * @device_alloc_chan_resources: allocate resources and return the
  *	number of allocated descriptors
  * @device_free_chan_resources: release DMA channel's resources
- * @device_memcpy_buf_to_buf: memcpy buf pointer to buf pointer
- * @device_memcpy_buf_to_pg: memcpy buf pointer to struct page
- * @device_memcpy_pg_to_pg: memcpy struct page/offset to struct page/offset
- * @device_memcpy_complete: poll the status of an IOAT DMA transaction
- * @device_memcpy_issue_pending: push appended descriptors to hardware
+ * @device_prep_dma_memcpy: prepares a memcpy operation
+ * @device_prep_dma_xor: prepares a xor operation
+ * @device_prep_dma_zero_sum: prepares a zero_sum operation
+ * @device_prep_dma_memset: prepares a memset operation
+ * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+ * @device_dependency_added: async_tx notifies the channel about new deps
+ * @device_issue_pending: push pending transactions to hardware
  */
 struct dma_device {
 
 	unsigned int chancnt;
 	struct list_head channels;
 	struct list_head global_node;
+	dma_cap_mask_t  cap_mask;
+	int max_xor;
 
 	struct kref refcount;
 	struct completion done;
 
 	int dev_id;
+	struct device *dev;
 
 	int (*device_alloc_chan_resources)(struct dma_chan *chan);
 	void (*device_free_chan_resources)(struct dma_chan *chan);
-	dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
-			void *dest, void *src, size_t len);
-	dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
-			struct page *page, unsigned int offset, void *kdata,
-			size_t len);
-	dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
-			struct page *dest_pg, unsigned int dest_off,
-			struct page *src_pg, unsigned int src_off, size_t len);
-	enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
+
+	struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
+		struct dma_chan *chan, size_t len, int int_en);
+	struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
+		struct dma_chan *chan, unsigned int src_cnt, size_t len,
+		int int_en);
+	struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(
+		struct dma_chan *chan, unsigned int src_cnt, size_t len,
+		u32 *result, int int_en);
+	struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
+		struct dma_chan *chan, int value, size_t len, int int_en);
+	struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
+		struct dma_chan *chan);
+
+	void (*device_dependency_added)(struct dma_chan *chan);
+	enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
 			dma_cookie_t cookie, dma_cookie_t *last,
 			dma_cookie_t *used);
-	void (*device_memcpy_issue_pending)(struct dma_chan *chan);
+	void (*device_issue_pending)(struct dma_chan *chan);
 };
 
 /* --- public DMA engine API --- */
 
-struct dma_client *dma_async_client_register(dma_event_callback event_callback);
+void dma_async_client_register(struct dma_client *client);
 void dma_async_client_unregister(struct dma_client *client);
-void dma_async_client_chan_request(struct dma_client *client,
-		unsigned int number);
-
-/**
- * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
- * @chan: DMA channel to offload copy to
- * @dest: destination address (virtual)
- * @src: source address (virtual)
- * @len: length
- *
- * Both @dest and @src must be mappable to a bus address according to the
- * DMA mapping API rules for streaming mappings.
- * Both @dest and @src must stay memory resident (kernel memory or locked
- * user space pages).
- */
-static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
-	void *dest, void *src, size_t len)
-{
-	int cpu = get_cpu();
-	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-	put_cpu();
-
-	return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
-}
-
-/**
- * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
- * @chan: DMA channel to offload copy to
- * @page: destination page
- * @offset: offset in page to copy to
- * @kdata: source address (virtual)
- * @len: length
- *
- * Both @page/@offset and @kdata must be mappable to a bus address according
- * to the DMA mapping API rules for streaming mappings.
- * Both @page/@offset and @kdata must stay memory resident (kernel memory or
- * locked user space pages)
- */
-static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
-	struct page *page, unsigned int offset, void *kdata, size_t len)
-{
-	int cpu = get_cpu();
-	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-	put_cpu();
-
-	return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
-	                                             kdata, len);
-}
-
-/**
- * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
- * @chan: DMA channel to offload copy to
- * @dest_pg: destination page
- * @dest_off: offset in page to copy to
- * @src_pg: source page
- * @src_off: offset in page to copy from
- * @len: length
- *
- * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
- * address according to the DMA mapping API rules for streaming mappings.
- * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
- * (kernel memory or locked user space pages).
- */
-static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
+void dma_async_client_chan_request(struct dma_client *client);
+dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
+	void *dest, void *src, size_t len);
+dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
+	struct page *page, unsigned int offset, void *kdata, size_t len);
+dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
 	struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
-	unsigned int src_off, size_t len)
-{
-	int cpu = get_cpu();
-	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-	put_cpu();
+	unsigned int src_off, size_t len);
+void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+	struct dma_chan *chan);
 
-	return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
-	                                            src_pg, src_off, len);
+static inline void
+async_tx_ack(struct dma_async_tx_descriptor *tx)
+{
+	tx->ack = 1;
 }
 
+#define first_dma_cap(mask) __first_dma_cap(&(mask))
+static inline int __first_dma_cap(const dma_cap_mask_t *srcp)
+{
+	return min_t(int, DMA_TX_TYPE_END,
+		find_first_bit(srcp->bits, DMA_TX_TYPE_END));
+}
+
+#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask))
+static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp)
+{
+	return min_t(int, DMA_TX_TYPE_END,
+		find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1));
+}
+
+#define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask))
+static inline void
+__dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp)
+{
+	set_bit(tx_type, dstp->bits);
+}
+
+#define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask))
+static inline int
+__dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp)
+{
+	return test_bit(tx_type, srcp->bits);
+}
+
+#define for_each_dma_cap_mask(cap, mask) \
+	for ((cap) = first_dma_cap(mask);	\
+		(cap) < DMA_TX_TYPE_END;	\
+		(cap) = next_dma_cap((cap), (mask)))
+
 /**
- * dma_async_memcpy_issue_pending - flush pending copies to HW
+ * dma_async_issue_pending - flush pending transactions to HW
  * @chan: target DMA channel
  *
  * This allows drivers to push copies to HW in batches,
  * reducing MMIO writes where possible.
  */
-static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
+static inline void dma_async_issue_pending(struct dma_chan *chan)
 {
-	return chan->device->device_memcpy_issue_pending(chan);
+	return chan->device->device_issue_pending(chan);
 }
 
+#define dma_async_memcpy_issue_pending(chan) dma_async_issue_pending(chan)
+
 /**
- * dma_async_memcpy_complete - poll for transaction completion
+ * dma_async_is_tx_complete - poll for transaction completion
  * @chan: DMA channel
  * @cookie: transaction identifier to check status of
  * @last: returns last completed cookie, can be NULL
@@ -306,12 +376,15 @@
  * internal state and can be used with dma_async_is_complete() to check
  * the status of multiple cookies without re-checking hardware state.
  */
-static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
+static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
 	dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
 {
-	return chan->device->device_memcpy_complete(chan, cookie, last, used);
+	return chan->device->device_is_tx_complete(chan, cookie, last, used);
 }
 
+#define dma_async_memcpy_complete(chan, cookie, last, used)\
+	dma_async_is_tx_complete(chan, cookie, last, used)
+
 /**
  * dma_async_is_complete - test a cookie against chan state
  * @cookie: transaction identifier to test status of
@@ -334,6 +407,7 @@
 	return DMA_IN_PROGRESS;
 }
 
+enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
 
 /* --- DMA device --- */
 
@@ -362,5 +436,4 @@
 	struct dma_pinned_list *pinned_list, struct page *page,
 	unsigned int offset, size_t len);
 
-#endif /* CONFIG_DMA_ENGINE */
 #endif /* DMAENGINE_H */
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 904bf3d..b8ac7b0 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -12,9 +12,17 @@
 	DMI_PRODUCT_NAME,
 	DMI_PRODUCT_VERSION,
 	DMI_PRODUCT_SERIAL,
+	DMI_PRODUCT_UUID,
 	DMI_BOARD_VENDOR,
 	DMI_BOARD_NAME,
 	DMI_BOARD_VERSION,
+	DMI_BOARD_SERIAL,
+	DMI_BOARD_ASSET_TAG,
+	DMI_CHASSIS_VENDOR,
+	DMI_CHASSIS_TYPE,
+	DMI_CHASSIS_VERSION,
+	DMI_CHASSIS_SERIAL,
+	DMI_CHASSIS_ASSET_TAG,
 	DMI_STRING_MAX,
 };
 
diff --git a/include/linux/ds17287rtc.h b/include/linux/ds17287rtc.h
index c281ba4..d85d3f4 100644
--- a/include/linux/ds17287rtc.h
+++ b/include/linux/ds17287rtc.h
@@ -11,7 +11,6 @@
 #define __LINUX_DS17287RTC_H
 
 #include <linux/rtc.h>			/* get the user-level API */
-#include <linux/spinlock.h>		/* spinlock_t */
 #include <linux/mc146818rtc.h>
 
 /* Register A */
diff --git a/include/linux/edd.h b/include/linux/edd.h
index b2b3e68..7b64782 100644
--- a/include/linux/edd.h
+++ b/include/linux/edd.h
@@ -49,10 +49,6 @@
 #define EDD_MBR_SIG_MAX 16        /* max number of signatures to store */
 #define EDD_MBR_SIG_NR_BUF 0x1ea  /* addr of number of MBR signtaures at EDD_MBR_SIG_BUF
 				     in boot_params - treat this as 1 byte  */
-#define EDD_CL_EQUALS   0x3d646465     /* "edd=" */
-#define EDD_CL_OFF      0x666f         /* "of" for off  */
-#define EDD_CL_SKIP     0x6b73         /* "sk" for skipmbr */
-#define EDD_CL_ON       0x6e6f	       /* "on" for on */
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
new file mode 100644
index 0000000..d774b77
--- /dev/null
+++ b/include/linux/eeprom_93cx6.h
@@ -0,0 +1,72 @@
+/*
+	Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.com>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the
+	Free Software Foundation, Inc.,
+	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+	Module: eeprom_93cx6
+	Abstract: EEPROM reader datastructures for 93cx6 chipsets.
+	Supported chipsets: 93c46 & 93c66.
+ */
+
+/*
+ * EEPROM operation defines.
+ */
+#define PCI_EEPROM_WIDTH_93C46	6
+#define PCI_EEPROM_WIDTH_93C66	8
+#define PCI_EEPROM_WIDTH_OPCODE	3
+#define PCI_EEPROM_WRITE_OPCODE	0x05
+#define PCI_EEPROM_READ_OPCODE	0x06
+#define PCI_EEPROM_EWDS_OPCODE	0x10
+#define PCI_EEPROM_EWEN_OPCODE	0x13
+
+/**
+ * struct eeprom_93cx6 - control structure for setting the commands
+ * for reading the eeprom data.
+ * @data: private pointer for the driver.
+ * @register_read(struct eeprom_93cx6 *eeprom): handler to
+ * read the eeprom register, this function should set all reg_* fields.
+ * @register_write(struct eeprom_93cx6 *eeprom): handler to
+ * write to the eeprom register by using all reg_* fields.
+ * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
+ * @reg_data_in: register field to indicate data input
+ * @reg_data_out: register field to indicate data output
+ * @reg_data_clock: register field to set the data clock
+ * @reg_chip_select: register field to set the chip select
+ *
+ * This structure is used for the communication between the driver
+ * and the eeprom_93cx6 handlers for reading the eeprom.
+ */
+struct eeprom_93cx6 {
+	void *data;
+
+	void (*register_read)(struct eeprom_93cx6 *eeprom);
+	void (*register_write)(struct eeprom_93cx6 *eeprom);
+
+	int width;
+
+	char reg_data_in;
+	char reg_data_out;
+	char reg_data_clock;
+	char reg_chip_select;
+};
+
+extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
+	const u8 word, u16 *data);
+extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
+	const u8 word, __le16 *data, const u16 words);
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index dfed800..16cb25c 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -45,6 +45,7 @@
 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp);
 extern struct dentry *efs_get_parent(struct dentry *);
 extern int efs_bmap(struct inode *, int);
 
diff --git a/include/linux/errno.h b/include/linux/errno.h
index d90b80f..4668583 100644
--- a/include/linux/errno.h
+++ b/include/linux/errno.h
@@ -5,7 +5,12 @@
 
 #ifdef __KERNEL__
 
-/* Should never be seen by user programs */
+/*
+ * These should never be seen by user programs.  To return one of ERESTART*
+ * codes, signal_pending() MUST be set.  Note that ptrace can observe these
+ * at syscall exit tracing, but they will never be left for the debugged user
+ * process to see.
+ */
 #define ERESTARTSYS	512
 #define ERESTARTNOINTR	513
 #define ERESTARTNOHAND	514	/* restart if no handler.. */
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 071c67a..6cdb973 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -39,13 +39,8 @@
 extern int		eth_header_cache(struct neighbour *neigh,
 					 struct hh_cache *hh);
 
-extern struct net_device *alloc_etherdev(int sizeof_priv);
-static inline void eth_copy_and_sum (struct sk_buff *dest, 
-				     const unsigned char *src, 
-				     int len, int base)
-{
-	memcpy (dest->data, src, len);
-}
+extern struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count);
+#define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
 
 /**
  * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index f2d248f..3a63224 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -265,6 +265,7 @@
 u32 ethtool_op_get_tx_csum(struct net_device *dev);
 int ethtool_op_set_tx_csum(struct net_device *dev, u32 data);
 int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data);
+int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data);
 u32 ethtool_op_get_sg(struct net_device *dev);
 int ethtool_op_set_sg(struct net_device *dev, u32 data);
 u32 ethtool_op_get_tso(struct net_device *dev);
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
index 0d6ecc6..b489fc6 100644
--- a/include/linux/eventfd.h
+++ b/include/linux/eventfd.h
@@ -19,7 +19,8 @@
 #else /* CONFIG_EVENTFD */
 
 #define eventfd_fget(fd) ERR_PTR(-ENOSYS)
-#define eventfd_signal(f, n) 0
+static inline int eventfd_signal(struct file *file, int n)
+{ return 0; }
 
 #endif /* CONFIG_EVENTFD */
 
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
new file mode 100644
index 0000000..8872fe8
--- /dev/null
+++ b/include/linux/exportfs.h
@@ -0,0 +1,126 @@
+#ifndef LINUX_EXPORTFS_H
+#define LINUX_EXPORTFS_H 1
+
+#include <linux/types.h>
+
+struct dentry;
+struct super_block;
+struct vfsmount;
+
+
+/**
+ * struct export_operations - for nfsd to communicate with file systems
+ * @decode_fh:      decode a file handle fragment and return a &struct dentry
+ * @encode_fh:      encode a file handle fragment from a dentry
+ * @get_name:       find the name for a given inode in a given directory
+ * @get_parent:     find the parent of a given directory
+ * @get_dentry:     find a dentry for the inode given a file handle sub-fragment
+ * @find_exported_dentry:
+ *	set by the exporting module to a standard helper function.
+ *
+ * Description:
+ *    The export_operations structure provides a means for nfsd to communicate
+ *    with a particular exported file system  - particularly enabling nfsd and
+ *    the filesystem to co-operate when dealing with file handles.
+ *
+ *    export_operations contains two basic operation for dealing with file
+ *    handles, decode_fh() and encode_fh(), and allows for some other
+ *    operations to be defined which standard helper routines use to get
+ *    specific information from the filesystem.
+ *
+ *    nfsd encodes information use to determine which filesystem a filehandle
+ *    applies to in the initial part of the file handle.  The remainder, termed
+ *    a file handle fragment, is controlled completely by the filesystem.  The
+ *    standard helper routines assume that this fragment will contain one or
+ *    two sub-fragments, one which identifies the file, and one which may be
+ *    used to identify the (a) directory containing the file.
+ *
+ *    In some situations, nfsd needs to get a dentry which is connected into a
+ *    specific part of the file tree.  To allow for this, it passes the
+ *    function acceptable() together with a @context which can be used to see
+ *    if the dentry is acceptable.  As there can be multiple dentrys for a
+ *    given file, the filesystem should check each one for acceptability before
+ *    looking for the next.  As soon as an acceptable one is found, it should
+ *    be returned.
+ *
+ * decode_fh:
+ *    @decode_fh is given a &struct super_block (@sb), a file handle fragment
+ *    (@fh, @fh_len) and an acceptability testing function (@acceptable,
+ *    @context).  It should return a &struct dentry which refers to the same
+ *    file that the file handle fragment refers to,  and which passes the
+ *    acceptability test.  If it cannot, it should return a %NULL pointer if
+ *    the file was found but no acceptable &dentries were available, or a
+ *    %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or
+ *    %ENOMEM).
+ *
+ * encode_fh:
+ *    @encode_fh should store in the file handle fragment @fh (using at most
+ *    @max_len bytes) information that can be used by @decode_fh to recover the
+ *    file refered to by the &struct dentry @de.  If the @connectable flag is
+ *    set, the encode_fh() should store sufficient information so that a good
+ *    attempt can be made to find not only the file but also it's place in the
+ *    filesystem.   This typically means storing a reference to de->d_parent in
+ *    the filehandle fragment.  encode_fh() should return the number of bytes
+ *    stored or a negative error code such as %-ENOSPC
+ *
+ * get_name:
+ *    @get_name should find a name for the given @child in the given @parent
+ *    directory.  The name should be stored in the @name (with the
+ *    understanding that it is already pointing to a a %NAME_MAX+1 sized
+ *    buffer.   get_name() should return %0 on success, a negative error code
+ *    or error.  @get_name will be called without @parent->i_mutex held.
+ *
+ * get_parent:
+ *    @get_parent should find the parent directory for the given @child which
+ *    is also a directory.  In the event that it cannot be found, or storage
+ *    space cannot be allocated, a %ERR_PTR should be returned.
+ *
+ * get_dentry:
+ *    Given a &super_block (@sb) and a pointer to a file-system specific inode
+ *    identifier, possibly an inode number, (@inump) get_dentry() should find
+ *    the identified inode and return a dentry for that inode.  Any suitable
+ *    dentry can be returned including, if necessary, a new dentry created with
+ *    d_alloc_root.  The caller can then find any other extant dentrys by
+ *    following the d_alias links.  If a new dentry was created using
+ *    d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry
+ *    should be d_rehash()ed.
+ *
+ *    If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code
+ *    can be returned.  The @inump will be whatever was passed to
+ *    nfsd_find_fh_dentry() in either the @obj or @parent parameters.
+ *
+ * Locking rules:
+ *    get_parent is called with child->d_inode->i_mutex down
+ *    get_name is not (which is possibly inconsistent)
+ */
+
+struct export_operations {
+	struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh,
+			int fh_len, int fh_type,
+			int (*acceptable)(void *context, struct dentry *de),
+			void *context);
+	int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
+			int connectable);
+	int (*get_name)(struct dentry *parent, char *name,
+			struct dentry *child);
+	struct dentry * (*get_parent)(struct dentry *child);
+	struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
+
+	/* This is set by the exporting module to a standard helper */
+	struct dentry * (*find_exported_dentry)(
+			struct super_block *sb, void *obj, void *parent,
+			int (*acceptable)(void *context, struct dentry *de),
+			void *context);
+};
+
+extern struct dentry *find_exported_dentry(struct super_block *sb, void *obj,
+	void *parent, int (*acceptable)(void *context, struct dentry *de),
+	void *context);
+
+extern int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+	int connectable);
+extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh,
+	int fh_len, int fileid_type, int (*acceptable)(void *, struct dentry *),
+	void *context);
+
+#endif /* LINUX_EXPORTFS_H */
diff --git a/include/linux/ext2_fs_sb.h b/include/linux/ext2_fs_sb.h
index 4eda0ed..d149f29 100644
--- a/include/linux/ext2_fs_sb.h
+++ b/include/linux/ext2_fs_sb.h
@@ -33,6 +33,8 @@
 	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
 	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
 	unsigned long s_groups_count;	/* Number of groups in the fs */
+	unsigned long s_overhead_last;  /* Last calculated overhead */
+	unsigned long s_blocks_last;    /* Last seen block count */
 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
 	struct ext2_super_block * s_es;	/* Pointer to the super block in the buffer */
 	struct buffer_head ** s_group_desc;
diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
index f61309c..d3c0835 100644
--- a/include/linux/ext3_fs_sb.h
+++ b/include/linux/ext3_fs_sb.h
@@ -38,6 +38,8 @@
 	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
 	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
 	unsigned long s_groups_count;	/* Number of groups in the fs */
+	unsigned long s_overhead_last;  /* Last calculated overhead */
+	unsigned long s_blocks_last;    /* Last seen block count */
 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
 	struct ext3_super_block * s_es;	/* Pointer to the super block in the buffer */
 	struct buffer_head ** s_group_desc;
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index 54c576d..de1f9f7 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -32,9 +32,9 @@
 /*
  * Define EXT4_RESERVATION to reserve data blocks for expanding files
  */
-#define EXT4_DEFAULT_RESERVE_BLOCKS     8
+#define EXT4_DEFAULT_RESERVE_BLOCKS	8
 /*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
-#define EXT4_MAX_RESERVE_BLOCKS         1027
+#define EXT4_MAX_RESERVE_BLOCKS		1027
 #define EXT4_RESERVE_WINDOW_NOT_ALLOCATED 0
 /*
  * Always enable hashed directories
@@ -204,12 +204,12 @@
 
 /* Used to pass group descriptor data when online resize is done */
 struct ext4_new_group_input {
-	__u32 group;            /* Group number for this data */
-	__u64 block_bitmap;     /* Absolute block number of block bitmap */
-	__u64 inode_bitmap;     /* Absolute block number of inode bitmap */
-	__u64 inode_table;      /* Absolute block number of inode table start */
-	__u32 blocks_count;     /* Total number of blocks in this group */
-	__u16 reserved_blocks;  /* Number of reserved blocks in this group */
+	__u32 group;		/* Group number for this data */
+	__u64 block_bitmap;	/* Absolute block number of block bitmap */
+	__u64 inode_bitmap;	/* Absolute block number of inode bitmap */
+	__u64 inode_table;	/* Absolute block number of inode table start */
+	__u32 blocks_count;	/* Total number of blocks in this group */
+	__u16 reserved_blocks;	/* Number of reserved blocks in this group */
 	__u16 unused;
 };
 
@@ -310,7 +310,7 @@
 			__u8	l_i_frag;	/* Fragment number */
 			__u8	l_i_fsize;	/* Fragment size */
 			__le16	l_i_file_acl_high;
-			__le16	l_i_uid_high;	/* these 2 fields    */
+			__le16	l_i_uid_high;	/* these 2 fields */
 			__le16	l_i_gid_high;	/* were reserved2[0] */
 			__u32	l_i_reserved2;
 		} linux2;
@@ -513,7 +513,14 @@
 /*150*/	__le32	s_blocks_count_hi;	/* Blocks count */
 	__le32	s_r_blocks_count_hi;	/* Reserved blocks count */
 	__le32	s_free_blocks_count_hi;	/* Free blocks count */
-	__u32	s_reserved[169];	/* Padding to the end of the block */
+	__u16	s_min_extra_isize;	/* All inodes have at least # bytes */
+	__u16	s_want_extra_isize; 	/* New inodes should reserve # bytes */
+	__u32	s_flags;		/* Miscellaneous flags */
+	__u16   s_raid_stride;		/* RAID stride */
+	__u16   s_mmp_interval;         /* # seconds to wait in MMP checking */
+	__u64   s_mmp_block;            /* Block for multi-mount protection */
+	__u32   s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
+	__u32   s_reserved[163];        /* Padding to the end of the block */
 };
 
 #ifdef __KERNEL__
@@ -780,9 +787,9 @@
  * Ok, these declarations are also in <linux/kernel.h> but none of the
  * ext4 source programs needs to include it so they are duplicated here.
  */
-# define NORET_TYPE    /**/
-# define ATTRIB_NORET  __attribute__((noreturn))
-# define NORET_AND     noreturn,
+# define NORET_TYPE	/**/
+# define ATTRIB_NORET	__attribute__((noreturn))
+# define NORET_AND	noreturn,
 
 /* balloc.c */
 extern unsigned int ext4_block_group(struct super_block *sb,
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
index 7eb1d73f..acfe5974 100644
--- a/include/linux/ext4_fs_extents.h
+++ b/include/linux/ext4_fs_extents.h
@@ -151,8 +151,8 @@
 	((struct ext4_extent_idx *) (((char *) (__hdr__)) +	\
 				     sizeof(struct ext4_extent_header)))
 #define EXT_HAS_FREE_INDEX(__path__) \
-        (le16_to_cpu((__path__)->p_hdr->eh_entries) \
-	                             < le16_to_cpu((__path__)->p_hdr->eh_max))
+	(le16_to_cpu((__path__)->p_hdr->eh_entries) \
+				     < le16_to_cpu((__path__)->p_hdr->eh_max))
 #define EXT_LAST_EXTENT(__hdr__) \
 	(EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
 #define EXT_LAST_INDEX(__hdr__) \
@@ -190,6 +190,7 @@
 
 extern int ext4_extent_tree_init(handle_t *, struct inode *);
 extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
+extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
 extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
 extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *);
 extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *);
diff --git a/include/linux/ext4_fs_i.h b/include/linux/ext4_fs_i.h
index d5b177e..9de4944 100644
--- a/include/linux/ext4_fs_i.h
+++ b/include/linux/ext4_fs_i.h
@@ -41,14 +41,14 @@
 
 struct ext4_block_alloc_info {
 	/* information about reservation window */
-	struct ext4_reserve_window_node	rsv_window_node;
+	struct ext4_reserve_window_node rsv_window_node;
 	/*
 	 * was i_next_alloc_block in ext4_inode_info
 	 * is the logical (file-relative) number of the
 	 * most-recently-allocated block in this file.
 	 * We use this for detecting linearly ascending allocation requests.
 	 */
-	__u32                   last_alloc_logical_block;
+	__u32 last_alloc_logical_block;
 	/*
 	 * Was i_next_alloc_goal in ext4_inode_info
 	 * is the *physical* companion to i_next_alloc_block.
@@ -56,7 +56,7 @@
 	 * allocated to this file.  This give us the goal (target) for the next
 	 * allocation when we detect linearly ascending requests.
 	 */
-	ext4_fsblk_t		last_alloc_physical_block;
+	ext4_fsblk_t last_alloc_physical_block;
 };
 
 #define rsv_start rsv_window._rsv_start
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
index 691a713..2347557 100644
--- a/include/linux/ext4_fs_sb.h
+++ b/include/linux/ext4_fs_sb.h
@@ -39,6 +39,8 @@
 	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
 	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
 	unsigned long s_groups_count;	/* Number of groups in the fs */
+	unsigned long s_overhead_last;  /* Last calculated overhead */
+	unsigned long s_blocks_last;    /* Last seen block count */
 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
 	struct ext4_super_block * s_es;	/* Pointer to the super block in the buffer */
 	struct buffer_head ** s_group_desc;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c654d0e..cec5410 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -119,6 +119,7 @@
 #define FB_ACCEL_NV_40          46      /* nVidia Arch 40               */
 #define FB_ACCEL_XGI_VOLARI_V	47	/* XGI Volari V3XT, V5, V8      */
 #define FB_ACCEL_XGI_VOLARI_Z	48	/* XGI Volari Z7                */
+#define FB_ACCEL_OMAP1610	49	/* TI OMAP16xx                  */
 #define FB_ACCEL_NEOMAGIC_NM2070 90	/* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91	/* NeoMagic NM2090              */
 #define FB_ACCEL_NEOMAGIC_NM2093 92	/* NeoMagic NM2093              */
@@ -529,6 +530,8 @@
 #define FB_EVENT_CONBLANK               0x0C
 /*      Get drawing requirements        */
 #define FB_EVENT_GET_REQ                0x0D
+/*      Unbind from the console if possible */
+#define FB_EVENT_FB_UNBIND              0x0E
 
 struct fb_event {
 	struct fb_info *info;
@@ -942,6 +945,7 @@
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
+extern struct class *fb_class;
 
 static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
 					   u8 *src, u32 s_pitch, u32 height)
diff --git a/include/linux/file.h b/include/linux/file.h
index a59001e..0114fbc 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -73,6 +73,7 @@
 extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag));
 extern void put_filp(struct file *);
 extern int get_unused_fd(void);
+extern int get_unused_fd_flags(int flags);
 extern void FASTCALL(put_unused_fd(unsigned int fd));
 struct kmem_cache;
 
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index d4455eb..1a45d6f 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -30,16 +30,38 @@
 #define FW_CDEV_EVENT_REQUEST		0x02
 #define FW_CDEV_EVENT_ISO_INTERRUPT	0x03
 
-/* The 'closure' fields are for user space to use.  Data passed in the
- * 'closure' field for a request will be returned in the corresponding
- * event.  It's a 64-bit type so that it's a fixed size type big
- * enough to hold a pointer on all platforms. */
-
+/**
+ * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
+ * @closure:	For arbitrary use by userspace
+ * @type:	Discriminates the fw_cdev_event_ types
+ *
+ * This struct may be used to access generic members of all fw_cdev_event_
+ * types regardless of the specific type.
+ *
+ * Data passed in the @closure field for a request will be returned in the
+ * corresponding event.  It is big enough to hold a pointer on all platforms.
+ * The ioctl used to set @closure depends on the @type of event.
+ */
 struct fw_cdev_event_common {
 	__u64 closure;
 	__u32 type;
 };
 
+/**
+ * struct fw_cdev_event_bus_reset - Sent when a bus reset occurred
+ * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_GET_INFO ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_BUS_RESET
+ * @node_id:       New node ID of this node
+ * @local_node_id: Node ID of the local node, i.e. of the controller
+ * @bm_node_id:    Node ID of the bus manager
+ * @irm_node_id:   Node ID of the iso resource manager
+ * @root_node_id:  Node ID of the root node
+ * @generation:    New bus generation
+ *
+ * This event is sent when the bus the device belongs to goes through a bus
+ * reset.  It provides information about the new bus configuration, such as
+ * new node ID for this device, new root ID, and others.
+ */
 struct fw_cdev_event_bus_reset {
 	__u64 closure;
 	__u32 type;
@@ -51,6 +73,20 @@
 	__u32 generation;
 };
 
+/**
+ * struct fw_cdev_event_response - Sent when a response packet was received
+ * @closure:	See &fw_cdev_event_common;
+ *		set by %FW_CDEV_IOC_SEND_REQUEST ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE
+ * @rcode:	Response code returned by the remote node
+ * @length:	Data length, i.e. the response's payload size in bytes
+ * @data:	Payload data, if any
+ *
+ * This event is sent when the stack receives a response to an outgoing request
+ * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl.  The payload data for responses
+ * carrying data (read and lock responses) follows immediately and can be
+ * accessed through the @data field.
+ */
 struct fw_cdev_event_response {
 	__u64 closure;
 	__u32 type;
@@ -59,6 +95,25 @@
 	__u32 data[0];
 };
 
+/**
+ * struct fw_cdev_event_request - Sent on incoming request to an address region
+ * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST
+ * @tcode:	Transaction code of the incoming request
+ * @offset:	The offset into the 48-bit per-node address space
+ * @handle:	Reference to the kernel-side pending request
+ * @length:	Data length, i.e. the request's payload size in bytes
+ * @data:	Incoming data, if any
+ *
+ * This event is sent when the stack receives an incoming request to an address
+ * region registered using the %FW_CDEV_IOC_ALLOCATE ioctl.  The request is
+ * guaranteed to be completely contained in the specified region.  Userspace is
+ * responsible for sending the response by %FW_CDEV_IOC_SEND_RESPONSE ioctl,
+ * using the same @handle.
+ *
+ * The payload data for requests carrying data (write and lock requests)
+ * follows immediately and can be accessed through the @data field.
+ */
 struct fw_cdev_event_request {
 	__u64 closure;
 	__u32 type;
@@ -69,14 +124,39 @@
 	__u32 data[0];
 };
 
+/**
+ * struct fw_cdev_event_iso_interrupt - Sent when an iso packet was completed
+ * @closure:	See &fw_cdev_event_common;
+ *		set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_ISO_INTERRUPT
+ * @cycle:	Cycle counter of the interrupt packet
+ * @header_length: Total length of following headers, in bytes
+ * @header:	Stripped headers, if any
+ *
+ * This event is sent when the controller has completed an &fw_cdev_iso_packet
+ * with the %FW_CDEV_ISO_INTERRUPT bit set.  In the receive case, the headers
+ * stripped of all packets up until and including the interrupt packet are
+ * returned in the @header field.
+ */
 struct fw_cdev_event_iso_interrupt {
 	__u64 closure;
 	__u32 type;
 	__u32 cycle;
-	__u32 header_length;	/* Length in bytes of following headers. */
+	__u32 header_length;
 	__u32 header[0];
 };
 
+/**
+ * union fw_cdev_event - Convenience union of fw_cdev_event_ types
+ * @common:        Valid for all types
+ * @bus_reset:     Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
+ * @response:      Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
+ * @request:       Valid if @common.type == %FW_CDEV_EVENT_REQUEST
+ * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
+ *
+ * Convenience union for userspace use.  Events could be read(2) into a char
+ * buffer and then cast to this union for further processing.
+ */
 union fw_cdev_event {
 	struct fw_cdev_event_common common;
 	struct fw_cdev_event_bus_reset bus_reset;
@@ -105,35 +185,47 @@
  */
 #define FW_CDEV_VERSION		1
 
+/**
+ * struct fw_cdev_get_info - General purpose information ioctl
+ * @version:	The version field is just a running serial number.
+ *		We never break backwards compatibility, but may add more
+ *		structs and ioctls in later revisions.
+ * @rom_length:	If @rom is non-zero, at most rom_length bytes of configuration
+ *		ROM will be copied into that user space address.  In either
+ *		case, @rom_length is updated with the actual length of the
+ *		configuration ROM.
+ * @rom:	If non-zero, address of a buffer to be filled by a copy of the
+ *		local node's configuration ROM
+ * @bus_reset:	If non-zero, address of a buffer to be filled by a
+ *		&struct fw_cdev_event_bus_reset with the current state
+ *		of the bus.  This does not cause a bus reset to happen.
+ * @bus_reset_closure: Value of &closure in this and subsequent bus reset events
+ * @card:	The index of the card this device belongs to
+ */
 struct fw_cdev_get_info {
-	/* The version field is just a running serial number.  We
-	 * never break backwards compatibility.  Userspace passes in
-	 * the version it expects and the kernel passes back the
-	 * highest version it can provide.  Even if the structs in
-	 * this interface are extended in a later version, the kernel
-	 * will not copy back more data than what was present in the
-	 * interface version userspace expects. */
 	__u32 version;
-
-	/* If non-zero, at most rom_length bytes of config rom will be
-	 * copied into that user space address.  In either case,
-	 * rom_length is updated with the actual length of the config
-	 * rom. */
 	__u32 rom_length;
 	__u64 rom;
-
-	/* If non-zero, a fw_cdev_event_bus_reset struct will be
-	 * copied here with the current state of the bus.  This does
-	 * not cause a bus reset to happen.  The value of closure in
-	 * this and sub-sequent bus reset events is set to
-	 * bus_reset_closure. */
 	__u64 bus_reset;
 	__u64 bus_reset_closure;
-
-	/* The index of the card this devices belongs to. */
 	__u32 card;
 };
 
+/**
+ * struct fw_cdev_send_request - Send an asynchronous request packet
+ * @tcode:	Transaction code of the request
+ * @length:	Length of outgoing payload, in bytes
+ * @offset:	48-bit offset at destination node
+ * @closure:	Passed back to userspace in the response event
+ * @data:	Userspace pointer to payload
+ * @generation:	The bus generation where packet is valid
+ *
+ * Send a request to the device.  This ioctl implements all outgoing requests.
+ * Both quadlet and block request specify the payload as a pointer to the data
+ * in the @data field.  Once the transaction completes, the kernel writes an
+ * &fw_cdev_event_request event back.  The @closure field is passed back to
+ * user space in the response event.
+ */
 struct fw_cdev_send_request {
 	__u32 tcode;
 	__u32 length;
@@ -143,6 +235,19 @@
 	__u32 generation;
 };
 
+/**
+ * struct fw_cdev_send_response - Send an asynchronous response packet
+ * @rcode:	Response code as determined by the userspace handler
+ * @length:	Length of outgoing payload, in bytes
+ * @data:	Userspace pointer to payload
+ * @handle:	The handle from the &fw_cdev_event_request
+ *
+ * Send a response to an incoming request.  By setting up an address range using
+ * the %FW_CDEV_IOC_ALLOCATE ioctl, userspace can listen for incoming requests.  An
+ * incoming request will generate an %FW_CDEV_EVENT_REQUEST, and userspace must
+ * send a reply using this ioctl.  The event has a handle to the kernel-side
+ * pending transaction, which should be used with this ioctl.
+ */
 struct fw_cdev_send_response {
 	__u32 rcode;
 	__u32 length;
@@ -150,6 +255,21 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_allocate - Allocate a CSR address range
+ * @offset:	Start offset of the address range
+ * @closure:	To be passed back to userspace in request events
+ * @length:	Length of the address range, in bytes
+ * @handle:	Handle to the allocation, written by the kernel
+ *
+ * Allocate an address range in the 48-bit address space on the local node
+ * (the controller).  This allows userspace to listen for requests with an
+ * offset within that address range.  When the kernel receives a request
+ * within the range, an &fw_cdev_event_request event will be written back.
+ * The @closure field is passed back to userspace in the response event.
+ * The @handle field is an out parameter, returning a handle to the allocated
+ * range to be used for later deallocation of the range.
+ */
 struct fw_cdev_allocate {
 	__u64 offset;
 	__u64 closure;
@@ -157,6 +277,11 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_deallocate - Free an address range allocation
+ * @handle:	Handle to the address range, as returned by the kernel when the
+ *		range was allocated
+ */
 struct fw_cdev_deallocate {
 	__u32 handle;
 };
@@ -164,10 +289,41 @@
 #define FW_CDEV_LONG_RESET	0
 #define FW_CDEV_SHORT_RESET	1
 
+/**
+ * struct fw_cdev_initiate_bus_reset - Initiate a bus reset
+ * @type:	%FW_CDEV_SHORT_RESET or %FW_CDEV_LONG_RESET
+ *
+ * Initiate a bus reset for the bus this device is on.  The bus reset can be
+ * either the original (long) bus reset or the arbitrated (short) bus reset
+ * introduced in 1394a-2000.
+ */
 struct fw_cdev_initiate_bus_reset {
-	__u32 type;
+	__u32 type;	/* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */
 };
 
+/**
+ * struct fw_cdev_add_descriptor - Add contents to the local node's config ROM
+ * @immediate:	If non-zero, immediate key to insert before pointer
+ * @key:	Upper 8 bits of root directory pointer
+ * @data:	Userspace pointer to contents of descriptor block
+ * @length:	Length of descriptor block data, in bytes
+ * @handle:	Handle to the descriptor, written by the kernel
+ *
+ * Add a descriptor block and optionally a preceding immediate key to the local
+ * node's configuration ROM.
+ *
+ * The @key field specifies the upper 8 bits of the descriptor root directory
+ * pointer and the @data and @length fields specify the contents. The @key
+ * should be of the form 0xXX000000. The offset part of the root directory entry
+ * will be filled in by the kernel.
+ *
+ * If not 0, the @immediate field specifies an immediate key which will be
+ * inserted before the root directory pointer.
+ *
+ * If successful, the kernel adds the descriptor and writes back a handle to the
+ * kernel-side object to be used for later removal of the descriptor block and
+ * immediate key.
+ */
 struct fw_cdev_add_descriptor {
 	__u32 immediate;
 	__u32 key;
@@ -176,6 +332,14 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_remove_descriptor - Remove contents from the configuration ROM
+ * @handle:	Handle to the descriptor, as returned by the kernel when the
+ *		descriptor was added
+ *
+ * Remove a descriptor block and accompanying immediate key from the local
+ * node's configuration ROM.
+ */
 struct fw_cdev_remove_descriptor {
 	__u32 handle;
 };
@@ -183,12 +347,24 @@
 #define FW_CDEV_ISO_CONTEXT_TRANSMIT	0
 #define FW_CDEV_ISO_CONTEXT_RECEIVE	1
 
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0		 1
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1		 2
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2		 4
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3		 8
-#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS	15
-
+/**
+ * struct fw_cdev_create_iso_context - Create a context for isochronous IO
+ * @type:	%FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE
+ * @header_size: Header size to strip for receive contexts
+ * @channel:	Channel to bind to
+ * @speed:	Speed to transmit at
+ * @closure:	To be returned in &fw_cdev_event_iso_interrupt
+ * @handle:	Handle to context, written back by kernel
+ *
+ * Prior to sending or receiving isochronous I/O, a context must be created.
+ * The context records information about the transmit or receive configuration
+ * and typically maps to an underlying hardware resource.  A context is set up
+ * for either sending or receiving.  It is bound to a specific isochronous
+ * channel.
+ *
+ * If a context was successfully created, the kernel writes back a handle to the
+ * context, which must be passed in for subsequent operations on that context.
+ */
 struct fw_cdev_create_iso_context {
 	__u32 type;
 	__u32 header_size;
@@ -198,16 +374,52 @@
 	__u32 handle;
 };
 
+#define FW_CDEV_ISO_PAYLOAD_LENGTH(v)	(v)
+#define FW_CDEV_ISO_INTERRUPT		(1 << 16)
+#define FW_CDEV_ISO_SKIP		(1 << 17)
+#define FW_CDEV_ISO_SYNC		(1 << 17)
+#define FW_CDEV_ISO_TAG(v)		((v) << 18)
+#define FW_CDEV_ISO_SY(v)		((v) << 20)
+#define FW_CDEV_ISO_HEADER_LENGTH(v)	((v) << 24)
+
+/**
+ * struct fw_cdev_iso_packet - Isochronous packet
+ * @control:	Contains the header length (8 uppermost bits), the sy field
+ *		(4 bits), the tag field (2 bits), a sync flag (1 bit),
+ *		a skip flag (1 bit), an interrupt flag (1 bit), and the
+ *		payload length (16 lowermost bits)
+ * @header:	Header and payload
+ *
+ * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.
+ *
+ * Use the FW_CDEV_ISO_ macros to fill in @control.  The sy and tag fields are
+ * specified by IEEE 1394a and IEC 61883.
+ *
+ * FIXME - finish this documentation
+ */
 struct fw_cdev_iso_packet {
-	__u16 payload_length;	/* Length of indirect payload. */
-	__u32 interrupt : 1;	/* Generate interrupt on this packet */
-	__u32 skip : 1;		/* Set to not send packet at all. */
-	__u32 tag : 2;
-	__u32 sy : 4;
-	__u32 header_length : 8;	/* Length of immediate header. */
+	__u32 control;
 	__u32 header[0];
 };
 
+/**
+ * struct fw_cdev_queue_iso - Queue isochronous packets for I/O
+ * @packets:	Userspace pointer to packet data
+ * @data:	Pointer into mmap()'ed payload buffer
+ * @size:	Size of packet data in bytes
+ * @handle:	Isochronous context handle
+ *
+ * Queue a number of isochronous packets for reception or transmission.
+ * This ioctl takes a pointer to an array of &fw_cdev_iso_packet structs,
+ * which describe how to transmit from or receive into a contiguous region
+ * of a mmap()'ed payload buffer.  As part of the packet descriptors,
+ * a series of headers can be supplied, which will be prepended to the
+ * payload during DMA.
+ *
+ * The kernel may or may not queue all packets, but will write back updated
+ * values of the @packets, @data and @size fields, so the ioctl can be
+ * resubmitted easily.
+ */
 struct fw_cdev_queue_iso {
 	__u64 packets;
 	__u64 data;
@@ -215,6 +427,23 @@
 	__u32 handle;
 };
 
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0		 1
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1		 2
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2		 4
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3		 8
+#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS	15
+
+/**
+ * struct fw_cdev_start_iso - Start an isochronous transmission or reception
+ * @cycle:	Cycle in which to start I/O.  If @cycle is greater than or
+ *		equal to 0, the I/O will start on that cycle.
+ * @sync:	Determines the value to wait for for receive packets that have
+ *		the %FW_CDEV_ISO_SYNC bit set
+ * @tags:	Tag filter bit mask.  Only valid for isochronous reception.
+ *		Determines the tag values for which packets will be accepted.
+ *		Use FW_CDEV_ISO_CONTEXT_MATCH_ macros to set @tags.
+ * @handle:	Isochronous context handle within which to transmit or receive
+ */
 struct fw_cdev_start_iso {
 	__s32 cycle;
 	__u32 sync;
@@ -222,6 +451,10 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_stop_iso - Stop an isochronous transmission or reception
+ * @handle:	Handle of isochronous context to stop
+ */
 struct fw_cdev_stop_iso {
 	__u32 handle;
 };
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 5e75e26..2d38b1a 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -1,5 +1,8 @@
 /* Freezer declarations */
 
+#ifndef FREEZER_H_INCLUDED
+#define FREEZER_H_INCLUDED
+
 #include <linux/sched.h>
 
 #ifdef CONFIG_PM
@@ -37,25 +40,25 @@
 
 /*
  * Wake up a frozen process
+ *
+ * task_lock() is taken to prevent the race with refrigerator() which may
+ * occur if the freezing of tasks fails.  Namely, without the lock, if the
+ * freezing of tasks failed, thaw_tasks() might have run before a task in
+ * refrigerator() could call frozen_process(), in which case the task would be
+ * frozen and no one would thaw it.
  */
 static inline int thaw_process(struct task_struct *p)
 {
+	task_lock(p);
 	if (frozen(p)) {
 		p->flags &= ~PF_FROZEN;
+		task_unlock(p);
 		wake_up_process(p);
 		return 1;
 	}
-	return 0;
-}
-
-/*
- * freezing is complete, mark process as frozen
- */
-static inline void frozen_process(struct task_struct *p)
-{
-	p->flags |= PF_FROZEN;
-	wmb();
 	clear_tsk_thread_flag(p, TIF_FREEZE);
+	task_unlock(p);
+	return 0;
 }
 
 extern void refrigerator(void);
@@ -71,14 +74,63 @@
 		return 0;
 }
 
-extern void thaw_some_processes(int all);
+/*
+ * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
+ * calls wait_for_completion(&vfork) and reset right after it returns from this
+ * function.  Next, the parent should call try_to_freeze() to freeze itself
+ * appropriately in case the child has exited before the freezing of tasks is
+ * complete.  However, we don't want kernel threads to be frozen in unexpected
+ * places, so we allow them to block freeze_processes() instead or to set
+ * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
+ * parents.  Fortunately, in the ____call_usermodehelper() case the parent won't
+ * really block freeze_processes(), since ____call_usermodehelper() (the child)
+ * does a little before exec/exit and it can't be frozen before waking up the
+ * parent.
+ */
+
+/*
+ * If the current task is a user space one, tell the freezer not to count it as
+ * freezable.
+ */
+static inline void freezer_do_not_count(void)
+{
+	if (current->mm)
+		current->flags |= PF_FREEZER_SKIP;
+}
+
+/*
+ * If the current task is a user space one, tell the freezer to count it as
+ * freezable again and try to freeze it.
+ */
+static inline void freezer_count(void)
+{
+	if (current->mm) {
+		current->flags &= ~PF_FREEZER_SKIP;
+		try_to_freeze();
+	}
+}
+
+/*
+ * Check if the task should be counted as freezeable by the freezer
+ */
+static inline int freezer_should_skip(struct task_struct *p)
+{
+	return !!(p->flags & PF_FREEZER_SKIP);
+}
+
+/*
+ * Tell the freezer that the current task should be frozen by it
+ */
+static inline void set_freezable(void)
+{
+	current->flags &= ~PF_NOFREEZE;
+}
 
 #else
 static inline int frozen(struct task_struct *p) { return 0; }
 static inline int freezing(struct task_struct *p) { return 0; }
 static inline void freeze(struct task_struct *p) { BUG(); }
 static inline int thaw_process(struct task_struct *p) { return 1; }
-static inline void frozen_process(struct task_struct *p) { BUG(); }
 
 static inline void refrigerator(void) {}
 static inline int freeze_processes(void) { BUG(); return 0; }
@@ -86,5 +138,10 @@
 
 static inline int try_to_freeze(void) { return 0; }
 
-
+static inline void freezer_do_not_count(void) {}
+static inline void freezer_count(void) {}
+static inline int freezer_should_skip(struct task_struct *p) { return 0; }
+static inline void set_freezable(void) {}
 #endif
+
+#endif	/* FREEZER_H_INCLUDED */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7cf0c54..98205f6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -44,7 +44,7 @@
 struct inodes_stat_t {
 	int nr_inodes;
 	int nr_unused;
-	int dummy[5];
+	int dummy[5];		/* padding for sysctl ABI compatibility */
 };
 extern struct inodes_stat_t inodes_stat;
 
@@ -283,11 +283,14 @@
 #include <linux/init.h>
 #include <linux/pid.h>
 #include <linux/mutex.h>
+#include <linux/sysctl.h>
+#include <linux/capability.h>
 
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 #include <asm/byteorder.h>
 
+struct export_operations;
 struct hd_geometry;
 struct iovec;
 struct nameidata;
@@ -820,6 +823,10 @@
 	union {
 		struct nfs_lock_info	nfs_fl;
 		struct nfs4_lock_info	nfs4_fl;
+		struct {
+			struct list_head link;	/* link in AFS vnode's pending_locks list */
+			int state;		/* state of grant or error if -ve */
+		} afs;
 	} fl_u;
 };
 
@@ -938,6 +945,7 @@
 	struct list_head	s_files;
 
 	struct block_device	*s_bdev;
+	struct mtd_info		*s_mtd;
 	struct list_head	s_instances;
 	struct quota_info	s_dquot;	/* Diskquota specific options */
 
@@ -983,6 +991,9 @@
 #define put_fs_excl() atomic_dec(&current->fs_excl)
 #define has_fs_excl() atomic_read(&current->fs_excl)
 
+#define is_owner_or_cap(inode)	\
+	((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER))
+
 /* not quite ready to be deprecated, but... */
 extern void lock_super(struct super_block *);
 extern void unlock_super(struct super_block *);
@@ -1053,7 +1064,7 @@
 };
 
 /*
- * "descriptor" for what we're up to with a read for sendfile().
+ * "descriptor" for what we're up to with a read.
  * This allows us to use the same read code yet
  * have multiple different users of the data that
  * we read from a file.
@@ -1104,7 +1115,6 @@
 	int (*aio_fsync) (struct kiocb *, int datasync);
 	int (*fasync) (int, struct file *, int);
 	int (*lock) (struct file *, int, struct file_lock *);
-	ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
 	ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
 	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 	int (*check_flags)(int);
@@ -1210,6 +1220,14 @@
 	__mark_inode_dirty(inode, I_DIRTY_SYNC);
 }
 
+/**
+ * inc_nlink - directly increment an inode's link count
+ * @inode: inode
+ *
+ * This is a low-level filesystem helper to replace any
+ * direct filesystem manipulation of i_nlink.  Currently,
+ * it is only here for parity with dec_nlink().
+ */
 static inline void inc_nlink(struct inode *inode)
 {
 	inode->i_nlink++;
@@ -1221,11 +1239,30 @@
 	mark_inode_dirty(inode);
 }
 
+/**
+ * drop_nlink - directly drop an inode's link count
+ * @inode: inode
+ *
+ * This is a low-level filesystem helper to replace any
+ * direct filesystem manipulation of i_nlink.  In cases
+ * where we are attempting to track writes to the
+ * filesystem, a decrement to zero means an imminent
+ * write when the file is truncated and actually unlinked
+ * on the filesystem.
+ */
 static inline void drop_nlink(struct inode *inode)
 {
 	inode->i_nlink--;
 }
 
+/**
+ * clear_nlink - directly zero an inode's link count
+ * @inode: inode
+ *
+ * This is a low-level filesystem helper to replace any
+ * direct filesystem manipulation of i_nlink.  See
+ * drop_nlink() for why we care about i_nlink hitting zero.
+ */
 static inline void clear_nlink(struct inode *inode)
 {
 	inode->i_nlink = 0;
@@ -1246,119 +1283,6 @@
 
 int sync_inode(struct inode *inode, struct writeback_control *wbc);
 
-/**
- * struct export_operations - for nfsd to communicate with file systems
- * @decode_fh:      decode a file handle fragment and return a &struct dentry
- * @encode_fh:      encode a file handle fragment from a dentry
- * @get_name:       find the name for a given inode in a given directory
- * @get_parent:     find the parent of a given directory
- * @get_dentry:     find a dentry for the inode given a file handle sub-fragment
- * @find_exported_dentry:
- *	set by the exporting module to a standard helper function.
- *
- * Description:
- *    The export_operations structure provides a means for nfsd to communicate
- *    with a particular exported file system  - particularly enabling nfsd and
- *    the filesystem to co-operate when dealing with file handles.
- *
- *    export_operations contains two basic operation for dealing with file
- *    handles, decode_fh() and encode_fh(), and allows for some other
- *    operations to be defined which standard helper routines use to get
- *    specific information from the filesystem.
- *
- *    nfsd encodes information use to determine which filesystem a filehandle
- *    applies to in the initial part of the file handle.  The remainder, termed
- *    a file handle fragment, is controlled completely by the filesystem.  The
- *    standard helper routines assume that this fragment will contain one or
- *    two sub-fragments, one which identifies the file, and one which may be
- *    used to identify the (a) directory containing the file.
- *
- *    In some situations, nfsd needs to get a dentry which is connected into a
- *    specific part of the file tree.  To allow for this, it passes the
- *    function acceptable() together with a @context which can be used to see
- *    if the dentry is acceptable.  As there can be multiple dentrys for a
- *    given file, the filesystem should check each one for acceptability before
- *    looking for the next.  As soon as an acceptable one is found, it should
- *    be returned.
- *
- * decode_fh:
- *    @decode_fh is given a &struct super_block (@sb), a file handle fragment
- *    (@fh, @fh_len) and an acceptability testing function (@acceptable,
- *    @context).  It should return a &struct dentry which refers to the same
- *    file that the file handle fragment refers to,  and which passes the
- *    acceptability test.  If it cannot, it should return a %NULL pointer if
- *    the file was found but no acceptable &dentries were available, or a
- *    %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or
- *    %ENOMEM).
- *
- * encode_fh:
- *    @encode_fh should store in the file handle fragment @fh (using at most
- *    @max_len bytes) information that can be used by @decode_fh to recover the
- *    file refered to by the &struct dentry @de.  If the @connectable flag is
- *    set, the encode_fh() should store sufficient information so that a good
- *    attempt can be made to find not only the file but also it's place in the
- *    filesystem.   This typically means storing a reference to de->d_parent in
- *    the filehandle fragment.  encode_fh() should return the number of bytes
- *    stored or a negative error code such as %-ENOSPC
- *
- * get_name:
- *    @get_name should find a name for the given @child in the given @parent
- *    directory.  The name should be stored in the @name (with the
- *    understanding that it is already pointing to a a %NAME_MAX+1 sized
- *    buffer.   get_name() should return %0 on success, a negative error code
- *    or error.  @get_name will be called without @parent->i_mutex held.
- *
- * get_parent:
- *    @get_parent should find the parent directory for the given @child which
- *    is also a directory.  In the event that it cannot be found, or storage
- *    space cannot be allocated, a %ERR_PTR should be returned.
- *
- * get_dentry:
- *    Given a &super_block (@sb) and a pointer to a file-system specific inode
- *    identifier, possibly an inode number, (@inump) get_dentry() should find
- *    the identified inode and return a dentry for that inode.  Any suitable
- *    dentry can be returned including, if necessary, a new dentry created with
- *    d_alloc_root.  The caller can then find any other extant dentrys by
- *    following the d_alias links.  If a new dentry was created using
- *    d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry
- *    should be d_rehash()ed.
- *
- *    If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code
- *    can be returned.  The @inump will be whatever was passed to
- *    nfsd_find_fh_dentry() in either the @obj or @parent parameters.
- *
- * Locking rules:
- *    get_parent is called with child->d_inode->i_mutex down
- *    get_name is not (which is possibly inconsistent)
- */
-
-struct export_operations {
-	struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
-			 int (*acceptable)(void *context, struct dentry *de),
-			 void *context);
-	int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
-			 int connectable);
-
-	/* the following are only called from the filesystem itself */
-	int (*get_name)(struct dentry *parent, char *name,
-			struct dentry *child);
-	struct dentry * (*get_parent)(struct dentry *child);
-	struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
-
-	/* This is set by the exporting module to a standard helper */
-	struct dentry * (*find_exported_dentry)(
-		struct super_block *sb, void *obj, void *parent,
-		int (*acceptable)(void *context, struct dentry *de),
-		void *context);
-
-
-};
-
-extern struct dentry *
-find_exported_dentry(struct super_block *sb, void *obj, void *parent,
-		     int (*acceptable)(void *context, struct dentry *de),
-		     void *context);
-
 struct file_system_type {
 	const char *name;
 	int fs_flags;
@@ -1495,7 +1419,7 @@
 
 #ifdef CONFIG_BLOCK
 extern int register_blkdev(unsigned int, const char *);
-extern int unregister_blkdev(unsigned int, const char *);
+extern void unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern void bd_set_size(struct block_device *, loff_t size);
 extern void bd_forget(struct inode *inode);
@@ -1583,6 +1507,9 @@
 extern int invalidate_partition(struct gendisk *, int);
 #endif
 extern int invalidate_inodes(struct super_block *);
+unsigned long __invalidate_mapping_pages(struct address_space *mapping,
+					pgoff_t start, pgoff_t end,
+					bool be_atomic);
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
 					pgoff_t start, pgoff_t end);
 
@@ -1734,7 +1661,6 @@
 		unsigned long, loff_t, loff_t *, size_t, ssize_t);
 extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
 extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
-extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
 extern void do_generic_mapping_read(struct address_space *mapping,
 				    struct file_ra_state *, struct file *,
 				    loff_t *, read_descriptor_t *, read_actor_t);
@@ -1764,9 +1690,6 @@
 #ifdef CONFIG_FS_XIP
 extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
 			     loff_t *ppos);
-extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos,
-				 size_t count, read_actor_t actor,
-				 void *target);
 extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma);
 extern ssize_t xip_file_write(struct file *filp, const char __user *buf,
 			      size_t len, loff_t *ppos);
@@ -2020,5 +1943,9 @@
 { }
 #endif	/* CONFIG_SECURITY */
 
+int proc_nr_files(ctl_table *table, int write, struct file *filp,
+		  void __user *buffer, size_t *lenp, loff_t *ppos);
+
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_FS_H */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 73710d6..695741b 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -112,7 +112,7 @@
 struct fsl_spi_platform_data {
 	u32 	initial_spmode;	/* initial SPMODE value */
 	u16	bus_num;
-
+	bool	qe_mode;
 	/* board specific information */
 	u16	max_chipselect;
 	void	(*activate_cs)(u8 cs, u8 polarity);
@@ -120,5 +120,10 @@
 	u32	sysclk;
 };
 
+struct mpc8xx_pcmcia_ops {
+	void(*hw_ctrl)(int slot, int enable);
+	int(*voltage_set)(int slot, int vcc, int vpp);
+};
+
 #endif /* _FSL_DEVICE_H_ */
 #endif /* __KERNEL__ */
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 534744e..9fbe9d2 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -339,7 +339,7 @@
 	char name[0];
 };
 
-#define FUSE_NAME_OFFSET ((unsigned) ((struct fuse_dirent *) 0)->name)
+#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
 #define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
 #define FUSE_DIRENT_SIZE(d) \
 	FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 899fc7f..9965035 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -17,7 +17,6 @@
 #define FUTEX_LOCK_PI		6
 #define FUTEX_UNLOCK_PI		7
 #define FUTEX_TRYLOCK_PI	8
-#define FUTEX_CMP_REQUEUE_PI	9
 
 #define FUTEX_PRIVATE_FLAG	128
 #define FUTEX_CMD_MASK		~FUTEX_PRIVATE_FLAG
@@ -98,14 +97,9 @@
 #define FUTEX_OWNER_DIED	0x40000000
 
 /*
- * Some processes have been requeued on this PI-futex
- */
-#define FUTEX_WAITER_REQUEUED	0x20000000
-
-/*
  * The rest of the robust-futex field is for the TID:
  */
-#define FUTEX_TID_MASK		0x0fffffff
+#define FUTEX_TID_MASK		0x3fffffff
 
 /*
  * This limit protects against a deliberately circular list.
@@ -139,7 +133,6 @@
 #define FUT_OFF_MMSHARED 2 /* We set bit 1 if key has a reference on mm */
 
 union futex_key {
-	u32 __user *uaddr;
 	struct {
 		unsigned long pgoff;
 		struct inode *inode;
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 4c03ee3..9756fc1 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -66,6 +66,7 @@
 #include <linux/smp.h>
 #include <linux/string.h>
 #include <linux/fs.h>
+#include <linux/workqueue.h>
 
 struct partition {
 	unsigned char boot_ind;		/* 0x80 - active */
@@ -94,6 +95,7 @@
 
 #define GENHD_FL_REMOVABLE			1
 #define GENHD_FL_DRIVERFS			2
+#define GENHD_FL_MEDIA_CHANGE_NOTIFY		4
 #define GENHD_FL_CD				8
 #define GENHD_FL_UP				16
 #define GENHD_FL_SUPPRESS_PARTITION_INFO	32
@@ -138,6 +140,7 @@
 #else
 	struct disk_stats dkstats;
 #endif
+	struct work_struct async_notify;
 };
 
 /* Structure for sysfs attributes on block devices */
@@ -419,7 +422,7 @@
 extern struct gendisk *alloc_disk(int minors);
 extern struct kobject *get_disk(struct gendisk *disk);
 extern void put_disk(struct gendisk *disk);
-
+extern void genhd_media_change_notify(struct gendisk *disk);
 extern void blk_register_region(dev_t dev, unsigned long range,
 			struct module *module,
 			struct kobject *(*probe)(dev_t, int *, void *),
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 0d2ef0b..bc68dd9 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -30,6 +30,9 @@
  * cannot handle allocation failures.
  *
  * __GFP_NORETRY: The VM implementation must not retry indefinitely.
+ *
+ * __GFP_MOVABLE: Flag that this page will be movable by the page migration
+ * mechanism or reclaimed
  */
 #define __GFP_WAIT	((__force gfp_t)0x10u)	/* Can wait and reschedule? */
 #define __GFP_HIGH	((__force gfp_t)0x20u)	/* Should access emergency pools? */
@@ -45,6 +48,7 @@
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
 #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
 #define __GFP_THISNODE	((__force gfp_t)0x40000u)/* No fallback, no policies */
+#define __GFP_MOVABLE	((__force gfp_t)0x80000u) /* Page is movable */
 
 #define __GFP_BITS_SHIFT 20	/* Room for 20 __GFP_FOO bits */
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
@@ -53,7 +57,8 @@
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
 			__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
 			__GFP_NOFAIL|__GFP_NORETRY|__GFP_COMP| \
-			__GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE)
+			__GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE| \
+			__GFP_MOVABLE)
 
 /* This equals 0, but use constants in case they ever change */
 #define GFP_NOWAIT	(GFP_ATOMIC & ~__GFP_HIGH)
@@ -65,6 +70,15 @@
 #define GFP_USER	(__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
 #define GFP_HIGHUSER	(__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
 			 __GFP_HIGHMEM)
+#define GFP_HIGHUSER_MOVABLE	(__GFP_WAIT | __GFP_IO | __GFP_FS | \
+				 __GFP_HARDWALL | __GFP_HIGHMEM | \
+				 __GFP_MOVABLE)
+#define GFP_NOFS_PAGECACHE	(__GFP_WAIT | __GFP_IO | __GFP_MOVABLE)
+#define GFP_USER_PAGECACHE	(__GFP_WAIT | __GFP_IO | __GFP_FS | \
+				 __GFP_HARDWALL | __GFP_MOVABLE)
+#define GFP_HIGHUSER_PAGECACHE	(__GFP_WAIT | __GFP_IO | __GFP_FS | \
+				 __GFP_HARDWALL | __GFP_HIGHMEM | \
+				 __GFP_MOVABLE)
 
 #ifdef CONFIG_NUMA
 #define GFP_THISNODE	(__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
@@ -92,6 +106,9 @@
 	if (flags & __GFP_DMA32)
 		return ZONE_DMA32;
 #endif
+	if ((flags & (__GFP_HIGHMEM | __GFP_MOVABLE)) ==
+			(__GFP_HIGHMEM | __GFP_MOVABLE))
+		return ZONE_MOVABLE;
 #ifdef CONFIG_HIGHMEM
 	if (flags & __GFP_HIGHMEM)
 		return ZONE_HIGHMEM;
diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h
index 8b7e4c1..a44a6a0 100644
--- a/include/linux/gfs2_ondisk.h
+++ b/include/linux/gfs2_ondisk.h
@@ -54,18 +54,6 @@
 	__be64 no_addr;
 };
 
-struct gfs2_inum_host {
-	__u64 no_formal_ino;
-	__u64 no_addr;
-};
-
-static inline int gfs2_inum_equal(const struct gfs2_inum_host *ino1,
-				  const struct gfs2_inum_host *ino2)
-{
-	return ino1->no_formal_ino == ino2->no_formal_ino &&
-	       ino1->no_addr == ino2->no_addr;
-}
-
 /*
  * Generic metadata head structure
  * Every inplace buffer logged in the journal must start with this.
@@ -94,12 +82,6 @@
 	__be32 __pad1;		/* Was incarnation number in gfs1 */
 };
 
-struct gfs2_meta_header_host {
-	__u32 mh_magic;
-	__u32 mh_type;
-	__u32 mh_format;
-};
-
 /*
  * super-block structure
  *
@@ -139,23 +121,6 @@
 	/* In gfs1, quota and license dinodes followed */
 };
 
-struct gfs2_sb_host {
-	struct gfs2_meta_header_host sb_header;
-
-	__u32 sb_fs_format;
-	__u32 sb_multihost_format;
-
-	__u32 sb_bsize;
-	__u32 sb_bsize_shift;
-
-	struct gfs2_inum_host sb_master_dir; /* Was jindex dinode in gfs1 */
-	struct gfs2_inum_host sb_root_dir;
-
-	char sb_lockproto[GFS2_LOCKNAME_LEN];
-	char sb_locktable[GFS2_LOCKNAME_LEN];
-	/* In gfs1, quota and license dinodes followed */
-};
-
 /*
  * resource index structure
  */
@@ -173,14 +138,6 @@
 	__u8 ri_reserved[64];
 };
 
-struct gfs2_rindex_host {
-	__u64 ri_addr;	/* grp block disk address */
-	__u64 ri_data0;	/* first data location */
-	__u32 ri_length;	/* length of rgrp header in fs blocks */
-	__u32 ri_data;	/* num of data blocks in rgrp */
-	__u32 ri_bitbytes;	/* number of bytes in data bitmaps */
-};
-
 /*
  * resource group header structure
  */
@@ -212,13 +169,6 @@
 	__u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */
 };
 
-struct gfs2_rgrp_host {
-	__u32 rg_flags;
-	__u32 rg_free;
-	__u32 rg_dinodes;
-	__u64 rg_igeneration;
-};
-
 /*
  * quota structure
  */
@@ -230,12 +180,6 @@
 	__u8 qu_reserved[64];
 };
 
-struct gfs2_quota_host {
-	__u64 qu_limit;
-	__u64 qu_warn;
-	__u64 qu_value;
-};
-
 /*
  * dinode structure
  */
@@ -315,29 +259,11 @@
 	struct gfs2_inum __pad4; /* Unused even in current gfs1 */
 
 	__be64 di_eattr;	/* extended attribute block number */
+	__be32 di_atime_nsec;   /* nsec portion of atime */
+	__be32 di_mtime_nsec;   /* nsec portion of mtime */
+	__be32 di_ctime_nsec;   /* nsec portion of ctime */
 
-	__u8 di_reserved[56];
-};
-
-struct gfs2_dinode_host {
-	__u64 di_size;	/* number of bytes in file */
-	__u64 di_blocks;	/* number of blocks in file */
-
-	/* This section varies from gfs1. Padding added to align with
-         * remainder of dinode
-	 */
-	__u64 di_goal_meta;	/* rgrp to alloc from next */
-	__u64 di_goal_data;	/* data block goal */
-	__u64 di_generation;	/* generation number for NFS */
-
-	__u32 di_flags;	/* GFS2_DIF_... */
-	__u16 di_height;	/* height of metadata */
-
-	/* These only apply to directories  */
-	__u16 di_depth;	/* Number of bits in the table */
-	__u32 di_entries;	/* The number of entries in the directory */
-
-	__u64 di_eattr;	/* extended attribute block number */
+	__u8 di_reserved[44];
 };
 
 /*
@@ -414,16 +340,6 @@
 	__be32 lh_hash;
 };
 
-struct gfs2_log_header_host {
-	struct gfs2_meta_header_host lh_header;
-
-	__u64 lh_sequence;	/* Sequence number of this transaction */
-	__u32 lh_flags;	/* GFS2_LOG_HEAD_... */
-	__u32 lh_tail;		/* Block number of log tail */
-	__u32 lh_blkno;
-	__u32 lh_hash;
-};
-
 /*
  * Log type descriptor
  */
@@ -464,11 +380,6 @@
 	__be64 ir_length;
 };
 
-struct gfs2_inum_range_host {
-	__u64 ir_start;
-	__u64 ir_length;
-};
-
 /*
  * Statfs change
  * Describes an change to the pool of free and allocated
@@ -481,12 +392,6 @@
 	__be64 sc_dinodes;
 };
 
-struct gfs2_statfs_change_host {
-	__u64 sc_total;
-	__u64 sc_free;
-	__u64 sc_dinodes;
-};
-
 /*
  * Quota change
  * Describes an allocation change for a particular
@@ -501,39 +406,12 @@
 	__be32 qc_id;
 };
 
-struct gfs2_quota_change_host {
-	__u64 qc_change;
-	__u32 qc_flags;	/* GFS2_QCF_... */
-	__u32 qc_id;
+struct gfs2_quota_lvb {
+        __be32 qb_magic;
+        __u32 __pad;
+        __be64 qb_limit;      /* Hard limit of # blocks to alloc */
+        __be64 qb_warn;       /* Warn user when alloc is above this # */
+        __be64 qb_value;       /* Current # blocks allocated */
 };
 
-#ifdef __KERNEL__
-/* Translation functions */
-
-extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf);
-extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf);
-extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf);
-extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf);
-extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf);
-extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf);
-extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf);
-extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf);
-struct gfs2_inode;
-extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
-extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf);
-extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf);
-extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf);
-extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf);
-extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf);
-extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf);
-extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf);
-extern void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf);
-
-/* Printing functions */
-
-extern void gfs2_rindex_print(const struct gfs2_rindex_host *ri);
-extern void gfs2_dinode_print(const struct gfs2_inode *ip);
-
-#endif /* __KERNEL__ */
-
 #endif /* __GFS2_ONDISK_DOT_H__ */
diff --git a/include/linux/gpio_mouse.h b/include/linux/gpio_mouse.h
new file mode 100644
index 0000000..44ed7aa
--- /dev/null
+++ b/include/linux/gpio_mouse.h
@@ -0,0 +1,61 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _GPIO_MOUSE_H
+#define _GPIO_MOUSE_H
+
+#define GPIO_MOUSE_POLARITY_ACT_HIGH	0x00
+#define GPIO_MOUSE_POLARITY_ACT_LOW	0x01
+
+#define GPIO_MOUSE_PIN_UP	0
+#define GPIO_MOUSE_PIN_DOWN	1
+#define GPIO_MOUSE_PIN_LEFT	2
+#define GPIO_MOUSE_PIN_RIGHT	3
+#define GPIO_MOUSE_PIN_BLEFT	4
+#define GPIO_MOUSE_PIN_BMIDDLE	5
+#define GPIO_MOUSE_PIN_BRIGHT	6
+#define GPIO_MOUSE_PIN_MAX	7
+
+/**
+ * struct gpio_mouse_platform_data
+ * @scan_ms: integer in ms specifying the scan periode.
+ * @polarity: Pin polarity, active high or low.
+ * @up: GPIO line for up value.
+ * @down: GPIO line for down value.
+ * @left: GPIO line for left value.
+ * @right: GPIO line for right value.
+ * @bleft: GPIO line for left button.
+ * @bmiddle: GPIO line for middle button.
+ * @bright: GPIO line for right button.
+ *
+ * This struct must be added to the platform_device in the board code.
+ * It is used by the gpio_mouse driver to setup GPIO lines and to
+ * calculate mouse movement.
+ */
+struct gpio_mouse_platform_data {
+	int scan_ms;
+	int polarity;
+
+	union {
+		struct {
+			int up;
+			int down;
+			int left;
+			int right;
+
+			int bleft;
+			int bmiddle;
+			int bright;
+		};
+		int pins[GPIO_MOUSE_PIN_MAX];
+	};
+};
+
+#endif /* _GPIO_MOUSE_H */
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 7803014..8d30229 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -79,6 +79,19 @@
 #endif
 
 #ifdef CONFIG_PREEMPT
+# define PREEMPT_CHECK_OFFSET 1
+#else
+# define PREEMPT_CHECK_OFFSET 0
+#endif
+
+/*
+ * Check whether we were atomic before we did preempt_disable():
+ * (used by the scheduler)
+ */
+#define in_atomic_preempt_off() \
+		((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
+
+#ifdef CONFIG_PREEMPT
 # define preemptible()	(preempt_count() == 0 && !irqs_disabled())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 827ee74..898103b 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -263,19 +263,28 @@
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5		0x00000100
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON		0x00000200
 #define HID_QUIRK_MIGHTYMOUSE			0x00000400
-#define HID_QUIRK_CYMOTION			0x00000800
-#define HID_QUIRK_POWERBOOK_HAS_FN		0x00001000
-#define HID_QUIRK_POWERBOOK_FN_ON		0x00002000
-#define HID_QUIRK_INVERT_HWHEEL			0x00004000
-#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD        0x00008000
-#define HID_QUIRK_BAD_RELATIVE_KEYS		0x00010000
-#define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00020000
-#define HID_QUIRK_IGNORE_MOUSE			0x00040000
-#define HID_QUIRK_SONY_PS3_CONTROLLER		0x00080000
-#define HID_QUIRK_LOGITECH_DESCRIPTOR		0x00100000
-#define HID_QUIRK_DUPLICATE_USAGES		0x00200000
-#define HID_QUIRK_RESET_LEDS			0x00400000
-#define HID_QUIRK_SWAPPED_MIN_MAX		0x00800000
+#define HID_QUIRK_POWERBOOK_HAS_FN		0x00000800
+#define HID_QUIRK_POWERBOOK_FN_ON		0x00001000
+#define HID_QUIRK_INVERT_HWHEEL			0x00002000
+#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD        0x00004000
+#define HID_QUIRK_BAD_RELATIVE_KEYS		0x00008000
+#define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00010000
+#define HID_QUIRK_IGNORE_MOUSE			0x00020000
+#define HID_QUIRK_SONY_PS3_CONTROLLER		0x00040000
+#define HID_QUIRK_DUPLICATE_USAGES		0x00080000
+#define HID_QUIRK_RESET_LEDS			0x00100000
+#define HID_QUIRK_HIDINPUT			0x00200000
+#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL	0x00400000
+#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP	0x00800000
+
+/*
+ * Separate quirks for runtime report descriptor fixup
+ */
+
+#define HID_QUIRK_RDESC_CYMOTION		0x00000001
+#define HID_QUIRK_RDESC_LOGITECH		0x00000002
+#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX		0x00000004
+#define HID_QUIRK_RDESC_PETALYNX		0x00000008
 
 /*
  * This is the global environment of the parser. This information is
@@ -488,6 +497,11 @@
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
 
 /* HID core API */
+
+#ifdef CONFIG_HID_DEBUG
+extern int hid_debug;
+#endif
+
 extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
 extern int hidinput_connect(struct hid_device *);
@@ -506,6 +520,7 @@
 int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks);
 int usbhid_quirks_init(char **quirks_param);
 void usbhid_quirks_exit(void);
+void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
 
 #ifdef CONFIG_HID_FF
 int hid_ff_init(struct hid_device *hid);
@@ -523,14 +538,19 @@
 #else
 static inline int hid_ff_init(struct hid_device *hid) { return -1; }
 #endif
-#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
-		__FILE__ , ## arg)
+
+#ifdef CONFIG_HID_DEBUG
+#define dbg_hid(format, arg...) if (hid_debug) \
+				printk(KERN_DEBUG "%s: " format ,\
+				__FILE__ , ## arg)
+#define dbg_hid_line(format, arg...) if (hid_debug) \
+				printk(format, ## arg)
 #else
-#define dbg(format, arg...) do {} while (0)
+#define dbg_hid(format, arg...) do {} while (0)
+#define dbg_hid_line dbg_hid
 #endif
 
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
 		__FILE__ , ## arg)
 #endif
 
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 98e2cce..12c5e4e 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -73,10 +73,27 @@
 }
 
 #ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+/**
+ * __alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA with caller-specified movable GFP flags
+ * @movableflags: The GFP flags related to the pages future ability to move like __GFP_MOVABLE
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA but the caller is expected
+ * to specify via movableflags whether the page will be movable in the
+ * future or not
+ *
+ * An architecture may override this function by defining
+ * __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE and providing their own
+ * implementation.
+ */
 static inline struct page *
-alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
+__alloc_zeroed_user_highpage(gfp_t movableflags,
+			struct vm_area_struct *vma,
+			unsigned long vaddr)
 {
-	struct page *page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr);
+	struct page *page = alloc_page_vma(GFP_HIGHUSER | movableflags,
+			vma, vaddr);
 
 	if (page)
 		clear_user_highpage(page, vaddr);
@@ -85,6 +102,36 @@
 }
 #endif
 
+/**
+ * alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA that the caller knows will
+ * not be able to move in the future using move_pages() or reclaim. If it
+ * is known that the page can move, use alloc_zeroed_user_highpage_movable
+ */
+static inline struct page *
+alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
+{
+	return __alloc_zeroed_user_highpage(0, vma, vaddr);
+}
+
+/**
+ * alloc_zeroed_user_highpage_movable - Allocate a zeroed HIGHMEM page for a VMA that the caller knows can move
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA that the caller knows will
+ * be able to migrate in the future using move_pages() or reclaimed
+ */
+static inline struct page *
+alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,
+					unsigned long vaddr)
+{
+	return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr);
+}
+
 static inline void clear_highpage(struct page *page)
 {
 	void *kaddr = kmap_atomic(page, KM_USER0);
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 17c29dc..540799b 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -329,12 +329,13 @@
 #ifdef CONFIG_TIMER_STATS
 
 extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
-				     void *timerf, char * comm);
+				     void *timerf, char *comm,
+				     unsigned int timer_flag);
 
 static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
 {
 	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
-				 timer->function, timer->start_comm);
+				 timer->function, timer->start_comm, 0);
 }
 
 extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer,
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index b4570b6..49b7053 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -15,6 +15,7 @@
 }
 
 int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
+int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
 int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
 int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
 void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
@@ -29,6 +30,7 @@
 void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
 
 extern unsigned long max_huge_pages;
+extern unsigned long hugepages_treat_as_movable;
 extern const unsigned long hugetlb_zero, hugetlb_infinity;
 extern int sysctl_hugetlb_shm_group;
 
@@ -163,7 +165,7 @@
 
 extern const struct file_operations hugetlbfs_file_operations;
 extern struct vm_operations_struct hugetlb_vm_ops;
-struct file *hugetlb_zero_setup(size_t);
+struct file *hugetlb_file_setup(const char *name, size_t);
 int hugetlb_get_quota(struct address_space *mapping);
 void hugetlb_put_quota(struct address_space *mapping);
 
@@ -185,7 +187,7 @@
 
 #define is_file_hugepages(file)		0
 #define set_file_hugepages(file)	BUG()
-#define hugetlb_zero_setup(size)	ERR_PTR(-ENOSYS)
+#define hugetlb_file_setup(name,size)	ERR_PTR(-ENOSYS)
 
 #endif /* !CONFIG_HUGETLBFS */
 
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index cae7d61..2eaba21 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -90,7 +90,7 @@
 				      const u8 *values);
 /* Returns the number of read bytes */
 extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
-					 u8 command, u8 *values);
+					 u8 command, u8 length, u8 *values);
 extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
 					  u8 command, u8 length,
 					  const u8 *values);
@@ -150,15 +150,20 @@
 
 /**
  * struct i2c_client - represent an I2C slave device
+ * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
+ *	I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
  * @addr: Address used on the I2C bus connected to the parent adapter.
  * @name: Indicates the type of the device, usually a chip name that's
  *	generic enough to hide second-sourcing and compatible revisions.
+ * @adapter: manages the bus segment hosting this I2C device
  * @dev: Driver model device node for the slave.
+ * @irq: indicates the IRQ generated by this device (if any)
  * @driver_name: Identifies new-style driver used with this device; also
  *	used as the module name for hotplug/coldplug modprobe support.
  *
  * An i2c_client identifies a single device (i.e. chip) connected to an
- * i2c bus. The behaviour is defined by the routines of the driver.
+ * i2c bus. The behaviour exposed to Linux is defined by the driver
+ * managing the device.
  */
 struct i2c_client {
 	unsigned short flags;		/* div., see below		*/
@@ -180,7 +185,8 @@
 
 static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
 {
-	return to_i2c_client(container_of(kobj, struct device, kobj));
+	struct device * const dev = container_of(kobj, struct device, kobj);
+	return to_i2c_client(dev);
 }
 
 static inline void *i2c_get_clientdata (struct i2c_client *dev)
@@ -201,7 +207,7 @@
  * @addr: stored in i2c_client.addr
  * @platform_data: stored in i2c_client.dev.platform_data
  * @irq: stored in i2c_client.irq
-
+ *
  * I2C doesn't actually support hardware probing, although controllers and
  * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
  * a device at a given address.  Drivers commonly need more information than
@@ -210,7 +216,7 @@
  * i2c_board_info is used to build tables of information listing I2C devices
  * that are present.  This information is used to grow the driver model tree
  * for "new style" I2C drivers.  For mainboards this is done statically using
- * i2c_register_board_info(), where @bus_num represents an adapter that isn't
+ * i2c_register_board_info(); bus numbers identify adapters that aren't
  * yet available.  For add-on boards, i2c_new_device() does this dynamically
  * with the adapter already known.
  */
@@ -518,8 +524,9 @@
 #define I2C_SMBUS_WORD_DATA	    3
 #define I2C_SMBUS_PROC_CALL	    4
 #define I2C_SMBUS_BLOCK_DATA	    5
-#define I2C_SMBUS_I2C_BLOCK_DATA    6
+#define I2C_SMBUS_I2C_BLOCK_BROKEN  6
 #define I2C_SMBUS_BLOCK_PROC_CALL   7		/* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA    8
 
 
 /* ----- commands for the ioctl like i2c_command call:
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index 52f53e2..333a370 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>	/* work_struct */
 #include <linux/mempool.h>
+#include <linux/mutex.h>
 
 #include <asm/io.h>
 #include <asm/semaphore.h>	/* Needed for MUTEX init macros */
@@ -425,7 +426,7 @@
 
 	struct device device;
 
-	struct semaphore lock;	/* device lock */
+	struct mutex lock;	/* device lock */
 };
 
 /*
@@ -544,7 +545,7 @@
 	struct i2o_dma hrt;	/* HW Resource Table */
 	i2o_lct *lct;		/* Logical Config Table */
 	struct i2o_dma dlct;	/* Temp LCT */
-	struct semaphore lct_lock;	/* Lock for LCT updates */
+	struct mutex lct_lock;	/* Lock for LCT updates */
 	struct i2o_dma status_block;	/* IOP status block */
 
 	struct i2o_io base;	/* controller messaging unit */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 07aba87..19ab258 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -25,6 +25,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
+#include <asm/mutex.h>
 
 /******************************************************************************
  * IDE driver configuration options (play with these as desired):
@@ -685,6 +686,8 @@
 	u8 mwdma_mask;
 	u8 swdma_mask;
 
+	u8 cbl;		/* cable type */
+
 	hwif_chipset_t chipset;	/* sub-module for tuning.. */
 
 	struct pci_dev  *pci_dev;	/* for pci chipsets */
@@ -735,8 +738,8 @@
 	void (*ide_dma_clear_irq)(ide_drive_t *drive);
 	void (*dma_host_on)(ide_drive_t *drive);
 	void (*dma_host_off)(ide_drive_t *drive);
-	int (*ide_dma_lostirq)(ide_drive_t *drive);
-	int (*ide_dma_timeout)(ide_drive_t *drive);
+	void (*dma_lost_irq)(ide_drive_t *drive);
+	void (*dma_timeout)(ide_drive_t *drive);
 
 	void (*OUTB)(u8 addr, unsigned long port);
 	void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
@@ -791,7 +794,6 @@
 	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
 	unsigned	reset      : 1;	/* reset after probe */
 	unsigned	autodma    : 1;	/* auto-attempt using DMA at boot */
-	unsigned	udma_four  : 1;	/* 1=ATA-66 capable, 0=default */
 	unsigned	no_lba48   : 1; /* 1 = cannot do LBA48 */
 	unsigned	no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
 	unsigned	auto_poll  : 1; /* supports nop auto-poll */
@@ -863,7 +865,7 @@
 
 typedef struct ide_driver_s ide_driver_t;
 
-extern struct semaphore ide_setting_sem;
+extern struct mutex ide_setting_mtx;
 
 int set_io_32bit(ide_drive_t *, int);
 int set_pio_mode(ide_drive_t *, int);
@@ -1001,6 +1003,7 @@
 	struct device_driver	gen_driver;
 	int		(*probe)(ide_drive_t *);
 	void		(*remove)(ide_drive_t *);
+	void		(*resume)(ide_drive_t *);
 	void		(*shutdown)(ide_drive_t *);
 #ifdef CONFIG_IDE_PROC_FS
 	ide_proc_entry_t	*proc;
@@ -1303,8 +1306,8 @@
 extern int ide_dma_setup(ide_drive_t *);
 extern void ide_dma_start(ide_drive_t *);
 extern int __ide_dma_end(ide_drive_t *);
-extern int __ide_dma_lostirq(ide_drive_t *);
-extern int __ide_dma_timeout(ide_drive_t *);
+extern void ide_dma_lost_irq(ide_drive_t *);
+extern void ide_dma_timeout(ide_drive_t *);
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
 
 #else
@@ -1381,11 +1384,11 @@
 
 
 extern spinlock_t ide_lock;
-extern struct semaphore ide_cfg_sem;
+extern struct mutex ide_cfg_mtx;
 /*
  * Structure locking:
  *
- * ide_cfg_sem and ide_lock together protect changes to
+ * ide_cfg_mtx and ide_lock together protect changes to
  * ide_hwif_t->{next,hwgroup}
  * ide_drive_t->next
  *
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 8268034..0edda41 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -78,9 +78,41 @@
 int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
 int idr_get_new(struct idr *idp, void *ptr, int *id);
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
+int idr_for_each(struct idr *idp,
+		 int (*fn)(int id, void *p, void *data), void *data);
 void *idr_replace(struct idr *idp, void *ptr, int id);
 void idr_remove(struct idr *idp, int id);
+void idr_remove_all(struct idr *idp);
 void idr_destroy(struct idr *idp);
 void idr_init(struct idr *idp);
 
+
+/*
+ * IDA - IDR based id allocator, use when translation from id to
+ * pointer isn't necessary.
+ */
+#define IDA_CHUNK_SIZE		128	/* 128 bytes per chunk */
+#define IDA_BITMAP_LONGS	(128 / sizeof(long) - 1)
+#define IDA_BITMAP_BITS		(IDA_BITMAP_LONGS * sizeof(long) * 8)
+
+struct ida_bitmap {
+	long			nr_busy;
+	unsigned long		bitmap[IDA_BITMAP_LONGS];
+};
+
+struct ida {
+	struct idr		idr;
+	struct ida_bitmap	*free_bitmap;
+};
+
+#define IDA_INIT(name)		{ .idr = IDR_INIT(name), .free_bitmap = NULL, }
+#define DEFINE_IDA(name)	struct ida name = IDA_INIT(name)
+
+int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
+int ida_get_new(struct ida *ida, int *p_id);
+void ida_remove(struct ida *ida, int id);
+void ida_destroy(struct ida *ida);
+void ida_init(struct ida *ida);
+
 #endif /* __IDR_H__ */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index ecd61e8..272f8c8 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -227,6 +227,17 @@
 #define WLAN_CAPABILITY_SHORT_SLOT_TIME	(1<<10)
 #define WLAN_CAPABILITY_DSSS_OFDM	(1<<13)
 
+/* 802.11g ERP information element */
+#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
+#define WLAN_ERP_USE_PROTECTION (1<<1)
+#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
+
+/* WLAN_ERP_BARKER_PREAMBLE values */
+enum {
+	WLAN_ERP_PREAMBLE_SHORT = 0,
+	WLAN_ERP_PREAMBLE_LONG = 1,
+};
+
 /* Status codes */
 enum ieee80211_statuscode {
 	WLAN_STATUS_SUCCESS = 0,
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 1db774c..3213f6f 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -33,6 +33,7 @@
 #define ETH_ZLEN	60		/* Min. octets in frame sans FCS */
 #define ETH_DATA_LEN	1500		/* Max. octets in payload	 */
 #define ETH_FRAME_LEN	1514		/* Max. octets in frame sans FCS */
+#define ETH_FCS_LEN	4		/* Octets in the FCS		 */
 
 /*
  *	These are the defined Ethernet Protocol ID's.
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 604c243..422084d 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -76,6 +76,8 @@
 #define IFLA_WEIGHT IFLA_WEIGHT
 	IFLA_OPERSTATE,
 	IFLA_LINKMODE,
+	IFLA_LINKINFO,
+#define IFLA_LINKINFO IFLA_LINKINFO
 	__IFLA_MAX
 };
 
@@ -140,4 +142,49 @@
 	__u32	retrans_time;
 };
 
+enum
+{
+	IFLA_INFO_UNSPEC,
+	IFLA_INFO_KIND,
+	IFLA_INFO_DATA,
+	IFLA_INFO_XSTATS,
+	__IFLA_INFO_MAX,
+};
+
+#define IFLA_INFO_MAX	(__IFLA_INFO_MAX - 1)
+
+/* VLAN section */
+
+enum
+{
+	IFLA_VLAN_UNSPEC,
+	IFLA_VLAN_ID,
+	IFLA_VLAN_FLAGS,
+	IFLA_VLAN_EGRESS_QOS,
+	IFLA_VLAN_INGRESS_QOS,
+	__IFLA_VLAN_MAX,
+};
+
+#define IFLA_VLAN_MAX	(__IFLA_VLAN_MAX - 1)
+
+struct ifla_vlan_flags {
+	__u32	flags;
+	__u32	mask;
+};
+
+enum
+{
+	IFLA_VLAN_QOS_UNSPEC,
+	IFLA_VLAN_QOS_MAPPING,
+	__IFLA_VLAN_QOS_MAX
+};
+
+#define IFLA_VLAN_QOS_MAX	(__IFLA_VLAN_QOS_MAX - 1)
+
+struct ifla_vlan_qos_mapping
+{
+	__u32 from;
+	__u32 to;
+};
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
new file mode 100644
index 0000000..0d9d7ea
--- /dev/null
+++ b/include/linux/if_macvlan.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_IF_MACVLAN_H
+#define _LINUX_IF_MACVLAN_H
+
+#ifdef __KERNEL__
+
+extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *);
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_IF_MACVLAN_H */
diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h
index 768372f..0f2f70d 100644
--- a/include/linux/if_ppp.h
+++ b/include/linux/if_ppp.h
@@ -110,6 +110,21 @@
 	struct ppp_comp_stats stats;
 };
 
+/* For PPPIOCGL2TPSTATS */
+struct pppol2tp_ioc_stats {
+	__u16		tunnel_id;	/* redundant */
+	__u16		session_id;	/* if zero, get tunnel stats */
+	__u32		using_ipsec:1;	/* valid only for session_id == 0 */
+	aligned_u64	tx_packets;
+	aligned_u64	tx_bytes;
+	aligned_u64	tx_errors;
+	aligned_u64	rx_packets;
+	aligned_u64	rx_bytes;
+	aligned_u64	rx_seq_discards;
+	aligned_u64	rx_oos_packets;
+	aligned_u64	rx_errors;
+};
+
 #define ifr__name       b.ifr_ifrn.ifrn_name
 #define stats_ptr       b.ifr_ifru.ifru_data
 
@@ -146,6 +161,7 @@
 #define PPPIOCDISCONN	_IO('t', 57)		/* disconnect channel */
 #define PPPIOCATTCHAN	_IOW('t', 56, int)	/* attach to ppp channel */
 #define PPPIOCGCHAN	_IOR('t', 55, int)	/* get ppp channel number */
+#define PPPIOCGL2TPSTATS _IOR('t', 54, struct pppol2tp_ioc_stats)
 
 #define SIOCGPPPSTATS   (SIOCDEVPRIVATE + 0)
 #define SIOCGPPPVER     (SIOCDEVPRIVATE + 1)	/* NEVER change this!! */
diff --git a/include/linux/if_pppol2tp.h b/include/linux/if_pppol2tp.h
new file mode 100644
index 0000000..516203b
--- /dev/null
+++ b/include/linux/if_pppol2tp.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Linux PPP over L2TP (PPPoL2TP) Socket Implementation (RFC 2661)
+ *
+ * This file supplies definitions required by the PPP over L2TP driver
+ * (pppol2tp.c).  All version information wrt this file is located in pppol2tp.c
+ *
+ * License:
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __LINUX_IF_PPPOL2TP_H
+#define __LINUX_IF_PPPOL2TP_H
+
+#include <asm/types.h>
+
+#ifdef __KERNEL__
+#include <linux/in.h>
+#endif
+
+/* Structure used to connect() the socket to a particular tunnel UDP
+ * socket.
+ */
+struct pppol2tp_addr
+{
+	pid_t	pid;			/* pid that owns the fd.
+					 * 0 => current */
+	int	fd;			/* FD of UDP socket to use */
+
+	struct sockaddr_in addr;	/* IP address and port to send to */
+
+	__be16 s_tunnel, s_session;	/* For matching incoming packets */
+	__be16 d_tunnel, d_session;	/* For sending outgoing packets */
+};
+
+/* Socket options:
+ * DEBUG	- bitmask of debug message categories
+ * SENDSEQ	- 0 => don't send packets with sequence numbers
+ *		  1 => send packets with sequence numbers
+ * RECVSEQ	- 0 => receive packet sequence numbers are optional
+ *		  1 => drop receive packets without sequence numbers
+ * LNSMODE	- 0 => act as LAC.
+ *		  1 => act as LNS.
+ * REORDERTO	- reorder timeout (in millisecs). If 0, don't try to reorder.
+ */
+enum {
+	PPPOL2TP_SO_DEBUG	= 1,
+	PPPOL2TP_SO_RECVSEQ	= 2,
+	PPPOL2TP_SO_SENDSEQ	= 3,
+	PPPOL2TP_SO_LNSMODE	= 4,
+	PPPOL2TP_SO_REORDERTO	= 5,
+};
+
+/* Debug message categories for the DEBUG socket option */
+enum {
+	PPPOL2TP_MSG_DEBUG	= (1 << 0),	/* verbose debug (if
+						 * compiled in) */
+	PPPOL2TP_MSG_CONTROL	= (1 << 1),	/* userspace - kernel
+						 * interface */
+	PPPOL2TP_MSG_SEQ	= (1 << 2),	/* sequence numbers */
+	PPPOL2TP_MSG_DATA	= (1 << 3),	/* data packets */
+};
+
+
+
+#endif
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 6f987be..2565254 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -27,6 +27,7 @@
 #include <asm/semaphore.h>
 #include <linux/ppp_channel.h>
 #endif /* __KERNEL__ */
+#include <linux/if_pppol2tp.h>
 
 /* For user-space programs to pick up these definitions
  * which they wouldn't get otherwise without defining __KERNEL__
@@ -50,8 +51,9 @@
  * Protocols supported by AF_PPPOX 
  */ 
 #define PX_PROTO_OE    0 /* Currently just PPPoE */
-#define PX_MAX_PROTO   1	
- 
+#define PX_PROTO_OL2TP 1 /* Now L2TP also */
+#define PX_MAX_PROTO   2
+
 struct sockaddr_pppox { 
        sa_family_t     sa_family;            /* address family, AF_PPPOX */ 
        unsigned int    sa_protocol;          /* protocol identifier */ 
@@ -60,6 +62,16 @@
        }sa_addr; 
 }__attribute__ ((packed)); 
 
+/* The use of the above union isn't viable because the size of this
+ * struct must stay fixed over time -- applications use sizeof(struct
+ * sockaddr_pppox) to fill it. We use a protocol specific sockaddr
+ * type instead.
+ */
+struct sockaddr_pppol2tp {
+	sa_family_t     sa_family;      /* address family, AF_PPPOX */
+	unsigned int    sa_protocol;    /* protocol identifier */
+	struct pppol2tp_addr pppol2tp;
+}__attribute__ ((packed));
 
 /*********************************************************************
  *
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 88aef7b..42eb694 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -36,6 +36,7 @@
 	unsigned long 		flags;
 	int			attached;
 	uid_t			owner;
+	gid_t			group;
 
 	wait_queue_head_t	read_wait;
 	struct sk_buff_head	readq;
@@ -78,6 +79,7 @@
 #define TUNSETPERSIST _IOW('T', 203, int) 
 #define TUNSETOWNER   _IOW('T', 204, int)
 #define TUNSETLINK    _IOW('T', 205, int)
+#define TUNSETGROUP   _IOW('T', 206, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN		0x0001
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 81e9bc9..f8443fd 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -99,7 +99,7 @@
 }
 
 struct vlan_priority_tci_mapping {
-	unsigned long priority;
+	u32 priority;
 	unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
 				  * at provisioning time.
 				  * ((skb->priority << 13) & 0xE000)
@@ -112,7 +112,10 @@
 	/** This will be the mapping that correlates skb->priority to
 	 * 3 bits of VLAN QOS tags...
 	 */
-	unsigned long ingress_priority_map[8];
+	unsigned int nr_ingress_mappings;
+	u32 ingress_priority_map[8];
+
+	unsigned int nr_egress_mappings;
 	struct vlan_priority_tci_mapping *egress_priority_map[16]; /* hash table */
 
 	unsigned short vlan_id;        /*  The VLAN Identifier for this interface. */
@@ -124,14 +127,8 @@
                                         *   like DHCP that use packet-filtering and don't understand
                                         *   802.1Q
                                         */
-	struct dev_mc_list *old_mc_list;  /* old multi-cast list for the VLAN interface..
-                                           * we save this so we can tell what changes were
-                                           * made, in order to feed the right changes down
-                                           * to the real hardware...
-                                           */
-	int old_allmulti;               /* similar to above. */
-	int old_promiscuity;            /* similar to above. */
 	struct net_device *real_dev;    /* the underlying device/interface */
+	unsigned char real_dev_addr[ETH_ALEN];
 	struct proc_dir_entry *dent;    /* Holds the proc data */
 	unsigned long cnt_inc_headroom_on_tx; /* How many times did we have to grow the skb on TX. */
 	unsigned long cnt_encap_on_xmit;      /* How many times did we have to encapsulate the skb on TX. */
@@ -395,6 +392,10 @@
 	GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
 };
 
+enum vlan_flags {
+	VLAN_FLAG_REORDER_HDR	= 0x1,
+};
+
 enum vlan_name_types {
 	VLAN_NAME_TYPE_PLUS_VID, /* Name will look like:  vlan0005 */
 	VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like:  eth1.0005 */
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index c0f7aec..d83fee2 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -3,35 +3,18 @@
 
 #ifdef __KERNEL__
 
+#include <linux/bitmap.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
 #include <linux/rcupdate.h>
 #include <linux/timer.h>
+#include <linux/sysctl.h>
 
 struct ipv4_devconf
 {
-	int	accept_redirects;
-	int	send_redirects;
-	int	secure_redirects;
-	int	shared_media;
-	int	accept_source_route;
-	int	rp_filter;
-	int	proxy_arp;
-	int	bootp_relay;
-	int	log_martians;
-	int	forwarding;
-	int	mc_forwarding;
-	int	tag;
-	int     arp_filter;
-	int	arp_announce;
-	int	arp_ignore;
-	int	arp_accept;
-	int	medium_id;
-	int	no_xfrm;
-	int	no_policy;
-	int	force_igmp_version;
-	int	promote_secondaries;
 	void	*sysctl;
+	int	data[__NET_IPV4_CONF_MAX - 1];
+	DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1);
 };
 
 extern struct ipv4_devconf ipv4_devconf;
@@ -60,30 +43,70 @@
 	struct rcu_head		rcu_head;
 };
 
-#define IN_DEV_FORWARD(in_dev)		((in_dev)->cnf.forwarding)
-#define IN_DEV_MFORWARD(in_dev)		(ipv4_devconf.mc_forwarding && (in_dev)->cnf.mc_forwarding)
-#define IN_DEV_RPFILTER(in_dev)		(ipv4_devconf.rp_filter && (in_dev)->cnf.rp_filter)
-#define IN_DEV_SOURCE_ROUTE(in_dev)	(ipv4_devconf.accept_source_route && (in_dev)->cnf.accept_source_route)
-#define IN_DEV_BOOTP_RELAY(in_dev)	(ipv4_devconf.bootp_relay && (in_dev)->cnf.bootp_relay)
+#define IPV4_DEVCONF(cnf, attr) ((cnf).data[NET_IPV4_CONF_ ## attr - 1])
+#define IPV4_DEVCONF_ALL(attr) IPV4_DEVCONF(ipv4_devconf, attr)
 
-#define IN_DEV_LOG_MARTIANS(in_dev)	(ipv4_devconf.log_martians || (in_dev)->cnf.log_martians)
-#define IN_DEV_PROXY_ARP(in_dev)	(ipv4_devconf.proxy_arp || (in_dev)->cnf.proxy_arp)
-#define IN_DEV_SHARED_MEDIA(in_dev)	(ipv4_devconf.shared_media || (in_dev)->cnf.shared_media)
-#define IN_DEV_TX_REDIRECTS(in_dev)	(ipv4_devconf.send_redirects || (in_dev)->cnf.send_redirects)
-#define IN_DEV_SEC_REDIRECTS(in_dev)	(ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
-#define IN_DEV_IDTAG(in_dev)		((in_dev)->cnf.tag)
-#define IN_DEV_MEDIUM_ID(in_dev)	((in_dev)->cnf.medium_id)
-#define IN_DEV_PROMOTE_SECONDARIES(in_dev)	(ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries)
+static inline int ipv4_devconf_get(struct in_device *in_dev, int index)
+{
+	index--;
+	return in_dev->cnf.data[index];
+}
+
+static inline void ipv4_devconf_set(struct in_device *in_dev, int index,
+				    int val)
+{
+	index--;
+	set_bit(index, in_dev->cnf.state);
+	in_dev->cnf.data[index] = val;
+}
+
+static inline void ipv4_devconf_setall(struct in_device *in_dev)
+{
+	bitmap_fill(in_dev->cnf.state, __NET_IPV4_CONF_MAX - 1);
+}
+
+#define IN_DEV_CONF_GET(in_dev, attr) \
+	ipv4_devconf_get((in_dev), NET_IPV4_CONF_ ## attr)
+#define IN_DEV_CONF_SET(in_dev, attr, val) \
+	ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val))
+
+#define IN_DEV_ANDCONF(in_dev, attr) \
+	(IPV4_DEVCONF_ALL(attr) && IN_DEV_CONF_GET((in_dev), attr))
+#define IN_DEV_ORCONF(in_dev, attr) \
+	(IPV4_DEVCONF_ALL(attr) || IN_DEV_CONF_GET((in_dev), attr))
+#define IN_DEV_MAXCONF(in_dev, attr) \
+	(max(IPV4_DEVCONF_ALL(attr), IN_DEV_CONF_GET((in_dev), attr)))
+
+#define IN_DEV_FORWARD(in_dev)		IN_DEV_CONF_GET((in_dev), FORWARDING)
+#define IN_DEV_MFORWARD(in_dev)		(IPV4_DEVCONF_ALL(MC_FORWARDING) && \
+					 IPV4_DEVCONF((in_dev)->cnf, \
+						      MC_FORWARDING))
+#define IN_DEV_RPFILTER(in_dev)		IN_DEV_ANDCONF((in_dev), RP_FILTER)
+#define IN_DEV_SOURCE_ROUTE(in_dev)	IN_DEV_ANDCONF((in_dev), \
+						       ACCEPT_SOURCE_ROUTE)
+#define IN_DEV_BOOTP_RELAY(in_dev)	IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
+
+#define IN_DEV_LOG_MARTIANS(in_dev)	IN_DEV_ORCONF((in_dev), LOG_MARTIANS)
+#define IN_DEV_PROXY_ARP(in_dev)	IN_DEV_ORCONF((in_dev), PROXY_ARP)
+#define IN_DEV_SHARED_MEDIA(in_dev)	IN_DEV_ORCONF((in_dev), SHARED_MEDIA)
+#define IN_DEV_TX_REDIRECTS(in_dev)	IN_DEV_ORCONF((in_dev), SEND_REDIRECTS)
+#define IN_DEV_SEC_REDIRECTS(in_dev)	IN_DEV_ORCONF((in_dev), \
+						      SECURE_REDIRECTS)
+#define IN_DEV_IDTAG(in_dev)		IN_DEV_CONF_GET(in_dev, TAG)
+#define IN_DEV_MEDIUM_ID(in_dev)	IN_DEV_CONF_GET(in_dev, MEDIUM_ID)
+#define IN_DEV_PROMOTE_SECONDARIES(in_dev) \
+					IN_DEV_ORCONF((in_dev), \
+						      PROMOTE_SECONDARIES)
 
 #define IN_DEV_RX_REDIRECTS(in_dev) \
 	((IN_DEV_FORWARD(in_dev) && \
-	  (ipv4_devconf.accept_redirects && (in_dev)->cnf.accept_redirects)) \
+	  IN_DEV_ANDCONF((in_dev), ACCEPT_REDIRECTS)) \
 	 || (!IN_DEV_FORWARD(in_dev) && \
-	  (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
+	  IN_DEV_ORCONF((in_dev), ACCEPT_REDIRECTS)))
 
-#define IN_DEV_ARPFILTER(in_dev)	(ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
-#define IN_DEV_ARP_ANNOUNCE(in_dev)	(max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
-#define IN_DEV_ARP_IGNORE(in_dev)	(max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore))
+#define IN_DEV_ARPFILTER(in_dev)	IN_DEV_ORCONF((in_dev), ARPFILTER)
+#define IN_DEV_ARP_ANNOUNCE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
+#define IN_DEV_ARP_IGNORE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
 
 struct in_ifaddr
 {
@@ -108,7 +131,6 @@
 extern int		inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
 extern int		devinet_ioctl(unsigned int cmd, void __user *);
 extern void		devinet_init(void);
-extern struct in_device *inetdev_init(struct net_device *dev);
 extern struct in_device	*inetdev_by_index(int);
 extern __be32		inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
 extern __be32		inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope);
diff --git a/include/linux/init.h b/include/linux/init.h
index e007ae4..5b52853 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -45,6 +45,19 @@
 #define __exitdata	__attribute__ ((__section__(".exit.data")))
 #define __exit_call	__attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
 
+/* modpost check for section mismatches during the kernel build.
+ * A section mismatch happens when there are references from a
+ * code or data section to an init section (both code or data).
+ * The init sections are (for most archs) discarded by the kernel
+ * when early init has completed so all such references are potential bugs.
+ * For exit sections the same issue exists.
+ * The following markers are used for the cases where the reference to
+ * the init/exit section (code or data) is valid and will teach modpost
+ * not to issue a warning.
+ * The markers follow same syntax rules as __init / __initdata. */
+#define __init_refok     noinline __attribute__ ((__section__ (".text.init.refok")))
+#define __initdata_refok          __attribute__ ((__section__ (".data.init.refok")))
+
 #ifdef MODULE
 #define __exit		__attribute__ ((__section__(".exit.text")))
 #else
@@ -158,9 +171,6 @@
 #define __setup(str, fn)					\
 	__setup_param(str, fn, fn, 0)
 
-#define __obsolete_setup(str)					\
-	__setup_null_param(str, __LINE__)
-
 /* NOTE: fn is as per module_param, not __setup!  Emits warning if fn
  * returns non-zero. */
 #define early_param(str, fn)					\
@@ -226,7 +236,6 @@
 #define __setup_param(str, unique_id, fn)	/* nothing */
 #define __setup_null_param(str, unique_id) 	/* nothing */
 #define __setup(str, func) 			/* nothing */
-#define __obsolete_setup(str) 			/* nothing */
 #endif
 
 /* Data marked not to be saved by software suspend */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 276ccaa..cab741c 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -8,6 +8,7 @@
 #include <linux/lockdep.h>
 #include <linux/ipc.h>
 #include <linux/pid_namespace.h>
+#include <linux/user_namespace.h>
 
 #define INIT_FDTABLE \
 {							\
@@ -78,6 +79,7 @@
 	.uts_ns		= &init_uts_ns,					\
 	.mnt_ns		= NULL,						\
 	INIT_IPC_NS(ipc_ns)						\
+	.user_ns	= &init_user_ns,				\
 }
 
 #define INIT_SIGHAND(sighand) {						\
diff --git a/include/linux/input.h b/include/linux/input.h
index be2bf3a..18c98b5 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -108,6 +108,13 @@
 
 /*
  * Keys and buttons
+ *
+ * Most of the keys/buttons are modeled after USB HUT 1.12
+ * (see http://www.usb.org/developers/hidpage).
+ * Abbreviations in the comments:
+ * AC - Application Control
+ * AL - Application Launch Button
+ * SC - System Control
  */
 
 #define KEY_RESERVED		0
@@ -226,7 +233,7 @@
 #define KEY_MUTE		113
 #define KEY_VOLUMEDOWN		114
 #define KEY_VOLUMEUP		115
-#define KEY_POWER		116
+#define KEY_POWER		116	/* SC System Power Down */
 #define KEY_KPEQUAL		117
 #define KEY_KPPLUSMINUS		118
 #define KEY_PAUSE		119
@@ -240,38 +247,39 @@
 #define KEY_RIGHTMETA		126
 #define KEY_COMPOSE		127
 
-#define KEY_STOP		128
+#define KEY_STOP		128	/* AC Stop */
 #define KEY_AGAIN		129
-#define KEY_PROPS		130
-#define KEY_UNDO		131
+#define KEY_PROPS		130	/* AC Properties */
+#define KEY_UNDO		131	/* AC Undo */
 #define KEY_FRONT		132
-#define KEY_COPY		133
-#define KEY_OPEN		134
-#define KEY_PASTE		135
-#define KEY_FIND		136
-#define KEY_CUT			137
-#define KEY_HELP		138
-#define KEY_MENU		139
-#define KEY_CALC		140
+#define KEY_COPY		133	/* AC Copy */
+#define KEY_OPEN		134	/* AC Open */
+#define KEY_PASTE		135	/* AC Paste */
+#define KEY_FIND		136	/* AC Search */
+#define KEY_CUT			137	/* AC Cut */
+#define KEY_HELP		138	/* AL Integrated Help Center */
+#define KEY_MENU		139	/* Menu (show menu) */
+#define KEY_CALC		140	/* AL Calculator */
 #define KEY_SETUP		141
-#define KEY_SLEEP		142
-#define KEY_WAKEUP		143
-#define KEY_FILE		144
+#define KEY_SLEEP		142	/* SC System Sleep */
+#define KEY_WAKEUP		143	/* System Wake Up */
+#define KEY_FILE		144	/* AL Local Machine Browser */
 #define KEY_SENDFILE		145
 #define KEY_DELETEFILE		146
 #define KEY_XFER		147
 #define KEY_PROG1		148
 #define KEY_PROG2		149
-#define KEY_WWW			150
+#define KEY_WWW			150	/* AL Internet Browser */
 #define KEY_MSDOS		151
-#define KEY_COFFEE		152
+#define KEY_COFFEE		152	/* AL Terminal Lock/Screensaver */
+#define KEY_SCREENLOCK		KEY_COFFEE
 #define KEY_DIRECTION		153
 #define KEY_CYCLEWINDOWS	154
 #define KEY_MAIL		155
-#define KEY_BOOKMARKS		156
+#define KEY_BOOKMARKS		156	/* AC Bookmarks */
 #define KEY_COMPUTER		157
-#define KEY_BACK		158
-#define KEY_FORWARD		159
+#define KEY_BACK		158	/* AC Back */
+#define KEY_FORWARD		159	/* AC Forward */
 #define KEY_CLOSECD		160
 #define KEY_EJECTCD		161
 #define KEY_EJECTCLOSECD	162
@@ -281,20 +289,20 @@
 #define KEY_STOPCD		166
 #define KEY_RECORD		167
 #define KEY_REWIND		168
-#define KEY_PHONE		169
+#define KEY_PHONE		169	/* Media Select Telephone */
 #define KEY_ISO			170
-#define KEY_CONFIG		171
-#define KEY_HOMEPAGE		172
-#define KEY_REFRESH		173
-#define KEY_EXIT		174
+#define KEY_CONFIG		171	/* AL Consumer Control Configuration */
+#define KEY_HOMEPAGE		172	/* AC Home */
+#define KEY_REFRESH		173	/* AC Refresh */
+#define KEY_EXIT		174	/* AC Exit */
 #define KEY_MOVE		175
 #define KEY_EDIT		176
 #define KEY_SCROLLUP		177
 #define KEY_SCROLLDOWN		178
 #define KEY_KPLEFTPAREN		179
 #define KEY_KPRIGHTPAREN	180
-#define KEY_NEW			181
-#define KEY_REDO		182
+#define KEY_NEW			181	/* AC New */
+#define KEY_REDO		182	/* AC Redo/Repeat */
 
 #define KEY_F13			183
 #define KEY_F14			184
@@ -314,11 +322,11 @@
 #define KEY_PROG3		202
 #define KEY_PROG4		203
 #define KEY_SUSPEND		205
-#define KEY_CLOSE		206
+#define KEY_CLOSE		206	/* AC Close */
 #define KEY_PLAY		207
 #define KEY_FASTFORWARD		208
 #define KEY_BASSBOOST		209
-#define KEY_PRINT		210
+#define KEY_PRINT		210	/* AC Print */
 #define KEY_HP			211
 #define KEY_CAMERA		212
 #define KEY_SOUND		213
@@ -327,11 +335,11 @@
 #define KEY_CHAT		216
 #define KEY_SEARCH		217
 #define KEY_CONNECT		218
-#define KEY_FINANCE		219
+#define KEY_FINANCE		219	/* AL Checkbook/Finance */
 #define KEY_SPORT		220
 #define KEY_SHOP		221
 #define KEY_ALTERASE		222
-#define KEY_CANCEL		223
+#define KEY_CANCEL		223	/* AC Cancel */
 #define KEY_BRIGHTNESSDOWN	224
 #define KEY_BRIGHTNESSUP	225
 #define KEY_MEDIA		226
@@ -341,10 +349,10 @@
 #define KEY_KBDILLUMDOWN	229
 #define KEY_KBDILLUMUP		230
 
-#define KEY_SEND		231
-#define KEY_REPLY		232
-#define KEY_FORWARDMAIL		233
-#define KEY_SAVE		234
+#define KEY_SEND		231	/* AC Send */
+#define KEY_REPLY		232	/* AC Reply */
+#define KEY_FORWARDMAIL		233	/* AC Forward Msg */
+#define KEY_SAVE		234	/* AC Save */
 #define KEY_DOCUMENTS		235
 
 #define KEY_BATTERY		236
@@ -433,15 +441,15 @@
 #define KEY_CLEAR		0x163
 #define KEY_POWER2		0x164
 #define KEY_OPTION		0x165
-#define KEY_INFO		0x166
+#define KEY_INFO		0x166	/* AL OEM Features/Tips/Tutorial */
 #define KEY_TIME		0x167
 #define KEY_VENDOR		0x168
 #define KEY_ARCHIVE		0x169
-#define KEY_PROGRAM		0x16a
+#define KEY_PROGRAM		0x16a	/* Media Select Program Guide */
 #define KEY_CHANNEL		0x16b
 #define KEY_FAVORITES		0x16c
 #define KEY_EPG			0x16d
-#define KEY_PVR			0x16e
+#define KEY_PVR			0x16e	/* Media Select Home */
 #define KEY_MHP			0x16f
 #define KEY_LANGUAGE		0x170
 #define KEY_TITLE		0x171
@@ -451,36 +459,36 @@
 #define KEY_MODE		0x175
 #define KEY_KEYBOARD		0x176
 #define KEY_SCREEN		0x177
-#define KEY_PC			0x178
-#define KEY_TV			0x179
-#define KEY_TV2			0x17a
-#define KEY_VCR			0x17b
-#define KEY_VCR2		0x17c
-#define KEY_SAT			0x17d
+#define KEY_PC			0x178	/* Media Select Computer */
+#define KEY_TV			0x179	/* Media Select TV */
+#define KEY_TV2			0x17a	/* Media Select Cable */
+#define KEY_VCR			0x17b	/* Media Select VCR */
+#define KEY_VCR2		0x17c	/* VCR Plus */
+#define KEY_SAT			0x17d	/* Media Select Satellite */
 #define KEY_SAT2		0x17e
-#define KEY_CD			0x17f
-#define KEY_TAPE		0x180
+#define KEY_CD			0x17f	/* Media Select CD */
+#define KEY_TAPE		0x180	/* Media Select Tape */
 #define KEY_RADIO		0x181
-#define KEY_TUNER		0x182
+#define KEY_TUNER		0x182	/* Media Select Tuner */
 #define KEY_PLAYER		0x183
 #define KEY_TEXT		0x184
-#define KEY_DVD			0x185
+#define KEY_DVD			0x185	/* Media Select DVD */
 #define KEY_AUX			0x186
 #define KEY_MP3			0x187
 #define KEY_AUDIO		0x188
 #define KEY_VIDEO		0x189
 #define KEY_DIRECTORY		0x18a
 #define KEY_LIST		0x18b
-#define KEY_MEMO		0x18c
+#define KEY_MEMO		0x18c	/* Media Select Messages */
 #define KEY_CALENDAR		0x18d
 #define KEY_RED			0x18e
 #define KEY_GREEN		0x18f
 #define KEY_YELLOW		0x190
 #define KEY_BLUE		0x191
-#define KEY_CHANNELUP		0x192
-#define KEY_CHANNELDOWN		0x193
+#define KEY_CHANNELUP		0x192	/* Channel Increment */
+#define KEY_CHANNELDOWN		0x193	/* Channel Decrement */
 #define KEY_FIRST		0x194
-#define KEY_LAST		0x195
+#define KEY_LAST		0x195	/* Recall Last */
 #define KEY_AB			0x196
 #define KEY_NEXT		0x197
 #define KEY_RESTART		0x198
@@ -491,21 +499,21 @@
 #define KEY_DIGITS		0x19d
 #define KEY_TEEN		0x19e
 #define KEY_TWEN		0x19f
-#define KEY_VIDEOPHONE		0x1a0
-#define KEY_GAMES		0x1a1
-#define KEY_ZOOMIN		0x1a2
-#define KEY_ZOOMOUT		0x1a3
-#define KEY_ZOOMRESET		0x1a4
-#define KEY_WORDPROCESSOR	0x1a5
-#define KEY_EDITOR		0x1a6
-#define KEY_SPREADSHEET		0x1a7
-#define KEY_GRAPHICSEDITOR	0x1a8
-#define KEY_PRESENTATION	0x1a9
-#define KEY_DATABASE		0x1aa
-#define KEY_NEWS		0x1ab
-#define KEY_VOICEMAIL		0x1ac
-#define KEY_ADDRESSBOOK		0x1ad
-#define KEY_MESSENGER		0x1ae
+#define KEY_VIDEOPHONE		0x1a0	/* Media Select Video Phone */
+#define KEY_GAMES		0x1a1	/* Media Select Games */
+#define KEY_ZOOMIN		0x1a2	/* AC Zoom In */
+#define KEY_ZOOMOUT		0x1a3	/* AC Zoom Out */
+#define KEY_ZOOMRESET		0x1a4	/* AC Zoom */
+#define KEY_WORDPROCESSOR	0x1a5	/* AL Word Processor */
+#define KEY_EDITOR		0x1a6	/* AL Text Editor */
+#define KEY_SPREADSHEET		0x1a7	/* AL Spreadsheet */
+#define KEY_GRAPHICSEDITOR	0x1a8	/* AL Graphics Editor */
+#define KEY_PRESENTATION	0x1a9	/* AL Presentation App */
+#define KEY_DATABASE		0x1aa	/* AL Database App */
+#define KEY_NEWS		0x1ab	/* AL Newsreader */
+#define KEY_VOICEMAIL		0x1ac	/* AL Voicemail */
+#define KEY_ADDRESSBOOK		0x1ad	/* AL Contacts/Address Book */
+#define KEY_MESSENGER		0x1ae	/* AL Instant Messaging */
 #define KEY_DISPLAYTOGGLE	0x1af	/* Turn display (LCD) on and off */
 
 #define KEY_DEL_EOL		0x1c0
@@ -603,6 +611,7 @@
 #define SW_LID			0x00  /* set = lid shut */
 #define SW_TABLET_MODE		0x01  /* set = tablet mode */
 #define SW_HEADPHONE_INSERT	0x02  /* set = inserted */
+#define SW_RADIO		0x03  /* set = radio enabled */
 #define SW_MAX			0x0f
 
 /*
@@ -972,15 +981,15 @@
 	struct mutex mutex;	/* serializes open and close operations */
 	unsigned int users;
 
-	struct class_device cdev;
+	struct device dev;
 	union {			/* temporarily so while we switching to struct device */
-		struct device *parent;
-	} dev;
+		struct device *dev;
+	} cdev;
 
 	struct list_head	h_list;
 	struct list_head	node;
 };
-#define to_input_dev(d) container_of(d, struct input_dev, cdev)
+#define to_input_dev(d) container_of(d, struct input_dev, dev)
 
 /*
  * Verify that we are in sync with input_device_id mod_devicetable.h #defines
@@ -1087,22 +1096,22 @@
 	struct list_head	h_node;
 };
 
-#define to_dev(n) container_of(n,struct input_dev,node)
-#define to_handler(n) container_of(n,struct input_handler,node)
-#define to_handle(n) container_of(n,struct input_handle,d_node)
-#define to_handle_h(n) container_of(n,struct input_handle,h_node)
+#define to_dev(n) container_of(n, struct input_dev, node)
+#define to_handler(n) container_of(n, struct input_handler, node)
+#define to_handle(n) container_of(n, struct input_handle, d_node)
+#define to_handle_h(n) container_of(n, struct input_handle, h_node)
 
 struct input_dev *input_allocate_device(void);
 void input_free_device(struct input_dev *dev);
 
 static inline struct input_dev *input_get_device(struct input_dev *dev)
 {
-	return to_input_dev(class_device_get(&dev->cdev));
+	return to_input_dev(get_device(&dev->dev));
 }
 
 static inline void input_put_device(struct input_dev *dev)
 {
-	class_device_put(&dev->cdev);
+	put_device(&dev->dev);
 }
 
 static inline void *input_get_drvdata(struct input_dev *dev)
diff --git a/include/linux/io.h b/include/linux/io.h
index 8423dd3..e3b2dda 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -63,32 +63,7 @@
 void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
 				    unsigned long size);
 void devm_iounmap(struct device *dev, void __iomem *addr);
-
-/**
- *	check_signature		-	find BIOS signatures
- *	@io_addr: mmio address to check
- *	@signature:  signature block
- *	@length: length of signature
- *
- *	Perform a signature comparison with the mmio address io_addr. This
- *	address should have been obtained by ioremap.
- *	Returns 1 on a match.
- */
-
-static inline int check_signature(const volatile void __iomem *io_addr,
-	const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
+int check_signature(const volatile void __iomem *io_addr,
+			const unsigned char *signature, int length);
 
 #endif /* _LINUX_IO_H */
diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h
index 8e2042b..2eaa142 100644
--- a/include/linux/ioprio.h
+++ b/include/linux/ioprio.h
@@ -47,8 +47,10 @@
 #define IOPRIO_NORM	(4)
 static inline int task_ioprio(struct task_struct *task)
 {
-	WARN_ON(!ioprio_valid(task->ioprio));
-	return IOPRIO_PRIO_DATA(task->ioprio);
+	if (ioprio_valid(task->ioprio))
+		return IOPRIO_PRIO_DATA(task->ioprio);
+
+	return IOPRIO_NORM;
 }
 
 static inline int task_nice_ioprio(struct task_struct *task)
diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h
deleted file mode 100644
index e234e20..0000000
--- a/include/linux/ip_mp_alg.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#ifndef _LINUX_IP_MP_ALG_H
-#define _LINUX_IP_MP_ALG_H
-
-enum ip_mp_alg {
-	IP_MP_ALG_NONE,
-	IP_MP_ALG_RR,
-	IP_MP_ALG_DRR,
-	IP_MP_ALG_RANDOM,
-	IP_MP_ALG_WRANDOM,
-	__IP_MP_ALG_MAX
-};
-
-#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1)
-
-#endif /* _LINUX_IP_MP_ALG_H */
-
diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index 1980867..3fd3ddd 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -52,6 +52,7 @@
 #ifdef __KERNEL__
 
 #include <linux/kref.h>
+#include <linux/spinlock.h>
 
 #define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
 
@@ -92,6 +93,7 @@
 
 #ifdef CONFIG_SYSVIPC
 #define INIT_IPC_NS(ns)		.ns		= &init_ipc_ns,
+extern void free_ipc_ns(struct kref *kref);
 extern struct ipc_namespace *copy_ipcs(unsigned long flags,
 						struct ipc_namespace *ns);
 #else
@@ -103,13 +105,9 @@
 }
 #endif
 
-#ifdef CONFIG_IPC_NS
-extern void free_ipc_ns(struct kref *kref);
-#endif
-
 static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
 {
-#ifdef CONFIG_IPC_NS
+#ifdef CONFIG_SYSVIPC
 	if (ns)
 		kref_get(&ns->kref);
 #endif
@@ -118,7 +116,7 @@
 
 static inline void put_ipc_ns(struct ipc_namespace *ns)
 {
-#ifdef CONFIG_IPC_NS
+#ifdef CONFIG_SYSVIPC
 	kref_put(&ns->kref, free_ipc_ns);
 #endif
 }
@@ -126,5 +124,3 @@
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_IPC_H */
-
-
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 09ea01a..97983dc9 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -27,8 +27,8 @@
 	int		ifr6_ifindex; 
 };
 
-#define IPV6_SRCRT_STRICT	0x01	/* this hop must be a neighbor	*/
-#define IPV6_SRCRT_TYPE_0	0	/* IPv6 type 0 Routing Header	*/
+#define IPV6_SRCRT_STRICT	0x01	/* Deprecated; will be removed */
+#define IPV6_SRCRT_TYPE_0	0	/* Deprecated; will be removed */
 #define IPV6_SRCRT_TYPE_2	2	/* IPv6 type 2 Routing Header	*/
 
 /*
@@ -209,9 +209,8 @@
 	DEVCONF_RTR_PROBE_INTERVAL,
 	DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN,
 	DEVCONF_PROXY_NDP,
-	__DEVCONF_OPTIMISTIC_DAD,
-	DEVCONF_ACCEPT_SOURCE_ROUTE,
 	DEVCONF_OPTIMISTIC_DAD,
+	DEVCONF_ACCEPT_SOURCE_ROUTE,
 	DEVCONF_MAX
 };
 
@@ -248,7 +247,7 @@
 	__u16			lastopt;
 	__u32			nhoff;
 	__u16			flags;
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	__u16			dsthao;
 #endif
 
@@ -300,8 +299,8 @@
 	/* pktoption flags */
 	union {
 		struct {
-			__u16	srcrt:2,
-				osrcrt:2,
+			__u16	srcrt:1,
+				osrcrt:1,
 			        rxinfo:1,
 			        rxoinfo:1,
 				rxhlim:1,
diff --git a/include/linux/irda.h b/include/linux/irda.h
index 945ba31..8e37357 100644
--- a/include/linux/irda.h
+++ b/include/linux/irda.h
@@ -216,6 +216,34 @@
 #define ifr_dtr       ifr_ifru.ifru_line.dtr
 #define ifr_rts       ifr_ifru.ifru_line.rts
 
+
+/* IrDA netlink definitions */
+#define IRDA_NL_NAME "irda"
+#define IRDA_NL_VERSION 1
+
+enum irda_nl_commands {
+	IRDA_NL_CMD_UNSPEC,
+	IRDA_NL_CMD_SET_MODE,
+	IRDA_NL_CMD_GET_MODE,
+
+	__IRDA_NL_CMD_AFTER_LAST
+};
+#define IRDA_NL_CMD_MAX (__IRDA_NL_CMD_AFTER_LAST - 1)
+
+enum nl80211_attrs {
+	IRDA_NL_ATTR_UNSPEC,
+	IRDA_NL_ATTR_IFNAME,
+	IRDA_NL_ATTR_MODE,
+
+	__IRDA_NL_ATTR_AFTER_LAST
+};
+#define IRDA_NL_ATTR_MAX (__IRDA_NL_ATTR_AFTER_LAST - 1)
+
+/* IrDA modes */
+#define IRDA_MODE_PRIMARY   0x1
+#define IRDA_MODE_SECONDARY 0x2
+#define IRDA_MODE_MONITOR   0x4
+
 #endif /* KERNEL_IRDA_H */
 
 
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 1695054..4465719 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -161,6 +161,7 @@
 	unsigned int		wake_depth;	/* nested wake enables */
 	unsigned int		irq_count;	/* For detecting broken IRQs */
 	unsigned int		irqs_unhandled;
+	unsigned long		last_unhandled;	/* Aging timer for unhandled count */
 	spinlock_t		lock;
 #ifdef CONFIG_SMP
 	cpumask_t		affinity;
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 12178d2..f73de6f 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -5,10 +5,11 @@
 #ifndef _LINUX_KALLSYMS_H
 #define _LINUX_KALLSYMS_H
 
+#include <linux/errno.h>
 
-#define KSYM_NAME_LEN 127
-#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN +	\
-			 2*(BITS_PER_LONG*3/10) + MODULE_NAME_LEN + 1)
+#define KSYM_NAME_LEN 128
+#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
+			 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
 
 #ifdef CONFIG_KALLSYMS
 /* Lookup the address for a symbol. Returns 0 if not found. */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 45353d7..1eb9cde 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -210,6 +210,7 @@
 #define TAINT_MACHINE_CHECK		(1<<4)
 #define TAINT_BAD_PAGE			(1<<5)
 #define TAINT_USER			(1<<6)
+#define TAINT_DIE			(1<<7)
 
 extern void dump_stack(void);
 
@@ -218,10 +219,14 @@
 	DUMP_PREFIX_ADDRESS,
 	DUMP_PREFIX_OFFSET
 };
-extern void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
-				size_t linebuflen);
-extern void print_hex_dump(const char *level, int prefix_type,
-				void *buf, size_t len);
+extern void hex_dump_to_buffer(const void *buf, size_t len,
+				int rowsize, int groupsize,
+				char *linebuf, size_t linebuflen, bool ascii);
+extern void print_hex_dump(const char *level, const char *prefix_str,
+				int prefix_type, int rowsize, int groupsize,
+				void *buf, size_t len, bool ascii);
+extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+			void *buf, size_t len);
 #define hex_asc(x)	"0123456789abcdef"[x]
 
 #ifdef DEBUG
diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h
index aea34e74..8c4350a 100644
--- a/include/linux/kernelcapi.h
+++ b/include/linux/kernelcapi.h
@@ -64,7 +64,7 @@
 	unsigned long nrecvdatapkt;
 	unsigned long nsentctlpkt;
 	unsigned long nsentdatapkt;
-	struct semaphore recv_sem;
+	struct mutex recv_mtx;
 	struct sk_buff_head recv_queue;
 	struct work_struct recv_work;
 	int release_in_progress;
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index c288e41..06cbf41 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -55,7 +55,7 @@
 	struct kobject		* parent;
 	struct kset		* kset;
 	struct kobj_type	* ktype;
-	struct dentry		* dentry;
+	struct sysfs_dirent	* sd;
 	wait_queue_head_t	poll;
 };
 
@@ -71,13 +71,14 @@
 extern void kobject_cleanup(struct kobject *);
 
 extern int __must_check kobject_add(struct kobject *);
-extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *);
+extern int __must_check kobject_shadow_add(struct kobject *kobj,
+					   struct sysfs_dirent *shadow_parent);
 extern void kobject_del(struct kobject *);
 
 extern int __must_check kobject_rename(struct kobject *, const char *new_name);
 extern int __must_check kobject_shadow_rename(struct kobject *kobj,
-						struct dentry *new_parent,
-						const char *new_name);
+					      struct sysfs_dirent *new_parent,
+					      const char *new_name);
 extern int __must_check kobject_move(struct kobject *, struct kobject *);
 
 extern int __must_check kobject_register(struct kobject *);
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index c762954..dae7143 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -261,12 +261,34 @@
 
 #endif
 
+/**
+ * ktime_equal - Compares two ktime_t variables to see if they are equal
+ * @cmp1:	comparable1
+ * @cmp2:	comparable2
+ *
+ * Compare two ktime_t variables, returns 1 if equal
+ */
+static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
+{
+	return cmp1.tv64 == cmp2.tv64;
+}
+
 static inline s64 ktime_to_us(const ktime_t kt)
 {
 	struct timeval tv = ktime_to_timeval(kt);
 	return (s64) tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
 }
 
+static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier)
+{
+       return ktime_to_us(ktime_sub(later, earlier));
+}
+
+static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
+{
+	return ktime_add_ns(kt, usec * 1000);
+}
+
 /*
  * The resolution of the clocks. The resolution value is returned in
  * the clock_getres() system call to give application programmers an
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 88afcef..494bed7 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -13,7 +13,6 @@
 #define __LINUX_LEDS_H_INCLUDED
 
 #include <linux/list.h>
-#include <linux/spinlock.h>
 
 struct device;
 struct class_device;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 666592e..47cd2a1 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -116,6 +116,7 @@
 enum {
 	/* various global constants */
 	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+	LIBATA_DUMB_MAX_PRD	= ATA_MAX_PRD / 4,	/* Worst case */
 	ATA_MAX_PORTS		= 8,
 	ATA_DEF_QUEUE		= 1,
 	/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
@@ -136,6 +137,8 @@
 	ATA_DFLAG_CDB_INTR	= (1 << 2), /* device asserts INTRQ when ready for CDB */
 	ATA_DFLAG_NCQ		= (1 << 3), /* device supports NCQ */
 	ATA_DFLAG_FLUSH_EXT	= (1 << 4), /* do FLUSH_EXT instead of FLUSH */
+	ATA_DFLAG_ACPI_PENDING	= (1 << 5), /* ACPI resume action pending */
+	ATA_DFLAG_ACPI_FAILED	= (1 << 6), /* ACPI on devcfg has failed */
 	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
 
 	ATA_DFLAG_PIO		= (1 << 8), /* device limited to PIO mode */
@@ -171,7 +174,6 @@
 	ATA_FLAG_SKIP_D2H_BSY	= (1 << 12), /* can't wait for the first D2H
 					      * Register FIS clearing BSY */
 	ATA_FLAG_DEBUGMSG	= (1 << 13),
-	ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
 	ATA_FLAG_IGN_SIMPLEX	= (1 << 15), /* ignore SIMPLEX */
 	ATA_FLAG_NO_IORDY	= (1 << 16), /* controller lacks iordy */
 	ATA_FLAG_ACPI_SATA	= (1 << 17), /* need native SATA ACPI layout */
@@ -194,9 +196,9 @@
 	ATA_PFLAG_SCSI_HOTPLUG	= (1 << 6), /* SCSI hotplug scheduled */
 	ATA_PFLAG_INITIALIZING	= (1 << 7), /* being initialized, don't touch */
 
-	ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */
 	ATA_PFLAG_SUSPENDED	= (1 << 17), /* port is suspended (power) */
 	ATA_PFLAG_PM_PENDING	= (1 << 18), /* PM operation pending */
+	ATA_PFLAG_GTM_VALID	= (1 << 19), /* acpi_gtm data valid */
 
 	/* struct ata_queued_cmd flags */
 	ATA_QCFLAG_ACTIVE	= (1 << 0), /* cmd not yet ack'd to scsi lyer */
@@ -299,7 +301,6 @@
 	ATA_HORKAGE_NODMA	= (1 << 1),	/* DMA problems */
 	ATA_HORKAGE_NONCQ	= (1 << 2),	/* Don't use NCQ */
 	ATA_HORKAGE_MAX_SEC_128	= (1 << 3),	/* Limit max sects to 128 */
-	ATA_HORKAGE_DMA_RW_ONLY	= (1 << 4),	/* ATAPI DMA for RW only */
 };
 
 enum hsm_task_states {
@@ -365,6 +366,9 @@
 	void			*private_data;
 	const struct ata_port_operations *ops;
 	unsigned long		flags;
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+#endif
 	struct ata_port		*simplex_claimed;	/* channel owning the DMA */
 	struct ata_port		*ports[0];
 };
@@ -430,7 +434,11 @@
 	struct ata_port		*ap;
 	unsigned int		devno;		/* 0 or 1 */
 	unsigned long		flags;		/* ATA_DFLAG_xxx */
+	unsigned int		horkage;	/* List of broken features */
 	struct scsi_device	*sdev;		/* attached SCSI device */
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+#endif
 	/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
 	u64			n_sectors;	/* size of device, if ATA */
 	unsigned int		class;		/* ATA_DEV_xxx */
@@ -458,11 +466,6 @@
 	/* error history */
 	struct ata_ering	ering;
 	int			spdn_cnt;
-	unsigned int		horkage;	/* List of broken features */
-#ifdef CONFIG_ATA_ACPI
-	/* ACPI objects info */
-	acpi_handle obj_handle;
-#endif
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
@@ -491,6 +494,17 @@
 	unsigned int		did_probe_mask;
 };
 
+struct ata_acpi_drive
+{
+	u32 pio;
+	u32 dma;
+} __packed;
+
+struct ata_acpi_gtm {
+	struct ata_acpi_drive drive[2];
+	u32 flags;
+} __packed;
+
 struct ata_port {
 	struct Scsi_Host	*scsi_host; /* our co-allocated scsi host */
 	const struct ata_port_operations *ops;
@@ -551,6 +565,10 @@
 
 	void			*private_data;
 
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+	struct ata_acpi_gtm	acpi_gtm;
+#endif
 	u8			sector_buf[ATA_SECT_SIZE]; /* owned by EH */
 };
 
@@ -574,8 +592,6 @@
 	void (*phy_reset) (struct ata_port *ap); /* obsolete */
 	int  (*set_mode) (struct ata_port *ap, struct ata_device **r_failed_dev);
 
-	void (*post_set_mode) (struct ata_port *ap);
-
 	int (*cable_detect) (struct ata_port *ap);
 
 	int  (*check_atapi_dma) (struct ata_queued_cmd *qc);
@@ -756,11 +772,13 @@
 extern u8 ata_altstatus(struct ata_port *ap);
 extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
 extern int ata_port_start (struct ata_port *ap);
+extern int ata_sff_port_start (struct ata_port *ap);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
 extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
 			  unsigned int buflen, int write_data);
 extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
 				unsigned int buflen, int write_data);
+extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
 extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -775,7 +793,6 @@
 extern void ata_id_c_string(const u16 *id, unsigned char *s,
 			    unsigned int ofs, unsigned int len);
 extern void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown);
-extern unsigned long ata_device_blacklisted(const struct ata_device *dev);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
@@ -852,11 +869,11 @@
 	unsigned long		val;
 };
 
-extern int ata_pci_init_native_host(struct ata_host *host);
+extern int ata_pci_init_sff_host(struct ata_host *host);
 extern int ata_pci_init_bmdma(struct ata_host *host);
-extern int ata_pci_prepare_native_host(struct pci_dev *pdev,
-				const struct ata_port_info * const * ppi,
-				struct ata_host **r_host);
+extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+				    const struct ata_port_info * const * ppi,
+				    struct ata_host **r_host);
 extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
 extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long);
 #endif /* CONFIG_PCI */
@@ -1090,11 +1107,9 @@
 {
 	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 
-	if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) {
-		if (ata_msg_warn(ap))
-			printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%p\n",
-				status, ap->ioaddr.status_addr);
-	}
+	if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ)))
+		DPRINTK("ATA: abnormal status 0x%X on port 0x%p\n",
+			status, ap->ioaddr.status_addr);
 
 	return status;
 }
diff --git a/include/linux/limits.h b/include/linux/limits.h
index eaf2e09..2d0f941 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -5,8 +5,6 @@
 
 #define NGROUPS_MAX    65536	/* supplemental group IDs are available */
 #define ARG_MAX       131072	/* # bytes of args + environ for exec() */
-#define CHILD_MAX        999    /* no limit :-) */
-#define OPEN_MAX         256	/* # open files a process may have */
 #define LINK_MAX         127	/* # links a file may have */
 #define MAX_CANON        255	/* size of the canonical input queue */
 #define MAX_INPUT        255	/* size of the type-ahead buffer */
diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h
index 9c01bde..08a9296 100644
--- a/include/linux/linux_logo.h
+++ b/include/linux/linux_logo.h
@@ -33,5 +33,13 @@
 };
 
 extern const struct linux_logo *fb_find_logo(int depth);
+#ifdef CONFIG_FB_LOGO_EXTRA
+extern void fb_append_extra_logo(const struct linux_logo *logo,
+				 unsigned int n);
+#else
+static inline void fb_append_extra_logo(const struct linux_logo *logo,
+					unsigned int n)
+{}
+#endif
 
 #endif /* _LINUX_LINUX_LOGO_H */
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index 246de1d..6f1637c 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -27,6 +27,7 @@
 						struct nfs_fh *,
 						struct file **);
 	void			(*fclose)(struct file *);
+	unsigned long		(*get_grace_period)(void);
 };
 
 extern struct nlmsvc_binding *	nlmsvc_ops;
@@ -38,4 +39,12 @@
 extern int	lockd_up(int proto);
 extern void	lockd_down(void);
 
+unsigned long get_nfs_grace_period(void);
+
+#ifdef CONFIG_NFSD_V4
+unsigned long get_nfs4_grace_period(void);
+#else
+static inline unsigned long get_nfs4_grace_period(void) {return 0;}
+#endif
+
 #endif /* LINUX_LOCKD_BIND_H */
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 05707e2..e2d1ce3 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -39,6 +39,7 @@
 struct nlm_host {
 	struct hlist_node	h_hash;		/* doubly linked list */
 	struct sockaddr_in	h_addr;		/* peer address */
+	struct sockaddr_in	h_saddr;	/* our address (optional) */
 	struct rpc_clnt	*	h_rpcclnt;	/* RPC client to talk to peer */
 	char *			h_name;		/* remote hostname */
 	u32			h_version;	/* interface version */
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
new file mode 100644
index 0000000..d793497
--- /dev/null
+++ b/include/linux/lzo.h
@@ -0,0 +1,44 @@
+#ifndef __LZO_H__
+#define __LZO_H__
+/*
+ *  LZO Public Kernel Interface
+ *  A mini subset of the LZO real-time data compression library
+ *
+ *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#define LZO1X_MEM_COMPRESS	(16384 * sizeof(unsigned char *))
+#define LZO1X_1_MEM_COMPRESS	LZO1X_MEM_COMPRESS
+
+#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
+
+/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
+int lzo1x_1_compress(const unsigned char *src, size_t src_len,
+			unsigned char *dst, size_t *dst_len, void *wrkmem);
+
+/* safe decompression with overrun testing */
+int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
+			unsigned char *dst, size_t *dst_len);
+
+/*
+ * Return values (< 0 = Error)
+ */
+#define LZO_E_OK			0
+#define LZO_E_ERROR			(-1)
+#define LZO_E_OUT_OF_MEMORY		(-2)
+#define LZO_E_NOT_COMPRESSIBLE		(-3)
+#define LZO_E_INPUT_OVERRUN		(-4)
+#define LZO_E_OUTPUT_OVERRUN		(-5)
+#define LZO_E_LOOKBEHIND_OVERRUN	(-6)
+#define LZO_E_EOF_NOT_FOUND		(-7)
+#define LZO_E_INPUT_NOT_CONSUMED	(-8)
+#define LZO_E_NOT_YET_IMPLEMENTED	(-9)
+
+#endif
diff --git a/include/linux/magic.h b/include/linux/magic.h
index 9d713c0..36cc20d 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -13,7 +13,6 @@
 #define HPFS_SUPER_MAGIC	0xf995e849
 #define ISOFS_SUPER_MAGIC	0x9660
 #define JFFS2_SUPER_MAGIC	0x72b6
-#define KVMFS_SUPER_MAGIC	0x19700426
 #define ANON_INODE_FS_MAGIC	0x09041934
 
 #define MINIX_SUPER_MAGIC	0x137F		/* original minix fs */
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index daabb3a..e147cf5 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -159,7 +159,7 @@
 
 extern struct mempolicy default_policy;
 extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
-		unsigned long addr);
+		unsigned long addr, gfp_t gfp_flags);
 extern unsigned slab_node(struct mempolicy *policy);
 
 extern enum zone_type policy_zone;
@@ -256,9 +256,9 @@
 #define set_cpuset_being_rebound(x) do {} while (0)
 
 static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
-		unsigned long addr)
+		unsigned long addr, gfp_t gfp_flags)
 {
-	return NODE_DATA(0)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+	return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags);
 }
 
 static inline int do_migrate_pages(struct mm_struct *mm,
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 4fb552d..7d1eaa97 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -54,6 +54,7 @@
 	MLX4_CMD_INIT_PORT	 = 0x9,
 	MLX4_CMD_CLOSE_PORT	 = 0xa,
 	MLX4_CMD_QUERY_HCA	 = 0xb,
+	MLX4_CMD_QUERY_PORT	 = 0x43,
 	MLX4_CMD_SET_PORT	 = 0xc,
 	MLX4_CMD_ACCESS_DDR	 = 0x2e,
 	MLX4_CMD_MAP_ICM	 = 0xffa,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 8c5f8fd..cfb78fb 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -41,6 +41,7 @@
 
 enum {
 	MLX4_FLAG_MSI_X		= 1 << 0,
+	MLX4_FLAG_OLD_PORT_CMDS	= 1 << 1,
 };
 
 enum {
@@ -131,10 +132,10 @@
 struct mlx4_caps {
 	u64			fw_ver;
 	int			num_ports;
-	int			vl_cap;
-	int			mtu_cap;
-	int			gid_table_len;
-	int			pkey_table_len;
+	int			vl_cap[MLX4_MAX_PORTS + 1];
+	int			mtu_cap[MLX4_MAX_PORTS + 1];
+	int			gid_table_len[MLX4_MAX_PORTS + 1];
+	int			pkey_table_len[MLX4_MAX_PORTS + 1];
 	int			local_ca_ack_delay;
 	int			num_uars;
 	int			bf_reg_size;
@@ -171,10 +172,11 @@
 	int			num_pds;
 	int			reserved_pds;
 	int			mtt_entry_sz;
+	u32			max_msg_sz;
 	u32			page_size_cap;
 	u32			flags;
 	u16			stat_rate_support;
-	u8			port_width_cap;
+	u8			port_width_cap[MLX4_MAX_PORTS + 1];
 };
 
 struct mlx4_buf_list {
@@ -321,8 +323,9 @@
 		   u64 db_rec, struct mlx4_srq *srq);
 void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq);
 int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark);
+int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark);
 
-int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port);
+int mlx4_INIT_PORT(struct mlx4_dev *dev, int port);
 int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port);
 
 int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]);
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 9eeb61a..3968b94 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -269,6 +269,10 @@
 	__be64			addr;
 };
 
+enum {
+	MLX4_INLINE_ALIGN	= 64,
+};
+
 struct mlx4_wqe_inline_seg {
 	__be32			byte_count;
 };
@@ -278,6 +282,9 @@
 		   struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar,
 		   int sqd_event, struct mlx4_qp *qp);
 
+int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
+		  struct mlx4_qp_context *context);
+
 static inline struct mlx4_qp *__mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn)
 {
 	return radix_tree_lookup(&dev->qp_table_tree, qpn & (dev->caps.num_qps - 1));
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 4670ebd..a5c4518 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1,9 +1,7 @@
 #ifndef _LINUX_MM_H
 #define _LINUX_MM_H
 
-#include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/capability.h>
 
 #ifdef __KERNEL__
 
@@ -20,6 +18,7 @@
 
 struct mempolicy;
 struct anon_vma;
+struct user_struct;
 
 #ifndef CONFIG_DISCONTIGMEM          /* Don't use mapnrs, do it properly */
 extern unsigned long max_mapnr;
@@ -27,7 +26,6 @@
 
 extern unsigned long num_physpages;
 extern void * high_memory;
-extern unsigned long vmalloc_earlyreserve;
 extern int page_cluster;
 
 #ifdef CONFIG_SYSCTL
@@ -601,8 +599,13 @@
 {
 	struct address_space *mapping = page->mapping;
 
+	VM_BUG_ON(PageSlab(page));
 	if (unlikely(PageSwapCache(page)))
 		mapping = &swapper_space;
+#ifdef CONFIG_SLUB
+	else if (unlikely(PageSlab(page)))
+		mapping = NULL;
+#endif
 	else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
 		mapping = NULL;
 	return mapping;
@@ -717,14 +720,7 @@
 					     unsigned long flags);
 #endif
 
-static inline int can_do_mlock(void)
-{
-	if (capable(CAP_IPC_LOCK))
-		return 1;
-	if (current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur != 0)
-		return 1;
-	return 0;
-}
+extern int can_do_mlock(void);
 extern int user_shm_lock(size_t, struct user_struct *);
 extern void user_shm_unlock(size_t, struct user_struct *);
 
@@ -815,27 +811,31 @@
 			       unsigned long flags, unsigned long new_addr);
 
 /*
- * Prototype to add a shrinker callback for ageable caches.
- * 
- * These functions are passed a count `nr_to_scan' and a gfpmask.  They should
- * scan `nr_to_scan' objects, attempting to free them.
+ * A callback you can register to apply pressure to ageable caches.
  *
- * The callback must return the number of objects which remain in the cache.
+ * 'shrink' is passed a count 'nr_to_scan' and a 'gfpmask'.  It should
+ * look through the least-recently-used 'nr_to_scan' entries and
+ * attempt to free them up.  It should return the number of objects
+ * which remain in the cache.  If it returns -1, it means it cannot do
+ * any scanning at this time (eg. there is a risk of deadlock).
  *
- * The callback will be passed nr_to_scan == 0 when the VM is querying the
- * cache size, so a fastpath for that case is appropriate.
+ * The 'gfpmask' refers to the allocation we are currently trying to
+ * fulfil.
+ *
+ * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
+ * querying the cache size, so a fastpath for that case is appropriate.
  */
-typedef int (*shrinker_t)(int nr_to_scan, gfp_t gfp_mask);
+struct shrinker {
+	int (*shrink)(int nr_to_scan, gfp_t gfp_mask);
+	int seeks;	/* seeks to recreate an obj */
 
-/*
- * Add an aging callback.  The int is the number of 'seeks' it takes
- * to recreate one of the objects that these functions age.
- */
-
-#define DEFAULT_SEEKS 2
-struct shrinker;
-extern struct shrinker *set_shrinker(int, shrinker_t);
-extern void remove_shrinker(struct shrinker *shrinker);
+	/* These are for internal use */
+	struct list_head list;
+	long nr;	/* objs pending delete */
+};
+#define DEFAULT_SEEKS 2 /* A good number if you don't know better. */
+extern void register_shrinker(struct shrinker *);
+extern void unregister_shrinker(struct shrinker *);
 
 /*
  * Some shared mappigns will want the pages marked read-only
@@ -1075,6 +1075,10 @@
 extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
 	unsigned long flag, unsigned long pgoff);
+extern unsigned long mmap_region(struct file *file, unsigned long addr,
+	unsigned long len, unsigned long flags,
+	unsigned int vm_flags, unsigned long pgoff,
+	int accountable);
 
 static inline unsigned long do_mmap(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index d09b134..da8eb8ad9 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -24,6 +24,14 @@
 #endif
 #define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
 
+/*
+ * PAGE_ALLOC_COSTLY_ORDER is the order at which allocations are deemed
+ * costly to service.  That is between allocation orders which should
+ * coelesce naturally under reasonable reclaim pressure and those which
+ * will not.
+ */
+#define PAGE_ALLOC_COSTLY_ORDER 3
+
 struct free_area {
 	struct list_head	free_list;
 	unsigned long		nr_free;
@@ -146,6 +154,7 @@
 	 */
 	ZONE_HIGHMEM,
 #endif
+	ZONE_MOVABLE,
 	MAX_NR_ZONES
 };
 
@@ -167,6 +176,7 @@
 	+ defined(CONFIG_ZONE_DMA32)	\
 	+ 1				\
 	+ defined(CONFIG_HIGHMEM)	\
+	+ 1				\
 )
 #if __ZONE_COUNT < 2
 #define ZONES_SHIFT 0
@@ -499,10 +509,22 @@
 	return (!!zone->present_pages);
 }
 
+extern int movable_zone;
+
+static inline int zone_movable_is_highmem(void)
+{
+#if defined(CONFIG_HIGHMEM) && defined(CONFIG_ARCH_POPULATES_NODE_MAP)
+	return movable_zone == ZONE_HIGHMEM;
+#else
+	return 0;
+#endif
+}
+
 static inline int is_highmem_idx(enum zone_type idx)
 {
 #ifdef CONFIG_HIGHMEM
-	return (idx == ZONE_HIGHMEM);
+	return (idx == ZONE_HIGHMEM ||
+		(idx == ZONE_MOVABLE && zone_movable_is_highmem()));
 #else
 	return 0;
 #endif
@@ -522,7 +544,9 @@
 static inline int is_highmem(struct zone *zone)
 {
 #ifdef CONFIG_HIGHMEM
-	return zone == zone->zone_pgdat->node_zones + ZONE_HIGHMEM;
+	int zone_idx = zone - zone->zone_pgdat->node_zones;
+	return zone_idx == ZONE_HIGHMEM ||
+		(zone_idx == ZONE_MOVABLE && zone_movable_is_highmem());
 #else
 	return 0;
 #endif
@@ -566,6 +590,11 @@
 int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int,
 			struct file *, void __user *, size_t *, loff_t *);
 
+extern int numa_zonelist_order_handler(struct ctl_table *, int,
+			struct file *, void __user *, size_t *, loff_t *);
+extern char numa_zonelist_order[];
+#define NUMA_ZONELIST_ORDER_LEN 16	/* string buffer size */
+
 #include <linux/topology.h>
 /* Returns the number of the current Node. */
 #ifndef numa_node_id
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 1fa4d98..8eed44f 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -14,7 +14,7 @@
 	int event;
 };
 
-extern struct mnt_namespace *copy_mnt_ns(int, struct mnt_namespace *,
+extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
 		struct fs_struct *);
 extern void __put_mnt_ns(struct mnt_namespace *ns);
 
diff --git a/include/linux/module.h b/include/linux/module.h
index e6e0f86..b6a646c 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -6,7 +6,6 @@
  * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
  * Rewritten again by Rusty Russell, 2002
  */
-#include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/stat.h>
 #include <linux/compiler.h>
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 0e09c00..f950921 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -146,7 +146,7 @@
 };
 
 struct msdos_dir_entry {
-	__u8	name[8],ext[3];	/* name and extension */
+	__u8	name[MSDOS_NAME];/* name and extension */
 	__u8	attr;		/* attribute bits */
 	__u8    lcase;		/* Case for base and extension */
 	__u8	ctime_cs;	/* Creation time, centiseconds (0-199) */
diff --git a/include/linux/mtd/super.h b/include/linux/mtd/super.h
new file mode 100644
index 0000000..4016dd6
--- /dev/null
+++ b/include/linux/mtd/super.h
@@ -0,0 +1,30 @@
+/* MTD-based superblock handling
+ *
+ * Copyright © 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __MTD_SUPER_H__
+#define __MTD_SUPER_H__
+
+#ifdef __KERNEL__
+
+#include <linux/mtd/mtd.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+
+extern int get_sb_mtd(struct file_system_type *fs_type, int flags,
+		      const char *dev_name, void *data,
+		      int (*fill_super)(struct super_block *, void *, int),
+		      struct vfsmount *mnt);
+extern void kill_mtd_super(struct super_block *sb);
+
+
+#endif /* __KERNEL__ */
+
+#endif /* __MTD_SUPER_H__ */
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index c6d4ab8..b021b3a 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -13,10 +13,6 @@
 #ifndef __ASM_MV643XX_H
 #define __ASM_MV643XX_H
 
-#ifdef __mips__
-#include <asm/addrspace.h>
-#include <asm/marvell.h>
-#endif
 #include <asm/types.h>
 
 /****************************************/
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 83e39eb..88766e4 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -148,8 +148,6 @@
 #include <linux/ncp_fs_i.h>
 #include <linux/ncp_fs_sb.h>
 
-/* undef because public define in umsdos_fs.h (ncp_fs.h isn't public) */
-#undef PRINTK
 /* define because it is easy to change PRINTK to {*}PRINTK */
 #define PRINTK(format, args...) printk(KERN_DEBUG format , ## args)
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f671cd2..da7a13c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -108,6 +108,14 @@
 #define MAX_HEADER (LL_MAX_HEADER + 48)
 #endif
 
+struct net_device_subqueue
+{
+	/* Give a control state for each queue.  This struct may contain
+	 * per-queue locks in the future.
+	 */
+	unsigned long   state;
+};
+
 /*
  *	Network device statistics. Akin to the 2.0 ether stats but
  *	with byte counters.
@@ -177,19 +185,25 @@
 
 DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat);
 
+struct dev_addr_list
+{
+	struct dev_addr_list	*next;
+	u8			da_addr[MAX_ADDR_LEN];
+	u8			da_addrlen;
+	u8			da_synced;
+	int			da_users;
+	int			da_gusers;
+};
 
 /*
  *	We tag multicasts with these structures.
  */
- 
-struct dev_mc_list
-{	
-	struct dev_mc_list	*next;
-	__u8			dmi_addr[MAX_ADDR_LEN];
-	unsigned char		dmi_addrlen;
-	int			dmi_users;
-	int			dmi_gusers;
-};
+
+#define dev_mc_list	dev_addr_list
+#define dmi_addr	da_addr
+#define dmi_addrlen	da_addrlen
+#define dmi_users	da_users
+#define dmi_gusers	da_gusers
 
 struct hh_cache
 {
@@ -314,9 +328,10 @@
 	/* Net device features */
 	unsigned long		features;
 #define NETIF_F_SG		1	/* Scatter/gather IO. */
-#define NETIF_F_IP_CSUM		2	/* Can checksum only TCP/UDP over IPv4. */
+#define NETIF_F_IP_CSUM		2	/* Can checksum TCP/UDP over IPv4. */
 #define NETIF_F_NO_CSUM		4	/* Does not require checksum. F.e. loopack. */
 #define NETIF_F_HW_CSUM		8	/* Can checksum all the packets. */
+#define NETIF_F_IPV6_CSUM	16	/* Can checksum TCP/UDP over IPV6 */
 #define NETIF_F_HIGHDMA		32	/* Can DMA to high memory. */
 #define NETIF_F_FRAGLIST	64	/* Scatter/gather IO. */
 #define NETIF_F_HW_VLAN_TX	128	/* Transmit VLAN hw acceleration */
@@ -325,6 +340,7 @@
 #define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
 #define NETIF_F_GSO		2048	/* Enable software GSO. */
 #define NETIF_F_LLTX		4096	/* LockLess TX */
+#define NETIF_F_MULTI_QUEUE	16384	/* Has multiple TX/RX queues */
 
 	/* Segmentation offload features */
 #define NETIF_F_GSO_SHIFT	16
@@ -338,8 +354,11 @@
 	/* List of features with software fallbacks. */
 #define NETIF_F_GSO_SOFTWARE	(NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
 
+
 #define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
-#define NETIF_F_ALL_CSUM	(NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
+#define NETIF_F_V4_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
+#define NETIF_F_V6_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
+#define NETIF_F_ALL_CSUM	(NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
 
 	struct net_device	*next_sched;
 
@@ -388,7 +407,10 @@
 	unsigned char		addr_len;	/* hardware address length	*/
 	unsigned short          dev_id;		/* for shared network cards */
 
-	struct dev_mc_list	*mc_list;	/* Multicast mac addresses	*/
+	struct dev_addr_list	*uc_list;	/* Secondary unicast mac addresses */
+	int			uc_count;	/* Number of installed ucasts	*/
+	int			uc_promisc;
+	struct dev_addr_list	*mc_list;	/* Multicast mac addresses	*/
 	int			mc_count;	/* Number of installed mcasts	*/
 	int			promiscuity;
 	int			allmulti;
@@ -493,6 +515,11 @@
 						void *saddr,
 						unsigned len);
 	int			(*rebuild_header)(struct sk_buff *skb);
+#define HAVE_CHANGE_RX_FLAGS
+	void			(*change_rx_flags)(struct net_device *dev,
+						   int flags);
+#define HAVE_SET_RX_MODE
+	void			(*set_rx_mode)(struct net_device *dev);
 #define HAVE_MULTICAST			 
 	void			(*set_multicast_list)(struct net_device *dev);
 #define HAVE_SET_MAC_ADDR  		 
@@ -535,22 +562,29 @@
 
 	/* bridge stuff */
 	struct net_bridge_port	*br_port;
+	/* macvlan */
+	struct macvlan_port	*macvlan_port;
 
 	/* class/net/name entry */
 	struct device		dev;
 	/* space for optional statistics and wireless sysfs groups */
 	struct attribute_group  *sysfs_groups[3];
+
+	/* rtnetlink link ops */
+	const struct rtnl_link_ops *rtnl_link_ops;
+
+	/* The TX queue control structures */
+	unsigned int			egress_subqueue_count;
+	struct net_device_subqueue	egress_subqueue[0];
 };
 #define to_net_dev(d) container_of(d, struct net_device, dev)
 
 #define	NETDEV_ALIGN		32
 #define	NETDEV_ALIGN_CONST	(NETDEV_ALIGN - 1)
 
-static inline void *netdev_priv(struct net_device *dev)
+static inline void *netdev_priv(const struct net_device *dev)
 {
-	return (char *)dev + ((sizeof(struct net_device)
-					+ NETDEV_ALIGN_CONST)
-				& ~NETDEV_ALIGN_CONST);
+	return dev->priv;
 }
 
 #define SET_MODULE_OWNER(dev) do { } while (0)
@@ -702,6 +736,62 @@
 	return test_bit(__LINK_STATE_START, &dev->state);
 }
 
+/*
+ * Routines to manage the subqueues on a device.  We only need start
+ * stop, and a check if it's stopped.  All other device management is
+ * done at the overall netdevice level.
+ * Also test the device if we're multiqueue.
+ */
+static inline void netif_start_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	clear_bit(__LINK_STATE_XOFF, &dev->egress_subqueue[queue_index].state);
+#endif
+}
+
+static inline void netif_stop_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+#ifdef CONFIG_NETPOLL_TRAP
+	if (netpoll_trap())
+		return;
+#endif
+	set_bit(__LINK_STATE_XOFF, &dev->egress_subqueue[queue_index].state);
+#endif
+}
+
+static inline int netif_subqueue_stopped(const struct net_device *dev,
+					 u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	return test_bit(__LINK_STATE_XOFF,
+			&dev->egress_subqueue[queue_index].state);
+#else
+	return 0;
+#endif
+}
+
+static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+#ifdef CONFIG_NETPOLL_TRAP
+	if (netpoll_trap())
+		return;
+#endif
+	if (test_and_clear_bit(__LINK_STATE_XOFF,
+			       &dev->egress_subqueue[queue_index].state))
+		__netif_schedule(dev);
+#endif
+}
+
+static inline int netif_is_multiqueue(const struct net_device *dev)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	return (!!(NETIF_F_MULTI_QUEUE & dev->features));
+#else
+	return 0;
+#endif
+}
 
 /* Use this variant when it is known for sure that it
  * is executing from interrupt context.
@@ -910,6 +1000,17 @@
 	return 0;
 }
 
+/* same as netif_rx_complete, except that local_irq_save(flags)
+ * has already been issued
+ */
+static inline void __netif_rx_complete(struct net_device *dev)
+{
+	BUG_ON(!test_bit(__LINK_STATE_RX_SCHED, &dev->state));
+	list_del(&dev->poll_list);
+	smp_mb__before_clear_bit();
+	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+
 /* Remove interface from poll list: it must be in the poll list
  * on current cpu. This primitive is called by dev->poll(), when
  * it completes the work. The device cannot be out of poll list at this
@@ -920,10 +1021,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	BUG_ON(!test_bit(__LINK_STATE_RX_SCHED, &dev->state));
-	list_del(&dev->poll_list);
-	smp_mb__before_clear_bit();
-	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
+	__netif_rx_complete(dev);
 	local_irq_restore(flags);
 }
 
@@ -940,17 +1038,6 @@
 	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
 }
 
-/* same as netif_rx_complete, except that local_irq_save(flags)
- * has already been issued
- */
-static inline void __netif_rx_complete(struct net_device *dev)
-{
-	BUG_ON(!test_bit(__LINK_STATE_RX_SCHED, &dev->state));
-	list_del(&dev->poll_list);
-	smp_mb__before_clear_bit();
-	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
-}
-
 static inline void netif_tx_lock(struct net_device *dev)
 {
 	spin_lock(&dev->_xmit_lock);
@@ -995,15 +1082,26 @@
 extern void		ether_setup(struct net_device *dev);
 
 /* Support for loadable net-drivers */
-extern struct net_device *alloc_netdev(int sizeof_priv, const char *name,
-				       void (*setup)(struct net_device *));
+extern struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+				       void (*setup)(struct net_device *),
+				       unsigned int queue_count);
+#define alloc_netdev(sizeof_priv, name, setup) \
+	alloc_netdev_mq(sizeof_priv, name, setup, 1)
 extern int		register_netdev(struct net_device *dev);
 extern void		unregister_netdev(struct net_device *dev);
-/* Functions used for multicast support */
-extern void		dev_mc_upload(struct net_device *dev);
+/* Functions used for secondary unicast and multicast support */
+extern void		dev_set_rx_mode(struct net_device *dev);
+extern void		__dev_set_rx_mode(struct net_device *dev);
+extern int		dev_unicast_delete(struct net_device *dev, void *addr, int alen);
+extern int		dev_unicast_add(struct net_device *dev, void *addr, int alen);
 extern int 		dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
 extern int		dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
+extern int		dev_mc_sync(struct net_device *to, struct net_device *from);
+extern void		dev_mc_unsync(struct net_device *to, struct net_device *from);
 extern void		dev_mc_discard(struct net_device *dev);
+extern int 		__dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all);
+extern int		__dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly);
+extern void		__dev_addr_discard(struct dev_addr_list **list);
 extern void		dev_set_promiscuity(struct net_device *dev, int inc);
 extern void		dev_set_allmulti(struct net_device *dev, int inc);
 extern void		netdev_state_change(struct net_device *dev);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 10b5c62..0eed0b7 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -275,7 +275,8 @@
 };
 extern int nf_register_queue_handler(int pf, 
                                      struct nf_queue_handler *qh);
-extern int nf_unregister_queue_handler(int pf);
+extern int nf_unregister_queue_handler(int pf,
+				       struct nf_queue_handler *qh);
 extern void nf_unregister_queue_handlers(struct nf_queue_handler *qh);
 extern void nf_reinject(struct sk_buff *skb,
 			struct nf_info *info,
diff --git a/include/linux/netfilter/nf_conntrack_ftp.h b/include/linux/netfilter/nf_conntrack_ftp.h
index 81453ea..b7c360f 100644
--- a/include/linux/netfilter/nf_conntrack_ftp.h
+++ b/include/linux/netfilter/nf_conntrack_ftp.h
@@ -37,8 +37,7 @@
 				       enum nf_ct_ftp_type type,
 				       unsigned int matchoff,
 				       unsigned int matchlen,
-				       struct nf_conntrack_expect *exp,
-				       u32 *seq);
+				       struct nf_conntrack_expect *exp);
 #endif /* __KERNEL__ */
 
 #endif /* _NF_CONNTRACK_FTP_H */
diff --git a/include/linux/netfilter/nf_conntrack_h323_types.h b/include/linux/netfilter/nf_conntrack_h323_types.h
index 38d74d5..f35b6b4 100644
--- a/include/linux/netfilter/nf_conntrack_h323_types.h
+++ b/include/linux/netfilter/nf_conntrack_h323_types.h
@@ -1,4 +1,4 @@
-/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
+/* Generated by Jing Min Zhao's ASN.1 parser, May 16 2007
  *
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
@@ -12,7 +12,7 @@
 
 typedef struct TransportAddress_ip6Address {	/* SEQUENCE */
 	int options;		/* No use */
-	unsigned ip6;
+	unsigned ip;
 } TransportAddress_ip6Address;
 
 typedef struct TransportAddress {	/* CHOICE */
@@ -364,23 +364,6 @@
 	Alerting_UUIE_fastStart fastStart;
 } Alerting_UUIE;
 
-typedef struct Information_UUIE_fastStart {	/* SEQUENCE OF */
-	int count;
-	OpenLogicalChannel item[30];
-} Information_UUIE_fastStart;
-
-typedef struct Information_UUIE {	/* SEQUENCE */
-	enum {
-		eInformation_UUIE_callIdentifier = (1 << 31),
-		eInformation_UUIE_tokens = (1 << 30),
-		eInformation_UUIE_cryptoTokens = (1 << 29),
-		eInformation_UUIE_fastStart = (1 << 28),
-		eInformation_UUIE_fastConnectRefused = (1 << 27),
-		eInformation_UUIE_circuitInfo = (1 << 26),
-	} options;
-	Information_UUIE_fastStart fastStart;
-} Information_UUIE;
-
 typedef struct FacilityReason {	/* CHOICE */
 	enum {
 		eFacilityReason_routeCallToGatekeeper,
@@ -471,7 +454,6 @@
 		CallProceeding_UUIE callProceeding;
 		Connect_UUIE connect;
 		Alerting_UUIE alerting;
-		Information_UUIE information;
 		Facility_UUIE facility;
 		Progress_UUIE progress;
 	};
@@ -561,6 +543,7 @@
 	} options;
 	OpenLogicalChannelAck_reverseLogicalChannelParameters
 	    reverseLogicalChannelParameters;
+	NetworkAccessParameters separateStack;
 	OpenLogicalChannelAck_forwardMultiplexAckParameters
 	    forwardMultiplexAckParameters;
 } OpenLogicalChannelAck;
diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h
index 9d8144a..c93061f 100644
--- a/include/linux/netfilter/nf_conntrack_pptp.h
+++ b/include/linux/netfilter/nf_conntrack_pptp.h
@@ -4,6 +4,8 @@
 
 #include <linux/netfilter/nf_conntrack_common.h>
 
+extern const char *pptp_msg_name[];
+
 /* state of the control session */
 enum pptp_ctrlsess_state {
 	PPTP_SESSION_NONE,			/* no session present */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 7e733a6..64f425a8 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -141,22 +141,22 @@
 	/* Arguments changed since 2.6.9, as this must now handle
 	   non-linear skb, using skb_header_pointer and
 	   skb_ip_make_writable. */
-	int (*match)(const struct sk_buff *skb,
-		     const struct net_device *in,
-		     const struct net_device *out,
-		     const struct xt_match *match,
-		     const void *matchinfo,
-		     int offset,
-		     unsigned int protoff,
-		     int *hotdrop);
+	bool (*match)(const struct sk_buff *skb,
+		      const struct net_device *in,
+		      const struct net_device *out,
+		      const struct xt_match *match,
+		      const void *matchinfo,
+		      int offset,
+		      unsigned int protoff,
+		      bool *hotdrop);
 
 	/* Called when user tries to insert an entry of this type. */
 	/* Should return true or false. */
-	int (*checkentry)(const char *tablename,
-			  const void *ip,
-			  const struct xt_match *match,
-			  void *matchinfo,
-			  unsigned int hook_mask);
+	bool (*checkentry)(const char *tablename,
+			   const void *ip,
+			   const struct xt_match *match,
+			   void *matchinfo,
+			   unsigned int hook_mask);
 
 	/* Called when entry of this type deleted. */
 	void (*destroy)(const struct xt_match *match, void *matchinfo);
@@ -202,11 +202,11 @@
            hook_mask is a bitmask of hooks from which it can be
            called. */
 	/* Should return true or false. */
-	int (*checkentry)(const char *tablename,
-			  const void *entry,
-			  const struct xt_target *target,
-			  void *targinfo,
-			  unsigned int hook_mask);
+	bool (*checkentry)(const char *tablename,
+			   const void *entry,
+			   const struct xt_target *target,
+			   void *targinfo,
+			   unsigned int hook_mask);
 
 	/* Called when entry of this type deleted. */
 	void (*destroy)(const struct xt_target *target, void *targinfo);
diff --git a/include/linux/netfilter/xt_connlimit.h b/include/linux/netfilter/xt_connlimit.h
new file mode 100644
index 0000000..90ae8b4
--- /dev/null
+++ b/include/linux/netfilter/xt_connlimit.h
@@ -0,0 +1,17 @@
+#ifndef _XT_CONNLIMIT_H
+#define _XT_CONNLIMIT_H
+
+struct xt_connlimit_data;
+
+struct xt_connlimit_info {
+	union {
+		u_int32_t v4_mask;
+		u_int32_t v6_mask[4];
+	};
+	unsigned int limit, inverse;
+
+	/* this needs to be at the end */
+	struct xt_connlimit_data *data __attribute__((aligned(8)));
+};
+
+#endif /* _XT_CONNLIMIT_H */
diff --git a/include/linux/netfilter/xt_u32.h b/include/linux/netfilter/xt_u32.h
new file mode 100644
index 0000000..9947f56
--- /dev/null
+++ b/include/linux/netfilter/xt_u32.h
@@ -0,0 +1,40 @@
+#ifndef _XT_U32_H
+#define _XT_U32_H 1
+
+enum xt_u32_ops {
+	XT_U32_AND,
+	XT_U32_LEFTSH,
+	XT_U32_RIGHTSH,
+	XT_U32_AT,
+};
+
+struct xt_u32_location_element {
+	u_int32_t number;
+	u_int8_t nextop;
+};
+
+struct xt_u32_value_element {
+	u_int32_t min;
+	u_int32_t max;
+};
+
+/*
+ * Any way to allow for an arbitrary number of elements?
+ * For now, I settle with a limit of 10 each.
+ */
+#define XT_U32_MAXSIZE 10
+
+struct xt_u32_test {
+	struct xt_u32_location_element location[XT_U32_MAXSIZE+1];
+	struct xt_u32_value_element value[XT_U32_MAXSIZE+1];
+	u_int8_t nnums;
+	u_int8_t nvalues;
+};
+
+struct xt_u32 {
+	struct xt_u32_test tests[XT_U32_MAXSIZE+1];
+	u_int8_t ntests;
+	u_int8_t invert;
+};
+
+#endif /* _XT_U32_H */
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 2f46dd7..e992cd6 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -264,6 +264,26 @@
 	__ret;							\
 })
 
+/* fn returns 0 to continue iteration */
+#define IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
+({								\
+	unsigned int __i, __n;					\
+	int __ret = 0;						\
+	struct ipt_entry *__entry;				\
+								\
+	for (__i = 0, __n = 0; __i < (size);			\
+	     __i += __entry->next_offset, __n++) { 		\
+		__entry = (void *)(entries) + __i;		\
+		if (__n < n)					\
+			continue;				\
+								\
+		__ret = fn(__entry , ## args);			\
+		if (__ret != 0)					\
+			break;					\
+	}							\
+	__ret;							\
+})
+
 /*
  *	Main firewall chains definitions and global var's definitions.
  */
diff --git a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
index d9bceed..daf50be 100644
--- a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+++ b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
@@ -18,13 +18,13 @@
 struct ipt_clusterip_tgt_info {
 
 	u_int32_t flags;
-	
+
 	/* only relevant for new ones */
 	u_int8_t clustermac[6];
 	u_int16_t num_total_nodes;
 	u_int16_t num_local_nodes;
 	u_int16_t local_nodes[CLUSTERIP_MAX_NODES];
-	enum clusterip_hashmode hash_mode;
+	u_int32_t hash_mode;
 	u_int32_t hash_initval;
 
 	struct clusterip_config *config;
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 4686f83..9a720f0 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -44,8 +44,14 @@
 	char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
 	unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
 
-	/* ARGH, HopByHop uses 0, so can't do 0 = ANY,
-	   instead IP6T_F_NOPROTO must be set */
+	/* Upper protocol number
+	 * - The allowed value is 0 (any) or protocol number of last parsable
+	 *   header, which is 50 (ESP), 59 (No Next Header), 135 (MH), or
+	 *   the non IPv6 extension headers.
+	 * - The protocol numbers of IPv6 extension headers except of ESP and
+	 *   MH do not match any packets.
+	 * - You also need to set IP6T_FLAGS_PROTO to "flags" to check protocol.
+	 */
 	u_int16_t proto;
 	/* TOS to match iff flags & IP6T_F_TOS */
 	u_int8_t tos;
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 7e7f33a..8726491 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -15,6 +15,7 @@
 
 #include <linux/types.h>
 
+#define NFS4_BITMAP_SIZE	2
 #define NFS4_VERIFIER_SIZE	8
 #define NFS4_STATEID_SIZE	16
 #define NFS4_FHSIZE		128
diff --git a/include/linux/nfs4_mount.h b/include/linux/nfs4_mount.h
index 26b4c83..a0dcf66 100644
--- a/include/linux/nfs4_mount.h
+++ b/include/linux/nfs4_mount.h
@@ -65,6 +65,7 @@
 #define NFS4_MOUNT_NOCTO	0x0010	/* 1 */
 #define NFS4_MOUNT_NOAC		0x0020	/* 1 */
 #define NFS4_MOUNT_STRICTLOCK	0x1000	/* 1 */
-#define NFS4_MOUNT_FLAGMASK	0xFFFF
+#define NFS4_MOUNT_UNSHARED	0x8000	/* 1 */
+#define NFS4_MOUNT_FLAGMASK	0x9033
 
 #endif
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 0543439..c098ae1 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -30,7 +30,9 @@
 #ifdef __KERNEL__
 
 #include <linux/in.h>
+#include <linux/kref.h>
 #include <linux/mm.h>
+#include <linux/namei.h>
 #include <linux/pagemap.h>
 #include <linux/rbtree.h>
 #include <linux/rwsem.h>
@@ -69,9 +71,8 @@
 
 struct nfs4_state;
 struct nfs_open_context {
-	atomic_t count;
-	struct vfsmount *vfsmnt;
-	struct dentry *dentry;
+	struct kref kref;
+	struct path path;
 	struct rpc_cred *cred;
 	struct nfs4_state *state;
 	fl_owner_t lockowner;
@@ -155,13 +156,9 @@
 	/*
 	 * This is the list of dirty unwritten pages.
 	 */
-	spinlock_t		req_lock;
-	struct list_head	dirty;
-	struct list_head	commit;
 	struct radix_tree_root	nfs_page_tree;
 
-	unsigned int		ndirty,
-				ncommit,
+	unsigned long		ncommit,
 				npages;
 
 	/* Open contexts for shared mmap writes */
@@ -187,6 +184,7 @@
 #define NFS_INO_INVALID_ACCESS	0x0008		/* cached access cred invalid */
 #define NFS_INO_INVALID_ACL	0x0010		/* cached acls are invalid */
 #define NFS_INO_REVAL_PAGECACHE	0x0020		/* must revalidate pagecache */
+#define NFS_INO_REVAL_FORCED	0x0040		/* force revalidation ignoring a delegation */
 
 /*
  * Bit offsets in flags field
@@ -496,21 +494,18 @@
 
 /*
  * linux/fs/mount_clnt.c
- * (Used only by nfsroot module)
  */
-extern int  nfsroot_mount(struct sockaddr_in *, char *, struct nfs_fh *,
-		int, int);
+extern int  nfs_mount(struct sockaddr *, size_t, char *, char *,
+		      int, int, struct nfs_fh *);
 
 /*
  * inline functions
  */
 
-static inline loff_t
-nfs_size_to_loff_t(__u64 size)
+static inline loff_t nfs_size_to_loff_t(__u64 size)
 {
-	loff_t maxsz = (((loff_t) ULONG_MAX) << PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE - 1;
-	if (size > maxsz)
-		return maxsz;
+	if (size > (__u64) OFFSET_MAX - 1)
+		return OFFSET_MAX - 1;
 	return (loff_t) size;
 }
 
@@ -557,6 +552,7 @@
 #define NFSDBG_ROOT		0x0080
 #define NFSDBG_CALLBACK		0x0100
 #define NFSDBG_CLIENT		0x0200
+#define NFSDBG_MOUNT		0x0400
 #define NFSDBG_ALL		0xFFFF
 
 #ifdef __KERNEL__
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 52b4378..0cac49b 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -16,7 +16,6 @@
 #define NFS_CS_INITING		1		/* busy initialising */
 	int			cl_nfsversion;	/* NFS protocol version */
 	unsigned long		cl_res_state;	/* NFS resources state */
-#define NFS_CS_RPCIOD		0		/* - rpciod started */
 #define NFS_CS_CALLBACK		1		/* - callback started */
 #define NFS_CS_IDMAP		2		/* - idmap started */
 #define NFS_CS_RENEWD		3		/* - renewd started */
@@ -35,7 +34,8 @@
 	nfs4_verifier		cl_confirm;
 	unsigned long		cl_state;
 
-	u32			cl_lockowner_id;
+	struct rb_root		cl_openowner_id;
+	struct rb_root		cl_lockowner_id;
 
 	/*
 	 * The following rwsem ensures exclusive access to the server
@@ -44,9 +44,7 @@
 	struct rw_semaphore	cl_sem;
 
 	struct list_head	cl_delegations;
-	struct list_head	cl_state_owners;
-	struct list_head	cl_unused;
-	int			cl_nunused;
+	struct rb_root		cl_state_owners;
 	spinlock_t		cl_lock;
 
 	unsigned long		cl_lease_time;
diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
index cc8b9c5..a3ade89 100644
--- a/include/linux/nfs_mount.h
+++ b/include/linux/nfs_mount.h
@@ -37,7 +37,7 @@
 	int		acdirmin;		/* 1 */
 	int		acdirmax;		/* 1 */
 	struct sockaddr_in addr;		/* 1 */
-	char		hostname[256];		/* 1 */
+	char		hostname[NFS_MAXNAMLEN + 1];		/* 1 */
 	int		namlen;			/* 2 */
 	unsigned int	bsize;			/* 3 */
 	struct nfs3_fh	root;			/* 4 */
@@ -62,6 +62,7 @@
 #define NFS_MOUNT_STRICTLOCK	0x1000	/* reserved for NFSv4 */
 #define NFS_MOUNT_SECFLAVOUR	0x2000	/* 5 */
 #define NFS_MOUNT_NORDIRPLUS	0x4000	/* 5 */
+#define NFS_MOUNT_UNSHARED	0x8000	/* 5 */
 #define NFS_MOUNT_FLAGMASK	0xFFFF
 
 #endif
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 41afab6..78e6079 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -16,12 +16,13 @@
 #include <linux/sunrpc/auth.h>
 #include <linux/nfs_xdr.h>
 
-#include <asm/atomic.h>
+#include <linux/kref.h>
 
 /*
  * Valid flags for the radix tree
  */
-#define NFS_PAGE_TAG_WRITEBACK	0
+#define NFS_PAGE_TAG_LOCKED	0
+#define NFS_PAGE_TAG_COMMIT	1
 
 /*
  * Valid flags for a dirty buffer
@@ -33,8 +34,7 @@
 
 struct nfs_inode;
 struct nfs_page {
-	struct list_head	wb_list,	/* Defines state of page: */
-				*wb_list_head;	/*      read/write/commit */
+	struct list_head	wb_list;	/* Defines state of page: */
 	struct page		*wb_page;	/* page to read in/write out */
 	struct nfs_open_context	*wb_context;	/* File state context info */
 	atomic_t		wb_complete;	/* i/os we're waiting for */
@@ -42,7 +42,7 @@
 	unsigned int		wb_offset,	/* Offset & ~PAGE_CACHE_MASK */
 				wb_pgbase,	/* Start of page data */
 				wb_bytes;	/* Length of request */
-	atomic_t		wb_count;	/* reference count */
+	struct kref		wb_kref;	/* reference count */
 	unsigned long		wb_flags;
 	struct nfs_writeverf	wb_verf;	/* Commit cookie */
 };
@@ -71,8 +71,8 @@
 extern	void nfs_release_request(struct nfs_page *req);
 
 
-extern	int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
-			  pgoff_t idx_start, unsigned int npages);
+extern	int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst,
+			  pgoff_t idx_start, unsigned int npages, int tag);
 extern	void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
 			     struct inode *inode,
 			     int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
@@ -81,14 +81,14 @@
 extern	int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
 				   struct nfs_page *);
 extern	void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
+extern	void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t);
 extern  int nfs_wait_on_request(struct nfs_page *);
 extern	void nfs_unlock_request(struct nfs_page *req);
-extern  int nfs_set_page_writeback_locked(struct nfs_page *req);
-extern  void nfs_clear_page_writeback(struct nfs_page *req);
+extern  void nfs_clear_page_tag_locked(struct nfs_page *req);
 
 
 /*
- * Lock the page of an asynchronous request without incrementing the wb_count
+ * Lock the page of an asynchronous request without getting a new reference
  */
 static inline int
 nfs_lock_request_dontget(struct nfs_page *req)
@@ -97,14 +97,14 @@
 }
 
 /*
- * Lock the page of an asynchronous request
+ * Lock the page of an asynchronous request and take a reference
  */
 static inline int
 nfs_lock_request(struct nfs_page *req)
 {
 	if (test_and_set_bit(PG_BUSY, &req->wb_flags))
 		return 0;
-	atomic_inc(&req->wb_count);
+	kref_get(&req->wb_kref);
 	return 1;
 }
 
@@ -117,7 +117,6 @@
 nfs_list_add_request(struct nfs_page *req, struct list_head *head)
 {
 	list_add_tail(&req->wb_list, head);
-	req->wb_list_head = head;
 }
 
 
@@ -131,7 +130,6 @@
 	if (list_empty(&req->wb_list))
 		return;
 	list_del_init(&req->wb_list);
-	req->wb_list_head = NULL;
 }
 
 static inline struct nfs_page *
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 10c26ed..38d7768 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -119,7 +119,7 @@
 	struct nfs_seqid *	seqid;
 	int			open_flags;
 	__u64                   clientid;
-	__u32                   id;
+	__u64                   id;
 	union {
 		struct iattr *  attrs;    /* UNCHECKED, GUARDED */
 		nfs4_verifier   verifier; /* EXCLUSIVE */
@@ -144,6 +144,7 @@
 	nfs4_stateid		delegation;
 	__u32			do_recall;
 	__u64			maxsize;
+	__u32			attrset[NFS4_BITMAP_SIZE];
 };
 
 /*
@@ -180,7 +181,7 @@
  *   */
 struct nfs_lowner {
 	__u64			clientid;
-	u32			id;
+	__u64			id;
 };
 
 struct nfs_lock_args {
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 9f62d61..78feb7b 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -42,6 +42,9 @@
 #define	NFSEXP_NOACL		0x8000	/* reserved for possible ACL related use */
 #define NFSEXP_ALLFLAGS		0xFE3F
 
+/* The flags that may vary depending on security flavor: */
+#define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
+					| NFSEXP_ALLSQUASH)
 
 #ifdef __KERNEL__
 
@@ -64,6 +67,19 @@
 	int migrated;
 };
 
+/*
+ * We keep an array of pseudoflavors with the export, in order from most
+ * to least preferred.  For the forseeable future, we don't expect more
+ * than the eight pseudoflavors null, unix, krb5, krb5i, krb5p, skpm3,
+ * spkm3i, and spkm3p (and using all 8 at once should be rare).
+ */
+#define MAX_SECINFO_LIST	8
+
+struct exp_flavor_info {
+	u32	pseudoflavor;
+	u32	flags;
+};
+
 struct svc_export {
 	struct cache_head	h;
 	struct auth_domain *	ex_client;
@@ -76,6 +92,8 @@
 	int			ex_fsid;
 	unsigned char *		ex_uuid; /* 16 byte fsid */
 	struct nfsd4_fs_locations ex_fslocs;
+	int			ex_nflavors;
+	struct exp_flavor_info	ex_flavors[MAX_SECINFO_LIST];
 };
 
 /* an "export key" (expkey) maps a filehandlefragement to an
@@ -95,10 +113,22 @@
 
 #define EX_SECURE(exp)		(!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
 #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
-#define EX_RDONLY(exp)		((exp)->ex_flags & NFSEXP_READONLY)
 #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
 #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
 
+static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
+{
+	struct exp_flavor_info *f;
+	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+	for (f = exp->ex_flavors; f < end; f++) {
+		if (f->pseudoflavor == rqstp->rq_flavor)
+			return f->flags & NFSEXP_READONLY;
+	}
+	return exp->ex_flags & NFSEXP_READONLY;
+}
+
+__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
 
 /*
  * Function declarations
@@ -112,13 +142,19 @@
 					struct vfsmount *mnt,
 					struct dentry *dentry,
 					struct cache_req *reqp);
+struct svc_export *	rqst_exp_get_by_name(struct svc_rqst *,
+					     struct vfsmount *,
+					     struct dentry *);
 struct svc_export *	exp_parent(struct auth_domain *clp,
 				   struct vfsmount *mnt,
 				   struct dentry *dentry,
 				   struct cache_req *reqp);
+struct svc_export *	rqst_exp_parent(struct svc_rqst *,
+					struct vfsmount *mnt,
+					struct dentry *dentry);
 int			exp_rootfh(struct auth_domain *, 
 					char *path, struct knfsd_fh *, int maxsize);
-__be32			exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
+__be32			exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
 __be32			nfserrno(int errno);
 
 extern struct cache_detail svc_export_cache;
@@ -135,6 +171,7 @@
 extern struct svc_export *
 exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
 	 struct cache_req *reqp);
+struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/nfsd/interface.h b/include/linux/nfsd/interface.h
deleted file mode 100644
index af09797..0000000
--- a/include/linux/nfsd/interface.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * include/linux/nfsd/interface.h
- *
- * defines interface between nfsd and other bits of
- * the kernel.  Particularly filesystems (eventually).
- *
- * Copyright (C) 2000 Neil Brown <neilb@cse.unsw.edu.au>
- */
-
-#ifndef LINUX_NFSD_INTERFACE_H
-#define LINUX_NFSD_INTERFACE_H
-
-#endif /* LINUX_NFSD_INTERFACE_H */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 72feac5..e452256 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -22,7 +22,6 @@
 #include <linux/nfsd/export.h>
 #include <linux/nfsd/auth.h>
 #include <linux/nfsd/stats.h>
-#include <linux/nfsd/interface.h>
 /*
  * nfsd version
  */
@@ -72,6 +71,9 @@
 		                struct svc_export **expp);
 __be32		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
 				const char *, int, struct svc_fh *);
+__be32		 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
+				const char *, int,
+				struct svc_export **, struct dentry **);
 __be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
 				struct iattr *, int, time_t);
 #ifdef CONFIG_NFSD_V4
@@ -120,7 +122,8 @@
 				struct kstatfs *);
 
 int		nfsd_notify_change(struct inode *, struct iattr *);
-__be32		nfsd_permission(struct svc_export *, struct dentry *, int);
+__be32		nfsd_permission(struct svc_rqst *, struct svc_export *,
+				struct dentry *, int);
 int		nfsd_sync_dir(struct dentry *dp);
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
@@ -149,6 +152,7 @@
  * NFSv4 State
  */
 #ifdef CONFIG_NFSD_V4
+extern unsigned int max_delegations;
 void nfs4_state_init(void);
 int nfs4_state_start(void);
 void nfs4_state_shutdown(void);
@@ -236,6 +240,7 @@
 #define	nfserr_badname		__constant_htonl(NFSERR_BADNAME)
 #define	nfserr_cb_path_down	__constant_htonl(NFSERR_CB_PATH_DOWN)
 #define	nfserr_locked		__constant_htonl(NFSERR_LOCKED)
+#define	nfserr_wrongsec		__constant_htonl(NFSERR_WRONGSEC)
 #define	nfserr_replay_me	__constant_htonl(NFSERR_REPLAY_ME)
 
 /* error codes for internal use */
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index ab5c236..db348f7 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -67,7 +67,7 @@
 	int			cbr_trunc;
 	stateid_t		cbr_stateid;
 	u32			cbr_fhlen;
-	u32			cbr_fhval[NFS4_FHSIZE];
+	char			cbr_fhval[NFS4_FHSIZE];
 	struct nfs4_delegation	*cbr_dp;
 };
 
@@ -224,6 +224,7 @@
 	struct inode		*fi_inode;
 	u32                     fi_id;      /* used with stateowner->so_id 
 					     * for stateid_hashtbl hash */
+	bool			fi_had_conflict;
 };
 
 /*
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 09799bc..1b65326 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -293,6 +293,12 @@
 	struct nfsd4_change_info  rn_tinfo; /* response */
 };
 
+struct nfsd4_secinfo {
+	u32 si_namelen;					/* request */
+	char *si_name;					/* request */
+	struct svc_export *si_exp;			/* response */
+};
+
 struct nfsd4_setattr {
 	stateid_t	sa_stateid;         /* request */
 	u32		sa_bmval[2];        /* request */
@@ -365,6 +371,7 @@
 		struct nfsd4_remove		remove;
 		struct nfsd4_rename		rename;
 		clientid_t			renew;
+		struct nfsd4_secinfo		secinfo;
 		struct nfsd4_setattr		setattr;
 		struct nfsd4_setclientid	setclientid;
 		struct nfsd4_setclientid_confirm setclientid_confirm;
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 9431101..576f2bb 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -196,6 +196,8 @@
 #define CPU_DEAD		0x0007 /* CPU (unsigned)v dead */
 #define CPU_LOCK_ACQUIRE	0x0008 /* Acquire all hotcpu locks */
 #define CPU_LOCK_RELEASE	0x0009 /* Release all hotcpu locks */
+#define CPU_DYING		0x000A /* CPU (unsigned)v not running any task,
+				        * not handling interrupts, soon dead */
 
 /* Used for CPU hotplug events occuring while tasks are frozen due to a suspend
  * operation in progress
@@ -208,6 +210,7 @@
 #define CPU_DOWN_PREPARE_FROZEN	(CPU_DOWN_PREPARE | CPU_TASKS_FROZEN)
 #define CPU_DOWN_FAILED_FROZEN	(CPU_DOWN_FAILED | CPU_TASKS_FROZEN)
 #define CPU_DEAD_FROZEN		(CPU_DEAD | CPU_TASKS_FROZEN)
+#define CPU_DYING_FROZEN	(CPU_DYING | CPU_TASKS_FROZEN)
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_NOTIFIER_H */
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 189e0dc..ce06188 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -28,10 +28,11 @@
 	struct ipc_namespace *ipc_ns;
 	struct mnt_namespace *mnt_ns;
 	struct pid_namespace *pid_ns;
+	struct user_namespace *user_ns;
 };
 extern struct nsproxy init_nsproxy;
 
-int copy_namespaces(int flags, struct task_struct *tsk);
+int copy_namespaces(unsigned long flags, struct task_struct *tsk);
 void get_task_namespaces(struct task_struct *tsk);
 void free_nsproxy(struct nsproxy *ns);
 int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h
index 2d5fd64..5799e8d 100644
--- a/include/linux/pata_platform.h
+++ b/include/linux/pata_platform.h
@@ -8,6 +8,11 @@
 	 * spacing used by ata_std_ports().
 	 */
 	unsigned int ioport_shift;
+	/* 
+	 * Indicate platform specific irq types and initial
+	 * IRQ flags when call request_irq()
+	 */
+	unsigned int irq_flags;
 };
 
 #endif /* __LINUX_PATA_PLATFORM_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index fbf3766..5e84f2e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -111,7 +111,8 @@
 
 typedef unsigned short __bitwise pci_bus_flags_t;
 enum pci_bus_flags {
-	PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
+	PCI_BUS_FLAGS_NO_MSI   = (__force pci_bus_flags_t) 1,
+	PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
 };
 
 struct pci_cap_saved_state {
@@ -138,6 +139,7 @@
 	unsigned short	subsystem_vendor;
 	unsigned short	subsystem_device;
 	unsigned int	class;		/* 3 bytes: (base,sub,prog-if) */
+	u8		revision;	/* PCI revision, low byte of class word */
 	u8		hdr_type;	/* PCI header type (`multi' flag masked out) */
 	u8		rom_base_reg;	/* which config register controls the ROM */
 	u8		pin;  		/* which interrupt pin this device uses */
@@ -313,7 +315,7 @@
 
 /* ---------------------------------------------------------------- */
 /** PCI Error Recovery System (PCI-ERS).  If a PCI device driver provides
- *  a set fof callbacks in struct pci_error_handlers, then that device driver
+ *  a set of callbacks in struct pci_error_handlers, then that device driver
  *  will be notified of PCI bus errors, and will be driven to recovery
  *  when an error occurs.
  */
@@ -370,7 +372,6 @@
 	int  (*suspend_late) (struct pci_dev *dev, pm_message_t state);
 	int  (*resume_early) (struct pci_dev *dev);
 	int  (*resume) (struct pci_dev *dev);	                /* Device woken up */
-	int  (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable);   /* Enable wake event */
 	void (*shutdown) (struct pci_dev *dev);
 
 	struct pci_error_handlers *err_handler;
@@ -431,6 +432,8 @@
  * code, or pci core code. */
 extern struct list_head pci_root_buses;	/* list of all known PCI buses */
 extern struct list_head pci_devices;	/* list of all devices */
+/* Some device drivers need know if pci is initiated */
+extern int no_pci_devices(void);
 
 void pcibios_fixup_bus(struct pci_bus *);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
@@ -475,7 +478,7 @@
 /* Generic PCI functions exported to card drivers */
 
 struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
-struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
+struct pci_dev __deprecated *pci_find_slot (unsigned int bus, unsigned int devfn);
 int pci_find_capability (struct pci_dev *dev, int cap);
 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
 int pci_find_ext_capability (struct pci_dev *dev, int cap);
@@ -544,11 +547,16 @@
 int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
 #define HAVE_PCI_SET_MWI
 int __must_check pci_set_mwi(struct pci_dev *dev);
+int pci_try_set_mwi(struct pci_dev *dev);
 void pci_clear_mwi(struct pci_dev *dev);
 void pci_intx(struct pci_dev *dev, int enable);
 void pci_msi_off(struct pci_dev *dev);
 int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
+int pcix_get_max_mmrbc(struct pci_dev *dev);
+int pcix_get_mmrbc(struct pci_dev *dev);
+int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
+int pcie_set_readrq(struct pci_dev *dev, int rq);
 void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
@@ -560,6 +568,7 @@
 void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
 void pci_remove_rom(struct pci_dev *pdev);
+size_t pci_get_rom_size(void __iomem *rom, size_t size);
 
 /* Power management related routines */
 int pci_save_state(struct pci_dev *dev);
@@ -717,6 +726,7 @@
 { return NULL; }
 
 #define pci_dev_present(ids)	(0)
+#define no_pci_devices()	(1)
 #define pci_find_present(ids)	(NULL)
 #define pci_dev_put(dev)	do { } while (0)
 
@@ -748,6 +758,17 @@
 static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
 static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) { }
 
+static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
+{ return NULL; }
+
+static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
+						unsigned int devfn)
+{ return NULL; }
+
+static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
+						unsigned int devfn)
+{ return NULL; }
+
 #endif /* CONFIG_PCI */
 
 /* Include architecture-dependent settings and functions */
@@ -865,5 +886,7 @@
 extern unsigned long pci_cardbus_io_size;
 extern unsigned long pci_cardbus_mem_size;
 
+extern int pcibios_add_platform_entries(struct pci_dev *dev);
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 62b3e00..2c7add1 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -133,6 +133,9 @@
 
 /* Vendors and devices.  Sort key: vendor first, device next. */
 
+#define PCI_VENDOR_ID_TTTECH		0x0357
+#define PCI_DEVICE_ID_TTTECH_MC322	0x000a
+
 #define PCI_VENDOR_ID_DYNALINK		0x0675
 #define PCI_DEVICE_ID_DYNALINK_IS64PH	0x1702
 
@@ -371,6 +374,8 @@
 #define PCI_DEVICE_ID_ATI_IXP600_SMBUS	0x4385
 #define PCI_DEVICE_ID_ATI_IXP600_IDE	0x438c
 #define PCI_DEVICE_ID_ATI_IXP700_SATA	0x4390
+#define PCI_DEVICE_ID_ATI_IXP700_SMBUS	0x4395
+#define PCI_DEVICE_ID_ATI_IXP700_IDE	0x439c
 
 #define PCI_VENDOR_ID_VLSI		0x1004
 #define PCI_DEVICE_ID_VLSI_82C592	0x0005
@@ -474,6 +479,9 @@
 #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
 #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL	0x252
 
+#define PCI_VENDOR_ID_UNISYS		0x1018
+#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C
+
 #define PCI_VENDOR_ID_COMPEX2		0x101a /* pci.ids says "AT&T GIS (NCR)" */
 #define PCI_DEVICE_ID_COMPEX2_100VG	0x0005
 
@@ -660,6 +668,7 @@
 #define PCI_DEVICE_ID_SI_965		0x0965
 #define PCI_DEVICE_ID_SI_966		0x0966
 #define PCI_DEVICE_ID_SI_968		0x0968
+#define PCI_DEVICE_ID_SI_1180		0x1180
 #define PCI_DEVICE_ID_SI_5511		0x5511
 #define PCI_DEVICE_ID_SI_5513		0x5513
 #define PCI_DEVICE_ID_SI_5517		0x5517
@@ -730,7 +739,6 @@
 #define PCI_DEVICE_ID_ELSA_MICROLINK	0x1000
 #define PCI_DEVICE_ID_ELSA_QS3000	0x3000
 
-
 #define PCI_VENDOR_ID_BUSLOGIC		      0x104B
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER    0x1040
@@ -776,7 +784,6 @@
 
 #define PCI_VENDOR_ID_SONY		0x104d
 
-
 /* Winbond have two vendor IDs! See 0x10ad as well */
 #define PCI_VENDOR_ID_WINBOND2		0x1050
 #define PCI_DEVICE_ID_WINBOND2_89C940F	0x5a5a
@@ -814,7 +821,6 @@
 #define PCI_DEVICE_ID_PROMISE_20276	0x5275
 #define PCI_DEVICE_ID_PROMISE_20277	0x7275
 
-
 #define PCI_VENDOR_ID_UMC		0x1060
 #define PCI_DEVICE_ID_UMC_UM8673F	0x0101
 #define PCI_DEVICE_ID_UMC_UM8886BF	0x673a
@@ -830,7 +836,6 @@
 #define PCI_DEVICE_ID_MYLEX_DAC960_BA	0xBA56
 #define PCI_DEVICE_ID_MYLEX_DAC960_GEM	0xB166
 
-
 #define PCI_VENDOR_ID_APPLE		0x106b
 #define PCI_DEVICE_ID_APPLE_BANDIT	0x0001
 #define PCI_DEVICE_ID_APPLE_HYDRA	0x000e
@@ -866,7 +871,6 @@
 #define PCI_DEVICE_ID_YAMAHA_744	0x0010
 #define PCI_DEVICE_ID_YAMAHA_754	0x0012
 
-
 #define PCI_VENDOR_ID_QLOGIC		0x1077
 #define PCI_DEVICE_ID_QLOGIC_ISP10160	0x1016
 #define PCI_DEVICE_ID_QLOGIC_ISP1020	0x1020
@@ -897,12 +901,9 @@
 #define PCI_DEVICE_ID_CYRIX_5530_AUDIO	0x0103
 #define PCI_DEVICE_ID_CYRIX_5530_VIDEO	0x0104
 
-
-
 #define PCI_VENDOR_ID_CONTAQ		0x1080
 #define PCI_DEVICE_ID_CONTAQ_82C693	0xc693
 
-
 #define PCI_VENDOR_ID_OLICOM		0x108d
 #define PCI_DEVICE_ID_OLICOM_OC2325	0x0012
 #define PCI_DEVICE_ID_OLICOM_OC2183	0x0013
@@ -934,23 +935,19 @@
 #define PCI_DEVICE_ID_SII_3112		0x3112
 #define PCI_DEVICE_ID_SII_1210SA	0x0240
 
-
 #define PCI_VENDOR_ID_BROOKTREE		0x109e
 #define PCI_DEVICE_ID_BROOKTREE_878	0x0878
 #define PCI_DEVICE_ID_BROOKTREE_879	0x0879
 
-
 #define PCI_VENDOR_ID_SGI		0x10a9
 #define PCI_DEVICE_ID_SGI_IOC3		0x0003
+#define PCI_DEVICE_ID_SGI_LITHIUM	0x1002
 #define PCI_DEVICE_ID_SGI_IOC4		0x100a
-#define PCI_VENDOR_ID_SGI_LITHIUM	0x1002
-
 
 #define PCI_VENDOR_ID_WINBOND		0x10ad
 #define PCI_DEVICE_ID_WINBOND_82C105	0x0105
 #define PCI_DEVICE_ID_WINBOND_83C553	0x0565
 
-
 #define PCI_VENDOR_ID_PLX		0x10b5
 #define PCI_DEVICE_ID_PLX_R685		0x1030
 #define PCI_DEVICE_ID_PLX_ROMULUS	0x106a
@@ -984,7 +981,6 @@
 #define PCI_DEVICE_ID_3COM_3CR990SVR97	0x9909
 #define PCI_DEVICE_ID_3COM_3CR990SVR	0x990a
 
-
 #define PCI_VENDOR_ID_AL		0x10b9
 #define PCI_DEVICE_ID_AL_M1533		0x1533
 #define PCI_DEVICE_ID_AL_M1535 		0x1535
@@ -1007,18 +1003,14 @@
 #define PCI_DEVICE_ID_AL_M5451		0x5451
 #define PCI_DEVICE_ID_AL_M7101		0x7101
 
-
-
 #define PCI_VENDOR_ID_NEOMAGIC		0x10c8
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
 #define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
 
-
 #define PCI_VENDOR_ID_TCONRAD		0x10da
 #define PCI_DEVICE_ID_TCONRAD_TOKENRING	0x0508
 
-
 #define PCI_VENDOR_ID_NVIDIA			0x10de
 #define PCI_DEVICE_ID_NVIDIA_TNT		0x0020
 #define PCI_DEVICE_ID_NVIDIA_TNT2		0x0028
@@ -1232,14 +1224,13 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_26              0x054E
 #define PCI_DEVICE_ID_NVIDIA_NVENET_27              0x054F
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE       0x0560
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE       0x056C
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_TT128		0x9128
 #define PCI_DEVICE_ID_IMS_TT3D		0x9135
 
-
-
-
 #define PCI_VENDOR_ID_INTERG		0x10ea
 #define PCI_DEVICE_ID_INTERG_1682	0x1682
 #define PCI_DEVICE_ID_INTERG_2000	0x2000
@@ -1258,7 +1249,6 @@
 #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
 #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
 
-
 #define PCI_VENDOR_ID_INIT		0x1101
 
 #define PCI_VENDOR_ID_CREATIVE		0x1102 /* duplicate: ECTIVA */
@@ -1291,6 +1281,7 @@
 #define PCI_DEVICE_ID_VIA_P4M890	0x0327
 #define PCI_DEVICE_ID_VIA_VT3324	0x0324
 #define PCI_DEVICE_ID_VIA_VT3336	0x0336
+#define PCI_DEVICE_ID_VIA_VT3351	0x0351
 #define PCI_DEVICE_ID_VIA_8371_0	0x0391
 #define PCI_DEVICE_ID_VIA_8501_0	0x0501
 #define PCI_DEVICE_ID_VIA_82C561	0x0561
@@ -1352,7 +1343,6 @@
 #define PCI_VENDOR_ID_SIEMENS           0x110A
 #define PCI_DEVICE_ID_SIEMENS_DSCC4     0x2102
 
-
 #define PCI_VENDOR_ID_VORTEX		0x1119
 #define PCI_DEVICE_ID_VORTEX_GDT60x0	0x0000
 #define PCI_DEVICE_ID_VORTEX_GDT6000B	0x0001
@@ -1378,8 +1368,8 @@
 #define PCI_VENDOR_ID_EF		0x111a
 #define PCI_DEVICE_ID_EF_ATM_FPGA	0x0000
 #define PCI_DEVICE_ID_EF_ATM_ASIC	0x0002
-#define PCI_VENDOR_ID_EF_ATM_LANAI2	0x0003
-#define PCI_VENDOR_ID_EF_ATM_LANAIHB	0x0005
+#define PCI_DEVICE_ID_EF_ATM_LANAI2	0x0003
+#define PCI_DEVICE_ID_EF_ATM_LANAIHB	0x0005
 
 #define PCI_VENDOR_ID_IDT		0x111d
 #define PCI_DEVICE_ID_IDT_IDT77201	0x0001
@@ -1387,7 +1377,6 @@
 #define PCI_VENDOR_ID_FORE		0x1127
 #define PCI_DEVICE_ID_FORE_PCA200E	0x0300
 
-
 #define PCI_VENDOR_ID_PHILIPS		0x1131
 #define PCI_DEVICE_ID_PHILIPS_SAA7146	0x7146
 #define PCI_DEVICE_ID_PHILIPS_SAA9730	0x9730
@@ -1406,7 +1395,6 @@
 #define PCI_DEVICE_ID_ZIATECH_5550_HC	0x5550
  
 
-
 #define PCI_VENDOR_ID_SYSKONNECT	0x1148
 #define PCI_DEVICE_ID_SYSKONNECT_TR	0x4200
 #define PCI_DEVICE_ID_SYSKONNECT_GE	0x4300
@@ -1414,7 +1402,6 @@
 #define PCI_DEVICE_ID_SYSKONNECT_9DXX	0x4400
 #define PCI_DEVICE_ID_SYSKONNECT_9MXX	0x4500
 
-
 #define PCI_VENDOR_ID_DIGI		0x114f
 #define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E	0x0070
 #define PCI_DEVICE_ID_DIGI_DF_M_E	0x0071
@@ -1425,17 +1412,16 @@
 #define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
 #define PCI_DEVICE_ID_NEO_2RJ45PRI      0x00CB
 
-
 #define PCI_VENDOR_ID_XIRCOM		0x115d
 #define PCI_DEVICE_ID_XIRCOM_RBM56G	0x0101
 #define PCI_DEVICE_ID_XIRCOM_X3201_MDM	0x0103
 
-
 #define PCI_VENDOR_ID_SERVERWORKS	  0x1166
 #define PCI_DEVICE_ID_SERVERWORKS_HE	  0x0008
 #define PCI_DEVICE_ID_SERVERWORKS_LE	  0x0009
 #define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
 #define PCI_DEVICE_ID_SERVERWORKS_EPB	  0x0103
+#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX	0x0104
 #define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE	0x0132
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4	  0x0200
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5	  0x0201
@@ -1498,7 +1484,6 @@
 #define PCI_DEVICE_ID_ZEITNET_1221	0x0001
 #define PCI_DEVICE_ID_ZEITNET_1225	0x0002
 
-
 #define PCI_VENDOR_ID_FUJITSU_ME	0x119e
 #define PCI_DEVICE_ID_FUJITSU_FS155	0x0001
 #define PCI_DEVICE_ID_FUJITSU_FS50	0x0003
@@ -1516,28 +1501,23 @@
 #define PCI_DEVICE_ID_V3_V960		0x0001
 #define PCI_DEVICE_ID_V3_V351		0x0002
 
-
 #define PCI_VENDOR_ID_ATT		0x11c1
 #define PCI_DEVICE_ID_ATT_VENUS_MODEM	0x480
 
-
 #define PCI_VENDOR_ID_SPECIALIX		0x11cb
 #define PCI_DEVICE_ID_SPECIALIX_IO8	0x2000
 #define PCI_DEVICE_ID_SPECIALIX_RIO	0x8000
 #define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004
 
-
 #define PCI_VENDOR_ID_ANALOG_DEVICES	0x11d4
 #define PCI_DEVICE_ID_AD1889JS		0x1889
 
-
 #define PCI_DEVICE_ID_SEGA_BBA		0x1234
 
 #define PCI_VENDOR_ID_ZORAN		0x11de
 #define PCI_DEVICE_ID_ZORAN_36057	0x6057
 #define PCI_DEVICE_ID_ZORAN_36120	0x6120
 
-
 #define PCI_VENDOR_ID_COMPEX		0x11f6
 #define PCI_DEVICE_ID_COMPEX_ENET100VG4	0x0112
 
@@ -1596,8 +1576,6 @@
 #define PCI_DEVICE_ID_3DFX_VOODOO3	0x0005
 #define PCI_DEVICE_ID_3DFX_VOODOO5	0x0009
 
-
-
 #define PCI_VENDOR_ID_AVM		0x1244
 #define PCI_DEVICE_ID_AVM_B1		0x0700
 #define PCI_DEVICE_ID_AVM_C4		0x0800
@@ -1606,7 +1584,6 @@
 #define PCI_DEVICE_ID_AVM_C2		0x1100
 #define PCI_DEVICE_ID_AVM_T1		0x1200
 
-
 #define PCI_VENDOR_ID_STALLION		0x124d
 
 /* Allied Telesyn */
@@ -1629,7 +1606,6 @@
 #define PCI_VENDOR_ID_SATSAGEM		0x1267
 #define PCI_DEVICE_ID_SATSAGEM_NICCY	0x1016
 
-
 #define PCI_VENDOR_ID_ENSONIQ		0x1274
 #define PCI_DEVICE_ID_ENSONIQ_CT5880	0x5880
 #define PCI_DEVICE_ID_ENSONIQ_ES1370	0x5000
@@ -1652,7 +1628,6 @@
 
 #define PCI_VENDOR_ID_ALTEON		0x12ae
 
-
 #define PCI_SUBVENDOR_ID_CONNECT_TECH			0x12c4
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232		0x0001
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232		0x0002
@@ -1683,7 +1658,6 @@
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485	0x0331
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485	0x0332
 
-
 #define PCI_VENDOR_ID_NVIDIA_SGS	0x12d2
 #define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
 
@@ -1793,7 +1767,6 @@
 #define PCI_DEVICE_ID_LMC_SSI		0x0005
 #define PCI_DEVICE_ID_LMC_T1		0x0006
 
-
 #define PCI_VENDOR_ID_NETGEAR		0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
 
@@ -1896,6 +1869,8 @@
 #define PCI_DEVICE_ID_OXSEMI_16PCI952	0x9521
 #define PCI_DEVICE_ID_OXSEMI_16PCI952PP	0x9523
 
+#define PCI_VENDOR_ID_CHELSIO		0x1425
+
 #define PCI_VENDOR_ID_SAMSUNG		0x144d
 
 #define PCI_VENDOR_ID_MYRICOM		0x14c1
@@ -1994,6 +1969,7 @@
 
 #define PCI_VENDOR_ID_ENE		0x1524
 #define PCI_DEVICE_ID_ENE_CB712_SD	0x0550
+#define PCI_DEVICE_ID_ENE_CB712_SD_2	0x0551
 #define PCI_DEVICE_ID_ENE_1211		0x1211
 #define PCI_DEVICE_ID_ENE_1225		0x1225
 #define PCI_DEVICE_ID_ENE_1410		0x1410
@@ -2003,13 +1979,10 @@
 #define PCI_DEVICE_ID_ENE_720		0x1421
 #define PCI_DEVICE_ID_ENE_722		0x1422
 
-#define PCI_VENDOR_ID_CHELSIO		0x1425
-
 #define PCI_SUBVENDOR_ID_PERLE          0x155f
 #define PCI_SUBDEVICE_ID_PCI_RAS4       0xf001
 #define PCI_SUBDEVICE_ID_PCI_RAS8       0xf010
 
-
 #define PCI_VENDOR_ID_SYBA		0x1592
 #define PCI_DEVICE_ID_SYBA_2P_EPP	0x0782
 #define PCI_DEVICE_ID_SYBA_1P_ECP	0x0783
@@ -2028,8 +2001,10 @@
 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
 #define PCI_DEVICE_ID_MELLANOX_SINAI	0x6274
 
-#define PCI_VENDOR_ID_PDC		0x15e9
+#define PCI_VENDOR_ID_QUICKNET		0x15e2
+#define PCI_DEVICE_ID_QUICKNET_XJ	0x0500
 
+#define PCI_VENDOR_ID_PDC		0x15e9
 
 #define PCI_VENDOR_ID_FARSITE           0x1619
 #define PCI_DEVICE_ID_FARSITE_T2P       0x0400
@@ -2046,6 +2021,8 @@
 #define PCI_DEVICE_ID_BCM1250_PCI	0x0001
 #define PCI_DEVICE_ID_BCM1250_HT	0x0002
 
+#define PCI_VENDOR_ID_ATHEROS		0x168c
+
 #define PCI_VENDOR_ID_NETCELL		0x169c
 #define PCI_DEVICE_ID_REVOLUTION	0x0044
 
@@ -2084,7 +2061,6 @@
 #define PCI_DEVICE_ID_HERC_WIN		0x5732
 #define PCI_DEVICE_ID_HERC_UNI		0x5832
 
-
 #define PCI_VENDOR_ID_SITECOM		0x182d
 #define PCI_DEVICE_ID_SITECOM_DC105V2	0x3069
 
@@ -2120,12 +2096,9 @@
 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2	0x0007
 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2V	0x0009
 
-
 #define PCI_VENDOR_ID_AKS		0x416c
 #define PCI_DEVICE_ID_AKS_ALADDINCARD	0x0100
 
-
-
 #define PCI_VENDOR_ID_S3		0x5333
 #define PCI_DEVICE_ID_S3_TRIO		0x8811
 #define PCI_DEVICE_ID_S3_868		0x8880
@@ -2137,7 +2110,6 @@
 #define PCI_VENDOR_ID_DUNORD		0x5544
 #define PCI_DEVICE_ID_DUNORD_I3000	0x0001
 
-
 #define PCI_VENDOR_ID_DCI		0x6666
 #define PCI_DEVICE_ID_DCI_PCCOM4	0x0001
 #define PCI_DEVICE_ID_DCI_PCCOM8	0x0002
@@ -2266,11 +2238,11 @@
 #define PCI_DEVICE_ID_INTEL_ICH8_5	0x283e
 #define PCI_DEVICE_ID_INTEL_ICH8_6	0x2850
 #define PCI_DEVICE_ID_INTEL_ICH9_0	0x2910
-#define PCI_DEVICE_ID_INTEL_ICH9_1	0x2911
+#define PCI_DEVICE_ID_INTEL_ICH9_1	0x2917
 #define PCI_DEVICE_ID_INTEL_ICH9_2	0x2912
 #define PCI_DEVICE_ID_INTEL_ICH9_3	0x2913
 #define PCI_DEVICE_ID_INTEL_ICH9_4	0x2914
-#define PCI_DEVICE_ID_INTEL_ICH9_5	0x2915
+#define PCI_DEVICE_ID_INTEL_ICH9_5	0x2919
 #define PCI_DEVICE_ID_INTEL_ICH9_6	0x2930
 #define PCI_DEVICE_ID_INTEL_82855PM_HB	0x3340
 #define PCI_DEVICE_ID_INTEL_82830_HB	0x3575
@@ -2381,7 +2353,6 @@
 #define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN   0x0500
 #define PCI_DEVICE_ID_ADAPTEC2_SCAMP	0x0503
 
-
 #define PCI_VENDOR_ID_HOLTEK		0x9412
 #define PCI_DEVICE_ID_HOLTEK_6565	0x6565
 
@@ -2397,6 +2368,8 @@
 #define PCI_DEVICE_ID_NETMOS_9845	0x9845
 #define PCI_DEVICE_ID_NETMOS_9855	0x9855
 
+#define PCI_VENDOR_ID_3COM_2		0xa727
+
 #define PCI_SUBVENDOR_ID_EXSYS		0xd84d
 #define PCI_SUBDEVICE_ID_EXSYS_4014	0x4014
 #define PCI_SUBDEVICE_ID_EXSYS_4055	0x4055
@@ -2405,13 +2378,7 @@
 #define PCI_DEVICE_ID_TIGERJET_300	0x0001
 #define PCI_DEVICE_ID_TIGERJET_100	0x0002
 
-#define PCI_VENDOR_ID_TTTECH		0x0357
-#define PCI_DEVICE_ID_TTTECH_MC322	0x000A
-
 #define PCI_VENDOR_ID_XILINX_RME	0xea60
 #define PCI_DEVICE_ID_RME_DIGI32	0x9896
 #define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
 #define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
-
-#define PCI_VENDOR_ID_QUICKNET		0x15E2
-#define PCI_DEVICE_ID_QUICKNET_XJ	0x0500
diff --git a/include/linux/pda_power.h b/include/linux/pda_power.h
new file mode 100644
index 0000000..1375f15
--- /dev/null
+++ b/include/linux/pda_power.h
@@ -0,0 +1,31 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PDA_POWER_H__
+#define __PDA_POWER_H__
+
+#define PDA_POWER_CHARGE_AC  (1 << 0)
+#define PDA_POWER_CHARGE_USB (1 << 1)
+
+struct pda_power_pdata {
+	int (*is_ac_online)(void);
+	int (*is_usb_online)(void);
+	void (*set_charge)(int flags);
+
+	char **supplied_to;
+	size_t num_supplicants;
+
+	unsigned int wait_for_status; /* msecs, default is 500 */
+	unsigned int wait_for_charger; /* msecs, default is 500 */
+};
+
+#endif /* __PDA_POWER_H__ */
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index b72be2f..926adaa 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -1,7 +1,7 @@
 #ifndef __LINUX_PERCPU_H
 #define __LINUX_PERCPU_H
 
-#include <linux/spinlock.h> /* For preempt_disable() */
+#include <linux/preempt.h>
 #include <linux/slab.h> /* For kmalloc() */
 #include <linux/smp.h>
 #include <linux/string.h> /* For memset() */
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
index f5aa593..3d9f709 100644
--- a/include/linux/percpu_counter.h
+++ b/include/linux/percpu_counter.h
@@ -8,6 +8,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/smp.h>
+#include <linux/list.h>
 #include <linux/threads.h>
 #include <linux/percpu.h>
 #include <linux/types.h>
@@ -17,6 +18,9 @@
 struct percpu_counter {
 	spinlock_t lock;
 	s64 count;
+#ifdef CONFIG_HOTPLUG_CPU
+	struct list_head list;	/* All percpu_counters are on a list */
+#endif
 	s32 *counters;
 };
 
@@ -26,18 +30,8 @@
 #define FBC_BATCH	(NR_CPUS*4)
 #endif
 
-static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
-{
-	spin_lock_init(&fbc->lock);
-	fbc->count = amount;
-	fbc->counters = alloc_percpu(s32);
-}
-
-static inline void percpu_counter_destroy(struct percpu_counter *fbc)
-{
-	free_percpu(fbc->counters);
-}
-
+void percpu_counter_init(struct percpu_counter *fbc, s64 amount);
+void percpu_counter_destroy(struct percpu_counter *fbc);
 void percpu_counter_mod(struct percpu_counter *fbc, s32 amount);
 s64 percpu_counter_sum(struct percpu_counter *fbc);
 
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 169c6c2..b9a17e0 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -29,7 +29,7 @@
 	kref_get(&ns->kref);
 }
 
-extern struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *ns);
+extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
 extern void free_pid_ns(struct kref *kref);
 
 static inline void put_pid_ns(struct pid_namespace *ns)
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 8bcbc54..8e41202 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -9,35 +9,39 @@
 #define PIPE_BUF_FLAG_ATOMIC	0x02	/* was atomically mapped */
 #define PIPE_BUF_FLAG_GIFT	0x04	/* page is a gift */
 
+/**
+ *	struct pipe_buffer - a linux kernel pipe buffer
+ *	@page: the page containing the data for the pipe buffer
+ *	@offset: offset of data inside the @page
+ *	@len: length of data inside the @page
+ *	@ops: operations associated with this buffer. See @pipe_buf_operations.
+ *	@flags: pipe buffer flags. See above.
+ *	@private: private data owned by the ops.
+ **/
 struct pipe_buffer {
 	struct page *page;
 	unsigned int offset, len;
 	const struct pipe_buf_operations *ops;
 	unsigned int flags;
+	unsigned long private;
 };
 
-/*
- * Note on the nesting of these functions:
- *
- * ->pin()
- *	->steal()
- *	...
- *	->map()
- *	...
- *	->unmap()
- *
- * That is, ->map() must be called on a pinned buffer, same goes for ->steal().
- */
-struct pipe_buf_operations {
-	int can_merge;
-	void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int);
-	void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *, void *);
-	int (*pin)(struct pipe_inode_info *, struct pipe_buffer *);
-	void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
-	int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
-	void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
-};
-
+/**
+ *	struct pipe_inode_info - a linux kernel pipe
+ *	@wait: reader/writer wait point in case of empty/full pipe
+ *	@nrbufs: the number of non-empty pipe buffers in this pipe
+ *	@curbuf: the current pipe buffer entry
+ *	@tmp_page: cached released page
+ *	@readers: number of current readers of this pipe
+ *	@writers: number of current writers of this pipe
+ *	@waiting_writers: number of writers blocked waiting for room
+ *	@r_counter: reader counter
+ *	@w_counter: writer counter
+ *	@fasync_readers: reader side fasync
+ *	@fasync_writers: writer side fasync
+ *	@inode: inode this pipe is attached to
+ *	@bufs: the circular array of pipe buffers
+ **/
 struct pipe_inode_info {
 	wait_queue_head_t wait;
 	unsigned int nrbufs, curbuf;
@@ -53,6 +57,79 @@
 	struct pipe_buffer bufs[PIPE_BUFFERS];
 };
 
+/*
+ * Note on the nesting of these functions:
+ *
+ * ->confirm()
+ *	->steal()
+ *	...
+ *	->map()
+ *	...
+ *	->unmap()
+ *
+ * That is, ->map() must be called on a confirmed buffer,
+ * same goes for ->steal(). See below for the meaning of each
+ * operation. Also see kerneldoc in fs/pipe.c for the pipe
+ * and generic variants of these hooks.
+ */
+struct pipe_buf_operations {
+	/*
+	 * This is set to 1, if the generic pipe read/write may coalesce
+	 * data into an existing buffer. If this is set to 0, a new pipe
+	 * page segment is always used for new data.
+	 */
+	int can_merge;
+
+	/*
+	 * ->map() returns a virtual address mapping of the pipe buffer.
+	 * The last integer flag reflects whether this should be an atomic
+	 * mapping or not. The atomic map is faster, however you can't take
+	 * page faults before calling ->unmap() again. So if you need to eg
+	 * access user data through copy_to/from_user(), then you must get
+	 * a non-atomic map. ->map() uses the KM_USER0 atomic slot for
+	 * atomic maps, so you can't map more than one pipe_buffer at once
+	 * and you have to be careful if mapping another page as source
+	 * or destination for a copy (IOW, it has to use something else
+	 * than KM_USER0).
+	 */
+	void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int);
+
+	/*
+	 * Undoes ->map(), finishes the virtual mapping of the pipe buffer.
+	 */
+	void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *, void *);
+
+	/*
+	 * ->confirm() verifies that the data in the pipe buffer is there
+	 * and that the contents are good. If the pages in the pipe belong
+	 * to a file system, we may need to wait for IO completion in this
+	 * hook. Returns 0 for good, or a negative error value in case of
+	 * error.
+	 */
+	int (*confirm)(struct pipe_inode_info *, struct pipe_buffer *);
+
+	/*
+	 * When the contents of this pipe buffer has been completely
+	 * consumed by a reader, ->release() is called.
+	 */
+	void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
+
+	/*
+	 * Attempt to take ownership of the pipe buffer and its contents.
+	 * ->steal() returns 0 for success, in which case the contents
+	 * of the pipe (the buf->page) is locked and now completely owned
+	 * by the caller. The page may then be transferred to a different
+	 * mapping, the most often used case is insertion into different
+	 * file address space cache.
+	 */
+	int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
+
+	/*
+	 * Get a reference to the pipe buffer.
+	 */
+	void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
+};
+
 /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
    memory allocation, whereas PIPE_BUF makes atomicity guarantees.  */
 #define PIPE_SIZE		PAGE_SIZE
@@ -68,39 +145,7 @@
 void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int);
 void generic_pipe_buf_unmap(struct pipe_inode_info *, struct pipe_buffer *, void *);
 void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
-int generic_pipe_buf_pin(struct pipe_inode_info *, struct pipe_buffer *);
+int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
 int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
 
-/*
- * splice is tied to pipes as a transport (at least for now), so we'll just
- * add the splice flags here.
- */
-#define SPLICE_F_MOVE	(0x01)	/* move pages instead of copying */
-#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
-				 /* we may still block on the fd we splice */
-				 /* from/to, of course */
-#define SPLICE_F_MORE	(0x04)	/* expect more data */
-#define SPLICE_F_GIFT	(0x08)	/* pages passed in are a gift */
-
-/*
- * Passed to the actors
- */
-struct splice_desc {
-	unsigned int len, total_len;	/* current and remaining length */
-	unsigned int flags;		/* splice flags */
-	struct file *file;		/* file to read/write */
-	loff_t pos;			/* file position */
-};
-
-typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
-			   struct splice_desc *);
-
-extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
-				loff_t *, size_t, unsigned int,
-				splice_actor *);
-
-extern ssize_t __splice_from_pipe(struct pipe_inode_info *, struct file *,
-				  loff_t *, size_t, unsigned int,
-				  splice_actor *);
-
 #endif
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index c3f01b3..30b8571 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -403,16 +403,13 @@
  *   1..32767		Reserved for ematches inside kernel tree
  *   32768..65535	Free to use, not reliable
  */
-enum
-{
-	TCF_EM_CONTAINER,
-	TCF_EM_CMP,
-	TCF_EM_NBYTE,
-	TCF_EM_U32,
-	TCF_EM_META,
-	TCF_EM_TEXT,
-	__TCF_EM_MAX
-};
+#define	TCF_EM_CONTAINER	0
+#define	TCF_EM_CMP		1
+#define	TCF_EM_NBYTE		2
+#define	TCF_EM_U32		3
+#define	TCF_EM_META		4
+#define	TCF_EM_TEXT		5
+#define	TCF_EM_MAX		5
 
 enum
 {
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index d10f353..268c515 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -101,6 +101,15 @@
 	__u8	priomap[TC_PRIO_MAX+1];	/* Map: logical priority -> PRIO band */
 };
 
+enum
+{
+	TCA_PRIO_UNSPEC,
+	TCA_PRIO_MQ,
+	__TCA_PRIO_MAX
+};
+
+#define TCA_PRIO_MAX    (__TCA_PRIO_MAX - 1)
+
 /* TBF section */
 
 struct tc_tbf_qopt
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 87545e0..273781c 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -110,37 +110,67 @@
 #define PM_SUSPEND_MAX		((__force suspend_state_t) 4)
 
 /**
- * struct pm_ops - Callbacks for managing platform dependent suspend states.
- * @valid: Callback to determine whether the given state can be entered.
- *	Valid states are advertised in /sys/power/state but can still
- *	be rejected by prepare or enter if the conditions aren't right.
- *	There is a %pm_valid_only_mem function available that can be assigned
- *	to this if you only implement mem sleep.
+ * struct pm_ops - Callbacks for managing platform dependent system sleep
+ *	states.
  *
- * @prepare: Prepare the platform for the given suspend state. Can return a
- *	negative error code if necessary.
+ * @valid: Callback to determine if given system sleep state is supported by
+ *	the platform.
+ *	Valid (ie. supported) states are advertised in /sys/power/state.  Note
+ *	that it still may be impossible to enter given system sleep state if the
+ *	conditions aren't right.
+ *	There is the %pm_valid_only_mem function available that can be assigned
+ *	to this if the platform only supports mem sleep.
  *
- * @enter: Enter the given suspend state, must be assigned. Can return a
- *	negative error code if necessary.
+ * @set_target: Tell the platform which system sleep state is going to be
+ *	entered.
+ *	@set_target() is executed right prior to suspending devices.  The
+ *	information conveyed to the platform code by @set_target() should be
+ *	disregarded by the platform as soon as @finish() is executed and if
+ *	@prepare() fails.  If @set_target() fails (ie. returns nonzero),
+ *	@prepare(), @enter() and @finish() will not be called by the PM core.
+ *	This callback is optional.  However, if it is implemented, the argument
+ *	passed to @prepare(), @enter() and @finish() is meaningless and should
+ *	be ignored.
  *
- * @finish: Called when the system has left the given state and all devices
- *	are resumed. The return value is ignored.
+ * @prepare: Prepare the platform for entering the system sleep state indicated
+ *	by @set_target() or represented by the argument if @set_target() is not
+ *	implemented.
+ *	@prepare() is called right after devices have been suspended (ie. the
+ *	appropriate .suspend() method has been executed for each device) and
+ *	before the nonboot CPUs are disabled (it is executed with IRQs enabled).
+ *	This callback is optional.  It returns 0 on success or a negative
+ *	error code otherwise, in which case the system cannot enter the desired
+ *	sleep state (@enter() and @finish() will not be called in that case).
+ *
+ * @enter: Enter the system sleep state indicated by @set_target() or
+ *	represented by the argument if @set_target() is not implemented.
+ *	This callback is mandatory.  It returns 0 on success or a negative
+ *	error code otherwise, in which case the system cannot enter the desired
+ *	sleep state.
+ *
+ * @finish: Called when the system has just left a sleep state, right after
+ *	the nonboot CPUs have been enabled and before devices are resumed (it is
+ *	executed with IRQs enabled).  If @set_target() is not implemented, the
+ *	argument represents the sleep state being left.
+ *	This callback is optional, but should be implemented by the platforms
+ *	that implement @prepare().  If implemented, it is always called after
+ *	@enter() (even if @enter() fails).
  */
 struct pm_ops {
 	int (*valid)(suspend_state_t state);
+	int (*set_target)(suspend_state_t state);
 	int (*prepare)(suspend_state_t state);
 	int (*enter)(suspend_state_t state);
 	int (*finish)(suspend_state_t state);
 };
 
+extern struct pm_ops *pm_ops;
+
 /**
  * pm_set_ops - set platform dependent power management ops
  * @pm_ops: The new power management operations to set.
  */
 extern void pm_set_ops(struct pm_ops *pm_ops);
-extern struct pm_ops *pm_ops;
-extern int pm_suspend(suspend_state_t state);
-
 extern int pm_valid_only_mem(suspend_state_t state);
 
 /**
@@ -161,6 +191,8 @@
  */
 extern void arch_suspend_enable_irqs(void);
 
+extern int pm_suspend(suspend_state_t state);
+
 /*
  * Device power management
  */
@@ -235,15 +267,10 @@
 	unsigned		can_wakeup:1;
 #ifdef	CONFIG_PM
 	unsigned		should_wakeup:1;
-	pm_message_t		prev_state;
-	void			* saved_state;
-	struct device		* pm_parent;
 	struct list_head	entry;
 #endif
 };
 
-extern void device_pm_set_parent(struct device * dev, struct device * parent);
-
 extern int device_power_down(pm_message_t state);
 extern void device_power_up(void);
 extern void device_resume(void);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
new file mode 100644
index 0000000..606c095
--- /dev/null
+++ b/include/linux/power_supply.h
@@ -0,0 +1,180 @@
+/*
+ *  Universal power supply monitor class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#ifndef __LINUX_POWER_SUPPLY_H__
+#define __LINUX_POWER_SUPPLY_H__
+
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+
+/*
+ * All voltages, currents, charges, energies, time and temperatures in uV,
+ * µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ * stated. It's driver's job to convert its raw values to units in which
+ * this class operates.
+ */
+
+/*
+ * For systems where the charger determines the maximum battery capacity
+ * the min and max fields should be used to present these values to user
+ * space. Unused/unknown fields will not appear in sysfs.
+ */
+
+enum {
+	POWER_SUPPLY_STATUS_UNKNOWN = 0,
+	POWER_SUPPLY_STATUS_CHARGING,
+	POWER_SUPPLY_STATUS_DISCHARGING,
+	POWER_SUPPLY_STATUS_NOT_CHARGING,
+	POWER_SUPPLY_STATUS_FULL,
+};
+
+enum {
+	POWER_SUPPLY_HEALTH_UNKNOWN = 0,
+	POWER_SUPPLY_HEALTH_GOOD,
+	POWER_SUPPLY_HEALTH_OVERHEAT,
+	POWER_SUPPLY_HEALTH_DEAD,
+	POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+	POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+};
+
+enum {
+	POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
+	POWER_SUPPLY_TECHNOLOGY_NiMH,
+	POWER_SUPPLY_TECHNOLOGY_LION,
+	POWER_SUPPLY_TECHNOLOGY_LIPO,
+	POWER_SUPPLY_TECHNOLOGY_LiFe,
+	POWER_SUPPLY_TECHNOLOGY_NiCd,
+};
+
+enum {
+	POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
+	POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
+	POWER_SUPPLY_CAPACITY_LEVEL_LOW,
+	POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
+	POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
+	POWER_SUPPLY_CAPACITY_LEVEL_FULL,
+};
+
+enum power_supply_property {
+	/* Properties of type `int' */
+	POWER_SUPPLY_PROP_STATUS = 0,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_EMPTY,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_AVG,
+	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+	POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
+	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_ENERGY_EMPTY,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
+	POWER_SUPPLY_PROP_ENERGY_AVG,
+	POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TEMP_AMBIENT,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+	POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+	/* Properties of type `const char *' */
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+enum power_supply_type {
+	POWER_SUPPLY_TYPE_BATTERY = 0,
+	POWER_SUPPLY_TYPE_UPS,
+	POWER_SUPPLY_TYPE_MAINS,
+	POWER_SUPPLY_TYPE_USB,
+};
+
+union power_supply_propval {
+	int intval;
+	const char *strval;
+};
+
+struct power_supply {
+	const char *name;
+	enum power_supply_type type;
+	enum power_supply_property *properties;
+	size_t num_properties;
+
+	char **supplied_to;
+	size_t num_supplicants;
+
+	int (*get_property)(struct power_supply *psy,
+			    enum power_supply_property psp,
+			    union power_supply_propval *val);
+	void (*external_power_changed)(struct power_supply *psy);
+
+	/* For APM emulation, think legacy userspace. */
+	int use_for_apm;
+
+	/* private */
+	struct device *dev;
+	struct work_struct changed_work;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+	struct led_trigger *charging_full_trig;
+	char *charging_full_trig_name;
+	struct led_trigger *charging_trig;
+	char *charging_trig_name;
+	struct led_trigger *full_trig;
+	char *full_trig_name;
+	struct led_trigger *online_trig;
+	char *online_trig_name;
+#endif
+};
+
+/*
+ * This is recommended structure to specify static power supply parameters.
+ * Generic one, parametrizable for different power supplies. Power supply
+ * class itself does not use it, but that's what implementing most platform
+ * drivers, should try reuse for consistency.
+ */
+
+struct power_supply_info {
+	const char *name;
+	int technology;
+	int voltage_max_design;
+	int voltage_min_design;
+	int charge_full_design;
+	int charge_empty_design;
+	int energy_full_design;
+	int energy_empty_design;
+	int use_for_apm;
+};
+
+extern void power_supply_changed(struct power_supply *psy);
+extern int power_supply_am_i_supplied(struct power_supply *psy);
+
+extern int power_supply_register(struct device *parent,
+				 struct power_supply *psy);
+extern void power_supply_unregister(struct power_supply *psy);
+
+/* For APM emulation, think legacy userspace. */
+extern struct class *power_supply_class;
+
+#endif /* __LINUX_POWER_SUPPLY_H__ */
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 52a9be4..e2eff90 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -59,4 +59,8 @@
 # define PR_ENDIAN_LITTLE	1	/* True little endian mode */
 # define PR_ENDIAN_PPC_LITTLE	2	/* "PowerPC" pseudo little endian */
 
+/* Get/set process seccomp mode */
+#define PR_GET_SECCOMP	21
+#define PR_SET_SECCOMP	22
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/prefetch.h b/include/linux/prefetch.h
index fc86f27..1adfe66 100644
--- a/include/linux/prefetch.h
+++ b/include/linux/prefetch.h
@@ -27,7 +27,7 @@
 	
 	prefetch(x)  	- prefetches the cacheline at "x" for read
 	prefetchw(x)	- prefetches the cacheline at "x" for write
-	spin_lock_prefetch(x) - prefectches the spinlock *x for taking
+	spin_lock_prefetch(x) - prefetches the spinlock *x for taking
 	
 	there is also PREFETCH_STRIDE which is the architecure-prefered 
 	"lookahead" size for prefetching streamed operations.
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 3469f96..28e3664 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -7,6 +7,8 @@
 #include <linux/magic.h>
 #include <asm/atomic.h>
 
+struct completion;
+
 /*
  * The proc filesystem constants/structures
  */
@@ -56,6 +58,14 @@
 	gid_t gid;
 	loff_t size;
 	const struct inode_operations *proc_iops;
+	/*
+	 * NULL ->proc_fops means "PDE is going away RSN" or
+	 * "PDE is just created". In either case, e.g. ->read_proc won't be
+	 * called because it's too late or too early, respectively.
+	 *
+	 * If you're allocating ->proc_fops dynamically, save a pointer
+	 * somewhere.
+	 */
 	const struct file_operations *proc_fops;
 	get_info_t *get_info;
 	struct module *owner;
@@ -66,6 +76,9 @@
 	atomic_t count;		/* use count */
 	int deleted;		/* delete flag */
 	void *set;
+	int pde_users;	/* number of callers into module in progress */
+	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
+	struct completion *pde_unload_completion;
 };
 
 struct kcore_list {
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index eeb1976..ae8146a 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -110,6 +110,8 @@
 		__ptrace_unlink(child);
 }
 
+int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data);
+int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data);
 
 #ifndef force_successful_syscall_return
 /*
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 6db9a4c..75e17a0 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -232,6 +232,7 @@
 	struct page **filemap; /* list of cache pages for the file */
 	unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
 	unsigned long file_pages; /* number of pages in the file */
+	int last_page_size; /* bytes in the last page */
 
 	unsigned long flags;
 
@@ -261,7 +262,7 @@
 
 char *file_path(struct file *file, char *buf, int count);
 void bitmap_print_sb(struct bitmap *bitmap);
-int bitmap_update_sb(struct bitmap *bitmap);
+void bitmap_update_sb(struct bitmap *bitmap);
 
 int  bitmap_setallbits(struct bitmap *bitmap);
 void bitmap_write_all(struct bitmap *bitmap);
@@ -277,8 +278,8 @@
 void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
 void bitmap_close_sync(struct bitmap *bitmap);
 
-int bitmap_unplug(struct bitmap *bitmap);
-int bitmap_daemon_work(struct bitmap *bitmap);
+void bitmap_unplug(struct bitmap *bitmap);
+void bitmap_daemon_work(struct bitmap *bitmap);
 #endif
 
 #endif
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index de72c49..28ac632 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -51,7 +51,7 @@
 
 	sector_t size;			/* Device size (in blocks) */
 	mddev_t *mddev;			/* RAID array if running */
-	unsigned long last_events;	/* IO event timestamp */
+	long last_events;		/* IO event timestamp */
 
 	struct block_device *bdev;	/* block device handle */
 
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index d8286db..93678f5 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -116,13 +116,46 @@
  *  attach a request to an active stripe (add_stripe_bh())
  *     lockdev attach-buffer unlockdev
  *  handle a stripe (handle_stripe())
- *     lockstripe clrSTRIPE_HANDLE ... (lockdev check-buffers unlockdev) .. change-state .. record io needed unlockstripe schedule io
+ *     lockstripe clrSTRIPE_HANDLE ...
+ *		(lockdev check-buffers unlockdev) ..
+ *		change-state ..
+ *		record io/ops needed unlockstripe schedule io/ops
  *  release an active stripe (release_stripe())
  *     lockdev if (!--cnt) { if  STRIPE_HANDLE, add to handle_list else add to inactive-list } unlockdev
  *
  * The refcount counts each thread that have activated the stripe,
  * plus raid5d if it is handling it, plus one for each active request
- * on a cached buffer.
+ * on a cached buffer, and plus one if the stripe is undergoing stripe
+ * operations.
+ *
+ * Stripe operations are performed outside the stripe lock,
+ * the stripe operations are:
+ * -copying data between the stripe cache and user application buffers
+ * -computing blocks to save a disk access, or to recover a missing block
+ * -updating the parity on a write operation (reconstruct write and
+ *  read-modify-write)
+ * -checking parity correctness
+ * -running i/o to disk
+ * These operations are carried out by raid5_run_ops which uses the async_tx
+ * api to (optionally) offload operations to dedicated hardware engines.
+ * When requesting an operation handle_stripe sets the pending bit for the
+ * operation and increments the count.  raid5_run_ops is then run whenever
+ * the count is non-zero.
+ * There are some critical dependencies between the operations that prevent some
+ * from being requested while another is in flight.
+ * 1/ Parity check operations destroy the in cache version of the parity block,
+ *    so we prevent parity dependent operations like writes and compute_blocks
+ *    from starting while a check is in progress.  Some dma engines can perform
+ *    the check without damaging the parity block, in these cases the parity
+ *    block is re-marked up to date (assuming the check was successful) and is
+ *    not re-read from disk.
+ * 2/ When a write operation is requested we immediately lock the affected
+ *    blocks, and mark them as not up to date.  This causes new read requests
+ *    to be held off, as well as parity checks and compute block operations.
+ * 3/ Once a compute block operation has been requested handle_stripe treats
+ *    that block as if it is up to date.  raid5_run_ops guaruntees that any
+ *    operation that is dependent on the compute block result is initiated after
+ *    the compute block completes.
  */
 
 struct stripe_head {
@@ -136,15 +169,46 @@
 	spinlock_t		lock;
 	int			bm_seq;	/* sequence number for bitmap flushes */
 	int			disks;			/* disks in stripe */
+	/* stripe_operations
+	 * @pending - pending ops flags (set for request->issue->complete)
+	 * @ack - submitted ops flags (set for issue->complete)
+	 * @complete - completed ops flags (set for complete)
+	 * @target - STRIPE_OP_COMPUTE_BLK target
+	 * @count - raid5_runs_ops is set to run when this is non-zero
+	 */
+	struct stripe_operations {
+		unsigned long	   pending;
+		unsigned long	   ack;
+		unsigned long	   complete;
+		int		   target;
+		int		   count;
+		u32		   zero_sum_result;
+	} ops;
 	struct r5dev {
 		struct bio	req;
 		struct bio_vec	vec;
 		struct page	*page;
-		struct bio	*toread, *towrite, *written;
+		struct bio	*toread, *read, *towrite, *written;
 		sector_t	sector;			/* sector of this page */
 		unsigned long	flags;
 	} dev[1]; /* allocated with extra space depending of RAID geometry */
 };
+
+/* stripe_head_state - collects and tracks the dynamic state of a stripe_head
+ *     for handle_stripe.  It is only valid under spin_lock(sh->lock);
+ */
+struct stripe_head_state {
+	int syncing, expanding, expanded;
+	int locked, uptodate, to_read, to_write, failed, written;
+	int to_fill, compute, req_compute, non_overwrite;
+	int failed_num;
+};
+
+/* r6_state - extra state data only relevant to r6 */
+struct r6_state {
+	int p_failed, q_failed, qd_idx, failed_num[2];
+};
+
 /* Flags */
 #define	R5_UPTODATE	0	/* page contains current data */
 #define	R5_LOCKED	1	/* IO has been submitted on "req" */
@@ -158,6 +222,15 @@
 #define	R5_ReWrite	9	/* have tried to over-write the readerror */
 
 #define	R5_Expanded	10	/* This block now has post-expand data */
+#define	R5_Wantcompute	11 /* compute_block in progress treat as
+				    * uptodate
+				    */
+#define	R5_Wantfill	12 /* dev->toread contains a bio that needs
+				    * filling
+				    */
+#define	R5_Wantprexor	13 /* distinguish blocks ready for rmw from
+				    * other "towrites"
+				    */
 /*
  * Write method
  */
@@ -180,6 +253,24 @@
 #define	STRIPE_EXPAND_SOURCE	10
 #define	STRIPE_EXPAND_READY	11
 /*
+ * Operations flags (in issue order)
+ */
+#define STRIPE_OP_BIOFILL	0
+#define STRIPE_OP_COMPUTE_BLK	1
+#define STRIPE_OP_PREXOR	2
+#define STRIPE_OP_BIODRAIN	3
+#define STRIPE_OP_POSTXOR	4
+#define STRIPE_OP_CHECK	5
+#define STRIPE_OP_IO		6
+
+/* modifiers to the base operations
+ * STRIPE_OP_MOD_REPAIR_PD - compute the parity block and write it back
+ * STRIPE_OP_MOD_DMA_CHECK - parity is not corrupted by the check
+ */
+#define STRIPE_OP_MOD_REPAIR_PD 7
+#define STRIPE_OP_MOD_DMA_CHECK 8
+
+/*
  * Plugging:
  *
  * To improve write throughput, we need to delay the handling of some
diff --git a/include/linux/raid/xor.h b/include/linux/raid/xor.h
index f0d67cb..3e12058 100644
--- a/include/linux/raid/xor.h
+++ b/include/linux/raid/xor.h
@@ -3,9 +3,10 @@
 
 #include <linux/raid/md.h>
 
-#define MAX_XOR_BLOCKS 5
+#define MAX_XOR_BLOCKS 4
 
-extern void xor_block(unsigned int count, unsigned int bytes, void **ptr);
+extern void xor_blocks(unsigned int count, unsigned int bytes,
+	void *dest, void **srcs);
 
 struct xor_block_template {
         struct xor_block_template *next;
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 7c1ffba..a8a6ea8 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -63,7 +63,7 @@
  * This structure represents a RF switch located on a network device.
  */
 struct rfkill {
-	char *name;
+	const char *name;
 	enum rfkill_type type;
 
 	enum rfkill_state state;
diff --git a/include/linux/rtc/m48t59.h b/include/linux/rtc/m48t59.h
new file mode 100644
index 0000000..e8c7c21
--- /dev/null
+++ b/include/linux/rtc/m48t59.h
@@ -0,0 +1,57 @@
+/*
+ * include/linux/rtc/m48t59.h
+ *
+ * Definitions for the platform data of m48t59 RTC chip driver.
+ *
+ * Copyright (c) 2007 Wind River Systems, Inc.
+ *
+ * Mark Zhan <rongkai.zhan@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_RTC_M48T59_H_
+#define _LINUX_RTC_M48T59_H_
+
+/*
+ * M48T59 Register Offset
+ */
+#define M48T59_YEAR		0x1fff
+#define M48T59_MONTH		0x1ffe
+#define M48T59_MDAY		0x1ffd	/* Day of Month */
+#define M48T59_WDAY		0x1ffc	/* Day of Week */
+#define M48T59_WDAY_CB			0x20	/* Century Bit */
+#define M48T59_WDAY_CEB			0x10	/* Century Enable Bit */
+#define M48T59_HOUR		0x1ffb
+#define M48T59_MIN		0x1ffa
+#define M48T59_SEC		0x1ff9
+#define M48T59_CNTL		0x1ff8
+#define M48T59_CNTL_READ		0x40
+#define M48T59_CNTL_WRITE		0x80
+#define M48T59_WATCHDOG		0x1ff7
+#define M48T59_INTR		0x1ff6
+#define M48T59_INTR_AFE			0x80	/* Alarm Interrupt Enable */
+#define M48T59_INTR_ABE			0x20
+#define M48T59_ALARM_DATE	0x1ff5
+#define M48T59_ALARM_HOUR	0x1ff4
+#define M48T59_ALARM_MIN	0x1ff3
+#define M48T59_ALARM_SEC	0x1ff2
+#define M48T59_UNUSED		0x1ff1
+#define M48T59_FLAGS		0x1ff0
+#define M48T59_FLAGS_WDT		0x80	/* watchdog timer expired */
+#define M48T59_FLAGS_AF			0x40	/* alarm */
+#define M48T59_FLAGS_BF			0x10	/* low battery */
+
+#define M48T59_NVRAM_SIZE	0x1ff0
+
+struct m48t59_plat_data {
+	/* The method to access M48T59 registers,
+	 * NOTE: The 'ofs' should be 0x00~0x1fff
+	 */
+	void (*write_byte)(struct device *dev, u32 ofs, u8 val);
+	unsigned char (*read_byte)(struct device *dev, u32 ofs);
+};
+
+#endif /* _LINUX_RTC_M48T59_H_ */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 1fae30a..c91476c 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -261,7 +261,7 @@
 	RTA_FLOW,
 	RTA_CACHEINFO,
 	RTA_SESSION,
-	RTA_MP_ALGO,
+	RTA_MP_ALGO, /* no longer used */
 	RTA_TABLE,
 	__RTA_MAX
 };
@@ -570,10 +570,16 @@
 }
 
 extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
+extern int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+				        struct rtattr *rta, int len);
 
 #define rtattr_parse_nested(tb, max, rta) \
 	rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
 
+#define rtattr_parse_nested_compat(tb, max, rta, data, len) \
+({	data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
+	__rtattr_parse_nested_compat(tb, max, rta, len); })
+
 extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
 extern int rtnl_unicast(struct sk_buff *skb, u32 pid);
 extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
@@ -638,6 +644,18 @@
 ({	(start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
 	(skb)->len; })
 
+#define RTA_NEST_COMPAT(skb, type, attrlen, data) \
+({	struct rtattr *__start = (struct rtattr *)skb_tail_pointer(skb); \
+	RTA_PUT(skb, type, attrlen, data); \
+	RTA_NEST(skb, type); \
+	__start; })
+
+#define RTA_NEST_COMPAT_END(skb, start) \
+({	struct rtattr *__nest = (void *)(start) + NLMSG_ALIGN((start)->rta_len); \
+	(start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
+	RTA_NEST_END(skb, __nest); \
+	(skb)->len; })
+
 #define RTA_NEST_CANCEL(skb, start) \
 ({	if (start) \
 		skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index a81897e..731edaca 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -26,6 +26,7 @@
 #define CLONE_STOPPED		0x02000000	/* Start in stopped state */
 #define CLONE_NEWUTS		0x04000000	/* New utsname group? */
 #define CLONE_NEWIPC		0x08000000	/* New ipcs */
+#define CLONE_NEWUSER		0x10000000	/* New user namespace */
 
 /*
  * Scheduling policies
@@ -34,6 +35,8 @@
 #define SCHED_FIFO		1
 #define SCHED_RR		2
 #define SCHED_BATCH		3
+/* SCHED_ISO: reserved but not implemented yet */
+#define SCHED_IDLE		5
 
 #ifdef __KERNEL__
 
@@ -130,6 +133,26 @@
 extern unsigned long nr_iowait(void);
 extern unsigned long weighted_cpuload(const int cpu);
 
+struct seq_file;
+struct cfs_rq;
+#ifdef CONFIG_SCHED_DEBUG
+extern void proc_sched_show_task(struct task_struct *p, struct seq_file *m);
+extern void proc_sched_set_task(struct task_struct *p);
+extern void
+print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now);
+#else
+static inline void
+proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+{
+}
+static inline void proc_sched_set_task(struct task_struct *p)
+{
+}
+static inline void
+print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now)
+{
+}
+#endif
 
 /*
  * Task state bitmask. NOTE! These bits are also
@@ -193,6 +216,7 @@
 extern void sched_init(void);
 extern void sched_init_smp(void);
 extern void init_idle(struct task_struct *idle, int cpu);
+extern void init_idle_bootup_task(struct task_struct *idle);
 
 extern cpumask_t nohz_cpu_mask;
 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)
@@ -264,6 +288,7 @@
 asmlinkage void schedule(void);
 
 struct nsproxy;
+struct user_namespace;
 
 /* Maximum number of active map areas.. This is a random (large) number */
 #define DEFAULT_MAX_MAP_COUNT	65536
@@ -479,7 +504,7 @@
 	 * from jiffies_to_ns(utime + stime) if sched_clock uses something
 	 * other than jiffies.)
 	 */
-	unsigned long long sched_time;
+	unsigned long long sum_sched_runtime;
 
 	/*
 	 * We don't bother to synchronize most readers of this at all,
@@ -506,6 +531,10 @@
 #ifdef CONFIG_TASKSTATS
 	struct taskstats *stats;
 #endif
+#ifdef CONFIG_AUDIT
+	unsigned audit_tty;
+	struct tty_audit_buf *tty_audit_buf;
+#endif
 };
 
 /* Context switch must be unlocked if interrupts are to be enabled */
@@ -521,31 +550,6 @@
 #define SIGNAL_STOP_CONTINUED	0x00000004 /* SIGCONT since WCONTINUED reap */
 #define SIGNAL_GROUP_EXIT	0x00000008 /* group exit in progress */
 
-
-/*
- * Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
- * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
- * values are inverted: lower p->prio value means higher priority.
- *
- * The MAX_USER_RT_PRIO value allows the actual maximum
- * RT priority to be separate from the value exported to
- * user-space.  This allows kernel threads to set their
- * priority to a value higher than any user task. Note:
- * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
- */
-
-#define MAX_USER_RT_PRIO	100
-#define MAX_RT_PRIO		MAX_USER_RT_PRIO
-
-#define MAX_PRIO		(MAX_RT_PRIO + 40)
-
-#define rt_prio(prio)		unlikely((prio) < MAX_RT_PRIO)
-#define rt_task(p)		rt_prio((p)->prio)
-#define batch_task(p)		(unlikely((p)->policy == SCHED_BATCH))
-#define is_rt_policy(p)		((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
-#define has_rt_policy(p)	unlikely(is_rt_policy((p)->policy))
-
 /*
  * Some day this will be a full-fledged user tracking system..
  */
@@ -583,13 +587,13 @@
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
 struct sched_info {
 	/* cumulative counters */
-	unsigned long	cpu_time,	/* time spent on the cpu */
-			run_delay,	/* time spent waiting on a runqueue */
-			pcnt;		/* # of timeslices run on this cpu */
+	unsigned long pcnt;	      /* # of times run on this cpu */
+	unsigned long long cpu_time,  /* time spent on the cpu */
+			   run_delay; /* time spent waiting on a runqueue */
 
 	/* timestamps */
-	unsigned long	last_arrival,	/* when we last ran on a cpu */
-			last_queued;	/* when we were last queued to run */
+	unsigned long long last_arrival,/* when we last ran on a cpu */
+			   last_queued;	/* when we were last queued to run */
 };
 #endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */
 
@@ -639,18 +643,24 @@
 #endif
 }
 
-enum idle_type
-{
-	SCHED_IDLE,
-	NOT_IDLE,
-	NEWLY_IDLE,
-	MAX_IDLE_TYPES
+enum cpu_idle_type {
+	CPU_IDLE,
+	CPU_NOT_IDLE,
+	CPU_NEWLY_IDLE,
+	CPU_MAX_IDLE_TYPES
 };
 
 /*
  * sched-domains (multiprocessor balancing) declarations:
  */
-#define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
+
+/*
+ * Increase resolution of nice-level calculations:
+ */
+#define SCHED_LOAD_SHIFT	10
+#define SCHED_LOAD_SCALE	(1L << SCHED_LOAD_SHIFT)
+
+#define SCHED_LOAD_SCALE_FUZZ	(SCHED_LOAD_SCALE >> 5)
 
 #ifdef CONFIG_SMP
 #define SD_LOAD_BALANCE		1	/* Do load balancing on this domain. */
@@ -719,14 +729,14 @@
 
 #ifdef CONFIG_SCHEDSTATS
 	/* load_balance() stats */
-	unsigned long lb_cnt[MAX_IDLE_TYPES];
-	unsigned long lb_failed[MAX_IDLE_TYPES];
-	unsigned long lb_balanced[MAX_IDLE_TYPES];
-	unsigned long lb_imbalance[MAX_IDLE_TYPES];
-	unsigned long lb_gained[MAX_IDLE_TYPES];
-	unsigned long lb_hot_gained[MAX_IDLE_TYPES];
-	unsigned long lb_nobusyg[MAX_IDLE_TYPES];
-	unsigned long lb_nobusyq[MAX_IDLE_TYPES];
+	unsigned long lb_cnt[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_failed[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_balanced[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_imbalance[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_gained[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_hot_gained[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_nobusyg[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_nobusyq[CPU_MAX_IDLE_TYPES];
 
 	/* Active load balancing */
 	unsigned long alb_cnt;
@@ -753,12 +763,6 @@
 extern int partition_sched_domains(cpumask_t *partition1,
 				    cpumask_t *partition2);
 
-/*
- * Maximum cache size the migration-costs auto-tuning code will
- * search from:
- */
-extern unsigned int max_cache_size;
-
 #endif	/* CONFIG_SMP */
 
 
@@ -809,14 +813,86 @@
 struct pipe_inode_info;
 struct uts_namespace;
 
-enum sleep_type {
-	SLEEP_NORMAL,
-	SLEEP_NONINTERACTIVE,
-	SLEEP_INTERACTIVE,
-	SLEEP_INTERRUPTED,
+struct rq;
+struct sched_domain;
+
+struct sched_class {
+	struct sched_class *next;
+
+	void (*enqueue_task) (struct rq *rq, struct task_struct *p,
+			      int wakeup, u64 now);
+	void (*dequeue_task) (struct rq *rq, struct task_struct *p,
+			      int sleep, u64 now);
+	void (*yield_task) (struct rq *rq, struct task_struct *p);
+
+	void (*check_preempt_curr) (struct rq *rq, struct task_struct *p);
+
+	struct task_struct * (*pick_next_task) (struct rq *rq, u64 now);
+	void (*put_prev_task) (struct rq *rq, struct task_struct *p, u64 now);
+
+	int (*load_balance) (struct rq *this_rq, int this_cpu,
+			struct rq *busiest,
+			unsigned long max_nr_move, unsigned long max_load_move,
+			struct sched_domain *sd, enum cpu_idle_type idle,
+			int *all_pinned, unsigned long *total_load_moved);
+
+	void (*set_curr_task) (struct rq *rq);
+	void (*task_tick) (struct rq *rq, struct task_struct *p);
+	void (*task_new) (struct rq *rq, struct task_struct *p);
 };
 
-struct prio_array;
+struct load_weight {
+	unsigned long weight, inv_weight;
+};
+
+/*
+ * CFS stats for a schedulable entity (task, task-group etc)
+ *
+ * Current field usage histogram:
+ *
+ *     4 se->block_start
+ *     4 se->run_node
+ *     4 se->sleep_start
+ *     4 se->sleep_start_fair
+ *     6 se->load.weight
+ *     7 se->delta_fair
+ *    15 se->wait_runtime
+ */
+struct sched_entity {
+	long			wait_runtime;
+	unsigned long		delta_fair_run;
+	unsigned long		delta_fair_sleep;
+	unsigned long		delta_exec;
+	s64			fair_key;
+	struct load_weight	load;		/* for load-balancing */
+	struct rb_node		run_node;
+	unsigned int		on_rq;
+
+	u64			wait_start_fair;
+	u64			wait_start;
+	u64			exec_start;
+	u64			sleep_start;
+	u64			sleep_start_fair;
+	u64			block_start;
+	u64			sleep_max;
+	u64			block_max;
+	u64			exec_max;
+	u64			wait_max;
+	u64			last_ran;
+
+	u64			sum_exec_runtime;
+	s64			sum_wait_runtime;
+	s64			sum_sleep_runtime;
+	unsigned long		wait_runtime_overruns;
+	unsigned long		wait_runtime_underruns;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	struct sched_entity	*parent;
+	/* rq on which this entity is (to be) queued: */
+	struct cfs_rq		*cfs_rq;
+	/* rq "owned" by this entity/group: */
+	struct cfs_rq		*my_q;
+#endif
+};
 
 struct task_struct {
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
@@ -832,23 +908,20 @@
 	int oncpu;
 #endif
 #endif
-	int load_weight;	/* for niceness load balancing purposes */
+
 	int prio, static_prio, normal_prio;
 	struct list_head run_list;
-	struct prio_array *array;
+	struct sched_class *sched_class;
+	struct sched_entity se;
 
 	unsigned short ioprio;
 #ifdef CONFIG_BLK_DEV_IO_TRACE
 	unsigned int btrace_seq;
 #endif
-	unsigned long sleep_avg;
-	unsigned long long timestamp, last_ran;
-	unsigned long long sched_time; /* sched_clock time spent running */
-	enum sleep_type sleep_type;
 
 	unsigned int policy;
 	cpumask_t cpus_allowed;
-	unsigned int time_slice, first_time_slice;
+	unsigned int time_slice;
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
 	struct sched_info sched_info;
@@ -905,7 +978,8 @@
 	unsigned int rt_priority;
 	cputime_t utime, stime;
 	unsigned long nvcsw, nivcsw; /* context switch counts */
-	struct timespec start_time;
+	struct timespec start_time; 		/* monotonic time */
+	struct timespec real_start_time;	/* boot based time */
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 	unsigned long min_flt, maj_flt;
 
@@ -1078,6 +1152,37 @@
 #endif
 };
 
+/*
+ * Priority of a process goes from 0..MAX_PRIO-1, valid RT
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
+ * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
+ * values are inverted: lower p->prio value means higher priority.
+ *
+ * The MAX_USER_RT_PRIO value allows the actual maximum
+ * RT priority to be separate from the value exported to
+ * user-space.  This allows kernel threads to set their
+ * priority to a value higher than any user task. Note:
+ * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
+ */
+
+#define MAX_USER_RT_PRIO	100
+#define MAX_RT_PRIO		MAX_USER_RT_PRIO
+
+#define MAX_PRIO		(MAX_RT_PRIO + 40)
+#define DEFAULT_PRIO		(MAX_RT_PRIO + 20)
+
+static inline int rt_prio(int prio)
+{
+	if (unlikely(prio < MAX_RT_PRIO))
+		return 1;
+	return 0;
+}
+
+static inline int rt_task(struct task_struct *p)
+{
+	return rt_prio(p->prio);
+}
+
 static inline pid_t process_group(struct task_struct *tsk)
 {
 	return tsk->signal->pgrp;
@@ -1162,6 +1267,7 @@
 					/* Not implemented yet, only for 486*/
 #define PF_STARTING	0x00000002	/* being created */
 #define PF_EXITING	0x00000004	/* getting shut down */
+#define PF_EXITPIDONE	0x00000008	/* pi exit done on shut down */
 #define PF_FORKNOEXEC	0x00000040	/* forked but didn't exec */
 #define PF_SUPERPRIV	0x00000100	/* used super-user privileges */
 #define PF_DUMPCORE	0x00000200	/* dumped core */
@@ -1182,6 +1288,7 @@
 #define PF_SPREAD_SLAB	0x02000000	/* Spread some slab caches over cpuset */
 #define PF_MEMPOLICY	0x10000000	/* Non-default NUMA mempolicy */
 #define PF_MUTEX_TESTER	0x20000000	/* Thread belongs to the rt mutex tester */
+#define PF_FREEZER_SKIP	0x40000000	/* Freezer should not count it as freezeable */
 
 /*
  * Only the _current_ task can read/write to tsk->flags, but other
@@ -1221,7 +1328,7 @@
 
 extern unsigned long long sched_clock(void);
 extern unsigned long long
-current_sched_time(const struct task_struct *current_task);
+task_sched_runtime(struct task_struct *task);
 
 /* sched_exec is called by processes performing an exec */
 #ifdef CONFIG_SMP
@@ -1230,6 +1337,8 @@
 #define sched_exec()   {}
 #endif
 
+extern void sched_clock_unstable_event(void);
+
 #ifdef CONFIG_HOTPLUG_CPU
 extern void idle_task_exit(void);
 #else
@@ -1238,6 +1347,14 @@
 
 extern void sched_idle_next(void);
 
+extern unsigned int sysctl_sched_granularity;
+extern unsigned int sysctl_sched_wakeup_granularity;
+extern unsigned int sysctl_sched_batch_wakeup_granularity;
+extern unsigned int sysctl_sched_stat_granularity;
+extern unsigned int sysctl_sched_runtime_limit;
+extern unsigned int sysctl_sched_child_runs_first;
+extern unsigned int sysctl_sched_features;
+
 #ifdef CONFIG_RT_MUTEXES
 extern int rt_mutex_getprio(struct task_struct *p);
 extern void rt_mutex_setprio(struct task_struct *p, int prio);
@@ -1293,7 +1410,7 @@
 extern void __set_special_pids(pid_t session, pid_t pgrp);
 
 /* per-UID process charging. */
-extern struct user_struct * alloc_uid(uid_t);
+extern struct user_struct * alloc_uid(struct user_namespace *, uid_t);
 static inline struct user_struct *get_uid(struct user_struct *u)
 {
 	atomic_inc(&u->__count);
@@ -1315,8 +1432,8 @@
 #else
  static inline void kick_process(struct task_struct *tsk) { }
 #endif
-extern void FASTCALL(sched_fork(struct task_struct * p, int clone_flags));
-extern void FASTCALL(sched_exit(struct task_struct * p));
+extern void sched_fork(struct task_struct *p, int clone_flags);
+extern void sched_dead(struct task_struct *p);
 
 extern int in_group_p(gid_t);
 extern int in_egroup_p(gid_t);
@@ -1404,7 +1521,7 @@
 extern void FASTCALL(__mmdrop(struct mm_struct *));
 static inline void mmdrop(struct mm_struct * mm)
 {
-	if (atomic_dec_and_test(&mm->mm_count))
+	if (unlikely(atomic_dec_and_test(&mm->mm_count)))
 		__mmdrop(mm);
 }
 
@@ -1615,11 +1732,13 @@
 	return 0;
 }
 
-/* Reevaluate whether the task has signals pending delivery.
-   This is required every time the blocked sigset_t changes.
-   callers must hold sighand->siglock.  */
-
-extern FASTCALL(void recalc_sigpending_tsk(struct task_struct *t));
+/*
+ * Reevaluate whether the task has signals pending delivery.
+ * Wake the task if so.
+ * This is required every time the blocked sigset_t changes.
+ * callers must hold sighand->siglock.
+ */
+extern void recalc_sigpending_and_wake(struct task_struct *t);
 extern void recalc_sigpending(void);
 
 extern void signal_wake_up(struct task_struct *t, int resume_stopped);
@@ -1634,10 +1753,7 @@
 	return task_thread_info(p)->cpu;
 }
 
-static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
-{
-	task_thread_info(p)->cpu = cpu;
-}
+extern void set_task_cpu(struct task_struct *p, unsigned int cpu);
 
 #else
 
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index b02308e..3ee412b 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -10,7 +10,7 @@
 struct screen_info {
 	u8  orig_x;		/* 0x00 */
 	u8  orig_y;		/* 0x01 */
-	u16 dontuse1;		/* 0x02 -- EXT_MEM_K sits here */
+	u16 ext_mem_k;		/* 0x02 */
 	u16 orig_video_page;	/* 0x04 */
 	u8  orig_video_mode;	/* 0x06 */
 	u8  orig_video_cols;	/* 0x07 */
@@ -27,7 +27,7 @@
 	u16 lfb_depth;		/* 0x16 */
 	u32 lfb_base;		/* 0x18 */
 	u32 lfb_size;		/* 0x1c */
-	u16 dontuse2, dontuse3;	/* 0x20 -- CL_MAGIC and CL_OFFSET here */
+	u16 cl_magic, cl_offset; /* 0x20 */
 	u16 lfb_linelength;	/* 0x24 */
 	u8  red_size;		/* 0x26 */
 	u8  red_pos;		/* 0x27 */
@@ -42,9 +42,8 @@
 	u16 pages;		/* 0x32 */
 	u16 vesa_attributes;	/* 0x34 */
 	u32 capabilities;       /* 0x36 */
-				/* 0x3a -- 0x3b reserved for future expansion */
-				/* 0x3c -- 0x3f micro stack for relocatable kernels */
-};
+	u8  _reserved[6];	/* 0x3a */
+} __attribute__((packed));
 
 extern struct screen_info screen_info;
 
diff --git a/include/linux/scx200_gpio.h b/include/linux/scx200_gpio.h
index 1a82d30..d2b0581 100644
--- a/include/linux/scx200_gpio.h
+++ b/include/linux/scx200_gpio.h
@@ -1,5 +1,3 @@
-#include <linux/spinlock.h>
-
 u32 scx200_gpio_configure(unsigned index, u32 set, u32 clear);
 
 extern unsigned scx200_gpio_base;
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 3e8b1cf..262a8dc 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -4,8 +4,6 @@
 
 #ifdef CONFIG_SECCOMP
 
-#define NR_SECCOMP_MODES 1
-
 #include <linux/thread_info.h>
 #include <asm/seccomp.h>
 
@@ -18,20 +16,23 @@
 		__secure_computing(this_syscall);
 }
 
-static inline int has_secure_computing(struct thread_info *ti)
-{
-	return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP));
-}
+extern long prctl_get_seccomp(void);
+extern long prctl_set_seccomp(unsigned long);
 
 #else /* CONFIG_SECCOMP */
 
 typedef struct { } seccomp_t;
 
 #define secure_computing(x) do { } while (0)
-/* static inline to preserve typechecking */
-static inline int has_secure_computing(struct thread_info *ti)
+
+static inline long prctl_get_seccomp(void)
 {
-	return 0;
+	return -EINVAL;
+}
+
+static inline long prctl_set_seccomp(unsigned long arg2)
+{
+	return -EINVAL;
 }
 
 #endif /* CONFIG_SECCOMP */
diff --git a/include/linux/security.h b/include/linux/security.h
index 9eb9e0f..c11dc8a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -71,6 +71,7 @@
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
 
+extern unsigned long mmap_min_addr;
 /*
  * Values used in the task_security_ops calls
  */
@@ -1241,8 +1242,9 @@
 	int (*file_ioctl) (struct file * file, unsigned int cmd,
 			   unsigned long arg);
 	int (*file_mmap) (struct file * file,
-			  unsigned long reqprot,
-			  unsigned long prot, unsigned long flags);
+			  unsigned long reqprot, unsigned long prot,
+			  unsigned long flags, unsigned long addr,
+			  unsigned long addr_only);
 	int (*file_mprotect) (struct vm_area_struct * vma,
 			      unsigned long reqprot,
 			      unsigned long prot);
@@ -1814,9 +1816,12 @@
 
 static inline int security_file_mmap (struct file *file, unsigned long reqprot,
 				      unsigned long prot,
-				      unsigned long flags)
+				      unsigned long flags,
+				      unsigned long addr,
+				      unsigned long addr_only)
 {
-	return security_ops->file_mmap (file, reqprot, prot, flags);
+	return security_ops->file_mmap (file, reqprot, prot, flags, addr,
+					addr_only);
 }
 
 static inline int security_file_mprotect (struct vm_area_struct *vma,
@@ -2489,7 +2494,9 @@
 
 static inline int security_file_mmap (struct file *file, unsigned long reqprot,
 				      unsigned long prot,
-				      unsigned long flags)
+				      unsigned long flags,
+				      unsigned long addr,
+				      unsigned long addr_only)
 {
 	return 0;
 }
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 3e3cccb..83783ab 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -50,5 +50,16 @@
 
 #define SEQ_START_TOKEN ((void *)1)
 
+/*
+ * Helpers for iteration over list_head-s in seq_files
+ */
+
+extern struct list_head *seq_list_start(struct list_head *head,
+		loff_t pos);
+extern struct list_head *seq_list_start_head(struct list_head *head,
+		loff_t pos);
+extern struct list_head *seq_list_next(void *v, struct list_head *head,
+		loff_t *ppos);
+
 #endif
 #endif
diff --git a/include/linux/serial.h b/include/linux/serial.h
index 33fc8cb..deb71431 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -177,11 +177,5 @@
 #ifdef __KERNEL__
 #include <linux/compiler.h>
 
-/* Allow architectures to override entries in serial8250_ports[] at run time: */
-struct uart_port;	/* forward declaration */
-extern int early_serial_setup(struct uart_port *port);
-extern int early_serial_console_init(char *options);
-extern int serial8250_start_console(struct uart_port *port, char *options);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SERIAL_H */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 71310d8..706ee9a 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -60,4 +60,8 @@
 void serial8250_suspend_port(int line);
 void serial8250_resume_port(int line);
 
+extern int serial8250_find_port(struct uart_port *p);
+extern int serial8250_find_port_for_earlycon(void);
+extern int setup_early_serial8250_console(char *cmdline);
+
 #endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index a3ac4c8..9c721cd 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -142,6 +142,9 @@
 /* Micrel KS8695 */
 #define PORT_KS8695	76
 
+/* Broadcom SB1250, etc. SOC */
+#define PORT_SB1250_DUART	77
+
 
 #ifdef __KERNEL__
 
@@ -152,6 +155,7 @@
 #include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/mutex.h>
+#include <linux/sysrq.h>
 
 struct uart_port;
 struct uart_info;
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 1ebf045..d9377ce 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -209,5 +209,6 @@
 #define SERIO_PENMOUNT	0x31
 #define SERIO_TOUCHRIGHT	0x32
 #define SERIO_TOUCHWIN	0x33
+#define SERIO_TAOSEVM	0x34
 
 #endif
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 9a5eac5..ea91abe 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -6,7 +6,6 @@
 
 #ifdef __KERNEL__
 #include <linux/list.h>
-#include <linux/spinlock.h>
 
 /*
  * Real Time signals may be queued.
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e7367c7..ce25643 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -65,13 +65,20 @@
  *	    is able to produce some skb->csum, it MUST use COMPLETE,
  *	    not UNNECESSARY.
  *
+ *	PARTIAL: identical to the case for output below.  This may occur
+ *	    on a packet received directly from another Linux OS, e.g.,
+ *	    a virtualised Linux kernel on the same host.  The packet can
+ *	    be treated in the same way as UNNECESSARY except that on
+ *	    output (i.e., forwarding) the checksum must be filled in
+ *	    by the OS or the hardware.
+ *
  * B. Checksumming on output.
  *
  *	NONE: skb is checksummed by protocol or csum is not required.
  *
  *	PARTIAL: device is required to csum packet as seen by hard_start_xmit
- *	from skb->transport_header to the end and to record the checksum
- *	at skb->transport_header + skb->csum.
+ *	from skb->csum_start to the end and to record the checksum
+ *	at skb->csum_start + skb->csum_offset.
  *
  *	Device must show its capabilities in dev->features, set
  *	at device setup time.
@@ -82,6 +89,7 @@
  *			  TCP/UDP over IPv4. Sigh. Vendors like this
  *			  way by an unknown reason. Though, see comment above
  *			  about CHECKSUM_UNNECESSARY. 8)
+ *	NETIF_F_IPV6_CSUM about as dumb as the last one but does IPv6 instead.
  *
  *	Any questions? No questions, good. 		--ANK
  */
@@ -147,8 +155,8 @@
 
 /* We divide dataref into two halves.  The higher 16 bits hold references
  * to the payload part of skb->data.  The lower 16 bits hold references to
- * the entire skb->data.  It is up to the users of the skb to agree on
- * where the payload starts.
+ * the entire skb->data.  A clone of a headerless skb holds the length of
+ * the header in skb->hdr_len.
  *
  * All users must obey the rule that the skb->data reference count must be
  * greater than or equal to the payload reference count.
@@ -196,7 +204,6 @@
  *	@sk: Socket we are owned by
  *	@tstamp: Time we arrived
  *	@dev: Device we arrived on/are leaving by
- *	@iif: ifindex of device we arrived on
  *	@transport_header: Transport layer header
  *	@network_header: Network layer header
  *	@mac_header: Link layer header
@@ -206,6 +213,7 @@
  *	@len: Length of actual data
  *	@data_len: Data length
  *	@mac_len: Length of link layer header
+ *	@hdr_len: writable header length of cloned skb
  *	@csum: Checksum (must include start/offset pair)
  *	@csum_start: Offset from skb->head where checksumming should start
  *	@csum_offset: Offset from csum_start where checksum should be stored
@@ -227,9 +235,12 @@
  *	@mark: Generic packet mark
  *	@nfct: Associated connection, if any
  *	@ipvs_property: skbuff is owned by ipvs
+ *	@nf_trace: netfilter packet trace flag
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nfct_reasm: netfilter conntrack re-assembly pointer
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
+ *	@iif: ifindex of device we arrived on
+ *	@queue_mapping: Queue mapping for multiqueue devices
  *	@tc_index: Traffic control index
  *	@tc_verd: traffic control verdict
  *	@dma_cookie: a cookie to one of several possible DMA operations
@@ -245,8 +256,6 @@
 	struct sock		*sk;
 	ktime_t			tstamp;
 	struct net_device	*dev;
-	int			iif;
-	/* 4 byte hole on 64 bit*/
 
 	struct  dst_entry	*dst;
 	struct	sec_path	*sp;
@@ -260,8 +269,9 @@
 	char			cb[48];
 
 	unsigned int		len,
-				data_len,
-				mac_len;
+				data_len;
+	__u16			mac_len,
+				hdr_len;
 	union {
 		__wsum		csum;
 		struct {
@@ -277,7 +287,8 @@
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-				ipvs_property:1;
+				ipvs_property:1,
+				nf_trace:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
@@ -288,12 +299,18 @@
 #ifdef CONFIG_BRIDGE_NETFILTER
 	struct nf_bridge_info	*nf_bridge;
 #endif
+
+	int			iif;
+	__u16			queue_mapping;
+
 #ifdef CONFIG_NET_SCHED
 	__u16			tc_index;	/* traffic control index */
 #ifdef CONFIG_NET_CLS_ACT
 	__u16			tc_verd;	/* traffic control verdict */
 #endif
 #endif
+	/* 2 byte hole */
+
 #ifdef CONFIG_NET_DMA
 	dma_cookie_t		dma_cookie;
 #endif
@@ -1322,6 +1339,20 @@
 }
 
 /**
+ *	skb_clone_writable - is the header of a clone writable
+ *	@skb: buffer to check
+ *	@len: length up to which to write
+ *
+ *	Returns true if modifying the header part of the cloned buffer
+ *	does not requires the data to be copied.
+ */
+static inline int skb_clone_writable(struct sk_buff *skb, int len)
+{
+	return !skb_header_cloned(skb) &&
+	       skb_headroom(skb) + len <= skb->hdr_len;
+}
+
+/**
  *	skb_cow - copy header of skb when it is required
  *	@skb: buffer to cow
  *	@headroom: needed headroom
@@ -1579,6 +1610,10 @@
 	return ktime_sub(ktime_get_real(), t);
 }
 
+static inline ktime_t net_invalid_timestamp(void)
+{
+	return ktime_set(0, 0);
+}
 
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
@@ -1604,7 +1639,7 @@
  *	if skb->ip_summed is CHECKSUM_UNNECESSARY which indicates that the
  *	hardware has already verified the correctness of the checksum.
  */
-static inline unsigned int skb_checksum_complete(struct sk_buff *skb)
+static inline __sum16 skb_checksum_complete(struct sk_buff *skb)
 {
 	return skb_csum_unnecessary(skb) ?
 	       0 : __skb_checksum_complete(skb);
@@ -1705,6 +1740,20 @@
 { }
 #endif
 
+static inline void skb_set_queue_mapping(struct sk_buff *skb, u16 queue_mapping)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	skb->queue_mapping = queue_mapping;
+#endif
+}
+
+static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_buff *from)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	to->queue_mapping = from->queue_mapping;
+#endif
+}
+
 static inline int skb_is_gso(const struct sk_buff *skb)
 {
 	return skb_shinfo(skb)->gso_size;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index a015236..0e1d0da 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -14,8 +14,6 @@
 #include <linux/gfp.h>
 #include <linux/types.h>
 
-typedef struct kmem_cache kmem_cache_t __deprecated;
-
 /*
  * Flags to pass to kmem_cache_create().
  * The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
@@ -33,6 +31,19 @@
 #define SLAB_TRACE		0x00200000UL	/* Trace allocations and frees */
 
 /*
+ * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
+ *
+ * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
+ *
+ * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
+ * Both make kfree a no-op.
+ */
+#define ZERO_SIZE_PTR ((void *)16)
+
+#define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) < \
+				(unsigned long)ZERO_SIZE_PTR)
+
+/*
  * struct kmem_cache related prototypes
  */
 void __init kmem_cache_init(void);
@@ -44,8 +55,6 @@
 			void (*)(void *, struct kmem_cache *, unsigned long));
 void kmem_cache_destroy(struct kmem_cache *);
 int kmem_cache_shrink(struct kmem_cache *);
-void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
-void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
 void kmem_cache_free(struct kmem_cache *, void *);
 unsigned int kmem_cache_size(struct kmem_cache *);
 const char *kmem_cache_name(struct kmem_cache *);
@@ -63,16 +72,6 @@
 		sizeof(struct __struct), __alignof__(struct __struct),\
 		(__flags), NULL, NULL)
 
-#ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
-#else
-static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
-					gfp_t flags, int node)
-{
-	return kmem_cache_alloc(cachep, flags);
-}
-#endif
-
 /*
  * The largest kmalloc size supported by the slab allocators is
  * 32 megabyte (2^25) or the maximum allocatable page order if that is
@@ -82,8 +81,8 @@
  * to do various tricks to work around compiler limitations in order to
  * ensure proper constant folding.
  */
-#define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT) <= 25 ? \
-				(MAX_ORDER + PAGE_SHIFT) : 25)
+#define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
+				(MAX_ORDER + PAGE_SHIFT - 1) : 25)
 
 #define KMALLOC_MAX_SIZE	(1UL << KMALLOC_SHIFT_HIGH)
 #define KMALLOC_MAX_ORDER	(KMALLOC_SHIFT_HIGH - PAGE_SHIFT)
@@ -91,51 +90,42 @@
 /*
  * Common kmalloc functions provided by all allocators
  */
-void *__kmalloc(size_t, gfp_t);
-void *__kzalloc(size_t, gfp_t);
 void * __must_check krealloc(const void *, size_t, gfp_t);
 void kfree(const void *);
 size_t ksize(const void *);
 
+/*
+ * Allocator specific definitions. These are mainly used to establish optimized
+ * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by
+ * selecting the appropriate general cache at compile time.
+ *
+ * Allocators must define at least:
+ *
+ *	kmem_cache_alloc()
+ *	__kmalloc()
+ *	kmalloc()
+ *
+ * Those wishing to support NUMA must also define:
+ *
+ *	kmem_cache_alloc_node()
+ *	kmalloc_node()
+ *
+ * See each allocator definition file for additional comments and
+ * implementation notes.
+ */
+#ifdef CONFIG_SLUB
+#include <linux/slub_def.h>
+#elif defined(CONFIG_SLOB)
+#include <linux/slob_def.h>
+#else
+#include <linux/slab_def.h>
+#endif
+
 /**
  * kcalloc - allocate memory for an array. The memory is set to zero.
  * @n: number of elements.
  * @size: element size.
  * @flags: the type of memory to allocate.
- */
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-{
-	if (n != 0 && size > ULONG_MAX / n)
-		return NULL;
-	return __kzalloc(n * size, flags);
-}
-
-/*
- * Allocator specific definitions. These are mainly used to establish optimized
- * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by selecting
- * the appropriate general cache at compile time.
- */
-
-#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB)
-#ifdef CONFIG_SLUB
-#include <linux/slub_def.h>
-#else
-#include <linux/slab_def.h>
-#endif /* !CONFIG_SLUB */
-#else
-
-/*
- * Fallback definitions for an allocator not wanting to provide
- * its own optimized kmalloc definitions (like SLOB).
- */
-
-/**
- * kmalloc - allocate memory
- * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * kmalloc is the normal method of allocating memory
- * in the kernel.
  *
  * The @flags argument may be one of:
  *
@@ -143,7 +133,7 @@
  *
  * %GFP_KERNEL - Allocate normal kernel ram.  May sleep.
  *
- * %GFP_ATOMIC - Allocation will not sleep.
+ * %GFP_ATOMIC - Allocation will not sleep.  May use emergency pools.
  *   For example, use this inside interrupt handlers.
  *
  * %GFP_HIGHUSER - Allocate pages from high memory.
@@ -152,18 +142,22 @@
  *
  * %GFP_NOFS - Do not make any fs calls while trying to get memory.
  *
+ * %GFP_NOWAIT - Allocation will not sleep.
+ *
+ * %GFP_THISNODE - Allocate node-local memory only.
+ *
+ * %GFP_DMA - Allocation suitable for DMA.
+ *   Should only be used for kmalloc() caches. Otherwise, use a
+ *   slab created with SLAB_DMA.
+ *
  * Also it is possible to set different flags by OR'ing
  * in one or more of the following additional @flags:
  *
  * %__GFP_COLD - Request cache-cold pages instead of
  *   trying to return cache-warm pages.
  *
- * %__GFP_DMA - Request memory from the DMA-capable zone.
- *
  * %__GFP_HIGH - This allocation has high priority and may use emergency pools.
  *
- * %__GFP_HIGHMEM - Allocated memory may be from highmem.
- *
  * %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail
  *   (think twice before using).
  *
@@ -173,24 +167,29 @@
  * %__GFP_NOWARN - If allocation fails, don't issue any warnings.
  *
  * %__GFP_REPEAT - If allocation fails initially, try once more before failing.
+ *
+ * There are other flags available as well, but these are not intended
+ * for general use, and so are not documented here. For a full list of
+ * potential flags, always refer to linux/gfp.h.
  */
-static inline void *kmalloc(size_t size, gfp_t flags)
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
 {
-	return __kmalloc(size, flags);
+	if (n != 0 && size > ULONG_MAX / n)
+		return NULL;
+	return __kmalloc(n * size, flags | __GFP_ZERO);
 }
 
+#if !defined(CONFIG_NUMA) && !defined(CONFIG_SLOB)
 /**
- * kzalloc - allocate memory. The memory is set to zero.
+ * kmalloc_node - allocate memory from a specific node
  * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate (see kmalloc).
+ * @flags: the type of memory to allocate (see kcalloc).
+ * @node: node to allocate from.
+ *
+ * kmalloc() for non-local nodes, used to allocate from a specific node
+ * if available. Equivalent to kmalloc() in the non-NUMA single-node
+ * case.
  */
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
-	return __kzalloc(size, flags);
-}
-#endif
-
-#ifndef CONFIG_NUMA
 static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
 	return kmalloc(size, flags);
@@ -200,7 +199,15 @@
 {
 	return __kmalloc(size, flags);
 }
-#endif /* !CONFIG_NUMA */
+
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+
+static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
+					gfp_t flags, int node)
+{
+	return kmem_cache_alloc(cachep, flags);
+}
+#endif /* !CONFIG_NUMA && !CONFIG_SLOB */
 
 /*
  * kmalloc_track_caller is a special version of kmalloc that records the
@@ -245,6 +252,23 @@
 
 #endif /* DEBUG_SLAB */
 
+/*
+ * Shortcuts
+ */
+static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags)
+{
+	return kmem_cache_alloc(k, flags | __GFP_ZERO);
+}
+
+/**
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+	return kmalloc(size, flags | __GFP_ZERO);
+}
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SLAB_H */
-
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 8d81a60..32bdc2f 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -25,10 +25,17 @@
 };
 extern struct cache_sizes malloc_sizes[];
 
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *__kmalloc(size_t size, gfp_t flags);
+
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
 	if (__builtin_constant_p(size)) {
 		int i = 0;
+
+		if (!size)
+			return ZERO_SIZE_PTR;
+
 #define CACHE(x) \
 		if (size <= x) \
 			goto found; \
@@ -51,39 +58,18 @@
 	return __kmalloc(size, flags);
 }
 
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
-	if (__builtin_constant_p(size)) {
-		int i = 0;
-#define CACHE(x) \
-		if (size <= x) \
-			goto found; \
-		else \
-			i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
-		{
-			extern void __you_cannot_kzalloc_that_much(void);
-			__you_cannot_kzalloc_that_much();
-		}
-found:
-#ifdef CONFIG_ZONE_DMA
-		if (flags & GFP_DMA)
-			return kmem_cache_zalloc(malloc_sizes[i].cs_dmacachep,
-						flags);
-#endif
-		return kmem_cache_zalloc(malloc_sizes[i].cs_cachep, flags);
-	}
-	return __kzalloc(size, flags);
-}
-
 #ifdef CONFIG_NUMA
 extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 
 static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
 	if (__builtin_constant_p(size)) {
 		int i = 0;
+
+		if (!size)
+			return ZERO_SIZE_PTR;
+
 #define CACHE(x) \
 		if (size <= x) \
 			goto found; \
diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h
new file mode 100644
index 0000000..a2daf2d
--- /dev/null
+++ b/include/linux/slob_def.h
@@ -0,0 +1,46 @@
+#ifndef __LINUX_SLOB_DEF_H
+#define __LINUX_SLOB_DEF_H
+
+void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
+
+static inline void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
+{
+	return kmem_cache_alloc_node(cachep, flags, -1);
+}
+
+void *__kmalloc_node(size_t size, gfp_t flags, int node);
+
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+{
+	return __kmalloc_node(size, flags, node);
+}
+
+/**
+ * kmalloc - allocate memory
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kcalloc).
+ *
+ * kmalloc is the normal method of allocating memory
+ * in the kernel.
+ */
+static inline void *kmalloc(size_t size, gfp_t flags)
+{
+	return __kmalloc_node(size, flags, -1);
+}
+
+static inline void *__kmalloc(size_t size, gfp_t flags)
+{
+	return kmalloc(size, flags);
+}
+
+/**
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kcalloc).
+ */
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+	return __kzalloc(size, flags);
+}
+
+#endif /* __LINUX_SLOB_DEF_H */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 0764c82..07f7e4c 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -16,7 +16,9 @@
 	unsigned long nr_partial;
 	atomic_long_t nr_slabs;
 	struct list_head partial;
+#ifdef CONFIG_SLUB_DEBUG
 	struct list_head full;
+#endif
 };
 
 /*
@@ -28,7 +30,7 @@
 	int size;		/* The size of an object including meta data */
 	int objsize;		/* The size of an object without meta data */
 	int offset;		/* Free pointer offset. */
-	unsigned int order;
+	int order;
 
 	/*
 	 * Avoid an extra cache line for UP, SMP and for the node local to
@@ -44,7 +46,9 @@
 	int align;		/* Alignment */
 	const char *name;	/* Name (only for display!) */
 	struct list_head list;	/* List of slab caches */
+#ifdef CONFIG_SLUB_DEBUG
 	struct kobject kobj;	/* For sysfs */
+#endif
 
 #ifdef CONFIG_NUMA
 	int defrag_ratio;
@@ -56,7 +60,13 @@
 /*
  * Kmalloc subsystem.
  */
-#define KMALLOC_SHIFT_LOW 3
+#if defined(ARCH_KMALLOC_MINALIGN) && ARCH_KMALLOC_MINALIGN > 8
+#define KMALLOC_MIN_SIZE ARCH_KMALLOC_MINALIGN
+#else
+#define KMALLOC_MIN_SIZE 8
+#endif
+
+#define KMALLOC_SHIFT_LOW ilog2(KMALLOC_MIN_SIZE)
 
 /*
  * We keep the general caches in an array of slab caches that are used for
@@ -70,15 +80,15 @@
  */
 static inline int kmalloc_index(size_t size)
 {
-	/*
-	 * We should return 0 if size == 0 but we use the smallest object
-	 * here for SLAB legacy reasons.
-	 */
-	WARN_ON_ONCE(size == 0);
+	if (!size)
+		return 0;
 
 	if (size > KMALLOC_MAX_SIZE)
 		return -1;
 
+	if (size <= KMALLOC_MIN_SIZE)
+		return KMALLOC_SHIFT_LOW;
+
 	if (size > 64 && size <= 96)
 		return 1;
 	if (size > 128 && size <= 192)
@@ -153,34 +163,25 @@
 #define SLUB_DMA 0
 #endif
 
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *__kmalloc(size_t size, gfp_t flags);
+
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
 	if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
 		struct kmem_cache *s = kmalloc_slab(size);
 
 		if (!s)
-			return NULL;
+			return ZERO_SIZE_PTR;
 
 		return kmem_cache_alloc(s, flags);
 	} else
 		return __kmalloc(size, flags);
 }
 
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
-	if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
-		struct kmem_cache *s = kmalloc_slab(size);
-
-		if (!s)
-			return NULL;
-
-		return kmem_cache_zalloc(s, flags);
-	} else
-		return __kzalloc(size, flags);
-}
-
 #ifdef CONFIG_NUMA
-extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+void *__kmalloc_node(size_t size, gfp_t flags, int node);
+void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 
 static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
@@ -188,7 +189,7 @@
 		struct kmem_cache *s = kmalloc_slab(size);
 
 		if (!s)
-			return NULL;
+			return ZERO_SIZE_PTR;
 
 		return kmem_cache_alloc_node(s, flags, node);
 	} else
diff --git a/include/linux/sm501-regs.h b/include/linux/sm501-regs.h
index cc9be4a..014e73b3 100644
--- a/include/linux/sm501-regs.h
+++ b/include/linux/sm501-regs.h
@@ -64,6 +64,11 @@
 #define SM501_DEBUG_CONTROL		(0x000034)
 
 /* power management */
+#define SM501_POWERMODE_P2X_SRC		(1<<29)
+#define SM501_POWERMODE_V2X_SRC		(1<<20)
+#define SM501_POWERMODE_M_SRC		(1<<12)
+#define SM501_POWERMODE_M1_SRC		(1<<4)
+
 #define SM501_CURRENT_GATE		(0x000038)
 #define SM501_CURRENT_CLOCK		(0x00003C)
 #define SM501_POWER_MODE_0_GATE		(0x000040)
@@ -104,6 +109,9 @@
 #define SM501_DEVICEID			(0x000060)
 /* 0x050100A0 */
 
+#define SM501_DEVICEID_SM501		(0x05010000)
+#define SM501_DEVICEID_IDMASK		(0xffff0000)
+
 #define SM501_PLLCLOCK_COUNT		(0x000064)
 #define SM501_MISC_TIMING		(0x000068)
 #define SM501_CURRENT_SDRAM_CLOCK	(0x00006C)
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h
index 13b3af5..2c5cd55 100644
--- a/include/linux/smb_fs.h
+++ b/include/linux/smb_fs.h
@@ -29,6 +29,7 @@
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
 #include <linux/smb_mount.h>
+#include <linux/jiffies.h>
 #include <asm/unaligned.h>
 
 static inline struct smb_sb_info *SMB_SB(struct super_block *sb)
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 96ac21f..259a13c 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -99,11 +99,14 @@
 static inline void smp_send_reschedule(int cpu) { }
 #define num_booting_cpus()			1
 #define smp_prepare_boot_cpu()			do {} while (0)
-static inline int smp_call_function_single(int cpuid, void (*func) (void *info),
-					   void *info, int retry, int wait)
-{
-	return -EBUSY;
-}
+#define smp_call_function_single(cpuid, func, info, retry, wait) \
+({ \
+	WARN_ON(cpuid != 0);	\
+	local_irq_disable();	\
+	(func)(info);		\
+	local_irq_enable();	\
+	0;			\
+})
 
 #endif /* !SMP */
 
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index cf715a4..58962c5 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -3,7 +3,6 @@
 
 #ifdef CONFIG_LOCK_KERNEL
 #include <linux/sched.h>
-#include <linux/spinlock.h>
 
 #define kernel_locked()		(current->lock_depth >= 0)
 
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 6e7c948..f852e1a 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -253,6 +253,9 @@
 
 #define MSG_EOF         MSG_FIN
 
+#define MSG_CMSG_CLOEXEC 0x40000000	/* Set close_on_exit for file
+					   descriptor received through
+					   SCM_RIGHTS */
 #if defined(CONFIG_COMPAT)
 #define MSG_CMSG_COMPAT	0x80000000	/* This message needs 32 bit fixups */
 #else
@@ -287,6 +290,7 @@
 #define SOL_NETLINK	270
 #define SOL_TIPC	271
 #define SOL_RXRPC	272
+#define SOL_PPPOL2TP	273
 
 /* IPX options */
 #define IPX_TYPE	1
diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h
index 34d4b07..40c7b5d 100644
--- a/include/linux/sonypi.h
+++ b/include/linux/sonypi.h
@@ -153,8 +153,6 @@
 #define SONYPI_COMMAND_GETCAMERAROMVERSION	18	/* obsolete */
 #define SONYPI_COMMAND_GETCAMERAREVISION	19	/* obsolete */
 
-int sonypi_camera_command(int command, u8 value);
-
 #endif				/* __KERNEL__ */
 
 #endif				/* _SONYPI_H_ */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index b6bedc3..302b81d 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -76,6 +76,7 @@
 #define	SPI_MODE_3	(SPI_CPOL|SPI_CPHA)
 #define	SPI_CS_HIGH	0x04			/* chipselect active high? */
 #define	SPI_LSB_FIRST	0x08			/* per-word bits-on-wire */
+#define	SPI_3WIRE	0x10			/* SI/SO signals shared */
 	u8			bits_per_word;
 	int			irq;
 	void			*controller_state;
@@ -341,9 +342,14 @@
  * chip transactions together.
  *
  * (ii) When the transfer is the last one in the message, the chip may
- * stay selected until the next transfer.  This is purely a performance
- * hint; the controller driver may need to select a different device
- * for the next message.
+ * stay selected until the next transfer.  On multi-device SPI busses
+ * with nothing blocking messages going to other devices, this is just
+ * a performance hint; starting a message to another device deselects
+ * this one.  But in other cases, this can be used to ensure correctness.
+ * Some devices need protocol transactions to be built from a series of
+ * spi_message submissions, where the content of one message is determined
+ * by the results of previous messages and where the whole transaction
+ * ends when the chipselect goes intactive.
  *
  * The code that submits an spi_message (and its spi_transfers)
  * to the lower layers is responsible for managing its memory.
@@ -480,14 +486,15 @@
 /**
  * spi_setup - setup SPI mode and clock rate
  * @spi: the device whose settings are being modified
- * Context: can sleep
+ * Context: can sleep, and no requests are queued to the device
  *
  * SPI protocol drivers may need to update the transfer mode if the
- * device doesn't work with the mode 0 default.  They may likewise need
+ * device doesn't work with its default.  They may likewise need
  * to update clock rates or word sizes from initial values.  This function
  * changes those settings, and must be called from a context that can sleep.
- * The changes take effect the next time the device is selected and data
- * is transferred to or from it.
+ * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
+ * effect the next time the device is selected and data is transferred to
+ * or from it.  When this function returns, the spi device is deselected.
  *
  * Note that this call will fail if the protocol driver specifies an option
  * that the underlying controller or its driver does not support.  For
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index 9dbca62..b8db32c 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -26,6 +26,7 @@
 	struct list_head	queue;
 	u8			busy;
 	u8			use_dma;
+	u8			flags;		/* extra spi->mode support */
 
 	struct spi_master	*master;
 
diff --git a/include/linux/spi/tle62x0.h b/include/linux/spi/tle62x0.h
new file mode 100644
index 0000000..60b5918
--- /dev/null
+++ b/include/linux/spi/tle62x0.h
@@ -0,0 +1,24 @@
+/*
+ * tle62x0.h - platform glue to Infineon TLE62x0 driver chips
+ *
+ * Copyright 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+struct tle62x0_pdata {
+	unsigned int		init_state;
+	unsigned int		gpio_count;
+};
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index a946176..c376f3b 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -282,6 +282,13 @@
 	1 : ({ local_irq_restore(flags); 0; }); \
 })
 
+#define write_trylock_irqsave(lock, flags) \
+({ \
+	local_irq_save(flags); \
+	write_trylock(lock) ? \
+	1 : ({ local_irq_restore(flags); 0; }); \
+})
+
 /*
  * Locks two spinlocks l1 and l2.
  * l1_first indicates if spinlock l1 should be taken first.
diff --git a/include/linux/splice.h b/include/linux/splice.h
new file mode 100644
index 0000000..33e447f
--- /dev/null
+++ b/include/linux/splice.h
@@ -0,0 +1,73 @@
+/*
+ * Function declerations and data structures related to the splice
+ * implementation.
+ *
+ * Copyright (C) 2007 Jens Axboe <jens.axboe@oracle.com>
+ *
+ */
+#ifndef SPLICE_H
+#define SPLICE_H
+
+#include <linux/pipe_fs_i.h>
+
+/*
+ * splice is tied to pipes as a transport (at least for now), so we'll just
+ * add the splice flags here.
+ */
+#define SPLICE_F_MOVE	(0x01)	/* move pages instead of copying */
+#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
+				 /* we may still block on the fd we splice */
+				 /* from/to, of course */
+#define SPLICE_F_MORE	(0x04)	/* expect more data */
+#define SPLICE_F_GIFT	(0x08)	/* pages passed in are a gift */
+
+/*
+ * Passed to the actors
+ */
+struct splice_desc {
+	unsigned int len, total_len;	/* current and remaining length */
+	unsigned int flags;		/* splice flags */
+	/*
+	 * actor() private data
+	 */
+	union {
+		void __user *userptr;	/* memory to write to */
+		struct file *file;	/* file to read/write */
+		void *data;		/* cookie */
+	} u;
+	loff_t pos;			/* file position */
+};
+
+struct partial_page {
+	unsigned int offset;
+	unsigned int len;
+	unsigned long private;
+};
+
+/*
+ * Passed to splice_to_pipe
+ */
+struct splice_pipe_desc {
+	struct page **pages;		/* page map */
+	struct partial_page *partial;	/* pages[] may not be contig */
+	int nr_pages;			/* number of pages in map */
+	unsigned int flags;		/* splice flags */
+	const struct pipe_buf_operations *ops;/* ops associated with output pipe */
+};
+
+typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
+			   struct splice_desc *);
+typedef int (splice_direct_actor)(struct pipe_inode_info *,
+				  struct splice_desc *);
+
+extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
+				loff_t *, size_t, unsigned int,
+				splice_actor *);
+extern ssize_t __splice_from_pipe(struct pipe_inode_info *,
+				  struct splice_desc *, splice_actor *);
+extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+			      struct splice_pipe_desc *);
+extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+				      splice_direct_actor *);
+
+#endif
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 534cdc7..7a69ca3 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -16,6 +16,7 @@
 #include <linux/sunrpc/xdr.h>
 
 #include <asm/atomic.h>
+#include <linux/rcupdate.h>
 
 /* size of the nodename buffer */
 #define UNX_MAXNODENAME	32
@@ -30,22 +31,28 @@
 /*
  * Client user credentials
  */
+struct rpc_auth;
+struct rpc_credops;
 struct rpc_cred {
 	struct hlist_node	cr_hash;	/* hash chain */
-	struct rpc_credops *	cr_ops;
-	unsigned long		cr_expire;	/* when to gc */
-	atomic_t		cr_count;	/* ref count */
-	unsigned short		cr_flags;	/* various flags */
+	struct list_head	cr_lru;		/* lru garbage collection */
+	struct rcu_head		cr_rcu;
+	struct rpc_auth *	cr_auth;
+	const struct rpc_credops *cr_ops;
 #ifdef RPC_DEBUG
 	unsigned long		cr_magic;	/* 0x0f4aa4f0 */
 #endif
+	unsigned long		cr_expire;	/* when to gc */
+	unsigned long		cr_flags;	/* various flags */
+	atomic_t		cr_count;	/* ref count */
 
 	uid_t			cr_uid;
 
 	/* per-flavor data */
 };
-#define RPCAUTH_CRED_NEW	0x0001
-#define RPCAUTH_CRED_UPTODATE	0x0002
+#define RPCAUTH_CRED_NEW	0
+#define RPCAUTH_CRED_UPTODATE	1
+#define RPCAUTH_CRED_HASHED	2
 
 #define RPCAUTH_CRED_MAGIC	0x0f4aa4f0
 
@@ -56,10 +63,10 @@
 #define RPC_CREDCACHE_MASK	(RPC_CREDCACHE_NR - 1)
 struct rpc_cred_cache {
 	struct hlist_head	hashtable[RPC_CREDCACHE_NR];
-	unsigned long		nextgc;		/* next garbage collection */
-	unsigned long		expire;		/* cache expiry interval */
+	spinlock_t		lock;
 };
 
+struct rpc_authops;
 struct rpc_auth {
 	unsigned int		au_cslack;	/* call cred size estimate */
 				/* guess at number of u32's auth adds before
@@ -69,7 +76,7 @@
 	unsigned int		au_verfsize;
 
 	unsigned int		au_flags;	/* various flags */
-	struct rpc_authops *	au_ops;		/* operations */
+	const struct rpc_authops *au_ops;		/* operations */
 	rpc_authflavor_t	au_flavor;	/* pseudoflavor (note may
 						 * differ from the flavor in
 						 * au_ops->au_flavor in gss
@@ -115,17 +122,19 @@
 						void *, __be32 *, void *);
 };
 
-extern struct rpc_authops	authunix_ops;
-extern struct rpc_authops	authnull_ops;
-#ifdef CONFIG_SUNRPC_SECURE
-extern struct rpc_authops	authdes_ops;
-#endif
+extern const struct rpc_authops	authunix_ops;
+extern const struct rpc_authops	authnull_ops;
 
-int			rpcauth_register(struct rpc_authops *);
-int			rpcauth_unregister(struct rpc_authops *);
+void __init		rpc_init_authunix(void);
+void __init		rpcauth_init_module(void);
+void __exit		rpcauth_remove_module(void);
+
+int			rpcauth_register(const struct rpc_authops *);
+int			rpcauth_unregister(const struct rpc_authops *);
 struct rpc_auth *	rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
-void			rpcauth_destroy(struct rpc_auth *);
+void			rpcauth_release(struct rpc_auth *);
 struct rpc_cred *	rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
+void			rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
 struct rpc_cred *	rpcauth_lookupcred(struct rpc_auth *, int);
 struct rpc_cred *	rpcauth_bindcred(struct rpc_task *);
 void			rpcauth_holdcred(struct rpc_task *);
@@ -138,8 +147,9 @@
 int			rpcauth_refreshcred(struct rpc_task *);
 void			rpcauth_invalcred(struct rpc_task *);
 int			rpcauth_uptodatecred(struct rpc_task *);
-int			rpcauth_init_credcache(struct rpc_auth *, unsigned long);
-void			rpcauth_free_credcache(struct rpc_auth *);
+int			rpcauth_init_credcache(struct rpc_auth *);
+void			rpcauth_destroy_credcache(struct rpc_auth *);
+void			rpcauth_clear_credcache(struct rpc_cred_cache *);
 
 static inline
 struct rpc_cred *	get_rpccred(struct rpc_cred *cred)
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 2db2fbf..67658e1 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -75,6 +75,7 @@
 	struct xdr_netobj	gc_wire_ctx;
 	u32			gc_win;
 	unsigned long		gc_expiry;
+	struct rcu_head		gc_rcu;
 };
 
 struct gss_upcall_msg;
@@ -85,11 +86,6 @@
 	struct gss_upcall_msg	*gc_upcall;
 };
 
-#define gc_uid			gc_base.cr_uid
-#define gc_count		gc_base.cr_count
-#define gc_flags		gc_base.cr_flags
-#define gc_expire		gc_base.cr_expire
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
 
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 6661142..c0d9d14 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -24,8 +24,10 @@
  * The high-level client handle
  */
 struct rpc_clnt {
-	atomic_t		cl_count;	/* Number of clones */
-	atomic_t		cl_users;	/* number of references */
+	struct kref		cl_kref;	/* Number of references */
+	struct list_head	cl_clients;	/* Global list of clients */
+	struct list_head	cl_tasks;	/* List of tasks */
+	spinlock_t		cl_lock;	/* spinlock */
 	struct rpc_xprt *	cl_xprt;	/* transport */
 	struct rpc_procinfo *	cl_procinfo;	/* procedure info */
 	u32			cl_prog,	/* RPC program number */
@@ -41,9 +43,7 @@
 	unsigned int		cl_softrtry : 1,/* soft timeouts */
 				cl_intr     : 1,/* interruptible */
 				cl_discrtry : 1,/* disconnect before retry */
-				cl_autobind : 1,/* use getport() */
-				cl_oneshot  : 1,/* dispose after use */
-				cl_dead     : 1;/* abandoned */
+				cl_autobind : 1;/* use getport() */
 
 	struct rpc_rtt *	cl_rtt;		/* RTO estimator data */
 
@@ -98,6 +98,7 @@
 	int			protocol;
 	struct sockaddr		*address;
 	size_t			addrsize;
+	struct sockaddr		*saddress;
 	struct rpc_timeout	*timeout;
 	char			*servername;
 	struct rpc_program	*program;
@@ -110,20 +111,20 @@
 #define RPC_CLNT_CREATE_HARDRTRY	(1UL << 0)
 #define RPC_CLNT_CREATE_INTR		(1UL << 1)
 #define RPC_CLNT_CREATE_AUTOBIND	(1UL << 2)
-#define RPC_CLNT_CREATE_ONESHOT		(1UL << 3)
-#define RPC_CLNT_CREATE_NONPRIVPORT	(1UL << 4)
-#define RPC_CLNT_CREATE_NOPING		(1UL << 5)
-#define RPC_CLNT_CREATE_DISCRTRY	(1UL << 6)
+#define RPC_CLNT_CREATE_NONPRIVPORT	(1UL << 3)
+#define RPC_CLNT_CREATE_NOPING		(1UL << 4)
+#define RPC_CLNT_CREATE_DISCRTRY	(1UL << 5)
 
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
 struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
 				struct rpc_program *, int);
 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
-int		rpc_shutdown_client(struct rpc_clnt *);
-int		rpc_destroy_client(struct rpc_clnt *);
+void		rpc_shutdown_client(struct rpc_clnt *);
 void		rpc_release_client(struct rpc_clnt *);
+
 int		rpcb_register(u32, u32, int, unsigned short, int *);
-void		rpcb_getport(struct rpc_task *);
+int		rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int);
+void		rpcb_getport_async(struct rpc_task *);
 
 void		rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
 
@@ -132,20 +133,16 @@
 			       void *calldata);
 int		rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
 			      int flags);
+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
+			       int flags);
 void		rpc_restart_call(struct rpc_task *);
 void		rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void		rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void		rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
 size_t		rpc_max_payload(struct rpc_clnt *);
 void		rpc_force_rebind(struct rpc_clnt *);
-int		rpc_ping(struct rpc_clnt *clnt, int flags);
 size_t		rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
 char *		rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
 
-/*
- * Helper function for NFSroot support
- */
-int		rpcb_getport_external(struct sockaddr_in *, __u32, __u32, int);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 5eca9e4..459c5fc 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -58,6 +58,7 @@
 u32 gss_delete_sec_context(
 		struct gss_ctx		**ctx_id);
 
+u32 gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 service);
 u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
 char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
 
@@ -77,7 +78,7 @@
 	struct module		*gm_owner;
 	struct xdr_netobj	gm_oid;
 	char			*gm_name;
-	struct gss_api_ops	*gm_ops;
+	const struct gss_api_ops *gm_ops;
 	/* pseudoflavors supported by this mechanism: */
 	int			gm_pf_num;
 	struct pf_desc *	gm_pfs;
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index ad29376..51b977a 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -23,9 +23,11 @@
 	void *private;
 	struct list_head pipe;
 	struct list_head in_upcall;
+	struct list_head in_downcall;
 	int pipelen;
 	int nreaders;
 	int nwriters;
+	int nkern_readwriters;
 	wait_queue_head_t waitq;
 #define RPC_PIPE_WAIT_FOR_OPEN	1
 	int flags;
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 2047fb2..8ea077d 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -98,7 +98,6 @@
 	unsigned short		tk_pid;		/* debugging aid */
 #endif
 };
-#define tk_auth			tk_client->cl_auth
 #define tk_xprt			tk_client->cl_xprt
 
 /* support walking a list of tasks on a wait queue */
@@ -110,11 +109,6 @@
 	if (!list_empty(head) &&  \
 	    ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1))
 
-/* .. and walking list of all tasks */
-#define	alltask_for_each(task, pos, head) \
-	list_for_each(pos, head) \
-		if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
-
 typedef void			(*rpc_action)(struct rpc_task *);
 
 struct rpc_call_ops {
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 4a7ae8a..8531a70 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -212,6 +212,7 @@
 	struct svc_pool *	rq_pool;	/* thread pool */
 	struct svc_procedure *	rq_procinfo;	/* procedure info */
 	struct auth_ops *	rq_authop;	/* authentication flavour */
+	u32			rq_flavor;	/* pseudoflavor */
 	struct svc_cred		rq_cred;	/* auth info */
 	struct sk_buff *	rq_skbuff;	/* fast recv inet buffer */
 	struct svc_deferred_req*rq_deferred;	/* deferred request we are replaying */
@@ -248,12 +249,13 @@
 						 */
 	/* Catering to nfsd */
 	struct auth_domain *	rq_client;	/* RPC peer info */
+	struct auth_domain *	rq_gssclient;	/* "gss/"-style peer info */
 	struct svc_cacherep *	rq_cacherep;	/* cache info */
 	struct knfsd_fh *	rq_reffh;	/* Referrence filehandle, used to
 						 * determine what device number
 						 * to report (real or virtual)
 						 */
-	int			rq_sendfile_ok; /* turned off in gss privacy
+	int			rq_splice_ok;   /* turned off in gss privacy
 						 * to prevent encrypting page
 						 * cache pages */
 	wait_queue_head_t	rq_wait;	/* synchronization */
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index de92619..22e1ef8 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -127,6 +127,7 @@
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
 extern void svcauth_unix_info_release(void *);
+extern int svcauth_unix_set_client(struct svc_rqst *rqstp);
 
 static inline unsigned long hash_str(char *name, int bits)
 {
diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h
index 5a5db16..417a1de 100644
--- a/include/linux/sunrpc/svcauth_gss.h
+++ b/include/linux/sunrpc/svcauth_gss.h
@@ -22,6 +22,7 @@
 int gss_svc_init(void);
 void gss_svc_shutdown(void);
 int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
+u32 svcauth_gss_flavor(struct auth_domain *dom);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index e21dd93..a53e0fa 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -59,6 +59,7 @@
 	/* cache of various info for TCP sockets */
 	void			*sk_info_authunix;
 
+	struct sockaddr_storage	sk_local;	/* local address */
 	struct sockaddr_storage	sk_remote;	/* remote peer's address */
 	int			sk_remotelen;	/* length of address */
 };
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 34f7590..d11cedd 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -17,6 +17,8 @@
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/msg_prot.h>
 
+#ifdef __KERNEL__
+
 extern unsigned int xprt_udp_slot_table_entries;
 extern unsigned int xprt_tcp_slot_table_entries;
 
@@ -194,7 +196,13 @@
 	char *			address_strings[RPC_DISPLAY_MAX];
 };
 
-#ifdef __KERNEL__
+struct rpc_xprtsock_create {
+	int			proto;		/* IPPROTO_UDP or IPPROTO_TCP */
+	struct sockaddr *	srcaddr;	/* optional local address */
+	struct sockaddr *	dstaddr;	/* remote peer address */
+	size_t			addrlen;
+	struct rpc_timeout *	timeout;	/* optional timeout parameters */
+};
 
 /*
  * Transport operations used by ULPs
@@ -204,7 +212,7 @@
 /*
  * Generic internal transport functions
  */
-struct rpc_xprt *	xprt_create_transport(int proto, struct sockaddr *addr, size_t size, struct rpc_timeout *toparms);
+struct rpc_xprt *	xprt_create_transport(struct rpc_xprtsock_create *args);
 void			xprt_connect(struct rpc_task *task);
 void			xprt_reserve(struct rpc_task *task);
 int			xprt_reserve_xprt(struct rpc_task *task);
@@ -242,8 +250,8 @@
 /*
  * Socket transport setup operations
  */
-struct rpc_xprt *	xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
-struct rpc_xprt *	xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
+struct rpc_xprt *	xs_setup_udp(struct rpc_xprtsock_create *args);
+struct rpc_xprt *	xs_setup_tcp(struct rpc_xprtsock_create *args);
 int			init_socket_xprt(void);
 void			cleanup_socket_xprt(void);
 
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 0068688..665f85f 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -188,7 +188,8 @@
 extern void swap_setup(void);
 
 /* linux/mm/vmscan.c */
-extern unsigned long try_to_free_pages(struct zone **, gfp_t);
+extern unsigned long try_to_free_pages(struct zone **zones, int order,
+					gfp_t gfp_mask);
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
 extern int remove_mapping(struct address_space *mapping, struct page *page);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index b02070e..83d0ec1 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -598,6 +598,8 @@
 
 asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
 					unsigned int flags);
+asmlinkage long sys_sync_file_range2(int fd, unsigned int flags,
+				     loff_t offset, loff_t nbytes);
 asmlinkage long sys_get_robust_list(int pid,
 				    struct robust_list_head __user * __user *head_ptr,
 				    size_t __user *len_ptr);
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index e699ab2..e2857465 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -101,8 +101,7 @@
 
 #define _SYSDEV_ATTR(_name,_mode,_show,_store)			\
 {								\
-	.attr = { .name = __stringify(_name), .mode = _mode,	\
-		 .owner = THIS_MODULE },			\
+	.attr = { .name = __stringify(_name), .mode = _mode },	\
 	.show	= _show,					\
 	.store	= _store,					\
 }
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 7d5d1ec..be8228e 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -19,10 +19,15 @@
 struct module;
 struct nameidata;
 struct dentry;
+struct sysfs_dirent;
 
+/* FIXME
+ * The *owner field is no longer used, but leave around
+ * until the tree gets cleaned up fully.
+ */
 struct attribute {
 	const char		* name;
-	struct module 		* owner;
+	struct module		* owner;
 	mode_t			mode;
 };
 
@@ -39,14 +44,14 @@
  */
 
 #define __ATTR(_name,_mode,_show,_store) { \
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
 	.show	= _show,					\
 	.store	= _store,					\
 }
 
 #define __ATTR_RO(_name) { \
-	.attr	= { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE },	\
-	.show	= _name##_show,	\
+	.attr	= { .name = __stringify(_name), .mode = 0444 },	\
+	.show	= _name##_show,					\
 }
 
 #define __ATTR_NULL { .attr = { .name = NULL } }
@@ -59,8 +64,10 @@
 	struct attribute	attr;
 	size_t			size;
 	void			*private;
-	ssize_t (*read)(struct kobject *, char *, loff_t, size_t);
-	ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
+	ssize_t (*read)(struct kobject *, struct bin_attribute *,
+			char *, loff_t, size_t);
+	ssize_t (*write)(struct kobject *, struct bin_attribute *,
+			 char *, loff_t, size_t);
 	int (*mmap)(struct kobject *, struct bin_attribute *attr,
 		    struct vm_area_struct *vma);
 };
@@ -70,12 +77,16 @@
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
 };
 
+#define SYSFS_TYPE_MASK		0x00ff
 #define SYSFS_ROOT		0x0001
 #define SYSFS_DIR		0x0002
 #define SYSFS_KOBJ_ATTR 	0x0004
 #define SYSFS_KOBJ_BIN_ATTR	0x0008
 #define SYSFS_KOBJ_LINK 	0x0020
-#define SYSFS_NOT_PINNED	(SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
+#define SYSFS_COPY_NAME		(SYSFS_DIR | SYSFS_KOBJ_LINK)
+
+#define SYSFS_FLAG_MASK		~SYSFS_TYPE_MASK
+#define SYSFS_FLAG_REMOVED	0x0100
 
 #ifdef CONFIG_SYSFS
 
@@ -83,13 +94,14 @@
 		void (*func)(void *), void *data, struct module *owner);
 
 extern int __must_check
-sysfs_create_dir(struct kobject *, struct dentry *);
+sysfs_create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent_sd);
 
 extern void
 sysfs_remove_dir(struct kobject *);
 
 extern int __must_check
-sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name);
+sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
+		 const char *new_name);
 
 extern int __must_check
 sysfs_move_dir(struct kobject *, struct kobject *);
@@ -129,8 +141,8 @@
 
 extern int sysfs_make_shadowed_dir(struct kobject *kobj,
 	void * (*follow_link)(struct dentry *, struct nameidata *));
-extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj);
-extern void sysfs_remove_shadow_dir(struct dentry *dir);
+extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj);
+extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd);
 
 extern int __must_check sysfs_init(void);
 
@@ -142,7 +154,8 @@
 	return -ENOSYS;
 }
 
-static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow)
+static inline int sysfs_create_dir(struct kobject *kobj,
+				   struct sysfs_dirent *shadow_parent_sd)
 {
 	return 0;
 }
@@ -152,9 +165,9 @@
 	;
 }
 
-static inline int sysfs_rename_dir(struct kobject * k,
-					struct dentry *new_parent,
-					const char *new_name)
+static inline int sysfs_rename_dir(struct kobject *kobj,
+				   struct sysfs_dirent *new_parent_sd,
+				   const char *new_name)
 {
 	return 0;
 }
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
index 1218733..ff46c6f 100644
--- a/include/linux/task_io_accounting_ops.h
+++ b/include/linux/task_io_accounting_ops.h
@@ -4,6 +4,8 @@
 #ifndef __TASK_IO_ACCOUNTING_OPS_INCLUDED
 #define __TASK_IO_ACCOUNTING_OPS_INCLUDED
 
+#include <linux/sched.h>
+
 #ifdef CONFIG_TASK_IO_ACCOUNTING
 static inline void task_io_account_read(size_t bytes)
 {
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index a46104a..dce1ed204 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -31,7 +31,7 @@
  */
 
 
-#define TASKSTATS_VERSION	4
+#define TASKSTATS_VERSION	5
 #define TS_COMM_LEN		32	/* should be >= TASK_COMM_LEN
 					 * in linux/sched.h */
 
@@ -149,6 +149,9 @@
 	__u64	read_bytes;		/* bytes of read I/O */
 	__u64	write_bytes;		/* bytes of write I/O */
 	__u64	cancelled_write_bytes;	/* bytes of cancelled write I/O */
+
+	__u64  nvcsw;			/* voluntary_ctxt_switches */
+	__u64  nivcsw;			/* nonvoluntary_ctxt_switches */
 };
 
 
diff --git a/include/linux/time.h b/include/linux/time.h
index dda9be6..ec3b0ce 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -36,7 +36,8 @@
 #define NSEC_PER_SEC	1000000000L
 #define FSEC_PER_SEC	1000000000000000L
 
-static inline int timespec_equal(struct timespec *a, struct timespec *b)
+static inline int timespec_equal(const struct timespec *a,
+                                 const struct timespec *b)
 {
 	return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
 }
@@ -116,6 +117,8 @@
 extern unsigned int alarm_setitimer(unsigned int seconds);
 extern int do_getitimer(int which, struct itimerval *value);
 extern void getnstimeofday(struct timespec *tv);
+extern void getboottime(struct timespec *ts);
+extern void monotonic_to_bootbased(struct timespec *ts);
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 extern int timekeeping_is_continuous(void);
diff --git a/include/linux/timer.h b/include/linux/timer.h
index e0c5c16..78cf899 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -3,7 +3,6 @@
 
 #include <linux/list.h>
 #include <linux/ktime.h>
-#include <linux/spinlock.h>
 #include <linux/stddef.h>
 
 struct tvec_t_base_s;
@@ -69,6 +68,12 @@
 extern int mod_timer(struct timer_list *timer, unsigned long expires);
 
 /*
+ * The jiffies value which is added to now, when there is no timer
+ * in the timer wheel:
+ */
+#define NEXT_TIMER_MAX_DELTA	((1UL << 30) - 1)
+
+/*
  * Return when the next timer-wheel timeout occurs (in absolute jiffies),
  * locks the timer base:
  */
@@ -85,16 +90,13 @@
  */
 #ifdef CONFIG_TIMER_STATS
 
+#define TIMER_STATS_FLAG_DEFERRABLE	0x1
+
 extern void init_timer_stats(void);
 
 extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
-				     void *timerf, char * comm);
-
-static inline void timer_stats_account_timer(struct timer_list *timer)
-{
-	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
-				 timer->function, timer->start_comm);
-}
+				     void *timerf, char *comm,
+				     unsigned int timer_flag);
 
 extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
 					       void *addr);
@@ -113,10 +115,6 @@
 {
 }
 
-static inline void timer_stats_account_timer(struct timer_list *timer)
-{
-}
-
 static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
 {
 }
diff --git a/include/linux/topology.h b/include/linux/topology.h
index a9d1f04..d0890a7 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -50,10 +50,10 @@
 	for_each_online_node(node)						\
 		if (nr_cpus_node(node))
 
-#ifndef node_distance
 /* Conform to ACPI 2.0 SLIT distance definitions */
 #define LOCAL_DISTANCE		10
 #define REMOTE_DISTANCE		20
+#ifndef node_distance
 #define node_distance(from,to)	((from) == (to) ? LOCAL_DISTANCE : REMOTE_DISTANCE)
 #endif
 #ifndef RECLAIM_DISTANCE
@@ -98,7 +98,7 @@
 	.cache_nice_tries	= 0,			\
 	.busy_idx		= 0,			\
 	.idle_idx		= 0,			\
-	.newidle_idx		= 1,			\
+	.newidle_idx		= 0,			\
 	.wake_idx		= 0,			\
 	.forkexec_idx		= 0,			\
 	.flags			= SD_LOAD_BALANCE	\
@@ -128,14 +128,15 @@
 	.imbalance_pct		= 125,			\
 	.cache_nice_tries	= 1,			\
 	.busy_idx		= 2,			\
-	.idle_idx		= 1,			\
-	.newidle_idx		= 2,			\
+	.idle_idx		= 0,			\
+	.newidle_idx		= 0,			\
 	.wake_idx		= 1,			\
 	.forkexec_idx		= 1,			\
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_NEWIDLE	\
 				| SD_BALANCE_EXEC	\
 				| SD_WAKE_AFFINE	\
+				| SD_WAKE_IDLE		\
 				| SD_SHARE_PKG_RESOURCES\
 				| BALANCE_FOR_MC_POWER,	\
 	.last_balance		= jiffies,		\
@@ -158,14 +159,15 @@
 	.imbalance_pct		= 125,			\
 	.cache_nice_tries	= 1,			\
 	.busy_idx		= 2,			\
-	.idle_idx		= 1,			\
-	.newidle_idx		= 2,			\
+	.idle_idx		= 0,			\
+	.newidle_idx		= 0,			\
 	.wake_idx		= 1,			\
 	.forkexec_idx		= 1,			\
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_NEWIDLE	\
 				| SD_BALANCE_EXEC	\
 				| SD_WAKE_AFFINE	\
+				| SD_WAKE_IDLE		\
 				| BALANCE_FOR_PKG_POWER,\
 	.last_balance		= jiffies,		\
 	.balance_interval	= 1,			\
diff --git a/include/linux/tty.h b/include/linux/tty.h
index bb45760..691a174 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -178,6 +178,7 @@
 #define L_IEXTEN(tty)	_L_FLAG((tty),IEXTEN)
 
 struct device;
+struct signal_struct;
 /*
  * Where all of the state associated with a tty is kept while the tty
  * is open.  Since the termios state should be kept even if the tty
@@ -310,6 +311,7 @@
 extern void tty_vhangup(struct tty_struct * tty);
 extern void tty_unhangup(struct file *filp);
 extern int tty_hung_up_p(struct file * filp);
+extern int is_tty(struct file *filp);
 extern void do_SAK(struct tty_struct *tty);
 extern void __do_SAK(struct tty_struct *tty);
 extern void disassociate_ctty(int priv);
@@ -338,9 +340,46 @@
 
 extern struct mutex tty_mutex;
 
+extern void tty_write_unlock(struct tty_struct *tty);
+extern int tty_write_lock(struct tty_struct *tty, int ndelay);
+#define tty_is_writelocked(tty)  (mutex_is_locked(&tty->atomic_write_lock))
+
+
+
 /* n_tty.c */
 extern struct tty_ldisc tty_ldisc_N_TTY;
 
+/* tty_audit.c */
+#ifdef CONFIG_AUDIT
+extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+			       size_t size);
+extern void tty_audit_exit(void);
+extern void tty_audit_fork(struct signal_struct *sig);
+extern void tty_audit_push(struct tty_struct *tty);
+extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid);
+extern void tty_audit_opening(void);
+#else
+static inline void tty_audit_add_data(struct tty_struct *tty,
+				      unsigned char *data, size_t size)
+{
+}
+static inline void tty_audit_exit(void)
+{
+}
+static inline void tty_audit_fork(struct signal_struct *sig)
+{
+}
+static inline void tty_audit_push(struct tty_struct *tty)
+{
+}
+static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+{
+}
+static inline void tty_audit_opening(void)
+{
+}
+#endif
+
 /* tty_ioctl.c */
 extern int n_tty_ioctl(struct tty_struct * tty, struct file * file,
 		       unsigned int cmd, unsigned long arg);
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 6de445c..8ec703f 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -42,6 +42,7 @@
 /* UDP encapsulation types */
 #define UDP_ENCAP_ESPINUDP_NON_IKE	1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
 #define UDP_ENCAP_ESPINUDP	2 /* draft-ietf-ipsec-udp-encaps-06 */
+#define UDP_ENCAP_L2TPINUDP	3 /* rfc2661 */
 
 #ifdef __KERNEL__
 #include <linux/types.h>
@@ -70,6 +71,11 @@
 #define UDPLITE_SEND_CC  0x2  		/* set via udplite setsockopt         */
 #define UDPLITE_RECV_CC  0x4		/* set via udplite setsocktopt        */
 	__u8		 pcflag;        /* marks socket as UDP-Lite if > 0    */
+	__u8		 unused[3];
+	/*
+	 * For encapsulation sockets.
+	 */
+	int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
 };
 
 static inline struct udp_sock *udp_sk(const struct sock *sk)
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 9af8bbc..b7fe138 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -13,10 +13,6 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-
-/* A word of warning: Our uio structure will clash with the C library one (which is now obsolete). Remove the C
-   library one from sys/uio.h if you have a very old library set */
-
 struct iovec
 {
 	void __user *iov_base;	/* BSD uses caddr_t (1003.1g requires void *) */
@@ -38,11 +34,6 @@
  
 #define UIO_FASTIOV	8
 #define UIO_MAXIOV	1024
-#if 0
-#define UIO_MAXIOV	16	/* Maximum iovec's in one operation 
-				   16 matches BSD */
-                                /* Beg pardon: BSD has 1024 --ANK */
-#endif
 
 /*
  * Total number of bytes covered by an iovec.
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 94bd38a..7a60946 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -146,6 +146,10 @@
 					 * active alternate setting */
 	unsigned num_altsetting;	/* number of alternate settings */
 
+	/* If there is an interface association descriptor then it will list
+	 * the associated interfaces */
+	struct usb_interface_assoc_descriptor *intf_assoc;
+
 	int minor;			/* minor number this interface is
 					 * bound to */
 	enum usb_interface_condition condition;		/* state of binding */
@@ -175,6 +179,7 @@
 
 /* this maximum is arbitrary */
 #define USB_MAXINTERFACES	32
+#define USB_MAXIADS		USB_MAXINTERFACES/2
 
 /**
  * struct usb_interface_cache - long-term representation of a device interface
@@ -245,6 +250,11 @@
 	struct usb_config_descriptor	desc;
 
 	char *string;		/* iConfiguration string, if present */
+
+	/* List of any Interface Association Descriptors in this
+	 * configuration. */
+	struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
+
 	/* the interfaces associated with this configuration,
 	 * stored in no particular order */
 	struct usb_interface *interface[USB_MAXINTERFACES];
@@ -403,6 +413,8 @@
 
 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
+	unsigned reset_resume:1;	/* needs reset instead of resume */
+	unsigned persist_enabled:1;	/* USB_PERSIST enabled for this dev */
 	unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
 	unsigned autoresume_disabled:1;  /*  disabled by the user */
 #endif
@@ -729,6 +741,22 @@
 	.bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
 
 /**
+ * USB_DEVICE_INTERFACE_PROTOCOL - macro used to describe a usb
+ *		device with a specific interface protocol
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific interface protocol of devices.
+ */
+#define USB_DEVICE_INTERFACE_PROTOCOL(vend,prod,pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+	.idVendor = (vend), \
+	.idProduct = (prod), \
+	.bInterfaceProtocol = (pr)
+
+/**
  * USB_DEVICE_INFO - macro used to describe a class of usb devices
  * @cl: bDeviceClass value
  * @sc: bDeviceSubClass value
@@ -754,6 +782,28 @@
 	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
 	.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
 
+/**
+ * USB_DEVICE_AND_INTERFACE_INFO - macro used to describe a specific usb device
+ * 		with a class of usb interfaces
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @cl: bInterfaceClass value
+ * @sc: bInterfaceSubClass value
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific device with a specific class of interfaces.
+ *
+ * This is especially useful when explicitly matching devices that have
+ * vendor specific bDeviceClass values, but standards-compliant interfaces.
+ */
+#define USB_DEVICE_AND_INTERFACE_INFO(vend,prod,cl,sc,pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+		| USB_DEVICE_ID_MATCH_DEVICE, \
+	.idVendor = (vend), .idProduct = (prod), \
+	.bInterfaceClass = (cl), \
+	.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+
 /* ----------------------------------------------------------------------- */
 
 /* Stuff for dynamic usb ids */
@@ -800,10 +850,15 @@
  *	do (or don't) show up otherwise in the filesystem.
  * @suspend: Called when the device is going to be suspended by the system.
  * @resume: Called when the device is being resumed by the system.
+ * @reset_resume: Called when the suspended device has been reset instead
+ *	of being resumed.
  * @pre_reset: Called by usb_reset_composite_device() when the device
  *	is about to be reset.
  * @post_reset: Called by usb_reset_composite_device() after the device
- *	has been reset.
+ *	has been reset, or in lieu of @resume following a reset-resume
+ *	(i.e., the device is reset instead of being resumed, as might
+ *	happen if power was lost).  The second argument tells which is
+ *	the reason.
  * @id_table: USB drivers use ID table to support hotplugging.
  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
  *	or your driver's probe function will never get called.
@@ -843,9 +898,10 @@
 
 	int (*suspend) (struct usb_interface *intf, pm_message_t message);
 	int (*resume) (struct usb_interface *intf);
+	int (*reset_resume)(struct usb_interface *intf);
 
-	void (*pre_reset) (struct usb_interface *intf);
-	void (*post_reset) (struct usb_interface *intf);
+	int (*pre_reset)(struct usb_interface *intf);
+	int (*post_reset)(struct usb_interface *intf);
 
 	const struct usb_device_id *id_table;
 
@@ -948,6 +1004,7 @@
 #define URB_ZERO_PACKET		0x0040	/* Finish bulk OUT with short packet */
 #define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt
 					 * needed */
+#define URB_FREE_BUFFER		0x0100	/* Free transfer buffer with the URB */
 
 struct usb_iso_packet_descriptor {
 	unsigned int offset;
@@ -958,11 +1015,26 @@
 
 struct urb;
 
+struct usb_anchor {
+	struct list_head urb_list;
+	wait_queue_head_t wait;
+	spinlock_t lock;
+};
+
+static inline void init_usb_anchor(struct usb_anchor *anchor)
+{
+	INIT_LIST_HEAD(&anchor->urb_list);
+	init_waitqueue_head(&anchor->wait);
+	spin_lock_init(&anchor->lock);
+}
+
 typedef void (*usb_complete_t)(struct urb *);
 
 /**
  * struct urb - USB Request Block
  * @urb_list: For use by current owner of the URB.
+ * @anchor_list: membership in the list of an anchor
+ * @anchor: to anchor URBs to a common mooring
  * @pipe: Holds endpoint number, direction, type, and more.
  *	Create these values with the eight macros available;
  *	usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
@@ -1135,6 +1207,8 @@
 	/* public: documented fields in the urb that can be used by drivers */
 	struct list_head urb_list;	/* list head for use by the urb's
 					 * current owner */
+	struct list_head anchor_list;	/* the URB may be anchored by the driver */
+	struct usb_anchor *anchor;
 	struct usb_device *dev; 	/* (in) pointer to associated device */
 	unsigned int pipe;		/* (in) pipe information */
 	int status;			/* (return) non-ISO status */
@@ -1270,6 +1344,11 @@
 extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
+extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
+extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);
+extern void usb_unanchor_urb(struct urb *urb);
+extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+					 unsigned int timeout);
 
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
 	gfp_t mem_flags, dma_addr_t *dma);
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index 43f160c..6ce42bf 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -1,5 +1,6 @@
 unifdef-y += audio.h
 unifdef-y += cdc.h
 unifdef-y += ch9.h
+unifdef-y += gadgetfs.h
 unifdef-y += midi.h
 
diff --git a/include/linux/usb/gadgetfs.h b/include/linux/usb/gadgetfs.h
new file mode 100644
index 0000000..e8654c3
--- /dev/null
+++ b/include/linux/usb/gadgetfs.h
@@ -0,0 +1,81 @@
+#ifndef __LINUX_USB_GADGETFS_H
+#define __LINUX_USB_GADGETFS_H
+
+#include <asm/types.h>
+#include <asm/ioctl.h>
+
+#include <linux/usb/ch9.h>
+
+/*
+ * Filesystem based user-mode API to USB Gadget controller hardware
+ *
+ * Other than ep0 operations, most things are done by read() and write()
+ * on endpoint files found in one directory.  They are configured by
+ * writing descriptors, and then may be used for normal stream style
+ * i/o requests.  When ep0 is configured, the device can enumerate;
+ * when it's closed, the device disconnects from usb.  Operations on
+ * ep0 require ioctl() operations.
+ *
+ * Configuration and device descriptors get written to /dev/gadget/$CHIP,
+ * which may then be used to read usb_gadgetfs_event structs.  The driver
+ * may activate endpoints as it handles SET_CONFIGURATION setup events,
+ * or earlier; writing endpoint descriptors to /dev/gadget/$ENDPOINT
+ * then performing data transfers by reading or writing.
+ */
+
+/*
+ * Events are delivered on the ep0 file descriptor, when the user mode driver
+ * reads from this file descriptor after writing the descriptors.  Don't
+ * stop polling this descriptor.
+ */
+
+enum usb_gadgetfs_event_type {
+	GADGETFS_NOP = 0,
+
+	GADGETFS_CONNECT,
+	GADGETFS_DISCONNECT,
+	GADGETFS_SETUP,
+	GADGETFS_SUSPEND,
+	// and likely more !
+};
+
+/* NOTE:  this structure must stay the same size and layout on
+ * both 32-bit and 64-bit kernels.
+ */
+struct usb_gadgetfs_event {
+	union {
+		// NOP, DISCONNECT, SUSPEND: nothing
+		// ... some hardware can't report disconnection
+
+		// CONNECT: just the speed
+		enum usb_device_speed	speed;
+
+		// SETUP: packet; DATA phase i/o precedes next event
+		// (setup.bmRequestType & USB_DIR_IN) flags direction
+		// ... includes SET_CONFIGURATION, SET_INTERFACE
+		struct usb_ctrlrequest	setup;
+	} u;
+	enum usb_gadgetfs_event_type	type;
+};
+
+
+/* endpoint ioctls */
+
+/* IN transfers may be reported to the gadget driver as complete
+ *	when the fifo is loaded, before the host reads the data;
+ * OUT transfers may be reported to the host's "client" driver as
+ *	complete when they're sitting in the FIFO unread.
+ * THIS returns how many bytes are "unclaimed" in the endpoint fifo
+ * (needed for precise fault handling, when the hardware allows it)
+ */
+#define	GADGETFS_FIFO_STATUS	_IO('g',1)
+
+/* discards any unclaimed data in the fifo. */
+#define	GADGETFS_FIFO_FLUSH	_IO('g',2)
+
+/* resets endpoint halt+toggle; used to implement set_interface.
+ * some hardware (like pxa2xx) can't support this.
+ */
+#define	GADGETFS_CLEAR_HALT	_IO('g',3)
+
+#endif /* __LINUX_USB_GADGETFS_H */
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 6bac8fa..8da374c 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -9,3 +9,6 @@
 
 /* string descriptors must not be fetched using a 255-byte read */
 #define USB_QUIRK_STRING_FETCH_255	0x00000002
+
+/* device can't resume correctly so reset it instead */
+#define USB_QUIRK_RESET_RESUME		0x00000004
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 32acbae..e8b8928 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -221,6 +221,9 @@
 	int (*port_probe) (struct usb_serial_port *port);
 	int (*port_remove) (struct usb_serial_port *port);
 
+	int (*suspend) (struct usb_serial *serial, pm_message_t message);
+	int (*resume) (struct usb_serial *serial);
+
 	/* serial function calls */
 	int  (*open)		(struct usb_serial_port *port, struct file * filp);
 	void (*close)		(struct usb_serial_port *port, struct file * filp);
@@ -249,6 +252,9 @@
 extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
 extern void usb_serial_disconnect(struct usb_interface *iface);
 
+extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
+extern int usb_serial_resume(struct usb_interface *intf);
+
 extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest);
 extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
 
@@ -269,6 +275,7 @@
 extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
 extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_resume (struct usb_serial *serial);
 extern int usb_serial_generic_write_room (struct usb_serial_port *port);
 extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
 extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h
index e17186d..4f59b2a 100644
--- a/include/linux/usb_gadget.h
+++ b/include/linux/usb_gadget.h
@@ -110,13 +110,6 @@
 		gfp_t gfp_flags);
 	void (*free_request) (struct usb_ep *ep, struct usb_request *req);
 
-	void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
-		dma_addr_t *dma, gfp_t gfp_flags);
-	void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
-		unsigned bytes);
-	// NOTE:  on 2.6, drivers may also use dma_map() and
-	// dma_sync_single_*() to directly manage dma overhead. 
-
 	int (*queue) (struct usb_ep *ep, struct usb_request *req,
 		gfp_t gfp_flags);
 	int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
@@ -235,47 +228,6 @@
 }
 
 /**
- * usb_ep_alloc_buffer - allocate an I/O buffer
- * @ep:the endpoint associated with the buffer
- * @len:length of the desired buffer
- * @dma:pointer to the buffer's DMA address; must be valid
- * @gfp_flags:GFP_* flags to use
- *
- * Returns a new buffer, or null if one could not be allocated.
- * The buffer is suitably aligned for dma, if that endpoint uses DMA,
- * and the caller won't have to care about dma-inconsistency
- * or any hidden "bounce buffer" mechanism.  No additional per-request
- * DMA mapping will be required for such buffers.
- * Free it later with usb_ep_free_buffer().
- *
- * You don't need to use this call to allocate I/O buffers unless you
- * want to make sure drivers don't incur costs for such "bounce buffer"
- * copies or per-request DMA mappings.
- */
-static inline void *
-usb_ep_alloc_buffer (struct usb_ep *ep, unsigned len, dma_addr_t *dma,
-	gfp_t gfp_flags)
-{
-	return ep->ops->alloc_buffer (ep, len, dma, gfp_flags);
-}
-
-/**
- * usb_ep_free_buffer - frees an i/o buffer
- * @ep:the endpoint associated with the buffer
- * @buf:CPU view address of the buffer
- * @dma:the buffer's DMA address
- * @len:length of the buffer
- *
- * reverses the effect of usb_ep_alloc_buffer().
- * caller guarantees the buffer will no longer be accessed
- */
-static inline void
-usb_ep_free_buffer (struct usb_ep *ep, void *buf, dma_addr_t dma, unsigned len)
-{
-	ep->ops->free_buffer (ep, buf, dma, len);
-}
-
-/**
  * usb_ep_queue - queues (submits) an I/O request to an endpoint.
  * @ep:the endpoint associated with the request
  * @req:the request being submitted
diff --git a/include/linux/usb_gadgetfs.h b/include/linux/usb_gadgetfs.h
deleted file mode 100644
index 8086d5a..0000000
--- a/include/linux/usb_gadgetfs.h
+++ /dev/null
@@ -1,75 +0,0 @@
-
-#include <asm/types.h>
-#include <asm/ioctl.h>
-
-#include <linux/usb/ch9.h>
-
-/*
- * Filesystem based user-mode API to USB Gadget controller hardware
- *
- * Almost everything can be done with only read and write operations,
- * on endpoint files found in one directory.  They are configured by
- * writing descriptors, and then may be used for normal stream style
- * i/o requests.  When ep0 is configured, the device can enumerate;
- * when it's closed, the device disconnects from usb.
- *
- * Configuration and device descriptors get written to /dev/gadget/$CHIP,
- * which may then be used to read usb_gadgetfs_event structs.  The driver
- * may activate endpoints as it handles SET_CONFIGURATION setup events,
- * or earlier; writing endpoint descriptors to /dev/gadget/$ENDPOINT
- * then performing data transfers by reading or writing.
- */
-
-/*
- * Events are delivered on the ep0 file descriptor, if the user mode driver
- * reads from this file descriptor after writing the descriptors.  Don't
- * stop polling this descriptor, if you write that kind of driver.
- */
-
-enum usb_gadgetfs_event_type {
-	GADGETFS_NOP = 0,
-
-	GADGETFS_CONNECT,
-	GADGETFS_DISCONNECT,
-	GADGETFS_SETUP,
-	GADGETFS_SUSPEND,
-	// and likely more !
-};
-
-struct usb_gadgetfs_event {
-	enum usb_gadgetfs_event_type	type;
-	union {
-		// NOP, DISCONNECT, SUSPEND: nothing
-		// ... some hardware can't report disconnection
-
-		// CONNECT: just the speed
-		enum usb_device_speed	speed;
-
-		// SETUP: packet; DATA phase i/o precedes next event
-		// (setup.bmRequestType & USB_DIR_IN) flags direction 
-		// ... includes SET_CONFIGURATION, SET_INTERFACE
-		struct usb_ctrlrequest	setup;
-	} u;
-};
-
-
-/* endpoint ioctls */
-
-/* IN transfers may be reported to the gadget driver as complete
- * 	when the fifo is loaded, before the host reads the data;
- * OUT transfers may be reported to the host's "client" driver as
- * 	complete when they're sitting in the FIFO unread.
- * THIS returns how many bytes are "unclaimed" in the endpoint fifo
- * (needed for precise fault handling, when the hardware allows it)
- */
-#define	GADGETFS_FIFO_STATUS	_IO('g',1)
-
-/* discards any unclaimed data in the fifo. */
-#define	GADGETFS_FIFO_FLUSH	_IO('g',2)
-
-/* resets endpoint halt+toggle; used to implement set_interface.
- * some hardware (like pxa2xx) can't support this.
- */
-#define	GADGETFS_CLEAR_HALT	_IO('g',3)
-
-
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
new file mode 100644
index 0000000..bb32057
--- /dev/null
+++ b/include/linux/user_namespace.h
@@ -0,0 +1,61 @@
+#ifndef _LINUX_USER_NAMESPACE_H
+#define _LINUX_USER_NAMESPACE_H
+
+#include <linux/kref.h>
+#include <linux/nsproxy.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+
+#define UIDHASH_BITS	(CONFIG_BASE_SMALL ? 3 : 8)
+#define UIDHASH_SZ	(1 << UIDHASH_BITS)
+
+struct user_namespace {
+	struct kref		kref;
+	struct list_head	uidhash_table[UIDHASH_SZ];
+	struct user_struct	*root_user;
+};
+
+extern struct user_namespace init_user_ns;
+
+#ifdef CONFIG_USER_NS
+
+static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
+{
+	if (ns)
+		kref_get(&ns->kref);
+	return ns;
+}
+
+extern struct user_namespace *copy_user_ns(int flags,
+					   struct user_namespace *old_ns);
+extern void free_user_ns(struct kref *kref);
+
+static inline void put_user_ns(struct user_namespace *ns)
+{
+	if (ns)
+		kref_put(&ns->kref, free_user_ns);
+}
+
+#else
+
+static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
+{
+	return &init_user_ns;
+}
+
+static inline struct user_namespace *copy_user_ns(int flags,
+						  struct user_namespace *old_ns)
+{
+	if (flags & CLONE_NEWUSER)
+		return ERR_PTR(-EINVAL);
+
+	return NULL;
+}
+
+static inline void put_user_ns(struct user_namespace *ns)
+{
+}
+
+#endif
+
+#endif /* _LINUX_USER_H */
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index f8d3b32..923db99 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -48,26 +48,14 @@
 	kref_get(&ns->kref);
 }
 
-#ifdef CONFIG_UTS_NS
-extern struct uts_namespace *copy_utsname(int flags, struct uts_namespace *ns);
+extern struct uts_namespace *copy_utsname(unsigned long flags,
+					struct uts_namespace *ns);
 extern void free_uts_ns(struct kref *kref);
 
 static inline void put_uts_ns(struct uts_namespace *ns)
 {
 	kref_put(&ns->kref, free_uts_ns);
 }
-#else
-static inline struct uts_namespace *copy_utsname(int flags,
-						struct uts_namespace *ns)
-{
-	return ns;
-}
-
-static inline void put_uts_ns(struct uts_namespace *ns)
-{
-}
-#endif
-
 static inline struct new_utsname *utsname(void)
 {
 	return &current->nsproxy->uts_ns->name;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index a25c2af..d16a2b5 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -243,8 +243,7 @@
 #define V4L2_CAP_SLICED_VBI_CAPTURE	0x00000040  /* Is a sliced VBI capture device */
 #define V4L2_CAP_SLICED_VBI_OUTPUT	0x00000080  /* Is a sliced VBI output device */
 #define V4L2_CAP_RDS_CAPTURE		0x00000100  /* RDS data capture */
-#define V4L2_CAP_VIDEO_OUTPUT_POS       0x00000200  /* Video output can have x,y coords */
-#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY	0x00000400  /* Can do video output overlay */
+#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY	0x00000200  /* Can do video output overlay */
 
 #define V4L2_CAP_TUNER			0x00010000  /* has a tuner */
 #define V4L2_CAP_AUDIO			0x00020000  /* has audio support */
@@ -267,8 +266,6 @@
 	__u32          		sizeimage;
 	enum v4l2_colorspace	colorspace;
 	__u32			priv;		/* private data, depends on pixelformat */
-	__u32 			left;	/* only valid if V4L2_CAP_VIDEO_OUTPUT_POS is set */
-	__u32 			top;	/* only valid if V4L2_CAP_VIDEO_OUTPUT_POS is set */
 };
 
 /*      Pixel format         FOURCC                        depth  Description  */
@@ -618,12 +615,16 @@
 #define V4L2_FBUF_CAP_BITMAP_CLIPPING	0x0008
 #define V4L2_FBUF_CAP_LOCAL_ALPHA	0x0010
 #define V4L2_FBUF_CAP_GLOBAL_ALPHA	0x0020
+#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA	0x0040
+#define V4L2_FBUF_CAP_GLOBAL_INV_ALPHA	0x0080
 /*  Flags for the 'flags' field. */
 #define V4L2_FBUF_FLAG_PRIMARY		0x0001
 #define V4L2_FBUF_FLAG_OVERLAY		0x0002
 #define V4L2_FBUF_FLAG_CHROMAKEY	0x0004
 #define V4L2_FBUF_FLAG_LOCAL_ALPHA	0x0008
 #define V4L2_FBUF_FLAG_GLOBAL_ALPHA	0x0010
+#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA	0x0020
+#define V4L2_FBUF_FLAG_GLOBAL_INV_ALPHA	0x0040
 
 struct v4l2_clip
 {
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 4b7ee83..132b260 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -65,9 +65,10 @@
 					  unsigned long flags, int node,
 					  gfp_t gfp_mask);
 extern struct vm_struct *remove_vm_area(void *addr);
+
 extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
 			struct page ***pages);
-extern void unmap_vm_area(struct vm_struct *area);
+extern void unmap_kernel_range(unsigned long addr, unsigned long size);
 
 /*
  *	Internals.  Dont't use..
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index d9325cf..75370ec 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -25,7 +25,7 @@
 #define HIGHMEM_ZONE(xx)
 #endif
 
-#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx)
+#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx) , xx##_MOVABLE
 
 enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 		FOR_ALL_ZONES(PGALLOC),
@@ -170,7 +170,8 @@
 #ifdef CONFIG_HIGHMEM
 		zone_page_state(&zones[ZONE_HIGHMEM], item) +
 #endif
-		zone_page_state(&zones[ZONE_NORMAL], item);
+		zone_page_state(&zones[ZONE_NORMAL], item) +
+		zone_page_state(&zones[ZONE_MOVABLE], item);
 }
 
 extern void zone_statistics(struct zonelist *, struct zone *);
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index d961635..699b7e9 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -75,6 +75,8 @@
 int vt_waitactive(int vt);
 void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
+extern int unbind_con_driver(const struct consw *csw, int first, int last,
+			     int deflt);
 
 /*
  * vc_screen.c shares this temporary buffer with the console write code so that
diff --git a/include/linux/wait.h b/include/linux/wait.h
index e820d00..0e68628 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -366,15 +366,15 @@
 
 /*
  * These are the old interfaces to sleep waiting for an event.
- * They are racy.  DO NOT use them, use the wait_event* interfaces above.  
- * We plan to remove these interfaces during 2.7.
+ * They are racy.  DO NOT use them, use the wait_event* interfaces above.
+ * We plan to remove these interfaces.
  */
-extern void FASTCALL(sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
-				      signed long timeout));
-extern void FASTCALL(interruptible_sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t *q,
-						    signed long timeout));
+extern void sleep_on(wait_queue_head_t *q);
+extern long sleep_on_timeout(wait_queue_head_t *q,
+				      signed long timeout);
+extern void interruptible_sleep_on(wait_queue_head_t *q);
+extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,
+					   signed long timeout);
 
 /*
  * Waitqueues which are removed from the waitqueue_head at wakeup time
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index ce0719a..ce6badc 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -148,7 +148,7 @@
 extern void init_workqueues(void);
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
-extern void cancel_work_sync(struct work_struct *work);
+extern int cancel_work_sync(struct work_struct *work);
 
 /*
  * Kill off a pending schedule_delayed_work().  Note that the work callback
@@ -166,14 +166,21 @@
 	return ret;
 }
 
-extern void cancel_rearming_delayed_work(struct delayed_work *work);
+extern int cancel_delayed_work_sync(struct delayed_work *work);
 
-/* Obsolete. use cancel_rearming_delayed_work() */
+/* Obsolete. use cancel_delayed_work_sync() */
 static inline
 void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
 					struct delayed_work *work)
 {
-	cancel_rearming_delayed_work(work);
+	cancel_delayed_work_sync(work);
+}
+
+/* Obsolete. use cancel_delayed_work_sync() */
+static inline
+void cancel_rearming_delayed_work(struct delayed_work *work)
+{
+	cancel_delayed_work_sync(work);
 }
 
 #endif
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 050915b..4ef4d22 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -4,6 +4,8 @@
 #ifndef WRITEBACK_H
 #define WRITEBACK_H
 
+#include <linux/sched.h>
+
 struct backing_dev_info;
 
 extern spinlock_t inode_lock;
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
new file mode 100644
index 0000000..88884d3
--- /dev/null
+++ b/include/net/9p/9p.h
@@ -0,0 +1,417 @@
+/*
+ * include/net/9p/9p.h
+ *
+ * 9P protocol definitions.
+ *
+ *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#ifndef NET_9P_H
+#define NET_9P_H
+
+#ifdef CONFIG_NET_9P_DEBUG
+
+#define P9_DEBUG_ERROR		(1<<0)
+#define P9_DEBUG_9P	        (1<<2)
+#define P9_DEBUG_VFS	        (1<<3)
+#define P9_DEBUG_CONV		(1<<4)
+#define P9_DEBUG_MUX		(1<<5)
+#define P9_DEBUG_TRANS		(1<<6)
+#define P9_DEBUG_SLABS	      	(1<<7)
+#define P9_DEBUG_FCALL		(1<<8)
+
+extern unsigned int p9_debug_level;
+
+#define P9_DPRINTK(level, format, arg...) \
+do {  \
+	if ((p9_debug_level & level) == level) \
+		printk(KERN_NOTICE "-- %s (%d): " \
+		format , __FUNCTION__, current->pid , ## arg); \
+} while (0)
+
+#define PRINT_FCALL_ERROR(s, fcall) P9_DPRINTK(P9_DEBUG_ERROR,   \
+	"%s: %.*s\n", s, fcall?fcall->params.rerror.error.len:0, \
+	fcall?fcall->params.rerror.error.str:"");
+
+#else
+#define P9_DPRINTK(level, format, arg...)  do { } while (0)
+#define PRINT_FCALL_ERROR(s, fcall) do { } while (0)
+#endif
+
+#define P9_EPRINTK(level, format, arg...) \
+do { \
+	printk(level "9p: %s (%d): " \
+		format , __FUNCTION__, current->pid , ## arg); \
+} while (0)
+
+
+/* Message Types */
+enum {
+	P9_TVERSION = 100,
+	P9_RVERSION,
+	P9_TAUTH = 102,
+	P9_RAUTH,
+	P9_TATTACH = 104,
+	P9_RATTACH,
+	P9_TERROR = 106,
+	P9_RERROR,
+	P9_TFLUSH = 108,
+	P9_RFLUSH,
+	P9_TWALK = 110,
+	P9_RWALK,
+	P9_TOPEN = 112,
+	P9_ROPEN,
+	P9_TCREATE = 114,
+	P9_RCREATE,
+	P9_TREAD = 116,
+	P9_RREAD,
+	P9_TWRITE = 118,
+	P9_RWRITE,
+	P9_TCLUNK = 120,
+	P9_RCLUNK,
+	P9_TREMOVE = 122,
+	P9_RREMOVE,
+	P9_TSTAT = 124,
+	P9_RSTAT,
+	P9_TWSTAT = 126,
+	P9_RWSTAT,
+};
+
+/* open modes */
+enum {
+	P9_OREAD = 0x00,
+	P9_OWRITE = 0x01,
+	P9_ORDWR = 0x02,
+	P9_OEXEC = 0x03,
+	P9_OEXCL = 0x04,
+	P9_OTRUNC = 0x10,
+	P9_OREXEC = 0x20,
+	P9_ORCLOSE = 0x40,
+	P9_OAPPEND = 0x80,
+};
+
+/* permissions */
+enum {
+	P9_DMDIR = 0x80000000,
+	P9_DMAPPEND = 0x40000000,
+	P9_DMEXCL = 0x20000000,
+	P9_DMMOUNT = 0x10000000,
+	P9_DMAUTH = 0x08000000,
+	P9_DMTMP = 0x04000000,
+	P9_DMSYMLINK = 0x02000000,
+	P9_DMLINK = 0x01000000,
+	/* 9P2000.u extensions */
+	P9_DMDEVICE = 0x00800000,
+	P9_DMNAMEDPIPE = 0x00200000,
+	P9_DMSOCKET = 0x00100000,
+	P9_DMSETUID = 0x00080000,
+	P9_DMSETGID = 0x00040000,
+};
+
+/* qid.types */
+enum {
+	P9_QTDIR = 0x80,
+	P9_QTAPPEND = 0x40,
+	P9_QTEXCL = 0x20,
+	P9_QTMOUNT = 0x10,
+	P9_QTAUTH = 0x08,
+	P9_QTTMP = 0x04,
+	P9_QTSYMLINK = 0x02,
+	P9_QTLINK = 0x01,
+	P9_QTFILE = 0x00,
+};
+
+#define P9_NOTAG	(u16)(~0)
+#define P9_NOFID	(u32)(~0)
+#define P9_MAXWELEM	16
+
+/* ample room for Twrite/Rread header */
+#define P9_IOHDRSZ	24
+
+struct p9_str {
+	u16 len;
+	char *str;
+};
+
+/* qids are the unique ID for a file (like an inode */
+struct p9_qid {
+	u8 type;
+	u32 version;
+	u64 path;
+};
+
+/* Plan 9 file metadata (stat) structure */
+struct p9_stat {
+	u16 size;
+	u16 type;
+	u32 dev;
+	struct p9_qid qid;
+	u32 mode;
+	u32 atime;
+	u32 mtime;
+	u64 length;
+	struct p9_str name;
+	struct p9_str uid;
+	struct p9_str gid;
+	struct p9_str muid;
+	struct p9_str extension;	/* 9p2000.u extensions */
+	u32 n_uid;			/* 9p2000.u extensions */
+	u32 n_gid;			/* 9p2000.u extensions */
+	u32 n_muid;			/* 9p2000.u extensions */
+};
+
+/* file metadata (stat) structure used to create Twstat message
+   The is similar to p9_stat, but the strings don't point to
+   the same memory block and should be freed separately
+*/
+struct p9_wstat {
+	u16 size;
+	u16 type;
+	u32 dev;
+	struct p9_qid qid;
+	u32 mode;
+	u32 atime;
+	u32 mtime;
+	u64 length;
+	char *name;
+	char *uid;
+	char *gid;
+	char *muid;
+	char *extension;	/* 9p2000.u extensions */
+	u32 n_uid;		/* 9p2000.u extensions */
+	u32 n_gid;		/* 9p2000.u extensions */
+	u32 n_muid;		/* 9p2000.u extensions */
+};
+
+/* Structures for Protocol Operations */
+struct p9_tversion {
+	u32 msize;
+	struct p9_str version;
+};
+
+struct p9_rversion {
+	u32 msize;
+	struct p9_str version;
+};
+
+struct p9_tauth {
+	u32 afid;
+	struct p9_str uname;
+	struct p9_str aname;
+};
+
+struct p9_rauth {
+	struct p9_qid qid;
+};
+
+struct p9_rerror {
+	struct p9_str error;
+	u32 errno;		/* 9p2000.u extension */
+};
+
+struct p9_tflush {
+	u16 oldtag;
+};
+
+struct p9_rflush {
+};
+
+struct p9_tattach {
+	u32 fid;
+	u32 afid;
+	struct p9_str uname;
+	struct p9_str aname;
+};
+
+struct p9_rattach {
+	struct p9_qid qid;
+};
+
+struct p9_twalk {
+	u32 fid;
+	u32 newfid;
+	u16 nwname;
+	struct p9_str wnames[16];
+};
+
+struct p9_rwalk {
+	u16 nwqid;
+	struct p9_qid wqids[16];
+};
+
+struct p9_topen {
+	u32 fid;
+	u8 mode;
+};
+
+struct p9_ropen {
+	struct p9_qid qid;
+	u32 iounit;
+};
+
+struct p9_tcreate {
+	u32 fid;
+	struct p9_str name;
+	u32 perm;
+	u8 mode;
+	struct p9_str extension;
+};
+
+struct p9_rcreate {
+	struct p9_qid qid;
+	u32 iounit;
+};
+
+struct p9_tread {
+	u32 fid;
+	u64 offset;
+	u32 count;
+};
+
+struct p9_rread {
+	u32 count;
+	u8 *data;
+};
+
+struct p9_twrite {
+	u32 fid;
+	u64 offset;
+	u32 count;
+	u8 *data;
+};
+
+struct p9_rwrite {
+	u32 count;
+};
+
+struct p9_tclunk {
+	u32 fid;
+};
+
+struct p9_rclunk {
+};
+
+struct p9_tremove {
+	u32 fid;
+};
+
+struct p9_rremove {
+};
+
+struct p9_tstat {
+	u32 fid;
+};
+
+struct p9_rstat {
+	struct p9_stat stat;
+};
+
+struct p9_twstat {
+	u32 fid;
+	struct p9_stat stat;
+};
+
+struct p9_rwstat {
+};
+
+/*
+  * fcall is the primary packet structure
+  *
+  */
+
+struct p9_fcall {
+	u32 size;
+	u8 id;
+	u16 tag;
+	void *sdata;
+
+	union {
+		struct p9_tversion tversion;
+		struct p9_rversion rversion;
+		struct p9_tauth tauth;
+		struct p9_rauth rauth;
+		struct p9_rerror rerror;
+		struct p9_tflush tflush;
+		struct p9_rflush rflush;
+		struct p9_tattach tattach;
+		struct p9_rattach rattach;
+		struct p9_twalk twalk;
+		struct p9_rwalk rwalk;
+		struct p9_topen topen;
+		struct p9_ropen ropen;
+		struct p9_tcreate tcreate;
+		struct p9_rcreate rcreate;
+		struct p9_tread tread;
+		struct p9_rread rread;
+		struct p9_twrite twrite;
+		struct p9_rwrite rwrite;
+		struct p9_tclunk tclunk;
+		struct p9_rclunk rclunk;
+		struct p9_tremove tremove;
+		struct p9_rremove rremove;
+		struct p9_tstat tstat;
+		struct p9_rstat rstat;
+		struct p9_twstat twstat;
+		struct p9_rwstat rwstat;
+	} params;
+};
+
+struct p9_idpool;
+
+int p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,
+	int dotu);
+int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *fc, int dotu);
+void p9_set_tag(struct p9_fcall *fc, u16 tag);
+struct p9_fcall *p9_create_tversion(u32 msize, char *version);
+struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname,
+	char *aname);
+struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname);
+struct p9_fcall *p9_create_tflush(u16 oldtag);
+struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
+	char **wnames);
+struct p9_fcall *p9_create_topen(u32 fid, u8 mode);
+struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
+	char *extension, int dotu);
+struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count);
+struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count,
+	const char *data);
+struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count,
+	const char __user *data);
+struct p9_fcall *p9_create_tclunk(u32 fid);
+struct p9_fcall *p9_create_tremove(u32 fid);
+struct p9_fcall *p9_create_tstat(u32 fid);
+struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat,
+	int dotu);
+
+int p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int dotu);
+int p9_errstr2errno(char *errstr, int len);
+
+struct p9_idpool *p9_idpool_create(void);
+void p9_idpool_destroy(struct p9_idpool *);
+int p9_idpool_get(struct p9_idpool *p);
+void p9_idpool_put(int id, struct p9_idpool *p);
+int p9_idpool_check(int id, struct p9_idpool *p);
+
+int p9_error_init(void);
+int p9_errstr2errno(char *, int);
+int __init p9_sysctl_register(void);
+void __exit p9_sysctl_unregister(void);
+#endif /* NET_9P_H */
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
new file mode 100644
index 0000000..d65ed7c
--- /dev/null
+++ b/include/net/9p/client.h
@@ -0,0 +1,80 @@
+/*
+ * include/net/9p/client.h
+ *
+ * 9P Client Definitions
+ *
+ *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#ifndef NET_9P_CLIENT_H
+#define NET_9P_CLIENT_H
+
+struct p9_client {
+	spinlock_t lock; /* protect client structure */
+	int msize;
+	unsigned char dotu;
+	struct p9_transport *trans;
+	struct p9_conn *conn;
+
+	struct p9_idpool *fidpool;
+	struct list_head fidlist;
+};
+
+struct p9_fid {
+	struct p9_client *clnt;
+	u32 fid;
+	int mode;
+	struct p9_qid qid;
+	u32 iounit;
+	uid_t uid;
+	void *aux;
+
+	int rdir_fpos;
+	int rdir_pos;
+	struct p9_fcall *rdir_fcall;
+	struct list_head flist;
+	struct list_head dlist;	/* list of all fids attached to a dentry */
+};
+
+struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
+								int dotu);
+void p9_client_destroy(struct p9_client *clnt);
+void p9_client_disconnect(struct p9_client *clnt);
+struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
+						     char *uname, char *aname);
+struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname);
+struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
+								int clone);
+int p9_client_open(struct p9_fid *fid, int mode);
+int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
+							char *extension);
+int p9_client_clunk(struct p9_fid *fid);
+int p9_client_remove(struct p9_fid *fid);
+int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count);
+int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count);
+int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count);
+int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset,
+								u32 count);
+int p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
+								u32 count);
+struct p9_stat *p9_client_stat(struct p9_fid *fid);
+int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
+struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset);
+
+#endif /* NET_9P_CLIENT_H */
diff --git a/include/net/9p/conn.h b/include/net/9p/conn.h
new file mode 100644
index 0000000..583b6a2
--- /dev/null
+++ b/include/net/9p/conn.h
@@ -0,0 +1,57 @@
+/*
+ * include/net/9p/conn.h
+ *
+ * Connection Definitions
+ *
+ *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#ifndef NET_9P_CONN_H
+#define NET_9P_CONN_H
+
+#undef P9_NONBLOCK
+
+struct p9_conn;
+struct p9_req;
+
+/**
+ * p9_mux_req_callback - callback function that is called when the
+ * response of a request is received. The callback is called from
+ * a workqueue and shouldn't block.
+ *
+ * @req - request
+ * @a - the pointer that was specified when the request was send to be
+ *      passed to the callback
+ */
+typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a);
+
+struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
+	unsigned char *dotu);
+void p9_conn_destroy(struct p9_conn *);
+int p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, struct p9_fcall **rc);
+
+#ifdef P9_NONBLOCK
+int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
+	p9_conn_req_callback cb, void *a);
+#endif /* P9_NONBLOCK */
+
+void p9_conn_cancel(struct p9_conn *m, int err);
+
+#endif /* NET_9P_CONN_H */
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
new file mode 100644
index 0000000..462d422
--- /dev/null
+++ b/include/net/9p/transport.h
@@ -0,0 +1,49 @@
+/*
+ * include/net/9p/transport.h
+ *
+ * Transport Definition
+ *
+ *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#ifndef NET_9P_TRANSPORT_H
+#define NET_9P_TRANSPORT_H
+
+enum p9_transport_status {
+	Connected,
+	Disconnected,
+	Hung,
+};
+
+struct p9_transport {
+	enum p9_transport_status status;
+	void *priv;
+
+	int (*write) (struct p9_transport *, void *, int);
+	int (*read) (struct p9_transport *, void *, int);
+	void (*close) (struct p9_transport *);
+	unsigned int (*poll)(struct p9_transport *, struct poll_table_struct *);
+};
+
+struct p9_transport *p9_trans_create_tcp(const char *addr, int port);
+struct p9_transport *p9_trans_create_unix(const char *addr);
+struct p9_transport *p9_trans_create_fd(int rfd, int wfd);
+
+#endif /* NET_9P_TRANSPORT_H */
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 8b06c2f..68b4eaf 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -19,7 +19,6 @@
 	struct gnet_stats_basic		tcfc_bstats;
 	struct gnet_stats_queue		tcfc_qstats;
 	struct gnet_stats_rate_est	tcfc_rate_est;
-	spinlock_t			*tcfc_stats_lock;
 	spinlock_t			tcfc_lock;
 };
 #define tcf_next	common.tcfc_next
@@ -32,7 +31,6 @@
 #define tcf_bstats	common.tcfc_bstats
 #define tcf_qstats	common.tcfc_qstats
 #define tcf_rate_est	common.tcfc_rate_est
-#define tcf_stats_lock	common.tcfc_stats_lock
 #define tcf_lock	common.tcfc_lock
 
 struct tcf_police {
@@ -123,34 +121,4 @@
 extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
 extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *, int);
 #endif /* CONFIG_NET_CLS_ACT */
-
-extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
-extern void tcf_police_destroy(struct tcf_police *p);
-extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
-extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
-extern int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p);
-
-static inline int
-tcf_police_release(struct tcf_police *p, int bind)
-{
-	int ret = 0;
-#ifdef CONFIG_NET_CLS_ACT
-	if (p) {
-		if (bind)
-			p->tcf_bindcnt--;
-
-		p->tcf_refcnt--;
-		if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) {
-			tcf_police_destroy(p);
-			ret = 1;
-		}
-	}
-#else
-	if (p && --p->tcf_refcnt == 0)
-		tcf_police_destroy(p);
-
-#endif /* CONFIG_NET_CLS_ACT */
-	return ret;
-}
-
 #endif
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index f3531d0..33b593e 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -61,7 +61,7 @@
 extern int			ipv6_chk_addr(struct in6_addr *addr,
 					      struct net_device *dev,
 					      int strict);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 extern int			ipv6_chk_home_addr(struct in6_addr *addr);
 #endif
 extern struct inet6_ifaddr *	ipv6_get_ifaddr(struct in6_addr *addr,
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index c0398f5..6de1e9e 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -62,13 +62,11 @@
 #define UNIXCREDS(skb)	(&UNIXCB((skb)).creds)
 #define UNIXSID(skb)	(&UNIXCB((skb)).secid)
 
-#define unix_state_rlock(s)	spin_lock(&unix_sk(s)->lock)
-#define unix_state_runlock(s)	spin_unlock(&unix_sk(s)->lock)
-#define unix_state_wlock(s)	spin_lock(&unix_sk(s)->lock)
-#define unix_state_wlock_nested(s) \
+#define unix_state_lock(s)	spin_lock(&unix_sk(s)->lock)
+#define unix_state_unlock(s)	spin_unlock(&unix_sk(s)->lock)
+#define unix_state_lock_nested(s) \
 				spin_lock_nested(&unix_sk(s)->lock, \
 				SINGLE_DEPTH_NESTING)
-#define unix_state_wunlock(s)	spin_unlock(&unix_sk(s)->lock)
 
 #ifdef __KERNEL__
 /* The AF_UNIX socket */
@@ -81,9 +79,10 @@
 	struct mutex		readlock;
         struct sock		*peer;
         struct sock		*other;
-        struct sock		*gc_tree;
+	struct list_head	link;
         atomic_t                inflight;
         spinlock_t		lock;
+	unsigned int		gc_candidate : 1;
         wait_queue_head_t       peer_wait;
 };
 #define unix_sk(__sk) ((struct unix_sock *)__sk)
diff --git a/include/net/ax88796.h b/include/net/ax88796.h
new file mode 100644
index 0000000..ee786a0
--- /dev/null
+++ b/include/net/ax88796.h
@@ -0,0 +1,27 @@
+/* include/net/ax88796.h
+ *
+ * Copyright 2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#ifndef __NET_AX88796_PLAT_H
+#define __NET_AX88796_PLAT_H
+
+#define AXFLG_HAS_EEPROM		(1<<0)
+#define AXFLG_MAC_FROMDEV		(1<<1)	/* device already has MAC */
+
+struct ax_plat_data {
+	unsigned int	 flags;
+	unsigned char	 wordlength;		/* 1 or 2 */
+	unsigned char	 dcr_val;		/* default value for DCR */
+	unsigned char	 rcr_val;		/* default value for RCR */
+	unsigned char	 gpoc_val;		/* default value for GPOC */
+	u32		*reg_offsets;		/* register offsets */
+};
+
+#endif /* __NET_AX88796_PLAT_H */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 93ce272..ebfb96b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -107,14 +107,14 @@
 #define HCI_IDLE_TIMEOUT	(6000)	/* 6 seconds */
 #define HCI_INIT_TIMEOUT	(10000)	/* 10 seconds */
 
-/* HCI Packet types */
+/* HCI data types */
 #define HCI_COMMAND_PKT		0x01
 #define HCI_ACLDATA_PKT		0x02
 #define HCI_SCODATA_PKT		0x03
 #define HCI_EVENT_PKT		0x04
 #define HCI_VENDOR_PKT		0xff
 
-/* HCI Packet types */
+/* HCI packet types */
 #define HCI_DM1		0x0008
 #define HCI_DM3		0x0400
 #define HCI_DM5		0x4000
@@ -129,6 +129,14 @@
 #define SCO_PTYPE_MASK	(HCI_HV1 | HCI_HV2 | HCI_HV3)
 #define ACL_PTYPE_MASK	(~SCO_PTYPE_MASK)
 
+/* eSCO packet types */
+#define ESCO_HV1	0x0001
+#define ESCO_HV2	0x0002
+#define ESCO_HV3	0x0004
+#define ESCO_EV3	0x0008
+#define ESCO_EV4	0x0010
+#define ESCO_EV5	0x0020
+
 /* ACL flags */
 #define ACL_CONT		0x01
 #define ACL_START		0x02
@@ -138,6 +146,7 @@
 /* Baseband links */
 #define SCO_LINK	0x00
 #define ACL_LINK	0x01
+#define ESCO_LINK	0x02
 
 /* LMP features */
 #define LMP_3SLOT	0x01
@@ -162,6 +171,11 @@
 #define LMP_PSCHEME	0x02
 #define LMP_PCONTROL	0x04
 
+#define LMP_ESCO	0x80
+
+#define LMP_EV4		0x01
+#define LMP_EV5		0x02
+
 #define LMP_SNIFF_SUBR	0x02
 
 /* Connection modes */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c0fc396..8f67c8a 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -78,6 +78,7 @@
 	__u16		voice_setting;
 
 	__u16		pkt_type;
+	__u16		esco_type;
 	__u16		link_policy;
 	__u16		link_mode;
 
@@ -109,6 +110,7 @@
 	struct sk_buff_head	cmd_q;
 
 	struct sk_buff		*sent_cmd;
+	struct sk_buff		*reassembly[3];
 
 	struct semaphore	req_lock;
 	wait_queue_head_t	req_wait_q;
@@ -437,6 +439,8 @@
 	return 0;
 }
 
+int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
+
 int hci_register_sysfs(struct hci_dev *hdev);
 void hci_unregister_sysfs(struct hci_dev *hdev);
 void hci_conn_add_sysfs(struct hci_conn *conn);
@@ -449,6 +453,7 @@
 #define lmp_encrypt_capable(dev)   ((dev)->features[0] & LMP_ENCRYPT)
 #define lmp_sniff_capable(dev)     ((dev)->features[0] & LMP_SNIFF)
 #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_esco_capable(dev)      ((dev)->features[3] & LMP_ESCO)
 
 /* ----- HCI protocols ----- */
 struct hci_proto {
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 8242a0e..87df4e8 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -129,8 +129,10 @@
 	__u8       data[0];
 } __attribute__ ((packed));
 
-#define L2CAP_CONF_SUCCESS	0x00
-#define L2CAP_CONF_UNACCEPT	0x01
+#define L2CAP_CONF_SUCCESS	0x0000
+#define L2CAP_CONF_UNACCEPT	0x0001
+#define L2CAP_CONF_REJECT	0x0002
+#define L2CAP_CONF_UNKNOWN	0x0003
 
 struct l2cap_conf_opt {
 	__u8       type;
@@ -215,6 +217,8 @@
 
 	__u32		link_mode;
 
+	__u8		conf_req[64];
+	__u8		conf_len;
 	__u8		conf_state;
 	__u8		conf_retry;
 	__u16		conf_mtu;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 3c563f0..25aa575 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -323,6 +323,7 @@
 #define RFCOMM_RELEASE_ONHUP  1
 #define RFCOMM_HANGUP_NOW     2
 #define RFCOMM_TTY_ATTACHED   3
+#define RFCOMM_TTY_RELEASED   4
 
 struct rfcomm_dev_req {
 	s16      dev_id;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 88171f8..7edaef6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -11,6 +11,44 @@
  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
  */
 
+
+/* Radiotap header iteration
+ *   implemented in net/wireless/radiotap.c
+ *   docs in Documentation/networking/radiotap-headers.txt
+ */
+/**
+ * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
+ * @rtheader: pointer to the radiotap header we are walking through
+ * @max_length: length of radiotap header in cpu byte ordering
+ * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg
+ * @this_arg: pointer to current radiotap arg
+ * @arg_index: internal next argument index
+ * @arg: internal next argument pointer
+ * @next_bitmap: internal pointer to next present u32
+ * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
+ */
+
+struct ieee80211_radiotap_iterator {
+	struct ieee80211_radiotap_header *rtheader;
+	int max_length;
+	int this_arg_index;
+	u8 *this_arg;
+
+	int arg_index;
+	u8 *arg;
+	__le32 *next_bitmap;
+	u32 bitmap_shifter;
+};
+
+extern int ieee80211_radiotap_iterator_init(
+   struct ieee80211_radiotap_iterator *iterator,
+   struct ieee80211_radiotap_header *radiotap_header,
+   int max_length);
+
+extern int ieee80211_radiotap_iterator_next(
+   struct ieee80211_radiotap_iterator *iterator);
+
+
 /* from net/wireless.h */
 struct wiphy;
 
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index 4f90f55..a6bb945 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -203,12 +203,10 @@
 
 #ifdef CONFIG_NETLABEL
 void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
-int cipso_v4_socket_setattr(const struct socket *sock,
-			    const struct cipso_v4_doi *doi_def,
-			    const struct netlbl_lsm_secattr *secattr);
+int cipso_v4_sock_setattr(struct sock *sk,
+			  const struct cipso_v4_doi *doi_def,
+			  const struct netlbl_lsm_secattr *secattr);
 int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
-int cipso_v4_socket_getattr(const struct socket *sock,
-			    struct netlbl_lsm_secattr *secattr);
 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
 			    struct netlbl_lsm_secattr *secattr);
 int cipso_v4_validate(unsigned char **option);
@@ -220,9 +218,9 @@
 	return;
 }
 
-static inline int cipso_v4_socket_setattr(const struct socket *sock,
-				  const struct cipso_v4_doi *doi_def,
-				  const struct netlbl_lsm_secattr *secattr)
+static inline int cipso_v4_sock_setattr(struct sock *sk,
+				      const struct cipso_v4_doi *doi_def,
+				      const struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOSYS;
 }
@@ -233,12 +231,6 @@
 	return -ENOSYS;
 }
 
-static inline int cipso_v4_socket_getattr(const struct socket *sock,
-					  struct netlbl_lsm_secattr *secattr)
-{
-	return -ENOSYS;
-}
-
 static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
 					  struct netlbl_lsm_secattr *secattr)
 {
diff --git a/include/net/dn.h b/include/net/dn.h
index ac4ce90..6277783 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -3,7 +3,6 @@
 
 #include <linux/dn.h>
 #include <net/sock.h>
-#include <net/tcp.h>
 #include <asm/byteorder.h>
 
 #define dn_ntohs(x) le16_to_cpu(x)
diff --git a/include/net/dst.h b/include/net/dst.h
index e12a8ce..e9ff4a4 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -47,7 +47,6 @@
 #define DST_NOXFRM		2
 #define DST_NOPOLICY		4
 #define DST_NOHASH		8
-#define DST_BALANCED            0x10
 	unsigned long		expires;
 
 	unsigned short		header_len;	/* more space at head required */
@@ -265,9 +264,16 @@
 {
 	return 0;
 } 
+static inline int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
+				struct sock *sk, int flags)
+{
+	return 0;
+}
 #else
 extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
 		       struct sock *sk, int flags);
+extern int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
+			 struct sock *sk, int flags);
 #endif
 #endif
 
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index ed3a887..83e41dd 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -64,7 +64,7 @@
 	void			(*flush_cache)(void);
 
 	int			nlgroup;
-	struct nla_policy	*policy;
+	const struct nla_policy	*policy;
 	struct list_head	*rules_list;
 	struct module		*owner;
 };
diff --git a/include/net/flow.h b/include/net/flow.h
index f3cc1f8..af59fa5 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -67,20 +67,16 @@
 
 		__be32		spi;
 
-#ifdef CONFIG_IPV6_MIP6
 		struct {
 			__u8	type;
 		} mht;
-#endif
 	} uli_u;
 #define fl_ip_sport	uli_u.ports.sport
 #define fl_ip_dport	uli_u.ports.dport
 #define fl_icmp_type	uli_u.icmpt.type
 #define fl_icmp_code	uli_u.icmpt.code
 #define fl_ipsec_spi	uli_u.spi
-#ifdef CONFIG_IPV6_MIP6
 #define fl_mh_type	uli_u.mht.type
-#endif
 	__u32           secid;	/* used by xfrm; see secid.txt */
 } __attribute__((__aligned__(BITS_PER_LONG/8)));
 
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index adff4c8..b6eaca1 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -60,7 +60,7 @@
 {
 	u8			cmd;
 	unsigned int		flags;
-	struct nla_policy	*policy;
+	const struct nla_policy	*policy;
 	int		       (*doit)(struct sk_buff *skb,
 				       struct genl_info *info);
 	int		       (*dumpit)(struct sk_buff *skb,
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 09a2532..47d52b2 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -209,9 +209,6 @@
 extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
 						  const int state);
 
-extern void __inet_twsk_kill(struct inet_timewait_sock *tw,
-			     struct inet_hashinfo *hashinfo);
-
 extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw,
 				  struct sock *sk,
 				  struct inet_hashinfo *hashinfo);
diff --git a/include/net/ip.h b/include/net/ip.h
index bb207db..abf2820 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -143,6 +143,7 @@
 	__wsum 	    csum;
 	int	    csumoffset; /* u16 offset of csum in iov[0].iov_base */
 				/* -1 if not needed */ 
+	int	    bound_dev_if;
 }; 
 
 void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 5a4a0366..8cadc77 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -39,7 +39,6 @@
 	int			fc_mx_len;
 	int			fc_mp_len;
 	u32			fc_flow;
-	u32			fc_mp_alg;
 	u32			fc_nlflags;
 	struct nl_info		fc_nlinfo;
  };
@@ -86,9 +85,6 @@
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	int			fib_power;
 #endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	u32			fib_mp_alg;
-#endif
 	struct fib_nh		fib_nh[0];
 #define fib_dev		fib_nh[0].nh_dev
 };
@@ -103,10 +99,6 @@
 	unsigned char	nh_sel;
 	unsigned char	type;
 	unsigned char	scope;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	__be32          network;
-	__be32          netmask;
-#endif
 	struct fib_info *fi;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	struct fib_rule	*r;
@@ -145,14 +137,6 @@
 #define FIB_RES_DEV(res)		(FIB_RES_NH(res).nh_dev)
 #define FIB_RES_OIF(res)		(FIB_RES_NH(res).nh_oif)
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-#define FIB_RES_NETWORK(res)		((res).network)
-#define FIB_RES_NETMASK(res)	        ((res).netmask)
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-#define FIB_RES_NETWORK(res)		(0)
-#define FIB_RES_NETMASK(res)	        (0)
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
-
 struct fib_table {
 	struct hlist_node tb_hlist;
 	u32		tb_id;
@@ -213,7 +197,7 @@
 #endif /* CONFIG_IP_MULTIPLE_TABLES */
 
 /* Exported by fib_frontend.c */
-extern struct nla_policy rtm_ipv4_policy[];
+extern const struct nla_policy rtm_ipv4_policy[];
 extern void		ip_fib_init(void);
 extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 			       struct net_device *dev, __be32 *spec_dst, u32 *itag);
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
deleted file mode 100644
index 25b5657..0000000
--- a/include/net/ip_mp_alg.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* ip_mp_alg.h: IPV4 multipath algorithm support.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#ifndef _NET_IP_MP_ALG_H
-#define _NET_IP_MP_ALG_H
-
-#include <linux/ip_mp_alg.h>
-#include <net/flow.h>
-#include <net/route.h>
-
-struct fib_nh;
-
-struct ip_mp_alg_ops {
-	void	(*mp_alg_select_route)(const struct flowi *flp,
-				       struct rtable *rth, struct rtable **rp);
-	void	(*mp_alg_flush)(void);
-	void	(*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
-				     unsigned char prefixlen,
-				     const struct fib_nh *nh);
-	void	(*mp_alg_remove)(struct rtable *rth);
-};
-
-extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
-extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
-
-extern struct ip_mp_alg_ops *ip_mp_alg_table[];
-
-static inline int multipath_select_route(const struct flowi *flp,
-					 struct rtable *rth,
-					 struct rtable **rp)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
-	/* mp_alg_select_route _MUST_ be implemented */
-	if (ops && (rth->u.dst.flags & DST_BALANCED)) {
-		ops->mp_alg_select_route(flp, rth, rp);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-static inline void multipath_flush(void)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	int i;
-
-	for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
-		struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
-
-		if (ops && ops->mp_alg_flush)
-			ops->mp_alg_flush();
-	}
-#endif
-}
-
-static inline void multipath_set_nhinfo(struct rtable *rth,
-					__be32 network, __be32 netmask,
-					unsigned char prefixlen,
-					const struct fib_nh *nh)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
-	if (ops && ops->mp_alg_set_nhinfo)
-		ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
-#endif
-}
-
-static inline void multipath_remove(struct rtable *rth)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
-	if (ops && ops->mp_alg_remove &&
-	    (rth->u.dst.flags & DST_BALANCED))
-		ops->mp_alg_remove(rth);
-#endif
-}
-
-static inline int multipath_comparekeys(const struct flowi *flp1,
-					const struct flowi *flp2)
-{
-	return flp1->fl4_dst == flp2->fl4_dst &&
-		flp1->fl4_src == flp2->fl4_src &&
-		flp1->oif == flp2->oif &&
-		flp1->mark == flp2->mark &&
-		!((flp1->fl4_tos ^ flp2->fl4_tos) &
-		  (IPTOS_RT_MASK | RTO_ONLINK));
-}
-
-#endif /* _NET_IP_MP_ALG_H */
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 4fa5dfe..46b9dce 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -469,6 +469,9 @@
 extern int			ip6_dst_lookup(struct sock *sk,
 					       struct dst_entry **dst,
 					       struct flowi *fl);
+extern int			ip6_dst_blackhole(struct sock *sk,
+						  struct dst_entry **dst,
+						  struct flowi *fl);
 extern int			ip6_sk_dst_lookup(struct sock *sk,
 						  struct dst_entry **dst,
 						  struct flowi *fl);
@@ -509,10 +512,6 @@
 
 extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
 
-extern struct ipv6_txoptions *	ipv6_invert_rthdr(struct sock *sk,
-						  struct ipv6_rt_hdr *hdr);
-
-
 /*
  *	socket options (ipv6_sockglue.c)
  */
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 36bee44..0838755 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -125,6 +125,9 @@
 extern int irsock_init(void);
 extern void irsock_cleanup(void);
 
+extern int irda_nl_register(void);
+extern void irda_nl_unregister(void);
+
 extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
 			    struct packet_type *ptype,
 			    struct net_device *orig_dev);
diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h
index f0248fb..9d0c78ea 100644
--- a/include/net/irda/irlap.h
+++ b/include/net/irda/irlap.h
@@ -208,6 +208,8 @@
 	int    xbofs_delay;   /* Nr of XBOF's used to MTT */
 	int    bofs_count;    /* Negotiated extra BOFs */
 	int    next_bofs;     /* Negotiated extra BOFs after next frame */
+
+	int    mode;     /* IrLAP mode (primary, secondary or monitor) */
 };
 
 /* 
@@ -289,4 +291,21 @@
 	self->disconnect_pending = FALSE;
 }
 
+/*
+ * Function irlap_next_state (self, state)
+ *
+ *    Switches state and provides debug information
+ *
+ */
+static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state)
+{
+	/*
+	if (!self || self->magic != LAP_MAGIC)
+		return;
+
+	IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]);
+	*/
+	self->state = state;
+}
+
 #endif
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h
index f9bd11b..b6c468c 100644
--- a/include/net/iucv/af_iucv.h
+++ b/include/net/iucv/af_iucv.h
@@ -60,6 +60,7 @@
 	char			dst_user_id[8];
 	char			dst_name[8];
 	struct list_head	accept_q;
+	spinlock_t		accept_q_lock;
 	struct sock		*parent;
 	struct iucv_path	*path;
 	struct sk_buff_head	send_skb_q;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a7f122b..c34fd9a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -347,9 +347,16 @@
  * @mac_addr: pointer to MAC address of the interface. This pointer is valid
  *	until the interface is removed (i.e. it cannot be used after
  *	remove_interface() callback was called for this interface).
+ *	This pointer will be %NULL for monitor interfaces, be careful.
  *
  * This structure is used in add_interface() and remove_interface()
  * callbacks of &struct ieee80211_hw.
+ *
+ * When you allow multiple interfaces to be added to your PHY, take care
+ * that the hardware can actually handle multiple MAC addresses. However,
+ * also take care that when there's no interface left with mac_addr != %NULL
+ * you remove the MAC address from the device to avoid acknowledging packets
+ * in pure monitor mode.
  */
 struct ieee80211_if_init_conf {
 	int if_id;
@@ -574,10 +581,11 @@
 	 * to returning zero. By returning non-zero addition of the interface
 	 * is inhibited. Unless monitor_during_oper is set, it is guaranteed
 	 * that monitor interfaces and normal interfaces are mutually
-	 * exclusive. The open() handler is called after add_interface()
-	 * if this is the first device added. At least one of the open()
-	 * open() and add_interface() callbacks has to be assigned. If
-	 * add_interface() is NULL, one STA interface is permitted only. */
+	 * exclusive. If assigned, the open() handler is called after
+	 * add_interface() if this is the first device added. The
+	 * add_interface() callback has to be assigned because it is the only
+	 * way to obtain the requested MAC address for any interface.
+	 */
 	int (*add_interface)(struct ieee80211_hw *hw,
 			     struct ieee80211_if_init_conf *conf);
 
@@ -921,12 +929,6 @@
 ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
 			  struct ieee80211_tx_control *control);
 
-/* Low level drivers that have their own MLME and MAC indicate
- * the aid for an associating station with this call */
-int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw,
-			      u8 *peer_address, u16 aid);
-
-
 /* Given an sk_buff with a raw 802.11 header at the data pointer this function
  * returns the 802.11 header length in bytes (not including encryption
  * headers). If the data in the sk_buff is too short to contain a valid 802.11
diff --git a/include/net/mip6.h b/include/net/mip6.h
index 68263c6..6327261 100644
--- a/include/net/mip6.h
+++ b/include/net/mip6.h
@@ -54,8 +54,4 @@
 #define IP6_MH_TYPE_BERROR	7   /* Binding Error */
 #define IP6_MH_TYPE_MAX		IP6_MH_TYPE_BERROR
 
-extern int mip6_init(void);
-extern void mip6_fini(void);
-extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb);
-
 #endif
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 1401ccc..7a67160 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -9,29 +9,10 @@
 #ifndef _NF_CONNTRACK_IPV4_H
 #define _NF_CONNTRACK_IPV4_H
 
-#ifdef CONFIG_NF_NAT_NEEDED
-#include <net/netfilter/nf_nat.h>
-#include <linux/netfilter/nf_conntrack_pptp.h>
-
-/* per conntrack: nat application helper private data */
-union nf_conntrack_nat_help {
-        /* insert nat helper private data here */
-	struct nf_nat_pptp nat_pptp_info;
-};
-
-struct nf_conn_nat {
-	struct nf_nat_info info;
-	union nf_conntrack_nat_help help;
-#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
-	defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
-	int masq_index;
-#endif
-};
-#endif /* CONFIG_NF_NAT_NEEDED */
-
 /* Returns new sk_buff, or NULL */
-struct sk_buff *
-nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
+struct sk_buff *nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
+
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
 
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
index b4b6049..5a89659 100644
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -7,7 +7,7 @@
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
 
-extern int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start,
+extern int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start,
 				  u8 *nexthdrp, int len);
 
 extern int nf_ct_frag6_init(void);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 4732432..810020e 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -82,6 +82,8 @@
 
 	union nf_conntrack_help help;
 
+	struct hlist_head expectations;
+
 	/* Current number of expected connections */
 	unsigned int expecting;
 };
@@ -117,9 +119,6 @@
 	/* Unique ID that identifies this conntrack*/
 	unsigned int id;
 
-	/* features - nat, helper, ... used by allocating system */
-	u_int32_t features;
-
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	u_int32_t mark;
 #endif
@@ -131,8 +130,8 @@
 	/* Storage reserved for other modules: */
 	union nf_conntrack_proto proto;
 
-	/* features dynamically at the end: helper, nat (both optional) */
-	char data[0];
+	/* Extensions */
+	struct nf_ct_ext *ext;
 };
 
 static inline struct nf_conn *
@@ -175,6 +174,10 @@
 extern int nf_ct_l3proto_try_module_get(unsigned short l3proto);
 extern void nf_ct_l3proto_module_put(unsigned short l3proto);
 
+extern struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced);
+extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced,
+				 int size);
+
 extern struct nf_conntrack_tuple_hash *
 __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
 		    const struct nf_conn *ignored_conntrack);
@@ -183,6 +186,10 @@
 
 extern void nf_conntrack_flush(void);
 
+extern int nf_ct_get_tuplepr(const struct sk_buff *skb,
+			     unsigned int nhoff,
+			     u_int16_t l3num,
+			     struct nf_conntrack_tuple *tuple);
 extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
 				const struct nf_conntrack_tuple *orig);
 
@@ -216,9 +223,6 @@
 				    struct nf_conn *conntrack,
 				    int dir);
 
-/* Call me when a conntrack is destroyed. */
-extern void (*nf_conntrack_destroyed)(struct nf_conn *conntrack);
-
 /* Fake conntrack entry for untracked connections */
 extern struct nf_conn nf_conntrack_untracked;
 
@@ -262,60 +266,10 @@
 	local_bh_enable();				\
 } while (0)
 
-/* no helper, no nat */
-#define	NF_CT_F_BASIC	0
-/* for helper */
-#define	NF_CT_F_HELP	1
-/* for nat. */
-#define	NF_CT_F_NAT	2
-#define NF_CT_F_NUM	4
-
 extern int
 nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size);
 extern void
 nf_conntrack_unregister_cache(u_int32_t features);
 
-/* valid combinations:
- * basic: nf_conn, nf_conn .. nf_conn_help
- * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help
- */
-#ifdef CONFIG_NF_NAT_NEEDED
-static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
-{
-	unsigned int offset = sizeof(struct nf_conn);
-
-	if (!(ct->features & NF_CT_F_NAT))
-		return NULL;
-
-	offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
-	return (struct nf_conn_nat *) ((void *)ct + offset);
-}
-
-static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
-{
-	unsigned int offset = sizeof(struct nf_conn);
-
-	if (!(ct->features & NF_CT_F_HELP))
-		return NULL;
-	if (ct->features & NF_CT_F_NAT) {
-		offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
-		offset += sizeof(struct nf_conn_nat);
-	}
-
-	offset = ALIGN(offset, __alignof__(struct nf_conn_help));
-	return (struct nf_conn_help *) ((void *)ct + offset);
-}
-#else /* No NAT */
-static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
-{
-	unsigned int offset = sizeof(struct nf_conn);
-
-	if (!(ct->features & NF_CT_F_HELP))
-		return NULL;
-
-	offset = ALIGN(offset, __alignof__(struct nf_conn_help));
-	return (struct nf_conn_help *) ((void *)ct + offset);
-}
-#endif /* CONFIG_NF_NAT_NEEDED */
 #endif /* __KERNEL__ */
 #endif /* _NF_CONNTRACK_H */
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 9fb9066..4056f5f 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -30,6 +30,9 @@
 extern int nf_conntrack_proto_init(void);
 extern void nf_conntrack_proto_fini(void);
 
+extern int nf_conntrack_helper_init(void);
+extern void nf_conntrack_helper_fini(void);
+
 struct nf_conntrack_l3proto;
 extern struct nf_conntrack_l3proto *nf_ct_find_l3proto(u_int16_t pf);
 /* Like above, but you already have conntrack read lock. */
@@ -55,8 +58,7 @@
 
 /* Find a connection corresponding to a tuple. */
 extern struct nf_conntrack_tuple_hash *
-nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
-		      const struct nf_conn *ignored_conntrack);
+nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple);
 
 extern int __nf_conntrack_confirm(struct sk_buff **pskb);
 
@@ -81,9 +83,8 @@
 	    struct nf_conntrack_l3proto *l3proto,
 	    struct nf_conntrack_l4proto *proto);
 
-extern struct list_head *nf_conntrack_hash;
-extern struct list_head nf_conntrack_expect_list;
+extern struct hlist_head *nf_conntrack_hash;
 extern rwlock_t nf_conntrack_lock ;
-extern struct list_head unconfirmed;
+extern struct hlist_head unconfirmed;
 
 #endif /* _NF_CONNTRACK_CORE_H */
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 811c907..f0b9078 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -49,15 +49,15 @@
 		atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
 }
 
-extern struct atomic_notifier_head nf_conntrack_expect_chain;
-extern int nf_conntrack_expect_register_notifier(struct notifier_block *nb);
-extern int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb);
+extern struct atomic_notifier_head nf_ct_expect_chain;
+extern int nf_ct_expect_register_notifier(struct notifier_block *nb);
+extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb);
 
 static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
-			  struct nf_conntrack_expect *exp)
+nf_ct_expect_event(enum ip_conntrack_expect_events event,
+		   struct nf_conntrack_expect *exp)
 {
-	atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+	atomic_notifier_call_chain(&nf_ct_expect_chain, event, exp);
 }
 
 #else /* CONFIG_NF_CONNTRACK_EVENTS */
@@ -67,9 +67,8 @@
 static inline void nf_conntrack_event(enum ip_conntrack_events event,
 				      struct nf_conn *ct) {}
 static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
-static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
-			  struct nf_conntrack_expect *exp) {}
+static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
+				      struct nf_conntrack_expect *exp) {}
 static inline void nf_ct_event_cache_flush(void) {}
 #endif /* CONFIG_NF_CONNTRACK_EVENTS */
 
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 173c7c1..cae1a0d 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -6,17 +6,21 @@
 #define _NF_CONNTRACK_EXPECT_H
 #include <net/netfilter/nf_conntrack.h>
 
-extern struct list_head nf_conntrack_expect_list;
-extern struct kmem_cache *nf_conntrack_expect_cachep;
-extern const struct file_operations exp_file_ops;
+extern struct hlist_head *nf_ct_expect_hash;
+extern unsigned int nf_ct_expect_hsize;
+extern unsigned int nf_ct_expect_max;
 
 struct nf_conntrack_expect
 {
-	/* Internal linked list (global expectation list) */
-	struct list_head list;
+	/* Conntrack expectation list member */
+	struct hlist_node lnode;
+
+	/* Hash member */
+	struct hlist_node hnode;
 
 	/* We expect this tuple, with the following mask */
-	struct nf_conntrack_tuple tuple, mask;
+	struct nf_conntrack_tuple tuple;
+	struct nf_conntrack_tuple_mask mask;
 
 	/* Function to call after setup and insertion */
 	void (*expectfn)(struct nf_conn *new,
@@ -52,29 +56,31 @@
 
 #define NF_CT_EXPECT_PERMANENT 0x1
 
+int nf_conntrack_expect_init(void);
+void nf_conntrack_expect_fini(void);
 
 struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple);
 
 struct nf_conntrack_expect *
-nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple);
+nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple);
 
 struct nf_conntrack_expect *
-find_expectation(const struct nf_conntrack_tuple *tuple);
+nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple);
 
 void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
 void nf_ct_remove_expectations(struct nf_conn *ct);
-void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
+void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
 
 /* Allocate space for an expectation: this is mandatory before calling
-   nf_conntrack_expect_related.  You will have to call put afterwards. */
-struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me);
-void nf_conntrack_expect_init(struct nf_conntrack_expect *, int,
-			      union nf_conntrack_address *,
-			      union nf_conntrack_address *,
-			      u_int8_t, __be16 *, __be16 *);
-void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
-int nf_conntrack_expect_related(struct nf_conntrack_expect *expect);
+   nf_ct_expect_related.  You will have to call put afterwards. */
+struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
+void nf_ct_expect_init(struct nf_conntrack_expect *, int,
+		       union nf_conntrack_address *,
+		       union nf_conntrack_address *,
+		       u_int8_t, __be16 *, __be16 *);
+void nf_ct_expect_put(struct nf_conntrack_expect *exp);
+int nf_ct_expect_related(struct nf_conntrack_expect *expect);
 
 #endif /*_NF_CONNTRACK_EXPECT_H*/
 
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
new file mode 100644
index 0000000..73b5711
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -0,0 +1,85 @@
+#ifndef _NF_CONNTRACK_EXTEND_H
+#define _NF_CONNTRACK_EXTEND_H
+
+#include <net/netfilter/nf_conntrack.h>
+
+enum nf_ct_ext_id
+{
+	NF_CT_EXT_HELPER,
+	NF_CT_EXT_NAT,
+	NF_CT_EXT_NUM,
+};
+
+#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
+#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
+
+/* Extensions: optional stuff which isn't permanently in struct. */
+struct nf_ct_ext {
+	u8 offset[NF_CT_EXT_NUM];
+	u8 len;
+	u8 real_len;
+	char data[0];
+};
+
+static inline int nf_ct_ext_exist(const struct nf_conn *ct, u8 id)
+{
+	return (ct->ext && ct->ext->offset[id]);
+}
+
+static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id)
+{
+	if (!nf_ct_ext_exist(ct, id))
+		return NULL;
+
+	return (void *)ct->ext + ct->ext->offset[id];
+}
+#define nf_ct_ext_find(ext, id)	\
+	((id##_TYPE *)__nf_ct_ext_find((ext), (id)))
+
+/* Destroy all relationships */
+extern void __nf_ct_ext_destroy(struct nf_conn *ct);
+static inline void nf_ct_ext_destroy(struct nf_conn *ct)
+{
+	if (ct->ext)
+		__nf_ct_ext_destroy(ct);
+}
+
+/* Free operation. If you want to free a object referred from private area,
+ * please implement __nf_ct_ext_free() and call it.
+ */
+static inline void nf_ct_ext_free(struct nf_conn *ct)
+{
+	if (ct->ext)
+		kfree(ct->ext);
+}
+
+/* Add this type, returns pointer to data or NULL. */
+void *
+__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
+#define nf_ct_ext_add(ct, id, gfp) \
+	((id##_TYPE *)__nf_ct_ext_add((ct), (id), (gfp)))
+
+#define NF_CT_EXT_F_PREALLOC	0x0001
+
+struct nf_ct_ext_type
+{
+	/* Destroys relationships (can be NULL). */
+	void (*destroy)(struct nf_conn *ct);
+	/* Called when realloacted (can be NULL).
+	   Contents has already been moved. */
+	void (*move)(struct nf_conn *ct, void *old);
+
+	enum nf_ct_ext_id id;
+
+	unsigned int flags;
+
+	/* Length and min alignment. */
+	u8 len;
+	u8 align;
+	/* initial size of nf_ct_ext. */
+	u8 alloc_size;
+};
+
+int nf_ct_extend_register(struct nf_ct_ext_type *type);
+void nf_ct_extend_unregister(struct nf_ct_ext_type *type);
+#endif /* _NF_CONNTRACK_EXTEND_H */
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 8c72ac9..d04f999 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -10,12 +10,13 @@
 #ifndef _NF_CONNTRACK_HELPER_H
 #define _NF_CONNTRACK_HELPER_H
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
 struct module;
 
 struct nf_conntrack_helper
-{	
-	struct list_head list; 		/* Internal use. */
+{
+	struct hlist_node hnode;	/* Internal use. */
 
 	const char *name;		/* name of the module */
 	struct module *me;		/* pointer to self */
@@ -23,10 +24,9 @@
 					 * expected connections */
 	unsigned int timeout;		/* timeout for expecteds */
 
-	/* Mask of things we will help (compared against server response) */
+	/* Tuple of things we will help (compared against server response) */
 	struct nf_conntrack_tuple tuple;
-	struct nf_conntrack_tuple mask;
-	
+
 	/* Function to call when data passes; return verdict, or -1 to
            invalidate. */
 	int (*help)(struct sk_buff **pskb,
@@ -52,4 +52,10 @@
 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
 
+extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
+
+static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
+{
+	return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+}
 #endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 96a58d8..3c58a2c 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -58,13 +58,11 @@
 
 	/*
 	 * Called before tracking. 
-	 *	*dataoff: offset of protocol header (TCP, UDP,...) in *pskb
+	 *	*dataoff: offset of protocol header (TCP, UDP,...) in skb
 	 *	*protonum: protocol number
 	 */
-	int (*prepare)(struct sk_buff **pskb, unsigned int hooknum,
-		       unsigned int *dataoff, u_int8_t *protonum);
-
-	u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
+	int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff,
+			   unsigned int *dataoff, u_int8_t *protonum);
 
 	int (*tuple_to_nfattr)(struct sk_buff *skb,
 			       const struct nf_conntrack_tuple *t);
@@ -91,8 +89,6 @@
 extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
 
 /* Existing built-in protocols */
-extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
-extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
 
 static inline struct nf_conntrack_l3proto *
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 5d72b16..040dae5 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -100,6 +100,14 @@
 	} dst;
 };
 
+struct nf_conntrack_tuple_mask
+{
+	struct {
+		union nf_conntrack_address u3;
+		union nf_conntrack_man_proto u;
+	} src;
+};
+
 /* This is optimized opposed to a memset of the whole structure.  Everything we
  * really care about is the  source/destination unions */
 #define NF_CT_TUPLE_U_BLANK(tuple)                              	\
@@ -112,11 +120,11 @@
 
 #ifdef __KERNEL__
 
-#define NF_CT_DUMP_TUPLE(tp)						    \
-DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",	    \
-	(tp), (tp)->src.l3num, (tp)->dst.protonum,			    \
-	NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
-	NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
+#define NF_CT_DUMP_TUPLE(tp)						     \
+pr_debug("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",	     \
+	 (tp), (tp)->src.l3num, (tp)->dst.protonum,			     \
+	 NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
+	 NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
 
 /* If we're the first tuple, it's the original dir. */
 #define NF_CT_DIRECTION(h)						\
@@ -125,8 +133,7 @@
 /* Connections have two entries in the hash table: one for each way */
 struct nf_conntrack_tuple_hash
 {
-	struct list_head list;
-
+	struct hlist_node hnode;
 	struct nf_conntrack_tuple tuple;
 };
 
@@ -162,31 +169,44 @@
 	return nf_ct_tuple_src_equal(t1, t2) && nf_ct_tuple_dst_equal(t1, t2);
 }
 
+static inline int nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
+					 const struct nf_conntrack_tuple_mask *m2)
+{
+	return (m1->src.u3.all[0] == m2->src.u3.all[0] &&
+		m1->src.u3.all[1] == m2->src.u3.all[1] &&
+		m1->src.u3.all[2] == m2->src.u3.all[2] &&
+		m1->src.u3.all[3] == m2->src.u3.all[3] &&
+		m1->src.u.all == m2->src.u.all);
+}
+
+static inline int nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
+					   const struct nf_conntrack_tuple *t2,
+					   const struct nf_conntrack_tuple_mask *mask)
+{
+	int count;
+
+	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
+		if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
+		    mask->src.u3.all[count])
+			return 0;
+	}
+
+	if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
+		return 0;
+
+	if (t1->src.l3num != t2->src.l3num ||
+	    t1->dst.protonum != t2->dst.protonum)
+		return 0;
+
+	return 1;
+}
+
 static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
 				       const struct nf_conntrack_tuple *tuple,
-				       const struct nf_conntrack_tuple *mask)
+				       const struct nf_conntrack_tuple_mask *mask)
 {
-	int count = 0;
-
-        for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
-                if ((t->src.u3.all[count] ^ tuple->src.u3.all[count]) &
-                    mask->src.u3.all[count])
-                        return 0;
-        }
-
-        for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
-                if ((t->dst.u3.all[count] ^ tuple->dst.u3.all[count]) &
-                    mask->dst.u3.all[count])
-                        return 0;
-        }
-
-        if ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all ||
-            (t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all ||
-            (t->src.l3num ^ tuple->src.l3num) & mask->src.l3num ||
-            (t->dst.protonum ^ tuple->dst.protonum) & mask->dst.protonum)
-                return 0;
-
-        return 1;
+	return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
+	       nf_ct_tuple_dst_equal(t, tuple);
 }
 
 #endif /* _NF_CONNTRACK_TUPLE_H */
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index bc57dd7..6ae52f7 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -51,16 +51,31 @@
 
 #ifdef __KERNEL__
 #include <linux/list.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
-/* The structure embedded in the conntrack structure. */
-struct nf_nat_info
+/* per conntrack: nat application helper private data */
+union nf_conntrack_nat_help
 {
-	struct list_head bysource;
-	struct nf_nat_seq seq[IP_CT_DIR_MAX];
+	/* insert nat helper private data here */
+	struct nf_nat_pptp nat_pptp_info;
 };
 
 struct nf_conn;
 
+/* The structure embedded in the conntrack structure. */
+struct nf_conn_nat
+{
+	struct hlist_node bysource;
+	struct nf_nat_seq seq[IP_CT_DIR_MAX];
+	struct nf_conn *ct;
+	union nf_conntrack_nat_help help;
+#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+    defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
+	int masq_index;
+#endif
+};
+
 /* Set up the info structure to map into this range. */
 extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
 				      const struct nf_nat_range *range,
@@ -70,7 +85,10 @@
 extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
 			     const struct nf_conn *ignored_conntrack);
 
-extern int nf_nat_module_is_loaded;
+static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
+{
+	return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+}
 
 #else  /* !__KERNEL__: iptables wants this to compile. */
 #define nf_nat_multi_range nf_nat_multi_range_compat
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
index 9778ffa..c3cd127 100644
--- a/include/net/netfilter/nf_nat_core.h
+++ b/include/net/netfilter/nf_nat_core.h
@@ -2,6 +2,7 @@
 #define _NF_NAT_CORE_H
 #include <linux/list.h>
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
 
 /* This header used to share core functionality between the standalone
    NAT module, and the compatibility layer's use of NAT for masquerading. */
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 83da7e1..9b7d6f2 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -332,17 +332,15 @@
  */
 
 #ifdef CONFIG_NETLABEL
-int netlbl_socket_setattr(const struct socket *sock,
-			  const struct netlbl_lsm_secattr *secattr);
+int netlbl_sock_setattr(struct sock *sk,
+			const struct netlbl_lsm_secattr *secattr);
 int netlbl_sock_getattr(struct sock *sk,
 			struct netlbl_lsm_secattr *secattr);
-int netlbl_socket_getattr(const struct socket *sock,
-			  struct netlbl_lsm_secattr *secattr);
 int netlbl_skbuff_getattr(const struct sk_buff *skb,
 			  struct netlbl_lsm_secattr *secattr);
 void netlbl_skbuff_err(struct sk_buff *skb, int error);
 #else
-static inline int netlbl_socket_setattr(const struct socket *sock,
+static inline int netlbl_sock_setattr(struct sock *sk,
 				     const struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOSYS;
@@ -354,12 +352,6 @@
 	return -ENOSYS;
 }
 
-static inline int netlbl_socket_getattr(const struct socket *sock,
-					struct netlbl_lsm_secattr *secattr)
-{
-	return -ENOSYS;
-}
-
 static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
 					struct netlbl_lsm_secattr *secattr)
 {
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 0bf325c..d7b824b 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -118,6 +118,9 @@
  * Nested Attributes Construction:
  *   nla_nest_start(skb, type)		start a nested attribute
  *   nla_nest_end(skb, nla)		finalize a nested attribute
+ *   nla_nest_compat_start(skb, type,	start a nested compat attribute
+ *			   len, data)
+ *   nla_nest_compat_end(skb, type)	finalize a nested compat attribute
  *   nla_nest_cancel(skb, nla)		cancel nested attribute construction
  *
  * Attribute Length Calculations:
@@ -152,6 +155,7 @@
  *   nla_find_nested()			find attribute in nested attributes
  *   nla_parse()			parse and validate stream of attrs
  *   nla_parse_nested()			parse nested attribuets
+ *   nla_parse_nested_compat()		parse nested compat attributes
  *   nla_for_each_attr()		loop over all attributes
  *   nla_for_each_nested()		loop over the nested attributes
  *=========================================================================
@@ -170,6 +174,7 @@
 	NLA_FLAG,
 	NLA_MSECS,
 	NLA_NESTED,
+	NLA_NESTED_COMPAT,
 	NLA_NUL_STRING,
 	NLA_BINARY,
 	__NLA_TYPE_MAX,
@@ -190,6 +195,7 @@
  *    NLA_NUL_STRING       Maximum length of string (excluding NUL)
  *    NLA_FLAG             Unused
  *    NLA_BINARY           Maximum length of attribute payload
+ *    NLA_NESTED_COMPAT    Exact length of structure payload
  *    All other            Exact length of attribute payload
  *
  * Example:
@@ -222,10 +228,10 @@
 				     gfp_t flags);
 
 extern int		nla_validate(struct nlattr *head, int len, int maxtype,
-				     struct nla_policy *policy);
+				     const struct nla_policy *policy);
 extern int		nla_parse(struct nlattr *tb[], int maxtype,
 				  struct nlattr *head, int len,
-				  struct nla_policy *policy);
+				  const struct nla_policy *policy);
 extern struct nlattr *	nla_find(struct nlattr *head, int len, int attrtype);
 extern size_t		nla_strlcpy(char *dst, const struct nlattr *nla,
 				    size_t dstsize);
@@ -360,7 +366,7 @@
  */
 static inline int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen,
 			      struct nlattr *tb[], int maxtype,
-			      struct nla_policy *policy)
+			      const struct nla_policy *policy)
 {
 	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
 		return -EINVAL;
@@ -392,7 +398,7 @@
  * @policy: validation policy
  */
 static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
-				 struct nla_policy *policy)
+				 const struct nla_policy *policy)
 {
 	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
 		return -EINVAL;
@@ -729,10 +735,43 @@
  */
 static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
 				   struct nlattr *nla,
-				   struct nla_policy *policy)
+				   const struct nla_policy *policy)
 {
 	return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
 }
+
+/**
+ * nla_parse_nested_compat - parse nested compat attributes
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @nla: attribute containing the nested attributes
+ * @data: pointer to point to contained structure
+ * @len: length of contained structure
+ * @policy: validation policy
+ *
+ * Parse a nested compat attribute. The compat attribute contains a structure
+ * and optionally a set of nested attributes. On success the data pointer
+ * points to the nested data and tb contains the parsed attributes
+ * (see nla_parse).
+ */
+static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype,
+					    struct nlattr *nla,
+					    const struct nla_policy *policy,
+					    int len)
+{
+	if (nla_len(nla) < len)
+		return -1;
+	if (nla_len(nla) >= NLA_ALIGN(len) + sizeof(struct nlattr))
+		return nla_parse_nested(tb, maxtype,
+					nla_data(nla) + NLA_ALIGN(len),
+					policy);
+	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
+	return 0;
+}
+
+#define nla_parse_nested_compat(tb, maxtype, nla, policy, data, len) \
+({	data = nla_len(nla) >= len ? nla_data(nla) : NULL; \
+	__nla_parse_nested_compat(tb, maxtype, nla, policy, len); })
 /**
  * nla_put_u8 - Add a u16 netlink attribute to a socket buffer
  * @skb: socket buffer to add attribute to
@@ -965,6 +1004,51 @@
 }
 
 /**
+ * nla_nest_compat_start - Start a new level of nested compat attributes
+ * @skb: socket buffer to add attributes to
+ * @attrtype: attribute type of container
+ * @attrlen: length of structure
+ * @data: pointer to structure
+ *
+ * Start a nested compat attribute that contains both a structure and
+ * a set of nested attributes.
+ *
+ * Returns the container attribute
+ */
+static inline struct nlattr *nla_nest_compat_start(struct sk_buff *skb,
+						   int attrtype, int attrlen,
+						   const void *data)
+{
+	struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
+
+	if (nla_put(skb, attrtype, attrlen, data) < 0)
+		return NULL;
+	if (nla_nest_start(skb, attrtype) == NULL) {
+		nlmsg_trim(skb, start);
+		return NULL;
+	}
+	return start;
+}
+
+/**
+ * nla_nest_compat_end - Finalize nesting of compat attributes
+ * @skb: socket buffer the attribtues are stored in
+ * @start: container attribute
+ *
+ * Corrects the container attribute header to include the all
+ * appeneded attributes.
+ *
+ * Returns the total data length of the skb.
+ */
+static inline int nla_nest_compat_end(struct sk_buff *skb, struct nlattr *start)
+{
+	struct nlattr *nest = (void *)start + NLMSG_ALIGN(start->nla_len);
+
+	start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
+	return nla_nest_end(skb, nest);
+}
+
+/**
  * nla_nest_cancel - Cancel nesting of attributes
  * @skb: socket buffer the message is stored in
  * @start: container attribute
@@ -990,7 +1074,7 @@
  * Returns 0 on success or a negative error code.
  */
 static inline int nla_validate_nested(struct nlattr *start, int maxtype,
-				      struct nla_policy *policy)
+				      const struct nla_policy *policy)
 {
 	return nla_validate(nla_data(start), nla_len(start), maxtype, policy);
 }
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 4129df7..7968b1d 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -65,8 +65,6 @@
 {
 #ifdef CONFIG_NET_CLS_ACT
 	struct tc_action *action;
-#elif defined CONFIG_NET_CLS_POLICE
-	struct tcf_police *police;
 #endif
 };
 
@@ -91,8 +89,6 @@
 {
 #ifdef CONFIG_NET_CLS_ACT
 	return !!exts->action;
-#elif defined CONFIG_NET_CLS_POLICE
-	return !!exts->police;
 #else
 	return 0;
 #endif
@@ -129,11 +125,7 @@
 #ifdef CONFIG_NET_CLS_ACT
 	if (exts->action)
 		return tcf_action_exec(skb, exts->action, res);
-#elif defined CONFIG_NET_CLS_POLICE
-	if (exts->police)
-		return tcf_police(skb, exts->police);
 #endif
-
 	return 0;
 }
 
@@ -306,6 +298,8 @@
 		return 1;
 }
 
+#define MODULE_ALIAS_TCF_EMATCH(kind)	MODULE_ALIAS("ematch-kind-" __stringify(kind))
+
 #else /* CONFIG_NET_EMATCH */
 
 struct tcf_ematch_tree
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 5754d53..9e22526 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -89,8 +89,10 @@
 		__qdisc_run(dev);
 }
 
+extern int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
+			      struct tcf_result *res);
 extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
-	struct tcf_result *res);
+		       struct tcf_result *res);
 
 /* Calculate maximal size of packet seen by hard_start_xmit
    routine of this device.
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index af89608..a581989 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -3,6 +3,8 @@
 
 #ifdef __KERNEL__
 
+#include <net/protocol.h>
+
 #define RAWV6_HTABLE_SIZE	MAX_INET_PROTOS
 extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
 extern rwlock_t raw_v6_lock;
@@ -23,6 +25,13 @@
 					  int type, int code, 
 					  int offset, __be32 info);
 
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+					   struct sk_buff *skb));
+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+					     struct sk_buff *skb));
+#endif
+
 #endif
 
 #endif
diff --git a/include/net/route.h b/include/net/route.h
index 749e4df..f7ce625 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -62,7 +62,6 @@
 	
 	unsigned		rt_flags;
 	__u16			rt_type;
-	__u16			rt_multipath_alg;
 
 	__be32			rt_dst;	/* Path destination	*/
 	__be32			rt_src;	/* Path source		*/
@@ -136,7 +135,7 @@
 
 #define IPTOS_RT_MASK	(IPTOS_TOS_MASK & ~3)
 
-extern __u8 ip_tos2prio[16];
+extern const __u8 ip_tos2prio[16];
 
 static inline char rt_tos2priority(u8 tos)
 {
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 3b3d474..3861c05 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -22,4 +22,62 @@
 		return AF_UNSPEC;
 }
 
+/**
+ *	struct rtnl_link_ops - rtnetlink link operations
+ *
+ *	@list: Used internally
+ *	@kind: Identifier
+ *	@maxtype: Highest device specific netlink attribute number
+ *	@policy: Netlink policy for device specific attribute validation
+ *	@validate: Optional validation function for netlink/changelink parameters
+ *	@priv_size: sizeof net_device private space
+ *	@setup: net_device setup function
+ *	@newlink: Function for configuring and registering a new device
+ *	@changelink: Function for changing parameters of an existing device
+ *	@dellink: Function to remove a device
+ *	@get_size: Function to calculate required room for dumping device
+ *		   specific netlink attributes
+ *	@fill_info: Function to dump device specific netlink attributes
+ *	@get_xstats_size: Function to calculate required room for dumping devic
+ *			  specific statistics
+ *	@fill_xstats: Function to dump device specific statistics
+ */
+struct rtnl_link_ops {
+	struct list_head	list;
+
+	const char		*kind;
+
+	size_t			priv_size;
+	void			(*setup)(struct net_device *dev);
+
+	int			maxtype;
+	const struct nla_policy	*policy;
+	int			(*validate)(struct nlattr *tb[],
+					    struct nlattr *data[]);
+
+	int			(*newlink)(struct net_device *dev,
+					   struct nlattr *tb[],
+					   struct nlattr *data[]);
+	int			(*changelink)(struct net_device *dev,
+					      struct nlattr *tb[],
+					      struct nlattr *data[]);
+	void			(*dellink)(struct net_device *dev);
+
+	size_t			(*get_size)(const struct net_device *dev);
+	int			(*fill_info)(struct sk_buff *skb,
+					     const struct net_device *dev);
+
+	size_t			(*get_xstats_size)(const struct net_device *dev);
+	int			(*fill_xstats)(struct sk_buff *skb,
+					       const struct net_device *dev);
+};
+
+extern int	__rtnl_link_register(struct rtnl_link_ops *ops);
+extern void	__rtnl_link_unregister(struct rtnl_link_ops *ops);
+
+extern int	rtnl_link_register(struct rtnl_link_ops *ops);
+extern void	rtnl_link_unregister(struct rtnl_link_ops *ops);
+
+#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
+
 #endif
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 1b8e351..8a67f24 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -290,7 +290,7 @@
 {
 	sch->qstats.drops++;
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
 		goto drop;
 
diff --git a/include/net/scm.h b/include/net/scm.h
index 5637d5e..423cb1d 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -8,7 +8,7 @@
 /* Well, we should have at least one descriptor open
  * to accept passed FDs 8)
  */
-#define SCM_MAX_FD	(OPEN_MAX-1)
+#define SCM_MAX_FD	255
 
 struct scm_fp_list
 {
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index dda72bf..16baef4 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -503,6 +503,13 @@
 	return frag;
 }
 
+static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc)
+{
+
+	sctp_assoc_sync_pmtu(asoc);
+	asoc->pmtu_pending = 0;
+}
+
 /* Walk through a list of TLV parameters.  Don't trust the
  * individual parameter lengths and instead depend on
  * the chunk length to indicate when to stop.  Make sure
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 5e81984..ee4559b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -912,6 +912,9 @@
 	 */
 	__u16 pathmaxrxt;
 
+	/* is the Path MTU update pending on this tranport */
+	__u8 pmtu_pending;
+
 	/* PMTU	      : The current known path MTU.  */
 	__u32 pathmtu;
 
@@ -1006,6 +1009,7 @@
 void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
 unsigned long sctp_transport_timeout(struct sctp_transport *);
 void sctp_transport_reset(struct sctp_transport *);
+void sctp_transport_update_pmtu(struct sctp_transport *, u32);
 
 
 /* This is the structure we use to queue packets as they come into
@@ -1565,6 +1569,9 @@
 	 */
 	__u16 pathmaxrxt;
 
+	/* Flag that path mtu update is pending */
+	__u8   pmtu_pending;
+
 	/* Association : The smallest PMTU discovered for all of the
 	 * PMTU	       : peer's transport addresses.
 	 */
diff --git a/include/net/sock.h b/include/net/sock.h
index 689b886..dfeb8b1 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -218,13 +218,13 @@
 	atomic_t		sk_rmem_alloc;
 	atomic_t		sk_wmem_alloc;
 	atomic_t		sk_omem_alloc;
+	int			sk_sndbuf;
 	struct sk_buff_head	sk_receive_queue;
 	struct sk_buff_head	sk_write_queue;
 	struct sk_buff_head	sk_async_wait_queue;
 	int			sk_wmem_queued;
 	int			sk_forward_alloc;
 	gfp_t			sk_allocation;
-	int			sk_sndbuf;
 	int			sk_route_caps;
 	int			sk_gso_type;
 	int			sk_rcvlowat;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e22b4f0..a8af9ae 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -254,6 +254,12 @@
 	return seq3 - seq2 >= seq1 - seq2;
 }
 
+static inline int tcp_too_many_orphans(struct sock *sk, int num)
+{
+	return (num > sysctl_tcp_max_orphans) ||
+		(sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
+		 atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]);
+}
 
 extern struct proto tcp_prot;
 
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
index 333bba6..cfc4ba4 100644
--- a/include/net/tipc/tipc_port.h
+++ b/include/net/tipc/tipc_port.h
@@ -1,8 +1,8 @@
 /*
  * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports
  * 
- * Copyright (c) 1994-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 1994-2007, Ericsson AB
+ * Copyright (c) 2005-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,7 @@
  * @conn_unacked: number of unacknowledged messages received from peer port
  * @published: non-zero if port has one or more associated names
  * @congested: non-zero if cannot send because of link or port congestion
+ * @max_pkt: maximum packet size "hint" used when building messages sent by port
  * @ref: unique reference to port in TIPC object registry
  * @phdr: preformatted message header used when sending messages
  */
@@ -68,6 +69,7 @@
 	u32 conn_unacked;
 	int published;
 	u32 congested;
+	u32 max_pkt;
 	u32 ref;
 	struct tipc_msg phdr;
 };
diff --git a/include/net/udp.h b/include/net/udp.h
index 496f89d..98755eb 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -119,16 +119,9 @@
 }
 
 
-struct udp_get_port_ops {
-	int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2);
-	int (*saddr_any)(const struct sock *sk);
-	unsigned int (*hash_port_and_rcv_saddr)(__u16 port,
-						const struct sock *sk);
-};
-
 /* net/ipv4/udp.c */
 extern int	udp_get_port(struct sock *sk, unsigned short snum,
-			     const struct udp_get_port_ops *ops);
+			     int (*saddr_cmp)(const struct sock *, const struct sock *));
 extern void	udp_err(struct sk_buff *, u32);
 
 extern int	udp_sendmsg(struct kiocb *iocb, struct sock *sk,
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 50b4b42..635b0ea 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -120,5 +120,5 @@
 
 extern void	udplite4_register(void);
 extern int 	udplite_get_port(struct sock *sk, unsigned short snum,
-				 const struct udp_get_port_ops *ops);
+			int (*scmp)(const struct sock *, const struct sock *));
 #endif	/* _UDPLITE_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 39ef925..ae959e9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -19,9 +19,19 @@
 #include <net/ipv6.h>
 #include <net/ip6_fib.h>
 
+#define XFRM_PROTO_ESP		50
+#define XFRM_PROTO_AH		51
+#define XFRM_PROTO_COMP		108
+#define XFRM_PROTO_IPIP		4
+#define XFRM_PROTO_IPV6		41
+#define XFRM_PROTO_ROUTING	IPPROTO_ROUTING
+#define XFRM_PROTO_DSTOPTS	IPPROTO_DSTOPTS
+
 #define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
 #define MODULE_ALIAS_XFRM_MODE(family, encap) \
 	MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
+#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
+	MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
 
 extern struct sock *xfrm_nl;
 extern u32 sysctl_xfrm_aevent_etime;
@@ -237,7 +247,6 @@
 extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
 extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
 extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
-#define XFRM_ACQ_EXPIRES	30
 
 struct xfrm_tmpl;
 extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
@@ -510,11 +519,9 @@
 	case IPPROTO_ICMPV6:
 		port = htons(fl->fl_icmp_type);
 		break;
-#ifdef CONFIG_IPV6_MIP6
 	case IPPROTO_MH:
 		port = htons(fl->fl_mh_type);
 		break;
-#endif
 	default:
 		port = 0;	/*XXX*/
 	}
@@ -921,6 +928,10 @@
 					  struct flowi *fl, struct xfrm_tmpl *tmpl,
 					  struct xfrm_policy *pol, int *err,
 					  unsigned short family);
+extern struct xfrm_state * xfrm_stateonly_find(xfrm_address_t *daddr,
+					       xfrm_address_t *saddr,
+					       unsigned short family,
+					       u8 mode, u8 proto, u32 reqid);
 extern int xfrm_state_check_expire(struct xfrm_state *x);
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_add(struct xfrm_state *x);
@@ -965,7 +976,7 @@
 
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
-extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
+extern int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
 extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
 extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
 extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
@@ -992,7 +1003,7 @@
 				 u8 **prevhdr);
 
 #ifdef CONFIG_XFRM
-extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
+extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
 extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
 extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
 #else
@@ -1001,12 +1012,13 @@
  	return -ENOPROTOOPT;
 } 
 
-static inline int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
+static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
 {
  	/* should not happen */
  	kfree_skb(skb);
 	return 0;
 }
+
 static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family)
 {
 	return -EINVAL;
@@ -1021,13 +1033,13 @@
 					  struct xfrm_sec_ctx *ctx, int delete,
 					  int *err);
 struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err);
-void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 u32 xfrm_get_acqseq(void);
 void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
 struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
 				  xfrm_address_t *daddr, xfrm_address_t *saddr,
 				  int create, unsigned short family);
-extern void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+extern int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
 			  struct flowi *fl, int family, int strict);
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index eae7e2e..ad6e278 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -126,4 +126,6 @@
 #define MANFID_POSSIO			0x030c
 #define PRODID_POSSIO_GCC		0x0003
 
+#define MANFID_NEC			0x0010
+
 #endif /* _LINUX_CISCODE_H */
diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h
index 5c07017..12243e8 100644
--- a/include/rdma/ib_cm.h
+++ b/include/rdma/ib_cm.h
@@ -385,7 +385,6 @@
 	u8		private_data_len;
 	u8		responder_resources;
 	u8		initiator_depth;
-	u8		target_ack_delay;
 	u8		failover_accepted;
 	u8		flow_control;
 	u8		rnr_retry_count;
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 739fa4d..30712dd 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -111,6 +111,9 @@
 #define IB_QP1_QKEY	0x80010000
 #define IB_QP_SET_QKEY	0x80000000
 
+#define IB_DEFAULT_PKEY_PARTIAL 0x7FFF
+#define IB_DEFAULT_PKEY_FULL	0xFFFF
+
 enum {
 	IB_MGMT_MAD_HDR = 24,
 	IB_MGMT_MAD_DATA = 232,
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index b3a36f7..c533d6c 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -35,6 +35,7 @@
 
 #include <linux/list.h>
 #include <linux/scatterlist.h>
+#include <linux/workqueue.h>
 
 struct ib_ucontext;
 
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 47cefca..0627a6a 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -890,6 +890,8 @@
 	spinlock_t                    client_data_lock;
 
 	struct ib_cache               cache;
+	int                          *pkey_tbl_len;
+	int                          *gid_tbl_len;
 
 	u32                           flags;
 
@@ -1118,6 +1120,12 @@
 		   u8 port_num, int port_modify_mask,
 		   struct ib_port_modify *port_modify);
 
+int ib_find_gid(struct ib_device *device, union ib_gid *gid,
+		u8 *port_num, u16 *index);
+
+int ib_find_pkey(struct ib_device *device,
+		 u8 port_num, u16 pkey, u16 *index);
+
 /**
  * ib_alloc_pd - Allocates an unused protection domain.
  * @device: The device on which to allocate the protection domain.
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 55ebf03..50e907f 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -48,6 +48,7 @@
 	ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT	= UEVENT_BASE + 14,
 
 	ISCSI_UEVENT_TGT_DSCVR		= UEVENT_BASE + 15,
+	ISCSI_UEVENT_SET_HOST_PARAM	= UEVENT_BASE + 16,
 
 	/* up events */
 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
@@ -71,6 +72,8 @@
 		/* messages u -> k */
 		struct msg_create_session {
 			uint32_t	initial_cmdsn;
+			uint16_t	cmds_max;
+			uint16_t	queue_depth;
 		} c_session;
 		struct msg_destroy_session {
 			uint32_t	sid;
@@ -136,6 +139,11 @@
 			 */
 			uint32_t	enable;
 		} tgt_dscvr;
+		struct msg_set_host_param {
+			uint32_t	host_no;
+			uint32_t	param; /* enum iscsi_host_param */
+			uint32_t	len;
+		} set_host_param;
 	} u;
 	union {
 		/* messages k -> u */
@@ -223,6 +231,11 @@
 	ISCSI_PARAM_CONN_PORT,
 	ISCSI_PARAM_CONN_ADDRESS,
 
+	ISCSI_PARAM_USERNAME,
+	ISCSI_PARAM_USERNAME_IN,
+	ISCSI_PARAM_PASSWORD,
+	ISCSI_PARAM_PASSWORD_IN,
+
 	/* must always be last */
 	ISCSI_PARAM_MAX,
 };
@@ -249,6 +262,24 @@
 #define ISCSI_SESS_RECOVERY_TMO		(1 << ISCSI_PARAM_SESS_RECOVERY_TMO)
 #define ISCSI_CONN_PORT			(1 << ISCSI_PARAM_CONN_PORT)
 #define ISCSI_CONN_ADDRESS		(1 << ISCSI_PARAM_CONN_ADDRESS)
+#define ISCSI_USERNAME			(1 << ISCSI_PARAM_USERNAME)
+#define ISCSI_USERNAME_IN		(1 << ISCSI_PARAM_USERNAME_IN)
+#define ISCSI_PASSWORD			(1 << ISCSI_PARAM_PASSWORD)
+#define ISCSI_PASSWORD_IN		(1 << ISCSI_PARAM_PASSWORD_IN)
+
+/* iSCSI HBA params */
+enum iscsi_host_param {
+	ISCSI_HOST_PARAM_HWADDRESS,
+	ISCSI_HOST_PARAM_INITIATOR_NAME,
+	ISCSI_HOST_PARAM_NETDEV_NAME,
+	ISCSI_HOST_PARAM_IPADDRESS,
+	ISCSI_HOST_PARAM_MAX,
+};
+
+#define ISCSI_HOST_HWADDRESS		(1 << ISCSI_HOST_PARAM_HWADDRESS)
+#define ISCSI_HOST_INITIATOR_NAME	(1 << ISCSI_HOST_PARAM_INITIATOR_NAME)
+#define ISCSI_HOST_NETDEV_NAME		(1 << ISCSI_HOST_PARAM_NETDEV_NAME)
+#define ISCSI_HOST_IPADDRESS		(1 << ISCSI_HOST_PARAM_IPADDRESS)
 
 #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
 #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
@@ -272,6 +303,9 @@
 #define CAP_MULTI_CONN		0x40
 #define CAP_TEXT_NEGO		0x80
 #define CAP_MARKERS		0x100
+#define CAP_FW_DB		0x200
+#define CAP_SENDTARGETS_OFFLOAD	0x400
+#define CAP_DATA_PATH_OFFLOAD	0x800
 
 /*
  * These flags describes reason of stop_conn() call
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index ea0816d..3f631b0 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -48,9 +48,8 @@
 #define debug_scsi(fmt...)
 #endif
 
-#define ISCSI_XMIT_CMDS_MAX	128	/* must be power of 2 */
-#define ISCSI_MGMT_CMDS_MAX	32	/* must be power of 2 */
-#define ISCSI_CONN_MAX			1
+#define ISCSI_DEF_XMIT_CMDS_MAX	128	/* must be power of 2 */
+#define ISCSI_MGMT_CMDS_MAX	16	/* must be power of 2 */
 
 #define ISCSI_MGMT_ITT_OFFSET	0xa00
 
@@ -73,6 +72,8 @@
 #define ISCSI_AGE_SHIFT			28
 #define ISCSI_AGE_MASK			(0xf << ISCSI_AGE_SHIFT)
 
+#define ISCSI_ADDRESS_BUF_LEN		64
+
 struct iscsi_mgmt_task {
 	/*
 	 * Becuae LLDs allocate their hdr differently, this is a pointer to
@@ -80,7 +81,7 @@
 	 */
 	struct iscsi_hdr	*hdr;
 	char			*data;		/* mgmt payload */
-	int			data_count;	/* counts data to be sent */
+	unsigned		data_count;	/* counts data to be sent */
 	uint32_t		itt;		/* this ITT */
 	void			*dd_data;	/* driver/transport data */
 	struct list_head	running;
@@ -90,6 +91,7 @@
 	ISCSI_TASK_COMPLETED,
 	ISCSI_TASK_PENDING,
 	ISCSI_TASK_RUNNING,
+	ISCSI_TASK_ABORTING,
 };
 
 struct iscsi_cmd_task {
@@ -99,16 +101,14 @@
 	 */
 	struct iscsi_cmd	*hdr;
 	int			itt;		/* this ITT */
-	int			datasn;		/* DataSN */
 
 	uint32_t		unsol_datasn;
-	int			imm_count;	/* imm-data (bytes)   */
-	int			unsol_count;	/* unsolicited (bytes)*/
+	unsigned		imm_count;	/* imm-data (bytes)   */
+	unsigned		unsol_count;	/* unsolicited (bytes)*/
 	/* offset in unsolicited stream (bytes); */
-	int			unsol_offset;
-	int			data_count;	/* remaining Data-Out */
+	unsigned		unsol_offset;
+	unsigned		data_count;	/* remaining Data-Out */
 	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
-	int			total_length;
 	struct iscsi_conn	*conn;		/* used connection    */
 	struct iscsi_mgmt_task	*mtask;		/* tmf mtask in progr */
 
@@ -152,18 +152,11 @@
 	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
 
 	/* xmit */
-	struct kfifo		*immqueue;	/* immediate xmit queue */
 	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
 	struct list_head	mgmt_run_list;	/* list of control tasks */
 	struct list_head	xmitqueue;	/* data-path cmd queue */
 	struct list_head	run_list;	/* list of cmds in progress */
 	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
-	/*
-	 * serializes connection xmit, access to kfifos:
-	 * xmitqueue, immqueue, mgmtqueue
-	 */
-	struct mutex		xmitmutex;
-
 	unsigned long		suspend_tx;	/* suspend Tx */
 	unsigned long		suspend_rx;	/* suspend Rx */
 
@@ -174,8 +167,8 @@
 	int			tmabort_state;	/* see TMABORT_INITIAL, etc.*/
 
 	/* negotiated params */
-	int			max_recv_dlength; /* initiator_max_recv_dsl*/
-	int			max_xmit_dlength; /* target_max_recv_dsl */
+	unsigned		max_recv_dlength; /* initiator_max_recv_dsl*/
+	unsigned		max_xmit_dlength; /* target_max_recv_dsl */
 	int			hdrdgst_en;
 	int			datadgst_en;
 	int			ifmarker_en;
@@ -183,6 +176,12 @@
 	/* values userspace uses to id a conn */
 	int			persistent_port;
 	char			*persistent_address;
+	/* remote portal currently connected to */
+	int			portal_port;
+	char			portal_address[ISCSI_ADDRESS_BUF_LEN];
+	/* local address */
+	int			local_port;
+	char			local_address[ISCSI_ADDRESS_BUF_LEN];
 
 	/* MIB-statistics */
 	uint64_t		txdata_octets;
@@ -213,18 +212,25 @@
 
 	/* configuration */
 	int			initial_r2t_en;
-	int			max_r2t;
+	unsigned		max_r2t;
 	int			imm_data_en;
-	int			first_burst;
-	int			max_burst;
+	unsigned		first_burst;
+	unsigned		max_burst;
 	int			time2wait;
 	int			time2retain;
 	int			pdu_inorder_en;
 	int			dataseq_inorder_en;
 	int			erl;
 	int			tpgt;
+	char			*username;
+	char			*username_in;
+	char			*password;
+	char			*password_in;
 	char			*targetname;
-
+	char			*initiatorname;
+	/* hw address or netdev iscsi connection is bound to */
+	char			*hwaddress;
+	char			*netdev;
 	/* control data */
 	struct iscsi_transport	*tt;
 	struct Scsi_Host	*host;
@@ -255,12 +261,22 @@
 extern int iscsi_queuecommand(struct scsi_cmnd *sc,
 			      void (*done)(struct scsi_cmnd *));
 
+
+/*
+ * iSCSI host helpers.
+ */
+extern int iscsi_host_set_param(struct Scsi_Host *shost,
+				enum iscsi_host_param param, char *buf,
+				int buflen);
+extern int iscsi_host_get_param(struct Scsi_Host *shost,
+				enum iscsi_host_param param, char *buf);
+
 /*
  * session management
  */
 extern struct iscsi_cls_session *
 iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
-		    int, int, uint32_t, uint32_t *);
+		    uint16_t, uint16_t, int, int, uint32_t, uint32_t *);
 extern void iscsi_session_teardown(struct iscsi_cls_session *);
 extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
 extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
@@ -289,8 +305,7 @@
 /*
  * pdu and task processing
  */
-extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
-				    struct iscsi_nopin *);
+extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);
 extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
 					struct iscsi_data *hdr);
 extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index a2e0c10..53e1705 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -135,4 +135,24 @@
 extern struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t);
 extern void scsi_free_sgtable(struct scatterlist *, int);
 
+extern int scsi_dma_map(struct scsi_cmnd *cmd);
+extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
+
+#define scsi_sg_count(cmd) ((cmd)->use_sg)
+#define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
+#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
+
+static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
+{
+	cmd->resid = resid;
+}
+
+static inline int scsi_get_resid(struct scsi_cmnd *cmd)
+{
+	return cmd->resid;
+}
+
+#define scsi_for_each_sg(cmd, sg, nseg, __i)			\
+	for (__i = 0, sg = scsi_sglist(cmd); __i < (nseg); __i++, (sg)++)
+
 #endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 2f3c5b8b..d5057bc 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -209,7 +209,6 @@
 extern int scsi_add_device(struct Scsi_Host *host, uint channel,
 			   uint target, uint lun);
 extern void scsi_remove_device(struct scsi_device *);
-extern int scsi_device_cancel(struct scsi_device *, int);
 
 extern int scsi_device_get(struct scsi_device *);
 extern void scsi_device_put(struct scsi_device *);
@@ -287,6 +286,7 @@
 extern void scsi_target_unblock(struct device *);
 extern void scsi_remove_target(struct device *);
 extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+extern int scsilun_to_int(struct scsi_lun *);
 extern const char *scsi_device_state_name(enum scsi_device_state);
 extern int scsi_is_sdev_device(const struct device *);
 extern int scsi_is_target_device(const struct device *);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 68f461b..ba07cf7c 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -339,12 +339,6 @@
 	enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
 
 	/*
-	 * suspend support
-	 */
-	int (*resume)(struct scsi_device *);
-	int (*suspend)(struct scsi_device *, pm_message_t state);
-
-	/*
 	 * Name of proc directory
 	 */
 	char *proc_name;
@@ -677,6 +671,10 @@
 #define shost_printk(prefix, shost, fmt, a...)	\
 	dev_printk(prefix, &(shost)->shost_gendev, fmt, ##a)
 
+static inline void *shost_priv(struct Scsi_Host *shost)
+{
+	return (void *)shost->hostdata;
+}
 
 int scsi_is_host_device(const struct device *);
 
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 1e79730..a0d80bc 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -1,4 +1,4 @@
-/* 
+/*
  *  FiberChannel transport specific attributes exported to sysfs.
  *
  *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
@@ -19,7 +19,7 @@
  *
  *  ========
  *
- *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
+ *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
  *    Rewrite for host, target, device, and remote port attributes,
  *    statistics, and service functions...
  *
@@ -62,8 +62,10 @@
 	FC_PORTTYPE_NLPORT,		/* (Public) Loop w/ FLPort */
 	FC_PORTTYPE_LPORT,		/* (Private) Loop w/o FLPort */
 	FC_PORTTYPE_PTP,		/* Point to Point w/ another NPort */
+	FC_PORTTYPE_NPIV,		/* VPORT based on NPIV */
 };
 
+
 /*
  * fc_port_state: If you alter this, you also need to alter scsi_transport_fc.c
  * (for the ascii descriptions).
@@ -83,7 +85,26 @@
 };
 
 
-/* 
+/*
+ * fc_vport_state: If you alter this, you also need to alter
+ * scsi_transport_fc.c (for the ascii descriptions).
+ */
+enum fc_vport_state {
+	FC_VPORT_UNKNOWN,
+	FC_VPORT_ACTIVE,
+	FC_VPORT_DISABLED,
+	FC_VPORT_LINKDOWN,
+	FC_VPORT_INITIALIZING,
+	FC_VPORT_NO_FABRIC_SUPP,
+	FC_VPORT_NO_FABRIC_RSCS,
+	FC_VPORT_FABRIC_LOGOUT,
+	FC_VPORT_FABRIC_REJ_WWN,
+	FC_VPORT_FAILED,
+};
+
+
+
+/*
  * FC Classes of Service
  * Note: values are not enumerated, as they can be "or'd" together
  * for reporting (e.g. report supported_classes). If you alter this list,
@@ -96,7 +117,7 @@
 #define FC_COS_CLASS4			0x10
 #define FC_COS_CLASS6			0x40
 
-/* 
+/*
  * FC Port Speeds
  * Note: values are not enumerated, as they can be "or'd" together
  * for reporting (e.g. report supported_speeds). If you alter this list,
@@ -124,16 +145,114 @@
 };
 
 /*
- * FC Remote Port Roles
+ * FC Port Roles
  * Note: values are not enumerated, as they can be "or'd" together
  * for reporting (e.g. report roles). If you alter this list,
  * you also need to alter scsi_transport_fc.c (for the ascii descriptions).
  */
-#define FC_RPORT_ROLE_UNKNOWN			0x00
-#define FC_RPORT_ROLE_FCP_TARGET		0x01
-#define FC_RPORT_ROLE_FCP_INITIATOR		0x02
-#define FC_RPORT_ROLE_IP_PORT			0x04
+#define FC_PORT_ROLE_UNKNOWN			0x00
+#define FC_PORT_ROLE_FCP_TARGET			0x01
+#define FC_PORT_ROLE_FCP_INITIATOR		0x02
+#define FC_PORT_ROLE_IP_PORT			0x04
 
+/* The following are for compatibility */
+#define FC_RPORT_ROLE_UNKNOWN			FC_PORT_ROLE_UNKNOWN
+#define FC_RPORT_ROLE_FCP_TARGET		FC_PORT_ROLE_FCP_TARGET
+#define FC_RPORT_ROLE_FCP_INITIATOR		FC_PORT_ROLE_FCP_INITIATOR
+#define FC_RPORT_ROLE_IP_PORT			FC_PORT_ROLE_IP_PORT
+
+
+/* Macro for use in defining Virtual Port attributes */
+#define FC_VPORT_ATTR(_name,_mode,_show,_store)				\
+struct class_device_attribute class_device_attr_vport_##_name = 	\
+	__ATTR(_name,_mode,_show,_store)
+
+
+/*
+ * FC Virtual Port Attributes
+ *
+ * This structure exists for each FC port is a virtual FC port. Virtual
+ * ports share the physical link with the Physical port. Each virtual
+ * ports has a unique presense on the SAN, and may be instantiated via
+ * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a
+ * unique presense, each vport has it's own view of the fabric,
+ * authentication priviledge, and priorities.
+ *
+ * A virtual port may support 1 or more FC4 roles. Typically it is a
+ * FCP Initiator. It could be a FCP Target, or exist sole for an IP over FC
+ * roles. FC port attributes for the vport will be reported on any
+ * fc_host class object allocated for an FCP Initiator.
+ *
+ * --
+ *
+ * Fixed attributes are not expected to change. The driver is
+ * expected to set these values after receiving the fc_vport structure
+ * via the vport_create() call from the transport.
+ * The transport fully manages all get functions w/o driver interaction.
+ *
+ * Dynamic attributes are expected to change. The driver participates
+ * in all get/set operations via functions provided by the driver.
+ *
+ * Private attributes are transport-managed values. They are fully
+ * managed by the transport w/o driver interaction.
+ */
+
+#define FC_VPORT_SYMBOLIC_NAMELEN		64
+struct fc_vport {
+	/* Fixed Attributes */
+
+	/* Dynamic Attributes */
+
+	/* Private (Transport-managed) Attributes */
+	enum fc_vport_state vport_state;
+	enum fc_vport_state vport_last_state;
+	u64 node_name;
+	u64 port_name;
+	u32 roles;
+	u32 vport_id;		/* Admin Identifier for the vport */
+	enum fc_port_type vport_type;
+	char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
+
+	/* exported data */
+	void *dd_data;			/* Used for driver-specific storage */
+
+	/* internal data */
+	struct Scsi_Host *shost;	/* Physical Port Parent */
+	unsigned int channel;
+	u32 number;
+	u8 flags;
+	struct list_head peers;
+	struct device dev;
+	struct work_struct vport_delete_work;
+} __attribute__((aligned(sizeof(unsigned long))));
+
+/* bit field values for struct fc_vport "flags" field: */
+#define FC_VPORT_CREATING		0x01
+#define FC_VPORT_DELETING		0x02
+#define FC_VPORT_DELETED		0x04
+#define FC_VPORT_DEL			0x06	/* Any DELETE state */
+
+#define	dev_to_vport(d)				\
+	container_of(d, struct fc_vport, dev)
+#define transport_class_to_vport(classdev)	\
+	dev_to_vport(classdev->dev)
+#define vport_to_shost(v)			\
+	(v->shost)
+#define vport_to_shost_channel(v)		\
+	(v->channel)
+#define vport_to_parent(v)			\
+	(v->dev.parent)
+
+
+/* Error return codes for vport_create() callback */
+#define VPCERR_UNSUPPORTED		-ENOSYS		/* no driver/adapter
+							   support */
+#define VPCERR_BAD_WWN			-ENOTUNIQ	/* driver validation
+							   of WWNs failed */
+#define VPCERR_NO_FABRIC_SUPP		-EOPNOTSUPP	/* Fabric connection
+							   is loop or the
+							   Fabric Port does
+							   not support NPIV */
 
 /*
  * fc_rport_identifiers: This set of data contains all elements
@@ -149,6 +268,7 @@
 	u32 roles;
 };
 
+
 /* Macro for use in defining Remote Port attributes */
 #define FC_RPORT_ATTR(_name,_mode,_show,_store)				\
 struct class_device_attribute class_device_attr_rport_##_name = 	\
@@ -278,7 +398,7 @@
 	u64 prim_seq_protocol_err_count;
 	u64 invalid_tx_word_count;
 	u64 invalid_crc_count;
-	
+
 	/* fc4 statistics  (only FCP supported currently) */
 	u64 fcp_input_requests;
 	u64 fcp_output_requests;
@@ -343,6 +463,7 @@
 	u8  supported_fc4s[FC_FC4_LIST_SIZE];
 	u32 supported_speeds;
 	u32 maxframe_size;
+	u16 max_npiv_vports;
 	char serial_number[FC_SERIAL_NUMBER_SIZE];
 
 	/* Dynamic Attributes */
@@ -361,8 +482,11 @@
 	/* internal data */
 	struct list_head rports;
 	struct list_head rport_bindings;
+	struct list_head vports;
 	u32 next_rport_number;
 	u32 next_target_id;
+	u32 next_vport_number;
+	u16 npiv_vports_inuse;
 
 	/* work queues for rport state manipulation */
 	char work_q_name[KOBJ_NAME_LEN];
@@ -388,6 +512,8 @@
 	(((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
 #define fc_host_maxframe_size(x)	\
 	(((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
+#define fc_host_max_npiv_vports(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->max_npiv_vports)
 #define fc_host_serial_number(x)	\
 	(((struct fc_host_attrs *)(x)->shost_data)->serial_number)
 #define fc_host_port_id(x)	\
@@ -412,10 +538,16 @@
 	(((struct fc_host_attrs *)(x)->shost_data)->rports)
 #define fc_host_rport_bindings(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->rport_bindings)
+#define fc_host_vports(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->vports)
 #define fc_host_next_rport_number(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
 #define fc_host_next_target_id(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
+#define fc_host_next_vport_number(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->next_vport_number)
+#define fc_host_npiv_vports_inuse(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->npiv_vports_inuse)
 #define fc_host_work_q_name(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
 #define fc_host_work_q(x) \
@@ -452,14 +584,20 @@
 	void    (*dev_loss_tmo_callbk)(struct fc_rport *);
 	void	(*terminate_rport_io)(struct fc_rport *);
 
+	void	(*set_vport_symbolic_name)(struct fc_vport *);
+	int  	(*vport_create)(struct fc_vport *, bool);
+	int	(*vport_disable)(struct fc_vport *, bool);
+	int  	(*vport_delete)(struct fc_vport *);
+
 	/* allocation lengths for host-specific data */
 	u32	 			dd_fcrport_size;
+	u32	 			dd_fcvport_size;
 
-	/* 
+	/*
 	 * The driver sets these to tell the transport class it
 	 * wants the attributes displayed in sysfs.  If the show_ flag
 	 * is not set, the attribute will be private to the transport
-	 * class 
+	 * class
 	 */
 
 	/* remote port fixed attributes */
@@ -512,7 +650,7 @@
 
 	switch (rport->port_state) {
 	case FC_PORTSTATE_ONLINE:
-		if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+		if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
 			result = 0;
 		else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
 			result = DID_IMM_RETRY << 16;
@@ -549,6 +687,27 @@
 	wwn[7] = inm & 0xff;
 }
 
+/**
+ * fc_vport_set_state() - called to set a vport's state. Saves the old state,
+ *   excepting the transitory states of initializing and sending the ELS
+ *   traffic to instantiate the vport on the link.
+ *
+ * Assumes the driver has surrounded this with the proper locking to ensure
+ * a coherent state change.
+ *
+ * @vport:	virtual port whose state is changing
+ * @new_state:  new state
+ **/
+static inline void
+fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state)
+{
+	if ((new_state != FC_VPORT_UNKNOWN) &&
+	    (new_state != FC_VPORT_INITIALIZING))
+		vport->vport_last_state = vport->vport_state;
+	vport->vport_state = new_state;
+}
+
+
 struct scsi_transport_template *fc_attach_transport(
 			struct fc_function_template *);
 void fc_release_transport(struct scsi_transport_template *);
@@ -567,5 +726,6 @@
 	 *   be sure to read the Vendor Type and ID formatting requirements
 	 *   specified in scsi_netlink.h
 	 */
+int fc_vport_terminate(struct fc_vport *vport);
 
 #endif /* SCSI_TRANSPORT_FC_H */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index d5c218d..706c0cd 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -79,7 +79,8 @@
 	char *name;
 	unsigned int caps;
 	/* LLD sets this to indicate what values it can export to sysfs */
-	unsigned int param_mask;
+	uint64_t param_mask;
+	uint64_t host_param_mask;
 	struct scsi_host_template *host_template;
 	/* LLD connection data size */
 	int conndata_size;
@@ -89,7 +90,8 @@
 	unsigned int max_conn;
 	unsigned int max_cmd_len;
 	struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
-		struct scsi_transport_template *t, uint32_t sn, uint32_t *hn);
+		struct scsi_transport_template *t, uint16_t, uint16_t,
+		uint32_t sn, uint32_t *hn);
 	void (*destroy_session) (struct iscsi_cls_session *session);
 	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
 				uint32_t cid);
@@ -105,14 +107,18 @@
 			       enum iscsi_param param, char *buf);
 	int (*get_session_param) (struct iscsi_cls_session *session,
 				  enum iscsi_param param, char *buf);
+	int (*get_host_param) (struct Scsi_Host *shost,
+				enum iscsi_host_param param, char *buf);
+	int (*set_host_param) (struct Scsi_Host *shost,
+			       enum iscsi_host_param param, char *buf,
+			       int buflen);
 	int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
 			 char *data, uint32_t data_size);
 	void (*get_stats) (struct iscsi_cls_conn *conn,
 			   struct iscsi_stats *stats);
 	void (*init_cmd_task) (struct iscsi_cmd_task *ctask);
 	void (*init_mgmt_task) (struct iscsi_conn *conn,
-				struct iscsi_mgmt_task *mtask,
-				char *data, uint32_t data_size);
+				struct iscsi_mgmt_task *mtask);
 	int (*xmit_cmd_task) (struct iscsi_conn *conn,
 			      struct iscsi_cmd_task *ctask);
 	void (*cleanup_cmd_task) (struct iscsi_conn *conn,
@@ -124,7 +130,7 @@
 			   uint64_t *ep_handle);
 	int (*ep_poll) (uint64_t ep_handle, int timeout_ms);
 	void (*ep_disconnect) (uint64_t ep_handle);
-	int (*tgt_dscvr) (enum iscsi_tgt_dscvr type, uint32_t host_no,
+	int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
 			  uint32_t enable, struct sockaddr *dst_addr);
 };
 
diff --git a/include/sound/version.h b/include/sound/version.h
index 50ee4fd..8e5b2f0 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by alsa/ksync script.  */
-#define CONFIG_SND_VERSION "1.0.14rc4"
-#define CONFIG_SND_DATE " (Wed May 16 09:45:46 2007 UTC)"
+#define CONFIG_SND_VERSION "1.0.14"
+#define CONFIG_SND_DATE " (Thu May 31 09:03:25 2007 UTC)"
diff --git a/include/video/tgafb.h b/include/video/tgafb.h
index 03d0dbe..7bc5e2c 100644
--- a/include/video/tgafb.h
+++ b/include/video/tgafb.h
@@ -216,6 +216,7 @@
 	u32 pll_freq;			/* pixclock in mhz */
 	u32 bits_per_pixel;		/* bits per pixel */
 	u32 sync_on_green;		/* set if sync is on green */
+	u32 palette[16];
 };
 
 
diff --git a/init/Kconfig b/init/Kconfig
index a9e99f8..e205682 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -120,15 +120,6 @@
 	  section 6.4 of the Linux Programmer's Guide, available from
 	  <http://www.tldp.org/guides.html>.
 
-config IPC_NS
-	bool "IPC Namespaces"
-	depends on SYSVIPC
-	default n
-	help
-	  Support ipc namespaces.  This allows containers, i.e. virtual
-	  environments, to use ipc namespaces to provide different ipc
-	  objects for different servers.  If unsure, say N.
-
 config SYSVIPC_SYSCTL
 	bool
 	depends on SYSVIPC
@@ -218,13 +209,14 @@
 
 	  Say N if unsure.
 
-config UTS_NS
-	bool "UTS Namespaces"
+config USER_NS
+	bool "User Namespaces (EXPERIMENTAL)"
 	default n
+	depends on EXPERIMENTAL
 	help
-	  Support uts namespaces.  This allows containers, i.e.
-	  vservers, to use uts namespaces to provide different
-	  uts info for different servers.  If unsure, say N.
+	  Support user namespaces.  This allows containers, i.e.
+	  vservers, to use user namespaces to provide different
+	  user info for different servers.  If unsure, say N.
 
 config AUDIT
 	bool "Auditing support"
@@ -554,7 +546,7 @@
 
 choice
 	prompt "Choose SLAB allocator"
-	default SLAB
+	default SLUB
 	help
 	   This option allows to select a slab allocator.
 
@@ -576,7 +568,7 @@
 	   and has enhanced diagnostics.
 
 config SLOB
-	depends on EMBEDDED && !SPARSEMEM
+	depends on EMBEDDED
 	bool "SLOB (Simple Allocator)"
 	help
 	   SLOB replaces the SLAB allocator with a drastically simpler
@@ -602,9 +594,7 @@
 	default 0 if BASE_FULL
 	default 1 if !BASE_FULL
 
-menu "Loadable module support"
-
-config MODULES
+menuconfig MODULES
 	bool "Enable loadable module support"
 	help
 	  Kernel modules are small pieces of compiled code which can
@@ -684,8 +674,5 @@
 	depends on (SMP && MODULE_UNLOAD) || HOTPLUG_CPU
 	help
 	  Need stop_machine() primitive.
-endmenu
 
-menu "Block layer"
 source "block/Kconfig"
-endmenu
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 46fe407..4efa1e5 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -25,6 +25,7 @@
 int root_mountflags = MS_RDONLY | MS_SILENT;
 char * __initdata root_device_name;
 static char __initdata saved_root_name[64];
+static int __initdata root_wait;
 
 dev_t ROOT_DEV;
 
@@ -216,6 +217,16 @@
 
 __setup("root=", root_dev_setup);
 
+static int __init rootwait_setup(char *str)
+{
+	if (*str)
+		return 0;
+	root_wait = 1;
+	return 1;
+}
+
+__setup("rootwait", rootwait_setup);
+
 static char * __initdata root_mount_data;
 static int __init root_data_setup(char *str)
 {
@@ -438,11 +449,20 @@
 			root_device_name += 5;
 	}
 
-	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
-
 	if (initrd_load())
 		goto out;
 
+	/* wait for any asynchronous scanning to complete */
+	if ((ROOT_DEV == 0) && root_wait) {
+		printk(KERN_INFO "Waiting for root device %s...\n",
+			saved_root_name);
+		while (driver_probe_done() != 0 ||
+			(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
+			msleep(100);
+	}
+
+	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+
 	if (is_floppy && rd_doload && rd_load_disk(0))
 		ROOT_DEV = Root_RAM0;
 
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index b222ce9..a6b4c0c 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -56,12 +56,9 @@
 	sys_chroot(".");
 
 	pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
-	if (pid > 0) {
-		while (pid != sys_wait4(-1, NULL, 0, NULL)) {
-			try_to_freeze();
+	if (pid > 0)
+		while (pid != sys_wait4(-1, NULL, 0, NULL))
 			yield();
-		}
-	}
 
 	/* move initrd to rootfs' /old */
 	sys_fchdir(old_fd);
diff --git a/init/main.c b/init/main.c
index 1940fa7..d3bcb3b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -132,20 +132,9 @@
 static char *execute_command;
 static char *ramdisk_execute_command;
 
+#ifdef CONFIG_SMP
 /* Setup configured maximum number of CPUs to activate */
-static unsigned int max_cpus = NR_CPUS;
-
-/*
- * If set, this is an indication to the drivers that reset the underlying
- * device before going ahead with the initialization otherwise driver might
- * rely on the BIOS and skip the reset operation.
- *
- * This is useful if kernel is booting in an unreliable environment.
- * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
- * skipped and devices will be in unknown state.
- */
-unsigned int reset_devices;
-EXPORT_SYMBOL(reset_devices);
+static unsigned int __initdata max_cpus = NR_CPUS;
 
 /*
  * Setup routine for controlling SMP activation
@@ -160,10 +149,10 @@
 static int __init nosmp(char *str)
 {
 	max_cpus = 0;
-	return 1;
+	return 0;
 }
 
-__setup("nosmp", nosmp);
+early_param("nosmp", nosmp);
 
 static int __init maxcpus(char *str)
 {
@@ -172,6 +161,21 @@
 }
 
 __setup("maxcpus=", maxcpus);
+#else
+#define max_cpus NR_CPUS
+#endif
+
+/*
+ * If set, this is an indication to the drivers that reset the underlying
+ * device before going ahead with the initialization otherwise driver might
+ * rely on the BIOS and skip the reset operation.
+ *
+ * This is useful if kernel is booting in an unreliable environment.
+ * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
+ * skipped and devices will be in unknown state.
+ */
+unsigned int reset_devices;
+EXPORT_SYMBOL(reset_devices);
 
 static int __init set_reset_devices(char *str)
 {
@@ -385,6 +389,10 @@
 {
 	unsigned int cpu;
 
+#ifndef CONFIG_HOTPLUG_CPU
+	cpu_possible_map = cpu_present_map;
+#endif
+
 	/* FIXME: This should be done in userspace --RR */
 	for_each_present_cpu(cpu) {
 		if (num_online_cpus() >= max_cpus)
@@ -423,7 +431,7 @@
  * gcc-3.4 accidentally inlines this function, so use noinline.
  */
 
-static void noinline rest_init(void)
+static void noinline __init_refok rest_init(void)
 	__releases(kernel_lock)
 {
 	int pid;
@@ -436,15 +444,16 @@
 
 	/*
 	 * The boot idle thread must execute schedule()
-	 * at least one to get things moving:
+	 * at least once to get things moving:
 	 */
+	init_idle_bootup_task(current);
 	preempt_enable_no_resched();
 	schedule();
 	preempt_disable();
 
 	/* Call into cpu_idle with preempt disabled */
 	cpu_idle();
-} 
+}
 
 /* Check for early params. */
 static int __init do_early_param(char *param, char *val)
@@ -452,7 +461,10 @@
 	struct obs_kernel_param *p;
 
 	for (p = __setup_start; p < __setup_end; p++) {
-		if (p->early && strcmp(param, p->str) == 0) {
+		if ((p->early && strcmp(param, p->str) == 0) ||
+		    (strcmp(param, "console") == 0 &&
+		     strcmp(p->str, "earlycon") == 0)
+		) {
 			if (p->setup_func(val) != 0)
 				printk(KERN_WARNING
 				       "Malformed early option '%s'\n", param);
@@ -525,6 +537,10 @@
 	setup_arch(&command_line);
 	setup_command_line(command_line);
 	unwind_setup();
+#ifndef CONFIG_HOTPLUG_CPU
+	if (max_cpus < 2)
+		cpu_possible_map = cpu_online_map;
+#endif
 	setup_per_cpu_areas();
 	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
 
@@ -724,6 +740,15 @@
 	do_initcalls();
 }
 
+static int __initdata nosoftlockup;
+
+static int __init nosoftlockup_setup(char *str)
+{
+	nosoftlockup = 1;
+	return 1;
+}
+__setup("nosoftlockup", nosoftlockup_setup);
+
 static void __init do_pre_smp_initcalls(void)
 {
 	extern int spawn_ksoftirqd(void);
@@ -733,7 +758,8 @@
 	migration_init();
 #endif
 	spawn_ksoftirqd();
-	spawn_softlockup_task();
+	if (!nosoftlockup)
+		spawn_softlockup_task();
 }
 
 static void run_init_process(char *init_filename)
diff --git a/ipc/compat.c b/ipc/compat.c
index 8b44aa9a..ab76fb0 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -225,7 +225,7 @@
 	int err;
 
 	if (!access_ok (VERIFY_WRITE, up, sizeof(*up)))
-		err = -EFAULT;
+		return -EFAULT;
 	err  = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
 	err |= __put_user(s->sem_otime, &up->sem_otime);
 	err |= __put_user(s->sem_ctime, &up->sem_ctime);
diff --git a/ipc/msg.c b/ipc/msg.c
index a388824..a03fcb52 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -87,7 +87,7 @@
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
 #endif
 
-static void __ipc_init __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
 {
 	ns->ids[IPC_MSG_IDS] = ids;
 	ns->msg_ctlmax = MSGMAX;
@@ -96,7 +96,6 @@
 	ipc_init_ids(ids, ns->msg_ctlmni);
 }
 
-#ifdef CONFIG_IPC_NS
 int msg_init_ns(struct ipc_namespace *ns)
 {
 	struct ipc_ids *ids;
@@ -128,7 +127,6 @@
 	kfree(ns->ids[IPC_MSG_IDS]);
 	ns->ids[IPC_MSG_IDS] = NULL;
 }
-#endif
 
 void __init msg_init(void)
 {
@@ -387,7 +385,7 @@
 asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
 {
 	struct kern_ipc_perm *ipcp;
-	struct msq_setbuf setbuf;
+	struct msq_setbuf uninitialized_var(setbuf);
 	struct msg_queue *msq;
 	int err, version;
 	struct ipc_namespace *ns;
@@ -511,7 +509,7 @@
 	err = audit_ipc_obj(ipcp);
 	if (err)
 		goto out_unlock_up;
-	if (cmd==IPC_SET) {
+	if (cmd == IPC_SET) {
 		err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid,
 					 setbuf.mode);
 		if (err)
diff --git a/ipc/sem.c b/ipc/sem.c
index 9964b22..b676fef 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -121,7 +121,7 @@
 #define sc_semopm	sem_ctls[2]
 #define sc_semmni	sem_ctls[3]
 
-static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
 {
 	ns->ids[IPC_SEM_IDS] = ids;
 	ns->sc_semmsl = SEMMSL;
@@ -132,7 +132,6 @@
 	ipc_init_ids(ids, ns->sc_semmni);
 }
 
-#ifdef CONFIG_IPC_NS
 int sem_init_ns(struct ipc_namespace *ns)
 {
 	struct ipc_ids *ids;
@@ -164,7 +163,6 @@
 	kfree(ns->ids[IPC_SEM_IDS]);
 	ns->ids[IPC_SEM_IDS] = NULL;
 }
-#endif
 
 void __init sem_init (void)
 {
@@ -858,7 +856,7 @@
 {
 	struct sem_array *sma;
 	int err;
-	struct sem_setbuf setbuf;
+	struct sem_setbuf uninitialized_var(setbuf);
 	struct kern_ipc_perm *ipcp;
 
 	if(cmd == IPC_SET) {
diff --git a/ipc/shm.c b/ipc/shm.c
index 4fefbad..242c3f6 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -77,7 +77,7 @@
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
 #endif
 
-static void __ipc_init __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
 {
 	ns->ids[IPC_SHM_IDS] = ids;
 	ns->shm_ctlmax = SHMMAX;
@@ -98,7 +98,6 @@
 		shm_destroy(ns, shp);
 }
 
-#ifdef CONFIG_IPC_NS
 int shm_init_ns(struct ipc_namespace *ns)
 {
 	struct ipc_ids *ids;
@@ -130,7 +129,6 @@
 	kfree(ns->ids[IPC_SHM_IDS]);
 	ns->ids[IPC_SHM_IDS] = NULL;
 }
-#endif
 
 void __init shm_init (void)
 {
@@ -254,8 +252,10 @@
 
 	if (sfd->vm_ops->get_policy)
 		pol = sfd->vm_ops->get_policy(vma, addr);
-	else
+	else if (vma->vm_policy)
 		pol = vma->vm_policy;
+	else
+		pol = current->mempolicy;
 	return pol;
 }
 #endif
@@ -364,9 +364,10 @@
 		return error;
 	}
 
+	sprintf (name, "SYSV%08x", key);
 	if (shmflg & SHM_HUGETLB) {
-		/* hugetlb_zero_setup takes care of mlock user accounting */
-		file = hugetlb_zero_setup(size);
+		/* hugetlb_file_setup takes care of mlock user accounting */
+		file = hugetlb_file_setup(name, size);
 		shp->mlock_user = current->user;
 	} else {
 		int acctflag = VM_ACCOUNT;
@@ -377,7 +378,6 @@
 		if  ((shmflg & SHM_NORESERVE) &&
 				sysctl_overcommit_memory != OVERCOMMIT_NEVER)
 			acctflag = 0;
-		sprintf (name, "SYSV%08x", key);
 		file = shmem_file_setup(name, size, acctflag);
 	}
 	error = PTR_ERR(file);
@@ -397,6 +397,11 @@
 	shp->shm_nattch = 0;
 	shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
 	shp->shm_file = file;
+	/*
+	 * shmid gets reported as "inode#" in /proc/pid/maps.
+	 * proc-ps tools use this. Changing this will break them.
+	 */
+	file->f_dentry->d_inode->i_ino = shp->id;
 
 	ns->shm_tot += numpages;
 	shm_unlock(shp);
diff --git a/ipc/util.c b/ipc/util.c
index 7536a72..44e5135 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -50,7 +50,6 @@
 	},
 };
 
-#ifdef CONFIG_IPC_NS
 static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
 {
 	int err;
@@ -110,14 +109,6 @@
 	shm_exit_ns(ns);
 	kfree(ns);
 }
-#else
-struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
-{
-	if (flags & CLONE_NEWIPC)
-		return ERR_PTR(-EINVAL);
-	return ns;
-}
-#endif
 
 /**
  *	ipc_init	-	initialise IPC subsystem
@@ -145,7 +136,7 @@
  *	array itself. 
  */
  
-void __ipc_init ipc_init_ids(struct ipc_ids* ids, int size)
+void ipc_init_ids(struct ipc_ids* ids, int size)
 {
 	int i;
 
diff --git a/ipc/util.h b/ipc/util.h
index e3aa2c5..333e891 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -41,12 +41,8 @@
 };
 
 struct seq_file;
-#ifdef CONFIG_IPC_NS
-#define __ipc_init
-#else
-#define __ipc_init	__init
-#endif
-void __ipc_init ipc_init_ids(struct ipc_ids *ids, int size);
+
+void ipc_init_ids(struct ipc_ids *ids, int size);
 #ifdef CONFIG_PROC_FS
 void __init ipc_init_proc_interface(const char *path, const char *header,
 		int ids, int (*show)(struct seq_file *, void *));
diff --git a/kernel/Makefile b/kernel/Makefile
index 642d427..2a99983 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -4,11 +4,12 @@
 
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
 	    exit.o itimer.o time.o softirq.o resource.o \
-	    sysctl.o capability.o ptrace.o timer.o user.o \
+	    sysctl.o capability.o ptrace.o timer.o user.o user_namespace.o \
 	    signal.o sys.o kmod.o workqueue.o pid.o \
 	    rcupdate.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
-	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o
+	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o \
+	    utsname.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-y += time/
@@ -48,7 +49,6 @@
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RELAY) += relay.o
 obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
-obj-$(CONFIG_UTS_NS) += utsname.o
 obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
 obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
 
diff --git a/kernel/audit.c b/kernel/audit.c
index d13276d..eb0f916 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -58,6 +58,7 @@
 #include <linux/selinux.h>
 #include <linux/inotify.h>
 #include <linux/freezer.h>
+#include <linux/tty.h>
 
 #include "audit.h"
 
@@ -391,6 +392,7 @@
 {
 	struct sk_buff *skb;
 
+	set_freezable();
 	while (!kthread_should_stop()) {
 		skb = skb_dequeue(&audit_skb_queue);
 		wake_up(&audit_backlog_wait);
@@ -423,6 +425,31 @@
 	return 0;
 }
 
+static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
+{
+	struct task_struct *tsk;
+	int err;
+
+	read_lock(&tasklist_lock);
+	tsk = find_task_by_pid(pid);
+	err = -ESRCH;
+	if (!tsk)
+		goto out;
+	err = 0;
+
+	spin_lock_irq(&tsk->sighand->siglock);
+	if (!tsk->signal->audit_tty)
+		err = -EPERM;
+	spin_unlock_irq(&tsk->sighand->siglock);
+	if (err)
+		goto out;
+
+	tty_audit_push_task(tsk, loginuid);
+out:
+	read_unlock(&tasklist_lock);
+	return err;
+}
+
 int audit_send_list(void *_dest)
 {
 	struct audit_netlink_list *dest = _dest;
@@ -511,6 +538,8 @@
 	case AUDIT_DEL:
 	case AUDIT_DEL_RULE:
 	case AUDIT_SIGNAL_INFO:
+	case AUDIT_TTY_GET:
+	case AUDIT_TTY_SET:
 		if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
 			err = -EPERM;
 		break;
@@ -622,6 +651,11 @@
 		err = audit_filter_user(&NETLINK_CB(skb), msg_type);
 		if (err == 1) {
 			err = 0;
+			if (msg_type == AUDIT_USER_TTY) {
+				err = audit_prepare_user_tty(pid, loginuid);
+				if (err)
+					break;
+			}
 			ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
 			if (ab) {
 				audit_log_format(ab,
@@ -638,8 +672,17 @@
 							" subj=%s", ctx);
 					kfree(ctx);
 				}
-				audit_log_format(ab, " msg='%.1024s'",
-					 (char *)data);
+				if (msg_type != AUDIT_USER_TTY)
+					audit_log_format(ab, " msg='%.1024s'",
+							 (char *)data);
+				else {
+					int size;
+
+					audit_log_format(ab, " msg=");
+					size = nlmsg_len(nlh);
+					audit_log_n_untrustedstring(ab, size,
+								    data);
+				}
 				audit_set_pid(ab, pid);
 				audit_log_end(ab);
 			}
@@ -730,6 +773,45 @@
 				0, 0, sig_data, sizeof(*sig_data) + len);
 		kfree(sig_data);
 		break;
+	case AUDIT_TTY_GET: {
+		struct audit_tty_status s;
+		struct task_struct *tsk;
+
+		read_lock(&tasklist_lock);
+		tsk = find_task_by_pid(pid);
+		if (!tsk)
+			err = -ESRCH;
+		else {
+			spin_lock_irq(&tsk->sighand->siglock);
+			s.enabled = tsk->signal->audit_tty != 0;
+			spin_unlock_irq(&tsk->sighand->siglock);
+		}
+		read_unlock(&tasklist_lock);
+		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0,
+				 &s, sizeof(s));
+		break;
+	}
+	case AUDIT_TTY_SET: {
+		struct audit_tty_status *s;
+		struct task_struct *tsk;
+
+		if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
+			return -EINVAL;
+		s = data;
+		if (s->enabled != 0 && s->enabled != 1)
+			return -EINVAL;
+		read_lock(&tasklist_lock);
+		tsk = find_task_by_pid(pid);
+		if (!tsk)
+			err = -ESRCH;
+		else {
+			spin_lock_irq(&tsk->sighand->siglock);
+			tsk->signal->audit_tty = s->enabled != 0;
+			spin_unlock_irq(&tsk->sighand->siglock);
+		}
+		read_unlock(&tasklist_lock);
+		break;
+	}
 	default:
 		err = -EINVAL;
 		break;
@@ -1185,7 +1267,7 @@
 }
 
 /**
- * audit_log_n_unstrustedstring - log a string that may contain random characters
+ * audit_log_n_untrustedstring - log a string that may contain random characters
  * @ab: audit_buffer
  * @len: lenth of string (not including trailing null)
  * @string: string to be logged
@@ -1201,25 +1283,24 @@
 const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
 					const char *string)
 {
-	const unsigned char *p = string;
+	const unsigned char *p;
 
-	while (*p) {
+	for (p = string; p < (const unsigned char *)string + len && *p; p++) {
 		if (*p == '"' || *p < 0x21 || *p > 0x7f) {
 			audit_log_hex(ab, string, len);
 			return string + len + 1;
 		}
-		p++;
 	}
 	audit_log_n_string(ab, len, string);
 	return p + 1;
 }
 
 /**
- * audit_log_unstrustedstring - log a string that may contain random characters
+ * audit_log_untrustedstring - log a string that may contain random characters
  * @ab: audit_buffer
  * @string: string to be logged
  *
- * Same as audit_log_n_unstrustedstring(), except that strlen is used to
+ * Same as audit_log_n_untrustedstring(), except that strlen is used to
  * determine string length.
  */
 const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
diff --git a/kernel/audit.h b/kernel/audit.h
index 815d6f5..9587743 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -115,7 +115,6 @@
 extern void		    audit_send_reply(int pid, int seq, int type,
 					     int done, int multi,
 					     void *payload, int size);
-extern void		    audit_log_lost(const char *message);
 extern void		    audit_panic(const char *message);
 
 struct audit_netlink_list {
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 74cc0fc..1bf093d 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -947,7 +947,7 @@
 
 		/* If the update involves invalidating rules, do the inode-based
 		 * filtering now, so we don't omit records. */
-		if (invalidating &&
+		if (invalidating && current->audit_context &&
 		    audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT)
 			audit_set_auditable(current->audit_context);
 
@@ -1210,8 +1210,8 @@
 	struct audit_entry *e;
 	struct audit_field *inode_f = entry->rule.inode_f;
 	struct audit_watch *watch = entry->rule.watch;
-	struct nameidata *ndp, *ndw;
-	int h, err, putnd_needed = 0;
+	struct nameidata *ndp = NULL, *ndw = NULL;
+	int h, err;
 #ifdef CONFIG_AUDITSYSCALL
 	int dont_count = 0;
 
@@ -1239,7 +1239,6 @@
 		err = audit_get_nd(watch->path, &ndp, &ndw);
 		if (err)
 			goto error;
-		putnd_needed = 1;
 	}
 
 	mutex_lock(&audit_filter_mutex);
@@ -1269,14 +1268,11 @@
 #endif
 	mutex_unlock(&audit_filter_mutex);
 
-	if (putnd_needed)
-		audit_put_nd(ndp, ndw);
-
+	audit_put_nd(ndp, ndw);		/* NULL args OK */
  	return 0;
 
 error:
-	if (putnd_needed)
-		audit_put_nd(ndp, ndw);
+	audit_put_nd(ndp, ndw);		/* NULL args OK */
 	if (watch)
 		audit_put_watch(watch); /* tmp watch, matches initial get */
 	return err;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e36481e..b7640a5 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -71,9 +71,6 @@
 
 extern struct list_head audit_filter_list[];
 
-/* No syscall auditing will take place unless audit_enabled != 0. */
-extern int audit_enabled;
-
 /* AUDIT_NAMES is the number of slots we reserve in the audit_context
  * for saving names from getname(). */
 #define AUDIT_NAMES    20
@@ -2040,7 +2037,7 @@
 
 /**
  * audit_core_dumps - record information about processes that end abnormally
- * @sig: signal value
+ * @signr: signal value
  *
  * If a process ends with a core dump, something fishy is going on and we
  * should record the event for investigation.
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 208cf34..181ae70 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -103,11 +103,19 @@
 	write_unlock_irq(&tasklist_lock);
 }
 
+struct take_cpu_down_param {
+	unsigned long mod;
+	void *hcpu;
+};
+
 /* Take this CPU down. */
-static int take_cpu_down(void *unused)
+static int take_cpu_down(void *_param)
 {
+	struct take_cpu_down_param *param = _param;
 	int err;
 
+	raw_notifier_call_chain(&cpu_chain, CPU_DYING | param->mod,
+				param->hcpu);
 	/* Ensure this CPU doesn't handle any more interrupts. */
 	err = __cpu_disable();
 	if (err < 0)
@@ -127,6 +135,10 @@
 	cpumask_t old_allowed, tmp;
 	void *hcpu = (void *)(long)cpu;
 	unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
+	struct take_cpu_down_param tcd_param = {
+		.mod = mod,
+		.hcpu = hcpu,
+	};
 
 	if (num_online_cpus() == 1)
 		return -EBUSY;
@@ -153,7 +165,7 @@
 	set_cpus_allowed(current, tmp);
 
 	mutex_lock(&cpu_bitmask_lock);
-	p = __stop_machine_run(take_cpu_down, NULL, cpu);
+	p = __stop_machine_run(take_cpu_down, &tcd_param, cpu);
 	mutex_unlock(&cpu_bitmask_lock);
 
 	if (IS_ERR(p) || cpu_online(cpu)) {
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index f57854b..b4796d8 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -981,10 +981,10 @@
 		mmarray = kmalloc(ntasks * sizeof(*mmarray), GFP_KERNEL);
 		if (!mmarray)
 			goto done;
-		write_lock_irq(&tasklist_lock);		/* block fork */
+		read_lock(&tasklist_lock);		/* block fork */
 		if (atomic_read(&cs->count) <= ntasks)
 			break;				/* got enough */
-		write_unlock_irq(&tasklist_lock);	/* try again */
+		read_unlock(&tasklist_lock);		/* try again */
 		kfree(mmarray);
 	}
 
@@ -1006,7 +1006,7 @@
 			continue;
 		mmarray[n++] = mm;
 	} while_each_thread(g, p);
-	write_unlock_irq(&tasklist_lock);
+	read_unlock(&tasklist_lock);
 
 	/*
 	 * Now that we've dropped the tasklist spinlock, we can
@@ -1682,9 +1682,9 @@
 
 	do_each_thread(g, p) {
 		if (p->cpuset == cs) {
-			pidarray[n++] = p->pid;
 			if (unlikely(n == npids))
 				goto array_full;
+			pidarray[n++] = p->pid;
 		}
 	} while_each_thread(g, p);
 
@@ -2138,6 +2138,9 @@
 static int cpuset_handle_cpuhp(struct notifier_block *nb,
 				unsigned long phase, void *cpu)
 {
+	if (phase == CPU_DYING || phase == CPU_DYING_FROZEN)
+		return NOTIFY_DONE;
+
 	common_cpu_mem_hotplug_unplug();
 	return 0;
 }
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index c0148ae..81e6978 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -99,9 +99,10 @@
 int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
 {
 	s64 tmp;
-	struct timespec ts;
-	unsigned long t1,t2,t3;
+	unsigned long t1;
+	unsigned long long t2, t3;
 	unsigned long flags;
+	struct timespec ts;
 
 	/* Though tsk->delays accessed later, early exit avoids
 	 * unnecessary returning of other data
@@ -124,11 +125,10 @@
 
 	d->cpu_count += t1;
 
-	jiffies_to_timespec(t2, &ts);
-	tmp = (s64)d->cpu_delay_total + timespec_to_ns(&ts);
+	tmp = (s64)d->cpu_delay_total + t2;
 	d->cpu_delay_total = (tmp < (s64)d->cpu_delay_total) ? 0 : tmp;
 
-	tmp = (s64)d->cpu_run_virtual_total + (s64)jiffies_to_usecs(t3) * 1000;
+	tmp = (s64)d->cpu_run_virtual_total + t3;
 	d->cpu_run_virtual_total =
 		(tmp < (s64)d->cpu_run_virtual_total) ?	0 : tmp;
 
diff --git a/kernel/exit.c b/kernel/exit.c
index c6d14b8..e8af8d0 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -31,6 +31,7 @@
 #include <linux/mempolicy.h>
 #include <linux/taskstats_kern.h>
 #include <linux/delayacct.h>
+#include <linux/freezer.h>
 #include <linux/cpuset.h>
 #include <linux/syscalls.h>
 #include <linux/signal.h>
@@ -122,9 +123,9 @@
 		sig->maj_flt += tsk->maj_flt;
 		sig->nvcsw += tsk->nvcsw;
 		sig->nivcsw += tsk->nivcsw;
-		sig->sched_time += tsk->sched_time;
 		sig->inblock += task_io_get_inblock(tsk);
 		sig->oublock += task_io_get_oublock(tsk);
+		sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
 		sig = NULL; /* Marker for below. */
 	}
 
@@ -182,7 +183,6 @@
 		zap_leader = (leader->exit_signal == -1);
 	}
 
-	sched_exit(p);
 	write_unlock_irq(&tasklist_lock);
 	proc_flush_task(p);
 	release_thread(p);
@@ -291,7 +291,7 @@
 	/* Set the exit signal to SIGCHLD so we signal init on exit */
 	current->exit_signal = SIGCHLD;
 
-	if (!has_rt_policy(current) && (task_nice(current) < 0))
+	if (task_nice(current) < 0)
 		set_user_nice(current, 0);
 	/* cpus_allowed? */
 	/* rt_priority? */
@@ -388,6 +388,11 @@
 	 * they would be locked into memory.
 	 */
 	exit_mm(current);
+	/*
+	 * We don't want to have TIF_FREEZE set if the system-wide hibernation
+	 * or suspend transition begins right now.
+	 */
+	current->flags |= PF_NOFREEZE;
 
 	set_special_pids(1, 1);
 	proc_clear_tty(current);
@@ -762,11 +767,8 @@
 		read_lock(&tasklist_lock);
 		spin_lock_irq(&tsk->sighand->siglock);
 		for (t = next_thread(tsk); t != tsk; t = next_thread(t))
-			if (!signal_pending(t) && !(t->flags & PF_EXITING)) {
-				recalc_sigpending_tsk(t);
-				if (signal_pending(t))
-					signal_wake_up(t, 0);
-			}
+			if (!signal_pending(t) && !(t->flags & PF_EXITING))
+				recalc_sigpending_and_wake(t);
 		spin_unlock_irq(&tsk->sighand->siglock);
 		read_unlock(&tasklist_lock);
 	}
@@ -862,6 +864,34 @@
 		release_task(tsk);
 }
 
+#ifdef CONFIG_DEBUG_STACK_USAGE
+static void check_stack_usage(void)
+{
+	static DEFINE_SPINLOCK(low_water_lock);
+	static int lowest_to_date = THREAD_SIZE;
+	unsigned long *n = end_of_stack(current);
+	unsigned long free;
+
+	while (*n == 0)
+		n++;
+	free = (unsigned long)n - (unsigned long)end_of_stack(current);
+
+	if (free >= lowest_to_date)
+		return;
+
+	spin_lock(&low_water_lock);
+	if (free < lowest_to_date) {
+		printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
+				"left\n",
+				current->comm, free);
+		lowest_to_date = free;
+	}
+	spin_unlock(&low_water_lock);
+}
+#else
+static inline void check_stack_usage(void) {}
+#endif
+
 fastcall NORET_TYPE void do_exit(long code)
 {
 	struct task_struct *tsk = current;
@@ -895,13 +925,29 @@
 	if (unlikely(tsk->flags & PF_EXITING)) {
 		printk(KERN_ALERT
 			"Fixing recursive fault but reboot is needed!\n");
+		/*
+		 * We can do this unlocked here. The futex code uses
+		 * this flag just to verify whether the pi state
+		 * cleanup has been done or not. In the worst case it
+		 * loops once more. We pretend that the cleanup was
+		 * done as there is no way to return. Either the
+		 * OWNER_DIED bit is set by now or we push the blocked
+		 * task into the wait for ever nirwana as well.
+		 */
+		tsk->flags |= PF_EXITPIDONE;
 		if (tsk->io_context)
 			exit_io_context();
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule();
 	}
 
+	/*
+	 * tsk->flags are checked in the futex code to protect against
+	 * an exiting task cleaning up the robust pi futexes.
+	 */
+	spin_lock_irq(&tsk->pi_lock);
 	tsk->flags |= PF_EXITING;
+	spin_unlock_irq(&tsk->pi_lock);
 
 	if (unlikely(in_atomic()))
 		printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
@@ -915,7 +961,7 @@
 	}
 	group_dead = atomic_dec_and_test(&tsk->signal->live);
 	if (group_dead) {
- 		hrtimer_cancel(&tsk->signal->real_timer);
+		hrtimer_cancel(&tsk->signal->real_timer);
 		exit_itimers(tsk->signal);
 	}
 	acct_collect(code, group_dead);
@@ -925,6 +971,8 @@
 	if (unlikely(tsk->compat_robust_list))
 		compat_exit_robust_list(tsk);
 #endif
+	if (group_dead)
+		tty_audit_exit();
 	if (unlikely(tsk->audit_context))
 		audit_free(tsk);
 
@@ -937,6 +985,7 @@
 	exit_sem(tsk);
 	__exit_files(tsk);
 	__exit_fs(tsk);
+	check_stack_usage();
 	exit_thread();
 	cpuset_exit(tsk);
 	exit_keys(tsk);
@@ -968,6 +1017,12 @@
 	 * Make sure we are holding no locks:
 	 */
 	debug_check_no_locks_held(tsk);
+	/*
+	 * We can do this unlocked here. The futex code uses this flag
+	 * just to verify whether the pi state cleanup has been done
+	 * or not. In the worst case it loops once more.
+	 */
+	tsk->flags |= PF_EXITPIDONE;
 
 	if (tsk->io_context)
 		exit_io_context();
diff --git a/kernel/fork.c b/kernel/fork.c
index 87069cf..ba39bdb 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -45,9 +45,11 @@
 #include <linux/acct.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
+#include <linux/freezer.h>
 #include <linux/delayacct.h>
 #include <linux/taskstats_kern.h>
 #include <linux/random.h>
+#include <linux/tty.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -876,7 +878,7 @@
 	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
 	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
 	sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
-	sig->sched_time = 0;
+	sig->sum_sched_runtime = 0;
 	INIT_LIST_HEAD(&sig->cpu_timers[0]);
 	INIT_LIST_HEAD(&sig->cpu_timers[1]);
 	INIT_LIST_HEAD(&sig->cpu_timers[2]);
@@ -896,6 +898,8 @@
 	}
 	acct_init_pacct(&sig->pacct);
 
+	tty_audit_fork(sig);
+
 	return 0;
 }
 
@@ -919,7 +923,7 @@
 {
 	unsigned long new_flags = p->flags;
 
-	new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE);
+	new_flags &= ~PF_SUPERPRIV;
 	new_flags |= PF_FORKNOEXEC;
 	if (!(clone_flags & CLONE_PTRACE))
 		p->ptrace = 0;
@@ -998,7 +1002,7 @@
 	if (atomic_read(&p->user->processes) >=
 			p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
 		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
-				p->user != &root_user)
+		    p->user != current->nsproxy->user_ns->root_user)
 			goto bad_fork_free;
 	}
 
@@ -1039,7 +1043,7 @@
 
 	p->utime = cputime_zero;
 	p->stime = cputime_zero;
- 	p->sched_time = 0;
+
 #ifdef CONFIG_TASK_XACCT
 	p->rchar = 0;		/* I/O counter: bytes read */
 	p->wchar = 0;		/* I/O counter: bytes written */
@@ -1058,6 +1062,8 @@
 
 	p->lock_depth = -1;		/* -1 = no lock */
 	do_posix_clock_monotonic_gettime(&p->start_time);
+	p->real_start_time = p->start_time;
+	monotonic_to_bootbased(&p->real_start_time);
 	p->security = NULL;
 	p->io_context = NULL;
 	p->io_wait = NULL;
@@ -1405,7 +1411,9 @@
 		}
 
 		if (clone_flags & CLONE_VFORK) {
+			freezer_do_not_count();
 			wait_for_completion(&vfork);
+			freezer_count();
 			if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
 				current->ptrace_message = nr;
 				ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
@@ -1598,7 +1606,7 @@
 	err = -EINVAL;
 	if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
 				CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
-				CLONE_NEWUTS|CLONE_NEWIPC))
+				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER))
 		goto bad_unshare_out;
 
 	if ((err = unshare_thread(unshare_flags)))
diff --git a/kernel/futex.c b/kernel/futex.c
index b7ce15c..5c3f45d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -56,12 +56,6 @@
 
 #include "rtmutex_common.h"
 
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
 #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
 
 /*
@@ -111,12 +105,6 @@
 	/* Optional priority inheritance state: */
 	struct futex_pi_state *pi_state;
 	struct task_struct *task;
-
-	/*
-	 * This waiter is used in case of requeue from a
-	 * normal futex to a PI-futex
-	 */
-	struct rt_mutex_waiter waiter;
 };
 
 /*
@@ -133,6 +121,24 @@
 static struct vfsmount *futex_mnt;
 
 /*
+ * Take mm->mmap_sem, when futex is shared
+ */
+static inline void futex_lock_mm(struct rw_semaphore *fshared)
+{
+	if (fshared)
+		down_read(fshared);
+}
+
+/*
+ * Release mm->mmap_sem, when the futex is shared
+ */
+static inline void futex_unlock_mm(struct rw_semaphore *fshared)
+{
+	if (fshared)
+		up_read(fshared);
+}
+
+/*
  * We hash on the keys returned from get_futex_key (see below).
  */
 static struct futex_hash_bucket *hash_futex(union futex_key *key)
@@ -216,9 +222,6 @@
 	if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ))
 		return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES;
 
-	/* Save the user address in the ley */
-	key->uaddr = uaddr;
-
 	/*
 	 * Private mappings are handled in a simple way.
 	 *
@@ -302,7 +305,18 @@
 }
 EXPORT_SYMBOL_GPL(drop_futex_key_refs);
 
-static inline int get_futex_value_locked(u32 *dest, u32 __user *from)
+static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
+{
+	u32 curval;
+
+	pagefault_disable();
+	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	pagefault_enable();
+
+	return curval;
+}
+
+static int get_futex_value_locked(u32 *dest, u32 __user *from)
 {
 	int ret;
 
@@ -424,18 +438,12 @@
 
 	rcu_read_lock();
 	p = find_task_by_pid(pid);
-	if (!p)
-		goto out_unlock;
-	if ((current->euid != p->euid) && (current->euid != p->uid)) {
-		p = NULL;
-		goto out_unlock;
-	}
-	if (p->exit_state != 0) {
-		p = NULL;
-		goto out_unlock;
-	}
-	get_task_struct(p);
-out_unlock:
+
+	if (!p || ((current->euid != p->euid) && (current->euid != p->uid)))
+		p = ERR_PTR(-ESRCH);
+	else
+		get_task_struct(p);
+
 	rcu_read_unlock();
 
 	return p;
@@ -502,7 +510,7 @@
 	struct futex_q *this, *next;
 	struct plist_head *head;
 	struct task_struct *p;
-	pid_t pid;
+	pid_t pid = uval & FUTEX_TID_MASK;
 
 	head = &hb->chain;
 
@@ -520,6 +528,8 @@
 				return -EINVAL;
 
 			WARN_ON(!atomic_read(&pi_state->refcount));
+			WARN_ON(pid && pi_state->owner &&
+				pi_state->owner->pid != pid);
 
 			atomic_inc(&pi_state->refcount);
 			*ps = pi_state;
@@ -530,15 +540,33 @@
 
 	/*
 	 * We are the first waiter - try to look up the real owner and attach
-	 * the new pi_state to it, but bail out when the owner died bit is set
-	 * and TID = 0:
+	 * the new pi_state to it, but bail out when TID = 0
 	 */
-	pid = uval & FUTEX_TID_MASK;
-	if (!pid && (uval & FUTEX_OWNER_DIED))
+	if (!pid)
 		return -ESRCH;
 	p = futex_find_get_task(pid);
-	if (!p)
-		return -ESRCH;
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+
+	/*
+	 * We need to look at the task state flags to figure out,
+	 * whether the task is exiting. To protect against the do_exit
+	 * change of the task flags, we do this protected by
+	 * p->pi_lock:
+	 */
+	spin_lock_irq(&p->pi_lock);
+	if (unlikely(p->flags & PF_EXITING)) {
+		/*
+		 * The task is on the way out. When PF_EXITPIDONE is
+		 * set, we know that the task has finished the
+		 * cleanup:
+		 */
+		int ret = (p->flags & PF_EXITPIDONE) ? -ESRCH : -EAGAIN;
+
+		spin_unlock_irq(&p->pi_lock);
+		put_task_struct(p);
+		return ret;
+	}
 
 	pi_state = alloc_pi_state();
 
@@ -551,7 +579,6 @@
 	/* Store the key for possible exit cleanups: */
 	pi_state->key = *key;
 
-	spin_lock_irq(&p->pi_lock);
 	WARN_ON(!list_empty(&pi_state->list));
 	list_add(&pi_state->list, &p->pi_state_list);
 	pi_state->owner = p;
@@ -618,17 +645,20 @@
 	 * preserve the owner died bit.)
 	 */
 	if (!(uval & FUTEX_OWNER_DIED)) {
-		newval = FUTEX_WAITERS | new_owner->pid;
-		/* Keep the FUTEX_WAITER_REQUEUED flag if it was set */
-		newval |= (uval & FUTEX_WAITER_REQUEUED);
+		int ret = 0;
 
-		pagefault_disable();
-		curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
-		pagefault_enable();
+		newval = FUTEX_WAITERS | new_owner->pid;
+
+		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
+
 		if (curval == -EFAULT)
-			return -EFAULT;
+			ret = -EFAULT;
 		if (curval != uval)
-			return -EINVAL;
+			ret = -EINVAL;
+		if (ret) {
+			spin_unlock(&pi_state->pi_mutex.wait_lock);
+			return ret;
+		}
 	}
 
 	spin_lock_irq(&pi_state->owner->pi_lock);
@@ -656,9 +686,7 @@
 	 * There is no waiter, so we unlock the futex. The owner died
 	 * bit has not to be preserved here. We are the owner:
 	 */
-	pagefault_disable();
-	oldval = futex_atomic_cmpxchg_inatomic(uaddr, uval, 0);
-	pagefault_enable();
+	oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
 
 	if (oldval == -EFAULT)
 		return oldval;
@@ -697,8 +725,7 @@
 	union futex_key key;
 	int ret;
 
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &key);
 	if (unlikely(ret != 0))
@@ -722,261 +749,7 @@
 
 	spin_unlock(&hb->lock);
 out:
-	if (fshared)
-		up_read(fshared);
-	return ret;
-}
-
-/*
- * Called from futex_requeue_pi.
- * Set FUTEX_WAITERS and FUTEX_WAITER_REQUEUED flags on the
- * PI-futex value; search its associated pi_state if an owner exist
- * or create a new one without owner.
- */
-static inline int
-lookup_pi_state_for_requeue(u32 __user *uaddr, struct futex_hash_bucket *hb,
-			    union futex_key *key,
-			    struct futex_pi_state **pi_state)
-{
-	u32 curval, uval, newval;
-
-retry:
-	/*
-	 * We can't handle a fault cleanly because we can't
-	 * release the locks here. Simply return the fault.
-	 */
-	if (get_futex_value_locked(&curval, uaddr))
-		return -EFAULT;
-
-	/* set the flags FUTEX_WAITERS and FUTEX_WAITER_REQUEUED */
-	if ((curval & (FUTEX_WAITERS | FUTEX_WAITER_REQUEUED))
-	    != (FUTEX_WAITERS | FUTEX_WAITER_REQUEUED)) {
-		/*
-		 * No waiters yet, we prepare the futex to have some waiters.
-		 */
-
-		uval = curval;
-		newval = uval | FUTEX_WAITERS | FUTEX_WAITER_REQUEUED;
-
-		pagefault_disable();
-		curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
-		pagefault_enable();
-
-		if (unlikely(curval == -EFAULT))
-			return -EFAULT;
-		if (unlikely(curval != uval))
-			goto retry;
-	}
-
-	if (!(curval & FUTEX_TID_MASK)
-	    || lookup_pi_state(curval, hb, key, pi_state)) {
-		/* the futex has no owner (yet) or the lookup failed:
-		   allocate one pi_state without owner */
-
-		*pi_state = alloc_pi_state();
-
-		/* Already stores the key: */
-		(*pi_state)->key = *key;
-
-		/* init the mutex without owner */
-		__rt_mutex_init(&(*pi_state)->pi_mutex, NULL);
-	}
-
-	return 0;
-}
-
-/*
- * Keep the first nr_wake waiter from futex1, wake up one,
- * and requeue the next nr_requeue waiters following hashed on
- * one physical page to another physical page (PI-futex uaddr2)
- */
-static int futex_requeue_pi(u32 __user *uaddr1,
-			    struct rw_semaphore *fshared,
-			    u32 __user *uaddr2,
-			    int nr_wake, int nr_requeue, u32 *cmpval)
-{
-	union futex_key key1, key2;
-	struct futex_hash_bucket *hb1, *hb2;
-	struct plist_head *head1;
-	struct futex_q *this, *next;
-	struct futex_pi_state *pi_state2 = NULL;
-	struct rt_mutex_waiter *waiter, *top_waiter = NULL;
-	struct rt_mutex *lock2 = NULL;
-	int ret, drop_count = 0;
-
-	if (refill_pi_state_cache())
-		return -ENOMEM;
-
-retry:
-	/*
-	 * First take all the futex related locks:
-	 */
-	if (fshared)
-		down_read(fshared);
-
-	ret = get_futex_key(uaddr1, fshared, &key1);
-	if (unlikely(ret != 0))
-		goto out;
-	ret = get_futex_key(uaddr2, fshared, &key2);
-	if (unlikely(ret != 0))
-		goto out;
-
-	hb1 = hash_futex(&key1);
-	hb2 = hash_futex(&key2);
-
-	double_lock_hb(hb1, hb2);
-
-	if (likely(cmpval != NULL)) {
-		u32 curval;
-
-		ret = get_futex_value_locked(&curval, uaddr1);
-
-		if (unlikely(ret)) {
-			spin_unlock(&hb1->lock);
-			if (hb1 != hb2)
-				spin_unlock(&hb2->lock);
-
-			/*
-			 * If we would have faulted, release mmap_sem, fault
-			 * it in and start all over again.
-			 */
-			if (fshared)
-				up_read(fshared);
-
-			ret = get_user(curval, uaddr1);
-
-			if (!ret)
-				goto retry;
-
-			return ret;
-		}
-		if (curval != *cmpval) {
-			ret = -EAGAIN;
-			goto out_unlock;
-		}
-	}
-
-	head1 = &hb1->chain;
-	plist_for_each_entry_safe(this, next, head1, list) {
-		if (!match_futex (&this->key, &key1))
-			continue;
-		if (++ret <= nr_wake) {
-			wake_futex(this);
-		} else {
-			/*
-			 * FIRST: get and set the pi_state
-			 */
-			if (!pi_state2) {
-				int s;
-				/* do this only the first time we requeue someone */
-				s = lookup_pi_state_for_requeue(uaddr2, hb2,
-								&key2, &pi_state2);
-				if (s) {
-					ret = s;
-					goto out_unlock;
-				}
-
-				lock2 = &pi_state2->pi_mutex;
-				spin_lock(&lock2->wait_lock);
-
-				/* Save the top waiter of the wait_list */
-				if (rt_mutex_has_waiters(lock2))
-					top_waiter = rt_mutex_top_waiter(lock2);
-			} else
-				atomic_inc(&pi_state2->refcount);
-
-
-			this->pi_state = pi_state2;
-
-			/*
-			 * SECOND: requeue futex_q to the correct hashbucket
-			 */
-
-			/*
-			 * If key1 and key2 hash to the same bucket, no need to
-			 * requeue.
-			 */
-			if (likely(head1 != &hb2->chain)) {
-				plist_del(&this->list, &hb1->chain);
-				plist_add(&this->list, &hb2->chain);
-				this->lock_ptr = &hb2->lock;
-#ifdef CONFIG_DEBUG_PI_LIST
-				this->list.plist.lock = &hb2->lock;
-#endif
-			}
-			this->key = key2;
-			get_futex_key_refs(&key2);
-			drop_count++;
-
-
-			/*
-			 * THIRD: queue it to lock2
-			 */
-			spin_lock_irq(&this->task->pi_lock);
-			waiter = &this->waiter;
-			waiter->task = this->task;
-			waiter->lock = lock2;
-			plist_node_init(&waiter->list_entry, this->task->prio);
-			plist_node_init(&waiter->pi_list_entry, this->task->prio);
-			plist_add(&waiter->list_entry, &lock2->wait_list);
-			this->task->pi_blocked_on = waiter;
-			spin_unlock_irq(&this->task->pi_lock);
-
-			if (ret - nr_wake >= nr_requeue)
-				break;
-		}
-	}
-
-	/* If we've requeued some tasks and the top_waiter of the rt_mutex
-	   has changed, we must adjust the priority of the owner, if any */
-	if (drop_count) {
-		struct task_struct *owner = rt_mutex_owner(lock2);
-		if (owner &&
-		    (top_waiter != (waiter = rt_mutex_top_waiter(lock2)))) {
-			int chain_walk = 0;
-
-			spin_lock_irq(&owner->pi_lock);
-			if (top_waiter)
-				plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters);
-			else
-				/*
-				 * There was no waiters before the requeue,
-				 * the flag must be updated
-				 */
-				mark_rt_mutex_waiters(lock2);
-
-			plist_add(&waiter->pi_list_entry, &owner->pi_waiters);
-			__rt_mutex_adjust_prio(owner);
-			if (owner->pi_blocked_on) {
-				chain_walk = 1;
-				get_task_struct(owner);
-			}
-
-			spin_unlock_irq(&owner->pi_lock);
-			spin_unlock(&lock2->wait_lock);
-
-			if (chain_walk)
-				rt_mutex_adjust_prio_chain(owner, 0, lock2, NULL,
-							   current);
-		} else {
-			/* No owner or the top_waiter does not change */
-			mark_rt_mutex_waiters(lock2);
-			spin_unlock(&lock2->wait_lock);
-		}
-	}
-
-out_unlock:
-	spin_unlock(&hb1->lock);
-	if (hb1 != hb2)
-		spin_unlock(&hb2->lock);
-
-	/* drop_futex_key_refs() must be called outside the spinlocks. */
-	while (--drop_count >= 0)
-		drop_futex_key_refs(&key1);
-
-out:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 	return ret;
 }
 
@@ -996,8 +769,7 @@
 	int ret, op_ret, attempt = 0;
 
 retryfull:
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr1, fshared, &key1);
 	if (unlikely(ret != 0))
@@ -1043,7 +815,7 @@
 		 */
 		if (attempt++) {
 			ret = futex_handle_fault((unsigned long)uaddr2,
-						fshared, attempt);
+						 fshared, attempt);
 			if (ret)
 				goto out;
 			goto retry;
@@ -1053,8 +825,7 @@
 		 * If we would have faulted, release mmap_sem,
 		 * fault it in and start all over again.
 		 */
-		if (fshared)
-			up_read(fshared);
+		futex_unlock_mm(fshared);
 
 		ret = get_user(dummy, uaddr2);
 		if (ret)
@@ -1091,8 +862,8 @@
 	if (hb1 != hb2)
 		spin_unlock(&hb2->lock);
 out:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
+
 	return ret;
 }
 
@@ -1111,8 +882,7 @@
 	int ret, drop_count = 0;
 
  retry:
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr1, fshared, &key1);
 	if (unlikely(ret != 0))
@@ -1140,8 +910,7 @@
 			 * If we would have faulted, release mmap_sem, fault
 			 * it in and start all over again.
 			 */
-			if (fshared)
-				up_read(fshared);
+			futex_unlock_mm(fshared);
 
 			ret = get_user(curval, uaddr1);
 
@@ -1174,7 +943,7 @@
 #ifdef CONFIG_DEBUG_PI_LIST
 				this->list.plist.lock = &hb2->lock;
 #endif
- 			}
+			}
 			this->key = key2;
 			get_futex_key_refs(&key2);
 			drop_count++;
@@ -1194,8 +963,7 @@
 		drop_futex_key_refs(&key1);
 
 out:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 	return ret;
 }
 
@@ -1326,12 +1094,10 @@
 /*
  * Fixup the pi_state owner with current.
  *
- * The cur->mm semaphore must be  held, it is released at return of this
- * function.
+ * Must be called with hash bucket lock held and mm->sem held for non
+ * private futexes.
  */
-static int fixup_pi_state_owner(u32 __user *uaddr, struct rw_semaphore *fshared,
-				struct futex_q *q,
-				struct futex_hash_bucket *hb,
+static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
 				struct task_struct *curr)
 {
 	u32 newtid = curr->pid | FUTEX_WAITERS;
@@ -1355,23 +1121,20 @@
 	list_add(&pi_state->list, &curr->pi_state_list);
 	spin_unlock_irq(&curr->pi_lock);
 
-	/* Unqueue and drop the lock */
-	unqueue_me_pi(q);
-	if (fshared)
-		up_read(fshared);
 	/*
 	 * We own it, so we have to replace the pending owner
 	 * TID. This must be atomic as we have preserve the
 	 * owner died bit here.
 	 */
-	ret = get_user(uval, uaddr);
+	ret = get_futex_value_locked(&uval, uaddr);
+
 	while (!ret) {
 		newval = (uval & FUTEX_OWNER_DIED) | newtid;
-		newval |= (uval & FUTEX_WAITER_REQUEUED);
-		curval = futex_atomic_cmpxchg_inatomic(uaddr,
-						       uval, newval);
+
+		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
+
 		if (curval == -EFAULT)
- 			ret = -EFAULT;
+			ret = -EFAULT;
 		if (curval == uval)
 			break;
 		uval = curval;
@@ -1386,6 +1149,7 @@
 #define ARG3_SHARED  1
 
 static long futex_wait_restart(struct restart_block *restart);
+
 static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
 		      u32 val, ktime_t *abs_time)
 {
@@ -1395,13 +1159,12 @@
 	struct futex_q q;
 	u32 uval;
 	int ret;
-	struct hrtimer_sleeper t, *to = NULL;
+	struct hrtimer_sleeper t;
 	int rem = 0;
 
 	q.pi_state = NULL;
  retry:
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &q.key);
 	if (unlikely(ret != 0))
@@ -1438,8 +1201,7 @@
 		 * If we would have faulted, release mmap_sem, fault it in and
 		 * start all over again.
 		 */
-		if (fshared)
-			up_read(fshared);
+		futex_unlock_mm(fshared);
 
 		ret = get_user(uval, uaddr);
 
@@ -1451,14 +1213,6 @@
 	if (uval != val)
 		goto out_unlock_release_sem;
 
-	/*
-	 * This rt_mutex_waiter structure is prepared here and will
-	 * be used only if this task is requeued from a normal futex to
-	 * a PI-futex with futex_requeue_pi.
-	 */
-	debug_rt_mutex_init_waiter(&q.waiter);
-	q.waiter.task = NULL;
-
 	/* Only actually queue if *uaddr contained val.  */
 	__queue_me(&q, hb);
 
@@ -1466,8 +1220,7 @@
 	 * Now the futex is queued and we have checked the data, we
 	 * don't want to hold mmap_sem while we sleep.
 	 */
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	/*
 	 * There might have been scheduling since the queue_me(), as we
@@ -1489,7 +1242,6 @@
 		if (!abs_time)
 			schedule();
 		else {
-			to = &t;
 			hrtimer_init(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 			hrtimer_init_sleeper(&t, current);
 			t.timer.expires = *abs_time;
@@ -1517,69 +1269,6 @@
 	 * we are the only user of it.
 	 */
 
-	if (q.pi_state) {
-		/*
-		 * We were woken but have been requeued on a PI-futex.
-		 * We have to complete the lock acquisition by taking
-		 * the rtmutex.
-		 */
-
-		struct rt_mutex *lock = &q.pi_state->pi_mutex;
-
-		spin_lock(&lock->wait_lock);
-		if (unlikely(q.waiter.task)) {
-			remove_waiter(lock, &q.waiter);
-		}
-		spin_unlock(&lock->wait_lock);
-
-		if (rem)
-			ret = -ETIMEDOUT;
-		else
-			ret = rt_mutex_timed_lock(lock, to, 1);
-
-		if (fshared)
-			down_read(fshared);
-		spin_lock(q.lock_ptr);
-
-		/*
-		 * Got the lock. We might not be the anticipated owner if we
-		 * did a lock-steal - fix up the PI-state in that case.
-		 */
-		if (!ret && q.pi_state->owner != curr) {
-			/*
-			 * We MUST play with the futex we were requeued on,
-			 * NOT the current futex.
-			 * We can retrieve it from the key of the pi_state
-			 */
-			uaddr = q.pi_state->key.uaddr;
-
-			/* mmap_sem and hash_bucket lock are unlocked at
-			   return of this function */
-			ret = fixup_pi_state_owner(uaddr, fshared,
-						   &q, hb, curr);
-		} else {
-			/*
-			 * Catch the rare case, where the lock was released
-			 * when we were on the way back before we locked
-			 * the hash bucket.
-			 */
-			if (ret && q.pi_state->owner == curr) {
-				if (rt_mutex_trylock(&q.pi_state->pi_mutex))
-					ret = 0;
-			}
-			/* Unqueue and drop the lock */
-			unqueue_me_pi(&q);
-			if (fshared)
-				up_read(fshared);
-		}
-
-		debug_rt_mutex_free_waiter(&q.waiter);
-
-		return ret;
-	}
-
-	debug_rt_mutex_free_waiter(&q.waiter);
-
 	/* If we were woken (and unqueued), we succeeded, whatever. */
 	if (!unqueue_me(&q))
 		return 0;
@@ -1609,8 +1298,7 @@
 	queue_unlock(&q, hb);
 
  out_release_sem:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 	return ret;
 }
 
@@ -1629,51 +1317,6 @@
 }
 
 
-static void set_pi_futex_owner(struct futex_hash_bucket *hb,
-			       union futex_key *key, struct task_struct *p)
-{
-	struct plist_head *head;
-	struct futex_q *this, *next;
-	struct futex_pi_state *pi_state = NULL;
-	struct rt_mutex *lock;
-
-	/* Search a waiter that should already exists */
-
-	head = &hb->chain;
-
-	plist_for_each_entry_safe(this, next, head, list) {
-		if (match_futex (&this->key, key)) {
-			pi_state = this->pi_state;
-			break;
-		}
-	}
-
-	BUG_ON(!pi_state);
-
-	/* set p as pi_state's owner */
-	lock = &pi_state->pi_mutex;
-
-	spin_lock(&lock->wait_lock);
-	spin_lock_irq(&p->pi_lock);
-
-	list_add(&pi_state->list, &p->pi_state_list);
-	pi_state->owner = p;
-
-
-	/* set p as pi_mutex's owner */
-	debug_rt_mutex_proxy_lock(lock, p);
-	WARN_ON(rt_mutex_owner(lock));
-	rt_mutex_set_owner(lock, p, 0);
-	rt_mutex_deadlock_account_lock(lock, p);
-
-	plist_add(&rt_mutex_top_waiter(lock)->pi_list_entry,
-		  &p->pi_waiters);
-	__rt_mutex_adjust_prio(p);
-
-	spin_unlock_irq(&p->pi_lock);
-	spin_unlock(&lock->wait_lock);
-}
-
 /*
  * Userspace tried a 0 -> TID atomic transition of the futex value
  * and failed. The kernel side here does the whole locking operation:
@@ -1688,7 +1331,7 @@
 	struct futex_hash_bucket *hb;
 	u32 uval, newval, curval;
 	struct futex_q q;
-	int ret, lock_held, attempt = 0;
+	int ret, lock_taken, ownerdied = 0, attempt = 0;
 
 	if (refill_pi_state_cache())
 		return -ENOMEM;
@@ -1702,17 +1345,17 @@
 
 	q.pi_state = NULL;
  retry:
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &q.key);
 	if (unlikely(ret != 0))
 		goto out_release_sem;
 
+ retry_unlocked:
 	hb = queue_lock(&q, -1, NULL);
 
  retry_locked:
-	lock_held = 0;
+	ret = lock_taken = 0;
 
 	/*
 	 * To avoid races, we attempt to take the lock here again
@@ -1721,64 +1364,61 @@
 	 */
 	newval = current->pid;
 
-	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, 0, newval);
-	pagefault_enable();
+	curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
 
 	if (unlikely(curval == -EFAULT))
 		goto uaddr_faulted;
 
-	/* We own the lock already */
+	/*
+	 * Detect deadlocks. In case of REQUEUE_PI this is a valid
+	 * situation and we return success to user space.
+	 */
 	if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) {
-		if (!detect && 0)
-			force_sig(SIGKILL, current);
-		/*
-		 * Normally, this check is done in user space.
-		 * In case of requeue, the owner may attempt to lock this futex,
-		 * even if the ownership has already been given by the previous
-		 * waker.
-		 * In the usual case, this is a case of deadlock, but not in case
-		 * of REQUEUE_PI.
-		 */
-		if (!(curval & FUTEX_WAITER_REQUEUED))
-			ret = -EDEADLK;
+		ret = -EDEADLK;
 		goto out_unlock_release_sem;
 	}
 
 	/*
-	 * Surprise - we got the lock. Just return
-	 * to userspace:
+	 * Surprise - we got the lock. Just return to userspace:
 	 */
 	if (unlikely(!curval))
 		goto out_unlock_release_sem;
 
 	uval = curval;
-	/*
-	 * In case of a requeue, check if there already is an owner
-	 * If not, just take the futex.
-	 */
-	if ((curval & FUTEX_WAITER_REQUEUED) && !(curval & FUTEX_TID_MASK)) {
-		/* set current as futex owner */
-		newval = curval | current->pid;
-		lock_held = 1;
-	} else
-		/* Set the WAITERS flag, so the owner will know it has someone
-		   to wake at next unlock */
-		newval = curval | FUTEX_WAITERS;
 
-	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
-	pagefault_enable();
+	/*
+	 * Set the WAITERS flag, so the owner will know it has someone
+	 * to wake at next unlock
+	 */
+	newval = curval | FUTEX_WAITERS;
+
+	/*
+	 * There are two cases, where a futex might have no owner (the
+	 * owner TID is 0): OWNER_DIED. We take over the futex in this
+	 * case. We also do an unconditional take over, when the owner
+	 * of the futex died.
+	 *
+	 * This is safe as we are protected by the hash bucket lock !
+	 */
+	if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
+		/* Keep the OWNER_DIED bit */
+		newval = (curval & ~FUTEX_TID_MASK) | current->pid;
+		ownerdied = 0;
+		lock_taken = 1;
+	}
+
+	curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
 
 	if (unlikely(curval == -EFAULT))
 		goto uaddr_faulted;
 	if (unlikely(curval != uval))
 		goto retry_locked;
 
-	if (lock_held) {
-		set_pi_futex_owner(hb, &q.key, curr);
+	/*
+	 * We took the lock due to owner died take over.
+	 */
+	if (unlikely(lock_taken))
 		goto out_unlock_release_sem;
-	}
 
 	/*
 	 * We dont have the lock. Look up the PI state (or create it if
@@ -1787,34 +1427,39 @@
 	ret = lookup_pi_state(uval, hb, &q.key, &q.pi_state);
 
 	if (unlikely(ret)) {
-		/*
-		 * There were no waiters and the owner task lookup
-		 * failed. When the OWNER_DIED bit is set, then we
-		 * know that this is a robust futex and we actually
-		 * take the lock. This is safe as we are protected by
-		 * the hash bucket lock. We also set the waiters bit
-		 * unconditionally here, to simplify glibc handling of
-		 * multiple tasks racing to acquire the lock and
-		 * cleanup the problems which were left by the dead
-		 * owner.
-		 */
-		if (curval & FUTEX_OWNER_DIED) {
-			uval = newval;
-			newval = current->pid |
-				FUTEX_OWNER_DIED | FUTEX_WAITERS;
+		switch (ret) {
 
-			pagefault_disable();
-			curval = futex_atomic_cmpxchg_inatomic(uaddr,
-							       uval, newval);
-			pagefault_enable();
+		case -EAGAIN:
+			/*
+			 * Task is exiting and we just wait for the
+			 * exit to complete.
+			 */
+			queue_unlock(&q, hb);
+			futex_unlock_mm(fshared);
+			cond_resched();
+			goto retry;
 
-			if (unlikely(curval == -EFAULT))
+		case -ESRCH:
+			/*
+			 * No owner found for this futex. Check if the
+			 * OWNER_DIED bit is set to figure out whether
+			 * this is a robust futex or not.
+			 */
+			if (get_futex_value_locked(&curval, uaddr))
 				goto uaddr_faulted;
-			if (unlikely(curval != uval))
+
+			/*
+			 * We simply start over in case of a robust
+			 * futex. The code above will take the futex
+			 * and return happy.
+			 */
+			if (curval & FUTEX_OWNER_DIED) {
+				ownerdied = 1;
 				goto retry_locked;
-			ret = 0;
+			}
+		default:
+			goto out_unlock_release_sem;
 		}
-		goto out_unlock_release_sem;
 	}
 
 	/*
@@ -1826,8 +1471,7 @@
 	 * Now the futex is queued and we have checked the data, we
 	 * don't want to hold mmap_sem while we sleep.
 	 */
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	WARN_ON(!q.pi_state);
 	/*
@@ -1841,35 +1485,44 @@
 		ret = ret ? 0 : -EWOULDBLOCK;
 	}
 
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 	spin_lock(q.lock_ptr);
 
-	/*
-	 * Got the lock. We might not be the anticipated owner if we
-	 * did a lock-steal - fix up the PI-state in that case.
-	 */
-	if (!ret && q.pi_state->owner != curr)
-		/* mmap_sem is unlocked at return of this function */
-		ret = fixup_pi_state_owner(uaddr, fshared, &q, hb, curr);
-	else {
+	if (!ret) {
+		/*
+		 * Got the lock. We might not be the anticipated owner
+		 * if we did a lock-steal - fix up the PI-state in
+		 * that case:
+		 */
+		if (q.pi_state->owner != curr)
+			ret = fixup_pi_state_owner(uaddr, &q, curr);
+	} else {
 		/*
 		 * Catch the rare case, where the lock was released
-		 * when we were on the way back before we locked
-		 * the hash bucket.
+		 * when we were on the way back before we locked the
+		 * hash bucket.
 		 */
-		if (ret && q.pi_state->owner == curr) {
-			if (rt_mutex_trylock(&q.pi_state->pi_mutex))
-				ret = 0;
+		if (q.pi_state->owner == curr &&
+		    rt_mutex_trylock(&q.pi_state->pi_mutex)) {
+			ret = 0;
+		} else {
+			/*
+			 * Paranoia check. If we did not take the lock
+			 * in the trylock above, then we should not be
+			 * the owner of the rtmutex, neither the real
+			 * nor the pending one:
+			 */
+			if (rt_mutex_owner(&q.pi_state->pi_mutex) == curr)
+				printk(KERN_ERR "futex_lock_pi: ret = %d "
+				       "pi-mutex: %p pi-state %p\n", ret,
+				       q.pi_state->pi_mutex.owner,
+				       q.pi_state->owner);
 		}
-		/* Unqueue and drop the lock */
-		unqueue_me_pi(&q);
-		if (fshared)
-			up_read(fshared);
 	}
 
-	if (!detect && ret == -EDEADLK && 0)
-		force_sig(SIGKILL, current);
+	/* Unqueue and drop the lock */
+	unqueue_me_pi(&q);
+	futex_unlock_mm(fshared);
 
 	return ret != -EINTR ? ret : -ERESTARTNOINTR;
 
@@ -1877,8 +1530,7 @@
 	queue_unlock(&q, hb);
 
  out_release_sem:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 	return ret;
 
  uaddr_faulted:
@@ -1887,18 +1539,20 @@
 	 * non-atomically.  Therefore, if get_user below is not
 	 * enough, we need to handle the fault ourselves, while
 	 * still holding the mmap_sem.
+	 *
+	 * ... and hb->lock. :-) --ANK
 	 */
+	queue_unlock(&q, hb);
+
 	if (attempt++) {
 		ret = futex_handle_fault((unsigned long)uaddr, fshared,
 					 attempt);
 		if (ret)
-			goto out_unlock_release_sem;
-		goto retry_locked;
+			goto out_release_sem;
+		goto retry_unlocked;
 	}
 
-	queue_unlock(&q, hb);
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	ret = get_user(uval, uaddr);
 	if (!ret && (uval != -EFAULT))
@@ -1932,27 +1586,24 @@
 	/*
 	 * First take all the futex related locks:
 	 */
-	if (fshared)
-		down_read(fshared);
+	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &key);
 	if (unlikely(ret != 0))
 		goto out;
 
 	hb = hash_futex(&key);
+retry_unlocked:
 	spin_lock(&hb->lock);
 
-retry_locked:
 	/*
 	 * To avoid races, try to do the TID -> 0 atomic transition
 	 * again. If it succeeds then we can return without waking
 	 * anyone else up:
 	 */
-	if (!(uval & FUTEX_OWNER_DIED)) {
-		pagefault_disable();
-		uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0);
-		pagefault_enable();
-	}
+	if (!(uval & FUTEX_OWNER_DIED))
+		uval = cmpxchg_futex_value_locked(uaddr, current->pid, 0);
+
 
 	if (unlikely(uval == -EFAULT))
 		goto pi_faulted;
@@ -1994,8 +1645,7 @@
 out_unlock:
 	spin_unlock(&hb->lock);
 out:
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	return ret;
 
@@ -2005,18 +1655,20 @@
 	 * non-atomically.  Therefore, if get_user below is not
 	 * enough, we need to handle the fault ourselves, while
 	 * still holding the mmap_sem.
+	 *
+	 * ... and hb->lock. --ANK
 	 */
+	spin_unlock(&hb->lock);
+
 	if (attempt++) {
 		ret = futex_handle_fault((unsigned long)uaddr, fshared,
 					 attempt);
 		if (ret)
-			goto out_unlock;
-		goto retry_locked;
+			goto out;
+		goto retry_unlocked;
 	}
 
-	spin_unlock(&hb->lock);
-	if (fshared)
-		up_read(fshared);
+	futex_unlock_mm(fshared);
 
 	ret = get_user(uval, uaddr);
 	if (!ret && (uval != -EFAULT))
@@ -2073,8 +1725,8 @@
 
 	if (printk_timed_ratelimit(&printk_interval, 60 * 60 * 1000)) {
 		printk(KERN_WARNING "Process `%s' used FUTEX_FD, which "
-		    	"will be removed from the kernel in June 2007\n",
-			current->comm);
+		       "will be removed from the kernel in June 2007\n",
+		       current->comm);
 	}
 
 	ret = -EINVAL;
@@ -2240,8 +1892,6 @@
 		 * userspace.
 		 */
 		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
-		/* Also keep the FUTEX_WAITER_REQUEUED flag if set */
-		mval |= (uval & FUTEX_WAITER_REQUEUED);
 		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
 
 		if (nval == -EFAULT)
@@ -2254,10 +1904,8 @@
 		 * Wake robust non-PI futexes here. The wakeup of
 		 * PI futexes happens in exit_pi_state():
 		 */
-		if (!pi) {
-			if (uval & FUTEX_WAITERS)
+		if (!pi && (uval & FUTEX_WAITERS))
 				futex_wake(uaddr, &curr->mm->mmap_sem, 1);
-		}
 	}
 	return 0;
 }
@@ -2378,9 +2026,6 @@
 	case FUTEX_TRYLOCK_PI:
 		ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
 		break;
-	case FUTEX_CMP_REQUEUE_PI:
-		ret = futex_requeue_pi(uaddr, fshared, uaddr2, val, val2, &val3);
-		break;
 	default:
 		ret = -ENOSYS;
 	}
@@ -2411,8 +2056,7 @@
 	/*
 	 * requeue parameter in 'utime' if cmd == FUTEX_REQUEUE.
 	 */
-	if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE
-	    || cmd == FUTEX_CMP_REQUEUE_PI)
+	if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE)
 		val2 = (u32) (unsigned long) utime;
 
 	return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index 338a9b4..f792136 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -144,20 +144,20 @@
 	struct timespec ts;
 	ktime_t t, *tp = NULL;
 	int val2 = 0;
+	int cmd = op & FUTEX_CMD_MASK;
 
-	if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
+	if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI)) {
 		if (get_compat_timespec(&ts, utime))
 			return -EFAULT;
 		if (!timespec_valid(&ts))
 			return -EINVAL;
 
 		t = timespec_to_ktime(ts);
-		if (op == FUTEX_WAIT)
+		if (cmd == FUTEX_WAIT)
 			t = ktime_add(ktime_get(), t);
 		tp = &t;
 	}
-	if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE
-	    || op == FUTEX_CMP_REQUEUE_PI)
+	if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE)
 		val2 = (int) (unsigned long) utime;
 
 	return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 23c03f4..72d0342 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1406,7 +1406,7 @@
 static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
 					unsigned long action, void *hcpu)
 {
-	long cpu = (long)hcpu;
+	unsigned int cpu = (long)hcpu;
 
 	switch (action) {
 
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index b0d81aa..32b1619 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -135,24 +135,62 @@
 	}
 }
 
+static inline int try_misrouted_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
+{
+	struct irqaction *action;
+
+	if (!irqfixup)
+		return 0;
+
+	/* We didn't actually handle the IRQ - see if it was misrouted? */
+	if (action_ret == IRQ_NONE)
+		return 1;
+
+	/*
+	 * But for 'irqfixup == 2' we also do it for handled interrupts if
+	 * they are marked as IRQF_IRQPOLL (or for irq zero, which is the
+	 * traditional PC timer interrupt.. Legacy)
+	 */
+	if (irqfixup < 2)
+		return 0;
+
+	if (!irq)
+		return 1;
+
+	/*
+	 * Since we don't get the descriptor lock, "action" can
+	 * change under us.  We don't really care, but we don't
+	 * want to follow a NULL pointer. So tell the compiler to
+	 * just load it once by using a barrier.
+	 */
+	action = desc->action;
+	barrier();
+	return action && (action->flags & IRQF_IRQPOLL);
+}
+
 void note_interrupt(unsigned int irq, struct irq_desc *desc,
 		    irqreturn_t action_ret)
 {
 	if (unlikely(action_ret != IRQ_HANDLED)) {
-		desc->irqs_unhandled++;
+		/*
+		 * If we are seeing only the odd spurious IRQ caused by
+		 * bus asynchronicity then don't eventually trigger an error,
+		 * otherwise the couter becomes a doomsday timer for otherwise
+		 * working systems
+		 */
+		if (jiffies - desc->last_unhandled > HZ/10)
+			desc->irqs_unhandled = 1;
+		else
+			desc->irqs_unhandled++;
+		desc->last_unhandled = jiffies;
 		if (unlikely(action_ret != IRQ_NONE))
 			report_bad_irq(irq, desc, action_ret);
 	}
 
-	if (unlikely(irqfixup)) {
-		/* Don't punish working computers */
-		if ((irqfixup == 2 && ((irq == 0) ||
-				(desc->action->flags & IRQF_IRQPOLL))) ||
-				action_ret == IRQ_NONE) {
-			int ok = misrouted_irq(irq);
-			if (action_ret == IRQ_NONE)
-				desc->irqs_unhandled -= ok;
-		}
+	if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
+		int ok = misrouted_irq(irq);
+		if (action_ret == IRQ_NONE)
+			desc->irqs_unhandled -= ok;
 	}
 
 	desc->irq_count++;
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index f1bda23..474219a 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -152,7 +152,7 @@
 /* Lookup the address for this symbol. Returns 0 if not found. */
 unsigned long kallsyms_lookup_name(const char *name)
 {
-	char namebuf[KSYM_NAME_LEN+1];
+	char namebuf[KSYM_NAME_LEN];
 	unsigned long i;
 	unsigned int off;
 
@@ -248,7 +248,7 @@
 {
 	const char *msym;
 
-	namebuf[KSYM_NAME_LEN] = 0;
+	namebuf[KSYM_NAME_LEN - 1] = 0;
 	namebuf[0] = 0;
 
 	if (is_ksym_addr(addr)) {
@@ -257,14 +257,15 @@
 		pos = get_symbol_pos(addr, symbolsize, offset);
 		/* Grab name */
 		kallsyms_expand_symbol(get_symbol_offset(pos), namebuf);
-		*modname = NULL;
+		if (modname)
+			*modname = NULL;
 		return namebuf;
 	}
 
 	/* see if it's in a module */
 	msym = module_address_lookup(addr, symbolsize, offset, modname);
 	if (msym)
-		return strncpy(namebuf, msym, KSYM_NAME_LEN);
+		return strncpy(namebuf, msym, KSYM_NAME_LEN - 1);
 
 	return NULL;
 }
@@ -272,7 +273,7 @@
 int lookup_symbol_name(unsigned long addr, char *symname)
 {
 	symname[0] = '\0';
-	symname[KSYM_NAME_LEN] = '\0';
+	symname[KSYM_NAME_LEN - 1] = '\0';
 
 	if (is_ksym_addr(addr)) {
 		unsigned long pos;
@@ -290,7 +291,7 @@
 			unsigned long *offset, char *modname, char *name)
 {
 	name[0] = '\0';
-	name[KSYM_NAME_LEN] = '\0';
+	name[KSYM_NAME_LEN - 1] = '\0';
 
 	if (is_ksym_addr(addr)) {
 		unsigned long pos;
@@ -311,18 +312,17 @@
 	char *modname;
 	const char *name;
 	unsigned long offset, size;
-	char namebuf[KSYM_NAME_LEN+1];
+	char namebuf[KSYM_NAME_LEN];
 
 	name = kallsyms_lookup(address, &size, &offset, &modname, namebuf);
 	if (!name)
 		return sprintf(buffer, "0x%lx", address);
-	else {
-		if (modname)
-			return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
+
+	if (modname)
+		return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
 				size, modname);
-		else
-			return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
-	}
+	else
+		return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
 }
 
 /* Look up a kernel symbol and print it to the kernel messages. */
@@ -342,8 +342,8 @@
 	unsigned long value;
 	unsigned int nameoff; /* If iterating in core kernel symbols */
 	char type;
-	char name[KSYM_NAME_LEN+1];
-	char module_name[MODULE_NAME_LEN + 1];
+	char name[KSYM_NAME_LEN];
+	char module_name[MODULE_NAME_LEN];
 	int exported;
 };
 
diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index cee4191..bc41ad0 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/kfifo.h>
+#include <linux/log2.h>
 
 /**
  * kfifo_init - allocates a new FIFO using a preallocated buffer
@@ -41,7 +42,7 @@
 	struct kfifo *fifo;
 
 	/* size must be a power of 2 */
-	BUG_ON(size & (size - 1));
+	BUG_ON(!is_power_of_2(size));
 
 	fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
 	if (!fifo)
diff --git a/kernel/kthread.c b/kernel/kthread.c
index df8a8e8..a404f7e 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -70,7 +70,7 @@
 	data = create->data;
 
 	/* OK, tell user we're spawned, wait for stop or wakeup */
-	__set_current_state(TASK_INTERRUPTIBLE);
+	__set_current_state(TASK_UNINTERRUPTIBLE);
 	complete(&create->started);
 	schedule();
 
@@ -162,7 +162,10 @@
  */
 void kthread_bind(struct task_struct *k, unsigned int cpu)
 {
-	BUG_ON(k->state != TASK_INTERRUPTIBLE);
+	if (k->state != TASK_UNINTERRUPTIBLE) {
+		WARN_ON(1);
+		return;
+	}
 	/* Must have done schedule() in kthread() before we set_task_cpu */
 	wait_task_inactive(k);
 	set_task_cpu(k, cpu);
@@ -212,7 +215,7 @@
 EXPORT_SYMBOL(kthread_stop);
 
 
-static __init void kthreadd_setup(void)
+static noinline __init_refok void kthreadd_setup(void)
 {
 	struct task_struct *tsk = current;
 
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 1a5ff22..edba2ff 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -379,7 +379,7 @@
 
 static void print_lock_name(struct lock_class *class)
 {
-	char str[KSYM_NAME_LEN + 1], c1, c2, c3, c4;
+	char str[KSYM_NAME_LEN], c1, c2, c3, c4;
 	const char *name;
 
 	get_usage_chars(class, &c1, &c2, &c3, &c4);
@@ -401,7 +401,7 @@
 static void print_lockdep_cache(struct lockdep_map *lock)
 {
 	const char *name;
-	char str[KSYM_NAME_LEN + 1];
+	char str[KSYM_NAME_LEN];
 
 	name = lock->name;
 	if (!name)
diff --git a/kernel/module.c b/kernel/module.c
index 9bd93de..33c04ad 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -61,10 +61,8 @@
 /* If this is set, the section belongs in the init part of the module */
 #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
 
-/* Protects module list */
-static DEFINE_SPINLOCK(modlist_lock);
-
-/* List of modules, protected by module_mutex AND modlist_lock */
+/* List of modules, protected by module_mutex or preempt_disable
+ * (add/delete uses stop_machine). */
 static DEFINE_MUTEX(module_mutex);
 static LIST_HEAD(modules);
 
@@ -488,8 +486,7 @@
         mod->field = NULL;                                            \
 }                                                                     \
 static struct module_attribute modinfo_##field = {                    \
-	.attr = { .name = __stringify(field), .mode = 0444,           \
-		  .owner = THIS_MODULE },                             \
+	.attr = { .name = __stringify(field), .mode = 0444 },         \
 	.show = show_modinfo_##field,                                 \
 	.setup = setup_modinfo_##field,                               \
 	.test = modinfo_##field##_exists,                             \
@@ -761,14 +758,13 @@
 void __symbol_put(const char *symbol)
 {
 	struct module *owner;
-	unsigned long flags;
 	const unsigned long *crc;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 	if (!__find_symbol(symbol, &owner, &crc, 1))
 		BUG();
 	module_put(owner);
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 }
 EXPORT_SYMBOL(__symbol_put);
 
@@ -793,7 +789,7 @@
 }
 
 static struct module_attribute refcnt = {
-	.attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE },
+	.attr = { .name = "refcnt", .mode = 0444 },
 	.show = show_refcnt,
 };
 
@@ -851,7 +847,7 @@
 }
 
 static struct module_attribute initstate = {
-	.attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
+	.attr = { .name = "initstate", .mode = 0444 },
 	.show = show_initstate,
 };
 
@@ -1032,7 +1028,6 @@
 		sattr->mattr.show = module_sect_show;
 		sattr->mattr.store = NULL;
 		sattr->mattr.attr.name = sattr->name;
-		sattr->mattr.attr.owner = mod;
 		sattr->mattr.attr.mode = S_IRUGO;
 		*(gattr++) = &(sattr++)->mattr.attr;
 	}
@@ -1090,7 +1085,6 @@
 		if (!attr->test ||
 		    (attr->test && attr->test(mod))) {
 			memcpy(temp_attr, attr, sizeof(*temp_attr));
-			temp_attr->attr.owner = mod;
 			error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
 			++temp_attr;
 		}
@@ -1231,14 +1225,14 @@
 void *__symbol_get(const char *symbol)
 {
 	struct module *owner;
-	unsigned long value, flags;
+	unsigned long value;
 	const unsigned long *crc;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 	value = __find_symbol(symbol, &owner, &crc, 1);
 	if (value && !strong_try_module_get(owner))
 		value = 0;
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 
 	return (void *)value;
 }
@@ -2139,7 +2133,7 @@
 			sym = get_ksymbol(mod, addr, NULL, NULL);
 			if (!sym)
 				goto out;
-			strlcpy(symname, sym, KSYM_NAME_LEN + 1);
+			strlcpy(symname, sym, KSYM_NAME_LEN);
 			mutex_unlock(&module_mutex);
 			return 0;
 		}
@@ -2164,9 +2158,9 @@
 			if (!sym)
 				goto out;
 			if (modname)
-				strlcpy(modname, mod->name, MODULE_NAME_LEN + 1);
+				strlcpy(modname, mod->name, MODULE_NAME_LEN);
 			if (name)
-				strlcpy(name, sym, KSYM_NAME_LEN + 1);
+				strlcpy(name, sym, KSYM_NAME_LEN);
 			mutex_unlock(&module_mutex);
 			return 0;
 		}
@@ -2187,8 +2181,8 @@
 			*value = mod->symtab[symnum].st_value;
 			*type = mod->symtab[symnum].st_info;
 			strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
-				KSYM_NAME_LEN + 1);
-			strlcpy(module_name, mod->name, MODULE_NAME_LEN + 1);
+				KSYM_NAME_LEN);
+			strlcpy(module_name, mod->name, MODULE_NAME_LEN);
 			*exported = is_exported(name, mod);
 			mutex_unlock(&module_mutex);
 			return 0;
@@ -2235,26 +2229,13 @@
 /* Called by the /proc file system to return a list of modules. */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
-	struct list_head *i;
-	loff_t n = 0;
-
 	mutex_lock(&module_mutex);
-	list_for_each(i, &modules) {
-		if (n++ == *pos)
-			break;
-	}
-	if (i == &modules)
-		return NULL;
-	return i;
+	return seq_list_start(&modules, *pos);
 }
 
 static void *m_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	struct list_head *i = p;
-	(*pos)++;
-	if (i->next == &modules)
-		return NULL;
-	return i->next;
+	return seq_list_next(p, &modules, pos);
 }
 
 static void m_stop(struct seq_file *m, void *p)
@@ -2324,11 +2305,10 @@
 /* Given an address, look for it in the module exception tables. */
 const struct exception_table_entry *search_module_extables(unsigned long addr)
 {
-	unsigned long flags;
 	const struct exception_table_entry *e = NULL;
 	struct module *mod;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 	list_for_each_entry(mod, &modules, list) {
 		if (mod->num_exentries == 0)
 			continue;
@@ -2339,7 +2319,7 @@
 		if (e)
 			break;
 	}
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 
 	/* Now, if we found one, we are running inside it now, hence
            we cannot unload the module, hence no refcnt needed. */
@@ -2351,25 +2331,24 @@
  */
 int is_module_address(unsigned long addr)
 {
-	unsigned long flags;
 	struct module *mod;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 
 	list_for_each_entry(mod, &modules, list) {
 		if (within(addr, mod->module_core, mod->core_size)) {
-			spin_unlock_irqrestore(&modlist_lock, flags);
+			preempt_enable();
 			return 1;
 		}
 	}
 
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 
 	return 0;
 }
 
 
-/* Is this a valid kernel address?  We don't grab the lock: we are oopsing. */
+/* Is this a valid kernel address? */
 struct module *__module_text_address(unsigned long addr)
 {
 	struct module *mod;
@@ -2384,11 +2363,10 @@
 struct module *module_text_address(unsigned long addr)
 {
 	struct module *mod;
-	unsigned long flags;
 
-	spin_lock_irqsave(&modlist_lock, flags);
+	preempt_disable();
 	mod = __module_text_address(addr);
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	preempt_enable();
 
 	return mod;
 }
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 1bc4b55..10f0bbb 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -21,6 +21,8 @@
 #include <linux/utsname.h>
 #include <linux/pid_namespace.h>
 
+static struct kmem_cache *nsproxy_cachep;
+
 struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
 
 static inline void get_nsproxy(struct nsproxy *ns)
@@ -43,9 +45,11 @@
 {
 	struct nsproxy *ns;
 
-	ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
-	if (ns)
+	ns = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
+	if (ns) {
+		memcpy(ns, orig, sizeof(struct nsproxy));
 		atomic_set(&ns->count, 1);
+	}
 	return ns;
 }
 
@@ -54,33 +58,51 @@
  * Return the newly created nsproxy.  Do not attach this to the task,
  * leave it to the caller to do proper locking and attach it to task.
  */
-static struct nsproxy *create_new_namespaces(int flags, struct task_struct *tsk,
-			struct fs_struct *new_fs)
+static struct nsproxy *create_new_namespaces(unsigned long flags,
+			struct task_struct *tsk, struct fs_struct *new_fs)
 {
 	struct nsproxy *new_nsp;
+	int err;
 
 	new_nsp = clone_nsproxy(tsk->nsproxy);
 	if (!new_nsp)
 		return ERR_PTR(-ENOMEM);
 
 	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
-	if (IS_ERR(new_nsp->mnt_ns))
+	if (IS_ERR(new_nsp->mnt_ns)) {
+		err = PTR_ERR(new_nsp->mnt_ns);
 		goto out_ns;
+	}
 
 	new_nsp->uts_ns = copy_utsname(flags, tsk->nsproxy->uts_ns);
-	if (IS_ERR(new_nsp->uts_ns))
+	if (IS_ERR(new_nsp->uts_ns)) {
+		err = PTR_ERR(new_nsp->uts_ns);
 		goto out_uts;
+	}
 
 	new_nsp->ipc_ns = copy_ipcs(flags, tsk->nsproxy->ipc_ns);
-	if (IS_ERR(new_nsp->ipc_ns))
+	if (IS_ERR(new_nsp->ipc_ns)) {
+		err = PTR_ERR(new_nsp->ipc_ns);
 		goto out_ipc;
+	}
 
 	new_nsp->pid_ns = copy_pid_ns(flags, tsk->nsproxy->pid_ns);
-	if (IS_ERR(new_nsp->pid_ns))
+	if (IS_ERR(new_nsp->pid_ns)) {
+		err = PTR_ERR(new_nsp->pid_ns);
 		goto out_pid;
+	}
+
+	new_nsp->user_ns = copy_user_ns(flags, tsk->nsproxy->user_ns);
+	if (IS_ERR(new_nsp->user_ns)) {
+		err = PTR_ERR(new_nsp->user_ns);
+		goto out_user;
+	}
 
 	return new_nsp;
 
+out_user:
+	if (new_nsp->pid_ns)
+		put_pid_ns(new_nsp->pid_ns);
 out_pid:
 	if (new_nsp->ipc_ns)
 		put_ipc_ns(new_nsp->ipc_ns);
@@ -91,15 +113,15 @@
 	if (new_nsp->mnt_ns)
 		put_mnt_ns(new_nsp->mnt_ns);
 out_ns:
-	kfree(new_nsp);
-	return ERR_PTR(-ENOMEM);
+	kmem_cache_free(nsproxy_cachep, new_nsp);
+	return ERR_PTR(err);
 }
 
 /*
  * called from clone.  This now handles copy for nsproxy and all
  * namespaces therein.
  */
-int copy_namespaces(int flags, struct task_struct *tsk)
+int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 {
 	struct nsproxy *old_ns = tsk->nsproxy;
 	struct nsproxy *new_ns;
@@ -110,7 +132,7 @@
 
 	get_nsproxy(old_ns);
 
-	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER)))
 		return 0;
 
 	if (!capable(CAP_SYS_ADMIN)) {
@@ -140,43 +162,39 @@
 		put_ipc_ns(ns->ipc_ns);
 	if (ns->pid_ns)
 		put_pid_ns(ns->pid_ns);
-	kfree(ns);
+	if (ns->user_ns)
+		put_user_ns(ns->user_ns);
+	kmem_cache_free(nsproxy_cachep, ns);
 }
 
 /*
  * Called from unshare. Unshare all the namespaces part of nsproxy.
- * On sucess, returns the new nsproxy and a reference to old nsproxy
- * to make sure it stays around.
+ * On success, returns the new nsproxy.
  */
 int unshare_nsproxy_namespaces(unsigned long unshare_flags,
 		struct nsproxy **new_nsp, struct fs_struct *new_fs)
 {
-	struct nsproxy *old_ns = current->nsproxy;
 	int err = 0;
 
-	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+			       CLONE_NEWUSER)))
 		return 0;
 
-#ifndef CONFIG_IPC_NS
-	if (unshare_flags & CLONE_NEWIPC)
-		return -EINVAL;
-#endif
-
-#ifndef CONFIG_UTS_NS
-	if (unshare_flags & CLONE_NEWUTS)
-		return -EINVAL;
-#endif
-
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	get_nsproxy(old_ns);
-
 	*new_nsp = create_new_namespaces(unshare_flags, current,
 				new_fs ? new_fs : current->fs);
-	if (IS_ERR(*new_nsp)) {
+	if (IS_ERR(*new_nsp))
 		err = PTR_ERR(*new_nsp);
-		put_nsproxy(old_ns);
-	}
 	return err;
 }
+
+static int __init nsproxy_cache_init(void)
+{
+	nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
+					   0, SLAB_PANIC, NULL, NULL);
+	return 0;
+}
+
+module_init(nsproxy_cache_init);
diff --git a/kernel/panic.c b/kernel/panic.c
index 623d182..f64f4c1 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -159,14 +159,15 @@
 {
 	static char buf[20];
 	if (tainted) {
-		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c",
+		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c",
 			tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
 			tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
 			tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
 			tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
  			tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
 			tainted & TAINT_BAD_PAGE ? 'B' : ' ',
-			tainted & TAINT_USER ? 'U' : ' ');
+			tainted & TAINT_USER ? 'U' : ' ',
+			tainted & TAINT_DIE ? 'D' : ' ');
 	}
 	else
 		snprintf(buf, sizeof(buf), "Not tainted");
diff --git a/kernel/params.c b/kernel/params.c
index e61c46c..effbaae 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -491,7 +491,6 @@
 			pattr->mattr.show = param_attr_show;
 			pattr->mattr.store = param_attr_store;
 			pattr->mattr.attr.name = (char *)&kp->name[name_skip];
-			pattr->mattr.attr.owner = mk->mod;
 			pattr->mattr.attr.mode = kp->perm;
 			*(gattr++) = &(pattr++)->mattr.attr;
 		}
diff --git a/kernel/pid.c b/kernel/pid.c
index eb66bd2..c6e3f9f 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -365,7 +365,7 @@
 }
 EXPORT_SYMBOL_GPL(find_get_pid);
 
-struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *old_ns)
+struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
 {
 	BUG_ON(!old_ns);
 	get_pid_ns(old_ns);
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 1de710e1..b53c8fc 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -161,7 +161,7 @@
 }
 static inline unsigned long long sched_ns(struct task_struct *p)
 {
-	return (p == current) ? current_sched_time(p) : p->sched_time;
+	return task_sched_runtime(p);
 }
 
 int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
@@ -246,10 +246,10 @@
 		} while (t != p);
 		break;
 	case CPUCLOCK_SCHED:
-		cpu->sched = p->signal->sched_time;
+		cpu->sched = p->signal->sum_sched_runtime;
 		/* Add in each other live thread.  */
 		while ((t = next_thread(t)) != p) {
-			cpu->sched += t->sched_time;
+			cpu->sched += t->se.sum_exec_runtime;
 		}
 		cpu->sched += sched_ns(p);
 		break;
@@ -422,7 +422,7 @@
  */
 static void cleanup_timers(struct list_head *head,
 			   cputime_t utime, cputime_t stime,
-			   unsigned long long sched_time)
+			   unsigned long long sum_exec_runtime)
 {
 	struct cpu_timer_list *timer, *next;
 	cputime_t ptime = cputime_add(utime, stime);
@@ -451,10 +451,10 @@
 	++head;
 	list_for_each_entry_safe(timer, next, head, entry) {
 		list_del_init(&timer->entry);
-		if (timer->expires.sched < sched_time) {
+		if (timer->expires.sched < sum_exec_runtime) {
 			timer->expires.sched = 0;
 		} else {
-			timer->expires.sched -= sched_time;
+			timer->expires.sched -= sum_exec_runtime;
 		}
 	}
 }
@@ -467,7 +467,7 @@
 void posix_cpu_timers_exit(struct task_struct *tsk)
 {
 	cleanup_timers(tsk->cpu_timers,
-		       tsk->utime, tsk->stime, tsk->sched_time);
+		       tsk->utime, tsk->stime, tsk->se.sum_exec_runtime);
 
 }
 void posix_cpu_timers_exit_group(struct task_struct *tsk)
@@ -475,7 +475,7 @@
 	cleanup_timers(tsk->signal->cpu_timers,
 		       cputime_add(tsk->utime, tsk->signal->utime),
 		       cputime_add(tsk->stime, tsk->signal->stime),
-		       tsk->sched_time + tsk->signal->sched_time);
+		     tsk->se.sum_exec_runtime + tsk->signal->sum_sched_runtime);
 }
 
 
@@ -536,7 +536,7 @@
 		nsleft = max_t(unsigned long long, nsleft, 1);
 		do {
 			if (likely(!(t->flags & PF_EXITING))) {
-				ns = t->sched_time + nsleft;
+				ns = t->se.sum_exec_runtime + nsleft;
 				if (t->it_sched_expires == 0 ||
 				    t->it_sched_expires > ns) {
 					t->it_sched_expires = ns;
@@ -1004,7 +1004,7 @@
 		struct cpu_timer_list *t = list_first_entry(timers,
 						      struct cpu_timer_list,
 						      entry);
-		if (!--maxfire || tsk->sched_time < t->expires.sched) {
+		if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) {
 			tsk->it_sched_expires = t->expires.sched;
 			break;
 		}
@@ -1024,7 +1024,7 @@
 	int maxfire;
 	struct signal_struct *const sig = tsk->signal;
 	cputime_t utime, stime, ptime, virt_expires, prof_expires;
-	unsigned long long sched_time, sched_expires;
+	unsigned long long sum_sched_runtime, sched_expires;
 	struct task_struct *t;
 	struct list_head *timers = sig->cpu_timers;
 
@@ -1044,12 +1044,12 @@
 	 */
 	utime = sig->utime;
 	stime = sig->stime;
-	sched_time = sig->sched_time;
+	sum_sched_runtime = sig->sum_sched_runtime;
 	t = tsk;
 	do {
 		utime = cputime_add(utime, t->utime);
 		stime = cputime_add(stime, t->stime);
-		sched_time += t->sched_time;
+		sum_sched_runtime += t->se.sum_exec_runtime;
 		t = next_thread(t);
 	} while (t != tsk);
 	ptime = cputime_add(utime, stime);
@@ -1090,7 +1090,7 @@
 		struct cpu_timer_list *t = list_first_entry(timers,
 						      struct cpu_timer_list,
 						      entry);
-		if (!--maxfire || sched_time < t->expires.sched) {
+		if (!--maxfire || sum_sched_runtime < t->expires.sched) {
 			sched_expires = t->expires.sched;
 			break;
 		}
@@ -1182,7 +1182,7 @@
 		virt_left = cputime_sub(virt_expires, utime);
 		virt_left = cputime_div_non_zero(virt_left, nthreads);
 		if (sched_expires) {
-			sched_left = sched_expires - sched_time;
+			sched_left = sched_expires - sum_sched_runtime;
 			do_div(sched_left, nthreads);
 			sched_left = max_t(unsigned long long, sched_left, 1);
 		} else {
@@ -1208,7 +1208,7 @@
 				t->it_virt_expires = ticks;
 			}
 
-			sched = t->sched_time + sched_left;
+			sched = t->se.sum_exec_runtime + sched_left;
 			if (sched_expires && (t->it_sched_expires == 0 ||
 					      t->it_sched_expires > sched)) {
 				t->it_sched_expires = sched;
@@ -1300,7 +1300,7 @@
 
 	if (UNEXPIRED(prof) && UNEXPIRED(virt) &&
 	    (tsk->it_sched_expires == 0 ||
-	     tsk->sched_time < tsk->it_sched_expires))
+	     tsk->se.sum_exec_runtime < tsk->it_sched_expires))
 		return;
 
 #undef	UNEXPIRED
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 588c99d..329ce01 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -353,9 +353,40 @@
 		 * it should be restarted.
 		 */
 		if (timr->it.real.interval.tv64 != 0) {
+			ktime_t now = hrtimer_cb_get_time(timer);
+
+			/*
+			 * FIXME: What we really want, is to stop this
+			 * timer completely and restart it in case the
+			 * SIG_IGN is removed. This is a non trivial
+			 * change which involves sighand locking
+			 * (sigh !), which we don't want to do late in
+			 * the release cycle.
+			 *
+			 * For now we just let timers with an interval
+			 * less than a jiffie expire every jiffie to
+			 * avoid softirq starvation in case of SIG_IGN
+			 * and a very small interval, which would put
+			 * the timer right back on the softirq pending
+			 * list. By moving now ahead of time we trick
+			 * hrtimer_forward() to expire the timer
+			 * later, while we still maintain the overrun
+			 * accuracy, but have some inconsistency in
+			 * the timer_gettime() case. This is at least
+			 * better than a starved softirq. A more
+			 * complex fix which solves also another related
+			 * inconsistency is already in the pipeline.
+			 */
+#ifdef CONFIG_HIGH_RES_TIMERS
+			{
+				ktime_t kj = ktime_set(0, NSEC_PER_SEC / HZ);
+
+				if (timr->it.real.interval.tv64 < kj.tv64)
+					now = ktime_add(now, kj);
+			}
+#endif
 			timr->it_overrun +=
-				hrtimer_forward(timer,
-						hrtimer_cb_get_time(timer),
+				hrtimer_forward(timer, now,
 						timr->it.real.interval);
 			ret = HRTIMER_RESTART;
 			++timr->it_requeue_pending;
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 8812985..fc45ed2 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/pm.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
 #include <linux/resume-trace.h>
@@ -97,6 +96,11 @@
 		}
 	}
 
+	if (pm_ops->set_target) {
+		error = pm_ops->set_target(state);
+		if (error)
+			goto Thaw;
+	}
 	suspend_console();
 	error = device_suspend(PMSG_SUSPEND);
 	if (error) {
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 0884193..e0233d8 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -31,16 +31,36 @@
 	return 1;
 }
 
+/*
+ * freezing is complete, mark current process as frozen
+ */
+static inline void frozen_process(void)
+{
+	if (!unlikely(current->flags & PF_NOFREEZE)) {
+		current->flags |= PF_FROZEN;
+		wmb();
+	}
+	clear_tsk_thread_flag(current, TIF_FREEZE);
+}
+
 /* Refrigerator is place where frozen processes are stored :-). */
 void refrigerator(void)
 {
 	/* Hmm, should we be allowed to suspend when there are realtime
 	   processes around? */
 	long save;
+
+	task_lock(current);
+	if (freezing(current)) {
+		frozen_process();
+		task_unlock(current);
+	} else {
+		task_unlock(current);
+		return;
+	}
 	save = current->state;
 	pr_debug("%s entered refrigerator\n", current->comm);
 
-	frozen_process(current);
 	spin_lock_irq(&current->sighand->siglock);
 	recalc_sigpending(); /* We sent fake signal, clean it up */
 	spin_unlock_irq(&current->sighand->siglock);
@@ -81,7 +101,7 @@
 		pr_debug("  clean up: %s\n", p->comm);
 		do_not_freeze(p);
 		spin_lock_irqsave(&p->sighand->siglock, flags);
-		recalc_sigpending_tsk(p);
+		recalc_sigpending_and_wake(p);
 		spin_unlock_irqrestore(&p->sighand->siglock, flags);
 	}
 }
@@ -112,22 +132,12 @@
 				cancel_freezing(p);
 				continue;
 			}
-			if (is_user_space(p)) {
-				if (!freeze_user_space)
-					continue;
+			if (freeze_user_space && !is_user_space(p))
+				continue;
 
-				/* Freeze the task unless there is a vfork
-				 * completion pending
-				 */
-				if (!p->vfork_done)
-					freeze_process(p);
-			} else {
-				if (freeze_user_space)
-					continue;
-
-				freeze_process(p);
-			}
-			todo++;
+			freeze_process(p);
+			if (!freezer_should_skip(p))
+				todo++;
 		} while_each_thread(g, p);
 		read_unlock(&tasklist_lock);
 		yield();			/* Yield is okay here */
@@ -149,13 +159,16 @@
 				TIMEOUT / HZ, todo);
 		read_lock(&tasklist_lock);
 		do_each_thread(g, p) {
-			if (is_user_space(p) == !freeze_user_space)
+			if (freeze_user_space && !is_user_space(p))
 				continue;
 
-			if (freezeable(p) && !frozen(p))
+			task_lock(p);
+			if (freezeable(p) && !frozen(p) &&
+			    !freezer_should_skip(p))
 				printk(KERN_ERR " %s\n", p->comm);
 
 			cancel_freezing(p);
+			task_unlock(p);
 		} while_each_thread(g, p);
 		read_unlock(&tasklist_lock);
 	}
@@ -200,9 +213,7 @@
 		if (is_user_space(p) == !thaw_user_space)
 			continue;
 
-		if (!thaw_process(p))
-			printk(KERN_WARNING " Strange, %s not stopped\n",
-				p->comm );
+		thaw_process(p);
 	} while_each_thread(g, p);
 	read_unlock(&tasklist_lock);
 }
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index b8b235c..8b1a1b8 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -584,7 +584,7 @@
 	resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
 	if (!IS_ERR(resume_bdev)) {
 		set_blocksize(resume_bdev, PAGE_SIZE);
-		memset(swsusp_header, 0, sizeof(PAGE_SIZE));
+		memset(swsusp_header, 0, PAGE_SIZE);
 		error = bio_read_page(swsusp_resume_block,
 					swsusp_header, NULL);
 		if (error)
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 24d7d78..d65305b 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -99,6 +99,8 @@
 	ssize_t res;
 
 	data = filp->private_data;
+	if (!data->ready)
+		return -ENODATA;
 	res = snapshot_read_next(&data->handle, count);
 	if (res > 0) {
 		if (copy_to_user(buf, data_of(data->handle), res))
@@ -245,7 +247,7 @@
 		break;
 
 	case SNAPSHOT_UNFREEZE:
-		if (!data->frozen)
+		if (!data->frozen || data->ready)
 			break;
 		mutex_lock(&pm_mutex);
 		thaw_processes();
diff --git a/kernel/printk.c b/kernel/printk.c
index 0bbdeac..051d27e 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -449,13 +449,16 @@
 #else
 static int printk_time = 0;
 #endif
-module_param(printk_time, int, S_IRUGO | S_IWUSR);
+module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
 
 static int __init printk_time_setup(char *str)
 {
 	if (*str)
 		return 0;
 	printk_time = 1;
+	printk(KERN_NOTICE "The 'time' option is deprecated and "
+		"is scheduled for removal in early 2008\n");
+	printk(KERN_NOTICE "Use 'printk.time=<value>' instead\n");
 	return 1;
 }
 
@@ -483,6 +486,9 @@
  * @fmt: format string
  *
  * This is printk().  It can be called from any context.  We want it to work.
+ * Be aware of the fact that if oops_in_progress is not set, we might try to
+ * wake klogd up which could deadlock on runqueue lock if printk() is called
+ * from scheduler code.
  *
  * We try to grab the console_sem.  If we succeed, it's easy - we log the output and
  * call the console drivers.  If we fail to get the semaphore we place the output
@@ -654,7 +660,7 @@
  */
 static int __init console_setup(char *str)
 {
-	char name[sizeof(console_cmdline[0].name)];
+	char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */
 	char *s, *options;
 	int idx;
 
@@ -662,27 +668,27 @@
 	 * Decode str into name, index, options.
 	 */
 	if (str[0] >= '0' && str[0] <= '9') {
-		strcpy(name, "ttyS");
-		strncpy(name + 4, str, sizeof(name) - 5);
+		strcpy(buf, "ttyS");
+		strncpy(buf + 4, str, sizeof(buf) - 5);
 	} else {
-		strncpy(name, str, sizeof(name) - 1);
+		strncpy(buf, str, sizeof(buf) - 1);
 	}
-	name[sizeof(name) - 1] = 0;
+	buf[sizeof(buf) - 1] = 0;
 	if ((options = strchr(str, ',')) != NULL)
 		*(options++) = 0;
 #ifdef __sparc__
 	if (!strcmp(str, "ttya"))
-		strcpy(name, "ttyS0");
+		strcpy(buf, "ttyS0");
 	if (!strcmp(str, "ttyb"))
-		strcpy(name, "ttyS1");
+		strcpy(buf, "ttyS1");
 #endif
-	for (s = name; *s; s++)
+	for (s = buf; *s; s++)
 		if ((*s >= '0' && *s <= '9') || *s == ',')
 			break;
 	idx = simple_strtoul(s, NULL, 10);
 	*s = 0;
 
-	add_preferred_console(name, idx, options);
+	add_preferred_console(buf, idx, options);
 	return 1;
 }
 __setup("console=", console_setup);
@@ -709,7 +715,7 @@
 	 *	See if this tty is not yet registered, and
 	 *	if we have a slot free.
 	 */
-	for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+	for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
 		if (strcmp(console_cmdline[i].name, name) == 0 &&
 			  console_cmdline[i].index == idx) {
 				selected_console = i;
@@ -726,6 +732,25 @@
 	return 0;
 }
 
+int __init update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
+{
+	struct console_cmdline *c;
+	int i;
+
+	for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+		if (strcmp(console_cmdline[i].name, name) == 0 &&
+			  console_cmdline[i].index == idx) {
+				c = &console_cmdline[i];
+				memcpy(c->name, name_new, sizeof(c->name));
+				c->name[sizeof(c->name) - 1] = 0;
+				c->options = options;
+				c->index = idx_new;
+				return i;
+		}
+	/* not found */
+	return -1;
+}
+
 #ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
 /**
  * suspend_console - suspend the console subsystem
@@ -942,6 +967,9 @@
 	if (preferred_console < 0 || bootconsole || !console_drivers)
 		preferred_console = selected_console;
 
+	if (console->early_setup)
+		console->early_setup();
+
 	/*
 	 *	See if we want to use this console driver. If we
 	 *	didn't select a console we take the first one
@@ -985,12 +1013,15 @@
 	if (!(console->flags & CON_ENABLED))
 		return;
 
-	if (bootconsole) {
+	if (bootconsole && (console->flags & CON_CONSDEV)) {
 		printk(KERN_INFO "console handover: boot [%s%d] -> real [%s%d]\n",
 		       bootconsole->name, bootconsole->index,
 		       console->name, console->index);
 		unregister_console(bootconsole);
 		console->flags &= ~CON_PRINTBUFFER;
+	} else {
+		printk(KERN_INFO "console [%s%d] enabled\n",
+		       console->name, console->index);
 	}
 
 	/*
diff --git a/kernel/profile.c b/kernel/profile.c
index cc91b9b..5b20fe9 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -26,6 +26,7 @@
 #include <asm/sections.h>
 #include <asm/semaphore.h>
 #include <asm/irq_regs.h>
+#include <asm/ptrace.h>
 
 struct profile_hit {
 	u32 pc, hits;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index ad7949a..4a1745f1 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -161,6 +161,7 @@
 int ptrace_attach(struct task_struct *task)
 {
 	int retval;
+	unsigned long flags;
 
 	audit_ptrace(task);
 
@@ -181,9 +182,7 @@
 	 * cpu's that may have task_lock).
 	 */
 	task_lock(task);
-	local_irq_disable();
-	if (!write_trylock(&tasklist_lock)) {
-		local_irq_enable();
+	if (!write_trylock_irqsave(&tasklist_lock, flags)) {
 		task_unlock(task);
 		do {
 			cpu_relax();
@@ -211,7 +210,7 @@
 	force_sig_specific(SIGSTOP, task);
 
 bad:
-	write_unlock_irq(&tasklist_lock);
+	write_unlock_irqrestore(&tasklist_lock, flags);
 	task_unlock(task);
 out:
 	return retval;
@@ -491,3 +490,22 @@
 	return ret;
 }
 #endif /* __ARCH_SYS_PTRACE */
+
+int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data)
+{
+	unsigned long tmp;
+	int copied;
+
+	copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
+	if (copied != sizeof(tmp))
+		return -EIO;
+	return put_user(tmp, (unsigned long __user *)data);
+}
+
+int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
+{
+	int copied;
+
+	copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
+	return (copied == sizeof(data)) ? 0 : -EIO;
+}
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 55ba82a..ddff332 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -40,6 +40,7 @@
 #include <linux/moduleparam.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
+#include <linux/freezer.h>
 #include <linux/cpu.h>
 #include <linux/random.h>
 #include <linux/delay.h>
@@ -518,7 +519,6 @@
 
 	VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
 	set_user_nice(current, 19);
-	current->flags |= PF_NOFREEZE;
 
 	do {
 		schedule_timeout_uninterruptible(1);
@@ -558,7 +558,6 @@
 
 	VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
 	set_user_nice(current, 19);
-	current->flags |= PF_NOFREEZE;
 
 	do {
 		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
@@ -589,7 +588,6 @@
 
 	VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
 	set_user_nice(current, 19);
-	current->flags |= PF_NOFREEZE;
 
 	do {
 		idx = cur_ops->readlock();
diff --git a/kernel/relay.c b/kernel/relay.c
index 4311101..a615a8f 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -21,6 +21,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/cpu.h>
+#include <linux/splice.h>
 
 /* list of open channels, for cpu hotplug */
 static DEFINE_MUTEX(relay_channels_mutex);
@@ -121,6 +122,7 @@
 		buf->page_array[i] = alloc_page(GFP_KERNEL);
 		if (unlikely(!buf->page_array[i]))
 			goto depopulate;
+		set_page_private(buf->page_array[i], (unsigned long)buf);
 	}
 	mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL);
 	if (!mem)
@@ -812,7 +814,10 @@
 	}
 
 	buf->bytes_consumed += bytes_consumed;
-	read_subbuf = read_pos / buf->chan->subbuf_size;
+	if (!read_pos)
+		read_subbuf = buf->subbufs_consumed % n_subbufs;
+	else
+		read_subbuf = read_pos / buf->chan->subbuf_size;
 	if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) {
 		if ((read_subbuf == buf->subbufs_produced % n_subbufs) &&
 		    (buf->offset == subbuf_size))
@@ -841,8 +846,9 @@
 	}
 
 	if (unlikely(produced - consumed >= n_subbufs)) {
-		consumed = (produced / n_subbufs) * n_subbufs;
+		consumed = produced - n_subbufs + 1;
 		buf->subbufs_consumed = consumed;
+		buf->bytes_consumed = 0;
 	}
 	
 	produced = (produced % n_subbufs) * subbuf_size + buf->offset;
@@ -899,7 +905,10 @@
 	size_t read_subbuf, padding, padding_start, padding_end;
 	size_t subbuf_size = buf->chan->subbuf_size;
 	size_t n_subbufs = buf->chan->n_subbufs;
+	size_t consumed = buf->subbufs_consumed % n_subbufs;
 
+	if (!read_pos)
+		read_pos = consumed * subbuf_size + buf->bytes_consumed;
 	read_subbuf = read_pos / subbuf_size;
 	padding = buf->padding[read_subbuf];
 	padding_start = (read_subbuf + 1) * subbuf_size - padding;
@@ -963,43 +972,6 @@
 	return ret;
 }
 
-/*
- *	subbuf_send_actor - send up to one subbuf's worth of data
- */
-static int subbuf_send_actor(size_t read_start,
-			     struct rchan_buf *buf,
-			     size_t avail,
-			     read_descriptor_t *desc,
-			     read_actor_t actor)
-{
-	unsigned long pidx, poff;
-	unsigned int subbuf_pages;
-	int ret = 0;
-
-	subbuf_pages = buf->chan->alloc_size >> PAGE_SHIFT;
-	pidx = (read_start / PAGE_SIZE) % subbuf_pages;
-	poff = read_start & ~PAGE_MASK;
-	while (avail) {
-		struct page *p = buf->page_array[pidx];
-		unsigned int len;
-
-		len = PAGE_SIZE - poff;
-		if (len > avail)
-			len = avail;
-
-		len = actor(desc, p, poff, len);
-		if (desc->error)
-			break;
-
-		avail -= len;
-		ret += len;
-		poff = 0;
-		pidx = (pidx + 1) % subbuf_pages;
-	}
-
-	return ret;
-}
-
 typedef int (*subbuf_actor_t) (size_t read_start,
 			       struct rchan_buf *buf,
 			       size_t avail,
@@ -1060,19 +1032,161 @@
 				       NULL, &desc);
 }
 
-static ssize_t relay_file_sendfile(struct file *filp,
-				   loff_t *ppos,
-				   size_t count,
-				   read_actor_t actor,
-				   void *target)
+static void relay_consume_bytes(struct rchan_buf *rbuf, int bytes_consumed)
 {
-	read_descriptor_t desc;
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-	return relay_file_read_subbufs(filp, ppos, subbuf_send_actor,
-				       actor, &desc);
+	rbuf->bytes_consumed += bytes_consumed;
+
+	if (rbuf->bytes_consumed >= rbuf->chan->subbuf_size) {
+		relay_subbufs_consumed(rbuf->chan, rbuf->cpu, 1);
+		rbuf->bytes_consumed %= rbuf->chan->subbuf_size;
+	}
+}
+
+static void relay_pipe_buf_release(struct pipe_inode_info *pipe,
+				   struct pipe_buffer *buf)
+{
+	struct rchan_buf *rbuf;
+
+	rbuf = (struct rchan_buf *)page_private(buf->page);
+	relay_consume_bytes(rbuf, buf->private);
+}
+
+static struct pipe_buf_operations relay_pipe_buf_ops = {
+	.can_merge = 0,
+	.map = generic_pipe_buf_map,
+	.unmap = generic_pipe_buf_unmap,
+	.confirm = generic_pipe_buf_confirm,
+	.release = relay_pipe_buf_release,
+	.steal = generic_pipe_buf_steal,
+	.get = generic_pipe_buf_get,
+};
+
+/*
+ *	subbuf_splice_actor - splice up to one subbuf's worth of data
+ */
+static int subbuf_splice_actor(struct file *in,
+			       loff_t *ppos,
+			       struct pipe_inode_info *pipe,
+			       size_t len,
+			       unsigned int flags,
+			       int *nonpad_ret)
+{
+	unsigned int pidx, poff, total_len, subbuf_pages, ret;
+	struct rchan_buf *rbuf = in->private_data;
+	unsigned int subbuf_size = rbuf->chan->subbuf_size;
+	uint64_t pos = (uint64_t) *ppos;
+	uint32_t alloc_size = (uint32_t) rbuf->chan->alloc_size;
+	size_t read_start = (size_t) do_div(pos, alloc_size);
+	size_t read_subbuf = read_start / subbuf_size;
+	size_t padding = rbuf->padding[read_subbuf];
+	size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding;
+	struct page *pages[PIPE_BUFFERS];
+	struct partial_page partial[PIPE_BUFFERS];
+	struct splice_pipe_desc spd = {
+		.pages = pages,
+		.nr_pages = 0,
+		.partial = partial,
+		.flags = flags,
+		.ops = &relay_pipe_buf_ops,
+	};
+
+	if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
+		return 0;
+
+	/*
+	 * Adjust read len, if longer than what is available
+	 */
+	if (len > (subbuf_size - read_start % subbuf_size))
+		len = subbuf_size - read_start % subbuf_size;
+
+	subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT;
+	pidx = (read_start / PAGE_SIZE) % subbuf_pages;
+	poff = read_start & ~PAGE_MASK;
+
+	for (total_len = 0; spd.nr_pages < subbuf_pages; spd.nr_pages++) {
+		unsigned int this_len, this_end, private;
+		unsigned int cur_pos = read_start + total_len;
+
+		if (!len)
+			break;
+
+		this_len = min_t(unsigned long, len, PAGE_SIZE - poff);
+		private = this_len;
+
+		spd.pages[spd.nr_pages] = rbuf->page_array[pidx];
+		spd.partial[spd.nr_pages].offset = poff;
+
+		this_end = cur_pos + this_len;
+		if (this_end >= nonpad_end) {
+			this_len = nonpad_end - cur_pos;
+			private = this_len + padding;
+		}
+		spd.partial[spd.nr_pages].len = this_len;
+		spd.partial[spd.nr_pages].private = private;
+
+		len -= this_len;
+		total_len += this_len;
+		poff = 0;
+		pidx = (pidx + 1) % subbuf_pages;
+
+		if (this_end >= nonpad_end) {
+			spd.nr_pages++;
+			break;
+		}
+	}
+
+	if (!spd.nr_pages)
+		return 0;
+
+	ret = *nonpad_ret = splice_to_pipe(pipe, &spd);
+	if (ret < 0 || ret < total_len)
+		return ret;
+
+        if (read_start + ret == nonpad_end)
+                ret += padding;
+
+        return ret;
+}
+
+static ssize_t relay_file_splice_read(struct file *in,
+				      loff_t *ppos,
+				      struct pipe_inode_info *pipe,
+				      size_t len,
+				      unsigned int flags)
+{
+	ssize_t spliced;
+	int ret;
+	int nonpad_ret = 0;
+
+	ret = 0;
+	spliced = 0;
+
+	while (len) {
+		ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret);
+		if (ret < 0)
+			break;
+		else if (!ret) {
+			if (spliced)
+				break;
+			if (flags & SPLICE_F_NONBLOCK) {
+				ret = -EAGAIN;
+				break;
+			}
+		}
+
+		*ppos += ret;
+		if (ret > len)
+			len = 0;
+		else
+			len -= ret;
+		spliced += nonpad_ret;
+		nonpad_ret = 0;
+	}
+
+	if (spliced)
+		return spliced;
+
+	return ret;
 }
 
 const struct file_operations relay_file_operations = {
@@ -1082,7 +1196,7 @@
 	.read		= relay_file_read,
 	.llseek		= no_llseek,
 	.release	= relay_file_release,
-	.sendfile       = relay_file_sendfile,
+	.splice_read	= relay_file_splice_read,
 };
 EXPORT_SYMBOL_GPL(relay_file_operations);
 
diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c
index da8d6bf..5aedbee 100644
--- a/kernel/rtmutex-debug.c
+++ b/kernel/rtmutex-debug.c
@@ -29,12 +29,6 @@
 
 #include "rtmutex_common.h"
 
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
 # define TRACE_WARN_ON(x)			WARN_ON(x)
 # define TRACE_BUG_ON(x)			BUG_ON(x)
 
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index 015fc63..e3055ba 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -260,6 +260,7 @@
 	int ret;
 
 	current->flags |= PF_MUTEX_TESTER;
+	set_freezable();
 	allow_signal(SIGHUP);
 
 	for(;;) {
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 12879f6..8cd9bd2 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -17,12 +17,6 @@
 
 #include "rtmutex_common.h"
 
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
 /*
  * lock->owner state tracking:
  *
@@ -56,7 +50,7 @@
  * state.
  */
 
-void
+static void
 rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
 		   unsigned long mask)
 {
@@ -81,6 +75,29 @@
 }
 
 /*
+ * We can speed up the acquire/release, if the architecture
+ * supports cmpxchg and if there's no debugging state to be set up
+ */
+#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES)
+# define rt_mutex_cmpxchg(l,c,n)	(cmpxchg(&l->owner, c, n) == c)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+	unsigned long owner, *p = (unsigned long *) &lock->owner;
+
+	do {
+		owner = *p;
+	} while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner);
+}
+#else
+# define rt_mutex_cmpxchg(l,c,n)	(0)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+	lock->owner = (struct task_struct *)
+			((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS);
+}
+#endif
+
+/*
  * Calculate task priority from the waiter list priority
  *
  * Return task->normal_prio when the waiter list is empty or when
@@ -100,7 +117,7 @@
  *
  * This can be both boosting and unboosting. task->pi_lock must be held.
  */
-void __rt_mutex_adjust_prio(struct task_struct *task)
+static void __rt_mutex_adjust_prio(struct task_struct *task)
 {
 	int prio = rt_mutex_getprio(task);
 
@@ -136,11 +153,11 @@
  * Decreases task's usage by one - may thus free the task.
  * Returns 0 or -EDEADLK.
  */
-int rt_mutex_adjust_prio_chain(struct task_struct *task,
-			       int deadlock_detect,
-			       struct rt_mutex *orig_lock,
-			       struct rt_mutex_waiter *orig_waiter,
-			       struct task_struct *top_task)
+static int rt_mutex_adjust_prio_chain(struct task_struct *task,
+				      int deadlock_detect,
+				      struct rt_mutex *orig_lock,
+				      struct rt_mutex_waiter *orig_waiter,
+				      struct task_struct *top_task)
 {
 	struct rt_mutex *lock;
 	struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter;
@@ -189,6 +206,19 @@
 	if (!waiter || !waiter->task)
 		goto out_unlock_pi;
 
+	/*
+	 * Check the orig_waiter state. After we dropped the locks,
+	 * the previous owner of the lock might have released the lock
+	 * and made us the pending owner:
+	 */
+	if (orig_waiter && !orig_waiter->task)
+		goto out_unlock_pi;
+
+	/*
+	 * Drop out, when the task has no waiters. Note,
+	 * top_waiter can be NULL, when we are in the deboosting
+	 * mode!
+	 */
 	if (top_waiter && (!task_has_pi_waiters(task) ||
 			   top_waiter != task_top_pi_waiter(task)))
 		goto out_unlock_pi;
@@ -501,8 +531,8 @@
  *
  * Must be called with lock->wait_lock held
  */
-void remove_waiter(struct rt_mutex *lock,
-		   struct rt_mutex_waiter *waiter)
+static void remove_waiter(struct rt_mutex *lock,
+			  struct rt_mutex_waiter *waiter)
 {
 	int first = (waiter == rt_mutex_top_waiter(lock));
 	struct task_struct *owner = rt_mutex_owner(lock);
@@ -636,9 +666,16 @@
 			 * all over without going into schedule to try
 			 * to get the lock now:
 			 */
-			if (unlikely(!waiter.task))
+			if (unlikely(!waiter.task)) {
+				/*
+				 * Reset the return value. We might
+				 * have returned with -EDEADLK and the
+				 * owner released the lock while we
+				 * were walking the pi chain.
+				 */
+				ret = 0;
 				continue;
-
+			}
 			if (unlikely(ret))
 				break;
 		}
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
index 242ec7e..2d3b835 100644
--- a/kernel/rtmutex_common.h
+++ b/kernel/rtmutex_common.h
@@ -103,7 +103,7 @@
 
 static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock)
 {
- 	return (struct task_struct *)
+	return (struct task_struct *)
 		((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS);
 }
 
@@ -113,29 +113,6 @@
 }
 
 /*
- * We can speed up the acquire/release, if the architecture
- * supports cmpxchg and if there's no debugging state to be set up
- */
-#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES)
-# define rt_mutex_cmpxchg(l,c,n)	(cmpxchg(&l->owner, c, n) == c)
-static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
-{
-	unsigned long owner, *p = (unsigned long *) &lock->owner;
-
-	do {
-		owner = *p;
-	} while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner);
-}
-#else
-# define rt_mutex_cmpxchg(l,c,n)	(0)
-static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
-{
-	lock->owner = (struct task_struct *)
-			((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS);
-}
-#endif
-
-/*
  * PI-futex support (proxy locking functions, etc.):
  */
 extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock);
@@ -144,14 +121,10 @@
 extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
 				  struct task_struct *proxy_owner);
 
-extern void rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
-			       unsigned long mask);
-extern void __rt_mutex_adjust_prio(struct task_struct *task);
-extern int rt_mutex_adjust_prio_chain(struct task_struct *task,
-				      int deadlock_detect,
-				      struct rt_mutex *orig_lock,
-				      struct rt_mutex_waiter *orig_waiter,
-				      struct task_struct *top_task);
-extern void remove_waiter(struct rt_mutex *lock,
-			  struct rt_mutex_waiter *waiter);
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# include "rtmutex-debug.h"
+#else
+# include "rtmutex.h"
+#endif
+
 #endif
diff --git a/kernel/sched.c b/kernel/sched.c
index 799d23b..cb31fb4a 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -16,13 +16,19 @@
  *		by Davide Libenzi, preemptible kernel bits by Robert Love.
  *  2003-09-03	Interactivity tuning by Con Kolivas.
  *  2004-04-02	Scheduler domains code by Nick Piggin
+ *  2007-04-15  Work begun on replacing all interactivity tuning with a
+ *              fair scheduling design by Con Kolivas.
+ *  2007-05-05  Load balancing (smp-nice) and other improvements
+ *              by Peter Williams
+ *  2007-05-06  Interactivity improvements to CFS by Mike Galbraith
+ *  2007-07-01  Group scheduling enhancements by Srivatsa Vaddagiri
  */
 
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/nmi.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/highmem.h>
 #include <linux/smp_lock.h>
 #include <asm/mmu_context.h>
@@ -53,9 +59,9 @@
 #include <linux/kprobes.h>
 #include <linux/delayacct.h>
 #include <linux/reciprocal_div.h>
+#include <linux/unistd.h>
 
 #include <asm/tlb.h>
-#include <asm/unistd.h>
 
 /*
  * Scheduler clock - returns current time in nanosec units.
@@ -91,6 +97,9 @@
 #define NS_TO_JIFFIES(TIME)	((TIME) / (1000000000 / HZ))
 #define JIFFIES_TO_NS(TIME)	((TIME) * (1000000000 / HZ))
 
+#define NICE_0_LOAD		SCHED_LOAD_SCALE
+#define NICE_0_SHIFT		SCHED_LOAD_SHIFT
+
 /*
  * These are the 'tuning knobs' of the scheduler:
  *
@@ -100,87 +109,6 @@
  */
 #define MIN_TIMESLICE		max(5 * HZ / 1000, 1)
 #define DEF_TIMESLICE		(100 * HZ / 1000)
-#define ON_RUNQUEUE_WEIGHT	 30
-#define CHILD_PENALTY		 95
-#define PARENT_PENALTY		100
-#define EXIT_WEIGHT		  3
-#define PRIO_BONUS_RATIO	 25
-#define MAX_BONUS		(MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
-#define INTERACTIVE_DELTA	  2
-#define MAX_SLEEP_AVG		(DEF_TIMESLICE * MAX_BONUS)
-#define STARVATION_LIMIT	(MAX_SLEEP_AVG)
-#define NS_MAX_SLEEP_AVG	(JIFFIES_TO_NS(MAX_SLEEP_AVG))
-
-/*
- * If a task is 'interactive' then we reinsert it in the active
- * array after it has expired its current timeslice. (it will not
- * continue to run immediately, it will still roundrobin with
- * other interactive tasks.)
- *
- * This part scales the interactivity limit depending on niceness.
- *
- * We scale it linearly, offset by the INTERACTIVE_DELTA delta.
- * Here are a few examples of different nice levels:
- *
- *  TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0]
- *  TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0]
- *  TASK_INTERACTIVE(  0): [1,1,1,1,0,0,0,0,0,0,0]
- *  TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0]
- *  TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0]
- *
- * (the X axis represents the possible -5 ... 0 ... +5 dynamic
- *  priority range a task can explore, a value of '1' means the
- *  task is rated interactive.)
- *
- * Ie. nice +19 tasks can never get 'interactive' enough to be
- * reinserted into the active array. And only heavily CPU-hog nice -20
- * tasks will be expired. Default nice 0 tasks are somewhere between,
- * it takes some effort for them to get interactive, but it's not
- * too hard.
- */
-
-#define CURRENT_BONUS(p) \
-	(NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
-		MAX_SLEEP_AVG)
-
-#define GRANULARITY	(10 * HZ / 1000 ? : 1)
-
-#ifdef CONFIG_SMP
-#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
-		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \
-			num_online_cpus())
-#else
-#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
-		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)))
-#endif
-
-#define SCALE(v1,v1_max,v2_max) \
-	(v1) * (v2_max) / (v1_max)
-
-#define DELTA(p) \
-	(SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
-		INTERACTIVE_DELTA)
-
-#define TASK_INTERACTIVE(p) \
-	((p)->prio <= (p)->static_prio - DELTA(p))
-
-#define INTERACTIVE_SLEEP(p) \
-	(JIFFIES_TO_NS(MAX_SLEEP_AVG * \
-		(MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1))
-
-#define TASK_PREEMPTS_CURR(p, rq) \
-	((p)->prio < (rq)->curr->prio)
-
-#define SCALE_PRIO(x, prio) \
-	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
-
-static unsigned int static_prio_timeslice(int static_prio)
-{
-	if (static_prio < NICE_TO_PRIO(0))
-		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
-	else
-		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
-}
 
 #ifdef CONFIG_SMP
 /*
@@ -203,28 +131,87 @@
 }
 #endif
 
-/*
- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
- * to time slice values: [800ms ... 100ms ... 5ms]
- *
- * The higher a thread's priority, the bigger timeslices
- * it gets during one round of execution. But even the lowest
- * priority thread gets MIN_TIMESLICE worth of execution time.
- */
+#define SCALE_PRIO(x, prio) \
+	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
 
-static inline unsigned int task_timeslice(struct task_struct *p)
+/*
+ * static_prio_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
+ * to time slice values: [800ms ... 100ms ... 5ms]
+ */
+static unsigned int static_prio_timeslice(int static_prio)
 {
-	return static_prio_timeslice(p->static_prio);
+	if (static_prio == NICE_TO_PRIO(19))
+		return 1;
+
+	if (static_prio < NICE_TO_PRIO(0))
+		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
+	else
+		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
+}
+
+static inline int rt_policy(int policy)
+{
+	if (unlikely(policy == SCHED_FIFO) || unlikely(policy == SCHED_RR))
+		return 1;
+	return 0;
+}
+
+static inline int task_has_rt_policy(struct task_struct *p)
+{
+	return rt_policy(p->policy);
 }
 
 /*
- * These are the runqueue data structures:
+ * This is the priority-queue data structure of the RT scheduling class:
  */
+struct rt_prio_array {
+	DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */
+	struct list_head queue[MAX_RT_PRIO];
+};
 
-struct prio_array {
-	unsigned int nr_active;
-	DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
-	struct list_head queue[MAX_PRIO];
+struct load_stat {
+	struct load_weight load;
+	u64 load_update_start, load_update_last;
+	unsigned long delta_fair, delta_exec, delta_stat;
+};
+
+/* CFS-related fields in a runqueue */
+struct cfs_rq {
+	struct load_weight load;
+	unsigned long nr_running;
+
+	s64 fair_clock;
+	u64 exec_clock;
+	s64 wait_runtime;
+	u64 sleeper_bonus;
+	unsigned long wait_runtime_overruns, wait_runtime_underruns;
+
+	struct rb_root tasks_timeline;
+	struct rb_node *rb_leftmost;
+	struct rb_node *rb_load_balance_curr;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	/* 'curr' points to currently running entity on this cfs_rq.
+	 * It is set to NULL otherwise (i.e when none are currently running).
+	 */
+	struct sched_entity *curr;
+	struct rq *rq;	/* cpu runqueue to which this cfs_rq is attached */
+
+	/* leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
+	 * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
+	 * (like users, containers etc.)
+	 *
+	 * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
+	 * list is used during load balance.
+	 */
+	struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */
+#endif
+};
+
+/* Real-Time classes' related field in a runqueue: */
+struct rt_rq {
+	struct rt_prio_array active;
+	int rt_load_balance_idx;
+	struct list_head *rt_load_balance_head, *rt_load_balance_curr;
 };
 
 /*
@@ -235,22 +222,28 @@
  * acquire operations must be ordered by ascending &runqueue.
  */
 struct rq {
-	spinlock_t lock;
+	spinlock_t lock;	/* runqueue lock */
 
 	/*
 	 * nr_running and cpu_load should be in the same cacheline because
 	 * remote CPUs use both these fields when doing load calculation.
 	 */
 	unsigned long nr_running;
-	unsigned long raw_weighted_load;
-#ifdef CONFIG_SMP
-	unsigned long cpu_load[3];
+	#define CPU_LOAD_IDX_MAX 5
+	unsigned long cpu_load[CPU_LOAD_IDX_MAX];
 	unsigned char idle_at_tick;
 #ifdef CONFIG_NO_HZ
 	unsigned char in_nohz_recently;
 #endif
+	struct load_stat ls;	/* capture load from *all* tasks on this cpu */
+	unsigned long nr_load_updates;
+	u64 nr_switches;
+
+	struct cfs_rq cfs;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	struct list_head leaf_cfs_rq_list; /* list of leaf cfs_rq on this cpu */
 #endif
-	unsigned long long nr_switches;
+	struct rt_rq  rt;
 
 	/*
 	 * This is part of a global counter where only the total sum
@@ -260,14 +253,18 @@
 	 */
 	unsigned long nr_uninterruptible;
 
-	unsigned long expired_timestamp;
-	/* Cached timestamp set by update_cpu_clock() */
-	unsigned long long most_recent_timestamp;
 	struct task_struct *curr, *idle;
 	unsigned long next_balance;
 	struct mm_struct *prev_mm;
-	struct prio_array *active, *expired, arrays[2];
-	int best_expired_prio;
+
+	u64 clock, prev_clock_raw;
+	s64 clock_max_delta;
+
+	unsigned int clock_warps, clock_overflows;
+	unsigned int clock_unstable_events;
+
+	struct sched_class *load_balance_class;
+
 	atomic_t nr_iowait;
 
 #ifdef CONFIG_SMP
@@ -307,6 +304,11 @@
 static DEFINE_PER_CPU(struct rq, runqueues) ____cacheline_aligned_in_smp;
 static DEFINE_MUTEX(sched_hotcpu_mutex);
 
+static inline void check_preempt_curr(struct rq *rq, struct task_struct *p)
+{
+	rq->curr->sched_class->check_preempt_curr(rq, p);
+}
+
 static inline int cpu_of(struct rq *rq)
 {
 #ifdef CONFIG_SMP
@@ -317,6 +319,52 @@
 }
 
 /*
+ * Per-runqueue clock, as finegrained as the platform can give us:
+ */
+static unsigned long long __rq_clock(struct rq *rq)
+{
+	u64 prev_raw = rq->prev_clock_raw;
+	u64 now = sched_clock();
+	s64 delta = now - prev_raw;
+	u64 clock = rq->clock;
+
+	/*
+	 * Protect against sched_clock() occasionally going backwards:
+	 */
+	if (unlikely(delta < 0)) {
+		clock++;
+		rq->clock_warps++;
+	} else {
+		/*
+		 * Catch too large forward jumps too:
+		 */
+		if (unlikely(delta > 2*TICK_NSEC)) {
+			clock++;
+			rq->clock_overflows++;
+		} else {
+			if (unlikely(delta > rq->clock_max_delta))
+				rq->clock_max_delta = delta;
+			clock += delta;
+		}
+	}
+
+	rq->prev_clock_raw = now;
+	rq->clock = clock;
+
+	return clock;
+}
+
+static inline unsigned long long rq_clock(struct rq *rq)
+{
+	int this_cpu = smp_processor_id();
+
+	if (this_cpu == cpu_of(rq))
+		return __rq_clock(rq);
+
+	return rq->clock;
+}
+
+/*
  * The domain tree (rq->sd) is protected by RCU's quiescent state transition.
  * See detach_destroy_domains: synchronize_sched for details.
  *
@@ -331,6 +379,18 @@
 #define task_rq(p)		cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/* Change a task's ->cfs_rq if it moves across CPUs */
+static inline void set_task_cfs_rq(struct task_struct *p)
+{
+	p->se.cfs_rq = &task_rq(p)->cfs;
+}
+#else
+static inline void set_task_cfs_rq(struct task_struct *p)
+{
+}
+#endif
+
 #ifndef prepare_arch_switch
 # define prepare_arch_switch(next)	do { } while (0)
 #endif
@@ -460,134 +520,6 @@
 	spin_unlock_irqrestore(&rq->lock, *flags);
 }
 
-#ifdef CONFIG_SCHEDSTATS
-/*
- * bump this up when changing the output format or the meaning of an existing
- * format, so that tools can adapt (or abort)
- */
-#define SCHEDSTAT_VERSION 14
-
-static int show_schedstat(struct seq_file *seq, void *v)
-{
-	int cpu;
-
-	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
-	seq_printf(seq, "timestamp %lu\n", jiffies);
-	for_each_online_cpu(cpu) {
-		struct rq *rq = cpu_rq(cpu);
-#ifdef CONFIG_SMP
-		struct sched_domain *sd;
-		int dcnt = 0;
-#endif
-
-		/* runqueue-specific stats */
-		seq_printf(seq,
-		    "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
-		    cpu, rq->yld_both_empty,
-		    rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
-		    rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
-		    rq->ttwu_cnt, rq->ttwu_local,
-		    rq->rq_sched_info.cpu_time,
-		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
-
-		seq_printf(seq, "\n");
-
-#ifdef CONFIG_SMP
-		/* domain-specific stats */
-		preempt_disable();
-		for_each_domain(cpu, sd) {
-			enum idle_type itype;
-			char mask_str[NR_CPUS];
-
-			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
-			seq_printf(seq, "domain%d %s", dcnt++, mask_str);
-			for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES;
-					itype++) {
-				seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
-						"%lu",
-				    sd->lb_cnt[itype],
-				    sd->lb_balanced[itype],
-				    sd->lb_failed[itype],
-				    sd->lb_imbalance[itype],
-				    sd->lb_gained[itype],
-				    sd->lb_hot_gained[itype],
-				    sd->lb_nobusyq[itype],
-				    sd->lb_nobusyg[itype]);
-			}
-			seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
-			    " %lu %lu %lu\n",
-			    sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
-			    sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
-			    sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
-			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
-			    sd->ttwu_move_balance);
-		}
-		preempt_enable();
-#endif
-	}
-	return 0;
-}
-
-static int schedstat_open(struct inode *inode, struct file *file)
-{
-	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
-	char *buf = kmalloc(size, GFP_KERNEL);
-	struct seq_file *m;
-	int res;
-
-	if (!buf)
-		return -ENOMEM;
-	res = single_open(file, show_schedstat, NULL);
-	if (!res) {
-		m = file->private_data;
-		m->buf = buf;
-		m->size = size;
-	} else
-		kfree(buf);
-	return res;
-}
-
-const struct file_operations proc_schedstat_operations = {
-	.open    = schedstat_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = single_release,
-};
-
-/*
- * Expects runqueue lock to be held for atomicity of update
- */
-static inline void
-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
-{
-	if (rq) {
-		rq->rq_sched_info.run_delay += delta_jiffies;
-		rq->rq_sched_info.pcnt++;
-	}
-}
-
-/*
- * Expects runqueue lock to be held for atomicity of update
- */
-static inline void
-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
-{
-	if (rq)
-		rq->rq_sched_info.cpu_time += delta_jiffies;
-}
-# define schedstat_inc(rq, field)	do { (rq)->field++; } while (0)
-# define schedstat_add(rq, field, amt)	do { (rq)->field += (amt); } while (0)
-#else /* !CONFIG_SCHEDSTATS */
-static inline void
-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
-{}
-static inline void
-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
-{}
-# define schedstat_inc(rq, field)	do { } while (0)
-# define schedstat_add(rq, field, amt)	do { } while (0)
-#endif
-
 /*
  * this_rq_lock - lock this runqueue and disable interrupts.
  */
@@ -603,444 +535,18 @@
 	return rq;
 }
 
-#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
 /*
- * Called when a process is dequeued from the active array and given
- * the cpu.  We should note that with the exception of interactive
- * tasks, the expired queue will become the active queue after the active
- * queue is empty, without explicitly dequeuing and requeuing tasks in the
- * expired queue.  (Interactive tasks may be requeued directly to the
- * active queue, thus delaying tasks in the expired queue from running;
- * see scheduler_tick()).
- *
- * This function is only called from sched_info_arrive(), rather than
- * dequeue_task(). Even though a task may be queued and dequeued multiple
- * times as it is shuffled about, we're really interested in knowing how
- * long it was from the *first* time it was queued to the time that it
- * finally hit a cpu.
+ * CPU frequency is/was unstable - start new by setting prev_clock_raw:
  */
-static inline void sched_info_dequeued(struct task_struct *t)
+void sched_clock_unstable_event(void)
 {
-	t->sched_info.last_queued = 0;
-}
+	unsigned long flags;
+	struct rq *rq;
 
-/*
- * Called when a task finally hits the cpu.  We can now calculate how
- * long it was waiting to run.  We also note when it began so that we
- * can keep stats on how long its timeslice is.
- */
-static void sched_info_arrive(struct task_struct *t)
-{
-	unsigned long now = jiffies, delta_jiffies = 0;
-
-	if (t->sched_info.last_queued)
-		delta_jiffies = now - t->sched_info.last_queued;
-	sched_info_dequeued(t);
-	t->sched_info.run_delay += delta_jiffies;
-	t->sched_info.last_arrival = now;
-	t->sched_info.pcnt++;
-
-	rq_sched_info_arrive(task_rq(t), delta_jiffies);
-}
-
-/*
- * Called when a process is queued into either the active or expired
- * array.  The time is noted and later used to determine how long we
- * had to wait for us to reach the cpu.  Since the expired queue will
- * become the active queue after active queue is empty, without dequeuing
- * and requeuing any tasks, we are interested in queuing to either. It
- * is unusual but not impossible for tasks to be dequeued and immediately
- * requeued in the same or another array: this can happen in sched_yield(),
- * set_user_nice(), and even load_balance() as it moves tasks from runqueue
- * to runqueue.
- *
- * This function is only called from enqueue_task(), but also only updates
- * the timestamp if it is already not set.  It's assumed that
- * sched_info_dequeued() will clear that stamp when appropriate.
- */
-static inline void sched_info_queued(struct task_struct *t)
-{
-	if (unlikely(sched_info_on()))
-		if (!t->sched_info.last_queued)
-			t->sched_info.last_queued = jiffies;
-}
-
-/*
- * Called when a process ceases being the active-running process, either
- * voluntarily or involuntarily.  Now we can calculate how long we ran.
- */
-static inline void sched_info_depart(struct task_struct *t)
-{
-	unsigned long delta_jiffies = jiffies - t->sched_info.last_arrival;
-
-	t->sched_info.cpu_time += delta_jiffies;
-	rq_sched_info_depart(task_rq(t), delta_jiffies);
-}
-
-/*
- * Called when tasks are switched involuntarily due, typically, to expiring
- * their time slice.  (This may also be called when switching to or from
- * the idle task.)  We are only called when prev != next.
- */
-static inline void
-__sched_info_switch(struct task_struct *prev, struct task_struct *next)
-{
-	struct rq *rq = task_rq(prev);
-
-	/*
-	 * prev now departs the cpu.  It's not interesting to record
-	 * stats about how efficient we were at scheduling the idle
-	 * process, however.
-	 */
-	if (prev != rq->idle)
-		sched_info_depart(prev);
-
-	if (next != rq->idle)
-		sched_info_arrive(next);
-}
-static inline void
-sched_info_switch(struct task_struct *prev, struct task_struct *next)
-{
-	if (unlikely(sched_info_on()))
-		__sched_info_switch(prev, next);
-}
-#else
-#define sched_info_queued(t)		do { } while (0)
-#define sched_info_switch(t, next)	do { } while (0)
-#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
-
-/*
- * Adding/removing a task to/from a priority array:
- */
-static void dequeue_task(struct task_struct *p, struct prio_array *array)
-{
-	array->nr_active--;
-	list_del(&p->run_list);
-	if (list_empty(array->queue + p->prio))
-		__clear_bit(p->prio, array->bitmap);
-}
-
-static void enqueue_task(struct task_struct *p, struct prio_array *array)
-{
-	sched_info_queued(p);
-	list_add_tail(&p->run_list, array->queue + p->prio);
-	__set_bit(p->prio, array->bitmap);
-	array->nr_active++;
-	p->array = array;
-}
-
-/*
- * Put task to the end of the run list without the overhead of dequeue
- * followed by enqueue.
- */
-static void requeue_task(struct task_struct *p, struct prio_array *array)
-{
-	list_move_tail(&p->run_list, array->queue + p->prio);
-}
-
-static inline void
-enqueue_task_head(struct task_struct *p, struct prio_array *array)
-{
-	list_add(&p->run_list, array->queue + p->prio);
-	__set_bit(p->prio, array->bitmap);
-	array->nr_active++;
-	p->array = array;
-}
-
-/*
- * __normal_prio - return the priority that is based on the static
- * priority but is modified by bonuses/penalties.
- *
- * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
- * into the -5 ... 0 ... +5 bonus/penalty range.
- *
- * We use 25% of the full 0...39 priority range so that:
- *
- * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
- * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
- *
- * Both properties are important to certain workloads.
- */
-
-static inline int __normal_prio(struct task_struct *p)
-{
-	int bonus, prio;
-
-	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
-
-	prio = p->static_prio - bonus;
-	if (prio < MAX_RT_PRIO)
-		prio = MAX_RT_PRIO;
-	if (prio > MAX_PRIO-1)
-		prio = MAX_PRIO-1;
-	return prio;
-}
-
-/*
- * To aid in avoiding the subversion of "niceness" due to uneven distribution
- * of tasks with abnormal "nice" values across CPUs the contribution that
- * each task makes to its run queue's load is weighted according to its
- * scheduling class and "nice" value.  For SCHED_NORMAL tasks this is just a
- * scaled version of the new time slice allocation that they receive on time
- * slice expiry etc.
- */
-
-/*
- * Assume: static_prio_timeslice(NICE_TO_PRIO(0)) == DEF_TIMESLICE
- * If static_prio_timeslice() is ever changed to break this assumption then
- * this code will need modification
- */
-#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
-#define LOAD_WEIGHT(lp) \
-	(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
-#define PRIO_TO_LOAD_WEIGHT(prio) \
-	LOAD_WEIGHT(static_prio_timeslice(prio))
-#define RTPRIO_TO_LOAD_WEIGHT(rp) \
-	(PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))
-
-static void set_load_weight(struct task_struct *p)
-{
-	if (has_rt_policy(p)) {
-#ifdef CONFIG_SMP
-		if (p == task_rq(p)->migration_thread)
-			/*
-			 * The migration thread does the actual balancing.
-			 * Giving its load any weight will skew balancing
-			 * adversely.
-			 */
-			p->load_weight = 0;
-		else
-#endif
-			p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
-	} else
-		p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
-}
-
-static inline void
-inc_raw_weighted_load(struct rq *rq, const struct task_struct *p)
-{
-	rq->raw_weighted_load += p->load_weight;
-}
-
-static inline void
-dec_raw_weighted_load(struct rq *rq, const struct task_struct *p)
-{
-	rq->raw_weighted_load -= p->load_weight;
-}
-
-static inline void inc_nr_running(struct task_struct *p, struct rq *rq)
-{
-	rq->nr_running++;
-	inc_raw_weighted_load(rq, p);
-}
-
-static inline void dec_nr_running(struct task_struct *p, struct rq *rq)
-{
-	rq->nr_running--;
-	dec_raw_weighted_load(rq, p);
-}
-
-/*
- * Calculate the expected normal priority: i.e. priority
- * without taking RT-inheritance into account. Might be
- * boosted by interactivity modifiers. Changes upon fork,
- * setprio syscalls, and whenever the interactivity
- * estimator recalculates.
- */
-static inline int normal_prio(struct task_struct *p)
-{
-	int prio;
-
-	if (has_rt_policy(p))
-		prio = MAX_RT_PRIO-1 - p->rt_priority;
-	else
-		prio = __normal_prio(p);
-	return prio;
-}
-
-/*
- * Calculate the current priority, i.e. the priority
- * taken into account by the scheduler. This value might
- * be boosted by RT tasks, or might be boosted by
- * interactivity modifiers. Will be RT if the task got
- * RT-boosted. If not then it returns p->normal_prio.
- */
-static int effective_prio(struct task_struct *p)
-{
-	p->normal_prio = normal_prio(p);
-	/*
-	 * If we are RT tasks or we were boosted to RT priority,
-	 * keep the priority unchanged. Otherwise, update priority
-	 * to the normal priority:
-	 */
-	if (!rt_prio(p->prio))
-		return p->normal_prio;
-	return p->prio;
-}
-
-/*
- * __activate_task - move a task to the runqueue.
- */
-static void __activate_task(struct task_struct *p, struct rq *rq)
-{
-	struct prio_array *target = rq->active;
-
-	if (batch_task(p))
-		target = rq->expired;
-	enqueue_task(p, target);
-	inc_nr_running(p, rq);
-}
-
-/*
- * __activate_idle_task - move idle task to the _front_ of runqueue.
- */
-static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
-{
-	enqueue_task_head(p, rq->active);
-	inc_nr_running(p, rq);
-}
-
-/*
- * Recalculate p->normal_prio and p->prio after having slept,
- * updating the sleep-average too:
- */
-static int recalc_task_prio(struct task_struct *p, unsigned long long now)
-{
-	/* Caller must always ensure 'now >= p->timestamp' */
-	unsigned long sleep_time = now - p->timestamp;
-
-	if (batch_task(p))
-		sleep_time = 0;
-
-	if (likely(sleep_time > 0)) {
-		/*
-		 * This ceiling is set to the lowest priority that would allow
-		 * a task to be reinserted into the active array on timeslice
-		 * completion.
-		 */
-		unsigned long ceiling = INTERACTIVE_SLEEP(p);
-
-		if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
-			/*
-			 * Prevents user tasks from achieving best priority
-			 * with one single large enough sleep.
-			 */
-			p->sleep_avg = ceiling;
-			/*
-			 * Using INTERACTIVE_SLEEP() as a ceiling places a
-			 * nice(0) task 1ms sleep away from promotion, and
-			 * gives it 700ms to round-robin with no chance of
-			 * being demoted.  This is more than generous, so
-			 * mark this sleep as non-interactive to prevent the
-			 * on-runqueue bonus logic from intervening should
-			 * this task not receive cpu immediately.
-			 */
-			p->sleep_type = SLEEP_NONINTERACTIVE;
-		} else {
-			/*
-			 * Tasks waking from uninterruptible sleep are
-			 * limited in their sleep_avg rise as they
-			 * are likely to be waiting on I/O
-			 */
-			if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
-				if (p->sleep_avg >= ceiling)
-					sleep_time = 0;
-				else if (p->sleep_avg + sleep_time >=
-					 ceiling) {
-						p->sleep_avg = ceiling;
-						sleep_time = 0;
-				}
-			}
-
-			/*
-			 * This code gives a bonus to interactive tasks.
-			 *
-			 * The boost works by updating the 'average sleep time'
-			 * value here, based on ->timestamp. The more time a
-			 * task spends sleeping, the higher the average gets -
-			 * and the higher the priority boost gets as well.
-			 */
-			p->sleep_avg += sleep_time;
-
-		}
-		if (p->sleep_avg > NS_MAX_SLEEP_AVG)
-			p->sleep_avg = NS_MAX_SLEEP_AVG;
-	}
-
-	return effective_prio(p);
-}
-
-/*
- * activate_task - move a task to the runqueue and do priority recalculation
- *
- * Update all the scheduling statistics stuff. (sleep average
- * calculation, priority modifiers, etc.)
- */
-static void activate_task(struct task_struct *p, struct rq *rq, int local)
-{
-	unsigned long long now;
-
-	if (rt_task(p))
-		goto out;
-
-	now = sched_clock();
-#ifdef CONFIG_SMP
-	if (!local) {
-		/* Compensate for drifting sched_clock */
-		struct rq *this_rq = this_rq();
-		now = (now - this_rq->most_recent_timestamp)
-			+ rq->most_recent_timestamp;
-	}
-#endif
-
-	/*
-	 * Sleep time is in units of nanosecs, so shift by 20 to get a
-	 * milliseconds-range estimation of the amount of time that the task
-	 * spent sleeping:
-	 */
-	if (unlikely(prof_on == SLEEP_PROFILING)) {
-		if (p->state == TASK_UNINTERRUPTIBLE)
-			profile_hits(SLEEP_PROFILING, (void *)get_wchan(p),
-				     (now - p->timestamp) >> 20);
-	}
-
-	p->prio = recalc_task_prio(p, now);
-
-	/*
-	 * This checks to make sure it's not an uninterruptible task
-	 * that is now waking up.
-	 */
-	if (p->sleep_type == SLEEP_NORMAL) {
-		/*
-		 * Tasks which were woken up by interrupts (ie. hw events)
-		 * are most likely of interactive nature. So we give them
-		 * the credit of extending their sleep time to the period
-		 * of time they spend on the runqueue, waiting for execution
-		 * on a CPU, first time around:
-		 */
-		if (in_interrupt())
-			p->sleep_type = SLEEP_INTERRUPTED;
-		else {
-			/*
-			 * Normal first-time wakeups get a credit too for
-			 * on-runqueue time, but it will be weighted down:
-			 */
-			p->sleep_type = SLEEP_INTERACTIVE;
-		}
-	}
-	p->timestamp = now;
-out:
-	__activate_task(p, rq);
-}
-
-/*
- * deactivate_task - remove a task from the runqueue.
- */
-static void deactivate_task(struct task_struct *p, struct rq *rq)
-{
-	dec_nr_running(p, rq);
-	dequeue_task(p, p->array);
-	p->array = NULL;
+	rq = task_rq_lock(current, &flags);
+	rq->prev_clock_raw = sched_clock();
+	rq->clock_unstable_events++;
+	task_rq_unlock(rq, &flags);
 }
 
 /*
@@ -1095,6 +601,354 @@
 }
 #endif
 
+static u64 div64_likely32(u64 divident, unsigned long divisor)
+{
+#if BITS_PER_LONG == 32
+	if (likely(divident <= 0xffffffffULL))
+		return (u32)divident / divisor;
+	do_div(divident, divisor);
+
+	return divident;
+#else
+	return divident / divisor;
+#endif
+}
+
+#if BITS_PER_LONG == 32
+# define WMULT_CONST	(~0UL)
+#else
+# define WMULT_CONST	(1UL << 32)
+#endif
+
+#define WMULT_SHIFT	32
+
+static inline unsigned long
+calc_delta_mine(unsigned long delta_exec, unsigned long weight,
+		struct load_weight *lw)
+{
+	u64 tmp;
+
+	if (unlikely(!lw->inv_weight))
+		lw->inv_weight = WMULT_CONST / lw->weight;
+
+	tmp = (u64)delta_exec * weight;
+	/*
+	 * Check whether we'd overflow the 64-bit multiplication:
+	 */
+	if (unlikely(tmp > WMULT_CONST)) {
+		tmp = ((tmp >> WMULT_SHIFT/2) * lw->inv_weight)
+				>> (WMULT_SHIFT/2);
+	} else {
+		tmp = (tmp * lw->inv_weight) >> WMULT_SHIFT;
+	}
+
+	return (unsigned long)min(tmp, (u64)sysctl_sched_runtime_limit);
+}
+
+static inline unsigned long
+calc_delta_fair(unsigned long delta_exec, struct load_weight *lw)
+{
+	return calc_delta_mine(delta_exec, NICE_0_LOAD, lw);
+}
+
+static void update_load_add(struct load_weight *lw, unsigned long inc)
+{
+	lw->weight += inc;
+	lw->inv_weight = 0;
+}
+
+static void update_load_sub(struct load_weight *lw, unsigned long dec)
+{
+	lw->weight -= dec;
+	lw->inv_weight = 0;
+}
+
+static void __update_curr_load(struct rq *rq, struct load_stat *ls)
+{
+	if (rq->curr != rq->idle && ls->load.weight) {
+		ls->delta_exec += ls->delta_stat;
+		ls->delta_fair += calc_delta_fair(ls->delta_stat, &ls->load);
+		ls->delta_stat = 0;
+	}
+}
+
+/*
+ * Update delta_exec, delta_fair fields for rq.
+ *
+ * delta_fair clock advances at a rate inversely proportional to
+ * total load (rq->ls.load.weight) on the runqueue, while
+ * delta_exec advances at the same rate as wall-clock (provided
+ * cpu is not idle).
+ *
+ * delta_exec / delta_fair is a measure of the (smoothened) load on this
+ * runqueue over any given interval. This (smoothened) load is used
+ * during load balance.
+ *
+ * This function is called /before/ updating rq->ls.load
+ * and when switching tasks.
+ */
+static void update_curr_load(struct rq *rq, u64 now)
+{
+	struct load_stat *ls = &rq->ls;
+	u64 start;
+
+	start = ls->load_update_start;
+	ls->load_update_start = now;
+	ls->delta_stat += now - start;
+	/*
+	 * Stagger updates to ls->delta_fair. Very frequent updates
+	 * can be expensive.
+	 */
+	if (ls->delta_stat >= sysctl_sched_stat_granularity)
+		__update_curr_load(rq, ls);
+}
+
+/*
+ * To aid in avoiding the subversion of "niceness" due to uneven distribution
+ * of tasks with abnormal "nice" values across CPUs the contribution that
+ * each task makes to its run queue's load is weighted according to its
+ * scheduling class and "nice" value.  For SCHED_NORMAL tasks this is just a
+ * scaled version of the new time slice allocation that they receive on time
+ * slice expiry etc.
+ */
+
+/*
+ * Assume: static_prio_timeslice(NICE_TO_PRIO(0)) == DEF_TIMESLICE
+ * If static_prio_timeslice() is ever changed to break this assumption then
+ * this code will need modification
+ */
+#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
+#define load_weight(lp) \
+	(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
+#define PRIO_TO_LOAD_WEIGHT(prio) \
+	load_weight(static_prio_timeslice(prio))
+#define RTPRIO_TO_LOAD_WEIGHT(rp) \
+	(PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + load_weight(rp))
+
+#define WEIGHT_IDLEPRIO		2
+#define WMULT_IDLEPRIO		(1 << 31)
+
+/*
+ * Nice levels are multiplicative, with a gentle 10% change for every
+ * nice level changed. I.e. when a CPU-bound task goes from nice 0 to
+ * nice 1, it will get ~10% less CPU time than another CPU-bound task
+ * that remained on nice 0.
+ *
+ * The "10% effect" is relative and cumulative: from _any_ nice level,
+ * if you go up 1 level, it's -10% CPU usage, if you go down 1 level
+ * it's +10% CPU usage. (to achieve that we use a multiplier of 1.25.
+ * If a task goes up by ~10% and another task goes down by ~10% then
+ * the relative distance between them is ~25%.)
+ */
+static const int prio_to_weight[40] = {
+/* -20 */ 88818, 71054, 56843, 45475, 36380, 29104, 23283, 18626, 14901, 11921,
+/* -10 */  9537,  7629,  6103,  4883,  3906,  3125,  2500,  2000,  1600,  1280,
+/*   0 */  NICE_0_LOAD /* 1024 */,
+/*   1 */          819,   655,   524,   419,   336,   268,   215,   172,   137,
+/*  10 */   110,    87,    70,    56,    45,    36,    29,    23,    18,    15,
+};
+
+/*
+ * Inverse (2^32/x) values of the prio_to_weight[] array, precalculated.
+ *
+ * In cases where the weight does not change often, we can use the
+ * precalculated inverse to speed up arithmetics by turning divisions
+ * into multiplications:
+ */
+static const u32 prio_to_wmult[40] = {
+/* -20 */     48356,     60446,     75558,     94446,    118058,
+/* -15 */    147573,    184467,    230589,    288233,    360285,
+/* -10 */    450347,    562979,    703746,    879575,   1099582,
+/*  -5 */   1374389,   1717986,   2147483,   2684354,   3355443,
+/*   0 */   4194304,   5244160,   6557201,   8196502,  10250518,
+/*   5 */  12782640,  16025997,  19976592,  24970740,  31350126,
+/*  10 */  39045157,  49367440,  61356675,  76695844,  95443717,
+/*  15 */ 119304647, 148102320, 186737708, 238609294, 286331153,
+};
+
+static inline void
+inc_load(struct rq *rq, const struct task_struct *p, u64 now)
+{
+	update_curr_load(rq, now);
+	update_load_add(&rq->ls.load, p->se.load.weight);
+}
+
+static inline void
+dec_load(struct rq *rq, const struct task_struct *p, u64 now)
+{
+	update_curr_load(rq, now);
+	update_load_sub(&rq->ls.load, p->se.load.weight);
+}
+
+static inline void inc_nr_running(struct task_struct *p, struct rq *rq, u64 now)
+{
+	rq->nr_running++;
+	inc_load(rq, p, now);
+}
+
+static inline void dec_nr_running(struct task_struct *p, struct rq *rq, u64 now)
+{
+	rq->nr_running--;
+	dec_load(rq, p, now);
+}
+
+static void activate_task(struct rq *rq, struct task_struct *p, int wakeup);
+
+/*
+ * runqueue iterator, to support SMP load-balancing between different
+ * scheduling classes, without having to expose their internal data
+ * structures to the load-balancing proper:
+ */
+struct rq_iterator {
+	void *arg;
+	struct task_struct *(*start)(void *);
+	struct task_struct *(*next)(void *);
+};
+
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+		      unsigned long max_nr_move, unsigned long max_load_move,
+		      struct sched_domain *sd, enum cpu_idle_type idle,
+		      int *all_pinned, unsigned long *load_moved,
+		      int this_best_prio, int best_prio, int best_prio_seen,
+		      struct rq_iterator *iterator);
+
+#include "sched_stats.h"
+#include "sched_rt.c"
+#include "sched_fair.c"
+#include "sched_idletask.c"
+#ifdef CONFIG_SCHED_DEBUG
+# include "sched_debug.c"
+#endif
+
+#define sched_class_highest (&rt_sched_class)
+
+static void set_load_weight(struct task_struct *p)
+{
+	task_rq(p)->cfs.wait_runtime -= p->se.wait_runtime;
+	p->se.wait_runtime = 0;
+
+	if (task_has_rt_policy(p)) {
+		p->se.load.weight = prio_to_weight[0] * 2;
+		p->se.load.inv_weight = prio_to_wmult[0] >> 1;
+		return;
+	}
+
+	/*
+	 * SCHED_IDLE tasks get minimal weight:
+	 */
+	if (p->policy == SCHED_IDLE) {
+		p->se.load.weight = WEIGHT_IDLEPRIO;
+		p->se.load.inv_weight = WMULT_IDLEPRIO;
+		return;
+	}
+
+	p->se.load.weight = prio_to_weight[p->static_prio - MAX_RT_PRIO];
+	p->se.load.inv_weight = prio_to_wmult[p->static_prio - MAX_RT_PRIO];
+}
+
+static void
+enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+	sched_info_queued(p);
+	p->sched_class->enqueue_task(rq, p, wakeup, now);
+	p->se.on_rq = 1;
+}
+
+static void
+dequeue_task(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+	p->sched_class->dequeue_task(rq, p, sleep, now);
+	p->se.on_rq = 0;
+}
+
+/*
+ * __normal_prio - return the priority that is based on the static prio
+ */
+static inline int __normal_prio(struct task_struct *p)
+{
+	return p->static_prio;
+}
+
+/*
+ * Calculate the expected normal priority: i.e. priority
+ * without taking RT-inheritance into account. Might be
+ * boosted by interactivity modifiers. Changes upon fork,
+ * setprio syscalls, and whenever the interactivity
+ * estimator recalculates.
+ */
+static inline int normal_prio(struct task_struct *p)
+{
+	int prio;
+
+	if (task_has_rt_policy(p))
+		prio = MAX_RT_PRIO-1 - p->rt_priority;
+	else
+		prio = __normal_prio(p);
+	return prio;
+}
+
+/*
+ * Calculate the current priority, i.e. the priority
+ * taken into account by the scheduler. This value might
+ * be boosted by RT tasks, or might be boosted by
+ * interactivity modifiers. Will be RT if the task got
+ * RT-boosted. If not then it returns p->normal_prio.
+ */
+static int effective_prio(struct task_struct *p)
+{
+	p->normal_prio = normal_prio(p);
+	/*
+	 * If we are RT tasks or we were boosted to RT priority,
+	 * keep the priority unchanged. Otherwise, update priority
+	 * to the normal priority:
+	 */
+	if (!rt_prio(p->prio))
+		return p->normal_prio;
+	return p->prio;
+}
+
+/*
+ * activate_task - move a task to the runqueue.
+ */
+static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
+{
+	u64 now = rq_clock(rq);
+
+	if (p->state == TASK_UNINTERRUPTIBLE)
+		rq->nr_uninterruptible--;
+
+	enqueue_task(rq, p, wakeup, now);
+	inc_nr_running(p, rq, now);
+}
+
+/*
+ * activate_idle_task - move idle task to the _front_ of runqueue.
+ */
+static inline void activate_idle_task(struct task_struct *p, struct rq *rq)
+{
+	u64 now = rq_clock(rq);
+
+	if (p->state == TASK_UNINTERRUPTIBLE)
+		rq->nr_uninterruptible--;
+
+	enqueue_task(rq, p, 0, now);
+	inc_nr_running(p, rq, now);
+}
+
+/*
+ * deactivate_task - remove a task from the runqueue.
+ */
+static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)
+{
+	u64 now = rq_clock(rq);
+
+	if (p->state == TASK_UNINTERRUPTIBLE)
+		rq->nr_uninterruptible++;
+
+	dequeue_task(rq, p, sleep, now);
+	dec_nr_running(p, rq, now);
+}
+
 /**
  * task_curr - is this task currently executing on a CPU?
  * @p: the task in question.
@@ -1107,10 +961,42 @@
 /* Used instead of source_load when we know the type == 0 */
 unsigned long weighted_cpuload(const int cpu)
 {
-	return cpu_rq(cpu)->raw_weighted_load;
+	return cpu_rq(cpu)->ls.load.weight;
+}
+
+static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
+{
+#ifdef CONFIG_SMP
+	task_thread_info(p)->cpu = cpu;
+	set_task_cfs_rq(p);
+#endif
 }
 
 #ifdef CONFIG_SMP
+
+void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
+{
+	int old_cpu = task_cpu(p);
+	struct rq *old_rq = cpu_rq(old_cpu), *new_rq = cpu_rq(new_cpu);
+	u64 clock_offset, fair_clock_offset;
+
+	clock_offset = old_rq->clock - new_rq->clock;
+	fair_clock_offset = old_rq->cfs.fair_clock -
+						 new_rq->cfs.fair_clock;
+	if (p->se.wait_start)
+		p->se.wait_start -= clock_offset;
+	if (p->se.wait_start_fair)
+		p->se.wait_start_fair -= fair_clock_offset;
+	if (p->se.sleep_start)
+		p->se.sleep_start -= clock_offset;
+	if (p->se.block_start)
+		p->se.block_start -= clock_offset;
+	if (p->se.sleep_start_fair)
+		p->se.sleep_start_fair -= fair_clock_offset;
+
+	__set_task_cpu(p, new_cpu);
+}
+
 struct migration_req {
 	struct list_head list;
 
@@ -1133,7 +1019,7 @@
 	 * If the task is not on a runqueue (and not running), then
 	 * it is sufficient to simply update the task's cpu field.
 	 */
-	if (!p->array && !task_running(rq, p)) {
+	if (!p->se.on_rq && !task_running(rq, p)) {
 		set_task_cpu(p, dest_cpu);
 		return 0;
 	}
@@ -1158,22 +1044,72 @@
 void wait_task_inactive(struct task_struct *p)
 {
 	unsigned long flags;
+	int running, on_rq;
 	struct rq *rq;
-	int preempted;
 
 repeat:
-	rq = task_rq_lock(p, &flags);
-	/* Must be off runqueue entirely, not preempted. */
-	if (unlikely(p->array || task_running(rq, p))) {
-		/* If it's preempted, we yield.  It could be a while. */
-		preempted = !task_running(rq, p);
-		task_rq_unlock(rq, &flags);
+	/*
+	 * We do the initial early heuristics without holding
+	 * any task-queue locks at all. We'll only try to get
+	 * the runqueue lock when things look like they will
+	 * work out!
+	 */
+	rq = task_rq(p);
+
+	/*
+	 * If the task is actively running on another CPU
+	 * still, just relax and busy-wait without holding
+	 * any locks.
+	 *
+	 * NOTE! Since we don't hold any locks, it's not
+	 * even sure that "rq" stays as the right runqueue!
+	 * But we don't care, since "task_running()" will
+	 * return false if the runqueue has changed and p
+	 * is actually now running somewhere else!
+	 */
+	while (task_running(rq, p))
 		cpu_relax();
-		if (preempted)
-			yield();
+
+	/*
+	 * Ok, time to look more closely! We need the rq
+	 * lock now, to be *sure*. If we're wrong, we'll
+	 * just go back and repeat.
+	 */
+	rq = task_rq_lock(p, &flags);
+	running = task_running(rq, p);
+	on_rq = p->se.on_rq;
+	task_rq_unlock(rq, &flags);
+
+	/*
+	 * Was it really running after all now that we
+	 * checked with the proper locks actually held?
+	 *
+	 * Oops. Go back and try again..
+	 */
+	if (unlikely(running)) {
+		cpu_relax();
 		goto repeat;
 	}
-	task_rq_unlock(rq, &flags);
+
+	/*
+	 * It's not enough that it's not actively running,
+	 * it must be off the runqueue _entirely_, and not
+	 * preempted!
+	 *
+	 * So if it wa still runnable (but just not actively
+	 * running right now), it's preempted, and we should
+	 * yield - it could be a while.
+	 */
+	if (unlikely(on_rq)) {
+		yield();
+		goto repeat;
+	}
+
+	/*
+	 * Ahh, all good. It wasn't running, and it wasn't
+	 * runnable, which means that it will never become
+	 * running in the future either. We're all done!
+	 */
 }
 
 /***
@@ -1210,11 +1146,12 @@
 static inline unsigned long source_load(int cpu, int type)
 {
 	struct rq *rq = cpu_rq(cpu);
+	unsigned long total = weighted_cpuload(cpu);
 
 	if (type == 0)
-		return rq->raw_weighted_load;
+		return total;
 
-	return min(rq->cpu_load[type-1], rq->raw_weighted_load);
+	return min(rq->cpu_load[type-1], total);
 }
 
 /*
@@ -1224,11 +1161,12 @@
 static inline unsigned long target_load(int cpu, int type)
 {
 	struct rq *rq = cpu_rq(cpu);
+	unsigned long total = weighted_cpuload(cpu);
 
 	if (type == 0)
-		return rq->raw_weighted_load;
+		return total;
 
-	return max(rq->cpu_load[type-1], rq->raw_weighted_load);
+	return max(rq->cpu_load[type-1], total);
 }
 
 /*
@@ -1237,9 +1175,10 @@
 static inline unsigned long cpu_avg_load_per_task(int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
+	unsigned long total = weighted_cpuload(cpu);
 	unsigned long n = rq->nr_running;
 
-	return n ? rq->raw_weighted_load / n : SCHED_LOAD_SCALE;
+	return n ? total / n : SCHED_LOAD_SCALE;
 }
 
 /*
@@ -1341,9 +1280,9 @@
 	struct sched_domain *tmp, *sd = NULL;
 
 	for_each_domain(cpu, tmp) {
- 		/*
- 	 	 * If power savings logic is enabled for a domain, stop there.
- 	 	 */
+		/*
+		 * If power savings logic is enabled for a domain, stop there.
+		 */
 		if (tmp->flags & SD_POWERSAVINGS_BALANCE)
 			break;
 		if (tmp->flags & flag)
@@ -1426,9 +1365,9 @@
 				if (idle_cpu(i))
 					return i;
 			}
-		}
-		else
+		} else {
 			break;
+		}
 	}
 	return cpu;
 }
@@ -1470,7 +1409,7 @@
 	if (!(old_state & state))
 		goto out;
 
-	if (p->array)
+	if (p->se.on_rq)
 		goto out_running;
 
 	cpu = task_cpu(p);
@@ -1525,11 +1464,11 @@
 			 * of the current CPU:
 			 */
 			if (sync)
-				tl -= current->load_weight;
+				tl -= current->se.load.weight;
 
 			if ((tl <= load &&
 				tl + target_load(cpu, idx) <= tl_per_task) ||
-				100*(tl + p->load_weight) <= imbalance*load) {
+			       100*(tl + p->se.load.weight) <= imbalance*load) {
 				/*
 				 * This domain has SD_WAKE_AFFINE and
 				 * p is cache cold in this domain, and
@@ -1563,7 +1502,7 @@
 		old_state = p->state;
 		if (!(old_state & state))
 			goto out;
-		if (p->array)
+		if (p->se.on_rq)
 			goto out_running;
 
 		this_cpu = smp_processor_id();
@@ -1572,25 +1511,7 @@
 
 out_activate:
 #endif /* CONFIG_SMP */
-	if (old_state == TASK_UNINTERRUPTIBLE) {
-		rq->nr_uninterruptible--;
-		/*
-		 * Tasks on involuntary sleep don't earn
-		 * sleep_avg beyond just interactive state.
-		 */
-		p->sleep_type = SLEEP_NONINTERACTIVE;
-	} else
-
-	/*
-	 * Tasks that have marked their sleep as noninteractive get
-	 * woken up with their sleep average not weighted in an
-	 * interactive way.
-	 */
-		if (old_state & TASK_NONINTERACTIVE)
-			p->sleep_type = SLEEP_NONINTERACTIVE;
-
-
-	activate_task(p, rq, cpu == this_cpu);
+	activate_task(rq, p, 1);
 	/*
 	 * Sync wakeups (i.e. those types of wakeups where the waker
 	 * has indicated that it will leave the CPU in short order)
@@ -1599,10 +1520,8 @@
 	 * the waker guarantees that the freshly woken up task is going
 	 * to be considered on this CPU.)
 	 */
-	if (!sync || cpu != this_cpu) {
-		if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
-	}
+	if (!sync || cpu != this_cpu)
+		check_preempt_curr(rq, p);
 	success = 1;
 
 out_running:
@@ -1625,19 +1544,36 @@
 	return try_to_wake_up(p, state, 0);
 }
 
-static void task_running_tick(struct rq *rq, struct task_struct *p);
 /*
  * Perform scheduler related setup for a newly forked process p.
  * p is forked by current.
+ *
+ * __sched_fork() is basic setup used by init_idle() too:
  */
-void fastcall sched_fork(struct task_struct *p, int clone_flags)
+static void __sched_fork(struct task_struct *p)
 {
-	int cpu = get_cpu();
+	p->se.wait_start_fair		= 0;
+	p->se.wait_start		= 0;
+	p->se.exec_start		= 0;
+	p->se.sum_exec_runtime		= 0;
+	p->se.delta_exec		= 0;
+	p->se.delta_fair_run		= 0;
+	p->se.delta_fair_sleep		= 0;
+	p->se.wait_runtime		= 0;
+	p->se.sum_wait_runtime		= 0;
+	p->se.sum_sleep_runtime		= 0;
+	p->se.sleep_start		= 0;
+	p->se.sleep_start_fair		= 0;
+	p->se.block_start		= 0;
+	p->se.sleep_max			= 0;
+	p->se.block_max			= 0;
+	p->se.exec_max			= 0;
+	p->se.wait_max			= 0;
+	p->se.wait_runtime_overruns	= 0;
+	p->se.wait_runtime_underruns	= 0;
 
-#ifdef CONFIG_SMP
-	cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
-#endif
-	set_task_cpu(p, cpu);
+	INIT_LIST_HEAD(&p->run_list);
+	p->se.on_rq = 0;
 
 	/*
 	 * We mark the process as running here, but have not actually
@@ -1646,16 +1582,29 @@
 	 * event cannot wake it up and insert it on the runqueue either.
 	 */
 	p->state = TASK_RUNNING;
+}
+
+/*
+ * fork()/clone()-time setup:
+ */
+void sched_fork(struct task_struct *p, int clone_flags)
+{
+	int cpu = get_cpu();
+
+	__sched_fork(p);
+
+#ifdef CONFIG_SMP
+	cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
+#endif
+	__set_task_cpu(p, cpu);
 
 	/*
 	 * Make sure we do not leak PI boosting priority to the child:
 	 */
 	p->prio = current->normal_prio;
 
-	INIT_LIST_HEAD(&p->run_list);
-	p->array = NULL;
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
-	if (unlikely(sched_info_on()))
+	if (likely(sched_info_on()))
 		memset(&p->sched_info, 0, sizeof(p->sched_info));
 #endif
 #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
@@ -1665,34 +1614,16 @@
 	/* Want to start with kernel preemption disabled. */
 	task_thread_info(p)->preempt_count = 1;
 #endif
-	/*
-	 * Share the timeslice between parent and child, thus the
-	 * total amount of pending timeslices in the system doesn't change,
-	 * resulting in more scheduling fairness.
-	 */
-	local_irq_disable();
-	p->time_slice = (current->time_slice + 1) >> 1;
-	/*
-	 * The remainder of the first timeslice might be recovered by
-	 * the parent if the child exits early enough.
-	 */
-	p->first_time_slice = 1;
-	current->time_slice >>= 1;
-	p->timestamp = sched_clock();
-	if (unlikely(!current->time_slice)) {
-		/*
-		 * This case is rare, it happens when the parent has only
-		 * a single jiffy left from its timeslice. Taking the
-		 * runqueue lock is not a problem.
-		 */
-		current->time_slice = 1;
-		task_running_tick(cpu_rq(cpu), current);
-	}
-	local_irq_enable();
 	put_cpu();
 }
 
 /*
+ * After fork, child runs first. (default) If set to 0 then
+ * parent will (try to) run first.
+ */
+unsigned int __read_mostly sysctl_sched_child_runs_first = 1;
+
+/*
  * wake_up_new_task - wake up a newly created task for the first time.
  *
  * This function will do some initial scheduler statistics housekeeping
@@ -1701,107 +1632,27 @@
  */
 void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
 {
-	struct rq *rq, *this_rq;
 	unsigned long flags;
-	int this_cpu, cpu;
+	struct rq *rq;
+	int this_cpu;
 
 	rq = task_rq_lock(p, &flags);
 	BUG_ON(p->state != TASK_RUNNING);
-	this_cpu = smp_processor_id();
-	cpu = task_cpu(p);
-
-	/*
-	 * We decrease the sleep average of forking parents
-	 * and children as well, to keep max-interactive tasks
-	 * from forking tasks that are max-interactive. The parent
-	 * (current) is done further down, under its lock.
-	 */
-	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
-		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
+	this_cpu = smp_processor_id(); /* parent's CPU */
 
 	p->prio = effective_prio(p);
 
-	if (likely(cpu == this_cpu)) {
-		if (!(clone_flags & CLONE_VM)) {
-			/*
-			 * The VM isn't cloned, so we're in a good position to
-			 * do child-runs-first in anticipation of an exec. This
-			 * usually avoids a lot of COW overhead.
-			 */
-			if (unlikely(!current->array))
-				__activate_task(p, rq);
-			else {
-				p->prio = current->prio;
-				p->normal_prio = current->normal_prio;
-				list_add_tail(&p->run_list, &current->run_list);
-				p->array = current->array;
-				p->array->nr_active++;
-				inc_nr_running(p, rq);
-			}
-			set_need_resched();
-		} else
-			/* Run child last */
-			__activate_task(p, rq);
-		/*
-		 * We skip the following code due to cpu == this_cpu
-	 	 *
-		 *   task_rq_unlock(rq, &flags);
-		 *   this_rq = task_rq_lock(current, &flags);
-		 */
-		this_rq = rq;
+	if (!sysctl_sched_child_runs_first || (clone_flags & CLONE_VM) ||
+			task_cpu(p) != this_cpu || !current->se.on_rq) {
+		activate_task(rq, p, 0);
 	} else {
-		this_rq = cpu_rq(this_cpu);
-
 		/*
-		 * Not the local CPU - must adjust timestamp. This should
-		 * get optimised away in the !CONFIG_SMP case.
+		 * Let the scheduling class do new task startup
+		 * management (if any):
 		 */
-		p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
-					+ rq->most_recent_timestamp;
-		__activate_task(p, rq);
-		if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
-
-		/*
-		 * Parent and child are on different CPUs, now get the
-		 * parent runqueue to update the parent's ->sleep_avg:
-		 */
-		task_rq_unlock(rq, &flags);
-		this_rq = task_rq_lock(current, &flags);
+		p->sched_class->task_new(rq, p);
 	}
-	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
-		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
-	task_rq_unlock(this_rq, &flags);
-}
-
-/*
- * Potentially available exiting-child timeslices are
- * retrieved here - this way the parent does not get
- * penalized for creating too many threads.
- *
- * (this cannot be used to 'generate' timeslices
- * artificially, because any timeslice recovered here
- * was given away by the parent in the first place.)
- */
-void fastcall sched_exit(struct task_struct *p)
-{
-	unsigned long flags;
-	struct rq *rq;
-
-	/*
-	 * If the child was a (relative-) CPU hog then decrease
-	 * the sleep_avg of the parent as well.
-	 */
-	rq = task_rq_lock(p->parent, &flags);
-	if (p->first_time_slice && task_cpu(p) == task_cpu(p->parent)) {
-		p->parent->time_slice += p->time_slice;
-		if (unlikely(p->parent->time_slice > task_timeslice(p)))
-			p->parent->time_slice = task_timeslice(p);
-	}
-	if (p->sleep_avg < p->parent->sleep_avg)
-		p->parent->sleep_avg = p->parent->sleep_avg /
-		(EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
-		(EXIT_WEIGHT + 1);
+	check_preempt_curr(rq, p);
 	task_rq_unlock(rq, &flags);
 }
 
@@ -1866,7 +1717,7 @@
 		/*
 		 * Remove function-return probe instances associated with this
 		 * task and put them back on the free list.
-	 	 */
+		 */
 		kprobe_flush_task(prev);
 		put_task_struct(prev);
 	}
@@ -1894,13 +1745,15 @@
  * context_switch - switch to the new MM and the new
  * thread's register state.
  */
-static inline struct task_struct *
+static inline void
 context_switch(struct rq *rq, struct task_struct *prev,
 	       struct task_struct *next)
 {
-	struct mm_struct *mm = next->mm;
-	struct mm_struct *oldmm = prev->active_mm;
+	struct mm_struct *mm, *oldmm;
 
+	prepare_task_switch(rq, next);
+	mm = next->mm;
+	oldmm = prev->active_mm;
 	/*
 	 * For paravirt, this is coupled with an exit in switch_to to
 	 * combine the page table reload and the switch backend into
@@ -1908,16 +1761,15 @@
 	 */
 	arch_enter_lazy_cpu_mode();
 
-	if (!mm) {
+	if (unlikely(!mm)) {
 		next->active_mm = oldmm;
 		atomic_inc(&oldmm->mm_count);
 		enter_lazy_tlb(oldmm, next);
 	} else
 		switch_mm(oldmm, mm, next);
 
-	if (!prev->mm) {
+	if (unlikely(!prev->mm)) {
 		prev->active_mm = NULL;
-		WARN_ON(rq->prev_mm);
 		rq->prev_mm = oldmm;
 	}
 	/*
@@ -1933,7 +1785,13 @@
 	/* Here we just switch the register state and the stack. */
 	switch_to(prev, next, prev);
 
-	return prev;
+	barrier();
+	/*
+	 * this_rq must be evaluated again because prev may have moved
+	 * CPUs since it called schedule(), thus the 'rq' on its stack
+	 * frame will be invalid.
+	 */
+	finish_task_switch(this_rq(), prev);
 }
 
 /*
@@ -2006,17 +1864,65 @@
 	return running + uninterruptible;
 }
 
-#ifdef CONFIG_SMP
-
 /*
- * Is this task likely cache-hot:
+ * Update rq->cpu_load[] statistics. This function is usually called every
+ * scheduler tick (TICK_NSEC).
  */
-static inline int
-task_hot(struct task_struct *p, unsigned long long now, struct sched_domain *sd)
+static void update_cpu_load(struct rq *this_rq)
 {
-	return (long long)(now - p->last_ran) < (long long)sd->cache_hot_time;
+	u64 fair_delta64, exec_delta64, idle_delta64, sample_interval64, tmp64;
+	unsigned long total_load = this_rq->ls.load.weight;
+	unsigned long this_load =  total_load;
+	struct load_stat *ls = &this_rq->ls;
+	u64 now = __rq_clock(this_rq);
+	int i, scale;
+
+	this_rq->nr_load_updates++;
+	if (unlikely(!(sysctl_sched_features & SCHED_FEAT_PRECISE_CPU_LOAD)))
+		goto do_avg;
+
+	/* Update delta_fair/delta_exec fields first */
+	update_curr_load(this_rq, now);
+
+	fair_delta64 = ls->delta_fair + 1;
+	ls->delta_fair = 0;
+
+	exec_delta64 = ls->delta_exec + 1;
+	ls->delta_exec = 0;
+
+	sample_interval64 = now - ls->load_update_last;
+	ls->load_update_last = now;
+
+	if ((s64)sample_interval64 < (s64)TICK_NSEC)
+		sample_interval64 = TICK_NSEC;
+
+	if (exec_delta64 > sample_interval64)
+		exec_delta64 = sample_interval64;
+
+	idle_delta64 = sample_interval64 - exec_delta64;
+
+	tmp64 = div64_64(SCHED_LOAD_SCALE * exec_delta64, fair_delta64);
+	tmp64 = div64_64(tmp64 * exec_delta64, sample_interval64);
+
+	this_load = (unsigned long)tmp64;
+
+do_avg:
+
+	/* Update our load: */
+	for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
+		unsigned long old_load, new_load;
+
+		/* scale is effectively 1 << i now, and >> i divides by scale */
+
+		old_load = this_rq->cpu_load[i];
+		new_load = this_load;
+
+		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
+	}
 }
 
+#ifdef CONFIG_SMP
+
 /*
  * double_rq_lock - safely lock two runqueues
  *
@@ -2133,23 +2039,17 @@
  * pull_task - move a task from a remote runqueue to the local runqueue.
  * Both runqueues must be locked.
  */
-static void pull_task(struct rq *src_rq, struct prio_array *src_array,
-		      struct task_struct *p, struct rq *this_rq,
-		      struct prio_array *this_array, int this_cpu)
+static void pull_task(struct rq *src_rq, struct task_struct *p,
+		      struct rq *this_rq, int this_cpu)
 {
-	dequeue_task(p, src_array);
-	dec_nr_running(p, src_rq);
+	deactivate_task(src_rq, p, 0);
 	set_task_cpu(p, this_cpu);
-	inc_nr_running(p, this_rq);
-	enqueue_task(p, this_array);
-	p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
-				+ this_rq->most_recent_timestamp;
+	activate_task(this_rq, p, 0);
 	/*
 	 * Note that idle threads have a prio of MAX_PRIO, for this test
 	 * to be always true for them.
 	 */
-	if (TASK_PREEMPTS_CURR(p, this_rq))
-		resched_task(this_rq->curr);
+	check_preempt_curr(this_rq, p);
 }
 
 /*
@@ -2157,7 +2057,7 @@
  */
 static
 int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
-		     struct sched_domain *sd, enum idle_type idle,
+		     struct sched_domain *sd, enum cpu_idle_type idle,
 		     int *all_pinned)
 {
 	/*
@@ -2174,132 +2074,67 @@
 		return 0;
 
 	/*
-	 * Aggressive migration if:
-	 * 1) task is cache cold, or
-	 * 2) too many balance attempts have failed.
+	 * Aggressive migration if too many balance attempts have failed:
 	 */
-
-	if (sd->nr_balance_failed > sd->cache_nice_tries) {
-#ifdef CONFIG_SCHEDSTATS
-		if (task_hot(p, rq->most_recent_timestamp, sd))
-			schedstat_inc(sd, lb_hot_gained[idle]);
-#endif
+	if (sd->nr_balance_failed > sd->cache_nice_tries)
 		return 1;
-	}
 
-	if (task_hot(p, rq->most_recent_timestamp, sd))
-		return 0;
 	return 1;
 }
 
-#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio)
-
-/*
- * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
- * load from busiest to this_rq, as part of a balancing operation within
- * "domain". Returns the number of tasks moved.
- *
- * Called with both runqueues locked.
- */
-static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
 		      unsigned long max_nr_move, unsigned long max_load_move,
-		      struct sched_domain *sd, enum idle_type idle,
-		      int *all_pinned)
+		      struct sched_domain *sd, enum cpu_idle_type idle,
+		      int *all_pinned, unsigned long *load_moved,
+		      int this_best_prio, int best_prio, int best_prio_seen,
+		      struct rq_iterator *iterator)
 {
-	int idx, pulled = 0, pinned = 0, this_best_prio, best_prio,
-	    best_prio_seen, skip_for_load;
-	struct prio_array *array, *dst_array;
-	struct list_head *head, *curr;
-	struct task_struct *tmp;
-	long rem_load_move;
+	int pulled = 0, pinned = 0, skip_for_load;
+	struct task_struct *p;
+	long rem_load_move = max_load_move;
 
 	if (max_nr_move == 0 || max_load_move == 0)
 		goto out;
 
-	rem_load_move = max_load_move;
 	pinned = 1;
-	this_best_prio = rq_best_prio(this_rq);
-	best_prio = rq_best_prio(busiest);
-	/*
-	 * Enable handling of the case where there is more than one task
-	 * with the best priority.   If the current running task is one
-	 * of those with prio==best_prio we know it won't be moved
-	 * and therefore it's safe to override the skip (based on load) of
-	 * any task we find with that prio.
-	 */
-	best_prio_seen = best_prio == busiest->curr->prio;
 
 	/*
-	 * We first consider expired tasks. Those will likely not be
-	 * executed in the near future, and they are most likely to
-	 * be cache-cold, thus switching CPUs has the least effect
-	 * on them.
+	 * Start the load-balancing iterator:
 	 */
-	if (busiest->expired->nr_active) {
-		array = busiest->expired;
-		dst_array = this_rq->expired;
-	} else {
-		array = busiest->active;
-		dst_array = this_rq->active;
-	}
-
-new_array:
-	/* Start searching at priority 0: */
-	idx = 0;
-skip_bitmap:
-	if (!idx)
-		idx = sched_find_first_bit(array->bitmap);
-	else
-		idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
-	if (idx >= MAX_PRIO) {
-		if (array == busiest->expired && busiest->active->nr_active) {
-			array = busiest->active;
-			dst_array = this_rq->active;
-			goto new_array;
-		}
+	p = iterator->start(iterator->arg);
+next:
+	if (!p)
 		goto out;
-	}
-
-	head = array->queue + idx;
-	curr = head->prev;
-skip_queue:
-	tmp = list_entry(curr, struct task_struct, run_list);
-
-	curr = curr->prev;
-
 	/*
 	 * To help distribute high priority tasks accross CPUs we don't
 	 * skip a task if it will be the highest priority task (i.e. smallest
 	 * prio value) on its new queue regardless of its load weight
 	 */
-	skip_for_load = tmp->load_weight > rem_load_move;
-	if (skip_for_load && idx < this_best_prio)
-		skip_for_load = !best_prio_seen && idx == best_prio;
+	skip_for_load = (p->se.load.weight >> 1) > rem_load_move +
+							 SCHED_LOAD_SCALE_FUZZ;
+	if (skip_for_load && p->prio < this_best_prio)
+		skip_for_load = !best_prio_seen && p->prio == best_prio;
 	if (skip_for_load ||
-	    !can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
+	    !can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned)) {
 
-		best_prio_seen |= idx == best_prio;
-		if (curr != head)
-			goto skip_queue;
-		idx++;
-		goto skip_bitmap;
+		best_prio_seen |= p->prio == best_prio;
+		p = iterator->next(iterator->arg);
+		goto next;
 	}
 
-	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
+	pull_task(busiest, p, this_rq, this_cpu);
 	pulled++;
-	rem_load_move -= tmp->load_weight;
+	rem_load_move -= p->se.load.weight;
 
 	/*
 	 * We only want to steal up to the prescribed number of tasks
 	 * and the prescribed amount of weighted load.
 	 */
 	if (pulled < max_nr_move && rem_load_move > 0) {
-		if (idx < this_best_prio)
-			this_best_prio = idx;
-		if (curr != head)
-			goto skip_queue;
-		idx++;
-		goto skip_bitmap;
+		if (p->prio < this_best_prio)
+			this_best_prio = p->prio;
+		p = iterator->next(iterator->arg);
+		goto next;
 	}
 out:
 	/*
@@ -2311,18 +2146,48 @@
 
 	if (all_pinned)
 		*all_pinned = pinned;
+	*load_moved = max_load_move - rem_load_move;
 	return pulled;
 }
 
 /*
+ * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
+ * load from busiest to this_rq, as part of a balancing operation within
+ * "domain". Returns the number of tasks moved.
+ *
+ * Called with both runqueues locked.
+ */
+static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+		      unsigned long max_nr_move, unsigned long max_load_move,
+		      struct sched_domain *sd, enum cpu_idle_type idle,
+		      int *all_pinned)
+{
+	struct sched_class *class = sched_class_highest;
+	unsigned long load_moved, total_nr_moved = 0, nr_moved;
+	long rem_load_move = max_load_move;
+
+	do {
+		nr_moved = class->load_balance(this_rq, this_cpu, busiest,
+				max_nr_move, (unsigned long)rem_load_move,
+				sd, idle, all_pinned, &load_moved);
+		total_nr_moved += nr_moved;
+		max_nr_move -= nr_moved;
+		rem_load_move -= load_moved;
+		class = class->next;
+	} while (class && max_nr_move && rem_load_move > 0);
+
+	return total_nr_moved;
+}
+
+/*
  * find_busiest_group finds and returns the busiest CPU group within the
  * domain. It calculates and returns the amount of weighted load which
  * should be moved to restore balance via the imbalance parameter.
  */
 static struct sched_group *
 find_busiest_group(struct sched_domain *sd, int this_cpu,
-		   unsigned long *imbalance, enum idle_type idle, int *sd_idle,
-		   cpumask_t *cpus, int *balance)
+		   unsigned long *imbalance, enum cpu_idle_type idle,
+		   int *sd_idle, cpumask_t *cpus, int *balance)
 {
 	struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
 	unsigned long max_load, avg_load, total_load, this_load, total_pwr;
@@ -2340,9 +2205,9 @@
 	max_load = this_load = total_load = total_pwr = 0;
 	busiest_load_per_task = busiest_nr_running = 0;
 	this_load_per_task = this_nr_running = 0;
-	if (idle == NOT_IDLE)
+	if (idle == CPU_NOT_IDLE)
 		load_idx = sd->busy_idx;
-	else if (idle == NEWLY_IDLE)
+	else if (idle == CPU_NEWLY_IDLE)
 		load_idx = sd->newidle_idx;
 	else
 		load_idx = sd->idle_idx;
@@ -2386,7 +2251,7 @@
 
 			avg_load += load;
 			sum_nr_running += rq->nr_running;
-			sum_weighted_load += rq->raw_weighted_load;
+			sum_weighted_load += weighted_cpuload(i);
 		}
 
 		/*
@@ -2426,8 +2291,9 @@
 		 * Busy processors will not participate in power savings
 		 * balance.
 		 */
- 		if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
- 			goto group_next;
+		if (idle == CPU_NOT_IDLE ||
+				!(sd->flags & SD_POWERSAVINGS_BALANCE))
+			goto group_next;
 
 		/*
 		 * If the local group is idle or completely loaded
@@ -2437,42 +2303,42 @@
 				    !this_nr_running))
 			power_savings_balance = 0;
 
- 		/*
+		/*
 		 * If a group is already running at full capacity or idle,
 		 * don't include that group in power savings calculations
- 		 */
- 		if (!power_savings_balance || sum_nr_running >= group_capacity
+		 */
+		if (!power_savings_balance || sum_nr_running >= group_capacity
 		    || !sum_nr_running)
- 			goto group_next;
+			goto group_next;
 
- 		/*
+		/*
 		 * Calculate the group which has the least non-idle load.
- 		 * This is the group from where we need to pick up the load
- 		 * for saving power
- 		 */
- 		if ((sum_nr_running < min_nr_running) ||
- 		    (sum_nr_running == min_nr_running &&
+		 * This is the group from where we need to pick up the load
+		 * for saving power
+		 */
+		if ((sum_nr_running < min_nr_running) ||
+		    (sum_nr_running == min_nr_running &&
 		     first_cpu(group->cpumask) <
 		     first_cpu(group_min->cpumask))) {
- 			group_min = group;
- 			min_nr_running = sum_nr_running;
+			group_min = group;
+			min_nr_running = sum_nr_running;
 			min_load_per_task = sum_weighted_load /
 						sum_nr_running;
- 		}
+		}
 
- 		/*
+		/*
 		 * Calculate the group which is almost near its
- 		 * capacity but still has some space to pick up some load
- 		 * from other group and save more power
- 		 */
- 		if (sum_nr_running <= group_capacity - 1) {
- 			if (sum_nr_running > leader_nr_running ||
- 			    (sum_nr_running == leader_nr_running &&
- 			     first_cpu(group->cpumask) >
- 			      first_cpu(group_leader->cpumask))) {
- 				group_leader = group;
- 				leader_nr_running = sum_nr_running;
- 			}
+		 * capacity but still has some space to pick up some load
+		 * from other group and save more power
+		 */
+		if (sum_nr_running <= group_capacity - 1) {
+			if (sum_nr_running > leader_nr_running ||
+			    (sum_nr_running == leader_nr_running &&
+			     first_cpu(group->cpumask) >
+			      first_cpu(group_leader->cpumask))) {
+				group_leader = group;
+				leader_nr_running = sum_nr_running;
+			}
 		}
 group_next:
 #endif
@@ -2527,7 +2393,7 @@
 	 * a think about bumping its value to force at least one task to be
 	 * moved
 	 */
-	if (*imbalance < busiest_load_per_task) {
+	if (*imbalance + SCHED_LOAD_SCALE_FUZZ < busiest_load_per_task/2) {
 		unsigned long tmp, pwr_now, pwr_move;
 		unsigned int imbn;
 
@@ -2541,7 +2407,8 @@
 		} else
 			this_load_per_task = SCHED_LOAD_SCALE;
 
-		if (max_load - this_load >= busiest_load_per_task * imbn) {
+		if (max_load - this_load + SCHED_LOAD_SCALE_FUZZ >=
+					busiest_load_per_task * imbn) {
 			*imbalance = busiest_load_per_task;
 			return busiest;
 		}
@@ -2588,7 +2455,7 @@
 
 out_balanced:
 #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
-	if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
+	if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
 		goto ret;
 
 	if (this == group_leader && group_leader != group_min) {
@@ -2605,7 +2472,7 @@
  * find_busiest_queue - find the busiest runqueue among the cpus in group.
  */
 static struct rq *
-find_busiest_queue(struct sched_group *group, enum idle_type idle,
+find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
 		   unsigned long imbalance, cpumask_t *cpus)
 {
 	struct rq *busiest = NULL, *rq;
@@ -2613,17 +2480,19 @@
 	int i;
 
 	for_each_cpu_mask(i, group->cpumask) {
+		unsigned long wl;
 
 		if (!cpu_isset(i, *cpus))
 			continue;
 
 		rq = cpu_rq(i);
+		wl = weighted_cpuload(i);
 
-		if (rq->nr_running == 1 && rq->raw_weighted_load > imbalance)
+		if (rq->nr_running == 1 && wl > imbalance)
 			continue;
 
-		if (rq->raw_weighted_load > max_load) {
-			max_load = rq->raw_weighted_load;
+		if (wl > max_load) {
+			max_load = wl;
 			busiest = rq;
 		}
 	}
@@ -2647,7 +2516,7 @@
  * tasks if there is an imbalance.
  */
 static int load_balance(int this_cpu, struct rq *this_rq,
-			struct sched_domain *sd, enum idle_type idle,
+			struct sched_domain *sd, enum cpu_idle_type idle,
 			int *balance)
 {
 	int nr_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
@@ -2660,10 +2529,10 @@
 	/*
 	 * When power savings policy is enabled for the parent domain, idle
 	 * sibling can pick up load irrespective of busy siblings. In this case,
-	 * let the state of idle sibling percolate up as IDLE, instead of
-	 * portraying it as NOT_IDLE.
+	 * let the state of idle sibling percolate up as CPU_IDLE, instead of
+	 * portraying it as CPU_NOT_IDLE.
 	 */
-	if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
+	if (idle != CPU_NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
 	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
 		sd_idle = 1;
 
@@ -2797,7 +2666,7 @@
  * Check this_cpu to ensure it is balanced within domain. Attempt to move
  * tasks if there is an imbalance.
  *
- * Called from schedule when this_rq is about to become idle (NEWLY_IDLE).
+ * Called from schedule when this_rq is about to become idle (CPU_NEWLY_IDLE).
  * this_rq is locked.
  */
 static int
@@ -2814,31 +2683,31 @@
 	 * When power savings policy is enabled for the parent domain, idle
 	 * sibling can pick up load irrespective of busy siblings. In this case,
 	 * let the state of idle sibling percolate up as IDLE, instead of
-	 * portraying it as NOT_IDLE.
+	 * portraying it as CPU_NOT_IDLE.
 	 */
 	if (sd->flags & SD_SHARE_CPUPOWER &&
 	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
 		sd_idle = 1;
 
-	schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
+	schedstat_inc(sd, lb_cnt[CPU_NEWLY_IDLE]);
 redo:
-	group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE,
+	group = find_busiest_group(sd, this_cpu, &imbalance, CPU_NEWLY_IDLE,
 				   &sd_idle, &cpus, NULL);
 	if (!group) {
-		schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
+		schedstat_inc(sd, lb_nobusyg[CPU_NEWLY_IDLE]);
 		goto out_balanced;
 	}
 
-	busiest = find_busiest_queue(group, NEWLY_IDLE, imbalance,
+	busiest = find_busiest_queue(group, CPU_NEWLY_IDLE, imbalance,
 				&cpus);
 	if (!busiest) {
-		schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
+		schedstat_inc(sd, lb_nobusyq[CPU_NEWLY_IDLE]);
 		goto out_balanced;
 	}
 
 	BUG_ON(busiest == this_rq);
 
-	schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
+	schedstat_add(sd, lb_imbalance[CPU_NEWLY_IDLE], imbalance);
 
 	nr_moved = 0;
 	if (busiest->nr_running > 1) {
@@ -2846,7 +2715,7 @@
 		double_lock_balance(this_rq, busiest);
 		nr_moved = move_tasks(this_rq, this_cpu, busiest,
 					minus_1_or_zero(busiest->nr_running),
-					imbalance, sd, NEWLY_IDLE, NULL);
+					imbalance, sd, CPU_NEWLY_IDLE, NULL);
 		spin_unlock(&busiest->lock);
 
 		if (!nr_moved) {
@@ -2857,7 +2726,7 @@
 	}
 
 	if (!nr_moved) {
-		schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
+		schedstat_inc(sd, lb_failed[CPU_NEWLY_IDLE]);
 		if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
 		    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
 			return -1;
@@ -2867,7 +2736,7 @@
 	return nr_moved;
 
 out_balanced:
-	schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+	schedstat_inc(sd, lb_balanced[CPU_NEWLY_IDLE]);
 	if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
 	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
 		return -1;
@@ -2883,28 +2752,33 @@
 static void idle_balance(int this_cpu, struct rq *this_rq)
 {
 	struct sched_domain *sd;
-	int pulled_task = 0;
-	unsigned long next_balance = jiffies + 60 *  HZ;
+	int pulled_task = -1;
+	unsigned long next_balance = jiffies + HZ;
 
 	for_each_domain(this_cpu, sd) {
-		if (sd->flags & SD_BALANCE_NEWIDLE) {
+		unsigned long interval;
+
+		if (!(sd->flags & SD_LOAD_BALANCE))
+			continue;
+
+		if (sd->flags & SD_BALANCE_NEWIDLE)
 			/* If we've pulled tasks over stop searching: */
 			pulled_task = load_balance_newidle(this_cpu,
-							this_rq, sd);
-			if (time_after(next_balance,
-				  sd->last_balance + sd->balance_interval))
-				next_balance = sd->last_balance
-						+ sd->balance_interval;
-			if (pulled_task)
-				break;
-		}
+								this_rq, sd);
+
+		interval = msecs_to_jiffies(sd->balance_interval);
+		if (time_after(next_balance, sd->last_balance + interval))
+			next_balance = sd->last_balance + interval;
+		if (pulled_task)
+			break;
 	}
-	if (!pulled_task)
+	if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
 		/*
 		 * We are going idle. next_balance may be set based on
 		 * a busy processor. So reset next_balance.
 		 */
 		this_rq->next_balance = next_balance;
+	}
 }
 
 /*
@@ -2948,7 +2822,7 @@
 		schedstat_inc(sd, alb_cnt);
 
 		if (move_tasks(target_rq, target_cpu, busiest_rq, 1,
-			       RTPRIO_TO_LOAD_WEIGHT(100), sd, SCHED_IDLE,
+			       RTPRIO_TO_LOAD_WEIGHT(100), sd, CPU_IDLE,
 			       NULL))
 			schedstat_inc(sd, alb_pushed);
 		else
@@ -2957,32 +2831,6 @@
 	spin_unlock(&target_rq->lock);
 }
 
-static void update_load(struct rq *this_rq)
-{
-	unsigned long this_load;
-	unsigned int i, scale;
-
-	this_load = this_rq->raw_weighted_load;
-
-	/* Update our load: */
-	for (i = 0, scale = 1; i < 3; i++, scale += scale) {
-		unsigned long old_load, new_load;
-
-		/* scale is effectively 1 << i now, and >> i divides by scale */
-
-		old_load = this_rq->cpu_load[i];
-		new_load = this_load;
-		/*
-		 * Round up the averaging division if load is increasing. This
-		 * prevents us from getting stuck on 9 if the load is 10, for
-		 * example.
-		 */
-		if (new_load > old_load)
-			new_load += scale-1;
-		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
-	}
-}
-
 #ifdef CONFIG_NO_HZ
 static struct {
 	atomic_t load_balancer;
@@ -3065,7 +2913,7 @@
  *
  * Balancing parameters are set up in arch_init_sched_domains.
  */
-static inline void rebalance_domains(int cpu, enum idle_type idle)
+static inline void rebalance_domains(int cpu, enum cpu_idle_type idle)
 {
 	int balance = 1;
 	struct rq *rq = cpu_rq(cpu);
@@ -3079,13 +2927,16 @@
 			continue;
 
 		interval = sd->balance_interval;
-		if (idle != SCHED_IDLE)
+		if (idle != CPU_IDLE)
 			interval *= sd->busy_factor;
 
 		/* scale ms to jiffies */
 		interval = msecs_to_jiffies(interval);
 		if (unlikely(!interval))
 			interval = 1;
+		if (interval > HZ*NR_CPUS/10)
+			interval = HZ*NR_CPUS/10;
+
 
 		if (sd->flags & SD_SERIALIZE) {
 			if (!spin_trylock(&balancing))
@@ -3099,7 +2950,7 @@
 				 * longer idle, or one of our SMT siblings is
 				 * not idle.
 				 */
-				idle = NOT_IDLE;
+				idle = CPU_NOT_IDLE;
 			}
 			sd->last_balance = jiffies;
 		}
@@ -3127,11 +2978,12 @@
  */
 static void run_rebalance_domains(struct softirq_action *h)
 {
-	int local_cpu = smp_processor_id();
-	struct rq *local_rq = cpu_rq(local_cpu);
-	enum idle_type idle = local_rq->idle_at_tick ? SCHED_IDLE : NOT_IDLE;
+	int this_cpu = smp_processor_id();
+	struct rq *this_rq = cpu_rq(this_cpu);
+	enum cpu_idle_type idle = this_rq->idle_at_tick ?
+						CPU_IDLE : CPU_NOT_IDLE;
 
-	rebalance_domains(local_cpu, idle);
+	rebalance_domains(this_cpu, idle);
 
 #ifdef CONFIG_NO_HZ
 	/*
@@ -3139,13 +2991,13 @@
 	 * balancing on behalf of the other idle cpus whose ticks are
 	 * stopped.
 	 */
-	if (local_rq->idle_at_tick &&
-	    atomic_read(&nohz.load_balancer) == local_cpu) {
+	if (this_rq->idle_at_tick &&
+	    atomic_read(&nohz.load_balancer) == this_cpu) {
 		cpumask_t cpus = nohz.cpu_mask;
 		struct rq *rq;
 		int balance_cpu;
 
-		cpu_clear(local_cpu, cpus);
+		cpu_clear(this_cpu, cpus);
 		for_each_cpu_mask(balance_cpu, cpus) {
 			/*
 			 * If this cpu gets work to do, stop the load balancing
@@ -3158,8 +3010,8 @@
 			rebalance_domains(balance_cpu, SCHED_IDLE);
 
 			rq = cpu_rq(balance_cpu);
-			if (time_after(local_rq->next_balance, rq->next_balance))
-				local_rq->next_balance = rq->next_balance;
+			if (time_after(this_rq->next_balance, rq->next_balance))
+				this_rq->next_balance = rq->next_balance;
 		}
 	}
 #endif
@@ -3172,9 +3024,8 @@
  * idle load balancing owner or decide to stop the periodic load balancing,
  * if the whole system is idle.
  */
-static inline void trigger_load_balance(int cpu)
+static inline void trigger_load_balance(struct rq *rq, int cpu)
 {
-	struct rq *rq = cpu_rq(cpu);
 #ifdef CONFIG_NO_HZ
 	/*
 	 * If we were in the nohz mode recently and busy at the current
@@ -3226,13 +3077,29 @@
 	if (time_after_eq(jiffies, rq->next_balance))
 		raise_softirq(SCHED_SOFTIRQ);
 }
-#else
+
+#else	/* CONFIG_SMP */
+
 /*
  * on UP we do not need to balance between CPUs:
  */
 static inline void idle_balance(int cpu, struct rq *rq)
 {
 }
+
+/* Avoid "used but not defined" warning on UP */
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+		      unsigned long max_nr_move, unsigned long max_load_move,
+		      struct sched_domain *sd, enum cpu_idle_type idle,
+		      int *all_pinned, unsigned long *load_moved,
+		      int this_best_prio, int best_prio, int best_prio_seen,
+		      struct rq_iterator *iterator)
+{
+	*load_moved = 0;
+
+	return 0;
+}
+
 #endif
 
 DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -3240,54 +3107,28 @@
 EXPORT_PER_CPU_SYMBOL(kstat);
 
 /*
- * This is called on clock ticks and on context switches.
- * Bank in p->sched_time the ns elapsed since the last tick or switch.
+ * Return p->sum_exec_runtime plus any more ns on the sched_clock
+ * that have not yet been banked in case the task is currently running.
  */
-static inline void
-update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
+unsigned long long task_sched_runtime(struct task_struct *p)
 {
-	p->sched_time += now - p->last_ran;
-	p->last_ran = rq->most_recent_timestamp = now;
-}
-
-/*
- * Return current->sched_time plus any more ns on the sched_clock
- * that have not yet been banked.
- */
-unsigned long long current_sched_time(const struct task_struct *p)
-{
-	unsigned long long ns;
 	unsigned long flags;
+	u64 ns, delta_exec;
+	struct rq *rq;
 
-	local_irq_save(flags);
-	ns = p->sched_time + sched_clock() - p->last_ran;
-	local_irq_restore(flags);
+	rq = task_rq_lock(p, &flags);
+	ns = p->se.sum_exec_runtime;
+	if (rq->curr == p) {
+		delta_exec = rq_clock(rq) - p->se.exec_start;
+		if ((s64)delta_exec > 0)
+			ns += delta_exec;
+	}
+	task_rq_unlock(rq, &flags);
 
 	return ns;
 }
 
 /*
- * We place interactive tasks back into the active array, if possible.
- *
- * To guarantee that this does not starve expired tasks we ignore the
- * interactivity of a task if the first expired task had to wait more
- * than a 'reasonable' amount of time. This deadline timeout is
- * load-dependent, as the frequency of array switched decreases with
- * increasing number of running tasks. We also ignore the interactivity
- * if a better static_prio task has expired:
- */
-static inline int expired_starving(struct rq *rq)
-{
-	if (rq->curr->static_prio > rq->best_expired_prio)
-		return 1;
-	if (!STARVATION_LIMIT || !rq->expired_timestamp)
-		return 0;
-	if (jiffies - rq->expired_timestamp > STARVATION_LIMIT * rq->nr_running)
-		return 1;
-	return 0;
-}
-
-/*
  * Account user cpu time to a process.
  * @p: the process that the cpu time gets accounted to
  * @hardirq_offset: the offset to subtract from hardirq_count()
@@ -3360,81 +3201,6 @@
 		cpustat->steal = cputime64_add(cpustat->steal, tmp);
 }
 
-static void task_running_tick(struct rq *rq, struct task_struct *p)
-{
-	if (p->array != rq->active) {
-		/* Task has expired but was not scheduled yet */
-		set_tsk_need_resched(p);
-		return;
-	}
-	spin_lock(&rq->lock);
-	/*
-	 * The task was running during this tick - update the
-	 * time slice counter. Note: we do not update a thread's
-	 * priority until it either goes to sleep or uses up its
-	 * timeslice. This makes it possible for interactive tasks
-	 * to use up their timeslices at their highest priority levels.
-	 */
-	if (rt_task(p)) {
-		/*
-		 * RR tasks need a special form of timeslice management.
-		 * FIFO tasks have no timeslices.
-		 */
-		if ((p->policy == SCHED_RR) && !--p->time_slice) {
-			p->time_slice = task_timeslice(p);
-			p->first_time_slice = 0;
-			set_tsk_need_resched(p);
-
-			/* put it at the end of the queue: */
-			requeue_task(p, rq->active);
-		}
-		goto out_unlock;
-	}
-	if (!--p->time_slice) {
-		dequeue_task(p, rq->active);
-		set_tsk_need_resched(p);
-		p->prio = effective_prio(p);
-		p->time_slice = task_timeslice(p);
-		p->first_time_slice = 0;
-
-		if (!rq->expired_timestamp)
-			rq->expired_timestamp = jiffies;
-		if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
-			enqueue_task(p, rq->expired);
-			if (p->static_prio < rq->best_expired_prio)
-				rq->best_expired_prio = p->static_prio;
-		} else
-			enqueue_task(p, rq->active);
-	} else {
-		/*
-		 * Prevent a too long timeslice allowing a task to monopolize
-		 * the CPU. We do this by splitting up the timeslice into
-		 * smaller pieces.
-		 *
-		 * Note: this does not mean the task's timeslices expire or
-		 * get lost in any way, they just might be preempted by
-		 * another task of equal priority. (one with higher
-		 * priority would have preempted this task already.) We
-		 * requeue this task to the end of the list on this priority
-		 * level, which is in essence a round-robin of tasks with
-		 * equal priority.
-		 *
-		 * This only applies to tasks in the interactive
-		 * delta range with at least TIMESLICE_GRANULARITY to requeue.
-		 */
-		if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
-			p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
-			(p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
-			(p->array == rq->active)) {
-
-			requeue_task(p, rq->active);
-			set_tsk_need_resched(p);
-		}
-	}
-out_unlock:
-	spin_unlock(&rq->lock);
-}
-
 /*
  * This function gets called by the timer code, with HZ frequency.
  * We call it with interrupts disabled.
@@ -3444,20 +3210,19 @@
  */
 void scheduler_tick(void)
 {
-	unsigned long long now = sched_clock();
-	struct task_struct *p = current;
 	int cpu = smp_processor_id();
-	int idle_at_tick = idle_cpu(cpu);
 	struct rq *rq = cpu_rq(cpu);
+	struct task_struct *curr = rq->curr;
 
-	update_cpu_clock(p, rq, now);
+	spin_lock(&rq->lock);
+	if (curr != rq->idle) /* FIXME: needed? */
+		curr->sched_class->task_tick(rq, curr);
+	update_cpu_load(rq);
+	spin_unlock(&rq->lock);
 
-	if (!idle_at_tick)
-		task_running_tick(rq, p);
 #ifdef CONFIG_SMP
-	update_load(rq);
-	rq->idle_at_tick = idle_at_tick;
-	trigger_load_balance(cpu);
+	rq->idle_at_tick = idle_cpu(cpu);
+	trigger_load_balance(rq, cpu);
 #endif
 }
 
@@ -3499,10 +3264,67 @@
 
 #endif
 
-static inline int interactive_sleep(enum sleep_type sleep_type)
+/*
+ * Print scheduling while atomic bug:
+ */
+static noinline void __schedule_bug(struct task_struct *prev)
 {
-	return (sleep_type == SLEEP_INTERACTIVE ||
-		sleep_type == SLEEP_INTERRUPTED);
+	printk(KERN_ERR "BUG: scheduling while atomic: %s/0x%08x/%d\n",
+		prev->comm, preempt_count(), prev->pid);
+	debug_show_held_locks(prev);
+	if (irqs_disabled())
+		print_irqtrace_events(prev);
+	dump_stack();
+}
+
+/*
+ * Various schedule()-time debugging checks and statistics:
+ */
+static inline void schedule_debug(struct task_struct *prev)
+{
+	/*
+	 * Test if we are atomic.  Since do_exit() needs to call into
+	 * schedule() atomically, we ignore that path for now.
+	 * Otherwise, whine if we are scheduling when we should not be.
+	 */
+	if (unlikely(in_atomic_preempt_off()) && unlikely(!prev->exit_state))
+		__schedule_bug(prev);
+
+	profile_hit(SCHED_PROFILING, __builtin_return_address(0));
+
+	schedstat_inc(this_rq(), sched_cnt);
+}
+
+/*
+ * Pick up the highest-prio task:
+ */
+static inline struct task_struct *
+pick_next_task(struct rq *rq, struct task_struct *prev, u64 now)
+{
+	struct sched_class *class;
+	struct task_struct *p;
+
+	/*
+	 * Optimization: we know that if all tasks are in
+	 * the fair class we can call that function directly:
+	 */
+	if (likely(rq->nr_running == rq->cfs.nr_running)) {
+		p = fair_sched_class.pick_next_task(rq, now);
+		if (likely(p))
+			return p;
+	}
+
+	class = sched_class_highest;
+	for ( ; ; ) {
+		p = class->pick_next_task(rq, now);
+		if (p)
+			return p;
+		/*
+		 * Will never be NULL as the idle class always
+		 * returns a non-NULL p:
+		 */
+		class = class->next;
+	}
 }
 
 /*
@@ -3511,158 +3333,60 @@
 asmlinkage void __sched schedule(void)
 {
 	struct task_struct *prev, *next;
-	struct prio_array *array;
-	struct list_head *queue;
-	unsigned long long now;
-	unsigned long run_time;
-	int cpu, idx, new_prio;
 	long *switch_count;
 	struct rq *rq;
-
-	/*
-	 * Test if we are atomic.  Since do_exit() needs to call into
-	 * schedule() atomically, we ignore that path for now.
-	 * Otherwise, whine if we are scheduling when we should not be.
-	 */
-	if (unlikely(in_atomic() && !current->exit_state)) {
-		printk(KERN_ERR "BUG: scheduling while atomic: "
-			"%s/0x%08x/%d\n",
-			current->comm, preempt_count(), current->pid);
-		debug_show_held_locks(current);
-		if (irqs_disabled())
-			print_irqtrace_events(current);
-		dump_stack();
-	}
-	profile_hit(SCHED_PROFILING, __builtin_return_address(0));
+	u64 now;
+	int cpu;
 
 need_resched:
 	preempt_disable();
-	prev = current;
+	cpu = smp_processor_id();
+	rq = cpu_rq(cpu);
+	rcu_qsctr_inc(cpu);
+	prev = rq->curr;
+	switch_count = &prev->nivcsw;
+
 	release_kernel_lock(prev);
 need_resched_nonpreemptible:
-	rq = this_rq();
 
-	/*
-	 * The idle thread is not allowed to schedule!
-	 * Remove this check after it has been exercised a bit.
-	 */
-	if (unlikely(prev == rq->idle) && prev->state != TASK_RUNNING) {
-		printk(KERN_ERR "bad: scheduling from the idle thread!\n");
-		dump_stack();
-	}
-
-	schedstat_inc(rq, sched_cnt);
-	now = sched_clock();
-	if (likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) {
-		run_time = now - prev->timestamp;
-		if (unlikely((long long)(now - prev->timestamp) < 0))
-			run_time = 0;
-	} else
-		run_time = NS_MAX_SLEEP_AVG;
-
-	/*
-	 * Tasks charged proportionately less run_time at high sleep_avg to
-	 * delay them losing their interactive status
-	 */
-	run_time /= (CURRENT_BONUS(prev) ? : 1);
+	schedule_debug(prev);
 
 	spin_lock_irq(&rq->lock);
-
-	switch_count = &prev->nivcsw;
-	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
-		switch_count = &prev->nvcsw;
-		if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
-				unlikely(signal_pending(prev))))
-			prev->state = TASK_RUNNING;
-		else {
-			if (prev->state == TASK_UNINTERRUPTIBLE)
-				rq->nr_uninterruptible++;
-			deactivate_task(prev, rq);
-		}
-	}
-
-	cpu = smp_processor_id();
-	if (unlikely(!rq->nr_running)) {
-		idle_balance(cpu, rq);
-		if (!rq->nr_running) {
-			next = rq->idle;
-			rq->expired_timestamp = 0;
-			goto switch_tasks;
-		}
-	}
-
-	array = rq->active;
-	if (unlikely(!array->nr_active)) {
-		/*
-		 * Switch the active and expired arrays.
-		 */
-		schedstat_inc(rq, sched_switch);
-		rq->active = rq->expired;
-		rq->expired = array;
-		array = rq->active;
-		rq->expired_timestamp = 0;
-		rq->best_expired_prio = MAX_PRIO;
-	}
-
-	idx = sched_find_first_bit(array->bitmap);
-	queue = array->queue + idx;
-	next = list_entry(queue->next, struct task_struct, run_list);
-
-	if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
-		unsigned long long delta = now - next->timestamp;
-		if (unlikely((long long)(now - next->timestamp) < 0))
-			delta = 0;
-
-		if (next->sleep_type == SLEEP_INTERACTIVE)
-			delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
-
-		array = next->array;
-		new_prio = recalc_task_prio(next, next->timestamp + delta);
-
-		if (unlikely(next->prio != new_prio)) {
-			dequeue_task(next, array);
-			next->prio = new_prio;
-			enqueue_task(next, array);
-		}
-	}
-	next->sleep_type = SLEEP_NORMAL;
-switch_tasks:
-	if (next == rq->idle)
-		schedstat_inc(rq, sched_goidle);
-	prefetch(next);
-	prefetch_stack(next);
 	clear_tsk_need_resched(prev);
-	rcu_qsctr_inc(task_cpu(prev));
 
-	update_cpu_clock(prev, rq, now);
+	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
+		if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
+				unlikely(signal_pending(prev)))) {
+			prev->state = TASK_RUNNING;
+		} else {
+			deactivate_task(rq, prev, 1);
+		}
+		switch_count = &prev->nvcsw;
+	}
 
-	prev->sleep_avg -= run_time;
-	if ((long)prev->sleep_avg <= 0)
-		prev->sleep_avg = 0;
-	prev->timestamp = prev->last_ran = now;
+	if (unlikely(!rq->nr_running))
+		idle_balance(cpu, rq);
+
+	now = __rq_clock(rq);
+	prev->sched_class->put_prev_task(rq, prev, now);
+	next = pick_next_task(rq, prev, now);
 
 	sched_info_switch(prev, next);
+
 	if (likely(prev != next)) {
-		next->timestamp = next->last_ran = now;
 		rq->nr_switches++;
 		rq->curr = next;
 		++*switch_count;
 
-		prepare_task_switch(rq, next);
-		prev = context_switch(rq, prev, next);
-		barrier();
-		/*
-		 * this_rq must be evaluated again because prev may have moved
-		 * CPUs since it called schedule(), thus the 'rq' on its stack
-		 * frame will be invalid.
-		 */
-		finish_task_switch(this_rq(), prev);
+		context_switch(rq, prev, next); /* unlocks the rq */
 	} else
 		spin_unlock_irq(&rq->lock);
 
-	prev = current;
-	if (unlikely(reacquire_kernel_lock(prev) < 0))
+	if (unlikely(reacquire_kernel_lock(current) < 0)) {
+		cpu = smp_processor_id();
+		rq = cpu_rq(cpu);
 		goto need_resched_nonpreemptible;
+	}
 	preempt_enable_no_resched();
 	if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
 		goto need_resched;
@@ -3990,74 +3714,85 @@
 }
 EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
 
-
-#define	SLEEP_ON_VAR					\
-	unsigned long flags;				\
-	wait_queue_t wait;				\
-	init_waitqueue_entry(&wait, current);
-
-#define SLEEP_ON_HEAD					\
-	spin_lock_irqsave(&q->lock,flags);		\
-	__add_wait_queue(q, &wait);			\
-	spin_unlock(&q->lock);
-
-#define	SLEEP_ON_TAIL					\
-	spin_lock_irq(&q->lock);			\
-	__remove_wait_queue(q, &wait);			\
-	spin_unlock_irqrestore(&q->lock, flags);
-
-void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
+static inline void
+sleep_on_head(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags)
 {
-	SLEEP_ON_VAR
+	spin_lock_irqsave(&q->lock, *flags);
+	__add_wait_queue(q, wait);
+	spin_unlock(&q->lock);
+}
+
+static inline void
+sleep_on_tail(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags)
+{
+	spin_lock_irq(&q->lock);
+	__remove_wait_queue(q, wait);
+	spin_unlock_irqrestore(&q->lock, *flags);
+}
+
+void __sched interruptible_sleep_on(wait_queue_head_t *q)
+{
+	unsigned long flags;
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
 
 	current->state = TASK_INTERRUPTIBLE;
 
-	SLEEP_ON_HEAD
+	sleep_on_head(q, &wait, &flags);
 	schedule();
-	SLEEP_ON_TAIL
+	sleep_on_tail(q, &wait, &flags);
 }
 EXPORT_SYMBOL(interruptible_sleep_on);
 
-long fastcall __sched
+long __sched
 interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
-	SLEEP_ON_VAR
+	unsigned long flags;
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
 
 	current->state = TASK_INTERRUPTIBLE;
 
-	SLEEP_ON_HEAD
+	sleep_on_head(q, &wait, &flags);
 	timeout = schedule_timeout(timeout);
-	SLEEP_ON_TAIL
+	sleep_on_tail(q, &wait, &flags);
 
 	return timeout;
 }
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 
-void fastcall __sched sleep_on(wait_queue_head_t *q)
+void __sched sleep_on(wait_queue_head_t *q)
 {
-	SLEEP_ON_VAR
+	unsigned long flags;
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
 
 	current->state = TASK_UNINTERRUPTIBLE;
 
-	SLEEP_ON_HEAD
+	sleep_on_head(q, &wait, &flags);
 	schedule();
-	SLEEP_ON_TAIL
+	sleep_on_tail(q, &wait, &flags);
 }
 EXPORT_SYMBOL(sleep_on);
 
-long fastcall __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
-	SLEEP_ON_VAR
+	unsigned long flags;
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
 
 	current->state = TASK_UNINTERRUPTIBLE;
 
-	SLEEP_ON_HEAD
+	sleep_on_head(q, &wait, &flags);
 	timeout = schedule_timeout(timeout);
-	SLEEP_ON_TAIL
+	sleep_on_tail(q, &wait, &flags);
 
 	return timeout;
 }
-
 EXPORT_SYMBOL(sleep_on_timeout);
 
 #ifdef CONFIG_RT_MUTEXES
@@ -4074,29 +3809,30 @@
  */
 void rt_mutex_setprio(struct task_struct *p, int prio)
 {
-	struct prio_array *array;
 	unsigned long flags;
+	int oldprio, on_rq;
 	struct rq *rq;
-	int oldprio;
+	u64 now;
 
 	BUG_ON(prio < 0 || prio > MAX_PRIO);
 
 	rq = task_rq_lock(p, &flags);
+	now = rq_clock(rq);
 
 	oldprio = p->prio;
-	array = p->array;
-	if (array)
-		dequeue_task(p, array);
+	on_rq = p->se.on_rq;
+	if (on_rq)
+		dequeue_task(rq, p, 0, now);
+
+	if (rt_prio(prio))
+		p->sched_class = &rt_sched_class;
+	else
+		p->sched_class = &fair_sched_class;
+
 	p->prio = prio;
 
-	if (array) {
-		/*
-		 * If changing to an RT priority then queue it
-		 * in the active array!
-		 */
-		if (rt_task(p))
-			array = rq->active;
-		enqueue_task(p, array);
+	if (on_rq) {
+		enqueue_task(rq, p, 0, now);
 		/*
 		 * Reschedule if we are currently running on this runqueue and
 		 * our priority decreased, or if we are not currently running on
@@ -4105,8 +3841,9 @@
 		if (task_running(rq, p)) {
 			if (p->prio > oldprio)
 				resched_task(rq->curr);
-		} else if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
+		} else {
+			check_preempt_curr(rq, p);
+		}
 	}
 	task_rq_unlock(rq, &flags);
 }
@@ -4115,10 +3852,10 @@
 
 void set_user_nice(struct task_struct *p, long nice)
 {
-	struct prio_array *array;
-	int old_prio, delta;
+	int old_prio, delta, on_rq;
 	unsigned long flags;
 	struct rq *rq;
+	u64 now;
 
 	if (TASK_NICE(p) == nice || nice < -20 || nice > 19)
 		return;
@@ -4127,20 +3864,21 @@
 	 * the task might be in the middle of scheduling on another CPU.
 	 */
 	rq = task_rq_lock(p, &flags);
+	now = rq_clock(rq);
 	/*
 	 * The RT priorities are set via sched_setscheduler(), but we still
 	 * allow the 'normal' nice value to be set - but as expected
 	 * it wont have any effect on scheduling until the task is
-	 * not SCHED_NORMAL/SCHED_BATCH:
+	 * SCHED_FIFO/SCHED_RR:
 	 */
-	if (has_rt_policy(p)) {
+	if (task_has_rt_policy(p)) {
 		p->static_prio = NICE_TO_PRIO(nice);
 		goto out_unlock;
 	}
-	array = p->array;
-	if (array) {
-		dequeue_task(p, array);
-		dec_raw_weighted_load(rq, p);
+	on_rq = p->se.on_rq;
+	if (on_rq) {
+		dequeue_task(rq, p, 0, now);
+		dec_load(rq, p, now);
 	}
 
 	p->static_prio = NICE_TO_PRIO(nice);
@@ -4149,9 +3887,9 @@
 	p->prio = effective_prio(p);
 	delta = p->prio - old_prio;
 
-	if (array) {
-		enqueue_task(p, array);
-		inc_raw_weighted_load(rq, p);
+	if (on_rq) {
+		enqueue_task(rq, p, 0, now);
+		inc_load(rq, p, now);
 		/*
 		 * If the task increased its priority or is running and
 		 * lowered its priority, then reschedule its CPU:
@@ -4271,20 +4009,28 @@
 }
 
 /* Actually do priority change: must hold rq lock. */
-static void __setscheduler(struct task_struct *p, int policy, int prio)
+static void
+__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
 {
-	BUG_ON(p->array);
+	BUG_ON(p->se.on_rq);
 
 	p->policy = policy;
+	switch (p->policy) {
+	case SCHED_NORMAL:
+	case SCHED_BATCH:
+	case SCHED_IDLE:
+		p->sched_class = &fair_sched_class;
+		break;
+	case SCHED_FIFO:
+	case SCHED_RR:
+		p->sched_class = &rt_sched_class;
+		break;
+	}
+
 	p->rt_priority = prio;
 	p->normal_prio = normal_prio(p);
 	/* we are holding p->pi_lock already */
 	p->prio = rt_mutex_getprio(p);
-	/*
-	 * SCHED_BATCH tasks are treated as perpetual CPU hogs:
-	 */
-	if (policy == SCHED_BATCH)
-		p->sleep_avg = 0;
 	set_load_weight(p);
 }
 
@@ -4299,8 +4045,7 @@
 int sched_setscheduler(struct task_struct *p, int policy,
 		       struct sched_param *param)
 {
-	int retval, oldprio, oldpolicy = -1;
-	struct prio_array *array;
+	int retval, oldprio, oldpolicy = -1, on_rq;
 	unsigned long flags;
 	struct rq *rq;
 
@@ -4311,27 +4056,27 @@
 	if (policy < 0)
 		policy = oldpolicy = p->policy;
 	else if (policy != SCHED_FIFO && policy != SCHED_RR &&
-			policy != SCHED_NORMAL && policy != SCHED_BATCH)
+			policy != SCHED_NORMAL && policy != SCHED_BATCH &&
+			policy != SCHED_IDLE)
 		return -EINVAL;
 	/*
 	 * Valid priorities for SCHED_FIFO and SCHED_RR are
-	 * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and
-	 * SCHED_BATCH is 0.
+	 * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL,
+	 * SCHED_BATCH and SCHED_IDLE is 0.
 	 */
 	if (param->sched_priority < 0 ||
 	    (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
 	    (!p->mm && param->sched_priority > MAX_RT_PRIO-1))
 		return -EINVAL;
-	if (is_rt_policy(policy) != (param->sched_priority != 0))
+	if (rt_policy(policy) != (param->sched_priority != 0))
 		return -EINVAL;
 
 	/*
 	 * Allow unprivileged RT tasks to decrease priority:
 	 */
 	if (!capable(CAP_SYS_NICE)) {
-		if (is_rt_policy(policy)) {
+		if (rt_policy(policy)) {
 			unsigned long rlim_rtprio;
-			unsigned long flags;
 
 			if (!lock_task_sighand(p, &flags))
 				return -ESRCH;
@@ -4347,6 +4092,12 @@
 			    param->sched_priority > rlim_rtprio)
 				return -EPERM;
 		}
+		/*
+		 * Like positive nice levels, dont allow tasks to
+		 * move out of SCHED_IDLE either:
+		 */
+		if (p->policy == SCHED_IDLE && policy != SCHED_IDLE)
+			return -EPERM;
 
 		/* can't change other user's priorities */
 		if ((current->euid != p->euid) &&
@@ -4374,13 +4125,13 @@
 		spin_unlock_irqrestore(&p->pi_lock, flags);
 		goto recheck;
 	}
-	array = p->array;
-	if (array)
-		deactivate_task(p, rq);
+	on_rq = p->se.on_rq;
+	if (on_rq)
+		deactivate_task(rq, p, 0);
 	oldprio = p->prio;
-	__setscheduler(p, policy, param->sched_priority);
-	if (array) {
-		__activate_task(p, rq);
+	__setscheduler(rq, p, policy, param->sched_priority);
+	if (on_rq) {
+		activate_task(rq, p, 0);
 		/*
 		 * Reschedule if we are currently running on this runqueue and
 		 * our priority decreased, or if we are not currently running on
@@ -4389,8 +4140,9 @@
 		if (task_running(rq, p)) {
 			if (p->prio > oldprio)
 				resched_task(rq->curr);
-		} else if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
+		} else {
+			check_preempt_curr(rq, p);
+		}
 	}
 	__task_rq_unlock(rq);
 	spin_unlock_irqrestore(&p->pi_lock, flags);
@@ -4662,41 +4414,18 @@
 /**
  * sys_sched_yield - yield the current processor to other threads.
  *
- * This function yields the current CPU by moving the calling thread
- * to the expired array. If there are no other threads running on this
- * CPU then this function will return.
+ * This function yields the current CPU to other tasks. If there are no
+ * other threads running on this CPU then this function will return.
  */
 asmlinkage long sys_sched_yield(void)
 {
 	struct rq *rq = this_rq_lock();
-	struct prio_array *array = current->array, *target = rq->expired;
 
 	schedstat_inc(rq, yld_cnt);
-	/*
-	 * We implement yielding by moving the task into the expired
-	 * queue.
-	 *
-	 * (special rule: RT tasks will just roundrobin in the active
-	 *  array.)
-	 */
-	if (rt_task(current))
-		target = rq->active;
-
-	if (array->nr_active == 1) {
+	if (unlikely(rq->nr_running == 1))
 		schedstat_inc(rq, yld_act_empty);
-		if (!rq->expired->nr_active)
-			schedstat_inc(rq, yld_both_empty);
-	} else if (!rq->expired->nr_active)
-		schedstat_inc(rq, yld_exp_empty);
-
-	if (array != target) {
-		dequeue_task(current, array);
-		enqueue_task(current, target);
-	} else
-		/*
-		 * requeue_task is cheaper so perform that if possible.
-		 */
-		requeue_task(current, array);
+	else
+		current->sched_class->yield_task(rq, current);
 
 	/*
 	 * Since we are going to call schedule() anyway, there's
@@ -4775,9 +4504,7 @@
 	BUG_ON(!in_softirq());
 
 	if (need_resched() && system_state == SYSTEM_RUNNING) {
-		raw_local_irq_disable();
-		_local_bh_enable();
-		raw_local_irq_enable();
+		local_bh_enable();
 		__cond_resched();
 		local_bh_disable();
 		return 1;
@@ -4849,6 +4576,7 @@
 		break;
 	case SCHED_NORMAL:
 	case SCHED_BATCH:
+	case SCHED_IDLE:
 		ret = 0;
 		break;
 	}
@@ -4873,6 +4601,7 @@
 		break;
 	case SCHED_NORMAL:
 	case SCHED_BATCH:
+	case SCHED_IDLE:
 		ret = 0;
 	}
 	return ret;
@@ -4907,7 +4636,7 @@
 		goto out_unlock;
 
 	jiffies_to_timespec(p->policy == SCHED_FIFO ?
-				0 : task_timeslice(p), &t);
+				0 : static_prio_timeslice(p->static_prio), &t);
 	read_unlock(&tasklist_lock);
 	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
 out_nounlock:
@@ -4927,14 +4656,14 @@
 	state = p->state ? __ffs(p->state) + 1 : 0;
 	printk("%-13.13s %c", p->comm,
 		state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?');
-#if (BITS_PER_LONG == 32)
+#if BITS_PER_LONG == 32
 	if (state == TASK_RUNNING)
-		printk(" running ");
+		printk(" running  ");
 	else
-		printk(" %08lX ", thread_saved_pc(p));
+		printk(" %08lx ", thread_saved_pc(p));
 #else
 	if (state == TASK_RUNNING)
-		printk("  running task   ");
+		printk("  running task    ");
 	else
 		printk(" %016lx ", thread_saved_pc(p));
 #endif
@@ -4946,11 +4675,7 @@
 		free = (unsigned long)n - (unsigned long)end_of_stack(p);
 	}
 #endif
-	printk("%5lu %5d %6d", free, p->pid, p->parent->pid);
-	if (!p->mm)
-		printk(" (L-TLB)\n");
-	else
-		printk(" (NOTLB)\n");
+	printk("%5lu %5d %6d\n", free, p->pid, p->parent->pid);
 
 	if (state != TASK_RUNNING)
 		show_stack(p, NULL);
@@ -4960,14 +4685,12 @@
 {
 	struct task_struct *g, *p;
 
-#if (BITS_PER_LONG == 32)
-	printk("\n"
-	       "                         free                        sibling\n");
-	printk("  task             PC    stack   pid father child younger older\n");
+#if BITS_PER_LONG == 32
+	printk(KERN_INFO
+		"  task                PC stack   pid father\n");
 #else
-	printk("\n"
-	       "                                 free                        sibling\n");
-	printk("  task                 PC        stack   pid father child younger older\n");
+	printk(KERN_INFO
+		"  task                        PC stack   pid father\n");
 #endif
 	read_lock(&tasklist_lock);
 	do_each_thread(g, p) {
@@ -4982,6 +4705,9 @@
 
 	touch_all_softlockup_watchdogs();
 
+#ifdef CONFIG_SCHED_DEBUG
+	sysrq_sched_debug_show();
+#endif
 	read_unlock(&tasklist_lock);
 	/*
 	 * Only show locks if all tasks are dumped:
@@ -4990,6 +4716,11 @@
 		debug_show_all_locks();
 }
 
+void __cpuinit init_idle_bootup_task(struct task_struct *idle)
+{
+	idle->sched_class = &idle_sched_class;
+}
+
 /**
  * init_idle - set up an idle thread for a given CPU
  * @idle: task in question
@@ -5003,13 +4734,12 @@
 	struct rq *rq = cpu_rq(cpu);
 	unsigned long flags;
 
-	idle->timestamp = sched_clock();
-	idle->sleep_avg = 0;
-	idle->array = NULL;
+	__sched_fork(idle);
+	idle->se.exec_start = sched_clock();
+
 	idle->prio = idle->normal_prio = MAX_PRIO;
-	idle->state = TASK_RUNNING;
 	idle->cpus_allowed = cpumask_of_cpu(cpu);
-	set_task_cpu(idle, cpu);
+	__set_task_cpu(idle, cpu);
 
 	spin_lock_irqsave(&rq->lock, flags);
 	rq->curr = rq->idle = idle;
@@ -5024,6 +4754,10 @@
 #else
 	task_thread_info(idle)->preempt_count = 0;
 #endif
+	/*
+	 * The idle tasks have their own, simple scheduling class:
+	 */
+	idle->sched_class = &idle_sched_class;
 }
 
 /*
@@ -5035,6 +4769,28 @@
  */
 cpumask_t nohz_cpu_mask = CPU_MASK_NONE;
 
+/*
+ * Increase the granularity value when there are more CPUs,
+ * because with more CPUs the 'effective latency' as visible
+ * to users decreases. But the relationship is not linear,
+ * so pick a second-best guess by going with the log2 of the
+ * number of CPUs.
+ *
+ * This idea comes from the SD scheduler of Con Kolivas:
+ */
+static inline void sched_init_granularity(void)
+{
+	unsigned int factor = 1 + ilog2(num_online_cpus());
+	const unsigned long gran_limit = 100000000;
+
+	sysctl_sched_granularity *= factor;
+	if (sysctl_sched_granularity > gran_limit)
+		sysctl_sched_granularity = gran_limit;
+
+	sysctl_sched_runtime_limit = sysctl_sched_granularity * 4;
+	sysctl_sched_wakeup_granularity = sysctl_sched_granularity / 2;
+}
+
 #ifdef CONFIG_SMP
 /*
  * This is how migration works:
@@ -5108,7 +4864,7 @@
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
 	struct rq *rq_dest, *rq_src;
-	int ret = 0;
+	int ret = 0, on_rq;
 
 	if (unlikely(cpu_is_offline(dest_cpu)))
 		return ret;
@@ -5124,20 +4880,13 @@
 	if (!cpu_isset(dest_cpu, p->cpus_allowed))
 		goto out;
 
+	on_rq = p->se.on_rq;
+	if (on_rq)
+		deactivate_task(rq_src, p, 0);
 	set_task_cpu(p, dest_cpu);
-	if (p->array) {
-		/*
-		 * Sync timestamp with rq_dest's before activating.
-		 * The same thing could be achieved by doing this step
-		 * afterwards, and pretending it was a local activate.
-		 * This way is cleaner and logically correct.
-		 */
-		p->timestamp = p->timestamp - rq_src->most_recent_timestamp
-				+ rq_dest->most_recent_timestamp;
-		deactivate_task(p, rq_src);
-		__activate_task(p, rq_dest);
-		if (TASK_PREEMPTS_CURR(p, rq_dest))
-			resched_task(rq_dest->curr);
+	if (on_rq) {
+		activate_task(rq_dest, p, 0);
+		check_preempt_curr(rq_dest, p);
 	}
 	ret = 1;
 out:
@@ -5163,8 +4912,6 @@
 		struct migration_req *req;
 		struct list_head *head;
 
-		try_to_freeze();
-
 		spin_lock_irq(&rq->lock);
 
 		if (cpu_is_offline(cpu)) {
@@ -5289,7 +5036,8 @@
 	write_unlock_irq(&tasklist_lock);
 }
 
-/* Schedules idle task to be the next runnable task on current CPU.
+/*
+ * Schedules idle task to be the next runnable task on current CPU.
  * It does so by boosting its priority to highest possible and adding it to
  * the _front_ of the runqueue. Used by CPU offline code.
  */
@@ -5309,10 +5057,10 @@
 	 */
 	spin_lock_irqsave(&rq->lock, flags);
 
-	__setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
+	__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
 
 	/* Add idle task to the _front_ of its priority queue: */
-	__activate_idle_task(p, rq);
+	activate_idle_task(p, rq);
 
 	spin_unlock_irqrestore(&rq->lock, flags);
 }
@@ -5362,16 +5110,15 @@
 static void migrate_dead_tasks(unsigned int dead_cpu)
 {
 	struct rq *rq = cpu_rq(dead_cpu);
-	unsigned int arr, i;
+	struct task_struct *next;
 
-	for (arr = 0; arr < 2; arr++) {
-		for (i = 0; i < MAX_PRIO; i++) {
-			struct list_head *list = &rq->arrays[arr].queue[i];
-
-			while (!list_empty(list))
-				migrate_dead(dead_cpu, list_entry(list->next,
-					     struct task_struct, run_list));
-		}
+	for ( ; ; ) {
+		if (!rq->nr_running)
+			break;
+		next = pick_next_task(rq, rq->curr, rq_clock(rq));
+		if (!next)
+			break;
+		migrate_dead(dead_cpu, next);
 	}
 }
 #endif /* CONFIG_HOTPLUG_CPU */
@@ -5395,14 +5142,13 @@
 
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
-		p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
+		p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);
 		if (IS_ERR(p))
 			return NOTIFY_BAD;
-		p->flags |= PF_NOFREEZE;
 		kthread_bind(p, cpu);
 		/* Must be high prio: stop_machine expects to yield to it. */
 		rq = task_rq_lock(p, &flags);
-		__setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
+		__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
 		task_rq_unlock(rq, &flags);
 		cpu_rq(cpu)->migration_thread = p;
 		break;
@@ -5433,9 +5179,10 @@
 		rq->migration_thread = NULL;
 		/* Idle task back to normal (off runqueue, low prio) */
 		rq = task_rq_lock(rq->idle, &flags);
-		deactivate_task(rq->idle, rq);
+		deactivate_task(rq, rq->idle, 0);
 		rq->idle->static_prio = MAX_PRIO;
-		__setscheduler(rq->idle, SCHED_NORMAL, 0);
+		__setscheduler(rq, rq->idle, SCHED_NORMAL, 0);
+		rq->idle->sched_class = &idle_sched_class;
 		migrate_dead_tasks(cpu);
 		task_rq_unlock(rq, &flags);
 		migrate_nr_uninterruptible(rq);
@@ -5744,483 +5491,6 @@
 
 #define SD_NODES_PER_DOMAIN 16
 
-/*
- * Self-tuning task migration cost measurement between source and target CPUs.
- *
- * This is done by measuring the cost of manipulating buffers of varying
- * sizes. For a given buffer-size here are the steps that are taken:
- *
- * 1) the source CPU reads+dirties a shared buffer
- * 2) the target CPU reads+dirties the same shared buffer
- *
- * We measure how long they take, in the following 4 scenarios:
- *
- *  - source: CPU1, target: CPU2 | cost1
- *  - source: CPU2, target: CPU1 | cost2
- *  - source: CPU1, target: CPU1 | cost3
- *  - source: CPU2, target: CPU2 | cost4
- *
- * We then calculate the cost3+cost4-cost1-cost2 difference - this is
- * the cost of migration.
- *
- * We then start off from a small buffer-size and iterate up to larger
- * buffer sizes, in 5% steps - measuring each buffer-size separately, and
- * doing a maximum search for the cost. (The maximum cost for a migration
- * normally occurs when the working set size is around the effective cache
- * size.)
- */
-#define SEARCH_SCOPE		2
-#define MIN_CACHE_SIZE		(64*1024U)
-#define DEFAULT_CACHE_SIZE	(5*1024*1024U)
-#define ITERATIONS		1
-#define SIZE_THRESH		130
-#define COST_THRESH		130
-
-/*
- * The migration cost is a function of 'domain distance'. Domain
- * distance is the number of steps a CPU has to iterate down its
- * domain tree to share a domain with the other CPU. The farther
- * two CPUs are from each other, the larger the distance gets.
- *
- * Note that we use the distance only to cache measurement results,
- * the distance value is not used numerically otherwise. When two
- * CPUs have the same distance it is assumed that the migration
- * cost is the same. (this is a simplification but quite practical)
- */
-#define MAX_DOMAIN_DISTANCE 32
-
-static unsigned long long migration_cost[MAX_DOMAIN_DISTANCE] =
-		{ [ 0 ... MAX_DOMAIN_DISTANCE-1 ] =
-/*
- * Architectures may override the migration cost and thus avoid
- * boot-time calibration. Unit is nanoseconds. Mostly useful for
- * virtualized hardware:
- */
-#ifdef CONFIG_DEFAULT_MIGRATION_COST
-			CONFIG_DEFAULT_MIGRATION_COST
-#else
-			-1LL
-#endif
-};
-
-/*
- * Allow override of migration cost - in units of microseconds.
- * E.g. migration_cost=1000,2000,3000 will set up a level-1 cost
- * of 1 msec, level-2 cost of 2 msecs and level3 cost of 3 msecs:
- */
-static int __init migration_cost_setup(char *str)
-{
-	int ints[MAX_DOMAIN_DISTANCE+1], i;
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-
-	printk("#ints: %d\n", ints[0]);
-	for (i = 1; i <= ints[0]; i++) {
-		migration_cost[i-1] = (unsigned long long)ints[i]*1000;
-		printk("migration_cost[%d]: %Ld\n", i-1, migration_cost[i-1]);
-	}
-	return 1;
-}
-
-__setup ("migration_cost=", migration_cost_setup);
-
-/*
- * Global multiplier (divisor) for migration-cutoff values,
- * in percentiles. E.g. use a value of 150 to get 1.5 times
- * longer cache-hot cutoff times.
- *
- * (We scale it from 100 to 128 to long long handling easier.)
- */
-
-#define MIGRATION_FACTOR_SCALE 128
-
-static unsigned int migration_factor = MIGRATION_FACTOR_SCALE;
-
-static int __init setup_migration_factor(char *str)
-{
-	get_option(&str, &migration_factor);
-	migration_factor = migration_factor * MIGRATION_FACTOR_SCALE / 100;
-	return 1;
-}
-
-__setup("migration_factor=", setup_migration_factor);
-
-/*
- * Estimated distance of two CPUs, measured via the number of domains
- * we have to pass for the two CPUs to be in the same span:
- */
-static unsigned long domain_distance(int cpu1, int cpu2)
-{
-	unsigned long distance = 0;
-	struct sched_domain *sd;
-
-	for_each_domain(cpu1, sd) {
-		WARN_ON(!cpu_isset(cpu1, sd->span));
-		if (cpu_isset(cpu2, sd->span))
-			return distance;
-		distance++;
-	}
-	if (distance >= MAX_DOMAIN_DISTANCE) {
-		WARN_ON(1);
-		distance = MAX_DOMAIN_DISTANCE-1;
-	}
-
-	return distance;
-}
-
-static unsigned int migration_debug;
-
-static int __init setup_migration_debug(char *str)
-{
-	get_option(&str, &migration_debug);
-	return 1;
-}
-
-__setup("migration_debug=", setup_migration_debug);
-
-/*
- * Maximum cache-size that the scheduler should try to measure.
- * Architectures with larger caches should tune this up during
- * bootup. Gets used in the domain-setup code (i.e. during SMP
- * bootup).
- */
-unsigned int max_cache_size;
-
-static int __init setup_max_cache_size(char *str)
-{
-	get_option(&str, &max_cache_size);
-	return 1;
-}
-
-__setup("max_cache_size=", setup_max_cache_size);
-
-/*
- * Dirty a big buffer in a hard-to-predict (for the L2 cache) way. This
- * is the operation that is timed, so we try to generate unpredictable
- * cachemisses that still end up filling the L2 cache:
- */
-static void touch_cache(void *__cache, unsigned long __size)
-{
-	unsigned long size = __size / sizeof(long);
-	unsigned long chunk1 = size / 3;
-	unsigned long chunk2 = 2 * size / 3;
-	unsigned long *cache = __cache;
-	int i;
-
-	for (i = 0; i < size/6; i += 8) {
-		switch (i % 6) {
-			case 0: cache[i]++;
-			case 1: cache[size-1-i]++;
-			case 2: cache[chunk1-i]++;
-			case 3: cache[chunk1+i]++;
-			case 4: cache[chunk2-i]++;
-			case 5: cache[chunk2+i]++;
-		}
-	}
-}
-
-/*
- * Measure the cache-cost of one task migration. Returns in units of nsec.
- */
-static unsigned long long
-measure_one(void *cache, unsigned long size, int source, int target)
-{
-	cpumask_t mask, saved_mask;
-	unsigned long long t0, t1, t2, t3, cost;
-
-	saved_mask = current->cpus_allowed;
-
-	/*
-	 * Flush source caches to RAM and invalidate them:
-	 */
-	sched_cacheflush();
-
-	/*
-	 * Migrate to the source CPU:
-	 */
-	mask = cpumask_of_cpu(source);
-	set_cpus_allowed(current, mask);
-	WARN_ON(smp_processor_id() != source);
-
-	/*
-	 * Dirty the working set:
-	 */
-	t0 = sched_clock();
-	touch_cache(cache, size);
-	t1 = sched_clock();
-
-	/*
-	 * Migrate to the target CPU, dirty the L2 cache and access
-	 * the shared buffer. (which represents the working set
-	 * of a migrated task.)
-	 */
-	mask = cpumask_of_cpu(target);
-	set_cpus_allowed(current, mask);
-	WARN_ON(smp_processor_id() != target);
-
-	t2 = sched_clock();
-	touch_cache(cache, size);
-	t3 = sched_clock();
-
-	cost = t1-t0 + t3-t2;
-
-	if (migration_debug >= 2)
-		printk("[%d->%d]: %8Ld %8Ld %8Ld => %10Ld.\n",
-			source, target, t1-t0, t1-t0, t3-t2, cost);
-	/*
-	 * Flush target caches to RAM and invalidate them:
-	 */
-	sched_cacheflush();
-
-	set_cpus_allowed(current, saved_mask);
-
-	return cost;
-}
-
-/*
- * Measure a series of task migrations and return the average
- * result. Since this code runs early during bootup the system
- * is 'undisturbed' and the average latency makes sense.
- *
- * The algorithm in essence auto-detects the relevant cache-size,
- * so it will properly detect different cachesizes for different
- * cache-hierarchies, depending on how the CPUs are connected.
- *
- * Architectures can prime the upper limit of the search range via
- * max_cache_size, otherwise the search range defaults to 20MB...64K.
- */
-static unsigned long long
-measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
-{
-	unsigned long long cost1, cost2;
-	int i;
-
-	/*
-	 * Measure the migration cost of 'size' bytes, over an
-	 * average of 10 runs:
-	 *
-	 * (We perturb the cache size by a small (0..4k)
-	 *  value to compensate size/alignment related artifacts.
-	 *  We also subtract the cost of the operation done on
-	 *  the same CPU.)
-	 */
-	cost1 = 0;
-
-	/*
-	 * dry run, to make sure we start off cache-cold on cpu1,
-	 * and to get any vmalloc pagefaults in advance:
-	 */
-	measure_one(cache, size, cpu1, cpu2);
-	for (i = 0; i < ITERATIONS; i++)
-		cost1 += measure_one(cache, size - i * 1024, cpu1, cpu2);
-
-	measure_one(cache, size, cpu2, cpu1);
-	for (i = 0; i < ITERATIONS; i++)
-		cost1 += measure_one(cache, size - i * 1024, cpu2, cpu1);
-
-	/*
-	 * (We measure the non-migrating [cached] cost on both
-	 *  cpu1 and cpu2, to handle CPUs with different speeds)
-	 */
-	cost2 = 0;
-
-	measure_one(cache, size, cpu1, cpu1);
-	for (i = 0; i < ITERATIONS; i++)
-		cost2 += measure_one(cache, size - i * 1024, cpu1, cpu1);
-
-	measure_one(cache, size, cpu2, cpu2);
-	for (i = 0; i < ITERATIONS; i++)
-		cost2 += measure_one(cache, size - i * 1024, cpu2, cpu2);
-
-	/*
-	 * Get the per-iteration migration cost:
-	 */
-	do_div(cost1, 2 * ITERATIONS);
-	do_div(cost2, 2 * ITERATIONS);
-
-	return cost1 - cost2;
-}
-
-static unsigned long long measure_migration_cost(int cpu1, int cpu2)
-{
-	unsigned long long max_cost = 0, fluct = 0, avg_fluct = 0;
-	unsigned int max_size, size, size_found = 0;
-	long long cost = 0, prev_cost;
-	void *cache;
-
-	/*
-	 * Search from max_cache_size*5 down to 64K - the real relevant
-	 * cachesize has to lie somewhere inbetween.
-	 */
-	if (max_cache_size) {
-		max_size = max(max_cache_size * SEARCH_SCOPE, MIN_CACHE_SIZE);
-		size = max(max_cache_size / SEARCH_SCOPE, MIN_CACHE_SIZE);
-	} else {
-		/*
-		 * Since we have no estimation about the relevant
-		 * search range
-		 */
-		max_size = DEFAULT_CACHE_SIZE * SEARCH_SCOPE;
-		size = MIN_CACHE_SIZE;
-	}
-
-	if (!cpu_online(cpu1) || !cpu_online(cpu2)) {
-		printk("cpu %d and %d not both online!\n", cpu1, cpu2);
-		return 0;
-	}
-
-	/*
-	 * Allocate the working set:
-	 */
-	cache = vmalloc(max_size);
-	if (!cache) {
-		printk("could not vmalloc %d bytes for cache!\n", 2 * max_size);
-		return 1000000; /* return 1 msec on very small boxen */
-	}
-
-	while (size <= max_size) {
-		prev_cost = cost;
-		cost = measure_cost(cpu1, cpu2, cache, size);
-
-		/*
-		 * Update the max:
-		 */
-		if (cost > 0) {
-			if (max_cost < cost) {
-				max_cost = cost;
-				size_found = size;
-			}
-		}
-		/*
-		 * Calculate average fluctuation, we use this to prevent
-		 * noise from triggering an early break out of the loop:
-		 */
-		fluct = abs(cost - prev_cost);
-		avg_fluct = (avg_fluct + fluct)/2;
-
-		if (migration_debug)
-			printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): "
-				"(%8Ld %8Ld)\n",
-				cpu1, cpu2, size,
-				(long)cost / 1000000,
-				((long)cost / 100000) % 10,
-				(long)max_cost / 1000000,
-				((long)max_cost / 100000) % 10,
-				domain_distance(cpu1, cpu2),
-				cost, avg_fluct);
-
-		/*
-		 * If we iterated at least 20% past the previous maximum,
-		 * and the cost has dropped by more than 20% already,
-		 * (taking fluctuations into account) then we assume to
-		 * have found the maximum and break out of the loop early:
-		 */
-		if (size_found && (size*100 > size_found*SIZE_THRESH))
-			if (cost+avg_fluct <= 0 ||
-				max_cost*100 > (cost+avg_fluct)*COST_THRESH) {
-
-				if (migration_debug)
-					printk("-> found max.\n");
-				break;
-			}
-		/*
-		 * Increase the cachesize in 10% steps:
-		 */
-		size = size * 10 / 9;
-	}
-
-	if (migration_debug)
-		printk("[%d][%d] working set size found: %d, cost: %Ld\n",
-			cpu1, cpu2, size_found, max_cost);
-
-	vfree(cache);
-
-	/*
-	 * A task is considered 'cache cold' if at least 2 times
-	 * the worst-case cost of migration has passed.
-	 *
-	 * (this limit is only listened to if the load-balancing
-	 * situation is 'nice' - if there is a large imbalance we
-	 * ignore it for the sake of CPU utilization and
-	 * processing fairness.)
-	 */
-	return 2 * max_cost * migration_factor / MIGRATION_FACTOR_SCALE;
-}
-
-static void calibrate_migration_costs(const cpumask_t *cpu_map)
-{
-	int cpu1 = -1, cpu2 = -1, cpu, orig_cpu = raw_smp_processor_id();
-	unsigned long j0, j1, distance, max_distance = 0;
-	struct sched_domain *sd;
-
-	j0 = jiffies;
-
-	/*
-	 * First pass - calculate the cacheflush times:
-	 */
-	for_each_cpu_mask(cpu1, *cpu_map) {
-		for_each_cpu_mask(cpu2, *cpu_map) {
-			if (cpu1 == cpu2)
-				continue;
-			distance = domain_distance(cpu1, cpu2);
-			max_distance = max(max_distance, distance);
-			/*
-			 * No result cached yet?
-			 */
-			if (migration_cost[distance] == -1LL)
-				migration_cost[distance] =
-					measure_migration_cost(cpu1, cpu2);
-		}
-	}
-	/*
-	 * Second pass - update the sched domain hierarchy with
-	 * the new cache-hot-time estimations:
-	 */
-	for_each_cpu_mask(cpu, *cpu_map) {
-		distance = 0;
-		for_each_domain(cpu, sd) {
-			sd->cache_hot_time = migration_cost[distance];
-			distance++;
-		}
-	}
-	/*
-	 * Print the matrix:
-	 */
-	if (migration_debug)
-		printk("migration: max_cache_size: %d, cpu: %d MHz:\n",
-			max_cache_size,
-#ifdef CONFIG_X86
-			cpu_khz/1000
-#else
-			-1
-#endif
-		);
-	if (system_state == SYSTEM_BOOTING && num_online_cpus() > 1) {
-		printk("migration_cost=");
-		for (distance = 0; distance <= max_distance; distance++) {
-			if (distance)
-				printk(",");
-			printk("%ld", (long)migration_cost[distance] / 1000);
-		}
-		printk("\n");
-	}
-	j1 = jiffies;
-	if (migration_debug)
-		printk("migration: %ld seconds\n", (j1-j0) / HZ);
-
-	/*
-	 * Move back to the original CPU. NUMA-Q gets confused
-	 * if we migrate to another quad during bootup.
-	 */
-	if (raw_smp_processor_id() != orig_cpu) {
-		cpumask_t mask = cpumask_of_cpu(orig_cpu),
-			saved_mask = current->cpus_allowed;
-
-		set_cpus_allowed(current, mask);
-		set_cpus_allowed(current, saved_mask);
-	}
-}
-
 #ifdef CONFIG_NUMA
 
 /**
@@ -6521,7 +5791,6 @@
 static int build_sched_domains(const cpumask_t *cpu_map)
 {
 	int i;
-	struct sched_domain *sd;
 #ifdef CONFIG_NUMA
 	struct sched_group **sched_group_nodes = NULL;
 	int sd_allnodes = 0;
@@ -6529,7 +5798,7 @@
 	/*
 	 * Allocate the per-node list of sched groups
 	 */
-	sched_group_nodes = kzalloc(sizeof(struct sched_group*)*MAX_NUMNODES,
+	sched_group_nodes = kzalloc(sizeof(struct sched_group *)*MAX_NUMNODES,
 					   GFP_KERNEL);
 	if (!sched_group_nodes) {
 		printk(KERN_WARNING "Can not alloc sched group node list\n");
@@ -6548,8 +5817,8 @@
 		cpus_and(nodemask, nodemask, *cpu_map);
 
 #ifdef CONFIG_NUMA
-		if (cpus_weight(*cpu_map)
-				> SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
+		if (cpus_weight(*cpu_map) >
+				SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
 			sd = &per_cpu(allnodes_domains, i);
 			*sd = SD_ALLNODES_INIT;
 			sd->span = *cpu_map;
@@ -6608,7 +5877,8 @@
 		if (i != first_cpu(this_sibling_map))
 			continue;
 
-		init_sched_build_groups(this_sibling_map, cpu_map, &cpu_to_cpu_group);
+		init_sched_build_groups(this_sibling_map, cpu_map,
+					&cpu_to_cpu_group);
 	}
 #endif
 
@@ -6619,11 +5889,11 @@
 		cpus_and(this_core_map, this_core_map, *cpu_map);
 		if (i != first_cpu(this_core_map))
 			continue;
-		init_sched_build_groups(this_core_map, cpu_map, &cpu_to_core_group);
+		init_sched_build_groups(this_core_map, cpu_map,
+					&cpu_to_core_group);
 	}
 #endif
 
-
 	/* Set up physical groups */
 	for (i = 0; i < MAX_NUMNODES; i++) {
 		cpumask_t nodemask = node_to_cpumask(i);
@@ -6638,7 +5908,8 @@
 #ifdef CONFIG_NUMA
 	/* Set up node groups */
 	if (sd_allnodes)
-		init_sched_build_groups(*cpu_map, cpu_map, &cpu_to_allnodes_group);
+		init_sched_build_groups(*cpu_map, cpu_map,
+					&cpu_to_allnodes_group);
 
 	for (i = 0; i < MAX_NUMNODES; i++) {
 		/* Set up node groups */
@@ -6666,6 +5937,7 @@
 		sched_group_nodes[i] = sg;
 		for_each_cpu_mask(j, nodemask) {
 			struct sched_domain *sd;
+
 			sd = &per_cpu(node_domains, j);
 			sd->groups = sg;
 		}
@@ -6710,19 +5982,22 @@
 	/* Calculate CPU power for physical packages and nodes */
 #ifdef CONFIG_SCHED_SMT
 	for_each_cpu_mask(i, *cpu_map) {
-		sd = &per_cpu(cpu_domains, i);
+		struct sched_domain *sd = &per_cpu(cpu_domains, i);
+
 		init_sched_groups_power(i, sd);
 	}
 #endif
 #ifdef CONFIG_SCHED_MC
 	for_each_cpu_mask(i, *cpu_map) {
-		sd = &per_cpu(core_domains, i);
+		struct sched_domain *sd = &per_cpu(core_domains, i);
+
 		init_sched_groups_power(i, sd);
 	}
 #endif
 
 	for_each_cpu_mask(i, *cpu_map) {
-		sd = &per_cpu(phys_domains, i);
+		struct sched_domain *sd = &per_cpu(phys_domains, i);
+
 		init_sched_groups_power(i, sd);
 	}
 
@@ -6750,10 +6025,6 @@
 #endif
 		cpu_attach_domain(sd, i);
 	}
-	/*
-	 * Tune cache-hot values:
-	 */
-	calibrate_migration_costs(cpu_map);
 
 	return 0;
 
@@ -6960,10 +6231,12 @@
 	/* Move init over to a non-isolated CPU */
 	if (set_cpus_allowed(current, non_isolated_cpus) < 0)
 		BUG();
+	sched_init_granularity();
 }
 #else
 void __init sched_init_smp(void)
 {
+	sched_init_granularity();
 }
 #endif /* CONFIG_SMP */
 
@@ -6977,28 +6250,51 @@
 		&& addr < (unsigned long)__sched_text_end);
 }
 
+static inline void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
+{
+	cfs_rq->tasks_timeline = RB_ROOT;
+	cfs_rq->fair_clock = 1;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	cfs_rq->rq = rq;
+#endif
+}
+
 void __init sched_init(void)
 {
-	int i, j, k;
+	u64 now = sched_clock();
 	int highest_cpu = 0;
+	int i, j;
+
+	/*
+	 * Link up the scheduling class hierarchy:
+	 */
+	rt_sched_class.next = &fair_sched_class;
+	fair_sched_class.next = &idle_sched_class;
+	idle_sched_class.next = NULL;
 
 	for_each_possible_cpu(i) {
-		struct prio_array *array;
+		struct rt_prio_array *array;
 		struct rq *rq;
 
 		rq = cpu_rq(i);
 		spin_lock_init(&rq->lock);
 		lockdep_set_class(&rq->lock, &rq->rq_lock_key);
 		rq->nr_running = 0;
-		rq->active = rq->arrays;
-		rq->expired = rq->arrays + 1;
-		rq->best_expired_prio = MAX_PRIO;
+		rq->clock = 1;
+		init_cfs_rq(&rq->cfs, rq);
+#ifdef CONFIG_FAIR_GROUP_SCHED
+		INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+		list_add(&rq->cfs.leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
+#endif
+		rq->ls.load_update_last = now;
+		rq->ls.load_update_start = now;
 
+		for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
+			rq->cpu_load[j] = 0;
 #ifdef CONFIG_SMP
 		rq->sd = NULL;
-		for (j = 1; j < 3; j++)
-			rq->cpu_load[j] = 0;
 		rq->active_balance = 0;
+		rq->next_balance = jiffies;
 		rq->push_cpu = 0;
 		rq->cpu = i;
 		rq->migration_thread = NULL;
@@ -7006,16 +6302,14 @@
 #endif
 		atomic_set(&rq->nr_iowait, 0);
 
-		for (j = 0; j < 2; j++) {
-			array = rq->arrays + j;
-			for (k = 0; k < MAX_PRIO; k++) {
-				INIT_LIST_HEAD(array->queue + k);
-				__clear_bit(k, array->bitmap);
-			}
-			// delimiter for bitsearch
-			__set_bit(MAX_PRIO, array->bitmap);
+		array = &rq->rt.active;
+		for (j = 0; j < MAX_RT_PRIO; j++) {
+			INIT_LIST_HEAD(array->queue + j);
+			__clear_bit(j, array->bitmap);
 		}
 		highest_cpu = i;
+		/* delimiter for bitsearch: */
+		__set_bit(MAX_RT_PRIO, array->bitmap);
 	}
 
 	set_load_weight(&init_task);
@@ -7042,6 +6336,10 @@
 	 * when this runqueue becomes "idle".
 	 */
 	init_idle(current, smp_processor_id());
+	/*
+	 * During early bootup we pretend to be a normal task:
+	 */
+	current->sched_class = &fair_sched_class;
 }
 
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
@@ -7072,31 +6370,59 @@
 #ifdef CONFIG_MAGIC_SYSRQ
 void normalize_rt_tasks(void)
 {
-	struct prio_array *array;
-	struct task_struct *p;
+	struct task_struct *g, *p;
 	unsigned long flags;
 	struct rq *rq;
+	int on_rq;
 
 	read_lock_irq(&tasklist_lock);
-	for_each_process(p) {
-		if (!rt_task(p))
+	do_each_thread(g, p) {
+		p->se.fair_key			= 0;
+		p->se.wait_runtime		= 0;
+		p->se.wait_start_fair		= 0;
+		p->se.wait_start		= 0;
+		p->se.exec_start		= 0;
+		p->se.sleep_start		= 0;
+		p->se.sleep_start_fair		= 0;
+		p->se.block_start		= 0;
+		task_rq(p)->cfs.fair_clock	= 0;
+		task_rq(p)->clock		= 0;
+
+		if (!rt_task(p)) {
+			/*
+			 * Renice negative nice level userspace
+			 * tasks back to 0:
+			 */
+			if (TASK_NICE(p) < 0 && p->mm)
+				set_user_nice(p, 0);
 			continue;
+		}
 
 		spin_lock_irqsave(&p->pi_lock, flags);
 		rq = __task_rq_lock(p);
+#ifdef CONFIG_SMP
+		/*
+		 * Do not touch the migration thread:
+		 */
+		if (p == rq->migration_thread)
+			goto out_unlock;
+#endif
 
-		array = p->array;
-		if (array)
-			deactivate_task(p, task_rq(p));
-		__setscheduler(p, SCHED_NORMAL, 0);
-		if (array) {
-			__activate_task(p, task_rq(p));
+		on_rq = p->se.on_rq;
+		if (on_rq)
+			deactivate_task(task_rq(p), p, 0);
+		__setscheduler(rq, p, SCHED_NORMAL, 0);
+		if (on_rq) {
+			activate_task(task_rq(p), p, 0);
 			resched_task(rq->curr);
 		}
-
+#ifdef CONFIG_SMP
+ out_unlock:
+#endif
 		__task_rq_unlock(rq);
 		spin_unlock_irqrestore(&p->pi_lock, flags);
-	}
+	} while_each_thread(g, p);
+
 	read_unlock_irq(&tasklist_lock);
 }
 
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
new file mode 100644
index 0000000..29f2c21
--- /dev/null
+++ b/kernel/sched_debug.c
@@ -0,0 +1,275 @@
+/*
+ * kernel/time/sched_debug.c
+ *
+ * Print the CFS rbtree
+ *
+ * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
+ *
+ * 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/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/utsname.h>
+
+/*
+ * This allows printing both to /proc/sched_debug and
+ * to the console
+ */
+#define SEQ_printf(m, x...)			\
+ do {						\
+	if (m)					\
+		seq_printf(m, x);		\
+	else					\
+		printk(x);			\
+ } while (0)
+
+static void
+print_task(struct seq_file *m, struct rq *rq, struct task_struct *p, u64 now)
+{
+	if (rq->curr == p)
+		SEQ_printf(m, "R");
+	else
+		SEQ_printf(m, " ");
+
+	SEQ_printf(m, "%15s %5d %15Ld %13Ld %13Ld %9Ld %5d "
+		      "%15Ld %15Ld %15Ld %15Ld %15Ld\n",
+		p->comm, p->pid,
+		(long long)p->se.fair_key,
+		(long long)(p->se.fair_key - rq->cfs.fair_clock),
+		(long long)p->se.wait_runtime,
+		(long long)(p->nvcsw + p->nivcsw),
+		p->prio,
+		(long long)p->se.sum_exec_runtime,
+		(long long)p->se.sum_wait_runtime,
+		(long long)p->se.sum_sleep_runtime,
+		(long long)p->se.wait_runtime_overruns,
+		(long long)p->se.wait_runtime_underruns);
+}
+
+static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu, u64 now)
+{
+	struct task_struct *g, *p;
+
+	SEQ_printf(m,
+	"\nrunnable tasks:\n"
+	"            task   PID        tree-key         delta       waiting"
+	"  switches  prio"
+	"        sum-exec        sum-wait       sum-sleep"
+	"    wait-overrun   wait-underrun\n"
+	"------------------------------------------------------------------"
+	"----------------"
+	"------------------------------------------------"
+	"--------------------------------\n");
+
+	read_lock_irq(&tasklist_lock);
+
+	do_each_thread(g, p) {
+		if (!p->se.on_rq || task_cpu(p) != rq_cpu)
+			continue;
+
+		print_task(m, rq, p, now);
+	} while_each_thread(g, p);
+
+	read_unlock_irq(&tasklist_lock);
+}
+
+static void
+print_cfs_rq_runtime_sum(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
+{
+	s64 wait_runtime_rq_sum = 0;
+	struct task_struct *p;
+	struct rb_node *curr;
+	unsigned long flags;
+	struct rq *rq = &per_cpu(runqueues, cpu);
+
+	spin_lock_irqsave(&rq->lock, flags);
+	curr = first_fair(cfs_rq);
+	while (curr) {
+		p = rb_entry(curr, struct task_struct, se.run_node);
+		wait_runtime_rq_sum += p->se.wait_runtime;
+
+		curr = rb_next(curr);
+	}
+	spin_unlock_irqrestore(&rq->lock, flags);
+
+	SEQ_printf(m, "  .%-30s: %Ld\n", "wait_runtime_rq_sum",
+		(long long)wait_runtime_rq_sum);
+}
+
+void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now)
+{
+	SEQ_printf(m, "\ncfs_rq %p\n", cfs_rq);
+
+#define P(x) \
+	SEQ_printf(m, "  .%-30s: %Ld\n", #x, (long long)(cfs_rq->x))
+
+	P(fair_clock);
+	P(exec_clock);
+	P(wait_runtime);
+	P(wait_runtime_overruns);
+	P(wait_runtime_underruns);
+	P(sleeper_bonus);
+#undef P
+
+	print_cfs_rq_runtime_sum(m, cpu, cfs_rq);
+}
+
+static void print_cpu(struct seq_file *m, int cpu, u64 now)
+{
+	struct rq *rq = &per_cpu(runqueues, cpu);
+
+#ifdef CONFIG_X86
+	{
+		unsigned int freq = cpu_khz ? : 1;
+
+		SEQ_printf(m, "\ncpu#%d, %u.%03u MHz\n",
+			   cpu, freq / 1000, (freq % 1000));
+	}
+#else
+	SEQ_printf(m, "\ncpu#%d\n", cpu);
+#endif
+
+#define P(x) \
+	SEQ_printf(m, "  .%-30s: %Ld\n", #x, (long long)(rq->x))
+
+	P(nr_running);
+	SEQ_printf(m, "  .%-30s: %lu\n", "load",
+		   rq->ls.load.weight);
+	P(ls.delta_fair);
+	P(ls.delta_exec);
+	P(nr_switches);
+	P(nr_load_updates);
+	P(nr_uninterruptible);
+	SEQ_printf(m, "  .%-30s: %lu\n", "jiffies", jiffies);
+	P(next_balance);
+	P(curr->pid);
+	P(clock);
+	P(prev_clock_raw);
+	P(clock_warps);
+	P(clock_overflows);
+	P(clock_unstable_events);
+	P(clock_max_delta);
+	P(cpu_load[0]);
+	P(cpu_load[1]);
+	P(cpu_load[2]);
+	P(cpu_load[3]);
+	P(cpu_load[4]);
+#undef P
+
+	print_cfs_stats(m, cpu, now);
+
+	print_rq(m, rq, cpu, now);
+}
+
+static int sched_debug_show(struct seq_file *m, void *v)
+{
+	u64 now = ktime_to_ns(ktime_get());
+	int cpu;
+
+	SEQ_printf(m, "Sched Debug Version: v0.05, %s %.*s\n",
+		init_utsname()->release,
+		(int)strcspn(init_utsname()->version, " "),
+		init_utsname()->version);
+
+	SEQ_printf(m, "now at %Lu nsecs\n", (unsigned long long)now);
+
+	for_each_online_cpu(cpu)
+		print_cpu(m, cpu, now);
+
+	SEQ_printf(m, "\n");
+
+	return 0;
+}
+
+void sysrq_sched_debug_show(void)
+{
+	sched_debug_show(NULL, NULL);
+}
+
+static int sched_debug_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, sched_debug_show, NULL);
+}
+
+static struct file_operations sched_debug_fops = {
+	.open		= sched_debug_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int __init init_sched_debug_procfs(void)
+{
+	struct proc_dir_entry *pe;
+
+	pe = create_proc_entry("sched_debug", 0644, NULL);
+	if (!pe)
+		return -ENOMEM;
+
+	pe->proc_fops = &sched_debug_fops;
+
+	return 0;
+}
+
+__initcall(init_sched_debug_procfs);
+
+void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+{
+	unsigned long flags;
+	int num_threads = 1;
+
+	rcu_read_lock();
+	if (lock_task_sighand(p, &flags)) {
+		num_threads = atomic_read(&p->signal->count);
+		unlock_task_sighand(p, &flags);
+	}
+	rcu_read_unlock();
+
+	SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid, num_threads);
+	SEQ_printf(m, "----------------------------------------------\n");
+#define P(F) \
+	SEQ_printf(m, "%-25s:%20Ld\n", #F, (long long)p->F)
+
+	P(se.wait_start);
+	P(se.wait_start_fair);
+	P(se.exec_start);
+	P(se.sleep_start);
+	P(se.sleep_start_fair);
+	P(se.block_start);
+	P(se.sleep_max);
+	P(se.block_max);
+	P(se.exec_max);
+	P(se.wait_max);
+	P(se.wait_runtime);
+	P(se.wait_runtime_overruns);
+	P(se.wait_runtime_underruns);
+	P(se.sum_wait_runtime);
+	P(se.sum_exec_runtime);
+	SEQ_printf(m, "%-25s:%20Ld\n",
+		   "nr_switches", (long long)(p->nvcsw + p->nivcsw));
+	P(se.load.weight);
+	P(policy);
+	P(prio);
+#undef P
+
+	{
+		u64 t0, t1;
+
+		t0 = sched_clock();
+		t1 = sched_clock();
+		SEQ_printf(m, "%-25s:%20Ld\n",
+			   "clock-delta", (long long)(t1-t0));
+	}
+}
+
+void proc_sched_set_task(struct task_struct *p)
+{
+	p->se.sleep_max = p->se.block_max = p->se.exec_max = p->se.wait_max = 0;
+	p->se.wait_runtime_overruns = p->se.wait_runtime_underruns = 0;
+	p->se.sum_exec_runtime = 0;
+}
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
new file mode 100644
index 0000000..6971db0
--- /dev/null
+++ b/kernel/sched_fair.c
@@ -0,0 +1,1131 @@
+/*
+ * Completely Fair Scheduling (CFS) Class (SCHED_NORMAL/SCHED_BATCH)
+ *
+ *  Copyright (C) 2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ *  Interactivity improvements by Mike Galbraith
+ *  (C) 2007 Mike Galbraith <efault@gmx.de>
+ *
+ *  Various enhancements by Dmitry Adamushko.
+ *  (C) 2007 Dmitry Adamushko <dmitry.adamushko@gmail.com>
+ *
+ *  Group scheduling enhancements by Srivatsa Vaddagiri
+ *  Copyright IBM Corporation, 2007
+ *  Author: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
+ *
+ *  Scaled math optimizations by Thomas Gleixner
+ *  Copyright (C) 2007, Thomas Gleixner <tglx@linutronix.de>
+ */
+
+/*
+ * Preemption granularity:
+ * (default: 2 msec, units: nanoseconds)
+ *
+ * NOTE: this granularity value is not the same as the concept of
+ * 'timeslice length' - timeslices in CFS will typically be somewhat
+ * larger than this value. (to see the precise effective timeslice
+ * length of your workload, run vmstat and monitor the context-switches
+ * field)
+ *
+ * On SMP systems the value of this is multiplied by the log2 of the
+ * number of CPUs. (i.e. factor 2x on 2-way systems, 3x on 4-way
+ * systems, 4x on 8-way systems, 5x on 16-way systems, etc.)
+ */
+unsigned int sysctl_sched_granularity __read_mostly = 2000000000ULL/HZ;
+
+/*
+ * SCHED_BATCH wake-up granularity.
+ * (default: 10 msec, units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+unsigned int sysctl_sched_batch_wakeup_granularity __read_mostly =
+							10000000000ULL/HZ;
+
+/*
+ * SCHED_OTHER wake-up granularity.
+ * (default: 1 msec, units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+unsigned int sysctl_sched_wakeup_granularity __read_mostly = 1000000000ULL/HZ;
+
+unsigned int sysctl_sched_stat_granularity __read_mostly;
+
+/*
+ * Initialized in sched_init_granularity():
+ */
+unsigned int sysctl_sched_runtime_limit __read_mostly;
+
+/*
+ * Debugging: various feature bits
+ */
+enum {
+	SCHED_FEAT_FAIR_SLEEPERS	= 1,
+	SCHED_FEAT_SLEEPER_AVG		= 2,
+	SCHED_FEAT_SLEEPER_LOAD_AVG	= 4,
+	SCHED_FEAT_PRECISE_CPU_LOAD	= 8,
+	SCHED_FEAT_START_DEBIT		= 16,
+	SCHED_FEAT_SKIP_INITIAL		= 32,
+};
+
+unsigned int sysctl_sched_features __read_mostly =
+		SCHED_FEAT_FAIR_SLEEPERS	*1 |
+		SCHED_FEAT_SLEEPER_AVG		*1 |
+		SCHED_FEAT_SLEEPER_LOAD_AVG	*1 |
+		SCHED_FEAT_PRECISE_CPU_LOAD	*1 |
+		SCHED_FEAT_START_DEBIT		*1 |
+		SCHED_FEAT_SKIP_INITIAL		*0;
+
+extern struct sched_class fair_sched_class;
+
+/**************************************************************
+ * CFS operations on generic schedulable entities:
+ */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+/* cpu runqueue to which this cfs_rq is attached */
+static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+{
+	return cfs_rq->rq;
+}
+
+/* currently running entity (if any) on this cfs_rq */
+static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq)
+{
+	return cfs_rq->curr;
+}
+
+/* An entity is a task if it doesn't "own" a runqueue */
+#define entity_is_task(se)	(!se->my_q)
+
+static inline void
+set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	cfs_rq->curr = se;
+}
+
+#else	/* CONFIG_FAIR_GROUP_SCHED */
+
+static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+{
+	return container_of(cfs_rq, struct rq, cfs);
+}
+
+static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq)
+{
+	struct rq *rq = rq_of(cfs_rq);
+
+	if (unlikely(rq->curr->sched_class != &fair_sched_class))
+		return NULL;
+
+	return &rq->curr->se;
+}
+
+#define entity_is_task(se)	1
+
+static inline void
+set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se) { }
+
+#endif	/* CONFIG_FAIR_GROUP_SCHED */
+
+static inline struct task_struct *task_of(struct sched_entity *se)
+{
+	return container_of(se, struct task_struct, se);
+}
+
+
+/**************************************************************
+ * Scheduling class tree data structure manipulation methods:
+ */
+
+/*
+ * Enqueue an entity into the rb-tree:
+ */
+static inline void
+__enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
+	struct rb_node *parent = NULL;
+	struct sched_entity *entry;
+	s64 key = se->fair_key;
+	int leftmost = 1;
+
+	/*
+	 * Find the right place in the rbtree:
+	 */
+	while (*link) {
+		parent = *link;
+		entry = rb_entry(parent, struct sched_entity, run_node);
+		/*
+		 * We dont care about collisions. Nodes with
+		 * the same key stay together.
+		 */
+		if (key - entry->fair_key < 0) {
+			link = &parent->rb_left;
+		} else {
+			link = &parent->rb_right;
+			leftmost = 0;
+		}
+	}
+
+	/*
+	 * Maintain a cache of leftmost tree entries (it is frequently
+	 * used):
+	 */
+	if (leftmost)
+		cfs_rq->rb_leftmost = &se->run_node;
+
+	rb_link_node(&se->run_node, parent, link);
+	rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline);
+	update_load_add(&cfs_rq->load, se->load.weight);
+	cfs_rq->nr_running++;
+	se->on_rq = 1;
+}
+
+static inline void
+__dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	if (cfs_rq->rb_leftmost == &se->run_node)
+		cfs_rq->rb_leftmost = rb_next(&se->run_node);
+	rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
+	update_load_sub(&cfs_rq->load, se->load.weight);
+	cfs_rq->nr_running--;
+	se->on_rq = 0;
+}
+
+static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq)
+{
+	return cfs_rq->rb_leftmost;
+}
+
+static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq)
+{
+	return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node);
+}
+
+/**************************************************************
+ * Scheduling class statistics methods:
+ */
+
+/*
+ * We rescale the rescheduling granularity of tasks according to their
+ * nice level, but only linearly, not exponentially:
+ */
+static long
+niced_granularity(struct sched_entity *curr, unsigned long granularity)
+{
+	u64 tmp;
+
+	/*
+	 * Negative nice levels get the same granularity as nice-0:
+	 */
+	if (likely(curr->load.weight >= NICE_0_LOAD))
+		return granularity;
+	/*
+	 * Positive nice level tasks get linearly finer
+	 * granularity:
+	 */
+	tmp = curr->load.weight * (u64)granularity;
+
+	/*
+	 * It will always fit into 'long':
+	 */
+	return (long) (tmp >> NICE_0_SHIFT);
+}
+
+static inline void
+limit_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	long limit = sysctl_sched_runtime_limit;
+
+	/*
+	 * Niced tasks have the same history dynamic range as
+	 * non-niced tasks:
+	 */
+	if (unlikely(se->wait_runtime > limit)) {
+		se->wait_runtime = limit;
+		schedstat_inc(se, wait_runtime_overruns);
+		schedstat_inc(cfs_rq, wait_runtime_overruns);
+	}
+	if (unlikely(se->wait_runtime < -limit)) {
+		se->wait_runtime = -limit;
+		schedstat_inc(se, wait_runtime_underruns);
+		schedstat_inc(cfs_rq, wait_runtime_underruns);
+	}
+}
+
+static inline void
+__add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta)
+{
+	se->wait_runtime += delta;
+	schedstat_add(se, sum_wait_runtime, delta);
+	limit_wait_runtime(cfs_rq, se);
+}
+
+static void
+add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta)
+{
+	schedstat_add(cfs_rq, wait_runtime, -se->wait_runtime);
+	__add_wait_runtime(cfs_rq, se, delta);
+	schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
+}
+
+/*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+ */
+static inline void
+__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr, u64 now)
+{
+	unsigned long delta, delta_exec, delta_fair;
+	long delta_mine;
+	struct load_weight *lw = &cfs_rq->load;
+	unsigned long load = lw->weight;
+
+	if (unlikely(!load))
+		return;
+
+	delta_exec = curr->delta_exec;
+#ifdef CONFIG_SCHEDSTATS
+	if (unlikely(delta_exec > curr->exec_max))
+		curr->exec_max = delta_exec;
+#endif
+
+	curr->sum_exec_runtime += delta_exec;
+	cfs_rq->exec_clock += delta_exec;
+
+	delta_fair = calc_delta_fair(delta_exec, lw);
+	delta_mine = calc_delta_mine(delta_exec, curr->load.weight, lw);
+
+	if (cfs_rq->sleeper_bonus > sysctl_sched_stat_granularity) {
+		delta = calc_delta_mine(cfs_rq->sleeper_bonus,
+					curr->load.weight, lw);
+		if (unlikely(delta > cfs_rq->sleeper_bonus))
+			delta = cfs_rq->sleeper_bonus;
+
+		cfs_rq->sleeper_bonus -= delta;
+		delta_mine -= delta;
+	}
+
+	cfs_rq->fair_clock += delta_fair;
+	/*
+	 * We executed delta_exec amount of time on the CPU,
+	 * but we were only entitled to delta_mine amount of
+	 * time during that period (if nr_running == 1 then
+	 * the two values are equal)
+	 * [Note: delta_mine - delta_exec is negative]:
+	 */
+	add_wait_runtime(cfs_rq, curr, delta_mine - delta_exec);
+}
+
+static void update_curr(struct cfs_rq *cfs_rq, u64 now)
+{
+	struct sched_entity *curr = cfs_rq_curr(cfs_rq);
+	unsigned long delta_exec;
+
+	if (unlikely(!curr))
+		return;
+
+	/*
+	 * Get the amount of time the current task was running
+	 * since the last time we changed load (this cannot
+	 * overflow on 32 bits):
+	 */
+	delta_exec = (unsigned long)(now - curr->exec_start);
+
+	curr->delta_exec += delta_exec;
+
+	if (unlikely(curr->delta_exec > sysctl_sched_stat_granularity)) {
+		__update_curr(cfs_rq, curr, now);
+		curr->delta_exec = 0;
+	}
+	curr->exec_start = now;
+}
+
+static inline void
+update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	se->wait_start_fair = cfs_rq->fair_clock;
+	se->wait_start = now;
+}
+
+/*
+ * We calculate fair deltas here, so protect against the random effects
+ * of a multiplication overflow by capping it to the runtime limit:
+ */
+#if BITS_PER_LONG == 32
+static inline unsigned long
+calc_weighted(unsigned long delta, unsigned long weight, int shift)
+{
+	u64 tmp = (u64)delta * weight >> shift;
+
+	if (unlikely(tmp > sysctl_sched_runtime_limit*2))
+		return sysctl_sched_runtime_limit*2;
+	return tmp;
+}
+#else
+static inline unsigned long
+calc_weighted(unsigned long delta, unsigned long weight, int shift)
+{
+	return delta * weight >> shift;
+}
+#endif
+
+/*
+ * Task is being enqueued - update stats:
+ */
+static void
+update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	s64 key;
+
+	/*
+	 * Are we enqueueing a waiting task? (for current tasks
+	 * a dequeue/enqueue event is a NOP)
+	 */
+	if (se != cfs_rq_curr(cfs_rq))
+		update_stats_wait_start(cfs_rq, se, now);
+	/*
+	 * Update the key:
+	 */
+	key = cfs_rq->fair_clock;
+
+	/*
+	 * Optimize the common nice 0 case:
+	 */
+	if (likely(se->load.weight == NICE_0_LOAD)) {
+		key -= se->wait_runtime;
+	} else {
+		u64 tmp;
+
+		if (se->wait_runtime < 0) {
+			tmp = -se->wait_runtime;
+			key += (tmp * se->load.inv_weight) >>
+					(WMULT_SHIFT - NICE_0_SHIFT);
+		} else {
+			tmp = se->wait_runtime;
+			key -= (tmp * se->load.weight) >> NICE_0_SHIFT;
+		}
+	}
+
+	se->fair_key = key;
+}
+
+/*
+ * Note: must be called with a freshly updated rq->fair_clock.
+ */
+static inline void
+__update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	unsigned long delta_fair = se->delta_fair_run;
+
+#ifdef CONFIG_SCHEDSTATS
+	{
+		s64 delta_wait = now - se->wait_start;
+		if (unlikely(delta_wait > se->wait_max))
+			se->wait_max = delta_wait;
+	}
+#endif
+
+	if (unlikely(se->load.weight != NICE_0_LOAD))
+		delta_fair = calc_weighted(delta_fair, se->load.weight,
+							NICE_0_SHIFT);
+
+	add_wait_runtime(cfs_rq, se, delta_fair);
+}
+
+static void
+update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	unsigned long delta_fair;
+
+	delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit),
+			(u64)(cfs_rq->fair_clock - se->wait_start_fair));
+
+	se->delta_fair_run += delta_fair;
+	if (unlikely(abs(se->delta_fair_run) >=
+				sysctl_sched_stat_granularity)) {
+		__update_stats_wait_end(cfs_rq, se, now);
+		se->delta_fair_run = 0;
+	}
+
+	se->wait_start_fair = 0;
+	se->wait_start = 0;
+}
+
+static inline void
+update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	update_curr(cfs_rq, now);
+	/*
+	 * Mark the end of the wait period if dequeueing a
+	 * waiting task:
+	 */
+	if (se != cfs_rq_curr(cfs_rq))
+		update_stats_wait_end(cfs_rq, se, now);
+}
+
+/*
+ * We are picking a new current task - update its stats:
+ */
+static inline void
+update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	/*
+	 * We are starting a new run period:
+	 */
+	se->exec_start = now;
+}
+
+/*
+ * We are descheduling a task - update its stats:
+ */
+static inline void
+update_stats_curr_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	se->exec_start = 0;
+}
+
+/**************************************************
+ * Scheduling class queueing methods:
+ */
+
+static void
+__enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	unsigned long load = cfs_rq->load.weight, delta_fair;
+	long prev_runtime;
+
+	if (sysctl_sched_features & SCHED_FEAT_SLEEPER_LOAD_AVG)
+		load = rq_of(cfs_rq)->cpu_load[2];
+
+	delta_fair = se->delta_fair_sleep;
+
+	/*
+	 * Fix up delta_fair with the effect of us running
+	 * during the whole sleep period:
+	 */
+	if (sysctl_sched_features & SCHED_FEAT_SLEEPER_AVG)
+		delta_fair = div64_likely32((u64)delta_fair * load,
+						load + se->load.weight);
+
+	if (unlikely(se->load.weight != NICE_0_LOAD))
+		delta_fair = calc_weighted(delta_fair, se->load.weight,
+							NICE_0_SHIFT);
+
+	prev_runtime = se->wait_runtime;
+	__add_wait_runtime(cfs_rq, se, delta_fair);
+	delta_fair = se->wait_runtime - prev_runtime;
+
+	/*
+	 * Track the amount of bonus we've given to sleepers:
+	 */
+	cfs_rq->sleeper_bonus += delta_fair;
+
+	schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
+}
+
+static void
+enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	struct task_struct *tsk = task_of(se);
+	unsigned long delta_fair;
+
+	if ((entity_is_task(se) && tsk->policy == SCHED_BATCH) ||
+			 !(sysctl_sched_features & SCHED_FEAT_FAIR_SLEEPERS))
+		return;
+
+	delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit),
+		(u64)(cfs_rq->fair_clock - se->sleep_start_fair));
+
+	se->delta_fair_sleep += delta_fair;
+	if (unlikely(abs(se->delta_fair_sleep) >=
+				sysctl_sched_stat_granularity)) {
+		__enqueue_sleeper(cfs_rq, se, now);
+		se->delta_fair_sleep = 0;
+	}
+
+	se->sleep_start_fair = 0;
+
+#ifdef CONFIG_SCHEDSTATS
+	if (se->sleep_start) {
+		u64 delta = now - se->sleep_start;
+
+		if ((s64)delta < 0)
+			delta = 0;
+
+		if (unlikely(delta > se->sleep_max))
+			se->sleep_max = delta;
+
+		se->sleep_start = 0;
+		se->sum_sleep_runtime += delta;
+	}
+	if (se->block_start) {
+		u64 delta = now - se->block_start;
+
+		if ((s64)delta < 0)
+			delta = 0;
+
+		if (unlikely(delta > se->block_max))
+			se->block_max = delta;
+
+		se->block_start = 0;
+		se->sum_sleep_runtime += delta;
+	}
+#endif
+}
+
+static void
+enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+	       int wakeup, u64 now)
+{
+	/*
+	 * Update the fair clock.
+	 */
+	update_curr(cfs_rq, now);
+
+	if (wakeup)
+		enqueue_sleeper(cfs_rq, se, now);
+
+	update_stats_enqueue(cfs_rq, se, now);
+	__enqueue_entity(cfs_rq, se);
+}
+
+static void
+dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+	       int sleep, u64 now)
+{
+	update_stats_dequeue(cfs_rq, se, now);
+	if (sleep) {
+		se->sleep_start_fair = cfs_rq->fair_clock;
+#ifdef CONFIG_SCHEDSTATS
+		if (entity_is_task(se)) {
+			struct task_struct *tsk = task_of(se);
+
+			if (tsk->state & TASK_INTERRUPTIBLE)
+				se->sleep_start = now;
+			if (tsk->state & TASK_UNINTERRUPTIBLE)
+				se->block_start = now;
+		}
+		cfs_rq->wait_runtime -= se->wait_runtime;
+#endif
+	}
+	__dequeue_entity(cfs_rq, se);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void
+__check_preempt_curr_fair(struct cfs_rq *cfs_rq, struct sched_entity *se,
+			  struct sched_entity *curr, unsigned long granularity)
+{
+	s64 __delta = curr->fair_key - se->fair_key;
+
+	/*
+	 * Take scheduling granularity into account - do not
+	 * preempt the current task unless the best task has
+	 * a larger than sched_granularity fairness advantage:
+	 */
+	if (__delta > niced_granularity(curr, granularity))
+		resched_task(rq_of(cfs_rq)->curr);
+}
+
+static inline void
+set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	/*
+	 * Any task has to be enqueued before it get to execute on
+	 * a CPU. So account for the time it spent waiting on the
+	 * runqueue. (note, here we rely on pick_next_task() having
+	 * done a put_prev_task_fair() shortly before this, which
+	 * updated rq->fair_clock - used by update_stats_wait_end())
+	 */
+	update_stats_wait_end(cfs_rq, se, now);
+	update_stats_curr_start(cfs_rq, se, now);
+	set_cfs_rq_curr(cfs_rq, se);
+}
+
+static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq, u64 now)
+{
+	struct sched_entity *se = __pick_next_entity(cfs_rq);
+
+	set_next_entity(cfs_rq, se, now);
+
+	return se;
+}
+
+static void
+put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev, u64 now)
+{
+	/*
+	 * If still on the runqueue then deactivate_task()
+	 * was not called and update_curr() has to be done:
+	 */
+	if (prev->on_rq)
+		update_curr(cfs_rq, now);
+
+	update_stats_curr_end(cfs_rq, prev, now);
+
+	if (prev->on_rq)
+		update_stats_wait_start(cfs_rq, prev, now);
+	set_cfs_rq_curr(cfs_rq, NULL);
+}
+
+static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
+{
+	struct rq *rq = rq_of(cfs_rq);
+	struct sched_entity *next;
+	u64 now = __rq_clock(rq);
+
+	/*
+	 * Dequeue and enqueue the task to update its
+	 * position within the tree:
+	 */
+	dequeue_entity(cfs_rq, curr, 0, now);
+	enqueue_entity(cfs_rq, curr, 0, now);
+
+	/*
+	 * Reschedule if another task tops the current one.
+	 */
+	next = __pick_next_entity(cfs_rq);
+	if (next == curr)
+		return;
+
+	__check_preempt_curr_fair(cfs_rq, next, curr, sysctl_sched_granularity);
+}
+
+/**************************************************
+ * CFS operations on tasks:
+ */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+/* Walk up scheduling entities hierarchy */
+#define for_each_sched_entity(se) \
+		for (; se; se = se->parent)
+
+static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+{
+	return p->se.cfs_rq;
+}
+
+/* runqueue on which this entity is (to be) queued */
+static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+{
+	return se->cfs_rq;
+}
+
+/* runqueue "owned" by this group */
+static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+{
+	return grp->my_q;
+}
+
+/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
+ * another cpu ('this_cpu')
+ */
+static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+{
+	/* A later patch will take group into account */
+	return &cpu_rq(this_cpu)->cfs;
+}
+
+/* Iterate thr' all leaf cfs_rq's on a runqueue */
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+	list_for_each_entry(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
+
+/* Do the two (enqueued) tasks belong to the same group ? */
+static inline int is_same_group(struct task_struct *curr, struct task_struct *p)
+{
+	if (curr->se.cfs_rq == p->se.cfs_rq)
+		return 1;
+
+	return 0;
+}
+
+#else	/* CONFIG_FAIR_GROUP_SCHED */
+
+#define for_each_sched_entity(se) \
+		for (; se; se = NULL)
+
+static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+{
+	return &task_rq(p)->cfs;
+}
+
+static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+{
+	struct task_struct *p = task_of(se);
+	struct rq *rq = task_rq(p);
+
+	return &rq->cfs;
+}
+
+/* runqueue "owned" by this group */
+static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+{
+	return NULL;
+}
+
+static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+{
+	return &cpu_rq(this_cpu)->cfs;
+}
+
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+		for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
+
+static inline int is_same_group(struct task_struct *curr, struct task_struct *p)
+{
+	return 1;
+}
+
+#endif	/* CONFIG_FAIR_GROUP_SCHED */
+
+/*
+ * The enqueue_task method is called before nr_running is
+ * increased. Here we update the fair scheduling stats and
+ * then put the task into the rbtree:
+ */
+static void
+enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+	struct cfs_rq *cfs_rq;
+	struct sched_entity *se = &p->se;
+
+	for_each_sched_entity(se) {
+		if (se->on_rq)
+			break;
+		cfs_rq = cfs_rq_of(se);
+		enqueue_entity(cfs_rq, se, wakeup, now);
+	}
+}
+
+/*
+ * The dequeue_task method is called before nr_running is
+ * decreased. We remove the task from the rbtree and
+ * update the fair scheduling stats:
+ */
+static void
+dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+	struct cfs_rq *cfs_rq;
+	struct sched_entity *se = &p->se;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		dequeue_entity(cfs_rq, se, sleep, now);
+		/* Don't dequeue parent if it has other entities besides us */
+		if (cfs_rq->load.weight)
+			break;
+	}
+}
+
+/*
+ * sched_yield() support is very simple - we dequeue and enqueue
+ */
+static void yield_task_fair(struct rq *rq, struct task_struct *p)
+{
+	struct cfs_rq *cfs_rq = task_cfs_rq(p);
+	u64 now = __rq_clock(rq);
+
+	/*
+	 * Dequeue and enqueue the task to update its
+	 * position within the tree:
+	 */
+	dequeue_entity(cfs_rq, &p->se, 0, now);
+	enqueue_entity(cfs_rq, &p->se, 0, now);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void check_preempt_curr_fair(struct rq *rq, struct task_struct *p)
+{
+	struct task_struct *curr = rq->curr;
+	struct cfs_rq *cfs_rq = task_cfs_rq(curr);
+	unsigned long gran;
+
+	if (unlikely(rt_prio(p->prio))) {
+		update_curr(cfs_rq, rq_clock(rq));
+		resched_task(curr);
+		return;
+	}
+
+	gran = sysctl_sched_wakeup_granularity;
+	/*
+	 * Batch tasks prefer throughput over latency:
+	 */
+	if (unlikely(p->policy == SCHED_BATCH))
+		gran = sysctl_sched_batch_wakeup_granularity;
+
+	if (is_same_group(curr, p))
+		__check_preempt_curr_fair(cfs_rq, &p->se, &curr->se, gran);
+}
+
+static struct task_struct *pick_next_task_fair(struct rq *rq, u64 now)
+{
+	struct cfs_rq *cfs_rq = &rq->cfs;
+	struct sched_entity *se;
+
+	if (unlikely(!cfs_rq->nr_running))
+		return NULL;
+
+	do {
+		se = pick_next_entity(cfs_rq, now);
+		cfs_rq = group_cfs_rq(se);
+	} while (cfs_rq);
+
+	return task_of(se);
+}
+
+/*
+ * Account for a descheduled task:
+ */
+static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, u64 now)
+{
+	struct sched_entity *se = &prev->se;
+	struct cfs_rq *cfs_rq;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		put_prev_entity(cfs_rq, se, now);
+	}
+}
+
+/**************************************************
+ * Fair scheduling class load-balancing methods:
+ */
+
+/*
+ * Load-balancing iterator. Note: while the runqueue stays locked
+ * during the whole iteration, the current task might be
+ * dequeued so the iterator has to be dequeue-safe. Here we
+ * achieve that by always pre-iterating before returning
+ * the current task:
+ */
+static inline struct task_struct *
+__load_balance_iterator(struct cfs_rq *cfs_rq, struct rb_node *curr)
+{
+	struct task_struct *p;
+
+	if (!curr)
+		return NULL;
+
+	p = rb_entry(curr, struct task_struct, se.run_node);
+	cfs_rq->rb_load_balance_curr = rb_next(curr);
+
+	return p;
+}
+
+static struct task_struct *load_balance_start_fair(void *arg)
+{
+	struct cfs_rq *cfs_rq = arg;
+
+	return __load_balance_iterator(cfs_rq, first_fair(cfs_rq));
+}
+
+static struct task_struct *load_balance_next_fair(void *arg)
+{
+	struct cfs_rq *cfs_rq = arg;
+
+	return __load_balance_iterator(cfs_rq, cfs_rq->rb_load_balance_curr);
+}
+
+static int cfs_rq_best_prio(struct cfs_rq *cfs_rq)
+{
+	struct sched_entity *curr;
+	struct task_struct *p;
+
+	if (!cfs_rq->nr_running)
+		return MAX_PRIO;
+
+	curr = __pick_next_entity(cfs_rq);
+	p = task_of(curr);
+
+	return p->prio;
+}
+
+static int
+load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+			unsigned long max_nr_move, unsigned long max_load_move,
+			struct sched_domain *sd, enum cpu_idle_type idle,
+			int *all_pinned, unsigned long *total_load_moved)
+{
+	struct cfs_rq *busy_cfs_rq;
+	unsigned long load_moved, total_nr_moved = 0, nr_moved;
+	long rem_load_move = max_load_move;
+	struct rq_iterator cfs_rq_iterator;
+
+	cfs_rq_iterator.start = load_balance_start_fair;
+	cfs_rq_iterator.next = load_balance_next_fair;
+
+	for_each_leaf_cfs_rq(busiest, busy_cfs_rq) {
+		struct cfs_rq *this_cfs_rq;
+		long imbalance;
+		unsigned long maxload;
+		int this_best_prio, best_prio, best_prio_seen = 0;
+
+		this_cfs_rq = cpu_cfs_rq(busy_cfs_rq, this_cpu);
+
+		imbalance = busy_cfs_rq->load.weight -
+						 this_cfs_rq->load.weight;
+		/* Don't pull if this_cfs_rq has more load than busy_cfs_rq */
+		if (imbalance <= 0)
+			continue;
+
+		/* Don't pull more than imbalance/2 */
+		imbalance /= 2;
+		maxload = min(rem_load_move, imbalance);
+
+		this_best_prio = cfs_rq_best_prio(this_cfs_rq);
+		best_prio = cfs_rq_best_prio(busy_cfs_rq);
+
+		/*
+		 * Enable handling of the case where there is more than one task
+		 * with the best priority. If the current running task is one
+		 * of those with prio==best_prio we know it won't be moved
+		 * and therefore it's safe to override the skip (based on load)
+		 * of any task we find with that prio.
+		 */
+		if (cfs_rq_curr(busy_cfs_rq) == &busiest->curr->se)
+			best_prio_seen = 1;
+
+		/* pass busy_cfs_rq argument into
+		 * load_balance_[start|next]_fair iterators
+		 */
+		cfs_rq_iterator.arg = busy_cfs_rq;
+		nr_moved = balance_tasks(this_rq, this_cpu, busiest,
+				max_nr_move, maxload, sd, idle, all_pinned,
+				&load_moved, this_best_prio, best_prio,
+				best_prio_seen, &cfs_rq_iterator);
+
+		total_nr_moved += nr_moved;
+		max_nr_move -= nr_moved;
+		rem_load_move -= load_moved;
+
+		if (max_nr_move <= 0 || rem_load_move <= 0)
+			break;
+	}
+
+	*total_load_moved = max_load_move - rem_load_move;
+
+	return total_nr_moved;
+}
+
+/*
+ * scheduler tick hitting a task of our scheduling class:
+ */
+static void task_tick_fair(struct rq *rq, struct task_struct *curr)
+{
+	struct cfs_rq *cfs_rq;
+	struct sched_entity *se = &curr->se;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		entity_tick(cfs_rq, se);
+	}
+}
+
+/*
+ * Share the fairness runtime between parent and child, thus the
+ * total amount of pressure for CPU stays equal - new tasks
+ * get a chance to run but frequent forkers are not allowed to
+ * monopolize the CPU. Note: the parent runqueue is locked,
+ * the child is not running yet.
+ */
+static void task_new_fair(struct rq *rq, struct task_struct *p)
+{
+	struct cfs_rq *cfs_rq = task_cfs_rq(p);
+	struct sched_entity *se = &p->se;
+	u64 now = rq_clock(rq);
+
+	sched_info_queued(p);
+
+	update_stats_enqueue(cfs_rq, se, now);
+	/*
+	 * Child runs first: we let it run before the parent
+	 * until it reschedules once. We set up the key so that
+	 * it will preempt the parent:
+	 */
+	p->se.fair_key = current->se.fair_key -
+		niced_granularity(&rq->curr->se, sysctl_sched_granularity) - 1;
+	/*
+	 * The first wait is dominated by the child-runs-first logic,
+	 * so do not credit it with that waiting time yet:
+	 */
+	if (sysctl_sched_features & SCHED_FEAT_SKIP_INITIAL)
+		p->se.wait_start_fair = 0;
+
+	/*
+	 * The statistical average of wait_runtime is about
+	 * -granularity/2, so initialize the task with that:
+	 */
+	if (sysctl_sched_features & SCHED_FEAT_START_DEBIT)
+		p->se.wait_runtime = -(sysctl_sched_granularity / 2);
+
+	__enqueue_entity(cfs_rq, se);
+	inc_nr_running(p, rq, now);
+}
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/* Account for a task changing its policy or group.
+ *
+ * This routine is mostly called to set cfs_rq->curr field when a task
+ * migrates between groups/classes.
+ */
+static void set_curr_task_fair(struct rq *rq)
+{
+	struct task_struct *curr = rq->curr;
+	struct sched_entity *se = &curr->se;
+	u64 now = rq_clock(rq);
+	struct cfs_rq *cfs_rq;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		set_next_entity(cfs_rq, se, now);
+	}
+}
+#else
+static void set_curr_task_fair(struct rq *rq)
+{
+}
+#endif
+
+/*
+ * All the scheduling class methods:
+ */
+struct sched_class fair_sched_class __read_mostly = {
+	.enqueue_task		= enqueue_task_fair,
+	.dequeue_task		= dequeue_task_fair,
+	.yield_task		= yield_task_fair,
+
+	.check_preempt_curr	= check_preempt_curr_fair,
+
+	.pick_next_task		= pick_next_task_fair,
+	.put_prev_task		= put_prev_task_fair,
+
+	.load_balance		= load_balance_fair,
+
+	.set_curr_task          = set_curr_task_fair,
+	.task_tick		= task_tick_fair,
+	.task_new		= task_new_fair,
+};
+
+#ifdef CONFIG_SCHED_DEBUG
+void print_cfs_stats(struct seq_file *m, int cpu, u64 now)
+{
+	struct rq *rq = cpu_rq(cpu);
+	struct cfs_rq *cfs_rq;
+
+	for_each_leaf_cfs_rq(rq, cfs_rq)
+		print_cfs_rq(m, cpu, cfs_rq, now);
+}
+#endif
diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c
new file mode 100644
index 0000000..41841e7
--- /dev/null
+++ b/kernel/sched_idletask.c
@@ -0,0 +1,71 @@
+/*
+ * idle-task scheduling class.
+ *
+ * (NOTE: these are not related to SCHED_IDLE tasks which are
+ *  handled in sched_fair.c)
+ */
+
+/*
+ * Idle tasks are unconditionally rescheduled:
+ */
+static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p)
+{
+	resched_task(rq->idle);
+}
+
+static struct task_struct *pick_next_task_idle(struct rq *rq, u64 now)
+{
+	schedstat_inc(rq, sched_goidle);
+
+	return rq->idle;
+}
+
+/*
+ * It is not legal to sleep in the idle task - print a warning
+ * message if some code attempts to do it:
+ */
+static void
+dequeue_task_idle(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+	spin_unlock_irq(&rq->lock);
+	printk(KERN_ERR "bad: scheduling from the idle thread!\n");
+	dump_stack();
+	spin_lock_irq(&rq->lock);
+}
+
+static void put_prev_task_idle(struct rq *rq, struct task_struct *prev, u64 now)
+{
+}
+
+static int
+load_balance_idle(struct rq *this_rq, int this_cpu, struct rq *busiest,
+			unsigned long max_nr_move, unsigned long max_load_move,
+			struct sched_domain *sd, enum cpu_idle_type idle,
+			int *all_pinned, unsigned long *total_load_moved)
+{
+	return 0;
+}
+
+static void task_tick_idle(struct rq *rq, struct task_struct *curr)
+{
+}
+
+/*
+ * Simple, special scheduling class for the per-CPU idle tasks:
+ */
+static struct sched_class idle_sched_class __read_mostly = {
+	/* no enqueue/yield_task for idle tasks */
+
+	/* dequeue is not valid, we print a debug message there: */
+	.dequeue_task		= dequeue_task_idle,
+
+	.check_preempt_curr	= check_preempt_curr_idle,
+
+	.pick_next_task		= pick_next_task_idle,
+	.put_prev_task		= put_prev_task_idle,
+
+	.load_balance		= load_balance_idle,
+
+	.task_tick		= task_tick_idle,
+	/* no .task_new for idle tasks */
+};
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
new file mode 100644
index 0000000..1192a27
--- /dev/null
+++ b/kernel/sched_rt.c
@@ -0,0 +1,255 @@
+/*
+ * Real-Time Scheduling Class (mapped to the SCHED_FIFO and SCHED_RR
+ * policies)
+ */
+
+/*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+ */
+static inline void update_curr_rt(struct rq *rq, u64 now)
+{
+	struct task_struct *curr = rq->curr;
+	u64 delta_exec;
+
+	if (!task_has_rt_policy(curr))
+		return;
+
+	delta_exec = now - curr->se.exec_start;
+	if (unlikely((s64)delta_exec < 0))
+		delta_exec = 0;
+	if (unlikely(delta_exec > curr->se.exec_max))
+		curr->se.exec_max = delta_exec;
+
+	curr->se.sum_exec_runtime += delta_exec;
+	curr->se.exec_start = now;
+}
+
+static void
+enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+	struct rt_prio_array *array = &rq->rt.active;
+
+	list_add_tail(&p->run_list, array->queue + p->prio);
+	__set_bit(p->prio, array->bitmap);
+}
+
+/*
+ * Adding/removing a task to/from a priority array:
+ */
+static void
+dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+	struct rt_prio_array *array = &rq->rt.active;
+
+	update_curr_rt(rq, now);
+
+	list_del(&p->run_list);
+	if (list_empty(array->queue + p->prio))
+		__clear_bit(p->prio, array->bitmap);
+}
+
+/*
+ * Put task to the end of the run list without the overhead of dequeue
+ * followed by enqueue.
+ */
+static void requeue_task_rt(struct rq *rq, struct task_struct *p)
+{
+	struct rt_prio_array *array = &rq->rt.active;
+
+	list_move_tail(&p->run_list, array->queue + p->prio);
+}
+
+static void
+yield_task_rt(struct rq *rq, struct task_struct *p)
+{
+	requeue_task_rt(rq, p);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p)
+{
+	if (p->prio < rq->curr->prio)
+		resched_task(rq->curr);
+}
+
+static struct task_struct *pick_next_task_rt(struct rq *rq, u64 now)
+{
+	struct rt_prio_array *array = &rq->rt.active;
+	struct task_struct *next;
+	struct list_head *queue;
+	int idx;
+
+	idx = sched_find_first_bit(array->bitmap);
+	if (idx >= MAX_RT_PRIO)
+		return NULL;
+
+	queue = array->queue + idx;
+	next = list_entry(queue->next, struct task_struct, run_list);
+
+	next->se.exec_start = now;
+
+	return next;
+}
+
+static void put_prev_task_rt(struct rq *rq, struct task_struct *p, u64 now)
+{
+	update_curr_rt(rq, now);
+	p->se.exec_start = 0;
+}
+
+/*
+ * Load-balancing iterator. Note: while the runqueue stays locked
+ * during the whole iteration, the current task might be
+ * dequeued so the iterator has to be dequeue-safe. Here we
+ * achieve that by always pre-iterating before returning
+ * the current task:
+ */
+static struct task_struct *load_balance_start_rt(void *arg)
+{
+	struct rq *rq = arg;
+	struct rt_prio_array *array = &rq->rt.active;
+	struct list_head *head, *curr;
+	struct task_struct *p;
+	int idx;
+
+	idx = sched_find_first_bit(array->bitmap);
+	if (idx >= MAX_RT_PRIO)
+		return NULL;
+
+	head = array->queue + idx;
+	curr = head->prev;
+
+	p = list_entry(curr, struct task_struct, run_list);
+
+	curr = curr->prev;
+
+	rq->rt.rt_load_balance_idx = idx;
+	rq->rt.rt_load_balance_head = head;
+	rq->rt.rt_load_balance_curr = curr;
+
+	return p;
+}
+
+static struct task_struct *load_balance_next_rt(void *arg)
+{
+	struct rq *rq = arg;
+	struct rt_prio_array *array = &rq->rt.active;
+	struct list_head *head, *curr;
+	struct task_struct *p;
+	int idx;
+
+	idx = rq->rt.rt_load_balance_idx;
+	head = rq->rt.rt_load_balance_head;
+	curr = rq->rt.rt_load_balance_curr;
+
+	/*
+	 * If we arrived back to the head again then
+	 * iterate to the next queue (if any):
+	 */
+	if (unlikely(head == curr)) {
+		int next_idx = find_next_bit(array->bitmap, MAX_RT_PRIO, idx+1);
+
+		if (next_idx >= MAX_RT_PRIO)
+			return NULL;
+
+		idx = next_idx;
+		head = array->queue + idx;
+		curr = head->prev;
+
+		rq->rt.rt_load_balance_idx = idx;
+		rq->rt.rt_load_balance_head = head;
+	}
+
+	p = list_entry(curr, struct task_struct, run_list);
+
+	curr = curr->prev;
+
+	rq->rt.rt_load_balance_curr = curr;
+
+	return p;
+}
+
+static int
+load_balance_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
+			unsigned long max_nr_move, unsigned long max_load_move,
+			struct sched_domain *sd, enum cpu_idle_type idle,
+			int *all_pinned, unsigned long *load_moved)
+{
+	int this_best_prio, best_prio, best_prio_seen = 0;
+	int nr_moved;
+	struct rq_iterator rt_rq_iterator;
+
+	best_prio = sched_find_first_bit(busiest->rt.active.bitmap);
+	this_best_prio = sched_find_first_bit(this_rq->rt.active.bitmap);
+
+	/*
+	 * Enable handling of the case where there is more than one task
+	 * with the best priority.   If the current running task is one
+	 * of those with prio==best_prio we know it won't be moved
+	 * and therefore it's safe to override the skip (based on load)
+	 * of any task we find with that prio.
+	 */
+	if (busiest->curr->prio == best_prio)
+		best_prio_seen = 1;
+
+	rt_rq_iterator.start = load_balance_start_rt;
+	rt_rq_iterator.next = load_balance_next_rt;
+	/* pass 'busiest' rq argument into
+	 * load_balance_[start|next]_rt iterators
+	 */
+	rt_rq_iterator.arg = busiest;
+
+	nr_moved = balance_tasks(this_rq, this_cpu, busiest, max_nr_move,
+			max_load_move, sd, idle, all_pinned, load_moved,
+			this_best_prio, best_prio, best_prio_seen,
+			&rt_rq_iterator);
+
+	return nr_moved;
+}
+
+static void task_tick_rt(struct rq *rq, struct task_struct *p)
+{
+	/*
+	 * RR tasks need a special form of timeslice management.
+	 * FIFO tasks have no timeslices.
+	 */
+	if (p->policy != SCHED_RR)
+		return;
+
+	if (--p->time_slice)
+		return;
+
+	p->time_slice = static_prio_timeslice(p->static_prio);
+	set_tsk_need_resched(p);
+
+	/* put it at the end of the queue: */
+	requeue_task_rt(rq, p);
+}
+
+/*
+ * No parent/child timeslice management necessary for RT tasks,
+ * just activate them:
+ */
+static void task_new_rt(struct rq *rq, struct task_struct *p)
+{
+	activate_task(rq, p, 1);
+}
+
+static struct sched_class rt_sched_class __read_mostly = {
+	.enqueue_task		= enqueue_task_rt,
+	.dequeue_task		= dequeue_task_rt,
+	.yield_task		= yield_task_rt,
+
+	.check_preempt_curr	= check_preempt_curr_rt,
+
+	.pick_next_task		= pick_next_task_rt,
+	.put_prev_task		= put_prev_task_rt,
+
+	.load_balance		= load_balance_rt,
+
+	.task_tick		= task_tick_rt,
+	.task_new		= task_new_rt,
+};
diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h
new file mode 100644
index 0000000..c63c38f
--- /dev/null
+++ b/kernel/sched_stats.h
@@ -0,0 +1,235 @@
+
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * bump this up when changing the output format or the meaning of an existing
+ * format, so that tools can adapt (or abort)
+ */
+#define SCHEDSTAT_VERSION 14
+
+static int show_schedstat(struct seq_file *seq, void *v)
+{
+	int cpu;
+
+	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+	seq_printf(seq, "timestamp %lu\n", jiffies);
+	for_each_online_cpu(cpu) {
+		struct rq *rq = cpu_rq(cpu);
+#ifdef CONFIG_SMP
+		struct sched_domain *sd;
+		int dcnt = 0;
+#endif
+
+		/* runqueue-specific stats */
+		seq_printf(seq,
+		    "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %llu %llu %lu",
+		    cpu, rq->yld_both_empty,
+		    rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
+		    rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
+		    rq->ttwu_cnt, rq->ttwu_local,
+		    rq->rq_sched_info.cpu_time,
+		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
+
+		seq_printf(seq, "\n");
+
+#ifdef CONFIG_SMP
+		/* domain-specific stats */
+		preempt_disable();
+		for_each_domain(cpu, sd) {
+			enum cpu_idle_type itype;
+			char mask_str[NR_CPUS];
+
+			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
+			seq_printf(seq, "domain%d %s", dcnt++, mask_str);
+			for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
+					itype++) {
+				seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
+						"%lu",
+				    sd->lb_cnt[itype],
+				    sd->lb_balanced[itype],
+				    sd->lb_failed[itype],
+				    sd->lb_imbalance[itype],
+				    sd->lb_gained[itype],
+				    sd->lb_hot_gained[itype],
+				    sd->lb_nobusyq[itype],
+				    sd->lb_nobusyg[itype]);
+			}
+			seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+			    " %lu %lu %lu\n",
+			    sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
+			    sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
+			    sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
+			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
+			    sd->ttwu_move_balance);
+		}
+		preempt_enable();
+#endif
+	}
+	return 0;
+}
+
+static int schedstat_open(struct inode *inode, struct file *file)
+{
+	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
+	char *buf = kmalloc(size, GFP_KERNEL);
+	struct seq_file *m;
+	int res;
+
+	if (!buf)
+		return -ENOMEM;
+	res = single_open(file, show_schedstat, NULL);
+	if (!res) {
+		m = file->private_data;
+		m->buf = buf;
+		m->size = size;
+	} else
+		kfree(buf);
+	return res;
+}
+
+const struct file_operations proc_schedstat_operations = {
+	.open    = schedstat_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+/*
+ * Expects runqueue lock to be held for atomicity of update
+ */
+static inline void
+rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
+{
+	if (rq) {
+		rq->rq_sched_info.run_delay += delta;
+		rq->rq_sched_info.pcnt++;
+	}
+}
+
+/*
+ * Expects runqueue lock to be held for atomicity of update
+ */
+static inline void
+rq_sched_info_depart(struct rq *rq, unsigned long long delta)
+{
+	if (rq)
+		rq->rq_sched_info.cpu_time += delta;
+}
+# define schedstat_inc(rq, field)	do { (rq)->field++; } while (0)
+# define schedstat_add(rq, field, amt)	do { (rq)->field += (amt); } while (0)
+#else /* !CONFIG_SCHEDSTATS */
+static inline void
+rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
+{}
+static inline void
+rq_sched_info_depart(struct rq *rq, unsigned long long delta)
+{}
+# define schedstat_inc(rq, field)	do { } while (0)
+# define schedstat_add(rq, field, amt)	do { } while (0)
+#endif
+
+#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
+/*
+ * Called when a process is dequeued from the active array and given
+ * the cpu.  We should note that with the exception of interactive
+ * tasks, the expired queue will become the active queue after the active
+ * queue is empty, without explicitly dequeuing and requeuing tasks in the
+ * expired queue.  (Interactive tasks may be requeued directly to the
+ * active queue, thus delaying tasks in the expired queue from running;
+ * see scheduler_tick()).
+ *
+ * This function is only called from sched_info_arrive(), rather than
+ * dequeue_task(). Even though a task may be queued and dequeued multiple
+ * times as it is shuffled about, we're really interested in knowing how
+ * long it was from the *first* time it was queued to the time that it
+ * finally hit a cpu.
+ */
+static inline void sched_info_dequeued(struct task_struct *t)
+{
+	t->sched_info.last_queued = 0;
+}
+
+/*
+ * Called when a task finally hits the cpu.  We can now calculate how
+ * long it was waiting to run.  We also note when it began so that we
+ * can keep stats on how long its timeslice is.
+ */
+static void sched_info_arrive(struct task_struct *t)
+{
+	unsigned long long now = sched_clock(), delta = 0;
+
+	if (t->sched_info.last_queued)
+		delta = now - t->sched_info.last_queued;
+	sched_info_dequeued(t);
+	t->sched_info.run_delay += delta;
+	t->sched_info.last_arrival = now;
+	t->sched_info.pcnt++;
+
+	rq_sched_info_arrive(task_rq(t), delta);
+}
+
+/*
+ * Called when a process is queued into either the active or expired
+ * array.  The time is noted and later used to determine how long we
+ * had to wait for us to reach the cpu.  Since the expired queue will
+ * become the active queue after active queue is empty, without dequeuing
+ * and requeuing any tasks, we are interested in queuing to either. It
+ * is unusual but not impossible for tasks to be dequeued and immediately
+ * requeued in the same or another array: this can happen in sched_yield(),
+ * set_user_nice(), and even load_balance() as it moves tasks from runqueue
+ * to runqueue.
+ *
+ * This function is only called from enqueue_task(), but also only updates
+ * the timestamp if it is already not set.  It's assumed that
+ * sched_info_dequeued() will clear that stamp when appropriate.
+ */
+static inline void sched_info_queued(struct task_struct *t)
+{
+	if (unlikely(sched_info_on()))
+		if (!t->sched_info.last_queued)
+			t->sched_info.last_queued = sched_clock();
+}
+
+/*
+ * Called when a process ceases being the active-running process, either
+ * voluntarily or involuntarily.  Now we can calculate how long we ran.
+ */
+static inline void sched_info_depart(struct task_struct *t)
+{
+	unsigned long long delta = sched_clock() - t->sched_info.last_arrival;
+
+	t->sched_info.cpu_time += delta;
+	rq_sched_info_depart(task_rq(t), delta);
+}
+
+/*
+ * Called when tasks are switched involuntarily due, typically, to expiring
+ * their time slice.  (This may also be called when switching to or from
+ * the idle task.)  We are only called when prev != next.
+ */
+static inline void
+__sched_info_switch(struct task_struct *prev, struct task_struct *next)
+{
+	struct rq *rq = task_rq(prev);
+
+	/*
+	 * prev now departs the cpu.  It's not interesting to record
+	 * stats about how efficient we were at scheduling the idle
+	 * process, however.
+	 */
+	if (prev != rq->idle)
+		sched_info_depart(prev);
+
+	if (next != rq->idle)
+		sched_info_arrive(next);
+}
+static inline void
+sched_info_switch(struct task_struct *prev, struct task_struct *next)
+{
+	if (unlikely(sched_info_on()))
+		__sched_info_switch(prev, next);
+}
+#else
+#define sched_info_queued(t)		do { } while (0)
+#define sched_info_switch(t, next)	do { } while (0)
+#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
+
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index c3391b6..ad64fcb 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -10,6 +10,7 @@
 #include <linux/sched.h>
 
 /* #define SECCOMP_DEBUG 1 */
+#define NR_SECCOMP_MODES 1
 
 /*
  * Secure computing mode 1 allows only read/write/exit/sigreturn.
@@ -54,3 +55,31 @@
 #endif
 	do_exit(SIGKILL);
 }
+
+long prctl_get_seccomp(void)
+{
+	return current->seccomp.mode;
+}
+
+long prctl_set_seccomp(unsigned long seccomp_mode)
+{
+	long ret;
+
+	/* can set it only once to be even more secure */
+	ret = -EPERM;
+	if (unlikely(current->seccomp.mode))
+		goto out;
+
+	ret = -EINVAL;
+	if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
+		current->seccomp.mode = seccomp_mode;
+		set_thread_flag(TIF_SECCOMP);
+#ifdef TIF_NOTSC
+		disable_TSC();
+#endif
+		ret = 0;
+	}
+
+ out:
+	return ret;
+}
diff --git a/kernel/signal.c b/kernel/signal.c
index 364fc95..39d1227 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -96,20 +96,38 @@
 
 #define PENDING(p,b) has_pending_signals(&(p)->signal, (b))
 
-fastcall void recalc_sigpending_tsk(struct task_struct *t)
+static int recalc_sigpending_tsk(struct task_struct *t)
 {
 	if (t->signal->group_stop_count > 0 ||
 	    (freezing(t)) ||
 	    PENDING(&t->pending, &t->blocked) ||
-	    PENDING(&t->signal->shared_pending, &t->blocked))
+	    PENDING(&t->signal->shared_pending, &t->blocked)) {
 		set_tsk_thread_flag(t, TIF_SIGPENDING);
-	else
-		clear_tsk_thread_flag(t, TIF_SIGPENDING);
+		return 1;
+	}
+	/*
+	 * We must never clear the flag in another thread, or in current
+	 * when it's possible the current syscall is returning -ERESTART*.
+	 * So we don't clear it here, and only callers who know they should do.
+	 */
+	return 0;
+}
+
+/*
+ * After recalculating TIF_SIGPENDING, we need to make sure the task wakes up.
+ * This is superfluous when called on current, the wakeup is a harmless no-op.
+ */
+void recalc_sigpending_and_wake(struct task_struct *t)
+{
+	if (recalc_sigpending_tsk(t))
+		signal_wake_up(t, 0);
 }
 
 void recalc_sigpending(void)
 {
-	recalc_sigpending_tsk(current);
+	if (!recalc_sigpending_tsk(current))
+		clear_thread_flag(TIF_SIGPENDING);
+
 }
 
 /* Given the mask, find the first available signal that should be serviced. */
@@ -345,7 +363,13 @@
  */
 int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 {
-	int signr = __dequeue_signal(&tsk->pending, mask, info);
+	int signr = 0;
+
+	/* We only dequeue private signals from ourselves, we don't let
+	 * signalfd steal them
+	 */
+	if (tsk == current)
+		signr = __dequeue_signal(&tsk->pending, mask, info);
 	if (!signr) {
 		signr = __dequeue_signal(&tsk->signal->shared_pending,
 					 mask, info);
@@ -373,7 +397,8 @@
 			}
 		}
 	}
-	recalc_sigpending_tsk(tsk);
+	if (likely(tsk == current))
+		recalc_sigpending();
 	if (signr && unlikely(sig_kernel_stop(signr))) {
 		/*
 		 * Set a marker that we have dequeued a stop signal.  Our
@@ -693,6 +718,37 @@
 #define LEGACY_QUEUE(sigptr, sig) \
 	(((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
 
+int print_fatal_signals;
+
+static void print_fatal_signal(struct pt_regs *regs, int signr)
+{
+	printk("%s/%d: potentially unexpected fatal signal %d.\n",
+		current->comm, current->pid, signr);
+
+#ifdef __i386__
+	printk("code at %08lx: ", regs->eip);
+	{
+		int i;
+		for (i = 0; i < 16; i++) {
+			unsigned char insn;
+
+			__get_user(insn, (unsigned char *)(regs->eip + i));
+			printk("%02x ", insn);
+		}
+	}
+#endif
+	printk("\n");
+	show_regs(regs);
+}
+
+static int __init setup_print_fatal_signals(char *str)
+{
+	get_option (&str, &print_fatal_signals);
+
+	return 1;
+}
+
+__setup("print-fatal-signals=", setup_print_fatal_signals);
 
 static int
 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
@@ -744,7 +800,7 @@
 		action->sa.sa_handler = SIG_DFL;
 		if (blocked) {
 			sigdelset(&t->blocked, sig);
-			recalc_sigpending_tsk(t);
+			recalc_sigpending_and_wake(t);
 		}
 	}
 	ret = specific_send_sig_info(sig, info, t);
@@ -1568,8 +1624,9 @@
 	/*
 	 * Queued signals ignored us while we were stopped for tracing.
 	 * So check for any that we should take before resuming user mode.
+	 * This sets TIF_SIGPENDING, but never clears it.
 	 */
-	recalc_sigpending();
+	recalc_sigpending_tsk(current);
 }
 
 void ptrace_notify(int exit_code)
@@ -1829,6 +1886,8 @@
 		 * Anything else is fatal, maybe with a core dump.
 		 */
 		current->flags |= PF_SIGNALED;
+		if ((signr != SIGKILL) && print_fatal_signals)
+			print_fatal_signal(regs, signr);
 		if (sig_kernel_coredump(signr)) {
 			/*
 			 * If it was able to dump core, this kills all
@@ -2273,7 +2332,7 @@
 			rm_from_queue_full(&mask, &t->signal->shared_pending);
 			do {
 				rm_from_queue_full(&mask, &t->pending);
-				recalc_sigpending_tsk(t);
+				recalc_sigpending_and_wake(t);
 				t = next_thread(t);
 			} while (t != current);
 		}
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 0b9886a..0f546dd 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -14,6 +14,7 @@
 #include <linux/notifier.h>
 #include <linux/percpu.h>
 #include <linux/cpu.h>
+#include <linux/freezer.h>
 #include <linux/kthread.h>
 #include <linux/rcupdate.h>
 #include <linux/smp.h>
@@ -488,9 +489,6 @@
 
 static int ksoftirqd(void * __bind_cpu)
 {
-	set_user_nice(current, 19);
-	current->flags |= PF_NOFREEZE;
-
 	set_current_state(TASK_INTERRUPTIBLE);
 
 	while (!kthread_should_stop()) {
@@ -615,12 +613,16 @@
 		kthread_bind(per_cpu(ksoftirqd, hotcpu),
 			     any_online_cpu(cpu_online_map));
 	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
+	case CPU_DEAD_FROZEN: {
+		struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+
 		p = per_cpu(ksoftirqd, hotcpu);
 		per_cpu(ksoftirqd, hotcpu) = NULL;
+		sched_setscheduler(p, SCHED_FIFO, &param);
 		kthread_stop(p);
 		takeover_tasklets(hotcpu);
 		break;
+	}
 #endif /* CONFIG_HOTPLUG_CPU */
  	}
 	return NOTIFY_OK;
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 0131e29..708d488 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -10,6 +10,7 @@
 #include <linux/cpu.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/freezer.h>
 #include <linux/kthread.h>
 #include <linux/notifier.h>
 #include <linux/module.h>
@@ -116,7 +117,6 @@
 	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
-	current->flags |= PF_NOFREEZE;
 
 	/* initialize timestamp */
 	touch_softlockup_watchdog();
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index fcee2a8..319821e 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -93,10 +93,6 @@
 static int stop_machine(void)
 {
 	int i, ret = 0;
-	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
-
-	/* One high-prio thread per cpu.  We'll do this one. */
-	sched_setscheduler(current, SCHED_FIFO, &param);
 
 	atomic_set(&stopmachine_thread_ack, 0);
 	stopmachine_num_threads = 0;
@@ -189,6 +185,10 @@
 
 	p = kthread_create(do_stop, &smdata, "kstopmachine");
 	if (!IS_ERR(p)) {
+		struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+
+		/* One high-prio thread per cpu.  We'll do this one. */
+		sched_setscheduler(p, SCHED_FIFO, &param);
 		kthread_bind(p, cpu);
 		wake_up_process(p);
 		wait_for_completion(&smdata.done);
diff --git a/kernel/sys.c b/kernel/sys.c
index 872271c..4d141ae 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -31,10 +31,12 @@
 #include <linux/cn_proc.h>
 #include <linux/getcpu.h>
 #include <linux/task_io_accounting_ops.h>
+#include <linux/seccomp.h>
 
 #include <linux/compat.h>
 #include <linux/syscalls.h>
 #include <linux/kprobes.h>
+#include <linux/user_namespace.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -1078,13 +1080,13 @@
 {
 	struct user_struct *new_user;
 
-	new_user = alloc_uid(new_ruid);
+	new_user = alloc_uid(current->nsproxy->user_ns, new_ruid);
 	if (!new_user)
 		return -EAGAIN;
 
 	if (atomic_read(&new_user->processes) >=
 				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
-			new_user != &root_user) {
+			new_user != current->nsproxy->user_ns->root_user) {
 		free_uid(new_user);
 		return -EAGAIN;
 	}
@@ -2241,6 +2243,13 @@
 			error = SET_ENDIAN(current, arg2);
 			break;
 
+		case PR_GET_SECCOMP:
+			error = prctl_get_seccomp();
+			break;
+		case PR_SET_SECCOMP:
+			error = prctl_set_seccomp(arg2);
+			break;
+
 		default:
 			error = -EINVAL;
 			break;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 7e11e2c..b0ec498 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -14,6 +14,7 @@
 
 cond_syscall(sys_nfsservctl);
 cond_syscall(sys_quotactl);
+cond_syscall(sys32_quotactl);
 cond_syscall(sys_acct);
 cond_syscall(sys_lookup_dcookie);
 cond_syscall(sys_swapon);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 30ee462..7063ebc 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -29,6 +29,7 @@
 #include <linux/utsname.h>
 #include <linux/capability.h>
 #include <linux/smp_lock.h>
+#include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kobject.h>
@@ -49,9 +50,6 @@
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
-extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
-                     void __user *buffer, size_t *lenp, loff_t *ppos);
-
 #ifdef CONFIG_X86
 #include <asm/nmi.h>
 #include <asm/stacktrace.h>
@@ -61,6 +59,7 @@
 
 /* External variables not in a header file. */
 extern int C_A_D;
+extern int print_fatal_signals;
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern int sysctl_panic_on_oom;
@@ -202,11 +201,94 @@
 		.mode		= 0555,
 		.child		= dev_table,
 	},
-
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
 	{ .ctl_name = 0 }
 };
 
+#ifdef CONFIG_SCHED_DEBUG
+static unsigned long min_sched_granularity_ns = 100000;		/* 100 usecs */
+static unsigned long max_sched_granularity_ns = 1000000000;	/* 1 second */
+static unsigned long min_wakeup_granularity_ns;			/* 0 usecs */
+static unsigned long max_wakeup_granularity_ns = 1000000000;	/* 1 second */
+#endif
+
 static ctl_table kern_table[] = {
+#ifdef CONFIG_SCHED_DEBUG
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_granularity_ns",
+		.data		= &sysctl_sched_granularity,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_sched_granularity_ns,
+		.extra2		= &max_sched_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_wakeup_granularity_ns",
+		.data		= &sysctl_sched_wakeup_granularity,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_wakeup_granularity_ns,
+		.extra2		= &max_wakeup_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_batch_wakeup_granularity_ns",
+		.data		= &sysctl_sched_batch_wakeup_granularity,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_wakeup_granularity_ns,
+		.extra2		= &max_wakeup_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_stat_granularity_ns",
+		.data		= &sysctl_sched_stat_granularity,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_wakeup_granularity_ns,
+		.extra2		= &max_wakeup_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_runtime_limit_ns",
+		.data		= &sysctl_sched_runtime_limit,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_sched_granularity_ns,
+		.extra2		= &max_sched_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_child_runs_first",
+		.data		= &sysctl_sched_child_runs_first,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_features",
+		.data		= &sysctl_sched_features,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
 	{
 		.ctl_name	= KERN_PANIC,
 		.procname	= "panic",
@@ -260,6 +342,14 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "print-fatal-signals",
+		.data		= &print_fatal_signals,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 #ifdef __sparc__
 	{
 		.ctl_name	= KERN_SPARC_REBOOT,
@@ -734,6 +824,14 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	 },
+	 {
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "hugepages_treat_as_movable",
+		.data		= &hugepages_treat_as_movable,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &hugetlb_treat_movable_handler,
+	},
 #endif
 	{
 		.ctl_name	= VM_LOWMEM_RESERVE_RATIO,
@@ -869,6 +967,27 @@
 		.strategy	= &sysctl_jiffies,
 	},
 #endif
+#ifdef CONFIG_SECURITY
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "mmap_min_addr",
+		.data		= &mmap_min_addr,
+		.maxlen         = sizeof(unsigned long),
+		.mode		= 0644,
+		.proc_handler	= &proc_doulongvec_minmax,
+	},
+#ifdef CONFIG_NUMA
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "numa_zonelist_order",
+		.data		= &numa_zonelist_order,
+		.maxlen		= NUMA_ZONELIST_ORDER_LEN,
+		.mode		= 0644,
+		.proc_handler	= &numa_zonelist_order_handler,
+		.strategy	= &sysctl_string,
+	},
+#endif
+#endif
 #if defined(CONFIG_X86_32) || \
    (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
 	{
@@ -882,6 +1001,10 @@
 		.extra1		= &zero,
 	},
 #endif
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
 	{ .ctl_name = 0 }
 };
 
@@ -1022,6 +1145,10 @@
 		.child		= binfmt_misc_table,
 	},
 #endif
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
 	{ .ctl_name = 0 }
 };
 
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 906cae7..059431e 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -196,6 +196,8 @@
 
 	/* fill in basic acct fields */
 	stats->version = TASKSTATS_VERSION;
+	stats->nvcsw = tsk->nvcsw;
+	stats->nivcsw = tsk->nivcsw;
 	bacct_add_tsk(stats, tsk);
 
 	/* fill in extended acct fields */
@@ -242,6 +244,8 @@
 		 */
 		delayacct_add_tsk(stats, tsk);
 
+		stats->nvcsw += tsk->nvcsw;
+		stats->nivcsw += tsk->nivcsw;
 	} while_each_thread(first, tsk);
 
 	unlock_task_sighand(first, &flags);
diff --git a/kernel/time.c b/kernel/time.c
index f04791f..ffe1914 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -57,14 +57,17 @@
  */
 asmlinkage long sys_time(time_t __user * tloc)
 {
-	time_t i;
-	struct timeval tv;
+	/*
+	 * We read xtime.tv_sec atomically - it's updated
+	 * atomically by update_wall_time(), so no need to
+	 * even read-lock the xtime seqlock:
+	 */
+	time_t i = xtime.tv_sec;
 
-	do_gettimeofday(&tv);
-	i = tv.tv_sec;
+	smp_rmb(); /* sys_time() results are coherent */
 
 	if (tloc) {
-		if (put_user(i,tloc))
+		if (put_user(i, tloc))
 			i = -EFAULT;
 	}
 	return i;
@@ -373,12 +376,25 @@
 
 	tv->tv_sec = sec;
 	tv->tv_usec = usec;
-}
 
+	/*
+	 * Make sure xtime.tv_sec [returned by sys_time()] always
+	 * follows the gettimeofday() result precisely. This
+	 * condition is extremely unlikely, it can hit at most
+	 * once per second:
+	 */
+	if (unlikely(xtime.tv_sec != tv->tv_sec)) {
+		unsigned long flags;
+
+		write_seqlock_irqsave(&xtime_lock, flags);
+		update_wall_time();
+		write_sequnlock_irqrestore(&xtime_lock, flags);
+	}
+}
 EXPORT_SYMBOL(do_gettimeofday);
 
+#else	/* CONFIG_TIME_INTERPOLATION */
 
-#else
 #ifndef CONFIG_GENERIC_TIME
 /*
  * Simulate gettimeofday using do_gettimeofday which only allows a timeval
@@ -394,7 +410,7 @@
 }
 EXPORT_SYMBOL_GPL(getnstimeofday);
 #endif
-#endif
+#endif	/* CONFIG_TIME_INTERPOLATION */
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 76212b2..2ad1c37 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -205,47 +205,6 @@
 }
 
 /**
- * clockevents_request_device
- */
-struct clock_event_device *clockevents_request_device(unsigned int features,
-						      cpumask_t cpumask)
-{
-	struct clock_event_device *cur, *dev = NULL;
-	struct list_head *tmp;
-
-	spin_lock(&clockevents_lock);
-
-	list_for_each(tmp, &clockevent_devices) {
-		cur = list_entry(tmp, struct clock_event_device, list);
-
-		if ((cur->features & features) == features &&
-		    cpus_equal(cpumask, cur->cpumask)) {
-			if (!dev || dev->rating < cur->rating)
-				dev = cur;
-		}
-	}
-
-	clockevents_exchange_device(NULL, dev);
-
-	spin_unlock(&clockevents_lock);
-
-	return dev;
-}
-
-/**
- * clockevents_release_device
- */
-void clockevents_release_device(struct clock_event_device *dev)
-{
-	spin_lock(&clockevents_lock);
-
-	clockevents_exchange_device(dev, NULL);
-	clockevents_notify_released();
-
-	spin_unlock(&clockevents_lock);
-}
-
-/**
  * clockevents_notify - notification about relevant events
  */
 void clockevents_notify(unsigned long reason, void *arg)
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index cb25649..438c6b7 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -11,7 +11,9 @@
 #include <linux/mm.h>
 #include <linux/time.h>
 #include <linux/timex.h>
-
+#include <linux/jiffies.h>
+#include <linux/hrtimer.h>
+#include <linux/capability.h>
 #include <asm/div64.h>
 #include <asm/timex.h>
 
@@ -120,7 +122,6 @@
 			 */
 			time_interpolator_update(-NSEC_PER_SEC);
 			time_state = TIME_OOP;
-			clock_was_set();
 			printk(KERN_NOTICE "Clock: inserting leap second "
 					"23:59:60 UTC\n");
 		}
@@ -135,7 +136,6 @@
 			 */
 			time_interpolator_update(NSEC_PER_SEC);
 			time_state = TIME_WAIT;
-			clock_was_set();
 			printk(KERN_NOTICE "Clock: deleting leap second "
 					"23:59:59 UTC\n");
 		}
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index eadfce2..8001d37 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -243,11 +243,18 @@
 {
 	int cpu = get_cpu();
 
-	if (cpu == *oncpu)
-		tick_do_broadcast_on_off(&reason);
-	else
-		smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
-					 &reason, 1, 1);
+	if (!cpu_isset(*oncpu, cpu_online_map)) {
+		printk(KERN_ERR "tick-braodcast: ignoring broadcast for "
+		       "offline CPU #%d\n", *oncpu);
+	} else {
+
+		if (cpu == *oncpu)
+			tick_do_broadcast_on_off(&reason);
+		else
+			smp_call_function_single(*oncpu,
+						 tick_do_broadcast_on_off,
+						 &reason, 1, 1);
+	}
 	put_cpu();
 }
 
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 3483e6c..52db9e3 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -167,9 +167,15 @@
 		goto end;
 
 	cpu = smp_processor_id();
-	if (unlikely(local_softirq_pending()))
-		printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
-		       local_softirq_pending());
+	if (unlikely(local_softirq_pending())) {
+		static int ratelimit;
+
+		if (ratelimit < 10) {
+			printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
+			       local_softirq_pending());
+			ratelimit++;
+		}
+	}
 
 	now = ktime_get();
 	/*
@@ -241,6 +247,21 @@
 		if (cpu == tick_do_timer_cpu)
 			tick_do_timer_cpu = -1;
 
+		ts->idle_sleeps++;
+
+		/*
+		 * delta_jiffies >= NEXT_TIMER_MAX_DELTA signals that
+		 * there is no timer pending or at least extremly far
+		 * into the future (12 days for HZ=1000). In this case
+		 * we simply stop the tick timer:
+		 */
+		if (unlikely(delta_jiffies >= NEXT_TIMER_MAX_DELTA)) {
+			ts->idle_expires.tv64 = KTIME_MAX;
+			if (ts->nohz_mode == NOHZ_MODE_HIGHRES)
+				hrtimer_cancel(&ts->sched_timer);
+			goto out;
+		}
+
 		/*
 		 * calculate the expiry time for the next timer wheel
 		 * timer
@@ -248,7 +269,6 @@
 		expires = ktime_add_ns(last_update, tick_period.tv64 *
 				       delta_jiffies);
 		ts->idle_expires = expires;
-		ts->idle_sleeps++;
 
 		if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
 			hrtimer_start(&ts->sched_timer, expires,
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 3d1042f..728cedf 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -36,9 +36,17 @@
  * at zero at system boot time, so wall_to_monotonic will be negative,
  * however, we will ALWAYS keep the tv_nsec part positive so we can use
  * the usual normalization.
+ *
+ * wall_to_monotonic is moved after resume from suspend for the monotonic
+ * time not to jump. We need to add total_sleep_time to wall_to_monotonic
+ * to get the real boot based time offset.
+ *
+ * - wall_to_monotonic is no longer the boot time, getboottime must be
+ * used instead.
  */
 struct timespec xtime __attribute__ ((aligned (16)));
 struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
+static unsigned long total_sleep_time;		/* seconds */
 
 EXPORT_SYMBOL(xtime);
 
@@ -251,6 +259,7 @@
 	xtime.tv_nsec = 0;
 	set_normalized_timespec(&wall_to_monotonic,
 		-xtime.tv_sec, -xtime.tv_nsec);
+	total_sleep_time = 0;
 
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 }
@@ -282,6 +291,7 @@
 
 		xtime.tv_sec += sleep_length;
 		wall_to_monotonic.tv_sec -= sleep_length;
+		total_sleep_time += sleep_length;
 	}
 	/* re-base the last cycle value */
 	clock->cycle_last = clocksource_read(clock);
@@ -476,3 +486,30 @@
 	change_clocksource();
 	update_vsyscall(&xtime, clock);
 }
+
+/**
+ * getboottime - Return the real time of system boot.
+ * @ts:		pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec.
+ *
+ * This is based on the wall_to_monotonic offset and the total suspend
+ * time. Calls to settimeofday will affect the value returned (which
+ * basically means that however wrong your real time clock is at boot time,
+ * you get the right time here).
+ */
+void getboottime(struct timespec *ts)
+{
+	set_normalized_timespec(ts,
+		- (wall_to_monotonic.tv_sec + total_sleep_time),
+		- wall_to_monotonic.tv_nsec);
+}
+
+/**
+ * monotonic_to_bootbased - Convert the monotonic time to boot based.
+ * @ts:		pointer to the timespec to be converted
+ */
+void monotonic_to_bootbased(struct timespec *ts)
+{
+	ts->tv_sec += total_sleep_time;
+}
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index 8bbcfb7..e5edc3a 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -38,7 +38,7 @@
 
 static void print_name_offset(struct seq_file *m, void *sym)
 {
-	char symname[KSYM_NAME_LEN+1];
+	char symname[KSYM_NAME_LEN];
 
 	if (lookup_symbol_name((unsigned long)sym, symname) < 0)
 		SEQ_printf(m, "<%p>", sym);
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
index 868f1bc..8ed62fd 100644
--- a/kernel/time/timer_stats.c
+++ b/kernel/time/timer_stats.c
@@ -68,6 +68,7 @@
 	 * Number of timeout events:
 	 */
 	unsigned long		count;
+	unsigned int		timer_flag;
 
 	/*
 	 * We save the command-line string to preserve
@@ -117,21 +118,6 @@
 
 static atomic_t overflow_count;
 
-static void reset_entries(void)
-{
-	nr_entries = 0;
-	memset(entries, 0, sizeof(entries));
-	atomic_set(&overflow_count, 0);
-}
-
-static struct entry *alloc_entry(void)
-{
-	if (nr_entries >= MAX_ENTRIES)
-		return NULL;
-
-	return entries + nr_entries++;
-}
-
 /*
  * The entries are in a hash-table, for fast lookup:
  */
@@ -149,6 +135,22 @@
 
 static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly;
 
+static void reset_entries(void)
+{
+	nr_entries = 0;
+	memset(entries, 0, sizeof(entries));
+	memset(tstat_hash_table, 0, sizeof(tstat_hash_table));
+	atomic_set(&overflow_count, 0);
+}
+
+static struct entry *alloc_entry(void)
+{
+	if (nr_entries >= MAX_ENTRIES)
+		return NULL;
+
+	return entries + nr_entries++;
+}
+
 static int match_entries(struct entry *entry1, struct entry *entry2)
 {
 	return entry1->timer       == entry2->timer	  &&
@@ -202,12 +204,15 @@
 	if (curr) {
 		*curr = *entry;
 		curr->count = 0;
+		curr->next = NULL;
 		memcpy(curr->comm, comm, TASK_COMM_LEN);
+
+		smp_mb(); /* Ensure that curr is initialized before insert */
+
 		if (prev)
 			prev->next = curr;
 		else
 			*head = curr;
-		curr->next = NULL;
 	}
  out_unlock:
 	spin_unlock(&table_lock);
@@ -227,19 +232,26 @@
  * incremented. Otherwise the timer is registered in a free slot.
  */
 void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
-			      void *timerf, char * comm)
+			      void *timerf, char *comm,
+			      unsigned int timer_flag)
 {
 	/*
 	 * It doesnt matter which lock we take:
 	 */
-	spinlock_t *lock = &per_cpu(lookup_lock, raw_smp_processor_id());
+	spinlock_t *lock;
 	struct entry *entry, input;
 	unsigned long flags;
 
+	if (likely(!active))
+		return;
+
+	lock = &per_cpu(lookup_lock, raw_smp_processor_id());
+
 	input.timer = timer;
 	input.start_func = startf;
 	input.expire_func = timerf;
 	input.pid = pid;
+	input.timer_flag = timer_flag;
 
 	spin_lock_irqsave(lock, flags);
 	if (!active)
@@ -257,7 +269,7 @@
 
 static void print_name_offset(struct seq_file *m, unsigned long addr)
 {
-	char symname[KSYM_NAME_LEN+1];
+	char symname[KSYM_NAME_LEN];
 
 	if (lookup_symbol_name(addr, symname) < 0)
 		seq_printf(m, "<%p>", (void *)addr);
@@ -286,7 +298,7 @@
 	period = ktime_to_timespec(time);
 	ms = period.tv_nsec / 1000000;
 
-	seq_puts(m, "Timer Stats Version: v0.1\n");
+	seq_puts(m, "Timer Stats Version: v0.2\n");
 	seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
 	if (atomic_read(&overflow_count))
 		seq_printf(m, "Overflow: %d entries\n",
@@ -294,8 +306,13 @@
 
 	for (i = 0; i < nr_entries; i++) {
 		entry = entries + i;
-		seq_printf(m, "%4lu, %5d %-16s ",
+ 		if (entry->timer_flag & TIMER_STATS_FLAG_DEFERRABLE) {
+			seq_printf(m, "%4luD, %5d %-16s ",
 				entry->count, entry->pid, entry->comm);
+		} else {
+			seq_printf(m, " %4lu, %5d %-16s ",
+				entry->count, entry->pid, entry->comm);
+		}
 
 		print_name_offset(m, (unsigned long)entry->start_func);
 		seq_puts(m, " (");
@@ -360,6 +377,7 @@
 		if (!active) {
 			reset_entries();
 			time_start = ktime_get();
+			smp_mb();
 			active = 1;
 		}
 		break;
diff --git a/kernel/timer.c b/kernel/timer.c
index 5ec5490..b7792fb 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -305,6 +305,20 @@
 	memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
 	timer->start_pid = current->pid;
 }
+
+static void timer_stats_account_timer(struct timer_list *timer)
+{
+	unsigned int flag = 0;
+
+	if (unlikely(tbase_get_deferrable(timer->base)))
+		flag |= TIMER_STATS_FLAG_DEFERRABLE;
+
+	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
+				 timer->function, timer->start_comm, flag);
+}
+
+#else
+static void timer_stats_account_timer(struct timer_list *timer) {}
 #endif
 
 /**
@@ -666,7 +680,7 @@
 static unsigned long __next_timer_interrupt(tvec_base_t *base)
 {
 	unsigned long timer_jiffies = base->timer_jiffies;
-	unsigned long expires = timer_jiffies + (LONG_MAX >> 1);
+	unsigned long expires = timer_jiffies + NEXT_TIMER_MAX_DELTA;
 	int index, slot, array, found = 0;
 	struct timer_list *nte;
 	tvec_t *varray[4];
@@ -752,6 +766,14 @@
 
 	tsdelta = ktime_to_timespec(hr_delta);
 	delta = timespec_to_jiffies(&tsdelta);
+
+	/*
+	 * Limit the delta to the max value, which is checked in
+	 * tick_nohz_stop_sched_tick():
+	 */
+	if (delta > NEXT_TIMER_MAX_DELTA)
+		delta = NEXT_TIMER_MAX_DELTA;
+
 	/*
 	 * Take rounding errors in to account and make sure, that it
 	 * expires in the next tick. Otherwise we go into an endless
@@ -1106,6 +1128,7 @@
 		getnstimeofday(&tp);
 		tp.tv_sec += wall_to_monotonic.tv_sec;
 		tp.tv_nsec += wall_to_monotonic.tv_nsec;
+		monotonic_to_bootbased(&tp);
 		if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
 			tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
 			tp.tv_sec++;
@@ -1198,7 +1221,8 @@
 			/*
 			 * The APs use this path later in boot
 			 */
-			base = kmalloc_node(sizeof(*base), GFP_KERNEL,
+			base = kmalloc_node(sizeof(*base),
+						GFP_KERNEL | __GFP_ZERO,
 						cpu_to_node(cpu));
 			if (!base)
 				return -ENOMEM;
@@ -1209,7 +1233,6 @@
 				kfree(base);
 				return -ENOMEM;
 			}
-			memset(base, 0, sizeof(*base));
 			per_cpu(tvec_bases, cpu) = base;
 		} else {
 			/*
diff --git a/kernel/user.c b/kernel/user.c
index 4869563..98b8250 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -14,20 +14,19 @@
 #include <linux/bitops.h>
 #include <linux/key.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/user_namespace.h>
 
 /*
  * UID task count cache, to get fast user lookup in "alloc_uid"
  * when changing user ID's (ie setuid() and friends).
  */
 
-#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
-#define UIDHASH_SZ		(1 << UIDHASH_BITS)
 #define UIDHASH_MASK		(UIDHASH_SZ - 1)
 #define __uidhashfn(uid)	(((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK)
-#define uidhashentry(uid)	(uidhash_table + __uidhashfn((uid)))
+#define uidhashentry(ns, uid)	((ns)->uidhash_table + __uidhashfn((uid)))
 
 static struct kmem_cache *uid_cachep;
-static struct list_head uidhash_table[UIDHASH_SZ];
 
 /*
  * The uidhash_lock is mostly taken from process context, but it is
@@ -94,9 +93,10 @@
 {
 	struct user_struct *ret;
 	unsigned long flags;
+	struct user_namespace *ns = current->nsproxy->user_ns;
 
 	spin_lock_irqsave(&uidhash_lock, flags);
-	ret = uid_hash_find(uid, uidhashentry(uid));
+	ret = uid_hash_find(uid, uidhashentry(ns, uid));
 	spin_unlock_irqrestore(&uidhash_lock, flags);
 	return ret;
 }
@@ -120,9 +120,9 @@
 	}
 }
 
-struct user_struct * alloc_uid(uid_t uid)
+struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
 {
-	struct list_head *hashent = uidhashentry(uid);
+	struct list_head *hashent = uidhashentry(ns, uid);
 	struct user_struct *up;
 
 	spin_lock_irq(&uidhash_lock);
@@ -211,11 +211,11 @@
 			0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
 
 	for(n = 0; n < UIDHASH_SZ; ++n)
-		INIT_LIST_HEAD(uidhash_table + n);
+		INIT_LIST_HEAD(init_user_ns.uidhash_table + n);
 
 	/* Insert the root user immediately (init already runs as root) */
 	spin_lock_irq(&uidhash_lock);
-	uid_hash_insert(&root_user, uidhashentry(0));
+	uid_hash_insert(&root_user, uidhashentry(&init_user_ns, 0));
 	spin_unlock_irq(&uidhash_lock);
 
 	return 0;
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
new file mode 100644
index 0000000..d055d98
--- /dev/null
+++ b/kernel/user_namespace.c
@@ -0,0 +1,87 @@
+/*
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation, version 2 of the
+ *  License.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/nsproxy.h>
+#include <linux/user_namespace.h>
+
+struct user_namespace init_user_ns = {
+	.kref = {
+		.refcount	= ATOMIC_INIT(2),
+	},
+	.root_user = &root_user,
+};
+
+EXPORT_SYMBOL_GPL(init_user_ns);
+
+#ifdef CONFIG_USER_NS
+
+/*
+ * Clone a new ns copying an original user ns, setting refcount to 1
+ * @old_ns: namespace to clone
+ * Return NULL on error (failure to kmalloc), new ns otherwise
+ */
+static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
+{
+	struct user_namespace *ns;
+	struct user_struct *new_user;
+	int n;
+
+	ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL);
+	if (!ns)
+		return ERR_PTR(-ENOMEM);
+
+	kref_init(&ns->kref);
+
+	for (n = 0; n < UIDHASH_SZ; ++n)
+		INIT_LIST_HEAD(ns->uidhash_table + n);
+
+	/* Insert new root user.  */
+	ns->root_user = alloc_uid(ns, 0);
+	if (!ns->root_user) {
+		kfree(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Reset current->user with a new one */
+	new_user = alloc_uid(ns, current->uid);
+	if (!new_user) {
+		free_uid(ns->root_user);
+		kfree(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	switch_uid(new_user);
+	return ns;
+}
+
+struct user_namespace * copy_user_ns(int flags, struct user_namespace *old_ns)
+{
+	struct user_namespace *new_ns;
+
+	BUG_ON(!old_ns);
+	get_user_ns(old_ns);
+
+	if (!(flags & CLONE_NEWUSER))
+		return old_ns;
+
+	new_ns = clone_user_ns(old_ns);
+
+	put_user_ns(old_ns);
+	return new_ns;
+}
+
+void free_user_ns(struct kref *kref)
+{
+	struct user_namespace *ns;
+
+	ns = container_of(kref, struct user_namespace, kref);
+	kfree(ns);
+}
+
+#endif /* CONFIG_USER_NS */
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 160c8c5..9d8180a 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -13,6 +13,7 @@
 #include <linux/uts.h>
 #include <linux/utsname.h>
 #include <linux/version.h>
+#include <linux/err.h>
 
 /*
  * Clone a new ns copying an original utsname, setting refcount to 1
@@ -24,10 +25,11 @@
 	struct uts_namespace *ns;
 
 	ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL);
-	if (ns) {
-		memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
-		kref_init(&ns->kref);
-	}
+	if (!ns)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
+	kref_init(&ns->kref);
 	return ns;
 }
 
@@ -37,7 +39,7 @@
  * utsname of this process won't be seen by parent, and vice
  * versa.
  */
-struct uts_namespace *copy_utsname(int flags, struct uts_namespace *old_ns)
+struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns)
 {
 	struct uts_namespace *new_ns;
 
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
index f22b9db..c76c064 100644
--- a/kernel/utsname_sysctl.c
+++ b/kernel/utsname_sysctl.c
@@ -18,10 +18,7 @@
 static void *get_uts(ctl_table *table, int write)
 {
 	char *which = table->data;
-#ifdef CONFIG_UTS_NS
-	struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
-	which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
-#endif
+
 	if (!write)
 		down_read(&uts_sem);
 	else
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index fb56fed..58e5c15 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -47,7 +47,6 @@
 
 	struct workqueue_struct *wq;
 	struct task_struct *thread;
-	int should_stop;
 
 	int run_depth;		/* Detect run_workqueue() recursion depth */
 } ____cacheline_aligned;
@@ -71,7 +70,13 @@
 
 static int singlethread_cpu __read_mostly;
 static cpumask_t cpu_singlethread_map __read_mostly;
-/* optimization, we could use cpu_possible_map */
+/*
+ * _cpu_down() first removes CPU from cpu_online_map, then CPU_DEAD
+ * flushes cwq->worklist. This means that flush_workqueue/wait_on_work
+ * which comes in between can't use for_each_online_cpu(). We could
+ * use cpu_possible_map, the cpumask below is more a documentation
+ * than optimization.
+ */
 static cpumask_t cpu_populated_map __read_mostly;
 
 /* If it's single threaded, it isn't in the list of workqueues. */
@@ -272,44 +277,27 @@
 	spin_unlock_irq(&cwq->lock);
 }
 
-/*
- * NOTE: the caller must not touch *cwq if this func returns true
- */
-static int cwq_should_stop(struct cpu_workqueue_struct *cwq)
-{
-	int should_stop = cwq->should_stop;
-
-	if (unlikely(should_stop)) {
-		spin_lock_irq(&cwq->lock);
-		should_stop = cwq->should_stop && list_empty(&cwq->worklist);
-		if (should_stop)
-			cwq->thread = NULL;
-		spin_unlock_irq(&cwq->lock);
-	}
-
-	return should_stop;
-}
-
 static int worker_thread(void *__cwq)
 {
 	struct cpu_workqueue_struct *cwq = __cwq;
 	DEFINE_WAIT(wait);
 
-	if (!cwq->wq->freezeable)
-		current->flags |= PF_NOFREEZE;
+	if (cwq->wq->freezeable)
+		set_freezable();
 
 	set_user_nice(current, -5);
 
 	for (;;) {
 		prepare_to_wait(&cwq->more_work, &wait, TASK_INTERRUPTIBLE);
-		if (!freezing(current) && !cwq->should_stop
-		    && list_empty(&cwq->worklist))
+		if (!freezing(current) &&
+		    !kthread_should_stop() &&
+		    list_empty(&cwq->worklist))
 			schedule();
 		finish_wait(&cwq->more_work, &wait);
 
 		try_to_freeze();
 
-		if (cwq_should_stop(cwq))
+		if (kthread_should_stop())
 			break;
 
 		run_workqueue(cwq);
@@ -340,18 +328,21 @@
 	insert_work(cwq, &barr->work, tail);
 }
 
-static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
+static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
 {
+	int active;
+
 	if (cwq->thread == current) {
 		/*
 		 * Probably keventd trying to flush its own queue. So simply run
 		 * it by hand rather than deadlocking.
 		 */
 		run_workqueue(cwq);
+		active = 1;
 	} else {
 		struct wq_barrier barr;
-		int active = 0;
 
+		active = 0;
 		spin_lock_irq(&cwq->lock);
 		if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) {
 			insert_wq_barrier(cwq, &barr, 1);
@@ -362,6 +353,8 @@
 		if (active)
 			wait_for_completion(&barr.done);
 	}
+
+	return active;
 }
 
 /**
@@ -389,16 +382,16 @@
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
 /*
- * Upon a successful return, the caller "owns" WORK_STRUCT_PENDING bit,
+ * Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit,
  * so this work can't be re-armed in any way.
  */
 static int try_to_grab_pending(struct work_struct *work)
 {
 	struct cpu_workqueue_struct *cwq;
-	int ret = 0;
+	int ret = -1;
 
 	if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work)))
-		return 1;
+		return 0;
 
 	/*
 	 * The queueing is in progress, or it is already queued. Try to
@@ -464,10 +457,28 @@
 		wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
 }
 
+static int __cancel_work_timer(struct work_struct *work,
+				struct timer_list* timer)
+{
+	int ret;
+
+	do {
+		ret = (timer && likely(del_timer(timer)));
+		if (!ret)
+			ret = try_to_grab_pending(work);
+		wait_on_work(work);
+	} while (unlikely(ret < 0));
+
+	work_clear_pending(work);
+	return ret;
+}
+
 /**
  * cancel_work_sync - block until a work_struct's callback has terminated
  * @work: the work which is to be flushed
  *
+ * Returns true if @work was pending.
+ *
  * cancel_work_sync() will cancel the work if it is queued. If the work's
  * callback appears to be running, cancel_work_sync() will block until it
  * has completed.
@@ -483,31 +494,26 @@
  * The caller must ensure that workqueue_struct on which this work was last
  * queued can't be destroyed before this function returns.
  */
-void cancel_work_sync(struct work_struct *work)
+int cancel_work_sync(struct work_struct *work)
 {
-	while (!try_to_grab_pending(work))
-		cpu_relax();
-	wait_on_work(work);
-	work_clear_pending(work);
+	return __cancel_work_timer(work, NULL);
 }
 EXPORT_SYMBOL_GPL(cancel_work_sync);
 
 /**
- * cancel_rearming_delayed_work - reliably kill off a delayed work.
+ * cancel_delayed_work_sync - reliably kill off a delayed work.
  * @dwork: the delayed work struct
  *
+ * Returns true if @dwork was pending.
+ *
  * It is possible to use this function if @dwork rearms itself via queue_work()
  * or queue_delayed_work(). See also the comment for cancel_work_sync().
  */
-void cancel_rearming_delayed_work(struct delayed_work *dwork)
+int cancel_delayed_work_sync(struct delayed_work *dwork)
 {
-	while (!del_timer(&dwork->timer) &&
-	       !try_to_grab_pending(&dwork->work))
-		cpu_relax();
-	wait_on_work(&dwork->work);
-	work_clear_pending(&dwork->work);
+	return __cancel_work_timer(&dwork->work, &dwork->timer);
 }
-EXPORT_SYMBOL(cancel_rearming_delayed_work);
+EXPORT_SYMBOL(cancel_delayed_work_sync);
 
 static struct workqueue_struct *keventd_wq __read_mostly;
 
@@ -674,7 +680,6 @@
 		return PTR_ERR(p);
 
 	cwq->thread = p;
-	cwq->should_stop = 0;
 
 	return 0;
 }
@@ -740,29 +745,26 @@
 
 static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
 {
-	struct wq_barrier barr;
-	int alive = 0;
+	/*
+	 * Our caller is either destroy_workqueue() or CPU_DEAD,
+	 * workqueue_mutex protects cwq->thread
+	 */
+	if (cwq->thread == NULL)
+		return;
 
-	spin_lock_irq(&cwq->lock);
-	if (cwq->thread != NULL) {
-		insert_wq_barrier(cwq, &barr, 1);
-		cwq->should_stop = 1;
-		alive = 1;
-	}
-	spin_unlock_irq(&cwq->lock);
-
-	if (alive) {
-		wait_for_completion(&barr.done);
-
-		while (unlikely(cwq->thread != NULL))
-			cpu_relax();
-		/*
-		 * Wait until cwq->thread unlocks cwq->lock,
-		 * it won't touch *cwq after that.
-		 */
-		smp_rmb();
-		spin_unlock_wait(&cwq->lock);
-	}
+	flush_cpu_workqueue(cwq);
+	/*
+	 * If the caller is CPU_DEAD and cwq->worklist was not empty,
+	 * a concurrent flush_workqueue() can insert a barrier after us.
+	 * However, in that case run_workqueue() won't return and check
+	 * kthread_should_stop() until it flushes all work_struct's.
+	 * When ->worklist becomes empty it is safe to exit because no
+	 * more work_structs can be queued on this cwq: flush_workqueue
+	 * checks list_empty(), and a "normal" queue_work() can't use
+	 * a dead CPU.
+	 */
+	kthread_stop(cwq->thread);
+	cwq->thread = NULL;
 }
 
 /**
diff --git a/lib/Kconfig b/lib/Kconfig
index 2e7ae6b..e5c2c51 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -41,6 +41,14 @@
 	  kernel tree does. Such modules that use library CRC32 functions
 	  require M here.
 
+config CRC7
+	tristate "CRC7 functions"
+	help
+	  This option is provided for the case where no in-kernel-tree
+	  modules require CRC7 functions, but a module built outside
+	  the kernel tree does. Such modules that use library CRC7
+	  functions require M here.
+
 config LIBCRC32C
 	tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
 	help
@@ -64,6 +72,12 @@
 config ZLIB_DEFLATE
 	tristate
 
+config LZO_COMPRESS
+	tristate
+
+config LZO_DECOMPRESS
+	tristate
+
 #
 # Generic allocator support is selected if needed
 #
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index fbc5c62..6408440 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -105,6 +105,15 @@
 	   can be detected via the NMI-watchdog, on platforms that
 	   support it.)
 
+config SCHED_DEBUG
+	bool "Collect scheduler debugging info"
+	depends on DEBUG_KERNEL && PROC_FS
+	default y
+	help
+	  If you say Y here, the /proc/sched_debug file will be provided
+	  that can help debug the scheduler. The runtime overhead of this
+	  option is minimal.
+
 config SCHEDSTATS
 	bool "Collect scheduler statistics"
 	depends on DEBUG_KERNEL && PROC_FS
@@ -126,7 +135,10 @@
 	  reprogrammed. The statistics can be read from /proc/timer_stats.
 	  The statistics collection is started by writing 1 to /proc/timer_stats,
 	  writing 0 stops it. This feature is useful to collect information
-	  about timer usage patterns in kernel and userspace.
+	  about timer usage patterns in kernel and userspace. This feature
+	  is lightweight if enabled in the kernel config but not activated
+	  (it defaults to deactivated on bootup and will only be activated
+	  if some application like powertop activates it explicitly).
 
 config DEBUG_SLAB
 	bool "Debug slab memory allocations"
@@ -140,6 +152,19 @@
 	bool "Memory leak debugging"
 	depends on DEBUG_SLAB
 
+config SLUB_DEBUG_ON
+	bool "SLUB debugging on by default"
+	depends on SLUB && SLUB_DEBUG
+	default n
+	help
+	  Boot with debugging on by default. SLUB boots by default with
+	  the runtime debug capabilities switched off. Enabling this is
+	  equivalent to specifying the "slub_debug" parameter on boot.
+	  There is no support for more fine grained debug control like
+	  possible with slub_debug=xxx. SLUB debugging may be switched
+	  off in a kernel built with CONFIG_SLUB_DEBUG_ON by specifying
+	  "slub_debug=-".
+
 config DEBUG_PREEMPT
 	bool "Debug preemptible kernel"
 	depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT
@@ -378,14 +403,13 @@
 config RCU_TORTURE_TEST
 	tristate "torture tests for RCU"
 	depends on DEBUG_KERNEL
+	depends on m
 	default n
 	help
 	  This option provides a kernel module that runs torture tests
 	  on the RCU infrastructure.  The kernel module may be built
 	  after the fact on the running kernel to be tested, if desired.
 
-	  Say Y here if you want RCU torture tests to start automatically
-	  at boot time (you probably don't).
 	  Say M if you want the RCU torture tests to build as a module.
 	  Say N if you are unsure.
 
diff --git a/lib/Makefile b/lib/Makefile
index c8c8e20..da68b2c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -21,7 +21,7 @@
 endif
 
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
-obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
+obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
@@ -43,12 +43,15 @@
 obj-$(CONFIG_CRC16)	+= crc16.o
 obj-$(CONFIG_CRC_ITU_T)	+= crc-itu-t.o
 obj-$(CONFIG_CRC32)	+= crc32.o
+obj-$(CONFIG_CRC7)	+= crc7.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
 obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
+obj-$(CONFIG_LZO_COMPRESS) += lzo/
+obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
 
 obj-$(CONFIG_TEXTSEARCH) += textsearch.o
 obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
diff --git a/lib/bug.c b/lib/bug.c
index 014b582..530f38f 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -38,6 +38,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/bug.h>
+#include <linux/sched.h>
 
 extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
 
@@ -112,7 +113,7 @@
 	return module_find_bug(bugaddr);
 }
 
-enum bug_trap_type report_bug(unsigned long bugaddr)
+enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
 {
 	const struct bug_entry *bug;
 	const char *file;
@@ -147,7 +148,7 @@
 			       "[verbose debug info unavailable]\n",
 			       (void *)bugaddr);
 
-		dump_stack();
+		show_regs(regs);
 		return BUG_TRAP_TYPE_WARN;
 	}
 
diff --git a/lib/check_signature.c b/lib/check_signature.c
new file mode 100644
index 0000000..fd6af19
--- /dev/null
+++ b/lib/check_signature.c
@@ -0,0 +1,26 @@
+#include <linux/io.h>
+#include <linux/module.h>
+
+/**
+ *	check_signature		-	find BIOS signatures
+ *	@io_addr: mmio address to check
+ *	@signature:  signature block
+ *	@length: length of signature
+ *
+ *	Perform a signature comparison with the mmio address io_addr. This
+ *	address should have been obtained by ioremap.
+ *	Returns 1 on a match.
+ */
+
+int check_signature(const volatile void __iomem *io_addr,
+			const unsigned char *signature, int length)
+{
+	while (length--) {
+		if (readb(io_addr) != *signature)
+			return 0;
+		io_addr++;
+		signature++;
+	}
+	return 1;
+}
+EXPORT_SYMBOL(check_signature);
diff --git a/lib/crc7.c b/lib/crc7.c
new file mode 100644
index 0000000..f1c3a14
--- /dev/null
+++ b/lib/crc7.c
@@ -0,0 +1,68 @@
+/*
+ *      crc7.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/crc7.h>
+
+
+/* Table for CRC-7 (polynomial x^7 + x^3 + 1) */
+const u8 crc7_syndrome_table[256] = {
+	0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+	0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+	0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
+	0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
+	0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
+	0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
+	0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
+	0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
+	0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
+	0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
+	0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
+	0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
+	0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
+	0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
+	0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
+	0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
+	0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
+	0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
+	0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
+	0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
+	0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+	0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+	0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
+	0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
+	0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
+	0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
+	0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
+	0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
+	0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
+	0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
+	0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
+	0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
+};
+EXPORT_SYMBOL(crc7_syndrome_table);
+
+/**
+ * crc7 - update the CRC7 for the data buffer
+ * @crc:     previous CRC7 value
+ * @buffer:  data pointer
+ * @len:     number of bytes in the buffer
+ * Context: any
+ *
+ * Returns the updated CRC7 value.
+ */
+u8 crc7(u8 crc, const u8 *buffer, size_t len)
+{
+	while (len--)
+		crc = crc7_byte(crc, *buffer++);
+	return crc;
+}
+EXPORT_SYMBOL(crc7);
+
+MODULE_DESCRIPTION("CRC7 calculations");
+MODULE_LICENSE("GPL");
diff --git a/lib/genalloc.c b/lib/genalloc.c
index eb7c2ba..f6d276d 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -54,11 +54,10 @@
 	int nbytes = sizeof(struct gen_pool_chunk) +
 				(nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
 
-	chunk = kmalloc_node(nbytes, GFP_KERNEL, nid);
+	chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
 	if (unlikely(chunk == NULL))
 		return -1;
 
-	memset(chunk, 0, nbytes);
 	spin_lock_init(&chunk->lock);
 	chunk->start_addr = addr;
 	chunk->end_addr = addr + size;
diff --git a/lib/hexdump.c b/lib/hexdump.c
index e6da5b7..473f5ae 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -16,42 +16,98 @@
  * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
  * @buf: data blob to dump
  * @len: number of bytes in the @buf
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
  * @linebuf: where to put the converted data
  * @linebuflen: total size of @linebuf, including space for terminating NUL
+ * @ascii: include ASCII after the hex output
  *
  * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
- * 16 bytes of input data converted to hex + ASCII output.
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
  *
  * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
  * to a hex + ASCII dump at the supplied memory location.
  * The converted output is always NUL-terminated.
  *
  * E.g.:
- *	hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf));
+ *   hex_dump_to_buffer(frame->data, frame->len, 16, 1,
+ *			linebuf, sizeof(linebuf), 1);
  *
  * example output buffer:
- * 40414243 44454647 48494a4b 4c4d4e4f  @ABCDEFGHIJKLMNO
+ * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
  */
-void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
-			size_t linebuflen)
+void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
+			int groupsize, char *linebuf, size_t linebuflen,
+			bool ascii)
 {
 	const u8 *ptr = buf;
 	u8 ch;
 	int j, lx = 0;
+	int ascii_column;
 
-	for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) {
-		if (j && !(j % 4))
+	if (rowsize != 16 && rowsize != 32)
+		rowsize = 16;
+
+	if (!len)
+		goto nil;
+	if (len > rowsize)		/* limit to one line at a time */
+		len = rowsize;
+	if ((len % groupsize) != 0)	/* no mixed size output */
+		groupsize = 1;
+
+	switch (groupsize) {
+	case 8: {
+		const u64 *ptr8 = buf;
+		int ngroups = len / groupsize;
+
+		for (j = 0; j < ngroups; j++)
+			lx += scnprintf(linebuf + lx, linebuflen - lx,
+				"%16.16llx ", (unsigned long long)*(ptr8 + j));
+		ascii_column = 17 * ngroups + 2;
+		break;
+	}
+
+	case 4: {
+		const u32 *ptr4 = buf;
+		int ngroups = len / groupsize;
+
+		for (j = 0; j < ngroups; j++)
+			lx += scnprintf(linebuf + lx, linebuflen - lx,
+				"%8.8x ", *(ptr4 + j));
+		ascii_column = 9 * ngroups + 2;
+		break;
+	}
+
+	case 2: {
+		const u16 *ptr2 = buf;
+		int ngroups = len / groupsize;
+
+		for (j = 0; j < ngroups; j++)
+			lx += scnprintf(linebuf + lx, linebuflen - lx,
+				"%4.4x ", *(ptr2 + j));
+		ascii_column = 5 * ngroups + 2;
+		break;
+	}
+
+	default:
+		for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen;
+		     j++) {
+			ch = ptr[j];
+			linebuf[lx++] = hex_asc(ch >> 4);
+			linebuf[lx++] = hex_asc(ch & 0x0f);
 			linebuf[lx++] = ' ';
-		ch = ptr[j];
-		linebuf[lx++] = hex_asc(ch >> 4);
-		linebuf[lx++] = hex_asc(ch & 0x0f);
+		}
+		ascii_column = 3 * rowsize + 2;
+		break;
 	}
-	if ((lx + 2) < linebuflen) {
+	if (!ascii)
+		goto nil;
+
+	while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
 		linebuf[lx++] = ' ';
-		linebuf[lx++] = ' ';
-	}
-	for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++)
+	for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++)
 		linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
+nil:
 	linebuf[lx++] = '\0';
 }
 EXPORT_SYMBOL(hex_dump_to_buffer);
@@ -59,46 +115,83 @@
 /**
  * print_hex_dump - print a text hex dump to syslog for a binary blob of data
  * @level: kernel log level (e.g. KERN_DEBUG)
+ * @prefix_str: string to prefix each line with;
+ *  caller supplies trailing spaces for alignment if desired
  * @prefix_type: controls whether prefix of an offset, address, or none
  *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
  * @buf: data blob to dump
  * @len: number of bytes in the @buf
+ * @ascii: include ASCII after the hex output
  *
  * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
  * to the kernel log at the specified kernel log level, with an optional
  * leading prefix.
  *
- * E.g.:
- *   print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
+ * print_hex_dump() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * "line size" chunks to format and print.
  *
- * Example output using %DUMP_PREFIX_OFFSET:
- * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f  @ABCDEFGHIJKLMNO
- * Example output using %DUMP_PREFIX_ADDRESS:
- * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f  pqrstuvwxyz{|}~.
+ * E.g.:
+ *   print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
+ *		16, 1, frame->data, frame->len, 1);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
+ * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
+ * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c  pqrstuvwxyz{|}~.
  */
-void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len)
+void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
+			int rowsize, int groupsize,
+			void *buf, size_t len, bool ascii)
 {
 	u8 *ptr = buf;
 	int i, linelen, remaining = len;
-	unsigned char linebuf[100];
+	unsigned char linebuf[200];
 
-	for (i = 0; i < len; i += 16) {
-		linelen = min(remaining, 16);
-		remaining -= 16;
-		hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf));
+	if (rowsize != 16 && rowsize != 32)
+		rowsize = 16;
+
+	for (i = 0; i < len; i += rowsize) {
+		linelen = min(remaining, rowsize);
+		remaining -= rowsize;
+		hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
+				linebuf, sizeof(linebuf), ascii);
 
 		switch (prefix_type) {
 		case DUMP_PREFIX_ADDRESS:
-			printk("%s%*p: %s\n", level,
+			printk("%s%s%*p: %s\n", level, prefix_str,
 				(int)(2 * sizeof(void *)), ptr + i, linebuf);
 			break;
 		case DUMP_PREFIX_OFFSET:
-			printk("%s%.8x: %s\n", level, i, linebuf);
+			printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
 			break;
 		default:
-			printk("%s%s\n", level, linebuf);
+			printk("%s%s%s\n", level, prefix_str, linebuf);
 			break;
 		}
 	}
 }
 EXPORT_SYMBOL(print_hex_dump);
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ *  caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), with log level of KERN_DEBUG,
+ * rowsize of 16, groupsize of 1, and ASCII output included.
+ */
+void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+			void *buf, size_t len)
+{
+	print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
+			buf, len, 1);
+}
+EXPORT_SYMBOL(print_hex_dump_bytes);
diff --git a/lib/idr.c b/lib/idr.c
index 305117c..5ca67b3 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -70,6 +70,26 @@
 	spin_unlock_irqrestore(&idp->lock, flags);
 }
 
+static void idr_mark_full(struct idr_layer **pa, int id)
+{
+	struct idr_layer *p = pa[0];
+	int l = 0;
+
+	__set_bit(id & IDR_MASK, &p->bitmap);
+	/*
+	 * If this layer is full mark the bit in the layer above to
+	 * show that this part of the radix tree is full.  This may
+	 * complete the layer above and require walking up the radix
+	 * tree.
+	 */
+	while (p->bitmap == IDR_FULL) {
+		if (!(p = pa[++l]))
+			break;
+		id = id >> IDR_BITS;
+		__set_bit((id & IDR_MASK), &p->bitmap);
+	}
+}
+
 /**
  * idr_pre_get - reserver resources for idr allocation
  * @idp:	idr handle
@@ -95,15 +115,15 @@
 }
 EXPORT_SYMBOL(idr_pre_get);
 
-static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
+static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
 {
 	int n, m, sh;
 	struct idr_layer *p, *new;
-	struct idr_layer *pa[MAX_LEVEL];
-	int l, id;
+	int l, id, oid;
 	long bm;
 
 	id = *starting_id;
+ restart:
 	p = idp->top;
 	l = idp->layers;
 	pa[l--] = NULL;
@@ -117,12 +137,23 @@
 		if (m == IDR_SIZE) {
 			/* no space available go back to previous layer. */
 			l++;
+			oid = id;
 			id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
+
+			/* if already at the top layer, we need to grow */
 			if (!(p = pa[l])) {
 				*starting_id = id;
 				return -2;
 			}
-			continue;
+
+			/* If we need to go up one layer, continue the
+			 * loop; otherwise, restart from the top.
+			 */
+			sh = IDR_BITS * (l + 1);
+			if (oid >> sh == id >> sh)
+				continue;
+			else
+				goto restart;
 		}
 		if (m != n) {
 			sh = IDR_BITS*l;
@@ -144,30 +175,13 @@
 		pa[l--] = p;
 		p = p->ary[m];
 	}
-	/*
-	 * We have reached the leaf node, plant the
-	 * users pointer and return the raw id.
-	 */
-	p->ary[m] = (struct idr_layer *)ptr;
-	__set_bit(m, &p->bitmap);
-	p->count++;
-	/*
-	 * If this layer is full mark the bit in the layer above
-	 * to show that this part of the radix tree is full.
-	 * This may complete the layer above and require walking
-	 * up the radix tree.
-	 */
-	n = id;
-	while (p->bitmap == IDR_FULL) {
-		if (!(p = pa[++l]))
-			break;
-		n = n >> IDR_BITS;
-		__set_bit((n & IDR_MASK), &p->bitmap);
-	}
-	return(id);
+
+	pa[l] = p;
+	return id;
 }
 
-static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+static int idr_get_empty_slot(struct idr *idp, int starting_id,
+			      struct idr_layer **pa)
 {
 	struct idr_layer *p, *new;
 	int layers, v, id;
@@ -213,12 +227,31 @@
 	}
 	idp->top = p;
 	idp->layers = layers;
-	v = sub_alloc(idp, ptr, &id);
+	v = sub_alloc(idp, &id, pa);
 	if (v == -2)
 		goto build_up;
 	return(v);
 }
 
+static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+{
+	struct idr_layer *pa[MAX_LEVEL];
+	int id;
+
+	id = idr_get_empty_slot(idp, starting_id, pa);
+	if (id >= 0) {
+		/*
+		 * Successfully found an empty slot.  Install the user
+		 * pointer and mark the slot full.
+		 */
+		pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
+		pa[0]->count++;
+		idr_mark_full(pa, id);
+	}
+
+	return id;
+}
+
 /**
  * idr_get_new_above - allocate new idr entry above or equal to a start id
  * @idp: idr handle
@@ -358,6 +391,53 @@
 EXPORT_SYMBOL(idr_remove);
 
 /**
+ * idr_remove_all - remove all ids from the given idr tree
+ * @idp: idr handle
+ *
+ * idr_destroy() only frees up unused, cached idp_layers, but this
+ * function will remove all id mappings and leave all idp_layers
+ * unused.
+ *
+ * A typical clean-up sequence for objects stored in an idr tree, will
+ * use idr_for_each() to free all objects, if necessay, then
+ * idr_remove_all() to remove all ids, and idr_destroy() to free
+ * up the cached idr_layers.
+ */
+void idr_remove_all(struct idr *idp)
+{
+	int n, id, max, error = 0;
+	struct idr_layer *p;
+	struct idr_layer *pa[MAX_LEVEL];
+	struct idr_layer **paa = &pa[0];
+
+	n = idp->layers * IDR_BITS;
+	p = idp->top;
+	max = 1 << n;
+
+	id = 0;
+	while (id < max && !error) {
+		while (n > IDR_BITS && p) {
+			n -= IDR_BITS;
+			*paa++ = p;
+			p = p->ary[(id >> n) & IDR_MASK];
+		}
+
+		id += 1 << n;
+		while (n < fls(id)) {
+			if (p) {
+				memset(p, 0, sizeof *p);
+				free_layer(idp, p);
+			}
+			n += IDR_BITS;
+			p = *--paa;
+		}
+	}
+	idp->top = NULL;
+	idp->layers = 0;
+}
+EXPORT_SYMBOL(idr_remove_all);
+
+/**
  * idr_destroy - release all cached layers within an idr tree
  * idp: idr handle
  */
@@ -404,6 +484,61 @@
 EXPORT_SYMBOL(idr_find);
 
 /**
+ * idr_for_each - iterate through all stored pointers
+ * @idp: idr handle
+ * @fn: function to be called for each pointer
+ * @data: data passed back to callback function
+ *
+ * Iterate over the pointers registered with the given idr.  The
+ * callback function will be called for each pointer currently
+ * registered, passing the id, the pointer and the data pointer passed
+ * to this function.  It is not safe to modify the idr tree while in
+ * the callback, so functions such as idr_get_new and idr_remove are
+ * not allowed.
+ *
+ * We check the return of @fn each time. If it returns anything other
+ * than 0, we break out and return that value.
+ *
+ * The caller must serialize idr_for_each() vs idr_get_new() and idr_remove().
+ */
+int idr_for_each(struct idr *idp,
+		 int (*fn)(int id, void *p, void *data), void *data)
+{
+	int n, id, max, error = 0;
+	struct idr_layer *p;
+	struct idr_layer *pa[MAX_LEVEL];
+	struct idr_layer **paa = &pa[0];
+
+	n = idp->layers * IDR_BITS;
+	p = idp->top;
+	max = 1 << n;
+
+	id = 0;
+	while (id < max) {
+		while (n > 0 && p) {
+			n -= IDR_BITS;
+			*paa++ = p;
+			p = p->ary[(id >> n) & IDR_MASK];
+		}
+
+		if (p) {
+			error = fn(id, (void *)p, data);
+			if (error)
+				break;
+		}
+
+		id += 1 << n;
+		while (n < fls(id)) {
+			n += IDR_BITS;
+			p = *--paa;
+		}
+	}
+
+	return error;
+}
+EXPORT_SYMBOL(idr_for_each);
+
+/**
  * idr_replace - replace pointer for given id
  * @idp: idr handle
  * @ptr: pointer you want associated with the id
@@ -473,3 +608,248 @@
 	spin_lock_init(&idp->lock);
 }
 EXPORT_SYMBOL(idr_init);
+
+
+/*
+ * IDA - IDR based ID allocator
+ *
+ * this is id allocator without id -> pointer translation.  Memory
+ * usage is much lower than full blown idr because each id only
+ * occupies a bit.  ida uses a custom leaf node which contains
+ * IDA_BITMAP_BITS slots.
+ *
+ * 2007-04-25  written by Tejun Heo <htejun@gmail.com>
+ */
+
+static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
+{
+	unsigned long flags;
+
+	if (!ida->free_bitmap) {
+		spin_lock_irqsave(&ida->idr.lock, flags);
+		if (!ida->free_bitmap) {
+			ida->free_bitmap = bitmap;
+			bitmap = NULL;
+		}
+		spin_unlock_irqrestore(&ida->idr.lock, flags);
+	}
+
+	kfree(bitmap);
+}
+
+/**
+ * ida_pre_get - reserve resources for ida allocation
+ * @ida:	ida handle
+ * @gfp_mask:	memory allocation flag
+ *
+ * This function should be called prior to locking and calling the
+ * following function.  It preallocates enough memory to satisfy the
+ * worst possible allocation.
+ *
+ * If the system is REALLY out of memory this function returns 0,
+ * otherwise 1.
+ */
+int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
+{
+	/* allocate idr_layers */
+	if (!idr_pre_get(&ida->idr, gfp_mask))
+		return 0;
+
+	/* allocate free_bitmap */
+	if (!ida->free_bitmap) {
+		struct ida_bitmap *bitmap;
+
+		bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask);
+		if (!bitmap)
+			return 0;
+
+		free_bitmap(ida, bitmap);
+	}
+
+	return 1;
+}
+EXPORT_SYMBOL(ida_pre_get);
+
+/**
+ * ida_get_new_above - allocate new ID above or equal to a start id
+ * @ida:	ida handle
+ * @staring_id:	id to start search at
+ * @p_id:	pointer to the allocated handle
+ *
+ * Allocate new ID above or equal to @ida.  It should be called with
+ * any required locks.
+ *
+ * If memory is required, it will return -EAGAIN, you should unlock
+ * and go back to the ida_pre_get() call.  If the ida is full, it will
+ * return -ENOSPC.
+ *
+ * @p_id returns a value in the range 0 ... 0x7fffffff.
+ */
+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
+{
+	struct idr_layer *pa[MAX_LEVEL];
+	struct ida_bitmap *bitmap;
+	unsigned long flags;
+	int idr_id = starting_id / IDA_BITMAP_BITS;
+	int offset = starting_id % IDA_BITMAP_BITS;
+	int t, id;
+
+ restart:
+	/* get vacant slot */
+	t = idr_get_empty_slot(&ida->idr, idr_id, pa);
+	if (t < 0) {
+		if (t == -1)
+			return -EAGAIN;
+		else /* will be -3 */
+			return -ENOSPC;
+	}
+
+	if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
+		return -ENOSPC;
+
+	if (t != idr_id)
+		offset = 0;
+	idr_id = t;
+
+	/* if bitmap isn't there, create a new one */
+	bitmap = (void *)pa[0]->ary[idr_id & IDR_MASK];
+	if (!bitmap) {
+		spin_lock_irqsave(&ida->idr.lock, flags);
+		bitmap = ida->free_bitmap;
+		ida->free_bitmap = NULL;
+		spin_unlock_irqrestore(&ida->idr.lock, flags);
+
+		if (!bitmap)
+			return -EAGAIN;
+
+		memset(bitmap, 0, sizeof(struct ida_bitmap));
+		pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap;
+		pa[0]->count++;
+	}
+
+	/* lookup for empty slot */
+	t = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, offset);
+	if (t == IDA_BITMAP_BITS) {
+		/* no empty slot after offset, continue to the next chunk */
+		idr_id++;
+		offset = 0;
+		goto restart;
+	}
+
+	id = idr_id * IDA_BITMAP_BITS + t;
+	if (id >= MAX_ID_BIT)
+		return -ENOSPC;
+
+	__set_bit(t, bitmap->bitmap);
+	if (++bitmap->nr_busy == IDA_BITMAP_BITS)
+		idr_mark_full(pa, idr_id);
+
+	*p_id = id;
+
+	/* Each leaf node can handle nearly a thousand slots and the
+	 * whole idea of ida is to have small memory foot print.
+	 * Throw away extra resources one by one after each successful
+	 * allocation.
+	 */
+	if (ida->idr.id_free_cnt || ida->free_bitmap) {
+		struct idr_layer *p = alloc_layer(&ida->idr);
+		if (p)
+			kmem_cache_free(idr_layer_cache, p);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ida_get_new_above);
+
+/**
+ * ida_get_new - allocate new ID
+ * @ida:	idr handle
+ * @p_id:	pointer to the allocated handle
+ *
+ * Allocate new ID.  It should be called with any required locks.
+ *
+ * If memory is required, it will return -EAGAIN, you should unlock
+ * and go back to the idr_pre_get() call.  If the idr is full, it will
+ * return -ENOSPC.
+ *
+ * @id returns a value in the range 0 ... 0x7fffffff.
+ */
+int ida_get_new(struct ida *ida, int *p_id)
+{
+	return ida_get_new_above(ida, 0, p_id);
+}
+EXPORT_SYMBOL(ida_get_new);
+
+/**
+ * ida_remove - remove the given ID
+ * @ida:	ida handle
+ * @id:		ID to free
+ */
+void ida_remove(struct ida *ida, int id)
+{
+	struct idr_layer *p = ida->idr.top;
+	int shift = (ida->idr.layers - 1) * IDR_BITS;
+	int idr_id = id / IDA_BITMAP_BITS;
+	int offset = id % IDA_BITMAP_BITS;
+	int n;
+	struct ida_bitmap *bitmap;
+
+	/* clear full bits while looking up the leaf idr_layer */
+	while ((shift > 0) && p) {
+		n = (idr_id >> shift) & IDR_MASK;
+		__clear_bit(n, &p->bitmap);
+		p = p->ary[n];
+		shift -= IDR_BITS;
+	}
+
+	if (p == NULL)
+		goto err;
+
+	n = idr_id & IDR_MASK;
+	__clear_bit(n, &p->bitmap);
+
+	bitmap = (void *)p->ary[n];
+	if (!test_bit(offset, bitmap->bitmap))
+		goto err;
+
+	/* update bitmap and remove it if empty */
+	__clear_bit(offset, bitmap->bitmap);
+	if (--bitmap->nr_busy == 0) {
+		__set_bit(n, &p->bitmap);	/* to please idr_remove() */
+		idr_remove(&ida->idr, idr_id);
+		free_bitmap(ida, bitmap);
+	}
+
+	return;
+
+ err:
+	printk(KERN_WARNING
+	       "ida_remove called for id=%d which is not allocated.\n", id);
+}
+EXPORT_SYMBOL(ida_remove);
+
+/**
+ * ida_destroy - release all cached layers within an ida tree
+ * ida:		ida handle
+ */
+void ida_destroy(struct ida *ida)
+{
+	idr_destroy(&ida->idr);
+	kfree(ida->free_bitmap);
+}
+EXPORT_SYMBOL(ida_destroy);
+
+/**
+ * ida_init - initialize ida handle
+ * @ida:	ida handle
+ *
+ * This function is use to set up the handle (@ida) that you will pass
+ * to the rest of the functions.
+ */
+void ida_init(struct ida *ida)
+{
+	memset(ida, 0, sizeof(struct ida));
+	idr_init(&ida->idr);
+
+}
+EXPORT_SYMBOL(ida_init);
diff --git a/lib/ioremap.c b/lib/ioremap.c
index a9e4415..7605214 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -7,7 +7,7 @@
  */
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
-
+#include <linux/sched.h>
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 
diff --git a/lib/kobject.c b/lib/kobject.c
index fc5f3f6..4b08e0f 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -44,7 +44,7 @@
 	return error;
 }
 
-static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)
+static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
 {
 	int error = 0;
 	if (kobject_name(kobj)) {
@@ -162,7 +162,7 @@
  *	@shadow_parent: sysfs directory to add to.
  */
 
-int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
+int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
 {
 	int error = 0;
 	struct kobject * parent;
@@ -202,14 +202,14 @@
 
 		/* be noisy on error issues */
 		if (error == -EEXIST)
-			printk("kobject_add failed for %s with -EEXIST, "
-			       "don't try to register things with the "
-			       "same name in the same directory.\n",
+			printk(KERN_ERR "kobject_add failed for %s with "
+			       "-EEXIST, don't try to register things with "
+			       "the same name in the same directory.\n",
 			       kobject_name(kobj));
 		else
-			printk("kobject_add failed for %s (%d)\n",
+			printk(KERN_ERR "kobject_add failed for %s (%d)\n",
 			       kobject_name(kobj), error);
-		 dump_stack();
+		dump_stack();
 	}
 
 	return error;
@@ -338,7 +338,7 @@
 	/* Note : if we want to send the new name alone, not the full path,
 	 * we could probably use kobject_name(kobj); */
 
-	error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name);
+	error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name);
 
 	/* This function is mostly/only used for network interface.
 	 * Some hotplug package track interfaces by their name and
@@ -361,8 +361,8 @@
  *	@new_name: object's new name
  */
 
-int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent,
-			  const char *new_name)
+int kobject_shadow_rename(struct kobject *kobj,
+			  struct sysfs_dirent *new_parent, const char *new_name)
 {
 	int error = 0;
 
@@ -597,10 +597,17 @@
 
 int kset_register(struct kset * k)
 {
+	int err;
+
 	if (!k)
 		return -EINVAL;
+
 	kset_init(k);
-	return kset_add(k);
+	err = kset_add(k);
+	if (err)
+		return err;
+	kobject_uevent(&k->kobj, KOBJ_ADD);
+	return 0;
 }
 
 
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
new file mode 100644
index 0000000..e764116
--- /dev/null
+++ b/lib/lzo/Makefile
@@ -0,0 +1,5 @@
+lzo_compress-objs := lzo1x_compress.o
+lzo_decompress-objs := lzo1x_decompress.o
+
+obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
+obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
new file mode 100644
index 0000000..c935f00
--- /dev/null
+++ b/lib/lzo/lzo1x_compress.c
@@ -0,0 +1,226 @@
+/*
+ *  LZO1X Compressor from MiniLZO
+ *
+ *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lzo.h>
+#include <asm/unaligned.h>
+#include "lzodefs.h"
+
+static noinline size_t
+_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+		unsigned char *out, size_t *out_len, void *wrkmem)
+{
+	const unsigned char * const in_end = in + in_len;
+	const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
+	const unsigned char ** const dict = wrkmem;
+	const unsigned char *ip = in, *ii = ip;
+	const unsigned char *end, *m, *m_pos;
+	size_t m_off, m_len, dindex;
+	unsigned char *op = out;
+
+	ip += 4;
+
+	for (;;) {
+		dindex = ((0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
+		m_pos = dict[dindex];
+
+		if (m_pos < in)
+			goto literal;
+
+		if (ip == m_pos || (ip - m_pos) > M4_MAX_OFFSET)
+			goto literal;
+
+		m_off = ip - m_pos;
+		if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+			goto try_match;
+
+		dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
+		m_pos = dict[dindex];
+
+		if (m_pos < in)
+			goto literal;
+
+		if (ip == m_pos || (ip - m_pos) > M4_MAX_OFFSET)
+			goto literal;
+
+		m_off = ip - m_pos;
+		if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+			goto try_match;
+
+		goto literal;
+
+try_match:
+		if (get_unaligned((const unsigned short *)m_pos)
+				== get_unaligned((const unsigned short *)ip)) {
+			if (likely(m_pos[2] == ip[2]))
+					goto match;
+		}
+
+literal:
+		dict[dindex] = ip;
+		++ip;
+		if (unlikely(ip >= ip_end))
+			break;
+		continue;
+
+match:
+		dict[dindex] = ip;
+		if (ip != ii) {
+			size_t t = ip - ii;
+
+			if (t <= 3) {
+				op[-2] |= t;
+			} else if (t <= 18) {
+				*op++ = (t - 3);
+			} else {
+				size_t tt = t - 18;
+
+				*op++ = 0;
+				while (tt > 255) {
+					tt -= 255;
+					*op++ = 0;
+				}
+				*op++ = tt;
+			}
+			do {
+				*op++ = *ii++;
+			} while (--t > 0);
+		}
+
+		ip += 3;
+		if (m_pos[3] != *ip++ || m_pos[4] != *ip++
+				|| m_pos[5] != *ip++ || m_pos[6] != *ip++
+				|| m_pos[7] != *ip++ || m_pos[8] != *ip++) {
+			--ip;
+			m_len = ip - ii;
+
+			if (m_off <= M2_MAX_OFFSET) {
+				m_off -= 1;
+				*op++ = (((m_len - 1) << 5)
+						| ((m_off & 7) << 2));
+				*op++ = (m_off >> 3);
+			} else if (m_off <= M3_MAX_OFFSET) {
+				m_off -= 1;
+				*op++ = (M3_MARKER | (m_len - 2));
+				goto m3_m4_offset;
+			} else {
+				m_off -= 0x4000;
+
+				*op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
+						| (m_len - 2));
+				goto m3_m4_offset;
+			}
+		} else {
+			end = in_end;
+			m = m_pos + M2_MAX_LEN + 1;
+
+			while (ip < end && *m == *ip) {
+				m++;
+				ip++;
+			}
+			m_len = ip - ii;
+
+			if (m_off <= M3_MAX_OFFSET) {
+				m_off -= 1;
+				if (m_len <= 33) {
+					*op++ = (M3_MARKER | (m_len - 2));
+				} else {
+					m_len -= 33;
+					*op++ = M3_MARKER | 0;
+					goto m3_m4_len;
+				}
+			} else {
+				m_off -= 0x4000;
+				if (m_len <= M4_MAX_LEN) {
+					*op++ = (M4_MARKER
+						| ((m_off & 0x4000) >> 11)
+						| (m_len - 2));
+				} else {
+					m_len -= M4_MAX_LEN;
+					*op++ = (M4_MARKER
+						| ((m_off & 0x4000) >> 11));
+m3_m4_len:
+					while (m_len > 255) {
+						m_len -= 255;
+						*op++ = 0;
+					}
+
+					*op++ = (m_len);
+				}
+			}
+m3_m4_offset:
+			*op++ = ((m_off & 63) << 2);
+			*op++ = (m_off >> 6);
+		}
+
+		ii = ip;
+		if (unlikely(ip >= ip_end))
+			break;
+	}
+
+	*out_len = op - out;
+	return in_end - ii;
+}
+
+int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
+			size_t *out_len, void *wrkmem)
+{
+	const unsigned char *ii;
+	unsigned char *op = out;
+	size_t t;
+
+	if (unlikely(in_len <= M2_MAX_LEN + 5)) {
+		t = in_len;
+	} else {
+		t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
+		op += *out_len;
+	}
+
+	if (t > 0) {
+		ii = in + in_len - t;
+
+		if (op == out && t <= 238) {
+			*op++ = (17 + t);
+		} else if (t <= 3) {
+			op[-2] |= t;
+		} else if (t <= 18) {
+			*op++ = (t - 3);
+		} else {
+			size_t tt = t - 18;
+
+			*op++ = 0;
+			while (tt > 255) {
+				tt -= 255;
+				*op++ = 0;
+			}
+
+			*op++ = tt;
+		}
+		do {
+			*op++ = *ii++;
+		} while (--t > 0);
+	}
+
+	*op++ = M4_MARKER | 1;
+	*op++ = 0;
+	*op++ = 0;
+
+	*out_len = op - out;
+	return LZO_E_OK;
+}
+EXPORT_SYMBOL_GPL(lzo1x_1_compress);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X-1 Compressor");
+
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
new file mode 100644
index 0000000..9dc7056
--- /dev/null
+++ b/lib/lzo/lzo1x_decompress.c
@@ -0,0 +1,254 @@
+/*
+ *  LZO1X Decompressor from MiniLZO
+ *
+ *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lzo.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include "lzodefs.h"
+
+#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
+#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
+#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
+
+#define COPY4(dst, src)	\
+		put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
+			unsigned char *out, size_t *out_len)
+{
+	const unsigned char * const ip_end = in + in_len;
+	unsigned char * const op_end = out + *out_len;
+	const unsigned char *ip = in, *m_pos;
+	unsigned char *op = out;
+	size_t t;
+
+	*out_len = 0;
+
+	if (*ip > 17) {
+		t = *ip++ - 17;
+		if (t < 4)
+			goto match_next;
+		if (HAVE_OP(t, op_end, op))
+			goto output_overrun;
+		if (HAVE_IP(t + 1, ip_end, ip))
+			goto input_overrun;
+		do {
+			*op++ = *ip++;
+		} while (--t > 0);
+		goto first_literal_run;
+	}
+
+	while ((ip < ip_end)) {
+		t = *ip++;
+		if (t >= 16)
+			goto match;
+		if (t == 0) {
+			if (HAVE_IP(1, ip_end, ip))
+				goto input_overrun;
+			while (*ip == 0) {
+				t += 255;
+				ip++;
+				if (HAVE_IP(1, ip_end, ip))
+					goto input_overrun;
+			}
+			t += 15 + *ip++;
+		}
+		if (HAVE_OP(t + 3, op_end, op))
+			goto output_overrun;
+		if (HAVE_IP(t + 4, ip_end, ip))
+			goto input_overrun;
+
+		COPY4(op, ip);
+		op += 4;
+		ip += 4;
+		if (--t > 0) {
+			if (t >= 4) {
+				do {
+					COPY4(op, ip);
+					op += 4;
+					ip += 4;
+					t -= 4;
+				} while (t >= 4);
+				if (t > 0) {
+					do {
+						*op++ = *ip++;
+					} while (--t > 0);
+				}
+			} else {
+				do {
+					*op++ = *ip++;
+				} while (--t > 0);
+			}
+		}
+
+first_literal_run:
+		t = *ip++;
+		if (t >= 16)
+			goto match;
+		m_pos = op - (1 + M2_MAX_OFFSET);
+		m_pos -= t >> 2;
+		m_pos -= *ip++ << 2;
+
+		if (HAVE_LB(m_pos, out, op))
+			goto lookbehind_overrun;
+
+		if (HAVE_OP(3, op_end, op))
+			goto output_overrun;
+		*op++ = *m_pos++;
+		*op++ = *m_pos++;
+		*op++ = *m_pos;
+
+		goto match_done;
+
+		do {
+match:
+			if (t >= 64) {
+				m_pos = op - 1;
+				m_pos -= (t >> 2) & 7;
+				m_pos -= *ip++ << 3;
+				t = (t >> 5) - 1;
+				if (HAVE_LB(m_pos, out, op))
+					goto lookbehind_overrun;
+				if (HAVE_OP(t + 3 - 1, op_end, op))
+					goto output_overrun;
+				goto copy_match;
+			} else if (t >= 32) {
+				t &= 31;
+				if (t == 0) {
+					if (HAVE_IP(1, ip_end, ip))
+						goto input_overrun;
+					while (*ip == 0) {
+						t += 255;
+						ip++;
+						if (HAVE_IP(1, ip_end, ip))
+							goto input_overrun;
+					}
+					t += 31 + *ip++;
+				}
+				m_pos = op - 1;
+				m_pos -= le16_to_cpu(get_unaligned(
+					(const unsigned short *)ip)) >> 2;
+				ip += 2;
+			} else if (t >= 16) {
+				m_pos = op;
+				m_pos -= (t & 8) << 11;
+
+				t &= 7;
+				if (t == 0) {
+					if (HAVE_IP(1, ip_end, ip))
+						goto input_overrun;
+					while (*ip == 0) {
+						t += 255;
+						ip++;
+						if (HAVE_IP(1, ip_end, ip))
+							goto input_overrun;
+					}
+					t += 7 + *ip++;
+				}
+				m_pos -= le16_to_cpu(get_unaligned(
+					(const unsigned short *)ip) >> 2);
+				ip += 2;
+				if (m_pos == op)
+					goto eof_found;
+				m_pos -= 0x4000;
+			} else {
+				m_pos = op - 1;
+				m_pos -= t >> 2;
+				m_pos -= *ip++ << 2;
+
+				if (HAVE_LB(m_pos, out, op))
+					goto lookbehind_overrun;
+				if (HAVE_OP(2, op_end, op))
+					goto output_overrun;
+
+				*op++ = *m_pos++;
+				*op++ = *m_pos;
+				goto match_done;
+			}
+
+			if (HAVE_LB(m_pos, out, op))
+				goto lookbehind_overrun;
+			if (HAVE_OP(t + 3 - 1, op_end, op))
+				goto output_overrun;
+
+			if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
+				COPY4(op, m_pos);
+				op += 4;
+				m_pos += 4;
+				t -= 4 - (3 - 1);
+				do {
+					COPY4(op, m_pos);
+					op += 4;
+					m_pos += 4;
+					t -= 4;
+				} while (t >= 4);
+				if (t > 0)
+					do {
+						*op++ = *m_pos++;
+					} while (--t > 0);
+			} else {
+copy_match:
+				*op++ = *m_pos++;
+				*op++ = *m_pos++;
+				do {
+					*op++ = *m_pos++;
+				} while (--t > 0);
+			}
+match_done:
+			t = ip[-2] & 3;
+			if (t == 0)
+				break;
+match_next:
+			if (HAVE_OP(t, op_end, op))
+				goto output_overrun;
+			if (HAVE_IP(t + 1, ip_end, ip))
+				goto input_overrun;
+
+			*op++ = *ip++;
+			if (t > 1) {
+				*op++ = *ip++;
+				if (t > 2)
+					*op++ = *ip++;
+			}
+
+			t = *ip++;
+		} while (ip < ip_end);
+	}
+
+	*out_len = op - out;
+	return LZO_E_EOF_NOT_FOUND;
+
+eof_found:
+	*out_len = op - out;
+	return (ip == ip_end ? LZO_E_OK :
+		(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+input_overrun:
+	*out_len = op - out;
+	return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+	*out_len = op - out;
+	return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+	*out_len = op - out;
+	return LZO_E_LOOKBEHIND_OVERRUN;
+}
+
+EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X Decompressor");
+
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
new file mode 100644
index 0000000..b6d482c
--- /dev/null
+++ b/lib/lzo/lzodefs.h
@@ -0,0 +1,43 @@
+/*
+ *  lzodefs.h -- architecture, OS and compiler specific defines
+ *
+ *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#define LZO_VERSION		0x2020
+#define LZO_VERSION_STRING	"2.02"
+#define LZO_VERSION_DATE	"Oct 17 2005"
+
+#define M1_MAX_OFFSET	0x0400
+#define M2_MAX_OFFSET	0x0800
+#define M3_MAX_OFFSET	0x4000
+#define M4_MAX_OFFSET	0xbfff
+
+#define M1_MIN_LEN	2
+#define M1_MAX_LEN	2
+#define M2_MIN_LEN	3
+#define M2_MAX_LEN	8
+#define M3_MIN_LEN	3
+#define M3_MAX_LEN	33
+#define M4_MIN_LEN	3
+#define M4_MAX_LEN	9
+
+#define M1_MARKER	0
+#define M2_MARKER	64
+#define M3_MARKER	32
+#define M4_MARKER	16
+
+#define D_BITS		14
+#define D_MASK		((1u << D_BITS) - 1)
+#define D_HIGH		((D_MASK >> 1) + 1)
+
+#define DX2(p, s1, s2)	(((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
+							<< (s1)) ^ (p)[0])
+#define DX3(p, s1, s2, s3)	((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index 8504490..cf22c61 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -3,8 +3,17 @@
  */
 
 #include <linux/percpu_counter.h>
+#include <linux/notifier.h>
+#include <linux/mutex.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
 #include <linux/module.h>
 
+#ifdef CONFIG_HOTPLUG_CPU
+static LIST_HEAD(percpu_counters);
+static DEFINE_MUTEX(percpu_counters_lock);
+#endif
+
 void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
 {
 	long count;
@@ -36,7 +45,7 @@
 
 	spin_lock(&fbc->lock);
 	ret = fbc->count;
-	for_each_possible_cpu(cpu) {
+	for_each_online_cpu(cpu) {
 		s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
 		ret += *pcount;
 	}
@@ -44,3 +53,60 @@
 	return ret < 0 ? 0 : ret;
 }
 EXPORT_SYMBOL(percpu_counter_sum);
+
+void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
+{
+	spin_lock_init(&fbc->lock);
+	fbc->count = amount;
+	fbc->counters = alloc_percpu(s32);
+#ifdef CONFIG_HOTPLUG_CPU
+	mutex_lock(&percpu_counters_lock);
+	list_add(&fbc->list, &percpu_counters);
+	mutex_unlock(&percpu_counters_lock);
+#endif
+}
+EXPORT_SYMBOL(percpu_counter_init);
+
+void percpu_counter_destroy(struct percpu_counter *fbc)
+{
+	free_percpu(fbc->counters);
+#ifdef CONFIG_HOTPLUG_CPU
+	mutex_lock(&percpu_counters_lock);
+	list_del(&fbc->list);
+	mutex_unlock(&percpu_counters_lock);
+#endif
+}
+EXPORT_SYMBOL(percpu_counter_destroy);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb,
+					unsigned long action, void *hcpu)
+{
+	unsigned int cpu;
+	struct percpu_counter *fbc;
+
+	if (action != CPU_DEAD)
+		return NOTIFY_OK;
+
+	cpu = (unsigned long)hcpu;
+	mutex_lock(&percpu_counters_lock);
+	list_for_each_entry(fbc, &percpu_counters, list) {
+		s32 *pcount;
+
+		spin_lock(&fbc->lock);
+		pcount = per_cpu_ptr(fbc->counters, cpu);
+		fbc->count += *pcount;
+		*pcount = 0;
+		spin_unlock(&fbc->lock);
+	}
+	mutex_unlock(&percpu_counters_lock);
+	return NOTIFY_OK;
+}
+
+static int __init percpu_counter_startup(void)
+{
+	hotcpu_notifier(percpu_counter_hotcpu_callback, 0);
+	return 0;
+}
+module_init(percpu_counter_startup);
+#endif
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 402eb4e..9927cca 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -151,6 +151,7 @@
 out:
 	return ret;
 }
+EXPORT_SYMBOL(radix_tree_preload);
 
 static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
 		int offset)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 0172902..6b6734d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -135,6 +135,103 @@
 	return i;
 }
 
+/* Decimal conversion is by far the most typical, and is used
+ * for /proc and /sys data. This directly impacts e.g. top performance
+ * with many processes running. We optimize it for speed
+ * using code from
+ * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
+ * (with permission from the author, Douglas W. Jones). */
+
+/* Formats correctly any integer in [0,99999].
+ * Outputs from one to five digits depending on input.
+ * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
+static char* put_dec_trunc(char *buf, unsigned q)
+{
+	unsigned d3, d2, d1, d0;
+	d1 = (q>>4) & 0xf;
+	d2 = (q>>8) & 0xf;
+	d3 = (q>>12);
+
+	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+	q = (d0 * 0xcd) >> 11;
+	d0 = d0 - 10*q;
+	*buf++ = d0 + '0'; /* least significant digit */
+	d1 = q + 9*d3 + 5*d2 + d1;
+	if (d1 != 0) {
+		q = (d1 * 0xcd) >> 11;
+		d1 = d1 - 10*q;
+		*buf++ = d1 + '0'; /* next digit */
+
+		d2 = q + 2*d2;
+		if ((d2 != 0) || (d3 != 0)) {
+			q = (d2 * 0xd) >> 7;
+			d2 = d2 - 10*q;
+			*buf++ = d2 + '0'; /* next digit */
+
+			d3 = q + 4*d3;
+			if (d3 != 0) {
+				q = (d3 * 0xcd) >> 11;
+				d3 = d3 - 10*q;
+				*buf++ = d3 + '0';  /* next digit */
+				if (q != 0)
+					*buf++ = q + '0';  /* most sign. digit */
+			}
+		}
+	}
+	return buf;
+}
+/* Same with if's removed. Always emits five digits */
+static char* put_dec_full(char *buf, unsigned q)
+{
+	/* BTW, if q is in [0,9999], 8-bit ints will be enough, */
+	/* but anyway, gcc produces better code with full-sized ints */
+	unsigned d3, d2, d1, d0;
+	d1 = (q>>4) & 0xf;
+	d2 = (q>>8) & 0xf;
+	d3 = (q>>12);
+
+	/* Possible ways to approx. divide by 10 */
+	/* gcc -O2 replaces multiply with shifts and adds */
+	// (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
+	// (x * 0x67) >> 10:  1100111
+	// (x * 0x34) >> 9:    110100 - same
+	// (x * 0x1a) >> 8:     11010 - same
+	// (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
+
+	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+	q = (d0 * 0xcd) >> 11;
+	d0 = d0 - 10*q;
+	*buf++ = d0 + '0';
+	d1 = q + 9*d3 + 5*d2 + d1;
+		q = (d1 * 0xcd) >> 11;
+		d1 = d1 - 10*q;
+		*buf++ = d1 + '0';
+
+		d2 = q + 2*d2;
+			q = (d2 * 0xd) >> 7;
+			d2 = d2 - 10*q;
+			*buf++ = d2 + '0';
+
+			d3 = q + 4*d3;
+				q = (d3 * 0xcd) >> 11; /* - shorter code */
+				/* q = (d3 * 0x67) >> 10; - would also work */
+				d3 = d3 - 10*q;
+				*buf++ = d3 + '0';
+					*buf++ = q + '0';
+	return buf;
+}
+/* No inlining helps gcc to use registers better */
+static noinline char* put_dec(char *buf, unsigned long long num)
+{
+	while (1) {
+		unsigned rem;
+		if (num < 100000)
+			return put_dec_trunc(buf, num);
+		rem = do_div(num, 100000);
+		buf = put_dec_full(buf, rem);
+	}
+}
+
 #define ZEROPAD	1		/* pad with zero */
 #define SIGN	2		/* unsigned/signed long */
 #define PLUS	4		/* show plus */
@@ -143,12 +240,14 @@
 #define SPECIAL	32		/* 0x */
 #define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
 
-static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
+static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
 {
-	char c,sign,tmp[66];
+	char sign,tmp[66];
 	const char *digits;
-	static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-	static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	/* we are called with base 8, 10 or 16, only, thus don't need "g..."  */
+	static const char small_digits[] = "0123456789abcdefx"; /* "ghijklmnopqrstuvwxyz"; */
+	static const char large_digits[] = "0123456789ABCDEFX"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+	int need_pfx = ((type & SPECIAL) && base != 10);
 	int i;
 
 	digits = (type & LARGE) ? large_digits : small_digits;
@@ -156,7 +255,6 @@
 		type &= ~ZEROPAD;
 	if (base < 2 || base > 36)
 		return NULL;
-	c = (type & ZEROPAD) ? '0' : ' ';
 	sign = 0;
 	if (type & SIGN) {
 		if ((signed long long) num < 0) {
@@ -171,64 +269,85 @@
 			size--;
 		}
 	}
-	if (type & SPECIAL) {
+	if (need_pfx) {
+		size--;
 		if (base == 16)
-			size -= 2;
-		else if (base == 8)
 			size--;
 	}
+
+	/* generate full string in tmp[], in reverse order */
 	i = 0;
 	if (num == 0)
-		tmp[i++]='0';
-	else while (num != 0)
+		tmp[i++] = '0';
+	/* Generic code, for any base:
+	else do {
 		tmp[i++] = digits[do_div(num,base)];
+	} while (num != 0);
+	*/
+	else if (base != 10) { /* 8 or 16 */
+		int mask = base - 1;
+		int shift = 3;
+		if (base == 16) shift = 4;
+		do {
+			tmp[i++] = digits[((unsigned char)num) & mask];
+			num >>= shift;
+		} while (num);
+	} else { /* base 10 */
+		i = put_dec(tmp, num) - tmp;
+	}
+
+	/* printing 100 using %2d gives "100", not "00" */
 	if (i > precision)
 		precision = i;
+	/* leading space padding */
 	size -= precision;
-	if (!(type&(ZEROPAD+LEFT))) {
-		while(size-->0) {
+	if (!(type & (ZEROPAD+LEFT))) {
+		while(--size >= 0) {
 			if (buf < end)
 				*buf = ' ';
 			++buf;
 		}
 	}
+	/* sign */
 	if (sign) {
 		if (buf < end)
 			*buf = sign;
 		++buf;
 	}
-	if (type & SPECIAL) {
-		if (base==8) {
+	/* "0x" / "0" prefix */
+	if (need_pfx) {
+		if (buf < end)
+			*buf = '0';
+		++buf;
+		if (base == 16) {
 			if (buf < end)
-				*buf = '0';
-			++buf;
-		} else if (base==16) {
-			if (buf < end)
-				*buf = '0';
-			++buf;
-			if (buf < end)
-				*buf = digits[33];
+				*buf = digits[16]; /* for arbitrary base: digits[33]; */
 			++buf;
 		}
 	}
+	/* zero or space padding */
 	if (!(type & LEFT)) {
-		while (size-- > 0) {
+		char c = (type & ZEROPAD) ? '0' : ' ';
+		while (--size >= 0) {
 			if (buf < end)
 				*buf = c;
 			++buf;
 		}
 	}
-	while (i < precision--) {
+	/* hmm even more zero padding? */
+	while (i <= --precision) {
 		if (buf < end)
 			*buf = '0';
 		++buf;
 	}
-	while (i-- > 0) {
+	/* actual digits of result */
+	while (--i >= 0) {
 		if (buf < end)
 			*buf = tmp[i];
 		++buf;
 	}
-	while (size-- > 0) {
+	/* trailing space padding */
+	while (--size >= 0) {
 		if (buf < end)
 			*buf = ' ';
 		++buf;
@@ -276,7 +395,7 @@
 	   used for unknown buffer sizes. */
 	if (unlikely((int) size < 0)) {
 		/* There can be only one.. */
-		static int warn = 1;
+		static char warn = 1;
 		WARN_ON(warn);
 		warn = 0;
 		return 0;
diff --git a/mm/Kconfig b/mm/Kconfig
index 8ac412b..8618722 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -117,7 +117,7 @@
 	bool "Allow for memory hot-add"
 	depends on SPARSEMEM || X86_64_ACPI_NUMA
 	depends on HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG
-	depends on (IA64 || X86 || PPC64)
+	depends on (IA64 || X86 || PPC64 || SUPERH)
 
 comment "Memory hotplug is currently incompatible with Software Suspend"
 	depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND
@@ -163,8 +163,16 @@
 	default "0" if !ZONE_DMA
 	default "1"
 
+config BOUNCE
+	def_bool y
+	depends on BLOCK && MMU && (ZONE_DMA || HIGHMEM)
+
 config NR_QUICK
 	int
 	depends on QUICKLIST
 	default "2" if (SUPERH && !SUPERH64)
 	default "1"
+
+config VIRT_TO_BUS
+	def_bool y
+	depends on !ARCH_NO_VIRT_TO_BUS
diff --git a/mm/Makefile b/mm/Makefile
index a9148ea..245e33a 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -13,9 +13,7 @@
 			   prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
 			   $(mmu-y)
 
-ifeq ($(CONFIG_MMU)$(CONFIG_BLOCK),yy)
-obj-y			+= bounce.o
-endif
+obj-$(CONFIG_BOUNCE)	+= bounce.o
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c
index b2486cf..00b0262 100644
--- a/mm/allocpercpu.c
+++ b/mm/allocpercpu.c
@@ -53,12 +53,9 @@
 	int node = cpu_to_node(cpu);
 
 	BUG_ON(pdata->ptrs[cpu]);
-	if (node_online(node)) {
-		/* FIXME: kzalloc_node(size, gfp, node) */
-		pdata->ptrs[cpu] = kmalloc_node(size, gfp, node);
-		if (pdata->ptrs[cpu])
-			memset(pdata->ptrs[cpu], 0, size);
-	} else
+	if (node_online(node))
+		pdata->ptrs[cpu] = kmalloc_node(size, gfp|__GFP_ZERO, node);
+	else
 		pdata->ptrs[cpu] = kzalloc(size, gfp);
 	return pdata->ptrs[cpu];
 }
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index e5de378..f50a281 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -55,22 +55,6 @@
 }
 EXPORT_SYMBOL(congestion_wait);
 
-long congestion_wait_interruptible(int rw, long timeout)
-{
-	long ret;
-	DEFINE_WAIT(wait);
-	wait_queue_head_t *wqh = &congestion_wqh[rw];
-
-	prepare_to_wait(wqh, &wait, TASK_INTERRUPTIBLE);
-	if (signal_pending(current))
-		ret = -ERESTARTSYS;
-	else
-		ret = io_schedule_timeout(timeout);
-	finish_wait(wqh, &wait);
-	return ret;
-}
-EXPORT_SYMBOL(congestion_wait_interruptible);
-
 /**
  * congestion_end - wake up sleepers on a congested backing_dev_info
  * @rw: READ or WRITE
diff --git a/mm/filemap.c b/mm/filemap.c
index edb1b0b..5d5449f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -120,6 +120,7 @@
 	page->mapping = NULL;
 	mapping->nrpages--;
 	__dec_zone_page_state(page, NR_FILE_PAGES);
+	BUG_ON(page_mapped(page));
 }
 
 void remove_from_page_cache(struct page *page)
@@ -866,13 +867,11 @@
 {
 	struct inode *inode = mapping->host;
 	unsigned long index;
-	unsigned long end_index;
 	unsigned long offset;
 	unsigned long last_index;
 	unsigned long next_index;
 	unsigned long prev_index;
 	unsigned int prev_offset;
-	loff_t isize;
 	struct page *cached_page;
 	int error;
 	struct file_ra_state ra = *_ra;
@@ -885,27 +884,12 @@
 	last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
-	isize = i_size_read(inode);
-	if (!isize)
-		goto out;
-
-	end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
 	for (;;) {
 		struct page *page;
+		unsigned long end_index;
+		loff_t isize;
 		unsigned long nr, ret;
 
-		/* nr is the maximum number of bytes to copy from this page */
-		nr = PAGE_CACHE_SIZE;
-		if (index >= end_index) {
-			if (index > end_index)
-				goto out;
-			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
-			if (nr <= offset) {
-				goto out;
-			}
-		}
-		nr = nr - offset;
-
 		cond_resched();
 		if (index == next_index)
 			next_index = page_cache_readahead(mapping, &ra, filp,
@@ -920,6 +904,32 @@
 		if (!PageUptodate(page))
 			goto page_not_up_to_date;
 page_ok:
+		/*
+		 * i_size must be checked after we know the page is Uptodate.
+		 *
+		 * Checking i_size after the check allows us to calculate
+		 * the correct value for "nr", which means the zero-filled
+		 * part of the page is not copied back to userspace (unless
+		 * another truncate extends the file - this is desired though).
+		 */
+
+		isize = i_size_read(inode);
+		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+		if (unlikely(!isize || index > end_index)) {
+			page_cache_release(page);
+			goto out;
+		}
+
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index == end_index) {
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				page_cache_release(page);
+				goto out;
+			}
+		}
+		nr = nr - offset;
 
 		/* If users can be writing to this page using arbitrary
 		 * virtual addresses, take care about potential aliasing
@@ -1006,31 +1016,6 @@
 			unlock_page(page);
 		}
 
-		/*
-		 * i_size must be checked after we have done ->readpage.
-		 *
-		 * Checking i_size after the readpage allows us to calculate
-		 * the correct value for "nr", which means the zero-filled
-		 * part of the page is not copied back to userspace (unless
-		 * another truncate extends the file - this is desired though).
-		 */
-		isize = i_size_read(inode);
-		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
-		if (unlikely(!isize || index > end_index)) {
-			page_cache_release(page);
-			goto out;
-		}
-
-		/* nr is the maximum number of bytes to copy from this page */
-		nr = PAGE_CACHE_SIZE;
-		if (index == end_index) {
-			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
-			if (nr <= offset) {
-				page_cache_release(page);
-				goto out;
-			}
-		}
-		nr = nr - offset;
 		goto page_ok;
 
 readpage_error:
@@ -1218,6 +1203,8 @@
 				retval = retval ?: desc.error;
 				break;
 			}
+			if (desc.count > 0)
+				break;
 		}
 	}
 out:
@@ -1245,26 +1232,6 @@
 	return written;
 }
 
-ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos,
-			 size_t count, read_actor_t actor, void *target)
-{
-	read_descriptor_t desc;
-
-	if (!count)
-		return 0;
-
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-
-	do_generic_file_read(in_file, ppos, &desc, actor);
-	if (desc.written)
-		return desc.written;
-	return desc.error;
-}
-EXPORT_SYMBOL(generic_file_sendfile);
-
 static ssize_t
 do_readahead(struct address_space *mapping, struct file *filp,
 	     unsigned long index, unsigned long nr)
@@ -1786,7 +1753,6 @@
 	page = __read_cache_page(mapping, index, filler, data);
 	if (IS_ERR(page))
 		return page;
-	mark_page_accessed(page);
 	if (PageUptodate(page))
 		goto out;
 
@@ -1985,7 +1951,6 @@
 	if (unlikely(*pos + *count > MAX_NON_LFS &&
 				!(file->f_flags & O_LARGEFILE))) {
 		if (*pos >= MAX_NON_LFS) {
-			send_sig(SIGXFSZ, current, 0);
 			return -EFBIG;
 		}
 		if (*count > MAX_NON_LFS - (unsigned long)*pos) {
@@ -2003,7 +1968,6 @@
 	if (likely(!isblk)) {
 		if (unlikely(*pos >= inode->i_sb->s_maxbytes)) {
 			if (*count || *pos > inode->i_sb->s_maxbytes) {
-				send_sig(SIGXFSZ, current, 0);
 				return -EFBIG;
 			}
 			/* zero-length writes at ->s_maxbytes are OK */
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 1b49dab..65ffc32 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/uio.h>
 #include <linux/rmap.h>
+#include <linux/sched.h>
 #include <asm/tlbflush.h>
 #include "filemap.h"
 
@@ -158,28 +159,6 @@
 }
 EXPORT_SYMBOL_GPL(xip_file_read);
 
-ssize_t
-xip_file_sendfile(struct file *in_file, loff_t *ppos,
-	     size_t count, read_actor_t actor, void *target)
-{
-	read_descriptor_t desc;
-
-	if (!count)
-		return 0;
-
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-
-	do_xip_mapping_read(in_file->f_mapping, &in_file->f_ra, in_file,
-			    ppos, &desc, actor);
-	if (desc.written)
-		return desc.written;
-	return desc.error;
-}
-EXPORT_SYMBOL_GPL(xip_file_sendfile);
-
 /*
  * __xip_unmap is invoked from xip_unmap and
  * xip_write
diff --git a/mm/highmem.c b/mm/highmem.c
index be8f8d3..7a967bc 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -46,9 +46,14 @@
 	pg_data_t *pgdat;
 	unsigned int pages = 0;
 
-	for_each_online_pgdat(pgdat)
+	for_each_online_pgdat(pgdat) {
 		pages += zone_page_state(&pgdat->node_zones[ZONE_HIGHMEM],
 			NR_FREE_PAGES);
+		if (zone_movable_is_highmem())
+			pages += zone_page_state(
+					&pgdat->node_zones[ZONE_MOVABLE],
+					NR_FREE_PAGES);
+	}
 
 	return pages;
 }
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index eb7180d..6912bbf 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -27,6 +27,9 @@
 static struct list_head hugepage_freelists[MAX_NUMNODES];
 static unsigned int nr_huge_pages_node[MAX_NUMNODES];
 static unsigned int free_huge_pages_node[MAX_NUMNODES];
+static gfp_t htlb_alloc_mask = GFP_HIGHUSER;
+unsigned long hugepages_treat_as_movable;
+
 /*
  * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
  */
@@ -66,14 +69,15 @@
 static struct page *dequeue_huge_page(struct vm_area_struct *vma,
 				unsigned long address)
 {
-	int nid = numa_node_id();
+	int nid;
 	struct page *page = NULL;
-	struct zonelist *zonelist = huge_zonelist(vma, address);
+	struct zonelist *zonelist = huge_zonelist(vma, address,
+						htlb_alloc_mask);
 	struct zone **z;
 
 	for (z = zonelist->zones; *z; z++) {
 		nid = zone_to_nid(*z);
-		if (cpuset_zone_allowed_softwall(*z, GFP_HIGHUSER) &&
+		if (cpuset_zone_allowed_softwall(*z, htlb_alloc_mask) &&
 		    !list_empty(&hugepage_freelists[nid]))
 			break;
 	}
@@ -101,13 +105,20 @@
 
 static int alloc_fresh_huge_page(void)
 {
-	static int nid = 0;
+	static int prev_nid;
 	struct page *page;
-	page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN,
-					HUGETLB_PAGE_ORDER);
-	nid = next_node(nid, node_online_map);
+	static DEFINE_SPINLOCK(nid_lock);
+	int nid;
+
+	spin_lock(&nid_lock);
+	nid = next_node(prev_nid, node_online_map);
 	if (nid == MAX_NUMNODES)
 		nid = first_node(node_online_map);
+	prev_nid = nid;
+	spin_unlock(&nid_lock);
+
+	page = alloc_pages_node(nid, htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
+					HUGETLB_PAGE_ORDER);
 	if (page) {
 		set_compound_page_dtor(page, free_huge_page);
 		spin_lock(&hugetlb_lock);
@@ -256,6 +267,19 @@
 	max_huge_pages = set_max_huge_pages(max_huge_pages);
 	return 0;
 }
+
+int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
+			struct file *file, void __user *buffer,
+			size_t *length, loff_t *ppos)
+{
+	proc_dointvec(table, write, file, buffer, length, ppos);
+	if (hugepages_treat_as_movable)
+		htlb_alloc_mask = GFP_HIGHUSER_MOVABLE;
+	else
+		htlb_alloc_mask = GFP_HIGHUSER;
+	return 0;
+}
+
 #endif /* CONFIG_SYSCTL */
 
 int hugetlb_report_meminfo(char *buf)
@@ -326,9 +350,10 @@
 	pte_t entry;
 
 	entry = pte_mkwrite(pte_mkdirty(*ptep));
-	ptep_set_access_flags(vma, address, ptep, entry, 1);
-	update_mmu_cache(vma, address, entry);
-	lazy_mmu_prot_update(entry);
+	if (ptep_set_access_flags(vma, address, ptep, entry, 1)) {
+		update_mmu_cache(vma, address, entry);
+		lazy_mmu_prot_update(entry);
+	}
 }
 
 
@@ -473,7 +498,7 @@
 	return VM_FAULT_MINOR;
 }
 
-int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
+static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
 			unsigned long address, pte_t *ptep, int write_access)
 {
 	int ret = VM_FAULT_SIGBUS;
diff --git a/mm/madvise.c b/mm/madvise.c
index e75096b..93ee375 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -10,6 +10,7 @@
 #include <linux/syscalls.h>
 #include <linux/mempolicy.h>
 #include <linux/hugetlb.h>
+#include <linux/sched.h>
 
 /*
  * Any behaviour which results in changes to the vma->vm_flags needs to
@@ -286,9 +287,11 @@
 	struct vm_area_struct * vma, *prev;
 	int unmapped_error = 0;
 	int error = -EINVAL;
+	int write;
 	size_t len;
 
-	if (madvise_need_mmap_write(behavior))
+	write = madvise_need_mmap_write(behavior);
+	if (write)
 		down_write(&current->mm->mmap_sem);
 	else
 		down_read(&current->mm->mmap_sem);
@@ -353,7 +356,7 @@
 			vma = find_vma(current->mm, start);
 	}
 out:
-	if (madvise_need_mmap_write(behavior))
+	if (write)
 		up_write(&current->mm->mmap_sem);
 	else
 		up_read(&current->mm->mmap_sem);
diff --git a/mm/memory.c b/mm/memory.c
index cb94488..9c6ff7f 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -78,11 +78,9 @@
  * and ZONE_HIGHMEM.
  */
 void * high_memory;
-unsigned long vmalloc_earlyreserve;
 
 EXPORT_SYMBOL(num_physpages);
 EXPORT_SYMBOL(high_memory);
-EXPORT_SYMBOL(vmalloc_earlyreserve);
 
 int randomize_va_space __read_mostly = 1;
 
@@ -1055,6 +1053,14 @@
 		do {
 			struct page *page;
 
+			/*
+			 * If tsk is ooming, cut off its access to large memory
+			 * allocations. It has a pending SIGKILL, but it can't
+			 * be processed until returning to user space.
+			 */
+			if (unlikely(test_tsk_thread_flag(tsk, TIF_MEMDIE)))
+				return -ENOMEM;
+
 			if (write)
 				foll_flags |= FOLL_WRITE;
 
@@ -1691,9 +1697,10 @@
 		flush_cache_page(vma, address, pte_pfn(orig_pte));
 		entry = pte_mkyoung(orig_pte);
 		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-		ptep_set_access_flags(vma, address, page_table, entry, 1);
-		update_mmu_cache(vma, address, entry);
-		lazy_mmu_prot_update(entry);
+		if (ptep_set_access_flags(vma, address, page_table, entry,1)) {
+			update_mmu_cache(vma, address, entry);
+			lazy_mmu_prot_update(entry);
+		}
 		ret |= VM_FAULT_WRITE;
 		goto unlock;
 	}
@@ -1708,11 +1715,11 @@
 	if (unlikely(anon_vma_prepare(vma)))
 		goto oom;
 	if (old_page == ZERO_PAGE(address)) {
-		new_page = alloc_zeroed_user_highpage(vma, address);
+		new_page = alloc_zeroed_user_highpage_movable(vma, address);
 		if (!new_page)
 			goto oom;
 	} else {
-		new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+		new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
 		if (!new_page)
 			goto oom;
 		cow_user_page(new_page, old_page, address, vma);
@@ -2230,7 +2237,7 @@
 
 		if (unlikely(anon_vma_prepare(vma)))
 			goto oom;
-		page = alloc_zeroed_user_highpage(vma, address);
+		page = alloc_zeroed_user_highpage_movable(vma, address);
 		if (!page)
 			goto oom;
 
@@ -2333,7 +2340,8 @@
 
 			if (unlikely(anon_vma_prepare(vma)))
 				goto oom;
-			page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+			page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+						vma, address);
 			if (!page)
 				goto oom;
 			copy_user_highpage(page, new_page, address, vma);
@@ -2525,10 +2533,9 @@
 		pte_t *pte, pmd_t *pmd, int write_access)
 {
 	pte_t entry;
-	pte_t old_entry;
 	spinlock_t *ptl;
 
-	old_entry = entry = *pte;
+	entry = *pte;
 	if (!pte_present(entry)) {
 		if (pte_none(entry)) {
 			if (vma->vm_ops) {
@@ -2561,8 +2568,7 @@
 		entry = pte_mkdirty(entry);
 	}
 	entry = pte_mkyoung(entry);
-	if (!pte_same(old_entry, entry)) {
-		ptep_set_access_flags(vma, address, pte, entry, write_access);
+	if (ptep_set_access_flags(vma, address, pte, entry, write_access)) {
 		update_mmu_cache(vma, address, entry);
 		lazy_mmu_prot_update(entry);
 	} else {
@@ -2674,7 +2680,7 @@
 	write = (vma->vm_flags & VM_WRITE) != 0;
 	BUG_ON(addr >= end);
 	BUG_ON(end > vma->vm_end);
-	len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE;
+	len = DIV_ROUND_UP(end, PAGE_SIZE) - addr/PAGE_SIZE;
 	ret = get_user_pages(current, current->mm, addr,
 			len, write, 0, NULL, NULL);
 	if (ret < 0)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 8427912..df9d554 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -65,7 +65,7 @@
 	int zone_type;
 
 	zone_type = zone - pgdat->node_zones;
-	if (!populated_zone(zone)) {
+	if (!zone->wait_table) {
 		int ret = 0;
 		ret = init_currently_empty_zone(zone, phys_start_pfn,
 						nr_pages, MEMMAP_HOTPLUG);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d76e8eb..9f4e9b9 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -101,8 +101,6 @@
 static struct kmem_cache *policy_cache;
 static struct kmem_cache *sn_cache;
 
-#define PDprintk(fmt...)
-
 /* Highest zone. An specific allocation for a zone below that is not
    policied. */
 enum zone_type policy_zone = 0;
@@ -175,7 +173,9 @@
 {
 	struct mempolicy *policy;
 
-	PDprintk("setting mode %d nodes[0] %lx\n", mode, nodes_addr(*nodes)[0]);
+	pr_debug("setting mode %d nodes[0] %lx\n",
+		 mode, nodes ? nodes_addr(*nodes)[0] : -1);
+
 	if (mode == MPOL_DEFAULT)
 		return NULL;
 	policy = kmem_cache_alloc(policy_cache, GFP_KERNEL);
@@ -379,7 +379,7 @@
 	int err = 0;
 	struct mempolicy *old = vma->vm_policy;
 
-	PDprintk("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
+	pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
 		 vma->vm_start, vma->vm_end, vma->vm_pgoff,
 		 vma->vm_ops, vma->vm_file,
 		 vma->vm_ops ? vma->vm_ops->set_policy : NULL);
@@ -594,7 +594,7 @@
 
 static struct page *new_node_page(struct page *page, unsigned long node, int **x)
 {
-	return alloc_pages_node(node, GFP_HIGHUSER, 0);
+	return alloc_pages_node(node, GFP_HIGHUSER_MOVABLE, 0);
 }
 
 /*
@@ -710,7 +710,8 @@
 {
 	struct vm_area_struct *vma = (struct vm_area_struct *)private;
 
-	return alloc_page_vma(GFP_HIGHUSER, vma, page_address_in_vma(page, vma));
+	return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
+					page_address_in_vma(page, vma));
 }
 #else
 
@@ -776,8 +777,8 @@
 	if (!new)
 		flags |= MPOL_MF_DISCONTIG_OK;
 
-	PDprintk("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
-			mode,nodes_addr(nodes)[0]);
+	pr_debug("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
+		 mode, nmask ? nodes_addr(*nmask)[0] : -1);
 
 	down_write(&mm->mmap_sem);
 	vma = check_range(mm, start, end, nmask,
@@ -1202,7 +1203,8 @@
 
 #ifdef CONFIG_HUGETLBFS
 /* Return a zonelist suitable for a huge page allocation. */
-struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
+struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
+							gfp_t gfp_flags)
 {
 	struct mempolicy *pol = get_vma_policy(current, vma, addr);
 
@@ -1210,7 +1212,7 @@
 		unsigned nid;
 
 		nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
-		return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+		return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags);
 	}
 	return zonelist_policy(GFP_HIGHUSER, pol);
 }
@@ -1434,7 +1436,7 @@
 	}
 	rb_link_node(&new->nd, parent, p);
 	rb_insert_color(&new->nd, &sp->root);
-	PDprintk("inserting %lx-%lx: %d\n", new->start, new->end,
+	pr_debug("inserting %lx-%lx: %d\n", new->start, new->end,
 		 new->policy ? new->policy->policy : 0);
 }
 
@@ -1459,7 +1461,7 @@
 
 static void sp_delete(struct shared_policy *sp, struct sp_node *n)
 {
-	PDprintk("deleting %lx-l%x\n", n->start, n->end);
+	pr_debug("deleting %lx-l%lx\n", n->start, n->end);
 	rb_erase(&n->nd, &sp->root);
 	mpol_free(n->policy);
 	kmem_cache_free(sn_cache, n);
@@ -1558,10 +1560,10 @@
 	struct sp_node *new = NULL;
 	unsigned long sz = vma_pages(vma);
 
-	PDprintk("set_shared_policy %lx sz %lu %d %lx\n",
+	pr_debug("set_shared_policy %lx sz %lu %d %lx\n",
 		 vma->vm_pgoff,
 		 sz, npol? npol->policy : -1,
-		npol ? nodes_addr(npol->v.nodes)[0] : -1);
+		 npol ? nodes_addr(npol->v.nodes)[0] : -1);
 
 	if (npol) {
 		new = sp_alloc(vma->vm_pgoff, vma->vm_pgoff + sz, npol);
@@ -1597,6 +1599,10 @@
 /* assumes fs == KERNEL_DS */
 void __init numa_policy_init(void)
 {
+	nodemask_t interleave_nodes;
+	unsigned long largest = 0;
+	int nid, prefer = 0;
+
 	policy_cache = kmem_cache_create("numa_policy",
 					 sizeof(struct mempolicy),
 					 0, SLAB_PANIC, NULL, NULL);
@@ -1605,10 +1611,31 @@
 				     sizeof(struct sp_node),
 				     0, SLAB_PANIC, NULL, NULL);
 
-	/* Set interleaving policy for system init. This way not all
-	   the data structures allocated at system boot end up in node zero. */
+	/*
+	 * Set interleaving policy for system init. Interleaving is only
+	 * enabled across suitably sized nodes (default is >= 16MB), or
+	 * fall back to the largest node if they're all smaller.
+	 */
+	nodes_clear(interleave_nodes);
+	for_each_online_node(nid) {
+		unsigned long total_pages = node_present_pages(nid);
 
-	if (do_set_mempolicy(MPOL_INTERLEAVE, &node_online_map))
+		/* Preserve the largest node */
+		if (largest < total_pages) {
+			largest = total_pages;
+			prefer = nid;
+		}
+
+		/* Interleave this node? */
+		if ((total_pages << PAGE_SHIFT) >= (16 << 20))
+			node_set(nid, interleave_nodes);
+	}
+
+	/* All too small, use the largest */
+	if (unlikely(nodes_empty(interleave_nodes)))
+		node_set(prefer, interleave_nodes);
+
+	if (do_set_mempolicy(MPOL_INTERLEAVE, &interleave_nodes))
 		printk("numa_policy_init: interleaving failed\n");
 }
 
diff --git a/mm/mempool.c b/mm/mempool.c
index cc1ca86..02d5ec3 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -62,10 +62,9 @@
 			mempool_free_t *free_fn, void *pool_data, int node_id)
 {
 	mempool_t *pool;
-	pool = kmalloc_node(sizeof(*pool), GFP_KERNEL, node_id);
+	pool = kmalloc_node(sizeof(*pool), GFP_KERNEL | __GFP_ZERO, node_id);
 	if (!pool)
 		return NULL;
-	memset(pool, 0, sizeof(*pool));
 	pool->elements = kmalloc_node(min_nr * sizeof(void *),
 					GFP_KERNEL, node_id);
 	if (!pool->elements) {
@@ -263,6 +262,9 @@
 {
 	unsigned long flags;
 
+	if (unlikely(element == NULL))
+		return;
+
 	smp_mb();
 	if (pool->curr_nr < pool->min_nr) {
 		spin_lock_irqsave(&pool->lock, flags);
diff --git a/mm/migrate.c b/mm/migrate.c
index a91ca00..34d8ada 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -761,7 +761,8 @@
 
 	*result = &pm->status;
 
-	return alloc_pages_node(pm->node, GFP_HIGHUSER | GFP_THISNODE, 0);
+	return alloc_pages_node(pm->node,
+				GFP_HIGHUSER_MOVABLE | GFP_THISNODE, 0);
 }
 
 /*
diff --git a/mm/mlock.c b/mm/mlock.c
index 3446b7e..7b26560 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -10,7 +10,18 @@
 #include <linux/mm.h>
 #include <linux/mempolicy.h>
 #include <linux/syscalls.h>
+#include <linux/sched.h>
+#include <linux/module.h>
 
+int can_do_mlock(void)
+{
+	if (capable(CAP_IPC_LOCK))
+		return 1;
+	if (current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur != 0)
+		return 1;
+	return 0;
+}
+EXPORT_SYMBOL(can_do_mlock);
 
 static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
 	unsigned long start, unsigned long end, unsigned int newflags)
@@ -233,9 +244,12 @@
 
 	locked = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+	if (lock_limit == RLIM_INFINITY)
+		allowed = 1;
 	lock_limit >>= PAGE_SHIFT;
 	spin_lock(&shmlock_user_lock);
-	if (locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
+	if (!allowed &&
+	    locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
 		goto out;
 	get_uid(user);
 	user->locked_shm += locked;
diff --git a/mm/mmap.c b/mm/mmap.c
index 68b9ad2..144b4a2 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -894,14 +894,11 @@
 			unsigned long flags, unsigned long pgoff)
 {
 	struct mm_struct * mm = current->mm;
-	struct vm_area_struct * vma, * prev;
 	struct inode *inode;
 	unsigned int vm_flags;
-	int correct_wcount = 0;
 	int error;
-	struct rb_node ** rb_link, * rb_parent;
 	int accountable = 1;
-	unsigned long charged = 0, reqprot = prot;
+	unsigned long reqprot = prot;
 
 	/*
 	 * Does the application expect PROT_READ to imply PROT_EXEC?
@@ -1023,10 +1020,28 @@
 		}
 	}
 
-	error = security_file_mmap(file, reqprot, prot, flags);
+	error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
 	if (error)
 		return error;
-		
+
+	return mmap_region(file, addr, len, flags, vm_flags, pgoff,
+			   accountable);
+}
+EXPORT_SYMBOL(do_mmap_pgoff);
+
+unsigned long mmap_region(struct file *file, unsigned long addr,
+			  unsigned long len, unsigned long flags,
+			  unsigned int vm_flags, unsigned long pgoff,
+			  int accountable)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma, *prev;
+	int correct_wcount = 0;
+	int error;
+	struct rb_node **rb_link, *rb_parent;
+	unsigned long charged = 0;
+	struct inode *inode =  file ? file->f_path.dentry->d_inode : NULL;
+
 	/* Clear old maps */
 	error = -ENOMEM;
 munmap_back:
@@ -1175,8 +1190,6 @@
 	return error;
 }
 
-EXPORT_SYMBOL(do_mmap_pgoff);
-
 /* Get an address range which is currently unmapped.
  * For shmat() with addr=0.
  *
@@ -1536,9 +1549,14 @@
 	 * vma->vm_start/vm_end cannot change under us because the caller
 	 * is required to hold the mmap_sem in read mode.  We need the
 	 * anon_vma lock to serialize against concurrent expand_stacks.
+	 * Also guard against wrapping around to address 0.
 	 */
-	address += 4 + PAGE_SIZE - 1;
-	address &= PAGE_MASK;
+	if (address < PAGE_ALIGN(address+4))
+		address = PAGE_ALIGN(address+4);
+	else {
+		anon_vma_unlock(vma);
+		return -ENOMEM;
+	}
 	error = 0;
 
 	/* Somebody else might have raced and expanded it already */
diff --git a/mm/mremap.c b/mm/mremap.c
index 5d4bd4f..bc7c52e 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -291,6 +291,10 @@
 		if ((addr <= new_addr) && (addr+old_len) > new_addr)
 			goto out;
 
+		ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+		if (ret)
+			goto out;
+
 		ret = do_munmap(mm, new_addr, new_len);
 		if (ret)
 			goto out;
@@ -390,8 +394,13 @@
 
 			new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
 						vma->vm_pgoff, map_flags);
-			ret = new_addr;
-			if (new_addr & ~PAGE_MASK)
+			if (new_addr & ~PAGE_MASK) {
+				ret = new_addr;
+				goto out;
+			}
+
+			ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+			if (ret)
 				goto out;
 		}
 		ret = move_vma(vma, addr, old_len, new_len, new_addr);
diff --git a/mm/msync.c b/mm/msync.c
index 358d73c..144a757 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -12,6 +12,7 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/syscalls.h>
+#include <linux/sched.h>
 
 /*
  * MS_SYNC syncs the entire file - including mappings.
diff --git a/mm/nommu.c b/mm/nommu.c
index 2b16b00..8bbbf14 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -367,6 +367,11 @@
 	return find_vma(mm, addr);
 }
 
+int expand_stack(struct vm_area_struct *vma, unsigned long address)
+{
+	return -ENOMEM;
+}
+
 /*
  * look up the first VMA exactly that exactly matches addr
  * - should be called with mm->mmap_sem at least held readlocked
@@ -639,7 +644,7 @@
 	}
 
 	/* allow the security API to have its say */
-	ret = security_file_mmap(file, reqprot, prot, flags);
+	ret = security_file_mmap(file, reqprot, prot, flags, addr, 0);
 	if (ret < 0)
 		return ret;
 
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index eec1481..886ea0d 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -476,15 +476,13 @@
  * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs
  */
 int dirty_writeback_centisecs_handler(ctl_table *table, int write,
-		struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+	struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
 {
 	proc_dointvec_userhz_jiffies(table, write, file, buffer, length, ppos);
-	if (dirty_writeback_interval) {
-		mod_timer(&wb_timer,
-			jiffies + dirty_writeback_interval);
-		} else {
+	if (dirty_writeback_interval)
+		mod_timer(&wb_timer, jiffies + dirty_writeback_interval);
+	else
 		del_timer(&wb_timer);
-	}
 	return 0;
 }
 
@@ -826,6 +824,7 @@
 		mapping2 = page_mapping(page);
 		if (mapping2) { /* Race with truncate? */
 			BUG_ON(mapping2 != mapping);
+			WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
 			if (mapping_cap_account_dirty(mapping)) {
 				__inc_zone_page_state(page, NR_FILE_DIRTY);
 				task_io_account_write(PAGE_CACHE_SIZE);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ae96dd8..e2a10b9 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -80,8 +80,9 @@
 	 256,
 #endif
 #ifdef CONFIG_HIGHMEM
-	 32
+	 32,
 #endif
+	 32,
 };
 
 EXPORT_SYMBOL(totalram_pages);
@@ -95,8 +96,9 @@
 #endif
 	 "Normal",
 #ifdef CONFIG_HIGHMEM
-	 "HighMem"
+	 "HighMem",
 #endif
+	 "Movable",
 };
 
 int min_free_kbytes = 1024;
@@ -126,16 +128,28 @@
     #endif
   #endif
 
-  struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
-  int __meminitdata nr_nodemap_entries;
-  unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
-  unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
+  static struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
+  static int __meminitdata nr_nodemap_entries;
+  static unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
+  static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
 #ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
-  unsigned long __initdata node_boundary_start_pfn[MAX_NUMNODES];
-  unsigned long __initdata node_boundary_end_pfn[MAX_NUMNODES];
+  static unsigned long __meminitdata node_boundary_start_pfn[MAX_NUMNODES];
+  static unsigned long __meminitdata node_boundary_end_pfn[MAX_NUMNODES];
 #endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
+  unsigned long __initdata required_kernelcore;
+  unsigned long __initdata required_movablecore;
+  unsigned long __initdata zone_movable_pfn[MAX_NUMNODES];
+
+  /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
+  int movable_zone;
+  EXPORT_SYMBOL(movable_zone);
 #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 
+#if MAX_NUMNODES > 1
+int nr_node_ids __read_mostly = MAX_NUMNODES;
+EXPORT_SYMBOL(nr_node_ids);
+#endif
+
 #ifdef CONFIG_DEBUG_VM
 static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
 {
@@ -669,26 +683,6 @@
 	return i;
 }
 
-#if MAX_NUMNODES > 1
-int nr_node_ids __read_mostly = MAX_NUMNODES;
-EXPORT_SYMBOL(nr_node_ids);
-
-/*
- * Figure out the number of possible node ids.
- */
-static void __init setup_nr_node_ids(void)
-{
-	unsigned int node;
-	unsigned int highest = 0;
-
-	for_each_node_mask(node, node_possible_map)
-		highest = node;
-	nr_node_ids = highest + 1;
-}
-#else
-static void __init setup_nr_node_ids(void) {}
-#endif
-
 #ifdef CONFIG_NUMA
 /*
  * Called from the vmstat counter updater to drain pagesets of this
@@ -915,11 +909,13 @@
 
 	u32 ignore_gfp_highmem;
 	u32 ignore_gfp_wait;
+	u32 min_order;
 
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
 
 	struct dentry *ignore_gfp_highmem_file;
 	struct dentry *ignore_gfp_wait_file;
+	struct dentry *min_order_file;
 
 #endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
 
@@ -927,6 +923,7 @@
 	.attr = FAULT_ATTR_INITIALIZER,
 	.ignore_gfp_wait = 1,
 	.ignore_gfp_highmem = 1,
+	.min_order = 1,
 };
 
 static int __init setup_fail_page_alloc(char *str)
@@ -937,6 +934,8 @@
 
 static int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
 {
+	if (order < fail_page_alloc.min_order)
+		return 0;
 	if (gfp_mask & __GFP_NOFAIL)
 		return 0;
 	if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM))
@@ -968,12 +967,17 @@
 	fail_page_alloc.ignore_gfp_highmem_file =
 		debugfs_create_bool("ignore-gfp-highmem", mode, dir,
 				      &fail_page_alloc.ignore_gfp_highmem);
+	fail_page_alloc.min_order_file =
+		debugfs_create_u32("min-order", mode, dir,
+				   &fail_page_alloc.min_order);
 
 	if (!fail_page_alloc.ignore_gfp_wait_file ||
-			!fail_page_alloc.ignore_gfp_highmem_file) {
+            !fail_page_alloc.ignore_gfp_highmem_file ||
+            !fail_page_alloc.min_order_file) {
 		err = -ENOMEM;
 		debugfs_remove(fail_page_alloc.ignore_gfp_wait_file);
 		debugfs_remove(fail_page_alloc.ignore_gfp_highmem_file);
+		debugfs_remove(fail_page_alloc.min_order_file);
 		cleanup_fault_attr_dentries(&fail_page_alloc.attr);
 	}
 
@@ -1329,7 +1333,7 @@
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;
 
-	did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask);
+	did_some_progress = try_to_free_pages(zonelist->zones, order, gfp_mask);
 
 	p->reclaim_state = NULL;
 	p->flags &= ~PF_MEMALLOC;
@@ -1366,7 +1370,8 @@
 	 */
 	do_retry = 0;
 	if (!(gfp_mask & __GFP_NORETRY)) {
-		if ((order <= 3) || (gfp_mask & __GFP_REPEAT))
+		if ((order <= PAGE_ALLOC_COSTLY_ORDER) ||
+						(gfp_mask & __GFP_REPEAT))
 			do_retry = 1;
 		if (gfp_mask & __GFP_NOFAIL)
 			do_retry = 1;
@@ -1479,13 +1484,14 @@
 {
 	return nr_free_zone_pages(gfp_zone(GFP_USER));
 }
+EXPORT_SYMBOL_GPL(nr_free_buffer_pages);
 
 /*
  * Amount of free RAM allocatable within all zones
  */
 unsigned int nr_free_pagecache_pages(void)
 {
-	return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER));
+	return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER_MOVABLE));
 }
 
 static inline void show_node(struct zone *zone)
@@ -1636,8 +1642,8 @@
  *
  * Add all populated zones of a node to the zonelist.
  */
-static int __meminit build_zonelists_node(pg_data_t *pgdat,
-			struct zonelist *zonelist, int nr_zones, enum zone_type zone_type)
+static int build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist,
+				int nr_zones, enum zone_type zone_type)
 {
 	struct zone *zone;
 
@@ -1656,9 +1662,102 @@
 	return nr_zones;
 }
 
+
+/*
+ *  zonelist_order:
+ *  0 = automatic detection of better ordering.
+ *  1 = order by ([node] distance, -zonetype)
+ *  2 = order by (-zonetype, [node] distance)
+ *
+ *  If not NUMA, ZONELIST_ORDER_ZONE and ZONELIST_ORDER_NODE will create
+ *  the same zonelist. So only NUMA can configure this param.
+ */
+#define ZONELIST_ORDER_DEFAULT  0
+#define ZONELIST_ORDER_NODE     1
+#define ZONELIST_ORDER_ZONE     2
+
+/* zonelist order in the kernel.
+ * set_zonelist_order() will set this to NODE or ZONE.
+ */
+static int current_zonelist_order = ZONELIST_ORDER_DEFAULT;
+static char zonelist_order_name[3][8] = {"Default", "Node", "Zone"};
+
+
 #ifdef CONFIG_NUMA
+/* The value user specified ....changed by config */
+static int user_zonelist_order = ZONELIST_ORDER_DEFAULT;
+/* string for sysctl */
+#define NUMA_ZONELIST_ORDER_LEN	16
+char numa_zonelist_order[16] = "default";
+
+/*
+ * interface for configure zonelist ordering.
+ * command line option "numa_zonelist_order"
+ *	= "[dD]efault	- default, automatic configuration.
+ *	= "[nN]ode 	- order by node locality, then by zone within node
+ *	= "[zZ]one      - order by zone, then by locality within zone
+ */
+
+static int __parse_numa_zonelist_order(char *s)
+{
+	if (*s == 'd' || *s == 'D') {
+		user_zonelist_order = ZONELIST_ORDER_DEFAULT;
+	} else if (*s == 'n' || *s == 'N') {
+		user_zonelist_order = ZONELIST_ORDER_NODE;
+	} else if (*s == 'z' || *s == 'Z') {
+		user_zonelist_order = ZONELIST_ORDER_ZONE;
+	} else {
+		printk(KERN_WARNING
+			"Ignoring invalid numa_zonelist_order value:  "
+			"%s\n", s);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static __init int setup_numa_zonelist_order(char *s)
+{
+	if (s)
+		return __parse_numa_zonelist_order(s);
+	return 0;
+}
+early_param("numa_zonelist_order", setup_numa_zonelist_order);
+
+/*
+ * sysctl handler for numa_zonelist_order
+ */
+int numa_zonelist_order_handler(ctl_table *table, int write,
+		struct file *file, void __user *buffer, size_t *length,
+		loff_t *ppos)
+{
+	char saved_string[NUMA_ZONELIST_ORDER_LEN];
+	int ret;
+
+	if (write)
+		strncpy(saved_string, (char*)table->data,
+			NUMA_ZONELIST_ORDER_LEN);
+	ret = proc_dostring(table, write, file, buffer, length, ppos);
+	if (ret)
+		return ret;
+	if (write) {
+		int oldval = user_zonelist_order;
+		if (__parse_numa_zonelist_order((char*)table->data)) {
+			/*
+			 * bogus value.  restore saved string
+			 */
+			strncpy((char*)table->data, saved_string,
+				NUMA_ZONELIST_ORDER_LEN);
+			user_zonelist_order = oldval;
+		} else if (oldval != user_zonelist_order)
+			build_all_zonelists();
+	}
+	return 0;
+}
+
+
 #define MAX_NODE_LOAD (num_online_nodes())
-static int __meminitdata node_load[MAX_NUMNODES];
+static int node_load[MAX_NUMNODES];
+
 /**
  * find_next_best_node - find the next node that should appear in a given node's fallback list
  * @node: node whose fallback list we're appending
@@ -1673,7 +1772,7 @@
  * on them otherwise.
  * It returns -1 if no node is found.
  */
-static int __meminit find_next_best_node(int node, nodemask_t *used_node_mask)
+static int find_next_best_node(int node, nodemask_t *used_node_mask)
 {
 	int n, val;
 	int min_val = INT_MAX;
@@ -1719,13 +1818,129 @@
 	return best_node;
 }
 
-static void __meminit build_zonelists(pg_data_t *pgdat)
+
+/*
+ * Build zonelists ordered by node and zones within node.
+ * This results in maximum locality--normal zone overflows into local
+ * DMA zone, if any--but risks exhausting DMA zone.
+ */
+static void build_zonelists_in_node_order(pg_data_t *pgdat, int node)
 {
-	int j, node, local_node;
 	enum zone_type i;
-	int prev_node, load;
+	int j;
 	struct zonelist *zonelist;
+
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		zonelist = pgdat->node_zonelists + i;
+		for (j = 0; zonelist->zones[j] != NULL; j++)
+			;
+ 		j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
+		zonelist->zones[j] = NULL;
+	}
+}
+
+/*
+ * Build zonelists ordered by zone and nodes within zones.
+ * This results in conserving DMA zone[s] until all Normal memory is
+ * exhausted, but results in overflowing to remote node while memory
+ * may still exist in local DMA zone.
+ */
+static int node_order[MAX_NUMNODES];
+
+static void build_zonelists_in_zone_order(pg_data_t *pgdat, int nr_nodes)
+{
+	enum zone_type i;
+	int pos, j, node;
+	int zone_type;		/* needs to be signed */
+	struct zone *z;
+	struct zonelist *zonelist;
+
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		zonelist = pgdat->node_zonelists + i;
+		pos = 0;
+		for (zone_type = i; zone_type >= 0; zone_type--) {
+			for (j = 0; j < nr_nodes; j++) {
+				node = node_order[j];
+				z = &NODE_DATA(node)->node_zones[zone_type];
+				if (populated_zone(z)) {
+					zonelist->zones[pos++] = z;
+					check_highest_zone(zone_type);
+				}
+			}
+		}
+		zonelist->zones[pos] = NULL;
+	}
+}
+
+static int default_zonelist_order(void)
+{
+	int nid, zone_type;
+	unsigned long low_kmem_size,total_size;
+	struct zone *z;
+	int average_size;
+	/*
+         * ZONE_DMA and ZONE_DMA32 can be very small area in the sytem.
+	 * If they are really small and used heavily, the system can fall
+	 * into OOM very easily.
+	 * This function detect ZONE_DMA/DMA32 size and confgigures zone order.
+	 */
+	/* Is there ZONE_NORMAL ? (ex. ppc has only DMA zone..) */
+	low_kmem_size = 0;
+	total_size = 0;
+	for_each_online_node(nid) {
+		for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++) {
+			z = &NODE_DATA(nid)->node_zones[zone_type];
+			if (populated_zone(z)) {
+				if (zone_type < ZONE_NORMAL)
+					low_kmem_size += z->present_pages;
+				total_size += z->present_pages;
+			}
+		}
+	}
+	if (!low_kmem_size ||  /* there are no DMA area. */
+	    low_kmem_size > total_size/2) /* DMA/DMA32 is big. */
+		return ZONELIST_ORDER_NODE;
+	/*
+	 * look into each node's config.
+  	 * If there is a node whose DMA/DMA32 memory is very big area on
+ 	 * local memory, NODE_ORDER may be suitable.
+         */
+	average_size = total_size / (num_online_nodes() + 1);
+	for_each_online_node(nid) {
+		low_kmem_size = 0;
+		total_size = 0;
+		for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++) {
+			z = &NODE_DATA(nid)->node_zones[zone_type];
+			if (populated_zone(z)) {
+				if (zone_type < ZONE_NORMAL)
+					low_kmem_size += z->present_pages;
+				total_size += z->present_pages;
+			}
+		}
+		if (low_kmem_size &&
+		    total_size > average_size && /* ignore small node */
+		    low_kmem_size > total_size * 70/100)
+			return ZONELIST_ORDER_NODE;
+	}
+	return ZONELIST_ORDER_ZONE;
+}
+
+static void set_zonelist_order(void)
+{
+	if (user_zonelist_order == ZONELIST_ORDER_DEFAULT)
+		current_zonelist_order = default_zonelist_order();
+	else
+		current_zonelist_order = user_zonelist_order;
+}
+
+static void build_zonelists(pg_data_t *pgdat)
+{
+	int j, node, load;
+	enum zone_type i;
 	nodemask_t used_mask;
+	int local_node, prev_node;
+	struct zonelist *zonelist;
+	int order = current_zonelist_order;
 
 	/* initialize zonelists */
 	for (i = 0; i < MAX_NR_ZONES; i++) {
@@ -1738,6 +1953,11 @@
 	load = num_online_nodes();
 	prev_node = local_node;
 	nodes_clear(used_mask);
+
+	memset(node_load, 0, sizeof(node_load));
+	memset(node_order, 0, sizeof(node_order));
+	j = 0;
+
 	while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
 		int distance = node_distance(local_node, node);
 
@@ -1753,23 +1973,25 @@
 		 * So adding penalty to the first node in same
 		 * distance group to make it round-robin.
 		 */
-
 		if (distance != node_distance(local_node, prev_node))
-			node_load[node] += load;
+			node_load[node] = load;
+
 		prev_node = node;
 		load--;
-		for (i = 0; i < MAX_NR_ZONES; i++) {
-			zonelist = pgdat->node_zonelists + i;
-			for (j = 0; zonelist->zones[j] != NULL; j++);
+		if (order == ZONELIST_ORDER_NODE)
+			build_zonelists_in_node_order(pgdat, node);
+		else
+			node_order[j++] = node;	/* remember order */
+	}
 
-	 		j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
-			zonelist->zones[j] = NULL;
-		}
+	if (order == ZONELIST_ORDER_ZONE) {
+		/* calculate node order -- i.e., DMA last! */
+		build_zonelists_in_zone_order(pgdat, j);
 	}
 }
 
 /* Construct the zonelist performance cache - see further mmzone.h */
-static void __meminit build_zonelist_cache(pg_data_t *pgdat)
+static void build_zonelist_cache(pg_data_t *pgdat)
 {
 	int i;
 
@@ -1786,9 +2008,15 @@
 	}
 }
 
+
 #else	/* CONFIG_NUMA */
 
-static void __meminit build_zonelists(pg_data_t *pgdat)
+static void set_zonelist_order(void)
+{
+	current_zonelist_order = ZONELIST_ORDER_ZONE;
+}
+
+static void build_zonelists(pg_data_t *pgdat)
 {
 	int node, local_node;
 	enum zone_type i,j;
@@ -1824,7 +2052,7 @@
 }
 
 /* non-NUMA variant of zonelist performance cache - just NULL zlcache_ptr */
-static void __meminit build_zonelist_cache(pg_data_t *pgdat)
+static void build_zonelist_cache(pg_data_t *pgdat)
 {
 	int i;
 
@@ -1835,7 +2063,7 @@
 #endif	/* CONFIG_NUMA */
 
 /* return values int ....just for stop_machine_run() */
-static int __meminit __build_all_zonelists(void *dummy)
+static int __build_all_zonelists(void *dummy)
 {
 	int nid;
 
@@ -1846,8 +2074,10 @@
 	return 0;
 }
 
-void __meminit build_all_zonelists(void)
+void build_all_zonelists(void)
 {
+	set_zonelist_order();
+
 	if (system_state == SYSTEM_BOOTING) {
 		__build_all_zonelists(NULL);
 		cpuset_init_current_mems_allowed();
@@ -1858,8 +2088,13 @@
 		/* cpuset refresh routine should be here */
 	}
 	vm_total_pages = nr_free_pagecache_pages();
-	printk("Built %i zonelists.  Total pages: %ld\n",
-			num_online_nodes(), vm_total_pages);
+	printk("Built %i zonelists in %s order.  Total pages: %ld\n",
+			num_online_nodes(),
+			zonelist_order_name[current_zonelist_order],
+			vm_total_pages);
+#ifdef CONFIG_NUMA
+	printk("Policy zone: %s\n", zone_names[policy_zone]);
+#endif
 }
 
 /*
@@ -1968,8 +2203,8 @@
 	}
 }
 
-void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
-				unsigned long size)
+static void __meminit zone_init_free_lists(struct pglist_data *pgdat,
+				struct zone *zone, unsigned long size)
 {
 	int order;
 	for (order = 0; order < MAX_ORDER ; order++) {
@@ -1983,7 +2218,7 @@
 	memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY)
 #endif
 
-static int __cpuinit zone_batchsize(struct zone *zone)
+static int __devinit zone_batchsize(struct zone *zone)
 {
 	int batch;
 
@@ -2165,7 +2400,7 @@
 
 #endif
 
-static __meminit noinline
+static noinline __init_refok
 int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
 {
 	int i;
@@ -2385,7 +2620,7 @@
 }
 
 /* If necessary, push the node boundary out for reserve hotadd */
-static void __init account_node_boundary(unsigned int nid,
+static void __meminit account_node_boundary(unsigned int nid,
 		unsigned long *start_pfn, unsigned long *end_pfn)
 {
 	printk(KERN_DEBUG "Entering account_node_boundary(%u, %lu, %lu)\n",
@@ -2405,7 +2640,7 @@
 void __init push_node_boundaries(unsigned int nid,
 		unsigned long start_pfn, unsigned long end_pfn) {}
 
-static void __init account_node_boundary(unsigned int nid,
+static void __meminit account_node_boundary(unsigned int nid,
 		unsigned long *start_pfn, unsigned long *end_pfn) {}
 #endif
 
@@ -2443,10 +2678,67 @@
 }
 
 /*
+ * This finds a zone that can be used for ZONE_MOVABLE pages. The
+ * assumption is made that zones within a node are ordered in monotonic
+ * increasing memory addresses so that the "highest" populated zone is used
+ */
+void __init find_usable_zone_for_movable(void)
+{
+	int zone_index;
+	for (zone_index = MAX_NR_ZONES - 1; zone_index >= 0; zone_index--) {
+		if (zone_index == ZONE_MOVABLE)
+			continue;
+
+		if (arch_zone_highest_possible_pfn[zone_index] >
+				arch_zone_lowest_possible_pfn[zone_index])
+			break;
+	}
+
+	VM_BUG_ON(zone_index == -1);
+	movable_zone = zone_index;
+}
+
+/*
+ * The zone ranges provided by the architecture do not include ZONE_MOVABLE
+ * because it is sized independant of architecture. Unlike the other zones,
+ * the starting point for ZONE_MOVABLE is not fixed. It may be different
+ * in each node depending on the size of each node and how evenly kernelcore
+ * is distributed. This helper function adjusts the zone ranges
+ * provided by the architecture for a given node by using the end of the
+ * highest usable zone for ZONE_MOVABLE. This preserves the assumption that
+ * zones within a node are in order of monotonic increases memory addresses
+ */
+void __meminit adjust_zone_range_for_zone_movable(int nid,
+					unsigned long zone_type,
+					unsigned long node_start_pfn,
+					unsigned long node_end_pfn,
+					unsigned long *zone_start_pfn,
+					unsigned long *zone_end_pfn)
+{
+	/* Only adjust if ZONE_MOVABLE is on this node */
+	if (zone_movable_pfn[nid]) {
+		/* Size ZONE_MOVABLE */
+		if (zone_type == ZONE_MOVABLE) {
+			*zone_start_pfn = zone_movable_pfn[nid];
+			*zone_end_pfn = min(node_end_pfn,
+				arch_zone_highest_possible_pfn[movable_zone]);
+
+		/* Adjust for ZONE_MOVABLE starting within this range */
+		} else if (*zone_start_pfn < zone_movable_pfn[nid] &&
+				*zone_end_pfn > zone_movable_pfn[nid]) {
+			*zone_end_pfn = zone_movable_pfn[nid];
+
+		/* Check if this whole range is within ZONE_MOVABLE */
+		} else if (*zone_start_pfn >= zone_movable_pfn[nid])
+			*zone_start_pfn = *zone_end_pfn;
+	}
+}
+
+/*
  * Return the number of pages a zone spans in a node, including holes
  * present_pages = zone_spanned_pages_in_node() - zone_absent_pages_in_node()
  */
-unsigned long __meminit zone_spanned_pages_in_node(int nid,
+static unsigned long __meminit zone_spanned_pages_in_node(int nid,
 					unsigned long zone_type,
 					unsigned long *ignored)
 {
@@ -2457,6 +2749,9 @@
 	get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn);
 	zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
 	zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
+	adjust_zone_range_for_zone_movable(nid, zone_type,
+				node_start_pfn, node_end_pfn,
+				&zone_start_pfn, &zone_end_pfn);
 
 	/* Check that this node has pages within the zone's required range */
 	if (zone_end_pfn < node_start_pfn || zone_start_pfn > node_end_pfn)
@@ -2534,7 +2829,7 @@
 }
 
 /* Return the number of page frames in holes in a zone on a node */
-unsigned long __meminit zone_absent_pages_in_node(int nid,
+static unsigned long __meminit zone_absent_pages_in_node(int nid,
 					unsigned long zone_type,
 					unsigned long *ignored)
 {
@@ -2547,18 +2842,21 @@
 	zone_end_pfn = min(arch_zone_highest_possible_pfn[zone_type],
 							node_end_pfn);
 
+	adjust_zone_range_for_zone_movable(nid, zone_type,
+			node_start_pfn, node_end_pfn,
+			&zone_start_pfn, &zone_end_pfn);
 	return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
 }
 
 #else
-static inline unsigned long zone_spanned_pages_in_node(int nid,
+static inline unsigned long __meminit zone_spanned_pages_in_node(int nid,
 					unsigned long zone_type,
 					unsigned long *zones_size)
 {
 	return zones_size[zone_type];
 }
 
-static inline unsigned long zone_absent_pages_in_node(int nid,
+static inline unsigned long __meminit zone_absent_pages_in_node(int nid,
 						unsigned long zone_type,
 						unsigned long *zholes_size)
 {
@@ -2678,7 +2976,7 @@
 	}
 }
 
-static void __meminit alloc_node_mem_map(struct pglist_data *pgdat)
+static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
 {
 	/* Skip empty nodes */
 	if (!pgdat->node_spanned_pages)
@@ -2704,7 +3002,7 @@
 			map = alloc_bootmem_node(pgdat, size);
 		pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);
 	}
-#ifdef CONFIG_FLATMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 	/*
 	 * With no DISCONTIG, the global mem_map is just set as node 0's
 	 */
@@ -2733,6 +3031,26 @@
 }
 
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+
+#if MAX_NUMNODES > 1
+/*
+ * Figure out the number of possible node ids.
+ */
+static void __init setup_nr_node_ids(void)
+{
+	unsigned int node;
+	unsigned int highest = 0;
+
+	for_each_node_mask(node, node_possible_map)
+		highest = node;
+	nr_node_ids = highest + 1;
+}
+#else
+static inline void setup_nr_node_ids(void)
+{
+}
+#endif
+
 /**
  * add_active_range - Register a range of PFNs backed by physical memory
  * @nid: The node ID the range resides on
@@ -2904,6 +3222,157 @@
 	return max_pfn;
 }
 
+unsigned long __init early_calculate_totalpages(void)
+{
+	int i;
+	unsigned long totalpages = 0;
+
+	for (i = 0; i < nr_nodemap_entries; i++)
+		totalpages += early_node_map[i].end_pfn -
+						early_node_map[i].start_pfn;
+
+	return totalpages;
+}
+
+/*
+ * Find the PFN the Movable zone begins in each node. Kernel memory
+ * is spread evenly between nodes as long as the nodes have enough
+ * memory. When they don't, some nodes will have more kernelcore than
+ * others
+ */
+void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
+{
+	int i, nid;
+	unsigned long usable_startpfn;
+	unsigned long kernelcore_node, kernelcore_remaining;
+	int usable_nodes = num_online_nodes();
+
+	/*
+	 * If movablecore was specified, calculate what size of
+	 * kernelcore that corresponds so that memory usable for
+	 * any allocation type is evenly spread. If both kernelcore
+	 * and movablecore are specified, then the value of kernelcore
+	 * will be used for required_kernelcore if it's greater than
+	 * what movablecore would have allowed.
+	 */
+	if (required_movablecore) {
+		unsigned long totalpages = early_calculate_totalpages();
+		unsigned long corepages;
+
+		/*
+		 * Round-up so that ZONE_MOVABLE is at least as large as what
+		 * was requested by the user
+		 */
+		required_movablecore =
+			roundup(required_movablecore, MAX_ORDER_NR_PAGES);
+		corepages = totalpages - required_movablecore;
+
+		required_kernelcore = max(required_kernelcore, corepages);
+	}
+
+	/* If kernelcore was not specified, there is no ZONE_MOVABLE */
+	if (!required_kernelcore)
+		return;
+
+	/* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */
+	find_usable_zone_for_movable();
+	usable_startpfn = arch_zone_lowest_possible_pfn[movable_zone];
+
+restart:
+	/* Spread kernelcore memory as evenly as possible throughout nodes */
+	kernelcore_node = required_kernelcore / usable_nodes;
+	for_each_online_node(nid) {
+		/*
+		 * Recalculate kernelcore_node if the division per node
+		 * now exceeds what is necessary to satisfy the requested
+		 * amount of memory for the kernel
+		 */
+		if (required_kernelcore < kernelcore_node)
+			kernelcore_node = required_kernelcore / usable_nodes;
+
+		/*
+		 * As the map is walked, we track how much memory is usable
+		 * by the kernel using kernelcore_remaining. When it is
+		 * 0, the rest of the node is usable by ZONE_MOVABLE
+		 */
+		kernelcore_remaining = kernelcore_node;
+
+		/* Go through each range of PFNs within this node */
+		for_each_active_range_index_in_nid(i, nid) {
+			unsigned long start_pfn, end_pfn;
+			unsigned long size_pages;
+
+			start_pfn = max(early_node_map[i].start_pfn,
+						zone_movable_pfn[nid]);
+			end_pfn = early_node_map[i].end_pfn;
+			if (start_pfn >= end_pfn)
+				continue;
+
+			/* Account for what is only usable for kernelcore */
+			if (start_pfn < usable_startpfn) {
+				unsigned long kernel_pages;
+				kernel_pages = min(end_pfn, usable_startpfn)
+								- start_pfn;
+
+				kernelcore_remaining -= min(kernel_pages,
+							kernelcore_remaining);
+				required_kernelcore -= min(kernel_pages,
+							required_kernelcore);
+
+				/* Continue if range is now fully accounted */
+				if (end_pfn <= usable_startpfn) {
+
+					/*
+					 * Push zone_movable_pfn to the end so
+					 * that if we have to rebalance
+					 * kernelcore across nodes, we will
+					 * not double account here
+					 */
+					zone_movable_pfn[nid] = end_pfn;
+					continue;
+				}
+				start_pfn = usable_startpfn;
+			}
+
+			/*
+			 * The usable PFN range for ZONE_MOVABLE is from
+			 * start_pfn->end_pfn. Calculate size_pages as the
+			 * number of pages used as kernelcore
+			 */
+			size_pages = end_pfn - start_pfn;
+			if (size_pages > kernelcore_remaining)
+				size_pages = kernelcore_remaining;
+			zone_movable_pfn[nid] = start_pfn + size_pages;
+
+			/*
+			 * Some kernelcore has been met, update counts and
+			 * break if the kernelcore for this node has been
+			 * satisified
+			 */
+			required_kernelcore -= min(required_kernelcore,
+								size_pages);
+			kernelcore_remaining -= size_pages;
+			if (!kernelcore_remaining)
+				break;
+		}
+	}
+
+	/*
+	 * If there is still required_kernelcore, we do another pass with one
+	 * less node in the count. This will push zone_movable_pfn[nid] further
+	 * along on the nodes that still have memory until kernelcore is
+	 * satisified
+	 */
+	usable_nodes--;
+	if (usable_nodes && required_kernelcore > usable_nodes)
+		goto restart;
+
+	/* Align start of ZONE_MOVABLE on all nids to MAX_ORDER_NR_PAGES */
+	for (nid = 0; nid < MAX_NUMNODES; nid++)
+		zone_movable_pfn[nid] =
+			roundup(zone_movable_pfn[nid], MAX_ORDER_NR_PAGES);
+}
+
 /**
  * free_area_init_nodes - Initialise all pg_data_t and zone data
  * @max_zone_pfn: an array of max PFNs for each zone
@@ -2933,19 +3402,37 @@
 	arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions();
 	arch_zone_highest_possible_pfn[0] = max_zone_pfn[0];
 	for (i = 1; i < MAX_NR_ZONES; i++) {
+		if (i == ZONE_MOVABLE)
+			continue;
 		arch_zone_lowest_possible_pfn[i] =
 			arch_zone_highest_possible_pfn[i-1];
 		arch_zone_highest_possible_pfn[i] =
 			max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
 	}
+	arch_zone_lowest_possible_pfn[ZONE_MOVABLE] = 0;
+	arch_zone_highest_possible_pfn[ZONE_MOVABLE] = 0;
+
+	/* Find the PFNs that ZONE_MOVABLE begins at in each node */
+	memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn));
+	find_zone_movable_pfns_for_nodes(zone_movable_pfn);
 
 	/* Print out the zone ranges */
 	printk("Zone PFN ranges:\n");
-	for (i = 0; i < MAX_NR_ZONES; i++)
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		if (i == ZONE_MOVABLE)
+			continue;
 		printk("  %-8s %8lu -> %8lu\n",
 				zone_names[i],
 				arch_zone_lowest_possible_pfn[i],
 				arch_zone_highest_possible_pfn[i]);
+	}
+
+	/* Print out the PFNs ZONE_MOVABLE begins at in each node */
+	printk("Movable zone start PFN for each node\n");
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		if (zone_movable_pfn[i])
+			printk("  Node %d: %lu\n", i, zone_movable_pfn[i]);
+	}
 
 	/* Print out the early_node_map[] */
 	printk("early_node_map[%d] active PFN ranges\n", nr_nodemap_entries);
@@ -2962,6 +3449,43 @@
 				find_min_pfn_for_node(nid), NULL);
 	}
 }
+
+static int __init cmdline_parse_core(char *p, unsigned long *core)
+{
+	unsigned long long coremem;
+	if (!p)
+		return -EINVAL;
+
+	coremem = memparse(p, &p);
+	*core = coremem >> PAGE_SHIFT;
+
+	/* Paranoid check that UL is enough for the coremem value */
+	WARN_ON((coremem >> PAGE_SHIFT) > ULONG_MAX);
+
+	return 0;
+}
+
+/*
+ * kernelcore=size sets the amount of memory for use for allocations that
+ * cannot be reclaimed or migrated.
+ */
+static int __init cmdline_parse_kernelcore(char *p)
+{
+	return cmdline_parse_core(p, &required_kernelcore);
+}
+
+/*
+ * movablecore=size sets the amount of memory for use for allocations that
+ * can be reclaimed or migrated.
+ */
+static int __init cmdline_parse_movablecore(char *p)
+{
+	return cmdline_parse_core(p, &required_movablecore);
+}
+
+early_param("kernelcore", cmdline_parse_kernelcore);
+early_param("movablecore", cmdline_parse_movablecore);
+
 #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 
 /**
@@ -3350,13 +3874,28 @@
 			for (order = 0; ((1UL << order) << PAGE_SHIFT) < size; order++)
 				;
 			table = (void*) __get_free_pages(GFP_ATOMIC, order);
+			/*
+			 * If bucketsize is not a power-of-two, we may free
+			 * some pages at the end of hash table.
+			 */
+			if (table) {
+				unsigned long alloc_end = (unsigned long)table +
+						(PAGE_SIZE << order);
+				unsigned long used = (unsigned long)table +
+						PAGE_ALIGN(size);
+				split_page(virt_to_page(table), order);
+				while (used < alloc_end) {
+					free_page(used);
+					used += PAGE_SIZE;
+				}
+			}
 		}
 	} while (!table && size > PAGE_SIZE && --log2qty);
 
 	if (!table)
 		panic("Failed to allocate %s hash table\n", tablename);
 
-	printk("%s hash table entries: %d (order: %d, %lu bytes)\n",
+	printk(KERN_INFO "%s hash table entries: %d (order: %d, %lu bytes)\n",
 	       tablename,
 	       (1U << log2qty),
 	       ilog2(size) - PAGE_SHIFT,
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 8ce0900..8f6ee07 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -92,6 +92,7 @@
 static int __pdflush(struct pdflush_work *my_work)
 {
 	current->flags |= PF_FLUSHER | PF_SWAPWRITE;
+	set_freezable();
 	my_work->fn = NULL;
 	my_work->who = current;
 	INIT_LIST_HEAD(&my_work->list);
diff --git a/mm/rmap.c b/mm/rmap.c
index 850165d..61e4925 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -53,24 +53,6 @@
 
 struct kmem_cache *anon_vma_cachep;
 
-static inline void validate_anon_vma(struct vm_area_struct *find_vma)
-{
-#ifdef CONFIG_DEBUG_VM
-	struct anon_vma *anon_vma = find_vma->anon_vma;
-	struct vm_area_struct *vma;
-	unsigned int mapcount = 0;
-	int found = 0;
-
-	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
-		mapcount++;
-		BUG_ON(mapcount > 100000);
-		if (vma == find_vma)
-			found = 1;
-	}
-	BUG_ON(!found);
-#endif
-}
-
 /* This must be called under the mmap_sem. */
 int anon_vma_prepare(struct vm_area_struct *vma)
 {
@@ -121,10 +103,8 @@
 {
 	struct anon_vma *anon_vma = vma->anon_vma;
 
-	if (anon_vma) {
+	if (anon_vma)
 		list_add_tail(&vma->anon_vma_node, &anon_vma->head);
-		validate_anon_vma(vma);
-	}
 }
 
 void anon_vma_link(struct vm_area_struct *vma)
@@ -134,7 +114,6 @@
 	if (anon_vma) {
 		spin_lock(&anon_vma->lock);
 		list_add_tail(&vma->anon_vma_node, &anon_vma->head);
-		validate_anon_vma(vma);
 		spin_unlock(&anon_vma->lock);
 	}
 }
@@ -148,7 +127,6 @@
 		return;
 
 	spin_lock(&anon_vma->lock);
-	validate_anon_vma(vma);
 	list_del(&vma->anon_vma_node);
 
 	/* We must garbage collect the anon_vma if it's empty */
diff --git a/mm/shmem.c b/mm/shmem.c
index e537317..96fa79f 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/xattr.h>
+#include <linux/exportfs.h>
 #include <linux/generic_acl.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
@@ -93,8 +94,11 @@
 	 * The above definition of ENTRIES_PER_PAGE, and the use of
 	 * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
 	 * might be reconsidered if it ever diverges from PAGE_SIZE.
+	 *
+	 * __GFP_MOVABLE is masked out as swap vectors cannot move
 	 */
-	return alloc_pages(gfp_mask, PAGE_CACHE_SHIFT-PAGE_SHIFT);
+	return alloc_pages((gfp_mask & ~__GFP_MOVABLE) | __GFP_ZERO,
+				PAGE_CACHE_SHIFT-PAGE_SHIFT);
 }
 
 static inline void shmem_dir_free(struct page *page)
@@ -372,7 +376,7 @@
 		}
 
 		spin_unlock(&info->lock);
-		page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping) | __GFP_ZERO);
+		page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping));
 		if (page)
 			set_page_private(page, 0);
 		spin_lock(&info->lock);
@@ -967,6 +971,8 @@
 		*nodelist++ = '\0';
 		if (nodelist_parse(nodelist, *policy_nodes))
 			goto out;
+		if (!nodes_subset(*policy_nodes, node_online_map))
+			goto out;
 	}
 	if (!strcmp(value, "default")) {
 		*policy = MPOL_DEFAULT;
@@ -1098,9 +1104,9 @@
 	 * Normally, filepage is NULL on entry, and either found
 	 * uptodate immediately, or allocated and zeroed, or read
 	 * in under swappage, which is then assigned to filepage.
-	 * But shmem_prepare_write passes in a locked filepage,
-	 * which may be found not uptodate by other callers too,
-	 * and may need to be copied from the swappage read in.
+	 * But shmem_readpage and shmem_prepare_write pass in a locked
+	 * filepage, which may be found not uptodate by other callers
+	 * too, and may need to be copied from the swappage read in.
 	 */
 repeat:
 	if (!filepage)
@@ -1483,9 +1489,18 @@
 static const struct inode_operations shmem_symlink_inline_operations;
 
 /*
- * Normally tmpfs makes no use of shmem_prepare_write, but it
- * lets a tmpfs file be used read-write below the loop driver.
+ * Normally tmpfs avoids the use of shmem_readpage and shmem_prepare_write;
+ * but providing them allows a tmpfs file to be used for splice, sendfile, and
+ * below the loop driver, in the generic fashion that many filesystems support.
  */
+static int shmem_readpage(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL);
+	unlock_page(page);
+	return error;
+}
+
 static int
 shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
@@ -1709,25 +1724,6 @@
 	return desc.error;
 }
 
-static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
-			 size_t count, read_actor_t actor, void *target)
-{
-	read_descriptor_t desc;
-
-	if (!count)
-		return 0;
-
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-
-	do_shmem_file_read(in_file, ppos, &desc, actor);
-	if (desc.written)
-		return desc.written;
-	return desc.error;
-}
-
 static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
@@ -2384,6 +2380,7 @@
 	.writepage	= shmem_writepage,
 	.set_page_dirty	= __set_page_dirty_no_writeback,
 #ifdef CONFIG_TMPFS
+	.readpage	= shmem_readpage,
 	.prepare_write	= shmem_prepare_write,
 	.commit_write	= simple_commit_write,
 #endif
@@ -2397,7 +2394,8 @@
 	.read		= shmem_file_read,
 	.write		= shmem_file_write,
 	.fsync		= simple_sync_file,
-	.sendfile	= shmem_file_sendfile,
+	.splice_read	= generic_file_splice_read,
+	.splice_write	= generic_file_splice_write,
 #endif
 };
 
diff --git a/mm/slab.c b/mm/slab.c
index 528243e..96d30ee 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -137,6 +137,7 @@
 
 /* Shouldn't this be in a header file somewhere? */
 #define	BYTES_PER_WORD		sizeof(void *)
+#define	REDZONE_ALIGN		max(BYTES_PER_WORD, __alignof__(unsigned long long))
 
 #ifndef cache_line_size
 #define cache_line_size()	L1_CACHE_BYTES
@@ -547,7 +548,7 @@
 	if (cachep->flags & SLAB_STORE_USER)
 		return (unsigned long long *)(objp + cachep->buffer_size -
 					      sizeof(unsigned long long) -
-					      BYTES_PER_WORD);
+					      REDZONE_ALIGN);
 	return (unsigned long long *) (objp + cachep->buffer_size -
 				       sizeof(unsigned long long));
 }
@@ -774,7 +775,9 @@
 	 */
 	BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
 #endif
-	WARN_ON_ONCE(size == 0);
+	if (!size)
+		return ZERO_SIZE_PTR;
+
 	while (size > csizep->cs_size)
 		csizep++;
 
@@ -929,7 +932,7 @@
  * the CPUs getting into lockstep and contending for the global cache chain
  * lock.
  */
-static void __devinit start_cpu_timer(int cpu)
+static void __cpuinit start_cpu_timer(int cpu)
 {
 	struct delayed_work *reap_work = &per_cpu(reap_work, cpu);
 
@@ -2037,7 +2040,7 @@
 	return left_over;
 }
 
-static int setup_cpu_cache(struct kmem_cache *cachep)
+static int __init_refok setup_cpu_cache(struct kmem_cache *cachep)
 {
 	if (g_cpucache_up == FULL)
 		return enable_cpucache(cachep);
@@ -2179,7 +2182,8 @@
 	 * above the next power of two: caches with object sizes just above a
 	 * power of two have a significant amount of internal fragmentation.
 	 */
-	if (size < 4096 || fls(size - 1) == fls(size-1 + 3 * BYTES_PER_WORD))
+	if (size < 4096 || fls(size - 1) == fls(size-1 + REDZONE_ALIGN +
+						2 * sizeof(unsigned long long)))
 		flags |= SLAB_RED_ZONE | SLAB_STORE_USER;
 	if (!(flags & SLAB_DESTROY_BY_RCU))
 		flags |= SLAB_POISON;
@@ -2220,12 +2224,20 @@
 	}
 
 	/*
-	 * Redzoning and user store require word alignment. Note this will be
-	 * overridden by architecture or caller mandated alignment if either
-	 * is greater than BYTES_PER_WORD.
+	 * Redzoning and user store require word alignment or possibly larger.
+	 * Note this will be overridden by architecture or caller mandated
+	 * alignment if either is greater than BYTES_PER_WORD.
 	 */
-	if (flags & SLAB_RED_ZONE || flags & SLAB_STORE_USER)
-		ralign = __alignof__(unsigned long long);
+	if (flags & SLAB_STORE_USER)
+		ralign = BYTES_PER_WORD;
+
+	if (flags & SLAB_RED_ZONE) {
+		ralign = REDZONE_ALIGN;
+		/* If redzoning, ensure that the second redzone is suitably
+		 * aligned, by adjusting the object size accordingly. */
+		size += REDZONE_ALIGN - 1;
+		size &= ~(REDZONE_ALIGN - 1);
+	}
 
 	/* 2) arch mandated alignment */
 	if (ralign < ARCH_SLAB_MINALIGN) {
@@ -2262,9 +2274,13 @@
 	}
 	if (flags & SLAB_STORE_USER) {
 		/* user store requires one word storage behind the end of
-		 * the real object.
+		 * the real object. But if the second red zone needs to be
+		 * aligned to 64 bits, we must allow that much space.
 		 */
-		size += BYTES_PER_WORD;
+		if (flags & SLAB_RED_ZONE)
+			size += REDZONE_ALIGN;
+		else
+			size += BYTES_PER_WORD;
 	}
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
 	if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
@@ -2338,7 +2354,7 @@
 		 * this should not happen at all.
 		 * But leave a BUG_ON for some lucky dude.
 		 */
-		BUG_ON(!cachep->slabp_cache);
+		BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
 	}
 	cachep->ctor = ctor;
 	cachep->name = name;
@@ -2730,7 +2746,7 @@
 	 * Be lazy and only check for valid flags here,  keeping it out of the
 	 * critical path in kmem_cache_alloc().
 	 */
-	BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK));
+	BUG_ON(flags & ~(GFP_DMA | __GFP_ZERO | GFP_LEVEL_MASK));
 
 	local_flags = (flags & GFP_LEVEL_MASK);
 	/* Take the l3 list lock to change the colour_next on this node */
@@ -3376,6 +3392,9 @@
 	local_irq_restore(save_flags);
 	ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
 
+	if (unlikely((flags & __GFP_ZERO) && ptr))
+		memset(ptr, 0, obj_size(cachep));
+
 	return ptr;
 }
 
@@ -3427,6 +3446,9 @@
 	objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
 	prefetchw(objp);
 
+	if (unlikely((flags & __GFP_ZERO) && objp))
+		memset(objp, 0, obj_size(cachep));
+
 	return objp;
 }
 
@@ -3539,7 +3561,7 @@
 	check_irq_off();
 	objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
 
-	if (use_alien_caches && cache_free_alien(cachep, objp))
+	if (cache_free_alien(cachep, objp))
 		return;
 
 	if (likely(ac->avail < ac->limit)) {
@@ -3568,23 +3590,6 @@
 EXPORT_SYMBOL(kmem_cache_alloc);
 
 /**
- * kmem_cache_zalloc - Allocate an object. The memory is set to zero.
- * @cache: The cache to allocate from.
- * @flags: See kmalloc().
- *
- * Allocate an object from this cache and set the allocated memory to zero.
- * The flags are only relevant if the cache has no available objects.
- */
-void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t flags)
-{
-	void *ret = __cache_alloc(cache, flags, __builtin_return_address(0));
-	if (ret)
-		memset(ret, 0, obj_size(cache));
-	return ret;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
-
-/**
  * kmem_ptr_validate - check if an untrusted pointer might
  *	be a slab entry.
  * @cachep: the cache we're checking against
@@ -3640,8 +3645,8 @@
 	struct kmem_cache *cachep;
 
 	cachep = kmem_find_general_cachep(size, flags);
-	if (unlikely(cachep == NULL))
-		return NULL;
+	if (unlikely(ZERO_OR_NULL_PTR(cachep)))
+		return cachep;
 	return kmem_cache_alloc_node(cachep, flags, node);
 }
 
@@ -3713,52 +3718,6 @@
 #endif
 
 /**
- * krealloc - reallocate memory. The contents will remain unchanged.
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
- */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
-{
-	struct kmem_cache *cache, *new_cache;
-	void *ret;
-
-	if (unlikely(!p))
-		return kmalloc_track_caller(new_size, flags);
-
-	if (unlikely(!new_size)) {
-		kfree(p);
-		return NULL;
-	}
-
-	cache = virt_to_cache(p);
-	new_cache = __find_general_cachep(new_size, flags);
-
-	/*
- 	 * If new size fits in the current cache, bail out.
- 	 */
-	if (likely(cache == new_cache))
-		return (void *)p;
-
-	/*
- 	 * We are on the slow-path here so do not use __cache_alloc
- 	 * because it bloats kernel text.
- 	 */
-	ret = kmalloc_track_caller(new_size, flags);
-	if (ret) {
-		memcpy(ret, p, min(new_size, ksize(p)));
-		kfree(p);
-	}
-	return ret;
-}
-EXPORT_SYMBOL(krealloc);
-
-/**
  * kmem_cache_free - Deallocate an object
  * @cachep: The cache the allocation was from.
  * @objp: The previously allocated object.
@@ -3793,7 +3752,7 @@
 	struct kmem_cache *c;
 	unsigned long flags;
 
-	if (unlikely(!objp))
+	if (unlikely(ZERO_OR_NULL_PTR(objp)))
 		return;
 	local_irq_save(flags);
 	kfree_debugcheck(objp);
@@ -4144,26 +4103,17 @@
 static void *s_start(struct seq_file *m, loff_t *pos)
 {
 	loff_t n = *pos;
-	struct list_head *p;
 
 	mutex_lock(&cache_chain_mutex);
 	if (!n)
 		print_slabinfo_header(m);
-	p = cache_chain.next;
-	while (n--) {
-		p = p->next;
-		if (p == &cache_chain)
-			return NULL;
-	}
-	return list_entry(p, struct kmem_cache, next);
+
+	return seq_list_start(&cache_chain, *pos);
 }
 
 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	struct kmem_cache *cachep = p;
-	++*pos;
-	return cachep->next.next == &cache_chain ?
-		NULL : list_entry(cachep->next.next, struct kmem_cache, next);
+	return seq_list_next(p, &cache_chain, pos);
 }
 
 static void s_stop(struct seq_file *m, void *p)
@@ -4173,7 +4123,7 @@
 
 static int s_show(struct seq_file *m, void *p)
 {
-	struct kmem_cache *cachep = p;
+	struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);
 	struct slab *slabp;
 	unsigned long active_objs;
 	unsigned long num_objs;
@@ -4342,17 +4292,8 @@
 
 static void *leaks_start(struct seq_file *m, loff_t *pos)
 {
-	loff_t n = *pos;
-	struct list_head *p;
-
 	mutex_lock(&cache_chain_mutex);
-	p = cache_chain.next;
-	while (n--) {
-		p = p->next;
-		if (p == &cache_chain)
-			return NULL;
-	}
-	return list_entry(p, struct kmem_cache, next);
+	return seq_list_start(&cache_chain, *pos);
 }
 
 static inline int add_caller(unsigned long *n, unsigned long v)
@@ -4403,7 +4344,7 @@
 {
 #ifdef CONFIG_KALLSYMS
 	unsigned long offset, size;
-	char modname[MODULE_NAME_LEN + 1], name[KSYM_NAME_LEN + 1];
+	char modname[MODULE_NAME_LEN], name[KSYM_NAME_LEN];
 
 	if (lookup_symbol_attrs(address, &size, &offset, modname, name) == 0) {
 		seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
@@ -4417,7 +4358,7 @@
 
 static int leaks_show(struct seq_file *m, void *p)
 {
-	struct kmem_cache *cachep = p;
+	struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);
 	struct slab *slabp;
 	struct kmem_list3 *l3;
 	const char *name;
@@ -4498,7 +4439,7 @@
  */
 size_t ksize(const void *objp)
 {
-	if (unlikely(objp == NULL))
+	if (unlikely(ZERO_OR_NULL_PTR(objp)))
 		return 0;
 
 	return obj_size(virt_to_cache(objp));
diff --git a/mm/slob.c b/mm/slob.c
index 71976c5..c89ef11 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -3,57 +3,159 @@
  *
  * Matt Mackall <mpm@selenic.com> 12/30/03
  *
+ * NUMA support by Paul Mundt, 2007.
+ *
  * How SLOB works:
  *
  * The core of SLOB is a traditional K&R style heap allocator, with
  * support for returning aligned objects. The granularity of this
- * allocator is 8 bytes on x86, though it's perhaps possible to reduce
- * this to 4 if it's deemed worth the effort. The slob heap is a
- * singly-linked list of pages from __get_free_page, grown on demand
- * and allocation from the heap is currently first-fit.
+ * allocator is as little as 2 bytes, however typically most architectures
+ * will require 4 bytes on 32-bit and 8 bytes on 64-bit.
+ *
+ * The slob heap is a linked list of pages from alloc_pages(), and
+ * within each page, there is a singly-linked list of free blocks (slob_t).
+ * The heap is grown on demand and allocation from the heap is currently
+ * first-fit.
  *
  * Above this is an implementation of kmalloc/kfree. Blocks returned
- * from kmalloc are 8-byte aligned and prepended with a 8-byte header.
+ * from kmalloc are prepended with a 4-byte header with the kmalloc size.
  * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
- * __get_free_pages directly so that it can return page-aligned blocks
- * and keeps a linked list of such pages and their orders. These
- * objects are detected in kfree() by their page alignment.
+ * alloc_pages() directly, allocating compound pages so the page order
+ * does not have to be separately tracked, and also stores the exact
+ * allocation size in page->private so that it can be used to accurately
+ * provide ksize(). These objects are detected in kfree() because slob_page()
+ * is false for them.
  *
  * SLAB is emulated on top of SLOB by simply calling constructors and
- * destructors for every SLAB allocation. Objects are returned with
- * the 8-byte alignment unless the SLAB_HWCACHE_ALIGN flag is
- * set, in which case the low-level allocator will fragment blocks to
- * create the proper alignment. Again, objects of page-size or greater
- * are allocated by calling __get_free_pages. As SLAB objects know
- * their size, no separate size bookkeeping is necessary and there is
- * essentially no allocation space overhead.
+ * destructors for every SLAB allocation. Objects are returned with the
+ * 4-byte alignment unless the SLAB_HWCACHE_ALIGN flag is set, in which
+ * case the low-level allocator will fragment blocks to create the proper
+ * alignment. Again, objects of page-size or greater are allocated by
+ * calling alloc_pages(). As SLAB objects know their size, no separate
+ * size bookkeeping is necessary and there is essentially no allocation
+ * space overhead, and compound pages aren't needed for multi-page
+ * allocations.
+ *
+ * NUMA support in SLOB is fairly simplistic, pushing most of the real
+ * logic down to the page allocator, and simply doing the node accounting
+ * on the upper levels. In the event that a node id is explicitly
+ * provided, alloc_pages_node() with the specified node id is used
+ * instead. The common case (or when the node id isn't explicitly provided)
+ * will default to the current node, as per numa_node_id().
+ *
+ * Node aware pages are still inserted in to the global freelist, and
+ * these are scanned for by matching against the node id encoded in the
+ * page flags. As a result, block allocations that can be satisfied from
+ * the freelist will only be done so on pages residing on the same node,
+ * in order to prevent random node placement.
  */
 
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/cache.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/timer.h>
 #include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <asm/atomic.h>
+
+/*
+ * slob_block has a field 'units', which indicates size of block if +ve,
+ * or offset of next block if -ve (in SLOB_UNITs).
+ *
+ * Free blocks of size 1 unit simply contain the offset of the next block.
+ * Those with larger size contain their size in the first SLOB_UNIT of
+ * memory, and the offset of the next free block in the second SLOB_UNIT.
+ */
+#if PAGE_SIZE <= (32767 * 2)
+typedef s16 slobidx_t;
+#else
+typedef s32 slobidx_t;
+#endif
 
 struct slob_block {
-	int units;
-	struct slob_block *next;
+	slobidx_t units;
 };
 typedef struct slob_block slob_t;
 
+/*
+ * We use struct page fields to manage some slob allocation aspects,
+ * however to avoid the horrible mess in include/linux/mm_types.h, we'll
+ * just define our own struct page type variant here.
+ */
+struct slob_page {
+	union {
+		struct {
+			unsigned long flags;	/* mandatory */
+			atomic_t _count;	/* mandatory */
+			slobidx_t units;	/* free units left in page */
+			unsigned long pad[2];
+			slob_t *free;		/* first free slob_t in page */
+			struct list_head list;	/* linked list of free pages */
+		};
+		struct page page;
+	};
+};
+static inline void struct_slob_page_wrong_size(void)
+{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); }
+
+/*
+ * free_slob_page: call before a slob_page is returned to the page allocator.
+ */
+static inline void free_slob_page(struct slob_page *sp)
+{
+	reset_page_mapcount(&sp->page);
+	sp->page.mapping = NULL;
+}
+
+/*
+ * All (partially) free slob pages go on this list.
+ */
+static LIST_HEAD(free_slob_pages);
+
+/*
+ * slob_page: True for all slob pages (false for bigblock pages)
+ */
+static inline int slob_page(struct slob_page *sp)
+{
+	return test_bit(PG_active, &sp->flags);
+}
+
+static inline void set_slob_page(struct slob_page *sp)
+{
+	__set_bit(PG_active, &sp->flags);
+}
+
+static inline void clear_slob_page(struct slob_page *sp)
+{
+	__clear_bit(PG_active, &sp->flags);
+}
+
+/*
+ * slob_page_free: true for pages on free_slob_pages list.
+ */
+static inline int slob_page_free(struct slob_page *sp)
+{
+	return test_bit(PG_private, &sp->flags);
+}
+
+static inline void set_slob_page_free(struct slob_page *sp)
+{
+	list_add(&sp->list, &free_slob_pages);
+	__set_bit(PG_private, &sp->flags);
+}
+
+static inline void clear_slob_page_free(struct slob_page *sp)
+{
+	list_del(&sp->list);
+	__clear_bit(PG_private, &sp->flags);
+}
+
 #define SLOB_UNIT sizeof(slob_t)
 #define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT)
 #define SLOB_ALIGN L1_CACHE_BYTES
 
-struct bigblock {
-	int order;
-	void *pages;
-	struct bigblock *next;
-};
-typedef struct bigblock bigblock_t;
-
 /*
  * struct slob_rcu is inserted at the tail of allocated slob blocks, which
  * were created with a SLAB_DESTROY_BY_RCU slab. slob_rcu is used to free
@@ -64,215 +166,321 @@
 	int size;
 };
 
-static slob_t arena = { .next = &arena, .units = 1 };
-static slob_t *slobfree = &arena;
-static bigblock_t *bigblocks;
+/*
+ * slob_lock protects all slob allocator structures.
+ */
 static DEFINE_SPINLOCK(slob_lock);
-static DEFINE_SPINLOCK(block_lock);
 
-static void slob_free(void *b, int size);
-static void slob_timer_cbk(void);
+/*
+ * Encode the given size and next info into a free slob block s.
+ */
+static void set_slob(slob_t *s, slobidx_t size, slob_t *next)
+{
+	slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
+	slobidx_t offset = next - base;
 
+	if (size > 1) {
+		s[0].units = size;
+		s[1].units = offset;
+	} else
+		s[0].units = -offset;
+}
 
-static void *slob_alloc(size_t size, gfp_t gfp, int align)
+/*
+ * Return the size of a slob block.
+ */
+static slobidx_t slob_units(slob_t *s)
+{
+	if (s->units > 0)
+		return s->units;
+	return 1;
+}
+
+/*
+ * Return the next free slob block pointer after this one.
+ */
+static slob_t *slob_next(slob_t *s)
+{
+	slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
+	slobidx_t next;
+
+	if (s[0].units < 0)
+		next = -s[0].units;
+	else
+		next = s[1].units;
+	return base+next;
+}
+
+/*
+ * Returns true if s is the last free block in its page.
+ */
+static int slob_last(slob_t *s)
+{
+	return !((unsigned long)slob_next(s) & ~PAGE_MASK);
+}
+
+static void *slob_new_page(gfp_t gfp, int order, int node)
+{
+	void *page;
+
+#ifdef CONFIG_NUMA
+	if (node != -1)
+		page = alloc_pages_node(node, gfp, order);
+	else
+#endif
+		page = alloc_pages(gfp, order);
+
+	if (!page)
+		return NULL;
+
+	return page_address(page);
+}
+
+/*
+ * Allocate a slob block within a given slob_page sp.
+ */
+static void *slob_page_alloc(struct slob_page *sp, size_t size, int align)
 {
 	slob_t *prev, *cur, *aligned = 0;
 	int delta = 0, units = SLOB_UNITS(size);
-	unsigned long flags;
 
-	spin_lock_irqsave(&slob_lock, flags);
-	prev = slobfree;
-	for (cur = prev->next; ; prev = cur, cur = cur->next) {
+	for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) {
+		slobidx_t avail = slob_units(cur);
+
 		if (align) {
 			aligned = (slob_t *)ALIGN((unsigned long)cur, align);
 			delta = aligned - cur;
 		}
-		if (cur->units >= units + delta) { /* room enough? */
+		if (avail >= units + delta) { /* room enough? */
+			slob_t *next;
+
 			if (delta) { /* need to fragment head to align? */
-				aligned->units = cur->units - delta;
-				aligned->next = cur->next;
-				cur->next = aligned;
-				cur->units = delta;
+				next = slob_next(cur);
+				set_slob(aligned, avail - delta, next);
+				set_slob(cur, delta, aligned);
 				prev = cur;
 				cur = aligned;
+				avail = slob_units(cur);
 			}
 
-			if (cur->units == units) /* exact fit? */
-				prev->next = cur->next; /* unlink */
-			else { /* fragment */
-				prev->next = cur + units;
-				prev->next->units = cur->units - units;
-				prev->next->next = cur->next;
-				cur->units = units;
+			next = slob_next(cur);
+			if (avail == units) { /* exact fit? unlink. */
+				if (prev)
+					set_slob(prev, slob_units(prev), next);
+				else
+					sp->free = next;
+			} else { /* fragment */
+				if (prev)
+					set_slob(prev, slob_units(prev), cur + units);
+				else
+					sp->free = cur + units;
+				set_slob(cur + units, avail - units, next);
 			}
 
-			slobfree = prev;
-			spin_unlock_irqrestore(&slob_lock, flags);
+			sp->units -= units;
+			if (!sp->units)
+				clear_slob_page_free(sp);
 			return cur;
 		}
-		if (cur == slobfree) {
-			spin_unlock_irqrestore(&slob_lock, flags);
-
-			if (size == PAGE_SIZE) /* trying to shrink arena? */
-				return 0;
-
-			cur = (slob_t *)__get_free_page(gfp);
-			if (!cur)
-				return 0;
-
-			slob_free(cur, PAGE_SIZE);
-			spin_lock_irqsave(&slob_lock, flags);
-			cur = slobfree;
-		}
+		if (slob_last(cur))
+			return NULL;
 	}
 }
 
-static void slob_free(void *block, int size)
+/*
+ * slob_alloc: entry point into the slob allocator.
+ */
+static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
 {
-	slob_t *cur, *b = (slob_t *)block;
+	struct slob_page *sp;
+	slob_t *b = NULL;
 	unsigned long flags;
 
-	if (!block)
-		return;
-
-	if (size)
-		b->units = SLOB_UNITS(size);
-
-	/* Find reinsertion point */
 	spin_lock_irqsave(&slob_lock, flags);
-	for (cur = slobfree; !(b > cur && b < cur->next); cur = cur->next)
-		if (cur >= cur->next && (b > cur || b < cur->next))
-			break;
+	/* Iterate through each partially free page, try to find room */
+	list_for_each_entry(sp, &free_slob_pages, list) {
+#ifdef CONFIG_NUMA
+		/*
+		 * If there's a node specification, search for a partial
+		 * page with a matching node id in the freelist.
+		 */
+		if (node != -1 && page_to_nid(&sp->page) != node)
+			continue;
+#endif
 
-	if (b + b->units == cur->next) {
-		b->units += cur->next->units;
-		b->next = cur->next->next;
-	} else
-		b->next = cur->next;
+		if (sp->units >= SLOB_UNITS(size)) {
+			b = slob_page_alloc(sp, size, align);
+			if (b)
+				break;
+		}
+	}
+	spin_unlock_irqrestore(&slob_lock, flags);
 
-	if (cur + cur->units == b) {
-		cur->units += b->units;
-		cur->next = b->next;
-	} else
-		cur->next = b;
+	/* Not enough space: must allocate a new page */
+	if (!b) {
+		b = slob_new_page(gfp, 0, node);
+		if (!b)
+			return 0;
+		sp = (struct slob_page *)virt_to_page(b);
+		set_slob_page(sp);
 
-	slobfree = cur;
+		spin_lock_irqsave(&slob_lock, flags);
+		sp->units = SLOB_UNITS(PAGE_SIZE);
+		sp->free = b;
+		INIT_LIST_HEAD(&sp->list);
+		set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
+		set_slob_page_free(sp);
+		b = slob_page_alloc(sp, size, align);
+		BUG_ON(!b);
+		spin_unlock_irqrestore(&slob_lock, flags);
+	}
+	if (unlikely((gfp & __GFP_ZERO) && b))
+		memset(b, 0, size);
+	return b;
+}
 
+/*
+ * slob_free: entry point into the slob allocator.
+ */
+static void slob_free(void *block, int size)
+{
+	struct slob_page *sp;
+	slob_t *prev, *next, *b = (slob_t *)block;
+	slobidx_t units;
+	unsigned long flags;
+
+	if (ZERO_OR_NULL_PTR(block))
+		return;
+	BUG_ON(!size);
+
+	sp = (struct slob_page *)virt_to_page(block);
+	units = SLOB_UNITS(size);
+
+	spin_lock_irqsave(&slob_lock, flags);
+
+	if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) {
+		/* Go directly to page allocator. Do not pass slob allocator */
+		if (slob_page_free(sp))
+			clear_slob_page_free(sp);
+		clear_slob_page(sp);
+		free_slob_page(sp);
+		free_page((unsigned long)b);
+		goto out;
+	}
+
+	if (!slob_page_free(sp)) {
+		/* This slob page is about to become partially free. Easy! */
+		sp->units = units;
+		sp->free = b;
+		set_slob(b, units,
+			(void *)((unsigned long)(b +
+					SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
+		set_slob_page_free(sp);
+		goto out;
+	}
+
+	/*
+	 * Otherwise the page is already partially free, so find reinsertion
+	 * point.
+	 */
+	sp->units += units;
+
+	if (b < sp->free) {
+		set_slob(b, units, sp->free);
+		sp->free = b;
+	} else {
+		prev = sp->free;
+		next = slob_next(prev);
+		while (b > next) {
+			prev = next;
+			next = slob_next(prev);
+		}
+
+		if (!slob_last(prev) && b + units == next) {
+			units += slob_units(next);
+			set_slob(b, units, slob_next(next));
+		} else
+			set_slob(b, units, next);
+
+		if (prev + slob_units(prev) == b) {
+			units = slob_units(b) + slob_units(prev);
+			set_slob(prev, units, slob_next(b));
+		} else
+			set_slob(prev, slob_units(prev), b);
+	}
+out:
 	spin_unlock_irqrestore(&slob_lock, flags);
 }
 
-void *__kmalloc(size_t size, gfp_t gfp)
-{
-	slob_t *m;
-	bigblock_t *bb;
-	unsigned long flags;
-
-	if (size < PAGE_SIZE - SLOB_UNIT) {
-		m = slob_alloc(size + SLOB_UNIT, gfp, 0);
-		return m ? (void *)(m + 1) : 0;
-	}
-
-	bb = slob_alloc(sizeof(bigblock_t), gfp, 0);
-	if (!bb)
-		return 0;
-
-	bb->order = get_order(size);
-	bb->pages = (void *)__get_free_pages(gfp, bb->order);
-
-	if (bb->pages) {
-		spin_lock_irqsave(&block_lock, flags);
-		bb->next = bigblocks;
-		bigblocks = bb;
-		spin_unlock_irqrestore(&block_lock, flags);
-		return bb->pages;
-	}
-
-	slob_free(bb, sizeof(bigblock_t));
-	return 0;
-}
-EXPORT_SYMBOL(__kmalloc);
-
-/**
- * krealloc - reallocate memory. The contents will remain unchanged.
- *
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
+/*
+ * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend.
  */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
+
+#ifndef ARCH_KMALLOC_MINALIGN
+#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long)
+#endif
+
+#ifndef ARCH_SLAB_MINALIGN
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long)
+#endif
+
+void *__kmalloc_node(size_t size, gfp_t gfp, int node)
 {
-	void *ret;
+	unsigned int *m;
+	int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
 
-	if (unlikely(!p))
-		return kmalloc_track_caller(new_size, flags);
+	if (size < PAGE_SIZE - align) {
+		if (!size)
+			return ZERO_SIZE_PTR;
 
-	if (unlikely(!new_size)) {
-		kfree(p);
-		return NULL;
+		m = slob_alloc(size + align, gfp, align, node);
+		if (m)
+			*m = size;
+		return (void *)m + align;
+	} else {
+		void *ret;
+
+		ret = slob_new_page(gfp | __GFP_COMP, get_order(size), node);
+		if (ret) {
+			struct page *page;
+			page = virt_to_page(ret);
+			page->private = size;
+		}
+		return ret;
 	}
-
-	ret = kmalloc_track_caller(new_size, flags);
-	if (ret) {
-		memcpy(ret, p, min(new_size, ksize(p)));
-		kfree(p);
-	}
-	return ret;
 }
-EXPORT_SYMBOL(krealloc);
+EXPORT_SYMBOL(__kmalloc_node);
 
 void kfree(const void *block)
 {
-	bigblock_t *bb, **last = &bigblocks;
-	unsigned long flags;
+	struct slob_page *sp;
 
-	if (!block)
+	if (ZERO_OR_NULL_PTR(block))
 		return;
 
-	if (!((unsigned long)block & (PAGE_SIZE-1))) {
-		/* might be on the big block list */
-		spin_lock_irqsave(&block_lock, flags);
-		for (bb = bigblocks; bb; last = &bb->next, bb = bb->next) {
-			if (bb->pages == block) {
-				*last = bb->next;
-				spin_unlock_irqrestore(&block_lock, flags);
-				free_pages((unsigned long)block, bb->order);
-				slob_free(bb, sizeof(bigblock_t));
-				return;
-			}
-		}
-		spin_unlock_irqrestore(&block_lock, flags);
-	}
-
-	slob_free((slob_t *)block - 1, 0);
-	return;
+	sp = (struct slob_page *)virt_to_page(block);
+	if (slob_page(sp)) {
+		int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+		unsigned int *m = (unsigned int *)(block - align);
+		slob_free(m, *m + align);
+	} else
+		put_page(&sp->page);
 }
-
 EXPORT_SYMBOL(kfree);
 
+/* can't use ksize for kmem_cache_alloc memory, only kmalloc */
 size_t ksize(const void *block)
 {
-	bigblock_t *bb;
-	unsigned long flags;
+	struct slob_page *sp;
 
-	if (!block)
+	if (ZERO_OR_NULL_PTR(block))
 		return 0;
 
-	if (!((unsigned long)block & (PAGE_SIZE-1))) {
-		spin_lock_irqsave(&block_lock, flags);
-		for (bb = bigblocks; bb; bb = bb->next)
-			if (bb->pages == block) {
-				spin_unlock_irqrestore(&slob_lock, flags);
-				return PAGE_SIZE << bb->order;
-			}
-		spin_unlock_irqrestore(&block_lock, flags);
-	}
-
-	return ((slob_t *)block - 1)->units * SLOB_UNIT;
+	sp = (struct slob_page *)virt_to_page(block);
+	if (slob_page(sp))
+		return ((slob_t *)block - 1)->units + SLOB_UNIT;
+	else
+		return sp->page.private;
 }
 
 struct kmem_cache {
@@ -289,7 +497,7 @@
 {
 	struct kmem_cache *c;
 
-	c = slob_alloc(sizeof(struct kmem_cache), flags, 0);
+	c = slob_alloc(sizeof(struct kmem_cache), flags, 0, -1);
 
 	if (c) {
 		c->name = name;
@@ -302,6 +510,8 @@
 		c->ctor = ctor;
 		/* ignore alignment unless it's forced */
 		c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
+		if (c->align < ARCH_SLAB_MINALIGN)
+			c->align = ARCH_SLAB_MINALIGN;
 		if (c->align < align)
 			c->align = align;
 	} else if (flags & SLAB_PANIC)
@@ -317,31 +527,21 @@
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
-void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags)
+void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
 {
 	void *b;
 
 	if (c->size < PAGE_SIZE)
-		b = slob_alloc(c->size, flags, c->align);
+		b = slob_alloc(c->size, flags, c->align, node);
 	else
-		b = (void *)__get_free_pages(flags, get_order(c->size));
+		b = slob_new_page(flags, get_order(c->size), node);
 
 	if (c->ctor)
 		c->ctor(b, c, 0);
 
 	return b;
 }
-EXPORT_SYMBOL(kmem_cache_alloc);
-
-void *kmem_cache_zalloc(struct kmem_cache *c, gfp_t flags)
-{
-	void *ret = kmem_cache_alloc(c, flags);
-	if (ret)
-		memset(ret, 0, c->size);
-
-	return ret;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
+EXPORT_SYMBOL(kmem_cache_alloc_node);
 
 static void __kmem_cache_free(void *b, int size)
 {
@@ -385,9 +585,6 @@
 }
 EXPORT_SYMBOL(kmem_cache_name);
 
-static struct timer_list slob_timer = TIMER_INITIALIZER(
-	(void (*)(unsigned long))slob_timer_cbk, 0, 0);
-
 int kmem_cache_shrink(struct kmem_cache *d)
 {
 	return 0;
@@ -399,17 +596,14 @@
 	return 0;
 }
 
-void __init kmem_cache_init(void)
+static unsigned int slob_ready __read_mostly;
+
+int slab_is_available(void)
 {
-	slob_timer_cbk();
+	return slob_ready;
 }
 
-static void slob_timer_cbk(void)
+void __init kmem_cache_init(void)
 {
-	void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
-
-	if (p)
-		free_page((unsigned long)p);
-
-	mod_timer(&slob_timer, jiffies + HZ);
+	slob_ready = 1;
 }
diff --git a/mm/slub.c b/mm/slub.c
index 98801d4..52a4f44 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -205,6 +205,11 @@
 #define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
 #endif
 
+/*
+ * The page->inuse field is 16 bit thus we have this limitation
+ */
+#define MAX_OBJECTS_PER_SLAB 65535
+
 /* Internal SLUB flags */
 #define __OBJECT_POISON 0x80000000	/* Poison object */
 
@@ -228,7 +233,7 @@
 
 /* A list of all slab caches on the system */
 static DECLARE_RWSEM(slub_lock);
-LIST_HEAD(slab_caches);
+static LIST_HEAD(slab_caches);
 
 /*
  * Tracking user of a slab.
@@ -247,9 +252,10 @@
 static int sysfs_slab_alias(struct kmem_cache *, const char *);
 static void sysfs_slab_remove(struct kmem_cache *);
 #else
-static int sysfs_slab_add(struct kmem_cache *s) { return 0; }
-static int sysfs_slab_alias(struct kmem_cache *s, const char *p) { return 0; }
-static void sysfs_slab_remove(struct kmem_cache *s) {}
+static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
+static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
+							{ return 0; }
+static inline void sysfs_slab_remove(struct kmem_cache *s) {}
 #endif
 
 /********************************************************************
@@ -323,7 +329,11 @@
 /*
  * Debug settings:
  */
+#ifdef CONFIG_SLUB_DEBUG_ON
+static int slub_debug = DEBUG_DEFAULT_FLAGS;
+#else
 static int slub_debug;
+#endif
 
 static char *slub_debug_slabs;
 
@@ -340,7 +350,7 @@
 
 	for (i = 0; i < length; i++) {
 		if (newline) {
-			printk(KERN_ERR "%10s 0x%p: ", text, addr + i);
+			printk(KERN_ERR "%8s 0x%p: ", text, addr + i);
 			newline = 0;
 		}
 		printk(" %02x", addr[i]);
@@ -397,10 +407,11 @@
 
 static void init_tracking(struct kmem_cache *s, void *object)
 {
-	if (s->flags & SLAB_STORE_USER) {
-		set_track(s, object, TRACK_FREE, NULL);
-		set_track(s, object, TRACK_ALLOC, NULL);
-	}
+	if (!(s->flags & SLAB_STORE_USER))
+		return;
+
+	set_track(s, object, TRACK_FREE, NULL);
+	set_track(s, object, TRACK_ALLOC, NULL);
 }
 
 static void print_track(const char *s, struct track *t)
@@ -408,65 +419,106 @@
 	if (!t->addr)
 		return;
 
-	printk(KERN_ERR "%s: ", s);
+	printk(KERN_ERR "INFO: %s in ", s);
 	__print_symbol("%s", (unsigned long)t->addr);
-	printk(" jiffies_ago=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
+	printk(" age=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
 }
 
-static void print_trailer(struct kmem_cache *s, u8 *p)
+static void print_tracking(struct kmem_cache *s, void *object)
+{
+	if (!(s->flags & SLAB_STORE_USER))
+		return;
+
+	print_track("Allocated", get_track(s, object, TRACK_ALLOC));
+	print_track("Freed", get_track(s, object, TRACK_FREE));
+}
+
+static void print_page_info(struct page *page)
+{
+	printk(KERN_ERR "INFO: Slab 0x%p used=%u fp=0x%p flags=0x%04lx\n",
+		page, page->inuse, page->freelist, page->flags);
+
+}
+
+static void slab_bug(struct kmem_cache *s, char *fmt, ...)
+{
+	va_list args;
+	char buf[100];
+
+	va_start(args, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	printk(KERN_ERR "========================================"
+			"=====================================\n");
+	printk(KERN_ERR "BUG %s: %s\n", s->name, buf);
+	printk(KERN_ERR "----------------------------------------"
+			"-------------------------------------\n\n");
+}
+
+static void slab_fix(struct kmem_cache *s, char *fmt, ...)
+{
+	va_list args;
+	char buf[100];
+
+	va_start(args, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	printk(KERN_ERR "FIX %s: %s\n", s->name, buf);
+}
+
+static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
 {
 	unsigned int off;	/* Offset of last byte */
+	u8 *addr = page_address(page);
+
+	print_tracking(s, p);
+
+	print_page_info(page);
+
+	printk(KERN_ERR "INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
+			p, p - addr, get_freepointer(s, p));
+
+	if (p > addr + 16)
+		print_section("Bytes b4", p - 16, 16);
+
+	print_section("Object", p, min(s->objsize, 128));
 
 	if (s->flags & SLAB_RED_ZONE)
 		print_section("Redzone", p + s->objsize,
 			s->inuse - s->objsize);
 
-	printk(KERN_ERR "FreePointer 0x%p -> 0x%p\n",
-			p + s->offset,
-			get_freepointer(s, p));
-
 	if (s->offset)
 		off = s->offset + sizeof(void *);
 	else
 		off = s->inuse;
 
-	if (s->flags & SLAB_STORE_USER) {
-		print_track("Last alloc", get_track(s, p, TRACK_ALLOC));
-		print_track("Last free ", get_track(s, p, TRACK_FREE));
+	if (s->flags & SLAB_STORE_USER)
 		off += 2 * sizeof(struct track);
-	}
 
 	if (off != s->size)
 		/* Beginning of the filler is the free pointer */
-		print_section("Filler", p + off, s->size - off);
+		print_section("Padding", p + off, s->size - off);
+
+	dump_stack();
 }
 
 static void object_err(struct kmem_cache *s, struct page *page,
 			u8 *object, char *reason)
 {
-	u8 *addr = page_address(page);
-
-	printk(KERN_ERR "*** SLUB %s: %s@0x%p slab 0x%p\n",
-			s->name, reason, object, page);
-	printk(KERN_ERR "    offset=%tu flags=0x%04lx inuse=%u freelist=0x%p\n",
-		object - addr, page->flags, page->inuse, page->freelist);
-	if (object > addr + 16)
-		print_section("Bytes b4", object - 16, 16);
-	print_section("Object", object, min(s->objsize, 128));
-	print_trailer(s, object);
-	dump_stack();
+	slab_bug(s, reason);
+	print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page, char *reason, ...)
+static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
 {
 	va_list args;
 	char buf[100];
 
-	va_start(args, reason);
-	vsnprintf(buf, sizeof(buf), reason, args);
+	va_start(args, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
-	printk(KERN_ERR "*** SLUB %s: %s in slab @0x%p\n", s->name, buf,
-		page);
+	slab_bug(s, fmt);
+	print_page_info(page);
 	dump_stack();
 }
 
@@ -485,15 +537,46 @@
 			s->inuse - s->objsize);
 }
 
-static int check_bytes(u8 *start, unsigned int value, unsigned int bytes)
+static u8 *check_bytes(u8 *start, unsigned int value, unsigned int bytes)
 {
 	while (bytes) {
 		if (*start != (u8)value)
-			return 0;
+			return start;
 		start++;
 		bytes--;
 	}
-	return 1;
+	return NULL;
+}
+
+static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
+						void *from, void *to)
+{
+	slab_fix(s, "Restoring 0x%p-0x%p=0x%x\n", from, to - 1, data);
+	memset(from, data, to - from);
+}
+
+static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
+			u8 *object, char *what,
+			u8* start, unsigned int value, unsigned int bytes)
+{
+	u8 *fault;
+	u8 *end;
+
+	fault = check_bytes(start, value, bytes);
+	if (!fault)
+		return 1;
+
+	end = start + bytes;
+	while (end > fault && end[-1] == value)
+		end--;
+
+	slab_bug(s, "%s overwritten", what);
+	printk(KERN_ERR "INFO: 0x%p-0x%p. First byte 0x%x instead of 0x%x\n",
+					fault, end - 1, fault[0], value);
+	print_trailer(s, page, object);
+
+	restore_bytes(s, what, value, fault, end);
+	return 0;
 }
 
 /*
@@ -534,14 +617,6 @@
  * may be used with merged slabcaches.
  */
 
-static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
-						void *from, void *to)
-{
-	printk(KERN_ERR "@@@ SLUB %s: Restoring %s (0x%x) from 0x%p-0x%p\n",
-		s->name, message, data, from, to - 1);
-	memset(from, data, to - from);
-}
-
 static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
 {
 	unsigned long off = s->inuse;	/* The end of info */
@@ -557,39 +632,39 @@
 	if (s->size == off)
 		return 1;
 
-	if (check_bytes(p + off, POISON_INUSE, s->size - off))
-		return 1;
-
-	object_err(s, page, p, "Object padding check fails");
-
-	/*
-	 * Restore padding
-	 */
-	restore_bytes(s, "object padding", POISON_INUSE, p + off, p + s->size);
-	return 0;
+	return check_bytes_and_report(s, page, p, "Object padding",
+				p + off, POISON_INUSE, s->size - off);
 }
 
 static int slab_pad_check(struct kmem_cache *s, struct page *page)
 {
-	u8 *p;
-	int length, remainder;
+	u8 *start;
+	u8 *fault;
+	u8 *end;
+	int length;
+	int remainder;
 
 	if (!(s->flags & SLAB_POISON))
 		return 1;
 
-	p = page_address(page);
+	start = page_address(page);
+	end = start + (PAGE_SIZE << s->order);
 	length = s->objects * s->size;
-	remainder = (PAGE_SIZE << s->order) - length;
+	remainder = end - (start + length);
 	if (!remainder)
 		return 1;
 
-	if (!check_bytes(p + length, POISON_INUSE, remainder)) {
-		slab_err(s, page, "Padding check failed");
-		restore_bytes(s, "slab padding", POISON_INUSE, p + length,
-			p + length + remainder);
-		return 0;
-	}
-	return 1;
+	fault = check_bytes(start + length, POISON_INUSE, remainder);
+	if (!fault)
+		return 1;
+	while (end > fault && end[-1] == POISON_INUSE)
+		end--;
+
+	slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1);
+	print_section("Padding", start, length);
+
+	restore_bytes(s, "slab padding", POISON_INUSE, start, end);
+	return 0;
 }
 
 static int check_object(struct kmem_cache *s, struct page *page,
@@ -602,41 +677,22 @@
 		unsigned int red =
 			active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE;
 
-		if (!check_bytes(endobject, red, s->inuse - s->objsize)) {
-			object_err(s, page, object,
-			active ? "Redzone Active" : "Redzone Inactive");
-			restore_bytes(s, "redzone", red,
-				endobject, object + s->inuse);
+		if (!check_bytes_and_report(s, page, object, "Redzone",
+			endobject, red, s->inuse - s->objsize))
 			return 0;
-		}
 	} else {
-		if ((s->flags & SLAB_POISON) && s->objsize < s->inuse &&
-			!check_bytes(endobject, POISON_INUSE,
-					s->inuse - s->objsize)) {
-		object_err(s, page, p, "Alignment padding check fails");
-		/*
-		 * Fix it so that there will not be another report.
-		 *
-		 * Hmmm... We may be corrupting an object that now expects
-		 * to be longer than allowed.
-		 */
-		restore_bytes(s, "alignment padding", POISON_INUSE,
-			endobject, object + s->inuse);
-		}
+		if ((s->flags & SLAB_POISON) && s->objsize < s->inuse)
+			check_bytes_and_report(s, page, p, "Alignment padding", endobject,
+				POISON_INUSE, s->inuse - s->objsize);
 	}
 
 	if (s->flags & SLAB_POISON) {
 		if (!active && (s->flags & __OBJECT_POISON) &&
-			(!check_bytes(p, POISON_FREE, s->objsize - 1) ||
-				p[s->objsize - 1] != POISON_END)) {
-
-			object_err(s, page, p, "Poison check failed");
-			restore_bytes(s, "Poison", POISON_FREE,
-						p, p + s->objsize -1);
-			restore_bytes(s, "Poison", POISON_END,
-					p + s->objsize - 1, p + s->objsize);
+			(!check_bytes_and_report(s, page, p, "Poison", p,
+					POISON_FREE, s->objsize - 1) ||
+			 !check_bytes_and_report(s, page, p, "Poison",
+			 	p + s->objsize -1, POISON_END, 1)))
 			return 0;
-		}
 		/*
 		 * check_pad_bytes cleans up on its own.
 		 */
@@ -669,25 +725,17 @@
 	VM_BUG_ON(!irqs_disabled());
 
 	if (!PageSlab(page)) {
-		slab_err(s, page, "Not a valid slab page flags=%lx "
-			"mapping=0x%p count=%d", page->flags, page->mapping,
-			page_count(page));
+		slab_err(s, page, "Not a valid slab page");
 		return 0;
 	}
 	if (page->offset * sizeof(void *) != s->offset) {
-		slab_err(s, page, "Corrupted offset %lu flags=0x%lx "
-			"mapping=0x%p count=%d",
-			(unsigned long)(page->offset * sizeof(void *)),
-			page->flags,
-			page->mapping,
-			page_count(page));
+		slab_err(s, page, "Corrupted offset %lu",
+			(unsigned long)(page->offset * sizeof(void *)));
 		return 0;
 	}
 	if (page->inuse > s->objects) {
-		slab_err(s, page, "inuse %u > max %u @0x%p flags=%lx "
-			"mapping=0x%p count=%d",
-			s->name, page->inuse, s->objects, page->flags,
-			page->mapping, page_count(page));
+		slab_err(s, page, "inuse %u > max %u",
+			s->name, page->inuse, s->objects);
 		return 0;
 	}
 	/* Slab_pad_check fixes things up after itself */
@@ -715,13 +763,10 @@
 				set_freepointer(s, object, NULL);
 				break;
 			} else {
-				slab_err(s, page, "Freepointer 0x%p corrupt",
-									fp);
+				slab_err(s, page, "Freepointer corrupt");
 				page->freelist = NULL;
 				page->inuse = s->objects;
-				printk(KERN_ERR "@@@ SLUB %s: Freelist "
-					"cleared. Slab 0x%p\n",
-					s->name, page);
+				slab_fix(s, "Freelist cleared");
 				return 0;
 			}
 			break;
@@ -733,11 +778,9 @@
 
 	if (page->inuse != s->objects - nr) {
 		slab_err(s, page, "Wrong object count. Counter is %d but "
-			"counted were %d", s, page, page->inuse,
-							s->objects - nr);
+			"counted were %d", page->inuse, s->objects - nr);
 		page->inuse = s->objects - nr;
-		printk(KERN_ERR "@@@ SLUB %s: Object count adjusted. "
-			"Slab @0x%p\n", s->name, page);
+		slab_fix(s, "Object count adjusted.");
 	}
 	return search == NULL;
 }
@@ -799,7 +842,7 @@
 		goto bad;
 
 	if (object && !on_freelist(s, page, object)) {
-		slab_err(s, page, "Object 0x%p already allocated", object);
+		object_err(s, page, object, "Object already allocated");
 		goto bad;
 	}
 
@@ -825,8 +868,7 @@
 		 * to avoid issues in the future. Marking all objects
 		 * as used avoids touching the remaining objects.
 		 */
-		printk(KERN_ERR "@@@ SLUB: %s slab 0x%p. Marking all objects used.\n",
-			s->name, page);
+		slab_fix(s, "Marking all objects used");
 		page->inuse = s->objects;
 		page->freelist = NULL;
 		/* Fix up fields that may be corrupted */
@@ -847,7 +889,7 @@
 	}
 
 	if (on_freelist(s, page, object)) {
-		slab_err(s, page, "Object 0x%p already free", object);
+		object_err(s, page, object, "Object already free");
 		goto fail;
 	}
 
@@ -866,8 +908,8 @@
 			dump_stack();
 		}
 		else
-			slab_err(s, page, "object at 0x%p belongs "
-				"to slab %s", object, page->slab->name);
+			object_err(s, page, object,
+					"page slab pointer corrupt.");
 		goto fail;
 	}
 
@@ -881,45 +923,63 @@
 	return 1;
 
 fail:
-	printk(KERN_ERR "@@@ SLUB: %s slab 0x%p object at 0x%p not freed.\n",
-		s->name, page, object);
+	slab_fix(s, "Object at 0x%p not freed", object);
 	return 0;
 }
 
 static int __init setup_slub_debug(char *str)
 {
-	if (!str || *str != '=')
-		slub_debug = DEBUG_DEFAULT_FLAGS;
-	else {
-		str++;
-		if (*str == 0 || *str == ',')
-			slub_debug = DEBUG_DEFAULT_FLAGS;
-		else
-		for( ;*str && *str != ','; str++)
-			switch (*str) {
-			case 'f' : case 'F' :
-				slub_debug |= SLAB_DEBUG_FREE;
-				break;
-			case 'z' : case 'Z' :
-				slub_debug |= SLAB_RED_ZONE;
-				break;
-			case 'p' : case 'P' :
-				slub_debug |= SLAB_POISON;
-				break;
-			case 'u' : case 'U' :
-				slub_debug |= SLAB_STORE_USER;
-				break;
-			case 't' : case 'T' :
-				slub_debug |= SLAB_TRACE;
-				break;
-			default:
-				printk(KERN_ERR "slub_debug option '%c' "
-					"unknown. skipped\n",*str);
-			}
-	}
+	slub_debug = DEBUG_DEFAULT_FLAGS;
+	if (*str++ != '=' || !*str)
+		/*
+		 * No options specified. Switch on full debugging.
+		 */
+		goto out;
 
 	if (*str == ',')
+		/*
+		 * No options but restriction on slabs. This means full
+		 * debugging for slabs matching a pattern.
+		 */
+		goto check_slabs;
+
+	slub_debug = 0;
+	if (*str == '-')
+		/*
+		 * Switch off all debugging measures.
+		 */
+		goto out;
+
+	/*
+	 * Determine which debug features should be switched on
+	 */
+	for ( ;*str && *str != ','; str++) {
+		switch (tolower(*str)) {
+		case 'f':
+			slub_debug |= SLAB_DEBUG_FREE;
+			break;
+		case 'z':
+			slub_debug |= SLAB_RED_ZONE;
+			break;
+		case 'p':
+			slub_debug |= SLAB_POISON;
+			break;
+		case 'u':
+			slub_debug |= SLAB_STORE_USER;
+			break;
+		case 't':
+			slub_debug |= SLAB_TRACE;
+			break;
+		default:
+			printk(KERN_ERR "slub_debug option '%c' "
+				"unknown. skipped\n",*str);
+		}
+	}
+
+check_slabs:
+	if (*str == ',')
 		slub_debug_slabs = str + 1;
+out:
 	return 1;
 }
 
@@ -939,7 +999,7 @@
 	 * Debugging or ctor may create a need to move the free
 	 * pointer. Fail if this happens.
 	 */
-	if (s->size >= 65535 * sizeof(void *)) {
+	if (s->objsize >= 65535 * sizeof(void *)) {
 		BUG_ON(s->flags & (SLAB_RED_ZONE | SLAB_POISON |
 				SLAB_STORE_USER | SLAB_DESTROY_BY_RCU));
 		BUG_ON(s->ctor);
@@ -1018,7 +1078,7 @@
 	void *last;
 	void *p;
 
-	BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK));
+	BUG_ON(flags & ~(GFP_DMA | __GFP_ZERO | GFP_LEVEL_MASK));
 
 	if (flags & __GFP_WAIT)
 		local_irq_enable();
@@ -1336,7 +1396,7 @@
 	unfreeze_slab(s, page);
 }
 
-static void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
+static inline void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
 {
 	slab_lock(page);
 	deactivate_slab(s, page, cpu);
@@ -1346,7 +1406,7 @@
  * Flush cpu slab.
  * Called from IPI handler with interrupts disabled.
  */
-static void __flush_cpu_slab(struct kmem_cache *s, int cpu)
+static inline void __flush_cpu_slab(struct kmem_cache *s, int cpu)
 {
 	struct page *page = s->cpu_slab[cpu];
 
@@ -1481,7 +1541,7 @@
  * Otherwise we can simply pick the next object from the lockless free list.
  */
 static void __always_inline *slab_alloc(struct kmem_cache *s,
-				gfp_t gfpflags, int node, void *addr)
+		gfp_t gfpflags, int node, void *addr)
 {
 	struct page *page;
 	void **object;
@@ -1499,6 +1559,10 @@
 		page->lockless_freelist = object[page->offset];
 	}
 	local_irq_restore(flags);
+
+	if (unlikely((gfpflags & __GFP_ZERO) && object))
+		memset(object, 0, s->objsize);
+
 	return object;
 }
 
@@ -1682,8 +1746,17 @@
 {
 	int order;
 	int rem;
+	int min_order = slub_min_order;
 
-	for (order = max(slub_min_order,
+	/*
+	 * If we would create too many object per slab then reduce
+	 * the slab order even if it goes below slub_min_order.
+	 */
+	while (min_order > 0 &&
+		(PAGE_SIZE << min_order) >= MAX_OBJECTS_PER_SLAB * size)
+			min_order--;
+
+	for (order = max(min_order,
 				fls(min_objects * size - 1) - PAGE_SHIFT);
 			order <= max_order; order++) {
 
@@ -1697,6 +1770,9 @@
 		if (rem <= slab_size / fract_leftover)
 			break;
 
+		/* If the next size is too high then exit now */
+		if (slab_size * 2 >= MAX_OBJECTS_PER_SLAB * size)
+			break;
 	}
 
 	return order;
@@ -1777,7 +1853,9 @@
 	atomic_long_set(&n->nr_slabs, 0);
 	spin_lock_init(&n->list_lock);
 	INIT_LIST_HEAD(&n->partial);
+#ifdef CONFIG_SLUB_DEBUG
 	INIT_LIST_HEAD(&n->full);
+#endif
 }
 
 #ifdef CONFIG_NUMA
@@ -1798,8 +1876,6 @@
 	BUG_ON(kmalloc_caches->size < sizeof(struct kmem_cache_node));
 
 	page = new_slab(kmalloc_caches, gfpflags | GFP_THISNODE, node);
-	/* new_slab() disables interupts */
-	local_irq_enable();
 
 	BUG_ON(!page);
 	n = page->freelist;
@@ -1807,10 +1883,19 @@
 	page->freelist = get_freepointer(kmalloc_caches, n);
 	page->inuse++;
 	kmalloc_caches->node[node] = n;
-	setup_object_debug(kmalloc_caches, page, n);
+#ifdef CONFIG_SLUB_DEBUG
+	init_object(kmalloc_caches, n, 1);
+	init_tracking(kmalloc_caches, n);
+#endif
 	init_kmem_cache_node(n);
 	atomic_long_inc(&n->nr_slabs);
 	add_partial(n, page);
+
+	/*
+	 * new_slab() disables interupts. If we do not reenable interrupts here
+	 * then bootup would continue with interrupts disabled.
+	 */
+	local_irq_enable();
 	return n;
 }
 
@@ -1917,7 +2002,6 @@
 	 */
 	s->inuse = size;
 
-#ifdef CONFIG_SLUB_DEBUG
 	if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) ||
 		s->ctor)) {
 		/*
@@ -1932,6 +2016,7 @@
 		size += sizeof(void *);
 	}
 
+#ifdef CONFIG_SLUB_DEBUG
 	if (flags & SLAB_STORE_USER)
 		/*
 		 * Need to store information about allocs and frees after
@@ -1979,7 +2064,7 @@
 	 * The page->inuse field is only 16 bit wide! So we cannot have
 	 * more than 64k objects per slab.
 	 */
-	if (!s->objects || s->objects > 65535)
+	if (!s->objects || s->objects > MAX_OBJECTS_PER_SLAB)
 		return 0;
 	return 1;
 
@@ -2016,7 +2101,6 @@
 			s->offset, flags);
 	return 0;
 }
-EXPORT_SYMBOL(kmem_cache_open);
 
 /*
  * Check if a given pointer is valid
@@ -2084,7 +2168,7 @@
 /*
  * Release all resources used by a slab cache.
  */
-static int kmem_cache_close(struct kmem_cache *s)
+static inline int kmem_cache_close(struct kmem_cache *s)
 {
 	int node;
 
@@ -2112,12 +2196,13 @@
 	s->refcount--;
 	if (!s->refcount) {
 		list_del(&s->list);
+		up_write(&slub_lock);
 		if (kmem_cache_close(s))
 			WARN_ON(1);
 		sysfs_slab_remove(s);
 		kfree(s);
-	}
-	up_write(&slub_lock);
+	} else
+		up_write(&slub_lock);
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
@@ -2190,47 +2275,92 @@
 	panic("Creation of kmalloc slab %s size=%d failed.\n", name, size);
 }
 
-static struct kmem_cache *get_slab(size_t size, gfp_t flags)
-{
-	int index = kmalloc_index(size);
-
-	if (!index)
-		return NULL;
-
-	/* Allocation too large? */
-	BUG_ON(index < 0);
-
 #ifdef CONFIG_ZONE_DMA
-	if ((flags & SLUB_DMA)) {
-		struct kmem_cache *s;
-		struct kmem_cache *x;
-		char *text;
-		size_t realsize;
+static noinline struct kmem_cache *dma_kmalloc_cache(int index, gfp_t flags)
+{
+	struct kmem_cache *s;
+	struct kmem_cache *x;
+	char *text;
+	size_t realsize;
 
-		s = kmalloc_caches_dma[index];
-		if (s)
-			return s;
+	s = kmalloc_caches_dma[index];
+	if (s)
+		return s;
 
-		/* Dynamically create dma cache */
-		x = kmalloc(kmem_size, flags & ~SLUB_DMA);
-		if (!x)
-			panic("Unable to allocate memory for dma cache\n");
+	/* Dynamically create dma cache */
+	x = kmalloc(kmem_size, flags & ~SLUB_DMA);
+	if (!x)
+		panic("Unable to allocate memory for dma cache\n");
 
-		if (index <= KMALLOC_SHIFT_HIGH)
-			realsize = 1 << index;
-		else {
-			if (index == 1)
-				realsize = 96;
-			else
-				realsize = 192;
-		}
-
-		text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
-				(unsigned int)realsize);
-		s = create_kmalloc_cache(x, text, realsize, flags);
+	realsize = kmalloc_caches[index].objsize;
+	text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
+			(unsigned int)realsize);
+	s = create_kmalloc_cache(x, text, realsize, flags);
+	down_write(&slub_lock);
+	if (!kmalloc_caches_dma[index]) {
 		kmalloc_caches_dma[index] = s;
+		up_write(&slub_lock);
 		return s;
 	}
+	up_write(&slub_lock);
+	kmem_cache_destroy(s);
+	return kmalloc_caches_dma[index];
+}
+#endif
+
+/*
+ * Conversion table for small slabs sizes / 8 to the index in the
+ * kmalloc array. This is necessary for slabs < 192 since we have non power
+ * of two cache sizes there. The size of larger slabs can be determined using
+ * fls.
+ */
+static s8 size_index[24] = {
+	3,	/* 8 */
+	4,	/* 16 */
+	5,	/* 24 */
+	5,	/* 32 */
+	6,	/* 40 */
+	6,	/* 48 */
+	6,	/* 56 */
+	6,	/* 64 */
+	1,	/* 72 */
+	1,	/* 80 */
+	1,	/* 88 */
+	1,	/* 96 */
+	7,	/* 104 */
+	7,	/* 112 */
+	7,	/* 120 */
+	7,	/* 128 */
+	2,	/* 136 */
+	2,	/* 144 */
+	2,	/* 152 */
+	2,	/* 160 */
+	2,	/* 168 */
+	2,	/* 176 */
+	2,	/* 184 */
+	2	/* 192 */
+};
+
+static struct kmem_cache *get_slab(size_t size, gfp_t flags)
+{
+	int index;
+
+	if (size <= 192) {
+		if (!size)
+			return ZERO_SIZE_PTR;
+
+		index = size_index[(size - 1) / 8];
+	} else {
+		if (size > KMALLOC_MAX_SIZE)
+			return NULL;
+
+		index = fls(size - 1);
+	}
+
+#ifdef CONFIG_ZONE_DMA
+	if (unlikely((flags & SLUB_DMA)))
+		return dma_kmalloc_cache(index, flags);
+
 #endif
 	return &kmalloc_caches[index];
 }
@@ -2239,9 +2369,10 @@
 {
 	struct kmem_cache *s = get_slab(size, flags);
 
-	if (s)
-		return slab_alloc(s, flags, -1, __builtin_return_address(0));
-	return NULL;
+	if (ZERO_OR_NULL_PTR(s))
+		return s;
+
+	return slab_alloc(s, flags, -1, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(__kmalloc);
 
@@ -2250,18 +2381,23 @@
 {
 	struct kmem_cache *s = get_slab(size, flags);
 
-	if (s)
-		return slab_alloc(s, flags, node, __builtin_return_address(0));
-	return NULL;
+	if (ZERO_OR_NULL_PTR(s))
+		return s;
+
+	return slab_alloc(s, flags, node, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(__kmalloc_node);
 #endif
 
 size_t ksize(const void *object)
 {
-	struct page *page = get_object_page(object);
+	struct page *page;
 	struct kmem_cache *s;
 
+	if (object == ZERO_SIZE_PTR)
+		return 0;
+
+	page = get_object_page(object);
 	BUG_ON(!page);
 	s = page->slab;
 	BUG_ON(!s);
@@ -2293,7 +2429,13 @@
 	struct kmem_cache *s;
 	struct page *page;
 
-	if (!x)
+	/*
+	 * This has to be an unsigned comparison. According to Linus
+	 * some gcc version treat a pointer as a signed entity. Then
+	 * this comparison would be true for all "negative" pointers
+	 * (which would cover the whole upper half of the address space).
+	 */
+	if (ZERO_OR_NULL_PTR(x))
 		return;
 
 	page = virt_to_head_page(x);
@@ -2382,43 +2524,6 @@
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
-/**
- * krealloc - reallocate memory. The contents will remain unchanged.
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
- */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
-{
-	void *ret;
-	size_t ks;
-
-	if (unlikely(!p))
-		return kmalloc(new_size, flags);
-
-	if (unlikely(!new_size)) {
-		kfree(p);
-		return NULL;
-	}
-
-	ks = ksize(p);
-	if (ks >= new_size)
-		return (void *)p;
-
-	ret = kmalloc(new_size, flags);
-	if (ret) {
-		memcpy(ret, p, min(new_size, ks));
-		kfree(p);
-	}
-	return ret;
-}
-EXPORT_SYMBOL(krealloc);
-
 /********************************************************************
  *			Basic setup of slabs
  *******************************************************************/
@@ -2426,6 +2531,7 @@
 void __init kmem_cache_init(void)
 {
 	int i;
+	int caches = 0;
 
 #ifdef CONFIG_NUMA
 	/*
@@ -2435,20 +2541,48 @@
 	 */
 	create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node",
 		sizeof(struct kmem_cache_node), GFP_KERNEL);
+	kmalloc_caches[0].refcount = -1;
+	caches++;
 #endif
 
 	/* Able to allocate the per node structures */
 	slab_state = PARTIAL;
 
 	/* Caches that are not of the two-to-the-power-of size */
-	create_kmalloc_cache(&kmalloc_caches[1],
+	if (KMALLOC_MIN_SIZE <= 64) {
+		create_kmalloc_cache(&kmalloc_caches[1],
 				"kmalloc-96", 96, GFP_KERNEL);
-	create_kmalloc_cache(&kmalloc_caches[2],
+		caches++;
+	}
+	if (KMALLOC_MIN_SIZE <= 128) {
+		create_kmalloc_cache(&kmalloc_caches[2],
 				"kmalloc-192", 192, GFP_KERNEL);
+		caches++;
+	}
 
-	for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
+	for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) {
 		create_kmalloc_cache(&kmalloc_caches[i],
 			"kmalloc", 1 << i, GFP_KERNEL);
+		caches++;
+	}
+
+
+	/*
+	 * Patch up the size_index table if we have strange large alignment
+	 * requirements for the kmalloc array. This is only the case for
+	 * mips it seems. The standard arches will not generate any code here.
+	 *
+	 * Largest permitted alignment is 256 bytes due to the way we
+	 * handle the index determination for the smaller caches.
+	 *
+	 * Make sure that nothing crazy happens if someone starts tinkering
+	 * around with ARCH_KMALLOC_MINALIGN
+	 */
+	BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
+		(KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));
+
+	for (i = 8; i < KMALLOC_MIN_SIZE; i += 8)
+		size_index[(i - 1) / 8] = KMALLOC_SHIFT_LOW;
 
 	slab_state = UP;
 
@@ -2465,8 +2599,8 @@
 				nr_cpu_ids * sizeof(struct page *);
 
 	printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
-		" Processors=%d, Nodes=%d\n",
-		KMALLOC_SHIFT_HIGH, cache_line_size(),
+		" CPUs=%d, Nodes=%d\n",
+		caches, cache_line_size(),
 		slub_min_order, slub_max_order, slub_min_objects,
 		nr_cpu_ids, nr_node_ids);
 }
@@ -2482,6 +2616,12 @@
 	if (s->ctor)
 		return 1;
 
+	/*
+	 * We may have set a slab to be unmergeable during bootstrap.
+	 */
+	if (s->refcount < 0)
+		return 1;
+
 	return 0;
 }
 
@@ -2489,7 +2629,7 @@
 		size_t align, unsigned long flags,
 		void (*ctor)(void *, struct kmem_cache *, unsigned long))
 {
-	struct list_head *h;
+	struct kmem_cache *s;
 
 	if (slub_nomerge || (flags & SLUB_NEVER_MERGE))
 		return NULL;
@@ -2501,10 +2641,7 @@
 	align = calculate_alignment(flags, align, size);
 	size = ALIGN(size, align);
 
-	list_for_each(h, &slab_caches) {
-		struct kmem_cache *s =
-			container_of(h, struct kmem_cache, list);
-
+	list_for_each_entry(s, &slab_caches, list) {
 		if (slab_unmergeable(s))
 			continue;
 
@@ -2547,25 +2684,26 @@
 		 */
 		s->objsize = max(s->objsize, (int)size);
 		s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
+		up_write(&slub_lock);
 		if (sysfs_slab_alias(s, name))
 			goto err;
-	} else {
-		s = kmalloc(kmem_size, GFP_KERNEL);
-		if (s && kmem_cache_open(s, GFP_KERNEL, name,
+		return s;
+	}
+	s = kmalloc(kmem_size, GFP_KERNEL);
+	if (s) {
+		if (kmem_cache_open(s, GFP_KERNEL, name,
 				size, align, flags, ctor)) {
-			if (sysfs_slab_add(s)) {
-				kfree(s);
-				goto err;
-			}
 			list_add(&s->list, &slab_caches);
-		} else
-			kfree(s);
+			up_write(&slub_lock);
+			if (sysfs_slab_add(s))
+				goto err;
+			return s;
+		}
+		kfree(s);
 	}
 	up_write(&slub_lock);
-	return s;
 
 err:
-	up_write(&slub_lock);
 	if (flags & SLAB_PANIC)
 		panic("Cannot create slabcache %s\n", name);
 	else
@@ -2574,32 +2712,7 @@
 }
 EXPORT_SYMBOL(kmem_cache_create);
 
-void *kmem_cache_zalloc(struct kmem_cache *s, gfp_t flags)
-{
-	void *x;
-
-	x = slab_alloc(s, flags, -1, __builtin_return_address(0));
-	if (x)
-		memset(x, 0, s->objsize);
-	return x;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
-
 #ifdef CONFIG_SMP
-static void for_all_slabs(void (*func)(struct kmem_cache *, int), int cpu)
-{
-	struct list_head *h;
-
-	down_read(&slub_lock);
-	list_for_each(h, &slab_caches) {
-		struct kmem_cache *s =
-			container_of(h, struct kmem_cache, list);
-
-		func(s, cpu);
-	}
-	up_read(&slub_lock);
-}
-
 /*
  * Use the cpu notifier to insure that the cpu slabs are flushed when
  * necessary.
@@ -2608,13 +2721,21 @@
 		unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
+	struct kmem_cache *s;
+	unsigned long flags;
 
 	switch (action) {
 	case CPU_UP_CANCELED:
 	case CPU_UP_CANCELED_FROZEN:
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
-		for_all_slabs(__flush_cpu_slab, cpu);
+		down_read(&slub_lock);
+		list_for_each_entry(s, &slab_caches, list) {
+			local_irq_save(flags);
+			__flush_cpu_slab(s, cpu);
+			local_irq_restore(flags);
+		}
+		up_read(&slub_lock);
 		break;
 	default:
 		break;
@@ -2631,8 +2752,8 @@
 {
 	struct kmem_cache *s = get_slab(size, gfpflags);
 
-	if (!s)
-		return NULL;
+	if (ZERO_OR_NULL_PTR(s))
+		return s;
 
 	return slab_alloc(s, gfpflags, -1, caller);
 }
@@ -2642,18 +2763,18 @@
 {
 	struct kmem_cache *s = get_slab(size, gfpflags);
 
-	if (!s)
-		return NULL;
+	if (ZERO_OR_NULL_PTR(s))
+		return s;
 
 	return slab_alloc(s, gfpflags, node, caller);
 }
 
 #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
-static int validate_slab(struct kmem_cache *s, struct page *page)
+static int validate_slab(struct kmem_cache *s, struct page *page,
+						unsigned long *map)
 {
 	void *p;
 	void *addr = page_address(page);
-	DECLARE_BITMAP(map, s->objects);
 
 	if (!check_slab(s, page) ||
 			!on_freelist(s, page, NULL))
@@ -2675,10 +2796,11 @@
 	return 1;
 }
 
-static void validate_slab_slab(struct kmem_cache *s, struct page *page)
+static void validate_slab_slab(struct kmem_cache *s, struct page *page,
+						unsigned long *map)
 {
 	if (slab_trylock(page)) {
-		validate_slab(s, page);
+		validate_slab(s, page, map);
 		slab_unlock(page);
 	} else
 		printk(KERN_INFO "SLUB %s: Skipped busy slab 0x%p\n",
@@ -2695,7 +2817,8 @@
 	}
 }
 
-static int validate_slab_node(struct kmem_cache *s, struct kmem_cache_node *n)
+static int validate_slab_node(struct kmem_cache *s,
+		struct kmem_cache_node *n, unsigned long *map)
 {
 	unsigned long count = 0;
 	struct page *page;
@@ -2704,7 +2827,7 @@
 	spin_lock_irqsave(&n->list_lock, flags);
 
 	list_for_each_entry(page, &n->partial, lru) {
-		validate_slab_slab(s, page);
+		validate_slab_slab(s, page, map);
 		count++;
 	}
 	if (count != n->nr_partial)
@@ -2715,7 +2838,7 @@
 		goto out;
 
 	list_for_each_entry(page, &n->full, lru) {
-		validate_slab_slab(s, page);
+		validate_slab_slab(s, page, map);
 		count++;
 	}
 	if (count != atomic_long_read(&n->nr_slabs))
@@ -2728,17 +2851,23 @@
 	return count;
 }
 
-static unsigned long validate_slab_cache(struct kmem_cache *s)
+static long validate_slab_cache(struct kmem_cache *s)
 {
 	int node;
 	unsigned long count = 0;
+	unsigned long *map = kmalloc(BITS_TO_LONGS(s->objects) *
+				sizeof(unsigned long), GFP_KERNEL);
+
+	if (!map)
+		return -ENOMEM;
 
 	flush_all(s);
 	for_each_online_node(node) {
 		struct kmem_cache_node *n = get_node(s, node);
 
-		count += validate_slab_node(s, n);
+		count += validate_slab_node(s, n, map);
 	}
+	kfree(map);
 	return count;
 }
 
@@ -2827,18 +2956,14 @@
 			get_order(sizeof(struct location) * t->max));
 }
 
-static int alloc_loc_track(struct loc_track *t, unsigned long max)
+static int alloc_loc_track(struct loc_track *t, unsigned long max, gfp_t flags)
 {
 	struct location *l;
 	int order;
 
-	if (!max)
-		max = PAGE_SIZE / sizeof(struct location);
-
 	order = get_order(sizeof(struct location) * max);
 
-	l = (void *)__get_free_pages(GFP_KERNEL, order);
-
+	l = (void *)__get_free_pages(flags, order);
 	if (!l)
 		return 0;
 
@@ -2904,7 +3029,7 @@
 	/*
 	 * Not found. Insert new tracking element.
 	 */
-	if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max))
+	if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max, GFP_ATOMIC))
 		return 0;
 
 	l = t->loc + pos;
@@ -2947,11 +3072,12 @@
 {
 	int n = 0;
 	unsigned long i;
-	struct loc_track t;
+	struct loc_track t = { 0, 0, NULL };
 	int node;
 
-	t.count = 0;
-	t.max = 0;
+	if (!alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location),
+			GFP_KERNEL))
+		return sprintf(buf, "Out of memory\n");
 
 	/* Push back cpu slabs */
 	flush_all(s);
@@ -3002,13 +3128,15 @@
 			n += sprintf(buf + n, " pid=%ld",
 				l->min_pid);
 
-		if (num_online_cpus() > 1 && !cpus_empty(l->cpus)) {
+		if (num_online_cpus() > 1 && !cpus_empty(l->cpus) &&
+				n < PAGE_SIZE - 60) {
 			n += sprintf(buf + n, " cpus=");
 			n += cpulist_scnprintf(buf + n, PAGE_SIZE - n - 50,
 					l->cpus);
 		}
 
-		if (num_online_nodes() > 1 && !nodes_empty(l->nodes)) {
+		if (num_online_nodes() > 1 && !nodes_empty(l->nodes) &&
+				n < PAGE_SIZE - 60) {
 			n += sprintf(buf + n, " nodes=");
 			n += nodelist_scnprintf(buf + n, PAGE_SIZE - n - 50,
 					l->nodes);
@@ -3353,11 +3481,14 @@
 static ssize_t validate_store(struct kmem_cache *s,
 			const char *buf, size_t length)
 {
-	if (buf[0] == '1')
-		validate_slab_cache(s);
-	else
-		return -EINVAL;
-	return length;
+	int ret = -EINVAL;
+
+	if (buf[0] == '1') {
+		ret = validate_slab_cache(s);
+		if (ret >= 0)
+			ret = length;
+	}
+	return ret;
 }
 SLAB_ATTR(validate);
 
@@ -3511,7 +3642,7 @@
 	.filter = uevent_filter,
 };
 
-decl_subsys(slab, &slab_ktype, &slab_uevent_ops);
+static decl_subsys(slab, &slab_ktype, &slab_uevent_ops);
 
 #define ID_STR_LENGTH 64
 
@@ -3609,7 +3740,7 @@
 	struct saved_alias *next;
 };
 
-struct saved_alias *alias_list;
+static struct saved_alias *alias_list;
 
 static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
 {
@@ -3637,7 +3768,7 @@
 
 static int __init slab_sysfs_init(void)
 {
-	struct list_head *h;
+	struct kmem_cache *s;
 	int err;
 
 	err = subsystem_register(&slab_subsys);
@@ -3648,10 +3779,7 @@
 
 	slab_state = SYSFS;
 
-	list_for_each(h, &slab_caches) {
-		struct kmem_cache *s =
-			container_of(h, struct kmem_cache, list);
-
+	list_for_each_entry(s, &slab_caches, list) {
 		err = sysfs_slab_add(s);
 		BUG_ON(err);
 	}
diff --git a/mm/sparse.c b/mm/sparse.c
index 6f3fff9..e03b39f 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -44,7 +44,7 @@
 #endif
 
 #ifdef CONFIG_SPARSEMEM_EXTREME
-static struct mem_section noinline *sparse_index_alloc(int nid)
+static struct mem_section noinline __init_refok *sparse_index_alloc(int nid)
 {
 	struct mem_section *section = NULL;
 	unsigned long array_size = SECTIONS_PER_ROOT *
@@ -209,6 +209,12 @@
 	return 1;
 }
 
+__attribute__((weak))
+void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+{
+	return NULL;
+}
+
 static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
 {
 	struct page *map;
@@ -219,6 +225,11 @@
 	if (map)
 		return map;
 
+  	map = alloc_bootmem_high_node(NODE_DATA(nid),
+                       sizeof(struct page) * PAGES_PER_SECTION);
+	if (map)
+		return map;
+
 	map = alloc_bootmem_node(NODE_DATA(nid),
 			sizeof(struct page) * PAGES_PER_SECTION);
 	if (map)
@@ -229,6 +240,27 @@
 	return NULL;
 }
 
+/*
+ * Allocate the accumulated non-linear sections, allocate a mem_map
+ * for each and record the physical to section mapping.
+ */
+void __init sparse_init(void)
+{
+	unsigned long pnum;
+	struct page *map;
+
+	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+		if (!valid_section_nr(pnum))
+			continue;
+
+		map = sparse_early_mem_map_alloc(pnum);
+		if (!map)
+			continue;
+		sparse_init_one_section(__nr_to_section(pnum), pnum, map);
+	}
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
 static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
 {
 	struct page *page, *ret;
@@ -269,27 +301,6 @@
 }
 
 /*
- * Allocate the accumulated non-linear sections, allocate a mem_map
- * for each and record the physical to section mapping.
- */
-void __init sparse_init(void)
-{
-	unsigned long pnum;
-	struct page *map;
-
-	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
-		if (!valid_section_nr(pnum))
-			continue;
-
-		map = sparse_early_mem_map_alloc(pnum);
-		if (!map)
-			continue;
-		sparse_init_one_section(__nr_to_section(pnum), pnum, map);
-	}
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-/*
  * returns the number of sections whose mem_maps were properly
  * set.  If this is <=0, then that means that the passed-in
  * map was not consumed and must be freed.
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 5f7cf2a..67daecb 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -21,7 +21,7 @@
 
 /*
  * swapper_space is a fiction, retained to simplify the path through
- * vmscan's shrink_list, to make sync_page look nicer, and to allow
+ * vmscan's shrink_page_list, to make sync_page look nicer, and to allow
  * future use of radix_tree tags in the swap cache.
  */
 static const struct address_space_operations swap_aops = {
@@ -334,7 +334,8 @@
 		 * Get a new page to read into from swap.
 		 */
 		if (!new_page) {
-			new_page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
+			new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+								vma, addr);
 			if (!new_page)
 				break;		/* Out of memory */
 		}
diff --git a/mm/swapfile.c b/mm/swapfile.c
index acc172c..7ff0a81 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -885,7 +885,7 @@
 		/*
 		 * So we could skip searching mms once swap count went
 		 * to 1, we did not mark any present ptes as dirty: must
-		 * mark page dirty so shrink_list will preserve it.
+		 * mark page dirty so shrink_page_list will preserve it.
 		 */
 		SetPageDirty(page);
 		unlock_page(page);
diff --git a/mm/truncate.c b/mm/truncate.c
index 4fbe1a2..f47e46d 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -100,9 +100,9 @@
 	if (PagePrivate(page))
 		do_invalidatepage(page, 0);
 
+	remove_from_page_cache(page);
 	ClearPageUptodate(page);
 	ClearPageMappedToDisk(page);
-	remove_from_page_cache(page);
 	page_cache_release(page);	/* pagecache ref */
 }
 
@@ -253,21 +253,8 @@
 }
 EXPORT_SYMBOL(truncate_inode_pages);
 
-/**
- * invalidate_mapping_pages - Invalidate all the unlocked pages of one inode
- * @mapping: the address_space which holds the pages to invalidate
- * @start: the offset 'from' which to invalidate
- * @end: the offset 'to' which to invalidate (inclusive)
- *
- * This function only removes the unlocked pages, if you want to
- * remove all the pages of one inode, you must call truncate_inode_pages.
- *
- * invalidate_mapping_pages() will not block on IO activity. It will not
- * invalidate pages which are dirty, locked, under writeback or mapped into
- * pagetables.
- */
-unsigned long invalidate_mapping_pages(struct address_space *mapping,
-				pgoff_t start, pgoff_t end)
+unsigned long __invalidate_mapping_pages(struct address_space *mapping,
+				pgoff_t start, pgoff_t end, bool be_atomic)
 {
 	struct pagevec pvec;
 	pgoff_t next = start;
@@ -308,17 +295,38 @@
 				break;
 		}
 		pagevec_release(&pvec);
+		if (likely(!be_atomic))
+			cond_resched();
 	}
 	return ret;
 }
+
+/**
+ * invalidate_mapping_pages - Invalidate all the unlocked pages of one inode
+ * @mapping: the address_space which holds the pages to invalidate
+ * @start: the offset 'from' which to invalidate
+ * @end: the offset 'to' which to invalidate (inclusive)
+ *
+ * This function only removes the unlocked pages, if you want to
+ * remove all the pages of one inode, you must call truncate_inode_pages.
+ *
+ * invalidate_mapping_pages() will not block on IO activity. It will not
+ * invalidate pages which are dirty, locked, under writeback or mapped into
+ * pagetables.
+ */
+unsigned long invalidate_mapping_pages(struct address_space *mapping,
+				pgoff_t start, pgoff_t end)
+{
+	return __invalidate_mapping_pages(mapping, start, end, false);
+}
 EXPORT_SYMBOL(invalidate_mapping_pages);
 
 /*
  * This is like invalidate_complete_page(), except it ignores the page's
  * refcount.  We do this because invalidate_inode_pages2() needs stronger
  * invalidation guarantees, and cannot afford to leave pages behind because
- * shrink_list() has a temp ref on them, or because they're transiently sitting
- * in the lru_cache_add() pagevecs.
+ * shrink_page_list() has a temp ref on them, or because they're transiently
+ * sitting in the lru_cache_add() pagevecs.
  */
 static int
 invalidate_complete_page2(struct address_space *mapping, struct page *page)
diff --git a/mm/util.c b/mm/util.c
index ace2aea..78f3783 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -5,20 +5,6 @@
 #include <asm/uaccess.h>
 
 /**
- * __kzalloc - allocate memory. The memory is set to zero.
- * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- */
-void *__kzalloc(size_t size, gfp_t flags)
-{
-	void *ret = kmalloc_track_caller(size, flags);
-	if (ret)
-		memset(ret, 0, size);
-	return ret;
-}
-EXPORT_SYMBOL(__kzalloc);
-
-/*
  * kstrdup - allocate space for and copy an existing string
  *
  * @s: the string to duplicate
@@ -58,6 +44,40 @@
 }
 EXPORT_SYMBOL(kmemdup);
 
+/**
+ * krealloc - reallocate memory. The contents will remain unchanged.
+ * @p: object to reallocate memory for.
+ * @new_size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * The contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.  If @p is %NULL, krealloc()
+ * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * %NULL pointer, the object pointed to is freed.
+ */
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+	void *ret;
+	size_t ks;
+
+	if (unlikely(!new_size)) {
+		kfree(p);
+		return ZERO_SIZE_PTR;
+	}
+
+	ks = ksize(p);
+	if (ks >= new_size)
+		return (void *)p;
+
+	ret = kmalloc_track_caller(new_size, flags);
+	if (ret) {
+		memcpy(ret, p, min(new_size, ks));
+		kfree(p);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(krealloc);
+
 /*
  * strndup_user - duplicate an existing string from user space
  *
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d3a9c53..8e05a11 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -68,12 +68,12 @@
 	} while (pud++, addr = next, addr != end);
 }
 
-void unmap_vm_area(struct vm_struct *area)
+void unmap_kernel_range(unsigned long addr, unsigned long size)
 {
 	pgd_t *pgd;
 	unsigned long next;
-	unsigned long addr = (unsigned long) area->addr;
-	unsigned long end = addr + area->size;
+	unsigned long start = addr;
+	unsigned long end = addr + size;
 
 	BUG_ON(addr >= end);
 	pgd = pgd_offset_k(addr);
@@ -84,7 +84,12 @@
 			continue;
 		vunmap_pud_range(pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
-	flush_tlb_kernel_range((unsigned long) area->addr, end);
+	flush_tlb_kernel_range(start, end);
+}
+
+static void unmap_vm_area(struct vm_struct *area)
+{
+	unmap_kernel_range((unsigned long)area->addr, area->size);
 }
 
 static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
@@ -427,11 +432,12 @@
 	area->nr_pages = nr_pages;
 	/* Please note that the recursion is strictly bounded. */
 	if (array_size > PAGE_SIZE) {
-		pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node);
+		pages = __vmalloc_node(array_size, gfp_mask | __GFP_ZERO,
+					PAGE_KERNEL, node);
 		area->flags |= VM_VPAGES;
 	} else {
 		pages = kmalloc_node(array_size,
-				(gfp_mask & GFP_LEVEL_MASK),
+				(gfp_mask & GFP_LEVEL_MASK) | __GFP_ZERO,
 				node);
 	}
 	area->pages = pages;
@@ -440,7 +446,6 @@
 		kfree(area);
 		return NULL;
 	}
-	memset(area->pages, 0, array_size);
 
 	for (i = 0; i < area->nr_pages; i++) {
 		if (node < 0)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 1be5a63..d419e10 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -66,17 +66,8 @@
 	int swappiness;
 
 	int all_unreclaimable;
-};
 
-/*
- * The list of shrinker callbacks used by to apply pressure to
- * ageable caches.
- */
-struct shrinker {
-	shrinker_t		shrinker;
-	struct list_head	list;
-	int			seeks;	/* seeks to recreate an obj */
-	long			nr;	/* objs pending delete */
+	int order;
 };
 
 #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
@@ -121,34 +112,25 @@
 /*
  * Add a shrinker callback to be called from the vm
  */
-struct shrinker *set_shrinker(int seeks, shrinker_t theshrinker)
+void register_shrinker(struct shrinker *shrinker)
 {
-        struct shrinker *shrinker;
-
-        shrinker = kmalloc(sizeof(*shrinker), GFP_KERNEL);
-        if (shrinker) {
-	        shrinker->shrinker = theshrinker;
-	        shrinker->seeks = seeks;
-	        shrinker->nr = 0;
-	        down_write(&shrinker_rwsem);
-	        list_add_tail(&shrinker->list, &shrinker_list);
-	        up_write(&shrinker_rwsem);
-	}
-	return shrinker;
+	shrinker->nr = 0;
+	down_write(&shrinker_rwsem);
+	list_add_tail(&shrinker->list, &shrinker_list);
+	up_write(&shrinker_rwsem);
 }
-EXPORT_SYMBOL(set_shrinker);
+EXPORT_SYMBOL(register_shrinker);
 
 /*
  * Remove one
  */
-void remove_shrinker(struct shrinker *shrinker)
+void unregister_shrinker(struct shrinker *shrinker)
 {
 	down_write(&shrinker_rwsem);
 	list_del(&shrinker->list);
 	up_write(&shrinker_rwsem);
-	kfree(shrinker);
 }
-EXPORT_SYMBOL(remove_shrinker);
+EXPORT_SYMBOL(unregister_shrinker);
 
 #define SHRINK_BATCH 128
 /*
@@ -185,7 +167,7 @@
 	list_for_each_entry(shrinker, &shrinker_list, list) {
 		unsigned long long delta;
 		unsigned long total_scan;
-		unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask);
+		unsigned long max_pass = (*shrinker->shrink)(0, gfp_mask);
 
 		delta = (4 * scanned) / shrinker->seeks;
 		delta *= max_pass;
@@ -213,8 +195,8 @@
 			int shrink_ret;
 			int nr_before;
 
-			nr_before = (*shrinker->shrinker)(0, gfp_mask);
-			shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask);
+			nr_before = (*shrinker->shrink)(0, gfp_mask);
+			shrink_ret = (*shrinker->shrink)(this_scan, gfp_mask);
 			if (shrink_ret == -1)
 				break;
 			if (shrink_ret < nr_before)
@@ -481,7 +463,8 @@
 
 		referenced = page_referenced(page, 1);
 		/* In active use or really unfreeable?  Activate it. */
-		if (referenced && page_mapping_inuse(page))
+		if (sc->order <= PAGE_ALLOC_COSTLY_ORDER &&
+					referenced && page_mapping_inuse(page))
 			goto activate_locked;
 
 #ifdef CONFIG_SWAP
@@ -514,7 +497,7 @@
 		}
 
 		if (PageDirty(page)) {
-			if (referenced)
+			if (sc->order <= PAGE_ALLOC_COSTLY_ORDER && referenced)
 				goto keep_locked;
 			if (!may_enter_fs)
 				goto keep_locked;
@@ -598,6 +581,51 @@
 	return nr_reclaimed;
 }
 
+/* LRU Isolation modes. */
+#define ISOLATE_INACTIVE 0	/* Isolate inactive pages. */
+#define ISOLATE_ACTIVE 1	/* Isolate active pages. */
+#define ISOLATE_BOTH 2		/* Isolate both active and inactive pages. */
+
+/*
+ * Attempt to remove the specified page from its LRU.  Only take this page
+ * if it is of the appropriate PageActive status.  Pages which are being
+ * freed elsewhere are also ignored.
+ *
+ * page:	page to consider
+ * mode:	one of the LRU isolation modes defined above
+ *
+ * returns 0 on success, -ve errno on failure.
+ */
+static int __isolate_lru_page(struct page *page, int mode)
+{
+	int ret = -EINVAL;
+
+	/* Only take pages on the LRU. */
+	if (!PageLRU(page))
+		return ret;
+
+	/*
+	 * When checking the active state, we need to be sure we are
+	 * dealing with comparible boolean values.  Take the logical not
+	 * of each.
+	 */
+	if (mode != ISOLATE_BOTH && (!PageActive(page) != !mode))
+		return ret;
+
+	ret = -EBUSY;
+	if (likely(get_page_unless_zero(page))) {
+		/*
+		 * Be careful not to clear PageLRU until after we're
+		 * sure the page is not being freed elsewhere -- the
+		 * page release code relies on it.
+		 */
+		ClearPageLRU(page);
+		ret = 0;
+	}
+
+	return ret;
+}
+
 /*
  * zone->lru_lock is heavily contended.  Some of the functions that
  * shrink the lists perform better by taking out a batch of pages
@@ -612,38 +640,90 @@
  * @src:	The LRU list to pull pages off.
  * @dst:	The temp list to put pages on to.
  * @scanned:	The number of pages that were scanned.
+ * @order:	The caller's attempted allocation order
+ * @mode:	One of the LRU isolation modes
  *
  * returns how many pages were moved onto *@dst.
  */
 static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
 		struct list_head *src, struct list_head *dst,
-		unsigned long *scanned)
+		unsigned long *scanned, int order, int mode)
 {
 	unsigned long nr_taken = 0;
-	struct page *page;
 	unsigned long scan;
 
 	for (scan = 0; scan < nr_to_scan && !list_empty(src); scan++) {
-		struct list_head *target;
+		struct page *page;
+		unsigned long pfn;
+		unsigned long end_pfn;
+		unsigned long page_pfn;
+		int zone_id;
+
 		page = lru_to_page(src);
 		prefetchw_prev_lru_page(page, src, flags);
 
 		VM_BUG_ON(!PageLRU(page));
 
-		list_del(&page->lru);
-		target = src;
-		if (likely(get_page_unless_zero(page))) {
-			/*
-			 * Be careful not to clear PageLRU until after we're
-			 * sure the page is not being freed elsewhere -- the
-			 * page release code relies on it.
-			 */
-			ClearPageLRU(page);
-			target = dst;
+		switch (__isolate_lru_page(page, mode)) {
+		case 0:
+			list_move(&page->lru, dst);
 			nr_taken++;
-		} /* else it is being freed elsewhere */
+			break;
 
-		list_add(&page->lru, target);
+		case -EBUSY:
+			/* else it is being freed elsewhere */
+			list_move(&page->lru, src);
+			continue;
+
+		default:
+			BUG();
+		}
+
+		if (!order)
+			continue;
+
+		/*
+		 * Attempt to take all pages in the order aligned region
+		 * surrounding the tag page.  Only take those pages of
+		 * the same active state as that tag page.  We may safely
+		 * round the target page pfn down to the requested order
+		 * as the mem_map is guarenteed valid out to MAX_ORDER,
+		 * where that page is in a different zone we will detect
+		 * it from its zone id and abort this block scan.
+		 */
+		zone_id = page_zone_id(page);
+		page_pfn = page_to_pfn(page);
+		pfn = page_pfn & ~((1 << order) - 1);
+		end_pfn = pfn + (1 << order);
+		for (; pfn < end_pfn; pfn++) {
+			struct page *cursor_page;
+
+			/* The target page is in the block, ignore it. */
+			if (unlikely(pfn == page_pfn))
+				continue;
+
+			/* Avoid holes within the zone. */
+			if (unlikely(!pfn_valid_within(pfn)))
+				break;
+
+			cursor_page = pfn_to_page(pfn);
+			/* Check that we have not crossed a zone boundary. */
+			if (unlikely(page_zone_id(cursor_page) != zone_id))
+				continue;
+			switch (__isolate_lru_page(cursor_page, mode)) {
+			case 0:
+				list_move(&cursor_page->lru, dst);
+				nr_taken++;
+				scan++;
+				break;
+
+			case -EBUSY:
+				/* else it is being freed elsewhere */
+				list_move(&cursor_page->lru, src);
+			default:
+				break;
+			}
+		}
 	}
 
 	*scanned = scan;
@@ -651,6 +731,24 @@
 }
 
 /*
+ * clear_active_flags() is a helper for shrink_active_list(), clearing
+ * any active bits from the pages in the list.
+ */
+static unsigned long clear_active_flags(struct list_head *page_list)
+{
+	int nr_active = 0;
+	struct page *page;
+
+	list_for_each_entry(page, page_list, lru)
+		if (PageActive(page)) {
+			ClearPageActive(page);
+			nr_active++;
+		}
+
+	return nr_active;
+}
+
+/*
  * shrink_inactive_list() is a helper for shrink_zone().  It returns the number
  * of reclaimed pages
  */
@@ -671,11 +769,18 @@
 		unsigned long nr_taken;
 		unsigned long nr_scan;
 		unsigned long nr_freed;
+		unsigned long nr_active;
 
 		nr_taken = isolate_lru_pages(sc->swap_cluster_max,
-					     &zone->inactive_list,
-					     &page_list, &nr_scan);
-		__mod_zone_page_state(zone, NR_INACTIVE, -nr_taken);
+			     &zone->inactive_list,
+			     &page_list, &nr_scan, sc->order,
+			     (sc->order > PAGE_ALLOC_COSTLY_ORDER)?
+					     ISOLATE_BOTH : ISOLATE_INACTIVE);
+		nr_active = clear_active_flags(&page_list);
+
+		__mod_zone_page_state(zone, NR_ACTIVE, -nr_active);
+		__mod_zone_page_state(zone, NR_INACTIVE,
+						-(nr_taken - nr_active));
 		zone->pages_scanned += nr_scan;
 		spin_unlock_irq(&zone->lru_lock);
 
@@ -820,7 +925,7 @@
 	lru_add_drain();
 	spin_lock_irq(&zone->lru_lock);
 	pgmoved = isolate_lru_pages(nr_pages, &zone->active_list,
-				    &l_hold, &pgscanned);
+			    &l_hold, &pgscanned, sc->order, ISOLATE_ACTIVE);
 	zone->pages_scanned += pgscanned;
 	__mod_zone_page_state(zone, NR_ACTIVE, -pgmoved);
 	spin_unlock_irq(&zone->lru_lock);
@@ -1011,7 +1116,7 @@
  * holds filesystem locks which prevent writeout this might not work, and the
  * allocation attempt will fail.
  */
-unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
+unsigned long try_to_free_pages(struct zone **zones, int order, gfp_t gfp_mask)
 {
 	int priority;
 	int ret = 0;
@@ -1026,6 +1131,7 @@
 		.swap_cluster_max = SWAP_CLUSTER_MAX,
 		.may_swap = 1,
 		.swappiness = vm_swappiness,
+		.order = order,
 	};
 
 	count_vm_event(ALLOCSTALL);
@@ -1131,6 +1237,7 @@
 		.may_swap = 1,
 		.swap_cluster_max = SWAP_CLUSTER_MAX,
 		.swappiness = vm_swappiness,
+		.order = order,
 	};
 	/*
 	 * temp_priority is used to remember the scanning priority at which
@@ -1314,6 +1421,7 @@
 	 * trying to free the first piece of memory in the first place).
 	 */
 	tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+	set_freezable();
 
 	order = 0;
 	for ( ; ; ) {
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 8faf27e..fadf791 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
+#include <linux/sched.h>
 
 #ifdef CONFIG_VM_EVENT_COUNTERS
 DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
@@ -471,13 +472,13 @@
 #endif
 
 #define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
-					TEXT_FOR_HIGHMEM(xx)
+					TEXT_FOR_HIGHMEM(xx) xx "_movable",
 
 static const char * const vmstat_text[] = {
 	/* Zoned VM counters */
 	"nr_free_pages",
-	"nr_active",
 	"nr_inactive",
+	"nr_active",
 	"nr_anon_pages",
 	"nr_mapped",
 	"nr_file_pages",
diff --git a/net/802/tr.c b/net/802/tr.c
index 0ba1946..e56e61a 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -567,7 +567,7 @@
 }
 
 
-static struct seq_operations rif_seq_ops = {
+static const struct seq_operations rif_seq_ops = {
 	.start = rif_seq_start,
 	.next  = rif_seq_next,
 	.stop  = rif_seq_stop,
diff --git a/net/8021q/Makefile b/net/8021q/Makefile
index 97feb44..10ca7f4 100644
--- a/net/8021q/Makefile
+++ b/net/8021q/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_VLAN_8021Q) += 8021q.o
 
-8021q-objs := vlan.o vlan_dev.o
+8021q-objs := vlan.o vlan_dev.o vlan_netlink.o
 
 ifeq ($(CONFIG_PROC_FS),y)
 8021q-objs += vlanproc.o
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index bd93c45..cda936b 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -97,35 +97,22 @@
 
 	/* Register us to receive netdevice events */
 	err = register_netdevice_notifier(&vlan_notifier_block);
-	if (err < 0) {
-		dev_remove_pack(&vlan_packet_type);
-		vlan_proc_cleanup();
-		return err;
-	}
+	if (err < 0)
+		goto err1;
+
+	err = vlan_netlink_init();
+	if (err < 0)
+		goto err2;
 
 	vlan_ioctl_set(vlan_ioctl_handler);
-
 	return 0;
-}
 
-/* Cleanup all vlan devices
- * Note: devices that have been registered that but not
- * brought up will exist but have no module ref count.
- */
-static void __exit vlan_cleanup_devices(void)
-{
-	struct net_device *dev, *nxt;
-
-	rtnl_lock();
-	for_each_netdev_safe(dev, nxt) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
-					    VLAN_DEV_INFO(dev)->vlan_id);
-
-			unregister_netdevice(dev);
-		}
-	}
-	rtnl_unlock();
+err2:
+	unregister_netdevice_notifier(&vlan_notifier_block);
+err1:
+	vlan_proc_cleanup();
+	dev_remove_pack(&vlan_packet_type);
+	return err;
 }
 
 /*
@@ -136,13 +123,13 @@
 {
 	int i;
 
+	vlan_netlink_fini();
 	vlan_ioctl_set(NULL);
 
 	/* Un-register us from receiving netdevice events */
 	unregister_netdevice_notifier(&vlan_notifier_block);
 
 	dev_remove_pack(&vlan_packet_type);
-	vlan_cleanup_devices();
 
 	/* This table must be empty if there are no module
 	 * references left.
@@ -197,6 +184,34 @@
 	kfree(grp);
 }
 
+static struct vlan_group *vlan_group_alloc(int ifindex)
+{
+	struct vlan_group *grp;
+	unsigned int size;
+	unsigned int i;
+
+	grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
+	if (!grp)
+		return NULL;
+
+	size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
+
+	for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
+		grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
+		if (!grp->vlan_devices_arrays[i])
+			goto err;
+	}
+
+	grp->real_dev_ifindex = ifindex;
+	hlist_add_head_rcu(&grp->hlist,
+			   &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
+	return grp;
+
+err:
+	vlan_group_free(grp);
+	return NULL;
+}
+
 static void vlan_rcu_free(struct rcu_head *rcu)
 {
 	vlan_group_free(container_of(rcu, struct vlan_group, rcu));
@@ -240,10 +255,8 @@
 			 * interlock with HW accelerating devices or SW vlan
 			 * input packet processing.
 			 */
-			if (real_dev->features &
-			    (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER)) {
+			if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
 				real_dev->vlan_rx_kill_vid(real_dev, vlan_id);
-			}
 
 			vlan_group_set_device(grp, vlan_id, NULL);
 			synchronize_net();
@@ -280,50 +293,66 @@
 	return ret;
 }
 
-static int unregister_vlan_device(const char *vlan_IF_name)
+int unregister_vlan_device(struct net_device *dev)
 {
-	struct net_device *dev = NULL;
 	int ret;
 
+	ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
+				  VLAN_DEV_INFO(dev)->vlan_id);
+	unregister_netdevice(dev);
 
-	dev = dev_get_by_name(vlan_IF_name);
-	ret = -EINVAL;
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			rtnl_lock();
-
-			ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
-						  VLAN_DEV_INFO(dev)->vlan_id);
-
-			dev_put(dev);
-			unregister_netdevice(dev);
-
-			rtnl_unlock();
-
-			if (ret == 1)
-				ret = 0;
-		} else {
-			printk(VLAN_ERR
-			       "%s: ERROR:	Tried to remove a non-vlan device "
-			       "with VLAN code, name: %s  priv_flags: %hX\n",
-			       __FUNCTION__, dev->name, dev->priv_flags);
-			dev_put(dev);
-			ret = -EPERM;
-		}
-	} else {
-#ifdef VLAN_DEBUG
-		printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__);
-#endif
-		ret = -EINVAL;
-	}
-
+	if (ret == 1)
+		ret = 0;
 	return ret;
 }
 
-static void vlan_setup(struct net_device *new_dev)
+/*
+ * vlan network devices have devices nesting below it, and are a special
+ * "super class" of normal network devices; split their locks off into a
+ * separate class since they always nest.
+ */
+static struct lock_class_key vlan_netdev_xmit_lock_key;
+
+static int vlan_dev_init(struct net_device *dev)
+{
+	struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
+
+	/* IFF_BROADCAST|IFF_MULTICAST; ??? */
+	dev->flags  = real_dev->flags & ~IFF_UP;
+	dev->iflink = real_dev->ifindex;
+	dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
+					  (1<<__LINK_STATE_DORMANT))) |
+		      (1<<__LINK_STATE_PRESENT);
+
+	if (is_zero_ether_addr(dev->dev_addr))
+		memcpy(dev->dev_addr, real_dev->dev_addr, dev->addr_len);
+	if (is_zero_ether_addr(dev->broadcast))
+		memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
+
+	if (real_dev->features & NETIF_F_HW_VLAN_TX) {
+		dev->hard_header     = real_dev->hard_header;
+		dev->hard_header_len = real_dev->hard_header_len;
+		dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
+		dev->rebuild_header  = real_dev->rebuild_header;
+	} else {
+		dev->hard_header     = vlan_dev_hard_header;
+		dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
+		dev->hard_start_xmit = vlan_dev_hard_start_xmit;
+		dev->rebuild_header  = vlan_dev_rebuild_header;
+	}
+	dev->hard_header_parse = real_dev->hard_header_parse;
+	dev->hard_header_cache = NULL;
+
+	lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
+	return 0;
+}
+
+void vlan_setup(struct net_device *new_dev)
 {
 	SET_MODULE_OWNER(new_dev);
 
+	ether_setup(new_dev);
+
 	/* new_dev->ifindex = 0;  it will be set when added to
 	 * the global list.
 	 * iflink is set as well.
@@ -340,12 +369,15 @@
 
 	/* set up method calls */
 	new_dev->change_mtu = vlan_dev_change_mtu;
+	new_dev->init = vlan_dev_init;
 	new_dev->open = vlan_dev_open;
 	new_dev->stop = vlan_dev_stop;
-	new_dev->set_mac_address = vlan_dev_set_mac_address;
 	new_dev->set_multicast_list = vlan_dev_set_multicast_list;
+	new_dev->change_rx_flags = vlan_change_rx_flags;
 	new_dev->destructor = free_netdev;
 	new_dev->do_ioctl = vlan_dev_ioctl;
+
+	memset(new_dev->broadcast, 0, ETH_ALEN);
 }
 
 static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev)
@@ -368,26 +400,97 @@
 	}
 }
 
-/*
- * vlan network devices have devices nesting below it, and are a special
- * "super class" of normal network devices; split their locks off into a
- * separate class since they always nest.
- */
-static struct lock_class_key vlan_netdev_xmit_lock_key;
+int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id)
+{
+	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
+		printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
+			__FUNCTION__, real_dev->name);
+		return -EOPNOTSUPP;
+	}
 
+	if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    !real_dev->vlan_rx_register) {
+		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
+			__FUNCTION__, real_dev->name);
+		return -EOPNOTSUPP;
+	}
+
+	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+	    (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
+		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
+			__FUNCTION__, real_dev->name);
+		return -EOPNOTSUPP;
+	}
+
+	/* The real device must be up and operating in order to
+	 * assosciate a VLAN device with it.
+	 */
+	if (!(real_dev->flags & IFF_UP))
+		return -ENETDOWN;
+
+	if (__find_vlan_dev(real_dev, vlan_id) != NULL) {
+		/* was already registered. */
+		printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
+		return -EEXIST;
+	}
+
+	return 0;
+}
+
+int register_vlan_dev(struct net_device *dev)
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct net_device *real_dev = vlan->real_dev;
+	unsigned short vlan_id = vlan->vlan_id;
+	struct vlan_group *grp, *ngrp = NULL;
+	int err;
+
+	grp = __vlan_find_group(real_dev->ifindex);
+	if (!grp) {
+		ngrp = grp = vlan_group_alloc(real_dev->ifindex);
+		if (!grp)
+			return -ENOBUFS;
+	}
+
+	err = register_netdevice(dev);
+	if (err < 0)
+		goto out_free_group;
+
+	/* Account for reference in struct vlan_dev_info */
+	dev_hold(real_dev);
+
+	vlan_transfer_operstate(real_dev, dev);
+	linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
+
+	/* So, got the sucker initialized, now lets place
+	 * it into our local structure.
+	 */
+	vlan_group_set_device(grp, vlan_id, dev);
+	if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
+		real_dev->vlan_rx_register(real_dev, ngrp);
+	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
+		real_dev->vlan_rx_add_vid(real_dev, vlan_id);
+
+	if (vlan_proc_add_dev(dev) < 0)
+		printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
+		       dev->name);
+	return 0;
+
+out_free_group:
+	if (ngrp)
+		vlan_group_free(ngrp);
+	return err;
+}
 
 /*  Attach a VLAN device to a mac address (ie Ethernet Card).
- *  Returns the device that was created, or NULL if there was
- *  an error of some kind.
+ *  Returns 0 if the device was created or a negative error code otherwise.
  */
-static struct net_device *register_vlan_device(const char *eth_IF_name,
-					       unsigned short VLAN_ID)
+static int register_vlan_device(struct net_device *real_dev,
+				unsigned short VLAN_ID)
 {
-	struct vlan_group *grp;
 	struct net_device *new_dev;
-	struct net_device *real_dev; /* the ethernet device */
 	char name[IFNAMSIZ];
-	int i;
+	int err;
 
 #ifdef VLAN_DEBUG
 	printk(VLAN_DBG "%s: if_name -:%s:-	vid: %i\n",
@@ -395,51 +498,11 @@
 #endif
 
 	if (VLAN_ID >= VLAN_VID_MASK)
-		goto out_ret_null;
+		return -ERANGE;
 
-	/* find the device relating to eth_IF_name. */
-	real_dev = dev_get_by_name(eth_IF_name);
-	if (!real_dev)
-		goto out_ret_null;
-
-	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
-		printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
-			__FUNCTION__, real_dev->name);
-		goto out_put_dev;
-	}
-
-	if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
-	    (real_dev->vlan_rx_register == NULL ||
-	     real_dev->vlan_rx_kill_vid == NULL)) {
-		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
-			__FUNCTION__, real_dev->name);
-		goto out_put_dev;
-	}
-
-	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
-	    (real_dev->vlan_rx_add_vid == NULL ||
-	     real_dev->vlan_rx_kill_vid == NULL)) {
-		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
-			__FUNCTION__, real_dev->name);
-		goto out_put_dev;
-	}
-
-	/* From this point on, all the data structures must remain
-	 * consistent.
-	 */
-	rtnl_lock();
-
-	/* The real device must be up and operating in order to
-	 * assosciate a VLAN device with it.
-	 */
-	if (!(real_dev->flags & IFF_UP))
-		goto out_unlock;
-
-	if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) {
-		/* was already registered. */
-		printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
-		goto out_unlock;
-	}
+	err = vlan_check_real_dev(real_dev, VLAN_ID);
+	if (err < 0)
+		return err;
 
 	/* Gotta set up the fields for the device. */
 #ifdef VLAN_DEBUG
@@ -475,138 +538,64 @@
 			       vlan_setup);
 
 	if (new_dev == NULL)
-		goto out_unlock;
-
-#ifdef VLAN_DEBUG
-	printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
-#endif
-	/* IFF_BROADCAST|IFF_MULTICAST; ??? */
-	new_dev->flags = real_dev->flags;
-	new_dev->flags &= ~IFF_UP;
-
-	new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
-					     (1<<__LINK_STATE_DORMANT))) |
-			 (1<<__LINK_STATE_PRESENT);
+		return -ENOBUFS;
 
 	/* need 4 bytes for extra VLAN header info,
 	 * hope the underlying device can handle it.
 	 */
 	new_dev->mtu = real_dev->mtu;
 
-	/* TODO: maybe just assign it to be ETHERNET? */
-	new_dev->type = real_dev->type;
-
-	new_dev->hard_header_len = real_dev->hard_header_len;
-	if (!(real_dev->features & NETIF_F_HW_VLAN_TX)) {
-		/* Regular ethernet + 4 bytes (18 total). */
-		new_dev->hard_header_len += VLAN_HLEN;
-	}
-
+#ifdef VLAN_DEBUG
+	printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
 	VLAN_MEM_DBG("new_dev->priv malloc, addr: %p  size: %i\n",
 		     new_dev->priv,
 		     sizeof(struct vlan_dev_info));
-
-	memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
-	memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
-	new_dev->addr_len = real_dev->addr_len;
-
-	if (real_dev->features & NETIF_F_HW_VLAN_TX) {
-		new_dev->hard_header = real_dev->hard_header;
-		new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
-		new_dev->rebuild_header = real_dev->rebuild_header;
-	} else {
-		new_dev->hard_header = vlan_dev_hard_header;
-		new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
-		new_dev->rebuild_header = vlan_dev_rebuild_header;
-	}
-	new_dev->hard_header_parse = real_dev->hard_header_parse;
+#endif
 
 	VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
 	VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
 	VLAN_DEV_INFO(new_dev)->dent = NULL;
-	VLAN_DEV_INFO(new_dev)->flags = 1;
+	VLAN_DEV_INFO(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
 
-#ifdef VLAN_DEBUG
-	printk(VLAN_DBG "About to go find the group for idx: %i\n",
-	       real_dev->ifindex);
-#endif
-
-	if (register_netdevice(new_dev))
+	new_dev->rtnl_link_ops = &vlan_link_ops;
+	err = register_vlan_dev(new_dev);
+	if (err < 0)
 		goto out_free_newdev;
 
-	lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
-
-	new_dev->iflink = real_dev->ifindex;
-	vlan_transfer_operstate(real_dev, new_dev);
-	linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
-
-	/* So, got the sucker initialized, now lets place
-	 * it into our local structure.
-	 */
-	grp = __vlan_find_group(real_dev->ifindex);
-
-	/* Note, we are running under the RTNL semaphore
-	 * so it cannot "appear" on us.
-	 */
-	if (!grp) { /* need to add a new group */
-		grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
-		if (!grp)
-			goto out_free_unregister;
-
-		for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
-			grp->vlan_devices_arrays[i] = kzalloc(
-				sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
-				GFP_KERNEL);
-
-			if (!grp->vlan_devices_arrays[i])
-				goto out_free_arrays;
-		}
-
-		/* printk(KERN_ALERT "VLAN REGISTER:  Allocated new group.\n"); */
-		grp->real_dev_ifindex = real_dev->ifindex;
-
-		hlist_add_head_rcu(&grp->hlist,
-				   &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
-
-		if (real_dev->features & NETIF_F_HW_VLAN_RX)
-			real_dev->vlan_rx_register(real_dev, grp);
-	}
-
-	vlan_group_set_device(grp, VLAN_ID, new_dev);
-
-	if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
-		printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
-							 new_dev->name);
-
-	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
-		real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);
-
-	rtnl_unlock();
-
-
+	/* Account for reference in struct vlan_dev_info */
+	dev_hold(real_dev);
 #ifdef VLAN_DEBUG
 	printk(VLAN_DBG "Allocated new device successfully, returning.\n");
 #endif
-	return new_dev;
-
-out_free_arrays:
-	vlan_group_free(grp);
-
-out_free_unregister:
-	unregister_netdev(new_dev);
-	goto out_unlock;
+	return 0;
 
 out_free_newdev:
 	free_netdev(new_dev);
+	return err;
+}
 
-out_unlock:
-	rtnl_unlock();
+static void vlan_sync_address(struct net_device *dev,
+			      struct net_device *vlandev)
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(vlandev);
 
-out_put_dev:
-	dev_put(real_dev);
+	/* May be called without an actual change */
+	if (!compare_ether_addr(vlan->real_dev_addr, dev->dev_addr))
+		return;
 
-out_ret_null:
-	return NULL;
+	/* vlan address was different from the old address and is equal to
+	 * the new address */
+	if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
+	    !compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
+		dev_unicast_delete(dev, vlandev->dev_addr, ETH_ALEN);
+
+	/* vlan address was equal to the old address and is different from
+	 * the new address */
+	if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
+	    compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
+		dev_unicast_add(dev, vlandev->dev_addr, ETH_ALEN);
+
+	memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN);
 }
 
 static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
@@ -635,6 +624,17 @@
 		}
 		break;
 
+	case NETDEV_CHANGEADDR:
+		/* Adjust unicast filters on underlying device */
+		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+			vlandev = vlan_group_get_device(grp, i);
+			if (!vlandev)
+				continue;
+
+			vlan_sync_address(dev, vlandev);
+		}
+		break;
+
 	case NETDEV_DOWN:
 		/* Put all VLANs for this dev in the down state too.  */
 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
@@ -697,9 +697,10 @@
  */
 static int vlan_ioctl_handler(void __user *arg)
 {
-	int err = 0;
+	int err;
 	unsigned short vid = 0;
 	struct vlan_ioctl_args args;
+	struct net_device *dev = NULL;
 
 	if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
 		return -EFAULT;
@@ -712,32 +713,57 @@
 	printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);
 #endif
 
+	rtnl_lock();
+
 	switch (args.cmd) {
 	case SET_VLAN_INGRESS_PRIORITY_CMD:
+	case SET_VLAN_EGRESS_PRIORITY_CMD:
+	case SET_VLAN_FLAG_CMD:
+	case ADD_VLAN_CMD:
+	case DEL_VLAN_CMD:
+	case GET_VLAN_REALDEV_NAME_CMD:
+	case GET_VLAN_VID_CMD:
+		err = -ENODEV;
+		dev = __dev_get_by_name(args.device1);
+		if (!dev)
+			goto out;
+
+		err = -EINVAL;
+		if (args.cmd != ADD_VLAN_CMD &&
+		    !(dev->priv_flags & IFF_802_1Q_VLAN))
+			goto out;
+	}
+
+	switch (args.cmd) {
+	case SET_VLAN_INGRESS_PRIORITY_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		err = vlan_dev_set_ingress_priority(args.device1,
-						    args.u.skb_priority,
-						    args.vlan_qos);
+			break;
+		vlan_dev_set_ingress_priority(dev,
+					      args.u.skb_priority,
+					      args.vlan_qos);
 		break;
 
 	case SET_VLAN_EGRESS_PRIORITY_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		err = vlan_dev_set_egress_priority(args.device1,
+			break;
+		err = vlan_dev_set_egress_priority(dev,
 						   args.u.skb_priority,
 						   args.vlan_qos);
 		break;
 
 	case SET_VLAN_FLAG_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		err = vlan_dev_set_vlan_flag(args.device1,
+			break;
+		err = vlan_dev_set_vlan_flag(dev,
 					     args.u.flag,
 					     args.vlan_qos);
 		break;
 
 	case SET_VLAN_NAME_TYPE_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if ((args.u.name_type >= 0) &&
@@ -750,26 +776,17 @@
 		break;
 
 	case ADD_VLAN_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		/* we have been given the name of the Ethernet Device we want to
-		 * talk to:  args.dev1	 We also have the
-		 * VLAN ID:  args.u.VID
-		 */
-		if (register_vlan_device(args.device1, args.u.VID)) {
-			err = 0;
-		} else {
-			err = -EINVAL;
-		}
+			break;
+		err = register_vlan_device(dev, args.u.VID);
 		break;
 
 	case DEL_VLAN_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		/* Here, the args.dev1 is the actual VLAN we want
-		 * to get rid of.
-		 */
-		err = unregister_vlan_device(args.device1);
+			break;
+		err = unregister_vlan_device(dev);
 		break;
 
 	case GET_VLAN_INGRESS_PRIORITY_CMD:
@@ -793,9 +810,7 @@
 		err = -EINVAL;
 		break;
 	case GET_VLAN_REALDEV_NAME_CMD:
-		err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
-		if (err)
-			goto out;
+		vlan_dev_get_realdev_name(dev, args.u.device2);
 		if (copy_to_user(arg, &args,
 				 sizeof(struct vlan_ioctl_args))) {
 			err = -EFAULT;
@@ -803,9 +818,7 @@
 		break;
 
 	case GET_VLAN_VID_CMD:
-		err = vlan_dev_get_vid(args.device1, &vid);
-		if (err)
-			goto out;
+		vlan_dev_get_vid(dev, &vid);
 		args.u.VID = vid;
 		if (copy_to_user(arg, &args,
 				 sizeof(struct vlan_ioctl_args))) {
@@ -817,9 +830,11 @@
 		/* pass on to underlying device instead?? */
 		printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
 			__FUNCTION__, args.cmd);
-		return -EINVAL;
+		err = -EINVAL;
+		break;
 	}
 out:
+	rtnl_unlock();
 	return err;
 }
 
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 1976cdb..7df5b29 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -58,15 +58,28 @@
 int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
 int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
 int vlan_dev_change_mtu(struct net_device *dev, int new_mtu);
-int vlan_dev_set_mac_address(struct net_device *dev, void* addr);
 int vlan_dev_open(struct net_device* dev);
 int vlan_dev_stop(struct net_device* dev);
 int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
-int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
-int vlan_dev_get_realdev_name(const char* dev_name, char* result);
-int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
+void vlan_dev_set_ingress_priority(const struct net_device *dev,
+				   u32 skb_prio, short vlan_prio);
+int vlan_dev_set_egress_priority(const struct net_device *dev,
+				 u32 skb_prio, short vlan_prio);
+int vlan_dev_set_vlan_flag(const struct net_device *dev,
+			   u32 flag, short flag_val);
+void vlan_dev_get_realdev_name(const struct net_device *dev, char *result);
+void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result);
+void vlan_change_rx_flags(struct net_device *dev, int change);
 void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
 
+int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id);
+void vlan_setup(struct net_device *dev);
+int register_vlan_dev(struct net_device *dev);
+int unregister_vlan_device(struct net_device *dev);
+
+int vlan_netlink_init(void);
+void vlan_netlink_fini(void);
+
+extern struct rtnl_link_ops vlan_link_ops;
+
 #endif /* !(__BEN_VLAN_802_1Q_INC__) */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index ec46084..4d2aa4d 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -73,7 +73,7 @@
 
 static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
 {
-	if (VLAN_DEV_INFO(skb->dev)->flags & 1) {
+	if (VLAN_DEV_INFO(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) {
 		if (skb_shared(skb) || skb_cloned(skb)) {
 			struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
 			kfree_skb(skb);
@@ -350,7 +350,8 @@
 	 * header shuffling in the hard_start_xmit.  Users can turn off this
 	 * REORDER behaviour with the vconfig tool.
 	 */
-	build_vlan_header = ((VLAN_DEV_INFO(dev)->flags & 1) == 0);
+	if (!(VLAN_DEV_INFO(dev)->flags & VLAN_FLAG_REORDER_HDR))
+		build_vlan_header = 1;
 
 	if (build_vlan_header) {
 		vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN);
@@ -534,269 +535,120 @@
 	return 0;
 }
 
-int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
+void vlan_dev_set_ingress_priority(const struct net_device *dev,
+				   u32 skb_prio, short vlan_prio)
 {
-	struct net_device *dev = dev_get_by_name(dev_name);
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
 
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			/* see if a priority mapping exists.. */
-			VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
-			dev_put(dev);
-			return 0;
-		}
+	if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio)
+		vlan->nr_ingress_mappings--;
+	else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio)
+		vlan->nr_ingress_mappings++;
 
-		dev_put(dev);
-	}
-	return -EINVAL;
+	vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
 }
 
-int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
+int vlan_dev_set_egress_priority(const struct net_device *dev,
+				 u32 skb_prio, short vlan_prio)
 {
-	struct net_device *dev = dev_get_by_name(dev_name);
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
 	struct vlan_priority_tci_mapping *mp = NULL;
 	struct vlan_priority_tci_mapping *np;
+	u32 vlan_qos = (vlan_prio << 13) & 0xE000;
 
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			/* See if a priority mapping exists.. */
-			mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
-			while (mp) {
-				if (mp->priority == skb_prio) {
-					mp->vlan_qos = ((vlan_prio << 13) & 0xE000);
-					dev_put(dev);
-					return 0;
-				}
-				mp = mp->next;
-			}
-
-			/* Create a new mapping then. */
-			mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
-			np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
-			if (np) {
-				np->next = mp;
-				np->priority = skb_prio;
-				np->vlan_qos = ((vlan_prio << 13) & 0xE000);
-				VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np;
-				dev_put(dev);
-				return 0;
-			} else {
-				dev_put(dev);
-				return -ENOBUFS;
-			}
+	/* See if a priority mapping exists.. */
+	mp = vlan->egress_priority_map[skb_prio & 0xF];
+	while (mp) {
+		if (mp->priority == skb_prio) {
+			if (mp->vlan_qos && !vlan_qos)
+				vlan->nr_egress_mappings--;
+			else if (!mp->vlan_qos && vlan_qos)
+				vlan->nr_egress_mappings++;
+			mp->vlan_qos = vlan_qos;
+			return 0;
 		}
-		dev_put(dev);
-	}
-	return -EINVAL;
-}
-
-/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */
-int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val)
-{
-	struct net_device *dev = dev_get_by_name(dev_name);
-
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			/* verify flag is supported */
-			if (flag == 1) {
-				if (flag_val) {
-					VLAN_DEV_INFO(dev)->flags |= 1;
-				} else {
-					VLAN_DEV_INFO(dev)->flags &= ~1;
-				}
-				dev_put(dev);
-				return 0;
-			} else {
-				printk(KERN_ERR  "%s: flag %i is not valid.\n",
-					__FUNCTION__, (int)(flag));
-				dev_put(dev);
-				return -EINVAL;
-			}
-		} else {
-			printk(KERN_ERR
-			       "%s: %s is not a vlan device, priv_flags: %hX.\n",
-			       __FUNCTION__, dev->name, dev->priv_flags);
-			dev_put(dev);
-		}
-	} else {
-		printk(KERN_ERR  "%s: Could not find device: %s\n",
-			__FUNCTION__, dev_name);
+		mp = mp->next;
 	}
 
-	return -EINVAL;
-}
+	/* Create a new mapping then. */
+	mp = vlan->egress_priority_map[skb_prio & 0xF];
+	np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
+	if (!np)
+		return -ENOBUFS;
 
-
-int vlan_dev_get_realdev_name(const char *dev_name, char* result)
-{
-	struct net_device *dev = dev_get_by_name(dev_name);
-	int rv = 0;
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
-			rv = 0;
-		} else {
-			rv = -EINVAL;
-		}
-		dev_put(dev);
-	} else {
-		rv = -ENODEV;
-	}
-	return rv;
-}
-
-int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
-{
-	struct net_device *dev = dev_get_by_name(dev_name);
-	int rv = 0;
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			*result = VLAN_DEV_INFO(dev)->vlan_id;
-			rv = 0;
-		} else {
-			rv = -EINVAL;
-		}
-		dev_put(dev);
-	} else {
-		rv = -ENODEV;
-	}
-	return rv;
-}
-
-
-int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
-{
-	struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
-	int i;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	printk("%s: Setting MAC address to ", dev->name);
-	for (i = 0; i < 6; i++)
-		printk(" %2.2x", dev->dev_addr[i]);
-	printk(".\n");
-
-	if (memcmp(VLAN_DEV_INFO(dev)->real_dev->dev_addr,
-		   dev->dev_addr,
-		   dev->addr_len) != 0) {
-		if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_PROMISC)) {
-			int flgs = VLAN_DEV_INFO(dev)->real_dev->flags;
-
-			/* Increment our in-use promiscuity counter */
-			dev_set_promiscuity(VLAN_DEV_INFO(dev)->real_dev, 1);
-
-			/* Make PROMISC visible to the user. */
-			flgs |= IFF_PROMISC;
-			printk("VLAN (%s):  Setting underlying device (%s) to promiscious mode.\n",
-			       dev->name, VLAN_DEV_INFO(dev)->real_dev->name);
-			dev_change_flags(VLAN_DEV_INFO(dev)->real_dev, flgs);
-		}
-	} else {
-		printk("VLAN (%s):  Underlying device (%s) has same MAC, not checking promiscious mode.\n",
-		       dev->name, VLAN_DEV_INFO(dev)->real_dev->name);
-	}
-
+	np->next = mp;
+	np->priority = skb_prio;
+	np->vlan_qos = vlan_qos;
+	vlan->egress_priority_map[skb_prio & 0xF] = np;
+	if (vlan_qos)
+		vlan->nr_egress_mappings++;
 	return 0;
 }
 
-static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
-				  struct dev_mc_list *dmi2)
+/* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */
+int vlan_dev_set_vlan_flag(const struct net_device *dev,
+			   u32 flag, short flag_val)
 {
-	return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) &&
-		(memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0));
-}
-
-/** dmi is a single entry into a dev_mc_list, a single node.  mc_list is
- *  an entire list, and we'll iterate through it.
- */
-static int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list)
-{
-	struct dev_mc_list *idmi;
-
-	for (idmi = mc_list; idmi != NULL; ) {
-		if (vlan_dmi_equals(dmi, idmi)) {
-			if (dmi->dmi_users > idmi->dmi_users)
-				return 1;
-			else
-				return 0;
+	/* verify flag is supported */
+	if (flag == VLAN_FLAG_REORDER_HDR) {
+		if (flag_val) {
+			VLAN_DEV_INFO(dev)->flags |= VLAN_FLAG_REORDER_HDR;
 		} else {
-			idmi = idmi->next;
+			VLAN_DEV_INFO(dev)->flags &= ~VLAN_FLAG_REORDER_HDR;
 		}
+		return 0;
 	}
-
-	return 1;
+	printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag);
+	return -EINVAL;
 }
 
-static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list)
+void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
 {
-	struct dev_mc_list *dmi = mc_list;
-	struct dev_mc_list *next;
-
-	while(dmi) {
-		next = dmi->next;
-		kfree(dmi);
-		dmi = next;
-	}
+	strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
 }
 
-static void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info)
+void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result)
 {
-	struct dev_mc_list *dmi, *new_dmi;
-
-	vlan_destroy_mc_list(vlan_info->old_mc_list);
-	vlan_info->old_mc_list = NULL;
-
-	for (dmi = mc_list; dmi != NULL; dmi = dmi->next) {
-		new_dmi = kmalloc(sizeof(*new_dmi), GFP_ATOMIC);
-		if (new_dmi == NULL) {
-			printk(KERN_ERR "vlan: cannot allocate memory. "
-			       "Multicast may not work properly from now.\n");
-			return;
-		}
-
-		/* Copy whole structure, then make new 'next' pointer */
-		*new_dmi = *dmi;
-		new_dmi->next = vlan_info->old_mc_list;
-		vlan_info->old_mc_list = new_dmi;
-	}
-}
-
-static void vlan_flush_mc_list(struct net_device *dev)
-{
-	struct dev_mc_list *dmi = dev->mc_list;
-
-	while (dmi) {
-		printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n",
-		       dev->name,
-		       dmi->dmi_addr[0],
-		       dmi->dmi_addr[1],
-		       dmi->dmi_addr[2],
-		       dmi->dmi_addr[3],
-		       dmi->dmi_addr[4],
-		       dmi->dmi_addr[5]);
-		dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-		dmi = dev->mc_list;
-	}
-
-	/* dev->mc_list is NULL by the time we get here. */
-	vlan_destroy_mc_list(VLAN_DEV_INFO(dev)->old_mc_list);
-	VLAN_DEV_INFO(dev)->old_mc_list = NULL;
+	*result = VLAN_DEV_INFO(dev)->vlan_id;
 }
 
 int vlan_dev_open(struct net_device *dev)
 {
-	if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_UP))
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct net_device *real_dev = vlan->real_dev;
+	int err;
+
+	if (!(real_dev->flags & IFF_UP))
 		return -ENETDOWN;
 
+	if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) {
+		err = dev_unicast_add(real_dev, dev->dev_addr, ETH_ALEN);
+		if (err < 0)
+			return err;
+	}
+	memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN);
+
+	if (dev->flags & IFF_ALLMULTI)
+		dev_set_allmulti(real_dev, 1);
+	if (dev->flags & IFF_PROMISC)
+		dev_set_promiscuity(real_dev, 1);
+
 	return 0;
 }
 
 int vlan_dev_stop(struct net_device *dev)
 {
-	vlan_flush_mc_list(dev);
+	struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
+
+	dev_mc_unsync(real_dev, dev);
+	if (dev->flags & IFF_ALLMULTI)
+		dev_set_allmulti(real_dev, -1);
+	if (dev->flags & IFF_PROMISC)
+		dev_set_promiscuity(real_dev, -1);
+
+	if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
+		dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len);
+
 	return 0;
 }
 
@@ -827,68 +679,18 @@
 	return err;
 }
 
+void vlan_change_rx_flags(struct net_device *dev, int change)
+{
+	struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
+
+	if (change & IFF_ALLMULTI)
+		dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+	if (change & IFF_PROMISC)
+		dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1);
+}
+
 /** Taken from Gleb + Lennert's VLAN code, and modified... */
 void vlan_dev_set_multicast_list(struct net_device *vlan_dev)
 {
-	struct dev_mc_list *dmi;
-	struct net_device *real_dev;
-	int inc;
-
-	if (vlan_dev && (vlan_dev->priv_flags & IFF_802_1Q_VLAN)) {
-		/* Then it's a real vlan device, as far as we can tell.. */
-		real_dev = VLAN_DEV_INFO(vlan_dev)->real_dev;
-
-		/* compare the current promiscuity to the last promisc we had.. */
-		inc = vlan_dev->promiscuity - VLAN_DEV_INFO(vlan_dev)->old_promiscuity;
-		if (inc) {
-			printk(KERN_INFO "%s: dev_set_promiscuity(master, %d)\n",
-			       vlan_dev->name, inc);
-			dev_set_promiscuity(real_dev, inc); /* found in dev.c */
-			VLAN_DEV_INFO(vlan_dev)->old_promiscuity = vlan_dev->promiscuity;
-		}
-
-		inc = vlan_dev->allmulti - VLAN_DEV_INFO(vlan_dev)->old_allmulti;
-		if (inc) {
-			printk(KERN_INFO "%s: dev_set_allmulti(master, %d)\n",
-			       vlan_dev->name, inc);
-			dev_set_allmulti(real_dev, inc); /* dev.c */
-			VLAN_DEV_INFO(vlan_dev)->old_allmulti = vlan_dev->allmulti;
-		}
-
-		/* looking for addresses to add to master's list */
-		for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) {
-			if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) {
-				dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-				printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n",
-				       vlan_dev->name,
-				       dmi->dmi_addr[0],
-				       dmi->dmi_addr[1],
-				       dmi->dmi_addr[2],
-				       dmi->dmi_addr[3],
-				       dmi->dmi_addr[4],
-				       dmi->dmi_addr[5]);
-			}
-		}
-
-		/* looking for addresses to delete from master's list */
-		for (dmi = VLAN_DEV_INFO(vlan_dev)->old_mc_list; dmi != NULL; dmi = dmi->next) {
-			if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) {
-				/* if we think we should add it to the new list, then we should really
-				 * delete it from the real list on the underlying device.
-				 */
-				dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-				printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n",
-				       vlan_dev->name,
-				       dmi->dmi_addr[0],
-				       dmi->dmi_addr[1],
-				       dmi->dmi_addr[2],
-				       dmi->dmi_addr[3],
-				       dmi->dmi_addr[4],
-				       dmi->dmi_addr[5]);
-			}
-		}
-
-		/* save multicast list */
-		vlan_copy_mc_list(vlan_dev->mc_list, VLAN_DEV_INFO(vlan_dev));
-	}
+	dev_mc_sync(VLAN_DEV_INFO(vlan_dev)->real_dev, vlan_dev);
 }
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
new file mode 100644
index 0000000..6cdd1e0
--- /dev/null
+++ b/net/8021q/vlan_netlink.c
@@ -0,0 +1,243 @@
+/*
+ *	VLAN netlink control interface
+ *
+ * 	Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/netlink.h>
+#include <net/rtnetlink.h>
+#include "vlan.h"
+
+
+static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
+	[IFLA_VLAN_ID]		= { .type = NLA_U16 },
+	[IFLA_VLAN_FLAGS]	= { .len = sizeof(struct ifla_vlan_flags) },
+	[IFLA_VLAN_EGRESS_QOS]	= { .type = NLA_NESTED },
+	[IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = {
+	[IFLA_VLAN_QOS_MAPPING] = { .len = sizeof(struct ifla_vlan_qos_mapping) },
+};
+
+
+static inline int vlan_validate_qos_map(struct nlattr *attr)
+{
+	if (!attr)
+		return 0;
+	return nla_validate_nested(attr, IFLA_VLAN_QOS_MAX, vlan_map_policy);
+}
+
+static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+	struct ifla_vlan_flags *flags;
+	u16 id;
+	int err;
+
+	if (tb[IFLA_ADDRESS]) {
+		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+			return -EINVAL;
+		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+			return -EADDRNOTAVAIL;
+	}
+
+	if (!data)
+		return -EINVAL;
+
+	if (data[IFLA_VLAN_ID]) {
+		id = nla_get_u16(data[IFLA_VLAN_ID]);
+		if (id >= VLAN_VID_MASK)
+			return -ERANGE;
+	}
+	if (data[IFLA_VLAN_FLAGS]) {
+		flags = nla_data(data[IFLA_VLAN_FLAGS]);
+		if ((flags->flags & flags->mask) & ~VLAN_FLAG_REORDER_HDR)
+			return -EINVAL;
+	}
+
+	err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
+	if (err < 0)
+		return err;
+	err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static int vlan_changelink(struct net_device *dev,
+			   struct nlattr *tb[], struct nlattr *data[])
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct ifla_vlan_flags *flags;
+	struct ifla_vlan_qos_mapping *m;
+	struct nlattr *attr;
+	int rem;
+
+	if (data[IFLA_VLAN_FLAGS]) {
+		flags = nla_data(data[IFLA_VLAN_FLAGS]);
+		vlan->flags = (vlan->flags & ~flags->mask) |
+			      (flags->flags & flags->mask);
+	}
+	if (data[IFLA_VLAN_INGRESS_QOS]) {
+		nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
+			m = nla_data(attr);
+			vlan_dev_set_ingress_priority(dev, m->to, m->from);
+		}
+	}
+	if (data[IFLA_VLAN_EGRESS_QOS]) {
+		nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
+			m = nla_data(attr);
+			vlan_dev_set_egress_priority(dev, m->from, m->to);
+		}
+	}
+	return 0;
+}
+
+static int vlan_newlink(struct net_device *dev,
+			struct nlattr *tb[], struct nlattr *data[])
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct net_device *real_dev;
+	int err;
+
+	if (!data[IFLA_VLAN_ID])
+		return -EINVAL;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+	real_dev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK]));
+	if (!real_dev)
+		return -ENODEV;
+
+	vlan->vlan_id  = nla_get_u16(data[IFLA_VLAN_ID]);
+	vlan->real_dev = real_dev;
+	vlan->flags    = VLAN_FLAG_REORDER_HDR;
+
+	err = vlan_check_real_dev(real_dev, vlan->vlan_id);
+	if (err < 0)
+		return err;
+
+	if (!tb[IFLA_MTU])
+		dev->mtu = real_dev->mtu;
+	else if (dev->mtu > real_dev->mtu)
+		return -EINVAL;
+
+	err = vlan_changelink(dev, tb, data);
+	if (err < 0)
+		return err;
+
+	return register_vlan_dev(dev);
+}
+
+static void vlan_dellink(struct net_device *dev)
+{
+	unregister_vlan_device(dev);
+}
+
+static inline size_t vlan_qos_map_size(unsigned int n)
+{
+	if (n == 0)
+		return 0;
+	/* IFLA_VLAN_{EGRESS,INGRESS}_QOS + n * IFLA_VLAN_QOS_MAPPING */
+	return nla_total_size(sizeof(struct nlattr)) +
+	       nla_total_size(sizeof(struct ifla_vlan_qos_mapping)) * n;
+}
+
+static size_t vlan_get_size(const struct net_device *dev)
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+
+	return nla_total_size(2) +	/* IFLA_VLAN_ID */
+	       vlan_qos_map_size(vlan->nr_ingress_mappings) +
+	       vlan_qos_map_size(vlan->nr_egress_mappings);
+}
+
+static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct vlan_priority_tci_mapping *pm;
+	struct ifla_vlan_flags f;
+	struct ifla_vlan_qos_mapping m;
+	struct nlattr *nest;
+	unsigned int i;
+
+	NLA_PUT_U16(skb, IFLA_VLAN_ID, VLAN_DEV_INFO(dev)->vlan_id);
+	if (vlan->flags) {
+		f.flags = vlan->flags;
+		f.mask  = ~0;
+		NLA_PUT(skb, IFLA_VLAN_FLAGS, sizeof(f), &f);
+	}
+	if (vlan->nr_ingress_mappings) {
+		nest = nla_nest_start(skb, IFLA_VLAN_INGRESS_QOS);
+		if (nest == NULL)
+			goto nla_put_failure;
+
+		for (i = 0; i < ARRAY_SIZE(vlan->ingress_priority_map); i++) {
+			if (!vlan->ingress_priority_map[i])
+				continue;
+
+			m.from = i;
+			m.to   = vlan->ingress_priority_map[i];
+			NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
+				sizeof(m), &m);
+		}
+		nla_nest_end(skb, nest);
+	}
+
+	if (vlan->nr_egress_mappings) {
+		nest = nla_nest_start(skb, IFLA_VLAN_EGRESS_QOS);
+		if (nest == NULL)
+			goto nla_put_failure;
+
+		for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
+			for (pm = vlan->egress_priority_map[i]; pm;
+			     pm = pm->next) {
+				if (!pm->vlan_qos)
+					continue;
+
+				m.from = pm->priority;
+				m.to   = (pm->vlan_qos >> 13) & 0x7;
+				NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
+					sizeof(m), &m);
+			}
+		}
+		nla_nest_end(skb, nest);
+	}
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+struct rtnl_link_ops vlan_link_ops __read_mostly = {
+	.kind		= "vlan",
+	.maxtype	= IFLA_VLAN_MAX,
+	.policy		= vlan_policy,
+	.priv_size	= sizeof(struct vlan_dev_info),
+	.setup		= vlan_setup,
+	.validate	= vlan_validate,
+	.newlink	= vlan_newlink,
+	.changelink	= vlan_changelink,
+	.dellink	= vlan_dellink,
+	.get_size	= vlan_get_size,
+	.fill_info	= vlan_fill_info,
+};
+
+int __init vlan_netlink_init(void)
+{
+	return rtnl_link_register(&vlan_link_ops);
+}
+
+void __exit vlan_netlink_fini(void)
+{
+	rtnl_link_unregister(&vlan_link_ops);
+}
+
+MODULE_ALIAS_RTNL_LINK("vlan");
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index d216a64..c0040c9 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -69,7 +69,7 @@
  *	Generic /proc/net/vlan/<file> file and inode operations
  */
 
-static struct seq_operations vlan_seq_ops = {
+static const struct seq_operations vlan_seq_ops = {
 	.start = vlan_seq_start,
 	.next = vlan_seq_next,
 	.stop = vlan_seq_stop,
@@ -342,7 +342,7 @@
 	seq_printf(seq, "Device: %s", dev_info->real_dev->name);
 	/* now show all PRIORITY mappings relating to this VLAN */
 	seq_printf(seq,
-		       "\nINGRESS priority mappings: 0:%lu  1:%lu  2:%lu  3:%lu  4:%lu  5:%lu  6:%lu 7:%lu\n",
+		       "\nINGRESS priority mappings: 0:%u  1:%u  2:%u  3:%u  4:%u  5:%u  6:%u 7:%u\n",
 		       dev_info->ingress_priority_map[0],
 		       dev_info->ingress_priority_map[1],
 		       dev_info->ingress_priority_map[2],
@@ -357,7 +357,7 @@
 		const struct vlan_priority_tci_mapping *mp
 			= dev_info->egress_priority_map[i];
 		while (mp) {
-			seq_printf(seq, "%lu:%hu ",
+			seq_printf(seq, "%u:%hu ",
 				   mp->priority, ((mp->vlan_qos >> 13) & 0x7));
 			mp = mp->next;
 		}
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
new file mode 100644
index 0000000..66821cd
--- /dev/null
+++ b/net/9p/Kconfig
@@ -0,0 +1,21 @@
+#
+# 9P protocol configuration
+#
+
+menuconfig NET_9P
+	depends on NET && EXPERIMENTAL
+	tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
+	help
+	  If you say Y here, you will get experimental support for
+	  Plan 9 resource sharing via the 9P2000 protocol.
+
+	  See <http://v9fs.sf.net> for more information.
+
+	  If unsure, say N.
+
+config NET_9P_DEBUG
+	bool "Debug information"
+	depends on NET_9P
+	help
+	  Say Y if you want the 9P subsistem to log debug information.
+
diff --git a/net/9p/Makefile b/net/9p/Makefile
new file mode 100644
index 0000000..85b3a78
--- /dev/null
+++ b/net/9p/Makefile
@@ -0,0 +1,13 @@
+obj-$(CONFIG_NET_9P) := 9pnet.o
+
+9pnet-objs := \
+	mod.o \
+	trans_fd.o \
+	mux.o \
+	client.o \
+	conv.o \
+	error.o \
+	fcprint.o \
+	util.o \
+
+9pnet-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/9p/client.c b/net/9p/client.c
new file mode 100644
index 0000000..cb17075
--- /dev/null
+++ b/net/9p/client.c
@@ -0,0 +1,965 @@
+/*
+ * net/9p/clnt.c
+ *
+ * 9P Client
+ *
+ *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <net/9p/9p.h>
+#include <net/9p/transport.h>
+#include <net/9p/conn.h>
+#include <net/9p/client.h>
+
+static struct p9_fid *p9_fid_create(struct p9_client *clnt);
+static void p9_fid_destroy(struct p9_fid *fid);
+static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu);
+
+struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
+								   int dotu)
+{
+	int err, n;
+	struct p9_client *clnt;
+	struct p9_fcall *tc, *rc;
+	struct p9_str *version;
+
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
+	if (!clnt)
+		return ERR_PTR(-ENOMEM);
+
+	P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n",
+		clnt, trans, msize, dotu);
+	spin_lock_init(&clnt->lock);
+	clnt->trans = trans;
+	clnt->msize = msize;
+	clnt->dotu = dotu;
+	INIT_LIST_HEAD(&clnt->fidlist);
+	clnt->fidpool = p9_idpool_create();
+	if (!clnt->fidpool) {
+		err = PTR_ERR(clnt->fidpool);
+		clnt->fidpool = NULL;
+		goto error;
+	}
+
+	clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu);
+	if (IS_ERR(clnt->conn)) {
+		err = PTR_ERR(clnt->conn);
+		clnt->conn = NULL;
+		goto error;
+	}
+
+	tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000");
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto error;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err)
+		goto error;
+
+	version = &rc->params.rversion.version;
+	if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8))
+		clnt->dotu = 1;
+	else if (version->len == 6 && !memcmp(version->str, "9P2000", 6))
+		clnt->dotu = 0;
+	else {
+		err = -EREMOTEIO;
+		goto error;
+	}
+
+	n = rc->params.rversion.msize;
+	if (n < clnt->msize)
+		clnt->msize = n;
+
+	kfree(tc);
+	kfree(rc);
+	return clnt;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	p9_client_destroy(clnt);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_create);
+
+void p9_client_destroy(struct p9_client *clnt)
+{
+	struct p9_fid *fid, *fidptr;
+
+	P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
+	if (clnt->conn) {
+		p9_conn_destroy(clnt->conn);
+		clnt->conn = NULL;
+	}
+
+	if (clnt->trans) {
+		clnt->trans->close(clnt->trans);
+		kfree(clnt->trans);
+		clnt->trans = NULL;
+	}
+
+	list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist)
+		p9_fid_destroy(fid);
+
+	if (clnt->fidpool)
+		p9_idpool_destroy(clnt->fidpool);
+
+	kfree(clnt);
+}
+EXPORT_SYMBOL(p9_client_destroy);
+
+void p9_client_disconnect(struct p9_client *clnt)
+{
+	P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
+	clnt->trans->status = Disconnected;
+	p9_conn_cancel(clnt->conn, -EIO);
+}
+EXPORT_SYMBOL(p9_client_disconnect);
+
+struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
+	char *uname, char *aname)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_fid *fid;
+
+	P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n",
+		clnt, afid?afid->fid:-1, uname, aname);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+
+	fid = p9_fid_create(clnt);
+	if (IS_ERR(fid)) {
+		err = PTR_ERR(fid);
+		fid = NULL;
+		goto error;
+	}
+
+	tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto error;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err)
+		goto error;
+
+	memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid));
+	kfree(tc);
+	kfree(rc);
+	return fid;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	if (fid)
+		p9_fid_destroy(fid);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_attach);
+
+struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_fid *fid;
+
+	P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname,
+									aname);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+
+	fid = p9_fid_create(clnt);
+	if (IS_ERR(fid)) {
+		err = PTR_ERR(fid);
+		fid = NULL;
+		goto error;
+	}
+
+	tc = p9_create_tauth(fid->fid, uname, aname);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto error;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err)
+		goto error;
+
+	memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid));
+	kfree(tc);
+	kfree(rc);
+	return fid;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	if (fid)
+		p9_fid_destroy(fid);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_auth);
+
+struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
+	int clone)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+	struct p9_fid *fid;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n",
+		oldfid->fid, nwname, wnames?wnames[0]:NULL);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = oldfid->clnt;
+	if (clone) {
+		fid = p9_fid_create(clnt);
+		if (IS_ERR(fid)) {
+			err = PTR_ERR(fid);
+			fid = NULL;
+			goto error;
+		}
+
+		fid->uid = oldfid->uid;
+	} else
+		fid = oldfid;
+
+	tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto error;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err) {
+		if (rc && rc->id == P9_RWALK)
+			goto clunk_fid;
+		else
+			goto error;
+	}
+
+	if (rc->params.rwalk.nwqid != nwname) {
+		err = -ENOENT;
+		goto clunk_fid;
+	}
+
+	if (nwname)
+		memmove(&fid->qid,
+			&rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1],
+			sizeof(struct p9_qid));
+	else
+		fid->qid = oldfid->qid;
+
+	kfree(tc);
+	kfree(rc);
+	return fid;
+
+clunk_fid:
+	kfree(tc);
+	kfree(rc);
+	rc = NULL;
+	tc = p9_create_tclunk(fid->fid);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto error;
+	}
+
+	p9_conn_rpc(clnt->conn, tc, &rc);
+
+error:
+	kfree(tc);
+	kfree(rc);
+	if (fid && (fid != oldfid))
+		p9_fid_destroy(fid);
+
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_walk);
+
+int p9_client_open(struct p9_fid *fid, int mode)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+
+	if (fid->mode != -1)
+		return -EINVAL;
+
+	tc = p9_create_topen(fid->fid, mode);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto done;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err)
+		goto done;
+
+	fid->mode = mode;
+	fid->iounit = rc->params.ropen.iounit;
+
+done:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_open);
+
+int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
+		     char *extension)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid,
+		name, perm, mode);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+
+	if (fid->mode != -1)
+		return -EINVAL;
+
+	tc = p9_create_tcreate(fid->fid, name, perm, mode, extension,
+							       clnt->dotu);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto done;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err)
+		goto done;
+
+	fid->mode = mode;
+	fid->iounit = rc->params.ropen.iounit;
+
+done:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_fcreate);
+
+int p9_client_clunk(struct p9_fid *fid)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+
+	tc = p9_create_tclunk(fid->fid);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto done;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err)
+		goto done;
+
+	p9_fid_destroy(fid);
+
+done:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_clunk);
+
+int p9_client_remove(struct p9_fid *fid)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+
+	tc = p9_create_tremove(fid->fid);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto done;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err)
+		goto done;
+
+	p9_fid_destroy(fid);
+
+done:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_remove);
+
+int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count)
+{
+	int err, n, rsize, total;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid,
+					(long long unsigned) offset, count);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+	total = 0;
+
+	rsize = fid->iounit;
+	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+		rsize = clnt->msize - P9_IOHDRSZ;
+
+	do {
+		if (count < rsize)
+			rsize = count;
+
+		tc = p9_create_tread(fid->fid, offset, rsize);
+		if (IS_ERR(tc)) {
+			err = PTR_ERR(tc);
+			tc = NULL;
+			goto error;
+		}
+
+		err = p9_conn_rpc(clnt->conn, tc, &rc);
+		if (err)
+			goto error;
+
+		n = rc->params.rread.count;
+		if (n > count)
+			n = count;
+
+		memmove(data, rc->params.rread.data, n);
+		count -= n;
+		data += n;
+		offset += n;
+		total += n;
+		kfree(tc);
+		tc = NULL;
+		kfree(rc);
+		rc = NULL;
+	} while (count > 0 && n == rsize);
+
+	return total;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_read);
+
+int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count)
+{
+	int err, n, rsize, total;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+					(long long unsigned) offset, count);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+	total = 0;
+
+	rsize = fid->iounit;
+	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+		rsize = clnt->msize - P9_IOHDRSZ;
+
+	do {
+		if (count < rsize)
+			rsize = count;
+
+		tc = p9_create_twrite(fid->fid, offset, rsize, data);
+		if (IS_ERR(tc)) {
+			err = PTR_ERR(tc);
+			tc = NULL;
+			goto error;
+		}
+
+		err = p9_conn_rpc(clnt->conn, tc, &rc);
+		if (err)
+			goto error;
+
+		n = rc->params.rread.count;
+		count -= n;
+		data += n;
+		offset += n;
+		total += n;
+		kfree(tc);
+		tc = NULL;
+		kfree(rc);
+		rc = NULL;
+	} while (count > 0);
+
+	return total;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_write);
+
+int
+p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count)
+{
+	int err, n, rsize, total;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+					(long long unsigned) offset, count);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+	total = 0;
+
+	rsize = fid->iounit;
+	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+		rsize = clnt->msize - P9_IOHDRSZ;
+
+	do {
+		if (count < rsize)
+			rsize = count;
+
+		tc = p9_create_tread(fid->fid, offset, rsize);
+		if (IS_ERR(tc)) {
+			err = PTR_ERR(tc);
+			tc = NULL;
+			goto error;
+		}
+
+		err = p9_conn_rpc(clnt->conn, tc, &rc);
+		if (err)
+			goto error;
+
+		n = rc->params.rread.count;
+		if (n > count)
+			n = count;
+
+		err = copy_to_user(data, rc->params.rread.data, n);
+		if (err) {
+			err = -EFAULT;
+			goto error;
+		}
+
+		count -= n;
+		data += n;
+		offset += n;
+		total += n;
+		kfree(tc);
+		tc = NULL;
+		kfree(rc);
+		rc = NULL;
+	} while (count > 0 && n == rsize);
+
+	return total;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_uread);
+
+int
+p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
+								   u32 count)
+{
+	int err, n, rsize, total;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+					(long long unsigned) offset, count);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+	total = 0;
+
+	rsize = fid->iounit;
+	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+		rsize = clnt->msize - P9_IOHDRSZ;
+
+	do {
+		if (count < rsize)
+			rsize = count;
+
+		tc = p9_create_twrite_u(fid->fid, offset, rsize, data);
+		if (IS_ERR(tc)) {
+			err = PTR_ERR(tc);
+			tc = NULL;
+			goto error;
+		}
+
+		err = p9_conn_rpc(clnt->conn, tc, &rc);
+		if (err)
+			goto error;
+
+		n = rc->params.rread.count;
+		count -= n;
+		data += n;
+		offset += n;
+		total += n;
+		kfree(tc);
+		tc = NULL;
+		kfree(rc);
+		rc = NULL;
+	} while (count > 0);
+
+	return total;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_uwrite);
+
+int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
+{
+	int n, total;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+					(long long unsigned) offset, count);
+	n = 0;
+	total = 0;
+	while (count) {
+		n = p9_client_read(fid, data, offset, count);
+		if (n <= 0)
+			break;
+
+		data += n;
+		offset += n;
+		count -= n;
+		total += n;
+	}
+
+	if (n < 0)
+		total = n;
+
+	return total;
+}
+EXPORT_SYMBOL(p9_client_readn);
+
+struct p9_stat *p9_client_stat(struct p9_fid *fid)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+	struct p9_stat *ret;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	ret = NULL;
+	clnt = fid->clnt;
+
+	tc = p9_create_tstat(fid->fid);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto error;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+	if (err)
+		goto error;
+
+	ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu);
+	if (IS_ERR(ret)) {
+		err = PTR_ERR(ret);
+		ret = NULL;
+		goto error;
+	}
+
+	kfree(tc);
+	kfree(rc);
+	return ret;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	kfree(ret);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_stat);
+
+int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
+{
+	int err;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	clnt = fid->clnt;
+
+	tc = p9_create_twstat(fid->fid, wst, clnt->dotu);
+	if (IS_ERR(tc)) {
+		err = PTR_ERR(tc);
+		tc = NULL;
+		goto done;
+	}
+
+	err = p9_conn_rpc(clnt->conn, tc, &rc);
+
+done:
+	kfree(tc);
+	kfree(rc);
+	return err;
+}
+EXPORT_SYMBOL(p9_client_wstat);
+
+struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset)
+{
+	int err, n, m;
+	struct p9_fcall *tc, *rc;
+	struct p9_client *clnt;
+	struct p9_stat st, *ret;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu\n", fid->fid,
+						(long long unsigned) offset);
+	err = 0;
+	tc = NULL;
+	rc = NULL;
+	ret = NULL;
+	clnt = fid->clnt;
+
+	/* if the offset is below or above the current response, free it */
+	if (offset < fid->rdir_fpos || (fid->rdir_fcall &&
+		offset >= fid->rdir_fpos+fid->rdir_fcall->params.rread.count)) {
+		fid->rdir_pos = 0;
+		if (fid->rdir_fcall)
+			fid->rdir_fpos += fid->rdir_fcall->params.rread.count;
+
+		kfree(fid->rdir_fcall);
+		fid->rdir_fcall = NULL;
+		if (offset < fid->rdir_fpos)
+			fid->rdir_fpos = 0;
+	}
+
+	if (!fid->rdir_fcall) {
+		n = fid->iounit;
+		if (!n || n > clnt->msize-P9_IOHDRSZ)
+			n = clnt->msize - P9_IOHDRSZ;
+
+		while (1) {
+			if (fid->rdir_fcall) {
+				fid->rdir_fpos +=
+					fid->rdir_fcall->params.rread.count;
+				kfree(fid->rdir_fcall);
+				fid->rdir_fcall = NULL;
+			}
+
+			tc = p9_create_tread(fid->fid, fid->rdir_fpos, n);
+			if (IS_ERR(tc)) {
+				err = PTR_ERR(tc);
+				tc = NULL;
+				goto error;
+			}
+
+			err = p9_conn_rpc(clnt->conn, tc, &rc);
+			if (err)
+				goto error;
+
+			n = rc->params.rread.count;
+			if (n == 0)
+				goto done;
+
+			fid->rdir_fcall = rc;
+			rc = NULL;
+			if (offset >= fid->rdir_fpos &&
+						offset < fid->rdir_fpos+n)
+				break;
+		}
+
+		fid->rdir_pos = 0;
+	}
+
+	m = offset - fid->rdir_fpos;
+	if (m < 0)
+		goto done;
+
+	n = p9_deserialize_stat(fid->rdir_fcall->params.rread.data + m,
+		fid->rdir_fcall->params.rread.count - m, &st, clnt->dotu);
+
+	if (!n) {
+		err = -EIO;
+		goto error;
+	}
+
+	fid->rdir_pos += n;
+	st.size = n;
+	ret = p9_clone_stat(&st, clnt->dotu);
+	if (IS_ERR(ret)) {
+		err = PTR_ERR(ret);
+		ret = NULL;
+		goto error;
+	}
+
+done:
+	kfree(tc);
+	kfree(rc);
+	return ret;
+
+error:
+	kfree(tc);
+	kfree(rc);
+	kfree(ret);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_dirread);
+
+static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
+{
+	int n;
+	char *p;
+	struct p9_stat *ret;
+
+	n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len +
+		st->muid.len;
+
+	if (dotu)
+		n += st->extension.len;
+
+	ret = kmalloc(n, GFP_KERNEL);
+	if (!ret)
+		return ERR_PTR(-ENOMEM);
+
+	memmove(ret, st, sizeof(struct p9_stat));
+	p = ((char *) ret) + sizeof(struct p9_stat);
+	memmove(p, st->name.str, st->name.len);
+	p += st->name.len;
+	memmove(p, st->uid.str, st->uid.len);
+	p += st->uid.len;
+	memmove(p, st->gid.str, st->gid.len);
+	p += st->gid.len;
+	memmove(p, st->muid.str, st->muid.len);
+	p += st->muid.len;
+
+	if (dotu) {
+		memmove(p, st->extension.str, st->extension.len);
+		p += st->extension.len;
+	}
+
+	return ret;
+}
+
+static struct p9_fid *p9_fid_create(struct p9_client *clnt)
+{
+	int err;
+	struct p9_fid *fid;
+
+	P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
+	fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
+	if (!fid)
+		return ERR_PTR(-ENOMEM);
+
+	fid->fid = p9_idpool_get(clnt->fidpool);
+	if (fid->fid < 0) {
+		err = -ENOSPC;
+		goto error;
+	}
+
+	memset(&fid->qid, 0, sizeof(struct p9_qid));
+	fid->mode = -1;
+	fid->rdir_fpos = 0;
+	fid->rdir_pos = 0;
+	fid->rdir_fcall = NULL;
+	fid->uid = current->fsuid;
+	fid->clnt = clnt;
+	fid->aux = NULL;
+
+	spin_lock(&clnt->lock);
+	list_add(&fid->flist, &clnt->fidlist);
+	spin_unlock(&clnt->lock);
+
+	return fid;
+
+error:
+	kfree(fid);
+	return ERR_PTR(err);
+}
+
+static void p9_fid_destroy(struct p9_fid *fid)
+{
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+	clnt = fid->clnt;
+	p9_idpool_put(fid->fid, clnt->fidpool);
+	spin_lock(&clnt->lock);
+	list_del(&fid->flist);
+	spin_unlock(&clnt->lock);
+	kfree(fid->rdir_fcall);
+	kfree(fid);
+}
diff --git a/net/9p/conv.c b/net/9p/conv.c
new file mode 100644
index 0000000..3745117
--- /dev/null
+++ b/net/9p/conv.c
@@ -0,0 +1,903 @@
+/*
+ * net/9p/conv.c
+ *
+ * 9P protocol conversion functions
+ *
+ *  Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/idr.h>
+#include <linux/uaccess.h>
+#include <net/9p/9p.h>
+
+/*
+ * Buffer to help with string parsing
+ */
+struct cbuf {
+	unsigned char *sp;
+	unsigned char *p;
+	unsigned char *ep;
+};
+
+static inline void buf_init(struct cbuf *buf, void *data, int datalen)
+{
+	buf->sp = buf->p = data;
+	buf->ep = data + datalen;
+}
+
+static inline int buf_check_overflow(struct cbuf *buf)
+{
+	return buf->p > buf->ep;
+}
+
+static int buf_check_size(struct cbuf *buf, int len)
+{
+	if (buf->p + len > buf->ep) {
+		if (buf->p < buf->ep) {
+			P9_EPRINTK(KERN_ERR,
+				"buffer overflow: want %d has %d\n", len,
+				(int)(buf->ep - buf->p));
+			dump_stack();
+			buf->p = buf->ep + 1;
+		}
+
+		return 0;
+	}
+
+	return 1;
+}
+
+static void *buf_alloc(struct cbuf *buf, int len)
+{
+	void *ret = NULL;
+
+	if (buf_check_size(buf, len)) {
+		ret = buf->p;
+		buf->p += len;
+	}
+
+	return ret;
+}
+
+static void buf_put_int8(struct cbuf *buf, u8 val)
+{
+	if (buf_check_size(buf, 1)) {
+		buf->p[0] = val;
+		buf->p++;
+	}
+}
+
+static void buf_put_int16(struct cbuf *buf, u16 val)
+{
+	if (buf_check_size(buf, 2)) {
+		*(__le16 *) buf->p = cpu_to_le16(val);
+		buf->p += 2;
+	}
+}
+
+static void buf_put_int32(struct cbuf *buf, u32 val)
+{
+	if (buf_check_size(buf, 4)) {
+		*(__le32 *)buf->p = cpu_to_le32(val);
+		buf->p += 4;
+	}
+}
+
+static void buf_put_int64(struct cbuf *buf, u64 val)
+{
+	if (buf_check_size(buf, 8)) {
+		*(__le64 *)buf->p = cpu_to_le64(val);
+		buf->p += 8;
+	}
+}
+
+static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
+{
+	char *ret;
+
+	ret = NULL;
+	if (buf_check_size(buf, slen + 2)) {
+		buf_put_int16(buf, slen);
+		ret = buf->p;
+		memcpy(buf->p, s, slen);
+		buf->p += slen;
+	}
+
+	return ret;
+}
+
+static inline void buf_put_string(struct cbuf *buf, const char *s)
+{
+	buf_put_stringn(buf, s, strlen(s));
+}
+
+static u8 buf_get_int8(struct cbuf *buf)
+{
+	u8 ret = 0;
+
+	if (buf_check_size(buf, 1)) {
+		ret = buf->p[0];
+		buf->p++;
+	}
+
+	return ret;
+}
+
+static u16 buf_get_int16(struct cbuf *buf)
+{
+	u16 ret = 0;
+
+	if (buf_check_size(buf, 2)) {
+		ret = le16_to_cpu(*(__le16 *)buf->p);
+		buf->p += 2;
+	}
+
+	return ret;
+}
+
+static u32 buf_get_int32(struct cbuf *buf)
+{
+	u32 ret = 0;
+
+	if (buf_check_size(buf, 4)) {
+		ret = le32_to_cpu(*(__le32 *)buf->p);
+		buf->p += 4;
+	}
+
+	return ret;
+}
+
+static u64 buf_get_int64(struct cbuf *buf)
+{
+	u64 ret = 0;
+
+	if (buf_check_size(buf, 8)) {
+		ret = le64_to_cpu(*(__le64 *)buf->p);
+		buf->p += 8;
+	}
+
+	return ret;
+}
+
+static void buf_get_str(struct cbuf *buf, struct p9_str *vstr)
+{
+	vstr->len = buf_get_int16(buf);
+	if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
+		vstr->str = buf->p;
+		buf->p += vstr->len;
+	} else {
+		vstr->len = 0;
+		vstr->str = NULL;
+	}
+}
+
+static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid)
+{
+	qid->type = buf_get_int8(bufp);
+	qid->version = buf_get_int32(bufp);
+	qid->path = buf_get_int64(bufp);
+}
+
+/**
+ * p9_size_wstat - calculate the size of a variable length stat struct
+ * @stat: metadata (stat) structure
+ * @dotu: non-zero if 9P2000.u
+ *
+ */
+
+static int p9_size_wstat(struct p9_wstat *wstat, int dotu)
+{
+	int size = 0;
+
+	if (wstat == NULL) {
+		P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n");
+		return 0;
+	}
+
+	size =			/* 2 + *//* size[2] */
+	    2 +			/* type[2] */
+	    4 +			/* dev[4] */
+	    1 +			/* qid.type[1] */
+	    4 +			/* qid.vers[4] */
+	    8 +			/* qid.path[8] */
+	    4 +			/* mode[4] */
+	    4 +			/* atime[4] */
+	    4 +			/* mtime[4] */
+	    8 +			/* length[8] */
+	    8;			/* minimum sum of string lengths */
+
+	if (wstat->name)
+		size += strlen(wstat->name);
+	if (wstat->uid)
+		size += strlen(wstat->uid);
+	if (wstat->gid)
+		size += strlen(wstat->gid);
+	if (wstat->muid)
+		size += strlen(wstat->muid);
+
+	if (dotu) {
+		size += 4 +	/* n_uid[4] */
+		    4 +		/* n_gid[4] */
+		    4 +		/* n_muid[4] */
+		    2;		/* string length of extension[4] */
+		if (wstat->extension)
+			size += strlen(wstat->extension);
+	}
+
+	return size;
+}
+
+/**
+ * buf_get_stat - safely decode a recieved metadata (stat) structure
+ * @bufp: buffer to deserialize
+ * @stat: metadata (stat) structure
+ * @dotu: non-zero if 9P2000.u
+ *
+ */
+
+static void
+buf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu)
+{
+	stat->size = buf_get_int16(bufp);
+	stat->type = buf_get_int16(bufp);
+	stat->dev = buf_get_int32(bufp);
+	stat->qid.type = buf_get_int8(bufp);
+	stat->qid.version = buf_get_int32(bufp);
+	stat->qid.path = buf_get_int64(bufp);
+	stat->mode = buf_get_int32(bufp);
+	stat->atime = buf_get_int32(bufp);
+	stat->mtime = buf_get_int32(bufp);
+	stat->length = buf_get_int64(bufp);
+	buf_get_str(bufp, &stat->name);
+	buf_get_str(bufp, &stat->uid);
+	buf_get_str(bufp, &stat->gid);
+	buf_get_str(bufp, &stat->muid);
+
+	if (dotu) {
+		buf_get_str(bufp, &stat->extension);
+		stat->n_uid = buf_get_int32(bufp);
+		stat->n_gid = buf_get_int32(bufp);
+		stat->n_muid = buf_get_int32(bufp);
+	}
+}
+
+/**
+ * p9_deserialize_stat - decode a received metadata structure
+ * @buf: buffer to deserialize
+ * @buflen: length of received buffer
+ * @stat: metadata structure to decode into
+ * @dotu: non-zero if 9P2000.u
+ *
+ * Note: stat will point to the buf region.
+ */
+
+int
+p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,
+		int dotu)
+{
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+	unsigned char *p;
+
+	buf_init(bufp, buf, buflen);
+	p = bufp->p;
+	buf_get_stat(bufp, stat, dotu);
+
+	if (buf_check_overflow(bufp))
+		return 0;
+	else
+		return bufp->p - p;
+}
+EXPORT_SYMBOL(p9_deserialize_stat);
+
+/**
+ * deserialize_fcall - unmarshal a response
+ * @buf: recieved buffer
+ * @buflen: length of received buffer
+ * @rcall: fcall structure to populate
+ * @rcalllen: length of fcall structure to populate
+ * @dotu: non-zero if 9P2000.u
+ *
+ */
+
+int
+p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall,
+		       int dotu)
+{
+
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+	int i = 0;
+
+	buf_init(bufp, buf, buflen);
+
+	rcall->size = buf_get_int32(bufp);
+	rcall->id = buf_get_int8(bufp);
+	rcall->tag = buf_get_int16(bufp);
+
+	P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size,
+							rcall->id, rcall->tag);
+
+	switch (rcall->id) {
+	default:
+		P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id);
+		return -EPROTO;
+	case P9_RVERSION:
+		rcall->params.rversion.msize = buf_get_int32(bufp);
+		buf_get_str(bufp, &rcall->params.rversion.version);
+		break;
+	case P9_RFLUSH:
+		break;
+	case P9_RATTACH:
+		rcall->params.rattach.qid.type = buf_get_int8(bufp);
+		rcall->params.rattach.qid.version = buf_get_int32(bufp);
+		rcall->params.rattach.qid.path = buf_get_int64(bufp);
+		break;
+	case P9_RWALK:
+		rcall->params.rwalk.nwqid = buf_get_int16(bufp);
+		if (rcall->params.rwalk.nwqid > P9_MAXWELEM) {
+			P9_EPRINTK(KERN_ERR,
+					"Rwalk with more than %d qids: %d\n",
+					P9_MAXWELEM, rcall->params.rwalk.nwqid);
+			return -EPROTO;
+		}
+
+		for (i = 0; i < rcall->params.rwalk.nwqid; i++)
+			buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]);
+		break;
+	case P9_ROPEN:
+		buf_get_qid(bufp, &rcall->params.ropen.qid);
+		rcall->params.ropen.iounit = buf_get_int32(bufp);
+		break;
+	case P9_RCREATE:
+		buf_get_qid(bufp, &rcall->params.rcreate.qid);
+		rcall->params.rcreate.iounit = buf_get_int32(bufp);
+		break;
+	case P9_RREAD:
+		rcall->params.rread.count = buf_get_int32(bufp);
+		rcall->params.rread.data = bufp->p;
+		buf_check_size(bufp, rcall->params.rread.count);
+		break;
+	case P9_RWRITE:
+		rcall->params.rwrite.count = buf_get_int32(bufp);
+		break;
+	case P9_RCLUNK:
+		break;
+	case P9_RREMOVE:
+		break;
+	case P9_RSTAT:
+		buf_get_int16(bufp);
+		buf_get_stat(bufp, &rcall->params.rstat.stat, dotu);
+		break;
+	case P9_RWSTAT:
+		break;
+	case P9_RERROR:
+		buf_get_str(bufp, &rcall->params.rerror.error);
+		if (dotu)
+			rcall->params.rerror.errno = buf_get_int16(bufp);
+		break;
+	}
+
+	if (buf_check_overflow(bufp)) {
+		P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n");
+		return -EIO;
+	}
+
+	return bufp->p - bufp->sp;
+}
+EXPORT_SYMBOL(p9_deserialize_fcall);
+
+static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p)
+{
+	*p = val;
+	buf_put_int8(bufp, val);
+}
+
+static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p)
+{
+	*p = val;
+	buf_put_int16(bufp, val);
+}
+
+static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p)
+{
+	*p = val;
+	buf_put_int32(bufp, val);
+}
+
+static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p)
+{
+	*p = val;
+	buf_put_int64(bufp, val);
+}
+
+static void
+p9_put_str(struct cbuf *bufp, char *data, struct p9_str *str)
+{
+	int len;
+	char *s;
+
+	if (data)
+		len = strlen(data);
+	else
+		len = 0;
+
+	s = buf_put_stringn(bufp, data, len);
+	if (str) {
+		str->len = len;
+		str->str = s;
+	}
+}
+
+static int
+p9_put_data(struct cbuf *bufp, const char *data, int count,
+		   unsigned char **pdata)
+{
+	*pdata = buf_alloc(bufp, count);
+	memmove(*pdata, data, count);
+	return count;
+}
+
+static int
+p9_put_user_data(struct cbuf *bufp, const char __user *data, int count,
+		   unsigned char **pdata)
+{
+	*pdata = buf_alloc(bufp, count);
+	return copy_from_user(*pdata, data, count);
+}
+
+static void
+p9_put_wstat(struct cbuf *bufp, struct p9_wstat *wstat,
+	       struct p9_stat *stat, int statsz, int dotu)
+{
+	p9_put_int16(bufp, statsz, &stat->size);
+	p9_put_int16(bufp, wstat->type, &stat->type);
+	p9_put_int32(bufp, wstat->dev, &stat->dev);
+	p9_put_int8(bufp, wstat->qid.type, &stat->qid.type);
+	p9_put_int32(bufp, wstat->qid.version, &stat->qid.version);
+	p9_put_int64(bufp, wstat->qid.path, &stat->qid.path);
+	p9_put_int32(bufp, wstat->mode, &stat->mode);
+	p9_put_int32(bufp, wstat->atime, &stat->atime);
+	p9_put_int32(bufp, wstat->mtime, &stat->mtime);
+	p9_put_int64(bufp, wstat->length, &stat->length);
+
+	p9_put_str(bufp, wstat->name, &stat->name);
+	p9_put_str(bufp, wstat->uid, &stat->uid);
+	p9_put_str(bufp, wstat->gid, &stat->gid);
+	p9_put_str(bufp, wstat->muid, &stat->muid);
+
+	if (dotu) {
+		p9_put_str(bufp, wstat->extension, &stat->extension);
+		p9_put_int32(bufp, wstat->n_uid, &stat->n_uid);
+		p9_put_int32(bufp, wstat->n_gid, &stat->n_gid);
+		p9_put_int32(bufp, wstat->n_muid, &stat->n_muid);
+	}
+}
+
+static struct p9_fcall *
+p9_create_common(struct cbuf *bufp, u32 size, u8 id)
+{
+	struct p9_fcall *fc;
+
+	size += 4 + 1 + 2;	/* size[4] id[1] tag[2] */
+	fc = kmalloc(sizeof(struct p9_fcall) + size, GFP_KERNEL);
+	if (!fc)
+		return ERR_PTR(-ENOMEM);
+
+	fc->sdata = (char *)fc + sizeof(*fc);
+
+	buf_init(bufp, (char *)fc->sdata, size);
+	p9_put_int32(bufp, size, &fc->size);
+	p9_put_int8(bufp, id, &fc->id);
+	p9_put_int16(bufp, P9_NOTAG, &fc->tag);
+
+	return fc;
+}
+
+void p9_set_tag(struct p9_fcall *fc, u16 tag)
+{
+	fc->tag = tag;
+	*(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
+}
+EXPORT_SYMBOL(p9_set_tag);
+
+struct p9_fcall *p9_create_tversion(u32 msize, char *version)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	size = 4 + 2 + strlen(version);	/* msize[4] version[s] */
+	fc = p9_create_common(bufp, size, P9_TVERSION);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, msize, &fc->params.tversion.msize);
+	p9_put_str(bufp, version, &fc->params.tversion.version);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tversion);
+
+struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	/* afid[4] uname[s] aname[s] */
+	size = 4 + 2 + strlen(uname) + 2 + strlen(aname);
+	fc = p9_create_common(bufp, size, P9_TAUTH);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, afid, &fc->params.tauth.afid);
+	p9_put_str(bufp, uname, &fc->params.tauth.uname);
+	p9_put_str(bufp, aname, &fc->params.tauth.aname);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tauth);
+
+struct p9_fcall *
+p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	/* fid[4] afid[4] uname[s] aname[s] */
+	size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname);
+	fc = p9_create_common(bufp, size, P9_TATTACH);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.tattach.fid);
+	p9_put_int32(bufp, afid, &fc->params.tattach.afid);
+	p9_put_str(bufp, uname, &fc->params.tattach.uname);
+	p9_put_str(bufp, aname, &fc->params.tattach.aname);
+
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tattach);
+
+struct p9_fcall *p9_create_tflush(u16 oldtag)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	size = 2;		/* oldtag[2] */
+	fc = p9_create_common(bufp, size, P9_TFLUSH);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tflush);
+
+struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
+				     char **wnames)
+{
+	int i, size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	if (nwname > P9_MAXWELEM) {
+		P9_DPRINTK(P9_DEBUG_ERROR, "nwname > %d\n", P9_MAXWELEM);
+		return NULL;
+	}
+
+	size = 4 + 4 + 2;	/* fid[4] newfid[4] nwname[2] ... */
+	for (i = 0; i < nwname; i++) {
+		size += 2 + strlen(wnames[i]);	/* wname[s] */
+	}
+
+	fc = p9_create_common(bufp, size, P9_TWALK);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.twalk.fid);
+	p9_put_int32(bufp, newfid, &fc->params.twalk.newfid);
+	p9_put_int16(bufp, nwname, &fc->params.twalk.nwname);
+	for (i = 0; i < nwname; i++) {
+		p9_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
+	}
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_twalk);
+
+struct p9_fcall *p9_create_topen(u32 fid, u8 mode)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	size = 4 + 1;		/* fid[4] mode[1] */
+	fc = p9_create_common(bufp, size, P9_TOPEN);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.topen.fid);
+	p9_put_int8(bufp, mode, &fc->params.topen.mode);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_topen);
+
+struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
+	char *extension, int dotu)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	/* fid[4] name[s] perm[4] mode[1] */
+	size = 4 + 2 + strlen(name) + 4 + 1;
+	if (dotu) {
+		size += 2 +			/* extension[s] */
+		    (extension == NULL ? 0 : strlen(extension));
+	}
+
+	fc = p9_create_common(bufp, size, P9_TCREATE);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.tcreate.fid);
+	p9_put_str(bufp, name, &fc->params.tcreate.name);
+	p9_put_int32(bufp, perm, &fc->params.tcreate.perm);
+	p9_put_int8(bufp, mode, &fc->params.tcreate.mode);
+	if (dotu)
+		p9_put_str(bufp, extension, &fc->params.tcreate.extension);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tcreate);
+
+struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	size = 4 + 8 + 4;	/* fid[4] offset[8] count[4] */
+	fc = p9_create_common(bufp, size, P9_TREAD);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.tread.fid);
+	p9_put_int64(bufp, offset, &fc->params.tread.offset);
+	p9_put_int32(bufp, count, &fc->params.tread.count);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tread);
+
+struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count,
+				      const char *data)
+{
+	int size, err;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	/* fid[4] offset[8] count[4] data[count] */
+	size = 4 + 8 + 4 + count;
+	fc = p9_create_common(bufp, size, P9_TWRITE);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.twrite.fid);
+	p9_put_int64(bufp, offset, &fc->params.twrite.offset);
+	p9_put_int32(bufp, count, &fc->params.twrite.count);
+	err = p9_put_data(bufp, data, count, &fc->params.twrite.data);
+	if (err) {
+		kfree(fc);
+		fc = ERR_PTR(err);
+	}
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_twrite);
+
+struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count,
+				      const char __user *data)
+{
+	int size, err;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	/* fid[4] offset[8] count[4] data[count] */
+	size = 4 + 8 + 4 + count;
+	fc = p9_create_common(bufp, size, P9_TWRITE);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.twrite.fid);
+	p9_put_int64(bufp, offset, &fc->params.twrite.offset);
+	p9_put_int32(bufp, count, &fc->params.twrite.count);
+	err = p9_put_user_data(bufp, data, count, &fc->params.twrite.data);
+	if (err) {
+		kfree(fc);
+		fc = ERR_PTR(err);
+	}
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_twrite_u);
+
+struct p9_fcall *p9_create_tclunk(u32 fid)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	size = 4;		/* fid[4] */
+	fc = p9_create_common(bufp, size, P9_TCLUNK);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.tclunk.fid);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tclunk);
+
+struct p9_fcall *p9_create_tremove(u32 fid)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	size = 4;		/* fid[4] */
+	fc = p9_create_common(bufp, size, P9_TREMOVE);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.tremove.fid);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tremove);
+
+struct p9_fcall *p9_create_tstat(u32 fid)
+{
+	int size;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	size = 4;		/* fid[4] */
+	fc = p9_create_common(bufp, size, P9_TSTAT);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.tstat.fid);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_tstat);
+
+struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat,
+				      int dotu)
+{
+	int size, statsz;
+	struct p9_fcall *fc;
+	struct cbuf buffer;
+	struct cbuf *bufp = &buffer;
+
+	statsz = p9_size_wstat(wstat, dotu);
+	size = 4 + 2 + 2 + statsz;	/* fid[4] stat[n] */
+	fc = p9_create_common(bufp, size, P9_TWSTAT);
+	if (IS_ERR(fc))
+		goto error;
+
+	p9_put_int32(bufp, fid, &fc->params.twstat.fid);
+	buf_put_int16(bufp, statsz + 2);
+	p9_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, dotu);
+
+	if (buf_check_overflow(bufp)) {
+		kfree(fc);
+		fc = ERR_PTR(-ENOMEM);
+	}
+error:
+	return fc;
+}
+EXPORT_SYMBOL(p9_create_twstat);
diff --git a/net/9p/error.c b/net/9p/error.c
new file mode 100644
index 0000000..ab2458b
--- /dev/null
+++ b/net/9p/error.c
@@ -0,0 +1,240 @@
+/*
+ * linux/fs/9p/error.c
+ *
+ * Error string handling
+ *
+ * Plan 9 uses error strings, Unix uses error numbers.  These functions
+ * try to help manage that and provide for dynamically adding error
+ * mappings.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/errno.h>
+#include <net/9p/9p.h>
+
+struct errormap {
+	char *name;
+	int val;
+
+	int namelen;
+	struct hlist_node list;
+};
+
+#define ERRHASHSZ		32
+static struct hlist_head hash_errmap[ERRHASHSZ];
+
+/* FixMe - reduce to a reasonable size */
+static struct errormap errmap[] = {
+	{"Operation not permitted", EPERM},
+	{"wstat prohibited", EPERM},
+	{"No such file or directory", ENOENT},
+	{"directory entry not found", ENOENT},
+	{"file not found", ENOENT},
+	{"Interrupted system call", EINTR},
+	{"Input/output error", EIO},
+	{"No such device or address", ENXIO},
+	{"Argument list too long", E2BIG},
+	{"Bad file descriptor", EBADF},
+	{"Resource temporarily unavailable", EAGAIN},
+	{"Cannot allocate memory", ENOMEM},
+	{"Permission denied", EACCES},
+	{"Bad address", EFAULT},
+	{"Block device required", ENOTBLK},
+	{"Device or resource busy", EBUSY},
+	{"File exists", EEXIST},
+	{"Invalid cross-device link", EXDEV},
+	{"No such device", ENODEV},
+	{"Not a directory", ENOTDIR},
+	{"Is a directory", EISDIR},
+	{"Invalid argument", EINVAL},
+	{"Too many open files in system", ENFILE},
+	{"Too many open files", EMFILE},
+	{"Text file busy", ETXTBSY},
+	{"File too large", EFBIG},
+	{"No space left on device", ENOSPC},
+	{"Illegal seek", ESPIPE},
+	{"Read-only file system", EROFS},
+	{"Too many links", EMLINK},
+	{"Broken pipe", EPIPE},
+	{"Numerical argument out of domain", EDOM},
+	{"Numerical result out of range", ERANGE},
+	{"Resource deadlock avoided", EDEADLK},
+	{"File name too long", ENAMETOOLONG},
+	{"No locks available", ENOLCK},
+	{"Function not implemented", ENOSYS},
+	{"Directory not empty", ENOTEMPTY},
+	{"Too many levels of symbolic links", ELOOP},
+	{"No message of desired type", ENOMSG},
+	{"Identifier removed", EIDRM},
+	{"No data available", ENODATA},
+	{"Machine is not on the network", ENONET},
+	{"Package not installed", ENOPKG},
+	{"Object is remote", EREMOTE},
+	{"Link has been severed", ENOLINK},
+	{"Communication error on send", ECOMM},
+	{"Protocol error", EPROTO},
+	{"Bad message", EBADMSG},
+	{"File descriptor in bad state", EBADFD},
+	{"Streams pipe error", ESTRPIPE},
+	{"Too many users", EUSERS},
+	{"Socket operation on non-socket", ENOTSOCK},
+	{"Message too long", EMSGSIZE},
+	{"Protocol not available", ENOPROTOOPT},
+	{"Protocol not supported", EPROTONOSUPPORT},
+	{"Socket type not supported", ESOCKTNOSUPPORT},
+	{"Operation not supported", EOPNOTSUPP},
+	{"Protocol family not supported", EPFNOSUPPORT},
+	{"Network is down", ENETDOWN},
+	{"Network is unreachable", ENETUNREACH},
+	{"Network dropped connection on reset", ENETRESET},
+	{"Software caused connection abort", ECONNABORTED},
+	{"Connection reset by peer", ECONNRESET},
+	{"No buffer space available", ENOBUFS},
+	{"Transport endpoint is already connected", EISCONN},
+	{"Transport endpoint is not connected", ENOTCONN},
+	{"Cannot send after transport endpoint shutdown", ESHUTDOWN},
+	{"Connection timed out", ETIMEDOUT},
+	{"Connection refused", ECONNREFUSED},
+	{"Host is down", EHOSTDOWN},
+	{"No route to host", EHOSTUNREACH},
+	{"Operation already in progress", EALREADY},
+	{"Operation now in progress", EINPROGRESS},
+	{"Is a named type file", EISNAM},
+	{"Remote I/O error", EREMOTEIO},
+	{"Disk quota exceeded", EDQUOT},
+/* errors from fossil, vacfs, and u9fs */
+	{"fid unknown or out of range", EBADF},
+	{"permission denied", EACCES},
+	{"file does not exist", ENOENT},
+	{"authentication failed", ECONNREFUSED},
+	{"bad offset in directory read", ESPIPE},
+	{"bad use of fid", EBADF},
+	{"wstat can't convert between files and directories", EPERM},
+	{"directory is not empty", ENOTEMPTY},
+	{"file exists", EEXIST},
+	{"file already exists", EEXIST},
+	{"file or directory already exists", EEXIST},
+	{"fid already in use", EBADF},
+	{"file in use", ETXTBSY},
+	{"i/o error", EIO},
+	{"file already open for I/O", ETXTBSY},
+	{"illegal mode", EINVAL},
+	{"illegal name", ENAMETOOLONG},
+	{"not a directory", ENOTDIR},
+	{"not a member of proposed group", EPERM},
+	{"not owner", EACCES},
+	{"only owner can change group in wstat", EACCES},
+	{"read only file system", EROFS},
+	{"no access to special file", EPERM},
+	{"i/o count too large", EIO},
+	{"unknown group", EINVAL},
+	{"unknown user", EINVAL},
+	{"bogus wstat buffer", EPROTO},
+	{"exclusive use file already open", EAGAIN},
+	{"corrupted directory entry", EIO},
+	{"corrupted file entry", EIO},
+	{"corrupted block label", EIO},
+	{"corrupted meta data", EIO},
+	{"illegal offset", EINVAL},
+	{"illegal path element", ENOENT},
+	{"root of file system is corrupted", EIO},
+	{"corrupted super block", EIO},
+	{"protocol botch", EPROTO},
+	{"file system is full", ENOSPC},
+	{"file is in use", EAGAIN},
+	{"directory entry is not allocated", ENOENT},
+	{"file is read only", EROFS},
+	{"file has been removed", EIDRM},
+	{"only support truncation to zero length", EPERM},
+	{"cannot remove root", EPERM},
+	{"file too big", EFBIG},
+	{"venti i/o error", EIO},
+	/* these are not errors */
+	{"u9fs rhostsauth: no authentication required", 0},
+	{"u9fs authnone: no authentication required", 0},
+	{NULL, -1}
+};
+
+/**
+ * p9_error_init - preload
+ * @errstr: error string
+ *
+ */
+
+int p9_error_init(void)
+{
+	struct errormap *c;
+	int bucket;
+
+	/* initialize hash table */
+	for (bucket = 0; bucket < ERRHASHSZ; bucket++)
+		INIT_HLIST_HEAD(&hash_errmap[bucket]);
+
+	/* load initial error map into hash table */
+	for (c = errmap; c->name != NULL; c++) {
+		c->namelen = strlen(c->name);
+		bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
+		INIT_HLIST_NODE(&c->list);
+		hlist_add_head(&c->list, &hash_errmap[bucket]);
+	}
+
+	return 1;
+}
+EXPORT_SYMBOL(p9_error_init);
+
+/**
+ * errstr2errno - convert error string to error number
+ * @errstr: error string
+ *
+ */
+
+int p9_errstr2errno(char *errstr, int len)
+{
+	int errno;
+	struct hlist_node *p;
+	struct errormap *c;
+	int bucket;
+
+	errno = 0;
+	p = NULL;
+	c = NULL;
+	bucket = jhash(errstr, len, 0) % ERRHASHSZ;
+	hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
+		if (c->namelen == len && !memcmp(c->name, errstr, len)) {
+			errno = c->val;
+			break;
+		}
+	}
+
+	if (errno == 0) {
+		/* TODO: if error isn't found, add it dynamically */
+		errstr[len] = 0;
+		printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
+		       errstr);
+		errno = 1;
+	}
+
+	return -errno;
+}
+EXPORT_SYMBOL(p9_errstr2errno);
diff --git a/net/9p/fcprint.c b/net/9p/fcprint.c
new file mode 100644
index 0000000..b1ae8ec
--- /dev/null
+++ b/net/9p/fcprint.c
@@ -0,0 +1,358 @@
+/*
+ *  net/9p/fcprint.c
+ *
+ *  Print 9P call.
+ *
+ *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <net/9p/9p.h>
+
+#ifdef CONFIG_NET_9P_DEBUG
+
+static int
+p9_printqid(char *buf, int buflen, struct p9_qid *q)
+{
+	int n;
+	char b[10];
+
+	n = 0;
+	if (q->type & P9_QTDIR)
+		b[n++] = 'd';
+	if (q->type & P9_QTAPPEND)
+		b[n++] = 'a';
+	if (q->type & P9_QTAUTH)
+		b[n++] = 'A';
+	if (q->type & P9_QTEXCL)
+		b[n++] = 'l';
+	if (q->type & P9_QTTMP)
+		b[n++] = 't';
+	if (q->type & P9_QTSYMLINK)
+		b[n++] = 'L';
+	b[n] = '\0';
+
+	return scnprintf(buf, buflen, "(%.16llx %x %s)",
+					(long long int) q->path, q->version, b);
+}
+
+static int
+p9_printperm(char *buf, int buflen, int perm)
+{
+	int n;
+	char b[15];
+
+	n = 0;
+	if (perm & P9_DMDIR)
+		b[n++] = 'd';
+	if (perm & P9_DMAPPEND)
+		b[n++] = 'a';
+	if (perm & P9_DMAUTH)
+		b[n++] = 'A';
+	if (perm & P9_DMEXCL)
+		b[n++] = 'l';
+	if (perm & P9_DMTMP)
+		b[n++] = 't';
+	if (perm & P9_DMDEVICE)
+		b[n++] = 'D';
+	if (perm & P9_DMSOCKET)
+		b[n++] = 'S';
+	if (perm & P9_DMNAMEDPIPE)
+		b[n++] = 'P';
+	if (perm & P9_DMSYMLINK)
+		b[n++] = 'L';
+	b[n] = '\0';
+
+	return scnprintf(buf, buflen, "%s%03o", b, perm&077);
+}
+
+static int
+p9_printstat(char *buf, int buflen, struct p9_stat *st, int extended)
+{
+	int n;
+
+	n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len,
+		st->name.str, st->uid.len, st->uid.str);
+	if (extended)
+		n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid);
+
+	n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str);
+	if (extended)
+		n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid);
+
+	n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str);
+	if (extended)
+		n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid);
+
+	n += scnprintf(buf+n, buflen-n, " q ");
+	n += p9_printqid(buf+n, buflen-n, &st->qid);
+	n += scnprintf(buf+n, buflen-n, " m ");
+	n += p9_printperm(buf+n, buflen-n, st->mode);
+	n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld",
+		st->atime, st->mtime, (long long int) st->length);
+
+	if (extended)
+		n += scnprintf(buf+n, buflen-n, " ext '%.*s'",
+			st->extension.len, st->extension.str);
+
+	return n;
+}
+
+static int
+p9_dumpdata(char *buf, int buflen, u8 *data, int datalen)
+{
+	int i, n;
+
+	i = n = 0;
+	while (i < datalen) {
+		n += scnprintf(buf + n, buflen - n, "%02x", data[i]);
+		if (i%4 == 3)
+			n += scnprintf(buf + n, buflen - n, " ");
+		if (i%32 == 31)
+			n += scnprintf(buf + n, buflen - n, "\n");
+
+		i++;
+	}
+	n += scnprintf(buf + n, buflen - n, "\n");
+
+	return n;
+}
+
+static int
+p9_printdata(char *buf, int buflen, u8 *data, int datalen)
+{
+	return p9_dumpdata(buf, buflen, data, datalen < 16?datalen:16);
+}
+
+int
+p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended)
+{
+	int i, ret, type, tag;
+
+	if (!fc)
+		return scnprintf(buf, buflen, "<NULL>");
+
+	type = fc->id;
+	tag = fc->tag;
+
+	ret = 0;
+	switch (type) {
+	case P9_TVERSION:
+		ret += scnprintf(buf+ret, buflen-ret,
+				"Tversion tag %u msize %u version '%.*s'", tag,
+				fc->params.tversion.msize,
+				fc->params.tversion.version.len,
+				fc->params.tversion.version.str);
+		break;
+
+	case P9_RVERSION:
+		ret += scnprintf(buf+ret, buflen-ret,
+				"Rversion tag %u msize %u version '%.*s'", tag,
+				fc->params.rversion.msize,
+				fc->params.rversion.version.len,
+				fc->params.rversion.version.str);
+		break;
+
+	case P9_TAUTH:
+		ret += scnprintf(buf+ret, buflen-ret,
+			"Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag,
+			fc->params.tauth.afid, fc->params.tauth.uname.len,
+			fc->params.tauth.uname.str, fc->params.tauth.aname.len,
+			fc->params.tauth.aname.str);
+		break;
+
+	case P9_RAUTH:
+		ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag);
+		p9_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid);
+		break;
+
+	case P9_TATTACH:
+		ret += scnprintf(buf+ret, buflen-ret,
+		 "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", tag,
+		 fc->params.tattach.fid, fc->params.tattach.afid,
+		 fc->params.tattach.uname.len, fc->params.tattach.uname.str,
+		 fc->params.tattach.aname.len, fc->params.tattach.aname.str);
+		break;
+
+	case P9_RATTACH:
+		ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ",
+									tag);
+		p9_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid);
+		break;
+
+	case P9_RERROR:
+		ret += scnprintf(buf+ret, buflen-ret,
+				"Rerror tag %u ename '%.*s'", tag,
+				fc->params.rerror.error.len,
+				fc->params.rerror.error.str);
+		if (extended)
+			ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n",
+				fc->params.rerror.errno);
+		break;
+
+	case P9_TFLUSH:
+		ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u",
+			tag, fc->params.tflush.oldtag);
+		break;
+
+	case P9_RFLUSH:
+		ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag);
+		break;
+
+	case P9_TWALK:
+		ret += scnprintf(buf+ret, buflen-ret,
+			"Twalk tag %u fid %d newfid %d nwname %d", tag,
+			fc->params.twalk.fid, fc->params.twalk.newfid,
+			fc->params.twalk.nwname);
+		for (i = 0; i < fc->params.twalk.nwname; i++)
+			ret += scnprintf(buf+ret, buflen-ret, " '%.*s'",
+				fc->params.twalk.wnames[i].len,
+				fc->params.twalk.wnames[i].str);
+		break;
+
+	case P9_RWALK:
+		ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d",
+			tag, fc->params.rwalk.nwqid);
+		for (i = 0; i < fc->params.rwalk.nwqid; i++)
+			ret += p9_printqid(buf+ret, buflen-ret,
+				&fc->params.rwalk.wqids[i]);
+		break;
+
+	case P9_TOPEN:
+		ret += scnprintf(buf+ret, buflen-ret,
+			"Topen tag %u fid %d mode %d", tag,
+			fc->params.topen.fid, fc->params.topen.mode);
+		break;
+
+	case P9_ROPEN:
+		ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag);
+		ret += p9_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid);
+		ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
+			fc->params.ropen.iounit);
+		break;
+
+	case P9_TCREATE:
+		ret += scnprintf(buf+ret, buflen-ret,
+			"Tcreate tag %u fid %d name '%.*s' perm ", tag,
+			fc->params.tcreate.fid, fc->params.tcreate.name.len,
+			fc->params.tcreate.name.str);
+
+		ret += p9_printperm(buf+ret, buflen-ret,
+						fc->params.tcreate.perm);
+		ret += scnprintf(buf+ret, buflen-ret, " mode %d",
+			fc->params.tcreate.mode);
+		break;
+
+	case P9_RCREATE:
+		ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag);
+		ret += p9_printqid(buf+ret, buflen-ret,
+						&fc->params.rcreate.qid);
+		ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
+			fc->params.rcreate.iounit);
+		break;
+
+	case P9_TREAD:
+		ret += scnprintf(buf+ret, buflen-ret,
+			"Tread tag %u fid %d offset %lld count %u", tag,
+			fc->params.tread.fid,
+			(long long int) fc->params.tread.offset,
+			fc->params.tread.count);
+		break;
+
+	case P9_RREAD:
+		ret += scnprintf(buf+ret, buflen-ret,
+			"Rread tag %u count %u data ", tag,
+			fc->params.rread.count);
+		ret += p9_printdata(buf+ret, buflen-ret, fc->params.rread.data,
+			fc->params.rread.count);
+		break;
+
+	case P9_TWRITE:
+		ret += scnprintf(buf+ret, buflen-ret,
+			"Twrite tag %u fid %d offset %lld count %u data ",
+			tag, fc->params.twrite.fid,
+			(long long int) fc->params.twrite.offset,
+			fc->params.twrite.count);
+		ret += p9_printdata(buf+ret, buflen-ret, fc->params.twrite.data,
+			fc->params.twrite.count);
+		break;
+
+	case P9_RWRITE:
+		ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u",
+			tag, fc->params.rwrite.count);
+		break;
+
+	case P9_TCLUNK:
+		ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d",
+			tag, fc->params.tclunk.fid);
+		break;
+
+	case P9_RCLUNK:
+		ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag);
+		break;
+
+	case P9_TREMOVE:
+		ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d",
+			tag, fc->params.tremove.fid);
+		break;
+
+	case P9_RREMOVE:
+		ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag);
+		break;
+
+	case P9_TSTAT:
+		ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d",
+			tag, fc->params.tstat.fid);
+		break;
+
+	case P9_RSTAT:
+		ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag);
+		ret += p9_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat,
+			extended);
+		break;
+
+	case P9_TWSTAT:
+		ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ",
+			tag, fc->params.twstat.fid);
+		ret += p9_printstat(buf+ret, buflen-ret,
+					&fc->params.twstat.stat, extended);
+		break;
+
+	case P9_RWSTAT:
+		ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag);
+		break;
+
+	default:
+		ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type);
+		break;
+	}
+
+	return ret;
+}
+
+#else
+int
+p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended)
+{
+	return 0;
+}
+EXPORT_SYMBOL(p9_printfcall);
+#endif /* CONFIG_NET_9P_DEBUG */
diff --git a/net/9p/mod.c b/net/9p/mod.c
new file mode 100644
index 0000000..4f9e1d2
--- /dev/null
+++ b/net/9p/mod.c
@@ -0,0 +1,85 @@
+/*
+ *  net/9p/9p.c
+ *
+ *  9P entry point
+ *
+ *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <net/9p/9p.h>
+
+#ifdef CONFIG_NET_9P_DEBUG
+unsigned int p9_debug_level = 0;	/* feature-rific global debug level  */
+EXPORT_SYMBOL(p9_debug_level);
+module_param_named(debug, p9_debug_level, uint, 0);
+MODULE_PARM_DESC(debug, "9P debugging level");
+#endif
+
+extern int p9_mux_global_init(void);
+extern void p9_mux_global_exit(void);
+extern int p9_sysctl_register(void);
+extern void p9_sysctl_unregister(void);
+
+/**
+ * v9fs_init - Initialize module
+ *
+ */
+static int __init init_p9(void)
+{
+	int ret;
+
+	p9_error_init();
+	printk(KERN_INFO "Installing 9P2000 support\n");
+	ret = p9_mux_global_init();
+	if (ret) {
+		printk(KERN_WARNING "9p: starting mux failed\n");
+		return ret;
+	}
+
+	ret = p9_sysctl_register();
+	if (ret) {
+		printk(KERN_WARNING "9p: registering sysctl failed\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+/**
+ * v9fs_init - shutdown module
+ *
+ */
+
+static void __exit exit_p9(void)
+{
+	p9_sysctl_unregister();
+	p9_mux_global_exit();
+}
+
+module_init(init_p9)
+module_exit(exit_p9)
+
+MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
+MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
+MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
+MODULE_LICENSE("GPL");
diff --git a/net/9p/mux.c b/net/9p/mux.c
new file mode 100644
index 0000000..acb0388
--- /dev/null
+++ b/net/9p/mux.c
@@ -0,0 +1,1054 @@
+/*
+ * net/9p/mux.c
+ *
+ * Protocol Multiplexer
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/kthread.h>
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <net/9p/9p.h>
+#include <net/9p/transport.h>
+#include <net/9p/conn.h>
+
+#define ERREQFLUSH	1
+#define SCHED_TIMEOUT	10
+#define MAXPOLLWADDR	2
+
+enum {
+	Rworksched = 1,		/* read work scheduled or running */
+	Rpending = 2,		/* can read */
+	Wworksched = 4,		/* write work scheduled or running */
+	Wpending = 8,		/* can write */
+};
+
+enum {
+	None,
+	Flushing,
+	Flushed,
+};
+
+struct p9_mux_poll_task;
+
+struct p9_req {
+	spinlock_t lock; /* protect request structure */
+	int tag;
+	struct p9_fcall *tcall;
+	struct p9_fcall *rcall;
+	int err;
+	p9_conn_req_callback cb;
+	void *cba;
+	int flush;
+	struct list_head req_list;
+};
+
+struct p9_conn {
+	spinlock_t lock; /* protect lock structure */
+	struct list_head mux_list;
+	struct p9_mux_poll_task *poll_task;
+	int msize;
+	unsigned char *extended;
+	struct p9_transport *trans;
+	struct p9_idpool *tagpool;
+	int err;
+	wait_queue_head_t equeue;
+	struct list_head req_list;
+	struct list_head unsent_req_list;
+	struct p9_fcall *rcall;
+	int rpos;
+	char *rbuf;
+	int wpos;
+	int wsize;
+	char *wbuf;
+	wait_queue_t poll_wait[MAXPOLLWADDR];
+	wait_queue_head_t *poll_waddr[MAXPOLLWADDR];
+	poll_table pt;
+	struct work_struct rq;
+	struct work_struct wq;
+	unsigned long wsched;
+};
+
+struct p9_mux_poll_task {
+	struct task_struct *task;
+	struct list_head mux_list;
+	int muxnum;
+};
+
+struct p9_mux_rpc {
+	struct p9_conn *m;
+	int err;
+	struct p9_fcall *tcall;
+	struct p9_fcall *rcall;
+	wait_queue_head_t wqueue;
+};
+
+static int p9_poll_proc(void *);
+static void p9_read_work(struct work_struct *work);
+static void p9_write_work(struct work_struct *work);
+static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address,
+			  poll_table * p);
+static u16 p9_mux_get_tag(struct p9_conn *);
+static void p9_mux_put_tag(struct p9_conn *, u16);
+
+static DEFINE_MUTEX(p9_mux_task_lock);
+static struct workqueue_struct *p9_mux_wq;
+
+static int p9_mux_num;
+static int p9_mux_poll_task_num;
+static struct p9_mux_poll_task p9_mux_poll_tasks[100];
+
+int p9_mux_global_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++)
+		p9_mux_poll_tasks[i].task = NULL;
+
+	p9_mux_wq = create_workqueue("v9fs");
+	if (!p9_mux_wq) {
+		printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void p9_mux_global_exit(void)
+{
+	destroy_workqueue(p9_mux_wq);
+}
+
+/**
+ * p9_mux_calc_poll_procs - calculates the number of polling procs
+ * based on the number of mounted v9fs filesystems.
+ *
+ * The current implementation returns sqrt of the number of mounts.
+ */
+static int p9_mux_calc_poll_procs(int muxnum)
+{
+	int n;
+
+	if (p9_mux_poll_task_num)
+		n = muxnum / p9_mux_poll_task_num +
+		    (muxnum % p9_mux_poll_task_num ? 1 : 0);
+	else
+		n = 1;
+
+	if (n > ARRAY_SIZE(p9_mux_poll_tasks))
+		n = ARRAY_SIZE(p9_mux_poll_tasks);
+
+	return n;
+}
+
+static int p9_mux_poll_start(struct p9_conn *m)
+{
+	int i, n;
+	struct p9_mux_poll_task *vpt, *vptlast;
+	struct task_struct *pproc;
+
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, p9_mux_num,
+		p9_mux_poll_task_num);
+	mutex_lock(&p9_mux_task_lock);
+
+	n = p9_mux_calc_poll_procs(p9_mux_num + 1);
+	if (n > p9_mux_poll_task_num) {
+		for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) {
+			if (p9_mux_poll_tasks[i].task == NULL) {
+				vpt = &p9_mux_poll_tasks[i];
+				P9_DPRINTK(P9_DEBUG_MUX, "create proc %p\n",
+									vpt);
+				pproc = kthread_create(p9_poll_proc, vpt,
+								"v9fs-poll");
+
+				if (!IS_ERR(pproc)) {
+					vpt->task = pproc;
+					INIT_LIST_HEAD(&vpt->mux_list);
+					vpt->muxnum = 0;
+					p9_mux_poll_task_num++;
+					wake_up_process(vpt->task);
+				}
+				break;
+			}
+		}
+
+		if (i >= ARRAY_SIZE(p9_mux_poll_tasks))
+			P9_DPRINTK(P9_DEBUG_ERROR,
+					"warning: no free poll slots\n");
+	}
+
+	n = (p9_mux_num + 1) / p9_mux_poll_task_num +
+	    ((p9_mux_num + 1) % p9_mux_poll_task_num ? 1 : 0);
+
+	vptlast = NULL;
+	for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) {
+		vpt = &p9_mux_poll_tasks[i];
+		if (vpt->task != NULL) {
+			vptlast = vpt;
+			if (vpt->muxnum < n) {
+				P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i);
+				list_add(&m->mux_list, &vpt->mux_list);
+				vpt->muxnum++;
+				m->poll_task = vpt;
+				memset(&m->poll_waddr, 0,
+							sizeof(m->poll_waddr));
+				init_poll_funcptr(&m->pt, p9_pollwait);
+				break;
+			}
+		}
+	}
+
+	if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) {
+		if (vptlast == NULL)
+			return -ENOMEM;
+
+		P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i);
+		list_add(&m->mux_list, &vptlast->mux_list);
+		vptlast->muxnum++;
+		m->poll_task = vptlast;
+		memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
+		init_poll_funcptr(&m->pt, p9_pollwait);
+	}
+
+	p9_mux_num++;
+	mutex_unlock(&p9_mux_task_lock);
+
+	return 0;
+}
+
+static void p9_mux_poll_stop(struct p9_conn *m)
+{
+	int i;
+	struct p9_mux_poll_task *vpt;
+
+	mutex_lock(&p9_mux_task_lock);
+	vpt = m->poll_task;
+	list_del(&m->mux_list);
+	for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
+		if (m->poll_waddr[i] != NULL) {
+			remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]);
+			m->poll_waddr[i] = NULL;
+		}
+	}
+	vpt->muxnum--;
+	if (!vpt->muxnum) {
+		P9_DPRINTK(P9_DEBUG_MUX, "destroy proc %p\n", vpt);
+		kthread_stop(vpt->task);
+		vpt->task = NULL;
+		p9_mux_poll_task_num--;
+	}
+	p9_mux_num--;
+	mutex_unlock(&p9_mux_task_lock);
+}
+
+/**
+ * p9_conn_create - allocate and initialize the per-session mux data
+ * Creates the polling task if this is the first session.
+ *
+ * @trans - transport structure
+ * @msize - maximum message size
+ * @extended - pointer to the extended flag
+ */
+struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
+				    unsigned char *extended)
+{
+	int i, n;
+	struct p9_conn *m, *mtmp;
+
+	P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, msize);
+	m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL);
+	if (!m)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock_init(&m->lock);
+	INIT_LIST_HEAD(&m->mux_list);
+	m->msize = msize;
+	m->extended = extended;
+	m->trans = trans;
+	m->tagpool = p9_idpool_create();
+	if (!m->tagpool) {
+		kfree(m);
+		return ERR_PTR(PTR_ERR(m->tagpool));
+	}
+
+	m->err = 0;
+	init_waitqueue_head(&m->equeue);
+	INIT_LIST_HEAD(&m->req_list);
+	INIT_LIST_HEAD(&m->unsent_req_list);
+	m->rcall = NULL;
+	m->rpos = 0;
+	m->rbuf = NULL;
+	m->wpos = m->wsize = 0;
+	m->wbuf = NULL;
+	INIT_WORK(&m->rq, p9_read_work);
+	INIT_WORK(&m->wq, p9_write_work);
+	m->wsched = 0;
+	memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
+	m->poll_task = NULL;
+	n = p9_mux_poll_start(m);
+	if (n)
+		return ERR_PTR(n);
+
+	n = trans->poll(trans, &m->pt);
+	if (n & POLLIN) {
+		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
+		set_bit(Rpending, &m->wsched);
+	}
+
+	if (n & POLLOUT) {
+		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
+		set_bit(Wpending, &m->wsched);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
+		if (IS_ERR(m->poll_waddr[i])) {
+			p9_mux_poll_stop(m);
+			mtmp = (void *)m->poll_waddr;	/* the error code */
+			kfree(m);
+			m = mtmp;
+			break;
+		}
+	}
+
+	return m;
+}
+EXPORT_SYMBOL(p9_conn_create);
+
+/**
+ * p9_mux_destroy - cancels all pending requests and frees mux resources
+ */
+void p9_conn_destroy(struct p9_conn *m)
+{
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m,
+		m->mux_list.prev, m->mux_list.next);
+	p9_conn_cancel(m, -ECONNRESET);
+
+	if (!list_empty(&m->req_list)) {
+		/* wait until all processes waiting on this session exit */
+		P9_DPRINTK(P9_DEBUG_MUX,
+			"mux %p waiting for empty request queue\n", m);
+		wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000);
+		P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m,
+			list_empty(&m->req_list));
+	}
+
+	p9_mux_poll_stop(m);
+	m->trans = NULL;
+	p9_idpool_destroy(m->tagpool);
+	kfree(m);
+}
+EXPORT_SYMBOL(p9_conn_destroy);
+
+/**
+ * p9_pollwait - called by files poll operation to add v9fs-poll task
+ * 	to files wait queue
+ */
+static void
+p9_pollwait(struct file *filp, wait_queue_head_t *wait_address,
+	      poll_table * p)
+{
+	int i;
+	struct p9_conn *m;
+
+	m = container_of(p, struct p9_conn, pt);
+	for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++)
+		if (m->poll_waddr[i] == NULL)
+			break;
+
+	if (i >= ARRAY_SIZE(m->poll_waddr)) {
+		P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n");
+		return;
+	}
+
+	m->poll_waddr[i] = wait_address;
+
+	if (!wait_address) {
+		P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n");
+		m->poll_waddr[i] = ERR_PTR(-EIO);
+		return;
+	}
+
+	init_waitqueue_entry(&m->poll_wait[i], m->poll_task->task);
+	add_wait_queue(wait_address, &m->poll_wait[i]);
+}
+
+/**
+ * p9_poll_mux - polls a mux and schedules read or write works if necessary
+ */
+static void p9_poll_mux(struct p9_conn *m)
+{
+	int n;
+
+	if (m->err < 0)
+		return;
+
+	n = m->trans->poll(m->trans, NULL);
+	if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
+		P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n);
+		if (n >= 0)
+			n = -ECONNRESET;
+		p9_conn_cancel(m, n);
+	}
+
+	if (n & POLLIN) {
+		set_bit(Rpending, &m->wsched);
+		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
+		if (!test_and_set_bit(Rworksched, &m->wsched)) {
+			P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
+			queue_work(p9_mux_wq, &m->rq);
+		}
+	}
+
+	if (n & POLLOUT) {
+		set_bit(Wpending, &m->wsched);
+		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
+		if ((m->wsize || !list_empty(&m->unsent_req_list))
+		    && !test_and_set_bit(Wworksched, &m->wsched)) {
+			P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
+			queue_work(p9_mux_wq, &m->wq);
+		}
+	}
+}
+
+/**
+ * p9_poll_proc - polls all v9fs transports for new events and queues
+ * 	the appropriate work to the work queue
+ */
+static int p9_poll_proc(void *a)
+{
+	struct p9_conn *m, *mtmp;
+	struct p9_mux_poll_task *vpt;
+
+	vpt = a;
+	P9_DPRINTK(P9_DEBUG_MUX, "start %p %p\n", current, vpt);
+	while (!kthread_should_stop()) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) {
+			p9_poll_mux(m);
+		}
+
+		P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n");
+		schedule_timeout(SCHED_TIMEOUT * HZ);
+	}
+
+	__set_current_state(TASK_RUNNING);
+	P9_DPRINTK(P9_DEBUG_MUX, "finish\n");
+	return 0;
+}
+
+/**
+ * p9_write_work - called when a transport can send some data
+ */
+static void p9_write_work(struct work_struct *work)
+{
+	int n, err;
+	struct p9_conn *m;
+	struct p9_req *req;
+
+	m = container_of(work, struct p9_conn, wq);
+
+	if (m->err < 0) {
+		clear_bit(Wworksched, &m->wsched);
+		return;
+	}
+
+	if (!m->wsize) {
+		if (list_empty(&m->unsent_req_list)) {
+			clear_bit(Wworksched, &m->wsched);
+			return;
+		}
+
+		spin_lock(&m->lock);
+again:
+		req = list_entry(m->unsent_req_list.next, struct p9_req,
+			       req_list);
+		list_move_tail(&req->req_list, &m->req_list);
+		if (req->err == ERREQFLUSH)
+			goto again;
+
+		m->wbuf = req->tcall->sdata;
+		m->wsize = req->tcall->size;
+		m->wpos = 0;
+		spin_unlock(&m->lock);
+	}
+
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos,
+								m->wsize);
+	clear_bit(Wpending, &m->wsched);
+	err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos);
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
+	if (err == -EAGAIN) {
+		clear_bit(Wworksched, &m->wsched);
+		return;
+	}
+
+	if (err < 0)
+		goto error;
+	else if (err == 0) {
+		err = -EREMOTEIO;
+		goto error;
+	}
+
+	m->wpos += err;
+	if (m->wpos == m->wsize)
+		m->wpos = m->wsize = 0;
+
+	if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
+		if (test_and_clear_bit(Wpending, &m->wsched))
+			n = POLLOUT;
+		else
+			n = m->trans->poll(m->trans, NULL);
+
+		if (n & POLLOUT) {
+			P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
+			queue_work(p9_mux_wq, &m->wq);
+		} else
+			clear_bit(Wworksched, &m->wsched);
+	} else
+		clear_bit(Wworksched, &m->wsched);
+
+	return;
+
+error:
+	p9_conn_cancel(m, err);
+	clear_bit(Wworksched, &m->wsched);
+}
+
+static void process_request(struct p9_conn *m, struct p9_req *req)
+{
+	int ecode;
+	struct p9_str *ename;
+
+	if (!req->err && req->rcall->id == P9_RERROR) {
+		ecode = req->rcall->params.rerror.errno;
+		ename = &req->rcall->params.rerror.error;
+
+		P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
+								ename->str);
+
+		if (*m->extended)
+			req->err = -ecode;
+
+		if (!req->err) {
+			req->err = p9_errstr2errno(ename->str, ename->len);
+
+			if (!req->err) {	/* string match failed */
+				PRINT_FCALL_ERROR("unknown error", req->rcall);
+			}
+
+			if (!req->err)
+				req->err = -ESERVERFAULT;
+		}
+	} else if (req->tcall && req->rcall->id != req->tcall->id + 1) {
+		P9_DPRINTK(P9_DEBUG_ERROR,
+				"fcall mismatch: expected %d, got %d\n",
+				req->tcall->id + 1, req->rcall->id);
+		if (!req->err)
+			req->err = -EIO;
+	}
+}
+
+/**
+ * p9_read_work - called when there is some data to be read from a transport
+ */
+static void p9_read_work(struct work_struct *work)
+{
+	int n, err;
+	struct p9_conn *m;
+	struct p9_req *req, *rptr, *rreq;
+	struct p9_fcall *rcall;
+	char *rbuf;
+
+	m = container_of(work, struct p9_conn, rq);
+
+	if (m->err < 0)
+		return;
+
+	rcall = NULL;
+	P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
+
+	if (!m->rcall) {
+		m->rcall =
+		    kmalloc(sizeof(struct p9_fcall) + m->msize, GFP_KERNEL);
+		if (!m->rcall) {
+			err = -ENOMEM;
+			goto error;
+		}
+
+		m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
+		m->rpos = 0;
+	}
+
+	clear_bit(Rpending, &m->wsched);
+	err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos);
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err);
+	if (err == -EAGAIN) {
+		clear_bit(Rworksched, &m->wsched);
+		return;
+	}
+
+	if (err <= 0)
+		goto error;
+
+	m->rpos += err;
+	while (m->rpos > 4) {
+		n = le32_to_cpu(*(__le32 *) m->rbuf);
+		if (n >= m->msize) {
+			P9_DPRINTK(P9_DEBUG_ERROR,
+				"requested packet size too big: %d\n", n);
+			err = -EIO;
+			goto error;
+		}
+
+		if (m->rpos < n)
+			break;
+
+		err =
+		    p9_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended);
+		if (err < 0) {
+			goto error;
+		}
+
+#ifdef CONFIG_NET_9P_DEBUG
+		if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
+			char buf[150];
+
+			p9_printfcall(buf, sizeof(buf), m->rcall,
+				*m->extended);
+			printk(KERN_NOTICE ">>> %p %s\n", m, buf);
+		}
+#endif
+
+		rcall = m->rcall;
+		rbuf = m->rbuf;
+		if (m->rpos > n) {
+			m->rcall = kmalloc(sizeof(struct p9_fcall) + m->msize,
+					   GFP_KERNEL);
+			if (!m->rcall) {
+				err = -ENOMEM;
+				goto error;
+			}
+
+			m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
+			memmove(m->rbuf, rbuf + n, m->rpos - n);
+			m->rpos -= n;
+		} else {
+			m->rcall = NULL;
+			m->rbuf = NULL;
+			m->rpos = 0;
+		}
+
+		P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m,
+							rcall->id, rcall->tag);
+
+		req = NULL;
+		spin_lock(&m->lock);
+		list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
+			if (rreq->tag == rcall->tag) {
+				req = rreq;
+				if (req->flush != Flushing)
+					list_del(&req->req_list);
+				break;
+			}
+		}
+		spin_unlock(&m->lock);
+
+		if (req) {
+			req->rcall = rcall;
+			process_request(m, req);
+
+			if (req->flush != Flushing) {
+				if (req->cb)
+					(*req->cb) (req, req->cba);
+				else
+					kfree(req->rcall);
+
+				wake_up(&m->equeue);
+			}
+		} else {
+			if (err >= 0 && rcall->id != P9_RFLUSH)
+				P9_DPRINTK(P9_DEBUG_ERROR,
+				  "unexpected response mux %p id %d tag %d\n",
+				  m, rcall->id, rcall->tag);
+			kfree(rcall);
+		}
+	}
+
+	if (!list_empty(&m->req_list)) {
+		if (test_and_clear_bit(Rpending, &m->wsched))
+			n = POLLIN;
+		else
+			n = m->trans->poll(m->trans, NULL);
+
+		if (n & POLLIN) {
+			P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
+			queue_work(p9_mux_wq, &m->rq);
+		} else
+			clear_bit(Rworksched, &m->wsched);
+	} else
+		clear_bit(Rworksched, &m->wsched);
+
+	return;
+
+error:
+	p9_conn_cancel(m, err);
+	clear_bit(Rworksched, &m->wsched);
+}
+
+/**
+ * p9_send_request - send 9P request
+ * The function can sleep until the request is scheduled for sending.
+ * The function can be interrupted. Return from the function is not
+ * a guarantee that the request is sent successfully. Can return errors
+ * that can be retrieved by PTR_ERR macros.
+ *
+ * @m: mux data
+ * @tc: request to be sent
+ * @cb: callback function to call when response is received
+ * @cba: parameter to pass to the callback function
+ */
+static struct p9_req *p9_send_request(struct p9_conn *m,
+					  struct p9_fcall *tc,
+					  p9_conn_req_callback cb, void *cba)
+{
+	int n;
+	struct p9_req *req;
+
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
+		tc, tc->id);
+	if (m->err < 0)
+		return ERR_PTR(m->err);
+
+	req = kmalloc(sizeof(struct p9_req), GFP_KERNEL);
+	if (!req)
+		return ERR_PTR(-ENOMEM);
+
+	if (tc->id == P9_TVERSION)
+		n = P9_NOTAG;
+	else
+		n = p9_mux_get_tag(m);
+
+	if (n < 0)
+		return ERR_PTR(-ENOMEM);
+
+	p9_set_tag(tc, n);
+
+#ifdef CONFIG_NET_9P_DEBUG
+	if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
+		char buf[150];
+
+		p9_printfcall(buf, sizeof(buf), tc, *m->extended);
+		printk(KERN_NOTICE "<<< %p %s\n", m, buf);
+	}
+#endif
+
+	spin_lock_init(&req->lock);
+	req->tag = n;
+	req->tcall = tc;
+	req->rcall = NULL;
+	req->err = 0;
+	req->cb = cb;
+	req->cba = cba;
+	req->flush = None;
+
+	spin_lock(&m->lock);
+	list_add_tail(&req->req_list, &m->unsent_req_list);
+	spin_unlock(&m->lock);
+
+	if (test_and_clear_bit(Wpending, &m->wsched))
+		n = POLLOUT;
+	else
+		n = m->trans->poll(m->trans, NULL);
+
+	if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
+		queue_work(p9_mux_wq, &m->wq);
+
+	return req;
+}
+
+static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req)
+{
+	p9_mux_put_tag(m, req->tag);
+	kfree(req);
+}
+
+static void p9_mux_flush_cb(struct p9_req *freq, void *a)
+{
+	p9_conn_req_callback cb;
+	int tag;
+	struct p9_conn *m;
+	struct p9_req *req, *rreq, *rptr;
+
+	m = a;
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
+		freq->tcall, freq->rcall, freq->err,
+		freq->tcall->params.tflush.oldtag);
+
+	spin_lock(&m->lock);
+	cb = NULL;
+	tag = freq->tcall->params.tflush.oldtag;
+	req = NULL;
+	list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
+		if (rreq->tag == tag) {
+			req = rreq;
+			list_del(&req->req_list);
+			break;
+		}
+	}
+	spin_unlock(&m->lock);
+
+	if (req) {
+		spin_lock(&req->lock);
+		req->flush = Flushed;
+		spin_unlock(&req->lock);
+
+		if (req->cb)
+			(*req->cb) (req, req->cba);
+		else
+			kfree(req->rcall);
+
+		wake_up(&m->equeue);
+	}
+
+	kfree(freq->tcall);
+	kfree(freq->rcall);
+	p9_mux_free_request(m, freq);
+}
+
+static int
+p9_mux_flush_request(struct p9_conn *m, struct p9_req *req)
+{
+	struct p9_fcall *fc;
+	struct p9_req *rreq, *rptr;
+
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
+
+	/* if a response was received for a request, do nothing */
+	spin_lock(&req->lock);
+	if (req->rcall || req->err) {
+		spin_unlock(&req->lock);
+		P9_DPRINTK(P9_DEBUG_MUX,
+			"mux %p req %p response already received\n", m, req);
+		return 0;
+	}
+
+	req->flush = Flushing;
+	spin_unlock(&req->lock);
+
+	spin_lock(&m->lock);
+	/* if the request is not sent yet, just remove it from the list */
+	list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
+		if (rreq->tag == req->tag) {
+			P9_DPRINTK(P9_DEBUG_MUX,
+			   "mux %p req %p request is not sent yet\n", m, req);
+			list_del(&rreq->req_list);
+			req->flush = Flushed;
+			spin_unlock(&m->lock);
+			if (req->cb)
+				(*req->cb) (req, req->cba);
+			return 0;
+		}
+	}
+	spin_unlock(&m->lock);
+
+	clear_thread_flag(TIF_SIGPENDING);
+	fc = p9_create_tflush(req->tag);
+	p9_send_request(m, fc, p9_mux_flush_cb, m);
+	return 1;
+}
+
+static void
+p9_conn_rpc_cb(struct p9_req *req, void *a)
+{
+	struct p9_mux_rpc *r;
+
+	P9_DPRINTK(P9_DEBUG_MUX, "req %p r %p\n", req, a);
+	r = a;
+	r->rcall = req->rcall;
+	r->err = req->err;
+
+	if (req->flush != None && !req->err)
+		r->err = -ERESTARTSYS;
+
+	wake_up(&r->wqueue);
+}
+
+/**
+ * p9_mux_rpc - sends 9P request and waits until a response is available.
+ *	The function can be interrupted.
+ * @m: mux data
+ * @tc: request to be sent
+ * @rc: pointer where a pointer to the response is stored
+ */
+int
+p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc,
+	     struct p9_fcall **rc)
+{
+	int err, sigpending;
+	unsigned long flags;
+	struct p9_req *req;
+	struct p9_mux_rpc r;
+
+	r.err = 0;
+	r.tcall = tc;
+	r.rcall = NULL;
+	r.m = m;
+	init_waitqueue_head(&r.wqueue);
+
+	if (rc)
+		*rc = NULL;
+
+	sigpending = 0;
+	if (signal_pending(current)) {
+		sigpending = 1;
+		clear_thread_flag(TIF_SIGPENDING);
+	}
+
+	req = p9_send_request(m, tc, p9_conn_rpc_cb, &r);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err);
+		return err;
+	}
+
+	err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0);
+	if (r.err < 0)
+		err = r.err;
+
+	if (err == -ERESTARTSYS && m->trans->status == Connected
+							&& m->err == 0) {
+		if (p9_mux_flush_request(m, req)) {
+			/* wait until we get response of the flush message */
+			do {
+				clear_thread_flag(TIF_SIGPENDING);
+				err = wait_event_interruptible(r.wqueue,
+					r.rcall || r.err);
+			} while (!r.rcall && !r.err && err == -ERESTARTSYS &&
+				m->trans->status == Connected && !m->err);
+
+			err = -ERESTARTSYS;
+		}
+		sigpending = 1;
+	}
+
+	if (sigpending) {
+		spin_lock_irqsave(&current->sighand->siglock, flags);
+		recalc_sigpending();
+		spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	}
+
+	if (rc)
+		*rc = r.rcall;
+	else
+		kfree(r.rcall);
+
+	p9_mux_free_request(m, req);
+	if (err > 0)
+		err = -EIO;
+
+	return err;
+}
+EXPORT_SYMBOL(p9_conn_rpc);
+
+#ifdef P9_NONBLOCK
+/**
+ * p9_conn_rpcnb - sends 9P request without waiting for response.
+ * @m: mux data
+ * @tc: request to be sent
+ * @cb: callback function to be called when response arrives
+ * @cba: value to pass to the callback function
+ */
+int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
+		   p9_conn_req_callback cb, void *a)
+{
+	int err;
+	struct p9_req *req;
+
+	req = p9_send_request(m, tc, cb, a);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err);
+		return PTR_ERR(req);
+	}
+
+	P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag);
+	return 0;
+}
+EXPORT_SYMBOL(p9_conn_rpcnb);
+#endif /* P9_NONBLOCK */
+
+/**
+ * p9_conn_cancel - cancel all pending requests with error
+ * @m: mux data
+ * @err: error code
+ */
+void p9_conn_cancel(struct p9_conn *m, int err)
+{
+	struct p9_req *req, *rtmp;
+	LIST_HEAD(cancel_list);
+
+	P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
+	m->err = err;
+	spin_lock(&m->lock);
+	list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
+		list_move(&req->req_list, &cancel_list);
+	}
+	list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
+		list_move(&req->req_list, &cancel_list);
+	}
+	spin_unlock(&m->lock);
+
+	list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
+		list_del(&req->req_list);
+		if (!req->err)
+			req->err = err;
+
+		if (req->cb)
+			(*req->cb) (req, req->cba);
+		else
+			kfree(req->rcall);
+	}
+
+	wake_up(&m->equeue);
+}
+EXPORT_SYMBOL(p9_conn_cancel);
+
+static u16 p9_mux_get_tag(struct p9_conn *m)
+{
+	int tag;
+
+	tag = p9_idpool_get(m->tagpool);
+	if (tag < 0)
+		return P9_NOTAG;
+	else
+		return (u16) tag;
+}
+
+static void p9_mux_put_tag(struct p9_conn *m, u16 tag)
+{
+	if (tag != P9_NOTAG && p9_idpool_check(tag, m->tagpool))
+		p9_idpool_put(tag, m->tagpool);
+}
diff --git a/net/9p/sysctl.c b/net/9p/sysctl.c
new file mode 100644
index 0000000..e7fe706
--- /dev/null
+++ b/net/9p/sysctl.c
@@ -0,0 +1,86 @@
+/*
+ *  net/9p/sysctl.c
+ *
+ *  9P sysctl interface
+ *
+ *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <linux/init.h>
+#include <net/9p/9p.h>
+
+enum {
+	P9_SYSCTL_NET = 487,
+	P9_SYSCTL_DEBUG = 1,
+};
+
+static ctl_table p9_table[] = {
+#ifdef CONFIG_NET_9P_DEBUG
+	{
+		.ctl_name       = P9_SYSCTL_DEBUG,
+		.procname       = "debug",
+		.data           = &p9_debug_level,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = &proc_dointvec
+	},
+#endif
+	{	.ctl_name	= 0 },
+};
+
+static ctl_table p9_net_table[] = {
+	{
+		.ctl_name	= P9_SYSCTL_NET,
+		.procname	= "9p",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= p9_table,
+	},
+	{	.ctl_name	= 0 },
+};
+
+static ctl_table p9_ctl_table[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= p9_net_table,
+	},
+	{	.ctl_name	= 0 },
+};
+
+static struct ctl_table_header *p9_table_header;
+
+int __init p9_sysctl_register(void)
+{
+	p9_table_header = register_sysctl_table(p9_ctl_table);
+	if (!p9_table_header)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void __exit p9_sysctl_unregister(void)
+{
+	 unregister_sysctl_table(p9_table_header);
+}
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
new file mode 100644
index 0000000..fd636e9
--- /dev/null
+++ b/net/9p/trans_fd.c
@@ -0,0 +1,363 @@
+/*
+ * linux/fs/9p/trans_fd.c
+ *
+ * Fd transport layer.  Includes deprecated socket layer.
+ *
+ *  Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
+ *  Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *  Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/in.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/ipv6.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/un.h>
+#include <linux/uaccess.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+#include <linux/file.h>
+#include <net/9p/9p.h>
+#include <net/9p/transport.h>
+
+#define P9_PORT 564
+
+struct p9_trans_fd {
+	struct file *rd;
+	struct file *wr;
+};
+
+static int p9_socket_open(struct p9_transport *trans, struct socket *csocket);
+static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd);
+static int p9_fd_read(struct p9_transport *trans, void *v, int len);
+static int p9_fd_write(struct p9_transport *trans, void *v, int len);
+static unsigned int p9_fd_poll(struct p9_transport *trans,
+						struct poll_table_struct *pt);
+static void p9_fd_close(struct p9_transport *trans);
+
+struct p9_transport *p9_trans_create_tcp(const char *addr, int port)
+{
+	int err;
+	struct p9_transport *trans;
+	struct socket *csocket;
+	struct sockaddr_in sin_server;
+
+	csocket = NULL;
+	trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
+	if (!trans)
+		return ERR_PTR(-ENOMEM);
+
+	trans->write = p9_fd_write;
+	trans->read = p9_fd_read;
+	trans->close = p9_fd_close;
+	trans->poll = p9_fd_poll;
+
+	sin_server.sin_family = AF_INET;
+	sin_server.sin_addr.s_addr = in_aton(addr);
+	sin_server.sin_port = htons(port);
+	sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+
+	if (!csocket) {
+		P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
+		err = -EIO;
+		goto error;
+	}
+
+	err = csocket->ops->connect(csocket,
+				    (struct sockaddr *)&sin_server,
+				    sizeof(struct sockaddr_in), 0);
+	if (err < 0) {
+		P9_EPRINTK(KERN_ERR,
+			"p9_trans_tcp: problem connecting socket to %s\n",
+			addr);
+		goto error;
+	}
+
+	err = p9_socket_open(trans, csocket);
+	if (err < 0)
+		goto error;
+
+	return trans;
+
+error:
+	if (csocket)
+		sock_release(csocket);
+
+	kfree(trans);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_trans_create_tcp);
+
+struct p9_transport *p9_trans_create_unix(const char *addr)
+{
+	int err;
+	struct socket *csocket;
+	struct sockaddr_un sun_server;
+	struct p9_transport *trans;
+
+	csocket = NULL;
+	trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
+	if (!trans)
+		return ERR_PTR(-ENOMEM);
+
+	trans->write = p9_fd_write;
+	trans->read = p9_fd_read;
+	trans->close = p9_fd_close;
+	trans->poll = p9_fd_poll;
+
+	if (strlen(addr) > UNIX_PATH_MAX) {
+		P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
+			addr);
+		err = -ENAMETOOLONG;
+		goto error;
+	}
+
+	sun_server.sun_family = PF_UNIX;
+	strcpy(sun_server.sun_path, addr);
+	sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+	err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
+			sizeof(struct sockaddr_un) - 1, 0);
+	if (err < 0) {
+		P9_EPRINTK(KERN_ERR,
+			"p9_trans_unix: problem connecting socket: %s: %d\n",
+			addr, err);
+		goto error;
+	}
+
+	err = p9_socket_open(trans, csocket);
+	if (err < 0)
+		goto error;
+
+	return trans;
+
+error:
+	if (csocket)
+		sock_release(csocket);
+
+	kfree(trans);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_trans_create_unix);
+
+struct p9_transport *p9_trans_create_fd(int rfd, int wfd)
+{
+	int err;
+	struct p9_transport *trans;
+
+	if (rfd == ~0 || wfd == ~0) {
+		printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
+		return ERR_PTR(-ENOPROTOOPT);
+	}
+
+	trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
+	if (!trans)
+		return ERR_PTR(-ENOMEM);
+
+	trans->write = p9_fd_write;
+	trans->read = p9_fd_read;
+	trans->close = p9_fd_close;
+	trans->poll = p9_fd_poll;
+
+	err = p9_fd_open(trans, rfd, wfd);
+	if (err < 0)
+		goto error;
+
+	return trans;
+
+error:
+	kfree(trans);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_trans_create_fd);
+
+static int p9_socket_open(struct p9_transport *trans, struct socket *csocket)
+{
+	int fd, ret;
+
+	csocket->sk->sk_allocation = GFP_NOIO;
+	fd = sock_map_fd(csocket);
+	if (fd < 0) {
+		P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
+		return fd;
+	}
+
+	ret = p9_fd_open(trans, fd, fd);
+	if (ret < 0) {
+		P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n");
+		sockfd_put(csocket);
+		return ret;
+	}
+
+	((struct p9_trans_fd *)trans->priv)->rd->f_flags |= O_NONBLOCK;
+
+	return 0;
+}
+
+static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd)
+{
+	struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
+					   GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	ts->rd = fget(rfd);
+	ts->wr = fget(wfd);
+	if (!ts->rd || !ts->wr) {
+		if (ts->rd)
+			fput(ts->rd);
+		if (ts->wr)
+			fput(ts->wr);
+		kfree(ts);
+		return -EIO;
+	}
+
+	trans->priv = ts;
+	trans->status = Connected;
+
+	return 0;
+}
+
+/**
+ * p9_fd_read- read from a fd
+ * @v9ses: session information
+ * @v: buffer to receive data into
+ * @len: size of receive buffer
+ *
+ */
+static int p9_fd_read(struct p9_transport *trans, void *v, int len)
+{
+	int ret;
+	struct p9_trans_fd *ts = NULL;
+
+	if (trans && trans->status != Disconnected)
+		ts = trans->priv;
+
+	if (!ts)
+		return -EREMOTEIO;
+
+	if (!(ts->rd->f_flags & O_NONBLOCK))
+		P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n");
+
+	ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
+	if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
+		trans->status = Disconnected;
+	return ret;
+}
+
+/**
+ * p9_fd_write - write to a socket
+ * @v9ses: session information
+ * @v: buffer to send data from
+ * @len: size of send buffer
+ *
+ */
+static int p9_fd_write(struct p9_transport *trans, void *v, int len)
+{
+	int ret;
+	mm_segment_t oldfs;
+	struct p9_trans_fd *ts = NULL;
+
+	if (trans && trans->status != Disconnected)
+		ts = trans->priv;
+
+	if (!ts)
+		return -EREMOTEIO;
+
+	if (!(ts->wr->f_flags & O_NONBLOCK))
+		P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n");
+
+	oldfs = get_fs();
+	set_fs(get_ds());
+	/* The cast to a user pointer is valid due to the set_fs() */
+	ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
+	set_fs(oldfs);
+
+	if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
+		trans->status = Disconnected;
+	return ret;
+}
+
+static unsigned int
+p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt)
+{
+	int ret, n;
+	struct p9_trans_fd *ts = NULL;
+	mm_segment_t oldfs;
+
+	if (trans && trans->status == Connected)
+		ts = trans->priv;
+
+	if (!ts)
+		return -EREMOTEIO;
+
+	if (!ts->rd->f_op || !ts->rd->f_op->poll)
+		return -EIO;
+
+	if (!ts->wr->f_op || !ts->wr->f_op->poll)
+		return -EIO;
+
+	oldfs = get_fs();
+	set_fs(get_ds());
+
+	ret = ts->rd->f_op->poll(ts->rd, pt);
+	if (ret < 0)
+		goto end;
+
+	if (ts->rd != ts->wr) {
+		n = ts->wr->f_op->poll(ts->wr, pt);
+		if (n < 0) {
+			ret = n;
+			goto end;
+		}
+		ret = (ret & ~POLLOUT) | (n & ~POLLIN);
+	}
+
+end:
+	set_fs(oldfs);
+	return ret;
+}
+
+/**
+ * p9_sock_close - shutdown socket
+ * @trans: private socket structure
+ *
+ */
+static void p9_fd_close(struct p9_transport *trans)
+{
+	struct p9_trans_fd *ts;
+
+	if (!trans)
+		return;
+
+	ts = xchg(&trans->priv, NULL);
+
+	if (!ts)
+		return;
+
+	trans->status = Disconnected;
+	if (ts->rd)
+		fput(ts->rd);
+	if (ts->wr)
+		fput(ts->wr);
+	kfree(ts);
+}
+
diff --git a/net/9p/util.c b/net/9p/util.c
new file mode 100644
index 0000000..22077b7
--- /dev/null
+++ b/net/9p/util.c
@@ -0,0 +1,125 @@
+/*
+ *  net/9p/util.c
+ *
+ *  This file contains some helper functions
+ *
+ *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/parser.h>
+#include <linux/idr.h>
+#include <net/9p/9p.h>
+
+struct p9_idpool {
+	struct semaphore lock;
+	struct idr pool;
+};
+
+struct p9_idpool *p9_idpool_create(void)
+{
+	struct p9_idpool *p;
+
+	p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL);
+	if (!p)
+		return ERR_PTR(-ENOMEM);
+
+	init_MUTEX(&p->lock);
+	idr_init(&p->pool);
+
+	return p;
+}
+EXPORT_SYMBOL(p9_idpool_create);
+
+void p9_idpool_destroy(struct p9_idpool *p)
+{
+	idr_destroy(&p->pool);
+	kfree(p);
+}
+EXPORT_SYMBOL(p9_idpool_destroy);
+
+/**
+ * p9_idpool_get - allocate numeric id from pool
+ * @p - pool to allocate from
+ *
+ * XXX - This seems to be an awful generic function, should it be in idr.c with
+ *            the lock included in struct idr?
+ */
+
+int p9_idpool_get(struct p9_idpool *p)
+{
+	int i = 0;
+	int error;
+
+retry:
+	if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
+		return 0;
+
+	if (down_interruptible(&p->lock) == -EINTR) {
+		P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n");
+		return -1;
+	}
+
+	/* no need to store exactly p, we just need something non-null */
+	error = idr_get_new(&p->pool, p, &i);
+	up(&p->lock);
+
+	if (error == -EAGAIN)
+		goto retry;
+	else if (error)
+		return -1;
+
+	return i;
+}
+EXPORT_SYMBOL(p9_idpool_get);
+
+/**
+ * p9_idpool_put - release numeric id from pool
+ * @p - pool to allocate from
+ *
+ * XXX - This seems to be an awful generic function, should it be in idr.c with
+ *            the lock included in struct idr?
+ */
+
+void p9_idpool_put(int id, struct p9_idpool *p)
+{
+	if (down_interruptible(&p->lock) == -EINTR) {
+		P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n");
+		return;
+	}
+	idr_remove(&p->pool, id);
+	up(&p->lock);
+}
+EXPORT_SYMBOL(p9_idpool_put);
+
+/**
+ * p9_idpool_check - check if the specified id is available
+ * @id - id to check
+ * @p - pool
+ */
+int p9_idpool_check(int id, struct p9_idpool *p)
+{
+	return idr_find(&p->pool, id) != NULL;
+}
+EXPORT_SYMBOL(p9_idpool_check);
diff --git a/net/Kconfig b/net/Kconfig
index f3de729..cdba08c 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -227,6 +227,7 @@
 endmenu
 
 source "net/rfkill/Kconfig"
+source "net/9p/Kconfig"
 
 endif   # if NET
 endmenu # Networking
diff --git a/net/Makefile b/net/Makefile
index 34e5b2d..bbe7d2a 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -37,7 +37,6 @@
 obj-$(CONFIG_IRDA)		+= irda/
 obj-$(CONFIG_BT)		+= bluetooth/
 obj-$(CONFIG_SUNRPC)		+= sunrpc/
-obj-$(CONFIG_RXRPC)		+= rxrpc/
 obj-$(CONFIG_AF_RXRPC)		+= rxrpc/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_DECNET)		+= decnet/
@@ -52,6 +51,7 @@
 obj-$(CONFIG_NETLABEL)		+= netlabel/
 obj-$(CONFIG_IUCV)		+= iucv/
 obj-$(CONFIG_RFKILL)		+= rfkill/
+obj-$(CONFIG_NET_9P)		+= 9p/
 
 ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_SYSCTL)		+= sysctl_net.o
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 5ef6a23..3d1655f 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -1024,7 +1024,7 @@
 	return 0;
 }
 
-static struct seq_operations aarp_seq_ops = {
+static const struct seq_operations aarp_seq_ops = {
 	.start  = aarp_seq_start,
 	.next   = aarp_seq_next,
 	.stop   = aarp_seq_stop,
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index 57ff812..87a582c 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -204,21 +204,21 @@
 	return 0;
 }
 
-static struct seq_operations atalk_seq_interface_ops = {
+static const struct seq_operations atalk_seq_interface_ops = {
 	.start  = atalk_seq_interface_start,
 	.next   = atalk_seq_interface_next,
 	.stop   = atalk_seq_interface_stop,
 	.show   = atalk_seq_interface_show,
 };
 
-static struct seq_operations atalk_seq_route_ops = {
+static const struct seq_operations atalk_seq_route_ops = {
 	.start  = atalk_seq_route_start,
 	.next   = atalk_seq_route_next,
 	.stop   = atalk_seq_route_stop,
 	.show   = atalk_seq_route_show,
 };
 
-static struct seq_operations atalk_seq_socket_ops = {
+static const struct seq_operations atalk_seq_socket_ops = {
 	.start  = atalk_seq_socket_start,
 	.next   = atalk_seq_socket_next,
 	.stop   = atalk_seq_socket_stop,
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 0e9f00c..faa6aaf 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -699,28 +699,13 @@
 #ifdef CONFIG_PROC_FS
 static void *br2684_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	loff_t offs = 0;
-	struct br2684_dev *brd;
-
 	read_lock(&devs_lock);
-
-	list_for_each_entry(brd, &br2684_devs, br2684_devs) {
-		if (offs == *pos)
-			return brd;
-		++offs;
-	}
-	return NULL;
+	return seq_list_start(&br2684_devs, *pos);
 }
 
 static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct br2684_dev *brd = v;
-
-	++*pos;
-
-	brd = list_entry(brd->br2684_devs.next,
-			 struct br2684_dev, br2684_devs);
-	return (&brd->br2684_devs != &br2684_devs) ? brd : NULL;
+	return seq_list_next(v, &br2684_devs, pos);
 }
 
 static void br2684_seq_stop(struct seq_file *seq, void *v)
@@ -730,7 +715,8 @@
 
 static int br2684_seq_show(struct seq_file *seq, void *v)
 {
-	const struct br2684_dev *brdev = v;
+	const struct br2684_dev *brdev = list_entry(v, struct br2684_dev,
+			br2684_devs);
 	const struct net_device *net_dev = brdev->net_dev;
 	const struct br2684_vcc *brvcc;
 
@@ -772,7 +758,7 @@
 	return 0;
 }
 
-static struct seq_operations br2684_seq_ops = {
+static const struct seq_operations br2684_seq_ops = {
 	.start = br2684_seq_start,
 	.next  = br2684_seq_next,
 	.stop  = br2684_seq_stop,
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 876b77f..ecf0f79 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -928,7 +928,7 @@
 	return 0;
 }
 
-static struct seq_operations arp_seq_ops = {
+static const struct seq_operations arp_seq_ops = {
 	.start	= clip_seq_start,
 	.next	= neigh_seq_next,
 	.stop	= neigh_seq_stop,
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 4dc5f2b..2770fb4 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1174,7 +1174,7 @@
 	return 0;
 }
 
-static struct seq_operations lec_seq_ops = {
+static const struct seq_operations lec_seq_ops = {
 	.start = lec_seq_start,
 	.next = lec_seq_next,
 	.stop = lec_seq_stop,
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
index 4b05cbe..91f3ffc 100644
--- a/net/atm/mpoa_proc.c
+++ b/net/atm/mpoa_proc.c
@@ -177,7 +177,7 @@
 	return 0;
 }
 
-static struct seq_operations mpc_op = {
+static const struct seq_operations mpc_op = {
 	.start =	mpc_start,
 	.next =		mpc_next,
 	.stop =		mpc_stop,
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 9e61e51..99fc1fe 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -110,7 +110,7 @@
 }
 
 static int __vcc_seq_open(struct inode *inode, struct file *file,
-	int family, struct seq_operations *ops)
+	int family, const struct seq_operations *ops)
 {
 	struct vcc_state *state;
 	struct seq_file *seq;
@@ -260,7 +260,7 @@
 	return 0;
 }
 
-static struct seq_operations atm_dev_seq_ops = {
+static const struct seq_operations atm_dev_seq_ops = {
 	.start	= atm_dev_seq_start,
 	.next	= atm_dev_seq_next,
 	.stop	= atm_dev_seq_stop,
@@ -295,7 +295,7 @@
 	return 0;
 }
 
-static struct seq_operations pvc_seq_ops = {
+static const struct seq_operations pvc_seq_ops = {
 	.start	= vcc_seq_start,
 	.next	= vcc_seq_next,
 	.stop	= vcc_seq_stop,
@@ -329,7 +329,7 @@
 	return 0;
 }
 
-static struct seq_operations vcc_seq_ops = {
+static const struct seq_operations vcc_seq_ops = {
 	.start	= vcc_seq_start,
 	.next	= vcc_seq_next,
 	.stop	= vcc_seq_stop,
@@ -364,7 +364,7 @@
 	return 0;
 }
 
-static struct seq_operations svc_seq_ops = {
+static const struct seq_operations svc_seq_ops = {
 	.start	= vcc_seq_start,
 	.next	= vcc_seq_next,
 	.stop	= vcc_seq_stop,
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 429e13a..c83cf843 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1924,7 +1924,7 @@
 	return 0;
 }
 
-static struct seq_operations ax25_info_seqops = {
+static const struct seq_operations ax25_info_seqops = {
 	.start = ax25_info_start,
 	.next = ax25_info_next,
 	.stop = ax25_info_stop,
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index d65b8e2..9ecf6f1 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -320,7 +320,7 @@
 	return 0;
 }
 
-static struct seq_operations ax25_rt_seqops = {
+static const struct seq_operations ax25_rt_seqops = {
 	.start = ax25_rt_seq_start,
 	.next = ax25_rt_seq_next,
 	.stop = ax25_rt_seq_stop,
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 75c7664..ce0b13d 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -185,7 +185,7 @@
 	return 0;
 }
 
-static struct seq_operations ax25_uid_seqops = {
+static const struct seq_operations ax25_uid_seqops = {
 	.start = ax25_uid_seq_start,
 	.next = ax25_uid_seq_next,
 	.stop = ax25_uid_seq_stop,
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 1c8f4a0..1f78c3e 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -36,6 +36,7 @@
 #include <linux/signal.h>
 #include <linux/init.h>
 #include <linux/wait.h>
+#include <linux/freezer.h>
 #include <linux/errno.h>
 #include <linux/net.h>
 #include <net/sock.h>
@@ -474,7 +475,6 @@
 
 	daemonize("kbnepd %s", dev->name);
 	set_user_nice(current, -15);
-	current->flags |= PF_NOFREEZE;
 
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(sk->sk_sleep, &wait);
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index 66bef1c..ca60a451 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
+#include <linux/freezer.h>
 #include <linux/skbuff.h>
 #include <linux/socket.h>
 #include <linux/ioctl.h>
@@ -287,7 +288,6 @@
 
 	daemonize("kcmtpd_ctr_%d", session->num);
 	set_user_nice(current, -15);
-	current->flags |= PF_NOFREEZE;
 
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(sk->sk_sleep, &wait);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 63980bd..5fdfc9a6 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -123,8 +123,8 @@
 	conn->state = BT_CONNECT;
 	conn->out = 1;
 
-	cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
 	cp.handle   = cpu_to_le16(handle);
+	cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
 
 	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
 }
@@ -220,19 +220,19 @@
 
 	del_timer(&conn->disc_timer);
 
-	if (conn->type == SCO_LINK) {
-		struct hci_conn *acl = conn->link;
-		if (acl) {
-			acl->link = NULL;
-			hci_conn_put(acl);
-		}
-	} else {
+	if (conn->type == ACL_LINK) {
 		struct hci_conn *sco = conn->link;
 		if (sco)
 			sco->link = NULL;
 
 		/* Unacked frames */
 		hdev->acl_cnt += conn->sent;
+	} else {
+		struct hci_conn *acl = conn->link;
+		if (acl) {
+			acl->link = NULL;
+			hci_conn_put(acl);
+		}
 	}
 
 	tasklet_disable(&hdev->tx_task);
@@ -297,9 +297,10 @@
 
 /* Create SCO or ACL connection.
  * Device _must_ be locked */
-struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
 {
 	struct hci_conn *acl;
+	struct hci_conn *sco;
 
 	BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
@@ -313,28 +314,26 @@
 	if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
 		hci_acl_connect(acl);
 
-	if (type == SCO_LINK) {
-		struct hci_conn *sco;
-
-		if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) {
-			if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) {
-				hci_conn_put(acl);
-				return NULL;
-			}
-		}
-		acl->link = sco;
-		sco->link = acl;
-
-		hci_conn_hold(sco);
-
-		if (acl->state == BT_CONNECTED &&
-				(sco->state == BT_OPEN || sco->state == BT_CLOSED))
-			hci_add_sco(sco, acl->handle);
-
-		return sco;
-	} else {
+	if (type == ACL_LINK)
 		return acl;
+
+	if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) {
+		if (!(sco = hci_conn_add(hdev, type, dst))) {
+			hci_conn_put(acl);
+			return NULL;
+		}
 	}
+
+	acl->link = sco;
+	sco->link = acl;
+
+	hci_conn_hold(sco);
+
+	if (acl->state == BT_CONNECTED &&
+			(sco->state == BT_OPEN || sco->state == BT_CLOSED))
+		hci_add_sco(sco, acl->handle);
+
+	return sco;
 }
 EXPORT_SYMBOL(hci_connect);
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index aa4b56a..f6d867e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -826,7 +826,7 @@
 int hci_register_dev(struct hci_dev *hdev)
 {
 	struct list_head *head = &hci_dev_list, *p;
-	int id = 0;
+	int i, id = 0;
 
 	BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner);
 
@@ -851,6 +851,7 @@
 
 	hdev->flags = 0;
 	hdev->pkt_type  = (HCI_DM1 | HCI_DH1 | HCI_HV1);
+	hdev->esco_type = (ESCO_HV1);
 	hdev->link_mode = (HCI_LM_ACCEPT);
 
 	hdev->idle_timeout = 0;
@@ -865,6 +866,9 @@
 	skb_queue_head_init(&hdev->cmd_q);
 	skb_queue_head_init(&hdev->raw_q);
 
+	for (i = 0; i < 3; i++)
+		hdev->reassembly[i] = NULL;
+
 	init_waitqueue_head(&hdev->req_wait_q);
 	init_MUTEX(&hdev->req_lock);
 
@@ -889,6 +893,8 @@
 /* Unregister HCI device */
 int hci_unregister_dev(struct hci_dev *hdev)
 {
+	int i;
+
 	BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
 	hci_unregister_sysfs(hdev);
@@ -899,9 +905,13 @@
 
 	hci_dev_do_close(hdev);
 
+	for (i = 0; i < 3; i++)
+		kfree_skb(hdev->reassembly[i]);
+
 	hci_notify(hdev, HCI_DEV_UNREG);
 
 	__hci_dev_put(hdev);
+
 	return 0;
 }
 EXPORT_SYMBOL(hci_unregister_dev);
@@ -922,6 +932,90 @@
 }
 EXPORT_SYMBOL(hci_resume_dev);
 
+/* Receive packet type fragment */
+#define __reassembly(hdev, type)  ((hdev)->reassembly[(type) - 2])
+
+int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
+{
+	if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
+		return -EILSEQ;
+
+	while (count) {
+		struct sk_buff *skb = __reassembly(hdev, type);
+		struct { int expect; } *scb;
+		int len = 0;
+
+		if (!skb) {
+			/* Start of the frame */
+
+			switch (type) {
+			case HCI_EVENT_PKT:
+				if (count >= HCI_EVENT_HDR_SIZE) {
+					struct hci_event_hdr *h = data;
+					len = HCI_EVENT_HDR_SIZE + h->plen;
+				} else
+					return -EILSEQ;
+				break;
+
+			case HCI_ACLDATA_PKT:
+				if (count >= HCI_ACL_HDR_SIZE) {
+					struct hci_acl_hdr *h = data;
+					len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
+				} else
+					return -EILSEQ;
+				break;
+
+			case HCI_SCODATA_PKT:
+				if (count >= HCI_SCO_HDR_SIZE) {
+					struct hci_sco_hdr *h = data;
+					len = HCI_SCO_HDR_SIZE + h->dlen;
+				} else
+					return -EILSEQ;
+				break;
+			}
+
+			skb = bt_skb_alloc(len, GFP_ATOMIC);
+			if (!skb) {
+				BT_ERR("%s no memory for packet", hdev->name);
+				return -ENOMEM;
+			}
+
+			skb->dev = (void *) hdev;
+			bt_cb(skb)->pkt_type = type;
+	
+			__reassembly(hdev, type) = skb;
+
+			scb = (void *) skb->cb;
+			scb->expect = len;
+		} else {
+			/* Continuation */
+
+			scb = (void *) skb->cb;
+			len = scb->expect;
+		}
+
+		len = min(len, count);
+
+		memcpy(skb_put(skb, len), data, len);
+
+		scb->expect -= len;
+
+		if (scb->expect == 0) {
+			/* Complete frame */
+
+			__reassembly(hdev, type) = NULL;
+
+			bt_cb(skb)->pkt_type = type;
+			hci_recv_frame(skb);
+		}
+
+		count -= len; data += len;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(hci_recv_fragment);
+
 /* ---- Interface to upper protocols ---- */
 
 /* Register/Unregister protocols.
@@ -1029,7 +1123,7 @@
 
 	skb = bt_skb_alloc(len, GFP_ATOMIC);
 	if (!skb) {
-		BT_ERR("%s Can't allocate memory for HCI command", hdev->name);
+		BT_ERR("%s no memory for command", hdev->name);
 		return -ENOMEM;
 	}
 
@@ -1161,7 +1255,7 @@
 static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote)
 {
 	struct hci_conn_hash *h = &hdev->conn_hash;
-	struct hci_conn  *conn = NULL;
+	struct hci_conn *conn = NULL;
 	int num = 0, min = ~0;
 	struct list_head *p;
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 447ba71..4baea1e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -350,11 +350,24 @@
 		if (hdev->features[0] & LMP_5SLOT)
 			hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
 
-		if (hdev->features[1] & LMP_HV2)
-			hdev->pkt_type |= (HCI_HV2);
+		if (hdev->features[1] & LMP_HV2) {
+			hdev->pkt_type  |= (HCI_HV2);
+			hdev->esco_type |= (ESCO_HV2);
+		}
 
-		if (hdev->features[1] & LMP_HV3)
-			hdev->pkt_type |= (HCI_HV3);
+		if (hdev->features[1] & LMP_HV3) {
+			hdev->pkt_type  |= (HCI_HV3);
+			hdev->esco_type |= (ESCO_HV3);
+		}
+
+		if (hdev->features[3] & LMP_ESCO)
+			hdev->esco_type |= (ESCO_EV3);
+
+		if (hdev->features[4] & LMP_EV4)
+			hdev->esco_type |= (ESCO_EV4);
+
+		if (hdev->features[4] & LMP_EV5)
+			hdev->esco_type |= (ESCO_EV5);
 
 		BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
 				lf->features[0], lf->features[1], lf->features[2]);
@@ -881,12 +894,12 @@
 		if (conn) {
 			conn->sent -= count;
 
-			if (conn->type == SCO_LINK) {
-				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
-					hdev->sco_cnt = hdev->sco_pkts;
-			} else {
+			if (conn->type == ACL_LINK) {
 				if ((hdev->acl_cnt += count) > hdev->acl_pkts)
 					hdev->acl_cnt = hdev->acl_pkts;
+			} else {
+				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
+					hdev->sco_cnt = hdev->sco_pkts;
 			}
 		}
 	}
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index ceadfcf..64d89ca 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/freezer.h>
 #include <linux/fcntl.h>
 #include <linux/skbuff.h>
 #include <linux/socket.h>
@@ -547,7 +548,6 @@
 
 	daemonize("khidpd_%04x%04x", vendor, product);
 	set_user_nice(current, -15);
-	current->flags |= PF_NOFREEZE;
 
 	init_waitqueue_entry(&ctrl_wait, current);
 	init_waitqueue_entry(&intr_wait, current);
@@ -581,15 +581,6 @@
 
 	hidp_del_timer(session);
 
-	fput(session->intr_sock->file);
-
-	wait_event_timeout(*(ctrl_sk->sk_sleep),
-		(ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
-
-	fput(session->ctrl_sock->file);
-
-	__hidp_unlink_session(session);
-
 	if (session->input) {
 		input_unregister_device(session->input);
 		session->input = NULL;
@@ -601,6 +592,15 @@
 		hid_free_device(session->hid);
 	}
 
+	fput(session->intr_sock->file);
+
+	wait_event_timeout(*(ctrl_sk->sk_sleep),
+		(ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
+
+	fput(session->ctrl_sock->file);
+
+	__hidp_unlink_session(session);
+
 	up_write(&hidp_session_sem);
 
 	kfree(session);
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index a59b1fb..670ff95 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -507,6 +507,7 @@
 	}
 
 	/* Default config options */
+	pi->conf_len = 0;
 	pi->conf_mtu = L2CAP_DEFAULT_MTU;
 	pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
 }
@@ -1271,42 +1272,6 @@
 	return len;
 }
 
-static inline void l2cap_parse_conf_req(struct sock *sk, void *data, int len)
-{
-	int type, hint, olen;
-	unsigned long val;
-	void *ptr = data;
-
-	BT_DBG("sk %p len %d", sk, len);
-
-	while (len >= L2CAP_CONF_OPT_SIZE) {
-		len -= l2cap_get_conf_opt(&ptr, &type, &olen, &val);
-
-		hint  = type & 0x80;
-		type &= 0x7f;
-
-		switch (type) {
-		case L2CAP_CONF_MTU:
-			l2cap_pi(sk)->conf_mtu = val;
-			break;
-
-		case L2CAP_CONF_FLUSH_TO:
-			l2cap_pi(sk)->flush_to = val;
-			break;
-
-		case L2CAP_CONF_QOS:
-			break;
-
-		default:
-			if (hint)
-				break;
-
-			/* FIXME: Reject unknown option */
-			break;
-		}
-	}
-}
-
 static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
 {
 	struct l2cap_conf_opt *opt = *ptr;
@@ -1358,39 +1323,75 @@
 	return ptr - data;
 }
 
-static inline int l2cap_conf_output(struct sock *sk, void **ptr)
+static int l2cap_parse_conf_req(struct sock *sk, void *data)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	int result = 0;
+	struct l2cap_conf_rsp *rsp = data;
+	void *ptr = rsp->data;
+	void *req = pi->conf_req;
+	int len = pi->conf_len;
+	int type, hint, olen;
+	unsigned long val;
+	u16 result = L2CAP_CONF_SUCCESS;
 
-	/* Configure output options and let the other side know
-	 * which ones we don't like. */
-	if (pi->conf_mtu < pi->omtu)
-		result = L2CAP_CONF_UNACCEPT;
-	else
-		pi->omtu = pi->conf_mtu;
+	BT_DBG("sk %p", sk);
 
-	l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+	while (len >= L2CAP_CONF_OPT_SIZE) {
+		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
 
-	BT_DBG("sk %p result %d", sk, result);
-	return result;
+		hint  = type & 0x80;
+		type &= 0x7f;
+
+		switch (type) {
+		case L2CAP_CONF_MTU:
+			pi->conf_mtu = val;
+			break;
+
+		case L2CAP_CONF_FLUSH_TO:
+			pi->flush_to = val;
+			break;
+
+		case L2CAP_CONF_QOS:
+			break;
+
+		default:
+			if (hint)
+				break;
+
+			result = L2CAP_CONF_UNKNOWN;
+			*((u8 *) ptr++) = type;
+			break;
+		}
+	}
+
+	if (result == L2CAP_CONF_SUCCESS) {
+		/* Configure output options and let the other side know
+		 * which ones we don't like. */
+
+		if (pi->conf_mtu < pi->omtu)
+			result = L2CAP_CONF_UNACCEPT;
+		else
+			pi->omtu = pi->conf_mtu;
+
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+	}
+
+	rsp->scid   = cpu_to_le16(pi->dcid);
+	rsp->result = cpu_to_le16(result);
+	rsp->flags  = cpu_to_le16(0x0000);
+
+	return ptr - data;
 }
 
-static int l2cap_build_conf_rsp(struct sock *sk, void *data, int *result)
+static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
 {
 	struct l2cap_conf_rsp *rsp = data;
 	void *ptr = rsp->data;
-	u16 flags = 0;
 
-	BT_DBG("sk %p complete %d", sk, result ? 1 : 0);
-
-	if (result)
-		*result = l2cap_conf_output(sk, &ptr);
-	else
-		flags = 0x0001;
+	BT_DBG("sk %p", sk);
 
 	rsp->scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
-	rsp->result = cpu_to_le16(result ? *result : 0);
+	rsp->result = cpu_to_le16(result);
 	rsp->flags  = cpu_to_le16(flags);
 
 	return ptr - data;
@@ -1535,7 +1536,7 @@
 	u16 dcid, flags;
 	u8 rsp[64];
 	struct sock *sk;
-	int result;
+	int len;
 
 	dcid  = __le16_to_cpu(req->dcid);
 	flags = __le16_to_cpu(req->flags);
@@ -1548,25 +1549,40 @@
 	if (sk->sk_state == BT_DISCONN)
 		goto unlock;
 
-	l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req));
+	/* Reject if config buffer is too small. */
+	len = cmd->len - sizeof(*req);
+	if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
+		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
+				l2cap_build_conf_rsp(sk, rsp,
+					L2CAP_CONF_REJECT, flags), rsp);
+		goto unlock;
+	}
+
+	/* Store config. */
+	memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
+	l2cap_pi(sk)->conf_len += len;
 
 	if (flags & 0x0001) {
 		/* Incomplete config. Send empty response. */
 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-				l2cap_build_conf_rsp(sk, rsp, NULL), rsp);
+				l2cap_build_conf_rsp(sk, rsp,
+					L2CAP_CONF_SUCCESS, 0x0001), rsp);
 		goto unlock;
 	}
 
 	/* Complete config. */
-	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-			l2cap_build_conf_rsp(sk, rsp, &result), rsp);
-
-	if (result)
+	len = l2cap_parse_conf_req(sk, rsp);
+	if (len < 0)
 		goto unlock;
 
-	/* Output config done */
+	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
+
+	/* Output config done. */
 	l2cap_pi(sk)->conf_state |= L2CAP_CONF_OUTPUT_DONE;
 
+	/* Reset config buffer. */
+	l2cap_pi(sk)->conf_len = 0;
+
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
 		sk->sk_state = BT_CONNECTED;
 		l2cap_chan_ready(sk);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 52e04df..bb722077 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -33,6 +33,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/init.h>
+#include <linux/freezer.h>
 #include <linux/wait.h>
 #include <linux/device.h>
 #include <linux/net.h>
@@ -1940,7 +1941,6 @@
 
 	daemonize("krfcommd");
 	set_user_nice(current, -10);
-	current->flags |= PF_NOFREEZE;
 
 	BT_DBG("");
 
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index b2b1cce..23ba61a 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -95,6 +95,10 @@
 
 	BT_DBG("dev %p dlc %p", dev, dlc);
 
+	write_lock_bh(&rfcomm_dev_lock);
+	list_del_init(&dev->list);
+	write_unlock_bh(&rfcomm_dev_lock);
+
 	rfcomm_dlc_lock(dlc);
 	/* Detach DLC if it's owned by this dev */
 	if (dlc->owner == dev)
@@ -156,8 +160,13 @@
 	read_lock(&rfcomm_dev_lock);
 
 	dev = __rfcomm_dev_get(id);
-	if (dev)
-		rfcomm_dev_hold(dev);
+
+	if (dev) {
+		if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+			dev = NULL;
+		else
+			rfcomm_dev_hold(dev);
+	}
 
 	read_unlock(&rfcomm_dev_lock);
 
@@ -265,6 +274,12 @@
 
 	dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
 
+	if (IS_ERR(dev->tty_dev)) {
+		list_del(&dev->list);
+		kfree(dev);
+		return PTR_ERR(dev->tty_dev);
+	}
+
 	return dev->id;
 }
 
@@ -272,10 +287,7 @@
 {
 	BT_DBG("dev %p", dev);
 
-	write_lock_bh(&rfcomm_dev_lock);
-	list_del_init(&dev->list);
-	write_unlock_bh(&rfcomm_dev_lock);
-
+	set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
 	rfcomm_dev_put(dev);
 }
 
@@ -329,7 +341,7 @@
 	if (copy_from_user(&req, arg, sizeof(req)))
 		return -EFAULT;
 
-	BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags);
+	BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags);
 
 	if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -370,7 +382,7 @@
 	if (copy_from_user(&req, arg, sizeof(req)))
 		return -EFAULT;
 
-	BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags);
+	BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);
 
 	if (!(dev = rfcomm_dev_get(req.dev_id)))
 		return -ENODEV;
@@ -383,6 +395,10 @@
 	if (req.flags & (1 << RFCOMM_HANGUP_NOW))
 		rfcomm_dlc_close(dev->dlc, 0);
 
+	/* Shut down TTY synchronously before freeing rfcomm_dev */
+	if (dev->tty)
+		tty_vhangup(dev->tty);
+
 	rfcomm_dev_del(dev);
 	rfcomm_dev_put(dev);
 	return 0;
@@ -415,6 +431,8 @@
 
 	list_for_each(p, &rfcomm_dev_list) {
 		struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list);
+		if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+			continue;
 		(di + n)->id      = dev->id;
 		(di + n)->flags   = dev->flags;
 		(di + n)->state   = dev->dlc->state;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 91b0170..3fc6972 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -121,6 +121,7 @@
 {
 	struct net_bridge *br = (struct net_bridge *)_data;
 	unsigned long delay = hold_time(br);
+	unsigned long next_timer = jiffies + br->forward_delay;
 	int i;
 
 	spin_lock_bh(&br->hash_lock);
@@ -129,14 +130,21 @@
 		struct hlist_node *h, *n;
 
 		hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) {
-			if (!f->is_static &&
-			    time_before_eq(f->ageing_timer + delay, jiffies))
+			unsigned long this_timer;
+			if (f->is_static)
+				continue;
+			this_timer = f->ageing_timer + delay;
+			if (time_before_eq(this_timer, jiffies))
 				fdb_delete(f);
+			else if (this_timer < next_timer)
+				next_timer = this_timer;
 		}
 	}
 	spin_unlock_bh(&br->hash_lock);
 
-	mod_timer(&br->gc_timer, jiffies + HZ/10);
+	/* Add HZ/4 to ensure we round the jiffies upwards to be after the next
+	 * timer, otherwise we might round down and will have no-op run. */
+	mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4));
 }
 
 /* Completely flush all dynamic entries in forwarding database.*/
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 849deaf..7b4ce91 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -368,10 +368,18 @@
 	list_for_each_entry(p, &br->port_list, list) {
 		unsigned long feature = p->dev->features;
 
+		/* if device needs checksumming, downgrade to hw checksumming */
 		if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
 			checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
+
+		/* if device can't do all checksum, downgrade to ipv4/ipv6 */
 		if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
-			checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
+			checksum ^= NETIF_F_HW_CSUM
+				| NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+		if (checksum & NETIF_F_IPV6_CSUM && !(feature & NETIF_F_IPV6_CSUM))
+			checksum &= ~NETIF_F_IPV6_CSUM;
+
 		if (!(feature & NETIF_F_IP_CSUM))
 			checksum = 0;
 
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 0e035d6..e38034a 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -178,7 +178,8 @@
 		br_send_config_bpdu(p, &bpdu);
 		p->topology_change_ack = 0;
 		p->config_pending = 0;
-		mod_timer(&p->hold_timer, jiffies + BR_HOLD_TIME);
+		mod_timer(&p->hold_timer,
+			  round_jiffies(jiffies + BR_HOLD_TIME));
 	}
 }
 
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 24e0ca4..77f5255 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -42,7 +42,7 @@
 	if (br->dev->flags & IFF_UP) {
 		br_config_bpdu_generation(br);
 
-		mod_timer(&br->hello_timer, jiffies + br->hello_time);
+		mod_timer(&br->hello_timer, round_jiffies(jiffies + br->hello_time));
 	}
 	spin_unlock(&br->lock);
 }
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 33c6c4a..4f42263 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -360,8 +360,9 @@
  *
  * Returns the number of bytes read.
  */
-static ssize_t brforward_read(struct kobject *kobj, char *buf,
-			   loff_t off, size_t count)
+static ssize_t brforward_read(struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t off, size_t count)
 {
 	struct device *dev = to_dev(kobj);
 	struct net_bridge *br = to_bridge(dev);
@@ -383,8 +384,7 @@
 
 static struct bin_attribute bridge_forward = {
 	.attr = { .name = SYSFS_BRIDGE_FDB,
-		  .mode = S_IRUGO,
-		  .owner = THIS_MODULE, },
+		  .mode = S_IRUGO, },
 	.read = brforward_read,
 };
 
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 2da2292..79db51f 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -29,8 +29,7 @@
 #define BRPORT_ATTR(_name,_mode,_show,_store)		        \
 struct brport_attribute brport_attr_##_name = { 	        \
 	.attr = {.name = __stringify(_name), 			\
-		 .mode = _mode, 				\
-		 .owner = THIS_MODULE, },			\
+		 .mode = _mode },				\
 	.show	= _show,					\
 	.store	= _store,					\
 };
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index ac9984f..4169a2a 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1525,14 +1525,14 @@
 	if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
 		return ret;
 
-	printk(KERN_NOTICE "Ebtables v2.0 registered\n");
+	printk(KERN_INFO "Ebtables v2.0 registered\n");
 	return 0;
 }
 
 static void __exit ebtables_fini(void)
 {
 	nf_unregister_sockopt(&ebt_sockopts);
-	printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
+	printk(KERN_INFO "Ebtables v2.0 unregistered\n");
 }
 
 EXPORT_SYMBOL(ebt_register_table);
diff --git a/net/compat.c b/net/compat.c
index 9a0f5f2..d74d821 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -276,7 +276,8 @@
 		err = security_file_receive(fp[i]);
 		if (err)
 			break;
-		err = get_unused_fd();
+		err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & kmsg->msg_flags
+					  ? O_CLOEXEC : 0);
 		if (err < 0)
 			break;
 		new_fd = err;
diff --git a/net/core/dev.c b/net/core/dev.c
index f2b6111..13a0d9f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -98,6 +98,7 @@
 #include <linux/seq_file.h>
 #include <linux/stat.h>
 #include <linux/if_bridge.h>
+#include <linux/if_macvlan.h>
 #include <net/dst.h>
 #include <net/pkt_sched.h>
 #include <net/checksum.h>
@@ -151,9 +152,22 @@
 static struct list_head ptype_all __read_mostly;	/* Taps */
 
 #ifdef CONFIG_NET_DMA
-static struct dma_client *net_dma_client;
-static unsigned int net_dma_count;
-static spinlock_t net_dma_event_lock;
+struct net_dma {
+	struct dma_client client;
+	spinlock_t lock;
+	cpumask_t channel_mask;
+	struct dma_chan *channels[NR_CPUS];
+};
+
+static enum dma_state_client
+netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+	enum dma_state state);
+
+static struct net_dma net_dma = {
+	.client = {
+		.event_callback = netdev_dma_event,
+	},
+};
 #endif
 
 /*
@@ -942,7 +956,7 @@
 		/*
 		 *	Initialize multicasting status
 		 */
-		dev_mc_upload(dev);
+		dev_set_rx_mode(dev);
 
 		/*
 		 *	Wakeup transmit queue engine
@@ -1429,7 +1443,9 @@
 			skb->next = nskb;
 			return rc;
 		}
-		if (unlikely(netif_queue_stopped(dev) && skb->next))
+		if (unlikely((netif_queue_stopped(dev) ||
+			     netif_subqueue_stopped(dev, skb->queue_mapping)) &&
+			     skb->next))
 			return NETDEV_TX_BUSY;
 	} while (skb->next);
 
@@ -1510,8 +1526,10 @@
 					      skb_headroom(skb));
 
 		if (!(dev->features & NETIF_F_GEN_CSUM) &&
-		    (!(dev->features & NETIF_F_IP_CSUM) ||
-		     skb->protocol != htons(ETH_P_IP)))
+		    !((dev->features & NETIF_F_IP_CSUM) &&
+		      skb->protocol == htons(ETH_P_IP)) &&
+		    !((dev->features & NETIF_F_IPV6_CSUM) &&
+		      skb->protocol == htons(ETH_P_IPV6)))
 			if (skb_checksum_help(skb))
 				goto out_kfree_skb;
 	}
@@ -1545,6 +1563,8 @@
 		spin_lock(&dev->queue_lock);
 		q = dev->qdisc;
 		if (q->enqueue) {
+			/* reset queue_mapping to zero */
+			skb->queue_mapping = 0;
 			rc = q->enqueue(skb, q);
 			qdisc_run(dev);
 			spin_unlock(&dev->queue_lock);
@@ -1574,7 +1594,8 @@
 
 			HARD_TX_LOCK(dev, cpu);
 
-			if (!netif_queue_stopped(dev)) {
+			if (!netif_queue_stopped(dev) &&
+			    !netif_subqueue_stopped(dev, skb->queue_mapping)) {
 				rc = 0;
 				if (!dev_hard_start_xmit(skb, dev)) {
 					HARD_TX_UNLOCK(dev);
@@ -1793,6 +1814,28 @@
 #define handle_bridge(skb, pt_prev, ret, orig_dev)	(skb)
 #endif
 
+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
+struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly;
+EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook);
+
+static inline struct sk_buff *handle_macvlan(struct sk_buff *skb,
+					     struct packet_type **pt_prev,
+					     int *ret,
+					     struct net_device *orig_dev)
+{
+	if (skb->dev->macvlan_port == NULL)
+		return skb;
+
+	if (*pt_prev) {
+		*ret = deliver_skb(skb, *pt_prev, orig_dev);
+		*pt_prev = NULL;
+	}
+	return macvlan_handle_frame_hook(skb);
+}
+#else
+#define handle_macvlan(skb, pt_prev, ret, orig_dev)	(skb)
+#endif
+
 #ifdef CONFIG_NET_CLS_ACT
 /* TODO: Maybe we should just force sch_ingress to be compiled in
  * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
@@ -1900,6 +1943,9 @@
 	skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
 	if (!skb)
 		goto out;
+	skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev);
+	if (!skb)
+		goto out;
 
 	type = skb->protocol;
 	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
@@ -2009,20 +2055,21 @@
 		}
 	}
 out:
+	local_irq_enable();
 #ifdef CONFIG_NET_DMA
 	/*
 	 * There may not be any more sk_buffs coming right now, so push
 	 * any pending DMA copies to hardware
 	 */
-	if (net_dma_client) {
-		struct dma_chan *chan;
-		rcu_read_lock();
-		list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node)
-			dma_async_memcpy_issue_pending(chan);
-		rcu_read_unlock();
+	if (!cpus_empty(net_dma.channel_mask)) {
+		int chan_idx;
+		for_each_cpu_mask(chan_idx, net_dma.channel_mask) {
+			struct dma_chan *chan = net_dma.channels[chan_idx];
+			if (chan)
+				dma_async_memcpy_issue_pending(chan);
+		}
 	}
 #endif
-	local_irq_enable();
 	return;
 
 softnet_break:
@@ -2496,6 +2543,32 @@
 	return 0;
 }
 
+static void __dev_set_promiscuity(struct net_device *dev, int inc)
+{
+	unsigned short old_flags = dev->flags;
+
+	ASSERT_RTNL();
+
+	if ((dev->promiscuity += inc) == 0)
+		dev->flags &= ~IFF_PROMISC;
+	else
+		dev->flags |= IFF_PROMISC;
+	if (dev->flags != old_flags) {
+		printk(KERN_INFO "device %s %s promiscuous mode\n",
+		       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
+							       "left");
+		audit_log(current->audit_context, GFP_ATOMIC,
+			AUDIT_ANOM_PROMISCUOUS,
+			"dev=%s prom=%d old_prom=%d auid=%u",
+			dev->name, (dev->flags & IFF_PROMISC),
+			(old_flags & IFF_PROMISC),
+			audit_get_loginuid(current->audit_context));
+
+		if (dev->change_rx_flags)
+			dev->change_rx_flags(dev, IFF_PROMISC);
+	}
+}
+
 /**
  *	dev_set_promiscuity	- update promiscuity count on a device
  *	@dev: device
@@ -2510,22 +2583,9 @@
 {
 	unsigned short old_flags = dev->flags;
 
-	if ((dev->promiscuity += inc) == 0)
-		dev->flags &= ~IFF_PROMISC;
-	else
-		dev->flags |= IFF_PROMISC;
-	if (dev->flags != old_flags) {
-		dev_mc_upload(dev);
-		printk(KERN_INFO "device %s %s promiscuous mode\n",
-		       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
-							       "left");
-		audit_log(current->audit_context, GFP_ATOMIC,
-			AUDIT_ANOM_PROMISCUOUS,
-			"dev=%s prom=%d old_prom=%d auid=%u",
-			dev->name, (dev->flags & IFF_PROMISC),
-			(old_flags & IFF_PROMISC),
-			audit_get_loginuid(current->audit_context));
-	}
+	__dev_set_promiscuity(dev, inc);
+	if (dev->flags != old_flags)
+		dev_set_rx_mode(dev);
 }
 
 /**
@@ -2544,11 +2604,185 @@
 {
 	unsigned short old_flags = dev->flags;
 
+	ASSERT_RTNL();
+
 	dev->flags |= IFF_ALLMULTI;
 	if ((dev->allmulti += inc) == 0)
 		dev->flags &= ~IFF_ALLMULTI;
-	if (dev->flags ^ old_flags)
-		dev_mc_upload(dev);
+	if (dev->flags ^ old_flags) {
+		if (dev->change_rx_flags)
+			dev->change_rx_flags(dev, IFF_ALLMULTI);
+		dev_set_rx_mode(dev);
+	}
+}
+
+/*
+ *	Upload unicast and multicast address lists to device and
+ *	configure RX filtering. When the device doesn't support unicast
+ *	filtering it is put in promiscous mode while unicast addresses
+ *	are present.
+ */
+void __dev_set_rx_mode(struct net_device *dev)
+{
+	/* dev_open will call this function so the list will stay sane. */
+	if (!(dev->flags&IFF_UP))
+		return;
+
+	if (!netif_device_present(dev))
+	        return;
+
+	if (dev->set_rx_mode)
+		dev->set_rx_mode(dev);
+	else {
+		/* Unicast addresses changes may only happen under the rtnl,
+		 * therefore calling __dev_set_promiscuity here is safe.
+		 */
+		if (dev->uc_count > 0 && !dev->uc_promisc) {
+			__dev_set_promiscuity(dev, 1);
+			dev->uc_promisc = 1;
+		} else if (dev->uc_count == 0 && dev->uc_promisc) {
+			__dev_set_promiscuity(dev, -1);
+			dev->uc_promisc = 0;
+		}
+
+		if (dev->set_multicast_list)
+			dev->set_multicast_list(dev);
+	}
+}
+
+void dev_set_rx_mode(struct net_device *dev)
+{
+	netif_tx_lock_bh(dev);
+	__dev_set_rx_mode(dev);
+	netif_tx_unlock_bh(dev);
+}
+
+int __dev_addr_delete(struct dev_addr_list **list, int *count,
+		      void *addr, int alen, int glbl)
+{
+	struct dev_addr_list *da;
+
+	for (; (da = *list) != NULL; list = &da->next) {
+		if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
+		    alen == da->da_addrlen) {
+			if (glbl) {
+				int old_glbl = da->da_gusers;
+				da->da_gusers = 0;
+				if (old_glbl == 0)
+					break;
+			}
+			if (--da->da_users)
+				return 0;
+
+			*list = da->next;
+			kfree(da);
+			(*count)--;
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+int __dev_addr_add(struct dev_addr_list **list, int *count,
+		   void *addr, int alen, int glbl)
+{
+	struct dev_addr_list *da;
+
+	for (da = *list; da != NULL; da = da->next) {
+		if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
+		    da->da_addrlen == alen) {
+			if (glbl) {
+				int old_glbl = da->da_gusers;
+				da->da_gusers = 1;
+				if (old_glbl)
+					return 0;
+			}
+			da->da_users++;
+			return 0;
+		}
+	}
+
+	da = kmalloc(sizeof(*da), GFP_ATOMIC);
+	if (da == NULL)
+		return -ENOMEM;
+	memcpy(da->da_addr, addr, alen);
+	da->da_addrlen = alen;
+	da->da_users = 1;
+	da->da_gusers = glbl ? 1 : 0;
+	da->next = *list;
+	*list = da;
+	(*count)++;
+	return 0;
+}
+
+void __dev_addr_discard(struct dev_addr_list **list)
+{
+	struct dev_addr_list *tmp;
+
+	while (*list != NULL) {
+		tmp = *list;
+		*list = tmp->next;
+		if (tmp->da_users > tmp->da_gusers)
+			printk("__dev_addr_discard: address leakage! "
+			       "da_users=%d\n", tmp->da_users);
+		kfree(tmp);
+	}
+}
+
+/**
+ *	dev_unicast_delete	- Release secondary unicast address.
+ *	@dev: device
+ *
+ *	Release reference to a secondary unicast address and remove it
+ *	from the device if the reference count drop to zero.
+ *
+ * 	The caller must hold the rtnl_mutex.
+ */
+int dev_unicast_delete(struct net_device *dev, void *addr, int alen)
+{
+	int err;
+
+	ASSERT_RTNL();
+
+	netif_tx_lock_bh(dev);
+	err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0);
+	if (!err)
+		__dev_set_rx_mode(dev);
+	netif_tx_unlock_bh(dev);
+	return err;
+}
+EXPORT_SYMBOL(dev_unicast_delete);
+
+/**
+ *	dev_unicast_add		- add a secondary unicast address
+ *	@dev: device
+ *
+ *	Add a secondary unicast address to the device or increase
+ *	the reference count if it already exists.
+ *
+ *	The caller must hold the rtnl_mutex.
+ */
+int dev_unicast_add(struct net_device *dev, void *addr, int alen)
+{
+	int err;
+
+	ASSERT_RTNL();
+
+	netif_tx_lock_bh(dev);
+	err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0);
+	if (!err)
+		__dev_set_rx_mode(dev);
+	netif_tx_unlock_bh(dev);
+	return err;
+}
+EXPORT_SYMBOL(dev_unicast_add);
+
+static void dev_unicast_discard(struct net_device *dev)
+{
+	netif_tx_lock_bh(dev);
+	__dev_addr_discard(&dev->uc_list);
+	dev->uc_count = 0;
+	netif_tx_unlock_bh(dev);
 }
 
 unsigned dev_get_flags(const struct net_device *dev)
@@ -2577,9 +2811,11 @@
 
 int dev_change_flags(struct net_device *dev, unsigned flags)
 {
-	int ret;
+	int ret, changes;
 	int old_flags = dev->flags;
 
+	ASSERT_RTNL();
+
 	/*
 	 *	Set the flags on our device.
 	 */
@@ -2594,7 +2830,10 @@
 	 *	Load in the correct multicast list now the flags have changed.
 	 */
 
-	dev_mc_upload(dev);
+	if (dev->change_rx_flags && (dev->flags ^ flags) & IFF_MULTICAST)
+		dev->change_rx_flags(dev, IFF_MULTICAST);
+
+	dev_set_rx_mode(dev);
 
 	/*
 	 *	Have we downed the interface. We handle IFF_UP ourselves
@@ -2607,7 +2846,7 @@
 		ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
 
 		if (!ret)
-			dev_mc_upload(dev);
+			dev_set_rx_mode(dev);
 	}
 
 	if (dev->flags & IFF_UP &&
@@ -2632,8 +2871,10 @@
 		dev_set_allmulti(dev, inc);
 	}
 
-	if (old_flags ^ dev->flags)
-		rtmsg_ifinfo(RTM_NEWLINK, dev, old_flags ^ dev->flags);
+	/* Exclude state transition flags, already notified */
+	changes = (old_flags ^ dev->flags) & ~(IFF_UP | IFF_RUNNING);
+	if (changes)
+		rtmsg_ifinfo(RTM_NEWLINK, dev, changes);
 
 	return ret;
 }
@@ -3105,6 +3346,22 @@
 		}
 	}
 
+	/* Fix illegal checksum combinations */
+	if ((dev->features & NETIF_F_HW_CSUM) &&
+	    (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+		printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n",
+		       dev->name);
+		dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
+	}
+
+	if ((dev->features & NETIF_F_NO_CSUM) &&
+	    (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+		printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n",
+		       dev->name);
+		dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
+	}
+
+
 	/* Fix illegal SG+CSUM combinations. */
 	if ((dev->features & NETIF_F_SG) &&
 	    !(dev->features & NETIF_F_ALL_CSUM)) {
@@ -3314,7 +3571,6 @@
 			continue;
 		}
 
-		netdev_unregister_sysfs(dev);
 		dev->reg_state = NETREG_UNREGISTERED;
 
 		netdev_wait_allrefs(dev);
@@ -3325,11 +3581,11 @@
 		BUG_TRAP(!dev->ip6_ptr);
 		BUG_TRAP(!dev->dn_ptr);
 
-		/* It must be the very last action,
-		 * after this 'dev' may point to freed up memory.
-		 */
 		if (dev->destructor)
 			dev->destructor(dev);
+
+		/* Free network device */
+		kobject_put(&dev->dev.kobj);
 	}
 
 out:
@@ -3342,16 +3598,18 @@
 }
 
 /**
- *	alloc_netdev - allocate network device
+ *	alloc_netdev_mq - allocate network device
  *	@sizeof_priv:	size of private data to allocate space for
  *	@name:		device name format string
  *	@setup:		callback to initialize device
+ *	@queue_count:	the number of subqueues to allocate
  *
  *	Allocates a struct net_device with private data area for driver use
- *	and performs basic initialization.
+ *	and performs basic initialization.  Also allocates subquue structs
+ *	for each queue on the device at the end of the netdevice.
  */
-struct net_device *alloc_netdev(int sizeof_priv, const char *name,
-		void (*setup)(struct net_device *))
+struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+		void (*setup)(struct net_device *), unsigned int queue_count)
 {
 	void *p;
 	struct net_device *dev;
@@ -3360,7 +3618,9 @@
 	BUG_ON(strlen(name) >= sizeof(dev->name));
 
 	/* ensure 32-byte alignment of both the device and private area */
-	alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
+	alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST +
+		     (sizeof(struct net_device_subqueue) * queue_count)) &
+		     ~NETDEV_ALIGN_CONST;
 	alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
 
 	p = kzalloc(alloc_size, GFP_KERNEL);
@@ -3373,15 +3633,22 @@
 		(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
 	dev->padded = (char *)dev - (char *)p;
 
-	if (sizeof_priv)
-		dev->priv = netdev_priv(dev);
+	if (sizeof_priv) {
+		dev->priv = ((char *)dev +
+			     ((sizeof(struct net_device) +
+			       (sizeof(struct net_device_subqueue) *
+				queue_count) + NETDEV_ALIGN_CONST)
+			      & ~NETDEV_ALIGN_CONST));
+	}
+
+	dev->egress_subqueue_count = queue_count;
 
 	dev->get_stats = internal_stats;
 	setup(dev);
 	strcpy(dev->name, name);
 	return dev;
 }
-EXPORT_SYMBOL(alloc_netdev);
+EXPORT_SYMBOL(alloc_netdev_mq);
 
 /**
  *	free_netdev - free network device
@@ -3470,8 +3737,9 @@
 	raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
 
 	/*
-	 *	Flush the multicast chain
+	 *	Flush the unicast and multicast chains
 	 */
+	dev_unicast_discard(dev);
 	dev_mc_discard(dev);
 
 	if (dev->uninit)
@@ -3480,6 +3748,9 @@
 	/* Notifier chain MUST detach us from master device. */
 	BUG_TRAP(!dev->master);
 
+	/* Remove entries from sysfs */
+	netdev_unregister_sysfs(dev);
+
 	/* Finish processing unregister after unlock */
 	net_set_todo(dev);
 
@@ -3559,12 +3830,13 @@
  * This is called when the number of channels allocated to the net_dma_client
  * changes.  The net_dma_client tries to have one DMA channel per CPU.
  */
-static void net_dma_rebalance(void)
+
+static void net_dma_rebalance(struct net_dma *net_dma)
 {
-	unsigned int cpu, i, n;
+	unsigned int cpu, i, n, chan_idx;
 	struct dma_chan *chan;
 
-	if (net_dma_count == 0) {
+	if (cpus_empty(net_dma->channel_mask)) {
 		for_each_online_cpu(cpu)
 			rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL);
 		return;
@@ -3573,10 +3845,12 @@
 	i = 0;
 	cpu = first_cpu(cpu_online_map);
 
-	rcu_read_lock();
-	list_for_each_entry(chan, &net_dma_client->channels, client_node) {
-		n = ((num_online_cpus() / net_dma_count)
-		   + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
+	for_each_cpu_mask(chan_idx, net_dma->channel_mask) {
+		chan = net_dma->channels[chan_idx];
+
+		n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask))
+		   + (i < (num_online_cpus() %
+			cpus_weight(net_dma->channel_mask)) ? 1 : 0));
 
 		while(n) {
 			per_cpu(softnet_data, cpu).net_dma = chan;
@@ -3585,7 +3859,6 @@
 		}
 		i++;
 	}
-	rcu_read_unlock();
 }
 
 /**
@@ -3594,23 +3867,53 @@
  * @chan: DMA channel for the event
  * @event: event type
  */
-static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
-	enum dma_event event)
+static enum dma_state_client
+netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+	enum dma_state state)
 {
-	spin_lock(&net_dma_event_lock);
-	switch (event) {
-	case DMA_RESOURCE_ADDED:
-		net_dma_count++;
-		net_dma_rebalance();
+	int i, found = 0, pos = -1;
+	struct net_dma *net_dma =
+		container_of(client, struct net_dma, client);
+	enum dma_state_client ack = DMA_DUP; /* default: take no action */
+
+	spin_lock(&net_dma->lock);
+	switch (state) {
+	case DMA_RESOURCE_AVAILABLE:
+		for (i = 0; i < NR_CPUS; i++)
+			if (net_dma->channels[i] == chan) {
+				found = 1;
+				break;
+			} else if (net_dma->channels[i] == NULL && pos < 0)
+				pos = i;
+
+		if (!found && pos >= 0) {
+			ack = DMA_ACK;
+			net_dma->channels[pos] = chan;
+			cpu_set(pos, net_dma->channel_mask);
+			net_dma_rebalance(net_dma);
+		}
 		break;
 	case DMA_RESOURCE_REMOVED:
-		net_dma_count--;
-		net_dma_rebalance();
+		for (i = 0; i < NR_CPUS; i++)
+			if (net_dma->channels[i] == chan) {
+				found = 1;
+				pos = i;
+				break;
+			}
+
+		if (found) {
+			ack = DMA_ACK;
+			cpu_clear(pos, net_dma->channel_mask);
+			net_dma->channels[i] = NULL;
+			net_dma_rebalance(net_dma);
+		}
 		break;
 	default:
 		break;
 	}
-	spin_unlock(&net_dma_event_lock);
+	spin_unlock(&net_dma->lock);
+
+	return ack;
 }
 
 /**
@@ -3618,12 +3921,10 @@
  */
 static int __init netdev_dma_register(void)
 {
-	spin_lock_init(&net_dma_event_lock);
-	net_dma_client = dma_async_client_register(netdev_dma_event);
-	if (net_dma_client == NULL)
-		return -ENOMEM;
-
-	dma_async_client_chan_request(net_dma_client, num_online_cpus());
+	spin_lock_init(&net_dma.lock);
+	dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask);
+	dma_async_client_register(&net_dma.client);
+	dma_async_client_chan_request(&net_dma.client);
 	return 0;
 }
 
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 5a54053..235a2a8 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -64,85 +64,24 @@
  */
 
 /*
- *	Update the multicast list into the physical NIC controller.
- */
-
-static void __dev_mc_upload(struct net_device *dev)
-{
-	/* Don't do anything till we up the interface
-	 * [dev_open will call this function so the list will
-	 * stay sane]
-	 */
-
-	if (!(dev->flags&IFF_UP))
-		return;
-
-	/*
-	 *	Devices with no set multicast or which have been
-	 *	detached don't get set.
-	 */
-
-	if (dev->set_multicast_list == NULL ||
-	    !netif_device_present(dev))
-		return;
-
-	dev->set_multicast_list(dev);
-}
-
-void dev_mc_upload(struct net_device *dev)
-{
-	netif_tx_lock_bh(dev);
-	__dev_mc_upload(dev);
-	netif_tx_unlock_bh(dev);
-}
-
-/*
  *	Delete a device level multicast
  */
 
 int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
 {
-	int err = 0;
-	struct dev_mc_list *dmi, **dmip;
+	int err;
 
 	netif_tx_lock_bh(dev);
-
-	for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
+	err = __dev_addr_delete(&dev->mc_list, &dev->mc_count,
+				addr, alen, glbl);
+	if (!err) {
 		/*
-		 *	Find the entry we want to delete. The device could
-		 *	have variable length entries so check these too.
+		 *	We have altered the list, so the card
+		 *	loaded filter is now wrong. Fix it
 		 */
-		if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
-		    alen == dmi->dmi_addrlen) {
-			if (glbl) {
-				int old_glbl = dmi->dmi_gusers;
-				dmi->dmi_gusers = 0;
-				if (old_glbl == 0)
-					break;
-			}
-			if (--dmi->dmi_users)
-				goto done;
 
-			/*
-			 *	Last user. So delete the entry.
-			 */
-			*dmip = dmi->next;
-			dev->mc_count--;
-
-			kfree(dmi);
-
-			/*
-			 *	We have altered the list, so the card
-			 *	loaded filter is now wrong. Fix it
-			 */
-			__dev_mc_upload(dev);
-
-			netif_tx_unlock_bh(dev);
-			return 0;
-		}
+		__dev_set_rx_mode(dev);
 	}
-	err = -ENOENT;
-done:
 	netif_tx_unlock_bh(dev);
 	return err;
 }
@@ -153,49 +92,91 @@
 
 int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
 {
-	int err = 0;
-	struct dev_mc_list *dmi, *dmi1;
-
-	dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
+	int err;
 
 	netif_tx_lock_bh(dev);
-	for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
-		if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
-		    dmi->dmi_addrlen == alen) {
-			if (glbl) {
-				int old_glbl = dmi->dmi_gusers;
-				dmi->dmi_gusers = 1;
-				if (old_glbl)
-					goto done;
-			}
-			dmi->dmi_users++;
-			goto done;
-		}
-	}
-
-	if ((dmi = dmi1) == NULL) {
-		netif_tx_unlock_bh(dev);
-		return -ENOMEM;
-	}
-	memcpy(dmi->dmi_addr, addr, alen);
-	dmi->dmi_addrlen = alen;
-	dmi->next = dev->mc_list;
-	dmi->dmi_users = 1;
-	dmi->dmi_gusers = glbl ? 1 : 0;
-	dev->mc_list = dmi;
-	dev->mc_count++;
-
-	__dev_mc_upload(dev);
-
+	err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl);
+	if (!err)
+		__dev_set_rx_mode(dev);
 	netif_tx_unlock_bh(dev);
-	return 0;
-
-done:
-	netif_tx_unlock_bh(dev);
-	kfree(dmi1);
 	return err;
 }
 
+/**
+ *	dev_mc_sync	- Synchronize device's multicast list to another device
+ *	@to: destination device
+ *	@from: source device
+ *
+ * 	Add newly added addresses to the destination device and release
+ * 	addresses that have no users left. The source device must be
+ * 	locked by netif_tx_lock_bh.
+ *
+ *	This function is intended to be called from the dev->set_multicast_list
+ *	function of layered software devices.
+ */
+int dev_mc_sync(struct net_device *to, struct net_device *from)
+{
+	struct dev_addr_list *da;
+	int err = 0;
+
+	netif_tx_lock_bh(to);
+	for (da = from->mc_list; da != NULL; da = da->next) {
+		if (!da->da_synced) {
+			err = __dev_addr_add(&to->mc_list, &to->mc_count,
+					     da->da_addr, da->da_addrlen, 0);
+			if (err < 0)
+				break;
+			da->da_synced = 1;
+			da->da_users++;
+		} else if (da->da_users == 1) {
+			__dev_addr_delete(&to->mc_list, &to->mc_count,
+					  da->da_addr, da->da_addrlen, 0);
+			__dev_addr_delete(&from->mc_list, &from->mc_count,
+					  da->da_addr, da->da_addrlen, 0);
+		}
+	}
+	if (!err)
+		__dev_set_rx_mode(to);
+	netif_tx_unlock_bh(to);
+
+	return err;
+}
+EXPORT_SYMBOL(dev_mc_sync);
+
+
+/**
+ * 	dev_mc_unsync	- Remove synchronized addresses from the destination
+ * 			  device
+ *	@to: destination device
+ *	@from: source device
+ *
+ * 	Remove all addresses that were added to the destination device by
+ * 	dev_mc_sync(). This function is intended to be called from the
+ * 	dev->stop function of layered software devices.
+ */
+void dev_mc_unsync(struct net_device *to, struct net_device *from)
+{
+	struct dev_addr_list *da;
+
+	netif_tx_lock_bh(from);
+	netif_tx_lock_bh(to);
+
+	for (da = from->mc_list; da != NULL; da = da->next) {
+		if (!da->da_synced)
+			continue;
+		__dev_addr_delete(&to->mc_list, &to->mc_count,
+				  da->da_addr, da->da_addrlen, 0);
+		da->da_synced = 0;
+		__dev_addr_delete(&from->mc_list, &from->mc_count,
+				  da->da_addr, da->da_addrlen, 0);
+	}
+	__dev_set_rx_mode(to);
+
+	netif_tx_unlock_bh(to);
+	netif_tx_unlock_bh(from);
+}
+EXPORT_SYMBOL(dev_mc_unsync);
+
 /*
  *	Discard multicast list when a device is downed
  */
@@ -203,16 +184,8 @@
 void dev_mc_discard(struct net_device *dev)
 {
 	netif_tx_lock_bh(dev);
-
-	while (dev->mc_list != NULL) {
-		struct dev_mc_list *tmp = dev->mc_list;
-		dev->mc_list = tmp->next;
-		if (tmp->dmi_users > tmp->dmi_gusers)
-			printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users);
-		kfree(tmp);
-	}
+	__dev_addr_discard(&dev->mc_list);
 	dev->mc_count = 0;
-
 	netif_tx_unlock_bh(dev);
 }
 
@@ -244,7 +217,7 @@
 
 static int dev_mc_seq_show(struct seq_file *seq, void *v)
 {
-	struct dev_mc_list *m;
+	struct dev_addr_list *m;
 	struct net_device *dev = v;
 
 	netif_tx_lock_bh(dev);
@@ -292,4 +265,3 @@
 
 EXPORT_SYMBOL(dev_mc_add);
 EXPORT_SYMBOL(dev_mc_delete);
-EXPORT_SYMBOL(dev_mc_upload);
diff --git a/net/core/dst.c b/net/core/dst.c
index 764bccb..c6a05879 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -111,13 +111,7 @@
 	spin_unlock(&dst_lock);
 }
 
-static int dst_discard_in(struct sk_buff *skb)
-{
-	kfree_skb(skb);
-	return 0;
-}
-
-static int dst_discard_out(struct sk_buff *skb)
+static int dst_discard(struct sk_buff *skb)
 {
 	kfree_skb(skb);
 	return 0;
@@ -138,8 +132,7 @@
 	dst->ops = ops;
 	dst->lastuse = jiffies;
 	dst->path = dst;
-	dst->input = dst_discard_in;
-	dst->output = dst_discard_out;
+	dst->input = dst->output = dst_discard;
 #if RT_CACHE_DEBUG >= 2
 	atomic_inc(&dst_total);
 #endif
@@ -153,8 +146,7 @@
 	   protocol module is unloaded.
 	 */
 	if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) {
-		dst->input = dst_discard_in;
-		dst->output = dst_discard_out;
+		dst->input = dst->output = dst_discard;
 	}
 	dst->obsolete = 2;
 }
@@ -242,8 +234,7 @@
 		return;
 
 	if (!unregister) {
-		dst->input = dst_discard_in;
-		dst->output = dst_discard_out;
+		dst->input = dst->output = dst_discard;
 	} else {
 		dst->dev = &loopback_dev;
 		dev_hold(&loopback_dev);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 8d5e5a0..0b531e9 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -52,6 +52,17 @@
 
 	return 0;
 }
+
+int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data)
+{
+	if (data)
+		dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	else
+		dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+
+	return 0;
+}
+
 u32 ethtool_op_get_sg(struct net_device *dev)
 {
 	return (dev->features & NETIF_F_SG) != 0;
@@ -980,5 +991,6 @@
 EXPORT_SYMBOL(ethtool_op_set_tso);
 EXPORT_SYMBOL(ethtool_op_set_tx_csum);
 EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
+EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum);
 EXPORT_SYMBOL(ethtool_op_set_ufo);
 EXPORT_SYMBOL(ethtool_op_get_ufo);
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index 17daf4c..cc84d8d 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -128,7 +128,8 @@
 		spin_unlock(e->stats_lock);
 	}
 
-	mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
+	if (elist[idx].list != NULL)
+		mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
 	read_unlock(&est_lock);
 }
 
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 6f3bb73..9df26a0 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1761,7 +1761,7 @@
 	return NULL;
 }
 
-static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = {
+static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
 	[NDTA_NAME]		= { .type = NLA_STRING },
 	[NDTA_THRESH1]		= { .type = NLA_U32 },
 	[NDTA_THRESH2]		= { .type = NLA_U32 },
@@ -1770,7 +1770,7 @@
 	[NDTA_PARMS]		= { .type = NLA_NESTED },
 };
 
-static struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] __read_mostly = {
+static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
 	[NDTPA_IFINDEX]			= { .type = NLA_U32 },
 	[NDTPA_QUEUE_LEN]		= { .type = NLA_U32 },
 	[NDTPA_PROXY_QLEN]		= { .type = NLA_U32 },
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b21307b..5c19b06 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -456,9 +456,15 @@
 #endif
 };
 
+/* Delete sysfs entries but hold kobject reference until after all
+ * netdev references are gone.
+ */
 void netdev_unregister_sysfs(struct net_device * net)
 {
-	device_del(&(net->dev));
+	struct device *dev = &(net->dev);
+
+	kobject_get(&dev->kobj);
+	device_del(dev);
 }
 
 /* Create sysfs entries for network device. */
diff --git a/net/core/netevent.c b/net/core/netevent.c
index 35d02c3..95f81de 100644
--- a/net/core/netevent.c
+++ b/net/core/netevent.c
@@ -15,6 +15,7 @@
 
 #include <linux/rtnetlink.h>
 #include <linux/notifier.h>
+#include <net/netevent.h>
 
 static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain);
 
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 758dafe..de1b26a 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -66,8 +66,9 @@
 
 		local_irq_save(flags);
 		netif_tx_lock(dev);
-		if (netif_queue_stopped(dev) ||
-		    dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
+		if ((netif_queue_stopped(dev) ||
+		     netif_subqueue_stopped(dev, skb->queue_mapping)) ||
+		     dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
 			skb_queue_head(&npinfo->txq, skb);
 			netif_tx_unlock(dev);
 			local_irq_restore(flags);
@@ -250,22 +251,24 @@
 		unsigned long flags;
 
 		local_irq_save(flags);
-		if (netif_tx_trylock(dev)) {
-			/* try until next clock tick */
-			for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
-					tries > 0; --tries) {
-				if (!netif_queue_stopped(dev))
+		/* try until next clock tick */
+		for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
+		     tries > 0; --tries) {
+			if (netif_tx_trylock(dev)) {
+				if (!netif_queue_stopped(dev) &&
+				    !netif_subqueue_stopped(dev, skb->queue_mapping))
 					status = dev->hard_start_xmit(skb, dev);
+				netif_tx_unlock(dev);
 
 				if (status == NETDEV_TX_OK)
 					break;
 
-				/* tickle device maybe there is some cleanup */
-				netpoll_poll(np);
-
-				udelay(USEC_PER_POLL);
 			}
-			netif_tx_unlock(dev);
+
+			/* tickle device maybe there is some cleanup */
+			netpoll_poll(np);
+
+			udelay(USEC_PER_POLL);
 		}
 		local_irq_restore(flags);
 	}
@@ -780,14 +783,19 @@
 				spin_unlock_irqrestore(&npinfo->rx_lock, flags);
 			}
 
-			np->dev->npinfo = NULL;
 			if (atomic_dec_and_test(&npinfo->refcnt)) {
 				skb_queue_purge(&npinfo->arp_tx);
 				skb_queue_purge(&npinfo->txq);
 				cancel_rearming_delayed_work(&npinfo->tx_work);
-				flush_scheduled_work();
 
+				/* clean after last, unfinished work */
+				if (!skb_queue_empty(&npinfo->txq)) {
+					struct sk_buff *skb;
+					skb = __skb_dequeue(&npinfo->txq);
+					kfree_skb(skb);
+				}
 				kfree(npinfo);
+				np->dev->npinfo = NULL;
 			}
 		}
 
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 9cd3a1c..bca787f 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -152,6 +152,9 @@
 #include <net/checksum.h>
 #include <net/ipv6.h>
 #include <net/addrconf.h>
+#ifdef CONFIG_XFRM
+#include <net/xfrm.h>
+#endif
 #include <asm/byteorder.h>
 #include <linux/rcupdate.h>
 #include <asm/bitops.h>
@@ -181,6 +184,8 @@
 #define F_MPLS_RND    (1<<8)	/* Random MPLS labels */
 #define F_VID_RND     (1<<9)	/* Random VLAN ID */
 #define F_SVID_RND    (1<<10)	/* Random SVLAN ID */
+#define F_FLOW_SEQ    (1<<11)	/* Sequential flows */
+#define F_IPSEC_ON    (1<<12)	/* ipsec on for flows */
 
 /* Thread control flag bits */
 #define T_TERMINATE   (1<<0)
@@ -207,8 +212,15 @@
 struct flow_state {
 	__be32 cur_daddr;
 	int count;
+#ifdef CONFIG_XFRM
+	struct xfrm_state *x;
+#endif
+	__u32 flags;
 };
 
+/* flow flag bits */
+#define F_INIT   (1<<0)		/* flow has been initialized */
+
 struct pktgen_dev {
 	/*
 	 * Try to keep frequent/infrequent used vars. separated.
@@ -228,6 +240,7 @@
 
 	int min_pkt_size;	/* = ETH_ZLEN; */
 	int max_pkt_size;	/* = ETH_ZLEN; */
+	int pkt_overhead;	/* overhead for MPLS, VLANs, IPSEC etc */
 	int nfrags;
 	__u32 delay_us;		/* Default delay */
 	__u32 delay_ns;
@@ -341,7 +354,11 @@
 	unsigned cflows;	/* Concurrent flows (config) */
 	unsigned lflow;		/* Flow length  (config) */
 	unsigned nflows;	/* accumulated flows (stats) */
-
+	unsigned curfl;		/* current sequenced flow (state)*/
+#ifdef CONFIG_XFRM
+	__u8	ipsmode;		/* IPSEC mode (config) */
+	__u8	ipsproto;		/* IPSEC type (config) */
+#endif
 	char result[512];
 };
 
@@ -690,6 +707,18 @@
 	if (pkt_dev->flags & F_MPLS_RND)
 		seq_printf(seq,  "MPLS_RND  ");
 
+	if (pkt_dev->cflows) {
+		if (pkt_dev->flags & F_FLOW_SEQ)
+			seq_printf(seq,  "FLOW_SEQ  "); /*in sequence flows*/
+		else
+			seq_printf(seq,  "FLOW_RND  ");
+	}
+
+#ifdef CONFIG_XFRM
+	if (pkt_dev->flags & F_IPSEC_ON)
+		seq_printf(seq,  "IPSEC  ");
+#endif
+
 	if (pkt_dev->flags & F_MACSRC_RND)
 		seq_printf(seq, "MACSRC_RND  ");
 
@@ -1181,6 +1210,14 @@
 		else if (strcmp(f, "!SVID_RND") == 0)
 			pkt_dev->flags &= ~F_SVID_RND;
 
+		else if (strcmp(f, "FLOW_SEQ") == 0)
+			pkt_dev->flags |= F_FLOW_SEQ;
+
+#ifdef CONFIG_XFRM
+		else if (strcmp(f, "IPSEC") == 0)
+			pkt_dev->flags |= F_IPSEC_ON;
+#endif
+
 		else if (strcmp(f, "!IPV6") == 0)
 			pkt_dev->flags &= ~F_IPV6;
 
@@ -1189,7 +1226,7 @@
 				"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
 				f,
 				"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, "
-				"MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n");
+				"MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n");
 			return count;
 		}
 		sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
@@ -2075,6 +2112,70 @@
 	pkt_dev->idle_acc += now - start;
 }
 
+static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
+{
+	pkt_dev->pkt_overhead = 0;
+	pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32);
+	pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev);
+	pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev);
+}
+
+static inline int f_seen(struct pktgen_dev *pkt_dev, int flow)
+{
+
+	if (pkt_dev->flows[flow].flags & F_INIT)
+		return 1;
+	else
+		return 0;
+}
+
+static inline int f_pick(struct pktgen_dev *pkt_dev)
+{
+	int flow = pkt_dev->curfl;
+
+	if (pkt_dev->flags & F_FLOW_SEQ) {
+		if (pkt_dev->flows[flow].count >= pkt_dev->lflow) {
+			/* reset time */
+			pkt_dev->flows[flow].count = 0;
+			pkt_dev->curfl += 1;
+			if (pkt_dev->curfl >= pkt_dev->cflows)
+				pkt_dev->curfl = 0; /*reset */
+		}
+	} else {
+		flow = random32() % pkt_dev->cflows;
+
+		if (pkt_dev->flows[flow].count > pkt_dev->lflow)
+			pkt_dev->flows[flow].count = 0;
+	}
+
+	return pkt_dev->curfl;
+}
+
+
+#ifdef CONFIG_XFRM
+/* If there was already an IPSEC SA, we keep it as is, else
+ * we go look for it ...
+*/
+inline
+void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
+{
+	struct xfrm_state *x = pkt_dev->flows[flow].x;
+	if (!x) {
+		/*slow path: we dont already have xfrm_state*/
+		x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr,
+					(xfrm_address_t *)&pkt_dev->cur_saddr,
+					AF_INET,
+					pkt_dev->ipsmode,
+					pkt_dev->ipsproto, 0);
+		if (x) {
+			pkt_dev->flows[flow].x = x;
+			set_pkt_overhead(pkt_dev);
+			pkt_dev->pkt_overhead+=x->props.header_len;
+		}
+
+	}
+}
+#endif
 /* Increment/randomize headers according to flags and current values
  * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
  */
@@ -2084,12 +2185,8 @@
 	__u32 imx;
 	int flow = 0;
 
-	if (pkt_dev->cflows) {
-		flow = random32() % pkt_dev->cflows;
-
-		if (pkt_dev->flows[flow].count > pkt_dev->lflow)
-			pkt_dev->flows[flow].count = 0;
-	}
+	if (pkt_dev->cflows)
+		flow = f_pick(pkt_dev);
 
 	/*  Deal with source MAC */
 	if (pkt_dev->src_mac_count > 1) {
@@ -2205,7 +2302,7 @@
 			pkt_dev->cur_saddr = htonl(t);
 		}
 
-		if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) {
+		if (pkt_dev->cflows && f_seen(pkt_dev, flow)) {
 			pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
 		} else {
 			imn = ntohl(pkt_dev->daddr_min);
@@ -2235,8 +2332,13 @@
 				}
 			}
 			if (pkt_dev->cflows) {
+				pkt_dev->flows[flow].flags |= F_INIT;
 				pkt_dev->flows[flow].cur_daddr =
 				    pkt_dev->cur_daddr;
+#ifdef CONFIG_XFRM
+				if (pkt_dev->flags & F_IPSEC_ON)
+					get_ipsec_sa(pkt_dev, flow);
+#endif
 				pkt_dev->nflows++;
 			}
 		}
@@ -2277,6 +2379,91 @@
 	pkt_dev->flows[flow].count++;
 }
 
+
+#ifdef CONFIG_XFRM
+static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
+{
+	struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
+	int err = 0;
+	struct iphdr *iph;
+
+	if (!x)
+		return 0;
+	/* XXX: we dont support tunnel mode for now until
+	 * we resolve the dst issue */
+	if (x->props.mode != XFRM_MODE_TRANSPORT)
+		return 0;
+
+	spin_lock(&x->lock);
+	iph = ip_hdr(skb);
+
+	err = x->mode->output(x, skb);
+	if (err)
+		goto error;
+	err = x->type->output(x, skb);
+	if (err)
+		goto error;
+
+	x->curlft.bytes +=skb->len;
+	x->curlft.packets++;
+	spin_unlock(&x->lock);
+
+error:
+	spin_unlock(&x->lock);
+	return err;
+}
+
+static inline void free_SAs(struct pktgen_dev *pkt_dev)
+{
+	if (pkt_dev->cflows) {
+		/* let go of the SAs if we have them */
+		int i = 0;
+		for (;  i < pkt_dev->nflows; i++){
+			struct xfrm_state *x = pkt_dev->flows[i].x;
+			if (x) {
+				xfrm_state_put(x);
+				pkt_dev->flows[i].x = NULL;
+			}
+		}
+	}
+}
+
+static inline int process_ipsec(struct pktgen_dev *pkt_dev,
+			      struct sk_buff *skb, __be16 protocol)
+{
+	if (pkt_dev->flags & F_IPSEC_ON) {
+		struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
+		int nhead = 0;
+		if (x) {
+			int ret;
+			__u8 *eth;
+			nhead = x->props.header_len - skb_headroom(skb);
+			if (nhead >0) {
+				ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
+				if (ret < 0) {
+					printk("Error expanding ipsec packet %d\n",ret);
+					return 0;
+				}
+			}
+
+			/* ipsec is not expecting ll header */
+			skb_pull(skb, ETH_HLEN);
+			ret = pktgen_output_ipsec(skb, pkt_dev);
+			if (ret) {
+				printk("Error creating ipsec packet %d\n",ret);
+				kfree_skb(skb);
+				return 0;
+			}
+			/* restore ll */
+			eth = (__u8 *) skb_push(skb, ETH_HLEN);
+			memcpy(eth, pkt_dev->hh, 12);
+			*(u16 *) & eth[12] = protocol;
+		}
+	}
+	return 1;
+}
+#endif
+
 static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
 {
 	unsigned i;
@@ -2323,9 +2510,7 @@
 
 	datalen = (odev->hard_header_len + 16) & ~0xf;
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
-			pkt_dev->nr_labels*sizeof(u32) +
-			VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
-			GFP_ATOMIC);
+			pkt_dev->pkt_overhead, GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
@@ -2368,7 +2553,7 @@
 
 	/* Eth + IPh + UDPh + mpls */
 	datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
-		  pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
+		  pkt_dev->pkt_overhead;
 	if (datalen < sizeof(struct pktgen_hdr))
 		datalen = sizeof(struct pktgen_hdr);
 
@@ -2391,8 +2576,7 @@
 	iph->check = ip_fast_csum((void *)iph, iph->ihl);
 	skb->protocol = protocol;
 	skb->mac_header = (skb->network_header - ETH_HLEN -
-			   pkt_dev->nr_labels * sizeof(u32) -
-			   VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev));
+			   pkt_dev->pkt_overhead);
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
 
@@ -2463,6 +2647,11 @@
 		pgh->tv_usec = htonl(timestamp.tv_usec);
 	}
 
+#ifdef CONFIG_XFRM
+	if (!process_ipsec(pkt_dev, skb, protocol))
+		return NULL;
+#endif
+
 	return skb;
 }
 
@@ -2662,9 +2851,7 @@
 	mod_cur_headers(pkt_dev);
 
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
-			pkt_dev->nr_labels*sizeof(u32) +
-			VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
-			GFP_ATOMIC);
+			pkt_dev->pkt_overhead, GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
@@ -2708,7 +2895,7 @@
 	/* Eth + IPh + UDPh + mpls */
 	datalen = pkt_dev->cur_pkt_size - 14 -
 		  sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
-		  pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
+		  pkt_dev->pkt_overhead;
 
 	if (datalen < sizeof(struct pktgen_hdr)) {
 		datalen = sizeof(struct pktgen_hdr);
@@ -2738,8 +2925,7 @@
 	ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
 
 	skb->mac_header = (skb->network_header - ETH_HLEN -
-			   pkt_dev->nr_labels * sizeof(u32) -
-			   VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev));
+			   pkt_dev->pkt_overhead);
 	skb->protocol = protocol;
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
@@ -2857,6 +3043,7 @@
 			pkt_dev->started_at = getCurUs();
 			pkt_dev->next_tx_us = getCurUs();	/* Transmit immediately */
 			pkt_dev->next_tx_ns = 0;
+			set_pkt_overhead(pkt_dev);
 
 			strcpy(pkt_dev->result, "Starting");
 			started++;
@@ -3139,7 +3326,9 @@
 		}
 	}
 
-	if (netif_queue_stopped(odev) || need_resched()) {
+	if ((netif_queue_stopped(odev) ||
+	     netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) ||
+	     need_resched()) {
 		idle_start = getCurUs();
 
 		if (!netif_running(odev)) {
@@ -3154,7 +3343,8 @@
 
 		pkt_dev->idle_acc += getCurUs() - idle_start;
 
-		if (netif_queue_stopped(odev)) {
+		if (netif_queue_stopped(odev) ||
+		    netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) {
 			pkt_dev->next_tx_us = getCurUs();	/* TODO */
 			pkt_dev->next_tx_ns = 0;
 			goto out;	/* Try the next interface */
@@ -3181,7 +3371,8 @@
 	}
 
 	netif_tx_lock_bh(odev);
-	if (!netif_queue_stopped(odev)) {
+	if (!netif_queue_stopped(odev) &&
+	    !netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) {
 
 		atomic_inc(&(pkt_dev->skb->users));
 	      retry_now:
@@ -3274,6 +3465,8 @@
 
 	set_current_state(TASK_INTERRUPTIBLE);
 
+	set_freezable();
+
 	while (!kthread_should_stop()) {
 		pkt_dev = next_to_run(t);
 
@@ -3446,11 +3639,18 @@
 	}
 	pkt_dev->entry->proc_fops = &pktgen_if_fops;
 	pkt_dev->entry->data = pkt_dev;
+#ifdef CONFIG_XFRM
+	pkt_dev->ipsmode = XFRM_MODE_TRANSPORT;
+	pkt_dev->ipsproto = IPPROTO_ESP;
+#endif
 
 	return add_dev_to_thread(t, pkt_dev);
 out2:
 	dev_put(pkt_dev->odev);
 out1:
+#ifdef CONFIG_XFRM
+	free_SAs(pkt_dev);
+#endif
 	if (pkt_dev->flows)
 		vfree(pkt_dev->flows);
 	kfree(pkt_dev);
@@ -3545,6 +3745,9 @@
 	if (pkt_dev->entry)
 		remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
 
+#ifdef CONFIG_XFRM
+	free_SAs(pkt_dev);
+#endif
 	if (pkt_dev->flows)
 		vfree(pkt_dev->flows);
 	kfree(pkt_dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 8c971a2..864cbdf 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -97,6 +97,19 @@
 	return 0;
 }
 
+int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+			         struct rtattr *rta, int len)
+{
+	if (RTA_PAYLOAD(rta) < len)
+		return -1;
+	if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
+		rta = RTA_DATA(rta) + RTA_ALIGN(len);
+		return rtattr_parse_nested(tb, maxattr, rta);
+	}
+	memset(tb, 0, sizeof(struct rtattr *) * maxattr);
+	return 0;
+}
+
 static struct rtnl_link *rtnl_msg_handlers[NPROTO];
 
 static inline int rtm_msgindex(int msgtype)
@@ -243,6 +256,150 @@
 
 EXPORT_SYMBOL_GPL(rtnl_unregister_all);
 
+static LIST_HEAD(link_ops);
+
+/**
+ * __rtnl_link_register - Register rtnl_link_ops with rtnetlink.
+ * @ops: struct rtnl_link_ops * to register
+ *
+ * The caller must hold the rtnl_mutex. This function should be used
+ * by drivers that create devices during module initialization. It
+ * must be called before registering the devices.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int __rtnl_link_register(struct rtnl_link_ops *ops)
+{
+	if (!ops->dellink)
+		ops->dellink = unregister_netdevice;
+
+	list_add_tail(&ops->list, &link_ops);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(__rtnl_link_register);
+
+/**
+ * rtnl_link_register - Register rtnl_link_ops with rtnetlink.
+ * @ops: struct rtnl_link_ops * to register
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int rtnl_link_register(struct rtnl_link_ops *ops)
+{
+	int err;
+
+	rtnl_lock();
+	err = __rtnl_link_register(ops);
+	rtnl_unlock();
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(rtnl_link_register);
+
+/**
+ * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+ * @ops: struct rtnl_link_ops * to unregister
+ *
+ * The caller must hold the rtnl_mutex.
+ */
+void __rtnl_link_unregister(struct rtnl_link_ops *ops)
+{
+	struct net_device *dev, *n;
+
+	for_each_netdev_safe(dev, n) {
+		if (dev->rtnl_link_ops == ops)
+			ops->dellink(dev);
+	}
+	list_del(&ops->list);
+}
+
+EXPORT_SYMBOL_GPL(__rtnl_link_unregister);
+
+/**
+ * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+ * @ops: struct rtnl_link_ops * to unregister
+ */
+void rtnl_link_unregister(struct rtnl_link_ops *ops)
+{
+	rtnl_lock();
+	__rtnl_link_unregister(ops);
+	rtnl_unlock();
+}
+
+EXPORT_SYMBOL_GPL(rtnl_link_unregister);
+
+static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind)
+{
+	const struct rtnl_link_ops *ops;
+
+	list_for_each_entry(ops, &link_ops, list) {
+		if (!strcmp(ops->kind, kind))
+			return ops;
+	}
+	return NULL;
+}
+
+static size_t rtnl_link_get_size(const struct net_device *dev)
+{
+	const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+	size_t size;
+
+	if (!ops)
+		return 0;
+
+	size = nlmsg_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */
+	       nlmsg_total_size(strlen(ops->kind) + 1);	 /* IFLA_INFO_KIND */
+
+	if (ops->get_size)
+		/* IFLA_INFO_DATA + nested data */
+		size += nlmsg_total_size(sizeof(struct nlattr)) +
+			ops->get_size(dev);
+
+	if (ops->get_xstats_size)
+		size += ops->get_xstats_size(dev);	/* IFLA_INFO_XSTATS */
+
+	return size;
+}
+
+static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
+{
+	const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+	struct nlattr *linkinfo, *data;
+	int err = -EMSGSIZE;
+
+	linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
+	if (linkinfo == NULL)
+		goto out;
+
+	if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0)
+		goto err_cancel_link;
+	if (ops->fill_xstats) {
+		err = ops->fill_xstats(skb, dev);
+		if (err < 0)
+			goto err_cancel_link;
+	}
+	if (ops->fill_info) {
+		data = nla_nest_start(skb, IFLA_INFO_DATA);
+		if (data == NULL)
+			goto err_cancel_link;
+		err = ops->fill_info(skb, dev);
+		if (err < 0)
+			goto err_cancel_data;
+		nla_nest_end(skb, data);
+	}
+
+	nla_nest_end(skb, linkinfo);
+	return 0;
+
+err_cancel_data:
+	nla_nest_cancel(skb, data);
+err_cancel_link:
+	nla_nest_cancel(skb, linkinfo);
+out:
+	return err;
+}
+
 static const int rtm_min[RTM_NR_FAMILIES] =
 {
 	[RTM_FAM(RTM_NEWLINK)]      = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
@@ -437,7 +594,7 @@
 	a->tx_compressed = b->tx_compressed;
 };
 
-static inline size_t if_nlmsg_size(int iwbuflen)
+static inline size_t if_nlmsg_size(const struct net_device *dev)
 {
 	return NLMSG_ALIGN(sizeof(struct ifinfomsg))
 	       + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
@@ -453,12 +610,12 @@
 	       + nla_total_size(4) /* IFLA_MASTER */
 	       + nla_total_size(1) /* IFLA_OPERSTATE */
 	       + nla_total_size(1) /* IFLA_LINKMODE */
-	       + nla_total_size(iwbuflen);
+	       + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
 }
 
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
-			    void *iwbuf, int iwbuflen, int type, u32 pid,
-			    u32 seq, u32 change, unsigned int flags)
+			    int type, u32 pid, u32 seq, u32 change,
+			    unsigned int flags)
 {
 	struct ifinfomsg *ifm;
 	struct nlmsghdr *nlh;
@@ -523,8 +680,10 @@
 		}
 	}
 
-	if (iwbuf)
-		NLA_PUT(skb, IFLA_WIRELESS, iwbuflen, iwbuf);
+	if (dev->rtnl_link_ops) {
+		if (rtnl_link_fill(skb, dev) < 0)
+			goto nla_put_failure;
+	}
 
 	return nlmsg_end(skb, nlh);
 
@@ -543,7 +702,7 @@
 	for_each_netdev(dev) {
 		if (idx < s_idx)
 			goto cont;
-		if (rtnl_fill_ifinfo(skb, dev, NULL, 0, RTM_NEWLINK,
+		if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
 				     NETLINK_CB(cb->skb).pid,
 				     cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0)
 			break;
@@ -555,8 +714,10 @@
 	return skb->len;
 }
 
-static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = {
+static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_IFNAME]		= { .type = NLA_STRING, .len = IFNAMSIZ-1 },
+	[IFLA_ADDRESS]		= { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
+	[IFLA_BROADCAST]	= { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
 	[IFLA_MAP]		= { .len = sizeof(struct rtnl_link_ifmap) },
 	[IFLA_MTU]		= { .type = NLA_U32 },
 	[IFLA_TXQLEN]		= { .type = NLA_U32 },
@@ -565,11 +726,145 @@
 	[IFLA_LINKMODE]		= { .type = NLA_U8 },
 };
 
+static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
+	[IFLA_INFO_KIND]	= { .type = NLA_STRING },
+	[IFLA_INFO_DATA]	= { .type = NLA_NESTED },
+};
+
+static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
+		      struct nlattr **tb, char *ifname, int modified)
+{
+	int send_addr_notify = 0;
+	int err;
+
+	if (tb[IFLA_MAP]) {
+		struct rtnl_link_ifmap *u_map;
+		struct ifmap k_map;
+
+		if (!dev->set_config) {
+			err = -EOPNOTSUPP;
+			goto errout;
+		}
+
+		if (!netif_device_present(dev)) {
+			err = -ENODEV;
+			goto errout;
+		}
+
+		u_map = nla_data(tb[IFLA_MAP]);
+		k_map.mem_start = (unsigned long) u_map->mem_start;
+		k_map.mem_end = (unsigned long) u_map->mem_end;
+		k_map.base_addr = (unsigned short) u_map->base_addr;
+		k_map.irq = (unsigned char) u_map->irq;
+		k_map.dma = (unsigned char) u_map->dma;
+		k_map.port = (unsigned char) u_map->port;
+
+		err = dev->set_config(dev, &k_map);
+		if (err < 0)
+			goto errout;
+
+		modified = 1;
+	}
+
+	if (tb[IFLA_ADDRESS]) {
+		struct sockaddr *sa;
+		int len;
+
+		if (!dev->set_mac_address) {
+			err = -EOPNOTSUPP;
+			goto errout;
+		}
+
+		if (!netif_device_present(dev)) {
+			err = -ENODEV;
+			goto errout;
+		}
+
+		len = sizeof(sa_family_t) + dev->addr_len;
+		sa = kmalloc(len, GFP_KERNEL);
+		if (!sa) {
+			err = -ENOMEM;
+			goto errout;
+		}
+		sa->sa_family = dev->type;
+		memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
+		       dev->addr_len);
+		err = dev->set_mac_address(dev, sa);
+		kfree(sa);
+		if (err)
+			goto errout;
+		send_addr_notify = 1;
+		modified = 1;
+	}
+
+	if (tb[IFLA_MTU]) {
+		err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
+		if (err < 0)
+			goto errout;
+		modified = 1;
+	}
+
+	/*
+	 * Interface selected by interface index but interface
+	 * name provided implies that a name change has been
+	 * requested.
+	 */
+	if (ifm->ifi_index > 0 && ifname[0]) {
+		err = dev_change_name(dev, ifname);
+		if (err < 0)
+			goto errout;
+		modified = 1;
+	}
+
+	if (tb[IFLA_BROADCAST]) {
+		nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
+		send_addr_notify = 1;
+	}
+
+	if (ifm->ifi_flags || ifm->ifi_change) {
+		unsigned int flags = ifm->ifi_flags;
+
+		/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
+		if (ifm->ifi_change)
+			flags = (flags & ifm->ifi_change) |
+				(dev->flags & ~ifm->ifi_change);
+		dev_change_flags(dev, flags);
+	}
+
+	if (tb[IFLA_TXQLEN])
+		dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+
+	if (tb[IFLA_WEIGHT])
+		dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
+
+	if (tb[IFLA_OPERSTATE])
+		set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+
+	if (tb[IFLA_LINKMODE]) {
+		write_lock_bh(&dev_base_lock);
+		dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+		write_unlock_bh(&dev_base_lock);
+	}
+
+	err = 0;
+
+errout:
+	if (err < 0 && modified && net_ratelimit())
+		printk(KERN_WARNING "A link change request failed with "
+		       "some changes comitted already. Interface %s may "
+		       "have been left with an inconsistent configuration, "
+		       "please check.\n", dev->name);
+
+	if (send_addr_notify)
+		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+	return err;
+}
+
 static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct ifinfomsg *ifm;
 	struct net_device *dev;
-	int err, send_addr_notify = 0, modified = 0;
+	int err;
 	struct nlattr *tb[IFLA_MAX+1];
 	char ifname[IFNAMSIZ];
 
@@ -584,7 +879,7 @@
 
 	err = -EINVAL;
 	ifm = nlmsg_data(nlh);
-	if (ifm->ifi_index >= 0)
+	if (ifm->ifi_index > 0)
 		dev = dev_get_by_index(ifm->ifi_index);
 	else if (tb[IFLA_IFNAME])
 		dev = dev_get_by_name(ifname);
@@ -604,134 +899,203 @@
 	    nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
 		goto errout_dev;
 
-	if (tb[IFLA_MAP]) {
-		struct rtnl_link_ifmap *u_map;
-		struct ifmap k_map;
-
-		if (!dev->set_config) {
-			err = -EOPNOTSUPP;
-			goto errout_dev;
-		}
-
-		if (!netif_device_present(dev)) {
-			err = -ENODEV;
-			goto errout_dev;
-		}
-
-		u_map = nla_data(tb[IFLA_MAP]);
-		k_map.mem_start = (unsigned long) u_map->mem_start;
-		k_map.mem_end = (unsigned long) u_map->mem_end;
-		k_map.base_addr = (unsigned short) u_map->base_addr;
-		k_map.irq = (unsigned char) u_map->irq;
-		k_map.dma = (unsigned char) u_map->dma;
-		k_map.port = (unsigned char) u_map->port;
-
-		err = dev->set_config(dev, &k_map);
-		if (err < 0)
-			goto errout_dev;
-
-		modified = 1;
-	}
-
-	if (tb[IFLA_ADDRESS]) {
-		struct sockaddr *sa;
-		int len;
-
-		if (!dev->set_mac_address) {
-			err = -EOPNOTSUPP;
-			goto errout_dev;
-		}
-
-		if (!netif_device_present(dev)) {
-			err = -ENODEV;
-			goto errout_dev;
-		}
-
-		len = sizeof(sa_family_t) + dev->addr_len;
-		sa = kmalloc(len, GFP_KERNEL);
-		if (!sa) {
-			err = -ENOMEM;
-			goto errout_dev;
-		}
-		sa->sa_family = dev->type;
-		memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
-		       dev->addr_len);
-		err = dev->set_mac_address(dev, sa);
-		kfree(sa);
-		if (err)
-			goto errout_dev;
-		send_addr_notify = 1;
-		modified = 1;
-	}
-
-	if (tb[IFLA_MTU]) {
-		err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
-		if (err < 0)
-			goto errout_dev;
-		modified = 1;
-	}
-
-	/*
-	 * Interface selected by interface index but interface
-	 * name provided implies that a name change has been
-	 * requested.
-	 */
-	if (ifm->ifi_index >= 0 && ifname[0]) {
-		err = dev_change_name(dev, ifname);
-		if (err < 0)
-			goto errout_dev;
-		modified = 1;
-	}
-
-	if (tb[IFLA_BROADCAST]) {
-		nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
-		send_addr_notify = 1;
-	}
-
-
-	if (ifm->ifi_flags)
-		dev_change_flags(dev, ifm->ifi_flags);
-
-	if (tb[IFLA_TXQLEN])
-		dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
-
-	if (tb[IFLA_WEIGHT])
-		dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
-
-	if (tb[IFLA_OPERSTATE])
-		set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
-
-	if (tb[IFLA_LINKMODE]) {
-		write_lock_bh(&dev_base_lock);
-		dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
-		write_unlock_bh(&dev_base_lock);
-	}
-
-	err = 0;
-
+	err = do_setlink(dev, ifm, tb, ifname, 0);
 errout_dev:
-	if (err < 0 && modified && net_ratelimit())
-		printk(KERN_WARNING "A link change request failed with "
-		       "some changes comitted already. Interface %s may "
-		       "have been left with an inconsistent configuration, "
-		       "please check.\n", dev->name);
-
-	if (send_addr_notify)
-		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
-
 	dev_put(dev);
 errout:
 	return err;
 }
 
+static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+	const struct rtnl_link_ops *ops;
+	struct net_device *dev;
+	struct ifinfomsg *ifm;
+	char ifname[IFNAMSIZ];
+	struct nlattr *tb[IFLA_MAX+1];
+	int err;
+
+	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+	if (err < 0)
+		return err;
+
+	if (tb[IFLA_IFNAME])
+		nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+
+	ifm = nlmsg_data(nlh);
+	if (ifm->ifi_index > 0)
+		dev = __dev_get_by_index(ifm->ifi_index);
+	else if (tb[IFLA_IFNAME])
+		dev = __dev_get_by_name(ifname);
+	else
+		return -EINVAL;
+
+	if (!dev)
+		return -ENODEV;
+
+	ops = dev->rtnl_link_ops;
+	if (!ops)
+		return -EOPNOTSUPP;
+
+	ops->dellink(dev);
+	return 0;
+}
+
+static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+	const struct rtnl_link_ops *ops;
+	struct net_device *dev;
+	struct ifinfomsg *ifm;
+	char kind[MODULE_NAME_LEN];
+	char ifname[IFNAMSIZ];
+	struct nlattr *tb[IFLA_MAX+1];
+	struct nlattr *linkinfo[IFLA_INFO_MAX+1];
+	int err;
+
+replay:
+	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+	if (err < 0)
+		return err;
+
+	if (tb[IFLA_IFNAME])
+		nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+	else
+		ifname[0] = '\0';
+
+	ifm = nlmsg_data(nlh);
+	if (ifm->ifi_index > 0)
+		dev = __dev_get_by_index(ifm->ifi_index);
+	else if (ifname[0])
+		dev = __dev_get_by_name(ifname);
+	else
+		dev = NULL;
+
+	if (tb[IFLA_LINKINFO]) {
+		err = nla_parse_nested(linkinfo, IFLA_INFO_MAX,
+				       tb[IFLA_LINKINFO], ifla_info_policy);
+		if (err < 0)
+			return err;
+	} else
+		memset(linkinfo, 0, sizeof(linkinfo));
+
+	if (linkinfo[IFLA_INFO_KIND]) {
+		nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind));
+		ops = rtnl_link_ops_get(kind);
+	} else {
+		kind[0] = '\0';
+		ops = NULL;
+	}
+
+	if (1) {
+		struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL;
+
+		if (ops) {
+			if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
+				err = nla_parse_nested(attr, ops->maxtype,
+						       linkinfo[IFLA_INFO_DATA],
+						       ops->policy);
+				if (err < 0)
+					return err;
+				data = attr;
+			}
+			if (ops->validate) {
+				err = ops->validate(tb, data);
+				if (err < 0)
+					return err;
+			}
+		}
+
+		if (dev) {
+			int modified = 0;
+
+			if (nlh->nlmsg_flags & NLM_F_EXCL)
+				return -EEXIST;
+			if (nlh->nlmsg_flags & NLM_F_REPLACE)
+				return -EOPNOTSUPP;
+
+			if (linkinfo[IFLA_INFO_DATA]) {
+				if (!ops || ops != dev->rtnl_link_ops ||
+				    !ops->changelink)
+					return -EOPNOTSUPP;
+
+				err = ops->changelink(dev, tb, data);
+				if (err < 0)
+					return err;
+				modified = 1;
+			}
+
+			return do_setlink(dev, ifm, tb, ifname, modified);
+		}
+
+		if (!(nlh->nlmsg_flags & NLM_F_CREATE))
+			return -ENODEV;
+
+		if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
+			return -EOPNOTSUPP;
+		if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
+			return -EOPNOTSUPP;
+
+		if (!ops) {
+#ifdef CONFIG_KMOD
+			if (kind[0]) {
+				__rtnl_unlock();
+				request_module("rtnl-link-%s", kind);
+				rtnl_lock();
+				ops = rtnl_link_ops_get(kind);
+				if (ops)
+					goto replay;
+			}
+#endif
+			return -EOPNOTSUPP;
+		}
+
+		if (!ifname[0])
+			snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
+		dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
+		if (!dev)
+			return -ENOMEM;
+
+		if (strchr(dev->name, '%')) {
+			err = dev_alloc_name(dev, dev->name);
+			if (err < 0)
+				goto err_free;
+		}
+		dev->rtnl_link_ops = ops;
+
+		if (tb[IFLA_MTU])
+			dev->mtu = nla_get_u32(tb[IFLA_MTU]);
+		if (tb[IFLA_ADDRESS])
+			memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]),
+			       nla_len(tb[IFLA_ADDRESS]));
+		if (tb[IFLA_BROADCAST])
+			memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]),
+			       nla_len(tb[IFLA_BROADCAST]));
+		if (tb[IFLA_TXQLEN])
+			dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+		if (tb[IFLA_WEIGHT])
+			dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
+		if (tb[IFLA_OPERSTATE])
+			set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+		if (tb[IFLA_LINKMODE])
+			dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+
+		if (ops->newlink)
+			err = ops->newlink(dev, tb, data);
+		else
+			err = register_netdevice(dev);
+err_free:
+		if (err < 0)
+			free_netdev(dev);
+		return err;
+	}
+}
+
 static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
 	struct ifinfomsg *ifm;
 	struct nlattr *tb[IFLA_MAX+1];
 	struct net_device *dev = NULL;
 	struct sk_buff *nskb;
-	char *iw_buf = NULL, *iw = NULL;
-	int iw_buf_len = 0;
 	int err;
 
 	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
@@ -739,21 +1103,21 @@
 		return err;
 
 	ifm = nlmsg_data(nlh);
-	if (ifm->ifi_index >= 0) {
+	if (ifm->ifi_index > 0) {
 		dev = dev_get_by_index(ifm->ifi_index);
 		if (dev == NULL)
 			return -ENODEV;
 	} else
 		return -EINVAL;
 
-	nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL);
+	nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
 	if (nskb == NULL) {
 		err = -ENOBUFS;
 		goto errout;
 	}
 
-	err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
-			       NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
+	err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid,
+			       nlh->nlmsg_seq, 0, 0);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in if_nlmsg_size */
 		WARN_ON(err == -EMSGSIZE);
@@ -762,7 +1126,6 @@
 	}
 	err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
 errout:
-	kfree(iw_buf);
 	dev_put(dev);
 
 	return err;
@@ -797,11 +1160,11 @@
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
 
-	skb = nlmsg_new(if_nlmsg_size(0), GFP_KERNEL);
+	skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
 	if (skb == NULL)
 		goto errout;
 
-	err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
+	err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in if_nlmsg_size() */
 		WARN_ON(err == -EMSGSIZE);
@@ -952,6 +1315,8 @@
 
 	rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo);
 	rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL);
+	rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL);
 
 	rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all);
 	rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all);
@@ -960,6 +1325,7 @@
 EXPORT_SYMBOL(__rta_fill);
 EXPORT_SYMBOL(rtattr_strlcpy);
 EXPORT_SYMBOL(rtattr_parse);
+EXPORT_SYMBOL(__rtattr_parse_nested_compat);
 EXPORT_SYMBOL(rtnetlink_put_metrics);
 EXPORT_SYMBOL(rtnl_lock);
 EXPORT_SYMBOL(rtnl_trylock);
diff --git a/net/core/scm.c b/net/core/scm.c
index 292ad8d..44c4ec2 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -228,7 +228,8 @@
 		err = security_file_receive(fp[i]);
 		if (err)
 			break;
-		err = get_unused_fd();
+		err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags
+					  ? O_CLOEXEC : 0);
 		if (err < 0)
 			break;
 		new_fd = err;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 1422573..0583e84 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -415,9 +415,11 @@
 	C(csum);
 	C(local_df);
 	n->cloned = 1;
+	n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
 	n->nohdr = 0;
 	C(pkt_type);
 	C(ip_summed);
+	skb_copy_queue_mapping(n, skb);
 	C(priority);
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	C(ipvs_property);
@@ -426,6 +428,10 @@
 	n->destructor = NULL;
 	C(mark);
 	__nf_copy(n, skb);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	C(nf_trace);
+#endif
 #ifdef CONFIG_NET_SCHED
 	C(tc_index);
 #ifdef CONFIG_NET_CLS_ACT
@@ -434,8 +440,8 @@
 	n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
 	C(iif);
 #endif
-	skb_copy_secmark(n, skb);
 #endif
+	skb_copy_secmark(n, skb);
 	C(truesize);
 	atomic_set(&n->users, 1);
 	C(head);
@@ -459,6 +465,7 @@
 #endif
 	new->sk		= NULL;
 	new->dev	= old->dev;
+	skb_copy_queue_mapping(new, old);
 	new->priority	= old->priority;
 	new->protocol	= old->protocol;
 	new->dst	= dst_clone(old->dst);
@@ -482,6 +489,10 @@
 	new->destructor = NULL;
 	new->mark	= old->mark;
 	__nf_copy(new, old);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	new->nf_trace	= old->nf_trace;
+#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	new->ipvs_property = old->ipvs_property;
 #endif
@@ -644,11 +655,10 @@
 
 	/* Copy only real data... and, alas, header. This should be
 	 * optimized for the cases when header is void. */
-	memcpy(data + nhead, skb->head,
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
-		skb->tail);
+	memcpy(data + nhead, skb->head, skb->tail);
 #else
-		skb->tail - skb->head);
+	memcpy(data + nhead, skb->head, skb->tail - skb->head);
 #endif
 	memcpy(data + size, skb_end_pointer(skb),
 	       sizeof(struct skb_shared_info));
@@ -677,6 +687,7 @@
 	skb->network_header   += off;
 	skb->mac_header	      += off;
 	skb->cloned   = 0;
+	skb->hdr_len  = 0;
 	skb->nohdr    = 0;
 	atomic_set(&skb_shinfo(skb)->dataref, 1);
 	return 0;
@@ -1707,6 +1718,11 @@
 		st->stepped_offset += frag->size;
 	}
 
+	if (st->frag_data) {
+		kunmap_skb_frag(st->frag_data);
+		st->frag_data = NULL;
+	}
+
 	if (st->cur_skb->next) {
 		st->cur_skb = st->cur_skb->next;
 		st->frag_idx = 0;
@@ -1926,6 +1942,7 @@
 		tail = nskb;
 
 		nskb->dev = skb->dev;
+		skb_copy_queue_mapping(nskb, skb);
 		nskb->priority = skb->priority;
 		nskb->protocol = skb->protocol;
 		nskb->dst = dst_clone(skb->dst);
@@ -2207,7 +2224,6 @@
 EXPORT_SYMBOL(pskb_expand_head);
 EXPORT_SYMBOL(skb_checksum);
 EXPORT_SYMBOL(skb_clone);
-EXPORT_SYMBOL(skb_clone_fraglist);
 EXPORT_SYMBOL(skb_copy);
 EXPORT_SYMBOL(skb_copy_and_csum_bits);
 EXPORT_SYMBOL(skb_copy_and_csum_dev);
diff --git a/net/core/sock.c b/net/core/sock.c
index 22183c2..091032a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -206,7 +206,20 @@
 		return -EINVAL;
 	if (copy_from_user(&tv, optval, sizeof(tv)))
 		return -EFAULT;
+	if (tv.tv_usec < 0 || tv.tv_usec >= USEC_PER_SEC)
+		return -EDOM;
 
+	if (tv.tv_sec < 0) {
+		static int warned __read_mostly;
+
+		*timeo_p = 0;
+		if (warned < 10 && net_ratelimit())
+			warned++;
+			printk(KERN_INFO "sock_set_timeout: `%s' (pid %d) "
+			       "tries to set negative timeout\n",
+			        current->comm, current->pid);
+		return 0;
+	}
 	*timeo_p = MAX_SCHEDULE_TIMEOUT;
 	if (tv.tv_sec == 0 && tv.tv_usec == 0)
 		return 0;
@@ -986,7 +999,7 @@
 	__sk_dst_set(sk, dst);
 	sk->sk_route_caps = dst->dev->features;
 	if (sk->sk_route_caps & NETIF_F_GSO)
-		sk->sk_route_caps |= NETIF_F_GSO_MASK;
+		sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
 	if (sk_can_gso(sk)) {
 		if (dst->header_len)
 			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
@@ -1839,46 +1852,15 @@
 EXPORT_SYMBOL(proto_unregister);
 
 #ifdef CONFIG_PROC_FS
-static inline struct proto *__proto_head(void)
-{
-	return list_entry(proto_list.next, struct proto, node);
-}
-
-static inline struct proto *proto_head(void)
-{
-	return list_empty(&proto_list) ? NULL : __proto_head();
-}
-
-static inline struct proto *proto_next(struct proto *proto)
-{
-	return proto->node.next == &proto_list ? NULL :
-		list_entry(proto->node.next, struct proto, node);
-}
-
-static inline struct proto *proto_get_idx(loff_t pos)
-{
-	struct proto *proto;
-	loff_t i = 0;
-
-	list_for_each_entry(proto, &proto_list, node)
-		if (i++ == pos)
-			goto out;
-
-	proto = NULL;
-out:
-	return proto;
-}
-
 static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	read_lock(&proto_list_lock);
-	return *pos ? proto_get_idx(*pos - 1) : SEQ_START_TOKEN;
+	return seq_list_start_head(&proto_list, *pos);
 }
 
 static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	++*pos;
-	return v == SEQ_START_TOKEN ? proto_head() : proto_next(v);
+	return seq_list_next(v, &proto_list, pos);
 }
 
 static void proto_seq_stop(struct seq_file *seq, void *v)
@@ -1926,7 +1908,7 @@
 
 static int proto_seq_show(struct seq_file *seq, void *v)
 {
-	if (v == SEQ_START_TOKEN)
+	if (v == &proto_list)
 		seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s",
 			   "protocol",
 			   "size",
@@ -1938,7 +1920,7 @@
 			   "module",
 			   "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n");
 	else
-		proto_seq_printf(seq, v);
+		proto_seq_printf(seq, list_entry(v, struct proto, node));
 	return 0;
 }
 
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index b297120..6d5ea97 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -24,6 +24,8 @@
 #ifdef CONFIG_XFRM
 extern u32 sysctl_xfrm_aevent_etime;
 extern u32 sysctl_xfrm_aevent_rseqth;
+extern int sysctl_xfrm_larval_drop;
+extern u32 sysctl_xfrm_acq_expires;
 #endif
 
 ctl_table core_table[] = {
@@ -118,6 +120,22 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "xfrm_larval_drop",
+		.data		= &sysctl_xfrm_larval_drop,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "xfrm_acq_expires",
+		.data		= &sysctl_xfrm_acq_expires,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
 #endif /* CONFIG_XFRM */
 #endif /* CONFIG_NET */
 	{
diff --git a/net/core/utils.c b/net/core/utils.c
index adecfd2..2030bb8 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -139,16 +139,16 @@
 	while(1) {
 		int c;
 		c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
-		if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM))) {
+		if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK))) {
 			goto out;
 		}
-		if (c & (IN6PTON_DOT | IN6PTON_DELIM)) {
+		if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
 			if (w == 0)
 				goto out;
 			*d++ = w & 0xff;
 			w = 0;
 			i++;
-			if (c & IN6PTON_DELIM) {
+			if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
 				if (i != 4)
 					goto out;
 				break;
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index b8a68dd..0549e47 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -1,8 +1,6 @@
-menu "DCCP Configuration (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL
-
-config IP_DCCP
+menuconfig IP_DCCP
 	tristate "The DCCP Protocol (EXPERIMENTAL)"
+	depends on INET && EXPERIMENTAL
 	---help---
 	  Datagram Congestion Control Protocol (RFC 4340)
 
@@ -19,19 +17,20 @@
 
 	  If in doubt, say N.
 
+if IP_DCCP
+
 config INET_DCCP_DIAG
-	depends on IP_DCCP && INET_DIAG
+	depends on INET_DIAG
 	def_tristate y if (IP_DCCP = y && INET_DIAG = y)
 	def_tristate m
 
 config IP_DCCP_ACKVEC
-	depends on IP_DCCP
 	bool
 
 source "net/dccp/ccids/Kconfig"
 
 menu "DCCP Kernel Hacking"
-	depends on IP_DCCP && DEBUG_KERNEL=y
+	depends on DEBUG_KERNEL=y
 
 config IP_DCCP_DEBUG
 	bool "DCCP debug messages"
@@ -61,4 +60,4 @@
 
 endmenu
 
-endmenu
+endif # IP_DDCP
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index d7d9ce7..e91c2b9 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1,8 +1,8 @@
 /*
  *  net/dccp/ccids/ccid3.c
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *
  *  An implementation of the DCCP protocol
  *
@@ -49,7 +49,6 @@
 
 static struct dccp_tx_hist *ccid3_tx_hist;
 static struct dccp_rx_hist *ccid3_rx_hist;
-static struct dccp_li_hist *ccid3_li_hist;
 
 /*
  *	Transmitter Half-Connection Routines
@@ -194,25 +193,20 @@
  *	The algorithm is not applicable if RTT < 4 microseconds.
  */
 static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
-						struct timeval *now)
+						ktime_t now)
 {
-	suseconds_t delta;
 	u32 quarter_rtts;
 
 	if (unlikely(hctx->ccid3hctx_rtt < 4))	/* avoid divide-by-zero */
 		return;
 
-	delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
-	DCCP_BUG_ON(delta < 0);
-
-	quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);
+	quarter_rtts = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count);
+	quarter_rtts /= hctx->ccid3hctx_rtt / 4;
 
 	if (quarter_rtts > 0) {
-		hctx->ccid3hctx_t_last_win_count = *now;
+		hctx->ccid3hctx_t_last_win_count = now;
 		hctx->ccid3hctx_last_win_count	+= min_t(u32, quarter_rtts, 5);
 		hctx->ccid3hctx_last_win_count	&= 0xF;		/* mod 16 */
-
-		ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
 	}
 }
 
@@ -312,8 +306,8 @@
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-	struct timeval now;
-	suseconds_t delay;
+	ktime_t now = ktime_get_real();
+	s64 delay;
 
 	BUG_ON(hctx == NULL);
 
@@ -325,8 +319,6 @@
 	if (unlikely(skb->len == 0))
 		return -EBADMSG;
 
-	dccp_timestamp(sk, &now);
-
 	switch (hctx->ccid3hctx_state) {
 	case TFRC_SSTATE_NO_SENT:
 		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
@@ -349,7 +341,7 @@
 			ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt);
 			hctx->ccid3hctx_rtt  = dp->dccps_syn_rtt;
 			hctx->ccid3hctx_x    = rfc3390_initial_rate(sk);
-			hctx->ccid3hctx_t_ld = now;
+			hctx->ccid3hctx_t_ld = ktime_to_timeval(now);
 		} else {
 			/* Sender does not have RTT sample: X = MSS/second */
 			hctx->ccid3hctx_x = dp->dccps_mss_cache;
@@ -361,7 +353,7 @@
 		break;
 	case TFRC_SSTATE_NO_FBACK:
 	case TFRC_SSTATE_FBACK:
-		delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
+		delay = ktime_us_delta(hctx->ccid3hctx_t_nom, now);
 		ccid3_pr_debug("delay=%ld\n", (long)delay);
 		/*
 		 *	Scheduling of packet transmissions [RFC 3448, 4.6]
@@ -371,10 +363,10 @@
 		 * else
 		 *       // send the packet in (t_nom - t_now) milliseconds.
 		 */
-		if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
-			return delay / 1000L;
+		if (delay - (s64)hctx->ccid3hctx_delta >= 1000)
+			return (u32)delay / 1000L;
 
-		ccid3_hc_tx_update_win_count(hctx, &now);
+		ccid3_hc_tx_update_win_count(hctx, now);
 		break;
 	case TFRC_SSTATE_TERM:
 		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
@@ -387,8 +379,8 @@
 	hctx->ccid3hctx_idle = 0;
 
 	/* set the nominal send time for the next following packet */
-	timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
-
+	hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom,
+					     hctx->ccid3hctx_t_ipi);
 	return 0;
 }
 
@@ -419,7 +411,6 @@
 
 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
-	const struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 	struct ccid3_options_received *opt_recv;
 	struct dccp_tx_hist_entry *packet;
@@ -491,7 +482,7 @@
 			ccid3_pr_debug("%s(%p), s=%u, MSS=%u, "
 				       "R_sample=%uus, X=%u\n", dccp_role(sk),
 				       sk, hctx->ccid3hctx_s,
-				       dp->dccps_mss_cache, r_sample,
+				       dccp_sk(sk)->dccps_mss_cache, r_sample,
 				       (unsigned)(hctx->ccid3hctx_x >> 6));
 
 			ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
@@ -820,154 +811,6 @@
 	return 0;
 }
 
-/* calculate first loss interval
- *
- * returns estimated loss interval in usecs */
-
-static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
-{
-	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
-	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
-	u32 x_recv, p;
-	suseconds_t rtt, delta;
-	struct timeval tstamp = { 0, };
-	int interval = 0;
-	int win_count = 0;
-	int step = 0;
-	u64 fval;
-
-	list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
-				 dccphrx_node) {
-		if (dccp_rx_hist_entry_data_packet(entry)) {
-			tail = entry;
-
-			switch (step) {
-			case 0:
-				tstamp	  = entry->dccphrx_tstamp;
-				win_count = entry->dccphrx_ccval;
-				step = 1;
-				break;
-			case 1:
-				interval = win_count - entry->dccphrx_ccval;
-				if (interval < 0)
-					interval += TFRC_WIN_COUNT_LIMIT;
-				if (interval > 4)
-					goto found;
-				break;
-			}
-		}
-	}
-
-	if (unlikely(step == 0)) {
-		DCCP_WARN("%s(%p), packet history has no data packets!\n",
-			  dccp_role(sk), sk);
-		return ~0;
-	}
-
-	if (unlikely(interval == 0)) {
-		DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
-			  "Defaulting to 1\n", dccp_role(sk), sk);
-		interval = 1;
-	}
-found:
-	if (!tail) {
-		DCCP_CRIT("tail is null\n");
-		return ~0;
-	}
-
-	delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
-	DCCP_BUG_ON(delta < 0);
-
-	rtt = delta * 4 / interval;
-	ccid3_pr_debug("%s(%p), approximated RTT to %dus\n",
-		       dccp_role(sk), sk, (int)rtt);
-
-	/*
-	 * Determine the length of the first loss interval via inverse lookup.
-	 * Assume that X_recv can be computed by the throughput equation
-	 *		    s
-	 *	X_recv = --------
-	 *		 R * fval
-	 * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
-	 */
-	if (rtt == 0) {			/* would result in divide-by-zero */
-		DCCP_WARN("RTT==0\n");
-		return ~0;
-	}
-
-	dccp_timestamp(sk, &tstamp);
-	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
-	DCCP_BUG_ON(delta <= 0);
-
-	x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
-	if (x_recv == 0) {		/* would also trigger divide-by-zero */
-		DCCP_WARN("X_recv==0\n");
-		if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
-			DCCP_BUG("stored value of X_recv is zero");
-			return ~0;
-		}
-	}
-
-	fval = scaled_div(hcrx->ccid3hcrx_s, rtt);
-	fval = scaled_div32(fval, x_recv);
-	p = tfrc_calc_x_reverse_lookup(fval);
-
-	ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
-		       "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
-
-	if (p == 0)
-		return ~0;
-	else
-		return 1000000 / p;
-}
-
-static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
-{
-	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
-	struct dccp_li_hist_entry *head;
-	u64 seq_temp;
-
-	if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
-		if (!dccp_li_hist_interval_new(ccid3_li_hist,
-		   &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
-			return;
-
-		head = list_entry(hcrx->ccid3hcrx_li_hist.next,
-		   struct dccp_li_hist_entry, dccplih_node);
-		head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
-	} else {
-		struct dccp_li_hist_entry *entry;
-		struct list_head *tail;
-
-		head = list_entry(hcrx->ccid3hcrx_li_hist.next,
-		   struct dccp_li_hist_entry, dccplih_node);
-		/* FIXME win count check removed as was wrong */
-		/* should make this check with receive history */
-		/* and compare there as per section 10.2 of RFC4342 */
-
-		/* new loss event detected */
-		/* calculate last interval length */
-		seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
-		entry = dccp_li_hist_entry_new(ccid3_li_hist, GFP_ATOMIC);
-
-		if (entry == NULL) {
-			DCCP_BUG("out of memory - can not allocate entry");
-			return;
-		}
-
-		list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist);
-
-		tail = hcrx->ccid3hcrx_li_hist.prev;
-		list_del(tail);
-		kmem_cache_free(ccid3_li_hist->dccplih_slab, tail);
-
-		/* Create the newest interval */
-		entry->dccplih_seqno = seq_loss;
-		entry->dccplih_interval = seq_temp;
-		entry->dccplih_win_count = win_loss;
-	}
-}
-
 static int ccid3_hc_rx_detect_loss(struct sock *sk,
 				    struct dccp_rx_hist_entry *packet)
 {
@@ -993,8 +836,15 @@
 	while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
 	   > TFRC_RECV_NUM_LATE_LOSS) {
 		loss = 1;
-		ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss,
-		   hcrx->ccid3hcrx_ccval_nonloss);
+		dccp_li_update_li(sk,
+				  &hcrx->ccid3hcrx_li_hist,
+				  &hcrx->ccid3hcrx_hist,
+				  &hcrx->ccid3hcrx_tstamp_last_feedback,
+				  hcrx->ccid3hcrx_s,
+				  hcrx->ccid3hcrx_bytes_recv,
+				  hcrx->ccid3hcrx_x_recv,
+				  hcrx->ccid3hcrx_seqno_nonloss,
+				  hcrx->ccid3hcrx_ccval_nonloss);
 		tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
 		dccp_inc_seqno(&tmp_seqno);
 		hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
@@ -1153,7 +1003,7 @@
 	dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
 
 	/* Empty loss interval history */
-	dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
+	dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
 }
 
 static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1237,19 +1087,12 @@
 	if (ccid3_tx_hist == NULL)
 		goto out_free_rx;
 
-	ccid3_li_hist = dccp_li_hist_new("ccid3");
-	if (ccid3_li_hist == NULL)
-		goto out_free_tx;
-
 	rc = ccid_register(&ccid3);
 	if (rc != 0)
-		goto out_free_loss_interval_history;
+		goto out_free_tx;
 out:
 	return rc;
 
-out_free_loss_interval_history:
-	dccp_li_hist_delete(ccid3_li_hist);
-	ccid3_li_hist = NULL;
 out_free_tx:
 	dccp_tx_hist_delete(ccid3_tx_hist);
 	ccid3_tx_hist = NULL;
@@ -1272,10 +1115,6 @@
 		dccp_rx_hist_delete(ccid3_rx_hist);
 		ccid3_rx_hist = NULL;
 	}
-	if (ccid3_li_hist != NULL) {
-		dccp_li_hist_delete(ccid3_li_hist);
-		ccid3_li_hist = NULL;
-	}
 }
 module_exit(ccid3_module_exit);
 
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 8d31b38..51d4b80 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -36,6 +36,7 @@
 #ifndef _DCCP_CCID3_H_
 #define _DCCP_CCID3_H_
 
+#include <linux/ktime.h>
 #include <linux/list.h>
 #include <linux/time.h>
 #include <linux/types.h>
@@ -108,10 +109,10 @@
 	enum ccid3_hc_tx_states		ccid3hctx_state:8;
 	u8				ccid3hctx_last_win_count;
 	u8				ccid3hctx_idle;
-	struct timeval			ccid3hctx_t_last_win_count;
+	ktime_t				ccid3hctx_t_last_win_count;
 	struct timer_list		ccid3hctx_no_feedback_timer;
 	struct timeval			ccid3hctx_t_ld;
-	struct timeval			ccid3hctx_t_nom;
+	ktime_t				ccid3hctx_t_nom;
 	u32				ccid3hctx_delta;
 	struct list_head		ccid3hctx_hist;
 	struct ccid3_options_received	ccid3hctx_options_received;
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 372d7e7..515225f 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -1,8 +1,8 @@
 /*
  *  net/dccp/ccids/lib/loss_interval.c
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -15,58 +15,38 @@
 #include <net/sock.h>
 #include "../../dccp.h"
 #include "loss_interval.h"
+#include "packet_history.h"
+#include "tfrc.h"
 
-struct dccp_li_hist *dccp_li_hist_new(const char *name)
+#define DCCP_LI_HIST_IVAL_F_LENGTH  8
+
+struct dccp_li_hist_entry {
+	struct list_head dccplih_node;
+	u64		 dccplih_seqno:48,
+			 dccplih_win_count:4;
+	u32		 dccplih_interval;
+};
+
+static struct kmem_cache *dccp_li_cachep __read_mostly;
+
+static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
 {
-	struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
-	static const char dccp_li_hist_mask[] = "li_hist_%s";
-	char *slab_name;
-
-	if (hist == NULL)
-		goto out;
-
-	slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1,
-			    GFP_ATOMIC);
-	if (slab_name == NULL)
-		goto out_free_hist;
-
-	sprintf(slab_name, dccp_li_hist_mask, name);
-	hist->dccplih_slab = kmem_cache_create(slab_name,
-					     sizeof(struct dccp_li_hist_entry),
-					       0, SLAB_HWCACHE_ALIGN,
-					       NULL, NULL);
-	if (hist->dccplih_slab == NULL)
-		goto out_free_slab_name;
-out:
-	return hist;
-out_free_slab_name:
-	kfree(slab_name);
-out_free_hist:
-	kfree(hist);
-	hist = NULL;
-	goto out;
+	return kmem_cache_alloc(dccp_li_cachep, prio);
 }
 
-EXPORT_SYMBOL_GPL(dccp_li_hist_new);
-
-void dccp_li_hist_delete(struct dccp_li_hist *hist)
+static inline void dccp_li_hist_entry_delete(struct dccp_li_hist_entry *entry)
 {
-	const char* name = kmem_cache_name(hist->dccplih_slab);
-
-	kmem_cache_destroy(hist->dccplih_slab);
-	kfree(name);
-	kfree(hist);
+	if (entry != NULL)
+		kmem_cache_free(dccp_li_cachep, entry);
 }
 
-EXPORT_SYMBOL_GPL(dccp_li_hist_delete);
-
-void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list)
+void dccp_li_hist_purge(struct list_head *list)
 {
 	struct dccp_li_hist_entry *entry, *next;
 
 	list_for_each_entry_safe(entry, next, list, dccplih_node) {
 		list_del_init(&entry->dccplih_node);
-		kmem_cache_free(hist->dccplih_slab, entry);
+		kmem_cache_free(dccp_li_cachep, entry);
 	}
 }
 
@@ -118,16 +98,16 @@
 
 EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
 
-int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
-   struct list_head *list, const u64 seq_loss, const u8 win_loss)
+static int dccp_li_hist_interval_new(struct list_head *list,
+				     const u64 seq_loss, const u8 win_loss)
 {
 	struct dccp_li_hist_entry *entry;
 	int i;
 
 	for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
-		entry = dccp_li_hist_entry_new(hist, GFP_ATOMIC);
+		entry = dccp_li_hist_entry_new(GFP_ATOMIC);
 		if (entry == NULL) {
-			dccp_li_hist_purge(hist, list);
+			dccp_li_hist_purge(list);
 			DCCP_BUG("loss interval list entry is NULL");
 			return 0;
 		}
@@ -140,4 +120,176 @@
 	return 1;
 }
 
-EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
+/* calculate first loss interval
+ *
+ * returns estimated loss interval in usecs */
+static u32 dccp_li_calc_first_li(struct sock *sk,
+				 struct list_head *hist_list,
+				 struct timeval *last_feedback,
+				 u16 s, u32 bytes_recv,
+				 u32 previous_x_recv)
+{
+	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
+	u32 x_recv, p;
+	suseconds_t rtt, delta;
+	struct timeval tstamp = { 0, 0 };
+	int interval = 0;
+	int win_count = 0;
+	int step = 0;
+	u64 fval;
+
+	list_for_each_entry_safe(entry, next, hist_list, dccphrx_node) {
+		if (dccp_rx_hist_entry_data_packet(entry)) {
+			tail = entry;
+
+			switch (step) {
+			case 0:
+				tstamp	  = entry->dccphrx_tstamp;
+				win_count = entry->dccphrx_ccval;
+				step = 1;
+				break;
+			case 1:
+				interval = win_count - entry->dccphrx_ccval;
+				if (interval < 0)
+					interval += TFRC_WIN_COUNT_LIMIT;
+				if (interval > 4)
+					goto found;
+				break;
+			}
+		}
+	}
+
+	if (unlikely(step == 0)) {
+		DCCP_WARN("%s(%p), packet history has no data packets!\n",
+			  dccp_role(sk), sk);
+		return ~0;
+	}
+
+	if (unlikely(interval == 0)) {
+		DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
+			  "Defaulting to 1\n", dccp_role(sk), sk);
+		interval = 1;
+	}
+found:
+	if (!tail) {
+		DCCP_CRIT("tail is null\n");
+		return ~0;
+	}
+
+	delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
+	DCCP_BUG_ON(delta < 0);
+
+	rtt = delta * 4 / interval;
+	dccp_pr_debug("%s(%p), approximated RTT to %dus\n",
+		      dccp_role(sk), sk, (int)rtt);
+
+	/*
+	 * Determine the length of the first loss interval via inverse lookup.
+	 * Assume that X_recv can be computed by the throughput equation
+	 *		    s
+	 *	X_recv = --------
+	 *		 R * fval
+	 * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
+	 */
+	if (rtt == 0) {			/* would result in divide-by-zero */
+		DCCP_WARN("RTT==0\n");
+		return ~0;
+	}
+
+	dccp_timestamp(sk, &tstamp);
+	delta = timeval_delta(&tstamp, last_feedback);
+	DCCP_BUG_ON(delta <= 0);
+
+	x_recv = scaled_div32(bytes_recv, delta);
+	if (x_recv == 0) {		/* would also trigger divide-by-zero */
+		DCCP_WARN("X_recv==0\n");
+		if (previous_x_recv == 0) {
+			DCCP_BUG("stored value of X_recv is zero");
+			return ~0;
+		}
+		x_recv = previous_x_recv;
+	}
+
+	fval = scaled_div(s, rtt);
+	fval = scaled_div32(fval, x_recv);
+	p = tfrc_calc_x_reverse_lookup(fval);
+
+	dccp_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
+		      "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
+
+	if (p == 0)
+		return ~0;
+	else
+		return 1000000 / p;
+}
+
+void dccp_li_update_li(struct sock *sk,
+		       struct list_head *li_hist_list,
+		       struct list_head *hist_list,
+		       struct timeval *last_feedback, u16 s, u32 bytes_recv,
+                       u32 previous_x_recv, u64 seq_loss, u8 win_loss)
+{
+	struct dccp_li_hist_entry *head;
+	u64 seq_temp;
+
+	if (list_empty(li_hist_list)) {
+		if (!dccp_li_hist_interval_new(li_hist_list, seq_loss,
+					       win_loss))
+			return;
+
+		head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
+				  dccplih_node);
+		head->dccplih_interval = dccp_li_calc_first_li(sk, hist_list,
+							       last_feedback,
+							       s, bytes_recv,
+							       previous_x_recv);
+	} else {
+		struct dccp_li_hist_entry *entry;
+		struct list_head *tail;
+
+		head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
+				  dccplih_node);
+		/* FIXME win count check removed as was wrong */
+		/* should make this check with receive history */
+		/* and compare there as per section 10.2 of RFC4342 */
+
+		/* new loss event detected */
+		/* calculate last interval length */
+		seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
+		entry = dccp_li_hist_entry_new(GFP_ATOMIC);
+
+		if (entry == NULL) {
+			DCCP_BUG("out of memory - can not allocate entry");
+			return;
+		}
+
+		list_add(&entry->dccplih_node, li_hist_list);
+
+		tail = li_hist_list->prev;
+		list_del(tail);
+		kmem_cache_free(dccp_li_cachep, tail);
+
+		/* Create the newest interval */
+		entry->dccplih_seqno = seq_loss;
+		entry->dccplih_interval = seq_temp;
+		entry->dccplih_win_count = win_loss;
+	}
+}
+
+EXPORT_SYMBOL_GPL(dccp_li_update_li);
+
+static __init int dccp_li_init(void)
+{
+	dccp_li_cachep = kmem_cache_create("dccp_li_hist",
+					   sizeof(struct dccp_li_hist_entry),
+					   0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	return dccp_li_cachep == NULL ? -ENOBUFS : 0;
+}
+
+static __exit void dccp_li_exit(void)
+{
+	kmem_cache_destroy(dccp_li_cachep);
+}
+
+module_init(dccp_li_init);
+module_exit(dccp_li_exit);
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index eb25701..906c806 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -3,8 +3,8 @@
 /*
  *  net/dccp/ccids/lib/loss_interval.h
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
  *  This program is free software; you can redistribute it and/or modify it
@@ -14,44 +14,16 @@
  */
 
 #include <linux/list.h>
-#include <linux/slab.h>
 #include <linux/time.h>
 
-#define DCCP_LI_HIST_IVAL_F_LENGTH  8
-
-struct dccp_li_hist {
-	struct kmem_cache *dccplih_slab;
-};
-
-extern struct dccp_li_hist *dccp_li_hist_new(const char *name);
-extern void dccp_li_hist_delete(struct dccp_li_hist *hist);
-
-struct dccp_li_hist_entry {
-	struct list_head dccplih_node;
-	u64		 dccplih_seqno:48,
-			 dccplih_win_count:4;
-	u32		 dccplih_interval;
-};
-
-static inline struct dccp_li_hist_entry *
-		dccp_li_hist_entry_new(struct dccp_li_hist *hist,
-				       const gfp_t prio)
-{
-	return kmem_cache_alloc(hist->dccplih_slab, prio);
-}
-
-static inline void dccp_li_hist_entry_delete(struct dccp_li_hist *hist,
-					     struct dccp_li_hist_entry *entry)
-{
-	if (entry != NULL)
-		kmem_cache_free(hist->dccplih_slab, entry);
-}
-
-extern void dccp_li_hist_purge(struct dccp_li_hist *hist,
-			       struct list_head *list);
+extern void dccp_li_hist_purge(struct list_head *list);
 
 extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
 
-extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
-   struct list_head *list, const u64 seq_loss, const u8 win_loss);
+extern void dccp_li_update_li(struct sock *sk,
+			      struct list_head *li_hist_list,
+			      struct list_head *hist_list,
+			      struct timeval *last_feedback, u16 s,
+			      u32 bytes_recv, u32 previous_x_recv,
+			      u64 seq_loss, u8 win_loss);
 #endif /* _DCCP_LI_HIST_ */
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index d8ad27b..e2d74cd 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -184,7 +184,7 @@
 /*
  * 	Checksumming routines
  */
-static inline int dccp_csum_coverage(const struct sk_buff *skb)
+static inline unsigned int dccp_csum_coverage(const struct sk_buff *skb)
 {
 	const struct dccp_hdr* dh = dccp_hdr(skb);
 
@@ -195,7 +195,7 @@
 
 static inline void dccp_csum_outgoing(struct sk_buff *skb)
 {
-	int cov = dccp_csum_coverage(skb);
+	unsigned int cov = dccp_csum_coverage(skb);
 
 	if (cov >= skb->len)
 		dccp_hdr(skb)->dccph_cscov = 0;
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 64eac25..b158c66 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -253,17 +253,6 @@
 
 	if (dst == NULL) {
 		opt = np->opt;
-		if (opt == NULL &&
-		    np->rxopt.bits.osrcrt == 2 &&
-		    ireq6->pktopts) {
-			struct sk_buff *pktopts = ireq6->pktopts;
-			struct inet6_skb_parm *rxopt = IP6CB(pktopts);
-
-			if (rxopt->srcrt)
-				opt = ipv6_invert_rthdr(sk,
-			  (struct ipv6_rt_hdr *)(skb_network_header(pktopts) +
-						 rxopt->srcrt));
-		}
 
 		if (opt != NULL && opt->srcrt != NULL) {
 			const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
@@ -570,15 +559,6 @@
 	if (sk_acceptq_is_full(sk))
 		goto out_overflow;
 
-	if (np->rxopt.bits.osrcrt == 2 && opt == NULL && ireq6->pktopts) {
-		const struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts);
-
-		if (rxopt->srcrt)
-			opt = ipv6_invert_rthdr(sk,
-		   (struct ipv6_rt_hdr *)(skb_network_header(ireq6->pktopts) +
-					  rxopt->srcrt));
-	}
-
 	if (dst == NULL) {
 		struct in6_addr *final_p = NULL, final;
 		struct flowi fl;
@@ -1043,9 +1023,13 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	err = xfrm_lookup(&dst, &fl, sk, 1);
-	if (err < 0)
-		goto failure;
+	err = __xfrm_lookup(&dst, &fl, sk, 1);
+	if (err < 0) {
+		if (err == -EREMOTE)
+			err = ip6_dst_blackhole(sk, &dst, &fl);
+		if (err < 0)
+			goto failure;
+	}
 
 	if (saddr == NULL) {
 		saddr = &fl.fl6_src;
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index 1f5e3ba..43a3adb 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -128,7 +128,7 @@
 	int error = 0, cnt = 0;
 	unsigned char *tbuf;
 
-	if (!buf || len < 0)
+	if (!buf)
 		return -EINVAL;
 
 	if (len == 0)
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index bfa910b..ed76d4a 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -2304,7 +2304,7 @@
 	return 0;
 }
 
-static struct seq_operations dn_socket_seq_ops = {
+static const struct seq_operations dn_socket_seq_ops = {
 	.start	= dn_socket_seq_start,
 	.next	= dn_socket_seq_next,
 	.stop	= dn_socket_seq_stop,
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 764a56a..fa6604f 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -461,7 +461,6 @@
 		if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) {
 			dn_dn2eth(mac_addr, ifa->ifa_local);
 			dev_mc_add(dev, mac_addr, ETH_ALEN, 0);
-			dev_mc_upload(dev);
 		}
 	}
 
@@ -638,7 +637,7 @@
 	return dn_dev;
 }
 
-static struct nla_policy dn_ifa_policy[IFA_MAX+1] __read_mostly = {
+static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
 	[IFA_ADDRESS]		= { .type = NLA_U16 },
 	[IFA_LOCAL]		= { .type = NLA_U16 },
 	[IFA_LABEL]		= { .type = NLA_STRING,
@@ -1064,8 +1063,6 @@
 	else
 		dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);
 
-	dev_mc_upload(dev);
-
 	dn_db->use_long = 1;
 
 	return 0;
@@ -1419,7 +1416,7 @@
 	return 0;
 }
 
-static struct seq_operations dn_dev_seq_ops = {
+static const struct seq_operations dn_dev_seq_ops = {
 	.start	= dn_dev_seq_start,
 	.next	= dn_dev_seq_next,
 	.stop	= dn_dev_seq_stop,
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 4bf066c..174d8a7 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -569,7 +569,7 @@
 			       NEIGH_SEQ_NEIGH_ONLY);
 }
 
-static struct seq_operations dn_neigh_seq_ops = {
+static const struct seq_operations dn_neigh_seq_ops = {
 	.start = dn_neigh_seq_start,
 	.next  = neigh_seq_next,
 	.stop  = neigh_seq_stop,
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index a8bf106..82622fb 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1726,7 +1726,7 @@
 	return 0;
 }
 
-static struct seq_operations dn_rt_cache_seq_ops = {
+static const struct seq_operations dn_rt_cache_seq_ops = {
 	.start	= dn_rt_cache_seq_start,
 	.next	= dn_rt_cache_seq_next,
 	.stop	= dn_rt_cache_seq_stop,
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 17a1932..84ff3dd 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -108,7 +108,7 @@
 	return err;
 }
 
-static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy dn_fib_rule_policy[FRA_MAX+1] = {
 	FRA_GENERIC_POLICY,
 };
 
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 0ac2524..12c7657 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -266,8 +266,11 @@
 static int eth_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr = p;
+
 	if (netif_running(dev))
 		return -EBUSY;
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 	return 0;
 }
@@ -316,9 +319,10 @@
 EXPORT_SYMBOL(ether_setup);
 
 /**
- * alloc_etherdev - Allocates and sets up an Ethernet device
+ * alloc_etherdev_mq - Allocates and sets up an Ethernet device
  * @sizeof_priv: Size of additional driver-private structure to be allocated
  *	for this Ethernet device
+ * @queue_count: The number of queues this device has.
  *
  * Fill in the fields of the device structure with Ethernet-generic
  * values. Basically does everything except registering the device.
@@ -328,8 +332,8 @@
  * this private data area.
  */
 
-struct net_device *alloc_etherdev(int sizeof_priv)
+struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count)
 {
-	return alloc_netdev(sizeof_priv, "eth%d", ether_setup);
+	return alloc_netdev_mq(sizeof_priv, "eth%d", ether_setup, queue_count);
 }
-EXPORT_SYMBOL(alloc_etherdev);
+EXPORT_SYMBOL(alloc_etherdev_mq);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 7ec6610..17ad278 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -140,7 +140,7 @@
 
 	dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
 	if (!dev) {
-		IEEE80211_ERROR("Unable to network device.\n");
+		IEEE80211_ERROR("Unable to allocate network device.\n");
 		goto failed;
 	}
 	ieee = netdev_priv(dev);
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index cc8110b..afb6c66 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -271,8 +271,11 @@
 			 */
 			dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
 			ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
-			if (ieee80211softmac_start_scan(mac))
+			if (ieee80211softmac_start_scan(mac)) {
 				dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
+				mac->associnfo.associating = 0;
+				mac->associnfo.associated = 0;
+			}
 			goto out;
 		} else {
 			mac->associnfo.associating = 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index e9cdc66..6398e6e 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -33,7 +33,10 @@
 	struct ieee80211softmac_device *softmac;
 	struct net_device *dev;
 
-	dev = alloc_ieee80211(sizeof(struct ieee80211softmac_device) + sizeof_priv);
+	dev = alloc_ieee80211(sizeof(*softmac) + sizeof_priv);
+	if (!dev)
+		return NULL;
+
 	softmac = ieee80211_priv(dev);
 	softmac->dev = dev;
 	softmac->ieee = netdev_priv(dev);
@@ -453,18 +456,13 @@
 ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_network *add_net)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
+	struct ieee80211softmac_network *softmac_net;
 
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
-			break;
-		else
-			softmac_net = NULL;
+			return;
 	}
-	if(softmac_net == NULL)
-		list_add(&(add_net->list), &mac->network_list);
+	list_add(&(add_net->list), &mac->network_list);
 }
 
 /* Add a network to the list, with locking */
@@ -503,16 +501,13 @@
 ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
 	u8 *bssid)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	struct ieee80211softmac_network *softmac_net;
+
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
-			break;
-		else
-			softmac_net = NULL;
+			return softmac_net;
 	}
-	return softmac_net;
+	return NULL;
 }
 
 /* Get a network from the list by BSSID with locking */
@@ -534,11 +529,9 @@
 ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_essid *essid)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
+	struct ieee80211softmac_network *softmac_net;
 
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if (softmac_net->essid.len == essid->len &&
 			!memcmp(softmac_net->essid.data, essid->data, essid->len))
 			return softmac_net;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 010fbb2..fb79097 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -116,48 +116,6 @@
 	  equal "cost" and chooses one of them in a non-deterministic fashion
 	  if a matching packet arrives.
 
-config IP_ROUTE_MULTIPATH_CACHED
-	bool "IP: equal cost multipath with caching support (EXPERIMENTAL)"
-	depends on IP_ROUTE_MULTIPATH
-	help
-	  Normally, equal cost multipath routing is not supported by the
-	  routing cache. If you say Y here, alternative routes are cached
-	  and on cache lookup a route is chosen in a configurable fashion.
-
-	  If unsure, say N.
-
-config IP_ROUTE_MULTIPATH_RR
-	tristate "MULTIPATH: round robin algorithm"
-	depends on IP_ROUTE_MULTIPATH_CACHED
-	help
-	  Multipath routes are chosen according to Round Robin
-
-config IP_ROUTE_MULTIPATH_RANDOM
-	tristate "MULTIPATH: random algorithm"
-	depends on IP_ROUTE_MULTIPATH_CACHED
-	help
-	  Multipath routes are chosen in a random fashion. Actually,
-	  there is no weight for a route. The advantage of this policy
-	  is that it is implemented stateless and therefore introduces only
-	  a very small delay.
-
-config IP_ROUTE_MULTIPATH_WRANDOM
-	tristate "MULTIPATH: weighted random algorithm"
-	depends on IP_ROUTE_MULTIPATH_CACHED
-	help
-	  Multipath routes are chosen in a weighted random fashion. 
-	  The per route weights are the weights visible via ip route 2. As the
-	  corresponding state management introduces some overhead routing delay
-	  is increased.
-
-config IP_ROUTE_MULTIPATH_DRR
-	tristate "MULTIPATH: interface round robin algorithm"
-	depends on IP_ROUTE_MULTIPATH_CACHED
-	help
-	  Connections are distributed in a round robin fashion over the
-	  available interfaces. This policy makes sense if the connections 
-	  should be primarily distributed on interfaces and not on routes. 
-
 config IP_ROUTE_VERBOSE
 	bool "IP: verbose route monitoring"
 	depends on IP_ADVANCED_ROUTER
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 4ff6c15..fbf1674 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -29,14 +29,9 @@
 obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
 obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
 obj-$(CONFIG_IP_PNP) += ipconfig.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
 obj-$(CONFIG_NETFILTER)	+= netfilter.o netfilter/
 obj-$(CONFIG_IP_VS) += ipvs/
 obj-$(CONFIG_INET_DIAG) += inet_diag.o 
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
 obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
 obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 041fba3..06c08e5 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1170,6 +1170,9 @@
 	int ihl;
 	int id;
 
+	if (!(features & NETIF_F_V4_CSUM))
+		features &= ~NETIF_F_SG;
+
 	if (unlikely(skb_shinfo(skb)->gso_type &
 		     ~(SKB_GSO_TCPV4 |
 		       SKB_GSO_UDP |
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 6da8ff5..7a23e59 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -339,3 +339,4 @@
 module_init(ah4_init);
 module_exit(ah4_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 7110779..9ab9d53 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -877,7 +877,7 @@
 
 	n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
 
-	if (ipv4_devconf.arp_accept) {
+	if (IPV4_DEVCONF_ALL(ARP_ACCEPT)) {
 		/* Unsolicited ARP is not accepted by default.
 		   It is possible, that this option should be enabled for some
 		   devices (strip is candidate)
@@ -885,7 +885,7 @@
 		if (n == NULL &&
 		    arp->ar_op == htons(ARPOP_REPLY) &&
 		    inet_addr_type(sip) == RTN_UNICAST)
-			n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
+			n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
 	}
 
 	if (n) {
@@ -987,11 +987,11 @@
 			return 0;
 		}
 		if (dev == NULL) {
-			ipv4_devconf.proxy_arp = 1;
+			IPV4_DEVCONF_ALL(PROXY_ARP) = 1;
 			return 0;
 		}
 		if (__in_dev_get_rtnl(dev)) {
-			__in_dev_get_rtnl(dev)->cnf.proxy_arp = 1;
+			IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 1);
 			return 0;
 		}
 		return -ENXIO;
@@ -1093,11 +1093,12 @@
 			return pneigh_delete(&arp_tbl, &ip, dev);
 		if (mask == 0) {
 			if (dev == NULL) {
-				ipv4_devconf.proxy_arp = 0;
+				IPV4_DEVCONF_ALL(PROXY_ARP) = 0;
 				return 0;
 			}
 			if (__in_dev_get_rtnl(dev)) {
-				__in_dev_get_rtnl(dev)->cnf.proxy_arp = 0;
+				IN_DEV_CONF_SET(__in_dev_get_rtnl(dev),
+						PROXY_ARP, 0);
 				return 0;
 			}
 			return -ENXIO;
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 86a2b52..ab56a05 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -45,6 +45,7 @@
 #include <net/cipso_ipv4.h>
 #include <asm/atomic.h>
 #include <asm/bug.h>
+#include <asm/unaligned.h>
 
 struct cipso_v4_domhsh_entry {
 	char *domain;
@@ -1000,7 +1001,7 @@
 		return -EFAULT;
 
 	for (iter = 0; iter < enumcat_len; iter += 2) {
-		cat = ntohs(*((__be16 *)&enumcat[iter]));
+		cat = ntohs(get_unaligned((__be16 *)&enumcat[iter]));
 		if (cat <= cat_prev)
 			return -EFAULT;
 		cat_prev = cat;
@@ -1068,8 +1069,8 @@
 
 	for (iter = 0; iter < net_cat_len; iter += 2) {
 		ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
-					    ntohs(*((__be16 *)&net_cat[iter])),
-					    GFP_ATOMIC);
+				ntohs(get_unaligned((__be16 *)&net_cat[iter])),
+				GFP_ATOMIC);
 		if (ret_val != 0)
 			return ret_val;
 	}
@@ -1102,9 +1103,10 @@
 		return -EFAULT;
 
 	for (iter = 0; iter < rngcat_len; iter += 4) {
-		cat_high = ntohs(*((__be16 *)&rngcat[iter]));
+		cat_high = ntohs(get_unaligned((__be16 *)&rngcat[iter]));
 		if ((iter + 4) <= rngcat_len)
-			cat_low = ntohs(*((__be16 *)&rngcat[iter + 2]));
+			cat_low = ntohs(
+				get_unaligned((__be16 *)&rngcat[iter + 2]));
 		else
 			cat_low = 0;
 
@@ -1201,9 +1203,10 @@
 	u16 cat_high;
 
 	for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
-		cat_high = ntohs(*((__be16 *)&net_cat[net_iter]));
+		cat_high = ntohs(get_unaligned((__be16 *)&net_cat[net_iter]));
 		if ((net_iter + 4) <= net_cat_len)
-			cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2]));
+			cat_low = ntohs(
+			      get_unaligned((__be16 *)&net_cat[net_iter + 2]));
 		else
 			cat_low = 0;
 
@@ -1565,7 +1568,7 @@
 	}
 
 	rcu_read_lock();
-	doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2])));
+	doi_def = cipso_v4_doi_search(ntohl(get_unaligned((__be32 *)&opt[2])));
 	if (doi_def == NULL) {
 		err_offset = 2;
 		goto validate_return_locked;
@@ -1709,22 +1712,22 @@
 }
 
 /**
- * cipso_v4_socket_setattr - Add a CIPSO option to a socket
- * @sock: the socket
+ * cipso_v4_sock_setattr - Add a CIPSO option to a socket
+ * @sk: the socket
  * @doi_def: the CIPSO DOI to use
  * @secattr: the specific security attributes of the socket
  *
  * Description:
  * Set the CIPSO option on the given socket using the DOI definition and
  * security attributes passed to the function.  This function requires
- * exclusive access to @sock->sk, which means it either needs to be in the
- * process of being created or locked via lock_sock(sock->sk).  Returns zero on
- * success and negative values on failure.
+ * exclusive access to @sk, which means it either needs to be in the
+ * process of being created or locked.  Returns zero on success and negative
+ * values on failure.
  *
  */
-int cipso_v4_socket_setattr(const struct socket *sock,
-			    const struct cipso_v4_doi *doi_def,
-			    const struct netlbl_lsm_secattr *secattr)
+int cipso_v4_sock_setattr(struct sock *sk,
+			  const struct cipso_v4_doi *doi_def,
+			  const struct netlbl_lsm_secattr *secattr)
 {
 	int ret_val = -EPERM;
 	u32 iter;
@@ -1732,7 +1735,6 @@
 	u32 buf_len = 0;
 	u32 opt_len;
 	struct ip_options *opt = NULL;
-	struct sock *sk;
 	struct inet_sock *sk_inet;
 	struct inet_connection_sock *sk_conn;
 
@@ -1740,7 +1742,6 @@
 	 * defined yet but it is not a problem as the only users of these
 	 * "lite" PF_INET sockets are functions which do an accept() call
 	 * afterwards so we will label the socket as part of the accept(). */
-	sk = sock->sk;
 	if (sk == NULL)
 		return 0;
 
@@ -1858,7 +1859,7 @@
 	if (ret_val == 0)
 		return ret_val;
 
-	doi = ntohl(*(__be32 *)&cipso_ptr[2]);
+	doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2]));
 	rcu_read_lock();
 	doi_def = cipso_v4_doi_search(doi);
 	if (doi_def == NULL) {
@@ -1892,29 +1893,6 @@
 }
 
 /**
- * cipso_v4_socket_getattr - Get the security attributes from a socket
- * @sock: the socket
- * @secattr: the security attributes
- *
- * Description:
- * Query @sock to see if there is a CIPSO option attached to the socket and if
- * there is return the CIPSO security attributes in @secattr.  Returns zero on
- * success and negative values on failure.
- *
- */
-int cipso_v4_socket_getattr(const struct socket *sock,
-			    struct netlbl_lsm_secattr *secattr)
-{
-	int ret_val;
-
-	lock_sock(sock->sk);
-	ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
-	release_sock(sock->sk);
-
-	return ret_val;
-}
-
-/**
  * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
  * @skb: the packet
  * @secattr: the security attributes
@@ -1936,7 +1914,7 @@
 	if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
 		return 0;
 
-	doi = ntohl(*(__be32 *)&cipso_ptr[2]);
+	doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2]));
 	rcu_read_lock();
 	doi_def = cipso_v4_doi_search(doi);
 	if (doi_def == NULL)
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index dd02a45..0301dd4 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -50,8 +50,12 @@
 			       RT_CONN_FLAGS(sk), oif,
 			       sk->sk_protocol,
 			       inet->sport, usin->sin_port, sk, 1);
-	if (err)
+	if (err) {
+		if (err == -ENETUNREACH)
+			IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
 		return err;
+	}
+
 	if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
 		ip_rt_put(rt);
 		return -EACCES;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7f95e6e..abf6352 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -64,21 +64,27 @@
 #include <net/rtnetlink.h>
 
 struct ipv4_devconf ipv4_devconf = {
-	.accept_redirects = 1,
-	.send_redirects =  1,
-	.secure_redirects = 1,
-	.shared_media =	  1,
+	.data = {
+		[NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
+		[NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
+		[NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
+		[NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
+	},
 };
 
 static struct ipv4_devconf ipv4_devconf_dflt = {
-	.accept_redirects =  1,
-	.send_redirects =    1,
-	.secure_redirects =  1,
-	.shared_media =	     1,
-	.accept_source_route = 1,
+	.data = {
+		[NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
+		[NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
+		[NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
+		[NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
+		[NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE - 1] = 1,
+	},
 };
 
-static struct nla_policy ifa_ipv4_policy[IFA_MAX+1] __read_mostly = {
+#define IPV4_DEVCONF_DFLT(attr) IPV4_DEVCONF(ipv4_devconf_dflt, attr)
+
+static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
 	[IFA_LOCAL]     	= { .type = NLA_U32 },
 	[IFA_ADDRESS]   	= { .type = NLA_U32 },
 	[IFA_BROADCAST] 	= { .type = NLA_U32 },
@@ -141,7 +147,7 @@
 	}
 }
 
-struct in_device *inetdev_init(struct net_device *dev)
+static struct in_device *inetdev_init(struct net_device *dev)
 {
 	struct in_device *in_dev;
 
@@ -321,12 +327,8 @@
 		}
 
 	}
-	if (destroy) {
+	if (destroy)
 		inet_free_ifa(ifa1);
-
-		if (!in_dev->ifa_list)
-			inetdev_destroy(in_dev);
-	}
 }
 
 static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
@@ -399,12 +401,10 @@
 	ASSERT_RTNL();
 
 	if (!in_dev) {
-		in_dev = inetdev_init(dev);
-		if (!in_dev) {
-			inet_free_ifa(ifa);
-			return -ENOBUFS;
-		}
+		inet_free_ifa(ifa);
+		return -ENOBUFS;
 	}
+	ipv4_devconf_setall(in_dev);
 	if (ifa->ifa_dev != in_dev) {
 		BUG_TRAP(!ifa->ifa_dev);
 		in_dev_hold(in_dev);
@@ -514,13 +514,12 @@
 
 	in_dev = __in_dev_get_rtnl(dev);
 	if (in_dev == NULL) {
-		in_dev = inetdev_init(dev);
-		if (in_dev == NULL) {
-			err = -ENOBUFS;
-			goto errout;
-		}
+		err = -ENOBUFS;
+		goto errout;
 	}
 
+	ipv4_devconf_setall(in_dev);
+
 	ifa = inet_alloc_ifa();
 	if (ifa == NULL) {
 		/*
@@ -1057,11 +1056,12 @@
 	if (!in_dev) {
 		if (event == NETDEV_REGISTER) {
 			in_dev = inetdev_init(dev);
-			if (!in_dev)
-				panic("devinet: Failed to create loopback\n");
 			if (dev == &loopback_dev) {
-				in_dev->cnf.no_xfrm = 1;
-				in_dev->cnf.no_policy = 1;
+				if (!in_dev)
+					panic("devinet: "
+					      "Failed to create loopback\n");
+				IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
+				IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
 			}
 		}
 		goto out;
@@ -1237,66 +1237,49 @@
 
 #ifdef CONFIG_SYSCTL
 
-void inet_forward_change(void)
+static void devinet_copy_dflt_conf(int i)
 {
 	struct net_device *dev;
-	int on = ipv4_devconf.forwarding;
-
-	ipv4_devconf.accept_redirects = !on;
-	ipv4_devconf_dflt.forwarding = on;
 
 	read_lock(&dev_base_lock);
 	for_each_netdev(dev) {
 		struct in_device *in_dev;
 		rcu_read_lock();
 		in_dev = __in_dev_get_rcu(dev);
-		if (in_dev)
-			in_dev->cnf.forwarding = on;
+		if (in_dev && !test_bit(i, in_dev->cnf.state))
+			in_dev->cnf.data[i] = ipv4_devconf_dflt.data[i];
 		rcu_read_unlock();
 	}
 	read_unlock(&dev_base_lock);
-
-	rt_cache_flush(0);
 }
 
-static int devinet_sysctl_forward(ctl_table *ctl, int write,
-				  struct file* filp, void __user *buffer,
-				  size_t *lenp, loff_t *ppos)
+static int devinet_conf_proc(ctl_table *ctl, int write,
+			     struct file* filp, void __user *buffer,
+			     size_t *lenp, loff_t *ppos)
 {
-	int *valp = ctl->data;
-	int val = *valp;
 	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
 
-	if (write && *valp != val) {
-		if (valp == &ipv4_devconf.forwarding)
-			inet_forward_change();
-		else if (valp != &ipv4_devconf_dflt.forwarding)
-			rt_cache_flush(0);
+	if (write) {
+		struct ipv4_devconf *cnf = ctl->extra1;
+		int i = (int *)ctl->data - cnf->data;
+
+		set_bit(i, cnf->state);
+
+		if (cnf == &ipv4_devconf_dflt)
+			devinet_copy_dflt_conf(i);
 	}
 
 	return ret;
 }
 
-int ipv4_doint_and_flush(ctl_table *ctl, int write,
-			 struct file* filp, void __user *buffer,
-			 size_t *lenp, loff_t *ppos)
+static int devinet_conf_sysctl(ctl_table *table, int __user *name, int nlen,
+			       void __user *oldval, size_t __user *oldlenp,
+			       void __user *newval, size_t newlen)
 {
-	int *valp = ctl->data;
-	int val = *valp;
-	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
-
-	if (write && *valp != val)
-		rt_cache_flush(0);
-
-	return ret;
-}
-
-int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
-				  void __user *oldval, size_t __user *oldlenp,
-				  void __user *newval, size_t newlen)
-{
+	struct ipv4_devconf *cnf;
 	int *valp = table->data;
 	int new;
+	int i;
 
 	if (!newval || !newlen)
 		return 0;
@@ -1327,10 +1310,113 @@
 	}
 
 	*valp = new;
-	rt_cache_flush(0);
+
+	cnf = table->extra1;
+	i = (int *)table->data - cnf->data;
+
+	set_bit(i, cnf->state);
+
+	if (cnf == &ipv4_devconf_dflt)
+		devinet_copy_dflt_conf(i);
+
 	return 1;
 }
 
+void inet_forward_change(void)
+{
+	struct net_device *dev;
+	int on = IPV4_DEVCONF_ALL(FORWARDING);
+
+	IPV4_DEVCONF_ALL(ACCEPT_REDIRECTS) = !on;
+	IPV4_DEVCONF_DFLT(FORWARDING) = on;
+
+	read_lock(&dev_base_lock);
+	for_each_netdev(dev) {
+		struct in_device *in_dev;
+		rcu_read_lock();
+		in_dev = __in_dev_get_rcu(dev);
+		if (in_dev)
+			IN_DEV_CONF_SET(in_dev, FORWARDING, on);
+		rcu_read_unlock();
+	}
+	read_unlock(&dev_base_lock);
+
+	rt_cache_flush(0);
+}
+
+static int devinet_sysctl_forward(ctl_table *ctl, int write,
+				  struct file* filp, void __user *buffer,
+				  size_t *lenp, loff_t *ppos)
+{
+	int *valp = ctl->data;
+	int val = *valp;
+	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+
+	if (write && *valp != val) {
+		if (valp == &IPV4_DEVCONF_ALL(FORWARDING))
+			inet_forward_change();
+		else if (valp != &IPV4_DEVCONF_DFLT(FORWARDING))
+			rt_cache_flush(0);
+	}
+
+	return ret;
+}
+
+int ipv4_doint_and_flush(ctl_table *ctl, int write,
+			 struct file* filp, void __user *buffer,
+			 size_t *lenp, loff_t *ppos)
+{
+	int *valp = ctl->data;
+	int val = *valp;
+	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+
+	if (write && *valp != val)
+		rt_cache_flush(0);
+
+	return ret;
+}
+
+int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
+				  void __user *oldval, size_t __user *oldlenp,
+				  void __user *newval, size_t newlen)
+{
+	int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
+				      newval, newlen);
+
+	if (ret == 1)
+		rt_cache_flush(0);
+
+	return ret;
+}
+
+
+#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc, sysctl) \
+	{ \
+		.ctl_name	= NET_IPV4_CONF_ ## attr, \
+		.procname	= name, \
+		.data		= ipv4_devconf.data + \
+				  NET_IPV4_CONF_ ## attr - 1, \
+		.maxlen		= sizeof(int), \
+		.mode		= mval, \
+		.proc_handler	= proc, \
+		.strategy	= sysctl, \
+		.extra1		= &ipv4_devconf, \
+	}
+
+#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
+	DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc, \
+			     devinet_conf_sysctl)
+
+#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
+	DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc, \
+			     devinet_conf_sysctl)
+
+#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc, sysctl) \
+	DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc, sysctl)
+
+#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \
+	DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush, \
+				     ipv4_doint_and_flush_strategy)
 
 static struct devinet_sysctl_table {
 	struct ctl_table_header *sysctl_header;
@@ -1341,178 +1427,34 @@
 	ctl_table		devinet_root_dir[2];
 } devinet_sysctl = {
 	.devinet_vars = {
-		{
-			.ctl_name	= NET_IPV4_CONF_FORWARDING,
-			.procname	= "forwarding",
-			.data		= &ipv4_devconf.forwarding,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &devinet_sysctl_forward,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_MC_FORWARDING,
-			.procname	= "mc_forwarding",
-			.data		= &ipv4_devconf.mc_forwarding,
-			.maxlen		= sizeof(int),
-			.mode		= 0444,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_ACCEPT_REDIRECTS,
-			.procname	= "accept_redirects",
-			.data		= &ipv4_devconf.accept_redirects,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_SECURE_REDIRECTS,
-			.procname	= "secure_redirects",
-			.data		= &ipv4_devconf.secure_redirects,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_SHARED_MEDIA,
-			.procname	= "shared_media",
-			.data		= &ipv4_devconf.shared_media,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_RP_FILTER,
-			.procname	= "rp_filter",
-			.data		= &ipv4_devconf.rp_filter,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_SEND_REDIRECTS,
-			.procname	= "send_redirects",
-			.data		= &ipv4_devconf.send_redirects,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE,
-			.procname	= "accept_source_route",
-			.data		= &ipv4_devconf.accept_source_route,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_PROXY_ARP,
-			.procname	= "proxy_arp",
-			.data		= &ipv4_devconf.proxy_arp,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_MEDIUM_ID,
-			.procname	= "medium_id",
-			.data		= &ipv4_devconf.medium_id,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_BOOTP_RELAY,
-			.procname	= "bootp_relay",
-			.data		= &ipv4_devconf.bootp_relay,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_LOG_MARTIANS,
-			.procname	= "log_martians",
-			.data		= &ipv4_devconf.log_martians,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_TAG,
-			.procname	= "tag",
-			.data		= &ipv4_devconf.tag,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_ARPFILTER,
-			.procname	= "arp_filter",
-			.data		= &ipv4_devconf.arp_filter,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_ARP_ANNOUNCE,
-			.procname	= "arp_announce",
-			.data		= &ipv4_devconf.arp_announce,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_ARP_IGNORE,
-			.procname	= "arp_ignore",
-			.data		= &ipv4_devconf.arp_ignore,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_ARP_ACCEPT,
-			.procname	= "arp_accept",
-			.data		= &ipv4_devconf.arp_accept,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &proc_dointvec,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_NOXFRM,
-			.procname	= "disable_xfrm",
-			.data		= &ipv4_devconf.no_xfrm,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &ipv4_doint_and_flush,
-			.strategy	= &ipv4_doint_and_flush_strategy,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_NOPOLICY,
-			.procname	= "disable_policy",
-			.data		= &ipv4_devconf.no_policy,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &ipv4_doint_and_flush,
-			.strategy	= &ipv4_doint_and_flush_strategy,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_FORCE_IGMP_VERSION,
-			.procname	= "force_igmp_version",
-			.data		= &ipv4_devconf.force_igmp_version,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &ipv4_doint_and_flush,
-			.strategy	= &ipv4_doint_and_flush_strategy,
-		},
-		{
-			.ctl_name	= NET_IPV4_CONF_PROMOTE_SECONDARIES,
-			.procname	= "promote_secondaries",
-			.data		= &ipv4_devconf.promote_secondaries,
-			.maxlen		= sizeof(int),
-			.mode		= 0644,
-			.proc_handler	= &ipv4_doint_and_flush,
-			.strategy	= &ipv4_doint_and_flush_strategy,
-		},
+		DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
+					     devinet_sysctl_forward,
+					     devinet_conf_sysctl),
+		DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
+
+		DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
+		DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
+		DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"),
+		DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"),
+		DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
+		DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
+					"accept_source_route"),
+		DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
+		DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
+		DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
+		DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
+		DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
+		DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
+		DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
+		DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
+		DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
+
+		DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
+		DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
+		DEVINET_SYSCTL_FLUSHING_ENTRY(FORCE_IGMP_VERSION,
+					      "force_igmp_version"),
+		DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
+					      "promote_secondaries"),
 	},
 	.devinet_dev = {
 		{
@@ -1561,6 +1503,7 @@
 		return;
 	for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
 		t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
+		t->devinet_vars[i].extra1 = p;
 	}
 
 	if (dev) {
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 47c95e8..98767a4 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -481,3 +481,4 @@
 module_init(esp4_init);
 module_exit(esp4_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_ESP);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 837f295..2eb909b 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -250,8 +250,6 @@
 	return -EINVAL;
 }
 
-#ifndef CONFIG_IP_NOSIOCRT
-
 static inline __be32 sk_extract_addr(struct sockaddr *addr)
 {
 	return ((struct sockaddr_in *) addr)->sin_addr.s_addr;
@@ -443,16 +441,7 @@
 	return -EINVAL;
 }
 
-#else
-
-int ip_rt_ioctl(unsigned int cmd, void *arg)
-{
-	return -EINVAL;
-}
-
-#endif
-
-struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = {
+const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = {
 	[RTA_DST]		= { .type = NLA_U32 },
 	[RTA_SRC]		= { .type = NLA_U32 },
 	[RTA_IIF]		= { .type = NLA_U32 },
@@ -464,7 +453,6 @@
 	[RTA_MULTIPATH]		= { .len = sizeof(struct rtnexthop) },
 	[RTA_PROTOINFO]		= { .type = NLA_U32 },
 	[RTA_FLOW]		= { .type = NLA_U32 },
-	[RTA_MP_ALGO]		= { .type = NLA_U32 },
 };
 
 static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -526,9 +514,6 @@
 		case RTA_FLOW:
 			cfg->fc_flow = nla_get_u32(attr);
 			break;
-		case RTA_MP_ALGO:
-			cfg->fc_mp_alg = nla_get_u32(attr);
-			break;
 		case RTA_TABLE:
 			cfg->fc_table = nla_get_u32(attr);
 			break;
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 9cfecf1..07e843a 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -456,6 +456,8 @@
 			fib_release_info(fi_drop);
 			if (state & FA_S_ACCESSED)
 				rt_cache_flush(-1);
+			rtmsg_fib(RTM_NEWROUTE, key, fa, cfg->fc_dst_len, tb->tb_id,
+				  &cfg->fc_nlinfo, NLM_F_REPLACE);
 			return 0;
 		}
 
@@ -523,7 +525,7 @@
 	rt_cache_flush(-1);
 
 	rtmsg_fib(RTM_NEWROUTE, key, new_fa, cfg->fc_dst_len, tb->tb_id,
-		  &cfg->fc_nlinfo);
+		  &cfg->fc_nlinfo, 0);
 	return 0;
 
 out_free_new_fa:
@@ -589,7 +591,7 @@
 
 		fa = fa_to_delete;
 		rtmsg_fib(RTM_DELROUTE, key, fa, cfg->fc_dst_len,
-			  tb->tb_id, &cfg->fc_nlinfo);
+			  tb->tb_id, &cfg->fc_nlinfo, 0);
 
 		kill_fn = 0;
 		write_lock_bh(&fib_hash_lock);
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index 0e8b70b..eef9eec 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -30,7 +30,8 @@
 			 int dst_len, u8 tos, struct fib_info *fi,
 			 unsigned int);
 extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
-		      int dst_len, u32 tb_id, struct nl_info *info);
+		      int dst_len, u32 tb_id, struct nl_info *info,
+		      unsigned int nlm_flags);
 extern struct fib_alias *fib_find_alias(struct list_head *fah,
 					u8 tos, u32 prio);
 extern int fib_detect_death(struct fib_info *fi, int order,
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 33083ad..2a94784 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -169,7 +169,7 @@
 	return NULL;
 }
 
-static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
 	FRA_GENERIC_POLICY,
 	[FRA_FLOW]	= { .type = NLA_U32 },
 };
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 406ea70..c434119 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -42,7 +42,6 @@
 #include <net/tcp.h>
 #include <net/sock.h>
 #include <net/ip_fib.h>
-#include <net/ip_mp_alg.h>
 #include <net/netlink.h>
 #include <net/nexthop.h>
 
@@ -301,7 +300,8 @@
 }
 
 void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
-	       int dst_len, u32 tb_id, struct nl_info *info)
+	       int dst_len, u32 tb_id, struct nl_info *info,
+	       unsigned int nlm_flags)
 {
 	struct sk_buff *skb;
 	u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
@@ -313,7 +313,7 @@
 
 	err = fib_dump_info(skb, info->pid, seq, event, tb_id,
 			    fa->fa_type, fa->fa_scope, key, dst_len,
-			    fa->fa_tos, fa->fa_info, 0);
+			    fa->fa_tos, fa->fa_info, nlm_flags);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in fib_nlmsg_size() */
 		WARN_ON(err == -EMSGSIZE);
@@ -696,13 +696,6 @@
 			goto err_inval;
 	}
 #endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	if (cfg->fc_mp_alg) {
-		if (cfg->fc_mp_alg < IP_MP_ALG_NONE ||
-		    cfg->fc_mp_alg > IP_MP_ALG_MAX)
-			goto err_inval;
-	}
-#endif
 
 	err = -ENOBUFS;
 	if (fib_info_cnt >= fib_hash_size) {
@@ -790,10 +783,6 @@
 #endif
 	}
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	fi->fib_mp_alg = cfg->fc_mp_alg;
-#endif
-
 	if (fib_props[cfg->fc_type].error) {
 		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
 			goto err_inval;
@@ -939,10 +928,6 @@
 	res->type = fa->fa_type;
 	res->scope = fa->fa_scope;
 	res->fi = fa->fa_info;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	res->netmask = mask;
-	res->network = zone & inet_make_mask(prefixlen);
-#endif
 	atomic_inc(&res->fi->fib_clntref);
 	return 0;
 }
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 9be7da7..30e332a 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1226,6 +1226,8 @@
 			fib_release_info(fi_drop);
 			if (state & FA_S_ACCESSED)
 				rt_cache_flush(-1);
+			rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
+				tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
 
 			goto succeeded;
 		}
@@ -1278,7 +1280,7 @@
 
 	rt_cache_flush(-1);
 	rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
-		  &cfg->fc_nlinfo);
+		  &cfg->fc_nlinfo, 0);
 succeeded:
 	return 0;
 
@@ -1624,7 +1626,7 @@
 
 	fa = fa_to_delete;
 	rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id,
-		  &cfg->fc_nlinfo);
+		  &cfg->fc_nlinfo, 0);
 
 	l = fib_find_node(t, key);
 	li = find_leaf_info(l, plen);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index d38cbba..02a899b 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -514,9 +514,15 @@
 
 	saddr = iph->daddr;
 	if (!(rt->rt_flags & RTCF_LOCAL)) {
-		if (sysctl_icmp_errors_use_inbound_ifaddr)
-			saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK);
-		else
+		struct net_device *dev = NULL;
+
+		if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr)
+			dev = dev_get_by_index(rt->fl.iif);
+
+		if (dev) {
+			saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK);
+			dev_put(dev);
+		} else
 			saddr = 0;
 	}
 
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index f4dd474..a646409 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -128,14 +128,16 @@
  * contradict to specs provided this delay is small enough.
  */
 
-#define IGMP_V1_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 1 || \
-		(in_dev)->cnf.force_igmp_version == 1 || \
-		((in_dev)->mr_v1_seen && \
-		time_before(jiffies, (in_dev)->mr_v1_seen)))
-#define IGMP_V2_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 2 || \
-		(in_dev)->cnf.force_igmp_version == 2 || \
-		((in_dev)->mr_v2_seen && \
-		time_before(jiffies, (in_dev)->mr_v2_seen)))
+#define IGMP_V1_SEEN(in_dev) \
+	(IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 1 || \
+	 IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
+	 ((in_dev)->mr_v1_seen && \
+	  time_before(jiffies, (in_dev)->mr_v1_seen)))
+#define IGMP_V2_SEEN(in_dev) \
+	(IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 2 || \
+	 IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
+	 ((in_dev)->mr_v2_seen && \
+	  time_before(jiffies, (in_dev)->mr_v2_seen)))
 
 static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
 static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 43fb160..fbe7714 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -31,10 +31,8 @@
 
 /*
  * This array holds the first and last local port number.
- * For high-usage systems, use sysctl to change this to
- * 32768-61000
  */
-int sysctl_local_port_range[2] = { 1024, 4999 };
+int sysctl_local_port_range[2] = { 32768, 61000 };
 
 int inet_csk_bind_conflict(const struct sock *sk,
 			   const struct inet_bind_bucket *tb)
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index a73cf93..2586df0 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -14,7 +14,8 @@
 #include <net/ip.h>
 
 /* Must be called with locally disabled BHs. */
-void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo)
+static void __inet_twsk_kill(struct inet_timewait_sock *tw,
+			     struct inet_hashinfo *hashinfo)
 {
 	struct inet_bind_hashbucket *bhead;
 	struct inet_bind_bucket *tb;
@@ -47,8 +48,6 @@
 	inet_twsk_put(tw);
 }
 
-EXPORT_SYMBOL_GPL(__inet_twsk_kill);
-
 /*
  * Enter the time wait state. This is called with locally disabled BH.
  * Essentially we whip up a timewait bucket, copy the relevant info into it
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 6328293..5c14ed6 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -809,7 +809,8 @@
 
 	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;
 
-	if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+	if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
+	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index d6427d9..c9e2b5e 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -399,6 +399,10 @@
 	to->tc_index = from->tc_index;
 #endif
 	nf_copy(to, from);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	to->nf_trace = from->nf_trace;
+#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	to->ipvs_property = from->ipvs_property;
 #endif
@@ -837,7 +841,7 @@
 	 */
 	if (transhdrlen &&
 	    length + fragheaderlen <= mtu &&
-	    rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
+	    rt->u.dst.dev->features & NETIF_F_V4_CSUM &&
 	    !exthdrlen)
 		csummode = CHECKSUM_PARTIAL;
 
@@ -1352,7 +1356,8 @@
 	}
 
 	{
-		struct flowi fl = { .nl_u = { .ip4_u =
+		struct flowi fl = { .oif = arg->bound_dev_if,
+				    .nl_u = { .ip4_u =
 					      { .daddr = daddr,
 						.saddr = rt->rt_spec_dst,
 						.tos = RT_TOS(ip_hdr(skb)->tos) } },
@@ -1376,6 +1381,7 @@
 	inet->tos = ip_hdr(skb)->tos;
 	sk->sk_priority = skb->priority;
 	sk->sk_protocol = ip_hdr(skb)->protocol;
+	sk->sk_bound_dev_if = arg->bound_dev_if;
 	ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0,
 		       &ipc, rt, MSG_DONTWAIT);
 	if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index ab86137..e787044 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -485,3 +485,4 @@
 MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
 
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP);
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index ebd2f2d..3964372 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -595,7 +595,8 @@
 	 */
 	max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr));
 
-	if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 0ebae41..d96582a 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -152,9 +152,11 @@
 			dev->flags |= IFF_MULTICAST;
 
 			in_dev = __in_dev_get_rtnl(dev);
-			if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL)
+			if (in_dev == NULL)
 				goto failure;
-			in_dev->cnf.rp_filter = 0;
+
+			ipv4_devconf_setall(in_dev);
+			IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
 
 			if (dev_open(dev))
 				goto failure;
@@ -218,10 +220,15 @@
 	}
 	dev->iflink = 0;
 
-	if ((in_dev = inetdev_init(dev)) == NULL)
+	rcu_read_lock();
+	if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {
+		rcu_read_unlock();
 		goto failure;
+	}
 
-	in_dev->cnf.rp_filter = 0;
+	ipv4_devconf_setall(in_dev);
+	IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
+	rcu_read_unlock();
 
 	if (dev_open(dev))
 		goto failure;
@@ -281,7 +288,7 @@
 	dev_set_allmulti(dev, -1);
 
 	if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) {
-		in_dev->cnf.mc_forwarding--;
+		IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
 		ip_rt_multicast_event(in_dev);
 	}
 
@@ -426,7 +433,7 @@
 
 	if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
 		return -EADDRNOTAVAIL;
-	in_dev->cnf.mc_forwarding++;
+	IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
 	dev_set_allmulti(dev, +1);
 	ip_rt_multicast_event(in_dev);
 
@@ -841,7 +848,7 @@
 {
 	rtnl_lock();
 	if (sk == mroute_socket) {
-		ipv4_devconf.mc_forwarding--;
+		IPV4_DEVCONF_ALL(MC_FORWARDING)--;
 
 		write_lock_bh(&mrt_lock);
 		mroute_socket=NULL;
@@ -890,7 +897,7 @@
 			mroute_socket=sk;
 			write_unlock_bh(&mrt_lock);
 
-			ipv4_devconf.mc_forwarding++;
+			IPV4_DEVCONF_ALL(MC_FORWARDING)++;
 		}
 		rtnl_unlock();
 		return ret;
diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
index 891b935..09d0c3f 100644
--- a/net/ipv4/ipvs/Kconfig
+++ b/net/ipv4/ipvs/Kconfig
@@ -1,10 +1,7 @@
 #
 # IP Virtual Server configuration
 #
-menu	"IP: Virtual Server Configuration"
-	depends on NETFILTER
-
-config	IP_VS
+menuconfig IP_VS
 	tristate "IP virtual server support (EXPERIMENTAL)"
 	depends on NETFILTER
 	---help---
@@ -25,9 +22,10 @@
 	  If you want to compile it in kernel, say Y. To compile it as a
 	  module, choose M here. If unsure, say N.
 
+if IP_VS
+
 config	IP_VS_DEBUG
 	bool "IP virtual server debugging"
-	depends on IP_VS
 	---help---
 	  Say Y here if you want to get additional messages useful in
 	  debugging the IP virtual server code. You can change the debug
@@ -35,7 +33,6 @@
 
 config	IP_VS_TAB_BITS
 	int "IPVS connection table size (the Nth power of 2)"
-	depends on IP_VS 
 	default "12" 
 	---help---
 	  The IPVS connection hash table uses the chaining scheme to handle
@@ -61,42 +58,35 @@
 	  needed for your box.
 
 comment "IPVS transport protocol load balancing support"
-        depends on IP_VS
 
 config	IP_VS_PROTO_TCP
 	bool "TCP load balancing support"
-	depends on IP_VS
 	---help---
 	  This option enables support for load balancing TCP transport
 	  protocol. Say Y if unsure.
 
 config	IP_VS_PROTO_UDP
 	bool "UDP load balancing support"
-	depends on IP_VS
 	---help---
 	  This option enables support for load balancing UDP transport
 	  protocol. Say Y if unsure.
 
 config	IP_VS_PROTO_ESP
 	bool "ESP load balancing support"
-	depends on IP_VS
 	---help---
 	  This option enables support for load balancing ESP (Encapsulation
 	  Security Payload) transport protocol. Say Y if unsure.
 
 config	IP_VS_PROTO_AH
 	bool "AH load balancing support"
-	depends on IP_VS
 	---help---
 	  This option enables support for load balancing AH (Authentication
 	  Header) transport protocol. Say Y if unsure.
 
 comment "IPVS scheduler"
-        depends on IP_VS
 
 config	IP_VS_RR
 	tristate "round-robin scheduling"
-	depends on IP_VS
 	---help---
 	  The robin-robin scheduling algorithm simply directs network
 	  connections to different real servers in a round-robin manner.
@@ -106,7 +96,6 @@
  
 config	IP_VS_WRR
         tristate "weighted round-robin scheduling" 
-	depends on IP_VS
 	---help---
 	  The weighted robin-robin scheduling algorithm directs network
 	  connections to different real servers based on server weights
@@ -120,7 +109,6 @@
 
 config	IP_VS_LC
         tristate "least-connection scheduling"
-        depends on IP_VS
 	---help---
 	  The least-connection scheduling algorithm directs network
 	  connections to the server with the least number of active 
@@ -131,7 +119,6 @@
 
 config	IP_VS_WLC
         tristate "weighted least-connection scheduling"
-        depends on IP_VS
 	---help---
 	  The weighted least-connection scheduling algorithm directs network
 	  connections to the server with the least active connections
@@ -142,7 +129,6 @@
 
 config	IP_VS_LBLC
 	tristate "locality-based least-connection scheduling"
-        depends on IP_VS
 	---help---
 	  The locality-based least-connection scheduling algorithm is for
 	  destination IP load balancing. It is usually used in cache cluster.
@@ -157,7 +143,6 @@
 
 config  IP_VS_LBLCR
 	tristate "locality-based least-connection with replication scheduling"
-        depends on IP_VS
 	---help---
 	  The locality-based least-connection with replication scheduling
 	  algorithm is also for destination IP load balancing. It is 
@@ -176,7 +161,6 @@
 
 config	IP_VS_DH
 	tristate "destination hashing scheduling"
-        depends on IP_VS
 	---help---
 	  The destination hashing scheduling algorithm assigns network
 	  connections to the servers through looking up a statically assigned
@@ -187,7 +171,6 @@
 
 config	IP_VS_SH
 	tristate "source hashing scheduling"
-        depends on IP_VS
 	---help---
 	  The source hashing scheduling algorithm assigns network
 	  connections to the servers through looking up a statically assigned
@@ -198,7 +181,6 @@
 
 config	IP_VS_SED
 	tristate "shortest expected delay scheduling"
-        depends on IP_VS
 	---help---
 	  The shortest expected delay scheduling algorithm assigns network
 	  connections to the server with the shortest expected delay. The 
@@ -212,7 +194,6 @@
 
 config	IP_VS_NQ
 	tristate "never queue scheduling"
-        depends on IP_VS
 	---help---
 	  The never queue scheduling algorithm adopts a two-speed model.
 	  When there is an idle server available, the job will be sent to
@@ -225,11 +206,10 @@
 	  module, choose M here. If unsure, say N.
 
 comment 'IPVS application helper'
-	depends on IP_VS
 
 config	IP_VS_FTP
   	tristate "FTP protocol helper"
-        depends on IP_VS && IP_VS_PROTO_TCP
+        depends on IP_VS_PROTO_TCP
 	---help---
 	  FTP is a protocol that transfers IP address and/or port number in
 	  the payload. In the virtual server via Network Address Translation,
@@ -241,4 +221,4 @@
 	  If you want to compile it in kernel, say Y. To compile it as a
 	  module, choose M here. If unsure, say N.
 
-endmenu
+endif # IP_VS
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 15ad5dd..8d6901d 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -549,7 +549,7 @@
 	return 0;
 }
 
-static struct seq_operations ip_vs_app_seq_ops = {
+static const struct seq_operations ip_vs_app_seq_ops = {
 	.start = ip_vs_app_seq_start,
 	.next  = ip_vs_app_seq_next,
 	.stop  = ip_vs_app_seq_stop,
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 7018f97..3b446b1 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -745,7 +745,7 @@
 	return 0;
 }
 
-static struct seq_operations ip_vs_conn_seq_ops = {
+static const struct seq_operations ip_vs_conn_seq_ops = {
 	.start = ip_vs_conn_seq_start,
 	.next  = ip_vs_conn_seq_next,
 	.stop  = ip_vs_conn_seq_stop,
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 68fe1d4..e1052bc 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -1783,7 +1783,7 @@
 	return 0;
 }
 
-static struct seq_operations ip_vs_info_seq_ops = {
+static const struct seq_operations ip_vs_info_seq_ops = {
 	.start = ip_vs_info_seq_start,
 	.next  = ip_vs_info_seq_next,
 	.stop  = ip_vs_info_seq_stop,
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 7ea2d98..356f067 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -67,6 +67,11 @@
 	struct ip_vs_seq        out_seq;        /* outgoing seq. struct */
 };
 
+struct ip_vs_sync_thread_data {
+	struct completion *startup;
+	int state;
+};
+
 #define IP_VS_SYNC_CONN_TIMEOUT (3*60*HZ)
 #define SIMPLE_CONN_SIZE  (sizeof(struct ip_vs_sync_conn))
 #define FULL_CONN_SIZE  \
@@ -751,6 +756,7 @@
 	mm_segment_t oldmm;
 	int state;
 	const char *name;
+	struct ip_vs_sync_thread_data *tinfo = startup;
 
 	/* increase the module use count */
 	ip_vs_use_count_inc();
@@ -789,7 +795,14 @@
 	add_wait_queue(&sync_wait, &wait);
 
 	set_sync_pid(state, current->pid);
-	complete((struct completion *)startup);
+	complete(tinfo->startup);
+
+	/*
+	 * once we call the completion queue above, we should
+	 * null out that reference, since its allocated on the
+	 * stack of the creating kernel thread
+	 */
+	tinfo->startup = NULL;
 
 	/* processing master/backup loop here */
 	if (state == IP_VS_STATE_MASTER)
@@ -801,6 +814,14 @@
 	remove_wait_queue(&sync_wait, &wait);
 
 	/* thread exits */
+
+	/*
+	 * If we weren't explicitly stopped, then we
+	 * exited in error, and should undo our state
+	 */
+	if ((!stop_master_sync) && (!stop_backup_sync))
+		ip_vs_sync_state -= tinfo->state;
+
 	set_sync_pid(state, 0);
 	IP_VS_INFO("sync thread stopped!\n");
 
@@ -812,6 +833,11 @@
 	set_stop_sync(state, 0);
 	wake_up(&stop_sync_wait);
 
+	/*
+	 * we need to free the structure that was allocated
+	 * for us in start_sync_thread
+	 */
+	kfree(tinfo);
 	return 0;
 }
 
@@ -838,11 +864,19 @@
 {
 	DECLARE_COMPLETION_ONSTACK(startup);
 	pid_t pid;
+	struct ip_vs_sync_thread_data *tinfo;
 
 	if ((state == IP_VS_STATE_MASTER && sync_master_pid) ||
 	    (state == IP_VS_STATE_BACKUP && sync_backup_pid))
 		return -EEXIST;
 
+	/*
+	 * Note that tinfo will be freed in sync_thread on exit
+	 */
+	tinfo = kmalloc(sizeof(struct ip_vs_sync_thread_data), GFP_KERNEL);
+	if (!tinfo)
+		return -ENOMEM;
+
 	IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
 	IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n",
 		  sizeof(struct ip_vs_sync_conn));
@@ -858,8 +892,11 @@
 		ip_vs_backup_syncid = syncid;
 	}
 
+	tinfo->state = state;
+	tinfo->startup = &startup;
+
   repeat:
-	if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
+	if ((pid = kernel_thread(fork_sync_thread, tinfo, 0)) < 0) {
 		IP_VS_ERR("could not create fork_sync_thread due to %d... "
 			  "retrying.\n", pid);
 		msleep_interruptible(1000);
diff --git a/net/ipv4/multipath.c b/net/ipv4/multipath.c
deleted file mode 100644
index 4e9ca7c..0000000
--- a/net/ipv4/multipath.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* multipath.c: IPV4 multipath algorithm support.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-
-#include <net/ip_mp_alg.h>
-
-static DEFINE_SPINLOCK(alg_table_lock);
-struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1];
-
-int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
-{
-	struct ip_mp_alg_ops **slot;
-	int err;
-
-	if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX ||
-	    !ops->mp_alg_select_route)
-		return -EINVAL;
-
-	spin_lock(&alg_table_lock);
-	slot = &ip_mp_alg_table[n];
-	if (*slot != NULL) {
-		err = -EBUSY;
-	} else {
-		*slot = ops;
-		err = 0;
-	}
-	spin_unlock(&alg_table_lock);
-
-	return err;
-}
-EXPORT_SYMBOL(multipath_alg_register);
-
-void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
-{
-	struct ip_mp_alg_ops **slot;
-
-	if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX)
-		return;
-
-	spin_lock(&alg_table_lock);
-	slot = &ip_mp_alg_table[n];
-	if (*slot == ops)
-		*slot = NULL;
-	spin_unlock(&alg_table_lock);
-
-	synchronize_net();
-}
-EXPORT_SYMBOL(multipath_alg_unregister);
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c
deleted file mode 100644
index b03c5ca..0000000
--- a/net/ipv4/multipath_drr.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- *              Device round robin policy for multipath.
- *
- *
- * Version:	$Id: multipath_drr.c,v 1.1.2.1 2004/09/16 07:42:34 elueck Exp $
- *
- * Authors:	Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-struct multipath_device {
-	int		ifi; /* interface index of device */
-	atomic_t	usecount;
-	int 		allocated;
-};
-
-#define MULTIPATH_MAX_DEVICECANDIDATES 10
-
-static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES];
-static DEFINE_SPINLOCK(state_lock);
-
-static int inline __multipath_findslot(void)
-{
-	int i;
-
-	for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
-		if (state[i].allocated == 0)
-			return i;
-	}
-	return -1;
-}
-
-static int inline __multipath_finddev(int ifindex)
-{
-	int i;
-
-	for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
-		if (state[i].allocated != 0 &&
-		    state[i].ifi == ifindex)
-			return i;
-	}
-	return -1;
-}
-
-static int drr_dev_event(struct notifier_block *this,
-			 unsigned long event, void *ptr)
-{
-	struct net_device *dev = ptr;
-	int devidx;
-
-	switch (event) {
-	case NETDEV_UNREGISTER:
-	case NETDEV_DOWN:
-		spin_lock_bh(&state_lock);
-
-		devidx = __multipath_finddev(dev->ifindex);
-		if (devidx != -1) {
-			state[devidx].allocated = 0;
-			state[devidx].ifi = 0;
-			atomic_set(&state[devidx].usecount, 0);
-		}
-
-		spin_unlock_bh(&state_lock);
-		break;
-	}
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block drr_dev_notifier = {
-	.notifier_call	= drr_dev_event,
-};
-
-
-static void drr_safe_inc(atomic_t *usecount)
-{
-	int n;
-
-	atomic_inc(usecount);
-
-	n = atomic_read(usecount);
-	if (n <= 0) {
-		int i;
-
-		spin_lock_bh(&state_lock);
-
-		for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++)
-			atomic_set(&state[i].usecount, 0);
-
-		spin_unlock_bh(&state_lock);
-	}
-}
-
-static void drr_select_route(const struct flowi *flp,
-			     struct rtable *first, struct rtable **rp)
-{
-	struct rtable *nh, *result, *cur_min;
-	int min_usecount = -1;
-	int devidx = -1;
-	int cur_min_devidx = -1;
-
-	/* 1. make sure all alt. nexthops have the same GC related data */
-	/* 2. determine the new candidate to be returned */
-	result = NULL;
-	cur_min = NULL;
-	for (nh = rcu_dereference(first); nh;
-	     nh = rcu_dereference(nh->u.dst.rt_next)) {
-		if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
-		    multipath_comparekeys(&nh->fl, flp)) {
-			int nh_ifidx = nh->u.dst.dev->ifindex;
-
-			nh->u.dst.lastuse = jiffies;
-			nh->u.dst.__use++;
-			if (result != NULL)
-				continue;
-
-			/* search for the output interface */
-
-			/* this is not SMP safe, only add/remove are
-			 * SMP safe as wrong usecount updates have no big
-			 * impact
-			 */
-			devidx = __multipath_finddev(nh_ifidx);
-			if (devidx == -1) {
-				/* add the interface to the array
-				 * SMP safe
-				 */
-				spin_lock_bh(&state_lock);
-
-				/* due to SMP: search again */
-				devidx = __multipath_finddev(nh_ifidx);
-				if (devidx == -1) {
-					/* add entry for device */
-					devidx = __multipath_findslot();
-					if (devidx == -1) {
-						/* unlikely but possible */
-						continue;
-					}
-
-					state[devidx].allocated = 1;
-					state[devidx].ifi = nh_ifidx;
-					atomic_set(&state[devidx].usecount, 0);
-					min_usecount = 0;
-				}
-
-				spin_unlock_bh(&state_lock);
-			}
-
-			if (min_usecount == 0) {
-				/* if the device has not been used it is
-				 * the primary target
-				 */
-				drr_safe_inc(&state[devidx].usecount);
-				result = nh;
-			} else {
-				int count =
-					atomic_read(&state[devidx].usecount);
-
-				if (min_usecount == -1 ||
-				    count < min_usecount) {
-					cur_min = nh;
-					cur_min_devidx = devidx;
-					min_usecount = count;
-				}
-			}
-		}
-	}
-
-	if (!result) {
-		if (cur_min) {
-			drr_safe_inc(&state[cur_min_devidx].usecount);
-			result = cur_min;
-		} else {
-			result = first;
-		}
-	}
-
-	*rp = result;
-}
-
-static struct ip_mp_alg_ops drr_ops = {
-	.mp_alg_select_route	=	drr_select_route,
-};
-
-static int __init drr_init(void)
-{
-	int err = register_netdevice_notifier(&drr_dev_notifier);
-
-	if (err)
-		return err;
-
-	err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR);
-	if (err)
-		goto fail;
-
-	return 0;
-
-fail:
-	unregister_netdevice_notifier(&drr_dev_notifier);
-	return err;
-}
-
-static void __exit drr_exit(void)
-{
-	unregister_netdevice_notifier(&drr_dev_notifier);
-	multipath_alg_unregister(&drr_ops, IP_MP_ALG_DRR);
-}
-
-module_init(drr_init);
-module_exit(drr_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c
deleted file mode 100644
index c312785..0000000
--- a/net/ipv4/multipath_random.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- *              Random policy for multipath.
- *
- *
- * Version:	$Id: multipath_random.c,v 1.1.2.3 2004/09/21 08:42:11 elueck Exp $
- *
- * Authors:	Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-#define MULTIPATH_MAX_CANDIDATES 40
-
-static void random_select_route(const struct flowi *flp,
-				struct rtable *first,
-				struct rtable **rp)
-{
-	struct rtable *rt;
-	struct rtable *decision;
-	unsigned char candidate_count = 0;
-
-	/* count all candidate */
-	for (rt = rcu_dereference(first); rt;
-	     rt = rcu_dereference(rt->u.dst.rt_next)) {
-		if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
-		    multipath_comparekeys(&rt->fl, flp))
-			++candidate_count;
-	}
-
-	/* choose a random candidate */
-	decision = first;
-	if (candidate_count > 1) {
-		unsigned char i = 0;
-		unsigned char candidate_no = (unsigned char)
-			(random32() % candidate_count);
-
-		/* find chosen candidate and adjust GC data for all candidates
-		 * to ensure they stay in cache
-		 */
-		for (rt = first; rt; rt = rt->u.dst.rt_next) {
-			if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
-			    multipath_comparekeys(&rt->fl, flp)) {
-				rt->u.dst.lastuse = jiffies;
-
-				if (i == candidate_no)
-					decision = rt;
-
-				if (i >= candidate_count)
-					break;
-
-				i++;
-			}
-		}
-	}
-
-	decision->u.dst.__use++;
-	*rp = decision;
-}
-
-static struct ip_mp_alg_ops random_ops = {
-	.mp_alg_select_route	=	random_select_route,
-};
-
-static int __init random_init(void)
-{
-	return multipath_alg_register(&random_ops, IP_MP_ALG_RANDOM);
-}
-
-static void __exit random_exit(void)
-{
-	multipath_alg_unregister(&random_ops, IP_MP_ALG_RANDOM);
-}
-
-module_init(random_init);
-module_exit(random_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c
deleted file mode 100644
index 0ad2252..0000000
--- a/net/ipv4/multipath_rr.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *              Round robin policy for multipath.
- *
- *
- * Version:	$Id: multipath_rr.c,v 1.1.2.2 2004/09/16 07:42:34 elueck Exp $
- *
- * Authors:	Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-static void rr_select_route(const struct flowi *flp,
-			    struct rtable *first, struct rtable **rp)
-{
-	struct rtable *nh, *result, *min_use_cand = NULL;
-	int min_use = -1;
-
-	/* 1. make sure all alt. nexthops have the same GC related data
-	 * 2. determine the new candidate to be returned
-	 */
-	result = NULL;
-	for (nh = rcu_dereference(first); nh;
-	     nh = rcu_dereference(nh->u.dst.rt_next)) {
-		if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
-		    multipath_comparekeys(&nh->fl, flp)) {
-			nh->u.dst.lastuse = jiffies;
-
-			if (min_use == -1 || nh->u.dst.__use < min_use) {
-				min_use = nh->u.dst.__use;
-				min_use_cand = nh;
-			}
-		}
-	}
-	result = min_use_cand;
-	if (!result)
-		result = first;
-
-	result->u.dst.__use++;
-	*rp = result;
-}
-
-static struct ip_mp_alg_ops rr_ops = {
-	.mp_alg_select_route	=	rr_select_route,
-};
-
-static int __init rr_init(void)
-{
-	return multipath_alg_register(&rr_ops, IP_MP_ALG_RR);
-}
-
-static void __exit rr_exit(void)
-{
-	multipath_alg_unregister(&rr_ops, IP_MP_ALG_RR);
-}
-
-module_init(rr_init);
-module_exit(rr_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
deleted file mode 100644
index 57c5036..0000000
--- a/net/ipv4/multipath_wrandom.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- *              Weighted random policy for multipath.
- *
- *
- * Version:	$Id: multipath_wrandom.c,v 1.1.2.3 2004/09/22 07:51:40 elueck Exp $
- *
- * Authors:	Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_fib.h>
-#include <net/ip_mp_alg.h>
-
-#define MULTIPATH_STATE_SIZE 15
-
-struct multipath_candidate {
-	struct multipath_candidate	*next;
-	int				power;
-	struct rtable			*rt;
-};
-
-struct multipath_dest {
-	struct list_head	list;
-
-	const struct fib_nh	*nh_info;
-	__be32			netmask;
-	__be32			network;
-	unsigned char		prefixlen;
-
-	struct rcu_head		rcu;
-};
-
-struct multipath_bucket {
-	struct list_head	head;
-	spinlock_t		lock;
-};
-
-struct multipath_route {
-	struct list_head	list;
-
-	int			oif;
-	__be32			gw;
-	struct list_head	dests;
-
-	struct rcu_head		rcu;
-};
-
-/* state: primarily weight per route information */
-static struct multipath_bucket state[MULTIPATH_STATE_SIZE];
-
-static unsigned char __multipath_lookup_weight(const struct flowi *fl,
-					       const struct rtable *rt)
-{
-	const int state_idx = rt->idev->dev->ifindex % MULTIPATH_STATE_SIZE;
-	struct multipath_route *r;
-	struct multipath_route *target_route = NULL;
-	struct multipath_dest *d;
-	int weight = 1;
-
-	/* lookup the weight information for a certain route */
-	rcu_read_lock();
-
-	/* find state entry for gateway or add one if necessary */
-	list_for_each_entry_rcu(r, &state[state_idx].head, list) {
-		if (r->gw == rt->rt_gateway &&
-		    r->oif == rt->idev->dev->ifindex) {
-			target_route = r;
-			break;
-		}
-	}
-
-	if (!target_route) {
-		/* this should not happen... but we are prepared */
-		printk( KERN_CRIT"%s: missing state for gateway: %u and " \
-			"device %d\n", __FUNCTION__, rt->rt_gateway,
-			rt->idev->dev->ifindex);
-		goto out;
-	}
-
-	/* find state entry for destination */
-	list_for_each_entry_rcu(d, &target_route->dests, list) {
-		__be32 targetnetwork = fl->fl4_dst &
-			inet_make_mask(d->prefixlen);
-
-		if ((targetnetwork & d->netmask) == d->network) {
-			weight = d->nh_info->nh_weight;
-			goto out;
-		}
-	}
-
-out:
-	rcu_read_unlock();
-	return weight;
-}
-
-static void wrandom_init_state(void)
-{
-	int i;
-
-	for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
-		INIT_LIST_HEAD(&state[i].head);
-		spin_lock_init(&state[i].lock);
-	}
-}
-
-static void wrandom_select_route(const struct flowi *flp,
-				 struct rtable *first,
-				 struct rtable **rp)
-{
-	struct rtable *rt;
-	struct rtable *decision;
-	struct multipath_candidate *first_mpc = NULL;
-	struct multipath_candidate *mpc, *last_mpc = NULL;
-	int power = 0;
-	int last_power;
-	int selector;
-	const size_t size_mpc = sizeof(struct multipath_candidate);
-
-	/* collect all candidates and identify their weights */
-	for (rt = rcu_dereference(first); rt;
-	     rt = rcu_dereference(rt->u.dst.rt_next)) {
-		if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
-		    multipath_comparekeys(&rt->fl, flp)) {
-			struct multipath_candidate* mpc =
-				(struct multipath_candidate*)
-				kmalloc(size_mpc, GFP_ATOMIC);
-
-			if (!mpc)
-				return;
-
-			power += __multipath_lookup_weight(flp, rt) * 10000;
-
-			mpc->power = power;
-			mpc->rt = rt;
-			mpc->next = NULL;
-
-			if (!first_mpc)
-				first_mpc = mpc;
-			else
-				last_mpc->next = mpc;
-
-			last_mpc = mpc;
-		}
-	}
-
-	/* choose a weighted random candidate */
-	decision = first;
-	selector = random32() % power;
-	last_power = 0;
-
-	/* select candidate, adjust GC data and cleanup local state */
-	decision = first;
-	last_mpc = NULL;
-	for (mpc = first_mpc; mpc; mpc = mpc->next) {
-		mpc->rt->u.dst.lastuse = jiffies;
-		if (last_power <= selector && selector < mpc->power)
-			decision = mpc->rt;
-
-		last_power = mpc->power;
-		kfree(last_mpc);
-		last_mpc = mpc;
-	}
-
-	/* concurrent __multipath_flush may lead to !last_mpc */
-	kfree(last_mpc);
-
-	decision->u.dst.__use++;
-	*rp = decision;
-}
-
-static void wrandom_set_nhinfo(__be32 network,
-			       __be32 netmask,
-			       unsigned char prefixlen,
-			       const struct fib_nh *nh)
-{
-	const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE;
-	struct multipath_route *r, *target_route = NULL;
-	struct multipath_dest *d, *target_dest = NULL;
-
-	/* store the weight information for a certain route */
-	spin_lock_bh(&state[state_idx].lock);
-
-	/* find state entry for gateway or add one if necessary */
-	list_for_each_entry_rcu(r, &state[state_idx].head, list) {
-		if (r->gw == nh->nh_gw && r->oif == nh->nh_oif) {
-			target_route = r;
-			break;
-		}
-	}
-
-	if (!target_route) {
-		const size_t size_rt = sizeof(struct multipath_route);
-		target_route = (struct multipath_route *)
-			kmalloc(size_rt, GFP_ATOMIC);
-
-		target_route->gw = nh->nh_gw;
-		target_route->oif = nh->nh_oif;
-		memset(&target_route->rcu, 0, sizeof(struct rcu_head));
-		INIT_LIST_HEAD(&target_route->dests);
-
-		list_add_rcu(&target_route->list, &state[state_idx].head);
-	}
-
-	/* find state entry for destination or add one if necessary */
-	list_for_each_entry_rcu(d, &target_route->dests, list) {
-		if (d->nh_info == nh) {
-			target_dest = d;
-			break;
-		}
-	}
-
-	if (!target_dest) {
-		const size_t size_dst = sizeof(struct multipath_dest);
-		target_dest = (struct multipath_dest*)
-			kmalloc(size_dst, GFP_ATOMIC);
-
-		target_dest->nh_info = nh;
-		target_dest->network = network;
-		target_dest->netmask = netmask;
-		target_dest->prefixlen = prefixlen;
-		memset(&target_dest->rcu, 0, sizeof(struct rcu_head));
-
-		list_add_rcu(&target_dest->list, &target_route->dests);
-	}
-	/* else: we already stored this info for another destination =>
-	 * we are finished
-	 */
-
-	spin_unlock_bh(&state[state_idx].lock);
-}
-
-static void __multipath_free(struct rcu_head *head)
-{
-	struct multipath_route *rt = container_of(head, struct multipath_route,
-						  rcu);
-	kfree(rt);
-}
-
-static void __multipath_free_dst(struct rcu_head *head)
-{
-	struct multipath_dest *dst = container_of(head,
-						  struct multipath_dest,
-						  rcu);
-	kfree(dst);
-}
-
-static void wrandom_flush(void)
-{
-	int i;
-
-	/* defere delete to all entries */
-	for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
-		struct multipath_route *r;
-
-		spin_lock_bh(&state[i].lock);
-		list_for_each_entry_rcu(r, &state[i].head, list) {
-			struct multipath_dest *d;
-			list_for_each_entry_rcu(d, &r->dests, list) {
-				list_del_rcu(&d->list);
-				call_rcu(&d->rcu,
-					 __multipath_free_dst);
-			}
-			list_del_rcu(&r->list);
-			call_rcu(&r->rcu,
-				 __multipath_free);
-		}
-
-		spin_unlock_bh(&state[i].lock);
-	}
-}
-
-static struct ip_mp_alg_ops wrandom_ops = {
-	.mp_alg_select_route	=	wrandom_select_route,
-	.mp_alg_flush		=	wrandom_flush,
-	.mp_alg_set_nhinfo	=	wrandom_set_nhinfo,
-};
-
-static int __init wrandom_init(void)
-{
-	wrandom_init_state();
-
-	return multipath_alg_register(&wrandom_ops, IP_MP_ALG_WRANDOM);
-}
-
-static void __exit wrandom_exit(void)
-{
-	multipath_alg_unregister(&wrandom_ops, IP_MP_ALG_WRANDOM);
-}
-
-module_init(wrandom_init);
-module_exit(wrandom_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 46509fa..fa97947 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -230,7 +230,7 @@
 	  To compile it as a module, choose M here.  If unsure, say N.
 
 config IP_NF_TARGET_SAME
-	tristate "SAME target support"
+	tristate "SAME target support (OBSOLETE)"
 	depends on NF_NAT
 	help
 	  This option adds a `SAME' target, which works like the standard SNAT
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index cae4121..d1149ab 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -224,7 +224,7 @@
 	static const char nulldevname[IFNAMSIZ];
 	unsigned int verdict = NF_DROP;
 	struct arphdr *arp;
-	int hotdrop = 0;
+	bool hotdrop = false;
 	struct arpt_entry *e, *back;
 	const char *indev, *outdev;
 	void *table_base;
@@ -1140,13 +1140,13 @@
 }
 
 /* The built-in targets: standard (NULL) and error. */
-static struct arpt_target arpt_standard_target = {
+static struct arpt_target arpt_standard_target __read_mostly = {
 	.name		= ARPT_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= NF_ARP,
 };
 
-static struct arpt_target arpt_error_target = {
+static struct arpt_target arpt_error_target __read_mostly = {
 	.name		= ARPT_ERROR_TARGET,
 	.target		= arpt_error,
 	.targetsize	= ARPT_FUNCTION_MAXNAMELEN,
@@ -1184,7 +1184,7 @@
 	if (ret < 0)
 		goto err4;
 
-	printk("arp_tables: (C) 2002 David S. Miller\n");
+	printk(KERN_INFO "arp_tables: (C) 2002 David S. Miller\n");
 	return 0;
 
 err4:
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 6298d40..c4bdab4 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -65,7 +65,7 @@
 	return mangle->target;
 }
 
-static int
+static bool
 checkentry(const char *tablename, const void *e, const struct xt_target *target,
 	   void *targinfo, unsigned int hook_mask)
 {
@@ -73,15 +73,15 @@
 
 	if (mangle->flags & ~ARPT_MANGLE_MASK ||
 	    !(mangle->flags & ARPT_MANGLE_MASK))
-		return 0;
+		return false;
 
 	if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
 	   mangle->target != ARPT_CONTINUE)
-		return 0;
-	return 1;
+		return false;
+	return true;
 }
 
-static struct arpt_target arpt_mangle_reg = {
+static struct arpt_target arpt_mangle_reg __read_mostly = {
 	.name		= "mangle",
 	.target		= target,
 	.targetsize	= sizeof(struct arpt_mangle),
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index e3f83bf..e1b402c 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -152,20 +152,20 @@
 	return 1;
 }
 
-static inline int
+static inline bool
 ip_checkentry(const struct ipt_ip *ip)
 {
 	if (ip->flags & ~IPT_F_MASK) {
 		duprintf("Unknown flag bits set: %08X\n",
 			 ip->flags & ~IPT_F_MASK);
-		return 0;
+		return false;
 	}
 	if (ip->invflags & ~IPT_INV_MASK) {
 		duprintf("Unknown invflag bits set: %08X\n",
 			 ip->invflags & ~IPT_INV_MASK);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -183,19 +183,19 @@
 }
 
 static inline
-int do_match(struct ipt_entry_match *m,
-	     const struct sk_buff *skb,
-	     const struct net_device *in,
-	     const struct net_device *out,
-	     int offset,
-	     int *hotdrop)
+bool do_match(struct ipt_entry_match *m,
+	      const struct sk_buff *skb,
+	      const struct net_device *in,
+	      const struct net_device *out,
+	      int offset,
+	      bool *hotdrop)
 {
 	/* Stop iteration if it doesn't match */
 	if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
 				      offset, ip_hdrlen(skb), hotdrop))
-		return 1;
+		return true;
 	else
-		return 0;
+		return false;
 }
 
 static inline struct ipt_entry *
@@ -204,6 +204,112 @@
 	return (struct ipt_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ipt_ip *ip)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
+		if (((__u32 *)ip)[i])
+			return 0;
+
+	return 1;
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+static const char *hooknames[] = {
+	[NF_IP_PRE_ROUTING]		= "PREROUTING",
+	[NF_IP_LOCAL_IN]		= "INPUT",
+	[NF_IP_FORWARD]			= "FORWARD",
+	[NF_IP_LOCAL_OUT]		= "OUTPUT",
+	[NF_IP_POST_ROUTING]		= "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP_TRACE_COMMENT_RULE,
+	NF_IP_TRACE_COMMENT_RETURN,
+	NF_IP_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP_TRACE_COMMENT_RULE]	= "rule",
+	[NF_IP_TRACE_COMMENT_RETURN]	= "return",
+	[NF_IP_TRACE_COMMENT_POLICY]	= "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ipt_standard_target *t = (void *)ipt_get_target(s);
+
+	if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ipt_entry)
+		   && strcmp(t->target.u.kernel.target->name,
+			     IPT_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+		   && unconditional(&s->ip)) {
+			/* Tail of chains: STANDARD target (return/policy) */
+			*comment = *chainname == hookname
+				? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
+				: (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+			 unsigned int hook,
+			 const struct net_device *in,
+			 const struct net_device *out,
+			 char *tablename,
+			 struct xt_table_info *private,
+			 struct ipt_entry *e)
+{
+	void *table_base;
+	struct ipt_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
+
+	IPT_ENTRY_ITERATE(root,
+			  private->size - private->hook_entry[hook],
+			  get_chainname_rulenum,
+			  e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ipt_do_table(struct sk_buff **pskb,
@@ -216,7 +322,7 @@
 	u_int16_t offset;
 	struct iphdr *ip;
 	u_int16_t datalen;
-	int hotdrop = 0;
+	bool hotdrop = false;
 	/* Initializing verdict to NF_DROP keeps gcc happy. */
 	unsigned int verdict = NF_DROP;
 	const char *indev, *outdev;
@@ -261,6 +367,14 @@
 
 			t = ipt_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+			/* The packet is traced: log it */
+			if (unlikely((*pskb)->nf_trace))
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+#endif
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -341,19 +455,6 @@
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ipt_ip *ip)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
-		if (((__u32 *)ip)[i])
-			return 0;
-
-	return 1;
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
@@ -499,7 +600,8 @@
 }
 
 static inline int check_match(struct ipt_entry_match *m, const char *name,
-				const struct ipt_ip *ip, unsigned int hookmask)
+				const struct ipt_ip *ip, unsigned int hookmask,
+				unsigned int *i)
 {
 	struct xt_match *match;
 	int ret;
@@ -515,6 +617,8 @@
 			 m->u.kernel.match->name);
 		ret = -EINVAL;
 	}
+	if (!ret)
+		(*i)++;
 	return ret;
 }
 
@@ -537,11 +641,10 @@
 	}
 	m->u.kernel.match = match;
 
-	ret = check_match(m, name, ip, hookmask);
+	ret = check_match(m, name, ip, hookmask, i);
 	if (ret)
 		goto err;
 
-	(*i)++;
 	return 0;
 err:
 	module_put(m->u.kernel.match->me);
@@ -1425,7 +1528,7 @@
 }
 
 static inline int
-compat_check_calc_match(struct ipt_entry_match *m,
+compat_find_calc_match(struct ipt_entry_match *m,
 	    const char *name,
 	    const struct ipt_ip *ip,
 	    unsigned int hookmask,
@@ -1449,6 +1552,31 @@
 }
 
 static inline int
+compat_release_match(struct ipt_entry_match *m, unsigned int *i)
+{
+	if (i && (*i)-- == 0)
+		return 1;
+
+	module_put(m->u.kernel.match->me);
+	return 0;
+}
+
+static inline int
+compat_release_entry(struct ipt_entry *e, unsigned int *i)
+{
+	struct ipt_entry_target *t;
+
+	if (i && (*i)-- == 0)
+		return 1;
+
+	/* Cleanup all matches */
+	IPT_MATCH_ITERATE(e, compat_release_match, NULL);
+	t = ipt_get_target(e);
+	module_put(t->u.kernel.target->me);
+	return 0;
+}
+
+static inline int
 check_compat_entry_size_and_hooks(struct ipt_entry *e,
 			   struct xt_table_info *newinfo,
 			   unsigned int *size,
@@ -1485,10 +1613,10 @@
 	off = 0;
 	entry_offset = (void *)e - (void *)base;
 	j = 0;
-	ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
+	ret = IPT_MATCH_ITERATE(e, compat_find_calc_match, name, &e->ip,
 			e->comefrom, &off, &j);
 	if (ret != 0)
-		goto cleanup_matches;
+		goto release_matches;
 
 	t = ipt_get_target(e);
 	target = try_then_request_module(xt_find_target(AF_INET,
@@ -1499,7 +1627,7 @@
 		duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
 							t->u.user.name);
 		ret = target ? PTR_ERR(target) : -ENOENT;
-		goto cleanup_matches;
+		goto release_matches;
 	}
 	t->u.kernel.target = target;
 
@@ -1526,8 +1654,8 @@
 
 out:
 	module_put(t->u.kernel.target->me);
-cleanup_matches:
-	IPT_MATCH_ITERATE(e, cleanup_match, &j);
+release_matches:
+	IPT_MATCH_ITERATE(e, compat_release_match, &j);
 	return ret;
 }
 
@@ -1574,15 +1702,26 @@
 	return ret;
 }
 
-static inline int compat_check_entry(struct ipt_entry *e, const char *name)
+static inline int compat_check_entry(struct ipt_entry *e, const char *name,
+						unsigned int *i)
 {
-	int ret;
+	int j, ret;
 
-	ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom);
+	j = 0;
+	ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
 	if (ret)
-		return ret;
+		goto cleanup_matches;
 
-	return check_target(e, name);
+	ret = check_target(e, name);
+	if (ret)
+		goto cleanup_matches;
+
+	(*i)++;
+	return 0;
+
+ cleanup_matches:
+	IPT_MATCH_ITERATE(e, cleanup_match, &j);
+	return ret;
 }
 
 static int
@@ -1673,10 +1812,17 @@
 	if (!mark_source_chains(newinfo, valid_hooks, entry1))
 		goto free_newinfo;
 
+	i = 0;
 	ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
-									name);
-	if (ret)
-		goto free_newinfo;
+								name, &i);
+	if (ret) {
+		j -= i;
+		IPT_ENTRY_ITERATE_CONTINUE(entry1, newinfo->size, i,
+						compat_release_entry, &j);
+		IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
+		xt_free_table_info(newinfo);
+		return ret;
+	}
 
 	/* And one copy for every other CPU */
 	for_each_possible_cpu(i)
@@ -1691,7 +1837,7 @@
 free_newinfo:
 	xt_free_table_info(newinfo);
 out:
-	IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j);
+	IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
 	return ret;
 out_unlock:
 	compat_flush_offsets();
@@ -2060,16 +2206,16 @@
 }
 
 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
-static inline int
+static inline bool
 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
 		     u_int8_t type, u_int8_t code,
-		     int invert)
+		     bool invert)
 {
 	return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
 		^ invert;
 }
 
-static int
+static bool
 icmp_match(const struct sk_buff *skb,
 	   const struct net_device *in,
 	   const struct net_device *out,
@@ -2077,14 +2223,14 @@
 	   const void *matchinfo,
 	   int offset,
 	   unsigned int protoff,
-	   int *hotdrop)
+	   bool *hotdrop)
 {
 	struct icmphdr _icmph, *ic;
 	const struct ipt_icmp *icmpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
 	if (ic == NULL) {
@@ -2092,8 +2238,8 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("Dropping evil ICMP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return icmp_type_code_match(icmpinfo->type,
@@ -2104,7 +2250,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 icmp_checkentry(const char *tablename,
 	   const void *info,
 	   const struct xt_match *match,
@@ -2118,7 +2264,7 @@
 }
 
 /* The built-in targets: standard (NULL) and error. */
-static struct xt_target ipt_standard_target = {
+static struct xt_target ipt_standard_target __read_mostly = {
 	.name		= IPT_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= AF_INET,
@@ -2129,7 +2275,7 @@
 #endif
 };
 
-static struct xt_target ipt_error_target = {
+static struct xt_target ipt_error_target __read_mostly = {
 	.name		= IPT_ERROR_TARGET,
 	.target		= ipt_error,
 	.targetsize	= IPT_FUNCTION_MAXNAMELEN,
@@ -2152,7 +2298,7 @@
 #endif
 };
 
-static struct xt_match icmp_matchstruct = {
+static struct xt_match icmp_matchstruct __read_mostly = {
 	.name		= "icmp",
 	.match		= icmp_match,
 	.matchsize	= sizeof(struct ipt_icmp),
@@ -2185,7 +2331,7 @@
 	if (ret < 0)
 		goto err5;
 
-	printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
+	printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
 	return 0;
 
 err5:
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 40e2734..dcc12b1 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -30,14 +30,6 @@
 
 #define CLUSTERIP_VERSION "0.8"
 
-#define DEBUG_CLUSTERIP
-
-#ifdef DEBUG_CLUSTERIP
-#define DEBUGP	printk
-#else
-#define DEBUGP
-#endif
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -122,9 +114,8 @@
 	list_for_each(pos, &clusterip_configs) {
 		struct clusterip_config *c = list_entry(pos,
 					struct clusterip_config, list);
-		if (c->clusterip == clusterip) {
+		if (c->clusterip == clusterip)
 			return c;
-		}
 	}
 
 	return NULL;
@@ -155,9 +146,8 @@
 {
 	int n;
 
-	for (n = 0; n < i->num_local_nodes; n++) {
+	for (n = 0; n < i->num_local_nodes; n++)
 		set_bit(i->local_nodes[n] - 1, &c->local_nodes);
-	}
 }
 
 static struct clusterip_config *
@@ -220,27 +210,28 @@
 	return 0;
 }
 
-static int
+static bool
 clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
 {
 	if (nodenum == 0 ||
 	    nodenum > c->num_total_nodes)
-		return 1;
+		return true;
 
 	if (test_and_clear_bit(nodenum - 1, &c->local_nodes))
-		return 0;
+		return false;
 
-	return 1;
+	return true;
 }
 #endif
 
 static inline u_int32_t
-clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
+clusterip_hashfn(const struct sk_buff *skb,
+		 const struct clusterip_config *config)
 {
-	struct iphdr *iph = ip_hdr(skb);
+	const struct iphdr *iph = ip_hdr(skb);
 	unsigned long hashval;
 	u_int16_t sport, dport;
-	u_int16_t *ports;
+	const u_int16_t *ports;
 
 	switch (iph->protocol) {
 	case IPPROTO_TCP:
@@ -249,15 +240,14 @@
 	case IPPROTO_SCTP:
 	case IPPROTO_DCCP:
 	case IPPROTO_ICMP:
-		ports = (void *)iph+iph->ihl*4;
+		ports = (const void *)iph+iph->ihl*4;
 		sport = ports[0];
 		dport = ports[1];
 		break;
 	default:
-		if (net_ratelimit()) {
+		if (net_ratelimit())
 			printk(KERN_NOTICE "CLUSTERIP: unknown protocol `%u'\n",
 				iph->protocol);
-		}
 		sport = dport = 0;
 	}
 
@@ -285,11 +275,11 @@
 	}
 
 	/* node numbers are 1..n, not 0..n */
-	return ((hashval % config->num_total_nodes)+1);
+	return (hashval % config->num_total_nodes) + 1;
 }
 
 static inline int
-clusterip_responsible(struct clusterip_config *config, u_int32_t hash)
+clusterip_responsible(const struct clusterip_config *config, u_int32_t hash)
 {
 	return test_bit(hash - 1, &config->local_nodes);
 }
@@ -353,15 +343,15 @@
 			break;
 	}
 
-#ifdef DEBUG_CLUSTERP
+#ifdef DEBUG
 	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 #endif
-	DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark);
+	pr_debug("hash=%u ct_hash=%u ", hash, ct->mark);
 	if (!clusterip_responsible(cipinfo->config, hash)) {
-		DEBUGP("not responsible\n");
+		pr_debug("not responsible\n");
 		return NF_DROP;
 	}
-	DEBUGP("responsible\n");
+	pr_debug("responsible\n");
 
 	/* despite being received via linklayer multicast, this is
 	 * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
@@ -370,7 +360,7 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
@@ -387,50 +377,34 @@
 	    cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
 		printk(KERN_WARNING "CLUSTERIP: unknown mode `%u'\n",
 			cipinfo->hash_mode);
-		return 0;
+		return false;
 
 	}
 	if (e->ip.dmsk.s_addr != htonl(0xffffffff)
 	    || e->ip.dst.s_addr == 0) {
 		printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n");
-		return 0;
+		return false;
 	}
 
 	/* FIXME: further sanity checks */
 
 	config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
-	if (config) {
-		if (cipinfo->config != NULL) {
-			/* Case A: This is an entry that gets reloaded, since
-			 * it still has a cipinfo->config pointer. Simply
-			 * increase the entry refcount and return */
-			if (cipinfo->config != config) {
-				printk(KERN_ERR "CLUSTERIP: Reloaded entry "
-				       "has invalid config pointer!\n");
-				return 0;
-			}
-		} else {
-			/* Case B: This is a new rule referring to an existing
-			 * clusterip config. */
-			cipinfo->config = config;
-		}
-	} else {
-		/* Case C: This is a completely new clusterip config */
+	if (!config) {
 		if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
 			printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
-			return 0;
+			return false;
 		} else {
 			struct net_device *dev;
 
 			if (e->ip.iniface[0] == '\0') {
 				printk(KERN_WARNING "CLUSTERIP: Please specify an interface name\n");
-				return 0;
+				return false;
 			}
 
 			dev = dev_get_by_name(e->ip.iniface);
 			if (!dev) {
 				printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface);
-				return 0;
+				return false;
 			}
 
 			config = clusterip_config_init(cipinfo,
@@ -438,20 +412,20 @@
 			if (!config) {
 				printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n");
 				dev_put(dev);
-				return 0;
+				return false;
 			}
 			dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
 		}
-		cipinfo->config = config;
 	}
+	cipinfo->config = config;
 
 	if (nf_ct_l3proto_try_module_get(target->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", target->family);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
 /* drop reference count of cluster config when rule is deleted */
@@ -468,13 +442,30 @@
 	nf_ct_l3proto_module_put(target->family);
 }
 
-static struct xt_target clusterip_tgt = {
+#ifdef CONFIG_COMPAT
+struct compat_ipt_clusterip_tgt_info
+{
+	u_int32_t	flags;
+	u_int8_t	clustermac[6];
+	u_int16_t	num_total_nodes;
+	u_int16_t	num_local_nodes;
+	u_int16_t	local_nodes[CLUSTERIP_MAX_NODES];
+	u_int32_t	hash_mode;
+	u_int32_t	hash_initval;
+	compat_uptr_t	config;
+};
+#endif /* CONFIG_COMPAT */
+
+static struct xt_target clusterip_tgt __read_mostly = {
 	.name		= "CLUSTERIP",
 	.family		= AF_INET,
 	.target		= target,
-	.targetsize	= sizeof(struct ipt_clusterip_tgt_info),
 	.checkentry	= checkentry,
 	.destroy	= destroy,
+	.targetsize	= sizeof(struct ipt_clusterip_tgt_info),
+#ifdef CONFIG_COMPAT
+	.compatsize	= sizeof(struct compat_ipt_clusterip_tgt_info),
+#endif /* CONFIG_COMPAT */
 	.me		= THIS_MODULE
 };
 
@@ -491,7 +482,7 @@
 	__be32 dst_ip;
 } __attribute__ ((packed));
 
-#ifdef CLUSTERIP_DEBUG
+#ifdef DEBUG
 static void arp_print(struct arp_payload *payload)
 {
 #define HBUFFERLEN 30
@@ -547,8 +538,9 @@
 	 * this wouldn't work, since we didn't subscribe the mcast group on
 	 * other interfaces */
 	if (c->dev != out) {
-		DEBUGP("CLUSTERIP: not mangling arp reply on different "
-		       "interface: cip'%s'-skb'%s'\n", c->dev->name, out->name);
+		pr_debug("CLUSTERIP: not mangling arp reply on different "
+			 "interface: cip'%s'-skb'%s'\n",
+			 c->dev->name, out->name);
 		clusterip_config_put(c);
 		return NF_ACCEPT;
 	}
@@ -556,8 +548,8 @@
 	/* mangle reply hardware address */
 	memcpy(payload->src_hw, c->clustermac, arp->ar_hln);
 
-#ifdef CLUSTERIP_DEBUG
-	DEBUGP(KERN_DEBUG "CLUSTERIP mangled arp reply: ");
+#ifdef DEBUG
+	pr_debug(KERN_DEBUG "CLUSTERIP mangled arp reply: ");
 	arp_print(payload);
 #endif
 
@@ -647,7 +639,7 @@
 	return 0;
 }
 
-static struct seq_operations clusterip_seq_ops = {
+static const struct seq_operations clusterip_seq_ops = {
 	.start	= clusterip_seq_start,
 	.next	= clusterip_seq_next,
 	.stop	= clusterip_seq_stop,
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 918ca92..f1253bd 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -24,8 +24,8 @@
 MODULE_DESCRIPTION("iptables ECN modification module");
 
 /* set ECT codepoint from IP header.
- * 	return 0 if there was an error. */
-static inline int
+ * 	return false if there was an error. */
+static inline bool
 set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
 	struct iphdr *iph = ip_hdr(*pskb);
@@ -33,18 +33,18 @@
 	if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
 		__u8 oldtos;
 		if (!skb_make_writable(pskb, sizeof(struct iphdr)))
-			return 0;
+			return false;
 		iph = ip_hdr(*pskb);
 		oldtos = iph->tos;
 		iph->tos &= ~IPT_ECN_IP_MASK;
 		iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
 		nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
 	}
-	return 1;
+	return true;
 }
 
-/* Return 0 if there was an error. */
-static inline int
+/* Return false if there was an error. */
+static inline bool
 set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
 	struct tcphdr _tcph, *tcph;
@@ -54,16 +54,16 @@
 	tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
 				  sizeof(_tcph), &_tcph);
 	if (!tcph)
-		return 0;
+		return false;
 
 	if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) ||
 	     tcph->ece == einfo->proto.tcp.ece) &&
-	    ((!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
-	     tcph->cwr == einfo->proto.tcp.cwr)))
-		return 1;
+	    (!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
+	     tcph->cwr == einfo->proto.tcp.cwr))
+		return true;
 
 	if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
-		return 0;
+		return false;
 	tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb);
 
 	oldval = ((__be16 *)tcph)[6];
@@ -74,7 +74,7 @@
 
 	nf_proto_csum_replace2(&tcph->check, *pskb,
 				oldval, ((__be16 *)tcph)[6], 0);
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -99,7 +99,7 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
@@ -112,23 +112,23 @@
 	if (einfo->operation & IPT_ECN_OP_MASK) {
 		printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
 			einfo->operation);
-		return 0;
+		return false;
 	}
 	if (einfo->ip_ect & ~IPT_ECN_IP_MASK) {
 		printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n",
 			einfo->ip_ect);
-		return 0;
+		return false;
 	}
 	if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
 	    && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) {
 		printk(KERN_WARNING "ECN: cannot use TCP operations on a "
 		       "non-tcp rule\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ipt_ecn_reg = {
+static struct xt_target ipt_ecn_reg __read_mostly = {
 	.name		= "ECN",
 	.family		= AF_INET,
 	.target		= target,
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index a42c5cd..5937ad1 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -27,12 +27,6 @@
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables syslog logging module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Use lock to serialize, so printks don't overlap */
 static DEFINE_SPINLOCK(log_lock);
 
@@ -41,7 +35,8 @@
 			const struct sk_buff *skb,
 			unsigned int iphoff)
 {
-	struct iphdr _iph, *ih;
+	struct iphdr _iph;
+	const struct iphdr *ih;
 	unsigned int logflags;
 
 	if (info->type == NF_LOG_TYPE_LOG)
@@ -100,7 +95,8 @@
 
 	switch (ih->protocol) {
 	case IPPROTO_TCP: {
-		struct tcphdr _tcph, *th;
+		struct tcphdr _tcph;
+		const struct tcphdr *th;
 
 		/* Max length: 10 "PROTO=TCP " */
 		printk("PROTO=TCP ");
@@ -151,7 +147,7 @@
 		if ((logflags & IPT_LOG_TCPOPT)
 		    && th->doff * 4 > sizeof(struct tcphdr)) {
 			unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
-			unsigned char *op;
+			const unsigned char *op;
 			unsigned int i, optsize;
 
 			optsize = th->doff * 4 - sizeof(struct tcphdr);
@@ -173,7 +169,8 @@
 	}
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE: {
-		struct udphdr _udph, *uh;
+		struct udphdr _udph;
+		const struct udphdr *uh;
 
 		if (ih->protocol == IPPROTO_UDP)
 			/* Max length: 10 "PROTO=UDP "     */
@@ -200,7 +197,8 @@
 		break;
 	}
 	case IPPROTO_ICMP: {
-		struct icmphdr _icmph, *ich;
+		struct icmphdr _icmph;
+		const struct icmphdr *ich;
 		static const size_t required_len[NR_ICMP_TYPES+1]
 			= { [ICMP_ECHOREPLY] = 4,
 			    [ICMP_DEST_UNREACH]
@@ -285,7 +283,8 @@
 	}
 	/* Max Length */
 	case IPPROTO_AH: {
-		struct ip_auth_hdr _ahdr, *ah;
+		struct ip_auth_hdr _ahdr;
+		const struct ip_auth_hdr *ah;
 
 		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
@@ -307,7 +306,8 @@
 		break;
 	}
 	case IPPROTO_ESP: {
-		struct ip_esp_hdr _esph, *eh;
+		struct ip_esp_hdr _esph;
+		const struct ip_esp_hdr *eh;
 
 		/* Max length: 10 "PROTO=ESP " */
 		printk("PROTO=ESP ");
@@ -385,11 +385,13 @@
 	       out ? out->name : "");
 #ifdef CONFIG_BRIDGE_NETFILTER
 	if (skb->nf_bridge) {
-		struct net_device *physindev = skb->nf_bridge->physindev;
-		struct net_device *physoutdev = skb->nf_bridge->physoutdev;
+		const struct net_device *physindev;
+		const struct net_device *physoutdev;
 
+		physindev = skb->nf_bridge->physindev;
 		if (physindev && in != physindev)
 			printk("PHYSIN=%s ", physindev->name);
+		physoutdev = skb->nf_bridge->physoutdev;
 		if (physoutdev && out != physoutdev)
 			printk("PHYSOUT=%s ", physoutdev->name);
 	}
@@ -435,27 +437,27 @@
 	return XT_CONTINUE;
 }
 
-static int ipt_log_checkentry(const char *tablename,
-			      const void *e,
-			      const struct xt_target *target,
-			      void *targinfo,
-			      unsigned int hook_mask)
+static bool ipt_log_checkentry(const char *tablename,
+			       const void *e,
+			       const struct xt_target *target,
+			       void *targinfo,
+			       unsigned int hook_mask)
 {
 	const struct ipt_log_info *loginfo = targinfo;
 
 	if (loginfo->level >= 8) {
-		DEBUGP("LOG: level %u >= 8\n", loginfo->level);
-		return 0;
+		pr_debug("LOG: level %u >= 8\n", loginfo->level);
+		return false;
 	}
 	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
-		DEBUGP("LOG: prefix term %i\n",
-		       loginfo->prefix[sizeof(loginfo->prefix)-1]);
-		return 0;
+		pr_debug("LOG: prefix term %i\n",
+			 loginfo->prefix[sizeof(loginfo->prefix)-1]);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ipt_log_reg = {
+static struct xt_target ipt_log_reg __read_mostly = {
 	.name		= "LOG",
 	.family		= AF_INET,
 	.target		= ipt_log_target,
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index d4f2d77..7c4e4be 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -27,17 +27,11 @@
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables MASQUERADE target module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Lock protects masq region inside conntrack */
 static DEFINE_RWLOCK(masq_lock);
 
 /* FIXME: Multiple targets. --RR */
-static int
+static bool
 masquerade_check(const char *tablename,
 		 const void *e,
 		 const struct xt_target *target,
@@ -47,14 +41,14 @@
 	const struct nf_nat_multi_range_compat *mr = targinfo;
 
 	if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
-		DEBUGP("masquerade_check: bad MAP_IPS.\n");
-		return 0;
+		pr_debug("masquerade_check: bad MAP_IPS.\n");
+		return false;
 	}
 	if (mr->rangesize != 1) {
-		DEBUGP("masquerade_check: bad rangesize %u.\n", mr->rangesize);
-		return 0;
+		pr_debug("masquerade_check: bad rangesize %u\n", mr->rangesize);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -70,7 +64,7 @@
 	enum ip_conntrack_info ctinfo;
 	struct nf_nat_range newrange;
 	const struct nf_nat_multi_range_compat *mr;
-	struct rtable *rt;
+	const struct rtable *rt;
 	__be32 newsrc;
 
 	NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
@@ -109,10 +103,10 @@
 	return nf_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static inline int
+static int
 device_cmp(struct nf_conn *i, void *ifindex)
 {
-	struct nf_conn_nat *nat = nfct_nat(i);
+	const struct nf_conn_nat *nat = nfct_nat(i);
 	int ret;
 
 	if (!nat)
@@ -129,7 +123,7 @@
 			     unsigned long event,
 			     void *ptr)
 {
-	struct net_device *dev = ptr;
+	const struct net_device *dev = ptr;
 
 	if (event == NETDEV_DOWN) {
 		/* Device was downed.  Search entire table for
@@ -147,7 +141,7 @@
 			   unsigned long event,
 			   void *ptr)
 {
-	struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
+	const struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
 
 	if (event == NETDEV_DOWN) {
 		/* IP address was deleted.  Search entire table for
@@ -169,7 +163,7 @@
 	.notifier_call	= masq_inet_event,
 };
 
-static struct xt_target masquerade = {
+static struct xt_target masquerade __read_mostly = {
 	.name		= "MASQUERADE",
 	.family		= AF_INET,
 	.target		= masquerade_target,
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 068c69b..41a011d 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -18,18 +18,11 @@
 #include <linux/netfilter/x_tables.h>
 #include <net/netfilter/nf_nat_rule.h>
 
-#define MODULENAME "NETMAP"
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
 MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
 check(const char *tablename,
       const void *e,
       const struct xt_target *target,
@@ -39,14 +32,14 @@
 	const struct nf_nat_multi_range_compat *mr = targinfo;
 
 	if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
-		DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
-		return 0;
+		pr_debug("NETMAP:check: bad MAP_IPS.\n");
+		return false;
 	}
 	if (mr->rangesize != 1) {
-		DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize);
-		return 0;
+		pr_debug("NETMAP:check: bad rangesize %u.\n", mr->rangesize);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -85,8 +78,8 @@
 	return nf_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct xt_target target_module = {
-	.name 		= MODULENAME,
+static struct xt_target target_module __read_mostly = {
+	.name 		= "NETMAP",
 	.family		= AF_INET,
 	.target 	= target,
 	.targetsize	= sizeof(struct nf_nat_multi_range_compat),
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 68cc76a1..6ac7a23 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -25,14 +25,8 @@
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables REDIRECT target module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* FIXME: Take multiple ranges --RR */
-static int
+static bool
 redirect_check(const char *tablename,
 	       const void *e,
 	       const struct xt_target *target,
@@ -42,14 +36,14 @@
 	const struct nf_nat_multi_range_compat *mr = targinfo;
 
 	if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
-		DEBUGP("redirect_check: bad MAP_IPS.\n");
-		return 0;
+		pr_debug("redirect_check: bad MAP_IPS.\n");
+		return false;
 	}
 	if (mr->rangesize != 1) {
-		DEBUGP("redirect_check: bad rangesize %u.\n", mr->rangesize);
-		return 0;
+		pr_debug("redirect_check: bad rangesize %u.\n", mr->rangesize);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -101,7 +95,7 @@
 	return nf_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct xt_target redirect_reg = {
+static struct xt_target redirect_reg __read_mostly = {
 	.name		= "REDIRECT",
 	.family		= AF_INET,
 	.target		= redirect_target,
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 9041e07..cb038c8 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -31,12 +31,6 @@
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables REJECT target module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Send RST reply */
 static void send_reset(struct sk_buff *oldskb, int hook)
 {
@@ -122,7 +116,7 @@
 	tcph->check = 0;
 	tcph->check = tcp_v4_check(sizeof(struct tcphdr),
 				   niph->saddr, niph->daddr,
-				   csum_partial((char *)tcph,
+				   csum_partial(tcph,
 						sizeof(struct tcphdr), 0));
 
 	/* Set DF, id = 0 */
@@ -217,30 +211,30 @@
 	return NF_DROP;
 }
 
-static int check(const char *tablename,
-		 const void *e_void,
-		 const struct xt_target *target,
-		 void *targinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *e_void,
+		  const struct xt_target *target,
+		  void *targinfo,
+		  unsigned int hook_mask)
 {
 	const struct ipt_reject_info *rejinfo = targinfo;
 	const struct ipt_entry *e = e_void;
 
 	if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
-		printk("REJECT: ECHOREPLY no longer supported.\n");
-		return 0;
+		printk("ipt_REJECT: ECHOREPLY no longer supported.\n");
+		return false;
 	} else if (rejinfo->with == IPT_TCP_RESET) {
 		/* Must specify that it's a TCP packet */
 		if (e->ip.proto != IPPROTO_TCP
 		    || (e->ip.invflags & XT_INV_PROTO)) {
-			DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
-			return 0;
+			printk("ipt_REJECT: TCP_RESET invalid for non-tcp\n");
+			return false;
 		}
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ipt_reject_reg = {
+static struct xt_target ipt_reject_reg __read_mostly = {
 	.name		= "REJECT",
 	.family		= AF_INET,
 	.target		= reject,
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 511e5ff..97641f1 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -27,13 +27,7 @@
 MODULE_AUTHOR("Martin Josefsson <gandalf@wlug.westbo.se>");
 MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
 same_check(const char *tablename,
 	      const void *e,
 	      const struct xt_target *target,
@@ -46,58 +40,56 @@
 	mr->ipnum = 0;
 
 	if (mr->rangesize < 1) {
-		DEBUGP("same_check: need at least one dest range.\n");
-		return 0;
+		pr_debug("same_check: need at least one dest range.\n");
+		return false;
 	}
 	if (mr->rangesize > IPT_SAME_MAX_RANGE) {
-		DEBUGP("same_check: too many ranges specified, maximum "
-				"is %u ranges\n",
-				IPT_SAME_MAX_RANGE);
-		return 0;
+		pr_debug("same_check: too many ranges specified, maximum "
+			 "is %u ranges\n", IPT_SAME_MAX_RANGE);
+		return false;
 	}
 	for (count = 0; count < mr->rangesize; count++) {
 		if (ntohl(mr->range[count].min_ip) >
 				ntohl(mr->range[count].max_ip)) {
-			DEBUGP("same_check: min_ip is larger than max_ip in "
-				"range `%u.%u.%u.%u-%u.%u.%u.%u'.\n",
-				NIPQUAD(mr->range[count].min_ip),
-				NIPQUAD(mr->range[count].max_ip));
-			return 0;
+			pr_debug("same_check: min_ip is larger than max_ip in "
+				 "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n",
+				 NIPQUAD(mr->range[count].min_ip),
+				 NIPQUAD(mr->range[count].max_ip));
+			return false;
 		}
 		if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) {
-			DEBUGP("same_check: bad MAP_IPS.\n");
-			return 0;
+			pr_debug("same_check: bad MAP_IPS.\n");
+			return false;
 		}
 		rangeip = (ntohl(mr->range[count].max_ip) -
 					ntohl(mr->range[count].min_ip) + 1);
 		mr->ipnum += rangeip;
 
-		DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip);
+		pr_debug("same_check: range %u, ipnum = %u\n", count, rangeip);
 	}
-	DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum);
+	pr_debug("same_check: total ipaddresses = %u\n", mr->ipnum);
 
 	mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL);
 	if (!mr->iparray) {
-		DEBUGP("same_check: Couldn't allocate %u bytes "
-			"for %u ipaddresses!\n",
-			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
-		return 0;
+		pr_debug("same_check: Couldn't allocate %Zu bytes "
+			 "for %u ipaddresses!\n",
+			 (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+		return false;
 	}
-	DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n",
-			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+	pr_debug("same_check: Allocated %Zu bytes for %u ipaddresses.\n",
+		 (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
 
 	for (count = 0; count < mr->rangesize; count++) {
 		for (countess = ntohl(mr->range[count].min_ip);
 				countess <= ntohl(mr->range[count].max_ip);
 					countess++) {
 			mr->iparray[index] = countess;
-			DEBUGP("same_check: Added ipaddress `%u.%u.%u.%u' "
-				"in index %u.\n",
-				HIPQUAD(countess), index);
+			pr_debug("same_check: Added ipaddress `%u.%u.%u.%u' "
+				 "in index %u.\n", HIPQUAD(countess), index);
 			index++;
 		}
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -107,8 +99,8 @@
 
 	kfree(mr->iparray);
 
-	DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n",
-			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+	pr_debug("same_destroy: Deallocated %Zu bytes for %u ipaddresses.\n",
+		 (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
 }
 
 static unsigned int
@@ -146,10 +138,9 @@
 
 	new_ip = htonl(same->iparray[aindex]);
 
-	DEBUGP("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, "
-			"new src=%u.%u.%u.%u\n",
-			NIPQUAD(t->src.ip), NIPQUAD(t->dst.ip),
-			NIPQUAD(new_ip));
+	pr_debug("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, "
+		 "new src=%u.%u.%u.%u\n",
+		 NIPQUAD(t->src.u3.ip), NIPQUAD(t->dst.u3.ip), NIPQUAD(new_ip));
 
 	/* Transfer from original range. */
 	newrange = ((struct nf_nat_range)
@@ -161,7 +152,7 @@
 	return nf_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct xt_target same_reg = {
+static struct xt_target same_reg __read_mostly = {
 	.name		= "SAME",
 	.family		= AF_INET,
 	.target		= same_target,
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 0ad02f2..25f5d0b 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -43,7 +43,7 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
@@ -58,12 +58,12 @@
 	    && tos != IPTOS_MINCOST
 	    && tos != IPTOS_NORMALSVC) {
 		printk(KERN_WARNING "TOS: bad tos value %#x\n", tos);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ipt_tos_reg = {
+static struct xt_target ipt_tos_reg __read_mostly = {
 	.name		= "TOS",
 	.family		= AF_INET,
 	.target		= target,
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index a991ec7..2b54e7b 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -62,25 +62,25 @@
 	return XT_CONTINUE;
 }
 
-static int ipt_ttl_checkentry(const char *tablename,
+static bool ipt_ttl_checkentry(const char *tablename,
 		const void *e,
 		const struct xt_target *target,
 		void *targinfo,
 		unsigned int hook_mask)
 {
-	struct ipt_TTL_info *info = targinfo;
+	const struct ipt_TTL_info *info = targinfo;
 
 	if (info->mode > IPT_TTL_MAXMODE) {
 		printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
 			info->mode);
-		return 0;
+		return false;
 	}
-	if ((info->mode != IPT_TTL_SET) && (info->ttl == 0))
-		return 0;
-	return 1;
+	if (info->mode != IPT_TTL_SET && info->ttl == 0)
+		return false;
+	return true;
 }
 
-static struct xt_target ipt_TTL = {
+static struct xt_target ipt_TTL __read_mostly = {
 	.name 		= "TTL",
 	.family		= AF_INET,
 	.target 	= ipt_ttl_target,
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 23b607b..6ca43e4 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -55,13 +55,6 @@
 #define ULOG_NL_EVENT		111		/* Harald's favorite number */
 #define ULOG_MAXNLGROUPS	32		/* numer of nlgroups */
 
-#if 0
-#define DEBUGP(format, args...) printk("%s:%s:" format, \
-				       __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
 
 static unsigned int nlbufsiz = NLMSG_GOODSIZE;
@@ -96,12 +89,12 @@
 	ulog_buff_t *ub = &ulog_buffers[nlgroupnum];
 
 	if (timer_pending(&ub->timer)) {
-		DEBUGP("ipt_ULOG: ulog_send: timer was pending, deleting\n");
+		pr_debug("ipt_ULOG: ulog_send: timer was pending, deleting\n");
 		del_timer(&ub->timer);
 	}
 
 	if (!ub->skb) {
-		DEBUGP("ipt_ULOG: ulog_send: nothing to send\n");
+		pr_debug("ipt_ULOG: ulog_send: nothing to send\n");
 		return;
 	}
 
@@ -110,8 +103,8 @@
 		ub->lastnlh->nlmsg_type = NLMSG_DONE;
 
 	NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1;
-	DEBUGP("ipt_ULOG: throwing %d packets to netlink group %u\n",
-		ub->qlen, nlgroupnum + 1);
+	pr_debug("ipt_ULOG: throwing %d packets to netlink group %u\n",
+		 ub->qlen, nlgroupnum + 1);
 	netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC);
 
 	ub->qlen = 0;
@@ -123,7 +116,7 @@
 /* timer function to flush queue in flushtimeout time */
 static void ulog_timer(unsigned long data)
 {
-	DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n");
+	pr_debug("ipt_ULOG: timer function called, calling ulog_send\n");
 
 	/* lock to protect against somebody modifying our structure
 	 * from ipt_ulog_target at the same time */
@@ -179,12 +172,10 @@
 	unsigned int groupnum = ffs(loginfo->nl_group) - 1;
 
 	/* calculate the size of the skb needed */
-	if ((loginfo->copy_range == 0) ||
-	    (loginfo->copy_range > skb->len)) {
+	if (loginfo->copy_range == 0 || loginfo->copy_range > skb->len)
 		copy_len = skb->len;
-	} else {
+	else
 		copy_len = loginfo->copy_range;
-	}
 
 	size = NLMSG_SPACE(sizeof(*pm) + copy_len);
 
@@ -206,8 +197,8 @@
 			goto alloc_failure;
 	}
 
-	DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen,
-		loginfo->qthreshold);
+	pr_debug("ipt_ULOG: qlen %d, qthreshold %Zu\n", ub->qlen,
+		 loginfo->qthreshold);
 
 	/* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
 	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT,
@@ -257,9 +248,8 @@
 		BUG();
 
 	/* check if we are building multi-part messages */
-	if (ub->qlen > 1) {
+	if (ub->qlen > 1)
 		ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
-	}
 
 	ub->lastnlh = nlh;
 
@@ -328,25 +318,25 @@
 	ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
 }
 
-static int ipt_ulog_checkentry(const char *tablename,
-			       const void *e,
-			       const struct xt_target *target,
-			       void *targinfo,
-			       unsigned int hookmask)
+static bool ipt_ulog_checkentry(const char *tablename,
+				const void *e,
+				const struct xt_target *target,
+				void *targinfo,
+				unsigned int hookmask)
 {
-	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
+	const struct ipt_ulog_info *loginfo = targinfo;
 
 	if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
-		DEBUGP("ipt_ULOG: prefix term %i\n",
-		       loginfo->prefix[sizeof(loginfo->prefix) - 1]);
-		return 0;
+		pr_debug("ipt_ULOG: prefix term %i\n",
+			 loginfo->prefix[sizeof(loginfo->prefix) - 1]);
+		return false;
 	}
 	if (loginfo->qthreshold > ULOG_MAX_QLEN) {
-		DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n",
-			loginfo->qthreshold);
-		return 0;
+		pr_debug("ipt_ULOG: queue threshold %Zu > MAX_QLEN\n",
+			 loginfo->qthreshold);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 #ifdef CONFIG_COMPAT
@@ -359,7 +349,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_ipt_ulog_info *cl = src;
+	const struct compat_ipt_ulog_info *cl = src;
 	struct ipt_ulog_info l = {
 		.nl_group	= cl->nl_group,
 		.copy_range	= cl->copy_range,
@@ -372,7 +362,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct ipt_ulog_info *l = src;
+	const struct ipt_ulog_info *l = src;
 	struct compat_ipt_ulog_info cl = {
 		.nl_group	= l->nl_group,
 		.copy_range	= l->copy_range,
@@ -384,7 +374,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_target ipt_ulog_reg = {
+static struct xt_target ipt_ulog_reg __read_mostly = {
 	.name		= "ULOG",
 	.family		= AF_INET,
 	.target		= ipt_ulog_target,
@@ -408,7 +398,7 @@
 {
 	int ret, i;
 
-	DEBUGP("ipt_ULOG: init module\n");
+	pr_debug("ipt_ULOG: init module\n");
 
 	if (nlbufsiz > 128*1024) {
 		printk("Netlink buffer has to be <= 128kB\n");
@@ -440,7 +430,7 @@
 	ulog_buff_t *ub;
 	int i;
 
-	DEBUGP("ipt_ULOG: cleanup_module\n");
+	pr_debug("ipt_ULOG: cleanup_module\n");
 
 	if (nflog)
 		nf_log_unregister(&ipt_ulog_logger);
@@ -451,7 +441,7 @@
 	for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
 		ub = &ulog_buffers[i];
 		if (timer_pending(&ub->timer)) {
-			DEBUGP("timer was pending, deleting\n");
+			pr_debug("timer was pending, deleting\n");
 			del_timer(&ub->timer);
 		}
 
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index a652a14..59f01f7 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -22,19 +22,19 @@
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_DESCRIPTION("iptables addrtype match");
 
-static inline int match_type(__be32 addr, u_int16_t mask)
+static inline bool match_type(__be32 addr, u_int16_t mask)
 {
 	return !!(mask & (1 << inet_addr_type(addr)));
 }
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in, const struct net_device *out,
-		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in, const struct net_device *out,
+		  const struct xt_match *match, const void *matchinfo,
+		  int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_addrtype_info *info = matchinfo;
 	const struct iphdr *iph = ip_hdr(skb);
-	int ret = 1;
+	bool ret = true;
 
 	if (info->source)
 		ret &= match_type(iph->saddr, info->source)^info->invert_source;
@@ -44,7 +44,7 @@
 	return ret;
 }
 
-static struct xt_match addrtype_match = {
+static struct xt_match addrtype_match __read_mostly = {
 	.name		= "addrtype",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 18a1678..61b017f 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -25,10 +25,10 @@
 #endif
 
 /* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
 {
-	int r=0;
+	bool r;
 	duprintf("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
 		min,spi,max);
 	r=(spi >= min && spi <= max) ^ invert;
@@ -36,7 +36,7 @@
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -44,14 +44,15 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct ip_auth_hdr _ahdr, *ah;
+	struct ip_auth_hdr _ahdr;
+	const struct ip_auth_hdr *ah;
 	const struct ipt_ah *ahinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	ah = skb_header_pointer(skb, protoff,
 				sizeof(_ahdr), &_ahdr);
@@ -60,7 +61,7 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("Dropping evil AH tinygram.\n");
-		*hotdrop = 1;
+		*hotdrop = true;
 		return 0;
 	}
 
@@ -70,7 +71,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip_void,
 	   const struct xt_match *match,
@@ -82,12 +83,12 @@
 	/* Must specify no unknown invflags */
 	if (ahinfo->invflags & ~IPT_AH_INV_MASK) {
 		duprintf("ipt_ah: unknown flags %X\n", ahinfo->invflags);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match ah_match = {
+static struct xt_match ah_match __read_mostly = {
 	.name		= "ah",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index 2621812..d6925c6 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -22,95 +22,96 @@
 MODULE_DESCRIPTION("iptables ECN matching module");
 MODULE_LICENSE("GPL");
 
-static inline int match_ip(const struct sk_buff *skb,
-			   const struct ipt_ecn_info *einfo)
+static inline bool match_ip(const struct sk_buff *skb,
+			    const struct ipt_ecn_info *einfo)
 {
 	return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect;
 }
 
-static inline int match_tcp(const struct sk_buff *skb,
-			    const struct ipt_ecn_info *einfo,
-			    int *hotdrop)
+static inline bool match_tcp(const struct sk_buff *skb,
+			     const struct ipt_ecn_info *einfo,
+			     bool *hotdrop)
 {
-	struct tcphdr _tcph, *th;
+	struct tcphdr _tcph;
+	const struct tcphdr *th;
 
 	/* In practice, TCP match does this, so can't fail.  But let's
 	 * be good citizens.
 	 */
 	th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
 	if (th == NULL) {
-		*hotdrop = 0;
-		return 0;
+		*hotdrop = false;
+		return false;
 	}
 
 	if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
 		if (einfo->invert & IPT_ECN_OP_MATCH_ECE) {
 			if (th->ece == 1)
-				return 0;
+				return false;
 		} else {
 			if (th->ece == 0)
-				return 0;
+				return false;
 		}
 	}
 
 	if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
 		if (einfo->invert & IPT_ECN_OP_MATCH_CWR) {
 			if (th->cwr == 1)
-				return 0;
+				return false;
 		} else {
 			if (th->cwr == 0)
-				return 0;
+				return false;
 		}
 	}
 
-	return 1;
+	return true;
 }
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in, const struct net_device *out,
-		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in, const struct net_device *out,
+		  const struct xt_match *match, const void *matchinfo,
+		  int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_ecn_info *info = matchinfo;
 
 	if (info->operation & IPT_ECN_OP_MATCH_IP)
 		if (!match_ip(skb, info))
-			return 0;
+			return false;
 
 	if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
 		if (ip_hdr(skb)->protocol != IPPROTO_TCP)
-			return 0;
+			return false;
 		if (!match_tcp(skb, info, hotdrop))
-			return 0;
+			return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static int checkentry(const char *tablename, const void *ip_void,
-		      const struct xt_match *match,
-		      void *matchinfo, unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *ip_void,
+		       const struct xt_match *match,
+		       void *matchinfo, unsigned int hook_mask)
 {
 	const struct ipt_ecn_info *info = matchinfo;
 	const struct ipt_ip *ip = ip_void;
 
 	if (info->operation & IPT_ECN_OP_MATCH_MASK)
-		return 0;
+		return false;
 
 	if (info->invert & IPT_ECN_OP_MATCH_MASK)
-		return 0;
+		return false;
 
 	if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)
 	    && ip->proto != IPPROTO_TCP) {
 		printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for"
 		       " non-tcp packets\n");
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static struct xt_match ecn_match = {
+static struct xt_match ecn_match __read_mostly = {
 	.name		= "ecn",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index 33af9e9..0106dc9 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -17,53 +17,47 @@
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 MODULE_DESCRIPTION("iptables arbitrary IP range match module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
       const struct xt_match *match,
       const void *matchinfo,
-      int offset, unsigned int protoff, int *hotdrop)
+      int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_iprange_info *info = matchinfo;
 	const struct iphdr *iph = ip_hdr(skb);
 
 	if (info->flags & IPRANGE_SRC) {
-		if (((ntohl(iph->saddr) < ntohl(info->src.min_ip))
-			  || (ntohl(iph->saddr) > ntohl(info->src.max_ip)))
+		if ((ntohl(iph->saddr) < ntohl(info->src.min_ip)
+			  || ntohl(iph->saddr) > ntohl(info->src.max_ip))
 			 ^ !!(info->flags & IPRANGE_SRC_INV)) {
-			DEBUGP("src IP %u.%u.%u.%u NOT in range %s"
-			       "%u.%u.%u.%u-%u.%u.%u.%u\n",
-				NIPQUAD(iph->saddr),
-				info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
-				NIPQUAD(info->src.min_ip),
-				NIPQUAD(info->src.max_ip));
-			return 0;
+			pr_debug("src IP %u.%u.%u.%u NOT in range %s"
+				 "%u.%u.%u.%u-%u.%u.%u.%u\n",
+				 NIPQUAD(iph->saddr),
+				 info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
+				 NIPQUAD(info->src.min_ip),
+				 NIPQUAD(info->src.max_ip));
+			return false;
 		}
 	}
 	if (info->flags & IPRANGE_DST) {
-		if (((ntohl(iph->daddr) < ntohl(info->dst.min_ip))
-			  || (ntohl(iph->daddr) > ntohl(info->dst.max_ip)))
+		if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip)
+			  || ntohl(iph->daddr) > ntohl(info->dst.max_ip))
 			 ^ !!(info->flags & IPRANGE_DST_INV)) {
-			DEBUGP("dst IP %u.%u.%u.%u NOT in range %s"
-			       "%u.%u.%u.%u-%u.%u.%u.%u\n",
-				NIPQUAD(iph->daddr),
-				info->flags & IPRANGE_DST_INV ? "(INV) " : "",
-				NIPQUAD(info->dst.min_ip),
-				NIPQUAD(info->dst.max_ip));
-			return 0;
+			pr_debug("dst IP %u.%u.%u.%u NOT in range %s"
+				 "%u.%u.%u.%u-%u.%u.%u.%u\n",
+				 NIPQUAD(iph->daddr),
+				 info->flags & IPRANGE_DST_INV ? "(INV) " : "",
+				 NIPQUAD(info->dst.min_ip),
+				 NIPQUAD(info->dst.max_ip));
+			return false;
 		}
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match iprange_match = {
+static struct xt_match iprange_match __read_mostly = {
 	.name		= "iprange",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 7fae9aa..b14e77d 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -21,7 +21,7 @@
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
 MODULE_DESCRIPTION("iptables owner match");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -29,29 +29,29 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct ipt_owner_info *info = matchinfo;
 
 	if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
-		return 0;
+		return false;
 
 	if(info->match & IPT_OWNER_UID) {
 		if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
 		    !!(info->invert & IPT_OWNER_UID))
-			return 0;
+			return false;
 	}
 
 	if(info->match & IPT_OWNER_GID) {
 		if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
 		    !!(info->invert & IPT_OWNER_GID))
-			return 0;
+			return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
@@ -63,12 +63,12 @@
 	if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) {
 		printk("ipt_owner: pid, sid and command matching "
 		       "not supported anymore\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match owner_match = {
+static struct xt_match owner_match __read_mostly = {
 	.name		= "owner",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 15a9e8b..3218043 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -163,24 +163,23 @@
 	struct recent_entry *e, *next;
 	unsigned int i;
 
-	for (i = 0; i < ip_list_hash_size; i++) {
+	for (i = 0; i < ip_list_hash_size; i++)
 		list_for_each_entry_safe(e, next, &t->iphash[i], list)
 			recent_entry_remove(t, e);
-	}
 }
 
-static int
+static bool
 ipt_recent_match(const struct sk_buff *skb,
 		 const struct net_device *in, const struct net_device *out,
 		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+		 int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_recent_info *info = matchinfo;
 	struct recent_table *t;
 	struct recent_entry *e;
 	__be32 addr;
 	u_int8_t ttl;
-	int ret = info->invert;
+	bool ret = info->invert;
 
 	if (info->side == IPT_RECENT_DEST)
 		addr = ip_hdr(skb)->daddr;
@@ -201,16 +200,16 @@
 			goto out;
 		e = recent_entry_init(t, addr, ttl);
 		if (e == NULL)
-			*hotdrop = 1;
-		ret ^= 1;
+			*hotdrop = true;
+		ret = !ret;
 		goto out;
 	}
 
 	if (info->check_set & IPT_RECENT_SET)
-		ret ^= 1;
+		ret = !ret;
 	else if (info->check_set & IPT_RECENT_REMOVE) {
 		recent_entry_remove(t, e);
-		ret ^= 1;
+		ret = !ret;
 	} else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) {
 		unsigned long t = jiffies - info->seconds * HZ;
 		unsigned int i, hits = 0;
@@ -219,7 +218,7 @@
 			if (info->seconds && time_after(t, e->stamps[i]))
 				continue;
 			if (++hits >= info->hit_count) {
-				ret ^= 1;
+				ret = !ret;
 				break;
 			}
 		}
@@ -235,7 +234,7 @@
 	return ret;
 }
 
-static int
+static bool
 ipt_recent_checkentry(const char *tablename, const void *ip,
 		      const struct xt_match *match, void *matchinfo,
 		      unsigned int hook_mask)
@@ -243,24 +242,24 @@
 	const struct ipt_recent_info *info = matchinfo;
 	struct recent_table *t;
 	unsigned i;
-	int ret = 0;
+	bool ret = false;
 
 	if (hweight8(info->check_set &
 		     (IPT_RECENT_SET | IPT_RECENT_REMOVE |
 		      IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1)
-		return 0;
+		return false;
 	if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) &&
 	    (info->seconds || info->hit_count))
-		return 0;
+		return false;
 	if (info->name[0] == '\0' ||
 	    strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
-		return 0;
+		return false;
 
 	mutex_lock(&recent_mutex);
 	t = recent_table_lookup(info->name);
 	if (t != NULL) {
 		t->refcnt++;
-		ret = 1;
+		ret = true;
 		goto out;
 	}
 
@@ -287,7 +286,7 @@
 	spin_lock_bh(&recent_lock);
 	list_add_tail(&t->list, &tables);
 	spin_unlock_bh(&recent_lock);
-	ret = 1;
+	ret = true;
 out:
 	mutex_unlock(&recent_mutex);
 	return ret;
@@ -323,18 +322,16 @@
 static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	struct recent_iter_state *st = seq->private;
-	struct recent_table *t = st->table;
+	const struct recent_table *t = st->table;
 	struct recent_entry *e;
 	loff_t p = *pos;
 
 	spin_lock_bh(&recent_lock);
 
-	for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++) {
-		list_for_each_entry(e, &t->iphash[st->bucket], list) {
+	for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++)
+		list_for_each_entry(e, &t->iphash[st->bucket], list)
 			if (p-- == 0)
 				return e;
-		}
-	}
 	return NULL;
 }
 
@@ -373,7 +370,7 @@
 	return 0;
 }
 
-static struct seq_operations recent_seq_ops = {
+static const struct seq_operations recent_seq_ops = {
 	.start		= recent_seq_start,
 	.next		= recent_seq_next,
 	.stop		= recent_seq_stop,
@@ -463,7 +460,7 @@
 };
 #endif /* CONFIG_PROC_FS */
 
-static struct xt_match recent_match = {
+static struct xt_match recent_match __read_mostly = {
 	.name		= "recent",
 	.family		= AF_INET,
 	.match		= ipt_recent_match,
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index d314844..e740441 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -18,7 +18,7 @@
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("iptables TOS match module");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -26,14 +26,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct ipt_tos_info *info = matchinfo;
 
 	return (ip_hdr(skb)->tos == info->tos) ^ info->invert;
 }
 
-static struct xt_match tos_match = {
+static struct xt_match tos_match __read_mostly = {
 	.name		= "tos",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index ab02d9e..a439900 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -18,37 +18,33 @@
 MODULE_DESCRIPTION("IP tables TTL matching module");
 MODULE_LICENSE("GPL");
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in, const struct net_device *out,
-		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in, const struct net_device *out,
+		  const struct xt_match *match, const void *matchinfo,
+		  int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_ttl_info *info = matchinfo;
 	const u8 ttl = ip_hdr(skb)->ttl;
 
 	switch (info->mode) {
 		case IPT_TTL_EQ:
-			return (ttl == info->ttl);
-			break;
+			return ttl == info->ttl;
 		case IPT_TTL_NE:
-			return (!(ttl == info->ttl));
-			break;
+			return ttl != info->ttl;
 		case IPT_TTL_LT:
-			return (ttl < info->ttl);
-			break;
+			return ttl < info->ttl;
 		case IPT_TTL_GT:
-			return (ttl > info->ttl);
-			break;
+			return ttl > info->ttl;
 		default:
 			printk(KERN_WARNING "ipt_ttl: unknown mode %d\n",
 				info->mode);
-			return 0;
+			return false;
 	}
 
-	return 0;
+	return false;
 }
 
-static struct xt_match ttl_match = {
+static struct xt_match ttl_match __read_mostly = {
 	.name		= "ttl",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 0654eaa..64552af 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -24,12 +24,6 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 			     struct nf_conntrack_tuple *tuple)
 {
@@ -84,36 +78,30 @@
 	return skb;
 }
 
-static int
-ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
-	     u_int8_t *protonum)
+static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
+			    unsigned int *dataoff, u_int8_t *protonum)
 {
+	struct iphdr _iph, *iph;
+
+	iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+	if (iph == NULL)
+		return -NF_DROP;
+
 	/* Never happen */
-	if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) {
+	if (iph->frag_off & htons(IP_OFFSET)) {
 		if (net_ratelimit()) {
-			printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n",
-			ip_hdr(*pskb)->protocol, hooknum);
+			printk(KERN_ERR "ipv4_get_l4proto: Frag of proto %u\n",
+			iph->protocol);
 		}
 		return -NF_DROP;
 	}
 
-	*dataoff = skb_network_offset(*pskb) + ip_hdrlen(*pskb);
-	*protonum = ip_hdr(*pskb)->protocol;
+	*dataoff = nhoff + (iph->ihl << 2);
+	*protonum = iph->protocol;
 
 	return NF_ACCEPT;
 }
 
-int nf_nat_module_is_loaded = 0;
-EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded);
-
-static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple)
-{
-	if (nf_nat_module_is_loaded)
-		return NF_CT_F_NAT;
-
-	return NF_CT_F_BASIC;
-}
-
 static unsigned int ipv4_confirm(unsigned int hooknum,
 				 struct sk_buff **pskb,
 				 const struct net_device *in,
@@ -133,6 +121,7 @@
 	struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn_help *help;
+	struct nf_conntrack_helper *helper;
 
 	/* This is where we call the helper: as the packet goes out. */
 	ct = nf_ct_get(*pskb, &ctinfo);
@@ -140,12 +129,14 @@
 		return NF_ACCEPT;
 
 	help = nfct_help(ct);
-	if (!help || !help->helper)
+	if (!help)
 		return NF_ACCEPT;
-
-	return help->helper->help(pskb,
-				  skb_network_offset(*pskb) + ip_hdrlen(*pskb),
-				  ct, ctinfo);
+	/* rcu_read_lock()ed by nf_hook_slow */
+	helper = rcu_dereference(help->helper);
+	if (!helper)
+		return NF_ACCEPT;
+	return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb),
+			    ct, ctinfo);
 }
 
 static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
@@ -154,12 +145,10 @@
 					  const struct net_device *out,
 					  int (*okfn)(struct sk_buff *))
 {
-#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
 	/* Previously seen (loopback)?  Ignore.  Do this before
 	   fragment check. */
 	if ((*pskb)->nfct)
 		return NF_ACCEPT;
-#endif
 
 	/* Gather fragments. */
 	if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
@@ -334,17 +323,17 @@
 
 	/* We only do TCP at the moment: is there a better way? */
 	if (strcmp(sk->sk_prot->name, "TCP")) {
-		DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n");
+		pr_debug("SO_ORIGINAL_DST: Not a TCP socket\n");
 		return -ENOPROTOOPT;
 	}
 
 	if ((unsigned int) *len < sizeof(struct sockaddr_in)) {
-		DEBUGP("SO_ORIGINAL_DST: len %u not %u\n",
-		       *len, sizeof(struct sockaddr_in));
+		pr_debug("SO_ORIGINAL_DST: len %d not %Zu\n",
+			 *len, sizeof(struct sockaddr_in));
 		return -EINVAL;
 	}
 
-	h = nf_conntrack_find_get(&tuple, NULL);
+	h = nf_conntrack_find_get(&tuple);
 	if (h) {
 		struct sockaddr_in sin;
 		struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
@@ -356,17 +345,17 @@
 			.tuple.dst.u3.ip;
 		memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
 
-		DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
-		       NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+		pr_debug("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
+			 NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
 		nf_ct_put(ct);
 		if (copy_to_user(user, &sin, sizeof(sin)) != 0)
 			return -EFAULT;
 		else
 			return 0;
 	}
-	DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
-	       NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
-	       NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
+	pr_debug("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
+		 NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
+		 NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
 	return -ENOENT;
 }
 
@@ -416,15 +405,14 @@
 	.get		= &getorigdst,
 };
 
-struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
+struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
 	.l3proto	 = PF_INET,
 	.name		 = "ipv4",
 	.pkt_to_tuple	 = ipv4_pkt_to_tuple,
 	.invert_tuple	 = ipv4_invert_tuple,
 	.print_tuple	 = ipv4_print_tuple,
 	.print_conntrack = ipv4_print_conntrack,
-	.prepare	 = ipv4_prepare,
-	.get_features	 = ipv4_get_features,
+	.get_l4proto	 = ipv4_get_l4proto,
 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 	.tuple_to_nfattr = ipv4_tuple_to_nfattr,
 	.nfattr_to_tuple = ipv4_nfattr_to_tuple,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 89f933e..3da9d73 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -18,12 +18,6 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #ifdef CONFIG_NF_CT_ACCT
 static unsigned int
 seq_print_counters(struct seq_file *s,
@@ -41,35 +35,36 @@
 	unsigned int bucket;
 };
 
-static struct list_head *ct_get_first(struct seq_file *seq)
+static struct hlist_node *ct_get_first(struct seq_file *seq)
 {
 	struct ct_iter_state *st = seq->private;
 
 	for (st->bucket = 0;
 	     st->bucket < nf_conntrack_htable_size;
 	     st->bucket++) {
-		if (!list_empty(&nf_conntrack_hash[st->bucket]))
-			return nf_conntrack_hash[st->bucket].next;
+		if (!hlist_empty(&nf_conntrack_hash[st->bucket]))
+			return nf_conntrack_hash[st->bucket].first;
 	}
 	return NULL;
 }
 
-static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+static struct hlist_node *ct_get_next(struct seq_file *seq,
+				      struct hlist_node *head)
 {
 	struct ct_iter_state *st = seq->private;
 
 	head = head->next;
-	while (head == &nf_conntrack_hash[st->bucket]) {
+	while (head == NULL) {
 		if (++st->bucket >= nf_conntrack_htable_size)
 			return NULL;
-		head = nf_conntrack_hash[st->bucket].next;
+		head = nf_conntrack_hash[st->bucket].first;
 	}
 	return head;
 }
 
-static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos)
 {
-	struct list_head *head = ct_get_first(seq);
+	struct hlist_node *head = ct_get_first(seq);
 
 	if (head)
 		while (pos && (head = ct_get_next(seq, head)))
@@ -169,7 +164,7 @@
 	return 0;
 }
 
-static struct seq_operations ct_seq_ops = {
+static const struct seq_operations ct_seq_ops = {
 	.start = ct_seq_start,
 	.next  = ct_seq_next,
 	.stop  = ct_seq_stop,
@@ -206,47 +201,68 @@
 };
 
 /* expects */
-static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_expect_iter_state {
+	unsigned int bucket;
+};
+
+static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
 {
-	struct list_head *e = &nf_conntrack_expect_list;
-	loff_t i;
+	struct ct_expect_iter_state *st = seq->private;
 
-	/* strange seq_file api calls stop even if we fail,
-	 * thus we need to grab lock since stop unlocks */
-	read_lock_bh(&nf_conntrack_lock);
-
-	if (list_empty(e))
-		return NULL;
-
-	for (i = 0; i <= *pos; i++) {
-		e = e->next;
-		if (e == &nf_conntrack_expect_list)
-			return NULL;
+	for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
+		if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
+			return nf_ct_expect_hash[st->bucket].first;
 	}
-	return e;
+	return NULL;
 }
 
-static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
+					     struct hlist_node *head)
 {
-	struct list_head *e = v;
+	struct ct_expect_iter_state *st = seq->private;
 
-	++*pos;
-	e = e->next;
-
-	if (e == &nf_conntrack_expect_list)
-		return NULL;
-
-	return e;
+	head = head->next;
+	while (head == NULL) {
+		if (++st->bucket >= nf_ct_expect_hsize)
+			return NULL;
+		head = nf_ct_expect_hash[st->bucket].first;
+	}
+	return head;
 }
 
-static void exp_seq_stop(struct seq_file *s, void *v)
+static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct hlist_node *head = ct_expect_get_first(seq);
+
+	if (head)
+		while (pos && (head = ct_expect_get_next(seq, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock_bh(&nf_conntrack_lock);
+	return ct_expect_get_idx(seq, *pos);
+}
+
+static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return ct_expect_get_next(seq, v);
+}
+
+static void exp_seq_stop(struct seq_file *seq, void *v)
 {
 	read_unlock_bh(&nf_conntrack_lock);
 }
 
 static int exp_seq_show(struct seq_file *s, void *v)
 {
-	struct nf_conntrack_expect *exp = v;
+	struct nf_conntrack_expect *exp;
+	struct hlist_node *n = v;
+
+	exp = hlist_entry(n, struct nf_conntrack_expect, hnode);
 
 	if (exp->tuple.src.l3num != AF_INET)
 		return 0;
@@ -266,7 +282,7 @@
 	return seq_putc(s, '\n');
 }
 
-static struct seq_operations exp_seq_ops = {
+static const struct seq_operations exp_seq_ops = {
 	.start = exp_seq_start,
 	.next = exp_seq_next,
 	.stop = exp_seq_stop,
@@ -275,7 +291,23 @@
 
 static int exp_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &exp_seq_ops);
+	struct seq_file *seq;
+	struct ct_expect_iter_state *st;
+	int ret;
+
+	st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
+	ret = seq_open(file, &exp_seq_ops);
+	if (ret)
+		goto out_free;
+	seq          = file->private_data;
+	seq->private = st;
+	memset(st, 0, sizeof(struct ct_expect_iter_state));
+	return ret;
+out_free:
+	kfree(st);
+	return ret;
 }
 
 static const struct file_operations ip_exp_file_ops = {
@@ -283,7 +315,7 @@
 	.open    = exp_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release
+	.release = seq_release_private,
 };
 
 static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
@@ -354,7 +386,7 @@
 	return 0;
 }
 
-static struct seq_operations ct_cpu_seq_ops = {
+static const struct seq_operations ct_cpu_seq_ops = {
 	.start  = ct_cpu_seq_start,
 	.next   = ct_cpu_seq_next,
 	.stop   = ct_cpu_seq_stop,
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index f4fc657..6593fd2 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -21,12 +21,6 @@
 
 static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int icmp_pkt_to_tuple(const struct sk_buff *skb,
 			     unsigned int dataoff,
 			     struct nf_conntrack_tuple *tuple)
@@ -125,8 +119,8 @@
 	if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
 	    || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
 		/* Can't create a new ICMP `conn' with this. */
-		DEBUGP("icmp: can't create new conn with type %u\n",
-		       conntrack->tuplehash[0].tuple.dst.u.icmp.type);
+		pr_debug("icmp: can't create new conn with type %u\n",
+			 conntrack->tuplehash[0].tuple.dst.u.icmp.type);
 		NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
 		return 0;
 	}
@@ -142,72 +136,42 @@
 		 unsigned int hooknum)
 {
 	struct nf_conntrack_tuple innertuple, origtuple;
-	struct {
-		struct icmphdr icmp;
-		struct iphdr ip;
-	} _in, *inside;
 	struct nf_conntrack_l4proto *innerproto;
 	struct nf_conntrack_tuple_hash *h;
-	int dataoff;
 
 	NF_CT_ASSERT(skb->nfct == NULL);
 
-	/* Not enough header? */
-	inside = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_in), &_in);
-	if (inside == NULL)
-		return -NF_ACCEPT;
-
-	/* Ignore ICMP's containing fragments (shouldn't happen) */
-	if (inside->ip.frag_off & htons(IP_OFFSET)) {
-		DEBUGP("icmp_error_message: fragment of proto %u\n",
-		       inside->ip.protocol);
+	/* Are they talking about one of our connections? */
+	if (!nf_ct_get_tuplepr(skb,
+			       skb_network_offset(skb) + ip_hdrlen(skb)
+						       + sizeof(struct icmphdr),
+			       PF_INET, &origtuple)) {
+		pr_debug("icmp_error_message: failed to get tuple\n");
 		return -NF_ACCEPT;
 	}
 
 	/* rcu_read_lock()ed by nf_hook_slow */
-	innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
-
-	dataoff = ip_hdrlen(skb) + sizeof(inside->icmp);
-	/* Are they talking about one of our connections? */
-	if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
-			     inside->ip.protocol, &origtuple,
-			     &nf_conntrack_l3proto_ipv4, innerproto)) {
-		DEBUGP("icmp_error_message: ! get_tuple p=%u",
-		       inside->ip.protocol);
-		return -NF_ACCEPT;
-	}
+	innerproto = __nf_ct_l4proto_find(PF_INET, origtuple.dst.protonum);
 
 	/* Ordinarily, we'd expect the inverted tupleproto, but it's
 	   been preserved inside the ICMP. */
 	if (!nf_ct_invert_tuple(&innertuple, &origtuple,
 				&nf_conntrack_l3proto_ipv4, innerproto)) {
-		DEBUGP("icmp_error_message: no match\n");
+		pr_debug("icmp_error_message: no match\n");
 		return -NF_ACCEPT;
 	}
 
 	*ctinfo = IP_CT_RELATED;
 
-	h = nf_conntrack_find_get(&innertuple, NULL);
+	h = nf_conntrack_find_get(&innertuple);
 	if (!h) {
-		/* Locally generated ICMPs will match inverted if they
-		   haven't been SNAT'ed yet */
-		/* FIXME: NAT code has to handle half-done double NAT --RR */
-		if (hooknum == NF_IP_LOCAL_OUT)
-			h = nf_conntrack_find_get(&origtuple, NULL);
-
-		if (!h) {
-			DEBUGP("icmp_error_message: no match\n");
-			return -NF_ACCEPT;
-		}
-
-		/* Reverse direction from that found */
-		if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
-			*ctinfo += IP_CT_IS_REPLY;
-	} else {
-		if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
-			*ctinfo += IP_CT_IS_REPLY;
+		pr_debug("icmp_error_message: no match\n");
+		return -NF_ACCEPT;
 	}
 
+	if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
+		*ctinfo += IP_CT_IS_REPLY;
+
 	/* Update skb to refer to this connection */
 	skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
 	skb->nfctinfo = *ctinfo;
@@ -348,7 +312,7 @@
 #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
 {
 	.l3proto		= PF_INET,
 	.l4proto		= IPPROTO_ICMP,
@@ -374,4 +338,3 @@
 #endif
 #endif
 };
-EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_icmp);
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c
index 0f17098..bd93a1d 100644
--- a/net/ipv4/netfilter/nf_nat_amanda.c
+++ b/net/ipv4/netfilter/nf_nat_amanda.c
@@ -45,7 +45,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -57,7 +57,7 @@
 				       matchoff, matchlen,
 				       buffer, strlen(buffer));
 	if (ret != NF_ACCEPT)
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index ea02f00..e848d8d 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -12,7 +12,6 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/skbuff.h>
-#include <linux/vmalloc.h>
 #include <net/checksum.h>
 #include <net/icmp.h>
 #include <net/ip.h>
@@ -32,20 +31,15 @@
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static DEFINE_RWLOCK(nf_nat_lock);
 
 static struct nf_conntrack_l3proto *l3proto = NULL;
 
 /* Calculated at init based on memory size */
 static unsigned int nf_nat_htable_size;
+static int nf_nat_vmalloced;
 
-static struct list_head *bysource;
+static struct hlist_head *bysource;
 
 #define MAX_IP_NAT_PROTO 256
 static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO];
@@ -87,19 +81,6 @@
 			    tuple->dst.protonum, 0) % nf_nat_htable_size;
 }
 
-/* Noone using conntrack by the time this called. */
-static void nf_nat_cleanup_conntrack(struct nf_conn *conn)
-{
-	struct nf_conn_nat *nat;
-	if (!(conn->status & IPS_NAT_DONE_MASK))
-		return;
-
-	nat = nfct_nat(conn);
-	write_lock_bh(&nf_nat_lock);
-	list_del(&nat->info.bysource);
-	write_unlock_bh(&nf_nat_lock);
-}
-
 /* Is this tuple already taken? (not by us) */
 int
 nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
@@ -166,10 +147,11 @@
 	unsigned int h = hash_by_src(tuple);
 	struct nf_conn_nat *nat;
 	struct nf_conn *ct;
+	struct hlist_node *n;
 
 	read_lock_bh(&nf_nat_lock);
-	list_for_each_entry(nat, &bysource[h], info.bysource) {
-		ct = (struct nf_conn *)((char *)nat - offsetof(struct nf_conn, data));
+	hlist_for_each_entry(nat, n, &bysource[h], bysource) {
+		ct = nat->ct;
 		if (same_src(ct, tuple)) {
 			/* Copy source part from reply tuple. */
 			nf_ct_invert_tuplepr(result,
@@ -254,7 +236,7 @@
 	   manips not an issue.  */
 	if (maniptype == IP_NAT_MANIP_SRC) {
 		if (find_appropriate_src(orig_tuple, tuple, range)) {
-			DEBUGP("get_unique_tuple: Found current src map\n");
+			pr_debug("get_unique_tuple: Found current src map\n");
 			if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
 				if (!nf_nat_used_tuple(tuple, ct))
 					return;
@@ -296,11 +278,20 @@
 		  unsigned int hooknum)
 {
 	struct nf_conntrack_tuple curr_tuple, new_tuple;
-	struct nf_conn_nat *nat = nfct_nat(ct);
-	struct nf_nat_info *info = &nat->info;
+	struct nf_conn_nat *nat;
 	int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
 	enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
 
+	/* nat helper or nfctnetlink also setup binding */
+	nat = nfct_nat(ct);
+	if (!nat) {
+		nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+		if (nat == NULL) {
+			pr_debug("failed to add NAT extension\n");
+			return NF_ACCEPT;
+		}
+	}
+
 	NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
 		     hooknum == NF_IP_POST_ROUTING ||
 		     hooknum == NF_IP_LOCAL_IN ||
@@ -337,7 +328,10 @@
 
 		srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 		write_lock_bh(&nf_nat_lock);
-		list_add(&info->bysource, &bysource[srchash]);
+		/* nf_conntrack_alter_reply might re-allocate exntension aera */
+		nat = nfct_nat(ct);
+		nat->ct = ct;
+		hlist_add_head(&nat->bysource, &bysource[srchash]);
 		write_unlock_bh(&nf_nat_lock);
 	}
 
@@ -462,8 +456,9 @@
 			return 0;
 	}
 
-	DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",
-	       *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
+	pr_debug("icmp_reply_translation: translating error %p manip %u "
+		 "dir %s\n", *pskb, manip,
+		 dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
 
 	/* rcu_read_lock()ed by nf_hook_slow */
 	l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
@@ -590,17 +585,69 @@
 EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr);
 #endif
 
+/* Noone using conntrack by the time this called. */
+static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
+{
+	struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+
+	if (nat == NULL || nat->ct == NULL)
+		return;
+
+	NF_CT_ASSERT(nat->ct->status & IPS_NAT_DONE_MASK);
+
+	write_lock_bh(&nf_nat_lock);
+	hlist_del(&nat->bysource);
+	nat->ct = NULL;
+	write_unlock_bh(&nf_nat_lock);
+}
+
+static void nf_nat_move_storage(struct nf_conn *conntrack, void *old)
+{
+	struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT);
+	struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old;
+	struct nf_conn *ct = old_nat->ct;
+	unsigned int srchash;
+
+	if (!(ct->status & IPS_NAT_DONE_MASK))
+		return;
+
+	srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+
+	write_lock_bh(&nf_nat_lock);
+	hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource);
+	new_nat->ct = ct;
+	write_unlock_bh(&nf_nat_lock);
+}
+
+static struct nf_ct_ext_type nat_extend __read_mostly = {
+	.len		= sizeof(struct nf_conn_nat),
+	.align		= __alignof__(struct nf_conn_nat),
+	.destroy	= nf_nat_cleanup_conntrack,
+	.move		= nf_nat_move_storage,
+	.id		= NF_CT_EXT_NAT,
+	.flags		= NF_CT_EXT_F_PREALLOC,
+};
+
 static int __init nf_nat_init(void)
 {
 	size_t i;
+	int ret;
+
+	ret = nf_ct_extend_register(&nat_extend);
+	if (ret < 0) {
+		printk(KERN_ERR "nf_nat_core: Unable to register extension\n");
+		return ret;
+	}
 
 	/* Leave them the same for the moment. */
 	nf_nat_htable_size = nf_conntrack_htable_size;
 
-	/* One vmalloc for both hash tables */
-	bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size);
-	if (!bysource)
-		return -ENOMEM;
+	bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
+					 &nf_nat_vmalloced);
+	if (!bysource) {
+		ret = -ENOMEM;
+		goto cleanup_extend;
+	}
 
 	/* Sew in builtin protocols. */
 	write_lock_bh(&nf_nat_lock);
@@ -612,18 +659,18 @@
 	write_unlock_bh(&nf_nat_lock);
 
 	for (i = 0; i < nf_nat_htable_size; i++) {
-		INIT_LIST_HEAD(&bysource[i]);
+		INIT_HLIST_HEAD(&bysource[i]);
 	}
 
-	/* FIXME: Man, this is a hack.  <SIGH> */
-	NF_CT_ASSERT(rcu_dereference(nf_conntrack_destroyed) == NULL);
-	rcu_assign_pointer(nf_conntrack_destroyed, nf_nat_cleanup_conntrack);
-
 	/* Initialize fake conntrack so that NAT will skip it */
 	nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
 
 	l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
 	return 0;
+
+ cleanup_extend:
+	nf_ct_extend_unregister(&nat_extend);
+	return ret;
 }
 
 /* Clear NAT section of all conntracks, in case we're loaded again. */
@@ -641,10 +688,10 @@
 static void __exit nf_nat_cleanup(void)
 {
 	nf_ct_iterate_cleanup(&clean_nat, NULL);
-	rcu_assign_pointer(nf_conntrack_destroyed, NULL);
 	synchronize_rcu();
-	vfree(bysource);
+	nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
 	nf_ct_l3proto_put(l3proto);
+	nf_ct_extend_unregister(&nat_extend);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c
index 751b598..3663bd8 100644
--- a/net/ipv4/netfilter/nf_nat_ftp.c
+++ b/net/ipv4/netfilter/nf_nat_ftp.c
@@ -25,12 +25,6 @@
 MODULE_DESCRIPTION("ftp NAT helper");
 MODULE_ALIAS("ip_nat_ftp");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* FIXME: Time out? --RR */
 
 static int
@@ -40,17 +34,15 @@
 		     unsigned int matchoff,
 		     unsigned int matchlen,
 		     struct nf_conn *ct,
-		     enum ip_conntrack_info ctinfo,
-		     u32 *seq)
+		     enum ip_conntrack_info ctinfo)
 {
 	char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
 
 	sprintf(buffer, "%u,%u,%u,%u,%u,%u",
 		NIPQUAD(newip), port>>8, port&0xFF);
 
-	DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+	pr_debug("calling nf_nat_mangle_tcp_packet\n");
 
-	*seq += strlen(buffer) - matchlen;
 	return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
 }
@@ -63,16 +55,14 @@
 		   unsigned int matchoff,
 		   unsigned int matchlen,
 		   struct nf_conn *ct,
-		   enum ip_conntrack_info ctinfo,
-		   u32 *seq)
+		   enum ip_conntrack_info ctinfo)
 {
 	char buffer[sizeof("|1|255.255.255.255|65535|")];
 
 	sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
 
-	DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+	pr_debug("calling nf_nat_mangle_tcp_packet\n");
 
-	*seq += strlen(buffer) - matchlen;
 	return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
 }
@@ -85,23 +75,21 @@
 		   unsigned int matchoff,
 		   unsigned int matchlen,
 		   struct nf_conn *ct,
-		   enum ip_conntrack_info ctinfo,
-		   u32 *seq)
+		   enum ip_conntrack_info ctinfo)
 {
 	char buffer[sizeof("|||65535|")];
 
 	sprintf(buffer, "|||%u|", port);
 
-	DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+	pr_debug("calling nf_nat_mangle_tcp_packet\n");
 
-	*seq += strlen(buffer) - matchlen;
 	return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
 }
 
 static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
 		       unsigned int, unsigned int, struct nf_conn *,
-		       enum ip_conntrack_info, u32 *seq)
+		       enum ip_conntrack_info)
 = {
 	[NF_CT_FTP_PORT] = mangle_rfc959_packet,
 	[NF_CT_FTP_PASV] = mangle_rfc959_packet,
@@ -116,15 +104,14 @@
 			       enum nf_ct_ftp_type type,
 			       unsigned int matchoff,
 			       unsigned int matchlen,
-			       struct nf_conntrack_expect *exp,
-			       u32 *seq)
+			       struct nf_conntrack_expect *exp)
 {
 	__be32 newip;
 	u_int16_t port;
 	int dir = CTINFO2DIR(ctinfo);
 	struct nf_conn *ct = exp->master;
 
-	DEBUGP("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
+	pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
 
 	/* Connection will come from wherever this packet goes, hence !dir */
 	newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
@@ -138,16 +125,15 @@
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
 	if (port == 0)
 		return NF_DROP;
 
-	if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo,
-			  seq)) {
-		nf_conntrack_unexpect_related(exp);
+	if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) {
+		nf_ct_unexpect_related(exp);
 		return NF_DROP;
 	}
 	return NF_ACCEPT;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index fcebc96..c1b059a 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -21,12 +21,6 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /****************************************************************************/
 static int set_addr(struct sk_buff **pskb,
 		    unsigned char **data, int dataoff,
@@ -126,12 +120,11 @@
 				    (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
 					i = 0;
 
-				DEBUGP
-				    ("nf_nat_ras: set signal address "
-				     "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-				     NIPQUAD(ip), port,
-				     NIPQUAD(ct->tuplehash[!dir].tuple.dst.
-					     ip), info->sig_port[!dir]);
+				pr_debug("nf_nat_ras: set signal address "
+					 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+					 NIPQUAD(addr.ip), port,
+					 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+					 info->sig_port[!dir]);
 				return set_h225_addr(pskb, data, 0, &taddr[i],
 						     &ct->tuplehash[!dir].
 						     tuple.dst.u3,
@@ -139,12 +132,11 @@
 			} else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
 				   port == info->sig_port[dir]) {
 				/* GK->GW */
-				DEBUGP
-				    ("nf_nat_ras: set signal address "
-				     "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-				     NIPQUAD(ip), port,
-				     NIPQUAD(ct->tuplehash[!dir].tuple.src.
-					     ip), info->sig_port[!dir]);
+				pr_debug("nf_nat_ras: set signal address "
+					 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+					 NIPQUAD(addr.ip), port,
+					 NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),
+					 info->sig_port[!dir]);
 				return set_h225_addr(pskb, data, 0, &taddr[i],
 						     &ct->tuplehash[!dir].
 						     tuple.src.u3,
@@ -171,12 +163,11 @@
 		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
 		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
 		    port == ct->tuplehash[dir].tuple.src.u.udp.port) {
-			DEBUGP("nf_nat_ras: set rasAddress "
-			       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-			       NIPQUAD(ip), ntohs(port),
-			       NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
-			       ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
-				     port));
+			pr_debug("nf_nat_ras: set rasAddress "
+				 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+				 NIPQUAD(addr.ip), ntohs(port),
+				 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+				 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
 			return set_h225_addr(pskb, data, 0, &taddr[i],
 					     &ct->tuplehash[!dir].tuple.dst.u3,
 					     ct->tuplehash[!dir].tuple.
@@ -237,12 +228,12 @@
 	for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
 	     nated_port != 0; nated_port += 2) {
 		rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(rtp_exp) == 0) {
+		if (nf_ct_expect_related(rtp_exp) == 0) {
 			rtcp_exp->tuple.dst.u.udp.port =
 			    htons(nated_port + 1);
-			if (nf_conntrack_expect_related(rtcp_exp) == 0)
+			if (nf_ct_expect_related(rtcp_exp) == 0)
 				break;
-			nf_conntrack_unexpect_related(rtp_exp);
+			nf_ct_unexpect_related(rtp_exp);
 		}
 	}
 
@@ -261,22 +252,22 @@
 		info->rtp_port[i][dir] = rtp_port;
 		info->rtp_port[i][!dir] = htons(nated_port);
 	} else {
-		nf_conntrack_unexpect_related(rtp_exp);
-		nf_conntrack_unexpect_related(rtcp_exp);
+		nf_ct_unexpect_related(rtp_exp);
+		nf_ct_unexpect_related(rtcp_exp);
 		return -1;
 	}
 
 	/* Success */
-	DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(rtp_exp->tuple.src.ip),
-	       ntohs(rtp_exp->tuple.src.u.udp.port),
-	       NIPQUAD(rtp_exp->tuple.dst.ip),
-	       ntohs(rtp_exp->tuple.dst.u.udp.port));
-	DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(rtcp_exp->tuple.src.ip),
-	       ntohs(rtcp_exp->tuple.src.u.udp.port),
-	       NIPQUAD(rtcp_exp->tuple.dst.ip),
-	       ntohs(rtcp_exp->tuple.dst.u.udp.port));
+	pr_debug("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(rtp_exp->tuple.src.u3.ip),
+		 ntohs(rtp_exp->tuple.src.u.udp.port),
+		 NIPQUAD(rtp_exp->tuple.dst.u3.ip),
+		 ntohs(rtp_exp->tuple.dst.u.udp.port));
+	pr_debug("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(rtcp_exp->tuple.src.u3.ip),
+		 ntohs(rtcp_exp->tuple.src.u.udp.port),
+		 NIPQUAD(rtcp_exp->tuple.dst.u3.ip),
+		 ntohs(rtcp_exp->tuple.dst.u.udp.port));
 
 	return 0;
 }
@@ -299,7 +290,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -313,13 +304,15 @@
 	if (set_h245_addr(pskb, data, dataoff, taddr,
 			  &ct->tuplehash[!dir].tuple.dst.u3,
 			  htons(nated_port)) < 0) {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return -1;
 	}
 
-	DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
-	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+	pr_debug("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(exp->tuple.src.u3.ip),
+		 ntohs(exp->tuple.src.u.tcp.port),
+		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
 }
@@ -347,7 +340,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -365,13 +358,15 @@
 		info->sig_port[dir] = port;
 		info->sig_port[!dir] = htons(nated_port);
 	} else {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return -1;
 	}
 
-	DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
-	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+	pr_debug("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(exp->tuple.src.u3.ip),
+		 ntohs(exp->tuple.src.u.tcp.port),
+		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
 }
@@ -433,7 +428,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -455,19 +450,21 @@
 		if (idx > 0 &&
 		    get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
 		    (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
-			set_h225_addr_hook(pskb, data, 0, &taddr[0],
-					   &ct->tuplehash[!dir].tuple.dst.u3,
-					   info->sig_port[!dir]);
+			set_h225_addr(pskb, data, 0, &taddr[0],
+				      &ct->tuplehash[!dir].tuple.dst.u3,
+				      info->sig_port[!dir]);
 		}
 	} else {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return -1;
 	}
 
 	/* Success */
-	DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
-	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+	pr_debug("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(exp->tuple.src.u3.ip),
+		 ntohs(exp->tuple.src.u.tcp.port),
+		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
 }
@@ -517,7 +514,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -531,15 +528,17 @@
 	if (!set_h225_addr(pskb, data, dataoff, taddr,
 			   &ct->tuplehash[!dir].tuple.dst.u3,
 			   htons(nated_port)) == 0) {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return -1;
 	}
 
 	/* Success */
-	DEBUGP("nf_nat_q931: expect Call Forwarding "
-	       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
-	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+	pr_debug("nf_nat_q931: expect Call Forwarding "
+		 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(exp->tuple.src.u3.ip),
+		 ntohs(exp->tuple.src.u.tcp.port),
+		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
 }
@@ -566,8 +565,6 @@
 	rcu_assign_pointer(nat_h245_hook, nat_h245);
 	rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
 	rcu_assign_pointer(nat_q931_hook, nat_q931);
-
-	DEBUGP("nf_nat_h323: init success\n");
 	return 0;
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 15b6e5c..93d8a0a 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -26,13 +26,9 @@
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_helper.h>
 
-#if 0
-#define DEBUGP printk
-#define DUMP_OFFSET(x)	printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
-#else
-#define DEBUGP(format, args...)
-#define DUMP_OFFSET(x)
-#endif
+#define DUMP_OFFSET(x) \
+	pr_debug("offset_before=%d, offset_after=%d, correction_pos=%u\n", \
+		 x->offset_before, x->offset_after, x->correction_pos);
 
 static DEFINE_SPINLOCK(nf_nat_seqofs_lock);
 
@@ -47,15 +43,15 @@
 	struct nf_nat_seq *this_way, *other_way;
 	struct nf_conn_nat *nat = nfct_nat(ct);
 
-	DEBUGP("nf_nat_resize_packet: old_size = %u, new_size = %u\n",
-		(*skb)->len, new_size);
+	pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n",
+		 ntohl(seq), seq);
 
 	dir = CTINFO2DIR(ctinfo);
 
-	this_way = &nat->info.seq[dir];
-	other_way = &nat->info.seq[!dir];
+	this_way = &nat->seq[dir];
+	other_way = &nat->seq[!dir];
 
-	DEBUGP("nf_nat_resize_packet: Seq_offset before: ");
+	pr_debug("nf_nat_resize_packet: Seq_offset before: ");
 	DUMP_OFFSET(this_way);
 
 	spin_lock_bh(&nf_nat_seqofs_lock);
@@ -72,7 +68,7 @@
 	}
 	spin_unlock_bh(&nf_nat_seqofs_lock);
 
-	DEBUGP("nf_nat_resize_packet: Seq_offset after: ");
+	pr_debug("nf_nat_resize_packet: Seq_offset after: ");
 	DUMP_OFFSET(this_way);
 }
 
@@ -100,14 +96,12 @@
 
 	/* update skb info */
 	if (rep_len > match_len) {
-		DEBUGP("nf_nat_mangle_packet: Extending packet by "
-		       "%u from %u bytes\n", rep_len - match_len,
-		       skb->len);
+		pr_debug("nf_nat_mangle_packet: Extending packet by "
+			 "%u from %u bytes\n", rep_len - match_len, skb->len);
 		skb_put(skb, rep_len - match_len);
 	} else {
-		DEBUGP("nf_nat_mangle_packet: Shrinking packet from "
-		       "%u from %u bytes\n", match_len - rep_len,
-		       skb->len);
+		pr_debug("nf_nat_mangle_packet: Shrinking packet from "
+			 "%u from %u bytes\n", match_len - rep_len, skb->len);
 		__skb_trim(skb, skb->len + rep_len - match_len);
 	}
 
@@ -178,7 +172,7 @@
 	datalen = (*pskb)->len - iph->ihl*4;
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		if (!(rt->rt_flags & RTCF_LOCAL) &&
-		    (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
+		    (*pskb)->dev->features & NETIF_F_V4_CSUM) {
 			(*pskb)->ip_summed = CHECKSUM_PARTIAL;
 			(*pskb)->csum_start = skb_headroom(*pskb) +
 					      skb_network_offset(*pskb) +
@@ -190,7 +184,7 @@
 			tcph->check = 0;
 			tcph->check = tcp_v4_check(datalen,
 						   iph->saddr, iph->daddr,
-						   csum_partial((char *)tcph,
+						   csum_partial(tcph,
 								datalen, 0));
 		}
 	} else
@@ -265,7 +259,7 @@
 
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		if (!(rt->rt_flags & RTCF_LOCAL) &&
-		    (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
+		    (*pskb)->dev->features & NETIF_F_V4_CSUM) {
 			(*pskb)->ip_summed = CHECKSUM_PARTIAL;
 			(*pskb)->csum_start = skb_headroom(*pskb) +
 					      skb_network_offset(*pskb) +
@@ -278,7 +272,7 @@
 			udph->check = 0;
 			udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
 							datalen, IPPROTO_UDP,
-							csum_partial((char *)udph,
+							csum_partial(udph,
 								     datalen, 0));
 			if (!udph->check)
 				udph->check = CSUM_MANGLED_0;
@@ -320,9 +314,9 @@
 			new_end_seq = htonl(ntohl(sack->end_seq)
 				      - natseq->offset_before);
 
-		DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
-			ntohl(sack->start_seq), new_start_seq,
-			ntohl(sack->end_seq), new_end_seq);
+		pr_debug("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
+			 ntohl(sack->start_seq), new_start_seq,
+			 ntohl(sack->end_seq), new_end_seq);
 
 		nf_proto_csum_replace4(&tcph->check, skb,
 				       sack->start_seq, new_start_seq, 0);
@@ -372,8 +366,7 @@
 			    op[1] >= 2+TCPOLEN_SACK_PERBLOCK &&
 			    ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
 				sack_adjust(*pskb, tcph, optoff+2,
-					    optoff+op[1],
-					    &nat->info.seq[!dir]);
+					    optoff+op[1], &nat->seq[!dir]);
 			optoff += op[1];
 		}
 	}
@@ -394,8 +387,8 @@
 
 	dir = CTINFO2DIR(ctinfo);
 
-	this_way = &nat->info.seq[dir];
-	other_way = &nat->info.seq[!dir];
+	this_way = &nat->seq[dir];
+	other_way = &nat->seq[!dir];
 
 	if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
 		return 0;
@@ -415,9 +408,9 @@
 	nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
 	nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
 
-	DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
-		ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
-		ntohl(newack));
+	pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n",
+		 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
+		 ntohl(newack));
 
 	tcph->seq = newseq;
 	tcph->ack_seq = newack;
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c
index 9b8c0da..bcf274b 100644
--- a/net/ipv4/netfilter/nf_nat_irc.c
+++ b/net/ipv4/netfilter/nf_nat_irc.c
@@ -22,12 +22,6 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <linux/netfilter/nf_conntrack_irc.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("IRC (DCC) NAT helper");
 MODULE_LICENSE("GPL");
@@ -44,9 +38,6 @@
 	u_int16_t port;
 	unsigned int ret;
 
-	DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
-	       expect->seq, exp_irc_info->len, ntohl(tcph->seq));
-
 	/* Reply comes from server. */
 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
 	exp->dir = IP_CT_DIR_REPLY;
@@ -55,7 +46,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -64,14 +55,14 @@
 
 	ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
 	sprintf(buffer, "%u %u", ip, port);
-	DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
-	       buffer, NIPQUAD(ip), port);
+	pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
+		 buffer, NIPQUAD(ip), port);
 
 	ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
 				       matchoff, matchlen, buffer,
 				       strlen(buffer));
 	if (ret != NF_ACCEPT)
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index a668887..984ec83 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -37,14 +37,6 @@
 MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
 MODULE_ALIAS("ip_nat_pptp");
 
-#if 0
-extern const char *pptp_msg_name[];
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
-				       __FUNCTION__, ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static void pptp_nat_expected(struct nf_conn *ct,
 			      struct nf_conntrack_expect *exp)
 {
@@ -60,7 +52,7 @@
 
 	/* And here goes the grand finale of corrosion... */
 	if (exp->dir == IP_CT_DIR_ORIGINAL) {
-		DEBUGP("we are PNS->PAC\n");
+		pr_debug("we are PNS->PAC\n");
 		/* therefore, build tuple for PAC->PNS */
 		t.src.l3num = AF_INET;
 		t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
@@ -69,7 +61,7 @@
 		t.dst.u.gre.key = ct_pptp_info->pns_call_id;
 		t.dst.protonum = IPPROTO_GRE;
 	} else {
-		DEBUGP("we are PAC->PNS\n");
+		pr_debug("we are PAC->PNS\n");
 		/* build tuple for PNS->PAC */
 		t.src.l3num = AF_INET;
 		t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
@@ -79,15 +71,15 @@
 		t.dst.protonum = IPPROTO_GRE;
 	}
 
-	DEBUGP("trying to unexpect other dir: ");
+	pr_debug("trying to unexpect other dir: ");
 	NF_CT_DUMP_TUPLE(&t);
-	other_exp = nf_conntrack_expect_find_get(&t);
+	other_exp = nf_ct_expect_find_get(&t);
 	if (other_exp) {
-		nf_conntrack_unexpect_related(other_exp);
-		nf_conntrack_expect_put(other_exp);
-		DEBUGP("success\n");
+		nf_ct_unexpect_related(other_exp);
+		nf_ct_expect_put(other_exp);
+		pr_debug("success\n");
 	} else {
-		DEBUGP("not found!\n");
+		pr_debug("not found!\n");
 	}
 
 	/* This must be a fresh one. */
@@ -161,9 +153,9 @@
 		cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
 		break;
 	default:
-		DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
-		      (msg <= PPTP_MSG_MAX)?
-		      pptp_msg_name[msg]:pptp_msg_name[0]);
+		pr_debug("unknown outbound packet 0x%04x:%s\n", msg,
+			 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] :
+					       pptp_msg_name[0]);
 		/* fall through */
 	case PPTP_SET_LINK_INFO:
 		/* only need to NAT in case PAC is behind NAT box */
@@ -179,8 +171,8 @@
 
 	/* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
 	 * down to here */
-	DEBUGP("altering call id from 0x%04x to 0x%04x\n",
-		ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
+	pr_debug("altering call id from 0x%04x to 0x%04x\n",
+		 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
 
 	/* mangle packet */
 	if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
@@ -255,8 +247,9 @@
 		pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
 		break;
 	default:
-		DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)?
-			pptp_msg_name[msg]:pptp_msg_name[0]);
+		pr_debug("unknown inbound packet %s\n",
+			 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] :
+					       pptp_msg_name[0]);
 		/* fall through */
 	case PPTP_START_SESSION_REQUEST:
 	case PPTP_START_SESSION_REPLY:
@@ -272,8 +265,8 @@
 	 * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
 
 	/* mangle packet */
-	DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
-		ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
+	pr_debug("altering peer call id from 0x%04x to 0x%04x\n",
+		 ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
 
 	if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
 				     pcid_off + sizeof(struct pptp_pkt_hdr) +
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
index c3908bc..2e40cc8 100644
--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -36,13 +36,6 @@
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
 
-#if 0
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
-				       __FUNCTION__, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
 /* is key in given range between min and max */
 static int
 gre_in_range(const struct nf_conntrack_tuple *tuple,
@@ -83,7 +76,7 @@
 		keyptr = &tuple->dst.u.gre.key;
 
 	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
-		DEBUGP("%p: NATing GRE PPTP\n", conntrack);
+		pr_debug("%p: NATing GRE PPTP\n", conntrack);
 		min = 1;
 		range_size = 0xffff;
 	} else {
@@ -91,7 +84,7 @@
 		range_size = ntohs(range->max.gre.key) - min + 1;
 	}
 
-	DEBUGP("min = %u, range_size = %u\n", min, range_size);
+	pr_debug("min = %u, range_size = %u\n", min, range_size);
 
 	for (i = 0; i < range_size; i++, key++) {
 		*keyptr = htons(min + key % range_size);
@@ -99,7 +92,7 @@
 			return 1;
 	}
 
-	DEBUGP("%p: no NAT mapping\n", conntrack);
+	pr_debug("%p: no NAT mapping\n", conntrack);
 	return 0;
 }
 
@@ -132,11 +125,11 @@
 		 * Try to behave like "nf_nat_proto_unknown" */
 		break;
 	case GRE_VERSION_PPTP:
-		DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
+		pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
 		pgreh->call_id = tuple->dst.u.gre.key;
 		break;
 	default:
-		DEBUGP("can't nat unknown GRE version\n");
+		pr_debug("can't nat unknown GRE version\n");
 		return 0;
 	}
 	return 1;
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 6740736..0f45427 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -24,12 +24,6 @@
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_rule.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
 
 static struct
@@ -140,39 +134,39 @@
 	return nf_nat_setup_info(ct, &mr->range[0], hooknum);
 }
 
-static int ipt_snat_checkentry(const char *tablename,
-			       const void *entry,
-			       const struct xt_target *target,
-			       void *targinfo,
-			       unsigned int hook_mask)
+static bool ipt_snat_checkentry(const char *tablename,
+				const void *entry,
+				const struct xt_target *target,
+				void *targinfo,
+				unsigned int hook_mask)
 {
 	struct nf_nat_multi_range_compat *mr = targinfo;
 
 	/* Must be a valid range */
 	if (mr->rangesize != 1) {
 		printk("SNAT: multiple ranges no longer supported\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static int ipt_dnat_checkentry(const char *tablename,
-			       const void *entry,
-			       const struct xt_target *target,
-			       void *targinfo,
-			       unsigned int hook_mask)
+static bool ipt_dnat_checkentry(const char *tablename,
+				const void *entry,
+				const struct xt_target *target,
+				void *targinfo,
+				unsigned int hook_mask)
 {
 	struct nf_nat_multi_range_compat *mr = targinfo;
 
 	/* Must be a valid range */
 	if (mr->rangesize != 1) {
 		printk("DNAT: multiple ranges no longer supported\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-inline unsigned int
+unsigned int
 alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
 {
 	/* Force range to this IP; let proto decide mapping for
@@ -186,8 +180,8 @@
 	struct nf_nat_range range
 		= { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
 
-	DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
-	       ct, NIPQUAD(ip));
+	pr_debug("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
+		 ct, NIPQUAD(ip));
 	return nf_nat_setup_info(ct, &range, hooknum);
 }
 
@@ -205,8 +199,8 @@
 	struct nf_nat_range range
 		= { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
 
-	DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
-	       ct, NIPQUAD(ip));
+	pr_debug("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+		 ct, NIPQUAD(ip));
 	return nf_nat_setup_info(ct, &range, hooknum);
 }
 
@@ -228,7 +222,7 @@
 	return ret;
 }
 
-static struct xt_target ipt_snat_reg = {
+static struct xt_target ipt_snat_reg __read_mostly = {
 	.name		= "SNAT",
 	.target		= ipt_snat_target,
 	.targetsize	= sizeof(struct nf_nat_multi_range_compat),
@@ -238,7 +232,7 @@
 	.family		= AF_INET,
 };
 
-static struct xt_target ipt_dnat_reg = {
+static struct xt_target ipt_dnat_reg __read_mostly = {
 	.name		= "DNAT",
 	.target		= ipt_dnat_target,
 	.targetsize	= sizeof(struct nf_nat_multi_range_compat),
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index fac97cf..a889ec3 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -26,12 +26,6 @@
 MODULE_DESCRIPTION("SIP NAT helper");
 MODULE_ALIAS("ip_nat_sip");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 struct addr_map {
 	struct {
 		char		src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
@@ -257,10 +251,12 @@
 	__be32 newip;
 	u_int16_t port;
 
-	DEBUGP("ip_nat_sdp():\n");
-
 	/* Connection will come from reply */
-	newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+	if (ct->tuplehash[dir].tuple.src.u3.ip ==
+	    ct->tuplehash[!dir].tuple.dst.u3.ip)
+		newip = exp->tuple.dst.u3.ip;
+	else
+		newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
 
 	exp->saved_ip = exp->tuple.dst.u3.ip;
 	exp->tuple.dst.u3.ip = newip;
@@ -274,7 +270,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
 		exp->tuple.dst.u.udp.port = htons(port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -282,7 +278,7 @@
 		return NF_DROP;
 
 	if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return NF_DROP;
 	}
 	return NF_ACCEPT;
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 6e88505..6bfcd3a 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -1276,9 +1276,6 @@
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(SNMP_PORT),
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.mask.src.l3num		= 0xFFFF,
-	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-	.mask.dst.protonum	= 0xFF,
 };
 
 static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
@@ -1290,9 +1287,6 @@
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(SNMP_TRAP_PORT),
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.mask.src.l3num		= 0xFFFF,
-	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-	.mask.dst.protonum	= 0xFF,
 };
 
 /*****************************************************************************
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 55dac36..332814d 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -19,6 +19,7 @@
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_rule.h>
 #include <net/netfilter/nf_nat_protocol.h>
@@ -26,12 +27,6 @@
 #include <net/netfilter/nf_nat_helper.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #ifdef CONFIG_XFRM
 static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
 {
@@ -113,8 +108,13 @@
 		return NF_ACCEPT;
 
 	nat = nfct_nat(ct);
-	if (!nat)
-		return NF_ACCEPT;
+	if (!nat) {
+		nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+		if (nat == NULL) {
+			pr_debug("failed to add NAT extension\n");
+			return NF_ACCEPT;
+		}
+	}
 
 	switch (ctinfo) {
 	case IP_CT_RELATED:
@@ -148,9 +148,9 @@
 				return ret;
 			}
 		} else
-			DEBUGP("Already setup manip %s for ct %p\n",
-			       maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
-			       ct);
+			pr_debug("Already setup manip %s for ct %p\n",
+				 maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
+				 ct);
 		break;
 
 	default:
@@ -264,7 +264,7 @@
 
 	ct = nf_ct_get(*pskb, &ctinfo);
 	if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
-		DEBUGP("nf_nat_standalone: adjusting sequence number\n");
+		pr_debug("nf_nat_standalone: adjusting sequence number\n");
 		if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
 			return NF_DROP;
 	}
@@ -326,26 +326,10 @@
 
 static int __init nf_nat_standalone_init(void)
 {
-	int size, ret = 0;
+	int ret = 0;
 
 	need_conntrack();
 
-	size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
-	       sizeof(struct nf_conn_nat);
-	ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
-	if (ret < 0) {
-		printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
-		return ret;
-	}
-
-	size = ALIGN(size, __alignof__(struct nf_conn_help)) +
-	       sizeof(struct nf_conn_help);
-	ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP,
-					  "nf_nat:help", size);
-	if (ret < 0) {
-		printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
-		goto cleanup_register_cache;
-	}
 #ifdef CONFIG_XFRM
 	BUG_ON(ip_nat_decode_session != NULL);
 	ip_nat_decode_session = nat_decode_session;
@@ -360,7 +344,6 @@
 		printk("nf_nat_init: can't register hooks.\n");
 		goto cleanup_rule_init;
 	}
-	nf_nat_module_is_loaded = 1;
 	return ret;
 
  cleanup_rule_init:
@@ -370,9 +353,6 @@
 	ip_nat_decode_session = NULL;
 	synchronize_net();
 #endif
-	nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP);
- cleanup_register_cache:
-	nf_conntrack_unregister_cache(NF_CT_F_NAT);
 	return ret;
 }
 
@@ -380,7 +360,6 @@
 {
 	nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
 	nf_nat_rule_cleanup();
-	nf_nat_module_is_loaded = 0;
 #ifdef CONFIG_XFRM
 	ip_nat_decode_session = NULL;
 	synchronize_net();
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c
index 2566b79..04dfeae 100644
--- a/net/ipv4/netfilter/nf_nat_tftp.c
+++ b/net/ipv4/netfilter/nf_nat_tftp.c
@@ -30,7 +30,7 @@
 		= ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
 	exp->dir = IP_CT_DIR_REPLY;
 	exp->expectfn = nf_nat_follow_master;
-	if (nf_conntrack_expect_related(exp) != 0)
+	if (nf_ct_expect_related(exp) != 0)
 		return NF_DROP;
 	return NF_ACCEPT;
 }
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cdbc6c1..3b690cf 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -260,7 +260,7 @@
 		seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
 
 	seq_printf(seq, "\nIp: %d %d",
-			ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
+		   IPV4_DEVCONF_ALL(FORWARDING) ? 1 : 2, sysctl_ip_default_ttl);
 
 	for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
 		seq_printf(seq, " %lu",
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index df9fe4f..88fa648 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -101,7 +101,6 @@
 #include <net/tcp.h>
 #include <net/icmp.h>
 #include <net/xfrm.h>
-#include <net/ip_mp_alg.h>
 #include <net/netevent.h>
 #include <net/rtnetlink.h>
 #ifdef CONFIG_SYSCTL
@@ -168,7 +167,7 @@
 
 #define ECN_OR_COST(class)	TC_PRIO_##class
 
-__u8 ip_tos2prio[16] = {
+const __u8 ip_tos2prio[16] = {
 	TC_PRIO_BESTEFFORT,
 	ECN_OR_COST(FILLER),
 	TC_PRIO_BESTEFFORT,
@@ -495,13 +494,11 @@
 
 static __inline__ void rt_free(struct rtable *rt)
 {
-	multipath_remove(rt);
 	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static __inline__ void rt_drop(struct rtable *rt)
 {
-	multipath_remove(rt);
 	ip_rt_put(rt);
 	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
@@ -574,52 +571,6 @@
 		(fl1->iif ^ fl2->iif)) == 0;
 }
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-static struct rtable **rt_remove_balanced_route(struct rtable **chain_head,
-						struct rtable *expentry,
-						int *removed_count)
-{
-	int passedexpired = 0;
-	struct rtable **nextstep = NULL;
-	struct rtable **rthp = chain_head;
-	struct rtable *rth;
-
-	if (removed_count)
-		*removed_count = 0;
-
-	while ((rth = *rthp) != NULL) {
-		if (rth == expentry)
-			passedexpired = 1;
-
-		if (((*rthp)->u.dst.flags & DST_BALANCED) != 0  &&
-		    compare_keys(&(*rthp)->fl, &expentry->fl)) {
-			if (*rthp == expentry) {
-				*rthp = rth->u.dst.rt_next;
-				continue;
-			} else {
-				*rthp = rth->u.dst.rt_next;
-				rt_free(rth);
-				if (removed_count)
-					++(*removed_count);
-			}
-		} else {
-			if (!((*rthp)->u.dst.flags & DST_BALANCED) &&
-			    passedexpired && !nextstep)
-				nextstep = &rth->u.dst.rt_next;
-
-			rthp = &rth->u.dst.rt_next;
-		}
-	}
-
-	rt_free(expentry);
-	if (removed_count)
-		++(*removed_count);
-
-	return nextstep;
-}
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-
-
 /* This runs via a timer and thus is always in BH context. */
 static void rt_check_expire(unsigned long dummy)
 {
@@ -658,22 +609,8 @@
 			}
 
 			/* Cleanup aged off entries. */
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-			/* remove all related balanced entries if necessary */
-			if (rth->u.dst.flags & DST_BALANCED) {
-				rthp = rt_remove_balanced_route(
-					&rt_hash_table[i].chain,
-					rth, NULL);
-				if (!rthp)
-					break;
-			} else {
-				*rthp = rth->u.dst.rt_next;
-				rt_free(rth);
-			}
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 			*rthp = rth->u.dst.rt_next;
 			rt_free(rth);
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 		}
 		spin_unlock(rt_hash_lock_addr(i));
 
@@ -721,9 +658,6 @@
 	if (delay < 0)
 		delay = ip_rt_min_delay;
 
-	/* flush existing multipath state*/
-	multipath_flush();
-
 	spin_lock_bh(&rt_flush_lock);
 
 	if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) {
@@ -842,30 +776,9 @@
 					rthp = &rth->u.dst.rt_next;
 					continue;
 				}
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-				/* remove all related balanced entries
-				 * if necessary
-				 */
-				if (rth->u.dst.flags & DST_BALANCED) {
-					int r;
-
-					rthp = rt_remove_balanced_route(
-						&rt_hash_table[k].chain,
-						rth,
-						&r);
-					goal -= r;
-					if (!rthp)
-						break;
-				} else {
-					*rthp = rth->u.dst.rt_next;
-					rt_free(rth);
-					goal--;
-				}
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 				*rthp = rth->u.dst.rt_next;
 				rt_free(rth);
 				goal--;
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 			}
 			spin_unlock_bh(rt_hash_lock_addr(k));
 			if (goal <= 0)
@@ -939,12 +852,7 @@
 
 	spin_lock_bh(rt_hash_lock_addr(hash));
 	while ((rth = *rthp) != NULL) {
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-		if (!(rth->u.dst.flags & DST_BALANCED) &&
-		    compare_keys(&rth->fl, &rt->fl)) {
-#else
 		if (compare_keys(&rth->fl, &rt->fl)) {
-#endif
 			/* Put it first */
 			*rthp = rth->u.dst.rt_next;
 			/*
@@ -1636,7 +1544,7 @@
 
 	atomic_set(&rth->u.dst.__refcnt, 1);
 	rth->u.dst.flags= DST_HOST;
-	if (in_dev->cnf.no_policy)
+	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
 		rth->u.dst.flags |= DST_NOPOLICY;
 	rth->fl.fl4_dst	= daddr;
 	rth->rt_dst	= daddr;
@@ -1774,13 +1682,9 @@
 
 	atomic_set(&rth->u.dst.__refcnt, 1);
 	rth->u.dst.flags= DST_HOST;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	if (res->fi->fib_nhs > 1)
-		rth->u.dst.flags |= DST_BALANCED;
-#endif
-	if (in_dev->cnf.no_policy)
+	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
 		rth->u.dst.flags |= DST_NOPOLICY;
-	if (out_dev->cnf.no_xfrm)
+	if (IN_DEV_CONF_GET(out_dev, NOXFRM))
 		rth->u.dst.flags |= DST_NOXFRM;
 	rth->fl.fl4_dst	= daddr;
 	rth->rt_dst	= daddr;
@@ -1812,11 +1716,11 @@
 	return err;
 }
 
-static inline int ip_mkroute_input_def(struct sk_buff *skb,
-				       struct fib_result* res,
-				       const struct flowi *fl,
-				       struct in_device *in_dev,
-				       __be32 daddr, __be32 saddr, u32 tos)
+static inline int ip_mkroute_input(struct sk_buff *skb,
+				   struct fib_result* res,
+				   const struct flowi *fl,
+				   struct in_device *in_dev,
+				   __be32 daddr, __be32 saddr, u32 tos)
 {
 	struct rtable* rth = NULL;
 	int err;
@@ -1837,63 +1741,6 @@
 	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
 }
 
-static inline int ip_mkroute_input(struct sk_buff *skb,
-				   struct fib_result* res,
-				   const struct flowi *fl,
-				   struct in_device *in_dev,
-				   __be32 daddr, __be32 saddr, u32 tos)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct rtable* rth = NULL, *rtres;
-	unsigned char hop, hopcount;
-	int err = -EINVAL;
-	unsigned int hash;
-
-	if (res->fi)
-		hopcount = res->fi->fib_nhs;
-	else
-		hopcount = 1;
-
-	/* distinguish between multipath and singlepath */
-	if (hopcount < 2)
-		return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
-					    saddr, tos);
-
-	/* add all alternatives to the routing cache */
-	for (hop = 0; hop < hopcount; hop++) {
-		res->nh_sel = hop;
-
-		/* put reference to previous result */
-		if (hop)
-			ip_rt_put(rtres);
-
-		/* create a routing cache entry */
-		err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
-				      &rth);
-		if (err)
-			return err;
-
-		/* put it into the cache */
-		hash = rt_hash(daddr, saddr, fl->iif);
-		err = rt_intern_hash(hash, rth, &rtres);
-		if (err)
-			return err;
-
-		/* forward hop information to multipath impl. */
-		multipath_set_nhinfo(rth,
-				     FIB_RES_NETWORK(*res),
-				     FIB_RES_NETMASK(*res),
-				     res->prefixlen,
-				     &FIB_RES_NH(*res));
-	}
-	skb->dst = &rtres->u.dst;
-	return err;
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
-	return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
-}
-
-
 /*
  *	NOTE. We drop all the packets that has local source
  *	addresses, because every properly looped back packet
@@ -2021,7 +1868,7 @@
 
 	atomic_set(&rth->u.dst.__refcnt, 1);
 	rth->u.dst.flags= DST_HOST;
-	if (in_dev->cnf.no_policy)
+	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
 		rth->u.dst.flags |= DST_NOPOLICY;
 	rth->fl.fl4_dst	= daddr;
 	rth->rt_dst	= daddr;
@@ -2211,16 +2058,9 @@
 
 	atomic_set(&rth->u.dst.__refcnt, 1);
 	rth->u.dst.flags= DST_HOST;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	if (res->fi) {
-		rth->rt_multipath_alg = res->fi->fib_mp_alg;
-		if (res->fi->fib_nhs > 1)
-			rth->u.dst.flags |= DST_BALANCED;
-	}
-#endif
-	if (in_dev->cnf.no_xfrm)
+	if (IN_DEV_CONF_GET(in_dev, NOXFRM))
 		rth->u.dst.flags |= DST_NOXFRM;
-	if (in_dev->cnf.no_policy)
+	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
 		rth->u.dst.flags |= DST_NOPOLICY;
 
 	rth->fl.fl4_dst	= oldflp->fl4_dst;
@@ -2277,12 +2117,12 @@
 	return err;
 }
 
-static inline int ip_mkroute_output_def(struct rtable **rp,
-					struct fib_result* res,
-					const struct flowi *fl,
-					const struct flowi *oldflp,
-					struct net_device *dev_out,
-					unsigned flags)
+static inline int ip_mkroute_output(struct rtable **rp,
+				    struct fib_result* res,
+				    const struct flowi *fl,
+				    const struct flowi *oldflp,
+				    struct net_device *dev_out,
+				    unsigned flags)
 {
 	struct rtable *rth = NULL;
 	int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
@@ -2295,68 +2135,6 @@
 	return err;
 }
 
-static inline int ip_mkroute_output(struct rtable** rp,
-				    struct fib_result* res,
-				    const struct flowi *fl,
-				    const struct flowi *oldflp,
-				    struct net_device *dev_out,
-				    unsigned flags)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	unsigned char hop;
-	unsigned hash;
-	int err = -EINVAL;
-	struct rtable *rth = NULL;
-
-	if (res->fi && res->fi->fib_nhs > 1) {
-		unsigned char hopcount = res->fi->fib_nhs;
-
-		for (hop = 0; hop < hopcount; hop++) {
-			struct net_device *dev2nexthop;
-
-			res->nh_sel = hop;
-
-			/* hold a work reference to the output device */
-			dev2nexthop = FIB_RES_DEV(*res);
-			dev_hold(dev2nexthop);
-
-			/* put reference to previous result */
-			if (hop)
-				ip_rt_put(*rp);
-
-			err = __mkroute_output(&rth, res, fl, oldflp,
-					       dev2nexthop, flags);
-
-			if (err != 0)
-				goto cleanup;
-
-			hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src,
-					oldflp->oif);
-			err = rt_intern_hash(hash, rth, rp);
-
-			/* forward hop information to multipath impl. */
-			multipath_set_nhinfo(rth,
-					     FIB_RES_NETWORK(*res),
-					     FIB_RES_NETMASK(*res),
-					     res->prefixlen,
-					     &FIB_RES_NH(*res));
-		cleanup:
-			/* release work reference to output device */
-			dev_put(dev2nexthop);
-
-			if (err != 0)
-				return err;
-		}
-		return err;
-	} else {
-		return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out,
-					     flags);
-	}
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-	return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);
-#endif
-}
-
 /*
  * Major route resolver routine.
  */
@@ -2570,17 +2348,6 @@
 		    rth->fl.mark == flp->mark &&
 		    !((rth->fl.fl4_tos ^ flp->fl4_tos) &
 			    (IPTOS_RT_MASK | RTO_ONLINK))) {
-
-			/* check for multipath routes and choose one if
-			 * necessary
-			 */
-			if (multipath_select_route(flp, rth, rp)) {
-				dst_hold(&(*rp)->u.dst);
-				RT_CACHE_STAT_INC(out_hit);
-				rcu_read_unlock_bh();
-				return 0;
-			}
-
 			rth->u.dst.lastuse = jiffies;
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
@@ -2598,6 +2365,69 @@
 
 EXPORT_SYMBOL_GPL(__ip_route_output_key);
 
+static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+}
+
+static struct dst_ops ipv4_dst_blackhole_ops = {
+	.family			=	AF_INET,
+	.protocol		=	__constant_htons(ETH_P_IP),
+	.destroy		=	ipv4_dst_destroy,
+	.check			=	ipv4_dst_check,
+	.update_pmtu		=	ipv4_rt_blackhole_update_pmtu,
+	.entry_size		=	sizeof(struct rtable),
+};
+
+
+static int ipv4_blackhole_output(struct sk_buff *skb)
+{
+	kfree_skb(skb);
+	return 0;
+}
+
+static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp, struct sock *sk)
+{
+	struct rtable *ort = *rp;
+	struct rtable *rt = (struct rtable *)
+		dst_alloc(&ipv4_dst_blackhole_ops);
+
+	if (rt) {
+		struct dst_entry *new = &rt->u.dst;
+
+		atomic_set(&new->__refcnt, 1);
+		new->__use = 1;
+		new->input = ipv4_blackhole_output;
+		new->output = ipv4_blackhole_output;
+		memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
+
+		new->dev = ort->u.dst.dev;
+		if (new->dev)
+			dev_hold(new->dev);
+
+		rt->fl = ort->fl;
+
+		rt->idev = ort->idev;
+		if (rt->idev)
+			in_dev_hold(rt->idev);
+		rt->rt_flags = ort->rt_flags;
+		rt->rt_type = ort->rt_type;
+		rt->rt_dst = ort->rt_dst;
+		rt->rt_src = ort->rt_src;
+		rt->rt_iif = ort->rt_iif;
+		rt->rt_gateway = ort->rt_gateway;
+		rt->rt_spec_dst = ort->rt_spec_dst;
+		rt->peer = ort->peer;
+		if (rt->peer)
+			atomic_inc(&rt->peer->refcnt);
+
+		dst_free(new);
+	}
+
+	dst_release(&(*rp)->u.dst);
+	*rp = rt;
+	return (rt ? 0 : -ENOMEM);
+}
+
 int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags)
 {
 	int err;
@@ -2610,7 +2440,11 @@
 			flp->fl4_src = (*rp)->rt_src;
 		if (!flp->fl4_dst)
 			flp->fl4_dst = (*rp)->rt_dst;
-		return xfrm_lookup((struct dst_entry **)rp, flp, sk, flags);
+		err = __xfrm_lookup((struct dst_entry **)rp, flp, sk, flags);
+		if (err == -EREMOTE)
+			err = ipv4_dst_blackhole(rp, flp, sk);
+
+		return err;
 	}
 
 	return 0;
@@ -2662,10 +2496,6 @@
 	if (rt->u.dst.tclassid)
 		NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid);
 #endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	if (rt->rt_multipath_alg != IP_MP_ALG_NONE)
-		NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
-#endif
 	if (rt->fl.iif)
 		NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
 	else if (rt->rt_src != rt->fl.fl4_src)
@@ -2692,7 +2522,7 @@
 		__be32 dst = rt->rt_dst;
 
 		if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
-		    ipv4_devconf.mc_forwarding) {
+		    IPV4_DEVCONF_ALL(MC_FORWARDING)) {
 			int err = ipmr_get_route(skb, r, nowait);
 			if (err <= 0) {
 				if (!nowait) {
@@ -3139,6 +2969,8 @@
 		kmem_cache_create("ip_dst_cache", sizeof(struct rtable), 0,
 				  SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
 
+	ipv4_dst_blackhole_ops.kmem_cachep = ipv4_dst_ops.kmem_cachep;
+
 	rt_hash_table = (struct rt_hash_bucket *)
 		alloc_large_system_hash("IP route cache",
 					sizeof(struct rt_hash_bucket),
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 6817d64..53ef0f4 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -37,12 +37,12 @@
 int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
 			void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-	int val = ipv4_devconf.forwarding;
+	int val = IPV4_DEVCONF_ALL(FORWARDING);
 	int ret;
 
 	ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
 
-	if (write && ipv4_devconf.forwarding != val)
+	if (write && IPV4_DEVCONF_ALL(FORWARDING) != val)
 		inet_forward_change();
 
 	return ret;
@@ -222,7 +222,7 @@
 	{
 		.ctl_name	= NET_IPV4_FORWARD,
 		.procname	= "ip_forward",
-		.data		= &ipv4_devconf.forwarding,
+		.data		= &IPV4_DEVCONF_ALL(FORWARDING),
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &ipv4_sysctl_forward,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index bd4c295..987b944 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1064,7 +1064,11 @@
 					break;
 			}
 			used = recv_actor(desc, skb, offset, len);
-			if (used <= len) {
+			if (used < 0) {
+				if (!copied)
+					copied = used;
+				break;
+			} else if (used <= len) {
 				seq += used;
 				copied += used;
 				offset += used;
@@ -1086,7 +1090,7 @@
 	tcp_rcv_space_adjust(sk);
 
 	/* Clean up data we have read: This will do ACK frames. */
-	if (copied)
+	if (copied > 0)
 		tcp_cleanup_rbuf(sk, copied);
 	return copied;
 }
@@ -1112,6 +1116,7 @@
 	long timeo;
 	struct task_struct *user_recv = NULL;
 	int copied_early = 0;
+	struct sk_buff *skb;
 
 	lock_sock(sk);
 
@@ -1138,16 +1143,26 @@
 #ifdef CONFIG_NET_DMA
 	tp->ucopy.dma_chan = NULL;
 	preempt_disable();
-	if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
-	    !sysctl_tcp_low_latency && __get_cpu_var(softnet_data).net_dma) {
-		preempt_enable_no_resched();
-		tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len);
-	} else
-		preempt_enable_no_resched();
+	skb = skb_peek_tail(&sk->sk_receive_queue);
+	{
+		int available = 0;
+
+		if (skb)
+			available = TCP_SKB_CB(skb)->seq + skb->len - (*seq);
+		if ((available < target) &&
+		    (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
+		    !sysctl_tcp_low_latency &&
+		    __get_cpu_var(softnet_data).net_dma) {
+			preempt_enable_no_resched();
+			tp->ucopy.pinned_list =
+					dma_pin_iovec_pages(msg->msg_iov, len);
+		} else {
+			preempt_enable_no_resched();
+		}
+	}
 #endif
 
 	do {
-		struct sk_buff *skb;
 		u32 offset;
 
 		/* Are we at urgent data? Stop if we have read anything or have SIGURG pending. */
@@ -1435,7 +1450,6 @@
 
 #ifdef CONFIG_NET_DMA
 	if (tp->ucopy.dma_chan) {
-		struct sk_buff *skb;
 		dma_cookie_t done, used;
 
 		dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
@@ -1674,9 +1688,8 @@
 	}
 	if (sk->sk_state != TCP_CLOSE) {
 		sk_stream_mem_reclaim(sk);
-		if (atomic_read(sk->sk_prot->orphan_count) > sysctl_tcp_max_orphans ||
-		    (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
-		     atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+		if (tcp_too_many_orphans(sk,
+				atomic_read(sk->sk_prot->orphan_count))) {
 			if (net_ratelimit())
 				printk(KERN_INFO "TCP: too many of orphaned "
 				       "sockets\n");
@@ -2465,13 +2478,10 @@
 			order++)
 		;
 	if (order >= 4) {
-		sysctl_local_port_range[0] = 32768;
-		sysctl_local_port_range[1] = 61000;
 		tcp_death_row.sysctl_max_tw_buckets = 180000;
 		sysctl_tcp_max_orphans = 4096 << (order - 4);
 		sysctl_max_syn_backlog = 1024;
 	} else if (order < 3) {
-		sysctl_local_port_range[0] = 1024 * (3 - order);
 		tcp_death_row.sysctl_max_tw_buckets >>= (3 - order);
 		sysctl_tcp_max_orphans >>= (3 - order);
 		sysctl_max_syn_backlog = 128;
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index 281c9f9..dd9ef65 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -29,7 +29,7 @@
 static int max_increment = 16;
 static int low_window = 14;
 static int beta = 819;		/* = 819/1024 (BICTCP_BETA_SCALE) */
-static int initial_ssthresh = 100;
+static int initial_ssthresh;
 static int smooth_part = 20;
 
 module_param(fast_convergence, int, 0644);
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 1422448..ebfaac2 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -29,7 +29,7 @@
 static int fast_convergence __read_mostly = 1;
 static int max_increment __read_mostly = 16;
 static int beta __read_mostly = 819;	/* = 819/1024 (BICTCP_BETA_SCALE) */
-static int initial_ssthresh __read_mostly = 100;
+static int initial_ssthresh __read_mostly;
 static int bic_scale __read_mostly = 41;
 static int tcp_friendliness __read_mostly = 1;
 
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c
index 4adc47c..b2b2256 100644
--- a/net/ipv4/tcp_illinois.c
+++ b/net/ipv4/tcp_illinois.c
@@ -90,6 +90,9 @@
 
 	ca->acked = pkts_acked;
 
+	if (ktime_equal(last, net_invalid_timestamp()))
+		return;
+
 	rtt = ktime_to_us(net_timedelta(last));
 
 	/* ignore bogus values, this prevents wraparound in alpha math */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 7641b27..4e5884a 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -953,7 +953,7 @@
 	int prior_fackets;
 	u32 lost_retrans = 0;
 	int flag = 0;
-	int dup_sack = 0;
+	int found_dup_sack = 0;
 	int cached_fack_count;
 	int i;
 	int first_sack_index;
@@ -964,20 +964,20 @@
 
 	/* Check for D-SACK. */
 	if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) {
-		dup_sack = 1;
+		found_dup_sack = 1;
 		tp->rx_opt.sack_ok |= 4;
 		NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV);
 	} else if (num_sacks > 1 &&
 			!after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) &&
 			!before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) {
-		dup_sack = 1;
+		found_dup_sack = 1;
 		tp->rx_opt.sack_ok |= 4;
 		NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV);
 	}
 
 	/* D-SACK for already forgotten data...
 	 * Do dumb counting. */
-	if (dup_sack &&
+	if (found_dup_sack &&
 			!after(ntohl(sp[0].end_seq), prior_snd_una) &&
 			after(ntohl(sp[0].end_seq), tp->undo_marker))
 		tp->undo_retrans--;
@@ -1058,6 +1058,7 @@
 		__u32 start_seq = ntohl(sp->start_seq);
 		__u32 end_seq = ntohl(sp->end_seq);
 		int fack_count;
+		int dup_sack = (found_dup_sack && (i == first_sack_index));
 
 		skb = cached_skb;
 		fack_count = cached_fack_count;
@@ -1397,7 +1398,9 @@
 		 * waiting for the first ACK and did not get it)...
 		 */
 		if ((tp->frto_counter == 1) && !(flag&FLAG_DATA_ACKED)) {
-			tp->retrans_out += tcp_skb_pcount(skb);
+			/* For some reason this R-bit might get cleared? */
+			if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
+				tp->retrans_out += tcp_skb_pcount(skb);
 			/* ...enter this if branch just for the first segment */
 			flag |= FLAG_DATA_ACKED;
 		} else {
@@ -1501,6 +1504,8 @@
 	tcp_set_ca_state(sk, TCP_CA_Loss);
 	tp->high_seq = tp->snd_nxt;
 	TCP_ECN_queue_cwr(tp);
+	/* Abort FRTO algorithm if one is in progress */
+	tp->frto_counter = 0;
 
 	clear_all_retrans_hints(tp);
 }
@@ -2035,7 +2040,7 @@
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 
-	tp->left_out = tp->sacked_out;
+	tcp_sync_left_out(tp);
 
 	if (tp->retrans_out == 0)
 		tp->retrans_stamp = 0;
@@ -2405,9 +2410,9 @@
 	struct sk_buff *skb;
 	__u32 now = tcp_time_stamp;
 	int acked = 0;
+	int prior_packets = tp->packets_out;
 	__s32 seq_rtt = -1;
-	u32 pkts_acked = 0;
-	ktime_t last_ackt = ktime_set(0,0);
+	ktime_t last_ackt = net_invalid_timestamp();
 
 	while ((skb = tcp_write_queue_head(sk)) &&
 	       skb != tcp_send_head(sk)) {
@@ -2435,7 +2440,6 @@
 		 */
 		if (!(scb->flags & TCPCB_FLAG_SYN)) {
 			acked |= FLAG_DATA_ACKED;
-			++pkts_acked;
 		} else {
 			acked |= FLAG_SYN_ACKED;
 			tp->retrans_stamp = 0;
@@ -2479,12 +2483,17 @@
 	}
 
 	if (acked&FLAG_ACKED) {
+		u32 pkts_acked = prior_packets - tp->packets_out;
 		const struct tcp_congestion_ops *ca_ops
 			= inet_csk(sk)->icsk_ca_ops;
 
 		tcp_ack_update_rtt(sk, acked, seq_rtt);
 		tcp_ack_packets_out(sk);
 
+		/* Is the ACK triggering packet unambiguous? */
+		if (acked & FLAG_RETRANS_DATA_ACKED)
+			last_ackt = net_invalid_timestamp();
+
 		if (ca_ops->pkts_acked)
 			ca_ops->pkts_acked(sk, pkts_acked, last_ackt);
 	}
@@ -2608,6 +2617,7 @@
 {
 	tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
 	tp->snd_cwnd_cnt = 0;
+	TCP_ECN_queue_cwr(tp);
 	tcp_moderate_cwnd(tp);
 }
 
@@ -2929,6 +2939,7 @@
 					   opt_rx->sack_ok) {
 						TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th;
 					}
+					break;
 #ifdef CONFIG_TCP_MD5SIG
 				case TCPOPT_MD5SIG:
 					/*
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 5a3e7f8..3f5f742 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -192,8 +192,11 @@
 			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
 			       IPPROTO_TCP,
 			       inet->sport, usin->sin_port, sk, 1);
-	if (tmp < 0)
+	if (tmp < 0) {
+		if (tmp == -ENETUNREACH)
+			IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
 		return tmp;
+	}
 
 	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
 		ip_rt_put(rt);
@@ -702,6 +705,8 @@
 				      ip_hdr(skb)->saddr, /* XXX */
 				      arg.iov[0].iov_len, IPPROTO_TCP, 0);
 	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+	if (twsk)
+		arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
 
 	ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
 
@@ -873,6 +878,7 @@
 				kfree(newkey);
 				return -ENOMEM;
 			}
+			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
 		}
 		if (tcp_alloc_md5sig_pool() == NULL) {
 			kfree(newkey);
@@ -1002,7 +1008,7 @@
 			return -EINVAL;
 
 		tp->md5sig_info = p;
-
+		sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
 	}
 
 	newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
@@ -2039,10 +2045,7 @@
 		struct hlist_node *node;
 		struct inet_timewait_sock *tw;
 
-		/* We can reschedule _before_ having picked the target: */
-		cond_resched_softirq();
-
-		read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+		read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 		sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
 			if (sk->sk_family != st->family) {
 				continue;
@@ -2059,7 +2062,7 @@
 			rc = tw;
 			goto out;
 		}
-		read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+		read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 		st->state = TCP_SEQ_STATE_ESTABLISHED;
 	}
 out:
@@ -2086,14 +2089,11 @@
 			cur = tw;
 			goto out;
 		}
-		read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+		read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 		st->state = TCP_SEQ_STATE_ESTABLISHED;
 
-		/* We can reschedule between buckets: */
-		cond_resched_softirq();
-
 		if (++st->bucket < tcp_hashinfo.ehash_size) {
-			read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+			read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 			sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
 		} else {
 			cur = NULL;
@@ -2138,7 +2138,6 @@
 
 	if (!rc) {
 		inet_listen_unlock(&tcp_hashinfo);
-		local_bh_disable();
 		st->state = TCP_SEQ_STATE_ESTABLISHED;
 		rc	  = established_get_idx(seq, pos);
 	}
@@ -2171,7 +2170,6 @@
 		rc = listening_get_next(seq, v);
 		if (!rc) {
 			inet_listen_unlock(&tcp_hashinfo);
-			local_bh_disable();
 			st->state = TCP_SEQ_STATE_ESTABLISHED;
 			rc	  = established_get_first(seq);
 		}
@@ -2203,8 +2201,7 @@
 	case TCP_SEQ_STATE_TIME_WAIT:
 	case TCP_SEQ_STATE_ESTABLISHED:
 		if (v)
-			read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
-		local_bh_enable();
+			read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 		break;
 	}
 }
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
index 43294ad..e49836c 100644
--- a/net/ipv4/tcp_lp.c
+++ b/net/ipv4/tcp_lp.c
@@ -266,7 +266,8 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct lp *lp = inet_csk_ca(sk);
 
-	tcp_lp_rtt_sample(sk,  ktime_to_us(net_timedelta(last)));
+	if (!ktime_equal(last, net_invalid_timestamp()))
+		tcp_lp_rtt_sample(sk,  ktime_to_us(net_timedelta(last)));
 
 	/* calc inference */
 	if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 53232dd..20aea15 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -699,6 +699,14 @@
 			tp->fackets_out -= diff;
 			if ((int)tp->fackets_out < 0)
 				tp->fackets_out = 0;
+			/* SACK fastpath might overwrite it unless dealt with */
+			if (tp->fastpath_skb_hint != NULL &&
+			    after(TCP_SKB_CB(tp->fastpath_skb_hint)->seq,
+				  TCP_SKB_CB(skb)->seq)) {
+				tp->fastpath_cnt_hint -= diff;
+				if ((int)tp->fastpath_cnt_hint < 0)
+					tp->fastpath_cnt_hint = 0;
+			}
 		}
 	}
 
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 3938d5d..f37d592 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -6,8 +6,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; either version 2 of the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,23 +24,22 @@
 #include <linux/tcp.h>
 #include <linux/proc_fs.h>
 #include <linux/module.h>
-#include <linux/kfifo.h>
 #include <linux/ktime.h>
 #include <linux/time.h>
-#include <linux/vmalloc.h>
 
 #include <net/tcp.h>
 
 MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
 MODULE_DESCRIPTION("TCP cwnd snooper");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("1.1");
 
 static int port __read_mostly = 0;
 MODULE_PARM_DESC(port, "Port to match (0=all)");
 module_param(port, int, 0);
 
-static int bufsize __read_mostly = 64*1024;
-MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
+static int bufsize __read_mostly = 4096;
+MODULE_PARM_DESC(bufsize, "Log buffer size in packets (4096)");
 module_param(bufsize, int, 0);
 
 static int full __read_mostly;
@@ -50,36 +48,38 @@
 
 static const char procname[] = "tcpprobe";
 
-struct {
-	struct kfifo	*fifo;
+struct tcp_log {
+	ktime_t tstamp;
+	__be32	saddr, daddr;
+	__be16	sport, dport;
+	u16	length;
+	u32	snd_nxt;
+	u32	snd_una;
+	u32	snd_wnd;
+	u32	snd_cwnd;
+	u32	ssthresh;
+	u32	srtt;
+};
+
+static struct {
 	spinlock_t	lock;
 	wait_queue_head_t wait;
 	ktime_t		start;
 	u32		lastcwnd;
-} tcpw;
 
-/*
- * Print to log with timestamps.
- * FIXME: causes an extra copy
- */
-static void printl(const char *fmt, ...)
+	unsigned long	head, tail;
+	struct tcp_log	*log;
+} tcp_probe;
+
+
+static inline int tcp_probe_used(void)
 {
-	va_list args;
-	int len;
-	struct timespec tv;
-	char tbuf[256];
+	return (tcp_probe.head - tcp_probe.tail) % bufsize;
+}
 
-	va_start(args, fmt);
-	/* want monotonic time since start of tcp_probe */
-	tv = ktime_to_timespec(ktime_sub(ktime_get(), tcpw.start));
-
-	len = sprintf(tbuf, "%lu.%09lu ",
-		      (unsigned long) tv.tv_sec, (unsigned long) tv.tv_nsec);
-	len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
-	va_end(args);
-
-	kfifo_put(tcpw.fifo, tbuf, len);
-	wake_up(&tcpw.wait);
+static inline int tcp_probe_avail(void)
+{
+	return bufsize - tcp_probe_used();
 }
 
 /*
@@ -94,63 +94,118 @@
 
 	/* Only update if port matches */
 	if ((port == 0 || ntohs(inet->dport) == port || ntohs(inet->sport) == port)
-	    && (full || tp->snd_cwnd != tcpw.lastcwnd)) {
-		printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u\n",
-		       NIPQUAD(inet->saddr), ntohs(inet->sport),
-		       NIPQUAD(inet->daddr), ntohs(inet->dport),
-		       skb->len, tp->snd_nxt, tp->snd_una,
-		       tp->snd_cwnd, tcp_current_ssthresh(sk),
-		       tp->snd_wnd, tp->srtt >> 3);
-		tcpw.lastcwnd = tp->snd_cwnd;
+	    && (full || tp->snd_cwnd != tcp_probe.lastcwnd)) {
+
+		spin_lock(&tcp_probe.lock);
+		/* If log fills, just silently drop */
+		if (tcp_probe_avail() > 1) {
+			struct tcp_log *p = tcp_probe.log + tcp_probe.head;
+
+			p->tstamp = ktime_get();
+			p->saddr = inet->saddr;
+			p->sport = inet->sport;
+			p->daddr = inet->daddr;
+			p->dport = inet->dport;
+			p->length = skb->len;
+			p->snd_nxt = tp->snd_nxt;
+			p->snd_una = tp->snd_una;
+			p->snd_cwnd = tp->snd_cwnd;
+			p->snd_wnd = tp->snd_wnd;
+			p->ssthresh = tcp_current_ssthresh(sk);
+			p->srtt = tp->srtt >> 3;
+
+			tcp_probe.head = (tcp_probe.head + 1) % bufsize;
+		}
+		tcp_probe.lastcwnd = tp->snd_cwnd;
+		spin_unlock(&tcp_probe.lock);
+
+		wake_up(&tcp_probe.wait);
 	}
 
 	jprobe_return();
 	return 0;
 }
 
-static struct jprobe tcp_probe = {
+static struct jprobe tcp_jprobe = {
 	.kp = {
 		.symbol_name	= "tcp_rcv_established",
 	},
 	.entry	= JPROBE_ENTRY(jtcp_rcv_established),
 };
 
-
 static int tcpprobe_open(struct inode * inode, struct file * file)
 {
-	kfifo_reset(tcpw.fifo);
-	tcpw.start = ktime_get();
+	/* Reset (empty) log */
+	spin_lock_bh(&tcp_probe.lock);
+	tcp_probe.head = tcp_probe.tail = 0;
+	tcp_probe.start = ktime_get();
+	spin_unlock_bh(&tcp_probe.lock);
+
 	return 0;
 }
 
+static int tcpprobe_sprint(char *tbuf, int n)
+{
+	const struct tcp_log *p
+		= tcp_probe.log + tcp_probe.tail % bufsize;
+	struct timespec tv
+		= ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start));
+
+	return snprintf(tbuf, n,
+			"%lu.%09lu %d.%d.%d.%d:%u %d.%d.%d.%d:%u"
+			" %d %#x %#x %u %u %u %u\n",
+			(unsigned long) tv.tv_sec,
+			(unsigned long) tv.tv_nsec,
+			NIPQUAD(p->saddr), ntohs(p->sport),
+			NIPQUAD(p->daddr), ntohs(p->dport),
+			p->length, p->snd_nxt, p->snd_una,
+			p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt);
+}
+
 static ssize_t tcpprobe_read(struct file *file, char __user *buf,
 			     size_t len, loff_t *ppos)
 {
 	int error = 0, cnt = 0;
-	unsigned char *tbuf;
 
 	if (!buf || len < 0)
 		return -EINVAL;
 
-	if (len == 0)
-		return 0;
+	while (cnt < len) {
+		char tbuf[128];
+		int width;
 
-	tbuf = vmalloc(len);
-	if (!tbuf)
-		return -ENOMEM;
+		/* Wait for data in buffer */
+		error = wait_event_interruptible(tcp_probe.wait,
+						 tcp_probe_used() > 0);
+		if (error)
+			break;
 
-	error = wait_event_interruptible(tcpw.wait,
-					 __kfifo_len(tcpw.fifo) != 0);
-	if (error)
-		goto out_free;
+		spin_lock_bh(&tcp_probe.lock);
+		if (tcp_probe.head == tcp_probe.tail) {
+			/* multiple readers race? */
+			spin_unlock_bh(&tcp_probe.lock);
+			continue;
+		}
 
-	cnt = kfifo_get(tcpw.fifo, tbuf, len);
-	error = copy_to_user(buf, tbuf, cnt);
+		width = tcpprobe_sprint(tbuf, sizeof(tbuf));
 
-out_free:
-	vfree(tbuf);
+		if (width < len)
+			tcp_probe.tail = (tcp_probe.tail + 1) % bufsize;
 
-	return error ? error : cnt;
+		spin_unlock_bh(&tcp_probe.lock);
+
+		/* if record greater than space available
+		   return partial buffer (so far) */
+		if (width >= len)
+			break;
+
+		error = copy_to_user(buf + cnt, tbuf, width);
+		if (error)
+			break;
+		cnt += width;
+	}
+
+	return cnt == 0 ? error : cnt;
 }
 
 static const struct file_operations tcpprobe_fops = {
@@ -163,34 +218,37 @@
 {
 	int ret = -ENOMEM;
 
-	init_waitqueue_head(&tcpw.wait);
-	spin_lock_init(&tcpw.lock);
-	tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock);
-	if (IS_ERR(tcpw.fifo))
-		return PTR_ERR(tcpw.fifo);
+	init_waitqueue_head(&tcp_probe.wait);
+	spin_lock_init(&tcp_probe.lock);
+
+	if (bufsize < 0)
+		return -EINVAL;
+
+	tcp_probe.log = kcalloc(sizeof(struct tcp_log), bufsize, GFP_KERNEL);
+	if (!tcp_probe.log)
+		goto err0;
 
 	if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
 		goto err0;
 
-	ret = register_jprobe(&tcp_probe);
+	ret = register_jprobe(&tcp_jprobe);
 	if (ret)
 		goto err1;
 
-	pr_info("TCP watch registered (port=%d)\n", port);
+	pr_info("TCP probe registered (port=%d)\n", port);
 	return 0;
  err1:
 	proc_net_remove(procname);
  err0:
-	kfifo_free(tcpw.fifo);
+	kfree(tcp_probe.log);
 	return ret;
 }
 module_init(tcpprobe_init);
 
 static __exit void tcpprobe_exit(void)
 {
-	kfifo_free(tcpw.fifo);
 	proc_net_remove(procname);
-	unregister_jprobe(&tcp_probe);
-
+	unregister_jprobe(&tcp_jprobe);
+	kfree(tcp_probe.log);
 }
 module_exit(tcpprobe_exit);
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 2ca97b2..e9b151b 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -78,9 +78,7 @@
 	if (sk->sk_err_soft)
 		orphans <<= 1;
 
-	if (orphans >= sysctl_tcp_max_orphans ||
-	    (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
-	     atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+	if (tcp_too_many_orphans(sk, orphans)) {
 		if (net_ratelimit())
 			printk(KERN_INFO "Out of socket memory\n");
 
@@ -294,9 +292,9 @@
 		 * we cannot allow such beasts to hang infinitely.
 		 */
 #ifdef TCP_DEBUG
-		if (net_ratelimit()) {
+		if (1) {
 			struct inet_sock *inet = inet_sk(sk);
-			printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
+			LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
 			       NIPQUAD(inet->daddr), ntohs(inet->dport),
 			       inet->num, tp->snd_una, tp->snd_nxt);
 		}
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index 73e19cf..e218a51 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -117,6 +117,9 @@
 	struct vegas *vegas = inet_csk_ca(sk);
 	u32 vrtt;
 
+	if (ktime_equal(last, net_invalid_timestamp()))
+		return;
+
 	/* Never allow zero rtt or baseRTT */
 	vrtt = ktime_to_us(net_timedelta(last)) + 1;
 
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
index 9edb340..ec854cc 100644
--- a/net/ipv4/tcp_veno.c
+++ b/net/ipv4/tcp_veno.c
@@ -74,6 +74,9 @@
 	struct veno *veno = inet_csk_ca(sk);
 	u32 vrtt;
 
+	if (ktime_equal(last, net_invalid_timestamp()))
+		return;
+
 	/* Never allow zero rtt or baseRTT */
 	vrtt = ktime_to_us(net_timedelta(last)) + 1;
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 4c7e95f..2835535 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -70,6 +70,7 @@
  *	Alexey Kuznetsov:		allow both IPv4 and IPv6 sockets to bind
  *					a single port at the same time.
  *	Derek Atkins <derek@ihtfp.com>: Add Encapulation Support
+ *	James Chapman		:	Add L2TP encapsulation type.
  *
  *
  *		This program is free software; you can redistribute it and/or
@@ -114,36 +115,14 @@
 
 static int udp_port_rover;
 
-/*
- * Note about this hash function :
- * Typical use is probably daddr = 0, only dport is going to vary hash
- */
-static inline unsigned int udp_hash_port(__u16 port)
-{
-	return port;
-}
-
-static inline int __udp_lib_port_inuse(unsigned int hash, int port,
-				       const struct sock *this_sk,
-				       struct hlist_head udptable[],
-				       const struct udp_get_port_ops *ops)
+static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
 {
 	struct sock *sk;
 	struct hlist_node *node;
-	struct inet_sock *inet;
 
-	sk_for_each(sk, node, &udptable[hash & (UDP_HTABLE_SIZE - 1)]) {
-		if (sk->sk_hash != hash)
-			continue;
-		inet = inet_sk(sk);
-		if (inet->num != port)
-			continue;
-		if (this_sk) {
-			if (ops->saddr_cmp(sk, this_sk))
-				return 1;
-		} else if (ops->saddr_any(sk))
+	sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
+		if (sk->sk_hash == num)
 			return 1;
-	}
 	return 0;
 }
 
@@ -154,16 +133,16 @@
  *  @snum:        port number to look up
  *  @udptable:    hash list table, must be of UDP_HTABLE_SIZE
  *  @port_rover:  pointer to record of last unallocated port
- *  @ops:         AF-dependent address operations
+ *  @saddr_comp:  AF-dependent comparison of bound local IP addresses
  */
 int __udp_lib_get_port(struct sock *sk, unsigned short snum,
 		       struct hlist_head udptable[], int *port_rover,
-		       const struct udp_get_port_ops *ops)
+		       int (*saddr_comp)(const struct sock *sk1,
+					 const struct sock *sk2 )    )
 {
 	struct hlist_node *node;
 	struct hlist_head *head;
 	struct sock *sk2;
-	unsigned int hash;
 	int    error = 1;
 
 	write_lock_bh(&udp_hash_lock);
@@ -178,8 +157,7 @@
 		for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
 			int size;
 
-			hash = ops->hash_port_and_rcv_saddr(result, sk);
-			head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+			head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
 			if (hlist_empty(head)) {
 				if (result > sysctl_local_port_range[1])
 					result = sysctl_local_port_range[0] +
@@ -204,16 +182,7 @@
 				result = sysctl_local_port_range[0]
 					+ ((result - sysctl_local_port_range[0]) &
 					   (UDP_HTABLE_SIZE - 1));
-			hash = udp_hash_port(result);
-			if (__udp_lib_port_inuse(hash, result,
-						 NULL, udptable, ops))
-				continue;
-			if (ops->saddr_any(sk))
-				break;
-
-			hash = ops->hash_port_and_rcv_saddr(result, sk);
-			if (! __udp_lib_port_inuse(hash, result,
-						   sk, udptable, ops))
+			if (! __udp_lib_lport_inuse(result, udptable))
 				break;
 		}
 		if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@@ -221,40 +190,21 @@
 gotit:
 		*port_rover = snum = result;
 	} else {
-		hash = udp_hash_port(snum);
-		head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
 
 		sk_for_each(sk2, node, head)
-			if (sk2->sk_hash == hash &&
-			    sk2 != sk &&
-			    inet_sk(sk2)->num == snum &&
-			    (!sk2->sk_reuse || !sk->sk_reuse) &&
-			    (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
-			     sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
-			    ops->saddr_cmp(sk, sk2))
+			if (sk2->sk_hash == snum                             &&
+			    sk2 != sk                                        &&
+			    (!sk2->sk_reuse        || !sk->sk_reuse)         &&
+			    (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
+			     || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+			    (*saddr_comp)(sk, sk2)                             )
 				goto fail;
-
-		if (!ops->saddr_any(sk)) {
-			hash = ops->hash_port_and_rcv_saddr(snum, sk);
-			head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
-
-			sk_for_each(sk2, node, head)
-				if (sk2->sk_hash == hash &&
-				    sk2 != sk &&
-				    inet_sk(sk2)->num == snum &&
-				    (!sk2->sk_reuse || !sk->sk_reuse) &&
-				    (!sk2->sk_bound_dev_if ||
-				     !sk->sk_bound_dev_if ||
-				     sk2->sk_bound_dev_if ==
-				     sk->sk_bound_dev_if) &&
-				    ops->saddr_cmp(sk, sk2))
-					goto fail;
-		}
 	}
 	inet_sk(sk)->num = snum;
-	sk->sk_hash = hash;
+	sk->sk_hash = snum;
 	if (sk_unhashed(sk)) {
-		head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
 		sk_add_node(sk, head);
 		sock_prot_inc_use(sk->sk_prot);
 	}
@@ -265,12 +215,12 @@
 }
 
 int udp_get_port(struct sock *sk, unsigned short snum,
-		 const struct udp_get_port_ops *ops)
+			int (*scmp)(const struct sock *, const struct sock *))
 {
-	return  __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops);
+	return  __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
 }
 
-static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
 {
 	struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
 
@@ -279,33 +229,9 @@
 		   inet1->rcv_saddr == inet2->rcv_saddr      ));
 }
 
-static int ipv4_rcv_saddr_any(const struct sock *sk)
-{
-	return !inet_sk(sk)->rcv_saddr;
-}
-
-static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr)
-{
-	addr ^= addr >> 16;
-	addr ^= addr >> 8;
-	return port ^ addr;
-}
-
-static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port,
-						 const struct sock *sk)
-{
-	return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr);
-}
-
-const struct udp_get_port_ops udp_ipv4_ops = {
-	.saddr_cmp = ipv4_rcv_saddr_equal,
-	.saddr_any = ipv4_rcv_saddr_any,
-	.hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr,
-};
-
 static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
 {
-	return udp_get_port(sk, snum, &udp_ipv4_ops);
+	return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
 }
 
 /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
@@ -317,77 +243,63 @@
 {
 	struct sock *sk, *result = NULL;
 	struct hlist_node *node;
-	unsigned int hash, hashwild;
-	int score, best = -1, hport = ntohs(dport);
-
-	hash = ipv4_hash_port_and_addr(hport, daddr);
-	hashwild = udp_hash_port(hport);
+	unsigned short hnum = ntohs(dport);
+	int badness = -1;
 
 	read_lock(&udp_hash_lock);
-
-lookup:
-
-	sk_for_each(sk, node, &udptable[hash & (UDP_HTABLE_SIZE - 1)]) {
+	sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
 		struct inet_sock *inet = inet_sk(sk);
 
-		if (sk->sk_hash != hash || ipv6_only_sock(sk) ||
-			inet->num != hport)
-			continue;
-
-		score = (sk->sk_family == PF_INET ? 1 : 0);
-		if (inet->rcv_saddr) {
-			if (inet->rcv_saddr != daddr)
-				continue;
-			score+=2;
-		}
-		if (inet->daddr) {
-			if (inet->daddr != saddr)
-				continue;
-			score+=2;
-		}
-		if (inet->dport) {
-			if (inet->dport != sport)
-				continue;
-			score+=2;
-		}
-		if (sk->sk_bound_dev_if) {
-			if (sk->sk_bound_dev_if != dif)
-				continue;
-			score+=2;
-		}
-		if (score == 9) {
-			result = sk;
-			goto found;
-		} else if (score > best) {
-			result = sk;
-			best = score;
+		if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
+			int score = (sk->sk_family == PF_INET ? 1 : 0);
+			if (inet->rcv_saddr) {
+				if (inet->rcv_saddr != daddr)
+					continue;
+				score+=2;
+			}
+			if (inet->daddr) {
+				if (inet->daddr != saddr)
+					continue;
+				score+=2;
+			}
+			if (inet->dport) {
+				if (inet->dport != sport)
+					continue;
+				score+=2;
+			}
+			if (sk->sk_bound_dev_if) {
+				if (sk->sk_bound_dev_if != dif)
+					continue;
+				score+=2;
+			}
+			if (score == 9) {
+				result = sk;
+				break;
+			} else if (score > badness) {
+				result = sk;
+				badness = score;
+			}
 		}
 	}
-
-	if (hash != hashwild) {
-		hash = hashwild;
-		goto lookup;
-	}
-found:
 	if (result)
 		sock_hold(result);
 	read_unlock(&udp_hash_lock);
 	return result;
 }
 
-static inline struct sock *udp_v4_mcast_next(struct sock *sk, unsigned int hnum,
-					     int hport, __be32 loc_addr,
+static inline struct sock *udp_v4_mcast_next(struct sock *sk,
+					     __be16 loc_port, __be32 loc_addr,
 					     __be16 rmt_port, __be32 rmt_addr,
 					     int dif)
 {
 	struct hlist_node *node;
 	struct sock *s = sk;
+	unsigned short hnum = ntohs(loc_port);
 
 	sk_for_each_from(s, node) {
 		struct inet_sock *inet = inet_sk(s);
 
 		if (s->sk_hash != hnum					||
-		    inet->num != hport					||
 		    (inet->daddr && inet->daddr != rmt_addr)		||
 		    (inet->dport != rmt_port && inet->dport)		||
 		    (inet->rcv_saddr && inet->rcv_saddr != loc_addr)	||
@@ -722,8 +634,11 @@
 						 .dport = dport } } };
 		security_sk_classify_flow(sk, &fl);
 		err = ip_route_output_flow(&rt, &fl, sk, 1);
-		if (err)
+		if (err) {
+			if (err == -ENETUNREACH)
+				IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
 			goto out;
+		}
 
 		err = -EACCES;
 		if ((rt->rt_flags & RTCF_BROADCAST) &&
@@ -1005,104 +920,6 @@
 	return 0;
 }
 
-/* return:
- * 	1  if the UDP system should process it
- *	0  if we should drop this packet
- * 	-1 if it should get processed by xfrm4_rcv_encap
- */
-static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
-{
-#ifndef CONFIG_XFRM
-	return 1;
-#else
-	struct udp_sock *up = udp_sk(sk);
-	struct udphdr *uh;
-	struct iphdr *iph;
-	int iphlen, len;
-
-	__u8 *udpdata;
-	__be32 *udpdata32;
-	__u16 encap_type = up->encap_type;
-
-	/* if we're overly short, let UDP handle it */
-	len = skb->len - sizeof(struct udphdr);
-	if (len <= 0)
-		return 1;
-
-	/* if this is not encapsulated socket, then just return now */
-	if (!encap_type)
-		return 1;
-
-	/* If this is a paged skb, make sure we pull up
-	 * whatever data we need to look at. */
-	if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
-		return 1;
-
-	/* Now we can get the pointers */
-	uh = udp_hdr(skb);
-	udpdata = (__u8 *)uh + sizeof(struct udphdr);
-	udpdata32 = (__be32 *)udpdata;
-
-	switch (encap_type) {
-	default:
-	case UDP_ENCAP_ESPINUDP:
-		/* Check if this is a keepalive packet.  If so, eat it. */
-		if (len == 1 && udpdata[0] == 0xff) {
-			return 0;
-		} else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
-			/* ESP Packet without Non-ESP header */
-			len = sizeof(struct udphdr);
-		} else
-			/* Must be an IKE packet.. pass it through */
-			return 1;
-		break;
-	case UDP_ENCAP_ESPINUDP_NON_IKE:
-		/* Check if this is a keepalive packet.  If so, eat it. */
-		if (len == 1 && udpdata[0] == 0xff) {
-			return 0;
-		} else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
-			   udpdata32[0] == 0 && udpdata32[1] == 0) {
-
-			/* ESP Packet with Non-IKE marker */
-			len = sizeof(struct udphdr) + 2 * sizeof(u32);
-		} else
-			/* Must be an IKE packet.. pass it through */
-			return 1;
-		break;
-	}
-
-	/* At this point we are sure that this is an ESPinUDP packet,
-	 * so we need to remove 'len' bytes from the packet (the UDP
-	 * header and optional ESP marker bytes) and then modify the
-	 * protocol to ESP, and then call into the transform receiver.
-	 */
-	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-		return 0;
-
-	/* Now we can update and verify the packet length... */
-	iph = ip_hdr(skb);
-	iphlen = iph->ihl << 2;
-	iph->tot_len = htons(ntohs(iph->tot_len) - len);
-	if (skb->len < iphlen + len) {
-		/* packet is too small!?! */
-		return 0;
-	}
-
-	/* pull the data buffer up to the ESP header and set the
-	 * transport header to point to ESP.  Keep UDP on the stack
-	 * for later.
-	 */
-	__skb_pull(skb, len);
-	skb_reset_transport_header(skb);
-
-	/* modify the protocol (it's ESP!) */
-	iph->protocol = IPPROTO_ESP;
-
-	/* and let the caller know to send this into the ESP processor... */
-	return -1;
-#endif
-}
-
 /* returns:
  *  -1: error
  *   0: success
@@ -1125,28 +942,28 @@
 
 	if (up->encap_type) {
 		/*
-		 * This is an encapsulation socket, so let's see if this is
-		 * an encapsulated packet.
-		 * If it's a keepalive packet, then just eat it.
-		 * If it's an encapsulateed packet, then pass it to the
-		 * IPsec xfrm input and return the response
-		 * appropriately.  Otherwise, just fall through and
-		 * pass this up the UDP socket.
+		 * This is an encapsulation socket so pass the skb to
+		 * the socket's udp_encap_rcv() hook. Otherwise, just
+		 * fall through and pass this up the UDP socket.
+		 * up->encap_rcv() returns the following value:
+		 * =0 if skb was successfully passed to the encap
+		 *    handler or was discarded by it.
+		 * >0 if skb should be passed on to UDP.
+		 * <0 if skb should be resubmitted as proto -N
 		 */
-		int ret;
 
-		ret = udp_encap_rcv(sk, skb);
-		if (ret == 0) {
-			/* Eat the packet .. */
-			kfree_skb(skb);
-			return 0;
+		/* if we're overly short, let UDP handle it */
+		if (skb->len > sizeof(struct udphdr) &&
+		    up->encap_rcv != NULL) {
+			int ret;
+
+			ret = (*up->encap_rcv)(sk, skb);
+			if (ret <= 0) {
+				UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
+				return -ret;
+			}
 		}
-		if (ret < 0) {
-			/* process the ESP packet */
-			ret = xfrm4_rcv_encap(skb, up->encap_type);
-			UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
-			return -ret;
-		}
+
 		/* FALLTHROUGH -- it's a UDP Packet */
 	}
 
@@ -1218,45 +1035,29 @@
 				    __be32 saddr, __be32 daddr,
 				    struct hlist_head udptable[])
 {
-	struct sock *sk, *skw, *sknext;
+	struct sock *sk;
 	int dif;
-	int hport = ntohs(uh->dest);
-	unsigned int hash = ipv4_hash_port_and_addr(hport, daddr);
-	unsigned int hashwild = udp_hash_port(hport);
-
-	dif = skb->dev->ifindex;
 
 	read_lock(&udp_hash_lock);
-
-	sk = sk_head(&udptable[hash & (UDP_HTABLE_SIZE - 1)]);
-	skw = sk_head(&udptable[hashwild & (UDP_HTABLE_SIZE - 1)]);
-
-	sk = udp_v4_mcast_next(sk, hash, hport, daddr, uh->source, saddr, dif);
-	if (!sk) {
-		hash = hashwild;
-		sk = udp_v4_mcast_next(skw, hash, hport, daddr, uh->source,
-			saddr, dif);
-	}
+	sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
+	dif = skb->dev->ifindex;
+	sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
 	if (sk) {
+		struct sock *sknext = NULL;
+
 		do {
 			struct sk_buff *skb1 = skb;
-			sknext = udp_v4_mcast_next(sk_next(sk), hash, hport,
-						daddr, uh->source, saddr, dif);
-			if (!sknext && hash != hashwild) {
-				hash = hashwild;
-				sknext = udp_v4_mcast_next(skw, hash, hport,
-					daddr, uh->source, saddr, dif);
-			}
+
+			sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr,
+						   uh->source, saddr, dif);
 			if (sknext)
 				skb1 = skb_clone(skb, GFP_ATOMIC);
 
 			if (skb1) {
 				int ret = udp_queue_rcv_skb(sk, skb1);
 				if (ret > 0)
-					/*
-					 * we should probably re-process
-					 * instead of dropping packets here.
-					 */
+					/* we should probably re-process instead
+					 * of dropping packets here. */
 					kfree_skb(skb1);
 			}
 			sk = sknext;
@@ -1343,7 +1144,7 @@
 		return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
 
 	sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
-			       skb->dev->ifindex, udptable);
+			       skb->dev->ifindex, udptable        );
 
 	if (sk != NULL) {
 		int ret = udp_queue_rcv_skb(sk, skb);
@@ -1451,6 +1252,9 @@
 		case 0:
 		case UDP_ENCAP_ESPINUDP:
 		case UDP_ENCAP_ESPINUDP_NON_IKE:
+			up->encap_rcv = xfrm4_udp_encap_rcv;
+			/* FALLTHROUGH */
+		case UDP_ENCAP_L2TPINUDP:
 			up->encap_type = val;
 			break;
 		default:
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index 06d9419..820a477 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -5,14 +5,14 @@
 #include <net/protocol.h>
 #include <net/inet_common.h>
 
-extern const struct udp_get_port_ops udp_ipv4_ops;
-
 extern int  	__udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
 extern void 	__udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
 
 extern int	__udp_lib_get_port(struct sock *sk, unsigned short snum,
 				   struct hlist_head udptable[], int *port_rover,
-				   const struct udp_get_port_ops *ops);
+				   int (*)(const struct sock*,const struct sock*));
+extern int	ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
+
 
 extern int	udp_setsockopt(struct sock *sk, int level, int optname,
 			       char __user *optval, int optlen);
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index 3653b32..f34fd68 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -19,15 +19,14 @@
 static int		udplite_port_rover;
 
 int udplite_get_port(struct sock *sk, unsigned short p,
-		     const struct udp_get_port_ops *ops)
+		     int (*c)(const struct sock *, const struct sock *))
 {
-	return  __udp_lib_get_port(sk, p, udplite_hash,
-				   &udplite_port_rover, ops);
+	return  __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
 }
 
 static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
 {
-	return udplite_get_port(sk, snum, &udp_ipv4_ops);
+	return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
 }
 
 static int udplite_rcv(struct sk_buff *skb)
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 5ceca95..2fa1082 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -16,13 +16,6 @@
 #include <net/ip.h>
 #include <net/xfrm.h>
 
-int xfrm4_rcv(struct sk_buff *skb)
-{
-	return xfrm4_rcv_encap(skb, 0);
-}
-
-EXPORT_SYMBOL(xfrm4_rcv);
-
 static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 {
 	switch (nexthdr) {
@@ -53,7 +46,7 @@
 }
 #endif
 
-int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
+static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 {
 	__be32 spi, seq;
 	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
@@ -139,10 +132,8 @@
 	nf_reset(skb);
 
 	if (decaps) {
-		if (!(skb->dev->flags&IFF_LOOPBACK)) {
-			dst_release(skb->dst);
-			skb->dst = NULL;
-		}
+		dst_release(skb->dst);
+		skb->dst = NULL;
 		netif_rx(skb);
 		return 0;
 	} else {
@@ -169,3 +160,108 @@
 	kfree_skb(skb);
 	return 0;
 }
+
+/* If it's a keepalive packet, then just eat it.
+ * If it's an encapsulated packet, then pass it to the
+ * IPsec xfrm input.
+ * Returns 0 if skb passed to xfrm or was dropped.
+ * Returns >0 if skb should be passed to UDP.
+ * Returns <0 if skb should be resubmitted (-ret is protocol)
+ */
+int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	struct udp_sock *up = udp_sk(sk);
+	struct udphdr *uh;
+	struct iphdr *iph;
+	int iphlen, len;
+	int ret;
+
+	__u8 *udpdata;
+	__be32 *udpdata32;
+	__u16 encap_type = up->encap_type;
+
+	/* if this is not encapsulated socket, then just return now */
+	if (!encap_type)
+		return 1;
+
+	/* If this is a paged skb, make sure we pull up
+	 * whatever data we need to look at. */
+	len = skb->len - sizeof(struct udphdr);
+	if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
+		return 1;
+
+	/* Now we can get the pointers */
+	uh = udp_hdr(skb);
+	udpdata = (__u8 *)uh + sizeof(struct udphdr);
+	udpdata32 = (__be32 *)udpdata;
+
+	switch (encap_type) {
+	default:
+	case UDP_ENCAP_ESPINUDP:
+		/* Check if this is a keepalive packet.  If so, eat it. */
+		if (len == 1 && udpdata[0] == 0xff) {
+			goto drop;
+		} else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
+			/* ESP Packet without Non-ESP header */
+			len = sizeof(struct udphdr);
+		} else
+			/* Must be an IKE packet.. pass it through */
+			return 1;
+		break;
+	case UDP_ENCAP_ESPINUDP_NON_IKE:
+		/* Check if this is a keepalive packet.  If so, eat it. */
+		if (len == 1 && udpdata[0] == 0xff) {
+			goto drop;
+		} else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
+			   udpdata32[0] == 0 && udpdata32[1] == 0) {
+
+			/* ESP Packet with Non-IKE marker */
+			len = sizeof(struct udphdr) + 2 * sizeof(u32);
+		} else
+			/* Must be an IKE packet.. pass it through */
+			return 1;
+		break;
+	}
+
+	/* At this point we are sure that this is an ESPinUDP packet,
+	 * so we need to remove 'len' bytes from the packet (the UDP
+	 * header and optional ESP marker bytes) and then modify the
+	 * protocol to ESP, and then call into the transform receiver.
+	 */
+	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		goto drop;
+
+	/* Now we can update and verify the packet length... */
+	iph = ip_hdr(skb);
+	iphlen = iph->ihl << 2;
+	iph->tot_len = htons(ntohs(iph->tot_len) - len);
+	if (skb->len < iphlen + len) {
+		/* packet is too small!?! */
+		goto drop;
+	}
+
+	/* pull the data buffer up to the ESP header and set the
+	 * transport header to point to ESP.  Keep UDP on the stack
+	 * for later.
+	 */
+	__skb_pull(skb, len);
+	skb_reset_transport_header(skb);
+
+	/* modify the protocol (it's ESP!) */
+	iph->protocol = IPPROTO_ESP;
+
+	/* process ESP */
+	ret = xfrm4_rcv_encap(skb, encap_type);
+	return ret;
+
+drop:
+	kfree_skb(skb);
+	return 0;
+}
+
+int xfrm4_rcv(struct sk_buff *skb)
+{
+	return xfrm4_rcv_encap(skb, 0);
+}
+
+EXPORT_SYMBOL(xfrm4_rcv);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index a2f2e6a..9963700 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -85,6 +85,8 @@
 	top_iph->saddr = x->props.saddr.a4;
 	top_iph->daddr = x->id.daddr.a4;
 
+	skb->protocol = htons(ETH_P_IP);
+
 	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 	return 0;
 }
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 5685103..9275c79 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -109,3 +109,4 @@
 module_init(ipip_init);
 module_exit(ipip_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP);
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 8e5d54f..eb0b808 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -109,7 +109,7 @@
 	  If unsure, say Y.
 
 config IPV6_MIP6
-	bool "IPv6: Mobility (EXPERIMENTAL)"
+	tristate "IPv6: Mobility (EXPERIMENTAL)"
 	depends on IPV6 && EXPERIMENTAL
 	select XFRM
 	---help---
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index bb3330904..87c23a7 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -14,7 +14,6 @@
 	xfrm6_output.o
 ipv6-$(CONFIG_NETFILTER) += netfilter.o
 ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
-ipv6-$(CONFIG_IPV6_MIP6) += mip6.o
 ipv6-$(CONFIG_PROC_FS) += proc.o
 
 ipv6-objs += $(ipv6-y)
@@ -28,6 +27,7 @@
 obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
 obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
 obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
+obj-$(CONFIG_IPV6_MIP6) += mip6.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 
 obj-$(CONFIG_IPV6_SIT) += sit.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c7ea248..0601292 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1034,7 +1034,7 @@
 			}
 
 			/* Rule 4: Prefer home address */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 			if (hiscore.rule < 4) {
 				if (ifa_result->flags & IFA_F_HOMEADDRESS)
 					hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
@@ -2259,7 +2259,7 @@
 
 	switch(event) {
 	case NETDEV_REGISTER:
-		if (!idev) {
+		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
 			idev = ipv6_add_dev(dev);
 			if (!idev)
 				printk(KERN_WARNING "IPv6: add_dev failed for %s\n",
@@ -2268,6 +2268,9 @@
 		break;
 	case NETDEV_UP:
 	case NETDEV_CHANGE:
+		if (dev->flags & IFF_SLAVE)
+			break;
+
 		if (event == NETDEV_UP) {
 			if (!netif_carrier_ok(dev)) {
 				/* device is not ready yet. */
@@ -2472,6 +2475,7 @@
 		write_unlock_bh(&idev->lock);
 
 		__ipv6_ifa_notify(RTM_DELADDR, ifa);
+		atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
 		in6_ifa_put(ifa);
 
 		write_lock_bh(&idev->lock);
@@ -2782,7 +2786,7 @@
 	return 0;
 }
 
-static struct seq_operations if6_seq_ops = {
+static const struct seq_operations if6_seq_ops = {
 	.start	= if6_seq_start,
 	.next	= if6_seq_next,
 	.show	= if6_seq_show,
@@ -2832,7 +2836,7 @@
 }
 #endif	/* CONFIG_PROC_FS */
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 /* Check if address is a home address configured on any interface. */
 int ipv6_chk_home_addr(struct in6_addr *addr)
 {
@@ -2979,7 +2983,7 @@
 	return pfx;
 }
 
-static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = {
+static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
 	[IFA_ADDRESS]		= { .len = sizeof(struct in6_addr) },
 	[IFA_LOCAL]		= { .len = sizeof(struct in6_addr) },
 	[IFA_CACHEINFO]		= { .len = sizeof(struct ifa_cacheinfo) },
@@ -4240,7 +4244,6 @@
 void __exit addrconf_cleanup(void)
 {
 	struct net_device *dev;
-	struct inet6_dev *idev;
 	struct inet6_ifaddr *ifa;
 	int i;
 
@@ -4258,7 +4261,7 @@
 	 */
 
 	for_each_netdev(dev) {
-		if ((idev = __in6_dev_get(dev)) == NULL)
+		if (__in6_dev_get(dev) == NULL)
 			continue;
 		addrconf_ifdown(dev, 1);
 	}
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6dd3772..eed0937 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -58,9 +58,6 @@
 #ifdef CONFIG_IPV6_TUNNEL
 #include <net/ip6_tunnel.h>
 #endif
-#ifdef CONFIG_IPV6_MIP6
-#include <net/mip6.h>
-#endif
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -853,9 +850,6 @@
 	ipv6_frag_init();
 	ipv6_nodata_init();
 	ipv6_destopt_init();
-#ifdef CONFIG_IPV6_MIP6
-	mip6_init();
-#endif
 
 	/* Init v6 transport protocols. */
 	udpv6_init();
@@ -921,9 +915,7 @@
 
 	/* Cleanup code parts. */
 	ipv6_packet_cleanup();
-#ifdef CONFIG_IPV6_MIP6
-	mip6_fini();
-#endif
+
 	addrconf_cleanup();
 	ip6_flowlabel_cleanup();
 	ip6_route_cleanup();
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index b696c84..53f46ab 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -74,7 +74,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 /**
  *	ipv6_rearrange_destopt - rearrange IPv6 destination options header
  *	@iph: IPv6 header
@@ -132,6 +132,8 @@
 bad:
 	return;
 }
+#else
+static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {}
 #endif
 
 /**
@@ -189,10 +191,8 @@
 	while (exthdr.raw < end) {
 		switch (nexthdr) {
 		case NEXTHDR_DEST:
-#ifdef CONFIG_IPV6_MIP6
 			if (dir == XFRM_POLICY_OUT)
 				ipv6_rearrange_destopt(iph, exthdr.opth);
-#endif
 		case NEXTHDR_HOP:
 			if (!zero_out_mutable_opts(exthdr.opth)) {
 				LIMIT_NETDEBUG(
@@ -228,7 +228,7 @@
 	u8 nexthdr;
 	char tmp_base[8];
 	struct {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		struct in6_addr saddr;
 #endif
 		struct in6_addr daddr;
@@ -247,7 +247,7 @@
 	memcpy(tmp_base, top_iph, sizeof(tmp_base));
 
 	tmp_ext = NULL;
-	extlen = skb_transport_offset(skb) + sizeof(struct ipv6hdr);
+	extlen = skb_transport_offset(skb) - sizeof(struct ipv6hdr);
 	if (extlen) {
 		extlen += sizeof(*tmp_ext);
 		tmp_ext = kmalloc(extlen, GFP_ATOMIC);
@@ -255,7 +255,7 @@
 			err = -ENOMEM;
 			goto error;
 		}
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		memcpy(tmp_ext, &top_iph->saddr, extlen);
 #else
 		memcpy(tmp_ext, &top_iph->daddr, extlen);
@@ -294,7 +294,7 @@
 
 	memcpy(top_iph, tmp_base, sizeof(tmp_base));
 	if (tmp_ext) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		memcpy(&top_iph->saddr, tmp_ext, extlen);
 #else
 		memcpy(&top_iph->daddr, tmp_ext, extlen);
@@ -554,3 +554,4 @@
 module_exit(ah6_fini);
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 9b81264..b8c533f 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -539,7 +539,7 @@
 	return 0;
 }
 
-static struct seq_operations ac6_seq_ops = {
+static const struct seq_operations ac6_seq_ops = {
 	.start	=	ac6_seq_start,
 	.next	=	ac6_seq_next,
 	.stop	=	ac6_seq_stop,
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 403eee6..fe0f490 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -177,8 +177,12 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
-		goto out;
+	if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
+		if (err == -EREMOTE)
+			err = ip6_dst_blackhole(sk, &dst, &fl);
+		if (err < 0)
+			goto out;
+	}
 
 	/* source address lookup done in ip6_dst_lookup */
 
@@ -653,11 +657,10 @@
 			rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg);
 
 			switch (rthdr->type) {
-			case IPV6_SRCRT_TYPE_0:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 			case IPV6_SRCRT_TYPE_2:
-#endif
 				break;
+#endif
 			default:
 				err = -EINVAL;
 				goto exit_f;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 7107bb7..2db31ce 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -421,3 +421,4 @@
 module_exit(esp6_fini);
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 14be0b9..c82d4d4 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -42,7 +42,7 @@
 #include <net/ndisc.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 #include <net/xfrm.h>
 #endif
 
@@ -90,6 +90,7 @@
  bad:
 	return -1;
 }
+EXPORT_SYMBOL_GPL(ipv6_find_tlv);
 
 /*
  *	Parsing tlv encoded headers.
@@ -196,7 +197,7 @@
   Destination options header.
  *****************************/
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
 {
 	struct sk_buff *skb = *skbp;
@@ -270,7 +271,7 @@
 #endif
 
 static struct tlvtype_proc tlvprocdestopt_lst[] = {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	{
 		.type	= IPV6_TLV_HAO,
 		.func	= ipv6_dest_hao,
@@ -283,7 +284,7 @@
 {
 	struct sk_buff *skb = *skbp;
 	struct inet6_skb_parm *opt = IP6CB(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	__u16 dstbuf;
 #endif
 	struct dst_entry *dst;
@@ -298,7 +299,7 @@
 	}
 
 	opt->lastopt = opt->dst1 = skb_network_header_len(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	dstbuf = opt->dst1;
 #endif
 
@@ -308,7 +309,7 @@
 		skb = *skbp;
 		skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
 		opt = IP6CB(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		opt->nhoff = dstbuf;
 #else
 		opt->nhoff = opt->dst1;
@@ -371,22 +372,13 @@
 	struct rt0_hdr *rthdr;
 	int accept_source_route = ipv6_devconf.accept_source_route;
 
-	if (accept_source_route < 0 ||
-	    ((idev = in6_dev_get(skb->dev)) == NULL)) {
-		kfree_skb(skb);
-		return -1;
-	}
-	if (idev->cnf.accept_source_route < 0) {
+	idev = in6_dev_get(skb->dev);
+	if (idev) {
+		if (accept_source_route > idev->cnf.accept_source_route)
+			accept_source_route = idev->cnf.accept_source_route;
 		in6_dev_put(idev);
-		kfree_skb(skb);
-		return -1;
 	}
 
-	if (accept_source_route > idev->cnf.accept_source_route)
-		accept_source_route = idev->cnf.accept_source_route;
-
-	in6_dev_put(idev);
-
 	if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
 	    !pskb_may_pull(skb, (skb_transport_offset(skb) +
 				 ((skb_transport_header(skb)[1] + 1) << 3)))) {
@@ -398,24 +390,6 @@
 
 	hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
 
-	switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
-	case IPV6_SRCRT_TYPE_2:
-		break;
-#endif
-	case IPV6_SRCRT_TYPE_0:
-		if (accept_source_route > 0)
-			break;
-		kfree_skb(skb);
-		return -1;
-	default:
-		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
-				 IPSTATS_MIB_INHDRERRORS);
-		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
-				  (&hdr->type) - skb_network_header(skb));
-		return -1;
-	}
-
 	if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
 	    skb->pkt_type != PACKET_HOST) {
 		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -427,7 +401,7 @@
 looped_back:
 	if (hdr->segments_left == 0) {
 		switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		case IPV6_SRCRT_TYPE_2:
 			/* Silently discard type 2 header unless it was
 			 * processed by own
@@ -453,18 +427,10 @@
 	}
 
 	switch (hdr->type) {
-	case IPV6_SRCRT_TYPE_0:
-		if (hdr->hdrlen & 0x01) {
-			IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
-					 IPSTATS_MIB_INHDRERRORS);
-			icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
-					  ((&hdr->hdrlen) -
-					   skb_network_header(skb)));
-			return -1;
-		}
-		break;
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	case IPV6_SRCRT_TYPE_2:
+		if (accept_source_route < 0)
+			goto unknown_rh;
 		/* Silently discard invalid RTH type 2 */
 		if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
 			IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -474,6 +440,8 @@
 		}
 		break;
 #endif
+	default:
+		goto unknown_rh;
 	}
 
 	/*
@@ -520,7 +488,7 @@
 	addr += i - 1;
 
 	switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	case IPV6_SRCRT_TYPE_2:
 		if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
 				     (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
@@ -577,6 +545,12 @@
 	skb_push(skb, skb->data - skb_network_header(skb));
 	dst_input(skb);
 	return -1;
+
+unknown_rh:
+	IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
+	icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
+			  (&hdr->type) - skb_network_header(skb));
+	return -1;
 }
 
 static struct inet6_protocol rthdr_protocol = {
@@ -590,72 +564,6 @@
 		printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
 };
 
-/*
-   This function inverts received rthdr.
-   NOTE: specs allow to make it automatically only if
-   packet authenticated.
-
-   I will not discuss it here (though, I am really pissed off at
-   this stupid requirement making rthdr idea useless)
-
-   Actually, it creates severe problems  for us.
-   Embryonic requests has no associated sockets,
-   so that user have no control over it and
-   cannot not only to set reply options, but
-   even to know, that someone wants to connect
-   without success. :-(
-
-   For now we need to test the engine, so that I created
-   temporary (or permanent) backdoor.
-   If listening socket set IPV6_RTHDR to 2, then we invert header.
-						   --ANK (980729)
- */
-
-struct ipv6_txoptions *
-ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
-{
-	/* Received rthdr:
-
-	   [ H1 -> H2 -> ... H_prev ]  daddr=ME
-
-	   Inverted result:
-	   [ H_prev -> ... -> H1 ] daddr =sender
-
-	   Note, that IP output engine will rewrite this rthdr
-	   by rotating it left by one addr.
-	 */
-
-	int n, i;
-	struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
-	struct rt0_hdr *irthdr;
-	struct ipv6_txoptions *opt;
-	int hdrlen = ipv6_optlen(hdr);
-
-	if (hdr->segments_left ||
-	    hdr->type != IPV6_SRCRT_TYPE_0 ||
-	    hdr->hdrlen & 0x01)
-		return NULL;
-
-	n = hdr->hdrlen >> 1;
-	opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
-	if (opt == NULL)
-		return NULL;
-	memset(opt, 0, sizeof(*opt));
-	opt->tot_len = sizeof(*opt) + hdrlen;
-	opt->srcrt = (void*)(opt+1);
-	opt->opt_nflen = hdrlen;
-
-	memcpy(opt->srcrt, hdr, sizeof(*hdr));
-	irthdr = (struct rt0_hdr*)opt->srcrt;
-	irthdr->reserved = 0;
-	opt->srcrt->segments_left = n;
-	for (i=0; i<n; i++)
-		memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
-	return opt;
-}
-
-EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
-
 /**********************************
   Hop-by-hop options.
  **********************************/
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index fc3882c..53b3998 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -157,7 +157,7 @@
 	return 1;
 }
 
-static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = {
 	FRA_GENERIC_POLICY,
 };
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index e9bcce9..6a6714d 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -272,7 +272,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 static void mip6_addr_swap(struct sk_buff *skb)
 {
 	struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -604,7 +604,7 @@
 
 	read_lock(&raw_v6_lock);
 	if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) {
-		while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr,
+		while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr,
 					    IP6CB(skb)->iif))) {
 			rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
 			sk = sk_next(sk);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index ca08ee8..662a7d9 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -619,14 +619,6 @@
 
 	ins = &fn->leaf;
 
-	if (fn->fn_flags&RTN_TL_ROOT &&
-	    fn->leaf == &ip6_null_entry &&
-	    !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
-		fn->leaf = rt;
-		rt->u.dst.rt6_next = NULL;
-		goto out;
-	}
-
 	for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) {
 		/*
 		 *	Search for duplicates
@@ -666,7 +658,6 @@
 	 *	insert node
 	 */
 
-out:
 	rt->u.dst.rt6_next = iter;
 	*ins = rt;
 	rt->rt6i_node = fn;
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index c206a15..413a4eb 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -648,7 +648,7 @@
 	return 0;
 }
 
-static struct seq_operations ip6fl_seq_ops = {
+static const struct seq_operations ip6fl_seq_ops = {
 	.start	=	ip6fl_seq_start,
 	.next	=	ip6fl_seq_next,
 	.stop	=	ip6fl_seq_stop,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4704b5f..50d86e9 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -521,6 +521,10 @@
 	to->tc_index = from->tc_index;
 #endif
 	nf_copy(to, from);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	to->nf_trace = from->nf_trace;
+#endif
 	skb_copy_secmark(to, from);
 }
 
@@ -543,7 +547,7 @@
 			found_rhdr = 1;
 			break;
 		case NEXTHDR_DEST:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 			if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
 				break;
 #endif
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a0902fb..281aee4 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -883,8 +883,8 @@
 	 */
 	max_headroom += LL_RESERVED_SPACE(tdev);
 
-	if (skb_headroom(skb) < max_headroom ||
-	    skb_cloned(skb) || skb_shared(skb)) {
+	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
 		struct sk_buff *new_skb;
 
 		if (!(new_skb = skb_realloc_headroom(skb, max_headroom)))
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 1ee50b5..473f165 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -500,4 +500,4 @@
 MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) for IPv6 - RFC3173");
 MODULE_AUTHOR("Mitsuru KANDA <mk@linux-ipv6.org>");
 
-
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_COMP);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index aa3d07c..d684639 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -123,7 +123,7 @@
 	struct ipv6hdr *ipv6h;
 	struct inet6_protocol *ops;
 
-	if (!(features & NETIF_F_HW_CSUM))
+	if (!(features & NETIF_F_V6_CSUM))
 		features &= ~NETIF_F_SG;
 
 	if (unlikely(skb_shinfo(skb)->gso_type &
@@ -336,16 +336,12 @@
 		break;
 
 	case IPV6_RECVRTHDR:
-		if (val < 0 || val > 2)
-			goto e_inval;
-		np->rxopt.bits.srcrt = val;
+		np->rxopt.bits.srcrt = valbool;
 		retv = 0;
 		break;
 
 	case IPV6_2292RTHDR:
-		if (val < 0 || val > 2)
-			goto e_inval;
-		np->rxopt.bits.osrcrt = val;
+		np->rxopt.bits.osrcrt = valbool;
 		retv = 0;
 		break;
 
@@ -416,11 +412,10 @@
 		if (optname == IPV6_RTHDR && opt && opt->srcrt) {
 			struct ipv6_rt_hdr *rthdr = opt->srcrt;
 			switch (rthdr->type) {
-			case IPV6_SRCRT_TYPE_0:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 			case IPV6_SRCRT_TYPE_2:
-#endif
 				break;
+#endif
 			default:
 				goto sticky_done;
 			}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 3e308fb..ae98818 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2423,7 +2423,7 @@
 	return 0;
 }
 
-static struct seq_operations igmp6_mc_seq_ops = {
+static const struct seq_operations igmp6_mc_seq_ops = {
 	.start	=	igmp6_mc_seq_start,
 	.next	=	igmp6_mc_seq_next,
 	.stop	=	igmp6_mc_seq_stop,
@@ -2597,7 +2597,7 @@
 	return 0;
 }
 
-static struct seq_operations igmp6_mcf_seq_ops = {
+static const struct seq_operations igmp6_mcf_seq_ops = {
 	.start	=	igmp6_mcf_seq_start,
 	.next	=	igmp6_mcf_seq_next,
 	.stop	=	igmp6_mcf_seq_stop,
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 13b7160..8a1399c 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -30,6 +30,7 @@
 #include <net/sock.h>
 #include <net/ipv6.h>
 #include <net/ip6_checksum.h>
+#include <net/rawv6.h>
 #include <net/xfrm.h>
 #include <net/mip6.h>
 
@@ -86,7 +87,7 @@
 	return len;
 }
 
-int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
+static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
 {
 	struct ip6_mh *mh;
 
@@ -471,7 +472,7 @@
 	.remote_addr	= mip6_xfrm_addr,
 };
 
-int __init mip6_init(void)
+static int __init mip6_init(void)
 {
 	printk(KERN_INFO "Mobile IPv6\n");
 
@@ -483,18 +484,35 @@
 		printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
 		goto mip6_rthdr_xfrm_fail;
 	}
+	if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
+		printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
+		goto mip6_rawv6_mh_fail;
+	}
+
+
 	return 0;
 
+ mip6_rawv6_mh_fail:
+	xfrm_unregister_type(&mip6_rthdr_type, AF_INET6);
  mip6_rthdr_xfrm_fail:
 	xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
  mip6_destopt_xfrm_fail:
 	return -EAGAIN;
 }
 
-void __exit mip6_fini(void)
+static void __exit mip6_fini(void)
 {
+	if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
+		printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
 	if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
 		printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
 	if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
 		printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
 }
+
+module_init(mip6_init);
+module_exit(mip6_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS);
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index d8b3645..0358e606 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1062,7 +1062,7 @@
 	pref = ra_msg->icmph.icmp6_router_pref;
 	/* 10b is handled as if it were 00b (medium) */
 	if (pref == ICMPV6_ROUTER_PREF_INVALID ||
-	    in6_dev->cnf.accept_ra_rtr_pref)
+	    !in6_dev->cnf.accept_ra_rtr_pref)
 		pref = ICMPV6_ROUTER_PREF_MEDIUM;
 #endif
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 9aa6240..aeda617 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -96,13 +96,13 @@
 }
 
 /* Returns whether matches rule or not. */
-static inline int
+static inline bool
 ip6_packet_match(const struct sk_buff *skb,
 		 const char *indev,
 		 const char *outdev,
 		 const struct ip6t_ip6 *ip6info,
 		 unsigned int *protoff,
-		 int *fragoff, int *hotdrop)
+		 int *fragoff, bool *hotdrop)
 {
 	size_t i;
 	unsigned long ret;
@@ -122,7 +122,7 @@
 		dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
 			ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
 			ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
-		return 0;
+		return false;
 	}
 
 	/* Look for ifname matches; this should unroll nicely. */
@@ -136,7 +136,7 @@
 		dprintf("VIA in mismatch (%s vs %s).%s\n",
 			indev, ip6info->iniface,
 			ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
-		return 0;
+		return false;
 	}
 
 	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
@@ -149,7 +149,7 @@
 		dprintf("VIA out mismatch (%s vs %s).%s\n",
 			outdev, ip6info->outiface,
 			ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
-		return 0;
+		return false;
 	}
 
 /* ... might want to do something with class and flowlabel here ... */
@@ -162,8 +162,8 @@
 		protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
 		if (protohdr < 0) {
 			if (_frag_off == 0)
-				*hotdrop = 1;
-			return 0;
+				*hotdrop = true;
+			return false;
 		}
 		*fragoff = _frag_off;
 
@@ -174,34 +174,34 @@
 
 		if (ip6info->proto == protohdr) {
 			if(ip6info->invflags & IP6T_INV_PROTO) {
-				return 0;
+				return false;
 			}
-			return 1;
+			return true;
 		}
 
 		/* We need match for the '-p all', too! */
 		if ((ip6info->proto != 0) &&
 			!(ip6info->invflags & IP6T_INV_PROTO))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
 /* should be ip6 safe */
-static inline int
+static inline bool
 ip6_checkentry(const struct ip6t_ip6 *ipv6)
 {
 	if (ipv6->flags & ~IP6T_F_MASK) {
 		duprintf("Unknown flag bits set: %08X\n",
 			 ipv6->flags & ~IP6T_F_MASK);
-		return 0;
+		return false;
 	}
 	if (ipv6->invflags & ~IP6T_INV_MASK) {
 		duprintf("Unknown invflag bits set: %08X\n",
 			 ipv6->invflags & ~IP6T_INV_MASK);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -219,20 +219,20 @@
 }
 
 static inline
-int do_match(struct ip6t_entry_match *m,
-	     const struct sk_buff *skb,
-	     const struct net_device *in,
-	     const struct net_device *out,
-	     int offset,
-	     unsigned int protoff,
-	     int *hotdrop)
+bool do_match(struct ip6t_entry_match *m,
+	      const struct sk_buff *skb,
+	      const struct net_device *in,
+	      const struct net_device *out,
+	      int offset,
+	      unsigned int protoff,
+	      bool *hotdrop)
 {
 	/* Stop iteration if it doesn't match */
 	if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
 				      offset, protoff, hotdrop))
-		return 1;
+		return true;
 	else
-		return 0;
+		return false;
 }
 
 static inline struct ip6t_entry *
@@ -241,6 +241,113 @@
 	return (struct ip6t_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ip6t_ip6 *ipv6)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ipv6); i++)
+		if (((char *)ipv6)[i])
+			break;
+
+	return (i == sizeof(*ipv6));
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+/* This cries for unification! */
+static const char *hooknames[] = {
+	[NF_IP6_PRE_ROUTING]		= "PREROUTING",
+	[NF_IP6_LOCAL_IN]		= "INPUT",
+	[NF_IP6_FORWARD]		= "FORWARD",
+	[NF_IP6_LOCAL_OUT]		= "OUTPUT",
+	[NF_IP6_POST_ROUTING]		= "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP6_TRACE_COMMENT_RULE,
+	NF_IP6_TRACE_COMMENT_RETURN,
+	NF_IP6_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP6_TRACE_COMMENT_RULE]	= "rule",
+	[NF_IP6_TRACE_COMMENT_RETURN]	= "return",
+	[NF_IP6_TRACE_COMMENT_POLICY]	= "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ip6t_standard_target *t = (void *)ip6t_get_target(s);
+
+	if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ip6t_entry)
+		   && strcmp(t->target.u.kernel.target->name,
+			     IP6T_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+		   && unconditional(&s->ipv6)) {
+			/* Tail of chains: STANDARD target (return/policy) */
+			*comment = *chainname == hookname
+				? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY]
+				: (char *)comments[NF_IP6_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+			 unsigned int hook,
+			 const struct net_device *in,
+			 const struct net_device *out,
+			 char *tablename,
+			 struct xt_table_info *private,
+			 struct ip6t_entry *e)
+{
+	void *table_base;
+	struct ip6t_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE];
+
+	IP6T_ENTRY_ITERATE(root,
+			   private->size - private->hook_entry[hook],
+			   get_chainname_rulenum,
+			   e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ip6t_do_table(struct sk_buff **pskb,
@@ -252,7 +359,7 @@
 	static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
 	int offset = 0;
 	unsigned int protoff = 0;
-	int hotdrop = 0;
+	bool hotdrop = false;
 	/* Initializing verdict to NF_DROP keeps gcc happy. */
 	unsigned int verdict = NF_DROP;
 	const char *indev, *outdev;
@@ -298,6 +405,14 @@
 
 			t = ip6t_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+			/* The packet is traced: log it */
+			if (unlikely((*pskb)->nf_trace))
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+#endif
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -377,19 +492,6 @@
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ip6t_ip6 *ipv6)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ipv6); i++)
-		if (((char *)ipv6)[i])
-			break;
-
-	return (i == sizeof(*ipv6));
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
@@ -1282,16 +1384,16 @@
 }
 
 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
-static inline int
+static inline bool
 icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
 		     u_int8_t type, u_int8_t code,
-		     int invert)
+		     bool invert)
 {
 	return (type == test_type && code >= min_code && code <= max_code)
 		^ invert;
 }
 
-static int
+static bool
 icmp6_match(const struct sk_buff *skb,
 	   const struct net_device *in,
 	   const struct net_device *out,
@@ -1299,22 +1401,22 @@
 	   const void *matchinfo,
 	   int offset,
 	   unsigned int protoff,
-	   int *hotdrop)
+	   bool *hotdrop)
 {
 	struct icmp6hdr _icmp, *ic;
 	const struct ip6t_icmp *icmpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
 	if (ic == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil ICMP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return icmp6_type_code_match(icmpinfo->type,
@@ -1325,7 +1427,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 icmp6_checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_match *match,
@@ -1339,13 +1441,13 @@
 }
 
 /* The built-in targets: standard (NULL) and error. */
-static struct xt_target ip6t_standard_target = {
+static struct xt_target ip6t_standard_target __read_mostly = {
 	.name		= IP6T_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= AF_INET6,
 };
 
-static struct xt_target ip6t_error_target = {
+static struct xt_target ip6t_error_target __read_mostly = {
 	.name		= IP6T_ERROR_TARGET,
 	.target		= ip6t_error,
 	.targetsize	= IP6T_FUNCTION_MAXNAMELEN,
@@ -1362,7 +1464,7 @@
 	.get		= do_ip6t_get_ctl,
 };
 
-static struct xt_match icmp6_matchstruct = {
+static struct xt_match icmp6_matchstruct __read_mostly = {
 	.name		= "icmp6",
 	.match		= &icmp6_match,
 	.matchsize	= sizeof(struct ip6t_icmp),
@@ -1395,7 +1497,7 @@
 	if (ret < 0)
 		goto err5;
 
-	printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
+	printk(KERN_INFO "ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
 	return 0;
 
 err5:
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 4115a57..ad4d943 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -58,28 +58,28 @@
 	return XT_CONTINUE;
 }
 
-static int ip6t_hl_checkentry(const char *tablename,
+static bool ip6t_hl_checkentry(const char *tablename,
 		const void *entry,
 		const struct xt_target *target,
 		void *targinfo,
 		unsigned int hook_mask)
 {
-	struct ip6t_HL_info *info = targinfo;
+	const struct ip6t_HL_info *info = targinfo;
 
 	if (info->mode > IP6T_HL_MAXMODE) {
 		printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
 			info->mode);
-		return 0;
+		return false;
 	}
-	if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
+	if (info->mode != IP6T_HL_SET && info->hop_limit == 0) {
 		printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
 			"make sense with value 0\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ip6t_HL = {
+static struct xt_target ip6t_HL __read_mostly = {
 	.name 		= "HL",
 	.family		= AF_INET6,
 	.target		= ip6t_hl_target,
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 5bb9cd3..b05327e 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -32,12 +32,6 @@
 #include <net/route.h>
 #include <linux/netfilter_ipv6/ip6t_LOG.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Use lock to serialize, so printks don't overlap */
 static DEFINE_SPINLOCK(log_lock);
 
@@ -48,7 +42,8 @@
 {
 	u_int8_t currenthdr;
 	int fragment;
-	struct ipv6hdr _ip6h, *ih;
+	struct ipv6hdr _ip6h;
+	const struct ipv6hdr *ih;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
 	unsigned int logflags;
@@ -78,7 +73,8 @@
 	ptr = ip6hoff + sizeof(struct ipv6hdr);
 	currenthdr = ih->nexthdr;
 	while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
-		struct ipv6_opt_hdr _hdr, *hp;
+		struct ipv6_opt_hdr _hdr;
+		const struct ipv6_opt_hdr *hp;
 
 		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
 		if (hp == NULL) {
@@ -92,7 +88,8 @@
 
 		switch (currenthdr) {
 		case IPPROTO_FRAGMENT: {
-			struct frag_hdr _fhdr, *fh;
+			struct frag_hdr _fhdr;
+			const struct frag_hdr *fh;
 
 			printk("FRAG:");
 			fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
@@ -131,7 +128,8 @@
 		/* Max Length */
 		case IPPROTO_AH:
 			if (logflags & IP6T_LOG_IPOPT) {
-				struct ip_auth_hdr _ahdr, *ah;
+				struct ip_auth_hdr _ahdr;
+				const struct ip_auth_hdr *ah;
 
 				/* Max length: 3 "AH " */
 				printk("AH ");
@@ -162,7 +160,8 @@
 			break;
 		case IPPROTO_ESP:
 			if (logflags & IP6T_LOG_IPOPT) {
-				struct ip_esp_hdr _esph, *eh;
+				struct ip_esp_hdr _esph;
+				const struct ip_esp_hdr *eh;
 
 				/* Max length: 4 "ESP " */
 				printk("ESP ");
@@ -202,7 +201,8 @@
 
 	switch (currenthdr) {
 	case IPPROTO_TCP: {
-		struct tcphdr _tcph, *th;
+		struct tcphdr _tcph;
+		const struct tcphdr *th;
 
 		/* Max length: 10 "PROTO=TCP " */
 		printk("PROTO=TCP ");
@@ -250,7 +250,8 @@
 
 		if ((logflags & IP6T_LOG_TCPOPT)
 		    && th->doff * 4 > sizeof(struct tcphdr)) {
-			u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
+			u_int8_t _opt[60 - sizeof(struct tcphdr)];
+			const u_int8_t *op;
 			unsigned int i;
 			unsigned int optsize = th->doff * 4
 					       - sizeof(struct tcphdr);
@@ -273,7 +274,8 @@
 	}
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE: {
-		struct udphdr _udph, *uh;
+		struct udphdr _udph;
+		const struct udphdr *uh;
 
 		if (currenthdr == IPPROTO_UDP)
 			/* Max length: 10 "PROTO=UDP "     */
@@ -298,7 +300,8 @@
 		break;
 	}
 	case IPPROTO_ICMPV6: {
-		struct icmp6hdr _icmp6h, *ic;
+		struct icmp6hdr _icmp6h;
+		const struct icmp6hdr *ic;
 
 		/* Max length: 13 "PROTO=ICMPv6 " */
 		printk("PROTO=ICMPv6 ");
@@ -448,27 +451,27 @@
 }
 
 
-static int ip6t_log_checkentry(const char *tablename,
-			       const void *entry,
-			       const struct xt_target *target,
-			       void *targinfo,
-			       unsigned int hook_mask)
+static bool ip6t_log_checkentry(const char *tablename,
+				const void *entry,
+				const struct xt_target *target,
+				void *targinfo,
+				unsigned int hook_mask)
 {
 	const struct ip6t_log_info *loginfo = targinfo;
 
 	if (loginfo->level >= 8) {
-		DEBUGP("LOG: level %u >= 8\n", loginfo->level);
-		return 0;
+		pr_debug("LOG: level %u >= 8\n", loginfo->level);
+		return false;
 	}
 	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
-		DEBUGP("LOG: prefix term %i\n",
-		       loginfo->prefix[sizeof(loginfo->prefix)-1]);
-		return 0;
+		pr_debug("LOG: prefix term %i\n",
+			 loginfo->prefix[sizeof(loginfo->prefix)-1]);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ip6t_log_reg = {
+static struct xt_target ip6t_log_reg __read_mostly = {
 	.name 		= "LOG",
 	.family		= AF_INET6,
 	.target 	= ip6t_log_target,
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index cb3d241..2f487cd 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -34,12 +34,6 @@
 MODULE_DESCRIPTION("IP6 tables REJECT target module");
 MODULE_LICENSE("GPL");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Send RST reply */
 static void send_reset(struct sk_buff *oldskb)
 {
@@ -54,7 +48,7 @@
 
 	if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
 	    (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
-		DEBUGP("ip6t_REJECT: addr is not unicast.\n");
+		pr_debug("ip6t_REJECT: addr is not unicast.\n");
 		return;
 	}
 
@@ -62,16 +56,17 @@
 	tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto);
 
 	if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
-		DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
+		pr_debug("ip6t_REJECT: Can't get TCP header.\n");
 		return;
 	}
 
 	otcplen = oldskb->len - tcphoff;
 
 	/* IP header checks: fragment, too short. */
-	if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
-		DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
-			proto, otcplen);
+	if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
+		pr_debug("ip6t_REJECT: proto(%d) != IPPROTO_TCP, "
+			 "or too short. otcplen = %d\n",
+			 proto, otcplen);
 		return;
 	}
 
@@ -80,14 +75,14 @@
 
 	/* No RST for RST. */
 	if (otcph.rst) {
-		DEBUGP("ip6t_REJECT: RST is set\n");
+		pr_debug("ip6t_REJECT: RST is set\n");
 		return;
 	}
 
 	/* Check checksum. */
 	if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
 			    skb_checksum(oldskb, tcphoff, otcplen, 0))) {
-		DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
+		pr_debug("ip6t_REJECT: TCP checksum is invalid\n");
 		return;
 	}
 
@@ -159,7 +154,7 @@
 	tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
 				      &ipv6_hdr(nskb)->daddr,
 				      sizeof(struct tcphdr), IPPROTO_TCP,
-				      csum_partial((char *)tcph,
+				      csum_partial(tcph,
 						   sizeof(struct tcphdr), 0));
 
 	nf_ct_attach(nskb, oldskb);
@@ -186,7 +181,7 @@
 {
 	const struct ip6t_reject_info *reject = targinfo;
 
-	DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
+	pr_debug("%s: medium point\n", __FUNCTION__);
 	/* WARNING: This code causes reentry within ip6tables.
 	   This means that the ip6tables jump stack is now crap.  We
 	   must return an absolute verdict. --RR */
@@ -221,30 +216,30 @@
 	return NF_DROP;
 }
 
-static int check(const char *tablename,
-		 const void *entry,
-		 const struct xt_target *target,
-		 void *targinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *entry,
+		  const struct xt_target *target,
+		  void *targinfo,
+		  unsigned int hook_mask)
 {
 	const struct ip6t_reject_info *rejinfo = targinfo;
 	const struct ip6t_entry *e = entry;
 
 	if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
 		printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
-		return 0;
+		return false;
 	} else if (rejinfo->with == IP6T_TCP_RESET) {
 		/* Must specify that it's a TCP packet */
 		if (e->ipv6.proto != IPPROTO_TCP
 		    || (e->ipv6.invflags & XT_INV_PROTO)) {
-			DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
-			return 0;
+			printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
+			return false;
 		}
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ip6t_reject_reg = {
+static struct xt_target ip6t_reject_reg __read_mostly = {
 	.name		= "REJECT",
 	.family		= AF_INET6,
 	.target		= reject6_target,
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index d3c1543..2a25fe25 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -23,25 +23,20 @@
 MODULE_DESCRIPTION("IPv6 AH match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
 {
-	int r=0;
-	DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-	       min,spi,max);
+	bool r;
+
+	pr_debug("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",
+		 invert ? '!' : ' ', min, spi, max);
 	r = (spi >= min && spi <= max) ^ invert;
-	DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
+	pr_debug(" result %s\n", r ? "PASS" : "FAILED");
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -49,9 +44,10 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct ip_auth_hdr *ah, _ah;
+	struct ip_auth_hdr _ah;
+	const struct ip_auth_hdr *ah;
 	const struct ip6t_ah *ahinfo = matchinfo;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
@@ -60,40 +56,40 @@
 	err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
 	if (err < 0) {
 		if (err != -ENOENT)
-			*hotdrop = 1;
-		return 0;
+			*hotdrop = true;
+		return false;
 	}
 
 	ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
 	if (ah == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	hdrlen = (ah->hdrlen + 2) << 2;
 
-	DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
-	DEBUGP("RES %04X ", ah->reserved);
-	DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
+	pr_debug("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
+	pr_debug("RES %04X ", ah->reserved);
+	pr_debug("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
 
-	DEBUGP("IPv6 AH spi %02X ",
-	       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
-			  ntohl(ah->spi),
-			  !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
-	DEBUGP("len %02X %04X %02X ",
-	       ahinfo->hdrlen, hdrlen,
-	       (!ahinfo->hdrlen ||
-		(ahinfo->hdrlen == hdrlen) ^
-		!!(ahinfo->invflags & IP6T_AH_INV_LEN)));
-	DEBUGP("res %02X %04X %02X\n",
-	       ahinfo->hdrres, ah->reserved,
-	       !(ahinfo->hdrres && ah->reserved));
+	pr_debug("IPv6 AH spi %02X ",
+		 spi_match(ahinfo->spis[0], ahinfo->spis[1],
+			   ntohl(ah->spi),
+			   !!(ahinfo->invflags & IP6T_AH_INV_SPI)));
+	pr_debug("len %02X %04X %02X ",
+		 ahinfo->hdrlen, hdrlen,
+		 (!ahinfo->hdrlen ||
+		  (ahinfo->hdrlen == hdrlen) ^
+		  !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
+	pr_debug("res %02X %04X %02X\n",
+		 ahinfo->hdrres, ah->reserved,
+		 !(ahinfo->hdrres && ah->reserved));
 
 	return (ah != NULL)
 	       &&
-	       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
-			  ntohl(ah->spi),
-			  !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
+	       spi_match(ahinfo->spis[0], ahinfo->spis[1],
+			 ntohl(ah->spi),
+			 !!(ahinfo->invflags & IP6T_AH_INV_SPI))
 	       &&
 	       (!ahinfo->hdrlen ||
 		(ahinfo->hdrlen == hdrlen) ^
@@ -103,7 +99,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	  const void *entry,
 	  const struct xt_match *match,
@@ -113,13 +109,13 @@
 	const struct ip6t_ah *ahinfo = matchinfo;
 
 	if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
-		DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
-		return 0;
+		pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match ah_match = {
+static struct xt_match ah_match __read_mostly = {
 	.name		= "ah",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 0f3dd93..34ba150 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -19,7 +19,7 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -27,16 +27,16 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	unsigned char eui64[8];
 	int i = 0;
 
 	if (!(skb_mac_header(skb) >= skb->head &&
-	      (skb_mac_header(skb) + ETH_HLEN) <= skb->data) &&
+	      skb_mac_header(skb) + ETH_HLEN <= skb->data) &&
 	    offset != 0) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	memset(eui64, 0, sizeof(eui64));
@@ -50,19 +50,19 @@
 			eui64[0] |= 0x02;
 
 			i = 0;
-			while ((ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i])
-			       && (i < 8))
+			while (ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i]
+			       && i < 8)
 				i++;
 
 			if (i == 8)
-				return 1;
+				return true;
 		}
 	}
 
-	return 0;
+	return false;
 }
 
-static struct xt_match eui64_match = {
+static struct xt_match eui64_match __read_mostly = {
 	.name		= "eui64",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 5a5da71..968aeba 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -22,25 +22,19 @@
 MODULE_DESCRIPTION("IPv6 FRAG match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Returns 1 if the id is matched by the range, 0 otherwise */
-static inline int
-id_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
+static inline bool
+id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert)
 {
-	int r = 0;
-	DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
-	       min, id, max);
+	bool r;
+	pr_debug("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
+		 min, id, max);
 	r = (id >= min && id <= max) ^ invert;
-	DEBUGP(" result %s\n", r ? "PASS" : "FAILED");
+	pr_debug(" result %s\n", r ? "PASS" : "FAILED");
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -48,9 +42,10 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct frag_hdr _frag, *fh;
+	struct frag_hdr _frag;
+	const struct frag_hdr *fh;
 	const struct ip6t_frag *fraginfo = matchinfo;
 	unsigned int ptr;
 	int err;
@@ -58,53 +53,53 @@
 	err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
 	if (err < 0) {
 		if (err != -ENOENT)
-			*hotdrop = 1;
-		return 0;
+			*hotdrop = true;
+		return false;
 	}
 
 	fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
 	if (fh == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
-	DEBUGP("INFO %04X ", fh->frag_off);
-	DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
-	DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
-	DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF));
-	DEBUGP("ID %u %08X\n", ntohl(fh->identification),
-	       ntohl(fh->identification));
+	pr_debug("INFO %04X ", fh->frag_off);
+	pr_debug("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
+	pr_debug("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
+	pr_debug("MF %04X ", fh->frag_off & htons(IP6_MF));
+	pr_debug("ID %u %08X\n", ntohl(fh->identification),
+		 ntohl(fh->identification));
 
-	DEBUGP("IPv6 FRAG id %02X ",
-	       (id_match(fraginfo->ids[0], fraginfo->ids[1],
-			 ntohl(fh->identification),
-			 !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
-	DEBUGP("res %02X %02X%04X %02X ",
-	       (fraginfo->flags & IP6T_FRAG_RES), fh->reserved,
-	       ntohs(fh->frag_off) & 0x6,
-	       !((fraginfo->flags & IP6T_FRAG_RES)
-		 && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
-	DEBUGP("first %02X %02X %02X ",
-	       (fraginfo->flags & IP6T_FRAG_FST),
-	       ntohs(fh->frag_off) & ~0x7,
-	       !((fraginfo->flags & IP6T_FRAG_FST)
-		 && (ntohs(fh->frag_off) & ~0x7)));
-	DEBUGP("mf %02X %02X %02X ",
-	       (fraginfo->flags & IP6T_FRAG_MF),
-	       ntohs(fh->frag_off) & IP6_MF,
-	       !((fraginfo->flags & IP6T_FRAG_MF)
-		 && !((ntohs(fh->frag_off) & IP6_MF))));
-	DEBUGP("last %02X %02X %02X\n",
-	       (fraginfo->flags & IP6T_FRAG_NMF),
-	       ntohs(fh->frag_off) & IP6_MF,
-	       !((fraginfo->flags & IP6T_FRAG_NMF)
-		 && (ntohs(fh->frag_off) & IP6_MF)));
+	pr_debug("IPv6 FRAG id %02X ",
+		 id_match(fraginfo->ids[0], fraginfo->ids[1],
+			  ntohl(fh->identification),
+			  !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)));
+	pr_debug("res %02X %02X%04X %02X ",
+		 fraginfo->flags & IP6T_FRAG_RES, fh->reserved,
+		 ntohs(fh->frag_off) & 0x6,
+		 !((fraginfo->flags & IP6T_FRAG_RES)
+		   && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
+	pr_debug("first %02X %02X %02X ",
+		 fraginfo->flags & IP6T_FRAG_FST,
+		 ntohs(fh->frag_off) & ~0x7,
+		 !((fraginfo->flags & IP6T_FRAG_FST)
+		   && (ntohs(fh->frag_off) & ~0x7)));
+	pr_debug("mf %02X %02X %02X ",
+		 fraginfo->flags & IP6T_FRAG_MF,
+		 ntohs(fh->frag_off) & IP6_MF,
+		 !((fraginfo->flags & IP6T_FRAG_MF)
+		   && !((ntohs(fh->frag_off) & IP6_MF))));
+	pr_debug("last %02X %02X %02X\n",
+		 fraginfo->flags & IP6T_FRAG_NMF,
+		 ntohs(fh->frag_off) & IP6_MF,
+		 !((fraginfo->flags & IP6T_FRAG_NMF)
+		   && (ntohs(fh->frag_off) & IP6_MF)));
 
 	return (fh != NULL)
 	       &&
-	       (id_match(fraginfo->ids[0], fraginfo->ids[1],
-			 ntohl(fh->identification),
-			 !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
+	       id_match(fraginfo->ids[0], fraginfo->ids[1],
+			ntohl(fh->identification),
+			!!(fraginfo->invflags & IP6T_FRAG_INV_IDS))
 	       &&
 	       !((fraginfo->flags & IP6T_FRAG_RES)
 		 && (fh->reserved || (ntohs(fh->frag_off) & 0x6)))
@@ -120,7 +115,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
@@ -130,13 +125,13 @@
 	const struct ip6t_frag *fraginfo = matchinfo;
 
 	if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
-		DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
-		return 0;
+		pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match frag_match = {
+static struct xt_match frag_match __read_mostly = {
 	.name		= "frag",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index d2373c7..e6ca601 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -25,12 +25,6 @@
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 MODULE_ALIAS("ip6t_dst");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /*
  *  (Type & 0xC0) >> 6
  *	0	-> ignorable
@@ -47,7 +41,7 @@
  *	5	-> RTALERT 2 x x
  */
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -55,45 +49,48 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct ipv6_opt_hdr _optsh, *oh;
+	struct ipv6_opt_hdr _optsh;
+	const struct ipv6_opt_hdr *oh;
 	const struct ip6t_opts *optinfo = matchinfo;
 	unsigned int temp;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
-	unsigned int ret = 0;
-	u8 _opttype, *tp = NULL;
-	u8 _optlen, *lp = NULL;
+	bool ret = false;
+	u8 _opttype;
+	u8 _optlen;
+	const u_int8_t *tp = NULL;
+	const u_int8_t *lp = NULL;
 	unsigned int optlen;
 	int err;
 
 	err = ipv6_find_hdr(skb, &ptr, match->data, NULL);
 	if (err < 0) {
 		if (err != -ENOENT)
-			*hotdrop = 1;
-		return 0;
+			*hotdrop = true;
+		return false;
 	}
 
 	oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
 	if (oh == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	hdrlen = ipv6_optlen(oh);
 	if (skb->len - ptr < hdrlen) {
 		/* Packet smaller than it's length field */
-		return 0;
+		return false;
 	}
 
-	DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
+	pr_debug("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
 
-	DEBUGP("len %02X %04X %02X ",
-	       optinfo->hdrlen, hdrlen,
-	       (!(optinfo->flags & IP6T_OPTS_LEN) ||
-		((optinfo->hdrlen == hdrlen) ^
-		 !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
+	pr_debug("len %02X %04X %02X ",
+		 optinfo->hdrlen, hdrlen,
+		 (!(optinfo->flags & IP6T_OPTS_LEN) ||
+		  ((optinfo->hdrlen == hdrlen) ^
+		   !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
 
 	ret = (oh != NULL) &&
 	      (!(optinfo->flags & IP6T_OPTS_LEN) ||
@@ -105,10 +102,10 @@
 	if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
 		return ret;
 	} else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
-		DEBUGP("Not strict - not implemented");
+		pr_debug("Not strict - not implemented");
 	} else {
-		DEBUGP("Strict ");
-		DEBUGP("#%d ", optinfo->optsnr);
+		pr_debug("Strict ");
+		pr_debug("#%d ", optinfo->optsnr);
 		for (temp = 0; temp < optinfo->optsnr; temp++) {
 			/* type field exists ? */
 			if (hdrlen < 1)
@@ -120,12 +117,11 @@
 
 			/* Type check */
 			if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
-				DEBUGP("Tbad %02X %02X\n",
-				       *tp,
-				       (optinfo->opts[temp] & 0xFF00) >> 8);
-				return 0;
+				pr_debug("Tbad %02X %02X\n", *tp,
+					 (optinfo->opts[temp] & 0xFF00) >> 8);
+				return false;
 			} else {
-				DEBUGP("Tok ");
+				pr_debug("Tok ");
 			}
 			/* Length check */
 			if (*tp) {
@@ -142,23 +138,23 @@
 				spec_len = optinfo->opts[temp] & 0x00FF;
 
 				if (spec_len != 0x00FF && spec_len != *lp) {
-					DEBUGP("Lbad %02X %04X\n", *lp,
-					       spec_len);
-					return 0;
+					pr_debug("Lbad %02X %04X\n", *lp,
+						 spec_len);
+					return false;
 				}
-				DEBUGP("Lok ");
+				pr_debug("Lok ");
 				optlen = *lp + 2;
 			} else {
-				DEBUGP("Pad1\n");
+				pr_debug("Pad1\n");
 				optlen = 1;
 			}
 
 			/* Step to the next */
-			DEBUGP("len%04X \n", optlen);
+			pr_debug("len%04X \n", optlen);
 
 			if ((ptr > skb->len - optlen || hdrlen < optlen) &&
-			    (temp < optinfo->optsnr - 1)) {
-				DEBUGP("new pointer is too large! \n");
+			    temp < optinfo->optsnr - 1) {
+				pr_debug("new pointer is too large! \n");
 				break;
 			}
 			ptr += optlen;
@@ -167,14 +163,14 @@
 		if (temp == optinfo->optsnr)
 			return ret;
 		else
-			return 0;
+			return false;
 	}
 
-	return 0;
+	return false;
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_match *match,
@@ -184,13 +180,13 @@
 	const struct ip6t_opts *optsinfo = matchinfo;
 
 	if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
-		DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
-		return 0;
+		pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match opts_match[] = {
+static struct xt_match opts_match[] __read_mostly = {
 	{
 		.name		= "hbh",
 		.family		= AF_INET6,
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index d606c0e..ca29ec0 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -19,37 +19,37 @@
 MODULE_DESCRIPTION("IP tables Hop Limit matching module");
 MODULE_LICENSE("GPL");
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in, const struct net_device *out,
-		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in, const struct net_device *out,
+		  const struct xt_match *match, const void *matchinfo,
+		  int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ip6t_hl_info *info = matchinfo;
 	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
 
 	switch (info->mode) {
 		case IP6T_HL_EQ:
-			return (ip6h->hop_limit == info->hop_limit);
+			return ip6h->hop_limit == info->hop_limit;
 			break;
 		case IP6T_HL_NE:
-			return (!(ip6h->hop_limit == info->hop_limit));
+			return ip6h->hop_limit != info->hop_limit;
 			break;
 		case IP6T_HL_LT:
-			return (ip6h->hop_limit < info->hop_limit);
+			return ip6h->hop_limit < info->hop_limit;
 			break;
 		case IP6T_HL_GT:
-			return (ip6h->hop_limit > info->hop_limit);
+			return ip6h->hop_limit > info->hop_limit;
 			break;
 		default:
 			printk(KERN_WARNING "ip6t_hl: unknown mode %d\n",
 				info->mode);
-			return 0;
+			return false;
 	}
 
-	return 0;
+	return false;
 }
 
-static struct xt_match hl_match = {
+static struct xt_match hl_match __read_mostly = {
 	.name		= "hl",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index fd6a086..2c65c2f 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -26,7 +26,7 @@
 MODULE_DESCRIPTION("IPv6 headers match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-static int
+static bool
 ipv6header_match(const struct sk_buff *skb,
 		 const struct net_device *in,
 		 const struct net_device *out,
@@ -34,7 +34,7 @@
 		 const void *matchinfo,
 		 int offset,
 		 unsigned int protoff,
-		 int *hotdrop)
+		 bool *hotdrop)
 {
 	const struct ip6t_ipv6header_info *info = matchinfo;
 	unsigned int temp;
@@ -58,7 +58,7 @@
 
 		/* Is there enough space for the next ext header? */
 		if (len < (int)sizeof(struct ipv6_opt_hdr))
-			return 0;
+			return false;
 		/* No more exthdr -> evaluate */
 		if (nexthdr == NEXTHDR_NONE) {
 			temp |= MASK_NONE;
@@ -74,9 +74,9 @@
 		BUG_ON(hp == NULL);
 
 		/* Calculate the header length */
-		if (nexthdr == NEXTHDR_FRAGMENT) {
+		if (nexthdr == NEXTHDR_FRAGMENT)
 			hdrlen = 8;
-		} else if (nexthdr == NEXTHDR_AUTH)
+		else if (nexthdr == NEXTHDR_AUTH)
 			hdrlen = (hp->hdrlen + 2) << 2;
 		else
 			hdrlen = ipv6_optlen(hp);
@@ -99,7 +99,7 @@
 			temp |= MASK_DSTOPTS;
 			break;
 		default:
-			return 0;
+			return false;
 			break;
 		}
 
@@ -110,7 +110,7 @@
 			break;
 	}
 
-	if ((nexthdr != NEXTHDR_NONE) && (nexthdr != NEXTHDR_ESP))
+	if (nexthdr != NEXTHDR_NONE && nexthdr != NEXTHDR_ESP)
 		temp |= MASK_PROTO;
 
 	if (info->modeflag)
@@ -124,7 +124,7 @@
 	}
 }
 
-static int
+static bool
 ipv6header_checkentry(const char *tablename,
 		      const void *ip,
 		      const struct xt_match *match,
@@ -136,12 +136,12 @@
 	/* invflags is 0 or 0xff in hard mode */
 	if ((!info->modeflag) && info->invflags != 0x00 &&
 	    info->invflags != 0xFF)
-		return 0;
+		return false;
 
-	return 1;
+	return true;
 }
 
-static struct xt_match ip6t_ipv6header_match = {
+static struct xt_match ip6t_ipv6header_match __read_mostly = {
 	.name		= "ipv6header",
 	.family		= AF_INET6,
 	.match		= &ipv6header_match,
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c
index c2a9098..0fa7140 100644
--- a/net/ipv6/netfilter/ip6t_mh.c
+++ b/net/ipv6/netfilter/ip6t_mh.c
@@ -31,16 +31,13 @@
 #endif
 
 /* Returns 1 if the type is matched by the range, 0 otherwise */
-static inline int
-type_match(u_int8_t min, u_int8_t max, u_int8_t type, int invert)
+static inline bool
+type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert)
 {
-	int ret;
-
-	ret = (type >= min && type <= max) ^ invert;
-	return ret;
+	return (type >= min && type <= max) ^ invert;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
 	 const struct net_device *in,
 	 const struct net_device *out,
@@ -48,29 +45,30 @@
 	 const void *matchinfo,
 	 int offset,
 	 unsigned int protoff,
-	 int *hotdrop)
+	 bool *hotdrop)
 {
-	struct ip6_mh _mh, *mh;
+	struct ip6_mh _mh;
+	const struct ip6_mh *mh;
 	const struct ip6t_mh *mhinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	mh = skb_header_pointer(skb, protoff, sizeof(_mh), &_mh);
 	if (mh == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil MH tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	if (mh->ip6mh_proto != IPPROTO_NONE) {
 		duprintf("Dropping invalid MH Payload Proto: %u\n",
 			 mh->ip6mh_proto);
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return type_match(mhinfo->types[0], mhinfo->types[1], mh->ip6mh_type,
@@ -78,7 +76,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 mh_checkentry(const char *tablename,
 	      const void *entry,
 	      const struct xt_match *match,
@@ -91,7 +89,7 @@
 	return !(mhinfo->invflags & ~IP6T_MH_INV_MASK);
 }
 
-static struct xt_match mh_match = {
+static struct xt_match mh_match __read_mostly = {
 	.name		= "mh",
 	.family		= AF_INET6,
 	.checkentry	= mh_checkentry,
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 43738bb..6036613 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -23,7 +23,7 @@
 MODULE_LICENSE("GPL");
 
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -31,29 +31,27 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct ip6t_owner_info *info = matchinfo;
 
 	if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
-		return 0;
+		return false;
 
-	if (info->match & IP6T_OWNER_UID) {
+	if (info->match & IP6T_OWNER_UID)
 		if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
 		    !!(info->invert & IP6T_OWNER_UID))
-			return 0;
-	}
+			return false;
 
-	if (info->match & IP6T_OWNER_GID) {
+	if (info->match & IP6T_OWNER_GID)
 		if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
 		    !!(info->invert & IP6T_OWNER_GID))
-			return 0;
-	}
+			return false;
 
-	return 1;
+	return true;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
@@ -65,12 +63,12 @@
 	if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
 		printk("ipt_owner: pid and sid matching "
 		       "not supported anymore\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match owner_match = {
+static struct xt_match owner_match __read_mostly = {
 	.name		= "owner",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 81ab00d..357cea7 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -24,25 +24,19 @@
 MODULE_DESCRIPTION("IPv6 RT match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Returns 1 if the id is matched by the range, 0 otherwise */
-static inline int
-segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
+static inline bool
+segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert)
 {
-	int r = 0;
-	DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",
-	       invert ? '!' : ' ', min, id, max);
+	bool r;
+	pr_debug("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",
+		 invert ? '!' : ' ', min, id, max);
 	r = (id >= min && id <= max) ^ invert;
-	DEBUGP(" result %s\n", r ? "PASS" : "FAILED");
+	pr_debug(" result %s\n", r ? "PASS" : "FAILED");
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -50,59 +44,61 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct ipv6_rt_hdr _route, *rh;
+	struct ipv6_rt_hdr _route;
+	const struct ipv6_rt_hdr *rh;
 	const struct ip6t_rt *rtinfo = matchinfo;
 	unsigned int temp;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
-	unsigned int ret = 0;
-	struct in6_addr *ap, _addr;
+	bool ret = false;
+	struct in6_addr _addr;
+	const struct in6_addr *ap;
 	int err;
 
 	err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
 	if (err < 0) {
 		if (err != -ENOENT)
-			*hotdrop = 1;
-		return 0;
+			*hotdrop = true;
+		return false;
 	}
 
 	rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
 	if (rh == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	hdrlen = ipv6_optlen(rh);
 	if (skb->len - ptr < hdrlen) {
 		/* Pcket smaller than its length field */
-		return 0;
+		return false;
 	}
 
-	DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
-	DEBUGP("TYPE %04X ", rh->type);
-	DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
+	pr_debug("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
+	pr_debug("TYPE %04X ", rh->type);
+	pr_debug("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
 
-	DEBUGP("IPv6 RT segsleft %02X ",
-	       (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
-			       rh->segments_left,
-			       !!(rtinfo->invflags & IP6T_RT_INV_SGS))));
-	DEBUGP("type %02X %02X %02X ",
-	       rtinfo->rt_type, rh->type,
-	       (!(rtinfo->flags & IP6T_RT_TYP) ||
-		((rtinfo->rt_type == rh->type) ^
-		 !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
-	DEBUGP("len %02X %04X %02X ",
-	       rtinfo->hdrlen, hdrlen,
-	       (!(rtinfo->flags & IP6T_RT_LEN) ||
-		((rtinfo->hdrlen == hdrlen) ^
-		 !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
-	DEBUGP("res %02X %02X %02X ",
-	       (rtinfo->flags & IP6T_RT_RES),
-	       ((struct rt0_hdr *)rh)->reserved,
-	       !((rtinfo->flags & IP6T_RT_RES) &&
-		 (((struct rt0_hdr *)rh)->reserved)));
+	pr_debug("IPv6 RT segsleft %02X ",
+		 segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
+				rh->segments_left,
+				!!(rtinfo->invflags & IP6T_RT_INV_SGS)));
+	pr_debug("type %02X %02X %02X ",
+		 rtinfo->rt_type, rh->type,
+		 (!(rtinfo->flags & IP6T_RT_TYP) ||
+		  ((rtinfo->rt_type == rh->type) ^
+		   !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
+	pr_debug("len %02X %04X %02X ",
+		 rtinfo->hdrlen, hdrlen,
+		 !(rtinfo->flags & IP6T_RT_LEN) ||
+		  ((rtinfo->hdrlen == hdrlen) ^
+		   !!(rtinfo->invflags & IP6T_RT_INV_LEN)));
+	pr_debug("res %02X %02X %02X ",
+		 rtinfo->flags & IP6T_RT_RES,
+		 ((const struct rt0_hdr *)rh)->reserved,
+		 !((rtinfo->flags & IP6T_RT_RES) &&
+		   (((const struct rt0_hdr *)rh)->reserved)));
 
 	ret = (rh != NULL)
 	      &&
@@ -129,18 +125,18 @@
 		ret = (*rp == 0);
 	}
 
-	DEBUGP("#%d ", rtinfo->addrnr);
+	pr_debug("#%d ", rtinfo->addrnr);
 	if (!(rtinfo->flags & IP6T_RT_FST)) {
 		return ret;
 	} else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) {
-		DEBUGP("Not strict ");
+		pr_debug("Not strict ");
 		if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) {
-			DEBUGP("There isn't enough space\n");
-			return 0;
+			pr_debug("There isn't enough space\n");
+			return false;
 		} else {
 			unsigned int i = 0;
 
-			DEBUGP("#%d ", rtinfo->addrnr);
+			pr_debug("#%d ", rtinfo->addrnr);
 			for (temp = 0;
 			     temp < (unsigned int)((hdrlen - 8) / 16);
 			     temp++) {
@@ -154,25 +150,25 @@
 				BUG_ON(ap == NULL);
 
 				if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) {
-					DEBUGP("i=%d temp=%d;\n", i, temp);
+					pr_debug("i=%d temp=%d;\n", i, temp);
 					i++;
 				}
 				if (i == rtinfo->addrnr)
 					break;
 			}
-			DEBUGP("i=%d #%d\n", i, rtinfo->addrnr);
+			pr_debug("i=%d #%d\n", i, rtinfo->addrnr);
 			if (i == rtinfo->addrnr)
 				return ret;
 			else
-				return 0;
+				return false;
 		}
 	} else {
-		DEBUGP("Strict ");
+		pr_debug("Strict ");
 		if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) {
-			DEBUGP("There isn't enough space\n");
-			return 0;
+			pr_debug("There isn't enough space\n");
+			return false;
 		} else {
-			DEBUGP("#%d ", rtinfo->addrnr);
+			pr_debug("#%d ", rtinfo->addrnr);
 			for (temp = 0; temp < rtinfo->addrnr; temp++) {
 				ap = skb_header_pointer(skb,
 							ptr
@@ -185,20 +181,20 @@
 				if (!ipv6_addr_equal(ap, &rtinfo->addrs[temp]))
 					break;
 			}
-			DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr);
-			if ((temp == rtinfo->addrnr) &&
-			    (temp == (unsigned int)((hdrlen - 8) / 16)))
+			pr_debug("temp=%d #%d\n", temp, rtinfo->addrnr);
+			if (temp == rtinfo->addrnr &&
+			    temp == (unsigned int)((hdrlen - 8) / 16))
 				return ret;
 			else
-				return 0;
+				return false;
 		}
 	}
 
-	return 0;
+	return false;
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_match *match,
@@ -208,21 +204,21 @@
 	const struct ip6t_rt *rtinfo = matchinfo;
 
 	if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
-		DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
-		return 0;
+		pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
+		return false;
 	}
 	if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) &&
 	    (!(rtinfo->flags & IP6T_RT_TYP) ||
 	     (rtinfo->rt_type != 0) ||
 	     (rtinfo->invflags & IP6T_RT_INV_TYP))) {
-		DEBUGP("`--rt-type 0' required before `--rt-0-*'");
-		return 0;
+		pr_debug("`--rt-type 0' required before `--rt-0-*'");
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static struct xt_match rt_match = {
+static struct xt_match rt_match __read_mostly = {
 	.name		= "rt",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index f2d2649..f0a9efa 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -21,12 +21,6 @@
 			    (1 << NF_IP6_LOCAL_OUT) | \
 			    (1 << NF_IP6_POST_ROUTING))
 
-#if 0
-#define DEBUGP(x, args...)	printk(KERN_DEBUG x, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
 static struct
 {
 	struct ip6t_replace repl;
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 0acda45..ec290e4 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -8,12 +8,6 @@
 
 #define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
 
-#if 0
-#define DEBUGP(x, args...)	printk(KERN_DEBUG x, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
 static struct
 {
 	struct ip6t_replace repl;
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 6d2a082..36df221 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -26,12 +26,6 @@
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 			     struct nf_conntrack_tuple *tuple)
 {
@@ -92,7 +86,7 @@
  *        - Note also special handling of AUTH header. Thanks to IPsec wizards.
  */
 
-int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp,
+int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
 			   int len)
 {
 	u8 nexthdr = *nexthdrp;
@@ -123,22 +117,25 @@
 	return start;
 }
 
-static int
-ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
-	     u_int8_t *protonum)
+static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
+			    unsigned int *dataoff, u_int8_t *protonum)
 {
-	unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
-	unsigned char pnum = ipv6_hdr(*pskb)->nexthdr;
-	int protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
-					     (*pskb)->len - extoff);
+	unsigned int extoff = nhoff + sizeof(struct ipv6hdr);
+	unsigned char pnum;
+	int protoff;
+
+	if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr),
+			  &pnum, sizeof(pnum)) != 0) {
+		pr_debug("ip6_conntrack_core: can't get nexthdr\n");
+		return -NF_ACCEPT;
+	}
+	protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff);
 	/*
-	 * (protoff == (*pskb)->len) mean that the packet doesn't have no data
+	 * (protoff == skb->len) mean that the packet doesn't have no data
 	 * except of IPv6 & ext headers. but it's tracked anyway. - YK
 	 */
-	if ((protoff < 0) || (protoff > (*pskb)->len)) {
-		DEBUGP("ip6_conntrack_core: can't find proto in pkt\n");
-		NF_CT_STAT_INC_ATOMIC(error);
-		NF_CT_STAT_INC_ATOMIC(invalid);
+	if ((protoff < 0) || (protoff > skb->len)) {
+		pr_debug("ip6_conntrack_core: can't find proto in pkt\n");
 		return -NF_ACCEPT;
 	}
 
@@ -147,11 +144,6 @@
 	return NF_ACCEPT;
 }
 
-static u_int32_t ipv6_get_features(const struct nf_conntrack_tuple *tuple)
-{
-	return NF_CT_F_BASIC;
-}
-
 static unsigned int ipv6_confirm(unsigned int hooknum,
 				 struct sk_buff **pskb,
 				 const struct net_device *in,
@@ -160,6 +152,7 @@
 {
 	struct nf_conn *ct;
 	struct nf_conn_help *help;
+	struct nf_conntrack_helper *helper;
 	enum ip_conntrack_info ctinfo;
 	unsigned int ret, protoff;
 	unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
@@ -172,18 +165,21 @@
 		goto out;
 
 	help = nfct_help(ct);
-	if (!help || !help->helper)
+	if (!help)
+		goto out;
+	/* rcu_read_lock()ed by nf_hook_slow */
+	helper = rcu_dereference(help->helper);
+	if (!helper)
 		goto out;
 
 	protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
 					 (*pskb)->len - extoff);
-	if (protoff < 0 || protoff > (*pskb)->len ||
-	    pnum == NEXTHDR_FRAGMENT) {
-		DEBUGP("proto header not found\n");
+	if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) {
+		pr_debug("proto header not found\n");
 		return NF_ACCEPT;
 	}
 
-	ret = help->helper->help(pskb, protoff, ct, ctinfo);
+	ret = helper->help(pskb, protoff, ct, ctinfo);
 	if (ret != NF_ACCEPT)
 		return ret;
 out:
@@ -377,14 +373,14 @@
 }
 #endif
 
-struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
+struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
 	.l3proto		= PF_INET6,
 	.name			= "ipv6",
 	.pkt_to_tuple		= ipv6_pkt_to_tuple,
 	.invert_tuple		= ipv6_invert_tuple,
 	.print_tuple		= ipv6_print_tuple,
 	.print_conntrack	= ipv6_print_conntrack,
-	.prepare		= ipv6_prepare,
+	.get_l4proto		= ipv6_get_l4proto,
 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 	.tuple_to_nfattr	= ipv6_tuple_to_nfattr,
 	.nfattr_to_tuple	= ipv6_nfattr_to_tuple,
@@ -393,7 +389,6 @@
 	.ctl_table_path		= nf_net_netfilter_sysctl_path,
 	.ctl_table		= nf_ct_ipv6_sysctl_table,
 #endif
-	.get_features		= ipv6_get_features,
 	.me			= THIS_MODULE,
 };
 
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 0be790d..ab154fb 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -27,12 +27,6 @@
 
 static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int icmpv6_pkt_to_tuple(const struct sk_buff *skb,
 			       unsigned int dataoff,
 			       struct nf_conntrack_tuple *tuple)
@@ -125,8 +119,8 @@
 
 	if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) {
 		/* Can't create a new ICMPv6 `conn' with this. */
-		DEBUGP("icmpv6: can't create new conn with type %u\n",
-		       type + 128);
+		pr_debug("icmpv6: can't create new conn with type %u\n",
+			 type + 128);
 		NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
 		return 0;
 	}
@@ -142,61 +136,36 @@
 {
 	struct nf_conntrack_tuple intuple, origtuple;
 	struct nf_conntrack_tuple_hash *h;
-	struct icmp6hdr _hdr, *hp;
-	unsigned int inip6off;
 	struct nf_conntrack_l4proto *inproto;
-	u_int8_t inprotonum;
-	unsigned int inprotoff;
 
 	NF_CT_ASSERT(skb->nfct == NULL);
 
-	hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr);
-	if (hp == NULL) {
-		DEBUGP("icmpv6_error: Can't get ICMPv6 hdr.\n");
-		return -NF_ACCEPT;
-	}
-
-	inip6off = icmp6off + sizeof(_hdr);
-	if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr),
-			  &inprotonum, sizeof(inprotonum)) != 0) {
-		DEBUGP("icmpv6_error: Can't get nexthdr in inner IPv6 header.\n");
-		return -NF_ACCEPT;
-	}
-	inprotoff = nf_ct_ipv6_skip_exthdr(skb,
-					   inip6off + sizeof(struct ipv6hdr),
-					   &inprotonum,
-					   skb->len - inip6off
-						    - sizeof(struct ipv6hdr));
-
-	if ((inprotoff < 0) || (inprotoff > skb->len) ||
-	    (inprotonum == NEXTHDR_FRAGMENT)) {
-		DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n");
+	/* Are they talking about one of our connections? */
+	if (!nf_ct_get_tuplepr(skb,
+			       skb_network_offset(skb)
+				+ sizeof(struct ipv6hdr)
+				+ sizeof(struct icmp6hdr),
+			       PF_INET6, &origtuple)) {
+		pr_debug("icmpv6_error: Can't get tuple\n");
 		return -NF_ACCEPT;
 	}
 
 	/* rcu_read_lock()ed by nf_hook_slow */
-	inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum);
-
-	/* Are they talking about one of our connections? */
-	if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
-			     &origtuple, &nf_conntrack_l3proto_ipv6, inproto)) {
-		DEBUGP("icmpv6_error: Can't get tuple\n");
-		return -NF_ACCEPT;
-	}
+	inproto = __nf_ct_l4proto_find(PF_INET6, origtuple.dst.protonum);
 
 	/* Ordinarily, we'd expect the inverted tupleproto, but it's
 	   been preserved inside the ICMP. */
 	if (!nf_ct_invert_tuple(&intuple, &origtuple,
 				&nf_conntrack_l3proto_ipv6, inproto)) {
-		DEBUGP("icmpv6_error: Can't invert tuple\n");
+		pr_debug("icmpv6_error: Can't invert tuple\n");
 		return -NF_ACCEPT;
 	}
 
 	*ctinfo = IP_CT_RELATED;
 
-	h = nf_conntrack_find_get(&intuple, NULL);
+	h = nf_conntrack_find_get(&intuple);
 	if (!h) {
-		DEBUGP("icmpv6_error: no match\n");
+		pr_debug("icmpv6_error: no match\n");
 		return -NF_ACCEPT;
 	} else {
 		if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
@@ -307,7 +276,7 @@
 };
 #endif /* CONFIG_SYSCTL */
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
 {
 	.l3proto		= PF_INET6,
 	.l4proto		= IPPROTO_ICMPV6,
@@ -328,5 +297,3 @@
 	.ctl_table		= icmpv6_sysctl_table,
 #endif
 };
-
-EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 347ab76..25442a8 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -44,12 +44,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */
 #define NF_CT_FRAG6_LOW_THRESH 196608  /* == 192*1024 */
 #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT
@@ -343,7 +337,7 @@
 	struct nf_ct_frag6_queue *fq;
 
 	if ((fq = frag_alloc_queue()) == NULL) {
-		DEBUGP("Can't alloc new queue\n");
+		pr_debug("Can't alloc new queue\n");
 		goto oom;
 	}
 
@@ -393,7 +387,7 @@
 	int offset, end;
 
 	if (fq->last_in & COMPLETE) {
-		DEBUGP("Allready completed\n");
+		pr_debug("Allready completed\n");
 		goto err;
 	}
 
@@ -402,7 +396,7 @@
 			((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1)));
 
 	if ((unsigned int)end > IPV6_MAXPLEN) {
-		DEBUGP("offset is too large.\n");
+		pr_debug("offset is too large.\n");
 		return -1;
 	}
 
@@ -420,7 +414,7 @@
 		 */
 		if (end < fq->len ||
 		    ((fq->last_in & LAST_IN) && end != fq->len)) {
-			DEBUGP("already received last fragment\n");
+			pr_debug("already received last fragment\n");
 			goto err;
 		}
 		fq->last_in |= LAST_IN;
@@ -433,13 +427,13 @@
 			/* RFC2460 says always send parameter problem in
 			 * this case. -DaveM
 			 */
-			DEBUGP("the end of this fragment is not rounded to 8 bytes.\n");
+			pr_debug("end of fragment not rounded to 8 bytes.\n");
 			return -1;
 		}
 		if (end > fq->len) {
 			/* Some bits beyond end -> corruption. */
 			if (fq->last_in & LAST_IN) {
-				DEBUGP("last packet already reached.\n");
+				pr_debug("last packet already reached.\n");
 				goto err;
 			}
 			fq->len = end;
@@ -451,11 +445,11 @@
 
 	/* Point into the IP datagram 'data' part. */
 	if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data)) {
-		DEBUGP("queue: message is too short.\n");
+		pr_debug("queue: message is too short.\n");
 		goto err;
 	}
 	if (pskb_trim_rcsum(skb, end - offset)) {
-		DEBUGP("Can't trim\n");
+		pr_debug("Can't trim\n");
 		goto err;
 	}
 
@@ -480,11 +474,11 @@
 		if (i > 0) {
 			offset += i;
 			if (end <= offset) {
-				DEBUGP("overlap\n");
+				pr_debug("overlap\n");
 				goto err;
 			}
 			if (!pskb_pull(skb, i)) {
-				DEBUGP("Can't pull\n");
+				pr_debug("Can't pull\n");
 				goto err;
 			}
 			if (skb->ip_summed != CHECKSUM_UNNECESSARY)
@@ -503,7 +497,7 @@
 			/* Eat head of the next overlapped fragment
 			 * and leave the loop. The next ones cannot overlap.
 			 */
-			DEBUGP("Eat head of the overlapped parts.: %d", i);
+			pr_debug("Eat head of the overlapped parts.: %d", i);
 			if (!pskb_pull(next, i))
 				goto err;
 
@@ -586,13 +580,13 @@
 		       sizeof(struct ipv6hdr) + fq->len -
 		       sizeof(struct frag_hdr));
 	if (payload_len > IPV6_MAXPLEN) {
-		DEBUGP("payload len is too large.\n");
+		pr_debug("payload len is too large.\n");
 		goto out_oversize;
 	}
 
 	/* Head of list must not be cloned. */
 	if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) {
-		DEBUGP("skb is cloned but can't expand head");
+		pr_debug("skb is cloned but can't expand head");
 		goto out_oom;
 	}
 
@@ -604,7 +598,7 @@
 		int i, plen = 0;
 
 		if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL) {
-			DEBUGP("Can't alloc skb\n");
+			pr_debug("Can't alloc skb\n");
 			goto out_oom;
 		}
 		clone->next = head->next;
@@ -719,11 +713,11 @@
 			return -1;
 		}
 		if (len < (int)sizeof(struct ipv6_opt_hdr)) {
-			DEBUGP("too short\n");
+			pr_debug("too short\n");
 			return -1;
 		}
 		if (nexthdr == NEXTHDR_NONE) {
-			DEBUGP("next header is none\n");
+			pr_debug("next header is none\n");
 			return -1;
 		}
 		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
@@ -764,7 +758,7 @@
 
 	/* Jumbo payload inhibits frag. header */
 	if (ipv6_hdr(skb)->payload_len == 0) {
-		DEBUGP("payload len = 0\n");
+		pr_debug("payload len = 0\n");
 		return skb;
 	}
 
@@ -773,14 +767,14 @@
 
 	clone = skb_clone(skb, GFP_ATOMIC);
 	if (clone == NULL) {
-		DEBUGP("Can't clone skb\n");
+		pr_debug("Can't clone skb\n");
 		return skb;
 	}
 
 	NFCT_FRAG6_CB(clone)->orig = skb;
 
 	if (!pskb_may_pull(clone, fhoff + sizeof(*fhdr))) {
-		DEBUGP("message is too short.\n");
+		pr_debug("message is too short.\n");
 		goto ret_orig;
 	}
 
@@ -789,7 +783,7 @@
 	fhdr = (struct frag_hdr *)skb_transport_header(clone);
 
 	if (!(fhdr->frag_off & htons(0xFFF9))) {
-		DEBUGP("Invalid fragment offset\n");
+		pr_debug("Invalid fragment offset\n");
 		/* It is not a fragmented frame */
 		goto ret_orig;
 	}
@@ -799,7 +793,7 @@
 
 	fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr);
 	if (fq == NULL) {
-		DEBUGP("Can't find and can't create new queue\n");
+		pr_debug("Can't find and can't create new queue\n");
 		goto ret_orig;
 	}
 
@@ -807,7 +801,7 @@
 
 	if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) {
 		spin_unlock(&fq->lock);
-		DEBUGP("Can't insert skb to queue\n");
+		pr_debug("Can't insert skb to queue\n");
 		fq_put(fq, NULL);
 		goto ret_orig;
 	}
@@ -815,7 +809,7 @@
 	if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) {
 		ret_skb = nf_ct_frag6_reasm(fq, dev);
 		if (ret_skb == NULL)
-			DEBUGP("Can't reassemble fragmented packets\n");
+			pr_debug("Can't reassemble fragmented packets\n");
 	}
 	spin_unlock(&fq->lock);
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 009a104..e27383d 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -49,7 +49,7 @@
 #include <net/udp.h>
 #include <net/inet_common.h>
 #include <net/tcp_states.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 #include <net/mip6.h>
 #endif
 
@@ -137,6 +137,28 @@
 	return 0;
 }
 
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+static int (*mh_filter)(struct sock *sock, struct sk_buff *skb);
+
+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+					   struct sk_buff *skb))
+{
+	rcu_assign_pointer(mh_filter, filter);
+	return 0;
+}
+EXPORT_SYMBOL(rawv6_mh_filter_register);
+
+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+					     struct sk_buff *skb))
+{
+	rcu_assign_pointer(mh_filter, NULL);
+	synchronize_rcu();
+	return 0;
+}
+EXPORT_SYMBOL(rawv6_mh_filter_unregister);
+
+#endif
+
 /*
  *	demultiplex raw sockets.
  *	(should consider queueing the skb in the sock receive_queue
@@ -178,16 +200,22 @@
 		case IPPROTO_ICMPV6:
 			filtered = icmpv6_filter(sk, skb);
 			break;
-#ifdef CONFIG_IPV6_MIP6
+
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		case IPPROTO_MH:
+		{
 			/* XXX: To validate MH only once for each packet,
 			 * this is placed here. It should be after checking
 			 * xfrm policy, however it doesn't. The checking xfrm
 			 * policy is placed in rawv6_rcv() because it is
 			 * required for each socket.
 			 */
-			filtered = mip6_mh_filter(sk, skb);
+			int (*filter)(struct sock *sock, struct sk_buff *skb);
+
+			filter = rcu_dereference(mh_filter);
+			filtered = filter ? filter(sk, skb) : 0;
 			break;
+		}
 #endif
 		default:
 			filtered = 0;
@@ -611,9 +639,7 @@
 	struct iovec *iov;
 	u8 __user *type = NULL;
 	u8 __user *code = NULL;
-#ifdef CONFIG_IPV6_MIP6
 	u8 len = 0;
-#endif
 	int probed = 0;
 	int i;
 
@@ -646,7 +672,6 @@
 				probed = 1;
 			}
 			break;
-#ifdef CONFIG_IPV6_MIP6
 		case IPPROTO_MH:
 			if (iov->iov_base && iov->iov_len < 1)
 				break;
@@ -660,7 +685,6 @@
 				len += iov->iov_len;
 
 			break;
-#endif
 		default:
 			probed = 1;
 			break;
@@ -818,8 +842,12 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
-		goto out;
+	if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
+		if (err == -EREMOTE)
+			err = ip6_dst_blackhole(sk, &dst, &fl);
+		if (err < 0)
+			goto out;
+	}
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -1252,7 +1280,7 @@
 	return 0;
 }
 
-static struct seq_operations raw6_seq_ops = {
+static const struct seq_operations raw6_seq_ops = {
 	.start =	raw6_seq_start,
 	.next =		raw6_seq_next,
 	.stop =		raw6_seq_stop,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b46ad53..fe8d983 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -119,6 +119,19 @@
 	.entry_size		=	sizeof(struct rt6_info),
 };
 
+static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+}
+
+static struct dst_ops ip6_dst_blackhole_ops = {
+	.family			=	AF_INET6,
+	.protocol		=	__constant_htons(ETH_P_IPV6),
+	.destroy		=	ip6_dst_destroy,
+	.check			=	ip6_dst_check,
+	.update_pmtu		=	ip6_rt_blackhole_update_pmtu,
+	.entry_size		=	sizeof(struct rt6_info),
+};
+
 struct rt6_info ip6_null_entry = {
 	.u = {
 		.dst = {
@@ -833,6 +846,54 @@
 
 EXPORT_SYMBOL(ip6_route_output);
 
+static int ip6_blackhole_output(struct sk_buff *skb)
+{
+	kfree_skb(skb);
+	return 0;
+}
+
+int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl)
+{
+	struct rt6_info *ort = (struct rt6_info *) *dstp;
+	struct rt6_info *rt = (struct rt6_info *)
+		dst_alloc(&ip6_dst_blackhole_ops);
+	struct dst_entry *new = NULL;
+
+	if (rt) {
+		new = &rt->u.dst;
+
+		atomic_set(&new->__refcnt, 1);
+		new->__use = 1;
+		new->input = ip6_blackhole_output;
+		new->output = ip6_blackhole_output;
+
+		memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
+		new->dev = ort->u.dst.dev;
+		if (new->dev)
+			dev_hold(new->dev);
+		rt->rt6i_idev = ort->rt6i_idev;
+		if (rt->rt6i_idev)
+			in6_dev_hold(rt->rt6i_idev);
+		rt->rt6i_expires = 0;
+
+		ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway);
+		rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
+		rt->rt6i_metric = 0;
+
+		memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
+#ifdef CONFIG_IPV6_SUBTREES
+		memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
+#endif
+
+		dst_free(new);
+	}
+
+	dst_release(*dstp);
+	*dstp = new;
+	return (new ? 0 : -ENOMEM);
+}
+EXPORT_SYMBOL_GPL(ip6_dst_blackhole);
+
 /*
  *	Destination cache support functions
  */
@@ -1938,7 +1999,7 @@
 	fib6_clean_all(rt6_mtu_change_route, 0, &arg);
 }
 
-static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = {
+static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
 	[RTA_GATEWAY]           = { .len = sizeof(struct in6_addr) },
 	[RTA_OIF]               = { .type = NLA_U32 },
 	[RTA_IIF]		= { .type = NLA_U32 },
@@ -2495,6 +2556,8 @@
 	ip6_dst_ops.kmem_cachep =
 		kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
 				  SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
+
 	fib6_init();
 #ifdef 	CONFIG_PROC_FS
 	p = proc_net_create("ipv6_route", 0, rt6_proc_info);
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1efa95a..eb20bb6 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -532,7 +532,8 @@
 	 */
 	max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr);
 
-	if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index e2f25ea..d67fb1e 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -265,8 +265,12 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
-		goto failure;
+	if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
+		if (err == -EREMOTE)
+			err = ip6_dst_blackhole(sk, &dst, &fl);
+		if (err < 0)
+			goto failure;
+	}
 
 	if (saddr == NULL) {
 		saddr = &fl.fl6_src;
@@ -480,17 +484,6 @@
 
 	if (dst == NULL) {
 		opt = np->opt;
-		if (opt == NULL &&
-		    np->rxopt.bits.osrcrt == 2 &&
-		    treq->pktopts) {
-			struct sk_buff *pktopts = treq->pktopts;
-			struct inet6_skb_parm *rxopt = IP6CB(pktopts);
-			if (rxopt->srcrt)
-				opt = ipv6_invert_rthdr(sk,
-			  (struct ipv6_rt_hdr *)(skb_network_header(pktopts) +
-						 rxopt->srcrt));
-		}
-
 		if (opt && opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
 			ipv6_addr_copy(&final, &fl.fl6_dst);
@@ -586,6 +579,7 @@
 				kfree(newkey);
 				return -ENOMEM;
 			}
+			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
 		}
 		tcp_alloc_md5sig_pool();
 		if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) {
@@ -720,6 +714,7 @@
 			return -ENOMEM;
 
 		tp->md5sig_info = p;
+		sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
 	}
 
 	newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
@@ -1385,15 +1380,6 @@
 	if (sk_acceptq_is_full(sk))
 		goto out_overflow;
 
-	if (np->rxopt.bits.osrcrt == 2 &&
-	    opt == NULL && treq->pktopts) {
-		struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
-		if (rxopt->srcrt)
-			opt = ipv6_invert_rthdr(sk,
-		   (struct ipv6_rt_hdr *)(skb_network_header(treq->pktopts) +
-					  rxopt->srcrt));
-	}
-
 	if (dst == NULL) {
 		struct in6_addr *final_p = NULL, final;
 		struct flowi fl;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index a7ae59c..4210951 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -52,28 +52,9 @@
 
 DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
 
-static int ipv6_rcv_saddr_any(const struct sock *sk)
-{
-	struct ipv6_pinfo *np = inet6_sk(sk);
-
-	return ipv6_addr_any(&np->rcv_saddr);
-}
-
-static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
-						 const struct sock *sk)
-{
-	return port;
-}
-
-const struct udp_get_port_ops udp_ipv6_ops = {
-	.saddr_cmp = ipv6_rcv_saddr_equal,
-	.saddr_any = ipv6_rcv_saddr_any,
-	.hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
-};
-
 static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
 {
-	return udp_get_port(sk, snum, &udp_ipv6_ops);
+	return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
 }
 
 static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
@@ -767,8 +748,12 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
-		goto out;
+	if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
+		if (err == -EREMOTE)
+			err = ip6_dst_blackhole(sk, &dst, &fl);
+		if (err < 0)
+			goto out;
+	}
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 36b0c11..6e252f3 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -6,8 +6,6 @@
 #include <net/addrconf.h>
 #include <net/inet_common.h>
 
-extern const struct udp_get_port_ops udp_ipv6_ops;
-
 extern int  	__udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
 extern void 	__udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
 			       int , int , int , __be32 , struct hlist_head []);
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index c40a513..f54016a 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -37,7 +37,7 @@
 
 static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
 {
-	return udplite_get_port(sk, snum, &udp_ipv6_ops);
+	return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
 }
 
 struct proto udplitev6_prot = {
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index d7ed8aa..c858537 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -104,10 +104,8 @@
 	nf_reset(skb);
 
 	if (decaps) {
-		if (!(skb->dev->flags&IFF_LOOPBACK)) {
-			dst_release(skb->dst);
-			skb->dst = NULL;
-		}
+		dst_release(skb->dst);
+		skb->dst = NULL;
 		netif_rx(skb);
 		return -1;
 	} else {
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index a6c0cdf..9fc95bc 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -80,6 +80,7 @@
 	top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
 	ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
 	ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+	skb->protocol = htons(ETH_P_IPV6);
 	return 0;
 }
 
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 1faa2ea..3ec0c47 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -18,7 +18,7 @@
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 #include <net/mip6.h>
 #endif
 
@@ -318,7 +318,7 @@
 			fl->proto = nexthdr;
 			return;
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		case IPPROTO_MH:
 			if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
 				struct ip6_mh *mh;
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index baa461b..cdadb48 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -65,7 +65,7 @@
 		goto end;
 
 	/* Rule 2: select MIPv6 RO or inbound trigger */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	for (i = 0; i < n; i++) {
 		if (src[i] &&
 		    (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
@@ -130,7 +130,7 @@
 		goto end;
 
 	/* Rule 2: select MIPv6 RO or inbound trigger */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	for (i = 0; i < n; i++) {
 		if (src[i] &&
 		    (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 5502cc94..6f87dd5 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -379,3 +379,4 @@
 module_init(xfrm6_tunnel_init);
 module_exit(xfrm6_tunnel_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_IPV6);
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index db32ac8..4226e71 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -286,21 +286,21 @@
 	return 0;
 }
 
-static struct seq_operations ipx_seq_interface_ops = {
+static const struct seq_operations ipx_seq_interface_ops = {
 	.start  = ipx_seq_interface_start,
 	.next   = ipx_seq_interface_next,
 	.stop   = ipx_seq_interface_stop,
 	.show   = ipx_seq_interface_show,
 };
 
-static struct seq_operations ipx_seq_route_ops = {
+static const struct seq_operations ipx_seq_route_ops = {
 	.start  = ipx_seq_route_start,
 	.next   = ipx_seq_route_next,
 	.stop   = ipx_seq_route_stop,
 	.show   = ipx_seq_route_show,
 };
 
-static struct seq_operations ipx_seq_socket_ops = {
+static const struct seq_operations ipx_seq_socket_ops = {
 	.start  = ipx_seq_socket_start,
 	.next   = ipx_seq_socket_next,
 	.stop   = ipx_seq_interface_stop,
diff --git a/net/irda/Makefile b/net/irda/Makefile
index d1366c2..187f6c5 100644
--- a/net/irda/Makefile
+++ b/net/irda/Makefile
@@ -10,6 +10,6 @@
 irda-y := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
           irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \
           irttp.o irda_device.o irias_object.o wrapper.o af_irda.o \
-	  discovery.o parameters.o irmod.o
+	  discovery.o parameters.o irnetlink.o irmod.o
 irda-$(CONFIG_PROC_FS) += irproc.o
 irda-$(CONFIG_SYSCTL) += irsysctl.o
diff --git a/net/irda/discovery.c b/net/irda/discovery.c
index f097341..af0cea7 100644
--- a/net/irda/discovery.c
+++ b/net/irda/discovery.c
@@ -395,7 +395,7 @@
 	return 0;
 }
 
-static struct seq_operations discovery_seq_ops = {
+static const struct seq_operations discovery_seq_ops = {
 	.start  = discovery_seq_start,
 	.next   = discovery_seq_next,
 	.stop   = discovery_seq_stop,
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index 4749f8f..2d63fa8 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -562,7 +562,7 @@
 	return 0;
 }
 
-static struct seq_operations ircomm_seq_ops = {
+static const struct seq_operations ircomm_seq_ops = {
 	.start  = ircomm_seq_start,
 	.next   = ircomm_seq_next,
 	.stop   = ircomm_seq_stop,
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 915d938..774eb70 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -1066,7 +1066,7 @@
 	return 0;
 }
 
-static struct seq_operations irias_seq_ops = {
+static const struct seq_operations irias_seq_ops = {
 	.start  = irias_seq_start,
 	.next   = irias_seq_next,
 	.stop   = irias_seq_stop,
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index ed69773..f5778ef 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -1217,7 +1217,7 @@
 	return 0;
 }
 
-static struct seq_operations irlan_seq_ops = {
+static const struct seq_operations irlan_seq_ops = {
 	.start = irlan_seq_start,
 	.next  = irlan_seq_next,
 	.stop  = irlan_seq_stop,
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index d93ebd1..2fc9f51 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -1210,7 +1210,7 @@
 	return 0;
 }
 
-static struct seq_operations irlap_seq_ops = {
+static const struct seq_operations irlap_seq_ops = {
 	.start  = irlap_seq_start,
 	.next   = irlap_seq_next,
 	.stop   = irlap_seq_stop,
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index 0b02073..a8b8873 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -317,23 +317,6 @@
 }
 
 /*
- * Function irlap_next_state (self, state)
- *
- *    Switches state and provides debug information
- *
- */
-static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state)
-{
-	/*
-	if (!self || self->magic != LAP_MAGIC)
-		return;
-
-	IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]);
-	*/
-	self->state = state;
-}
-
-/*
  * Function irlap_state_ndm (event, skb, frame)
  *
  *    NDM (Normal Disconnected Mode) state
@@ -1086,7 +1069,6 @@
 			} else {
 				/* Final packet of window */
 				irlap_send_data_primary_poll(self, skb);
-				irlap_next_state(self, LAP_NRM_P);
 
 				/*
 				 * Make sure state machine does not try to send
@@ -1436,14 +1418,14 @@
 		 */
 		self->remote_busy = FALSE;
 
+		/* Stop final timer */
+		del_timer(&self->final_timer);
+
 		/*
 		 *  Nr as expected?
 		 */
 		ret = irlap_validate_nr_received(self, info->nr);
 		if (ret == NR_EXPECTED) {
-			/* Stop final timer */
-			del_timer(&self->final_timer);
-
 			/* Update Nr received */
 			irlap_update_nr_received(self, info->nr);
 
@@ -1475,14 +1457,12 @@
 
 			/* Resend rejected frames */
 			irlap_resend_rejected_frames(self, CMD_FRAME);
-
-			/* Final timer ??? Jean II */
+			irlap_start_final_timer(self, self->final_timeout * 2);
 
 			irlap_next_state(self, LAP_NRM_P);
 		} else if (ret == NR_INVALID) {
 			IRDA_DEBUG(1, "%s(), Received RR with "
 				   "invalid nr !\n", __FUNCTION__);
-			del_timer(&self->final_timer);
 
 			irlap_next_state(self, LAP_RESET_WAIT);
 
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index 3c5a68e..25a3444 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -101,6 +101,13 @@
 
 	irlap_insert_info(self, skb);
 
+	if (unlikely(self->mode & IRDA_MODE_MONITOR)) {
+		IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __FUNCTION__,
+			   self->netdev->name);
+		dev_kfree_skb(skb);
+		return;
+	}
+
 	dev_queue_xmit(skb);
 }
 
@@ -798,16 +805,19 @@
 		self->vs = (self->vs + 1) % 8;
 		self->ack_required = FALSE;
 
+		irlap_next_state(self, LAP_NRM_P);
 		irlap_send_i_frame(self, tx_skb, CMD_FRAME);
 	} else {
 		IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__);
 
 		if (self->ack_required) {
 			irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);
+			irlap_next_state(self, LAP_NRM_P);
 			irlap_send_rr_frame(self, CMD_FRAME);
 			self->ack_required = FALSE;
 		} else {
 			skb->data[1] |= PF_BIT;
+			irlap_next_state(self, LAP_NRM_P);
 			irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);
 		}
 	}
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 9df0461..24a5e3f 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -1994,7 +1994,7 @@
 	return 0;
 }
 
-static struct seq_operations irlmp_seq_ops = {
+static const struct seq_operations irlmp_seq_ops = {
 	.start  = irlmp_seq_start,
 	.next   = irlmp_seq_next,
 	.stop   = irlmp_seq_stop,
diff --git a/net/irda/irmod.c b/net/irda/irmod.c
index c7fad2c..1900937 100644
--- a/net/irda/irmod.c
+++ b/net/irda/irmod.c
@@ -88,16 +88,23 @@
  */
 static int __init irda_init(void)
 {
+	int ret = 0;
+
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
 
 	/* Lower layer of the stack */
 	irlmp_init();
 	irlap_init();
 
+	/* Driver/dongle support */
+	irda_device_init();
+
 	/* Higher layers of the stack */
 	iriap_init();
 	irttp_init();
-	irsock_init();
+	ret = irsock_init();
+	if (ret < 0)
+		goto out_err_1;
 
 	/* Add IrDA packet type (Start receiving packets) */
 	dev_add_pack(&irda_packet_type);
@@ -107,13 +114,44 @@
 	irda_proc_register();
 #endif
 #ifdef CONFIG_SYSCTL
-	irda_sysctl_register();
+	ret = irda_sysctl_register();
+	if (ret < 0)
+		goto out_err_2;
 #endif
 
-	/* Driver/dongle support */
-	irda_device_init();
+	ret = irda_nl_register();
+	if (ret < 0)
+		goto out_err_3;
 
 	return 0;
+
+ out_err_3:
+#ifdef CONFIG_SYSCTL
+	irda_sysctl_unregister();
+#endif
+ out_err_2:
+#ifdef CONFIG_PROC_FS
+	irda_proc_unregister();
+#endif
+
+	/* Remove IrDA packet type (stop receiving packets) */
+	dev_remove_pack(&irda_packet_type);
+
+	/* Remove higher layers */
+	irsock_cleanup();
+ out_err_1:
+	irttp_cleanup();
+	iriap_cleanup();
+
+	/* Remove lower layers */
+	irda_device_cleanup();
+	irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */
+
+	/* Remove middle layer */
+	irlmp_cleanup();
+
+
+	return ret;
 }
 
 /*
@@ -125,6 +163,8 @@
 static void __exit irda_cleanup(void)
 {
 	/* Remove External APIs */
+	irda_nl_unregister();
+
 #ifdef CONFIG_SYSCTL
 	irda_sysctl_unregister();
 #endif
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
new file mode 100644
index 0000000..db71658
--- /dev/null
+++ b/net/irda/irnetlink.c
@@ -0,0 +1,170 @@
+/*
+ * IrDA netlink layer, for stack configuration.
+ *
+ * Copyright (c) 2007 Samuel Ortiz <samuel@sortiz>
+ *
+ * Partly based on the 802.11 nelink implementation
+ * (see net/wireless/nl80211.c) which is:
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/socket.h>
+#include <linux/irda.h>
+#include <net/sock.h>
+#include <net/irda/irda.h>
+#include <net/irda/irlap.h>
+#include <net/genetlink.h>
+
+
+
+static struct genl_family irda_nl_family = {
+	.id = GENL_ID_GENERATE,
+	.name = IRDA_NL_NAME,
+	.hdrsize = 0,
+	.version = IRDA_NL_VERSION,
+	.maxattr = IRDA_NL_CMD_MAX,
+};
+
+static struct net_device * ifname_to_netdev(struct genl_info *info)
+{
+	char * ifname;
+
+	if (!info->attrs[IRDA_NL_ATTR_IFNAME])
+		return NULL;
+
+	ifname = nla_data(info->attrs[IRDA_NL_ATTR_IFNAME]);
+
+	IRDA_DEBUG(5, "%s(): Looking for %s\n", __FUNCTION__, ifname);
+
+	return dev_get_by_name(ifname);
+}
+
+static int irda_nl_set_mode(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net_device * dev;
+	struct irlap_cb * irlap;
+	u32 mode;
+
+	if (!info->attrs[IRDA_NL_ATTR_MODE])
+		return -EINVAL;
+
+	mode = nla_get_u32(info->attrs[IRDA_NL_ATTR_MODE]);
+
+	IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __FUNCTION__, mode);
+
+	dev = ifname_to_netdev(info);
+	if (!dev)
+		return -ENODEV;
+
+	irlap = (struct irlap_cb *)dev->atalk_ptr;
+	if (!irlap) {
+		dev_put(dev);
+		return -ENODEV;
+	}
+
+	irlap->mode = mode;
+
+	dev_put(dev);
+
+	return 0;
+}
+
+static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net_device * dev;
+	struct irlap_cb * irlap;
+	struct sk_buff *msg;
+	void *hdr;
+	int ret = -ENOBUFS;
+
+	dev = ifname_to_netdev(info);
+	if (!dev)
+		return -ENODEV;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg) {
+		dev_put(dev);
+		return -ENOMEM;
+	}
+
+	irlap = (struct irlap_cb *)dev->atalk_ptr;
+	if (!irlap) {
+		ret = -ENODEV;
+		goto err_out;
+	}
+
+	hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+			  &irda_nl_family, 0,  IRDA_NL_CMD_GET_MODE);
+	if (IS_ERR(hdr)) {
+		ret = PTR_ERR(hdr);
+		goto err_out;
+	}
+
+	if(nla_put_string(msg, IRDA_NL_ATTR_IFNAME,
+			  dev->name));
+		goto err_out;
+
+	if(nla_put_u32(msg, IRDA_NL_ATTR_MODE, irlap->mode))
+		goto err_out;
+
+	genlmsg_end(msg, hdr);
+
+	return genlmsg_unicast(msg, info->snd_pid);
+
+ err_out:
+	nlmsg_free(msg);
+	dev_put(dev);
+
+	return ret;
+}
+
+static struct nla_policy irda_nl_policy[IRDA_NL_ATTR_MAX + 1] = {
+	[IRDA_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING,
+				  .len = IFNAMSIZ-1 },
+	[IRDA_NL_ATTR_MODE] = { .type = NLA_U32 },
+};
+
+static struct genl_ops irda_nl_ops[] = {
+	{
+		.cmd = IRDA_NL_CMD_SET_MODE,
+		.doit = irda_nl_set_mode,
+		.policy = irda_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = IRDA_NL_CMD_GET_MODE,
+		.doit = irda_nl_get_mode,
+		.policy = irda_nl_policy,
+		/* can be retrieved by unprivileged users */
+	},
+
+};
+
+int irda_nl_register(void)
+{
+	int err, i;
+
+	err = genl_register_family(&irda_nl_family);
+	if (err)
+		return err;
+
+	for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) {
+		err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+ err_out:
+	genl_unregister_family(&irda_nl_family);
+	return err;
+}
+
+void irda_nl_unregister(void)
+{
+	genl_unregister_family(&irda_nl_family);
+}
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 7069e4a..7f50832a 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -369,6 +369,20 @@
 /* Everything is happily mixed up. Waiting for next clean up - Jean II */
 
 /*
+ * Initialization, that has to be done on new tsap
+ * instance allocation and on duplication
+ */
+static void irttp_init_tsap(struct tsap_cb *tsap)
+{
+	spin_lock_init(&tsap->lock);
+	init_timer(&tsap->todo_timer);
+
+	skb_queue_head_init(&tsap->rx_queue);
+	skb_queue_head_init(&tsap->tx_queue);
+	skb_queue_head_init(&tsap->rx_fragments);
+}
+
+/*
  * Function irttp_open_tsap (stsap, notify)
  *
  *    Create TSAP connection endpoint,
@@ -395,10 +409,11 @@
 		IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__);
 		return NULL;
 	}
-	spin_lock_init(&self->lock);
+
+	/* Initialize internal objects */
+	irttp_init_tsap(self);
 
 	/* Initialise todo timer */
-	init_timer(&self->todo_timer);
 	self->todo_timer.data     = (unsigned long) self;
 	self->todo_timer.function = &irttp_todo_expired;
 
@@ -418,9 +433,6 @@
 	self->magic = TTP_TSAP_MAGIC;
 	self->connected = FALSE;
 
-	skb_queue_head_init(&self->rx_queue);
-	skb_queue_head_init(&self->tx_queue);
-	skb_queue_head_init(&self->rx_fragments);
 	/*
 	 *  Create LSAP at IrLMP layer
 	 */
@@ -1455,12 +1467,9 @@
 
 	/* Not everything should be copied */
 	new->notify.instance = instance;
-	spin_lock_init(&new->lock);
-	init_timer(&new->todo_timer);
 
-	skb_queue_head_init(&new->rx_queue);
-	skb_queue_head_init(&new->tx_queue);
-	skb_queue_head_init(&new->rx_fragments);
+	/* Initialize internal objects */
+	irttp_init_tsap(new);
 
 	/* This is locked */
 	hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL);
@@ -1866,7 +1875,7 @@
 	return 0;
 }
 
-static struct seq_operations irttp_seq_ops = {
+static const struct seq_operations irttp_seq_ops = {
 	.start  = irttp_seq_start,
 	.next   = irttp_seq_next,
 	.stop   = irttp_seq_stop,
diff --git a/net/iucv/Kconfig b/net/iucv/Kconfig
index f8fcc3d..16ce9cd 100644
--- a/net/iucv/Kconfig
+++ b/net/iucv/Kconfig
@@ -1,13 +1,13 @@
 config IUCV
-	tristate "IUCV support (VM only)"
+	tristate "IUCV support (S390 - z/VM only)"
 	depends on S390
 	help
-	  Select this option if you want to use inter-user communication under
-	  VM or VIF sockets. If you run on z/VM, say "Y" to enable a fast
+	  Select this option if you want to use inter-user communication
+	  under VM or VIF. If you run on z/VM, say "Y" to enable a fast
 	  communication link between VM guests.
 
 config AFIUCV
-	tristate "AF_IUCV support (VM only)"
+	tristate "AF_IUCV support (S390 - z/VM only)"
 	depends on IUCV
 	help
 	  Select this option if you want to use inter-user communication under
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index d9e9ddb..53ae14c 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -219,6 +219,7 @@
 
 	sock_init_data(sock, sk);
 	INIT_LIST_HEAD(&iucv_sk(sk)->accept_q);
+	spin_lock_init(&iucv_sk(sk)->accept_q_lock);
 	skb_queue_head_init(&iucv_sk(sk)->send_skb_q);
 	skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q);
 	iucv_sk(sk)->send_tag = 0;
@@ -274,15 +275,25 @@
 
 void iucv_accept_enqueue(struct sock *parent, struct sock *sk)
 {
+	unsigned long flags;
+	struct iucv_sock *par = iucv_sk(parent);
+
 	sock_hold(sk);
-	list_add_tail(&iucv_sk(sk)->accept_q, &iucv_sk(parent)->accept_q);
+	spin_lock_irqsave(&par->accept_q_lock, flags);
+	list_add_tail(&iucv_sk(sk)->accept_q, &par->accept_q);
+	spin_unlock_irqrestore(&par->accept_q_lock, flags);
 	iucv_sk(sk)->parent = parent;
 	parent->sk_ack_backlog++;
 }
 
 void iucv_accept_unlink(struct sock *sk)
 {
+	unsigned long flags;
+	struct iucv_sock *par = iucv_sk(iucv_sk(sk)->parent);
+
+	spin_lock_irqsave(&par->accept_q_lock, flags);
 	list_del_init(&iucv_sk(sk)->accept_q);
+	spin_unlock_irqrestore(&par->accept_q_lock, flags);
 	iucv_sk(sk)->parent->sk_ack_backlog--;
 	iucv_sk(sk)->parent = NULL;
 	sock_put(sk);
@@ -298,8 +309,8 @@
 		lock_sock(sk);
 
 		if (sk->sk_state == IUCV_CLOSED) {
-			release_sock(sk);
 			iucv_accept_unlink(sk);
+			release_sock(sk);
 			continue;
 		}
 
@@ -879,6 +890,7 @@
 	/* Find out if this path belongs to af_iucv. */
 	read_lock(&iucv_sk_list.lock);
 	iucv = NULL;
+	sk = NULL;
 	sk_for_each(sk, node, &iucv_sk_list.head)
 		if (sk->sk_state == IUCV_LISTEN &&
 		    !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) {
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index b733306..ad5150b 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -1494,7 +1494,10 @@
 	struct iucv_irq_list *p, *n;
 
 	/* Serialize tasklet, iucv_path_sever and iucv_path_connect. */
-	spin_lock(&iucv_table_lock);
+	if (!spin_trylock(&iucv_table_lock)) {
+		tasklet_schedule(&iucv_tasklet);
+		return;
+	}
 	iucv_active_cpu = smp_processor_id();
 
 	spin_lock_irq(&iucv_queue_lock);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index a994441..0f8304b 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1448,8 +1448,6 @@
 	int err;
 	struct km_event c;
 
-	xfrm_probe_algs();
-
 	x = pfkey_msg2xfrm_state(hdr, ext_hdrs);
 	if (IS_ERR(x))
 		return PTR_ERR(x);
@@ -1684,6 +1682,7 @@
 	unsigned proto;
 	struct km_event c;
 	struct xfrm_audit audit_info;
+	int err;
 
 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
 	if (proto == 0)
@@ -1691,7 +1690,9 @@
 
 	audit_info.loginuid = audit_get_loginuid(current->audit_context);
 	audit_info.secid = 0;
-	xfrm_state_flush(proto, &audit_info);
+	err = xfrm_state_flush(proto, &audit_info);
+	if (err)
+		return err;
 	c.data.proto = proto;
 	c.seq = hdr->sadb_msg_seq;
 	c.pid = hdr->sadb_msg_pid;
@@ -2685,10 +2686,13 @@
 {
 	struct km_event c;
 	struct xfrm_audit audit_info;
+	int err;
 
 	audit_info.loginuid = audit_get_loginuid(current->audit_context);
 	audit_info.secid = 0;
-	xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+	err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+	if (err)
+		return err;
 	c.data.type = XFRM_POLICY_TYPE_MAIN;
 	c.event = XFRM_MSG_FLUSHPOLICY;
 	c.pid = hdr->sadb_msg_pid;
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index 3ab9d9f..49be6c9 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -184,14 +184,14 @@
 	return 0;
 }
 
-static struct seq_operations llc_seq_socket_ops = {
+static const struct seq_operations llc_seq_socket_ops = {
 	.start  = llc_seq_start,
 	.next   = llc_seq_next,
 	.stop   = llc_seq_stop,
 	.show   = llc_seq_socket_show,
 };
 
-static struct seq_operations llc_seq_core_ops = {
+static const struct seq_operations llc_seq_core_ops = {
 	.start  = llc_seq_start,
 	.next   = llc_seq_next,
 	.stop   = llc_seq_stop,
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index bb6c0fe..476c848 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -112,7 +112,7 @@
 		      local->wep_iv & 0xffffff);
 DEBUGFS_READONLY_FILE(tx_power_reduction, 20, "%d.%d dBm",
 		      local->hw.conf.tx_power_reduction / 10,
-		      local->hw.conf.tx_power_reduction & 10);
+		      local->hw.conf.tx_power_reduction % 10);
 DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
 		      local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
 
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 9e39646..a3e01d7 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -118,7 +118,7 @@
 			 sdata->u.sta.authenticated ? "AUTH\n" : "",
 			 sdata->u.sta.associated ? "ASSOC\n" : "",
 			 sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
-			 sdata->u.sta.use_protection ? "CTS prot\n" : "");
+			 sdata->use_protection ? "CTS prot\n" : "");
 }
 __IEEE80211_IF_FILE(flags);
 
diff --git a/net/mac80211/hostapd_ioctl.h b/net/mac80211/hostapd_ioctl.h
index 34fa128..52da513 100644
--- a/net/mac80211/hostapd_ioctl.h
+++ b/net/mac80211/hostapd_ioctl.h
@@ -26,24 +26,16 @@
  * mess shall be deleted completely. */
 enum {
 	PRISM2_PARAM_IEEE_802_1X = 23,
-	PRISM2_PARAM_ANTSEL_TX = 24,
-	PRISM2_PARAM_ANTSEL_RX = 25,
 
 	/* Instant802 additions */
 	PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001,
-	PRISM2_PARAM_DROP_UNENCRYPTED = 1002,
 	PRISM2_PARAM_PREAMBLE = 1003,
 	PRISM2_PARAM_SHORT_SLOT_TIME = 1006,
 	PRISM2_PARAM_NEXT_MODE = 1008,
-	PRISM2_PARAM_CLEAR_KEYS = 1009,
 	PRISM2_PARAM_RADIO_ENABLED = 1010,
 	PRISM2_PARAM_ANTENNA_MODE = 1013,
 	PRISM2_PARAM_STAT_TIME = 1016,
 	PRISM2_PARAM_STA_ANTENNA_SEL = 1017,
-	PRISM2_PARAM_FORCE_UNICAST_RATE = 1018,
-	PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019,
-	PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020,
-	PRISM2_PARAM_MAX_RATECTRL_RATE = 1021,
 	PRISM2_PARAM_TX_POWER_REDUCTION = 1022,
 	PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024,
 	PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026,
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 6e36df6..2ddf4ef 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -24,6 +24,7 @@
 #include <linux/compiler.h>
 #include <linux/bitmap.h>
 #include <net/cfg80211.h>
+#include <asm/unaligned.h>
 
 #include "ieee80211_common.h"
 #include "ieee80211_i.h"
@@ -56,6 +57,17 @@
 	{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
 
 
+/*
+ * For seeing transmitted packets on monitor interfaces
+ * we have a radiotap header too.
+ */
+struct ieee80211_tx_status_rtap_hdr {
+	struct ieee80211_radiotap_header hdr;
+	__le16 tx_flags;
+	u8 data_retries;
+} __attribute__ ((packed));
+
+
 static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata,
 					      struct ieee80211_hdr *hdr)
 {
@@ -430,7 +442,7 @@
 	if (!tx->u.tx.rate)
 		return TXRX_DROP;
 	if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
-	    tx->local->cts_protect_erp_frames && tx->fragmented &&
+	    tx->sdata->use_protection && tx->fragmented &&
 	    extra.nonerp) {
 		tx->u.tx.last_frag_rate = tx->u.tx.rate;
 		tx->u.tx.probe_last_frag = extra.probe ? 1 : 0;
@@ -528,7 +540,7 @@
 		/* reserve enough extra head and tail room for possible
 		 * encryption */
 		frag = frags[i] =
-			dev_alloc_skb(tx->local->hw.extra_tx_headroom +
+			dev_alloc_skb(tx->local->tx_headroom +
 				      frag_threshold +
 				      IEEE80211_ENCRYPT_HEADROOM +
 				      IEEE80211_ENCRYPT_TAILROOM);
@@ -537,8 +549,8 @@
 		/* Make sure that all fragments use the same priority so
 		 * that they end up using the same TX queue */
 		frag->priority = first->priority;
-		skb_reserve(frag, tx->local->hw.extra_tx_headroom +
-			IEEE80211_ENCRYPT_HEADROOM);
+		skb_reserve(frag, tx->local->tx_headroom +
+				  IEEE80211_ENCRYPT_HEADROOM);
 		fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);
 		memcpy(fhdr, first->data, hdrlen);
 		if (i == num_fragm - 2)
@@ -856,8 +868,7 @@
 	 * for the frame. */
 	if (mode->mode == MODE_IEEE80211G &&
 	    (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
-	    tx->u.tx.unicast &&
-	    tx->local->cts_protect_erp_frames &&
+	    tx->u.tx.unicast && tx->sdata->use_protection &&
 	    !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
 		control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
 
@@ -1118,7 +1129,138 @@
 }
 
 
-static void inline
+/*
+ * deal with packet injection down monitor interface
+ * with Radiotap Header -- only called for monitor mode interface
+ */
+
+static ieee80211_txrx_result
+__ieee80211_parse_tx_radiotap(
+	struct ieee80211_txrx_data *tx,
+	struct sk_buff *skb, struct ieee80211_tx_control *control)
+{
+	/*
+	 * this is the moment to interpret and discard the radiotap header that
+	 * must be at the start of the packet injected in Monitor mode
+	 *
+	 * Need to take some care with endian-ness since radiotap
+	 * args are little-endian
+	 */
+
+	struct ieee80211_radiotap_iterator iterator;
+	struct ieee80211_radiotap_header *rthdr =
+		(struct ieee80211_radiotap_header *) skb->data;
+	struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode;
+	int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
+
+	/*
+	 * default control situation for all injected packets
+	 * FIXME: this does not suit all usage cases, expand to allow control
+	 */
+
+	control->retry_limit = 1; /* no retry */
+	control->key_idx = -1; /* no encryption key */
+	control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
+			    IEEE80211_TXCTL_USE_CTS_PROTECT);
+	control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT |
+			  IEEE80211_TXCTL_NO_ACK;
+	control->antenna_sel_tx = 0; /* default to default antenna */
+
+	/*
+	 * for every radiotap entry that is present
+	 * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
+	 * entries present, or -EINVAL on error)
+	 */
+
+	while (!ret) {
+		int i, target_rate;
+
+		ret = ieee80211_radiotap_iterator_next(&iterator);
+
+		if (ret)
+			continue;
+
+		/* see if this argument is something we can use */
+		switch (iterator.this_arg_index) {
+		/*
+		 * You must take care when dereferencing iterator.this_arg
+		 * for multibyte types... the pointer is not aligned.  Use
+		 * get_unaligned((type *)iterator.this_arg) to dereference
+		 * iterator.this_arg for type "type" safely on all arches.
+		*/
+		case IEEE80211_RADIOTAP_RATE:
+			/*
+			 * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps
+			 * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps
+			 */
+			target_rate = (*iterator.this_arg) * 5;
+			for (i = 0; i < mode->num_rates; i++) {
+				struct ieee80211_rate *r = &mode->rates[i];
+
+				if (r->rate > target_rate)
+					continue;
+
+				control->rate = r;
+
+				if (r->flags & IEEE80211_RATE_PREAMBLE2)
+					control->tx_rate = r->val2;
+				else
+					control->tx_rate = r->val;
+
+				/* end on exact match */
+				if (r->rate == target_rate)
+					i = mode->num_rates;
+			}
+			break;
+
+		case IEEE80211_RADIOTAP_ANTENNA:
+			/*
+			 * radiotap uses 0 for 1st ant, mac80211 is 1 for
+			 * 1st ant
+			 */
+			control->antenna_sel_tx = (*iterator.this_arg) + 1;
+			break;
+
+		case IEEE80211_RADIOTAP_DBM_TX_POWER:
+			control->power_level = *iterator.this_arg;
+			break;
+
+		case IEEE80211_RADIOTAP_FLAGS:
+			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
+				/*
+				 * this indicates that the skb we have been
+				 * handed has the 32-bit FCS CRC at the end...
+				 * we should react to that by snipping it off
+				 * because it will be recomputed and added
+				 * on transmission
+				 */
+				if (skb->len < (iterator.max_length + FCS_LEN))
+					return TXRX_DROP;
+
+				skb_trim(skb, skb->len - FCS_LEN);
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
+		return TXRX_DROP;
+
+	/*
+	 * remove the radiotap header
+	 * iterator->max_length was sanity-checked against
+	 * skb->len by iterator init
+	 */
+	skb_pull(skb, iterator.max_length);
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result inline
 __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
 		       struct sk_buff *skb,
 		       struct net_device *dev,
@@ -1126,6 +1268,9 @@
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_sub_if_data *sdata;
+	ieee80211_txrx_result res = TXRX_CONTINUE;
+
 	int hdrlen;
 
 	memset(tx, 0, sizeof(*tx));
@@ -1135,7 +1280,32 @@
 	tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	tx->sta = sta_info_get(local, hdr->addr1);
 	tx->fc = le16_to_cpu(hdr->frame_control);
+
+	/*
+	 * set defaults for things that can be set by
+	 * injected radiotap headers
+	 */
 	control->power_level = local->hw.conf.power_level;
+	control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+	if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta)
+		control->antenna_sel_tx = tx->sta->antenna_sel_tx;
+
+	/* process and remove the injection radiotap header */
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) {
+		if (__ieee80211_parse_tx_radiotap(tx, skb, control) ==
+								TXRX_DROP) {
+			return TXRX_DROP;
+		}
+		/*
+		 * we removed the radiotap header after this point,
+		 * we filled control with what we could use
+		 * set to the actual ieee header now
+		 */
+		hdr = (struct ieee80211_hdr *) skb->data;
+		res = TXRX_QUEUED; /* indication it was monitor packet */
+	}
+
 	tx->u.tx.control = control;
 	tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1);
 	if (is_multicast_ether_addr(hdr->addr1))
@@ -1152,9 +1322,6 @@
 		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
 		tx->sta->clear_dst_mask = 0;
 	}
-	control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-	if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta)
-		control->antenna_sel_tx = tx->sta->antenna_sel_tx;
 	hdrlen = ieee80211_get_hdrlen(tx->fc);
 	if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
 		u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
@@ -1162,6 +1329,7 @@
 	}
 	control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
 
+	return res;
 }
 
 static int inline is_ieee80211_device(struct net_device *dev,
@@ -1274,7 +1442,7 @@
 	struct sta_info *sta;
 	ieee80211_tx_handler *handler;
 	struct ieee80211_txrx_data tx;
-	ieee80211_txrx_result res = TXRX_DROP;
+	ieee80211_txrx_result res = TXRX_DROP, res_prepare;
 	int ret, i;
 
 	WARN_ON(__ieee80211_queue_pending(local, control->queue));
@@ -1284,15 +1452,26 @@
 		return 0;
 	}
 
-	__ieee80211_tx_prepare(&tx, skb, dev, control);
+	res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);
+
+	if (res_prepare == TXRX_DROP) {
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
 	sta = tx.sta;
 	tx.u.tx.mgmt_interface = mgmt;
 	tx.u.tx.mode = local->hw.conf.mode;
 
-	for (handler = local->tx_handlers; *handler != NULL; handler++) {
-		res = (*handler)(&tx);
-		if (res != TXRX_CONTINUE)
-			break;
+	if (res_prepare == TXRX_QUEUED) { /* if it was an injected packet */
+		res = TXRX_CONTINUE;
+	} else {
+		for (handler = local->tx_handlers; *handler != NULL;
+		     handler++) {
+			res = (*handler)(&tx);
+			if (res != TXRX_CONTINUE)
+				break;
+		}
 	}
 
 	skb = tx.skb; /* handlers are allowed to change skb */
@@ -1467,8 +1646,7 @@
 	}
 	osdata = IEEE80211_DEV_TO_SUB_IF(odev);
 
-	headroom = osdata->local->hw.extra_tx_headroom +
-		IEEE80211_ENCRYPT_HEADROOM;
+	headroom = osdata->local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM;
 	if (skb_headroom(skb) < headroom) {
 		if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) {
 			dev_kfree_skb(skb);
@@ -1494,6 +1672,56 @@
 }
 
 
+int ieee80211_monitor_start_xmit(struct sk_buff *skb,
+				 struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_tx_packet_data *pkt_data;
+	struct ieee80211_radiotap_header *prthdr =
+		(struct ieee80211_radiotap_header *)skb->data;
+	u16 len;
+
+	/*
+	 * there must be a radiotap header at the
+	 * start in this case
+	 */
+	if (unlikely(prthdr->it_version)) {
+		/* only version 0 is supported */
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	skb->dev = local->mdev;
+
+	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+	memset(pkt_data, 0, sizeof(*pkt_data));
+	pkt_data->ifindex = dev->ifindex;
+	pkt_data->mgmt_iface = 0;
+	pkt_data->do_not_encrypt = 1;
+
+	/* above needed because we set skb device to master */
+
+	/*
+	 * fix up the pointers accounting for the radiotap
+	 * header still being in there.  We are being given
+	 * a precooked IEEE80211 header so no need for
+	 * normal processing
+	 */
+	len = le16_to_cpu(get_unaligned(&prthdr->it_len));
+	skb_set_mac_header(skb, len);
+	skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr));
+	skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr));
+
+	/*
+	 * pass the radiotap header up to
+	 * the next stage intact
+	 */
+	dev_queue_xmit(skb);
+
+	return NETDEV_TX_OK;
+}
+
+
 /**
  * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
  * subinterfaces (wlan#, WDS, and VLAN interfaces)
@@ -1509,8 +1737,8 @@
  * encapsulated packet will then be passed to master interface, wlan#.11, for
  * transmission (through low-level driver).
  */
-static int ieee80211_subif_start_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
+int ieee80211_subif_start_xmit(struct sk_buff *skb,
+			       struct net_device *dev)
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct ieee80211_tx_packet_data *pkt_data;
@@ -1619,7 +1847,7 @@
 	 * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
 	 * alloc_skb() (net/core/skbuff.c)
 	 */
-	head_need = hdrlen + encaps_len + local->hw.extra_tx_headroom;
+	head_need = hdrlen + encaps_len + local->tx_headroom;
 	head_need -= skb_headroom(skb);
 
 	/* We are going to modify skb data, so make a copy of it if happens to
@@ -1658,7 +1886,7 @@
 
 	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
 	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
-	pkt_data->ifindex = sdata->dev->ifindex;
+	pkt_data->ifindex = dev->ifindex;
 	pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
 	pkt_data->do_not_encrypt = no_encrypt;
 
@@ -1706,9 +1934,9 @@
 		return 0;
 	}
 
-	if (skb_headroom(skb) < sdata->local->hw.extra_tx_headroom) {
-		if (pskb_expand_head(skb,
-		    sdata->local->hw.extra_tx_headroom, 0, GFP_ATOMIC)) {
+	if (skb_headroom(skb) < sdata->local->tx_headroom) {
+		if (pskb_expand_head(skb, sdata->local->tx_headroom,
+				     0, GFP_ATOMIC)) {
 			dev_kfree_skb(skb);
 			return 0;
 		}
@@ -1847,12 +2075,12 @@
 	bh_len = ap->beacon_head_len;
 	bt_len = ap->beacon_tail_len;
 
-	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+	skb = dev_alloc_skb(local->tx_headroom +
 		bh_len + bt_len + 256 /* maximum TIM len */);
 	if (!skb)
 		return NULL;
 
-	skb_reserve(skb, local->hw.extra_tx_headroom);
+	skb_reserve(skb, local->tx_headroom);
 	memcpy(skb_put(skb, bh_len), b_head, bh_len);
 
 	ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
@@ -2376,8 +2604,7 @@
 	struct ieee80211_if_init_conf conf;
 
 	if (local->open_count && local->open_count == local->monitors &&
-	    !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) &&
-	    local->ops->add_interface) {
+	    !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) {
 		conf.if_id = -1;
 		conf.type = IEEE80211_IF_TYPE_MNTR;
 		conf.mac_addr = NULL;
@@ -2420,21 +2647,14 @@
 	}
 	ieee80211_start_soft_monitor(local);
 
-	if (local->ops->add_interface) {
-		conf.if_id = dev->ifindex;
-		conf.type = sdata->type;
-		conf.mac_addr = dev->dev_addr;
-		res = local->ops->add_interface(local_to_hw(local), &conf);
-		if (res) {
-			if (sdata->type == IEEE80211_IF_TYPE_MNTR)
-				ieee80211_start_hard_monitor(local);
-			return res;
-		}
-	} else {
-		if (sdata->type != IEEE80211_IF_TYPE_STA)
-			return -EOPNOTSUPP;
-		if (local->open_count > 0)
-			return -ENOBUFS;
+	conf.if_id = dev->ifindex;
+	conf.type = sdata->type;
+	conf.mac_addr = dev->dev_addr;
+	res = local->ops->add_interface(local_to_hw(local), &conf);
+	if (res) {
+		if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+			ieee80211_start_hard_monitor(local);
+		return res;
 	}
 
 	if (local->open_count == 0) {
@@ -2474,6 +2694,8 @@
 	if (sdata->type == IEEE80211_IF_TYPE_STA &&
 	    !local->user_space_mlme)
 		netif_carrier_off(dev);
+	else
+		netif_carrier_on(dev);
 
 	netif_start_queue(dev);
 	return 0;
@@ -2939,34 +3161,6 @@
 }
 EXPORT_SYMBOL(ieee80211_radar_status);
 
-int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, u8 *peer_address,
-			      u16 aid)
-{
-	struct sk_buff *skb;
-	struct ieee80211_msg_set_aid_for_sta *msg;
-	struct ieee80211_local *local = hw_to_local(hw);
-
-	/* unlikely because if this event only happens for APs,
-	 * which require an open ap device. */
-	if (unlikely(!local->apdev))
-		return 0;
-
-	skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
-			    sizeof(struct ieee80211_msg_set_aid_for_sta));
-
-	if (!skb)
-		return -ENOMEM;
-	skb_reserve(skb, sizeof(struct ieee80211_frame_info));
-
-	msg = (struct ieee80211_msg_set_aid_for_sta *)
-		skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta));
-	memcpy(msg->sta_address, peer_address, ETH_ALEN);
-	msg->aid = aid;
-
-	ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta);
-	return 0;
-}
-EXPORT_SYMBOL(ieee80211_set_aid_for_sta);
 
 static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
 {
@@ -3278,8 +3472,10 @@
 			return TXRX_DROP;
 		}
 	}
-	while ((skb = __skb_dequeue(&entry->skb_list)))
+	while ((skb = __skb_dequeue(&entry->skb_list))) {
 		memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
+		dev_kfree_skb(skb);
+	}
 
 	/* Complete frame has been reassembled - process it now */
 	rx->fragmented = 1;
@@ -4280,6 +4476,9 @@
 	struct ieee80211_local *local = hw_to_local(hw);
 	u16 frag, type;
 	u32 msg_type;
+	struct ieee80211_tx_status_rtap_hdr *rthdr;
+	struct ieee80211_sub_if_data *sdata;
+	int monitors;
 
 	if (!status) {
 		printk(KERN_ERR
@@ -4391,27 +4590,100 @@
 			local->dot11FailedCount++;
 	}
 
-	if (!(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS)
-	    || unlikely(!local->apdev)) {
-		dev_kfree_skb(skb);
-		return;
-	}
-
 	msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ?
 		ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail;
 
-	/* skb was the original skb used for TX. Clone it and give the clone
-	 * to netif_rx(). Free original skb. */
-	skb2 = skb_copy(skb, GFP_ATOMIC);
-	if (!skb2) {
+	/* this was a transmitted frame, but now we want to reuse it */
+	skb_orphan(skb);
+
+	if ((status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) &&
+	    local->apdev) {
+		if (local->monitors) {
+			skb2 = skb_clone(skb, GFP_ATOMIC);
+		} else {
+			skb2 = skb;
+			skb = NULL;
+		}
+
+		if (skb2)
+			/* Send frame to hostapd */
+			ieee80211_rx_mgmt(local, skb2, NULL, msg_type);
+
+		if (!skb)
+			return;
+	}
+
+	if (!local->monitors) {
 		dev_kfree_skb(skb);
 		return;
 	}
-	dev_kfree_skb(skb);
-	skb = skb2;
 
-	/* Send frame to hostapd */
-	ieee80211_rx_mgmt(local, skb, NULL, msg_type);
+	/* send frame to monitor interfaces now */
+
+	if (skb_headroom(skb) < sizeof(*rthdr)) {
+		printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	rthdr = (struct ieee80211_tx_status_rtap_hdr*)
+				skb_push(skb, sizeof(*rthdr));
+
+	memset(rthdr, 0, sizeof(*rthdr));
+	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
+	rthdr->hdr.it_present =
+		cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
+			    (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
+
+	if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
+	    !is_multicast_ether_addr(hdr->addr1))
+		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
+
+	if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
+	    (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
+		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
+	else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
+		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
+
+	rthdr->data_retries = status->retry_count;
+
+	read_lock(&local->sub_if_lock);
+	monitors = local->monitors;
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		/*
+		 * Using the monitors counter is possibly racy, but
+		 * if the value is wrong we simply either clone the skb
+		 * once too much or forget sending it to one monitor iface
+		 * The latter case isn't nice but fixing the race is much
+		 * more complicated.
+		 */
+		if (!monitors || !skb)
+			goto out;
+
+		if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
+			if (!netif_running(sdata->dev))
+				continue;
+			monitors--;
+			if (monitors)
+				skb2 = skb_clone(skb, GFP_KERNEL);
+			else
+				skb2 = NULL;
+			skb->dev = sdata->dev;
+			/* XXX: is this sufficient for BPF? */
+			skb_set_mac_header(skb, 0);
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			skb->pkt_type = PACKET_OTHERHOST;
+			skb->protocol = htons(ETH_P_802_2);
+			memset(skb->cb, 0, sizeof(skb->cb));
+			netif_rx(skb);
+			skb = skb2;
+			break;
+		}
+	}
+ out:
+	read_unlock(&local->sub_if_lock);
+	if (skb)
+		dev_kfree_skb(skb);
 }
 EXPORT_SYMBOL(ieee80211_tx_status);
 
@@ -4615,6 +4887,9 @@
 			 ((sizeof(struct ieee80211_local) +
 			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
 
+	BUG_ON(!ops->tx);
+	BUG_ON(!ops->config);
+	BUG_ON(!ops->add_interface);
 	local->ops = ops;
 
 	/* for now, mdev needs sub_if_data :/ */
@@ -4643,8 +4918,6 @@
 	local->short_retry_limit = 7;
 	local->long_retry_limit = 4;
 	local->hw.conf.radio_enabled = 1;
-	local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP;
-	local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN;
 
 	local->enabled_modes = (unsigned int) -1;
 
@@ -4708,6 +4981,14 @@
 		goto fail_workqueue;
 	}
 
+	/*
+	 * The hardware needs headroom for sending the frame,
+	 * and we need some headroom for passing the frame to monitor
+	 * interfaces, but never both at the same time.
+	 */
+	local->tx_headroom = max(local->hw.extra_tx_headroom,
+				 sizeof(struct ieee80211_tx_status_rtap_hdr));
+
 	debugfs_hw_add(local);
 
 	local->hw.conf.beacon_int = 1000;
diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h
index b9a73e7..77c6afb 100644
--- a/net/mac80211/ieee80211_common.h
+++ b/net/mac80211/ieee80211_common.h
@@ -47,21 +47,16 @@
 	ieee80211_msg_normal = 0,
 	ieee80211_msg_tx_callback_ack = 1,
 	ieee80211_msg_tx_callback_fail = 2,
-	ieee80211_msg_passive_scan = 3,
+	/* hole at 3, was ieee80211_msg_passive_scan but unused */
 	ieee80211_msg_wep_frame_unknown_key = 4,
 	ieee80211_msg_michael_mic_failure = 5,
 	/* hole at 6, was monitor but never sent to userspace */
 	ieee80211_msg_sta_not_assoc = 7,
-	ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */,
+	/* 8 was ieee80211_msg_set_aid_for_sta */
 	ieee80211_msg_key_threshold_notification = 9,
 	ieee80211_msg_radar = 11,
 };
 
-struct ieee80211_msg_set_aid_for_sta {
-	char	sta_address[ETH_ALEN];
-	u16	aid;
-};
-
 struct ieee80211_msg_key_notification {
 	int tx_rx_count;
 	char ifname[IFNAMSIZ];
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index af4d14d..055a2a9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -99,6 +99,12 @@
 	int probe_resp;
 	unsigned long last_update;
 
+	/* during assocation, we save an ERP value from a probe response so
+	 * that we can feed ERP info to the driver when handling the
+	 * association completes. these fields probably won't be up-to-date
+	 * otherwise, you probably don't want to use them. */
+	int has_erp_value;
+	u8 erp_value;
 };
 
 
@@ -235,7 +241,6 @@
 	unsigned int authenticated:1;
 	unsigned int associated:1;
 	unsigned int probereq_poll:1;
-	unsigned int use_protection:1;
 	unsigned int create_ibss:1;
 	unsigned int mixed_cell:1;
 	unsigned int wmm_enabled:1;
@@ -278,6 +283,7 @@
 	int mc_count;
 	unsigned int allmulti:1;
 	unsigned int promisc:1;
+	unsigned int use_protection:1; /* CTS protect ERP frames */
 
 	struct net_device_stats stats;
 	int drop_unencrypted;
@@ -392,6 +398,7 @@
 	int monitors;
 	struct iw_statistics wstats;
 	u8 wstats_flags;
+	int tx_headroom; /* required headroom for hardware/radiotap */
 
 	enum {
 		IEEE80211_DEV_UNINITIALIZED = 0,
@@ -437,7 +444,6 @@
 	int *basic_rates[NUM_IEEE80211_MODES];
 
 	int rts_threshold;
-	int cts_protect_erp_frames;
 	int fragmentation_threshold;
 	int short_retry_limit; /* dot11ShortRetryLimit */
 	int long_retry_limit; /* dot11LongRetryLimit */
@@ -513,8 +519,6 @@
 		STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2
 	} sta_antenna_sel;
 
-	int rate_ctrl_num_up, rate_ctrl_num_down;
-
 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 	/* TX/RX handler statistics */
 	unsigned int tx_handlers_drop;
@@ -719,6 +723,8 @@
 			     struct ieee80211_hw_mode *mode);
 void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
 int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
+int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
+int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
 void ieee80211_if_setup(struct net_device *dev);
 void ieee80211_if_mgmt_setup(struct net_device *dev);
 int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
index cf0f32e..8532a5c 100644
--- a/net/mac80211/ieee80211_iface.c
+++ b/net/mac80211/ieee80211_iface.c
@@ -157,6 +157,8 @@
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	int oldtype = sdata->type;
 
+	dev->hard_start_xmit = ieee80211_subif_start_xmit;
+
 	sdata->type = type;
 	switch (type) {
 	case IEEE80211_IF_TYPE_WDS:
@@ -196,6 +198,7 @@
 	}
 	case IEEE80211_IF_TYPE_MNTR:
 		dev->type = ARPHRD_IEEE80211_RADIOTAP;
+		dev->hard_start_xmit = ieee80211_monitor_start_xmit;
 		break;
 	default:
 		printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 352f03b..5918dd0 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -345,6 +345,8 @@
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct iw_range *range = (struct iw_range *) extra;
+	struct ieee80211_hw_mode *mode = NULL;
+	int c = 0;
 
 	data->length = sizeof(struct iw_range);
 	memset(range, 0, sizeof(struct iw_range));
@@ -378,6 +380,29 @@
 	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
 			  IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
 
+	list_for_each_entry(mode, &local->modes_list, list) {
+		int i = 0;
+
+		if (!(local->enabled_modes & (1 << mode->mode)) ||
+		    (local->hw_modes & local->enabled_modes &
+		     (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
+			continue;
+
+		while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) {
+			struct ieee80211_channel *chan = &mode->channels[i];
+
+			if (chan->flag & IEEE80211_CHAN_W_SCAN) {
+				range->freq[c].i = chan->chan;
+				range->freq[c].m = chan->freq * 100000;
+				range->freq[c].e = 1;
+				c++;
+			}
+			i++;
+		}
+	}
+	range->num_channels = c;
+	range->num_frequency = c;
+
 	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
 	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
 	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
@@ -838,6 +863,67 @@
 }
 
 
+static int ieee80211_ioctl_siwrate(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *rate, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw_mode *mode;
+	int i;
+	u32 target_rate = rate->value / 100000;
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (!sdata->bss)
+		return -ENODEV;
+	mode = local->oper_hw_mode;
+	/* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
+	 * target_rate = X, rate->fixed = 1 means only rate X
+	 * target_rate = X, rate->fixed = 0 means all rates <= X */
+	sdata->bss->max_ratectrl_rateidx = -1;
+	sdata->bss->force_unicast_rateidx = -1;
+	if (rate->value < 0)
+		return 0;
+	for (i=0; i< mode->num_rates; i++) {
+		struct ieee80211_rate *rates = &mode->rates[i];
+		int this_rate = rates->rate;
+
+		if (mode->mode == MODE_ATHEROS_TURBO ||
+		    mode->mode == MODE_ATHEROS_TURBOG)
+			this_rate *= 2;
+		if (target_rate == this_rate) {
+			sdata->bss->max_ratectrl_rateidx = i;
+			if (rate->fixed)
+				sdata->bss->force_unicast_rateidx = i;
+			break;
+		}
+	}
+	return 0;
+}
+
+static int ieee80211_ioctl_giwrate(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *rate, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sta_info *sta;
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_STA)
+		sta = sta_info_get(local, sdata->u.sta.bssid);
+	else
+		return -EOPNOTSUPP;
+	if (!sta)
+		return -ENODEV;
+	if (sta->txrate < local->oper_hw_mode->num_rates)
+		rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
+	else
+		rate->value = 0;
+	sta_info_put(sta);
+	return 0;
+}
+
 static int ieee80211_ioctl_siwrts(struct net_device *dev,
 				  struct iw_request_info *info,
 				  struct iw_param *rts, char *extra)
@@ -970,118 +1056,6 @@
 	return 0;
 }
 
-static int ieee80211_ioctl_clear_keys(struct net_device *dev)
-{
-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-	struct ieee80211_key_conf key;
-	int i;
-	u8 addr[ETH_ALEN];
-	struct ieee80211_key_conf *keyconf;
-	struct ieee80211_sub_if_data *sdata;
-	struct sta_info *sta;
-
-	memset(addr, 0xff, ETH_ALEN);
-	read_lock(&local->sub_if_lock);
-	list_for_each_entry(sdata, &local->sub_if_list, list) {
-		for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-			keyconf = NULL;
-			if (sdata->keys[i] &&
-			    !sdata->keys[i]->force_sw_encrypt &&
-			    local->ops->set_key &&
-			    (keyconf = ieee80211_key_data2conf(local,
-							       sdata->keys[i])))
-				local->ops->set_key(local_to_hw(local),
-						   DISABLE_KEY, addr,
-						   keyconf, 0);
-			kfree(keyconf);
-			ieee80211_key_free(sdata->keys[i]);
-			sdata->keys[i] = NULL;
-		}
-		sdata->default_key = NULL;
-	}
-	read_unlock(&local->sub_if_lock);
-
-	spin_lock_bh(&local->sta_lock);
-	list_for_each_entry(sta, &local->sta_list, list) {
-		keyconf = NULL;
-		if (sta->key && !sta->key->force_sw_encrypt &&
-		    local->ops->set_key &&
-		    (keyconf = ieee80211_key_data2conf(local, sta->key)))
-			local->ops->set_key(local_to_hw(local), DISABLE_KEY,
-					   sta->addr, keyconf, sta->aid);
-		kfree(keyconf);
-		ieee80211_key_free(sta->key);
-		sta->key = NULL;
-	}
-	spin_unlock_bh(&local->sta_lock);
-
-	memset(&key, 0, sizeof(key));
-	if (local->ops->set_key &&
-		    local->ops->set_key(local_to_hw(local), REMOVE_ALL_KEYS,
-				       NULL, &key, 0))
-		printk(KERN_DEBUG "%s: failed to remove hwaccel keys\n",
-		       dev->name);
-
-	return 0;
-}
-
-
-static int
-ieee80211_ioctl_force_unicast_rate(struct net_device *dev,
-				   struct ieee80211_sub_if_data *sdata,
-				   int rate)
-{
-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-	struct ieee80211_hw_mode *mode;
-	int i;
-
-	if (sdata->type != IEEE80211_IF_TYPE_AP)
-		return -ENOENT;
-
-	if (rate == 0) {
-		sdata->u.ap.force_unicast_rateidx = -1;
-		return 0;
-	}
-
-	mode = local->oper_hw_mode;
-	for (i = 0; i < mode->num_rates; i++) {
-		if (mode->rates[i].rate == rate) {
-			sdata->u.ap.force_unicast_rateidx = i;
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-
-static int
-ieee80211_ioctl_max_ratectrl_rate(struct net_device *dev,
-				  struct ieee80211_sub_if_data *sdata,
-				  int rate)
-{
-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-	struct ieee80211_hw_mode *mode;
-	int i;
-
-	if (sdata->type != IEEE80211_IF_TYPE_AP)
-		return -ENOENT;
-
-	if (rate == 0) {
-		sdata->u.ap.max_ratectrl_rateidx = -1;
-		return 0;
-	}
-
-	mode = local->oper_hw_mode;
-	for (i = 0; i < mode->num_rates; i++) {
-		if (mode->rates[i].rate == rate) {
-			sdata->u.ap.max_ratectrl_rateidx = i;
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-
 static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local,
 					 struct ieee80211_key *key)
 {
@@ -1205,24 +1179,11 @@
 			sdata->ieee802_1x = value;
 		break;
 
-	case PRISM2_PARAM_ANTSEL_TX:
-		local->hw.conf.antenna_sel_tx = value;
-		if (ieee80211_hw_config(local))
-			ret = -EINVAL;
-		break;
-
-	case PRISM2_PARAM_ANTSEL_RX:
-		local->hw.conf.antenna_sel_rx = value;
-		if (ieee80211_hw_config(local))
-			ret = -EINVAL;
-		break;
-
 	case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
-		local->cts_protect_erp_frames = value;
-		break;
-
-	case PRISM2_PARAM_DROP_UNENCRYPTED:
-		sdata->drop_unencrypted = value;
+		if (sdata->type != IEEE80211_IF_TYPE_AP)
+			ret = -ENOENT;
+		else
+			sdata->use_protection = value;
 		break;
 
 	case PRISM2_PARAM_PREAMBLE:
@@ -1251,10 +1212,6 @@
 		local->next_mode = value;
 		break;
 
-	case PRISM2_PARAM_CLEAR_KEYS:
-		ret = ieee80211_ioctl_clear_keys(dev);
-		break;
-
 	case PRISM2_PARAM_RADIO_ENABLED:
 		ret = ieee80211_ioctl_set_radio_enabled(dev, value);
 		break;
@@ -1269,22 +1226,6 @@
 		local->sta_antenna_sel = value;
 		break;
 
-	case PRISM2_PARAM_FORCE_UNICAST_RATE:
-		ret = ieee80211_ioctl_force_unicast_rate(dev, sdata, value);
-		break;
-
-	case PRISM2_PARAM_MAX_RATECTRL_RATE:
-		ret = ieee80211_ioctl_max_ratectrl_rate(dev, sdata, value);
-		break;
-
-	case PRISM2_PARAM_RATE_CTRL_NUM_UP:
-		local->rate_ctrl_num_up = value;
-		break;
-
-	case PRISM2_PARAM_RATE_CTRL_NUM_DOWN:
-		local->rate_ctrl_num_down = value;
-		break;
-
 	case PRISM2_PARAM_TX_POWER_REDUCTION:
 		if (value < 0)
 			ret = -EINVAL;
@@ -1364,20 +1305,8 @@
 		*param = sdata->ieee802_1x;
 		break;
 
-	case PRISM2_PARAM_ANTSEL_TX:
-		*param = local->hw.conf.antenna_sel_tx;
-		break;
-
-	case PRISM2_PARAM_ANTSEL_RX:
-		*param = local->hw.conf.antenna_sel_rx;
-		break;
-
 	case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
-		*param = local->cts_protect_erp_frames;
-		break;
-
-	case PRISM2_PARAM_DROP_UNENCRYPTED:
-		*param = sdata->drop_unencrypted;
+		*param = sdata->use_protection;
 		break;
 
 	case PRISM2_PARAM_PREAMBLE:
@@ -1403,14 +1332,6 @@
 		*param = local->sta_antenna_sel;
 		break;
 
-	case PRISM2_PARAM_RATE_CTRL_NUM_UP:
-		*param = local->rate_ctrl_num_up;
-		break;
-
-	case PRISM2_PARAM_RATE_CTRL_NUM_DOWN:
-		*param = local->rate_ctrl_num_down;
-		break;
-
 	case PRISM2_PARAM_TX_POWER_REDUCTION:
 		*param = local->hw.conf.tx_power_reduction;
 		break;
@@ -1778,8 +1699,8 @@
 	(iw_handler) NULL,				/* SIOCGIWNICKN */
 	(iw_handler) NULL,				/* -- hole -- */
 	(iw_handler) NULL,				/* -- hole -- */
-	(iw_handler) NULL,				/* SIOCSIWRATE */
-	(iw_handler) NULL,				/* SIOCGIWRATE */
+	(iw_handler) ieee80211_ioctl_siwrate,		/* SIOCSIWRATE */
+	(iw_handler) ieee80211_ioctl_giwrate,		/* SIOCGIWRATE */
 	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */
 	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */
 	(iw_handler) ieee80211_ioctl_siwfrag,		/* SIOCSIWFRAG */
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 3e07e9d..ba2bf8f 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -76,33 +76,36 @@
 
 /* Parsed Information Elements */
 struct ieee802_11_elems {
+	/* pointers to IEs */
 	u8 *ssid;
-	u8 ssid_len;
 	u8 *supp_rates;
-	u8 supp_rates_len;
 	u8 *fh_params;
-	u8 fh_params_len;
 	u8 *ds_params;
-	u8 ds_params_len;
 	u8 *cf_params;
-	u8 cf_params_len;
 	u8 *tim;
-	u8 tim_len;
 	u8 *ibss_params;
-	u8 ibss_params_len;
 	u8 *challenge;
-	u8 challenge_len;
 	u8 *wpa;
-	u8 wpa_len;
 	u8 *rsn;
-	u8 rsn_len;
 	u8 *erp_info;
-	u8 erp_info_len;
 	u8 *ext_supp_rates;
-	u8 ext_supp_rates_len;
 	u8 *wmm_info;
-	u8 wmm_info_len;
 	u8 *wmm_param;
+
+	/* length of them, respectively */
+	u8 ssid_len;
+	u8 supp_rates_len;
+	u8 fh_params_len;
+	u8 ds_params_len;
+	u8 cf_params_len;
+	u8 tim_len;
+	u8 ibss_params_len;
+	u8 challenge_len;
+	u8 wpa_len;
+	u8 rsn_len;
+	u8 erp_info_len;
+	u8 ext_supp_rates_len;
+	u8 wmm_info_len;
 	u8 wmm_param_len;
 };
 
@@ -311,6 +314,25 @@
 }
 
 
+static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+	int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+
+	if (use_protection != sdata->use_protection) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
+			       MAC_FMT ")\n",
+			       dev->name,
+			       use_protection ? "enabled" : "disabled",
+			       MAC_ARG(ifsta->bssid));
+		}
+		sdata->use_protection = use_protection;
+	}
+}
+
+
 static void ieee80211_sta_send_associnfo(struct net_device *dev,
 					 struct ieee80211_if_sta *ifsta)
 {
@@ -366,6 +388,7 @@
 				     struct ieee80211_if_sta *ifsta, int assoc)
 {
 	union iwreq_data wrqu;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	if (ifsta->associated == assoc)
 		return;
@@ -374,9 +397,18 @@
 
 	if (assoc) {
 		struct ieee80211_sub_if_data *sdata;
+		struct ieee80211_sta_bss *bss;
 		sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 		if (sdata->type != IEEE80211_IF_TYPE_STA)
 			return;
+
+		bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+		if (bss) {
+			if (bss->has_erp_value)
+				ieee80211_handle_erp_ie(dev, bss->erp_value);
+			ieee80211_rx_bss_put(dev, bss);
+		}
+
 		netif_carrier_on(dev);
 		ifsta->prev_bssid_set = 1;
 		memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
@@ -384,6 +416,7 @@
 		ieee80211_sta_send_associnfo(dev, ifsta);
 	} else {
 		netif_carrier_off(dev);
+		sdata->use_protection = 0;
 		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
 	}
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -1155,6 +1188,8 @@
 	if (status_code != WLAN_STATUS_SUCCESS) {
 		printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
 		       dev->name, status_code);
+		if (status_code == WLAN_STATUS_REASSOC_NO_ASSOC)
+			ifsta->prev_bssid_set = 0;
 		return;
 	}
 
@@ -1172,6 +1207,18 @@
 		return;
 	}
 
+	/* it probably doesn't, but if the frame includes an ERP value then
+	 * update our stored copy */
+	if (elems.erp_info && elems.erp_info_len >= 1) {
+		struct ieee80211_sta_bss *bss
+			= ieee80211_rx_bss_get(dev, ifsta->bssid);
+		if (bss) {
+			bss->erp_value = elems.erp_info[0];
+			bss->has_erp_value = 1;
+			ieee80211_rx_bss_put(dev, bss);
+		}
+	}
+
 	printk(KERN_DEBUG "%s: associated\n", dev->name);
 	ifsta->aid = aid;
 	ifsta->ap_capab = capab_info;
@@ -1494,6 +1541,12 @@
 		return;
 	}
 
+	/* save the ERP value so that it is available at association time */
+	if (elems.erp_info && elems.erp_info_len >= 1) {
+		bss->erp_value = elems.erp_info[0];
+		bss->has_erp_value = 1;
+	}
+
 	bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
 	bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
 	if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
@@ -1609,10 +1662,8 @@
 				     size_t len,
 				     struct ieee80211_rx_status *rx_status)
 {
-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_if_sta *ifsta;
-	int use_protection;
 	size_t baselen;
 	struct ieee802_11_elems elems;
 
@@ -1636,23 +1687,8 @@
 				   &elems) == ParseFailed)
 		return;
 
-	use_protection = 0;
-	if (elems.erp_info && elems.erp_info_len >= 1) {
-		use_protection =
-			(elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
-	}
-
-	if (use_protection != !!ifsta->use_protection) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
-			       MAC_FMT ")\n",
-			       dev->name,
-			       use_protection ? "enabled" : "disabled",
-			       MAC_ARG(ifsta->bssid));
-		}
-		ifsta->use_protection = use_protection ? 1 : 0;
-		local->cts_protect_erp_frames = use_protection;
-	}
+	if (elems.erp_info && elems.erp_info_len >= 1)
+		ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
 
 	if (elems.wmm_param && ifsta->wmm_enabled) {
 		ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
@@ -2590,11 +2626,17 @@
 
 	read_lock(&local->sub_if_lock);
 	list_for_each_entry(sdata, &local->sub_if_list, list) {
+
+		/* No need to wake the master device. */
+		if (sdata->dev == local->mdev)
+			continue;
+
 		if (sdata->type == IEEE80211_IF_TYPE_STA) {
 			if (sdata->u.sta.associated)
 				ieee80211_send_nullfunc(local, sdata, 0);
 			ieee80211_sta_timer((unsigned long)sdata);
 		}
+
 		netif_wake_queue(sdata->dev);
 	}
 	read_unlock(&local->sub_if_lock);
@@ -2736,6 +2778,12 @@
 
 	read_lock(&local->sub_if_lock);
 	list_for_each_entry(sdata, &local->sub_if_list, list) {
+
+		/* Don't stop the master interface, otherwise we can't transmit
+		 * probes! */
+		if (sdata->dev == local->mdev)
+			continue;
+
 		netif_stop_queue(sdata->dev);
 		if (sdata->type == IEEE80211_IF_TYPE_STA &&
 		    sdata->u.sta.associated)
@@ -2995,7 +3043,7 @@
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct sta_info *sta;
-	struct ieee80211_sub_if_data *sdata = NULL;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	/* TODO: Could consider removing the least recently used entry and
 	 * allow new one to be added. */
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
index 2048cfd..f6780d6 100644
--- a/net/mac80211/rc80211_simple.c
+++ b/net/mac80211/rc80211_simple.c
@@ -187,9 +187,13 @@
 		}
 #endif
 
-		if (per_failed > local->rate_ctrl_num_down) {
+		/*
+		 * XXX: Make these configurable once we have an
+		 * interface to the rate control algorithms
+		 */
+		if (per_failed > RATE_CONTROL_NUM_DOWN) {
 			rate_control_rate_dec(local, sta);
-		} else if (per_failed < local->rate_ctrl_num_up) {
+		} else if (per_failed < RATE_CONTROL_NUM_UP) {
 			rate_control_rate_inc(local, sta);
 		}
 		srctrl->tx_avg_rate_sum += status->control.rate->rate;
@@ -283,14 +287,16 @@
 	int i;
 	sta->txrate = 0;
 	mode = local->oper_hw_mode;
-	/* TODO: what is a good starting rate for STA? About middle? Maybe not
-	 * the lowest or the highest rate.. Could consider using RSSI from
-	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
-	 * after assoc.. */
+	/* TODO: This routine should consider using RSSI from previous packets
+	 * as we need to have IEEE 802.1X auth succeed immediately after assoc..
+	 * Until that method is implemented, we will use the lowest supported rate
+	 * as a workaround, */
 	for (i = 0; i < mode->num_rates; i++) {
 		if ((sta->supp_rates & BIT(i)) &&
-		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
+		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) {
 			sta->txrate = i;
+			break;
+		}
 	}
 }
 
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index a567dae..3ac39f1 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -102,6 +102,16 @@
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NF_CT_PROTO_UDPLITE
+	tristate 'UDP-Lite protocol connection tracking support (EXPERIMENTAL)'
+	depends on EXPERIMENTAL && NF_CONNTRACK
+	help
+	  With this option enabled, the layer 3 independent connection
+	  tracking code will be able to do state tracking on UDP-Lite
+	  connections.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NF_CONNTRACK_AMANDA
 	tristate "Amanda backup protocol support"
 	depends on NF_CONNTRACK
@@ -343,6 +353,18 @@
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_TRACE
+	tristate  '"TRACE" target support'
+	depends on NETFILTER_XTABLES
+	depends on IP_NF_RAW || IP6_NF_RAW
+	help
+	  The TRACE target allows you to mark packets so that the kernel
+	  will log every rule which match the packets as those traverse
+	  the tables, chains, rules.
+
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 config NETFILTER_XT_TARGET_SECMARK
 	tristate '"SECMARK" target support'
 	depends on NETFILTER_XTABLES && NETWORK_SECMARK
@@ -411,6 +433,13 @@
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_MATCH_CONNLIMIT
+	tristate '"connlimit" match support"'
+	depends on NETFILTER_XTABLES
+	---help---
+	  This match allows you to match against the number of parallel
+	  connections to a server per client IP address (or address block).
+
 config NETFILTER_XT_MATCH_CONNMARK
 	tristate  '"connmark" connection mark match support'
 	depends on NETFILTER_XTABLES
@@ -635,6 +664,19 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_U32
+	tristate '"u32" match support'
+	depends on NETFILTER_XTABLES
+	---help---
+	  u32 allows you to extract quantities of up to 4 bytes from a packet,
+	  AND them with specified masks, shift them by specified amounts and
+	  test whether the results are in any of a set of specified ranges.
+	  The specification of what to extract is general enough to skip over
+	  headers with lengths stored in the packet, as in IP or TCP header
+	  lengths.
+
+	  Details and examples are in the kernel module source.
+
 config NETFILTER_XT_MATCH_HASHLIMIT
 	tristate '"hashlimit" match support'
 	depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index b2b5c75..0c054bf 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,6 +1,6 @@
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
 
-nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o
 nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
@@ -16,6 +16,7 @@
 # SCTP protocol connection tracking
 obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
 obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
 
 # netlink interface for nf_conntrack
 obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
@@ -44,6 +45,7 @@
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
@@ -51,6 +53,7 @@
 # matches
 obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
@@ -72,4 +75,5 @@
 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index a84478e..381a77c 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -203,7 +203,9 @@
 		return 0;
 
 	/* Not exclusive use of packet?  Must copy. */
-	if (skb_shared(*pskb) || skb_cloned(*pskb))
+	if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len))
+		goto copy_skb;
+	if (skb_shared(*pskb))
 		goto copy_skb;
 
 	return pskb_may_pull(*pskb, writable_len);
@@ -229,13 +231,13 @@
 {
 	__be32 diff[] = { ~from, to };
 	if (skb->ip_summed != CHECKSUM_PARTIAL) {
-		*sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
+		*sum = csum_fold(csum_partial(diff, sizeof(diff),
 				~csum_unfold(*sum)));
 		if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
-			skb->csum = ~csum_partial((char *)diff, sizeof(diff),
+			skb->csum = ~csum_partial(diff, sizeof(diff),
 						~skb->csum);
 	} else if (pseudohdr)
-		*sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff),
+		*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
 				csum_unfold(*sum)));
 }
 EXPORT_SYMBOL(nf_proto_csum_replace4);
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index b8869ea..e42ab23 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -142,23 +142,22 @@
 		if (port == 0 || len > 5)
 			break;
 
-		exp = nf_conntrack_expect_alloc(ct);
+		exp = nf_ct_expect_alloc(ct);
 		if (exp == NULL) {
 			ret = NF_DROP;
 			goto out;
 		}
 		tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-		nf_conntrack_expect_init(exp, family,
-					 &tuple->src.u3, &tuple->dst.u3,
-					 IPPROTO_TCP, NULL, &port);
+		nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+				  IPPROTO_TCP, NULL, &port);
 
 		nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
 		if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
 			ret = nf_nat_amanda(pskb, ctinfo, off - dataoff,
 					    len, exp);
-		else if (nf_conntrack_expect_related(exp) != 0)
+		else if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
-		nf_conntrack_expect_put(exp);
+		nf_ct_expect_put(exp);
 	}
 
 out:
@@ -175,9 +174,6 @@
 		.tuple.src.l3num	= AF_INET,
 		.tuple.src.u.udp.port	= __constant_htons(10080),
 		.tuple.dst.protonum	= IPPROTO_UDP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 	},
 	{
 		.name			= "amanda",
@@ -188,9 +184,6 @@
 		.tuple.src.l3num	= AF_INET6,
 		.tuple.src.u.udp.port	= __constant_htons(10080),
 		.tuple.dst.protonum	= IPPROTO_UDP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 	},
 };
 
@@ -208,13 +201,14 @@
 {
 	int ret, i;
 
-	ret = -ENOMEM;
 	for (i = 0; i < ARRAY_SIZE(search); i++) {
 		search[i].ts = textsearch_prepare(ts_algo, search[i].string,
 						  search[i].len,
 						  GFP_KERNEL, TS_AUTOLOAD);
-		if (search[i].ts == NULL)
+		if (IS_ERR(search[i].ts)) {
+			ret = PTR_ERR(search[i].ts);
 			goto err1;
+		}
 	}
 	ret = nf_conntrack_helper_register(&amanda_helper[0]);
 	if (ret < 0)
@@ -227,10 +221,9 @@
 err2:
 	nf_conntrack_helper_unregister(&amanda_helper[0]);
 err1:
-	for (; i >= 0; i--) {
-		if (search[i].ts)
-			textsearch_destroy(search[i].ts);
-	}
+	while (--i >= 0)
+		textsearch_destroy(search[i].ts);
+
 	return ret;
 }
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index e8b5c2d..8cce814 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -36,15 +36,10 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
 #define NF_CONNTRACK_VERSION	"0.5.0"
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 DEFINE_RWLOCK(nf_conntrack_lock);
 EXPORT_SYMBOL_GPL(nf_conntrack_lock);
 
@@ -52,57 +47,27 @@
 atomic_t nf_conntrack_count = ATOMIC_INIT(0);
 EXPORT_SYMBOL_GPL(nf_conntrack_count);
 
-void (*nf_conntrack_destroyed)(struct nf_conn *conntrack);
-EXPORT_SYMBOL_GPL(nf_conntrack_destroyed);
-
 unsigned int nf_conntrack_htable_size __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
 
 int nf_conntrack_max __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_max);
 
-struct list_head *nf_conntrack_hash __read_mostly;
+struct hlist_head *nf_conntrack_hash __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_hash);
 
 struct nf_conn nf_conntrack_untracked __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_untracked);
 
 unsigned int nf_ct_log_invalid __read_mostly;
-LIST_HEAD(unconfirmed);
+HLIST_HEAD(unconfirmed);
 static int nf_conntrack_vmalloc __read_mostly;
-
+static struct kmem_cache *nf_conntrack_cachep __read_mostly;
 static unsigned int nf_conntrack_next_id;
 
 DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
 EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat);
 
-/*
- * This scheme offers various size of "struct nf_conn" dependent on
- * features(helper, nat, ...)
- */
-
-#define NF_CT_FEATURES_NAMELEN	256
-static struct {
-	/* name of slab cache. printed in /proc/slabinfo */
-	char *name;
-
-	/* size of slab cache */
-	size_t size;
-
-	/* slab cache pointer */
-	struct kmem_cache *cachep;
-
-	/* allocated slab cache + modules which uses this slab cache */
-	int use;
-
-} nf_ct_cache[NF_CT_F_NUM];
-
-/* protect members of nf_ct_cache except of "use" */
-DEFINE_RWLOCK(nf_ct_cache_lock);
-
-/* This avoids calling kmem_cache_create() with same name simultaneously */
-static DEFINE_MUTEX(nf_ct_cache_mutex);
-
 static int nf_conntrack_hash_rnd_initted;
 static unsigned int nf_conntrack_hash_rnd;
 
@@ -125,122 +90,6 @@
 				nf_conntrack_hash_rnd);
 }
 
-int nf_conntrack_register_cache(u_int32_t features, const char *name,
-				size_t size)
-{
-	int ret = 0;
-	char *cache_name;
-	struct kmem_cache *cachep;
-
-	DEBUGP("nf_conntrack_register_cache: features=0x%x, name=%s, size=%d\n",
-	       features, name, size);
-
-	if (features < NF_CT_F_BASIC || features >= NF_CT_F_NUM) {
-		DEBUGP("nf_conntrack_register_cache: invalid features.: 0x%x\n",
-			features);
-		return -EINVAL;
-	}
-
-	mutex_lock(&nf_ct_cache_mutex);
-
-	write_lock_bh(&nf_ct_cache_lock);
-	/* e.g: multiple helpers are loaded */
-	if (nf_ct_cache[features].use > 0) {
-		DEBUGP("nf_conntrack_register_cache: already resisterd.\n");
-		if ((!strncmp(nf_ct_cache[features].name, name,
-			      NF_CT_FEATURES_NAMELEN))
-		    && nf_ct_cache[features].size == size) {
-			DEBUGP("nf_conntrack_register_cache: reusing.\n");
-			nf_ct_cache[features].use++;
-			ret = 0;
-		} else
-			ret = -EBUSY;
-
-		write_unlock_bh(&nf_ct_cache_lock);
-		mutex_unlock(&nf_ct_cache_mutex);
-		return ret;
-	}
-	write_unlock_bh(&nf_ct_cache_lock);
-
-	/*
-	 * The memory space for name of slab cache must be alive until
-	 * cache is destroyed.
-	 */
-	cache_name = kmalloc(sizeof(char)*NF_CT_FEATURES_NAMELEN, GFP_ATOMIC);
-	if (cache_name == NULL) {
-		DEBUGP("nf_conntrack_register_cache: can't alloc cache_name\n");
-		ret = -ENOMEM;
-		goto out_up_mutex;
-	}
-
-	if (strlcpy(cache_name, name, NF_CT_FEATURES_NAMELEN)
-						>= NF_CT_FEATURES_NAMELEN) {
-		printk("nf_conntrack_register_cache: name too long\n");
-		ret = -EINVAL;
-		goto out_free_name;
-	}
-
-	cachep = kmem_cache_create(cache_name, size, 0, 0,
-				   NULL, NULL);
-	if (!cachep) {
-		printk("nf_conntrack_register_cache: Can't create slab cache "
-		       "for the features = 0x%x\n", features);
-		ret = -ENOMEM;
-		goto out_free_name;
-	}
-
-	write_lock_bh(&nf_ct_cache_lock);
-	nf_ct_cache[features].use = 1;
-	nf_ct_cache[features].size = size;
-	nf_ct_cache[features].cachep = cachep;
-	nf_ct_cache[features].name = cache_name;
-	write_unlock_bh(&nf_ct_cache_lock);
-
-	goto out_up_mutex;
-
-out_free_name:
-	kfree(cache_name);
-out_up_mutex:
-	mutex_unlock(&nf_ct_cache_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_register_cache);
-
-/* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */
-void nf_conntrack_unregister_cache(u_int32_t features)
-{
-	struct kmem_cache *cachep;
-	char *name;
-
-	/*
-	 * This assures that kmem_cache_create() isn't called before destroying
-	 * slab cache.
-	 */
-	DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features);
-	mutex_lock(&nf_ct_cache_mutex);
-
-	write_lock_bh(&nf_ct_cache_lock);
-	if (--nf_ct_cache[features].use > 0) {
-		write_unlock_bh(&nf_ct_cache_lock);
-		mutex_unlock(&nf_ct_cache_mutex);
-		return;
-	}
-	cachep = nf_ct_cache[features].cachep;
-	name = nf_ct_cache[features].name;
-	nf_ct_cache[features].cachep = NULL;
-	nf_ct_cache[features].name = NULL;
-	nf_ct_cache[features].size = 0;
-	write_unlock_bh(&nf_ct_cache_lock);
-
-	synchronize_net();
-
-	kmem_cache_destroy(cachep);
-	kfree(name);
-
-	mutex_unlock(&nf_ct_cache_mutex);
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_unregister_cache);
-
 int
 nf_ct_get_tuple(const struct sk_buff *skb,
 		unsigned int nhoff,
@@ -264,6 +113,36 @@
 }
 EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
 
+int nf_ct_get_tuplepr(const struct sk_buff *skb,
+		      unsigned int nhoff,
+		      u_int16_t l3num,
+		      struct nf_conntrack_tuple *tuple)
+{
+	struct nf_conntrack_l3proto *l3proto;
+	struct nf_conntrack_l4proto *l4proto;
+	unsigned int protoff;
+	u_int8_t protonum;
+	int ret;
+
+	rcu_read_lock();
+
+	l3proto = __nf_ct_l3proto_find(l3num);
+	ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum);
+	if (ret != NF_ACCEPT) {
+		rcu_read_unlock();
+		return 0;
+	}
+
+	l4proto = __nf_ct_l4proto_find(l3num, protonum);
+
+	ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple,
+			      l3proto, l4proto);
+
+	rcu_read_unlock();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr);
+
 int
 nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
 		   const struct nf_conntrack_tuple *orig,
@@ -286,9 +165,9 @@
 static void
 clean_from_lists(struct nf_conn *ct)
 {
-	DEBUGP("clean_from_lists(%p)\n", ct);
-	list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
-	list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
+	pr_debug("clean_from_lists(%p)\n", ct);
+	hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
+	hlist_del(&ct->tuplehash[IP_CT_DIR_REPLY].hnode);
 
 	/* Destroy all pending expectations */
 	nf_ct_remove_expectations(ct);
@@ -298,20 +177,15 @@
 destroy_conntrack(struct nf_conntrack *nfct)
 {
 	struct nf_conn *ct = (struct nf_conn *)nfct;
-	struct nf_conn_help *help = nfct_help(ct);
 	struct nf_conntrack_l4proto *l4proto;
-	typeof(nf_conntrack_destroyed) destroyed;
 
-	DEBUGP("destroy_conntrack(%p)\n", ct);
+	pr_debug("destroy_conntrack(%p)\n", ct);
 	NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
 	NF_CT_ASSERT(!timer_pending(&ct->timeout));
 
 	nf_conntrack_event(IPCT_DESTROY, ct);
 	set_bit(IPS_DYING_BIT, &ct->status);
 
-	if (help && help->helper && help->helper->destroy)
-		help->helper->destroy(ct);
-
 	/* To make sure we don't get any weird locking issues here:
 	 * destroy_conntrack() MUST NOT be called with a write lock
 	 * to nf_conntrack_lock!!! -HW */
@@ -321,9 +195,7 @@
 	if (l4proto && l4proto->destroy)
 		l4proto->destroy(ct);
 
-	destroyed = rcu_dereference(nf_conntrack_destroyed);
-	if (destroyed)
-		destroyed(ct);
+	nf_ct_ext_destroy(ct);
 
 	rcu_read_unlock();
 
@@ -336,8 +208,8 @@
 
 	/* We overload first tuple to link into unconfirmed list. */
 	if (!nf_ct_is_confirmed(ct)) {
-		BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list));
-		list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+		BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode));
+		hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
 	}
 
 	NF_CT_STAT_INC(delete);
@@ -346,13 +218,23 @@
 	if (ct->master)
 		nf_ct_put(ct->master);
 
-	DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
+	pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct);
 	nf_conntrack_free(ct);
 }
 
 static void death_by_timeout(unsigned long ul_conntrack)
 {
 	struct nf_conn *ct = (void *)ul_conntrack;
+	struct nf_conn_help *help = nfct_help(ct);
+	struct nf_conntrack_helper *helper;
+
+	if (help) {
+		rcu_read_lock();
+		helper = rcu_dereference(help->helper);
+		if (helper && helper->destroy)
+			helper->destroy(ct);
+		rcu_read_unlock();
+	}
 
 	write_lock_bh(&nf_conntrack_lock);
 	/* Inside lock so preempt is disabled on module removal path.
@@ -368,9 +250,10 @@
 		    const struct nf_conn *ignored_conntrack)
 {
 	struct nf_conntrack_tuple_hash *h;
+	struct hlist_node *n;
 	unsigned int hash = hash_conntrack(tuple);
 
-	list_for_each_entry(h, &nf_conntrack_hash[hash], list) {
+	hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) {
 		if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
 		    nf_ct_tuple_equal(tuple, &h->tuple)) {
 			NF_CT_STAT_INC(found);
@@ -385,13 +268,12 @@
 
 /* Find a connection corresponding to a tuple. */
 struct nf_conntrack_tuple_hash *
-nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
-		      const struct nf_conn *ignored_conntrack)
+nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_tuple_hash *h;
 
 	read_lock_bh(&nf_conntrack_lock);
-	h = __nf_conntrack_find(tuple, ignored_conntrack);
+	h = __nf_conntrack_find(tuple, NULL);
 	if (h)
 		atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use);
 	read_unlock_bh(&nf_conntrack_lock);
@@ -405,10 +287,10 @@
 				       unsigned int repl_hash)
 {
 	ct->id = ++nf_conntrack_next_id;
-	list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
-		 &nf_conntrack_hash[hash]);
-	list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list,
-		 &nf_conntrack_hash[repl_hash]);
+	hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
+		       &nf_conntrack_hash[hash]);
+	hlist_add_head(&ct->tuplehash[IP_CT_DIR_REPLY].hnode,
+		       &nf_conntrack_hash[repl_hash]);
 }
 
 void nf_conntrack_hash_insert(struct nf_conn *ct)
@@ -432,6 +314,7 @@
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct;
 	struct nf_conn_help *help;
+	struct hlist_node *n;
 	enum ip_conntrack_info ctinfo;
 
 	ct = nf_ct_get(*pskb, &ctinfo);
@@ -454,24 +337,24 @@
 	/* No external references means noone else could have
 	   confirmed us. */
 	NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
-	DEBUGP("Confirming conntrack %p\n", ct);
+	pr_debug("Confirming conntrack %p\n", ct);
 
 	write_lock_bh(&nf_conntrack_lock);
 
 	/* See if there's one in the list already, including reverse:
 	   NAT could have grabbed it without realizing, since we're
 	   not in the hash.  If there is, we lost race. */
-	list_for_each_entry(h, &nf_conntrack_hash[hash], list)
+	hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode)
 		if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
 				      &h->tuple))
 			goto out;
-	list_for_each_entry(h, &nf_conntrack_hash[repl_hash], list)
+	hlist_for_each_entry(h, n, &nf_conntrack_hash[repl_hash], hnode)
 		if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
 				      &h->tuple))
 			goto out;
 
 	/* Remove from unconfirmed list */
-	list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+	hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
 
 	__nf_conntrack_hash_insert(ct, hash, repl_hash);
 	/* Timer relative to confirmation time, not original
@@ -518,24 +401,33 @@
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken);
 
+#define NF_CT_EVICTION_RANGE	8
+
 /* There's a small race here where we may free a just-assured
    connection.  Too bad: we're in trouble anyway. */
-static int early_drop(struct list_head *chain)
+static int early_drop(unsigned int hash)
 {
-	/* Traverse backwards: gives us oldest, which is roughly LRU */
+	/* Use oldest entry, which is roughly LRU */
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct = NULL, *tmp;
+	struct hlist_node *n;
+	unsigned int i, cnt = 0;
 	int dropped = 0;
 
 	read_lock_bh(&nf_conntrack_lock);
-	list_for_each_entry_reverse(h, chain, list) {
-		tmp = nf_ct_tuplehash_to_ctrack(h);
-		if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) {
-			ct = tmp;
-			atomic_inc(&ct->ct_general.use);
-			break;
+	for (i = 0; i < nf_conntrack_htable_size; i++) {
+		hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) {
+			tmp = nf_ct_tuplehash_to_ctrack(h);
+			if (!test_bit(IPS_ASSURED_BIT, &tmp->status))
+				ct = tmp;
+			cnt++;
 		}
+		if (ct || cnt >= NF_CT_EVICTION_RANGE)
+			break;
+		hash = (hash + 1) % nf_conntrack_htable_size;
 	}
+	if (ct)
+		atomic_inc(&ct->ct_general.use);
 	read_unlock_bh(&nf_conntrack_lock);
 
 	if (!ct)
@@ -550,14 +442,10 @@
 	return dropped;
 }
 
-static struct nf_conn *
-__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
-		     const struct nf_conntrack_tuple *repl,
-		     const struct nf_conntrack_l3proto *l3proto,
-		     u_int32_t features)
+struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
+				   const struct nf_conntrack_tuple *repl)
 {
 	struct nf_conn *conntrack = NULL;
-	struct nf_conntrack_helper *helper;
 
 	if (unlikely(!nf_conntrack_hash_rnd_initted)) {
 		get_random_bytes(&nf_conntrack_hash_rnd, 4);
@@ -570,8 +458,7 @@
 	if (nf_conntrack_max
 	    && atomic_read(&nf_conntrack_count) > nf_conntrack_max) {
 		unsigned int hash = hash_conntrack(orig);
-		/* Try dropping from this hash chain. */
-		if (!early_drop(&nf_conntrack_hash[hash])) {
+		if (!early_drop(hash)) {
 			atomic_dec(&nf_conntrack_count);
 			if (net_ratelimit())
 				printk(KERN_WARNING
@@ -581,72 +468,28 @@
 		}
 	}
 
-	/*  find features needed by this conntrack. */
-	features |= l3proto->get_features(orig);
-
-	/* FIXME: protect helper list per RCU */
-	read_lock_bh(&nf_conntrack_lock);
-	helper = __nf_ct_helper_find(repl);
-	/* NAT might want to assign a helper later */
-	if (helper || features & NF_CT_F_NAT)
-		features |= NF_CT_F_HELP;
-	read_unlock_bh(&nf_conntrack_lock);
-
-	DEBUGP("nf_conntrack_alloc: features=0x%x\n", features);
-
-	read_lock_bh(&nf_ct_cache_lock);
-
-	if (unlikely(!nf_ct_cache[features].use)) {
-		DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n",
-			features);
-		goto out;
-	}
-
-	conntrack = kmem_cache_alloc(nf_ct_cache[features].cachep, GFP_ATOMIC);
+	conntrack = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC);
 	if (conntrack == NULL) {
-		DEBUGP("nf_conntrack_alloc: Can't alloc conntrack from cache\n");
-		goto out;
+		pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
+		atomic_dec(&nf_conntrack_count);
+		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(conntrack, 0, nf_ct_cache[features].size);
-	conntrack->features = features;
 	atomic_set(&conntrack->ct_general.use, 1);
 	conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
 	conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
 	/* Don't set timer yet: wait for confirmation */
 	setup_timer(&conntrack->timeout, death_by_timeout,
 		    (unsigned long)conntrack);
-	read_unlock_bh(&nf_ct_cache_lock);
 
 	return conntrack;
-out:
-	read_unlock_bh(&nf_ct_cache_lock);
-	atomic_dec(&nf_conntrack_count);
-	return conntrack;
-}
-
-struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
-				   const struct nf_conntrack_tuple *repl)
-{
-	struct nf_conntrack_l3proto *l3proto;
-	struct nf_conn *ct;
-
-	rcu_read_lock();
-	l3proto = __nf_ct_l3proto_find(orig->src.l3num);
-	ct = __nf_conntrack_alloc(orig, repl, l3proto, 0);
-	rcu_read_unlock();
-
-	return ct;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
 
 void nf_conntrack_free(struct nf_conn *conntrack)
 {
-	u_int32_t features = conntrack->features;
-	NF_CT_ASSERT(features >= NF_CT_F_BASIC && features < NF_CT_F_NUM);
-	DEBUGP("nf_conntrack_free: features = 0x%x, conntrack=%p\n", features,
-	       conntrack);
-	kmem_cache_free(nf_ct_cache[features].cachep, conntrack);
+	nf_ct_ext_free(conntrack);
+	kmem_cache_free(nf_conntrack_cachep, conntrack);
 	atomic_dec(&nf_conntrack_count);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_free);
@@ -661,44 +504,41 @@
 	       unsigned int dataoff)
 {
 	struct nf_conn *conntrack;
+	struct nf_conn_help *help;
 	struct nf_conntrack_tuple repl_tuple;
 	struct nf_conntrack_expect *exp;
-	u_int32_t features = 0;
 
 	if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
-		DEBUGP("Can't invert tuple.\n");
+		pr_debug("Can't invert tuple.\n");
 		return NULL;
 	}
 
-	read_lock_bh(&nf_conntrack_lock);
-	exp = __nf_conntrack_expect_find(tuple);
-	if (exp && exp->helper)
-		features = NF_CT_F_HELP;
-	read_unlock_bh(&nf_conntrack_lock);
-
-	conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto, features);
+	conntrack = nf_conntrack_alloc(tuple, &repl_tuple);
 	if (conntrack == NULL || IS_ERR(conntrack)) {
-		DEBUGP("Can't allocate conntrack.\n");
+		pr_debug("Can't allocate conntrack.\n");
 		return (struct nf_conntrack_tuple_hash *)conntrack;
 	}
 
 	if (!l4proto->new(conntrack, skb, dataoff)) {
 		nf_conntrack_free(conntrack);
-		DEBUGP("init conntrack: can't track with proto module\n");
+		pr_debug("init conntrack: can't track with proto module\n");
 		return NULL;
 	}
 
 	write_lock_bh(&nf_conntrack_lock);
-	exp = find_expectation(tuple);
-
+	exp = nf_ct_find_expectation(tuple);
 	if (exp) {
-		DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
-			conntrack, exp);
+		pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
+			 conntrack, exp);
 		/* Welcome, Mr. Bond.  We've been expecting you... */
 		__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
 		conntrack->master = exp->master;
-		if (exp->helper)
-			nfct_help(conntrack)->helper = exp->helper;
+		if (exp->helper) {
+			help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC);
+			if (help)
+				rcu_assign_pointer(help->helper, exp->helper);
+		}
+
 #ifdef CONFIG_NF_CONNTRACK_MARK
 		conntrack->mark = exp->master->mark;
 #endif
@@ -708,22 +548,27 @@
 		nf_conntrack_get(&conntrack->master->ct_general);
 		NF_CT_STAT_INC(expect_new);
 	} else {
-		struct nf_conn_help *help = nfct_help(conntrack);
+		struct nf_conntrack_helper *helper;
 
-		if (help)
-			help->helper = __nf_ct_helper_find(&repl_tuple);
+		helper = __nf_ct_helper_find(&repl_tuple);
+		if (helper) {
+			help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC);
+			if (help)
+				rcu_assign_pointer(help->helper, helper);
+		}
 		NF_CT_STAT_INC(new);
 	}
 
 	/* Overload tuple linked list to put us in unconfirmed list. */
-	list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
+	hlist_add_head(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
+		       &unconfirmed);
 
 	write_unlock_bh(&nf_conntrack_lock);
 
 	if (exp) {
 		if (exp->expectfn)
 			exp->expectfn(conntrack, exp);
-		nf_conntrack_expect_put(exp);
+		nf_ct_expect_put(exp);
 	}
 
 	return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
@@ -747,12 +592,12 @@
 	if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
 			     dataoff, l3num, protonum, &tuple, l3proto,
 			     l4proto)) {
-		DEBUGP("resolve_normal_ct: Can't get tuple\n");
+		pr_debug("resolve_normal_ct: Can't get tuple\n");
 		return NULL;
 	}
 
 	/* look for tuple match */
-	h = nf_conntrack_find_get(&tuple, NULL);
+	h = nf_conntrack_find_get(&tuple);
 	if (!h) {
 		h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff);
 		if (!h)
@@ -770,13 +615,14 @@
 	} else {
 		/* Once we've had two way comms, always ESTABLISHED. */
 		if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
-			DEBUGP("nf_conntrack_in: normal packet for %p\n", ct);
+			pr_debug("nf_conntrack_in: normal packet for %p\n", ct);
 			*ctinfo = IP_CT_ESTABLISHED;
 		} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
-			DEBUGP("nf_conntrack_in: related packet for %p\n", ct);
+			pr_debug("nf_conntrack_in: related packet for %p\n",
+				 ct);
 			*ctinfo = IP_CT_RELATED;
 		} else {
-			DEBUGP("nf_conntrack_in: new packet for %p\n", ct);
+			pr_debug("nf_conntrack_in: new packet for %p\n", ct);
 			*ctinfo = IP_CT_NEW;
 		}
 		*set_reply = 0;
@@ -806,9 +652,12 @@
 
 	/* rcu_read_lock()ed by nf_hook_slow */
 	l3proto = __nf_ct_l3proto_find((u_int16_t)pf);
-
-	if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) {
-		DEBUGP("not prepared to track yet or error occured\n");
+	ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb),
+				   &dataoff, &protonum);
+	if (ret <= 0) {
+		pr_debug("not prepared to track yet or error occured\n");
+		NF_CT_STAT_INC_ATOMIC(error);
+		NF_CT_STAT_INC_ATOMIC(invalid);
 		return -ret;
 	}
 
@@ -844,7 +693,7 @@
 	if (ret < 0) {
 		/* Invalid: inverse of the return code tells
 		 * the netfilter core what to do */
-		DEBUGP("nf_conntrack_in: Can't track with proto module\n");
+		pr_debug("nf_conntrack_in: Can't track with proto module\n");
 		nf_conntrack_put((*pskb)->nfct);
 		(*pskb)->nfct = NULL;
 		NF_CT_STAT_INC_ATOMIC(invalid);
@@ -879,22 +728,36 @@
 			      const struct nf_conntrack_tuple *newreply)
 {
 	struct nf_conn_help *help = nfct_help(ct);
+	struct nf_conntrack_helper *helper;
 
 	write_lock_bh(&nf_conntrack_lock);
 	/* Should be unconfirmed, so not in hash table yet */
 	NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
 
-	DEBUGP("Altering reply tuple of %p to ", ct);
+	pr_debug("Altering reply tuple of %p to ", ct);
 	NF_CT_DUMP_TUPLE(newreply);
 
 	ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
-	if (!ct->master && help && help->expecting == 0) {
-		struct nf_conntrack_helper *helper;
-		helper = __nf_ct_helper_find(newreply);
-		if (helper)
-			memset(&help->help, 0, sizeof(help->help));
-		help->helper = helper;
+	if (ct->master || (help && help->expecting != 0))
+		goto out;
+
+	helper = __nf_ct_helper_find(newreply);
+	if (helper == NULL) {
+		if (help)
+			rcu_assign_pointer(help->helper, NULL);
+		goto out;
 	}
+
+	if (help == NULL) {
+		help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
+		if (help == NULL)
+			goto out;
+	} else {
+		memset(&help->help, 0, sizeof(help->help));
+	}
+
+	rcu_assign_pointer(help->helper, helper);
+out:
 	write_unlock_bh(&nf_conntrack_lock);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
@@ -1038,16 +901,17 @@
 {
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct;
+	struct hlist_node *n;
 
 	write_lock_bh(&nf_conntrack_lock);
 	for (; *bucket < nf_conntrack_htable_size; (*bucket)++) {
-		list_for_each_entry(h, &nf_conntrack_hash[*bucket], list) {
+		hlist_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnode) {
 			ct = nf_ct_tuplehash_to_ctrack(h);
 			if (iter(ct, data))
 				goto found;
 		}
 	}
-	list_for_each_entry(h, &unconfirmed, list) {
+	hlist_for_each_entry(h, n, &unconfirmed, hnode) {
 		ct = nf_ct_tuplehash_to_ctrack(h);
 		if (iter(ct, data))
 			set_bit(IPS_DYING_BIT, &ct->status);
@@ -1082,14 +946,15 @@
 	return 1;
 }
 
-static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size)
+void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, int size)
 {
 	if (vmalloced)
 		vfree(hash);
 	else
 		free_pages((unsigned long)hash,
-			   get_order(sizeof(struct list_head) * size));
+			   get_order(sizeof(struct hlist_head) * size));
 }
+EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
 
 void nf_conntrack_flush(void)
 {
@@ -1101,8 +966,6 @@
    supposed to kill the mall. */
 void nf_conntrack_cleanup(void)
 {
-	int i;
-
 	rcu_assign_pointer(ip_ct_attach, NULL);
 
 	/* This makes sure all current packets have passed through
@@ -1123,49 +986,46 @@
 
 	rcu_assign_pointer(nf_ct_destroy, NULL);
 
-	for (i = 0; i < NF_CT_F_NUM; i++) {
-		if (nf_ct_cache[i].use == 0)
-			continue;
-
-		NF_CT_ASSERT(nf_ct_cache[i].use == 1);
-		nf_ct_cache[i].use = 1;
-		nf_conntrack_unregister_cache(i);
-	}
-	kmem_cache_destroy(nf_conntrack_expect_cachep);
-	free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
-			    nf_conntrack_htable_size);
+	kmem_cache_destroy(nf_conntrack_cachep);
+	nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
+			     nf_conntrack_htable_size);
 
 	nf_conntrack_proto_fini();
+	nf_conntrack_helper_fini();
+	nf_conntrack_expect_fini();
 }
 
-static struct list_head *alloc_hashtable(int size, int *vmalloced)
+struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced)
 {
-	struct list_head *hash;
-	unsigned int i;
+	struct hlist_head *hash;
+	unsigned int size, i;
 
 	*vmalloced = 0;
+
+	size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head));
 	hash = (void*)__get_free_pages(GFP_KERNEL,
-				       get_order(sizeof(struct list_head)
+				       get_order(sizeof(struct hlist_head)
 						 * size));
 	if (!hash) {
 		*vmalloced = 1;
 		printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
-		hash = vmalloc(sizeof(struct list_head) * size);
+		hash = vmalloc(sizeof(struct hlist_head) * size);
 	}
 
 	if (hash)
 		for (i = 0; i < size; i++)
-			INIT_LIST_HEAD(&hash[i]);
+			INIT_HLIST_HEAD(&hash[i]);
 
 	return hash;
 }
+EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable);
 
 int set_hashsize(const char *val, struct kernel_param *kp)
 {
 	int i, bucket, hashsize, vmalloced;
 	int old_vmalloced, old_size;
 	int rnd;
-	struct list_head *hash, *old_hash;
+	struct hlist_head *hash, *old_hash;
 	struct nf_conntrack_tuple_hash *h;
 
 	/* On boot, we can set this without any fancy locking. */
@@ -1176,7 +1036,7 @@
 	if (!hashsize)
 		return -EINVAL;
 
-	hash = alloc_hashtable(hashsize, &vmalloced);
+	hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced);
 	if (!hash)
 		return -ENOMEM;
 
@@ -1186,12 +1046,12 @@
 
 	write_lock_bh(&nf_conntrack_lock);
 	for (i = 0; i < nf_conntrack_htable_size; i++) {
-		while (!list_empty(&nf_conntrack_hash[i])) {
-			h = list_entry(nf_conntrack_hash[i].next,
-				       struct nf_conntrack_tuple_hash, list);
-			list_del(&h->list);
+		while (!hlist_empty(&nf_conntrack_hash[i])) {
+			h = hlist_entry(nf_conntrack_hash[i].first,
+					struct nf_conntrack_tuple_hash, hnode);
+			hlist_del(&h->hnode);
 			bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
-			list_add_tail(&h->list, &hash[bucket]);
+			hlist_add_head(&h->hnode, &hash[bucket]);
 		}
 	}
 	old_size = nf_conntrack_htable_size;
@@ -1204,7 +1064,7 @@
 	nf_conntrack_hash_rnd = rnd;
 	write_unlock_bh(&nf_conntrack_lock);
 
-	free_conntrack_hash(old_hash, old_vmalloced, old_size);
+	nf_ct_free_hashtable(old_hash, old_vmalloced, old_size);
 	return 0;
 }
 
@@ -1213,50 +1073,58 @@
 
 int __init nf_conntrack_init(void)
 {
+	int max_factor = 8;
 	int ret;
 
 	/* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
-	 * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
+	 * machine has 512 buckets. >= 1GB machines have 16384 buckets. */
 	if (!nf_conntrack_htable_size) {
 		nf_conntrack_htable_size
 			= (((num_physpages << PAGE_SHIFT) / 16384)
-			   / sizeof(struct list_head));
+			   / sizeof(struct hlist_head));
 		if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
-			nf_conntrack_htable_size = 8192;
-		if (nf_conntrack_htable_size < 16)
-			nf_conntrack_htable_size = 16;
+			nf_conntrack_htable_size = 16384;
+		if (nf_conntrack_htable_size < 32)
+			nf_conntrack_htable_size = 32;
+
+		/* Use a max. factor of four by default to get the same max as
+		 * with the old struct list_heads. When a table size is given
+		 * we use the old value of 8 to avoid reducing the max.
+		 * entries. */
+		max_factor = 4;
 	}
-	nf_conntrack_max = 8 * nf_conntrack_htable_size;
-
-	printk("nf_conntrack version %s (%u buckets, %d max)\n",
-	       NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
-	       nf_conntrack_max);
-
-	nf_conntrack_hash = alloc_hashtable(nf_conntrack_htable_size,
-					    &nf_conntrack_vmalloc);
+	nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
+						  &nf_conntrack_vmalloc);
 	if (!nf_conntrack_hash) {
 		printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
 		goto err_out;
 	}
 
-	ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic",
-					  sizeof(struct nf_conn));
-	if (ret < 0) {
+	nf_conntrack_max = max_factor * nf_conntrack_htable_size;
+
+	printk("nf_conntrack version %s (%u buckets, %d max)\n",
+	       NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
+	       nf_conntrack_max);
+
+	nf_conntrack_cachep = kmem_cache_create("nf_conntrack",
+						sizeof(struct nf_conn),
+						0, 0, NULL, NULL);
+	if (!nf_conntrack_cachep) {
 		printk(KERN_ERR "Unable to create nf_conn slab cache\n");
 		goto err_free_hash;
 	}
 
-	nf_conntrack_expect_cachep = kmem_cache_create("nf_conntrack_expect",
-					sizeof(struct nf_conntrack_expect),
-					0, 0, NULL, NULL);
-	if (!nf_conntrack_expect_cachep) {
-		printk(KERN_ERR "Unable to create nf_expect slab cache\n");
-		goto err_free_conntrack_slab;
-	}
-
 	ret = nf_conntrack_proto_init();
 	if (ret < 0)
-		goto out_free_expect_slab;
+		goto err_free_conntrack_slab;
+
+	ret = nf_conntrack_expect_init();
+	if (ret < 0)
+		goto out_fini_proto;
+
+	ret = nf_conntrack_helper_init();
+	if (ret < 0)
+		goto out_fini_expect;
 
 	/* For use by REJECT target */
 	rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach);
@@ -1270,13 +1138,15 @@
 
 	return ret;
 
-out_free_expect_slab:
-	kmem_cache_destroy(nf_conntrack_expect_cachep);
+out_fini_expect:
+	nf_conntrack_expect_fini();
+out_fini_proto:
+	nf_conntrack_proto_fini();
 err_free_conntrack_slab:
-	nf_conntrack_unregister_cache(NF_CT_F_BASIC);
+	kmem_cache_destroy(nf_conntrack_cachep);
 err_free_hash:
-	free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
-			    nf_conntrack_htable_size);
+	nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
+			     nf_conntrack_htable_size);
 err_out:
 	return -ENOMEM;
 }
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 6bd421d..83c41ac 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -26,8 +26,8 @@
 ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
 EXPORT_SYMBOL_GPL(nf_conntrack_chain);
 
-ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_chain);
+ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain);
+EXPORT_SYMBOL_GPL(nf_ct_expect_chain);
 
 DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
 EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
@@ -103,14 +103,14 @@
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
 
-int nf_conntrack_expect_register_notifier(struct notifier_block *nb)
+int nf_ct_expect_register_notifier(struct notifier_block *nb)
 {
-	return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
+	return atomic_notifier_chain_register(&nf_ct_expect_chain, nb);
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_register_notifier);
+EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier);
 
-int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
+int nf_ct_expect_unregister_notifier(struct notifier_block *nb)
 {
-	return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, nb);
+	return atomic_notifier_chain_unregister(&nf_ct_expect_chain, nb);
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_unregister_notifier);
+EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 117cbfd..2191fe0 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -19,6 +19,7 @@
 #include <linux/err.h>
 #include <linux/percpu.h>
 #include <linux/kernel.h>
+#include <linux/jhash.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
@@ -26,11 +27,20 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
 
-LIST_HEAD(nf_conntrack_expect_list);
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_list);
+struct hlist_head *nf_ct_expect_hash __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
 
-struct kmem_cache *nf_conntrack_expect_cachep __read_mostly;
-static unsigned int nf_conntrack_expect_next_id;
+unsigned int nf_ct_expect_hsize __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
+
+static unsigned int nf_ct_expect_hash_rnd __read_mostly;
+static unsigned int nf_ct_expect_count;
+unsigned int nf_ct_expect_max __read_mostly;
+static int nf_ct_expect_hash_rnd_initted __read_mostly;
+static int nf_ct_expect_vmalloc;
+
+static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
+static unsigned int nf_ct_expect_next_id;
 
 /* nf_conntrack_expect helper functions */
 void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
@@ -40,60 +50,83 @@
 	NF_CT_ASSERT(master_help);
 	NF_CT_ASSERT(!timer_pending(&exp->timeout));
 
-	list_del(&exp->list);
-	NF_CT_STAT_INC(expect_delete);
+	hlist_del(&exp->hnode);
+	nf_ct_expect_count--;
+
+	hlist_del(&exp->lnode);
 	master_help->expecting--;
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
+
+	NF_CT_STAT_INC(expect_delete);
 }
 EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);
 
-static void expectation_timed_out(unsigned long ul_expect)
+static void nf_ct_expectation_timed_out(unsigned long ul_expect)
 {
 	struct nf_conntrack_expect *exp = (void *)ul_expect;
 
 	write_lock_bh(&nf_conntrack_lock);
 	nf_ct_unlink_expect(exp);
 	write_unlock_bh(&nf_conntrack_lock);
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
+}
+
+static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple)
+{
+	if (unlikely(!nf_ct_expect_hash_rnd_initted)) {
+		get_random_bytes(&nf_ct_expect_hash_rnd, 4);
+		nf_ct_expect_hash_rnd_initted = 1;
+	}
+
+	return jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all),
+		      (((tuple->dst.protonum ^ tuple->src.l3num) << 16) |
+		       tuple->dst.u.all) ^ nf_ct_expect_hash_rnd) %
+	       nf_ct_expect_hsize;
 }
 
 struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_expect *i;
+	struct hlist_node *n;
+	unsigned int h;
 
-	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+	if (!nf_ct_expect_count)
+		return NULL;
+
+	h = nf_ct_expect_dst_hash(tuple);
+	hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
 		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
 			return i;
 	}
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
 
 /* Just find a expectation corresponding to a tuple. */
 struct nf_conntrack_expect *
-nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple)
+nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_expect *i;
 
 	read_lock_bh(&nf_conntrack_lock);
-	i = __nf_conntrack_expect_find(tuple);
+	i = __nf_ct_expect_find(tuple);
 	if (i)
 		atomic_inc(&i->use);
 	read_unlock_bh(&nf_conntrack_lock);
 
 	return i;
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);
+EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
 
 /* If an expectation for this connection is found, it gets delete from
  * global list then returned. */
 struct nf_conntrack_expect *
-find_expectation(const struct nf_conntrack_tuple *tuple)
+nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_expect *exp;
 
-	exp = __nf_conntrack_expect_find(tuple);
+	exp = __nf_ct_expect_find(tuple);
 	if (!exp)
 		return NULL;
 
@@ -119,17 +152,18 @@
 /* delete all expectations for this conntrack */
 void nf_ct_remove_expectations(struct nf_conn *ct)
 {
-	struct nf_conntrack_expect *i, *tmp;
 	struct nf_conn_help *help = nfct_help(ct);
+	struct nf_conntrack_expect *exp;
+	struct hlist_node *n, *next;
 
 	/* Optimization: most connection never expect any others. */
 	if (!help || help->expecting == 0)
 		return;
 
-	list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
-		if (i->master == ct && del_timer(&i->timeout)) {
-			nf_ct_unlink_expect(i);
-			nf_conntrack_expect_put(i);
+	hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
+		if (del_timer(&exp->timeout)) {
+			nf_ct_unlink_expect(exp);
+			nf_ct_expect_put(exp);
 		}
 	}
 }
@@ -141,25 +175,16 @@
 {
 	/* Part covered by intersection of masks must be unequal,
 	   otherwise they clash */
-	struct nf_conntrack_tuple intersect_mask;
+	struct nf_conntrack_tuple_mask intersect_mask;
 	int count;
 
-	intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num;
 	intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
-	intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all;
-	intersect_mask.dst.protonum = a->mask.dst.protonum
-					& b->mask.dst.protonum;
 
 	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
 		intersect_mask.src.u3.all[count] =
 			a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
 	}
 
-	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
-		intersect_mask.dst.u3.all[count] =
-			a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count];
-	}
-
 	return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
 }
 
@@ -168,36 +193,29 @@
 {
 	return a->master == b->master
 		&& nf_ct_tuple_equal(&a->tuple, &b->tuple)
-		&& nf_ct_tuple_equal(&a->mask, &b->mask);
+		&& nf_ct_tuple_mask_equal(&a->mask, &b->mask);
 }
 
 /* Generally a bad idea to call this: could have matched already. */
-void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp)
+void nf_ct_unexpect_related(struct nf_conntrack_expect *exp)
 {
-	struct nf_conntrack_expect *i;
-
 	write_lock_bh(&nf_conntrack_lock);
-	/* choose the oldest expectation to evict */
-	list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
-		if (expect_matches(i, exp) && del_timer(&i->timeout)) {
-			nf_ct_unlink_expect(i);
-			write_unlock_bh(&nf_conntrack_lock);
-			nf_conntrack_expect_put(i);
-			return;
-		}
+	if (del_timer(&exp->timeout)) {
+		nf_ct_unlink_expect(exp);
+		nf_ct_expect_put(exp);
 	}
 	write_unlock_bh(&nf_conntrack_lock);
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_unexpect_related);
+EXPORT_SYMBOL_GPL(nf_ct_unexpect_related);
 
 /* We don't increase the master conntrack refcount for non-fulfilled
  * conntracks. During the conntrack destruction, the expectations are
  * always killed before the conntrack itself */
-struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me)
+struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
 {
 	struct nf_conntrack_expect *new;
 
-	new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC);
+	new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC);
 	if (!new)
 		return NULL;
 
@@ -205,12 +223,12 @@
 	atomic_set(&new->use, 1);
 	return new;
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_alloc);
+EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
 
-void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family,
-			      union nf_conntrack_address *saddr,
-			      union nf_conntrack_address *daddr,
-			      u_int8_t proto, __be16 *src, __be16 *dst)
+void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family,
+		       union nf_conntrack_address *saddr,
+		       union nf_conntrack_address *daddr,
+		       u_int8_t proto, __be16 *src, __be16 *dst)
 {
 	int len;
 
@@ -224,8 +242,6 @@
 	exp->helper = NULL;
 	exp->tuple.src.l3num = family;
 	exp->tuple.dst.protonum = proto;
-	exp->mask.src.l3num = 0xFFFF;
-	exp->mask.dst.protonum = 0xFF;
 
 	if (saddr) {
 		memcpy(&exp->tuple.src.u3, saddr, len);
@@ -242,21 +258,6 @@
 		memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3));
 	}
 
-	if (daddr) {
-		memcpy(&exp->tuple.dst.u3, daddr, len);
-		if (sizeof(exp->tuple.dst.u3) > len)
-			/* address needs to be cleared for nf_ct_tuple_equal */
-			memset((void *)&exp->tuple.dst.u3 + len, 0x00,
-			       sizeof(exp->tuple.dst.u3) - len);
-		memset(&exp->mask.dst.u3, 0xFF, len);
-		if (sizeof(exp->mask.dst.u3) > len)
-			memset((void *)&exp->mask.dst.u3 + len, 0x00,
-			       sizeof(exp->mask.dst.u3) - len);
-	} else {
-		memset(&exp->tuple.dst.u3, 0x00, sizeof(exp->tuple.dst.u3));
-		memset(&exp->mask.dst.u3, 0x00, sizeof(exp->mask.dst.u3));
-	}
-
 	if (src) {
 		exp->tuple.src.u.all = (__force u16)*src;
 		exp->mask.src.u.all = 0xFFFF;
@@ -265,36 +266,42 @@
 		exp->mask.src.u.all = 0;
 	}
 
-	if (dst) {
-		exp->tuple.dst.u.all = (__force u16)*dst;
-		exp->mask.dst.u.all = 0xFFFF;
-	} else {
-		exp->tuple.dst.u.all = 0;
-		exp->mask.dst.u.all = 0;
-	}
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_init);
+	memcpy(&exp->tuple.dst.u3, daddr, len);
+	if (sizeof(exp->tuple.dst.u3) > len)
+		/* address needs to be cleared for nf_ct_tuple_equal */
+		memset((void *)&exp->tuple.dst.u3 + len, 0x00,
+		       sizeof(exp->tuple.dst.u3) - len);
 
-void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
+	exp->tuple.dst.u.all = (__force u16)*dst;
+}
+EXPORT_SYMBOL_GPL(nf_ct_expect_init);
+
+void nf_ct_expect_put(struct nf_conntrack_expect *exp)
 {
 	if (atomic_dec_and_test(&exp->use))
-		kmem_cache_free(nf_conntrack_expect_cachep, exp);
+		kmem_cache_free(nf_ct_expect_cachep, exp);
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_put);
+EXPORT_SYMBOL_GPL(nf_ct_expect_put);
 
-static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
+static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
 {
 	struct nf_conn_help *master_help = nfct_help(exp->master);
+	unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
 
 	atomic_inc(&exp->use);
-	master_help->expecting++;
-	list_add(&exp->list, &nf_conntrack_expect_list);
 
-	setup_timer(&exp->timeout, expectation_timed_out, (unsigned long)exp);
+	hlist_add_head(&exp->lnode, &master_help->expectations);
+	master_help->expecting++;
+
+	hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]);
+	nf_ct_expect_count++;
+
+	setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
+		    (unsigned long)exp);
 	exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
 	add_timer(&exp->timeout);
 
-	exp->id = ++nf_conntrack_expect_next_id;
+	exp->id = ++nf_ct_expect_next_id;
 	atomic_inc(&exp->use);
 	NF_CT_STAT_INC(expect_create);
 }
@@ -302,16 +309,16 @@
 /* Race with expectations being used means we could have none to find; OK. */
 static void evict_oldest_expect(struct nf_conn *master)
 {
-	struct nf_conntrack_expect *i;
+	struct nf_conn_help *master_help = nfct_help(master);
+	struct nf_conntrack_expect *exp = NULL;
+	struct hlist_node *n;
 
-	list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
-		if (i->master == master) {
-			if (del_timer(&i->timeout)) {
-				nf_ct_unlink_expect(i);
-				nf_conntrack_expect_put(i);
-			}
-			break;
-		}
+	hlist_for_each_entry(exp, n, &master_help->expectations, lnode)
+		; /* nothing */
+
+	if (exp && del_timer(&exp->timeout)) {
+		nf_ct_unlink_expect(exp);
+		nf_ct_expect_put(exp);
 	}
 }
 
@@ -327,17 +334,24 @@
 	return 1;
 }
 
-int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
+int nf_ct_expect_related(struct nf_conntrack_expect *expect)
 {
 	struct nf_conntrack_expect *i;
 	struct nf_conn *master = expect->master;
 	struct nf_conn_help *master_help = nfct_help(master);
+	struct hlist_node *n;
+	unsigned int h;
 	int ret;
 
 	NF_CT_ASSERT(master_help);
 
 	write_lock_bh(&nf_conntrack_lock);
-	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+	if (!master_help->helper) {
+		ret = -ESHUTDOWN;
+		goto out;
+	}
+	h = nf_ct_expect_dst_hash(&expect->tuple);
+	hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
 		if (expect_matches(i, expect)) {
 			/* Refresh timer: if it's dying, ignore.. */
 			if (refresh_timer(i)) {
@@ -354,57 +368,86 @@
 	    master_help->expecting >= master_help->helper->max_expected)
 		evict_oldest_expect(master);
 
-	nf_conntrack_expect_insert(expect);
-	nf_conntrack_expect_event(IPEXP_NEW, expect);
+	if (nf_ct_expect_count >= nf_ct_expect_max) {
+		if (net_ratelimit())
+			printk(KERN_WARNING
+			       "nf_conntrack: expectation table full");
+		ret = -EMFILE;
+		goto out;
+	}
+
+	nf_ct_expect_insert(expect);
+	nf_ct_expect_event(IPEXP_NEW, expect);
 	ret = 0;
 out:
 	write_unlock_bh(&nf_conntrack_lock);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_related);
+EXPORT_SYMBOL_GPL(nf_ct_expect_related);
 
 #ifdef CONFIG_PROC_FS
-static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_expect_iter_state {
+	unsigned int bucket;
+};
+
+static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
 {
-	struct list_head *e = &nf_conntrack_expect_list;
-	loff_t i;
+	struct ct_expect_iter_state *st = seq->private;
 
-	/* strange seq_file api calls stop even if we fail,
-	 * thus we need to grab lock since stop unlocks */
-	read_lock_bh(&nf_conntrack_lock);
-
-	if (list_empty(e))
-		return NULL;
-
-	for (i = 0; i <= *pos; i++) {
-		e = e->next;
-		if (e == &nf_conntrack_expect_list)
-			return NULL;
+	for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
+		if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
+			return nf_ct_expect_hash[st->bucket].first;
 	}
-	return e;
+	return NULL;
 }
 
-static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
+					     struct hlist_node *head)
 {
-	struct list_head *e = v;
+	struct ct_expect_iter_state *st = seq->private;
 
-	++*pos;
-	e = e->next;
-
-	if (e == &nf_conntrack_expect_list)
-		return NULL;
-
-	return e;
+	head = head->next;
+	while (head == NULL) {
+		if (++st->bucket >= nf_ct_expect_hsize)
+			return NULL;
+		head = nf_ct_expect_hash[st->bucket].first;
+	}
+	return head;
 }
 
-static void exp_seq_stop(struct seq_file *s, void *v)
+static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct hlist_node *head = ct_expect_get_first(seq);
+
+	if (head)
+		while (pos && (head = ct_expect_get_next(seq, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock_bh(&nf_conntrack_lock);
+	return ct_expect_get_idx(seq, *pos);
+}
+
+static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return ct_expect_get_next(seq, v);
+}
+
+static void exp_seq_stop(struct seq_file *seq, void *v)
 {
 	read_unlock_bh(&nf_conntrack_lock);
 }
 
 static int exp_seq_show(struct seq_file *s, void *v)
 {
-	struct nf_conntrack_expect *expect = v;
+	struct nf_conntrack_expect *expect;
+	struct hlist_node *n = v;
+
+	expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
 
 	if (expect->timeout.function)
 		seq_printf(s, "%ld ", timer_pending(&expect->timeout)
@@ -421,7 +464,7 @@
 	return seq_putc(s, '\n');
 }
 
-static struct seq_operations exp_seq_ops = {
+static const struct seq_operations exp_seq_ops = {
 	.start = exp_seq_start,
 	.next = exp_seq_next,
 	.stop = exp_seq_stop,
@@ -430,14 +473,96 @@
 
 static int exp_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &exp_seq_ops);
+	struct seq_file *seq;
+	struct ct_expect_iter_state *st;
+	int ret;
+
+	st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
+	ret = seq_open(file, &exp_seq_ops);
+	if (ret)
+		goto out_free;
+	seq          = file->private_data;
+	seq->private = st;
+	memset(st, 0, sizeof(struct ct_expect_iter_state));
+	return ret;
+out_free:
+	kfree(st);
+	return ret;
 }
 
-const struct file_operations exp_file_ops = {
+static const struct file_operations exp_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = exp_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release
+	.release = seq_release_private,
 };
 #endif /* CONFIG_PROC_FS */
+
+static int __init exp_proc_init(void)
+{
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *proc;
+
+	proc = proc_net_fops_create("nf_conntrack_expect", 0440, &exp_file_ops);
+	if (!proc)
+		return -ENOMEM;
+#endif /* CONFIG_PROC_FS */
+	return 0;
+}
+
+static void exp_proc_remove(void)
+{
+#ifdef CONFIG_PROC_FS
+	proc_net_remove("nf_conntrack_expect");
+#endif /* CONFIG_PROC_FS */
+}
+
+module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
+
+int __init nf_conntrack_expect_init(void)
+{
+	int err = -ENOMEM;
+
+	if (!nf_ct_expect_hsize) {
+		nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
+		if (!nf_ct_expect_hsize)
+			nf_ct_expect_hsize = 1;
+	}
+	nf_ct_expect_max = nf_ct_expect_hsize * 4;
+
+	nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
+						  &nf_ct_expect_vmalloc);
+	if (nf_ct_expect_hash == NULL)
+		goto err1;
+
+	nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
+					sizeof(struct nf_conntrack_expect),
+					0, 0, NULL, NULL);
+	if (!nf_ct_expect_cachep)
+		goto err2;
+
+	err = exp_proc_init();
+	if (err < 0)
+		goto err3;
+
+	return 0;
+
+err3:
+	nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
+			     nf_ct_expect_hsize);
+err2:
+	kmem_cache_destroy(nf_ct_expect_cachep);
+err1:
+	return err;
+}
+
+void nf_conntrack_expect_fini(void)
+{
+	exp_proc_remove();
+	kmem_cache_destroy(nf_ct_expect_cachep);
+	nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
+			     nf_ct_expect_hsize);
+}
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
new file mode 100644
index 0000000..a1a65a1
--- /dev/null
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -0,0 +1,195 @@
+/* Structure dynamic extension infrastructure
+ * Copyright (C) 2004 Rusty Russell IBM Corporation
+ * Copyright (C) 2007 Netfilter Core Team <coreteam@netfilter.org>
+ * Copyright (C) 2007 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/rcupdate.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM];
+static DEFINE_MUTEX(nf_ct_ext_type_mutex);
+
+/* Horrible trick to figure out smallest amount worth kmallocing. */
+#define CACHE(x) (x) + 0 *
+enum {
+	NF_CT_EXT_MIN_SIZE =
+#include <linux/kmalloc_sizes.h>
+	1 };
+#undef CACHE
+
+void __nf_ct_ext_destroy(struct nf_conn *ct)
+{
+	unsigned int i;
+	struct nf_ct_ext_type *t;
+
+	for (i = 0; i < NF_CT_EXT_NUM; i++) {
+		if (!nf_ct_ext_exist(ct, i))
+			continue;
+
+		rcu_read_lock();
+		t = rcu_dereference(nf_ct_ext_types[i]);
+
+		/* Here the nf_ct_ext_type might have been unregisterd.
+		 * I.e., it has responsible to cleanup private
+		 * area in all conntracks when it is unregisterd.
+		 */
+		if (t && t->destroy)
+			t->destroy(ct);
+		rcu_read_unlock();
+	}
+}
+EXPORT_SYMBOL(__nf_ct_ext_destroy);
+
+static void *
+nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
+{
+	unsigned int off, len, real_len;
+	struct nf_ct_ext_type *t;
+
+	rcu_read_lock();
+	t = rcu_dereference(nf_ct_ext_types[id]);
+	BUG_ON(t == NULL);
+	off = ALIGN(sizeof(struct nf_ct_ext), t->align);
+	len = off + t->len;
+	real_len = t->alloc_size;
+	rcu_read_unlock();
+
+	*ext = kzalloc(real_len, gfp);
+	if (!*ext)
+		return NULL;
+
+	(*ext)->offset[id] = off;
+	(*ext)->len = len;
+	(*ext)->real_len = real_len;
+
+	return (void *)(*ext) + off;
+}
+
+void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
+{
+	struct nf_ct_ext *new;
+	int i, newlen, newoff;
+	struct nf_ct_ext_type *t;
+
+	if (!ct->ext)
+		return nf_ct_ext_create(&ct->ext, id, gfp);
+
+	if (nf_ct_ext_exist(ct, id))
+		return NULL;
+
+	rcu_read_lock();
+	t = rcu_dereference(nf_ct_ext_types[id]);
+	BUG_ON(t == NULL);
+
+	newoff = ALIGN(ct->ext->len, t->align);
+	newlen = newoff + t->len;
+	rcu_read_unlock();
+
+	if (newlen >= ct->ext->real_len) {
+		new = kmalloc(newlen, gfp);
+		if (!new)
+			return NULL;
+
+		memcpy(new, ct->ext, ct->ext->len);
+
+		for (i = 0; i < NF_CT_EXT_NUM; i++) {
+			if (!nf_ct_ext_exist(ct, i))
+				continue;
+
+			rcu_read_lock();
+			t = rcu_dereference(nf_ct_ext_types[i]);
+			if (t && t->move)
+				t->move(ct, ct->ext + ct->ext->offset[id]);
+			rcu_read_unlock();
+		}
+		kfree(ct->ext);
+		new->real_len = newlen;
+		ct->ext = new;
+	}
+
+	ct->ext->offset[id] = newoff;
+	ct->ext->len = newlen;
+	memset((void *)ct->ext + newoff, 0, newlen - newoff);
+	return (void *)ct->ext + newoff;
+}
+EXPORT_SYMBOL(__nf_ct_ext_add);
+
+static void update_alloc_size(struct nf_ct_ext_type *type)
+{
+	int i, j;
+	struct nf_ct_ext_type *t1, *t2;
+	enum nf_ct_ext_id min = 0, max = NF_CT_EXT_NUM - 1;
+
+	/* unnecessary to update all types */
+	if ((type->flags & NF_CT_EXT_F_PREALLOC) == 0) {
+		min = type->id;
+		max = type->id;
+	}
+
+	/* This assumes that extended areas in conntrack for the types
+	   whose NF_CT_EXT_F_PREALLOC bit set are allocated in order */
+	for (i = min; i <= max; i++) {
+		t1 = nf_ct_ext_types[i];
+		if (!t1)
+			continue;
+
+		t1->alloc_size = sizeof(struct nf_ct_ext)
+				 + ALIGN(sizeof(struct nf_ct_ext), t1->align)
+				 + t1->len;
+		for (j = 0; j < NF_CT_EXT_NUM; j++) {
+			t2 = nf_ct_ext_types[j];
+			if (t2 == NULL || t2 == t1 ||
+			    (t2->flags & NF_CT_EXT_F_PREALLOC) == 0)
+				continue;
+
+			t1->alloc_size = ALIGN(t1->alloc_size, t2->align)
+					 + t2->len;
+		}
+		if (t1->alloc_size < NF_CT_EXT_MIN_SIZE)
+			t1->alloc_size = NF_CT_EXT_MIN_SIZE;
+	}
+}
+
+/* This MUST be called in process context. */
+int nf_ct_extend_register(struct nf_ct_ext_type *type)
+{
+	int ret = 0;
+
+	mutex_lock(&nf_ct_ext_type_mutex);
+	if (nf_ct_ext_types[type->id]) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* This ensures that nf_ct_ext_create() can allocate enough area
+	   before updating alloc_size */
+	type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align)
+			   + type->len;
+	rcu_assign_pointer(nf_ct_ext_types[type->id], type);
+	update_alloc_size(type);
+out:
+	mutex_unlock(&nf_ct_ext_type_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_extend_register);
+
+/* This MUST be called in process context. */
+void nf_ct_extend_unregister(struct nf_ct_ext_type *type)
+{
+	mutex_lock(&nf_ct_ext_type_mutex);
+	rcu_assign_pointer(nf_ct_ext_types[type->id], NULL);
+	update_alloc_size(type);
+	mutex_unlock(&nf_ct_ext_type_mutex);
+	synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index a186799..c763ee7 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -48,16 +48,9 @@
 				enum nf_ct_ftp_type type,
 				unsigned int matchoff,
 				unsigned int matchlen,
-				struct nf_conntrack_expect *exp,
-				u32 *seq);
+				struct nf_conntrack_expect *exp);
 EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char);
 static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char);
 static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
@@ -139,13 +132,13 @@
 			if (*data == term && i == array_size - 1)
 				return len;
 
-			DEBUGP("Char %u (got %u nums) `%u' unexpected\n",
-			       len, i, *data);
+			pr_debug("Char %u (got %u nums) `%u' unexpected\n",
+				 len, i, *data);
 			return 0;
 		}
 	}
-	DEBUGP("Failed to fill %u numbers separated by %c\n", array_size, sep);
-
+	pr_debug("Failed to fill %u numbers separated by %c\n",
+		 array_size, sep);
 	return 0;
 }
 
@@ -179,13 +172,13 @@
 			if (tmp_port == 0)
 				break;
 			*port = htons(tmp_port);
-			DEBUGP("get_port: return %d\n", tmp_port);
+			pr_debug("get_port: return %d\n", tmp_port);
 			return i + 1;
 		}
 		else if (data[i] >= '0' && data[i] <= '9')
 			tmp_port = tmp_port*10 + data[i] - '0';
 		else { /* Some other crap */
-			DEBUGP("get_port: invalid char.\n");
+			pr_debug("get_port: invalid char.\n");
 			break;
 		}
 	}
@@ -202,22 +195,22 @@
 	/* First character is delimiter, then "1" for IPv4 or "2" for IPv6,
 	   then delimiter again. */
 	if (dlen <= 3) {
-		DEBUGP("EPRT: too short\n");
+		pr_debug("EPRT: too short\n");
 		return 0;
 	}
 	delim = data[0];
 	if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) {
-		DEBUGP("try_eprt: invalid delimitter.\n");
+		pr_debug("try_eprt: invalid delimitter.\n");
 		return 0;
 	}
 
 	if ((cmd->l3num == PF_INET && data[1] != '1') ||
 	    (cmd->l3num == PF_INET6 && data[1] != '2')) {
-		DEBUGP("EPRT: invalid protocol number.\n");
+		pr_debug("EPRT: invalid protocol number.\n");
 		return 0;
 	}
 
-	DEBUGP("EPRT: Got %c%c%c\n", delim, data[1], delim);
+	pr_debug("EPRT: Got %c%c%c\n", delim, data[1], delim);
 
 	if (data[1] == '1') {
 		u_int32_t array[4];
@@ -235,7 +228,7 @@
 
 	if (length == 0)
 		return 0;
-	DEBUGP("EPRT: Got IP address!\n");
+	pr_debug("EPRT: Got IP address!\n");
 	/* Start offset includes initial "|1|", and trailing delimiter */
 	return get_port(data, 3 + length + 1, dlen, delim, &cmd->u.tcp.port);
 }
@@ -268,7 +261,7 @@
 {
 	size_t i;
 
-	DEBUGP("find_pattern `%s': dlen = %u\n", pattern, dlen);
+	pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen);
 	if (dlen == 0)
 		return 0;
 
@@ -283,17 +276,17 @@
 #if 0
 		size_t i;
 
-		DEBUGP("ftp: string mismatch\n");
+		pr_debug("ftp: string mismatch\n");
 		for (i = 0; i < plen; i++) {
-			DEBUGP("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
-				i, data[i], data[i],
-				pattern[i], pattern[i]);
+			pr_debug("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
+				 i, data[i], data[i],
+				 pattern[i], pattern[i]);
 		}
 #endif
 		return 0;
 	}
 
-	DEBUGP("Pattern matches!\n");
+	pr_debug("Pattern matches!\n");
 	/* Now we've found the constant string, try to skip
 	   to the 'skip' character */
 	for (i = plen; data[i] != skip; i++)
@@ -302,14 +295,14 @@
 	/* Skip over the last character */
 	i++;
 
-	DEBUGP("Skipped up to `%c'!\n", skip);
+	pr_debug("Skipped up to `%c'!\n", skip);
 
 	*numoff = i;
 	*numlen = getnum(data + i, dlen - i, cmd, term);
 	if (!*numlen)
 		return -1;
 
-	DEBUGP("Match succeeded!\n");
+	pr_debug("Match succeeded!\n");
 	return 1;
 }
 
@@ -335,15 +328,17 @@
 		if (info->seq_aft_nl[dir][i] == nl_seq)
 			return;
 
-		if (oldest == info->seq_aft_nl_num[dir]
-		    || before(info->seq_aft_nl[dir][i], oldest))
+		if (oldest == info->seq_aft_nl_num[dir] ||
+		    before(info->seq_aft_nl[dir][i],
+			   info->seq_aft_nl[dir][oldest]))
 			oldest = i;
 	}
 
 	if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) {
 		info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq;
 		nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
-	} else if (oldest != NUM_SEQ_TO_REMEMBER) {
+	} else if (oldest != NUM_SEQ_TO_REMEMBER &&
+		   after(nl_seq, info->seq_aft_nl[dir][oldest])) {
 		info->seq_aft_nl[dir][oldest] = nl_seq;
 		nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
 	}
@@ -363,6 +358,7 @@
 	unsigned int matchlen, matchoff;
 	struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
 	struct nf_conntrack_expect *exp;
+	union nf_conntrack_address *daddr;
 	struct nf_conntrack_man cmd = {};
 	unsigned int i;
 	int found = 0, ends_in_nl;
@@ -371,7 +367,7 @@
 	/* Until there's been traffic both ways, don't look in packets. */
 	if (ctinfo != IP_CT_ESTABLISHED
 	    && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
-		DEBUGP("ftp: Conntrackinfo = %u\n", ctinfo);
+		pr_debug("ftp: Conntrackinfo = %u\n", ctinfo);
 		return NF_ACCEPT;
 	}
 
@@ -382,8 +378,8 @@
 	dataoff = protoff + th->doff * 4;
 	/* No data? */
 	if (dataoff >= (*pskb)->len) {
-		DEBUGP("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
-			(*pskb)->len);
+		pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
+			 (*pskb)->len);
 		return NF_ACCEPT;
 	}
 	datalen = (*pskb)->len - dataoff;
@@ -398,11 +394,11 @@
 	/* Look up to see if we're just after a \n. */
 	if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
 		/* Now if this ends in \n, update ftp info. */
-		DEBUGP("nf_conntrack_ftp_help: wrong seq pos %s(%u) or %s(%u)\n",
-		       ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
-		       ct_ftp_info->seq_aft_nl[dir][0],
-		       ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
-		       ct_ftp_info->seq_aft_nl[dir][1]);
+		pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n",
+			 ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
+			 ct_ftp_info->seq_aft_nl[dir][0],
+			 ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
+			 ct_ftp_info->seq_aft_nl[dir][1]);
 		ret = NF_ACCEPT;
 		goto out_update_nl;
 	}
@@ -440,11 +436,11 @@
 		goto out_update_nl;
 	}
 
-	DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
-	       (int)matchlen, fb_ptr + matchoff,
-	       matchlen, ntohl(th->seq) + matchoff);
+	pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
+		 matchlen, fb_ptr + matchoff,
+		 matchlen, ntohl(th->seq) + matchoff);
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL) {
 		ret = NF_DROP;
 		goto out;
@@ -453,7 +449,7 @@
 	/* We refer to the reverse direction ("!dir") tuples here,
 	 * because we're expecting something in the other direction.
 	 * Doesn't matter unless NAT is happening.  */
-	exp->tuple.dst.u3 = ct->tuplehash[!dir].tuple.dst.u3;
+	daddr = &ct->tuplehash[!dir].tuple.dst.u3;
 
 	/* Update the ftp info */
 	if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) &&
@@ -464,14 +460,16 @@
 		   different IP address.  Simply don't record it for
 		   NAT. */
 		if (cmd.l3num == PF_INET) {
-			DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n",
-			       NIPQUAD(cmd.u3.ip),
-			       NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
+			pr_debug("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT
+				 " != " NIPQUAD_FMT "\n",
+				 NIPQUAD(cmd.u3.ip),
+				 NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
 		} else {
-			DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n",
-			       NIP6(*((struct in6_addr *)cmd.u3.ip6)),
-			       NIP6(*((struct in6_addr *)ct->tuplehash[dir]
-							.tuple.src.u3.ip6)));
+			pr_debug("conntrack_ftp: NOT RECORDING: " NIP6_FMT
+				 " != " NIP6_FMT "\n",
+				 NIP6(*((struct in6_addr *)cmd.u3.ip6)),
+				 NIP6(*((struct in6_addr *)
+					ct->tuplehash[dir].tuple.src.u3.ip6)));
 		}
 
 		/* Thanks to Cristiano Lincoln Mattos
@@ -482,54 +480,29 @@
 			ret = NF_ACCEPT;
 			goto out_put_expect;
 		}
-		memcpy(&exp->tuple.dst.u3, &cmd.u3.all,
-		       sizeof(exp->tuple.dst.u3));
+		daddr = &cmd.u3;
 	}
 
-	exp->tuple.src.u3 = ct->tuplehash[!dir].tuple.src.u3;
-	exp->tuple.src.l3num = cmd.l3num;
-	exp->tuple.src.u.tcp.port = 0;
-	exp->tuple.dst.u.tcp.port = cmd.u.tcp.port;
-	exp->tuple.dst.protonum = IPPROTO_TCP;
-
-	exp->mask = (struct nf_conntrack_tuple)
-		    { .src = { .l3num = 0xFFFF,
-			       .u = { .tcp = { 0 }},
-			     },
-		      .dst = { .protonum = 0xFF,
-			       .u = { .tcp = { __constant_htons(0xFFFF) }},
-			     },
-		    };
-	if (cmd.l3num == PF_INET) {
-		exp->mask.src.u3.ip = htonl(0xFFFFFFFF);
-		exp->mask.dst.u3.ip = htonl(0xFFFFFFFF);
-	} else {
-		memset(exp->mask.src.u3.ip6, 0xFF,
-		       sizeof(exp->mask.src.u3.ip6));
-		memset(exp->mask.dst.u3.ip6, 0xFF,
-		       sizeof(exp->mask.src.u3.ip6));
-	}
-
-	exp->expectfn = NULL;
-	exp->helper = NULL;
-	exp->flags = 0;
+	nf_ct_expect_init(exp, cmd.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, daddr,
+			  IPPROTO_TCP, NULL, &cmd.u.tcp.port);
 
 	/* Now, NAT might want to mangle the packet, and register the
 	 * (possibly changed) expectation itself. */
 	nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
 	if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
 		ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
-				 matchoff, matchlen, exp, &seq);
+				 matchoff, matchlen, exp);
 	else {
 		/* Can't expect this?  Best to drop packet now. */
-		if (nf_conntrack_expect_related(exp) != 0)
+		if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
 		else
 			ret = NF_ACCEPT;
 	}
 
 out_put_expect:
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 out_update_nl:
 	/* Now if this ends in \n, update ftp info.  Seq may have been
@@ -541,8 +514,8 @@
 	return ret;
 }
 
-static struct nf_conntrack_helper ftp[MAX_PORTS][2];
-static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")];
+static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
+static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly;
 
 /* don't make this __exit, since it's called from __init ! */
 static void nf_conntrack_ftp_fini(void)
@@ -553,9 +526,9 @@
 			if (ftp[i][j].me == NULL)
 				continue;
 
-			DEBUGP("nf_ct_ftp: unregistering helper for pf: %d "
-			       "port: %d\n",
-				ftp[i][j].tuple.src.l3num, ports[i]);
+			pr_debug("nf_ct_ftp: unregistering helper for pf: %d "
+				 "port: %d\n",
+				 ftp[i][j].tuple.src.l3num, ports[i]);
 			nf_conntrack_helper_unregister(&ftp[i][j]);
 		}
 	}
@@ -583,9 +556,6 @@
 		for (j = 0; j < 2; j++) {
 			ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
 			ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
-			ftp[i][j].mask.src.l3num = 0xFFFF;
-			ftp[i][j].mask.src.u.tcp.port = htons(0xFFFF);
-			ftp[i][j].mask.dst.protonum = 0xFF;
 			ftp[i][j].max_expected = 1;
 			ftp[i][j].timeout = 5 * 60;	/* 5 Minutes */
 			ftp[i][j].me = THIS_MODULE;
@@ -597,9 +567,9 @@
 				sprintf(tmpname, "ftp-%d", ports[i]);
 			ftp[i][j].name = tmpname;
 
-			DEBUGP("nf_ct_ftp: registering helper for pf: %d "
-			       "port: %d\n",
-				ftp[i][j].tuple.src.l3num, ports[i]);
+			pr_debug("nf_ct_ftp: registering helper for pf: %d "
+				 "port: %d\n",
+				 ftp[i][j].tuple.src.l3num, ports[i]);
 			ret = nf_conntrack_helper_register(&ftp[i][j]);
 			if (ret) {
 				printk("nf_ct_ftp: failed to register helper "
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
index f6fad71..a869403 100644
--- a/net/netfilter/nf_conntrack_h323_asn1.c
+++ b/net/netfilter/nf_conntrack_h323_asn1.c
@@ -518,7 +518,7 @@
 			CHECK_BOUND(bs, 2);
 			len = get_len(bs);
 			CHECK_BOUND(bs, len);
-			if (!base) {
+			if (!base || !(son->attr & DECODE)) {
 				PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
 				      " ", son->name);
 				bs->cur += len;
@@ -555,15 +555,6 @@
 
 	/* Decode the extension components */
 	for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
-		if (i < f->ub && son->attr & STOP) {
-			PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
-			      son->name);
-			return H323_ERROR_STOP;
-		}
-
-		if (!((0x80000000 >> opt) & bmp2))	/* Not present */
-			continue;
-
 		/* Check Range */
 		if (i >= f->ub) {	/* Newer Version? */
 			CHECK_BOUND(bs, 2);
@@ -573,6 +564,15 @@
 			continue;
 		}
 
+		if (son->attr & STOP) {
+			PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+			      son->name);
+			return H323_ERROR_STOP;
+		}
+
+		if (!((0x80000000 >> opt) & bmp2))	/* Not present */
+			continue;
+
 		CHECK_BOUND(bs, 2);
 		len = get_len(bs);
 		CHECK_BOUND(bs, len);
@@ -704,6 +704,8 @@
 	} else {
 		ext = 0;
 		type = get_bits(bs, f->sz);
+		if (type >= f->lb)
+			return H323_ERROR_RANGE;
 	}
 
 	/* Write Type */
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index b284db7..a8a9dfb 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -31,12 +31,6 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Parameters */
 static unsigned int default_rrq_ttl __read_mostly = 300;
 module_param(default_rrq_ttl, uint, 0600);
@@ -150,9 +144,9 @@
 		if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
 			/* Netmeeting sends TPKT header and data separately */
 			if (info->tpkt_len[dir] > 0) {
-				DEBUGP("nf_ct_h323: previous packet "
-				       "indicated separate TPKT data of %hu "
-				       "bytes\n", info->tpkt_len[dir]);
+				pr_debug("nf_ct_h323: previous packet "
+					 "indicated separate TPKT data of %hu "
+					 "bytes\n", info->tpkt_len[dir]);
 				if (info->tpkt_len[dir] <= tcpdatalen) {
 					/* Yes, there was a TPKT header
 					 * received */
@@ -163,9 +157,7 @@
 				}
 
 				/* Fragmented TPKT */
-				if (net_ratelimit())
-					printk("nf_ct_h323: "
-					       "fragmented TPKT\n");
+				pr_debug("nf_ct_h323: fragmented TPKT\n");
 				goto clear_out;
 			}
 
@@ -192,9 +184,9 @@
 	if (tpktlen > tcpdatalen) {
 		if (tcpdatalen == 4) {	/* Separate TPKT header */
 			/* Netmeeting sends TPKT header and data separately */
-			DEBUGP("nf_ct_h323: separate TPKT header indicates "
-			       "there will be TPKT data of %hu bytes\n",
-			       tpktlen - 4);
+			pr_debug("nf_ct_h323: separate TPKT header indicates "
+				 "there will be TPKT data of %hu bytes\n",
+				 tpktlen - 4);
 			info->tpkt_len[dir] = tpktlen - 4;
 			return 0;
 		}
@@ -282,22 +274,22 @@
 	rtcp_port = htons(ntohs(port) + 1);
 
 	/* Create expect for RTP */
-	if ((rtp_exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_UDP, NULL, &rtp_port);
+	nf_ct_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_UDP, NULL, &rtp_port);
 
 	/* Create expect for RTCP */
-	if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) {
-		nf_conntrack_expect_put(rtp_exp);
+	if ((rtcp_exp = nf_ct_expect_alloc(ct)) == NULL) {
+		nf_ct_expect_put(rtp_exp);
 		return -1;
 	}
-	nf_conntrack_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_UDP, NULL, &rtcp_port);
+	nf_ct_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_UDP, NULL, &rtcp_port);
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
 		   &ct->tuplehash[!dir].tuple.dst.u3,
@@ -308,22 +300,22 @@
 		ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
 				   taddr, port, rtp_port, rtp_exp, rtcp_exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(rtp_exp) == 0) {
-			if (nf_conntrack_expect_related(rtcp_exp) == 0) {
-				DEBUGP("nf_ct_h323: expect RTP ");
+		if (nf_ct_expect_related(rtp_exp) == 0) {
+			if (nf_ct_expect_related(rtcp_exp) == 0) {
+				pr_debug("nf_ct_h323: expect RTP ");
 				NF_CT_DUMP_TUPLE(&rtp_exp->tuple);
-				DEBUGP("nf_ct_h323: expect RTCP ");
+				pr_debug("nf_ct_h323: expect RTCP ");
 				NF_CT_DUMP_TUPLE(&rtcp_exp->tuple);
 			} else {
-				nf_conntrack_unexpect_related(rtp_exp);
+				nf_ct_unexpect_related(rtp_exp);
 				ret = -1;
 			}
 		} else
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(rtp_exp);
-	nf_conntrack_expect_put(rtcp_exp);
+	nf_ct_expect_put(rtp_exp);
+	nf_ct_expect_put(rtcp_exp);
 
 	return ret;
 }
@@ -349,12 +341,12 @@
 		return 0;
 
 	/* Create expect for T.120 connections */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_TCP, NULL, &port);
 	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple channels */
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -366,14 +358,14 @@
 		ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr,
 			       port, exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(exp) == 0) {
-			DEBUGP("nf_ct_h323: expect T.120 ");
+		if (nf_ct_expect_related(exp) == 0) {
+			pr_debug("nf_ct_h323: expect T.120 ");
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 		} else
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -415,7 +407,7 @@
 {
 	int ret;
 
-	DEBUGP("nf_ct_h323: OpenLogicalChannel\n");
+	pr_debug("nf_ct_h323: OpenLogicalChannel\n");
 
 	if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
 	    eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
@@ -475,7 +467,7 @@
 	H2250LogicalChannelAckParameters *ack;
 	int ret;
 
-	DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n");
+	pr_debug("nf_ct_h323: OpenLogicalChannelAck\n");
 
 	if ((olca->options &
 	     eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
@@ -520,6 +512,16 @@
 		}
 	}
 
+	if ((olca->options & eOpenLogicalChannelAck_separateStack) &&
+		olca->separateStack.networkAddress.choice ==
+		eNetworkAccessParameters_networkAddress_localAreaAddress) {
+		ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
+				  &olca->separateStack.networkAddress.
+				  localAreaAddress);
+		if (ret < 0)
+			return -1;
+	}
+
 	return 0;
 }
 
@@ -536,8 +538,8 @@
 			return process_olc(pskb, ct, ctinfo, data, dataoff,
 					   &mscm->request.openLogicalChannel);
 		}
-		DEBUGP("nf_ct_h323: H.245 Request %d\n",
-		       mscm->request.choice);
+		pr_debug("nf_ct_h323: H.245 Request %d\n",
+			 mscm->request.choice);
 		break;
 	case eMultimediaSystemControlMessage_response:
 		if (mscm->response.choice ==
@@ -546,11 +548,11 @@
 					    &mscm->response.
 					    openLogicalChannelAck);
 		}
-		DEBUGP("nf_ct_h323: H.245 Response %d\n",
-		       mscm->response.choice);
+		pr_debug("nf_ct_h323: H.245 Response %d\n",
+			 mscm->response.choice);
 		break;
 	default:
-		DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice);
+		pr_debug("nf_ct_h323: H.245 signal %d\n", mscm->choice);
 		break;
 	}
 
@@ -572,24 +574,23 @@
 	    ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
 		return NF_ACCEPT;
 	}
-	DEBUGP("nf_ct_h245: skblen = %u\n", (*pskb)->len);
+	pr_debug("nf_ct_h245: skblen = %u\n", (*pskb)->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
 	/* Process each TPKT */
 	while (get_tpkt_data(pskb, protoff, ct, ctinfo,
 			     &data, &datalen, &dataoff)) {
-		DEBUGP("nf_ct_h245: TPKT len=%d ", datalen);
+		pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
 		NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 		/* Decode H.245 signal */
 		ret = DecodeMultimediaSystemControlMessage(data, datalen,
 							   &mscm);
 		if (ret < 0) {
-			if (net_ratelimit())
-				printk("nf_ct_h245: decoding error: %s\n",
-				       ret == H323_ERROR_BOUND ?
-				       "out of bound" : "out of range");
+			pr_debug("nf_ct_h245: decoding error: %s\n",
+				 ret == H323_ERROR_BOUND ?
+				 "out of bound" : "out of range");
 			/* We don't drop when decoding error */
 			break;
 		}
@@ -616,8 +617,6 @@
 	.max_expected		= H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
 	.timeout		= 240,
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-	.mask.dst.protonum	= 0xFF,
 	.help			= h245_help
 };
 
@@ -640,7 +639,7 @@
 	case eTransportAddress_ip6Address:
 		if (family != AF_INET6)
 			return 0;
-		p = data + taddr->ip6Address.ip6;
+		p = data + taddr->ip6Address.ip;
 		len = 16;
 		break;
 	default:
@@ -674,12 +673,12 @@
 		return 0;
 
 	/* Create expect for h245 connection */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_TCP, NULL, &port);
 	exp->helper = &nf_conntrack_helper_h245;
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -691,14 +690,14 @@
 		ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr,
 			       port, exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(exp) == 0) {
-			DEBUGP("nf_ct_q931: expect H.245 ");
+		if (nf_ct_expect_related(exp) == 0) {
+			pr_debug("nf_ct_q931: expect H.245 ");
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 		} else
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -781,16 +780,16 @@
 	if (callforward_filter &&
 	    callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
 				  ct->tuplehash[!dir].tuple.src.l3num)) {
-		DEBUGP("nf_ct_q931: Call Forwarding not tracked\n");
+		pr_debug("nf_ct_q931: Call Forwarding not tracked\n");
 		return 0;
 	}
 
 	/* Create expect for the second call leg */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3, &addr,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+			  IPPROTO_TCP, NULL, &port);
 	exp->helper = nf_conntrack_helper_q931;
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -802,14 +801,14 @@
 		ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
 					 taddr, port, exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(exp) == 0) {
-			DEBUGP("nf_ct_q931: expect Call Forwarding ");
+		if (nf_ct_expect_related(exp) == 0) {
+			pr_debug("nf_ct_q931: expect Call Forwarding ");
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 		} else
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -827,7 +826,7 @@
 	union nf_conntrack_address addr;
 	typeof(set_h225_addr_hook) set_h225_addr;
 
-	DEBUGP("nf_ct_q931: Setup\n");
+	pr_debug("nf_ct_q931: Setup\n");
 
 	if (setup->options & eSetup_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -842,11 +841,11 @@
 	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
 			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
-		DEBUGP("nf_ct_q931: set destCallSignalAddress "
-		       NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
-		       NIP6(*(struct in6_addr *)&addr), ntohs(port),
-		       NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
-		       ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
+		pr_debug("nf_ct_q931: set destCallSignalAddress "
+			 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
+			 NIP6(*(struct in6_addr *)&addr), ntohs(port),
+			 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
+			 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
 		ret = set_h225_addr(pskb, data, dataoff,
 				    &setup->destCallSignalAddress,
 				    &ct->tuplehash[!dir].tuple.src.u3,
@@ -860,11 +859,11 @@
 	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
 			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
-		DEBUGP("nf_ct_q931: set sourceCallSignalAddress "
-		       NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
-		       NIP6(*(struct in6_addr *)&addr), ntohs(port),
-		       NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
-		       ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
+		pr_debug("nf_ct_q931: set sourceCallSignalAddress "
+			 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
+			 NIP6(*(struct in6_addr *)&addr), ntohs(port),
+			 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
+			 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
 		ret = set_h225_addr(pskb, data, dataoff,
 				    &setup->sourceCallSignalAddress,
 				    &ct->tuplehash[!dir].tuple.dst.u3,
@@ -895,7 +894,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: CallProceeding\n");
+	pr_debug("nf_ct_q931: CallProceeding\n");
 
 	if (callproc->options & eCallProceeding_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -925,7 +924,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: Connect\n");
+	pr_debug("nf_ct_q931: Connect\n");
 
 	if (connect->options & eConnect_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -955,7 +954,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: Alerting\n");
+	pr_debug("nf_ct_q931: Alerting\n");
 
 	if (alert->options & eAlerting_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -977,30 +976,6 @@
 }
 
 /****************************************************************************/
-static int process_information(struct sk_buff **pskb,
-			       struct nf_conn *ct,
-			       enum ip_conntrack_info ctinfo,
-			       unsigned char **data, int dataoff,
-			       Information_UUIE *info)
-{
-	int ret;
-	int i;
-
-	DEBUGP("nf_ct_q931: Information\n");
-
-	if (info->options & eInformation_UUIE_fastStart) {
-		for (i = 0; i < info->fastStart.count; i++) {
-			ret = process_olc(pskb, ct, ctinfo, data, dataoff,
-					  &info->fastStart.item[i]);
-			if (ret < 0)
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
-/****************************************************************************/
 static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
 			    enum ip_conntrack_info ctinfo,
 			    unsigned char **data, int dataoff,
@@ -1009,7 +984,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: Facility\n");
+	pr_debug("nf_ct_q931: Facility\n");
 
 	if (facility->reason.choice == eFacilityReason_callForwarded) {
 		if (facility->options & eFacility_UUIE_alternativeAddress)
@@ -1048,7 +1023,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: Progress\n");
+	pr_debug("nf_ct_q931: Progress\n");
 
 	if (progress->options & eProgress_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -1096,11 +1071,6 @@
 		ret = process_alerting(pskb, ct, ctinfo, data, dataoff,
 				       &pdu->h323_message_body.alerting);
 		break;
-	case eH323_UU_PDU_h323_message_body_information:
-		ret = process_information(pskb, ct, ctinfo, data, dataoff,
-					  &pdu->h323_message_body.
-					  information);
-		break;
 	case eH323_UU_PDU_h323_message_body_facility:
 		ret = process_facility(pskb, ct, ctinfo, data, dataoff,
 				       &pdu->h323_message_body.facility);
@@ -1110,8 +1080,8 @@
 				       &pdu->h323_message_body.progress);
 		break;
 	default:
-		DEBUGP("nf_ct_q931: Q.931 signal %d\n",
-		       pdu->h323_message_body.choice);
+		pr_debug("nf_ct_q931: Q.931 signal %d\n",
+			 pdu->h323_message_body.choice);
 		break;
 	}
 
@@ -1145,23 +1115,22 @@
 	    ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
 		return NF_ACCEPT;
 	}
-	DEBUGP("nf_ct_q931: skblen = %u\n", (*pskb)->len);
+	pr_debug("nf_ct_q931: skblen = %u\n", (*pskb)->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
 	/* Process each TPKT */
 	while (get_tpkt_data(pskb, protoff, ct, ctinfo,
 			     &data, &datalen, &dataoff)) {
-		DEBUGP("nf_ct_q931: TPKT len=%d ", datalen);
+		pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
 		NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 		/* Decode Q.931 signal */
 		ret = DecodeQ931(data, datalen, &q931);
 		if (ret < 0) {
-			if (net_ratelimit())
-				printk("nf_ct_q931: decoding error: %s\n",
-				       ret == H323_ERROR_BOUND ?
-				       "out of bound" : "out of range");
+			pr_debug("nf_ct_q931: decoding error: %s\n",
+				 ret == H323_ERROR_BOUND ?
+				 "out of bound" : "out of range");
 			/* We don't drop when decoding error */
 			break;
 		}
@@ -1192,9 +1161,6 @@
 		.tuple.src.l3num	= AF_INET,
 		.tuple.src.u.tcp.port	= __constant_htons(Q931_PORT),
 		.tuple.dst.protonum	= IPPROTO_TCP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.tcp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 		.help			= q931_help
 	},
 	{
@@ -1206,9 +1172,6 @@
 		.tuple.src.l3num	= AF_INET6,
 		.tuple.src.u.tcp.port	= __constant_htons(Q931_PORT),
 		.tuple.dst.protonum	= IPPROTO_TCP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.tcp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 		.help			= q931_help
 	},
 };
@@ -1244,7 +1207,7 @@
 	tuple.dst.u.tcp.port = port;
 	tuple.dst.protonum = IPPROTO_TCP;
 
-	exp = __nf_conntrack_expect_find(&tuple);
+	exp = __nf_ct_expect_find(&tuple);
 	if (exp && exp->master == ct)
 		return exp;
 	return NULL;
@@ -1290,14 +1253,13 @@
 		return 0;
 
 	/* Create expect for Q.931 */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 gkrouted_only ? /* only accept calls from GK? */
-					&ct->tuplehash[!dir].tuple.src.u3 :
-					NULL,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  gkrouted_only ? /* only accept calls from GK? */
+				&ct->tuplehash[!dir].tuple.src.u3 : NULL,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_TCP, NULL, &port);
 	exp->helper = nf_conntrack_helper_q931;
 	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple calls */
 
@@ -1305,8 +1267,8 @@
 	if (nat_q931 && ct->status & IPS_NAT_MASK) {	/* Need NAT */
 		ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(exp) == 0) {
-			DEBUGP("nf_ct_ras: expect Q.931 ");
+		if (nf_ct_expect_related(exp) == 0) {
+			pr_debug("nf_ct_ras: expect Q.931 ");
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 
 			/* Save port for looking up expect in processing RCF */
@@ -1315,7 +1277,7 @@
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -1327,7 +1289,7 @@
 {
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	DEBUGP("nf_ct_ras: GRQ\n");
+	pr_debug("nf_ct_ras: GRQ\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK)	/* NATed */
@@ -1347,7 +1309,7 @@
 	union nf_conntrack_address addr;
 	struct nf_conntrack_expect *exp;
 
-	DEBUGP("nf_ct_ras: GCF\n");
+	pr_debug("nf_ct_ras: GCF\n");
 
 	if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port))
 		return 0;
@@ -1362,20 +1324,20 @@
 		return 0;
 
 	/* Need new expect */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3, &addr,
-				 IPPROTO_UDP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+			  IPPROTO_UDP, NULL, &port);
 	exp->helper = nf_conntrack_helper_ras;
 
-	if (nf_conntrack_expect_related(exp) == 0) {
-		DEBUGP("nf_ct_ras: expect RAS ");
+	if (nf_ct_expect_related(exp) == 0) {
+		pr_debug("nf_ct_ras: expect RAS ");
 		NF_CT_DUMP_TUPLE(&exp->tuple);
 	} else
 		ret = -1;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -1389,7 +1351,7 @@
 	int ret;
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	DEBUGP("nf_ct_ras: RRQ\n");
+	pr_debug("nf_ct_ras: RRQ\n");
 
 	ret = expect_q931(pskb, ct, ctinfo, data,
 			  rrq->callSignalAddress.item,
@@ -1407,7 +1369,7 @@
 	}
 
 	if (rrq->options & eRegistrationRequest_timeToLive) {
-		DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
+		pr_debug("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
 		info->timeout = rrq->timeToLive;
 	} else
 		info->timeout = default_rrq_ttl;
@@ -1426,7 +1388,7 @@
 	struct nf_conntrack_expect *exp;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	DEBUGP("nf_ct_ras: RCF\n");
+	pr_debug("nf_ct_ras: RCF\n");
 
 	set_sig_addr = rcu_dereference(set_sig_addr_hook);
 	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
@@ -1438,14 +1400,13 @@
 	}
 
 	if (rcf->options & eRegistrationConfirm_timeToLive) {
-		DEBUGP("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
+		pr_debug("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
 		info->timeout = rcf->timeToLive;
 	}
 
 	if (info->timeout > 0) {
-		DEBUGP
-		    ("nf_ct_ras: set RAS connection timeout to %u seconds\n",
-		     info->timeout);
+		pr_debug("nf_ct_ras: set RAS connection timeout to "
+			 "%u seconds\n", info->timeout);
 		nf_ct_refresh(ct, *pskb, info->timeout * HZ);
 
 		/* Set expect timeout */
@@ -1453,9 +1414,9 @@
 		exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
 				  info->sig_port[!dir]);
 		if (exp) {
-			DEBUGP("nf_ct_ras: set Q.931 expect "
-			       "timeout to %u seconds for",
-			       info->timeout);
+			pr_debug("nf_ct_ras: set Q.931 expect "
+				 "timeout to %u seconds for",
+				 info->timeout);
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 			set_expect_timeout(exp, info->timeout);
 		}
@@ -1475,7 +1436,7 @@
 	int ret;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	DEBUGP("nf_ct_ras: URQ\n");
+	pr_debug("nf_ct_ras: URQ\n");
 
 	set_sig_addr = rcu_dereference(set_sig_addr_hook);
 	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
@@ -1508,7 +1469,7 @@
 	union nf_conntrack_address addr;
 	typeof(set_h225_addr_hook) set_h225_addr;
 
-	DEBUGP("nf_ct_ras: ARQ\n");
+	pr_debug("nf_ct_ras: ARQ\n");
 
 	set_h225_addr = rcu_dereference(set_h225_addr_hook);
 	if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
@@ -1551,7 +1512,7 @@
 	struct nf_conntrack_expect *exp;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	DEBUGP("nf_ct_ras: ACF\n");
+	pr_debug("nf_ct_ras: ACF\n");
 
 	if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress,
 			   &addr, &port))
@@ -1567,21 +1528,21 @@
 	}
 
 	/* Need new expect */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3, &addr,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+			  IPPROTO_TCP, NULL, &port);
 	exp->flags = NF_CT_EXPECT_PERMANENT;
 	exp->helper = nf_conntrack_helper_q931;
 
-	if (nf_conntrack_expect_related(exp) == 0) {
-		DEBUGP("nf_ct_ras: expect Q.931 ");
+	if (nf_ct_expect_related(exp) == 0) {
+		pr_debug("nf_ct_ras: expect Q.931 ");
 		NF_CT_DUMP_TUPLE(&exp->tuple);
 	} else
 		ret = -1;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -1593,7 +1554,7 @@
 {
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	DEBUGP("nf_ct_ras: LRQ\n");
+	pr_debug("nf_ct_ras: LRQ\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK)
@@ -1613,28 +1574,28 @@
 	union nf_conntrack_address addr;
 	struct nf_conntrack_expect *exp;
 
-	DEBUGP("nf_ct_ras: LCF\n");
+	pr_debug("nf_ct_ras: LCF\n");
 
 	if (!get_h225_addr(ct, *data, &lcf->callSignalAddress,
 			   &addr, &port))
 		return 0;
 
 	/* Need new expect for call signal */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3, &addr,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+			  IPPROTO_TCP, NULL, &port);
 	exp->flags = NF_CT_EXPECT_PERMANENT;
 	exp->helper = nf_conntrack_helper_q931;
 
-	if (nf_conntrack_expect_related(exp) == 0) {
-		DEBUGP("nf_ct_ras: expect Q.931 ");
+	if (nf_ct_expect_related(exp) == 0) {
+		pr_debug("nf_ct_ras: expect Q.931 ");
 		NF_CT_DUMP_TUPLE(&exp->tuple);
 	} else
 		ret = -1;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	/* Ignore rasAddress */
 
@@ -1650,7 +1611,7 @@
 	typeof(set_ras_addr_hook) set_ras_addr;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	DEBUGP("nf_ct_ras: IRR\n");
+	pr_debug("nf_ct_ras: IRR\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK) {
@@ -1709,7 +1670,7 @@
 		return process_irr(pskb, ct, ctinfo, data,
 				   &ras->infoRequestResponse);
 	default:
-		DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice);
+		pr_debug("nf_ct_ras: RAS message %d\n", ras->choice);
 		break;
 	}
 
@@ -1725,7 +1686,7 @@
 	int datalen = 0;
 	int ret;
 
-	DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len);
+	pr_debug("nf_ct_ras: skblen = %u\n", (*pskb)->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
@@ -1733,16 +1694,15 @@
 	data = get_udp_data(pskb, protoff, &datalen);
 	if (data == NULL)
 		goto accept;
-	DEBUGP("nf_ct_ras: RAS message len=%d ", datalen);
+	pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
 	NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 	/* Decode RAS message */
 	ret = DecodeRasMessage(data, datalen, &ras);
 	if (ret < 0) {
-		if (net_ratelimit())
-			printk("nf_ct_ras: decoding error: %s\n",
-			       ret == H323_ERROR_BOUND ?
-			       "out of bound" : "out of range");
+		pr_debug("nf_ct_ras: decoding error: %s\n",
+			 ret == H323_ERROR_BOUND ?
+			 "out of bound" : "out of range");
 		goto accept;
 	}
 
@@ -1771,9 +1731,6 @@
 		.tuple.src.l3num	= AF_INET,
 		.tuple.src.u.udp.port	= __constant_htons(RAS_PORT),
 		.tuple.dst.protonum	= IPPROTO_UDP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 		.help			= ras_help,
 	},
 	{
@@ -1784,9 +1741,6 @@
 		.tuple.src.l3num	= AF_INET6,
 		.tuple.src.u.udp.port	= __constant_htons(RAS_PORT),
 		.tuple.dst.protonum	= IPPROTO_UDP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 		.help			= ras_help,
 	},
 };
@@ -1799,7 +1753,7 @@
 	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
 	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
 	kfree(h323_buffer);
-	DEBUGP("nf_ct_h323: fini\n");
+	pr_debug("nf_ct_h323: fini\n");
 }
 
 /****************************************************************************/
@@ -1822,7 +1776,7 @@
 	ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
 	if (ret < 0)
 		goto err4;
-	DEBUGP("nf_ct_h323: init success\n");
+	pr_debug("nf_ct_h323: init success\n");
 	return 0;
 
 err4:
diff --git a/net/netfilter/nf_conntrack_h323_types.c b/net/netfilter/nf_conntrack_h323_types.c
index 4c6f8b3..3a21fdf 100644
--- a/net/netfilter/nf_conntrack_h323_types.c
+++ b/net/netfilter/nf_conntrack_h323_types.c
@@ -1,4 +1,4 @@
-/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
+/* Generated by Jing Min Zhao's ASN.1 parser, May 16 2007
  *
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
@@ -37,7 +37,7 @@
 
 static field_t _TransportAddress_ip6Address[] = {	/* SEQUENCE */
 	{FNAME("ip") OCTSTR, FIXD, 16, 0, DECODE,
-	 offsetof(TransportAddress_ip6Address, ip6), NULL},
+	 offsetof(TransportAddress_ip6Address, ip), NULL},
 	{FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
 };
 
@@ -67,7 +67,8 @@
 	{FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0,
 	 _TransportAddress_ipxAddress},
 	{FNAME("ip6Address") SEQ, 0, 2, 2, DECODE | EXT,
-	offsetof(TransportAddress, ip6Address), _TransportAddress_ip6Address},
+	 offsetof(TransportAddress, ip6Address),
+	 _TransportAddress_ip6Address},
 	{FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
 	{FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
 	{FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0,
@@ -638,7 +639,8 @@
 };
 
 static field_t _UnicastAddress_iP6Address[] = {	/* SEQUENCE */
-	{FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
+	{FNAME("network") OCTSTR, FIXD, 16, 0, DECODE,
+	 offsetof(UnicastAddress_iP6Address, network), NULL},
 	{FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
 };
 
@@ -665,8 +667,8 @@
 	 offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress},
 	{FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0,
 	 _UnicastAddress_iPXAddress},
-	{FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
-	 _UnicastAddress_iP6Address},
+	{FNAME("iP6Address") SEQ, 0, 2, 2, DECODE | EXT,
+	 offsetof(UnicastAddress, iP6Address), _UnicastAddress_iP6Address},
 	{FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
 	{FNAME("iPSourceRouteAddress") SEQ, 0, 4, 4, SKIP | EXT, 0,
 	 _UnicastAddress_iPSourceRouteAddress},
@@ -984,19 +986,12 @@
 	{FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
 };
 
-static field_t _Information_UUIE_fastStart[] = {	/* SEQUENCE OF */
-	{FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
-	 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
-	,
-};
-
 static field_t _Information_UUIE[] = {	/* SEQUENCE */
 	{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
 	{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
 	{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
 	{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
-	{FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
-	 offsetof(Information_UUIE, fastStart), _Information_UUIE_fastStart},
+	{FNAME("fastStart") SEQOF, SEMI, 0, 30, SKIP | OPT, 0, NULL},
 	{FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
 	{FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
 };
@@ -1343,9 +1338,7 @@
 	 offsetof(H323_UU_PDU_h323_message_body, connect), _Connect_UUIE},
 	{FNAME("alerting") SEQ, 1, 3, 17, DECODE | EXT,
 	 offsetof(H323_UU_PDU_h323_message_body, alerting), _Alerting_UUIE},
-	{FNAME("information") SEQ, 0, 1, 7, DECODE | EXT,
-	 offsetof(H323_UU_PDU_h323_message_body, information),
-	 _Information_UUIE},
+	{FNAME("information") SEQ, 0, 1, 7, SKIP | EXT, 0, _Information_UUIE},
 	{FNAME("releaseComplete") SEQ, 1, 2, 11, SKIP | EXT, 0,
 	 _ReleaseComplete_UUIE},
 	{FNAME("facility") SEQ, 3, 5, 21, DECODE | EXT,
@@ -1430,7 +1423,9 @@
 	 DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
 				      reverseLogicalChannelParameters),
 	 _OpenLogicalChannelAck_reverseLogicalChannelParameters},
-	{FNAME("separateStack") SEQ, 2, 4, 5, SKIP | EXT | OPT, 0, NULL},
+	{FNAME("separateStack") SEQ, 2, 4, 5, DECODE | EXT | OPT,
+	 offsetof(OpenLogicalChannelAck, separateStack),
+	 _NetworkAccessParameters},
 	{FNAME("forwardMultiplexAckParameters") CHOICE, 0, 1, 1,
 	 DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
 				      forwardMultiplexAckParameters),
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 0743be4..b1179dd 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -26,23 +26,43 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
-static __read_mostly LIST_HEAD(helpers);
+static struct hlist_head *nf_ct_helper_hash __read_mostly;
+static unsigned int nf_ct_helper_hsize __read_mostly;
+static unsigned int nf_ct_helper_count __read_mostly;
+static int nf_ct_helper_vmalloc;
+
+
+/* Stupid hash, but collision free for the default registrations of the
+ * helpers currently in the kernel. */
+static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple)
+{
+	return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^
+		tuple->src.u.all) % nf_ct_helper_hsize;
+}
 
 struct nf_conntrack_helper *
 __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
 {
-	struct nf_conntrack_helper *h;
+	struct nf_conntrack_helper *helper;
+	struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
+	struct hlist_node *n;
+	unsigned int h;
 
-	list_for_each_entry(h, &helpers, list) {
-		if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
-			return h;
+	if (!nf_ct_helper_count)
+		return NULL;
+
+	h = helper_hash(tuple);
+	hlist_for_each_entry(helper, n, &nf_ct_helper_hash[h], hnode) {
+		if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask))
+			return helper;
 	}
 	return NULL;
 }
 
 struct nf_conntrack_helper *
-nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
+nf_ct_helper_find_get(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_helper *helper;
 
@@ -75,16 +95,32 @@
 __nf_conntrack_helper_find_byname(const char *name)
 {
 	struct nf_conntrack_helper *h;
+	struct hlist_node *n;
+	unsigned int i;
 
-	list_for_each_entry(h, &helpers, list) {
-		if (!strcmp(h->name, name))
-			return h;
+	for (i = 0; i < nf_ct_helper_hsize; i++) {
+		hlist_for_each_entry(h, n, &nf_ct_helper_hash[i], hnode) {
+			if (!strcmp(h->name, name))
+				return h;
+		}
 	}
-
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname);
 
+struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+	struct nf_conn_help *help;
+
+	help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, gfp);
+	if (help)
+		INIT_HLIST_HEAD(&help->expectations);
+	else
+		pr_debug("failed to add helper extension area");
+	return help;
+}
+EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
+
 static inline int unhelp(struct nf_conntrack_tuple_hash *i,
 			 const struct nf_conntrack_helper *me)
 {
@@ -93,27 +129,20 @@
 
 	if (help && help->helper == me) {
 		nf_conntrack_event(IPCT_HELPER, ct);
-		help->helper = NULL;
+		rcu_assign_pointer(help->helper, NULL);
 	}
 	return 0;
 }
 
 int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
-	int size, ret;
+	unsigned int h = helper_hash(&me->tuple);
 
 	BUG_ON(me->timeout == 0);
 
-	size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_help)) +
-	       sizeof(struct nf_conn_help);
-	ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
-					  size);
-	if (ret < 0) {
-		printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n");
-		return ret;
-	}
 	write_lock_bh(&nf_conntrack_lock);
-	list_add(&me->list, &helpers);
+	hlist_add_head(&me->hnode, &nf_ct_helper_hash[h]);
+	nf_ct_helper_count++;
 	write_unlock_bh(&nf_conntrack_lock);
 
 	return 0;
@@ -122,29 +151,34 @@
 
 void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
 {
-	unsigned int i;
 	struct nf_conntrack_tuple_hash *h;
-	struct nf_conntrack_expect *exp, *tmp;
+	struct nf_conntrack_expect *exp;
+	struct hlist_node *n, *next;
+	unsigned int i;
 
 	/* Need write lock here, to delete helper. */
 	write_lock_bh(&nf_conntrack_lock);
-	list_del(&me->list);
+	hlist_del(&me->hnode);
+	nf_ct_helper_count--;
 
 	/* Get rid of expectations */
-	list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
-		struct nf_conn_help *help = nfct_help(exp->master);
-		if ((help->helper == me || exp->helper == me) &&
-		    del_timer(&exp->timeout)) {
-			nf_ct_unlink_expect(exp);
-			nf_conntrack_expect_put(exp);
+	for (i = 0; i < nf_ct_expect_hsize; i++) {
+		hlist_for_each_entry_safe(exp, n, next,
+					  &nf_ct_expect_hash[i], hnode) {
+			struct nf_conn_help *help = nfct_help(exp->master);
+			if ((help->helper == me || exp->helper == me) &&
+			    del_timer(&exp->timeout)) {
+				nf_ct_unlink_expect(exp);
+				nf_ct_expect_put(exp);
+			}
 		}
 	}
 
 	/* Get rid of expecteds, set helpers to NULL. */
-	list_for_each_entry(h, &unconfirmed, list)
+	hlist_for_each_entry(h, n, &unconfirmed, hnode)
 		unhelp(h, me);
 	for (i = 0; i < nf_conntrack_htable_size; i++) {
-		list_for_each_entry(h, &nf_conntrack_hash[i], list)
+		hlist_for_each_entry(h, n, &nf_conntrack_hash[i], hnode)
 			unhelp(h, me);
 	}
 	write_unlock_bh(&nf_conntrack_lock);
@@ -153,3 +187,38 @@
 	synchronize_net();
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
+
+static struct nf_ct_ext_type helper_extend __read_mostly = {
+	.len	= sizeof(struct nf_conn_help),
+	.align	= __alignof__(struct nf_conn_help),
+	.id	= NF_CT_EXT_HELPER,
+};
+
+int nf_conntrack_helper_init()
+{
+	int err;
+
+	nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
+	nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize,
+						  &nf_ct_helper_vmalloc);
+	if (!nf_ct_helper_hash)
+		return -ENOMEM;
+
+	err = nf_ct_extend_register(&helper_extend);
+	if (err < 0)
+		goto err1;
+
+	return 0;
+
+err1:
+	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
+			     nf_ct_helper_hsize);
+	return err;
+}
+
+void nf_conntrack_helper_fini()
+{
+	nf_ct_extend_unregister(&helper_extend);
+	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
+			     nf_ct_helper_hsize);
+}
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 43ccd0e..1562ca9 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -12,6 +12,7 @@
 #include <linux/moduleparam.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
+#include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/netfilter.h>
 
@@ -55,13 +56,6 @@
 
 #define MINMATCHLEN	5
 
-#if 0
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \
-				       __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* tries to get the ip_addr and port out of a dcc command
  * return value: -1 on failure, 0 on success
  *	data		pointer to first byte of DCC command data
@@ -99,6 +93,7 @@
 		struct nf_conn *ct, enum ip_conntrack_info ctinfo)
 {
 	unsigned int dataoff;
+	struct iphdr *iph;
 	struct tcphdr _tcph, *th;
 	char *data, *data_limit, *ib_ptr;
 	int dir = CTINFO2DIR(ctinfo);
@@ -148,9 +143,10 @@
 		data += 5;
 		/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
 
-		DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
-			NIPQUAD(iph->saddr), ntohs(th->source),
-			NIPQUAD(iph->daddr), ntohs(th->dest));
+		iph = ip_hdr(*pskb);
+		pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n",
+			 NIPQUAD(iph->saddr), ntohs(th->source),
+			 NIPQUAD(iph->daddr), ntohs(th->dest));
 
 		for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
 			if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
@@ -158,18 +154,18 @@
 				continue;
 			}
 			data += strlen(dccprotos[i]);
-			DEBUGP("DCC %s detected\n", dccprotos[i]);
+			pr_debug("DCC %s detected\n", dccprotos[i]);
 
 			/* we have at least
 			 * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
 			 * data left (== 14/13 bytes) */
 			if (parse_dcc((char *)data, data_limit, &dcc_ip,
 				       &dcc_port, &addr_beg_p, &addr_end_p)) {
-				DEBUGP("unable to parse dcc command\n");
+				pr_debug("unable to parse dcc command\n");
 				continue;
 			}
-			DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n",
-				HIPQUAD(dcc_ip), dcc_port);
+			pr_debug("DCC bound ip/port: %u.%u.%u.%u:%u\n",
+				 HIPQUAD(dcc_ip), dcc_port);
 
 			/* dcc_ip can be the internal OR external (NAT'ed) IP */
 			tuple = &ct->tuplehash[dir].tuple;
@@ -184,16 +180,16 @@
 				continue;
 			}
 
-			exp = nf_conntrack_expect_alloc(ct);
+			exp = nf_ct_expect_alloc(ct);
 			if (exp == NULL) {
 				ret = NF_DROP;
 				goto out;
 			}
 			tuple = &ct->tuplehash[!dir].tuple;
 			port = htons(dcc_port);
-			nf_conntrack_expect_init(exp, tuple->src.l3num,
-						 NULL, &tuple->dst.u3,
-						 IPPROTO_TCP, NULL, &port);
+			nf_ct_expect_init(exp, tuple->src.l3num,
+					  NULL, &tuple->dst.u3,
+					  IPPROTO_TCP, NULL, &port);
 
 			nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
 			if (nf_nat_irc && ct->status & IPS_NAT_MASK)
@@ -201,9 +197,9 @@
 						 addr_beg_p - ib_ptr,
 						 addr_end_p - addr_beg_p,
 						 exp);
-			else if (nf_conntrack_expect_related(exp) != 0)
+			else if (nf_ct_expect_related(exp) != 0)
 				ret = NF_DROP;
-			nf_conntrack_expect_put(exp);
+			nf_ct_expect_put(exp);
 			goto out;
 		}
 	}
@@ -239,9 +235,6 @@
 		irc[i].tuple.src.l3num = AF_INET;
 		irc[i].tuple.src.u.tcp.port = htons(ports[i]);
 		irc[i].tuple.dst.protonum = IPPROTO_TCP;
-		irc[i].mask.src.l3num = 0xFFFF;
-		irc[i].mask.src.u.tcp.port = htons(0xFFFF);
-		irc[i].mask.dst.protonum = 0xFF;
 		irc[i].max_expected = max_dcc_channels;
 		irc[i].timeout = dcc_timeout;
 		irc[i].me = THIS_MODULE;
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index cbd96f3..991c52c 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -31,12 +31,6 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 				struct nf_conntrack_tuple *tuple)
 {
@@ -67,29 +61,21 @@
 	return 0;
 }
 
-static int
-generic_prepare(struct sk_buff **pskb, unsigned int hooknum,
-		unsigned int *dataoff, u_int8_t *protonum)
+static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
+			       unsigned int *dataoff, u_int8_t *protonum)
 {
 	/* Never track !!! */
 	return -NF_ACCEPT;
 }
 
 
-static u_int32_t generic_get_features(const struct nf_conntrack_tuple *tuple)
-
-{
-	return NF_CT_F_BASIC;
-}
-
-struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = {
+struct nf_conntrack_l3proto nf_conntrack_l3proto_generic __read_mostly = {
 	.l3proto	 = PF_UNSPEC,
 	.name		 = "unknown",
 	.pkt_to_tuple	 = generic_pkt_to_tuple,
 	.invert_tuple	 = generic_invert_tuple,
 	.print_tuple	 = generic_print_tuple,
 	.print_conntrack = generic_print_conntrack,
-	.prepare	 = generic_prepare,
-	.get_features	 = generic_get_features,
+	.get_l4proto	 = generic_get_l4proto,
 };
 EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic);
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index 1093478..1d59fab 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -74,7 +74,7 @@
 	if (mask == 0)
 		goto out;
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL)
 		goto out;
 
@@ -83,16 +83,13 @@
 
 	exp->mask.src.u3.ip       = mask;
 	exp->mask.src.u.udp.port  = htons(0xFFFF);
-	exp->mask.dst.u3.ip       = htonl(0xFFFFFFFF);
-	exp->mask.dst.u.udp.port  = htons(0xFFFF);
-	exp->mask.dst.protonum    = 0xFF;
 
 	exp->expectfn             = NULL;
 	exp->flags                = NF_CT_EXPECT_PERMANENT;
 	exp->helper               = NULL;
 
-	nf_conntrack_expect_related(exp);
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_related(exp);
+	nf_ct_expect_put(exp);
 
 	nf_ct_refresh(ct, *pskb, timeout * HZ);
 out:
@@ -104,9 +101,6 @@
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(NMBD_PORT),
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.mask.src.l3num		= 0xFFFF,
-	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-	.mask.dst.protonum	= 0xFF,
 	.max_expected		= 1,
 	.me			= THIS_MODULE,
 	.help			= help,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index d6d39e2..6f89b10 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -171,21 +171,29 @@
 {
 	struct nfattr *nest_helper;
 	const struct nf_conn_help *help = nfct_help(ct);
+	struct nf_conntrack_helper *helper;
 
-	if (!help || !help->helper)
+	if (!help)
 		return 0;
 
-	nest_helper = NFA_NEST(skb, CTA_HELP);
-	NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name);
+	rcu_read_lock();
+	helper = rcu_dereference(help->helper);
+	if (!helper)
+		goto out;
 
-	if (help->helper->to_nfattr)
-		help->helper->to_nfattr(skb, ct);
+	nest_helper = NFA_NEST(skb, CTA_HELP);
+	NFA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);
+
+	if (helper->to_nfattr)
+		helper->to_nfattr(skb, ct);
 
 	NFA_NEST_END(skb, nest_helper);
-
+out:
+	rcu_read_unlock();
 	return 0;
 
 nfattr_failure:
+	rcu_read_unlock();
 	return -1;
 }
 
@@ -420,7 +428,7 @@
 {
 	struct nf_conn *ct, *last;
 	struct nf_conntrack_tuple_hash *h;
-	struct list_head *i;
+	struct hlist_node *n;
 	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
 	u_int8_t l3proto = nfmsg->nfgen_family;
 
@@ -428,8 +436,8 @@
 	last = (struct nf_conn *)cb->args[1];
 	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
 restart:
-		list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
-			h = (struct nf_conntrack_tuple_hash *) i;
+		hlist_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]],
+				     hnode) {
 			if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
 				continue;
 			ct = nf_ct_tuplehash_to_ctrack(h);
@@ -681,7 +689,7 @@
 	if (err < 0)
 		return err;
 
-	h = nf_conntrack_find_get(&tuple, NULL);
+	h = nf_conntrack_find_get(&tuple);
 	if (!h)
 		return -ENOENT;
 
@@ -736,7 +744,7 @@
 	if (err < 0)
 		return err;
 
-	h = nf_conntrack_find_get(&tuple, NULL);
+	h = nf_conntrack_find_get(&tuple);
 	if (!h)
 		return -ENOENT;
 
@@ -842,31 +850,30 @@
 		if (help && help->helper) {
 			/* we had a helper before ... */
 			nf_ct_remove_expectations(ct);
-			help->helper = NULL;
+			rcu_assign_pointer(help->helper, NULL);
 		}
 
 		return 0;
 	}
 
-	if (!help) {
-		/* FIXME: we need to reallocate and rehash */
-		return -EBUSY;
-	}
-
 	helper = __nf_conntrack_helper_find_byname(helpname);
 	if (helper == NULL)
 		return -EINVAL;
 
-	if (help->helper == helper)
-		return 0;
+	if (help) {
+		if (help->helper == helper)
+			return 0;
+		if (help->helper)
+			return -EBUSY;
+		/* need to zero data of old helper */
+		memset(&help->help, 0, sizeof(help->help));
+	} else {
+		help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
+		if (help == NULL)
+			return -ENOMEM;
+	}
 
-	if (help->helper)
-		/* we had a helper before ... */
-		nf_ct_remove_expectations(ct);
-
-	/* need to zero data of old helper */
-	memset(&help->help, 0, sizeof(help->help));
-	help->helper = helper;
+	rcu_assign_pointer(help->helper, helper);
 
 	return 0;
 }
@@ -950,6 +957,7 @@
 	struct nf_conn *ct;
 	int err = -EINVAL;
 	struct nf_conn_help *help;
+	struct nf_conntrack_helper *helper;
 
 	ct = nf_conntrack_alloc(otuple, rtuple);
 	if (ct == NULL || IS_ERR(ct))
@@ -979,15 +987,23 @@
 		ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
 
-	help = nfct_help(ct);
-	if (help)
-		help->helper = nf_ct_helper_find_get(rtuple);
+	helper = nf_ct_helper_find_get(rtuple);
+	if (helper) {
+		help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
+		if (help == NULL) {
+			nf_ct_helper_put(helper);
+			err = -ENOMEM;
+			goto err;
+		}
+		/* not in hash table yet so not strictly necessary */
+		rcu_assign_pointer(help->helper, helper);
+	}
 
 	add_timer(&ct->timeout);
 	nf_conntrack_hash_insert(ct);
 
-	if (help && help->helper)
-		nf_ct_helper_put(help->helper);
+	if (helper)
+		nf_ct_helper_put(helper);
 
 	return 0;
 
@@ -1078,22 +1094,29 @@
 static inline int
 ctnetlink_exp_dump_mask(struct sk_buff *skb,
 			const struct nf_conntrack_tuple *tuple,
-			const struct nf_conntrack_tuple *mask)
+			const struct nf_conntrack_tuple_mask *mask)
 {
 	int ret;
 	struct nf_conntrack_l3proto *l3proto;
 	struct nf_conntrack_l4proto *l4proto;
-	struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+	struct nf_conntrack_tuple m;
+	struct nfattr *nest_parms;
+
+	memset(&m, 0xFF, sizeof(m));
+	m.src.u.all = mask->src.u.all;
+	memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
+
+	nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
 
 	l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
-	ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
+	ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
 	nf_ct_l3proto_put(l3proto);
 
 	if (unlikely(ret < 0))
 		goto nfattr_failure;
 
 	l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
-	ret = ctnetlink_dump_tuples_proto(skb, mask, l4proto);
+	ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
 	nf_ct_l4proto_put(l4proto);
 	if (unlikely(ret < 0))
 		goto nfattr_failure;
@@ -1212,32 +1235,52 @@
 	return NOTIFY_DONE;
 }
 #endif
+static int ctnetlink_exp_done(struct netlink_callback *cb)
+{
+	if (cb->args[1])
+		nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
+	return 0;
+}
 
 static int
 ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	struct nf_conntrack_expect *exp = NULL;
-	struct list_head *i;
-	u_int32_t *id = (u_int32_t *) &cb->args[0];
+	struct nf_conntrack_expect *exp, *last;
 	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+	struct hlist_node *n;
 	u_int8_t l3proto = nfmsg->nfgen_family;
 
 	read_lock_bh(&nf_conntrack_lock);
-	list_for_each_prev(i, &nf_conntrack_expect_list) {
-		exp = (struct nf_conntrack_expect *) i;
-		if (l3proto && exp->tuple.src.l3num != l3proto)
-			continue;
-		if (exp->id <= *id)
-			continue;
-		if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
-					    cb->nlh->nlmsg_seq,
-					    IPCTNL_MSG_EXP_NEW,
-					    1, exp) < 0)
-			goto out;
-		*id = exp->id;
+	last = (struct nf_conntrack_expect *)cb->args[1];
+	for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) {
+restart:
+		hlist_for_each_entry(exp, n, &nf_ct_expect_hash[cb->args[0]],
+				     hnode) {
+			if (l3proto && exp->tuple.src.l3num != l3proto)
+				continue;
+			if (cb->args[1]) {
+				if (exp != last)
+					continue;
+				cb->args[1] = 0;
+			}
+			if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
+						    cb->nlh->nlmsg_seq,
+						    IPCTNL_MSG_EXP_NEW,
+						    1, exp) < 0) {
+				atomic_inc(&exp->use);
+				cb->args[1] = (unsigned long)exp;
+				goto out;
+			}
+		}
+		if (cb->args[1]) {
+			cb->args[1] = 0;
+			goto restart;
+		}
 	}
 out:
 	read_unlock_bh(&nf_conntrack_lock);
+	if (last)
+		nf_ct_expect_put(last);
 
 	return skb->len;
 }
@@ -1264,7 +1307,7 @@
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		return netlink_dump_start(ctnl, skb, nlh,
 					  ctnetlink_exp_dump_table,
-					  ctnetlink_done);
+					  ctnetlink_exp_done);
 	}
 
 	if (cda[CTA_EXPECT_MASTER-1])
@@ -1275,14 +1318,14 @@
 	if (err < 0)
 		return err;
 
-	exp = nf_conntrack_expect_find_get(&tuple);
+	exp = nf_ct_expect_find_get(&tuple);
 	if (!exp)
 		return -ENOENT;
 
 	if (cda[CTA_EXPECT_ID-1]) {
 		__be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
 		if (exp->id != ntohl(id)) {
-			nf_conntrack_expect_put(exp);
+			nf_ct_expect_put(exp);
 			return -ENOENT;
 		}
 	}
@@ -1298,14 +1341,14 @@
 	if (err <= 0)
 		goto free;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
 
 free:
 	kfree_skb(skb2);
 out:
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 	return err;
 }
 
@@ -1313,11 +1356,13 @@
 ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
 		     struct nlmsghdr *nlh, struct nfattr *cda[])
 {
-	struct nf_conntrack_expect *exp, *tmp;
+	struct nf_conntrack_expect *exp;
 	struct nf_conntrack_tuple tuple;
 	struct nf_conntrack_helper *h;
 	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+	struct hlist_node *n, *next;
 	u_int8_t u3 = nfmsg->nfgen_family;
+	unsigned int i;
 	int err;
 
 	if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
@@ -1330,25 +1375,26 @@
 			return err;
 
 		/* bump usage count to 2 */
-		exp = nf_conntrack_expect_find_get(&tuple);
+		exp = nf_ct_expect_find_get(&tuple);
 		if (!exp)
 			return -ENOENT;
 
 		if (cda[CTA_EXPECT_ID-1]) {
 			__be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
 			if (exp->id != ntohl(id)) {
-				nf_conntrack_expect_put(exp);
+				nf_ct_expect_put(exp);
 				return -ENOENT;
 			}
 		}
 
 		/* after list removal, usage count == 1 */
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		/* have to put what we 'get' above.
 		 * after this line usage count == 0 */
-		nf_conntrack_expect_put(exp);
+		nf_ct_expect_put(exp);
 	} else if (cda[CTA_EXPECT_HELP_NAME-1]) {
 		char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]);
+		struct nf_conn_help *m_help;
 
 		/* delete all expectations for this helper */
 		write_lock_bh(&nf_conntrack_lock);
@@ -1357,24 +1403,30 @@
 			write_unlock_bh(&nf_conntrack_lock);
 			return -EINVAL;
 		}
-		list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
-					 list) {
-			struct nf_conn_help *m_help = nfct_help(exp->master);
-			if (m_help->helper == h
-			    && del_timer(&exp->timeout)) {
-				nf_ct_unlink_expect(exp);
-				nf_conntrack_expect_put(exp);
+		for (i = 0; i < nf_ct_expect_hsize; i++) {
+			hlist_for_each_entry_safe(exp, n, next,
+						  &nf_ct_expect_hash[i],
+						  hnode) {
+				m_help = nfct_help(exp->master);
+				if (m_help->helper == h
+				    && del_timer(&exp->timeout)) {
+					nf_ct_unlink_expect(exp);
+					nf_ct_expect_put(exp);
+				}
 			}
 		}
 		write_unlock_bh(&nf_conntrack_lock);
 	} else {
 		/* This basically means we have to flush everything*/
 		write_lock_bh(&nf_conntrack_lock);
-		list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
-					 list) {
-			if (del_timer(&exp->timeout)) {
-				nf_ct_unlink_expect(exp);
-				nf_conntrack_expect_put(exp);
+		for (i = 0; i < nf_ct_expect_hsize; i++) {
+			hlist_for_each_entry_safe(exp, n, next,
+						  &nf_ct_expect_hash[i],
+						  hnode) {
+				if (del_timer(&exp->timeout)) {
+					nf_ct_unlink_expect(exp);
+					nf_ct_expect_put(exp);
+				}
 			}
 		}
 		write_unlock_bh(&nf_conntrack_lock);
@@ -1410,7 +1462,7 @@
 		return err;
 
 	/* Look for master conntrack of this expectation */
-	h = nf_conntrack_find_get(&master_tuple, NULL);
+	h = nf_conntrack_find_get(&master_tuple);
 	if (!h)
 		return -ENOENT;
 	ct = nf_ct_tuplehash_to_ctrack(h);
@@ -1422,7 +1474,7 @@
 		goto out;
 	}
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (!exp) {
 		err = -ENOMEM;
 		goto out;
@@ -1433,10 +1485,11 @@
 	exp->master = ct;
 	exp->helper = NULL;
 	memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
-	memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
+	memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3));
+	exp->mask.src.u.all = mask.src.u.all;
 
-	err = nf_conntrack_expect_related(exp);
-	nf_conntrack_expect_put(exp);
+	err = nf_ct_expect_related(exp);
+	nf_ct_expect_put(exp);
 
 out:
 	nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
@@ -1466,7 +1519,7 @@
 		return err;
 
 	write_lock_bh(&nf_conntrack_lock);
-	exp = __nf_conntrack_expect_find(&tuple);
+	exp = __nf_ct_expect_find(&tuple);
 
 	if (!exp) {
 		write_unlock_bh(&nf_conntrack_lock);
@@ -1556,7 +1609,7 @@
 		goto err_unreg_exp_subsys;
 	}
 
-	ret = nf_conntrack_expect_register_notifier(&ctnl_notifier_exp);
+	ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp);
 	if (ret < 0) {
 		printk("ctnetlink_init: cannot expect register notifier.\n");
 		goto err_unreg_notifier;
@@ -1582,7 +1635,7 @@
 	printk("ctnetlink: unregistering from nfnetlink.\n");
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
-	nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
+	nf_ct_expect_unregister_notifier(&ctnl_notifier_exp);
 	nf_conntrack_unregister_notifier(&ctnl_notifier);
 #endif
 
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 115bcb5..b080419 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -65,7 +65,7 @@
 			     struct nf_conntrack_expect *exp) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
 
-#if 0
+#ifdef DEBUG
 /* PptpControlMessageType names */
 const char *pptp_msg_name[] = {
 	"UNKNOWN_MESSAGE",
@@ -86,9 +86,6 @@
 	"SET_LINK_INFO"
 };
 EXPORT_SYMBOL(pptp_msg_name);
-#define DEBUGP(format, args...)	printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
-#else
-#define DEBUGP(format, args...)
 #endif
 
 #define SECS *HZ
@@ -102,7 +99,7 @@
 			 struct nf_conntrack_expect *exp)
 {
 	typeof(nf_nat_pptp_hook_expectfn) nf_nat_pptp_expectfn;
-	DEBUGP("increasing timeouts\n");
+	pr_debug("increasing timeouts\n");
 
 	/* increase timeout of GRE data channel conntrack entry */
 	ct->proto.gre.timeout	     = PPTP_GRE_TIMEOUT;
@@ -121,17 +118,17 @@
 
 		/* obviously this tuple inversion only works until you do NAT */
 		nf_ct_invert_tuplepr(&inv_t, &exp->tuple);
-		DEBUGP("trying to unexpect other dir: ");
+		pr_debug("trying to unexpect other dir: ");
 		NF_CT_DUMP_TUPLE(&inv_t);
 
-		exp_other = nf_conntrack_expect_find_get(&inv_t);
+		exp_other = nf_ct_expect_find_get(&inv_t);
 		if (exp_other) {
 			/* delete other expectation.  */
-			DEBUGP("found\n");
-			nf_conntrack_unexpect_related(exp_other);
-			nf_conntrack_expect_put(exp_other);
+			pr_debug("found\n");
+			nf_ct_unexpect_related(exp_other);
+			nf_ct_expect_put(exp_other);
 		} else {
-			DEBUGP("not found\n");
+			pr_debug("not found\n");
 		}
 	}
 	rcu_read_unlock();
@@ -143,13 +140,13 @@
 	struct nf_conntrack_expect *exp;
 	struct nf_conn *sibling;
 
-	DEBUGP("trying to timeout ct or exp for tuple ");
+	pr_debug("trying to timeout ct or exp for tuple ");
 	NF_CT_DUMP_TUPLE(t);
 
-	h = nf_conntrack_find_get(t, NULL);
+	h = nf_conntrack_find_get(t);
 	if (h)  {
 		sibling = nf_ct_tuplehash_to_ctrack(h);
-		DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
+		pr_debug("setting timeout of conntrack %p to 0\n", sibling);
 		sibling->proto.gre.timeout	  = 0;
 		sibling->proto.gre.stream_timeout = 0;
 		if (del_timer(&sibling->timeout))
@@ -157,11 +154,11 @@
 		nf_ct_put(sibling);
 		return 1;
 	} else {
-		exp = nf_conntrack_expect_find_get(t);
+		exp = nf_ct_expect_find_get(t);
 		if (exp) {
-			DEBUGP("unexpect_related of expect %p\n", exp);
-			nf_conntrack_unexpect_related(exp);
-			nf_conntrack_expect_put(exp);
+			pr_debug("unexpect_related of expect %p\n", exp);
+			nf_ct_unexpect_related(exp);
+			nf_ct_expect_put(exp);
 			return 1;
 		}
 	}
@@ -182,7 +179,7 @@
 	t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
 	t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
 	if (!destroy_sibling_or_exp(&t))
-		DEBUGP("failed to timeout original pns->pac ct/exp\n");
+		pr_debug("failed to timeout original pns->pac ct/exp\n");
 
 	/* try reply (pac->pns) tuple */
 	memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
@@ -190,7 +187,7 @@
 	t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id;
 	t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id;
 	if (!destroy_sibling_or_exp(&t))
-		DEBUGP("failed to timeout reply pac->pns ct/exp\n");
+		pr_debug("failed to timeout reply pac->pns ct/exp\n");
 }
 
 /* expect GRE connections (PNS->PAC and PAC->PNS direction) */
@@ -201,36 +198,36 @@
 	int ret = 1;
 	typeof(nf_nat_pptp_hook_exp_gre) nf_nat_pptp_exp_gre;
 
-	exp_orig = nf_conntrack_expect_alloc(ct);
+	exp_orig = nf_ct_expect_alloc(ct);
 	if (exp_orig == NULL)
 		goto out;
 
-	exp_reply = nf_conntrack_expect_alloc(ct);
+	exp_reply = nf_ct_expect_alloc(ct);
 	if (exp_reply == NULL)
 		goto out_put_orig;
 
 	/* original direction, PNS->PAC */
 	dir = IP_CT_DIR_ORIGINAL;
-	nf_conntrack_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
-				 &ct->tuplehash[dir].tuple.src.u3,
-				 &ct->tuplehash[dir].tuple.dst.u3,
-				 IPPROTO_GRE, &peer_callid, &callid);
+	nf_ct_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
+			  &ct->tuplehash[dir].tuple.src.u3,
+			  &ct->tuplehash[dir].tuple.dst.u3,
+			  IPPROTO_GRE, &peer_callid, &callid);
 	exp_orig->expectfn = pptp_expectfn;
 
 	/* reply direction, PAC->PNS */
 	dir = IP_CT_DIR_REPLY;
-	nf_conntrack_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
-				 &ct->tuplehash[dir].tuple.src.u3,
-				 &ct->tuplehash[dir].tuple.dst.u3,
-				 IPPROTO_GRE, &callid, &peer_callid);
+	nf_ct_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
+			  &ct->tuplehash[dir].tuple.src.u3,
+			  &ct->tuplehash[dir].tuple.dst.u3,
+			  IPPROTO_GRE, &callid, &peer_callid);
 	exp_reply->expectfn = pptp_expectfn;
 
 	nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre);
 	if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK)
 		nf_nat_pptp_exp_gre(exp_orig, exp_reply);
-	if (nf_conntrack_expect_related(exp_orig) != 0)
+	if (nf_ct_expect_related(exp_orig) != 0)
 		goto out_put_both;
-	if (nf_conntrack_expect_related(exp_reply) != 0)
+	if (nf_ct_expect_related(exp_reply) != 0)
 		goto out_unexpect_orig;
 
 	/* Add GRE keymap entries */
@@ -243,16 +240,16 @@
 	ret = 0;
 
 out_put_both:
-	nf_conntrack_expect_put(exp_reply);
+	nf_ct_expect_put(exp_reply);
 out_put_orig:
-	nf_conntrack_expect_put(exp_orig);
+	nf_ct_expect_put(exp_orig);
 out:
 	return ret;
 
 out_unexpect_both:
-	nf_conntrack_unexpect_related(exp_reply);
+	nf_ct_unexpect_related(exp_reply);
 out_unexpect_orig:
-	nf_conntrack_unexpect_related(exp_orig);
+	nf_ct_unexpect_related(exp_orig);
 	goto out_put_both;
 }
 
@@ -270,7 +267,7 @@
 	typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound;
 
 	msg = ntohs(ctlh->messageType);
-	DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
+	pr_debug("inbound control message %s\n", pptp_msg_name[msg]);
 
 	switch (msg) {
 	case PPTP_START_SESSION_REPLY:
@@ -305,8 +302,8 @@
 		pcid = pptpReq->ocack.peersCallID;
 		if (info->pns_call_id != pcid)
 			goto invalid;
-		DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
-			ntohs(cid), ntohs(pcid));
+		pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
+			 ntohs(cid), ntohs(pcid));
 
 		if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) {
 			info->cstate = PPTP_CALL_OUT_CONF;
@@ -322,7 +319,7 @@
 			goto invalid;
 
 		cid = pptpReq->icreq.callID;
-		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+		pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
 		info->cstate = PPTP_CALL_IN_REQ;
 		info->pac_call_id = cid;
 		break;
@@ -341,7 +338,7 @@
 		if (info->pns_call_id != pcid)
 			goto invalid;
 
-		DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
+		pr_debug("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
 		info->cstate = PPTP_CALL_IN_CONF;
 
 		/* we expect a GRE connection from PAC to PNS */
@@ -351,7 +348,7 @@
 	case PPTP_CALL_DISCONNECT_NOTIFY:
 		/* server confirms disconnect */
 		cid = pptpReq->disc.callID;
-		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+		pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
 		info->cstate = PPTP_CALL_NONE;
 
 		/* untrack this call id, unexpect GRE packets */
@@ -374,11 +371,11 @@
 	return NF_ACCEPT;
 
 invalid:
-	DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
-	       "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
-	       msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
-	       msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,
-	       ntohs(info->pns_call_id), ntohs(info->pac_call_id));
+	pr_debug("invalid %s: type=%d cid=%u pcid=%u "
+		 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
+		 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
+		 msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,
+		 ntohs(info->pns_call_id), ntohs(info->pac_call_id));
 	return NF_ACCEPT;
 }
 
@@ -396,7 +393,7 @@
 	typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound;
 
 	msg = ntohs(ctlh->messageType);
-	DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
+	pr_debug("outbound control message %s\n", pptp_msg_name[msg]);
 
 	switch (msg) {
 	case PPTP_START_SESSION_REQUEST:
@@ -418,7 +415,7 @@
 		info->cstate = PPTP_CALL_OUT_REQ;
 		/* track PNS call id */
 		cid = pptpReq->ocreq.callID;
-		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+		pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
 		info->pns_call_id = cid;
 		break;
 
@@ -432,8 +429,8 @@
 		pcid = pptpReq->icack.peersCallID;
 		if (info->pac_call_id != pcid)
 			goto invalid;
-		DEBUGP("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
-		       ntohs(cid), ntohs(pcid));
+		pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
+			 ntohs(cid), ntohs(pcid));
 
 		if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) {
 			/* part two of the three-way handshake */
@@ -469,11 +466,11 @@
 	return NF_ACCEPT;
 
 invalid:
-	DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
-	       "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
-	       msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
-	       msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,
-	       ntohs(info->pns_call_id), ntohs(info->pac_call_id));
+	pr_debug("invalid %s: type=%d cid=%u pcid=%u "
+		 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
+		 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
+		 msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,
+		 ntohs(info->pns_call_id), ntohs(info->pac_call_id));
 	return NF_ACCEPT;
 }
 
@@ -524,7 +521,7 @@
 
 	pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
 	if (!pptph) {
-		DEBUGP("no full PPTP header, can't track\n");
+		pr_debug("no full PPTP header, can't track\n");
 		return NF_ACCEPT;
 	}
 	nexthdr_off += sizeof(_pptph);
@@ -533,7 +530,7 @@
 	/* if it's not a control message we can't do anything with it */
 	if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
 	    ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
-		DEBUGP("not a control packet\n");
+		pr_debug("not a control packet\n");
 		return NF_ACCEPT;
 	}
 
@@ -569,8 +566,8 @@
 		/* server -> client (PAC -> PNS) */
 		ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
 				       ctinfo);
-	DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
-		oldsstate, info->sstate, oldcstate, info->cstate);
+	pr_debug("sstate: %d->%d, cstate: %d->%d\n",
+		 oldsstate, info->sstate, oldcstate, info->cstate);
 	spin_unlock_bh(&nf_pptp_lock);
 
 	return ret;
@@ -585,9 +582,6 @@
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.tcp.port	= __constant_htons(PPTP_CONTROL_PORT),
 	.tuple.dst.protonum	= IPPROTO_TCP,
-	.mask.src.l3num		= 0xffff,
-	.mask.src.u.tcp.port	= __constant_htons(0xffff),
-	.mask.dst.protonum	= 0xff,
 	.help			= conntrack_pptp_help,
 	.destroy		= pptp_destroy_siblings,
 };
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 6faf1be..d8b5018 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -98,7 +98,7 @@
 #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
 {
 	.l3proto		= PF_UNSPEC,
 	.l4proto		= 0,
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 5434472..bdbead8 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -40,12 +40,6 @@
 #define GRE_TIMEOUT		(30 * HZ)
 #define GRE_STREAM_TIMEOUT	(180 * HZ)
 
-#if 0
-#define DEBUGP(format, args...)	printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
 static DEFINE_RWLOCK(nf_ct_gre_lock);
 static LIST_HEAD(gre_keymap_list);
 
@@ -87,7 +81,7 @@
 	}
 	read_unlock_bh(&nf_ct_gre_lock);
 
-	DEBUGP("lookup src key 0x%x for ", key);
+	pr_debug("lookup src key 0x%x for ", key);
 	NF_CT_DUMP_TUPLE(t);
 
 	return key;
@@ -100,7 +94,6 @@
 	struct nf_conn_help *help = nfct_help(ct);
 	struct nf_ct_gre_keymap **kmp, *km;
 
-	BUG_ON(strcmp(help->helper->name, "pptp"));
 	kmp = &help->help.ct_pptp_info.keymap[dir];
 	if (*kmp) {
 		/* check whether it's a retransmission */
@@ -108,8 +101,8 @@
 			if (gre_key_cmpfn(km, t) && km == *kmp)
 				return 0;
 		}
-		DEBUGP("trying to override keymap_%s for ct %p\n",
-			dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
+		pr_debug("trying to override keymap_%s for ct %p\n",
+			 dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
 		return -EEXIST;
 	}
 
@@ -119,7 +112,7 @@
 	memcpy(&km->tuple, t, sizeof(*t));
 	*kmp = km;
 
-	DEBUGP("adding new entry %p: ", km);
+	pr_debug("adding new entry %p: ", km);
 	NF_CT_DUMP_TUPLE(&km->tuple);
 
 	write_lock_bh(&nf_ct_gre_lock);
@@ -136,14 +129,13 @@
 	struct nf_conn_help *help = nfct_help(ct);
 	enum ip_conntrack_dir dir;
 
-	DEBUGP("entering for ct %p\n", ct);
-	BUG_ON(strcmp(help->helper->name, "pptp"));
+	pr_debug("entering for ct %p\n", ct);
 
 	write_lock_bh(&nf_ct_gre_lock);
 	for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
 		if (help->help.ct_pptp_info.keymap[dir]) {
-			DEBUGP("removing %p from list\n",
-				help->help.ct_pptp_info.keymap[dir]);
+			pr_debug("removing %p from list\n",
+				 help->help.ct_pptp_info.keymap[dir]);
 			list_del(&help->help.ct_pptp_info.keymap[dir]->list);
 			kfree(help->help.ct_pptp_info.keymap[dir]);
 			help->help.ct_pptp_info.keymap[dir] = NULL;
@@ -188,7 +180,7 @@
 		return 1;
 
 	if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
-		DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
+		pr_debug("GRE_VERSION_PPTP but unknown proto\n");
 		return 0;
 	}
 
@@ -244,7 +236,7 @@
 static int gre_new(struct nf_conn *ct, const struct sk_buff *skb,
 		   unsigned int dataoff)
 {
-	DEBUGP(": ");
+	pr_debug(": ");
 	NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 
 	/* initialize to sane value.  Ideally a conntrack helper
@@ -260,16 +252,16 @@
 static void gre_destroy(struct nf_conn *ct)
 {
 	struct nf_conn *master = ct->master;
-	DEBUGP(" entering\n");
+	pr_debug(" entering\n");
 
 	if (!master)
-		DEBUGP("no master !?!\n");
+		pr_debug("no master !?!\n");
 	else
 		nf_ct_gre_keymap_destroy(master);
 }
 
 /* protocol helper struct */
-static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = {
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
 	.l3proto	 = AF_INET,
 	.l4proto	 = IPPROTO_GRE,
 	.name		 = "gre",
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 0d3254b..04192ac 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -25,12 +25,6 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
-#if 0
-#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Protects conntrack->proto.sctp */
 static DEFINE_RWLOCK(sctp_lock);
 
@@ -151,9 +145,6 @@
 {
 	sctp_sctphdr_t _hdr, *hp;
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	/* Actually only need first 8 bytes. */
 	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
 	if (hp == NULL)
@@ -167,9 +158,6 @@
 static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
 			     const struct nf_conntrack_tuple *orig)
 {
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	tuple->src.u.sctp.port = orig->dst.u.sctp.port;
 	tuple->dst.u.sctp.port = orig->src.u.sctp.port;
 	return 1;
@@ -179,9 +167,6 @@
 static int sctp_print_tuple(struct seq_file *s,
 			    const struct nf_conntrack_tuple *tuple)
 {
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	return seq_printf(s, "sport=%hu dport=%hu ",
 			  ntohs(tuple->src.u.sctp.port),
 			  ntohs(tuple->dst.u.sctp.port));
@@ -193,9 +178,6 @@
 {
 	enum sctp_conntrack state;
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	read_lock_bh(&sctp_lock);
 	state = conntrack->proto.sctp.state;
 	read_unlock_bh(&sctp_lock);
@@ -219,13 +201,10 @@
 	sctp_chunkhdr_t _sch, *sch;
 	int flag;
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	flag = 0;
 
 	for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
-		DEBUGP("Chunk Num: %d  Type: %d\n", count, sch->type);
+		pr_debug("Chunk Num: %d  Type: %d\n", count, sch->type);
 
 		if (sch->type == SCTP_CID_INIT
 			|| sch->type == SCTP_CID_INIT_ACK
@@ -242,7 +221,7 @@
 			|| sch->type == SCTP_CID_COOKIE_ECHO
 			|| flag)
 		      && count !=0) || !sch->length) {
-			DEBUGP("Basic checks failed\n");
+			pr_debug("Basic checks failed\n");
 			return 1;
 		}
 
@@ -251,7 +230,7 @@
 		}
 	}
 
-	DEBUGP("Basic checks passed\n");
+	pr_debug("Basic checks passed\n");
 	return count == 0;
 }
 
@@ -261,50 +240,47 @@
 {
 	int i;
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
-	DEBUGP("Chunk type: %d\n", chunk_type);
+	pr_debug("Chunk type: %d\n", chunk_type);
 
 	switch (chunk_type) {
 		case SCTP_CID_INIT:
-			DEBUGP("SCTP_CID_INIT\n");
+			pr_debug("SCTP_CID_INIT\n");
 			i = 0; break;
 		case SCTP_CID_INIT_ACK:
-			DEBUGP("SCTP_CID_INIT_ACK\n");
+			pr_debug("SCTP_CID_INIT_ACK\n");
 			i = 1; break;
 		case SCTP_CID_ABORT:
-			DEBUGP("SCTP_CID_ABORT\n");
+			pr_debug("SCTP_CID_ABORT\n");
 			i = 2; break;
 		case SCTP_CID_SHUTDOWN:
-			DEBUGP("SCTP_CID_SHUTDOWN\n");
+			pr_debug("SCTP_CID_SHUTDOWN\n");
 			i = 3; break;
 		case SCTP_CID_SHUTDOWN_ACK:
-			DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
+			pr_debug("SCTP_CID_SHUTDOWN_ACK\n");
 			i = 4; break;
 		case SCTP_CID_ERROR:
-			DEBUGP("SCTP_CID_ERROR\n");
+			pr_debug("SCTP_CID_ERROR\n");
 			i = 5; break;
 		case SCTP_CID_COOKIE_ECHO:
-			DEBUGP("SCTP_CID_COOKIE_ECHO\n");
+			pr_debug("SCTP_CID_COOKIE_ECHO\n");
 			i = 6; break;
 		case SCTP_CID_COOKIE_ACK:
-			DEBUGP("SCTP_CID_COOKIE_ACK\n");
+			pr_debug("SCTP_CID_COOKIE_ACK\n");
 			i = 7; break;
 		case SCTP_CID_SHUTDOWN_COMPLETE:
-			DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
+			pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n");
 			i = 8; break;
 		default:
 			/* Other chunks like DATA, SACK, HEARTBEAT and
 			its ACK do not cause a change in state */
-			DEBUGP("Unknown chunk type, Will stay in %s\n",
-						sctp_conntrack_names[cur_state]);
+			pr_debug("Unknown chunk type, Will stay in %s\n",
+				 sctp_conntrack_names[cur_state]);
 			return cur_state;
 	}
 
-	DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n",
-			dir, sctp_conntrack_names[cur_state], chunk_type,
-			sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
+	pr_debug("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n",
+		 dir, sctp_conntrack_names[cur_state], chunk_type,
+		 sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
 
 	return sctp_conntracks[dir][i][cur_state];
 }
@@ -323,9 +299,6 @@
 	u_int32_t offset, count;
 	char map[256 / sizeof (char)] = {0};
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
 	if (sh == NULL)
 		return -1;
@@ -340,7 +313,7 @@
 		&& !test_bit(SCTP_CID_ABORT, (void *)map)
 		&& !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
 		&& (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
-		DEBUGP("Verification tag check failed\n");
+		pr_debug("Verification tag check failed\n");
 		return -1;
 	}
 
@@ -385,8 +358,9 @@
 
 		/* Invalid */
 		if (newconntrack == SCTP_CONNTRACK_MAX) {
-			DEBUGP("nf_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
-			       CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
+			pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
+				 "conntrack=%u\n",
+				 CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
 			write_unlock_bh(&sctp_lock);
 			return -1;
 		}
@@ -402,8 +376,8 @@
 					write_unlock_bh(&sctp_lock);
 					return -1;
 			}
-			DEBUGP("Setting vtag %x for dir %d\n",
-					ih->init_tag, !CTINFO2DIR(ctinfo));
+			pr_debug("Setting vtag %x for dir %d\n",
+				 ih->init_tag, !CTINFO2DIR(ctinfo));
 			conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
 		}
 
@@ -418,7 +392,7 @@
 	if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
 		&& CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
 		&& newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
-		DEBUGP("Setting assured bit\n");
+		pr_debug("Setting assured bit\n");
 		set_bit(IPS_ASSURED_BIT, &conntrack->status);
 		nf_conntrack_event_cache(IPCT_STATUS, skb);
 	}
@@ -436,9 +410,6 @@
 	u_int32_t offset, count;
 	char map[256 / sizeof (char)] = {0};
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
 	if (sh == NULL)
 		return 0;
@@ -460,8 +431,9 @@
 					 SCTP_CONNTRACK_NONE, sch->type);
 
 		/* Invalid: delete conntrack */
-		if (newconntrack == SCTP_CONNTRACK_MAX) {
-			DEBUGP("nf_conntrack_sctp: invalid new deleting.\n");
+		if (newconntrack == SCTP_CONNTRACK_NONE ||
+		    newconntrack == SCTP_CONNTRACK_MAX) {
+			pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
 			return 0;
 		}
 
@@ -475,8 +447,8 @@
 				if (ih == NULL)
 					return 0;
 
-				DEBUGP("Setting vtag %x for new conn\n",
-					ih->init_tag);
+				pr_debug("Setting vtag %x for new conn\n",
+					 ih->init_tag);
 
 				conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
 								ih->init_tag;
@@ -488,8 +460,8 @@
 		/* If it is a shutdown ack OOTB packet, we expect a return
 		   shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
 		else {
-			DEBUGP("Setting vtag %x for new conn OOTB\n",
-				sh->vtag);
+			pr_debug("Setting vtag %x for new conn OOTB\n",
+				 sh->vtag);
 			conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
 		}
 
@@ -629,7 +601,7 @@
 #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
 	.l3proto		= PF_INET,
 	.l4proto 		= IPPROTO_SCTP,
 	.name 			= "sctp",
@@ -650,7 +622,7 @@
 #endif
 };
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = {
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
 	.l3proto		= PF_INET6,
 	.l4proto 		= IPPROTO_SCTP,
 	.name 			= "sctp",
@@ -688,8 +660,6 @@
  cleanup_sctp4:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
  out:
-	DEBUGP("SCTP conntrack module loading %s\n",
-					ret ? "failed": "succeeded");
 	return ret;
 }
 
@@ -697,7 +667,6 @@
 {
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
-	DEBUGP("SCTP conntrack module unloaded\n");
 }
 
 module_init(nf_conntrack_proto_sctp_init);
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index ccdd5d2..87ad3cc 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -26,13 +26,6 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
-#if 0
-#define DEBUGP printk
-#define DEBUGP_VARS
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Protects conntrack->proto.tcp */
 static DEFINE_RWLOCK(tcp_lock);
 
@@ -496,7 +489,8 @@
 	}
 }
 
-static int tcp_in_window(struct ip_ct_tcp *state,
+static int tcp_in_window(struct nf_conn *ct,
+			 struct ip_ct_tcp *state,
 			 enum ip_conntrack_dir dir,
 			 unsigned int index,
 			 const struct sk_buff *skb,
@@ -506,6 +500,7 @@
 {
 	struct ip_ct_tcp_state *sender = &state->seen[dir];
 	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
+	struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
 	__u32 seq, ack, sack, end, win, swin;
 	int res;
 
@@ -520,18 +515,17 @@
 	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
 		tcp_sack(skb, dataoff, tcph, &sack);
 
-	DEBUGP("tcp_in_window: START\n");
-	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
-	       "seq=%u ack=%u sack=%u win=%u end=%u\n",
-		NIPQUAD(iph->saddr), ntohs(tcph->source),
-		NIPQUAD(iph->daddr), ntohs(tcph->dest),
-		seq, ack, sack, win, end);
-	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
-	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
-		receiver->td_scale);
+	pr_debug("tcp_in_window: START\n");
+	pr_debug("tcp_in_window: ");
+	NF_CT_DUMP_TUPLE(tuple);
+	pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n",
+		 seq, ack, sack, win, end);
+	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		 sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 sender->td_scale,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		 receiver->td_scale);
 
 	if (sender->td_end == 0) {
 		/*
@@ -609,23 +603,22 @@
 		 */
 		seq = end = sender->td_end;
 
-	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
-	       "seq=%u ack=%u sack =%u win=%u end=%u\n",
-		NIPQUAD(iph->saddr), ntohs(tcph->source),
-		NIPQUAD(iph->daddr), ntohs(tcph->dest),
-		seq, ack, sack, win, end);
-	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
-	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
-		receiver->td_scale);
+	pr_debug("tcp_in_window: ");
+	NF_CT_DUMP_TUPLE(tuple);
+	pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n",
+		 seq, ack, sack, win, end);
+	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		 sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 sender->td_scale,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		 receiver->td_scale);
 
-	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
-		before(seq, sender->td_maxend + 1),
-		after(end, sender->td_end - receiver->td_maxwin - 1),
-		before(sack, receiver->td_end + 1),
-		after(ack, receiver->td_end - MAXACKWINDOW(sender)));
+	pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
+		 before(seq, sender->td_maxend + 1),
+		 after(end, sender->td_end - receiver->td_maxwin - 1),
+		 before(sack, receiver->td_end + 1),
+		 after(ack, receiver->td_end - MAXACKWINDOW(sender)));
 
 	if (before(seq, sender->td_maxend + 1) &&
 	    after(end, sender->td_end - receiver->td_maxwin - 1) &&
@@ -694,10 +687,10 @@
 			: "SEQ is over the upper bound (over the window of the receiver)");
 	}
 
-	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
-	       "receiver end=%u maxend=%u maxwin=%u\n",
-		res, sender->td_end, sender->td_maxend, sender->td_maxwin,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
+	pr_debug("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
+		 "receiver end=%u maxend=%u maxwin=%u\n",
+		 res, sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
 
 	return res;
 }
@@ -711,11 +704,9 @@
 			     int dir)
 {
 	struct tcphdr *tcph = (void *)skb->data + dataoff;
-	__u32 end;
-#ifdef DEBUGP_VARS
 	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir];
 	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir];
-#endif
+	__u32 end;
 
 	end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph);
 
@@ -727,12 +718,12 @@
 		conntrack->proto.tcp.seen[dir].td_end = end;
 	conntrack->proto.tcp.last_end = end;
 	write_unlock_bh(&tcp_lock);
-	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
-	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
-		receiver->td_scale);
+	pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
+		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		 sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 sender->td_scale,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		 receiver->td_scale);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update);
 #endif
@@ -823,6 +814,7 @@
 		      int pf,
 		      unsigned int hooknum)
 {
+	struct nf_conntrack_tuple *tuple;
 	enum tcp_conntrack new_state, old_state;
 	enum ip_conntrack_dir dir;
 	struct tcphdr *th, _tcph;
@@ -837,6 +829,7 @@
 	dir = CTINFO2DIR(ctinfo);
 	index = get_conntrack_index(th);
 	new_state = tcp_conntracks[dir][index][old_state];
+	tuple = &conntrack->tuplehash[dir].tuple;
 
 	switch (new_state) {
 	case TCP_CONNTRACK_IGNORE:
@@ -880,9 +873,8 @@
 		return NF_ACCEPT;
 	case TCP_CONNTRACK_MAX:
 		/* Invalid packet */
-		DEBUGP("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
-		       dir, get_conntrack_index(th),
-		       old_state);
+		pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
+			 dir, get_conntrack_index(th), old_state);
 		write_unlock_bh(&tcp_lock);
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -933,7 +925,7 @@
 		break;
 	}
 
-	if (!tcp_in_window(&conntrack->proto.tcp, dir, index,
+	if (!tcp_in_window(conntrack, &conntrack->proto.tcp, dir, index,
 			   skb, dataoff, th, pf)) {
 		write_unlock_bh(&tcp_lock);
 		return -NF_ACCEPT;
@@ -942,13 +934,12 @@
 	/* From now on we have got in-window packets */
 	conntrack->proto.tcp.last_index = index;
 
-	DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
-	       "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
-		NIPQUAD(iph->saddr), ntohs(th->source),
-		NIPQUAD(iph->daddr), ntohs(th->dest),
-		(th->syn ? 1 : 0), (th->ack ? 1 : 0),
-		(th->fin ? 1 : 0), (th->rst ? 1 : 0),
-		old_state, new_state);
+	pr_debug("tcp_conntracks: ");
+	NF_CT_DUMP_TUPLE(tuple);
+	pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
+		 (th->syn ? 1 : 0), (th->ack ? 1 : 0),
+		 (th->fin ? 1 : 0), (th->rst ? 1 : 0),
+		 old_state, new_state);
 
 	conntrack->proto.tcp.state = new_state;
 	if (old_state != new_state
@@ -997,10 +988,8 @@
 {
 	enum tcp_conntrack new_state;
 	struct tcphdr *th, _tcph;
-#ifdef DEBUGP_VARS
 	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
 	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1];
-#endif
 
 	th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
 	BUG_ON(th == NULL);
@@ -1012,7 +1001,7 @@
 
 	/* Invalid: delete conntrack */
 	if (new_state >= TCP_CONNTRACK_MAX) {
-		DEBUGP("nf_ct_tcp: invalid new deleting.\n");
+		pr_debug("nf_ct_tcp: invalid new deleting.\n");
 		return 0;
 	}
 
@@ -1065,12 +1054,12 @@
 	conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
 	conntrack->proto.tcp.last_index = TCP_NONE_SET;
 
-	DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
-	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
-		receiver->td_scale);
+	pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
+		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		 sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 sender->td_scale,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		 receiver->td_scale);
 	return 1;
 }
 
@@ -1383,7 +1372,7 @@
 #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly =
 {
 	.l3proto		= PF_INET,
 	.l4proto 		= IPPROTO_TCP,
@@ -1412,7 +1401,7 @@
 };
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4);
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly =
 {
 	.l3proto		= PF_INET6,
 	.l4proto 		= IPPROTO_TCP,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 3620ecc..13d94a0 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -191,7 +191,7 @@
 #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
 {
 	.l3proto		= PF_INET,
 	.l4proto		= IPPROTO_UDP,
@@ -218,7 +218,7 @@
 };
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
 
-struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
 {
 	.l3proto		= PF_INET6,
 	.l4proto		= IPPROTO_UDP,
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
new file mode 100644
index 0000000..93e747b
--- /dev/null
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -0,0 +1,266 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/udp.h>
+#include <linux/seq_file.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+
+static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
+static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
+
+static int udplite_pkt_to_tuple(const struct sk_buff *skb,
+				unsigned int dataoff,
+				struct nf_conntrack_tuple *tuple)
+{
+	struct udphdr _hdr, *hp;
+
+	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL)
+		return 0;
+
+	tuple->src.u.udp.port = hp->source;
+	tuple->dst.u.udp.port = hp->dest;
+	return 1;
+}
+
+static int udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
+				const struct nf_conntrack_tuple *orig)
+{
+	tuple->src.u.udp.port = orig->dst.u.udp.port;
+	tuple->dst.u.udp.port = orig->src.u.udp.port;
+	return 1;
+}
+
+/* Print out the per-protocol part of the tuple. */
+static int udplite_print_tuple(struct seq_file *s,
+			       const struct nf_conntrack_tuple *tuple)
+{
+	return seq_printf(s, "sport=%hu dport=%hu ",
+			  ntohs(tuple->src.u.udp.port),
+			  ntohs(tuple->dst.u.udp.port));
+}
+
+/* Print out the private part of the conntrack. */
+static int udplite_print_conntrack(struct seq_file *s,
+				   const struct nf_conn *conntrack)
+{
+	return 0;
+}
+
+/* Returns verdict for packet, and may modify conntracktype */
+static int udplite_packet(struct nf_conn *conntrack,
+			  const struct sk_buff *skb,
+			  unsigned int dataoff,
+			  enum ip_conntrack_info ctinfo,
+			  int pf,
+			  unsigned int hooknum)
+{
+	/* If we've seen traffic both ways, this is some kind of UDP
+	   stream.  Extend timeout. */
+	if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+		nf_ct_refresh_acct(conntrack, ctinfo, skb,
+				   nf_ct_udplite_timeout_stream);
+		/* Also, more likely to be important, and not a probe */
+		if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status))
+			nf_conntrack_event_cache(IPCT_STATUS, skb);
+	} else
+		nf_ct_refresh_acct(conntrack, ctinfo, skb,
+				   nf_ct_udplite_timeout);
+
+	return NF_ACCEPT;
+}
+
+/* Called when a new connection for this protocol found. */
+static int udplite_new(struct nf_conn *conntrack, const struct sk_buff *skb,
+		       unsigned int dataoff)
+{
+	return 1;
+}
+
+static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
+			 enum ip_conntrack_info *ctinfo,
+			 int pf,
+			 unsigned int hooknum)
+{
+	unsigned int udplen = skb->len - dataoff;
+	struct udphdr _hdr, *hdr;
+	unsigned int cscov;
+
+	/* Header is too small? */
+	hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+	if (hdr == NULL) {
+		if (LOG_INVALID(IPPROTO_UDPLITE))
+			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+				      "nf_ct_udplite: short packet ");
+		return -NF_ACCEPT;
+	}
+
+	cscov = ntohs(hdr->len);
+	if (cscov == 0)
+		cscov = udplen;
+	else if (cscov < sizeof(*hdr) || cscov > udplen) {
+		if (LOG_INVALID(IPPROTO_UDPLITE))
+			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+				"nf_ct_udplite: invalid checksum coverage ");
+		return -NF_ACCEPT;
+	}
+
+	/* UDPLITE mandates checksums */
+	if (!hdr->check) {
+		if (LOG_INVALID(IPPROTO_UDPLITE))
+			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+				      "nf_ct_udplite: checksum missing ");
+		return -NF_ACCEPT;
+	}
+
+	/* Checksum invalid? Ignore. */
+	if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) &&
+	    ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
+	     (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))) {
+		if (pf == PF_INET) {
+			struct iphdr *iph = ip_hdr(skb);
+
+			skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+						       udplen, IPPROTO_UDPLITE, 0);
+		} else {
+			struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+			__wsum hsum = skb_checksum(skb, 0, dataoff, 0);
+
+			skb->csum = ~csum_unfold(
+				csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
+						udplen, IPPROTO_UDPLITE,
+						csum_sub(0, hsum)));
+		}
+
+		skb->ip_summed = CHECKSUM_NONE;
+		if (__skb_checksum_complete_head(skb, dataoff + cscov)) {
+			if (LOG_INVALID(IPPROTO_UDPLITE))
+				nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+					      "nf_ct_udplite: bad UDPLite "
+					      "checksum ");
+			return -NF_ACCEPT;
+		}
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+
+	return NF_ACCEPT;
+}
+
+#ifdef CONFIG_SYSCTL
+static unsigned int udplite_sysctl_table_users;
+static struct ctl_table_header *udplite_sysctl_header;
+static struct ctl_table udplite_sysctl_table[] = {
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nf_conntrack_udplite_timeout",
+		.data		= &nf_ct_udplite_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nf_conntrack_udplite_timeout_stream",
+		.data		= &nf_ct_udplite_timeout_stream,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_SYSCTL */
+
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
+{
+	.l3proto		= PF_INET,
+	.l4proto		= IPPROTO_UDPLITE,
+	.name			= "udplite",
+	.pkt_to_tuple		= udplite_pkt_to_tuple,
+	.invert_tuple		= udplite_invert_tuple,
+	.print_tuple		= udplite_print_tuple,
+	.print_conntrack	= udplite_print_conntrack,
+	.packet			= udplite_packet,
+	.new			= udplite_new,
+	.error			= udplite_error,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
+#endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &udplite_sysctl_table_users,
+	.ctl_table_header	= &udplite_sysctl_header,
+	.ctl_table		= udplite_sysctl_table,
+#endif
+};
+
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
+{
+	.l3proto		= PF_INET6,
+	.l4proto		= IPPROTO_UDPLITE,
+	.name			= "udplite",
+	.pkt_to_tuple		= udplite_pkt_to_tuple,
+	.invert_tuple		= udplite_invert_tuple,
+	.print_tuple		= udplite_print_tuple,
+	.print_conntrack	= udplite_print_conntrack,
+	.packet			= udplite_packet,
+	.new			= udplite_new,
+	.error			= udplite_error,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
+#endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &udplite_sysctl_table_users,
+	.ctl_table_header	= &udplite_sysctl_header,
+	.ctl_table		= udplite_sysctl_table,
+#endif
+};
+
+static int __init nf_conntrack_proto_udplite_init(void)
+{
+	int err;
+
+	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4);
+	if (err < 0)
+		goto err1;
+	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
+	if (err < 0)
+		goto err2;
+	return 0;
+err2:
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+err1:
+	return err;
+}
+
+static void __exit nf_conntrack_proto_udplite_exit(void)
+{
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+}
+
+module_init(nf_conntrack_proto_udplite_init);
+module_exit(nf_conntrack_proto_udplite_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index eb2d1dc..355d371 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -40,12 +40,6 @@
 static unsigned int ports_c;
 module_param_array(ports, ushort, &ports_c, 0400);
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 struct sane_request {
 	__be32 RPC_code;
 #define SANE_NET_START      7   /* RPC code */
@@ -125,15 +119,15 @@
 	ct_sane_info->state = SANE_STATE_NORMAL;
 
 	if (datalen < sizeof(struct sane_reply_net_start)) {
-		DEBUGP("nf_ct_sane: NET_START reply too short\n");
+		pr_debug("nf_ct_sane: NET_START reply too short\n");
 		goto out;
 	}
 
 	reply = (struct sane_reply_net_start *)sb_ptr;
 	if (reply->status != htonl(SANE_STATUS_SUCCESS)) {
 		/* saned refused the command */
-		DEBUGP("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
-			ntohl(reply->status));
+		pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
+			 ntohl(reply->status));
 		goto out;
 	}
 
@@ -141,35 +135,32 @@
 	if (reply->zero != 0)
 		goto out;
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL) {
 		ret = NF_DROP;
 		goto out;
 	}
 
 	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-	nf_conntrack_expect_init(exp, family,
-				 &tuple->src.u3, &tuple->dst.u3,
-				 IPPROTO_TCP,
-				 NULL, &reply->port);
+	nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+			  IPPROTO_TCP, NULL, &reply->port);
 
-	DEBUGP("nf_ct_sane: expect: ");
+	pr_debug("nf_ct_sane: expect: ");
 	NF_CT_DUMP_TUPLE(&exp->tuple);
-	NF_CT_DUMP_TUPLE(&exp->mask);
 
 	/* Can't expect this?  Best to drop packet now. */
-	if (nf_conntrack_expect_related(exp) != 0)
+	if (nf_ct_expect_related(exp) != 0)
 		ret = NF_DROP;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 out:
 	spin_unlock_bh(&nf_sane_lock);
 	return ret;
 }
 
-static struct nf_conntrack_helper sane[MAX_PORTS][2];
-static char sane_names[MAX_PORTS][2][sizeof("sane-65535")];
+static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
+static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly;
 
 /* don't make this __exit, since it's called from __init ! */
 static void nf_conntrack_sane_fini(void)
@@ -178,9 +169,9 @@
 
 	for (i = 0; i < ports_c; i++) {
 		for (j = 0; j < 2; j++) {
-			DEBUGP("nf_ct_sane: unregistering helper for pf: %d "
-			       "port: %d\n",
-				sane[i][j].tuple.src.l3num, ports[i]);
+			pr_debug("nf_ct_sane: unregistering helper for pf: %d "
+				 "port: %d\n",
+				 sane[i][j].tuple.src.l3num, ports[i]);
 			nf_conntrack_helper_unregister(&sane[i][j]);
 		}
 	}
@@ -208,8 +199,6 @@
 		for (j = 0; j < 2; j++) {
 			sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
 			sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
-			sane[i][j].mask.src.u.tcp.port = 0xFFFF;
-			sane[i][j].mask.dst.protonum = 0xFF;
 			sane[i][j].max_expected = 1;
 			sane[i][j].timeout = 5 * 60;	/* 5 Minutes */
 			sane[i][j].me = THIS_MODULE;
@@ -221,9 +210,9 @@
 				sprintf(tmpname, "sane-%d", ports[i]);
 			sane[i][j].name = tmpname;
 
-			DEBUGP("nf_ct_sane: registering helper for pf: %d "
-			       "port: %d\n",
-				sane[i][j].tuple.src.l3num, ports[i]);
+			pr_debug("nf_ct_sane: registering helper for pf: %d "
+				 "port: %d\n",
+				 sane[i][j].tuple.src.l3num, ports[i]);
 			ret = nf_conntrack_helper_register(&sane[i][j]);
 			if (ret) {
 				printk(KERN_ERR "nf_ct_sane: failed to "
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 7aaa8c9..1276a44 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -21,12 +21,6 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <linux/netfilter/nf_conntrack_sip.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
 MODULE_DESCRIPTION("SIP connection tracking helper");
@@ -285,7 +279,7 @@
 	const char *aux = dptr;
 
 	if (!parse_addr(ct, dptr, &dptr, &addr, limit)) {
-		DEBUGP("ip: %s parse failed.!\n", dptr);
+		pr_debug("ip: %s parse failed.!\n", dptr);
 		return 0;
 	}
 
@@ -344,8 +338,8 @@
 				    ct_sip_lnlen(dptr, limit),
 				    hnfo->case_sensitive);
 		if (!aux) {
-			DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
-			       hnfo->lname);
+			pr_debug("'%s' not found in '%s'.\n", hnfo->ln_str,
+				 hnfo->lname);
 			return -1;
 		}
 		aux += hnfo->ln_strlen;
@@ -356,11 +350,11 @@
 
 		*matchoff = (aux - k) + shift;
 
-		DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname,
-		       *matchlen);
+		pr_debug("%s match succeeded! - len: %u\n", hnfo->lname,
+			 *matchlen);
 		return 1;
 	}
-	DEBUGP("%s header not found.\n", hnfo->lname);
+	pr_debug("%s header not found.\n", hnfo->lname);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ct_sip_get_info);
@@ -378,23 +372,23 @@
 	int ret;
 	typeof(nf_nat_sdp_hook) nf_nat_sdp;
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL)
 		return NF_DROP;
-	nf_conntrack_expect_init(exp, family,
-				 &ct->tuplehash[!dir].tuple.src.u3, addr,
-				 IPPROTO_UDP, NULL, &port);
+	nf_ct_expect_init(exp, family,
+			  &ct->tuplehash[!dir].tuple.src.u3, addr,
+			  IPPROTO_UDP, NULL, &port);
 
 	nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
 	if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
 		ret = nf_nat_sdp(pskb, ctinfo, exp, dptr);
 	else {
-		if (nf_conntrack_expect_related(exp) != 0)
+		if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
 		else
 			ret = NF_ACCEPT;
 	}
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -424,7 +418,7 @@
 	if (!skb_is_nonlinear(*pskb))
 		dptr = (*pskb)->data + dataoff;
 	else {
-		DEBUGP("Copy of skbuff not supported yet.\n");
+		pr_debug("Copy of skbuff not supported yet.\n");
 		goto out;
 	}
 
@@ -442,6 +436,9 @@
 
 	/* RTP info only in some SDP pkts */
 	if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+	    memcmp(dptr, "UPDATE", sizeof("UPDATE") - 1) != 0 &&
+	    memcmp(dptr, "SIP/2.0 180", sizeof("SIP/2.0 180") - 1) != 0 &&
+	    memcmp(dptr, "SIP/2.0 183", sizeof("SIP/2.0 183") - 1) != 0 &&
 	    memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
 		goto out;
 	}
@@ -503,9 +500,6 @@
 		for (j = 0; j < 2; j++) {
 			sip[i][j].tuple.dst.protonum = IPPROTO_UDP;
 			sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
-			sip[i][j].mask.src.l3num = 0xFFFF;
-			sip[i][j].mask.src.u.udp.port = htons(0xFFFF);
-			sip[i][j].mask.dst.protonum = 0xFF;
 			sip[i][j].max_expected = 2;
 			sip[i][j].timeout = 3 * 60; /* 3 minutes */
 			sip[i][j].me = THIS_MODULE;
@@ -518,7 +512,7 @@
 				sprintf(tmpname, "sip-%u", i);
 			sip[i][j].name = tmpname;
 
-			DEBUGP("port #%u: %u\n", i, ports[i]);
+			pr_debug("port #%u: %u\n", i, ports[i]);
 
 			ret = nf_conntrack_helper_register(&sip[i][j]);
 			if (ret) {
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 45baeb0..ffb6ff8 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -25,12 +25,6 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_PROC_FS
@@ -60,35 +54,36 @@
 	unsigned int bucket;
 };
 
-static struct list_head *ct_get_first(struct seq_file *seq)
+static struct hlist_node *ct_get_first(struct seq_file *seq)
 {
 	struct ct_iter_state *st = seq->private;
 
 	for (st->bucket = 0;
 	     st->bucket < nf_conntrack_htable_size;
 	     st->bucket++) {
-		if (!list_empty(&nf_conntrack_hash[st->bucket]))
-			return nf_conntrack_hash[st->bucket].next;
+		if (!hlist_empty(&nf_conntrack_hash[st->bucket]))
+			return nf_conntrack_hash[st->bucket].first;
 	}
 	return NULL;
 }
 
-static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+static struct hlist_node *ct_get_next(struct seq_file *seq,
+				      struct hlist_node *head)
 {
 	struct ct_iter_state *st = seq->private;
 
 	head = head->next;
-	while (head == &nf_conntrack_hash[st->bucket]) {
+	while (head == NULL) {
 		if (++st->bucket >= nf_conntrack_htable_size)
 			return NULL;
-		head = nf_conntrack_hash[st->bucket].next;
+		head = nf_conntrack_hash[st->bucket].first;
 	}
 	return head;
 }
 
-static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos)
 {
-	struct list_head *head = ct_get_first(seq);
+	struct hlist_node *head = ct_get_first(seq);
 
 	if (head)
 		while (pos && (head = ct_get_next(seq, head)))
@@ -190,7 +185,7 @@
 	return 0;
 }
 
-static struct seq_operations ct_seq_ops = {
+static const struct seq_operations ct_seq_ops = {
 	.start = ct_seq_start,
 	.next  = ct_seq_next,
 	.stop  = ct_seq_stop,
@@ -294,7 +289,7 @@
 	return 0;
 }
 
-static struct seq_operations ct_cpu_seq_ops = {
+static const struct seq_operations ct_cpu_seq_ops = {
 	.start	= ct_cpu_seq_start,
 	.next	= ct_cpu_seq_next,
 	.stop	= ct_cpu_seq_stop,
@@ -371,7 +366,14 @@
 		.extra1		= &log_invalid_proto_min,
 		.extra2		= &log_invalid_proto_max,
 	},
-
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nf_conntrack_expect_max",
+		.data		= &nf_ct_expect_max,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -410,7 +412,7 @@
 static int __init nf_conntrack_standalone_init(void)
 {
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+	struct proc_dir_entry *proc, *proc_stat;
 #endif
 	int ret = 0;
 
@@ -422,13 +424,9 @@
 	proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
 	if (!proc) goto cleanup_init;
 
-	proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
-					&exp_file_ops);
-	if (!proc_exp) goto cleanup_proc;
-
 	proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
 	if (!proc_stat)
-		goto cleanup_proc_exp;
+		goto cleanup_proc;
 
 	proc_stat->proc_fops = &ct_cpu_seq_fops;
 	proc_stat->owner = THIS_MODULE;
@@ -448,8 +446,6 @@
 #endif
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("nf_conntrack", proc_net_stat);
- cleanup_proc_exp:
-	proc_net_remove("nf_conntrack_expect");
  cleanup_proc:
 	proc_net_remove("nf_conntrack");
  cleanup_init:
@@ -465,7 +461,6 @@
 #endif
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("nf_conntrack", proc_net_stat);
-	proc_net_remove("nf_conntrack_expect");
 	proc_net_remove("nf_conntrack");
 #endif /* CNFIG_PROC_FS */
 	nf_conntrack_cleanup();
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index 37c4542..cc19506 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -29,13 +29,6 @@
 module_param_array(ports, ushort, &ports_c, 0400);
 MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
 
-#if 0
-#define DEBUGP(format, args...) printk("%s:%s:" format, \
-				       __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb,
 				 enum ip_conntrack_info ctinfo,
 				 struct nf_conntrack_expect *exp) __read_mostly;
@@ -62,39 +55,35 @@
 	case TFTP_OPCODE_READ:
 	case TFTP_OPCODE_WRITE:
 		/* RRQ and WRQ works the same way */
-		DEBUGP("");
 		NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 		NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 
-		exp = nf_conntrack_expect_alloc(ct);
+		exp = nf_ct_expect_alloc(ct);
 		if (exp == NULL)
 			return NF_DROP;
 		tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-		nf_conntrack_expect_init(exp, family,
-					 &tuple->src.u3, &tuple->dst.u3,
-					 IPPROTO_UDP,
-					 NULL, &tuple->dst.u.udp.port);
+		nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+				  IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
 
-		DEBUGP("expect: ");
+		pr_debug("expect: ");
 		NF_CT_DUMP_TUPLE(&exp->tuple);
-		NF_CT_DUMP_TUPLE(&exp->mask);
 
 		nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
 		if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
 			ret = nf_nat_tftp(pskb, ctinfo, exp);
-		else if (nf_conntrack_expect_related(exp) != 0)
+		else if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
-		nf_conntrack_expect_put(exp);
+		nf_ct_expect_put(exp);
 		break;
 	case TFTP_OPCODE_DATA:
 	case TFTP_OPCODE_ACK:
-		DEBUGP("Data/ACK opcode\n");
+		pr_debug("Data/ACK opcode\n");
 		break;
 	case TFTP_OPCODE_ERROR:
-		DEBUGP("Error opcode\n");
+		pr_debug("Error opcode\n");
 		break;
 	default:
-		DEBUGP("Unknown opcode\n");
+		pr_debug("Unknown opcode\n");
 	}
 	return ret;
 }
@@ -128,9 +117,6 @@
 		for (j = 0; j < 2; j++) {
 			tftp[i][j].tuple.dst.protonum = IPPROTO_UDP;
 			tftp[i][j].tuple.src.u.udp.port = htons(ports[i]);
-			tftp[i][j].mask.src.l3num = 0xFFFF;
-			tftp[i][j].mask.dst.protonum = 0xFF;
-			tftp[i][j].mask.src.u.udp.port = htons(0xFFFF);
 			tftp[i][j].max_expected = 1;
 			tftp[i][j].timeout = 5 * 60; /* 5 minutes */
 			tftp[i][j].me = THIS_MODULE;
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 91b220c..9498579 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -140,7 +140,7 @@
 	return seq_printf(s, "%2lld %s\n", *pos, logger->name);
 }
 
-static struct seq_operations nflog_seq_ops = {
+static const struct seq_operations nflog_seq_ops = {
 	.start	= seq_start,
 	.next	= seq_next,
 	.stop	= seq_stop,
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index b1f2ace..a481a34 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,7 @@
  */
 static struct nf_queue_handler *queue_handler[NPROTO];
 
-static DEFINE_RWLOCK(queue_handler_lock);
+static DEFINE_MUTEX(queue_handler_mutex);
 
 /* return EBUSY when somebody else is registered, return EEXIST if the
  * same handler is registered, return 0 in case of success. */
@@ -28,30 +28,37 @@
 	if (pf >= NPROTO)
 		return -EINVAL;
 
-	write_lock_bh(&queue_handler_lock);
+	mutex_lock(&queue_handler_mutex);
 	if (queue_handler[pf] == qh)
 		ret = -EEXIST;
 	else if (queue_handler[pf])
 		ret = -EBUSY;
 	else {
-		queue_handler[pf] = qh;
+		rcu_assign_pointer(queue_handler[pf], qh);
 		ret = 0;
 	}
-	write_unlock_bh(&queue_handler_lock);
+	mutex_unlock(&queue_handler_mutex);
 
 	return ret;
 }
 EXPORT_SYMBOL(nf_register_queue_handler);
 
 /* The caller must flush their queue before this */
-int nf_unregister_queue_handler(int pf)
+int nf_unregister_queue_handler(int pf, struct nf_queue_handler *qh)
 {
 	if (pf >= NPROTO)
 		return -EINVAL;
 
-	write_lock_bh(&queue_handler_lock);
-	queue_handler[pf] = NULL;
-	write_unlock_bh(&queue_handler_lock);
+	mutex_lock(&queue_handler_mutex);
+	if (queue_handler[pf] != qh) {
+		mutex_unlock(&queue_handler_mutex);
+		return -EINVAL;
+	}
+
+	rcu_assign_pointer(queue_handler[pf], NULL);
+	mutex_unlock(&queue_handler_mutex);
+
+	synchronize_rcu();
 
 	return 0;
 }
@@ -61,12 +68,14 @@
 {
 	int pf;
 
-	write_lock_bh(&queue_handler_lock);
+	mutex_lock(&queue_handler_mutex);
 	for (pf = 0; pf < NPROTO; pf++)  {
 		if (queue_handler[pf] == qh)
-			queue_handler[pf] = NULL;
+			rcu_assign_pointer(queue_handler[pf], NULL);
 	}
-	write_unlock_bh(&queue_handler_lock);
+	mutex_unlock(&queue_handler_mutex);
+
+	synchronize_rcu();
 }
 EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
 
@@ -89,18 +98,21 @@
 	struct net_device *physoutdev = NULL;
 #endif
 	struct nf_afinfo *afinfo;
+	struct nf_queue_handler *qh;
 
 	/* QUEUE == DROP if noone is waiting, to be safe. */
-	read_lock(&queue_handler_lock);
-	if (!queue_handler[pf]) {
-		read_unlock(&queue_handler_lock);
+	rcu_read_lock();
+
+	qh = rcu_dereference(queue_handler[pf]);
+	if (!qh) {
+		rcu_read_unlock();
 		kfree_skb(skb);
 		return 1;
 	}
 
 	afinfo = nf_get_afinfo(pf);
 	if (!afinfo) {
-		read_unlock(&queue_handler_lock);
+		rcu_read_unlock();
 		kfree_skb(skb);
 		return 1;
 	}
@@ -110,7 +122,7 @@
 		if (net_ratelimit())
 			printk(KERN_ERR "OOM queueing packet %p\n",
 			       skb);
-		read_unlock(&queue_handler_lock);
+		rcu_read_unlock();
 		kfree_skb(skb);
 		return 1;
 	}
@@ -120,7 +132,7 @@
 
 	/* If it's going away, ignore hook. */
 	if (!try_module_get(info->elem->owner)) {
-		read_unlock(&queue_handler_lock);
+		rcu_read_unlock();
 		kfree(info);
 		return 0;
 	}
@@ -138,10 +150,9 @@
 	}
 #endif
 	afinfo->saveroute(skb, info);
-	status = queue_handler[pf]->outfn(skb, info, queuenum,
-					  queue_handler[pf]->data);
+	status = qh->outfn(skb, info, queuenum, qh->data);
 
-	read_unlock(&queue_handler_lock);
+	rcu_read_unlock();
 
 	if (status < 0) {
 		/* James M doesn't say fuck enough. */
@@ -308,18 +319,18 @@
 	loff_t *pos = v;
 	struct nf_queue_handler *qh;
 
-	read_lock_bh(&queue_handler_lock);
-	qh = queue_handler[*pos];
+	rcu_read_lock();
+	qh = rcu_dereference(queue_handler[*pos]);
 	if (!qh)
 		ret = seq_printf(s, "%2lld NONE\n", *pos);
 	else
 		ret = seq_printf(s, "%2lld %s\n", *pos, qh->name);
-	read_unlock_bh(&queue_handler_lock);
+	rcu_read_unlock();
 
 	return ret;
 }
 
-static struct seq_operations nfqueue_seq_ops = {
+static const struct seq_operations nfqueue_seq_ops = {
 	.start	= seq_start,
 	.next	= seq_next,
 	.stop	= seq_stop,
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index e32e30e..e185a5b 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -962,7 +962,7 @@
 			  inst->flushtimeout, atomic_read(&inst->use));
 }
 
-static struct seq_operations nful_seq_ops = {
+static const struct seq_operations nful_seq_ops = {
 	.start	= seq_start,
 	.next	= seq_next,
 	.stop	= seq_stop,
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7a97bec..bb65a38 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -913,9 +913,7 @@
 		case NFQNL_CFG_CMD_PF_UNBIND:
 			QDEBUG("unregistering queue handler for pf=%u\n",
 				ntohs(cmd->pf));
-			/* This is a bug and a feature.  We can unregister
-			 * other handlers(!) */
-			ret = nf_unregister_queue_handler(ntohs(cmd->pf));
+			ret = nf_unregister_queue_handler(ntohs(cmd->pf), &nfqh);
 			break;
 		default:
 			ret = -EINVAL;
@@ -1050,7 +1048,7 @@
 			  atomic_read(&inst->use));
 }
 
-static struct seq_operations nfqnl_seq_ops = {
+static const struct seq_operations nfqnl_seq_ops = {
 	.start	= seq_start,
 	.next	= seq_next,
 	.stop	= seq_stop,
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 0eb2504..cc2baa6 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -320,8 +320,8 @@
 		return -EINVAL;
 	}
 	if (match->hooks && (hook_mask & ~match->hooks) != 0) {
-		printk("%s_tables: %s match: bad hook_mask %u\n",
-		       xt_prefix[family], match->name, hook_mask);
+		printk("%s_tables: %s match: bad hook_mask %u/%u\n",
+		       xt_prefix[family], match->name, hook_mask, match->hooks);
 		return -EINVAL;
 	}
 	if (match->proto && (match->proto != proto || inv_proto)) {
@@ -410,8 +410,9 @@
 		return -EINVAL;
 	}
 	if (target->hooks && (hook_mask & ~target->hooks) != 0) {
-		printk("%s_tables: %s target: bad hook_mask %u\n",
-		       xt_prefix[family], target->name, hook_mask);
+		printk("%s_tables: %s target: bad hook_mask %u/%u\n",
+		       xt_prefix[family], target->name, hook_mask,
+		       target->hooks);
 		return -EINVAL;
 	}
 	if (target->proto && (target->proto != proto || inv_proto)) {
@@ -744,7 +745,7 @@
 		return 0;
 }
 
-static struct seq_operations xt_tgt_seq_ops = {
+static const struct seq_operations xt_tgt_seq_ops = {
 	.start	= xt_tgt_seq_start,
 	.next	= xt_tgt_seq_next,
 	.stop	= xt_tgt_seq_stop,
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 3088483..5194285 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -39,7 +39,7 @@
 	return XT_CONTINUE;
 }
 
-static struct xt_target xt_classify_target[] = {
+static struct xt_target xt_classify_target[] __read_mostly = {
 	{
 		.family		= AF_INET,
 		.name 		= "CLASSIFY",
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index b03ce00..5a00c54 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -76,33 +76,33 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_target *target,
 	   void *targinfo,
 	   unsigned int hook_mask)
 {
-	struct xt_connmark_target_info *matchinfo = targinfo;
+	const struct xt_connmark_target_info *matchinfo = targinfo;
 
 	if (nf_ct_l3proto_try_module_get(target->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", target->family);
-		return 0;
+		return false;
 	}
 	if (matchinfo->mode == XT_CONNMARK_RESTORE) {
 		if (strcmp(tablename, "mangle") != 0) {
 			printk(KERN_WARNING "CONNMARK: restore can only be "
 			       "called from \"mangle\" table, not \"%s\"\n",
 			       tablename);
-			return 0;
+			return false;
 		}
 	}
 	if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
 		printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -121,7 +121,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_connmark_target_info *cm = src;
+	const struct compat_xt_connmark_target_info *cm = src;
 	struct xt_connmark_target_info m = {
 		.mark	= cm->mark,
 		.mask	= cm->mask,
@@ -132,7 +132,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_connmark_target_info *m = src;
+	const struct xt_connmark_target_info *m = src;
 	struct compat_xt_connmark_target_info cm = {
 		.mark	= m->mark,
 		.mask	= m->mask,
@@ -142,7 +142,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_target xt_connmark_target[] = {
+static struct xt_target xt_connmark_target[] __read_mostly = {
 	{
 		.name		= "CONNMARK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 81c0c58..63d7313 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -33,7 +33,7 @@
  * If the packet has a security mark and the connection does not, copy
  * the security mark from the packet to the connection.
  */
-static void secmark_save(struct sk_buff *skb)
+static void secmark_save(const struct sk_buff *skb)
 {
 	if (skb->secmark) {
 		struct nf_conn *ct;
@@ -85,16 +85,16 @@
 	return XT_CONTINUE;
 }
 
-static int checkentry(const char *tablename, const void *entry,
-		      const struct xt_target *target, void *targinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *entry,
+		       const struct xt_target *target, void *targinfo,
+		       unsigned int hook_mask)
 {
-	struct xt_connsecmark_target_info *info = targinfo;
+	const struct xt_connsecmark_target_info *info = targinfo;
 
 	if (nf_ct_l3proto_try_module_get(target->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", target->family);
-		return 0;
+		return false;
 	}
 	switch (info->mode) {
 	case CONNSECMARK_SAVE:
@@ -103,10 +103,10 @@
 
 	default:
 		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
 static void
@@ -115,7 +115,7 @@
 	nf_ct_l3proto_module_put(target->family);
 }
 
-static struct xt_target xt_connsecmark_target[] = {
+static struct xt_target xt_connsecmark_target[] __read_mostly = {
 	{
 		.name		= "CONNSECMARK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 9f2f220..798ab73 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -66,22 +66,22 @@
 	return XT_CONTINUE;
 }
 
-static int checkentry(const char *tablename,
-		      const void *e_void,
-		      const struct xt_target *target,
-		      void *targinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+		       const void *e_void,
+		       const struct xt_target *target,
+		       void *targinfo,
+		       unsigned int hook_mask)
 {
 	const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp;
 
-	if ((dscp > XT_DSCP_MAX)) {
+	if (dscp > XT_DSCP_MAX) {
 		printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target xt_dscp_target[] = {
+static struct xt_target xt_dscp_target[] __read_mostly = {
 	{
 		.name		= "DSCP",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 4381780..f30fe0b 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -65,43 +65,43 @@
 }
 
 
-static int
+static bool
 checkentry_v0(const char *tablename,
 	      const void *entry,
 	      const struct xt_target *target,
 	      void *targinfo,
 	      unsigned int hook_mask)
 {
-	struct xt_mark_target_info *markinfo = targinfo;
+	const struct xt_mark_target_info *markinfo = targinfo;
 
 	if (markinfo->mark > 0xffffffff) {
 		printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static int
+static bool
 checkentry_v1(const char *tablename,
 	      const void *entry,
 	      const struct xt_target *target,
 	      void *targinfo,
 	      unsigned int hook_mask)
 {
-	struct xt_mark_target_info_v1 *markinfo = targinfo;
+	const struct xt_mark_target_info_v1 *markinfo = targinfo;
 
 	if (markinfo->mode != XT_MARK_SET
 	    && markinfo->mode != XT_MARK_AND
 	    && markinfo->mode != XT_MARK_OR) {
 		printk(KERN_WARNING "MARK: unknown mode %u\n",
 		       markinfo->mode);
-		return 0;
+		return false;
 	}
 	if (markinfo->mark > 0xffffffff) {
 		printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 #ifdef CONFIG_COMPAT
@@ -114,7 +114,7 @@
 
 static void compat_from_user_v1(void *dst, void *src)
 {
-	struct compat_xt_mark_target_info_v1 *cm = src;
+	const struct compat_xt_mark_target_info_v1 *cm = src;
 	struct xt_mark_target_info_v1 m = {
 		.mark	= cm->mark,
 		.mode	= cm->mode,
@@ -124,7 +124,7 @@
 
 static int compat_to_user_v1(void __user *dst, void *src)
 {
-	struct xt_mark_target_info_v1 *m = src;
+	const struct xt_mark_target_info_v1 *m = src;
 	struct compat_xt_mark_target_info_v1 cm = {
 		.mark	= m->mark,
 		.mode	= m->mode,
@@ -133,7 +133,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_target xt_mark_target[] = {
+static struct xt_target xt_mark_target[] __read_mostly = {
 	{
 		.name		= "MARK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index 901ed7a..d3594c7 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -38,21 +38,21 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 nflog_checkentry(const char *tablename, const void *entry,
 		 const struct xt_target *target, void *targetinfo,
 		 unsigned int hookmask)
 {
-	struct xt_nflog_info *info = targetinfo;
+	const struct xt_nflog_info *info = targetinfo;
 
 	if (info->flags & ~XT_NFLOG_MASK)
-		return 0;
+		return false;
 	if (info->prefix[sizeof(info->prefix) - 1] != '\0')
-		return 0;
-	return 1;
+		return false;
+	return true;
 }
 
-static struct xt_target xt_nflog_target[] = {
+static struct xt_target xt_nflog_target[] __read_mostly = {
 	{
 		.name		= "NFLOG",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 201155b..13f59f3 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -36,7 +36,7 @@
 	return NF_QUEUE_NR(tinfo->queuenum);
 }
 
-static struct xt_target xt_nfqueue_target[] = {
+static struct xt_target xt_nfqueue_target[] __read_mostly = {
 	{
 		.name		= "NFQUEUE",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 5085fb3..b7d6312 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -33,7 +33,7 @@
 	return XT_CONTINUE;
 }
 
-static struct xt_target xt_notrack_target[] = {
+static struct xt_target xt_notrack_target[] __read_mostly = {
 	{
 		.name		= "NOTRACK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 705f0e8..c83779a 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -51,7 +51,7 @@
 	return XT_CONTINUE;
 }
 
-static int checkentry_selinux(struct xt_secmark_target_info *info)
+static bool checkentry_selinux(struct xt_secmark_target_info *info)
 {
 	int err;
 	struct xt_secmark_target_selinux_info *sel = &info->u.sel;
@@ -63,53 +63,53 @@
 		if (err == -EINVAL)
 			printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
 			       sel->selctx);
-		return 0;
+		return false;
 	}
 
 	if (!sel->selsid) {
 		printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
 		       sel->selctx);
-		return 0;
+		return false;
 	}
 
 	err = selinux_relabel_packet_permission(sel->selsid);
 	if (err) {
 		printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static int checkentry(const char *tablename, const void *entry,
-		      const struct xt_target *target, void *targinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *entry,
+		       const struct xt_target *target, void *targinfo,
+		       unsigned int hook_mask)
 {
 	struct xt_secmark_target_info *info = targinfo;
 
 	if (mode && mode != info->mode) {
 		printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
 		       "rules for mode %hu\n", mode, info->mode);
-		return 0;
+		return false;
 	}
 
 	switch (info->mode) {
 	case SECMARK_MODE_SEL:
 		if (!checkentry_selinux(info))
-			return 0;
+			return false;
 		break;
 
 	default:
 		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
-		return 0;
+		return false;
 	}
 
 	if (!mode)
 		mode = info->mode;
-	return 1;
+	return true;
 }
 
-static struct xt_target xt_secmark_target[] = {
+static struct xt_target xt_secmark_target[] __read_mostly = {
 	{
 		.name		= "SECMARK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 15fe8f6..d40f7e4 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -93,7 +93,7 @@
 				return 0;
 
 			opt[i+2] = (newmss & 0xff00) >> 8;
-			opt[i+3] = (newmss & 0x00ff);
+			opt[i+3] = newmss & 0x00ff;
 
 			nf_proto_csum_replace2(&tcph->check, *pskb,
 					       htons(oldmss), htons(newmss), 0);
@@ -126,7 +126,7 @@
 	opt[0] = TCPOPT_MSS;
 	opt[1] = TCPOLEN_MSS;
 	opt[2] = (newmss & 0xff00) >> 8;
-	opt[3] = (newmss & 0x00ff);
+	opt[3] = newmss & 0x00ff;
 
 	nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
 
@@ -197,19 +197,19 @@
 #define TH_SYN 0x02
 
 /* Must specify -p tcp --syn */
-static inline int find_syn_match(const struct xt_entry_match *m)
+static inline bool find_syn_match(const struct xt_entry_match *m)
 {
 	const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data;
 
 	if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
 	    tcpinfo->flg_cmp & TH_SYN &&
 	    !(tcpinfo->invflags & XT_TCP_INV_FLAGS))
-		return 1;
+		return true;
 
-	return 0;
+	return false;
 }
 
-static int
+static bool
 xt_tcpmss_checkentry4(const char *tablename,
 		      const void *entry,
 		      const struct xt_target *target,
@@ -225,16 +225,16 @@
 			   (1 << NF_IP_POST_ROUTING))) != 0) {
 		printk("xt_TCPMSS: path-MTU clamping only supported in "
 		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return 0;
+		return false;
 	}
 	if (IPT_MATCH_ITERATE(e, find_syn_match))
-		return 1;
+		return true;
 	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
-	return 0;
+	return false;
 }
 
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
-static int
+static bool
 xt_tcpmss_checkentry6(const char *tablename,
 		      const void *entry,
 		      const struct xt_target *target,
@@ -250,16 +250,16 @@
 			   (1 << NF_IP6_POST_ROUTING))) != 0) {
 		printk("xt_TCPMSS: path-MTU clamping only supported in "
 		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return 0;
+		return false;
 	}
 	if (IP6T_MATCH_ITERATE(e, find_syn_match))
-		return 1;
+		return true;
 	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
-	return 0;
+	return false;
 }
 #endif
 
-static struct xt_target xt_tcpmss_reg[] = {
+static struct xt_target xt_tcpmss_reg[] __read_mostly = {
 	{
 		.family		= AF_INET,
 		.name		= "TCPMSS",
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
new file mode 100644
index 0000000..4df2ded
--- /dev/null
+++ b/net/netfilter/xt_TRACE.c
@@ -0,0 +1,53 @@
+/* This is a module which is used to mark packets for tracing.
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TRACE");
+MODULE_ALIAS("ip6t_TRACE");
+
+static unsigned int
+target(struct sk_buff **pskb,
+       const struct net_device *in,
+       const struct net_device *out,
+       unsigned int hooknum,
+       const struct xt_target *target,
+       const void *targinfo)
+{
+	(*pskb)->nf_trace = 1;
+	return XT_CONTINUE;
+}
+
+static struct xt_target xt_trace_target[] __read_mostly = {
+	{
+		.name		= "TRACE",
+		.family		= AF_INET,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "TRACE",
+		.family		= AF_INET6,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init xt_trace_init(void)
+{
+	return xt_register_targets(xt_trace_target,
+				   ARRAY_SIZE(xt_trace_target));
+}
+
+static void __exit xt_trace_fini(void)
+{
+	xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target));
+}
+
+module_init(xt_trace_init);
+module_exit(xt_trace_fini);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 7db492d..64bcdb0 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -15,7 +15,7 @@
 MODULE_ALIAS("ipt_comment");
 MODULE_ALIAS("ip6t_comment");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -23,13 +23,13 @@
       const void *matchinfo,
       int offset,
       unsigned int protooff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	/* We always match */
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_comment_match[] = {
+static struct xt_match xt_comment_match[] __read_mostly = {
 	{
 		.name		= "comment",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 804afe5..dd4d79b 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -15,7 +15,7 @@
 MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
 MODULE_ALIAS("ipt_connbytes");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -23,10 +23,10 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_connbytes_info *sinfo = matchinfo;
-	struct nf_conn *ct;
+	const struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 	u_int64_t what = 0;	/* initialize to make gcc happy */
 	u_int64_t bytes = 0;
@@ -35,7 +35,7 @@
 
 	ct = nf_ct_get(skb, &ctinfo);
 	if (!ct)
-		return 0;
+		return false;
 	counters = ct->counters;
 
 	switch (sinfo->what) {
@@ -90,36 +90,36 @@
 	}
 
 	if (sinfo->count.to)
-		return (what <= sinfo->count.to && what >= sinfo->count.from);
+		return what <= sinfo->count.to && what >= sinfo->count.from;
 	else
-		return (what >= sinfo->count.from);
+		return what >= sinfo->count.from;
 }
 
-static int check(const char *tablename,
-		 const void *ip,
-		 const struct xt_match *match,
-		 void *matchinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *ip,
+		  const struct xt_match *match,
+		  void *matchinfo,
+		  unsigned int hook_mask)
 {
 	const struct xt_connbytes_info *sinfo = matchinfo;
 
 	if (sinfo->what != XT_CONNBYTES_PKTS &&
 	    sinfo->what != XT_CONNBYTES_BYTES &&
 	    sinfo->what != XT_CONNBYTES_AVGPKT)
-		return 0;
+		return false;
 
 	if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
 	    sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
 	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
-		return 0;
+		return false;
 
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
 static void
@@ -128,7 +128,7 @@
 	nf_ct_l3proto_module_put(match->family);
 }
 
-static struct xt_match xt_connbytes_match[] = {
+static struct xt_match xt_connbytes_match[] __read_mostly = {
 	{
 		.name		= "connbytes",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
new file mode 100644
index 0000000..3335dd5
--- /dev/null
+++ b/net/netfilter/xt_connlimit.c
@@ -0,0 +1,313 @@
+/*
+ * netfilter module to limit the number of parallel tcp
+ * connections per IP address.
+ *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
+ *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
+ *		only ignore TIME_WAIT or gone connections
+ *   Copyright © Jan Engelhardt <jengelh@gmx.de>, 2007
+ *
+ * based on ...
+ *
+ * Kernel module to match connection tracking information.
+ * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
+ */
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/netfilter/nf_conntrack_tcp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_connlimit.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+/* we will save the tuples of all connections we care about */
+struct xt_connlimit_conn {
+	struct list_head list;
+	struct nf_conntrack_tuple tuple;
+};
+
+struct xt_connlimit_data {
+	struct list_head iphash[256];
+	spinlock_t lock;
+};
+
+static u_int32_t connlimit_rnd;
+static bool connlimit_rnd_inited;
+
+static inline unsigned int connlimit_iphash(u_int32_t addr)
+{
+	if (unlikely(!connlimit_rnd_inited)) {
+		get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
+		connlimit_rnd_inited = true;
+	}
+	return jhash_1word(addr, connlimit_rnd) & 0xFF;
+}
+
+static inline unsigned int
+connlimit_iphash6(const union nf_conntrack_address *addr,
+		  const union nf_conntrack_address *mask)
+{
+	union nf_conntrack_address res;
+	unsigned int i;
+
+	if (unlikely(!connlimit_rnd_inited)) {
+		get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
+		connlimit_rnd_inited = true;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i)
+		res.ip6[i] = addr->ip6[i] & mask->ip6[i];
+
+	return jhash2(res.ip6, ARRAY_SIZE(res.ip6), connlimit_rnd) & 0xFF;
+}
+
+static inline bool already_closed(const struct nf_conn *conn)
+{
+	u_int16_t proto = conn->tuplehash[0].tuple.dst.protonum;
+
+	if (proto == IPPROTO_TCP)
+		return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT;
+	else
+		return 0;
+}
+
+static inline unsigned int
+same_source_net(const union nf_conntrack_address *addr,
+		const union nf_conntrack_address *mask,
+		const union nf_conntrack_address *u3, unsigned int family)
+{
+	if (family == AF_INET) {
+		return (addr->ip & mask->ip) == (u3->ip & mask->ip);
+	} else {
+		union nf_conntrack_address lh, rh;
+		unsigned int i;
+
+		for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) {
+			lh.ip6[i] = addr->ip6[i] & mask->ip6[i];
+			rh.ip6[i] = u3->ip6[i] & mask->ip6[i];
+		}
+
+		return memcmp(&lh.ip6, &rh.ip6, sizeof(lh.ip6)) == 0;
+	}
+}
+
+static int count_them(struct xt_connlimit_data *data,
+		      const struct nf_conntrack_tuple *tuple,
+		      const union nf_conntrack_address *addr,
+		      const union nf_conntrack_address *mask,
+		      const struct xt_match *match)
+{
+	struct nf_conntrack_tuple_hash *found;
+	struct xt_connlimit_conn *conn;
+	struct xt_connlimit_conn *tmp;
+	struct nf_conn *found_ct;
+	struct list_head *hash;
+	bool addit = true;
+	int matches = 0;
+
+
+	if (match->family == AF_INET6)
+		hash = &data->iphash[connlimit_iphash6(addr, mask)];
+	else
+		hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)];
+
+	read_lock_bh(&nf_conntrack_lock);
+
+	/* check the saved connections */
+	list_for_each_entry_safe(conn, tmp, hash, list) {
+		found    = __nf_conntrack_find(&conn->tuple, NULL);
+		found_ct = NULL;
+
+		if (found != NULL)
+			found_ct = nf_ct_tuplehash_to_ctrack(found);
+
+		if (found_ct != NULL &&
+		    nf_ct_tuple_equal(&conn->tuple, tuple) &&
+		    !already_closed(found_ct))
+			/*
+			 * Just to be sure we have it only once in the list.
+			 * We should not see tuples twice unless someone hooks
+			 * this into a table without "-p tcp --syn".
+			 */
+			addit = false;
+
+		if (found == NULL) {
+			/* this one is gone */
+			list_del(&conn->list);
+			kfree(conn);
+			continue;
+		}
+
+		if (already_closed(found_ct)) {
+			/*
+			 * we do not care about connections which are
+			 * closed already -> ditch it
+			 */
+			list_del(&conn->list);
+			kfree(conn);
+			continue;
+		}
+
+		if (same_source_net(addr, mask, &conn->tuple.src.u3,
+		    match->family))
+			/* same source network -> be counted! */
+			++matches;
+	}
+
+	read_unlock_bh(&nf_conntrack_lock);
+
+	if (addit) {
+		/* save the new connection in our list */
+		conn = kzalloc(sizeof(*conn), GFP_ATOMIC);
+		if (conn == NULL)
+			return -ENOMEM;
+		conn->tuple = *tuple;
+		list_add(&conn->list, hash);
+		++matches;
+	}
+
+	return matches;
+}
+
+static bool connlimit_match(const struct sk_buff *skb,
+			    const struct net_device *in,
+			    const struct net_device *out,
+			    const struct xt_match *match,
+			    const void *matchinfo, int offset,
+			    unsigned int protoff, bool *hotdrop)
+{
+	const struct xt_connlimit_info *info = matchinfo;
+	union nf_conntrack_address addr, mask;
+	struct nf_conntrack_tuple tuple;
+	const struct nf_conntrack_tuple *tuple_ptr = &tuple;
+	enum ip_conntrack_info ctinfo;
+	const struct nf_conn *ct;
+	int connections;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (ct != NULL)
+		tuple_ptr = &ct->tuplehash[0].tuple;
+	else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
+				    match->family, &tuple))
+		goto hotdrop;
+
+	if (match->family == AF_INET6) {
+		const struct ipv6hdr *iph = ipv6_hdr(skb);
+		memcpy(&addr.ip6, &iph->saddr, sizeof(iph->saddr));
+		memcpy(&mask.ip6, info->v6_mask, sizeof(info->v6_mask));
+	} else {
+		const struct iphdr *iph = ip_hdr(skb);
+		addr.ip = iph->saddr;
+		mask.ip = info->v4_mask;
+	}
+
+	spin_lock_bh(&info->data->lock);
+	connections = count_them(info->data, tuple_ptr, &addr, &mask, match);
+	spin_unlock_bh(&info->data->lock);
+
+	if (connections < 0) {
+		/* kmalloc failed, drop it entirely */
+		*hotdrop = true;
+		return false;
+	}
+
+	return (connections > info->limit) ^ info->inverse;
+
+ hotdrop:
+	*hotdrop = true;
+	return false;
+}
+
+static bool connlimit_check(const char *tablename, const void *ip,
+			    const struct xt_match *match, void *matchinfo,
+			    unsigned int hook_mask)
+{
+	struct xt_connlimit_info *info = matchinfo;
+	unsigned int i;
+
+	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+		printk(KERN_WARNING "cannot load conntrack support for "
+		       "address family %u\n", match->family);
+		return false;
+	}
+
+	/* init private data */
+	info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
+	if (info->data == NULL) {
+		nf_ct_l3proto_module_put(match->family);
+		return false;
+	}
+
+	spin_lock_init(&info->data->lock);
+	for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i)
+		INIT_LIST_HEAD(&info->data->iphash[i]);
+
+	return true;
+}
+
+static void connlimit_destroy(const struct xt_match *match, void *matchinfo)
+{
+	struct xt_connlimit_info *info = matchinfo;
+	struct xt_connlimit_conn *conn;
+	struct xt_connlimit_conn *tmp;
+	struct list_head *hash = info->data->iphash;
+	unsigned int i;
+
+	nf_ct_l3proto_module_put(match->family);
+
+	for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) {
+		list_for_each_entry_safe(conn, tmp, &hash[i], list) {
+			list_del(&conn->list);
+			kfree(conn);
+		}
+	}
+
+	kfree(info->data);
+}
+
+static struct xt_match connlimit_reg[] __read_mostly = {
+	{
+		.name       = "connlimit",
+		.family     = AF_INET,
+		.checkentry = connlimit_check,
+		.match      = connlimit_match,
+		.matchsize  = sizeof(struct xt_connlimit_info),
+		.destroy    = connlimit_destroy,
+		.me         = THIS_MODULE,
+	},
+	{
+		.name       = "connlimit",
+		.family     = AF_INET6,
+		.checkentry = connlimit_check,
+		.match      = connlimit_match,
+		.matchsize  = sizeof(struct xt_connlimit_info),
+		.destroy    = connlimit_destroy,
+		.me         = THIS_MODULE,
+	},
+};
+
+static int __init xt_connlimit_init(void)
+{
+	return xt_register_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg));
+}
+
+static void __exit xt_connlimit_exit(void)
+{
+	xt_unregister_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg));
+}
+
+module_init(xt_connlimit_init);
+module_exit(xt_connlimit_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter xt_connlimit match module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_connlimit");
+MODULE_ALIAS("ip6t_connlimit");
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index e180325..e73fa9b 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -30,7 +30,7 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("ipt_connmark");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -38,38 +38,38 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_connmark_info *info = matchinfo;
-	struct nf_conn *ct;
+	const struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 
 	ct = nf_ct_get(skb, &ctinfo);
 	if (!ct)
-		return 0;
+		return false;
 
-	return (((ct->mark) & info->mask) == info->mark) ^ info->invert;
+	return ((ct->mark & info->mask) == info->mark) ^ info->invert;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
 	   void *matchinfo,
 	   unsigned int hook_mask)
 {
-	struct xt_connmark_info *cm = matchinfo;
+	const struct xt_connmark_info *cm = matchinfo;
 
 	if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
 		printk(KERN_WARNING "connmark: only support 32bit mark\n");
-		return 0;
+		return false;
 	}
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -88,7 +88,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_connmark_info *cm = src;
+	const struct compat_xt_connmark_info *cm = src;
 	struct xt_connmark_info m = {
 		.mark	= cm->mark,
 		.mask	= cm->mask,
@@ -99,7 +99,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_connmark_info *m = src;
+	const struct xt_connmark_info *m = src;
 	struct compat_xt_connmark_info cm = {
 		.mark	= m->mark,
 		.mask	= m->mask,
@@ -109,7 +109,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_match xt_connmark_match[] = {
+static struct xt_match xt_connmark_match[] __read_mostly = {
 	{
 		.name		= "connmark",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 189ded5..ca4b69f 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -19,7 +19,7 @@
 MODULE_DESCRIPTION("iptables connection tracking match module");
 MODULE_ALIAS("ipt_conntrack");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -27,14 +27,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_conntrack_info *sinfo = matchinfo;
-	struct nf_conn *ct;
+	const struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 	unsigned int statebit;
 
-	ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
+	ct = nf_ct_get(skb, &ctinfo);
 
 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
 
@@ -54,53 +54,53 @@
 		}
 		if (FWINV((statebit & sinfo->statemask) == 0,
 			  XT_CONNTRACK_STATE))
-			return 0;
+			return false;
 	}
 
 	if (ct == NULL) {
 		if (sinfo->flags & ~XT_CONNTRACK_STATE)
-			return 0;
-		return 1;
+			return false;
+		return true;
 	}
 
 	if (sinfo->flags & XT_CONNTRACK_PROTO &&
 	    FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
 		  XT_CONNTRACK_PROTO))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_ORIGSRC &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip &
 		   sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
 		  XT_CONNTRACK_ORIGSRC))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_ORIGDST &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip &
 		   sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
 		  XT_CONNTRACK_ORIGDST))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_REPLSRC &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip &
 		   sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
 		  XT_CONNTRACK_REPLSRC))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_REPLDST &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip &
 		   sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
 		  XT_CONNTRACK_REPLDST))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_STATUS &&
 	    FWINV((ct->status & sinfo->statusmask) == 0,
 		  XT_CONNTRACK_STATUS))
-		return 0;
+		return false;
 
 	if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
 		unsigned long expires = timer_pending(&ct->timeout) ?
@@ -109,12 +109,12 @@
 		if (FWINV(!(expires >= sinfo->expires_min &&
 			    expires <= sinfo->expires_max),
 			  XT_CONNTRACK_EXPIRES))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
@@ -124,9 +124,9 @@
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static void destroy(const struct xt_match *match, void *matchinfo)
@@ -150,7 +150,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_conntrack_info *cm = src;
+	const struct compat_xt_conntrack_info *cm = src;
 	struct xt_conntrack_info m = {
 		.statemask	= cm->statemask,
 		.statusmask	= cm->statusmask,
@@ -167,7 +167,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_conntrack_info *m = src;
+	const struct xt_conntrack_info *m = src;
 	struct compat_xt_conntrack_info cm = {
 		.statemask	= m->statemask,
 		.statusmask	= m->statusmask,
@@ -183,7 +183,7 @@
 }
 #endif
 
-static struct xt_match conntrack_match = {
+static struct xt_match conntrack_match __read_mostly = {
 	.name		= "conntrack",
 	.match		= match,
 	.checkentry	= checkentry,
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 2c9c0de..83224ec 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -31,40 +31,40 @@
 static unsigned char *dccp_optbuf;
 static DEFINE_SPINLOCK(dccp_buflock);
 
-static inline int
+static inline bool
 dccp_find_option(u_int8_t option,
 		 const struct sk_buff *skb,
 		 unsigned int protoff,
 		 const struct dccp_hdr *dh,
-		 int *hotdrop)
+		 bool *hotdrop)
 {
 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
-	unsigned char *op;
+	const unsigned char *op;
 	unsigned int optoff = __dccp_hdr_len(dh);
 	unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh);
 	unsigned int i;
 
 	if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	if (!optlen)
-		return 0;
+		return false;
 
 	spin_lock_bh(&dccp_buflock);
 	op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf);
 	if (op == NULL) {
 		/* If we don't have the whole header, drop packet. */
 		spin_unlock_bh(&dccp_buflock);
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	for (i = 0; i < optlen; ) {
 		if (op[i] == option) {
 			spin_unlock_bh(&dccp_buflock);
-			return 1;
+			return true;
 		}
 
 		if (op[i] < 2)
@@ -74,24 +74,24 @@
 	}
 
 	spin_unlock_bh(&dccp_buflock);
-	return 0;
+	return false;
 }
 
 
-static inline int
+static inline bool
 match_types(const struct dccp_hdr *dh, u_int16_t typemask)
 {
-	return (typemask & (1 << dh->dccph_type));
+	return typemask & (1 << dh->dccph_type);
 }
 
-static inline int
+static inline bool
 match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
-	     const struct dccp_hdr *dh, int *hotdrop)
+	     const struct dccp_hdr *dh, bool *hotdrop)
 {
 	return dccp_find_option(option, skb, protoff, dh, hotdrop);
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -99,25 +99,25 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_dccp_info *info = matchinfo;
 	struct dccp_hdr _dh, *dh;
 
 	if (offset)
-		return 0;
+		return false;
 
 	dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
 	if (dh == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
-	return  DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
-			&& (ntohs(dh->dccph_sport) <= info->spts[1])),
+	return  DCCHECK(ntohs(dh->dccph_sport) >= info->spts[0]
+			&& ntohs(dh->dccph_sport) <= info->spts[1],
 			XT_DCCP_SRC_PORTS, info->flags, info->invflags)
-		&& DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0])
-			&& (ntohs(dh->dccph_dport) <= info->dpts[1])),
+		&& DCCHECK(ntohs(dh->dccph_dport) >= info->dpts[0]
+			&& ntohs(dh->dccph_dport) <= info->dpts[1],
 			XT_DCCP_DEST_PORTS, info->flags, info->invflags)
 		&& DCCHECK(match_types(dh, info->typemask),
 			   XT_DCCP_TYPE, info->flags, info->invflags)
@@ -126,7 +126,7 @@
 			   XT_DCCP_OPTION, info->flags, info->invflags);
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *inf,
 	   const struct xt_match *match,
@@ -140,7 +140,7 @@
 		&& !(info->invflags & ~info->flags);
 }
 
-static struct xt_match xt_dccp_match[] = {
+static struct xt_match xt_dccp_match[] __read_mostly = {
 	{
 		.name 		= "dccp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index 56b247e..dde6d66 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -22,14 +22,14 @@
 MODULE_ALIAS("ipt_dscp");
 MODULE_ALIAS("ip6t_dscp");
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in,
-		 const struct net_device *out,
-		 const struct xt_match *match,
-		 const void *matchinfo,
-		 int offset,
-		 unsigned int protoff,
-		 int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  const struct xt_match *match,
+		  const void *matchinfo,
+		  int offset,
+		  unsigned int protoff,
+		  bool *hotdrop)
 {
 	const struct xt_dscp_info *info = matchinfo;
 	u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -37,14 +37,14 @@
 	return (dscp == info->dscp) ^ !!info->invert;
 }
 
-static int match6(const struct sk_buff *skb,
-		  const struct net_device *in,
-		  const struct net_device *out,
-		  const struct xt_match *match,
-		  const void *matchinfo,
-		  int offset,
-		  unsigned int protoff,
-		  int *hotdrop)
+static bool match6(const struct sk_buff *skb,
+		   const struct net_device *in,
+		   const struct net_device *out,
+		   const struct xt_match *match,
+		   const void *matchinfo,
+		   int offset,
+		   unsigned int protoff,
+		   bool *hotdrop)
 {
 	const struct xt_dscp_info *info = matchinfo;
 	u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -52,23 +52,23 @@
 	return (dscp == info->dscp) ^ !!info->invert;
 }
 
-static int checkentry(const char *tablename,
-		      const void *info,
-		      const struct xt_match *match,
-		      void *matchinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+		       const void *info,
+		       const struct xt_match *match,
+		       void *matchinfo,
+		       unsigned int hook_mask)
 {
 	const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp;
 
 	if (dscp > XT_DSCP_MAX) {
 		printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_dscp_match[] = {
+static struct xt_match xt_dscp_match[] __read_mostly = {
 	{
 		.name		= "dscp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
index 7c95f14..b11378e 100644
--- a/net/netfilter/xt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -31,10 +31,10 @@
 #endif
 
 /* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
 {
-	int r = 0;
+	bool r;
 	duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
 		 min, spi, max);
 	r = (spi >= min && spi <= max) ^ invert;
@@ -42,7 +42,7 @@
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -50,14 +50,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	struct ip_esp_hdr _esp, *eh;
 	const struct xt_esp *espinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
 	if (eh == NULL) {
@@ -65,8 +65,8 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("Dropping evil ESP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
@@ -74,7 +74,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip_void,
 	   const struct xt_match *match,
@@ -85,13 +85,13 @@
 
 	if (espinfo->invflags & ~XT_ESP_INV_MASK) {
 		duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_esp_match[] = {
+static struct xt_match xt_esp_match[] __read_mostly = {
 	{
 		.name		= "esp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index d3043fa..d6b3d01 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -94,7 +94,8 @@
 static HLIST_HEAD(hashlimit_htables);
 static struct kmem_cache *hashlimit_cachep __read_mostly;
 
-static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
+static inline bool dst_cmp(const struct dsthash_ent *ent,
+			   const struct dsthash_dst *b)
 {
 	return !memcmp(&ent->dst, b, sizeof(ent->dst));
 }
@@ -106,7 +107,8 @@
 }
 
 static struct dsthash_ent *
-dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
+dsthash_find(const struct xt_hashlimit_htable *ht,
+	     const struct dsthash_dst *dst)
 {
 	struct dsthash_ent *ent;
 	struct hlist_node *pos;
@@ -122,7 +124,8 @@
 
 /* allocate dsthash_ent, initialize dst, put in htable and lock it */
 static struct dsthash_ent *
-dsthash_alloc_init(struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
+dsthash_alloc_init(struct xt_hashlimit_htable *ht,
+		   const struct dsthash_dst *dst)
 {
 	struct dsthash_ent *ent;
 
@@ -227,19 +230,21 @@
 	return 0;
 }
 
-static int select_all(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
+static bool select_all(const struct xt_hashlimit_htable *ht,
+		       const struct dsthash_ent *he)
 {
 	return 1;
 }
 
-static int select_gc(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
+static bool select_gc(const struct xt_hashlimit_htable *ht,
+		      const struct dsthash_ent *he)
 {
-	return (jiffies >= he->expires);
+	return jiffies >= he->expires;
 }
 
 static void htable_selective_cleanup(struct xt_hashlimit_htable *ht,
-				int (*select)(struct xt_hashlimit_htable *ht,
-					      struct dsthash_ent *he))
+			bool (*select)(const struct xt_hashlimit_htable *ht,
+				      const struct dsthash_ent *he))
 {
 	unsigned int i;
 
@@ -282,7 +287,8 @@
 	vfree(hinfo);
 }
 
-static struct xt_hashlimit_htable *htable_find_get(char *name, int family)
+static struct xt_hashlimit_htable *htable_find_get(const char *name,
+						   int family)
 {
 	struct xt_hashlimit_htable *hinfo;
 	struct hlist_node *pos;
@@ -367,7 +373,8 @@
 }
 
 static int
-hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst,
+hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
+		   struct dsthash_dst *dst,
 		   const struct sk_buff *skb, unsigned int protoff)
 {
 	__be16 _ports[2], *ports;
@@ -432,7 +439,7 @@
 	return 0;
 }
 
-static int
+static bool
 hashlimit_match(const struct sk_buff *skb,
 		const struct net_device *in,
 		const struct net_device *out,
@@ -440,10 +447,10 @@
 		const void *matchinfo,
 		int offset,
 		unsigned int protoff,
-		int *hotdrop)
+		bool *hotdrop)
 {
-	struct xt_hashlimit_info *r =
-		((struct xt_hashlimit_info *)matchinfo)->u.master;
+	const struct xt_hashlimit_info *r =
+		((const struct xt_hashlimit_info *)matchinfo)->u.master;
 	struct xt_hashlimit_htable *hinfo = r->hinfo;
 	unsigned long now = jiffies;
 	struct dsthash_ent *dh;
@@ -478,20 +485,20 @@
 		/* We're underlimit. */
 		dh->rateinfo.credit -= dh->rateinfo.cost;
 		spin_unlock_bh(&hinfo->lock);
-		return 1;
+		return true;
 	}
 
 	spin_unlock_bh(&hinfo->lock);
 
 	/* default case: we're overlimit, thus don't match */
-	return 0;
+	return false;
 
 hotdrop:
-	*hotdrop = 1;
-	return 0;
+	*hotdrop = true;
+	return false;
 }
 
-static int
+static bool
 hashlimit_checkentry(const char *tablename,
 		     const void *inf,
 		     const struct xt_match *match,
@@ -505,20 +512,20 @@
 	    user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
 		printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
 		       r->cfg.avg, r->cfg.burst);
-		return 0;
+		return false;
 	}
 	if (r->cfg.mode == 0 ||
 	    r->cfg.mode > (XT_HASHLIMIT_HASH_DPT |
 			   XT_HASHLIMIT_HASH_DIP |
 			   XT_HASHLIMIT_HASH_SIP |
 			   XT_HASHLIMIT_HASH_SPT))
-		return 0;
+		return false;
 	if (!r->cfg.gc_interval)
-		return 0;
+		return false;
 	if (!r->cfg.expire)
-		return 0;
+		return false;
 	if (r->name[sizeof(r->name) - 1] != '\0')
-		return 0;
+		return false;
 
 	/* This is the best we've got: We cannot release and re-grab lock,
 	 * since checkentry() is called before x_tables.c grabs xt_mutex.
@@ -530,19 +537,19 @@
 	r->hinfo = htable_find_get(r->name, match->family);
 	if (!r->hinfo && htable_create(r, match->family) != 0) {
 		mutex_unlock(&hlimit_mutex);
-		return 0;
+		return false;
 	}
 	mutex_unlock(&hlimit_mutex);
 
 	/* Ugly hack: For SMP, we only want to use one set */
 	r->u.master = r;
-	return 1;
+	return true;
 }
 
 static void
 hashlimit_destroy(const struct xt_match *match, void *matchinfo)
 {
-	struct xt_hashlimit_info *r = matchinfo;
+	const struct xt_hashlimit_info *r = matchinfo;
 
 	htable_put(r->hinfo);
 }
@@ -571,7 +578,7 @@
 }
 #endif
 
-static struct xt_match xt_hashlimit[] = {
+static struct xt_match xt_hashlimit[] __read_mostly = {
 	{
 		.name		= "hashlimit",
 		.family		= AF_INET,
@@ -694,7 +701,7 @@
 	return 0;
 }
 
-static struct seq_operations dl_seq_ops = {
+static const struct seq_operations dl_seq_ops = {
 	.start = dl_seq_start,
 	.next  = dl_seq_next,
 	.stop  = dl_seq_stop,
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index c139b2f..0a1f4c6 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -22,13 +22,8 @@
 MODULE_ALIAS("ipt_helper");
 MODULE_ALIAS("ip6t_helper");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -36,61 +31,51 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_helper_info *info = matchinfo;
-	struct nf_conn *ct;
-	struct nf_conn_help *master_help;
+	const struct nf_conn *ct;
+	const struct nf_conn_help *master_help;
+	const struct nf_conntrack_helper *helper;
 	enum ip_conntrack_info ctinfo;
-	int ret = info->invert;
+	bool ret = info->invert;
 
-	ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
-	if (!ct) {
-		DEBUGP("xt_helper: Eek! invalid conntrack?\n");
+	ct = nf_ct_get(skb, &ctinfo);
+	if (!ct || !ct->master)
 		return ret;
-	}
 
-	if (!ct->master) {
-		DEBUGP("xt_helper: conntrack %p has no master\n", ct);
-		return ret;
-	}
-
-	read_lock_bh(&nf_conntrack_lock);
 	master_help = nfct_help(ct->master);
-	if (!master_help || !master_help->helper) {
-		DEBUGP("xt_helper: master ct %p has no helper\n",
-			exp->expectant);
-		goto out_unlock;
-	}
+	if (!master_help)
+		return ret;
 
-	DEBUGP("master's name = %s , info->name = %s\n",
-		ct->master->helper->name, info->name);
+	/* rcu_read_lock()ed by nf_hook_slow */
+	helper = rcu_dereference(master_help->helper);
+	if (!helper)
+		return ret;
 
 	if (info->name[0] == '\0')
-		ret ^= 1;
+		ret = !ret;
 	else
 		ret ^= !strncmp(master_help->helper->name, info->name,
 				strlen(master_help->helper->name));
-out_unlock:
-	read_unlock_bh(&nf_conntrack_lock);
 	return ret;
 }
 
-static int check(const char *tablename,
-		 const void *inf,
-		 const struct xt_match *match,
-		 void *matchinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *inf,
+		  const struct xt_match *match,
+		  void *matchinfo,
+		  unsigned int hook_mask)
 {
 	struct xt_helper_info *info = matchinfo;
 
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
 	info->name[29] = '\0';
-	return 1;
+	return true;
 }
 
 static void
@@ -99,7 +84,7 @@
 	nf_ct_l3proto_module_put(match->family);
 }
 
-static struct xt_match xt_helper_match[] = {
+static struct xt_match xt_helper_match[] __read_mostly = {
 	{
 		.name		= "helper",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 77288c5..3dad173 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -20,7 +20,7 @@
 MODULE_ALIAS("ipt_length");
 MODULE_ALIAS("ip6t_length");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -28,7 +28,7 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_length_info *info = matchinfo;
 	u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len);
@@ -36,7 +36,7 @@
 	return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
 }
 
-static int
+static bool
 match6(const struct sk_buff *skb,
        const struct net_device *in,
        const struct net_device *out,
@@ -44,16 +44,16 @@
        const void *matchinfo,
        int offset,
        unsigned int protoff,
-       int *hotdrop)
+       bool *hotdrop)
 {
 	const struct xt_length_info *info = matchinfo;
-	const u_int16_t pktlen = (ntohs(ipv6_hdr(skb)->payload_len) +
-				  sizeof(struct ipv6hdr));
+	const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) +
+				 sizeof(struct ipv6hdr);
 
 	return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
 }
 
-static struct xt_match xt_length_match[] = {
+static struct xt_match xt_length_match[] __read_mostly = {
 	{
 		.name		= "length",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 571a72a..4fcca79 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -57,7 +57,7 @@
 
 #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
 
-static int
+static bool
 ipt_limit_match(const struct sk_buff *skb,
 		const struct net_device *in,
 		const struct net_device *out,
@@ -65,9 +65,10 @@
 		const void *matchinfo,
 		int offset,
 		unsigned int protoff,
-		int *hotdrop)
+		bool *hotdrop)
 {
-	struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master;
+	struct xt_rateinfo *r =
+		((const struct xt_rateinfo *)matchinfo)->master;
 	unsigned long now = jiffies;
 
 	spin_lock_bh(&limit_lock);
@@ -79,11 +80,11 @@
 		/* We're not limited. */
 		r->credit -= r->cost;
 		spin_unlock_bh(&limit_lock);
-		return 1;
+		return true;
 	}
 
 	spin_unlock_bh(&limit_lock);
-	return 0;
+	return false;
 }
 
 /* Precision saver. */
@@ -98,7 +99,7 @@
 	return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
 }
 
-static int
+static bool
 ipt_limit_checkentry(const char *tablename,
 		     const void *inf,
 		     const struct xt_match *match,
@@ -112,7 +113,7 @@
 	    || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
 		printk("Overflow in xt_limit, try lower: %u/%u\n",
 		       r->avg, r->burst);
-		return 0;
+		return false;
 	}
 
 	/* For SMP, we only want to use one set of counters. */
@@ -125,7 +126,7 @@
 		r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
 		r->cost = user2credits(r->avg);
 	}
-	return 1;
+	return true;
 }
 
 #ifdef CONFIG_COMPAT
@@ -144,7 +145,7 @@
  * master pointer, which does not need to be preserved. */
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_rateinfo *cm = src;
+	const struct compat_xt_rateinfo *cm = src;
 	struct xt_rateinfo m = {
 		.avg		= cm->avg,
 		.burst		= cm->burst,
@@ -158,7 +159,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_rateinfo *m = src;
+	const struct xt_rateinfo *m = src;
 	struct compat_xt_rateinfo cm = {
 		.avg		= m->avg,
 		.burst		= m->burst,
@@ -172,7 +173,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_match xt_limit_match[] = {
+static struct xt_match xt_limit_match[] __read_mostly = {
 	{
 		.name		= "limit",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 1d3a1d9..00490d7 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -24,7 +24,7 @@
 MODULE_ALIAS("ipt_mac");
 MODULE_ALIAS("ip6t_mac");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -32,19 +32,19 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
     const struct xt_mac_info *info = matchinfo;
 
     /* Is mac pointer valid? */
-    return (skb_mac_header(skb) >= skb->head &&
-	    (skb_mac_header(skb) + ETH_HLEN) <= skb->data
-	    /* If so, compare... */
-	    && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
-		^ info->invert));
+    return skb_mac_header(skb) >= skb->head &&
+	   skb_mac_header(skb) + ETH_HLEN <= skb->data
+	   /* If so, compare... */
+	   && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
+		^ info->invert);
 }
 
-static struct xt_match xt_mac_match[] = {
+static struct xt_match xt_mac_match[] __read_mostly = {
 	{
 		.name		= "mac",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 39911dd..c02a7f8 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -19,7 +19,7 @@
 MODULE_ALIAS("ipt_mark");
 MODULE_ALIAS("ip6t_mark");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -27,14 +27,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_mark_info *info = matchinfo;
 
 	return ((skb->mark & info->mask) == info->mark) ^ info->invert;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_match *match,
@@ -45,9 +45,9 @@
 
 	if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
 		printk(KERN_WARNING "mark: only supports 32bit mark\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 #ifdef CONFIG_COMPAT
@@ -60,7 +60,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_mark_info *cm = src;
+	const struct compat_xt_mark_info *cm = src;
 	struct xt_mark_info m = {
 		.mark	= cm->mark,
 		.mask	= cm->mask,
@@ -71,7 +71,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_mark_info *m = src;
+	const struct xt_mark_info *m = src;
 	struct compat_xt_mark_info cm = {
 		.mark	= m->mark,
 		.mask	= m->mask,
@@ -81,7 +81,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_match xt_mark_match[] = {
+static struct xt_match xt_mark_match[] __read_mostly = {
 	{
 		.name		= "mark",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index 4dce2a8..e8ae102 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -33,24 +33,24 @@
 #endif
 
 /* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
+static inline bool
 ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
 	    u_int8_t count, u_int16_t src, u_int16_t dst)
 {
 	unsigned int i;
 	for (i = 0; i < count; i++) {
 		if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
-			return 1;
+			return true;
 
 		if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
-			return 1;
+			return true;
 	}
 
-	return 0;
+	return false;
 }
 
 /* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
+static inline bool
 ports_match_v1(const struct xt_multiport_v1 *minfo,
 	       u_int16_t src, u_int16_t dst)
 {
@@ -67,34 +67,34 @@
 
 			if (minfo->flags == XT_MULTIPORT_SOURCE
 			    && src >= s && src <= e)
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 			if (minfo->flags == XT_MULTIPORT_DESTINATION
 			    && dst >= s && dst <= e)
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 			if (minfo->flags == XT_MULTIPORT_EITHER
 			    && ((dst >= s && dst <= e)
 				|| (src >= s && src <= e)))
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 		} else {
 			/* exact port matching */
 			duprintf("src or dst matches with %d?\n", s);
 
 			if (minfo->flags == XT_MULTIPORT_SOURCE
 			    && src == s)
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 			if (minfo->flags == XT_MULTIPORT_DESTINATION
 			    && dst == s)
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 			if (minfo->flags == XT_MULTIPORT_EITHER
 			    && (src == s || dst == s))
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 		}
 	}
 
 	return minfo->invert;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -102,13 +102,13 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	__be16 _ports[2], *pptr;
 	const struct xt_multiport *multiinfo = matchinfo;
 
 	if (offset)
-		return 0;
+		return false;
 
 	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
 	if (pptr == NULL) {
@@ -116,8 +116,8 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return ports_match(multiinfo->ports,
@@ -125,7 +125,7 @@
 			   ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
-static int
+static bool
 match_v1(const struct sk_buff *skb,
 	 const struct net_device *in,
 	 const struct net_device *out,
@@ -133,13 +133,13 @@
 	 const void *matchinfo,
 	 int offset,
 	 unsigned int protoff,
-	 int *hotdrop)
+	 bool *hotdrop)
 {
 	__be16 _ports[2], *pptr;
 	const struct xt_multiport_v1 *multiinfo = matchinfo;
 
 	if (offset)
-		return 0;
+		return false;
 
 	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
 	if (pptr == NULL) {
@@ -147,14 +147,14 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
-static inline int
+static inline bool
 check(u_int16_t proto,
       u_int8_t ip_invflags,
       u_int8_t match_flags,
@@ -172,7 +172,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *info,
 	   const struct xt_match *match,
@@ -186,7 +186,7 @@
 		     multiinfo->count);
 }
 
-static int
+static bool
 checkentry_v1(const char *tablename,
 	      const void *info,
 	      const struct xt_match *match,
@@ -200,7 +200,7 @@
 		     multiinfo->count);
 }
 
-static int
+static bool
 checkentry6(const char *tablename,
 	    const void *info,
 	    const struct xt_match *match,
@@ -214,7 +214,7 @@
 		     multiinfo->count);
 }
 
-static int
+static bool
 checkentry6_v1(const char *tablename,
 	       const void *info,
 	       const struct xt_match *match,
@@ -228,7 +228,7 @@
 		     multiinfo->count);
 }
 
-static struct xt_match xt_multiport_match[] = {
+static struct xt_match xt_multiport_match[] __read_mostly = {
 	{
 		.name		= "multiport",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 35a0fe2..f47cab7a6 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -14,8 +14,6 @@
 #include <linux/netfilter/xt_physdev.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_bridge.h>
-#define MATCH   1
-#define NOMATCH 0
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
@@ -23,7 +21,7 @@
 MODULE_ALIAS("ipt_physdev");
 MODULE_ALIAS("ip6t_physdev");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -31,14 +29,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	int i;
 	static const char nulldevname[IFNAMSIZ];
 	const struct xt_physdev_info *info = matchinfo;
-	unsigned int ret;
+	bool ret;
 	const char *indev, *outdev;
-	struct nf_bridge_info *nf_bridge;
+	const struct nf_bridge_info *nf_bridge;
 
 	/* Not a bridged IP packet or no info available yet:
 	 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
@@ -47,61 +45,61 @@
 		/* Return MATCH if the invert flags of the used options are on */
 		if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
 		    !(info->invert & XT_PHYSDEV_OP_BRIDGED))
-			return NOMATCH;
+			return false;
 		if ((info->bitmask & XT_PHYSDEV_OP_ISIN) &&
 		    !(info->invert & XT_PHYSDEV_OP_ISIN))
-			return NOMATCH;
+			return false;
 		if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) &&
 		    !(info->invert & XT_PHYSDEV_OP_ISOUT))
-			return NOMATCH;
+			return false;
 		if ((info->bitmask & XT_PHYSDEV_OP_IN) &&
 		    !(info->invert & XT_PHYSDEV_OP_IN))
-			return NOMATCH;
+			return false;
 		if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
 		    !(info->invert & XT_PHYSDEV_OP_OUT))
-			return NOMATCH;
-		return MATCH;
+			return false;
+		return true;
 	}
 
 	/* This only makes sense in the FORWARD and POSTROUTING chains */
 	if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
 	    (!!(nf_bridge->mask & BRNF_BRIDGED) ^
 	    !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
-		return NOMATCH;
+		return false;
 
 	if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
 	    (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
 	    (info->bitmask & XT_PHYSDEV_OP_ISOUT &&
 	    (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
-		return NOMATCH;
+		return false;
 
 	if (!(info->bitmask & XT_PHYSDEV_OP_IN))
 		goto match_outdev;
 	indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
-	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+	for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) {
 		ret |= (((const unsigned int *)indev)[i]
 			^ ((const unsigned int *)info->physindev)[i])
 			& ((const unsigned int *)info->in_mask)[i];
 	}
 
-	if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN))
-		return NOMATCH;
+	if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN))
+		return false;
 
 match_outdev:
 	if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
-		return MATCH;
+		return true;
 	outdev = nf_bridge->physoutdev ?
 		 nf_bridge->physoutdev->name : nulldevname;
-	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+	for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) {
 		ret |= (((const unsigned int *)outdev)[i]
 			^ ((const unsigned int *)info->physoutdev)[i])
 			& ((const unsigned int *)info->out_mask)[i];
 	}
 
-	return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
+	return ret ^ !(info->invert & XT_PHYSDEV_OP_OUT);
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 		       const void *ip,
 		       const struct xt_match *match,
@@ -112,7 +110,7 @@
 
 	if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
 	    info->bitmask & ~XT_PHYSDEV_OP_MASK)
-		return 0;
+		return false;
 	if (info->bitmask & XT_PHYSDEV_OP_OUT &&
 	    (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
 	     info->invert & XT_PHYSDEV_OP_BRIDGED) &&
@@ -122,12 +120,12 @@
 		       "OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
 		       "traffic is not supported anymore.\n");
 		if (hook_mask & (1 << NF_IP_LOCAL_OUT))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_physdev_match[] = {
+static struct xt_match xt_physdev_match[] __read_mostly = {
 	{
 		.name		= "physdev",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index e1409fc..a52925f 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -21,29 +21,29 @@
 MODULE_ALIAS("ipt_pkttype");
 MODULE_ALIAS("ip6t_pkttype");
 
-static int match(const struct sk_buff *skb,
+static bool match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
       const struct xt_match *match,
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	u_int8_t type;
 	const struct xt_pkttype_info *info = matchinfo;
 
 	if (skb->pkt_type == PACKET_LOOPBACK)
-		type = (MULTICAST(ip_hdr(skb)->daddr)
+		type = MULTICAST(ip_hdr(skb)->daddr)
 			? PACKET_MULTICAST
-			: PACKET_BROADCAST);
+			: PACKET_BROADCAST;
 	else
 		type = skb->pkt_type;
 
 	return (type == info->pkttype) ^ info->invert;
 }
 
-static struct xt_match xt_pkttype_match[] = {
+static struct xt_match xt_pkttype_match[] __read_mostly = {
 	{
 		.name		= "pkttype",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 15b45a9..6d6d3b7 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -20,7 +20,7 @@
 MODULE_DESCRIPTION("Xtables IPsec policy matching module");
 MODULE_LICENSE("GPL");
 
-static inline int
+static inline bool
 xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m,
 	    const union xt_policy_addr *a2, unsigned short family)
 {
@@ -30,11 +30,11 @@
 	case AF_INET6:
 		return !ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6);
 	}
-	return 0;
+	return false;
 }
 
-static inline int
-match_xfrm_state(struct xfrm_state *x, const struct xt_policy_elem *e,
+static inline bool
+match_xfrm_state(const struct xfrm_state *x, const struct xt_policy_elem *e,
 		 unsigned short family)
 {
 #define MATCH_ADDR(x,y,z)	(!e->match.x ||			       \
@@ -55,7 +55,7 @@
 		unsigned short family)
 {
 	const struct xt_policy_elem *e;
-	struct sec_path *sp = skb->sp;
+	const struct sec_path *sp = skb->sp;
 	int strict = info->flags & XT_POLICY_MATCH_STRICT;
 	int i, pos;
 
@@ -85,7 +85,7 @@
 		 unsigned short family)
 {
 	const struct xt_policy_elem *e;
-	struct dst_entry *dst = skb->dst;
+	const struct dst_entry *dst = skb->dst;
 	int strict = info->flags & XT_POLICY_MATCH_STRICT;
 	int i, pos;
 
@@ -108,14 +108,14 @@
 	return strict ? i == info->len : 0;
 }
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in,
-		 const struct net_device *out,
-		 const struct xt_match *match,
-		 const void *matchinfo,
-		 int offset,
-		 unsigned int protoff,
-		 int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  const struct xt_match *match,
+		  const void *matchinfo,
+		  int offset,
+		  unsigned int protoff,
+		  bool *hotdrop)
 {
 	const struct xt_policy_info *info = matchinfo;
 	int ret;
@@ -126,45 +126,45 @@
 		ret = match_policy_out(skb, info, match->family);
 
 	if (ret < 0)
-		ret = info->flags & XT_POLICY_MATCH_NONE ? 1 : 0;
+		ret = info->flags & XT_POLICY_MATCH_NONE ? true : false;
 	else if (info->flags & XT_POLICY_MATCH_NONE)
-		ret = 0;
+		ret = false;
 
 	return ret;
 }
 
-static int checkentry(const char *tablename, const void *ip_void,
-		      const struct xt_match *match,
-		      void *matchinfo, unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *ip_void,
+		       const struct xt_match *match,
+		       void *matchinfo, unsigned int hook_mask)
 {
 	struct xt_policy_info *info = matchinfo;
 
 	if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
 		printk(KERN_ERR "xt_policy: neither incoming nor "
 				"outgoing policy selected\n");
-		return 0;
+		return false;
 	}
 	/* hook values are equal for IPv4 and IPv6 */
 	if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
 	    && info->flags & XT_POLICY_MATCH_OUT) {
 		printk(KERN_ERR "xt_policy: output policy not valid in "
 				"PRE_ROUTING and INPUT\n");
-		return 0;
+		return false;
 	}
 	if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
 	    && info->flags & XT_POLICY_MATCH_IN) {
 		printk(KERN_ERR "xt_policy: input policy not valid in "
 				"POST_ROUTING and OUTPUT\n");
-		return 0;
+		return false;
 	}
 	if (info->len > XT_POLICY_MAX_ELEM) {
 		printk(KERN_ERR "xt_policy: too many policy elements\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_policy_match[] = {
+static struct xt_match xt_policy_match[] __read_mostly = {
 	{
 		.name		= "policy",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index bfdde06..dae9744 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -16,19 +16,20 @@
 
 static DEFINE_SPINLOCK(quota_lock);
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in, const struct net_device *out,
       const struct xt_match *match, const void *matchinfo,
-      int offset, unsigned int protoff, int *hotdrop)
+      int offset, unsigned int protoff, bool *hotdrop)
 {
-	struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master;
-	int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0;
+	struct xt_quota_info *q =
+		((const struct xt_quota_info *)matchinfo)->master;
+	bool ret = q->flags & XT_QUOTA_INVERT;
 
 	spin_lock_bh(&quota_lock);
 	if (q->quota >= skb->len) {
 		q->quota -= skb->len;
-		ret ^= 1;
+		ret = !ret;
 	} else {
 		/* we do not allow even small packets from now on */
 		q->quota = 0;
@@ -38,21 +39,21 @@
 	return ret;
 }
 
-static int
+static bool
 checkentry(const char *tablename, const void *entry,
 	   const struct xt_match *match, void *matchinfo,
 	   unsigned int hook_mask)
 {
-	struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
+	struct xt_quota_info *q = matchinfo;
 
 	if (q->flags & ~XT_QUOTA_MASK)
-		return 0;
+		return false;
 	/* For SMP, we only want to use one set of counters. */
 	q->master = q;
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_quota_match[] = {
+static struct xt_match xt_quota_match[] __read_mostly = {
 	{
 		.name		= "quota",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index c2017f8..cc3e76d 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -21,7 +21,7 @@
 MODULE_DESCRIPTION("X_tables realm match");
 MODULE_ALIAS("ipt_realm");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -29,15 +29,15 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_realm_info *info = matchinfo;
-	struct dst_entry *dst = skb->dst;
+	const struct dst_entry *dst = skb->dst;
 
 	return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
 }
 
-static struct xt_match realm_match = {
+static struct xt_match realm_match __read_mostly = {
 	.name		= "realm",
 	.match		= match,
 	.matchsize	= sizeof(struct xt_realm_info),
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index f86d8d7..c002153 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -23,7 +23,7 @@
 #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
 					      || (!!((invflag) & (option)) ^ (cond)))
 
-static int
+static bool
 match_flags(const struct xt_sctp_flag_info *flag_info,
 	    const int flag_count,
 	    u_int8_t chunktype,
@@ -31,23 +31,21 @@
 {
 	int i;
 
-	for (i = 0; i < flag_count; i++) {
-		if (flag_info[i].chunktype == chunktype) {
+	for (i = 0; i < flag_count; i++)
+		if (flag_info[i].chunktype == chunktype)
 			return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
-		}
-	}
 
-	return 1;
+	return true;
 }
 
-static inline int
+static inline bool
 match_packet(const struct sk_buff *skb,
 	     unsigned int offset,
 	     const u_int32_t *chunkmap,
 	     int chunk_match_type,
 	     const struct xt_sctp_flag_info *flag_info,
 	     const int flag_count,
-	     int *hotdrop)
+	     bool *hotdrop)
 {
 	u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
 	sctp_chunkhdr_t _sch, *sch;
@@ -56,16 +54,15 @@
 	int i = 0;
 #endif
 
-	if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
+	if (chunk_match_type == SCTP_CHUNK_MATCH_ALL)
 		SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
-	}
 
 	do {
 		sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
 		if (sch == NULL || sch->length == 0) {
 			duprintf("Dropping invalid SCTP packet.\n");
-			*hotdrop = 1;
-			return 0;
+			*hotdrop = true;
+			return false;
 		}
 
 		duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
@@ -80,28 +77,26 @@
 			case SCTP_CHUNK_MATCH_ANY:
 				if (match_flags(flag_info, flag_count,
 					sch->type, sch->flags)) {
-					return 1;
+					return true;
 				}
 				break;
 
 			case SCTP_CHUNK_MATCH_ALL:
 				if (match_flags(flag_info, flag_count,
-					sch->type, sch->flags)) {
+				    sch->type, sch->flags))
 					SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
-				}
 				break;
 
 			case SCTP_CHUNK_MATCH_ONLY:
 				if (!match_flags(flag_info, flag_count,
-					sch->type, sch->flags)) {
-					return 0;
-				}
+				    sch->type, sch->flags))
+					return false;
 				break;
 			}
 		} else {
 			switch (chunk_match_type) {
 			case SCTP_CHUNK_MATCH_ONLY:
-				return 0;
+				return false;
 			}
 		}
 	} while (offset < skb->len);
@@ -110,16 +105,16 @@
 	case SCTP_CHUNK_MATCH_ALL:
 		return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
 	case SCTP_CHUNK_MATCH_ANY:
-		return 0;
+		return false;
 	case SCTP_CHUNK_MATCH_ONLY:
-		return 1;
+		return true;
 	}
 
 	/* This will never be reached, but required to stop compiler whine */
-	return 0;
+	return false;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -127,29 +122,29 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_sctp_info *info = matchinfo;
 	sctp_sctphdr_t _sh, *sh;
 
 	if (offset) {
 		duprintf("Dropping non-first fragment.. FIXME\n");
-		return 0;
+		return false;
 	}
 
 	sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
 	if (sh == NULL) {
 		duprintf("Dropping evil TCP offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 	duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
 
-	return  SCCHECK(((ntohs(sh->source) >= info->spts[0])
-			&& (ntohs(sh->source) <= info->spts[1])),
+	return  SCCHECK(ntohs(sh->source) >= info->spts[0]
+			&& ntohs(sh->source) <= info->spts[1],
 			XT_SCTP_SRC_PORTS, info->flags, info->invflags)
-		&& SCCHECK(((ntohs(sh->dest) >= info->dpts[0])
-			&& (ntohs(sh->dest) <= info->dpts[1])),
+		&& SCCHECK(ntohs(sh->dest) >= info->dpts[0]
+			&& ntohs(sh->dest) <= info->dpts[1],
 			XT_SCTP_DEST_PORTS, info->flags, info->invflags)
 		&& SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t),
 					info->chunkmap, info->chunk_match_type,
@@ -158,7 +153,7 @@
 			   XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *inf,
 	   const struct xt_match *match,
@@ -177,7 +172,7 @@
 				| SCTP_CHUNK_MATCH_ONLY)));
 }
 
-static struct xt_match xt_sctp_match[] = {
+static struct xt_match xt_sctp_match[] __read_mostly = {
 	{
 		.name		= "sctp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index 149294f..e0a528d 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -20,7 +20,7 @@
 MODULE_ALIAS("ipt_state");
 MODULE_ALIAS("ip6t_state");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -28,7 +28,7 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_state_info *sinfo = matchinfo;
 	enum ip_conntrack_info ctinfo;
@@ -44,18 +44,18 @@
 	return (sinfo->statemask & statebit);
 }
 
-static int check(const char *tablename,
-		 const void *inf,
-		 const struct xt_match *match,
-		 void *matchinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *inf,
+		  const struct xt_match *match,
+		  void *matchinfo,
+		  unsigned int hook_mask)
 {
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -64,7 +64,7 @@
 	nf_ct_l3proto_module_put(match->family);
 }
 
-static struct xt_match xt_state_match[] = {
+static struct xt_match xt_state_match[] __read_mostly = {
 	{
 		.name		= "state",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
index 091a9f8..4089dae 100644
--- a/net/netfilter/xt_statistic.c
+++ b/net/netfilter/xt_statistic.c
@@ -24,26 +24,26 @@
 
 static DEFINE_SPINLOCK(nth_lock);
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in, const struct net_device *out,
       const struct xt_match *match, const void *matchinfo,
-      int offset, unsigned int protoff, int *hotdrop)
+      int offset, unsigned int protoff, bool *hotdrop)
 {
 	struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
-	int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0;
+	bool ret = info->flags & XT_STATISTIC_INVERT;
 
 	switch (info->mode) {
 	case XT_STATISTIC_MODE_RANDOM:
 		if ((net_random() & 0x7FFFFFFF) < info->u.random.probability)
-			ret ^= 1;
+			ret = !ret;
 		break;
 	case XT_STATISTIC_MODE_NTH:
 		info = info->master;
 		spin_lock_bh(&nth_lock);
 		if (info->u.nth.count++ == info->u.nth.every) {
 			info->u.nth.count = 0;
-			ret ^= 1;
+			ret = !ret;
 		}
 		spin_unlock_bh(&nth_lock);
 		break;
@@ -52,21 +52,21 @@
 	return ret;
 }
 
-static int
+static bool
 checkentry(const char *tablename, const void *entry,
 	   const struct xt_match *match, void *matchinfo,
 	   unsigned int hook_mask)
 {
-	struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+	struct xt_statistic_info *info = matchinfo;
 
 	if (info->mode > XT_STATISTIC_MODE_MAX ||
 	    info->flags & ~XT_STATISTIC_MASK)
-		return 0;
+		return false;
 	info->master = info;
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_statistic_match[] = {
+static struct xt_match xt_statistic_match[] __read_mostly = {
 	{
 		.name		= "statistic",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 999a005..8641334 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -21,14 +21,14 @@
 MODULE_ALIAS("ipt_string");
 MODULE_ALIAS("ip6t_string");
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in,
-		 const struct net_device *out,
-		 const struct xt_match *match,
-		 const void *matchinfo,
-		 int offset,
-		 unsigned int protoff,
-		 int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  const struct xt_match *match,
+		  const void *matchinfo,
+		  int offset,
+		  unsigned int protoff,
+		  bool *hotdrop)
 {
 	const struct xt_string_info *conf = matchinfo;
 	struct ts_state state;
@@ -42,30 +42,30 @@
 
 #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
 
-static int checkentry(const char *tablename,
-		      const void *ip,
-		      const struct xt_match *match,
-		      void *matchinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+		       const void *ip,
+		       const struct xt_match *match,
+		       void *matchinfo,
+		       unsigned int hook_mask)
 {
 	struct xt_string_info *conf = matchinfo;
 	struct ts_config *ts_conf;
 
 	/* Damn, can't handle this case properly with iptables... */
 	if (conf->from_offset > conf->to_offset)
-		return 0;
+		return false;
 	if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0')
-		return 0;
+		return false;
 	if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE)
-		return 0;
+		return false;
 	ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
 				     GFP_KERNEL, TS_AUTOLOAD);
 	if (IS_ERR(ts_conf))
-		return 0;
+		return false;
 
 	conf->config = ts_conf;
 
-	return 1;
+	return true;
 }
 
 static void destroy(const struct xt_match *match, void *matchinfo)
@@ -73,7 +73,7 @@
 	textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
 }
 
-static struct xt_match xt_string_match[] = {
+static struct xt_match xt_string_match[] __read_mostly = {
 	{
 		.name 		= "string",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 80571d0..cd5f6d7 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -23,7 +23,7 @@
 MODULE_DESCRIPTION("iptables TCP MSS match module");
 MODULE_ALIAS("ipt_tcpmss");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -31,7 +31,7 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_tcpmss_match_info *info = matchinfo;
 	struct tcphdr _tcph, *th;
@@ -77,11 +77,11 @@
 	return info->invert;
 
 dropit:
-	*hotdrop = 1;
-	return 0;
+	*hotdrop = true;
+	return false;
 }
 
-static struct xt_match xt_tcpmss_match[] = {
+static struct xt_match xt_tcpmss_match[] __read_mostly = {
 	{
 		.name		= "tcpmss",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 46414b5..ab7d845 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -27,22 +27,19 @@
 
 
 /* Returns 1 if the port is matched by the range, 0 otherwise */
-static inline int
-port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
+static inline bool
+port_match(u_int16_t min, u_int16_t max, u_int16_t port, bool invert)
 {
-	int ret;
-
-	ret = (port >= min && port <= max) ^ invert;
-	return ret;
+	return (port >= min && port <= max) ^ invert;
 }
 
-static int
+static bool
 tcp_find_option(u_int8_t option,
 		const struct sk_buff *skb,
 		unsigned int protoff,
 		unsigned int optlen,
-		int invert,
-		int *hotdrop)
+		bool invert,
+		bool *hotdrop)
 {
 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
 	u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
@@ -57,8 +54,8 @@
 	op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr),
 				optlen, _opt);
 	if (op == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	for (i = 0; i < optlen; ) {
@@ -70,7 +67,7 @@
 	return invert;
 }
 
-static int
+static bool
 tcp_match(const struct sk_buff *skb,
 	  const struct net_device *in,
 	  const struct net_device *out,
@@ -78,7 +75,7 @@
 	  const void *matchinfo,
 	  int offset,
 	  unsigned int protoff,
-	  int *hotdrop)
+	  bool *hotdrop)
 {
 	struct tcphdr _tcph, *th;
 	const struct xt_tcp *tcpinfo = matchinfo;
@@ -92,51 +89,51 @@
 		*/
 		if (offset == 1) {
 			duprintf("Dropping evil TCP offset=1 frag.\n");
-			*hotdrop = 1;
+			*hotdrop = true;
 		}
 		/* Must not be a fragment. */
-		return 0;
+		return false;
 	}
 
-#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
+#define FWINVTCP(bool, invflg) ((bool) ^ !!(tcpinfo->invflags & (invflg)))
 
 	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
 	if (th == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil TCP offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
 			ntohs(th->source),
 			!!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
-		return 0;
+		return false;
 	if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
 			ntohs(th->dest),
 			!!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
-		return 0;
+		return false;
 	if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
 		      == tcpinfo->flg_cmp,
 		      XT_TCP_INV_FLAGS))
-		return 0;
+		return false;
 	if (tcpinfo->option) {
 		if (th->doff * 4 < sizeof(_tcph)) {
-			*hotdrop = 1;
-			return 0;
+			*hotdrop = true;
+			return false;
 		}
 		if (!tcp_find_option(tcpinfo->option, skb, protoff,
 				     th->doff*4 - sizeof(_tcph),
 				     tcpinfo->invflags & XT_TCP_INV_OPTION,
 				     hotdrop))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 tcp_checkentry(const char *tablename,
 	       const void *info,
 	       const struct xt_match *match,
@@ -149,7 +146,7 @@
 	return !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
 }
 
-static int
+static bool
 udp_match(const struct sk_buff *skb,
 	  const struct net_device *in,
 	  const struct net_device *out,
@@ -157,22 +154,22 @@
 	  const void *matchinfo,
 	  int offset,
 	  unsigned int protoff,
-	  int *hotdrop)
+	  bool *hotdrop)
 {
 	struct udphdr _udph, *uh;
 	const struct xt_udp *udpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
 	if (uh == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil UDP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return port_match(udpinfo->spts[0], udpinfo->spts[1],
@@ -184,7 +181,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 udp_checkentry(const char *tablename,
 	       const void *info,
 	       const struct xt_match *match,
@@ -197,7 +194,7 @@
 	return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
 }
 
-static struct xt_match xt_tcpudp_match[] = {
+static struct xt_match xt_tcpudp_match[] __read_mostly = {
 	{
 		.name		= "tcp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c
new file mode 100644
index 0000000..04b677a
--- /dev/null
+++ b/net/netfilter/xt_u32.c
@@ -0,0 +1,135 @@
+/*
+ *	xt_u32 - kernel module to match u32 packet content
+ *
+ *	Original author: Don Cohen <don@isis.cs3-inc.com>
+ *	© Jan Engelhardt <jengelh@gmx.de>, 2007
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_u32.h>
+
+static bool u32_match_it(const struct xt_u32 *data,
+			 const struct sk_buff *skb)
+{
+	const struct xt_u32_test *ct;
+	unsigned int testind;
+	unsigned int nnums;
+	unsigned int nvals;
+	unsigned int i;
+	u_int32_t pos;
+	u_int32_t val;
+	u_int32_t at;
+	int ret;
+
+	/*
+	 * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
+	 * (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands.
+	 */
+	for (testind = 0; testind < data->ntests; ++testind) {
+		ct  = &data->tests[testind];
+		at  = 0;
+		pos = ct->location[0].number;
+
+		if (skb->len < 4 || pos > skb->len - 4);
+			return false;
+
+		ret   = skb_copy_bits(skb, pos, &val, sizeof(val));
+		BUG_ON(ret < 0);
+		val   = ntohl(val);
+		nnums = ct->nnums;
+
+		/* Inner loop runs over "&", "<<", ">>" and "@" operands */
+		for (i = 1; i < nnums; ++i) {
+			u_int32_t number = ct->location[i].number;
+			switch (ct->location[i].nextop) {
+			case XT_U32_AND:
+				val &= number;
+				break;
+			case XT_U32_LEFTSH:
+				val <<= number;
+				break;
+			case XT_U32_RIGHTSH:
+				val >>= number;
+				break;
+			case XT_U32_AT:
+				if (at + val < at)
+					return false;
+				at += val;
+				pos = number;
+				if (at + 4 < at || skb->len < at + 4 ||
+				    pos > skb->len - at - 4)
+					return false;
+
+				ret = skb_copy_bits(skb, at + pos, &val,
+						    sizeof(val));
+				BUG_ON(ret < 0);
+				val = ntohl(val);
+				break;
+			}
+		}
+
+		/* Run over the "," and ":" operands */
+		nvals = ct->nvalues;
+		for (i = 0; i < nvals; ++i)
+			if (ct->value[i].min <= val && val <= ct->value[i].max)
+				break;
+
+		if (i >= ct->nvalues)
+			return false;
+	}
+
+	return true;
+}
+
+static bool u32_match(const struct sk_buff *skb,
+		      const struct net_device *in,
+		      const struct net_device *out,
+		      const struct xt_match *match, const void *matchinfo,
+		      int offset, unsigned int protoff, bool *hotdrop)
+{
+	const struct xt_u32 *data = matchinfo;
+	bool ret;
+
+	ret = u32_match_it(data, skb);
+	return ret ^ data->invert;
+}
+
+static struct xt_match u32_reg[] __read_mostly = {
+	{
+		.name       = "u32",
+		.family     = AF_INET,
+		.match      = u32_match,
+		.matchsize  = sizeof(struct xt_u32),
+		.me         = THIS_MODULE,
+	},
+	{
+		.name       = "u32",
+		.family     = AF_INET6,
+		.match      = u32_match,
+		.matchsize  = sizeof(struct xt_u32),
+		.me         = THIS_MODULE,
+	},
+};
+
+static int __init xt_u32_init(void)
+{
+	return xt_register_matches(u32_reg, ARRAY_SIZE(u32_reg));
+}
+
+static void __exit xt_u32_exit(void)
+{
+	xt_unregister_matches(u32_reg, ARRAY_SIZE(u32_reg));
+}
+
+module_init(xt_u32_init);
+module_exit(xt_u32_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter u32 match module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_u32");
+MODULE_ALIAS("ip6t_u32");
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 07e47db..24b660f 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -59,7 +59,7 @@
 };
 
 /* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
+static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
 	[NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
 	[NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
 	[NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index f2535e7..b165712 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -246,19 +246,18 @@
 
 /**
  * netlbl_socket_setattr - Label a socket using the correct protocol
- * @sock: the socket to label
+ * @sk: the socket to label
  * @secattr: the security attributes
  *
  * Description:
  * Attach the correct label to the given socket using the security attributes
- * specified in @secattr.  This function requires exclusive access to
- * @sock->sk, which means it either needs to be in the process of being
- * created or locked via lock_sock(sock->sk).  Returns zero on success,
- * negative values on failure.
+ * specified in @secattr.  This function requires exclusive access to @sk,
+ * which means it either needs to be in the process of being created or locked.
+ * Returns zero on success, negative values on failure.
  *
  */
-int netlbl_socket_setattr(const struct socket *sock,
-			  const struct netlbl_lsm_secattr *secattr)
+int netlbl_sock_setattr(struct sock *sk,
+			const struct netlbl_lsm_secattr *secattr)
 {
 	int ret_val = -ENOENT;
 	struct netlbl_dom_map *dom_entry;
@@ -269,9 +268,9 @@
 		goto socket_setattr_return;
 	switch (dom_entry->type) {
 	case NETLBL_NLTYPE_CIPSOV4:
-		ret_val = cipso_v4_socket_setattr(sock,
-						  dom_entry->type_def.cipsov4,
-						  secattr);
+		ret_val = cipso_v4_sock_setattr(sk,
+						dom_entry->type_def.cipsov4,
+						secattr);
 		break;
 	case NETLBL_NLTYPE_UNLABELED:
 		ret_val = 0;
@@ -309,30 +308,6 @@
 }
 
 /**
- * netlbl_socket_getattr - Determine the security attributes of a socket
- * @sock: the socket
- * @secattr: the security attributes
- *
- * Description:
- * Examines the given socket to see any NetLabel style labeling has been
- * applied to the socket, if so it parses the socket label and returns the
- * security attributes in @secattr.  Returns zero on success, negative values
- * on failure.
- *
- */
-int netlbl_socket_getattr(const struct socket *sock,
-			  struct netlbl_lsm_secattr *secattr)
-{
-	int ret_val;
-
-	ret_val = cipso_v4_socket_getattr(sock, secattr);
-	if (ret_val == 0)
-		return 0;
-
-	return netlbl_unlabel_getattr(secattr);
-}
-
-/**
  * netlbl_skbuff_getattr - Determine the security attributes of a packet
  * @skb: the packet
  * @secattr: the security attributes
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index e8c80f3..e00fc21 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -59,7 +59,7 @@
 };
 
 /* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
+static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
 	[NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
 	[NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
 	[NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index b931ede..5c303c68a 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -61,7 +61,7 @@
 };
 
 /* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
+static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
 	[NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
 };
 
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 42f12bd..89dcc48 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -46,10 +46,6 @@
 #include "netlabel_cipso_v4.h"
 #include "netlabel_user.h"
 
-/* do not do any auditing if audit_enabled == 0, see kernel/audit.c for
- * details */
-extern int audit_enabled;
-
 /*
  * NetLabel NETLINK Setup Functions
  */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1f15821..a3c8e69 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1713,7 +1713,7 @@
 	return 0;
 }
 
-static struct seq_operations netlink_seq_ops = {
+static const struct seq_operations netlink_seq_ops = {
 	.start  = netlink_seq_start,
 	.next   = netlink_seq_next,
 	.stop   = netlink_seq_stop,
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index df5f820..e4d7bed 100644
--- a/net/netlink/attr.c
+++ b/net/netlink/attr.c
@@ -24,9 +24,9 @@
 };
 
 static int validate_nla(struct nlattr *nla, int maxtype,
-			struct nla_policy *policy)
+			const struct nla_policy *policy)
 {
-	struct nla_policy *pt;
+	const struct nla_policy *pt;
 	int minlen = 0, attrlen = nla_len(nla);
 
 	if (nla->nla_type <= 0 || nla->nla_type > maxtype)
@@ -72,6 +72,17 @@
 			return -ERANGE;
 		break;
 
+	case NLA_NESTED_COMPAT:
+		if (attrlen < pt->len)
+			return -ERANGE;
+		if (attrlen < NLA_ALIGN(pt->len))
+			break;
+		if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
+			return -ERANGE;
+		nla = nla_data(nla) + NLA_ALIGN(pt->len);
+		if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
+			return -ERANGE;
+		break;
 	default:
 		if (pt->len)
 			minlen = pt->len;
@@ -99,7 +110,7 @@
  * Returns 0 on success or a negative error code.
  */
 int nla_validate(struct nlattr *head, int len, int maxtype,
-		 struct nla_policy *policy)
+		 const struct nla_policy *policy)
 {
 	struct nlattr *nla;
 	int rem, err;
@@ -130,7 +141,7 @@
  * Returns 0 on success or a negative error code.
  */
 int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
-	      struct nla_policy *policy)
+	      const struct nla_policy *policy)
 {
 	struct nlattr *nla;
 	int rem, err;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 6e31234..b9ab62f 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -472,7 +472,7 @@
 	return skb;
 }
 
-static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] __read_mostly = {
+static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
 	[CTRL_ATTR_FAMILY_ID]	= { .type = NLA_U16 },
 	[CTRL_ATTR_FAMILY_NAME]	= { .type = NLA_NUL_STRING,
 				    .len = GENL_NAMSIZ - 1 },
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 5d4a26c..5d66490 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1328,7 +1328,7 @@
 	return 0;
 }
 
-static struct seq_operations nr_info_seqops = {
+static const struct seq_operations nr_info_seqops = {
 	.start = nr_info_start,
 	.next = nr_info_next,
 	.stop = nr_info_stop,
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 2f76e062..24fe4a6 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -922,7 +922,7 @@
 	return 0;
 }
 
-static struct seq_operations nr_node_seqops = {
+static const struct seq_operations nr_node_seqops = {
 	.start = nr_node_start,
 	.next = nr_node_next,
 	.stop = nr_node_stop,
@@ -1006,7 +1006,7 @@
 	return 0;
 }
 
-static struct seq_operations nr_neigh_seqops = {
+static const struct seq_operations nr_neigh_seqops = {
 	.start = nr_neigh_start,
 	.next = nr_neigh_next,
 	.stop = nr_neigh_stop,
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 02e401c..7c27bd3 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -83,22 +83,6 @@
 #include <net/inet_common.h>
 #endif
 
-#define CONFIG_SOCK_PACKET	1
-
-/*
-   Proposed replacement for SIOC{ADD,DEL}MULTI and
-   IFF_PROMISC, IFF_ALLMULTI flags.
-
-   It is more expensive, but I believe,
-   it is really correct solution: reentereble, safe and fault tolerant.
-
-   IFF_PROMISC/IFF_ALLMULTI/SIOC{ADD/DEL}MULTI are faked by keeping
-   reference count and global flag, so that real status is
-   (gflag|(count != 0)), so that we can use obsolete faulty interface
-   not harming clever users.
- */
-#define CONFIG_PACKET_MULTICAST	1
-
 /*
    Assumptions:
    - if device has no dev->hard_header routine, it adds and removes ll header
@@ -159,7 +143,6 @@
 
 /* Private packet socket structures. */
 
-#ifdef CONFIG_PACKET_MULTICAST
 struct packet_mclist
 {
 	struct packet_mclist	*next;
@@ -179,7 +162,7 @@
 	unsigned short	mr_alen;
 	unsigned char	mr_address[MAX_ADDR_LEN];
 };
-#endif
+
 #ifdef CONFIG_PACKET_MMAP
 static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing);
 #endif
@@ -205,9 +188,7 @@
 				origdev:1;
 	int			ifindex;	/* bound device		*/
 	__be16			num;
-#ifdef CONFIG_PACKET_MULTICAST
 	struct packet_mclist	*mclist;
-#endif
 #ifdef CONFIG_PACKET_MMAP
 	atomic_t		mapped;
 	unsigned int            pg_vec_order;
@@ -263,7 +244,6 @@
 
 static const struct proto_ops packet_ops;
 
-#ifdef CONFIG_SOCK_PACKET
 static const struct proto_ops packet_ops_spkt;
 
 static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,  struct packet_type *pt, struct net_device *orig_dev)
@@ -435,7 +415,6 @@
 		dev_put(dev);
 	return err;
 }
-#endif
 
 static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
 				      unsigned int res)
@@ -851,9 +830,7 @@
 		__sock_put(sk);
 	}
 
-#ifdef CONFIG_PACKET_MULTICAST
 	packet_flush_mclist(sk);
-#endif
 
 #ifdef CONFIG_PACKET_MMAP
 	if (po->pg_vec) {
@@ -936,8 +913,6 @@
  *	Bind a packet socket to a device
  */
 
-#ifdef CONFIG_SOCK_PACKET
-
 static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	struct sock *sk=sock->sk;
@@ -960,7 +935,6 @@
 	}
 	return err;
 }
-#endif
 
 static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
@@ -1012,11 +986,8 @@
 
 	if (!capable(CAP_NET_RAW))
 		return -EPERM;
-	if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW
-#ifdef CONFIG_SOCK_PACKET
-	    && sock->type != SOCK_PACKET
-#endif
-	    )
+	if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW &&
+	    sock->type != SOCK_PACKET)
 		return -ESOCKTNOSUPPORT;
 
 	sock->state = SS_UNCONNECTED;
@@ -1027,10 +998,9 @@
 		goto out;
 
 	sock->ops = &packet_ops;
-#ifdef CONFIG_SOCK_PACKET
 	if (sock->type == SOCK_PACKET)
 		sock->ops = &packet_ops_spkt;
-#endif
+
 	sock_init_data(sock, sk);
 
 	po = pkt_sk(sk);
@@ -1046,10 +1016,10 @@
 
 	spin_lock_init(&po->bind_lock);
 	po->prot_hook.func = packet_rcv;
-#ifdef CONFIG_SOCK_PACKET
+
 	if (sock->type == SOCK_PACKET)
 		po->prot_hook.func = packet_rcv_spkt;
-#endif
+
 	po->prot_hook.af_packet_priv = sk;
 
 	if (proto) {
@@ -1169,7 +1139,6 @@
 	return err;
 }
 
-#ifdef CONFIG_SOCK_PACKET
 static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
 			       int *uaddr_len, int peer)
 {
@@ -1190,7 +1159,6 @@
 
 	return 0;
 }
-#endif
 
 static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
 			  int *uaddr_len, int peer)
@@ -1221,7 +1189,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PACKET_MULTICAST
 static void packet_dev_mc(struct net_device *dev, struct packet_mclist *i, int what)
 {
 	switch (i->type) {
@@ -1349,7 +1316,6 @@
 	}
 	rtnl_unlock();
 }
-#endif
 
 static int
 packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
@@ -1362,7 +1328,6 @@
 		return -ENOPROTOOPT;
 
 	switch(optname)	{
-#ifdef CONFIG_PACKET_MULTICAST
 	case PACKET_ADD_MEMBERSHIP:
 	case PACKET_DROP_MEMBERSHIP:
 	{
@@ -1383,7 +1348,7 @@
 			ret = packet_mc_drop(sk, &mreq);
 		return ret;
 	}
-#endif
+
 #ifdef CONFIG_PACKET_MMAP
 	case PACKET_RX_RING:
 	{
@@ -1506,11 +1471,10 @@
 
 		switch (msg) {
 		case NETDEV_UNREGISTER:
-#ifdef CONFIG_PACKET_MULTICAST
 			if (po->mclist)
 				packet_dev_mclist(dev, po->mclist, -1);
-			// fallthrough
-#endif
+			/* fallthrough */
+
 		case NETDEV_DOWN:
 			if (dev->ifindex == po->ifindex) {
 				spin_lock(&po->bind_lock);
@@ -1856,7 +1820,6 @@
 #endif
 
 
-#ifdef CONFIG_SOCK_PACKET
 static const struct proto_ops packet_ops_spkt = {
 	.family =	PF_PACKET,
 	.owner =	THIS_MODULE,
@@ -1877,7 +1840,6 @@
 	.mmap =		sock_no_mmap,
 	.sendpage =	sock_no_sendpage,
 };
-#endif
 
 static const struct proto_ops packet_ops = {
 	.family =	PF_PACKET,
@@ -1966,7 +1928,7 @@
 	return 0;
 }
 
-static struct seq_operations packet_seq_ops = {
+static const struct seq_operations packet_seq_ops = {
 	.start	= packet_seq_start,
 	.next	= packet_seq_next,
 	.stop	= packet_seq_stop,
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index e5c840c..230e35c 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -55,7 +55,7 @@
 
 static void rfkill_schedule_toggle(struct rfkill_task *task)
 {
-	unsigned int flags;
+	unsigned long flags;
 
 	spin_lock_irqsave(&task->lock, flags);
 
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index a973603..f3986d4 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -296,7 +296,7 @@
 	struct device *dev;
 
 	rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL);
-	if (rfkill)
+	if (!rfkill)
 		return NULL;
 
 	mutex_init(&rfkill->mutex);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index d476c43..f4d3aba 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1454,7 +1454,7 @@
 	return 0;
 }
 
-static struct seq_operations rose_info_seqops = {
+static const struct seq_operations rose_info_seqops = {
 	.start = rose_info_start,
 	.next = rose_info_next,
 	.stop = rose_info_stop,
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 929a784..bbcbad1 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -1118,7 +1118,7 @@
 	return 0;
 }
 
-static struct seq_operations rose_node_seqops = {
+static const struct seq_operations rose_node_seqops = {
 	.start = rose_node_start,
 	.next = rose_node_next,
 	.stop = rose_node_stop,
@@ -1200,7 +1200,7 @@
 }
 
 
-static struct seq_operations rose_neigh_seqops = {
+static const struct seq_operations rose_neigh_seqops = {
 	.start = rose_neigh_start,
 	.next = rose_neigh_next,
 	.stop = rose_neigh_stop,
@@ -1284,7 +1284,7 @@
 	return 0;
 }
 
-static struct seq_operations rose_route_seqops = {
+static const struct seq_operations rose_route_seqops = {
 	.start = rose_route_start,
 	.next = rose_route_next,
 	.stop = rose_route_stop,
diff --git a/net/rxrpc/Kconfig b/net/rxrpc/Kconfig
index 91b3d52..e662f1d 100644
--- a/net/rxrpc/Kconfig
+++ b/net/rxrpc/Kconfig
@@ -4,7 +4,7 @@
 
 config AF_RXRPC
 	tristate "RxRPC session sockets"
-	depends on EXPERIMENTAL
+	depends on INET && EXPERIMENTAL
 	select KEYS
 	help
 	  Say Y or M here to include support for RxRPC session sockets (just
diff --git a/net/rxrpc/ar-call.c b/net/rxrpc/ar-call.c
index 4d92d88..3c04b00 100644
--- a/net/rxrpc/ar-call.c
+++ b/net/rxrpc/ar-call.c
@@ -15,6 +15,25 @@
 #include <net/af_rxrpc.h>
 #include "ar-internal.h"
 
+const char *rxrpc_call_states[] = {
+	[RXRPC_CALL_CLIENT_SEND_REQUEST]	= "ClSndReq",
+	[RXRPC_CALL_CLIENT_AWAIT_REPLY]		= "ClAwtRpl",
+	[RXRPC_CALL_CLIENT_RECV_REPLY]		= "ClRcvRpl",
+	[RXRPC_CALL_CLIENT_FINAL_ACK]		= "ClFnlACK",
+	[RXRPC_CALL_SERVER_SECURING]		= "SvSecure",
+	[RXRPC_CALL_SERVER_ACCEPTING]		= "SvAccept",
+	[RXRPC_CALL_SERVER_RECV_REQUEST]	= "SvRcvReq",
+	[RXRPC_CALL_SERVER_ACK_REQUEST]		= "SvAckReq",
+	[RXRPC_CALL_SERVER_SEND_REPLY]		= "SvSndRpl",
+	[RXRPC_CALL_SERVER_AWAIT_ACK]		= "SvAwtACK",
+	[RXRPC_CALL_COMPLETE]			= "Complete",
+	[RXRPC_CALL_SERVER_BUSY]		= "SvBusy  ",
+	[RXRPC_CALL_REMOTELY_ABORTED]		= "RmtAbort",
+	[RXRPC_CALL_LOCALLY_ABORTED]		= "LocAbort",
+	[RXRPC_CALL_NETWORK_ERROR]		= "NetError",
+	[RXRPC_CALL_DEAD]			= "Dead    ",
+};
+
 struct kmem_cache *rxrpc_call_jar;
 LIST_HEAD(rxrpc_calls);
 DEFINE_RWLOCK(rxrpc_call_lock);
diff --git a/net/rxrpc/ar-connection.c b/net/rxrpc/ar-connection.c
index 43cb3e0..482750e 100644
--- a/net/rxrpc/ar-connection.c
+++ b/net/rxrpc/ar-connection.c
@@ -211,7 +211,7 @@
 		conn->header_size = sizeof(struct rxrpc_header);
 	}
 
-	_leave(" = %p{%d}", conn, conn->debug_id);
+	_leave(" = %p{%d}", conn, conn ? conn->debug_id : 0);
 	return conn;
 }
 
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c
index 591c442..cc9102c 100644
--- a/net/rxrpc/ar-output.c
+++ b/net/rxrpc/ar-output.c
@@ -640,6 +640,7 @@
 			goto efault;
 		sp->remain -= copy;
 		skb->mark += copy;
+		copied += copy;
 
 		len -= copy;
 		segment -= copy;
@@ -709,6 +710,8 @@
 
 	} while (segment > 0);
 
+success:
+	ret = copied;
 out:
 	call->tx_pending = skb;
 	_leave(" = %d", ret);
@@ -725,7 +728,7 @@
 
 maybe_error:
 	if (copied)
-		ret = copied;
+		goto success;
 	goto out;
 
 efault:
diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c
index 58f4b4e..2e83ce3 100644
--- a/net/rxrpc/ar-proc.c
+++ b/net/rxrpc/ar-proc.c
@@ -25,55 +25,18 @@
 	[RXRPC_CONN_NETWORK_ERROR]	= "NetError",
 };
 
-const char *rxrpc_call_states[] = {
-	[RXRPC_CALL_CLIENT_SEND_REQUEST]	= "ClSndReq",
-	[RXRPC_CALL_CLIENT_AWAIT_REPLY]		= "ClAwtRpl",
-	[RXRPC_CALL_CLIENT_RECV_REPLY]		= "ClRcvRpl",
-	[RXRPC_CALL_CLIENT_FINAL_ACK]		= "ClFnlACK",
-	[RXRPC_CALL_SERVER_SECURING]		= "SvSecure",
-	[RXRPC_CALL_SERVER_ACCEPTING]		= "SvAccept",
-	[RXRPC_CALL_SERVER_RECV_REQUEST]	= "SvRcvReq",
-	[RXRPC_CALL_SERVER_ACK_REQUEST]		= "SvAckReq",
-	[RXRPC_CALL_SERVER_SEND_REPLY]		= "SvSndRpl",
-	[RXRPC_CALL_SERVER_AWAIT_ACK]		= "SvAwtACK",
-	[RXRPC_CALL_COMPLETE]			= "Complete",
-	[RXRPC_CALL_SERVER_BUSY]		= "SvBusy  ",
-	[RXRPC_CALL_REMOTELY_ABORTED]		= "RmtAbort",
-	[RXRPC_CALL_LOCALLY_ABORTED]		= "LocAbort",
-	[RXRPC_CALL_NETWORK_ERROR]		= "NetError",
-	[RXRPC_CALL_DEAD]			= "Dead    ",
-};
-
 /*
  * generate a list of extant and dead calls in /proc/net/rxrpc_calls
  */
 static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	read_lock(&rxrpc_call_lock);
-	if (!pos)
-		return SEQ_START_TOKEN;
-	pos--;
-
-	list_for_each(_p, &rxrpc_calls)
-		if (!pos--)
-			break;
-
-	return _p != &rxrpc_calls ? _p : NULL;
+	return seq_list_start_head(&rxrpc_calls, *_pos);
 }
 
 static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = (v == SEQ_START_TOKEN) ? rxrpc_calls.next : _p->next;
-
-	return _p != &rxrpc_calls ? _p : NULL;
+	return seq_list_next(v, &rxrpc_calls, pos);
 }
 
 static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
@@ -87,7 +50,7 @@
 	struct rxrpc_call *call;
 	char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
 
-	if (v == SEQ_START_TOKEN) {
+	if (v == &rxrpc_calls) {
 		seq_puts(seq,
 			 "Proto Local                  Remote                "
 			 " SvID ConnID   CallID   End Use State    Abort   "
@@ -123,7 +86,7 @@
 	return 0;
 }
 
-static struct seq_operations rxrpc_call_seq_ops = {
+static const struct seq_operations rxrpc_call_seq_ops = {
 	.start  = rxrpc_call_seq_start,
 	.next   = rxrpc_call_seq_next,
 	.stop   = rxrpc_call_seq_stop,
@@ -148,32 +111,14 @@
  */
 static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	read_lock(&rxrpc_connection_lock);
-	if (!pos)
-		return SEQ_START_TOKEN;
-	pos--;
-
-	list_for_each(_p, &rxrpc_connections)
-		if (!pos--)
-			break;
-
-	return _p != &rxrpc_connections ? _p : NULL;
+	return seq_list_start_head(&rxrpc_connections, *_pos);
 }
 
 static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
 				       loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = (v == SEQ_START_TOKEN) ? rxrpc_connections.next : _p->next;
-
-	return _p != &rxrpc_connections ? _p : NULL;
+	return seq_list_next(v, &rxrpc_connections, pos);
 }
 
 static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
@@ -187,7 +132,7 @@
 	struct rxrpc_transport *trans;
 	char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
 
-	if (v == SEQ_START_TOKEN) {
+	if (v == &rxrpc_connections) {
 		seq_puts(seq,
 			 "Proto Local                  Remote                "
 			 " SvID ConnID   Calls    End Use State    Key     "
@@ -225,7 +170,7 @@
 	return 0;
 }
 
-static struct seq_operations rxrpc_connection_seq_ops = {
+static const struct seq_operations rxrpc_connection_seq_ops = {
 	.start  = rxrpc_connection_seq_start,
 	.next   = rxrpc_connection_seq_next,
 	.stop   = rxrpc_connection_seq_stop,
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 475df84..d3f7c3f 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -111,6 +111,17 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called sch_prio.
 
+config NET_SCH_RR
+	tristate "Multi Band Round Robin Queuing (RR)"
+	select NET_SCH_PRIO
+	---help---
+	  Say Y here if you want to use an n-band round robin packet
+	  scheduler.
+
+	  The module uses sch_prio for its framework and is aliased as
+	  sch_rr, so it will load sch_prio, although it is referred
+	  to using sch_rr.
+
 config NET_SCH_RED
 	tristate "Random Early Detection (RED)"
 	---help---
@@ -275,7 +286,6 @@
 config NET_CLS_RSVP
 	tristate "IPv4 Resource Reservation Protocol (RSVP)"
 	select NET_CLS
-	select NET_ESTIMATOR
 	---help---
 	  The Resource Reservation Protocol (RSVP) permits end systems to
 	  request a minimum and maximum data flow rate for a connection; this
@@ -290,7 +300,6 @@
 config NET_CLS_RSVP6
 	tristate "IPv6 Resource Reservation Protocol (RSVP6)"
 	select NET_CLS
-	select NET_ESTIMATOR
 	---help---
 	  The Resource Reservation Protocol (RSVP) permits end systems to
 	  request a minimum and maximum data flow rate for a connection; this
@@ -382,7 +391,6 @@
 
 config NET_CLS_ACT
 	bool "Actions"
-	select NET_ESTIMATOR
 	---help---
 	  Say Y here if you want to use traffic control actions. Actions
 	  get attached to classifiers and are invoked after a successful
@@ -464,13 +472,12 @@
 
 config NET_CLS_POLICE
 	bool "Traffic Policing (obsolete)"
-	depends on NET_CLS_ACT!=y
-	select NET_ESTIMATOR
+	select NET_CLS_ACT
+	select NET_ACT_POLICE
 	---help---
 	  Say Y here if you want to do traffic policing, i.e. strict
-	  bandwidth limiting. This option is obsoleted by the traffic
-	  policer implemented as action, it stays here for compatibility
-	  reasons.
+	  bandwidth limiting. This option is obsolete and just selects
+	  the option replacing it. It will be removed in the future.
 
 config NET_CLS_IND
 	bool "Incoming device classification"
@@ -480,14 +487,6 @@
 	  classification based on the incoming device. This option is
 	  likely to disappear in favour of the metadata ematch.
 
-config NET_ESTIMATOR
-	bool "Rate estimator"
-	---help---
-	  Say Y here to allow using rate estimators to estimate the current
-	  rate-of-flow for network devices, queues, etc. This module is
-	  automatically selected if needed but can be selected manually for
-	  statistical purposes.
-
 endif # NET_SCHED
 
 endmenu
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 020767a..b67c36f 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -8,7 +8,6 @@
 obj-$(CONFIG_NET_CLS)		+= cls_api.o
 obj-$(CONFIG_NET_CLS_ACT)	+= act_api.o
 obj-$(CONFIG_NET_ACT_POLICE)	+= act_police.o
-obj-$(CONFIG_NET_CLS_POLICE)	+= act_police.o
 obj-$(CONFIG_NET_ACT_GACT)	+= act_gact.o
 obj-$(CONFIG_NET_ACT_MIRRED)	+= act_mirred.o
 obj-$(CONFIG_NET_ACT_IPT)	+= act_ipt.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 711dd26..feef366 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -11,23 +11,13 @@
  *
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
-#include <net/sock.h>
 #include <net/sch_generic.h>
 #include <net/act_api.h>
 #include <net/netlink.h>
@@ -42,10 +32,8 @@
 			write_lock_bh(hinfo->lock);
 			*p1p = p->tcfc_next;
 			write_unlock_bh(hinfo->lock);
-#ifdef CONFIG_NET_ESTIMATOR
 			gen_kill_estimator(&p->tcfc_bstats,
 					   &p->tcfc_rate_est);
-#endif
 			kfree(p);
 			return;
 		}
@@ -232,15 +220,12 @@
 		p->tcfc_bindcnt = 1;
 
 	spin_lock_init(&p->tcfc_lock);
-	p->tcfc_stats_lock = &p->tcfc_lock;
 	p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo);
 	p->tcfc_tm.install = jiffies;
 	p->tcfc_tm.lastuse = jiffies;
-#ifdef CONFIG_NET_ESTIMATOR
 	if (est)
 		gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est,
-				  p->tcfc_stats_lock, est);
-#endif
+				  &p->tcfc_lock, est);
 	a->priv = (void *) p;
 	return p;
 }
@@ -599,12 +584,12 @@
 	if (compat_mode) {
 		if (a->type == TCA_OLD_COMPAT)
 			err = gnet_stats_start_copy_compat(skb, 0,
-				TCA_STATS, TCA_XSTATS, h->tcf_stats_lock, &d);
+				TCA_STATS, TCA_XSTATS, &h->tcf_lock, &d);
 		else
 			return 0;
 	} else
 		err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
-			h->tcf_stats_lock, &d);
+					    &h->tcf_lock, &d);
 
 	if (err < 0)
 		goto errout;
@@ -614,9 +599,7 @@
 			goto errout;
 
 	if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(&d, &h->tcf_rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0)
 		goto errout;
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 7517f37..a9631e4 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -10,26 +10,15 @@
  *
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_gact.h>
 #include <net/tc_act/tc_gact.h>
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 00b05f4..6b407ec 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -11,27 +11,15 @@
  * Copyright:	Jamal Hadi Salim (2002-4)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/kmod.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_ipt.h>
 #include <net/tc_act/tc_ipt.h>
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index de21c92..5795789 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -12,31 +12,19 @@
  *
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_mirred.h>
 #include <net/tc_act/tc_mirred.h>
 
-#include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 
 #define MIRRED_TAB_MASK     7
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 45b3cda..b46fab5 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -9,26 +9,15 @@
  * Authors:	Jamal Hadi Salim (2002-4)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_pedit.h>
 #include <net/tc_act/tc_pedit.h>
@@ -164,8 +153,7 @@
 				printk("offset must be on 32 bit boundaries\n");
 				goto bad;
 			}
-			if (skb->len < 0 ||
-			    (offset > 0 && offset > skb->len)) {
+			if (offset > 0 && offset > skb->len) {
 				printk("offset %d cant exceed pkt length %d\n",
 				       offset, skb->len);
 				goto bad;
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 616f465..bf90e60f 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -10,25 +10,15 @@
  * 		J Hadi Salim (action changes)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/module.h>
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
-#include <net/sock.h>
 #include <net/act_api.h>
 #include <net/netlink.h>
 
@@ -60,7 +50,6 @@
 
 /* Each policer is serialized by its individual spinlock */
 
-#ifdef CONFIG_NET_CLS_ACT
 static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
 			      int type, struct tc_action *a)
 {
@@ -106,9 +95,8 @@
 	nlmsg_trim(skb, r);
 	goto done;
 }
-#endif
 
-void tcf_police_destroy(struct tcf_police *p)
+static void tcf_police_destroy(struct tcf_police *p)
 {
 	unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
 	struct tcf_common **p1p;
@@ -118,10 +106,8 @@
 			write_lock_bh(&police_lock);
 			*p1p = p->tcf_next;
 			write_unlock_bh(&police_lock);
-#ifdef CONFIG_NET_ESTIMATOR
 			gen_kill_estimator(&p->tcf_bstats,
 					   &p->tcf_rate_est);
-#endif
 			if (p->tcfp_R_tab)
 				qdisc_put_rtab(p->tcfp_R_tab);
 			if (p->tcfp_P_tab)
@@ -133,7 +119,6 @@
 	BUG_TRAP(0);
 }
 
-#ifdef CONFIG_NET_CLS_ACT
 static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
 				 struct tc_action *a, int ovr, int bind)
 {
@@ -185,7 +170,6 @@
 	ret = ACT_P_CREATED;
 	police->tcf_refcnt = 1;
 	spin_lock_init(&police->tcf_lock);
-	police->tcf_stats_lock = &police->tcf_lock;
 	if (bind)
 		police->tcf_bindcnt = 1;
 override:
@@ -227,15 +211,13 @@
 		police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
 	police->tcf_action = parm->action;
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tb[TCA_POLICE_AVRATE-1])
 		police->tcfp_ewma_rate =
 			*(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
 	if (est)
 		gen_replace_estimator(&police->tcf_bstats,
 				      &police->tcf_rate_est,
-				      police->tcf_stats_lock, est);
-#endif
+				      &police->tcf_lock, est);
 
 	spin_unlock_bh(&police->tcf_lock);
 	if (ret != ACT_P_CREATED)
@@ -262,10 +244,19 @@
 static int tcf_act_police_cleanup(struct tc_action *a, int bind)
 {
 	struct tcf_police *p = a->priv;
+	int ret = 0;
 
-	if (p != NULL)
-		return tcf_police_release(p, bind);
-	return 0;
+	if (p != NULL) {
+		if (bind)
+			p->tcf_bindcnt--;
+
+		p->tcf_refcnt--;
+		if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) {
+			tcf_police_destroy(p);
+			ret = 1;
+		}
+	}
+	return ret;
 }
 
 static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
@@ -281,14 +272,12 @@
 	police->tcf_bstats.bytes += skb->len;
 	police->tcf_bstats.packets++;
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (police->tcfp_ewma_rate &&
 	    police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
 		police->tcf_qstats.overlimits++;
 		spin_unlock(&police->tcf_lock);
 		return police->tcf_action;
 	}
-#endif
 
 	if (skb->len <= police->tcfp_mtu) {
 		if (police->tcfp_R_tab == NULL) {
@@ -348,10 +337,8 @@
 	if (police->tcfp_result)
 		RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
 			&police->tcfp_result);
-#ifdef CONFIG_NET_ESTIMATOR
 	if (police->tcfp_ewma_rate)
 		RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
-#endif
 	return skb->len;
 
 rtattr_failure:
@@ -391,240 +378,3 @@
 
 module_init(police_init_module);
 module_exit(police_cleanup_module);
-
-#else /* CONFIG_NET_CLS_ACT */
-
-static struct tcf_common *tcf_police_lookup(u32 index)
-{
-	struct tcf_hashinfo *hinfo = &police_hash_info;
-	struct tcf_common *p;
-
-	read_lock(hinfo->lock);
-	for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p;
-	     p = p->tcfc_next) {
-		if (p->tcfc_index == index)
-			break;
-	}
-	read_unlock(hinfo->lock);
-
-	return p;
-}
-
-static u32 tcf_police_new_index(void)
-{
-	u32 *idx_gen = &police_idx_gen;
-	u32 val = *idx_gen;
-
-	do {
-		if (++val == 0)
-			val = 1;
-	} while (tcf_police_lookup(val));
-
-	return (*idx_gen = val);
-}
-
-struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est)
-{
-	unsigned int h;
-	struct tcf_police *police;
-	struct rtattr *tb[TCA_POLICE_MAX];
-	struct tc_police *parm;
-	int size;
-
-	if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
-		return NULL;
-
-	if (tb[TCA_POLICE_TBF-1] == NULL)
-		return NULL;
-	size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
-	if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
-		return NULL;
-
-	parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
-
-	if (parm->index) {
-		struct tcf_common *pc;
-
-		pc = tcf_police_lookup(parm->index);
-		if (pc) {
-			police = to_police(pc);
-			police->tcf_refcnt++;
-			return police;
-		}
-	}
-	police = kzalloc(sizeof(*police), GFP_KERNEL);
-	if (unlikely(!police))
-		return NULL;
-
-	police->tcf_refcnt = 1;
-	spin_lock_init(&police->tcf_lock);
-	police->tcf_stats_lock = &police->tcf_lock;
-	if (parm->rate.rate) {
-		police->tcfp_R_tab =
-			qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
-		if (police->tcfp_R_tab == NULL)
-			goto failure;
-		if (parm->peakrate.rate) {
-			police->tcfp_P_tab =
-				qdisc_get_rtab(&parm->peakrate,
-					       tb[TCA_POLICE_PEAKRATE-1]);
-			if (police->tcfp_P_tab == NULL)
-				goto failure;
-		}
-	}
-	if (tb[TCA_POLICE_RESULT-1]) {
-		if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
-			goto failure;
-		police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
-	}
-#ifdef CONFIG_NET_ESTIMATOR
-	if (tb[TCA_POLICE_AVRATE-1]) {
-		if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32))
-			goto failure;
-		police->tcfp_ewma_rate =
-			*(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
-	}
-#endif
-	police->tcfp_toks = police->tcfp_burst = parm->burst;
-	police->tcfp_mtu = parm->mtu;
-	if (police->tcfp_mtu == 0) {
-		police->tcfp_mtu = ~0;
-		if (police->tcfp_R_tab)
-			police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log;
-	}
-	if (police->tcfp_P_tab)
-		police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
-	police->tcfp_t_c = psched_get_time();
-	police->tcf_index = parm->index ? parm->index :
-		tcf_police_new_index();
-	police->tcf_action = parm->action;
-#ifdef CONFIG_NET_ESTIMATOR
-	if (est)
-		gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est,
-				  police->tcf_stats_lock, est);
-#endif
-	h = tcf_hash(police->tcf_index, POL_TAB_MASK);
-	write_lock_bh(&police_lock);
-	police->tcf_next = tcf_police_ht[h];
-	tcf_police_ht[h] = &police->common;
-	write_unlock_bh(&police_lock);
-	return police;
-
-failure:
-	if (police->tcfp_R_tab)
-		qdisc_put_rtab(police->tcfp_R_tab);
-	kfree(police);
-	return NULL;
-}
-
-int tcf_police(struct sk_buff *skb, struct tcf_police *police)
-{
-	psched_time_t now;
-	long toks;
-	long ptoks = 0;
-
-	spin_lock(&police->tcf_lock);
-
-	police->tcf_bstats.bytes += skb->len;
-	police->tcf_bstats.packets++;
-
-#ifdef CONFIG_NET_ESTIMATOR
-	if (police->tcfp_ewma_rate &&
-	    police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
-		police->tcf_qstats.overlimits++;
-		spin_unlock(&police->tcf_lock);
-		return police->tcf_action;
-	}
-#endif
-	if (skb->len <= police->tcfp_mtu) {
-		if (police->tcfp_R_tab == NULL) {
-			spin_unlock(&police->tcf_lock);
-			return police->tcfp_result;
-		}
-
-		now = psched_get_time();
-		toks = psched_tdiff_bounded(now, police->tcfp_t_c,
-					    police->tcfp_burst);
-		if (police->tcfp_P_tab) {
-			ptoks = toks + police->tcfp_ptoks;
-			if (ptoks > (long)L2T_P(police, police->tcfp_mtu))
-				ptoks = (long)L2T_P(police, police->tcfp_mtu);
-			ptoks -= L2T_P(police, skb->len);
-		}
-		toks += police->tcfp_toks;
-		if (toks > (long)police->tcfp_burst)
-			toks = police->tcfp_burst;
-		toks -= L2T(police, skb->len);
-		if ((toks|ptoks) >= 0) {
-			police->tcfp_t_c = now;
-			police->tcfp_toks = toks;
-			police->tcfp_ptoks = ptoks;
-			spin_unlock(&police->tcf_lock);
-			return police->tcfp_result;
-		}
-	}
-
-	police->tcf_qstats.overlimits++;
-	spin_unlock(&police->tcf_lock);
-	return police->tcf_action;
-}
-EXPORT_SYMBOL(tcf_police);
-
-int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police)
-{
-	unsigned char *b = skb_tail_pointer(skb);
-	struct tc_police opt;
-
-	opt.index = police->tcf_index;
-	opt.action = police->tcf_action;
-	opt.mtu = police->tcfp_mtu;
-	opt.burst = police->tcfp_burst;
-	if (police->tcfp_R_tab)
-		opt.rate = police->tcfp_R_tab->rate;
-	else
-		memset(&opt.rate, 0, sizeof(opt.rate));
-	if (police->tcfp_P_tab)
-		opt.peakrate = police->tcfp_P_tab->rate;
-	else
-		memset(&opt.peakrate, 0, sizeof(opt.peakrate));
-	RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
-	if (police->tcfp_result)
-		RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
-			&police->tcfp_result);
-#ifdef CONFIG_NET_ESTIMATOR
-	if (police->tcfp_ewma_rate)
-		RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
-#endif
-	return skb->len;
-
-rtattr_failure:
-	nlmsg_trim(skb, b);
-	return -1;
-}
-
-int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police)
-{
-	struct gnet_dump d;
-
-	if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
-					 TCA_XSTATS, police->tcf_stats_lock,
-					 &d) < 0)
-		goto errout;
-
-	if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
-	    gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 ||
-#endif
-	    gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0)
-		goto errout;
-
-	if (gnet_stats_finish_copy(&d) < 0)
-		goto errout;
-
-	return 0;
-
-errout:
-	return -1;
-}
-
-#endif /* CONFIG_NET_CLS_ACT */
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 36e1eda..fb84ef3 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <net/netlink.h>
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index ebf94ed..5f0fbca 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -14,26 +14,16 @@
  *
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/netlink.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
 
@@ -468,11 +458,6 @@
 		tcf_action_destroy(exts->action, TCA_ACT_UNBIND);
 		exts->action = NULL;
 	}
-#elif defined CONFIG_NET_CLS_POLICE
-	if (exts->police) {
-		tcf_police_release(exts->police, TCA_ACT_UNBIND);
-		exts->police = NULL;
-	}
 #endif
 }
 
@@ -506,17 +491,6 @@
 			exts->action = act;
 		}
 	}
-#elif defined CONFIG_NET_CLS_POLICE
-	if (map->police && tb[map->police-1]) {
-		struct tcf_police *p;
-
-		p = tcf_police_locate(tb[map->police-1], rate_tlv);
-		if (p == NULL)
-			return -EINVAL;
-
-		exts->police = p;
-	} else if (map->action && tb[map->action-1])
-		return -EOPNOTSUPP;
 #else
 	if ((map->action && tb[map->action-1]) ||
 	    (map->police && tb[map->police-1]))
@@ -539,15 +513,6 @@
 		if (act)
 			tcf_action_destroy(act, TCA_ACT_UNBIND);
 	}
-#elif defined CONFIG_NET_CLS_POLICE
-	if (src->police) {
-		struct tcf_police *p;
-		tcf_tree_lock(tp);
-		p = xchg(&dst->police, src->police);
-		tcf_tree_unlock(tp);
-		if (p)
-			tcf_police_release(p, TCA_ACT_UNBIND);
-	}
 #endif
 }
 
@@ -576,17 +541,6 @@
 			p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
 		}
 	}
-#elif defined CONFIG_NET_CLS_POLICE
-	if (map->police && exts->police) {
-		struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb);
-
-		RTA_PUT(skb, map->police, 0, NULL);
-
-		if (tcf_police_dump(skb, exts->police) < 0)
-			goto rtattr_failure;
-
-		p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
-	}
 #endif
 	return 0;
 rtattr_failure: __attribute__ ((unused))
@@ -601,10 +555,6 @@
 	if (exts->action)
 		if (tcf_action_copy_stats(skb, exts->action, 1) < 0)
 			goto rtattr_failure;
-#elif defined CONFIG_NET_CLS_POLICE
-	if (exts->police)
-		if (tcf_police_dump_stats(skb, exts->police) < 0)
-			goto rtattr_failure;
 #endif
 	return 0;
 rtattr_failure: __attribute__ ((unused))
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index c885412..8dbcf27 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -13,7 +13,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/rtnetlink.h>
 #include <linux/skbuff.h>
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index bbec4a0..8adbd6a 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -19,29 +19,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <linux/netfilter.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index cc941d0..0a8409c 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -10,28 +10,14 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <net/netlink.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
diff --git a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c
index 0a683c0..cbb5e0d 100644
--- a/net/sched/cls_rsvp.c
+++ b/net/sched/cls_rsvp.c
@@ -10,27 +10,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/ip.h>
 #include <net/netlink.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
diff --git a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c
index 93b6abe..dd08aea 100644
--- a/net/sched/cls_rsvp6.c
+++ b/net/sched/cls_rsvp6.c
@@ -10,28 +10,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
 #include <linux/ipv6.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 #include <net/netlink.h>
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 47ac0c5..2314820 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -9,12 +9,9 @@
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <net/ip.h>
 #include <net/act_api.h>
 #include <net/netlink.h>
 #include <net/pkt_cls.h>
-#include <net/route.h>
 
 
 /*
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index c7a347b..8dbe369 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -30,30 +30,14 @@
  *	nfmark match added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro>
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
 #include <linux/rtnetlink.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
@@ -798,9 +782,6 @@
 #ifdef CONFIG_CLS_U32_PERF
 	printk("    Performance counters on\n");
 #endif
-#ifdef CONFIG_NET_CLS_POLICE
-	printk("    OLD policer on \n");
-#endif
 #ifdef CONFIG_NET_CLS_IND
 	printk("    input device check on \n");
 #endif
diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c
index 8d6dacd..cc49c93 100644
--- a/net/sched/em_cmp.c
+++ b/net/sched/em_cmp.c
@@ -98,3 +98,4 @@
 module_init(init_em_cmp);
 module_exit(exit_em_cmp);
 
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_CMP);
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 60acf8c..650f09c 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -848,3 +848,5 @@
 
 module_init(init_em_meta);
 module_exit(exit_em_meta);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_META);
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c
index b4b36ef..370a1b2 100644
--- a/net/sched/em_nbyte.c
+++ b/net/sched/em_nbyte.c
@@ -76,3 +76,5 @@
 
 module_init(init_em_nbyte);
 module_exit(exit_em_nbyte);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_NBYTE);
diff --git a/net/sched/em_text.c b/net/sched/em_text.c
index e8f4616..d5cd86e 100644
--- a/net/sched/em_text.c
+++ b/net/sched/em_text.c
@@ -150,3 +150,5 @@
 
 module_init(init_em_text);
 module_exit(exit_em_text);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_TEXT);
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c
index 0a2a7fe..112796e 100644
--- a/net/sched/em_u32.c
+++ b/net/sched/em_u32.c
@@ -60,3 +60,5 @@
 
 module_init(init_em_u32);
 module_exit(exit_em_u32);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_U32);
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 63146d3..f3a104e 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -84,9 +84,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
 #include <linux/rtnetlink.h>
 #include <linux/skbuff.h>
 #include <net/pkt_cls.h>
@@ -224,6 +222,19 @@
 
 		if (em->ops == NULL) {
 			err = -ENOENT;
+#ifdef CONFIG_KMOD
+			__rtnl_unlock();
+			request_module("ematch-kind-%u", em_hdr->kind);
+			rtnl_lock();
+			em->ops = tcf_em_lookup(em_hdr->kind);
+			if (em->ops) {
+				/* We dropped the RTNL mutex in order to
+				 * perform the module load. Tell the caller
+				 * to replay the request. */
+				module_put(em->ops->owner);
+				err = -EAGAIN;
+			}
+#endif
 			goto errout;
 		}
 
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index bec600a..13c09bc 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -19,30 +19,18 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/kmod.h>
 #include <linux/list.h>
-#include <linux/bitops.h>
 #include <linux/hrtimer.h>
 
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
 static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid,
 			struct Qdisc *old, struct Qdisc *new);
 static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n,
@@ -290,11 +278,7 @@
 
 	wd->qdisc->flags &= ~TCQ_F_THROTTLED;
 	smp_wmb();
-	if (spin_trylock(&dev->queue_lock)) {
-		qdisc_run(dev);
-		spin_unlock(&dev->queue_lock);
-	} else
-		netif_schedule(dev);
+	netif_schedule(dev);
 
 	return HRTIMER_NORESTART;
 }
@@ -515,7 +499,6 @@
 	sch->handle = handle;
 
 	if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
-#ifdef CONFIG_NET_ESTIMATOR
 		if (tca[TCA_RATE-1]) {
 			err = gen_new_estimator(&sch->bstats, &sch->rate_est,
 						sch->stats_lock,
@@ -531,7 +514,6 @@
 				goto err_out3;
 			}
 		}
-#endif
 		qdisc_lock_tree(dev);
 		list_add_tail(&sch->list, &dev->qdisc_list);
 		qdisc_unlock_tree(dev);
@@ -559,11 +541,9 @@
 		if (err)
 			return err;
 	}
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tca[TCA_RATE-1])
 		gen_replace_estimator(&sch->bstats, &sch->rate_est,
 			sch->stats_lock, tca[TCA_RATE-1]);
-#endif
 	return 0;
 }
 
@@ -839,9 +819,7 @@
 		goto rtattr_failure;
 
 	if (gnet_stats_copy_basic(&d, &q->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(&d, &q->qstats) < 0)
 		goto rtattr_failure;
 
@@ -1167,47 +1145,57 @@
    to this qdisc, (optionally) tests for protocol and asks
    specific classifiers.
  */
+int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
+		       struct tcf_result *res)
+{
+	__be16 protocol = skb->protocol;
+	int err = 0;
+
+	for (; tp; tp = tp->next) {
+		if ((tp->protocol == protocol ||
+		     tp->protocol == htons(ETH_P_ALL)) &&
+		    (err = tp->classify(skb, tp, res)) >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+			if (err != TC_ACT_RECLASSIFY && skb->tc_verd)
+				skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0);
+#endif
+			return err;
+		}
+	}
+	return -1;
+}
+EXPORT_SYMBOL(tc_classify_compat);
+
 int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
-	struct tcf_result *res)
+		struct tcf_result *res)
 {
 	int err = 0;
-	__be16 protocol = skb->protocol;
+	__be16 protocol;
 #ifdef CONFIG_NET_CLS_ACT
 	struct tcf_proto *otp = tp;
 reclassify:
 #endif
 	protocol = skb->protocol;
 
-	for ( ; tp; tp = tp->next) {
-		if ((tp->protocol == protocol ||
-			tp->protocol == htons(ETH_P_ALL)) &&
-			(err = tp->classify(skb, tp, res)) >= 0) {
+	err = tc_classify_compat(skb, tp, res);
 #ifdef CONFIG_NET_CLS_ACT
-			if ( TC_ACT_RECLASSIFY == err) {
-				__u32 verd = (__u32) G_TC_VERD(skb->tc_verd);
-				tp = otp;
+	if (err == TC_ACT_RECLASSIFY) {
+		u32 verd = G_TC_VERD(skb->tc_verd);
+		tp = otp;
 
-				if (MAX_REC_LOOP < verd++) {
-					printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n",
-						tp->prio&0xffff, ntohs(tp->protocol));
-					return TC_ACT_SHOT;
-				}
-				skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd);
-				goto reclassify;
-			} else {
-				if (skb->tc_verd)
-					skb->tc_verd = SET_TC_VERD(skb->tc_verd,0);
-				return err;
-			}
-#else
-
-			return err;
-#endif
+		if (verd++ >= MAX_REC_LOOP) {
+			printk("rule prio %u protocol %02x reclassify loop, "
+			       "packet dropped\n",
+			       tp->prio&0xffff, ntohs(tp->protocol));
+			return TC_ACT_SHOT;
 		}
-
+		skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd);
+		goto reclassify;
 	}
-	return -1;
+#endif
+	return err;
 }
+EXPORT_SYMBOL(tc_classify);
 
 void tcf_destroy(struct tcf_proto *tp)
 {
@@ -1274,4 +1262,3 @@
 EXPORT_SYMBOL(qdisc_put_rtab);
 EXPORT_SYMBOL(register_qdisc);
 EXPORT_SYMBOL(unregister_qdisc);
-EXPORT_SYMBOL(tc_classify);
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index be7d299..417ec8f 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -2,24 +2,19 @@
 
 /* Written 1998-2000 by Werner Almesberger, EPFL ICA */
 
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
-#include <linux/interrupt.h>
 #include <linux/atmdev.h>
 #include <linux/atmclip.h>
-#include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
-#include <linux/file.h> /* for fput */
+#include <linux/file.h>		/* for fput */
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
-#include <net/sock.h>
 
-
-extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */
+extern struct socket *sockfd_lookup(int fd, int *err);	/* @@@ fix this */
 
 #if 0 /* control */
 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
@@ -33,7 +28,6 @@
 #define D2PRINTK(format,args...)
 #endif
 
-
 /*
  * The ATM queuing discipline provides a framework for invoking classifiers
  * (aka "filters"), which in turn select classes of this queuing discipline.
@@ -55,23 +49,21 @@
  *  - should lock the flow while there is data in the queue (?)
  */
 
-
 #define PRIV(sch) qdisc_priv(sch)
 #define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back))
 
-
 struct atm_flow_data {
-	struct Qdisc		*q;		/* FIFO, TBF, etc. */
+	struct Qdisc		*q;	/* FIFO, TBF, etc. */
 	struct tcf_proto	*filter_list;
-	struct atm_vcc		*vcc;		/* VCC; NULL if VCC is closed */
-	void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* chaining */
+	struct atm_vcc		*vcc;	/* VCC; NULL if VCC is closed */
+	void			(*old_pop)(struct atm_vcc *vcc,
+					   struct sk_buff * skb); /* chaining */
 	struct atm_qdisc_data	*parent;	/* parent qdisc */
 	struct socket		*sock;		/* for closing */
 	u32			classid;	/* x:y type ID */
 	int			ref;		/* reference count */
 	struct gnet_stats_basic	bstats;
 	struct gnet_stats_queue	qstats;
-	spinlock_t		*stats_lock;
 	struct atm_flow_data	*next;
 	struct atm_flow_data	*excess;	/* flow for excess traffic;
 						   NULL to set CLP instead */
@@ -86,76 +78,74 @@
 	struct tasklet_struct	task;		/* requeue tasklet */
 };
 
-
 /* ------------------------- Class/flow operations ------------------------- */
 
-
-static int find_flow(struct atm_qdisc_data *qdisc,struct atm_flow_data *flow)
+static int find_flow(struct atm_qdisc_data *qdisc, struct atm_flow_data *flow)
 {
 	struct atm_flow_data *walk;
 
-	DPRINTK("find_flow(qdisc %p,flow %p)\n",qdisc,flow);
+	DPRINTK("find_flow(qdisc %p,flow %p)\n", qdisc, flow);
 	for (walk = qdisc->flows; walk; walk = walk->next)
-		if (walk == flow) return 1;
+		if (walk == flow)
+			return 1;
 	DPRINTK("find_flow: not found\n");
 	return 0;
 }
 
-
-static __inline__ struct atm_flow_data *lookup_flow(struct Qdisc *sch,
-    u32 classid)
+static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct atm_flow_data *flow;
 
 	for (flow = p->flows; flow; flow = flow->next)
-		if (flow->classid == classid) break;
+		if (flow->classid == classid)
+			break;
 	return flow;
 }
 
-
-static int atm_tc_graft(struct Qdisc *sch,unsigned long arg,
-    struct Qdisc *new,struct Qdisc **old)
+static int atm_tc_graft(struct Qdisc *sch, unsigned long arg,
+			struct Qdisc *new, struct Qdisc **old)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
-	struct atm_flow_data *flow = (struct atm_flow_data *) arg;
+	struct atm_flow_data *flow = (struct atm_flow_data *)arg;
 
-	DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",sch,
-	    p,flow,new,old);
-	if (!find_flow(p,flow)) return -EINVAL;
-	if (!new) new = &noop_qdisc;
-	*old = xchg(&flow->q,new);
-	if (*old) qdisc_reset(*old);
+	DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",
+		sch, p, flow, new, old);
+	if (!find_flow(p, flow))
+		return -EINVAL;
+	if (!new)
+		new = &noop_qdisc;
+	*old = xchg(&flow->q, new);
+	if (*old)
+		qdisc_reset(*old);
 	return 0;
 }
 
-
-static struct Qdisc *atm_tc_leaf(struct Qdisc *sch,unsigned long cl)
+static struct Qdisc *atm_tc_leaf(struct Qdisc *sch, unsigned long cl)
 {
-	struct atm_flow_data *flow = (struct atm_flow_data *) cl;
+	struct atm_flow_data *flow = (struct atm_flow_data *)cl;
 
-	DPRINTK("atm_tc_leaf(sch %p,flow %p)\n",sch,flow);
+	DPRINTK("atm_tc_leaf(sch %p,flow %p)\n", sch, flow);
 	return flow ? flow->q : NULL;
 }
 
-
-static unsigned long atm_tc_get(struct Qdisc *sch,u32 classid)
+static unsigned long atm_tc_get(struct Qdisc *sch, u32 classid)
 {
-	struct atm_qdisc_data *p __attribute__((unused)) = PRIV(sch);
+	struct atm_qdisc_data *p __maybe_unused = PRIV(sch);
 	struct atm_flow_data *flow;
 
-	DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
-	flow = lookup_flow(sch,classid);
-	if (flow) flow->ref++;
-	DPRINTK("atm_tc_get: flow %p\n",flow);
-	return (unsigned long) flow;
+	DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
+	flow = lookup_flow(sch, classid);
+	if (flow)
+		flow->ref++;
+	DPRINTK("atm_tc_get: flow %p\n", flow);
+	return (unsigned long)flow;
 }
 
-
 static unsigned long atm_tc_bind_filter(struct Qdisc *sch,
-    unsigned long parent, u32 classid)
+					unsigned long parent, u32 classid)
 {
-	return atm_tc_get(sch,classid);
+	return atm_tc_get(sch, classid);
 }
 
 /*
@@ -163,72 +153,75 @@
  * requested (atm_tc_destroy, etc.). The assumption here is that we never drop
  * anything that still seems to be in use.
  */
-
 static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
-	struct atm_flow_data *flow = (struct atm_flow_data *) cl;
+	struct atm_flow_data *flow = (struct atm_flow_data *)cl;
 	struct atm_flow_data **prev;
 
-	DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n",sch,p,flow);
-	if (--flow->ref) return;
+	DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+	if (--flow->ref)
+		return;
 	DPRINTK("atm_tc_put: destroying\n");
 	for (prev = &p->flows; *prev; prev = &(*prev)->next)
-		if (*prev == flow) break;
+		if (*prev == flow)
+			break;
 	if (!*prev) {
-		printk(KERN_CRIT "atm_tc_put: class %p not found\n",flow);
+		printk(KERN_CRIT "atm_tc_put: class %p not found\n", flow);
 		return;
 	}
 	*prev = flow->next;
-	DPRINTK("atm_tc_put: qdisc %p\n",flow->q);
+	DPRINTK("atm_tc_put: qdisc %p\n", flow->q);
 	qdisc_destroy(flow->q);
 	tcf_destroy_chain(flow->filter_list);
 	if (flow->sock) {
 		DPRINTK("atm_tc_put: f_count %d\n",
-		    file_count(flow->sock->file));
+			file_count(flow->sock->file));
 		flow->vcc->pop = flow->old_pop;
 		sockfd_put(flow->sock);
 	}
-	if (flow->excess) atm_tc_put(sch,(unsigned long) flow->excess);
-	if (flow != &p->link) kfree(flow);
+	if (flow->excess)
+		atm_tc_put(sch, (unsigned long)flow->excess);
+	if (flow != &p->link)
+		kfree(flow);
 	/*
 	 * If flow == &p->link, the qdisc no longer works at this point and
 	 * needs to be removed. (By the caller of atm_tc_put.)
 	 */
 }
 
-
-static void sch_atm_pop(struct atm_vcc *vcc,struct sk_buff *skb)
+static void sch_atm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 {
 	struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent;
 
-	D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n",vcc,skb,p);
-	VCC2FLOW(vcc)->old_pop(vcc,skb);
+	D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p);
+	VCC2FLOW(vcc)->old_pop(vcc, skb);
 	tasklet_schedule(&p->task);
 }
 
 static const u8 llc_oui_ip[] = {
-	0xaa,		/* DSAP: non-ISO */
-	0xaa,		/* SSAP: non-ISO */
-	0x03,		/* Ctrl: Unnumbered Information Command PDU */
-	0x00,		/* OUI: EtherType */
+	0xaa,			/* DSAP: non-ISO */
+	0xaa,			/* SSAP: non-ISO */
+	0x03,			/* Ctrl: Unnumbered Information Command PDU */
+	0x00,			/* OUI: EtherType */
 	0x00, 0x00,
-	0x08, 0x00 };	/* Ethertype IP (0800) */
+	0x08, 0x00
+};				/* Ethertype IP (0800) */
 
 static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
-    struct rtattr **tca, unsigned long *arg)
+			 struct rtattr **tca, unsigned long *arg)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
-	struct atm_flow_data *flow = (struct atm_flow_data *) *arg;
+	struct atm_flow_data *flow = (struct atm_flow_data *)*arg;
 	struct atm_flow_data *excess = NULL;
-	struct rtattr *opt = tca[TCA_OPTIONS-1];
+	struct rtattr *opt = tca[TCA_OPTIONS - 1];
 	struct rtattr *tb[TCA_ATM_MAX];
 	struct socket *sock;
-	int fd,error,hdr_len;
+	int fd, error, hdr_len;
 	void *hdr;
 
 	DPRINTK("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x,"
-	    "flow %p,opt %p)\n",sch,p,classid,parent,flow,opt);
+		"flow %p,opt %p)\n", sch, p, classid, parent, flow, opt);
 	/*
 	 * The concept of parents doesn't apply for this qdisc.
 	 */
@@ -241,33 +234,36 @@
 	 * class needs to be removed and a new one added. (This may be changed
 	 * later.)
 	 */
-	if (flow) return -EBUSY;
+	if (flow)
+		return -EBUSY;
 	if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt))
 		return -EINVAL;
-	if (!tb[TCA_ATM_FD-1] || RTA_PAYLOAD(tb[TCA_ATM_FD-1]) < sizeof(fd))
+	if (!tb[TCA_ATM_FD - 1] || RTA_PAYLOAD(tb[TCA_ATM_FD - 1]) < sizeof(fd))
 		return -EINVAL;
-	fd = *(int *) RTA_DATA(tb[TCA_ATM_FD-1]);
-	DPRINTK("atm_tc_change: fd %d\n",fd);
-	if (tb[TCA_ATM_HDR-1]) {
-		hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR-1]);
-		hdr = RTA_DATA(tb[TCA_ATM_HDR-1]);
-	}
-	else {
+	fd = *(int *)RTA_DATA(tb[TCA_ATM_FD - 1]);
+	DPRINTK("atm_tc_change: fd %d\n", fd);
+	if (tb[TCA_ATM_HDR - 1]) {
+		hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR - 1]);
+		hdr = RTA_DATA(tb[TCA_ATM_HDR - 1]);
+	} else {
 		hdr_len = RFC1483LLC_LEN;
-		hdr = NULL; /* default LLC/SNAP for IP */
+		hdr = NULL;	/* default LLC/SNAP for IP */
 	}
-	if (!tb[TCA_ATM_EXCESS-1]) excess = NULL;
+	if (!tb[TCA_ATM_EXCESS - 1])
+		excess = NULL;
 	else {
-		if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS-1]) != sizeof(u32))
+		if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS - 1]) != sizeof(u32))
 			return -EINVAL;
-		excess = (struct atm_flow_data *) atm_tc_get(sch,
-		    *(u32 *) RTA_DATA(tb[TCA_ATM_EXCESS-1]));
-		if (!excess) return -ENOENT;
+		excess = (struct atm_flow_data *)
+			atm_tc_get(sch, *(u32 *)RTA_DATA(tb[TCA_ATM_EXCESS - 1]));
+		if (!excess)
+			return -ENOENT;
 	}
 	DPRINTK("atm_tc_change: type %d, payload %d, hdr_len %d\n",
-	    opt->rta_type,RTA_PAYLOAD(opt),hdr_len);
-	if (!(sock = sockfd_lookup(fd,&error))) return error; /* f_count++ */
-	DPRINTK("atm_tc_change: f_count %d\n",file_count(sock->file));
+		opt->rta_type, RTA_PAYLOAD(opt), hdr_len);
+	if (!(sock = sockfd_lookup(fd, &error)))
+		return error;	/* f_count++ */
+	DPRINTK("atm_tc_change: f_count %d\n", file_count(sock->file));
 	if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
 		error = -EPROTOTYPE;
 		goto err_out;
@@ -280,37 +276,37 @@
 			error = -EINVAL;
 			goto err_out;
 		}
-		if (find_flow(p,flow)) {
+		if (find_flow(p, flow)) {
 			error = -EEXIST;
 			goto err_out;
 		}
-	}
-	else {
+	} else {
 		int i;
 		unsigned long cl;
 
 		for (i = 1; i < 0x8000; i++) {
-			classid = TC_H_MAKE(sch->handle,0x8000 | i);
-			if (!(cl = atm_tc_get(sch,classid))) break;
-			atm_tc_put(sch,cl);
+			classid = TC_H_MAKE(sch->handle, 0x8000 | i);
+			if (!(cl = atm_tc_get(sch, classid)))
+				break;
+			atm_tc_put(sch, cl);
 		}
 	}
-	DPRINTK("atm_tc_change: new id %x\n",classid);
-	flow = kmalloc(sizeof(struct atm_flow_data)+hdr_len,GFP_KERNEL);
-	DPRINTK("atm_tc_change: flow %p\n",flow);
+	DPRINTK("atm_tc_change: new id %x\n", classid);
+	flow = kmalloc(sizeof(struct atm_flow_data) + hdr_len, GFP_KERNEL);
+	DPRINTK("atm_tc_change: flow %p\n", flow);
 	if (!flow) {
 		error = -ENOBUFS;
 		goto err_out;
 	}
-	memset(flow,0,sizeof(*flow));
+	memset(flow, 0, sizeof(*flow));
 	flow->filter_list = NULL;
-	if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,classid)))
+	if (!(flow->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid)))
 		flow->q = &noop_qdisc;
-	DPRINTK("atm_tc_change: qdisc %p\n",flow->q);
+	DPRINTK("atm_tc_change: qdisc %p\n", flow->q);
 	flow->sock = sock;
-	flow->vcc = ATM_SD(sock); /* speedup */
+	flow->vcc = ATM_SD(sock);	/* speedup */
 	flow->vcc->user_back = flow;
-	DPRINTK("atm_tc_change: vcc %p\n",flow->vcc);
+	DPRINTK("atm_tc_change: vcc %p\n", flow->vcc);
 	flow->old_pop = flow->vcc->pop;
 	flow->parent = p;
 	flow->vcc->pop = sch_atm_pop;
@@ -321,50 +317,53 @@
 	p->link.next = flow;
 	flow->hdr_len = hdr_len;
 	if (hdr)
-		memcpy(flow->hdr,hdr,hdr_len);
+		memcpy(flow->hdr, hdr, hdr_len);
 	else
-		memcpy(flow->hdr,llc_oui_ip,sizeof(llc_oui_ip));
-	*arg = (unsigned long) flow;
+		memcpy(flow->hdr, llc_oui_ip, sizeof(llc_oui_ip));
+	*arg = (unsigned long)flow;
 	return 0;
 err_out:
-	if (excess) atm_tc_put(sch,(unsigned long) excess);
+	if (excess)
+		atm_tc_put(sch, (unsigned long)excess);
 	sockfd_put(sock);
 	return error;
 }
 
-
-static int atm_tc_delete(struct Qdisc *sch,unsigned long arg)
+static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
-	struct atm_flow_data *flow = (struct atm_flow_data *) arg;
+	struct atm_flow_data *flow = (struct atm_flow_data *)arg;
 
-	DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n",sch,p,flow);
-	if (!find_flow(PRIV(sch),flow)) return -EINVAL;
-	if (flow->filter_list || flow == &p->link) return -EBUSY;
+	DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+	if (!find_flow(PRIV(sch), flow))
+		return -EINVAL;
+	if (flow->filter_list || flow == &p->link)
+		return -EBUSY;
 	/*
 	 * Reference count must be 2: one for "keepalive" (set at class
 	 * creation), and one for the reference held when calling delete.
 	 */
 	if (flow->ref < 2) {
-		printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n",flow->ref);
+		printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n", flow->ref);
 		return -EINVAL;
 	}
-	if (flow->ref > 2) return -EBUSY; /* catch references via excess, etc.*/
-	atm_tc_put(sch,arg);
+	if (flow->ref > 2)
+		return -EBUSY;	/* catch references via excess, etc. */
+	atm_tc_put(sch, arg);
 	return 0;
 }
 
-
-static void atm_tc_walk(struct Qdisc *sch,struct qdisc_walker *walker)
+static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct atm_flow_data *flow;
 
-	DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker);
-	if (walker->stop) return;
+	DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+	if (walker->stop)
+		return;
 	for (flow = p->flows; flow; flow = flow->next) {
 		if (walker->count >= walker->skip)
-			if (walker->fn(sch,(unsigned long) flow,walker) < 0) {
+			if (walker->fn(sch, (unsigned long)flow, walker) < 0) {
 				walker->stop = 1;
 				break;
 			}
@@ -372,73 +371,71 @@
 	}
 }
 
-
-static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch,unsigned long cl)
+static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch, unsigned long cl)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
-	struct atm_flow_data *flow = (struct atm_flow_data *) cl;
+	struct atm_flow_data *flow = (struct atm_flow_data *)cl;
 
-	DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n",sch,p,flow);
+	DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
 	return flow ? &flow->filter_list : &p->link.filter_list;
 }
 
-
 /* --------------------------- Qdisc operations ---------------------------- */
 
-
-static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch)
+static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
-	struct atm_flow_data *flow = NULL ; /* @@@ */
+	struct atm_flow_data *flow = NULL;	/* @@@ */
 	struct tcf_result res;
 	int result;
 	int ret = NET_XMIT_POLICED;
 
-	D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
-	result = TC_POLICE_OK; /* be nice to gcc */
+	D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+	result = TC_POLICE_OK;	/* be nice to gcc */
 	if (TC_H_MAJ(skb->priority) != sch->handle ||
-	    !(flow = (struct atm_flow_data *) atm_tc_get(sch,skb->priority)))
+	    !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority)))
 		for (flow = p->flows; flow; flow = flow->next)
 			if (flow->filter_list) {
-				result = tc_classify(skb,flow->filter_list,
-				    &res);
-				if (result < 0) continue;
-				flow = (struct atm_flow_data *) res.class;
-				if (!flow) flow = lookup_flow(sch,res.classid);
+				result = tc_classify_compat(skb,
+							    flow->filter_list,
+							    &res);
+				if (result < 0)
+					continue;
+				flow = (struct atm_flow_data *)res.class;
+				if (!flow)
+					flow = lookup_flow(sch, res.classid);
 				break;
 			}
-	if (!flow) flow = &p->link;
+	if (!flow)
+		flow = &p->link;
 	else {
 		if (flow->vcc)
 			ATM_SKB(skb)->atm_options = flow->vcc->atm_options;
-			/*@@@ looks good ... but it's not supposed to work :-)*/
-#ifdef CONFIG_NET_CLS_POLICE
+		/*@@@ looks good ... but it's not supposed to work :-) */
+#ifdef CONFIG_NET_CLS_ACT
 		switch (result) {
-			case TC_POLICE_SHOT:
-				kfree_skb(skb);
-				break;
-			case TC_POLICE_RECLASSIFY:
-				if (flow->excess) flow = flow->excess;
-				else {
-					ATM_SKB(skb)->atm_options |=
-					    ATM_ATMOPT_CLP;
-					break;
-				}
-				/* fall through */
-			case TC_POLICE_OK:
-				/* fall through */
-			default:
-				break;
+		case TC_ACT_QUEUED:
+		case TC_ACT_STOLEN:
+			kfree_skb(skb);
+			return NET_XMIT_SUCCESS;
+		case TC_ACT_SHOT:
+			kfree_skb(skb);
+			goto drop;
+		case TC_POLICE_RECLASSIFY:
+			if (flow->excess)
+				flow = flow->excess;
+			else
+				ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP;
+			break;
 		}
 #endif
 	}
-	if (
-#ifdef CONFIG_NET_CLS_POLICE
-	    result == TC_POLICE_SHOT ||
-#endif
-	    (ret = flow->q->enqueue(skb,flow->q)) != 0) {
+
+	if ((ret = flow->q->enqueue(skb, flow->q)) != 0) {
+drop: __maybe_unused
 		sch->qstats.drops++;
-		if (flow) flow->qstats.drops++;
+		if (flow)
+			flow->qstats.drops++;
 		return ret;
 	}
 	sch->bstats.bytes += skb->len;
@@ -462,7 +459,6 @@
 	return NET_XMIT_BYPASS;
 }
 
-
 /*
  * Dequeue packets and send them over ATM. Note that we quite deliberately
  * avoid checking net_device's flow control here, simply because sch_atm
@@ -470,166 +466,163 @@
  * non-ATM interfaces.
  */
 
-
 static void sch_atm_dequeue(unsigned long data)
 {
-	struct Qdisc *sch = (struct Qdisc *) data;
+	struct Qdisc *sch = (struct Qdisc *)data;
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct atm_flow_data *flow;
 	struct sk_buff *skb;
 
-	D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n",sch,p);
+	D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p);
 	for (flow = p->link.next; flow; flow = flow->next)
 		/*
 		 * If traffic is properly shaped, this won't generate nasty
 		 * little bursts. Otherwise, it may ... (but that's okay)
 		 */
 		while ((skb = flow->q->dequeue(flow->q))) {
-			if (!atm_may_send(flow->vcc,skb->truesize)) {
-				(void) flow->q->ops->requeue(skb,flow->q);
+			if (!atm_may_send(flow->vcc, skb->truesize)) {
+				(void)flow->q->ops->requeue(skb, flow->q);
 				break;
 			}
-			D2PRINTK("atm_tc_dequeue: sending on class %p\n",flow);
+			D2PRINTK("atm_tc_dequeue: sending on class %p\n", flow);
 			/* remove any LL header somebody else has attached */
 			skb_pull(skb, skb_network_offset(skb));
 			if (skb_headroom(skb) < flow->hdr_len) {
 				struct sk_buff *new;
 
-				new = skb_realloc_headroom(skb,flow->hdr_len);
+				new = skb_realloc_headroom(skb, flow->hdr_len);
 				dev_kfree_skb(skb);
-				if (!new) continue;
+				if (!new)
+					continue;
 				skb = new;
 			}
 			D2PRINTK("sch_atm_dequeue: ip %p, data %p\n",
 				 skb_network_header(skb), skb->data);
 			ATM_SKB(skb)->vcc = flow->vcc;
-			memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
-			    flow->hdr_len);
+			memcpy(skb_push(skb, flow->hdr_len), flow->hdr,
+			       flow->hdr_len);
 			atomic_add(skb->truesize,
 				   &sk_atm(flow->vcc)->sk_wmem_alloc);
 			/* atm.atm_options are already set by atm_tc_enqueue */
-			(void) flow->vcc->send(flow->vcc,skb);
+			flow->vcc->send(flow->vcc, skb);
 		}
 }
 
-
 static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct sk_buff *skb;
 
-	D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n",sch,p);
+	D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p);
 	tasklet_schedule(&p->task);
 	skb = p->link.q->dequeue(p->link.q);
-	if (skb) sch->q.qlen--;
+	if (skb)
+		sch->q.qlen--;
 	return skb;
 }
 
-
-static int atm_tc_requeue(struct sk_buff *skb,struct Qdisc *sch)
+static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 	int ret;
 
-	D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
-	ret = p->link.q->ops->requeue(skb,p->link.q);
+	D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+	ret = p->link.q->ops->requeue(skb, p->link.q);
 	if (!ret) {
-	sch->q.qlen++;
-	sch->qstats.requeues++;
-    } else {
+		sch->q.qlen++;
+		sch->qstats.requeues++;
+	} else {
 		sch->qstats.drops++;
 		p->link.qstats.drops++;
 	}
 	return ret;
 }
 
-
 static unsigned int atm_tc_drop(struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct atm_flow_data *flow;
 	unsigned int len;
 
-	DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n",sch,p);
+	DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n", sch, p);
 	for (flow = p->flows; flow; flow = flow->next)
 		if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q)))
 			return len;
 	return 0;
 }
 
-
-static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt)
+static int atm_tc_init(struct Qdisc *sch, struct rtattr *opt)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 
-	DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
+	DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
 	p->flows = &p->link;
-	if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,
-					   sch->handle)))
+	if (!(p->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+					    sch->handle)))
 		p->link.q = &noop_qdisc;
-	DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q);
+	DPRINTK("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
 	p->link.filter_list = NULL;
 	p->link.vcc = NULL;
 	p->link.sock = NULL;
 	p->link.classid = sch->handle;
 	p->link.ref = 1;
 	p->link.next = NULL;
-	tasklet_init(&p->task,sch_atm_dequeue,(unsigned long) sch);
+	tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch);
 	return 0;
 }
 
-
 static void atm_tc_reset(struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct atm_flow_data *flow;
 
-	DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n",sch,p);
-	for (flow = p->flows; flow; flow = flow->next) qdisc_reset(flow->q);
+	DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
+	for (flow = p->flows; flow; flow = flow->next)
+		qdisc_reset(flow->q);
 	sch->q.qlen = 0;
 }
 
-
 static void atm_tc_destroy(struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct atm_flow_data *flow;
 
-	DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p);
+	DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
 	/* races ? */
 	while ((flow = p->flows)) {
 		tcf_destroy_chain(flow->filter_list);
+		flow->filter_list = NULL;
 		if (flow->ref > 1)
-			printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow,
-			    flow->ref);
-		atm_tc_put(sch,(unsigned long) flow);
+			printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow,
+			       flow->ref);
+		atm_tc_put(sch, (unsigned long)flow);
 		if (p->flows == flow) {
 			printk(KERN_ERR "atm_destroy: putting flow %p didn't "
-			    "kill it\n",flow);
-			p->flows = flow->next; /* brute force */
+			       "kill it\n", flow);
+			p->flows = flow->next;	/* brute force */
 			break;
 		}
 	}
 	tasklet_kill(&p->task);
 }
 
-
 static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
-    struct sk_buff *skb, struct tcmsg *tcm)
+			     struct sk_buff *skb, struct tcmsg *tcm)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
-	struct atm_flow_data *flow = (struct atm_flow_data *) cl;
+	struct atm_flow_data *flow = (struct atm_flow_data *)cl;
 	unsigned char *b = skb_tail_pointer(skb);
 	struct rtattr *rta;
 
 	DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
-	    sch,p,flow,skb,tcm);
-	if (!find_flow(p,flow)) return -EINVAL;
+		sch, p, flow, skb, tcm);
+	if (!find_flow(p, flow))
+		return -EINVAL;
 	tcm->tcm_handle = flow->classid;
 	tcm->tcm_info = flow->q->handle;
-	rta = (struct rtattr *) b;
-	RTA_PUT(skb,TCA_OPTIONS,0,NULL);
-	RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr);
+	rta = (struct rtattr *)b;
+	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	RTA_PUT(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr);
 	if (flow->vcc) {
 		struct sockaddr_atmpvc pvc;
 		int state;
@@ -638,16 +631,16 @@
 		pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1;
 		pvc.sap_addr.vpi = flow->vcc->vpi;
 		pvc.sap_addr.vci = flow->vcc->vci;
-		RTA_PUT(skb,TCA_ATM_ADDR,sizeof(pvc),&pvc);
+		RTA_PUT(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc);
 		state = ATM_VF2VS(flow->vcc->flags);
-		RTA_PUT(skb,TCA_ATM_STATE,sizeof(state),&state);
+		RTA_PUT(skb, TCA_ATM_STATE, sizeof(state), &state);
 	}
 	if (flow->excess)
-		RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(u32),&flow->classid);
+		RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(u32), &flow->classid);
 	else {
 		static u32 zero;
 
-		RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(zero),&zero);
+		RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(zero), &zero);
 	}
 	rta->rta_len = skb_tail_pointer(skb) - b;
 	return skb->len;
@@ -658,9 +651,9 @@
 }
 static int
 atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
-	struct gnet_dump *d)
+			struct gnet_dump *d)
 {
-	struct atm_flow_data *flow = (struct atm_flow_data *) arg;
+	struct atm_flow_data *flow = (struct atm_flow_data *)arg;
 
 	flow->qstats.qlen = flow->q->q.qlen;
 
@@ -677,38 +670,35 @@
 }
 
 static struct Qdisc_class_ops atm_class_ops = {
-	.graft		=	atm_tc_graft,
-	.leaf		=	atm_tc_leaf,
-	.get		=	atm_tc_get,
-	.put		=	atm_tc_put,
-	.change		=	atm_tc_change,
-	.delete		=	atm_tc_delete,
-	.walk		=	atm_tc_walk,
-	.tcf_chain	=	atm_tc_find_tcf,
-	.bind_tcf	=	atm_tc_bind_filter,
-	.unbind_tcf	=	atm_tc_put,
-	.dump		=	atm_tc_dump_class,
-	.dump_stats	=	atm_tc_dump_class_stats,
+	.graft		= atm_tc_graft,
+	.leaf		= atm_tc_leaf,
+	.get		= atm_tc_get,
+	.put		= atm_tc_put,
+	.change		= atm_tc_change,
+	.delete		= atm_tc_delete,
+	.walk		= atm_tc_walk,
+	.tcf_chain	= atm_tc_find_tcf,
+	.bind_tcf	= atm_tc_bind_filter,
+	.unbind_tcf	= atm_tc_put,
+	.dump		= atm_tc_dump_class,
+	.dump_stats	= atm_tc_dump_class_stats,
 };
 
 static struct Qdisc_ops atm_qdisc_ops = {
-	.next		=	NULL,
-	.cl_ops		=	&atm_class_ops,
-	.id		=	"atm",
-	.priv_size	=	sizeof(struct atm_qdisc_data),
-	.enqueue	=	atm_tc_enqueue,
-	.dequeue	=	atm_tc_dequeue,
-	.requeue	=	atm_tc_requeue,
-	.drop		=	atm_tc_drop,
-	.init		=	atm_tc_init,
-	.reset		=	atm_tc_reset,
-	.destroy	=	atm_tc_destroy,
-	.change		=	NULL,
-	.dump		=	atm_tc_dump,
-	.owner		=	THIS_MODULE,
+	.cl_ops		= &atm_class_ops,
+	.id		= "atm",
+	.priv_size	= sizeof(struct atm_qdisc_data),
+	.enqueue	= atm_tc_enqueue,
+	.dequeue	= atm_tc_dequeue,
+	.requeue	= atm_tc_requeue,
+	.drop		= atm_tc_drop,
+	.init		= atm_tc_init,
+	.reset		= atm_tc_reset,
+	.destroy	= atm_tc_destroy,
+	.dump		= atm_tc_dump,
+	.owner		= THIS_MODULE,
 };
 
-
 static int __init atm_init(void)
 {
 	return register_qdisc(&atm_qdisc_ops);
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c
index cb0c456..f914fc4 100644
--- a/net/sched/sch_blackhole.c
+++ b/net/sched/sch_blackhole.c
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index a294542..e38c283 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -11,28 +11,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/pkt_sched.h>
 
 
@@ -98,7 +82,7 @@
 	unsigned char		priority2;	/* priority to be used after overlimit */
 	unsigned char		ewma_log;	/* time constant for idle time calculation */
 	unsigned char		ovl_strategy;
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	unsigned char		police;
 #endif
 
@@ -148,7 +132,6 @@
 	struct gnet_stats_basic bstats;
 	struct gnet_stats_queue qstats;
 	struct gnet_stats_rate_est rate_est;
-	spinlock_t		*stats_lock;
 	struct tc_cbq_xstats	xstats;
 
 	struct tcf_proto	*filter_list;
@@ -171,7 +154,7 @@
 	struct cbq_class	*active[TC_CBQ_MAXPRIO+1];	/* List of all classes
 								   with backlog */
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	struct cbq_class	*rx_class;
 #endif
 	struct cbq_class	*tx_class;
@@ -213,7 +196,7 @@
 	return NULL;
 }
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 
 static struct cbq_class *
 cbq_reclassify(struct sk_buff *skb, struct cbq_class *this)
@@ -264,7 +247,8 @@
 		/*
 		 * Step 2+n. Apply classifier.
 		 */
-		if (!head->filter_list || (result = tc_classify(skb, head->filter_list, &res)) < 0)
+		if (!head->filter_list ||
+		    (result = tc_classify_compat(skb, head->filter_list, &res)) < 0)
 			goto fallback;
 
 		if ((cl = (void*)res.class) == NULL) {
@@ -284,15 +268,8 @@
 			*qerr = NET_XMIT_SUCCESS;
 		case TC_ACT_SHOT:
 			return NULL;
-		}
-#elif defined(CONFIG_NET_CLS_POLICE)
-		switch (result) {
-		case TC_POLICE_RECLASSIFY:
+		case TC_ACT_RECLASSIFY:
 			return cbq_reclassify(skb, cl);
-		case TC_POLICE_SHOT:
-			return NULL;
-		default:
-			break;
 		}
 #endif
 		if (cl->level == 0)
@@ -406,7 +383,7 @@
 	int ret;
 	struct cbq_class *cl = cbq_classify(skb, sch, &ret);
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	q->rx_class = cl;
 #endif
 	if (cl == NULL) {
@@ -416,7 +393,7 @@
 		return ret;
 	}
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	cl->q->__parent = sch;
 #endif
 	if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) {
@@ -451,7 +428,7 @@
 
 	cbq_mark_toplevel(q, cl);
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	q->rx_class = cl;
 	cl->q->__parent = sch;
 #endif
@@ -686,9 +663,7 @@
 	return HRTIMER_NORESTART;
 }
 
-
-#ifdef CONFIG_NET_CLS_POLICE
-
+#ifdef CONFIG_NET_CLS_ACT
 static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child)
 {
 	int len = skb->len;
@@ -1381,7 +1356,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p)
 {
 	cl->police = p->police;
@@ -1442,7 +1417,6 @@
 	q->link.ewma_log = TC_CBQ_DEF_EWMA;
 	q->link.avpkt = q->link.allot/2;
 	q->link.minidle = -0x7FFFFFFF;
-	q->link.stats_lock = &sch->dev->queue_lock;
 
 	qdisc_watchdog_init(&q->watchdog, sch);
 	hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
@@ -1550,7 +1524,7 @@
 	return -1;
 }
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl)
 {
 	unsigned char *b = skb_tail_pointer(skb);
@@ -1576,7 +1550,7 @@
 	    cbq_dump_rate(skb, cl) < 0 ||
 	    cbq_dump_wrr(skb, cl) < 0 ||
 	    cbq_dump_ovl(skb, cl) < 0 ||
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	    cbq_dump_police(skb, cl) < 0 ||
 #endif
 	    cbq_dump_fopt(skb, cl) < 0)
@@ -1653,9 +1627,7 @@
 		cl->xstats.undertime = cl->undertime - q->now;
 
 	if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(d, &cl->qstats) < 0)
 		return -1;
 
@@ -1673,7 +1645,7 @@
 						     cl->classid)) == NULL)
 				return -ENOBUFS;
 		} else {
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 			if (cl->police == TC_POLICE_RECLASSIFY)
 				new->reshape_fail = cbq_reshape_fail;
 #endif
@@ -1726,9 +1698,7 @@
 	tcf_destroy_chain(cl->filter_list);
 	qdisc_destroy(cl->q);
 	qdisc_put_rtab(cl->R_tab);
-#ifdef CONFIG_NET_ESTIMATOR
 	gen_kill_estimator(&cl->bstats, &cl->rate_est);
-#endif
 	if (cl != &q->link)
 		kfree(cl);
 }
@@ -1740,7 +1710,7 @@
 	struct cbq_class *cl;
 	unsigned h;
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	q->rx_class = NULL;
 #endif
 	/*
@@ -1748,10 +1718,12 @@
 	 * classes from root to leafs which means that filters can still
 	 * be bound to classes which have been destroyed already. --TGR '04
 	 */
-	for (h = 0; h < 16; h++)
-		for (cl = q->classes[h]; cl; cl = cl->next)
+	for (h = 0; h < 16; h++) {
+		for (cl = q->classes[h]; cl; cl = cl->next) {
 			tcf_destroy_chain(cl->filter_list);
-
+			cl->filter_list = NULL;
+		}
+	}
 	for (h = 0; h < 16; h++) {
 		struct cbq_class *next;
 
@@ -1767,7 +1739,7 @@
 	struct cbq_class *cl = (struct cbq_class*)arg;
 
 	if (--cl->refcnt == 0) {
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 		struct cbq_sched_data *q = qdisc_priv(sch);
 
 		spin_lock_bh(&sch->dev->queue_lock);
@@ -1815,7 +1787,7 @@
 	    RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt))
 			return -EINVAL;
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	if (tb[TCA_CBQ_POLICE-1] &&
 	    RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police))
 			return -EINVAL;
@@ -1858,7 +1830,7 @@
 		if (tb[TCA_CBQ_OVL_STRATEGY-1])
 			cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1]));
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 		if (tb[TCA_CBQ_POLICE-1])
 			cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1]));
 #endif
@@ -1871,11 +1843,10 @@
 
 		sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
 		if (tca[TCA_RATE-1])
 			gen_replace_estimator(&cl->bstats, &cl->rate_est,
-				cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+					      &sch->dev->queue_lock,
+					      tca[TCA_RATE-1]);
 		return 0;
 	}
 
@@ -1933,7 +1904,6 @@
 	cl->allot = parent->allot;
 	cl->quantum = cl->allot;
 	cl->weight = cl->R_tab->rate.rate;
-	cl->stats_lock = &sch->dev->queue_lock;
 
 	sch_tree_lock(sch);
 	cbq_link_class(cl);
@@ -1953,7 +1923,7 @@
 	cl->overlimit = cbq_ovl_classic;
 	if (tb[TCA_CBQ_OVL_STRATEGY-1])
 		cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1]));
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	if (tb[TCA_CBQ_POLICE-1])
 		cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1]));
 #endif
@@ -1961,11 +1931,9 @@
 		cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
 	sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tca[TCA_RATE-1])
 		gen_new_estimator(&cl->bstats, &cl->rate_est,
-			cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+				  &sch->dev->queue_lock, tca[TCA_RATE-1]);
 
 	*arg = (unsigned long)cl;
 	return 0;
@@ -1999,7 +1967,7 @@
 		q->tx_class = NULL;
 		q->tx_borrowed = NULL;
 	}
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 	if (q->rx_class == cl)
 		q->rx_class = NULL;
 #endif
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 3c6fd18..60f8919 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -9,7 +9,6 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
-#include <linux/netdevice.h> /* for pkt_sched */
 #include <linux/rtnetlink.h>
 #include <net/pkt_sched.h>
 #include <net/dsfield.h>
@@ -238,25 +237,23 @@
 		D2PRINTK("result %d class 0x%04x\n", result, res.classid);
 
 		switch (result) {
-#ifdef CONFIG_NET_CLS_POLICE
-			case TC_POLICE_SHOT:
-				kfree_skb(skb);
-				sch->qstats.drops++;
-				return NET_XMIT_POLICED;
-#if 0
-			case TC_POLICE_RECLASSIFY:
-				/* FIXME: what to do here ??? */
+#ifdef CONFIG_NET_CLS_ACT
+		case TC_ACT_QUEUED:
+		case TC_ACT_STOLEN:
+			kfree_skb(skb);
+			return NET_XMIT_SUCCESS;
+		case TC_ACT_SHOT:
+			kfree_skb(skb);
+			sch->qstats.drops++;
+			return NET_XMIT_BYPASS;
 #endif
-#endif
-			case TC_POLICE_OK:
-				skb->tc_index = TC_H_MIN(res.classid);
-				break;
-			case TC_POLICE_UNSPEC:
-				/* fall through */
-			default:
-				if (p->default_index != NO_DEFAULT_INDEX)
-					skb->tc_index = p->default_index;
-				break;
+		case TC_ACT_OK:
+			skb->tc_index = TC_H_MIN(res.classid);
+			break;
+		default:
+			if (p->default_index != NO_DEFAULT_INDEX)
+				skb->tc_index = p->default_index;
+			break;
 		}
 	}
 
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index c2689f4..c264308 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -13,7 +13,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index f28bb2d..c81649c 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -11,27 +11,19 @@
  *              - Ingress support
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
 #include <linux/rcupdate.h>
 #include <linux/list.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
 /* Main transmission queue. */
@@ -59,122 +51,143 @@
 	spin_unlock_bh(&dev->queue_lock);
 }
 
+static inline int qdisc_qlen(struct Qdisc *q)
+{
+	return q->q.qlen;
+}
+
+static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev,
+				  struct Qdisc *q)
+{
+	if (unlikely(skb->next))
+		dev->gso_skb = skb;
+	else
+		q->ops->requeue(skb, q);
+
+	netif_schedule(dev);
+	return 0;
+}
+
+static inline struct sk_buff *dev_dequeue_skb(struct net_device *dev,
+					      struct Qdisc *q)
+{
+	struct sk_buff *skb;
+
+	if ((skb = dev->gso_skb))
+		dev->gso_skb = NULL;
+	else
+		skb = q->dequeue(q);
+
+	return skb;
+}
+
+static inline int handle_dev_cpu_collision(struct sk_buff *skb,
+					   struct net_device *dev,
+					   struct Qdisc *q)
+{
+	int ret;
+
+	if (unlikely(dev->xmit_lock_owner == smp_processor_id())) {
+		/*
+		 * Same CPU holding the lock. It may be a transient
+		 * configuration error, when hard_start_xmit() recurses. We
+		 * detect it by checking xmit owner and drop the packet when
+		 * deadloop is detected. Return OK to try the next skb.
+		 */
+		kfree_skb(skb);
+		if (net_ratelimit())
+			printk(KERN_WARNING "Dead loop on netdevice %s, "
+			       "fix it urgently!\n", dev->name);
+		ret = qdisc_qlen(q);
+	} else {
+		/*
+		 * Another cpu is holding lock, requeue & delay xmits for
+		 * some time.
+		 */
+		__get_cpu_var(netdev_rx_stat).cpu_collision++;
+		ret = dev_requeue_skb(skb, dev, q);
+	}
+
+	return ret;
+}
+
 /*
-   dev->queue_lock serializes queue accesses for this device
-   AND dev->qdisc pointer itself.
-
-   netif_tx_lock serializes accesses to device driver.
-
-   dev->queue_lock and netif_tx_lock are mutually exclusive,
-   if one is grabbed, another must be free.
+ * NOTE: Called under dev->queue_lock with locally disabled BH.
+ *
+ * __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this
+ * device at a time. dev->queue_lock serializes queue accesses for
+ * this device AND dev->qdisc pointer itself.
+ *
+ *  netif_tx_lock serializes accesses to device driver.
+ *
+ *  dev->queue_lock and netif_tx_lock are mutually exclusive,
+ *  if one is grabbed, another must be free.
+ *
+ * Note, that this procedure can be called by a watchdog timer
+ *
+ * Returns to the caller:
+ *				0  - queue is empty or throttled.
+ *				>0 - queue is not empty.
+ *
  */
-
-
-/* Kick device.
-
-   Returns:  0  - queue is empty or throttled.
-	    >0  - queue is not empty.
-
-   NOTE: Called under dev->queue_lock with locally disabled BH.
-*/
-
 static inline int qdisc_restart(struct net_device *dev)
 {
 	struct Qdisc *q = dev->qdisc;
 	struct sk_buff *skb;
+	unsigned lockless;
+	int ret;
 
 	/* Dequeue packet */
-	if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
-		unsigned nolock = (dev->features & NETIF_F_LLTX);
-
-		dev->gso_skb = NULL;
-
-		/*
-		 * When the driver has LLTX set it does its own locking
-		 * in start_xmit. No need to add additional overhead by
-		 * locking again. These checks are worth it because
-		 * even uncongested locks can be quite expensive.
-		 * The driver can do trylock like here too, in case
-		 * of lock congestion it should return -1 and the packet
-		 * will be requeued.
-		 */
-		if (!nolock) {
-			if (!netif_tx_trylock(dev)) {
-			collision:
-				/* So, someone grabbed the driver. */
-
-				/* It may be transient configuration error,
-				   when hard_start_xmit() recurses. We detect
-				   it by checking xmit owner and drop the
-				   packet when deadloop is detected.
-				*/
-				if (dev->xmit_lock_owner == smp_processor_id()) {
-					kfree_skb(skb);
-					if (net_ratelimit())
-						printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
-					goto out;
-				}
-				__get_cpu_var(netdev_rx_stat).cpu_collision++;
-				goto requeue;
-			}
-		}
-
-		{
-			/* And release queue */
-			spin_unlock(&dev->queue_lock);
-
-			if (!netif_queue_stopped(dev)) {
-				int ret;
-
-				ret = dev_hard_start_xmit(skb, dev);
-				if (ret == NETDEV_TX_OK) {
-					if (!nolock) {
-						netif_tx_unlock(dev);
-					}
-					spin_lock(&dev->queue_lock);
-					q = dev->qdisc;
-					goto out;
-				}
-				if (ret == NETDEV_TX_LOCKED && nolock) {
-					spin_lock(&dev->queue_lock);
-					q = dev->qdisc;
-					goto collision;
-				}
-			}
-
-			/* NETDEV_TX_BUSY - we need to requeue */
-			/* Release the driver */
-			if (!nolock) {
-				netif_tx_unlock(dev);
-			}
-			spin_lock(&dev->queue_lock);
-			q = dev->qdisc;
-		}
-
-		/* Device kicked us out :(
-		   This is possible in three cases:
-
-		   0. driver is locked
-		   1. fastroute is enabled
-		   2. device cannot determine busy state
-		      before start of transmission (f.e. dialout)
-		   3. device is buggy (ppp)
-		 */
-
-requeue:
-		if (unlikely(q == &noop_qdisc))
-			kfree_skb(skb);
-		else if (skb->next)
-			dev->gso_skb = skb;
-		else
-			q->ops->requeue(skb, q);
-		netif_schedule(dev);
+	if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
 		return 0;
+
+	/*
+	 * When the driver has LLTX set, it does its own locking in
+	 * start_xmit. These checks are worth it because even uncongested
+	 * locks can be quite expensive. The driver can do a trylock, as
+	 * is being done here; in case of lock contention it should return
+	 * NETDEV_TX_LOCKED and the packet will be requeued.
+	 */
+	lockless = (dev->features & NETIF_F_LLTX);
+
+	if (!lockless && !netif_tx_trylock(dev)) {
+		/* Another CPU grabbed the driver tx lock */
+		return handle_dev_cpu_collision(skb, dev, q);
 	}
 
-out:
-	BUG_ON((int) q->q.qlen < 0);
-	return q->q.qlen;
+	/* And release queue */
+	spin_unlock(&dev->queue_lock);
+
+	ret = dev_hard_start_xmit(skb, dev);
+
+	if (!lockless)
+		netif_tx_unlock(dev);
+
+	spin_lock(&dev->queue_lock);
+	q = dev->qdisc;
+
+	switch (ret) {
+	case NETDEV_TX_OK:
+		/* Driver sent out skb successfully */
+		ret = qdisc_qlen(q);
+		break;
+
+	case NETDEV_TX_LOCKED:
+		/* Driver try lock failed */
+		ret = handle_dev_cpu_collision(skb, dev, q);
+		break;
+
+	default:
+		/* Driver returned NETDEV_TX_BUSY - requeue skb */
+		if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit()))
+			printk(KERN_WARNING "BUG %s code %d qlen %d\n",
+			       dev->name, ret, q->q.qlen);
+
+		ret = dev_requeue_skb(skb, dev, q);
+		break;
+	}
+
+	return ret;
 }
 
 void __qdisc_run(struct net_device *dev)
@@ -224,7 +237,8 @@
 	if (dev->tx_timeout) {
 		if (dev->watchdog_timeo <= 0)
 			dev->watchdog_timeo = 5*HZ;
-		if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
+		if (!mod_timer(&dev->watchdog_timer,
+			       round_jiffies(jiffies + dev->watchdog_timeo)))
 			dev_hold(dev);
 	}
 }
@@ -492,9 +506,7 @@
 		return;
 
 	list_del(&qdisc->list);
-#ifdef CONFIG_NET_ESTIMATOR
 	gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
-#endif
 	if (ops->reset)
 		ops->reset(qdisc);
 	if (ops->destroy)
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index fa1b4fe..3cc6dda 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 #include <net/red.h>
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 9d124c4..55e7e45 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -53,7 +53,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/jiffies.h>
 #include <linux/compiler.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
@@ -62,13 +61,11 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <linux/init.h>
-#include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/pkt_sched.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
-#include <asm/system.h>
 #include <asm/div64.h>
 
 /*
@@ -122,7 +119,6 @@
 	struct gnet_stats_basic bstats;
 	struct gnet_stats_queue qstats;
 	struct gnet_stats_rate_est rate_est;
-	spinlock_t	*stats_lock;
 	unsigned int	level;		/* class level in hierarchy */
 	struct tcf_proto *filter_list;	/* filter list */
 	unsigned int	filter_cnt;	/* filter count */
@@ -1054,11 +1050,10 @@
 		}
 		sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
 		if (tca[TCA_RATE-1])
 			gen_replace_estimator(&cl->bstats, &cl->rate_est,
-				cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+					      &sch->dev->queue_lock,
+					      tca[TCA_RATE-1]);
 		return 0;
 	}
 
@@ -1098,7 +1093,6 @@
 	cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
 	if (cl->qdisc == NULL)
 		cl->qdisc = &noop_qdisc;
-	cl->stats_lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&cl->children);
 	cl->vt_tree = RB_ROOT;
 	cl->cf_tree = RB_ROOT;
@@ -1112,11 +1106,9 @@
 	cl->cl_pcvtoff = parent->cl_cvtoff;
 	sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tca[TCA_RATE-1])
 		gen_new_estimator(&cl->bstats, &cl->rate_est,
-			cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+				  &sch->dev->queue_lock, tca[TCA_RATE-1]);
 	*arg = (unsigned long)cl;
 	return 0;
 }
@@ -1128,9 +1120,7 @@
 
 	tcf_destroy_chain(cl->filter_list);
 	qdisc_destroy(cl->qdisc);
-#ifdef CONFIG_NET_ESTIMATOR
 	gen_kill_estimator(&cl->bstats, &cl->rate_est);
-#endif
 	if (cl != &q->root)
 		kfree(cl);
 }
@@ -1184,9 +1174,6 @@
 		case TC_ACT_SHOT:
 			return NULL;
 		}
-#elif defined(CONFIG_NET_CLS_POLICE)
-		if (result == TC_POLICE_SHOT)
-			return NULL;
 #endif
 		if ((cl = (struct hfsc_class *)res.class) == NULL) {
 			if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
@@ -1384,9 +1371,7 @@
 	xstats.rtwork  = cl->cl_cumul;
 
 	if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(d, &cl->qstats) < 0)
 		return -1;
 
@@ -1448,8 +1433,6 @@
 		return -EINVAL;
 	qopt = RTA_DATA(opt);
 
-	sch->stats_lock = &sch->dev->queue_lock;
-
 	q->defcls = qopt->defcls;
 	for (i = 0; i < HFSC_HSIZE; i++)
 		INIT_LIST_HEAD(&q->clhash[i]);
@@ -1464,7 +1447,6 @@
 					  sch->handle);
 	if (q->root.qdisc == NULL)
 		q->root.qdisc = &noop_qdisc;
-	q->root.stats_lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&q->root.children);
 	q->root.vt_tree = RB_ROOT;
 	q->root.cf_tree = RB_ROOT;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 99bcec8..246a2f9 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -28,32 +28,16 @@
  * $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $
  */
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
 #include <linux/list.h>
 #include <linux/compiler.h>
-#include <net/netlink.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
 #include <linux/rbtree.h>
+#include <net/netlink.h>
+#include <net/pkt_sched.h>
 
 /* HTB algorithm.
     Author: devik@cdi.cz
@@ -69,8 +53,6 @@
 */
 
 #define HTB_HSIZE 16		/* classid hash size */
-#define HTB_EWMAC 2		/* rate average over HTB_EWMAC*HTB_HSIZE sec */
-#define HTB_RATECM 1		/* whether to use rate computer */
 #define HTB_HYSTERESIS 1	/* whether to use mode hysteresis for speedup */
 #define HTB_VER 0x30011		/* major must be matched with number suplied by TC as version */
 
@@ -95,12 +77,6 @@
 	struct tc_htb_xstats xstats;	/* our special stats */
 	int refcnt;		/* usage count of this class */
 
-#ifdef HTB_RATECM
-	/* rate measurement counters */
-	unsigned long rate_bytes, sum_bytes;
-	unsigned long rate_packets, sum_packets;
-#endif
-
 	/* topology */
 	int level;		/* our level (see above) */
 	struct htb_class *parent;	/* parent class */
@@ -153,15 +129,12 @@
 				/* of un.leaf originals should be done. */
 };
 
-/* TODO: maybe compute rate when size is too large .. or drop ? */
 static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
 			   int size)
 {
 	int slot = size >> rate->rate.cell_log;
-	if (slot > 255) {
-		cl->xstats.giants++;
-		slot = 255;
-	}
+	if (slot > 255)
+		return (rate->data[255]*(slot >> 8) + rate->data[slot & 0xFF]);
 	return rate->data[slot];
 }
 
@@ -194,10 +167,6 @@
 	int rate2quantum;	/* quant = rate / rate2quantum */
 	psched_time_t now;	/* cached dequeue time */
 	struct qdisc_watchdog watchdog;
-#ifdef HTB_RATECM
-	struct timer_list rttim;	/* rate computer timer */
-	int recmp_bucket;	/* which hash bucket to recompute next */
-#endif
 
 	/* non shaped skbs; let them go directly thru */
 	struct sk_buff_head direct_queue;
@@ -280,9 +249,6 @@
 		case TC_ACT_SHOT:
 			return NULL;
 		}
-#elif defined(CONFIG_NET_CLS_POLICE)
-		if (result == TC_POLICE_SHOT)
-			return HTB_DIRECT;
 #endif
 		if ((cl = (void *)res.class) == NULL) {
 			if (res.classid == sch->handle)
@@ -634,13 +600,14 @@
 		cl->qstats.drops++;
 		return NET_XMIT_DROP;
 	} else {
-		cl->bstats.packets++;
+		cl->bstats.packets +=
+			skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
 		cl->bstats.bytes += skb->len;
 		htb_activate(q, cl);
 	}
 
 	sch->q.qlen++;
-	sch->bstats.packets++;
+	sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
 	sch->bstats.bytes += skb->len;
 	return NET_XMIT_SUCCESS;
 }
@@ -677,34 +644,6 @@
 	return NET_XMIT_SUCCESS;
 }
 
-#ifdef HTB_RATECM
-#define RT_GEN(D,R) R+=D-(R/HTB_EWMAC);D=0
-static void htb_rate_timer(unsigned long arg)
-{
-	struct Qdisc *sch = (struct Qdisc *)arg;
-	struct htb_sched *q = qdisc_priv(sch);
-	struct hlist_node *p;
-	struct htb_class *cl;
-
-
-	/* lock queue so that we can muck with it */
-	spin_lock_bh(&sch->dev->queue_lock);
-
-	q->rttim.expires = jiffies + HZ;
-	add_timer(&q->rttim);
-
-	/* scan and recompute one bucket at time */
-	if (++q->recmp_bucket >= HTB_HSIZE)
-		q->recmp_bucket = 0;
-
-	hlist_for_each_entry(cl,p, q->hash + q->recmp_bucket, hlist) {
-		RT_GEN(cl->sum_bytes, cl->rate_bytes);
-		RT_GEN(cl->sum_packets, cl->rate_packets);
-	}
-	spin_unlock_bh(&sch->dev->queue_lock);
-}
-#endif
-
 /**
  * htb_charge_class - charges amount "bytes" to leaf and ancestors
  *
@@ -717,8 +656,9 @@
  * In such case we remove class from event queue first.
  */
 static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
-			     int level, int bytes)
+			     int level, struct sk_buff *skb)
 {
+	int bytes = skb->len;
 	long toks, diff;
 	enum htb_cmode old_mode;
 
@@ -750,16 +690,12 @@
 			if (cl->cmode != HTB_CAN_SEND)
 				htb_add_to_wait_tree(q, cl, diff);
 		}
-#ifdef HTB_RATECM
-		/* update rate counters */
-		cl->sum_bytes += bytes;
-		cl->sum_packets++;
-#endif
 
 		/* update byte stats except for leaves which are already updated */
 		if (cl->level) {
 			cl->bstats.bytes += bytes;
-			cl->bstats.packets++;
+			cl->bstats.packets += skb_is_gso(skb)?
+					skb_shinfo(skb)->gso_segs:1;
 		}
 		cl = cl->parent;
 	}
@@ -943,7 +879,7 @@
 		   gives us slightly better performance */
 		if (!cl->un.leaf.q->q.qlen)
 			htb_deactivate(q, cl);
-		htb_charge_class(q, cl, level, skb->len);
+		htb_charge_class(q, cl, level, skb);
 	}
 	return skb;
 }
@@ -976,8 +912,9 @@
 
 		if (q->now >= q->near_ev_cache[level]) {
 			event = htb_do_events(q, level);
-			q->near_ev_cache[level] = event ? event :
-							  PSCHED_TICKS_PER_SEC;
+			if (!event)
+				event = q->now + PSCHED_TICKS_PER_SEC;
+			q->near_ev_cache[level] = event;
 		} else
 			event = q->near_ev_cache[level];
 
@@ -1094,13 +1031,6 @@
 	if (q->direct_qlen < 2)	/* some devices have zero tx_queue_len */
 		q->direct_qlen = 2;
 
-#ifdef HTB_RATECM
-	init_timer(&q->rttim);
-	q->rttim.function = htb_rate_timer;
-	q->rttim.data = (unsigned long)sch;
-	q->rttim.expires = jiffies + HZ;
-	add_timer(&q->rttim);
-#endif
 	if ((q->rate2quantum = gopt->rate2quantum) < 1)
 		q->rate2quantum = 1;
 	q->defcls = gopt->defcls;
@@ -1174,11 +1104,6 @@
 {
 	struct htb_class *cl = (struct htb_class *)arg;
 
-#ifdef HTB_RATECM
-	cl->rate_est.bps = cl->rate_bytes / (HTB_EWMAC * HTB_HSIZE);
-	cl->rate_est.pps = cl->rate_packets / (HTB_EWMAC * HTB_HSIZE);
-#endif
-
 	if (!cl->level && cl->un.leaf.q)
 		cl->qstats.qlen = cl->un.leaf.q->q.qlen;
 	cl->xstats.tokens = cl->tokens;
@@ -1276,6 +1201,7 @@
 		BUG_TRAP(cl->un.leaf.q);
 		qdisc_destroy(cl->un.leaf.q);
 	}
+	gen_kill_estimator(&cl->bstats, &cl->rate_est);
 	qdisc_put_rtab(cl->rate);
 	qdisc_put_rtab(cl->ceil);
 
@@ -1304,9 +1230,6 @@
 	struct htb_sched *q = qdisc_priv(sch);
 
 	qdisc_watchdog_cancel(&q->watchdog);
-#ifdef HTB_RATECM
-	del_timer_sync(&q->rttim);
-#endif
 	/* This line used to be after htb_destroy_class call below
 	   and surprisingly it worked in 2.4. But it must precede it
 	   because filter need its target class alive to be able to call
@@ -1402,6 +1325,20 @@
 	if (!cl) {		/* new class */
 		struct Qdisc *new_q;
 		int prio;
+		struct {
+			struct rtattr		rta;
+			struct gnet_estimator	opt;
+		} est = {
+			.rta = {
+				.rta_len	= RTA_LENGTH(sizeof(est.opt)),
+				.rta_type	= TCA_RATE,
+			},
+			.opt = {
+				/* 4s interval, 16s averaging constant */
+				.interval	= 2,
+				.ewma_log	= 2,
+			},
+		};
 
 		/* check for valid classid */
 		if (!classid || TC_H_MAJ(classid ^ sch->handle)
@@ -1417,6 +1354,9 @@
 		if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
 			goto failure;
 
+		gen_new_estimator(&cl->bstats, &cl->rate_est,
+				  &sch->dev->queue_lock,
+				  tca[TCA_RATE-1] ? : &est.rta);
 		cl->refcnt = 1;
 		INIT_LIST_HEAD(&cl->sibling);
 		INIT_HLIST_NODE(&cl->hlist);
@@ -1468,8 +1408,13 @@
 		hlist_add_head(&cl->hlist, q->hash + htb_hash(classid));
 		list_add_tail(&cl->sibling,
 			      parent ? &parent->children : &q->root);
-	} else
+	} else {
+		if (tca[TCA_RATE-1])
+			gen_replace_estimator(&cl->bstats, &cl->rate_est,
+					      &sch->dev->queue_lock,
+					      tca[TCA_RATE-1]);
 		sch_tree_lock(sch);
+	}
 
 	/* it used to be a nasty bug here, we have to check that node
 	   is really leaf before changing cl->un.leaf ! */
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index f8b9f1c..51f16b0 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -9,21 +9,14 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/list.h>
 #include <linux/skbuff.h>
-#include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <linux/netfilter.h>
-#include <linux/smp.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-#include <linux/kmod.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
 
 
 #undef DEBUG_INGRESS
@@ -171,31 +164,12 @@
 			result = TC_ACT_OK;
 			break;
 	}
-/* backward compat */
-#else
-#ifdef	CONFIG_NET_CLS_POLICE
-	switch (result) {
-		case TC_POLICE_SHOT:
-		result = NF_DROP;
-		sch->qstats.drops++;
-		break;
-		case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
-		case TC_POLICE_OK:
-		case TC_POLICE_UNSPEC:
-		default:
-		sch->bstats.packets++;
-		sch->bstats.bytes += skb->len;
-		result = NF_ACCEPT;
-		break;
-	}
-
 #else
 	D2PRINTK("Overriding result to ACCEPT\n");
 	result = NF_ACCEPT;
 	sch->bstats.packets++;
 	sch->bstats.bytes += skb->len;
 #endif
-#endif
 
 	return result;
 }
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 5d9d8bc..9e5e87e 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -14,11 +14,9 @@
  */
 
 #include <linux/module.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 6d7542c..2d8c084 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -12,37 +12,23 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
 
 struct prio_sched_data
 {
 	int bands;
+	int curband; /* for round-robin */
 	struct tcf_proto *filter_list;
 	u8  prio2band[TC_PRIO_MAX+1];
 	struct Qdisc *queues[TCQ_PRIO_BANDS];
+	int mq;
 };
 
 
@@ -70,14 +56,17 @@
 #endif
 			if (TC_H_MAJ(band))
 				band = 0;
-			return q->queues[q->prio2band[band&TC_PRIO_MAX]];
+			band = q->prio2band[band&TC_PRIO_MAX];
+			goto out;
 		}
 		band = res.classid;
 	}
 	band = TC_H_MIN(band) - 1;
 	if (band >= q->bands)
-		return q->queues[q->prio2band[0]];
-
+		band = q->prio2band[0];
+out:
+	if (q->mq)
+		skb_set_queue_mapping(skb, band);
 	return q->queues[band];
 }
 
@@ -144,17 +133,58 @@
 	struct Qdisc *qdisc;
 
 	for (prio = 0; prio < q->bands; prio++) {
-		qdisc = q->queues[prio];
-		skb = qdisc->dequeue(qdisc);
-		if (skb) {
-			sch->q.qlen--;
-			return skb;
+		/* Check if the target subqueue is available before
+		 * pulling an skb.  This way we avoid excessive requeues
+		 * for slower queues.
+		 */
+		if (!netif_subqueue_stopped(sch->dev, (q->mq ? prio : 0))) {
+			qdisc = q->queues[prio];
+			skb = qdisc->dequeue(qdisc);
+			if (skb) {
+				sch->q.qlen--;
+				return skb;
+			}
 		}
 	}
 	return NULL;
 
 }
 
+static struct sk_buff *rr_dequeue(struct Qdisc* sch)
+{
+	struct sk_buff *skb;
+	struct prio_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *qdisc;
+	int bandcount;
+
+	/* Only take one pass through the queues.  If nothing is available,
+	 * return nothing.
+	 */
+	for (bandcount = 0; bandcount < q->bands; bandcount++) {
+		/* Check if the target subqueue is available before
+		 * pulling an skb.  This way we avoid excessive requeues
+		 * for slower queues.  If the queue is stopped, try the
+		 * next queue.
+		 */
+		if (!netif_subqueue_stopped(sch->dev,
+					    (q->mq ? q->curband : 0))) {
+			qdisc = q->queues[q->curband];
+			skb = qdisc->dequeue(qdisc);
+			if (skb) {
+				sch->q.qlen--;
+				q->curband++;
+				if (q->curband >= q->bands)
+					q->curband = 0;
+				return skb;
+			}
+		}
+		q->curband++;
+		if (q->curband >= q->bands)
+			q->curband = 0;
+	}
+	return NULL;
+}
+
 static unsigned int prio_drop(struct Qdisc* sch)
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
@@ -198,21 +228,41 @@
 static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
-	struct tc_prio_qopt *qopt = RTA_DATA(opt);
+	struct tc_prio_qopt *qopt;
+	struct rtattr *tb[TCA_PRIO_MAX];
 	int i;
 
-	if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+	if (rtattr_parse_nested_compat(tb, TCA_PRIO_MAX, opt, qopt,
+				       sizeof(*qopt)))
 		return -EINVAL;
-	if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2)
+	q->bands = qopt->bands;
+	/* If we're multiqueue, make sure the number of incoming bands
+	 * matches the number of queues on the device we're associating with.
+	 * If the number of bands requested is zero, then set q->bands to
+	 * dev->egress_subqueue_count.
+	 */
+	q->mq = RTA_GET_FLAG(tb[TCA_PRIO_MQ - 1]);
+	if (q->mq) {
+		if (sch->handle != TC_H_ROOT)
+			return -EINVAL;
+		if (netif_is_multiqueue(sch->dev)) {
+			if (q->bands == 0)
+				q->bands = sch->dev->egress_subqueue_count;
+			else if (q->bands != sch->dev->egress_subqueue_count)
+				return -EINVAL;
+		} else
+			return -EOPNOTSUPP;
+	}
+
+	if (q->bands > TCQ_PRIO_BANDS || q->bands < 2)
 		return -EINVAL;
 
 	for (i=0; i<=TC_PRIO_MAX; i++) {
-		if (qopt->priomap[i] >= qopt->bands)
+		if (qopt->priomap[i] >= q->bands)
 			return -EINVAL;
 	}
 
 	sch_tree_lock(sch);
-	q->bands = qopt->bands;
 	memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
 
 	for (i=q->bands; i<TCQ_PRIO_BANDS; i++) {
@@ -268,11 +318,17 @@
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
 	unsigned char *b = skb_tail_pointer(skb);
+	struct rtattr *nest;
 	struct tc_prio_qopt opt;
 
 	opt.bands = q->bands;
 	memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1);
-	RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+	nest = RTA_NEST_COMPAT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+	if (q->mq)
+		RTA_PUT_FLAG(skb, TCA_PRIO_MQ);
+	RTA_NEST_COMPAT_END(skb, nest);
+
 	return skb->len;
 
 rtattr_failure:
@@ -443,17 +499,44 @@
 	.owner		=	THIS_MODULE,
 };
 
+static struct Qdisc_ops rr_qdisc_ops = {
+	.next		=	NULL,
+	.cl_ops		=	&prio_class_ops,
+	.id		=	"rr",
+	.priv_size	=	sizeof(struct prio_sched_data),
+	.enqueue	=	prio_enqueue,
+	.dequeue	=	rr_dequeue,
+	.requeue	=	prio_requeue,
+	.drop		=	prio_drop,
+	.init		=	prio_init,
+	.reset		=	prio_reset,
+	.destroy	=	prio_destroy,
+	.change		=	prio_tune,
+	.dump		=	prio_dump,
+	.owner		=	THIS_MODULE,
+};
+
 static int __init prio_module_init(void)
 {
-	return register_qdisc(&prio_qdisc_ops);
+	int err;
+
+	err = register_qdisc(&prio_qdisc_ops);
+	if (err < 0)
+		return err;
+	err = register_qdisc(&rr_qdisc_ops);
+	if (err < 0)
+		unregister_qdisc(&prio_qdisc_ops);
+	return err;
 }
 
 static void __exit prio_module_exit(void)
 {
 	unregister_qdisc(&prio_qdisc_ops);
+	unregister_qdisc(&rr_qdisc_ops);
 }
 
 module_init(prio_module_init)
 module_exit(prio_module_exit)
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("sch_rr");
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 00db53e..9b95fef 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 96dfdf7..9579573 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -10,31 +10,17 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
 #include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
 #include <linux/init.h>
+#include <linux/ipv6.h>
+#include <linux/skbuff.h>
 #include <net/ip.h>
 #include <net/netlink.h>
-#include <linux/ipv6.h>
-#include <net/route.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
 
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 5386295..8c2639a 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -13,29 +13,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/jiffies.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/pkt_sched.h>
 
 
@@ -142,7 +125,7 @@
 
 	if (skb->len > q->max_size) {
 		sch->qstats.drops++;
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 		if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
 #endif
 			kfree_skb(skb);
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index f05ad9a..0968184 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -9,30 +9,17 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
 #include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
 #include <linux/init.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
 #include <linux/moduleparam.h>
-#include <net/sock.h>
+#include <net/dst.h>
+#include <net/neighbour.h>
 #include <net/pkt_sched.h>
 
 /*
@@ -225,7 +212,6 @@
 	return 0;
 }
 
-/* "teql*" netdevice routines */
 
 static int
 __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev)
@@ -277,6 +263,7 @@
 	int busy;
 	int nores;
 	int len = skb->len;
+	int subq = skb->queue_mapping;
 	struct sk_buff *skb_res = NULL;
 
 	start = master->slaves;
@@ -293,7 +280,9 @@
 
 		if (slave->qdisc_sleeping != q)
 			continue;
-		if (netif_queue_stopped(slave) || ! netif_running(slave)) {
+		if (netif_queue_stopped(slave) ||
+		    netif_subqueue_stopped(slave, subq) ||
+		    !netif_running(slave)) {
 			busy = 1;
 			continue;
 		}
@@ -302,6 +291,7 @@
 		case 0:
 			if (netif_tx_trylock(slave)) {
 				if (!netif_queue_stopped(slave) &&
+				    !netif_subqueue_stopped(slave, subq) &&
 				    slave->hard_start_xmit(skb, slave) == 0) {
 					netif_tx_unlock(slave);
 					master->slaves = NEXT_SLAVE(q);
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig
index 9cba49e..8210f54 100644
--- a/net/sctp/Kconfig
+++ b/net/sctp/Kconfig
@@ -2,11 +2,9 @@
 # SCTP configuration
 #
 
-menu "SCTP Configuration (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL
-
-config IP_SCTP
+menuconfig IP_SCTP
 	tristate "The SCTP Protocol (EXPERIMENTAL)"
+	depends on INET && EXPERIMENTAL
 	depends on IPV6 || IPV6=n
 	select CRYPTO if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5
 	select CRYPTO_HMAC if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5
@@ -36,9 +34,10 @@
 
 	  If in doubt, say N.
 
+if IP_SCTP
+
 config SCTP_DBG_MSG
 	bool "SCTP: Debug messages"
-	depends on IP_SCTP
 	help
 	  If you say Y, this will enable verbose debugging messages. 
 
@@ -47,7 +46,6 @@
 
 config SCTP_DBG_OBJCNT
 	bool "SCTP: Debug object counts"
-	depends on IP_SCTP
 	help
 	  If you say Y, this will enable debugging support for counting the 
 	  type of objects that are currently allocated.  This is useful for 
@@ -59,7 +57,6 @@
 
 choice
 	prompt "SCTP: Cookie HMAC Algorithm"
-	depends on IP_SCTP
 	default SCTP_HMAC_MD5
 	help
 	  HMAC algorithm to be used during association initialization.  It
@@ -86,4 +83,5 @@
 	  advised to use either HMAC-MD5 or HMAC-SHA1.
 
 endchoice
-endmenu
+
+endif # IP_SCTP
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index df94e3c..498edb0 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1231,6 +1231,10 @@
 	/* Get the lowest pmtu of all the transports. */
 	list_for_each(pos, &asoc->peer.transport_addr_list) {
 		t = list_entry(pos, struct sctp_transport, transports);
+		if (t->pmtu_pending && t->dst) {
+			sctp_transport_update_pmtu(t, dst_mtu(t->dst));
+			t->pmtu_pending = 0;
+		}
 		if (!pmtu || (t->pathmtu < pmtu))
 			pmtu = t->pathmtu;
 	}
diff --git a/net/sctp/debug.c b/net/sctp/debug.c
index e8c0f74..80f70aa 100644
--- a/net/sctp/debug.c
+++ b/net/sctp/debug.c
@@ -77,8 +77,6 @@
 /* Lookup "chunk type" debug name. */
 const char *sctp_cname(const sctp_subtype_t cid)
 {
-	if (cid.chunk < 0)
-		return "illegal chunk id";
 	if (cid.chunk <= SCTP_CID_BASE_MAX)
 		return sctp_cid_tbl[cid.chunk];
 
@@ -146,8 +144,6 @@
 /* Lookup primitive debug name. */
 const char *sctp_pname(const sctp_subtype_t id)
 {
-	if (id.primitive < 0)
-		return "illegal primitive";
 	if (id.primitive <= SCTP_EVENT_PRIMITIVE_MAX)
 		return sctp_primitive_tbl[id.primitive];
 	return "unknown_primitive";
@@ -161,8 +157,6 @@
 /* Lookup "other" debug name. */
 const char *sctp_oname(const sctp_subtype_t id)
 {
-	if (id.other < 0)
-		return "illegal 'other' event";
 	if (id.other <= SCTP_EVENT_OTHER_MAX)
 		return sctp_other_tbl[id.other];
 	return "unknown 'other' event";
@@ -184,8 +178,6 @@
 /* Lookup timer debug name. */
 const char *sctp_tname(const sctp_subtype_t id)
 {
-	if (id.timeout < 0)
-		return "illegal 'timer' event";
 	if (id.timeout <= SCTP_EVENT_TIMEOUT_MAX)
 		return sctp_timer_tbl[id.timeout];
 	return "unknown_timer";
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 885109f..d57ff7f 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -367,24 +367,18 @@
 void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
 			   struct sctp_transport *t, __u32 pmtu)
 {
-	if (sock_owned_by_user(sk) || !t || (t->pathmtu == pmtu))
+	if (!t || (t->pathmtu == pmtu))
 		return;
 
+	if (sock_owned_by_user(sk)) {
+		asoc->pmtu_pending = 1;
+		t->pmtu_pending = 1;
+		return;
+	}
+
 	if (t->param_flags & SPP_PMTUD_ENABLE) {
-		if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
-			printk(KERN_WARNING "%s: Reported pmtu %d too low, "
-			       "using default minimum of %d\n",
-			       __FUNCTION__, pmtu,
-			       SCTP_DEFAULT_MINSEGMENT);
-			/* Use default minimum segment size and disable
-			 * pmtu discovery on this transport.
-			 */
-			t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
-			t->param_flags = (t->param_flags & ~SPP_PMTUD) |
-				SPP_PMTUD_DISABLE;
-		} else {
-			t->pathmtu = pmtu;
-		}
+		/* Update transports view of the MTU */
+		sctp_transport_update_pmtu(t, pmtu);
 
 		/* Update association pmtu. */
 		sctp_assoc_sync_pmtu(asoc);
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 84cd536..2c29394 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -844,6 +844,10 @@
 			dev = dev_get_by_index(addr->v6.sin6_scope_id);
 			if (!dev)
 				return 0;
+			if (!ipv6_chk_addr(&addr->v6.sin6_addr, dev, 0)) {
+				dev_put(dev);
+				return 0;
+			}
 			dev_put(dev);
 		}
 		af = opt->pf->af;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 2f12bf2..e4cd841 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -250,7 +250,7 @@
 	return 0;
 }
 
-static struct seq_operations sctp_eps_ops = {
+static const struct seq_operations sctp_eps_ops = {
 	.start = sctp_eps_seq_start,
 	.next  = sctp_eps_seq_next,
 	.stop  = sctp_eps_seq_stop,
@@ -361,7 +361,7 @@
 	return 0;
 }
 
-static struct seq_operations sctp_assoc_ops = {
+static const struct seq_operations sctp_assoc_ops = {
 	.start = sctp_assocs_seq_start,
 	.next  = sctp_assocs_seq_next,
 	.stop  = sctp_assocs_seq_stop,
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 523071c..70a91ec 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -960,7 +960,7 @@
 	if (state > SCTP_STATE_MAX)
 		return &bug;
 
-	if (cid >= 0 && cid <= SCTP_CID_BASE_MAX)
+	if (cid <= SCTP_CID_BASE_MAX)
 		return &chunk_event_table[cid][state];
 
 	if (sctp_prsctp_enable) {
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 4dcdabf..b1917f6 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -333,12 +333,19 @@
 	if (!sp->pf->bind_verify(sp, addr))
 		return -EADDRNOTAVAIL;
 
-	/* We must either be unbound, or bind to the same port.  */
-	if (bp->port && (snum != bp->port)) {
-		SCTP_DEBUG_PRINTK("sctp_do_bind:"
+	/* We must either be unbound, or bind to the same port.
+	 * It's OK to allow 0 ports if we are already bound.
+	 * We'll just inhert an already bound port in this case
+	 */
+	if (bp->port) {
+		if (!snum)
+			snum = bp->port;
+		else if (snum != bp->port) {
+			SCTP_DEBUG_PRINTK("sctp_do_bind:"
 				  " New port %d does not match existing port "
 				  "%d.\n", snum, bp->port);
-		return -EINVAL;
+			return -EINVAL;
+		}
 	}
 
 	if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
@@ -973,6 +980,7 @@
 	union sctp_addr *sa_addr;
 	void *addr_buf;
 	unsigned short port;
+	unsigned int f_flags = 0;
 
 	sp = sctp_sk(sk);
 	ep = sp->ep;
@@ -1099,7 +1107,14 @@
 	af->to_sk_daddr(&to, sk);
 	sk->sk_err = 0;
 
-	timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
+	/* in-kernel sockets don't generally have a file allocated to them
+	 * if all they do is call sock_create_kern().
+	 */
+	if (sk->sk_socket->file)
+		f_flags = sk->sk_socket->file->f_flags;
+
+	timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
+
 	err = sctp_wait_for_connect(asoc, &timeo);
 
 	/* Don't free association on exit. */
@@ -1655,6 +1670,9 @@
 		goto out_free;
 	}
 
+	if (asoc->pmtu_pending)
+		sctp_assoc_pending_pmtu(asoc);
+
 	/* If fragmentation is disabled and the message length exceeds the
 	 * association fragmentation point, return EMSGSIZE.  The I-D
 	 * does not specify what this error is, but this looks like
@@ -3365,12 +3383,13 @@
 	sctp_assoc_t associd;
 	int retval = 0;
 
-	if (len != sizeof(status)) {
+	if (len < sizeof(status)) {
 		retval = -EINVAL;
 		goto out;
 	}
 
-	if (copy_from_user(&status, optval, sizeof(status))) {
+	len = sizeof(status);
+	if (copy_from_user(&status, optval, len)) {
 		retval = -EFAULT;
 		goto out;
 	}
@@ -3442,12 +3461,13 @@
 	struct sctp_transport *transport;
 	int retval = 0;
 
-	if (len != sizeof(pinfo)) {
+	if (len < sizeof(pinfo)) {
 		retval = -EINVAL;
 		goto out;
 	}
 
-	if (copy_from_user(&pinfo, optval, sizeof(pinfo))) {
+	len = sizeof(pinfo);
+	if (copy_from_user(&pinfo, optval, len)) {
 		retval = -EFAULT;
 		goto out;
 	}
@@ -3513,8 +3533,11 @@
 static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
 				  int __user *optlen)
 {
-	if (len != sizeof(struct sctp_event_subscribe))
+	if (len < sizeof(struct sctp_event_subscribe))
 		return -EINVAL;
+	len = sizeof(struct sctp_event_subscribe);
+	if (put_user(len, optlen))
+		return -EFAULT;
 	if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len))
 		return -EFAULT;
 	return 0;
@@ -3536,9 +3559,12 @@
 	/* Applicable to UDP-style socket only */
 	if (sctp_style(sk, TCP))
 		return -EOPNOTSUPP;
-	if (len != sizeof(int))
+	if (len < sizeof(int))
 		return -EINVAL;
-	if (copy_to_user(optval, &sctp_sk(sk)->autoclose, len))
+	len = sizeof(int);
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &sctp_sk(sk)->autoclose, sizeof(int)))
 		return -EFAULT;
 	return 0;
 }
@@ -3550,6 +3576,7 @@
 	struct sock *sk = asoc->base.sk;
 	struct socket *sock;
 	struct inet_sock *inetsk;
+	struct sctp_af *af;
 	int err = 0;
 
 	/* An association cannot be branched off from an already peeled-off
@@ -3571,8 +3598,9 @@
 	/* Make peeled-off sockets more like 1-1 accepted sockets.
 	 * Set the daddr and initialize id to something more random
 	 */
+	af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family);
+	af->to_sk_daddr(&asoc->peer.primary_addr, sk);
 	inetsk = inet_sk(sock->sk);
-	inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
 	inetsk->id = asoc->next_tsn ^ jiffies;
 
 	*sockp = sock;
@@ -3587,8 +3615,9 @@
 	int retval = 0;
 	struct sctp_association *asoc;
 
-	if (len != sizeof(sctp_peeloff_arg_t))
+	if (len < sizeof(sctp_peeloff_arg_t))
 		return -EINVAL;
+	len = sizeof(sctp_peeloff_arg_t);
 	if (copy_from_user(&peeloff, optval, len))
 		return -EFAULT;
 
@@ -3616,6 +3645,8 @@
 
 	/* Return the fd mapped to the new socket.  */
 	peeloff.sd = retval;
+	if (put_user(len, optlen))
+		return -EFAULT;
 	if (copy_to_user(optval, &peeloff, len))
 		retval = -EFAULT;
 
@@ -3724,9 +3755,9 @@
 	struct sctp_association *asoc = NULL;
 	struct sctp_sock        *sp = sctp_sk(sk);
 
-	if (len != sizeof(struct sctp_paddrparams))
+	if (len < sizeof(struct sctp_paddrparams))
 		return -EINVAL;
-
+	len = sizeof(struct sctp_paddrparams);
 	if (copy_from_user(&params, optval, len))
 		return -EFAULT;
 
@@ -3825,9 +3856,11 @@
 	struct sctp_association *asoc = NULL;
 	struct sctp_sock        *sp = sctp_sk(sk);
 
-	if (len != sizeof(struct sctp_assoc_value))
+	if (len < sizeof(struct sctp_assoc_value))
 		return - EINVAL;
 
+	len = sizeof(struct sctp_assoc_value);
+
 	if (copy_from_user(&params, optval, len))
 		return -EFAULT;
 
@@ -3876,8 +3909,11 @@
  */
 static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, int __user *optlen)
 {
-	if (len != sizeof(struct sctp_initmsg))
+	if (len < sizeof(struct sctp_initmsg))
 		return -EINVAL;
+	len = sizeof(struct sctp_initmsg);
+	if (put_user(len, optlen))
+		return -EFAULT;
 	if (copy_to_user(optval, &sctp_sk(sk)->initmsg, len))
 		return -EFAULT;
 	return 0;
@@ -3892,7 +3928,7 @@
 	struct list_head *pos;
 	int cnt = 0;
 
-	if (len != sizeof(sctp_assoc_t))
+	if (len < sizeof(sctp_assoc_t))
 		return -EINVAL;
 
 	if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
@@ -3928,10 +3964,12 @@
 	struct sctp_sock *sp = sctp_sk(sk);
 	int addrlen;
 
-	if (len != sizeof(struct sctp_getaddrs_old))
+	if (len < sizeof(struct sctp_getaddrs_old))
 		return -EINVAL;
 
-	if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old)))
+	len = sizeof(struct sctp_getaddrs_old);
+
+	if (copy_from_user(&getaddrs, optval, len))
 		return -EFAULT;
 
 	if (getaddrs.addr_num <= 0) return -EINVAL;
@@ -3954,7 +3992,9 @@
 		if (cnt >= getaddrs.addr_num) break;
 	}
 	getaddrs.addr_num = cnt;
-	if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old)))
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &getaddrs, len))
 		return -EFAULT;
 
 	return 0;
@@ -3987,8 +4027,7 @@
 		return -EINVAL;
 
 	to = optval + offsetof(struct sctp_getaddrs,addrs);
-	space_left = len - sizeof(struct sctp_getaddrs) -
-			offsetof(struct sctp_getaddrs,addrs);
+	space_left = len - offsetof(struct sctp_getaddrs,addrs);
 
 	list_for_each(pos, &asoc->peer.transport_addr_list) {
 		from = list_entry(pos, struct sctp_transport, transports);
@@ -4025,7 +4064,7 @@
 	rwlock_t *addr_lock;
 	int cnt = 0;
 
-	if (len != sizeof(sctp_assoc_t))
+	if (len < sizeof(sctp_assoc_t))
 		return -EINVAL;
 
 	if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
@@ -4139,7 +4178,7 @@
 		to += addrlen;
 		cnt ++;
 		space_left -= addrlen;
-		bytes_copied += addrlen;
+		*bytes_copied += addrlen;
 	}
 
 	return cnt;
@@ -4167,10 +4206,11 @@
 	void *buf;
 	int bytes_copied = 0;
 
-	if (len != sizeof(struct sctp_getaddrs_old))
+	if (len < sizeof(struct sctp_getaddrs_old))
 		return -EINVAL;
 
-	if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old)))
+	len = sizeof(struct sctp_getaddrs_old);
+	if (copy_from_user(&getaddrs, optval, len))
 		return -EFAULT;
 
 	if (getaddrs.addr_num <= 0) return -EINVAL;
@@ -4242,7 +4282,7 @@
 
 	/* copy the leading structure back to user */
 	getaddrs.addr_num = cnt;
-	if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old)))
+	if (copy_to_user(optval, &getaddrs, len))
 		err = -EFAULT;
 
 error:
@@ -4270,7 +4310,7 @@
 	void *addrs;
 	void *buf;
 
-	if (len <= sizeof(struct sctp_getaddrs))
+	if (len < sizeof(struct sctp_getaddrs))
 		return -EINVAL;
 
 	if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs)))
@@ -4294,8 +4334,8 @@
 	}
 
 	to = optval + offsetof(struct sctp_getaddrs,addrs);
-	space_left = len - sizeof(struct sctp_getaddrs) -
-			 offsetof(struct sctp_getaddrs,addrs);
+	space_left = len - offsetof(struct sctp_getaddrs,addrs);
+
 	addrs = kmalloc(space_left, GFP_KERNEL);
 	if (!addrs)
 		return -ENOMEM;
@@ -4343,11 +4383,12 @@
 		err = -EFAULT;
 		goto error;
 	}
-	if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num))
-		return -EFAULT;
+	if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) {
+		err = -EFAULT;
+		goto error;
+	}
 	if (put_user(bytes_copied, optlen))
-		return -EFAULT;
-
+		err = -EFAULT;
 error:
 	kfree(addrs);
 	return err;
@@ -4366,10 +4407,12 @@
 	struct sctp_association *asoc;
 	struct sctp_sock *sp = sctp_sk(sk);
 
-	if (len != sizeof(struct sctp_prim))
+	if (len < sizeof(struct sctp_prim))
 		return -EINVAL;
 
-	if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))
+	len = sizeof(struct sctp_prim);
+
+	if (copy_from_user(&prim, optval, len))
 		return -EFAULT;
 
 	asoc = sctp_id2assoc(sk, prim.ssp_assoc_id);
@@ -4385,7 +4428,9 @@
 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
 			(union sctp_addr *)&prim.ssp_addr);
 
-	if (copy_to_user(optval, &prim, sizeof(struct sctp_prim)))
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &prim, len))
 		return -EFAULT;
 
 	return 0;
@@ -4402,10 +4447,15 @@
 {
 	struct sctp_setadaptation adaptation;
 
-	if (len != sizeof(struct sctp_setadaptation))
+	if (len < sizeof(struct sctp_setadaptation))
 		return -EINVAL;
 
+	len = sizeof(struct sctp_setadaptation);
+
 	adaptation.ssb_adaptation_ind = sctp_sk(sk)->adaptation_ind;
+
+	if (put_user(len, optlen))
+		return -EFAULT;
 	if (copy_to_user(optval, &adaptation, len))
 		return -EFAULT;
 
@@ -4439,9 +4489,12 @@
 	struct sctp_association *asoc;
 	struct sctp_sock *sp = sctp_sk(sk);
 
-	if (len != sizeof(struct sctp_sndrcvinfo))
+	if (len < sizeof(struct sctp_sndrcvinfo))
 		return -EINVAL;
-	if (copy_from_user(&info, optval, sizeof(struct sctp_sndrcvinfo)))
+
+	len = sizeof(struct sctp_sndrcvinfo);
+
+	if (copy_from_user(&info, optval, len))
 		return -EFAULT;
 
 	asoc = sctp_id2assoc(sk, info.sinfo_assoc_id);
@@ -4462,7 +4515,9 @@
 		info.sinfo_timetolive = sp->default_timetolive;
 	}
 
-	if (copy_to_user(optval, &info, sizeof(struct sctp_sndrcvinfo)))
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &info, len))
 		return -EFAULT;
 
 	return 0;
@@ -4513,10 +4568,12 @@
 	struct sctp_rtoinfo rtoinfo;
 	struct sctp_association *asoc;
 
-	if (len != sizeof (struct sctp_rtoinfo))
+	if (len < sizeof (struct sctp_rtoinfo))
 		return -EINVAL;
 
-	if (copy_from_user(&rtoinfo, optval, sizeof (struct sctp_rtoinfo)))
+	len = sizeof(struct sctp_rtoinfo);
+
+	if (copy_from_user(&rtoinfo, optval, len))
 		return -EFAULT;
 
 	asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
@@ -4568,11 +4625,12 @@
 	struct list_head *pos;
 	int cnt = 0;
 
-	if (len != sizeof (struct sctp_assocparams))
+	if (len < sizeof (struct sctp_assocparams))
 		return -EINVAL;
 
-	if (copy_from_user(&assocparams, optval,
-			sizeof (struct sctp_assocparams)))
+	len = sizeof(struct sctp_assocparams);
+
+	if (copy_from_user(&assocparams, optval, len))
 		return -EFAULT;
 
 	asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
@@ -4658,9 +4716,11 @@
 	struct sctp_sock *sp;
 	struct sctp_association *asoc;
 
-	if (len != sizeof(struct sctp_assoc_value))
+	if (len < sizeof(struct sctp_assoc_value))
 		return -EINVAL;
 
+	len = sizeof(struct sctp_assoc_value);
+
 	if (copy_from_user(&params, optval, len))
 		return -EFAULT;
 
@@ -6071,8 +6131,11 @@
 	 * queued to the backlog.  This prevents a potential race between
 	 * backlog processing on the old socket and new-packet processing
 	 * on the new socket.
+	 *
+	 * The caller has just allocated newsk so we can guarantee that other
+	 * paths won't try to lock it and then oldsk.
 	 */
-	sctp_lock_sock(newsk);
+	lock_sock_nested(newsk, SINGLE_DEPTH_NESTING);
 	sctp_assoc_migrate(assoc, newsk);
 
 	/* If the association on the newsk is already closed before accept()
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 961df27..5f467c9 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -241,6 +241,45 @@
 		transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
 }
 
+/* this is a complete rip-off from __sk_dst_check
+ * the cookie is always 0 since this is how it's used in the
+ * pmtu code
+ */
+static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
+{
+	struct dst_entry *dst = t->dst;
+
+	if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) {
+		dst_release(t->dst);
+		t->dst = NULL;
+		return NULL;
+	}
+
+	return dst;
+}
+
+void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
+{
+	struct dst_entry *dst;
+
+	if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
+		printk(KERN_WARNING "%s: Reported pmtu %d too low, "
+		       "using default minimum of %d\n",
+		       __FUNCTION__, pmtu,
+		       SCTP_DEFAULT_MINSEGMENT);
+		/* Use default minimum segment size and disable
+		 * pmtu discovery on this transport.
+		 */
+		t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
+	} else {
+		t->pathmtu = pmtu;
+	}
+
+	dst = sctp_transport_dst_check(t);
+	if (dst)
+		dst->ops->update_pmtu(dst, pmtu);
+}
+
 /* Caches the dst entry and source address for a transport's destination
  * address.
  */
diff --git a/net/socket.c b/net/socket.c
index f453019..b711142 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1939,9 +1939,7 @@
 	total_len = err;
 
 	cmsg_ptr = (unsigned long)msg_sys.msg_control;
-	msg_sys.msg_flags = 0;
-	if (MSG_CMSG_COMPAT & flags)
-		msg_sys.msg_flags = MSG_CMSG_COMPAT;
+	msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
 
 	if (sock->file->f_flags & O_NONBLOCK)
 		flags |= MSG_DONTWAIT;
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 9527f2b..29a8ecc 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -13,17 +13,22 @@
 #include <linux/errno.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/spinlock.h>
+#include <linux/smp_lock.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY	RPCDBG_AUTH
 #endif
 
-static struct rpc_authops *	auth_flavors[RPC_AUTH_MAXFLAVOR] = {
+static DEFINE_SPINLOCK(rpc_authflavor_lock);
+static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
 	&authnull_ops,		/* AUTH_NULL */
 	&authunix_ops,		/* AUTH_UNIX */
 	NULL,			/* others can be loadable modules */
 };
 
+static LIST_HEAD(cred_unused);
+static unsigned long number_cred_unused;
+
 static u32
 pseudoflavor_to_flavor(u32 flavor) {
 	if (flavor >= RPC_AUTH_MAXFLAVOR)
@@ -32,55 +37,67 @@
 }
 
 int
-rpcauth_register(struct rpc_authops *ops)
+rpcauth_register(const struct rpc_authops *ops)
 {
 	rpc_authflavor_t flavor;
+	int ret = -EPERM;
 
 	if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
 		return -EINVAL;
-	if (auth_flavors[flavor] != NULL)
-		return -EPERM;		/* what else? */
-	auth_flavors[flavor] = ops;
-	return 0;
+	spin_lock(&rpc_authflavor_lock);
+	if (auth_flavors[flavor] == NULL) {
+		auth_flavors[flavor] = ops;
+		ret = 0;
+	}
+	spin_unlock(&rpc_authflavor_lock);
+	return ret;
 }
 
 int
-rpcauth_unregister(struct rpc_authops *ops)
+rpcauth_unregister(const struct rpc_authops *ops)
 {
 	rpc_authflavor_t flavor;
+	int ret = -EPERM;
 
 	if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
 		return -EINVAL;
-	if (auth_flavors[flavor] != ops)
-		return -EPERM;		/* what else? */
-	auth_flavors[flavor] = NULL;
-	return 0;
+	spin_lock(&rpc_authflavor_lock);
+	if (auth_flavors[flavor] == ops) {
+		auth_flavors[flavor] = NULL;
+		ret = 0;
+	}
+	spin_unlock(&rpc_authflavor_lock);
+	return ret;
 }
 
 struct rpc_auth *
 rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
 {
 	struct rpc_auth		*auth;
-	struct rpc_authops	*ops;
+	const struct rpc_authops *ops;
 	u32			flavor = pseudoflavor_to_flavor(pseudoflavor);
 
 	auth = ERR_PTR(-EINVAL);
 	if (flavor >= RPC_AUTH_MAXFLAVOR)
 		goto out;
 
-	/* FIXME - auth_flavors[] really needs an rw lock,
-	 * and module refcounting. */
 #ifdef CONFIG_KMOD
 	if ((ops = auth_flavors[flavor]) == NULL)
 		request_module("rpc-auth-%u", flavor);
 #endif
-	if ((ops = auth_flavors[flavor]) == NULL)
+	spin_lock(&rpc_authflavor_lock);
+	ops = auth_flavors[flavor];
+	if (ops == NULL || !try_module_get(ops->owner)) {
+		spin_unlock(&rpc_authflavor_lock);
 		goto out;
+	}
+	spin_unlock(&rpc_authflavor_lock);
 	auth = ops->create(clnt, pseudoflavor);
+	module_put(ops->owner);
 	if (IS_ERR(auth))
 		return auth;
 	if (clnt->cl_auth)
-		rpcauth_destroy(clnt->cl_auth);
+		rpcauth_release(clnt->cl_auth);
 	clnt->cl_auth = auth;
 
 out:
@@ -88,7 +105,7 @@
 }
 
 void
-rpcauth_destroy(struct rpc_auth *auth)
+rpcauth_release(struct rpc_auth *auth)
 {
 	if (!atomic_dec_and_test(&auth->au_count))
 		return;
@@ -97,11 +114,31 @@
 
 static DEFINE_SPINLOCK(rpc_credcache_lock);
 
+static void
+rpcauth_unhash_cred_locked(struct rpc_cred *cred)
+{
+	hlist_del_rcu(&cred->cr_hash);
+	smp_mb__before_clear_bit();
+	clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
+}
+
+static void
+rpcauth_unhash_cred(struct rpc_cred *cred)
+{
+	spinlock_t *cache_lock;
+
+	cache_lock = &cred->cr_auth->au_credcache->lock;
+	spin_lock(cache_lock);
+	if (atomic_read(&cred->cr_count) == 0)
+		rpcauth_unhash_cred_locked(cred);
+	spin_unlock(cache_lock);
+}
+
 /*
  * Initialize RPC credential cache
  */
 int
-rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
+rpcauth_init_credcache(struct rpc_auth *auth)
 {
 	struct rpc_cred_cache *new;
 	int i;
@@ -111,8 +148,7 @@
 		return -ENOMEM;
 	for (i = 0; i < RPC_CREDCACHE_NR; i++)
 		INIT_HLIST_HEAD(&new->hashtable[i]);
-	new->expire = expire;
-	new->nextgc = jiffies + (expire >> 1);
+	spin_lock_init(&new->lock);
 	auth->au_credcache = new;
 	return 0;
 }
@@ -121,13 +157,13 @@
  * Destroy a list of credentials
  */
 static inline
-void rpcauth_destroy_credlist(struct hlist_head *head)
+void rpcauth_destroy_credlist(struct list_head *head)
 {
 	struct rpc_cred *cred;
 
-	while (!hlist_empty(head)) {
-		cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
-		hlist_del_init(&cred->cr_hash);
+	while (!list_empty(head)) {
+		cred = list_entry(head->next, struct rpc_cred, cr_lru);
+		list_del_init(&cred->cr_lru);
 		put_rpccred(cred);
 	}
 }
@@ -137,58 +173,95 @@
  * that are not referenced.
  */
 void
-rpcauth_free_credcache(struct rpc_auth *auth)
+rpcauth_clear_credcache(struct rpc_cred_cache *cache)
 {
-	struct rpc_cred_cache *cache = auth->au_credcache;
-	HLIST_HEAD(free);
-	struct hlist_node *pos, *next;
+	LIST_HEAD(free);
+	struct hlist_head *head;
 	struct rpc_cred	*cred;
 	int		i;
 
 	spin_lock(&rpc_credcache_lock);
+	spin_lock(&cache->lock);
 	for (i = 0; i < RPC_CREDCACHE_NR; i++) {
-		hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
-			cred = hlist_entry(pos, struct rpc_cred, cr_hash);
-			__hlist_del(&cred->cr_hash);
-			hlist_add_head(&cred->cr_hash, &free);
+		head = &cache->hashtable[i];
+		while (!hlist_empty(head)) {
+			cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
+			get_rpccred(cred);
+			if (!list_empty(&cred->cr_lru)) {
+				list_del(&cred->cr_lru);
+				number_cred_unused--;
+			}
+			list_add_tail(&cred->cr_lru, &free);
+			rpcauth_unhash_cred_locked(cred);
 		}
 	}
+	spin_unlock(&cache->lock);
 	spin_unlock(&rpc_credcache_lock);
 	rpcauth_destroy_credlist(&free);
 }
 
-static void
-rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
+/*
+ * Destroy the RPC credential cache
+ */
+void
+rpcauth_destroy_credcache(struct rpc_auth *auth)
 {
-	if (atomic_read(&cred->cr_count) != 1)
-	       return;
-	if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
-		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-	if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
-		__hlist_del(&cred->cr_hash);
-		hlist_add_head(&cred->cr_hash, free);
+	struct rpc_cred_cache *cache = auth->au_credcache;
+
+	if (cache) {
+		auth->au_credcache = NULL;
+		rpcauth_clear_credcache(cache);
+		kfree(cache);
 	}
 }
 
 /*
  * Remove stale credentials. Avoid sleeping inside the loop.
  */
-static void
-rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free)
+static int
+rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 {
-	struct rpc_cred_cache *cache = auth->au_credcache;
-	struct hlist_node *pos, *next;
-	struct rpc_cred	*cred;
-	int		i;
+	spinlock_t *cache_lock;
+	struct rpc_cred *cred;
 
-	dprintk("RPC:       gc'ing RPC credentials for auth %p\n", auth);
-	for (i = 0; i < RPC_CREDCACHE_NR; i++) {
-		hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
-			cred = hlist_entry(pos, struct rpc_cred, cr_hash);
-			rpcauth_prune_expired(auth, cred, free);
+	while (!list_empty(&cred_unused)) {
+		cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
+		list_del_init(&cred->cr_lru);
+		number_cred_unused--;
+		if (atomic_read(&cred->cr_count) != 0)
+			continue;
+		cache_lock = &cred->cr_auth->au_credcache->lock;
+		spin_lock(cache_lock);
+		if (atomic_read(&cred->cr_count) == 0) {
+			get_rpccred(cred);
+			list_add_tail(&cred->cr_lru, free);
+			rpcauth_unhash_cred_locked(cred);
+			nr_to_scan--;
 		}
+		spin_unlock(cache_lock);
+		if (nr_to_scan == 0)
+			break;
 	}
-	cache->nextgc = jiffies + cache->expire;
+	return nr_to_scan;
+}
+
+/*
+ * Run memory cache shrinker.
+ */
+static int
+rpcauth_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
+{
+	LIST_HEAD(free);
+	int res;
+
+	if (list_empty(&cred_unused))
+		return 0;
+	spin_lock(&rpc_credcache_lock);
+	nr_to_scan = rpcauth_prune_expired(&free, nr_to_scan);
+	res = (number_cred_unused / 100) * sysctl_vfs_cache_pressure;
+	spin_unlock(&rpc_credcache_lock);
+	rpcauth_destroy_credlist(&free);
+	return res;
 }
 
 /*
@@ -198,53 +271,56 @@
 rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
 		int flags)
 {
+	LIST_HEAD(free);
 	struct rpc_cred_cache *cache = auth->au_credcache;
-	HLIST_HEAD(free);
-	struct hlist_node *pos, *next;
-	struct rpc_cred	*new = NULL,
-			*cred = NULL;
+	struct hlist_node *pos;
+	struct rpc_cred	*cred = NULL,
+			*entry, *new;
 	int		nr = 0;
 
 	if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
 		nr = acred->uid & RPC_CREDCACHE_MASK;
-retry:
-	spin_lock(&rpc_credcache_lock);
-	if (time_before(cache->nextgc, jiffies))
-		rpcauth_gc_credcache(auth, &free);
-	hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
-		struct rpc_cred *entry;
-		entry = hlist_entry(pos, struct rpc_cred, cr_hash);
-		if (entry->cr_ops->crmatch(acred, entry, flags)) {
-			hlist_del(&entry->cr_hash);
-			cred = entry;
-			break;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
+		if (!entry->cr_ops->crmatch(acred, entry, flags))
+			continue;
+		spin_lock(&cache->lock);
+		if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
+			spin_unlock(&cache->lock);
+			continue;
 		}
-		rpcauth_prune_expired(auth, entry, &free);
+		cred = get_rpccred(entry);
+		spin_unlock(&cache->lock);
+		break;
 	}
-	if (new) {
-		if (cred)
-			hlist_add_head(&new->cr_hash, &free);
-		else
-			cred = new;
-	}
-	if (cred) {
-		hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
-		get_rpccred(cred);
-	}
-	spin_unlock(&rpc_credcache_lock);
+	rcu_read_unlock();
 
-	rpcauth_destroy_credlist(&free);
+	if (cred != NULL)
+		goto found;
 
-	if (!cred) {
-		new = auth->au_ops->crcreate(auth, acred, flags);
-		if (!IS_ERR(new)) {
-#ifdef RPC_DEBUG
-			new->cr_magic = RPCAUTH_CRED_MAGIC;
-#endif
-			goto retry;
-		} else
-			cred = new;
-	} else if ((cred->cr_flags & RPCAUTH_CRED_NEW)
+	new = auth->au_ops->crcreate(auth, acred, flags);
+	if (IS_ERR(new)) {
+		cred = new;
+		goto out;
+	}
+
+	spin_lock(&cache->lock);
+	hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
+		if (!entry->cr_ops->crmatch(acred, entry, flags))
+			continue;
+		cred = get_rpccred(entry);
+		break;
+	}
+	if (cred == NULL) {
+		cred = new;
+		set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
+		hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
+	} else
+		list_add_tail(&new->cr_lru, &free);
+	spin_unlock(&cache->lock);
+found:
+	if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
 			&& cred->cr_ops->cr_init != NULL
 			&& !(flags & RPCAUTH_LOOKUP_NEW)) {
 		int res = cred->cr_ops->cr_init(auth, cred);
@@ -253,8 +329,9 @@
 			cred = ERR_PTR(res);
 		}
 	}
-
-	return (struct rpc_cred *) cred;
+	rpcauth_destroy_credlist(&free);
+out:
+	return cred;
 }
 
 struct rpc_cred *
@@ -275,10 +352,27 @@
 	return ret;
 }
 
+void
+rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+		  struct rpc_auth *auth, const struct rpc_credops *ops)
+{
+	INIT_HLIST_NODE(&cred->cr_hash);
+	INIT_LIST_HEAD(&cred->cr_lru);
+	atomic_set(&cred->cr_count, 1);
+	cred->cr_auth = auth;
+	cred->cr_ops = ops;
+	cred->cr_expire = jiffies;
+#ifdef RPC_DEBUG
+	cred->cr_magic = RPCAUTH_CRED_MAGIC;
+#endif
+	cred->cr_uid = acred->uid;
+}
+EXPORT_SYMBOL(rpcauth_init_cred);
+
 struct rpc_cred *
 rpcauth_bindcred(struct rpc_task *task)
 {
-	struct rpc_auth *auth = task->tk_auth;
+	struct rpc_auth *auth = task->tk_client->cl_auth;
 	struct auth_cred acred = {
 		.uid = current->fsuid,
 		.gid = current->fsgid,
@@ -288,7 +382,7 @@
 	int flags = 0;
 
 	dprintk("RPC: %5u looking up %s cred\n",
-		task->tk_pid, task->tk_auth->au_ops->au_name);
+		task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
 	get_group_info(acred.group_info);
 	if (task->tk_flags & RPC_TASK_ROOTCREDS)
 		flags |= RPCAUTH_LOOKUP_ROOTCREDS;
@@ -304,19 +398,42 @@
 void
 rpcauth_holdcred(struct rpc_task *task)
 {
-	dprintk("RPC: %5u holding %s cred %p\n",
-		task->tk_pid, task->tk_auth->au_ops->au_name,
-		task->tk_msg.rpc_cred);
-	if (task->tk_msg.rpc_cred)
-		get_rpccred(task->tk_msg.rpc_cred);
+	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+	if (cred != NULL) {
+		get_rpccred(cred);
+		dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
+				cred->cr_auth->au_ops->au_name, cred);
+	}
 }
 
 void
 put_rpccred(struct rpc_cred *cred)
 {
-	cred->cr_expire = jiffies;
+	/* Fast path for unhashed credentials */
+	if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
+		goto need_lock;
+
 	if (!atomic_dec_and_test(&cred->cr_count))
 		return;
+	goto out_destroy;
+need_lock:
+	if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
+		return;
+	if (!list_empty(&cred->cr_lru)) {
+		number_cred_unused--;
+		list_del_init(&cred->cr_lru);
+	}
+	if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
+		rpcauth_unhash_cred(cred);
+	else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
+		cred->cr_expire = jiffies;
+		list_add_tail(&cred->cr_lru, &cred_unused);
+		number_cred_unused++;
+		spin_unlock(&rpc_credcache_lock);
+		return;
+	}
+	spin_unlock(&rpc_credcache_lock);
+out_destroy:
 	cred->cr_ops->crdestroy(cred);
 }
 
@@ -326,7 +443,7 @@
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 
 	dprintk("RPC: %5u releasing %s cred %p\n",
-		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+		task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
 	put_rpccred(cred);
 	task->tk_msg.rpc_cred = NULL;
@@ -338,7 +455,7 @@
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 
 	dprintk("RPC: %5u marshaling %s cred %p\n",
-		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+		task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
 	return cred->cr_ops->crmarshal(task, p);
 }
@@ -349,7 +466,7 @@
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 
 	dprintk("RPC: %5u validating %s cred %p\n",
-		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+		task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
 	return cred->cr_ops->crvalidate(task, p);
 }
@@ -359,13 +476,17 @@
 		__be32 *data, void *obj)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+	int ret;
 
 	dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
 			task->tk_pid, cred->cr_ops->cr_name, cred);
 	if (cred->cr_ops->crwrap_req)
 		return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
 	/* By default, we encode the arguments normally. */
-	return encode(rqstp, data, obj);
+	lock_kernel();
+	ret = encode(rqstp, data, obj);
+	unlock_kernel();
+	return ret;
 }
 
 int
@@ -373,6 +494,7 @@
 		__be32 *data, void *obj)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+	int ret;
 
 	dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
 			task->tk_pid, cred->cr_ops->cr_name, cred);
@@ -380,7 +502,10 @@
 		return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
 						   data, obj);
 	/* By default, we decode the arguments normally. */
-	return decode(rqstp, data, obj);
+	lock_kernel();
+	ret = decode(rqstp, data, obj);
+	unlock_kernel();
+	return ret;
 }
 
 int
@@ -390,7 +515,7 @@
 	int err;
 
 	dprintk("RPC: %5u refreshing %s cred %p\n",
-		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+		task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
 	err = cred->cr_ops->crrefresh(task);
 	if (err < 0)
@@ -401,17 +526,35 @@
 void
 rpcauth_invalcred(struct rpc_task *task)
 {
+	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+
 	dprintk("RPC: %5u invalidating %s cred %p\n",
-		task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
-	spin_lock(&rpc_credcache_lock);
-	if (task->tk_msg.rpc_cred)
-		task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-	spin_unlock(&rpc_credcache_lock);
+		task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+	if (cred)
+		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 }
 
 int
 rpcauth_uptodatecred(struct rpc_task *task)
 {
-	return !(task->tk_msg.rpc_cred) ||
-		(task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
+	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+
+	return cred == NULL ||
+		test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
+}
+
+static struct shrinker rpc_cred_shrinker = {
+	.shrink = rpcauth_cache_shrinker,
+	.seeks = DEFAULT_SEEKS,
+};
+
+void __init rpcauth_init_module(void)
+{
+	rpc_init_authunix();
+	register_shrinker(&rpc_cred_shrinker);
+}
+
+void __exit rpcauth_remove_module(void)
+{
+	unregister_shrinker(&rpc_cred_shrinker);
 }
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 4e4ccc5..abfda33 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -43,6 +43,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
@@ -54,9 +55,10 @@
 #include <linux/sunrpc/gss_api.h>
 #include <asm/uaccess.h>
 
-static struct rpc_authops authgss_ops;
+static const struct rpc_authops authgss_ops;
 
-static struct rpc_credops gss_credops;
+static const struct rpc_credops gss_credops;
+static const struct rpc_credops gss_nullops;
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY	RPCDBG_AUTH
@@ -64,7 +66,6 @@
 
 #define NFS_NGROUPS	16
 
-#define GSS_CRED_EXPIRE		(60 * HZ)	/* XXX: reasonable? */
 #define GSS_CRED_SLACK		1024		/* XXX: unused */
 /* length of a krb5 verifier (48), plus data added before arguments when
  * using integrity (two 4-byte integers): */
@@ -79,19 +80,16 @@
 /* dump the buffer in `emacs-hexl' style */
 #define isprint(c)      ((c > 0x1f) && (c < 0x7f))
 
-static DEFINE_RWLOCK(gss_ctx_lock);
-
 struct gss_auth {
+	struct kref kref;
 	struct rpc_auth rpc_auth;
 	struct gss_api_mech *mech;
 	enum rpc_gss_svc service;
-	struct list_head upcalls;
 	struct rpc_clnt *client;
 	struct dentry *dentry;
-	spinlock_t lock;
 };
 
-static void gss_destroy_ctx(struct gss_cl_ctx *);
+static void gss_free_ctx(struct gss_cl_ctx *);
 static struct rpc_pipe_ops gss_upcall_ops;
 
 static inline struct gss_cl_ctx *
@@ -105,20 +103,24 @@
 gss_put_ctx(struct gss_cl_ctx *ctx)
 {
 	if (atomic_dec_and_test(&ctx->count))
-		gss_destroy_ctx(ctx);
+		gss_free_ctx(ctx);
 }
 
+/* gss_cred_set_ctx:
+ * called by gss_upcall_callback and gss_create_upcall in order
+ * to set the gss context. The actual exchange of an old context
+ * and a new one is protected by the inode->i_lock.
+ */
 static void
 gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
 {
 	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
 	struct gss_cl_ctx *old;
-	write_lock(&gss_ctx_lock);
+
 	old = gss_cred->gc_ctx;
-	gss_cred->gc_ctx = ctx;
-	cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
-	cred->cr_flags &= ~RPCAUTH_CRED_NEW;
-	write_unlock(&gss_ctx_lock);
+	rcu_assign_pointer(gss_cred->gc_ctx, ctx);
+	set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+	clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
 	if (old)
 		gss_put_ctx(old);
 }
@@ -129,10 +131,10 @@
 	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
 	int res = 0;
 
-	read_lock(&gss_ctx_lock);
-	if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx)
+	rcu_read_lock();
+	if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
 		res = 1;
-	read_unlock(&gss_ctx_lock);
+	rcu_read_unlock();
 	return res;
 }
 
@@ -171,10 +173,10 @@
 	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
 	struct gss_cl_ctx *ctx = NULL;
 
-	read_lock(&gss_ctx_lock);
+	rcu_read_lock();
 	if (gss_cred->gc_ctx)
 		ctx = gss_get_ctx(gss_cred->gc_ctx);
-	read_unlock(&gss_ctx_lock);
+	rcu_read_unlock();
 	return ctx;
 }
 
@@ -269,10 +271,10 @@
 }
 
 static struct gss_upcall_msg *
-__gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
+__gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
 {
 	struct gss_upcall_msg *pos;
-	list_for_each_entry(pos, &gss_auth->upcalls, list) {
+	list_for_each_entry(pos, &rpci->in_downcall, list) {
 		if (pos->uid != uid)
 			continue;
 		atomic_inc(&pos->count);
@@ -290,24 +292,24 @@
 static inline struct gss_upcall_msg *
 gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
 {
+	struct inode *inode = gss_auth->dentry->d_inode;
+	struct rpc_inode *rpci = RPC_I(inode);
 	struct gss_upcall_msg *old;
 
-	spin_lock(&gss_auth->lock);
-	old = __gss_find_upcall(gss_auth, gss_msg->uid);
+	spin_lock(&inode->i_lock);
+	old = __gss_find_upcall(rpci, gss_msg->uid);
 	if (old == NULL) {
 		atomic_inc(&gss_msg->count);
-		list_add(&gss_msg->list, &gss_auth->upcalls);
+		list_add(&gss_msg->list, &rpci->in_downcall);
 	} else
 		gss_msg = old;
-	spin_unlock(&gss_auth->lock);
+	spin_unlock(&inode->i_lock);
 	return gss_msg;
 }
 
 static void
 __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
 {
-	if (list_empty(&gss_msg->list))
-		return;
 	list_del_init(&gss_msg->list);
 	rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
 	wake_up_all(&gss_msg->waitqueue);
@@ -318,10 +320,14 @@
 gss_unhash_msg(struct gss_upcall_msg *gss_msg)
 {
 	struct gss_auth *gss_auth = gss_msg->auth;
+	struct inode *inode = gss_auth->dentry->d_inode;
 
-	spin_lock(&gss_auth->lock);
-	__gss_unhash_msg(gss_msg);
-	spin_unlock(&gss_auth->lock);
+	if (list_empty(&gss_msg->list))
+		return;
+	spin_lock(&inode->i_lock);
+	if (!list_empty(&gss_msg->list))
+		__gss_unhash_msg(gss_msg);
+	spin_unlock(&inode->i_lock);
 }
 
 static void
@@ -330,16 +336,16 @@
 	struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
 			struct gss_cred, gc_base);
 	struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
+	struct inode *inode = gss_msg->auth->dentry->d_inode;
 
-	BUG_ON(gss_msg == NULL);
+	spin_lock(&inode->i_lock);
 	if (gss_msg->ctx)
 		gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
 	else
 		task->tk_status = gss_msg->msg.errno;
-	spin_lock(&gss_msg->auth->lock);
 	gss_cred->gc_upcall = NULL;
 	rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
-	spin_unlock(&gss_msg->auth->lock);
+	spin_unlock(&inode->i_lock);
 	gss_release_msg(gss_msg);
 }
 
@@ -386,11 +392,12 @@
 gss_refresh_upcall(struct rpc_task *task)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
-	struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
+	struct gss_auth *gss_auth = container_of(cred->cr_auth,
 			struct gss_auth, rpc_auth);
 	struct gss_cred *gss_cred = container_of(cred,
 			struct gss_cred, gc_base);
 	struct gss_upcall_msg *gss_msg;
+	struct inode *inode = gss_auth->dentry->d_inode;
 	int err = 0;
 
 	dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
@@ -400,7 +407,7 @@
 		err = PTR_ERR(gss_msg);
 		goto out;
 	}
-	spin_lock(&gss_auth->lock);
+	spin_lock(&inode->i_lock);
 	if (gss_cred->gc_upcall != NULL)
 		rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
 	else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
@@ -411,7 +418,7 @@
 		rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
 	} else
 		err = gss_msg->msg.errno;
-	spin_unlock(&gss_auth->lock);
+	spin_unlock(&inode->i_lock);
 	gss_release_msg(gss_msg);
 out:
 	dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n",
@@ -422,6 +429,7 @@
 static inline int
 gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
 {
+	struct inode *inode = gss_auth->dentry->d_inode;
 	struct rpc_cred *cred = &gss_cred->gc_base;
 	struct gss_upcall_msg *gss_msg;
 	DEFINE_WAIT(wait);
@@ -435,12 +443,11 @@
 	}
 	for (;;) {
 		prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
-		spin_lock(&gss_auth->lock);
+		spin_lock(&inode->i_lock);
 		if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
-			spin_unlock(&gss_auth->lock);
 			break;
 		}
-		spin_unlock(&gss_auth->lock);
+		spin_unlock(&inode->i_lock);
 		if (signalled()) {
 			err = -ERESTARTSYS;
 			goto out_intr;
@@ -451,6 +458,7 @@
 		gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
 	else
 		err = gss_msg->msg.errno;
+	spin_unlock(&inode->i_lock);
 out_intr:
 	finish_wait(&gss_msg->waitqueue, &wait);
 	gss_release_msg(gss_msg);
@@ -489,12 +497,11 @@
 	const void *p, *end;
 	void *buf;
 	struct rpc_clnt *clnt;
-	struct gss_auth *gss_auth;
-	struct rpc_cred *cred;
 	struct gss_upcall_msg *gss_msg;
+	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct gss_cl_ctx *ctx;
 	uid_t uid;
-	int err = -EFBIG;
+	ssize_t err = -EFBIG;
 
 	if (mlen > MSG_BUF_MAXSIZE)
 		goto out;
@@ -503,7 +510,7 @@
 	if (!buf)
 		goto out;
 
-	clnt = RPC_I(filp->f_path.dentry->d_inode)->private;
+	clnt = RPC_I(inode)->private;
 	err = -EFAULT;
 	if (copy_from_user(buf, src, mlen))
 		goto err;
@@ -519,43 +526,38 @@
 	ctx = gss_alloc_context();
 	if (ctx == NULL)
 		goto err;
-	err = 0;
-	gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
-	p = gss_fill_context(p, end, ctx, gss_auth->mech);
+
+	err = -ENOENT;
+	/* Find a matching upcall */
+	spin_lock(&inode->i_lock);
+	gss_msg = __gss_find_upcall(RPC_I(inode), uid);
+	if (gss_msg == NULL) {
+		spin_unlock(&inode->i_lock);
+		goto err_put_ctx;
+	}
+	list_del_init(&gss_msg->list);
+	spin_unlock(&inode->i_lock);
+
+	p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
 	if (IS_ERR(p)) {
 		err = PTR_ERR(p);
-		if (err != -EACCES)
-			goto err_put_ctx;
+		gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
+		goto err_release_msg;
 	}
-	spin_lock(&gss_auth->lock);
-	gss_msg = __gss_find_upcall(gss_auth, uid);
-	if (gss_msg) {
-		if (err == 0 && gss_msg->ctx == NULL)
-			gss_msg->ctx = gss_get_ctx(ctx);
-		gss_msg->msg.errno = err;
-		__gss_unhash_msg(gss_msg);
-		spin_unlock(&gss_auth->lock);
-		gss_release_msg(gss_msg);
-	} else {
-		struct auth_cred acred = { .uid = uid };
-		spin_unlock(&gss_auth->lock);
-		cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
-		if (IS_ERR(cred)) {
-			err = PTR_ERR(cred);
-			goto err_put_ctx;
-		}
-		gss_cred_set_ctx(cred, gss_get_ctx(ctx));
-	}
-	gss_put_ctx(ctx);
-	kfree(buf);
-	dprintk("RPC:       gss_pipe_downcall returning length %Zu\n", mlen);
-	return mlen;
+	gss_msg->ctx = gss_get_ctx(ctx);
+	err = mlen;
+
+err_release_msg:
+	spin_lock(&inode->i_lock);
+	__gss_unhash_msg(gss_msg);
+	spin_unlock(&inode->i_lock);
+	gss_release_msg(gss_msg);
 err_put_ctx:
 	gss_put_ctx(ctx);
 err:
 	kfree(buf);
 out:
-	dprintk("RPC:       gss_pipe_downcall returning %d\n", err);
+	dprintk("RPC:       gss_pipe_downcall returning %Zd\n", err);
 	return err;
 }
 
@@ -563,27 +565,21 @@
 gss_pipe_release(struct inode *inode)
 {
 	struct rpc_inode *rpci = RPC_I(inode);
-	struct rpc_clnt *clnt;
-	struct rpc_auth *auth;
-	struct gss_auth *gss_auth;
+	struct gss_upcall_msg *gss_msg;
 
-	clnt = rpci->private;
-	auth = clnt->cl_auth;
-	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-	spin_lock(&gss_auth->lock);
-	while (!list_empty(&gss_auth->upcalls)) {
-		struct gss_upcall_msg *gss_msg;
+	spin_lock(&inode->i_lock);
+	while (!list_empty(&rpci->in_downcall)) {
 
-		gss_msg = list_entry(gss_auth->upcalls.next,
+		gss_msg = list_entry(rpci->in_downcall.next,
 				struct gss_upcall_msg, list);
 		gss_msg->msg.errno = -EPIPE;
 		atomic_inc(&gss_msg->count);
 		__gss_unhash_msg(gss_msg);
-		spin_unlock(&gss_auth->lock);
+		spin_unlock(&inode->i_lock);
 		gss_release_msg(gss_msg);
-		spin_lock(&gss_auth->lock);
+		spin_lock(&inode->i_lock);
 	}
-	spin_unlock(&gss_auth->lock);
+	spin_unlock(&inode->i_lock);
 }
 
 static void
@@ -637,18 +633,13 @@
 	gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
 	if (gss_auth->service == 0)
 		goto err_put_mech;
-	INIT_LIST_HEAD(&gss_auth->upcalls);
-	spin_lock_init(&gss_auth->lock);
 	auth = &gss_auth->rpc_auth;
 	auth->au_cslack = GSS_CRED_SLACK >> 2;
 	auth->au_rslack = GSS_VERF_SLACK >> 2;
 	auth->au_ops = &authgss_ops;
 	auth->au_flavor = flavor;
 	atomic_set(&auth->au_count, 1);
-
-	err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
-	if (err)
-		goto err_put_mech;
+	kref_init(&gss_auth->kref);
 
 	gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
 			clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
@@ -657,7 +648,13 @@
 		goto err_put_mech;
 	}
 
+	err = rpcauth_init_credcache(auth);
+	if (err)
+		goto err_unlink_pipe;
+
 	return auth;
+err_unlink_pipe:
+	rpc_unlink(gss_auth->dentry);
 err_put_mech:
 	gss_mech_put(gss_auth->mech);
 err_free:
@@ -668,6 +665,25 @@
 }
 
 static void
+gss_free(struct gss_auth *gss_auth)
+{
+	rpc_unlink(gss_auth->dentry);
+	gss_auth->dentry = NULL;
+	gss_mech_put(gss_auth->mech);
+
+	kfree(gss_auth);
+	module_put(THIS_MODULE);
+}
+
+static void
+gss_free_callback(struct kref *kref)
+{
+	struct gss_auth *gss_auth = container_of(kref, struct gss_auth, kref);
+
+	gss_free(gss_auth);
+}
+
+static void
 gss_destroy(struct rpc_auth *auth)
 {
 	struct gss_auth *gss_auth;
@@ -675,23 +691,51 @@
 	dprintk("RPC:       destroying GSS authenticator %p flavor %d\n",
 			auth, auth->au_flavor);
 
-	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-	rpc_unlink(gss_auth->dentry);
-	gss_auth->dentry = NULL;
-	gss_mech_put(gss_auth->mech);
+	rpcauth_destroy_credcache(auth);
 
-	rpcauth_free_credcache(auth);
-	kfree(gss_auth);
-	module_put(THIS_MODULE);
+	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
+	kref_put(&gss_auth->kref, gss_free_callback);
 }
 
-/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure
+/*
+ * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call
+ * to the server with the GSS control procedure field set to
+ * RPC_GSS_PROC_DESTROY. This should normally cause the server to release
+ * all RPCSEC_GSS state associated with that context.
+ */
+static int
+gss_destroying_context(struct rpc_cred *cred)
+{
+	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+	struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
+	struct rpc_task *task;
+
+	if (gss_cred->gc_ctx == NULL ||
+			gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY)
+		return 0;
+
+	gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY;
+	cred->cr_ops = &gss_nullops;
+
+	/* Take a reference to ensure the cred will be destroyed either
+	 * by the RPC call or by the put_rpccred() below */
+	get_rpccred(cred);
+
+	task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
+	if (!IS_ERR(task))
+		rpc_put_task(task);
+
+	put_rpccred(cred);
+	return 1;
+}
+
+/* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure
  * to create a new cred or context, so they check that things have been
  * allocated before freeing them. */
 static void
-gss_destroy_ctx(struct gss_cl_ctx *ctx)
+gss_do_free_ctx(struct gss_cl_ctx *ctx)
 {
-	dprintk("RPC:       gss_destroy_ctx\n");
+	dprintk("RPC:       gss_free_ctx\n");
 
 	if (ctx->gc_gss_ctx)
 		gss_delete_sec_context(&ctx->gc_gss_ctx);
@@ -701,15 +745,46 @@
 }
 
 static void
-gss_destroy_cred(struct rpc_cred *rc)
+gss_free_ctx_callback(struct rcu_head *head)
 {
-	struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
+	struct gss_cl_ctx *ctx = container_of(head, struct gss_cl_ctx, gc_rcu);
+	gss_do_free_ctx(ctx);
+}
 
-	dprintk("RPC:       gss_destroy_cred \n");
+static void
+gss_free_ctx(struct gss_cl_ctx *ctx)
+{
+	call_rcu(&ctx->gc_rcu, gss_free_ctx_callback);
+}
 
-	if (cred->gc_ctx)
-		gss_put_ctx(cred->gc_ctx);
-	kfree(cred);
+static void
+gss_free_cred(struct gss_cred *gss_cred)
+{
+	dprintk("RPC:       gss_free_cred %p\n", gss_cred);
+	kfree(gss_cred);
+}
+
+static void
+gss_free_cred_callback(struct rcu_head *head)
+{
+	struct gss_cred *gss_cred = container_of(head, struct gss_cred, gc_base.cr_rcu);
+	gss_free_cred(gss_cred);
+}
+
+static void
+gss_destroy_cred(struct rpc_cred *cred)
+{
+	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+	struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
+	struct gss_cl_ctx *ctx = gss_cred->gc_ctx;
+
+	if (gss_destroying_context(cred))
+		return;
+	rcu_assign_pointer(gss_cred->gc_ctx, NULL);
+	call_rcu(&cred->cr_rcu, gss_free_cred_callback);
+	if (ctx)
+		gss_put_ctx(ctx);
+	kref_put(&gss_auth->kref, gss_free_callback);
 }
 
 /*
@@ -734,16 +809,14 @@
 	if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
 		goto out_err;
 
-	atomic_set(&cred->gc_count, 1);
-	cred->gc_uid = acred->uid;
+	rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops);
 	/*
 	 * Note: in order to force a call to call_refresh(), we deliberately
 	 * fail to flag the credential as RPCAUTH_CRED_UPTODATE.
 	 */
-	cred->gc_flags = 0;
-	cred->gc_base.cr_ops = &gss_credops;
-	cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
+	cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
 	cred->gc_service = gss_auth->service;
+	kref_get(&gss_auth->kref);
 	return &cred->gc_base;
 
 out_err:
@@ -774,7 +847,7 @@
 	 * we don't really care if the credential has expired or not,
 	 * since the caller should be prepared to reinitialise it.
 	 */
-	if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
+	if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
 		goto out;
 	/* Don't match with creds that have expired. */
 	if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
@@ -830,7 +903,7 @@
 	mic.data = (u8 *)(p + 1);
 	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
-		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 	} else if (maj_stat != 0) {
 		printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
 		goto out_put_ctx;
@@ -855,6 +928,13 @@
 	return 0;
 }
 
+/* Dummy refresh routine: used only when destroying the context */
+static int
+gss_refresh_null(struct rpc_task *task)
+{
+	return -EACCES;
+}
+
 static __be32 *
 gss_validate(struct rpc_task *task, __be32 *p)
 {
@@ -883,12 +963,15 @@
 
 	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-	if (maj_stat)
+		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+	if (maj_stat) {
+		dprintk("RPC: %5u gss_validate: gss_verify_mic returned"
+				"error 0x%08x\n", task->tk_pid, maj_stat);
 		goto out_bad;
+	}
 	/* We leave it to unwrap to calculate au_rslack. For now we just
 	 * calculate the length of the verifier: */
-	task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2;
+	cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2;
 	gss_put_ctx(ctx);
 	dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n",
 			task->tk_pid);
@@ -917,7 +1000,9 @@
 	offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
 	*p++ = htonl(rqstp->rq_seqno);
 
+	lock_kernel();
 	status = encode(rqstp, p, obj);
+	unlock_kernel();
 	if (status)
 		return status;
 
@@ -937,7 +1022,7 @@
 	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
 	status = -EIO; /* XXX? */
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 	else if (maj_stat)
 		return status;
 	q = xdr_encode_opaque(p, NULL, mic.len);
@@ -1011,7 +1096,9 @@
 	offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
 	*p++ = htonl(rqstp->rq_seqno);
 
+	lock_kernel();
 	status = encode(rqstp, p, obj);
+	unlock_kernel();
 	if (status)
 		return status;
 
@@ -1036,7 +1123,7 @@
 	/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
 	 * done anyway, so it's safe to put the request on the wire: */
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 	else if (maj_stat)
 		return status;
 
@@ -1070,12 +1157,16 @@
 		/* The spec seems a little ambiguous here, but I think that not
 		 * wrapping context destruction requests makes the most sense.
 		 */
+		lock_kernel();
 		status = encode(rqstp, p, obj);
+		unlock_kernel();
 		goto out;
 	}
 	switch (gss_cred->gc_service) {
 		case RPC_GSS_SVC_NONE:
+			lock_kernel();
 			status = encode(rqstp, p, obj);
+			unlock_kernel();
 			break;
 		case RPC_GSS_SVC_INTEGRITY:
 			status = gss_wrap_req_integ(cred, ctx, encode,
@@ -1123,7 +1214,7 @@
 
 	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 	if (maj_stat != GSS_S_COMPLETE)
 		return status;
 	return 0;
@@ -1148,7 +1239,7 @@
 
 	maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
-		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 	if (maj_stat != GSS_S_COMPLETE)
 		return status;
 	if (ntohl(*(*p)++) != rqstp->rq_seqno)
@@ -1188,10 +1279,12 @@
 			break;
 	}
 	/* take into account extra slack for integrity and privacy cases: */
-	task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp)
+	cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
 						+ (savedlen - head->iov_len);
 out_decode:
+	lock_kernel();
 	status = decode(rqstp, p, obj);
+	unlock_kernel();
 out:
 	gss_put_ctx(ctx);
 	dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid,
@@ -1199,7 +1292,7 @@
 	return status;
 }
 
-static struct rpc_authops authgss_ops = {
+static const struct rpc_authops authgss_ops = {
 	.owner		= THIS_MODULE,
 	.au_flavor	= RPC_AUTH_GSS,
 #ifdef RPC_DEBUG
@@ -1211,7 +1304,7 @@
 	.crcreate	= gss_create_cred
 };
 
-static struct rpc_credops gss_credops = {
+static const struct rpc_credops gss_credops = {
 	.cr_name	= "AUTH_GSS",
 	.crdestroy	= gss_destroy_cred,
 	.cr_init	= gss_cred_init,
@@ -1223,6 +1316,17 @@
 	.crunwrap_resp	= gss_unwrap_resp,
 };
 
+static const struct rpc_credops gss_nullops = {
+	.cr_name	= "AUTH_GSS",
+	.crdestroy	= gss_destroy_cred,
+	.crmatch	= gss_match,
+	.crmarshal	= gss_marshal,
+	.crrefresh	= gss_refresh_null,
+	.crvalidate	= gss_validate,
+	.crwrap_req	= gss_wrap_req,
+	.crunwrap_resp	= gss_unwrap_resp,
+};
+
 static struct rpc_pipe_ops gss_upcall_ops = {
 	.upcall		= gss_pipe_upcall,
 	.downcall	= gss_pipe_downcall,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 7b19432..9843eac 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -201,7 +201,7 @@
 	kfree(kctx);
 }
 
-static struct gss_api_ops gss_kerberos_ops = {
+static const struct gss_api_ops gss_kerberos_ops = {
 	.gss_import_sec_context	= gss_import_sec_context_kerberos,
 	.gss_get_mic		= gss_get_mic_kerberos,
 	.gss_verify_mic		= gss_verify_mic_kerberos,
@@ -231,6 +231,7 @@
 static struct gss_api_mech gss_kerberos_mech = {
 	.gm_name	= "krb5",
 	.gm_owner	= THIS_MODULE,
+	.gm_oid		= {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},
 	.gm_ops		= &gss_kerberos_ops,
 	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
 	.gm_pfs		= gss_kerberos_pfs,
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 2687251..61801a0 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -194,6 +194,20 @@
 EXPORT_SYMBOL(gss_mech_get_by_pseudoflavor);
 
 u32
+gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service)
+{
+	int i;
+
+	for (i = 0; i < gm->gm_pf_num; i++) {
+		if (gm->gm_pfs[i].service == service) {
+			return gm->gm_pfs[i].pseudoflavor;
+		}
+	}
+	return RPC_AUTH_MAXFLAVOR; /* illegal value */
+}
+EXPORT_SYMBOL(gss_svc_to_pseudoflavor);
+
+u32
 gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
 {
 	int i;
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 7e15aa6..5deb4b6 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -202,7 +202,7 @@
 	return err;
 }
 
-static struct gss_api_ops gss_spkm3_ops = {
+static const struct gss_api_ops gss_spkm3_ops = {
 	.gss_import_sec_context	= gss_import_sec_context_spkm3,
 	.gss_get_mic		= gss_get_mic_spkm3,
 	.gss_verify_mic		= gss_verify_mic_spkm3,
@@ -217,6 +217,7 @@
 static struct gss_api_mech gss_spkm3_mech = {
 	.gm_name	= "spkm3",
 	.gm_owner	= THIS_MODULE,
+	.gm_oid		= {7, "\053\006\001\005\005\001\003"},
 	.gm_ops		= &gss_spkm3_ops,
 	.gm_pf_num	= ARRAY_SIZE(gss_spkm3_pfs),
 	.gm_pfs		= gss_spkm3_pfs,
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 099a983..4906975 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -743,6 +743,15 @@
 
 static struct auth_ops svcauthops_gss;
 
+u32 svcauth_gss_flavor(struct auth_domain *dom)
+{
+	struct gss_domain *gd = container_of(dom, struct gss_domain, h);
+
+	return gd->pseudoflavor;
+}
+
+EXPORT_SYMBOL(svcauth_gss_flavor);
+
 int
 svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
 {
@@ -853,7 +862,7 @@
 	u32 priv_len, maj_stat;
 	int pad, saved_len, remaining_len, offset;
 
-	rqstp->rq_sendfile_ok = 0;
+	rqstp->rq_splice_ok = 0;
 
 	priv_len = svc_getnl(&buf->head[0]);
 	if (rqstp->rq_deferred) {
@@ -913,10 +922,23 @@
 	struct gss_svc_data *svcdata = rqstp->rq_auth_data;
 	struct rsc *rsci = svcdata->rsci;
 	struct rpc_gss_wire_cred *gc = &svcdata->clcred;
+	int stat;
 
-	rqstp->rq_client = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
-	if (rqstp->rq_client == NULL)
+	/*
+	 * A gss export can be specified either by:
+	 * 	export	*(sec=krb5,rw)
+	 * or by
+	 * 	export gss/krb5(rw)
+	 * The latter is deprecated; but for backwards compatibility reasons
+	 * the nfsd code will still fall back on trying it if the former
+	 * doesn't work; so we try to make both available to nfsd, below.
+	 */
+	rqstp->rq_gssclient = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
+	if (rqstp->rq_gssclient == NULL)
 		return SVC_DENIED;
+	stat = svcauth_unix_set_client(rqstp);
+	if (stat == SVC_DROP)
+		return stat;
 	return SVC_OK;
 }
 
@@ -1088,7 +1110,6 @@
 			svc_putnl(resv, GSS_SEQ_WIN);
 			if (svc_safe_putnetobj(resv, &rsip->out_token))
 				goto drop;
-			rqstp->rq_client = NULL;
 		}
 		goto complete;
 	case RPC_GSS_PROC_DESTROY:
@@ -1131,6 +1152,8 @@
 		}
 		svcdata->rsci = rsci;
 		cache_get(&rsci->h);
+		rqstp->rq_flavor = gss_svc_to_pseudoflavor(
+					rsci->mechctx->mech_type, gc->gc_svc);
 		ret = SVC_OK;
 		goto out;
 	}
@@ -1317,6 +1340,9 @@
 	if (rqstp->rq_client)
 		auth_domain_put(rqstp->rq_client);
 	rqstp->rq_client = NULL;
+	if (rqstp->rq_gssclient)
+		auth_domain_put(rqstp->rq_gssclient);
+	rqstp->rq_gssclient = NULL;
 	if (rqstp->rq_cred.cr_group_info)
 		put_group_info(rqstp->rq_cred.cr_group_info);
 	rqstp->rq_cred.cr_group_info = NULL;
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 3df9fcc..537d0e8 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -76,7 +76,7 @@
 static int
 nul_refresh(struct rpc_task *task)
 {
-	task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
+	set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
 	return 0;
 }
 
@@ -101,7 +101,7 @@
 	return p;
 }
 
-struct rpc_authops authnull_ops = {
+const struct rpc_authops authnull_ops = {
 	.owner		= THIS_MODULE,
 	.au_flavor	= RPC_AUTH_NULL,
 #ifdef RPC_DEBUG
@@ -122,7 +122,7 @@
 };
 
 static
-struct rpc_credops	null_credops = {
+const struct rpc_credops null_credops = {
 	.cr_name	= "AUTH_NULL",
 	.crdestroy	= nul_destroy_cred,
 	.crmatch	= nul_match,
@@ -133,9 +133,11 @@
 
 static
 struct rpc_cred null_cred = {
+	.cr_lru		= LIST_HEAD_INIT(null_cred.cr_lru),
+	.cr_auth	= &null_auth,
 	.cr_ops		= &null_credops,
 	.cr_count	= ATOMIC_INIT(1),
-	.cr_flags	= RPCAUTH_CRED_UPTODATE,
+	.cr_flags	= 1UL << RPCAUTH_CRED_UPTODATE,
 #ifdef RPC_DEBUG
 	.cr_magic	= RPCAUTH_CRED_MAGIC,
 #endif
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 4e7733a..5ed91e5 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -20,11 +20,6 @@
 	gid_t			uc_gids[NFS_NGROUPS];
 };
 #define uc_uid			uc_base.cr_uid
-#define uc_count		uc_base.cr_count
-#define uc_flags		uc_base.cr_flags
-#define uc_expire		uc_base.cr_expire
-
-#define UNX_CRED_EXPIRE		(60 * HZ)
 
 #define UNX_WRITESLACK		(21 + (UNX_MAXNODENAME >> 2))
 
@@ -34,15 +29,14 @@
 
 static struct rpc_auth		unix_auth;
 static struct rpc_cred_cache	unix_cred_cache;
-static struct rpc_credops	unix_credops;
+static const struct rpc_credops	unix_credops;
 
 static struct rpc_auth *
 unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 {
 	dprintk("RPC:       creating UNIX authenticator for client %p\n",
 			clnt);
-	if (atomic_inc_return(&unix_auth.au_count) == 0)
-		unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
+	atomic_inc(&unix_auth.au_count);
 	return &unix_auth;
 }
 
@@ -50,7 +44,7 @@
 unx_destroy(struct rpc_auth *auth)
 {
 	dprintk("RPC:       destroying UNIX authenticator %p\n", auth);
-	rpcauth_free_credcache(auth);
+	rpcauth_clear_credcache(auth->au_credcache);
 }
 
 /*
@@ -74,8 +68,8 @@
 	if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
 		return ERR_PTR(-ENOMEM);
 
-	atomic_set(&cred->uc_count, 1);
-	cred->uc_flags = RPCAUTH_CRED_UPTODATE;
+	rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
+	cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
 	if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
 		cred->uc_uid = 0;
 		cred->uc_gid = 0;
@@ -85,22 +79,34 @@
 		if (groups > NFS_NGROUPS)
 			groups = NFS_NGROUPS;
 
-		cred->uc_uid = acred->uid;
 		cred->uc_gid = acred->gid;
 		for (i = 0; i < groups; i++)
 			cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
 		if (i < NFS_NGROUPS)
 		  cred->uc_gids[i] = NOGROUP;
 	}
-	cred->uc_base.cr_ops = &unix_credops;
 
-	return (struct rpc_cred *) cred;
+	return &cred->uc_base;
+}
+
+static void
+unx_free_cred(struct unx_cred *unx_cred)
+{
+	dprintk("RPC:       unx_free_cred %p\n", unx_cred);
+	kfree(unx_cred);
+}
+
+static void
+unx_free_cred_callback(struct rcu_head *head)
+{
+	struct unx_cred *unx_cred = container_of(head, struct unx_cred, uc_base.cr_rcu);
+	unx_free_cred(unx_cred);
 }
 
 static void
 unx_destroy_cred(struct rpc_cred *cred)
 {
-	kfree(cred);
+	call_rcu(&cred->cr_rcu, unx_free_cred_callback);
 }
 
 /*
@@ -111,7 +117,7 @@
 static int
 unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
 {
-	struct unx_cred	*cred = (struct unx_cred *) rcred;
+	struct unx_cred	*cred = container_of(rcred, struct unx_cred, uc_base);
 	int		i;
 
 	if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
@@ -142,7 +148,7 @@
 unx_marshal(struct rpc_task *task, __be32 *p)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
-	struct unx_cred	*cred = (struct unx_cred *) task->tk_msg.rpc_cred;
+	struct unx_cred	*cred = container_of(task->tk_msg.rpc_cred, struct unx_cred, uc_base);
 	__be32		*base, *hold;
 	int		i;
 
@@ -175,7 +181,7 @@
 static int
 unx_refresh(struct rpc_task *task)
 {
-	task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
+	set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
 	return 0;
 }
 
@@ -198,13 +204,18 @@
 		printk("RPC: giant verf size: %u\n", size);
 		return NULL;
 	}
-	task->tk_auth->au_rslack = (size >> 2) + 2;
+	task->tk_msg.rpc_cred->cr_auth->au_rslack = (size >> 2) + 2;
 	p += (size >> 2);
 
 	return p;
 }
 
-struct rpc_authops	authunix_ops = {
+void __init rpc_init_authunix(void)
+{
+	spin_lock_init(&unix_cred_cache.lock);
+}
+
+const struct rpc_authops authunix_ops = {
 	.owner		= THIS_MODULE,
 	.au_flavor	= RPC_AUTH_UNIX,
 #ifdef RPC_DEBUG
@@ -218,7 +229,6 @@
 
 static
 struct rpc_cred_cache	unix_cred_cache = {
-	.expire		= UNX_CRED_EXPIRE,
 };
 
 static
@@ -232,7 +242,7 @@
 };
 
 static
-struct rpc_credops	unix_credops = {
+const struct rpc_credops unix_credops = {
 	.cr_name	= "AUTH_UNIX",
 	.crdestroy	= unx_destroy_cred,
 	.crmatch	= unx_match,
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 543b085..01c3c41 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1210,7 +1210,7 @@
 	return cd->cache_show(m, cd, cp);
 }
 
-static struct seq_operations cache_content_op = {
+static const struct seq_operations cache_content_op = {
 	.start	= c_start,
 	.next	= c_next,
 	.stop	= c_stop,
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d8fbee4..52429b1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -44,6 +44,12 @@
 	dprintk("RPC: %5u %s (status %d)\n", t->tk_pid,		\
 			__FUNCTION__, t->tk_status)
 
+/*
+ * All RPC clients are linked into this list
+ */
+static LIST_HEAD(all_clients);
+static DEFINE_SPINLOCK(rpc_client_lock);
+
 static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
 
 
@@ -66,6 +72,21 @@
 static __be32 *	call_header(struct rpc_task *task);
 static __be32 *	call_verify(struct rpc_task *task);
 
+static int	rpc_ping(struct rpc_clnt *clnt, int flags);
+
+static void rpc_register_client(struct rpc_clnt *clnt)
+{
+	spin_lock(&rpc_client_lock);
+	list_add(&clnt->cl_clients, &all_clients);
+	spin_unlock(&rpc_client_lock);
+}
+
+static void rpc_unregister_client(struct rpc_clnt *clnt)
+{
+	spin_lock(&rpc_client_lock);
+	list_del(&clnt->cl_clients);
+	spin_unlock(&rpc_client_lock);
+}
 
 static int
 rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
@@ -111,6 +132,9 @@
 	dprintk("RPC:       creating %s client for %s (xprt %p)\n",
 			program->name, servname, xprt);
 
+	err = rpciod_up();
+	if (err)
+		goto out_no_rpciod;
 	err = -EINVAL;
 	if (!xprt)
 		goto out_no_xprt;
@@ -121,8 +145,6 @@
 	clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
 	if (!clnt)
 		goto out_err;
-	atomic_set(&clnt->cl_users, 0);
-	atomic_set(&clnt->cl_count, 1);
 	clnt->cl_parent = clnt;
 
 	clnt->cl_server = clnt->cl_inline_name;
@@ -148,6 +170,8 @@
 	if (clnt->cl_metrics == NULL)
 		goto out_no_stats;
 	clnt->cl_program  = program;
+	INIT_LIST_HEAD(&clnt->cl_tasks);
+	spin_lock_init(&clnt->cl_lock);
 
 	if (!xprt_bound(clnt->cl_xprt))
 		clnt->cl_autobind = 1;
@@ -155,6 +179,8 @@
 	clnt->cl_rtt = &clnt->cl_rtt_default;
 	rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval);
 
+	kref_init(&clnt->cl_kref);
+
 	err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
 	if (err < 0)
 		goto out_no_path;
@@ -172,6 +198,7 @@
 	if (clnt->cl_nodelen > UNX_MAXNODENAME)
 		clnt->cl_nodelen = UNX_MAXNODENAME;
 	memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen);
+	rpc_register_client(clnt);
 	return clnt;
 
 out_no_auth:
@@ -188,6 +215,8 @@
 out_err:
 	xprt_put(xprt);
 out_no_xprt:
+	rpciod_down();
+out_no_rpciod:
 	return ERR_PTR(err);
 }
 
@@ -205,13 +234,32 @@
 {
 	struct rpc_xprt *xprt;
 	struct rpc_clnt *clnt;
+	struct rpc_xprtsock_create xprtargs = {
+		.proto = args->protocol,
+		.srcaddr = args->saddress,
+		.dstaddr = args->address,
+		.addrlen = args->addrsize,
+		.timeout = args->timeout
+	};
+	char servername[20];
 
-	xprt = xprt_create_transport(args->protocol, args->address,
-					args->addrsize, args->timeout);
+	xprt = xprt_create_transport(&xprtargs);
 	if (IS_ERR(xprt))
 		return (struct rpc_clnt *)xprt;
 
 	/*
+	 * If the caller chooses not to specify a hostname, whip
+	 * up a string representation of the passed-in address.
+	 */
+	if (args->servername == NULL) {
+		struct sockaddr_in *addr =
+					(struct sockaddr_in *) &args->address;
+		snprintf(servername, sizeof(servername), NIPQUAD_FMT,
+			NIPQUAD(addr->sin_addr.s_addr));
+		args->servername = servername;
+	}
+
+	/*
 	 * By default, kernel RPC client connects from a reserved port.
 	 * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters,
 	 * but it is always enabled for rpciod, which handles the connect
@@ -245,8 +293,6 @@
 		clnt->cl_intr = 1;
 	if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
 		clnt->cl_autobind = 1;
-	if (args->flags & RPC_CLNT_CREATE_ONESHOT)
-		clnt->cl_oneshot = 1;
 	if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
 		clnt->cl_discrtry = 1;
 
@@ -268,24 +314,25 @@
 	new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
 	if (!new)
 		goto out_no_clnt;
-	atomic_set(&new->cl_count, 1);
-	atomic_set(&new->cl_users, 0);
+	new->cl_parent = clnt;
+	/* Turn off autobind on clones */
+	new->cl_autobind = 0;
+	INIT_LIST_HEAD(&new->cl_tasks);
+	spin_lock_init(&new->cl_lock);
+	rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
 	new->cl_metrics = rpc_alloc_iostats(clnt);
 	if (new->cl_metrics == NULL)
 		goto out_no_stats;
+	kref_init(&new->cl_kref);
 	err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
 	if (err != 0)
 		goto out_no_path;
-	new->cl_parent = clnt;
-	atomic_inc(&clnt->cl_count);
-	new->cl_xprt = xprt_get(clnt->cl_xprt);
-	/* Turn off autobind on clones */
-	new->cl_autobind = 0;
-	new->cl_oneshot = 0;
-	new->cl_dead = 0;
-	rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
 	if (new->cl_auth)
 		atomic_inc(&new->cl_auth->au_count);
+	xprt_get(clnt->cl_xprt);
+	kref_get(&clnt->cl_kref);
+	rpc_register_client(new);
+	rpciod_up();
 	return new;
 out_no_path:
 	rpc_free_iostats(new->cl_metrics);
@@ -298,86 +345,86 @@
 
 /*
  * Properly shut down an RPC client, terminating all outstanding
- * requests. Note that we must be certain that cl_oneshot and
- * cl_dead are cleared, or else the client would be destroyed
- * when the last task releases it.
+ * requests.
  */
-int
-rpc_shutdown_client(struct rpc_clnt *clnt)
+void rpc_shutdown_client(struct rpc_clnt *clnt)
 {
-	dprintk("RPC:       shutting down %s client for %s, tasks=%d\n",
-			clnt->cl_protname, clnt->cl_server,
-			atomic_read(&clnt->cl_users));
+	dprintk("RPC:       shutting down %s client for %s\n",
+			clnt->cl_protname, clnt->cl_server);
 
-	while (atomic_read(&clnt->cl_users) > 0) {
-		/* Don't let rpc_release_client destroy us */
-		clnt->cl_oneshot = 0;
-		clnt->cl_dead = 0;
+	while (!list_empty(&clnt->cl_tasks)) {
 		rpc_killall_tasks(clnt);
 		wait_event_timeout(destroy_wait,
-			!atomic_read(&clnt->cl_users), 1*HZ);
+			list_empty(&clnt->cl_tasks), 1*HZ);
 	}
 
-	if (atomic_read(&clnt->cl_users) < 0) {
-		printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n",
-				clnt, atomic_read(&clnt->cl_users));
-#ifdef RPC_DEBUG
-		rpc_show_tasks();
-#endif
-		BUG();
-	}
-
-	return rpc_destroy_client(clnt);
+	rpc_release_client(clnt);
 }
 
 /*
- * Delete an RPC client
+ * Free an RPC client
  */
-int
-rpc_destroy_client(struct rpc_clnt *clnt)
+static void
+rpc_free_client(struct kref *kref)
 {
-	if (!atomic_dec_and_test(&clnt->cl_count))
-		return 1;
-	BUG_ON(atomic_read(&clnt->cl_users) != 0);
+	struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
 
 	dprintk("RPC:       destroying %s client for %s\n",
 			clnt->cl_protname, clnt->cl_server);
-	if (clnt->cl_auth) {
-		rpcauth_destroy(clnt->cl_auth);
-		clnt->cl_auth = NULL;
-	}
 	if (!IS_ERR(clnt->cl_dentry)) {
 		rpc_rmdir(clnt->cl_dentry);
 		rpc_put_mount();
 	}
 	if (clnt->cl_parent != clnt) {
-		rpc_destroy_client(clnt->cl_parent);
+		rpc_release_client(clnt->cl_parent);
 		goto out_free;
 	}
 	if (clnt->cl_server != clnt->cl_inline_name)
 		kfree(clnt->cl_server);
 out_free:
+	rpc_unregister_client(clnt);
 	rpc_free_iostats(clnt->cl_metrics);
 	clnt->cl_metrics = NULL;
 	xprt_put(clnt->cl_xprt);
+	rpciod_down();
 	kfree(clnt);
-	return 0;
 }
 
 /*
- * Release an RPC client
+ * Free an RPC client
+ */
+static void
+rpc_free_auth(struct kref *kref)
+{
+	struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
+
+	if (clnt->cl_auth == NULL) {
+		rpc_free_client(kref);
+		return;
+	}
+
+	/*
+	 * Note: RPCSEC_GSS may need to send NULL RPC calls in order to
+	 *       release remaining GSS contexts. This mechanism ensures
+	 *       that it can do so safely.
+	 */
+	kref_init(kref);
+	rpcauth_release(clnt->cl_auth);
+	clnt->cl_auth = NULL;
+	kref_put(kref, rpc_free_client);
+}
+
+/*
+ * Release reference to the RPC client
  */
 void
 rpc_release_client(struct rpc_clnt *clnt)
 {
-	dprintk("RPC:       rpc_release_client(%p, %d)\n",
-			clnt, atomic_read(&clnt->cl_users));
+	dprintk("RPC:       rpc_release_client(%p)\n", clnt);
 
-	if (!atomic_dec_and_test(&clnt->cl_users))
-		return;
-	wake_up(&destroy_wait);
-	if (clnt->cl_oneshot || clnt->cl_dead)
-		rpc_destroy_client(clnt);
+	if (list_empty(&clnt->cl_tasks))
+		wake_up(&destroy_wait);
+	kref_put(&clnt->cl_kref, rpc_free_auth);
 }
 
 /**
@@ -468,82 +515,96 @@
 	rpc_restore_sigmask(oldset);
 }
 
-/*
- * New rpc_call implementation
+static
+struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
+		struct rpc_message *msg,
+		int flags,
+		const struct rpc_call_ops *ops,
+		void *data)
+{
+	struct rpc_task *task, *ret;
+	sigset_t oldset;
+
+	task = rpc_new_task(clnt, flags, ops, data);
+	if (task == NULL) {
+		rpc_release_calldata(ops, data);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
+	rpc_task_sigmask(task, &oldset);
+	if (msg != NULL) {
+		rpc_call_setup(task, msg, 0);
+		if (task->tk_status != 0) {
+			ret = ERR_PTR(task->tk_status);
+			rpc_put_task(task);
+			goto out;
+		}
+	}
+	atomic_inc(&task->tk_count);
+	rpc_execute(task);
+	ret = task;
+out:
+	rpc_restore_sigmask(&oldset);
+	return ret;
+}
+
+/**
+ * rpc_call_sync - Perform a synchronous RPC call
+ * @clnt: pointer to RPC client
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
  */
 int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 {
 	struct rpc_task	*task;
-	sigset_t	oldset;
-	int		status;
-
-	/* If this client is slain all further I/O fails */
-	if (clnt->cl_dead)
-		return -EIO;
+	int status;
 
 	BUG_ON(flags & RPC_TASK_ASYNC);
 
-	task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
-	if (task == NULL)
-		return -ENOMEM;
-
-	/* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
-	rpc_task_sigmask(task, &oldset);
-
-	/* Set up the call info struct and execute the task */
-	rpc_call_setup(task, msg, 0);
-	if (task->tk_status == 0) {
-		atomic_inc(&task->tk_count);
-		rpc_execute(task);
-	}
+	task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL);
+	if (IS_ERR(task))
+		return PTR_ERR(task);
 	status = task->tk_status;
 	rpc_put_task(task);
-	rpc_restore_sigmask(&oldset);
 	return status;
 }
 
-/*
- * New rpc_call implementation
+/**
+ * rpc_call_async - Perform an asynchronous RPC call
+ * @clnt: pointer to RPC client
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
+ * @ops: RPC call ops
+ * @data: user call data
  */
 int
 rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
 	       const struct rpc_call_ops *tk_ops, void *data)
 {
 	struct rpc_task	*task;
-	sigset_t	oldset;
-	int		status;
 
-	/* If this client is slain all further I/O fails */
-	status = -EIO;
-	if (clnt->cl_dead)
-		goto out_release;
-
-	flags |= RPC_TASK_ASYNC;
-
-	/* Create/initialize a new RPC task */
-	status = -ENOMEM;
-	if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
-		goto out_release;
-
-	/* Mask signals on GSS_AUTH upcalls */
-	rpc_task_sigmask(task, &oldset);
-
-	rpc_call_setup(task, msg, 0);
-
-	/* Set up the call info struct and execute the task */
-	status = task->tk_status;
-	if (status == 0)
-		rpc_execute(task);
-	else
-		rpc_put_task(task);
-
-	rpc_restore_sigmask(&oldset);
-	return status;
-out_release:
-	rpc_release_calldata(tk_ops, data);
-	return status;
+	task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data);
+	if (IS_ERR(task))
+		return PTR_ERR(task);
+	rpc_put_task(task);
+	return 0;
 }
 
+/**
+ * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
+ * @clnt: pointer to RPC client
+ * @flags: RPC flags
+ * @ops: RPC call ops
+ * @data: user call data
+ */
+struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
+					const struct rpc_call_ops *tk_ops,
+					void *data)
+{
+	return rpc_do_run_task(clnt, NULL, flags, tk_ops, data);
+}
+EXPORT_SYMBOL(rpc_run_task);
 
 void
 rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
@@ -745,7 +806,7 @@
 static void
 call_allocate(struct rpc_task *task)
 {
-	unsigned int slack = task->tk_auth->au_cslack;
+	unsigned int slack = task->tk_msg.rpc_cred->cr_auth->au_cslack;
 	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = task->tk_xprt;
 	struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
@@ -843,10 +904,8 @@
 	if (encode == NULL)
 		return;
 
-	lock_kernel();
 	task->tk_status = rpcauth_wrap_req(task, encode, req, p,
 			task->tk_msg.rpc_argp);
-	unlock_kernel();
 	if (task->tk_status == -ENOMEM) {
 		/* XXX: Is this sane? */
 		rpc_delay(task, 3*HZ);
@@ -1177,10 +1236,8 @@
 	task->tk_action = rpc_exit_task;
 
 	if (decode) {
-		lock_kernel();
 		task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
 						      task->tk_msg.rpc_resp);
-		unlock_kernel();
 	}
 	dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
 			task->tk_status);
@@ -1273,9 +1330,9 @@
 		 * - if it isn't pointer subtraction in the NFS client may give
 		 *   undefined results
 		 */
-		printk(KERN_WARNING
-		       "call_verify: XDR representation not a multiple of"
-		       " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len);
+		dprintk("RPC: %5u %s: XDR representation not a multiple of"
+		       " 4 bytes: 0x%x\n", task->tk_pid, __FUNCTION__,
+		       task->tk_rqstp->rq_rcv_buf.len);
 		goto out_eio;
 	}
 	if ((len -= 3) < 0)
@@ -1283,7 +1340,8 @@
 	p += 1;	/* skip XID */
 
 	if ((n = ntohl(*p++)) != RPC_REPLY) {
-		printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n);
+		dprintk("RPC: %5u %s: not an RPC reply: %x\n",
+				task->tk_pid, __FUNCTION__, n);
 		goto out_garbage;
 	}
 	if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
@@ -1334,7 +1392,8 @@
 			       "authentication.\n", task->tk_client->cl_server);
 			break;
 		default:
-			printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
+			dprintk("RPC: %5u %s: unknown auth error: %x\n",
+					task->tk_pid, __FUNCTION__, n);
 			error = -EIO;
 		}
 		dprintk("RPC: %5u %s: call rejected %d\n",
@@ -1342,7 +1401,8 @@
 		goto out_err;
 	}
 	if (!(p = rpcauth_checkverf(task, p))) {
-		printk(KERN_WARNING "call_verify: auth check failed\n");
+		dprintk("RPC: %5u %s: auth check failed\n",
+				task->tk_pid, __FUNCTION__);
 		goto out_garbage;		/* bad verifier, retry */
 	}
 	len = p - (__be32 *)iov->iov_base - 1;
@@ -1381,7 +1441,8 @@
 				task->tk_pid, __FUNCTION__);
 		break;			/* retry */
 	default:
-		printk(KERN_WARNING "call_verify: server accept status: %x\n", n);
+		dprintk("RPC: %5u %s: server accept status: %x\n",
+				task->tk_pid, __FUNCTION__, n);
 		/* Also retry */
 	}
 
@@ -1395,14 +1456,16 @@
 out_retry:
 		return ERR_PTR(-EAGAIN);
 	}
-	printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__);
 out_eio:
 	error = -EIO;
 out_err:
 	rpc_exit(task, error);
+	dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid,
+			__FUNCTION__, error);
 	return ERR_PTR(error);
 out_overflow:
-	printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
+	dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid,
+			__FUNCTION__);
 	goto out_garbage;
 }
 
@@ -1421,7 +1484,7 @@
 	.p_decode = rpcproc_decode_null,
 };
 
-int rpc_ping(struct rpc_clnt *clnt, int flags)
+static int rpc_ping(struct rpc_clnt *clnt, int flags)
 {
 	struct rpc_message msg = {
 		.rpc_proc = &rpcproc_null,
@@ -1432,3 +1495,51 @@
 	put_rpccred(msg.rpc_cred);
 	return err;
 }
+
+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
+{
+	struct rpc_message msg = {
+		.rpc_proc = &rpcproc_null,
+		.rpc_cred = cred,
+	};
+	return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL);
+}
+EXPORT_SYMBOL(rpc_call_null);
+
+#ifdef RPC_DEBUG
+void rpc_show_tasks(void)
+{
+	struct rpc_clnt *clnt;
+	struct rpc_task *t;
+
+	spin_lock(&rpc_client_lock);
+	if (list_empty(&all_clients))
+		goto out;
+	printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
+		"-rpcwait -action- ---ops--\n");
+	list_for_each_entry(clnt, &all_clients, cl_clients) {
+		if (list_empty(&clnt->cl_tasks))
+			continue;
+		spin_lock(&clnt->cl_lock);
+		list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
+			const char *rpc_waitq = "none";
+
+			if (RPC_IS_QUEUED(t))
+				rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
+
+			printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
+				t->tk_pid,
+				(t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
+				t->tk_flags, t->tk_status,
+				t->tk_client,
+				(t->tk_client ? t->tk_client->cl_prog : 0),
+				t->tk_rqstp, t->tk_timeout,
+				rpc_waitq,
+				t->tk_action, t->tk_ops);
+		}
+		spin_unlock(&clnt->cl_lock);
+	}
+out:
+	spin_unlock(&rpc_client_lock);
+}
+#endif
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 5887457d..e787b6a 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -344,7 +344,7 @@
 		mutex_lock(&inode->i_mutex);
 		clnt = RPC_I(inode)->private;
 		if (clnt) {
-			atomic_inc(&clnt->cl_users);
+			kref_get(&clnt->cl_kref);
 			m->private = clnt;
 		} else {
 			single_release(inode, file);
@@ -448,6 +448,15 @@
 	simple_release_fs(&rpc_mount, &rpc_mount_count);
 }
 
+static int rpc_delete_dentry(struct dentry *dentry)
+{
+	return 1;
+}
+
+static struct dentry_operations rpc_dentry_operations = {
+	.d_delete = rpc_delete_dentry,
+};
+
 static int
 rpc_lookup_parent(char *path, struct nameidata *nd)
 {
@@ -506,7 +515,7 @@
  * FIXME: This probably has races.
  */
 static void
-rpc_depopulate(struct dentry *parent)
+rpc_depopulate(struct dentry *parent, int start, int eof)
 {
 	struct inode *dir = parent->d_inode;
 	struct list_head *pos, *next;
@@ -518,6 +527,10 @@
 	spin_lock(&dcache_lock);
 	list_for_each_safe(pos, next, &parent->d_subdirs) {
 		dentry = list_entry(pos, struct dentry, d_u.d_child);
+		if (!dentry->d_inode ||
+				dentry->d_inode->i_ino < start ||
+				dentry->d_inode->i_ino >= eof)
+			continue;
 		spin_lock(&dentry->d_lock);
 		if (!d_unhashed(dentry)) {
 			dget_locked(dentry);
@@ -533,11 +546,11 @@
 	if (n) {
 		do {
 			dentry = dvec[--n];
-			if (dentry->d_inode) {
-				rpc_close_pipes(dentry->d_inode);
+			if (S_ISREG(dentry->d_inode->i_mode))
 				simple_unlink(dir, dentry);
-			}
-			inode_dir_notify(dir, DN_DELETE);
+			else if (S_ISDIR(dentry->d_inode->i_mode))
+				simple_rmdir(dir, dentry);
+			d_delete(dentry);
 			dput(dentry);
 		} while (n);
 		goto repeat;
@@ -560,6 +573,7 @@
 		dentry = d_alloc_name(parent, files[i].name);
 		if (!dentry)
 			goto out_bad;
+		dentry->d_op = &rpc_dentry_operations;
 		mode = files[i].mode;
 		inode = rpc_get_inode(dir->i_sb, mode);
 		if (!inode) {
@@ -607,21 +621,14 @@
 __rpc_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error;
-
-	shrink_dcache_parent(dentry);
-	if (d_unhashed(dentry))
-		return 0;
-	if ((error = simple_rmdir(dir, dentry)) != 0)
-		return error;
-	if (!error) {
-		inode_dir_notify(dir, DN_DELETE);
-		d_drop(dentry);
-	}
-	return 0;
+	error = simple_rmdir(dir, dentry);
+	if (!error)
+		d_delete(dentry);
+	return error;
 }
 
 static struct dentry *
-rpc_lookup_create(struct dentry *parent, const char *name, int len)
+rpc_lookup_create(struct dentry *parent, const char *name, int len, int exclusive)
 {
 	struct inode *dir = parent->d_inode;
 	struct dentry *dentry;
@@ -630,7 +637,9 @@
 	dentry = lookup_one_len(name, parent, len);
 	if (IS_ERR(dentry))
 		goto out_err;
-	if (dentry->d_inode) {
+	if (!dentry->d_inode)
+		dentry->d_op = &rpc_dentry_operations;
+	else if (exclusive) {
 		dput(dentry);
 		dentry = ERR_PTR(-EEXIST);
 		goto out_err;
@@ -649,7 +658,7 @@
 
 	if ((error = rpc_lookup_parent(path, nd)) != 0)
 		return ERR_PTR(error);
-	dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len);
+	dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len, 1);
 	if (IS_ERR(dentry))
 		rpc_release_path(nd);
 	return dentry;
@@ -681,7 +690,7 @@
 	rpc_release_path(&nd);
 	return dentry;
 err_depopulate:
-	rpc_depopulate(dentry);
+	rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
 	__rpc_rmdir(dir, dentry);
 err_dput:
 	dput(dentry);
@@ -701,7 +710,7 @@
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
 	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-	rpc_depopulate(dentry);
+	rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
 	error = __rpc_rmdir(dir, dentry);
 	dput(dentry);
 	mutex_unlock(&dir->i_mutex);
@@ -716,10 +725,21 @@
 	struct inode *dir, *inode;
 	struct rpc_inode *rpci;
 
-	dentry = rpc_lookup_create(parent, name, strlen(name));
+	dentry = rpc_lookup_create(parent, name, strlen(name), 0);
 	if (IS_ERR(dentry))
 		return dentry;
 	dir = parent->d_inode;
+	if (dentry->d_inode) {
+		rpci = RPC_I(dentry->d_inode);
+		if (rpci->private != private ||
+				rpci->ops != ops ||
+				rpci->flags != flags) {
+			dput (dentry);
+			dentry = ERR_PTR(-EBUSY);
+		}
+		rpci->nkern_readwriters++;
+		goto out;
+	}
 	inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR);
 	if (!inode)
 		goto err_dput;
@@ -730,6 +750,7 @@
 	rpci->private = private;
 	rpci->flags = flags;
 	rpci->ops = ops;
+	rpci->nkern_readwriters = 1;
 	inode_dir_notify(dir, DN_CREATE);
 	dget(dentry);
 out:
@@ -754,13 +775,11 @@
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
 	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-	if (!d_unhashed(dentry)) {
-		d_drop(dentry);
-		if (dentry->d_inode) {
-			rpc_close_pipes(dentry->d_inode);
-			error = simple_unlink(dir, dentry);
-		}
-		inode_dir_notify(dir, DN_DELETE);
+	if (--RPC_I(dentry->d_inode)->nkern_readwriters == 0) {
+		rpc_close_pipes(dentry->d_inode);
+		error = simple_unlink(dir, dentry);
+		if (!error)
+			d_delete(dentry);
 	}
 	dput(dentry);
 	mutex_unlock(&dir->i_mutex);
@@ -833,6 +852,7 @@
 	rpci->nreaders = 0;
 	rpci->nwriters = 0;
 	INIT_LIST_HEAD(&rpci->in_upcall);
+	INIT_LIST_HEAD(&rpci->in_downcall);
 	INIT_LIST_HEAD(&rpci->pipe);
 	rpci->pipelen = 0;
 	init_waitqueue_head(&rpci->waitq);
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 6c7aa8a..d1740db 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -12,6 +12,8 @@
  *  Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  */
 
+#include <linux/module.h>
+
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/kernel.h>
@@ -184,8 +186,8 @@
 		.program	= &rpcb_program,
 		.version	= version,
 		.authflavor	= RPC_AUTH_UNIX,
-		.flags		= (RPC_CLNT_CREATE_ONESHOT |
-				   RPC_CLNT_CREATE_NOPING),
+		.flags		= (RPC_CLNT_CREATE_NOPING |
+				   RPC_CLNT_CREATE_INTR),
 	};
 
 	((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
@@ -238,6 +240,7 @@
 
 	error = rpc_call_sync(rpcb_clnt, &msg, 0);
 
+	rpc_shutdown_client(rpcb_clnt);
 	if (error < 0)
 		printk(KERN_WARNING "RPC: failed to contact local rpcbind "
 				"server (errno %d).\n", -error);
@@ -246,21 +249,20 @@
 	return error;
 }
 
-#ifdef CONFIG_ROOT_NFS
 /**
- * rpcb_getport_external - obtain the port for an RPC service on a given host
+ * rpcb_getport_sync - obtain the port for an RPC service on a given host
  * @sin: address of remote peer
  * @prog: RPC program number to bind
  * @vers: RPC version number to bind
  * @prot: transport protocol to use to make this request
  *
  * Called from outside the RPC client in a synchronous task context.
+ * Uses default timeout parameters specified by underlying transport.
  *
- * For now, this supports only version 2 queries, but is used only by
- * mount_clnt for NFS_ROOT.
+ * XXX: Needs to support IPv6, and rpcbind versions 3 and 4
  */
-int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
-				__u32 vers, int prot)
+int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
+		      __u32 vers, int prot)
 {
 	struct rpcbind_args map = {
 		.r_prog		= prog,
@@ -277,15 +279,16 @@
 	char hostname[40];
 	int status;
 
-	dprintk("RPC:       rpcb_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
-			NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+	dprintk("RPC:       %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
+		__FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
 
-	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
+	sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
 	rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0);
 	if (IS_ERR(rpcb_clnt))
 		return PTR_ERR(rpcb_clnt);
 
 	status = rpc_call_sync(rpcb_clnt, &msg, 0);
+	rpc_shutdown_client(rpcb_clnt);
 
 	if (status >= 0) {
 		if (map.r_port != 0)
@@ -294,16 +297,16 @@
 	}
 	return status;
 }
-#endif
+EXPORT_SYMBOL_GPL(rpcb_getport_sync);
 
 /**
- * rpcb_getport - obtain the port for a given RPC service on a given host
+ * rpcb_getport_async - obtain the port for a given RPC service on a given host
  * @task: task that is waiting for portmapper request
  *
  * This one can be called for an ongoing RPC request, and can be used in
  * an async (rpciod) context.
  */
-void rpcb_getport(struct rpc_task *task)
+void rpcb_getport_async(struct rpc_task *task)
 {
 	struct rpc_clnt *clnt = task->tk_client;
 	int bind_version;
@@ -314,17 +317,17 @@
 	struct sockaddr addr;
 	int status;
 
-	dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d)\n",
-			task->tk_pid, clnt->cl_server,
-			clnt->cl_prog, clnt->cl_vers, xprt->prot);
+	dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
+		task->tk_pid, __FUNCTION__,
+		clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
 
 	/* Autobind on cloned rpc clients is discouraged */
 	BUG_ON(clnt->cl_parent != clnt);
 
 	if (xprt_test_and_set_binding(xprt)) {
 		status = -EACCES;		/* tell caller to check again */
-		dprintk("RPC: %5u rpcb_getport waiting for another binder\n",
-				task->tk_pid);
+		dprintk("RPC: %5u %s: waiting for another binder\n",
+			task->tk_pid, __FUNCTION__);
 		goto bailout_nowake;
 	}
 
@@ -335,27 +338,28 @@
 	/* Someone else may have bound if we slept */
 	if (xprt_bound(xprt)) {
 		status = 0;
-		dprintk("RPC: %5u rpcb_getport already bound\n", task->tk_pid);
+		dprintk("RPC: %5u %s: already bound\n",
+			task->tk_pid, __FUNCTION__);
 		goto bailout_nofree;
 	}
 
 	if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) {
 		xprt->bind_index = 0;
 		status = -EACCES;	/* tell caller to try again later */
-		dprintk("RPC: %5u rpcb_getport no more getport versions "
-				"available\n", task->tk_pid);
+		dprintk("RPC: %5u %s: no more getport versions available\n",
+			task->tk_pid, __FUNCTION__);
 		goto bailout_nofree;
 	}
 	bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
 
-	dprintk("RPC: %5u rpcb_getport trying rpcbind version %u\n",
-			task->tk_pid, bind_version);
+	dprintk("RPC: %5u %s: trying rpcbind version %u\n",
+		task->tk_pid, __FUNCTION__, bind_version);
 
 	map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
 	if (!map) {
 		status = -ENOMEM;
-		dprintk("RPC: %5u rpcb_getport no memory available\n",
-				task->tk_pid);
+		dprintk("RPC: %5u %s: no memory available\n",
+			task->tk_pid, __FUNCTION__);
 		goto bailout_nofree;
 	}
 	map->r_prog = clnt->cl_prog;
@@ -373,16 +377,17 @@
 	rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
 	if (IS_ERR(rpcb_clnt)) {
 		status = PTR_ERR(rpcb_clnt);
-		dprintk("RPC: %5u rpcb_getport rpcb_create failed, error %ld\n",
-				task->tk_pid, PTR_ERR(rpcb_clnt));
+		dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
+			task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
 		goto bailout;
 	}
 
 	child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
+	rpc_release_client(rpcb_clnt);
 	if (IS_ERR(child)) {
 		status = -EIO;
-		dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n",
-				task->tk_pid);
+		dprintk("RPC: %5u %s: rpc_run_task failed\n",
+			task->tk_pid, __FUNCTION__);
 		goto bailout_nofree;
 	}
 	rpc_put_task(child);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 944d753..2ac43c4 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -25,7 +25,6 @@
 #ifdef RPC_DEBUG
 #define RPCDBG_FACILITY		RPCDBG_SCHED
 #define RPC_TASK_MAGIC_ID	0xf00baa
-static int			rpc_task_id;
 #endif
 
 /*
@@ -40,7 +39,6 @@
 static mempool_t	*rpc_buffer_mempool __read_mostly;
 
 static void			__rpc_default_timer(struct rpc_task *task);
-static void			rpciod_killall(void);
 static void			rpc_async_schedule(struct work_struct *);
 static void			 rpc_release_task(struct rpc_task *task);
 
@@ -50,23 +48,13 @@
 static RPC_WAITQ(delay_queue, "delayq");
 
 /*
- * All RPC tasks are linked into this list
- */
-static LIST_HEAD(all_tasks);
-
-/*
  * rpciod-related stuff
  */
 static DEFINE_MUTEX(rpciod_mutex);
-static unsigned int		rpciod_users;
+static atomic_t rpciod_users = ATOMIC_INIT(0);
 struct workqueue_struct *rpciod_workqueue;
 
 /*
- * Spinlock for other critical sections of code.
- */
-static DEFINE_SPINLOCK(rpc_sched_lock);
-
-/*
  * Disable the timer for a given RPC task. Should be called with
  * queue->lock and bh_disabled in order to avoid races within
  * rpc_run_timer().
@@ -267,18 +255,33 @@
 	return 0;
 }
 
+#ifdef RPC_DEBUG
+static void rpc_task_set_debuginfo(struct rpc_task *task)
+{
+	static atomic_t rpc_pid;
+
+	task->tk_magic = RPC_TASK_MAGIC_ID;
+	task->tk_pid = atomic_inc_return(&rpc_pid);
+}
+#else
+static inline void rpc_task_set_debuginfo(struct rpc_task *task)
+{
+}
+#endif
+
 static void rpc_set_active(struct rpc_task *task)
 {
+	struct rpc_clnt *clnt;
 	if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0)
 		return;
-	spin_lock(&rpc_sched_lock);
-#ifdef RPC_DEBUG
-	task->tk_magic = RPC_TASK_MAGIC_ID;
-	task->tk_pid = rpc_task_id++;
-#endif
+	rpc_task_set_debuginfo(task);
 	/* Add to global list of all tasks */
-	list_add_tail(&task->tk_task, &all_tasks);
-	spin_unlock(&rpc_sched_lock);
+	clnt = task->tk_client;
+	if (clnt != NULL) {
+		spin_lock(&clnt->cl_lock);
+		list_add_tail(&task->tk_task, &clnt->cl_tasks);
+		spin_unlock(&clnt->cl_lock);
+	}
 }
 
 /*
@@ -818,6 +821,7 @@
 	if (tk_ops->rpc_call_prepare != NULL)
 		task->tk_action = rpc_prepare_task;
 	task->tk_calldata = calldata;
+	INIT_LIST_HEAD(&task->tk_task);
 
 	/* Initialize retry counters */
 	task->tk_garb_retry = 2;
@@ -830,7 +834,7 @@
 	task->tk_workqueue = rpciod_workqueue;
 
 	if (clnt) {
-		atomic_inc(&clnt->cl_users);
+		kref_get(&clnt->cl_kref);
 		if (clnt->cl_softrtry)
 			task->tk_flags |= RPC_TASK_SOFT;
 		if (!clnt->cl_intr)
@@ -860,9 +864,7 @@
 }
 
 /*
- * Create a new task for the specified client.  We have to
- * clean up after an allocation failure, as the client may
- * have specified "oneshot".
+ * Create a new task for the specified client.
  */
 struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
 {
@@ -870,7 +872,7 @@
 
 	task = rpc_alloc_task();
 	if (!task)
-		goto cleanup;
+		goto out;
 
 	rpc_init_task(task, clnt, flags, tk_ops, calldata);
 
@@ -878,16 +880,6 @@
 	task->tk_flags |= RPC_TASK_DYNAMIC;
 out:
 	return task;
-
-cleanup:
-	/* Check whether to release the client */
-	if (clnt) {
-		printk("rpc_new_task: failed, users=%d, oneshot=%d\n",
-			atomic_read(&clnt->cl_users), clnt->cl_oneshot);
-		atomic_inc(&clnt->cl_users); /* pretend we were used ... */
-		rpc_release_client(clnt);
-	}
-	goto out;
 }
 
 
@@ -920,11 +912,13 @@
 #endif
 	dprintk("RPC: %5u release task\n", task->tk_pid);
 
-	/* Remove from global task list */
-	spin_lock(&rpc_sched_lock);
-	list_del(&task->tk_task);
-	spin_unlock(&rpc_sched_lock);
-
+	if (!list_empty(&task->tk_task)) {
+		struct rpc_clnt *clnt = task->tk_client;
+		/* Remove from client task list */
+		spin_lock(&clnt->cl_lock);
+		list_del(&task->tk_task);
+		spin_unlock(&clnt->cl_lock);
+	}
 	BUG_ON (RPC_IS_QUEUED(task));
 
 	/* Synchronously delete any running timer */
@@ -939,29 +933,6 @@
 	rpc_put_task(task);
 }
 
-/**
- * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
- * @clnt: pointer to RPC client
- * @flags: RPC flags
- * @ops: RPC call ops
- * @data: user call data
- */
-struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
-					const struct rpc_call_ops *ops,
-					void *data)
-{
-	struct rpc_task *task;
-	task = rpc_new_task(clnt, flags, ops, data);
-	if (task == NULL) {
-		rpc_release_calldata(ops, data);
-		return ERR_PTR(-ENOMEM);
-	}
-	atomic_inc(&task->tk_count);
-	rpc_execute(task);
-	return task;
-}
-EXPORT_SYMBOL(rpc_run_task);
-
 /*
  * Kill all tasks for the given client.
  * XXX: kill their descendants as well?
@@ -969,44 +940,25 @@
 void rpc_killall_tasks(struct rpc_clnt *clnt)
 {
 	struct rpc_task	*rovr;
-	struct list_head *le;
 
+
+	if (list_empty(&clnt->cl_tasks))
+		return;
 	dprintk("RPC:       killing all tasks for client %p\n", clnt);
-
 	/*
 	 * Spin lock all_tasks to prevent changes...
 	 */
-	spin_lock(&rpc_sched_lock);
-	alltask_for_each(rovr, le, &all_tasks) {
+	spin_lock(&clnt->cl_lock);
+	list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) {
 		if (! RPC_IS_ACTIVATED(rovr))
 			continue;
-		if (!clnt || rovr->tk_client == clnt) {
+		if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
 			rovr->tk_flags |= RPC_TASK_KILLED;
 			rpc_exit(rovr, -EIO);
 			rpc_wake_up_task(rovr);
 		}
 	}
-	spin_unlock(&rpc_sched_lock);
-}
-
-static void rpciod_killall(void)
-{
-	unsigned long flags;
-
-	while (!list_empty(&all_tasks)) {
-		clear_thread_flag(TIF_SIGPENDING);
-		rpc_killall_tasks(NULL);
-		flush_workqueue(rpciod_workqueue);
-		if (!list_empty(&all_tasks)) {
-			dprintk("RPC:       rpciod_killall: waiting for tasks "
-					"to exit\n");
-			yield();
-		}
-	}
-
-	spin_lock_irqsave(&current->sighand->siglock, flags);
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	spin_unlock(&clnt->cl_lock);
 }
 
 /*
@@ -1018,28 +970,27 @@
 	struct workqueue_struct *wq;
 	int error = 0;
 
+	if (atomic_inc_not_zero(&rpciod_users))
+		return 0;
+
 	mutex_lock(&rpciod_mutex);
-	dprintk("RPC:       rpciod_up: users %u\n", rpciod_users);
-	rpciod_users++;
-	if (rpciod_workqueue)
-		goto out;
-	/*
-	 * If there's no pid, we should be the first user.
-	 */
-	if (rpciod_users > 1)
-		printk(KERN_WARNING "rpciod_up: no workqueue, %u users??\n", rpciod_users);
+
+	/* Guard against races with rpciod_down() */
+	if (rpciod_workqueue != NULL)
+		goto out_ok;
 	/*
 	 * Create the rpciod thread and wait for it to start.
 	 */
+	dprintk("RPC:       creating workqueue rpciod\n");
 	error = -ENOMEM;
 	wq = create_workqueue("rpciod");
-	if (wq == NULL) {
-		printk(KERN_WARNING "rpciod_up: create workqueue failed, error=%d\n", error);
-		rpciod_users--;
+	if (wq == NULL)
 		goto out;
-	}
+
 	rpciod_workqueue = wq;
 	error = 0;
+out_ok:
+	atomic_inc(&rpciod_users);
 out:
 	mutex_unlock(&rpciod_mutex);
 	return error;
@@ -1048,59 +999,19 @@
 void
 rpciod_down(void)
 {
+	if (!atomic_dec_and_test(&rpciod_users))
+		return;
+
 	mutex_lock(&rpciod_mutex);
-	dprintk("RPC:       rpciod_down sema %u\n", rpciod_users);
-	if (rpciod_users) {
-		if (--rpciod_users)
-			goto out;
-	} else
-		printk(KERN_WARNING "rpciod_down: no users??\n");
+	dprintk("RPC:       destroying workqueue rpciod\n");
 
-	if (!rpciod_workqueue) {
-		dprintk("RPC:       rpciod_down: Nothing to do!\n");
-		goto out;
+	if (atomic_read(&rpciod_users) == 0 && rpciod_workqueue != NULL) {
+		destroy_workqueue(rpciod_workqueue);
+		rpciod_workqueue = NULL;
 	}
-	rpciod_killall();
-
-	destroy_workqueue(rpciod_workqueue);
-	rpciod_workqueue = NULL;
- out:
 	mutex_unlock(&rpciod_mutex);
 }
 
-#ifdef RPC_DEBUG
-void rpc_show_tasks(void)
-{
-	struct list_head *le;
-	struct rpc_task *t;
-
-	spin_lock(&rpc_sched_lock);
-	if (list_empty(&all_tasks)) {
-		spin_unlock(&rpc_sched_lock);
-		return;
-	}
-	printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
-		"-rpcwait -action- ---ops--\n");
-	alltask_for_each(t, le, &all_tasks) {
-		const char *rpc_waitq = "none";
-
-		if (RPC_IS_QUEUED(t))
-			rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
-
-		printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
-			t->tk_pid,
-			(t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
-			t->tk_flags, t->tk_status,
-			t->tk_client,
-			(t->tk_client ? t->tk_client->cl_prog : 0),
-			t->tk_rqstp, t->tk_timeout,
-			rpc_waitq,
-			t->tk_action, t->tk_ops);
-	}
-	spin_unlock(&rpc_sched_lock);
-}
-#endif
-
 void
 rpc_destroy_mempool(void)
 {
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 73075de..384c4ad 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -28,15 +28,11 @@
 EXPORT_SYMBOL(rpc_sleep_on);
 EXPORT_SYMBOL(rpc_wake_up_next);
 EXPORT_SYMBOL(rpc_wake_up_task);
-EXPORT_SYMBOL(rpciod_down);
-EXPORT_SYMBOL(rpciod_up);
-EXPORT_SYMBOL(rpc_new_task);
 EXPORT_SYMBOL(rpc_wake_up_status);
 
 /* RPC client functions */
 EXPORT_SYMBOL(rpc_clone_client);
 EXPORT_SYMBOL(rpc_bind_new_program);
-EXPORT_SYMBOL(rpc_destroy_client);
 EXPORT_SYMBOL(rpc_shutdown_client);
 EXPORT_SYMBOL(rpc_killall_tasks);
 EXPORT_SYMBOL(rpc_call_sync);
@@ -61,7 +57,7 @@
 EXPORT_SYMBOL(rpcauth_create);
 EXPORT_SYMBOL(rpcauth_lookupcred);
 EXPORT_SYMBOL(rpcauth_lookup_credcache);
-EXPORT_SYMBOL(rpcauth_free_credcache);
+EXPORT_SYMBOL(rpcauth_destroy_credcache);
 EXPORT_SYMBOL(rpcauth_init_credcache);
 EXPORT_SYMBOL(put_rpccred);
 
@@ -156,6 +152,7 @@
 	cache_register(&ip_map_cache);
 	cache_register(&unix_gid_cache);
 	init_socket_xprt();
+	rpcauth_init_module();
 out:
 	return err;
 }
@@ -163,6 +160,7 @@
 static void __exit
 cleanup_sunrpc(void)
 {
+	rpcauth_remove_module();
 	cleanup_socket_xprt();
 	unregister_rpc_pipefs();
 	rpc_destroy_mempool();
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e673ef9..55ea6df 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -814,7 +814,7 @@
 	rqstp->rq_res.tail[0].iov_base = NULL;
 	rqstp->rq_res.tail[0].iov_len = 0;
 	/* Will be turned off only in gss privacy case: */
-	rqstp->rq_sendfile_ok = 1;
+	rqstp->rq_splice_ok = 1;
 	/* tcp needs a space for the record length... */
 	if (rqstp->rq_prot == IPPROTO_TCP)
 		svc_putnl(resv, 0);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 07dcd20..41147941 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -5,6 +5,7 @@
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/svcauth.h>
+#include <linux/sunrpc/gss_api.h>
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/hash.h>
@@ -637,7 +638,7 @@
 	}
 }
 
-static int
+int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
 	struct sockaddr_in *sin = svc_addr_in(rqstp);
@@ -672,6 +673,8 @@
 	return SVC_OK;
 }
 
+EXPORT_SYMBOL(svcauth_unix_set_client);
+
 static int
 svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
@@ -707,6 +710,7 @@
 	svc_putnl(resv, RPC_AUTH_NULL);
 	svc_putnl(resv, 0);
 
+	rqstp->rq_flavor = RPC_AUTH_NULL;
 	return SVC_OK;
 }
 
@@ -784,6 +788,7 @@
 	svc_putnl(resv, RPC_AUTH_NULL);
 	svc_putnl(resv, 0);
 
+	rqstp->rq_flavor = RPC_AUTH_UNIX;
 	return SVC_OK;
 
 badcred:
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 5baf48d..64b9b8c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -644,6 +644,7 @@
 	struct msghdr msg = {
 		.msg_flags	= MSG_DONTWAIT,
 	};
+	struct sockaddr *sin;
 	int len;
 
 	len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
@@ -654,6 +655,19 @@
 	memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
 	rqstp->rq_addrlen = svsk->sk_remotelen;
 
+	/* Destination address in request is needed for binding the
+	 * source address in RPC callbacks later.
+	 */
+	sin = (struct sockaddr *)&svsk->sk_local;
+	switch (sin->sa_family) {
+	case AF_INET:
+		rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
+		break;
+	case AF_INET6:
+		rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
+		break;
+	}
+
 	dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
 		svsk, iov[0].iov_base, iov[0].iov_len, len);
 
@@ -1064,6 +1078,12 @@
 		goto failed;
 	memcpy(&newsvsk->sk_remote, sin, slen);
 	newsvsk->sk_remotelen = slen;
+	err = kernel_getsockname(newsock, sin, &slen);
+	if (unlikely(err < 0)) {
+		dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err);
+		slen = offsetof(struct sockaddr, sa_data);
+	}
+	memcpy(&newsvsk->sk_local, sin, slen);
 
 	svc_sock_received(newsvsk);
 
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 5b05b73..c8c2edc 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -127,7 +127,7 @@
 		clear_bit(XPRT_LOCKED, &xprt->state);
 		smp_mb__after_clear_bit();
 	} else
-		schedule_work(&xprt->task_cleanup);
+		queue_work(rpciod_workqueue, &xprt->task_cleanup);
 }
 
 /*
@@ -515,7 +515,7 @@
 	if (xprt_connecting(xprt))
 		xprt_release_write(xprt, NULL);
 	else
-		schedule_work(&xprt->task_cleanup);
+		queue_work(rpciod_workqueue, &xprt->task_cleanup);
 	return;
 out_abort:
 	spin_unlock(&xprt->transport_lock);
@@ -886,27 +886,24 @@
 
 /**
  * xprt_create_transport - create an RPC transport
- * @proto: requested transport protocol
- * @ap: remote peer address
- * @size: length of address
- * @to: timeout parameters
+ * @args: rpc transport creation arguments
  *
  */
-struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to)
+struct rpc_xprt *xprt_create_transport(struct rpc_xprtsock_create *args)
 {
 	struct rpc_xprt	*xprt;
 	struct rpc_rqst	*req;
 
-	switch (proto) {
+	switch (args->proto) {
 	case IPPROTO_UDP:
-		xprt = xs_setup_udp(ap, size, to);
+		xprt = xs_setup_udp(args);
 		break;
 	case IPPROTO_TCP:
-		xprt = xs_setup_tcp(ap, size, to);
+		xprt = xs_setup_tcp(args);
 		break;
 	default:
 		printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
-				proto);
+				args->proto);
 		return ERR_PTR(-EIO);
 	}
 	if (IS_ERR(xprt)) {
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index cc33c58..4ae7eed 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -235,6 +235,7 @@
 	 * Connection of transports
 	 */
 	struct delayed_work	connect_worker;
+	struct sockaddr_storage	addr;
 	unsigned short		port;
 
 	/*
@@ -653,8 +654,7 @@
 
 	dprintk("RPC:       xs_destroy xprt %p\n", xprt);
 
-	cancel_delayed_work(&transport->connect_worker);
-	flush_scheduled_work();
+	cancel_rearming_delayed_work(&transport->connect_worker);
 
 	xprt_disconnect(xprt);
 	xs_close(xprt);
@@ -1001,7 +1001,7 @@
 		/* Try to schedule an autoclose RPC calls */
 		set_bit(XPRT_CLOSE_WAIT, &xprt->state);
 		if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
-			schedule_work(&xprt->task_cleanup);
+			queue_work(rpciod_workqueue, &xprt->task_cleanup);
 	default:
 		xprt_disconnect(xprt);
 	}
@@ -1146,31 +1146,36 @@
 	sap->sin_port = htons(port);
 }
 
-static int xs_bindresvport(struct sock_xprt *transport, struct socket *sock)
+static int xs_bind(struct sock_xprt *transport, struct socket *sock)
 {
 	struct sockaddr_in myaddr = {
 		.sin_family = AF_INET,
 	};
+	struct sockaddr_in *sa;
 	int err;
 	unsigned short port = transport->port;
 
+	if (!transport->xprt.resvport)
+		port = 0;
+	sa = (struct sockaddr_in *)&transport->addr;
+	myaddr.sin_addr = sa->sin_addr;
 	do {
 		myaddr.sin_port = htons(port);
 		err = kernel_bind(sock, (struct sockaddr *) &myaddr,
 						sizeof(myaddr));
+		if (!transport->xprt.resvport)
+			break;
 		if (err == 0) {
 			transport->port = port;
-			dprintk("RPC:       xs_bindresvport bound to port %u\n",
-					port);
-			return 0;
+			break;
 		}
 		if (port <= xprt_min_resvport)
 			port = xprt_max_resvport;
 		else
 			port--;
 	} while (err == -EADDRINUSE && port != transport->port);
-
-	dprintk("RPC:       can't bind to reserved port (%d).\n", -err);
+	dprintk("RPC:       xs_bind "NIPQUAD_FMT":%u: %s (%d)\n",
+		NIPQUAD(myaddr.sin_addr), port, err ? "failed" : "ok", err);
 	return err;
 }
 
@@ -1229,7 +1234,7 @@
 	}
 	xs_reclassify_socket(sock);
 
-	if (xprt->resvport && xs_bindresvport(transport, sock) < 0) {
+	if (xs_bind(transport, sock)) {
 		sock_release(sock);
 		goto out;
 	}
@@ -1316,7 +1321,7 @@
 		}
 		xs_reclassify_socket(sock);
 
-		if (xprt->resvport && xs_bindresvport(transport, sock) < 0) {
+		if (xs_bind(transport, sock)) {
 			sock_release(sock);
 			goto out;
 		}
@@ -1410,18 +1415,16 @@
 		dprintk("RPC:       xs_connect delayed xprt %p for %lu "
 				"seconds\n",
 				xprt, xprt->reestablish_timeout / HZ);
-		schedule_delayed_work(&transport->connect_worker,
-					xprt->reestablish_timeout);
+		queue_delayed_work(rpciod_workqueue,
+				   &transport->connect_worker,
+				   xprt->reestablish_timeout);
 		xprt->reestablish_timeout <<= 1;
 		if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
 			xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
 	} else {
 		dprintk("RPC:       xs_connect scheduled xprt %p\n", xprt);
-		schedule_delayed_work(&transport->connect_worker, 0);
-
-		/* flush_scheduled_work can sleep... */
-		if (!RPC_IS_ASYNC(task))
-			flush_scheduled_work();
+		queue_delayed_work(rpciod_workqueue,
+				   &transport->connect_worker, 0);
 	}
 }
 
@@ -1476,7 +1479,7 @@
 	.set_buffer_size	= xs_udp_set_buffer_size,
 	.reserve_xprt		= xprt_reserve_xprt_cong,
 	.release_xprt		= xprt_release_xprt_cong,
-	.rpcbind		= rpcb_getport,
+	.rpcbind		= rpcb_getport_async,
 	.set_port		= xs_set_port,
 	.connect		= xs_connect,
 	.buf_alloc		= rpc_malloc,
@@ -1493,7 +1496,7 @@
 static struct rpc_xprt_ops xs_tcp_ops = {
 	.reserve_xprt		= xprt_reserve_xprt,
 	.release_xprt		= xs_tcp_release_xprt,
-	.rpcbind		= rpcb_getport,
+	.rpcbind		= rpcb_getport_async,
 	.set_port		= xs_set_port,
 	.connect		= xs_connect,
 	.buf_alloc		= rpc_malloc,
@@ -1505,12 +1508,12 @@
 	.print_stats		= xs_tcp_print_stats,
 };
 
-static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size)
+static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned int slot_table_size)
 {
 	struct rpc_xprt *xprt;
 	struct sock_xprt *new;
 
-	if (addrlen > sizeof(xprt->addr)) {
+	if (args->addrlen > sizeof(xprt->addr)) {
 		dprintk("RPC:       xs_setup_xprt: address too large\n");
 		return ERR_PTR(-EBADF);
 	}
@@ -1532,8 +1535,10 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memcpy(&xprt->addr, addr, addrlen);
-	xprt->addrlen = addrlen;
+	memcpy(&xprt->addr, args->dstaddr, args->addrlen);
+	xprt->addrlen = args->addrlen;
+	if (args->srcaddr)
+		memcpy(&new->addr, args->srcaddr, args->addrlen);
 	new->port = xs_get_random_port();
 
 	return xprt;
@@ -1541,22 +1546,20 @@
 
 /**
  * xs_setup_udp - Set up transport to use a UDP socket
- * @addr: address of remote server
- * @addrlen: length of address in bytes
- * @to:   timeout parameters
+ * @args: rpc transport creation arguments
  *
  */
-struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args)
 {
 	struct rpc_xprt *xprt;
 	struct sock_xprt *transport;
 
-	xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries);
+	xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries);
 	if (IS_ERR(xprt))
 		return xprt;
 	transport = container_of(xprt, struct sock_xprt, xprt);
 
-	if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
+	if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0)
 		xprt_set_bound(xprt);
 
 	xprt->prot = IPPROTO_UDP;
@@ -1572,8 +1575,8 @@
 
 	xprt->ops = &xs_udp_ops;
 
-	if (to)
-		xprt->timeout = *to;
+	if (args->timeout)
+		xprt->timeout = *args->timeout;
 	else
 		xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
 
@@ -1586,22 +1589,20 @@
 
 /**
  * xs_setup_tcp - Set up transport to use a TCP socket
- * @addr: address of remote server
- * @addrlen: length of address in bytes
- * @to: timeout parameters
+ * @args: rpc transport creation arguments
  *
  */
-struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args)
 {
 	struct rpc_xprt *xprt;
 	struct sock_xprt *transport;
 
-	xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries);
+	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
 	if (IS_ERR(xprt))
 		return xprt;
 	transport = container_of(xprt, struct sock_xprt, xprt);
 
-	if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
+	if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0)
 		xprt_set_bound(xprt);
 
 	xprt->prot = IPPROTO_TCP;
@@ -1616,8 +1617,8 @@
 
 	xprt->ops = &xs_tcp_ops;
 
-	if (to)
-		xprt->timeout = *to;
+	if (args->timeout)
+		xprt->timeout = *args->timeout;
 	else
 		xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
 
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig
index f9e367d..3b30d11 100644
--- a/net/tipc/Kconfig
+++ b/net/tipc/Kconfig
@@ -2,11 +2,9 @@
 # TIPC configuration
 #
 
-menu "TIPC Configuration (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL
-
-config TIPC
+menuconfig TIPC
 	tristate "The TIPC Protocol (EXPERIMENTAL)"
+	depends on INET && EXPERIMENTAL
 	---help---
 	  The Transparent Inter Process Communication (TIPC) protocol is
 	  specially designed for intra cluster communication. This protocol
@@ -22,9 +20,10 @@
 
 	  If in doubt, say N.
 
+if TIPC
+
 config TIPC_ADVANCED
 	bool "TIPC: Advanced configuration"
-	depends on TIPC
 	default n
 	help
 	  Saying Y here will open some advanced configuration
@@ -33,7 +32,7 @@
 
 config TIPC_ZONES
 	int "Maximum number of zones in network"
-	depends on TIPC && TIPC_ADVANCED
+	depends on TIPC_ADVANCED
 	default "3"
 	help
 	 Max number of zones inside TIPC network. Max supported value 
@@ -44,7 +43,7 @@
 
 config TIPC_CLUSTERS
 	int "Maximum number of clusters in a zone"
-	depends on TIPC && TIPC_ADVANCED
+	depends on TIPC_ADVANCED
 	default "1"
 	help
           ***Only 1 (one cluster in a zone) is supported by current code.
@@ -59,7 +58,7 @@
 
 config TIPC_NODES
 	int "Maximum number of nodes in cluster"
-	depends on TIPC && TIPC_ADVANCED
+	depends on TIPC_ADVANCED
 	default "255"
 	help
 	  Maximum number of nodes inside a TIPC cluster. Maximum 
@@ -70,7 +69,7 @@
 
 config TIPC_SLAVE_NODES
 	int "Maximum number of slave nodes in cluster"
-	depends on TIPC && TIPC_ADVANCED
+	depends on TIPC_ADVANCED
 	default "0"
 	help
           ***This capability is not supported by current code.***
@@ -83,7 +82,7 @@
 
 config TIPC_PORTS
 	int "Maximum number of ports in a node"
-	depends on TIPC && TIPC_ADVANCED
+	depends on TIPC_ADVANCED
 	default "8191"
 	help
 	  Maximum number of ports within a node. Maximum 
@@ -94,7 +93,7 @@
 
 config TIPC_LOG
 	int "Size of log buffer"
-	depends on TIPC && TIPC_ADVANCED
+	depends on TIPC_ADVANCED
 	default 0
 	help
  	  Size (in bytes) of TIPC's internal log buffer, which records the
@@ -106,7 +105,6 @@
 
 config TIPC_DEBUG
 	bool "Enable debugging support"
-	depends on TIPC
 	default n
 	help
  	  This will enable debugging of TIPC.
@@ -114,4 +112,4 @@
 	  Only say Y here if you are having trouble with TIPC.  It will
 	  enable the display of detailed information about what is going on.
 
-endmenu
+endif # TIPC
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 0ee6ded..711ca4b 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -1,8 +1,8 @@
 /*
  * net/tipc/eth_media.c: Ethernet bearer support for TIPC
  *
- * Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2001-2007, Ericsson AB
+ * Copyright (c) 2005-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -87,6 +87,9 @@
 /**
  * recv_msg - handle incoming TIPC message from an Ethernet interface
  *
+ * Accept only packets explicitly sent to this node, or broadcast packets;
+ * ignores packets sent using Ethernet multicast, and traffic sent to other
+ * nodes (which can happen if interface is running in promiscuous mode).
  * Routine truncates any Ethernet padding/CRC appended to the message,
  * and ensures message size matches actual length
  */
@@ -98,9 +101,7 @@
 	u32 size;
 
 	if (likely(eb_ptr->bearer)) {
-	       if (likely(!dev->promiscuity) ||
-		   !memcmp(skb_mac_header(buf), dev->dev_addr, ETH_ALEN) ||
-		   !memcmp(skb_mac_header(buf), dev->broadcast, ETH_ALEN)) {
+		if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
 			size = msg_size((struct tipc_msg *)buf->data);
 			skb_trim(buf, size);
 			if (likely(buf->len == size)) {
@@ -120,18 +121,20 @@
 
 static int enable_bearer(struct tipc_bearer *tb_ptr)
 {
-	struct net_device *dev, *pdev;
+	struct net_device *dev = NULL;
+	struct net_device *pdev = NULL;
 	struct eth_bearer *eb_ptr = &eth_bearers[0];
 	struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
 	char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
 
 	/* Find device with specified name */
-	dev = NULL;
-	for_each_netdev(pdev)
-		if (!strncmp(dev->name, driver_name, IFNAMSIZ)) {
+
+	for_each_netdev(pdev){
+		if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) {
 			dev = pdev;
 			break;
 		}
+	}
 	if (!dev)
 		return -ENODEV;
 
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2124f32..5adfdfd 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1,8 +1,8 @@
 /*
  * net/tipc/link.c: TIPC link code
  *
- * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2004-2006, Wind River Systems
+ * Copyright (c) 1996-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1260,7 +1260,7 @@
 	 * (Must not hold any locks while building message.)
 	 */
 
-	res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
+	res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,
 			!sender->user_port, &buf);
 
 	read_lock_bh(&tipc_net_lock);
@@ -1271,7 +1271,7 @@
 		if (likely(l_ptr)) {
 			if (likely(buf)) {
 				res = link_send_buf_fast(l_ptr, buf,
-							 &sender->max_pkt);
+							 &sender->publ.max_pkt);
 				if (unlikely(res < 0))
 					buf_discard(buf);
 exit:
@@ -1299,12 +1299,12 @@
 			 * then re-try fast path or fragment the message
 			 */
 
-			sender->max_pkt = link_max_pkt(l_ptr);
+			sender->publ.max_pkt = link_max_pkt(l_ptr);
 			tipc_node_unlock(node);
 			read_unlock_bh(&tipc_net_lock);
 
 
-			if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
+			if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt)
 				goto again;
 
 			return link_send_sections_long(sender, msg_sect,
@@ -1357,7 +1357,7 @@
 
 again:
 	fragm_no = 1;
-	max_pkt = sender->max_pkt - INT_H_SIZE;
+	max_pkt = sender->publ.max_pkt - INT_H_SIZE;
 		/* leave room for tunnel header in case of link changeover */
 	fragm_sz = max_pkt - INT_H_SIZE;
 		/* leave room for fragmentation header in each fragment */
@@ -1463,7 +1463,7 @@
 			goto reject;
 		}
 		if (link_max_pkt(l_ptr) < max_pkt) {
-			sender->max_pkt = link_max_pkt(l_ptr);
+			sender->publ.max_pkt = link_max_pkt(l_ptr);
 			tipc_node_unlock(node);
 			for (; buf_chain; buf_chain = buf) {
 				buf = buf_chain->next;
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 4cdafa2..6a7f7b4 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -60,7 +60,7 @@
 		rep_nlh = nlmsg_hdr(rep_buf);
 		memcpy(rep_nlh, req_nlh, hdr_space);
 		rep_nlh->nlmsg_len = rep_buf->len;
-		genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid);
+		genlmsg_unicast(rep_buf, NETLINK_CB(skb).pid);
 	}
 
 	return 0;
diff --git a/net/tipc/port.c b/net/tipc/port.c
index bcd5da0..5d2b9ce 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -1,8 +1,8 @@
 /*
  * net/tipc/port.c: TIPC port code
  *
- * Copyright (c) 1992-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 1992-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -239,6 +239,8 @@
 	}
 
 	tipc_port_lock(ref);
+	p_ptr->publ.usr_handle = usr_handle;
+	p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
 	p_ptr->publ.ref = ref;
 	msg = &p_ptr->publ.phdr;
 	msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
@@ -248,11 +250,9 @@
 	msg_set_importance(msg,importance);
 	p_ptr->last_in_seqno = 41;
 	p_ptr->sent = 1;
-	p_ptr->publ.usr_handle = usr_handle;
 	INIT_LIST_HEAD(&p_ptr->wait_list);
 	INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
 	p_ptr->congested_link = NULL;
-	p_ptr->max_pkt = MAX_PKT_DEFAULT;
 	p_ptr->dispatcher = dispatcher;
 	p_ptr->wakeup = wakeup;
 	p_ptr->user_port = NULL;
@@ -1243,7 +1243,7 @@
 	res = TIPC_OK;
 exit:
 	tipc_port_unlock(p_ptr);
-	p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
+	p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref);
 	return res;
 }
 
diff --git a/net/tipc/port.h b/net/tipc/port.h
index 7ef4d64..e5f8c16 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -1,8 +1,8 @@
 /*
  * net/tipc/port.h: Include file for TIPC port code
  *
- * Copyright (c) 1994-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 1994-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,6 @@
  * @acked:
  * @publications: list of publications for port
  * @pub_count: total # of publications port has made during its lifetime
- * @max_pkt: maximum packet size "hint" used when building messages sent by port
  * @probing_state:
  * @probing_interval:
  * @last_in_seqno:
@@ -102,7 +101,6 @@
 	u32 acked;
 	struct list_head publications;
 	u32 pub_count;
-	u32 max_pkt;
 	u32 probing_state;
 	u32 probing_interval;
 	u32 last_in_seqno;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 45832fb..4a8f37f 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1,8 +1,8 @@
 /*
  * net/tipc/socket.c: TIPC socket API
  *
- * Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2004-2006, Wind River Systems
+ * Copyright (c) 2001-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -607,23 +607,24 @@
 static int send_stream(struct kiocb *iocb, struct socket *sock,
 		       struct msghdr *m, size_t total_len)
 {
+	struct tipc_port *tport;
 	struct msghdr my_msg;
 	struct iovec my_iov;
 	struct iovec *curr_iov;
 	int curr_iovlen;
 	char __user *curr_start;
+	u32 hdr_size;
 	int curr_left;
 	int bytes_to_send;
 	int bytes_sent;
 	int res;
 
-	if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
-		return send_packet(iocb, sock, m, total_len);
-
-	/* Can only send large data streams if already connected */
+	/* Handle special cases where there is no connection */
 
 	if (unlikely(sock->state != SS_CONNECTED)) {
-		if (sock->state == SS_DISCONNECTING)
+		if (sock->state == SS_UNCONNECTED)
+			return send_packet(iocb, sock, m, total_len);
+		else if (sock->state == SS_DISCONNECTING)
 			return -EPIPE;
 		else
 			return -ENOTCONN;
@@ -648,17 +649,25 @@
 	my_msg.msg_name = NULL;
 	bytes_sent = 0;
 
+	tport = tipc_sk(sock->sk)->p;
+	hdr_size = msg_hdr_sz(&tport->phdr);
+
 	while (curr_iovlen--) {
 		curr_start = curr_iov->iov_base;
 		curr_left = curr_iov->iov_len;
 
 		while (curr_left) {
-			bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE)
-				? curr_left : TIPC_MAX_USER_MSG_SIZE;
+			bytes_to_send = tport->max_pkt - hdr_size;
+			if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE)
+				bytes_to_send = TIPC_MAX_USER_MSG_SIZE;
+			if (curr_left < bytes_to_send)
+				bytes_to_send = curr_left;
 			my_iov.iov_base = curr_start;
 			my_iov.iov_len = bytes_to_send;
 			if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
-				return bytes_sent ? bytes_sent : res;
+				if (bytes_sent != 0)
+					res = bytes_sent;
+				return res;
 			}
 			curr_left -= bytes_to_send;
 			curr_start += bytes_to_send;
@@ -1600,33 +1609,6 @@
 }
 
 /**
- * Placeholders for non-implemented functionality
- *
- * Returns error code (POSIX-compliant where defined)
- */
-
-static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
-{
-	return -EINVAL;
-}
-
-static int no_mmap(struct file *file, struct socket *sock,
-		   struct vm_area_struct *vma)
-{
-	return -EINVAL;
-}
-static ssize_t no_sendpage(struct socket *sock, struct page *page,
-			   int offset, size_t size, int flags)
-{
-	return -EINVAL;
-}
-
-static int no_skpair(struct socket *s1, struct socket *s2)
-{
-	return -EOPNOTSUPP;
-}
-
-/**
  * Protocol switches for the various types of TIPC sockets
  */
 
@@ -1636,19 +1618,19 @@
 	.release	= release,
 	.bind		= bind,
 	.connect	= connect,
-	.socketpair	= no_skpair,
+	.socketpair	= sock_no_socketpair,
 	.accept		= accept,
 	.getname	= get_name,
 	.poll		= poll,
-	.ioctl		= ioctl,
+	.ioctl		= sock_no_ioctl,
 	.listen		= listen,
 	.shutdown	= shutdown,
 	.setsockopt	= setsockopt,
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_msg,
 	.recvmsg	= recv_msg,
-	.mmap		= no_mmap,
-	.sendpage	= no_sendpage
+        .mmap		= sock_no_mmap,
+        .sendpage	= sock_no_sendpage
 };
 
 static struct proto_ops packet_ops = {
@@ -1657,19 +1639,19 @@
 	.release	= release,
 	.bind		= bind,
 	.connect	= connect,
-	.socketpair	= no_skpair,
+	.socketpair	= sock_no_socketpair,
 	.accept		= accept,
 	.getname	= get_name,
 	.poll		= poll,
-	.ioctl		= ioctl,
+	.ioctl		= sock_no_ioctl,
 	.listen		= listen,
 	.shutdown	= shutdown,
 	.setsockopt	= setsockopt,
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_packet,
 	.recvmsg	= recv_msg,
-	.mmap		= no_mmap,
-	.sendpage	= no_sendpage
+        .mmap		= sock_no_mmap,
+        .sendpage	= sock_no_sendpage
 };
 
 static struct proto_ops stream_ops = {
@@ -1678,19 +1660,19 @@
 	.release	= release,
 	.bind		= bind,
 	.connect	= connect,
-	.socketpair	= no_skpair,
+	.socketpair	= sock_no_socketpair,
 	.accept		= accept,
 	.getname	= get_name,
 	.poll		= poll,
-	.ioctl		= ioctl,
+	.ioctl		= sock_no_ioctl,
 	.listen		= listen,
 	.shutdown	= shutdown,
 	.setsockopt	= setsockopt,
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_stream,
 	.recvmsg	= recv_stream,
-	.mmap		= no_mmap,
-	.sendpage	= no_sendpage
+        .mmap		= sock_no_mmap,
+        .sendpage	= sock_no_sendpage
 };
 
 static struct net_proto_family tipc_family_ops = {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index fc12ba5..65ebccc 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -174,11 +174,11 @@
 {
 	struct sock *peer;
 
-	unix_state_rlock(s);
+	unix_state_lock(s);
 	peer = unix_peer(s);
 	if (peer)
 		sock_hold(peer);
-	unix_state_runlock(s);
+	unix_state_unlock(s);
 	return peer;
 }
 
@@ -369,7 +369,7 @@
 	unix_remove_socket(sk);
 
 	/* Clear state */
-	unix_state_wlock(sk);
+	unix_state_lock(sk);
 	sock_orphan(sk);
 	sk->sk_shutdown = SHUTDOWN_MASK;
 	dentry	     = u->dentry;
@@ -378,7 +378,7 @@
 	u->mnt	     = NULL;
 	state = sk->sk_state;
 	sk->sk_state = TCP_CLOSE;
-	unix_state_wunlock(sk);
+	unix_state_unlock(sk);
 
 	wake_up_interruptible_all(&u->peer_wait);
 
@@ -386,12 +386,12 @@
 
 	if (skpair!=NULL) {
 		if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
-			unix_state_wlock(skpair);
+			unix_state_lock(skpair);
 			/* No more writes */
 			skpair->sk_shutdown = SHUTDOWN_MASK;
 			if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
 				skpair->sk_err = ECONNRESET;
-			unix_state_wunlock(skpair);
+			unix_state_unlock(skpair);
 			skpair->sk_state_change(skpair);
 			read_lock(&skpair->sk_callback_lock);
 			sk_wake_async(skpair,1,POLL_HUP);
@@ -448,7 +448,7 @@
 	err = -EINVAL;
 	if (!u->addr)
 		goto out;			/* No listens on an unbound socket */
-	unix_state_wlock(sk);
+	unix_state_lock(sk);
 	if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
 		goto out_unlock;
 	if (backlog > sk->sk_max_ack_backlog)
@@ -462,7 +462,7 @@
 	err = 0;
 
 out_unlock:
-	unix_state_wunlock(sk);
+	unix_state_unlock(sk);
 out:
 	return err;
 }
@@ -592,7 +592,8 @@
 	u->dentry = NULL;
 	u->mnt	  = NULL;
 	spin_lock_init(&u->lock);
-	atomic_set(&u->inflight, sock ? 0 : -1);
+	atomic_set(&u->inflight, 0);
+	INIT_LIST_HEAD(&u->link);
 	mutex_init(&u->readlock); /* single task reading lock */
 	init_waitqueue_head(&u->peer_wait);
 	unix_insert_socket(unix_sockets_unbound, sk);
@@ -858,6 +859,31 @@
 	goto out_up;
 }
 
+static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
+{
+	if (unlikely(sk1 == sk2) || !sk2) {
+		unix_state_lock(sk1);
+		return;
+	}
+	if (sk1 < sk2) {
+		unix_state_lock(sk1);
+		unix_state_lock_nested(sk2);
+	} else {
+		unix_state_lock(sk2);
+		unix_state_lock_nested(sk1);
+	}
+}
+
+static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
+{
+	if (unlikely(sk1 == sk2) || !sk2) {
+		unix_state_unlock(sk1);
+		return;
+	}
+	unix_state_unlock(sk1);
+	unix_state_unlock(sk2);
+}
+
 static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
 			      int alen, int flags)
 {
@@ -877,11 +903,19 @@
 		    !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
 			goto out;
 
+restart:
 		other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
 		if (!other)
 			goto out;
 
-		unix_state_wlock(sk);
+		unix_state_double_lock(sk, other);
+
+		/* Apparently VFS overslept socket death. Retry. */
+		if (sock_flag(other, SOCK_DEAD)) {
+			unix_state_double_unlock(sk, other);
+			sock_put(other);
+			goto restart;
+		}
 
 		err = -EPERM;
 		if (!unix_may_send(sk, other))
@@ -896,7 +930,7 @@
 		 *	1003.1g breaking connected state with AF_UNSPEC
 		 */
 		other = NULL;
-		unix_state_wlock(sk);
+		unix_state_double_lock(sk, other);
 	}
 
 	/*
@@ -905,19 +939,19 @@
 	if (unix_peer(sk)) {
 		struct sock *old_peer = unix_peer(sk);
 		unix_peer(sk)=other;
-		unix_state_wunlock(sk);
+		unix_state_double_unlock(sk, other);
 
 		if (other != old_peer)
 			unix_dgram_disconnected(sk, old_peer);
 		sock_put(old_peer);
 	} else {
 		unix_peer(sk)=other;
-		unix_state_wunlock(sk);
+		unix_state_double_unlock(sk, other);
 	}
 	return 0;
 
 out_unlock:
-	unix_state_wunlock(sk);
+	unix_state_double_unlock(sk, other);
 	sock_put(other);
 out:
 	return err;
@@ -936,7 +970,7 @@
 		(skb_queue_len(&other->sk_receive_queue) >
 		 other->sk_max_ack_backlog);
 
-	unix_state_runlock(other);
+	unix_state_unlock(other);
 
 	if (sched)
 		timeo = schedule_timeout(timeo);
@@ -994,11 +1028,11 @@
 		goto out;
 
 	/* Latch state of peer */
-	unix_state_rlock(other);
+	unix_state_lock(other);
 
 	/* Apparently VFS overslept socket death. Retry. */
 	if (sock_flag(other, SOCK_DEAD)) {
-		unix_state_runlock(other);
+		unix_state_unlock(other);
 		sock_put(other);
 		goto restart;
 	}
@@ -1048,18 +1082,18 @@
 		goto out_unlock;
 	}
 
-	unix_state_wlock_nested(sk);
+	unix_state_lock_nested(sk);
 
 	if (sk->sk_state != st) {
-		unix_state_wunlock(sk);
-		unix_state_runlock(other);
+		unix_state_unlock(sk);
+		unix_state_unlock(other);
 		sock_put(other);
 		goto restart;
 	}
 
 	err = security_unix_stream_connect(sock, other->sk_socket, newsk);
 	if (err) {
-		unix_state_wunlock(sk);
+		unix_state_unlock(sk);
 		goto out_unlock;
 	}
 
@@ -1096,23 +1130,20 @@
 	smp_mb__after_atomic_inc();	/* sock_hold() does an atomic_inc() */
 	unix_peer(sk)	= newsk;
 
-	unix_state_wunlock(sk);
+	unix_state_unlock(sk);
 
 	/* take ten and and send info to listening sock */
 	spin_lock(&other->sk_receive_queue.lock);
 	__skb_queue_tail(&other->sk_receive_queue, skb);
-	/* Undo artificially decreased inflight after embrion
-	 * is installed to listening socket. */
-	atomic_inc(&newu->inflight);
 	spin_unlock(&other->sk_receive_queue.lock);
-	unix_state_runlock(other);
+	unix_state_unlock(other);
 	other->sk_data_ready(other, 0);
 	sock_put(other);
 	return 0;
 
 out_unlock:
 	if (other)
-		unix_state_runlock(other);
+		unix_state_unlock(other);
 
 out:
 	if (skb)
@@ -1178,10 +1209,10 @@
 	wake_up_interruptible(&unix_sk(sk)->peer_wait);
 
 	/* attach accepted sock to socket */
-	unix_state_wlock(tsk);
+	unix_state_lock(tsk);
 	newsock->state = SS_CONNECTED;
 	sock_graft(tsk, newsock);
-	unix_state_wunlock(tsk);
+	unix_state_unlock(tsk);
 	return 0;
 
 out:
@@ -1208,7 +1239,7 @@
 	}
 
 	u = unix_sk(sk);
-	unix_state_rlock(sk);
+	unix_state_lock(sk);
 	if (!u->addr) {
 		sunaddr->sun_family = AF_UNIX;
 		sunaddr->sun_path[0] = 0;
@@ -1219,7 +1250,7 @@
 		*uaddr_len = addr->len;
 		memcpy(sunaddr, addr->name, *uaddr_len);
 	}
-	unix_state_runlock(sk);
+	unix_state_unlock(sk);
 	sock_put(sk);
 out:
 	return err;
@@ -1337,7 +1368,7 @@
 			goto out_free;
 	}
 
-	unix_state_rlock(other);
+	unix_state_lock(other);
 	err = -EPERM;
 	if (!unix_may_send(sk, other))
 		goto out_unlock;
@@ -1347,20 +1378,20 @@
 		 *	Check with 1003.1g - what should
 		 *	datagram error
 		 */
-		unix_state_runlock(other);
+		unix_state_unlock(other);
 		sock_put(other);
 
 		err = 0;
-		unix_state_wlock(sk);
+		unix_state_lock(sk);
 		if (unix_peer(sk) == other) {
 			unix_peer(sk)=NULL;
-			unix_state_wunlock(sk);
+			unix_state_unlock(sk);
 
 			unix_dgram_disconnected(sk, other);
 			sock_put(other);
 			err = -ECONNREFUSED;
 		} else {
-			unix_state_wunlock(sk);
+			unix_state_unlock(sk);
 		}
 
 		other = NULL;
@@ -1397,14 +1428,14 @@
 	}
 
 	skb_queue_tail(&other->sk_receive_queue, skb);
-	unix_state_runlock(other);
+	unix_state_unlock(other);
 	other->sk_data_ready(other, len);
 	sock_put(other);
 	scm_destroy(siocb->scm);
 	return len;
 
 out_unlock:
-	unix_state_runlock(other);
+	unix_state_unlock(other);
 out_free:
 	kfree_skb(skb);
 out:
@@ -1494,14 +1525,14 @@
 			goto out_err;
 		}
 
-		unix_state_rlock(other);
+		unix_state_lock(other);
 
 		if (sock_flag(other, SOCK_DEAD) ||
 		    (other->sk_shutdown & RCV_SHUTDOWN))
 			goto pipe_err_free;
 
 		skb_queue_tail(&other->sk_receive_queue, skb);
-		unix_state_runlock(other);
+		unix_state_unlock(other);
 		other->sk_data_ready(other, size);
 		sent+=size;
 	}
@@ -1512,7 +1543,7 @@
 	return sent;
 
 pipe_err_free:
-	unix_state_runlock(other);
+	unix_state_unlock(other);
 	kfree_skb(skb);
 pipe_err:
 	if (sent==0 && !(msg->msg_flags&MSG_NOSIGNAL))
@@ -1641,7 +1672,7 @@
 {
 	DEFINE_WAIT(wait);
 
-	unix_state_rlock(sk);
+	unix_state_lock(sk);
 
 	for (;;) {
 		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
@@ -1654,14 +1685,14 @@
 			break;
 
 		set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-		unix_state_runlock(sk);
+		unix_state_unlock(sk);
 		timeo = schedule_timeout(timeo);
-		unix_state_rlock(sk);
+		unix_state_lock(sk);
 		clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
 	}
 
 	finish_wait(sk->sk_sleep, &wait);
-	unix_state_runlock(sk);
+	unix_state_unlock(sk);
 	return timeo;
 }
 
@@ -1711,20 +1742,23 @@
 		int chunk;
 		struct sk_buff *skb;
 
+		unix_state_lock(sk);
 		skb = skb_dequeue(&sk->sk_receive_queue);
 		if (skb==NULL)
 		{
 			if (copied >= target)
-				break;
+				goto unlock;
 
 			/*
 			 *	POSIX 1003.1g mandates this order.
 			 */
 
 			if ((err = sock_error(sk)) != 0)
-				break;
+				goto unlock;
 			if (sk->sk_shutdown & RCV_SHUTDOWN)
-				break;
+				goto unlock;
+
+			unix_state_unlock(sk);
 			err = -EAGAIN;
 			if (!timeo)
 				break;
@@ -1738,7 +1772,11 @@
 			}
 			mutex_lock(&u->readlock);
 			continue;
+ unlock:
+			unix_state_unlock(sk);
+			break;
 		}
+		unix_state_unlock(sk);
 
 		if (check_creds) {
 			/* Never glue messages from different writers */
@@ -1816,12 +1854,12 @@
 	mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
 
 	if (mode) {
-		unix_state_wlock(sk);
+		unix_state_lock(sk);
 		sk->sk_shutdown |= mode;
 		other=unix_peer(sk);
 		if (other)
 			sock_hold(other);
-		unix_state_wunlock(sk);
+		unix_state_unlock(sk);
 		sk->sk_state_change(sk);
 
 		if (other &&
@@ -1833,9 +1871,9 @@
 				peer_mode |= SEND_SHUTDOWN;
 			if (mode&SEND_SHUTDOWN)
 				peer_mode |= RCV_SHUTDOWN;
-			unix_state_wlock(other);
+			unix_state_lock(other);
 			other->sk_shutdown |= peer_mode;
-			unix_state_wunlock(other);
+			unix_state_unlock(other);
 			other->sk_state_change(other);
 			read_lock(&other->sk_callback_lock);
 			if (peer_mode == SHUTDOWN_MASK)
@@ -1973,7 +2011,7 @@
 	else {
 		struct sock *s = v;
 		struct unix_sock *u = unix_sk(s);
-		unix_state_rlock(s);
+		unix_state_lock(s);
 
 		seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu",
 			s,
@@ -2001,14 +2039,14 @@
 			for ( ; i < len; i++)
 				seq_putc(seq, u->addr->name->sun_path[i]);
 		}
-		unix_state_runlock(s);
+		unix_state_unlock(s);
 		seq_putc(seq, '\n');
 	}
 
 	return 0;
 }
 
-static struct seq_operations unix_seq_ops = {
+static const struct seq_operations unix_seq_ops = {
 	.start  = unix_seq_start,
 	.next   = unix_seq_next,
 	.stop   = unix_seq_stop,
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index f20b7ea..406b643 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -62,6 +62,10 @@
  *	AV		1 Mar 1999
  *		Damn. Added missing check for ->dead in listen queues scanning.
  *
+ *	Miklos Szeredi 25 Jun 2007
+ *		Reimplement with a cycle collecting algorithm. This should
+ *		solve several problems with the previous code, like being racy
+ *		wrt receive and holding up unrelated socket operations.
  */
 
 #include <linux/kernel.h>
@@ -84,10 +88,9 @@
 
 /* Internal data structures and random procedures: */
 
-#define GC_HEAD		((struct sock *)(-1))
-#define GC_ORPHAN	((struct sock *)(-3))
-
-static struct sock *gc_current = GC_HEAD; /* stack of objects to mark */
+static LIST_HEAD(gc_inflight_list);
+static LIST_HEAD(gc_candidates);
+static DEFINE_SPINLOCK(unix_gc_lock);
 
 atomic_t unix_tot_inflight = ATOMIC_INIT(0);
 
@@ -122,8 +125,16 @@
 {
 	struct sock *s = unix_get_socket(fp);
 	if(s) {
-		atomic_inc(&unix_sk(s)->inflight);
+		struct unix_sock *u = unix_sk(s);
+		spin_lock(&unix_gc_lock);
+		if (atomic_inc_return(&u->inflight) == 1) {
+			BUG_ON(!list_empty(&u->link));
+			list_add_tail(&u->link, &gc_inflight_list);
+		} else {
+			BUG_ON(list_empty(&u->link));
+		}
 		atomic_inc(&unix_tot_inflight);
+		spin_unlock(&unix_gc_lock);
 	}
 }
 
@@ -131,182 +142,218 @@
 {
 	struct sock *s = unix_get_socket(fp);
 	if(s) {
-		atomic_dec(&unix_sk(s)->inflight);
+		struct unix_sock *u = unix_sk(s);
+		spin_lock(&unix_gc_lock);
+		BUG_ON(list_empty(&u->link));
+		if (atomic_dec_and_test(&u->inflight))
+			list_del_init(&u->link);
 		atomic_dec(&unix_tot_inflight);
+		spin_unlock(&unix_gc_lock);
 	}
 }
 
-
-/*
- *	Garbage Collector Support Functions
- */
-
-static inline struct sock *pop_stack(void)
+static inline struct sk_buff *sock_queue_head(struct sock *sk)
 {
-	struct sock *p = gc_current;
-	gc_current = unix_sk(p)->gc_tree;
-	return p;
+	return (struct sk_buff *) &sk->sk_receive_queue;
 }
 
-static inline int empty_stack(void)
+#define receive_queue_for_each_skb(sk, next, skb) \
+	for (skb = sock_queue_head(sk)->next, next = skb->next; \
+	     skb != sock_queue_head(sk); skb = next, next = skb->next)
+
+static void scan_inflight(struct sock *x, void (*func)(struct sock *),
+			  struct sk_buff_head *hitlist)
 {
-	return gc_current == GC_HEAD;
+	struct sk_buff *skb;
+	struct sk_buff *next;
+
+	spin_lock(&x->sk_receive_queue.lock);
+	receive_queue_for_each_skb(x, next, skb) {
+		/*
+		 *	Do we have file descriptors ?
+		 */
+		if (UNIXCB(skb).fp) {
+			bool hit = false;
+			/*
+			 *	Process the descriptors of this socket
+			 */
+			int nfd = UNIXCB(skb).fp->count;
+			struct file **fp = UNIXCB(skb).fp->fp;
+			while (nfd--) {
+				/*
+				 *	Get the socket the fd matches
+				 *	if it indeed does so
+				 */
+				struct sock *sk = unix_get_socket(*fp++);
+				if(sk) {
+					hit = true;
+					func(sk);
+				}
+			}
+			if (hit && hitlist != NULL) {
+				__skb_unlink(skb, &x->sk_receive_queue);
+				__skb_queue_tail(hitlist, skb);
+			}
+		}
+	}
+	spin_unlock(&x->sk_receive_queue.lock);
 }
 
-static void maybe_unmark_and_push(struct sock *x)
+static void scan_children(struct sock *x, void (*func)(struct sock *),
+			  struct sk_buff_head *hitlist)
 {
-	struct unix_sock *u = unix_sk(x);
+	if (x->sk_state != TCP_LISTEN)
+		scan_inflight(x, func, hitlist);
+	else {
+		struct sk_buff *skb;
+		struct sk_buff *next;
+		struct unix_sock *u;
+		LIST_HEAD(embryos);
 
-	if (u->gc_tree != GC_ORPHAN)
-		return;
-	sock_hold(x);
-	u->gc_tree = gc_current;
-	gc_current = x;
+		/*
+		 * For a listening socket collect the queued embryos
+		 * and perform a scan on them as well.
+		 */
+		spin_lock(&x->sk_receive_queue.lock);
+		receive_queue_for_each_skb(x, next, skb) {
+			u = unix_sk(skb->sk);
+
+			/*
+			 * An embryo cannot be in-flight, so it's safe
+			 * to use the list link.
+			 */
+			BUG_ON(!list_empty(&u->link));
+			list_add_tail(&u->link, &embryos);
+		}
+		spin_unlock(&x->sk_receive_queue.lock);
+
+		while (!list_empty(&embryos)) {
+			u = list_entry(embryos.next, struct unix_sock, link);
+			scan_inflight(&u->sk, func, hitlist);
+			list_del_init(&u->link);
+		}
+	}
 }
 
+static void dec_inflight(struct sock *sk)
+{
+	atomic_dec(&unix_sk(sk)->inflight);
+}
+
+static void inc_inflight(struct sock *sk)
+{
+	atomic_inc(&unix_sk(sk)->inflight);
+}
+
+static void inc_inflight_move_tail(struct sock *sk)
+{
+	struct unix_sock *u = unix_sk(sk);
+
+	atomic_inc(&u->inflight);
+	/*
+	 * If this is still a candidate, move it to the end of the
+	 * list, so that it's checked even if it was already passed
+	 * over
+	 */
+	if (u->gc_candidate)
+		list_move_tail(&u->link, &gc_candidates);
+}
 
 /* The external entry point: unix_gc() */
 
 void unix_gc(void)
 {
-	static DEFINE_MUTEX(unix_gc_sem);
-	int i;
-	struct sock *s;
+	static bool gc_in_progress = false;
+
+	struct unix_sock *u;
+	struct unix_sock *next;
 	struct sk_buff_head hitlist;
-	struct sk_buff *skb;
+	struct list_head cursor;
 
+	spin_lock(&unix_gc_lock);
+
+	/* Avoid a recursive GC. */
+	if (gc_in_progress)
+		goto out;
+
+	gc_in_progress = true;
 	/*
-	 *	Avoid a recursive GC.
+	 * First, select candidates for garbage collection.  Only
+	 * in-flight sockets are considered, and from those only ones
+	 * which don't have any external reference.
+	 *
+	 * Holding unix_gc_lock will protect these candidates from
+	 * being detached, and hence from gaining an external
+	 * reference.  This also means, that since there are no
+	 * possible receivers, the receive queues of these sockets are
+	 * static during the GC, even though the dequeue is done
+	 * before the detach without atomicity guarantees.
 	 */
+	list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
+		int total_refs;
+		int inflight_refs;
 
-	if (!mutex_trylock(&unix_gc_sem))
-		return;
+		total_refs = file_count(u->sk.sk_socket->file);
+		inflight_refs = atomic_read(&u->inflight);
 
-	spin_lock(&unix_table_lock);
-
-	forall_unix_sockets(i, s)
-	{
-		unix_sk(s)->gc_tree = GC_ORPHAN;
-	}
-	/*
-	 *	Everything is now marked
-	 */
-
-	/* Invariant to be maintained:
-		- everything unmarked is either:
-		-- (a) on the stack, or
-		-- (b) has all of its children unmarked
-		- everything on the stack is always unmarked
-		- nothing is ever pushed onto the stack twice, because:
-		-- nothing previously unmarked is ever pushed on the stack
-	 */
-
-	/*
-	 *	Push root set
-	 */
-
-	forall_unix_sockets(i, s)
-	{
-		int open_count = 0;
-
-		/*
-		 *	If all instances of the descriptor are not
-		 *	in flight we are in use.
-		 *
-		 *	Special case: when socket s is embrion, it may be
-		 *	hashed but still not in queue of listening socket.
-		 *	In this case (see unix_create1()) we set artificial
-		 *	negative inflight counter to close race window.
-		 *	It is trick of course and dirty one.
-		 */
-		if (s->sk_socket && s->sk_socket->file)
-			open_count = file_count(s->sk_socket->file);
-		if (open_count > atomic_read(&unix_sk(s)->inflight))
-			maybe_unmark_and_push(s);
-	}
-
-	/*
-	 *	Mark phase
-	 */
-
-	while (!empty_stack())
-	{
-		struct sock *x = pop_stack();
-		struct sock *sk;
-
-		spin_lock(&x->sk_receive_queue.lock);
-		skb = skb_peek(&x->sk_receive_queue);
-
-		/*
-		 *	Loop through all but first born
-		 */
-
-		while (skb && skb != (struct sk_buff *)&x->sk_receive_queue) {
-			/*
-			 *	Do we have file descriptors ?
-			 */
-			if(UNIXCB(skb).fp)
-			{
-				/*
-				 *	Process the descriptors of this socket
-				 */
-				int nfd=UNIXCB(skb).fp->count;
-				struct file **fp = UNIXCB(skb).fp->fp;
-				while(nfd--)
-				{
-					/*
-					 *	Get the socket the fd matches if
-					 *	it indeed does so
-					 */
-					if((sk=unix_get_socket(*fp++))!=NULL)
-					{
-						maybe_unmark_and_push(sk);
-					}
-				}
-			}
-			/* We have to scan not-yet-accepted ones too */
-			if (x->sk_state == TCP_LISTEN)
-				maybe_unmark_and_push(skb->sk);
-			skb=skb->next;
+		BUG_ON(inflight_refs < 1);
+		BUG_ON(total_refs < inflight_refs);
+		if (total_refs == inflight_refs) {
+			list_move_tail(&u->link, &gc_candidates);
+			u->gc_candidate = 1;
 		}
-		spin_unlock(&x->sk_receive_queue.lock);
-		sock_put(x);
 	}
 
+	/*
+	 * Now remove all internal in-flight reference to children of
+	 * the candidates.
+	 */
+	list_for_each_entry(u, &gc_candidates, link)
+		scan_children(&u->sk, dec_inflight, NULL);
+
+	/*
+	 * Restore the references for children of all candidates,
+	 * which have remaining references.  Do this recursively, so
+	 * only those remain, which form cyclic references.
+	 *
+	 * Use a "cursor" link, to make the list traversal safe, even
+	 * though elements might be moved about.
+	 */
+	list_add(&cursor, &gc_candidates);
+	while (cursor.next != &gc_candidates) {
+		u = list_entry(cursor.next, struct unix_sock, link);
+
+		/* Move cursor to after the current position. */
+		list_move(&cursor, &u->link);
+
+		if (atomic_read(&u->inflight) > 0) {
+			list_move_tail(&u->link, &gc_inflight_list);
+			u->gc_candidate = 0;
+			scan_children(&u->sk, inc_inflight_move_tail, NULL);
+		}
+	}
+	list_del(&cursor);
+
+	/*
+	 * Now gc_candidates contains only garbage.  Restore original
+	 * inflight counters for these as well, and remove the skbuffs
+	 * which are creating the cycle(s).
+	 */
 	skb_queue_head_init(&hitlist);
+	list_for_each_entry(u, &gc_candidates, link)
+		scan_children(&u->sk, inc_inflight, &hitlist);
 
-	forall_unix_sockets(i, s)
-	{
-		struct unix_sock *u = unix_sk(s);
+	spin_unlock(&unix_gc_lock);
 
-		if (u->gc_tree == GC_ORPHAN) {
-			struct sk_buff *nextsk;
-
-			spin_lock(&s->sk_receive_queue.lock);
-			skb = skb_peek(&s->sk_receive_queue);
-			while (skb &&
-			       skb != (struct sk_buff *)&s->sk_receive_queue) {
-				nextsk = skb->next;
-				/*
-				 *	Do we have file descriptors ?
-				 */
-				if (UNIXCB(skb).fp) {
-					__skb_unlink(skb,
-						     &s->sk_receive_queue);
-					__skb_queue_tail(&hitlist, skb);
-				}
-				skb = nextsk;
-			}
-			spin_unlock(&s->sk_receive_queue.lock);
-		}
-		u->gc_tree = GC_ORPHAN;
-	}
-	spin_unlock(&unix_table_lock);
-
-	/*
-	 *	Here we are. Hitlist is filled. Die.
-	 */
-
+	/* Here we are. Hitlist is filled. Die. */
 	__skb_queue_purge(&hitlist);
-	mutex_unlock(&unix_gc_sem);
+
+	spin_lock(&unix_gc_lock);
+
+	/* All candidates should have been detached by now. */
+	BUG_ON(!list_empty(&gc_candidates));
+	gc_in_progress = false;
+
+ out:
+	spin_unlock(&unix_gc_lock);
 }
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 7a19e0e..849cc06 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -454,7 +454,7 @@
 	}
 
 	if (conf->data_size && conf->data) {
-		if (conf->data_size > 128000 || conf->data_size < 0) {
+		if (conf->data_size > 128000) {
 			printk(KERN_INFO
 			    "%s: ERROR, Invalid firmware data size %i !\n",
 					wandev->name, conf->data_size);
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
index 2051065..236e7ea 100644
--- a/net/wanrouter/wanproc.c
+++ b/net/wanrouter/wanproc.c
@@ -164,14 +164,14 @@
 	return 0;
 }
 
-static struct seq_operations config_op = {
+static const struct seq_operations config_op = {
 	.start	= r_start,
 	.next	= r_next,
 	.stop	= r_stop,
 	.show	= config_show,
 };
 
-static struct seq_operations status_op = {
+static const struct seq_operations status_op = {
 	.start	= r_start,
 	.next	= r_next,
 	.stop	= r_stop,
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 3a96ae6..092116e 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_WIRELESS_EXT) += wext.o
 obj-$(CONFIG_CFG80211) += cfg80211.o
 
-cfg80211-y += core.o sysfs.o
+cfg80211-y += core.o sysfs.o radiotap.o
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
new file mode 100644
index 0000000..68c11d0
--- /dev/null
+++ b/net/wireless/radiotap.c
@@ -0,0 +1,257 @@
+/*
+ * Radiotap parser
+ *
+ * Copyright 2007		Andy Green <andy@warmcat.com>
+ */
+
+#include <net/cfg80211.h>
+#include <net/ieee80211_radiotap.h>
+#include <asm/unaligned.h>
+
+/* function prototypes and related defs are in include/net/cfg80211.h */
+
+/**
+ * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
+ * @iterator: radiotap_iterator to initialize
+ * @radiotap_header: radiotap header to parse
+ * @max_length: total length we can parse into (eg, whole packet length)
+ *
+ * Returns: 0 or a negative error code if there is a problem.
+ *
+ * This function initializes an opaque iterator struct which can then
+ * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
+ * argument which is present in the header.  It knows about extended
+ * present headers and handles them.
+ *
+ * How to use:
+ * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
+ * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
+ * checking for a good 0 return code.  Then loop calling
+ * __ieee80211_radiotap_iterator_next()... it returns either 0,
+ * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
+ * The iterator's @this_arg member points to the start of the argument
+ * associated with the current argument index that is present, which can be
+ * found in the iterator's @this_arg_index member.  This arg index corresponds
+ * to the IEEE80211_RADIOTAP_... defines.
+ *
+ * Radiotap header length:
+ * You can find the CPU-endian total radiotap header length in
+ * iterator->max_length after executing ieee80211_radiotap_iterator_init()
+ * successfully.
+ *
+ * Alignment Gotcha:
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned.  Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ *
+ * Example code:
+ * See Documentation/networking/radiotap-headers.txt
+ */
+
+int ieee80211_radiotap_iterator_init(
+    struct ieee80211_radiotap_iterator *iterator,
+    struct ieee80211_radiotap_header *radiotap_header,
+    int max_length)
+{
+	/* Linux only supports version 0 radiotap format */
+	if (radiotap_header->it_version)
+		return -EINVAL;
+
+	/* sanity check for allowed length and radiotap length field */
+	if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
+		return -EINVAL;
+
+	iterator->rtheader = radiotap_header;
+	iterator->max_length = le16_to_cpu(get_unaligned(
+						&radiotap_header->it_len));
+	iterator->arg_index = 0;
+	iterator->bitmap_shifter = le32_to_cpu(get_unaligned(
+						&radiotap_header->it_present));
+	iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
+	iterator->this_arg = NULL;
+
+	/* find payload start allowing for extended bitmap(s) */
+
+	if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
+		while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) &
+				   (1<<IEEE80211_RADIOTAP_EXT)) {
+			iterator->arg += sizeof(u32);
+
+			/*
+			 * check for insanity where the present bitmaps
+			 * keep claiming to extend up to or even beyond the
+			 * stated radiotap header length
+			 */
+
+			if (((ulong)iterator->arg -
+			     (ulong)iterator->rtheader) > iterator->max_length)
+				return -EINVAL;
+		}
+
+		iterator->arg += sizeof(u32);
+
+		/*
+		 * no need to check again for blowing past stated radiotap
+		 * header length, because ieee80211_radiotap_iterator_next
+		 * checks it before it is dereferenced
+		 */
+	}
+
+	/* we are all initialized happily */
+
+	return 0;
+}
+EXPORT_SYMBOL(ieee80211_radiotap_iterator_init);
+
+
+/**
+ * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
+ * @iterator: radiotap_iterator to move to next arg (if any)
+ *
+ * Returns: 0 if there is an argument to handle,
+ * -ENOENT if there are no more args or -EINVAL
+ * if there is something else wrong.
+ *
+ * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
+ * in @this_arg_index and sets @this_arg to point to the
+ * payload for the field.  It takes care of alignment handling and extended
+ * present fields.  @this_arg can be changed by the caller (eg,
+ * incremented to move inside a compound argument like
+ * IEEE80211_RADIOTAP_CHANNEL).  The args pointed to are in
+ * little-endian format whatever the endianess of your CPU.
+ *
+ * Alignment Gotcha:
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned.  Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ */
+
+int ieee80211_radiotap_iterator_next(
+    struct ieee80211_radiotap_iterator *iterator)
+{
+
+	/*
+	 * small length lookup table for all radiotap types we heard of
+	 * starting from b0 in the bitmap, so we can walk the payload
+	 * area of the radiotap header
+	 *
+	 * There is a requirement to pad args, so that args
+	 * of a given length must begin at a boundary of that length
+	 * -- but note that compound args are allowed (eg, 2 x u16
+	 * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
+	 * a reliable indicator of alignment requirement.
+	 *
+	 * upper nybble: content alignment for arg
+	 * lower nybble: content length for arg
+	 */
+
+	static const u8 rt_sizes[] = {
+		[IEEE80211_RADIOTAP_TSFT] = 0x88,
+		[IEEE80211_RADIOTAP_FLAGS] = 0x11,
+		[IEEE80211_RADIOTAP_RATE] = 0x11,
+		[IEEE80211_RADIOTAP_CHANNEL] = 0x24,
+		[IEEE80211_RADIOTAP_FHSS] = 0x22,
+		[IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
+		[IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
+		[IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
+		[IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
+		[IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
+		[IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
+		[IEEE80211_RADIOTAP_ANTENNA] = 0x11,
+		[IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
+		[IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11
+		/*
+		 * add more here as they are defined in
+		 * include/net/ieee80211_radiotap.h
+		 */
+	};
+
+	/*
+	 * for every radiotap entry we can at
+	 * least skip (by knowing the length)...
+	 */
+
+	while (iterator->arg_index < sizeof(rt_sizes)) {
+		int hit = 0;
+		int pad;
+
+		if (!(iterator->bitmap_shifter & 1))
+			goto next_entry; /* arg not present */
+
+		/*
+		 * arg is present, account for alignment padding
+		 *  8-bit args can be at any alignment
+		 * 16-bit args must start on 16-bit boundary
+		 * 32-bit args must start on 32-bit boundary
+		 * 64-bit args must start on 64-bit boundary
+		 *
+		 * note that total arg size can differ from alignment of
+		 * elements inside arg, so we use upper nybble of length
+		 * table to base alignment on
+		 *
+		 * also note: these alignments are ** relative to the
+		 * start of the radiotap header **.  There is no guarantee
+		 * that the radiotap header itself is aligned on any
+		 * kind of boundary.
+		 *
+		 * the above is why get_unaligned() is used to dereference
+		 * multibyte elements from the radiotap area
+		 */
+
+		pad = (((ulong)iterator->arg) -
+			((ulong)iterator->rtheader)) &
+			((rt_sizes[iterator->arg_index] >> 4) - 1);
+
+		if (pad)
+			iterator->arg +=
+				(rt_sizes[iterator->arg_index] >> 4) - pad;
+
+		/*
+		 * this is what we will return to user, but we need to
+		 * move on first so next call has something fresh to test
+		 */
+		iterator->this_arg_index = iterator->arg_index;
+		iterator->this_arg = iterator->arg;
+		hit = 1;
+
+		/* internally move on the size of this arg */
+		iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
+
+		/*
+		 * check for insanity where we are given a bitmap that
+		 * claims to have more arg content than the length of the
+		 * radiotap section.  We will normally end up equalling this
+		 * max_length on the last arg, never exceeding it.
+		 */
+
+		if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
+		    iterator->max_length)
+			return -EINVAL;
+
+	next_entry:
+		iterator->arg_index++;
+		if (unlikely((iterator->arg_index & 31) == 0)) {
+			/* completed current u32 bitmap */
+			if (iterator->bitmap_shifter & 1) {
+				/* b31 was set, there is more */
+				/* move to next u32 bitmap */
+				iterator->bitmap_shifter = le32_to_cpu(
+					get_unaligned(iterator->next_bitmap));
+				iterator->next_bitmap++;
+			} else
+				/* no more bitmaps: end */
+				iterator->arg_index = sizeof(rt_sizes);
+		} else /* just try the next bit */
+			iterator->bitmap_shifter >>= 1;
+
+		/* if we found a valid arg earlier, return it now */
+		if (hit)
+			return 0;
+	}
+
+	/* we don't know how to handle any more args, we're done */
+	return -ENOENT;
+}
+EXPORT_SYMBOL(ieee80211_radiotap_iterator_next);
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 3ebae14..88aaacd 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -33,7 +33,7 @@
 			      struct device_attribute *attr,
 			      char *buf)
 {
-	char *addr = dev_to_rdev(dev)->wiphy.perm_addr;
+	unsigned char *addr = dev_to_rdev(dev)->wiphy.perm_addr;
 
 	return sprintf(buf, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
 		       addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c
index 96001f0..7405b9c 100644
--- a/net/x25/x25_proc.c
+++ b/net/x25/x25_proc.c
@@ -234,21 +234,21 @@
 	return 0;
 }
 
-static struct seq_operations x25_seq_route_ops = {
+static const struct seq_operations x25_seq_route_ops = {
 	.start  = x25_seq_route_start,
 	.next   = x25_seq_route_next,
 	.stop   = x25_seq_route_stop,
 	.show   = x25_seq_route_show,
 };
 
-static struct seq_operations x25_seq_socket_ops = {
+static const struct seq_operations x25_seq_socket_ops = {
 	.start  = x25_seq_socket_start,
 	.next   = x25_seq_socket_next,
 	.stop   = x25_seq_socket_stop,
 	.show   = x25_seq_socket_show,
 };
 
-static struct seq_operations x25_seq_forward_ops = {
+static const struct seq_operations x25_seq_forward_ops = {
 	.start  = x25_seq_forward_start,
 	.next   = x25_seq_forward_next,
 	.stop   = x25_seq_forward_stop,
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 6249a94..5ced62c 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -347,67 +347,44 @@
 	return ARRAY_SIZE(calg_list);
 }
 
-/* Todo: generic iterators */
-struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
+struct xfrm_algo_list {
+	struct xfrm_algo_desc *algs;
+	int entries;
+	u32 type;
+	u32 mask;
+};
+
+static const struct xfrm_algo_list xfrm_aalg_list = {
+	.algs = aalg_list,
+	.entries = ARRAY_SIZE(aalg_list),
+	.type = CRYPTO_ALG_TYPE_HASH,
+	.mask = CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC,
+};
+
+static const struct xfrm_algo_list xfrm_ealg_list = {
+	.algs = ealg_list,
+	.entries = ARRAY_SIZE(ealg_list),
+	.type = CRYPTO_ALG_TYPE_BLKCIPHER,
+	.mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
+};
+
+static const struct xfrm_algo_list xfrm_calg_list = {
+	.algs = calg_list,
+	.entries = ARRAY_SIZE(calg_list),
+	.type = CRYPTO_ALG_TYPE_COMPRESS,
+	.mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
+};
+
+static struct xfrm_algo_desc *xfrm_find_algo(
+	const struct xfrm_algo_list *algo_list,
+	int match(const struct xfrm_algo_desc *entry, const void *data),
+	const void *data, int probe)
 {
-	int i;
-
-	for (i = 0; i < aalg_entries(); i++) {
-		if (aalg_list[i].desc.sadb_alg_id == alg_id) {
-			if (aalg_list[i].available)
-				return &aalg_list[i];
-			else
-				break;
-		}
-	}
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
-
-struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
-{
-	int i;
-
-	for (i = 0; i < ealg_entries(); i++) {
-		if (ealg_list[i].desc.sadb_alg_id == alg_id) {
-			if (ealg_list[i].available)
-				return &ealg_list[i];
-			else
-				break;
-		}
-	}
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
-
-struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
-{
-	int i;
-
-	for (i = 0; i < calg_entries(); i++) {
-		if (calg_list[i].desc.sadb_alg_id == alg_id) {
-			if (calg_list[i].available)
-				return &calg_list[i];
-			else
-				break;
-		}
-	}
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
-
-static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
-					      int entries, u32 type, u32 mask,
-					      char *name, int probe)
-{
+	struct xfrm_algo_desc *list = algo_list->algs;
 	int i, status;
 
-	if (!name)
-		return NULL;
-
-	for (i = 0; i < entries; i++) {
-		if (strcmp(name, list[i].name) &&
-		    (!list[i].compat || strcmp(name, list[i].compat)))
+	for (i = 0; i < algo_list->entries; i++) {
+		if (!match(list + i, data))
 			continue;
 
 		if (list[i].available)
@@ -416,8 +393,8 @@
 		if (!probe)
 			break;
 
-		status = crypto_has_alg(list[i].name, type,
-					mask | CRYPTO_ALG_ASYNC);
+		status = crypto_has_alg(list[i].name, algo_list->type,
+					algo_list->mask);
 		if (!status)
 			break;
 
@@ -427,27 +404,60 @@
 	return NULL;
 }
 
+static int xfrm_alg_id_match(const struct xfrm_algo_desc *entry,
+			     const void *data)
+{
+	return entry->desc.sadb_alg_id == (unsigned long)data;
+}
+
+struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
+{
+	return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_id_match,
+			      (void *)(unsigned long)alg_id, 1);
+}
+EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
+
+struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
+{
+	return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_id_match,
+			      (void *)(unsigned long)alg_id, 1);
+}
+EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
+
+struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
+{
+	return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_id_match,
+			      (void *)(unsigned long)alg_id, 1);
+}
+EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
+
+static int xfrm_alg_name_match(const struct xfrm_algo_desc *entry,
+			       const void *data)
+{
+	const char *name = data;
+
+	return name && (!strcmp(name, entry->name) ||
+			(entry->compat && !strcmp(name, entry->compat)));
+}
+
 struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe)
 {
-	return xfrm_get_byname(aalg_list, aalg_entries(),
-			       CRYPTO_ALG_TYPE_HASH, CRYPTO_ALG_TYPE_HASH_MASK,
-			       name, probe);
+	return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_name_match, name,
+			      probe);
 }
 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
 
 struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe)
 {
-	return xfrm_get_byname(ealg_list, ealg_entries(),
-			       CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_MASK,
-			       name, probe);
+	return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_name_match, name,
+			      probe);
 }
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
 
 struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
 {
-	return xfrm_get_byname(calg_list, calg_entries(),
-			       CRYPTO_ALG_TYPE_COMPRESS, CRYPTO_ALG_TYPE_MASK,
-			       name, probe);
+	return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_name_match, name,
+			      probe);
 }
 EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
 
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d0882e5..157bfbd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -26,9 +26,12 @@
 #include <net/xfrm.h>
 #include <net/ip.h>
 #include <linux/audit.h>
+#include <linux/cache.h>
 
 #include "xfrm_hash.h"
 
+int sysctl_xfrm_larval_drop __read_mostly;
+
 DEFINE_MUTEX(xfrm_cfg_mutex);
 EXPORT_SYMBOL(xfrm_cfg_mutex);
 
@@ -831,11 +834,67 @@
 }
 EXPORT_SYMBOL(xfrm_policy_byid);
 
-void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
 {
-	int dir;
+	int dir, err = 0;
+
+	for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
+		struct xfrm_policy *pol;
+		struct hlist_node *entry;
+		int i;
+
+		hlist_for_each_entry(pol, entry,
+				     &xfrm_policy_inexact[dir], bydst) {
+			if (pol->type != type)
+				continue;
+			err = security_xfrm_policy_delete(pol);
+			if (err) {
+				xfrm_audit_log(audit_info->loginuid,
+					       audit_info->secid,
+					       AUDIT_MAC_IPSEC_DELSPD, 0,
+					       pol, NULL);
+				return err;
+			}
+                }
+		for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
+			hlist_for_each_entry(pol, entry,
+					     xfrm_policy_bydst[dir].table + i,
+					     bydst) {
+				if (pol->type != type)
+					continue;
+				err = security_xfrm_policy_delete(pol);
+				if (err) {
+					xfrm_audit_log(audit_info->loginuid,
+						       audit_info->secid,
+						       AUDIT_MAC_IPSEC_DELSPD,
+						       0, pol, NULL);
+					return err;
+				}
+			}
+		}
+	}
+	return err;
+}
+#else
+static inline int
+xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+{
+	return 0;
+}
+#endif
+
+int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+{
+	int dir, err = 0;
 
 	write_lock_bh(&xfrm_policy_lock);
+
+	err = xfrm_policy_flush_secctx_check(type, audit_info);
+	if (err)
+		goto out;
+
 	for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
 		struct xfrm_policy *pol;
 		struct hlist_node *entry;
@@ -888,7 +947,9 @@
 		xfrm_policy_count[dir] -= killed;
 	}
 	atomic_inc(&flow_cache_genid);
+out:
 	write_unlock_bh(&xfrm_policy_lock);
+	return err;
 }
 EXPORT_SYMBOL(xfrm_policy_flush);
 
@@ -1390,8 +1451,8 @@
  * At the moment we eat a raw IP route. Mostly to speed up lookups
  * on interfaces with disabled IPsec.
  */
-int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
-		struct sock *sk, int flags)
+int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
+		  struct sock *sk, int flags)
 {
 	struct xfrm_policy *policy;
 	struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
@@ -1509,6 +1570,13 @@
 
 		if (unlikely(nx<0)) {
 			err = nx;
+			if (err == -EAGAIN && sysctl_xfrm_larval_drop) {
+				/* EREMOTE tells the caller to generate
+				 * a one-shot blackhole route.
+				 */
+				xfrm_pol_put(policy);
+				return -EREMOTE;
+			}
 			if (err == -EAGAIN && flags) {
 				DECLARE_WAITQUEUE(wait, current);
 
@@ -1598,6 +1666,21 @@
 	*dst_p = NULL;
 	return err;
 }
+EXPORT_SYMBOL(__xfrm_lookup);
+
+int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
+		struct sock *sk, int flags)
+{
+	int err = __xfrm_lookup(dst_p, fl, sk, flags);
+
+	if (err == -EREMOTE) {
+		dst_release(*dst_p);
+		*dst_p = NULL;
+		err = -EAGAIN;
+	}
+
+	return err;
+}
 EXPORT_SYMBOL(xfrm_lookup);
 
 static inline int
@@ -2558,4 +2641,3 @@
 }
 EXPORT_SYMBOL(xfrm_migrate);
 #endif
-
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9955ff4..e070c3f 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -21,18 +21,21 @@
 #include <linux/cache.h>
 #include <asm/uaccess.h>
 #include <linux/audit.h>
+#include <linux/cache.h>
 
 #include "xfrm_hash.h"
 
 struct sock *xfrm_nl;
 EXPORT_SYMBOL(xfrm_nl);
 
-u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
+u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME;
 EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
 
-u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
+u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE;
 EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
 
+u32 sysctl_xfrm_acq_expires __read_mostly = 30;
+
 /* Each xfrm_state may be linked to two tables:
 
    1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
@@ -388,12 +391,48 @@
 }
 EXPORT_SYMBOL(xfrm_state_delete);
 
-void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
 {
-	int i;
-	int err = 0;
+	int i, err = 0;
+
+	for (i = 0; i <= xfrm_state_hmask; i++) {
+		struct hlist_node *entry;
+		struct xfrm_state *x;
+
+		hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
+			if (xfrm_id_proto_match(x->id.proto, proto) &&
+			   (err = security_xfrm_state_delete(x)) != 0) {
+				xfrm_audit_log(audit_info->loginuid,
+					       audit_info->secid,
+					       AUDIT_MAC_IPSEC_DELSA,
+                                               0, NULL, x);
+
+				return err;
+			}
+		}
+	}
+
+	return err;
+}
+#else
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
+{
+	return 0;
+}
+#endif
+
+int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+{
+	int i, err = 0;
 
 	spin_lock_bh(&xfrm_state_lock);
+	err = xfrm_state_flush_secctx_check(proto, audit_info);
+	if (err)
+		goto out;
+
 	for (i = 0; i <= xfrm_state_hmask; i++) {
 		struct hlist_node *entry;
 		struct xfrm_state *x;
@@ -416,8 +455,12 @@
 			}
 		}
 	}
+	err = 0;
+
+out:
 	spin_unlock_bh(&xfrm_state_lock);
 	wake_up(&km_waitq);
+	return err;
 }
 EXPORT_SYMBOL(xfrm_state_flush);
 
@@ -622,8 +665,8 @@
 				h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
 				hlist_add_head(&x->byspi, xfrm_state_byspi+h);
 			}
-			x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
-			x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
+			x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
+			x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
 			add_timer(&x->timer);
 			xfrm_state_num++;
 			xfrm_hash_grow_check(x->bydst.next != NULL);
@@ -643,6 +686,37 @@
 	return x;
 }
 
+struct xfrm_state *
+xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
+		    unsigned short family, u8 mode, u8 proto, u32 reqid)
+{
+	unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family);
+	struct xfrm_state *rx = NULL, *x = NULL;
+	struct hlist_node *entry;
+
+	spin_lock(&xfrm_state_lock);
+	hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
+		if (x->props.family == family &&
+		    x->props.reqid == reqid &&
+		    !(x->props.flags & XFRM_STATE_WILDRECV) &&
+		    xfrm_state_addr_check(x, daddr, saddr, family) &&
+		    mode == x->props.mode &&
+		    proto == x->id.proto &&
+		    x->km.state == XFRM_STATE_VALID) {
+			rx = x;
+			break;
+		}
+	}
+
+	if (rx)
+		xfrm_state_hold(rx);
+	spin_unlock(&xfrm_state_lock);
+
+
+	return rx;
+}
+EXPORT_SYMBOL(xfrm_stateonly_find);
+
 static void __xfrm_state_insert(struct xfrm_state *x)
 {
 	unsigned int h;
@@ -772,9 +846,9 @@
 		x->props.family = family;
 		x->props.mode = mode;
 		x->props.reqid = reqid;
-		x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
+		x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
 		xfrm_state_hold(x);
-		x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
+		x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
 		add_timer(&x->timer);
 		hlist_add_head(&x->bydst, xfrm_state_bydst+h);
 		h = xfrm_src_hash(daddr, saddr, family);
@@ -1686,7 +1760,7 @@
 	    x->type && x->type->get_mtu)
 		res = x->type->get_mtu(x, mtu);
 	else
-		res = mtu;
+		res = mtu - x->props.header_len;
 	spin_unlock_bh(&x->lock);
 	return res;
 }
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index b14c7e5..c06883b 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1418,10 +1418,13 @@
 	struct km_event c;
 	struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
 	struct xfrm_audit audit_info;
+	int err;
 
 	audit_info.loginuid = NETLINK_CB(skb).loginuid;
 	audit_info.secid = NETLINK_CB(skb).sid;
-	xfrm_state_flush(p->proto, &audit_info);
+	err = xfrm_state_flush(p->proto, &audit_info);
+	if (err)
+		return err;
 	c.data.proto = p->proto;
 	c.event = nlh->nlmsg_type;
 	c.seq = nlh->nlmsg_seq;
@@ -1582,7 +1585,9 @@
 
 	audit_info.loginuid = NETLINK_CB(skb).loginuid;
 	audit_info.secid = NETLINK_CB(skb).sid;
-	xfrm_policy_flush(type, &audit_info);
+	err = xfrm_policy_flush(type, &audit_info);
+	if (err)
+		return err;
 	c.data.type = type;
 	c.event = nlh->nlmsg_type;
 	c.seq = nlh->nlmsg_seq;
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index f7b6705..f98d772 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -108,7 +108,7 @@
 
 quiet_cmd_gen		  = GEN     $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
       cmd_gen		  = \
-FNAME=$(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$@)			\
+FNAME=$(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$@);			\
 STUBDEF=__ASM_STUB_`echo $$FNAME | tr a-z.- A-Z__`;			\
 (echo "/* File autogenerated by 'make headers_install' */" ;		\
 echo "\#ifndef $$STUBDEF" ;						\
@@ -144,7 +144,7 @@
 	$(call cmd,check)
 
 # Other dependencies for $(check-y)
--include /dev/null $(check-y)
+include /dev/null $(wildcard $(check-y))
 
 # ... but leave $(check-y) as .PHONY for now until those deps are actually correct.
 .PHONY: $(check-y)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
new file mode 100755
index 0000000..25e20a2
--- /dev/null
+++ b/scripts/checkpatch.pl
@@ -0,0 +1,964 @@
+#!/usr/bin/perl -w
+# (c) 2001, Dave Jones. <davej@codemonkey.org.uk> (the file handling bit)
+# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
+# (c) 2007, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite, etc)
+# Licensed under the terms of the GNU GPL License version 2
+
+use strict;
+
+my $P = $0;
+$P =~ s@.*/@@g;
+
+my $V = '0.07';
+
+use Getopt::Long qw(:config no_auto_abbrev);
+
+my $quiet = 0;
+my $tree = 1;
+my $chk_signoff = 1;
+my $chk_patch = 1;
+my $tst_type = 0;
+GetOptions(
+	'q|quiet'	=> \$quiet,
+	'tree!'		=> \$tree,
+	'signoff!'	=> \$chk_signoff,
+	'patch!'	=> \$chk_patch,
+	'test-type!'	=> \$tst_type,
+) or exit;
+
+my $exit = 0;
+
+if ($#ARGV < 0) {
+	print "usage: $P [options] patchfile\n";
+	print "version: $V\n";
+	print "options: -q           => quiet\n";
+	print "         --no-tree    => run without a kernel tree\n";
+	exit(1);
+}
+
+if ($tree && !top_of_kernel_tree()) {
+	print "Must be run from the top-level dir. of a kernel tree\n";
+	exit(2);
+}
+
+my @dep_includes = ();
+my @dep_functions = ();
+my $removal = 'Documentation/feature-removal-schedule.txt';
+if ($tree && -f $removal) {
+	open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
+	while (<REMOVE>) {
+		if (/^Files:\s+(.*\S)/) {
+			for my $file (split(/[, ]+/, $1)) {
+				if ($file =~ m@include/(.*)@) {
+					push(@dep_includes, $1);
+				}
+			}
+
+		} elsif (/^Funcs:\s+(.*\S)/) {
+			for my $func (split(/[, ]+/, $1)) {
+				push(@dep_functions, $func);
+			}
+		}
+	}
+}
+
+my @rawlines = ();
+while (<>) {
+	chomp;
+	push(@rawlines, $_);
+	if (eof(ARGV)) {
+		if (!process($ARGV, @rawlines)) {
+			$exit = 1;
+		}
+		@rawlines = ();
+	}
+}
+
+exit($exit);
+
+sub top_of_kernel_tree {
+	if ((-f "COPYING") && (-f "CREDITS") && (-f "Kbuild") &&
+	    (-f "MAINTAINERS") && (-f "Makefile") && (-f "README") &&
+	    (-d "Documentation") && (-d "arch") && (-d "include") &&
+	    (-d "drivers") && (-d "fs") && (-d "init") && (-d "ipc") &&
+	    (-d "kernel") && (-d "lib") && (-d "scripts")) {
+		return 1;
+	}
+	return 0;
+}
+
+sub expand_tabs {
+	my ($str) = @_;
+
+	my $res = '';
+	my $n = 0;
+	for my $c (split(//, $str)) {
+		if ($c eq "\t") {
+			$res .= ' ';
+			$n++;
+			for (; ($n % 8) != 0; $n++) {
+				$res .= ' ';
+			}
+			next;
+		}
+		$res .= $c;
+		$n++;
+	}
+
+	return $res;
+}
+
+sub line_stats {
+	my ($line) = @_;
+
+	# Drop the diff line leader and expand tabs
+	$line =~ s/^.//;
+	$line = expand_tabs($line);
+
+	# Pick the indent from the front of the line.
+	my ($white) = ($line =~ /^(\s*)/);
+
+	return (length($line), length($white));
+}
+
+sub sanitise_line {
+	my ($line) = @_;
+
+	my $res = '';
+	my $l = '';
+
+	my $quote = '';
+
+	foreach my $c (split(//, $line)) {
+		if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
+			if ($quote eq '') {
+				$quote = $c;
+				$res .= $c;
+				$l = $c;
+				next;
+			} elsif ($quote eq $c) {
+				$quote = '';
+			}
+		}
+		if ($quote && $c ne "\t") {
+			$res .= "X";
+		} else {
+			$res .= $c;
+		}
+
+		$l = $c;
+	}
+
+	return $res;
+}
+
+sub ctx_block_get {
+	my ($linenr, $remain, $outer, $open, $close) = @_;
+	my $line;
+	my $start = $linenr - 1;
+	my $blk = '';
+	my @o;
+	my @c;
+	my @res = ();
+
+	for ($line = $start; $remain > 0; $line++) {
+		next if ($rawlines[$line] =~ /^-/);
+		$remain--;
+
+		$blk .= $rawlines[$line];
+
+		@o = ($blk =~ /$open/g);
+		@c = ($blk =~ /$close/g);
+
+		if (!$outer || (scalar(@o) - scalar(@c)) == 1) {
+			push(@res, $rawlines[$line]);
+		}
+
+		last if (scalar(@o) == scalar(@c));
+	}
+
+	return @res;
+}
+sub ctx_block_outer {
+	my ($linenr, $remain) = @_;
+
+	return ctx_block_get($linenr, $remain, 1, '\{', '\}');
+}
+sub ctx_block {
+	my ($linenr, $remain) = @_;
+
+	return ctx_block_get($linenr, $remain, 0, '\{', '\}');
+}
+sub ctx_statement {
+	my ($linenr, $remain) = @_;
+
+	return ctx_block_get($linenr, $remain, 0, '\(', '\)');
+}
+
+sub ctx_locate_comment {
+	my ($first_line, $end_line) = @_;
+
+	# Catch a comment on the end of the line itself.
+	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
+	return $current_comment if (defined $current_comment);
+
+	# Look through the context and try and figure out if there is a
+	# comment.
+	my $in_comment = 0;
+	$current_comment = '';
+	for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
+		my $line = $rawlines[$linenr - 1];
+		#warn "           $line\n";
+		if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
+			$in_comment = 1;
+		}
+		if ($line =~ m@/\*@) {
+			$in_comment = 1;
+		}
+		if (!$in_comment && $current_comment ne '') {
+			$current_comment = '';
+		}
+		$current_comment .= $line . "\n" if ($in_comment);
+		if ($line =~ m@\*/@) {
+			$in_comment = 0;
+		}
+	}
+
+	chomp($current_comment);
+	return($current_comment);
+}
+sub ctx_has_comment {
+	my ($first_line, $end_line) = @_;
+	my $cmt = ctx_locate_comment($first_line, $end_line);
+
+	##print "LINE: $rawlines[$end_line - 1 ]\n";
+	##print "CMMT: $cmt\n";
+
+	return ($cmt ne '');
+}
+
+sub cat_vet {
+	my ($vet) = @_;
+
+	$vet =~ s/\t/^I/;
+	$vet =~ s/$/\$/;
+
+	return $vet;
+}
+
+sub ERROR {
+	print "ERROR: $_[0]\n";
+	our $clean = 0;
+}
+sub WARN {
+	print "WARNING: $_[0]\n";
+	our $clean = 0;
+}
+sub CHK {
+	print "CHECK: $_[0]\n";
+	our $clean = 0;
+}
+
+sub process {
+	my $filename = shift;
+	my @lines = @_;
+
+	my $linenr=0;
+	my $prevline="";
+	my $stashline="";
+
+	my $length;
+	my $indent;
+	my $previndent=0;
+	my $stashindent=0;
+
+	our $clean = 1;
+	my $signoff = 0;
+	my $is_patch = 0;
+
+	# Trace the real file/line as we go.
+	my $realfile = '';
+	my $realline = 0;
+	my $realcnt = 0;
+	my $here = '';
+	my $in_comment = 0;
+	my $first_line = 0;
+
+	my $Ident	= qr{[A-Za-z\d_]+};
+	my $Storage	= qr{extern|static};
+	my $Sparse	= qr{__user|__kernel|__force|__iomem};
+	my $NonptrType	= qr{
+				\b
+				(?:const\s+)?
+				(?:unsigned\s+)?
+				(?:
+					void|
+					char|
+					short|
+					int|
+					long|
+					unsigned|
+					float|
+					double|
+					long\s+int|
+					long\s+long|
+					long\s+long\s+int|
+					u8|u16|u32|u64|
+					s8|s16|s32|s64|
+					struct\s+$Ident|
+					union\s+$Ident|
+					enum\s+$Ident|
+					${Ident}_t
+				)
+				(?:\s+$Sparse)*
+				\b
+			  }x;
+	my $Type	= qr{
+				\b$NonptrType\b
+				(?:\s*\*+\s*const|\s*\*+)?
+			  }x;
+	my $Declare	= qr{(?:$Storage\s+)?$Type};
+	my $Attribute	= qr{__read_mostly|__init|__initdata};
+
+	# Pre-scan the patch looking for any __setup documentation.
+	my @setup_docs = ();
+	my $setup_docs = 0;
+	foreach my $line (@lines) {
+		if ($line=~/^\+\+\+\s+(\S+)/) {
+			$setup_docs = 0;
+			if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
+				$setup_docs = 1;
+			}
+			next;
+		}
+
+		if ($setup_docs && $line =~ /^\+/) {
+			push(@setup_docs, $line);
+		}
+	}
+
+	foreach my $line (@lines) {
+		$linenr++;
+
+		my $rawline = $line;
+
+#extract the filename as it passes
+		if ($line=~/^\+\+\+\s+(\S+)/) {
+			$realfile=$1;
+			$realfile =~ s@^[^/]*/@@;
+			$in_comment = 0;
+			next;
+		}
+#extract the line range in the file after the patch is applied
+		if ($line=~/^\@\@ -\d+,\d+ \+(\d+)(,(\d+))? \@\@/) {
+			$is_patch = 1;
+			$first_line = $linenr + 1;
+			$in_comment = 0;
+			$realline=$1-1;
+			if (defined $2) {
+				$realcnt=$3+1;
+			} else {
+				$realcnt=1+1;
+			}
+			next;
+		}
+
+# track the line number as we move through the hunk, note that
+# new versions of GNU diff omit the leading space on completely
+# blank context lines so we need to count that too.
+		if ($line =~ /^( |\+|$)/) {
+			$realline++;
+			$realcnt-- if ($realcnt != 0);
+
+			# track any sort of multi-line comment.  Obviously if
+			# the added text or context do not include the whole
+			# comment we will not see it. Such is life.
+			#
+			# Guestimate if this is a continuing comment.  If this
+			# is the start of a diff block and this line starts
+			# ' *' then it is very likely a comment.
+			if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
+				$in_comment = 1;
+			}
+			if ($line =~ m@/\*@) {
+				$in_comment = 1;
+			}
+			if ($line =~ m@\*/@) {
+				$in_comment = 0;
+			}
+
+			# Measure the line length and indent.
+			($length, $indent) = line_stats($line);
+
+			# Track the previous line.
+			($prevline, $stashline) = ($stashline, $line);
+			($previndent, $stashindent) = ($stashindent, $indent);
+		} elsif ($realcnt == 1) {
+			$realcnt--;
+		}
+
+#make up the handle for any error we report on this line
+		$here = "#$linenr: ";
+		$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
+
+		my $hereline = "$here\n$line\n";
+		my $herecurr = "$here\n$line\n";
+		my $hereprev = "$here\n$prevline\n$line\n";
+
+#check the patch for a signoff:
+		if ($line =~ /^\s*signed-off-by:/i) {
+			# This is a signoff, if ugly, so do not double report.
+			$signoff++;
+			if (!($line =~ /^\s*Signed-off-by:/)) {
+				WARN("Signed-off-by: is the preferred form\n" .
+					$herecurr);
+			}
+			if ($line =~ /^\s*signed-off-by:\S/i) {
+				WARN("need space after Signed-off-by:\n" .
+					$herecurr);
+			}
+		}
+
+# Check for wrappage within a valid hunk of the file
+		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) {
+			ERROR("patch seems to be corrupt (line wrapped?)\n" .
+				$herecurr);
+		}
+
+# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
+		if (($realfile =~ /^$/ || $line =~ /^\+/) &&
+		     !($line =~ m/^(
+				[\x09\x0A\x0D\x20-\x7E]              # ASCII
+				| [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
+				|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
+				| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
+				|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
+				|  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
+				| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
+				|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
+				)*$/x )) {
+			ERROR("Invalid UTF-8\n" . $herecurr);
+		}
+
+#ignore lines being removed
+		if ($line=~/^-/) {next;}
+
+# check we are in a valid source file if not then ignore this hunk
+		next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
+
+#trailing whitespace
+		if ($line =~ /^\+.*\S\s+$/ || $line =~ /^\+\s+$/) {
+			my $herevet = "$here\n" . cat_vet($line) . "\n";
+			ERROR("trailing whitespace\n" . $herevet);
+		}
+#80 column limit
+		if ($line =~ /^\+/ && !($prevline=~/\/\*\*/) && $length > 80) {
+			WARN("line over 80 characters\n" . $herecurr);
+		}
+
+# check we are in a valid source file *.[hc] if not then ignore this hunk
+		next if ($realfile !~ /\.[hc]$/);
+
+# at the beginning of a line any tabs must come first and anything
+# more than 8 must use tabs.
+		if ($line=~/^\+\s* \t\s*\S/ or $line=~/^\+\s*        \s*/) {
+			my $herevet = "$here\n" . cat_vet($line) . "\n";
+			ERROR("use tabs not spaces\n" . $herevet);
+		}
+
+		#
+		# The rest of our checks refer specifically to C style
+		# only apply those _outside_ comments.
+		#
+		next if ($in_comment);
+
+# Remove comments from the line before processing.
+		$line =~ s@/\*.*\*/@@g;
+		$line =~ s@/\*.*@@;
+		$line =~ s@.*\*/@@;
+
+# Standardise the strings and chars within the input to simplify matching.
+		$line = sanitise_line($line);
+
+#
+# Checks which may be anchored in the context.
+#
+
+# Check for switch () and associated case and default
+# statements should be at the same indent.
+		if ($line=~/\bswitch\s*\(.*\)/) {
+			my $err = '';
+			my $sep = '';
+			my @ctx = ctx_block_outer($linenr, $realcnt);
+			shift(@ctx);
+			for my $ctx (@ctx) {
+				my ($clen, $cindent) = line_stats($ctx);
+				if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
+							$indent != $cindent) {
+					$err .= "$sep$ctx\n";
+					$sep = '';
+				} else {
+					$sep = "[...]\n";
+				}
+			}
+			if ($err ne '') {
+				ERROR("switch and case should be at the same indent\n$hereline\n$err\n");
+			}
+		}
+
+# if/while/etc brace do not go on next line, unless defining a do while loop,
+# or if that brace on the next line is for something else
+		if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
+			my @ctx = ctx_statement($linenr, $realcnt);
+			my $ctx_ln = $linenr + $#ctx + 1;
+			my $ctx_cnt = $realcnt - $#ctx - 1;
+			my $ctx = join("\n", @ctx);
+
+			while ($ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^-/) {
+				$ctx_ln++;
+				$ctx_cnt--;
+			}
+			##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>";
+
+			if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
+				ERROR("That { should be on the previous line\n" .
+					"$here\n$ctx\n$lines[$ctx_ln - 1]");
+			}
+		}
+
+#ignore lines not being added
+		if ($line=~/^[^\+]/) {next;}
+
+# TEST: allow direct testing of the type matcher.
+		if ($tst_type && $line =~ /^.$Declare$/) {
+			ERROR("TEST: is type $Declare\n" . $herecurr);
+			next;
+		}
+
+#
+# Checks which are anchored on the added line.
+#
+
+# check for malformed paths in #include statements (uses RAW line)
+		if ($rawline =~ m{^.#\s*include\s+[<"](.*)[">]}) {
+			my $path = $1;
+			if ($path =~ m{//}) {
+				ERROR("malformed #include filename\n" .
+					$herecurr);
+			}
+			# Sanitise this special form of string.
+			$path = 'X' x length($path);
+			$line =~ s{\<.*\>}{<$path>};
+		}
+
+# no C99 // comments
+		if ($line =~ m{//}) {
+			ERROR("do not use C99 // comments\n" . $herecurr);
+		}
+		# Remove C99 comments.
+		$line =~ s@//.*@@;
+
+#EXPORT_SYMBOL should immediately follow its function closing }.
+		if (($line =~ /EXPORT_SYMBOL.*\((.*)\)/) ||
+		    ($line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+			my $name = $1;
+			if (($prevline !~ /^}/) &&
+			   ($prevline !~ /^\+}/) &&
+			   ($prevline !~ /^ }/) &&
+			   ($prevline !~ /\s$name(?:\s+$Attribute)?\s*(?:;|=)/)) {
+				WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
+			}
+		}
+
+# check for static initialisers.
+		if ($line=~/\s*static\s.*=\s+(0|NULL);/) {
+			ERROR("do not initialise statics to 0 or NULL\n" .
+				$herecurr);
+		}
+
+# check for new typedefs, only function parameters and sparse annotations
+# make sense.
+		if ($line =~ /\btypedef\s/ &&
+		    $line !~ /\btypedef\s+$Type\s+\(\s*\*$Ident\s*\)\s*\(/ &&
+		    $line !~ /\b__bitwise(?:__|)\b/) {
+			WARN("do not add new typedefs\n" . $herecurr);
+		}
+
+# * goes on variable not on type
+		if ($line =~ m{\($NonptrType(\*+)(?:\s+const)?\)}) {
+			ERROR("\"(foo$1)\" should be \"(foo $1)\"\n" .
+				$herecurr);
+
+		} elsif ($line =~ m{\($NonptrType\s+(\*+)(?!\s+const)\s+\)}) {
+			ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
+				$herecurr);
+
+		} elsif ($line =~ m{$NonptrType(\*+)(?:\s+const)?\s+[A-Za-z\d_]+}) {
+			ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
+				$herecurr);
+
+		} elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+const)\s+[A-Za-z\d_]+}) {
+			ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
+				$herecurr);
+		}
+
+# # no BUG() or BUG_ON()
+# 		if ($line =~ /\b(BUG|BUG_ON)\b/) {
+# 			print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
+# 			print "$herecurr";
+# 			$clean = 0;
+# 		}
+
+# printk should use KERN_* levels.  Note that follow on printk's on the
+# same line do not need a level, so we use the current block context
+# to try and find and validate the current printk.  In summary the current
+# printk includes all preceeding printk's which have no newline on the end.
+# we assume the first bad printk is the one to report.
+		if ($line =~ /\bprintk\((?!KERN_)/) {
+			my $ok = 0;
+			for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
+				#print "CHECK<$lines[$ln - 1]\n";
+				# we have a preceeding printk if it ends
+				# with "\n" ignore it, else it is to blame
+				if ($lines[$ln - 1] =~ m{\bprintk\(}) {
+					if ($rawlines[$ln - 1] !~ m{\\n"}) {
+						$ok = 1;
+					}
+					last;
+				}
+			}
+			if ($ok == 0) {
+				WARN("printk() should include KERN_ facility level\n" . $herecurr);
+			}
+		}
+
+# function brace can't be on same line, except for #defines of do while,
+# or if closed on same line
+		if (($line=~/$Type\s*[A-Za-z\d_]+\(.*\).* {/) and
+		    !($line=~/\#define.*do\s{/) and !($line=~/}/)) {
+			ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
+		}
+
+# Check operator spacing.
+		# Note we expand the line with the leading + as the real
+		# line will be displayed with the leading + and the tabs
+		# will therefore also expand that way.
+		my $opline = $line;
+		$opline = expand_tabs($opline);
+		$opline =~ s/^./ /;
+		if (!($line=~/\#\s*include/)) {
+			my @elements = split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/, $opline);
+			my $off = 0;
+			for (my $n = 0; $n < $#elements; $n += 2) {
+				$off += length($elements[$n]);
+
+				my $a = '';
+				$a = 'V' if ($elements[$n] ne '');
+				$a = 'W' if ($elements[$n] =~ /\s$/);
+				$a = 'B' if ($elements[$n] =~ /(\[|\()$/);
+				$a = 'O' if ($elements[$n] eq '');
+				$a = 'E' if ($elements[$n] eq '' && $n == 0);
+
+				my $op = $elements[$n + 1];
+
+				my $c = '';
+				if (defined $elements[$n + 2]) {
+					$c = 'V' if ($elements[$n + 2] ne '');
+					$c = 'W' if ($elements[$n + 2] =~ /^\s/);
+					$c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
+					$c = 'O' if ($elements[$n + 2] eq '');
+				} else {
+					$c = 'E';
+				}
+
+				# Pick up the preceeding and succeeding characters.
+				my $ca = substr($opline, 0, $off);
+				my $cc = '';
+				if (length($opline) >= ($off + length($elements[$n + 1]))) {
+					$cc = substr($opline, $off + length($elements[$n + 1]));
+				}
+				my $cb = "$ca$;$cc";
+
+				my $ctx = "${a}x${c}";
+
+				my $at = "(ctx:$ctx)";
+
+				my $ptr = (" " x $off) . "^";
+				my $hereptr = "$hereline$ptr\n";
+
+				##print "<$s1:$op:$s2> <$elements[$n]:$elements[$n + 1]:$elements[$n + 2]>\n";
+
+				# ; should have either the end of line or a space or \ after it
+				if ($op eq ';') {
+					if ($ctx !~ /.x[WEB]/ && $cc !~ /^\\/ &&
+					    $cc !~ /^;/) {
+						ERROR("need space after that '$op' $at\n" . $hereptr);
+					}
+
+				# // is a comment
+				} elsif ($op eq '//') {
+
+				# -> should have no spaces
+				} elsif ($op eq '->') {
+					if ($ctx =~ /Wx.|.xW/) {
+						ERROR("no spaces around that '$op' $at\n" . $hereptr);
+					}
+
+				# , must have a space on the right.
+				} elsif ($op eq ',') {
+					if ($ctx !~ /.xW|.xE/ && $cc !~ /^}/) {
+						ERROR("need space after that '$op' $at\n" . $hereptr);
+					}
+
+				# unary ! and unary ~ are allowed no space on the right
+				} elsif ($op eq '!' or $op eq '~') {
+					if ($ctx !~ /[WOEB]x./) {
+						ERROR("need space before that '$op' $at\n" . $hereptr);
+					}
+					if ($ctx =~ /.xW/) {
+						ERROR("no space after that '$op' $at\n" . $hereptr);
+					}
+
+				# unary ++ and unary -- are allowed no space on one side.
+				} elsif ($op eq '++' or $op eq '--') {
+					if ($ctx !~ /[WOB]x[^W]/ && $ctx !~ /[^W]x[WOBE]/) {
+						ERROR("need space one side of that '$op' $at\n" . $hereptr);
+					}
+					if ($ctx =~ /Wx./ && $cc =~ /^;/) {
+						ERROR("no space before that '$op' $at\n" . $hereptr);
+					}
+
+				# & is both unary and binary
+				# unary:
+				# 	a &b
+				# binary (consistent spacing):
+				#	a&b		OK
+				#	a & b		OK
+				#
+				# boiling down to: if there is a space on the right then there
+				# should be one on the left.
+				#
+				# - is the same
+				#
+				} elsif ($op eq '&' or $op eq '-') {
+					if ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]/) {
+						ERROR("need space before that '$op' $at\n" . $hereptr);
+					}
+
+				# * is the same as & only adding:
+				# type:
+				# 	(foo *)
+				#	(foo **)
+				#
+				} elsif ($op eq '*') {
+					if ($ca !~ /$Type$/ && $cb !~ /(\*$;|$;\*)/ &&
+					    $ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB|BxB/) {
+						ERROR("need space before that '$op' $at\n" . $hereptr);
+					}
+
+				# << and >> may either have or not have spaces both sides
+				} elsif ($op eq '<<' or $op eq '>>' or $op eq '+' or $op eq '/' or
+					 $op eq '^' or $op eq '|')
+				{
+					if ($ctx !~ /VxV|WxW|VxE|WxE/) {
+						ERROR("need consistent spacing around '$op' $at\n" .
+							$hereptr);
+					}
+
+				# All the others need spaces both sides.
+				} elsif ($ctx !~ /[EW]x[WE]/) {
+					ERROR("need spaces around that '$op' $at\n" . $hereptr);
+				}
+				$off += length($elements[$n + 1]);
+			}
+		}
+
+#need space before brace following if, while, etc
+		if ($line =~ /\(.*\){/ || $line =~ /do{/) {
+			ERROR("need a space before the open brace '{'\n" . $herecurr);
+		}
+
+# closing brace should have a space following it when it has anything
+# on the line
+		if ($line =~ /}(?!(?:,|;|\)))\S/) {
+			ERROR("need a space after that close brace '}'\n" . $herecurr);
+		}
+
+#goto labels aren't indented, allow a single space however
+		if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
+		   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
+			WARN("labels should not be indented\n" . $herecurr);
+		}
+
+# Need a space before open parenthesis after if, while etc
+		if ($line=~/\b(if|while|for|switch)\(/) {
+			ERROR("need a space before the open parenthesis '('\n" . $herecurr);
+		}
+
+# Check for illegal assignment in if conditional.
+		if ($line=~/\bif\s*\(.*[^<>!=]=[^=].*\)/) {
+			#next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
+			ERROR("do not use assignment in if condition\n" . $herecurr);
+		}
+
+		# Check for }<nl>else {, these must be at the same
+		# indent level to be relevant to each other.
+		if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
+						$previndent == $indent) {
+			ERROR("else should follow close brace '}'\n" . $hereprev);
+		}
+
+#studly caps, commented out until figure out how to distinguish between use of existing and adding new
+#		if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
+#		    print "No studly caps, use _\n";
+#		    print "$herecurr";
+#		    $clean = 0;
+#		}
+
+#no spaces allowed after \ in define
+		if ($line=~/\#define.*\\\s$/) {
+			WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr);
+		}
+
+#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
+		if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
+			my $checkfile = "include/linux/$1.h";
+			if (-f $checkfile) {
+				CHK("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
+					$herecurr);
+			}
+		}
+
+# if and else should not have general statements after it
+		if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/ &&
+		    $1 !~ /^\s*(?:\sif|{|\\|$)/) {
+			ERROR("trailing statements should be on next line\n" . $herecurr);
+		}
+
+# multi-statement macros should be enclosed in a do while loop, grab the
+# first statement and ensure its the whole macro if its not enclosed
+# in a known goot container
+		if (($prevline=~/\#define.*\\/) and
+		   !($prevline=~/do\s+{/) and !($prevline=~/\(\{/) and
+		   !($line=~/do.*{/) and !($line=~/\(\{/) and
+		   !($line=~/^.\s*$Declare\s/)) {
+			# Grab the first statement, if that is the entire macro
+			# its ok.  This may start either on the #define line
+			# or the one below.
+			my $ln = $linenr;
+			my $cnt = $realcnt;
+
+			# If the macro starts on the define line start there.
+			if ($prevline !~ m{^.#\s*define\s*$Ident(?:\([^\)]*\))?\s*\\\s*$}) {
+				$ln--;
+				$cnt++;
+			}
+			my @ctx = ctx_statement($ln, $cnt);
+			my $ctx_ln = $ln + $#ctx + 1;
+			my $ctx = join("\n", @ctx);
+
+			# Pull in any empty extension lines.
+			while ($ctx =~ /\\$/ &&
+			       $lines[$ctx_ln - 1] =~ /^.\s*(?:\\)?$/) {
+				$ctx .= $lines[$ctx_ln - 1];
+				$ctx_ln++;
+			}
+
+			if ($ctx =~ /\\$/) {
+				if ($ctx =~ /;/) {
+					ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
+				} else {
+					ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
+				}
+			}
+		}
+
+# don't include deprecated include files (uses RAW line)
+		for my $inc (@dep_includes) {
+			if ($rawline =~ m@\#\s*include\s*\<$inc>@) {
+				ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
+			}
+		}
+
+# don't use deprecated functions
+		for my $func (@dep_functions) {
+			if ($line =~ /\b$func\b/) {
+				ERROR("Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr);
+			}
+		}
+
+# no volatiles please
+		if ($line =~ /\bvolatile\b/ && $line !~ /\basm\s+volatile\b/) {
+			WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
+		}
+
+# warn about #if 0
+		if ($line =~ /^.#\s*if\s+0\b/) {
+			CHK("if this code is redundant consider removing it\n" .
+				$herecurr);
+		}
+
+# warn about #ifdefs in C files
+#		if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
+#			print "#ifdef in C files should be avoided\n";
+#			print "$herecurr";
+#			$clean = 0;
+#		}
+
+# check for spinlock_t definitions without a comment.
+		if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
+			my $which = $1;
+			if (!ctx_has_comment($first_line, $linenr)) {
+				CHK("$1 definition without comment\n" . $herecurr);
+			}
+		}
+# check for memory barriers without a comment.
+		if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
+			if (!ctx_has_comment($first_line, $linenr)) {
+				CHK("memory barrier without comment\n" . $herecurr);
+			}
+		}
+# check of hardware specific defines
+		if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@) {
+			CHK("architecture specific defines should be avoided\n" .  $herecurr);
+		}
+
+# check the location of the inline attribute, that it is between
+# storage class and type.
+		if ($line =~ /$Type\s+(?:inline|__always_inline)\b/ ||
+		    $line =~ /\b(?:inline|always_inline)\s+$Storage/) {
+			ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
+		}
+
+# check for new externs in .c files.
+		if ($line =~ /^.\s*extern\s/ && ($realfile =~ /\.c$/)) {
+			WARN("externs should be avoided in .c files\n" .  $herecurr);
+		}
+
+# checks for new __setup's
+		if ($rawline =~ /\b__setup\("([^"]*)"/) {
+			my $name = $1;
+
+			if (!grep(/$name/, @setup_docs)) {
+				CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
+			}
+		}
+	}
+
+	if ($chk_patch && !$is_patch) {
+		ERROR("Does not appear to be a unified-diff format patch\n");
+	}
+	if ($is_patch && $chk_signoff && $signoff == 0) {
+		ERROR("Missing Signed-off-by: line(s)\n");
+	}
+
+	if ($clean == 1 && $quiet == 0) {
+		print "Your patch has no obvious style problems and is ready for submission.\n"
+	}
+	if ($clean == 0 && $quiet == 0) {
+		print "Your patch has style problems, please review.  If any of these errors\n";
+		print "are false positives report them to the maintainer, see\n";
+		print "CHECKPATCH in MAINTAINERS.\n";
+	}
+	return $clean;
+}
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index f98171f..0dcc01c 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -99,6 +99,11 @@
 #define __IGNORE_setfsuid32
 #define __IGNORE_setfsgid32
 
+/* sync_file_range had a stupid ABI. Allow sync_file_range2 instead */
+#ifdef __NR_sync_file_range2
+#define __IGNORE_sync_file_range
+#endif
+
 /* Unmerged syscalls for AFS, STREAMS, etc. */
 #define __IGNORE_afs_syscall
 #define __IGNORE_getpmsg
diff --git a/scripts/decodecode b/scripts/decodecode
new file mode 100644
index 0000000..1e1a8f6
--- /dev/null
+++ b/scripts/decodecode
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Disassemble the Code: line in Linux oopses
+# usage: decodecode < oops.file
+#
+# options: set env. variable AFLAGS=options to pass options to "as";
+# e.g., to decode an i386 oops on an x86_64 system, use:
+# AFLAGS=--32 decodecode < 386.oops
+
+T=`mktemp`
+code=
+
+while read i ; do
+
+case "$i" in
+*Code:*)
+	code=$i
+	;;
+esac
+
+done
+
+if [ -z "$code" ]; then
+	exit
+fi
+
+echo $code
+code=`echo $code | sed -e 's/.*Code: //'`
+
+marker=`expr index "$code" "\<"`
+if [ $marker -eq 0 ]; then
+	marker=`expr index "$code" "\("`
+fi
+
+if [ $marker -ne 0 ]; then
+	beforemark=`echo "$code" | cut -c-$((${marker} - 1))`
+	echo -n "	.byte 0x" > $T.s
+	echo $beforemark | sed -e 's/ /,0x/g' >> $T.s
+	as $AFLAGS -o $T.o $T.s
+	objdump -S $T.o
+	rm $T.o $T.s
+
+# and fix code at-and-after marker
+	code=`echo "$code" | cut -c$((${marker} + 1))-`
+fi
+
+code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g'`
+echo -n "	.byte 0x" > $T.s
+echo $code >> $T.s
+as $AFLAGS -o $T.o $T.s
+objdump -S $T.o
+rm $T.o $T.s
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 8b809b2..10b0066 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -31,7 +31,7 @@
 #include <string.h>
 #include <ctype.h>
 
-#define KSYM_NAME_LEN		127
+#define KSYM_NAME_LEN		128
 
 
 struct sym_entry {
@@ -254,7 +254,7 @@
 	unsigned int i, k, off;
 	unsigned int best_idx[256];
 	unsigned int *markers;
-	char buf[KSYM_NAME_LEN+1];
+	char buf[KSYM_NAME_LEN];
 
 	printf("#include <asm/types.h>\n");
 	printf("#if BITS_PER_LONG == 64\n");
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index 120d624..cdca738 100644
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -4,21 +4,15 @@
 # What library to link
 ldflags()
 {
-	$cc -print-file-name=libncursesw.so | grep -q /
-	if [ $? -eq 0 ]; then
-		echo '-lncursesw'
-		exit
-	fi
-	$cc -print-file-name=libncurses.so | grep -q /
-	if [ $? -eq 0 ]; then
-		echo '-lncurses'
-		exit
-	fi
-	$cc -print-file-name=libcurses.so | grep -q /
-	if [ $? -eq 0 ]; then
-		echo '-lcurses'
-		exit
-	fi
+	for ext in so a dylib ; do
+		for lib in ncursesw ncurses curses ; do
+			$cc -print-file-name=lib${lib}.${ext} | grep -q /
+			if [ $? -eq 0 ]; then
+				echo "-l${lib}"
+				exit
+			fi
+		done
+	done
 	exit 1
 }
 
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index ed1244d..f646381 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -353,11 +353,16 @@
 
 static int do_of_entry (const char *filename, struct of_device_id *of, char *alias)
 {
+    int len;
     char *tmp;
-    sprintf (alias, "of:N%sT%sC%s",
+    len = sprintf (alias, "of:N%sT%s",
                     of->name[0] ? of->name : "*",
-                    of->type[0] ? of->type : "*",
-                    of->compatible[0] ? of->compatible : "*");
+                    of->type[0] ? of->type : "*");
+
+    if (of->compatible[0])
+        sprintf (&alias[len], "%sC%s",
+                     of->type[0] ? "*" : "",
+                     of->compatible);
 
     /* Replace all whitespace with underscores */
     for (tmp = alias; tmp && *tmp; tmp++)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 113dc77..3645e98 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -582,6 +582,12 @@
 
 /**
  * Whitelist to allow certain references to pass with no warning.
+ *
+ * Pattern 0:
+ *   Do not warn if funtion/data are marked with __init_refok/__initdata_refok.
+ *   The pattern is identified by:
+ *   fromsec = .text.init.refok | .data.init.refok
+ *
  * Pattern 1:
  *   If a module parameter is declared __initdata and permissions=0
  *   then this is legal despite the warning generated.
@@ -619,14 +625,6 @@
  *   This pattern is identified by
  *   refsymname = __init_begin, _sinittext, _einittext
  *
- * Pattern 6:
- *   During the early init phase we have references from .init.text to
- *   .text we have an intended section mismatch - do not warn about it.
- *   See kernel_init() in init/main.c
- *   tosec   = .init.text
- *   fromsec = .text
- *   atsym = kernel_init
- *
  * Pattern 7:
  *  Logos used in drivers/video/logo reside in __initdata but the
  *  funtion that references them are EXPORT_SYMBOL() so cannot be
@@ -642,16 +640,11 @@
  *  tosec   = .init.text
  *  fromsec  = .paravirtprobe
  *
- * Pattern 9:
- *  Some of functions are common code between boot time and hotplug
- *  time. The bootmem allocater is called only boot time in its
- *  functions. So it's ok to reference.
- *  tosec    = .init.text
- *
  * Pattern 10:
- *  ia64 has machvec table for each platform. It is mixture of function
- *  pointer of .init.text and .text.
- *  fromsec  = .machvec
+ *  ia64 has machvec table for each platform and
+ *  powerpc has a machine desc table for each platform.
+ *  It is mixture of function pointers of .init.text and .text.
+ *  fromsec  = .machvec | .machine.desc
  **/
 static int secref_whitelist(const char *modname, const char *tosec,
 			    const char *fromsec, const char *atsym,
@@ -678,11 +671,10 @@
 		NULL
 	};
 
-	const char *pat4sym[] = {
-		"sparse_index_alloc",
-		"zone_wait_table_init",
-		NULL
-	};
+	/* Check for pattern 0 */
+	if ((strcmp(fromsec, ".text.init.refok") == 0) ||
+	    (strcmp(fromsec, ".data.init.refok") == 0))
+		return 1;
 
 	/* Check for pattern 1 */
 	if (strcmp(tosec, ".init.data") != 0)
@@ -725,12 +717,6 @@
 		if (strcmp(refsymname, *s) == 0)
 			return 1;
 
-	/* Check for pattern 6 */
-	if ((strcmp(tosec, ".init.text") == 0) &&
-	    (strcmp(fromsec, ".text") == 0) &&
-	    (strcmp(refsymname, "kernel_init") == 0))
-		return 1;
-
 	/* Check for pattern 7 */
 	if ((strcmp(tosec, ".init.data") == 0) &&
 	    (strncmp(fromsec, ".text", strlen(".text")) == 0) &&
@@ -742,15 +728,9 @@
 	    (strcmp(fromsec, ".paravirtprobe") == 0))
 		return 1;
 
-	/* Check for pattern 9 */
-	if ((strcmp(tosec, ".init.text") == 0) &&
-	    (strcmp(fromsec, ".text") == 0))
-		for (s = pat4sym; *s; s++)
-			if (strcmp(atsym, *s) == 0)
-				return 1;
-
 	/* Check for pattern 10 */
-	if (strcmp(fromsec, ".machvec") == 0)
+	if ((strcmp(fromsec, ".machvec") == 0) ||
+	    (strcmp(fromsec, ".machine.desc") == 0))
 		return 1;
 
 	return 0;
@@ -884,30 +864,34 @@
 			     elf->strtab + before->st_name, refsymname))
 		return;
 
+	/* fromsec whitelist - without a valid 'before'
+	 * powerpc has a GOT table in .got2 section */
+	if (strcmp(fromsec, ".got2") == 0)
+		return;
+
 	if (before && after) {
-		warn("%s - Section mismatch: reference to %s:%s from %s "
-		     "between '%s' (at offset 0x%llx) and '%s'\n",
-		     modname, secname, refsymname, fromsec,
+		warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
+		     "(between '%s' and '%s')\n",
+		     modname, fromsec, (unsigned long long)r.r_offset,
+		     secname, refsymname,
 		     elf->strtab + before->st_name,
-		     (long long)r.r_offset,
 		     elf->strtab + after->st_name);
 	} else if (before) {
-		warn("%s - Section mismatch: reference to %s:%s from %s "
-		     "after '%s' (at offset 0x%llx)\n",
-		     modname, secname, refsymname, fromsec,
-		     elf->strtab + before->st_name,
-		     (long long)r.r_offset);
+		warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
+		     "(after '%s')\n",
+		     modname, fromsec, (unsigned long long)r.r_offset,
+		     secname, refsymname,
+		     elf->strtab + before->st_name);
 	} else if (after) {
-		warn("%s - Section mismatch: reference to %s:%s from %s "
+		warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
 		     "before '%s' (at offset -0x%llx)\n",
-		     modname, secname, refsymname, fromsec,
-		     elf->strtab + after->st_name,
-		     (long long)r.r_offset);
+		     modname, fromsec, (unsigned long long)r.r_offset,
+		     secname, refsymname,
+		     elf->strtab + after->st_name);
 	} else {
-		warn("%s - Section mismatch: reference to %s:%s from %s "
-		     "(offset 0x%llx)\n",
-		     modname, secname, fromsec, refsymname,
-		     (long long)r.r_offset);
+		warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n",
+		     modname, fromsec, (unsigned long long)r.r_offset,
+		     secname, refsymname);
 	}
 }
 
@@ -1068,6 +1052,7 @@
 		".plt",  /* seen on ARCH=um build on x86_64. Harmless */
 		"__ftr_fixup",		/* powerpc cpu feature fixup */
 		"__fw_ftr_fixup",	/* powerpc firmware feature fixup */
+		".cranges",	/* used by sh64 */
 		NULL
 	};
 	/* Start of section names */
@@ -1148,6 +1133,7 @@
 		".fixup",
 		".smp_locks",
 		".plt",  /* seen on ARCH=um build on x86_64. Harmless */
+		".cranges",	/* used by sh64 */
 		NULL
 	};
 	/* Start of section names */
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 6873d5a..d9cc690 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -7,6 +7,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <string.h>
+#include <limits.h>
 #include "modpost.h"
 
 /*
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index 88b5281..aa0ccdb 100644
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -69,8 +69,8 @@
 # Install arch-specific kernel image(s)
 #
 case "${ARCH}" in
-	i386)
-		[ -f "${objtree}/arch/i386/boot/bzImage" ] && cp -v -- "${objtree}/arch/i386/boot/bzImage" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}"
+	i386|x86_64)
+		[ -f "${objtree}/arch/$ARCH/boot/bzImage" ] && cp -v -- "${objtree}/arch/$ARCH/boot/bzImage" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}"
 		;;
 	alpha)
 		[ -f "${objtree}/arch/alpha/boot/vmlinux.gz" ] && cp -v -- "${objtree}/arch/alpha/boot/vmlinux.gz" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}"
diff --git a/security/dummy.c b/security/dummy.c
index 8ffd764..d6a112c 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -420,8 +420,12 @@
 
 static int dummy_file_mmap (struct file *file, unsigned long reqprot,
 			    unsigned long prot,
-			    unsigned long flags)
+			    unsigned long flags,
+			    unsigned long addr,
+			    unsigned long addr_only)
 {
+	if (addr < mmap_min_addr)
+		return -EACCES;
 	return 0;
 }
 
diff --git a/security/security.c b/security/security.c
index fc8601b..27e5863 100644
--- a/security/security.c
+++ b/security/security.c
@@ -24,6 +24,7 @@
 extern void security_fixup_ops(struct security_operations *ops);
 
 struct security_operations *security_ops;	/* Initialized to NULL */
+unsigned long mmap_min_addr;		/* 0 means no protection */
 
 static inline int verify(struct security_operations *ops)
 {
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index e4396a8..78c408f 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -586,7 +586,7 @@
 				}
 			}
 			if (inode)
-				audit_log_format(ab, " dev=%s ino=%ld",
+				audit_log_format(ab, " dev=%s ino=%lu",
 						 inode->i_sb->s_id,
 						 inode->i_ino);
 			break;
@@ -832,6 +832,7 @@
  * @tsid: target security identifier
  * @tclass: target security class
  * @requested: requested permissions, interpreted based on @tclass
+ * @flags:  AVC_STRICT or 0
  * @avd: access vector decisions
  *
  * Check the AVC to determine whether the @requested permissions are granted
@@ -846,8 +847,9 @@
  * should be released for the auditing.
  */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
-                         u16 tclass, u32 requested,
-                         struct av_decision *avd)
+			 u16 tclass, u32 requested,
+			 unsigned flags,
+			 struct av_decision *avd)
 {
 	struct avc_node *node;
 	struct avc_entry entry, *p_ae;
@@ -874,7 +876,7 @@
 	denied = requested & ~(p_ae->avd.allowed);
 
 	if (!requested || denied) {
-		if (selinux_enforcing)
+		if (selinux_enforcing || (flags & AVC_STRICT))
 			rc = -EACCES;
 		else
 			if (node)
@@ -909,7 +911,7 @@
 	struct av_decision avd;
 	int rc;
 
-	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
+	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
 	avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
 	return rc;
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ad8dd4e..520b999 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1592,9 +1592,10 @@
 	rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
 	if (rc == 0)
 		rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
-					SECCLASS_CAPABILITY,
-					CAP_TO_MASK(CAP_SYS_ADMIN),
-					NULL);
+					  SECCLASS_CAPABILITY,
+					  CAP_TO_MASK(CAP_SYS_ADMIN),
+					  0,
+					  NULL);
 
 	if (rc == 0)
 		cap_sys_admin = 1;
@@ -2317,7 +2318,7 @@
 	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
 		return -EOPNOTSUPP;
 
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+	if (!is_owner_or_cap(inode))
 		return -EPERM;
 
 	AVC_AUDIT_DATA_INIT(&ad,FS);
@@ -2568,12 +2569,16 @@
 }
 
 static int selinux_file_mmap(struct file *file, unsigned long reqprot,
-			     unsigned long prot, unsigned long flags)
+			     unsigned long prot, unsigned long flags,
+			     unsigned long addr, unsigned long addr_only)
 {
-	int rc;
+	int rc = 0;
+	u32 sid = ((struct task_security_struct*)(current->security))->sid;
 
-	rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
-	if (rc)
+	if (addr < mmap_min_addr)
+		rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
+				  MEMPROTECT__MMAP_ZERO, NULL);
+	if (rc || addr_only)
 		return rc;
 
 	if (selinux_checkreqprot)
@@ -4626,7 +4631,7 @@
 		if (p->ptrace & PT_PTRACED) {
 			error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
 						     SECCLASS_PROCESS,
-						     PROCESS__PTRACE, &avd);
+						     PROCESS__PTRACE, 0, &avd);
 			if (!error)
 				tsec->sid = sid;
 			task_unlock(p);
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index b83e740..049bf69 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -158,3 +158,4 @@
    S_(SECCLASS_KEY, KEY__CREATE, "create")
    S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
    S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
+   S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 5fee173..eda89a2 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -823,3 +823,4 @@
 #define DCCP_SOCKET__NAME_BIND                    0x00200000UL
 #define DCCP_SOCKET__NODE_BIND                    0x00400000UL
 #define DCCP_SOCKET__NAME_CONNECT                 0x00800000UL
+#define MEMPROTECT__MMAP_ZERO                     0x00000001UL
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 6ed10c3..e145f6e 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -102,9 +102,11 @@
                u16 tclass, u32 requested,
                struct av_decision *avd, int result, struct avc_audit_data *auditdata);
 
+#define AVC_STRICT 1 /* Ignore permissive mode. */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
-                         u16 tclass, u32 requested,
-                         struct av_decision *avd);
+			 u16 tclass, u32 requested,
+			 unsigned flags,
+			 struct av_decision *avd);
 
 int avc_has_perm(u32 ssid, u32 tsid,
                  u16 tclass, u32 requested,
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index 3787990..e77de0e 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -63,3 +63,4 @@
     S_("key")
     S_(NULL)
     S_("dccp_socket")
+    S_("memprotect")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index 35f309f..a9c2b20 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -49,6 +49,7 @@
 #define SECCLASS_PACKET                                  57
 #define SECCLASS_KEY                                     58
 #define SECCLASS_DCCP_SOCKET                             60
+#define SECCLASS_MEMPROTECT                              61
 
 /*
  * Security identifier indices for initial entities
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index b94378a..83bdd4d 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -41,6 +41,7 @@
 
 int security_load_policy(void * data, size_t len);
 
+#define SEL_VEC_MAX 32
 struct av_decision {
 	u32 allowed;
 	u32 decided;
@@ -87,6 +88,9 @@
 
 int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
 
+int security_get_classes(char ***classes, int *nclasses);
+int security_get_permissions(char *class, char ***perms, int *nperms);
+
 #define SECURITY_FS_USE_XATTR		1 /* use xattr */
 #define SECURITY_FS_USE_TRANS		2 /* use transition SIDs, e.g. devpts/tmpfs */
 #define SECURITY_FS_USE_TASK		3 /* use task SIDs, e.g. pipefs/sockfs */
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index bf87507..e64eca2 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -36,8 +36,8 @@
 #include "security.h"
 
 /**
- * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
- * @sock: the socket to label
+ * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
+ * @sk: the socket to label
  * @sid: the SID to use
  *
  * Description:
@@ -47,17 +47,17 @@
  * this function and rcu_read_unlock() after this function returns.
  *
  */
-static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
+static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
 {
 	int rc;
-	struct sk_security_struct *sksec = sock->sk->sk_security;
+	struct sk_security_struct *sksec = sk->sk_security;
 	struct netlbl_lsm_secattr secattr;
 
 	rc = security_netlbl_sid_to_secattr(sid, &secattr);
 	if (rc != 0)
 		return rc;
 
-	rc = netlbl_socket_setattr(sock, &secattr);
+	rc = netlbl_sock_setattr(sk, &secattr);
 	if (rc == 0) {
 		spin_lock_bh(&sksec->nlbl_lock);
 		sksec->nlbl_state = NLBL_LABELED;
@@ -206,7 +206,7 @@
 	/* Try to set the NetLabel on the socket to save time later, if we fail
 	 * here we will pick up the pieces in later calls to
 	 * selinux_netlbl_inode_permission(). */
-	selinux_netlbl_socket_setsid(sock, sksec->sid);
+	selinux_netlbl_sock_setsid(sk, sksec->sid);
 
 	rcu_read_unlock();
 }
@@ -223,14 +223,15 @@
 int selinux_netlbl_socket_post_create(struct socket *sock)
 {
 	int rc = 0;
+	struct sock *sk = sock->sk;
 	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
-	struct sk_security_struct *sksec = sock->sk->sk_security;
+	struct sk_security_struct *sksec = sk->sk_security;
 
 	sksec->sclass = isec->sclass;
 
 	rcu_read_lock();
 	if (sksec->nlbl_state == NLBL_REQUIRE)
-		rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
+		rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
 	rcu_read_unlock();
 
 	return rc;
@@ -251,14 +252,16 @@
 int selinux_netlbl_inode_permission(struct inode *inode, int mask)
 {
 	int rc;
-	struct sk_security_struct *sksec;
+	struct sock *sk;
 	struct socket *sock;
+	struct sk_security_struct *sksec;
 
 	if (!S_ISSOCK(inode->i_mode) ||
 	    ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
 		return 0;
 	sock = SOCKET_I(inode);
-	sksec = sock->sk->sk_security;
+	sk = sock->sk;
+	sksec = sk->sk_security;
 
 	rcu_read_lock();
 	if (sksec->nlbl_state != NLBL_REQUIRE) {
@@ -266,9 +269,9 @@
 		return 0;
 	}
 	local_bh_disable();
-	bh_lock_sock_nested(sock->sk);
-	rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
-	bh_unlock_sock(sock->sk);
+	bh_lock_sock_nested(sk);
+	rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
+	bh_unlock_sock(sk);
 	local_bh_enable();
 	rcu_read_unlock();
 
@@ -345,14 +348,17 @@
 				     int optname)
 {
 	int rc = 0;
-	struct sk_security_struct *sksec = sock->sk->sk_security;
+	struct sock *sk = sock->sk;
+	struct sk_security_struct *sksec = sk->sk_security;
 	struct netlbl_lsm_secattr secattr;
 
 	rcu_read_lock();
 	if (level == IPPROTO_IP && optname == IP_OPTIONS &&
 	    sksec->nlbl_state == NLBL_LABELED) {
 		netlbl_secattr_init(&secattr);
-		rc = netlbl_socket_getattr(sock, &secattr);
+		lock_sock(sk);
+		rc = netlbl_sock_getattr(sk, &secattr);
+		release_sock(sk);
 		if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
 			rc = -EACCES;
 		netlbl_secattr_destroy(&secattr);
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index ccfe875..eddc7b4 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -110,6 +110,8 @@
 	{ AUDIT_DEL_RULE,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
 	{ AUDIT_USER,		NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
 	{ AUDIT_SIGNAL_INFO,	NETLINK_AUDIT_SOCKET__NLMSG_READ     },
+	{ AUDIT_TTY_GET,	NETLINK_AUDIT_SOCKET__NLMSG_READ     },
+	{ AUDIT_TTY_SET,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
 };
 
 
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index aca099a..c9e92da 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -67,6 +67,10 @@
 static int bool_num = 0;
 static int *bool_pending_values = NULL;
 
+/* global data for classes */
+static struct dentry *class_dir = NULL;
+static unsigned long last_class_ino;
+
 extern void selnl_notify_setenforce(int val);
 
 /* Check whether a task is allowed to use a security operation. */
@@ -106,6 +110,7 @@
 
 #define SEL_INITCON_INO_OFFSET 	0x01000000
 #define SEL_BOOL_INO_OFFSET	0x02000000
+#define SEL_CLASS_INO_OFFSET	0x04000000
 #define SEL_INO_MASK		0x00ffffff
 
 #define TMPBUFLEN	12
@@ -237,6 +242,11 @@
 
 /* declaration for sel_write_load */
 static int sel_make_bools(void);
+static int sel_make_classes(void);
+
+/* declaration for sel_make_class_dirs */
+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+			unsigned long *ino);
 
 static ssize_t sel_read_mls(struct file *filp, char __user *buf,
 				size_t count, loff_t *ppos)
@@ -287,10 +297,18 @@
 		goto out;
 
 	ret = sel_make_bools();
+	if (ret) {
+		length = ret;
+		goto out1;
+	}
+
+	ret = sel_make_classes();
 	if (ret)
 		length = ret;
 	else
 		length = count;
+
+out1:
 	audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
 		"policy loaded auid=%u",
 		audit_get_loginuid(current->audit_context));
@@ -940,9 +958,8 @@
 	.write          = sel_commit_bools_write,
 };
 
-/* delete booleans - partial revoke() from
- * fs/proc/generic.c proc_kill_inodes */
-static void sel_remove_bools(struct dentry *de)
+/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
+static void sel_remove_entries(struct dentry *de)
 {
 	struct list_head *p, *node;
 	struct super_block *sb = de->d_sb;
@@ -998,7 +1015,7 @@
 	kfree(bool_pending_values);
 	bool_pending_values = NULL;
 
-	sel_remove_bools(dir);
+	sel_remove_entries(dir);
 
 	if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
 		return -ENOMEM;
@@ -1048,7 +1065,7 @@
 	return ret;
 err:
 	kfree(values);
-	sel_remove_bools(dir);
+	sel_remove_entries(dir);
 	ret = -ENOMEM;
 	goto out;
 }
@@ -1294,7 +1311,227 @@
 	return ret;
 }
 
-static int sel_make_dir(struct inode *dir, struct dentry *dentry)
+static inline unsigned int sel_div(unsigned long a, unsigned long b)
+{
+	return a / b - (a % b < 0);
+}
+
+static inline unsigned long sel_class_to_ino(u16 class)
+{
+	return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
+}
+
+static inline u16 sel_ino_to_class(unsigned long ino)
+{
+	return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
+}
+
+static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
+{
+	return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
+}
+
+static inline u32 sel_ino_to_perm(unsigned long ino)
+{
+	return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
+}
+
+static ssize_t sel_read_class(struct file * file, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	ssize_t rc, len;
+	char *page;
+	unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+
+	page = (char *)__get_free_page(GFP_KERNEL);
+	if (!page) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino));
+	rc = simple_read_from_buffer(buf, count, ppos, page, len);
+	free_page((unsigned long)page);
+out:
+	return rc;
+}
+
+static const struct file_operations sel_class_ops = {
+	.read		= sel_read_class,
+};
+
+static ssize_t sel_read_perm(struct file * file, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	ssize_t rc, len;
+	char *page;
+	unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+
+	page = (char *)__get_free_page(GFP_KERNEL);
+	if (!page) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
+	rc = simple_read_from_buffer(buf, count, ppos, page, len);
+	free_page((unsigned long)page);
+out:
+	return rc;
+}
+
+static const struct file_operations sel_perm_ops = {
+	.read		= sel_read_perm,
+};
+
+static int sel_make_perm_files(char *objclass, int classvalue,
+				struct dentry *dir)
+{
+	int i, rc = 0, nperms;
+	char **perms;
+
+	rc = security_get_permissions(objclass, &perms, &nperms);
+	if (rc)
+		goto out;
+
+	for (i = 0; i < nperms; i++) {
+		struct inode *inode;
+		struct dentry *dentry;
+
+		dentry = d_alloc_name(dir, perms[i]);
+		if (!dentry) {
+			rc = -ENOMEM;
+			goto out1;
+		}
+
+		inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+		if (!inode) {
+			rc = -ENOMEM;
+			goto out1;
+		}
+		inode->i_fop = &sel_perm_ops;
+		/* i+1 since perm values are 1-indexed */
+		inode->i_ino = sel_perm_to_ino(classvalue, i+1);
+		d_add(dentry, inode);
+	}
+
+out1:
+	for (i = 0; i < nperms; i++)
+		kfree(perms[i]);
+	kfree(perms);
+out:
+	return rc;
+}
+
+static int sel_make_class_dir_entries(char *classname, int index,
+					struct dentry *dir)
+{
+	struct dentry *dentry = NULL;
+	struct inode *inode = NULL;
+	int rc;
+
+	dentry = d_alloc_name(dir, "index");
+	if (!dentry) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+	if (!inode) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	inode->i_fop = &sel_class_ops;
+	inode->i_ino = sel_class_to_ino(index);
+	d_add(dentry, inode);
+
+	dentry = d_alloc_name(dir, "perms");
+	if (!dentry) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino);
+	if (rc)
+		goto out;
+
+	rc = sel_make_perm_files(classname, index, dentry);
+
+out:
+	return rc;
+}
+
+static void sel_remove_classes(void)
+{
+	struct list_head *class_node;
+
+	list_for_each(class_node, &class_dir->d_subdirs) {
+		struct dentry *class_subdir = list_entry(class_node,
+					struct dentry, d_u.d_child);
+		struct list_head *class_subdir_node;
+
+		list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
+			struct dentry *d = list_entry(class_subdir_node,
+						struct dentry, d_u.d_child);
+
+			if (d->d_inode)
+				if (d->d_inode->i_mode & S_IFDIR)
+					sel_remove_entries(d);
+		}
+
+		sel_remove_entries(class_subdir);
+	}
+
+	sel_remove_entries(class_dir);
+}
+
+static int sel_make_classes(void)
+{
+	int rc = 0, nclasses, i;
+	char **classes;
+
+	/* delete any existing entries */
+	sel_remove_classes();
+
+	rc = security_get_classes(&classes, &nclasses);
+	if (rc < 0)
+		goto out;
+
+	/* +2 since classes are 1-indexed */
+	last_class_ino = sel_class_to_ino(nclasses+2);
+
+	for (i = 0; i < nclasses; i++) {
+		struct dentry *class_name_dir;
+
+		class_name_dir = d_alloc_name(class_dir, classes[i]);
+		if (!class_name_dir) {
+			rc = -ENOMEM;
+			goto out1;
+		}
+
+		rc = sel_make_dir(class_dir->d_inode, class_name_dir,
+				&last_class_ino);
+		if (rc)
+			goto out1;
+
+		/* i+1 since class values are 1-indexed */
+		rc = sel_make_class_dir_entries(classes[i], i+1,
+				class_name_dir);
+		if (rc)
+			goto out1;
+	}
+
+out1:
+	for (i = 0; i < nclasses; i++)
+		kfree(classes[i]);
+	kfree(classes);
+out:
+	return rc;
+}
+
+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+			unsigned long *ino)
 {
 	int ret = 0;
 	struct inode *inode;
@@ -1306,7 +1543,7 @@
 	}
 	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
-	inode->i_ino = ++sel_last_ino;
+	inode->i_ino = ++(*ino);
 	/* directory inodes start off with i_nlink == 2 (for "." entry) */
 	inc_nlink(inode);
 	d_add(dentry, inode);
@@ -1352,7 +1589,7 @@
 		goto err;
 	}
 
-	ret = sel_make_dir(root_inode, dentry);
+	ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
 	if (ret)
 		goto err;
 
@@ -1385,7 +1622,7 @@
 		goto err;
 	}
 
-	ret = sel_make_dir(root_inode, dentry);
+	ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
 	if (ret)
 		goto err;
 
@@ -1399,7 +1636,7 @@
 		goto err;
 	}
 
-	ret = sel_make_dir(root_inode, dentry);
+	ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
 	if (ret)
 		goto err;
 
@@ -1407,6 +1644,18 @@
 	if (ret)
 		goto err;
 
+	dentry = d_alloc_name(sb->s_root, "class");
+	if (!dentry) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
+	if (ret)
+		goto err;
+
+	class_dir = dentry;
+
 out:
 	return ret;
 err:
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0ac1021..f05f97a 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -598,6 +599,7 @@
 	struct range_trans *rt, *lrt = NULL;
 
 	for (i = 0; i < SYM_NUM; i++) {
+		cond_resched();
 		hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
 		hashtab_destroy(p->symtab[i].table);
 	}
@@ -612,6 +614,7 @@
 	avtab_destroy(&p->te_avtab);
 
 	for (i = 0; i < OCON_NUM; i++) {
+		cond_resched();
 		c = p->ocontexts[i];
 		while (c) {
 			ctmp = c;
@@ -623,6 +626,7 @@
 
 	g = p->genfs;
 	while (g) {
+		cond_resched();
 		kfree(g->fstype);
 		c = g->head;
 		while (c) {
@@ -639,18 +643,21 @@
 	cond_policydb_destroy(p);
 
 	for (tr = p->role_tr; tr; tr = tr->next) {
+		cond_resched();
 		kfree(ltr);
 		ltr = tr;
 	}
 	kfree(ltr);
 
 	for (ra = p->role_allow; ra; ra = ra -> next) {
+		cond_resched();
 		kfree(lra);
 		lra = ra;
 	}
 	kfree(lra);
 
 	for (rt = p->range_tr; rt; rt = rt -> next) {
+		cond_resched();
 		if (lrt) {
 			ebitmap_destroy(&lrt->target_range.level[0].cat);
 			ebitmap_destroy(&lrt->target_range.level[1].cat);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 40660ff..b5f017f 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1587,19 +1587,18 @@
 			   u32 *nel)
 {
 	struct context *fromcon, usercon;
-	u32 *mysids, *mysids2, sid;
+	u32 *mysids = NULL, *mysids2, sid;
 	u32 mynel = 0, maxnel = SIDS_NEL;
 	struct user_datum *user;
 	struct role_datum *role;
-	struct av_decision avd;
 	struct ebitmap_node *rnode, *tnode;
 	int rc = 0, i, j;
 
-	if (!ss_initialized) {
-		*sids = NULL;
-		*nel = 0;
+	*sids = NULL;
+	*nel = 0;
+
+	if (!ss_initialized)
 		goto out;
-	}
 
 	POLICY_RDLOCK;
 
@@ -1635,17 +1634,9 @@
 			if (mls_setup_user_range(fromcon, user, &usercon))
 				continue;
 
-			rc = context_struct_compute_av(fromcon, &usercon,
-						       SECCLASS_PROCESS,
-						       PROCESS__TRANSITION,
-						       &avd);
-			if (rc ||  !(avd.allowed & PROCESS__TRANSITION))
-				continue;
 			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
-			if (rc) {
-				kfree(mysids);
+			if (rc)
 				goto out_unlock;
-			}
 			if (mynel < maxnel) {
 				mysids[mynel++] = sid;
 			} else {
@@ -1653,7 +1644,6 @@
 				mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
 				if (!mysids2) {
 					rc = -ENOMEM;
-					kfree(mysids);
 					goto out_unlock;
 				}
 				memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
@@ -1664,11 +1654,32 @@
 		}
 	}
 
-	*sids = mysids;
-	*nel = mynel;
-
 out_unlock:
 	POLICY_RDUNLOCK;
+	if (rc || !mynel) {
+		kfree(mysids);
+		goto out;
+	}
+
+	mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
+	if (!mysids2) {
+		rc = -ENOMEM;
+		kfree(mysids);
+		goto out;
+	}
+	for (i = 0, j = 0; i < mynel; i++) {
+		rc = avc_has_perm_noaudit(fromsid, mysids[i],
+					  SECCLASS_PROCESS,
+					  PROCESS__TRANSITION, AVC_STRICT,
+					  NULL);
+		if (!rc)
+			mysids2[j++] = mysids[i];
+		cond_resched();
+	}
+	rc = 0;
+	kfree(mysids);
+	*sids = mysids2;
+	*nel = j;
 out:
 	return rc;
 }
@@ -1996,6 +2007,101 @@
 	return rc;
 }
 
+static int get_classes_callback(void *k, void *d, void *args)
+{
+	struct class_datum *datum = d;
+	char *name = k, **classes = args;
+	int value = datum->value - 1;
+
+	classes[value] = kstrdup(name, GFP_ATOMIC);
+	if (!classes[value])
+		return -ENOMEM;
+
+	return 0;
+}
+
+int security_get_classes(char ***classes, int *nclasses)
+{
+	int rc = -ENOMEM;
+
+	POLICY_RDLOCK;
+
+	*nclasses = policydb.p_classes.nprim;
+	*classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
+	if (!*classes)
+		goto out;
+
+	rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+			*classes);
+	if (rc < 0) {
+		int i;
+		for (i = 0; i < *nclasses; i++)
+			kfree((*classes)[i]);
+		kfree(*classes);
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+}
+
+static int get_permissions_callback(void *k, void *d, void *args)
+{
+	struct perm_datum *datum = d;
+	char *name = k, **perms = args;
+	int value = datum->value - 1;
+
+	perms[value] = kstrdup(name, GFP_ATOMIC);
+	if (!perms[value])
+		return -ENOMEM;
+
+	return 0;
+}
+
+int security_get_permissions(char *class, char ***perms, int *nperms)
+{
+	int rc = -ENOMEM, i;
+	struct class_datum *match;
+
+	POLICY_RDLOCK;
+
+	match = hashtab_search(policydb.p_classes.table, class);
+	if (!match) {
+		printk(KERN_ERR "%s:  unrecognized class %s\n",
+			__FUNCTION__, class);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	*nperms = match->permissions.nprim;
+	*perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC);
+	if (!*perms)
+		goto out;
+
+	if (match->comdatum) {
+		rc = hashtab_map(match->comdatum->permissions.table,
+				get_permissions_callback, *perms);
+		if (rc < 0)
+			goto err;
+	}
+
+	rc = hashtab_map(match->permissions.table, get_permissions_callback,
+			*perms);
+	if (rc < 0)
+		goto err;
+
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+
+err:
+	POLICY_RDUNLOCK;
+	for (i = 0; i < *nperms; i++)
+		kfree((*perms)[i]);
+	kfree(*perms);
+	return rc;
+}
+
 struct selinux_audit_rule {
 	u32 au_seqno;
 	struct context au_ctxt;
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 19c65a8..7bc2767 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -361,7 +361,7 @@
  err:
 	if (card)
 		snd_card_free(card);
-	if (CKEN & CKEN_AC97) {
+	if (CKEN & (1 << CKEN_AC97)) {
 		GCR |= GCR_ACLINK_OFF;
 		free_irq(IRQ_AC97, NULL);
 		pxa_set_cken(CKEN_AC97, 0);
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index c7e1b26..e7ed868 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -987,7 +987,7 @@
 		if (platform_get_drvdata(device))
 			return 0;
 		platform_device_unregister(device);
-		err = -ENODEV
+		err = -ENODEV;
 	} else
 		err = PTR_ERR(device);
 	platform_driver_unregister(&sa11xx_uda1341_driver);
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index ebb1bda..2025db5 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -1048,7 +1048,7 @@
 /*********************************************************************
  * module init stuff
  *********************************************************************/
-static void __init_or_module snd_mts64_unregister_all(void)
+static void snd_mts64_unregister_all(void)
 {
 	int i;
 
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 61a323c..4f6800b 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -953,7 +953,7 @@
 static struct isa_driver snd_opl3sa2_isa_driver = {
 	.match		= snd_opl3sa2_isa_match,
 	.probe		= snd_opl3sa2_isa_probe,
-	.remove		= __devexit( snd_opl3sa2_isa_remove),
+	.remove		= __devexit_p(snd_opl3sa2_isa_remove),
 #ifdef CONFIG_PM
 	.suspend	= snd_opl3sa2_isa_suspend,
 	.resume		= snd_opl3sa2_isa_resume,
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 4b30ae6..866d4de 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,35 +5,6 @@
 #
 # Prompt user for primary drivers.
 
-config OSS_OBSOLETE
-	bool "Obsolete OSS drivers"
-	depends on SOUND_PRIME
-	help
-	  This option enables support for obsolete OSS drivers that
-	  are scheduled for removal in the near future.
-
-	  Please contact Adrian Bunk <bunk@stusta.de> if you had to
-	  say Y here because your hardware is not properly supported
-	  by ALSA.
-
-	  If unsure, say N.
-
-config SOUND_BT878
-	tristate "BT878 audio dma"
-	depends on SOUND_PRIME && PCI && OSS_OBSOLETE
-	---help---
-	  Audio DMA support for bt878 based grabber boards.  As you might have
-	  already noticed, bt878 is listed with two functions in /proc/pci.
-	  Function 0 does the video stuff (bt848 compatible), function 1 does
-	  the same for audio data.  This is a driver for the audio part of
-	  the chip.  If you say 'Y' here you get a oss-compatible dsp device
-	  where you can record from.  If you want just watch TV you probably
-	  don't need this driver as most TV cards handle sound with a short
-	  cable from the TV card to your sound card's line-in.
-
-	  To compile this driver as a module, choose M here: the module will
-	  be called btaudio.
-
 config SOUND_BCM_CS4297A
 	tristate "Crystal Sound CS4297a (for Swarm)"
 	depends on SOUND_PRIME && SIBYTE_SWARM
@@ -44,13 +15,6 @@
 	  note that CONFIG_KGDB should not be enabled at the same
 	  time, since it also attempts to use this UART port.
 
-config SOUND_ICH
-	tristate "Intel ICH (i8xx) audio support"
-	depends on SOUND_PRIME && PCI && OSS_OBSOLETE
-	help
-	  Support for integral audio in Intel's I/O Controller Hub (ICH)
-	  chipset, as used on the 810/820/840 motherboards.
-
 config SOUND_VWSND
 	tristate "SGI Visual Workstation Sound"
 	depends on SOUND_PRIME && X86_VISWS
@@ -346,29 +310,9 @@
 	  and Pinnacle). Larger values reduce the chance of data overruns at
 	  the expense of overall latency. If unsure, use the default.
 
-config SOUND_VIA82CXXX
-	tristate "VIA 82C686 Audio Codec"
-	depends on SOUND_PRIME && PCI && OSS_OBSOLETE
-	help
-	  Say Y here to include support for the audio codec found on VIA
-	  82Cxxx-based chips. Typically these are built into a motherboard.
-
-	  DO NOT select Sound Blaster or Adlib with this driver, unless
-	  you have a Sound Blaster or Adlib card in addition to your VIA
-	  audio chip.
-
-config MIDI_VIA82CXXX
-	bool "VIA 82C686 MIDI"
-	depends on SOUND_VIA82CXXX && ISA_DMA_API
-	help
-	  Answer Y to use the MIDI interface of the Via686. You may need to
-	  enable this in the BIOS before it will work. This is for connection
-	  to external MIDI hardware, and is not required for software playback
-	  of MIDI files.
-
 config SOUND_OSS
 	tristate "OSS sound modules"
-	depends on SOUND_PRIME && ISA_DMA_API
+	depends on SOUND_PRIME && ISA_DMA_API && VIRT_TO_BUS
 	help
 	  OSS is the Open Sound System suite of sound card drivers.  They make
 	  sound programming easier since they provide a common API.  Say Y or
@@ -400,23 +344,10 @@
 
 	  Say Y unless you have 16MB or more RAM or a PCI sound card.
 
-config SOUND_CS4232
-	tristate "Crystal CS4232 based (PnP) cards"
-	depends on SOUND_OSS && OSS_OBSOLETE
-	help
-	  Say Y here if you have a card based on the Crystal CS4232 chip set,
-	  which uses its own Plug and Play protocol.
-
-	  If you compile the driver into the kernel, you have to add
-	  "cs4232=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
-	  command line.
-
-	  See <file:Documentation/sound/oss/CS4232> for more information on
-	  configuring this card.
-
 config SOUND_SSCAPE
 	tristate "Ensoniq SoundScape support"
 	depends on SOUND_OSS
+	depends on VIRT_TO_BUS
 	help
 	  Answer Y if you have a sound card based on the Ensoniq SoundScape
 	  chipset. Such cards are being manufactured at least by Ensoniq, Spea
@@ -719,13 +650,6 @@
 	  Say Y here to include support for the Rockwell WaveArtist sound
 	  system.  This driver is mainly for the NetWinder.
 
-config SOUND_TVMIXER
-	tristate "TV card (bt848) mixer support"
-	depends on SOUND_PRIME && I2C && VIDEO_V4L1 && OSS_OBSOLETE
-	help
-	  Support for audio mixer facilities on the BT848 TV frame-grabber
-	  card.
-
 config SOUND_KAHLUA
 	tristate "XpressAudio Sound Blaster emulation"
 	depends on SOUND_SB
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 2489bd6..7a2f9ae 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -18,20 +18,15 @@
 obj-$(CONFIG_SOUND_SSCAPE)	+= sscape.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o uart401.o
 obj-$(CONFIG_SOUND_MSS)		+= ad1848.o
-obj-$(CONFIG_SOUND_OPL3SA2)	+= opl3sa2.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_PAS)		+= pas2.o sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SB)		+= sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_KAHLUA)	+= kahlua.o
 obj-$(CONFIG_SOUND_MPU401)	+= mpu401.o
 obj-$(CONFIG_SOUND_UART6850)	+= uart6850.o
-obj-$(CONFIG_SOUND_ADLIB)	+= adlib_card.o opl3.o
 obj-$(CONFIG_SOUND_YM3812)	+= opl3.o
 obj-$(CONFIG_SOUND_VMIDI)	+= v_midi.o
 obj-$(CONFIG_SOUND_VIDC)	+= vidc_mod.o
 obj-$(CONFIG_SOUND_WAVEARTIST)	+= waveartist.o
-obj-$(CONFIG_SOUND_AD1816)	+= ad1816.o
-obj-$(CONFIG_SOUND_AD1889)	+= ad1889.o ac97_codec.o
-obj-$(CONFIG_SOUND_ACI_MIXER)	+= aci.o
 
 obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o ac97_codec.o
 ifeq ($(CONFIG_MIDI_VIA82CXXX),y)
@@ -40,24 +35,16 @@
 obj-$(CONFIG_SOUND_MSNDCLAS)	+= msnd.o msnd_classic.o
 obj-$(CONFIG_SOUND_MSNDPIN)	+= msnd.o msnd_pinnacle.o
 obj-$(CONFIG_SOUND_VWSND)	+= vwsnd.o
-obj-$(CONFIG_SOUND_NM256)	+= nm256_audio.o ac97.o
 obj-$(CONFIG_SOUND_ICH)		+= i810_audio.o ac97_codec.o
 obj-$(CONFIG_SOUND_ES1371)	+= es1371.o ac97_codec.o
 obj-$(CONFIG_SOUND_VRC5477)	+= nec_vrc5477.o ac97_codec.o
 obj-$(CONFIG_SOUND_AU1550_AC97)	+= au1550_ac97.o ac97_codec.o
-obj-$(CONFIG_SOUND_FUSION)	+= cs46xx.o ac97_codec.o
 obj-$(CONFIG_SOUND_TRIDENT)	+= trident.o ac97_codec.o
-obj-$(CONFIG_SOUND_EMU10K1)	+= ac97_codec.o
 obj-$(CONFIG_SOUND_BCM_CS4297A)	+= swarm_cs4297a.o
 obj-$(CONFIG_SOUND_BT878)	+= btaudio.o
 
 obj-$(CONFIG_SOUND_WM97XX)	+= ac97_plugin_wm97xx.o
 
-ifeq ($(CONFIG_MIDI_EMU10K1),y)
-  obj-$(CONFIG_SOUND_EMU10K1)	+= sound.o
-endif
-
-obj-$(CONFIG_SOUND_EMU10K1)	+= emu10k1/
 obj-$(CONFIG_DMASOUND)		+= dmasound/
 
 # Declare multi-part drivers.
diff --git a/sound/oss/ac97.c b/sound/oss/ac97.c
deleted file mode 100644
index 72cf4ed..0000000
--- a/sound/oss/ac97.c
+++ /dev/null
@@ -1,432 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include "ac97.h"
-
-/* Flag for mono controls. */
-#define MO 0
-/* And for stereo. */
-#define ST 1
-
-/* Whether or not the bits in the channel are inverted. */
-#define INV 1
-#define NINV 0
-
-static struct ac97_chn_desc {
-    int ac97_regnum;
-    int oss_channel;
-    int maxval;
-    int is_stereo;
-    int oss_mask;
-    int recordNum;
-    u16 regmask;
-    int is_inverted;
-} mixerRegs[] = {
-    { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME,   0x3f, ST, SOUND_MASK_VOLUME,   5, 0x0000, INV  },
-    { AC97_MASTER_VOL_MONO,   SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000, INV  },
-    { AC97_MASTER_TONE,       SOUND_MIXER_TREBLE,   0x0f, MO, SOUND_MASK_TREBLE,  -1, 0x00ff, INV  },
-    { AC97_MASTER_TONE,       SOUND_MIXER_BASS,     0x0f, MO, SOUND_MASK_BASS,    -1, 0xff00, INV  },
-    { AC97_PCBEEP_VOL,        SOUND_MIXER_SPEAKER,  0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e, INV  },
-    { AC97_PHONE_VOL,         SOUND_MIXER_PHONEIN,  0x1f, MO, SOUND_MASK_PHONEIN,  7, 0x0000, INV  },
-    { AC97_MIC_VOL,           SOUND_MIXER_MIC,      0x1f, MO, SOUND_MASK_MIC,      0, 0x0000, INV  },
-    { AC97_LINEIN_VOL,        SOUND_MIXER_LINE,     0x1f, ST, SOUND_MASK_LINE,     4, 0x0000, INV  },
-    { AC97_CD_VOL,            SOUND_MIXER_CD,       0x1f, ST, SOUND_MASK_CD,       1, 0x0000, INV  },
-    { AC97_VIDEO_VOL,         SOUND_MIXER_VIDEO,    0x1f, ST, SOUND_MASK_VIDEO,    2, 0x0000, INV  },
-    { AC97_AUX_VOL,           SOUND_MIXER_LINE1,    0x1f, ST, SOUND_MASK_LINE1,	   3, 0x0000, INV  },
-    { AC97_PCMOUT_VOL,        SOUND_MIXER_PCM,      0x1f, ST, SOUND_MASK_PCM,     -1, 0x0000, INV  },
-    { AC97_RECORD_GAIN,       SOUND_MIXER_IGAIN,    0x0f, ST, SOUND_MASK_IGAIN,   -1, 0x0000, NINV },
-    { -1,		      -1,		    0xff, 0,  0,                  -1, 0x0000, 0    },
-};
-
-static struct ac97_chn_desc *
-ac97_find_chndesc (struct ac97_hwint *dev, int oss_channel)
-{
-    int x;
-
-    for (x = 0; mixerRegs[x].oss_channel != -1; x++) {
-	if (mixerRegs[x].oss_channel == oss_channel)
-	    return mixerRegs + x;
-    }
-
-    return NULL;
-}
-
-static inline int
-ac97_is_valid_channel (struct ac97_hwint *dev, struct ac97_chn_desc *chn)
-{
-    return (dev->last_written_mixer_values[chn->ac97_regnum / 2]
-	    != AC97_REG_UNSUPPORTED);
-}
-
-int
-ac97_init (struct ac97_hwint *dev)
-{
-    int x;
-    int reg0;
-
-    /* Clear out the arrays of cached values. */
-    for (x = 0; x < AC97_REG_CNT; x++)
-	dev->last_written_mixer_values[x] = AC97_REGVAL_UNKNOWN;
-
-    for (x = 0; x < SOUND_MIXER_NRDEVICES; x++)
-	dev->last_written_OSS_values[x] = AC97_REGVAL_UNKNOWN;
-
-    /* Clear the device masks.  */
-    dev->mixer_devmask = 0;
-    dev->mixer_stereomask = 0;
-    dev->mixer_recmask = 0;
-
-    /* ??? Do a "standard reset" via register 0? */
-
-    /* Hardware-dependent reset.  */
-    if (dev->reset_device (dev))
-	return -1;
-
-    /* Check the mixer device capabilities.  */
-    reg0 = dev->read_reg (dev, AC97_RESET);
-
-    if (reg0 < 0)
-	return -1;
-
-    /* Check for support for treble/bass controls.  */
-    if (! (reg0 & 4)) {
-	dev->last_written_mixer_values[AC97_MASTER_TONE / 2] 
-	    = AC97_REG_UNSUPPORTED;
-    }
-
-    /* ??? There may be other tests here? */
-
-    /* Fill in the device masks.  */
-    for (x = 0; mixerRegs[x].ac97_regnum != -1; x++) {
-	if (ac97_is_valid_channel (dev, mixerRegs + x)) {
-	    dev->mixer_devmask |= mixerRegs[x].oss_mask;
-
-	    if (mixerRegs[x].is_stereo)
-		dev->mixer_stereomask |= mixerRegs[x].oss_mask;
-
-	    if (mixerRegs[x].recordNum != -1)
-		dev->mixer_recmask |= mixerRegs[x].oss_mask;
-	}
-    }
-
-    return 0;
-}
-
-/* Return the contents of register REG; use the cache if the value in it
-   is valid.  Returns a negative error code on failure. */
-static int
-ac97_get_register (struct ac97_hwint *dev, u8 reg) 
-{
-    if (reg > 127 || (reg & 1))
-	return -EINVAL;
-
-    /* See if it's in the cache, or if it's just plain invalid.  */
-    switch (dev->last_written_mixer_values[reg / 2]) {
-    case AC97_REG_UNSUPPORTED:
-	return -EINVAL;
-	break;
-    case AC97_REGVAL_UNKNOWN:
-	dev->last_written_mixer_values[reg / 2] = dev->read_reg (dev, reg);
-	break;
-    default:
-	break;
-    }
-    return dev->last_written_mixer_values[reg / 2];
-}
-
-/* Write VALUE to AC97 register REG, and cache its value in the last-written
-   cache.  Returns a negative error code on failure, or 0 on success. */
-int
-ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value)
-{
-    if (reg > 127 || (reg & 1))
-	return -EINVAL;
-
-    if (dev->last_written_mixer_values[reg / 2] == AC97_REG_UNSUPPORTED)
-	return -EINVAL;
-    else {
-	int res = dev->write_reg (dev, reg, value);
-	if (res >= 0) {
-	    dev->last_written_mixer_values[reg / 2] = value;
-	    return 0;
-	}
-	else
-	    return res;
-    }
-}
-
-/* Scale VALUE (a value fro 0 to MAXVAL) to a value from 0-100.  If
-   IS_STEREO is set, VALUE is a stereo value; the left channel value
-   is in the lower 8 bits, and the right channel value is in the upper
-   8 bits.
-
-   A negative error code is returned on failure, or the unsigned
-   scaled value on success.  */
-
-static int
-ac97_scale_to_oss_val (int value, int maxval, int is_stereo, int inv)
-{
-    /* Muted?  */
-    if (value & AC97_MUTE)
-	return 0;
-
-    if (is_stereo)
-	return (ac97_scale_to_oss_val (value & 255, maxval, 0, inv) << 8)
-	| (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
-    else {
-	int i;
-	
-	/* Inverted. */
-	if (inv)
-	    value = maxval - value;
-
-	i = (value * 100 + (maxval / 2)) / maxval;
-	if (i > 100)
-	     i = 100;
-	if (i < 0)
-	    i = 0;
-	return i;
-    }
-}
-
-static int
-ac97_scale_from_oss_val (int value, int maxval, int is_stereo, int inv)
-{
-    if (is_stereo)
-	return (ac97_scale_from_oss_val (value & 255, maxval, 0, inv) << 8)
-	| (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
-    else {
-	int i = ((value & 255) * maxval + 50) / 100;
-	if (inv)
-	    i = maxval - i;
-	if (i < 0)
-	    i = 0;
-	if (i > maxval)
-	    i = maxval;
-	return i;
-    }
-}
-
-static int
-ac97_set_mixer (struct ac97_hwint *dev, int oss_channel, u16 oss_value)
-{
-    int scaled_value;
-    struct ac97_chn_desc *channel = ac97_find_chndesc (dev, oss_channel);
-    int result;
-
-    if (channel == NULL)
-	return -ENODEV;
-    if (! ac97_is_valid_channel (dev, channel))
-	return -ENODEV;
-    scaled_value = ac97_scale_from_oss_val (oss_value, channel->maxval,
-					    channel->is_stereo, 
-					    channel->is_inverted);
-    if (scaled_value < 0)
-	return scaled_value;
-
-    if (channel->regmask != 0) {
-	int mv;
-
-	int oldval = ac97_get_register (dev, channel->ac97_regnum);
-	if (oldval < 0)
-	    return oldval;
-
-	for (mv = channel->regmask; ! (mv & 1); mv >>= 1)
-	    scaled_value <<= 1;
-
-	scaled_value &= channel->regmask;
-	scaled_value |= (oldval & ~channel->regmask);
-    }
-    result = ac97_put_register (dev, channel->ac97_regnum, scaled_value);
-    if (result == 0)
-	dev->last_written_OSS_values[oss_channel] = oss_value;
-    return result;
-}
-
-static int
-ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel)
-{
-    struct ac97_chn_desc *channel = ac97_find_chndesc (dev, oss_channel);
-    int regval;
-
-    if (channel == NULL)
-	return -ENODEV;
-
-    if (! ac97_is_valid_channel (dev, channel))
-	return -ENODEV;
-
-    regval = ac97_get_register (dev, channel->ac97_regnum);
-
-    if (regval < 0)
-	return regval;
-
-    if (channel->regmask != 0) {
-	int mv;
-
-	regval &= channel->regmask;
-
-	for (mv = channel->regmask; ! (mv & 1); mv >>= 1)
-	    regval >>= 1;
-    }
-    return ac97_scale_to_oss_val (regval, channel->maxval,
-				  channel->is_stereo, 
-				  channel->is_inverted);
-}
-
-static int
-ac97_get_recmask (struct ac97_hwint *dev)
-{
-    int recReg = ac97_get_register (dev, AC97_RECORD_SELECT);
-
-    if (recReg < 0)
-	return recReg;
-    else {
-	int x;
-	for (x = 0; mixerRegs[x].ac97_regnum >= 0; x++) {
-	    if (mixerRegs[x].recordNum == (recReg & 7))
-		return mixerRegs[x].oss_mask;
-	}
-	return -ENODEV;
-    }
-}
-
-static int
-ac97_set_recmask (struct ac97_hwint *dev, int oss_recmask)
-{
-    int x;
-
-    if (oss_recmask == 0)
-	oss_recmask = SOUND_MIXER_MIC;
-
-    for (x = 0; mixerRegs[x].ac97_regnum >= 0; x++) { 
-	if ((mixerRegs[x].recordNum >= 0)
-	     && (oss_recmask & mixerRegs[x].oss_mask))
-	    break;
-    }
-    if (mixerRegs[x].ac97_regnum < 0)
-	return -ENODEV;
-    else {
-	int regval = (mixerRegs[x].recordNum << 8) | mixerRegs[x].recordNum;
-	int res = ac97_put_register (dev, AC97_RECORD_SELECT, regval);
-	if (res == 0)
-	    return ac97_get_recmask (dev);
-	else
-	    return res;
-    }
-}
-
-/* Set the mixer DEV to the list of values in VALUE_LIST.  Return 0 on
-   success, or a negative error code.  */
-int
-ac97_set_values (struct ac97_hwint *dev, 
-		 struct ac97_mixer_value_list *value_list)
-{
-    int x;
-
-    for (x = 0; value_list[x].oss_channel != -1; x++) {
-	int chnum = value_list[x].oss_channel;
-	struct ac97_chn_desc *chent = ac97_find_chndesc (dev, chnum);
-	if (chent != NULL) {
-	    u16 val;
-	    int res;
-
-	    if (chent->is_stereo)
-		val = (value_list[x].value.stereo.right << 8) 
-		      | value_list[x].value.stereo.left;
-	    else {
-		/* We do this so the returned value looks OK in the
-		   mixer app.  It's not necessary otherwise.  */
-		val = (value_list[x].value.mono << 8) 
-		      | value_list[x].value.mono;
-	    }
-	    res = ac97_set_mixer (dev, chnum, val);
-	    if (res < 0)
-		return res;
-	}
-	else
-	    return -ENODEV;
-    }
-    return 0;
-}
-
-int
-ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd, void __user *arg)
-{
-    int ret;
-
-    switch (cmd) {
-    case SOUND_MIXER_READ_RECSRC:
-	ret = ac97_get_recmask (dev);
-	break;
-
-    case SOUND_MIXER_WRITE_RECSRC:
-	{
-	    if (get_user (ret, (int __user *) arg))
-		ret = -EFAULT;
-	    else
-		ret = ac97_set_recmask (dev, ret);
-	}
-	break;
-
-    case SOUND_MIXER_READ_CAPS:
-	ret = SOUND_CAP_EXCL_INPUT;
-	break;
-
-    case SOUND_MIXER_READ_DEVMASK:
-	ret = dev->mixer_devmask;
-	break;
-
-    case SOUND_MIXER_READ_RECMASK:
-	ret = dev->mixer_recmask;
-	break;
-
-    case SOUND_MIXER_READ_STEREODEVS:
-	ret = dev->mixer_stereomask;
-	break;
-
-    default:
-	/* Read or write request. */
-	ret = -EINVAL;
-	if (_IOC_TYPE (cmd) == 'M') {
-	    int dir = _SIOC_DIR (cmd);
-	    int channel = _IOC_NR (cmd);
-
-	    if (channel >= 0 && channel < SOUND_MIXER_NRDEVICES) {
-		ret = 0;
-		if (dir & _SIOC_WRITE) {
-		    int val;
-		    if (get_user (val, (int __user *) arg) == 0)
-			ret = ac97_set_mixer (dev, channel, val);
-		    else
-			ret = -EFAULT;
-		}
-		if (ret >= 0 && (dir & _SIOC_READ)) {
-		    if (dev->last_written_OSS_values[channel]
-			== AC97_REGVAL_UNKNOWN)
-			dev->last_written_OSS_values[channel]
-			    = ac97_get_mixer_scaled (dev, channel);
-		    ret = dev->last_written_OSS_values[channel];
-		}
-	    }
-	}
-	break;
-    }
-
-    if (ret < 0)
-	return ret;
-    else
-	return put_user(ret, (int __user *) arg);
-}
-
-EXPORT_SYMBOL(ac97_init);
-EXPORT_SYMBOL(ac97_set_values);
-EXPORT_SYMBOL(ac97_put_register);
-EXPORT_SYMBOL(ac97_mixer_ioctl);
-MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- *  c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/ac97.h b/sound/oss/ac97.h
deleted file mode 100644
index 01837a9..0000000
--- a/sound/oss/ac97.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * ac97.h 
- * 
- * definitions for the AC97, Intel's Audio Codec 97 Spec
- * also includes support for a generic AC97 interface
- */
-
-#ifndef _AC97_H_
-#define _AC97_H_
-#include "sound_config.h"
-#include "sound_calls.h"
-
-#define  AC97_RESET              0x0000      //
-#define  AC97_MASTER_VOL_STEREO  0x0002      // Line Out
-#define  AC97_HEADPHONE_VOL      0x0004      // 
-#define  AC97_MASTER_VOL_MONO    0x0006      // TAD Output
-#define  AC97_MASTER_TONE        0x0008      //
-#define  AC97_PCBEEP_VOL         0x000a      // none
-#define  AC97_PHONE_VOL          0x000c      // TAD Input (mono)
-#define  AC97_MIC_VOL            0x000e      // MIC Input (mono)
-#define  AC97_LINEIN_VOL         0x0010      // Line Input (stereo)
-#define  AC97_CD_VOL             0x0012      // CD Input (stereo)
-#define  AC97_VIDEO_VOL          0x0014      // none
-#define  AC97_AUX_VOL            0x0016      // Aux Input (stereo)
-#define  AC97_PCMOUT_VOL         0x0018      // Wave Output (stereo)
-#define  AC97_RECORD_SELECT      0x001a      //
-#define  AC97_RECORD_GAIN        0x001c
-#define  AC97_RECORD_GAIN_MIC    0x001e
-#define  AC97_GENERAL_PURPOSE    0x0020
-#define  AC97_3D_CONTROL         0x0022
-#define  AC97_MODEM_RATE         0x0024
-#define  AC97_POWER_CONTROL      0x0026
-
-/* registers 0x0028 - 0x0058 are reserved */
-
-/* AC'97 2.0 */
-#define AC97_EXTENDED_ID	0x0028	/* Extended Audio ID */
-#define AC97_EXTENDED_STATUS	0x002A	/* Extended Audio Status */
-#define AC97_PCM_FRONT_DAC_RATE 0x002C  /* PCM Front DAC Rate */
-#define AC97_PCM_SURR_DAC_RATE  0x002E  /* PCM Surround DAC Rate */
-#define AC97_PCM_LFE_DAC_RATE   0x0030  /* PCM LFE DAC Rate */
-#define AC97_PCM_LR_ADC_RATE	0x0032	/* PCM LR DAC Rate */
-#define AC97_PCM_MIC_ADC_RATE   0x0034  /* PCM MIC ADC Rate */
-#define AC97_CENTER_LFE_MASTER  0x0036  /* Center + LFE Master Volume */
-#define AC97_SURROUND_MASTER    0x0038  /* Surround (Rear) Master Volume */
-#define AC97_RESERVED_3A	0x003A	/* Reserved */
-/* range 0x3c-0x58 - MODEM */
-
-/* registers 0x005a - 0x007a are vendor reserved */
-
-#define  AC97_VENDOR_ID1         0x007c
-#define  AC97_VENDOR_ID2         0x007e
-
-/* volume control bit defines */
-
-#define AC97_MUTE                0x8000
-#define AC97_MICBOOST            0x0040
-#define AC97_LEFTVOL             0x3f00
-#define AC97_RIGHTVOL            0x003f
-
-/* record mux defines */
-
-#define AC97_RECMUX_MIC          0x0000
-#define AC97_RECMUX_CD           0x0101
-#define AC97_RECMUX_VIDEO        0x0202      /* not used */
-#define AC97_RECMUX_AUX          0x0303      
-#define AC97_RECMUX_LINE         0x0404      
-#define AC97_RECMUX_STEREO_MIX   0x0505
-#define AC97_RECMUX_MONO_MIX     0x0606
-#define AC97_RECMUX_PHONE        0x0707
-
-
-/* general purpose register bit defines */
-
-#define AC97_GP_LPBK             0x0080      /* Loopback mode */
-#define AC97_GP_MS               0x0100      /* Mic Select 0=Mic1, 1=Mic2 */
-#define AC97_GP_MIX              0x0200      /* Mono output select 0=Mix, 1=Mic */
-#define AC97_GP_RLBK             0x0400      /* Remote Loopback - Modem line codec */
-#define AC97_GP_LLBK             0x0800      /* Local Loopback - Modem Line codec */
-#define AC97_GP_LD               0x1000      /* Loudness 1=on */
-#define AC97_GP_3D               0x2000      /* 3D Enhancement 1=on */
-#define AC97_GP_ST               0x4000      /* Stereo Enhancement 1=on */
-#define AC97_GP_POP              0x8000      /* Pcm Out Path, 0=pre 3D, 1=post 3D */
-
-
-/* powerdown control and status bit defines */
-
-/* status */
-#define AC97_PWR_MDM             0x0010      /* Modem section ready */
-#define AC97_PWR_REF             0x0008      /* Vref nominal */
-#define AC97_PWR_ANL             0x0004      /* Analog section ready */
-#define AC97_PWR_DAC             0x0002      /* DAC section ready */
-#define AC97_PWR_ADC             0x0001      /* ADC section ready */
-
-/* control */
-#define AC97_PWR_PR0             0x0100      /* ADC and Mux powerdown */
-#define AC97_PWR_PR1             0x0200      /* DAC powerdown */
-#define AC97_PWR_PR2             0x0400      /* Output mixer powerdown (Vref on) */
-#define AC97_PWR_PR3             0x0800      /* Output mixer powerdown (Vref off) */
-#define AC97_PWR_PR4             0x1000      /* AC-link powerdown */
-#define AC97_PWR_PR5             0x2000      /* Internal Clk disable */
-#define AC97_PWR_PR6             0x4000      /* HP amp powerdown */
-#define AC97_PWR_PR7             0x8000      /* Modem off - if supported */
-
-/* useful power states */
-#define AC97_PWR_D0              0x0000      /* everything on */
-#define AC97_PWR_D1              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4
-#define AC97_PWR_D2              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
-#define AC97_PWR_D3              AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
-#define AC97_PWR_ANLOFF          AC97_PWR_PR2|AC97_PWR_PR3  /* analog section off */
-
-/* Total number of defined registers.  */
-#define AC97_REG_CNT 64
-
-/* Generic AC97 mixer interface. */
-
-/* Structure describing access to the hardware. */
-struct ac97_hwint
-{
-    /* Perform any hardware-specific reset and initialization.  Returns
-     0 on success, or a negative error code.  */
-    int (*reset_device) (struct ac97_hwint *dev);
-
-    /* Returns the contents of the specified register REG.  The caller
-       should check to see if the desired contents are available in
-       the cache first, if applicable. Returns a positive unsigned value
-       representing the contents of the register, or a negative error
-       code.  */
-    int (*read_reg) (struct ac97_hwint *dev, u8 reg);
-
-    /* Writes VALUE to register REG.  Returns 0 on success, or a
-       negative error code.  */
-    int (*write_reg) (struct ac97_hwint *dev, u8 reg, u16 value);
-
-    /* Hardware-specific information. */
-    void *driver_private;
-
-    /* Three OSS masks. */
-    int mixer_devmask;
-    int mixer_stereomask;
-    int mixer_recmask;
-
-    /* The mixer cache. The indices correspond to the AC97 hardware register
-       number / 2, since the register numbers are always an even number.
-
-       Unknown values are set to -1; unsupported registers contain a
-       -2.  */
-    int last_written_mixer_values[AC97_REG_CNT];
-
-    /* A cache of values written via OSS; we need these so we can return
-       the values originally written by the user.
-
-       Why the original user values?  Because the real-world hardware
-       has less precision, and some existing applications assume that
-       they will get back the exact value that they wrote (aumix).
-
-       A -1 value indicates that no value has been written to this mixer
-       channel via OSS.  */
-    int last_written_OSS_values[SOUND_MIXER_NRDEVICES];
-};
-
-/* Values stored in the register cache.  */
-#define AC97_REGVAL_UNKNOWN -1
-#define AC97_REG_UNSUPPORTED -2
-
-struct ac97_mixer_value_list
-{
-    /* Mixer channel to set.  List is terminated by a value of -1.  */
-    int oss_channel;
-    /* The scaled value to set it to; values generally range from 0-100. */
-    union {
-	struct {
-	    u8 left, right;
-	} stereo;
-	u8 mono;
-    } value;
-};
-
-/* Initialize the ac97 mixer by resetting it.  */
-extern int ac97_init (struct ac97_hwint *dev);
-
-/* Sets the mixer DEV to the values in VALUE_LIST.  Returns 0 on success,
-   or a negative error code.  */
-extern int ac97_set_values (struct ac97_hwint *dev,
-			    struct ac97_mixer_value_list *value_list);
-
-/* Writes the specified VALUE to the AC97 register REG in the mixer.
-   Takes care of setting the last-written cache as well.  */
-extern int ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value);
-
-/* Default ioctl. */
-extern int ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd,
-			     void __user * arg);
-
-#endif
-
-/*
- * Local variables:
- *  c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/aci.c b/sound/oss/aci.c
deleted file mode 100644
index 3bfac37..0000000
--- a/sound/oss/aci.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Audio Command Interface (ACI) driver (sound/aci.c)
- *
- * ACI is a protocol used to communicate with the microcontroller on
- * some sound cards produced by miro, e.g. the miroSOUND PCM12 and
- * PCM20. The ACI has been developed for miro by Norberto Pellicci
- * <pellicci@home.com>. Special thanks to both him and miro for
- * providing the ACI specification.
- *
- * The main function of the ACI is to control the mixer and to get a
- * product identification. On the PCM20, ACI also controls the radio
- * tuner on this card, this is supported in the Video for Linux 
- * miropcm20 driver.
- * -
- * This is a fullfeatured implementation. Unsupported features
- * are bugs... (:
- *
- * It is not longer necessary to load the mad16 module first. The
- * user is currently responsible to set the mad16 mixer correctly.
- *
- * To toggle the solo mode for full duplex operation just use the OSS
- * record switch for the pcm ('wave') controller.           Robert
- * -
- *
- * Revision history:
- *
- *   1995-11-10  Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
- *        First version written.
- *   1995-12-31  Markus Kuhn
- *        Second revision, general code cleanup.
- *   1996-05-16	 Hannu Savolainen
- *	  Integrated with other parts of the driver.
- *   1996-05-28  Markus Kuhn
- *        Initialize CS4231A mixer, make ACI first mixer,
- *        use new private mixer API for solo mode.
- *   1998-08-18  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- *	  Small modification to export ACI functions and 
- *	  complete modularisation.
- *   2000-06-20  Robert Siemer <Robert.Siemer@gmx.de>
- *        Don't initialize the CS4231A mixer anymore, so the code is
- *        working again, and other small changes to fit in todays
- *        kernels.
- *   2000-08-26  Robert Siemer
- *        Clean up and rewrite for 2.4.x. Maybe it's SMP safe now... (:
- *        ioctl bugfix, and integration of solo-mode into OSS-API,
- *        added (OSS-limited) equalizer support, return value bugfix,
- *        changed param aci_reset to reset, new params: ide, wss.
- *   2001-04-20  Robert Siemer
- *        even more cleanups...
- *   2001-10-08  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- *   	  Get rid of check_region, .bss optimizations, use set_current_state
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h> 
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include "sound_config.h"
-
-int aci_port;	/* as determined by bit 4 in the OPTi 929 MC4 register */
-static int aci_idcode[2];	/* manufacturer and product ID */
-int aci_version;	/* ACI firmware version	*/
-
-EXPORT_SYMBOL(aci_port);
-EXPORT_SYMBOL(aci_version);
-
-#include "aci.h"
-
-
-static int aci_solo;	/* status bit of the card that can't be		*
-			 * checked with ACI versions prior to 0xb0	*/
-static int aci_amp;   /* status bit for power-amp/line-out level
-			   but I have no docs about what is what... */
-static int aci_micpreamp=3; /* microphone preamp-level that can't be    *
-			 * checked with ACI versions prior to 0xb0	*/
-
-static int mixer_device;
-static struct mutex aci_mutex;
-
-#ifdef MODULE
-static int reset;
-module_param(reset, bool, 0);
-MODULE_PARM_DESC(reset,"When set to 1, reset aci mixer.");
-#else
-static int reset = 1;
-#endif
-
-static int ide=-1;
-module_param(ide, int, 0);
-MODULE_PARM_DESC(ide,"1 enable, 0 disable ide-port - untested"
-		 " default: do nothing");
-static int wss=-1;
-module_param(wss, int, 0);
-MODULE_PARM_DESC(wss,"change between ACI/WSS-mixer; use 0 and 1 - untested"
-		 " default: do nothing; for PCM1-pro only");
-
-#ifdef DEBUG
-static void print_bits(unsigned char c)
-{
-	int j;
-	printk(KERN_DEBUG "aci: ");
-
-	for (j=7; j>=0; j--) {
-		printk("%d", (c >> j) & 0x1);
-	}
-
-	printk("\n");
-}
-#endif
-
-/*
- * This busy wait code normally requires less than 15 loops and
- * practically always less than 100 loops on my i486/DX2 66 MHz.
- *
- * Warning: Waiting on the general status flag after reseting the MUTE
- * function can take a VERY long time, because the PCM12 does some kind
- * of fade-in effect. For this reason, access to the MUTE function has
- * not been implemented at all.
- *
- * - The OSS interface has no mute option. It takes about 3 seconds to
- * fade-in on my PCM20. busy_wait() handles it great now...     Robert
- */
-
-static int busy_wait(void)
-{
-	#define MINTIME 500
-	long timeout;
-	unsigned char byte;
-
-	for (timeout = 1; timeout <= MINTIME+30; timeout++) {
-		if (((byte=inb(BUSY_REGISTER)) & 1) == 0) {
-			if (timeout >= MINTIME)
-				printk(KERN_DEBUG "aci: Got READYFLAG in round %ld.\n", timeout-MINTIME);
-			return byte;
-		}
-		if (timeout >= MINTIME) {
-			long out=10*HZ;
-			switch (timeout-MINTIME) {
-			case 0 ... 9:
-				out /= 10;
-			case 10 ... 19:
-				out /= 10;
-			case 20 ... 30:
-				out /= 10;
-			default:
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				schedule_timeout(out);
-				break;
-			}
-		}
-	}
-	printk(KERN_WARNING "aci: busy_wait() time out.\n");
-	return -EBUSY;
-}
-
-/* The four ACI command types are fucked up. [-:
- * implied is: 1w      - special case for INIT
- * write   is: 2w1r
- * read    is: x(1w1r) where x is 1 or 2 (1 CHECK_SIG, 1 CHECK_STER,
- *                                        1 VERSION, 2 IDCODE)
- *  the command is only in the first write, rest is protocol overhead
- *
- * indexed is technically a write and used for STATUS
- * and the special case for TUNE is: 3w1r
- * 
- * Here the new general sheme: TUNE --> aci_rw_cmd(x,  y,  z)
- *                indexed and write --> aci_rw_cmd(x,  y, -1)
- *           implied and read (x=1) --> aci_rw_cmd(x, -1, -1)
- *
- * Read (x>=2) is not implemented (only used during initialization).
- * Use aci_idcode[2] and aci_version...                    Robert
- */
-
-/* Some notes for error detection: theoretically it is possible.
- * But it doubles the I/O-traffic from ww(r) to wwwrw(r) in the normal 
- * case and doesn't seem to be designed for that...        Robert
- */
-
-static inline int aci_rawwrite(unsigned char byte)
-{
-	if (busy_wait() >= 0) {
-#ifdef DEBUG
-		printk(KERN_DEBUG "aci_rawwrite(%d)\n", byte);
-#endif
-		outb(byte, COMMAND_REGISTER);
-		return 0;
-	} else
-		return -EBUSY;
-}
-
-static inline int aci_rawread(void)
-{
-	unsigned char byte;
-
-	if (busy_wait() >= 0) {
-		byte=inb(STATUS_REGISTER);
-#ifdef DEBUG
-		printk(KERN_DEBUG "%d = aci_rawread()\n", byte);
-#endif
-		return byte;
-	} else
-		return -EBUSY;
-}
-
-
-int aci_rw_cmd(int write1, int write2, int write3)
-{
-	int write[] = {write1, write2, write3};
-	int read = -EINTR, i;
-
-	if (mutex_lock_interruptible(&aci_mutex))
-		goto out;
-
-	for (i=0; i<3; i++) {
-		if (write[i]< 0 || write[i] > 255)
-			break;
-		else {
-			read = aci_rawwrite(write[i]);
-			if (read < 0)
-				goto out_up;
-		}
-		
-	}
-	
-	read = aci_rawread();
-out_up:	mutex_unlock(&aci_mutex);
-out:	return read;
-}
-
-EXPORT_SYMBOL(aci_rw_cmd);
-
-static int setvolume(int __user *arg, 
-		     unsigned char left_index, unsigned char right_index)
-{
-	int vol, ret, uservol, buf;
-
-	__get_user(uservol, arg);
-
-	/* left channel */
-	vol = uservol & 0xff;
-	if (vol > 100)
-		vol = 100;
-	vol = SCALE(100, 0x20, vol);
-	if ((buf=aci_write_cmd(left_index, 0x20 - vol))<0)
-		return buf;
-	ret = SCALE(0x20, 100, vol);
-
-
-	/* right channel */
-	vol = (uservol >> 8) & 0xff;
-	if (vol > 100)
-		vol = 100;
-	vol = SCALE(100, 0x20, vol);
-	if ((buf=aci_write_cmd(right_index, 0x20 - vol))<0)
-		return buf;
-	ret |= SCALE(0x20, 100, vol) << 8;
- 
-	__put_user(ret, arg);
-
-	return 0;
-}
-
-static int getvolume(int __user *arg,
-		     unsigned char left_index, unsigned char right_index)
-{
-	int vol;
-	int buf;
-
-	/* left channel */
-	if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0)
-		return buf;
-	vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
-	
-	/* right channel */
-	if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0)
-		return buf;
-	vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
-
-	__put_user(vol, arg);
-
-	return 0;
-}
-
-
-/* The equalizer is somewhat strange on the ACI. From -12dB to +12dB
- * write:  0xff..down.to..0x80==0x00..up.to..0x7f
- */
-
-static inline unsigned int eq_oss2aci(unsigned int vol)
-{
-	int boost=0;
-	unsigned int ret;
-
-	if (vol > 100)
-		vol = 100;
-	if (vol > 50) {
-		vol -= 51;
-		boost=1;
-	}
-	if (boost)
-		ret=SCALE(49, 0x7e, vol)+1;
-	else
-		ret=0xff - SCALE(50, 0x7f, vol);
-	return ret;
-}
-
-static inline unsigned int eq_aci2oss(unsigned int vol)
-{
-	if (vol < 0x80)
-		return SCALE(0x7f, 50, vol) + 50;
-	else
-		return SCALE(0x7f, 50, 0xff-vol);
-}
-
-
-static int setequalizer(int __user *arg, 
-			unsigned char left_index, unsigned char right_index)
-{
-	int buf;
-	unsigned int vol;
-
-	__get_user(vol, arg);
-
-	/* left channel */
-	if ((buf=aci_write_cmd(left_index, eq_oss2aci(vol & 0xff)))<0)
-		return buf;
-
-	/* right channel */
-	if ((buf=aci_write_cmd(right_index, eq_oss2aci((vol>>8) & 0xff)))<0)
-		return buf;
-
-	/* the ACI equalizer is more precise */
-	return 0;
-}
-
-static int getequalizer(int __user *arg,
-			unsigned char left_index, unsigned char right_index)
-{
-	int buf;
-	unsigned int vol;
-
-	/* left channel */
-	if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0)
-		return buf;
-	vol = eq_aci2oss(buf);
-	
-	/* right channel */
-	if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0)
-		return buf;
-	vol |= eq_aci2oss(buf) << 8;
-
-	__put_user(vol, arg);
-
-	return 0;
-}
-
-static int aci_mixer_ioctl (int dev, unsigned int cmd, void __user * arg)
-{
-	int vol, buf;
-	int __user *p = arg;
-
-	switch (cmd) {
-	case SOUND_MIXER_WRITE_VOLUME:
-		return setvolume(p, 0x01, 0x00);
-	case SOUND_MIXER_WRITE_CD:
-		return setvolume(p, 0x3c, 0x34);
-	case SOUND_MIXER_WRITE_MIC:
-		return setvolume(p, 0x38, 0x30);
-	case SOUND_MIXER_WRITE_LINE:
-		return setvolume(p, 0x39, 0x31);
-	case SOUND_MIXER_WRITE_SYNTH:
-		return setvolume(p, 0x3b, 0x33);
-	case SOUND_MIXER_WRITE_PCM:
-		return setvolume(p, 0x3a, 0x32);
-	case MIXER_WRITE(SOUND_MIXER_RADIO): /* fall through */
-	case SOUND_MIXER_WRITE_LINE1:  /* AUX1 or radio */
-		return setvolume(p, 0x3d, 0x35);
-	case SOUND_MIXER_WRITE_LINE2:  /* AUX2 */
-		return setvolume(p, 0x3e, 0x36);
-	case SOUND_MIXER_WRITE_BASS:   /* set band one and two */
-		if (aci_idcode[1]=='C') {
-			if ((buf=setequalizer(p, 0x48, 0x40)) || 
-			    (buf=setequalizer(p, 0x49, 0x41)));
-			return buf;
-		}
-		break;
-	case SOUND_MIXER_WRITE_TREBLE: /* set band six and seven */
-		if (aci_idcode[1]=='C') {
-			if ((buf=setequalizer(p, 0x4d, 0x45)) || 
-			    (buf=setequalizer(p, 0x4e, 0x46)));
-			return buf;
-		}
-		break;
-	case SOUND_MIXER_WRITE_IGAIN:  /* MIC pre-amp */
-		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
-			__get_user(vol, p);
-			vol = vol & 0xff;
-			if (vol > 100)
-				vol = 100;
-			vol = SCALE(100, 3, vol);
-			if ((buf=aci_write_cmd(ACI_WRITE_IGAIN, vol))<0)
-				return buf;
-			aci_micpreamp = vol;
-			vol = SCALE(3, 100, vol);
-			vol |= (vol << 8);
-			__put_user(vol, p);
-			return 0;
-		}
-		break;
-	case SOUND_MIXER_WRITE_OGAIN:  /* Power-amp/line-out level */
-		if (aci_idcode[1]=='A' || aci_idcode[1]=='B') {
-			__get_user(buf, p);
-			buf = buf & 0xff;
-			if (buf > 50)
-				vol = 1;
-			else
-				vol = 0;
-			if ((buf=aci_write_cmd(ACI_SET_POWERAMP, vol))<0)
-				return buf;
-			aci_amp = vol;
-			if (aci_amp)
-				buf = (100 || 100<<8);
-			else
-				buf = 0;
-			__put_user(buf, p);
-			return 0;
-		}
-		break;
-	case SOUND_MIXER_WRITE_RECSRC:
-		/* handle solo mode control */
-		__get_user(buf, p);
-		/* unset solo when RECSRC for PCM is requested */
-		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
-			vol = !(buf & SOUND_MASK_PCM);
-			if ((buf=aci_write_cmd(ACI_SET_SOLOMODE, vol))<0)
-				return buf;
-			aci_solo = vol;
-		}
-		buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
-		       SOUND_MASK_SYNTH| SOUND_MASK_LINE2);
-		if (aci_idcode[1] == 'C') /* PCM20 radio */
-			buf |= SOUND_MASK_RADIO;
-		else
-			buf |= SOUND_MASK_LINE1;
-		if (!aci_solo)
-			buf |= SOUND_MASK_PCM;
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_DEVMASK:
-		buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD    |
-		       SOUND_MASK_MIC    | SOUND_MASK_LINE  |
-		       SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
-		       SOUND_MASK_LINE2);
-		switch (aci_idcode[1]) {
-		case 'C': /* PCM20 radio */
-			buf |= (SOUND_MASK_RADIO | SOUND_MASK_IGAIN |
-				SOUND_MASK_BASS  | SOUND_MASK_TREBLE);
-			break;
-		case 'B': /* PCM12 */
-			buf |= (SOUND_MASK_LINE1 | SOUND_MASK_IGAIN |
-				SOUND_MASK_OGAIN);
-			break;
-		case 'A': /* PCM1-pro */
-			buf |= (SOUND_MASK_LINE1 | SOUND_MASK_OGAIN);
-			break;
-		default:
-			buf |= SOUND_MASK_LINE1;
-		}
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_STEREODEVS:
-		buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD    |
-		       SOUND_MASK_MIC    | SOUND_MASK_LINE  |
-		       SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
-		       SOUND_MASK_LINE2);
-		switch (aci_idcode[1]) {
-		case 'C': /* PCM20 radio */
-			buf |= (SOUND_MASK_RADIO |
-				SOUND_MASK_BASS  | SOUND_MASK_TREBLE);
-			break;
-		default:
-			buf |= SOUND_MASK_LINE1;
-		}
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_RECMASK:
-		buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
-		       SOUND_MASK_SYNTH| SOUND_MASK_LINE2| SOUND_MASK_PCM);
-		if (aci_idcode[1] == 'C') /* PCM20 radio */
-			buf |= SOUND_MASK_RADIO;
-		else
-			buf |= SOUND_MASK_LINE1;
-
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_RECSRC:
-		buf = (SOUND_MASK_CD    | SOUND_MASK_MIC   | SOUND_MASK_LINE  |
-		       SOUND_MASK_SYNTH | SOUND_MASK_LINE2);
-		/* do we need aci_solo or can I get it from the ACI? */
-		switch (aci_idcode[1]) {
-		case 'B': /* PCM12 */
-		case 'C': /* PCM20 radio */
-			if (aci_version >= 0xb0) {
-				if ((vol=aci_rw_cmd(ACI_STATUS,
-						    ACI_S_GENERAL, -1))<0)
-					return vol;
-				if (vol & 0x20)
-					buf |= SOUND_MASK_PCM;
-			}
-			else
-				if (!aci_solo)
-					buf |= SOUND_MASK_PCM;
-			break;
-		default:
-			buf |= SOUND_MASK_PCM;
-		}
-		if (aci_idcode[1] == 'C') /* PCM20 radio */
-			buf |= SOUND_MASK_RADIO;
-		else
-			buf |= SOUND_MASK_LINE1;
-
-		__put_user(buf, p);
-		return 0;
-	case SOUND_MIXER_READ_CAPS:
-		__put_user(0, p);
-		return 0;
-	case SOUND_MIXER_READ_VOLUME:
-		return getvolume(p, 0x04, 0x03);
-	case SOUND_MIXER_READ_CD:
-		return getvolume(p, 0x0a, 0x09);
-	case SOUND_MIXER_READ_MIC:
-		return getvolume(p, 0x06, 0x05);
-	case SOUND_MIXER_READ_LINE:
-		return getvolume(p, 0x08, 0x07);
-	case SOUND_MIXER_READ_SYNTH:
-		return getvolume(p, 0x0c, 0x0b);
-	case SOUND_MIXER_READ_PCM:
-		return getvolume(p, 0x0e, 0x0d);
-	case MIXER_READ(SOUND_MIXER_RADIO): /* fall through */
-	case SOUND_MIXER_READ_LINE1:  /* AUX1 */
-		return getvolume(p, 0x11, 0x10);
-	case SOUND_MIXER_READ_LINE2:  /* AUX2 */
-		return getvolume(p, 0x13, 0x12);
-	case SOUND_MIXER_READ_BASS:   /* get band one */
-		if (aci_idcode[1]=='C') {
-			return getequalizer(p, 0x23, 0x22);
-		}
-		break;
-	case SOUND_MIXER_READ_TREBLE: /* get band seven */
-		if (aci_idcode[1]=='C') {
-			return getequalizer(p, 0x2f, 0x2e);
-		}
-		break;
-	case SOUND_MIXER_READ_IGAIN:  /* MIC pre-amp */
-		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
-			/* aci_micpreamp or ACI? */
-			if (aci_version >= 0xb0) {
-				if ((buf=aci_indexed_cmd(ACI_STATUS,
-							 ACI_S_READ_IGAIN))<0)
-					return buf;
-			}
-			else
-				buf=aci_micpreamp;
-			vol = SCALE(3, 100, buf <= 3 ? buf : 3);
-			vol |= vol << 8;
-			__put_user(vol, p);
-			return 0;
-		}
-		break;
-	case SOUND_MIXER_READ_OGAIN:
-		if (aci_amp)
-			buf = (100 || 100<<8);
-		else
-			buf = 0;
-		__put_user(buf, p);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static struct mixer_operations aci_mixer_operations =
-{
-	.owner = THIS_MODULE,
-	.id    = "ACI",
-	.ioctl = aci_mixer_ioctl
-};
-
-/*
- * There is also an internal mixer in the codec (CS4231A or AD1845),
- * that deserves no purpose in an ACI based system which uses an
- * external ACI controlled stereo mixer. Make sure that this codec
- * mixer has the AUX1 input selected as the recording source, that the
- * input gain is set near maximum and that the other channels going
- * from the inputs to the codec output are muted.
- */
-
-static int __init attach_aci(void)
-{
-	char *boardname;
-	int i, rc = -EBUSY;
-
-	mutex_init(&aci_mutex);
-
-	outb(0xE3, 0xf8f); /* Write MAD16 password */
-	aci_port = (inb(0xf90) & 0x10) ?
-		0x344: 0x354; /* Get aci_port from MC4_PORT */
-
-	if (!request_region(aci_port, 3, "sound mixer (ACI)")) {
-		printk(KERN_NOTICE
-		       "aci: I/O area 0x%03x-0x%03x already used.\n",
-		       aci_port, aci_port+2);
-		goto out;
-	}
-
-	/* force ACI into a known state */
-	rc = -EFAULT;
-	for (i=0; i<3; i++)
-		if (aci_rw_cmd(ACI_ERROR_OP, -1, -1)<0)
-			goto out_release_region;
-
-	/* official this is one aci read call: */
-	rc = -EFAULT;
-	if ((aci_idcode[0]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0 ||
-	    (aci_idcode[1]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0) {
-		printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n",
-		       aci_port);
-		goto out_release_region;
-	}
-
-	if ((aci_version=aci_rw_cmd(ACI_READ_VERSION, -1, -1))<0) {
-		printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n",
-		       aci_port);
-		goto out_release_region;
-	}
-
-	if (aci_idcode[0] == 'm') {
-		/* It looks like a miro sound card. */
-		switch (aci_idcode[1]) {
-		case 'A':
-			boardname = "PCM1 pro / early PCM12";
-			break;
-		case 'B':
-			boardname = "PCM12";
-			break;
-		case 'C':
-			boardname = "PCM20 radio";
-			break;
-		default:
-			boardname = "unknown miro";
-		}
-	} else {
-		printk(KERN_WARNING "aci: Warning: unsupported card! - "
-		       "no hardware, no specs...\n");
-		boardname = "unknown Cardinal Technologies";
-	}
-
-	printk(KERN_INFO "<ACI 0x%02x, id %02x/%02x \"%c/%c\", (%s)> at 0x%03x\n",
-	       aci_version,
-	       aci_idcode[0], aci_idcode[1],
-	       aci_idcode[0], aci_idcode[1],
-	       boardname, aci_port);
-
-	rc = -EBUSY;
-	if (reset) {
-		/* first write()s after reset fail with my PCM20 */
-		if (aci_rw_cmd(ACI_INIT, -1, -1)<0 ||
-		    aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0 ||
-		    aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0)
-			goto out_release_region;
-	}
-
-	/* the PCM20 is muted after reset (and reboot) */
-	if (aci_rw_cmd(ACI_SET_MUTE, 0x00, -1)<0)
-		goto out_release_region;
-
-	if (ide>=0)
-		if (aci_rw_cmd(ACI_SET_IDE, !ide, -1)<0)
-			goto out_release_region;
-	
-	if (wss>=0 && aci_idcode[1]=='A')
-		if (aci_rw_cmd(ACI_SET_WSS, !!wss, -1)<0)
-			goto out_release_region;
-
-	mixer_device = sound_install_mixer(MIXER_DRIVER_VERSION, boardname,
-					   &aci_mixer_operations,
-					   sizeof(aci_mixer_operations), NULL);
-	rc = 0;
-	if (mixer_device < 0) {
-		printk(KERN_ERR "aci: Failed to install mixer.\n");
-		rc = mixer_device;
-		goto out_release_region;
-	} /* else Maybe initialize the CS4231A mixer here... */
-out:	return rc;
-out_release_region:
-	release_region(aci_port, 3);
-	goto out;
-}
-
-static void __exit unload_aci(void)
-{
-	sound_unload_mixerdev(mixer_device);
-	release_region(aci_port, 3);
-}
-
-module_init(attach_aci);
-module_exit(unload_aci);
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/aci.h b/sound/oss/aci.h
deleted file mode 100644
index 20102ee..0000000
--- a/sound/oss/aci.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef _ACI_H_
-#define _ACI_H_
-
-extern int aci_port;
-extern int aci_version;		/* ACI firmware version	*/
-extern int aci_rw_cmd(int write1, int write2, int write3);
-
-#define aci_indexed_cmd(a, b) aci_rw_cmd(a, b, -1)
-#define aci_write_cmd(a, b)   aci_rw_cmd(a, b, -1)
-#define aci_read_cmd(a)       aci_rw_cmd(a,-1, -1)
-
-#define COMMAND_REGISTER    (aci_port)      /* write register */
-#define STATUS_REGISTER     (aci_port + 1)  /* read register */
-#define BUSY_REGISTER       (aci_port + 2)  /* also used for rds */
-
-#define RDS_REGISTER        BUSY_REGISTER
-
-#define ACI_SET_MUTE          0x0d
-#define ACI_SET_POWERAMP      0x0f
-#define ACI_SET_TUNERMUTE     0xa3
-#define ACI_SET_TUNERMONO     0xa4
-#define ACI_SET_IDE           0xd0
-#define ACI_SET_WSS           0xd1
-#define ACI_SET_SOLOMODE      0xd2
-#define ACI_WRITE_IGAIN       0x03
-#define ACI_WRITE_TUNE        0xa7
-#define ACI_READ_TUNERSTEREO  0xa8
-#define ACI_READ_TUNERSTATION 0xa9
-#define ACI_READ_VERSION      0xf1
-#define ACI_READ_IDCODE       0xf2
-#define ACI_INIT              0xff
-#define ACI_STATUS            0xf0
-#define     ACI_S_GENERAL     0x00
-#define     ACI_S_READ_IGAIN  0x21
-#define ACI_ERROR_OP          0xdf
-
-/*
- * The following macro SCALE can be used to scale one integer volume
- * value into another one using only integer arithmetic. If the input
- * value x is in the range 0 <= x <= xmax, then the result will be in
- * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
- *
- * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
- * following nice properties:
- *
- * - SCALE(xmax,ymax,xmax) = ymax
- * - SCALE(xmax,ymax,0) = 0
- * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
- *
- * In addition, the rounding error is minimal and nicely distributed.
- * The proofs are left as an exercise to the reader.
- */
-
-#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
-
-
-#endif  /* _ACI_H_ */
diff --git a/sound/oss/ad1816.c b/sound/oss/ad1816.c
deleted file mode 100644
index caabf31..0000000
--- a/sound/oss/ad1816.c
+++ /dev/null
@@ -1,1368 +0,0 @@
-/*
- *
- * AD1816 lowlevel sound driver for Linux 2.6.0 and above
- *
- * Copyright (C) 1998-2003 by Thorsten Knabe <linux@thorsten-knabe.de>
- *
- * Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
- *
- *
- * version: 1.5
- * status: beta
- * date: 2003/07/15
- *
- * Changes:
- *	Oleg Drokin: Some cleanup of load/unload functions.	1998/11/24
- *	
- *	Thorsten Knabe: attach and unload rewritten, 
- *	some argument checks added				1998/11/30
- *
- *	Thorsten Knabe: Buggy isa bridge workaround added	1999/01/16
- *	
- *	David Moews/Thorsten Knabe: Introduced options 
- *	parameter. Added slightly modified patch from 
- *	David Moews to disable dsp audio sources by setting 
- *	bit 0 of options parameter. This seems to be
- *	required by some Aztech/Newcom SC-16 cards.		1999/04/18
- *
- *	Christoph Hellwig: Adapted to module_init/module_exit.	2000/03/03
- *
- *	Christoph Hellwig: Added isapnp support			2000/03/15
- *
- *	Arnaldo Carvalho de Melo: get rid of check_region	2001/10/07
- *      
- *      Thorsten Knabe: Compiling with CONFIG_PNP enabled
- *	works again. It is now possible to use more than one 
- *	AD1816 sound card. Sample rate now may be changed during
- *	playback/capture. printk() uses log levels everywhere.
- *	SMP fixes. DMA handling fixes.
- *	Other minor code cleanup.				2003/07/15
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/isapnp.h>
-#include <linux/stddef.h>
-#include <linux/spinlock.h>
-#include "sound_config.h"
-
-#define DEBUGNOISE(x)
-
-#define CHECK_FOR_POWER { int timeout=100; \
-  while (timeout > 0 && (inb(devc->base)&0x80)!= 0x80) {\
-          timeout--; \
-  } \
-  if (timeout==0) {\
-          printk(KERN_WARNING "ad1816: Check for power failed in %s line: %d\n",__FILE__,__LINE__); \
-  } \
-}
-
-/* structure to hold device specific information */
-typedef struct
-{
-        int            base;          /* set in attach */
-	int            irq;
-	int            dma_playback;
-        int            dma_capture;
-  
-	int            opened;         /* open */
-        int            speed;	
-	int            channels;
-	int            audio_format;
-        int            audio_mode; 
-  
-        int            recmask;        /* setup */
-	unsigned char  format_bits;
-	int            supported_devices;
-	int            supported_rec_devices;
-	unsigned short levels[SOUND_MIXER_NRDEVICES];
-					/* misc */
-	struct pnp_dev *pnpdev;	 /* configured via pnp */
-        int            dev_no;   /* this is the # in audio_devs and NOT 
-				    in ad1816_info */
-	spinlock_t	lock;  
-} ad1816_info;
-
-static int nr_ad1816_devs;
-static int ad1816_clockfreq = 33000;
-static int options;
-
-/* supported audio formats */
-static int  ad_format_mask =
-AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW;
-
-/* array of device info structures */
-static ad1816_info dev_info[MAX_AUDIO_DEV];
-
-
-/* ------------------------------------------------------------------- */
-
-/* functions for easier access to inderect registers */
-
-static int ad_read (ad1816_info * devc, int reg)
-{
-	int result;
-	
-	CHECK_FOR_POWER;
-	outb ((unsigned char) (reg & 0x3f), devc->base+0);
-	result = inb(devc->base+2);
-	result+= inb(devc->base+3)<<8;
-	return (result);
-}
-
-
-static void ad_write (ad1816_info * devc, int reg, int data)
-{
-	CHECK_FOR_POWER;
-	outb ((unsigned char) (reg & 0xff), devc->base+0);
-	outb ((unsigned char) (data & 0xff),devc->base+2);
-	outb ((unsigned char) ((data>>8)&0xff),devc->base+3);
-}
-
-/* ------------------------------------------------------------------- */
-
-/* function interface required by struct audio_driver */
-
-static void ad1816_halt_input (int dev)
-{
-	unsigned long flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	unsigned char buffer;
-	
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: halt_input called\n"));
-	
-	spin_lock_irqsave(&devc->lock,flags); 
-	
-	if(!isa_dma_bridge_buggy) {
-	        disable_dma(audio_devs[dev]->dmap_in->dma);
-	}
-	
-	buffer=inb(devc->base+9);
-	if (buffer & 0x01) {
-		/* disable capture */
-		outb(buffer & ~0x01,devc->base+9); 
-	}
-
-	if(!isa_dma_bridge_buggy) {
-	        enable_dma(audio_devs[dev]->dmap_in->dma);
-	}
-
-	/* Clear interrupt status */
-	outb (~0x40, devc->base+1);	
-	
-	devc->audio_mode &= ~PCM_ENABLE_INPUT;
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static void ad1816_halt_output (int dev)
-{
-	unsigned long  flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	unsigned char buffer;
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: halt_output called!\n"));
-
-	spin_lock_irqsave(&devc->lock,flags); 
-	/* Mute pcm output */
-	ad_write(devc, 4, ad_read(devc,4)|0x8080);
-
-	if(!isa_dma_bridge_buggy) {
-	        disable_dma(audio_devs[dev]->dmap_out->dma);
-	}
-
-	buffer=inb(devc->base+8);
-	if (buffer & 0x01) {
-		/* disable capture */
-		outb(buffer & ~0x01,devc->base+8); 
-	}
-
-	if(!isa_dma_bridge_buggy) {
-	        enable_dma(audio_devs[dev]->dmap_out->dma);
-	}
-
-	/* Clear interrupt status */
-	outb ((unsigned char)~0x80, devc->base+1);	
-
-	devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static void ad1816_output_block (int dev, unsigned long buf, 
-				 int count, int intrflag)
-{
-	unsigned long flags;
-	unsigned long cnt;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: output_block called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
-  
-	cnt = count/4 - 1;
-  
-	spin_lock_irqsave(&devc->lock,flags);
-	
-	/* set transfer count */
-	ad_write (devc, 8, cnt & 0xffff); 
-	
-	devc->audio_mode |= PCM_ENABLE_OUTPUT; 
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-static void ad1816_start_input (int dev, unsigned long buf, int count,
-				int intrflag)
-{
-	unsigned long flags;
-	unsigned long  cnt;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: start_input called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
-
-	cnt = count/4 - 1;
-
-	spin_lock_irqsave(&devc->lock,flags);
-
-	/* set transfer count */
-	ad_write (devc, 10, cnt & 0xffff); 
-	devc->audio_mode |= PCM_ENABLE_INPUT;
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static int ad1816_prepare_for_input (int dev, int bsize, int bcount)
-{
-	unsigned long flags;
-	unsigned int freq;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	unsigned char fmt_bits;
-	
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: prepare_for_input called: bsize=%d bcount=%d\n",bsize,bcount));
-
-	spin_lock_irqsave(&devc->lock,flags);
-	fmt_bits= (devc->format_bits&0x7)<<3;
-	
-	/* set mono/stereo mode */
-	if (devc->channels > 1) {
-		fmt_bits |=0x4;
-	}
-	/* set Mono/Stereo in playback/capture register */
-	outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8); 
-	outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
-
-	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
-
-	/* write playback/capture speeds */
-	ad_write (devc, 2, freq & 0xffff);	
-	ad_write (devc, 3, freq & 0xffff);	
-
-	spin_unlock_irqrestore(&devc->lock,flags);
-
-	ad1816_halt_input(dev);
-	return 0;
-}
-
-static int ad1816_prepare_for_output (int dev, int bsize, int bcount)
-{
-	unsigned long flags;
-	unsigned int freq;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	unsigned char fmt_bits;
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: prepare_for_output called: bsize=%d bcount=%d\n",bsize,bcount));
-
-	spin_lock_irqsave(&devc->lock,flags);
-
-	fmt_bits= (devc->format_bits&0x7)<<3;
-	/* set mono/stereo mode */
-	if (devc->channels > 1) {
-		fmt_bits |=0x4;
-	}
-
-	/* write format bits to playback/capture registers */
-	outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8); 
-	outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
-  
-	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
-	
-	/* write playback/capture speeds */
-	ad_write (devc, 2, freq & 0xffff);
-	ad_write (devc, 3, freq & 0xffff);
-
-	spin_unlock_irqrestore(&devc->lock,flags);
-	
-	ad1816_halt_output(dev);
-	return 0;
-
-}
-
-static void ad1816_trigger (int dev, int state) 
-{
-	unsigned long flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: trigger called! (devc=%d,devc->base=%d\n", devc, devc->base));
-
-	/* mode may have changed */
-
-	spin_lock_irqsave(&devc->lock,flags);
-
-	/* mask out modes not specified on open call */
-	state &= devc->audio_mode; 
-				
-	/* setup soundchip to new io-mode */
-	if (state & PCM_ENABLE_INPUT) {
-		/* enable capture */
-		outb(inb(devc->base+9)|0x01, devc->base+9);
-	} else {
-		/* disable capture */
-		outb(inb(devc->base+9)&~0x01, devc->base+9);
-	}
-
-	if (state & PCM_ENABLE_OUTPUT) {
-		/* enable playback */
-		outb(inb(devc->base+8)|0x01, devc->base+8);
-		/* unmute pcm output */
-		ad_write(devc, 4, ad_read(devc,4)&~0x8080);
-	} else {
-		/* mute pcm output */
-		ad_write(devc, 4, ad_read(devc,4)|0x8080);
-		/* disable capture */
-		outb(inb(devc->base+8)&~0x01, devc->base+8);
-	}
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-/* halt input & output */
-static void ad1816_halt (int dev)
-{
-	ad1816_halt_input(dev);
-	ad1816_halt_output(dev);
-}
-
-static void ad1816_reset (int dev)
-{
-	ad1816_halt (dev);
-}
-
-/* set playback speed */
-static int ad1816_set_speed (int dev, int arg)
-{
-	unsigned long flags;
-	unsigned int freq;
-	int ret;
-
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	spin_lock_irqsave(&devc->lock, flags);
-	if (arg == 0) {
-		ret = devc->speed;
-		spin_unlock_irqrestore(&devc->lock, flags);
-		return ret;
-	}
-	/* range checking */
-	if (arg < 4000) {
-		arg = 4000;
-	}
-	if (arg > 55000) {
-		arg = 55000;
-	}
-	devc->speed = arg;
-
-	/* change speed during playback */
-	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
-	/* write playback/capture speeds */
-	ad_write (devc, 2, freq & 0xffff);	
-	ad_write (devc, 3, freq & 0xffff);	
-
-	ret = devc->speed;
-	spin_unlock_irqrestore(&devc->lock, flags);
-	return ret;
-
-}
-
-static unsigned int ad1816_set_bits (int dev, unsigned int arg)
-{
-	unsigned long flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-	
-	static struct format_tbl {
-		int             format;
-		unsigned char   bits;
-	} format2bits[] = {
-		{ 0, 0 },
-		{ AFMT_MU_LAW, 1 },
-		{ AFMT_A_LAW, 3 },
-		{ AFMT_IMA_ADPCM, 0 },
-		{ AFMT_U8, 0 },
-		{ AFMT_S16_LE, 2 },
-		{ AFMT_S16_BE, 6 },
-		{ AFMT_S8, 0 },
-		{ AFMT_U16_LE, 0 },
-		{ AFMT_U16_BE, 0 }
-  	};
-
-	int  i, n = sizeof (format2bits) / sizeof (struct format_tbl);
-
-	spin_lock_irqsave(&devc->lock, flags);
-	/* return current format */
-	if (arg == 0) {
-	  	arg = devc->audio_format;
-		spin_unlock_irqrestore(&devc->lock, flags);
-		return arg;
-	}
-	devc->audio_format = arg;
-
-	/* search matching format bits */
-	for (i = 0; i < n; i++)
-		if (format2bits[i].format == arg) {
-			devc->format_bits = format2bits[i].bits;
-			devc->audio_format = arg;
-			spin_unlock_irqrestore(&devc->lock, flags);
-			return arg;
-		}
-
-	/* Still hanging here. Something must be terribly wrong */
-	devc->format_bits = 0;
-	devc->audio_format = AFMT_U8;
-	spin_unlock_irqrestore(&devc->lock, flags);
-	return(AFMT_U8); 
-}
-
-static short ad1816_set_channels (int dev, short arg)
-{
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-
-	if (arg != 1 && arg != 2)
-		return devc->channels;
-
-	devc->channels = arg;
-	return arg;
-}
-
-/* open device */
-static int ad1816_open (int dev, int mode) 
-{
-	ad1816_info    *devc = NULL;
-	unsigned long   flags;
-
-	/* is device number valid ? */
-	if (dev < 0 || dev >= num_audiodevs)
-		return -(ENXIO);
-
-	/* get device info of this dev */
-	devc = (ad1816_info *) audio_devs[dev]->devc; 
-
-	/* make check if device already open atomic */
-	spin_lock_irqsave(&devc->lock,flags);
-
-	if (devc->opened) {
-		spin_unlock_irqrestore(&devc->lock,flags);
-		return -(EBUSY);
-	}
-
-	/* mark device as open */
-	devc->opened = 1; 
-
-	devc->audio_mode = 0;
-	devc->speed = 8000;
-	devc->audio_format=AFMT_U8;
-	devc->channels=1;
-	spin_unlock_irqrestore(&devc->lock,flags);
-	ad1816_reset(devc->dev_no); /* halt all pending output */
-	return 0;
-}
-
-static void ad1816_close (int dev) /* close device */
-{
-	unsigned long flags;
-	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
-
-	/* halt all pending output */
-	ad1816_reset(devc->dev_no); 
-
-	spin_lock_irqsave(&devc->lock,flags);
-	devc->opened = 0;
-	devc->audio_mode = 0;
-	devc->speed = 8000;
-	devc->audio_format=AFMT_U8;
-	devc->format_bits = 0;
-	spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-/* ------------------------------------------------------------------- */
-
-/* Audio driver structure */
-
-static struct audio_driver ad1816_audio_driver =
-{
-	.owner			= THIS_MODULE,
-	.open			= ad1816_open,
-	.close			= ad1816_close,
-	.output_block		= ad1816_output_block,
-	.start_input		= ad1816_start_input,
-	.prepare_for_input	= ad1816_prepare_for_input,
-	.prepare_for_output	= ad1816_prepare_for_output,
-	.halt_io		= ad1816_halt,
-	.halt_input		= ad1816_halt_input,
-	.halt_output		= ad1816_halt_output,
-	.trigger		= ad1816_trigger,
-	.set_speed		= ad1816_set_speed,
-	.set_bits		= ad1816_set_bits,
-	.set_channels		= ad1816_set_channels,
-};
-
-
-/* ------------------------------------------------------------------- */
-
-/* Interrupt handler */
-
-
-static irqreturn_t ad1816_interrupt (int irq, void *dev_id)
-{
-	unsigned char	status;
-	ad1816_info	*devc = (ad1816_info *)dev_id;
-	
-	if (irq < 0 || irq > 15) {
-	        printk(KERN_WARNING "ad1816: Got bogus interrupt %d\n", irq);
-		return IRQ_NONE;
-	}
-
-	spin_lock(&devc->lock);
-
-	/* read interrupt register */
-	status = inb (devc->base+1); 
-	/* Clear all interrupt  */
-	outb (~status, devc->base+1);	
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: Got interrupt subclass %d\n",status));
-
-	if (status == 0) {
-		DEBUGNOISE(printk(KERN_DEBUG "ad1816: interrupt: Got interrupt, but no source.\n"));
-		spin_unlock(&devc->lock);
-		return IRQ_NONE;
-	}
-
-	if (devc->opened && (devc->audio_mode & PCM_ENABLE_INPUT) && (status&64))
-		DMAbuf_inputintr (devc->dev_no);
-
-	if (devc->opened && (devc->audio_mode & PCM_ENABLE_OUTPUT) && (status & 128))
-		DMAbuf_outputintr (devc->dev_no, 1);
-
-	spin_unlock(&devc->lock);
-	return IRQ_HANDLED;
-}
-
-/* ------------------------------------------------------------------- */
-
-/* Mixer stuff */
-
-struct mixer_def {
-	unsigned int regno: 7;
-	unsigned int polarity:1;	/* 0=normal, 1=reversed */
-	unsigned int bitpos:4;
-	unsigned int nbits:4;
-};
-
-static char mix_cvt[101] = {
-	 0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
-	43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
-	65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
-	80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
-	91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
-	100
-};
-
-typedef struct mixer_def mixer_ent;
-
-/*
- * Most of the mixer entries work in backwards. Setting the polarity field
- * makes them to work correctly.
- *
- * The channel numbering used by individual soundcards is not fixed. Some
- * cards have assigned different meanings for the AUX1, AUX2 and LINE inputs.
- * The current version doesn't try to compensate this.
- */
-
-#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r)	\
-  {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
-
-
-static mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
-MIX_ENT(SOUND_MIXER_VOLUME,	14, 1, 8, 5,	14, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH,	 5, 1, 8, 6,	 5, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_PCM,	 4, 1, 8, 6,	 4, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_SPEAKER,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE,	18, 1, 8, 5,	18, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_MIC,	19, 1, 8, 5,	19, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_CD,	 	15, 1, 8, 5,	15, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_IMIX,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV,	20, 0, 8, 4,	20, 0, 0, 4),
-MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE1, 	17, 1, 8, 5,	17, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE2,	16, 1, 8, 5,	16, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE3,      39, 0, 9, 4,    39, 1, 0, 5)
-};
-
-
-static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
-{
-	0x4343,		/* Master Volume */
-	0x3232,		/* Bass */
-	0x3232,		/* Treble */
-	0x0000,		/* FM */
-	0x4343,		/* PCM */
-	0x0000,		/* PC Speaker */
-	0x0000,		/* Ext Line */
-	0x0000,		/* Mic */
-	0x0000,		/* CD */
-	0x0000,		/* Recording monitor */
-	0x0000,		/* SB PCM */
-	0x0000,		/* Recording level */
-	0x0000,		/* Input gain */
-	0x0000,		/* Output gain */
-	0x0000,		/* Line1 */
-	0x0000,		/* Line2 */
-	0x0000		/* Line3 (usually line in)*/
-};
-
-#define LEFT_CHN	0
-#define RIGHT_CHN	1
-
-
-
-static int
-ad1816_set_recmask (ad1816_info * devc, int mask)
-{
-  	unsigned long 	flags;
-	unsigned char   recdev;
-	int             i, n;
-	
-	spin_lock_irqsave(&devc->lock, flags);
-	mask &= devc->supported_rec_devices;
-	
-	n = 0;
-	/* Count selected device bits */
-	for (i = 0; i < 32; i++)
-		if (mask & (1 << i))
-			n++;
-	
-	if (n == 0)
-		mask = SOUND_MASK_MIC;
-	else if (n != 1) { /* Too many devices selected */
-		/* Filter out active settings */
-		mask &= ~devc->recmask;	
-		
-		n = 0;
-		/* Count selected device bits */
-		for (i = 0; i < 32; i++) 
-			if (mask & (1 << i))
-				n++;
-		
-		if (n != 1)
-			mask = SOUND_MASK_MIC;
-	}
-	
-	switch (mask) {
-	case SOUND_MASK_MIC:
-		recdev = 5;
-		break;
-		
-	case SOUND_MASK_LINE:
-		recdev = 0;
-		break;
-		
-	case SOUND_MASK_CD:
-		recdev = 2;
-		break;
-		
-	case SOUND_MASK_LINE1:
-		recdev = 4;
-		break;
-		
-	case SOUND_MASK_LINE2:
-		recdev = 3;
-		break;
-		
-	case SOUND_MASK_VOLUME:
-		recdev = 1;
-		break;
-		
-	default:
-		mask = SOUND_MASK_MIC;
-		recdev = 5;
-	}
-	
-	recdev <<= 4;
-	ad_write (devc, 20, 
-		  (ad_read (devc, 20) & 0x8f8f) | recdev | (recdev<<8));
-
-	devc->recmask = mask;
-	spin_unlock_irqrestore(&devc->lock, flags);
-	return mask;
-}
-
-static void
-change_bits (int *regval, int dev, int chn, int newval)
-{
-	unsigned char   mask;
-	int             shift;
-  
-	/* Reverse polarity*/
-
-	if (mix_devices[dev][chn].polarity == 1) 
-		newval = 100 - newval;
-
-	mask = (1 << mix_devices[dev][chn].nbits) - 1;
-	shift = mix_devices[dev][chn].bitpos;
-	/* Scale it */
-	newval = (int) ((newval * mask) + 50) / 100;	
-	/* Clear bits */
-	*regval &= ~(mask << shift);	
-	/* Set new value */
-	*regval |= (newval & mask) << shift;	
-}
-
-static int
-ad1816_mixer_get (ad1816_info * devc, int dev)
-{
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_get called!\n"));
-	
-	/* range check + supported mixer check */
-	if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES )
-	        return (-(EINVAL));
-	if (!((1 << dev) & devc->supported_devices))
-		return -(EINVAL);
-	
-	return devc->levels[dev];
-}
-
-static int
-ad1816_mixer_set (ad1816_info * devc, int dev, int value)
-{
-	int   left = value & 0x000000ff;
-	int   right = (value & 0x0000ff00) >> 8;
-	int   retvol;
-
-	int   regoffs;
-	int   val;
-	int   valmute;
-	unsigned long flags;
-
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_set called!\n"));
-	
-	if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES )
-		return -(EINVAL);
-
-	if (left > 100)
-		left = 100;
-	if (left < 0)
-		left = 0;
-	if (right > 100)
-		right = 100;
-	if (right < 0)
-		right = 0;
-	
-	/* Mono control */
-	if (mix_devices[dev][RIGHT_CHN].nbits == 0) 
-		right = left;
-	retvol = left | (right << 8);
-	
-	/* Scale it */
-	
-	left = mix_cvt[left];
-	right = mix_cvt[right];
-
-	/* reject all mixers that are not supported */
-	if (!(devc->supported_devices & (1 << dev)))
-		return -(EINVAL);
-	
-	/* sanity check */
-	if (mix_devices[dev][LEFT_CHN].nbits == 0)
-		return -(EINVAL);
-	spin_lock_irqsave(&devc->lock, flags);
-
-	/* keep precise volume internal */
-	devc->levels[dev] = retvol;
-
-	/* Set the left channel */
-	regoffs = mix_devices[dev][LEFT_CHN].regno;
-	val = ad_read (devc, regoffs);
-	change_bits (&val, dev, LEFT_CHN, left);
-
-	valmute=val;
-
-	/* Mute bit masking on some registers */
-	if ( regoffs==5 || regoffs==14 || regoffs==15 ||
-	     regoffs==16 || regoffs==17 || regoffs==18 || 
-	     regoffs==19 || regoffs==39) {
-		if (left==0)
-			valmute |= 0x8000;
-		else
-			valmute &= ~0x8000;
-	}
-	ad_write (devc, regoffs, valmute); /* mute */
-
-	/*
-	 * Set the right channel
-	 */
- 
-	/* Was just a mono channel */
-	if (mix_devices[dev][RIGHT_CHN].nbits == 0) {
-		spin_unlock_irqrestore(&devc->lock, flags);
-		return retvol;		
-	}
-
-	regoffs = mix_devices[dev][RIGHT_CHN].regno;
-	val = ad_read (devc, regoffs);
-	change_bits (&val, dev, RIGHT_CHN, right);
-
-	valmute=val;
-	if ( regoffs==5 || regoffs==14 || regoffs==15 ||
-	     regoffs==16 || regoffs==17 || regoffs==18 || 
-	     regoffs==19 || regoffs==39) {
-		if (right==0)
-			valmute |= 0x80;
-		else
-			valmute &= ~0x80;
-	}
-	ad_write (devc, regoffs, valmute); /* mute */
-	spin_unlock_irqrestore(&devc->lock, flags);
-       	return retvol;
-}
-
-#define MIXER_DEVICES ( SOUND_MASK_VOLUME | \
-			SOUND_MASK_SYNTH | \
-			SOUND_MASK_PCM | \
-			SOUND_MASK_LINE | \
-			SOUND_MASK_LINE1 | \
-			SOUND_MASK_LINE2 | \
-			SOUND_MASK_LINE3 | \
-			SOUND_MASK_MIC | \
-			SOUND_MASK_CD | \
-			SOUND_MASK_RECLEV  \
-			)
-#define REC_DEVICES ( SOUND_MASK_LINE2 |\
-		      SOUND_MASK_LINE |\
-		      SOUND_MASK_LINE1 |\
-		      SOUND_MASK_MIC |\
-		      SOUND_MASK_CD |\
-		      SOUND_MASK_VOLUME \
-		      )
-     
-static void
-ad1816_mixer_reset (ad1816_info * devc)
-{
-	int  i;
-
-	devc->supported_devices = MIXER_DEVICES;
-	
-	devc->supported_rec_devices = REC_DEVICES;
-
-	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-		if (devc->supported_devices & (1 << i))
-			ad1816_mixer_set (devc, i, default_mixer_levels[i]);
-	ad1816_set_recmask (devc, SOUND_MASK_MIC);
-}
-
-static int
-ad1816_mixer_ioctl (int dev, unsigned int cmd, void __user * arg)
-{
-	ad1816_info    *devc = mixer_devs[dev]->devc;
-	int val;
-	int __user *p = arg;
-  
-	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_ioctl called!\n"));
-  
-	/* Mixer ioctl */
-	if (((cmd >> 8) & 0xff) == 'M') { 
-		
-		/* set ioctl */
-		if (_SIOC_DIR (cmd) & _SIOC_WRITE) { 
-			switch (cmd & 0xff){
-			case SOUND_MIXER_RECSRC:
-				
-				if (get_user(val, p))
-					return -EFAULT;
-				val=ad1816_set_recmask (devc, val);
-				return put_user(val, p);
-				break;
-				
-			default:
-				if (get_user(val, p))
-					return -EFAULT;
-				if ((val=ad1816_mixer_set (devc, cmd & 0xff, val))<0)
-				        return val;
-				else
-				        return put_user(val, p);
-			}
-		} else { 
-			/* read ioctl */
-			switch (cmd & 0xff) {
-				
-			case SOUND_MIXER_RECSRC:
-				val=devc->recmask;
-				return put_user(val, p);
-				break;
-				
-			case SOUND_MIXER_DEVMASK:
-				val=devc->supported_devices;
-				return put_user(val, p);
-				break;
-
-			case SOUND_MIXER_STEREODEVS:
-				val=devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
-				return put_user(val, p);
-				break;
-				
-			case SOUND_MIXER_RECMASK:
-				val=devc->supported_rec_devices;
-				return put_user(val, p);
-				break;
-				
-			case SOUND_MIXER_CAPS:
-				val=SOUND_CAP_EXCL_INPUT;
-				return put_user(val, p);
-				break;
-				
-			default:
-			        if ((val=ad1816_mixer_get (devc, cmd & 0xff))<0)
-				        return val;
-				else
-				        return put_user(val, p);
-			}
-		}
-	} else
-		/* not for mixer */
-		return -(EINVAL);
-}
-
-/* ------------------------------------------------------------------- */
-
-/* Mixer structure */
-
-static struct mixer_operations ad1816_mixer_operations = {
-	.owner	= THIS_MODULE,
-	.id	= "AD1816",
-	.name	= "AD1816 Mixer",
-	.ioctl	= ad1816_mixer_ioctl
-};
-
-
-/* ------------------------------------------------------------------- */
-
-/* stuff for card recognition, init and unloading PNP ...*/
-
-
-/* check if AD1816 present at specified hw_config and register device with OS 
- * return 1 if initialization was successful, 0 otherwise
- */
-static int __init ad1816_init_card (struct address_info *hw_config, 
-	struct pnp_dev *pnp)
-{
-	ad1816_info    *devc = NULL;
-	int tmp;
-	int oss_devno = -1;
-
-	printk(KERN_INFO "ad1816: initializing card: io=0x%x, irq=%d, dma=%d, "
-			 "dma2=%d, clockfreq=%d, options=%d isadmabug=%d "
-			 "%s\n",
-	       hw_config->io_base,
-	       hw_config->irq,
-	       hw_config->dma,
-	       hw_config->dma2,
-	       ad1816_clockfreq,
-	       options,
-	       isa_dma_bridge_buggy,
-	       pnp?"(PNP)":"");
-
-	/* ad1816_info structure remaining ? */
-	if (nr_ad1816_devs >= MAX_AUDIO_DEV) {
-		printk(KERN_WARNING "ad1816: no more ad1816_info structures "
-			"left\n");
-		goto out;
-	}
-
-	devc = &dev_info[nr_ad1816_devs];
-	devc->base = hw_config->io_base;
-	devc->irq = hw_config->irq;
-	devc->dma_playback=hw_config->dma;
-	devc->dma_capture=hw_config->dma2;
-	devc->opened = 0;
-	devc->pnpdev = pnp;
-	spin_lock_init(&devc->lock);
-
-	if (!request_region(devc->base, 16, "AD1816 Sound")) {
-		printk(KERN_WARNING "ad1816: I/O port 0x%03x not free\n",
-				    devc->base);
-		goto out;
-	}
-
-	printk(KERN_INFO "ad1816: Examining AD1816 at address 0x%03x.\n", 
-		devc->base);
-	
-
-	/* tests for ad1816 */
-	/* base+0: bit 1 must be set but not 255 */
-	tmp=inb(devc->base);
-	if ( (tmp&0x80)==0 || tmp==255 ) {
-		printk (KERN_INFO "ad1816: Chip is not an AD1816 or chip "
-			"is not active (Test 0)\n");
-		goto out_release_region;
-	}
-
-	/* writes to ireg 8 are copied to ireg 9 */
-	ad_write(devc,8,12345); 
-	if (ad_read(devc,9)!=12345) {
-		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 1)\n");
-		goto out_release_region;
-	}
-  
-	/* writes to ireg 8 are copied to ireg 9 */
-	ad_write(devc,8,54321); 
-	if (ad_read(devc,9)!=54321) {
-		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 2)\n");
-		goto out_release_region;
-	}
-
-	/* writes to ireg 10 are copied to ireg 11 */
-	ad_write(devc,10,54321); 
-	if (ad_read(devc,11)!=54321) {
-		printk (KERN_INFO "ad1816: Chip is not an AD1816 (Test 3)\n");
-		goto out_release_region;
-	}
-
-	/* writes to ireg 10 are copied to ireg 11 */
-	ad_write(devc,10,12345); 
-	if (ad_read(devc,11)!=12345) {
-		printk (KERN_INFO "ad1816: Chip is not an AD1816 (Test 4)\n");
-		goto out_release_region;
-	}
-
-	/* bit in base +1 cannot be set to 1 */
-	tmp=inb(devc->base+1);
-	outb(0xff,devc->base+1); 
-	if (inb(devc->base+1)!=tmp) {
-		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 5)\n");
-		goto out_release_region;
-	}
-  
-	printk(KERN_INFO "ad1816: AD1816 (version %d) successfully detected!\n",
-		ad_read(devc,45));
-
-	/* disable all interrupts */
-	ad_write(devc,1,0);     
-
-	/* Clear pending interrupts */
-	outb (0, devc->base+1);	
-
-	/* allocate irq */
-	if (devc->irq < 0 || devc->irq > 15)
-		goto out_release_region;
-	if (request_irq(devc->irq, ad1816_interrupt,0,
-			"SoundPort", devc) < 0)	{
-	        printk(KERN_WARNING "ad1816: IRQ in use\n");
-		goto out_release_region;
-	}
-
-	/* DMA stuff */
-	if (sound_alloc_dma (devc->dma_playback, "Sound System")) {
-		printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
-				    devc->dma_playback);
-		goto out_free_irq;
-	}
-	
-	if ( devc->dma_capture >= 0 && 
-	  	devc->dma_capture != devc->dma_playback) {
-		if (sound_alloc_dma(devc->dma_capture,
-				    "Sound System (capture)")) {
-			printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
-					    devc->dma_capture);
-			goto out_free_dma;
-		}
-		devc->audio_mode=DMA_AUTOMODE|DMA_DUPLEX;
-	} else {
-	  	printk(KERN_WARNING "ad1816: Only one DMA channel "
-			"available/configured. No duplex operation possible\n");
-		devc->audio_mode=DMA_AUTOMODE;
-	}
-
-	conf_printf2 ("AD1816 audio driver",
-		      devc->base, devc->irq, devc->dma_playback, 
-		      devc->dma_capture);
-
-	/* register device */
-	if ((oss_devno = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
-					      "AD1816 audio driver",
-					      &ad1816_audio_driver,
-					      sizeof (struct audio_driver),
-					      devc->audio_mode,
-					      ad_format_mask,
-					      devc,
-					      devc->dma_playback, 
-					      devc->dma_capture)) < 0) {
-		printk(KERN_WARNING "ad1816: Can't install sound driver\n");
-		goto out_free_dma_2;
-	}
-
-
-	ad_write(devc,32,0x80f0); /* sound system mode */
-	if (options&1) {
-	        ad_write(devc,33,0); /* disable all audiosources for dsp */
-	} else {
-	        ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
-	}
-	ad_write(devc,4,0x8080);  /* default values for volumes (muted)*/
-	ad_write(devc,5,0x8080);
-	ad_write(devc,6,0x8080);
-	ad_write(devc,7,0x8080);
-	ad_write(devc,15,0x8888);
-	ad_write(devc,16,0x8888);
-	ad_write(devc,17,0x8888);
-	ad_write(devc,18,0x8888);
-	ad_write(devc,19,0xc888); /* +20db mic active */
-	ad_write(devc,14,0x0000); /* Master volume unmuted */
-	ad_write(devc,39,0x009f); /* 3D effect on 0% phone out muted */
-	ad_write(devc,44,0x0080); /* everything on power, 3d enabled for d/a */
-	outb(0x10,devc->base+8); /* set dma mode */
-	outb(0x10,devc->base+9);
-  
-	/* enable capture + playback interrupt */
-	ad_write(devc,1,0xc000); 
-	
-	/* set mixer defaults */
-	ad1816_mixer_reset (devc); 
-  
-	/* register mixer */
-	if ((audio_devs[oss_devno]->mixer_dev=sound_install_mixer(
-				       MIXER_DRIVER_VERSION,
-				       "AD1816 audio driver",
-				       &ad1816_mixer_operations,
-				       sizeof (struct mixer_operations),
-				       devc)) < 0) {
-	  	printk(KERN_WARNING "Can't install mixer\n");
-	}
-	/* make ad1816_info active */
-	nr_ad1816_devs++;
-	printk(KERN_INFO "ad1816: card successfully installed!\n");
-	return 1;
-	/* error handling */
-out_free_dma_2:
-	if (devc->dma_capture >= 0 && devc->dma_capture != devc->dma_playback)
-	        sound_free_dma(devc->dma_capture);
-out_free_dma:
-	sound_free_dma(devc->dma_playback);
-out_free_irq:
-	free_irq(devc->irq, devc);
-out_release_region:
-	release_region(devc->base, 16);
-out:
-	return 0;
-}
-
-static void __exit unload_card(ad1816_info *devc)
-{
-	int  mixer, dev = 0;
-	
-	if (devc != NULL) {
-		printk("ad1816: Unloading card at address 0x%03x\n",devc->base);
-		
-		dev = devc->dev_no;
-		mixer = audio_devs[dev]->mixer_dev;
-
-		/* unreg mixer*/
-		if(mixer>=0) {
-			sound_unload_mixerdev(mixer);
-		}
-		/* unreg audiodev */
-		sound_unload_audiodev(dev);
-		
-		/* free dma channels */
-		if (devc->dma_capture>=0 && 
-		  	devc->dma_capture != devc->dma_playback) {
-			sound_free_dma(devc->dma_capture);
-		}
-		sound_free_dma (devc->dma_playback);
-		/* free irq */
-		free_irq(devc->irq, devc);
-		/* free io */
-		release_region (devc->base, 16);
-#ifdef __ISAPNP__
-		if (devc->pnpdev) {
-		  	pnp_disable_dev(devc->pnpdev);
-			pnp_device_detach(devc->pnpdev);
-		}
-#endif
-		
-	} else
-		printk(KERN_WARNING "ad1816: no device/card specified\n");
-}
-
-static int __initdata io = -1;
-static int __initdata irq = -1;
-static int __initdata dma = -1;
-static int __initdata dma2 = -1;
-
-#ifdef __ISAPNP__
-/* use isapnp for configuration */
-static int isapnp	= 1;
-static int isapnpjump;
-module_param(isapnp, bool, 0);
-module_param(isapnpjump, int, 0);
-#endif
-
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(dma, int, 0);
-module_param(dma2, int, 0);
-module_param(ad1816_clockfreq, int, 0);
-module_param(options, int, 0);
-
-#ifdef __ISAPNP__
-static struct {
-	unsigned short card_vendor, card_device;
-	unsigned short vendor;
-	unsigned short function;
-	struct ad1816_data *data;
-} isapnp_ad1816_list[] __initdata = {
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7150), 
-		NULL },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7180),
-		NULL },
-	{0}
-};
-
-MODULE_DEVICE_TABLE(isapnp, isapnp_ad1816_list);
-
-
-static void __init ad1816_config_pnp_card(struct pnp_card *card,
-					  unsigned short vendor,
-					  unsigned short function)
-{
-	struct address_info cfg;
-  	struct pnp_dev *card_dev = pnp_find_dev(card, vendor, function, NULL);
-	if (!card_dev) return;
-	if (pnp_device_attach(card_dev) < 0) {
-	  	printk(KERN_WARNING "ad1816: Failed to attach PnP device\n");
-		return;
-	}
-	if (pnp_activate_dev(card_dev) < 0) {
-		printk(KERN_WARNING "ad1816: Failed to activate PnP device\n");
-		pnp_device_detach(card_dev);
-		return;
-	}
-	cfg.io_base = pnp_port_start(card_dev, 2);
-	cfg.irq = pnp_irq(card_dev, 0);
-	cfg.dma = pnp_irq(card_dev, 0);
-	cfg.dma2 = pnp_irq(card_dev, 1);
-	if (!ad1816_init_card(&cfg, card_dev)) {
-	  	pnp_disable_dev(card_dev);
-		pnp_device_detach(card_dev);
-	}
-}
-
-static void __init ad1816_config_pnp_cards(void)
-{
-	int nr_pnp_cfg;
-	int i;
-	
-	/* Count entries in isapnp_ad1816_list */
-	for (nr_pnp_cfg = 0; isapnp_ad1816_list[nr_pnp_cfg].card_vendor != 0; 
-		nr_pnp_cfg++);
-	/* Check and adjust isapnpjump */
-	if( isapnpjump < 0 || isapnpjump >= nr_pnp_cfg) {
-		printk(KERN_WARNING 
-			"ad1816: Valid range for isapnpjump is 0-%d. "
-			"Adjusted to 0.\n", nr_pnp_cfg-1);
-		isapnpjump = 0;
-	}
-	for (i = isapnpjump; isapnp_ad1816_list[i].card_vendor != 0; i++) {
-	 	struct pnp_card *card = NULL;
-		/* iterate over all pnp cards */		
-		while ((card = pnp_find_card(isapnp_ad1816_list[i].card_vendor,
-		              	isapnp_ad1816_list[i].card_device, card))) 
-			ad1816_config_pnp_card(card, 
-				isapnp_ad1816_list[i].vendor,
-				isapnp_ad1816_list[i].function);
-	}
-}
-#endif
-
-/* module initialization */
-static int __init init_ad1816(void)
-{
-	printk(KERN_INFO "ad1816: AD1816 sounddriver "
-			 "Copyright (C) 1998-2003 by Thorsten Knabe and "
-			 "others\n");
-#ifdef AD1816_CLOCK 
-	/* set ad1816_clockfreq if set during compilation */
-	ad1816_clockfreq=AD1816_CLOCK;
-#endif
-	if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
-		ad1816_clockfreq=33000;
-	}
-
-#ifdef __ISAPNP__
-	/* configure PnP cards */
-	if(isapnp) ad1816_config_pnp_cards();
-#endif
-	/* configure card by module params */
-	if (io != -1 && irq != -1 && dma != -1) {
-		struct address_info cfg;
-		cfg.io_base = io;
-		cfg.irq = irq;
-		cfg.dma = dma;
-		cfg.dma2 = dma2;
-		ad1816_init_card(&cfg, NULL);
-	}
-	if (nr_ad1816_devs <= 0)
-	  	return -ENODEV;
-	return 0;
-}
-
-/* module cleanup */
-static void __exit cleanup_ad1816 (void)
-{
-	int          i;
-	ad1816_info  *devc = NULL;
-  
-	/* remove any soundcard */
-	for (i = 0;  i < nr_ad1816_devs; i++) {
-		devc = &dev_info[i];
-		unload_card(devc);
-	}     
-	nr_ad1816_devs=0;
-	printk(KERN_INFO "ad1816: driver unloaded!\n");
-}
-
-module_init(init_ad1816);
-module_exit(cleanup_ad1816);
-
-#ifndef MODULE
-/* kernel command line parameter evaluation */
-static int __init setup_ad1816(char *str)
-{
-	/* io, irq, dma, dma2 */
-	int ints[5];
-	
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io	= ints[1];
-	irq	= ints[2];
-	dma	= ints[3];
-	dma2	= ints[4];
-	return 1;
-}
-
-__setup("ad1816=", setup_ad1816);
-#endif
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
deleted file mode 100644
index c0730a3..0000000
--- a/sound/oss/ad1889.c
+++ /dev/null
@@ -1,1101 +0,0 @@
-/*
- *  Copyright 2001-2004 Randolph Chung <tausq@debian.org>
- *
- *  Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   Notes:
- *   1. Only flat DMA is supported; s-g is not supported right now
- *
- *
-<jsm> tausq: Anyway, to set up sample rates for D to A, you just use the sample rate on the codec. For A to D, you need to set the codec always to 48K (using the split sample rate feature on the codec) and then set the resampler on the AD1889 to the sample rate you want.
-<jsm> Also, when changing the sample rate on the codec you need to power it down and re power it up for the change to take effect!
- *
- * $Id: ad1889.c,v 1.3 2002/10/19 21:31:44 grundler Exp $
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/sound.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-
-#include <asm/delay.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#include "ad1889.h"
-
-#define DBG(fmt, arg...) printk(fmt, ##arg)
-#define DEVNAME "ad1889"
-
-#define NR_HW_CH	4
-#define DAC_RUNNING	1
-#define ADC_RUNNING	2
-
-#define UNDERRUN(dev)	(0)
-
-#define AD1889_READW(dev,reg) readw(dev->regbase + reg)
-#define AD1889_WRITEW(dev,reg,val) writew((val), dev->regbase + reg)
-#define AD1889_READL(dev,reg) readl(dev->regbase + reg)
-#define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
-
-//now 100ms
-/* #define WAIT_10MS()	schedule_timeout(HZ/10) */
-#define WAIT_10MS()	do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
-
-/* currently only support a single device */
-static ad1889_dev_t *ad1889_dev = NULL;
-
-/************************* helper routines ***************************** */
-static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
-{
-	struct ac97_codec *ac97_codec = dev->ac97_codec;
-
-	DBG("Setting WAV rate to %d\n", rate);
-	dev->state[AD_WAV_STATE].dmabuf.rate = rate;
-	AD1889_WRITEW(dev, AD_DS_WAS, rate);
-
-	/* Cycle the DAC to enable the new rate */
-	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
-	WAIT_10MS();
-	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
-}
-
-static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
-{
-	u16 tmp;
-
-	DBG("Setting WAV format to 0x%x\n", fmt);
-
-	tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
-	if (fmt & AFMT_S16_LE) {
-		//tmp |= 0x0100; /* set WA16 */
-		tmp |= 0x0300; /* set WA16 stereo */
-	} else if (fmt & AFMT_U8) {
-		tmp &= ~0x0100; /* clear WA16 */
-	} 
-	AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
-}
-
-static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
-{
-	u16 tmp;
-
-	DBG("Setting ADC format to 0x%x\n", fmt);
-
-	tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
-	if (fmt & AFMT_S16_LE) {
-		tmp |= 0x0100; /* set WA16 */
-	} else if (fmt & AFMT_U8) {
-		tmp &= ~0x0100; /* clear WA16 */
-	} 
-	AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
-}
-
-static void ad1889_start_wav(ad1889_state_t *state)
-{
-	unsigned long flags;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int cnt;
-	u16 tmp;
-
-	spin_lock_irqsave(&state->card->lock, flags);
-
-	if (dmabuf->dma_len)	/* DMA already in flight */
-		goto skip_dma;
-
-	/* setup dma */
-	cnt = dmabuf->wr_ptr - dmabuf->rd_ptr;
-	if (cnt == 0)		/* done - don't need to do anything */
-		goto skip_dma;
-
-	/* If the wr_ptr has wrapped, only map to the end */
-	if (cnt < 0)
-		cnt = DMA_SIZE - dmabuf->rd_ptr;
-
-	dmabuf->dma_handle = pci_map_single(ad1889_dev->pci,
-					dmabuf->rawbuf + dmabuf->rd_ptr,
-					cnt, PCI_DMA_TODEVICE);
-	dmabuf->dma_len = cnt;
-	dmabuf->ready = 1;
-
-	DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
-	    dmabuf->rd_ptr, dmabuf->dma_len);
-
-        /* load up the current register set */
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVICC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCA, dmabuf->dma_handle);
-
-	/* TODO: for now we load the base registers with the same thing */
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVIBC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBA, dmabuf->dma_handle);
-
-	/* and we're off to the races... */
-	AD1889_WRITEL(ad1889_dev, AD_DMA_CHSS, 0x8);
-	tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
-	tmp |= 0x0400; /* set WAEN */
-	AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
-	(void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
-
-	dmabuf->enable |= DAC_RUNNING;
-
-skip_dma:
-	spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-
-static void ad1889_stop_wav(ad1889_state_t *state)
-{
-	unsigned long flags;
-	struct dmabuf *dmabuf = &state->dmabuf;
-
-	spin_lock_irqsave(&state->card->lock, flags);
-
-	if (dmabuf->enable & DAC_RUNNING) {
-		u16 tmp;
-		unsigned long cnt = dmabuf->dma_len;
-
-		tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
-		tmp &= ~0x0400; /* clear WAEN */
-		AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
-		(void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
-		pci_unmap_single(ad1889_dev->pci, dmabuf->dma_handle, 
-				cnt, PCI_DMA_TODEVICE);
-
-		dmabuf->enable &= ~DAC_RUNNING;
-
-		/* update dma pointers */
-		dmabuf->rd_ptr += cnt;
-		dmabuf->rd_ptr &= (DMA_SIZE - 1);
-
-		dmabuf->dma_handle = 0;
-		dmabuf->dma_len = 0;
-		dmabuf->ready = 0;
-
-		wake_up(&dmabuf->wait);
-	}
-
-	spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-
-#if 0
-static void ad1889_startstop_adc(ad1889_state_t *state, int start)
-{
-	u16 tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&state->card->lock, flags);
-	
-	tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
-	if (start) {
-		state->dmabuf.enable |= ADC_RUNNING;
-		tmp |= 0x0004; /* set ADEN */
-	} else {
-		state->dmabuf.enable &= ~ADC_RUNNING;
-		tmp &= ~0x0004; /* clear ADEN */
-	}
-	AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
-
-	spin_unlock_irqrestore(&state->card->lock, flags);
-}
-#endif
-
-static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
-{
-	ad1889_dev_t *dev;
-	struct dmabuf *dmabuf;
-	int i;
-
-	if ((dev = kzalloc(sizeof(ad1889_dev_t), GFP_KERNEL)) == NULL)
-		return NULL;
-	spin_lock_init(&dev->lock);
-	dev->pci = pci;
-
-	for (i = 0; i < AD_MAX_STATES; i++) {
-		dev->state[i].card = dev;
-		mutex_init(&dev->state[i].mutex);
-		init_waitqueue_head(&dev->state[i].dmabuf.wait);
-	}
-
-	/* allocate dma buffer */
-
-	for (i = 0; i < AD_MAX_STATES; i++) {
-		dmabuf = &dev->state[i].dmabuf;
-		dmabuf->rawbuf = kmalloc(DMA_SIZE, GFP_KERNEL|GFP_DMA);
-		if (!dmabuf->rawbuf)
-			goto err_free_dmabuf;
-		dmabuf->rawbuf_size = DMA_SIZE;
-		dmabuf->dma_handle = 0;
-		dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
-		dmabuf->ready = 0;
-		dmabuf->rate = 48000;
-	}
-	return dev;
-
-err_free_dmabuf:
-	while (--i >= 0)
-		kfree(dev->state[i].dmabuf.rawbuf);
-	kfree(dev);
-	return NULL;
-}
-
-static void ad1889_free_dev(ad1889_dev_t *dev)
-{
-	int j;
-	struct dmabuf *dmabuf;
-
-	if (dev == NULL) 
-		return;
-
-	if (dev->ac97_codec)
-		ac97_release_codec(dev->ac97_codec);
-
-	for (j = 0; j < AD_MAX_STATES; j++) {
-		dmabuf = &dev->state[j].dmabuf;
-		kfree(dmabuf->rawbuf);
-	}
-
-	kfree(dev);
-}
-
-static inline void ad1889_trigger_playback(ad1889_dev_t *dev)
-{
-#if 0
-	u32 val;
-	struct dmabuf *dmabuf = &dev->state[AD_WAV_STATE].dmabuf;
-#endif
-
-	ad1889_start_wav(&dev->state[AD_WAV_STATE]);
-}
-
-static int ad1889_read_proc (char *page, char **start, off_t off,
-			     int count, int *eof, void *data)
-{
-	char *out = page;
-	int len, i;
-	ad1889_dev_t *dev = data;
-	ad1889_reg_t regs[] = {
-		{ "WSMC", AD_DS_WSMC, 16 },
-		{ "RAMC", AD_DS_RAMC, 16 },
-		{ "WADA", AD_DS_WADA, 16 },
-		{ "SYDA", AD_DS_SYDA, 16 },
-		{ "WAS", AD_DS_WAS, 16 },
-		{ "RES", AD_DS_RES, 16 },
-		{ "CCS", AD_DS_CCS, 16 },
-		{ "ADCBA", AD_DMA_ADCBA, 32 },
-		{ "ADCCA", AD_DMA_ADCCA, 32 },
-		{ "ADCBC", AD_DMA_ADCBC, 32 },
-		{ "ADCCC", AD_DMA_ADCCC, 32 },
-		{ "ADCIBC", AD_DMA_ADCIBC, 32 },
-		{ "ADCICC", AD_DMA_ADCICC, 32 },
-		{ "ADCCTRL", AD_DMA_ADCCTRL, 16 },
-		{ "WAVBA", AD_DMA_WAVBA, 32 },
-		{ "WAVCA", AD_DMA_WAVCA, 32 },
-		{ "WAVBC", AD_DMA_WAVBC, 32 },
-		{ "WAVCC", AD_DMA_WAVCC, 32 },
-		{ "WAVIBC", AD_DMA_WAVIBC, 32 },
-		{ "WAVICC", AD_DMA_WAVICC, 32 },
-		{ "WAVCTRL", AD_DMA_WAVCTRL, 16 },
-		{ "DISR", AD_DMA_DISR, 32 },
-		{ "CHSS", AD_DMA_CHSS, 32 },
-		{ "IPC", AD_GPIO_IPC, 16 },
-		{ "OP", AD_GPIO_OP, 16 },
-		{ "IP", AD_GPIO_IP, 16 },
-		{ "ACIC", AD_AC97_ACIC, 16 },
-		{ "AC97_RESET", AD_AC97_BASE + AC97_RESET, 16 },
-		{ "AC97_MASTER_VOL_STEREO", AD_AC97_BASE + AC97_MASTER_VOL_STEREO, 16 },
-		{ "AC97_HEADPHONE_VOL", AD_AC97_BASE + AC97_HEADPHONE_VOL, 16 },
-		{ "AC97_MASTER_VOL_MONO", AD_AC97_BASE + AC97_MASTER_VOL_MONO, 16 },
-		{ "AC97_MASTER_TONE", AD_AC97_BASE + AC97_MASTER_TONE, 16 },
-		{ "AC97_PCBEEP_VOL", AD_AC97_BASE + AC97_PCBEEP_VOL, 16 },
-		{ "AC97_PHONE_VOL", AD_AC97_BASE + AC97_PHONE_VOL, 16 },
-		{ "AC97_MIC_VOL", AD_AC97_BASE + AC97_MIC_VOL, 16 },
-		{ "AC97_LINEIN_VOL", AD_AC97_BASE + AC97_LINEIN_VOL, 16 },
-		{ "AC97_CD_VOL", AD_AC97_BASE + AC97_CD_VOL, 16 },
-		{ "AC97_VIDEO_VOL", AD_AC97_BASE + AC97_VIDEO_VOL, 16 },
-		{ "AC97_AUX_VOL", AD_AC97_BASE + AC97_AUX_VOL, 16 },
-		{ "AC97_PCMOUT_VOL", AD_AC97_BASE + AC97_PCMOUT_VOL, 16 },
-		{ "AC97_RECORD_SELECT", AD_AC97_BASE + AC97_RECORD_SELECT, 16 },
-		{ "AC97_RECORD_GAIN", AD_AC97_BASE + AC97_RECORD_GAIN, 16 },
-		{ "AC97_RECORD_GAIN_MIC", AD_AC97_BASE + AC97_RECORD_GAIN_MIC, 16 },
-		{ "AC97_GENERAL_PURPOSE", AD_AC97_BASE + AC97_GENERAL_PURPOSE, 16 },
-		{ "AC97_3D_CONTROL", AD_AC97_BASE + AC97_3D_CONTROL, 16 },
-		{ "AC97_MODEM_RATE", AD_AC97_BASE + AC97_MODEM_RATE, 16 },
-		{ "AC97_POWER_CONTROL", AD_AC97_BASE + AC97_POWER_CONTROL, 16 },
-		{ NULL }
-	};
-
-	if (dev == NULL)
-		return -ENODEV;
-
-	for (i = 0; regs[i].name != 0; i++)
-		out += sprintf(out, "%s: 0x%0*x\n", regs[i].name, 
-			regs[i].width >> 2, 
-			(regs[i].width == 16 
-			 	? AD1889_READW(dev, regs[i].offset)
-				: AD1889_READL(dev, regs[i].offset)));
-
-	for (i = 0; i < AD_MAX_STATES; i++) {
-		out += sprintf(out, "DMA status for %s:\n", 
-			(i == AD_WAV_STATE ? "WAV" : "ADC")); 
-		out += sprintf(out, "\t\t0x%p (IOVA: 0x%llu)\n",
-			dev->state[i].dmabuf.rawbuf,
-			(unsigned long long)dev->state[i].dmabuf.dma_handle);
-
-		out += sprintf(out, "\tread ptr: offset %u\n", 
-			(unsigned int)dev->state[i].dmabuf.rd_ptr);
-		out += sprintf(out, "\twrite ptr: offset %u\n", 
-			(unsigned int)dev->state[i].dmabuf.wr_ptr);
-		out += sprintf(out, "\tdma len: offset %u\n", 
-			(unsigned int)dev->state[i].dmabuf.dma_len);
-	}
-
-	len = out - page - off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0) return 0;
-	} else {
-		len = count;
-	}
-	*start = page + off;
-	return len;
-}
-
-/***************************** DMA interfaces ************************** */
-#if 0
-static inline unsigned long ad1889_get_dma_addr(ad1889_state_t *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	u32 offset;
-
-	if (!(dmabuf->enable & (DAC_RUNNING | ADC_RUNNING))) {
-		printk(KERN_ERR DEVNAME ": get_dma_addr called without dma enabled\n");
-		return 0;
-	}
-	
-	if (dmabuf->enable & DAC_RUNNING)
-		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
-	else
-		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
-
-	return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
-}
-
-static void ad1889_update_ptr(ad1889_dev_t *dev, int wake)
-{
-	ad1889_state_t *state;
-	struct dmabuf *dmabuf;
-	unsigned long hwptr;
-	int diff;
-
-	/* check ADC first */
-	state = &dev->adc_state;
-	dmabuf = &state->dmabuf;
-	if (dmabuf->enable & ADC_RUNNING) {
-		hwptr = ad1889_get_dma_addr(state);
-		diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-
-		dmabuf->hwptr = hwptr;
-		dmabuf->total_bytes += diff;
-		dmabuf->count += diff;
-		if (dmabuf->count > dmabuf->dmasize)
-			dmabuf->count = dmabuf->dmasize;
-
-		if (dmabuf->mapped) {
-			if (wake & dmabuf->count >= dmabuf->fragsize)
-				wake_up(&dmabuf->wait);
-		} else {
-			if (wake & dmabuf->count > 0)
-				wake_up(&dmabuf->wait);
-		}
-	}
-
-	/* check DAC */
-	state = &dev->wav_state;
-	dmabuf = &state->dmabuf;
-	if (dmabuf->enable & DAC_RUNNING) {
-XXX
-
-}
-#endif
-
-/************************* /dev/dsp interfaces ************************* */
-
-static ssize_t ad1889_read(struct file *file, char __user *buffer, size_t count,
-	loff_t *ppos)
-{
-	return 0;
-}
-
-static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t count,
-	loff_t *ppos)
-{
-	ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
-	ad1889_state_t *state = &dev->state[AD_WAV_STATE];
-	volatile struct dmabuf *dmabuf = &state->dmabuf;
-	ssize_t ret = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	mutex_lock(&state->mutex);
-#if 0
-	if (dmabuf->mapped) {
-		ret = -ENXIO;
-		goto err1;
-	}
-#endif
-	if (!access_ok(VERIFY_READ, buffer, count)) {
-		ret = -EFAULT;
-		goto err1;
-	}
-
-	add_wait_queue(&state->dmabuf.wait, &wait);
-
-	/* start filling dma buffer.... */
-	while (count > 0) {
-		long rem;
-		long cnt = count;
-		unsigned long flags;
-
-		for (;;) {
-			long used_bytes;
-			long timeout;	/* max time for DMA in jiffies */
-
-			/* buffer is full if wr catches up to rd */
-			spin_lock_irqsave(&state->card->lock, flags);
-			used_bytes = dmabuf->wr_ptr - dmabuf->rd_ptr;
-			timeout = (dmabuf->dma_len * HZ) / dmabuf->rate;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-
-			/* adjust for buffer wrap around */
-			used_bytes = (used_bytes + DMA_SIZE) & (DMA_SIZE - 1);
-
-			/* If at least one page unused */
-			if (used_bytes < (DMA_SIZE - 0x1000))
-				break;
-
-			/* dma buffer full */
-
-			if (file->f_flags & O_NONBLOCK) {
-				ret = -EAGAIN;
-				goto err2;
-			}
-
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(timeout + 1);
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				goto err2;
-			}
-		}
-
-		/* watch out for wrapping around static buffer */
-		spin_lock_irqsave(&state->card->lock, flags);
-		rem = DMA_SIZE - dmabuf->wr_ptr;
-		if (cnt > rem)
-			cnt = rem;
-
-		rem = dmabuf->wr_ptr;
-
-		/* update dma pointers */
-		dmabuf->wr_ptr += cnt;
-		dmabuf->wr_ptr &= DMA_SIZE - 1;	/* wrap ptr if necessary */
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* transfer unwrapped chunk */
-		if (copy_from_user(dmabuf->rawbuf + rem, buffer, cnt)) {
-			ret = -EFAULT;
-			goto err2;
-		}
-
-		DBG("Writing 0x%lx bytes to +0x%lx\n", cnt, rem);
-
-		/* update counters */
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-
-		/* we have something to play - go play it! */
-		ad1889_trigger_playback(dev);
-	}
-
-err2:
-	remove_wait_queue(&state->dmabuf.wait, &wait);
-err1:
-	mutex_unlock(&state->mutex);
-	return ret;
-}
-
-static unsigned int ad1889_poll(struct file *file, struct poll_table_struct *wait)
-{
-	unsigned int mask = 0;
-#if 0
-	ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
-	ad1889_state_t *state = NULL;
-	struct dmabuf *dmabuf;
-	unsigned long flags;
-	
-	if (!(file->f_mode & (FMODE_READ | FMODE_WRITE)))
-		return -EINVAL;
-
-	if (file->f_mode & FMODE_WRITE) {
-		state = &dev->state[AD_WAV_STATE];
-		if (!state) return 0;
-		dmabuf = &state->dmabuf;
-		poll_wait(file, &dmabuf->wait, wait);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		state = &dev->state[AD_ADC_STATE];
-		if (!state) return 0;
-		dmabuf = &state->dmabuf;
-		poll_wait(file, &dmabuf->wait, wait);
-	}
-
-	spin_lock_irqsave(&dev->lock, flags);
-	ad1889_update_ptr(dev, 0);
-
-	if (file->f_mode & FMODE_WRITE) {
-		state = &dev->state[WAV_STATE];
-		dmabuf = &state->dmabuf;
-		if (dmabuf->mapped) {
-			if (dmabuf->count >= (int)dmabuf->fragsize)
-				mask |= POLLOUT | POLLWRNORM;
-		} else {
-			if ((int)dmabuf->dmasize >= dmabuf->count + 
-				(int)dmabuf->fragsize)
-				mask |= POLLOUT | POLLWRNORM;
-		}
-	}
-
-	if (file ->f_mode & FMODE_READ) {
-		state = &dev->state[AD_ADC_STATE];
-		dmabuf = &state->dmabuf;
-		if (dmabuf->count >= (int)dmabuf->fragsize)
-			mask |= POLLIN | POLLRDNORM;
-	}
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-#endif
-	return mask;
-}
-
-static int ad1889_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	return 0;
-}
-
-static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-	unsigned long arg)
-{
-	int val = 0;
-	ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
-	struct dmabuf *dmabuf;
-	audio_buf_info abinfo;
-	int __user *p = (int __user *)arg;
-
-	DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
-
-	switch (cmd)
-	{
-	case OSS_GETVERSION:
-		return put_user(SOUND_VERSION, p);
-
-	case SNDCTL_DSP_RESET:
-		break;
-
-	case SNDCTL_DSP_SYNC:
-		break;
-
-	case SNDCTL_DSP_SPEED:
-		/* set sampling rate */
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val > 5400 && val < 48000)
-		{
-			if (file->f_mode & FMODE_WRITE)
-				AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
-			if (file->f_mode & FMODE_READ)
-				AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
-		}
-		return 0;
-
-	case SNDCTL_DSP_STEREO: /* undocumented? */
-		if (get_user(val, p))
-			return -EFAULT;
-		if (file->f_mode & FMODE_READ) {
-			val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
-			if (val) {
-				val |= 0x0200;  /* set WAST */
-			} else {
-				val &= ~0x0200; /* clear WAST */
-			}
-			AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
-			if (val) {
-				val |= 0x0002;  /* set ADST */
-			} else {
-				val &= ~0x0002; /* clear ADST */
-			}
-			AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
-		}
-
-		return 0;
-
-	case SNDCTL_DSP_GETBLKSIZE:
-		return put_user(DMA_SIZE, p);
-
-	case SNDCTL_DSP_GETFMTS:
-		return put_user(AFMT_S16_LE|AFMT_U8, p);
-
-	case SNDCTL_DSP_SETFMT:
-		if (get_user(val, p))
-			return -EFAULT;
-
-		if (val == 0) {
-			if (file->f_mode & FMODE_READ) 
-				ad1889_set_adc_fmt(dev, val);
-
-			if (file->f_mode & FMODE_WRITE) 
-				ad1889_set_wav_fmt(dev, val);
-		} else {
-			val = AFMT_S16_LE | AFMT_U8;
-		}
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_CHANNELS:
-		break;
-
-	case SNDCTL_DSP_POST:
-		/* send all data to device */
-		break;
-
-	case SNDCTL_DSP_SUBDIVIDE:
-		break;
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		/* not supported; uses fixed fragment sizes */
-		return put_user(DMA_SIZE, p);
-
-	case SNDCTL_DSP_GETOSPACE:
-	case SNDCTL_DSP_GETISPACE:
-		/* space left in dma buffers */
-		if (cmd == SNDCTL_DSP_GETOSPACE)
-			dmabuf = &dev->state[AD_WAV_STATE].dmabuf;
-		else
-			dmabuf = &dev->state[AD_ADC_STATE].dmabuf;
-		abinfo.fragments = 1;
-		abinfo.fragstotal = 1;
-		abinfo.fragsize = DMA_SIZE;
-		abinfo.bytes = DMA_SIZE;
-		return copy_to_user(p, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-	case SNDCTL_DSP_NONBLOCK:
-		file->f_flags |= O_NONBLOCK;
-		return 0;
-
-	case SNDCTL_DSP_GETCAPS:
-		return put_user(0, p);
-
-	case SNDCTL_DSP_GETTRIGGER:
-	case SNDCTL_DSP_SETTRIGGER:
-		break;
-
-	case SNDCTL_DSP_GETIPTR:
-	case SNDCTL_DSP_GETOPTR:
-		break;
-
-	case SNDCTL_DSP_SETDUPLEX:
-		break;
-	
-	case SNDCTL_DSP_GETODELAY:
-		break;
-
-	case SOUND_PCM_READ_RATE:
-		return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
-
-	case SOUND_PCM_READ_CHANNELS:
-	case SOUND_PCM_READ_BITS:
-		break;
-
-	case SNDCTL_DSP_MAPINBUF:
-	case SNDCTL_DSP_MAPOUTBUF:
-	case SNDCTL_DSP_SETSYNCRO:
-	case SOUND_PCM_WRITE_FILTER:
-	case SOUND_PCM_READ_FILTER:
-		break;
-
-	default:
-		break;
-	}
-
-	return -ENOTTY;
-}
-
-static int ad1889_open(struct inode *inode, struct file *file)
-{
-	/* check minor; only support /dev/dsp atm */
-	if (iminor(inode) != 3)
-		return -ENXIO;
-	
-	file->private_data = ad1889_dev;
-
-	ad1889_set_wav_rate(ad1889_dev, 48000);
-	ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
-	AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
-	return nonseekable_open(inode, file);
-}
-
-static int ad1889_release(struct inode *inode, struct file *file)
-{
-	/* if we have state free it here */
-	return 0;
-}
-
-static const struct file_operations ad1889_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= ad1889_read,
-	.write		= ad1889_write,
-	.poll		= ad1889_poll,
-	.ioctl		= ad1889_ioctl,
-	.mmap		= ad1889_mmap,
-	.open		= ad1889_open,
-	.release	= ad1889_release,
-};
-
-/************************* /dev/mixer interfaces ************************ */
-static int ad1889_mixer_open(struct inode *inode, struct file *file)
-{
-	if (ad1889_dev->ac97_codec->dev_mixer != iminor(inode))
-		return -ENODEV;
-
-	file->private_data = ad1889_dev->ac97_codec;
-	return 0;
-}
-
-static int ad1889_mixer_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static int ad1889_mixer_ioctl(struct inode *inode, struct file *file,
-	unsigned int cmd, unsigned long arg)
-{
-	struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
-	return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static const struct file_operations ad1889_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.ioctl		= ad1889_mixer_ioctl,
-	.open		= ad1889_mixer_open,
-	.release	= ad1889_mixer_release,
-};
-
-/************************* AC97 interfaces ****************************** */
-static void ad1889_codec_write(struct ac97_codec *ac97, u8 reg, u16 val)
-{
-	ad1889_dev_t *dev = ac97->private_data;
-
-	//DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + AD_AC97_BASE + reg);
-	AD1889_WRITEW(dev, AD_AC97_BASE + reg, val);
-}
-
-static u16 ad1889_codec_read(struct ac97_codec *ac97, u8 reg)
-{
-	ad1889_dev_t *dev = ac97->private_data;
-	//DBG("Reading from 0x%lx\n", dev->regbase + AD_AC97_BASE + reg);
-	return AD1889_READW(dev, AD_AC97_BASE + reg);
-}	
-
-static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
-{
-	struct ac97_codec *ac97;
-	u16 eid;
-
-	if ((ac97 = ac97_alloc_codec()) == NULL) 
-		return -ENOMEM;
-
-	ac97->private_data = dev;
-	ac97->id = id;
-
-	ac97->codec_read = ad1889_codec_read;
-	ac97->codec_write = ad1889_codec_write;
-
-	if (ac97_probe_codec(ac97) == 0) {
-		printk(DEVNAME ": ac97_probe_codec failed\n");
-		goto out_free;
-	}
-
-	eid = ad1889_codec_read(ac97, AC97_EXTENDED_ID);
-	if (eid == 0xffff) {
-		printk(KERN_WARNING DEVNAME ": no codec attached?\n");
-		goto out_free;
-	}
-
-	dev->ac97_features = eid;
-
-	if ((ac97->dev_mixer = register_sound_mixer(&ad1889_mixer_fops, -1)) < 0) {
-		printk(KERN_ERR DEVNAME ": cannot register mixer\n");
-		goto out_free;
-	}
-
-	dev->ac97_codec = ac97;
-	return 0;
-
-out_free:
-	ac97_release_codec(ac97);
-	return -ENODEV;
-}
-
-static int ad1889_aclink_reset(struct pci_dev * pcidev)
-{
-	u16 stat;
-	int retry = 200;
-	ad1889_dev_t *dev = pci_get_drvdata(pcidev);
-
-	AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
-	AD1889_READW(dev, AD_DS_CCS);
-
-	WAIT_10MS();
-
-	stat = AD1889_READW(dev, AD_AC97_ACIC);
-	stat |= 0x0002;				/* Reset Disable */
-	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
-	(void) AD1889_READW(dev, AD_AC97_ACIC);	/* flush posted write */
-
-	udelay(10);
-
-	stat = AD1889_READW(dev, AD_AC97_ACIC);
-	stat |= 0x0001;				/* Interface Enable */
-	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
-
-	do {
-		if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000)	/* Ready */
-			break;
-		WAIT_10MS();
-		retry--;
-	} while (retry > 0);
-
-	if (!retry) {
-		printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
-			    AD1889_READW(dev, AD_AC97_ACIC));
-		return -EBUSY;
-	}
-
-	/* TODO reset AC97 codec */
-	/* TODO set wave/adc pci ctrl status */
-
-	stat = AD1889_READW(dev, AD_AC97_ACIC);
-	stat |= 0x0004;				/* Audio Stream Output Enable */
-	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
-	return 0;
-}
-
-/************************* PCI interfaces ****************************** */
-/* PCI device table */
-static struct pci_device_id ad1889_id_tbl[] = {
-	{ PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS, PCI_ANY_ID, 
-	  PCI_ANY_ID, 0, 0, (unsigned long)DEVNAME },
-	{ },
-};
-MODULE_DEVICE_TABLE(pci, ad1889_id_tbl);
-
-static irqreturn_t ad1889_interrupt(int irq, void *dev_id)
-{
-	u32 stat;
-	ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
-
-	stat = AD1889_READL(dev, AD_DMA_DISR);
-
-	/* clear ISR */
-	AD1889_WRITEL(dev, AD_DMA_DISR, stat);
-
-	if (stat & 0x8) {		/* WAVI */
-		DBG("WAV interrupt\n");
-		dev->stats.wav_intrs++;
-		if (dev->state[AD_WAV_STATE].dmabuf.ready) {
-			ad1889_stop_wav(&dev->state[AD_WAV_STATE]);	/* clean up */
-			ad1889_start_wav(&dev->state[AD_WAV_STATE]);	/* start new */
-		}
-	}
-
-	if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
-		DBG("ADC interrupt\n");
-		dev->stats.adc_intrs++;
-	}
-	if(stat)
-		return IRQ_HANDLED;
-	return IRQ_NONE;
-}
-
-static void ad1889_initcfg(ad1889_dev_t *dev)
-{
-	u16 tmp16;
-	u32 tmp32;
-
-	/* make sure the interrupt bits are setup the way we want */
-	tmp32 = AD1889_READL(dev, AD_DMA_WAVCTRL);
-	tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
-	tmp32 |= 0x6;  /* intr on count, loop */
-	AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
-
-	/* unmute... */
-	tmp16 = AD1889_READW(dev, AD_DS_WADA);
-	tmp16 &= ~0x8080;
-	AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
-}
-
-static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
-{
-	int err;
-	ad1889_dev_t *dev;
-	unsigned long bar;
-	struct proc_dir_entry *proc_root = NULL;
-
-	if ((err = pci_enable_device(pcidev)) != 0) {
-		printk(KERN_ERR DEVNAME ": pci_enable_device failed\n");
-		return err;
-	}
-
-	pci_set_master(pcidev);
-	if ((dev = ad1889_alloc_dev(pcidev)) == NULL) {
-		printk(KERN_ERR DEVNAME ": cannot allocate memory for device\n");
-		return -ENOMEM;
-	}
-	pci_set_drvdata(pcidev, dev);
-	bar = pci_resource_start(pcidev, 0);
-	
-        if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
-		printk(KERN_ERR DEVNAME ": memory region not assigned\n");
-		goto out1;
-	}
-
-	if (pci_request_region(pcidev, 0, DEVNAME)) {
-		printk(KERN_ERR DEVNAME ": unable to request memory region\n");
-		goto out1;
-	}
-
-	dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
-	if (!dev->regbase) {
-		printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
-		goto out2;
-	}
-
-	if (request_irq(pcidev->irq, ad1889_interrupt, IRQF_SHARED, DEVNAME, dev) != 0) {
-		printk(KERN_ERR DEVNAME ": unable to request interrupt\n");
-		goto out3;
-	}
-
-	printk(KERN_INFO DEVNAME ": %s at %p IRQ %d\n",
-		(char *)ent->driver_data, dev->regbase, pcidev->irq);
-
-	if (ad1889_aclink_reset(pcidev) != 0)
-		goto out4;
-
-	/* register /dev/dsp */
-	if ((dev->dev_audio = register_sound_dsp(&ad1889_fops, -1)) < 0) {
-		printk(KERN_ERR DEVNAME ": cannot register /dev/dsp\n");
-		goto out4;
-	}
-
-	if ((err = ad1889_ac97_init(dev, 0)) != 0)
-		goto out5;
-
-	/* XXX: cleanups */
-	if (((proc_root = proc_mkdir("driver/ad1889", NULL)) == NULL) ||
-	    create_proc_read_entry("ac97", S_IFREG|S_IRUGO, proc_root, ac97_read_proc, dev->ac97_codec) == NULL ||
-	    create_proc_read_entry("info", S_IFREG|S_IRUGO, proc_root, ad1889_read_proc, dev) == NULL) 
-		goto out5;
-	
-	ad1889_initcfg(dev);
-
-	//DBG(DEVNAME ": Driver initialization done!\n");
-
-	ad1889_dev = dev;
-
-	return 0;
-
-out5:
-	unregister_sound_dsp(dev->dev_audio);
-out4:
-	free_irq(pcidev->irq, dev);
-out3:
-	iounmap(dev->regbase);
-out2:
-	pci_release_region(pcidev, 0);
-out1:
-	ad1889_free_dev(dev);
-	pci_set_drvdata(pcidev, NULL);
-
-	return -ENODEV;
-}
-
-static void __devexit ad1889_remove(struct pci_dev *pcidev)
-{
-	ad1889_dev_t *dev = pci_get_drvdata(pcidev);
-
-	if (dev == NULL) return;
-	
-	unregister_sound_mixer(dev->ac97_codec->dev_mixer);
-	unregister_sound_dsp(dev->dev_audio);
-	free_irq(pcidev->irq, dev);
-	iounmap(dev->regbase);
-	pci_release_region(pcidev, 0);
-
-	/* any hw programming needed? */
-	ad1889_free_dev(dev);
-	pci_set_drvdata(pcidev, NULL);
-}
-
-MODULE_AUTHOR("Randolph Chung");
-MODULE_DESCRIPTION("Analog Devices AD1889 PCI Audio");
-MODULE_LICENSE("GPL");
-
-static struct pci_driver ad1889_driver = {
-	.name		= DEVNAME,
-	.id_table	= ad1889_id_tbl,
-	.probe		= ad1889_probe,
-	.remove		= __devexit_p(ad1889_remove),
-};
-
-static int __init ad1889_init_module(void)
-{
-	return pci_register_driver(&ad1889_driver);
-}
-
-static void ad1889_exit_module(void)
-{
-	pci_unregister_driver(&ad1889_driver);
-	return;
-}
-
-module_init(ad1889_init_module);
-module_exit(ad1889_exit_module);
diff --git a/sound/oss/ad1889.h b/sound/oss/ad1889.h
deleted file mode 100644
index 0991376..0000000
--- a/sound/oss/ad1889.h
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _AD1889_H_
-#define _AD1889_H_
-
-#define AD_DS_WSMC	0x00	/* DMA input wave/syn mixer control */
-#define AD_DS_RAMC	0x02	/* DMA output resamp/ADC mixer control */
-#define AD_DS_WADA	0x04	/* DMA input wave attenuation */
-#define AD_DS_SYDA	0x06	/* DMA input syn attentuation */
-#define AD_DS_WAS	0x08	/* wave input sample rate */
-#define AD_DS_RES	0x0a	/* resampler output sample rate */
-#define AD_DS_CCS	0x0c	/* chip control/status */
-
-#define AD_DMA_RESBA	0x40	/* RES base addr */
-#define AD_DMA_RESCA	0x44	/* RES current addr */
-#define AD_DMA_RESBC	0x48	/* RES base cnt */
-#define AD_DMA_RESCC	0x4c	/* RES current count */
-#define AD_DMA_ADCBA	0x50	/* ADC */
-#define AD_DMA_ADCCA	0x54
-#define AD_DMA_ADCBC	0x58
-#define AD_DMA_ADCCC	0x5c
-#define AD_DMA_SYNBA	0x60	/* SYN */
-#define AD_DMA_SYNCA	0x64
-#define AD_DMA_SYNBC	0x68
-#define AD_DMA_SYNCC	0x6c
-#define AD_DMA_WAVBA	0x70	/* WAV */
-#define AD_DMA_WAVCA	0x74
-#define AD_DMA_WAVBC	0x78
-#define AD_DMA_WAVCC	0x7c
-#define AD_DMA_RESICC	0x80	/* RES interrupt current count */
-#define AD_DMA_RESIBC	0x84	/* RES interrupt base count */
-#define AD_DMA_ADCICC	0x88	/* ADC interrupt current count */
-#define AD_DMA_ADCIBC	0x8c	/* ADC interrupt base count */
-#define AD_DMA_SYNICC	0x90	/* SYN interrupt current count */
-#define AD_DMA_SYNIBC	0x94	/* SYN interrupt base count */
-#define AD_DMA_WAVICC	0x98	/* WAV interrupt current count */
-#define AD_DMA_WAVIBC	0x9c	/* WAV interrupt base count */
-#define AD_DMA_RESCTRL	0xa0	/* RES PCI control/status */
-#define AD_DMA_ADCCTRL	0xa8	/* ADC PCI control/status */
-#define AD_DMA_SYNCTRL	0xb0	/* SYN PCI control/status */
-#define AD_DMA_WAVCTRL	0xb8	/* WAV PCI control/status */
-#define AD_DMA_DISR	0xc0	/* PCI DMA intr status */
-#define AD_DMA_CHSS	0xc4	/* PCI DMA channel stop status */
-
-#define AD_GPIO_IPC	0xc8	/* IO port ctrl */
-#define AD_GPIO_OP	0xca	/* IO output status */
-#define AD_GPIO_IP	0xcc	/* IO input status */
-
-/* AC97 registers, 0x100 - 0x17f; see ac97.h */
-#define AD_AC97_BASE    0x100   /* ac97 base register */
-#define AD_AC97_ACIC	0x180	/* AC Link interface ctrl */
-
-/* OPL3; BAR1 */
-#define AD_OPL_M0AS	0x00	/* Music0 address/status */
-#define AD_OPL_M0DATA	0x01	/* Music0 data */
-#define AD_OPL_M1A	0x02	/* Music1 address */
-#define AD_OPL_M1DATA	0x03	/* Music1 data */
-/* 0x04-0x0f reserved */
-
-/* MIDI; BAR2 */
-#define AD_MIDA		0x00	/* MIDI data */
-#define AD_MISC		0x01	/* MIDI status/cmd */
-/* 0x02-0xff reserved */
-
-#define AD_DS_IOMEMSIZE	512
-#define AD_OPL_MEMSIZE	16
-#define AD_MIDI_MEMSIZE	16
-
-#define AD_WAV_STATE	0
-#define AD_ADC_STATE	1
-#define AD_MAX_STATES	2
-
-#define DMA_SIZE	(128*1024)
-
-#define DMA_FLAG_MAPPED	1
-
-struct ad1889_dev;
-
-typedef struct ad1889_state {
-	struct ad1889_dev *card;
-
-	mode_t open_mode;
-	struct dmabuf {
-		unsigned int rate;
-		unsigned char fmt, enable;
-
-		/* buf management */
-		size_t rawbuf_size;
-		void *rawbuf;
-		dma_addr_t dma_handle;	/* mapped address */
-		unsigned long dma_len;	/* number of bytes mapped */
-
-		/* indexes into rawbuf for setting up DMA engine */
-		volatile unsigned long rd_ptr, wr_ptr;
-
-		wait_queue_head_t wait; /* to wait for buf servicing */
-
-		/* OSS bits */
-		unsigned int mapped:1;
-		unsigned int ready:1;
-		unsigned int ossfragshift;
-		int ossmaxfrags;
-		unsigned int subdivision;
-	} dmabuf;
-
-	struct mutex mutex;
-} ad1889_state_t;
-
-typedef struct ad1889_dev {
-	void __iomem *regbase;
-	struct pci_dev *pci;
-	
-	spinlock_t lock;
-
-	int dev_audio;
-
-	/* states; one per channel; right now only WAV and ADC */
-	struct ad1889_state state[AD_MAX_STATES];
-
-	/* AC97 codec */
-	struct ac97_codec *ac97_codec;
-	u16 ac97_features;
-
-	/* debugging stuff */
-	struct stats {
-		unsigned int wav_intrs, adc_intrs;
-		unsigned int blocks, underrun, error;
-	} stats;
-} ad1889_dev_t;
-
-typedef struct ad1889_reg {
-	const char *name;
-	int offset;
-	int width;
-} ad1889_reg_t;
-
-#endif
diff --git a/sound/oss/adlib_card.c b/sound/oss/adlib_card.c
deleted file mode 100644
index c9a7c9b..0000000
--- a/sound/oss/adlib_card.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * sound/oss/adlib_card.c
- *
- * Detection routine for the AdLib card.
- *
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "sound_config.h"
-
-#include "opl3.h"
-
-static void __init attach_adlib_card(struct address_info *hw_config)
-{
-	hw_config->slots[0] = opl3_init(hw_config->io_base, hw_config->osp, THIS_MODULE);
-}
-
-static int __init probe_adlib(struct address_info *hw_config)
-{
-	return opl3_detect(hw_config->io_base, hw_config->osp);
-}
-
-static struct address_info cfg;
-
-static int __initdata io = -1;
-
-module_param(io, int, 0);
-
-static int __init init_adlib(void)
-{
-	cfg.io_base = io;
-
-	if (cfg.io_base == -1) {
-		printk(KERN_ERR "adlib: must specify I/O address.\n");
-		return -EINVAL;
-	}
-	if (probe_adlib(&cfg) == 0)
-		return -ENODEV;
-	attach_adlib_card(&cfg);
-
-	return 0;
-}
-
-static void __exit cleanup_adlib(void)
-{
-	sound_unload_synthdev(cfg.slots[0]);
-	
-}
-
-module_init(init_adlib);
-module_exit(cleanup_adlib);
-
-#ifndef MODULE
-static int __init setup_adlib(char *str)
-{
-        /* io */
-	int ints[2];
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io = ints[1];
-
-	return 1;
-}
-__setup("adlib=", setup_adlib);
-#endif
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/cs461x.h b/sound/oss/cs461x.h
deleted file mode 100644
index 0ce4133..0000000
--- a/sound/oss/cs461x.h
+++ /dev/null
@@ -1,1691 +0,0 @@
-#ifndef __CS461X_H
-#define __CS461X_H
-
-/*
- *  Copyright (c) by Cirrus Logic Corporation <pcaudio@crystal.cirrus.com>
- *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- *  Definitions for Cirrus Logic CS461x chips
- *
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS            0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4610
-#define PCI_DEVICE_ID_CIRRUS_4610       0x6001
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4612
-#define PCI_DEVICE_ID_CIRRUS_4612       0x6003
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4615
-#define PCI_DEVICE_ID_CIRRUS_4615       0x6004
-#endif
-
-/*
- *  Direct registers
- */
-
-/*
- *  The following define the offsets of the registers accessed via base address
- *  register zero on the CS461x part.
- */
-#define BA0_HISR				0x00000000
-#define BA0_HSR0                                0x00000004
-#define BA0_HICR                                0x00000008
-#define BA0_DMSR                                0x00000100
-#define BA0_HSAR                                0x00000110
-#define BA0_HDAR                                0x00000114
-#define BA0_HDMR                                0x00000118
-#define BA0_HDCR                                0x0000011C
-#define BA0_PFMC                                0x00000200
-#define BA0_PFCV1                               0x00000204
-#define BA0_PFCV2                               0x00000208
-#define BA0_PCICFG00                            0x00000300
-#define BA0_PCICFG04                            0x00000304
-#define BA0_PCICFG08                            0x00000308
-#define BA0_PCICFG0C                            0x0000030C
-#define BA0_PCICFG10                            0x00000310
-#define BA0_PCICFG14                            0x00000314
-#define BA0_PCICFG18                            0x00000318
-#define BA0_PCICFG1C                            0x0000031C
-#define BA0_PCICFG20                            0x00000320
-#define BA0_PCICFG24                            0x00000324
-#define BA0_PCICFG28                            0x00000328
-#define BA0_PCICFG2C                            0x0000032C
-#define BA0_PCICFG30                            0x00000330
-#define BA0_PCICFG34                            0x00000334
-#define BA0_PCICFG38                            0x00000338
-#define BA0_PCICFG3C                            0x0000033C
-#define BA0_CLKCR1                              0x00000400
-#define BA0_CLKCR2                              0x00000404
-#define BA0_PLLM                                0x00000408
-#define BA0_PLLCC                               0x0000040C
-#define BA0_FRR                                 0x00000410 
-#define BA0_CFL1                                0x00000414
-#define BA0_CFL2                                0x00000418
-#define BA0_SERMC1                              0x00000420
-#define BA0_SERMC2                              0x00000424
-#define BA0_SERC1                               0x00000428
-#define BA0_SERC2                               0x0000042C
-#define BA0_SERC3                               0x00000430
-#define BA0_SERC4                               0x00000434
-#define BA0_SERC5                               0x00000438
-#define BA0_SERBSP                              0x0000043C
-#define BA0_SERBST                              0x00000440
-#define BA0_SERBCM                              0x00000444
-#define BA0_SERBAD                              0x00000448
-#define BA0_SERBCF                              0x0000044C
-#define BA0_SERBWP                              0x00000450
-#define BA0_SERBRP                              0x00000454
-#ifndef NO_CS4612
-#define BA0_ASER_FADDR                          0x00000458
-#endif
-#define BA0_ACCTL                               0x00000460
-#define BA0_ACSTS                               0x00000464
-#define BA0_ACOSV                               0x00000468
-#define BA0_ACCAD                               0x0000046C
-#define BA0_ACCDA                               0x00000470
-#define BA0_ACISV                               0x00000474
-#define BA0_ACSAD                               0x00000478
-#define BA0_ACSDA                               0x0000047C
-#define BA0_JSPT                                0x00000480
-#define BA0_JSCTL                               0x00000484
-#define BA0_JSC1                                0x00000488
-#define BA0_JSC2                                0x0000048C
-#define BA0_MIDCR                               0x00000490
-#define BA0_MIDSR                               0x00000494
-#define BA0_MIDWP                               0x00000498
-#define BA0_MIDRP                               0x0000049C
-#define BA0_JSIO                                0x000004A0
-#ifndef NO_CS4612
-#define BA0_ASER_MASTER                         0x000004A4
-#endif
-#define BA0_CFGI                                0x000004B0
-#define BA0_SSVID                               0x000004B4
-#define BA0_GPIOR                               0x000004B8
-#ifndef NO_CS4612
-#define BA0_EGPIODR                             0x000004BC
-#define BA0_EGPIOPTR                            0x000004C0
-#define BA0_EGPIOTR                             0x000004C4
-#define BA0_EGPIOWR                             0x000004C8
-#define BA0_EGPIOSR                             0x000004CC
-#define BA0_SERC6                               0x000004D0
-#define BA0_SERC7                               0x000004D4
-#define BA0_SERACC                              0x000004D8
-#define BA0_ACCTL2                              0x000004E0
-#define BA0_ACSTS2                              0x000004E4
-#define BA0_ACOSV2                              0x000004E8
-#define BA0_ACCAD2                              0x000004EC
-#define BA0_ACCDA2                              0x000004F0
-#define BA0_ACISV2                              0x000004F4
-#define BA0_ACSAD2                              0x000004F8
-#define BA0_ACSDA2                              0x000004FC
-#define BA0_IOTAC0                              0x00000500
-#define BA0_IOTAC1                              0x00000504
-#define BA0_IOTAC2                              0x00000508
-#define BA0_IOTAC3                              0x0000050C
-#define BA0_IOTAC4                              0x00000510
-#define BA0_IOTAC5                              0x00000514
-#define BA0_IOTAC6                              0x00000518
-#define BA0_IOTAC7                              0x0000051C
-#define BA0_IOTAC8                              0x00000520
-#define BA0_IOTAC9                              0x00000524
-#define BA0_IOTAC10                             0x00000528
-#define BA0_IOTAC11                             0x0000052C
-#define BA0_IOTFR0                              0x00000540
-#define BA0_IOTFR1                              0x00000544
-#define BA0_IOTFR2                              0x00000548
-#define BA0_IOTFR3                              0x0000054C
-#define BA0_IOTFR4                              0x00000550
-#define BA0_IOTFR5                              0x00000554
-#define BA0_IOTFR6                              0x00000558
-#define BA0_IOTFR7                              0x0000055C
-#define BA0_IOTFIFO                             0x00000580
-#define BA0_IOTRRD                              0x00000584
-#define BA0_IOTFP                               0x00000588
-#define BA0_IOTCR                               0x0000058C
-#define BA0_DPCID                               0x00000590
-#define BA0_DPCIA                               0x00000594
-#define BA0_DPCIC                               0x00000598
-#define BA0_PCPCIR                              0x00000600
-#define BA0_PCPCIG                              0x00000604
-#define BA0_PCPCIEN                             0x00000608
-#define BA0_EPCIPMC                             0x00000610
-#endif
-
-/*
- *  The following define the offsets of the registers and memories accessed via
- *  base address register one on the CS461x part.
- */
-#define BA1_SP_DMEM0                            0x00000000
-#define BA1_SP_DMEM1                            0x00010000
-#define BA1_SP_PMEM                             0x00020000
-#define BA1_SP_REG				0x00030000
-#define BA1_SPCR                                0x00030000
-#define BA1_DREG                                0x00030004
-#define BA1_DSRWP                               0x00030008
-#define BA1_TWPR                                0x0003000C
-#define BA1_SPWR                                0x00030010
-#define BA1_SPIR                                0x00030014
-#define BA1_FGR1                                0x00030020
-#define BA1_SPCS                                0x00030028
-#define BA1_SDSR                                0x0003002C
-#define BA1_FRMT                                0x00030030
-#define BA1_FRCC                                0x00030034
-#define BA1_FRSC                                0x00030038
-#define BA1_OMNI_MEM                            0x000E0000
-
-/*
- *  The following defines are for the flags in the host interrupt status
- *  register.
- */
-#define HISR_VC_MASK                            0x0000FFFF
-#define HISR_VC0                                0x00000001
-#define HISR_VC1                                0x00000002
-#define HISR_VC2                                0x00000004
-#define HISR_VC3                                0x00000008
-#define HISR_VC4                                0x00000010
-#define HISR_VC5                                0x00000020
-#define HISR_VC6                                0x00000040
-#define HISR_VC7                                0x00000080
-#define HISR_VC8                                0x00000100
-#define HISR_VC9                                0x00000200
-#define HISR_VC10                               0x00000400
-#define HISR_VC11                               0x00000800
-#define HISR_VC12                               0x00001000
-#define HISR_VC13                               0x00002000
-#define HISR_VC14                               0x00004000
-#define HISR_VC15                               0x00008000
-#define HISR_INT0                               0x00010000
-#define HISR_INT1                               0x00020000
-#define HISR_DMAI                               0x00040000
-#define HISR_FROVR                              0x00080000
-#define HISR_MIDI                               0x00100000
-#ifdef NO_CS4612
-#define HISR_RESERVED                           0x0FE00000
-#else
-#define HISR_SBINT                              0x00200000
-#define HISR_RESERVED                           0x0FC00000
-#endif
-#define HISR_H0P                                0x40000000
-#define HISR_INTENA                             0x80000000
-
-/*
- *  The following defines are for the flags in the host signal register 0.
- */
-#define HSR0_VC_MASK                            0xFFFFFFFF
-#define HSR0_VC16                               0x00000001
-#define HSR0_VC17                               0x00000002
-#define HSR0_VC18                               0x00000004
-#define HSR0_VC19                               0x00000008
-#define HSR0_VC20                               0x00000010
-#define HSR0_VC21                               0x00000020
-#define HSR0_VC22                               0x00000040
-#define HSR0_VC23                               0x00000080
-#define HSR0_VC24                               0x00000100
-#define HSR0_VC25                               0x00000200
-#define HSR0_VC26                               0x00000400
-#define HSR0_VC27                               0x00000800
-#define HSR0_VC28                               0x00001000
-#define HSR0_VC29                               0x00002000
-#define HSR0_VC30                               0x00004000
-#define HSR0_VC31                               0x00008000
-#define HSR0_VC32                               0x00010000
-#define HSR0_VC33                               0x00020000
-#define HSR0_VC34                               0x00040000
-#define HSR0_VC35                               0x00080000
-#define HSR0_VC36                               0x00100000
-#define HSR0_VC37                               0x00200000
-#define HSR0_VC38                               0x00400000
-#define HSR0_VC39                               0x00800000
-#define HSR0_VC40                               0x01000000
-#define HSR0_VC41                               0x02000000
-#define HSR0_VC42                               0x04000000
-#define HSR0_VC43                               0x08000000
-#define HSR0_VC44                               0x10000000
-#define HSR0_VC45                               0x20000000
-#define HSR0_VC46                               0x40000000
-#define HSR0_VC47                               0x80000000
-
-/*
- *  The following defines are for the flags in the host interrupt control
- *  register.
- */
-#define HICR_IEV                                0x00000001
-#define HICR_CHGM                               0x00000002
-
-/*
- *  The following defines are for the flags in the DMA status register.
- */
-#define DMSR_HP                                 0x00000001
-#define DMSR_HR                                 0x00000002
-#define DMSR_SP                                 0x00000004
-#define DMSR_SR                                 0x00000008
-
-/*
- *  The following defines are for the flags in the host DMA source address
- *  register.
- */
-#define HSAR_HOST_ADDR_MASK                     0xFFFFFFFF
-#define HSAR_DSP_ADDR_MASK                      0x0000FFFF
-#define HSAR_MEMID_MASK                         0x000F0000
-#define HSAR_MEMID_SP_DMEM0                     0x00000000
-#define HSAR_MEMID_SP_DMEM1                     0x00010000
-#define HSAR_MEMID_SP_PMEM                      0x00020000
-#define HSAR_MEMID_SP_DEBUG                     0x00030000
-#define HSAR_MEMID_OMNI_MEM                     0x000E0000
-#define HSAR_END                                0x40000000
-#define HSAR_ERR                                0x80000000
-
-/*
- *  The following defines are for the flags in the host DMA destination address
- *  register.
- */
-#define HDAR_HOST_ADDR_MASK                     0xFFFFFFFF
-#define HDAR_DSP_ADDR_MASK                      0x0000FFFF
-#define HDAR_MEMID_MASK                         0x000F0000
-#define HDAR_MEMID_SP_DMEM0                     0x00000000
-#define HDAR_MEMID_SP_DMEM1                     0x00010000
-#define HDAR_MEMID_SP_PMEM                      0x00020000
-#define HDAR_MEMID_SP_DEBUG                     0x00030000
-#define HDAR_MEMID_OMNI_MEM                     0x000E0000
-#define HDAR_END                                0x40000000
-#define HDAR_ERR                                0x80000000
-
-/*
- *  The following defines are for the flags in the host DMA control register.
- */
-#define HDMR_AC_MASK                            0x0000F000
-#define HDMR_AC_8_16                            0x00001000
-#define HDMR_AC_M_S                             0x00002000
-#define HDMR_AC_B_L                             0x00004000
-#define HDMR_AC_S_U                             0x00008000
-
-/*
- *  The following defines are for the flags in the host DMA control register.
- */
-#define HDCR_COUNT_MASK                         0x000003FF
-#define HDCR_DONE                               0x00004000
-#define HDCR_OPT                                0x00008000
-#define HDCR_WBD                                0x00400000
-#define HDCR_WBS                                0x00800000
-#define HDCR_DMS_MASK                           0x07000000
-#define HDCR_DMS_LINEAR                         0x00000000
-#define HDCR_DMS_16_DWORDS                      0x01000000
-#define HDCR_DMS_32_DWORDS                      0x02000000
-#define HDCR_DMS_64_DWORDS                      0x03000000
-#define HDCR_DMS_128_DWORDS                     0x04000000
-#define HDCR_DMS_256_DWORDS                     0x05000000
-#define HDCR_DMS_512_DWORDS                     0x06000000
-#define HDCR_DMS_1024_DWORDS                    0x07000000
-#define HDCR_DH                                 0x08000000
-#define HDCR_SMS_MASK                           0x70000000
-#define HDCR_SMS_LINEAR                         0x00000000
-#define HDCR_SMS_16_DWORDS                      0x10000000
-#define HDCR_SMS_32_DWORDS                      0x20000000
-#define HDCR_SMS_64_DWORDS                      0x30000000
-#define HDCR_SMS_128_DWORDS                     0x40000000
-#define HDCR_SMS_256_DWORDS                     0x50000000
-#define HDCR_SMS_512_DWORDS                     0x60000000
-#define HDCR_SMS_1024_DWORDS                    0x70000000
-#define HDCR_SH                                 0x80000000
-#define HDCR_COUNT_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the performance monitor control
- *  register.
- */
-#define PFMC_C1SS_MASK                          0x0000001F
-#define PFMC_C1EV                               0x00000020
-#define PFMC_C1RS                               0x00008000
-#define PFMC_C2SS_MASK                          0x001F0000
-#define PFMC_C2EV                               0x00200000
-#define PFMC_C2RS                               0x80000000
-#define PFMC_C1SS_SHIFT                         0
-#define PFMC_C2SS_SHIFT                         16
-#define PFMC_BUS_GRANT                          0
-#define PFMC_GRANT_AFTER_REQ                    1
-#define PFMC_TRANSACTION                        2
-#define PFMC_DWORD_TRANSFER                     3
-#define PFMC_SLAVE_READ                         4
-#define PFMC_SLAVE_WRITE                        5
-#define PFMC_PREEMPTION                         6
-#define PFMC_DISCONNECT_RETRY                   7
-#define PFMC_INTERRUPT                          8
-#define PFMC_BUS_OWNERSHIP                      9
-#define PFMC_TRANSACTION_LAG                    10
-#define PFMC_PCI_CLOCK                          11
-#define PFMC_SERIAL_CLOCK                       12
-#define PFMC_SP_CLOCK                           13
-
-/*
- *  The following defines are for the flags in the performance counter value 1
- *  register.
- */
-#define PFCV1_PC1V_MASK                         0xFFFFFFFF
-#define PFCV1_PC1V_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the performance counter value 2
- *  register.
- */
-#define PFCV2_PC2V_MASK                         0xFFFFFFFF
-#define PFCV2_PC2V_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the clock control register 1.
- */
-#define CLKCR1_OSCS                             0x00000001
-#define CLKCR1_OSCP                             0x00000002
-#define CLKCR1_PLLSS_MASK                       0x0000000C
-#define CLKCR1_PLLSS_SERIAL                     0x00000000
-#define CLKCR1_PLLSS_CRYSTAL                    0x00000004
-#define CLKCR1_PLLSS_PCI                        0x00000008
-#define CLKCR1_PLLSS_RESERVED                   0x0000000C
-#define CLKCR1_PLLP                             0x00000010
-#define CLKCR1_SWCE                             0x00000020
-#define CLKCR1_PLLOS                            0x00000040
-
-/*
- *  The following defines are for the flags in the clock control register 2.
- */
-#define CLKCR2_PDIVS_MASK                       0x0000000F
-#define CLKCR2_PDIVS_1                          0x00000001
-#define CLKCR2_PDIVS_2                          0x00000002
-#define CLKCR2_PDIVS_4                          0x00000004
-#define CLKCR2_PDIVS_7                          0x00000007
-#define CLKCR2_PDIVS_8                          0x00000008
-#define CLKCR2_PDIVS_16                         0x00000000
-
-/*
- *  The following defines are for the flags in the PLL multiplier register.
- */
-#define PLLM_MASK                               0x000000FF
-#define PLLM_SHIFT                              0
-
-/*
- *  The following defines are for the flags in the PLL capacitor coefficient
- *  register.
- */
-#define PLLCC_CDR_MASK                          0x00000007
-#ifndef NO_CS4610
-#define PLLCC_CDR_240_350_MHZ                   0x00000000
-#define PLLCC_CDR_184_265_MHZ                   0x00000001
-#define PLLCC_CDR_144_205_MHZ                   0x00000002
-#define PLLCC_CDR_111_160_MHZ                   0x00000003
-#define PLLCC_CDR_87_123_MHZ                    0x00000004
-#define PLLCC_CDR_67_96_MHZ                     0x00000005
-#define PLLCC_CDR_52_74_MHZ                     0x00000006
-#define PLLCC_CDR_45_58_MHZ                     0x00000007
-#endif
-#ifndef NO_CS4612
-#define PLLCC_CDR_271_398_MHZ                   0x00000000
-#define PLLCC_CDR_227_330_MHZ                   0x00000001
-#define PLLCC_CDR_167_239_MHZ                   0x00000002
-#define PLLCC_CDR_150_215_MHZ                   0x00000003
-#define PLLCC_CDR_107_154_MHZ                   0x00000004
-#define PLLCC_CDR_98_140_MHZ                    0x00000005
-#define PLLCC_CDR_73_104_MHZ                    0x00000006
-#define PLLCC_CDR_63_90_MHZ                     0x00000007
-#endif
-#define PLLCC_LPF_MASK                          0x000000F8
-#ifndef NO_CS4610
-#define PLLCC_LPF_23850_60000_KHZ               0x00000000
-#define PLLCC_LPF_7960_26290_KHZ                0x00000008
-#define PLLCC_LPF_4160_10980_KHZ                0x00000018
-#define PLLCC_LPF_1740_4580_KHZ                 0x00000038
-#define PLLCC_LPF_724_1910_KHZ                  0x00000078
-#define PLLCC_LPF_317_798_KHZ                   0x000000F8
-#endif
-#ifndef NO_CS4612
-#define PLLCC_LPF_25580_64530_KHZ               0x00000000
-#define PLLCC_LPF_14360_37270_KHZ               0x00000008
-#define PLLCC_LPF_6100_16020_KHZ                0x00000018
-#define PLLCC_LPF_2540_6690_KHZ                 0x00000038
-#define PLLCC_LPF_1050_2780_KHZ                 0x00000078
-#define PLLCC_LPF_450_1160_KHZ                  0x000000F8
-#endif
-
-/*
- *  The following defines are for the flags in the feature reporting register.
- */
-#define FRR_FAB_MASK                            0x00000003
-#define FRR_MASK_MASK                           0x0000001C
-#ifdef NO_CS4612
-#define FRR_CFOP_MASK                           0x000000E0
-#else
-#define FRR_CFOP_MASK                           0x00000FE0
-#endif
-#define FRR_CFOP_NOT_DVD                        0x00000020
-#define FRR_CFOP_A3D                            0x00000040
-#define FRR_CFOP_128_PIN                        0x00000080
-#ifndef NO_CS4612
-#define FRR_CFOP_CS4280                         0x00000800
-#endif
-#define FRR_FAB_SHIFT                           0
-#define FRR_MASK_SHIFT                          2
-#define FRR_CFOP_SHIFT                          5
-
-/*
- *  The following defines are for the flags in the configuration load 1
- *  register.
- */
-#define CFL1_CLOCK_SOURCE_MASK                  0x00000003
-#define CFL1_CLOCK_SOURCE_CS423X                0x00000000
-#define CFL1_CLOCK_SOURCE_AC97                  0x00000001
-#define CFL1_CLOCK_SOURCE_CRYSTAL               0x00000002
-#define CFL1_CLOCK_SOURCE_DUAL_AC97             0x00000003
-#define CFL1_VALID_DATA_MASK                    0x000000FF
-
-/*
- *  The following defines are for the flags in the configuration load 2
- *  register.
- */
-#define CFL2_VALID_DATA_MASK                    0x000000FF
-
-/*
- *  The following defines are for the flags in the serial port master control
- *  register 1.
- */
-#define SERMC1_MSPE                             0x00000001
-#define SERMC1_PTC_MASK                         0x0000000E
-#define SERMC1_PTC_CS423X                       0x00000000
-#define SERMC1_PTC_AC97                         0x00000002
-#define SERMC1_PTC_DAC                          0x00000004
-#define SERMC1_PLB                              0x00000010
-#define SERMC1_XLB                              0x00000020
-
-/*
- *  The following defines are for the flags in the serial port master control
- *  register 2.
- */
-#define SERMC2_LROE                             0x00000001
-#define SERMC2_MCOE                             0x00000002
-#define SERMC2_MCDIV                            0x00000004
-
-/*
- *  The following defines are for the flags in the serial port 1 configuration
- *  register.
- */
-#define SERC1_SO1EN                             0x00000001
-#define SERC1_SO1F_MASK                         0x0000000E
-#define SERC1_SO1F_CS423X                       0x00000000
-#define SERC1_SO1F_AC97                         0x00000002
-#define SERC1_SO1F_DAC                          0x00000004
-#define SERC1_SO1F_SPDIF                        0x00000006
-
-/*
- *  The following defines are for the flags in the serial port 2 configuration
- *  register.
- */
-#define SERC2_SI1EN                             0x00000001
-#define SERC2_SI1F_MASK                         0x0000000E
-#define SERC2_SI1F_CS423X                       0x00000000
-#define SERC2_SI1F_AC97                         0x00000002
-#define SERC2_SI1F_ADC                          0x00000004
-#define SERC2_SI1F_SPDIF                        0x00000006
-
-/*
- *  The following defines are for the flags in the serial port 3 configuration
- *  register.
- */
-#define SERC3_SO2EN                             0x00000001
-#define SERC3_SO2F_MASK                         0x00000006
-#define SERC3_SO2F_DAC                          0x00000000
-#define SERC3_SO2F_SPDIF                        0x00000002
-
-/*
- *  The following defines are for the flags in the serial port 4 configuration
- *  register.
- */
-#define SERC4_SO3EN                             0x00000001
-#define SERC4_SO3F_MASK                         0x00000006
-#define SERC4_SO3F_DAC                          0x00000000
-#define SERC4_SO3F_SPDIF                        0x00000002
-
-/*
- *  The following defines are for the flags in the serial port 5 configuration
- *  register.
- */
-#define SERC5_SI2EN                             0x00000001
-#define SERC5_SI2F_MASK                         0x00000006
-#define SERC5_SI2F_ADC                          0x00000000
-#define SERC5_SI2F_SPDIF                        0x00000002
-
-/*
- *  The following defines are for the flags in the serial port backdoor sample
- *  pointer register.
- */
-#define SERBSP_FSP_MASK                         0x0000000F
-#define SERBSP_FSP_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the serial port backdoor status
- *  register.
- */
-#define SERBST_RRDY                             0x00000001
-#define SERBST_WBSY                             0x00000002
-
-/*
- *  The following defines are for the flags in the serial port backdoor command
- *  register.
- */
-#define SERBCM_RDC                              0x00000001
-#define SERBCM_WRC                              0x00000002
-
-/*
- *  The following defines are for the flags in the serial port backdoor address
- *  register.
- */
-#ifdef NO_CS4612
-#define SERBAD_FAD_MASK                         0x000000FF
-#else
-#define SERBAD_FAD_MASK                         0x000001FF
-#endif
-#define SERBAD_FAD_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the serial port backdoor
- *  configuration register.
- */
-#define SERBCF_HBP                              0x00000001
-
-/*
- *  The following defines are for the flags in the serial port backdoor write
- *  port register.
- */
-#define SERBWP_FWD_MASK                         0x000FFFFF
-#define SERBWP_FWD_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the serial port backdoor read
- *  port register.
- */
-#define SERBRP_FRD_MASK                         0x000FFFFF
-#define SERBRP_FRD_SHIFT                        0
-
-/*
- *  The following defines are for the flags in the async FIFO address register.
- */
-#ifndef NO_CS4612
-#define ASER_FADDR_A1_MASK                      0x000001FF
-#define ASER_FADDR_EN1                          0x00008000
-#define ASER_FADDR_A2_MASK                      0x01FF0000
-#define ASER_FADDR_EN2                          0x80000000
-#define ASER_FADDR_A1_SHIFT                     0
-#define ASER_FADDR_A2_SHIFT                     16
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 control register.
- */
-#define ACCTL_RSTN                              0x00000001
-#define ACCTL_ESYN                              0x00000002
-#define ACCTL_VFRM                              0x00000004
-#define ACCTL_DCV                               0x00000008
-#define ACCTL_CRW                               0x00000010
-#define ACCTL_ASYN                              0x00000020
-#ifndef NO_CS4612
-#define ACCTL_TC                                0x00000040
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 status register.
- */
-#define ACSTS_CRDY                              0x00000001
-#define ACSTS_VSTS                              0x00000002
-#ifndef NO_CS4612
-#define ACSTS_WKUP                              0x00000004
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 output slot valid
- *  register.
- */
-#define ACOSV_SLV3                              0x00000001
-#define ACOSV_SLV4                              0x00000002
-#define ACOSV_SLV5                              0x00000004
-#define ACOSV_SLV6                              0x00000008
-#define ACOSV_SLV7                              0x00000010
-#define ACOSV_SLV8                              0x00000020
-#define ACOSV_SLV9                              0x00000040
-#define ACOSV_SLV10                             0x00000080
-#define ACOSV_SLV11                             0x00000100
-#define ACOSV_SLV12                             0x00000200
-
-/*
- *  The following defines are for the flags in the AC97 command address
- *  register.
- */
-#define ACCAD_CI_MASK                           0x0000007F
-#define ACCAD_CI_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the AC97 command data register.
- */
-#define ACCDA_CD_MASK                           0x0000FFFF
-#define ACCDA_CD_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the AC97 input slot valid
- *  register.
- */
-#define ACISV_ISV3                              0x00000001
-#define ACISV_ISV4                              0x00000002
-#define ACISV_ISV5                              0x00000004
-#define ACISV_ISV6                              0x00000008
-#define ACISV_ISV7                              0x00000010
-#define ACISV_ISV8                              0x00000020
-#define ACISV_ISV9                              0x00000040
-#define ACISV_ISV10                             0x00000080
-#define ACISV_ISV11                             0x00000100
-#define ACISV_ISV12                             0x00000200
-
-/*
- *  The following defines are for the flags in the AC97 status address
- *  register.
- */
-#define ACSAD_SI_MASK                           0x0000007F
-#define ACSAD_SI_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the AC97 status data register.
- */
-#define ACSDA_SD_MASK                           0x0000FFFF
-#define ACSDA_SD_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the joystick poll/trigger
- *  register.
- */
-#define JSPT_CAX                                0x00000001
-#define JSPT_CAY                                0x00000002
-#define JSPT_CBX                                0x00000004
-#define JSPT_CBY                                0x00000008
-#define JSPT_BA1                                0x00000010
-#define JSPT_BA2                                0x00000020
-#define JSPT_BB1                                0x00000040
-#define JSPT_BB2                                0x00000080
-
-/*
- *  The following defines are for the flags in the joystick control register.
- */
-#define JSCTL_SP_MASK                           0x00000003
-#define JSCTL_SP_SLOW                           0x00000000
-#define JSCTL_SP_MEDIUM_SLOW                    0x00000001
-#define JSCTL_SP_MEDIUM_FAST                    0x00000002
-#define JSCTL_SP_FAST                           0x00000003
-#define JSCTL_ARE                               0x00000004
-
-/*
- *  The following defines are for the flags in the joystick coordinate pair 1
- *  readback register.
- */
-#define JSC1_Y1V_MASK                           0x0000FFFF
-#define JSC1_X1V_MASK                           0xFFFF0000
-#define JSC1_Y1V_SHIFT                          0
-#define JSC1_X1V_SHIFT                          16
-
-/*
- *  The following defines are for the flags in the joystick coordinate pair 2
- *  readback register.
- */
-#define JSC2_Y2V_MASK                           0x0000FFFF
-#define JSC2_X2V_MASK                           0xFFFF0000
-#define JSC2_Y2V_SHIFT                          0
-#define JSC2_X2V_SHIFT                          16
-
-/*
- *  The following defines are for the flags in the MIDI control register.
- */
-#define MIDCR_TXE                               0x00000001	/* Enable transmitting. */
-#define MIDCR_RXE                               0x00000002	/* Enable receiving. */
-#define MIDCR_RIE                               0x00000004	/* Interrupt upon tx ready. */
-#define MIDCR_TIE                               0x00000008	/* Interrupt upon rx ready. */
-#define MIDCR_MLB                               0x00000010	/* Enable midi loopback. */
-#define MIDCR_MRST                              0x00000020	/* Reset interface. */
-
-/*
- *  The following defines are for the flags in the MIDI status register.
- */
-#define MIDSR_TBF                               0x00000001	/* Tx FIFO is full. */
-#define MIDSR_RBE                               0x00000002	/* Rx FIFO is empty. */
-
-/*
- *  The following defines are for the flags in the MIDI write port register.
- */
-#define MIDWP_MWD_MASK                          0x000000FF
-#define MIDWP_MWD_SHIFT                         0
-
-/*
- *  The following defines are for the flags in the MIDI read port register.
- */
-#define MIDRP_MRD_MASK                          0x000000FF
-#define MIDRP_MRD_SHIFT                         0
-
-/*
- *  The following defines are for the flags in the joystick GPIO register.
- */
-#define JSIO_DAX                                0x00000001
-#define JSIO_DAY                                0x00000002
-#define JSIO_DBX                                0x00000004
-#define JSIO_DBY                                0x00000008
-#define JSIO_AXOE                               0x00000010
-#define JSIO_AYOE                               0x00000020
-#define JSIO_BXOE                               0x00000040
-#define JSIO_BYOE                               0x00000080
-
-/*
- *  The following defines are for the flags in the master async/sync serial
- *  port enable register.
- */
-#ifndef NO_CS4612
-#define ASER_MASTER_ME                          0x00000001
-#endif
-
-/*
- *  The following defines are for the flags in the configuration interface
- *  register.
- */
-#define CFGI_CLK                                0x00000001
-#define CFGI_DOUT                               0x00000002
-#define CFGI_DIN_EEN                            0x00000004
-#define CFGI_EELD                               0x00000008
-
-/*
- *  The following defines are for the flags in the subsystem ID and vendor ID
- *  register.
- */
-#define SSVID_VID_MASK                          0x0000FFFF
-#define SSVID_SID_MASK                          0xFFFF0000
-#define SSVID_VID_SHIFT                         0
-#define SSVID_SID_SHIFT                         16
-
-/*
- *  The following defines are for the flags in the GPIO pin interface register.
- */
-#define GPIOR_VOLDN                             0x00000001
-#define GPIOR_VOLUP                             0x00000002
-#define GPIOR_SI2D                              0x00000004
-#define GPIOR_SI2OE                             0x00000008
-
-/*
- *  The following defines are for the flags in the extended GPIO pin direction
- *  register.
- */
-#ifndef NO_CS4612
-#define EGPIODR_GPOE0                           0x00000001
-#define EGPIODR_GPOE1                           0x00000002
-#define EGPIODR_GPOE2                           0x00000004
-#define EGPIODR_GPOE3                           0x00000008
-#define EGPIODR_GPOE4                           0x00000010
-#define EGPIODR_GPOE5                           0x00000020
-#define EGPIODR_GPOE6                           0x00000040
-#define EGPIODR_GPOE7                           0x00000080
-#define EGPIODR_GPOE8                           0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the extended GPIO pin polarity/
- *  type register.
- */
-#ifndef NO_CS4612
-#define EGPIOPTR_GPPT0                          0x00000001
-#define EGPIOPTR_GPPT1                          0x00000002
-#define EGPIOPTR_GPPT2                          0x00000004
-#define EGPIOPTR_GPPT3                          0x00000008
-#define EGPIOPTR_GPPT4                          0x00000010
-#define EGPIOPTR_GPPT5                          0x00000020
-#define EGPIOPTR_GPPT6                          0x00000040
-#define EGPIOPTR_GPPT7                          0x00000080
-#define EGPIOPTR_GPPT8                          0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the extended GPIO pin sticky
- *  register.
- */
-#ifndef NO_CS4612
-#define EGPIOTR_GPS0                            0x00000001
-#define EGPIOTR_GPS1                            0x00000002
-#define EGPIOTR_GPS2                            0x00000004
-#define EGPIOTR_GPS3                            0x00000008
-#define EGPIOTR_GPS4                            0x00000010
-#define EGPIOTR_GPS5                            0x00000020
-#define EGPIOTR_GPS6                            0x00000040
-#define EGPIOTR_GPS7                            0x00000080
-#define EGPIOTR_GPS8                            0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the extended GPIO ping wakeup
- *  register.
- */
-#ifndef NO_CS4612
-#define EGPIOWR_GPW0                            0x00000001
-#define EGPIOWR_GPW1                            0x00000002
-#define EGPIOWR_GPW2                            0x00000004
-#define EGPIOWR_GPW3                            0x00000008
-#define EGPIOWR_GPW4                            0x00000010
-#define EGPIOWR_GPW5                            0x00000020
-#define EGPIOWR_GPW6                            0x00000040
-#define EGPIOWR_GPW7                            0x00000080
-#define EGPIOWR_GPW8                            0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the extended GPIO pin status
- *  register.
- */
-#ifndef NO_CS4612
-#define EGPIOSR_GPS0                            0x00000001
-#define EGPIOSR_GPS1                            0x00000002
-#define EGPIOSR_GPS2                            0x00000004
-#define EGPIOSR_GPS3                            0x00000008
-#define EGPIOSR_GPS4                            0x00000010
-#define EGPIOSR_GPS5                            0x00000020
-#define EGPIOSR_GPS6                            0x00000040
-#define EGPIOSR_GPS7                            0x00000080
-#define EGPIOSR_GPS8                            0x00000100
-#endif
-
-/*
- *  The following defines are for the flags in the serial port 6 configuration
- *  register.
- */
-#ifndef NO_CS4612
-#define SERC6_ASDO2EN                           0x00000001
-#endif
-
-/*
- *  The following defines are for the flags in the serial port 7 configuration
- *  register.
- */
-#ifndef NO_CS4612
-#define SERC7_ASDI2EN                           0x00000001
-#define SERC7_POSILB                            0x00000002
-#define SERC7_SIPOLB                            0x00000004
-#define SERC7_SOSILB                            0x00000008
-#define SERC7_SISOLB                            0x00000010
-#endif
-
-/*
- *  The following defines are for the flags in the serial port AC link
- *  configuration register.
- */
-#ifndef NO_CS4612
-#define SERACC_CODEC_TYPE_MASK                  0x00000001
-#define SERACC_CODEC_TYPE_1_03                  0x00000000
-#define SERACC_CODEC_TYPE_2_0                   0x00000001
-#define SERACC_TWO_CODECS                       0x00000002
-#define SERACC_MDM                              0x00000004
-#define SERACC_HSP                              0x00000008
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 control register 2.
- */
-#ifndef NO_CS4612
-#define ACCTL2_RSTN                             0x00000001
-#define ACCTL2_ESYN                             0x00000002
-#define ACCTL2_VFRM                             0x00000004
-#define ACCTL2_DCV                              0x00000008
-#define ACCTL2_CRW                              0x00000010
-#define ACCTL2_ASYN                             0x00000020
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 status register 2.
- */
-#ifndef NO_CS4612
-#define ACSTS2_CRDY                             0x00000001
-#define ACSTS2_VSTS                             0x00000002
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 output slot valid
- *  register 2.
- */
-#ifndef NO_CS4612
-#define ACOSV2_SLV3                             0x00000001
-#define ACOSV2_SLV4                             0x00000002
-#define ACOSV2_SLV5                             0x00000004
-#define ACOSV2_SLV6                             0x00000008
-#define ACOSV2_SLV7                             0x00000010
-#define ACOSV2_SLV8                             0x00000020
-#define ACOSV2_SLV9                             0x00000040
-#define ACOSV2_SLV10                            0x00000080
-#define ACOSV2_SLV11                            0x00000100
-#define ACOSV2_SLV12                            0x00000200
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 command address
- *  register 2.
- */
-#ifndef NO_CS4612
-#define ACCAD2_CI_MASK                          0x0000007F
-#define ACCAD2_CI_SHIFT                         0
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 command data register
- *  2.
- */
-#ifndef NO_CS4612
-#define ACCDA2_CD_MASK                          0x0000FFFF
-#define ACCDA2_CD_SHIFT                         0  
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 input slot valid
- *  register 2.
- */
-#ifndef NO_CS4612
-#define ACISV2_ISV3                             0x00000001
-#define ACISV2_ISV4                             0x00000002
-#define ACISV2_ISV5                             0x00000004
-#define ACISV2_ISV6                             0x00000008
-#define ACISV2_ISV7                             0x00000010
-#define ACISV2_ISV8                             0x00000020
-#define ACISV2_ISV9                             0x00000040
-#define ACISV2_ISV10                            0x00000080
-#define ACISV2_ISV11                            0x00000100
-#define ACISV2_ISV12                            0x00000200
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 status address
- *  register 2.
- */
-#ifndef NO_CS4612
-#define ACSAD2_SI_MASK                          0x0000007F
-#define ACSAD2_SI_SHIFT                         0
-#endif
-
-/*
- *  The following defines are for the flags in the AC97 status data register 2.
- */
-#ifndef NO_CS4612
-#define ACSDA2_SD_MASK                          0x0000FFFF
-#define ACSDA2_SD_SHIFT                         0
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap address and control
- *  registers (all 12).
- */
-#ifndef NO_CS4612
-#define IOTAC_SA_MASK                           0x0000FFFF
-#define IOTAC_MSK_MASK                          0x000F0000
-#define IOTAC_IODC_MASK                         0x06000000
-#define IOTAC_IODC_16_BIT                       0x00000000
-#define IOTAC_IODC_10_BIT                       0x02000000
-#define IOTAC_IODC_12_BIT                       0x04000000
-#define IOTAC_WSPI                              0x08000000
-#define IOTAC_RSPI                              0x10000000
-#define IOTAC_WSE                               0x20000000
-#define IOTAC_WE                                0x40000000
-#define IOTAC_RE                                0x80000000
-#define IOTAC_SA_SHIFT                          0
-#define IOTAC_MSK_SHIFT                         16
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap fast read registers
- *  (all 8).
- */
-#ifndef NO_CS4612
-#define IOTFR_D_MASK                            0x0000FFFF
-#define IOTFR_A_MASK                            0x000F0000
-#define IOTFR_R_MASK                            0x0F000000
-#define IOTFR_ALL                               0x40000000
-#define IOTFR_VL                                0x80000000
-#define IOTFR_D_SHIFT                           0
-#define IOTFR_A_SHIFT                           16
-#define IOTFR_R_SHIFT                           24
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap FIFO register.
- */
-#ifndef NO_CS4612
-#define IOTFIFO_BA_MASK                         0x00003FFF
-#define IOTFIFO_S_MASK                          0x00FF0000
-#define IOTFIFO_OF                              0x40000000
-#define IOTFIFO_SPIOF                           0x80000000
-#define IOTFIFO_BA_SHIFT                        0
-#define IOTFIFO_S_SHIFT                         16
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap retry read data
- *  register.
- */
-#ifndef NO_CS4612
-#define IOTRRD_D_MASK                           0x0000FFFF
-#define IOTRRD_RDV                              0x80000000
-#define IOTRRD_D_SHIFT                          0
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap FIFO pointer
- *  register.
- */
-#ifndef NO_CS4612
-#define IOTFP_CA_MASK                           0x00003FFF
-#define IOTFP_PA_MASK                           0x3FFF0000
-#define IOTFP_CA_SHIFT                          0
-#define IOTFP_PA_SHIFT                          16
-#endif
-
-/*
- *  The following defines are for the flags in the I/O trap control register.
- */
-#ifndef NO_CS4612
-#define IOTCR_ITD                               0x00000001
-#define IOTCR_HRV                               0x00000002
-#define IOTCR_SRV                               0x00000004
-#define IOTCR_DTI                               0x00000008
-#define IOTCR_DFI                               0x00000010
-#define IOTCR_DDP                               0x00000020
-#define IOTCR_JTE                               0x00000040
-#define IOTCR_PPE                               0x00000080
-#endif
-
-/*
- *  The following defines are for the flags in the direct PCI data register.
- */
-#ifndef NO_CS4612
-#define DPCID_D_MASK                            0xFFFFFFFF
-#define DPCID_D_SHIFT                           0
-#endif
-
-/*
- *  The following defines are for the flags in the direct PCI address register.
- */
-#ifndef NO_CS4612
-#define DPCIA_A_MASK                            0xFFFFFFFF
-#define DPCIA_A_SHIFT                           0
-#endif
-
-/*
- *  The following defines are for the flags in the direct PCI command register.
- */
-#ifndef NO_CS4612
-#define DPCIC_C_MASK                            0x0000000F
-#define DPCIC_C_IOREAD                          0x00000002
-#define DPCIC_C_IOWRITE                         0x00000003
-#define DPCIC_BE_MASK                           0x000000F0
-#endif
-
-/*
- *  The following defines are for the flags in the PC/PCI request register.
- */
-#ifndef NO_CS4612
-#define PCPCIR_RDC_MASK                         0x00000007
-#define PCPCIR_C_MASK                           0x00007000
-#define PCPCIR_REQ                              0x00008000
-#define PCPCIR_RDC_SHIFT                        0
-#define PCPCIR_C_SHIFT                          12
-#endif
-
-/*
- *  The following defines are for the flags in the PC/PCI grant register.
- */ 
-#ifndef NO_CS4612
-#define PCPCIG_GDC_MASK                         0x00000007
-#define PCPCIG_VL                               0x00008000
-#define PCPCIG_GDC_SHIFT                        0
-#endif
-
-/*
- *  The following defines are for the flags in the PC/PCI master enable
- *  register.
- */
-#ifndef NO_CS4612
-#define PCPCIEN_EN                              0x00000001
-#endif
-
-/*
- *  The following defines are for the flags in the extended PCI power
- *  management control register.
- */
-#ifndef NO_CS4612
-#define EPCIPMC_GWU                             0x00000001
-#define EPCIPMC_FSPC                            0x00000002
-#endif 
-
-/*
- *  The following defines are for the flags in the SP control register.
- */
-#define SPCR_RUN                                0x00000001
-#define SPCR_STPFR                              0x00000002
-#define SPCR_RUNFR                              0x00000004
-#define SPCR_TICK                               0x00000008
-#define SPCR_DRQEN                              0x00000020
-#define SPCR_RSTSP                              0x00000040
-#define SPCR_OREN                               0x00000080
-#ifndef NO_CS4612
-#define SPCR_PCIINT                             0x00000100
-#define SPCR_OINTD                              0x00000200
-#define SPCR_CRE                                0x00008000
-#endif
-
-/*
- *  The following defines are for the flags in the debug index register.
- */
-#define DREG_REGID_MASK                         0x0000007F
-#define DREG_DEBUG                              0x00000080
-#define DREG_RGBK_MASK                          0x00000700
-#define DREG_TRAP                               0x00000800
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_TRAPX                              0x00001000
-#endif
-#endif
-#define DREG_REGID_SHIFT                        0
-#define DREG_RGBK_SHIFT                         8
-#define DREG_RGBK_REGID_MASK                    0x0000077F
-#define DREG_REGID_R0                           0x00000010
-#define DREG_REGID_R1                           0x00000011
-#define DREG_REGID_R2                           0x00000012
-#define DREG_REGID_R3                           0x00000013
-#define DREG_REGID_R4                           0x00000014
-#define DREG_REGID_R5                           0x00000015
-#define DREG_REGID_R6                           0x00000016
-#define DREG_REGID_R7                           0x00000017
-#define DREG_REGID_R8                           0x00000018
-#define DREG_REGID_R9                           0x00000019
-#define DREG_REGID_RA                           0x0000001A
-#define DREG_REGID_RB                           0x0000001B
-#define DREG_REGID_RC                           0x0000001C
-#define DREG_REGID_RD                           0x0000001D
-#define DREG_REGID_RE                           0x0000001E
-#define DREG_REGID_RF                           0x0000001F
-#define DREG_REGID_RA_BUS_LOW                   0x00000020
-#define DREG_REGID_RA_BUS_HIGH                  0x00000038
-#define DREG_REGID_YBUS_LOW                     0x00000050
-#define DREG_REGID_YBUS_HIGH                    0x00000058
-#define DREG_REGID_TRAP_0                       0x00000100
-#define DREG_REGID_TRAP_1                       0x00000101
-#define DREG_REGID_TRAP_2                       0x00000102
-#define DREG_REGID_TRAP_3                       0x00000103
-#define DREG_REGID_TRAP_4                       0x00000104
-#define DREG_REGID_TRAP_5                       0x00000105
-#define DREG_REGID_TRAP_6                       0x00000106
-#define DREG_REGID_TRAP_7                       0x00000107
-#define DREG_REGID_INDIRECT_ADDRESS             0x0000010E
-#define DREG_REGID_TOP_OF_STACK                 0x0000010F
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_REGID_TRAP_8                       0x00000110
-#define DREG_REGID_TRAP_9                       0x00000111
-#define DREG_REGID_TRAP_10                      0x00000112
-#define DREG_REGID_TRAP_11                      0x00000113
-#define DREG_REGID_TRAP_12                      0x00000114
-#define DREG_REGID_TRAP_13                      0x00000115
-#define DREG_REGID_TRAP_14                      0x00000116
-#define DREG_REGID_TRAP_15                      0x00000117
-#define DREG_REGID_TRAP_16                      0x00000118
-#define DREG_REGID_TRAP_17                      0x00000119
-#define DREG_REGID_TRAP_18                      0x0000011A
-#define DREG_REGID_TRAP_19                      0x0000011B
-#define DREG_REGID_TRAP_20                      0x0000011C
-#define DREG_REGID_TRAP_21                      0x0000011D
-#define DREG_REGID_TRAP_22                      0x0000011E
-#define DREG_REGID_TRAP_23                      0x0000011F
-#endif
-#endif
-#define DREG_REGID_RSA0_LOW                     0x00000200
-#define DREG_REGID_RSA0_HIGH                    0x00000201
-#define DREG_REGID_RSA1_LOW                     0x00000202
-#define DREG_REGID_RSA1_HIGH                    0x00000203
-#define DREG_REGID_RSA2                         0x00000204
-#define DREG_REGID_RSA3                         0x00000205
-#define DREG_REGID_RSI0_LOW                     0x00000206
-#define DREG_REGID_RSI0_HIGH                    0x00000207
-#define DREG_REGID_RSI1                         0x00000208
-#define DREG_REGID_RSI2                         0x00000209
-#define DREG_REGID_SAGUSTATUS                   0x0000020A
-#define DREG_REGID_RSCONFIG01_LOW               0x0000020B
-#define DREG_REGID_RSCONFIG01_HIGH              0x0000020C
-#define DREG_REGID_RSCONFIG23_LOW               0x0000020D
-#define DREG_REGID_RSCONFIG23_HIGH              0x0000020E
-#define DREG_REGID_RSDMA01E                     0x0000020F
-#define DREG_REGID_RSDMA23E                     0x00000210
-#define DREG_REGID_RSD0_LOW                     0x00000211
-#define DREG_REGID_RSD0_HIGH                    0x00000212
-#define DREG_REGID_RSD1_LOW                     0x00000213
-#define DREG_REGID_RSD1_HIGH                    0x00000214
-#define DREG_REGID_RSD2_LOW                     0x00000215
-#define DREG_REGID_RSD2_HIGH                    0x00000216
-#define DREG_REGID_RSD3_LOW                     0x00000217
-#define DREG_REGID_RSD3_HIGH                    0x00000218
-#define DREG_REGID_SRAR_HIGH                    0x0000021A
-#define DREG_REGID_SRAR_LOW                     0x0000021B
-#define DREG_REGID_DMA_STATE                    0x0000021C
-#define DREG_REGID_CURRENT_DMA_STREAM           0x0000021D
-#define DREG_REGID_NEXT_DMA_STREAM              0x0000021E
-#define DREG_REGID_CPU_STATUS                   0x00000300
-#define DREG_REGID_MAC_MODE                     0x00000301
-#define DREG_REGID_STACK_AND_REPEAT             0x00000302
-#define DREG_REGID_INDEX0                       0x00000304
-#define DREG_REGID_INDEX1                       0x00000305
-#define DREG_REGID_DMA_STATE_0_3                0x00000400
-#define DREG_REGID_DMA_STATE_4_7                0x00000404
-#define DREG_REGID_DMA_STATE_8_11               0x00000408
-#define DREG_REGID_DMA_STATE_12_15              0x0000040C
-#define DREG_REGID_DMA_STATE_16_19              0x00000410
-#define DREG_REGID_DMA_STATE_20_23              0x00000414
-#define DREG_REGID_DMA_STATE_24_27              0x00000418
-#define DREG_REGID_DMA_STATE_28_31              0x0000041C
-#define DREG_REGID_DMA_STATE_32_35              0x00000420
-#define DREG_REGID_DMA_STATE_36_39              0x00000424
-#define DREG_REGID_DMA_STATE_40_43              0x00000428
-#define DREG_REGID_DMA_STATE_44_47              0x0000042C
-#define DREG_REGID_DMA_STATE_48_51              0x00000430
-#define DREG_REGID_DMA_STATE_52_55              0x00000434
-#define DREG_REGID_DMA_STATE_56_59              0x00000438
-#define DREG_REGID_DMA_STATE_60_63              0x0000043C
-#define DREG_REGID_DMA_STATE_64_67              0x00000440
-#define DREG_REGID_DMA_STATE_68_71              0x00000444
-#define DREG_REGID_DMA_STATE_72_75              0x00000448
-#define DREG_REGID_DMA_STATE_76_79              0x0000044C
-#define DREG_REGID_DMA_STATE_80_83              0x00000450
-#define DREG_REGID_DMA_STATE_84_87              0x00000454
-#define DREG_REGID_DMA_STATE_88_91              0x00000458
-#define DREG_REGID_DMA_STATE_92_95              0x0000045C
-#define DREG_REGID_TRAP_SELECT                  0x00000500
-#define DREG_REGID_TRAP_WRITE_0                 0x00000500
-#define DREG_REGID_TRAP_WRITE_1                 0x00000501
-#define DREG_REGID_TRAP_WRITE_2                 0x00000502
-#define DREG_REGID_TRAP_WRITE_3                 0x00000503
-#define DREG_REGID_TRAP_WRITE_4                 0x00000504
-#define DREG_REGID_TRAP_WRITE_5                 0x00000505
-#define DREG_REGID_TRAP_WRITE_6                 0x00000506
-#define DREG_REGID_TRAP_WRITE_7                 0x00000507
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_REGID_TRAP_WRITE_8                 0x00000510
-#define DREG_REGID_TRAP_WRITE_9                 0x00000511
-#define DREG_REGID_TRAP_WRITE_10                0x00000512
-#define DREG_REGID_TRAP_WRITE_11                0x00000513
-#define DREG_REGID_TRAP_WRITE_12                0x00000514
-#define DREG_REGID_TRAP_WRITE_13                0x00000515
-#define DREG_REGID_TRAP_WRITE_14                0x00000516
-#define DREG_REGID_TRAP_WRITE_15                0x00000517
-#define DREG_REGID_TRAP_WRITE_16                0x00000518
-#define DREG_REGID_TRAP_WRITE_17                0x00000519
-#define DREG_REGID_TRAP_WRITE_18                0x0000051A
-#define DREG_REGID_TRAP_WRITE_19                0x0000051B
-#define DREG_REGID_TRAP_WRITE_20                0x0000051C
-#define DREG_REGID_TRAP_WRITE_21                0x0000051D
-#define DREG_REGID_TRAP_WRITE_22                0x0000051E
-#define DREG_REGID_TRAP_WRITE_23                0x0000051F
-#endif
-#endif
-#define DREG_REGID_MAC0_ACC0_LOW                0x00000600
-#define DREG_REGID_MAC0_ACC1_LOW                0x00000601
-#define DREG_REGID_MAC0_ACC2_LOW                0x00000602
-#define DREG_REGID_MAC0_ACC3_LOW                0x00000603
-#define DREG_REGID_MAC1_ACC0_LOW                0x00000604
-#define DREG_REGID_MAC1_ACC1_LOW                0x00000605
-#define DREG_REGID_MAC1_ACC2_LOW                0x00000606
-#define DREG_REGID_MAC1_ACC3_LOW                0x00000607
-#define DREG_REGID_MAC0_ACC0_MID                0x00000608
-#define DREG_REGID_MAC0_ACC1_MID                0x00000609
-#define DREG_REGID_MAC0_ACC2_MID                0x0000060A
-#define DREG_REGID_MAC0_ACC3_MID                0x0000060B
-#define DREG_REGID_MAC1_ACC0_MID                0x0000060C
-#define DREG_REGID_MAC1_ACC1_MID                0x0000060D
-#define DREG_REGID_MAC1_ACC2_MID                0x0000060E
-#define DREG_REGID_MAC1_ACC3_MID                0x0000060F
-#define DREG_REGID_MAC0_ACC0_HIGH               0x00000610
-#define DREG_REGID_MAC0_ACC1_HIGH               0x00000611
-#define DREG_REGID_MAC0_ACC2_HIGH               0x00000612
-#define DREG_REGID_MAC0_ACC3_HIGH               0x00000613
-#define DREG_REGID_MAC1_ACC0_HIGH               0x00000614
-#define DREG_REGID_MAC1_ACC1_HIGH               0x00000615
-#define DREG_REGID_MAC1_ACC2_HIGH               0x00000616
-#define DREG_REGID_MAC1_ACC3_HIGH               0x00000617
-#define DREG_REGID_RSHOUT_LOW                   0x00000620
-#define DREG_REGID_RSHOUT_MID                   0x00000628
-#define DREG_REGID_RSHOUT_HIGH                  0x00000630
-
-/*
- *  The following defines are for the flags in the DMA stream requestor write
- */
-#define DSRWP_DSR_MASK                          0x0000000F
-#define DSRWP_DSR_BG_RQ                         0x00000001
-#define DSRWP_DSR_PRIORITY_MASK                 0x00000006
-#define DSRWP_DSR_PRIORITY_0                    0x00000000
-#define DSRWP_DSR_PRIORITY_1                    0x00000002
-#define DSRWP_DSR_PRIORITY_2                    0x00000004
-#define DSRWP_DSR_PRIORITY_3                    0x00000006
-#define DSRWP_DSR_RQ_PENDING                    0x00000008
-
-/*
- *  The following defines are for the flags in the trap write port register.
- */
-#define TWPR_TW_MASK                            0x0000FFFF
-#define TWPR_TW_SHIFT                           0
-
-/*
- *  The following defines are for the flags in the stack pointer write
- *  register.
- */
-#define SPWR_STKP_MASK                          0x0000000F
-#define SPWR_STKP_SHIFT                         0
-
-/*
- *  The following defines are for the flags in the SP interrupt register.
- */
-#define SPIR_FRI                                0x00000001
-#define SPIR_DOI                                0x00000002
-#define SPIR_GPI2                               0x00000004
-#define SPIR_GPI3                               0x00000008
-#define SPIR_IP0                                0x00000010
-#define SPIR_IP1                                0x00000020
-#define SPIR_IP2                                0x00000040
-#define SPIR_IP3                                0x00000080
-
-/*
- *  The following defines are for the flags in the functional group 1 register.
- */
-#define FGR1_F1S_MASK                           0x0000FFFF
-#define FGR1_F1S_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the SP clock status register.
- */
-#define SPCS_FRI                                0x00000001
-#define SPCS_DOI                                0x00000002
-#define SPCS_GPI2                               0x00000004
-#define SPCS_GPI3                               0x00000008
-#define SPCS_IP0                                0x00000010
-#define SPCS_IP1                                0x00000020
-#define SPCS_IP2                                0x00000040
-#define SPCS_IP3                                0x00000080
-#define SPCS_SPRUN                              0x00000100
-#define SPCS_SLEEP                              0x00000200
-#define SPCS_FG                                 0x00000400
-#define SPCS_ORUN                               0x00000800
-#define SPCS_IRQ                                0x00001000
-#define SPCS_FGN_MASK                           0x0000E000
-#define SPCS_FGN_SHIFT                          13
-
-/*
- *  The following defines are for the flags in the SP DMA requestor status
- *  register.
- */
-#define SDSR_DCS_MASK                           0x000000FF
-#define SDSR_DCS_SHIFT                          0
-#define SDSR_DCS_NONE                           0x00000007
-
-/*
- *  The following defines are for the flags in the frame timer register.
- */
-#define FRMT_FTV_MASK                           0x0000FFFF
-#define FRMT_FTV_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the frame timer current count
- *  register.
- */
-#define FRCC_FCC_MASK                           0x0000FFFF
-#define FRCC_FCC_SHIFT                          0
-
-/*
- *  The following defines are for the flags in the frame timer save count
- *  register.
- */
-#define FRSC_FCS_MASK                           0x0000FFFF
-#define FRSC_FCS_SHIFT                          0
-
-/*
- *  The following define the various flags stored in the scatter/gather
- *  descriptors.
- */
-#define DMA_SG_NEXT_ENTRY_MASK                  0x00000FF8
-#define DMA_SG_SAMPLE_END_MASK                  0x0FFF0000
-#define DMA_SG_SAMPLE_END_FLAG                  0x10000000
-#define DMA_SG_LOOP_END_FLAG                    0x20000000
-#define DMA_SG_SIGNAL_END_FLAG                  0x40000000
-#define DMA_SG_SIGNAL_PAGE_FLAG                 0x80000000
-#define DMA_SG_NEXT_ENTRY_SHIFT                 3
-#define DMA_SG_SAMPLE_END_SHIFT                 16
-
-/*
- *  The following define the offsets of the fields within the on-chip generic
- *  DMA requestor.
- */
-#define DMA_RQ_CONTROL1                         0x00000000
-#define DMA_RQ_CONTROL2                         0x00000004
-#define DMA_RQ_SOURCE_ADDR                      0x00000008
-#define DMA_RQ_DESTINATION_ADDR                 0x0000000C
-#define DMA_RQ_NEXT_PAGE_ADDR                   0x00000010
-#define DMA_RQ_NEXT_PAGE_SGDESC                 0x00000014
-#define DMA_RQ_LOOP_START_ADDR                  0x00000018
-#define DMA_RQ_POST_LOOP_ADDR                   0x0000001C
-#define DMA_RQ_PAGE_MAP_ADDR                    0x00000020
-
-/*
- *  The following defines are for the flags in the first control word of the
- *  on-chip generic DMA requestor.
- */
-#define DMA_RQ_C1_COUNT_MASK                    0x000003FF
-#define DMA_RQ_C1_DESTINATION_SCATTER           0x00001000
-#define DMA_RQ_C1_SOURCE_GATHER                 0x00002000
-#define DMA_RQ_C1_DONE_FLAG                     0x00004000
-#define DMA_RQ_C1_OPTIMIZE_STATE                0x00008000
-#define DMA_RQ_C1_SAMPLE_END_STATE_MASK         0x00030000
-#define DMA_RQ_C1_FULL_PAGE                     0x00000000
-#define DMA_RQ_C1_BEFORE_SAMPLE_END             0x00010000
-#define DMA_RQ_C1_PAGE_MAP_ERROR                0x00020000
-#define DMA_RQ_C1_AT_SAMPLE_END                 0x00030000
-#define DMA_RQ_C1_LOOP_END_STATE_MASK           0x000C0000
-#define DMA_RQ_C1_NOT_LOOP_END                  0x00000000
-#define DMA_RQ_C1_BEFORE_LOOP_END               0x00040000
-#define DMA_RQ_C1_2PAGE_LOOP_BEGIN              0x00080000
-#define DMA_RQ_C1_LOOP_BEGIN                    0x000C0000
-#define DMA_RQ_C1_PAGE_MAP_MASK                 0x00300000
-#define DMA_RQ_C1_PM_NONE_PENDING               0x00000000
-#define DMA_RQ_C1_PM_NEXT_PENDING               0x00100000
-#define DMA_RQ_C1_PM_RESERVED                   0x00200000
-#define DMA_RQ_C1_PM_LOOP_NEXT_PENDING          0x00300000
-#define DMA_RQ_C1_WRITEBACK_DEST_FLAG           0x00400000
-#define DMA_RQ_C1_WRITEBACK_SRC_FLAG            0x00800000
-#define DMA_RQ_C1_DEST_SIZE_MASK                0x07000000
-#define DMA_RQ_C1_DEST_LINEAR                   0x00000000
-#define DMA_RQ_C1_DEST_MOD16                    0x01000000
-#define DMA_RQ_C1_DEST_MOD32                    0x02000000
-#define DMA_RQ_C1_DEST_MOD64                    0x03000000
-#define DMA_RQ_C1_DEST_MOD128                   0x04000000
-#define DMA_RQ_C1_DEST_MOD256                   0x05000000
-#define DMA_RQ_C1_DEST_MOD512                   0x06000000
-#define DMA_RQ_C1_DEST_MOD1024                  0x07000000
-#define DMA_RQ_C1_DEST_ON_HOST                  0x08000000
-#define DMA_RQ_C1_SOURCE_SIZE_MASK              0x70000000
-#define DMA_RQ_C1_SOURCE_LINEAR                 0x00000000
-#define DMA_RQ_C1_SOURCE_MOD16                  0x10000000
-#define DMA_RQ_C1_SOURCE_MOD32                  0x20000000
-#define DMA_RQ_C1_SOURCE_MOD64                  0x30000000
-#define DMA_RQ_C1_SOURCE_MOD128                 0x40000000
-#define DMA_RQ_C1_SOURCE_MOD256                 0x50000000
-#define DMA_RQ_C1_SOURCE_MOD512                 0x60000000
-#define DMA_RQ_C1_SOURCE_MOD1024                0x70000000
-#define DMA_RQ_C1_SOURCE_ON_HOST                0x80000000
-#define DMA_RQ_C1_COUNT_SHIFT                   0
-
-/*
- *  The following defines are for the flags in the second control word of the
- *  on-chip generic DMA requestor.
- */
-#define DMA_RQ_C2_VIRTUAL_CHANNEL_MASK          0x0000003F
-#define DMA_RQ_C2_VIRTUAL_SIGNAL_MASK           0x00000300
-#define DMA_RQ_C2_NO_VIRTUAL_SIGNAL             0x00000000
-#define DMA_RQ_C2_SIGNAL_EVERY_DMA              0x00000100
-#define DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG        0x00000200
-#define DMA_RQ_C2_SIGNAL_DEST_PINGPONG          0x00000300
-#define DMA_RQ_C2_AUDIO_CONVERT_MASK            0x0000F000
-#define DMA_RQ_C2_AC_NONE                       0x00000000
-#define DMA_RQ_C2_AC_8_TO_16_BIT                0x00001000
-#define DMA_RQ_C2_AC_MONO_TO_STEREO             0x00002000
-#define DMA_RQ_C2_AC_ENDIAN_CONVERT             0x00004000
-#define DMA_RQ_C2_AC_SIGNED_CONVERT             0x00008000
-#define DMA_RQ_C2_LOOP_END_MASK                 0x0FFF0000
-#define DMA_RQ_C2_LOOP_MASK                     0x30000000
-#define DMA_RQ_C2_NO_LOOP                       0x00000000
-#define DMA_RQ_C2_ONE_PAGE_LOOP                 0x10000000
-#define DMA_RQ_C2_TWO_PAGE_LOOP                 0x20000000
-#define DMA_RQ_C2_MULTI_PAGE_LOOP               0x30000000
-#define DMA_RQ_C2_SIGNAL_LOOP_BACK              0x40000000
-#define DMA_RQ_C2_SIGNAL_POST_BEGIN_PAGE        0x80000000
-#define DMA_RQ_C2_VIRTUAL_CHANNEL_SHIFT         0
-#define DMA_RQ_C2_LOOP_END_SHIFT                16
-
-/*
- *  The following defines are for the flags in the source and destination words
- *  of the on-chip generic DMA requestor.
- */
-#define DMA_RQ_SD_ADDRESS_MASK                  0x0000FFFF
-#define DMA_RQ_SD_MEMORY_ID_MASK                0x000F0000
-#define DMA_RQ_SD_SP_PARAM_ADDR                 0x00000000
-#define DMA_RQ_SD_SP_SAMPLE_ADDR                0x00010000
-#define DMA_RQ_SD_SP_PROGRAM_ADDR               0x00020000
-#define DMA_RQ_SD_SP_DEBUG_ADDR                 0x00030000
-#define DMA_RQ_SD_OMNIMEM_ADDR                  0x000E0000
-#define DMA_RQ_SD_END_FLAG                      0x40000000
-#define DMA_RQ_SD_ERROR_FLAG                    0x80000000
-#define DMA_RQ_SD_ADDRESS_SHIFT                 0
-
-/*
- *  The following defines are for the flags in the page map address word of the
- *  on-chip generic DMA requestor.
- */
-#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_MASK   0x00000FF8
-#define DMA_RQ_PMA_PAGE_TABLE_MASK              0xFFFFF000
-#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_SHIFT  3
-#define DMA_RQ_PMA_PAGE_TABLE_SHIFT             12
-
-#define BA1_VARIDEC_BUF_1       0x000
-
-#define BA1_PDTC                0x0c0    /* BA1_PLAY_DMA_TRANSACTION_COUNT_REG */
-#define BA1_PFIE                0x0c4    /* BA1_PLAY_FORMAT_&_INTERRUPT_ENABLE_REG */
-#define BA1_PBA                 0x0c8    /* BA1_PLAY_BUFFER_ADDRESS */
-#define BA1_PVOL                0x0f8    /* BA1_PLAY_VOLUME_REG */
-#define BA1_PSRC                0x288    /* BA1_PLAY_SAMPLE_RATE_CORRECTION_REG */
-#define BA1_PCTL                0x2a4    /* BA1_PLAY_CONTROL_REG */
-#define BA1_PPI                 0x2b4    /* BA1_PLAY_PHASE_INCREMENT_REG */
-
-#define BA1_CCTL                0x064    /* BA1_CAPTURE_CONTROL_REG */
-#define BA1_CIE                 0x104    /* BA1_CAPTURE_INTERRUPT_ENABLE_REG */
-#define BA1_CBA                 0x10c    /* BA1_CAPTURE_BUFFER_ADDRESS */
-#define BA1_CSRC                0x2c8    /* BA1_CAPTURE_SAMPLE_RATE_CORRECTION_REG */
-#define BA1_CCI                 0x2d8    /* BA1_CAPTURE_COEFFICIENT_INCREMENT_REG */
-#define BA1_CD                  0x2e0    /* BA1_CAPTURE_DELAY_REG */
-#define BA1_CPI                 0x2f4    /* BA1_CAPTURE_PHASE_INCREMENT_REG */
-#define BA1_CVOL                0x2f8    /* BA1_CAPTURE_VOLUME_REG */
-
-#define BA1_CFG1                0x134    /* BA1_CAPTURE_FRAME_GROUP_1_REG */
-#define BA1_CFG2                0x138    /* BA1_CAPTURE_FRAME_GROUP_2_REG */
-#define BA1_CCST                0x13c    /* BA1_CAPTURE_CONSTANT_REG */
-#define BA1_CSPB                0x340    /* BA1_CAPTURE_SPB_ADDRESS */
-
-/*
- *
- */
-
-#define CS461X_MODE_OUTPUT	(1<<0)	 /* MIDI UART - output */ 
-#define CS461X_MODE_INPUT	(1<<1)	 /* MIDI UART - input */
-
-//****************************************************************************
-//
-// The following define the offsets of the AC97 shadow registers, which appear
-// as a virtual extension to the base address register zero memory range.
-//
-//****************************************************************************
-#define AC97_REG_OFFSET_MASK                    0x0000007EL
-#define AC97_CODEC_NUMBER_MASK                  0x00003000L
-
-#define BA0_AC97_RESET                          0x00001000L
-#define BA0_AC97_MASTER_VOLUME                  0x00001002L
-#define BA0_AC97_HEADPHONE_VOLUME               0x00001004L
-#define BA0_AC97_MASTER_VOLUME_MONO             0x00001006L
-#define BA0_AC97_MASTER_TONE                    0x00001008L
-#define BA0_AC97_PC_BEEP_VOLUME                 0x0000100AL
-#define BA0_AC97_PHONE_VOLUME                   0x0000100CL
-#define BA0_AC97_MIC_VOLUME                     0x0000100EL
-#define BA0_AC97_LINE_IN_VOLUME                 0x00001010L
-#define BA0_AC97_CD_VOLUME                      0x00001012L
-#define BA0_AC97_VIDEO_VOLUME                   0x00001014L
-#define BA0_AC97_AUX_VOLUME                     0x00001016L
-#define BA0_AC97_PCM_OUT_VOLUME                 0x00001018L
-#define BA0_AC97_RECORD_SELECT                  0x0000101AL
-#define BA0_AC97_RECORD_GAIN                    0x0000101CL
-#define BA0_AC97_RECORD_GAIN_MIC                0x0000101EL
-#define BA0_AC97_GENERAL_PURPOSE                0x00001020L
-#define BA0_AC97_3D_CONTROL                     0x00001022L
-#define BA0_AC97_MODEM_RATE                     0x00001024L
-#define BA0_AC97_POWERDOWN                      0x00001026L
-#define BA0_AC97_EXT_AUDIO_ID                   0x00001028L
-#define BA0_AC97_EXT_AUDIO_POWER                0x0000102AL
-#define BA0_AC97_PCM_FRONT_DAC_RATE             0x0000102CL
-#define BA0_AC97_PCM_SURR_DAC_RATE              0x0000102EL
-#define BA0_AC97_PCM_LFE_DAC_RATE               0x00001030L
-#define BA0_AC97_PCM_LR_ADC_RATE                0x00001032L
-#define BA0_AC97_MIC_ADC_RATE                   0x00001034L
-#define BA0_AC97_6CH_VOL_C_LFE                  0x00001036L
-#define BA0_AC97_6CH_VOL_SURROUND               0x00001038L
-#define BA0_AC97_RESERVED_3A                    0x0000103AL
-#define BA0_AC97_EXT_MODEM_ID                   0x0000103CL
-#define BA0_AC97_EXT_MODEM_POWER                0x0000103EL
-#define BA0_AC97_LINE1_CODEC_RATE               0x00001040L
-#define BA0_AC97_LINE2_CODEC_RATE               0x00001042L
-#define BA0_AC97_HANDSET_CODEC_RATE             0x00001044L
-#define BA0_AC97_LINE1_CODEC_LEVEL              0x00001046L
-#define BA0_AC97_LINE2_CODEC_LEVEL              0x00001048L
-#define BA0_AC97_HANDSET_CODEC_LEVEL            0x0000104AL
-#define BA0_AC97_GPIO_PIN_CONFIG                0x0000104CL
-#define BA0_AC97_GPIO_PIN_TYPE                  0x0000104EL
-#define BA0_AC97_GPIO_PIN_STICKY                0x00001050L
-#define BA0_AC97_GPIO_PIN_WAKEUP                0x00001052L
-#define BA0_AC97_GPIO_PIN_STATUS                0x00001054L
-#define BA0_AC97_MISC_MODEM_AFE_STAT            0x00001056L
-#define BA0_AC97_RESERVED_58                    0x00001058L
-#define BA0_AC97_CRYSTAL_REV_N_FAB_ID           0x0000105AL
-#define BA0_AC97_TEST_AND_MISC_CTRL             0x0000105CL
-#define BA0_AC97_AC_MODE                        0x0000105EL
-#define BA0_AC97_MISC_CRYSTAL_CONTROL           0x00001060L
-#define BA0_AC97_LINE1_HYPRID_CTRL              0x00001062L
-#define BA0_AC97_VENDOR_RESERVED_64             0x00001064L
-#define BA0_AC97_VENDOR_RESERVED_66             0x00001066L
-#define BA0_AC97_SPDIF_CONTROL                  0x00001068L
-#define BA0_AC97_VENDOR_RESERVED_6A             0x0000106AL
-#define BA0_AC97_VENDOR_RESERVED_6C             0x0000106CL
-#define BA0_AC97_VENDOR_RESERVED_6E             0x0000106EL
-#define BA0_AC97_VENDOR_RESERVED_70             0x00001070L
-#define BA0_AC97_VENDOR_RESERVED_72             0x00001072L
-#define BA0_AC97_VENDOR_RESERVED_74             0x00001074L
-#define BA0_AC97_CAL_ADDRESS                    0x00001076L
-#define BA0_AC97_CAL_DATA                       0x00001078L
-#define BA0_AC97_VENDOR_RESERVED_7A             0x0000107AL
-#define BA0_AC97_VENDOR_ID1                     0x0000107CL
-#define BA0_AC97_VENDOR_ID2                     0x0000107EL
-#endif				/* __CS461X_H */
diff --git a/sound/oss/cs461x_image.h b/sound/oss/cs461x_image.h
deleted file mode 100644
index b5c5a46..0000000
--- a/sound/oss/cs461x_image.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/****************************************************************************
- * "CWCIMAGE.H"-- For CS46XX. Ver 1.04
- *      Copyright 1998-2001 (c) Cirrus Logic Corp.
- *      Version 1.04
- ****************************************************************************
- */
-#ifndef __CS_IMAGE_H
-#define __CS_IMAGE_H
-
-#define CLEAR__COUNT     3
-#define FILL__COUNT      4
-#define BA1__DWORD_SIZE  13*1024+512
-
-static struct
-{
-        unsigned BA1__DestByteOffset;
-        unsigned BA1__SourceSize;
-} ClrStat[CLEAR__COUNT] ={ {0x00000000, 0x00003000 },
-                           {0x00010000, 0x00003800 },
-                           {0x00020000, 0x00007000 } };
-
-static u32 FillArray1[]={
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00200040,0x00008010,0x00000000,
-0x00000000,0x80000001,0x00000001,0x00060000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00900080,0x00000173,0x00000000,
-0x00000000,0x00000010,0x00800000,0x00900000,
-0xf2c0000f,0x00000200,0x00000000,0x00010600,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x330300c2,
-0x06000000,0x00000000,0x80008000,0x80008000,
-0x3fc0000f,0x00000301,0x00010400,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00b00000,0x00d0806d,0x330480c3,
-0x04800000,0x00000001,0x00800001,0x0000ffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x066a0600,0x06350070,0x0000929d,0x929d929d,
-0x00000000,0x0000735a,0x00000600,0x00000000,
-0x929d735a,0x00000000,0x00010000,0x735a735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000804f,0x000000c3,
-0x05000000,0x00a00010,0x00000000,0x80008000,
-0x00000000,0x00000000,0x00000700,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000080,0x00a00000,0x0000809a,0x000000c2,
-0x07400000,0x00000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x000107a0,
-0x00c80028,0x000000c2,0x06800000,0x00000000,
-0x06e00080,0x00300000,0x000080bb,0x000000c9,
-0x07a00000,0x04000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x00000780,
-0x00c80028,0x000000c5,0xff800000,0x00000000,
-0x00640080,0x00c00000,0x00008197,0x000000c9,
-0x07800000,0x04000000,0x80008000,0xffffffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000805e,0x000000c1,
-0x00000000,0x00800000,0x80008000,0x80008000,
-0x00020000,0x0000ffff,0x00000000,0x00000000};
-
-static u32 FillArray2[]={
-0x929d0600,0x929d929d,0x929d929d,0x929d0000,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x00100635,0x060b013f,0x00000004,
-0x00000001,0x007a0002,0x00000000,0x066e0610,
-0x0105929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0xa431ac75,0x0001735a,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051,
-0x00000000,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x00000000,0x06400136,
-0x0000270f,0x00010000,0x007a0000,0x00000000,
-0x068e0645,0x0105929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0xa431ac75,0x0001735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x735a0100,0x00000000,0x00000000,0x00000000};
-
-static u32 FillArray3[]={
-0x00000000,0x00000000,0x00000000,0x00010004};
-
-static u32 FillArray4[]={
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00001705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00009705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00011705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00019705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00021705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00029705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00031705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00039705,0x00001400,0x000a411e,0x00001003,
-0x000fe19e,0x00001003,0x0009c730,0x00001003,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00009705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00011705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00019705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00021705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00029705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00031705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00039705,0x00001400,0x000a211e,0x00001003,
-0x0000a730,0x00001008,0x000e2730,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x00000000,0x00000000,0x000f619c,0x00001003,
-0x0007f801,0x000c0000,0x00000037,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0000373c,0x00001000,0x00000000,0x00000000,
-0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000273c,0x00001000,
-0x00000033,0x00001000,0x000e679e,0x00001003,
-0x00007705,0x00001400,0x000ac71e,0x00001003,
-0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000a730,0x00001003,
-0x00000033,0x00001000,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x000c0000,
-0x00000032,0x00001000,0x0000273d,0x00001000,
-0x0004a730,0x00001003,0x00000f41,0x00097140,
-0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-0x00002725,0x000aa400,0x00013705,0x00093a00,
-0x0000002e,0x0009d6c0,0x00038630,0x00001004,
-0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000,
-0x00000000,0x000c70e0,0x0007d182,0x0002c640,
-0x00000630,0x00001004,0x000799b8,0x0002c6c0,
-0x00031705,0x00092240,0x00039f05,0x000932c0,
-0x0003520a,0x00000000,0x00040731,0x0000100b,
-0x00010705,0x000b20c0,0x00000000,0x000eba44,
-0x00032108,0x000c60c4,0x00065208,0x000c2917,
-0x000406b0,0x00001007,0x00012f05,0x00036880,
-0x0002818e,0x000c0000,0x0004410a,0x00000000,
-0x00040630,0x00001007,0x00029705,0x000c0000,
-0x00000000,0x00000000,0x00003fc1,0x0003fc40,
-0x000037c1,0x00091b40,0x00003fc1,0x000911c0,
-0x000037c1,0x000957c0,0x00003fc1,0x000951c0,
-0x000037c1,0x00000000,0x00003fc1,0x000991c0,
-0x000037c1,0x00000000,0x00003fc1,0x0009d1c0,
-0x000037c1,0x00000000,0x0001ccc1,0x000915c0,
-0x0001c441,0x0009d800,0x0009cdc1,0x00091240,
-0x0001c541,0x00091d00,0x0009cfc1,0x00095240,
-0x0001c741,0x00095c80,0x000e8ca9,0x00099240,
-0x000e85ad,0x00095640,0x00069ca9,0x00099d80,
-0x000e952d,0x00099640,0x000eaca9,0x0009d6c0,
-0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80,
-0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0,
-0x000ec5ad,0x0009da40,0x000edca9,0x0009d300,
-0x000a6e0a,0x00001000,0x000ed52d,0x00091e40,
-0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40,
-0x0006fca9,0x00002500,0x000fb208,0x000c59a0,
-0x000ef52d,0x0009de40,0x00068ca9,0x000912c1,
-0x000683ad,0x00095241,0x00020f05,0x000991c1,
-0x00000000,0x00000000,0x00086f88,0x00001000,
-0x0009cf81,0x000b5340,0x0009c701,0x000b92c0,
-0x0009de81,0x000bd300,0x0009d601,0x000b1700,
-0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0,
-0x000a0f81,0x000bd740,0x00020701,0x000b5c80,
-0x000a1681,0x000b97c0,0x00021601,0x00002500,
-0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0,
-0x00021681,0x00002d00,0x00020f81,0x000bd800,
-0x000a0701,0x000b5bc0,0x00021601,0x00003500,
-0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0,
-0x00021681,0x00003d00,0x00020f81,0x000b1d00,
-0x000a0701,0x000b1fc0,0x00021601,0x00020500,
-0x00020f81,0x000b1341,0x000a0701,0x000b9fc0,
-0x00021681,0x00020d00,0x00020f81,0x000bde80,
-0x000a0701,0x000bdfc0,0x00021601,0x00021500,
-0x00020f81,0x000b9341,0x00020701,0x000b53c1,
-0x00021681,0x00021d00,0x000a0f81,0x000d0380,
-0x0000b601,0x000b15c0,0x00007b01,0x00000000,
-0x00007b81,0x000bd1c0,0x00007b01,0x00000000,
-0x00007b81,0x000b91c0,0x00007b01,0x000b57c0,
-0x00007b81,0x000b51c0,0x00007b01,0x000b1b40,
-0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0,
-0x0007e488,0x000d7e45,0x00000000,0x000d7a44,
-0x0007e48a,0x00000000,0x00011f05,0x00084080,
-0x00000000,0x00000000,0x00001705,0x000b3540,
-0x00008a01,0x000bf040,0x00007081,0x000bb5c0,
-0x00055488,0x00000000,0x0000d482,0x0003fc40,
-0x0003fc88,0x00000000,0x0001e401,0x000b3a00,
-0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784,
-0x000c86b0,0x00001007,0x00008281,0x000bb240,
-0x0000b801,0x000b7140,0x00007888,0x00000000,
-0x0000073c,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x00055288,0x000c555c,
-0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-0x0000fa88,0x00000000,0x00000032,0x00001000,
-0x0000073d,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x0008c01c,0x00001003,
-0x00002705,0x00001008,0x0008b201,0x000c1392,
-0x0000ba01,0x00000000,0x00008731,0x00001400,
-0x0004c108,0x000fe0c4,0x00057488,0x00000000,
-0x000a6388,0x00001001,0x0008b334,0x000bc141,
-0x0003020e,0x00000000,0x000886b0,0x00001008,
-0x00003625,0x000c5dfa,0x000a638a,0x00001001,
-0x0008020e,0x00001002,0x0008a6b0,0x00001008,
-0x0007f301,0x00000000,0x00000000,0x00000000,
-0x00002725,0x000a8c40,0x000000ae,0x00000000,
-0x000d8630,0x00001008,0x00000000,0x000c74e0,
-0x0007d182,0x0002d640,0x000a8630,0x00001008,
-0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5,
-0x0007420a,0x000c0000,0x00062208,0x000c4117,
-0x00070630,0x00001009,0x00000000,0x000c0000,
-0x0001022e,0x00000000,0x0003a630,0x00001009,
-0x00000000,0x000c0000,0x00000036,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x0002a730,0x00001008,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0002a730,0x00001008,
-0x00000033,0x00001000,0x0002a705,0x00001008,
-0x00007a01,0x000c0000,0x000e6288,0x000d550a,
-0x0006428a,0x00000000,0x00060730,0x0000100a,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0007aab0,0x00034880,0x00078fb0,0x0000100b,
-0x00057488,0x00000000,0x00033b94,0x00081140,
-0x000183ae,0x00000000,0x000786b0,0x0000100b,
-0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-0x00042731,0x00001003,0x0007aab0,0x00034880,
-0x00048fb0,0x0000100a,0x00057488,0x00000000,
-0x00033b94,0x00081140,0x000183ae,0x00000000,
-0x000806b0,0x0000100b,0x00022f05,0x00000000,
-0x00007401,0x00091140,0x00048f05,0x000951c0,
-0x00042731,0x00001003,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x000fe19e,0x00001003,0x00000000,0x00000000,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00000f41,0x00097140,0x0000a841,0x0009b240,
-0x0000a0c1,0x0009f040,0x0001c641,0x00093540,
-0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44,
-0x00055208,0x00000000,0x00010705,0x000a2880,
-0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5,
-0x0004ef0a,0x000c0000,0x00012f05,0x00036880,
-0x00065308,0x000c2997,0x000d86b0,0x0000100a,
-0x0004410a,0x000d40c7,0x00000000,0x00000000,
-0x00080730,0x00001004,0x00056f0a,0x000ea105,
-0x00000000,0x00000000,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x0000273d,0x00001000,0x00000000,0x000eba44,
-0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x00000000,0x000e5084,
-0x00000000,0x000eba44,0x00087401,0x000e4782,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x0007c108,0x000c0000,
-0x0007e721,0x000bed40,0x00005f25,0x000badc0,
-0x0003ba97,0x000beb80,0x00065590,0x000b2e00,
-0x00033217,0x00003ec0,0x00065590,0x000b8e40,
-0x0003ed80,0x000491c0,0x00073fb0,0x00074c80,
-0x000283a0,0x0000100c,0x000ee388,0x00042970,
-0x00008301,0x00021ef2,0x000b8f14,0x0000000f,
-0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6,
-0x000032ac,0x000c3916,0x0004edc2,0x00074c80,
-0x00078898,0x00001000,0x00038894,0x00000032,
-0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6,
-0x0004edc2,0x000c1956,0x0000722c,0x00034a00,
-0x00041705,0x0009ed40,0x00058730,0x00001400,
-0x000d7488,0x000c3a00,0x00048f05,0x00000000};
-
-static struct
-{   u32 Offset;
-    u32 Size;
-    u32 *pFill;
-} FillStat[FILL__COUNT] = {
-                            {0x00000000, sizeof(FillArray1), FillArray1},
-                            {0x00001800, sizeof(FillArray2), FillArray2},
-                            {0x000137f0, sizeof(FillArray3), FillArray3},
-                            {0x00020000, sizeof(FillArray4), FillArray4}
-                          };
-
-
-#endif
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
deleted file mode 100644
index 2a1f0d9..0000000
--- a/sound/oss/cs46xx.c
+++ /dev/null
@@ -1,5444 +0,0 @@
-/*
- *	Crystal SoundFusion CS46xx driver
- *
- *	Copyright 1998-2001 Cirrus Logic Corporation <pcaudio@crystal.cirrus.com>
- *						<twoller@crystal.cirrus.com>
- *	Copyright 1999-2000 Jaroslav Kysela <perex@suse.cz>
- *	Copyright 2000 Alan Cox <alan@redhat.com>
- *
- *	The core of this code is taken from the ALSA project driver by 
- *	Jaroslav. Please send Jaroslav the credit for the driver and 
- *	report bugs in this port to <alan@redhat.com>
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *	Current maintainers:
- *		Cirrus Logic Corporation, Thomas Woller (tw)
- *			<twoller@crystal.cirrus.com>
- *		Nils Faerber (nf)
- *			<nils@kernelconcepts.de>
- *		Thanks to David Pollard for testing.
- *
- *	Changes:
- *	20000909-nf	Changed cs_read, cs_write and drain_dac
- *	20001025-tw	Separate Playback/Capture structs and buffers.
- *			Added Scatter/Gather support for Playback.
- *			Added Capture.
- *	20001027-nf	Port to kernel 2.4.0-test9, some clean-ups
- *			Start of powermanagement support (CS46XX_PM).
- *	20001128-tw	Add module parm for default buffer order.
- *			added DMA_GFP flag to kmalloc dma buffer allocs.
- *			backfill silence to eliminate stuttering on
- *			underruns.
- *	20001201-tw	add resyncing of swptr on underruns.
- *	20001205-tw-nf	fixed GETOSPACE ioctl() after open()
- *	20010113-tw	patch from Hans Grobler general cleanup.
- *	20010117-tw	2.4.0 pci cleanup, wrapper code for 2.2.16-2.4.0
- *	20010118-tw	basic PM support for 2.2.16+ and 2.4.0/2.4.2.
- *	20010228-dh	patch from David Huggins - cs_update_ptr recursion.
- *	20010409-tw	add hercules game theatre XP amp code.
- *	20010420-tw	cleanup powerdown/up code.
- *	20010521-tw	eliminate pops, and fixes for powerdown.
- *	20010525-tw	added fixes for thinkpads with powerdown logic.
- *	20010723-sh     patch from Horms (Simon Horman) -
- *	                SOUND_PCM_READ_BITS returns bits as set in driver
- *	                rather than a logical or of the possible values.
- *	                Various ioctls handle the case where the device
- *	                is open for reading or writing but not both better.
- *
- *	Status:
- *	Playback/Capture supported from 8k-48k.
- *	16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported.
- *
- *	APM/PM - 2.2.x APM is enabled and functioning fine. APM can also
- *	be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
- *	definition.
- *
- *      Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
- *	so, use the drain/polarity to enable.  
- *	hercules_egpio_disable set to 1, will force a 0 to EGPIODR.
- *
- *	VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
- *	the external amplifier for the "back" speakers, since we do not
- *	support the secondary codec then this external amp is also not
- *	turned on.
- */
- 
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/ac97_codec.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#include "cs46xxpm.h"
-#include "cs46xx_wrapper-24.h"
-#include "cs461x.h"
-
-/* MIDI buffer sizes */
-#define CS_MIDIINBUF  500
-#define CS_MIDIOUTBUF 500
-
-#define ADC_RUNNING	1
-#define DAC_RUNNING	2
-
-#define CS_FMT_16BIT	1		/* These are fixed in fact */
-#define CS_FMT_STEREO	2
-#define CS_FMT_MASK	3
-
-#define CS_TYPE_ADC	1
-#define CS_TYPE_DAC	2
-
-#define CS_TRUE 	1
-#define CS_FALSE 	0
-
-#define CS_INC_USE_COUNT(m) (atomic_inc(m))
-#define CS_DEC_USE_COUNT(m) (atomic_dec(m))
-#define CS_DEC_AND_TEST(m) (atomic_dec_and_test(m))
-#define CS_IN_USE(m) (atomic_read(m) != 0)
-
-#define CS_DBGBREAKPOINT {__asm__("INT $3");}
-/*
- *	CS461x definitions
- */
- 
-#define CS461X_BA0_SIZE		0x2000
-#define CS461X_BA1_DATA0_SIZE	0x3000
-#define CS461X_BA1_DATA1_SIZE	0x3800
-#define CS461X_BA1_PRG_SIZE	0x7000
-#define CS461X_BA1_REG_SIZE	0x0100
-
-#define GOF_PER_SEC	200
-
-#define CSDEBUG_INTERFACE 1
-#define CSDEBUG 1
-/*
- * Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG
- *
- *
- * CSDEBUG is usual mode is set to 1, then use the
- * cs_debuglevel and cs_debugmask to turn on or off debugging.
- * Debug level of 1 has been defined to be kernel errors and info
- * that should be printed on any released driver.
- */
-#if CSDEBUG
-#define CS_DBGOUT(mask,level,x) if ((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;}
-#else
-#define CS_DBGOUT(mask,level,x) 
-#endif
-/*
- * cs_debugmask areas
- */
-#define CS_INIT	 	0x00000001		/* initialization and probe functions */
-#define CS_ERROR 	0x00000002		/* tmp debugging bit placeholder */
-#define CS_INTERRUPT	0x00000004		/* interrupt handler (separate from all other) */
-#define CS_FUNCTION 	0x00000008		/* enter/leave functions */
-#define CS_WAVE_WRITE 	0x00000010		/* write information for wave */
-#define CS_WAVE_READ 	0x00000020		/* read information for wave */
-#define CS_MIDI_WRITE 	0x00000040		/* write information for midi */
-#define CS_MIDI_READ 	0x00000080		/* read information for midi */
-#define CS_MPU401_WRITE 0x00000100		/* write information for mpu401 */
-#define CS_MPU401_READ 	0x00000200		/* read information for mpu401 */
-#define CS_OPEN		0x00000400		/* all open functions in the driver */
-#define CS_RELEASE	0x00000800		/* all release functions in the driver */
-#define CS_PARMS	0x00001000		/* functional and operational parameters */
-#define CS_IOCTL	0x00002000		/* ioctl (non-mixer) */
-#define CS_PM		0x00004000		/* PM */
-#define CS_TMP		0x10000000		/* tmp debug mask bit */
-
-#define CS_IOCTL_CMD_SUSPEND	0x1	// suspend
-#define CS_IOCTL_CMD_RESUME	0x2	// resume
-
-#if CSDEBUG
-static unsigned long cs_debuglevel = 1;			/* levels range from 1-9 */
-module_param(cs_debuglevel, ulong, 0644);
-static unsigned long cs_debugmask = CS_INIT | CS_ERROR;	/* use CS_DBGOUT with various mask values */
-module_param(cs_debugmask, ulong, 0644);
-#endif
-static unsigned long hercules_egpio_disable;  /* if non-zero set all EGPIO to 0 */
-module_param(hercules_egpio_disable, ulong, 0);
-static unsigned long initdelay = 700;  /* PM delay in millisecs */
-module_param(initdelay, ulong, 0);
-static unsigned long powerdown = -1;  /* turn on/off powerdown processing in driver */
-module_param(powerdown, ulong, 0);
-#define DMABUF_DEFAULTORDER 3
-static unsigned long defaultorder = DMABUF_DEFAULTORDER;
-module_param(defaultorder, ulong, 0);
-
-static int external_amp;
-module_param(external_amp, bool, 0);
-static int thinkpad;
-module_param(thinkpad, bool, 0);
-
-/*
-* set the powerdown module parm to 0 to disable all 
-* powerdown. also set thinkpad to 1 to disable powerdown, 
-* but also to enable the clkrun functionality.
-*/
-static unsigned cs_powerdown = 1;
-static unsigned cs_laptop_wait = 1;
-
-/* An instance of the 4610 channel */
-struct cs_channel 
-{
-	int used;
-	int num;
-	void *state;
-};
-
-#define CS46XX_MAJOR_VERSION "1"
-#define CS46XX_MINOR_VERSION "28"
-
-#ifdef __ia64__
-#define CS46XX_ARCH	     	"64"	//architecture key
-#else
-#define CS46XX_ARCH	     	"32"	//architecture key
-#endif
-
-static struct list_head cs46xx_devs = { &cs46xx_devs, &cs46xx_devs };
-
-/* magic numbers to protect our data structures */
-#define CS_CARD_MAGIC		0x43525553 /* "CRUS" */
-#define CS_STATE_MAGIC		0x4c4f4749 /* "LOGI" */
-#define NR_HW_CH		3
-
-/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
-#define NR_AC97		2
-
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-static const unsigned sample_shift[] = { 0, 1, 1, 2 };
-
-/* "software" or virtual channel, an instance of opened /dev/dsp */
-struct cs_state {
-	unsigned int magic;
-	struct cs_card *card;	/* Card info */
-
-	/* single open lock mechanism, only used for recording */
-	struct mutex open_mutex;
-	wait_queue_head_t open_wait;
-
-	/* file mode */
-	mode_t open_mode;
-
-	/* virtual channel number */
-	int virt;
-	
-	struct dmabuf {
-		/* wave sample stuff */
-		unsigned int rate;
-		unsigned char fmt, enable;
-
-		/* hardware channel */
-		struct cs_channel *channel;
-		int pringbuf;		/* Software ring slot */
-		void *pbuf;		/* 4K hardware DMA buffer */
-
-		/* OSS buffer management stuff */
-		void *rawbuf;
-		dma_addr_t dma_handle;
-		unsigned buforder;
-		unsigned numfrag;
-		unsigned fragshift;
-		unsigned divisor;
-		unsigned type;
-		void *tmpbuff;			/* tmp buffer for sample conversions */
-		dma_addr_t dmaaddr;
-		dma_addr_t dmaaddr_tmpbuff;
-		unsigned buforder_tmpbuff;	/* Log base 2 of size in bytes.. */
-
-		/* our buffer acts like a circular ring */
-		unsigned hwptr;		/* where dma last started, updated by update_ptr */
-		unsigned swptr;		/* where driver last clear/filled, updated by read/write */
-		int count;		/* bytes to be comsumed or been generated by dma machine */
-		unsigned total_bytes;	/* total bytes dmaed by hardware */
-		unsigned blocks;	/* total blocks */
-
-		unsigned error;		/* number of over/underruns */
-		unsigned underrun;	/* underrun pending before next write has occurred */
-		wait_queue_head_t wait;	/* put process on wait queue when no more space in buffer */
-
-		/* redundant, but makes calculations easier */
-		unsigned fragsize;
-		unsigned dmasize;
-		unsigned fragsamples;
-
-		/* OSS stuff */
-		unsigned mapped:1;
-		unsigned ready:1;
-		unsigned endcleared:1;
-		unsigned SGok:1;
-		unsigned update_flag;
-		unsigned ossfragshift;
-		int ossmaxfrags;
-		unsigned subdivision;
-	} dmabuf;
-	/* Guard against mmap/write/read races */
-	struct mutex sem;
-};
-
-struct cs_card {
-	struct cs_channel channel[2];
-	unsigned int magic;
-
-	/* We keep cs461x cards in a linked list */
-	struct cs_card *next;
-
-	/* The cs461x has a certain amount of cross channel interaction
-	   so we use a single per card lock */
-	spinlock_t lock;
-	
-	/* Keep AC97 sane */
-	spinlock_t ac97_lock;
-
-	/* mixer use count */
-	atomic_t mixer_use_cnt;
-
-	/* PCI device stuff */
-	struct pci_dev *pci_dev;
-	struct list_head list;
-
-	unsigned int pctl, cctl;	/* Hardware DMA flag sets */
-
-	/* soundcore stuff */
-	int dev_audio;
-	int dev_midi;
-
-	/* structures for abstraction of hardware facilities, codecs, banks and channels*/
-	struct ac97_codec *ac97_codec[NR_AC97];
-	struct cs_state *states[2];
-
-	u16 ac97_features;
-	
-	int amplifier;			/* Amplifier control */
-	void (*amplifier_ctrl)(struct cs_card *, int);
-	void (*amp_init)(struct cs_card *);
-	
-	int active;			/* Active clocking */
-	void (*active_ctrl)(struct cs_card *, int);
-	
-	/* hardware resources */
-	unsigned long ba0_addr;
-	unsigned long ba1_addr;
-	u32 irq;
-	
-	/* mappings */
-	void __iomem *ba0;
-	union
-	{
-		struct
-		{
-			u8 __iomem *data0;
-			u8 __iomem *data1;
-			u8 __iomem *pmem;
-			u8 __iomem *reg;
-		} name;
-		u8 __iomem *idx[4];
-	} ba1;
-	
-	/* Function support */
-	struct cs_channel *(*alloc_pcm_channel)(struct cs_card *);
-	struct cs_channel *(*alloc_rec_pcm_channel)(struct cs_card *);
-	void (*free_pcm_channel)(struct cs_card *, int chan);
-
-	/* /dev/midi stuff */
-	struct {
-		unsigned ird, iwr, icnt;
-		unsigned ord, owr, ocnt;
-		wait_queue_head_t open_wait;
-		wait_queue_head_t iwait;
-		wait_queue_head_t owait;
-		spinlock_t lock;
-		unsigned char ibuf[CS_MIDIINBUF];
-		unsigned char obuf[CS_MIDIOUTBUF];
-		mode_t open_mode;
-		struct mutex open_mutex;
-	} midi;
-	struct cs46xx_pm pm;
-};
-
-static int cs_open_mixdev(struct inode *inode, struct file *file);
-static int cs_release_mixdev(struct inode *inode, struct file *file);
-static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-			unsigned long arg);
-static int cs_hardware_init(struct cs_card *card);
-static int cs46xx_powerup(struct cs_card *card, unsigned int type);
-static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
-static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
-#ifdef CONFIG_PM
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
-static int cs46xx_resume_tbl(struct pci_dev *pcidev);
-#endif
-
-#if CSDEBUG
-
-/* DEBUG ROUTINES */
-
-#define SOUND_MIXER_CS_GETDBGLEVEL 	_SIOWR('M',120, int)
-#define SOUND_MIXER_CS_SETDBGLEVEL 	_SIOWR('M',121, int)
-#define SOUND_MIXER_CS_GETDBGMASK 	_SIOWR('M',122, int)
-#define SOUND_MIXER_CS_SETDBGMASK 	_SIOWR('M',123, int)
-#define SOUND_MIXER_CS_APM	 	_SIOWR('M',124, int)
-
-static void printioctl(unsigned int x)
-{
-    unsigned int i;
-    unsigned char vidx;
-	/* these values are incorrect for the ac97 driver, fix.
-         * Index of mixtable1[] member is Device ID 
-         * and must be <= SOUND_MIXER_NRDEVICES.
-         * Value of array member is index into s->mix.vol[]
-         */
-        static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
-                [SOUND_MIXER_PCM]     = 1,   /* voice */
-                [SOUND_MIXER_LINE1]   = 2,   /* AUX */
-                [SOUND_MIXER_CD]      = 3,   /* CD */
-                [SOUND_MIXER_LINE]    = 4,   /* Line */
-                [SOUND_MIXER_SYNTH]   = 5,   /* FM */
-                [SOUND_MIXER_MIC]     = 6,   /* Mic */
-                [SOUND_MIXER_SPEAKER] = 7,   /* Speaker */
-                [SOUND_MIXER_RECLEV]  = 8,   /* Recording level */
-                [SOUND_MIXER_VOLUME]  = 9    /* Master Volume */
-        };
-        
-    switch (x) {
-	case SOUND_MIXER_CS_GETDBGMASK:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGMASK: ") );
-		break;
-	case SOUND_MIXER_CS_GETDBGLEVEL:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGLEVEL: ") );
-		break;
-	case SOUND_MIXER_CS_SETDBGMASK:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGMASK: ") );
-		break;
-	case SOUND_MIXER_CS_SETDBGLEVEL:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGLEVEL: ") );
-		break;
-        case OSS_GETVERSION:
-		CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION: ") );
-		break;
-        case SNDCTL_DSP_SYNC:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC: ") );
-		break;
-        case SNDCTL_DSP_SETDUPLEX:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX: ") );
-		break;
-        case SNDCTL_DSP_GETCAPS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS: ") );
-		break;
-        case SNDCTL_DSP_RESET:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET: ") );
-		break;
-        case SNDCTL_DSP_SPEED:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED: ") );
-		break;
-        case SNDCTL_DSP_STEREO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO: ") );
-		break;
-        case SNDCTL_DSP_CHANNELS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS: ") );
-		break;
-        case SNDCTL_DSP_GETFMTS: 
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS: ") );
-		break;
-        case SNDCTL_DSP_SETFMT: 
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT: ") );
-		break;
-        case SNDCTL_DSP_POST:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST: ") );
-		break;
-        case SNDCTL_DSP_GETTRIGGER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER: ") );
-		break;
-        case SNDCTL_DSP_SETTRIGGER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER: ") );
-		break;
-        case SNDCTL_DSP_GETOSPACE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE: ") );
-		break;
-        case SNDCTL_DSP_GETISPACE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE: ") );
-		break;
-        case SNDCTL_DSP_NONBLOCK:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK: ") );
-		break;
-        case SNDCTL_DSP_GETODELAY:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY: ") );
-		break;
-        case SNDCTL_DSP_GETIPTR:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR: ") );
-		break;
-        case SNDCTL_DSP_GETOPTR:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR: ") );
-		break;
-        case SNDCTL_DSP_GETBLKSIZE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE: ") );
-		break;
-        case SNDCTL_DSP_SETFRAGMENT:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFRAGMENT: ") );
-		break;
-        case SNDCTL_DSP_SUBDIVIDE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE: ") );
-		break;
-        case SOUND_PCM_READ_RATE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE: ") );
-		break;
-        case SOUND_PCM_READ_CHANNELS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_CHANNELS: ") );
-		break;
-        case SOUND_PCM_READ_BITS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS: ") );
-		break;
-        case SOUND_PCM_WRITE_FILTER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_WRITE_FILTER: ") );
-		break;
-        case SNDCTL_DSP_SETSYNCRO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO: ") );
-		break;
-        case SOUND_PCM_READ_FILTER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER: ") );
-		break;
-        case SOUND_MIXER_PRIVATE1:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1: ") );
-		break;
-        case SOUND_MIXER_PRIVATE2:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2: ") );
-		break;
-        case SOUND_MIXER_PRIVATE3:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3: ") );
-		break;
-        case SOUND_MIXER_PRIVATE4:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4: ") );
-		break;
-        case SOUND_MIXER_PRIVATE5:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5: ") );
-		break;
-        case SOUND_MIXER_INFO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO: ") );
-		break;
-        case SOUND_OLD_MIXER_INFO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO: ") );
-		break;
-	default:
-		switch (_IOC_NR(x)) {
-			case SOUND_MIXER_VOLUME:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME: ") );
-				break;
-			case SOUND_MIXER_SPEAKER:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SPEAKER: ") );
-				break;
-			case SOUND_MIXER_RECLEV:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECLEV: ") );
-				break;
-			case SOUND_MIXER_MIC:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_MIC: ") );
-				break;
-			case SOUND_MIXER_SYNTH:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SYNTH: ") );
-				break;
-			case SOUND_MIXER_RECSRC: 
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECSRC: ") );
-				break;
-			case SOUND_MIXER_DEVMASK:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_DEVMASK: ") );
-				break;
-			case SOUND_MIXER_RECMASK:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECMASK: ") );
-				break;
-			case SOUND_MIXER_STEREODEVS: 
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_STEREODEVS: ") );
-				break;
-			case SOUND_MIXER_CAPS:
-				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:") );
-				break;
-			default:
-				i = _IOC_NR(x);
-				if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) {
-					CS_DBGOUT(CS_IOCTL, 4, printk("UNKNOWN IOCTL: 0x%.8x NR=%d ",x,i) );
-				} else {
-					CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d ",
-							x,i));
-				}
-				break;
-		}
-    }
-    CS_DBGOUT(CS_IOCTL, 4, printk("command = 0x%x IOC_NR=%d\n",x, _IOC_NR(x)) );
-}
-#endif
-
-/*
- *  common I/O routines
- */
-
-static void cs461x_poke(struct cs_card *codec, unsigned long reg, unsigned int val)
-{
-	writel(val, codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff));
-}
-
-static unsigned int cs461x_peek(struct cs_card *codec, unsigned long reg)
-{
-	return readl(codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff));
-}
-
-static void cs461x_pokeBA0(struct cs_card *codec, unsigned long reg, unsigned int val)
-{
-	writel(val, codec->ba0 + reg);
-}
-
-static unsigned int cs461x_peekBA0(struct cs_card *codec, unsigned long reg)
-{
-	return readl(codec->ba0 + reg);
-}
-
-
-static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg);
-static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 data);
-
-static struct cs_channel *cs_alloc_pcm_channel(struct cs_card *card)
-{
-	if (card->channel[1].used == 1)
-		return NULL;
-	card->channel[1].used = 1;
-	card->channel[1].num = 1;
-	return &card->channel[1];
-}
-
-static struct cs_channel *cs_alloc_rec_pcm_channel(struct cs_card *card)
-{
-	if (card->channel[0].used == 1)
-		return NULL;
-	card->channel[0].used = 1;
-	card->channel[0].num = 0;
-	return &card->channel[0];
-}
-
-static void cs_free_pcm_channel(struct cs_card *card, int channel)
-{
-	card->channel[channel].state = NULL;
-	card->channel[channel].used = 0;
-}
-
-/*
- * setup a divisor value to help with conversion from
- * 16bit Stereo, down to 8bit stereo/mono or 16bit mono.
- * assign a divisor of 1 if using 16bit Stereo as that is
- * the only format that the static image will capture.
- */
-static void cs_set_divisor(struct dmabuf *dmabuf)
-{
-	if (dmabuf->type == CS_TYPE_DAC)
-		dmabuf->divisor = 1;
-	else if (!(dmabuf->fmt & CS_FMT_STEREO) &&
-	    (dmabuf->fmt & CS_FMT_16BIT))
-		dmabuf->divisor = 2;
-	else if ((dmabuf->fmt & CS_FMT_STEREO) &&
-	    !(dmabuf->fmt & CS_FMT_16BIT))
-		dmabuf->divisor = 2;
-	else if (!(dmabuf->fmt & CS_FMT_STEREO) &&
-	    !(dmabuf->fmt & CS_FMT_16BIT))
-		dmabuf->divisor = 4;
-	else
-		dmabuf->divisor = 1;
-
-	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, printk(
-		"cs46xx: cs_set_divisor()- %s %d\n",
-			(dmabuf->type == CS_TYPE_ADC) ? "ADC" : "DAC", 
-			dmabuf->divisor) );
-}
-
-/*
-* mute some of the more prevalent registers to avoid popping.
-*/
-static void cs_mute(struct cs_card *card, int state) 
-{
-	struct ac97_codec *dev = card->ac97_codec[0];
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()+ %s\n",
-		(state == CS_TRUE) ? "Muting" : "UnMuting"));
-
-	if (state == CS_TRUE) {
-	/*
-	* fix pops when powering up on thinkpads
-	*/
-		card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, 
-				(u8)BA0_AC97_MASTER_VOLUME); 
-		card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, 
-				(u8)BA0_AC97_HEADPHONE_VOLUME); 
-		card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, 
-				(u8)BA0_AC97_MASTER_VOLUME_MONO); 
-		card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, 
-				(u8)BA0_AC97_PCM_OUT_VOLUME);
-			
-		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000);
-		cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
-		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
-		cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
-	} else {
-		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, card->pm.u32AC97_master_volume);
-		cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, card->pm.u32AC97_headphone_volume);
-		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono);
-		cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume);
-	}
-	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()-\n"));
-}
-
-/* set playback sample rate */
-static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate)
-{	
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned int tmp1, tmp2;
-	unsigned int phiIncr;
-	unsigned int correctionPerGOF, correctionPerSec;
-	unsigned long flags;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()+ %d\n",rate) );
-
-	/*
-	 *  Compute the values used to drive the actual sample rate conversion.
-	 *  The following formulas are being computed, using inline assembly
-	 *  since we need to use 64 bit arithmetic to compute the values:
-	 *
-	 *  phiIncr = floor((Fs,in * 2^26) / Fs,out)
-	 *  correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
-         *                                   GOF_PER_SEC)
-         *  ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
-         *                       GOF_PER_SEC * correctionPerGOF
-	 *
-	 *  i.e.
-	 *
-	 *  phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
-	 *  correctionPerGOF:correctionPerSec =
-	 *      dividend:remainder(ulOther / GOF_PER_SEC)
-	 */
-	tmp1 = rate << 16;
-	phiIncr = tmp1 / 48000;
-	tmp1 -= phiIncr * 48000;
-	tmp1 <<= 10;
-	phiIncr <<= 10;
-	tmp2 = tmp1 / 48000;
-	phiIncr += tmp2;
-	tmp1 -= tmp2 * 48000;
-	correctionPerGOF = tmp1 / GOF_PER_SEC;
-	tmp1 -= correctionPerGOF * GOF_PER_SEC;
-	correctionPerSec = tmp1;
-
-	/*
-	 *  Fill in the SampleRateConverter control block.
-	 */
-	spin_lock_irqsave(&state->card->lock, flags);
-	cs461x_poke(state->card, BA1_PSRC,
-	  ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
-	cs461x_poke(state->card, BA1_PPI, phiIncr);
-	spin_unlock_irqrestore(&state->card->lock, flags);
-	dmabuf->rate = rate;
-	
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()- %d\n",rate) );
-	return rate;
-}
-
-/* set recording sample rate */
-static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned int phiIncr, coeffIncr, tmp1, tmp2;
-	unsigned int correctionPerGOF, correctionPerSec, initialDelay;
-	unsigned int frameGroupLength, cnt;
-	unsigned long flags;
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()+ %d\n",rate) );
-
-	/*
-	 *  We can only decimate by up to a factor of 1/9th the hardware rate.
-	 *  Correct the value if an attempt is made to stray outside that limit.
-	 */
-	if ((rate * 9) < 48000)
-		rate = 48000 / 9;
-
-	/*
-	 *  We cannot capture at at rate greater than the Input Rate (48000).
-	 *  Return an error if an attempt is made to stray outside that limit.
-	 */
-	if (rate > 48000)
-		rate = 48000;
-
-	/*
-	 *  Compute the values used to drive the actual sample rate conversion.
-	 *  The following formulas are being computed, using inline assembly
-	 *  since we need to use 64 bit arithmetic to compute the values:
-	 *
-	 *     coeffIncr = -floor((Fs,out * 2^23) / Fs,in)
-	 *     phiIncr = floor((Fs,in * 2^26) / Fs,out)
-	 *     correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
-	 *                                GOF_PER_SEC)
-	 *     correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
-	 *                          GOF_PER_SEC * correctionPerGOF
-	 *     initialDelay = ceil((24 * Fs,in) / Fs,out)
-	 *
-	 * i.e.
-	 *
-	 *     coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
-	 *     phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
-	 *     correctionPerGOF:correctionPerSec =
-	 * 	    dividend:remainder(ulOther / GOF_PER_SEC)
-	 *     initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
-	 */
-	tmp1 = rate << 16;
-	coeffIncr = tmp1 / 48000;
-	tmp1 -= coeffIncr * 48000;
-	tmp1 <<= 7;
-	coeffIncr <<= 7;
-	coeffIncr += tmp1 / 48000;
-	coeffIncr ^= 0xFFFFFFFF;
-	coeffIncr++;
-	tmp1 = 48000 << 16;
-	phiIncr = tmp1 / rate;
-	tmp1 -= phiIncr * rate;
-	tmp1 <<= 10;
-	phiIncr <<= 10;
-	tmp2 = tmp1 / rate;
-	phiIncr += tmp2;
-	tmp1 -= tmp2 * rate;
-	correctionPerGOF = tmp1 / GOF_PER_SEC;
-	tmp1 -= correctionPerGOF * GOF_PER_SEC;
-	correctionPerSec = tmp1;
-	initialDelay = ((48000 * 24) + rate - 1) / rate;
-
-	/*
-	 *  Fill in the VariDecimate control block.
-	 */
-	spin_lock_irqsave(&card->lock, flags);
-	cs461x_poke(card, BA1_CSRC,
-		((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
-	cs461x_poke(card, BA1_CCI, coeffIncr);
-	cs461x_poke(card, BA1_CD,
-		(((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
-	cs461x_poke(card, BA1_CPI, phiIncr);
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	/*
-	 *  Figure out the frame group length for the write back task.  Basically,
-	 *  this is just the factors of 24000 (2^6*3*5^3) that are not present in
-	 *  the output sample rate.
-	 */
-	frameGroupLength = 1;
-	for (cnt = 2; cnt <= 64; cnt *= 2) {
-		if (((rate / cnt) * cnt) != rate)
-			frameGroupLength *= 2;
-	}
-	if (((rate / 3) * 3) != rate) {
-		frameGroupLength *= 3;
-	}
-	for (cnt = 5; cnt <= 125; cnt *= 5) {
-		if (((rate / cnt) * cnt) != rate) 
-			frameGroupLength *= 5;
-        }
-
-	/*
-	 * Fill in the WriteBack control block.
-	 */
-	spin_lock_irqsave(&card->lock, flags);
-	cs461x_poke(card, BA1_CFG1, frameGroupLength);
-	cs461x_poke(card, BA1_CFG2, (0x00800000 | frameGroupLength));
-	cs461x_poke(card, BA1_CCST, 0x0000FFFF);
-	cs461x_poke(card, BA1_CSPB, ((65536 * rate) / 24000));
-	cs461x_poke(card, (BA1_CSPB + 4), 0x0000FFFF);
-	spin_unlock_irqrestore(&card->lock, flags);
-	dmabuf->rate = rate;
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()- %d\n",rate) );
-	return rate;
-}
-
-/* prepare channel attributes for playback */ 
-static void cs_play_setup(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-        unsigned int tmp, Count, playFormat;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") );
-        cs461x_poke(card, BA1_PVOL, 0x80008000);
-        if (!dmabuf->SGok)
-               cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf));
-    
-        Count = 4;                                                          
-        playFormat=cs461x_peek(card, BA1_PFIE);                             
-        if ((dmabuf->fmt & CS_FMT_STEREO)) {                                
-                playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO;                 
-                Count *= 2;                                                 
-        } else
-                playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO;                  
-                                                                            
-        if ((dmabuf->fmt & CS_FMT_16BIT)) {                                 
-                playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT                    
-                           | DMA_RQ_C2_AC_SIGNED_CONVERT);                  
-                Count *= 2;                                                 
-        } else
-                playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT                     
-                           | DMA_RQ_C2_AC_SIGNED_CONVERT);                  
-                                                                            
-        cs461x_poke(card, BA1_PFIE, playFormat);                            
-                                                                            
-        tmp = cs461x_peek(card, BA1_PDTC);                                  
-        tmp &= 0xfffffe00;                                                  
-        cs461x_poke(card, BA1_PDTC, tmp | --Count);                         
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") );
-}
-
-static struct InitStruct
-{
-    u32 off;
-    u32 val;
-} InitArray[] = { {0x00000040, 0x3fc0000f},
-                  {0x0000004c, 0x04800000},
-
-                  {0x000000b3, 0x00000780},
-                  {0x000000b7, 0x00000000},
-                  {0x000000bc, 0x07800000},
-
-                  {0x000000cd, 0x00800000},
-                };
-
-/*
- * "SetCaptureSPValues()" -- Initialize record task values before each
- * 	capture startup.  
- */
-static void SetCaptureSPValues(struct cs_card *card)
-{
-	unsigned i, offset;
-	CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") );
-	for (i = 0; i < sizeof(InitArray) / sizeof(struct InitStruct); i++) {
-		offset = InitArray[i].off*4; /* 8bit to 32bit offset value */
-		cs461x_poke(card, offset, InitArray[i].val );
-	}
-	CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()-\n") );
-}
-
-/* prepare channel attributes for recording */
-static void cs_rec_setup(struct cs_state *state)
-{
-	struct cs_card *card = state->card;
-	struct dmabuf *dmabuf = &state->dmabuf;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n"));
-	SetCaptureSPValues(card);
-
-	/*
-	 * set the attenuation to 0dB 
-	 */
-	cs461x_poke(card, BA1_CVOL, 0x80008000);
-
-	/*
-	 * set the physical address of the capture buffer into the SP
-	 */
-	cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->rawbuf));
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()-\n") );
-}
-
-
-/* get current playback/recording dma buffer pointer (byte offset from LBA),
-   called with spinlock held! */
-   
-static inline unsigned cs_get_dma_addr(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	u32 offset;
-	
-	if ( (!(dmabuf->enable & DAC_RUNNING)) &&
-	     (!(dmabuf->enable & ADC_RUNNING) ) )
-	{
-		CS_DBGOUT(CS_ERROR, 2, printk(
-			"cs46xx: ERROR cs_get_dma_addr(): not enabled \n") );
-		return 0;
-	}
-		
-	/*
-	 * granularity is byte boundary, good part.
-	 */
-	if (dmabuf->enable & DAC_RUNNING)
-		offset = cs461x_peek(state->card, BA1_PBA);                                  
-	else /* ADC_RUNNING must be set */
-		offset = cs461x_peek(state->card, BA1_CBA);                                  
-
-	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9, 
-		printk("cs46xx: cs_get_dma_addr() %d\n",offset) );
-	offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf;
-	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, 
-		printk("cs46xx: cs_get_dma_addr()- %d\n",offset) );
-	return offset;
-}
-
-static void resync_dma_ptrs(struct cs_state *state)
-{
-	struct dmabuf *dmabuf;
-	
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") );
-	if (state) {
-		dmabuf = &state->dmabuf;
-		dmabuf->hwptr=dmabuf->swptr = 0;
-		dmabuf->pringbuf = 0;
-	}
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") );
-}
-	
-/* Stop recording (lock held) */
-static inline void __stop_adc(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned int tmp;
-	
-	dmabuf->enable &= ~ADC_RUNNING;
-	
-	tmp = cs461x_peek(card, BA1_CCTL);
-	tmp &= 0xFFFF0000;
-	cs461x_poke(card, BA1_CCTL, tmp );
-}
-
-static void stop_adc(struct cs_state *state)
-{
-	unsigned long flags;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()+ \n") );
-	spin_lock_irqsave(&state->card->lock, flags);
-	__stop_adc(state);
-	spin_unlock_irqrestore(&state->card->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()- \n") );
-}
-
-static void start_adc(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned long flags;
-	unsigned int tmp;
-
-	spin_lock_irqsave(&card->lock, flags);
-	if (!(dmabuf->enable & ADC_RUNNING) && 
-	     ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) 
-	       && dmabuf->ready) && 
-	       ((card->pm.flags & CS46XX_PM_IDLE) || 
-	        (card->pm.flags & CS46XX_PM_RESUMED)) )
-	{
-		dmabuf->enable |= ADC_RUNNING;
-		cs_set_divisor(dmabuf);
-		tmp = cs461x_peek(card, BA1_CCTL);
-		tmp &= 0xFFFF0000;
-		tmp |= card->cctl;
-		CS_DBGOUT(CS_FUNCTION, 2, printk(
-			"cs46xx: start_adc() poke 0x%x \n",tmp) );
-		cs461x_poke(card, BA1_CCTL, tmp);
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* stop playback (lock held) */
-static inline void __stop_dac(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned int tmp;
-
-	dmabuf->enable &= ~DAC_RUNNING;
-	
-	tmp=cs461x_peek(card, BA1_PCTL);
-	tmp&=0xFFFF;
-	cs461x_poke(card, BA1_PCTL, tmp);
-}
-
-static void stop_dac(struct cs_state *state)
-{
-	unsigned long flags;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()+ \n") );
-	spin_lock_irqsave(&state->card->lock, flags);
-	__stop_dac(state);
-	spin_unlock_irqrestore(&state->card->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()- \n") );
-}	
-
-static void start_dac(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card = state->card;
-	unsigned long flags;
-	int tmp;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()+ \n") );
-	spin_lock_irqsave(&card->lock, flags);
-	if (!(dmabuf->enable & DAC_RUNNING) && 
-	    ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) &&
-	       ((card->pm.flags & CS46XX_PM_IDLE) || 
-	        (card->pm.flags & CS46XX_PM_RESUMED)) )
-	{
-		dmabuf->enable |= DAC_RUNNING;
-		tmp = cs461x_peek(card, BA1_PCTL);
-		tmp &= 0xFFFF;
-		tmp |= card->pctl;
-		CS_DBGOUT(CS_PARMS, 6, printk(
-		    "cs46xx: start_dac() poke card=%p tmp=0x%.08x addr=%p \n",
-		    card, (unsigned)tmp, 
-		    card->ba1.idx[(BA1_PCTL >> 16) & 3]+(BA1_PCTL&0xffff) ) );
-		cs461x_poke(card, BA1_PCTL, tmp);
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()- \n") );
-}
-
-#define DMABUF_MINORDER 1
-
-/*
- * allocate DMA buffer, playback and recording buffers are separate.
- */
-static int alloc_dmabuf(struct cs_state *state)
-{
-
-	struct cs_card *card=state->card;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	void *rawbuf = NULL;
-	void *tmpbuff = NULL;
-	int order;
-	struct page *map, *mapend;
-	unsigned long df;
-	
-	dmabuf->ready  = dmabuf->mapped = 0;
-	dmabuf->SGok = 0;
-/*
-* check for order within limits, but do not overwrite value.
-*/
-	if ((defaultorder > 1) && (defaultorder < 12))
-		df = defaultorder;
-	else
-		df = 2;	
-
-	for (order = df; order >= DMABUF_MINORDER; order--)
-		if ((rawbuf = (void *)pci_alloc_consistent(
-			card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr)))
-			    break;
-	if (!rawbuf) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-			"cs46xx: alloc_dmabuf(): unable to allocate rawbuf\n"));
-		return -ENOMEM;
-	}
-	dmabuf->buforder = order;
-	dmabuf->rawbuf = rawbuf;
-	// Now mark the pages as reserved; otherwise the 
-	// remap_pfn_range() in cs46xx_mmap doesn't work.
-	// 1. get index to last page in mem_map array for rawbuf.
-	mapend = virt_to_page(dmabuf->rawbuf + 
-		(PAGE_SIZE << dmabuf->buforder) - 1);
-
-	// 2. mark each physical page in range as 'reserved'.
-	for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
-		cs4x_mem_map_reserve(map);
-
-	CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: alloc_dmabuf(): allocated %ld (order = %d) bytes at %p\n",
-	       PAGE_SIZE << order, order, rawbuf) );
-
-/*
-*  only allocate the conversion buffer for the ADC
-*/
-	if (dmabuf->type == CS_TYPE_DAC) {
-		dmabuf->tmpbuff = NULL;
-		dmabuf->buforder_tmpbuff = 0;
-		return 0;
-	}
-/*
- * now the temp buffer for 16/8 conversions
- */
-
-	tmpbuff = (void *) pci_alloc_consistent(
-		card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr_tmpbuff);
-
-	if (!tmpbuff)
-		return -ENOMEM;
-	CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: allocated %ld (order = %d) bytes at %p\n",
-	       PAGE_SIZE << order, order, tmpbuff) );
-
-	dmabuf->tmpbuff = tmpbuff;
-	dmabuf->buforder_tmpbuff = order;
-	
-	// Now mark the pages as reserved; otherwise the 
-	// remap_pfn_range() in cs46xx_mmap doesn't work.
-	// 1. get index to last page in mem_map array for rawbuf.
-	mapend = virt_to_page(dmabuf->tmpbuff + 
-		(PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);
-
-	// 2. mark each physical page in range as 'reserved'.
-	for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)
-		cs4x_mem_map_reserve(map);
-	return 0;
-}
-
-/* free DMA buffer */
-static void dealloc_dmabuf(struct cs_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct page *map, *mapend;
-
-	if (dmabuf->rawbuf) {
-		// Undo prog_dmabuf()'s marking the pages as reserved 
-		mapend = virt_to_page(dmabuf->rawbuf + 
-				(PAGE_SIZE << dmabuf->buforder) - 1);
-		for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
-			cs4x_mem_map_unreserve(map);
-		free_dmabuf(state->card, dmabuf);
-	}
-
-	if (dmabuf->tmpbuff) {
-		// Undo prog_dmabuf()'s marking the pages as reserved 
-		mapend = virt_to_page(dmabuf->tmpbuff +
-				(PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);
-		for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)
-			cs4x_mem_map_unreserve(map);
-		free_dmabuf2(state->card, dmabuf);
-	}
-
-	dmabuf->rawbuf = NULL;
-	dmabuf->tmpbuff = NULL;
-	dmabuf->mapped = dmabuf->ready = 0;
-	dmabuf->SGok = 0;
-}
-
-static int __prog_dmabuf(struct cs_state *state)
-{
-        struct dmabuf *dmabuf = &state->dmabuf;
-        unsigned long flags;
-        unsigned long allocated_pages, allocated_bytes;                     
-        unsigned long tmp1, tmp2, fmt=0;                                           
-        unsigned long *ptmp = (unsigned long *) dmabuf->pbuf;               
-        unsigned long SGarray[9], nSGpages=0;                               
-        int ret;
-
-	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()+ \n"));
-/*
- * check for CAPTURE and use only non-sg for initial release
- */
-	if (dmabuf->type == CS_TYPE_ADC) {
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n"));
-		/* 
-		 * add in non-sg support for capture.
-		 */
-		spin_lock_irqsave(&state->card->lock, flags);
-	/* add code to reset the rawbuf memory. TRW */
-		resync_dma_ptrs(state);
-		dmabuf->total_bytes = dmabuf->blocks = 0;
-		dmabuf->count = dmabuf->error = dmabuf->underrun = 0;
-
-		dmabuf->SGok = 0;                                                   
-
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* allocate DMA buffer if not allocated yet */
-		if (!dmabuf->rawbuf || !dmabuf->tmpbuff)
-			if ((ret = alloc_dmabuf(state)))
-				return ret; 
-	/*
-	 * static image only supports 16Bit signed, stereo - hard code fmt
-	 */
-		fmt = CS_FMT_16BIT | CS_FMT_STEREO;
-
-		dmabuf->numfrag = 2;                                        
-		dmabuf->fragsize = 2048;                                    
-		dmabuf->fragsamples = 2048 >> sample_shift[fmt];    
-		dmabuf->dmasize = 4096;                                     
-		dmabuf->fragshift = 11;                                     
-
-		memset(dmabuf->rawbuf, (fmt & CS_FMT_16BIT) ? 0 : 0x80,
-		       dmabuf->dmasize);
-        	memset(dmabuf->tmpbuff, (fmt & CS_FMT_16BIT) ? 0 : 0x80, 
-			PAGE_SIZE<<dmabuf->buforder_tmpbuff);      
-
-		/*
-		 *      Now set up the ring
-		 */
-
-		spin_lock_irqsave(&state->card->lock, flags);
-		cs_rec_setup(state);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* set the ready flag for the dma buffer */
-		dmabuf->ready = 1;
-
-		CS_DBGOUT(CS_PARMS, 4, printk(
-			"cs46xx: prog_dmabuf(): CAPTURE rate=%d fmt=0x%x numfrag=%d "
-			"fragsize=%d dmasize=%d\n",
-			    dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
-			    dmabuf->fragsize, dmabuf->dmasize) );
-
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n"));
-		return 0;
-	} else if (dmabuf->type == CS_TYPE_DAC) {
-	/*
-	 * Must be DAC
-	 */
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() DAC\n"));
-		spin_lock_irqsave(&state->card->lock, flags);
-		resync_dma_ptrs(state);
-		dmabuf->total_bytes = dmabuf->blocks = 0;
-		dmabuf->count = dmabuf->error = dmabuf->underrun = 0;
-
-		dmabuf->SGok = 0;                                                   
-
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* allocate DMA buffer if not allocated yet */
-		if (!dmabuf->rawbuf)
-			if ((ret = alloc_dmabuf(state)))
-				return ret;
-
-		allocated_pages = 1 << dmabuf->buforder;                            
-		allocated_bytes = allocated_pages*PAGE_SIZE;                        
-										    
-		if (allocated_pages < 2) {
-			CS_DBGOUT(CS_FUNCTION, 4, printk(
-			    "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n",
-				(unsigned)allocated_pages));
-			return -ENOMEM;
-		}
-										    
-		/* Use all the pages allocated, fragsize 4k. */
-		/* Use 'pbuf' for S/G page map table. */
-		dmabuf->SGok = 1;           /* Use S/G. */
-
-		nSGpages = allocated_bytes/4096;    /* S/G pages always 4k. */
-										    
-		     /* Set up S/G variables. */
-		*ptmp = virt_to_bus(dmabuf->rawbuf);                                
-		*(ptmp + 1) = 0x00000008;
-		for (tmp1 = 1; tmp1 < nSGpages; tmp1++) {
-			*(ptmp + 2 * tmp1) = virt_to_bus((dmabuf->rawbuf) + 4096 * tmp1);
-			if (tmp1 == nSGpages - 1)
-				tmp2 = 0xbfff0000;
-			else                                                        
-				tmp2 = 0x80000000 + 8 * (tmp1 + 1);
-			*(ptmp + 2 * tmp1 + 1) = tmp2;
-		}                                                                   
-		SGarray[0] = 0x82c0200d;                                            
-		SGarray[1] = 0xffff0000;                                            
-		SGarray[2] = *ptmp;                                                 
-		SGarray[3] = 0x00010600;                                            
-		SGarray[4] = *(ptmp+2);                                             
-		SGarray[5] = 0x80000010;                                            
-		SGarray[6] = *ptmp;
-		SGarray[7] = *(ptmp+2);
-		SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10;
-
-		if (dmabuf->SGok) {
-			dmabuf->numfrag = nSGpages;
-			dmabuf->fragsize = 4096;
-			dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt];
-			dmabuf->fragshift = 12;
-			dmabuf->dmasize = dmabuf->numfrag * 4096;
-		} else {
-			SGarray[0] = 0xf2c0000f;                                    
-			SGarray[1] = 0x00000200;                                    
-			SGarray[2] = 0;                                             
-			SGarray[3] = 0x00010600;                                    
-			SGarray[4]=SGarray[5]=SGarray[6]=SGarray[7]=SGarray[8] = 0; 
-			dmabuf->numfrag = 2;                                        
-			dmabuf->fragsize = 2048;                                    
-			dmabuf->fragsamples = 2048 >> sample_shift[dmabuf->fmt];    
-			dmabuf->dmasize = 4096;                                     
-			dmabuf->fragshift = 11;                                     
-		}
-		for (tmp1 = 0; tmp1 < sizeof(SGarray) / 4; tmp1++)
-			cs461x_poke(state->card, BA1_PDTC+tmp1 * 4, SGarray[tmp1]);
-
-		memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
-		       dmabuf->dmasize);
-
-		/*
-		 *      Now set up the ring
-		 */
-
-		spin_lock_irqsave(&state->card->lock, flags);
-		cs_play_setup(state);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		/* set the ready flag for the dma buffer */
-		dmabuf->ready = 1;
-
-		CS_DBGOUT(CS_PARMS, 4, printk(
-			"cs46xx: prog_dmabuf(): PLAYBACK rate=%d fmt=0x%x numfrag=%d "
-			"fragsize=%d dmasize=%d\n",
-			    dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
-			    dmabuf->fragsize, dmabuf->dmasize) );
-
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n"));
-		return 0;
-	} else {
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n",
-			dmabuf->type));
-	}
-	return 1;
-}
-
-static int prog_dmabuf(struct cs_state *state)
-{
-	int ret;
-	
-	mutex_lock(&state->sem);
-	ret = __prog_dmabuf(state);
-	mutex_unlock(&state->sem);
-	
-	return ret;
-}
-
-static void cs_clear_tail(struct cs_state *state)
-{
-}
-
-static int drain_dac(struct cs_state *state, int nonblock)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct cs_card *card=state->card;
-	unsigned long flags;
-	unsigned long tmo;
-	int count;
-
-	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()+ \n"));
-	if (dmabuf->mapped || !dmabuf->ready)
-	{
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0, not ready\n"));
-		return 0;
-	}
-
-	add_wait_queue(&dmabuf->wait, &wait);
-	for (;;) {
-		/* It seems that we have to set the current state to TASK_INTERRUPTIBLE
-		   every time to make the process really go to sleep */
-		current->state = TASK_INTERRUPTIBLE;
-
-		spin_lock_irqsave(&state->card->lock, flags);
-		count = dmabuf->count;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (count <= 0)
-			break;
-
-		if (signal_pending(current))
-			break;
-
-		if (nonblock) {
-			remove_wait_queue(&dmabuf->wait, &wait);
-			current->state = TASK_RUNNING;
-			return -EBUSY;
-		}
-
-		tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
-		tmo >>= sample_shift[dmabuf->fmt];
-		tmo += (2048*HZ)/dmabuf->rate;
-		
-		if (!schedule_timeout(tmo ? tmo : 1) && tmo){
-			printk(KERN_ERR "cs46xx: drain_dac, dma timeout? %d\n", count);
-			break;
-		}
-	}
-	remove_wait_queue(&dmabuf->wait, &wait);
-	current->state = TASK_RUNNING;
-	if (signal_pending(current)) {
-		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- -ERESTARTSYS\n"));
-		/*
-		* set to silence and let that clear the fifos.
-		*/
-		cs461x_clear_serial_FIFOs(card, CS_TYPE_DAC);
-		return -ERESTARTSYS;
-	}
-
-	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0\n"));
-	return 0;
-}
-
-
-/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */
-static void cs_update_ptr(struct cs_card *card, int wake)
-{
-	struct cs_state *state;
-	struct dmabuf *dmabuf;
-	unsigned hwptr;
-	int diff;
-
-	/* error handling and process wake up for ADC */
-	state = card->states[0];
-	if (state) {
-		dmabuf = &state->dmabuf;
-		if (dmabuf->enable & ADC_RUNNING) {
-			/* update hardware pointer */
-			hwptr = cs_get_dma_addr(state);
-
-			diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-			CS_DBGOUT(CS_PARMS, 9, printk(
-				"cs46xx: cs_update_ptr()+ ADC hwptr=%d diff=%d\n", 
-				hwptr,diff) );
-			dmabuf->hwptr = hwptr;
-			dmabuf->total_bytes += diff;
-			dmabuf->count += diff;
-			if (dmabuf->count > dmabuf->dmasize)
-				dmabuf->count = dmabuf->dmasize;
-
-			if (dmabuf->mapped) {
-				if (wake && dmabuf->count >= (signed)dmabuf->fragsize)
-					wake_up(&dmabuf->wait);
-			} else {
-				if (wake && dmabuf->count > 0)
-					wake_up(&dmabuf->wait);
-			}
-		}
-	}
-
-/*
- * Now the DAC
- */
-	state = card->states[1];
-	if (state) {
-		dmabuf = &state->dmabuf;
-		/* error handling and process wake up for DAC */
-		if (dmabuf->enable & DAC_RUNNING) {
-			/* update hardware pointer */
-			hwptr = cs_get_dma_addr(state);
-
-			diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-			CS_DBGOUT(CS_PARMS, 9, printk(
-				"cs46xx: cs_update_ptr()+ DAC hwptr=%d diff=%d\n", 
-				hwptr,diff) );
-			dmabuf->hwptr = hwptr;
-			dmabuf->total_bytes += diff;
-			if (dmabuf->mapped) {
-				dmabuf->count += diff;
-				if (wake && dmabuf->count >= (signed)dmabuf->fragsize)
-					wake_up(&dmabuf->wait);
-				/*
-				 * other drivers use fragsize, but don't see any sense
-				 * in that, since dmasize is the buffer asked for
-				 * via mmap.
-				 */
-				if (dmabuf->count > dmabuf->dmasize)
-					dmabuf->count &= dmabuf->dmasize-1;
-			} else {
-				dmabuf->count -= diff;
-				/*
-				 * backfill with silence and clear out the last 
-				 * "diff" number of bytes.
-				 */
-				if (hwptr >= diff) {
-					memset(dmabuf->rawbuf + hwptr - diff, 
-						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff);
-				} else {
-					memset(dmabuf->rawbuf, 
-						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
-						(unsigned)hwptr);
-					memset((char *)dmabuf->rawbuf + 
-							dmabuf->dmasize + hwptr - diff,
-						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, 
-						diff - hwptr); 
-				}
-
-				if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
-					CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
-					  "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n",
-					  	dmabuf->count));
-					/* 
-					* buffer underrun or buffer overrun, reset the
-					* count of bytes written back to 0.
-					*/
-					if (dmabuf->count < 0)
-						dmabuf->underrun = 1;
-					dmabuf->count = 0;
-					dmabuf->error++;
-				}
-				if (wake && dmabuf->count < (signed)dmabuf->dmasize / 2)
-					wake_up(&dmabuf->wait);
-			}
-		}
-	}
-}
-
-
-/* hold spinlock for the following! */
-static void cs_handle_midi(struct cs_card *card)
-{
-        unsigned char ch;
-        int wake;
-        unsigned temp1;
-
-        wake = 0;
-        while (!(cs461x_peekBA0(card,  BA0_MIDSR) & MIDSR_RBE)) {
-                ch = cs461x_peekBA0(card, BA0_MIDRP);
-                if (card->midi.icnt < CS_MIDIINBUF) {
-                        card->midi.ibuf[card->midi.iwr] = ch;
-                        card->midi.iwr = (card->midi.iwr + 1) % CS_MIDIINBUF;
-                        card->midi.icnt++;
-                }
-                wake = 1;
-        }
-        if (wake)
-                wake_up(&card->midi.iwait);
-        wake = 0;
-        while (!(cs461x_peekBA0(card,  BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) {
-                temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff;
-                cs461x_pokeBA0(card, BA0_MIDWP,temp1);
-                card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF;
-                card->midi.ocnt--;
-                if (card->midi.ocnt < CS_MIDIOUTBUF-16)
-                        wake = 1;
-        }
-        if (wake)
-                wake_up(&card->midi.owait);
-}
-
-static irqreturn_t cs_interrupt(int irq, void *dev_id)
-{
-	struct cs_card *card = (struct cs_card *)dev_id;
-	/* Single channel card */
-	struct cs_state *recstate = card->channel[0].state;
-	struct cs_state *playstate = card->channel[1].state;
-	u32 status;
-
-	CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()+ \n"));
-
-	spin_lock(&card->lock);
-
-	status = cs461x_peekBA0(card, BA0_HISR);
-	
-	if ((status & 0x7fffffff) == 0) {
-		cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
-		spin_unlock(&card->lock);
-		return IRQ_HANDLED;	/* Might be IRQ_NONE.. */
-	}
-	
-	/*
-	 * check for playback or capture interrupt only
-	 */
-	if (((status & HISR_VC0) && playstate && playstate->dmabuf.ready) ||
-	    (((status & HISR_VC1) && recstate && recstate->dmabuf.ready))) {
-		CS_DBGOUT(CS_INTERRUPT, 8, printk(
-			"cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status));
-		cs_update_ptr(card, CS_TRUE);
-	}
-
-        if (status & HISR_MIDI)
-                cs_handle_midi(card);
-	
- 	/* clear 'em */
-	cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
-	spin_unlock(&card->lock);
-	CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()- \n"));
-	return IRQ_HANDLED;
-}
-
-
-/**********************************************************************/
-
-static ssize_t cs_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
-        struct cs_card *card = file->private_data;
-        ssize_t ret;
-        unsigned long flags;
-        unsigned ptr;
-        int cnt;
-
-        if (!access_ok(VERIFY_WRITE, buffer, count))
-                return -EFAULT;
-        ret = 0;
-        while (count > 0) {
-                spin_lock_irqsave(&card->lock, flags);
-                ptr = card->midi.ird;
-                cnt = CS_MIDIINBUF - ptr;
-                if (card->midi.icnt < cnt)
-                        cnt = card->midi.icnt;
-                spin_unlock_irqrestore(&card->lock, flags);
-                if (cnt > count)
-                        cnt = count;
-                if (cnt <= 0) {
-                        if (file->f_flags & O_NONBLOCK)
-                                return ret ? ret : -EAGAIN;
-                        interruptible_sleep_on(&card->midi.iwait);
-                        if (signal_pending(current))
-                                return ret ? ret : -ERESTARTSYS;
-                        continue;
-                }
-                if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt))
-                        return ret ? ret : -EFAULT;
-                ptr = (ptr + cnt) % CS_MIDIINBUF;
-                spin_lock_irqsave(&card->lock, flags);
-                card->midi.ird = ptr;
-                card->midi.icnt -= cnt;
-                spin_unlock_irqrestore(&card->lock, flags);
-                count -= cnt;
-                buffer += cnt;
-                ret += cnt;
-        }
-        return ret;
-}
-
-
-static ssize_t cs_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-        struct cs_card *card = file->private_data;
-        ssize_t ret;
-        unsigned long flags;
-        unsigned ptr;
-        int cnt;
-
-        if (!access_ok(VERIFY_READ, buffer, count))
-                return -EFAULT;
-        ret = 0;
-        while (count > 0) {
-                spin_lock_irqsave(&card->lock, flags);
-                ptr = card->midi.owr;
-                cnt = CS_MIDIOUTBUF - ptr;
-                if (card->midi.ocnt + cnt > CS_MIDIOUTBUF)
-                        cnt = CS_MIDIOUTBUF - card->midi.ocnt;
-                if (cnt <= 0)
-                        cs_handle_midi(card);
-                spin_unlock_irqrestore(&card->lock, flags);
-                if (cnt > count)
-                        cnt = count;
-                if (cnt <= 0) {
-                        if (file->f_flags & O_NONBLOCK)
-                                return ret ? ret : -EAGAIN;
-                        interruptible_sleep_on(&card->midi.owait);
-                        if (signal_pending(current))
-                                return ret ? ret : -ERESTARTSYS;
-                        continue;
-                }
-                if (copy_from_user(card->midi.obuf + ptr, buffer, cnt))
-                        return ret ? ret : -EFAULT;
-                ptr = (ptr + cnt) % CS_MIDIOUTBUF;
-                spin_lock_irqsave(&card->lock, flags);
-                card->midi.owr = ptr;
-                card->midi.ocnt += cnt;
-                spin_unlock_irqrestore(&card->lock, flags);
-                count -= cnt;
-                buffer += cnt;
-                ret += cnt;
-                spin_lock_irqsave(&card->lock, flags);
-                cs_handle_midi(card);
-                spin_unlock_irqrestore(&card->lock, flags);
-        }
-        return ret;
-}
-
-
-static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait)
-{
-        struct cs_card *card = file->private_data;
-        unsigned long flags;
-        unsigned int mask = 0;
-
-        if (file->f_flags & FMODE_WRITE)
-                poll_wait(file, &card->midi.owait, wait);
-        if (file->f_flags & FMODE_READ)
-                poll_wait(file, &card->midi.iwait, wait);
-        spin_lock_irqsave(&card->lock, flags);
-        if (file->f_flags & FMODE_READ) {
-                if (card->midi.icnt > 0)
-                        mask |= POLLIN | POLLRDNORM;
-        }
-        if (file->f_flags & FMODE_WRITE) {
-                if (card->midi.ocnt < CS_MIDIOUTBUF)
-                        mask |= POLLOUT | POLLWRNORM;
-        }
-        spin_unlock_irqrestore(&card->lock, flags);
-        return mask;
-}
-
-
-static int cs_midi_open(struct inode *inode, struct file *file)
-{
-        unsigned int minor = iminor(inode);
-        struct cs_card *card = NULL;
-        unsigned long flags;
-	struct list_head *entry;
-
-	list_for_each(entry, &cs46xx_devs) {
-		card = list_entry(entry, struct cs_card, list);
-		if (card->dev_midi == minor)
-			break;
-	}
-
-	if (entry == &cs46xx_devs)
-		return -ENODEV;
-	if (!card) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
-			"cs46xx: cs46xx_midi_open(): Error - unable to find card struct\n"));
-		return -ENODEV;
-	}
-
-        file->private_data = card;
-        /* wait for device to become free */
-        mutex_lock(&card->midi.open_mutex);
-        while (card->midi.open_mode & file->f_mode) {
-                if (file->f_flags & O_NONBLOCK) {
-                        mutex_unlock(&card->midi.open_mutex);
-                        return -EBUSY;
-                }
-                mutex_unlock(&card->midi.open_mutex);
-                interruptible_sleep_on(&card->midi.open_wait);
-                if (signal_pending(current))
-                        return -ERESTARTSYS;
-                mutex_lock(&card->midi.open_mutex);
-        }
-        spin_lock_irqsave(&card->midi.lock, flags);
-        if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) {
-                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
-                card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
-                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
-                cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f);            /* Enable xmit, rcv. */
-                cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM);   /* Enable interrupts */
-        }
-        if (file->f_mode & FMODE_READ)
-                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
-        if (file->f_mode & FMODE_WRITE)
-                card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
-        spin_unlock_irqrestore(&card->midi.lock, flags);
-        card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE));
-        mutex_unlock(&card->midi.open_mutex);
-        return 0;
-}
-
-
-static int cs_midi_release(struct inode *inode, struct file *file)
-{
-        struct cs_card *card = file->private_data;
-        DECLARE_WAITQUEUE(wait, current);
-        unsigned long flags;
-        unsigned count, tmo;
-
-        if (file->f_mode & FMODE_WRITE) {
-                current->state = TASK_INTERRUPTIBLE;
-                add_wait_queue(&card->midi.owait, &wait);
-                for (;;) {
-                        spin_lock_irqsave(&card->midi.lock, flags);
-                        count = card->midi.ocnt;
-                        spin_unlock_irqrestore(&card->midi.lock, flags);
-                        if (count <= 0)
-                                break;
-                        if (signal_pending(current))
-                                break;
-                        if (file->f_flags & O_NONBLOCK)
-                        	break;
-                        tmo = (count * HZ) / 3100;
-                        if (!schedule_timeout(tmo ? : 1) && tmo)
-                                printk(KERN_DEBUG "cs46xx: midi timed out??\n");
-                }
-                remove_wait_queue(&card->midi.owait, &wait);
-                current->state = TASK_RUNNING;
-        }
-        mutex_lock(&card->midi.open_mutex);
-        card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE)));
-        mutex_unlock(&card->midi.open_mutex);
-        wake_up(&card->midi.open_wait);
-        return 0;
-}
-
-/*
- *   Midi file operations struct.
- */
-static /*const*/ struct file_operations cs_midi_fops = {
-	CS_OWNER	CS_THIS_MODULE
-	.llseek		= no_llseek,
-	.read		= cs_midi_read,
-	.write		= cs_midi_write,
-	.poll		= cs_midi_poll,
-	.open		= cs_midi_open,
-	.release	= cs_midi_release,
-};
-
-/*
- *
- * CopySamples copies 16-bit stereo signed samples from the source to the
- * destination, possibly converting down to unsigned 8-bit and/or mono.
- * count specifies the number of output bytes to write.
- *
- *  Arguments:
- *
- *  dst             - Pointer to a destination buffer.
- *  src             - Pointer to a source buffer
- *  count           - The number of bytes to copy into the destination buffer.
- *  fmt             - CS_FMT_16BIT and/or CS_FMT_STEREO bits
- *  dmabuf          - pointer to the dma buffer structure
- *
- * NOTES: only call this routine if the output desired is not 16 Signed Stereo
- * 	
- *
- */
-static void CopySamples(char *dst, char *src, int count, unsigned fmt, 
-		struct dmabuf *dmabuf)
-{
-    s32 s32AudioSample;
-    s16 *psSrc = (s16 *)src;
-    s16 *psDst = (s16 *)dst;
-    u8 *pucDst = (u8 *)dst;
-
-    CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: CopySamples()+ ") );
-    CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
-	" dst=%p src=%p count=%d fmt=0x%x\n",
-	dst,src,count,fmt) );
-
-    /*
-     * See if the data should be output as 8-bit unsigned stereo.
-     */
-    if ((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) {
-        /*
-         * Convert each 16-bit signed stereo sample to 8-bit unsigned 
-	 * stereo using rounding.
-         */
-        psSrc = (s16 *)src;
-	count = count / 2;
-        while (count--)
-            *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8);
-    }
-    /*
-     * See if the data should be output at 8-bit unsigned mono.
-     */
-    else if (!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) {
-        /*
-         * Convert each 16-bit signed stereo sample to 8-bit unsigned 
-	 * mono using averaging and rounding.
-         */
-        psSrc = (s16 *)src;
-	count = count / 2;
-        while (count--) {
-	    s32AudioSample = ((*psSrc) + (*(psSrc + 1))) / 2 + (s32)0x80;
-	    if (s32AudioSample > 0x7fff)
-	    	s32AudioSample = 0x7fff;
-            *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8);
-	    psSrc += 2;
-        }
-    }
-    /*
-     * See if the data should be output at 16-bit signed mono.
-     */
-    else if (!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT)) {
-        /*
-         * Convert each 16-bit signed stereo sample to 16-bit signed 
-	 * mono using averaging.
-         */
-        psSrc = (s16 *)src;
-	count = count / 2;
-        while (count--) {
-            *(psDst++) = (s16)((*psSrc) + (*(psSrc + 1))) / 2;
-	    psSrc += 2;
-        }
-    }
-}
-
-/*
- * cs_copy_to_user()
- * replacement for the standard copy_to_user, to allow for a conversion from
- * 16 bit to 8 bit and from stereo to mono, if the record conversion is active.  
- * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo, 
- * so we convert from any of the other format combinations.
- */
-static unsigned cs_copy_to_user(
-	struct cs_state *s, 
-	void __user *dest, 
-	void *hwsrc, 
-	unsigned cnt, 
-	unsigned *copied)
-{
-	struct dmabuf *dmabuf = &s->dmabuf;
-	void *src = hwsrc;  /* default to the standard destination buffer addr */
-
-	CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO 
-		"cs_copy_to_user()+ fmt=0x%x cnt=%d dest=%p\n",
-		dmabuf->fmt,(unsigned)cnt,dest) );
-
-	if (cnt > dmabuf->dmasize)
-		cnt = dmabuf->dmasize;
-	if (!cnt) {
-		*copied = 0;
-		return 0;
-	}
-	if (dmabuf->divisor != 1) {
-		if (!dmabuf->tmpbuff) {
-			*copied = cnt / dmabuf->divisor;
-			return 0;
-		}
-
-		CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt, 
-			dmabuf->fmt, dmabuf);
-		src = dmabuf->tmpbuff;
-		cnt = cnt/dmabuf->divisor;
-	}
-        if (copy_to_user(dest, src, cnt)) {
-		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR 
-			"cs46xx: cs_copy_to_user()- fault dest=%p src=%p cnt=%d\n",
-				dest,src,cnt));
-		*copied = 0;
-		return -EFAULT;
-	}
-	*copied = cnt;
-	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO 
-		"cs46xx: cs_copy_to_user()- copied bytes is %d \n",cnt));
-	return 0;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to
-   the user's buffer.  it is filled by the dma machine and drained by this loop. */
-static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state;
-	DECLARE_WAITQUEUE(wait, current);
-	struct dmabuf *dmabuf;
-	ssize_t ret = 0;
-	unsigned long flags;
-	unsigned swptr;
-	int cnt;
-	unsigned copied = 0;
-
-	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-		printk("cs46xx: cs_read()+ %zd\n",count) );
-	state = card->states[0];
-	if (!state)
-		return -ENODEV;
-	dmabuf = &state->dmabuf;
-
-	if (dmabuf->mapped)
-		return -ENXIO;
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-	
-	mutex_lock(&state->sem);
-	if (!dmabuf->ready && (ret = __prog_dmabuf(state)))
-		goto out2;
-
-	add_wait_queue(&state->dmabuf.wait, &wait);
-	while (count > 0) {
-		while (!(card->pm.flags & CS46XX_PM_IDLE)) {
-			schedule();
-			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto out;
-			}
-		}
-		spin_lock_irqsave(&state->card->lock, flags);
-		swptr = dmabuf->swptr;
-		cnt = dmabuf->dmasize - swptr;
-		if (dmabuf->count < cnt)
-			cnt = dmabuf->count;
-		if (cnt <= 0)
-			__set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (cnt > (count * dmabuf->divisor))
-			cnt = count * dmabuf->divisor;
-		if (cnt <= 0) {
-			/* buffer is empty, start the dma machine and wait for data to be
-			   recorded */
-			start_adc(state);
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret)
-					ret = -EAGAIN;
-				goto out;
- 			}
-			mutex_unlock(&state->sem);
-			schedule();
-			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto out;
-			}
-			mutex_lock(&state->sem);
-			if (dmabuf->mapped) {
-				if (!ret)
-					ret = -ENXIO;
-				goto out;
-			}
- 			continue;
-		}
-
-		CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO 
-			"_read() copy_to cnt=%d count=%zd ", cnt,count) );
-		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO 
-			" .dmasize=%d .count=%d buffer=%p ret=%zd\n",
-			dmabuf->dmasize,dmabuf->count,buffer,ret));
-
-                if (cs_copy_to_user(state, buffer, 
-			(char *)dmabuf->rawbuf + swptr, cnt, &copied)) {
-			if (!ret)
-				ret = -EFAULT;
-			goto out;
-		}
-                swptr = (swptr + cnt) % dmabuf->dmasize;
-                spin_lock_irqsave(&card->lock, flags);
-                dmabuf->swptr = swptr;
-                dmabuf->count -= cnt;
-                spin_unlock_irqrestore(&card->lock, flags);
-                count -= copied;
-                buffer += copied;
-                ret += copied;
-                start_adc(state);
-	}
-out:
-	remove_wait_queue(&state->dmabuf.wait, &wait);
-out2:
-	mutex_unlock(&state->sem);
-	set_current_state(TASK_RUNNING);
-	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-		printk("cs46xx: cs_read()- %zd\n",ret) );
-	return ret;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to
-   the soundcard.  it is drained by the dma machine and filled by this loop. */
-static ssize_t cs_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state;
-	DECLARE_WAITQUEUE(wait, current);
-	struct dmabuf *dmabuf;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned swptr;
-	int cnt;
-
-	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,
-		printk("cs46xx: cs_write called, count = %zd\n", count) );
-	state = card->states[1];
-	if (!state)
-		return -ENODEV;
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-	dmabuf = &state->dmabuf;
-
-	mutex_lock(&state->sem);
-	if (dmabuf->mapped) {
-		ret = -ENXIO;
-		goto out;
-	}
-
-	if (!dmabuf->ready && (ret = __prog_dmabuf(state)))
-		goto out;
-	add_wait_queue(&state->dmabuf.wait, &wait);
-	ret = 0;
-/*
-* Start the loop to read from the user's buffer and write to the dma buffer.
-* check for PM events and underrun/overrun in the loop.
-*/
-	while (count > 0) {
-		while (!(card->pm.flags & CS46XX_PM_IDLE)) {
-			schedule();
-			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto out;
-			}
-		}
-		spin_lock_irqsave(&state->card->lock, flags);
-		if (dmabuf->count < 0) {
-			/* buffer underrun, we are recovering from sleep_on_timeout,
-			   resync hwptr and swptr */
-			dmabuf->count = 0;
-			dmabuf->swptr = dmabuf->hwptr;
-		}
-		if (dmabuf->underrun) {
-			dmabuf->underrun = 0;
-			dmabuf->hwptr = cs_get_dma_addr(state);
-			dmabuf->swptr = dmabuf->hwptr;
-		}
-
-		swptr = dmabuf->swptr;
-		cnt = dmabuf->dmasize - swptr;
-		if (dmabuf->count + cnt > dmabuf->dmasize)
-			cnt = dmabuf->dmasize - dmabuf->count;
-		if (cnt <= 0)
-			__set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			/* buffer is full, start the dma machine and wait for data to be
-			   played */
-			start_dac(state);
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret)
-					ret = -EAGAIN;
-				goto out;
- 			}
-			mutex_unlock(&state->sem);
-			schedule();
- 			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto out;
- 			}
-			mutex_lock(&state->sem);
-			if (dmabuf->mapped) {
-				if (!ret)
-					ret = -ENXIO;
-				goto out;
-			}
- 			continue;
- 		}
-		if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
-			if (!ret)
-				ret = -EFAULT;
-			goto out;
-		}
-		spin_lock_irqsave(&state->card->lock, flags);
-		swptr = (swptr + cnt) % dmabuf->dmasize;
-		dmabuf->swptr = swptr;
-		dmabuf->count += cnt;
-		if (dmabuf->count > dmabuf->dmasize) {
-			CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk(
-			    "cs46xx: cs_write() d->count > dmasize - resetting\n"));
-			dmabuf->count = dmabuf->dmasize;
-		}
-		dmabuf->endcleared = 0;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-		start_dac(state);
-	}
-out:
-	mutex_unlock(&state->sem);
-	remove_wait_queue(&state->dmabuf.wait, &wait);
-	set_current_state(TASK_RUNNING);
-
-	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, 
-		printk("cs46xx: cs_write()- ret=%zd\n", ret));
-	return ret;
-}
-
-static unsigned int cs_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct cs_card *card = file->private_data;
-	struct dmabuf *dmabuf;
-	struct cs_state *state;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()+ \n"));
-	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) {
-		return -EINVAL;
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			poll_wait(file, &dmabuf->wait, wait);
-		}
-	}
-	if (file->f_mode & FMODE_READ) {
-		state = card->states[0];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			poll_wait(file, &dmabuf->wait, wait);
-		}
-	}
-
-	spin_lock_irqsave(&card->lock, flags);
-	cs_update_ptr(card, CS_FALSE);
-	if (file->f_mode & FMODE_READ) {
-		state = card->states[0];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			if (dmabuf->count >= (signed)dmabuf->fragsize)
-				mask |= POLLIN | POLLRDNORM;
-		}
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			if (dmabuf->mapped) {
-				if (dmabuf->count >= (signed)dmabuf->fragsize)
-				    mask |= POLLOUT | POLLWRNORM;
-			} else {
-				if ((signed)dmabuf->dmasize >= dmabuf->count 
-					+ (signed)dmabuf->fragsize)
-				    mask |= POLLOUT | POLLWRNORM;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()- (0x%x) \n",
-		mask));
-	return mask;
-}
-
-/*
- *	We let users mmap the ring buffer. Its not the real DMA buffer but
- *	that side of the code is hidden in the IRQ handling. We do a software
- *	emulation of DMA from a 64K or so buffer into a 2K FIFO. 
- *	(the hardware probably deserves a moan here but Crystal send me nice
- *	toys ;)).
- */
- 
-static int cs_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state;
-	struct dmabuf *dmabuf;
-	int ret = 0;
-	unsigned long size;
-
-	CS_DBGOUT(CS_FUNCTION | CS_PARMS, 2, printk("cs46xx: cs_mmap()+ file=%p %s %s\n", 
-		file, vma->vm_flags & VM_WRITE ? "VM_WRITE" : "",
-		vma->vm_flags & VM_READ ? "VM_READ" : "") );
-
-	if (vma->vm_flags & VM_WRITE) {
-		state = card->states[1];
-		if (state) {
-			CS_DBGOUT(CS_OPEN, 2, printk(
-			  "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") );
-			if ((ret = prog_dmabuf(state)) != 0)
-				return ret;
-		}
-	} else if (vma->vm_flags & VM_READ) {
-		state = card->states[0];
-		if (state) {
-			CS_DBGOUT(CS_OPEN, 2, printk(
-			  "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") );
-			if ((ret = prog_dmabuf(state)) != 0)
-				return ret;
-		}
-	} else {
-		CS_DBGOUT(CS_ERROR, 2, printk(
-		  "cs46xx: cs_mmap() return -EINVAL\n") );
-		return -EINVAL;
-	}
-
-/*
- * For now ONLY support playback, but seems like the only way to use
- * mmap() is to open an FD with RDWR, just read or just write access
- * does not function, get an error back from the kernel.
- * Also, QuakeIII opens with RDWR!  So, there must be something
- * to needing read/write access mapping.  So, allow read/write but 
- * use the DAC only.
- */
-	state = card->states[1];  
-	if (!state) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	mutex_lock(&state->sem);
-	dmabuf = &state->dmabuf;
-	if (cs4x_pgoff(vma) != 0) {
-		ret = -EINVAL;
-		goto out;
-	}
-	size = vma->vm_end - vma->vm_start;
-
-	CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) );
-
-	if (size > (PAGE_SIZE << dmabuf->buforder)) {
-		ret = -EINVAL;
-		goto out;
-	}
-	if (remap_pfn_range(vma, vma->vm_start,
-			     virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
-			     size, vma->vm_page_prot)) {
-		ret = -EAGAIN;
-		goto out;
-	}
-	dmabuf->mapped = 1;
-
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") );
-out:
-	mutex_unlock(&state->sem);
-	return ret;	
-}
-
-static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state;
-	struct dmabuf *dmabuf = NULL;
-	unsigned long flags;
-	audio_buf_info abinfo;
-	count_info cinfo;
-	int val, valsave, ret;
-	int mapped = 0;
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-
-	state = card->states[0];
-	if (state) {
-		dmabuf = &state->dmabuf;
-		mapped = (file->f_mode & FMODE_READ) && dmabuf->mapped;
-	}
-	state = card->states[1];
-	if (state) {
-		dmabuf = &state->dmabuf;
-		mapped |= (file->f_mode & FMODE_WRITE) && dmabuf->mapped;
-	}
-		
-#if CSDEBUG
-	printioctl(cmd);
-#endif
-
-	switch (cmd) {
-	case OSS_GETVERSION:
-		return put_user(SOUND_VERSION, p);
-	case SNDCTL_DSP_RESET:
-		/* FIXME: spin_lock ? */
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				stop_dac(state);
-				synchronize_irq(card->irq);
-				dmabuf->ready = 0;
-				resync_dma_ptrs(state);
-				dmabuf->swptr = dmabuf->hwptr = 0;
-				dmabuf->count = dmabuf->total_bytes = 0;
-				dmabuf->blocks = 0;
-				dmabuf->SGok = 0;
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				stop_adc(state);
-				synchronize_irq(card->irq);
-				resync_dma_ptrs(state);
-				dmabuf->ready = 0;
-				dmabuf->swptr = dmabuf->hwptr = 0;
-				dmabuf->count = dmabuf->total_bytes = 0;
-				dmabuf->blocks = 0;
-				dmabuf->SGok = 0;
-			}
-		}
-		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_RESET()-\n") );
-		return 0;
-	case SNDCTL_DSP_SYNC:
-		if (file->f_mode & FMODE_WRITE)
-			return drain_dac(state, file->f_flags & O_NONBLOCK);
-		return 0;
-	case SNDCTL_DSP_SPEED: /* set sample rate */
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val >= 0) {
-			if (file->f_mode & FMODE_READ) {
-				state = card->states[0];
-				if (state) {
-					dmabuf = &state->dmabuf;
-					stop_adc(state);
-					dmabuf->ready = 0;
-					dmabuf->SGok = 0;
-					cs_set_adc_rate(state, val);
-					cs_set_divisor(dmabuf);
-				}
-			}
-			if (file->f_mode & FMODE_WRITE) {
-				state = card->states[1];
-				if (state) {
-					dmabuf = &state->dmabuf;
-					stop_dac(state);
-					dmabuf->ready = 0;
-					dmabuf->SGok = 0;
-					cs_set_dac_rate(state, val);
-					cs_set_divisor(dmabuf);
-				}
-			}
-			CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
-			    "cs46xx: cs_ioctl() DSP_SPEED %s %s %d\n",
-				file->f_mode & FMODE_WRITE ? "DAC" : "",
-				file->f_mode & FMODE_READ ? "ADC" : "",
-				dmabuf->rate ) );
-			return put_user(dmabuf->rate, p);
-		}
-		return put_user(0, p);
-	case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
-		if (get_user(val, p))
-			return -EFAULT;
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				stop_dac(state);
-				dmabuf->ready = 0;
-				dmabuf->SGok = 0;
-				if (val)
-					dmabuf->fmt |= CS_FMT_STEREO;
-				else
-					dmabuf->fmt &= ~CS_FMT_STEREO;
-				cs_set_divisor(dmabuf);
-				CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
-				    "cs46xx: DSP_STEREO() DAC %s\n",
-				    (dmabuf->fmt & CS_FMT_STEREO) ?
-					"STEREO":"MONO") );
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				stop_adc(state);
-				dmabuf->ready = 0;
-				dmabuf->SGok = 0;
-				if (val)
-					dmabuf->fmt |= CS_FMT_STEREO;
-				else
-					dmabuf->fmt &= ~CS_FMT_STEREO;
-				cs_set_divisor(dmabuf);
-				CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
-				    "cs46xx: DSP_STEREO() ADC %s\n",
-				    (dmabuf->fmt & CS_FMT_STEREO) ?
-					"STEREO":"MONO") );
-			}
-		}
-		return 0;
-	case SNDCTL_DSP_GETBLKSIZE:
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if ((val = prog_dmabuf(state)))
-					return val;
-				return put_user(dmabuf->fragsize, p);
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if ((val = prog_dmabuf(state)))
-					return val;
-				return put_user(dmabuf->fragsize/dmabuf->divisor, 
-						p);
-			}
-		}
-		return put_user(0, p);
-	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
-		return put_user(AFMT_S16_LE | AFMT_U8, p);
-	case SNDCTL_DSP_SETFMT: /* Select sample format */
-		if (get_user(val, p))
-			return -EFAULT;
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
-		    "cs46xx: cs_ioctl() DSP_SETFMT %s %s %s %s\n",
-			file->f_mode & FMODE_WRITE ? "DAC" : "",
-			file->f_mode & FMODE_READ ? "ADC" : "",
-			val == AFMT_S16_LE ? "16Bit Signed" : "",
-			val == AFMT_U8 ? "8Bit Unsigned" : "") );
-		valsave = val;
-		if (val != AFMT_QUERY) {
-			if (val==AFMT_S16_LE || val==AFMT_U8) {
-				if (file->f_mode & FMODE_WRITE) {
-					state = card->states[1];
-					if (state) {
-						dmabuf = &state->dmabuf;
-						stop_dac(state);
-						dmabuf->ready = 0;
-						dmabuf->SGok = 0;
-						if (val == AFMT_S16_LE)
-							dmabuf->fmt |= CS_FMT_16BIT;
-						else
-							dmabuf->fmt &= ~CS_FMT_16BIT;
-						cs_set_divisor(dmabuf);
-						if ((ret = prog_dmabuf(state)))
-							return ret;
-					}
-				}
-				if (file->f_mode & FMODE_READ) {
-					val = valsave;
-					state = card->states[0];
-					if (state) {
-						dmabuf = &state->dmabuf;
-						stop_adc(state);
-						dmabuf->ready = 0;
-						dmabuf->SGok = 0;
-						if (val == AFMT_S16_LE)
-							dmabuf->fmt |= CS_FMT_16BIT;
-						else
-							dmabuf->fmt &= ~CS_FMT_16BIT;
-						cs_set_divisor(dmabuf);
-						if ((ret = prog_dmabuf(state)))
-							return ret;
-					}
-				}
-			} else {
-				CS_DBGOUT(CS_IOCTL | CS_ERROR, 2, printk(
-				    "cs46xx: DSP_SETFMT() Unsupported format (0x%x)\n",
-					valsave) );
-			}
-		} else {
-			if (file->f_mode & FMODE_WRITE) {
-				state = card->states[1];
-				if (state)
-					dmabuf = &state->dmabuf;
-			} else if (file->f_mode & FMODE_READ) {
-				state = card->states[0];
-				if (state)
-					dmabuf = &state->dmabuf;
-			}
-		}
-		if (dmabuf) {
-			if (dmabuf->fmt & CS_FMT_16BIT)
-				return put_user(AFMT_S16_LE, p);
-			else
-				return put_user(AFMT_U8, p);
-		}
-		return put_user(0, p);
-	case SNDCTL_DSP_CHANNELS:
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val != 0) {
-			if (file->f_mode & FMODE_WRITE) {
-				state = card->states[1];
-				if (state) {
-					dmabuf = &state->dmabuf;
-					stop_dac(state);
-					dmabuf->ready = 0;
-					dmabuf->SGok = 0;
-					if (val > 1)
-						dmabuf->fmt |= CS_FMT_STEREO;
-					else
-						dmabuf->fmt &= ~CS_FMT_STEREO;
-					cs_set_divisor(dmabuf);
-					if (prog_dmabuf(state))
-						return 0;
-				}
-			}
-			if (file->f_mode & FMODE_READ) {
-				state = card->states[0];
-				if (state) {
-					dmabuf = &state->dmabuf;
-					stop_adc(state);
-					dmabuf->ready = 0;
-					dmabuf->SGok = 0;
-					if (val > 1)
-						dmabuf->fmt |= CS_FMT_STEREO;
-					else
-						dmabuf->fmt &= ~CS_FMT_STEREO;
-					cs_set_divisor(dmabuf);
-					if (prog_dmabuf(state))
-						return 0;
-				}
-			}
-		}
-		return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
-				p);
-	case SNDCTL_DSP_POST:
-		/*
-		 * There will be a longer than normal pause in the data.
-		 * so... do nothing, because there is nothing that we can do.
-		 */
-		return 0;
-	case SNDCTL_DSP_SUBDIVIDE:
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (dmabuf->subdivision)
-					return -EINVAL;
-				if (get_user(val, p))
-					return -EFAULT;
-				if (val != 1 && val != 2)
-					return -EINVAL;
-				dmabuf->subdivision = val;
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (dmabuf->subdivision)
-					return -EINVAL;
-				if (get_user(val, p))
-					return -EFAULT;
-				if (val != 1 && val != 2)
-					return -EINVAL;
-				dmabuf->subdivision = val;
-			}
-		}
-		return 0;
-	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, p))
-			return -EFAULT;
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				dmabuf->ossfragshift = val & 0xffff;
-				dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				dmabuf->ossfragshift = val & 0xffff;
-				dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
-			}
-		}
-		return 0;
-	case SNDCTL_DSP_GETOSPACE:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			abinfo.fragsize = dmabuf->fragsize;
-			abinfo.fragstotal = dmabuf->numfrag;
-		/*
-		 * for mmap we always have total space available
-		 */
-			if (dmabuf->mapped)
-				abinfo.bytes = dmabuf->dmasize;
-			else
-				abinfo.bytes = dmabuf->dmasize - dmabuf->count;
-
-			abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-			return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-		}
-		return -ENODEV;
-	case SNDCTL_DSP_GETISPACE:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		state = card->states[0];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			abinfo.fragsize = dmabuf->fragsize/dmabuf->divisor;
-			abinfo.bytes = dmabuf->count/dmabuf->divisor;
-			abinfo.fragstotal = dmabuf->numfrag;
-			abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-			return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-		}
-		return -ENODEV;
-	case SNDCTL_DSP_NONBLOCK:
-		file->f_flags |= O_NONBLOCK;
-		return 0;
-	case SNDCTL_DSP_GETCAPS:
-		return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP,
-			    p);
-	case SNDCTL_DSP_GETTRIGGER:
-		val = 0;
-		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()+\n") );
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (dmabuf->enable & DAC_RUNNING)
-					val |= PCM_ENABLE_INPUT;
-			}
-		}
-		if (file->f_mode & FMODE_READ) {
-			if (state) {
-				state = card->states[0];
-				dmabuf = &state->dmabuf;
-				if (dmabuf->enable & ADC_RUNNING)
-					val |= PCM_ENABLE_OUTPUT;
-			}
-		}
-		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()- val=0x%x\n",val) );
-		return put_user(val, p);
-	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, p))
-			return -EFAULT;
-		if (file->f_mode & FMODE_READ) {
-			state = card->states[0];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (val & PCM_ENABLE_INPUT) {
-					if (!dmabuf->ready && (ret = prog_dmabuf(state)))
-						return ret;
-					start_adc(state);
-				} else
-					stop_adc(state);
-			}
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			state = card->states[1];
-			if (state) {
-				dmabuf = &state->dmabuf;
-				if (val & PCM_ENABLE_OUTPUT) {
-					if (!dmabuf->ready && (ret = prog_dmabuf(state)))
-						return ret;
-					start_dac(state);
-				} else
-					stop_dac(state);
-			}
-		}
-		return 0;
-	case SNDCTL_DSP_GETIPTR:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		state = card->states[0];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			cinfo.bytes = dmabuf->total_bytes/dmabuf->divisor;
-			cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift;
-			cinfo.ptr = dmabuf->hwptr/dmabuf->divisor;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-			if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
-				return -EFAULT;
-			return 0;
-		}
-		return -ENODEV;
-	case SNDCTL_DSP_GETOPTR:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			cinfo.bytes = dmabuf->total_bytes;
-			if (dmabuf->mapped) {
-				cinfo.blocks = (cinfo.bytes >> dmabuf->fragshift) 
-							- dmabuf->blocks;
-				CS_DBGOUT(CS_PARMS, 8, 
-					printk("total_bytes=%d blocks=%d dmabuf->blocks=%d\n", 
-					cinfo.bytes,cinfo.blocks,dmabuf->blocks) );
-				dmabuf->blocks = cinfo.bytes >> dmabuf->fragshift;
-			} else {
-				cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
-			}
-			cinfo.ptr = dmabuf->hwptr;
-
-			CS_DBGOUT(CS_PARMS, 4, printk(
-			    "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n",
-				cinfo.bytes,cinfo.blocks,cinfo.ptr) );
-			spin_unlock_irqrestore(&state->card->lock, flags);
-			if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
-				return -EFAULT;
-			return 0;
-		}
-		return -ENODEV;
-	case SNDCTL_DSP_SETDUPLEX:
-		return 0;
-	case SNDCTL_DSP_GETODELAY:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			spin_lock_irqsave(&state->card->lock, flags);
-			cs_update_ptr(card, CS_TRUE);
-			val = dmabuf->count;
-			spin_unlock_irqrestore(&state->card->lock, flags);
-		} else
-			val = 0;
-		return put_user(val, p);
-	case SOUND_PCM_READ_RATE:
-		if (file->f_mode & FMODE_READ)
-			state = card->states[0];
-		else 
-			state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			return put_user(dmabuf->rate, p);
-		}
-		return put_user(0, p);
-	case SOUND_PCM_READ_CHANNELS:
-		if (file->f_mode & FMODE_READ)
-			state = card->states[0];
-		else 
-			state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
-				p);
-		}
-		return put_user(0, p);
-	case SOUND_PCM_READ_BITS:
-		if (file->f_mode & FMODE_READ)
-			state = card->states[0];
-		else 
-			state = card->states[1];
-		if (state) {
-			dmabuf = &state->dmabuf;
-			return put_user((dmabuf->fmt & CS_FMT_16BIT) ? 
-			  	AFMT_S16_LE : AFMT_U8, p);
-
-		}
-		return put_user(0, p);
-	case SNDCTL_DSP_MAPINBUF:
-	case SNDCTL_DSP_MAPOUTBUF:
-	case SNDCTL_DSP_SETSYNCRO:
-	case SOUND_PCM_WRITE_FILTER:
-	case SOUND_PCM_READ_FILTER:
-		return -EINVAL;
-	}
-	return -EINVAL;
-}
-
-
-/*
- *	AMP control - null AMP
- */
- 
-static void amp_none(struct cs_card *card, int change)
-{	
-}
-
-/*
- *	Crystal EAPD mode
- */
- 
-static void amp_voyetra(struct cs_card *card, int change)
-{
-	/* Manage the EAPD bit on the Crystal 4297 
-	   and the Analog AD1885 */
-	   
-	int old = card->amplifier;
-	
-	card->amplifier+=change;
-	if (card->amplifier && !old) {
-		/* Turn the EAPD amp on */
-		cs_ac97_set(card->ac97_codec[0],  AC97_POWER_CONTROL, 
-			cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) |
-				0x8000);
-	} else if(old && !card->amplifier) {
-		/* Turn the EAPD amp off */
-		cs_ac97_set(card->ac97_codec[0],  AC97_POWER_CONTROL, 
-			cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
-				~0x8000);
-	}
-}
-
-		       
-/*
- *	Game Theatre XP card - EGPIO[2] is used to enable the external amp.
- */
- 
-static void amp_hercules(struct cs_card *card, int change)
-{
-	int old = card->amplifier;
-	if (!card) {
-		CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO 
-			"cs46xx: amp_hercules() called before initialized.\n"));
-		return;
-	}
-	card->amplifier+=change;
-	if ((card->amplifier && !old) && !(hercules_egpio_disable)) {
-		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO 
-			"cs46xx: amp_hercules() external amp enabled\n"));
-		cs461x_pokeBA0(card, BA0_EGPIODR, 
-			EGPIODR_GPOE2);     /* enable EGPIO2 output */
-		cs461x_pokeBA0(card, BA0_EGPIOPTR, 
-			EGPIOPTR_GPPT2);   /* open-drain on output */
-	} else if (old && !card->amplifier) {
-		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO 
-			"cs46xx: amp_hercules() external amp disabled\n"));
-		cs461x_pokeBA0(card, BA0_EGPIODR, 0); /* disable */
-		cs461x_pokeBA0(card, BA0_EGPIOPTR, 0); /* disable */
-	}
-}
-
-/*
- *	Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
- *	whenever we need to beat on the chip.
- *
- *	The original idea and code for this hack comes from David Kaiser at
- *	Linuxcare. Perhaps one day Crystal will document their chips well
- *	enough to make them useful.
- */
- 
-static void clkrun_hack(struct cs_card *card, int change)
-{
-	struct pci_dev *acpi_dev;
-	u16 control;
-	u8 pp;
-	unsigned long port;
-	int old = card->active;
-	
-	card->active+=change;
-	
-	acpi_dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
-	if (acpi_dev == NULL)
-		return;		/* Not a thinkpad thats for sure */
-
-	/* Find the control port */		
-	pci_read_config_byte(acpi_dev, 0x41, &pp);
-	port = pp << 8;
-
-	/* Read ACPI port */	
-	control = inw(port + 0x10);
-
-	/* Flip CLKRUN off while running */
-	if (!card->active && old) {
-		CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
-			"cs46xx: clkrun() enable clkrun - change=%d active=%d\n",
-				change,card->active));
-		outw(control|0x2000, port+0x10);
-	} else {
-	/*
-	* sometimes on a resume the bit is set, so always reset the bit.
-	*/
-		CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
-			"cs46xx: clkrun() disable clkrun - change=%d active=%d\n",
-				change,card->active));
-		outw(control&~0x2000, port+0x10);
-	}
-	pci_dev_put(acpi_dev);
-}
-
-	
-static int cs_open(struct inode *inode, struct file *file)
-{
-	struct cs_card *card = file->private_data;
-	struct cs_state *state = NULL;
-	struct dmabuf *dmabuf = NULL;
-	struct list_head *entry;
-        unsigned int minor = iminor(inode);
-	int ret = 0;
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()+ file=%p %s %s\n",
-		file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
-		file->f_mode & FMODE_READ ? "FMODE_READ" : "") );
-
-	list_for_each(entry, &cs46xx_devs) {
-		card = list_entry(entry, struct cs_card, list);
-
-		if (!((card->dev_audio ^ minor) & ~0xf))
-			break;
-	}
-	if (entry == &cs46xx_devs)
-		return -ENODEV;
-	if (!card) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
-			"cs46xx: cs_open(): Error - unable to find audio card struct\n"));
-		return -ENODEV;
-	}
-
-	/*
-	 * hardcode state[0] for capture, [1] for playback
-	 */
-	if (file->f_mode & FMODE_READ) {
-		CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") );
-		if (card->states[0] == NULL) {
-			state = card->states[0] =
-				kzalloc(sizeof(struct cs_state), GFP_KERNEL);
-			if (state == NULL)
-				return -ENOMEM;
-			mutex_init(&state->sem);
-			dmabuf = &state->dmabuf;
-			dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-			if (dmabuf->pbuf == NULL) {
-				kfree(state);
-				card->states[0] = NULL;
-				return -ENOMEM;
-			}
-		} else {
-			state = card->states[0];
-			if (state->open_mode & FMODE_READ)
-				return -EBUSY;
-		}
-		dmabuf->channel = card->alloc_rec_pcm_channel(card);
-			
-		if (dmabuf->channel == NULL) {
-			kfree(card->states[0]);
-			card->states[0] = NULL;
-			return -ENODEV;
-		}
-
-		/* Now turn on external AMP if needed */
-		state->card = card;
-		state->card->active_ctrl(state->card, 1);
-		state->card->amplifier_ctrl(state->card, 1);
-		
-		if ((tmp = cs46xx_powerup(card, CS_POWER_ADC))) {
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs46xx_powerup of ADC failed (0x%x)\n", tmp));
-			return -EIO;
-		}
-
-		dmabuf->channel->state = state;
-		/* initialize the virtual channel */
-		state->virt = 0;
-		state->magic = CS_STATE_MAGIC;
-		init_waitqueue_head(&dmabuf->wait);
-		mutex_init(&state->open_mutex);
-		file->private_data = card;
-
-		mutex_lock(&state->open_mutex);
-
-		/* set default sample format. According to OSS Programmer's Guide  /dev/dsp
-		   should be default to unsigned 8-bits, mono, with sample rate 8kHz and
-		   /dev/dspW will accept 16-bits sample */
-
-		/* Default input is 8bit mono */
-		dmabuf->fmt &= ~CS_FMT_MASK;
-		dmabuf->type = CS_TYPE_ADC;
-		dmabuf->ossfragshift = 0;
-		dmabuf->ossmaxfrags  = 0;
-		dmabuf->subdivision  = 0;
-		cs_set_adc_rate(state, 8000);
-		cs_set_divisor(dmabuf);
-
-		state->open_mode |= FMODE_READ;
-		mutex_unlock(&state->open_mutex);
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") );
-		if (card->states[1] == NULL) {
-			state = card->states[1] =
-				kzalloc(sizeof(struct cs_state), GFP_KERNEL);
-			if (state == NULL)
-				return -ENOMEM;
-			mutex_init(&state->sem);
-			dmabuf = &state->dmabuf;
-			dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-			if (dmabuf->pbuf == NULL) {
-				kfree(state);
-				card->states[1] = NULL;
-				return -ENOMEM;
-			}
-		} else {
-			state = card->states[1];
-			if (state->open_mode & FMODE_WRITE)
-				return -EBUSY;
-		}
-		dmabuf->channel = card->alloc_pcm_channel(card);
-			
-		if (dmabuf->channel == NULL) {
-			kfree(card->states[1]);
-			card->states[1] = NULL;
-			return -ENODEV;
-		}
-
-		/* Now turn on external AMP if needed */
-		state->card = card;
-		state->card->active_ctrl(state->card, 1);
-		state->card->amplifier_ctrl(state->card, 1);
-
-		if ((tmp = cs46xx_powerup(card, CS_POWER_DAC))) {
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs46xx_powerup of DAC failed (0x%x)\n", tmp));
-			return -EIO;
-		}
-		
-		dmabuf->channel->state = state;
-		/* initialize the virtual channel */
-		state->virt = 1;
-		state->magic = CS_STATE_MAGIC;
-		init_waitqueue_head(&dmabuf->wait);
-		mutex_init(&state->open_mutex);
-		file->private_data = card;
-
-		mutex_lock(&state->open_mutex);
-
-		/* set default sample format. According to OSS Programmer's Guide  /dev/dsp
-		   should be default to unsigned 8-bits, mono, with sample rate 8kHz and
-		   /dev/dspW will accept 16-bits sample */
-
-		/* Default output is 8bit mono. */
-		dmabuf->fmt &= ~CS_FMT_MASK;
-		dmabuf->type = CS_TYPE_DAC;
-		dmabuf->ossfragshift = 0;
-		dmabuf->ossmaxfrags  = 0;
-		dmabuf->subdivision  = 0;
-		cs_set_dac_rate(state, 8000);
-		cs_set_divisor(dmabuf);
-
-		state->open_mode |= FMODE_WRITE;
-		mutex_unlock(&state->open_mutex);
-		if ((ret = prog_dmabuf(state)))
-			return ret;
-	}
-	CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n"));
-	return nonseekable_open(inode, file);
-}
-
-static int cs_release(struct inode *inode, struct file *file)
-{
-	struct cs_card *card = file->private_data;
-	struct dmabuf *dmabuf;
-	struct cs_state *state;
-	unsigned int tmp;
-	CS_DBGOUT(CS_RELEASE | CS_FUNCTION, 2, printk("cs46xx: cs_release()+ file=%p %s %s\n",
-		file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
-		file->f_mode & FMODE_READ ? "FMODE_READ" : ""));
-
-	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ)))
-		return -EINVAL;
-	state = card->states[1];
-	if (state) {
-		if ((state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE)) {
-			CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n"));
-			dmabuf = &state->dmabuf;
-			cs_clear_tail(state);
-			drain_dac(state, file->f_flags & O_NONBLOCK);
-			/* stop DMA state machine and free DMA buffers/channels */
-			mutex_lock(&state->open_mutex);
-			stop_dac(state);
-			dealloc_dmabuf(state);
-			state->card->free_pcm_channel(state->card, dmabuf->channel->num);
-			free_page((unsigned long)state->dmabuf.pbuf);
-
-			/* we're covered by the open_mutex */
-			mutex_unlock(&state->open_mutex);
-			state->card->states[state->virt] = NULL;
-			state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-
-			if ((tmp = cs461x_powerdown(card, CS_POWER_DAC, CS_FALSE))) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
-					"cs46xx: cs_release_mixdev() powerdown DAC failure (0x%x)\n",tmp) );
-			}
-
-			/* Now turn off external AMP if needed */
-			state->card->amplifier_ctrl(state->card, -1);
-			state->card->active_ctrl(state->card, -1);
-			kfree(state);
-		}
-	}
-
-	state = card->states[0];
-	if (state) {
-		if ((state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ)) {
-			CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n"));
-			dmabuf = &state->dmabuf;
-			mutex_lock(&state->open_mutex);
-			stop_adc(state);
-			dealloc_dmabuf(state);
-			state->card->free_pcm_channel(state->card, dmabuf->channel->num);
-			free_page((unsigned long)state->dmabuf.pbuf);
-
-			/* we're covered by the open_mutex */
-			mutex_unlock(&state->open_mutex);
-			state->card->states[state->virt] = NULL;
-			state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-
-			if ((tmp = cs461x_powerdown(card, CS_POWER_ADC, CS_FALSE))) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
-					"cs46xx: cs_release_mixdev() powerdown ADC failure (0x%x)\n",tmp) );
-			}
-
-			/* Now turn off external AMP if needed */
-			state->card->amplifier_ctrl(state->card, -1);
-			state->card->active_ctrl(state->card, -1);
-			kfree(state);
-		}
-	}
-
-	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n"));
-	return 0;
-}
-
-static void printpm(struct cs_card *s)
-{
-	CS_DBGOUT(CS_PM, 9, printk("pm struct:\n"));
-	CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n",
-		(unsigned)s->pm.flags,s->pm.u32CLKCR1_SAVE,s->pm.u32SSPMValue));
-	CS_DBGOUT(CS_PM, 9, printk("u32PPLVCvalue: 0x%x u32PPRVCvalue: 0x%x\n",
-		s->pm.u32PPLVCvalue,s->pm.u32PPRVCvalue));
-	CS_DBGOUT(CS_PM, 9, printk("u32FMLVCvalue: 0x%x u32FMRVCvalue: 0x%x\n",
-		s->pm.u32FMLVCvalue,s->pm.u32FMRVCvalue));
-	CS_DBGOUT(CS_PM, 9, printk("u32GPIORvalue: 0x%x u32JSCTLvalue: 0x%x\n",
-		s->pm.u32GPIORvalue,s->pm.u32JSCTLvalue));
-	CS_DBGOUT(CS_PM, 9, printk("u32SSCR: 0x%x u32SRCSA: 0x%x\n",
-		s->pm.u32SSCR,s->pm.u32SRCSA));
-	CS_DBGOUT(CS_PM, 9, printk("u32DacASR: 0x%x u32AdcASR: 0x%x\n",
-		s->pm.u32DacASR,s->pm.u32AdcASR));
-	CS_DBGOUT(CS_PM, 9, printk("u32DacSR: 0x%x u32AdcSR: 0x%x\n",
-		s->pm.u32DacSR,s->pm.u32AdcSR));
-	CS_DBGOUT(CS_PM, 9, printk("u32MIDCR_Save: 0x%x\n",
-		s->pm.u32MIDCR_Save));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_powerdown: 0x%x _general_purpose 0x%x\n",
-		s->pm.u32AC97_powerdown,s->pm.u32AC97_general_purpose));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume: 0x%x\n",
-		s->pm.u32AC97_master_volume));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_headphone_volume: 0x%x\n",
-		s->pm.u32AC97_headphone_volume));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume_mono: 0x%x\n",
-		s->pm.u32AC97_master_volume_mono));
-	CS_DBGOUT(CS_PM, 9, printk("u32AC97_pcm_out_volume: 0x%x\n",
-		s->pm.u32AC97_pcm_out_volume));
-	CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_play: 0x%x dmabuf_count_play: %d\n",
-		s->pm.dmabuf_swptr_play,s->pm.dmabuf_count_play));
-	CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_capture: 0x%x dmabuf_count_capture: %d\n",
-		s->pm.dmabuf_swptr_capture,s->pm.dmabuf_count_capture));
-
-}
-
-/****************************************************************************
-*
-*  Suspend - save the ac97 regs, mute the outputs and power down the part.  
-*
-****************************************************************************/
-static void cs46xx_ac97_suspend(struct cs_card *card)
-{
-	int Count,i;
-	struct ac97_codec *dev=card->ac97_codec[0];
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()+\n"));
-
-	if (card->states[1]) {
-		stop_dac(card->states[1]);
-		resync_dma_ptrs(card->states[1]);
-	}
-	if (card->states[0]) {
-		stop_adc(card->states[0]);
-		resync_dma_ptrs(card->states[0]);
-	}
-
-	for (Count = 0x2, i = 0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE)
-			&& (i < CS46XX_AC97_NUMBER_RESTORE_REGS);
-			Count += 2, i++) {
-		card->pm.ac97[i] = cs_ac97_get(dev, BA0_AC97_RESET + Count);
-	}
-/*
-* Save the ac97 volume registers as well as the current powerdown state.
-* Now, mute the all the outputs (master, headphone, and mono), as well
-* as the PCM volume, in preparation for powering down the entire part.
-	card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, 
-			(u8)BA0_AC97_MASTER_VOLUME); 
-	card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, 
-			(u8)BA0_AC97_HEADPHONE_VOLUME); 
-	card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, 
-			(u8)BA0_AC97_MASTER_VOLUME_MONO); 
-	card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, 
-			(u8)BA0_AC97_PCM_OUT_VOLUME);
-*/ 
-/*
-* mute the outputs
-*/
-	cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000);
-	cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
-	cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
-	cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
-
-/*
-* save the registers that cause pops
-*/
-	card->pm.u32AC97_powerdown = (u32)cs_ac97_get(dev, (u8)AC97_POWER_CONTROL); 
-	card->pm.u32AC97_general_purpose = (u32)cs_ac97_get(dev, (u8)BA0_AC97_GENERAL_PURPOSE); 
-/*
-* And power down everything on the AC97 codec.
-* well, for now, only power down the DAC/ADC and MIXER VREFON components. 
-* trouble with removing VREF.
-*/
-	if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-			CS_POWER_MIXVON, CS_TRUE))) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp));
-	}
-
-	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()-\n"));
-}
-
-/****************************************************************************
-*
-*  Resume - power up the part and restore its registers..  
-*
-****************************************************************************/
-static void cs46xx_ac97_resume(struct cs_card *card)
-{
-	int Count,i;
-	struct ac97_codec *dev=card->ac97_codec[0];
-
-	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()+\n"));
-
-/*
-* First, we restore the state of the general purpose register.  This
-* contains the mic select (mic1 or mic2) and if we restore this after
-* we restore the mic volume/boost state and mic2 was selected at
-* suspend time, we will end up with a brief period of time where mic1
-* is selected with the volume/boost settings for mic2, causing
-* acoustic feedback.  So we restore the general purpose register
-* first, thereby getting the correct mic selected before we restore
-* the mic volume/boost.
-*/
-	cs_ac97_set(dev, (u8)BA0_AC97_GENERAL_PURPOSE, 
-		(u16)card->pm.u32AC97_general_purpose);
-/*
-* Now, while the outputs are still muted, restore the state of power
-* on the AC97 part.
-*/
-	cs_ac97_set(dev, (u8)BA0_AC97_POWERDOWN, (u16)card->pm.u32AC97_powerdown);
-	mdelay(5 * cs_laptop_wait);
-/*
-* Restore just the first set of registers, from register number
-* 0x02 to the register number that ulHighestRegToRestore specifies.
-*/
-	for (Count = 0x2, i=0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE) &&
-			(i < CS46XX_AC97_NUMBER_RESTORE_REGS); Count += 2, i++) {
-		cs_ac97_set(dev, (u8)(BA0_AC97_RESET + Count), (u16)card->pm.ac97[i]);
-	}
-
-	/* Check if we have to init the amplifier */
-	if (card->amp_init)
-		card->amp_init(card);
-        
-	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()-\n"));
-}
-
-
-static int cs46xx_restart_part(struct cs_card *card)
-{
-	struct dmabuf *dmabuf;
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk( "cs46xx: cs46xx_restart_part()+\n"));
-	if (card->states[1]) {
-		dmabuf = &card->states[1]->dmabuf;
-		dmabuf->ready = 0;
-		resync_dma_ptrs(card->states[1]);
-		cs_set_divisor(dmabuf);
-		if (__prog_dmabuf(card->states[1])) {
-			CS_DBGOUT(CS_PM | CS_ERROR, 1, 
-				printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() dac error\n"));
-			return -1;
-		}
-		cs_set_dac_rate(card->states[1], dmabuf->rate);
-	}
-	if (card->states[0]) {
-		dmabuf = &card->states[0]->dmabuf;
-		dmabuf->ready = 0;
-		resync_dma_ptrs(card->states[0]);
-		cs_set_divisor(dmabuf);
-		if (__prog_dmabuf(card->states[0])) {
-			CS_DBGOUT(CS_PM | CS_ERROR, 1, 
-				printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() adc error\n"));
-			return -1;
-		}
-		cs_set_adc_rate(card->states[0], dmabuf->rate);
-	}
-	card->pm.flags |= CS46XX_PM_RESUMED;
-	if (card->states[0])
-		start_adc(card->states[0]);
-	if (card->states[1])
-		start_dac(card->states[1]);
-
-	card->pm.flags |= CS46XX_PM_IDLE;
-	card->pm.flags &= ~(CS46XX_PM_SUSPENDING | CS46XX_PM_SUSPENDED 
-			| CS46XX_PM_RESUMING | CS46XX_PM_RESUMED);
-	if (card->states[0])
-		wake_up(&card->states[0]->dmabuf.wait);
-	if (card->states[1])
-		wake_up(&card->states[1]->dmabuf.wait);
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk( "cs46xx: cs46xx_restart_part()-\n"));
-	return 0;
-}
-
-static void cs461x_reset(struct cs_card *card);
-static void cs461x_proc_stop(struct cs_card *card);
-static int cs46xx_suspend(struct cs_card *card, pm_message_t state)
-{
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk("cs46xx: cs46xx_suspend()+ flags=0x%x s=%p\n",
-			(unsigned)card->pm.flags,card));
-/*
-* check the current state, only suspend if IDLE
-*/
-	if (!(card->pm.flags & CS46XX_PM_IDLE)) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 2, 
-			printk("cs46xx: cs46xx_suspend() unable to suspend, not IDLE\n"));
-		return 1;
-	}
-	card->pm.flags &= ~CS46XX_PM_IDLE;
-	card->pm.flags |= CS46XX_PM_SUSPENDING;
-
-	card->active_ctrl(card,1);
-	
-	tmp = cs461x_peek(card, BA1_PFIE);
-	tmp &= ~0x0000f03f;
-	tmp |=  0x00000010;
-	cs461x_poke(card, BA1_PFIE, tmp);	/* playback interrupt disable */
-
-	tmp = cs461x_peek(card, BA1_CIE);
-	tmp &= ~0x0000003f;
-	tmp |=  0x00000011;
-	cs461x_poke(card, BA1_CIE, tmp);	/* capture interrupt disable */
-
-	/*
-         *  Stop playback DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_PCTL);
-	cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
-	/*
-         *  Stop capture DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_CCTL);
-	cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
-	if (card->states[1]) {
-		card->pm.dmabuf_swptr_play = card->states[1]->dmabuf.swptr;
-		card->pm.dmabuf_count_play = card->states[1]->dmabuf.count;
-	}
-	if (card->states[0]) {
-		card->pm.dmabuf_swptr_capture = card->states[0]->dmabuf.swptr;
-		card->pm.dmabuf_count_capture = card->states[0]->dmabuf.count;
-	}
-
-	cs46xx_ac97_suspend(card);
-
-	/*
-         *  Reset the processor.
-         */
-	cs461x_reset(card);
-
-	cs461x_proc_stop(card);
-
-	/*
-	 *  Power down the DAC and ADC.  For now leave the other areas on.
-	 */
-	cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, 0x0300);
-
-	/*
-	 *  Power down the PLL.
-	 */
-	cs461x_pokeBA0(card, BA0_CLKCR1, 0);
-
-	/*
-	 *  Turn off the Processor by turning off the software clock enable flag in 
-	 *  the clock control register.
-	 */
-	tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE;
-	cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
-	card->active_ctrl(card,-1);
-
-	card->pm.flags &= ~CS46XX_PM_SUSPENDING;
-	card->pm.flags |= CS46XX_PM_SUSPENDED;
-
-	printpm(card);
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk("cs46xx: cs46xx_suspend()- flags=0x%x\n",
-			(unsigned)card->pm.flags));
-	return 0;
-}
-
-static int cs46xx_resume(struct cs_card *card)
-{
-	int i;
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk( "cs46xx: cs46xx_resume()+ flags=0x%x\n",
-			(unsigned)card->pm.flags));
-	if (!(card->pm.flags & CS46XX_PM_SUSPENDED)) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 2, 
-			printk("cs46xx: cs46xx_resume() unable to resume, not SUSPENDED\n"));
-		return 1;
-	}
-	card->pm.flags |= CS46XX_PM_RESUMING;
-	card->pm.flags &= ~CS46XX_PM_SUSPENDED;
-	printpm(card);
-	card->active_ctrl(card, 1);
-
-	for (i = 0; i < 5; i++) {
-		if (cs_hardware_init(card) != 0) {
-			CS_DBGOUT(CS_PM | CS_ERROR, 4, printk(
-				"cs46xx: cs46xx_resume()- ERROR in cs_hardware_init()\n"));
-			mdelay(10 * cs_laptop_wait);
-			cs461x_reset(card);
-			continue;
-		}
-		break;
-	}
-	if (i >= 4) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 1, printk(
-			"cs46xx: cs46xx_resume()- cs_hardware_init() failed, retried %d times.\n",i));
-		return 0;
-	}
-
-	if (cs46xx_restart_part(card)) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 4, printk(
-			"cs46xx: cs46xx_resume(): cs46xx_restart_part() returned error\n"));
-	}
-
-	card->active_ctrl(card, -1);
-
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=0x%x\n",
-		(unsigned)card->pm.flags));
-	return 0;
-}
-
-static /*const*/ struct file_operations cs461x_fops = {
-	CS_OWNER	CS_THIS_MODULE
-	.llseek		= no_llseek,
-	.read		= cs_read,
-	.write		= cs_write,
-	.poll		= cs_poll,
-	.ioctl		= cs_ioctl,
-	.mmap		= cs_mmap,
-	.open		= cs_open,
-	.release	= cs_release,
-};
-
-/* Write AC97 codec registers */
-
-
-static u16 _cs_ac97_get(struct ac97_codec *dev, u8 reg)
-{
-	struct cs_card *card = dev->private_data;
-	int count,loopcnt;
-	unsigned int tmp;
-	u16 ret;
-	
-	/*
-	 *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
-	 *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97 
-	 *  3. Write ACCTL = Control Register = 460h for initiating the write
-	 *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
-	 *  5. if DCV not cleared, break and return error
-	 *  6. Read ACSTS = Status Register = 464h, check VSTS bit
-	 */
-
-	cs461x_peekBA0(card, BA0_ACSDA);
-
-	/*
-	 *  Setup the AC97 control registers on the CS461x to send the
-	 *  appropriate command to the AC97 to perform the read.
-	 *  ACCAD = Command Address Register = 46Ch
-	 *  ACCDA = Command Data Register = 470h
-	 *  ACCTL = Control Register = 460h
-	 *  set DCV - will clear when process completed
-	 *  set CRW - Read command
-	 *  set VFRM - valid frame enabled
-	 *  set ESYN - ASYNC generation enabled
-	 *  set RSTN - ARST# inactive, AC97 codec not reset
-	 */
-
-	cs461x_pokeBA0(card, BA0_ACCAD, reg);
-	cs461x_pokeBA0(card, BA0_ACCDA, 0);
-	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW |
-					     ACCTL_VFRM | ACCTL_ESYN |
-					     ACCTL_RSTN);
-
-
-	/*
-	 *  Wait for the read to occur.
-	 */
-	if (!(card->pm.flags & CS46XX_PM_IDLE))
-		loopcnt = 2000;
-	else
-		loopcnt = 500 * cs_laptop_wait;
- 	loopcnt *= cs_laptop_wait;
-	for (count = 0; count < loopcnt; count++) {
-		/*
-		 *  First, we want to wait for a short time.
-	 	 */
-		udelay(10 * cs_laptop_wait);
-		/*
-		 *  Now, check to see if the read has completed.
-		 *  ACCTL = 460h, DCV should be reset by now and 460h = 17h
-		 */
-		if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV))
-			break;
-	}
-
-	/*
-	 *  Make sure the read completed.
-	 */
-	if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-			"cs46xx: AC'97 read problem (ACCTL_DCV), reg = 0x%x returning 0xffff\n", reg));
-		return 0xffff;
-	}
-
-	/*
-	 *  Wait for the valid status bit to go active.
-	 */
-
-	if (!(card->pm.flags & CS46XX_PM_IDLE))
-		loopcnt = 2000;
-	else
-		loopcnt = 1000;
- 	loopcnt *= cs_laptop_wait;
-	for (count = 0; count < loopcnt; count++) {
-		/*
-		 *  Read the AC97 status register.
-		 *  ACSTS = Status Register = 464h
-		 *  VSTS - Valid Status
-		 */
-		if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_VSTS)
-			break;
-		udelay(10 * cs_laptop_wait);
-	}
-	
-	/*
-	 *  Make sure we got valid status.
-	 */
-	if (!((tmp = cs461x_peekBA0(card, BA0_ACSTS)) & ACSTS_VSTS)) {
-		CS_DBGOUT(CS_ERROR, 2, printk(KERN_WARNING 
-			"cs46xx: AC'97 read problem (ACSTS_VSTS), reg = 0x%x val=0x%x 0xffff \n", 
-				reg, tmp));
-		return 0xffff;
-	}
-
-	/*
-	 *  Read the data returned from the AC97 register.
-	 *  ACSDA = Status Data Register = 474h
-	 */
-	CS_DBGOUT(CS_FUNCTION, 9, printk(KERN_INFO
-		"cs46xx: cs_ac97_get() reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", 
-			reg, cs461x_peekBA0(card, BA0_ACSDA),
-			cs461x_peekBA0(card, BA0_ACCAD)));
-	ret = cs461x_peekBA0(card, BA0_ACSDA);
-	return ret;
-}
-
-static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg)
-{
-	u16 ret;
-	struct cs_card *card = dev->private_data;
-	
-	spin_lock(&card->ac97_lock);
-	ret = _cs_ac97_get(dev, reg);
-	spin_unlock(&card->ac97_lock);
-	return ret;
-}
-
-static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val)
-{
-	struct cs_card *card = dev->private_data;
-	int count;
-	int val2 = 0;
-	
-	spin_lock(&card->ac97_lock);
-	
-	if (reg == AC97_CD_VOL)
-		val2 = _cs_ac97_get(dev, AC97_CD_VOL);
-
-	/*
-	 *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
-	 *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
-	 *  3. Write ACCTL = Control Register = 460h for initiating the write
-	 *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
-	 *  5. if DCV not cleared, break and return error
-	 */
-
-	/*
-	 *  Setup the AC97 control registers on the CS461x to send the
-	 *  appropriate command to the AC97 to perform the read.
-	 *  ACCAD = Command Address Register = 46Ch
-	 *  ACCDA = Command Data Register = 470h
-	 *  ACCTL = Control Register = 460h
-	 *  set DCV - will clear when process completed
-	 *  reset CRW - Write command
-	 *  set VFRM - valid frame enabled
-	 *  set ESYN - ASYNC generation enabled
-	 *  set RSTN - ARST# inactive, AC97 codec not reset
-         */
-	cs461x_pokeBA0(card, BA0_ACCAD, reg);
-	cs461x_pokeBA0(card, BA0_ACCDA, val);
-	cs461x_peekBA0(card, BA0_ACCTL);
-	cs461x_pokeBA0(card, BA0_ACCTL, 0 | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
-	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM |
-				             ACCTL_ESYN | ACCTL_RSTN);
-	for (count = 0; count < 1000; count++) {
-		/*
-		 *  First, we want to wait for a short time.
-		 */
-		udelay(10 * cs_laptop_wait);
-		/*
-		 *  Now, check to see if the write has completed.
-		 *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
-		 */
-		if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV))
-			break;
-	}
-	/*
-	 *  Make sure the write completed.
-	 */
-	if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-			"cs46xx: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val));
-	}
-
-	spin_unlock(&card->ac97_lock);
-
-	/*
-	 *	Adjust power if the mixer is selected/deselected according
-	 *	to the CD.
-	 *
-	 *	IF the CD is a valid input source (mixer or direct) AND
-	 *		the CD is not muted THEN power is needed
-	 *
-	 *	We do two things. When record select changes the input to
-	 *	add/remove the CD we adjust the power count if the CD is
-	 *	unmuted.
-	 *
-	 *	When the CD mute changes we adjust the power level if the
-	 *	CD was a valid input.
-	 *
-	 *      We also check for CD volume != 0, as the CD mute isn't
-	 *      normally tweaked from userspace.
-	 */
-	 
-	/* CD mute change ? */
-	
-	if (reg == AC97_CD_VOL) {
-		/* Mute bit change ? */
-		if ((val2^val) & 0x8000 ||
-		    ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val)) {
-			/* This is a hack but its cleaner than the alternatives.
-			   Right now card->ac97_codec[0] might be NULL as we are
-			   still doing codec setup. This does an early assignment
-			   to avoid the problem if it occurs */
-			   
-			if (card->ac97_codec[0] == NULL)
-				card->ac97_codec[0] = dev;
-				
-			/* Mute on */
-			if (val & 0x8000 || val == 0x1f1f)
-				card->amplifier_ctrl(card, -1);
-			else { /* Mute off power on */
-				if (card->amp_init)
-					card->amp_init(card);
-				card->amplifier_ctrl(card, 1);
-			}
-		}
-	}
-}
-
-/* OSS /dev/mixer file operation methods */
-
-static int cs_open_mixdev(struct inode *inode, struct file *file)
-{
-	int i = 0;
-	unsigned int minor = iminor(inode);
-	struct cs_card *card = NULL;
-	struct list_head *entry;
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
-		  printk(KERN_INFO "cs46xx: cs_open_mixdev()+\n"));
-
-	list_for_each(entry, &cs46xx_devs) {
-		card = list_entry(entry, struct cs_card, list);
-		for (i = 0; i < NR_AC97; i++)
-			if (card->ac97_codec[i] != NULL &&
-			    card->ac97_codec[i]->dev_mixer == minor)
-				goto match;
-	}
-	if (!card) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
-			printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n"));
-		return -ENODEV;
-	}
- match:
-	if (!card->ac97_codec[i])
-		return -ENODEV;
-	file->private_data = card->ac97_codec[i];
-
-	card->active_ctrl(card,1);
-	if (!CS_IN_USE(&card->mixer_use_cnt)) {
-		if ((tmp = cs46xx_powerup(card, CS_POWER_MIXVON))) {
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs_open_mixdev() powerup failure (0x%x)\n", tmp));
-			return -EIO;
-		}
-	}
-	card->amplifier_ctrl(card, 1);
-	CS_INC_USE_COUNT(&card->mixer_use_cnt);
-	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
-		  printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n"));
-	return nonseekable_open(inode, file);
-}
-
-static int cs_release_mixdev(struct inode *inode, struct file *file)
-{
-	unsigned int minor = iminor(inode);
-	struct cs_card *card = NULL;
-	struct list_head *entry;
-	int i;
-	unsigned int tmp;
-
-	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
-		  printk(KERN_INFO "cs46xx: cs_release_mixdev()+\n"));
-	list_for_each(entry, &cs46xx_devs)
-	{
-		card = list_entry(entry, struct cs_card, list);
-		for (i = 0; i < NR_AC97; i++)
-			if (card->ac97_codec[i] != NULL &&
-			    card->ac97_codec[i]->dev_mixer == minor)
-				goto match;
-	}
-	if (!card) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
-			printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n"));
-		return -ENODEV;
-	}
-match:
-	if (!CS_DEC_AND_TEST(&card->mixer_use_cnt)) {
-		CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
-			  printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n"));
-		card->active_ctrl(card, -1);
-		card->amplifier_ctrl(card, -1);
-		return 0;
-	}
-/*
-* ok, no outstanding mixer opens, so powerdown.
-*/
-	if ((tmp = cs461x_powerdown(card, CS_POWER_MIXVON, CS_FALSE))) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n", tmp));
-		card->active_ctrl(card, -1);
-		card->amplifier_ctrl(card, -1);
-		return -EIO;
-	}
-	card->active_ctrl(card, -1);
-	card->amplifier_ctrl(card, -1);
-	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
-		  printk(KERN_INFO "cs46xx: cs_release_mixdev()- 0\n"));
-	return 0;
-}
-
-static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-			unsigned long arg)
-{
-	struct ac97_codec *codec = file->private_data;
-	struct cs_card *card = NULL;
-	struct list_head *entry;
-	unsigned long __user *p = (long __user *)arg;
-#if CSDEBUG_INTERFACE
-        int val;
-
-	if (	(cmd == SOUND_MIXER_CS_GETDBGMASK) ||
-		(cmd == SOUND_MIXER_CS_SETDBGMASK) ||
-		(cmd == SOUND_MIXER_CS_GETDBGLEVEL) ||
-		(cmd == SOUND_MIXER_CS_SETDBGLEVEL) ||
-		(cmd == SOUND_MIXER_CS_APM)) {
-		switch (cmd) {
-		case SOUND_MIXER_CS_GETDBGMASK:
-			return put_user(cs_debugmask, p);
-		case SOUND_MIXER_CS_GETDBGLEVEL:
-			return put_user(cs_debuglevel, p);
-		case SOUND_MIXER_CS_SETDBGMASK:
-			if (get_user(val, p))
-				return -EFAULT;
-			cs_debugmask = val;
-			return 0;
-		case SOUND_MIXER_CS_SETDBGLEVEL:
-			if (get_user(val, p))
-				return -EFAULT;
-			cs_debuglevel = val;
-			return 0;
-		case SOUND_MIXER_CS_APM:
-			if (get_user(val, p))
-				return -EFAULT;
-			if (val == CS_IOCTL_CMD_SUSPEND) {
-				list_for_each(entry, &cs46xx_devs) {
-					card = list_entry(entry, struct cs_card, list);
-					cs46xx_suspend(card, PMSG_ON);
-				}
-
-			} else if (val == CS_IOCTL_CMD_RESUME) {
-				list_for_each(entry, &cs46xx_devs) {
-					card = list_entry(entry, struct cs_card, list);
-					cs46xx_resume(card);
-				}
-			} else {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
-				    "cs46xx: mixer_ioctl(): invalid APM cmd (%d)\n",
-					val));
-			}
-			return 0;
-		default:
-			CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
-				"cs46xx: mixer_ioctl(): ERROR unknown debug cmd\n"));
-			return 0;
-		}
-	}
-#endif
-	return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static /*const*/ struct file_operations cs_mixer_fops = {
-	CS_OWNER	CS_THIS_MODULE
-	.llseek		= no_llseek,
-	.ioctl		= cs_ioctl_mixdev,
-	.open		= cs_open_mixdev,
-	.release	= cs_release_mixdev,
-};
-
-/* AC97 codec initialisation. */
-static int __init cs_ac97_init(struct cs_card *card)
-{
-	int num_ac97 = 0;
-	int ready_2nd = 0;
-	struct ac97_codec *codec;
-	u16 eid;
-
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-		"cs46xx: cs_ac97_init()+\n") );
-
-	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
-		if ((codec = ac97_alloc_codec()) == NULL)
-			return -ENOMEM;
-
-		/* initialize some basic codec information, other fields will be filled
-		   in ac97_probe_codec */
-		codec->private_data = card;
-		codec->id = num_ac97;
-
-		codec->codec_read = cs_ac97_get;
-		codec->codec_write = cs_ac97_set;
-	
-		if (ac97_probe_codec(codec) == 0) {
-			CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-				"cs46xx: cs_ac97_init()- codec number %d not found\n",
-					num_ac97) );
-			card->ac97_codec[num_ac97] = NULL;
-			break;
-		}
-		CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-			"cs46xx: cs_ac97_init() found codec %d\n",num_ac97));
-
-		eid = cs_ac97_get(codec, AC97_EXTENDED_ID);
-		
-		if (eid == 0xFFFF) {
-			printk(KERN_WARNING "cs46xx: codec %d not present\n",num_ac97);
-			ac97_release_codec(codec);
-			break;
-		}
-		
-		card->ac97_features = eid;
-			
-		if ((codec->dev_mixer = register_sound_mixer(&cs_mixer_fops, -1)) < 0) {
-			printk(KERN_ERR "cs46xx: couldn't register mixer!\n");
-			ac97_release_codec(codec);
-			break;
-		}
-		card->ac97_codec[num_ac97] = codec;
-
-		CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-			"cs46xx: cs_ac97_init() ac97_codec[%d] set to %p\n",
-				(unsigned int)num_ac97,
-				codec));
-		/* if there is no secondary codec at all, don't probe any more */
-		if (!ready_2nd)
-		{
-			num_ac97 += 1;
-			break;
-		}
-	}
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-		"cs46xx: cs_ac97_init()- %d\n", (unsigned int)num_ac97));
-	return num_ac97;
-}
-
-/*
- * load the static image into the DSP
- */
-#include "cs461x_image.h"
-static void cs461x_download_image(struct cs_card *card)
-{
-    unsigned i, j, temp1, temp2, offset, count;
-    unsigned char __iomem *pBA1 = ioremap(card->ba1_addr, 0x40000);
-    for (i = 0; i < CLEAR__COUNT; i++) {
-        offset = ClrStat[i].BA1__DestByteOffset;
-        count  = ClrStat[i].BA1__SourceSize;
-        for (temp1 = offset; temp1 < (offset + count); temp1 += 4)
-              writel(0, pBA1+temp1);
-    }
-
-    for (i = 0; i < FILL__COUNT; i++) {
-        temp2 = FillStat[i].Offset;
-        for (j = 0; j < (FillStat[i].Size) / 4; j++) {
-            temp1 = (FillStat[i]).pFill[j];
-            writel(temp1, pBA1+temp2 + j * 4);
-        }
-    }
-    iounmap(pBA1);
-}
-
-/*
- *  Chip reset
- */
-
-static void cs461x_reset(struct cs_card *card)
-{
-	int idx;
-
-	/*
-	 *  Write the reset bit of the SP control register.
-	 */
-	cs461x_poke(card, BA1_SPCR, SPCR_RSTSP);
-
-	/*
-	 *  Write the control register.
-	 */
-	cs461x_poke(card, BA1_SPCR, SPCR_DRQEN);
-
-	/*
-	 *  Clear the trap registers.
-	 */
-	for (idx = 0; idx < 8; idx++) {
-		cs461x_poke(card, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
-		cs461x_poke(card, BA1_TWPR, 0xFFFF);
-	}
-	cs461x_poke(card, BA1_DREG, 0);
-
-	/*
-	 *  Set the frame timer to reflect the number of cycles per frame.
-	 */
-	cs461x_poke(card, BA1_FRMT, 0xadf);
-}
-
-static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type)
-{
-	int idx, loop, startfifo=0, endfifo=0, powerdown1 = 0;
-	unsigned int tmp;
-
-	/*
-	 *  See if the devices are powered down.  If so, we must power them up first
-	 *  or they will not respond.
-	 */
-	if (!((tmp = cs461x_peekBA0(card, BA0_CLKCR1)) & CLKCR1_SWCE)) {
-		cs461x_pokeBA0(card, BA0_CLKCR1, tmp | CLKCR1_SWCE);
-		powerdown1 = 1;
-	}
-
-	/*
-	 *  We want to clear out the serial port FIFOs so we don't end up playing
-	 *  whatever random garbage happens to be in them.  We fill the sample FIFOS
-	 *  with zero (silence).
-         */
-	cs461x_pokeBA0(card, BA0_SERBWP, 0);
-
-	/*
-	* Check for which FIFO locations to clear, if we are currently
-	* playing or capturing then we don't want to put in 128 bytes of
-	* "noise".
-	 */
-	if (type & CS_TYPE_DAC) {
-		startfifo = 128;
-		endfifo = 256;
-	}
-	if (type & CS_TYPE_ADC) {
-		startfifo = 0;
-		if (!endfifo)
-			endfifo = 128;
-	}
-	/*
-	 *  Fill sample FIFO locations (256 locations total).
-	 */
-	for (idx = startfifo; idx < endfifo; idx++) {
-		/*
-		 *  Make sure the previous FIFO write operation has completed.
-		 */
-		for (loop = 0; loop < 5; loop++) {
-			udelay(50);
-			if (!(cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY))
-				break;
-		}
-		if (cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY) {
-			if (powerdown1)
-				cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-		}
-		/*
-		 *  Write the serial port FIFO index.
-		 */
-		cs461x_pokeBA0(card, BA0_SERBAD, idx);
-		/*
-		 *  Tell the serial port to load the new value into the FIFO location.
-		 */
-		cs461x_pokeBA0(card, BA0_SERBCM, SERBCM_WRC);
-	}
-	/*
-	 *  Now, if we powered up the devices, then power them back down again.
-	 *  This is kinda ugly, but should never happen.
-	 */
-	if (powerdown1)
-		cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-}
-
-
-static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag)
-{
-	int count;
-	unsigned int tmp=0,muted=0;
-
-	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
-		"cs46xx: cs461x_powerdown()+ type=0x%x\n",type));
-	if (!cs_powerdown && !suspendflag) {
-		CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
-			"cs46xx: cs461x_powerdown() DISABLED exiting\n"));
-		return 0;
-	}
-	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-	CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
-		"cs46xx: cs461x_powerdown() powerdown reg=0x%x\n",tmp));
-/*
-* if powering down only the VREF, and not powering down the DAC/ADC,
-* then do not power down the VREF, UNLESS both the DAC and ADC are not
-* currently powered down.  If powering down DAC and ADC, then
-* it is possible to power down the VREF (ON).
-*/
-	if (((type & CS_POWER_MIXVON) &&
-		 (!(type & CS_POWER_ADC) || (!(type & CS_POWER_DAC))))
-	      && 
-		((tmp & CS_AC97_POWER_CONTROL_ADC_ON) ||
-		 (tmp & CS_AC97_POWER_CONTROL_DAC_ON))) {
-		CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
-			"cs46xx: cs461x_powerdown()- 0  unable to powerdown. tmp=0x%x\n",tmp));
-		return 0;
-	}
-/*
-* for now, always keep power to the mixer block.
-* not sure why it's a problem but it seems to be if we power off.
-*/
-	type &= ~CS_POWER_MIXVON;
-	type &= ~CS_POWER_MIXVOFF;
-
-	/*
-	 *  Power down indicated areas.
-	 */
-	if (type & CS_POWER_MIXVOFF) {
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVOFF\n"));
-		/*
-		 *  Power down the MIXER (VREF ON) on the AC97 card.  
-		 */
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp |= CS_AC97_POWER_CONTROL_MIXVOFF;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_MIXVOFF_ON))
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVOFF_ON) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerdown MIXVOFF failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_MIXVON) {
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVON\n"));
-		/*
-		 *  Power down the MIXER (VREF ON) on the AC97 card.  
-		 */
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_MIXVON_ON) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp |= CS_AC97_POWER_CONTROL_MIXVON;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_MIXVON_ON))
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVON_ON) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerdown MIXVON failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_ADC) {
-		/*
-		 *  Power down the ADC on the AC97 card.  
-		 */
-		CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs461x_powerdown()+ ADC\n"));
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_ADC_ON) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp |= CS_AC97_POWER_CONTROL_ADC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
-
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_ADC_ON))
-					break;
-			}
-
-			/*
-			 *  Check the status..
-			 */
-			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_ADC_ON) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerdown ADC failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_DAC) {
-		/*
-		 *  Power down the DAC on the AC97 card.  
-		 */
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ DAC\n"));
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_DAC_ON) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp |= CS_AC97_POWER_CONTROL_DAC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_DAC_ON))
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_DAC_ON) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerdown DAC failed\n"));
-				return 1;
-			}
-		}
-	}
-	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-	if (muted)
-		cs_mute(card, CS_FALSE);
-	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
-		"cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp));
-	return 0;
-}
-
-static int cs46xx_powerup(struct cs_card *card, unsigned int type)
-{
-	int count;
-	unsigned int tmp = 0, muted = 0;
-
-	CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
-		"cs46xx: cs46xx_powerup()+ type=0x%x\n",type));
-	/*
-	* check for VREF and powerup if need to.
-	*/
-	if (type & CS_POWER_MIXVON)
-		type |= CS_POWER_MIXVOFF;
-	if (type & (CS_POWER_DAC | CS_POWER_ADC))
-		type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF;
-
-	/*
-	 *  Power up indicated areas.
-	 */
-	if (type & CS_POWER_MIXVOFF) {
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVOFF\n"));
-		/*
-		 *  Power up the MIXER (VREF ON) on the AC97 card.  
-		 */
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON)) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp &= ~CS_AC97_POWER_CONTROL_MIXVOFF;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_MIXVOFF_ON)
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVOFF_ON)) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerup MIXVOFF failed\n"));
-				return 1;
-			}
-		}
-	}
-	if(type & CS_POWER_MIXVON) {
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVON\n"));
-		/*
-		 *  Power up the MIXER (VREF ON) on the AC97 card.  
-		 */
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_MIXVON_ON)) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp &= ~CS_AC97_POWER_CONTROL_MIXVON;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_MIXVON_ON)
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVON_ON)) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerup MIXVON failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_ADC) {
-		/*
-		 *  Power up the ADC on the AC97 card.  
-		 */
-		CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs46xx_powerup()+ ADC\n"));
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_ADC_ON)) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp &= ~CS_AC97_POWER_CONTROL_ADC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_ADC_ON)
-					break;
-			}
-
-			/*
-			 *  Check the status..
-			 */
-			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_ADC_ON)) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerup ADC failed\n"));
-				return 1;
-			}
-		}
-	}
-	if (type & CS_POWER_DAC) {
-		/*
-		 *  Power up the DAC on the AC97 card.  
-		 */
-
-		CS_DBGOUT(CS_FUNCTION, 4, 
-			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ DAC\n"));
-		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_DAC_ON)) {
-			if (!muted) {
-				cs_mute(card, CS_TRUE);
-				muted = 1;
-			}
-			tmp &= ~CS_AC97_POWER_CONTROL_DAC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-			/*
-			 *  Now, we wait until we sample a ready state.
-			 */
-			for (count = 0; count < 32; count++) {
-				/*
-				 *  First, lets wait a short while to let things settle out a
-				 *  bit, and to prevent retrying the read too quickly.
-				 */
-				udelay(500);
-
-				/*
-				 *  Read the current state of the power control register.
-				 */
-				if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-					CS_AC97_POWER_CONTROL_DAC_ON)
-					break;
-			}
-			
-			/*
-			 *  Check the status..
-			 */
-			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_DAC_ON)) {
-				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
-					"cs46xx: powerup DAC failed\n"));
-				return 1;
-			}
-		}
-	}
-	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-	if (muted)
-		cs_mute(card, CS_FALSE);
-	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
-		"cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp));
-	return 0;
-}
-
-static void cs461x_proc_start(struct cs_card *card)
-{
-	int cnt;
-
-	/*
-	 *  Set the frame timer to reflect the number of cycles per frame.
-	 */
-	cs461x_poke(card, BA1_FRMT, 0xadf);
-	/*
-	 *  Turn on the run, run at frame, and DMA enable bits in the local copy of
-	 *  the SP control register.
-	 */
-	cs461x_poke(card, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
-	/*
-	 *  Wait until the run at frame bit resets itself in the SP control
-	 *  register.
-	 */
-	for (cnt = 0; cnt < 25; cnt++) {
-		udelay(50);
-		if (!(cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR))
-			break;
-	}
-
-	if (cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR)
-		printk(KERN_WARNING "cs46xx: SPCR_RUNFR never reset\n");
-}
-
-static void cs461x_proc_stop(struct cs_card *card)
-{
-	/*
-	 *  Turn off the run, run at frame, and DMA enable bits in the local copy of
-	 *  the SP control register.
-	 */
-	cs461x_poke(card, BA1_SPCR, 0);
-}
-
-static int cs_hardware_init(struct cs_card *card)
-{
-	unsigned long end_time;
-	unsigned int tmp,count;
-	
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-		"cs46xx: cs_hardware_init()+\n") );
-	/* 
-	 *  First, blast the clock control register to zero so that the PLL starts
-         *  out in a known state, and blast the master serial port control register
-         *  to zero so that the serial ports also start out in a known state.
-         */
-        cs461x_pokeBA0(card, BA0_CLKCR1, 0);
-        cs461x_pokeBA0(card, BA0_SERMC1, 0);
-
-	/*
-	 *  If we are in AC97 mode, then we must set the part to a host controlled
-         *  AC-link.  Otherwise, we won't be able to bring up the link.
-         */        
-        cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03);	/* 1.03 card */
-        /* cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); */ /* 2.00 card */
-
-        /*
-         *  Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
-         *  spec) and then drive it high.  This is done for non AC97 modes since
-         *  there might be logic external to the CS461x that uses the ARST# line
-         *  for a reset.
-         */
-        cs461x_pokeBA0(card, BA0_ACCTL, 1);
-        udelay(50);
-        cs461x_pokeBA0(card, BA0_ACCTL, 0);
-        udelay(50);
-        cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_RSTN);
-
-	/*
-	 *  The first thing we do here is to enable sync generation.  As soon
-	 *  as we start receiving bit clock, we'll start producing the SYNC
-	 *  signal.
-	 */
-	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
-
-	/*
-	 *  Now wait for a short while to allow the AC97 part to start
-	 *  generating bit clock (so we don't try to start the PLL without an
-	 *  input clock).
-	 */
-	mdelay(5 * cs_laptop_wait);		/* 1 should be enough ?? (and pigs might fly) */
-
-	/*
-	 *  Set the serial port timing configuration, so that
-	 *  the clock control circuit gets its clock from the correct place.
-	 */
-	cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97);
-
-	/*
-	* The part seems to not be ready for a while after a resume.
-	* so, if we are resuming, then wait for 700 mils.  Note that 600 mils
-	* is not enough for some platforms! tested on an IBM Thinkpads and 
-	* reference cards.
-	*/
-	if (!(card->pm.flags & CS46XX_PM_IDLE))
-		mdelay(initdelay);
-	/*
-	 *  Write the selected clock control setup to the hardware.  Do not turn on
-	 *  SWCE yet (if requested), so that the devices clocked by the output of
-	 *  PLL are not clocked until the PLL is stable.
-	 */
-	cs461x_pokeBA0(card, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
-	cs461x_pokeBA0(card, BA0_PLLM, 0x3a);
-	cs461x_pokeBA0(card, BA0_CLKCR2, CLKCR2_PDIVS_8);
-
-	/*
-	 *  Power up the PLL.
-	 */
-	cs461x_pokeBA0(card, BA0_CLKCR1, CLKCR1_PLLP);
-
-	/*
-         *  Wait until the PLL has stabilized.
-	 */
-	mdelay(5 * cs_laptop_wait);		/* Again 1 should be enough ?? */
-
-	/*
-	 *  Turn on clocking of the core so that we can setup the serial ports.
-	 */
-	tmp = cs461x_peekBA0(card, BA0_CLKCR1) | CLKCR1_SWCE;
-	cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
-	/*
-	 *  Fill the serial port FIFOs with silence.
-	 */
-	cs461x_clear_serial_FIFOs(card,CS_TYPE_DAC | CS_TYPE_ADC);
-
-	/*
-	 *  Set the serial port FIFO pointer to the first sample in the FIFO.
-	 */
-	/* cs461x_pokeBA0(card, BA0_SERBSP, 0); */
-
-	/*
-	 *  Write the serial port configuration to the part.  The master
-	 *  enable bit is not set until all other values have been written.
-	 */
-	cs461x_pokeBA0(card, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
-	cs461x_pokeBA0(card, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
-	cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
-
-
-	mdelay(5 * cs_laptop_wait);		/* Shouldnt be needed ?? */
-	
-/*
-* If we are resuming under 2.2.x then we cannot schedule a timeout,
-* so just spin the CPU.
-*/
-	if (card->pm.flags & CS46XX_PM_IDLE) {
-	/*
-	 * Wait for the card ready signal from the AC97 card.
-	 */
-		end_time = jiffies + 3 * (HZ >> 2);
-		do {
-		/*
-		 *  Read the AC97 status register to see if we've seen a CODEC READY
-		 *  signal from the AC97 card.
-		 */
-			if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)
-				break;
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout(1);
-		} while (time_before(jiffies, end_time));
-	} else {
-		for (count = 0; count < 100; count++) {
-		// First, we want to wait for a short time.
-			udelay(25 * cs_laptop_wait);
-
-			if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)
-				break;
-		}
-	}
-
-	/*
-	 *  Make sure CODEC is READY.
-	 */
-	if (!(cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING  
-			"cs46xx: create - never read card ready from AC'97\n"));
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING  
-			"cs46xx: probably not a bug, try using the CS4232 driver,\n"));
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING  
-			"cs46xx: or turn off any automatic Power Management support in the BIOS.\n"));
-		return -EIO;
-	}
-
-	/*
-	 *  Assert the vaid frame signal so that we can start sending commands
-	 *  to the AC97 card.
-	 */
-	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
-
-	if (card->pm.flags & CS46XX_PM_IDLE) {
-	/*
-	 *  Wait until we've sampled input slots 3 and 4 as valid, meaning that
-	 *  the card is pumping ADC data across the AC-link.
-	 */
-		end_time = jiffies + 3 * (HZ >> 2);
-		do {
-			/*
-			 *  Read the input slot valid register and see if input slots 3 and
-			 *  4 are valid yet.
-			 */
-			if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
-				break;
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout(1);
-		} while (time_before(jiffies, end_time));
-	} else {
-		for (count = 0; count < 100; count++) {
-		// First, we want to wait for a short time.
-			udelay(25 * cs_laptop_wait);
-
-			if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
-				break;
-		}
-	}
-	/*
-	 *  Make sure input slots 3 and 4 are valid.  If not, then return
-	 *  an error.
-	 */
-	if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4)) {
-		printk(KERN_WARNING "cs46xx: create - never read ISV3 & ISV4 from AC'97\n");
-		return -EIO;
-	}
-
-	/*
-	 *  Now, assert valid frame and the slot 3 and 4 valid bits.  This will
-	 *  commense the transfer of digital audio data to the AC97 card.
-	 */
-	cs461x_pokeBA0(card, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
-
-	/*
-	 *  Turn off the Processor by turning off the software clock enable flag in 
-	 *  the clock control register.
-	 */
-	/* tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; */
-	/* cs461x_pokeBA0(card, BA0_CLKCR1, tmp); */
-
-	/*
-         *  Reset the processor.
-         */
-	cs461x_reset(card);
-
-	/*
-         *  Download the image to the processor.
-	 */
-	
-	cs461x_download_image(card);
-
-	/*
-         *  Stop playback DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_PCTL);
-	card->pctl = tmp & 0xffff0000;
-	cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
-	/*
-         *  Stop capture DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_CCTL);
-	card->cctl = tmp & 0x0000ffff;
-	cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
-	/* initialize AC97 codec and register /dev/mixer */
-	if (card->pm.flags & CS46XX_PM_IDLE) {
-		if (cs_ac97_init(card) <= 0) {
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs_ac97_init() failure\n"));
-			return -EIO;
-		}
-	} else {
-		cs46xx_ac97_resume(card);
-	}
-	
-	cs461x_proc_start(card);
-
-	/*
-	 *  Enable interrupts on the part.
-	 */
-	cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM);
-
-	tmp = cs461x_peek(card, BA1_PFIE);
-	tmp &= ~0x0000f03f;
-	cs461x_poke(card, BA1_PFIE, tmp);	/* playback interrupt enable */
-
-	tmp = cs461x_peek(card, BA1_CIE);
-	tmp &= ~0x0000003f;
-	tmp |=  0x00000001;
-	cs461x_poke(card, BA1_CIE, tmp);	/* capture interrupt enable */	
-
-	/*
-	 *  If IDLE then Power down the part.  We will power components up 
-	 *  when we need them.  
-	 */
-	if (card->pm.flags & CS46XX_PM_IDLE) {
-		if (!cs_powerdown) {
-			if ((tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC |
-					CS_POWER_MIXVON))) {
-				CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-					"cs46xx: cs461x_powerup() failure (0x%x)\n",tmp) );
-				return -EIO;
-			}
-		} else {
-			if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-					CS_POWER_MIXVON, CS_FALSE))) {
-				CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-					"cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
-				return -EIO;
-			}
-		}
-	}
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-		"cs46xx: cs_hardware_init()- 0\n"));
-	return 0;
-}
-
-/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
-   until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
-   
-/*
- *	Card subid table
- */
- 
-struct cs_card_type
-{
-	u16 vendor;
-	u16 id;
-	char *name;
-	void (*amp)(struct cs_card *, int);
-	void (*amp_init)(struct cs_card *);
-	void (*active)(struct cs_card *, int);
-};
-
-static struct cs_card_type cards[] = {
-	{
-		.vendor	= 0x1489,
-		.id	= 0x7001,
-		.name	= "Genius Soundmaker 128 value",
-		.amp	= amp_none,
-	},
-	{
-		.vendor	= 0x5053,
-		.id	= 0x3357,
-		.name	= "Voyetra",
-		.amp	= amp_voyetra,
-	},
-	{
-		.vendor	= 0x1071,
-		.id	= 0x6003,
-		.name	= "Mitac MI6020/21",
-		.amp	= amp_voyetra,
-	},
-	{
-		.vendor	= 0x14AF,
-		.id	= 0x0050,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0050,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0051,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0052,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0053,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0x0054,
-		.name	= "Hercules Game Theatre XP",
-		.amp	= amp_hercules,
-	},
-	{
-		.vendor	= 0x1681,
-		.id	= 0xa010,
-		.name	= "Hercules Fortissimo II",
-		.amp	= amp_none,
-	},
-	/* Not sure if the 570 needs the clkrun hack */
-	{
-		.vendor	= PCI_VENDOR_ID_IBM,
-		.id	= 0x0132,
-		.name	= "Thinkpad 570",
-		.amp	= amp_none,
-		.active	= clkrun_hack,
-	},
-	{
-		.vendor	= PCI_VENDOR_ID_IBM,
-		.id	= 0x0153,
-		.name	= "Thinkpad 600X/A20/T20",
-		.amp	= amp_none,
-		.active	= clkrun_hack,
-	},
-	{
-		.vendor	= PCI_VENDOR_ID_IBM,
-		.id	= 0x1010,
-		.name	= "Thinkpad 600E (unsupported)",
-	},
-	{
-		.name	= "Card without SSID set",
-	},
-	{ 0, },
-};
-
-MODULE_AUTHOR("Alan Cox <alan@redhat.com>, Jaroslav Kysela, <pcaudio@crystal.cirrus.com>");
-MODULE_DESCRIPTION("Crystal SoundFusion Audio Support");
-MODULE_LICENSE("GPL");
-
-static const char cs46xx_banner[] = KERN_INFO "Crystal 4280/46xx + AC97 Audio, version " CS46XX_MAJOR_VERSION "." CS46XX_MINOR_VERSION "." CS46XX_ARCH ", " __TIME__ " " __DATE__ "\n";
-static const char fndmsg[] = KERN_INFO "cs46xx: Found %d audio device(s).\n";
-
-static int __devinit cs46xx_probe(struct pci_dev *pci_dev,
-				  const struct pci_device_id *pciid)
-{
-	int i, j;
-	u16 ss_card, ss_vendor;
-	struct cs_card *card;
-	dma_addr_t dma_mask;
-	struct cs_card_type *cp = &cards[0];
-
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2,
-		  printk(KERN_INFO "cs46xx: probe()+\n"));
-
-	dma_mask = 0xffffffff;	/* this enables playback and recording */
-	if (pci_enable_device(pci_dev)) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
-			 "cs46xx: pci_enable_device() failed\n"));
-		return -1;
-	}
-	if (!RSRCISMEMORYREGION(pci_dev, 0) ||
-	    !RSRCISMEMORYREGION(pci_dev, 1)) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-			 "cs46xx: probe()- Memory region not assigned\n"));
-		return -1;
-	}
-	if (pci_dev->irq == 0) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-			 "cs46xx: probe() IRQ not assigned\n"));
-		return -1;
-	}
-	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-		      "cs46xx: probe() architecture does not support 32bit PCI busmaster DMA\n"));
-		return -1;
-	}
-	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
-	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card);
-
-	if ((card = kzalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) {
-		printk(KERN_ERR "cs46xx: out of memory\n");
-		return -ENOMEM;
-	}
-	card->ba0_addr = RSRCADDRESS(pci_dev, 0);
-	card->ba1_addr = RSRCADDRESS(pci_dev, 1);
-	card->pci_dev = pci_dev;
-	card->irq = pci_dev->irq;
-	card->magic = CS_CARD_MAGIC;
-	spin_lock_init(&card->lock);
-	spin_lock_init(&card->ac97_lock);
-
-	pci_set_master(pci_dev);
-
-	printk(cs46xx_banner);
-	printk(KERN_INFO "cs46xx: Card found at 0x%08lx and 0x%08lx, IRQ %d\n",
-	       card->ba0_addr, card->ba1_addr, card->irq);
-
-	card->alloc_pcm_channel = cs_alloc_pcm_channel;
-	card->alloc_rec_pcm_channel = cs_alloc_rec_pcm_channel;
-	card->free_pcm_channel = cs_free_pcm_channel;
-	card->amplifier_ctrl = amp_none;
-	card->active_ctrl = amp_none;
-
-	while (cp->name)
-	{
-		if (cp->vendor == ss_vendor && cp->id == ss_card) {
-			card->amplifier_ctrl = cp->amp;
-			if (cp->active)
-				card->active_ctrl = cp->active;
-			if (cp->amp_init)
-				card->amp_init = cp->amp_init;
-			break;
-		}
-		cp++;
-	}
-	if (cp->name == NULL) {
-		printk(KERN_INFO "cs46xx: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
-			ss_vendor, ss_card, card->ba0_addr, card->ba1_addr,  card->irq);
-	} else {
-		printk(KERN_INFO "cs46xx: %s (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
-			cp->name, ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq);
-	}
-	
-	if (card->amplifier_ctrl == NULL) {
-		card->amplifier_ctrl = amp_none;
-		card->active_ctrl = clkrun_hack;
-	}		
-
-	if (external_amp == 1) {
-		printk(KERN_INFO "cs46xx: Crystal EAPD support forced on.\n");
-		card->amplifier_ctrl = amp_voyetra;
-	}
-
-	if (thinkpad == 1) {
-		printk(KERN_INFO "cs46xx: Activating CLKRUN hack for Thinkpad.\n");
-		card->active_ctrl = clkrun_hack;
-	}
-/*
-* The thinkpads don't work well without runtime updating on their kernel 
-* delay values (or any laptop with variable CPU speeds really).
-* so, just to be safe set the init delay to 2100.  Eliminates
-* failures on T21 Thinkpads.  remove this code when the udelay
-* and mdelay kernel code is replaced by a pm timer, or the delays
-* work well for battery and/or AC power both.
-*/
-	if (card->active_ctrl == clkrun_hack) {
-		initdelay = 2100;
-		cs_laptop_wait = 5;
-	}
-	if ((card->active_ctrl == clkrun_hack) && !(powerdown == 1)) {
-/*
-* for some currently unknown reason, powering down the DAC and ADC component
-* blocks on thinkpads causes some funky behavior... distoorrrtion and ac97 
-* codec access problems.  probably the serial clock becomes unsynced. 
-* added code to sync the chips back up, but only helped about 70% the time.
-*/
-		cs_powerdown = 0;
-	}
-	if (powerdown == 0)
-		cs_powerdown = 0;
-	card->active_ctrl(card, 1);
-
-	/* claim our iospace and irq */
-	
-	card->ba0 = ioremap_nocache(card->ba0_addr, CS461X_BA0_SIZE);
-	card->ba1.name.data0 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE);
-	card->ba1.name.data1 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE);
-	card->ba1.name.pmem = ioremap_nocache(card->ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
-	card->ba1.name.reg = ioremap_nocache(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
-	
-	CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO 
-		"cs46xx: card=%p card->ba0=%p\n",card,card->ba0) );
-	CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO 
-		"cs46xx: card->ba1=%p %p %p %p\n",
-			card->ba1.name.data0,
-			card->ba1.name.data1,
-			card->ba1.name.pmem,
-			card->ba1.name.reg) );
-
-	if (card->ba0 == 0 || card->ba1.name.data0 == 0 ||
-		card->ba1.name.data1 == 0 || card->ba1.name.pmem == 0 ||
-		card->ba1.name.reg == 0)
-		goto fail2;
-		
-	if (request_irq(card->irq, &cs_interrupt, IRQF_SHARED, "cs46xx", card)) {
-		printk(KERN_ERR "cs46xx: unable to allocate irq %d\n", card->irq);
-		goto fail2;
-	}
-	/* register /dev/dsp */
-	if ((card->dev_audio = register_sound_dsp(&cs461x_fops, -1)) < 0) {
-		printk(KERN_ERR "cs46xx: unable to register dsp\n");
-		goto fail;
-	}
-
-        /* register /dev/midi */
-        if ((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0)
-                printk(KERN_ERR "cs46xx: unable to register midi\n");
-                
-	card->pm.flags |= CS46XX_PM_IDLE;
-	for (i = 0; i < 5; i++) {
-		if (cs_hardware_init(card) != 0) {
-			CS_DBGOUT(CS_ERROR, 4, printk(
-				"cs46xx: ERROR in cs_hardware_init()... retrying\n"));
-			for (j = 0; j < NR_AC97; j++)
-				if (card->ac97_codec[j] != NULL) {
-					unregister_sound_mixer(card->ac97_codec[j]->dev_mixer);
-					ac97_release_codec(card->ac97_codec[j]);
-				}
-			mdelay(10 * cs_laptop_wait);
-			continue;
-		}
-		break;
-	}
-	if(i >= 4) {
-		CS_DBGOUT(CS_PM | CS_ERROR, 1, printk(
-			"cs46xx: cs46xx_probe()- cs_hardware_init() failed, retried %d times.\n",i));
-                unregister_sound_dsp(card->dev_audio);
-                if (card->dev_midi)
-                        unregister_sound_midi(card->dev_midi);
-                goto fail;
-	}
-
-        init_waitqueue_head(&card->midi.open_wait);
-        mutex_init(&card->midi.open_mutex);
-        init_waitqueue_head(&card->midi.iwait);
-        init_waitqueue_head(&card->midi.owait);
-        cs461x_pokeBA0(card, BA0_MIDCR, MIDCR_MRST);   
-        cs461x_pokeBA0(card, BA0_MIDCR, 0);   
-
-	/* 
-	* Check if we have to init the amplifier, but probably already done
-	* since the CD logic in the ac97 init code will turn on the ext amp.
-	*/
-	if (cp->amp_init)
-		cp->amp_init(card);
-        card->active_ctrl(card, -1);
-
-	PCI_SET_DRIVER_DATA(pci_dev, card);
-	PCI_SET_DMA_MASK(pci_dev, dma_mask);
-	list_add(&card->list, &cs46xx_devs);
-
-	CS_DBGOUT(CS_PM, 9, printk(KERN_INFO "cs46xx: pm.flags=0x%x card=%p\n",
-		(unsigned)card->pm.flags,card));
-
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
-		"cs46xx: probe()- device allocated successfully\n"));
-        return 0;
-
-fail:
-	free_irq(card->irq, card);
-fail2:
-	if (card->ba0)
-		iounmap(card->ba0);
-	if (card->ba1.name.data0)
-		iounmap(card->ba1.name.data0);
-	if (card->ba1.name.data1)
-		iounmap(card->ba1.name.data1);
-	if (card->ba1.name.pmem)
-		iounmap(card->ba1.name.pmem);
-	if (card->ba1.name.reg)
-		iounmap(card->ba1.name.reg);
-	kfree(card);
-	CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO
-		"cs46xx: probe()- no device allocated\n"));
-	return -ENODEV;
-} // probe_cs46xx
-
-// --------------------------------------------------------------------- 
-
-static void __devexit cs46xx_remove(struct pci_dev *pci_dev)
-{
-	struct cs_card *card = PCI_GET_DRIVER_DATA(pci_dev);
-	int i;
-	unsigned int tmp;
-	
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
-		 "cs46xx: cs46xx_remove()+\n"));
-
-	card->active_ctrl(card,1);
-	
-	tmp = cs461x_peek(card, BA1_PFIE);
-	tmp &= ~0x0000f03f;
-	tmp |=  0x00000010;
-	cs461x_poke(card, BA1_PFIE, tmp);	/* playback interrupt disable */
-
-	tmp = cs461x_peek(card, BA1_CIE);
-	tmp &= ~0x0000003f;
-	tmp |=  0x00000011;
-	cs461x_poke(card, BA1_CIE, tmp);	/* capture interrupt disable */
-
-	/*
-         *  Stop playback DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_PCTL);
-	cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
-	/*
-         *  Stop capture DMA.
-	 */
-	tmp = cs461x_peek(card, BA1_CCTL);
-	cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
-	/*
-         *  Reset the processor.
-         */
-	cs461x_reset(card);
-
-	cs461x_proc_stop(card);
-
-	/*
-	 *  Power down the DAC and ADC.  We will power them up (if) when we need
-	 *  them.
-	 */
-	if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-			CS_POWER_MIXVON, CS_TRUE))) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
-	}
-
-	/*
-	 *  Power down the PLL.
-	 */
-	cs461x_pokeBA0(card, BA0_CLKCR1, 0);
-
-	/*
-	 *  Turn off the Processor by turning off the software clock enable flag in 
-	 *  the clock control register.
-	 */
-	tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE;
-	cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
-	card->active_ctrl(card,-1);
-
-	/* free hardware resources */
-	free_irq(card->irq, card);
-	iounmap(card->ba0);
-	iounmap(card->ba1.name.data0);
-	iounmap(card->ba1.name.data1);
-	iounmap(card->ba1.name.pmem);
-	iounmap(card->ba1.name.reg);
-	
-	/* unregister audio devices */
-	for (i = 0; i < NR_AC97; i++)
-		if (card->ac97_codec[i] != NULL) {
-			unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-			ac97_release_codec(card->ac97_codec[i]);
-		}
-	unregister_sound_dsp(card->dev_audio);
-        if (card->dev_midi)
-                unregister_sound_midi(card->dev_midi);
-	list_del(&card->list);
-	kfree(card);
-	PCI_SET_DRIVER_DATA(pci_dev,NULL);
-
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
-		 "cs46xx: cs46xx_remove()-: remove successful\n"));
-}
-
-enum {
-	CS46XX_4610 = 0,
-	CS46XX_4612,  	/* same as 4630 */
-	CS46XX_4615,  	/* same as 4624 */
-};
-
-static struct pci_device_id cs46xx_pci_tbl[] = {
-	{
-		.vendor	     = PCI_VENDOR_ID_CIRRUS,
-		.device	     = PCI_DEVICE_ID_CIRRUS_4610,
-		.subvendor   = PCI_ANY_ID,
-		.subdevice   = PCI_ANY_ID,
-		.driver_data = CS46XX_4610,
-	},
-	{
-		.vendor	     = PCI_VENDOR_ID_CIRRUS,
-		.device	     = PCI_DEVICE_ID_CIRRUS_4612,
-		.subvendor   = PCI_ANY_ID,
-		.subdevice   = PCI_ANY_ID,
-		.driver_data = CS46XX_4612,
-	},
-	{
-		.vendor	     = PCI_VENDOR_ID_CIRRUS,
-		.device	     = PCI_DEVICE_ID_CIRRUS_4615,
-		.subvendor   = PCI_ANY_ID,
-		.subdevice   = PCI_ANY_ID,
-		.driver_data = CS46XX_4615,
-	},
-	{ 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, cs46xx_pci_tbl);
-
-static struct pci_driver cs46xx_pci_driver = {
-	.name	  = "cs46xx",
-	.id_table = cs46xx_pci_tbl,
-	.probe	  = cs46xx_probe,
-	.remove	  = __devexit_p(cs46xx_remove),
-#ifdef CONFIG_PM
-	.suspend  = cs46xx_suspend_tbl,
-	.resume	  = cs46xx_resume_tbl,
-#endif
-};
-
-static int __init cs46xx_init_module(void)
-{
-	int rtn = 0;
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO 
-		"cs46xx: cs46xx_init_module()+ \n"));
-	rtn = pci_register_driver(&cs46xx_pci_driver);
-
-	if (rtn == -ENODEV) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk( 
-			"cs46xx: Unable to detect valid cs46xx device\n"));
-	}
-
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs46xx: cs46xx_init_module()- (%d)\n",rtn));
-	return rtn;
-}
-
-static void __exit cs46xx_cleanup_module(void)
-{
-	pci_unregister_driver(&cs46xx_pci_driver);
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs46xx: cleanup_cs46xx() finished\n"));
-}
-
-module_init(cs46xx_init_module);
-module_exit(cs46xx_cleanup_module);
-
-#ifdef CONFIG_PM
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
-{
-	struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 2, 
-		printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n"));
-	cs46xx_suspend(s, state);
-	return 0;
-}
-
-static int cs46xx_resume_tbl(struct pci_dev *pcidev)
-{
-	struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 2, 
-		printk(KERN_INFO "cs46xx: cs46xx_resume_tbl request\n"));
-	cs46xx_resume(s);
-	return 0;
-}
-#endif
diff --git a/sound/oss/cs46xx_wrapper-24.h b/sound/oss/cs46xx_wrapper-24.h
deleted file mode 100644
index f68e011..0000000
--- a/sound/oss/cs46xx_wrapper-24.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
-*
-*      "cs46xx_wrapper.c" --  Cirrus Logic-Crystal CS46XX linux audio driver.
-*
-*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
-*            -- tom woller (twoller@crystal.cirrus.com) or
-*               (pcaudio@crystal.cirrus.com).
-*
-*      This program is free software; you can redistribute it and/or modify
-*      it under the terms of the GNU General Public License as published by
-*      the Free Software Foundation; either version 2 of the License, or
-*      (at your option) any later version.
-*
-*      This program is distributed in the hope that it will be useful,
-*      but WITHOUT ANY WARRANTY; without even the implied warranty of
-*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*      GNU General Public License for more details.
-*
-*      You should have received a copy of the GNU General Public License
-*      along with this program; if not, write to the Free Software
-*      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* 01/11/2001 trw - new file from cs4281 wrapper code. 
-*
-*******************************************************************************/
-#ifndef __CS46XX_WRAPPER24_H
-#define __CS46XX_WRAPPER24_H
-
-#include <linux/spinlock.h>
-
-#define CS_OWNER .owner =
-#define CS_THIS_MODULE THIS_MODULE,
-static inline void cs46xx_null(struct pci_dev *pcidev) { return; }
-#define cs4x_mem_map_reserve(page) SetPageReserved(page)
-#define cs4x_mem_map_unreserve(page) ClearPageReserved(page)
-
-#define free_dmabuf(card, dmabuf) \
-	pci_free_consistent((card)->pci_dev, \
-			    PAGE_SIZE << (dmabuf)->buforder, \
-			    (dmabuf)->rawbuf, (dmabuf)->dmaaddr);
-#define free_dmabuf2(card, dmabuf) \
-	pci_free_consistent((card)->pci_dev, \
-				    PAGE_SIZE << (dmabuf)->buforder_tmpbuff, \
-				    (dmabuf)->tmpbuff, (dmabuf)->dmaaddr_tmpbuff);
-#define cs4x_pgoff(vma) ((vma)->vm_pgoff)
-
-#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
-	 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
-#define RSRCISMEMORYREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
-	 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
-#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
-#define PCI_GET_DRIVER_DATA pci_get_drvdata
-#define PCI_SET_DRIVER_DATA pci_set_drvdata
-#define PCI_SET_DMA_MASK(pcidev,mask) pcidev->dma_mask = mask
-
-#endif
diff --git a/sound/oss/cs46xxpm.h b/sound/oss/cs46xxpm.h
deleted file mode 100644
index 2932b6e..0000000
--- a/sound/oss/cs46xxpm.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
-*
-*      "cs46xxpm.h" --  Cirrus Logic-Crystal CS46XX linux audio driver.
-*
-*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
-*            -- tom woller (twoller@crystal.cirrus.com) or
-*               (pcaudio@crystal.cirrus.com).
-*
-*      This program is free software; you can redistribute it and/or modify
-*      it under the terms of the GNU General Public License as published by
-*      the Free Software Foundation; either version 2 of the License, or
-*      (at your option) any later version.
-*
-*      This program is distributed in the hope that it will be useful,
-*      but WITHOUT ANY WARRANTY; without even the implied warranty of
-*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*      GNU General Public License for more details.
-*
-*      You should have received a copy of the GNU General Public License
-*      along with this program; if not, write to the Free Software
-*      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* 12/22/00 trw - new file. 
-*
-*******************************************************************************/
-#ifndef __CS46XXPM_H
-#define __CS46XXPM_H
-
-#define CS46XX_AC97_HIGHESTREGTORESTORE 0x26
-#define CS46XX_AC97_NUMBER_RESTORE_REGS (CS46XX_AC97_HIGHESTREGTORESTORE/2-1)
-
-/* PM state defintions */
-#define CS46XX_PM_NOT_REGISTERED	0x1000
-#define CS46XX_PM_IDLE			0x0001
-#define CS46XX_PM_SUSPENDING		0x0002
-#define CS46XX_PM_SUSPENDED		0x0004
-#define CS46XX_PM_RESUMING		0x0008
-#define CS46XX_PM_RESUMED		0x0010
-
-#define CS_POWER_DAC			0x0001
-#define CS_POWER_ADC			0x0002
-#define CS_POWER_MIXVON			0x0004
-#define CS_POWER_MIXVOFF		0x0008
-#define CS_AC97_POWER_CONTROL_ON	0xf000  /* always on bits (inverted) */
-#define CS_AC97_POWER_CONTROL_ADC	0x0100
-#define CS_AC97_POWER_CONTROL_DAC	0x0200
-#define CS_AC97_POWER_CONTROL_MIXVON	0x0400
-#define CS_AC97_POWER_CONTROL_MIXVOFF	0x0800
-#define CS_AC97_POWER_CONTROL_ADC_ON	0x0001
-#define CS_AC97_POWER_CONTROL_DAC_ON	0x0002
-#define CS_AC97_POWER_CONTROL_MIXVON_ON	0x0004
-#define CS_AC97_POWER_CONTROL_MIXVOFF_ON 0x0008
-
-struct cs46xx_pm {
-	unsigned long flags;
-	u32 u32CLKCR1_SAVE,u32SSPMValue,u32PPLVCvalue,u32PPRVCvalue;
-	u32 u32FMLVCvalue,u32FMRVCvalue,u32GPIORvalue,u32JSCTLvalue,u32SSCR;
-	u32 u32SRCSA,u32DacASR,u32AdcASR,u32DacSR,u32AdcSR,u32MIDCR_Save;
-	u32 u32SSPM_BITS;
-	u32 ac97[CS46XX_AC97_NUMBER_RESTORE_REGS];
-	u32 u32AC97_master_volume, u32AC97_headphone_volume, u32AC97_master_volume_mono;
-	u32 u32AC97_pcm_out_volume, u32AC97_powerdown, u32AC97_general_purpose;
-	u32 u32hwptr_playback,u32hwptr_capture;
-	unsigned dmabuf_swptr_play;
-	int dmabuf_count_play;
-	unsigned dmabuf_swptr_capture;
-	int dmabuf_count_capture;
-};
-
-#endif
diff --git a/sound/oss/emu10k1/8010.h b/sound/oss/emu10k1/8010.h
deleted file mode 100644
index 61c6c42..0000000
--- a/sound/oss/emu10k1/8010.h
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
- **********************************************************************
- *     8010.h
- *     Copyright 1999-2001 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date		    Author	    Summary of changes
- *     ----		    ------	    ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox	    Cleaned of 8bit chars, DOS
- *					    line endings
- *     December 8, 1999     Jon Taylor	    Added lots of new register info
- *     May 16, 2001         Daniel Bertrand Added unofficial DBG register info
- *     Oct-Nov 2001         D.B.            Added unofficial Audigy registers 
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- *
- **********************************************************************
- */
-
-
-#ifndef _8010_H
-#define _8010_H
-
-#include <linux/types.h>
-
-// Driver version:
-#define MAJOR_VER 0
-#define MINOR_VER 20
-#define DRIVER_VERSION "0.20a"
-
-
-// Audigy specify registers are prefixed with 'A_'
-
-/************************************************************************************************/
-/* PCI function 0 registers, address = <val> + PCIBASE0						*/
-/************************************************************************************************/
-
-#define PTR			0x00		/* Indexed register set pointer register	*/
-						/* NOTE: The CHANNELNUM and ADDRESS words can	*/
-						/* be modified independently of each other.	*/
-#define PTR_CHANNELNUM_MASK	0x0000003f	/* For each per-channel register, indicates the	*/
-						/* channel number of the register to be		*/
-						/* accessed.  For non per-channel registers the	*/
-						/* value should be set to zero.			*/
-#define PTR_ADDRESS_MASK	0x07ff0000	/* Register index				*/
-
-#define DATA			0x04		/* Indexed register set data register		*/
-
-#define IPR			0x08		/* Global interrupt pending register		*/
-						/* Clear pending interrupts by writing a 1 to	*/
-						/* the relevant bits and zero to the other bits	*/
-
-/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
-#define A_IPR_MIDITRANSBUFEMPTY2	0x10000000	/* MIDI UART transmit buffer empty		*/
-#define A_IPR_MIDIRECVBUFEMPTY2	0x08000000	/* MIDI UART receive buffer empty		*/
-
-#define IPR_SAMPLERATETRACKER	0x01000000	/* Sample rate tracker lock status change	*/
-#define IPR_FXDSP		0x00800000	/* Enable FX DSP interrupts			*/
-#define IPR_FORCEINT		0x00400000	/* Force Sound Blaster interrupt		*/
-#define IPR_PCIERROR		0x00200000	/* PCI bus error				*/
-#define IPR_VOLINCR		0x00100000	/* Volume increment button pressed		*/
-#define IPR_VOLDECR		0x00080000	/* Volume decrement button pressed		*/
-#define IPR_MUTE		0x00040000	/* Mute button pressed				*/
-#define IPR_MICBUFFULL		0x00020000	/* Microphone buffer full			*/
-#define IPR_MICBUFHALFFULL	0x00010000	/* Microphone buffer half full			*/
-#define IPR_ADCBUFFULL		0x00008000	/* ADC buffer full				*/
-#define IPR_ADCBUFHALFFULL	0x00004000	/* ADC buffer half full				*/
-#define IPR_EFXBUFFULL		0x00002000	/* Effects buffer full				*/
-#define IPR_EFXBUFHALFFULL	0x00001000	/* Effects buffer half full			*/
-#define IPR_GPSPDIFSTATUSCHANGE	0x00000800	/* GPSPDIF channel status change		*/
-#define IPR_CDROMSTATUSCHANGE	0x00000400	/* CD-ROM channel status change			*/
-#define IPR_INTERVALTIMER	0x00000200	/* Interval timer terminal count		*/
-#define IPR_MIDITRANSBUFEMPTY	0x00000100	/* MIDI UART transmit buffer empty		*/
-#define IPR_MIDIRECVBUFEMPTY	0x00000080	/* MIDI UART receive buffer empty		*/
-#define IPR_CHANNELLOOP		0x00000040	/* One or more channel loop interrupts pending	*/
-#define IPR_CHANNELNUMBERMASK	0x0000003f	/* When IPR_CHANNELLOOP is set, indicates the	*/
-						/* Highest set channel in CLIPL or CLIPH.  When	*/
-						/* IP is written with CL set, the bit in CLIPL	*/
-						/* or CLIPH corresponding to the CIN value 	*/
-						/* written will be cleared.			*/
-#define A_IPR_MIDITRANSBUFEMPTY1	IPR_MIDITRANSBUFEMPTY	/* MIDI UART transmit buffer empty		*/
-#define A_IPR_MIDIRECVBUFEMPTY1	IPR_MIDIRECVBUFEMPTY	/* MIDI UART receive buffer empty		*/
-
-
-
-#define INTE			0x0c		/* Interrupt enable register			*/
-#define INTE_VIRTUALSB_MASK	0xc0000000	/* Virtual Soundblaster I/O port capture	*/
-#define INTE_VIRTUALSB_220	0x00000000	/* Capture at I/O base address 0x220-0x22f	*/
-#define INTE_VIRTUALSB_240	0x40000000	/* Capture at I/O base address 0x240		*/
-#define INTE_VIRTUALSB_260	0x80000000	/* Capture at I/O base address 0x260		*/
-#define INTE_VIRTUALSB_280	0xc0000000	/* Capture at I/O base address 0x280		*/
-#define INTE_VIRTUALMPU_MASK	0x30000000	/* Virtual MPU I/O port capture			*/
-#define INTE_VIRTUALMPU_300	0x00000000	/* Capture at I/O base address 0x300-0x301	*/
-#define INTE_VIRTUALMPU_310	0x10000000	/* Capture at I/O base address 0x310		*/
-#define INTE_VIRTUALMPU_320	0x20000000	/* Capture at I/O base address 0x320		*/
-#define INTE_VIRTUALMPU_330	0x30000000	/* Capture at I/O base address 0x330		*/
-#define INTE_MASTERDMAENABLE	0x08000000	/* Master DMA emulation at 0x000-0x00f		*/
-#define INTE_SLAVEDMAENABLE	0x04000000	/* Slave DMA emulation at 0x0c0-0x0df		*/
-#define INTE_MASTERPICENABLE	0x02000000	/* Master PIC emulation at 0x020-0x021		*/
-#define INTE_SLAVEPICENABLE	0x01000000	/* Slave PIC emulation at 0x0a0-0x0a1		*/
-#define INTE_VSBENABLE		0x00800000	/* Enable virtual Soundblaster			*/
-#define INTE_ADLIBENABLE	0x00400000	/* Enable AdLib emulation at 0x388-0x38b	*/
-#define INTE_MPUENABLE		0x00200000	/* Enable virtual MPU				*/
-#define INTE_FORCEINT		0x00100000	/* Continuously assert INTAN			*/
-
-#define INTE_MRHANDENABLE	0x00080000	/* Enable the "Mr. Hand" logic			*/
-						/* NOTE: There is no reason to use this under	*/
-						/* Linux, and it will cause odd hardware 	*/
-						/* behavior and possibly random segfaults and	*/
-						/* lockups if enabled.				*/
-
-/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
-#define A_INTE_MIDITXENABLE2	0x00020000	/* Enable MIDI transmit-buffer-empty interrupts	*/
-#define A_INTE_MIDIRXENABLE2	0x00010000	/* Enable MIDI receive-buffer-empty interrupts	*/
-
-
-#define INTE_SAMPLERATETRACKER	0x00002000	/* Enable sample rate tracker interrupts	*/
-						/* NOTE: This bit must always be enabled       	*/
-#define INTE_FXDSPENABLE	0x00001000	/* Enable FX DSP interrupts			*/
-#define INTE_PCIERRORENABLE	0x00000800	/* Enable PCI bus error interrupts		*/
-#define INTE_VOLINCRENABLE	0x00000400	/* Enable volume increment button interrupts	*/
-#define INTE_VOLDECRENABLE	0x00000200	/* Enable volume decrement button interrupts	*/
-#define INTE_MUTEENABLE		0x00000100	/* Enable mute button interrupts		*/
-#define INTE_MICBUFENABLE	0x00000080	/* Enable microphone buffer interrupts		*/
-#define INTE_ADCBUFENABLE	0x00000040	/* Enable ADC buffer interrupts			*/
-#define INTE_EFXBUFENABLE	0x00000020	/* Enable Effects buffer interrupts		*/
-#define INTE_GPSPDIFENABLE	0x00000010	/* Enable GPSPDIF status interrupts		*/
-#define INTE_CDSPDIFENABLE	0x00000008	/* Enable CDSPDIF status interrupts		*/
-#define INTE_INTERVALTIMERENB	0x00000004	/* Enable interval timer interrupts		*/
-#define INTE_MIDITXENABLE	0x00000002	/* Enable MIDI transmit-buffer-empty interrupts	*/
-#define INTE_MIDIRXENABLE	0x00000001	/* Enable MIDI receive-buffer-empty interrupts	*/
-
-/* The next two interrupts are for the midi port on the Audigy (A_MPU2)	*/
-#define A_INTE_MIDITXENABLE1  	INTE_MIDITXENABLE
-#define A_INTE_MIDIRXENABLE1	INTE_MIDIRXENABLE
-
-#define WC			0x10		/* Wall Clock register				*/
-#define WC_SAMPLECOUNTER_MASK	0x03FFFFC0	/* Sample periods elapsed since reset		*/
-#define WC_SAMPLECOUNTER	0x14060010
-#define WC_CURRENTCHANNEL	0x0000003F	/* Channel [0..63] currently being serviced	*/
-						/* NOTE: Each channel takes 1/64th of a sample	*/
-						/* period to be serviced.			*/
-
-#define HCFG			0x14		/* Hardware config register			*/
-						/* NOTE: There is no reason to use the legacy	*/
-						/* SoundBlaster emulation stuff described below	*/
-						/* under Linux, and all kinds of weird hardware	*/
-						/* behavior can result if you try.  Don't.	*/
-#define HCFG_LEGACYFUNC_MASK	0xe0000000	/* Legacy function number 			*/
-#define HCFG_LEGACYFUNC_MPU	0x00000000	/* Legacy MPU	 				*/
-#define HCFG_LEGACYFUNC_SB	0x40000000	/* Legacy SB					*/
-#define HCFG_LEGACYFUNC_AD	0x60000000	/* Legacy AD					*/
-#define HCFG_LEGACYFUNC_MPIC	0x80000000	/* Legacy MPIC					*/
-#define HCFG_LEGACYFUNC_MDMA	0xa0000000	/* Legacy MDMA					*/
-#define HCFG_LEGACYFUNC_SPCI	0xc0000000	/* Legacy SPCI					*/
-#define HCFG_LEGACYFUNC_SDMA	0xe0000000	/* Legacy SDMA					*/
-#define HCFG_IOCAPTUREADDR	0x1f000000	/* The 4 LSBs of the captured I/O address.	*/
-#define HCFG_LEGACYWRITE	0x00800000	/* 1 = write, 0 = read 				*/
-#define HCFG_LEGACYWORD		0x00400000	/* 1 = word, 0 = byte 				*/
-#define HCFG_LEGACYINT		0x00200000	/* 1 = legacy event captured. Write 1 to clear.	*/
-						/* NOTE: The rest of the bits in this register	*/
-						/* _are_ relevant under Linux.			*/
-#define HCFG_CODECFORMAT_MASK	0x00070000	/* CODEC format					*/
-#define HCFG_CODECFORMAT_AC97	0x00000000	/* AC97 CODEC format -- Primary Output		*/
-#define HCFG_CODECFORMAT_I2S	0x00010000	/* I2S CODEC format -- Secondary (Rear) Output	*/
-#define HCFG_GPINPUT0		0x00004000	/* External pin112				*/
-#define HCFG_GPINPUT1		0x00002000	/* External pin110				*/
-
-#define HCFG_GPOUTPUT_MASK	0x00001c00	/* External pins which may be controlled	*/
-#define HCFG_GPOUT0		0x00001000	/* set to enable digital out on 5.1 cards	*/
-
-#define HCFG_JOYENABLE      	0x00000200	/* Internal joystick enable    			*/
-#define HCFG_PHASETRACKENABLE	0x00000100	/* Phase tracking enable			*/
-						/* 1 = Force all 3 async digital inputs to use	*/
-						/* the same async sample rate tracker (ZVIDEO)	*/
-#define HCFG_AC3ENABLE_MASK	0x0x0000e0	/* AC3 async input control - Not implemented	*/
-#define HCFG_AC3ENABLE_ZVIDEO	0x00000080	/* Channels 0 and 1 replace ZVIDEO		*/
-#define HCFG_AC3ENABLE_CDSPDIF	0x00000040	/* Channels 0 and 1 replace CDSPDIF		*/
-#define HCFG_AC3ENABLE_GPSPDIF  0x00000020      /* Channels 0 and 1 replace GPSPDIF             */
-#define HCFG_AUTOMUTE		0x00000010	/* When set, the async sample rate convertors	*/
-						/* will automatically mute their output when	*/
-						/* they are not rate-locked to the external	*/
-						/* async audio source  				*/
-#define HCFG_LOCKSOUNDCACHE	0x00000008	/* 1 = Cancel bustmaster accesses to soundcache */
-						/* NOTE: This should generally never be used.  	*/
-#define HCFG_LOCKTANKCACHE_MASK	0x00000004	/* 1 = Cancel bustmaster accesses to tankcache	*/
-						/* NOTE: This should generally never be used.  	*/
-#define HCFG_LOCKTANKCACHE	0x01020014
-#define HCFG_MUTEBUTTONENABLE	0x00000002	/* 1 = Master mute button sets AUDIOENABLE = 0.	*/
-						/* NOTE: This is a 'cheap' way to implement a	*/
-						/* master mute function on the mute button, and	*/
-						/* in general should not be used unless a more	*/
-						/* sophisticated master mute function has not	*/
-						/* been written.       				*/
-#define HCFG_AUDIOENABLE	0x00000001	/* 0 = CODECs transmit zero-valued samples	*/
-						/* Should be set to 1 when the EMU10K1 is	*/
-						/* completely initialized.			*/
-
-//For Audigy, MPU port move to 0x70-0x74 ptr register
-
-#define MUDATA			0x18		/* MPU401 data register (8 bits)       		*/
-
-#define MUCMD			0x19		/* MPU401 command register (8 bits)    		*/
-#define MUCMD_RESET		0xff		/* RESET command				*/
-#define MUCMD_ENTERUARTMODE	0x3f		/* Enter_UART_mode command			*/
-						/* NOTE: All other commands are ignored		*/
-
-#define MUSTAT			MUCMD		/* MPU401 status register (8 bits)     		*/
-#define MUSTAT_IRDYN		0x80		/* 0 = MIDI data or command ACK			*/
-#define MUSTAT_ORDYN		0x40		/* 0 = MUDATA can accept a command or data	*/
-
-#define A_IOCFG			0x18		/* GPIO on Audigy card (16bits)			*/
-#define A_GPINPUT_MASK		0xff00
-#define A_GPOUTPUT_MASK		0x00ff
-
-#define TIMER			0x1a		/* Timer terminal count register (16-bit)	*/
-						/* NOTE: After the rate is changed, a maximum	*/
-						/* of 1024 sample periods should be allowed	*/
-						/* before the new rate is guaranteed accurate.	*/
-#define TIMER_RATE_MASK		0x03ff		/* Timer interrupt rate in sample periods	*/
-						/* 0 == 1024 periods, [1..4] are not useful	*/
-
-#define AC97DATA		0x1c		/* AC97 register set data register (16 bit)	*/
-
-#define AC97ADDRESS		0x1e		/* AC97 register set address register (8 bit)	*/
-#define AC97ADDRESS_READY	0x80		/* Read-only bit, reflects CODEC READY signal	*/
-#define AC97ADDRESS_ADDRESS	0x7f		/* Address of indexed AC97 register		*/
-
-/********************************************************************************************************/
-/* Emu10k1 pointer-offset register set, accessed through the PTR and DATA registers			*/
-/********************************************************************************************************/
-
-#define CPF			0x00		/* Current pitch and fraction register			*/
-#define CPF_CURRENTPITCH_MASK	0xffff0000	/* Current pitch (linear, 0x4000 == unity pitch shift) 	*/
-#define CPF_CURRENTPITCH	0x10100000
-#define CPF_STEREO_MASK		0x00008000	/* 1 = Even channel interleave, odd channel locked	*/
-#define CPF_STOP_MASK		0x00004000	/* 1 = Current pitch forced to 0			*/
-#define CPF_FRACADDRESS_MASK	0x00003fff	/* Linear fractional address of the current channel	*/
-
-#define PTRX			0x01		/* Pitch target and send A/B amounts register		*/
-#define PTRX_PITCHTARGET_MASK	0xffff0000	/* Pitch target of specified channel			*/
-#define PTRX_PITCHTARGET	0x10100001
-#define PTRX_FXSENDAMOUNT_A_MASK 0x0000ff00	/* Linear level of channel output sent to FX send bus A	*/
-#define PTRX_FXSENDAMOUNT_A	0x08080001
-#define PTRX_FXSENDAMOUNT_B_MASK 0x000000ff	/* Linear level of channel output sent to FX send bus B	*/
-#define PTRX_FXSENDAMOUNT_B	0x08000001
-
-#define CVCF			0x02		/* Current volume and filter cutoff register		*/
-#define CVCF_CURRENTVOL_MASK	0xffff0000	/* Current linear volume of specified channel		*/
-#define CVCF_CURRENTVOL		0x10100002
-#define CVCF_CURRENTFILTER_MASK	0x0000ffff	/* Current filter cutoff frequency of specified channel	*/
-#define CVCF_CURRENTFILTER	0x10000002
-
-#define VTFT			0x03		/* Volume target and filter cutoff target register	*/
-#define VTFT_VOLUMETARGET_MASK	0xffff0000	/* Volume target of specified channel			*/
-#define VTFT_FILTERTARGET_MASK	0x0000ffff	/* Filter cutoff target of specified channel		*/
-
-#define Z1			0x05		/* Filter delay memory 1 register			*/
-
-#define Z2			0x04		/* Filter delay memory 2 register			*/
-
-#define PSST			0x06		/* Send C amount and loop start address register	*/
-#define PSST_FXSENDAMOUNT_C_MASK 0xff000000	/* Linear level of channel output sent to FX send bus C	*/
-
-#define PSST_FXSENDAMOUNT_C	0x08180006
-
-#define PSST_LOOPSTARTADDR_MASK	0x00ffffff	/* Loop start address of the specified channel		*/
-#define PSST_LOOPSTARTADDR	0x18000006
-
-#define DSL			0x07		/* Send D amount and loop start address register	*/
-#define DSL_FXSENDAMOUNT_D_MASK	0xff000000	/* Linear level of channel output sent to FX send bus D	*/
-
-#define DSL_FXSENDAMOUNT_D	0x08180007
-
-#define DSL_LOOPENDADDR_MASK	0x00ffffff	/* Loop end address of the specified channel		*/
-#define DSL_LOOPENDADDR		0x18000007
-
-#define CCCA			0x08		/* Filter Q, interp. ROM, byte size, cur. addr register */
-#define CCCA_RESONANCE		0xf0000000	/* Lowpass filter resonance (Q) height			*/
-#define CCCA_INTERPROMMASK	0x0e000000	/* Selects passband of interpolation ROM		*/
-						/* 1 == full band, 7 == lowpass				*/
-						/* ROM 0 is used when pitch shifting downward or less	*/
-						/* then 3 semitones upward.  Increasingly higher ROM	*/
-						/* numbers are used, typically in steps of 3 semitones,	*/
-						/* as upward pitch shifting is performed.		*/
-#define CCCA_INTERPROM_0	0x00000000	/* Select interpolation ROM 0				*/
-#define CCCA_INTERPROM_1	0x02000000	/* Select interpolation ROM 1				*/
-#define CCCA_INTERPROM_2	0x04000000	/* Select interpolation ROM 2				*/
-#define CCCA_INTERPROM_3	0x06000000	/* Select interpolation ROM 3				*/
-#define CCCA_INTERPROM_4	0x08000000	/* Select interpolation ROM 4				*/
-#define CCCA_INTERPROM_5	0x0a000000	/* Select interpolation ROM 5				*/
-#define CCCA_INTERPROM_6	0x0c000000	/* Select interpolation ROM 6				*/
-#define CCCA_INTERPROM_7	0x0e000000	/* Select interpolation ROM 7				*/
-#define CCCA_8BITSELECT		0x01000000	/* 1 = Sound memory for this channel uses 8-bit samples	*/
-#define CCCA_CURRADDR_MASK	0x00ffffff	/* Current address of the selected channel		*/
-#define CCCA_CURRADDR		0x18000008
-
-#define CCR			0x09		/* Cache control register				*/
-#define CCR_CACHEINVALIDSIZE	0x07190009
-#define CCR_CACHEINVALIDSIZE_MASK	0xfe000000	/* Number of invalid samples cache for this channel    	*/
-#define CCR_CACHELOOPFLAG	0x01000000	/* 1 = Cache has a loop service pending			*/
-#define CCR_INTERLEAVEDSAMPLES	0x00800000	/* 1 = A cache service will fetch interleaved samples	*/
-#define CCR_WORDSIZEDSAMPLES	0x00400000	/* 1 = A cache service will fetch word sized samples	*/
-#define CCR_READADDRESS		0x06100009
-#define CCR_READADDRESS_MASK	0x003f0000	/* Location of cache just beyond current cache service	*/
-#define CCR_LOOPINVALSIZE	0x0000fe00	/* Number of invalid samples in cache prior to loop	*/
-						/* NOTE: This is valid only if CACHELOOPFLAG is set	*/
-#define CCR_LOOPFLAG		0x00000100	/* Set for a single sample period when a loop occurs	*/
-#define CCR_CACHELOOPADDRHI	0x000000ff	/* DSL_LOOPSTARTADDR's hi byte if CACHELOOPFLAG is set	*/
-
-#define CLP			0x0a		/* Cache loop register (valid if CCR_CACHELOOPFLAG = 1) */
-						/* NOTE: This register is normally not used		*/
-#define CLP_CACHELOOPADDR	0x0000ffff	/* Cache loop address (DSL_LOOPSTARTADDR [0..15])	*/
-
-#define FXRT			0x0b		/* Effects send routing register			*/
-						/* NOTE: It is illegal to assign the same routing to	*/
-						/* two effects sends.					*/
-#define FXRT_CHANNELA		0x000f0000	/* Effects send bus number for channel's effects send A	*/
-#define FXRT_CHANNELB		0x00f00000	/* Effects send bus number for channel's effects send B	*/
-#define FXRT_CHANNELC		0x0f000000	/* Effects send bus number for channel's effects send C	*/
-#define FXRT_CHANNELD		0xf0000000	/* Effects send bus number for channel's effects send D	*/
-
-#define MAPA			0x0c		/* Cache map A						*/
-
-#define MAPB			0x0d		/* Cache map B						*/
-
-#define MAP_PTE_MASK		0xffffe000	/* The 19 MSBs of the PTE indexed by the PTI		*/
-#define MAP_PTI_MASK		0x00001fff	/* The 13 bit index to one of the 8192 PTE dwords      	*/
-
-#define ENVVOL			0x10		/* Volume envelope register				*/
-#define ENVVOL_MASK		0x0000ffff	/* Current value of volume envelope state variable	*/  
-						/* 0x8000-n == 666*n usec delay	       			*/
-
-#define ATKHLDV 		0x11		/* Volume envelope hold and attack register		*/
-#define ATKHLDV_PHASE0		0x00008000	/* 0 = Begin attack phase				*/
-#define ATKHLDV_HOLDTIME_MASK	0x00007f00	/* Envelope hold time (127-n == n*88.2msec)		*/
-#define ATKHLDV_ATTACKTIME_MASK	0x0000007f	/* Envelope attack time, log encoded			*/
-						/* 0 = infinite, 1 = 10.9msec, ... 0x7f = 5.5msec	*/
-
-#define DCYSUSV 		0x12		/* Volume envelope sustain and decay register		*/
-#define DCYSUSV_PHASE1_MASK	0x00008000	/* 0 = Begin attack phase, 1 = begin release phase	*/
-#define DCYSUSV_SUSTAINLEVEL_MASK 0x00007f00	/* 127 = full, 0 = off, 0.75dB increments		*/
-#define DCYSUSV_CHANNELENABLE_MASK 0x00000080	/* 1 = Inhibit envelope engine from writing values in	*/
-						/* this channel and from writing to pitch, filter and	*/
-						/* volume targets.					*/
-#define DCYSUSV_DECAYTIME_MASK	0x0000007f	/* Volume envelope decay time, log encoded     		*/
-						/* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec		*/
-
-#define LFOVAL1 		0x13		/* Modulation LFO value					*/
-#define LFOVAL_MASK		0x0000ffff	/* Current value of modulation LFO state variable	*/
-						/* 0x8000-n == 666*n usec delay				*/
-
-#define ENVVAL			0x14		/* Modulation envelope register				*/
-#define ENVVAL_MASK		0x0000ffff	/* Current value of modulation envelope state variable 	*/
-						/* 0x8000-n == 666*n usec delay				*/
-
-#define ATKHLDM			0x15		/* Modulation envelope hold and attack register		*/
-#define ATKHLDM_PHASE0		0x00008000	/* 0 = Begin attack phase				*/
-#define ATKHLDM_HOLDTIME	0x00007f00	/* Envelope hold time (127-n == n*42msec)		*/
-#define ATKHLDM_ATTACKTIME	0x0000007f	/* Envelope attack time, log encoded			*/
-						/* 0 = infinite, 1 = 11msec, ... 0x7f = 5.5msec		*/
-
-#define DCYSUSM			0x16		/* Modulation envelope decay and sustain register	*/
-#define DCYSUSM_PHASE1_MASK	0x00008000	/* 0 = Begin attack phase, 1 = begin release phase	*/
-#define DCYSUSM_SUSTAINLEVEL_MASK 0x00007f00	/* 127 = full, 0 = off, 0.75dB increments		*/
-#define DCYSUSM_DECAYTIME_MASK	0x0000007f	/* Envelope decay time, log encoded			*/
-						/* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec		*/
-
-#define LFOVAL2 		0x17		/* Vibrato LFO register					*/
-#define LFOVAL2_MASK		0x0000ffff	/* Current value of vibrato LFO state variable 		*/
-						/* 0x8000-n == 666*n usec delay				*/
-
-#define IP			0x18		/* Initial pitch register				*/
-#define IP_MASK			0x0000ffff	/* Exponential initial pitch shift			*/
-						/* 4 bits of octave, 12 bits of fractional octave	*/
-#define IP_UNITY		0x0000e000	/* Unity pitch shift					*/
-
-#define IFATN			0x19		/* Initial filter cutoff and attenuation register	*/
-#define IFATN_FILTERCUTOFF_MASK	0x0000ff00	/* Initial filter cutoff frequency in exponential units	*/
-						/* 6 most significant bits are semitones		*/
-						/* 2 least significant bits are fractions		*/
-#define IFATN_FILTERCUTOFF	0x08080019
-#define IFATN_ATTENUATION_MASK	0x000000ff	/* Initial attenuation in 0.375dB steps			*/
-#define IFATN_ATTENUATION	0x08000019
-
-
-#define PEFE			0x1a		/* Pitch envelope and filter envelope amount register	*/
-#define PEFE_PITCHAMOUNT_MASK	0x0000ff00	/* Pitch envlope amount					*/
-						/* Signed 2's complement, +/- one octave peak extremes	*/
-#define PEFE_PITCHAMOUNT	0x0808001a
-#define PEFE_FILTERAMOUNT_MASK	0x000000ff	/* Filter envlope amount				*/
-						/* Signed 2's complement, +/- six octaves peak extremes */
-#define PEFE_FILTERAMOUNT	0x0800001a
-#define FMMOD			0x1b		/* Vibrato/filter modulation from LFO register		*/
-#define FMMOD_MODVIBRATO	0x0000ff00	/* Vibrato LFO modulation depth				*/
-						/* Signed 2's complement, +/- one octave extremes	*/
-#define FMMOD_MOFILTER		0x000000ff	/* Filter LFO modulation depth				*/
-						/* Signed 2's complement, +/- three octave extremes	*/
-
-
-#define TREMFRQ 		0x1c		/* Tremolo amount and modulation LFO frequency register	*/
-#define TREMFRQ_DEPTH		0x0000ff00	/* Tremolo depth					*/
-						/* Signed 2's complement, with +/- 12dB extremes	*/
-#define TREMFRQ_FREQUENCY	0x000000ff	/* Tremolo LFO frequency				*/
-						/* ??Hz steps, maximum of ?? Hz.			*/
-
-#define FM2FRQ2 		0x1d		/* Vibrato amount and vibrato LFO frequency register	*/
-#define FM2FRQ2_DEPTH		0x0000ff00	/* Vibrato LFO vibrato depth				*/
-						/* Signed 2's complement, +/- one octave extremes	*/
-#define FM2FRQ2_FREQUENCY	0x000000ff	/* Vibrato LFO frequency				*/
-						/* 0.039Hz steps, maximum of 9.85 Hz.			*/
-
-#define TEMPENV 		0x1e		/* Tempory envelope register				*/
-#define TEMPENV_MASK		0x0000ffff	/* 16-bit value						*/
-						/* NOTE: All channels contain internal variables; do	*/
-						/* not write to these locations.			*/
-
-#define CD0			0x20		/* Cache data 0 register				*/
-#define CD1			0x21		/* Cache data 1 register				*/
-#define CD2			0x22		/* Cache data 2 register				*/
-#define CD3			0x23		/* Cache data 3 register				*/
-#define CD4			0x24		/* Cache data 4 register				*/
-#define CD5			0x25		/* Cache data 5 register				*/
-#define CD6			0x26		/* Cache data 6 register				*/
-#define CD7			0x27		/* Cache data 7 register				*/
-#define CD8			0x28		/* Cache data 8 register				*/
-#define CD9			0x29		/* Cache data 9 register				*/
-#define CDA			0x2a		/* Cache data A register				*/
-#define CDB			0x2b		/* Cache data B register				*/
-#define CDC			0x2c		/* Cache data C register				*/
-#define CDD			0x2d		/* Cache data D register				*/
-#define CDE			0x2e		/* Cache data E register				*/
-#define CDF			0x2f		/* Cache data F register				*/
-
-#define PTB			0x40		/* Page table base register				*/
-#define PTB_MASK		0xfffff000	/* Physical address of the page table in host memory	*/
-
-#define TCB			0x41		/* Tank cache base register    				*/
-#define TCB_MASK		0xfffff000	/* Physical address of the bottom of host based TRAM	*/
-
-#define ADCCR			0x42		/* ADC sample rate/stereo control register		*/
-#define ADCCR_RCHANENABLE	0x00000010	/* Enables right channel for writing to the host       	*/
-#define ADCCR_LCHANENABLE	0x00000008	/* Enables left channel for writing to the host		*/
-						/* NOTE: To guarantee phase coherency, both channels	*/
-						/* must be disabled prior to enabling both channels.	*/
-#define A_ADCCR_RCHANENABLE	0x00000020
-#define A_ADCCR_LCHANENABLE	0x00000010
-
-#define A_ADCCR_SAMPLERATE_MASK 0x0000000F      /* Audigy sample rate convertor output rate		*/
-#define ADCCR_SAMPLERATE_MASK	0x00000007	/* Sample rate convertor output rate			*/
-
-#define ADCCR_SAMPLERATE_48	0x00000000	/* 48kHz sample rate					*/
-#define ADCCR_SAMPLERATE_44	0x00000001	/* 44.1kHz sample rate					*/
-#define ADCCR_SAMPLERATE_32	0x00000002	/* 32kHz sample rate					*/
-#define ADCCR_SAMPLERATE_24	0x00000003	/* 24kHz sample rate					*/
-#define ADCCR_SAMPLERATE_22	0x00000004	/* 22.05kHz sample rate					*/
-#define ADCCR_SAMPLERATE_16	0x00000005	/* 16kHz sample rate					*/
-#define ADCCR_SAMPLERATE_11	0x00000006	/* 11.025kHz sample rate				*/
-#define ADCCR_SAMPLERATE_8	0x00000007	/* 8kHz sample rate					*/
-
-#define A_ADCCR_SAMPLERATE_12	0x00000006	/* 12kHz sample rate					*/
-#define A_ADCCR_SAMPLERATE_11	0x00000007	/* 11.025kHz sample rate				*/
-#define A_ADCCR_SAMPLERATE_8	0x00000008	/* 8kHz sample rate					*/
-
-#define FXWC			0x43		/* FX output write channels register			*/
-						/* When set, each bit enables the writing of the	*/
-						/* corresponding FX output channel (internal registers  */
-						/* 0x20-0x3f) into host memory. This mode of recording	*/
-						/* is 16bit, 48KHz only. All 32	channels can be enabled */
-						/* simultaneously.					*/
-#define TCBS			0x44		/* Tank cache buffer size register			*/
-#define TCBS_MASK		0x00000007	/* Tank cache buffer size field				*/
-#define TCBS_BUFFSIZE_16K	0x00000000
-#define TCBS_BUFFSIZE_32K	0x00000001
-#define TCBS_BUFFSIZE_64K	0x00000002
-#define TCBS_BUFFSIZE_128K	0x00000003
-#define TCBS_BUFFSIZE_256K	0x00000004
-#define TCBS_BUFFSIZE_512K	0x00000005
-#define TCBS_BUFFSIZE_1024K	0x00000006
-#define TCBS_BUFFSIZE_2048K	0x00000007
-
-#define MICBA			0x45		/* AC97 microphone buffer address register		*/
-#define MICBA_MASK		0xfffff000	/* 20 bit base address					*/
-
-#define ADCBA			0x46		/* ADC buffer address register				*/
-#define ADCBA_MASK		0xfffff000	/* 20 bit base address					*/
-
-#define FXBA			0x47		/* FX Buffer Address */
-#define FXBA_MASK		0xfffff000	/* 20 bit base address					*/
-
-#define MICBS			0x49		/* Microphone buffer size register			*/
-
-#define ADCBS			0x4a		/* ADC buffer size register				*/
-
-#define FXBS			0x4b		/* FX buffer size register				*/
-
-/* The following mask values define the size of the ADC, MIX and FX buffers in bytes */
-#define ADCBS_BUFSIZE_NONE	0x00000000
-#define ADCBS_BUFSIZE_384	0x00000001
-#define ADCBS_BUFSIZE_448	0x00000002
-#define ADCBS_BUFSIZE_512	0x00000003
-#define ADCBS_BUFSIZE_640	0x00000004
-#define ADCBS_BUFSIZE_768	0x00000005
-#define ADCBS_BUFSIZE_896	0x00000006
-#define ADCBS_BUFSIZE_1024	0x00000007
-#define ADCBS_BUFSIZE_1280	0x00000008
-#define ADCBS_BUFSIZE_1536	0x00000009
-#define ADCBS_BUFSIZE_1792	0x0000000a
-#define ADCBS_BUFSIZE_2048	0x0000000b
-#define ADCBS_BUFSIZE_2560	0x0000000c
-#define ADCBS_BUFSIZE_3072	0x0000000d
-#define ADCBS_BUFSIZE_3584	0x0000000e
-#define ADCBS_BUFSIZE_4096	0x0000000f
-#define ADCBS_BUFSIZE_5120	0x00000010
-#define ADCBS_BUFSIZE_6144	0x00000011
-#define ADCBS_BUFSIZE_7168	0x00000012
-#define ADCBS_BUFSIZE_8192	0x00000013
-#define ADCBS_BUFSIZE_10240	0x00000014
-#define ADCBS_BUFSIZE_12288	0x00000015
-#define ADCBS_BUFSIZE_14366	0x00000016
-#define ADCBS_BUFSIZE_16384	0x00000017
-#define ADCBS_BUFSIZE_20480	0x00000018
-#define ADCBS_BUFSIZE_24576	0x00000019
-#define ADCBS_BUFSIZE_28672	0x0000001a
-#define ADCBS_BUFSIZE_32768	0x0000001b
-#define ADCBS_BUFSIZE_40960	0x0000001c
-#define ADCBS_BUFSIZE_49152	0x0000001d
-#define ADCBS_BUFSIZE_57344	0x0000001e
-#define ADCBS_BUFSIZE_65536	0x0000001f
-
-
-#define CDCS			0x50		/* CD-ROM digital channel status register	*/
-
-#define GPSCS			0x51		/* General Purpose SPDIF channel status register*/
-
-#define DBG			0x52		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
-
-/* definitions for debug register - taken from the alsa drivers */
-#define DBG_ZC                  0x80000000      /* zero tram counter */
-#define DBG_SATURATION_OCCURED  0x02000000      /* saturation control */
-#define DBG_SATURATION_ADDR     0x01ff0000      /* saturation address */
-#define DBG_SINGLE_STEP         0x00008000      /* single step mode */
-#define DBG_STEP                0x00004000      /* start single step */
-#define DBG_CONDITION_CODE      0x00003e00      /* condition code */
-#define DBG_SINGLE_STEP_ADDR    0x000001ff      /* single step address */
-
-
-#define REG53			0x53		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
-
-#define A_DBG			 0x53
-#define A_DBG_SINGLE_STEP	 0x00020000	/* Set to zero to start dsp */
-#define A_DBG_ZC		 0x40000000	/* zero tram counter */
-#define A_DBG_STEP_ADDR		 0x000003ff
-#define A_DBG_SATURATION_OCCURED 0x20000000
-#define A_DBG_SATURATION_ADDR	 0x0ffc0000
-
-#define SPCS0			0x54		/* SPDIF output Channel Status 0 register	*/
-
-#define SPCS1			0x55		/* SPDIF output Channel Status 1 register	*/
-
-#define SPCS2			0x56		/* SPDIF output Channel Status 2 register	*/
-
-#define SPCS_CLKACCYMASK	0x30000000	/* Clock accuracy				*/
-#define SPCS_CLKACCY_1000PPM	0x00000000	/* 1000 parts per million			*/
-#define SPCS_CLKACCY_50PPM	0x10000000	/* 50 parts per million				*/
-#define SPCS_CLKACCY_VARIABLE	0x20000000	/* Variable accuracy				*/
-#define SPCS_SAMPLERATEMASK	0x0f000000	/* Sample rate					*/
-#define SPCS_SAMPLERATE_44	0x00000000	/* 44.1kHz sample rate				*/
-#define SPCS_SAMPLERATE_48	0x02000000	/* 48kHz sample rate				*/
-#define SPCS_SAMPLERATE_32	0x03000000	/* 32kHz sample rate				*/
-#define SPCS_CHANNELNUMMASK	0x00f00000	/* Channel number				*/
-#define SPCS_CHANNELNUM_UNSPEC	0x00000000	/* Unspecified channel number			*/
-#define SPCS_CHANNELNUM_LEFT	0x00100000	/* Left channel					*/
-#define SPCS_CHANNELNUM_RIGHT	0x00200000	/* Right channel				*/
-#define SPCS_SOURCENUMMASK	0x000f0000	/* Source number				*/
-#define SPCS_SOURCENUM_UNSPEC	0x00000000	/* Unspecified source number			*/
-#define SPCS_GENERATIONSTATUS	0x00008000	/* Originality flag (see IEC-958 spec)		*/
-#define SPCS_CATEGORYCODEMASK	0x00007f00	/* Category code (see IEC-958 spec)		*/
-#define SPCS_MODEMASK		0x000000c0	/* Mode (see IEC-958 spec)			*/
-#define SPCS_EMPHASISMASK	0x00000038	/* Emphasis					*/
-#define SPCS_EMPHASIS_NONE	0x00000000	/* No emphasis					*/
-#define SPCS_EMPHASIS_50_15	0x00000008	/* 50/15 usec 2 channel				*/
-#define SPCS_COPYRIGHT		0x00000004	/* Copyright asserted flag -- do not modify	*/
-#define SPCS_NOTAUDIODATA	0x00000002	/* 0 = Digital audio, 1 = not audio		*/
-#define SPCS_PROFESSIONAL	0x00000001	/* 0 = Consumer (IEC-958), 1 = pro (AES3-1992)	*/
-
-/* The 32-bit CLIx and SOLx registers all have one bit per channel control/status      		*/
-#define CLIEL			0x58		/* Channel loop interrupt enable low register	*/
-
-#define CLIEH			0x59		/* Channel loop interrupt enable high register	*/
-
-#define CLIPL			0x5a		/* Channel loop interrupt pending low register	*/
-
-#define CLIPH			0x5b		/* Channel loop interrupt pending high register	*/
-
-#define SOLEL			0x5c		/* Stop on loop enable low register		*/
-
-#define SOLEH			0x5d		/* Stop on loop enable high register		*/
-
-#define SPBYPASS		0x5e		/* SPDIF BYPASS mode register			*/
-#define SPBYPASS_ENABLE		0x00000001	/* Enable SPDIF bypass mode			*/
-
-#define AC97SLOT		0x5f		/* additional AC97 slots enable bits */
-#define AC97SLOT_CNTR		0x10		/* Center enable */
-#define AC97SLOT_LFE		0x20		/* LFE enable */
-
-#define CDSRCS			0x60		/* CD-ROM Sample Rate Converter status register	*/
-
-#define GPSRCS			0x61		/* General Purpose SPDIF sample rate cvt status */
-
-#define ZVSRCS			0x62		/* ZVideo sample rate converter status		*/
-						/* NOTE: This one has no SPDIFLOCKED field	*/
-						/* Assumes sample lock				*/
-
-/* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS.			*/
-#define SRCS_SPDIFLOCKED	0x02000000	/* SPDIF stream locked				*/
-#define SRCS_RATELOCKED		0x01000000	/* Sample rate locked				*/
-#define SRCS_ESTSAMPLERATE	0x0007ffff	/* Do not modify this field.			*/
-
-
-/* Note that these values can vary +/- by a small amount                                        */
-#define SRCS_SPDIFRATE_44	0x0003acd9
-#define SRCS_SPDIFRATE_48	0x00040000
-#define SRCS_SPDIFRATE_96	0x00080000
-
-#define MICIDX                  0x63            /* Microphone recording buffer index register   */
-#define MICIDX_MASK             0x0000ffff      /* 16-bit value                                 */
-#define MICIDX_IDX		0x10000063
-
-#define A_ADCIDX		0x63
-#define A_ADCIDX_IDX		0x10000063
-
-#define ADCIDX			0x64		/* ADC recording buffer index register		*/
-#define ADCIDX_MASK		0x0000ffff	/* 16 bit index field				*/
-#define ADCIDX_IDX		0x10000064
-
-#define FXIDX			0x65		/* FX recording buffer index register		*/
-#define FXIDX_MASK		0x0000ffff	/* 16-bit value					*/
-#define FXIDX_IDX		0x10000065
-
-/* This is the MPU port on the card (via the game port)						*/
-#define A_MUDATA1		0x70
-#define A_MUCMD1		0x71
-#define A_MUSTAT1		A_MUCMD1
-
-/* This is the MPU port on the Audigy Drive 							*/
-#define A_MUDATA2		0x72
-#define A_MUCMD2		0x73
-#define A_MUSTAT2		A_MUCMD2	
-
-/* The next two are the Audigy equivalent of FXWC						*/
-/* the Audigy can record any output (16bit, 48kHz, up to 64 channel simultaneously) 		*/
-/* Each bit selects a channel for recording */
-#define A_FXWC1			0x74            /* Selects 0x7f-0x60 for FX recording           */
-#define A_FXWC2			0x75		/* Selects 0x9f-0x80 for FX recording           */
-
-#define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
-#define A_SPDIF_48000		0x00000080
-#define A_SPDIF_44100		0x00000000
-#define A_SPDIF_96000		0x00000040
-
-#define A_FXRT2			0x7c
-#define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
-#define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send F	*/
-#define A_FXRT_CHANNELG		0x003f0000	/* Effects send bus number for channel's effects send G	*/
-#define A_FXRT_CHANNELH		0x3f000000	/* Effects send bus number for channel's effects send H	*/
-
-#define A_SENDAMOUNTS		0x7d
-#define A_FXSENDAMOUNT_E_MASK	0xff000000
-#define A_FXSENDAMOUNT_F_MASK	0x00ff0000
-#define A_FXSENDAMOUNT_G_MASK	0x0000ff00
-#define A_FXSENDAMOUNT_H_MASK	0x000000ff
-
-/* The send amounts for this one are the same as used with the emu10k1 */
-#define A_FXRT1			0x7e
-#define A_FXRT_CHANNELA		0x0000003f
-#define A_FXRT_CHANNELB		0x00003f00
-#define A_FXRT_CHANNELC		0x003f0000
-#define A_FXRT_CHANNELD		0x3f000000
-
-
-/* Each FX general purpose register is 32 bits in length, all bits are used			*/
-#define FXGPREGBASE		0x100		/* FX general purpose registers base       	*/
-#define A_FXGPREGBASE		0x400		/* Audigy GPRs, 0x400 to 0x5ff			*/
-/* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is	*/
-/* decompressed back to 20 bits on a read.  There are a total of 160 locations, the last 32	*/
-/* locations are for external TRAM. 								*/
-#define TANKMEMDATAREGBASE	0x200		/* Tank memory data registers base     		*/
-#define TANKMEMDATAREG_MASK	0x000fffff	/* 20 bit tank audio data field			*/
-
-/* Combined address field and memory opcode or flag field.  160 locations, last 32 are external	*/
-#define TANKMEMADDRREGBASE	0x300		/* Tank memory address registers base		*/
-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff	/* 20 bit tank address field			*/
-#define TANKMEMADDRREG_CLEAR	0x00800000	/* Clear tank memory				*/
-#define TANKMEMADDRREG_ALIGN	0x00400000	/* Align read or write relative to tank access	*/
-#define TANKMEMADDRREG_WRITE	0x00200000	/* Write to tank memory				*/
-#define TANKMEMADDRREG_READ	0x00100000	/* Read from tank memory			*/
-
-#define MICROCODEBASE		0x400		/* Microcode data base address			*/
-
-/* Each DSP microcode instruction is mapped into 2 doublewords 					*/
-/* NOTE: When writing, always write the LO doubleword first.  Reads can be in either order.	*/
-#define LOWORD_OPX_MASK		0x000ffc00	/* Instruction operand X			*/
-#define LOWORD_OPY_MASK		0x000003ff	/* Instruction operand Y			*/
-#define HIWORD_OPCODE_MASK	0x00f00000	/* Instruction opcode				*/
-#define HIWORD_RESULT_MASK	0x000ffc00	/* Instruction result				*/
-#define HIWORD_OPA_MASK		0x000003ff	/* Instruction operand A			*/
-
-
-/* Audigy Soundcard have a different instruction format */
-#define AUDIGY_CODEBASE		0x600
-#define A_LOWORD_OPY_MASK	0x000007ff		
-#define A_LOWORD_OPX_MASK	0x007ff000
-#define A_HIWORD_OPCODE_MASK	0x0f000000
-#define A_HIWORD_RESULT_MASK	0x007ff000
-#define A_HIWORD_OPA_MASK	0x000007ff
-
-
-#endif /* _8010_H */
diff --git a/sound/oss/emu10k1/Makefile b/sound/oss/emu10k1/Makefile
deleted file mode 100644
index b3af9cc..0000000
--- a/sound/oss/emu10k1/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Makefile for Creative Labs EMU10K1 
-#
-# 12 Apr 2000 Rui Sousa
-
-obj-$(CONFIG_SOUND_EMU10K1) += emu10k1.o
-
-emu10k1-objs := audio.o cardmi.o cardmo.o cardwi.o cardwo.o ecard.o \
-                efxmgr.o emuadxmg.o hwaccess.o irqmgr.o main.o midi.o \
-                mixer.o passthrough.o recmgr.o timer.o voicemgr.o
-
-ifdef DEBUG
-    EXTRA_CFLAGS += -DEMU10K1_DEBUG
-endif
-
-ifdef CONFIG_MIDI_EMU10K1
-    EXTRA_CFLAGS += -DEMU10K1_SEQUENCER
-endif
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
deleted file mode 100644
index e75ea21..0000000
--- a/sound/oss/emu10k1/audio.c
+++ /dev/null
@@ -1,1595 +0,0 @@
-/*
- **********************************************************************
- *     audio.c -- /dev/dsp interface for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999	    Alan Cox        cleaned up types/leaks
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-
-#include "hwaccess.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "recmgr.h"
-#include "irqmgr.h"
-#include "audio.h"
-#include "8010.h"
-
-static void calculate_ofrag(struct woinst *);
-static void calculate_ifrag(struct wiinst *);
-
-static void emu10k1_waveout_bh(unsigned long refdata);
-static void emu10k1_wavein_bh(unsigned long refdata);
-
-/* Audio file operations */
-static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	ssize_t ret = 0;
-	unsigned long flags;
-
-	DPD(3, "emu10k1_audio_read(), buffer=%p, count=%d\n", buffer, (u32) count);
-
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-
-	spin_lock_irqsave(&wiinst->lock, flags);
-
-	if (wiinst->mmapped) {
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-		return -ENXIO;
-	}
-
-	if (wiinst->state == WAVE_STATE_CLOSED) {
-		calculate_ifrag(wiinst);
-
-		while (emu10k1_wavein_open(wave_dev) < 0) {
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-
-			if (file->f_flags & O_NONBLOCK)
-				return -EAGAIN;
-
-			interruptible_sleep_on(&wave_dev->card->open_wait);
-
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			spin_lock_irqsave(&wiinst->lock, flags);
-		}
-	}
-
-	spin_unlock_irqrestore(&wiinst->lock, flags);
-
-	while (count > 0) {
-		u32 bytestocopy;
-
-		spin_lock_irqsave(&wiinst->lock, flags);
-
-		if (!(wiinst->state & WAVE_STATE_STARTED)
-		    && (wave_dev->enablebits & PCM_ENABLE_INPUT))
-			emu10k1_wavein_start(wave_dev);
-
-		emu10k1_wavein_update(wave_dev->card, wiinst);
-		emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-
-		DPD(3, "bytestocopy --> %d\n", bytestocopy);
-
-		if ((bytestocopy >= wiinst->buffer.fragment_size)
-		    || (bytestocopy >= count)) {
-			int rc;
-
-			bytestocopy = min_t(u32, bytestocopy, count);
-
-			rc = emu10k1_wavein_xferdata(wiinst,
-						     (u8 __user *)buffer,
-						     &bytestocopy);
-			if (rc)
-				return rc;
-
-			count -= bytestocopy;
-			buffer += bytestocopy;
-			ret += bytestocopy;
-		}
-
-		if (count > 0) {
-			if ((file->f_flags & O_NONBLOCK)
-			    || (!(wave_dev->enablebits & PCM_ENABLE_INPUT)))
-				return (ret ? ret : -EAGAIN);
-
-			interruptible_sleep_on(&wiinst->wait_queue);
-
-			if (signal_pending(current))
-				return (ret ? ret : -ERESTARTSYS);
-
-		}
-	}
-
-	DPD(3, "bytes copied -> %d\n", (u32) ret);
-
-	return ret;
-}
-
-static ssize_t emu10k1_audio_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct woinst *woinst = wave_dev->woinst;
-	ssize_t ret;
-	unsigned long flags;
-
-	DPD(3, "emu10k1_audio_write(), buffer=%p, count=%d\n", buffer, (u32) count);
-
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-
-	spin_lock_irqsave(&woinst->lock, flags);
-
-	if (woinst->mmapped) {
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		return -ENXIO;
-	}
-	// This is for emu10k1 revs less than 7, we need to go through tram
-	if (woinst->format.passthrough == 1) {
-		int r;
-		
-		woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2;
-		woinst->buffer.numfrags = PT_BLOCKCOUNT;
-		calculate_ofrag(woinst);
-		
-		r = emu10k1_pt_write(file, buffer, count);
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		return r;
-	}
-
-	if (woinst->state == WAVE_STATE_CLOSED) {
-		calculate_ofrag(woinst);
-
-		while (emu10k1_waveout_open(wave_dev) < 0) {
-			spin_unlock_irqrestore(&woinst->lock, flags);
-
-			if (file->f_flags & O_NONBLOCK)
-				return -EAGAIN;
-
-			interruptible_sleep_on(&wave_dev->card->open_wait);
-
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-		}
-	}
-
-	spin_unlock_irqrestore(&woinst->lock, flags);
-
-	ret = 0;
-	if (count % woinst->format.bytespersample)
-                return -EINVAL;
-
-	count /= woinst->num_voices;
-
-	while (count > 0) {
-		u32 bytestocopy;
-
-		spin_lock_irqsave(&woinst->lock, flags);
-		emu10k1_waveout_update(woinst);
-		emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-		spin_unlock_irqrestore(&woinst->lock, flags);
-
-		DPD(3, "bytestocopy --> %d\n", bytestocopy);
-
-		if ((bytestocopy >= woinst->buffer.fragment_size)
-		    || (bytestocopy >= count)) {
-
-			bytestocopy = min_t(u32, bytestocopy, count);
-
-			emu10k1_waveout_xferdata(woinst, (u8 __user *) buffer, &bytestocopy);
-
-			count -= bytestocopy;
-			buffer += bytestocopy * woinst->num_voices;
-			ret += bytestocopy * woinst->num_voices;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-			woinst->total_copied += bytestocopy;
-
-			if (!(woinst->state & WAVE_STATE_STARTED)
-			    && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)
-			    && (woinst->total_copied >= woinst->buffer.fragment_size))
-				emu10k1_waveout_start(wave_dev);
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (count > 0) {
-			if ((file->f_flags & O_NONBLOCK)
-			    || (!(wave_dev->enablebits & PCM_ENABLE_OUTPUT)))
-				return (ret ? ret : -EAGAIN);
-
-			interruptible_sleep_on(&woinst->wait_queue);
-
-			if (signal_pending(current))
-				return (ret ? ret : -ERESTARTSYS);
-		}
-	}
-
-	DPD(3, "bytes copied -> %d\n", (u32) ret);
-
-	return ret;
-}
-
-static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct woinst *woinst = NULL;
-	struct wiinst *wiinst = NULL;
-	int val = 0;
-	u32 bytestocopy;
-	unsigned long flags;
-	int __user *p = (int __user *)arg;
-
-	DPF(4, "emu10k1_audio_ioctl()\n");
-
-	if (file->f_mode & FMODE_WRITE)
-		woinst = wave_dev->woinst;
-
-	if (file->f_mode & FMODE_READ)
-		wiinst = wave_dev->wiinst;
-
-	switch (cmd) {
-	case OSS_GETVERSION:
-		DPF(2, "OSS_GETVERSION:\n");
-		return put_user(SOUND_VERSION, p);
-
-	case SNDCTL_DSP_RESET:
-		DPF(2, "SNDCTL_DSP_RESET:\n");
-		wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT;
-
-		if (file->f_mode & FMODE_WRITE) {
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (woinst->state & WAVE_STATE_OPEN) {
-				emu10k1_waveout_close(wave_dev);
-			}
-
-			woinst->mmapped = 0;
-			woinst->total_copied = 0;
-			woinst->total_played = 0;
-			woinst->blocks = 0;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			if (wiinst->state & WAVE_STATE_OPEN) {
-				emu10k1_wavein_close(wave_dev);
-			}
-
-			wiinst->mmapped = 0;
-			wiinst->total_recorded = 0;
-			wiinst->blocks = 0;
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-		}
-
-		break;
-
-	case SNDCTL_DSP_SYNC:
-		DPF(2, "SNDCTL_DSP_SYNC:\n");
-
-		if (file->f_mode & FMODE_WRITE) {
-
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (woinst->state & WAVE_STATE_OPEN) {
-
-				if (woinst->state & WAVE_STATE_STARTED)
-					while ((woinst->total_played < woinst->total_copied)
-					       && !signal_pending(current)) {
-						spin_unlock_irqrestore(&woinst->lock, flags);
-						interruptible_sleep_on(&woinst->wait_queue);
-						spin_lock_irqsave(&woinst->lock, flags);
-					}
-				emu10k1_waveout_close(wave_dev);
-			}
-
-			woinst->mmapped = 0;
-			woinst->total_copied = 0;
-			woinst->total_played = 0;
-			woinst->blocks = 0;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			if (wiinst->state & WAVE_STATE_OPEN) {
-				emu10k1_wavein_close(wave_dev);
-			}
-
-			wiinst->mmapped = 0;
-			wiinst->total_recorded = 0;
-			wiinst->blocks = 0;
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-		}
-
-		break;
-
-	case SNDCTL_DSP_SETDUPLEX:
-		DPF(2, "SNDCTL_DSP_SETDUPLEX:\n");
-		break;
-
-	case SNDCTL_DSP_GETCAPS:
-		DPF(2, "SNDCTL_DSP_GETCAPS:\n");
-		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |
-				DSP_CAP_TRIGGER | DSP_CAP_MMAP |
-				DSP_CAP_COPROC| DSP_CAP_MULTI, p);
-	case SNDCTL_DSP_SPEED:
-		DPF(2, "SNDCTL_DSP_SPEED:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, "val is %d\n", val);
-
-		if (val > 0) {
-			if (file->f_mode & FMODE_READ) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&wiinst->lock, flags);
-
-				format = wiinst->format;
-				format.samplingrate = val;
-
-				if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&wiinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = wiinst->format.samplingrate;
-
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-
-				DPD(2, "set recording sampling rate -> %d\n", val);
-			}
-
-			if (file->f_mode & FMODE_WRITE) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&woinst->lock, flags);
-
-				format = woinst->format;
-				format.samplingrate = val;
-
-				if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&woinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = woinst->format.samplingrate;
-
-				spin_unlock_irqrestore(&woinst->lock, flags);
-
-				DPD(2, "set playback sampling rate -> %d\n", val);
-			}
-
-			return put_user(val, p);
-		} else {
-			if (file->f_mode & FMODE_READ)
-				val = wiinst->format.samplingrate;
-			else if (file->f_mode & FMODE_WRITE)
-				val = woinst->format.samplingrate;
-
-			return put_user(val, p);
-		}
-		break;
-
-	case SNDCTL_DSP_STEREO:
-		DPF(2, "SNDCTL_DSP_STEREO:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, " val is %d\n", val);
-
-		if (file->f_mode & FMODE_READ) {
-			struct wave_format format;
-
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			format = wiinst->format;
-			format.channels = val ? 2 : 1;
-
-			if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				return -EINVAL;
-			}
-
-			val = wiinst->format.channels - 1;
-
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-			DPD(2, "set recording stereo -> %d\n", val);
-		}
-
-		if (file->f_mode & FMODE_WRITE) {
-			struct wave_format format;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			format = woinst->format;
-			format.channels = val ? 2 : 1;
-
-			if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
-				spin_unlock_irqrestore(&woinst->lock, flags);
-				return -EINVAL;
-			}
-
-			val = woinst->format.channels - 1;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-
-			DPD(2, "set playback stereo -> %d\n", val);
-		}
-
-		return put_user(val, p);
-
-		break;
-
-	case SNDCTL_DSP_CHANNELS:
-		DPF(2, "SNDCTL_DSP_CHANNELS:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, " val is %d\n", val);
-
-		if (val > 0) {
-			if (file->f_mode & FMODE_READ) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&wiinst->lock, flags);
-
-				format = wiinst->format;
-				format.channels = val;
-
-				if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&wiinst->lock, flags);
-					return -EINVAL;
-				}
-				val = wiinst->format.channels;
-
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				DPD(2, "set recording number of channels -> %d\n", val);
-			}
-
-			if (file->f_mode & FMODE_WRITE) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&woinst->lock, flags);
-
-				format = woinst->format;
-				format.channels = val;
-
-				if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&woinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = woinst->format.channels;
-
-				spin_unlock_irqrestore(&woinst->lock, flags);
-				DPD(2, "set playback number of channels -> %d\n", val);
-			}
-
-			return put_user(val, p);
-		} else {
-			if (file->f_mode & FMODE_READ)
-				val = wiinst->format.channels;
-			else if (file->f_mode & FMODE_WRITE)
-				val = woinst->format.channels;
-
-			return put_user(val, p);
-		}
-		break;
-
-	case SNDCTL_DSP_GETFMTS:
-		DPF(2, "SNDCTL_DSP_GETFMTS:\n");
-
-		if (file->f_mode & FMODE_READ)
-			val = AFMT_S16_LE;
-		else if (file->f_mode & FMODE_WRITE) {
-			val = AFMT_S16_LE | AFMT_U8;
-			if (emu10k1_find_control_gpr(&wave_dev->card->mgr,
-						     wave_dev->card->pt.patch_name, 
-						     wave_dev->card->pt.enable_gpr_name) >= 0)
-				val |= AFMT_AC3;
-		}
-		return put_user(val, p);
-
-	case SNDCTL_DSP_SETFMT:	/* Same as SNDCTL_DSP_SAMPLESIZE */
-		DPF(2, "SNDCTL_DSP_SETFMT:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, " val is %d\n", val);
-
-		if (val != AFMT_QUERY) {
-			if (file->f_mode & FMODE_READ) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&wiinst->lock, flags);
-
-				format = wiinst->format;
-				format.id = val;
-
-				if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&wiinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = wiinst->format.id;
-
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				DPD(2, "set recording format -> %d\n", val);
-			}
-
-			if (file->f_mode & FMODE_WRITE) {
-				struct wave_format format;
-
-				spin_lock_irqsave(&woinst->lock, flags);
-
-				format = woinst->format;
-				format.id = val;
-
-				if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
-					spin_unlock_irqrestore(&woinst->lock, flags);
-					return -EINVAL;
-				}
-
-				val = woinst->format.id;
-
-				spin_unlock_irqrestore(&woinst->lock, flags);
-				DPD(2, "set playback format -> %d\n", val);
-			}
-
-			return put_user(val, p);
-		} else {
-			if (file->f_mode & FMODE_READ)
-				val = wiinst->format.id;
-			else if (file->f_mode & FMODE_WRITE)
-				val = woinst->format.id;
-
-			return put_user(val, p);
-		}
-		break;
-
-	case SOUND_PCM_READ_BITS:
-
-		if (file->f_mode & FMODE_READ)
-			val = wiinst->format.bitsperchannel;
-		else if (file->f_mode & FMODE_WRITE)
-			val = woinst->format.bitsperchannel;
-
-		return put_user(val, p);
-
-	case SOUND_PCM_READ_RATE:
-
-		if (file->f_mode & FMODE_READ)
-			val = wiinst->format.samplingrate;
-		else if (file->f_mode & FMODE_WRITE)
-			val = woinst->format.samplingrate;
-
-		return put_user(val, p);
-
-	case SOUND_PCM_READ_CHANNELS:
-
-		if (file->f_mode & FMODE_READ)
-			val = wiinst->format.channels;
-		else if (file->f_mode & FMODE_WRITE)
-			val = woinst->format.channels;
-
-		return put_user(val, p);
-
-	case SOUND_PCM_WRITE_FILTER:
-		DPF(2, "SOUND_PCM_WRITE_FILTER: not implemented\n");
-		break;
-
-	case SOUND_PCM_READ_FILTER:
-		DPF(2, "SOUND_PCM_READ_FILTER: not implemented\n");
-		break;
-
-	case SNDCTL_DSP_SETSYNCRO:
-		DPF(2, "SNDCTL_DSP_SETSYNCRO: not implemented\n");
-		break;
-
-	case SNDCTL_DSP_GETTRIGGER:
-		DPF(2, "SNDCTL_DSP_GETTRIGGER:\n");
-
-		if (file->f_mode & FMODE_WRITE && (wave_dev->enablebits & PCM_ENABLE_OUTPUT))
-			val |= PCM_ENABLE_OUTPUT;
-
-		if (file->f_mode & FMODE_READ && (wave_dev->enablebits & PCM_ENABLE_INPUT))
-			val |= PCM_ENABLE_INPUT;
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_SETTRIGGER:
-		DPF(2, "SNDCTL_DSP_SETTRIGGER:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		if (file->f_mode & FMODE_WRITE) {
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (val & PCM_ENABLE_OUTPUT) {
-				wave_dev->enablebits |= PCM_ENABLE_OUTPUT;
-				if (woinst->state & WAVE_STATE_OPEN)
-					emu10k1_waveout_start(wave_dev);
-			} else {
-				wave_dev->enablebits &= ~PCM_ENABLE_OUTPUT;
-				if (woinst->state & WAVE_STATE_STARTED)
-					emu10k1_waveout_stop(wave_dev);
-			}
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			if (val & PCM_ENABLE_INPUT) {
-				wave_dev->enablebits |= PCM_ENABLE_INPUT;
-				if (wiinst->state & WAVE_STATE_OPEN)
-					emu10k1_wavein_start(wave_dev);
-			} else {
-				wave_dev->enablebits &= ~PCM_ENABLE_INPUT;
-				if (wiinst->state & WAVE_STATE_STARTED)
-					emu10k1_wavein_stop(wave_dev);
-			}
-
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-		}
-		break;
-
-	case SNDCTL_DSP_GETOSPACE:
-		{
-			audio_buf_info info;
-
-			DPF(4, "SNDCTL_DSP_GETOSPACE:\n");
-
-			if (!(file->f_mode & FMODE_WRITE))
-				return -EINVAL;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (woinst->state & WAVE_STATE_OPEN) {
-				emu10k1_waveout_update(woinst);
-				emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-				info.bytes = bytestocopy;
-			} else {
-				calculate_ofrag(woinst);
-				info.bytes = woinst->buffer.size;
-			}
-			spin_unlock_irqrestore(&woinst->lock, flags);
-
-			info.bytes *= woinst->num_voices;
-			info.fragsize = woinst->buffer.fragment_size * woinst->num_voices;
-			info.fragstotal = woinst->buffer.numfrags * woinst->num_voices;
-			info.fragments = info.bytes / info.fragsize;
-
-			if (copy_to_user(p, &info, sizeof(info)))
-				return -EFAULT;
-		}
-		break;
-
-	case SNDCTL_DSP_GETISPACE:
-		{
-			audio_buf_info info;
-
-			DPF(4, "SNDCTL_DSP_GETISPACE:\n");
-
-			if (!(file->f_mode & FMODE_READ))
-				return -EINVAL;
-
-			spin_lock_irqsave(&wiinst->lock, flags);
-			if (wiinst->state & WAVE_STATE_OPEN) {
-				emu10k1_wavein_update(wave_dev->card, wiinst);
-				emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-				info.bytes = bytestocopy;
-			} else {
-				calculate_ifrag(wiinst);
-				info.bytes = 0;
-			}
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-
-			info.fragstotal = wiinst->buffer.numfrags;
-			info.fragments = info.bytes / wiinst->buffer.fragment_size;
-			info.fragsize = wiinst->buffer.fragment_size;
-
-			if (copy_to_user(p, &info, sizeof(info)))
-				return -EFAULT;
-		}
-		break;
-
-	case SNDCTL_DSP_NONBLOCK:
-		DPF(2, "SNDCTL_DSP_NONBLOCK:\n");
-
-		file->f_flags |= O_NONBLOCK;
-		break;
-
-	case SNDCTL_DSP_GETODELAY:
-		DPF(4, "SNDCTL_DSP_GETODELAY:\n");
-
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-
-		spin_lock_irqsave(&woinst->lock, flags);
-		if (woinst->state & WAVE_STATE_OPEN) {
-			emu10k1_waveout_update(woinst);
-			emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-			val = woinst->buffer.size - bytestocopy;
-		} else
-			val = 0;
-
-		val *= woinst->num_voices;
-		spin_unlock_irqrestore(&woinst->lock, flags);
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_GETIPTR:
-		{
-			count_info cinfo;
-
-			DPF(4, "SNDCTL_DSP_GETIPTR: \n");
-
-			if (!(file->f_mode & FMODE_READ))
-				return -EINVAL;
-
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			if (wiinst->state & WAVE_STATE_OPEN) {
-				emu10k1_wavein_update(wave_dev->card, wiinst);
-				cinfo.ptr = wiinst->buffer.hw_pos;
-				cinfo.bytes = cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % wiinst->buffer.size;
-				cinfo.blocks = cinfo.bytes / wiinst->buffer.fragment_size - wiinst->blocks;
-				wiinst->blocks = cinfo.bytes / wiinst->buffer.fragment_size;
-			} else {
-				cinfo.ptr = 0;
-				cinfo.bytes = 0;
-				cinfo.blocks = 0;
-			}
-
-			if (wiinst->mmapped)
-				wiinst->buffer.bytestocopy %= wiinst->buffer.fragment_size;
-
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-
-			if (copy_to_user(p, &cinfo, sizeof(cinfo)))
-				return -EFAULT;
-		}
-		break;
-
-	case SNDCTL_DSP_GETOPTR:
-		{
-			count_info cinfo;
-
-			DPF(4, "SNDCTL_DSP_GETOPTR:\n");
-
-			if (!(file->f_mode & FMODE_WRITE))
-				return -EINVAL;
-
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (woinst->state & WAVE_STATE_OPEN || 
-			    ((woinst->format.passthrough == 1) && wave_dev->card->pt.state)) {
-				int num_fragments;
-
-				if (woinst->format.passthrough == 1) {
-					emu10k1_pt_waveout_update(wave_dev);
-					cinfo.bytes = woinst->total_played;
-				} else {
-					emu10k1_waveout_update(woinst);
-					cinfo.bytes = woinst->total_played;
-				}
-
-				cinfo.ptr = woinst->buffer.hw_pos;
-				num_fragments = cinfo.bytes / woinst->buffer.fragment_size;
-				cinfo.blocks = num_fragments - woinst->blocks;
-				woinst->blocks = num_fragments;
-
-				cinfo.bytes *= woinst->num_voices;
-				cinfo.ptr *= woinst->num_voices;
-			} else {
-				cinfo.ptr = 0;
-				cinfo.bytes = 0;
-				cinfo.blocks = 0;
-			}
-
-			if (woinst->mmapped)
-				woinst->buffer.free_bytes %= woinst->buffer.fragment_size;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-
-			if (copy_to_user(p, &cinfo, sizeof(cinfo)))
-				return -EFAULT;
-		}
-		break;
-
-	case SNDCTL_DSP_GETBLKSIZE:
-		DPF(2, "SNDCTL_DSP_GETBLKSIZE:\n");
-
-		if (file->f_mode & FMODE_WRITE) {
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			calculate_ofrag(woinst);
-			val = woinst->buffer.fragment_size * woinst->num_voices;
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			spin_lock_irqsave(&wiinst->lock, flags);
-
-			calculate_ifrag(wiinst);
-			val = wiinst->buffer.fragment_size;
-
-			spin_unlock_irqrestore(&wiinst->lock, flags);
-		}
-
-		return put_user(val, p);
-
-		break;
-
-	case SNDCTL_DSP_POST:
-		if (file->f_mode & FMODE_WRITE) {
-			spin_lock_irqsave(&woinst->lock, flags);
-
-			if (!(woinst->state & WAVE_STATE_STARTED)
-			    && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)
-			    && (woinst->total_copied > 0))
-				emu10k1_waveout_start(wave_dev);
-
-			spin_unlock_irqrestore(&woinst->lock, flags);
-		}
-
-		break;
-
-	case SNDCTL_DSP_SUBDIVIDE:
-		DPF(2, "SNDCTL_DSP_SUBDIVIDE: not implemented\n");
-		break;
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n");
-
-		if (get_user(val, p))
-			return -EFAULT;
-
-		DPD(2, "val is %#x\n", val);
-
-		if (val == 0)
-			return -EIO;
-
-		if (file->f_mode & FMODE_WRITE) {
-			/* digital pass-through fragment count and size are fixed values */
-			if (woinst->state & WAVE_STATE_OPEN || (woinst->format.passthrough == 1))
-				return -EINVAL;	/* too late to change */
-
-			woinst->buffer.ossfragshift = val & 0xffff;
-			woinst->buffer.numfrags = (val >> 16) & 0xffff;
-		}
-
-		if (file->f_mode & FMODE_READ) {
-			if (wiinst->state & WAVE_STATE_OPEN)
-				return -EINVAL;	/* too late to change */
-
-			wiinst->buffer.ossfragshift = val & 0xffff;
-			wiinst->buffer.numfrags = (val >> 16) & 0xffff;
-		}
-
-		break;
-
-	case SNDCTL_COPR_LOAD:
-		{
-			copr_buffer *buf;
-			u32 i;
-
-			DPF(4, "SNDCTL_COPR_LOAD:\n");
-
-			buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL);
-			if (!buf)
-				return -ENOMEM;
-
-			if (copy_from_user(buf, p, sizeof(copr_buffer))) {
-				kfree (buf);
-				return -EFAULT;
-			}
-
-			if ((buf->command != CMD_READ) && (buf->command != CMD_WRITE)) {
-				kfree (buf);
-				return -EINVAL;
-			}
-
-			if (buf->command == CMD_WRITE) {
-				
-#ifdef DBGEMU
-				if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) {
-#else
-				if (((buf->offs < 0x100) || (buf->offs + buf->len > (wave_dev->card->is_audigy ? 0xe00 : 0x800)) || (buf->len > 1000)
-				) && !(
-					//any register allowed raw access to users goes here:
-					(buf->offs == DBG ||
-					  buf->offs == A_DBG)
-					&& (buf->len == 1))) {
-#endif		
-					kfree(buf);
-					return -EINVAL;
-				}
-			} else {
-				if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) {
-					kfree(buf);
-					return -EINVAL;
-				}
-			}			
-				
-			if (((unsigned)buf->flags) > 0x3f)
-				buf->flags = 0;
-
-			if (buf->command == CMD_READ) {
-				for (i = 0; i < buf->len; i++)
-					((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, buf->flags);
-
-				if (copy_to_user(p, buf, sizeof(copr_buffer))) {
-					kfree(buf);
-					return -EFAULT;
-				}
-			} else {
-				for (i = 0; i < buf->len; i++)
-					sblive_writeptr(wave_dev->card, buf->offs + i, buf->flags, ((u32 *) buf->data)[i]);
-			}
-
-			kfree (buf);
-			break;
-		}
-
-	default:		/* Default is unrecognized command */
-		DPD(2, "default: %#x\n", cmd);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int *type)
-{
-	struct emu10k1_wavedevice *wave_dev = vma->vm_private_data;
-	struct woinst *woinst = wave_dev->woinst;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	struct page *dmapage;
-	unsigned long pgoff;
-	int rd, wr;
-
-	DPF(3, "emu10k1_mm_nopage()\n");
-	DPD(3, "addr: %#lx\n", address);
-
-	if (address > vma->vm_end) {
-		DPF(1, "EXIT, returning NOPAGE_SIGBUS\n");
-		return NOPAGE_SIGBUS; /* Disallow mremap */
-	}
-
-	pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT);
-	if (woinst != NULL)
-		wr = woinst->mmapped;
-	else
-		wr = 0;
-
-	if (wiinst != NULL)
-		rd = wiinst->mmapped;
-	else
-		rd = 0;
-
-	/* if full-duplex (read+write) and we have two sets of bufs,
-	* then the playback buffers come first, sez soundcard.c */
-	if (wr) {
-		if (pgoff >= woinst->buffer.pages) {
-			pgoff -= woinst->buffer.pages;
-			dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
-		} else
-			dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]);
-	} else {
-		dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
-	}
-
-	get_page (dmapage);
-
-	DPD(3, "page: %#lx\n", (unsigned long) dmapage);
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return dmapage;
-}
-
-static struct vm_operations_struct emu10k1_mm_ops = {
-	.nopage         = emu10k1_mm_nopage,
-};
-
-static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	unsigned long max_pages, n_pages, pgoffset;
-	struct woinst *woinst = NULL;
-	struct wiinst *wiinst = NULL;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_audio_mmap()\n");
-
-	max_pages = 0;
-	if (vma->vm_flags & VM_WRITE) {
-		woinst = wave_dev->woinst;
-
-		spin_lock_irqsave(&woinst->lock, flags);
-
-		/* No m'mapping possible for multichannel */
-		if (woinst->num_voices > 1) {
-			spin_unlock_irqrestore(&woinst->lock, flags);
-                	return -EINVAL;
-		}
-
-		if (woinst->state == WAVE_STATE_CLOSED) {
-			calculate_ofrag(woinst);
-
-			if (emu10k1_waveout_open(wave_dev) < 0) {
-				spin_unlock_irqrestore(&woinst->lock, flags);
-				ERROR();
-				return -EINVAL;
-			}
-		}
-
-		woinst->mmapped = 1;
-		max_pages += woinst->buffer.pages;
-		spin_unlock_irqrestore(&woinst->lock, flags);
-	}
-
-	if (vma->vm_flags & VM_READ) {
-		wiinst = wave_dev->wiinst;
-
-		spin_lock_irqsave(&wiinst->lock, flags);
-		if (wiinst->state == WAVE_STATE_CLOSED) {
-			calculate_ifrag(wiinst);
-
-			if (emu10k1_wavein_open(wave_dev) < 0) {
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				ERROR();
-				return -EINVAL;
-			}
-		}
-
-		wiinst->mmapped = 1;
-		max_pages += wiinst->buffer.pages;
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-	}
-
-	n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	pgoffset = vma->vm_pgoff;
-
-	DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset);
-	DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages);
-
-	if (pgoffset + n_pages > max_pages)
-		return -EINVAL;
-
-	vma->vm_flags |= VM_RESERVED;
-	vma->vm_ops = &emu10k1_mm_ops;
-	vma->vm_private_data = wave_dev;
-	return 0;
-}
-
-static int emu10k1_audio_open(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct emu10k1_card *card = NULL;
-	struct list_head *entry;
-	struct emu10k1_wavedevice *wave_dev;
-
-	DPF(2, "emu10k1_audio_open()\n");
-
-	/* Check for correct device to open */
-
-	list_for_each(entry, &emu10k1_devs) {
-		card = list_entry(entry, struct emu10k1_card, list);
-
-		if (!((card->audio_dev ^ minor) & ~0xf) || !((card->audio_dev1 ^ minor) & ~0xf))
-			goto match;
-	}
-
-	return -ENODEV;
-
-match:
-
-	wave_dev = kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
-
-	if (wave_dev == NULL) { 
-		ERROR();
-		return -ENOMEM;
-	}
-
-	wave_dev->card = card;
-	wave_dev->wiinst = NULL;
-	wave_dev->woinst = NULL;
-	wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT;	/* Default */
-
-	if (file->f_mode & FMODE_READ) {
-		/* Recording */
-		struct wiinst *wiinst;
-
-		if ((wiinst = kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
-			ERROR();
-			kfree(wave_dev);
-			return -ENOMEM;
-		}
-
-		wiinst->recsrc = card->wavein.recsrc;
-                wiinst->fxwc = card->wavein.fxwc;
-
-		switch (wiinst->recsrc) {
-		case WAVERECORD_AC97:
-			wiinst->format.id = AFMT_S16_LE;
-			wiinst->format.samplingrate = 8000;
-			wiinst->format.bitsperchannel = 16;
-			wiinst->format.channels = 1;
-			break;
-		case WAVERECORD_MIC:
-			wiinst->format.id = AFMT_S16_LE;
-			wiinst->format.samplingrate = 8000;
-			wiinst->format.bitsperchannel = 16;
-			wiinst->format.channels = 1;
-			break;
-		case WAVERECORD_FX:
-			wiinst->format.id = AFMT_S16_LE;
-			wiinst->format.samplingrate = 48000;
-			wiinst->format.bitsperchannel = 16;
-			wiinst->format.channels = hweight32(wiinst->fxwc);
-			break;
-		default:
-			kfree(wave_dev);
-			kfree(wiinst);
-			BUG();
-			break;
-		}
-
-		wiinst->state = WAVE_STATE_CLOSED;
-
-		wiinst->buffer.ossfragshift = 0;
-		wiinst->buffer.fragment_size = 0;
-		wiinst->buffer.numfrags = 0;
-
-		init_waitqueue_head(&wiinst->wait_queue);
-
-		wiinst->mmapped = 0;
-		wiinst->total_recorded = 0;
-		wiinst->blocks = 0;
-		spin_lock_init(&wiinst->lock);
-		tasklet_init(&wiinst->timer.tasklet, emu10k1_wavein_bh, (unsigned long) wave_dev);
-		wave_dev->wiinst = wiinst;
-		emu10k1_wavein_setformat(wave_dev, &wiinst->format);
-	}
-
-	if (file->f_mode & FMODE_WRITE) {
-		struct woinst *woinst;
-		int i;
-
-		if ((woinst = kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
-			ERROR();
-			kfree(wave_dev);
-			return -ENOMEM;
-		}
-
-		if (wave_dev->wiinst != NULL) {
-			woinst->format = wave_dev->wiinst->format;
-		} else {
-			woinst->format.id = AFMT_U8;
-			woinst->format.samplingrate = 8000;
-			woinst->format.bitsperchannel = 8;
-			woinst->format.channels = 1;
-		}
-
-		woinst->state = WAVE_STATE_CLOSED;
-
-		woinst->buffer.fragment_size = 0;
-		woinst->buffer.ossfragshift = 0;
-		woinst->buffer.numfrags = 0;
-		woinst->device = (card->audio_dev1 == minor);
-		woinst->timer.state = TIMER_STATE_UNINSTALLED;
-		woinst->num_voices = 1;
-		for (i = 0; i < WAVEOUT_MAXVOICES; i++) {
-			woinst->voice[i].usage = VOICE_USAGE_FREE;
-			woinst->voice[i].mem.emupageindex = -1;
-		}
-
-		init_waitqueue_head(&woinst->wait_queue);
-
-		woinst->mmapped = 0;
-		woinst->total_copied = 0;
-		woinst->total_played = 0;
-		woinst->blocks = 0;
-		spin_lock_init(&woinst->lock);
-		tasklet_init(&woinst->timer.tasklet, emu10k1_waveout_bh, (unsigned long) wave_dev);
-		wave_dev->woinst = woinst;
-		emu10k1_waveout_setformat(wave_dev, &woinst->format);
-	}
-
-	file->private_data = (void *) wave_dev;
-
-	return nonseekable_open(inode, file);
-}
-
-static int emu10k1_audio_release(struct inode *inode, struct file *file)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct emu10k1_card *card;
-	unsigned long flags;
-
-	card = wave_dev->card;
-
-	DPF(2, "emu10k1_audio_release()\n");
-
-	if (file->f_mode & FMODE_WRITE) {
-		struct woinst *woinst = wave_dev->woinst;
-
-		spin_lock_irqsave(&woinst->lock, flags);
-		if(woinst->format.passthrough==2)
-			card->pt.state=PT_STATE_PLAYING;
-		if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE){
-			spin_lock(&card->pt.lock);
-                        emu10k1_pt_stop(card);
-			spin_unlock(&card->pt.lock);
-		}
-		if (woinst->state & WAVE_STATE_OPEN) {
-			if (woinst->state & WAVE_STATE_STARTED) {
-				if (!(file->f_flags & O_NONBLOCK)) {
-					while (!signal_pending(current)
-					       && (woinst->total_played < woinst->total_copied)) {
-						DPF(4, "Buffer hasn't been totally played, sleep....\n");
-						spin_unlock_irqrestore(&woinst->lock, flags);
-						interruptible_sleep_on(&woinst->wait_queue);
-						spin_lock_irqsave(&woinst->lock, flags);
-					}
-				}
-			}
-			emu10k1_waveout_close(wave_dev);
-		}
-
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		/* remove the tasklet */
-		tasklet_kill(&woinst->timer.tasklet);
-		kfree(wave_dev->woinst);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		struct wiinst *wiinst = wave_dev->wiinst;
-
-		spin_lock_irqsave(&wiinst->lock, flags);
-
-		if (wiinst->state & WAVE_STATE_OPEN) {
-			emu10k1_wavein_close(wave_dev);
-		}
-
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-		tasklet_kill(&wiinst->timer.tasklet);
-		kfree(wave_dev->wiinst);
-	}
-
-	kfree(wave_dev);
-
-	if (waitqueue_active(&card->open_wait))
-		wake_up_interruptible(&card->open_wait);
-
-	return 0;
-}
-
-/* FIXME sort out poll() + mmap() */
-static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct woinst *woinst = wave_dev->woinst;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	unsigned int mask = 0;
-	u32 bytestocopy;
-	unsigned long flags;
-
-	DPF(4, "emu10k1_audio_poll()\n");
-
-	if (file->f_mode & FMODE_WRITE)
-		poll_wait(file, &woinst->wait_queue, wait);
-
-	if (file->f_mode & FMODE_READ)
-		poll_wait(file, &wiinst->wait_queue, wait);
-
-	if (file->f_mode & FMODE_WRITE) {
-		spin_lock_irqsave(&woinst->lock, flags);
-
-		if (woinst->state & WAVE_STATE_OPEN) {
-			emu10k1_waveout_update(woinst);
-			emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-
-			if (bytestocopy >= woinst->buffer.fragment_size)
-				mask |= POLLOUT | POLLWRNORM;
-		} else
-			mask |= POLLOUT | POLLWRNORM;
-
-		spin_unlock_irqrestore(&woinst->lock, flags);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		spin_lock_irqsave(&wiinst->lock, flags);
-
-		if (wiinst->state & WAVE_STATE_OPEN) {
-			emu10k1_wavein_update(wave_dev->card, wiinst);
-			emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-			if (bytestocopy >= wiinst->buffer.fragment_size)
-				mask |= POLLIN | POLLRDNORM;
-		}
-
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-	}
-
-	return mask;
-}
-
-static void calculate_ofrag(struct woinst *woinst)
-{
-	struct waveout_buffer *buffer = &woinst->buffer;
-	u32 fragsize;
-
-	if (buffer->fragment_size)
-		return;
-
-	if (!buffer->ossfragshift) {
-		fragsize = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1;
-
-		while (fragsize) {
-			fragsize >>= 1;
-			buffer->ossfragshift++;
-		}
-	}
-
-	if (buffer->ossfragshift < WAVEOUT_MINFRAGSHIFT)
-		buffer->ossfragshift = WAVEOUT_MINFRAGSHIFT;
-
-	buffer->fragment_size = 1 << buffer->ossfragshift;
-
-	while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE)
-		buffer->fragment_size >>= 1;
-
-	/* now we are sure that:
-	 (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS)
-	*/
-
-	if (!buffer->numfrags) {
-		u32 numfrags;
-
-		numfrags = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTBUFLEN) /
-			   (buffer->fragment_size * 1000) - 1;
-
-		buffer->numfrags = 1;
-
-		while (numfrags) {
-			numfrags >>= 1;
-			buffer->numfrags <<= 1;
-		}
-	}
-
-	if (buffer->numfrags < WAVEOUT_MINFRAGS)
-		buffer->numfrags = WAVEOUT_MINFRAGS;
-
-	if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE)
-		buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size;
-
-	if (buffer->numfrags < WAVEOUT_MINFRAGS)
-		BUG();
-
-	buffer->size = buffer->fragment_size * buffer->numfrags;
-	buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
-
-	DPD(2, " calculated playback fragment_size -> %d\n", buffer->fragment_size);
-	DPD(2, " calculated playback numfrags -> %d\n", buffer->numfrags);
-
-	return;
-}
-
-static void calculate_ifrag(struct wiinst *wiinst)
-{
-	struct wavein_buffer *buffer = &wiinst->buffer;
-	u32 fragsize, bufsize, size[4];
-	int i, j;
-
-	if (buffer->fragment_size)
-		return;
-
-	if (!buffer->ossfragshift) {
-		fragsize = (wiinst->format.bytespersec * WAVEIN_DEFAULTFRAGLEN) / 1000 - 1;
-
-		while (fragsize) {
-			fragsize >>= 1;
-			buffer->ossfragshift++;
-		}
-	}
-
-	if (buffer->ossfragshift < WAVEIN_MINFRAGSHIFT)
-		buffer->ossfragshift = WAVEIN_MINFRAGSHIFT;
-
-	buffer->fragment_size = 1 << buffer->ossfragshift;
-
-	while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE)
-		buffer->fragment_size >>= 1;
-
-	/* now we are sure that:
-	   (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS)
-        */
-
-
-	if (!buffer->numfrags)
-		buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1;
-
-	if (buffer->numfrags < WAVEIN_MINFRAGS)
-		buffer->numfrags = WAVEIN_MINFRAGS;
-
-	if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE)
-		buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size;
-
-	if (buffer->numfrags < WAVEIN_MINFRAGS)
-		BUG();
-
-	bufsize = buffer->fragment_size * buffer->numfrags;
-
-	/* the buffer size for recording is restricted to certain values, adjust it now */
-	if (bufsize >= 0x10000) {
-		buffer->size = 0x10000;
-		buffer->sizeregval = 0x1f;
-	} else {
-		buffer->size = 0;
-		size[0] = 384;
-		size[1] = 448;
-		size[2] = 512;
-		size[3] = 640;
-
-		for (i = 0; i < 8; i++)
-			for (j = 0; j < 4; j++)
-				if (bufsize >= size[j]) {
-					buffer->size = size[j];
-					size[j] *= 2;
-					buffer->sizeregval = i * 4 + j + 1;
-				} else
-					goto exitloop;
-	      exitloop:
-		if (buffer->size == 0) {
-			buffer->size = 384;
-			buffer->sizeregval = 0x01;
-		}
-	}
-
-	/* adjust the fragment size so that buffer size is an integer multiple */
-	while (buffer->size % buffer->fragment_size)
-		buffer->fragment_size >>= 1;
-
-	buffer->numfrags = buffer->size / buffer->fragment_size;
-	buffer->pages =  buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
-
-	DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size);
-	DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags);
-	DPD(2, " buffer size register -> %#04x\n", buffer->sizeregval);
-
-	return;
-}
-
-static void emu10k1_wavein_bh(unsigned long refdata)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	u32 bytestocopy;
-	unsigned long flags;
-
-	if (!wiinst)
-		return;
-
-	spin_lock_irqsave(&wiinst->lock, flags);
-
-	if (!(wiinst->state & WAVE_STATE_STARTED)) {
-		spin_unlock_irqrestore(&wiinst->lock, flags);
-		return;
-	}
-
-	emu10k1_wavein_update(wave_dev->card, wiinst);
-	emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-	spin_unlock_irqrestore(&wiinst->lock, flags);
-
-	if (bytestocopy >= wiinst->buffer.fragment_size) {
-	 	if (waitqueue_active(&wiinst->wait_queue))
-			wake_up_interruptible(&wiinst->wait_queue);
-	} else
-		DPD(3, "Not enough transfer size, %d\n", bytestocopy);
-
-	return;
-}
-
-static void emu10k1_waveout_bh(unsigned long refdata)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata;
-	struct woinst *woinst = wave_dev->woinst;
-	u32 bytestocopy;
-	unsigned long flags;
-
-	if (!woinst)
-		return;
-
-	spin_lock_irqsave(&woinst->lock, flags);
-
-	if (!(woinst->state & WAVE_STATE_STARTED)) {
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		return;
-	}
-
-	emu10k1_waveout_update(woinst);
-	emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-
-	if (woinst->buffer.fill_silence) {
-		spin_unlock_irqrestore(&woinst->lock, flags);
-		emu10k1_waveout_fillsilence(woinst);
-	} else
-		spin_unlock_irqrestore(&woinst->lock, flags);
-
-	if (bytestocopy >= woinst->buffer.fragment_size) {
-		if (waitqueue_active(&woinst->wait_queue))
-			wake_up_interruptible(&woinst->wait_queue);
-	} else
-		DPD(3, "Not enough transfer size -> %d\n", bytestocopy);
-
-	return;
-}
-
-const struct file_operations emu10k1_audio_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= emu10k1_audio_read,
-	.write		= emu10k1_audio_write,
-	.poll		= emu10k1_audio_poll,
-	.ioctl		= emu10k1_audio_ioctl,
-	.mmap		= emu10k1_audio_mmap,
-	.open		= emu10k1_audio_open,
-	.release	= emu10k1_audio_release,
-};
diff --git a/sound/oss/emu10k1/audio.h b/sound/oss/emu10k1/audio.h
deleted file mode 100644
index 26ee81b..0000000
--- a/sound/oss/emu10k1/audio.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- **********************************************************************
- *     audio.c -- /dev/dsp interface for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999	    Alan Cox        cleaned up types/leaks
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#ifndef _AUDIO_H
-#define _AUDIO_H
-
-struct emu10k1_wavedevice
-{
-        struct emu10k1_card *card;
-        struct wiinst *wiinst;
-        struct woinst *woinst;
-        u16 enablebits;
-};
-
-#endif /* _AUDIO_H */
diff --git a/sound/oss/emu10k1/cardmi.c b/sound/oss/emu10k1/cardmi.c
deleted file mode 100644
index 57674f8..0000000
--- a/sound/oss/emu10k1/cardmi.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- **********************************************************************
- *     sblive_mi.c - MIDI UART input HAL for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        clean up
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "cardmi.h"
-#include "irqmgr.h"
-
-
-static int emu10k1_mpuin_callback(struct emu10k1_mpuin *card_mpuin, u32 msg, unsigned long data, u32 bytesvalid);
-
-static int sblive_miStateInit(struct emu10k1_mpuin *);
-static int sblive_miStateEntry(struct emu10k1_mpuin *, u8);
-static int sblive_miStateParse(struct emu10k1_mpuin *, u8);
-static int sblive_miState3Byte(struct emu10k1_mpuin *, u8);
-static int sblive_miState3ByteKey(struct emu10k1_mpuin *, u8);
-static int sblive_miState3ByteVel(struct emu10k1_mpuin *, u8);
-static int sblive_miState2Byte(struct emu10k1_mpuin *, u8);
-static int sblive_miState2ByteKey(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon2(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon2Key(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3Key(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3Vel(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysExNorm(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysReal(struct emu10k1_mpuin *, u8);
-
-
-static struct {
-	int (*Fn) (struct emu10k1_mpuin *, u8);
-} midistatefn[] = {
-
-	{
-	sblive_miStateParse}, {
-	sblive_miState3Byte},	/* 0x8n, 0x9n, 0xAn, 0xBn, 0xEn */
-	{
-	sblive_miState3ByteKey},	/* Byte 1                       */
-	{
-	sblive_miState3ByteVel},	/* Byte 2                       */
-	{
-	sblive_miState2Byte},	/* 0xCn, 0xDn                   */
-	{
-	sblive_miState2ByteKey},	/* Byte 1                       */
-	{
-	sblive_miStateSysCommon2},	/* 0xF1 , 0xF3                  */
-	{
-	sblive_miStateSysCommon2Key},	/* 0xF1 , 0xF3, Byte 1          */
-	{
-	sblive_miStateSysCommon3},	/* 0xF2                         */
-	{
-	sblive_miStateSysCommon3Key},	/* 0xF2 , Byte 1                */
-	{
-	sblive_miStateSysCommon3Vel},	/* 0xF2 , Byte 2                */
-	{
-	sblive_miStateSysExNorm},	/* 0xF0, 0xF7, Normal mode      */
-	{
-	sblive_miStateSysReal}	/* 0xF4 - 0xF6 ,0xF8 - 0xFF     */
-};
-
-
-/* Installs the IRQ handler for the MPU in port                 */
-
-/* and initialize parameters                                    */
-
-int emu10k1_mpuin_open(struct emu10k1_card *card, struct midi_openinfo *openinfo)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
-	DPF(2, "emu10k1_mpuin_open\n");
-
-	if (!(card_mpuin->status & FLAGS_AVAILABLE))
-		return -1;
-
-	/* Copy open info and mark channel as in use */
-	card_mpuin->openinfo = *openinfo;
-	card_mpuin->status &= ~FLAGS_AVAILABLE;	/* clear */
-	card_mpuin->status |= FLAGS_READY;	/* set */
-	card_mpuin->status &= ~FLAGS_MIDM_STARTED;	/* clear */
-	card_mpuin->firstmidiq = NULL;
-	card_mpuin->lastmidiq = NULL;
-	card_mpuin->qhead = 0;
-	card_mpuin->qtail = 0;
-
-	sblive_miStateInit(card_mpuin);
-
-	emu10k1_mpu_reset(card);
-	emu10k1_mpu_acquire(card);
-
-	return 0;
-}
-
-int emu10k1_mpuin_close(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
-	DPF(2, "emu10k1_mpuin_close()\n");
-
-	/* Check if there are pending input SysEx buffers */
-	if (card_mpuin->firstmidiq != NULL) {
-		ERROR();
-		return -1;
-	}
-
-	/* Disable RX interrupt */
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
-	emu10k1_mpu_release(card);
-
-	card_mpuin->status |= FLAGS_AVAILABLE;	/* set */
-	card_mpuin->status &= ~FLAGS_MIDM_STARTED;	/* clear */
-
-	return 0;
-}
-
-/* Adds MIDI buffer to local queue list                         */
-
-int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *card_mpuin, struct midi_hdr *midihdr)
-{
-	struct midi_queue *midiq;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpuin_add_buffer()\n");
-
-	/* Update MIDI buffer flags */
-	midihdr->flags |= MIDIBUF_INQUEUE;	/* set */
-	midihdr->flags &= ~MIDIBUF_DONE;	/* clear */
-
-	if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
-		/* Message lost */
-		return -1;
-	}
-
-	midiq->next = NULL;
-	midiq->qtype = 1;
-	midiq->length = midihdr->bufferlength;
-	midiq->sizeLeft = midihdr->bufferlength;
-	midiq->midibyte = midihdr->data;
-	midiq->refdata = (unsigned long) midihdr;
-
-	spin_lock_irqsave(&card_mpuin->lock, flags);
-
-	if (card_mpuin->firstmidiq == NULL) {
-		card_mpuin->firstmidiq = midiq;
-		card_mpuin->lastmidiq = midiq;
-	} else {
-		(card_mpuin->lastmidiq)->next = midiq;
-		card_mpuin->lastmidiq = midiq;
-	}
-
-	spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-	return 0;
-}
-
-/* First set the Time Stamp if MIDI IN has not started.         */
-
-/* Then enable RX Irq.                                          */
-
-int emu10k1_mpuin_start(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-	u8 dummy;
-
-	DPF(2, "emu10k1_mpuin_start()\n");
-
-	/* Set timestamp if not set */
-	if (card_mpuin->status & FLAGS_MIDM_STARTED) {
-		DPF(2, "Time Stamp not changed\n");
-	} else {
-		while (!emu10k1_mpu_read_data(card, &dummy));
-
-		card_mpuin->status |= FLAGS_MIDM_STARTED;	/* set */
-
-		/* Set new time stamp */
-		card_mpuin->timestart = (jiffies * 1000) / HZ;
-		DPD(2, "New Time Stamp = %d\n", card_mpuin->timestart);
-
-		card_mpuin->qhead = 0;
-		card_mpuin->qtail = 0;
-
-		emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-	}
-
-	return 0;
-}
-
-/* Disable the RX Irq.  If a partial recorded buffer            */
-
-/* exist, send it up to IMIDI level.                            */
-
-int emu10k1_mpuin_stop(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-	struct midi_queue *midiq;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpuin_stop()\n");
-
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
-	card_mpuin->status &= ~FLAGS_MIDM_STARTED;	/* clear */
-
-	if (card_mpuin->firstmidiq) {
-		spin_lock_irqsave(&card_mpuin->lock, flags);
-
-		midiq = card_mpuin->firstmidiq;
-		if (midiq != NULL) {
-			if (midiq->sizeLeft == midiq->length)
-				midiq = NULL;
-			else {
-				card_mpuin->firstmidiq = midiq->next;
-				if (card_mpuin->firstmidiq == NULL)
-					card_mpuin->lastmidiq = NULL;
-			}
-		}
-
-		spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-		if (midiq) {
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
-			kfree(midiq);
-		}
-	}
-
-	return 0;
-}
-
-/* Disable the RX Irq.  If any buffer                           */
-
-/* exist, send it up to IMIDI level.                            */
-int emu10k1_mpuin_reset(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-	struct midi_queue *midiq;
-
-	DPF(2, "emu10k1_mpuin_reset()\n");
-
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
-	while (card_mpuin->firstmidiq) {
-		midiq = card_mpuin->firstmidiq;
-		card_mpuin->firstmidiq = midiq->next;
-
-		if (midiq->sizeLeft == midiq->length)
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
-		else
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
-
-		kfree(midiq);
-	}
-
-	card_mpuin->lastmidiq = NULL;
-	card_mpuin->status &= ~FLAGS_MIDM_STARTED;
-
-	return 0;
-}
-
-/* Passes the message with the data back to the client          */
-
-/* via IRQ & DPC callbacks to Ring 3                            */
-static int emu10k1_mpuin_callback(struct emu10k1_mpuin *card_mpuin, u32 msg, unsigned long data, u32 bytesvalid)
-{
-	unsigned long timein;
-	struct midi_queue *midiq;
-	unsigned long callback_msg[3];
-	struct midi_hdr *midihdr;
-
-	/* Called during ISR. The data & code touched are:
-	 * 1. card_mpuin
-	 * 2. The function to be called
-	 */
-
-	timein = card_mpuin->timein;
-	if (card_mpuin->timestart <= timein)
-		callback_msg[0] = timein - card_mpuin->timestart;
-	else
-		callback_msg[0] = (~0x0L - card_mpuin->timestart) + timein;
-
-	if (msg == ICARDMIDI_INDATA || msg == ICARDMIDI_INDATAERROR) {
-		callback_msg[1] = data;
-		callback_msg[2] = bytesvalid;
-		DPD(2, "emu10k1_mpuin_callback: midimsg = %#lx\n", data);
-	} else {
-		midiq = (struct midi_queue *) data;
-		midihdr = (struct midi_hdr *) midiq->refdata;
-
-		callback_msg[1] = midiq->length - midiq->sizeLeft;
-		callback_msg[2] = midiq->refdata;
-		midihdr->flags &= ~MIDIBUF_INQUEUE;
-		midihdr->flags |= MIDIBUF_DONE;
-
-		midihdr->bytesrecorded = midiq->length - midiq->sizeLeft;
-	}
-
-	/* Notify client that Sysex buffer has been sent */
-	emu10k1_midi_callback(msg, card_mpuin->openinfo.refdata, callback_msg);
-
-	return 0;
-}
-
-void emu10k1_mpuin_bh(unsigned long refdata)
-{
-	u8 data;
-	unsigned idx;
-	struct emu10k1_mpuin *card_mpuin = (struct emu10k1_mpuin *) refdata;
-	unsigned long flags;
-
-	while (card_mpuin->qhead != card_mpuin->qtail) {
-		spin_lock_irqsave(&card_mpuin->lock, flags);
-		idx = card_mpuin->qhead;
-		data = card_mpuin->midiq[idx].data;
-		card_mpuin->timein = card_mpuin->midiq[idx].timein;
-		idx = (idx + 1) % MIDIIN_MAX_BUFFER_SIZE;
-		card_mpuin->qhead = idx;
-		spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-		sblive_miStateEntry(card_mpuin, data);
-	}
-
-	return;
-}
-
-/* IRQ callback handler routine for the MPU in port */
-
-int emu10k1_mpuin_irqhandler(struct emu10k1_card *card)
-{
-	unsigned idx;
-	unsigned count;
-	u8 MPUIvalue;
-	struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
-	/* IRQ service routine. The data and code touched are:
-	 * 1. card_mpuin
-	 */
-
-	count = 0;
-	idx = card_mpuin->qtail;
-
-	while (1) {
-		if (emu10k1_mpu_read_data(card, &MPUIvalue) < 0) {
-			break;
-		} else {
-			++count;
-			card_mpuin->midiq[idx].data = MPUIvalue;
-			card_mpuin->midiq[idx].timein = (jiffies * 1000) / HZ;
-			idx = (idx + 1) % MIDIIN_MAX_BUFFER_SIZE;
-		}
-	}
-
-	if (count) {
-		card_mpuin->qtail = idx;
-
-		tasklet_hi_schedule(&card_mpuin->tasklet);
-	}
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*   Supporting functions for Midi-In Interpretation State Machine           */
-
-/*****************************************************************************/
-
-/* FIXME: This should be a macro */
-static int sblive_miStateInit(struct emu10k1_mpuin *card_mpuin)
-{
-	card_mpuin->status = 0;	/* For MIDI running status */
-	card_mpuin->fstatus = 0;	/* For 0xFn status only */
-	card_mpuin->curstate = STIN_PARSE;
-	card_mpuin->laststate = STIN_PARSE;
-	card_mpuin->data = 0;
-	card_mpuin->timestart = 0;
-	card_mpuin->timein = 0;
-
-	return 0;
-}
-
-/* FIXME: This should be a macro */
-static int sblive_miStateEntry(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	return midistatefn[card_mpuin->curstate].Fn(card_mpuin, data);
-}
-
-static int sblive_miStateParse(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	switch (data & 0xf0) {
-	case 0x80:
-	case 0x90:
-	case 0xA0:
-	case 0xB0:
-	case 0xE0:
-		card_mpuin->curstate = STIN_3BYTE;
-		break;
-
-	case 0xC0:
-	case 0xD0:
-		card_mpuin->curstate = STIN_2BYTE;
-		break;
-
-	case 0xF0:
-		/* System messages do not affect the previous running status! */
-		switch (data & 0x0f) {
-		case 0x0:
-			card_mpuin->laststate = card_mpuin->curstate;
-			card_mpuin->curstate = STIN_SYS_EX_NORM;
-
-			if (card_mpuin->firstmidiq) {
-				struct midi_queue *midiq;
-
-				midiq = card_mpuin->firstmidiq;
-				*midiq->midibyte = data;
-				--midiq->sizeLeft;
-				++midiq->midibyte;
-			}
-
-			return CTSTATUS_NEXT_BYTE;
-
-		case 0x7:
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, 0xf7, 0);
-			return -1;
-
-		case 0x2:
-			card_mpuin->laststate = card_mpuin->curstate;
-			card_mpuin->curstate = STIN_SYS_COMMON_3;
-			break;
-
-		case 0x1:
-		case 0x3:
-			card_mpuin->laststate = card_mpuin->curstate;
-			card_mpuin->curstate = STIN_SYS_COMMON_2;
-			break;
-
-		default:
-			/* includes 0xF4 - 0xF6, 0xF8 - 0xFF */
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-		}
-
-		break;
-
-	default:
-		DPF(2, "BUG: default case hit\n");
-		return -1;
-	}
-
-	return midistatefn[card_mpuin->curstate].Fn(card_mpuin, data);
-}
-
-static int sblive_miState3Byte(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	u8 temp = data & 0xf0;
-
-	if (temp < 0x80) {
-		return midistatefn[STIN_3BYTE_KEY].Fn(card_mpuin, data);
-	} else if (temp <= 0xe0 && temp != 0xc0 && temp != 0xd0) {
-		card_mpuin->status = data;
-		card_mpuin->curstate = STIN_3BYTE_KEY;
-
-		return CTSTATUS_NEXT_BYTE;
-	}
-
-	return midistatefn[STIN_PARSE].Fn(card_mpuin, data);
-}
-
-static int sblive_miState3ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = STIN_PARSE;
-		tmp = ((unsigned long) data) << 8;
-		tmp |= (unsigned long) card_mpuin->status;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->data = data;
-	card_mpuin->curstate = STIN_3BYTE_VEL;
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miState3ByteVel(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 2 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = STIN_PARSE;
-		tmp = ((unsigned long) data) << 8;
-		tmp |= card_mpuin->data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->status;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->curstate = STIN_3BYTE;
-	tmp = (unsigned long) data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->status;
-
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 3);
-
-	return 0;
-}
-
-static int sblive_miState2Byte(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	u8 temp = data & 0xf0;
-
-	if ((temp == 0xc0) || (temp == 0xd0)) {
-		card_mpuin->status = data;
-		card_mpuin->curstate = STIN_2BYTE_KEY;
-
-		return CTSTATUS_NEXT_BYTE;
-	}
-
-	if (temp < 0x80)
-		return midistatefn[STIN_2BYTE_KEY].Fn(card_mpuin, data);
-
-	return midistatefn[STIN_PARSE].Fn(card_mpuin, data);
-}
-
-static int sblive_miState2ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = STIN_PARSE;
-		tmp = (unsigned long) data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->status;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->curstate = STIN_2BYTE;
-	tmp = (unsigned long) data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->status;
-
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 2);
-
-	return 0;
-}
-
-static int sblive_miStateSysCommon2(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	card_mpuin->fstatus = data;
-	card_mpuin->curstate = STIN_SYS_COMMON_2_KEY;
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon2Key(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = card_mpuin->laststate;
-		tmp = (unsigned long) data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->fstatus;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->curstate = card_mpuin->laststate;
-	tmp = (unsigned long) data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->fstatus;
-
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 2);
-
-	return 0;
-}
-
-static int sblive_miStateSysCommon3(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	card_mpuin->fstatus = data;
-	card_mpuin->curstate = STIN_SYS_COMMON_3_KEY;
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon3Key(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = card_mpuin->laststate;
-		tmp = (unsigned long) data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->fstatus;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->data = data;
-	card_mpuin->curstate = STIN_SYS_COMMON_3_VEL;
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon3Vel(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 2 */
-{
-	unsigned long tmp;
-
-	if (data > 0x7f) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = card_mpuin->laststate;
-		tmp = (unsigned long) data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->data;
-		tmp = tmp << 8;
-		tmp |= (unsigned long) card_mpuin->fstatus;
-
-		emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
-		return -1;
-	}
-
-	card_mpuin->curstate = card_mpuin->laststate;
-	tmp = (unsigned long) data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->data;
-	tmp = tmp << 8;
-	tmp |= (unsigned long) card_mpuin->fstatus;
-
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 3);
-
-	return 0;
-}
-
-static int sblive_miStateSysExNorm(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	unsigned long flags;
-
-	if ((data > 0x7f) && (data != 0xf7)) {
-		/* Real-time messages check */
-		if (data > 0xf7)
-			return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
-		/* Invalid Data! */
-		DPF(2, "Invalid data!\n");
-
-		card_mpuin->curstate = card_mpuin->laststate;
-
-		if (card_mpuin->firstmidiq) {
-			struct midi_queue *midiq;
-
-			midiq = card_mpuin->firstmidiq;
-			*midiq->midibyte = data;
-			--midiq->sizeLeft;
-			++midiq->midibyte;
-
-			spin_lock_irqsave(&card_mpuin->lock, flags);
-
-			card_mpuin->firstmidiq = midiq->next;
-			if (card_mpuin->firstmidiq == NULL)
-				card_mpuin->lastmidiq = NULL;
-
-			spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
-
-			kfree(midiq);
-		}
-
-		return -1;
-	}
-
-	if (card_mpuin->firstmidiq) {
-		struct midi_queue *midiq;
-
-		midiq = card_mpuin->firstmidiq;
-		*midiq->midibyte = data;
-		--midiq->sizeLeft;
-		++midiq->midibyte;
-	}
-
-	if (data == 0xf7) {
-		/* End of Sysex buffer */
-		/* Send down the buffer */
-
-		card_mpuin->curstate = card_mpuin->laststate;
-
-		if (card_mpuin->firstmidiq) {
-			struct midi_queue *midiq;
-
-			midiq = card_mpuin->firstmidiq;
-
-			spin_lock_irqsave(&card_mpuin->lock, flags);
-
-			card_mpuin->firstmidiq = midiq->next;
-			if (card_mpuin->firstmidiq == NULL)
-				card_mpuin->lastmidiq = NULL;
-
-			spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
-
-			kfree(midiq);
-		}
-
-		return 0;
-	}
-
-	if (card_mpuin->firstmidiq) {
-		struct midi_queue *midiq;
-
-		midiq = card_mpuin->firstmidiq;
-
-		if (midiq->sizeLeft == 0) {
-			/* Special case */
-
-			spin_lock_irqsave(&card_mpuin->lock, flags);
-
-			card_mpuin->firstmidiq = midiq->next;
-			if (card_mpuin->firstmidiq == NULL)
-				card_mpuin->lastmidiq = NULL;
-
-			spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
-			emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
-
-			kfree(midiq);
-
-			return CTSTATUS_NEXT_BYTE;
-		}
-	}
-
-	return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysReal(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
-	emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, data, 1);
-
-	return CTSTATUS_NEXT_BYTE;
-}
diff --git a/sound/oss/emu10k1/cardmi.h b/sound/oss/emu10k1/cardmi.h
deleted file mode 100644
index d12c241..0000000
--- a/sound/oss/emu10k1/cardmi.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- **********************************************************************
- *     sblive_mi.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        cleaned up
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#ifndef _CARDMI_H
-#define _CARDMI_H
-
-#include "icardmid.h"
-#include <linux/interrupt.h>
-
-typedef enum
-{
-	STIN_PARSE = 0,
-	STIN_3BYTE,                     /* 0x80, 0x90, 0xA0, 0xB0, 0xE0 */
-	STIN_3BYTE_KEY,                 /* Byte 1 */
-	STIN_3BYTE_VEL,                 /* Byte 1 */
-	STIN_2BYTE,                     /* 0xC0, 0xD0 */
-	STIN_2BYTE_KEY,                 /* Byte 1 */
-	STIN_SYS_COMMON_2,              /* 0xF1, 0xF3  */
-	STIN_SYS_COMMON_2_KEY,
-	STIN_SYS_COMMON_3,              /* 0xF2 */
-	STIN_SYS_COMMON_3_KEY,
-	STIN_SYS_COMMON_3_VEL,
-	STIN_SYS_EX_NORM,               /* 0xF0, Normal mode */
-	STIN_SYS_REAL
-} midi_in_state;
-
-
-/* flags for card MIDI in object */
-#define FLAGS_MIDM_STARTED          0x00001000      // Data has started to come in after Midm Start
-#define MIDIIN_MAX_BUFFER_SIZE      200             // Definition for struct emu10k1_mpuin
-
-struct midi_data
-{
-	u8 data;
-	u32 timein;
-};
-
-struct emu10k1_mpuin
-{
-	spinlock_t        lock;
-	struct midi_queue *firstmidiq;
-	struct midi_queue *lastmidiq;
-	unsigned          qhead, qtail;
-	struct midi_data  midiq[MIDIIN_MAX_BUFFER_SIZE];
-	struct tasklet_struct tasklet;
-	struct midi_openinfo    openinfo;
-
-	/* For MIDI state machine */
-	u8              status;        /* For MIDI running status */
-	u8              fstatus;       /* For 0xFn status only */
-	midi_in_state   curstate;
-	midi_in_state   laststate;
-	u32             timestart;
-	u32             timein;
-	u8              data;
-};
-
-int emu10k1_mpuin_open(struct emu10k1_card *, struct midi_openinfo *);
-int emu10k1_mpuin_close(struct emu10k1_card *);
-int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *, struct midi_hdr *);
-int emu10k1_mpuin_start(struct emu10k1_card *);
-int emu10k1_mpuin_stop(struct emu10k1_card *);
-int emu10k1_mpuin_reset(struct emu10k1_card *);
-
-int emu10k1_mpuin_irqhandler(struct emu10k1_card *);
-void emu10k1_mpuin_bh(unsigned long);
-
-#endif  /* _CARDMI_H */
diff --git a/sound/oss/emu10k1/cardmo.c b/sound/oss/emu10k1/cardmo.c
deleted file mode 100644
index a8cc75d..0000000
--- a/sound/oss/emu10k1/cardmo.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*     
- **********************************************************************
- *     cardmo.c - MIDI UART output HAL for emu10k1 driver 
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- *     November 2, 1999     Alan Cox        cleaned up
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */
-
-#include <linux/slab.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "cardmo.h"
-#include "irqmgr.h"
-
-/* Installs the IRQ handler for the MPU out port               *
- * and initialize parameters                                    */
-
-int emu10k1_mpuout_open(struct emu10k1_card *card, struct midi_openinfo *openinfo)
-{
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-
-	DPF(2, "emu10k1_mpuout_open()\n");
-
-	if (!(card_mpuout->status & FLAGS_AVAILABLE))
-		return -1;
-
-	/* Copy open info and mark channel as in use */
-	card_mpuout->intr = 0;
-	card_mpuout->openinfo = *openinfo;
-	card_mpuout->status &= ~FLAGS_AVAILABLE;
-	card_mpuout->laststatus = 0x80;
-	card_mpuout->firstmidiq = NULL;
-	card_mpuout->lastmidiq = NULL;
-
-	emu10k1_mpu_reset(card);
-	emu10k1_mpu_acquire(card);
-
-	return 0;
-}
-
-int emu10k1_mpuout_close(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-	struct midi_queue *midiq;
-	struct midi_hdr *midihdr;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpuout_close()\n");
-
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
-	spin_lock_irqsave(&card_mpuout->lock, flags);
-
-	while (card_mpuout->firstmidiq != NULL) {
-		midiq = card_mpuout->firstmidiq;
-		midihdr = (struct midi_hdr *) midiq->refdata;
-
-		card_mpuout->firstmidiq = midiq->next;
-
-		kfree(midihdr->data);
-		kfree(midihdr);
-		kfree(midiq);
-	}
-
-	card_mpuout->lastmidiq = NULL;
-
-	emu10k1_mpu_release(card);
-
-	card_mpuout->status |= FLAGS_AVAILABLE;
-
-	spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
-	return 0;
-}
-
-/* If there isn't enough buffer space, reject Midi Buffer.     *
-* Otherwise, disable TX, create object to hold Midi            *
-*  uffer, update buffer flags and other parameters             *
-* before enabling TX again.                                    */
-
-int emu10k1_mpuout_add_buffer(struct emu10k1_card *card, struct midi_hdr *midihdr)
-{
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-	struct midi_queue *midiq;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpuout_add_buffer()\n");
-
-	if (card_mpuout->state == CARDMIDIOUT_STATE_SUSPEND)
-		return 0;
-
-	midihdr->flags |= MIDIBUF_INQUEUE;
-	midihdr->flags &= ~MIDIBUF_DONE;
-
-	if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
-		/* Message lost */
-		return -1;
-	}
-
-	midiq->next = NULL;
-	midiq->qtype = 1;
-	midiq->length = midihdr->bufferlength;
-	midiq->sizeLeft = midihdr->bufferlength;
-	midiq->midibyte = midihdr->data;
-
-	midiq->refdata = (unsigned long) midihdr;
-
-	spin_lock_irqsave(&card_mpuout->lock, flags);
-
-	if (card_mpuout->firstmidiq == NULL) {
-		card_mpuout->firstmidiq = midiq;
-		card_mpuout->lastmidiq = midiq;
-	} else {
-		(card_mpuout->lastmidiq)->next = midiq;
-		card_mpuout->lastmidiq = midiq;
-	}
-
-	card_mpuout->intr = 0;
-
-	emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
-	spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
-	return 0;
-}
-
-void emu10k1_mpuout_bh(unsigned long refdata)
-{
-	struct emu10k1_card *card = (struct emu10k1_card *) refdata;
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-	int cByteSent = 0;
-	struct midi_queue *midiq;
-	struct midi_queue *doneq = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card_mpuout->lock, flags);
-
-	while (card_mpuout->firstmidiq != NULL) {
-		midiq = card_mpuout->firstmidiq;
-
-		while (cByteSent < 4 && midiq->sizeLeft) {
-			if (emu10k1_mpu_write_data(card, *midiq->midibyte) < 0) {
-				DPF(2, "emu10k1_mpuoutDpcCallback error!!\n");
-			} else {
-				++cByteSent;
-				--midiq->sizeLeft;
-				++midiq->midibyte;
-			}
-		}
-
-		if (midiq->sizeLeft == 0) {
-			if (doneq == NULL)
-				doneq = midiq;
-			card_mpuout->firstmidiq = midiq->next;
-		} else
-			break;
-	}
-
-	if (card_mpuout->firstmidiq == NULL)
-		card_mpuout->lastmidiq = NULL;
-
-	if (doneq != NULL) {
-		while (doneq != card_mpuout->firstmidiq) {
-			unsigned long callback_msg[3];
-
-			midiq = doneq;
-			doneq = midiq->next;
-
-			if (midiq->qtype) {
-				callback_msg[0] = 0;
-				callback_msg[1] = midiq->length;
-				callback_msg[2] = midiq->refdata;
-
-				emu10k1_midi_callback(ICARDMIDI_OUTLONGDATA, card_mpuout->openinfo.refdata, callback_msg);
-			} else if (((u8) midiq->refdata) < 0xF0 && ((u8) midiq->refdata) > 0x7F)
-				card_mpuout->laststatus = (u8) midiq->refdata;
-
-			kfree(midiq);
-		}
-	}
-
-	if ((card_mpuout->firstmidiq != NULL) || cByteSent) {
-		card_mpuout->intr = 0;
-		emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-	}
-
-	spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
-	return;
-}
-
-int emu10k1_mpuout_irqhandler(struct emu10k1_card *card)
-{
-	struct emu10k1_mpuout *card_mpuout = card->mpuout;
-
-	DPF(4, "emu10k1_mpuout_irqhandler\n");
-
-	card_mpuout->intr = 1;
-	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
-	tasklet_hi_schedule(&card_mpuout->tasklet);
-
-	return 0;
-}
diff --git a/sound/oss/emu10k1/cardmo.h b/sound/oss/emu10k1/cardmo.h
deleted file mode 100644
index 7026eb3..0000000
--- a/sound/oss/emu10k1/cardmo.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- **********************************************************************
- *     cardmo.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox	    cleaned up
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#ifndef _CARDMO_H
-#define _CARDMO_H
-
-#include "icardmid.h"
-#include <linux/interrupt.h>
-
-#define CARDMIDIOUT_STATE_DEFAULT    0x00000000
-#define CARDMIDIOUT_STATE_SUSPEND    0x00000001
-
-struct emu10k1_mpuout
-{
-	u32			status;
-	u32			state;
-	volatile int		intr;
-	struct midi_queue	*firstmidiq;
-	struct midi_queue	*lastmidiq;
-	u8			laststatus;
-	struct tasklet_struct 	tasklet;
-	spinlock_t		lock;
-	struct midi_openinfo	openinfo;
-};
-
-int emu10k1_mpuout_open(struct emu10k1_card *, struct midi_openinfo *);
-int emu10k1_mpuout_close(struct emu10k1_card *);
-int emu10k1_mpuout_add_buffer(struct emu10k1_card *, struct midi_hdr *);
-
-int emu10k1_mpuout_irqhandler(struct emu10k1_card *);
-void emu10k1_mpuout_bh(unsigned long);
-
-#endif  /* _CARDMO_H */
diff --git a/sound/oss/emu10k1/cardwi.c b/sound/oss/emu10k1/cardwi.c
deleted file mode 100644
index 060d1be..0000000
--- a/sound/oss/emu10k1/cardwi.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- **********************************************************************
- *     cardwi.c - PCM input HAL for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include <linux/poll.h>
-#include "hwaccess.h"
-#include "timer.h"
-#include "recmgr.h"
-#include "audio.h"
-#include "cardwi.h"
-
-/**
- * query_format - returns a valid sound format
- *
- * This function will return a valid sound format as close
- * to the requested one as possible. 
- */
-static void query_format(int recsrc, struct wave_format *wave_fmt)
-{
-
-	switch (recsrc) {
-	case WAVERECORD_AC97:
-
-		if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
-			wave_fmt->channels = 2;
-
-		if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)
-			wave_fmt->samplingrate = 0xBB80;
-		else if (wave_fmt->samplingrate >= (0xAC44 + 0x7D00) / 2)
-			wave_fmt->samplingrate = 0xAC44;
-		else if (wave_fmt->samplingrate >= (0x7D00 + 0x5DC0) / 2)
-			wave_fmt->samplingrate = 0x7D00;
-		else if (wave_fmt->samplingrate >= (0x5DC0 + 0x5622) / 2)
-			wave_fmt->samplingrate = 0x5DC0;
-		else if (wave_fmt->samplingrate >= (0x5622 + 0x3E80) / 2)
-			wave_fmt->samplingrate = 0x5622;
-		else if (wave_fmt->samplingrate >= (0x3E80 + 0x2B11) / 2)
-			wave_fmt->samplingrate = 0x3E80;
-		else if (wave_fmt->samplingrate >= (0x2B11 + 0x1F40) / 2)
-			wave_fmt->samplingrate = 0x2B11;
-		else
-			wave_fmt->samplingrate = 0x1F40;
-
-		switch (wave_fmt->id) {
-		case AFMT_S16_LE:
-			wave_fmt->bitsperchannel = 16;
-			break;
-		case AFMT_U8:
-			wave_fmt->bitsperchannel = 8;
-			break;
-		default:
-			wave_fmt->id = AFMT_S16_LE;
-			wave_fmt->bitsperchannel = 16;
-			break;
-		}
-
-		break;
-
-	/* these can't be changed from the original values */
-	case WAVERECORD_MIC:
-	case WAVERECORD_FX:
-		break;
-
-	default:
-		BUG();
-		break;
-	}
-
-	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
-	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
-	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
-	wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
-}
-
-static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	buffer->addr = pci_alloc_consistent(card->pci_dev, buffer->size * buffer->cov,
-					    &buffer->dma_handle);
-	if (buffer->addr == NULL)
-		return -1;
-
-	return 0;
-}
-
-static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	if (buffer->addr != NULL)
-		pci_free_consistent(card->pci_dev, buffer->size * buffer->cov,
-				    buffer->addr, buffer->dma_handle);
-}
-
-int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	struct wiinst **wiinst_tmp = NULL;
-	u16 delay;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_wavein_open()\n");
-
-	switch (wiinst->recsrc) {
-	case WAVERECORD_AC97:
-		wiinst_tmp = &card->wavein.ac97;
-		break;
-	case WAVERECORD_MIC:
-		wiinst_tmp = &card->wavein.mic;
-		break;
-	case WAVERECORD_FX:
-		wiinst_tmp = &card->wavein.fx;
-		break;
-	default:
-		BUG();
-		break;
-	}
-
-	spin_lock_irqsave(&card->lock, flags);
-	if (*wiinst_tmp != NULL) {
-		spin_unlock_irqrestore(&card->lock, flags);
-		return -1;
-	}
-
-	*wiinst_tmp = wiinst;
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	/* handle 8 bit recording */
-	if (wiinst->format.bytesperchannel == 1) {
-		if (wiinst->buffer.size > 0x8000) {
-			wiinst->buffer.size = 0x8000;
-			wiinst->buffer.sizeregval = 0x1f;
-		} else
-			wiinst->buffer.sizeregval += 4;
-
-		wiinst->buffer.cov = 2;
-	} else
-		wiinst->buffer.cov = 1;
-
-	if (alloc_buffer(card, &wiinst->buffer) < 0) {
-		ERROR();
-		return -1;
-	}
-
-	emu10k1_set_record_src(card, wiinst);
-
-	emu10k1_reset_record(card, &wiinst->buffer);
-
-	wiinst->buffer.hw_pos = 0;
-	wiinst->buffer.pos = 0;
-	wiinst->buffer.bytestocopy = 0;
-
-	delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
-
-	emu10k1_timer_install(card, &wiinst->timer, delay / 2);
-
-	wiinst->state = WAVE_STATE_OPEN;
-
-	return 0;
-}
-
-void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_wavein_close()\n");
-
-	emu10k1_wavein_stop(wave_dev);
-
-	emu10k1_timer_uninstall(card, &wiinst->timer);
-
-	free_buffer(card, &wiinst->buffer);
-
-	spin_lock_irqsave(&card->lock, flags);
-	switch (wave_dev->wiinst->recsrc) {
-	case WAVERECORD_AC97:
-		card->wavein.ac97 = NULL;
-		break;
-	case WAVERECORD_MIC:
-		card->wavein.mic = NULL;
-		break;
-	case WAVERECORD_FX:
-		card->wavein.fx = NULL;
-		break;
-	default:
-		BUG();
-		break;
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	wiinst->state = WAVE_STATE_CLOSED;
-}
-
-void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-
-	DPF(2, "emu10k1_wavein_start()\n");
-
-	emu10k1_start_record(card, &wiinst->buffer);
-	emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
-
-	wiinst->state |= WAVE_STATE_STARTED;
-}
-
-void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-
-	DPF(2, "emu10k1_wavein_stop()\n");
-
-	if (!(wiinst->state & WAVE_STATE_STARTED))
-		return;
-
-	emu10k1_timer_disable(card, &wiinst->timer);
-	emu10k1_stop_record(card, &wiinst->buffer);
-
-	wiinst->state &= ~WAVE_STATE_STARTED;
-}
-
-int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct wiinst *wiinst = wave_dev->wiinst;
-	u16 delay;
-
-	DPF(2, "emu10k1_wavein_setformat()\n");
-
-	if (wiinst->state & WAVE_STATE_STARTED)
-		return -1;
-
-	query_format(wiinst->recsrc, format);
-
-	if ((wiinst->format.samplingrate != format->samplingrate)
-	    || (wiinst->format.bitsperchannel != format->bitsperchannel)
-	    || (wiinst->format.channels != format->channels)) {
-
-		wiinst->format = *format;
-
-		if (wiinst->state == WAVE_STATE_CLOSED)
-			return 0;
-
-		wiinst->buffer.size *= wiinst->buffer.cov;
-
-		if (wiinst->format.bytesperchannel == 1) {
-			wiinst->buffer.cov = 2;
-			wiinst->buffer.size /= wiinst->buffer.cov;
-		} else
-			wiinst->buffer.cov = 1;
-
-		emu10k1_timer_uninstall(card, &wiinst->timer);
-
-		delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
-
-		emu10k1_timer_install(card, &wiinst->timer, delay / 2);
-	}
-
-	return 0;
-}
-
-void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
-{
-	struct wavein_buffer *buffer = &wiinst->buffer;
-
-	*size = buffer->bytestocopy;
-
-	if (wiinst->mmapped)
-		return;
-
-	if (*size > buffer->size) {
-		*size = buffer->size;
-		buffer->pos = buffer->hw_pos;
-		buffer->bytestocopy = buffer->size;
-		DPF(1, "buffer overrun\n");
-	}
-}
-
-static int copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
-{
-	if (cov == 1) {
-		if (__copy_to_user(dst, src + str, len))
-			return -EFAULT;
-	} else {
-		u8 byte;
-		u32 i;
-
-		src += 1 + 2 * str;
-
-		for (i = 0; i < len; i++) {
-			byte = src[2 * i] ^ 0x80;
-			if (__copy_to_user(dst + i, &byte, 1))
-				return -EFAULT;
-		}
-	}
-
-	return 0;
-}
-
-int emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
-{
-	struct wavein_buffer *buffer = &wiinst->buffer;
-	u32 sizetocopy, sizetocopy_now, start;
-	unsigned long flags;
-	int ret;
-
-	sizetocopy = min_t(u32, buffer->size, *size);
-	*size = sizetocopy;
-
-	if (!sizetocopy)
-		return 0;
-
-	spin_lock_irqsave(&wiinst->lock, flags);
-	start = buffer->pos;
-	buffer->pos += sizetocopy;
-	buffer->pos %= buffer->size;
-	buffer->bytestocopy -= sizetocopy;
-	sizetocopy_now = buffer->size - start;
-
-	spin_unlock_irqrestore(&wiinst->lock, flags);
-
-	if (sizetocopy > sizetocopy_now) {
-		sizetocopy -= sizetocopy_now;
-
-		ret = copy_block(data, buffer->addr, start, sizetocopy_now,
-				 buffer->cov);
-		if (ret == 0)
-			ret = copy_block(data + sizetocopy_now, buffer->addr, 0,
-					 sizetocopy, buffer->cov);
-	} else {
-		ret = copy_block(data, buffer->addr, start, sizetocopy,
-				 buffer->cov);
-	}
-
-	return ret;
-}
-
-void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
-{
-	u32 hw_pos;
-	u32 diff;
-
-	/* There is no actual start yet */
-	if (!(wiinst->state & WAVE_STATE_STARTED)) {
-		hw_pos = wiinst->buffer.hw_pos;
-	} else {
-		/* hw_pos in byte units */
-		hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov;
-	}
-
-	diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;
-	wiinst->total_recorded += diff;
-	wiinst->buffer.bytestocopy += diff;
-
-	wiinst->buffer.hw_pos = hw_pos;
-}
diff --git a/sound/oss/emu10k1/cardwi.h b/sound/oss/emu10k1/cardwi.h
deleted file mode 100644
index e82029b..0000000
--- a/sound/oss/emu10k1/cardwi.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- **********************************************************************
- *     cardwi.h -- header file for card wave input functions
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-#ifndef _CARDWI_H
-#define _CARDWI_H
-
-#include "icardwav.h"
-#include "audio.h"
-#include "timer.h"
-
-struct wavein_buffer {
-	u16 ossfragshift;
-        u32 fragment_size;
-        u32 numfrags;
-	u32 hw_pos;		/* hardware cursor position */
-	u32 pos;		/* software cursor position */
-	u32 bytestocopy;	/* bytes of recorded data available */
-	u32 size;
-	u32 pages;
-	u32 sizereg;
-	u32 sizeregval;
-        u32 addrreg;
-        u32 idxreg;
-        u32 adcctl;
-	void *addr;
-	u8 cov;
-	dma_addr_t dma_handle;	
-};
-
-struct wiinst
-{
-	u8 state;
-	struct emu_timer timer;
-	struct wave_format format;
-	struct wavein_buffer buffer;
-	wait_queue_head_t wait_queue;
-	u8 mmapped;
-	u32 total_recorded;	/* total bytes read() from device */
-	u32 blocks;
-	spinlock_t lock;
-	u8 recsrc;
-	u16 fxwc;
-};
-
-#define WAVEIN_MAXBUFSIZE	65536
-#define WAVEIN_MINBUFSIZE	368
-
-#define WAVEIN_DEFAULTFRAGLEN	100 
-#define WAVEIN_DEFAULTBUFLEN	1000
-
-#define WAVEIN_MINFRAGSHIFT	8 
-#define WAVEIN_MINFRAGS		2
-
-int emu10k1_wavein_open(struct emu10k1_wavedevice *);
-void emu10k1_wavein_close(struct emu10k1_wavedevice *);
-void emu10k1_wavein_start(struct emu10k1_wavedevice *);
-void emu10k1_wavein_stop(struct emu10k1_wavedevice *);
-void emu10k1_wavein_getxfersize(struct wiinst *, u32 *);
-int emu10k1_wavein_xferdata(struct wiinst *, u8 __user *, u32 *);
-int emu10k1_wavein_setformat(struct emu10k1_wavedevice *, struct wave_format *);
-void emu10k1_wavein_update(struct emu10k1_card *, struct wiinst *);
-
-
-#endif /* _CARDWI_H */
diff --git a/sound/oss/emu10k1/cardwo.c b/sound/oss/emu10k1/cardwo.c
deleted file mode 100644
index 54daca4..0000000
--- a/sound/oss/emu10k1/cardwo.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- **********************************************************************
- *     cardwo.c - PCM output HAL for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include <linux/poll.h>
-#include "hwaccess.h"
-#include "8010.h"
-#include "voicemgr.h"
-#include "cardwo.h"
-#include "audio.h"
-
-static u32 samplerate_to_linearpitch(u32 samplingrate)
-{
-	samplingrate = (samplingrate << 8) / 375;
-	return (samplingrate >> 1) + (samplingrate & 1);
-}
-
-static void query_format(struct emu10k1_wavedevice *wave_dev, struct wave_format *wave_fmt)
-{
-	int i, j, do_passthrough = 0, is_ac3 = 0;
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-
-	if ((wave_fmt->channels > 2) && (wave_fmt->id != AFMT_S16_LE) && (wave_fmt->id != AFMT_U8))
-		wave_fmt->channels = 2;
-
-	if ((wave_fmt->channels < 1) || (wave_fmt->channels > WAVEOUT_MAXVOICES))
-		wave_fmt->channels = 2;
-
-	if (wave_fmt->channels == 2)
-		woinst->num_voices = 1;
-	else
-		woinst->num_voices = wave_fmt->channels;
-
-	if (wave_fmt->samplingrate >= 0x2ee00)
-		wave_fmt->samplingrate = 0x2ee00;
-
-	wave_fmt->passthrough = 0;
-	do_passthrough = is_ac3 = 0;
-
-	if (card->pt.selected)
-		do_passthrough = 1;
-
-	switch (wave_fmt->id) {
-	case AFMT_S16_LE:
-		wave_fmt->bitsperchannel = 16;
-		break;
-	case AFMT_U8:
-		wave_fmt->bitsperchannel = 8;
-		break;
-	case AFMT_AC3:
-		do_passthrough = 1;
-		is_ac3 = 1;
-		break;
-	default:
-		wave_fmt->id = AFMT_S16_LE;
-		wave_fmt->bitsperchannel = 16;
-		break;
-	}	
-	if (do_passthrough) {
-		/* currently only one waveout instance may use pass-through */
-		if (woinst->state != WAVE_STATE_CLOSED || 
-		    card->pt.state != PT_STATE_INACTIVE ||
-		    (wave_fmt->samplingrate != 48000 && !is_ac3)) {
-			DPF(2, "unable to set pass-through mode\n");
-		} else if (USE_PT_METHOD1) {
-			i = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.intr_gpr_name);
-			j = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.enable_gpr_name);
-			if (i < 0 || j < 0)
-				DPF(2, "unable to set pass-through mode\n");
-			else {
-				wave_fmt->samplingrate = 48000;
-				wave_fmt->channels = 2;
-				card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,
-									    card->pt.pos_gpr_name);
-				wave_fmt->passthrough = 1;
-				card->pt.intr_gpr = i;
-				card->pt.enable_gpr = j;
-				card->pt.state = PT_STATE_INACTIVE;
-			
-				DPD(2, "is_ac3 is %d\n", is_ac3);
-				card->pt.ac3data = is_ac3;
-				wave_fmt->bitsperchannel = 16;
-			}
-		}else{
-			DPF(2, "Using Passthrough Method 2\n");
-			card->pt.enable_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,
-								       card->pt.enable_gpr_name);
-			wave_fmt->passthrough = 2;
-			wave_fmt->bitsperchannel = 16;
-		}
-	}
-
-	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
-	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
-	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
-
-	if (wave_fmt->channels == 2)
-		wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel;
-	else
-		wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel;
-}
-
-static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned int voicenum)
-{
-	struct emu_voice *voice = &woinst->voice[voicenum];
-
-	/* Allocate voices here, if no voices available, return error. */
-
-	voice->usage = VOICE_USAGE_PLAYBACK;
-
-	voice->flags = 0;
-
-	if (woinst->format.channels == 2)
-		voice->flags |= VOICE_FLAGS_STEREO;
-
-	if (woinst->format.bitsperchannel == 16)
-		voice->flags |= VOICE_FLAGS_16BIT;
-
-	if (emu10k1_voice_alloc(card, voice) < 0) {
-		voice->usage = VOICE_USAGE_FREE;
-		return -1;
-	}
-
-	/* Calculate pitch */
-	voice->initial_pitch = (u16) (srToPitch(woinst->format.samplingrate) >> 8);
-	voice->pitch_target = samplerate_to_linearpitch(woinst->format.samplingrate);
-
-	DPD(2, "Initial pitch --> %#x\n", voice->initial_pitch);
-
-	voice->startloop = (voice->mem.emupageindex << 12) /
-	 woinst->format.bytespervoicesample;
-	voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;
-	voice->start = voice->startloop;
-
-	
-	voice->params[0].volume_target = 0xffff;
-	voice->params[0].initial_fc = 0xff;
-	voice->params[0].initial_attn = 0x00;
-	voice->params[0].byampl_env_sustain = 0x7f;
-	voice->params[0].byampl_env_decay = 0x7f;
-
-	
-	if (voice->flags & VOICE_FLAGS_STEREO) {
-		if (woinst->format.passthrough == 2) {
-			voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PT];
-			voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PT];
-			voice->params[0].send_dcba = 0xff;
-			voice->params[1].send_dcba = 0xff00;
-			voice->params[0].send_hgfe = voice->params[1].send_hgfe=0;
-		} else {
-			voice->params[0].send_dcba = card->waveout.send_dcba[SEND_LEFT];
-			voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_LEFT];
-			voice->params[1].send_dcba = card->waveout.send_dcba[SEND_RIGHT];
-			voice->params[1].send_hgfe = card->waveout.send_hgfe[SEND_RIGHT];
-
-			if (woinst->device) {
-				// /dev/dps1
-				voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PCM1];
-				voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];
-			} else {
-				voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PCM];
-				voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];
-			}
-		}
-		
-		voice->params[1].volume_target = 0xffff;
-		voice->params[1].initial_fc = 0xff;
-		voice->params[1].initial_attn = 0x00;
-		voice->params[1].byampl_env_sustain = 0x7f;
-		voice->params[1].byampl_env_decay = 0x7f;
-	} else {
-		if (woinst->num_voices > 1) {
-			// Multichannel pcm
-			voice->params[0].send_dcba=0xff;
-			voice->params[0].send_hgfe=0;
-			if (card->is_audigy) {
-				voice->params[0].send_routing = 0x3f3f3f00 + card->mchannel_fx + voicenum;
-				voice->params[0].send_routing2 = 0x3f3f3f3f;
-			} else {
-				voice->params[0].send_routing = 0xfff0 + card->mchannel_fx + voicenum;
-			}
-			
-		} else {
-			voice->params[0].send_dcba = card->waveout.send_dcba[SEND_MONO];
-			voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_MONO];
-
-			if (woinst->device) {
-				voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM1];
-				voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];
-			} else {
-				voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM];
-				voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];
-			}
-		}
-	}
-
-	DPD(2, "voice: startloop=%#x, endloop=%#x\n", voice->startloop, voice->endloop);
-
-	emu10k1_voice_playback_setup(voice);
-
-	return 0;
-}
-
-int emu10k1_waveout_open(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-	struct waveout_buffer *buffer = &woinst->buffer;
-	unsigned int voicenum;
-	u16 delay;
-
-	DPF(2, "emu10k1_waveout_open()\n");
-
-	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-		if (emu10k1_voice_alloc_buffer(card, &woinst->voice[voicenum].mem, woinst->buffer.pages) < 0) {
-			ERROR();
-			emu10k1_waveout_close(wave_dev);
-			return -1;
-		}
-
-		if (get_voice(card, woinst, voicenum) < 0) {
-			ERROR();
-			emu10k1_waveout_close(wave_dev);
-			return -1;
-		}
-	}
-
-	buffer->fill_silence = 0;
-	buffer->silence_bytes = 0;
-	buffer->silence_pos = 0;
-	buffer->hw_pos = 0;
-	buffer->free_bytes = woinst->buffer.size;
-
-	delay = (48000 * woinst->buffer.fragment_size) /
-		 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
-
-	emu10k1_timer_install(card, &woinst->timer, delay);
-
-	woinst->state = WAVE_STATE_OPEN;
-
-	return 0;
-}
-
-void emu10k1_waveout_close(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-	unsigned int voicenum;
-
-	DPF(2, "emu10k1_waveout_close()\n");
-
-	emu10k1_waveout_stop(wave_dev);
-
-	emu10k1_timer_uninstall(card, &woinst->timer);
-
-	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-		emu10k1_voice_free(&woinst->voice[voicenum]);
-		emu10k1_voice_free_buffer(card, &woinst->voice[voicenum].mem);
-	}
-
-	woinst->state = WAVE_STATE_CLOSED;
-}
-
-void emu10k1_waveout_start(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-	struct pt_data *pt = &card->pt;
-
-	DPF(2, "emu10k1_waveout_start()\n");
-
-	if (woinst->format.passthrough == 2) {
-		emu10k1_pt_setup(wave_dev);
-		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 1);
-		pt->state = PT_STATE_PLAYING;
-	}
-
-	/* Actual start */
-	emu10k1_voices_start(woinst->voice, woinst->num_voices, woinst->total_played);
-
-	emu10k1_timer_enable(card, &woinst->timer);
-
-	woinst->state |= WAVE_STATE_STARTED;
-}
-
-int emu10k1_waveout_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-	unsigned int voicenum;
-	u16 delay;
-
-	DPF(2, "emu10k1_waveout_setformat()\n");
-
-	if (woinst->state & WAVE_STATE_STARTED)
-		return -1;
-
-	query_format(wave_dev, format);
-
-	if (woinst->format.samplingrate != format->samplingrate ||
-	    woinst->format.channels != format->channels ||
-	    woinst->format.bitsperchannel != format->bitsperchannel) {
-
-		woinst->format = *format;
-
-		if (woinst->state == WAVE_STATE_CLOSED)
-			return 0;
-
-		emu10k1_timer_uninstall(card, &woinst->timer);
-
-		for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-			emu10k1_voice_free(&woinst->voice[voicenum]);
-
-			if (get_voice(card, woinst, voicenum) < 0) {
-				ERROR();
-				emu10k1_waveout_close(wave_dev);
-				return -1;
-			}
-		}
-
-		delay = (48000 * woinst->buffer.fragment_size) /
-			 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
-
-		emu10k1_timer_install(card, &woinst->timer, delay);
-	}
-
-	return 0;
-}
-
-void emu10k1_waveout_stop(struct emu10k1_wavedevice *wave_dev)
-{
-	struct emu10k1_card *card = wave_dev->card;
-	struct woinst *woinst = wave_dev->woinst;
-
-	DPF(2, "emu10k1_waveout_stop()\n");
-
-	if (!(woinst->state & WAVE_STATE_STARTED))
-		return;
-
-	emu10k1_timer_disable(card, &woinst->timer);
-
-	/* Stop actual voices */
-	emu10k1_voices_stop(woinst->voice, woinst->num_voices);
-
-	emu10k1_waveout_update(woinst);
-
-	woinst->state &= ~WAVE_STATE_STARTED;
-}
-
-/**
- * emu10k1_waveout_getxfersize -
- *
- * gives the total free bytes on the voice buffer, including silence bytes
- * (basically: total_free_bytes = free_bytes + silence_bytes).
- *
- */
-void emu10k1_waveout_getxfersize(struct woinst *woinst, u32 *total_free_bytes)
-{
-	struct waveout_buffer *buffer = &woinst->buffer;
-	int pending_bytes;
-
-	if (woinst->mmapped) {
-		*total_free_bytes = buffer->free_bytes;
-		return;
-	}
-
-	pending_bytes = buffer->size - buffer->free_bytes;
-
-	buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size * 2) ? 1 : 0;
-
-	if (pending_bytes > (signed) buffer->silence_bytes) {
-		*total_free_bytes = (buffer->free_bytes + buffer->silence_bytes);
-	} else {
-		*total_free_bytes = buffer->size;
-		buffer->silence_bytes = pending_bytes;
-		if (pending_bytes < 0) {
-			buffer->silence_pos = buffer->hw_pos;
-			buffer->silence_bytes = 0;
-			buffer->free_bytes = buffer->size;
-			DPF(1, "buffer underrun\n");
-		}
-	}
-}
-
-/**
- * copy_block -
- *
- * copies a block of pcm data to a voice buffer.
- * Notice that the voice buffer is actually a set of disjointed memory pages.
- *
- */
-static void copy_block(void **dst, u32 str, u8 __user *src, u32 len)
-{
-	unsigned int pg;
-	unsigned int pgoff;
-	unsigned int k;
-
-	pg = str / PAGE_SIZE;
-	pgoff = str % PAGE_SIZE;
-
-	if (len > PAGE_SIZE - pgoff) {
-		k = PAGE_SIZE - pgoff;
-		if (__copy_from_user((u8 *)dst[pg] + pgoff, src, k))
-			return;
-		len -= k;
-		while (len > PAGE_SIZE) {
-			if (__copy_from_user(dst[++pg], src + k, PAGE_SIZE))
-				return;
-			k += PAGE_SIZE;
-			len -= PAGE_SIZE;
-		}
-		if (__copy_from_user(dst[++pg], src + k, len))
-			return;
-
-	} else
-		__copy_from_user((u8 *)dst[pg] + pgoff, src, len);
-}
-
-/**
- * copy_ilv_block -
- *
- * copies a block of pcm data containing n interleaved channels to n mono voice buffers.
- * Notice that the voice buffer is actually a set of disjointed memory pages.
- *
- */
-static void copy_ilv_block(struct woinst *woinst, u32 str, u8 __user *src, u32 len) 
-{
-        unsigned int pg;
-	unsigned int pgoff;
-	unsigned int voice_num;
-	struct emu_voice *voice = woinst->voice;
-
-	pg = str / PAGE_SIZE;
-	pgoff = str % PAGE_SIZE;
-
-	while (len) { 
-		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) {
-			if (__copy_from_user((u8 *)(voice[voice_num].mem.addr[pg]) + pgoff, src, woinst->format.bytespervoicesample))
-				return;
-			src += woinst->format.bytespervoicesample;
-		}
-
-		len -= woinst->format.bytespervoicesample;
-
-		pgoff += woinst->format.bytespervoicesample;
-		if (pgoff >= PAGE_SIZE) {
-			pgoff = 0;
-			pg++;
-		}
-	}
-}
-
-/**
- * fill_block -
- *
- * fills a set voice buffers with a block of a given sample.
- *
- */
-static void fill_block(struct woinst *woinst, u32 str, u8 data, u32 len)
-{
-	unsigned int pg;
-	unsigned int pgoff;
-	unsigned int voice_num;
-        struct emu_voice *voice = woinst->voice;
-	unsigned int  k;
-
-	pg = str / PAGE_SIZE;
-	pgoff = str % PAGE_SIZE;
-
-	if (len > PAGE_SIZE - pgoff) {
-		k = PAGE_SIZE - pgoff;
-		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, k);
-		len -= k;
-		while (len > PAGE_SIZE) {
-			pg++;
-			for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-				memset(voice[voice_num].mem.addr[pg], data, PAGE_SIZE);
-
-			len -= PAGE_SIZE;
-		}
-		pg++;
-		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset(voice[voice_num].mem.addr[pg], data, len);
-
-	} else {
-		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, len);
-	}
-}
-
-/**
- * emu10k1_waveout_xferdata -
- *
- * copies pcm data to the voice buffer. Silence samples
- * previously added to the buffer are overwritten.
- *
- */
-void emu10k1_waveout_xferdata(struct woinst *woinst, u8 __user *data, u32 *size)
-{
-	struct waveout_buffer *buffer = &woinst->buffer;
-	struct voice_mem *mem = &woinst->voice[0].mem;
-	u32 sizetocopy, sizetocopy_now, start;
-	unsigned long flags;
-
-	sizetocopy = min_t(u32, buffer->size, *size);
-	*size = sizetocopy;
-
-	if (!sizetocopy)
-		return;
-	
-	spin_lock_irqsave(&woinst->lock, flags);
-	start = (buffer->size + buffer->silence_pos - buffer->silence_bytes) % buffer->size;
-
-	if (sizetocopy > buffer->silence_bytes) {
-		buffer->silence_pos += sizetocopy - buffer->silence_bytes;
-		buffer->free_bytes -= sizetocopy - buffer->silence_bytes;
-		buffer->silence_bytes = 0;
-	} else
-		buffer->silence_bytes -= sizetocopy;
-
-	spin_unlock_irqrestore(&woinst->lock, flags);
-
-	sizetocopy_now = buffer->size - start;
-	if (sizetocopy > sizetocopy_now) {
-		sizetocopy -= sizetocopy_now;
-		if (woinst->num_voices > 1) {
-			copy_ilv_block(woinst, start, data, sizetocopy_now);
-			copy_ilv_block(woinst, 0, data + sizetocopy_now * woinst->num_voices, sizetocopy);
-		} else {
-			copy_block(mem->addr, start, data, sizetocopy_now);
-			copy_block(mem->addr, 0, data + sizetocopy_now, sizetocopy);
-		}
-	} else {
-		if (woinst->num_voices > 1)
-			copy_ilv_block(woinst, start, data, sizetocopy);
-		else
-			copy_block(mem->addr, start, data, sizetocopy);
-	}
-}
-
-/**
- * emu10k1_waveout_fillsilence -
- *
- * adds samples of silence to the voice buffer so that we
- * don't loop over stale pcm data.
- *
- */
-void emu10k1_waveout_fillsilence(struct woinst *woinst)
-{
-	struct waveout_buffer *buffer = &woinst->buffer;
-	u32 sizetocopy, sizetocopy_now, start;
-	u8 filldata;
-	unsigned long flags;
-
-	sizetocopy = buffer->fragment_size;
-
-	if (woinst->format.bitsperchannel == 16)
-		filldata = 0x00;
-	else
-		filldata = 0x80;
-
-	spin_lock_irqsave(&woinst->lock, flags);
-	buffer->silence_bytes += sizetocopy;
-	buffer->free_bytes -= sizetocopy;
-	buffer->silence_pos %= buffer->size;
-	start = buffer->silence_pos;
-	buffer->silence_pos += sizetocopy;
-	spin_unlock_irqrestore(&woinst->lock, flags);
-
-	sizetocopy_now = buffer->size - start;
-
-	if (sizetocopy > sizetocopy_now) {
-		sizetocopy -= sizetocopy_now;
-		fill_block(woinst, start, filldata, sizetocopy_now);
-		fill_block(woinst, 0, filldata, sizetocopy);
-	} else {
-		fill_block(woinst, start, filldata, sizetocopy);
-	}
-}
-
-/**
- * emu10k1_waveout_update -
- *
- * updates the position of the voice buffer hardware pointer (hw_pos)
- * and the number of free bytes on the buffer (free_bytes).
- * The free bytes _don't_ include silence bytes that may have been
- * added to the buffer.
- *
- */
-void emu10k1_waveout_update(struct woinst *woinst)
-{
-	u32 hw_pos;
-	u32 diff;
-
-	/* There is no actual start yet */
-	if (!(woinst->state & WAVE_STATE_STARTED)) {
-		hw_pos = woinst->buffer.hw_pos;
-	} else {
-		/* hw_pos in sample units */
-		hw_pos = sblive_readptr(woinst->voice[0].card, CCCA_CURRADDR, woinst->voice[0].num);
-
-		if(hw_pos < woinst->voice[0].start)
-			hw_pos += woinst->buffer.size / woinst->format.bytespervoicesample - woinst->voice[0].start;
-		else
-			hw_pos -= woinst->voice[0].start;
-
-		hw_pos *= woinst->format.bytespervoicesample;
-	}
-
-	diff = (woinst->buffer.size + hw_pos - woinst->buffer.hw_pos) % woinst->buffer.size;
-	woinst->total_played += diff;
-	woinst->buffer.free_bytes += diff;
-	woinst->buffer.hw_pos = hw_pos;
-}
diff --git a/sound/oss/emu10k1/cardwo.h b/sound/oss/emu10k1/cardwo.h
deleted file mode 100644
index 1dece88..0000000
--- a/sound/oss/emu10k1/cardwo.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*     
- **********************************************************************
- *     cardwo.h -- header file for card wave out functions
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */
-
-#ifndef _CARDWO_H
-#define _CARDWO_H
-
-#include "icardwav.h"
-#include "audio.h"
-#include "voicemgr.h"
-#include "timer.h"
-
-/* setting this to other than a power of two may break some applications */
-#define WAVEOUT_MAXBUFSIZE	MAXBUFSIZE
-
-#define WAVEOUT_DEFAULTFRAGLEN	20 /* Time to play a fragment in ms (latency) */
-#define WAVEOUT_DEFAULTBUFLEN	500 /* Time to play the entire buffer in ms */
-
-#define WAVEOUT_MINFRAGSHIFT	6 /* Minimum fragment size in bytes is 2^6 */
-#define WAVEOUT_MINFRAGS	3 /* _don't_ go bellow 3, it would break silence filling */
-#define WAVEOUT_MAXVOICES	6
-
-struct waveout_buffer {
-	u16 ossfragshift;
-	u32 numfrags;
-	u32 fragment_size;	/* in bytes units */
-	u32 size;		/* in bytes units */
-	u32 pages;		/* buffer size in page units*/
-	u32 silence_pos;	/* software cursor position (including silence bytes) */
-	u32 hw_pos;		/* hardware cursor position */
-	u32 free_bytes;		/* free bytes available on the buffer (not including silence bytes) */
-	u8 fill_silence;
-	u32 silence_bytes;      /* silence bytes on the buffer */
-};
-
-struct woinst 
-{
-	u8 state;
-	u8 num_voices;
-	struct emu_voice voice[WAVEOUT_MAXVOICES];
-	struct emu_timer timer;
-	struct wave_format format;
-	struct waveout_buffer buffer;
-	wait_queue_head_t wait_queue;
-	u8 mmapped;
-	u32 total_copied;	/* total number of bytes written() to the buffer (excluding silence) */
-	u32 total_played;	/* total number of bytes played including silence */
-	u32 blocks;
-	u8 device;
-	spinlock_t lock;
-};
-
-int emu10k1_waveout_open(struct emu10k1_wavedevice *);
-void emu10k1_waveout_close(struct emu10k1_wavedevice *);
-void emu10k1_waveout_start(struct emu10k1_wavedevice *);
-void emu10k1_waveout_stop(struct emu10k1_wavedevice *);
-void emu10k1_waveout_getxfersize(struct woinst*, u32 *);
-void emu10k1_waveout_xferdata(struct woinst*, u8 __user *, u32 *);
-void emu10k1_waveout_fillsilence(struct woinst*);
-int emu10k1_waveout_setformat(struct emu10k1_wavedevice*, struct wave_format*);
-void emu10k1_waveout_update(struct woinst*);
-
-#endif /* _CARDWO_H */
diff --git a/sound/oss/emu10k1/ecard.c b/sound/oss/emu10k1/ecard.c
deleted file mode 100644
index 4ae635f..0000000
--- a/sound/oss/emu10k1/ecard.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*     
- **********************************************************************
- *     ecard.c - E-card initialization code
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */ 
-
-#include "ecard.h"
-#include "hwaccess.h"
-
-/* Private routines */
-static void ecard_setadcgain(struct emu10k1_card *, struct ecard_state *, u16);
-static void ecard_write(struct emu10k1_card *, u32);
-
-/**************************************************************************
- * @func Set the gain of the ECARD's CS3310 Trim/gain controller.  The
- * trim value consists of a 16bit value which is composed of two
- * 8 bit gain/trim values, one for the left channel and one for the
- * right channel.  The following table maps from the Gain/Attenuation
- * value in decibels into the corresponding bit pattern for a single
- * channel.
- */
-
-static void ecard_setadcgain(struct emu10k1_card *card, struct ecard_state *ecard, u16 gain)
-{
-	u32 currbit;
-	ecard->adc_gain = gain;
-
-	/* Enable writing to the TRIM registers */
-	ecard_write(card, ecard->control_bits & ~EC_TRIM_CSN);
-
-	/* Do it again to insure that we meet hold time requirements */
-	ecard_write(card, ecard->control_bits & ~EC_TRIM_CSN);
-
-	for (currbit = (1L << 15); currbit; currbit >>= 1) {
-
-		u32 value = ecard->control_bits & ~(EC_TRIM_CSN|EC_TRIM_SDATA);
-
-		if (gain & currbit)
-		      value |= EC_TRIM_SDATA;
-
-		/* Clock the bit */
-		ecard_write(card, value);
-		ecard_write(card, value | EC_TRIM_SCLK);
-		ecard_write(card, value);
-	}
-
-	ecard_write(card, ecard->control_bits);
-}
-
-/**************************************************************************
- * @func Clock bits into the Ecard's control latch.  The Ecard uses a
- *  control latch will is loaded bit-serially by toggling the Modem control
- *  lines from function 2 on the E8010.  This function hides these details
- *  and presents the illusion that we are actually writing to a distinct
- *  register.
- */
-static void ecard_write(struct emu10k1_card *card, u32 value)
-{
-	u16 count;
-	u32 data, hcvalue;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	hcvalue = inl(card->iobase + HCFG) & ~(HOOKN_BIT|HANDN_BIT|PULSEN_BIT);
-
-	outl(card->iobase + HCFG, hcvalue);
-
-	for (count = 0 ; count < EC_NUM_CONTROL_BITS; count++) {
-	
-		/* Set up the value */
-		data = ((value & 0x1) ? PULSEN_BIT : 0);
-		value >>= 1;
-
-		outl(card->iobase + HCFG, hcvalue | data);
-
-		/* Clock the shift register */
-		outl(card->iobase + HCFG, hcvalue | data | HANDN_BIT);
-		outl(card->iobase + HCFG, hcvalue | data);
-	}
-
-	/* Latch the bits */
-	outl(card->iobase + HCFG, hcvalue | HOOKN_BIT);
-	outl(card->iobase + HCFG, hcvalue);
-
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-void __devinit emu10k1_ecard_init(struct emu10k1_card *card)
-{
-	u32 hcvalue;
-	struct ecard_state ecard;
-
-	/* Set up the initial settings */
-	ecard.mux0_setting = EC_DEFAULT_SPDIF0_SEL;
-	ecard.mux1_setting = EC_DEFAULT_SPDIF1_SEL;
-	ecard.mux2_setting = 0;
-	ecard.adc_gain = EC_DEFAULT_ADC_GAIN;
-	ecard.control_bits = EC_RAW_RUN_MODE | 
-                             EC_SPDIF0_SELECT(ecard.mux0_setting) |
-			     EC_SPDIF1_SELECT(ecard.mux1_setting);
-
-
-	/* Step 0: Set the codec type in the hardware control register 
-	 * and enable audio output */
-	hcvalue = emu10k1_readfn0(card, HCFG);
-	emu10k1_writefn0(card, HCFG, hcvalue | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S);
-
-	/* Step 1: Turn off the led and deassert TRIM_CS */
-	ecard_write(card, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
-
-	/* Step 2: Calibrate the ADC and DAC */
-	ecard_write(card, EC_DACCAL | EC_LEDN | EC_TRIM_CSN);
-
-	/* Step 3: Wait for awhile; FIXME: Is this correct? */
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ);
-
-	/* Step 4: Switch off the DAC and ADC calibration.  Note
-	 * That ADC_CAL is actually an inverted signal, so we assert
-	 * it here to stop calibration.  */
-	ecard_write(card, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
-
-	/* Step 4: Switch into run mode */
-	ecard_write(card, ecard.control_bits);
-
-	/* Step 5: Set the analog input gain */
-	ecard_setadcgain(card, &ecard, ecard.adc_gain);
-}
-
-
diff --git a/sound/oss/emu10k1/ecard.h b/sound/oss/emu10k1/ecard.h
deleted file mode 100644
index 67aead1..0000000
--- a/sound/oss/emu10k1/ecard.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*     
- **********************************************************************
- *     ecard.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */ 
-
-#ifndef _ECARD_H
-#define _ECARD_H
-
-#include "8010.h"
-#include "hwaccess.h"
-#include <linux/init.h>
-
-/* In A1 Silicon, these bits are in the HC register */
-#define HOOKN_BIT   (1L << 12)
-#define HANDN_BIT   (1L << 11)
-#define PULSEN_BIT  (1L << 10)
-
-#define EC_GDI1 (1 << 13)
-#define EC_GDI0 (1 << 14)
-
-#define EC_NUM_CONTROL_BITS 20
-
-#define EC_AC3_DATA_SELN  0x0001L
-#define EC_EE_DATA_SEL    0x0002L
-#define EC_EE_CNTRL_SELN  0x0004L
-#define EC_EECLK          0x0008L
-#define EC_EECS           0x0010L
-#define EC_EESDO          0x0020L
-#define EC_TRIM_CSN	  0x0040L
-#define EC_TRIM_SCLK	  0x0080L
-#define EC_TRIM_SDATA	  0x0100L
-#define EC_TRIM_MUTEN	  0x0200L
-#define EC_ADCCAL	  0x0400L
-#define EC_ADCRSTN	  0x0800L
-#define EC_DACCAL	  0x1000L
-#define EC_DACMUTEN	  0x2000L
-#define EC_LEDN		  0x4000L
-
-#define EC_SPDIF0_SEL_SHIFT	15
-#define EC_SPDIF1_SEL_SHIFT	17	
-#define EC_SPDIF0_SEL_MASK	(0x3L << EC_SPDIF0_SEL_SHIFT)
-#define EC_SPDIF1_SEL_MASK	(0x7L << EC_SPDIF1_SEL_SHIFT)
-#define EC_SPDIF0_SELECT(_x) (((_x) << EC_SPDIF0_SEL_SHIFT) & EC_SPDIF0_SEL_MASK)
-#define EC_SPDIF1_SELECT(_x) (((_x) << EC_SPDIF1_SEL_SHIFT) & EC_SPDIF1_SEL_MASK)
-#define EC_CURRENT_PROM_VERSION 0x01 /* Self-explanatory.  This should
-                                      * be incremented any time the EEPROM's
-                                      * format is changed.  */
-
-#define EC_EEPROM_SIZE	        0x40 /* ECARD EEPROM has 64 16-bit words */
-
-/* Addresses for special values stored in to EEPROM */
-#define EC_PROM_VERSION_ADDR	0x20	/* Address of the current prom version */
-#define EC_BOARDREV0_ADDR	0x21	/* LSW of board rev */
-#define EC_BOARDREV1_ADDR 	0x22	/* MSW of board rev */ 
-
-#define EC_LAST_PROMFILE_ADDR	0x2f
-
-#define EC_SERIALNUM_ADD	0x30	/* First word of serial number.  The number
-                                         * can be up to 30 characters in length
-                                         * and is stored as a NULL-terminated
-                                         * ASCII string.  Any unused bytes must be
-                                         * filled with zeros */
-#define EC_CHECKSUM_ADDR	0x3f    /* Location at which checksum is stored */
-
-
-
-/* Most of this stuff is pretty self-evident.  According to the hardware 
- * dudes, we need to leave the ADCCAL bit low in order to avoid a DC 
- * offset problem.  Weird.
- */
-#define EC_RAW_RUN_MODE	(EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | EC_TRIM_CSN)
-
-
-#define EC_DEFAULT_ADC_GAIN   0xC4C4
-#define EC_DEFAULT_SPDIF0_SEL 0x0
-#define EC_DEFAULT_SPDIF1_SEL 0x4
-
-#define HC_EA 0x01L
-
-/* ECARD state structure.  This structure maintains the state
- * for various portions of the ECARD's onboard hardware.
- */
-struct ecard_state {
-	u32 control_bits;
-	u16 adc_gain;
-	u16 mux0_setting;
-	u16 mux1_setting;
-	u16 mux2_setting;
-};
-
-void emu10k1_ecard_init(struct emu10k1_card *) __devinit;
-
-#endif /* _ECARD_H */
diff --git a/sound/oss/emu10k1/efxmgr.c b/sound/oss/emu10k1/efxmgr.c
deleted file mode 100644
index 7d5865d..0000000
--- a/sound/oss/emu10k1/efxmgr.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- **********************************************************************
- *     efxmgr.c
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */
-
-#include <linux/bitops.h>
-#include "hwaccess.h"
-#include "efxmgr.h"
-
-int emu10k1_find_control_gpr(struct patch_manager *mgr, const char *patch_name, const char *gpr_name)
-{
-        struct dsp_patch *patch;
-	struct dsp_rpatch *rpatch;
-	char s[PATCH_NAME_SIZE + 4];
-	unsigned long *gpr_used;
-	int i;
-
-	DPD(2, "emu10k1_find_control_gpr(): %s %s\n", patch_name, gpr_name);
-
-	rpatch = &mgr->rpatch;
-	if (!strcmp(rpatch->name, patch_name)) {
-		gpr_used = rpatch->gpr_used;
-		goto match;
-	}
-
-	for (i = 0; i < mgr->current_pages * PATCHES_PER_PAGE; i++) {
-		patch = PATCH(mgr, i);
-			sprintf(s,"%s", patch->name);
-
-		if (!strcmp(s, patch_name)) {
-			gpr_used = patch->gpr_used;
-			goto match;
-		}
-	}
-
-	return -1;
-
-  match:
-	for (i = 0; i < NUM_GPRS; i++)
-		if (mgr->gpr[i].type == GPR_TYPE_CONTROL &&
-		    test_bit(i, gpr_used) &&
-		    !strcmp(mgr->gpr[i].name, gpr_name))
-			return i;
-
-	return -1;
-}
-
-void emu10k1_set_control_gpr(struct emu10k1_card *card, int addr, s32 val, int flag)
-{
-	struct patch_manager *mgr = &card->mgr;
-
-	DPD(2, "emu10k1_set_control_gpr(): %d %x\n", addr, val);
-
-	if (addr < 0 || addr >= NUM_GPRS)
-		return;
-
-	//fixme: once patch manager is up, remember to fix this for the audigy
-	if (card->is_audigy) {
-		sblive_writeptr(card, A_GPR_BASE + addr, 0, val);
-	} else {
-		if (flag)
-			val += sblive_readptr(card, GPR_BASE + addr, 0);
-		if (val > mgr->gpr[addr].max)
-			val = mgr->gpr[addr].max;
-		else if (val < mgr->gpr[addr].min)
-			val = mgr->gpr[addr].min;
-		sblive_writeptr(card, GPR_BASE + addr, 0, val);
-	}
-	
-	
-}
-
-//TODO: make this configurable:
-#define VOLCTRL_CHANNEL SOUND_MIXER_VOLUME
-#define VOLCTRL_STEP_SIZE        5
-
-//An internal function for setting OSS mixer controls.
-static void emu10k1_set_oss_vol(struct emu10k1_card *card, int oss_mixer,
-				unsigned int left, unsigned int right)
-{
-	extern char volume_params[SOUND_MIXER_NRDEVICES];
-
-	card->ac97->mixer_state[oss_mixer] = (right << 8) | left;
-
-	if (!card->is_aps)
-		card->ac97->write_mixer(card->ac97, oss_mixer, left, right);
-	
-	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left,
-			       volume_params[oss_mixer]);
-
-	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right,
-			       volume_params[oss_mixer]);
-}
-
-//FIXME: mute should unmute when pressed a second time
-void emu10k1_mute_irqhandler(struct emu10k1_card *card)
-{
-	int oss_channel = VOLCTRL_CHANNEL;
-	int left, right;
-	static int val;
-
-	if (val) {
-		left = val & 0xff;
-		right = (val >> 8) & 0xff;
-		val = 0;
-	} else {
-		val = card->ac97->mixer_state[oss_channel];
-		left = 0;
-		right = 0;
-	}
-
-	emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_volincr_irqhandler(struct emu10k1_card *card)
-{
-	int oss_channel = VOLCTRL_CHANNEL;
-	int left, right;
-
-	left = card->ac97->mixer_state[oss_channel] & 0xff;
-	right = (card->ac97->mixer_state[oss_channel] >> 8) & 0xff;
-
-	if ((left += VOLCTRL_STEP_SIZE) > 100)
-		left = 100;
-
-	if ((right += VOLCTRL_STEP_SIZE) > 100)
-		right = 100;
-
-	emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_voldecr_irqhandler(struct emu10k1_card *card)
-{
-	int oss_channel = VOLCTRL_CHANNEL;
-	int left, right;
-
-	left = card->ac97->mixer_state[oss_channel] & 0xff;
-	right = (card->ac97->mixer_state[oss_channel] >> 8) & 0xff;
-
-	if ((left -= VOLCTRL_STEP_SIZE) < 0)
-		left = 0;
-
-	if ((right -= VOLCTRL_STEP_SIZE) < 0)
-		right = 0;
-
-	emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int scale)
-{
-	struct patch_manager *mgr = &card->mgr;
-	unsigned long flags;
-
-	static const s32 log2lin[4] ={           //  attenuation (dB)
-		0x7fffffff,                      //       0.0         
-		0x7fffffff * 0.840896415253715 , //       1.5          
-		0x7fffffff * 0.707106781186548,  //       3.0
-		0x7fffffff * 0.594603557501361 , //       4.5
-	};
-
-	if (addr < 0)
-		return;
-
-	vol = (100 - vol ) * scale / 100;
-
-	// Thanks to the comp.dsp newsgroup for this neat trick:
-	vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
-
-	spin_lock_irqsave(&mgr->lock, flags);
-	emu10k1_set_control_gpr(card, addr, vol, 0);
-	spin_unlock_irqrestore(&mgr->lock, flags);
-}
-
-void emu10k1_dsp_irqhandler(struct emu10k1_card *card)
-{
-	unsigned long flags;
-
-	if (card->pt.state != PT_STATE_INACTIVE) {
-		u32 bc;
-		bc = sblive_readptr(card, GPR_BASE + card->pt.intr_gpr, 0);
-		if (bc != 0) {
-			DPD(3, "pt interrupt, bc = %d\n", bc);
-			spin_lock_irqsave(&card->pt.lock, flags);
-			card->pt.blocks_played = bc;
-			if (card->pt.blocks_played >= card->pt.blocks_copied) {
-				DPF(1, "buffer underrun in passthrough playback\n");
-				emu10k1_pt_stop(card);
-			}
-			wake_up_interruptible(&card->pt.wait);
-			spin_unlock_irqrestore(&card->pt.lock, flags);
-		}
-	}
-}
-
diff --git a/sound/oss/emu10k1/efxmgr.h b/sound/oss/emu10k1/efxmgr.h
deleted file mode 100644
index ef48e5c..0000000
--- a/sound/oss/emu10k1/efxmgr.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/*     
- **********************************************************************
- *     sblive_fx.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */
-
-#ifndef _EFXMGR_H
-#define _EFXMGR_H
-
-struct emu_efx_info_t{
-	int opcode_shift;
-	int high_operand_shift;
-	int instruction_start;
-	int gpr_base;
-	int output_base;
-};
-
-
-#define WRITE_EFX(a, b, c) sblive_writeptr((a), emu_efx_info[card->is_audigy].instruction_start + (b), 0, (c))
-
-#define OP(op, z, w, x, y) \
-	do { WRITE_EFX(card, (pc) * 2, ((x) << emu_efx_info[card->is_audigy].high_operand_shift) | (y)); \
-	WRITE_EFX(card, (pc) * 2 + 1, ((op) << emu_efx_info[card->is_audigy].opcode_shift ) | ((z) << emu_efx_info[card->is_audigy].high_operand_shift) | (w)); \
-	++pc; } while (0)
-
-#define NUM_INPUTS 0x20
-#define NUM_OUTPUTS 0x20
-#define NUM_GPRS 0x100
-
-#define A_NUM_INPUTS 0x60
-#define A_NUM_OUTPUTS 0x60  //fixme: this may or may not be true
-#define A_NUM_GPRS 0x200
-
-#define GPR_NAME_SIZE   32
-#define PATCH_NAME_SIZE 32
-
-struct dsp_rpatch {
-	char name[PATCH_NAME_SIZE];
-	u16 code_start;
-	u16 code_size;
-
-	unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
-	unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
-	unsigned long route[NUM_OUTPUTS];
-	unsigned long route_v[NUM_OUTPUTS];
-};
-
-struct dsp_patch {
-	char name[PATCH_NAME_SIZE];
-	u8 id;
-	unsigned long input;	/* bitmap of the lines used as inputs */
-	unsigned long output;	/* bitmap of the lines used as outputs */
-	u16 code_start;
-	u16 code_size;
-
-	unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];	/* bitmap of used gprs */
-	unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
-	u8 traml_istart;	/* starting address of the internal tram lines used */
-	u8 traml_isize;		/* number of internal tram lines used */
-
-	u8 traml_estart;
-	u8 traml_esize;
-
-	u16 tramb_istart;        /* starting address of the internal tram memory used */
-	u16 tramb_isize;         /* amount of internal memory used */
-	u32 tramb_estart;
-	u32 tramb_esize;
-};
-
-struct dsp_gpr {
-	u8 type;			/* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */
-	char name[GPR_NAME_SIZE];	/* gpr value, only valid for control gprs */
-	s32 min, max;			/* value range for this gpr, only valid for control gprs */
-	u8 line;			/* which input/output line is the gpr attached, only valid for input/output gprs */
-	u8 usage;
-};
-
-enum {
-	GPR_TYPE_NULL = 0,
-	GPR_TYPE_IO,
-	GPR_TYPE_STATIC,
-	GPR_TYPE_DYNAMIC,
-	GPR_TYPE_CONTROL,
-	GPR_TYPE_CONSTANT
-};
-
-#define GPR_BASE 0x100
-#define OUTPUT_BASE 0x20
-
-#define A_GPR_BASE 0x400
-#define A_OUTPUT_BASE 0x60
-
-#define MAX_PATCHES_PAGES 32
-
-struct patch_manager {
-	void *patch[MAX_PATCHES_PAGES];
-	int current_pages;
-	struct dsp_rpatch rpatch;
-	struct dsp_gpr gpr[NUM_GPRS];   /* gpr usage table */
-	spinlock_t lock;
-	s16 ctrl_gpr[SOUND_MIXER_NRDEVICES][2];
-};
-
-#define PATCHES_PER_PAGE (PAGE_SIZE / sizeof(struct dsp_patch))
-
-#define PATCH(mgr, i) ((struct dsp_patch *) (mgr)->patch[(i) / PATCHES_PER_PAGE] + (i) % PATCHES_PER_PAGE)
-
-/* PCM volume control */
-#define TMP_PCM_L     0x100 //temp PCM L (after the vol control)       
-#define TMP_PCM_R     0x101
-#define VOL_PCM_L     0x102 //vol PCM
-#define VOL_PCM_R     0x103
-
-/* Routing patch */
-#define TMP_AC_L      0x104 //tmp ac97 out
-#define TMP_AC_R      0x105
-#define TMP_REAR_L    0x106 //output - Temp Rear
-#define TMP_REAR_R    0x107
-#define TMP_DIGI_L    0x108 //output - Temp digital
-#define TMP_DIGI_R    0x109
-#define DSP_VOL_L     0x10a // main dsp volume
-#define DSP_VOL_R     0x10b
-
-/* hw inputs */
-#define PCM_IN_L 	0x00
-#define PCM_IN_R 	0x01
-
-#define PCM1_IN_L        0x04
-#define PCM1_IN_R        0x05
-//mutilchannel playback stream appear here:
-
-#define MULTI_FRONT_L	0x08
-#define MULTI_FRONT_R	0x09
-#define MULTI_REAR_L	0x0a
-#define MULTI_REAR_R	0x0b
-#define MULTI_CENTER	0x0c
-#define MULTI_LFE	0x0d
-
-#define AC97_IN_L	0x10
-#define AC97_IN_R	0x11
-#define SPDIF_CD_L	0x12
-#define SPDIF_CD_R	0x13
-
-/* hw outputs */
-#define AC97_FRONT_L	0x20
-#define AC97_FRONT_R	0x21
-#define DIGITAL_OUT_L	0x22
-#define DIGITAL_OUT_R	0x23
-#define DIGITAL_CENTER	0x24
-#define DIGITAL_LFE	0x25
-
-#define ANALOG_REAR_L	0x28
-#define ANALOG_REAR_R	0x29
-#define ADC_REC_L	0x2a
-#define ADC_REC_R	0x2b
-
-#define ANALOG_CENTER	0x31
-#define ANALOG_LFE	0x32
-
-
-#define INPUT_PATCH_START(patch, nm, ln, i)		\
-do {							\
-	patch = PATCH(mgr, patch_n);			\
-	strcpy(patch->name, nm);			\
-	patch->code_start = pc * 2;			\
-	patch->input = (1<<(0x1f&ln));			\
-	patch->output= (1<<(0x1f&ln));			\
-	patch->id = i;					\
-} while(0)
-
-#define INPUT_PATCH_END(patch)				\
-do {							\
-	patch->code_size = pc * 2 - patch->code_start;	\
-	patch_n++;					\
-} while(0)
-
-
-#define ROUTING_PATCH_START(patch, nm)	\
-do {					\
-	patch = &mgr->rpatch;		\
-	strcpy(patch->name, nm);	\
-	patch->code_start = pc * 2;	\
-} while(0)
-
-#define ROUTING_PATCH_END(patch)			\
-do {                                                    \
-	patch->code_size = pc * 2 - patch->code_start;      \
-} while(0)
-
-#define CONNECT(input, output) set_bit(input, &rpatch->route[(output) - OUTPUT_BASE]);
-
-#define CONNECT_V(input, output) set_bit(input, &rpatch->route_v[(output) - OUTPUT_BASE]);
-
-#define OUTPUT_PATCH_START(patch, nm, ln, i)		\
-do {							\
-	patch = PATCH(mgr, patch_n);			\
-	strcpy(patch->name, nm);			\
-	patch->code_start = pc * 2;			\
-	patch->input = (1<<(0x1f&ln));			\
-	patch->output= (1<<(0x1f&ln));			\
-	patch->id = i;					\
-} while(0)
-
-#define OUTPUT_PATCH_END(patch)				\
-do {							\
-	patch->code_size = pc * 2 - patch->code_start;	\
-	patch_n++;					\
-} while(0)
-
-#define GET_OUTPUT_GPR(patch, g, ln)			\
-do {							\
-	mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_IO;	\
-	mgr->gpr[(g) - GPR_BASE].usage++;		\
-	mgr->gpr[(g) - GPR_BASE].line = ln;		\
-	set_bit((g) - GPR_BASE, patch->gpr_used);	\
-} while(0)
-
-#define GET_INPUT_GPR(patch, g, ln)			\
-do {							\
-	mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_IO;	\
-	mgr->gpr[(g) - GPR_BASE].usage++;		\
-	mgr->gpr[(g) - GPR_BASE].line = ln;		\
-	set_bit((g) - GPR_BASE, patch->gpr_used);	\
-	set_bit((g) - GPR_BASE, patch->gpr_input);	\
-} while(0)
-
-#define GET_DYNAMIC_GPR(patch, g)				\
-do {								\
-	mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_DYNAMIC;	\
-	mgr->gpr[(g) - GPR_BASE].usage++;			\
-	set_bit((g) - GPR_BASE, patch->gpr_used);          	\
-} while(0)
-
-#define GET_CONTROL_GPR(patch, g, nm, a, b)			\
-do {								\
-	strcpy(mgr->gpr[(g) - GPR_BASE].name, nm);		\
-	mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_CONTROL;	\
-	mgr->gpr[(g) - GPR_BASE].usage++;			\
-	mgr->gpr[(g) - GPR_BASE].min = a;			\
-	mgr->gpr[(g) - GPR_BASE].max = b;			\
-	sblive_writeptr(card, g, 0, b);				\
-	set_bit((g) - GPR_BASE, patch->gpr_used);		\
-} while(0)
-
-#endif /* _EFXMGR_H */
diff --git a/sound/oss/emu10k1/emuadxmg.c b/sound/oss/emu10k1/emuadxmg.c
deleted file mode 100644
index d7d2d4c..0000000
--- a/sound/oss/emu10k1/emuadxmg.c
+++ /dev/null
@@ -1,104 +0,0 @@
-
-/*     
- **********************************************************************
- *     emuadxmg.c - Address space manager for emu10k1 driver 
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */
-
-#include "hwaccess.h"
-
-/* Allocates emu address space */
-
-int emu10k1_addxmgr_alloc(u32 size, struct emu10k1_card *card)
-{
-	u16 *pagetable = card->emupagetable;
-	u16 index = 0;
-	u16 numpages;
-	unsigned long flags;
-
-	/* Convert bytes to pages */
-	numpages = (size / EMUPAGESIZE) + ((size % EMUPAGESIZE) ? 1 : 0);
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	while (index < (MAXPAGES - 1)) {
-		if (pagetable[index] & 0x8000) {
-			/* This block of pages is in use, jump to the start of the next block. */
-			index += (pagetable[index] & 0x7fff);
-		} else {
-			/* Found free block */
-			if (pagetable[index] >= numpages) {
-
-				/* Block is large enough */
-
-				/* If free block is larger than the block requested
-				 * then adjust the size of the block remaining */
-				if (pagetable[index] > numpages)
-					pagetable[index + numpages] = pagetable[index] - numpages;
-
-				pagetable[index] = (numpages | 0x8000);	/* Mark block as used */
-
-				spin_unlock_irqrestore(&card->lock, flags);
-
-				return index;
-			} else {
-				/* Block too small, jump to the start of the next block */
-				index += pagetable[index];
-			}
-		}
-	}
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	return -1;
-}
-
-/* Frees a previously allocated emu address space. */
-
-void emu10k1_addxmgr_free(struct emu10k1_card *card, int index)
-{
-	u16 *pagetable = card->emupagetable;
-	u16 origsize = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	if (pagetable[index] & 0x8000) {
-		/* Block is allocated - mark block as free */
-		origsize = pagetable[index] & 0x7fff;
-		pagetable[index] = origsize;
-
-		/* If next block is free, we concat both blocks */
-		if (!(pagetable[index + origsize] & 0x8000))
-			pagetable[index] += pagetable[index + origsize] & 0x7fff;
-	}
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	return;
-}
diff --git a/sound/oss/emu10k1/hwaccess.c b/sound/oss/emu10k1/hwaccess.c
deleted file mode 100644
index 2dc16a8..0000000
--- a/sound/oss/emu10k1/hwaccess.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- **********************************************************************
- *     hwaccess.c -- Hardware access layer
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     December 9, 1999     Jon Taylor      rewrote the I/O subsystem
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include <asm/io.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "icardmid.h"
-
-/*************************************************************************
-* Function : srToPitch                                                   *
-* Input    : sampleRate - sampling rate                                  *
-* Return   : pitch value                                                 *
-* About    : convert sampling rate to pitch                              *
-* Note     : for 8010, sampling rate is at 48kHz, this function should   *
-*            be changed.                                                 *
-*************************************************************************/
-u32 srToPitch(u32 sampleRate)
-{
-	int i;
-
-	/* FIXME: These tables should be defined in a headerfile */
-	static u32 logMagTable[128] = {
-		0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
-		0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
-		0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
-		0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
-		0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
-		0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
-		0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
-		0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
-		0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
-		0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
-		0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
-		0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
-		0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
-		0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
-		0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
-		0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
-	};
-
-	static char logSlopeTable[128] = {
-		0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
-		0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
-		0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
-		0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
-		0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
-		0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
-		0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
-		0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
-		0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
-		0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
-		0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
-		0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
-		0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
-		0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
-		0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
-		0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
-	};
-
-	if (sampleRate == 0)
-		return 0;	/* Bail out if no leading "1" */
-
-	sampleRate *= 11185;	/* Scale 48000 to 0x20002380 */
-
-	for (i = 31; i > 0; i--) {
-		if (sampleRate & 0x80000000) {	/* Detect leading "1" */
-			return (u32) (((s32) (i - 15) << 20) +
-				      logMagTable[0x7f & (sampleRate >> 24)] +
-				      (0x7f & (sampleRate >> 17)) * logSlopeTable[0x7f & (sampleRate >> 24)]);
-		}
-		sampleRate = sampleRate << 1;
-	}
-
-	DPF(2, "srToPitch: BUG!\n");
-	return 0;		/* Should never reach this point */
-}
-
-/*******************************************
-* write/read PCI function 0 registers      *
-********************************************/
-void emu10k1_writefn0(struct emu10k1_card *card, u32 reg, u32 data)
-{
-	unsigned long flags;
-
-	if (reg & 0xff000000) {
-		u32 mask;
-		u8 size, offset;
-
-		size = (reg >> 24) & 0x3f;
-		offset = (reg >> 16) & 0x1f;
-		mask = ((1 << size) - 1) << offset;
-		data = (data << offset) & mask;
-		reg &= 0x7f;
-
-		spin_lock_irqsave(&card->lock, flags);
-		data |= inl(card->iobase + reg) & ~mask;
-		outl(data, card->iobase + reg);
-		spin_unlock_irqrestore(&card->lock, flags);
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-		outl(data, card->iobase + reg);
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-
-	return;
-}
-
-#ifdef DBGEMU
-void emu10k1_writefn0_2(struct emu10k1_card *card, u32 reg, u32 data, int size)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	if (size == 32)
-		outl(data, card->iobase + (reg & 0x1F));
-	else if (size == 16)
-		outw(data, card->iobase + (reg & 0x1F));
-	else
-		outb(data, card->iobase + (reg & 0x1F));
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	return;
-}
-#endif  /*  DBGEMU  */
-
-u32 emu10k1_readfn0(struct emu10k1_card * card, u32 reg)
-{
-	u32 val;
-	unsigned long flags;
-
-	if (reg & 0xff000000) {
-		u32 mask;
-		u8 size, offset;
-
-		size = (reg >> 24) & 0x3f;
-		offset = (reg >> 16) & 0x1f;
-		mask = ((1 << size) - 1) << offset;
-		reg &= 0x7f;
-
-		spin_lock_irqsave(&card->lock, flags);
-		val = inl(card->iobase + reg);
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		return (val & mask) >> offset;
-        } else {
-		spin_lock_irqsave(&card->lock, flags);
-		val = inl(card->iobase + reg);
-		spin_unlock_irqrestore(&card->lock, flags);
-		return val;
-	}
-}
-
-void emu10k1_timer_set(struct emu10k1_card * card, u16 data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	outw(data & TIMER_RATE_MASK, card->iobase + TIMER);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/************************************************************************
-* write/read Emu10k1 pointer-offset register set, accessed through      *
-*  the PTR and DATA registers                                           *
-*************************************************************************/
-#define A_PTR_ADDRESS_MASK 0x0fff0000
-void sblive_writeptr(struct emu10k1_card *card, u32 reg, u32 channel, u32 data)
-{
-	u32 regptr;
-	unsigned long flags;
-
-	regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
-
-	if (reg & 0xff000000) {
-		u32 mask;
-		u8 size, offset;
-
-		size = (reg >> 24) & 0x3f;
-		offset = (reg >> 16) & 0x1f;
-		mask = ((1 << size) - 1) << offset;
-		data = (data << offset) & mask;
-
-		spin_lock_irqsave(&card->lock, flags);
-		outl(regptr, card->iobase + PTR);
-		data |= inl(card->iobase + DATA) & ~mask;
-		outl(data, card->iobase + DATA);
-		spin_unlock_irqrestore(&card->lock, flags);
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-		outl(regptr, card->iobase + PTR);
-		outl(data, card->iobase + DATA);
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-}
-
-/* ... :  data, reg, ... , TAGLIST_END */
-void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...)
-{
-	va_list args;
-
-	unsigned long flags;
-        u32 reg;
-
-	va_start(args, channel);
-
-	spin_lock_irqsave(&card->lock, flags);
-	while ((reg = va_arg(args, u32)) != TAGLIST_END) {
-		u32 data = va_arg(args, u32);
-		u32 regptr = (((reg << 16) & A_PTR_ADDRESS_MASK)
-			      | (channel & PTR_CHANNELNUM_MASK));
-		outl(regptr, card->iobase + PTR);
-		if (reg & 0xff000000) {
-			int size = (reg >> 24) & 0x3f;
-                        int offset = (reg >> 16) & 0x1f;
-			u32 mask = ((1 << size) - 1) << offset;
-			data = (data << offset) & mask;
-
-			data |= inl(card->iobase + DATA) & ~mask;
-		}
-		outl(data, card->iobase + DATA);
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	va_end(args);
-
-	return;
-}
-
-u32 sblive_readptr(struct emu10k1_card * card, u32 reg, u32 channel)
-{
-	u32 regptr, val;
-	unsigned long flags;
-
-	regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
-
-	if (reg & 0xff000000) {
-		u32 mask;
-		u8 size, offset;
-
-		size = (reg >> 24) & 0x3f;
-		offset = (reg >> 16) & 0x1f;
-		mask = ((1 << size) - 1) << offset;
-
-		spin_lock_irqsave(&card->lock, flags);
-		outl(regptr, card->iobase + PTR);
-		val = inl(card->iobase + DATA);
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		return (val & mask) >> offset;
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-		outl(regptr, card->iobase + PTR);
-		val = inl(card->iobase + DATA);
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		return val;
-	}
-}
-
-void emu10k1_irq_enable(struct emu10k1_card *card, u32 irq_mask)
-{
-	u32 val;
-	unsigned long flags;
-
-	DPF(2,"emu10k1_irq_enable()\n");
-
-	spin_lock_irqsave(&card->lock, flags);
-        val = inl(card->iobase + INTE) | irq_mask;
-        outl(val, card->iobase + INTE);
-	spin_unlock_irqrestore(&card->lock, flags);
-	return;
-}
-
-void emu10k1_irq_disable(struct emu10k1_card *card, u32 irq_mask)
-{
-        u32 val;
-        unsigned long flags;
-
-        DPF(2,"emu10k1_irq_disable()\n");
-
-        spin_lock_irqsave(&card->lock, flags);
-        val = inl(card->iobase + INTE) & ~irq_mask;
-        outl(val, card->iobase + INTE);
-        spin_unlock_irqrestore(&card->lock, flags);
-        return;
-}
-
-void emu10k1_clear_stop_on_loop(struct emu10k1_card *card, u32 voicenum)
-{
-	/* Voice interrupt */
-	if (voicenum >= 32)
-		sblive_writeptr(card, SOLEH | ((0x0100 | (voicenum - 32)) << 16), 0, 0);
-	else
-		sblive_writeptr(card, SOLEL | ((0x0100 | voicenum) << 16), 0, 0);
-
-	return;
-}
-
-static void sblive_wcwait(struct emu10k1_card *card, u32 wait)
-{
-	volatile unsigned uCount;
-	u32 newtime = 0, curtime;
-
-	curtime = emu10k1_readfn0(card, WC_SAMPLECOUNTER);
-	while (wait--) {
-		uCount = 0;
-		while (uCount++ < TIMEOUT) {
-			newtime = emu10k1_readfn0(card, WC_SAMPLECOUNTER);
-			if (newtime != curtime)
-				break;
-		}
-
-		if (uCount >= TIMEOUT)
-			break;
-
-		curtime = newtime;
-	}
-}
-
-u16 emu10k1_ac97_read(struct ac97_codec *codec, u8 reg)
-{
-	struct emu10k1_card *card = codec->private_data;
-	u16 data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	outb(reg, card->iobase + AC97ADDRESS);
-	data = inw(card->iobase + AC97DATA);
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	return data;
-}
-
-void emu10k1_ac97_write(struct ac97_codec *codec, u8 reg, u16 value)
-{
-	struct emu10k1_card *card = codec->private_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	outb(reg, card->iobase + AC97ADDRESS);
-	outw(value, card->iobase + AC97DATA);
-	outb( AC97_EXTENDED_ID, card->iobase + AC97ADDRESS); 
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/*********************************************************
-*            MPU access functions                        *
-**********************************************************/
-
-int emu10k1_mpu_write_data(struct emu10k1_card *card, u8 data)
-{
-	unsigned long flags;
-	int ret;
-
-	if (card->is_audigy) {
-		if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_ORDYN) == 0) {
-			sblive_writeptr(card, A_MUDATA, 0, data);
-			ret = 0;
-		} else
-			ret = -1;
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-
-		if ((inb(card->iobase + MUSTAT) & MUSTAT_ORDYN) == 0) {
-			outb(data, card->iobase + MUDATA);
-			ret = 0;
-		} else
-			ret = -1;
-
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-
-	return ret;
-}
-
-int emu10k1_mpu_read_data(struct emu10k1_card *card, u8 * data)
-{
-	unsigned long flags;
-	int ret;
-
-	if (card->is_audigy) {
-		if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_IRDYN) == 0) {
-			*data = sblive_readptr(card, A_MUDATA,0);
-			ret = 0;
-		} else
-			ret = -1;
-	} else {
-		spin_lock_irqsave(&card->lock, flags);
-
-		if ((inb(card->iobase + MUSTAT) & MUSTAT_IRDYN) == 0) {
-			*data = inb(card->iobase + MUDATA);
-			ret = 0;
-		} else
-			ret = -1;
-
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-
-	return ret;
-}
-
-int emu10k1_mpu_reset(struct emu10k1_card *card)
-{
-	u8 status;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_mpu_reset()\n");
-	if (card->is_audigy) {
-		if (card->mpuacqcount == 0) {
-			sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET);
-			sblive_wcwait(card, 8);
-			sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET);
-			sblive_wcwait(card, 8);
-			sblive_writeptr(card, A_MUCMD, 0, MUCMD_ENTERUARTMODE);
-			sblive_wcwait(card, 8);
-			status = sblive_readptr(card, A_MUDATA, 0);
-			if (status == 0xfe)
-				return 0;
-			else
-				return -1;
-		}
-
-		return 0;
-	} else {
-		if (card->mpuacqcount == 0) {
-			spin_lock_irqsave(&card->lock, flags);
-			outb(MUCMD_RESET, card->iobase + MUCMD);
-			spin_unlock_irqrestore(&card->lock, flags);
-
-			sblive_wcwait(card, 8);
-
-			spin_lock_irqsave(&card->lock, flags);
-			outb(MUCMD_RESET, card->iobase + MUCMD);
-			spin_unlock_irqrestore(&card->lock, flags);
-
-			sblive_wcwait(card, 8);
-
-			spin_lock_irqsave(&card->lock, flags);
-			outb(MUCMD_ENTERUARTMODE, card->iobase + MUCMD);
-			spin_unlock_irqrestore(&card->lock, flags);
-
-			sblive_wcwait(card, 8);
-
-			spin_lock_irqsave(&card->lock, flags);
-			status = inb(card->iobase + MUDATA);
-			spin_unlock_irqrestore(&card->lock, flags);
-
-			if (status == 0xfe)
-				return 0;
-			else
-				return -1;
-		}
-
-		return 0;
-	}
-}
-
-int emu10k1_mpu_acquire(struct emu10k1_card *card)
-{
-	/* FIXME: This should be a macro */
-	++card->mpuacqcount;
-
-	return 0;
-}
-
-int emu10k1_mpu_release(struct emu10k1_card *card)
-{
-	/* FIXME: this should be a macro */
-	--card->mpuacqcount;
-
-	return 0;
-}
diff --git a/sound/oss/emu10k1/hwaccess.h b/sound/oss/emu10k1/hwaccess.h
deleted file mode 100644
index 85e27bd..0000000
--- a/sound/oss/emu10k1/hwaccess.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- **********************************************************************
- *     hwaccess.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date		    Author	    Summary of changes
- *     ----		    ------	    ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#ifndef _HWACCESS_H
-#define _HWACCESS_H
-
-#include <linux/fs.h>
-#include <linux/sound.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <asm/io.h>
-
-#include "efxmgr.h"
-#include "passthrough.h"
-#include "midi.h"
-
-#define EMUPAGESIZE     4096            /* don't change */
-#define NUM_G           64              /* use all channels */
-#define NUM_FXSENDS     4               /* don't change */
-/* setting this to other than a power of two may break some applications */
-#define MAXBUFSIZE	65536
-#define MAXPAGES	8192 
-#define BUFMAXPAGES     (MAXBUFSIZE / PAGE_SIZE)
-
-#define FLAGS_AVAILABLE     0x0001
-#define FLAGS_READY         0x0002
-
-struct memhandle
-{
-	dma_addr_t dma_handle;
-	void *addr;
-	u32 size;
-};
-
-#define DEBUG_LEVEL 2
-
-#ifdef EMU10K1_DEBUG
-# define DPD(level,x,y...) do {if(level <= DEBUG_LEVEL) printk( KERN_NOTICE "emu10k1: %s: %d: " x , __FILE__ , __LINE__ , y );} while(0)
-# define DPF(level,x)   do {if(level <= DEBUG_LEVEL) printk( KERN_NOTICE "emu10k1: %s: %d: " x , __FILE__ , __LINE__ );} while(0)
-#else
-# define DPD(level,x,y...) do { } while (0) /* not debugging: nothing */
-# define DPF(level,x) do { } while (0)
-#endif /* EMU10K1_DEBUG */
-
-#define ERROR() DPF(1,"error\n")
-
-/* DATA STRUCTURES */
-
-struct emu10k1_waveout
-{
-	u32 send_routing[3];
-	// audigy only:
-	u32 send_routing2[3];
-
-	u32 send_dcba[3];
-	// audigy only:
-	u32 send_hgfe[3];
-};
-#define ROUTE_PCM 0
-#define ROUTE_PT 1
-#define ROUTE_PCM1 2
-
-#define SEND_MONO 0
-#define SEND_LEFT 1
-#define SEND_RIGHT 2
-
-struct emu10k1_wavein
-{
-        struct wiinst *ac97;
-        struct wiinst *mic;
-        struct wiinst *fx;
-
-        u8 recsrc;
-        u32 fxwc;
-};
-
-#define CMD_READ 1
-#define CMD_WRITE 2
-
-struct mixer_private_ioctl {
-        u32 cmd;
-        u32 val[90];
-};
-
-/* bogus ioctls numbers to escape from OSS mixer limitations */
-#define CMD_WRITEFN0            _IOW('D', 0, struct mixer_private_ioctl)
-#define CMD_READFN0		_IOR('D', 1, struct mixer_private_ioctl) 
-#define CMD_WRITEPTR		_IOW('D', 2, struct mixer_private_ioctl) 
-#define CMD_READPTR		_IOR('D', 3, struct mixer_private_ioctl) 
-#define CMD_SETRECSRC		_IOW('D', 4, struct mixer_private_ioctl) 
-#define CMD_GETRECSRC		_IOR('D', 5, struct mixer_private_ioctl) 
-#define CMD_GETVOICEPARAM	_IOR('D', 6, struct mixer_private_ioctl) 
-#define CMD_SETVOICEPARAM	_IOW('D', 7, struct mixer_private_ioctl) 
-#define CMD_GETPATCH		_IOR('D', 8, struct mixer_private_ioctl) 
-#define CMD_GETGPR		_IOR('D', 9, struct mixer_private_ioctl) 
-#define CMD_GETCTLGPR           _IOR('D', 10, struct mixer_private_ioctl)
-#define CMD_SETPATCH		_IOW('D', 11, struct mixer_private_ioctl) 
-#define CMD_SETGPR		_IOW('D', 12, struct mixer_private_ioctl) 
-#define CMD_SETCTLGPR		_IOW('D', 13, struct mixer_private_ioctl)
-#define CMD_SETGPOUT		_IOW('D', 14, struct mixer_private_ioctl)
-#define CMD_GETGPR2OSS		_IOR('D', 15, struct mixer_private_ioctl)
-#define CMD_SETGPR2OSS		_IOW('D', 16, struct mixer_private_ioctl)
-#define CMD_SETMCH_FX		_IOW('D', 17, struct mixer_private_ioctl)
-#define CMD_SETPASSTHROUGH	_IOW('D', 18, struct mixer_private_ioctl)
-#define CMD_PRIVATE3_VERSION	_IOW('D', 19, struct mixer_private_ioctl)
-#define CMD_AC97_BOOST		_IOW('D', 20, struct mixer_private_ioctl)
-
-//up this number when breaking compatibility
-#define PRIVATE3_VERSION 2
-
-struct emu10k1_card 
-{
-	struct list_head list;
-
-	struct memhandle	virtualpagetable;
-	struct memhandle	tankmem;
-	struct memhandle	silentpage;
-
-	spinlock_t		lock;
-
-	u8			voicetable[NUM_G];
-	u16			emupagetable[MAXPAGES];
-
-	struct list_head	timers;
-	u16			timer_delay;
-	spinlock_t		timer_lock;
-
-	struct pci_dev		*pci_dev;
-	unsigned long           iobase;
-	unsigned long		length;
-	unsigned short		model;
-	unsigned int irq; 
-
-	int	audio_dev;
-	int	audio_dev1;
-	int	midi_dev;
-#ifdef EMU10K1_SEQUENCER
-	int seq_dev;
-	struct emu10k1_mididevice *seq_mididev;
-#endif
-
-	struct ac97_codec *ac97;
-	int ac97_supported_mixers;
-	int ac97_stereo_mixers;
-
-	/* Number of first fx voice for multichannel output */
-	u8 mchannel_fx;
-	struct emu10k1_waveout	waveout;
-	struct emu10k1_wavein	wavein;
-	struct emu10k1_mpuout	*mpuout;
-	struct emu10k1_mpuin	*mpuin;
-
-	struct mutex		open_sem;
-	mode_t			open_mode;
-	wait_queue_head_t	open_wait;
-
-	u32	    mpuacqcount;	  // Mpu acquire count
-	u32	    has_toslink;	       // TOSLink detection
-
-	u8 chiprev;                    /* Chip revision                */
-	u8 is_audigy;
-	u8 is_aps;
-
-	struct patch_manager mgr;
-	struct pt_data pt;
-};
-
-int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *);
-void emu10k1_addxmgr_free(struct emu10k1_card *, int);
-
-int emu10k1_find_control_gpr(struct patch_manager *, const char *, const char *);
-void emu10k1_set_control_gpr(struct emu10k1_card *, int , s32, int );
-
-void emu10k1_set_volume_gpr(struct emu10k1_card *, int, s32, int);
-
-
-#define VOL_6BIT 0x40
-#define VOL_5BIT 0x20
-#define VOL_4BIT 0x10
-
-#define TIMEOUT 		    16384
-
-u32 srToPitch(u32);
-
-extern struct list_head emu10k1_devs;
-
-/* Hardware Abstraction Layer access functions */
-
-void emu10k1_writefn0(struct emu10k1_card *, u32, u32);
-void emu10k1_writefn0_2(struct emu10k1_card *, u32, u32, int);
-u32 emu10k1_readfn0(struct emu10k1_card *, u32);
-
-void emu10k1_timer_set(struct emu10k1_card *, u16);
-
-void sblive_writeptr(struct emu10k1_card *, u32, u32, u32);
-void sblive_writeptr_tag(struct emu10k1_card *, u32, ...);
-#define TAGLIST_END	0
-
-u32 sblive_readptr(struct emu10k1_card *, u32 , u32 );
-
-void emu10k1_irq_enable(struct emu10k1_card *, u32);
-void emu10k1_irq_disable(struct emu10k1_card *, u32);
-void emu10k1_clear_stop_on_loop(struct emu10k1_card *, u32);
-
-/* AC97 Codec register access function */
-u16 emu10k1_ac97_read(struct ac97_codec *, u8);
-void emu10k1_ac97_write(struct ac97_codec *, u8, u16);
-
-/* MPU access function*/
-int emu10k1_mpu_write_data(struct emu10k1_card *, u8);
-int emu10k1_mpu_read_data(struct emu10k1_card *, u8 *);
-int emu10k1_mpu_reset(struct emu10k1_card *);
-int emu10k1_mpu_acquire(struct emu10k1_card *);
-int emu10k1_mpu_release(struct emu10k1_card *);
-
-#endif  /* _HWACCESS_H */
diff --git a/sound/oss/emu10k1/icardmid.h b/sound/oss/emu10k1/icardmid.h
deleted file mode 100644
index 6a6ef41..0000000
--- a/sound/oss/emu10k1/icardmid.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- **********************************************************************
- *     isblive_mid.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#ifndef _ICARDMIDI_H
-#define _ICARDMIDI_H
-
-/* MIDI defines */
-#define MIDI_DATA_FIRST                 0x00
-#define MIDI_DATA_LAST                  0x7F
-#define MIDI_STATUS_FIRST               0x80
-#define MIDI_STATUS_LAST                0xFF
-
-/* Channel status bytes */
-#define MIDI_STATUS_CHANNEL_FIRST       0x80
-#define MIDI_STATUS_CHANNEL_LAST        0xE0
-#define MIDI_STATUS_CHANNEL_MASK        0xF0
-
-/* Channel voice messages */
-#define MIDI_VOICE_NOTE_OFF             0x80
-#define MIDI_VOICE_NOTE_ON              0x90
-#define MIDI_VOICE_POLY_PRESSURE        0xA0
-#define MIDI_VOICE_CONTROL_CHANGE       0xB0
-#define MIDI_VOICE_PROGRAM_CHANGE       0xC0
-#define MIDI_VOICE_CHANNEL_PRESSURE     0xD0
-#define MIDI_VOICE_PITCH_BEND           0xE0
-
-/* Channel mode messages */
-#define MIDI_MODE_CHANNEL               MIDI_VOICE_CONTROL_CHANGE
-
-/* System status bytes */
-#define MIDI_STATUS_SYSTEM_FIRST        0xF0
-#define MIDI_STATUS_SYSTEM_LAST         0xFF
-
-/* System exclusive messages */
-#define MIDI_SYSEX_BEGIN                0xF0
-#define MIDI_SYSEX_EOX                  0xF7
-
-/* System common messages */
-#define MIDI_COMMON_TCQF                0xF1	/* Time code quarter frame  */
-#define MIDI_COMMON_SONG_POSITION       0xF2
-#define MIDI_COMMON_SONG_SELECT         0xF3
-#define MIDI_COMMON_UNDEFINED_F4        0xF4
-#define MIDI_COMMON_UNDEFINED_F5        0xF5
-#define MIDI_COMMON_TUNE_REQUEST        0xF6
-
-/* System real-time messages */
-#define MIDI_RTIME_TIMING_CLOCK         0xF8
-#define MIDI_RTIME_UNDEFINED_F9         0xF9
-#define MIDI_RTIME_START                0xFA
-#define MIDI_RTIME_CONTINUE             0xFB
-#define MIDI_RTIME_STOP                 0xFC
-#define MIDI_RTIME_UNDEFINED_FD         0xFD
-#define MIDI_RTIME_ACTIVE_SENSING       0xFE
-#define MIDI_RTIME_SYSTEM_RESET         0xFF
-
-/* Flags for flags parm of midiOutCachePatches(), midiOutCacheDrumPatches() */
-#define MIDI_CACHE_ALL                  1
-#define MIDI_CACHE_BESTFIT              2
-#define MIDI_CACHE_QUERY                3
-#define MIDI_UNCACHE                    4
-
-/* Event declarations for MPU IRQ Callbacks */
-#define ICARDMIDI_INLONGDATA            0x00000001 /* MIM_LONGDATA */
-#define ICARDMIDI_INLONGERROR           0x00000002 /* MIM_LONGERROR */
-#define ICARDMIDI_OUTLONGDATA           0x00000004 /* MOM_DONE for MPU OUT buffer */
-#define ICARDMIDI_INDATA                0x00000010 /* MIM_DATA */
-#define ICARDMIDI_INDATAERROR           0x00000020 /* MIM_ERROR */
-
-/* Declaration for flags in CARDMIDIBUFFERHDR */
-/* Make it the same as MHDR_DONE, MHDR_INQUEUE in mmsystem.h */
-#define MIDIBUF_DONE                    0x00000001
-#define MIDIBUF_INQUEUE                 0x00000004
-
-/* Declaration for msg parameter in midiCallbackFn */
-#define ICARDMIDI_OUTBUFFEROK           0x00000001
-#define ICARDMIDI_INMIDIOK              0x00000002
-
-/* Declaration for technology in struct midi_caps */
-#define MT_MIDIPORT                     0x00000001	/* In original MIDIOUTCAPS structure */
-#define MT_FMSYNTH                      0x00000004	/* In original MIDIOUTCAPS structure */
-#define MT_AWESYNTH                     0x00001000
-#define MT_PCISYNTH                     0x00002000
-#define MT_PCISYNTH64                   0x00004000
-#define CARDMIDI_AWEMASK                0x0000F000
-
-enum LocalErrorCode
-{
-        CTSTATUS_NOTENABLED = 0x7000,
-        CTSTATUS_READY,
-        CTSTATUS_BUSY,
-        CTSTATUS_DATAAVAIL,
-        CTSTATUS_NODATA,
-        CTSTATUS_NEXT_BYTE
-};
-
-/* MIDI data block header */
-struct midi_hdr
-{
-	u8 *reserved;		/* Pointer to original locked data block */
-	u32 bufferlength;	/* Length of data in data block */
-	u32 bytesrecorded;	/* Used for input only */
-	u32 user;		/* For client's use */
-	u32 flags;		/* Assorted flags (see defines) */
-	struct list_head list;	/* Reserved for driver */
-	u8 *data;		/* Second copy of first pointer */
-};
-
-/* Enumeration for SetControl */
-enum
-{
-	MIDIOBJVOLUME = 0x1,
-	MIDIQUERYACTIVEINST
-};
-
-struct midi_queue
-{
-	struct midi_queue  *next;
-	u32 qtype;            /* 0 = short message, 1 = long data */
-	u32 length;
-	u32 sizeLeft;
-	u8 *midibyte;
-	unsigned long refdata;
-};
-
-struct midi_openinfo
-{
-	u32     cbsize;
-	u32     flags;
-	unsigned long  refdata;
-	u32     streamid;
-};
-
-int emu10k1_midi_callback(unsigned long , unsigned long, unsigned long *);
-
-#endif /* _ICARDMIDI_H */
diff --git a/sound/oss/emu10k1/icardwav.h b/sound/oss/emu10k1/icardwav.h
deleted file mode 100644
index 25be409..0000000
--- a/sound/oss/emu10k1/icardwav.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*     
- **********************************************************************
- *     icardwav.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */
-
-#ifndef _ICARDWAV_H
-#define _ICARDWAV_H
-
-struct wave_format 
-{
-	int id;
-	int samplingrate;
-	u8 bitsperchannel;
-	u8 channels;		/* 1 = Mono, 2 = Stereo, 3, ... = Multichannel */
-	u8 bytesperchannel;
-	u8 bytespervoicesample;
-	u8 bytespersample;
-	int bytespersec;
-	u8 passthrough;
-};
-
-/* emu10k1_wave states */
-#define WAVE_STATE_OPEN		0x01	
-#define WAVE_STATE_STARTED	0x02
-#define WAVE_STATE_CLOSED	0x04
-
-#endif /* _ICARDWAV_H */
diff --git a/sound/oss/emu10k1/irqmgr.c b/sound/oss/emu10k1/irqmgr.c
deleted file mode 100644
index fb2ce63..0000000
--- a/sound/oss/emu10k1/irqmgr.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- **********************************************************************
- *     irqmgr.c - IRQ manager for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "cardmi.h"
-#include "cardmo.h"
-#include "irqmgr.h"
-
-/* Interrupt handler */
-
-irqreturn_t emu10k1_interrupt(int irq, void *dev_id)
-{
-	struct emu10k1_card *card = (struct emu10k1_card *) dev_id;
-	u32 irqstatus, irqstatus_tmp;
-	int handled = 0;
-
-	DPD(4, "emu10k1_interrupt called, irq =  %u\n", irq);
-
-	/*
-	 ** NOTE :
-	 ** We do a 'while loop' here cos on certain machines, with both
-	 ** playback and recording going on at the same time, IRQs will
-	 ** stop coming in after a while. Checking IPND indeed shows that
-	 ** there are interrupts pending but the PIC says no IRQs pending.
-	 ** I suspect that some boards need edge-triggered IRQs but are not
-	 ** getting that condition if we don't completely clear the IPND
-	 ** (make sure no more interrupts are pending).
-	 ** - Eric
-	 */
-
-	while ((irqstatus = inl(card->iobase + IPR))) {
-		DPD(4, "irq status %#x\n", irqstatus);
-
-		irqstatus_tmp = irqstatus;
-
-		if (irqstatus & IRQTYPE_TIMER) {
-			emu10k1_timer_irqhandler(card);
-			irqstatus &= ~IRQTYPE_TIMER;
-		}
-
-		if (irqstatus & IRQTYPE_DSP) {
-			emu10k1_dsp_irqhandler(card);
-			irqstatus &= ~IRQTYPE_DSP;
-		}
-
-		if (irqstatus & IRQTYPE_MPUIN) {
-			emu10k1_mpuin_irqhandler(card);
-			irqstatus &= ~IRQTYPE_MPUIN;
-		}
-
-		if (irqstatus & IRQTYPE_MPUOUT) {
-			emu10k1_mpuout_irqhandler(card);
-			irqstatus &= ~IRQTYPE_MPUOUT;
-		}
-
-		if (irqstatus & IPR_MUTE) {
-			emu10k1_mute_irqhandler(card);
-			irqstatus &=~IPR_MUTE;
-		}
-
-		if (irqstatus & IPR_VOLINCR) {
-			emu10k1_volincr_irqhandler(card);
-			irqstatus &=~IPR_VOLINCR;
-		}
-
-		if (irqstatus & IPR_VOLDECR) {
-			emu10k1_voldecr_irqhandler(card);
-			irqstatus &=~IPR_VOLDECR;
-		}
-
-		if (irqstatus){
-			printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: %#08x\n", irqstatus);
-			//make sure any interrupts we don't handle are disabled:
-			emu10k1_irq_disable(card, ~(INTE_MIDIRXENABLE | INTE_MIDITXENABLE | INTE_INTERVALTIMERENB |
-						INTE_VOLDECRENABLE | INTE_VOLINCRENABLE | INTE_MUTEENABLE |
-						INTE_FXDSPENABLE));
-		}
-
-		/* acknowledge interrupt */
-		outl(irqstatus_tmp, card->iobase + IPR);
-		handled = 1;
-	}
-	return IRQ_RETVAL(handled);
-}
diff --git a/sound/oss/emu10k1/irqmgr.h b/sound/oss/emu10k1/irqmgr.h
deleted file mode 100644
index 7e7c9ca..0000000
--- a/sound/oss/emu10k1/irqmgr.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- **********************************************************************
- *     irq.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#ifndef _IRQ_H
-#define _IRQ_H
-
-/* EMU Irq Types */
-#define IRQTYPE_PCIBUSERROR	IPR_PCIERROR
-#define IRQTYPE_MIXERBUTTON	(IPR_VOLINCR | IPR_VOLDECR | IPR_MUTE)
-#define IRQTYPE_VOICE		(IPR_CHANNELLOOP | IPR_CHANNELNUMBERMASK)
-#define IRQTYPE_RECORD		(IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL | IPR_MICBUFFULL | IPR_MICBUFHALFFULL | IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)
-#define IRQTYPE_MPUOUT		(IPR_MIDITRANSBUFEMPTY | A_IPR_MIDITRANSBUFEMPTY2) 
-#define IRQTYPE_MPUIN		(IPR_MIDIRECVBUFEMPTY | A_IPR_MIDIRECVBUFEMPTY2)
-#define IRQTYPE_TIMER		IPR_INTERVALTIMER
-#define IRQTYPE_SPDIF		(IPR_GPSPDIFSTATUSCHANGE | IPR_CDROMSTATUSCHANGE)
-#define IRQTYPE_DSP		IPR_FXDSP
-
-void emu10k1_timer_irqhandler(struct emu10k1_card *);
-void emu10k1_dsp_irqhandler(struct emu10k1_card *);
-void emu10k1_mute_irqhandler(struct emu10k1_card *);
-void emu10k1_volincr_irqhandler(struct emu10k1_card *);
-void emu10k1_voldecr_irqhandler(struct emu10k1_card *);
-
-#endif /* _IRQ_H */
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
deleted file mode 100644
index 16ac025..0000000
--- a/sound/oss/emu10k1/main.c
+++ /dev/null
@@ -1,1471 +0,0 @@
- /*
- **********************************************************************
- *     main.c - Creative EMU10K1 audio driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        cleaned up stuff
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- *
- *      Supported devices:
- *      /dev/dsp:        Standard /dev/dsp device, OSS-compatible
- *      /dev/dsp1:       Routes to rear speakers only	 
- *      /dev/mixer:      Standard /dev/mixer device, OSS-compatible
- *      /dev/midi:       Raw MIDI UART device, mostly OSS-compatible
- *	/dev/sequencer:  Sequencer Interface (requires sound.o)
- *
- *      Revision history:
- *      0.1 beta Initial release
- *      0.2 Lowered initial mixer vol. Improved on stuttering wave playback. Added MIDI UART support.
- *      0.3 Fixed mixer routing bug, added APS, joystick support.
- *      0.4 Added rear-channel, SPDIF support.
- *	0.5 Source cleanup, SMP fixes, multiopen support, 64 bit arch fixes,
- *	    moved bh's to tasklets, moved to the new PCI driver initialization style.
- *	0.6 Make use of pci_alloc_consistent, improve compatibility layer for 2.2 kernels,
- *	    code reorganization and cleanup.
- *	0.7 Support for the Emu-APS. Bug fixes for voice cache setup, mmaped sound + poll().
- *          Support for setting external TRAM size.
- *      0.8 Make use of the kernel ac97 interface. Support for a dsp patch manager.
- *      0.9 Re-enables rear speakers volume controls
- *     0.10 Initializes rear speaker volume.
- *	    Dynamic patch storage allocation.
- *	    New private ioctls to change control gpr values.
- *	    Enable volume control interrupts.
- *	    By default enable dsp routes to digital out. 
- *     0.11 Fixed fx / 4 problem.
- *     0.12 Implemented mmaped for recording.
- *	    Fixed bug: not unreserving mmaped buffer pages.
- *	    IRQ handler cleanup.
- *     0.13 Fixed problem with dsp1
- *          Simplified dsp patch writing (inside the driver)
- *	    Fixed several bugs found by the Stanford tools
- *     0.14 New control gpr to oss mixer mapping feature (Chris Purnell)
- *          Added AC3 Passthrough Support (Juha Yrjola)
- *          Added Support for 5.1 cards (digital out and the third analog out)
- *     0.15 Added Sequencer Support (Daniel Mack)
- *          Support for multichannel pcm playback (Eduard Hasenleithner)
- *     0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand)
- *          Small code format cleanup.
- *          Deadlock bug fix for emu10k1_volxxx_irqhandler().
- *     0.17 Fix for mixer SOUND_MIXER_INFO ioctl.
- *	    Fix for HIGHMEM machines (emu10k1 can only do 31 bit bus master) 
- *	    midi poll initial implementation.
- *	    Small mixer fixes/cleanups.
- *	    Improved support for 5.1 cards.
- *     0.18 Fix for possible leak in pci_alloc_consistent()
- *          Cleaned up poll() functions (audio and midi). Don't start input.
- *	    Restrict DMA pages used to 512Mib range.
- *	    New AC97_BOOST mixer ioctl.
- *    0.19a Added Support for Audigy Cards
- *	    Real fix for kernel with highmem support (cast dma_handle to u32).
- *	    Fix recording buffering parameters calculation.
- *	    Use unsigned long for variables in bit ops.
- *    0.20a Fixed recording startup
- *	    Fixed timer rate setting (it's a 16-bit register)
- *	0.21 Converted code to use pci_name() instead of accessing slot_name
- *	    directly (Eugene Teo)
- *********************************************************************/
-
-/* These are only included once per module */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/dma-mapping.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "efxmgr.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "cardmo.h"
-#include "cardmi.h"
-#include "recmgr.h"
-#include "ecard.h"
-
-
-#ifdef EMU10K1_SEQUENCER
-#define MIDI_SYNTH_NAME "EMU10K1 MIDI"
-#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
- 
-#include "../sound_config.h"
-#include "../midi_synth.h"
-
-/* this should be in dev_table.h */
-#define SNDCARD_EMU10K1 46
-#endif
- 
-
-/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
-#define EMU10K1_DMA_MASK DMA_29BIT_MASK	/* DMA buffer mask for pci_alloc_consist */
-
-#ifndef PCI_VENDOR_ID_CREATIVE
-#define PCI_VENDOR_ID_CREATIVE 0x1102
-#endif
-
-#ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1
-#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
-#endif
-#ifndef PCI_DEVICE_ID_CREATIVE_AUDIGY
-#define PCI_DEVICE_ID_CREATIVE_AUDIGY 0x0004
-#endif
-
-#define EMU_APS_SUBID	0x40011102
- 
-enum {
-	EMU10K1 = 0,
-	AUDIGY,
-};
-
-static char *card_names[] __devinitdata = {
-	"EMU10K1",
-	"Audigy",
-};
-
-static struct pci_device_id emu10k1_pci_tbl[] = {
-	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1},
-	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_AUDIGY,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AUDIGY},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, emu10k1_pci_tbl);
-
-/* Global var instantiation */
-
-LIST_HEAD(emu10k1_devs);
-
-extern struct file_operations emu10k1_audio_fops;
-extern struct file_operations emu10k1_mixer_fops;
-extern struct file_operations emu10k1_midi_fops;
-
-#ifdef EMU10K1_SEQUENCER
-static struct midi_operations emu10k1_midi_operations;
-#endif
-
-extern irqreturn_t emu10k1_interrupt(int, void *);
-
-static int __devinit emu10k1_audio_init(struct emu10k1_card *card)
-{
-	/* Assign default playback voice parameters */
-	if (card->is_audigy)
-		card->mchannel_fx = 0;
-	else
-		card->mchannel_fx = 8;
-
-
-	if (card->is_audigy) {
-		/* mono voice */
-		card->waveout.send_dcba[SEND_MONO] = 0xffffffff;
-		card->waveout.send_hgfe[SEND_MONO] = 0x0000ffff;
-	
-		/* stereo voice */
-		/* left */
-		card->waveout.send_dcba[SEND_LEFT] = 0x00ff00ff;
-		card->waveout.send_hgfe[SEND_LEFT] = 0x00007f7f;	
-		/* right */
-		card->waveout.send_dcba[SEND_RIGHT] = 0xff00ff00;
-		card->waveout.send_hgfe[SEND_RIGHT] = 0x00007f7f;
-
-		card->waveout.send_routing[ROUTE_PCM] = 0x03020100; // Regular pcm
-		card->waveout.send_routing2[ROUTE_PCM] = 0x07060504;
-
-		card->waveout.send_routing[ROUTE_PT] = 0x3f3f3d3c; // Passthrough
-		card->waveout.send_routing2[ROUTE_PT] = 0x3f3f3f3f;
-		
-		card->waveout.send_routing[ROUTE_PCM1] = 0x03020100; // Spare
-		card->waveout.send_routing2[ROUTE_PCM1] = 0x07060404;
-		
-	} else {
-		/* mono voice */
-		card->waveout.send_dcba[SEND_MONO] = 0x0000ffff;
-	
-		/* stereo voice */
-		/* left */
-		card->waveout.send_dcba[SEND_LEFT] = 0x000000ff;
-		/* right */
-		card->waveout.send_dcba[SEND_RIGHT] = 0x0000ff00;
-
-		card->waveout.send_routing[ROUTE_PCM] = 0x3210; // pcm
-		card->waveout.send_routing[ROUTE_PT] = 0x3210; // passthrough
-		card->waveout.send_routing[ROUTE_PCM1] = 0x7654; // /dev/dsp1
-	}
-
-	/* Assign default recording parameters */
-	/* FIXME */
-	if (card->is_aps)
-		card->wavein.recsrc = WAVERECORD_FX;
-	else
-		card->wavein.recsrc = WAVERECORD_AC97;
-
-	card->wavein.fxwc = 0x0003;
-	return 0;
-}
-
-static void emu10k1_audio_cleanup(struct emu10k1_card *card)
-{
-}
-
-static int __devinit emu10k1_register_devices(struct emu10k1_card *card)
-{
-	card->audio_dev = register_sound_dsp(&emu10k1_audio_fops, -1);
-	if (card->audio_dev < 0) {
-		printk(KERN_ERR "emu10k1: cannot register first audio device!\n");
-		goto err_dev;
-	}
-
-	card->audio_dev1 = register_sound_dsp(&emu10k1_audio_fops, -1);
-	if (card->audio_dev1 < 0) {
-		printk(KERN_ERR "emu10k1: cannot register second audio device!\n");
-		goto err_dev1;
-	}
-
-	card->ac97->dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);
-	if (card->ac97->dev_mixer < 0) {
-		printk(KERN_ERR "emu10k1: cannot register mixer device\n");
-		goto err_mixer;
-        }
-
-	card->midi_dev = register_sound_midi(&emu10k1_midi_fops, -1);
-	if (card->midi_dev < 0) {
-                printk(KERN_ERR "emu10k1: cannot register midi device!\n");
-		goto err_midi;
-        }
-
-#ifdef EMU10K1_SEQUENCER
-	card->seq_dev = sound_alloc_mididev();
-	if (card->seq_dev == -1)
-		printk(KERN_WARNING "emu10k1: unable to register sequencer device!");
-	else {
-		std_midi_synth.midi_dev = card->seq_dev;
-		midi_devs[card->seq_dev] = 
-			(struct midi_operations *)
-			kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
-
-		if (midi_devs[card->seq_dev] == NULL) {
-			printk(KERN_ERR "emu10k1: unable to allocate memory!");
-			sound_unload_mididev(card->seq_dev);
-			card->seq_dev = -1;
-			/* return without error */
-		} else {
-			memcpy((char *)midi_devs[card->seq_dev], 
-				(char *)&emu10k1_midi_operations, 
-				sizeof(struct midi_operations));
-			midi_devs[card->seq_dev]->devc = card;
-			sequencer_init();
-			card->seq_mididev = NULL;
-		}
-	}
-#endif
-	return 0;
-
-err_midi:
-	unregister_sound_mixer(card->ac97->dev_mixer);
-err_mixer:
-	unregister_sound_dsp(card->audio_dev);
-err_dev1:
-	unregister_sound_dsp(card->audio_dev);
-err_dev:
-	return -ENODEV;
-}
-
-static void emu10k1_unregister_devices(struct emu10k1_card *card)
-{
-#ifdef EMU10K1_SEQUENCER
-	if (card->seq_dev > -1) {
-		kfree(midi_devs[card->seq_dev]);
-		midi_devs[card->seq_dev] = NULL;
-		sound_unload_mididev(card->seq_dev);
-		card->seq_dev = -1;
-	}
-#endif
-
-	unregister_sound_midi(card->midi_dev);
-	unregister_sound_mixer(card->ac97->dev_mixer);
-	unregister_sound_dsp(card->audio_dev1);
-	unregister_sound_dsp(card->audio_dev);
-}
-
-static int emu10k1_info_proc (char *page, char **start, off_t off,
-			      int count, int *eof, void *data)
-{
-	struct emu10k1_card *card = data;
-	int len = 0;
-	
-	if (card == NULL)
-		return -ENODEV;
-
-	len += sprintf (page + len, "Driver Version : %s\n", DRIVER_VERSION);
-	len += sprintf (page + len, "Card type      : %s\n", card->is_aps ? "Aps" : (card->is_audigy ? "Audigy" : "Emu10k1"));
-	len += sprintf (page + len, "Revision       : %d\n", card->chiprev);
-	len += sprintf (page + len, "Model          : %#06x\n", card->model);
-	len += sprintf (page + len, "IO             : %#06lx-%#06lx\n", card->iobase, card->iobase + card->length - 1);
-	len += sprintf (page + len, "IRQ            : %d\n\n", card->irq);
-	
-	len += sprintf (page + len, "Registered /dev Entries:\n");
-	len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev / 16);
-	len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev1 / 16);
-	len += sprintf (page + len, "/dev/mixer%d\n", card->ac97->dev_mixer / 16);
-	len += sprintf (page + len, "/dev/midi%d\n", card->midi_dev / 16);
-
-#ifdef EMU10K1_SEQUENCER
-	len += sprintf (page + len, "/dev/sequencer\n");
-#endif
-
-	return len;
-}
-
-static int __devinit emu10k1_proc_init(struct emu10k1_card *card)
-{
-	char s[48];
-
-	if (!proc_mkdir ("driver/emu10k1", NULL)) {
-		printk(KERN_ERR "emu10k1: unable to create proc directory driver/emu10k1\n");
-		goto err_out;
-	}
-
-	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
-	if (!proc_mkdir (s, NULL)) {
-		printk(KERN_ERR "emu10k1: unable to create proc directory %s\n", s);
-		goto err_emu10k1_proc;
-	}
-
-	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
-	if (!create_proc_read_entry (s, 0, NULL, emu10k1_info_proc, card)) {
-		printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
-		goto err_dev_proc;
-	}
-
-	if (!card->is_aps) {
-		sprintf(s, "driver/emu10k1/%s/ac97", pci_name(card->pci_dev));
-		if (!create_proc_read_entry (s, 0, NULL, ac97_read_proc, card->ac97)) {
-			printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
-			goto err_proc_ac97;
-		}
-	}
-
-	return 0;
-
-err_proc_ac97:
-	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
-	remove_proc_entry(s, NULL);
-
-err_dev_proc:
-	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
-	remove_proc_entry(s, NULL);
-
-err_emu10k1_proc:
-	remove_proc_entry("driver/emu10k1", NULL);
-
-err_out:
-	return -EIO;
-}
-
-static void emu10k1_proc_cleanup(struct emu10k1_card *card)
-{
-	char s[48];
-
-	if (!card->is_aps) {
-		sprintf(s, "driver/emu10k1/%s/ac97", pci_name(card->pci_dev));
-		remove_proc_entry(s, NULL);
-	}
-
-	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
-	remove_proc_entry(s, NULL);
-
-	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
-	remove_proc_entry(s, NULL);
-		
-	remove_proc_entry("driver/emu10k1", NULL);
-}
-
-static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
-{
-	struct ac97_codec *codec  = ac97_alloc_codec();
-	
-	if(codec == NULL)
-	{
-		printk(KERN_ERR "emu10k1: cannot allocate mixer\n");
-		return -EIO;
-	}
-	card->ac97 = codec;
-	card->ac97->private_data = card;
-
-	if (!card->is_aps) {
-		card->ac97->id = 0;
-		card->ac97->codec_read = emu10k1_ac97_read;
-        	card->ac97->codec_write = emu10k1_ac97_write;
-
-		if (ac97_probe_codec (card->ac97) == 0) {
-			printk(KERN_ERR "emu10k1: unable to probe AC97 codec\n");
-			goto err_out;
-		}
-		/* 5.1: Enable the additional AC97 Slots and unmute extra channels on AC97 codec */
-		if (codec->codec_read(codec, AC97_EXTENDED_ID) & 0x0080){
-			printk(KERN_INFO "emu10k1: SBLive! 5.1 card detected\n"); 
-			sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
-			codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0);
-		}
-
-		// Force 5bit:		    
-		//card->ac97->bit_resolution=5;
-
-		/* these will store the original values and never be modified */
-		card->ac97_supported_mixers = card->ac97->supported_mixers;
-		card->ac97_stereo_mixers = card->ac97->stereo_mixers;
-	}
-
-	return 0;
-
- err_out:
- 	ac97_release_codec(card->ac97);
-	return -EIO;
-}
-
-static void emu10k1_mixer_cleanup(struct emu10k1_card *card)
-{
-	ac97_release_codec(card->ac97);
-}
-
-static int __devinit emu10k1_midi_init(struct emu10k1_card *card)
-{
-	int ret;
-
-	card->mpuout = kzalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);
-	if (card->mpuout == NULL) {
-		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");
-		ret = -ENOMEM;
-		goto err_out1;
-	}
-
-	card->mpuout->intr = 1;
-	card->mpuout->status = FLAGS_AVAILABLE;
-	card->mpuout->state = CARDMIDIOUT_STATE_DEFAULT;
-
-	tasklet_init(&card->mpuout->tasklet, emu10k1_mpuout_bh, (unsigned long) card);
-
-	spin_lock_init(&card->mpuout->lock);
-
-	card->mpuin = kzalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL);
-	if (card->mpuin == NULL) {
-		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuin: out of memory\n");
-		ret = -ENOMEM;
-                goto err_out2;
-	}
-
-	card->mpuin->status = FLAGS_AVAILABLE;
-
-	tasklet_init(&card->mpuin->tasklet, emu10k1_mpuin_bh, (unsigned long) card->mpuin);
-
-	spin_lock_init(&card->mpuin->lock);
-
-	/* Reset the MPU port */
-	if (emu10k1_mpu_reset(card) < 0) {
-		ERROR();
-		ret = -EIO;
-		goto err_out3;
-	}
-
-	return 0;
-
-err_out3:
-	kfree(card->mpuin);
-err_out2:
-	kfree(card->mpuout);
-err_out1:
-	return ret;
-}
-
-static void emu10k1_midi_cleanup(struct emu10k1_card *card)
-{
-	tasklet_kill(&card->mpuout->tasklet);
-	kfree(card->mpuout);
-
-	tasklet_kill(&card->mpuin->tasklet);
-	kfree(card->mpuin);
-}
-
-static void __devinit voice_init(struct emu10k1_card *card)
-{
-	int i;
-
-	for (i = 0; i < NUM_G; i++)
-		card->voicetable[i] = VOICE_USAGE_FREE;
-}
-
-static void __devinit timer_init(struct emu10k1_card *card)
-{
-	INIT_LIST_HEAD(&card->timers);
-	card->timer_delay = TIMER_STOPPED;
-	spin_lock_init(&card->timer_lock);
-}
-
-static void __devinit addxmgr_init(struct emu10k1_card *card)
-{
-	u32 count;
-
-	for (count = 0; count < MAXPAGES; count++)
-		card->emupagetable[count] = 0;
-
-	/* Mark first page as used */
-	/* This page is reserved by the driver */
-	card->emupagetable[0] = 0x8001;
-	card->emupagetable[1] = MAXPAGES - 1;
-}
-
-static void fx_cleanup(struct patch_manager *mgr)
-{
-	int i;
-	for(i = 0; i < mgr->current_pages; i++)
-		free_page((unsigned long) mgr->patch[i]);
-}
-
-static int __devinit fx_init(struct emu10k1_card *card)
-{
-	struct patch_manager *mgr = &card->mgr;
-	struct dsp_patch *patch;
-	struct dsp_rpatch *rpatch;
-	s32 left, right;
-	int i;
-	u32 pc = 0;
-	u32 patch_n=0;
-	struct emu_efx_info_t emu_efx_info[2]=
-		{{ 20, 10, 0x400, 0x100, 0x20 },
-		 { 24, 12, 0x600, 0x400, 0x60 },
-		}; 
-			
-
-	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-		mgr->ctrl_gpr[i][0] = -1;
-		mgr->ctrl_gpr[i][1] = -1;
-	}
-
-
-	if (card->is_audigy)
-		mgr->current_pages = (2 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
-	else
-		/* !! The number below must equal the number of patches, currently 11 !! */
-		mgr->current_pages = (11 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
-	
-	for (i = 0; i < mgr->current_pages; i++) {
-		mgr->patch[i] = (void *)__get_free_page(GFP_KERNEL);
-		if (mgr->patch[i] == NULL) {
-			mgr->current_pages = i;
-			fx_cleanup(mgr);
-			return -ENOMEM;
-		}
-		memset(mgr->patch[i], 0, PAGE_SIZE);
-	}
-
-	if (card->is_audigy) {
-		for (i = 0; i < 1024; i++)
-			OP(0xf, 0x0c0, 0x0c0, 0x0cf, 0x0c0);
-
-		for (i = 0; i < 512 ; i++)
-			sblive_writeptr(card, A_GPR_BASE+i,0,0);
-
-		pc=0;
-
-		//Pcm input volume
-		OP(0, 0x402, 0x0c0, 0x406, 0x000);
-		OP(0, 0x403, 0x0c0, 0x407, 0x001);
-
-		//CD-Digital input Volume
-		OP(0, 0x404, 0x0c0, 0x40d, 0x42);
-		OP(0, 0x405, 0x0c0, 0x40f, 0x43);
-
-		// CD + PCM 
-		OP(6, 0x400, 0x0c0, 0x402, 0x404);
-		OP(6, 0x401, 0x0c0, 0x403, 0x405);
-		
-		// Front Output + Master Volume
-		OP(0, 0x68, 0x0c0, 0x408, 0x400);
-		OP(0, 0x69, 0x0c0, 0x409, 0x401);
-
-		// Add-in analog inputs for other speakers
-		OP(6, 0x400, 0x40, 0x400, 0xc0);
-		OP(6, 0x401, 0x41, 0x401, 0xc0);
-
-		// Digital Front + Master Volume
-		OP(0, 0x60, 0x0c0, 0x408, 0x400);
-		OP(0, 0x61, 0x0c0, 0x409, 0x401);
-
-		// Rear Output + Rear Volume
-		OP(0, 0x06e, 0x0c0, 0x419, 0x400);
-		OP(0, 0x06f, 0x0c0, 0x41a, 0x401);		
-
-		// Digital Rear Output + Rear Volume
-		OP(0, 0x066, 0x0c0, 0x419, 0x400);
-		OP(0, 0x067, 0x0c0, 0x41a, 0x401);		
-
-		// Audigy Drive, Headphone out
-		OP(6, 0x64, 0x0c0, 0x0c0, 0x400);
-		OP(6, 0x65, 0x0c0, 0x0c0, 0x401);
-
-		// ac97 Recording
-		OP(6, 0x76, 0x0c0, 0x0c0, 0x40);
-		OP(6, 0x77, 0x0c0, 0x0c0, 0x41);
-		
-		// Center = sub = Left/2 + Right/2
-		OP(0xe, 0x400, 0x401, 0xcd, 0x400);
-
-		// center/sub  Volume (master)
-		OP(0, 0x06a, 0x0c0, 0x408, 0x400);
-		OP(0, 0x06b, 0x0c0, 0x409, 0x400);
-
-		// Digital center/sub  Volume (master)
-		OP(0, 0x062, 0x0c0, 0x408, 0x400);
-		OP(0, 0x063, 0x0c0, 0x409, 0x400);
-
-		ROUTING_PATCH_START(rpatch, "Routing");
-		ROUTING_PATCH_END(rpatch);
-
-		/* delimiter patch */
-		patch = PATCH(mgr, patch_n);
-		patch->code_size = 0;
-
-	
-		sblive_writeptr(card, 0x53, 0, 0);
-	} else {
-		for (i = 0; i < 512 ; i++)
-			OP(6, 0x40, 0x40, 0x40, 0x40);
-
-		for (i = 0; i < 256; i++)
-			sblive_writeptr_tag(card, 0,
-					    FXGPREGBASE + i, 0,
-					    TANKMEMADDRREGBASE + i, 0,
-					    TAGLIST_END);
-
-		
-		pc = 0;
-
-		//first free GPR = 0x11b
-	
-		
-		/* FX volume correction and Volume control*/
-		INPUT_PATCH_START(patch, "Pcm L vol", 0x0, 0);
-		GET_OUTPUT_GPR(patch, 0x100, 0x0);
-		GET_CONTROL_GPR(patch, 0x106, "Vol", 0, 0x7fffffff);
-		GET_DYNAMIC_GPR(patch, 0x112);
-
-		OP(4, 0x112, 0x40, PCM_IN_L, 0x44); //*4	
-		OP(0, 0x100, 0x040, 0x112, 0x106);  //*vol	
-		INPUT_PATCH_END(patch);
-
-
-		INPUT_PATCH_START(patch, "Pcm R vol", 0x1, 0);
-		GET_OUTPUT_GPR(patch, 0x101, 0x1);
-		GET_CONTROL_GPR(patch, 0x107, "Vol", 0, 0x7fffffff);
-		GET_DYNAMIC_GPR(patch, 0x112);
-
-		OP(4, 0x112, 0x40, PCM_IN_R, 0x44); 
-		OP(0, 0x101, 0x040, 0x112, 0x107);
-
-		INPUT_PATCH_END(patch);
-
-
-		// CD-Digital In Volume control	
-		INPUT_PATCH_START(patch, "CD-Digital Vol L", 0x12, 0);
-		GET_OUTPUT_GPR(patch, 0x10c, 0x12);
-		GET_CONTROL_GPR(patch, 0x10d, "Vol", 0, 0x7fffffff);
-
-		OP(0, 0x10c, 0x040, SPDIF_CD_L, 0x10d);
-		INPUT_PATCH_END(patch);
-
-		INPUT_PATCH_START(patch, "CD-Digital Vol R", 0x13, 0);
-		GET_OUTPUT_GPR(patch, 0x10e, 0x13);
-		GET_CONTROL_GPR(patch, 0x10f, "Vol", 0, 0x7fffffff);
-
-		OP(0, 0x10e, 0x040, SPDIF_CD_R, 0x10f);
-		INPUT_PATCH_END(patch);
-
-		//Volume Correction for Multi-channel Inputs	
-		INPUT_PATCH_START(patch, "Multi-Channel Gain", 0x08, 0);
-		patch->input=patch->output=0x3F00;
-
-		GET_OUTPUT_GPR(patch, 0x113, MULTI_FRONT_L);
-		GET_OUTPUT_GPR(patch, 0x114, MULTI_FRONT_R);
-		GET_OUTPUT_GPR(patch, 0x115, MULTI_REAR_L);
-		GET_OUTPUT_GPR(patch, 0x116, MULTI_REAR_R);
-		GET_OUTPUT_GPR(patch, 0x117, MULTI_CENTER);
-		GET_OUTPUT_GPR(patch, 0x118, MULTI_LFE);
-
-		OP(4, 0x113, 0x40, MULTI_FRONT_L, 0x44);
-		OP(4, 0x114, 0x40, MULTI_FRONT_R, 0x44);
-		OP(4, 0x115, 0x40, MULTI_REAR_L, 0x44);
-		OP(4, 0x116, 0x40, MULTI_REAR_R, 0x44);
-		OP(4, 0x117, 0x40, MULTI_CENTER, 0x44);
-		OP(4, 0x118, 0x40, MULTI_LFE, 0x44);
-	
-		INPUT_PATCH_END(patch);
-
-
-		//Routing patch start	
-		ROUTING_PATCH_START(rpatch, "Routing");
-		GET_INPUT_GPR(rpatch, 0x100, 0x0);
-		GET_INPUT_GPR(rpatch, 0x101, 0x1);
-		GET_INPUT_GPR(rpatch, 0x10c, 0x12);
-		GET_INPUT_GPR(rpatch, 0x10e, 0x13);
-		GET_INPUT_GPR(rpatch, 0x113, MULTI_FRONT_L);
-		GET_INPUT_GPR(rpatch, 0x114, MULTI_FRONT_R);
-		GET_INPUT_GPR(rpatch, 0x115, MULTI_REAR_L);
-		GET_INPUT_GPR(rpatch, 0x116, MULTI_REAR_R);
-		GET_INPUT_GPR(rpatch, 0x117, MULTI_CENTER);
-		GET_INPUT_GPR(rpatch, 0x118, MULTI_LFE);
-
-		GET_DYNAMIC_GPR(rpatch, 0x102);
-		GET_DYNAMIC_GPR(rpatch, 0x103);
-
-		GET_OUTPUT_GPR(rpatch, 0x104, 0x8);
-		GET_OUTPUT_GPR(rpatch, 0x105, 0x9);
-		GET_OUTPUT_GPR(rpatch, 0x10a, 0x2);
-		GET_OUTPUT_GPR(rpatch, 0x10b, 0x3);
-		
-		
-		/* input buffer */
-		OP(6, 0x102, AC97_IN_L, 0x40, 0x40);
-		OP(6, 0x103, AC97_IN_R, 0x40, 0x40);
-
-
-		/* Digital In + PCM + MULTI_FRONT-> AC97 out (front speakers)*/
-		OP(6, AC97_FRONT_L, 0x100, 0x10c, 0x113);
-
-		CONNECT(MULTI_FRONT_L, AC97_FRONT_L);
-		CONNECT(PCM_IN_L, AC97_FRONT_L);
-		CONNECT(SPDIF_CD_L, AC97_FRONT_L);
-
-		OP(6, AC97_FRONT_R, 0x101, 0x10e, 0x114);
-
-		CONNECT(MULTI_FRONT_R, AC97_FRONT_R);
-		CONNECT(PCM_IN_R, AC97_FRONT_R);
-		CONNECT(SPDIF_CD_R, AC97_FRONT_R);
-
-		/* Digital In + PCM + AC97 In + PCM1 + MULTI_REAR --> Rear Channel */ 
-		OP(6, 0x104, PCM1_IN_L, 0x100, 0x115);
-		OP(6, 0x104, 0x104, 0x10c, 0x102);
-
-		CONNECT(MULTI_REAR_L, ANALOG_REAR_L);
-		CONNECT(AC97_IN_L, ANALOG_REAR_L);
-		CONNECT(PCM_IN_L, ANALOG_REAR_L);
-		CONNECT(SPDIF_CD_L, ANALOG_REAR_L);
-		CONNECT(PCM1_IN_L, ANALOG_REAR_L);
-
-		OP(6, 0x105, PCM1_IN_R, 0x101, 0x116);
-		OP(6, 0x105, 0x105, 0x10e, 0x103);
-
-		CONNECT(MULTI_REAR_R, ANALOG_REAR_R);
-		CONNECT(AC97_IN_R, ANALOG_REAR_R);
-		CONNECT(PCM_IN_R, ANALOG_REAR_R);
-		CONNECT(SPDIF_CD_R, ANALOG_REAR_R);
-		CONNECT(PCM1_IN_R, ANALOG_REAR_R);
-
-		/* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */
-		OP(6, 0x10b, 0x100, 0x102, 0x10c);
-		OP(6, 0x10b, 0x10b, 0x113, 0x40);
-
-		CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L);
-		CONNECT(PCM_IN_L, DIGITAL_OUT_L);
-		CONNECT(AC97_IN_L, DIGITAL_OUT_L);
-		CONNECT(SPDIF_CD_L, DIGITAL_OUT_L);
-
-		OP(6, 0x10a, 0x101, 0x103, 0x10e);
-		OP(6, 0x10b, 0x10b, 0x114, 0x40);
-
-		CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R);
-		CONNECT(PCM_IN_R, DIGITAL_OUT_R);
-		CONNECT(AC97_IN_R, DIGITAL_OUT_R);
-		CONNECT(SPDIF_CD_R, DIGITAL_OUT_R);
-
-		/* AC97 In --> ADC Recording Buffer */
-		OP(6, ADC_REC_L, 0x102, 0x40, 0x40);
-
-		CONNECT(AC97_IN_L, ADC_REC_L);
-
-		OP(6, ADC_REC_R, 0x103, 0x40, 0x40);
-
-		CONNECT(AC97_IN_R, ADC_REC_R);
-
-
-		/* fx12:Analog-Center */
-		OP(6, ANALOG_CENTER, 0x117, 0x40, 0x40);
-		CONNECT(MULTI_CENTER, ANALOG_CENTER);
-
-		/* fx11:Analog-LFE */
-		OP(6, ANALOG_LFE, 0x118, 0x40, 0x40);
-		CONNECT(MULTI_LFE, ANALOG_LFE);
-
-		/* fx12:Digital-Center */
-		OP(6, DIGITAL_CENTER, 0x117, 0x40, 0x40);
-		CONNECT(MULTI_CENTER, DIGITAL_CENTER);
-		
-		/* fx11:Analog-LFE */
-		OP(6, DIGITAL_LFE, 0x118, 0x40, 0x40);
-		CONNECT(MULTI_LFE, DIGITAL_LFE);
-	
-		ROUTING_PATCH_END(rpatch);
-
-
-		// Rear volume control	
-		OUTPUT_PATCH_START(patch, "Vol Rear L", 0x8, 0);
-		GET_INPUT_GPR(patch, 0x104, 0x8);
-		GET_CONTROL_GPR(patch, 0x119, "Vol", 0, 0x7fffffff);
-
-		OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x119);
-		OUTPUT_PATCH_END(patch);
-
-		OUTPUT_PATCH_START(patch, "Vol Rear R", 0x9, 0);
-		GET_INPUT_GPR(patch, 0x105, 0x9);
-		GET_CONTROL_GPR(patch, 0x11a, "Vol", 0, 0x7fffffff);
-
-		OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x11a);
-		OUTPUT_PATCH_END(patch);
-
-
-		//Master volume control on front-digital	
-		OUTPUT_PATCH_START(patch, "Vol Master L", 0x2, 1);
-		GET_INPUT_GPR(patch, 0x10a, 0x2);
-		GET_CONTROL_GPR(patch, 0x108, "Vol", 0, 0x7fffffff);
-
-		OP(0, DIGITAL_OUT_L, 0x040, 0x10a, 0x108);
-		OUTPUT_PATCH_END(patch);
-
-
-		OUTPUT_PATCH_START(patch, "Vol Master R", 0x3, 1);
-		GET_INPUT_GPR(patch, 0x10b, 0x3);
-		GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff);
-
-		OP(0, DIGITAL_OUT_R, 0x040, 0x10b, 0x109);
-		OUTPUT_PATCH_END(patch);
-
-
-		/* delimiter patch */
-		patch = PATCH(mgr, patch_n);
-		patch->code_size = 0;
-
-	
-		sblive_writeptr(card, DBG, 0, 0);
-	}
-
-	spin_lock_init(&mgr->lock);
-
-	// Set up Volume controls, try to keep this the same for both Audigy and Live
-
-	//Master volume
-	mgr->ctrl_gpr[SOUND_MIXER_VOLUME][0] = 8;
-	mgr->ctrl_gpr[SOUND_MIXER_VOLUME][1] = 9;
-
-	left = card->ac97->mixer_state[SOUND_MIXER_VOLUME] & 0xff;
-	right = (card->ac97->mixer_state[SOUND_MIXER_VOLUME] >> 8) & 0xff;
-
-	emu10k1_set_volume_gpr(card, 8, left, 1 << card->ac97->bit_resolution);
-	emu10k1_set_volume_gpr(card, 9, right, 1 << card->ac97->bit_resolution);
-
-	//Rear volume
-	mgr->ctrl_gpr[ SOUND_MIXER_OGAIN ][0] = 0x19;
-	mgr->ctrl_gpr[ SOUND_MIXER_OGAIN ][1] = 0x1a;
-
-	left = right = 67;
-	card->ac97->mixer_state[SOUND_MIXER_OGAIN] = (right << 8) | left;
-
-	card->ac97->supported_mixers |= SOUND_MASK_OGAIN;
-	card->ac97->stereo_mixers |= SOUND_MASK_OGAIN;
-
-	emu10k1_set_volume_gpr(card, 0x19, left, VOL_5BIT);
-	emu10k1_set_volume_gpr(card, 0x1a, right, VOL_5BIT);
-
-	//PCM Volume
-	mgr->ctrl_gpr[SOUND_MIXER_PCM][0] = 6;
-	mgr->ctrl_gpr[SOUND_MIXER_PCM][1] = 7;
-
-	left = card->ac97->mixer_state[SOUND_MIXER_PCM] & 0xff;
-	right = (card->ac97->mixer_state[SOUND_MIXER_PCM] >> 8) & 0xff;
-
-	emu10k1_set_volume_gpr(card, 6, left, VOL_5BIT);
-	emu10k1_set_volume_gpr(card, 7, right, VOL_5BIT);
-
-	//CD-Digital Volume
-	mgr->ctrl_gpr[SOUND_MIXER_DIGITAL1][0] = 0xd;
-	mgr->ctrl_gpr[SOUND_MIXER_DIGITAL1][1] = 0xf;
-
-	left = right = 67;
-	card->ac97->mixer_state[SOUND_MIXER_DIGITAL1] = (right << 8) | left; 
-
-	card->ac97->supported_mixers |= SOUND_MASK_DIGITAL1;
-	card->ac97->stereo_mixers |= SOUND_MASK_DIGITAL1;
-
-	emu10k1_set_volume_gpr(card, 0xd, left, VOL_5BIT);
-	emu10k1_set_volume_gpr(card, 0xf, right, VOL_5BIT);
-
-
-	//hard wire the ac97's pcm, pcm volume is done above using dsp code.
-	if (card->is_audigy)
-		//for Audigy, we mute it and use the philips 6 channel DAC instead
-		emu10k1_ac97_write(card->ac97, 0x18, 0x8000);
-	else
-		//For the Live we hardwire it to full volume
-		emu10k1_ac97_write(card->ac97, 0x18, 0x0);
-
-	//remove it from the ac97_codec's control
-	card->ac97_supported_mixers &= ~SOUND_MASK_PCM;
-	card->ac97_stereo_mixers &= ~SOUND_MASK_PCM;
-
-	//set Igain to 0dB by default, maybe consider hardwiring it here.
-	emu10k1_ac97_write(card->ac97, AC97_RECORD_GAIN, 0x0000);
-	card->ac97->mixer_state[SOUND_MIXER_IGAIN] = 0x101; 
-
-	return 0;
-}
-
-static int __devinit hw_init(struct emu10k1_card *card)
-{
-	int nCh;
-	u32 pagecount; /* tmp */
-	int ret;
-
-	/* Disable audio and lock cache */
-	emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
-
-	/* Reset recording buffers */
-	sblive_writeptr_tag(card, 0,
-			    MICBS, ADCBS_BUFSIZE_NONE,
-			    MICBA, 0,
-			    FXBS, ADCBS_BUFSIZE_NONE,
-			    FXBA, 0,
-			    ADCBS, ADCBS_BUFSIZE_NONE,
-			    ADCBA, 0,
-			    TAGLIST_END);
-
-	/* Disable channel interrupt */
-	emu10k1_writefn0(card, INTE, 0);
-	sblive_writeptr_tag(card, 0,
-			    CLIEL, 0,
-			    CLIEH, 0,
-			    SOLEL, 0,
-			    SOLEH, 0,
-			    TAGLIST_END);
-
-	if (card->is_audigy) {
-		sblive_writeptr_tag(card,0,
-				    0x5e,0xf00,
-				    0x5f,0x3,
-				    TAGLIST_END);
-	}
-
-	/* Init envelope engine */
-	for (nCh = 0; nCh < NUM_G; nCh++) {
-		sblive_writeptr_tag(card, nCh,
-				    DCYSUSV, 0,
-				    IP, 0,
-				    VTFT, 0xffff,
-				    CVCF, 0xffff,
-				    PTRX, 0,
-				    //CPF, 0,
-				    CCR, 0,
-
-				    PSST, 0,
-				    DSL, 0x10,
-				    CCCA, 0,
-				    Z1, 0,
-				    Z2, 0,
-				    FXRT, 0xd01c0000,
-
-				    ATKHLDM, 0,
-				    DCYSUSM, 0,
-				    IFATN, 0xffff,
-				    PEFE, 0,
-				    FMMOD, 0,
-				    TREMFRQ, 24,	/* 1 Hz */
-				    FM2FRQ2, 24,	/* 1 Hz */
-				    TEMPENV, 0,
-
-				    /*** These are last so OFF prevents writing ***/
-				    LFOVAL2, 0,
-				    LFOVAL1, 0,
-				    ATKHLDV, 0,
-				    ENVVOL, 0,
-				    ENVVAL, 0,
-                                    TAGLIST_END);
-		sblive_writeptr(card, CPF, nCh, 0);
-		/*
-		  Audigy FXRT initialization
-		  reversed eng'd, may not be accurate.
-		 */
-		if (card->is_audigy) {
-			sblive_writeptr_tag(card,nCh,
-					    0x4c,0x0,
-					    0x4d,0x0,
-					    0x4e,0x0,
-					    0x4f,0x0,
-					    A_FXRT1, 0x3f3f3f3f,
-					    A_FXRT2, 0x3f3f3f3f,
-					    A_SENDAMOUNTS, 0,
-					    TAGLIST_END);
-		}
-	}
-	
-
-	/*
-	 ** Init to 0x02109204 :
-	 ** Clock accuracy    = 0     (1000ppm)
-	 ** Sample Rate       = 2     (48kHz)
-	 ** Audio Channel     = 1     (Left of 2)
-	 ** Source Number     = 0     (Unspecified)
-	 ** Generation Status = 1     (Original for Cat Code 12)
-	 ** Cat Code          = 12    (Digital Signal Mixer)
-	 ** Mode              = 0     (Mode 0)
-	 ** Emphasis          = 0     (None)
-	 ** CP                = 1     (Copyright unasserted)
-	 ** AN                = 0     (Digital audio)
-	 ** P                 = 0     (Consumer)
-	 */
-
-	sblive_writeptr_tag(card, 0,
-
-			    /* SPDIF0 */
-			    SPCS0, (SPCS_CLKACCY_1000PPM | 0x002000000 |
-				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
-			    /* SPDIF1 */
-			    SPCS1, (SPCS_CLKACCY_1000PPM | 0x002000000 |
-				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
-			    /* SPDIF2 & SPDIF3 */
-			    SPCS2, (SPCS_CLKACCY_1000PPM | 0x002000000 |
-				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
-			    TAGLIST_END);
-
-	if (card->is_audigy && (card->chiprev == 4)) {
-		/* Hacks for Alice3 to work independent of haP16V driver */
-		u32 tmp;
-
-		//Setup SRCMulti_I2S SamplingRate
-		tmp = sblive_readptr(card, A_SPDIF_SAMPLERATE, 0);
-		tmp &= 0xfffff1ff;
-		tmp |= (0x2<<9);
-		sblive_writeptr(card, A_SPDIF_SAMPLERATE, 0, tmp);
-
-		/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
-		emu10k1_writefn0(card, 0x20, 0x600000);
-		emu10k1_writefn0(card, 0x24, 0x14);
-
-		/* Setup SRCMulti Input Audio Enable */
-		emu10k1_writefn0(card, 0x20, 0x6E0000);
-		emu10k1_writefn0(card, 0x24, 0xFF00FF00);
-	}
-
-	ret = fx_init(card);		/* initialize effects engine */
-	if (ret < 0)
-		return ret;
-
-	card->tankmem.size = 0;
-
-	card->virtualpagetable.size = MAXPAGES * sizeof(u32);
-
-	card->virtualpagetable.addr = pci_alloc_consistent(card->pci_dev, card->virtualpagetable.size, &card->virtualpagetable.dma_handle);
-	if (card->virtualpagetable.addr == NULL) {
-		ERROR();
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	card->silentpage.size = EMUPAGESIZE;
-
-	card->silentpage.addr = pci_alloc_consistent(card->pci_dev, card->silentpage.size, &card->silentpage.dma_handle);
-	if (card->silentpage.addr == NULL) {
-		ERROR();
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
-		((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pagecount);
-
-	/* Init page table & tank memory base register */
-	sblive_writeptr_tag(card, 0,
-			    PTB, (u32) card->virtualpagetable.dma_handle,
-			    TCB, 0,
-			    TCBS, 0,
-			    TAGLIST_END);
-
-	for (nCh = 0; nCh < NUM_G; nCh++) {
-		sblive_writeptr_tag(card, nCh,
-				    MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
-				    MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
-				    TAGLIST_END);
-	}
-
-	/* Hokay, now enable the AUD bit */
-	/* Enable Audio = 1 */
-	/* Mute Disable Audio = 0 */
-	/* Lock Tank Memory = 1 */
-	/* Lock Sound Memory = 0 */
-	/* Auto Mute = 1 */
-	if (card->is_audigy) {
-		if (card->chiprev == 4)
-			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_AC3ENABLE_CDSPDIF | HCFG_AC3ENABLE_GPSPDIF | HCFG_AUTOMUTE | HCFG_JOYENABLE);
-		else
-			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_AUTOMUTE | HCFG_JOYENABLE);
-	} else {
-		if (card->model == 0x20 || card->model == 0xc400 ||
-		 (card->model == 0x21 && card->chiprev < 6))
-	        	emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE);
-		else
-			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE);
-	}
-	/* Enable Vol_Ctrl irqs */
-	emu10k1_irq_enable(card, INTE_VOLINCRENABLE | INTE_VOLDECRENABLE | INTE_MUTEENABLE | INTE_FXDSPENABLE);
-
-	if (card->is_audigy && (card->chiprev == 4)) {
-		/* Unmute Analog now.  Set GPO6 to 1 for Apollo.
-		 * This has to be done after init ALice3 I2SOut beyond 48KHz.
-		 * So, sequence is important. */
-		u32 tmp = emu10k1_readfn0(card, A_IOCFG);
-		tmp |= 0x0040;
-		emu10k1_writefn0(card, A_IOCFG, tmp);
-	}
-	
-	/* FIXME: TOSLink detection */
-	card->has_toslink = 0;
-
-	/* Initialize digital passthrough variables */
-	card->pt.pos_gpr = card->pt.intr_gpr = card->pt.enable_gpr = -1;
-	card->pt.selected = 0;
-	card->pt.state = PT_STATE_INACTIVE;
-	card->pt.spcs_to_use = 0x01;
-	card->pt.patch_name = "AC3pass";
-	card->pt.intr_gpr_name = "count";
-	card->pt.enable_gpr_name = "enable";
-	card->pt.pos_gpr_name = "ptr";
-	spin_lock_init(&card->pt.lock);
-	init_waitqueue_head(&card->pt.wait);
-
-/*	tmp = sblive_readfn0(card, HCFG);
-	if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
-		sblive_writefn0(card, HCFG, tmp | 0x800);
-
-		udelay(512);
-
-		if (tmp != (sblive_readfn0(card, HCFG) & ~0x800)) {
-			card->has_toslink = 1;
-			sblive_writefn0(card, HCFG, tmp);
-		}
-	}
-*/
-	return 0;
-
-  err1:
-	pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
-  err0:
-	fx_cleanup(&card->mgr);
-
-	return ret;
-}
-
-static int __devinit emu10k1_init(struct emu10k1_card *card)
-{
-	/* Init Card */
-	if (hw_init(card) < 0)
-		return -1;
-
-	voice_init(card);
-	timer_init(card);
-	addxmgr_init(card);
-
-	DPD(2, "  hw control register -> %#x\n", emu10k1_readfn0(card, HCFG));
-
-	return 0;
-}
-
-static void emu10k1_cleanup(struct emu10k1_card *card)
-{
-	int ch;
-
-	emu10k1_writefn0(card, INTE, 0);
-
-	/** Shutdown the chip **/
-	for (ch = 0; ch < NUM_G; ch++)
-		sblive_writeptr(card, DCYSUSV, ch, 0);
-
-	for (ch = 0; ch < NUM_G; ch++) {
-		sblive_writeptr_tag(card, ch,
-				    VTFT, 0,
-				    CVCF, 0,
-				    PTRX, 0,
-				    //CPF, 0,
-				    TAGLIST_END);
-		sblive_writeptr(card, CPF, ch, 0);
-	}
-
-	/* Disable audio and lock cache */
-	emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
-
-	sblive_writeptr_tag(card, 0,
-                            PTB, 0,
-
-			    /* Reset recording buffers */
-			    MICBS, ADCBS_BUFSIZE_NONE,
-			    MICBA, 0,
-			    FXBS, ADCBS_BUFSIZE_NONE,
-			    FXBA, 0,
-			    FXWC, 0,
-			    ADCBS, ADCBS_BUFSIZE_NONE,
-			    ADCBA, 0,
-			    TCBS, 0,
-			    TCB, 0,
-			    DBG, 0x8000,
-
-			    /* Disable channel interrupt */
-			    CLIEL, 0,
-			    CLIEH, 0,
-			    SOLEL, 0,
-			    SOLEH, 0,
-			    TAGLIST_END);
-
-	if (card->is_audigy)
-		sblive_writeptr(card, 0, A_DBG,  A_DBG_SINGLE_STEP);
-
-	pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
-	pci_free_consistent(card->pci_dev, card->silentpage.size, card->silentpage.addr, card->silentpage.dma_handle);
-	
-	if(card->tankmem.size != 0)
-		pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
-
-	/* release patch storage memory */
-	fx_cleanup(&card->mgr);
-}
-
-/* Driver initialization routine */
-static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
-{
-	struct emu10k1_card *card;
-	u32 subsysvid;
-	int ret;
-
-	if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) {
-		printk(KERN_ERR "emu10k1: architecture does not support 29bit PCI busmaster DMA\n");
-		return -ENODEV;
-	}
-
-	if (pci_enable_device(pci_dev))
-		return -EIO;
-
-	pci_set_master(pci_dev);
-
-	if ((card = kzalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
-                printk(KERN_ERR "emu10k1: out of memory\n");
-                return -ENOMEM;
-        }
-
-	card->iobase = pci_resource_start(pci_dev, 0);
-	card->length = pci_resource_len(pci_dev, 0); 
-
-	if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) {
-		printk(KERN_ERR "emu10k1: IO space in use\n");
-		ret = -EBUSY;
-		goto err_region;
-	}
-
-	pci_set_drvdata(pci_dev, card);
-
-	card->irq = pci_dev->irq;
-	card->pci_dev = pci_dev;
-
-	/* Reserve IRQ Line */
-	if (request_irq(card->irq, emu10k1_interrupt, IRQF_SHARED, card_names[pci_id->driver_data], card)) {
-		printk(KERN_ERR "emu10k1: IRQ in use\n");
-		ret = -EBUSY;
-		goto err_irq;
-	}
-
-	pci_read_config_byte(pci_dev, PCI_REVISION_ID, &card->chiprev);
-	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
-
-	printk(KERN_INFO "emu10k1: %s rev %d model %#04x found, IO at %#04lx-%#04lx, IRQ %d\n",
-		card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase,
-		card->iobase + card->length - 1, card->irq);
-
-	if (pci_id->device == PCI_DEVICE_ID_CREATIVE_AUDIGY)
-		card->is_audigy = 1;
-
-	pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
-	card->is_aps = (subsysvid == EMU_APS_SUBID);
-
-	spin_lock_init(&card->lock);
-	mutex_init(&card->open_sem);
-	card->open_mode = 0;
-	init_waitqueue_head(&card->open_wait);
-
-	ret = emu10k1_audio_init(card);
-	if (ret < 0) {
-                printk(KERN_ERR "emu10k1: cannot initialize audio devices\n");
-                goto err_audio;
-        }
-
-	ret = emu10k1_mixer_init(card);
-	if (ret < 0) {
-		printk(KERN_ERR "emu10k1: cannot initialize AC97 codec\n");
-                goto err_mixer;
-	}
-
-	ret = emu10k1_midi_init(card);
-	if (ret < 0) {
-		printk(KERN_ERR "emu10k1: cannot register midi device\n");
-		goto err_midi;
-	}
-
-	ret = emu10k1_init(card);
-	if (ret < 0) {
-		printk(KERN_ERR "emu10k1: cannot initialize device\n");
-		goto err_emu10k1_init;
-	}
-
-	if (card->is_aps)
-		emu10k1_ecard_init(card);
-
-	ret = emu10k1_register_devices(card);
-	if (ret < 0)
-		goto err_register;
-
-	/* proc entries must be created after registering devices, as
-	 * emu10k1_info_proc prints card->audio_dev &co. */
-	ret = emu10k1_proc_init(card);
-	if (ret < 0) {
-		printk(KERN_ERR "emu10k1: cannot initialize proc directory\n");
-                goto err_proc;
-	}
-	
-	list_add(&card->list, &emu10k1_devs);
-
-	return 0;
-
-err_proc:
-	emu10k1_unregister_devices(card);
-
-err_register:
-	emu10k1_cleanup(card);
-	
-err_emu10k1_init:
-	emu10k1_midi_cleanup(card);
-
-err_midi:
-	emu10k1_mixer_cleanup(card);
-
-err_mixer:
-	emu10k1_audio_cleanup(card);
-
-err_audio:
-	free_irq(card->irq, card);
-
-err_irq:
-	release_region(card->iobase, card->length);
-	pci_set_drvdata(pci_dev, NULL);
-
-err_region:
-	kfree(card);
-
-	return ret;
-}
-
-static void __devexit emu10k1_remove(struct pci_dev *pci_dev)
-{
-	struct emu10k1_card *card = pci_get_drvdata(pci_dev);
-
-	list_del(&card->list);
-
-	emu10k1_unregister_devices(card);
-	emu10k1_cleanup(card);
-	emu10k1_midi_cleanup(card);
-	emu10k1_mixer_cleanup(card);
-	emu10k1_proc_cleanup(card);
-	emu10k1_audio_cleanup(card);	
-	free_irq(card->irq, card);
-	release_region(card->iobase, card->length);
-	kfree(card);
-	pci_set_drvdata(pci_dev, NULL);
-}
-
-MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@lists.sourceforge.net)");
-MODULE_DESCRIPTION("Creative EMU10K1 PCI Audio Driver v" DRIVER_VERSION "\nCopyright (C) 1999 Creative Technology Ltd.");
-MODULE_LICENSE("GPL");
-
-static struct pci_driver emu10k1_pci_driver = {
-	.name		= "emu10k1",
-	.id_table	= emu10k1_pci_tbl,
-	.probe		= emu10k1_probe,
-	.remove		= __devexit_p(emu10k1_remove),
-};
-
-static int __init emu10k1_init_module(void)
-{
-	printk(KERN_INFO "Creative EMU10K1 PCI Audio Driver, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
-
-	return pci_register_driver(&emu10k1_pci_driver);
-}
-
-static void __exit emu10k1_cleanup_module(void)
-{
-	pci_unregister_driver(&emu10k1_pci_driver);
-
-	return;
-}
-
-module_init(emu10k1_init_module);
-module_exit(emu10k1_cleanup_module);
-
-#ifdef EMU10K1_SEQUENCER
-
-/* in midi.c */
-extern int emu10k1_seq_midi_open(int dev, int mode, 
-				void (*input)(int dev, unsigned char midi_byte),
-				void (*output)(int dev));
-extern void emu10k1_seq_midi_close(int dev);
-extern int emu10k1_seq_midi_out(int dev, unsigned char midi_byte);
-extern int emu10k1_seq_midi_start_read(int dev);
-extern int emu10k1_seq_midi_end_read(int dev);
-extern void emu10k1_seq_midi_kick(int dev);
-extern int emu10k1_seq_midi_buffer_status(int dev);
-
-static struct midi_operations emu10k1_midi_operations =
-{
-	THIS_MODULE,
-	{"EMU10K1 MIDI", 0, 0, SNDCARD_EMU10K1},
-	&std_midi_synth,
-	{0},
-	emu10k1_seq_midi_open,
-	emu10k1_seq_midi_close,
-	NULL,
-	emu10k1_seq_midi_out,
-	emu10k1_seq_midi_start_read,
-	emu10k1_seq_midi_end_read,
-	emu10k1_seq_midi_kick,
-	NULL,
-	emu10k1_seq_midi_buffer_status,
-	NULL
-};
-
-#endif
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
deleted file mode 100644
index df1e990..0000000
--- a/sound/oss/emu10k1/midi.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- **********************************************************************
- *     midi.c - /dev/midi interface for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-
-#include "hwaccess.h"
-#include "cardmo.h"
-#include "cardmi.h"
-#include "midi.h"
-
-#ifdef EMU10K1_SEQUENCER
-#include "../sound_config.h"
-#endif
-
-static DEFINE_SPINLOCK(midi_spinlock);
-
-static void init_midi_hdr(struct midi_hdr *midihdr)
-{
-	midihdr->bufferlength = MIDIIN_BUFLEN;
-	midihdr->bytesrecorded = 0;
-	midihdr->flags = 0;
-}
-
-static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hdr **midihdrptr)
-{
-	struct midi_hdr *midihdr;
-
-	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
-		ERROR();
-		return -EINVAL;
-	}
-
-	init_midi_hdr(midihdr);
-
-	midihdr->data = kmalloc(MIDIIN_BUFLEN, GFP_KERNEL);
-	if (!midihdr->data) {
-		ERROR();
-		kfree(midihdr);
-		return -1;
-	}
-
-	if (emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr) < 0) {
-		ERROR();
-		kfree(midihdr->data);
-		kfree(midihdr);
-		return -1;
-	}
-
-	*midihdrptr = midihdr;
-	list_add_tail(&midihdr->list, &midi_dev->mid_hdrs);
-
-	return 0;
-}
-
-static int emu10k1_midi_open(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct emu10k1_card *card = NULL;
-	struct emu10k1_mididevice *midi_dev;
-	struct list_head *entry;
-
-	DPF(2, "emu10k1_midi_open()\n");
-
-	/* Check for correct device to open */
-	list_for_each(entry, &emu10k1_devs) {
-		card = list_entry(entry, struct emu10k1_card, list);
-
-		if (card->midi_dev == minor)
-			goto match;
-	}
-
-	return -ENODEV;
-
-match:
-#ifdef EMU10K1_SEQUENCER
-	if (card->seq_mididev)	/* card is opened by sequencer */
-		return -EBUSY;
-#endif
-
-	/* Wait for device to become free */
-	mutex_lock(&card->open_sem);
-	while (card->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
-		if (file->f_flags & O_NONBLOCK) {
-			mutex_unlock(&card->open_sem);
-			return -EBUSY;
-		}
-
-		mutex_unlock(&card->open_sem);
-		interruptible_sleep_on(&card->open_wait);
-
-		if (signal_pending(current)) {
-			return -ERESTARTSYS;
-		}
-
-		mutex_lock(&card->open_sem);
-	}
-
-	if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
-		return -EINVAL;
-
-	midi_dev->card = card;
-	midi_dev->mistate = MIDIIN_STATE_STOPPED;
-	init_waitqueue_head(&midi_dev->oWait);
-	init_waitqueue_head(&midi_dev->iWait);
-	midi_dev->ird = 0;
-	midi_dev->iwr = 0;
-	midi_dev->icnt = 0;
-	INIT_LIST_HEAD(&midi_dev->mid_hdrs);
-
-	if (file->f_mode & FMODE_READ) {
-		struct midi_openinfo dsCardMidiOpenInfo;
-		struct midi_hdr *midihdr1;
-		struct midi_hdr *midihdr2;
-
-		dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
-		if (emu10k1_mpuin_open(card, &dsCardMidiOpenInfo) < 0) {
-			ERROR();
-			kfree(midi_dev);
-			return -ENODEV;
-		}
-
-		/* Add two buffers to receive sysex buffer */
-		if (midiin_add_buffer(midi_dev, &midihdr1) < 0) {
-			kfree(midi_dev);
-			return -ENODEV;
-		}
-
-		if (midiin_add_buffer(midi_dev, &midihdr2) < 0) {
-			list_del(&midihdr1->list);
-			kfree(midihdr1->data);
-			kfree(midihdr1);
-			kfree(midi_dev);
-			return -ENODEV;
-		}
-	}
-
-	if (file->f_mode & FMODE_WRITE) {
-		struct midi_openinfo dsCardMidiOpenInfo;
-
-		dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
-		if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
-			ERROR();
-			kfree(midi_dev);
-			return -ENODEV;
-		}
-	}
-
-	file->private_data = (void *) midi_dev;
-
-	card->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
-
-	mutex_unlock(&card->open_sem);
-
-	return nonseekable_open(inode, file);
-}
-
-static int emu10k1_midi_release(struct inode *inode, struct file *file)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
-	struct emu10k1_card *card;
-
-	lock_kernel();
-
-	card = midi_dev->card;
-	DPF(2, "emu10k1_midi_release()\n");
-
-	if (file->f_mode & FMODE_WRITE) {
-		if (!(file->f_flags & O_NONBLOCK)) {
-
-			while (!signal_pending(current) && (card->mpuout->firstmidiq != NULL)) {
-				DPF(4, "Cannot close - buffers not empty\n");
-
-				interruptible_sleep_on(&midi_dev->oWait);
-
-			}
-		}
-
-		emu10k1_mpuout_close(card);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		struct midi_hdr *midihdr;
-
-		if (midi_dev->mistate == MIDIIN_STATE_STARTED) {
-			emu10k1_mpuin_stop(card);
-			midi_dev->mistate = MIDIIN_STATE_STOPPED;
-		}
-
-		emu10k1_mpuin_reset(card);
-		emu10k1_mpuin_close(card);
-
-		while (!list_empty(&midi_dev->mid_hdrs)) {
-			midihdr = list_entry(midi_dev->mid_hdrs.next, struct midi_hdr, list);
-
-			list_del(midi_dev->mid_hdrs.next);
-			kfree(midihdr->data);
-			kfree(midihdr);
-		}
-	}
-
-	kfree(midi_dev);
-
-	mutex_lock(&card->open_sem);
-	card->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE));
-	mutex_unlock(&card->open_sem);
-	wake_up_interruptible(&card->open_wait);
-
-	unlock_kernel();
-
-	return 0;
-}
-
-static ssize_t emu10k1_midi_read(struct file *file, char __user *buffer, size_t count, loff_t * pos)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
-	ssize_t ret = 0;
-	u16 cnt;
-	unsigned long flags;
-
-	DPD(4, "emu10k1_midi_read(), count %#x\n", (u32) count);
-
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-
-	if (midi_dev->mistate == MIDIIN_STATE_STOPPED) {
-		if (emu10k1_mpuin_start(midi_dev->card) < 0) {
-			ERROR();
-			return -EINVAL;
-		}
-
-		midi_dev->mistate = MIDIIN_STATE_STARTED;
-	}
-
-	while (count > 0) {
-		cnt = MIDIIN_BUFLEN - midi_dev->ird;
-
-		spin_lock_irqsave(&midi_spinlock, flags);
-
-		if (midi_dev->icnt < cnt)
-			cnt = midi_dev->icnt;
-
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-
-		if (cnt > count)
-			cnt = count;
-
-		if (cnt <= 0) {
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			DPF(2, " Go to sleep...\n");
-
-			interruptible_sleep_on(&midi_dev->iWait);
-
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
-
-			continue;
-		}
-
-		if (copy_to_user(buffer, midi_dev->iBuf + midi_dev->ird, cnt)) {
-			ERROR();
-			return ret ? ret : -EFAULT;
-		}
-
-		midi_dev->ird += cnt;
-		midi_dev->ird %= MIDIIN_BUFLEN;
-
-		spin_lock_irqsave(&midi_spinlock, flags);
-
-		midi_dev->icnt -= cnt;
-
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-
-		if (midi_dev->icnt == 0)
-			break;
-	}
-
-	return ret;
-}
-
-static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t * pos)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
-	struct midi_hdr *midihdr;
-	unsigned long flags;
-
-	DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count);
-
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-
-	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
-		return -EINVAL;
-
-	midihdr->bufferlength = count;
-	midihdr->bytesrecorded = 0;
-	midihdr->flags = 0;
-
-	midihdr->data = kmalloc(count, GFP_KERNEL);
-	if (!midihdr->data) {
-		ERROR();
-		kfree(midihdr);
-		return -EINVAL;
-	}
-
-	if (copy_from_user(midihdr->data, buffer, count)) {
-		kfree(midihdr->data);
-		kfree(midihdr);
-		return -EFAULT;
-	}
-
-	spin_lock_irqsave(&midi_spinlock, flags);
-
-	if (emu10k1_mpuout_add_buffer(midi_dev->card, midihdr) < 0) {
-		ERROR();
-		kfree(midihdr->data);
-		kfree(midihdr);
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-		return -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&midi_spinlock, flags);
-
-	return count;
-}
-
-static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	DPF(4, "emu10k1_midi_poll() called\n");
-
-	if (file->f_mode & FMODE_WRITE)
-		poll_wait(file, &midi_dev->oWait, wait);
-
-	if (file->f_mode & FMODE_READ)
-		poll_wait(file, &midi_dev->iWait, wait);
-
-	spin_lock_irqsave(&midi_spinlock, flags);
-
-	if (file->f_mode & FMODE_WRITE)
-		mask |= POLLOUT | POLLWRNORM;
-
-	if (file->f_mode & FMODE_READ) {
-		if (midi_dev->mistate == MIDIIN_STATE_STARTED)
-			if (midi_dev->icnt > 0)
-				mask |= POLLIN | POLLRDNORM;
-	}
-
-	spin_unlock_irqrestore(&midi_spinlock, flags);
-
-	return mask;
-}
-
-int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg)
-{
-	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) refdata;
-	struct midi_hdr *midihdr = NULL;
-	unsigned long flags;
-	int i;
-
-	DPF(4, "emu10k1_midi_callback()\n");
-
-	spin_lock_irqsave(&midi_spinlock, flags);
-
-	switch (msg) {
-	case ICARDMIDI_OUTLONGDATA:
-		midihdr = (struct midi_hdr *) pmsg[2];
-
-		kfree(midihdr->data);
-		kfree(midihdr);
-		wake_up_interruptible(&midi_dev->oWait);
-
-		break;
-
-	case ICARDMIDI_INLONGDATA:
-		midihdr = (struct midi_hdr *) pmsg[2];
-
-		for (i = 0; i < midihdr->bytesrecorded; i++) {
-			midi_dev->iBuf[midi_dev->iwr++] = midihdr->data[i];
-			midi_dev->iwr %= MIDIIN_BUFLEN;
-		}
-
-		midi_dev->icnt += midihdr->bytesrecorded;
-
-		if (midi_dev->mistate == MIDIIN_STATE_STARTED) {
-			init_midi_hdr(midihdr);
-			emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr);
-			wake_up_interruptible(&midi_dev->iWait);
-		}
-		break;
-
-	case ICARDMIDI_INDATA:
-		{
-			u8 *pBuf = (u8 *) & pmsg[1];
-			u16 bytesvalid = pmsg[2];
-
-			for (i = 0; i < bytesvalid; i++) {
-				midi_dev->iBuf[midi_dev->iwr++] = pBuf[i];
-				midi_dev->iwr %= MIDIIN_BUFLEN;
-			}
-
-			midi_dev->icnt += bytesvalid;
-		}
-
-		wake_up_interruptible(&midi_dev->iWait);
-		break;
-
-	default:		/* Unknown message */
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-		return -1;
-	}
-
-	spin_unlock_irqrestore(&midi_spinlock, flags);
-
-	return 0;
-}
-
-/* MIDI file operations */
-const struct file_operations emu10k1_midi_fops = {
-	.owner		= THIS_MODULE,
-	.read		= emu10k1_midi_read,
-	.write		= emu10k1_midi_write,
-	.poll		= emu10k1_midi_poll,
-	.open		= emu10k1_midi_open,
-	.release	= emu10k1_midi_release,
-};
-
-
-#ifdef EMU10K1_SEQUENCER
-
-/* functions used for sequencer access */
-
-int emu10k1_seq_midi_open(int dev, int mode,
-				void (*input) (int dev, unsigned char data),
-				void (*output) (int dev))
-{
-	struct emu10k1_card *card;
-	struct midi_openinfo dsCardMidiOpenInfo;
-	struct emu10k1_mididevice *midi_dev;
-
-	if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
-		return -EINVAL;
-
-	card = midi_devs[dev]->devc;
-
-	if (card->open_mode)		/* card is opened native */
-		return -EBUSY;
-			
-	DPF(2, "emu10k1_seq_midi_open()\n");
-	
-	if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
-		return -EINVAL;
-
-	midi_dev->card = card;
-	midi_dev->mistate = MIDIIN_STATE_STOPPED;
-	init_waitqueue_head(&midi_dev->oWait);
-	init_waitqueue_head(&midi_dev->iWait);
-	midi_dev->ird = 0;
-	midi_dev->iwr = 0;
-	midi_dev->icnt = 0;
-	INIT_LIST_HEAD(&midi_dev->mid_hdrs);
-
-	dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
-	if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
-		ERROR();
-		return -ENODEV;
-	}
-
-	card->seq_mididev = midi_dev;
-		
-	return 0;
-}
-
-void emu10k1_seq_midi_close(int dev)
-{
-	struct emu10k1_card *card;
-
-	DPF(2, "emu10k1_seq_midi_close()\n");
-	if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
-		return;
-
-	card = midi_devs[dev]->devc;
-	emu10k1_mpuout_close(card);
-
-	kfree(card->seq_mididev);
-	card->seq_mididev = NULL;
-}
-
-int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
-{
-	struct emu10k1_card *card;
-	struct midi_hdr *midihdr;
-	unsigned long flags;
-
-	if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
-		return -EINVAL;
-
-	card = midi_devs[dev]->devc;
-
-	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
-		return -EINVAL;
-
-	midihdr->bufferlength = 1;
-	midihdr->bytesrecorded = 0;
-	midihdr->flags = 0;
-
-	midihdr->data = kmalloc(1, GFP_KERNEL);
-	if (!midihdr->data) {
-		ERROR();
-		kfree(midihdr);
-		return -EINVAL;
-	}
-
-	*(midihdr->data) = midi_byte;
-	
-	spin_lock_irqsave(&midi_spinlock, flags);
-
-	if (emu10k1_mpuout_add_buffer(card, midihdr) < 0) {
-		ERROR();
-		kfree(midihdr->data);
-		kfree(midihdr);
-		spin_unlock_irqrestore(&midi_spinlock, flags);
-		return -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&midi_spinlock, flags);
-
-	return 1;
-}
-
-int emu10k1_seq_midi_start_read(int dev)
-{
-	return 0;
-}
-
-int emu10k1_seq_midi_end_read(int dev)
-{
-	return 0;
-}
-
-void emu10k1_seq_midi_kick(int dev)
-{
-}
-
-int emu10k1_seq_midi_buffer_status(int dev)
-{
-	int count;
-	struct midi_queue *queue;
-	struct emu10k1_card *card;
-
-	if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
-		return -EINVAL;
-
-	count = 0;
-
-	card = midi_devs[dev]->devc;
-	queue = card->mpuout->firstmidiq;
-
-	while (queue != NULL) {
-		count++;
-		if (queue == card->mpuout->lastmidiq)
-			break;
-
-		queue = queue->next;
-	}
-
-	return count;
-}
-
-#endif
-
diff --git a/sound/oss/emu10k1/midi.h b/sound/oss/emu10k1/midi.h
deleted file mode 100644
index 2459ec9..0000000
--- a/sound/oss/emu10k1/midi.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*     
- **********************************************************************
- *     midi.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */ 
-
-#ifndef _MIDI_H
-#define _MIDI_H
-
-#define FMODE_MIDI_SHIFT 3
-#define FMODE_MIDI_READ  (FMODE_READ << FMODE_MIDI_SHIFT)
-#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
-
-#define MIDIIN_STATE_STARTED 0x00000001
-#define MIDIIN_STATE_STOPPED 0x00000002
-
-#define MIDIIN_BUFLEN 1024
-
-struct emu10k1_mididevice
-{
-	struct emu10k1_card *card;
-	u32 mistate;
-	wait_queue_head_t oWait;
-	wait_queue_head_t iWait;
-	s8 iBuf[MIDIIN_BUFLEN];
-	u16 ird, iwr, icnt;
-	struct list_head mid_hdrs;
-};
-
-/* uncomment next line to use midi port on Audigy drive */
-//#define USE_AUDIGY_DRIVE_MIDI
-
-#ifdef USE_AUDIGY_DRIVE_MIDI
-#define A_MUDATA	A_MUDATA2
-#define A_MUCMD		A_MUCMD2
-#define A_MUSTAT	A_MUCMD2
-#define A_IPR_MIDITRANSBUFEMPTY	A_IPR_MIDITRANSBUFEMPTY2
-#define A_IPR_MIDIRECVBUFEMPTY	A_IPR_MIDIRECVBUFEMPTY2
-#define A_INTE_MIDITXENABLE	A_INTE_MIDITXENABLE2
-#define A_INTE_MIDIRXENABLE	A_INTE_MIDIRXENABLE2
-#else
-#define A_MUDATA	A_MUDATA1
-#define A_MUCMD		A_MUCMD1
-#define A_MUSTAT	A_MUCMD1
-#define A_IPR_MIDITRANSBUFEMPTY	A_IPR_MIDITRANSBUFEMPTY1
-#define A_IPR_MIDIRECVBUFEMPTY	A_IPR_MIDIRECVBUFEMPTY1
-#define A_INTE_MIDITXENABLE	A_INTE_MIDITXENABLE1
-#define A_INTE_MIDIRXENABLE	A_INTE_MIDIRXENABLE1
-#endif
-
-
-#endif /* _MIDI_H */
-
diff --git a/sound/oss/emu10k1/mixer.c b/sound/oss/emu10k1/mixer.c
deleted file mode 100644
index bc3805f..0000000
--- a/sound/oss/emu10k1/mixer.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- **********************************************************************
- *     mixer.c - /dev/mixer interface for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        cleaned up stuff
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/fs.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "recmgr.h"
-
-
-static const u32 bass_table[41][5] = {
-	{ 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
-	{ 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
-	{ 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
-	{ 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c },
-	{ 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b },
-	{ 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 },
-	{ 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f },
-	{ 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 },
-	{ 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 },
-	{ 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 },
-	{ 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 },
-	{ 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be },
-	{ 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b },
-	{ 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c },
-	{ 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b },
-	{ 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 },
-	{ 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a },
-	{ 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 },
-	{ 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 },
-	{ 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e },
-	{ 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee },
-	{ 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 },
-	{ 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 },
-	{ 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 },
-	{ 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 },
-	{ 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e },
-	{ 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 },
-	{ 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 },
-	{ 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 },
-	{ 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 },
-	{ 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 },
-	{ 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca },
-	{ 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 },
-	{ 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 },
-	{ 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 },
-	{ 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 },
-	{ 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a },
-	{ 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f },
-	{ 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 },
-	{ 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 },
-	{ 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
-};
-
-static const u32 treble_table[41][5] = {
-	{ 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
-	{ 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
-	{ 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
-	{ 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca },
-	{ 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 },
-	{ 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 },
-	{ 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 },
-	{ 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 },
-	{ 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 },
-	{ 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df },
-	{ 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff },
-	{ 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 },
-	{ 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c },
-	{ 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 },
-	{ 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 },
-	{ 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 },
-	{ 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 },
-	{ 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d },
-	{ 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 },
-	{ 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 },
-	{ 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f },
-	{ 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb },
-	{ 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 },
-	{ 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 },
-	{ 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd },
-	{ 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 },
-	{ 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad },
-	{ 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 },
-	{ 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 },
-	{ 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c },
-	{ 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 },
-	{ 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 },
-	{ 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 },
-	{ 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 },
-	{ 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 },
-	{ 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 },
-	{ 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d },
-	{ 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b },
-	{ 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 },
-	{ 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd },
-	{ 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
-};
-
-
-static void set_bass(struct emu10k1_card *card, int l, int r)
-{
-	int i;
-
-	l = (l * 40 + 50) / 100;
-	r = (r * 40 + 50) / 100;
-
-	for (i = 0; i < 5; i++)
-		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]);
-}
-
-static void set_treble(struct emu10k1_card *card, int l, int r)
-{
-	int i;
-
-	l = (l * 40 + 50) / 100;
-	r = (r * 40 + 50) / 100;
-
-	for (i = 0; i < 5; i++)
-		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]);
-}
-
-const char volume_params[SOUND_MIXER_NRDEVICES]= {
-/* Used by the ac97 driver */
-	[SOUND_MIXER_VOLUME]	=	VOL_6BIT,
-	[SOUND_MIXER_BASS]	=	VOL_4BIT,
-	[SOUND_MIXER_TREBLE]	=	VOL_4BIT,
-	[SOUND_MIXER_PCM]	=	VOL_5BIT,
-	[SOUND_MIXER_SPEAKER]	=	VOL_4BIT,
-	[SOUND_MIXER_LINE]	=	VOL_5BIT,
-	[SOUND_MIXER_MIC]	=	VOL_5BIT,
-	[SOUND_MIXER_CD]	=	VOL_5BIT,
-	[SOUND_MIXER_ALTPCM]	=	VOL_6BIT,
-	[SOUND_MIXER_IGAIN]	=	VOL_4BIT,
-	[SOUND_MIXER_LINE1]	=	VOL_5BIT,
-	[SOUND_MIXER_PHONEIN]	= 	VOL_5BIT,
-	[SOUND_MIXER_PHONEOUT]	= 	VOL_6BIT,
-	[SOUND_MIXER_VIDEO]	=	VOL_5BIT,
-/* Not used by the ac97 driver */
-	[SOUND_MIXER_SYNTH]	=	VOL_5BIT,
-	[SOUND_MIXER_IMIX]	=	VOL_5BIT,
-	[SOUND_MIXER_RECLEV]	=	VOL_5BIT,
-	[SOUND_MIXER_OGAIN]	=	VOL_5BIT,
-	[SOUND_MIXER_LINE2]	=	VOL_5BIT,
-	[SOUND_MIXER_LINE3]	=	VOL_5BIT,
-	[SOUND_MIXER_DIGITAL1]	=	VOL_5BIT,
-	[SOUND_MIXER_DIGITAL2]	=	VOL_5BIT,
-	[SOUND_MIXER_DIGITAL3]	=	VOL_5BIT,
-	[SOUND_MIXER_RADIO]	=	VOL_5BIT,
-	[SOUND_MIXER_MONITOR]	=	VOL_5BIT
-};
-
-/* Mixer file operations */
-static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, unsigned long arg)
-{
-	struct mixer_private_ioctl *ctl;
-	struct dsp_patch *patch;
-	u32 size, page;
-	int addr, size_reg, i, ret;
-	unsigned int id, ch;
-	void __user *argp = (void __user *)arg;
-
-	switch (cmd) {
-
-	case SOUND_MIXER_PRIVATE3:
-
-		ctl = kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
-		if (ctl == NULL)
-			return -ENOMEM;
-
-		if (copy_from_user(ctl, argp, sizeof(struct mixer_private_ioctl))) {
-			kfree(ctl);
-			return -EFAULT;
-		}
-
-		ret = 0;
-		switch (ctl->cmd) {
-#ifdef DBGEMU
-		case CMD_WRITEFN0:
-			emu10k1_writefn0_2(card, ctl->val[0], ctl->val[1], ctl->val[2]);
-			break;
-#endif
-		case CMD_WRITEPTR:
-#ifdef DBGEMU
-			if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000) {
-#else
-			if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000 || ((ctl->val[0] < 0x100 ) &&
-		    //Any register allowed raw access goes here:
-				     (ctl->val[0] != A_SPDIF_SAMPLERATE) && (ctl->val[0] != A_DBG)
-			)
-				) {
-#endif
-				ret = -EINVAL;
-				break;
-			}
-			sblive_writeptr(card, ctl->val[0], ctl->val[1], ctl->val[2]);
-			break;
-
-		case CMD_READFN0:
-			ctl->val[2] = emu10k1_readfn0(card, ctl->val[0]);
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_READPTR:
-			if (ctl->val[1] >= 0x40 || (ctl->val[0] & 0x7ff) > 0xff) {
-				ret = -EINVAL;
-				break;
-			}
-
-			if ((ctl->val[0] & 0x7ff) > 0x3f)
-				ctl->val[1] = 0x00;
-
-			ctl->val[2] = sblive_readptr(card, ctl->val[0], ctl->val[1]);
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_SETRECSRC:
-			switch (ctl->val[0]) {
-			case WAVERECORD_AC97:
-				if (card->is_aps) {
-					ret = -EINVAL;
-					break;
-				}
-
-				card->wavein.recsrc = WAVERECORD_AC97;
-				break;
-
-			case WAVERECORD_MIC:
-				card->wavein.recsrc = WAVERECORD_MIC;
-				break;
-
-			case WAVERECORD_FX:
-				card->wavein.recsrc = WAVERECORD_FX;
-				card->wavein.fxwc = ctl->val[1] & 0xffff;
-
-				if (!card->wavein.fxwc)
-					ret = -EINVAL;
-
-				break;
-
-			default:
-				ret = -EINVAL;
-				break;
-			}
-			break;
-
-		case CMD_GETRECSRC:
-			ctl->val[0] = card->wavein.recsrc;
-			ctl->val[1] = card->wavein.fxwc;
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_GETVOICEPARAM:
-			ctl->val[0] = card->waveout.send_routing[0];
-			ctl->val[1] = card->waveout.send_dcba[0];
-
-			ctl->val[2] = card->waveout.send_routing[1];
-			ctl->val[3] = card->waveout.send_dcba[1];
-
-			ctl->val[4] = card->waveout.send_routing[2];
-			ctl->val[5] = card->waveout.send_dcba[2];
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_SETVOICEPARAM:
-			card->waveout.send_routing[0] = ctl->val[0];
-			card->waveout.send_dcba[0] = ctl->val[1];
-
-			card->waveout.send_routing[1] = ctl->val[2];
-			card->waveout.send_dcba[1] = ctl->val[3];
-
-			card->waveout.send_routing[2] = ctl->val[4];
-			card->waveout.send_dcba[2] = ctl->val[5];
-
-			break;
-		
-		case CMD_SETMCH_FX:
-			card->mchannel_fx = ctl->val[0] & 0x000f;
-			break;
-		
-		case CMD_GETPATCH:
-			if (ctl->val[0] == 0) {
-				if (copy_to_user(argp, &card->mgr.rpatch, sizeof(struct dsp_rpatch)))
-                                	ret = -EFAULT;
-			} else {
-				if ((ctl->val[0] - 1) / PATCHES_PER_PAGE >= card->mgr.current_pages) {
-					ret = -EINVAL;
-					break;
-				}
-
-				if (copy_to_user(argp, PATCH(&card->mgr, ctl->val[0] - 1), sizeof(struct dsp_patch)))
-					ret = -EFAULT;
-			}
-
-			break;
-
-		case CMD_GETGPR:
-			id = ctl->val[0];
-
-			if (id > NUM_GPRS) {
-				ret = -EINVAL;
-				break;
-			}
-
-			if (copy_to_user(argp, &card->mgr.gpr[id], sizeof(struct dsp_gpr)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_GETCTLGPR:
-			addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, &((char *) ctl->val)[PATCH_NAME_SIZE]);
-			ctl->val[0] = sblive_readptr(card, addr, 0);
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_SETPATCH:
-			if (ctl->val[0] == 0)
-				memcpy(&card->mgr.rpatch, &ctl->val[1], sizeof(struct dsp_rpatch));
-			else {
-				page = (ctl->val[0] - 1) / PATCHES_PER_PAGE;
-				if (page > MAX_PATCHES_PAGES) {
-					ret = -EINVAL;
-					break;
-				}
-
-				if (page >= card->mgr.current_pages) {
-					for (i = card->mgr.current_pages; i < page + 1; i++) {
-				                card->mgr.patch[i] = (void *)__get_free_page(GFP_KERNEL);
-						if(card->mgr.patch[i] == NULL) {
-							card->mgr.current_pages = i;
-							ret = -ENOMEM;
-							break;
-						}
-						memset(card->mgr.patch[i], 0, PAGE_SIZE);
-					}
-					card->mgr.current_pages = page + 1;
-				}
-
-				patch = PATCH(&card->mgr, ctl->val[0] - 1);
-
-				memcpy(patch, &ctl->val[1], sizeof(struct dsp_patch));
-
-				if (patch->code_size == 0) {
-					for(i = page + 1; i < card->mgr.current_pages; i++)
-                                                free_page((unsigned long) card->mgr.patch[i]);
-
-					card->mgr.current_pages = page + 1;
-				}
-			}
-			break;
-
-		case CMD_SETGPR:
-			if (ctl->val[0] > NUM_GPRS) {
-				ret = -EINVAL;
-				break;
-			}
-
-			memcpy(&card->mgr.gpr[ctl->val[0]], &ctl->val[1], sizeof(struct dsp_gpr));
-			break;
-
-		case CMD_SETCTLGPR:
-			addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, (char *) ctl->val + PATCH_NAME_SIZE);
-			emu10k1_set_control_gpr(card, addr, *((s32 *)((char *) ctl->val + 2 * PATCH_NAME_SIZE)), 0);
-			break;
-
-		case CMD_SETGPOUT:
-			if ( ((ctl->val[0] > 2) && (!card->is_audigy))
-			     || (ctl->val[0] > 15) || ctl->val[1] > 1) {
-				ret= -EINVAL;
-				break;
-			}
-
-			if (card->is_audigy)
-				emu10k1_writefn0(card, (1 << 24) | ((ctl->val[0]) << 16) | A_IOCFG, ctl->val[1]);
-			else
-				emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]);
-			break;
-
-		case CMD_GETGPR2OSS:
-			id = ctl->val[0];
-			ch = ctl->val[1];
-
-			if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) {
-				ret = -EINVAL;
-				break;
-			}
-
-			ctl->val[2] = card->mgr.ctrl_gpr[id][ch];
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-
-			break;
-
-		case CMD_SETGPR2OSS:
-			id = ctl->val[0];
-			/* 0 == left, 1 == right */
-			ch = ctl->val[1];
-			addr = ctl->val[2];
-
-			if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) {
-				ret = -EINVAL;
-				break;
-			}
-
-			card->mgr.ctrl_gpr[id][ch] = addr;
-
-			if (card->is_aps)
-				break;
-
-			if (addr >= 0) {
-				unsigned int state = card->ac97->mixer_state[id];
-
-				if (ch == 1) {
-					state >>= 8;
-					card->ac97->stereo_mixers |= (1 << id);
-				}
-
-				card->ac97->supported_mixers |= (1 << id);
-
-				if (id == SOUND_MIXER_TREBLE) {
-					set_treble(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff);
-				} else if (id == SOUND_MIXER_BASS) {
-					set_bass(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff);
-				} else
-					emu10k1_set_volume_gpr(card, addr, state & 0xff,
-							       volume_params[id]);
-			} else {
-				card->ac97->stereo_mixers &= ~(1 << id);
-				card->ac97->stereo_mixers |= card->ac97_stereo_mixers;
-
-				if (ch == 0) {
-					card->ac97->supported_mixers &= ~(1 << id);
-					card->ac97->supported_mixers |= card->ac97_supported_mixers;
-				}
-			}
-			break;
-
-		case CMD_SETPASSTHROUGH:
-			card->pt.selected = ctl->val[0] ? 1 : 0;
-			if (card->pt.state != PT_STATE_INACTIVE)
-				break;
-
-			card->pt.spcs_to_use = ctl->val[0] & 0x07;
-			break;
-
-		case CMD_PRIVATE3_VERSION:
-			ctl->val[0] = PRIVATE3_VERSION;	//private3 version
-			ctl->val[1] = MAJOR_VER;	//major driver version
-			ctl->val[2] = MINOR_VER;	//minor driver version
-			ctl->val[3] = card->is_audigy;	//1=card is audigy
-
-			if (card->is_audigy)
-				ctl->val[4]=emu10k1_readfn0(card, 0x18);
-
-			if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
-				ret = -EFAULT;
-			break;
-
-		case CMD_AC97_BOOST:
-			if (ctl->val[0])
-				emu10k1_ac97_write(card->ac97, 0x18, 0x0);	
-			else
-				emu10k1_ac97_write(card->ac97, 0x18, 0x0808);
-			break;
-		default:
-			ret = -EINVAL;
-			break;
-		}
-
-		kfree(ctl);
-		return ret;
-		break;
-
-	case SOUND_MIXER_PRIVATE4:
-
-		if (copy_from_user(&size, argp, sizeof(size)))
-			return -EFAULT;
-
-		DPD(2, "External tram size %#x\n", size);
-
-		if (size > 0x1fffff)
-			return -EINVAL;
-
-		size_reg = 0;
-
-		if (size != 0) {
-			size = (size - 1) >> 14;
-
-			while (size) {
-				size >>= 1;
-				size_reg++;
-			}
-
-			size = 0x4000 << size_reg;
-		}
-
-		DPD(2, "External tram size %#x %#x\n", size, size_reg);
-
-		if (size != card->tankmem.size) {
-			if (card->tankmem.size > 0) {
-				emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 1);
-
-				sblive_writeptr_tag(card, 0, TCB, 0, TCBS, 0, TAGLIST_END);
-
-				pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
-
-				card->tankmem.size = 0;
-			}
-
-			if (size != 0) {
-				card->tankmem.addr = pci_alloc_consistent(card->pci_dev, size, &card->tankmem.dma_handle);
-				if (card->tankmem.addr == NULL)
-					return -ENOMEM;
-
-				card->tankmem.size = size;
-
-				sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS,(u32) size_reg, TAGLIST_END);
-
-				emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0);
-			}
-		}
-		return 0;
-		break;
-
-	default:
-		break;
-	}
-
-	return -EINVAL;
-}
-
-static int emu10k1_dsp_mixer(struct emu10k1_card *card, unsigned int oss_mixer, unsigned long arg)
-{
-	unsigned int left, right;
-	int val;
-	int scale;
-
-	card->ac97->modcnt++;
-
-	if (get_user(val, (int __user *)arg))
-		return -EFAULT;
-
-	/* cleanse input a little */
-	right = ((val >> 8)  & 0xff);
-	left = (val  & 0xff);
-
-	if (right > 100) right = 100;
-	if (left > 100) left = 100;
-
-	card->ac97->mixer_state[oss_mixer] = (right << 8) | left;
-	if (oss_mixer == SOUND_MIXER_TREBLE) {
-		set_treble(card, left, right);
-		return 0;
-	} if (oss_mixer == SOUND_MIXER_BASS) {
-		set_bass(card, left, right);
-		return 0;
-	}
-
-	if (oss_mixer == SOUND_MIXER_VOLUME)
-		scale = 1 << card->ac97->bit_resolution;
-	else
-		scale = volume_params[oss_mixer];
-
-	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left, scale);
-	emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right, scale);
-
-	if (card->ac97_supported_mixers & (1 << oss_mixer))
-		card->ac97->write_mixer(card->ac97, oss_mixer, left, right);
-
-	return 0;
-}
-
-static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-	struct emu10k1_card *card = file->private_data;
-	unsigned int oss_mixer = _IOC_NR(cmd);
-	
-	ret = -EINVAL;
-	if (!card->is_aps) {
-		if (cmd == SOUND_MIXER_INFO) {
-			mixer_info info;
-
-			strlcpy(info.id, card->ac97->name, sizeof(info.id));
-
-			if (card->is_audigy)
-				strlcpy(info.name, "Audigy - Emu10k1", sizeof(info.name));
-			else
-				strlcpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name));
-				
-			info.modify_counter = card->ac97->modcnt;
-
-			if (copy_to_user((void __user *)arg, &info, sizeof(info)))
-				return -EFAULT;
-
-			return 0;
-		}
-
-		if ((_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
-			ret = emu10k1_dsp_mixer(card, oss_mixer, arg);
-		else
-			ret = card->ac97->mixer_ioctl(card->ac97, cmd, arg);
-	}
-	
-	if (ret < 0)
-		ret = emu10k1_private_mixer(card, cmd, arg);
-
-	return ret;
-}
-
-static int emu10k1_mixer_open(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct emu10k1_card *card = NULL;
-	struct list_head *entry;
-
-	DPF(4, "emu10k1_mixer_open()\n");
-
-	list_for_each(entry, &emu10k1_devs) {
-		card = list_entry(entry, struct emu10k1_card, list);
-
-		if (card->ac97->dev_mixer == minor)
-			goto match;
-	}
-
-	return -ENODEV;
-
-      match:
-	file->private_data = card;
-	return 0;
-}
-
-static int emu10k1_mixer_release(struct inode *inode, struct file *file)
-{
-	DPF(4, "emu10k1_mixer_release()\n");
-	return 0;
-}
-
-const struct file_operations emu10k1_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.ioctl		= emu10k1_mixer_ioctl,
-	.open		= emu10k1_mixer_open,
-	.release	= emu10k1_mixer_release,
-};
diff --git a/sound/oss/emu10k1/passthrough.c b/sound/oss/emu10k1/passthrough.c
deleted file mode 100644
index 6d21d43..0000000
--- a/sound/oss/emu10k1/passthrough.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- **********************************************************************
- *     passthrough.c -- Emu10k1 digital passthrough
- *     Copyright (C) 2001  Juha Yrjölä <jyrjola@cc.hut.fi>
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     May 15, 2001	    Juha Yrjölä	    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-                       
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-
-#include "hwaccess.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "recmgr.h"
-#include "irqmgr.h"
-#include "audio.h"
-#include "8010.h"
-
-static void pt_putsamples(struct pt_data *pt, u16 *ptr, u16 left, u16 right)
-{
-	unsigned int idx;
-
-	ptr[pt->copyptr] = left;
-	idx = pt->copyptr + PT_SAMPLES/2;
-	idx %= PT_SAMPLES;
-	ptr[idx] = right;
-}
-
-static inline int pt_can_write(struct pt_data *pt)
-{
-	return pt->blocks_copied < pt->blocks_played + 8;
-}
-
-static int pt_wait_for_write(struct emu10k1_wavedevice *wavedev, int nonblock)
-{
-	struct emu10k1_card *card = wavedev->card;
-	struct pt_data *pt = &card->pt;
-
-	if (nonblock && !pt_can_write(pt))
-		return -EAGAIN;
-	while (!pt_can_write(pt) && pt->state != PT_STATE_INACTIVE) {
-		interruptible_sleep_on(&pt->wait);
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-	}
-	if (pt->state == PT_STATE_INACTIVE)
-		return -EAGAIN;
-	
-	return 0;
-}
-
-static int pt_putblock(struct emu10k1_wavedevice *wave_dev, u16 *block, int nonblock)
-{
-	struct woinst *woinst = wave_dev->woinst;
-	struct emu10k1_card *card = wave_dev->card;
-	struct pt_data *pt = &card->pt;
-	u16 *ptr = (u16 *) card->tankmem.addr;
-	int i = 0, r;
-	unsigned long flags;
-
-	r = pt_wait_for_write(wave_dev, nonblock);
-	if (r < 0)
-		return r;
-	spin_lock_irqsave(&card->pt.lock, flags);
-	while (i < PT_BLOCKSAMPLES) {
-		pt_putsamples(pt, ptr, block[2*i], block[2*i+1]);
-		if (pt->copyptr == 0)
-			pt->copyptr = PT_SAMPLES;
-		pt->copyptr--;
-		i++;
-	}
-	woinst->total_copied += PT_BLOCKSIZE;
-	pt->blocks_copied++;
-	if (pt->blocks_copied >= 4 && pt->state != PT_STATE_PLAYING) {
-		DPF(2, "activating digital pass-through playback\n");
-		sblive_writeptr(card, GPR_BASE + pt->enable_gpr, 0, 1);
-		pt->state = PT_STATE_PLAYING;
-	}
-	spin_unlock_irqrestore(&card->pt.lock, flags);
-	return 0;
-}
-
-int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev)
-{
-	u32 bits;
-	struct emu10k1_card *card = wave_dev->card;
-	struct pt_data *pt = &card->pt;
-	int i;
-
-	for (i = 0; i < 3; i++) {
-		pt->old_spcs[i] = sblive_readptr(card, SPCS0 + i, 0);
-		if (pt->spcs_to_use & (1 << i)) {
-			DPD(2, "using S/PDIF port %d\n", i);
-			bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
-				SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
-				0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
-			if (pt->ac3data)
-				bits |= SPCS_NOTAUDIODATA;
-			sblive_writeptr(card, SPCS0 + i, 0, bits);
-		}
-	}
-	return 0;
-}
-
-ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t count)
-{
-	struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-	struct emu10k1_card *card = wave_dev->card;
-	struct pt_data *pt = &card->pt;
-	int nonblock, i, r, blocks, blocks_copied, bytes_copied = 0;
-
-	DPD(3, "emu10k1_pt_write(): %d bytes\n", count);
-	
-	nonblock = file->f_flags & O_NONBLOCK;
-	
-	if (card->tankmem.size < PT_SAMPLES*2)
-		return -EFAULT;
-	if (pt->state == PT_STATE_INACTIVE) {
-		DPF(2, "bufptr init\n");
-		pt->playptr = PT_SAMPLES-1;
-		pt->copyptr = PT_INITPTR;
-		pt->blocks_played = pt->blocks_copied = 0;
-		memset(card->tankmem.addr, 0, card->tankmem.size);
-		pt->state = PT_STATE_ACTIVATED;
-		pt->buf = kmalloc(PT_BLOCKSIZE, GFP_KERNEL);
-		pt->prepend_size = 0;
-		if (pt->buf == NULL)
-			return -ENOMEM;
-		emu10k1_pt_setup(wave_dev);
-	}
-	if (pt->prepend_size) {
-		int needed = PT_BLOCKSIZE - pt->prepend_size;
-
-		DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed);
-		if (count < needed) {
-			if (copy_from_user(pt->buf + pt->prepend_size,
-					   buffer, count))
-				return -EFAULT;
-			pt->prepend_size += count;
-			DPD(3, "prepend size now %d\n", pt->prepend_size);
-			return count;
-		}
-		if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed))
-			return -EFAULT;
-		r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock);
-		if (r)
-			return r;
-		bytes_copied += needed;
-		pt->prepend_size = 0;
-	}
-	blocks = (count-bytes_copied)/PT_BLOCKSIZE;
-	blocks_copied = 0;
-	while (blocks > 0) {
-		u16 __user *bufptr = (u16 __user *) buffer + (bytes_copied/2);
-		if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE))
-			return -EFAULT;
-		r = pt_putblock(wave_dev, (u16 *)pt->buf, nonblock);
-		if (r) {
-			if (bytes_copied)
-				return bytes_copied;
-			else
-				return r;
-		}
-		bytes_copied += PT_BLOCKSIZE;
-		blocks--;
-		blocks_copied++;
-	}
-	i = count - bytes_copied;
-	if (i) {
-		pt->prepend_size = i;
-		if (copy_from_user(pt->buf, buffer + bytes_copied, i))
-			return -EFAULT;
-		bytes_copied += i;
-		DPD(3, "filling prepend buffer with %d bytes", i);
-	}
-	return bytes_copied;
-}
-
-void emu10k1_pt_stop(struct emu10k1_card *card)
-{
-	struct pt_data *pt = &card->pt;
-	int i;
-
-	if (pt->state != PT_STATE_INACTIVE) {
-		DPF(2, "digital pass-through stopped\n");
-		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 0);
-		for (i = 0; i < 3; i++) {
-                        if (pt->spcs_to_use & (1 << i))
-				sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]);
-		}
-		pt->state = PT_STATE_INACTIVE;
-		kfree(pt->buf);
-	}
-}
-
-void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev)
-{
-	struct woinst *woinst = wave_dev->woinst;
-	struct pt_data *pt = &wave_dev->card->pt;
-	u32 pos;
-
-	if (pt->state == PT_STATE_PLAYING && pt->pos_gpr >= 0) {
-		pos = sblive_readptr(wave_dev->card, GPR_BASE + pt->pos_gpr, 0);
-		if (pos > PT_BLOCKSAMPLES)
-			pos = PT_BLOCKSAMPLES;
-		pos = 4 * (PT_BLOCKSAMPLES - pos);
-	} else
-		pos = 0;
-	woinst->total_played = pt->blocks_played * woinst->buffer.fragment_size + pos;
-	woinst->buffer.hw_pos = pos;
-}
diff --git a/sound/oss/emu10k1/passthrough.h b/sound/oss/emu10k1/passthrough.h
deleted file mode 100644
index 420cc978..0000000
--- a/sound/oss/emu10k1/passthrough.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- **********************************************************************
- *     passthrough.h -- Emu10k1 digital passthrough header file
- *     Copyright (C) 2001  Juha Yrjölä <jyrjola@cc.hut.fi>
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     May 15, 2001	    Juha Yrjölä     base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#ifndef _PASSTHROUGH_H
-#define _PASSTHROUGH_H
-
-#include "audio.h"
-
-/* number of 16-bit stereo samples in XTRAM buffer */
-#define PT_SAMPLES 0x8000
-#define PT_BLOCKSAMPLES 0x400
-#define PT_BLOCKSIZE (PT_BLOCKSAMPLES*4)
-#define PT_BLOCKSIZE_LOG2 12
-#define PT_BLOCKCOUNT (PT_SAMPLES/PT_BLOCKSAMPLES)
-#define PT_INITPTR (PT_SAMPLES/2-1)
-
-#define PT_STATE_INACTIVE 0
-#define PT_STATE_ACTIVATED 1
-#define PT_STATE_PLAYING 2
-
-/* passthrough struct */
-struct pt_data
-{
-	u8	selected, state, spcs_to_use;
-	int	intr_gpr, enable_gpr, pos_gpr;
-	u32	blocks_played, blocks_copied, old_spcs[3];
-	u32	playptr, copyptr;
-	u32	prepend_size;
-	u8	*buf;
-	u8	ac3data;
-
-	char	*patch_name, *intr_gpr_name, *enable_gpr_name, *pos_gpr_name;
-
-	wait_queue_head_t wait;
-	spinlock_t lock;
-};
-
-/*
-  Passthrough can be done in two methods:
-
-  Method 1 : tram
-     In original emu10k1, we couldn't bypass the sample rate converters. Even at 48kHz
-     (the internal sample rate of the emu10k1) the samples would get messed up.
-     To over come this, samples are copied into the tram and a special dsp patch copies
-     the samples out and generates interrupts when a block has finnished playing.
-
-  Method 2 : Interpolator bypass
-
-     Creative fixed the sample rate convert problem in emu10k1 rev 7 and higher
-     (including the emu10k2 (audigy)). This allows us to use the regular, and much simpler
-     playback method. 
-
-
-  In both methods, dsp code is used to mux audio and passthrough. This ensures that the spdif
-  doesn't receive audio and pasthrough data at the same time. The spdif flag SPCS_NOTAUDIODATA
-  is set to tell 
-
- */
-
-// emu10k1 revs greater than or equal to 7 can use method2
-
-#define USE_PT_METHOD2  (card->is_audigy)
-#define USE_PT_METHOD1	!USE_PT_METHOD2
-
-ssize_t emu10k1_pt_write(struct file *file, const char __user *buf, size_t count);
-
-int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev);
-void emu10k1_pt_stop(struct emu10k1_card *card);
-void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev);
-
-#endif /* _PASSTHROUGH_H */
diff --git a/sound/oss/emu10k1/recmgr.c b/sound/oss/emu10k1/recmgr.c
deleted file mode 100644
index 2ce5618..0000000
--- a/sound/oss/emu10k1/recmgr.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- **********************************************************************
- *     recmgr.c -- Recording manager for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include <linux/delay.h>
-#include "8010.h"
-#include "recmgr.h"
-
-void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	DPF(2, "emu10k1_reset_record()\n");
-
-	sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE);
-
-	sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval);	
-
-	while (sblive_readptr(card, buffer->idxreg, 0))
-		udelay(5);
-}
-
-void emu10k1_start_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	DPF(2, "emu10k1_start_record()\n");
-
-	if (buffer->adcctl)
-		sblive_writeptr(card, ADCCR, 0, buffer->adcctl);
-}
-
-void emu10k1_stop_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
-	DPF(2, "emu10k1_stop_record()\n");
-
-	/* Disable record transfer */
-	if (buffer->adcctl)
-		sblive_writeptr(card, ADCCR, 0, 0);
-}
-
-void emu10k1_set_record_src(struct emu10k1_card *card, struct wiinst *wiinst)
-{
-	struct wavein_buffer *buffer = &wiinst->buffer;
-
-	DPF(2, "emu10k1_set_record_src()\n");
-
-	switch (wiinst->recsrc) {
-
-	case WAVERECORD_AC97:
-		DPF(2, "recording source: AC97\n");
-		buffer->sizereg = ADCBS;
-		buffer->addrreg = ADCBA;
-		buffer->idxreg = card->is_audigy ? A_ADCIDX_IDX : ADCIDX_IDX;
-
-		switch (wiinst->format.samplingrate) {
-		case 0xBB80:
-			buffer->adcctl = ADCCR_SAMPLERATE_48;
-			break;
-		case 0xAC44:
-			buffer->adcctl = ADCCR_SAMPLERATE_44;
-			break;
-		case 0x7D00:
-			buffer->adcctl = ADCCR_SAMPLERATE_32;
-			break;
-		case 0x5DC0:
-			buffer->adcctl = ADCCR_SAMPLERATE_24;
-			break;
-		case 0x5622:
-			buffer->adcctl = ADCCR_SAMPLERATE_22;
-			break;
-		case 0x3E80:
-			buffer->adcctl = ADCCR_SAMPLERATE_16;
-			break;
-		// FIXME: audigy supports 12kHz recording
-		/*
-		case ????:
-			buffer->adcctl = A_ADCCR_SAMPLERATE_12;
-			break;
-		*/
-		case 0x2B11:
-			buffer->adcctl = card->is_audigy ? A_ADCCR_SAMPLERATE_11 : ADCCR_SAMPLERATE_11;
-			break;
-		case 0x1F40:
-			buffer->adcctl = card->is_audigy ? A_ADCCR_SAMPLERATE_8 : ADCCR_SAMPLERATE_8;
-			break;
-		default:
-			BUG();
-			break;
-		}
-
-		buffer->adcctl |= card->is_audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
-
-		if (wiinst->format.channels == 2)
-			buffer->adcctl |= card->is_audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
-
-		break;
-
-	case WAVERECORD_MIC:
-		DPF(2, "recording source: MIC\n");
-		buffer->sizereg = MICBS;
-		buffer->addrreg = MICBA;
-		buffer->idxreg = MICIDX_IDX;
-		buffer->adcctl = 0;
-		break;
-
-	case WAVERECORD_FX:
-		DPF(2, "recording source: FX\n");
-		buffer->sizereg = FXBS;
-		buffer->addrreg = FXBA;
-		buffer->idxreg = FXIDX_IDX;
-		buffer->adcctl = 0;
-
-		sblive_writeptr(card, FXWC, 0, wiinst->fxwc);
-		break;
-	default:
-		BUG();
-		break;
-	}
-
-	DPD(2, "bus addx: %#lx\n", (unsigned long) buffer->dma_handle);
-
-	sblive_writeptr(card, buffer->addrreg, 0, (u32)buffer->dma_handle);
-}
diff --git a/sound/oss/emu10k1/recmgr.h b/sound/oss/emu10k1/recmgr.h
deleted file mode 100644
index a68766a..0000000
--- a/sound/oss/emu10k1/recmgr.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*     
- **********************************************************************
- *     recmgr.h
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */
-
-#ifndef _RECORDMGR_H
-#define _RECORDMGR_H
-
-#include "hwaccess.h"
-#include "cardwi.h"
-
-/* Recording resources */
-#define WAVERECORD_AC97		0x01
-#define WAVERECORD_MIC		0x02
-#define WAVERECORD_FX		0x03
-
-void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer);
-void emu10k1_start_record(struct emu10k1_card *, struct wavein_buffer *);
-void emu10k1_stop_record(struct emu10k1_card *, struct wavein_buffer *);
-void emu10k1_set_record_src(struct emu10k1_card *, struct wiinst *wiinst);
-
-#endif /* _RECORDMGR_H */
diff --git a/sound/oss/emu10k1/timer.c b/sound/oss/emu10k1/timer.c
deleted file mode 100644
index d10d307..0000000
--- a/sound/oss/emu10k1/timer.c
+++ /dev/null
@@ -1,176 +0,0 @@
-
-/*
- **********************************************************************
- *     timer.c
- *     Copyright (C) 1999, 2000 Creative Labs, inc.
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-/* 3/6/2000	Improved support for different timer delays  Rui Sousa */
-
-/* 4/3/2000	Implemented timer list using list.h 	     Rui Sousa */
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "irqmgr.h"
-#include "timer.h"
-
-/* Try to schedule only once per fragment */
-
-void emu10k1_timer_irqhandler(struct emu10k1_card *card)
-{
-	struct emu_timer *t;
-	struct list_head *entry;
-
-	spin_lock(&card->timer_lock);
-
-	list_for_each(entry, &card->timers) {
-		t = list_entry(entry, struct emu_timer, list);
-
-		if (t->state & TIMER_STATE_ACTIVE) {
-			t->count++;
-			if (t->count == t->count_max) {
-				t->count = 0;
-				tasklet_hi_schedule(&t->tasklet);
-			}
-		}
-	}
-
-	spin_unlock(&card->timer_lock);
-
-	return;
-}
-
-void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u16 delay)
-{
-	struct emu_timer *t;
-	struct list_head *entry;
-	unsigned long flags;
-
-	if (delay < 5)
-		delay = 5;
-
-	timer->delay = delay;
-	timer->state = TIMER_STATE_INSTALLED;
-
-	spin_lock_irqsave(&card->timer_lock, flags);
-
-	timer->count_max = timer->delay / (card->timer_delay < 1024 ? card->timer_delay : 1024);
-	timer->count = timer->count_max - 1;
-
-	list_add(&timer->list, &card->timers);
-
-	if (card->timer_delay > delay) {
-		if (card->timer_delay == TIMER_STOPPED)
-			emu10k1_irq_enable(card, INTE_INTERVALTIMERENB);
-
-		card->timer_delay = delay;
-		delay = (delay < 1024 ? delay : 1024);
-
-		emu10k1_timer_set(card, delay);
-
-		list_for_each(entry, &card->timers) {
-			t = list_entry(entry, struct emu_timer, list);
-
-			t->count_max = t->delay / delay;
-			/* don't want to think much, just force scheduling 
-			   on the next interrupt */
-			t->count = t->count_max - 1;
-		}
-
-		DPD(2, "timer rate --> %u\n", delay);
-	}
-
-	spin_unlock_irqrestore(&card->timer_lock, flags);
-
-	return;
-}
-
-void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
-{
-	struct emu_timer *t;
-	struct list_head *entry;
-	u16 delay = TIMER_STOPPED;
-	unsigned long flags;
-
-	if (timer->state == TIMER_STATE_UNINSTALLED)
-		return;
-
-	spin_lock_irqsave(&card->timer_lock, flags);
-
-	list_del(&timer->list);
-
-	list_for_each(entry, &card->timers) {
-		t = list_entry(entry, struct emu_timer, list);
-
-		if (t->delay < delay)
-			delay = t->delay;
-	}
-
-	if (card->timer_delay != delay) {
-		card->timer_delay = delay;
-
-		if (delay == TIMER_STOPPED)
-			emu10k1_irq_disable(card, INTE_INTERVALTIMERENB);
-		else {
-			delay = (delay < 1024 ? delay : 1024);
-
-			emu10k1_timer_set(card, delay);
-
-			list_for_each(entry, &card->timers) {
-				t = list_entry(entry, struct emu_timer, list);
-
-				t->count_max = t->delay / delay;
-				t->count = t->count_max - 1;
-			}
-		}
-
-		DPD(2, "timer rate --> %u\n", delay);
-	}
-
-	spin_unlock_irqrestore(&card->timer_lock, flags);
-
-	timer->state = TIMER_STATE_UNINSTALLED;
-
-	return;
-}
-
-void emu10k1_timer_enable(struct emu10k1_card *card, struct emu_timer *timer)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->timer_lock, flags);
-	timer->state |= TIMER_STATE_ACTIVE;
-	spin_unlock_irqrestore(&card->timer_lock, flags);
-
-	return;
-}
-
-void emu10k1_timer_disable(struct emu10k1_card *card, struct emu_timer *timer)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->timer_lock, flags);
-	timer->state &= ~TIMER_STATE_ACTIVE;
-	spin_unlock_irqrestore(&card->timer_lock, flags);
-
-	return;
-}
diff --git a/sound/oss/emu10k1/timer.h b/sound/oss/emu10k1/timer.h
deleted file mode 100644
index b2543b4..0000000
--- a/sound/oss/emu10k1/timer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- **********************************************************************
- *     timer.h
- *     Copyright (C) 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-
-#ifndef _TIMER_H
-#define _TIMER_H
-
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include "hwaccess.h"
-
-struct emu_timer 
-{
-	struct list_head list;
-	struct tasklet_struct tasklet;
-	u8 state; 
-	u16 count;				/* current number of interrupts */
-	u16 count_max;				/* number of interrupts needed to schedule the bh */
-	u16 delay;                              /* timer delay */
-};
-
-void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u16);
-void emu10k1_timer_uninstall(struct emu10k1_card *, struct emu_timer *);
-void emu10k1_timer_enable(struct emu10k1_card *, struct emu_timer *);
-void emu10k1_timer_disable(struct emu10k1_card *, struct emu_timer *);
-
-#define TIMER_STOPPED 			0xffff 
-#define TIMER_STATE_INSTALLED 		0x01
-#define TIMER_STATE_ACTIVE		0x02
-#define TIMER_STATE_UNINSTALLED 	0x04
-
-#endif /* _TIMER_H */
diff --git a/sound/oss/emu10k1/voicemgr.c b/sound/oss/emu10k1/voicemgr.c
deleted file mode 100644
index d88b602..0000000
--- a/sound/oss/emu10k1/voicemgr.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- **********************************************************************
- *     voicemgr.c - Voice manager for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include "voicemgr.h"
-#include "8010.h"
-
-#define PITCH_48000 0x00004000
-#define PITCH_96000 0x00008000
-#define PITCH_85000 0x00007155
-#define PITCH_80726 0x00006ba2
-#define PITCH_67882 0x00005a82
-#define PITCH_57081 0x00004c1c
-
-static u32 emu10k1_select_interprom(struct emu10k1_card *card,
-				    struct emu_voice *voice)
-{
-	if(voice->pitch_target==PITCH_48000)
-		return CCCA_INTERPROM_0;
-	else if(voice->pitch_target<PITCH_48000)
-		return CCCA_INTERPROM_1;
-	else  if(voice->pitch_target>=PITCH_96000)
-		return CCCA_INTERPROM_0;
-	else  if(voice->pitch_target>=PITCH_85000)
-		return CCCA_INTERPROM_6;
-	else  if(voice->pitch_target>=PITCH_80726)
-		return CCCA_INTERPROM_5;
-	else  if(voice->pitch_target>=PITCH_67882)
-		return CCCA_INTERPROM_4;
-	else  if(voice->pitch_target>=PITCH_57081)
-		return CCCA_INTERPROM_3;
-	else  
-		return CCCA_INTERPROM_2;
-}
-
-
-/**
- * emu10k1_voice_alloc_buffer -
- *
- * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
- * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
- * is passed to the device so that it can do DMA to host memory.
- *
- */
-int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages)
-{
-	u32 pageindex, pagecount;
-	u32 busaddx;
-	int i;
-
-	DPD(2, "requested pages is: %d\n", pages);
-
-	if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0)
-	{
-		DPF(1, "couldn't allocate emu10k1 address space\n");
-		return -1;
-	}
-
-	/* Fill in virtual memory table */
-	for (pagecount = 0; pagecount < pages; pagecount++) {
-		if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount]))
-			== NULL) {
-			mem->pages = pagecount;
-			DPF(1, "couldn't allocate dma memory\n");
-			return -1;
-		}
-
-		DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]);
-
-		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-			busaddx = (u32) mem->dma_handle[pagecount] + i * EMUPAGESIZE;
-
-			DPD(3, "Bus Addx: %#x\n", busaddx);
-
-			pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-
-			((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
-		}
-	}
-
-	mem->pages = pagecount;
-
-	return 0;
-}
-
-/**
- * emu10k1_voice_free_buffer -
- *
- * frees the memory buffer for a voice.
- */
-void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem)
-{
-	u32 pagecount, pageindex;
-	int i;
-
-	if (mem->emupageindex < 0)
-		return;
-
-	for (pagecount = 0; pagecount < mem->pages; pagecount++) {
-		pci_free_consistent(card->pci_dev, PAGE_SIZE,
-					mem->addr[pagecount],
-					mem->dma_handle[pagecount]);
-
-		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-			pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-			((u32 *) card->virtualpagetable.addr)[pageindex] =
-				cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pageindex);
-		}
-	}
-
-	emu10k1_addxmgr_free(card, mem->emupageindex);
-	mem->emupageindex = -1;
-}
-
-int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
-{
-	u8 *voicetable = card->voicetable;
-	int i;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_voice_alloc()\n");
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	if (voice->flags & VOICE_FLAGS_STEREO) {
-		for (i = 0; i < NUM_G; i += 2)
-			if ((voicetable[i] == VOICE_USAGE_FREE) && (voicetable[i + 1] == VOICE_USAGE_FREE)) {
-				voicetable[i] = voice->usage;
-				voicetable[i + 1] = voice->usage;
-				break;
-			}
-	} else {
-		for (i = 0; i < NUM_G; i++)
-			if (voicetable[i] == VOICE_USAGE_FREE) {
-				voicetable[i] = voice->usage;
-				break;
-			}
-	}
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	if (i >= NUM_G)
-		return -1;
-
-	voice->card = card;
-	voice->num = i;
-
-	for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
-		DPD(2, " voice allocated -> %d\n", voice->num + i);
-
-		sblive_writeptr_tag(card, voice->num + i, IFATN, 0xffff,
-							DCYSUSV, 0,
-							VTFT, 0x0000ffff,
-							PTRX, 0,
-							TAGLIST_END);
-	}
-
-	return 0;
-}
-
-void emu10k1_voice_free(struct emu_voice *voice)
-{
-	struct emu10k1_card *card = voice->card;
-	int i;
-	unsigned long flags;
-
-	DPF(2, "emu10k1_voice_free()\n");
-
-	if (voice->usage == VOICE_USAGE_FREE)
-		return;
-
-	for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
-		DPD(2, " voice released -> %d\n", voice->num + i);
-
-		sblive_writeptr_tag(card, voice->num + i, DCYSUSV, 0, 
-							VTFT, 0x0000ffff,
-							PTRX_PITCHTARGET, 0,
-							CVCF, 0x0000ffff,
-							//CPF, 0,
-							TAGLIST_END);
-		
-		sblive_writeptr(card, CPF, voice->num + i, 0);
-	}
-
-	voice->usage = VOICE_USAGE_FREE;
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	card->voicetable[voice->num] = VOICE_USAGE_FREE;
-
-	if (voice->flags & VOICE_FLAGS_STEREO)
-		card->voicetable[voice->num + 1] = VOICE_USAGE_FREE;
-
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-void emu10k1_voice_playback_setup(struct emu_voice *voice)
-{
-	struct emu10k1_card *card = voice->card;
-	u32 start;
-	int i;
-
-	DPF(2, "emu10k1_voice_playback_setup()\n");
-
-	if (voice->flags & VOICE_FLAGS_STEREO) {
-		/* Set stereo bit */
-		start = 28;
-		sblive_writeptr(card, CPF, voice->num, CPF_STEREO_MASK);
-		sblive_writeptr(card, CPF, voice->num + 1, CPF_STEREO_MASK);
-	} else {
-		start = 30;
-		sblive_writeptr(card, CPF, voice->num, 0);
-	}
-
-	if(!(voice->flags & VOICE_FLAGS_16BIT))
-		start *= 2;
-
-	voice->start += start;
-
-	for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
-		if (card->is_audigy) {
-			sblive_writeptr(card, A_FXRT1, voice->num + i, voice->params[i].send_routing);
-			sblive_writeptr(card, A_FXRT2, voice->num + i, voice->params[i].send_routing2);
-			sblive_writeptr(card,  A_SENDAMOUNTS, voice->num + i, voice->params[i].send_hgfe);
-		} else {
-			sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16);
-		}
-
-		/* Stop CA */
-		/* Assumption that PT is already 0 so no harm overwriting */
-		sblive_writeptr(card, PTRX, voice->num + i, ((voice->params[i].send_dcba & 0xff) << 8)
-				| ((voice->params[i].send_dcba & 0xff00) >> 8));
-
-		sblive_writeptr_tag(card, voice->num + i,
-				/* CSL, ST, CA */
-				    DSL, voice->endloop | (voice->params[i].send_dcba & 0xff000000),
-				    PSST, voice->startloop | ((voice->params[i].send_dcba & 0x00ff0000) << 8),
-				    CCCA, (voice->start) |  emu10k1_select_interprom(card,voice) |
-				        ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT),
-				    /* Clear filter delay memory */
-				    Z1, 0,
-				    Z2, 0,
-				    /* Invalidate maps */
-				    MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
-				    MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
-				/* modulation envelope */
-				    CVCF, 0x0000ffff,
-				    VTFT, 0x0000ffff,
-				    ATKHLDM, 0,
-				    DCYSUSM, 0x007f,
-				    LFOVAL1, 0x8000,
-				    LFOVAL2, 0x8000,
-				    FMMOD, 0,
-				    TREMFRQ, 0,
-				    FM2FRQ2, 0,
-				    ENVVAL, 0x8000,
-				/* volume envelope */
-				    ATKHLDV, 0x7f7f,
-				    ENVVOL, 0x8000,
-				/* filter envelope */
-				    PEFE_FILTERAMOUNT, 0x7f,
-				/* pitch envelope */
-				    PEFE_PITCHAMOUNT, 0, TAGLIST_END);
-
-		voice->params[i].fc_target = 0xffff;
-	}
-}
-
-void emu10k1_voices_start(struct emu_voice *first_voice, unsigned int num_voices, int set)
-{
-	struct emu10k1_card *card = first_voice->card;
-	struct emu_voice *voice;
-	unsigned int voicenum;
-	int j;
-
-	DPF(2, "emu10k1_voices_start()\n");
-
-	for (voicenum = 0; voicenum < num_voices; voicenum++)
-	{
-		voice = first_voice + voicenum;
-
-		if (!set) {
-			u32 cra, ccis, cs, sample;
-			if (voice->flags & VOICE_FLAGS_STEREO) {
-				cra = 64;
-				ccis = 28;
-				cs = 4;
-			} else {
-				cra = 64;
-				ccis = 30;
-				cs = 2;
-			}
-
-			if(voice->flags & VOICE_FLAGS_16BIT) {
-				sample = 0x00000000;
-			} else {
-				sample = 0x80808080;		
-				ccis *= 2;
-			}
-
-			for(j = 0; j < cs; j++)
-	        	        sblive_writeptr(card, CD0 + j, voice->num, sample);
-
-			/* Reset cache */
-			sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, 0);
-			if (voice->flags & VOICE_FLAGS_STEREO)
-				sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num + 1, 0);
-
-			sblive_writeptr(card, CCR_READADDRESS, voice->num, cra);
-
-			if (voice->flags & VOICE_FLAGS_STEREO)
-				sblive_writeptr(card, CCR_READADDRESS, voice->num + 1, cra);
-
-			/* Fill cache */
-			sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, ccis);
-		}
-
-		for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
-			sblive_writeptr_tag(card, voice->num + j,
-				    IFATN, (voice->params[j].initial_fc << 8) | voice->params[j].initial_attn,
-				    VTFT, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
-				    CVCF, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
-				    DCYSUSV, (voice->params[j].byampl_env_sustain << 8) | voice->params[j].byampl_env_decay,
-				    TAGLIST_END);
-	
-			emu10k1_clear_stop_on_loop(card, voice->num + j);
-		}
-	}
-
-
-        for (voicenum = 0; voicenum < num_voices; voicenum++)
-	{
-		voice = first_voice + voicenum;
-
-		for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
-			sblive_writeptr(card, PTRX_PITCHTARGET, voice->num + j, voice->pitch_target);
-
-			if (j == 0)
-				sblive_writeptr(card, CPF_CURRENTPITCH, voice->num, voice->pitch_target);
-
-			sblive_writeptr(card, IP, voice->num + j, voice->initial_pitch);
-		}
-	}
-}
-
-void emu10k1_voices_stop(struct emu_voice *first_voice, int num_voices)
-{
-	struct emu10k1_card *card = first_voice->card;
-	struct emu_voice *voice;
-	unsigned int voice_num;
-	int j;
-
-	DPF(2, "emu10k1_voice_stop()\n");
-
-        for (voice_num = 0; voice_num < num_voices; voice_num++)
-	{
-		voice = first_voice + voice_num;
-
-		for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
-			sblive_writeptr_tag(card, voice->num + j,
-						PTRX_PITCHTARGET, 0,
-						CPF_CURRENTPITCH, 0,
-						IFATN, 0xffff,
-						VTFT, 0x0000ffff,
-						CVCF, 0x0000ffff,
-						IP, 0,
-						TAGLIST_END);
-		}
-	}
-}
-
diff --git a/sound/oss/emu10k1/voicemgr.h b/sound/oss/emu10k1/voicemgr.h
deleted file mode 100644
index 099a8cb..0000000
--- a/sound/oss/emu10k1/voicemgr.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- **********************************************************************
- *     sblive_voice.h -- EMU Voice Resource Manager header file
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#ifndef _VOICEMGR_H
-#define _VOICEMGR_H
-
-#include "hwaccess.h"
-
-/* struct emu_voice.usage flags */
-#define VOICE_USAGE_FREE		0x01
-#define VOICE_USAGE_MIDI		0x02
-#define VOICE_USAGE_PLAYBACK		0x04
-
-/* struct emu_voice.flags flags */
-#define VOICE_FLAGS_STEREO		0x02
-#define VOICE_FLAGS_16BIT		0x04
-
-struct voice_param
-{
-	/* FX bus amount send */
-
-	u32 send_routing;
-	// audigy only:
-	u32 send_routing2;
-
-	u32 send_dcba;
-	// audigy only:
-	u32 send_hgfe;
-
-
-	u32 initial_fc;
-	u32 fc_target;
-
-	u32 initial_attn;
-	u32 volume_target;
-
-	u32 byampl_env_sustain;
-	u32 byampl_env_decay;
-};
-
-struct voice_mem {
-	int emupageindex;
-	void *addr[BUFMAXPAGES];
-	dma_addr_t dma_handle[BUFMAXPAGES];
-	u32 pages;
-};
-
-struct emu_voice
-{
-	struct emu10k1_card *card;
-	u8 usage;		/* Free, MIDI, playback */
-	u8 num;			/* Voice ID */
-	u8 flags;		/* Stereo/mono, 8/16 bit */
-
-	u32 startloop;
-	u32 endloop;
-	u32 start;
-
-	u32 initial_pitch;
-	u32 pitch_target;
-
-	struct voice_param params[2];
-
-	struct voice_mem mem;
-};
-
-int emu10k1_voice_alloc_buffer(struct emu10k1_card *, struct voice_mem *, u32);
-void emu10k1_voice_free_buffer(struct emu10k1_card *, struct voice_mem *);
-int emu10k1_voice_alloc(struct emu10k1_card *, struct emu_voice *);
-void emu10k1_voice_free(struct emu_voice *);
-void emu10k1_voice_playback_setup(struct emu_voice *);
-void emu10k1_voices_start(struct emu_voice *, unsigned int, int);
-void emu10k1_voices_stop(struct emu_voice *, int);
-
-#endif /* _VOICEMGR_H */
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index 593a3aa..5264857 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -2894,7 +2894,7 @@
 	s->irq = pcidev->irq;
 	s->vendor = pcidev->vendor;
 	s->device = pcidev->device;
-	pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+	s->rev = pcidev->revision;
 	s->codec->private_data = s;
 	s->codec->id = 0;
 	s->codec->codec_read = rdcodec;
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index 2796c0e..a690ca5 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -1003,7 +1003,8 @@
 		}
 		if (!devc->shared_irq)
 		{
-			if (request_irq(devc->irq, mpuintr, 0, "mpu401", (void *)m) < 0)
+			if (request_irq(devc->irq, mpuintr, 0, "mpu401",
+					hw_config) < 0)
 			{
 				printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq);
 				ret = -ENOMEM;
@@ -1112,7 +1113,7 @@
 	return 0;
 
 out_irq:
-	free_irq(devc->irq, (void *)m);
+	free_irq(devc->irq, hw_config);
 out_mididev:
 	sound_unload_mididev(m);
 out_err:
@@ -1227,7 +1228,7 @@
 	if (n != -1) {
 		release_region(hw_config->io_base, 2);
 		if (hw_config->always_detect == 0 && hw_config->irq > 0)
-			free_irq(hw_config->irq, (void *)n);
+			free_irq(hw_config->irq, hw_config);
 		p=mpu401_synth_operations[n];
 		sound_unload_mididev(n);
 		sound_unload_timerdev(hw_config->slots[2]);
diff --git a/sound/oss/nm256.h b/sound/oss/nm256.h
deleted file mode 100644
index 1dade90..0000000
--- a/sound/oss/nm256.h
+++ /dev/null
@@ -1,292 +0,0 @@
-#ifndef _NM256_H_
-#define _NM256_H_
-
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-
-#include "ac97.h"
-
-/* The revisions that we currently handle.  */
-enum nm256rev {
-    REV_NM256AV, REV_NM256ZX
-};
-
-/* Per-card structure. */
-struct nm256_info 
-{
-    /* Magic number used to verify that this struct is valid. */
-#define NM_MAGIC_SIG 0x55aa00ff
-    int magsig;
-
-    /* Revision number */
-    enum nm256rev rev;
-
-    struct ac97_hwint mdev;
-
-    /* Our audio device numbers. */
-    int dev[2];
-
-    /* The # of times each device has been opened. (Should only be 
-       0 or 1). */
-    int opencnt[2];
-
-    /* We use two devices, because we can do simultaneous play and record.
-       This keeps track of which device is being used for what purpose;
-       these are the actual device numbers. */
-    int dev_for_play;
-    int dev_for_record;
-
-	spinlock_t lock;
-	
-    /* The mixer device. */
-    int mixer_oss_dev;
-
-    /* 
-     * Can only be opened once for each operation.  These aren't set
-     * until an actual I/O operation is performed; this allows one
-     * device to be open for read/write without inhibiting I/O to
-     * the other device.
-     */
-    int is_open_play;
-    int is_open_record;
-
-    /* Non-zero if we're currently playing a sample. */
-    int playing;
-    /* Ditto for recording a sample. */
-    int recording;
-
-    /* The two memory ports.  */
-    struct nm256_ports {
-	/* Physical address of the port. */
-	u32 physaddr;
-	/* Our mapped-in pointer. */
-	char __iomem *ptr;
-	/* PTR's offset within the physical port.  */
-	u32 start_offset;
-	/* And the offset of the end of the buffer.  */
-	u32 end_offset;
-    } port[2];
-
-    /* The following are offsets within memory port 1. */
-    u32 coeffBuf;
-    u32 allCoeffBuf;
-
-    /* Record and playback buffers. */
-    u32 abuf1, abuf2;
-
-    /* Offset of the AC97 mixer in memory port 2. */
-    u32 mixer;
-
-    /* Offset of the mixer status register in memory port 2.  */
-    u32 mixer_status_offset;
-
-    /* Non-zero if we have written initial values to the mixer. */
-    u8 mixer_values_init;
-
-    /* 
-     * Status mask bit; (*mixer_status_loc & mixer_status_mask) == 0 means
-     * it's ready.  
-     */
-    u16 mixer_status_mask;
-
-    /* The sizes of the playback and record ring buffers. */
-    u32 playbackBufferSize;
-    u32 recordBufferSize;
-
-    /* Are the coefficient values in the memory cache current? */
-    u8 coeffsCurrent;
-
-    /* For writes, the amount we last wrote. */
-    u32 requested_amt;
-    /* The start of the block currently playing. */
-    u32 curPlayPos;
-
-    /* The amount of data we were requested to record. */
-    u32 requestedRecAmt;
-    /* The offset of the currently-recording block. */
-    u32 curRecPos;
-    /* The destination buffer. */
-    char *recBuf;
-
-    /* Our IRQ number. */
-    int irq;
-
-    /* A flag indicating how many times we've grabbed the IRQ. */
-    int has_irq;
-
-    /* The card interrupt service routine. */
-    irq_handler_t introutine;
-
-    /* Current audio config, cached. */
-    struct sinfo {
-	u32 samplerate;
-	u8 bits;
-	u8 stereo;
-    } sinfo[2]; /* goes with each device */
-
-    /* The cards are stored in a chain;  this is the next card. */
-    struct nm256_info *next_card;
-};
-
-/* The BIOS signature. */
-#define NM_SIGNATURE 0x4e4d0000
-/* Signature mask. */
-#define NM_SIG_MASK 0xffff0000
-
-/* Size of the second memory area. */
-#define NM_PORT2_SIZE 4096
-
-/* The base offset of the mixer in the second memory area. */
-#define NM_MIXER_OFFSET 0x600
-
-/* The maximum size of a coefficient entry. */
-#define NM_MAX_COEFFICIENT 0x5000
-
-/* The interrupt register. */
-#define NM_INT_REG 0xa04
-/* And its bits. */
-#define NM_PLAYBACK_INT 0x40
-#define NM_RECORD_INT 0x100
-#define NM_MISC_INT_1 0x4000
-#define NM_MISC_INT_2 0x1
-#define NM_ACK_INT(CARD, X) nm256_writePort16((CARD), 2, NM_INT_REG, (X) << 1)
-
-/* The AV's "mixer ready" status bit and location. */
-#define NM_MIXER_STATUS_OFFSET 0xa04
-#define NM_MIXER_READY_MASK 0x0800
-#define NM_MIXER_PRESENCE 0xa06
-#define NM_PRESENCE_MASK 0x0050
-#define NM_PRESENCE_VALUE 0x0040
-
-/*
- * For the ZX.  It uses the same interrupt register, but it holds 32
- * bits instead of 16.
- */
-#define NM2_PLAYBACK_INT 0x10000
-#define NM2_RECORD_INT 0x80000
-#define NM2_MISC_INT_1 0x8
-#define NM2_MISC_INT_2 0x2
-#define NM2_ACK_INT(CARD, X) nm256_writePort32((CARD), 2, NM_INT_REG, (X))
-
-/* The ZX's "mixer ready" status bit and location. */
-#define NM2_MIXER_STATUS_OFFSET 0xa06
-#define NM2_MIXER_READY_MASK 0x0800
-
-/* The playback registers start from here. */
-#define NM_PLAYBACK_REG_OFFSET 0x0
-/* The record registers start from here. */
-#define NM_RECORD_REG_OFFSET 0x200
-
-/* The rate register is located 2 bytes from the start of the register area. */
-#define NM_RATE_REG_OFFSET 2
-
-/* Mono/stereo flag, number of bits on playback, and rate mask. */
-#define NM_RATE_STEREO 1
-#define NM_RATE_BITS_16 2
-#define NM_RATE_MASK 0xf0
-
-/* Playback enable register. */
-#define NM_PLAYBACK_ENABLE_REG (NM_PLAYBACK_REG_OFFSET + 0x1)
-#define NM_PLAYBACK_ENABLE_FLAG 1
-#define NM_PLAYBACK_ONESHOT 2
-#define NM_PLAYBACK_FREERUN 4
-
-/* Mutes the audio output. */
-#define NM_AUDIO_MUTE_REG (NM_PLAYBACK_REG_OFFSET + 0x18)
-#define NM_AUDIO_MUTE_LEFT 0x8000
-#define NM_AUDIO_MUTE_RIGHT 0x0080
-
-/* Recording enable register. */
-#define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0)
-#define NM_RECORD_ENABLE_FLAG 1
-#define NM_RECORD_FREERUN 2
-
-#define NM_RBUFFER_START (NM_RECORD_REG_OFFSET + 0x4)
-#define NM_RBUFFER_END   (NM_RECORD_REG_OFFSET + 0x10)
-#define NM_RBUFFER_WMARK (NM_RECORD_REG_OFFSET + 0xc)
-#define NM_RBUFFER_CURRP (NM_RECORD_REG_OFFSET + 0x8)
-
-#define NM_PBUFFER_START (NM_PLAYBACK_REG_OFFSET + 0x4)
-#define NM_PBUFFER_END   (NM_PLAYBACK_REG_OFFSET + 0x14)
-#define NM_PBUFFER_WMARK (NM_PLAYBACK_REG_OFFSET + 0xc)
-#define NM_PBUFFER_CURRP (NM_PLAYBACK_REG_OFFSET + 0x8)
-
-/* A few trivial routines to make it easier to work with the registers
-   on the chip. */
-
-/* This is a common code portion used to fix up the port offsets. */
-#define NM_FIX_PORT \
-  if (port < 1 || port > 2 || card == NULL) \
-      return -1; \
-\
-    if (offset < card->port[port - 1].start_offset \
-	|| offset >= card->port[port - 1].end_offset) { \
-	printk (KERN_ERR "Bad access: port %d, offset 0x%x\n", port, offset); \
-	return -1; \
-    } \
-    offset -= card->port[port - 1].start_offset;
-
-#define DEFwritePortX(X, func) \
-static inline int nm256_writePort##X (struct nm256_info *card,\
-				      int port, int offset, int value)\
-{\
-    u##X __iomem *addr;\
-\
-    if (nm256_debug > 1)\
-        printk (KERN_DEBUG "Writing 0x%x to %d:0x%x\n", value, port, offset);\
-\
-    NM_FIX_PORT;\
-\
-    addr = (u##X __iomem *)(card->port[port - 1].ptr + offset);\
-    func (value, addr);\
-    return 0;\
-}
-
-DEFwritePortX (8, writeb)
-DEFwritePortX (16, writew)
-DEFwritePortX (32, writel)
-
-#define DEFreadPortX(X, func) \
-static inline u##X nm256_readPort##X (struct nm256_info *card,\
-					int port, int offset)\
-{\
-    u##X __iomem *addr;\
-\
-    NM_FIX_PORT\
-\
-    addr = (u##X __iomem *)(card->port[port - 1].ptr + offset);\
-    return func(addr);\
-}
-
-DEFreadPortX (8, readb)
-DEFreadPortX (16, readw)
-DEFreadPortX (32, readl)
-
-static inline int
-nm256_writeBuffer8 (struct nm256_info *card, u8 *src, int port, int offset,
-		      int amt)
-{
-    NM_FIX_PORT;
-    memcpy_toio (card->port[port - 1].ptr + offset, src, amt);
-    return 0;
-}
-
-static inline int
-nm256_readBuffer8 (struct nm256_info *card, u8 *dst, int port, int offset,
-		     int amt)
-{
-    NM_FIX_PORT;
-    memcpy_fromio (dst, card->port[port - 1].ptr + offset, amt);
-    return 0;
-}
-
-/* Returns a non-zero value if we should use the coefficient cache. */
-static int nm256_cachedCoefficients (struct nm256_info *card);
-
-#endif
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
deleted file mode 100644
index 44cd155..0000000
--- a/sound/oss/nm256_audio.c
+++ /dev/null
@@ -1,1662 +0,0 @@
-/* 
- * Audio driver for the NeoMagic 256AV and 256ZX chipsets in native
- * mode, with AC97 mixer support.
- *
- * Overall design and parts of this code stolen from vidc_*.c and
- * skeleton.c.
- *
- * Yeah, there are a lot of magic constants in here.  You tell ME what
- * they are.  I just get this stuff psychically, remember? 
- *
- * This driver was written by someone who wishes to remain anonymous. 
- * It is in the public domain, so share and enjoy.  Try to make a profit
- * off of it; go on, I dare you.  
- *
- * Changes:
- * 11-10-2000	Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
- *		Added some __init
- * 19-04-2001	Marcus Meissner <mm@caldera.de>
- *		Ported to 2.4 PCI API.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include "sound_config.h"
-
-static int nm256_debug;
-static int force_load;
-
-#include "nm256.h"
-#include "nm256_coeff.h"
-
-/* 
- * The size of the playback reserve.  When the playback buffer has less
- * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new
- * buffer.
- */
-#define NM256_PLAY_WMARK_SIZE 512
-
-static struct audio_driver nm256_audio_driver;
-
-static int nm256_grabInterrupt (struct nm256_info *card);
-static int nm256_releaseInterrupt (struct nm256_info *card);
-static irqreturn_t nm256_interrupt (int irq, void *dev_id);
-static irqreturn_t nm256_interrupt_zx (int irq, void *dev_id);
-
-/* These belong in linux/pci.h. */
-#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
-#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
-#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
-
-/* List of cards.  */
-static struct nm256_info *nmcard_list;
-
-/* Release the mapped-in memory for CARD.  */
-static void
-nm256_release_ports (struct nm256_info *card)
-{
-    int x;
-
-    for (x = 0; x < 2; x++) {
-	if (card->port[x].ptr != NULL) {
-	    iounmap (card->port[x].ptr);
-	    card->port[x].ptr = NULL;
-	}
-    }
-}
-
-/* 
- * Map in the memory ports for CARD, if they aren't already mapped in
- * and have been configured.  If successful, a zero value is returned;
- * otherwise any previously mapped-in areas are released and a non-zero
- * value is returned.
- *
- * This is invoked twice, once for each port.  Ideally it would only be
- * called once, but we now need to map in the second port in order to
- * check how much memory the card has on the 256ZX.
- */
-static int
-nm256_remap_ports (struct nm256_info *card)
-{
-    int x;
-
-    for (x = 0; x < 2; x++) {
-	if (card->port[x].ptr == NULL && card->port[x].end_offset > 0) {
-	    u32 physaddr 
-		= card->port[x].physaddr + card->port[x].start_offset;
-	    u32 size 
-		= card->port[x].end_offset - card->port[x].start_offset;
-
-	    card->port[x].ptr = ioremap_nocache (physaddr, size);
-						  
-	    if (card->port[x].ptr == NULL) {
-		printk (KERN_ERR "NM256: Unable to remap port %d\n", x + 1);
-		nm256_release_ports (card);
-		return -1;
-	    }
-	}
-    }
-    return 0;
-}
-
-/* Locate the card in our list. */
-static struct nm256_info *
-nm256_find_card (int dev)
-{
-    struct nm256_info *card;
-
-    for (card = nmcard_list; card != NULL; card = card->next_card)
-	if (card->dev[0] == dev || card->dev[1] == dev)
-	    return card;
-
-    return NULL;
-}
-
-/*
- * Ditto, but find the card struct corresponding to the mixer device DEV 
- * instead. 
- */
-static struct nm256_info *
-nm256_find_card_for_mixer (int dev)
-{
-    struct nm256_info *card;
-
-    for (card = nmcard_list; card != NULL; card = card->next_card)
-	if (card->mixer_oss_dev == dev)
-	    return card;
-
-    return NULL;
-}
-
-static int usecache;
-static int buffertop;
-
-/* Check to see if we're using the bank of cached coefficients. */
-static int
-nm256_cachedCoefficients (struct nm256_info *card)
-{
-    return usecache;
-}
-
-/* The actual rates supported by the card. */
-static int samplerates[9] = {
-    8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999
-};
-
-/*
- * Set the card samplerate, word size and stereo mode to correspond to
- * the settings in the CARD struct for the specified device in DEV.
- * We keep two separate sets of information, one for each device; the
- * hardware is not actually configured until a read or write is
- * attempted.
- */
-
-static int
-nm256_setInfo (int dev, struct nm256_info *card)
-{
-    int x;
-    int w;
-    int targetrate;
-
-    if (card->dev[0] == dev)
-	w = 0;
-    else if (card->dev[1] == dev)
-	w = 1;
-    else
-	return -ENODEV;
-
-    targetrate = card->sinfo[w].samplerate;
-
-    if ((card->sinfo[w].bits != 8 && card->sinfo[w].bits != 16)
-	|| targetrate < samplerates[0]
-	|| targetrate > samplerates[7])
-	return -EINVAL;
-
-    for (x = 0; x < 8; x++)
-	if (targetrate < ((samplerates[x] + samplerates[x + 1]) / 2))
-	    break;
-
-    if (x < 8) {
-	u8 ratebits = ((x << 4) & NM_RATE_MASK);
-	if (card->sinfo[w].bits == 16)
-	    ratebits |= NM_RATE_BITS_16;
-	if (card->sinfo[w].stereo)
-	    ratebits |= NM_RATE_STEREO;
-
-	card->sinfo[w].samplerate = samplerates[x];
-
-
-	if (card->dev_for_play == dev && card->playing) {
-	    if (nm256_debug)
-		printk (KERN_DEBUG "Setting play ratebits to 0x%x\n",
-			ratebits);
-	    nm256_loadCoefficient (card, 0, x);
-	    nm256_writePort8 (card, 2,
-			      NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET,
-			      ratebits);
-	}
-
-	if (card->dev_for_record == dev && card->recording) {
-	    if (nm256_debug)
-		printk (KERN_DEBUG "Setting record ratebits to 0x%x\n",
-			ratebits);
-	    nm256_loadCoefficient (card, 1, x);
-	    nm256_writePort8 (card, 2,
-			      NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET,
-			      ratebits);
-	}
-	return 0;
-    }
-    else
-	return -EINVAL;
-}
-
-/* Start the play process going. */
-static void
-startPlay (struct nm256_info *card)
-{
-    if (! card->playing) {
-	card->playing = 1;
-	if (nm256_grabInterrupt (card) == 0) {
-	    nm256_setInfo (card->dev_for_play, card);
-
-	    /* Enable playback engine and interrupts. */
-	    nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG,
-			      NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN);
-
-	    /* Enable both channels. */
-	    nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG, 0x0);
-	}
-    }
-}
-
-/* 
- * Request one chunk of AMT bytes from the recording device.  When the
- * operation is complete, the data will be copied into BUFFER and the
- * function DMAbuf_inputintr will be invoked.
- */
-
-static void
-nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
-{
-    u32 endpos;
-    int enableEngine = 0;
-    u32 ringsize = card->recordBufferSize;
-    unsigned long flags;
-
-    if (amt > (ringsize / 2)) {
-	/*
-	 * Of course this won't actually work right, because the
-	 * caller is going to assume we will give what we got asked
-	 * for.
-	 */
-	printk (KERN_ERR "NM256: Read request too large: %d\n", amt);
-	amt = ringsize / 2;
-    }
-
-    if (amt < 8) {
-	printk (KERN_ERR "NM256: Read request too small; %d\n", amt);
-	return;
-    }
-
-    spin_lock_irqsave(&card->lock,flags);
-    /*
-     * If we're not currently recording, set up the start and end registers
-     * for the recording engine.
-     */
-    if (! card->recording) {
-	card->recording = 1;
-	if (nm256_grabInterrupt (card) == 0) {
-	    card->curRecPos = 0;
-	    nm256_setInfo (card->dev_for_record, card);
-	    nm256_writePort32 (card, 2, NM_RBUFFER_START, card->abuf2);
-	    nm256_writePort32 (card, 2, NM_RBUFFER_END,
-				 card->abuf2 + ringsize);
-
-	    nm256_writePort32 (card, 2, NM_RBUFFER_CURRP,
-				 card->abuf2 + card->curRecPos);
-	    enableEngine = 1;
-	}
-	else {
-	    /* Not sure what else to do here.  */
-	    spin_unlock_irqrestore(&card->lock,flags);
-	    return;
-	}
-    }
-
-    /* 
-     * If we happen to go past the end of the buffer a bit (due to a
-     * delayed interrupt) it's OK.  So might as well set the watermark
-     * right at the end of the data we want.
-     */
-    endpos = card->abuf2 + ((card->curRecPos + amt) % ringsize);
-
-    card->recBuf = buffer;
-    card->requestedRecAmt = amt;
-    nm256_writePort32 (card, 2, NM_RBUFFER_WMARK, endpos);
-    /* Enable recording engine and interrupts. */
-    if (enableEngine)
-	nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG,
-			    NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN);
-
-    spin_unlock_irqrestore(&card->lock,flags);
-}
-
-/* Stop the play engine. */
-static void
-stopPlay (struct nm256_info *card)
-{
-    /* Shut off sound from both channels. */
-    nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG,
-		       NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT);
-    /* Disable play engine. */
-    nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG, 0);
-    if (card->playing) {
-	nm256_releaseInterrupt (card);
-
-	/* Reset the relevant state bits. */
-	card->playing = 0;
-	card->curPlayPos = 0;
-    }
-}
-
-/* Stop recording. */
-static void
-stopRecord (struct nm256_info *card)
-{
-    /* Disable recording engine. */
-    nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG, 0);
-
-    if (card->recording) {
-	nm256_releaseInterrupt (card);
-
-	card->recording = 0;
-	card->curRecPos = 0;
-    }
-}
-
-/*
- * Ring buffers, man.  That's where the hip-hop, wild-n-wooly action's at.
- * 1972?  (Well, I suppose it was cheep-n-easy to implement.)
- *
- * Write AMT bytes of BUFFER to the playback ring buffer, and start the
- * playback engine running.  It will only accept up to 1/2 of the total
- * size of the ring buffer.  No check is made that we're about to overwrite
- * the currently-playing sample.
- */
-
-static void
-nm256_write_block (struct nm256_info *card, char *buffer, u32 amt)
-{
-    u32 ringsize = card->playbackBufferSize;
-    u32 endstop;
-    unsigned long flags;
-
-    if (amt > (ringsize / 2)) {
-	printk (KERN_ERR "NM256: Write request too large: %d\n", amt);
-	amt = (ringsize / 2);
-    }
-
-    if (amt < NM256_PLAY_WMARK_SIZE) {
-	printk (KERN_ERR "NM256: Write request too small: %d\n", amt);
-	return;
-    }
-
-    card->curPlayPos %= ringsize;
-
-    card->requested_amt = amt;
-
-    spin_lock_irqsave(&card->lock,flags);
-
-    if ((card->curPlayPos + amt) >= ringsize) {
-	u32 rem = ringsize - card->curPlayPos;
-
-	nm256_writeBuffer8 (card, buffer, 1,
-			      card->abuf1 + card->curPlayPos,
-			      rem);
-	if (amt > rem)
-	    nm256_writeBuffer8 (card, buffer + rem, 1, card->abuf1,
-				  amt - rem);
-    } 
-    else
-	nm256_writeBuffer8 (card, buffer, 1,
-			      card->abuf1 + card->curPlayPos,
-			      amt);
-
-    /*
-     * Setup the start-n-stop-n-limit registers, and start that engine
-     * goin'. 
-     *
-     * Normally we just let it wrap around to avoid the click-click
-     * action scene.
-     */
-    if (! card->playing) {
-	/* The PBUFFER_END register in this case points to one sample
-	   before the end of the buffer. */
-	int w = (card->dev_for_play == card->dev[0] ? 0 : 1);
-	int sampsize = (card->sinfo[w].bits == 16 ? 2 : 1);
-
-	if (card->sinfo[w].stereo)
-	    sampsize *= 2;
-
-	/* Need to set the not-normally-changing-registers up. */
-	nm256_writePort32 (card, 2, NM_PBUFFER_START,
-			     card->abuf1 + card->curPlayPos);
-	nm256_writePort32 (card, 2, NM_PBUFFER_END,
-			     card->abuf1 + ringsize - sampsize);
-	nm256_writePort32 (card, 2, NM_PBUFFER_CURRP,
-			     card->abuf1 + card->curPlayPos);
-    }
-    endstop = (card->curPlayPos + amt - NM256_PLAY_WMARK_SIZE) % ringsize;
-    nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
-
-    if (! card->playing)
-	startPlay (card);
-
-    spin_unlock_irqrestore(&card->lock,flags);
-}
-
-/*  We just got a card playback interrupt; process it.  */
-static void
-nm256_get_new_block (struct nm256_info *card)
-{
-    /* Check to see how much got played so far. */
-    u32 amt = nm256_readPort32 (card, 2, NM_PBUFFER_CURRP) - card->abuf1;
-
-    if (amt >= card->playbackBufferSize) {
-	printk (KERN_ERR "NM256: Sound playback pointer invalid!\n");
-	amt = 0;
-    }
-
-    if (amt < card->curPlayPos)
-	amt = (card->playbackBufferSize - card->curPlayPos) + amt;
-    else
-	amt -= card->curPlayPos;
-
-    if (card->requested_amt > (amt + NM256_PLAY_WMARK_SIZE)) {
-	u32 endstop =
-	    card->curPlayPos + card->requested_amt - NM256_PLAY_WMARK_SIZE;
-	nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
-    } 
-    else {
-	card->curPlayPos += card->requested_amt;
-	/* Get a new block to write.  This will eventually invoke
-	   nm256_write_block () or stopPlay ().  */
-	DMAbuf_outputintr (card->dev_for_play, 1);
-    }
-}
-
-/* 
- * Read the last-recorded block from the ring buffer, copy it into the
- * saved buffer pointer, and invoke DMAuf_inputintr() with the recording
- * device. 
- */
-
-static void
-nm256_read_block (struct nm256_info *card)
-{
-    /* Grab the current position of the recording pointer. */
-    u32 currptr = nm256_readPort32 (card, 2, NM_RBUFFER_CURRP) - card->abuf2;
-    u32 amtToRead = card->requestedRecAmt;
-    u32 ringsize = card->recordBufferSize;
-
-    if (currptr >= card->recordBufferSize) {
-	printk (KERN_ERR "NM256: Sound buffer record pointer invalid!\n");
-        currptr = 0;
-    }
-
-    /*
-     * This test is probably redundant; we shouldn't be here unless
-     * it's true.
-     */
-    if (card->recording) {
-	/* If we wrapped around, copy everything from the start of our
-	   recording buffer to the end of the buffer. */
-	if (currptr < card->curRecPos) {
-	    u32 amt = min (ringsize - card->curRecPos, amtToRead);
-
-	    nm256_readBuffer8 (card, card->recBuf, 1,
-				 card->abuf2 + card->curRecPos,
-				 amt);
-	    amtToRead -= amt;
-	    card->curRecPos += amt;
-	    card->recBuf += amt;
-	    if (card->curRecPos == ringsize)
-		card->curRecPos = 0;
-	}
-
-	if ((card->curRecPos < currptr) && (amtToRead > 0)) {
-	    u32 amt = min (currptr - card->curRecPos, amtToRead);
-	    nm256_readBuffer8 (card, card->recBuf, 1,
-				 card->abuf2 + card->curRecPos, amt);
-	    card->curRecPos = ((card->curRecPos + amt) % ringsize);
-	}
-	card->recBuf = NULL;
-	card->requestedRecAmt = 0;
-	DMAbuf_inputintr (card->dev_for_record);
-    }
-}
-
-/*
- * Initialize the hardware. 
- */
-static void
-nm256_initHw (struct nm256_info *card)
-{
-    /* Reset everything. */
-    nm256_writePort8 (card, 2, 0x0, 0x11);
-    nm256_writePort16 (card, 2, 0x214, 0);
-
-    stopRecord (card);
-    stopPlay (card);
-}
-
-/* 
- * Handle a potential interrupt for the device referred to by DEV_ID. 
- *
- * I don't like the cut-n-paste job here either between the two routines,
- * but there are sufficient differences between the two interrupt handlers
- * that parameterizing it isn't all that great either.  (Could use a macro,
- * I suppose...yucky bleah.)
- */
-
-static irqreturn_t
-nm256_interrupt (int irq, void *dev_id)
-{
-    struct nm256_info *card = (struct nm256_info *)dev_id;
-    u16 status;
-    static int badintrcount;
-    int handled = 0;
-
-    if ((card == NULL) || (card->magsig != NM_MAGIC_SIG)) {
-	printk (KERN_ERR "NM256: Bad card pointer\n");
-	return IRQ_NONE;
-    }
-
-    status = nm256_readPort16 (card, 2, NM_INT_REG);
-
-    /* Not ours. */
-    if (status == 0) {
-	if (badintrcount++ > 1000) {
-	    /*
-	     * I'm not sure if the best thing is to stop the card from
-	     * playing or just release the interrupt (after all, we're in
-	     * a bad situation, so doing fancy stuff may not be such a good
-	     * idea).
-	     *
-	     * I worry about the card engine continuing to play noise
-	     * over and over, however--that could become a very
-	     * obnoxious problem.  And we know that when this usually
-	     * happens things are fairly safe, it just means the user's
-	     * inserted a PCMCIA card and someone's spamming us with IRQ 9s.
-	     */
-
-	    handled = 1;
-	    if (card->playing)
-		stopPlay (card);
-	    if (card->recording)
-		stopRecord (card);
-	    badintrcount = 0;
-	}
-	return IRQ_RETVAL(handled);
-    }
-
-    badintrcount = 0;
-
-    /* Rather boring; check for individual interrupts and process them. */
-
-    if (status & NM_PLAYBACK_INT) {
-	handled = 1;
-	status &= ~NM_PLAYBACK_INT;
-	NM_ACK_INT (card, NM_PLAYBACK_INT);
-
-	if (card->playing)
-	    nm256_get_new_block (card);
-    }
-
-    if (status & NM_RECORD_INT) {
-	handled = 1;
-	status &= ~NM_RECORD_INT;
-	NM_ACK_INT (card, NM_RECORD_INT);
-
-	if (card->recording)
-	    nm256_read_block (card);
-    }
-
-    if (status & NM_MISC_INT_1) {
-	u8 cbyte;
-
-	handled = 1;
-	status &= ~NM_MISC_INT_1;
-	printk (KERN_ERR "NM256: Got misc interrupt #1\n");
-	NM_ACK_INT (card, NM_MISC_INT_1);
-	nm256_writePort16 (card, 2, NM_INT_REG, 0x8000);
-	cbyte = nm256_readPort8 (card, 2, 0x400);
-	nm256_writePort8 (card, 2, 0x400, cbyte | 2);
-    }
-
-    if (status & NM_MISC_INT_2) {
-	u8 cbyte;
-
-	handled = 1;
-	status &= ~NM_MISC_INT_2;
-	printk (KERN_ERR "NM256: Got misc interrupt #2\n");
-	NM_ACK_INT (card, NM_MISC_INT_2);
-	cbyte = nm256_readPort8 (card, 2, 0x400);
-	nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
-    }
-
-    /* Unknown interrupt. */
-    if (status) {
-	handled = 1;
-	printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
-		status);
-	/* Pray. */
-	NM_ACK_INT (card, status);
-    }
-    return IRQ_RETVAL(handled);
-}
-
-/*
- * Handle a potential interrupt for the device referred to by DEV_ID.
- * This handler is for the 256ZX, and is very similar to the non-ZX
- * routine.
- */
-
-static irqreturn_t
-nm256_interrupt_zx (int irq, void *dev_id)
-{
-    struct nm256_info *card = (struct nm256_info *)dev_id;
-    u32 status;
-    static int badintrcount;
-    int handled = 0;
-
-    if ((card == NULL) || (card->magsig != NM_MAGIC_SIG)) {
-	printk (KERN_ERR "NM256: Bad card pointer\n");
-	return IRQ_NONE;
-    }
-
-    status = nm256_readPort32 (card, 2, NM_INT_REG);
-
-    /* Not ours. */
-    if (status == 0) {
-	if (badintrcount++ > 1000) {
-	    printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n");
-	    /*
-	     * I'm not sure if the best thing is to stop the card from
-	     * playing or just release the interrupt (after all, we're in
-	     * a bad situation, so doing fancy stuff may not be such a good
-	     * idea).
-	     *
-	     * I worry about the card engine continuing to play noise
-	     * over and over, however--that could become a very
-	     * obnoxious problem.  And we know that when this usually
-	     * happens things are fairly safe, it just means the user's
-	     * inserted a PCMCIA card and someone's spamming us with 
-	     * IRQ 9s.
-	     */
-
-	    handled = 1;
-	    if (card->playing)
-		stopPlay (card);
-	    if (card->recording)
-		stopRecord (card);
-	    badintrcount = 0;
-	}
-	return IRQ_RETVAL(handled);
-    }
-
-    badintrcount = 0;
-
-    /* Rather boring; check for individual interrupts and process them. */
-
-    if (status & NM2_PLAYBACK_INT) {
-	handled = 1;
-	status &= ~NM2_PLAYBACK_INT;
-	NM2_ACK_INT (card, NM2_PLAYBACK_INT);
-
-	if (card->playing)
-	    nm256_get_new_block (card);
-    }
-
-    if (status & NM2_RECORD_INT) {
-	handled = 1;
-	status &= ~NM2_RECORD_INT;
-	NM2_ACK_INT (card, NM2_RECORD_INT);
-
-	if (card->recording)
-	    nm256_read_block (card);
-    }
-
-    if (status & NM2_MISC_INT_1) {
-	u8 cbyte;
-
-	handled = 1;
-	status &= ~NM2_MISC_INT_1;
-	printk (KERN_ERR "NM256: Got misc interrupt #1\n");
-	NM2_ACK_INT (card, NM2_MISC_INT_1);
-	cbyte = nm256_readPort8 (card, 2, 0x400);
-	nm256_writePort8 (card, 2, 0x400, cbyte | 2);
-    }
-
-    if (status & NM2_MISC_INT_2) {
-	u8 cbyte;
-
-	handled = 1;
-	status &= ~NM2_MISC_INT_2;
-	printk (KERN_ERR "NM256: Got misc interrupt #2\n");
-	NM2_ACK_INT (card, NM2_MISC_INT_2);
-	cbyte = nm256_readPort8 (card, 2, 0x400);
-	nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
-    }
-
-    /* Unknown interrupt. */
-    if (status) {
-	handled = 1;
-	printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
-		status);
-	/* Pray. */
-	NM2_ACK_INT (card, status);
-    }
-    return IRQ_RETVAL(handled);
-}
-
-/* 
- * Request our interrupt.
- */
-static int
-nm256_grabInterrupt (struct nm256_info *card)
-{
-    if (card->has_irq++ == 0) {
-	if (request_irq (card->irq, card->introutine, IRQF_SHARED,
-			 "NM256_audio", card) < 0) {
-	    printk (KERN_ERR "NM256: can't obtain IRQ %d\n", card->irq);
-	    return -1;
-	}
-    }
-    return 0;
-}
-
-/* 
- * Release our interrupt. 
- */
-static int
-nm256_releaseInterrupt (struct nm256_info *card)
-{
-    if (card->has_irq <= 0) {
-	printk (KERN_ERR "nm256: too many calls to releaseInterrupt\n");
-	return -1;
-    }
-    card->has_irq--;
-    if (card->has_irq == 0) {
-	free_irq (card->irq, card);
-    }
-    return 0;
-}
-
-/*
- * Waits for the mixer to become ready to be written; returns a zero value
- * if it timed out.
- */
-
-static int
-nm256_isReady (struct ac97_hwint *dev)
-{
-    struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-    int t2 = 10;
-    u32 testaddr;
-    u16 testb;
-    int done = 0;
-
-    if (card->magsig != NM_MAGIC_SIG) {
-	printk (KERN_ERR "NM256: Bad magic signature in isReady!\n");
-	return 0;
-    }
-
-    testaddr = card->mixer_status_offset;
-    testb = card->mixer_status_mask;
-
-    /* 
-     * Loop around waiting for the mixer to become ready. 
-     */
-    while (! done && t2-- > 0) {
-	if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0)
-	    done = 1;
-	else
-	    udelay (100);
-    }
-    return done;
-}
-
-/*
- * Return the contents of the AC97 mixer register REG.  Returns a positive
- * value if successful, or a negative error code.
- */
-static int
-nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg)
-{
-    struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-
-    if (card->magsig != NM_MAGIC_SIG) {
-	printk (KERN_ERR "NM256: Bad magic signature in readAC97Reg!\n");
-	return -EINVAL;
-    }
-
-    if (reg < 128) {
-	int res;
-
-	nm256_isReady (dev);
-	res = nm256_readPort16 (card, 2, card->mixer + reg);
-	/* Magic delay.  Bleah yucky.  */
-        udelay (1000);
-	return res;
-    }
-    else
-	return -EINVAL;
-}
-
-/* 
- * Writes VALUE to AC97 mixer register REG.  Returns 0 if successful, or
- * a negative error code. 
- */
-static int
-nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value)
-{
-    unsigned long flags;
-    int tries = 2;
-    int done = 0;
-    u32 base;
-
-    struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-
-    if (card->magsig != NM_MAGIC_SIG) {
-	printk (KERN_ERR "NM256: Bad magic signature in writeAC97Reg!\n");
-	return -EINVAL;
-    }
-
-    base = card->mixer;
-
-    spin_lock_irqsave(&card->lock,flags);
-
-    nm256_isReady (dev);
-
-    /* Wait for the write to take, too. */
-    while ((tries-- > 0) && !done) {
-	nm256_writePort16 (card, 2, base + reg, value);
-	if (nm256_isReady (dev)) {
-	    done = 1;
-	    break;
-	}
-
-    }
-
-    spin_unlock_irqrestore(&card->lock,flags);
-    udelay (1000);
-
-    return ! done;
-}
-
-/* 
- * Initial register values to be written to the AC97 mixer.
- * While most of these are identical to the reset values, we do this
- * so that we have most of the register contents cached--this avoids
- * reading from the mixer directly (which seems to be problematic,
- * probably due to ignorance).
- */
-struct initialValues 
-{
-    unsigned short port;
-    unsigned short value;
-};
-
-static struct initialValues nm256_ac97_initial_values[] = 
-{
-    { AC97_MASTER_VOL_STEREO, 0x8000 },
-    { AC97_HEADPHONE_VOL,     0x8000 },
-    { AC97_MASTER_VOL_MONO,   0x0000 },
-    { AC97_PCBEEP_VOL,        0x0000 },
-    { AC97_PHONE_VOL,         0x0008 },
-    { AC97_MIC_VOL,           0x8000 },
-    { AC97_LINEIN_VOL,        0x8808 },
-    { AC97_CD_VOL,            0x8808 },
-    { AC97_VIDEO_VOL,         0x8808 },
-    { AC97_AUX_VOL,           0x8808 },
-    { AC97_PCMOUT_VOL,        0x0808 },
-    { AC97_RECORD_SELECT,     0x0000 },
-    { AC97_RECORD_GAIN,       0x0B0B },
-    { AC97_GENERAL_PURPOSE,   0x0000 },
-    { 0xffff, 0xffff }
-};
-
-/* Initialize the AC97 into a known state.  */
-static int
-nm256_resetAC97 (struct ac97_hwint *dev)
-{
-    struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-    int x;
-
-    if (card->magsig != NM_MAGIC_SIG) {
-	printk (KERN_ERR "NM256: Bad magic signature in resetAC97!\n");
-	return -EINVAL;
-    }
-
-    /* Reset the mixer.  'Tis magic!  */
-    nm256_writePort8 (card, 2, 0x6c0, 1);
-//  nm256_writePort8 (card, 2, 0x6cc, 0x87);	/* This crashes Dell latitudes */
-    nm256_writePort8 (card, 2, 0x6cc, 0x80);
-    nm256_writePort8 (card, 2, 0x6cc, 0x0);
-
-    if (! card->mixer_values_init) {
-	for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) {
-	    ac97_put_register (dev,
-			       nm256_ac97_initial_values[x].port,
-			       nm256_ac97_initial_values[x].value);
-	    card->mixer_values_init = 1;
-	}
-    }
-
-    return 0;
-}
-
-/*
- * We don't do anything particularly special here; it just passes the
- * mixer ioctl to the AC97 driver.
- */
-static int
-nm256_default_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
-{
-    struct nm256_info *card = nm256_find_card_for_mixer (dev);
-    if (card != NULL)
-	return ac97_mixer_ioctl (&(card->mdev), cmd, arg);
-    else
-	return -ENODEV;
-}
-
-static struct mixer_operations nm256_mixer_operations = {
-	.owner	= THIS_MODULE,
-	.id	= "NeoMagic",
-	.name	= "NM256AC97Mixer",
-	.ioctl	= nm256_default_mixer_ioctl
-};
-
-/*
- * Default settings for the OSS mixer.  These are set last, after the
- * mixer is initialized.
- *
- * I "love" C sometimes.  Got braces?
- */
-static struct ac97_mixer_value_list mixer_defaults[] = {
-    { SOUND_MIXER_VOLUME,  { { 85, 85 } } },
-    { SOUND_MIXER_SPEAKER, { { 100 } } },
-    { SOUND_MIXER_PCM,     { { 65, 65 } } },
-    { SOUND_MIXER_CD,      { { 65, 65 } } },
-    { -1,                  {  { 0,  0 } } }
-};
-
-
-/* Installs the AC97 mixer into CARD.  */
-static int __devinit
-nm256_install_mixer (struct nm256_info *card)
-{
-    int mixer;
-
-    card->mdev.reset_device = nm256_resetAC97;
-    card->mdev.read_reg = nm256_readAC97Reg;
-    card->mdev.write_reg = nm256_writeAC97Reg;
-    card->mdev.driver_private = (void *)card;
-
-    if (ac97_init (&(card->mdev)))
-	return -1;
-
-    mixer = sound_alloc_mixerdev();
-    if (num_mixers >= MAX_MIXER_DEV) {
-	printk ("NM256 mixer: Unable to alloc mixerdev\n");
-	return -1;
-    }
-
-    mixer_devs[mixer] = &nm256_mixer_operations;
-    card->mixer_oss_dev = mixer;
-
-    /* Some reasonable default values.  */
-    ac97_set_values (&(card->mdev), mixer_defaults);
-
-    printk(KERN_INFO "Initialized AC97 mixer\n");
-    return 0;
-}
-
-/* 
- * See if the signature left by the NM256 BIOS is intact; if so, we use
- * the associated address as the end of our audio buffer in the video
- * RAM.
- */
-
-static void __devinit
-nm256_peek_for_sig (struct nm256_info *card)
-{
-    u32 port1offset 
-	= card->port[0].physaddr + card->port[0].end_offset - 0x0400;
-    /* The signature is located 1K below the end of video RAM.  */
-    char __iomem *temp = ioremap_nocache (port1offset, 16);
-    /* Default buffer end is 5120 bytes below the top of RAM.  */
-    u32 default_value = card->port[0].end_offset - 0x1400;
-    u32 sig;
-
-    /* Install the default value first, so we don't have to repeatedly
-       do it if there is a problem.  */
-    card->port[0].end_offset = default_value;
-
-    if (temp == NULL) {
-	printk (KERN_ERR "NM256: Unable to scan for card signature in video RAM\n");
-	return;
-    }
-    sig = readl (temp);
-    if ((sig & NM_SIG_MASK) == NM_SIGNATURE) {
-	u32 pointer = readl (temp + 4);
-
-	/*
-	 * If it's obviously invalid, don't use it (the port already has a
-	 * suitable default value set).
-	 */
-	if (pointer != 0xffffffff)
-	    card->port[0].end_offset = pointer;
-
-	printk (KERN_INFO "NM256: Found card signature in video RAM: 0x%x\n",
-		pointer);
-    }
-
-    iounmap (temp);
-}
-
-/* 
- * Install a driver for the PCI device referenced by PCIDEV.
- * VERSTR is a human-readable version string.
- */
-
-static int __devinit
-nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
-{
-    struct nm256_info *card;
-    int x;
-
-    if (pci_enable_device(pcidev))
-	    return 0;
-
-    card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL);
-    if (card == NULL) {
-	printk (KERN_ERR "NM256: out of memory!\n");
-	return 0;
-    }
-
-    card->magsig = NM_MAGIC_SIG;
-    card->playing  = 0;
-    card->recording = 0;
-    card->rev = rev;
-    spin_lock_init(&card->lock);
-
-    /* Init the memory port info.  */
-    for (x = 0; x < 2; x++) {
-	card->port[x].physaddr = pci_resource_start (pcidev, x);
-	card->port[x].ptr = NULL;
-	card->port[x].start_offset = 0;
-	card->port[x].end_offset = 0;
-    }
-
-    /* Port 2 is easy.  */
-    card->port[1].start_offset = 0;
-    card->port[1].end_offset = NM_PORT2_SIZE;
-
-    /* Yuck.  But we have to map in port 2 so we can check how much RAM the
-       card has.  */
-    if (nm256_remap_ports (card)) {
-	kfree (card);
-	return 0;
-    }
-
-    /* 
-     * The NM256 has two memory ports.  The first port is nothing
-     * more than a chunk of video RAM, which is used as the I/O ring
-     * buffer.  The second port has the actual juicy stuff (like the
-     * mixer and the playback engine control registers).
-     */
-
-    if (card->rev == REV_NM256AV) {
-	/* Ok, try to see if this is a non-AC97 version of the hardware. */
-	int pval = nm256_readPort16 (card, 2, NM_MIXER_PRESENCE);
-	if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
-	    if (! force_load) {
-		printk (KERN_ERR "NM256: This doesn't look to me like the AC97-compatible version.\n");
-		printk (KERN_ERR "       You can force the driver to load by passing in the module\n");
-		printk (KERN_ERR "       parameter:\n");
-		printk (KERN_ERR "              force_load = 1\n");
-		printk (KERN_ERR "\n");
-		printk (KERN_ERR "       More likely, you should be using the appropriate SB-16 or\n");
-		printk (KERN_ERR "       CS4232 driver instead.  (If your BIOS has settings for\n");
-		printk (KERN_ERR "       IRQ and/or DMA for the sound card, this is *not* the correct\n");
-		printk (KERN_ERR "       driver to use.)\n");
-		nm256_release_ports (card);
-		kfree (card);
-		return 0;
-	    }
-	    else {
-		printk (KERN_INFO "NM256: Forcing driver load as per user request.\n");
-	    }
-	}
-	else {
-	 /*   printk (KERN_INFO "NM256: Congratulations. You're not running Eunice.\n")*/;
-	}
-	card->port[0].end_offset = 2560 * 1024;
-	card->introutine = nm256_interrupt;
-	card->mixer_status_offset = NM_MIXER_STATUS_OFFSET;
-	card->mixer_status_mask = NM_MIXER_READY_MASK;
-    } 
-    else {
-	/* Not sure if there is any relevant detect for the ZX or not.  */
-	if (nm256_readPort8 (card, 2, 0xa0b) != 0)
-	    card->port[0].end_offset = 6144 * 1024;
-	else
-	    card->port[0].end_offset = 4096 * 1024;
-
-	card->introutine = nm256_interrupt_zx;
-	card->mixer_status_offset = NM2_MIXER_STATUS_OFFSET;
-	card->mixer_status_mask = NM2_MIXER_READY_MASK;
-    }
-
-    if (buffertop >= 98304 && buffertop < card->port[0].end_offset)
-	card->port[0].end_offset = buffertop;
-    else
-	nm256_peek_for_sig (card);
-
-    card->port[0].start_offset = card->port[0].end_offset - 98304;
-
-    printk (KERN_INFO "NM256: Mapping port 1 from 0x%x - 0x%x\n",
-	    card->port[0].start_offset, card->port[0].end_offset);
-
-    if (nm256_remap_ports (card)) {
-	kfree (card);
-	return 0;
-    }
-
-    /* See if we can get the interrupt. */
-
-    card->irq = pcidev->irq;
-    card->has_irq = 0;
-
-    if (nm256_grabInterrupt (card) != 0) {
-	nm256_release_ports (card);
-	kfree (card);
-	return 0;
-    }
-
-    nm256_releaseInterrupt (card);
-
-    /*
-     *	Init the board.
-     */
-
-    card->playbackBufferSize = 16384;
-    card->recordBufferSize = 16384;
-
-    card->coeffBuf = card->port[0].end_offset - NM_MAX_COEFFICIENT;
-    card->abuf2 = card->coeffBuf - card->recordBufferSize;
-    card->abuf1 = card->abuf2 - card->playbackBufferSize;
-    card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4);
-
-    /* Fixed setting. */
-    card->mixer = NM_MIXER_OFFSET;
-    card->mixer_values_init = 0;
-
-    card->is_open_play = 0;
-    card->is_open_record = 0;
-
-    card->coeffsCurrent = 0;
-
-    card->opencnt[0] = 0; card->opencnt[1] = 0;
-
-    /* Reasonable default settings, but largely unnecessary. */
-    for (x = 0; x < 2; x++) {
-	card->sinfo[x].bits = 8;
-	card->sinfo[x].stereo = 0;
-	card->sinfo[x].samplerate = 8000;
-    }
-
-    nm256_initHw (card);
-
-    for (x = 0; x < 2; x++) {
-	if ((card->dev[x] =
-	     sound_install_audiodrv(AUDIO_DRIVER_VERSION,
-				    "NM256", &nm256_audio_driver,
-				    sizeof(struct audio_driver),
-				    DMA_NODMA, AFMT_U8 | AFMT_S16_LE,
-				    NULL, -1, -1)) >= 0) {
-	    /* 1K minimum buffer size. */
-	    audio_devs[card->dev[x]]->min_fragment = 10;
-	    /* Maximum of 8K buffer size. */
-	    audio_devs[card->dev[x]]->max_fragment = 13;
-	}
-	else {
-	    printk(KERN_ERR "NM256: Too many PCM devices available\n");
-	    nm256_release_ports (card);
-	    kfree (card);
-	    return 0;
-	}
-    }
-
-    pci_set_drvdata(pcidev,card);
-
-    /* Insert the card in the list.  */
-    card->next_card = nmcard_list;
-    nmcard_list = card;
-
-    printk(KERN_INFO "Initialized NeoMagic %s audio in PCI native mode\n",
-	   verstr);
-
-    /* 
-     * And our mixer.  (We should allow support for other mixers, maybe.)
-     */
-
-    nm256_install_mixer (card);
-
-    return 1;
-}
-
-
-static int __devinit
-nm256_probe(struct pci_dev *pcidev,const struct pci_device_id *pciid)
-{
-    if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO)
-	return nm256_install(pcidev, REV_NM256AV, "256AV");
-    if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO)
-	return nm256_install(pcidev, REV_NM256ZX, "256ZX");
-    if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO)
-	return nm256_install(pcidev, REV_NM256ZX, "256XL+");
-    return -1; /* should not come here ... */
-}
-
-static void __devinit
-nm256_remove(struct pci_dev *pcidev) {
-    struct nm256_info *xcard = pci_get_drvdata(pcidev);
-    struct nm256_info *card,*next_card = NULL;
-
-    for (card = nmcard_list; card != NULL; card = next_card) {
-	next_card = card->next_card;
-	if (card == xcard) {
-	    stopPlay (card);
-	    stopRecord (card);
-	    if (card->has_irq)
-		free_irq (card->irq, card);
-	    nm256_release_ports (card);
-	    sound_unload_mixerdev (card->mixer_oss_dev);
-	    sound_unload_audiodev (card->dev[0]);
-	    sound_unload_audiodev (card->dev[1]);
-	    kfree (card);
-	    break;
-	}
-    }
-    if (nmcard_list == card)
-    	nmcard_list = next_card;
-}
-
-/*
- * Open the device
- *
- * DEV  - device
- * MODE - mode to open device (logical OR of OPEN_READ and OPEN_WRITE)
- *
- * Called when opening the DMAbuf               (dmabuf.c:259)
- */
-static int
-nm256_audio_open(int dev, int mode)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-    int w;
-	
-    if (card == NULL)
-	return -ENODEV;
-
-    if (card->dev[0] == dev)
-	w = 0;
-    else if (card->dev[1] == dev)
-	w = 1;
-    else
-	return -ENODEV;
-
-    if (card->opencnt[w] > 0)
-	return -EBUSY;
-
-    /* No bits set? Huh? */
-    if (! ((mode & OPEN_READ) || (mode & OPEN_WRITE)))
-	return -EIO;
-
-    /*
-     * If it's open for both read and write, and the card's currently
-     * being read or written to, then do the opposite of what has
-     * already been done.  Otherwise, don't specify any mode until the
-     * user actually tries to do I/O.  (Some programs open the device
-     * for both read and write, but only actually do reading or writing.)
-     */
-
-    if ((mode & OPEN_WRITE) && (mode & OPEN_READ)) {
-	if (card->is_open_play)
-	    mode = OPEN_WRITE;
-	else if (card->is_open_record)
-	    mode = OPEN_READ;
-	else mode = 0;
-    }
-	
-    if (mode & OPEN_WRITE) {
-	if (card->is_open_play == 0) {
-	    card->dev_for_play = dev;
-	    card->is_open_play = 1;
-	}
-	else
-	    return -EBUSY;
-    }
-
-    if (mode & OPEN_READ) {
-	if (card->is_open_record == 0) {
-	    card->dev_for_record = dev;
-	    card->is_open_record = 1;
-	}
-	else
-	    return -EBUSY;
-    }
-
-    card->opencnt[w]++;
-    return 0;
-}
-
-/*
- * Close the device
- *
- * DEV  - device
- *
- * Called when closing the DMAbuf               (dmabuf.c:477)
- *      after halt_xfer
- */
-static void
-nm256_audio_close(int dev)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-	
-    if (card != NULL) {
-	int w;
-
-	if (card->dev[0] == dev)
-	    w = 0;
-	else if (card->dev[1] == dev)
-	    w = 1;
-	else
-	    return;
-
-	card->opencnt[w]--;
-	if (card->opencnt[w] <= 0) {
-	    card->opencnt[w] = 0;
-
-	    if (card->dev_for_play == dev) {
-		stopPlay (card);
-		card->is_open_play = 0;
-		card->dev_for_play = -1;
-	    }
-
-	    if (card->dev_for_record == dev) {
-		stopRecord (card);
-		card->is_open_record = 0;
-		card->dev_for_record = -1;
-	    }
-	}
-    }
-}
-
-/* Standard ioctl handler. */
-static int
-nm256_audio_ioctl(int dev, unsigned int cmd, void __user *arg)
-{
-    int ret;
-    u32 oldinfo;
-    int w;
-
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card == NULL)
-	return -ENODEV;
-
-    if (dev == card->dev[0])
-	w = 0;
-    else
-	w = 1;
-
-    /* 
-     * The code here is messy.  There are probably better ways to do
-     * it.  (It should be possible to handle it the same way the AC97 mixer 
-     * is done.)
-     */
-    switch (cmd)
-	{
-	case SOUND_PCM_WRITE_RATE:
-	    if (get_user(ret, (int __user *) arg))
-		return -EFAULT;
-
-	    if (ret != 0) {
-		oldinfo = card->sinfo[w].samplerate;
-		card->sinfo[w].samplerate = ret;
-		ret = nm256_setInfo(dev, card);
-		if (ret != 0)
-		    card->sinfo[w].samplerate = oldinfo;
-	    }
-	    if (ret == 0)
-		ret = card->sinfo[w].samplerate;
-	    break;
-
-	case SOUND_PCM_READ_RATE:
-	    ret = card->sinfo[w].samplerate;
-	    break;
-
-	case SNDCTL_DSP_STEREO:
-	    if (get_user(ret, (int __user *) arg))
-		return -EFAULT;
-
-	    card->sinfo[w].stereo = ret ? 1 : 0;
-	    ret = nm256_setInfo (dev, card);
-	    if (ret == 0)
-		ret = card->sinfo[w].stereo;
-
-	    break;
-
-	case SOUND_PCM_WRITE_CHANNELS:
-	    if (get_user(ret, (int __user *) arg))
-		return -EFAULT;
-
-	    if (ret < 1 || ret > 3)
-		ret = card->sinfo[w].stereo + 1;
-	    else {
-		card->sinfo[w].stereo = ret - 1;
-		ret = nm256_setInfo (dev, card);
-		if (ret == 0)
-		    ret = card->sinfo[w].stereo + 1;
-	    }
-	    break;
-
-	case SOUND_PCM_READ_CHANNELS:
-	    ret = card->sinfo[w].stereo + 1;
-	    break;
-
-	case SNDCTL_DSP_SETFMT:
-	    if (get_user(ret, (int __user *) arg))
-		return -EFAULT;
-
-	    if (ret != 0) {
-		oldinfo = card->sinfo[w].bits;
-		card->sinfo[w].bits = ret;
-		ret = nm256_setInfo (dev, card);
-		if (ret != 0)
-		    card->sinfo[w].bits = oldinfo;
-	    }
-	    if (ret == 0)
-		ret = card->sinfo[w].bits;
-	    break;
-
-	case SOUND_PCM_READ_BITS:
-	    ret = card->sinfo[w].bits;
-	    break;
-
-	default:
-	    return -EINVAL;
-	}
-    return put_user(ret, (int __user *) arg);
-}
-
-/*
- * Given the sound device DEV and an associated physical buffer PHYSBUF, 
- * return a pointer to the actual buffer in kernel space. 
- *
- * This routine should exist as part of the soundcore routines.
- */
-
-static char *
-nm256_getDMAbuffer (int dev, unsigned long physbuf)
-{
-    struct audio_operations *adev = audio_devs[dev];
-    struct dma_buffparms *dmap = adev->dmap_out;
-    char *dma_start =
-	(char *)(physbuf - (unsigned long)dmap->raw_buf_phys 
-		 + (unsigned long)dmap->raw_buf);
-
-    return dma_start;
-}
-
-
-/*
- * Output a block to sound device
- *
- * dev          - device number
- * buf          - physical address of buffer
- * total_count  - total byte count in buffer
- * intrflag     - set if this has been called from an interrupt 
- *				  (via DMAbuf_outputintr)
- * restart_dma  - set if engine needs to be re-initialised
- *
- * Called when:
- *  1. Starting output                                  (dmabuf.c:1327)
- *  2.                                                  (dmabuf.c:1504)
- *  3. A new buffer needs to be sent to the device      (dmabuf.c:1579)
- */
-static void
-nm256_audio_output_block(int dev, unsigned long physbuf,
-				       int total_count, int intrflag)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card != NULL) {
-	char *dma_buf = nm256_getDMAbuffer (dev, physbuf);
-	card->is_open_play = 1;
-	card->dev_for_play = dev;
-	nm256_write_block (card, dma_buf, total_count);
-    }
-}
-
-/* Ditto, but do recording instead.  */
-static void
-nm256_audio_start_input(int dev, unsigned long physbuf, int count,
-			int intrflag)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card != NULL) {
-	char *dma_buf = nm256_getDMAbuffer (dev, physbuf);
-	card->is_open_record = 1;
-	card->dev_for_record = dev;
-	nm256_startRecording (card, dma_buf, count);
-    }
-}
-
-/* 
- * Prepare for inputting samples to DEV. 
- * Each requested buffer will be BSIZE byes long, with a total of
- * BCOUNT buffers. 
- */
-
-static int
-nm256_audio_prepare_for_input(int dev, int bsize, int bcount)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card == NULL) 
-	return -ENODEV;
-
-    if (card->is_open_record && card->dev_for_record != dev)
-	return -EBUSY;
-
-    audio_devs[dev]->dmap_in->flags |= DMA_NODMA;
-    return 0;
-}
-
-/*
- * Prepare for outputting samples to `dev'
- *
- * Each buffer that will be passed will be `bsize' bytes long,
- * with a total of `bcount' buffers.
- *
- * Called when:
- *  1. A trigger enables audio output                   (dmabuf.c:978)
- *  2. We get a write buffer without dma_mode setup     (dmabuf.c:1152)
- *  3. We restart a transfer                            (dmabuf.c:1324)
- */
-
-static int
-nm256_audio_prepare_for_output(int dev, int bsize, int bcount)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card == NULL)
-	return -ENODEV;
-
-    if (card->is_open_play && card->dev_for_play != dev)
-	return -EBUSY;
-
-    audio_devs[dev]->dmap_out->flags |= DMA_NODMA;
-    return 0;
-}
-
-/* Stop the current operations associated with DEV.  */
-static void
-nm256_audio_reset(int dev)
-{
-    struct nm256_info *card = nm256_find_card (dev);
-
-    if (card != NULL) {
-	if (card->dev_for_play == dev)
-	    stopPlay (card);
-	if (card->dev_for_record == dev)
-	    stopRecord (card);
-    }
-}
-
-static int
-nm256_audio_local_qlen(int dev)
-{
-    return 0;
-}
-
-static struct audio_driver nm256_audio_driver =
-{
-	.owner			= THIS_MODULE,
-	.open			= nm256_audio_open,
-	.close			= nm256_audio_close,
-	.output_block		= nm256_audio_output_block,
-	.start_input		= nm256_audio_start_input,
-	.ioctl			= nm256_audio_ioctl,
-	.prepare_for_input	= nm256_audio_prepare_for_input,
-	.prepare_for_output	= nm256_audio_prepare_for_output,
-	.halt_io		= nm256_audio_reset,
-	.local_qlen		= nm256_audio_local_qlen,
-};
-
-static struct pci_device_id nm256_pci_tbl[] = {
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO,
-	PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO,
-	PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO,
-	PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{0,}
-};
-MODULE_DEVICE_TABLE(pci, nm256_pci_tbl);
-MODULE_LICENSE("GPL");
-
-
-static struct pci_driver nm256_pci_driver = {
-	.name		= "nm256_audio",
-	.id_table	= nm256_pci_tbl,
-	.probe		= nm256_probe,
-	.remove		= nm256_remove,
-};
-
-module_param(usecache, bool, 0);
-module_param(buffertop, int, 0);
-module_param(nm256_debug, bool, 0644);
-module_param(force_load, bool, 0);
-
-static int __init do_init_nm256(void)
-{
-    printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1p\n");
-    return pci_register_driver(&nm256_pci_driver);
-}
-
-static void __exit cleanup_nm256 (void)
-{
-    pci_unregister_driver(&nm256_pci_driver);
-}
-
-module_init(do_init_nm256);
-module_exit(cleanup_nm256);
-
-/*
- * Local variables:
- *  c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/nm256_coeff.h b/sound/oss/nm256_coeff.h
deleted file mode 100644
index 6fc07f3..0000000
--- a/sound/oss/nm256_coeff.h
+++ /dev/null
@@ -1,4697 +0,0 @@
-#ifndef NM256_COEFF_H
-#define NM256_COEFF_H
-
-#define NM_TOTAL_COEFF_COUNT 0x3158
-
-static char coefficients[NM_TOTAL_COEFF_COUNT * 4] = { 
-	0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA5, 0x01, 0xEF, 0xFC, 0x21,
-	0x05, 0x87, 0xF7, 0x62, 0x11, 0xE9, 0x45, 0x5E, 0xF9, 0xB5, 0x01,
-	0xDE, 0xFF, 0xA4, 0xFF, 0x60, 0x00, 0xCA, 0xFF, 0x0D, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06,
-	0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1,
-	0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFD, 0xFF,
-	0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E,
-	0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC,
-	0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x02, 0x00, 0x05,
-	0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
-	0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
-	0x60, 0x00, 0xA4, 0xFF, 0xDE, 0xFF, 0xB5, 0x01, 0x5E, 0xF9, 0xE9,
-	0x45, 0x62, 0x11, 0x87, 0xF7, 0x21, 0x05, 0xEF, 0xFC, 0xA5, 0x01,
-	0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84,
-	0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
-	0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
-	0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-	0xCA, 0x01, 0x95, 0xFC, 0xEA, 0x05, 0xBB, 0xF5, 0x25, 0x17, 0x3C,
-	0x43, 0x8D, 0xF6, 0x43, 0x03, 0xF5, 0xFE, 0x26, 0x00, 0x20, 0x00,
-	0xE2, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5,
-	0x01, 0x4C, 0xFC, 0x26, 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33,
-	0x8F, 0xF1, 0xCA, 0x06, 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24,
-	0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD5, 0xFF, 0xBC, 0x00,
-	0xF0, 0xFD, 0xEC, 0x04, 0xD9, 0xF3, 0xB1, 0x3E, 0xCD, 0x1E, 0xC1,
-	0xF3, 0xAF, 0x06, 0x49, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38,
-	0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA,
-	0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0x98, 0x01, 0x0D, 0xFD,
-	0xE0, 0x04, 0x14, 0xF8, 0xC3, 0x0F, 0x89, 0x46, 0x4C, 0xFA, 0x38,
-	0x01, 0x25, 0x00, 0x7D, 0xFF, 0x73, 0x00, 0xC2, 0xFF, 0x0F, 0x00,
-	0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F,
-	0x07, 0x84, 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05,
-	0x41, 0xFD, 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x15, 0x00, 0x97, 0xFF, 0x37, 0x01, 0x22, 0xFD, 0x23, 0x06,
-	0x2F, 0xF2, 0x11, 0x39, 0x7B, 0x26, 0x50, 0xF2, 0x1B, 0x07, 0x32,
-	0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-	0xC8, 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93,
-	0xF9, 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC,
-	0xA2, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
-	0x00, 0x6A, 0xFF, 0x53, 0x01, 0xA6, 0xFD, 0xA6, 0x03, 0xA1, 0xFA,
-	0xDE, 0x08, 0x76, 0x48, 0x0C, 0xFF, 0xDE, 0xFE, 0x73, 0x01, 0xC9,
-	0xFE, 0xCA, 0x00, 0xA0, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
-	0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
-	0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x68,
-	0xFF, 0x93, 0x01, 0x92, 0xFC, 0xE2, 0x06, 0x83, 0xF1, 0x8C, 0x32,
-	0xED, 0x2D, 0x90, 0xF1, 0x1E, 0x07, 0x57, 0xFC, 0xBD, 0x01, 0x51,
-	0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00,
-	0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76,
-	0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF, 0x03, 0x01, 0x53,
-	0xFE, 0x53, 0x02, 0x39, 0xFD, 0xA9, 0x02, 0xF2, 0x48, 0xB9, 0x04,
-	0x54, 0xFC, 0xCA, 0x02, 0x16, 0xFE, 0x20, 0x01, 0x7F, 0xFF, 0x20,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC3, 0x01,
-	0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7, 0x43, 0x20,
-	0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00, 0xDD, 0xFF,
-	0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCD, 0x01, 0x43,
-	0xFC, 0x2A, 0x07, 0xBC, 0xF1, 0x64, 0x2B, 0xE3, 0x34, 0xA3, 0xF1,
-	0xAE, 0x06, 0xBD, 0xFC, 0x77, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
-	0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8, 0xFD,
-	0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3, 0xC8,
-	0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x14, 0x00, 0xAC, 0xFF, 0xAC, 0x00, 0x08, 0xFF, 0xFD, 0x00, 0xB5,
-	0xFF, 0x4B, 0xFD, 0xF4, 0x47, 0x30, 0x0B, 0xBC, 0xF9, 0x17, 0x04,
-	0x6E, 0xFD, 0x6D, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01, 0x26, 0xFD, 0xAD, 0x04,
-	0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C, 0xFB, 0xD4, 0x00, 0x5D,
-	0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0x01, 0x07, 0xBE,
-	0xF2, 0xD6, 0x23, 0x1F, 0x3B, 0xA5, 0xF2, 0xC5, 0x05, 0x62, 0xFD,
-	0x10, 0x01, 0xAB, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19,
-	0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD, 0x4D, 0x06, 0x00, 0xF2,
-	0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23, 0x07, 0x34, 0xFC, 0xDD,
-	0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF,
-	0x56, 0x00, 0xB9, 0xFF, 0xB8, 0xFF, 0xF7, 0x01, 0xE2, 0xF8, 0x8D,
-	0x45, 0x46, 0x12, 0x3C, 0xF7, 0x43, 0x05, 0xDF, 0xFC, 0xAC, 0x01,
-	0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70,
-	0xFF, 0x46, 0x01, 0xC3, 0xFD, 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07,
-	0xA6, 0x48, 0xF8, 0xFF, 0x70, 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9,
-	0x00, 0x9A, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xDE, 0x01, 0x5D, 0xFC, 0x74, 0x06, 0x63, 0xF4, 0x23, 0x1C, 0x66,
-	0x40, 0xAA, 0xF4, 0x65, 0x04, 0x44, 0xFE, 0x8B, 0x00, 0xEE, 0xFF,
-	0xF5, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F,
-	0x01, 0x80, 0xFC, 0xF7, 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F,
-	0x83, 0xF1, 0x13, 0x07, 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C,
-	0x00, 0xFD, 0xFF, 0x06, 0x00, 0xED, 0xFF, 0x05, 0x00, 0x5D, 0x00,
-	0x95, 0xFE, 0xE2, 0x03, 0x7F, 0xF5, 0xCC, 0x41, 0xC7, 0x19, 0xFF,
-	0xF4, 0x37, 0x06, 0x75, 0xFC, 0xD6, 0x01, 0x39, 0xFF, 0x35, 0x00,
-	0xFE, 0xFF, 0x1B, 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18,
-	0x02, 0xAA, 0xFD, 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB,
-	0x05, 0x03, 0xF7, 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBB, 0x01, 0xBA, 0xFC,
-	0x95, 0x05, 0x83, 0xF6, 0x8C, 0x14, 0x87, 0x44, 0xBB, 0xF7, 0x98,
-	0x02, 0x5A, 0xFF, 0xEE, 0xFF, 0x3C, 0x00, 0xD8, 0xFF, 0x0A, 0x00,
-	0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A,
-	0x07, 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06,
-	0xD5, 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01,
-	0x00, 0x07, 0x00, 0xBE, 0xFF, 0xEA, 0x00, 0xA2, 0xFD, 0x65, 0x05,
-	0x28, 0xF3, 0xDB, 0x3C, 0x78, 0x21, 0x30, 0xF3, 0xDF, 0x06, 0x3A,
-	0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
-	0xB2, 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76,
-	0xFC, 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD,
-	0x79, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
-	0x00, 0x58, 0xFF, 0x82, 0x01, 0x3F, 0xFD, 0x78, 0x04, 0xF2, 0xF8,
-	0x50, 0x0D, 0x5E, 0x47, 0xD5, 0xFB, 0x6F, 0x00, 0x96, 0x00, 0x40,
-	0xFF, 0x91, 0x00, 0xB7, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
-	0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
-	0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x85,
-	0xFF, 0x5B, 0x01, 0xE9, 0xFC, 0x73, 0x06, 0xD8, 0xF1, 0xE5, 0x36,
-	0x19, 0x29, 0xF8, 0xF1, 0x29, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x42,
-	0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3, 0xFF, 0x47, 0x00,
-	0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44, 0x8D,
-	0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45, 0xFF,
-	0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x75, 0xFF, 0x39,
-	0x01, 0xE0, 0xFD, 0x33, 0x03, 0x87, 0xFB, 0xA2, 0x06, 0xCB, 0x48,
-	0xEA, 0x00, 0x01, 0xFE, 0xE9, 0x01, 0x8A, 0xFE, 0xE8, 0x00, 0x95,
-	0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF, 0xDA, 0x01,
-	0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32, 0x41, 0x1F,
-	0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF, 0xF0, 0xFF,
-	0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5B, 0xFF, 0xAB, 0x01, 0x6F,
-	0xFC, 0x08, 0x07, 0x7E, 0xF1, 0x21, 0x30, 0x67, 0x30, 0x7D, 0xF1,
-	0x05, 0x07, 0x73, 0xFC, 0xA8, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD,
-	0xFF, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0x67, 0xFE,
-	0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B, 0xA6, 0xF4, 0x5A,
-	0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-	0x1A, 0x00, 0x96, 0xFF, 0xE5, 0x00, 0x91, 0xFE, 0xDC, 0x01, 0x1A,
-	0xFE, 0xB3, 0x00, 0xC3, 0x48, 0xE1, 0x06, 0x6E, 0xFB, 0x40, 0x03,
-	0xDA, 0xFD, 0x3C, 0x01, 0x74, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05,
-	0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E,
-	0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-	0x33, 0x00, 0x41, 0xFF, 0xD9, 0x01, 0x36, 0xFC, 0x28, 0x07, 0x01,
-	0xF2, 0xCE, 0x28, 0x23, 0x37, 0xE0, 0xF1, 0x6B, 0x06, 0xEF, 0xFC,
-	0x57, 0x01, 0x87, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B,
-	0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E, 0xFD, 0x9C, 0x05, 0xDC, 0xF2,
-	0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2, 0xF3, 0x06, 0x35, 0xFC, 0xE6,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xB8, 0xFF,
-	0x8E, 0x00, 0x46, 0xFF, 0x8A, 0x00, 0x86, 0x00, 0xA7, 0xFB, 0x48,
-	0x47, 0x95, 0x0D, 0xD9, 0xF8, 0x84, 0x04, 0x39, 0xFD, 0x85, 0x01,
-	0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
-	0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
-	0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
-	0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-	0xE6, 0x01, 0x3B, 0xFC, 0xDA, 0x06, 0x3F, 0xF3, 0x2C, 0x21, 0x11,
-	0x3D, 0x3A, 0xF3, 0x58, 0x05, 0xAA, 0xFD, 0xE5, 0x00, 0xC1, 0xFF,
-	0x06, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B,
-	0x01, 0xCF, 0xFC, 0x96, 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A,
-	0xD4, 0xF1, 0x2B, 0x07, 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32,
-	0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD9, 0xFF, 0x39, 0x00, 0xF4, 0xFF,
-	0x4E, 0xFF, 0xAC, 0x02, 0x98, 0xF7, 0x65, 0x44, 0xD6, 0x14, 0x6C,
-	0xF6, 0x9F, 0x05, 0xB6, 0xFC, 0xBD, 0x01, 0x42, 0xFF, 0x32, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE,
-	0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01,
-	0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C,
-	0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD5, 0x01, 0x78, 0xFC,
-	0x2F, 0x06, 0x13, 0xF5, 0x7C, 0x19, 0xF7, 0x41, 0x9B, 0xF5, 0xD1,
-	0x03, 0x9F, 0xFE, 0x57, 0x00, 0x08, 0x00, 0xEC, 0xFF, 0x06, 0x00,
-	0xFD, 0xFF, 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16,
-	0x07, 0x85, 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06,
-	0x84, 0xFC, 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04,
-	0x00, 0xF6, 0xFF, 0xEB, 0xFF, 0x91, 0x00, 0x3B, 0xFE, 0x75, 0x04,
-	0x92, 0xF4, 0x36, 0x40, 0x6E, 0x1C, 0x50, 0xF4, 0x7B, 0x06, 0x5B,
-	0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00,
-	0x9C, 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3,
-	0xFF, 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD,
-	0x49, 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-	0x00, 0x49, 0xFF, 0xAA, 0x01, 0xE4, 0xFC, 0x38, 0x05, 0x54, 0xF7,
-	0xFE, 0x11, 0xAA, 0x45, 0x09, 0xF9, 0xE2, 0x01, 0xC4, 0xFF, 0xB3,
-	0xFF, 0x59, 0x00, 0xCD, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
-	0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
-	0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA9,
-	0xFF, 0x15, 0x01, 0x5B, 0xFD, 0xD0, 0x05, 0x97, 0xF2, 0xE6, 0x3A,
-	0x21, 0x24, 0xB1, 0xF2, 0x04, 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x39,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00,
-	0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD,
-	0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF,
-	0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x6A,
-	0x01, 0x74, 0xFD, 0x0A, 0x04, 0xD5, 0xF9, 0xED, 0x0A, 0x03, 0x48,
-	0x7C, 0xFD, 0x9E, 0xFF, 0x0A, 0x01, 0x01, 0xFF, 0xAF, 0x00, 0xAB,
-	0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01,
-	0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE, 0x3D, 0x91,
-	0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF, 0x02, 0x00,
-	0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x75, 0xFF, 0x7A, 0x01, 0xB8,
-	0xFC, 0xB4, 0x06, 0x9E, 0xF1, 0xA2, 0x34, 0xAD, 0x2B, 0xB6, 0xF1,
-	0x29, 0x07, 0x45, 0xFC, 0xCB, 0x01, 0x49, 0xFF, 0x31, 0x00, 0xFD,
-	0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B, 0xFF,
-	0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6, 0xCA,
-	0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x20, 0x00, 0x80, 0xFF, 0x1C, 0x01, 0x1C, 0xFE, 0xBD,
-	0x02, 0x6E, 0xFC, 0x7D, 0x04, 0xF3, 0x48, 0xE2, 0x02, 0x1F, 0xFD,
-	0x60, 0x02, 0x4C, 0xFE, 0x06, 0x01, 0x89, 0xFF, 0x1D, 0x00, 0xFE,
-	0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01, 0x88, 0xFC, 0x09, 0x06,
-	0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20, 0xF6, 0x83, 0x03, 0xCF,
-	0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
-	0x2E, 0x00, 0x50, 0xFF, 0xBF, 0x01, 0x54, 0xFC, 0x20, 0x07, 0x94,
-	0xF1, 0xA6, 0x2D, 0xD0, 0x32, 0x85, 0xF1, 0xDD, 0x06, 0x96, 0xFC,
-	0x90, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB,
-	0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE, 0xB9, 0x04, 0x27, 0xF4,
-	0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99, 0x06, 0x50, 0xFC, 0xE2,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA2, 0xFF,
-	0xC7, 0x00, 0xD0, 0xFE, 0x65, 0x01, 0xF6, 0xFE, 0xD9, 0xFE, 0x6A,
-	0x48, 0x1F, 0x09, 0x87, 0xFA, 0xB3, 0x03, 0xA0, 0xFD, 0x56, 0x01,
-	0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4D,
-	0xFF, 0xA0, 0x01, 0xFB, 0xFC, 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10,
-	0x2B, 0x46, 0xBB, 0xF9, 0x83, 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68,
-	0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
-	0xE1, 0x01, 0x31, 0xFC, 0x19, 0x07, 0x5B, 0xF2, 0x30, 0x26, 0x4B,
-	0x39, 0x3B, 0xF2, 0x1A, 0x06, 0x29, 0xFD, 0x33, 0x01, 0x99, 0xFF,
-	0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28,
-	0x01, 0x3A, 0xFD, 0x00, 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25,
-	0x79, 0xF2, 0x12, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35,
-	0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC4, 0xFF, 0x70, 0x00, 0x84, 0xFF,
-	0x19, 0x00, 0x4D, 0x01, 0x22, 0xFA, 0x70, 0x46, 0x0A, 0x10, 0xFC,
-	0xF7, 0xEB, 0x04, 0x08, 0xFD, 0x9A, 0x01, 0x4F, 0xFF, 0x2E, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90,
-	0xFD, 0xD2, 0x03, 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE,
-	0x33, 0xFF, 0x45, 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16,
-	0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4B, 0xFC,
-	0xA9, 0x06, 0xD2, 0xF3, 0x81, 0x1E, 0xE4, 0x3E, 0xEF, 0xF3, 0xDE,
-	0x04, 0xF9, 0xFD, 0xB7, 0x00, 0xD8, 0xFF, 0xFD, 0xFF, 0x03, 0x00,
-	0xFD, 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0,
-	0x06, 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07,
-	0x4E, 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08,
-	0x00, 0xE4, 0xFF, 0x1D, 0x00, 0x2D, 0x00, 0xEA, 0xFE, 0x56, 0x03,
-	0x6D, 0xF6, 0x17, 0x43, 0x70, 0x17, 0xA6, 0xF5, 0xF3, 0x05, 0x91,
-	0xFC, 0xCC, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-	0x86, 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73,
-	0x03, 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE,
-	0x14, 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33,
-	0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x99, 0xFC, 0xE1, 0x05, 0xD1, 0xF5,
-	0xDC, 0x16, 0x65, 0x43, 0xAD, 0xF6, 0x31, 0x03, 0x00, 0xFF, 0x20,
-	0x00, 0x23, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00,
-	0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
-	0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
-	0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0xFF, 0xFF, 0xD3,
-	0xFF, 0xC1, 0x00, 0xE7, 0xFD, 0xFA, 0x04, 0xC4, 0xF3, 0x7E, 0x3E,
-	0x19, 0x1F, 0xB0, 0xF3, 0xB5, 0x06, 0x47, 0xFC, 0xE4, 0x01, 0x36,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8, 0x00,
-	0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48, 0x47,
-	0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64, 0xFF,
-	0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x96,
-	0x01, 0x13, 0xFD, 0xD5, 0x04, 0x2C, 0xF8, 0x7D, 0x0F, 0xA3, 0x46,
-	0x76, 0xFA, 0x22, 0x01, 0x32, 0x00, 0x76, 0xFF, 0x76, 0x00, 0xC1,
-	0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF, 0xE4, 0x01,
-	0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54, 0x3A, 0x74,
-	0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF, 0x11, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x95, 0xFF, 0x3B, 0x01, 0x1B,
-	0xFD, 0x2D, 0x06, 0x24, 0xF2, 0xD3, 0x38, 0xC6, 0x26, 0x45, 0xF2,
-	0x1D, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
-	0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2, 0xFF, 0xE2, 0xFF,
-	0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11, 0x8F, 0xF7, 0x1D,
-	0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x51, 0x01, 0xAC, 0xFD, 0x9A,
-	0x03, 0xBA, 0xFA, 0x9E, 0x08, 0x81, 0x48, 0x40, 0xFF, 0xC6, 0xFE,
-	0x80, 0x01, 0xC2, 0xFE, 0xCE, 0x00, 0x9F, 0xFF, 0x17, 0x00, 0xFE,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06,
-	0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23,
-	0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFD, 0xFF,
-	0x27, 0x00, 0x66, 0xFF, 0x96, 0x01, 0x8E, 0xFC, 0xE7, 0x06, 0x81,
-	0xF1, 0x48, 0x32, 0x34, 0x2E, 0x8D, 0xF1, 0x1C, 0x07, 0x5A, 0xFC,
-	0xBB, 0x01, 0x53, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9,
-	0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9, 0xFE, 0xA6, 0x03, 0xE4, 0xF5,
-	0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5, 0x1A, 0x06, 0x81, 0xFC, 0xD2,
-	0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8B, 0xFF,
-	0xFF, 0x00, 0x5A, 0xFE, 0x46, 0x02, 0x52, 0xFD, 0x70, 0x02, 0xED,
-	0x48, 0xF5, 0x04, 0x3B, 0xFC, 0xD7, 0x02, 0x0F, 0xFE, 0x23, 0x01,
-	0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-	0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
-	0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
-	0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF,
-	0xCE, 0x01, 0x41, 0xFC, 0x2A, 0x07, 0xC2, 0xF1, 0x1B, 0x2B, 0x25,
-	0x35, 0xA8, 0xF1, 0xA7, 0x06, 0xC2, 0xFC, 0x74, 0x01, 0x78, 0xFF,
-	0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9,
-	0x00, 0xBF, 0xFD, 0x38, 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20,
-	0x66, 0xF3, 0xCE, 0x06, 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAE, 0xFF, 0xA9, 0x00, 0x0F, 0xFF,
-	0xF0, 0x00, 0xCD, 0xFF, 0x1B, 0xFD, 0xE4, 0x47, 0x73, 0x0B, 0xA2,
-	0xF9, 0x23, 0x04, 0x68, 0xFD, 0x70, 0x01, 0x5F, 0xFF, 0x29, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B,
-	0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB,
-	0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC,
-	0xFD, 0x06, 0xCB, 0xF2, 0x8A, 0x23, 0x58, 0x3B, 0xB4, 0xF2, 0xBA,
-	0x05, 0x6A, 0xFD, 0x0B, 0x01, 0xAE, 0xFF, 0x0D, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56,
-	0x06, 0xF7, 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07,
-	0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
-	0x00, 0xCF, 0xFF, 0x52, 0x00, 0xC0, 0xFF, 0xAC, 0xFF, 0x0C, 0x02,
-	0xBC, 0xF8, 0x6D, 0x45, 0x8E, 0x12, 0x24, 0xF7, 0x4D, 0x05, 0xDB,
-	0xFC, 0xAE, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x24, 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E,
-	0xFB, 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01,
-	0xA3, 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36,
-	0x00, 0x37, 0xFF, 0xDD, 0x01, 0x60, 0xFC, 0x6D, 0x06, 0x76, 0xF4,
-	0xD8, 0x1B, 0x95, 0x40, 0xC3, 0xF4, 0x56, 0x04, 0x4E, 0xFE, 0x85,
-	0x00, 0xF1, 0xFF, 0xF4, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00,
-	0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
-	0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
-	0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x02,
-	0x00, 0x63, 0x00, 0x8A, 0xFE, 0xF3, 0x03, 0x63, 0xF5, 0xA1, 0x41,
-	0x12, 0x1A, 0xEB, 0xF4, 0x3F, 0x06, 0x72, 0xFC, 0xD7, 0x01, 0x39,
-	0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00,
-	0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07,
-	0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF,
-	0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBA,
-	0x01, 0xBF, 0xFC, 0x8B, 0x05, 0x99, 0xF6, 0x43, 0x14, 0xA9, 0x44,
-	0xDE, 0xF7, 0x85, 0x02, 0x65, 0xFF, 0xE7, 0xFF, 0x3F, 0x00, 0xD6,
-	0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD5, 0x01,
-	0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46, 0x36, 0xC5,
-	0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF, 0x1E, 0x00,
-	0xFE, 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBC, 0xFF, 0xEF, 0x00, 0x9A,
-	0xFD, 0x72, 0x05, 0x16, 0xF3, 0xA5, 0x3C, 0xC4, 0x21, 0x21, 0xF3,
-	0xE4, 0x06, 0x39, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6, 0x00,
-	0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9, 0x5A,
-	0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x80, 0x01, 0x45, 0xFD, 0x6C,
-	0x04, 0x0B, 0xF9, 0x0B, 0x0D, 0x73, 0x47, 0x02, 0xFC, 0x58, 0x00,
-	0xA3, 0x00, 0x39, 0xFF, 0x94, 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37, 0xFC, 0xEB, 0x06,
-	0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD, 0xF2, 0x84, 0x05, 0x8D,
-	0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF,
-	0x1D, 0x00, 0x83, 0xFF, 0x5E, 0x01, 0xE3, 0xFC, 0x7B, 0x06, 0xD0,
-	0xF1, 0xA5, 0x36, 0x62, 0x29, 0xEF, 0xF1, 0x29, 0x07, 0x39, 0xFC,
-	0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5,
-	0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF, 0x67, 0x02, 0x14, 0xF8,
-	0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C, 0x05, 0xC5, 0xFC, 0xB7,
-	0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00,
-	0x76, 0xFF, 0x35, 0x01, 0xE7, 0xFD, 0x26, 0x03, 0xA1, 0xFB, 0x64,
-	0x06, 0xD2, 0x48, 0x21, 0x01, 0xE8, 0xFD, 0xF7, 0x01, 0x83, 0xFE,
-	0xEC, 0x00, 0x93, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39,
-	0xFF, 0xD9, 0x01, 0x6D, 0xFC, 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A,
-	0x5F, 0x41, 0x3A, 0xF5, 0x0C, 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE,
-	0xFF, 0xEF, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF,
-	0xAD, 0x01, 0x6C, 0xFC, 0x0C, 0x07, 0x7F, 0xF1, 0xDC, 0x2F, 0xAD,
-	0x30, 0x7D, 0xF1, 0x01, 0x07, 0x76, 0xFC, 0xA6, 0x01, 0x5E, 0xFF,
-	0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D,
-	0x00, 0x5D, 0xFE, 0x3E, 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B,
-	0x93, 0xF4, 0x62, 0x06, 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36,
-	0x00, 0xFE, 0xFF, 0x19, 0x00, 0x97, 0xFF, 0xE2, 0x00, 0x98, 0xFE,
-	0xCF, 0x01, 0x33, 0xFE, 0x7D, 0x00, 0xBB, 0x48, 0x1F, 0x07, 0x54,
-	0xFB, 0x4C, 0x03, 0xD3, 0xFD, 0x3F, 0x01, 0x73, 0xFF, 0x23, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3,
-	0xFC, 0x5D, 0x05, 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8,
-	0x2A, 0x02, 0x9A, 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C,
-	0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDA, 0x01, 0x35, 0xFC,
-	0x27, 0x07, 0x09, 0xF2, 0x85, 0x28, 0x63, 0x37, 0xE9, 0xF1, 0x63,
-	0x06, 0xF5, 0xFC, 0x53, 0x01, 0x89, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-	0x00, 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8,
-	0x05, 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06,
-	0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
-	0x00, 0xB9, 0xFF, 0x8A, 0x00, 0x4D, 0xFF, 0x7D, 0x00, 0x9C, 0x00,
-	0x7B, 0xFB, 0x31, 0x47, 0xD9, 0x0D, 0xC0, 0xF8, 0x8F, 0x04, 0x34,
-	0xFD, 0x87, 0x01, 0x56, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x29, 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C,
-	0xF9, 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00,
-	0x19, 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD5, 0x06, 0x4F, 0xF3,
-	0xE0, 0x20, 0x45, 0x3D, 0x4D, 0xF3, 0x4B, 0x05, 0xB3, 0xFD, 0xE0,
-	0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00,
-	0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
-	0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
-	0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xDA, 0xFF, 0x36,
-	0x00, 0xFA, 0xFF, 0x43, 0xFF, 0xBF, 0x02, 0x75, 0xF7, 0x42, 0x44,
-	0x20, 0x15, 0x55, 0xF6, 0xA9, 0x05, 0xB2, 0xFC, 0xBF, 0x01, 0x41,
-	0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF,
-	0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05, 0xEA,
-	0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA, 0x00,
-	0x8D, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD4,
-	0x01, 0x7C, 0xFC, 0x27, 0x06, 0x28, 0xF5, 0x31, 0x19, 0x21, 0x42,
-	0xB8, 0xF5, 0xC0, 0x03, 0xAA, 0xFE, 0x51, 0x00, 0x0B, 0x00, 0xEA,
-	0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF, 0xB7, 0x01,
-	0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3, 0x31, 0x7E,
-	0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF, 0x28, 0x00,
-	0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xE8, 0xFF, 0x96, 0x00, 0x31,
-	0xFE, 0x84, 0x04, 0x79, 0xF4, 0x07, 0x40, 0xBA, 0x1C, 0x3E, 0xF4,
-	0x82, 0x06, 0x58, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8, 0xFE, 0x93, 0x01,
-	0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08, 0xE1, 0xFA, 0x86,
-	0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA8, 0x01, 0xE9, 0xFC, 0x2D,
-	0x05, 0x6B, 0xF7, 0xB6, 0x11, 0xC8, 0x45, 0x30, 0xF9, 0xCD, 0x01,
-	0xD0, 0xFF, 0xAC, 0xFF, 0x5C, 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD,
-	0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07,
-	0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11,
-	0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x10, 0x00, 0xA7, 0xFF, 0x19, 0x01, 0x53, 0xFD, 0xDB, 0x05, 0x88,
-	0xF2, 0xAD, 0x3A, 0x6D, 0x24, 0xA4, 0xF2, 0x08, 0x07, 0x32, 0xFC,
-	0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBF,
-	0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44, 0x00, 0x01, 0x01, 0xB6, 0xFA,
-	0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8, 0xC4, 0x04, 0x1B, 0xFD, 0x92,
-	0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
-	0x63, 0xFF, 0x67, 0x01, 0x7A, 0xFD, 0xFE, 0x03, 0xEE, 0xF9, 0xAA,
-	0x0A, 0x16, 0x48, 0xAC, 0xFD, 0x86, 0xFF, 0x17, 0x01, 0xFA, 0xFE,
-	0xB3, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-	0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
-	0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
-	0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x73, 0xFF,
-	0x7D, 0x01, 0xB3, 0xFC, 0xBB, 0x06, 0x9A, 0xF1, 0x60, 0x34, 0xF5,
-	0x2B, 0xB0, 0xF1, 0x28, 0x07, 0x47, 0xFC, 0xCA, 0x01, 0x4A, 0xFF,
-	0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17,
-	0x00, 0x10, 0xFF, 0x15, 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16,
-	0xF1, 0xF5, 0xD3, 0x05, 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x19, 0x01,
-	0x23, 0xFE, 0xB0, 0x02, 0x87, 0xFC, 0x41, 0x04, 0xF4, 0x48, 0x1C,
-	0x03, 0x06, 0xFD, 0x6E, 0x02, 0x45, 0xFE, 0x09, 0x01, 0x88, 0xFF,
-	0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C,
-	0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6,
-	0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07,
-	0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4F, 0xFF, 0xC1, 0x01, 0x52, 0xFC,
-	0x22, 0x07, 0x98, 0xF1, 0x5E, 0x2D, 0x13, 0x33, 0x87, 0xF1, 0xD8,
-	0x06, 0x9B, 0xFC, 0x8D, 0x01, 0x6B, 0xFF, 0x25, 0x00, 0xFD, 0xFF,
-	0x03, 0x00, 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8,
-	0x04, 0x10, 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06,
-	0x4E, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16,
-	0x00, 0xA3, 0xFF, 0xC3, 0x00, 0xD7, 0xFE, 0x58, 0x01, 0x0F, 0xFF,
-	0xA6, 0xFE, 0x5D, 0x48, 0x61, 0x09, 0x6E, 0xFA, 0xC0, 0x03, 0x99,
-	0xFD, 0x59, 0x01, 0x68, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x2E, 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7,
-	0xF7, 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00,
-	0x8E, 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
-	0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x16, 0x07, 0x67, 0xF2,
-	0xE5, 0x25, 0x87, 0x39, 0x47, 0xF2, 0x10, 0x06, 0x30, 0xFD, 0x2F,
-	0x01, 0x9C, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x00,
-	0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
-	0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-	0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC5, 0xFF, 0x6D,
-	0x00, 0x8B, 0xFF, 0x0D, 0x00, 0x63, 0x01, 0xF9, 0xF9, 0x55, 0x46,
-	0x51, 0x10, 0xE3, 0xF7, 0xF7, 0x04, 0x03, 0xFD, 0x9D, 0x01, 0x4E,
-	0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF,
-	0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57,
-	0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00,
-	0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3,
-	0x01, 0x4D, 0xFC, 0xA3, 0x06, 0xE4, 0xF3, 0x36, 0x1E, 0x16, 0x3F,
-	0x05, 0xF4, 0xCF, 0x04, 0x02, 0xFE, 0xB2, 0x00, 0xDB, 0xFF, 0xFC,
-	0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF, 0x8B, 0x01,
-	0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A, 0x2D, 0x9A,
-	0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF, 0x2F, 0x00,
-	0xFD, 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x1A, 0x00, 0x33, 0x00, 0xDF,
-	0xFE, 0x68, 0x03, 0x4E, 0xF6, 0xEE, 0x42, 0xBB, 0x17, 0x90, 0xF5,
-	0xFC, 0x05, 0x8E, 0xFC, 0xCD, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
-	0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74, 0x02,
-	0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC, 0xA9,
-	0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC7, 0x01, 0x9D, 0xFC, 0xD8,
-	0x05, 0xE7, 0xF5, 0x91, 0x16, 0x89, 0x43, 0xCD, 0xF6, 0x1E, 0x03,
-	0x0B, 0xFF, 0x1A, 0x00, 0x26, 0x00, 0xE0, 0xFF, 0x08, 0x00, 0xFD,
-	0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01, 0x48, 0xFC, 0x28, 0x07,
-	0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97, 0xF1, 0xBE, 0x06, 0xB0,
-	0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00,
-	0x00, 0x00, 0xD0, 0xFF, 0xC7, 0x00, 0xDE, 0xFD, 0x08, 0x05, 0xB0,
-	0xF3, 0x4A, 0x3E, 0x64, 0x1F, 0xA0, 0xF3, 0xBB, 0x06, 0x45, 0xFC,
-	0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA9,
-	0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01, 0x7A, 0xFF, 0xC5, 0xFD,
-	0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8, 0x03, 0x7D, 0xFD, 0x66,
-	0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
-	0x52, 0xFF, 0x93, 0x01, 0x18, 0xFD, 0xC9, 0x04, 0x45, 0xF8, 0x36,
-	0x0F, 0xBB, 0x46, 0xA1, 0xFA, 0x0C, 0x01, 0x3E, 0x00, 0x70, 0xFF,
-	0x7A, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39,
-	0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24,
-	0x8F, 0x3A, 0x82, 0xF2, 0xE1, 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6,
-	0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x17, 0x00, 0x93, 0xFF,
-	0x3F, 0x01, 0x15, 0xFD, 0x36, 0x06, 0x19, 0xF2, 0x97, 0x38, 0x11,
-	0x27, 0x3B, 0xF2, 0x1F, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF,
-	0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9,
-	0xFF, 0xD6, 0xFF, 0xC3, 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11,
-	0x77, 0xF7, 0x28, 0x05, 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6D, 0xFF, 0x4E, 0x01,
-	0xB3, 0xFD, 0x8D, 0x03, 0xD4, 0xFA, 0x5D, 0x08, 0x8D, 0x48, 0x74,
-	0xFF, 0xAE, 0xFE, 0x8D, 0x01, 0xBB, 0xFE, 0xD1, 0x00, 0x9E, 0xFF,
-	0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57,
-	0xFC, 0x85, 0x06, 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4,
-	0x8C, 0x04, 0x2C, 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04,
-	0x00, 0xFD, 0xFF, 0x27, 0x00, 0x65, 0xFF, 0x98, 0x01, 0x8A, 0xFC,
-	0xEC, 0x06, 0x7F, 0xF1, 0x04, 0x32, 0x7B, 0x2E, 0x8A, 0xF1, 0x1A,
-	0x07, 0x5D, 0xFC, 0xB8, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF,
-	0x06, 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8,
-	0x03, 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06,
-	0x7D, 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C,
-	0x00, 0x8D, 0xFF, 0xFC, 0x00, 0x61, 0xFE, 0x39, 0x02, 0x6B, 0xFD,
-	0x37, 0x02, 0xEB, 0x48, 0x31, 0x05, 0x21, 0xFC, 0xE4, 0x02, 0x08,
-	0xFE, 0x26, 0x01, 0x7C, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x32, 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A,
-	0xF6, 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF,
-	0xFE, 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x32,
-	0x00, 0x47, 0xFF, 0xD0, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xCA, 0xF1,
-	0xD1, 0x2A, 0x65, 0x35, 0xAE, 0xF1, 0xA0, 0x06, 0xC7, 0xFC, 0x70,
-	0x01, 0x7A, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00,
-	0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
-	0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA5,
-	0x00, 0x16, 0xFF, 0xE3, 0x00, 0xE4, 0xFF, 0xEB, 0xFC, 0xD2, 0x47,
-	0xB6, 0x0B, 0x89, 0xF9, 0x2F, 0x04, 0x62, 0xFD, 0x72, 0x01, 0x5E,
-	0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x56, 0xFF,
-	0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D, 0x26,
-	0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89, 0x00,
-	0xBA, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6,
-	0x01, 0x34, 0xFC, 0xF9, 0x06, 0xD9, 0xF2, 0x3F, 0x23, 0x90, 0x3B,
-	0xC4, 0xF2, 0xAE, 0x05, 0x72, 0xFD, 0x07, 0x01, 0xB0, 0xFF, 0x0C,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF, 0x51, 0x01,
-	0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60, 0x28, 0x0E,
-	0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF, 0x34, 0x00,
-	0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x4F, 0x00, 0xC7, 0xFF, 0xA0,
-	0xFF, 0x20, 0x02, 0x96, 0xF8, 0x4E, 0x45, 0xD7, 0x12, 0x0D, 0xF7,
-	0x58, 0x05, 0xD6, 0xFC, 0xB0, 0x01, 0x47, 0xFF, 0x30, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40, 0x01, 0xD0, 0xFD,
-	0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48, 0x62, 0x00, 0x3F,
-	0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98, 0xFF, 0x19, 0x00,
-	0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x63, 0xFC, 0x66,
-	0x06, 0x89, 0xF4, 0x8C, 0x1B, 0xC3, 0x40, 0xDD, 0xF4, 0x46, 0x04,
-	0x58, 0xFE, 0x80, 0x00, 0xF4, 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD,
-	0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06,
-	0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A,
-	0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00,
-	0xEF, 0xFF, 0xFF, 0xFF, 0x69, 0x00, 0x80, 0xFE, 0x04, 0x04, 0x48,
-	0xF5, 0x74, 0x41, 0x5D, 0x1A, 0xD7, 0xF4, 0x47, 0x06, 0x6F, 0xFC,
-	0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x93,
-	0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD, 0x01, 0xDC, 0xFD, 0x3C, 0x01,
-	0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB, 0x1F, 0x03, 0xEA, 0xFD, 0x34,
-	0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00,
-	0x44, 0xFF, 0xB8, 0x01, 0xC3, 0xFC, 0x81, 0x05, 0xB0, 0xF6, 0xFA,
-	0x13, 0xCC, 0x44, 0x02, 0xF8, 0x71, 0x02, 0x71, 0xFF, 0xE1, 0xFF,
-	0x42, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43,
-	0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
-	0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
-	0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x09, 0x00, 0xBA, 0xFF,
-	0xF4, 0x00, 0x91, 0xFD, 0x7E, 0x05, 0x05, 0xF3, 0x6E, 0x3C, 0x10,
-	0x22, 0x12, 0xF3, 0xE9, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35,
-	0xFF, 0xA9, 0x00, 0x4D, 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C,
-	0x18, 0xF9, 0x66, 0x04, 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5A, 0xFF, 0x7D, 0x01,
-	0x4B, 0xFD, 0x60, 0x04, 0x24, 0xF9, 0xC6, 0x0C, 0x86, 0x47, 0x30,
-	0xFC, 0x41, 0x00, 0xB0, 0x00, 0x32, 0xFF, 0x98, 0x00, 0xB4, 0xFF,
-	0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38,
-	0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3,
-	0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01,
-	0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x81, 0xFF, 0x62, 0x01, 0xDD, 0xFC,
-	0x83, 0x06, 0xC9, 0xF1, 0x66, 0x36, 0xAC, 0x29, 0xE7, 0xF1, 0x2A,
-	0x07, 0x3A, 0xFC, 0xD5, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-	0x0B, 0x00, 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B,
-	0x02, 0xF0, 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05,
-	0xC1, 0xFC, 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x22, 0x00, 0x77, 0xFF, 0x32, 0x01, 0xED, 0xFD, 0x19, 0x03,
-	0xBB, 0xFB, 0x26, 0x06, 0xD7, 0x48, 0x58, 0x01, 0xCF, 0xFD, 0x04,
-	0x02, 0x7D, 0xFE, 0xEF, 0x00, 0x92, 0xFF, 0x1B, 0x00, 0xFE, 0xFF,
-	0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1,
-	0xF4, 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE,
-	0x66, 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2B,
-	0x00, 0x59, 0xFF, 0xB0, 0x01, 0x69, 0xFC, 0x0F, 0x07, 0x80, 0xF1,
-	0x96, 0x2F, 0xF2, 0x30, 0x7C, 0xF1, 0xFD, 0x06, 0x7A, 0xFC, 0xA3,
-	0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF4, 0xFF,
-	0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
-	0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
-	0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x98, 0xFF, 0xDE,
-	0x00, 0x9F, 0xFE, 0xC2, 0x01, 0x4B, 0xFE, 0x48, 0x00, 0xB3, 0x48,
-	0x5E, 0x07, 0x3B, 0xFB, 0x59, 0x03, 0xCD, 0xFD, 0x42, 0x01, 0x71,
-	0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF,
-	0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C,
-	0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00,
-	0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDB,
-	0x01, 0x35, 0xFC, 0x25, 0x07, 0x13, 0xF2, 0x3A, 0x28, 0xA0, 0x37,
-	0xF2, 0xF1, 0x5A, 0x06, 0xFB, 0xFC, 0x4F, 0x01, 0x8B, 0xFF, 0x1A,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF, 0x09, 0x01,
-	0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64, 0x23, 0xD2,
-	0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
-	0xFD, 0xFF, 0x11, 0x00, 0xBB, 0xFF, 0x87, 0x00, 0x54, 0xFF, 0x70,
-	0x00, 0xB3, 0x00, 0x4E, 0xFB, 0x1A, 0x47, 0x1F, 0x0E, 0xA8, 0xF8,
-	0x9B, 0x04, 0x2E, 0xFD, 0x8A, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65, 0xFD,
-	0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD, 0xD9,
-	0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14, 0x00,
-	0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD0,
-	0x06, 0x5E, 0xF3, 0x94, 0x20, 0x7B, 0x3D, 0x60, 0xF3, 0x3E, 0x05,
-	0xBB, 0xFD, 0xDB, 0x00, 0xC6, 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE,
-	0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01, 0xC4, 0xFC, 0xA4, 0x06,
-	0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6, 0xF1, 0x2A, 0x07, 0x40,
-	0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00,
-	0xDB, 0xFF, 0x33, 0x00, 0x01, 0x00, 0x38, 0xFF, 0xD3, 0x02, 0x53,
-	0xF7, 0x1F, 0x44, 0x69, 0x15, 0x3F, 0xF6, 0xB2, 0x05, 0xAD, 0xFC,
-	0xC1, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20,
-	0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE, 0xDE, 0x02, 0x2E, 0xFC,
-	0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E, 0xFD, 0x3F, 0x02, 0x5D,
-	0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-	0x3B, 0xFF, 0xD3, 0x01, 0x7F, 0xFC, 0x1F, 0x06, 0x3C, 0xF5, 0xE6,
-	0x18, 0x4D, 0x42, 0xD5, 0xF5, 0xAF, 0x03, 0xB4, 0xFE, 0x4B, 0x00,
-	0x0E, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53,
-	0xFF, 0xBA, 0x01, 0x5B, 0xFC, 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E,
-	0x26, 0x32, 0x80, 0xF1, 0xEA, 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66,
-	0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8, 0xFF, 0xE6, 0xFF,
-	0x9C, 0x00, 0x27, 0xFE, 0x94, 0x04, 0x61, 0xF4, 0xD7, 0x3F, 0x06,
-	0x1D, 0x2B, 0xF4, 0x89, 0x06, 0x56, 0xFC, 0xE0, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF,
-	0xFE, 0x86, 0x01, 0xBA, 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08,
-	0xC7, 0xFA, 0x93, 0x03, 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA6, 0x01,
-	0xEE, 0xFC, 0x23, 0x05, 0x83, 0xF7, 0x6E, 0x11, 0xE5, 0x45, 0x57,
-	0xF9, 0xB8, 0x01, 0xDC, 0xFF, 0xA5, 0xFF, 0x5F, 0x00, 0xCA, 0xFF,
-	0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32,
-	0xFC, 0x1E, 0x07, 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2,
-	0x32, 0x06, 0x18, 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x11, 0x00, 0xA4, 0xFF, 0x1D, 0x01, 0x4C, 0xFD,
-	0xE6, 0x05, 0x7B, 0xF2, 0x71, 0x3A, 0xB8, 0x24, 0x97, 0xF2, 0x0B,
-	0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x0F, 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17,
-	0x01, 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04,
-	0x15, 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x28, 0x00, 0x64, 0xFF, 0x65, 0x01, 0x81, 0xFD, 0xF2, 0x03,
-	0x08, 0xFA, 0x68, 0x0A, 0x25, 0x48, 0xDE, 0xFD, 0x6E, 0xFF, 0x24,
-	0x01, 0xF3, 0xFE, 0xB6, 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8,
-	0xF3, 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD,
-	0xC4, 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x23,
-	0x00, 0x71, 0xFF, 0x81, 0x01, 0xAE, 0xFC, 0xC1, 0x06, 0x95, 0xF1,
-	0x1E, 0x34, 0x3E, 0x2C, 0xAB, 0xF1, 0x27, 0x07, 0x49, 0xFC, 0xC8,
-	0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF,
-	0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
-	0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
-	0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83,
-	0xFF, 0x16, 0x01, 0x2A, 0xFE, 0xA3, 0x02, 0xA1, 0xFC, 0x06, 0x04,
-	0xF5, 0x48, 0x56, 0x03, 0xED, 0xFC, 0x7B, 0x02, 0x3E, 0xFE, 0x0C,
-	0x01, 0x86, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-	0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17, 0x02,
-	0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B, 0x00,
-	0xE4, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3,
-	0x01, 0x4F, 0xFC, 0x24, 0x07, 0x9C, 0xF1, 0x17, 0x2D, 0x57, 0x33,
-	0x8A, 0xF1, 0xD3, 0x06, 0x9F, 0xFC, 0x8A, 0x01, 0x6D, 0xFF, 0x25,
-	0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF, 0xB4, 0x00,
-	0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B, 0x1E, 0xDB,
-	0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC0, 0x00, 0xDE, 0xFE, 0x4B,
-	0x01, 0x27, 0xFF, 0x73, 0xFE, 0x4F, 0x48, 0xA2, 0x09, 0x54, 0xFA,
-	0xCC, 0x03, 0x93, 0xFD, 0x5C, 0x01, 0x67, 0xFF, 0x27, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C, 0x01, 0x05, 0xFD,
-	0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46, 0x0D, 0xFA, 0x58,
-	0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4, 0xFF, 0x0E, 0x00,
-	0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x14,
-	0x07, 0x73, 0xF2, 0x99, 0x25, 0xC2, 0x39, 0x54, 0xF2, 0x05, 0x06,
-	0x37, 0xFD, 0x2B, 0x01, 0x9E, 0xFF, 0x13, 0x00, 0xFF, 0xFF, 0xFF,
-	0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06,
-	0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31,
-	0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-	0xC6, 0xFF, 0x69, 0x00, 0x91, 0xFF, 0x00, 0x00, 0x78, 0x01, 0xD0,
-	0xF9, 0x39, 0x46, 0x98, 0x10, 0xCB, 0xF7, 0x02, 0x05, 0xFE, 0xFC,
-	0x9F, 0x01, 0x4D, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
-	0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D, 0xFD, 0xB9, 0x03, 0x7B, 0xFA,
-	0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE, 0x03, 0xFF, 0x5F, 0x01, 0xD4,
-	0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE2, 0x01, 0x4F, 0xFC, 0x9C, 0x06, 0xF5, 0xF3, 0xEA,
-	0x1D, 0x47, 0x3F, 0x1B, 0xF4, 0xC1, 0x04, 0x0B, 0xFE, 0xAC, 0x00,
-	0xDE, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
-	0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
-	0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
-	0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE6, 0xFF, 0x17, 0x00,
-	0x39, 0x00, 0xD4, 0xFE, 0x7A, 0x03, 0x2F, 0xF6, 0xC7, 0x42, 0x06,
-	0x18, 0x7B, 0xF5, 0x05, 0x06, 0x8A, 0xFC, 0xCF, 0x01, 0x3C, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49,
-	0xFE, 0x67, 0x02, 0x13, 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04,
-	0x7A, 0xFC, 0xB6, 0x02, 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01,
-	0xA1, 0xFC, 0xCF, 0x05, 0xFC, 0xF5, 0x47, 0x16, 0xB0, 0x43, 0xEE,
-	0xF6, 0x0C, 0x03, 0x16, 0xFF, 0x14, 0x00, 0x29, 0x00, 0xDF, 0xFF,
-	0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46,
-	0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1,
-	0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE,
-	0xFF, 0x02, 0x00, 0x01, 0x00, 0xCE, 0xFF, 0xCC, 0x00, 0xD5, 0xFD,
-	0x16, 0x05, 0x9B, 0xF3, 0x18, 0x3E, 0xB1, 0x1F, 0x8F, 0xF3, 0xC0,
-	0x06, 0x43, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x15, 0x00, 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92,
-	0xFF, 0x94, 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04,
-	0x77, 0xFD, 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x91, 0x01, 0x1E, 0xFD, 0xBE, 0x04,
-	0x5E, 0xF8, 0xF0, 0x0E, 0xD3, 0x46, 0xCB, 0xFA, 0xF6, 0x00, 0x4B,
-	0x00, 0x69, 0xFF, 0x7D, 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA,
-	0xF2, 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD,
-	0x17, 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18,
-	0x00, 0x91, 0xFF, 0x43, 0x01, 0x0E, 0xFD, 0x40, 0x06, 0x0F, 0xF2,
-	0x5B, 0x38, 0x5C, 0x27, 0x30, 0xF2, 0x21, 0x07, 0x33, 0xFC, 0xDE,
-	0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCC, 0xFF,
-	0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
-	0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
-	0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6E,
-	0xFF, 0x4B, 0x01, 0xB9, 0xFD, 0x80, 0x03, 0xEE, 0xFA, 0x1D, 0x08,
-	0x98, 0x48, 0xA8, 0xFF, 0x95, 0xFE, 0x9A, 0x01, 0xB4, 0xFE, 0xD4,
-	0x00, 0x9C, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F,
-	0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF,
-	0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9B,
-	0x01, 0x86, 0xFC, 0xF1, 0x06, 0x7E, 0xF1, 0xC0, 0x31, 0xC2, 0x2E,
-	0x87, 0xF1, 0x17, 0x07, 0x5F, 0xFC, 0xB6, 0x01, 0x55, 0xFF, 0x2D,
-	0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00, 0x54, 0x00,
-	0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56, 0x19, 0x1E,
-	0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF, 0x35, 0x00,
-	0xFE, 0xFF, 0x1C, 0x00, 0x8E, 0xFF, 0xF9, 0x00, 0x68, 0xFE, 0x2C,
-	0x02, 0x84, 0xFD, 0xFF, 0x01, 0xE6, 0x48, 0x6E, 0x05, 0x07, 0xFC,
-	0xF1, 0x02, 0x01, 0xFE, 0x29, 0x01, 0x7B, 0xFF, 0x21, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4, 0xFC,
-	0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7, 0xB6,
-	0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A, 0x00,
-	0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3E, 0xFC, 0x2B,
-	0x07, 0xD0, 0xF1, 0x89, 0x2A, 0xA6, 0x35, 0xB4, 0xF1, 0x99, 0x06,
-	0xCD, 0xFC, 0x6D, 0x01, 0x7C, 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01,
-	0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00, 0xAE, 0xFD, 0x52, 0x05,
-	0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47, 0xF3, 0xD8, 0x06, 0x3C,
-	0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
-	0xB0, 0xFF, 0xA2, 0x00, 0x1D, 0xFF, 0xD6, 0x00, 0xFC, 0xFF, 0xBC,
-	0xFC, 0xC0, 0x47, 0xFA, 0x0B, 0x70, 0xF9, 0x3C, 0x04, 0x5C, 0xFD,
-	0x75, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
-	0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD, 0x89, 0x04, 0xCD, 0xF8,
-	0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91, 0x00, 0x83, 0x00, 0x4A,
-	0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF5, 0x06, 0xE7, 0xF2, 0xF2,
-	0x22, 0xC7, 0x3B, 0xD4, 0xF2, 0xA2, 0x05, 0x7A, 0xFD, 0x02, 0x01,
-	0xB2, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88,
-	0xFF, 0x55, 0x01, 0xF2, 0xFC, 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37,
-	0xAA, 0x28, 0x05, 0xF2, 0x27, 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41,
-	0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD2, 0xFF, 0x4C, 0x00,
-	0xCD, 0xFF, 0x94, 0xFF, 0x34, 0x02, 0x70, 0xF8, 0x2E, 0x45, 0x20,
-	0x13, 0xF6, 0xF6, 0x62, 0x05, 0xD1, 0xFC, 0xB2, 0x01, 0x46, 0xFF,
-	0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D,
-	0x01, 0xD6, 0xFD, 0x46, 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48,
-	0x98, 0x00, 0x26, 0xFE, 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96,
-	0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01,
-	0x66, 0xFC, 0x5E, 0x06, 0x9C, 0xF4, 0x40, 0x1B, 0xEF, 0x40, 0xF7,
-	0xF4, 0x35, 0x04, 0x62, 0xFE, 0x7A, 0x00, 0xF7, 0xFF, 0xF2, 0xFF,
-	0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75,
-	0xFC, 0x03, 0x07, 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1,
-	0x0A, 0x07, 0x6E, 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD,
-	0xFF, 0x05, 0x00, 0xF0, 0xFF, 0xFC, 0xFF, 0x6E, 0x00, 0x76, 0xFE,
-	0x15, 0x04, 0x2C, 0xF5, 0x49, 0x41, 0xA9, 0x1A, 0xC3, 0xF4, 0x4F,
-	0x06, 0x6C, 0xFC, 0xD9, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-	0x1A, 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5,
-	0xFD, 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03,
-	0xE4, 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB6, 0x01, 0xC8, 0xFC, 0x77, 0x05,
-	0xC7, 0xF6, 0xB1, 0x13, 0xED, 0x44, 0x26, 0xF8, 0x5D, 0x02, 0x7D,
-	0xFF, 0xDA, 0xFF, 0x46, 0x00, 0xD4, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-	0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3,
-	0xF1, 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC,
-	0x5C, 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
-	0x00, 0xB7, 0xFF, 0xF9, 0x00, 0x89, 0xFD, 0x8A, 0x05, 0xF4, 0xF2,
-	0x37, 0x3C, 0x5B, 0x22, 0x03, 0xF3, 0xED, 0x06, 0x37, 0xFC, 0xE6,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
-	0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
-	0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
-	0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B,
-	0xFF, 0x7A, 0x01, 0x50, 0xFD, 0x54, 0x04, 0x3D, 0xF9, 0x82, 0x0C,
-	0x9A, 0x47, 0x5E, 0xFC, 0x2A, 0x00, 0xBD, 0x00, 0x2B, 0xFF, 0x9B,
-	0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21, 0xC0,
-	0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD, 0xFF,
-	0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x80, 0xFF, 0x66,
-	0x01, 0xD8, 0xFC, 0x8B, 0x06, 0xC1, 0xF1, 0x27, 0x36, 0xF6, 0x29,
-	0xDF, 0xF1, 0x2A, 0x07, 0x3B, 0xFC, 0xD4, 0x01, 0x44, 0xFF, 0x32,
-	0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00, 0xEA, 0xFF,
-	0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68, 0x14, 0x8E,
-	0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF, 0x32, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x79, 0xFF, 0x2F, 0x01, 0xF4,
-	0xFD, 0x0C, 0x03, 0xD4, 0xFB, 0xE9, 0x05, 0xDE, 0x48, 0x8F, 0x01,
-	0xB6, 0xFD, 0x11, 0x02, 0x76, 0xFE, 0xF2, 0x00, 0x91, 0xFF, 0x1B,
-	0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7, 0x01, 0x73, 0xFC,
-	0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41, 0x71, 0xF5, 0xEB,
-	0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED, 0xFF, 0x06, 0x00,
-	0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB2, 0x01, 0x65, 0xFC, 0x12,
-	0x07, 0x82, 0xF1, 0x50, 0x2F, 0x38, 0x31, 0x7C, 0xF1, 0xF9, 0x06,
-	0x7E, 0xFC, 0xA1, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04,
-	0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04,
-	0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F,
-	0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
-	0x9A, 0xFF, 0xDB, 0x00, 0xA6, 0xFE, 0xB4, 0x01, 0x64, 0xFE, 0x12,
-	0x00, 0xAA, 0x48, 0x9E, 0x07, 0x21, 0xFB, 0x66, 0x03, 0xC6, 0xFD,
-	0x45, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-	0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD, 0xFC, 0x48, 0x05, 0x30, 0xF7,
-	0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8, 0x01, 0x02, 0xB2, 0xFF, 0xBD,
-	0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x24, 0x07, 0x1C, 0xF2, 0xF0,
-	0x27, 0xDF, 0x37, 0xFB, 0xF1, 0x51, 0x06, 0x01, 0xFD, 0x4B, 0x01,
-	0x8D, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
-	0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
-	0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBC, 0xFF, 0x84, 0x00,
-	0x5B, 0xFF, 0x64, 0x00, 0xC9, 0x00, 0x22, 0xFB, 0x02, 0x47, 0x64,
-	0x0E, 0x8F, 0xF8, 0xA7, 0x04, 0x29, 0xFD, 0x8C, 0x01, 0x54, 0xFF,
-	0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E,
-	0x01, 0x6B, 0xFD, 0x1D, 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47,
-	0x33, 0xFD, 0xC1, 0xFF, 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD,
-	0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-	0x40, 0xFC, 0xCB, 0x06, 0x6E, 0xF3, 0x49, 0x20, 0xB0, 0x3D, 0x73,
-	0xF3, 0x31, 0x05, 0xC4, 0xFD, 0xD6, 0x00, 0xC8, 0xFF, 0x03, 0x00,
-	0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF,
-	0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1,
-	0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD,
-	0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x2F, 0x00, 0x07, 0x00, 0x2C, 0xFF,
-	0xE6, 0x02, 0x31, 0xF7, 0xFA, 0x43, 0xB3, 0x15, 0x29, 0xF6, 0xBC,
-	0x05, 0xA9, 0xFC, 0xC2, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1,
-	0x02, 0x47, 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD,
-	0x4D, 0x02, 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFE,
-	0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01, 0x83, 0xFC, 0x16, 0x06,
-	0x51, 0xF5, 0x9B, 0x18, 0x75, 0x42, 0xF3, 0xF5, 0x9D, 0x03, 0xBF,
-	0xFE, 0x45, 0x00, 0x11, 0x00, 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
-	0x2E, 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E,
-	0xF1, 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC,
-	0x94, 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF9,
-	0xFF, 0xE3, 0xFF, 0xA1, 0x00, 0x1E, 0xFE, 0xA3, 0x04, 0x49, 0xF4,
-	0xA8, 0x3F, 0x52, 0x1D, 0x19, 0xF4, 0x90, 0x06, 0x53, 0xFC, 0xE1,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
-	0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
-	0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
-	0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C,
-	0xFF, 0xA3, 0x01, 0xF3, 0xFC, 0x18, 0x05, 0x9B, 0xF7, 0x27, 0x11,
-	0x02, 0x46, 0x7F, 0xF9, 0xA3, 0x01, 0xE8, 0xFF, 0x9F, 0xFF, 0x63,
-	0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
-	0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2,
-	0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF,
-	0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA2, 0xFF, 0x22,
-	0x01, 0x45, 0xFD, 0xF1, 0x05, 0x6D, 0xF2, 0x38, 0x3A, 0x03, 0x25,
-	0x8B, 0xF2, 0x0E, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x3A, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00, 0x7A, 0xFF,
-	0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0, 0x0F, 0x20,
-	0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF, 0x2E, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x62, 0x01, 0x87,
-	0xFD, 0xE5, 0x03, 0x21, 0xFA, 0x25, 0x0A, 0x33, 0x48, 0x0F, 0xFE,
-	0x57, 0xFF, 0x31, 0x01, 0xEC, 0xFE, 0xB9, 0x00, 0xA7, 0xFF, 0x15,
-	0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48, 0xFC,
-	0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3, 0xF3,
-	0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
-	0xFE, 0xFF, 0x23, 0x00, 0x70, 0xFF, 0x84, 0x01, 0xA9, 0xFC, 0xC7,
-	0x06, 0x91, 0xF1, 0xDC, 0x33, 0x87, 0x2C, 0xA5, 0xF1, 0x26, 0x07,
-	0x4B, 0xFC, 0xC6, 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
-	0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00, 0xFA, 0xFE, 0x3A, 0x03,
-	0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6, 0xF5, 0xE6, 0x05, 0x97,
-	0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00,
-	0x1E, 0x00, 0x84, 0xFF, 0x13, 0x01, 0x31, 0xFE, 0x95, 0x02, 0xBA,
-	0xFC, 0xCB, 0x03, 0xF7, 0x48, 0x91, 0x03, 0xD3, 0xFC, 0x88, 0x02,
-	0x38, 0xFE, 0x10, 0x01, 0x85, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
-	0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC, 0xEF, 0x05, 0xB0, 0xF5,
-	0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D, 0x03, 0xEF, 0xFE, 0x2A,
-	0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-	0x4D, 0xFF, 0xC4, 0x01, 0x4D, 0xFC, 0x25, 0x07, 0xA1, 0xF1, 0xCE,
-	0x2C, 0x99, 0x33, 0x8E, 0xF1, 0xCD, 0x06, 0xA4, 0xFC, 0x87, 0x01,
-	0x6E, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD7,
-	0xFF, 0xBA, 0x00, 0xF4, 0xFD, 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E,
-	0xA7, 0x1E, 0xCA, 0xF3, 0xAC, 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36,
-	0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBD, 0x00,
-	0xE5, 0xFE, 0x3E, 0x01, 0x3F, 0xFF, 0x41, 0xFE, 0x41, 0x48, 0xE4,
-	0x09, 0x3B, 0xFA, 0xD9, 0x03, 0x8D, 0xFD, 0x5F, 0x01, 0x66, 0xFF,
-	0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99,
-	0x01, 0x0B, 0xFD, 0xE6, 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46,
-	0x37, 0xFA, 0x42, 0x01, 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3,
-	0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01,
-	0x31, 0xFC, 0x11, 0x07, 0x7F, 0xF2, 0x4E, 0x25, 0xFD, 0x39, 0x60,
-	0xF2, 0xFB, 0x05, 0x3E, 0xFD, 0x26, 0x01, 0xA0, 0xFF, 0x12, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25,
-	0xFD, 0x1E, 0x06, 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2,
-	0x1A, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD,
-	0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x66, 0x00, 0x98, 0xFF, 0xF4, 0xFF,
-	0x8E, 0x01, 0xA7, 0xF9, 0x1D, 0x46, 0xDF, 0x10, 0xB3, 0xF7, 0x0D,
-	0x05, 0xF8, 0xFC, 0xA1, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD,
-	0x03, 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE,
-	0x6C, 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFE,
-	0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x51, 0xFC, 0x96, 0x06,
-	0x07, 0xF4, 0x9E, 0x1D, 0x77, 0x3F, 0x32, 0xF4, 0xB2, 0x04, 0x15,
-	0xFE, 0xA7, 0x00, 0xE0, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
-	0x26, 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84,
-	0xF1, 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC,
-	0xBE, 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE7,
-	0xFF, 0x14, 0x00, 0x3F, 0x00, 0xC9, 0xFE, 0x8C, 0x03, 0x11, 0xF6,
-	0x9E, 0x42, 0x50, 0x18, 0x66, 0xF5, 0x0D, 0x06, 0x86, 0xFC, 0xD0,
-	0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
-	0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
-	0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
-	0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-	0xFF, 0xC4, 0x01, 0xA5, 0xFC, 0xC5, 0x05, 0x13, 0xF6, 0xFD, 0x15,
-	0xD4, 0x43, 0x0F, 0xF7, 0xF9, 0x02, 0x21, 0xFF, 0x0D, 0x00, 0x2C,
-	0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49, 0xFF,
-	0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B, 0xC3,
-	0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76, 0xFF,
-	0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00, 0xCB, 0xFF, 0xD1,
-	0x00, 0xCC, 0xFD, 0x24, 0x05, 0x87, 0xF3, 0xE4, 0x3D, 0xFD, 0x1F,
-	0x7F, 0xF3, 0xC6, 0x06, 0x41, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00, 0x05, 0xFF,
-	0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E, 0x0B, 0xC8,
-	0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF, 0x28, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x8F, 0x01, 0x23,
-	0xFD, 0xB2, 0x04, 0x76, 0xF8, 0xAA, 0x0E, 0xED, 0x46, 0xF7, 0xFA,
-	0xDF, 0x00, 0x57, 0x00, 0x62, 0xFF, 0x80, 0x00, 0xBD, 0xFF, 0x10,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x33, 0xFC,
-	0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B, 0x9E, 0xF2, 0xCB,
-	0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x18, 0x00, 0x8F, 0xFF, 0x47, 0x01, 0x08, 0xFD, 0x49,
-	0x06, 0x05, 0xF2, 0x1D, 0x38, 0xA6, 0x27, 0x26, 0xF2, 0x23, 0x07,
-	0x33, 0xFC, 0xDD, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
-	0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01,
-	0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2,
-	0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x24, 0x00, 0x6F, 0xFF, 0x48, 0x01, 0xC0, 0xFD, 0x73, 0x03, 0x07,
-	0xFB, 0xDD, 0x07, 0xA1, 0x48, 0xDD, 0xFF, 0x7D, 0xFE, 0xA7, 0x01,
-	0xAD, 0xFE, 0xD8, 0x00, 0x9B, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
-	0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C, 0xFC, 0x78, 0x06, 0x5A, 0xF4,
-	0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4, 0x6D, 0x04, 0x3F, 0xFE, 0x8E,
-	0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-	0x62, 0xFF, 0x9E, 0x01, 0x82, 0xFC, 0xF5, 0x06, 0x7D, 0xF1, 0x7B,
-	0x31, 0x09, 0x2F, 0x84, 0xF1, 0x15, 0x07, 0x62, 0xFC, 0xB4, 0x01,
-	0x56, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
-	0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
-	0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
-	0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x8F, 0xFF, 0xF5, 0x00,
-	0x6F, 0xFE, 0x1E, 0x02, 0x9D, 0xFD, 0xC7, 0x01, 0xE1, 0x48, 0xAB,
-	0x05, 0xEE, 0xFB, 0xFE, 0x02, 0xFB, 0xFD, 0x2C, 0x01, 0x7A, 0xFF,
-	0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC,
-	0x01, 0xB8, 0xFC, 0x9A, 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44,
-	0xA9, 0xF7, 0xA2, 0x02, 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8,
-	0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD3, 0x01,
-	0x3C, 0xFC, 0x2A, 0x07, 0xD8, 0xF1, 0x3F, 0x2A, 0xE6, 0x35, 0xBB,
-	0xF1, 0x92, 0x06, 0xD2, 0xFC, 0x69, 0x01, 0x7E, 0xFF, 0x1F, 0x00,
-	0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6,
-	0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3,
-	0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x13, 0x00, 0xB1, 0xFF, 0x9F, 0x00, 0x24, 0xFF, 0xC9, 0x00,
-	0x13, 0x00, 0x8D, 0xFC, 0xAE, 0x47, 0x3E, 0x0C, 0x56, 0xF9, 0x48,
-	0x04, 0x56, 0xFD, 0x78, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E,
-	0x04, 0xE6, 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00,
-	0x90, 0x00, 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xF1, 0x06,
-	0xF5, 0xF2, 0xA7, 0x22, 0xFF, 0x3B, 0xE4, 0xF2, 0x96, 0x05, 0x81,
-	0xFD, 0xFD, 0x00, 0xB5, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF,
-	0x1C, 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC,
-	0xF1, 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC,
-	0xD8, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3,
-	0xFF, 0x49, 0x00, 0xD4, 0xFF, 0x88, 0xFF, 0x49, 0x02, 0x4B, 0xF8,
-	0x0D, 0x45, 0x68, 0x13, 0xDF, 0xF6, 0x6C, 0x05, 0xCC, 0xFC, 0xB4,
-	0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
-	0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
-	0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
-	0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-	0xFF, 0xDA, 0x01, 0x69, 0xFC, 0x57, 0x06, 0xAF, 0xF4, 0xF5, 0x1A,
-	0x1D, 0x41, 0x11, 0xF5, 0x25, 0x04, 0x6C, 0xFE, 0x74, 0x00, 0xF9,
-	0xFF, 0xF1, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF,
-	0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44,
-	0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF,
-	0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF1, 0xFF, 0xF9, 0xFF, 0x74,
-	0x00, 0x6C, 0xFE, 0x25, 0x04, 0x11, 0xF5, 0x1D, 0x41, 0xF5, 0x1A,
-	0xAF, 0xF4, 0x57, 0x06, 0x69, 0xFC, 0xDA, 0x01, 0x38, 0xFF, 0x36,
-	0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00, 0x8E, 0xFE,
-	0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1, 0x06, 0x7B,
-	0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF, 0x23, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB4, 0x01, 0xCC,
-	0xFC, 0x6C, 0x05, 0xDF, 0xF6, 0x68, 0x13, 0x0D, 0x45, 0x4B, 0xF8,
-	0x49, 0x02, 0x88, 0xFF, 0xD4, 0xFF, 0x49, 0x00, 0xD3, 0xFF, 0x0B,
-	0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37, 0xFC,
-	0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1, 0x6F,
-	0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE, 0xFF,
-	0x01, 0x00, 0x0B, 0x00, 0xB5, 0xFF, 0xFD, 0x00, 0x81, 0xFD, 0x96,
-	0x05, 0xE4, 0xF2, 0xFF, 0x3B, 0xA7, 0x22, 0xF5, 0xF2, 0xF1, 0x06,
-	0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
-	0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF, 0x90, 0x00, 0x7A, 0x00,
-	0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6, 0xF8, 0x7E, 0x04, 0x3C,
-	0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x2A, 0x00, 0x5C, 0xFF, 0x78, 0x01, 0x56, 0xFD, 0x48, 0x04, 0x56,
-	0xF9, 0x3E, 0x0C, 0xAE, 0x47, 0x8D, 0xFC, 0x13, 0x00, 0xC9, 0x00,
-	0x24, 0xFF, 0x9F, 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC, 0xDD, 0x06, 0x37, 0xF3,
-	0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F, 0x05, 0xA6, 0xFD, 0xE8,
-	0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00,
-	0x7E, 0xFF, 0x69, 0x01, 0xD2, 0xFC, 0x92, 0x06, 0xBB, 0xF1, 0xE6,
-	0x35, 0x3F, 0x2A, 0xD8, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
-	0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD8, 0xFF, 0x3A,
-	0x00, 0xF1, 0xFF, 0x54, 0xFF, 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44,
-	0xB1, 0x14, 0x77, 0xF6, 0x9A, 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42,
-	0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
-	0x2C, 0x01, 0xFB, 0xFD, 0xFE, 0x02, 0xEE, 0xFB, 0xAB, 0x05, 0xE1,
-	0x48, 0xC7, 0x01, 0x9D, 0xFD, 0x1E, 0x02, 0x6F, 0xFE, 0xF5, 0x00,
-	0x8F, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6,
-	0x01, 0x77, 0xFC, 0x33, 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41,
-	0x8D, 0xF5, 0xDA, 0x03, 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC,
-	0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x56, 0xFF, 0xB4, 0x01,
-	0x62, 0xFC, 0x15, 0x07, 0x84, 0xF1, 0x09, 0x2F, 0x7B, 0x31, 0x7D,
-	0xF1, 0xF5, 0x06, 0x82, 0xFC, 0x9E, 0x01, 0x62, 0xFF, 0x28, 0x00,
-	0xFD, 0xFF, 0x04, 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F,
-	0xFE, 0x6D, 0x04, 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4,
-	0x78, 0x06, 0x5C, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0x18, 0x00, 0x9B, 0xFF, 0xD8, 0x00, 0xAD, 0xFE, 0xA7, 0x01,
-	0x7D, 0xFE, 0xDD, 0xFF, 0xA1, 0x48, 0xDD, 0x07, 0x07, 0xFB, 0x73,
-	0x03, 0xC0, 0xFD, 0x48, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D,
-	0x05, 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01,
-	0xBE, 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0xFD,
-	0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDD, 0x01, 0x33, 0xFC, 0x23, 0x07,
-	0x26, 0xF2, 0xA6, 0x27, 0x1D, 0x38, 0x05, 0xF2, 0x49, 0x06, 0x08,
-	0xFD, 0x47, 0x01, 0x8F, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x0E, 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E,
-	0xF2, 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC,
-	0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBD,
-	0xFF, 0x80, 0x00, 0x62, 0xFF, 0x57, 0x00, 0xDF, 0x00, 0xF7, 0xFA,
-	0xED, 0x46, 0xAA, 0x0E, 0x76, 0xF8, 0xB2, 0x04, 0x23, 0xFD, 0x8F,
-	0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
-	0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
-	0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
-	0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-	0xFF, 0xE5, 0x01, 0x41, 0xFC, 0xC6, 0x06, 0x7F, 0xF3, 0xFD, 0x1F,
-	0xE4, 0x3D, 0x87, 0xF3, 0x24, 0x05, 0xCC, 0xFD, 0xD1, 0x00, 0xCB,
-	0xFF, 0x02, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76, 0xFF,
-	0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34, 0x89,
-	0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49, 0xFF,
-	0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2C, 0x00, 0x0D,
-	0x00, 0x21, 0xFF, 0xF9, 0x02, 0x0F, 0xF7, 0xD4, 0x43, 0xFD, 0x15,
-	0x13, 0xF6, 0xC5, 0x05, 0xA5, 0xFC, 0xC4, 0x01, 0x40, 0xFF, 0x33,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF, 0x1E, 0x01,
-	0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2, 0x48, 0xC6,
-	0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01, 0x8A, 0xFF,
-	0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD0, 0x01, 0x86,
-	0xFC, 0x0D, 0x06, 0x66, 0xF5, 0x50, 0x18, 0x9E, 0x42, 0x11, 0xF6,
-	0x8C, 0x03, 0xC9, 0xFE, 0x3F, 0x00, 0x14, 0x00, 0xE7, 0xFF, 0x07,
-	0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE, 0x01, 0x56, 0xFC,
-	0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32, 0x84, 0xF1, 0xE0,
-	0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF,
-	0x03, 0x00, 0xFA, 0xFF, 0xE0, 0xFF, 0xA7, 0x00, 0x15, 0xFE, 0xB2,
-	0x04, 0x32, 0xF4, 0x77, 0x3F, 0x9E, 0x1D, 0x07, 0xF4, 0x96, 0x06,
-	0x51, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
-	0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE,
-	0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3,
-	0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x2F, 0x00, 0x4C, 0xFF, 0xA1, 0x01, 0xF8, 0xFC, 0x0D, 0x05, 0xB3,
-	0xF7, 0xDF, 0x10, 0x1D, 0x46, 0xA7, 0xF9, 0x8E, 0x01, 0xF4, 0xFF,
-	0x98, 0xFF, 0x66, 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
-	0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31, 0xFC, 0x1A, 0x07, 0x56, 0xF2,
-	0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2, 0x1E, 0x06, 0x25, 0xFD, 0x35,
-	0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x12, 0x00,
-	0xA0, 0xFF, 0x26, 0x01, 0x3E, 0xFD, 0xFB, 0x05, 0x60, 0xF2, 0xFD,
-	0x39, 0x4E, 0x25, 0x7F, 0xF2, 0x11, 0x07, 0x31, 0xFC, 0xE3, 0x01,
-	0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
-	0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
-	0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
-	0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF,
-	0x5F, 0x01, 0x8D, 0xFD, 0xD9, 0x03, 0x3B, 0xFA, 0xE4, 0x09, 0x41,
-	0x48, 0x41, 0xFE, 0x3F, 0xFF, 0x3E, 0x01, 0xE5, 0xFE, 0xBD, 0x00,
-	0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-	0x01, 0x4A, 0xFC, 0xAC, 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E,
-	0xE4, 0xF3, 0xE5, 0x04, 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE,
-	0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6E, 0xFF, 0x87, 0x01,
-	0xA4, 0xFC, 0xCD, 0x06, 0x8E, 0xF1, 0x99, 0x33, 0xCE, 0x2C, 0xA1,
-	0xF1, 0x25, 0x07, 0x4D, 0xFC, 0xC4, 0x01, 0x4D, 0xFF, 0x2F, 0x00,
-	0xFD, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF,
-	0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5,
-	0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE,
-	0xFF, 0x1E, 0x00, 0x85, 0xFF, 0x10, 0x01, 0x38, 0xFE, 0x88, 0x02,
-	0xD3, 0xFC, 0x91, 0x03, 0xF7, 0x48, 0xCB, 0x03, 0xBA, 0xFC, 0x95,
-	0x02, 0x31, 0xFE, 0x13, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00, 0x00,
-	0xFE, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6,
-	0x05, 0xC6, 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03,
-	0xFA, 0xFE, 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0xFD,
-	0xFF, 0x30, 0x00, 0x4C, 0xFF, 0xC6, 0x01, 0x4B, 0xFC, 0x26, 0x07,
-	0xA5, 0xF1, 0x87, 0x2C, 0xDC, 0x33, 0x91, 0xF1, 0xC7, 0x06, 0xA9,
-	0xFC, 0x84, 0x01, 0x70, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x03, 0x00,
-	0xFF, 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF,
-	0xF3, 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC,
-	0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA7,
-	0xFF, 0xB9, 0x00, 0xEC, 0xFE, 0x31, 0x01, 0x57, 0xFF, 0x0F, 0xFE,
-	0x33, 0x48, 0x25, 0x0A, 0x21, 0xFA, 0xE5, 0x03, 0x87, 0xFD, 0x62,
-	0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
-	0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
-	0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
-	0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A,
-	0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0E, 0x07, 0x8B, 0xF2, 0x03, 0x25,
-	0x38, 0x3A, 0x6D, 0xF2, 0xF1, 0x05, 0x45, 0xFD, 0x22, 0x01, 0xA2,
-	0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF,
-	0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0,
-	0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF,
-	0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x63, 0x00, 0x9F,
-	0xFF, 0xE8, 0xFF, 0xA3, 0x01, 0x7F, 0xF9, 0x02, 0x46, 0x27, 0x11,
-	0x9B, 0xF7, 0x18, 0x05, 0xF3, 0xFC, 0xA3, 0x01, 0x4C, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF, 0x52, 0x01,
-	0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C, 0x48, 0x26,
-	0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00, 0xA0, 0xFF,
-	0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE1, 0x01, 0x53,
-	0xFC, 0x90, 0x06, 0x19, 0xF4, 0x52, 0x1D, 0xA8, 0x3F, 0x49, 0xF4,
-	0xA3, 0x04, 0x1E, 0xFE, 0xA1, 0x00, 0xE3, 0xFF, 0xF9, 0xFF, 0x04,
-	0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90, 0xFC,
-	0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1, 0x1D,
-	0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-	0x07, 0x00, 0xE8, 0xFF, 0x11, 0x00, 0x45, 0x00, 0xBF, 0xFE, 0x9D,
-	0x03, 0xF3, 0xF5, 0x75, 0x42, 0x9B, 0x18, 0x51, 0xF5, 0x16, 0x06,
-	0x83, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
-	0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE, 0x4D, 0x02, 0x45, 0xFD,
-	0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47, 0xFC, 0xD1, 0x02, 0x12,
-	0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x33, 0x00, 0x40, 0xFF, 0xC2, 0x01, 0xA9, 0xFC, 0xBC, 0x05, 0x29,
-	0xF6, 0xB3, 0x15, 0xFA, 0x43, 0x31, 0xF7, 0xE6, 0x02, 0x2C, 0xFF,
-	0x07, 0x00, 0x2F, 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
-	0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC, 0x2A, 0x07, 0xBF, 0xF1,
-	0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB, 0x06, 0xBF, 0xFC, 0x75,
-	0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00,
-	0xC8, 0xFF, 0xD6, 0x00, 0xC4, 0xFD, 0x31, 0x05, 0x73, 0xF3, 0xB0,
-	0x3D, 0x49, 0x20, 0x6E, 0xF3, 0xCB, 0x06, 0x40, 0xFC, 0xE6, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA,
-	0x00, 0x0C, 0xFF, 0xF7, 0x00, 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47,
-	0x51, 0x0B, 0xAF, 0xF9, 0x1D, 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60,
-	0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF,
-	0x8C, 0x01, 0x29, 0xFD, 0xA7, 0x04, 0x8F, 0xF8, 0x64, 0x0E, 0x02,
-	0x47, 0x22, 0xFB, 0xC9, 0x00, 0x64, 0x00, 0x5B, 0xFF, 0x84, 0x00,
-	0xBC, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5,
-	0x01, 0x33, 0xFC, 0xFF, 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B,
-	0xAD, 0xF2, 0xBF, 0x05, 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8D, 0xFF, 0x4B, 0x01,
-	0x01, 0xFD, 0x51, 0x06, 0xFB, 0xF1, 0xDF, 0x37, 0xF0, 0x27, 0x1C,
-	0xF2, 0x24, 0x07, 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00,
-	0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2,
-	0xFF, 0x01, 0x02, 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7,
-	0x48, 0x05, 0xDD, 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x45, 0x01, 0xC6, 0xFD,
-	0x66, 0x03, 0x21, 0xFB, 0x9E, 0x07, 0xAA, 0x48, 0x12, 0x00, 0x64,
-	0xFE, 0xB4, 0x01, 0xA6, 0xFE, 0xDB, 0x00, 0x9A, 0xFF, 0x19, 0x00,
-	0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70,
-	0x06, 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04,
-	0x49, 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFD,
-	0xFF, 0x29, 0x00, 0x61, 0xFF, 0xA1, 0x01, 0x7E, 0xFC, 0xF9, 0x06,
-	0x7C, 0xF1, 0x38, 0x31, 0x50, 0x2F, 0x82, 0xF1, 0x12, 0x07, 0x65,
-	0xFC, 0xB2, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00,
-	0xED, 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71,
-	0xF5, 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC,
-	0xD7, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91,
-	0xFF, 0xF2, 0x00, 0x76, 0xFE, 0x11, 0x02, 0xB6, 0xFD, 0x8F, 0x01,
-	0xDE, 0x48, 0xE9, 0x05, 0xD4, 0xFB, 0x0C, 0x03, 0xF4, 0xFD, 0x2F,
-	0x01, 0x79, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
-	0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
-	0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
-	0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44,
-	0xFF, 0xD4, 0x01, 0x3B, 0xFC, 0x2A, 0x07, 0xDF, 0xF1, 0xF6, 0x29,
-	0x27, 0x36, 0xC1, 0xF1, 0x8B, 0x06, 0xD8, 0xFC, 0x66, 0x01, 0x80,
-	0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xBD, 0xFF,
-	0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C, 0x9E,
-	0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x9B, 0x00, 0x2B,
-	0xFF, 0xBD, 0x00, 0x2A, 0x00, 0x5E, 0xFC, 0x9A, 0x47, 0x82, 0x0C,
-	0x3D, 0xF9, 0x54, 0x04, 0x50, 0xFD, 0x7A, 0x01, 0x5B, 0xFF, 0x2A,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x81, 0x01,
-	0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69, 0x47, 0xEB,
-	0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00, 0xB6, 0xFF,
-	0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37,
-	0xFC, 0xED, 0x06, 0x03, 0xF3, 0x5B, 0x22, 0x37, 0x3C, 0xF4, 0xF2,
-	0x8A, 0x05, 0x89, 0xFD, 0xF9, 0x00, 0xB7, 0xFF, 0x0A, 0x00, 0x01,
-	0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C, 0x01, 0xE6, 0xFC,
-	0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29, 0xF3, 0xF1, 0x29,
-	0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-	0x0B, 0x00, 0xD4, 0xFF, 0x46, 0x00, 0xDA, 0xFF, 0x7D, 0xFF, 0x5D,
-	0x02, 0x26, 0xF8, 0xED, 0x44, 0xB1, 0x13, 0xC7, 0xF6, 0x77, 0x05,
-	0xC8, 0xFC, 0xB6, 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03,
-	0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0,
-	0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-	0x35, 0x00, 0x38, 0xFF, 0xD9, 0x01, 0x6C, 0xFC, 0x4F, 0x06, 0xC3,
-	0xF4, 0xA9, 0x1A, 0x49, 0x41, 0x2C, 0xF5, 0x15, 0x04, 0x76, 0xFE,
-	0x6E, 0x00, 0xFC, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B,
-	0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E, 0xFC, 0x0A, 0x07, 0x7E, 0xF1,
-	0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1, 0x03, 0x07, 0x75, 0xFC, 0xA7,
-	0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF2, 0xFF,
-	0xF7, 0xFF, 0x7A, 0x00, 0x62, 0xFE, 0x35, 0x04, 0xF7, 0xF4, 0xEF,
-	0x40, 0x40, 0x1B, 0x9C, 0xF4, 0x5E, 0x06, 0x66, 0xFC, 0xDB, 0x01,
-	0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
-	0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
-	0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
-	0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF,
-	0xB2, 0x01, 0xD1, 0xFC, 0x62, 0x05, 0xF6, 0xF6, 0x20, 0x13, 0x2E,
-	0x45, 0x70, 0xF8, 0x34, 0x02, 0x94, 0xFF, 0xCD, 0xFF, 0x4C, 0x00,
-	0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA,
-	0x01, 0x36, 0xFC, 0x27, 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37,
-	0xE4, 0xF1, 0x67, 0x06, 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B,
-	0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B, 0x00, 0xB2, 0xFF, 0x02, 0x01,
-	0x7A, 0xFD, 0xA2, 0x05, 0xD4, 0xF2, 0xC7, 0x3B, 0xF2, 0x22, 0xE7,
-	0xF2, 0xF5, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
-	0xFD, 0xFF, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83,
-	0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8,
-	0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x75, 0x01, 0x5C, 0xFD,
-	0x3C, 0x04, 0x70, 0xF9, 0xFA, 0x0B, 0xC0, 0x47, 0xBC, 0xFC, 0xFC,
-	0xFF, 0xD6, 0x00, 0x1D, 0xFF, 0xA2, 0x00, 0xB0, 0xFF, 0x13, 0x00,
-	0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8,
-	0x06, 0x47, 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05,
-	0xAE, 0xFD, 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0xFE,
-	0xFF, 0x1F, 0x00, 0x7C, 0xFF, 0x6D, 0x01, 0xCD, 0xFC, 0x99, 0x06,
-	0xB4, 0xF1, 0xA6, 0x35, 0x89, 0x2A, 0xD0, 0xF1, 0x2B, 0x07, 0x3E,
-	0xFC, 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
-	0xD9, 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86,
-	0xF7, 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC,
-	0xBE, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
-	0x00, 0x7B, 0xFF, 0x29, 0x01, 0x01, 0xFE, 0xF1, 0x02, 0x07, 0xFC,
-	0x6E, 0x05, 0xE6, 0x48, 0xFF, 0x01, 0x84, 0xFD, 0x2C, 0x02, 0x68,
-	0xFE, 0xF9, 0x00, 0x8E, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-	0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
-	0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
-	0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x55,
-	0xFF, 0xB6, 0x01, 0x5F, 0xFC, 0x17, 0x07, 0x87, 0xF1, 0xC2, 0x2E,
-	0xC0, 0x31, 0x7E, 0xF1, 0xF1, 0x06, 0x86, 0xFC, 0x9B, 0x01, 0x63,
-	0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF,
-	0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94,
-	0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9C, 0xFF, 0xD4, 0x00, 0xB4,
-	0xFE, 0x9A, 0x01, 0x95, 0xFE, 0xA8, 0xFF, 0x98, 0x48, 0x1D, 0x08,
-	0xEE, 0xFA, 0x80, 0x03, 0xB9, 0xFD, 0x4B, 0x01, 0x6E, 0xFF, 0x25,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA9, 0x01,
-	0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8, 0x45, 0x1C,
-	0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00, 0xCC, 0xFF,
-	0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDE, 0x01, 0x33,
-	0xFC, 0x21, 0x07, 0x30, 0xF2, 0x5C, 0x27, 0x5B, 0x38, 0x0F, 0xF2,
-	0x40, 0x06, 0x0E, 0xFD, 0x43, 0x01, 0x91, 0xFF, 0x18, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57, 0xFD,
-	0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2, 0x06,
-	0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x10, 0x00, 0xBE, 0xFF, 0x7D, 0x00, 0x69, 0xFF, 0x4B, 0x00, 0xF6,
-	0x00, 0xCB, 0xFA, 0xD3, 0x46, 0xF0, 0x0E, 0x5E, 0xF8, 0xBE, 0x04,
-	0x1E, 0xFD, 0x91, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01, 0x77, 0xFD, 0x04, 0x04,
-	0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94, 0xFD, 0x92, 0xFF, 0x10,
-	0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x43, 0xFC, 0xC0, 0x06, 0x8F,
-	0xF3, 0xB1, 0x1F, 0x18, 0x3E, 0x9B, 0xF3, 0x16, 0x05, 0xD5, 0xFD,
-	0xCC, 0x00, 0xCE, 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22,
-	0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC, 0xB8, 0x06, 0x9C, 0xF1,
-	0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29, 0x07, 0x46, 0xFC, 0xCA,
-	0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF,
-	0x29, 0x00, 0x14, 0x00, 0x16, 0xFF, 0x0C, 0x03, 0xEE, 0xF6, 0xB0,
-	0x43, 0x47, 0x16, 0xFC, 0xF5, 0xCF, 0x05, 0xA1, 0xFC, 0xC6, 0x01,
-	0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81,
-	0xFF, 0x1B, 0x01, 0x20, 0xFE, 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04,
-	0xF4, 0x48, 0xFF, 0x02, 0x13, 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07,
-	0x01, 0x88, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
-	0xCF, 0x01, 0x8A, 0xFC, 0x05, 0x06, 0x7B, 0xF5, 0x06, 0x18, 0xC7,
-	0x42, 0x2F, 0xF6, 0x7A, 0x03, 0xD4, 0xFE, 0x39, 0x00, 0x17, 0x00,
-	0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0,
-	0x01, 0x53, 0xFC, 0x21, 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32,
-	0x86, 0xF1, 0xDB, 0x06, 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25,
-	0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDE, 0xFF, 0xAC, 0x00,
-	0x0B, 0xFE, 0xC1, 0x04, 0x1B, 0xF4, 0x47, 0x3F, 0xEA, 0x1D, 0xF5,
-	0xF3, 0x9C, 0x06, 0x4F, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x16, 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F,
-	0x01, 0x03, 0xFF, 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA,
-	0xB9, 0x03, 0x9D, 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4D, 0xFF, 0x9F, 0x01, 0xFE, 0xFC,
-	0x02, 0x05, 0xCB, 0xF7, 0x98, 0x10, 0x39, 0x46, 0xD0, 0xF9, 0x78,
-	0x01, 0x00, 0x00, 0x91, 0xFF, 0x69, 0x00, 0xC6, 0xFF, 0x0E, 0x00,
-	0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17,
-	0x07, 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06,
-	0x2C, 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF,
-	0xFF, 0x13, 0x00, 0x9E, 0xFF, 0x2B, 0x01, 0x37, 0xFD, 0x05, 0x06,
-	0x54, 0xF2, 0xC2, 0x39, 0x99, 0x25, 0x73, 0xF2, 0x14, 0x07, 0x31,
-	0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-	0xC4, 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D,
-	0xFA, 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD,
-	0x9C, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
-	0x00, 0x67, 0xFF, 0x5C, 0x01, 0x93, 0xFD, 0xCC, 0x03, 0x54, 0xFA,
-	0xA2, 0x09, 0x4F, 0x48, 0x73, 0xFE, 0x27, 0xFF, 0x4B, 0x01, 0xDE,
-	0xFE, 0xC0, 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
-	0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
-	0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6D,
-	0xFF, 0x8A, 0x01, 0x9F, 0xFC, 0xD3, 0x06, 0x8A, 0xF1, 0x57, 0x33,
-	0x17, 0x2D, 0x9C, 0xF1, 0x24, 0x07, 0x4F, 0xFC, 0xC3, 0x01, 0x4E,
-	0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE4, 0xFF, 0x1B, 0x00,
-	0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43, 0x96,
-	0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x86, 0xFF, 0x0C, 0x01, 0x3E,
-	0xFE, 0x7B, 0x02, 0xED, 0xFC, 0x56, 0x03, 0xF5, 0x48, 0x06, 0x04,
-	0xA1, 0xFC, 0xA3, 0x02, 0x2A, 0xFE, 0x16, 0x01, 0x83, 0xFF, 0x1F,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC8, 0x01,
-	0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77, 0x43, 0xBD,
-	0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00, 0xE1, 0xFF,
-	0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC8, 0x01, 0x49,
-	0xFC, 0x27, 0x07, 0xAB, 0xF1, 0x3E, 0x2C, 0x1E, 0x34, 0x95, 0xF1,
-	0xC1, 0x06, 0xAE, 0xFC, 0x81, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE,
-	0xFF, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4, 0x00, 0xE2, 0xFD,
-	0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F, 0xA8, 0xF3, 0xB8,
-	0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x15, 0x00, 0xA8, 0xFF, 0xB6, 0x00, 0xF3, 0xFE, 0x24, 0x01, 0x6E,
-	0xFF, 0xDE, 0xFD, 0x25, 0x48, 0x68, 0x0A, 0x08, 0xFA, 0xF2, 0x03,
-	0x81, 0xFD, 0x65, 0x01, 0x64, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04,
-	0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38,
-	0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0B, 0x07, 0x97,
-	0xF2, 0xB8, 0x24, 0x71, 0x3A, 0x7B, 0xF2, 0xE6, 0x05, 0x4C, 0xFD,
-	0x1D, 0x01, 0xA4, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16,
-	0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18, 0xFD, 0x32, 0x06, 0x1F, 0xF2,
-	0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2, 0x1E, 0x07, 0x32, 0xFC, 0xDF,
-	0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
-	0x5F, 0x00, 0xA5, 0xFF, 0xDC, 0xFF, 0xB8, 0x01, 0x57, 0xF9, 0xE5,
-	0x45, 0x6E, 0x11, 0x83, 0xF7, 0x23, 0x05, 0xEE, 0xFC, 0xA6, 0x01,
-	0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C,
-	0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
-	0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
-	0x00, 0x9E, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xE0, 0x01, 0x56, 0xFC, 0x89, 0x06, 0x2B, 0xF4, 0x06, 0x1D, 0xD7,
-	0x3F, 0x61, 0xF4, 0x94, 0x04, 0x27, 0xFE, 0x9C, 0x00, 0xE6, 0xFF,
-	0xF8, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97,
-	0x01, 0x8C, 0xFC, 0xEA, 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E,
-	0x8B, 0xF1, 0x1B, 0x07, 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D,
-	0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9, 0xFF, 0x0E, 0x00, 0x4B, 0x00,
-	0xB4, 0xFE, 0xAF, 0x03, 0xD5, 0xF5, 0x4D, 0x42, 0xE6, 0x18, 0x3C,
-	0xF5, 0x1F, 0x06, 0x7F, 0xFC, 0xD3, 0x01, 0x3B, 0xFF, 0x35, 0x00,
-	0xFE, 0xFF, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F,
-	0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC,
-	0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xC1, 0x01, 0xAD, 0xFC,
-	0xB2, 0x05, 0x3F, 0xF6, 0x69, 0x15, 0x1F, 0x44, 0x53, 0xF7, 0xD3,
-	0x02, 0x38, 0xFF, 0x01, 0x00, 0x33, 0x00, 0xDB, 0xFF, 0x09, 0x00,
-	0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A,
-	0x07, 0xC6, 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06,
-	0xC4, 0xFC, 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02,
-	0x00, 0x04, 0x00, 0xC6, 0xFF, 0xDB, 0x00, 0xBB, 0xFD, 0x3E, 0x05,
-	0x60, 0xF3, 0x7B, 0x3D, 0x94, 0x20, 0x5E, 0xF3, 0xD0, 0x06, 0x3E,
-	0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00,
-	0xAE, 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03,
-	0xFD, 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD,
-	0x71, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C,
-	0x00, 0x55, 0xFF, 0x8A, 0x01, 0x2E, 0xFD, 0x9B, 0x04, 0xA8, 0xF8,
-	0x1F, 0x0E, 0x1A, 0x47, 0x4E, 0xFB, 0xB3, 0x00, 0x70, 0x00, 0x54,
-	0xFF, 0x87, 0x00, 0xBB, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
-	0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
-	0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8B,
-	0xFF, 0x4F, 0x01, 0xFB, 0xFC, 0x5A, 0x06, 0xF2, 0xF1, 0xA0, 0x37,
-	0x3A, 0x28, 0x13, 0xF2, 0x25, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40,
-	0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00,
-	0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2,
-	0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF,
-	0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x42,
-	0x01, 0xCD, 0xFD, 0x59, 0x03, 0x3B, 0xFB, 0x5E, 0x07, 0xB3, 0x48,
-	0x48, 0x00, 0x4B, 0xFE, 0xC2, 0x01, 0x9F, 0xFE, 0xDE, 0x00, 0x98,
-	0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDD, 0x01,
-	0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB, 0x40, 0xD0,
-	0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF, 0xF4, 0xFF,
-	0x05, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA3, 0x01, 0x7A,
-	0xFC, 0xFD, 0x06, 0x7C, 0xF1, 0xF2, 0x30, 0x96, 0x2F, 0x80, 0xF1,
-	0x0F, 0x07, 0x69, 0xFC, 0xB0, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD,
-	0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85, 0xFE,
-	0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4, 0x43,
-	0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-	0x1B, 0x00, 0x92, 0xFF, 0xEF, 0x00, 0x7D, 0xFE, 0x04, 0x02, 0xCF,
-	0xFD, 0x58, 0x01, 0xD7, 0x48, 0x26, 0x06, 0xBB, 0xFB, 0x19, 0x03,
-	0xED, 0xFD, 0x32, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
-	0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01, 0xC1, 0xFC, 0x86, 0x05,
-	0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0, 0xF7, 0x7B, 0x02, 0x6B,
-	0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-	0x33, 0x00, 0x43, 0xFF, 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE7,
-	0xF1, 0xAC, 0x29, 0x66, 0x36, 0xC9, 0xF1, 0x83, 0x06, 0xDD, 0xFC,
-	0x62, 0x01, 0x81, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x08,
-	0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD, 0x78, 0x05, 0x0E, 0xF3,
-	0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6, 0x06, 0x38, 0xFC, 0xE6,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB4, 0xFF,
-	0x98, 0x00, 0x32, 0xFF, 0xB0, 0x00, 0x41, 0x00, 0x30, 0xFC, 0x86,
-	0x47, 0xC6, 0x0C, 0x24, 0xF9, 0x60, 0x04, 0x4B, 0xFD, 0x7D, 0x01,
-	0x5A, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x5A,
-	0xFF, 0x7E, 0x01, 0x48, 0xFD, 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C,
-	0x7C, 0x47, 0x19, 0xFC, 0x4D, 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96,
-	0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xE6, 0x01, 0x38, 0xFC, 0xE9, 0x06, 0x12, 0xF3, 0x10, 0x22, 0x6E,
-	0x3C, 0x05, 0xF3, 0x7E, 0x05, 0x91, 0xFD, 0xF4, 0x00, 0xBA, 0xFF,
-	0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60,
-	0x01, 0xE0, 0xFC, 0x7F, 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29,
-	0xEB, 0xF1, 0x2A, 0x07, 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33,
-	0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5, 0xFF, 0x42, 0x00, 0xE1, 0xFF,
-	0x71, 0xFF, 0x71, 0x02, 0x02, 0xF8, 0xCC, 0x44, 0xFA, 0x13, 0xB0,
-	0xF6, 0x81, 0x05, 0xC3, 0xFC, 0xB8, 0x01, 0x44, 0xFF, 0x31, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA,
-	0xFD, 0x1F, 0x03, 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01,
-	0xDC, 0xFD, 0xFD, 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B,
-	0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x6F, 0xFC,
-	0x47, 0x06, 0xD7, 0xF4, 0x5D, 0x1A, 0x74, 0x41, 0x48, 0xF5, 0x04,
-	0x04, 0x80, 0xFE, 0x69, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
-	0xFD, 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D,
-	0x07, 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06,
-	0x78, 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05,
-	0x00, 0xF3, 0xFF, 0xF4, 0xFF, 0x80, 0x00, 0x58, 0xFE, 0x46, 0x04,
-	0xDD, 0xF4, 0xC3, 0x40, 0x8C, 0x1B, 0x89, 0xF4, 0x66, 0x06, 0x63,
-	0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
-	0x98, 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62,
-	0x00, 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD,
-	0x40, 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-	0x00, 0x47, 0xFF, 0xB0, 0x01, 0xD6, 0xFC, 0x58, 0x05, 0x0D, 0xF7,
-	0xD7, 0x12, 0x4E, 0x45, 0x96, 0xF8, 0x20, 0x02, 0xA0, 0xFF, 0xC7,
-	0xFF, 0x4F, 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
-	0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
-	0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 0xB0,
-	0xFF, 0x07, 0x01, 0x72, 0xFD, 0xAE, 0x05, 0xC4, 0xF2, 0x90, 0x3B,
-	0x3F, 0x23, 0xD9, 0xF2, 0xF9, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89, 0x00,
-	0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47, 0xFC,
-	0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56, 0xFF,
-	0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5E, 0xFF, 0x72,
-	0x01, 0x62, 0xFD, 0x2F, 0x04, 0x89, 0xF9, 0xB6, 0x0B, 0xD2, 0x47,
-	0xEB, 0xFC, 0xE4, 0xFF, 0xE3, 0x00, 0x16, 0xFF, 0xA5, 0x00, 0xAF,
-	0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-	0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61, 0x3D, 0x56,
-	0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF, 0x05, 0x00,
-	0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x7A, 0xFF, 0x70, 0x01, 0xC7,
-	0xFC, 0xA0, 0x06, 0xAE, 0xF1, 0x65, 0x35, 0xD1, 0x2A, 0xCA, 0xF1,
-	0x2A, 0x07, 0x40, 0xFC, 0xD0, 0x01, 0x47, 0xFF, 0x32, 0x00, 0xFD,
-	0xFF, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x3D, 0xFF,
-	0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15, 0x4A, 0xF6, 0xAD,
-	0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF, 0x26, 0x01, 0x08, 0xFE, 0xE4,
-	0x02, 0x21, 0xFC, 0x31, 0x05, 0xEB, 0x48, 0x37, 0x02, 0x6B, 0xFD,
-	0x39, 0x02, 0x61, 0xFE, 0xFC, 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFE,
-	0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06,
-	0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF,
-	0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFD, 0xFF,
-	0x2D, 0x00, 0x54, 0xFF, 0xB8, 0x01, 0x5D, 0xFC, 0x1A, 0x07, 0x8A,
-	0xF1, 0x7B, 0x2E, 0x04, 0x32, 0x7F, 0xF1, 0xEC, 0x06, 0x8A, 0xFC,
-	0x98, 0x01, 0x65, 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8,
-	0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C, 0xFE, 0x8C, 0x04, 0x6D, 0xF4,
-	0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4, 0x85, 0x06, 0x57, 0xFC, 0xE0,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9E, 0xFF,
-	0xD1, 0x00, 0xBB, 0xFE, 0x8D, 0x01, 0xAE, 0xFE, 0x74, 0xFF, 0x8D,
-	0x48, 0x5D, 0x08, 0xD4, 0xFA, 0x8D, 0x03, 0xB3, 0xFD, 0x4E, 0x01,
-	0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
-	0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
-	0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
-	0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-	0xDF, 0x01, 0x32, 0xFC, 0x1F, 0x07, 0x3B, 0xF2, 0x11, 0x27, 0x97,
-	0x38, 0x19, 0xF2, 0x36, 0x06, 0x15, 0xFD, 0x3F, 0x01, 0x93, 0xFF,
-	0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B,
-	0x01, 0x50, 0xFD, 0xE1, 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24,
-	0x9D, 0xF2, 0x09, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x7A, 0x00, 0x70, 0xFF,
-	0x3E, 0x00, 0x0C, 0x01, 0xA1, 0xFA, 0xBB, 0x46, 0x36, 0x0F, 0x45,
-	0xF8, 0xC9, 0x04, 0x18, 0xFD, 0x93, 0x01, 0x52, 0xFF, 0x2D, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D,
-	0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD,
-	0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x45, 0xFC,
-	0xBB, 0x06, 0xA0, 0xF3, 0x64, 0x1F, 0x4A, 0x3E, 0xB0, 0xF3, 0x08,
-	0x05, 0xDE, 0xFD, 0xC7, 0x00, 0xD0, 0xFF, 0x00, 0x00, 0x02, 0x00,
-	0xFE, 0xFF, 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE,
-	0x06, 0x97, 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07,
-	0x48, 0xFC, 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
-	0x00, 0xE0, 0xFF, 0x26, 0x00, 0x1A, 0x00, 0x0B, 0xFF, 0x1E, 0x03,
-	0xCD, 0xF6, 0x89, 0x43, 0x91, 0x16, 0xE7, 0xF5, 0xD8, 0x05, 0x9D,
-	0xFC, 0xC7, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x1F, 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94,
-	0xFC, 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02,
-	0x42, 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
-	0x00, 0x3C, 0xFF, 0xCD, 0x01, 0x8E, 0xFC, 0xFC, 0x05, 0x90, 0xF5,
-	0xBB, 0x17, 0xEE, 0x42, 0x4E, 0xF6, 0x68, 0x03, 0xDF, 0xFE, 0x33,
-	0x00, 0x1A, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-	0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
-	0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
-	0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFC, 0xFF, 0xDB,
-	0xFF, 0xB2, 0x00, 0x02, 0xFE, 0xCF, 0x04, 0x05, 0xF4, 0x16, 0x3F,
-	0x36, 0x1E, 0xE4, 0xF3, 0xA3, 0x06, 0x4D, 0xFC, 0xE3, 0x01, 0x36,
-	0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00,
-	0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81,
-	0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF,
-	0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9D,
-	0x01, 0x03, 0xFD, 0xF7, 0x04, 0xE3, 0xF7, 0x51, 0x10, 0x55, 0x46,
-	0xF9, 0xF9, 0x63, 0x01, 0x0D, 0x00, 0x8B, 0xFF, 0x6D, 0x00, 0xC5,
-	0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01,
-	0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5, 0x39, 0x4D,
-	0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF, 0x13, 0x00,
-	0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x9C, 0xFF, 0x2F, 0x01, 0x30,
-	0xFD, 0x10, 0x06, 0x47, 0xF2, 0x87, 0x39, 0xE5, 0x25, 0x67, 0xF2,
-	0x16, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD,
-	0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06, 0x00,
-	0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7, 0xFC,
-	0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x59, 0x01, 0x99, 0xFD, 0xC0,
-	0x03, 0x6E, 0xFA, 0x61, 0x09, 0x5D, 0x48, 0xA6, 0xFE, 0x0F, 0xFF,
-	0x58, 0x01, 0xD7, 0xFE, 0xC3, 0x00, 0xA3, 0xFF, 0x16, 0x00, 0xFE,
-	0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4E, 0xFC, 0xA0, 0x06,
-	0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10, 0xF4, 0xC8, 0x04, 0x07,
-	0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
-	0x25, 0x00, 0x6B, 0xFF, 0x8D, 0x01, 0x9B, 0xFC, 0xD8, 0x06, 0x87,
-	0xF1, 0x13, 0x33, 0x5E, 0x2D, 0x98, 0xF1, 0x22, 0x07, 0x52, 0xFC,
-	0xC1, 0x01, 0x4F, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE5,
-	0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE, 0x71, 0x03, 0x3F, 0xF6,
-	0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00, 0x06, 0x8C, 0xFC, 0xCE,
-	0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF,
-	0x09, 0x01, 0x45, 0xFE, 0x6E, 0x02, 0x06, 0xFD, 0x1C, 0x03, 0xF4,
-	0x48, 0x41, 0x04, 0x87, 0xFC, 0xB0, 0x02, 0x23, 0xFE, 0x19, 0x01,
-	0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F,
-	0xFF, 0xC6, 0x01, 0x9F, 0xFC, 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16,
-	0x9E, 0x43, 0xDD, 0xF6, 0x15, 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28,
-	0x00, 0xDF, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-	0xCA, 0x01, 0x47, 0xFC, 0x28, 0x07, 0xB0, 0xF1, 0xF5, 0x2B, 0x60,
-	0x34, 0x9A, 0xF1, 0xBB, 0x06, 0xB3, 0xFC, 0x7D, 0x01, 0x73, 0xFF,
-	0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9,
-	0x00, 0xDA, 0xFD, 0x0F, 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F,
-	0x97, 0xF3, 0xBD, 0x06, 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x15, 0x00, 0xAA, 0xFF, 0xB3, 0x00, 0xFA, 0xFE,
-	0x17, 0x01, 0x86, 0xFF, 0xAC, 0xFD, 0x16, 0x48, 0xAA, 0x0A, 0xEE,
-	0xF9, 0xFE, 0x03, 0x7A, 0xFD, 0x67, 0x01, 0x63, 0xFF, 0x28, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B,
-	0xFD, 0xC4, 0x04, 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA,
-	0x01, 0x01, 0x44, 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC,
-	0x08, 0x07, 0xA4, 0xF2, 0x6D, 0x24, 0xAD, 0x3A, 0x88, 0xF2, 0xDB,
-	0x05, 0x53, 0xFD, 0x19, 0x01, 0xA7, 0xFF, 0x10, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B,
-	0x06, 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07,
-	0x33, 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D,
-	0x00, 0xCB, 0xFF, 0x5C, 0x00, 0xAC, 0xFF, 0xD0, 0xFF, 0xCD, 0x01,
-	0x30, 0xF9, 0xC8, 0x45, 0xB6, 0x11, 0x6B, 0xF7, 0x2D, 0x05, 0xE9,
-	0xFC, 0xA8, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x25, 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1,
-	0xFA, 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01,
-	0xB8, 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
-	0x00, 0x37, 0xFF, 0xE0, 0x01, 0x58, 0xFC, 0x82, 0x06, 0x3E, 0xF4,
-	0xBA, 0x1C, 0x07, 0x40, 0x79, 0xF4, 0x84, 0x04, 0x31, 0xFE, 0x96,
-	0x00, 0xE8, 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-	0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
-	0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
-	0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEA, 0xFF, 0x0B,
-	0x00, 0x51, 0x00, 0xAA, 0xFE, 0xC0, 0x03, 0xB8, 0xF5, 0x21, 0x42,
-	0x31, 0x19, 0x28, 0xF5, 0x27, 0x06, 0x7C, 0xFC, 0xD4, 0x01, 0x3A,
-	0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA, 0x00,
-	0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48, 0x50,
-	0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C, 0xFF,
-	0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xBF,
-	0x01, 0xB2, 0xFC, 0xA9, 0x05, 0x55, 0xF6, 0x20, 0x15, 0x42, 0x44,
-	0x75, 0xF7, 0xBF, 0x02, 0x43, 0xFF, 0xFA, 0xFF, 0x36, 0x00, 0xDA,
-	0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01,
-	0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86, 0x35, 0xB1,
-	0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF, 0x20, 0x00,
-	0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE0, 0x00, 0xB3,
-	0xFD, 0x4B, 0x05, 0x4D, 0xF3, 0x45, 0x3D, 0xE0, 0x20, 0x4F, 0xF3,
-	0xD5, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19, 0xFF, 0xDD, 0x00,
-	0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B, 0x7C, 0xF9, 0x35,
-	0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x2C, 0x00, 0x56, 0xFF, 0x87, 0x01, 0x34, 0xFD, 0x8F,
-	0x04, 0xC0, 0xF8, 0xD9, 0x0D, 0x31, 0x47, 0x7B, 0xFB, 0x9C, 0x00,
-	0x7D, 0x00, 0x4D, 0xFF, 0x8A, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06,
-	0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76,
-	0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF,
-	0x1A, 0x00, 0x89, 0xFF, 0x53, 0x01, 0xF5, 0xFC, 0x63, 0x06, 0xE9,
-	0xF1, 0x63, 0x37, 0x85, 0x28, 0x09, 0xF2, 0x27, 0x07, 0x35, 0xFC,
-	0xDA, 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD1,
-	0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A, 0xFF, 0x2A, 0x02, 0x83, 0xF8,
-	0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7, 0x5D, 0x05, 0xD3, 0xFC, 0xB1,
-	0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
-	0x73, 0xFF, 0x3F, 0x01, 0xD3, 0xFD, 0x4C, 0x03, 0x54, 0xFB, 0x1F,
-	0x07, 0xBB, 0x48, 0x7D, 0x00, 0x33, 0xFE, 0xCF, 0x01, 0x98, 0xFE,
-	0xE2, 0x00, 0x97, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-	0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
-	0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
-	0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5E, 0xFF,
-	0xA6, 0x01, 0x76, 0xFC, 0x01, 0x07, 0x7D, 0xF1, 0xAD, 0x30, 0xDC,
-	0x2F, 0x7F, 0xF1, 0x0C, 0x07, 0x6C, 0xFC, 0xAD, 0x01, 0x5A, 0xFF,
-	0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C,
-	0x00, 0x7B, 0xFE, 0x0C, 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A,
-	0xCD, 0xF4, 0x4B, 0x06, 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35,
-	0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x93, 0xFF, 0xEC, 0x00, 0x83, 0xFE,
-	0xF7, 0x01, 0xE8, 0xFD, 0x21, 0x01, 0xD2, 0x48, 0x64, 0x06, 0xA1,
-	0xFB, 0x26, 0x03, 0xE7, 0xFD, 0x35, 0x01, 0x76, 0xFF, 0x22, 0x00,
-	0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5,
-	0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8,
-	0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B,
-	0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x39, 0xFC,
-	0x29, 0x07, 0xEF, 0xF1, 0x62, 0x29, 0xA5, 0x36, 0xD0, 0xF1, 0x7B,
-	0x06, 0xE3, 0xFC, 0x5E, 0x01, 0x83, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
-	0x01, 0x00, 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84,
-	0x05, 0xFD, 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06,
-	0x37, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12,
-	0x00, 0xB5, 0xFF, 0x94, 0x00, 0x39, 0xFF, 0xA3, 0x00, 0x58, 0x00,
-	0x02, 0xFC, 0x73, 0x47, 0x0B, 0x0D, 0x0B, 0xF9, 0x6C, 0x04, 0x45,
-	0xFD, 0x80, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x2A, 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31,
-	0xF9, 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00,
-	0x2E, 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36,
-	0x00, 0x37, 0xFF, 0xE6, 0x01, 0x39, 0xFC, 0xE4, 0x06, 0x21, 0xF3,
-	0xC4, 0x21, 0xA5, 0x3C, 0x16, 0xF3, 0x72, 0x05, 0x9A, 0xFD, 0xEF,
-	0x00, 0xBC, 0xFF, 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-	0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
-	0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
-	0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD6, 0xFF, 0x3F,
-	0x00, 0xE7, 0xFF, 0x65, 0xFF, 0x85, 0x02, 0xDE, 0xF7, 0xA9, 0x44,
-	0x43, 0x14, 0x99, 0xF6, 0x8B, 0x05, 0xBF, 0xFC, 0xBA, 0x01, 0x43,
-	0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF,
-	0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB,
-	0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00,
-	0x91, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
-	0x01, 0x72, 0xFC, 0x3F, 0x06, 0xEB, 0xF4, 0x12, 0x1A, 0xA1, 0x41,
-	0x63, 0xF5, 0xF3, 0x03, 0x8A, 0xFE, 0x63, 0x00, 0x02, 0x00, 0xEE,
-	0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF, 0xB1, 0x01,
-	0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15, 0x31, 0x7C,
-	0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF, 0x29, 0x00,
-	0xFD, 0xFF, 0x04, 0x00, 0xF4, 0xFF, 0xF1, 0xFF, 0x85, 0x00, 0x4E,
-	0xFE, 0x56, 0x04, 0xC3, 0xF4, 0x95, 0x40, 0xD8, 0x1B, 0x76, 0xF4,
-	0x6D, 0x06, 0x60, 0xFC, 0xDD, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB, 0x01,
-	0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB, 0x60,
-	0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAE, 0x01, 0xDB, 0xFC, 0x4D,
-	0x05, 0x24, 0xF7, 0x8E, 0x12, 0x6D, 0x45, 0xBC, 0xF8, 0x0C, 0x02,
-	0xAC, 0xFF, 0xC0, 0xFF, 0x52, 0x00, 0xCF, 0xFF, 0x0C, 0x00, 0xFD,
-	0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x25, 0x07,
-	0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7, 0xF1, 0x56, 0x06, 0xFE,
-	0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0x0D, 0x00, 0xAE, 0xFF, 0x0B, 0x01, 0x6A, 0xFD, 0xBA, 0x05, 0xB4,
-	0xF2, 0x58, 0x3B, 0x8A, 0x23, 0xCB, 0xF2, 0xFD, 0x06, 0x34, 0xFC,
-	0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBB,
-	0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00, 0xBE, 0x00, 0x38, 0xFB,
-	0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1, 0x04, 0x2B, 0xFD, 0x8B,
-	0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00,
-	0x5F, 0xFF, 0x70, 0x01, 0x68, 0xFD, 0x23, 0x04, 0xA2, 0xF9, 0x73,
-	0x0B, 0xE4, 0x47, 0x1B, 0xFD, 0xCD, 0xFF, 0xF0, 0x00, 0x0F, 0xFF,
-	0xA9, 0x00, 0xAE, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-	0xFF, 0xE6, 0x01, 0x3F, 0xFC, 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20,
-	0x96, 0x3D, 0x69, 0xF3, 0x38, 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7,
-	0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x78, 0xFF,
-	0x74, 0x01, 0xC2, 0xFC, 0xA7, 0x06, 0xA8, 0xF1, 0x25, 0x35, 0x1B,
-	0x2B, 0xC2, 0xF1, 0x2A, 0x07, 0x41, 0xFC, 0xCE, 0x01, 0x47, 0xFF,
-	0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04,
-	0x00, 0x32, 0xFF, 0xDC, 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15,
-	0x34, 0xF6, 0xB7, 0x05, 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x23, 0x01,
-	0x0F, 0xFE, 0xD7, 0x02, 0x3B, 0xFC, 0xF5, 0x04, 0xED, 0x48, 0x70,
-	0x02, 0x52, 0xFD, 0x46, 0x02, 0x5A, 0xFE, 0xFF, 0x00, 0x8B, 0xFF,
-	0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81,
-	0xFC, 0x1A, 0x06, 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5,
-	0xA6, 0x03, 0xB9, 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07,
-	0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x53, 0xFF, 0xBB, 0x01, 0x5A, 0xFC,
-	0x1C, 0x07, 0x8D, 0xF1, 0x34, 0x2E, 0x48, 0x32, 0x81, 0xF1, 0xE7,
-	0x06, 0x8E, 0xFC, 0x96, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
-	0x04, 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B,
-	0x04, 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06,
-	0x55, 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
-	0x00, 0x9F, 0xFF, 0xCE, 0x00, 0xC2, 0xFE, 0x80, 0x01, 0xC6, 0xFE,
-	0x40, 0xFF, 0x81, 0x48, 0x9E, 0x08, 0xBA, 0xFA, 0x9A, 0x03, 0xAC,
-	0xFD, 0x51, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x2F, 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F,
-	0xF7, 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF,
-	0xA2, 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35,
-	0x00, 0x3D, 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1D, 0x07, 0x45, 0xF2,
-	0xC6, 0x26, 0xD3, 0x38, 0x24, 0xF2, 0x2D, 0x06, 0x1B, 0xFD, 0x3B,
-	0x01, 0x95, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00,
-	0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
-	0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
-	0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC1, 0xFF, 0x76,
-	0x00, 0x76, 0xFF, 0x32, 0x00, 0x22, 0x01, 0x76, 0xFA, 0xA3, 0x46,
-	0x7D, 0x0F, 0x2C, 0xF8, 0xD5, 0x04, 0x13, 0xFD, 0x96, 0x01, 0x51,
-	0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64, 0xFF,
-	0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A, 0x2C,
-	0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8, 0x00,
-	0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-	0x01, 0x47, 0xFC, 0xB5, 0x06, 0xB0, 0xF3, 0x19, 0x1F, 0x7E, 0x3E,
-	0xC4, 0xF3, 0xFA, 0x04, 0xE7, 0xFD, 0xC1, 0x00, 0xD3, 0xFF, 0xFF,
-	0xFF, 0x02, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF, 0x82, 0x01,
-	0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62, 0x2C, 0xA8,
-	0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF, 0x30, 0x00,
-	0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF, 0x23, 0x00, 0x20, 0x00, 0x00,
-	0xFF, 0x31, 0x03, 0xAD, 0xF6, 0x65, 0x43, 0xDC, 0x16, 0xD1, 0xF5,
-	0xE1, 0x05, 0x99, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14, 0x01, 0x2D, 0xFE,
-	0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48, 0x73, 0x03, 0xE0,
-	0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86, 0xFF, 0x1E, 0x00,
-	0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCC, 0x01, 0x91, 0xFC, 0xF3,
-	0x05, 0xA6, 0xF5, 0x70, 0x17, 0x17, 0x43, 0x6D, 0xF6, 0x56, 0x03,
-	0xEA, 0xFE, 0x2D, 0x00, 0x1D, 0x00, 0xE4, 0xFF, 0x08, 0x00, 0xFD,
-	0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07,
-	0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2,
-	0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00,
-	0xFD, 0xFF, 0xD8, 0xFF, 0xB7, 0x00, 0xF9, 0xFD, 0xDE, 0x04, 0xEF,
-	0xF3, 0xE4, 0x3E, 0x81, 0x1E, 0xD2, 0xF3, 0xA9, 0x06, 0x4B, 0xFC,
-	0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA5,
-	0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45, 0x01, 0x33, 0xFF, 0x5A, 0xFE,
-	0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA, 0xD2, 0x03, 0x90, 0xFD, 0x5E,
-	0x01, 0x66, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
-	0x4F, 0xFF, 0x9A, 0x01, 0x08, 0xFD, 0xEB, 0x04, 0xFC, 0xF7, 0x0A,
-	0x10, 0x70, 0x46, 0x22, 0xFA, 0x4D, 0x01, 0x19, 0x00, 0x84, 0xFF,
-	0x70, 0x00, 0xC4, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
-	0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
-	0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
-	0xFF, 0x13, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x99, 0xFF,
-	0x33, 0x01, 0x29, 0xFD, 0x1A, 0x06, 0x3B, 0xF2, 0x4B, 0x39, 0x30,
-	0x26, 0x5B, 0xF2, 0x19, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF,
-	0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95,
-	0xFF, 0xFA, 0xFF, 0x83, 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10,
-	0xBF, 0xF7, 0x07, 0x05, 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x56, 0x01,
-	0xA0, 0xFD, 0xB3, 0x03, 0x87, 0xFA, 0x1F, 0x09, 0x6A, 0x48, 0xD9,
-	0xFE, 0xF6, 0xFE, 0x65, 0x01, 0xD0, 0xFE, 0xC7, 0x00, 0xA2, 0xFF,
-	0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50,
-	0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4,
-	0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03,
-	0x00, 0xFD, 0xFF, 0x26, 0x00, 0x69, 0xFF, 0x90, 0x01, 0x96, 0xFC,
-	0xDD, 0x06, 0x85, 0xF1, 0xD0, 0x32, 0xA6, 0x2D, 0x94, 0xF1, 0x20,
-	0x07, 0x54, 0xFC, 0xBF, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-	0x07, 0x00, 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83,
-	0x03, 0x20, 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06,
-	0x88, 0xFC, 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
-	0x00, 0x89, 0xFF, 0x06, 0x01, 0x4C, 0xFE, 0x60, 0x02, 0x1F, 0xFD,
-	0xE2, 0x02, 0xF3, 0x48, 0x7D, 0x04, 0x6E, 0xFC, 0xBD, 0x02, 0x1C,
-	0xFE, 0x1C, 0x01, 0x80, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0x33, 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07,
-	0xF6, 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF,
-	0x11, 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
-	0x00, 0x49, 0xFF, 0xCB, 0x01, 0x45, 0xFC, 0x29, 0x07, 0xB6, 0xF1,
-	0xAD, 0x2B, 0xA2, 0x34, 0x9E, 0xF1, 0xB4, 0x06, 0xB8, 0xFC, 0x7A,
-	0x01, 0x75, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00,
-	0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
-	0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAB, 0xFF, 0xAF,
-	0x00, 0x01, 0xFF, 0x0A, 0x01, 0x9E, 0xFF, 0x7C, 0xFD, 0x03, 0x48,
-	0xED, 0x0A, 0xD5, 0xF9, 0x0A, 0x04, 0x74, 0xFD, 0x6A, 0x01, 0x62,
-	0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF,
-	0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1,
-	0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00,
-	0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-	0x01, 0x33, 0xFC, 0x04, 0x07, 0xB1, 0xF2, 0x21, 0x24, 0xE6, 0x3A,
-	0x97, 0xF2, 0xD0, 0x05, 0x5B, 0xFD, 0x15, 0x01, 0xA9, 0xFF, 0x0F,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF, 0x45, 0x01,
-	0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80, 0x27, 0x2B,
-	0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF, 0x34, 0x00,
-	0xFD, 0xFF, 0x0D, 0x00, 0xCD, 0xFF, 0x59, 0x00, 0xB3, 0xFF, 0xC4,
-	0xFF, 0xE2, 0x01, 0x09, 0xF9, 0xAA, 0x45, 0xFE, 0x11, 0x54, 0xF7,
-	0x38, 0x05, 0xE4, 0xFC, 0xAA, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC, 0xFD,
-	0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF, 0x89,
-	0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18, 0x00,
-	0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5B, 0xFC, 0x7B,
-	0x06, 0x50, 0xF4, 0x6E, 0x1C, 0x36, 0x40, 0x92, 0xF4, 0x75, 0x04,
-	0x3B, 0xFE, 0x91, 0x00, 0xEB, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD,
-	0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01, 0x84, 0xFC, 0xF3, 0x06,
-	0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85, 0xF1, 0x16, 0x07, 0x61,
-	0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00,
-	0xEC, 0xFF, 0x08, 0x00, 0x57, 0x00, 0x9F, 0xFE, 0xD1, 0x03, 0x9B,
-	0xF5, 0xF7, 0x41, 0x7C, 0x19, 0x13, 0xF5, 0x2F, 0x06, 0x78, 0xFC,
-	0xD5, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8F,
-	0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02, 0x91, 0xFD, 0xE3, 0x01,
-	0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8, 0x02, 0xFE, 0xFD, 0x2B,
-	0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
-	0x42, 0xFF, 0xBD, 0x01, 0xB6, 0xFC, 0x9F, 0x05, 0x6C, 0xF6, 0xD6,
-	0x14, 0x65, 0x44, 0x98, 0xF7, 0xAC, 0x02, 0x4E, 0xFF, 0xF4, 0xFF,
-	0x39, 0x00, 0xD9, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45,
-	0xFF, 0xD2, 0x01, 0x3D, 0xFC, 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A,
-	0xC6, 0x35, 0xB7, 0xF1, 0x96, 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D,
-	0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x06, 0x00, 0xC1, 0xFF,
-	0xE5, 0x00, 0xAA, 0xFD, 0x58, 0x05, 0x3A, 0xF3, 0x11, 0x3D, 0x2C,
-	0x21, 0x3F, 0xF3, 0xDA, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20,
-	0xFF, 0xD0, 0x00, 0x07, 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C,
-	0x63, 0xF9, 0x42, 0x04, 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x85, 0x01,
-	0x39, 0xFD, 0x84, 0x04, 0xD9, 0xF8, 0x95, 0x0D, 0x48, 0x47, 0xA7,
-	0xFB, 0x86, 0x00, 0x8A, 0x00, 0x46, 0xFF, 0x8E, 0x00, 0xB8, 0xFF,
-	0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35,
-	0xFC, 0xF3, 0x06, 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2,
-	0x9C, 0x05, 0x7E, 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01,
-	0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x87, 0xFF, 0x57, 0x01, 0xEF, 0xFC,
-	0x6B, 0x06, 0xE0, 0xF1, 0x23, 0x37, 0xCE, 0x28, 0x01, 0xF2, 0x28,
-	0x07, 0x36, 0xFC, 0xD9, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-	0x0B, 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F,
-	0x02, 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05,
-	0xCF, 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x23, 0x00, 0x74, 0xFF, 0x3C, 0x01, 0xDA, 0xFD, 0x40, 0x03,
-	0x6E, 0xFB, 0xE1, 0x06, 0xC3, 0x48, 0xB3, 0x00, 0x1A, 0xFE, 0xDC,
-	0x01, 0x91, 0xFE, 0xE5, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-	0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6,
-	0xF4, 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE,
-	0x77, 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A,
-	0x00, 0x5C, 0xFF, 0xA8, 0x01, 0x73, 0xFC, 0x05, 0x07, 0x7D, 0xF1,
-	0x67, 0x30, 0x21, 0x30, 0x7E, 0xF1, 0x08, 0x07, 0x6F, 0xFC, 0xAB,
-	0x01, 0x5B, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF0, 0xFF,
-	0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
-	0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
-	0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE8,
-	0x00, 0x8A, 0xFE, 0xE9, 0x01, 0x01, 0xFE, 0xEA, 0x00, 0xCB, 0x48,
-	0xA2, 0x06, 0x87, 0xFB, 0x33, 0x03, 0xE0, 0xFD, 0x39, 0x01, 0x75,
-	0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF,
-	0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13, 0xFD,
-	0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47, 0x00,
-	0xD3, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD8,
-	0x01, 0x37, 0xFC, 0x29, 0x07, 0xF8, 0xF1, 0x19, 0x29, 0xE5, 0x36,
-	0xD8, 0xF1, 0x73, 0x06, 0xE9, 0xFC, 0x5B, 0x01, 0x85, 0xFF, 0x1C,
-	0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF, 0xFB, 0x00,
-	0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81, 0x22, 0xFC,
-	0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00,
-	0xFD, 0xFF, 0x12, 0x00, 0xB7, 0xFF, 0x91, 0x00, 0x40, 0xFF, 0x96,
-	0x00, 0x6F, 0x00, 0xD5, 0xFB, 0x5E, 0x47, 0x50, 0x0D, 0xF2, 0xF8,
-	0x78, 0x04, 0x3F, 0xFD, 0x82, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79, 0x01, 0x53, 0xFD,
-	0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47, 0x76, 0xFC, 0x1F,
-	0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2, 0xFF, 0x13, 0x00,
-	0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xDF,
-	0x06, 0x30, 0xF3, 0x78, 0x21, 0xDB, 0x3C, 0x28, 0xF3, 0x65, 0x05,
-	0xA2, 0xFD, 0xEA, 0x00, 0xBE, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE,
-	0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06,
-	0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C,
-	0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
-	0xD8, 0xFF, 0x3C, 0x00, 0xEE, 0xFF, 0x5A, 0xFF, 0x98, 0x02, 0xBB,
-	0xF7, 0x87, 0x44, 0x8C, 0x14, 0x83, 0xF6, 0x95, 0x05, 0xBA, 0xFC,
-	0xBB, 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
-	0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7, 0xFD, 0x05, 0x03, 0xE1, 0xFB,
-	0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01, 0xAA, 0xFD, 0x18, 0x02, 0x72,
-	0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-	0x39, 0xFF, 0xD6, 0x01, 0x75, 0xFC, 0x37, 0x06, 0xFF, 0xF4, 0xC7,
-	0x19, 0xCC, 0x41, 0x7F, 0xF5, 0xE2, 0x03, 0x95, 0xFE, 0x5D, 0x00,
-	0x05, 0x00, 0xED, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
-	0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
-	0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
-	0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF5, 0xFF, 0xEE, 0xFF,
-	0x8B, 0x00, 0x44, 0xFE, 0x65, 0x04, 0xAA, 0xF4, 0x66, 0x40, 0x23,
-	0x1C, 0x63, 0xF4, 0x74, 0x06, 0x5D, 0xFC, 0xDE, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA,
-	0xFE, 0xAE, 0x01, 0x70, 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07,
-	0x14, 0xFB, 0x6D, 0x03, 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24,
-	0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAC, 0x01,
-	0xDF, 0xFC, 0x43, 0x05, 0x3C, 0xF7, 0x46, 0x12, 0x8D, 0x45, 0xE2,
-	0xF8, 0xF7, 0x01, 0xB8, 0xFF, 0xB9, 0xFF, 0x56, 0x00, 0xCE, 0xFF,
-	0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34,
-	0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2,
-	0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF,
-	0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAB, 0xFF, 0x10, 0x01, 0x62, 0xFD,
-	0xC5, 0x05, 0xA5, 0xF2, 0x1F, 0x3B, 0xD6, 0x23, 0xBE, 0xF2, 0x01,
-	0x07, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x10, 0x00, 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4,
-	0x00, 0x0C, 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04,
-	0x26, 0xFD, 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x29, 0x00, 0x60, 0xFF, 0x6D, 0x01, 0x6E, 0xFD, 0x17, 0x04,
-	0xBC, 0xF9, 0x30, 0x0B, 0xF4, 0x47, 0x4B, 0xFD, 0xB5, 0xFF, 0xFD,
-	0x00, 0x08, 0xFF, 0xAC, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76,
-	0xF3, 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD,
-	0xD4, 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21,
-	0x00, 0x77, 0xFF, 0x77, 0x01, 0xBD, 0xFC, 0xAE, 0x06, 0xA3, 0xF1,
-	0xE3, 0x34, 0x64, 0x2B, 0xBC, 0xF1, 0x2A, 0x07, 0x43, 0xFC, 0xCD,
-	0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDD, 0xFF,
-	0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
-	0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
-	0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F,
-	0xFF, 0x20, 0x01, 0x16, 0xFE, 0xCA, 0x02, 0x54, 0xFC, 0xB9, 0x04,
-	0xF2, 0x48, 0xA9, 0x02, 0x39, 0xFD, 0x53, 0x02, 0x53, 0xFE, 0x03,
-	0x01, 0x8A, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF,
-	0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89,
-	0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00,
-	0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBD,
-	0x01, 0x57, 0xFC, 0x1E, 0x07, 0x90, 0xF1, 0xED, 0x2D, 0x8C, 0x32,
-	0x83, 0xF1, 0xE2, 0x06, 0x92, 0xFC, 0x93, 0x01, 0x68, 0xFF, 0x26,
-	0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF, 0xA4, 0x00,
-	0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78, 0x1D, 0x10,
-	0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF, 0xCA, 0x00, 0xC9, 0xFE, 0x73,
-	0x01, 0xDE, 0xFE, 0x0C, 0xFF, 0x76, 0x48, 0xDE, 0x08, 0xA1, 0xFA,
-	0xA6, 0x03, 0xA6, 0xFD, 0x53, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00,
-	0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6, 0xFC,
-	0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9, 0x98,
-	0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E, 0x00,
-	0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x32, 0xFC, 0x1B,
-	0x07, 0x50, 0xF2, 0x7B, 0x26, 0x11, 0x39, 0x2F, 0xF2, 0x23, 0x06,
-	0x22, 0xFD, 0x37, 0x01, 0x97, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01, 0x41, 0xFD, 0xF6, 0x05,
-	0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84, 0xF2, 0x0F, 0x07, 0x31,
-	0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00,
-	0xC2, 0xFF, 0x73, 0x00, 0x7D, 0xFF, 0x25, 0x00, 0x38, 0x01, 0x4C,
-	0xFA, 0x89, 0x46, 0xC3, 0x0F, 0x14, 0xF8, 0xE0, 0x04, 0x0D, 0xFD,
-	0x98, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
-	0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD, 0xDF, 0x03, 0x2E, 0xFA,
-	0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B, 0xFF, 0x38, 0x01, 0xE9,
-	0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE4, 0x01, 0x49, 0xFC, 0xAF, 0x06, 0xC1, 0xF3, 0xCD,
-	0x1E, 0xB1, 0x3E, 0xD9, 0xF3, 0xEC, 0x04, 0xF0, 0xFD, 0xBC, 0x00,
-	0xD5, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F,
-	0xFF, 0x85, 0x01, 0xA6, 0xFC, 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33,
-	0xAB, 0x2C, 0xA3, 0xF1, 0x26, 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D,
-	0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE2, 0xFF, 0x20, 0x00,
-	0x26, 0x00, 0xF5, 0xFE, 0x43, 0x03, 0x8D, 0xF6, 0x3C, 0x43, 0x25,
-	0x17, 0xBB, 0xF5, 0xEA, 0x05, 0x95, 0xFC, 0xCA, 0x01, 0x3D, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11,
-	0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48,
-	0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84,
-	0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-	0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A,
-	0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00,
-	0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1,
-	0xFD, 0x4E, 0x05, 0x4A, 0xF3, 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3,
-	0xD6, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE,
-	0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7,
-	0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00,
-	0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5, 0x01, 0x4C, 0xFC, 0x26,
-	0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33, 0x8F, 0xF1, 0xCA, 0x06,
-	0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x16,
-	0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF,
-	0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A,
-	0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F, 0x07, 0x84,
-	0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05, 0x41, 0xFD,
-	0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8,
-	0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9,
-	0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2,
-	0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
-	0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
-	0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0x07, 0x00, 0xE8, 0xFF, 0x12,
-	0x00, 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42,
-	0x76, 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B,
-	0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF,
-	0xC3, 0x01, 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7,
-	0x43, 0x20, 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00,
-	0xDD, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4,
-	0x00, 0xC8, 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20,
-	0x76, 0xF3, 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01,
-	0x26, 0xFD, 0xAD, 0x04, 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C,
-	0xFB, 0xD4, 0x00, 0x5D, 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF,
-	0x10, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04,
-	0xFD, 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2,
-	0x23, 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x46, 0x01, 0xC3, 0xFD,
-	0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07, 0xA6, 0x48, 0xF8, 0xFF, 0x70,
-	0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9, 0x00, 0x9A, 0xFF, 0x19, 0x00,
-	0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
-	0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
-	0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B,
-	0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18, 0x02, 0xAA, 0xFD,
-	0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB, 0x05, 0x03, 0xF7,
-	0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07, 0xDC,
-	0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5, 0xFC,
-	0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xB2,
-	0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76, 0xFC,
-	0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD, 0x79,
-	0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
-	0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
-	0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xD3, 0xFF, 0x47,
-	0x00, 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44,
-	0x8D, 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45,
-	0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF,
-	0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32,
-	0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF,
-	0xF0, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77,
-	0x00, 0x67, 0xFE, 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B,
-	0xA6, 0xF4, 0x5A, 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36,
-	0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01,
-	0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E,
-	0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF,
-	0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E,
-	0xFD, 0x9C, 0x05, 0xDC, 0xF2, 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2,
-	0xF3, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x76, 0x01, 0x59, 0xFD,
-	0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C, 0xB6, 0x47, 0xA4, 0xFC, 0x07,
-	0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0, 0x00, 0xB1, 0xFF, 0x13, 0x00,
-	0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B, 0x01, 0xCF, 0xFC, 0x96,
-	0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A, 0xD4, 0xF1, 0x2B, 0x07,
-	0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00,
-	0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02,
-	0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25,
-	0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C, 0x00, 0xFD, 0xFF,
-	0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16, 0x07, 0x85,
-	0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06, 0x84, 0xFC,
-	0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9C,
-	0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF,
-	0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49,
-	0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
-	0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
-	0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F,
-	0x00, 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46,
-	0xCD, 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53,
-	0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-	0xE5, 0x01, 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE,
-	0x3D, 0x91, 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF,
-	0x02, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11,
-	0x00, 0x1B, 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16,
-	0x07, 0xF6, 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33,
-	0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01,
-	0x88, 0xFC, 0x09, 0x06, 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20,
-	0xF6, 0x83, 0x03, 0xCF, 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF,
-	0x07, 0x00, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10,
-	0xFE, 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3,
-	0x99, 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4D, 0xFF, 0xA0, 0x01, 0xFB, 0xFC,
-	0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10, 0x2B, 0x46, 0xBB, 0xF9, 0x83,
-	0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68, 0x00, 0xC7, 0xFF, 0x0E, 0x00,
-	0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
-	0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
-	0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00,
-	0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90, 0xFD, 0xD2, 0x03,
-	0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE, 0x33, 0xFF, 0x45,
-	0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16, 0x00, 0xFD, 0xFF,
-	0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06, 0x8C,
-	0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E, 0xFC,
-	0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x86,
-	0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73, 0x03,
-	0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE, 0x14,
-	0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00,
-	0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
-	0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
-	0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8,
-	0x00, 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48,
-	0x47, 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64,
-	0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF,
-	0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54,
-	0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF,
-	0x11, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2,
-	0xFF, 0xE2, 0xFF, 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11,
-	0x8F, 0xF7, 0x1D, 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01,
-	0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55,
-	0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF,
-	0x04, 0x00, 0x07, 0x00, 0xE9, 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9,
-	0xFE, 0xA6, 0x03, 0xE4, 0xF5, 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5,
-	0x1A, 0x06, 0x81, 0xFC, 0xD2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE,
-	0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC1, 0x01, 0xAB, 0xFC,
-	0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15, 0x0B, 0x44, 0x42, 0xF7, 0xDC,
-	0x02, 0x32, 0xFF, 0x04, 0x00, 0x31, 0x00, 0xDC, 0xFF, 0x09, 0x00,
-	0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9, 0x00, 0xBF, 0xFD, 0x38,
-	0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20, 0x66, 0xF3, 0xCE, 0x06,
-	0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-	0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04,
-	0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A,
-	0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
-	0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56, 0x06, 0xF7,
-	0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07, 0x34, 0xFC,
-	0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24,
-	0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB,
-	0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3,
-	0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00,
-	0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
-	0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
-	0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1,
-	0x00, 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48,
-	0x07, 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78,
-	0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF,
-	0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46,
-	0x36, 0xC5, 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF,
-	0x1E, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E,
-	0xFF, 0xB6, 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C,
-	0x31, 0xF9, 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01,
-	0x37, 0xFC, 0xEB, 0x06, 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD,
-	0xF2, 0x84, 0x05, 0x8D, 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00,
-	0x01, 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77,
-	0xFF, 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6,
-	0x7C, 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF,
-	0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD9, 0x01, 0x6D, 0xFC,
-	0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A, 0x5F, 0x41, 0x3A, 0xF5, 0x0C,
-	0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
-	0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
-	0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
-	0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF,
-	0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3, 0xFC, 0x5D, 0x05,
-	0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8, 0x2A, 0x02, 0x9A,
-	0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C, 0x00, 0x00, 0x00,
-	0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05, 0xCC,
-	0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35, 0xFC,
-	0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29,
-	0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C, 0xF9,
-	0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00, 0x19,
-	0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x20, 0x00,
-	0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
-	0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
-	0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C,
-	0xFF, 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05,
-	0xEA, 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA,
-	0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF,
-	0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3,
-	0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF,
-	0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8,
-	0xFE, 0x93, 0x01, 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08,
-	0xE1, 0xFA, 0x86, 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01,
-	0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14,
-	0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00,
-	0xFF, 0xFF, 0x10, 0x00, 0xBF, 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44,
-	0x00, 0x01, 0x01, 0xB6, 0xFA, 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8,
-	0xC4, 0x04, 0x1B, 0xFD, 0x92, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF,
-	0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x44, 0xFC,
-	0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F, 0x31, 0x3E, 0xA5, 0xF3, 0x0F,
-	0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF, 0xFF, 0x01, 0x00, 0x02, 0x00,
-	0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17, 0x00, 0x10, 0xFF, 0x15,
-	0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16, 0xF1, 0xF5, 0xD3, 0x05,
-	0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
-	0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06,
-	0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9,
-	0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0x03, 0x00,
-	0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8, 0x04, 0x10,
-	0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06, 0x4E, 0xFC,
-	0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E,
-	0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7,
-	0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E,
-	0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x13, 0x00,
-	0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
-	0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-	0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68,
-	0xFF, 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09,
-	0x57, 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2,
-	0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF,
-	0x8B, 0x01, 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A,
-	0x2D, 0x9A, 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF,
-	0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42,
-	0xFE, 0x74, 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04,
-	0x94, 0xFC, 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01,
-	0x48, 0xFC, 0x28, 0x07, 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97,
-	0xF1, 0xBE, 0x06, 0xB0, 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00,
-	0xFE, 0xFF, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D,
-	0x01, 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9,
-	0xF8, 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC,
-	0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24, 0x8F, 0x3A, 0x82, 0xF2, 0xE1,
-	0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6, 0xFF, 0x10, 0x00, 0x00, 0x00,
-	0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
-	0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
-	0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57, 0xFC, 0x85, 0x06,
-	0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4, 0x8C, 0x04, 0x2C,
-	0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04, 0x00, 0x06, 0x00,
-	0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03, 0xC7,
-	0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D, 0xFC,
-	0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32,
-	0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A, 0xF6,
-	0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF, 0xFE,
-	0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x05, 0x00,
-	0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
-	0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x56,
-	0xFF, 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D,
-	0x26, 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89,
-	0x00, 0xBA, 0xFF, 0x11, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF,
-	0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60,
-	0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF,
-	0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40,
-	0x01, 0xD0, 0xFD, 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48,
-	0x62, 0x00, 0x3F, 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98,
-	0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01,
-	0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80,
-	0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00,
-	0xFD, 0xFF, 0x1B, 0x00, 0x93, 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD,
-	0x01, 0xDC, 0xFD, 0x3C, 0x01, 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB,
-	0x1F, 0x03, 0xEA, 0xFD, 0x34, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43, 0xFF, 0xD6, 0x01, 0x39, 0xFC,
-	0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29, 0x85, 0x36, 0xCC, 0xF1, 0x7F,
-	0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
-	0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35, 0xFF, 0xA9, 0x00, 0x4D,
-	0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C, 0x18, 0xF9, 0x66, 0x04,
-	0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06,
-	0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96,
-	0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01, 0x00, 0x0B, 0x00,
-	0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B, 0x02, 0xF0,
-	0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05, 0xC1, 0xFC,
-	0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35,
-	0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4,
-	0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66,
-	0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0x05, 0x00, 0xF4, 0xFF,
-	0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
-	0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
-	0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x47,
-	0xFF, 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12,
-	0x5C, 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51,
-	0x00, 0xD0, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF,
-	0x09, 0x01, 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64,
-	0x23, 0xD2, 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71,
-	0x01, 0x65, 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47,
-	0x03, 0xFD, 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE,
-	0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01,
-	0xC4, 0xFC, 0xA4, 0x06, 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6,
-	0xF1, 0x2A, 0x07, 0x40, 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C,
-	0xFE, 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02,
-	0x5E, 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C,
-	0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0xBA, 0x01, 0x5B, 0xFC,
-	0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E, 0x26, 0x32, 0x80, 0xF1, 0xEA,
-	0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
-	0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
-	0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
-	0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32, 0xFC, 0x1E, 0x07,
-	0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2, 0x32, 0x06, 0x18,
-	0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
-	0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01, 0x8B,
-	0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15, 0xFD,
-	0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8, 0xF3,
-	0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD, 0xC4,
-	0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0xE1, 0xFF,
-	0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
-	0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
-	0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D,
-	0xFF, 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17,
-	0x02, 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B,
-	0x00, 0xE4, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF,
-	0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B,
-	0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C,
-	0x01, 0x05, 0xFD, 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46,
-	0x0D, 0xFA, 0x58, 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4,
-	0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01,
-	0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61,
-	0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D,
-	0xFD, 0xB9, 0x03, 0x7B, 0xFA, 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE,
-	0x03, 0xFF, 0x5F, 0x01, 0xD4, 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16,
-	0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A, 0xFF, 0x8E, 0x01, 0x99, 0xFC,
-	0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32, 0x82, 0x2D, 0x96, 0xF1, 0x21,
-	0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-	0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49, 0xFE, 0x67, 0x02, 0x13,
-	0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04, 0x7A, 0xFC, 0xB6, 0x02,
-	0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07,
-	0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5,
-	0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x15, 0x00,
-	0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92, 0xFF, 0x94,
-	0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04, 0x77, 0xFD,
-	0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36,
-	0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2,
-	0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17,
-	0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xCC, 0xFF,
-	0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
-	0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
-	0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37,
-	0xFF, 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C,
-	0x1F, 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA,
-	0xFF, 0xF7, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00,
-	0x54, 0x00, 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56,
-	0x19, 0x1E, 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF,
-	0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE,
-	0x01, 0xB4, 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44,
-	0x86, 0xF7, 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9,
-	0xFF, 0x0A, 0x00, 0x01, 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00,
-	0xAE, 0xFD, 0x52, 0x05, 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47,
-	0xF3, 0xD8, 0x06, 0x3C, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36,
-	0xFD, 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB,
-	0x91, 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11,
-	0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88, 0xFF, 0x55, 0x01, 0xF2, 0xFC,
-	0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37, 0xAA, 0x28, 0x05, 0xF2, 0x27,
-	0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-	0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
-	0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
-	0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFD,
-	0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75, 0xFC, 0x03, 0x07,
-	0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1, 0x0A, 0x07, 0x6E,
-	0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x1A, 0x00,
-	0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD, 0x05,
-	0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4, 0xFD,
-	0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33,
-	0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3, 0xF1,
-	0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC, 0x5C,
-	0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
-	0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
-	0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
-	0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37,
-	0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21,
-	0xC0, 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD,
-	0xFF, 0x07, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00,
-	0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68,
-	0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF,
-	0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
-	0x01, 0x73, 0xFC, 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41,
-	0x71, 0xF5, 0xEB, 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED,
-	0xFF, 0x06, 0x00, 0x04, 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00,
-	0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C,
-	0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD,
-	0xFC, 0x48, 0x05, 0x30, 0xF7, 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8,
-	0x01, 0x02, 0xB2, 0xFF, 0xBD, 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C,
-	0x00, 0x00, 0x00, 0x0E, 0x00, 0xAC, 0xFF, 0x0E, 0x01, 0x66, 0xFD,
-	0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B, 0xB0, 0x23, 0xC4, 0xF2, 0xFF,
-	0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E, 0x01, 0x6B, 0xFD, 0x1D,
-	0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47, 0x33, 0xFD, 0xC1, 0xFF,
-	0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD, 0xFF, 0x14, 0x00, 0xFE,
-	0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06,
-	0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42,
-	0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-	0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1, 0x02, 0x47,
-	0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD, 0x4D, 0x02,
-	0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E,
-	0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1,
-	0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94,
-	0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
-	0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
-	0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
-	0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C,
-	0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26,
-	0xF2, 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96,
-	0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00,
-	0x7A, 0xFF, 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0,
-	0x0F, 0x20, 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF,
-	0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-	0x01, 0x48, 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E,
-	0xCF, 0xF3, 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF,
-	0xFF, 0x03, 0x00, 0x08, 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00,
-	0xFA, 0xFE, 0x3A, 0x03, 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6,
-	0xF5, 0xE6, 0x05, 0x97, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00,
-	0xFE, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93,
-	0xFC, 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6,
-	0x4D, 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08,
-	0x00, 0x03, 0x00, 0xFE, 0xFF, 0xD7, 0xFF, 0xBA, 0x00, 0xF4, 0xFD,
-	0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E, 0xA7, 0x1E, 0xCA, 0xF3, 0xAC,
-	0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-	0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
-	0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
-	0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0xFF,
-	0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25, 0xFD, 0x1E, 0x06,
-	0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2, 0x1A, 0x07, 0x31,
-	0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-	0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03, 0x94,
-	0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C, 0x01,
-	0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26,
-	0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84, 0xF1,
-	0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC, 0xBE,
-	0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
-	0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
-	0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
-	0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49,
-	0xFF, 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B,
-	0xC3, 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76,
-	0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00,
-	0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E,
-	0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF,
-	0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-	0x01, 0x33, 0xFC, 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B,
-	0x9E, 0xF2, 0xCB, 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E,
-	0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF,
-	0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48,
-	0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00,
-	0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C,
-	0xFC, 0x78, 0x06, 0x5A, 0xF4, 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4,
-	0x6D, 0x04, 0x3F, 0xFE, 0x8E, 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04,
-	0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x5A, 0x00, 0x9A, 0xFE,
-	0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41, 0xA1, 0x19, 0x09, 0xF5, 0x33,
-	0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-	0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC, 0x01, 0xB8, 0xFC, 0x9A,
-	0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44, 0xA9, 0xF7, 0xA2, 0x02,
-	0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8, 0xFF, 0x0A, 0x00, 0x01,
-	0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05,
-	0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B,
-	0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-	0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E, 0x04, 0xE6,
-	0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00, 0x90, 0x00,
-	0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFE, 0xFF, 0x1C,
-	0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1,
-	0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8,
-	0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00,
-	0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
-	0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
-	0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C,
-	0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30,
-	0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C,
-	0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00,
-	0x8E, 0xFE, 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1,
-	0x06, 0x7B, 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF,
-	0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8,
-	0x01, 0x37, 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37,
-	0xDC, 0xF1, 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C,
-	0x00, 0xFE, 0xFF, 0x11, 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF,
-	0x90, 0x00, 0x7A, 0x00, 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6,
-	0xF8, 0x7E, 0x04, 0x3C, 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00,
-	0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B,
-	0xFC, 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3,
-	0x5F, 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01,
-	0x00, 0x0A, 0x00, 0xD8, 0xFF, 0x3A, 0x00, 0xF1, 0xFF, 0x54, 0xFF,
-	0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44, 0xB1, 0x14, 0x77, 0xF6, 0x9A,
-	0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
-	0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
-	0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
-	0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x04,
-	0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F, 0xFE, 0x6D, 0x04,
-	0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4, 0x78, 0x06, 0x5C,
-	0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
-	0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05, 0x48,
-	0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE, 0xFF,
-	0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0E,
-	0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E, 0xF2,
-	0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC, 0xE5,
-	0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00,
-	0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
-	0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
-	0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76,
-	0xFF, 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34,
-	0x89, 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49,
-	0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF,
-	0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2,
-	0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01,
-	0x8A, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE,
-	0x01, 0x56, 0xFC, 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32,
-	0x84, 0xF1, 0xE0, 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26,
-	0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE,
-	0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94,
-	0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00,
-	0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31,
-	0xFC, 0x1A, 0x07, 0x56, 0xF2, 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2,
-	0x1E, 0x06, 0x25, 0xFD, 0x35, 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF,
-	0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71, 0x00, 0x81, 0xFF, 0x1F, 0x00,
-	0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46, 0xE7, 0x0F, 0x08, 0xF8, 0xE6,
-	0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
-	0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x4A, 0xFC, 0xAC,
-	0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E, 0xE4, 0xF3, 0xE5, 0x04,
-	0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0x08,
-	0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03,
-	0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93,
-	0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFE, 0xFF,
-	0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6, 0x05, 0xC6,
-	0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03, 0xFA, 0xFE,
-	0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFF,
-	0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3,
-	0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00,
-	0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
-	0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
-	0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96,
-	0xFF, 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38,
-	0xA0, 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C,
-	0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF,
-	0x52, 0x01, 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C,
-	0x48, 0x26, 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00,
-	0xA0, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94,
-	0x01, 0x90, 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E,
-	0x8E, 0xF1, 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E,
-	0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE,
-	0x4D, 0x02, 0x45, 0xFD, 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47,
-	0xFC, 0xD1, 0x02, 0x12, 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00,
-	0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42,
-	0xFC, 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1,
-	0xAB, 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
-	0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA, 0x00, 0x0C, 0xFF, 0xF7, 0x00,
-	0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47, 0x51, 0x0B, 0xAF, 0xF9, 0x1D,
-	0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00,
-	0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
-	0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
-	0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x0C,
-	0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2, 0xFF, 0x01, 0x02,
-	0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7, 0x48, 0x05, 0xDD,
-	0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
-	0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06, 0x6C,
-	0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49, 0xFE,
-	0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xED,
-	0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71, 0xF5,
-	0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC, 0xD7,
-	0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00,
-	0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
-	0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
-	0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x07, 0x00, 0xBD,
-	0xFF, 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C,
-	0x9E, 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF,
-	0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69,
-	0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00,
-	0xB6, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C,
-	0x01, 0xE6, 0xFC, 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29,
-	0xF3, 0xF1, 0x29, 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33,
-	0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01,
-	0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05,
-	0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF,
-	0x1A, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E,
-	0xFC, 0x0A, 0x07, 0x7E, 0xF1, 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1,
-	0x03, 0x07, 0x75, 0xFC, 0xA7, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD,
-	0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3, 0x00, 0x95, 0xFE, 0xD5, 0x01,
-	0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48, 0x00, 0x07, 0x61, 0xFB, 0x46,
-	0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73, 0xFF, 0x23, 0x00, 0x00, 0x00,
-	0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA, 0x01, 0x36, 0xFC, 0x27,
-	0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37, 0xE4, 0xF1, 0x67, 0x06,
-	0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x11,
-	0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00,
-	0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36,
-	0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8, 0x06, 0x47,
-	0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05, 0xAE, 0xFD,
-	0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD9,
-	0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7,
-	0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE,
-	0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00,
-	0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
-	0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
-	0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF7, 0xFF, 0xEA,
-	0xFF, 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40,
-	0x94, 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37,
-	0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-	0xA9, 0x01, 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8,
-	0x45, 0x1C, 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00,
-	0xCC, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17,
-	0x01, 0x57, 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24,
-	0xAA, 0xF2, 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01,
-	0x77, 0xFD, 0x04, 0x04, 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94,
-	0xFD, 0x92, 0xFF, 0x10, 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF,
-	0x15, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5,
-	0xFC, 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1,
-	0x29, 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x1B, 0x01, 0x20, 0xFE,
-	0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04, 0xF4, 0x48, 0xFF, 0x02, 0x13,
-	0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07, 0x01, 0x88, 0xFF, 0x1D, 0x00,
-	0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
-	0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
-	0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16,
-	0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F, 0x01, 0x03, 0xFF,
-	0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA, 0xB9, 0x03, 0x9D,
-	0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07, 0x61,
-	0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C, 0xFD,
-	0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC4,
-	0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D, 0xFA,
-	0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD, 0x9C,
-	0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
-	0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
-	0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE4, 0xFF, 0x1B,
-	0x00, 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43,
-	0x96, 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D,
-	0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF,
-	0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77,
-	0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00,
-	0xE1, 0xFF, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4,
-	0x00, 0xE2, 0xFD, 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F,
-	0xA8, 0xF3, 0xB8, 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01,
-	0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B,
-	0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF,
-	0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18,
-	0xFD, 0x32, 0x06, 0x1F, 0xF2, 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2,
-	0x1E, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x4F, 0x01, 0xB0, 0xFD,
-	0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08, 0x86, 0x48, 0x5A, 0xFF, 0xBA,
-	0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF, 0x00, 0x9E, 0xFF, 0x17, 0x00,
-	0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97, 0x01, 0x8C, 0xFC, 0xEA,
-	0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E, 0x8B, 0xF1, 0x1B, 0x07,
-	0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C,
-	0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD,
-	0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C,
-	0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-	0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xC6,
-	0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06, 0xC4, 0xFC,
-	0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAE,
-	0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD,
-	0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71,
-	0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-	0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
-	0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
-	0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51,
-	0x00, 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45,
-	0xB2, 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47,
-	0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF,
-	0xDD, 0x01, 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB,
-	0x40, 0xD0, 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF,
-	0xF4, 0xFF, 0x05, 0x00, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66,
-	0x00, 0x85, 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A,
-	0xE1, 0xF4, 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35,
-	0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01,
-	0xC1, 0xFC, 0x86, 0x05, 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0,
-	0xF7, 0x7B, 0x02, 0x6B, 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF,
-	0x0B, 0x00, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96,
-	0xFD, 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3,
-	0xE6, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0x00, 0x00, 0x2B, 0x00, 0x5A, 0xFF, 0x7E, 0x01, 0x48, 0xFD,
-	0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C, 0x7C, 0x47, 0x19, 0xFC, 0x4D,
-	0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96, 0x00, 0xB5, 0xFF, 0x12, 0x00,
-	0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
-	0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
-	0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00,
-	0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA, 0xFD, 0x1F, 0x03,
-	0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01, 0xDC, 0xFD, 0xFD,
-	0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B, 0x00, 0xFD, 0xFF,
-	0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07, 0x80,
-	0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78, 0xFC,
-	0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x98,
-	0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62, 0x00,
-	0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD, 0x40,
-	0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-	0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
-	0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
-	0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89,
-	0x00, 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47,
-	0xFC, 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56,
-	0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-	0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61,
-	0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF,
-	0x05, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE,
-	0xFF, 0x3D, 0xFF, 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15,
-	0x4A, 0xF6, 0xAD, 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32,
-	0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01,
-	0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7,
-	0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF,
-	0x06, 0x00, 0x04, 0x00, 0xF8, 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C,
-	0xFE, 0x8C, 0x04, 0x6D, 0xF4, 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4,
-	0x85, 0x06, 0x57, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-	0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4A, 0xFF, 0xA7, 0x01, 0xEC, 0xFC,
-	0x28, 0x05, 0x77, 0xF7, 0x92, 0x11, 0xD7, 0x45, 0x43, 0xF9, 0xC3,
-	0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E, 0x00, 0xCB, 0xFF, 0x0D, 0x00,
-	0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B, 0x01, 0x50, 0xFD, 0xE1,
-	0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24, 0x9D, 0xF2, 0x09, 0x07,
-	0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00,
-	0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03,
-	0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D,
-	0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15, 0x00, 0xFE, 0xFF,
-	0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE, 0x06, 0x97,
-	0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07, 0x48, 0xFC,
-	0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F,
-	0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC,
-	0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42,
-	0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-	0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
-	0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
-	0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2,
-	0x00, 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48,
-	0x81, 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68,
-	0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF,
-	0xE2, 0x01, 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5,
-	0x39, 0x4D, 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF,
-	0x13, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E,
-	0xFF, 0x06, 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10,
-	0xD7, 0xF7, 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E,
-	0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01,
-	0x4E, 0xFC, 0xA0, 0x06, 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10,
-	0xF4, 0xC8, 0x04, 0x07, 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF,
-	0x03, 0x00, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9,
-	0xFE, 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5,
-	0x00, 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
-	0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01, 0x9F, 0xFC,
-	0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16, 0x9E, 0x43, 0xDD, 0xF6, 0x15,
-	0x03, 0x10, 0xFF, 0x17, 0x00, 0x28, 0x00, 0xDF, 0xFF, 0x09, 0x00,
-	0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
-	0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
-	0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-	0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B, 0xFD, 0xC4, 0x04,
-	0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA, 0x01, 0x01, 0x44,
-	0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
-	0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06, 0x14,
-	0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33, 0xFC,
-	0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25,
-	0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1, 0xFA,
-	0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01, 0xB8,
-	0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-	0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
-	0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
-	0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA,
-	0x00, 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48,
-	0x50, 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C,
-	0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF,
-	0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86,
-	0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF,
-	0x20, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19,
-	0xFF, 0xDD, 0x00, 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B,
-	0x7C, 0xF9, 0x35, 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01,
-	0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC,
-	0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00,
-	0x00, 0x00, 0x0C, 0x00, 0xD1, 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A,
-	0xFF, 0x2A, 0x02, 0x83, 0xF8, 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7,
-	0x5D, 0x05, 0xD3, 0xFC, 0xB1, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF,
-	0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x64, 0xFC,
-	0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B, 0xD9, 0x40, 0xEA, 0xF4, 0x3E,
-	0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5, 0xFF, 0xF3, 0xFF, 0x05, 0x00,
-	0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C, 0x00, 0x7B, 0xFE, 0x0C,
-	0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A, 0xCD, 0xF4, 0x4B, 0x06,
-	0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF,
-	0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05,
-	0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77,
-	0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0x01, 0x00,
-	0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84, 0x05, 0xFD,
-	0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06, 0x37, 0xFC,
-	0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A,
-	0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9,
-	0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E,
-	0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-	0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
-	0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
-	0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78,
-	0xFF, 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06,
-	0xDB, 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1,
-	0x00, 0x91, 0xFF, 0x1B, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF,
-	0xB1, 0x01, 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15,
-	0x31, 0x7C, 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF,
-	0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3,
-	0xFE, 0xBB, 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07,
-	0x2E, 0xFB, 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24,
-	0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01,
-	0x34, 0xFC, 0x25, 0x07, 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7,
-	0xF1, 0x56, 0x06, 0xFE, 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00,
-	0xFF, 0xFF, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A,
-	0x00, 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8,
-	0xA1, 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
-	0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3F, 0xFC,
-	0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20, 0x96, 0x3D, 0x69, 0xF3, 0x38,
-	0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7, 0xFF, 0x04, 0x00, 0x02, 0x00,
-	0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
-	0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
-	0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
-	0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81, 0xFC, 0x1A, 0x06,
-	0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5, 0xA6, 0x03, 0xB9,
-	0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0x04, 0x00,
-	0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04, 0x55,
-	0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55, 0xFC,
-	0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F,
-	0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F, 0xF7,
-	0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF, 0xA2,
-	0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00,
-	0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
-	0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
-	0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64,
-	0xFF, 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A,
-	0x2C, 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8,
-	0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF,
-	0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62,
-	0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF,
-	0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14,
-	0x01, 0x2D, 0xFE, 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48,
-	0x73, 0x03, 0xE0, 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86,
-	0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01,
-	0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C,
-	0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00,
-	0xFD, 0xFF, 0x16, 0x00, 0xA5, 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45,
-	0x01, 0x33, 0xFF, 0x5A, 0xFE, 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA,
-	0xD2, 0x03, 0x90, 0xFD, 0x5E, 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC,
-	0x12, 0x07, 0x79, 0xF2, 0x73, 0x25, 0xDF, 0x39, 0x5A, 0xF2, 0x00,
-	0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F, 0xFF, 0x13, 0x00, 0x00, 0x00,
-	0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95, 0xFF, 0xFA, 0xFF, 0x83,
-	0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10, 0xBF, 0xF7, 0x07, 0x05,
-	0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
-	0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06,
-	0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10,
-	0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0x07, 0x00,
-	0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83, 0x03, 0x20,
-	0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06, 0x88, 0xFC,
-	0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33,
-	0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6,
-	0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11,
-	0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00,
-	0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
-	0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
-	0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x53,
-	0xFF, 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E,
-	0xE1, 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F,
-	0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF,
-	0x45, 0x01, 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80,
-	0x27, 0x2B, 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF,
-	0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49,
-	0x01, 0xBC, 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48,
-	0xC3, 0xFF, 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C,
-	0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01,
-	0x84, 0xFC, 0xF3, 0x06, 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85,
-	0xF1, 0x16, 0x07, 0x61, 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00,
-	0xFD, 0xFF, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25,
-	0x02, 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB,
-	0xF8, 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD2, 0x01, 0x3D, 0xFC,
-	0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A, 0xC6, 0x35, 0xB7, 0xF1, 0x96,
-	0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D, 0xFF, 0x1F, 0x00, 0xFE, 0xFF,
-	0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
-	0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
-	0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF3, 0x06,
-	0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2, 0x9C, 0x05, 0x7E,
-	0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00,
-	0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02, 0x5E,
-	0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF, 0xFC,
-	0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36,
-	0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6, 0xF4,
-	0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE, 0x77,
-	0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF0, 0xFF,
-	0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
-	0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
-	0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x45,
-	0xFF, 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13,
-	0xFD, 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47,
-	0x00, 0xD3, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF,
-	0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81,
-	0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79,
-	0x01, 0x53, 0xFD, 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47,
-	0x76, 0xFC, 0x1F, 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2,
-	0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01,
-	0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC,
-	0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7,
-	0xFD, 0x05, 0x03, 0xE1, 0xFB, 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01,
-	0xAA, 0xFD, 0x18, 0x02, 0x72, 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B,
-	0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB3, 0x01, 0x64, 0xFC,
-	0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F, 0x5A, 0x31, 0x7D, 0xF1, 0xF7,
-	0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF,
-	0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA, 0xFE, 0xAE, 0x01, 0x70,
-	0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07, 0x14, 0xFB, 0x6D, 0x03,
-	0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07,
-	0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04,
-	0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x10, 0x00,
-	0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4, 0x00, 0x0C,
-	0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04, 0x26, 0xFD,
-	0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3,
-	0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4,
-	0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDD, 0xFF,
-	0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
-	0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
-	0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3B,
-	0xFF, 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18,
-	0x89, 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12,
-	0x00, 0xE8, 0xFF, 0x07, 0x00, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF,
-	0xA4, 0x00, 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78,
-	0x1D, 0x10, 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF,
-	0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2,
-	0x01, 0xF6, 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46,
-	0x93, 0xF9, 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8,
-	0xFF, 0x0E, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01,
-	0x41, 0xFD, 0xF6, 0x05, 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84,
-	0xF2, 0x0F, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00,
-	0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A,
-	0xFD, 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE,
-	0x4B, 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16,
-	0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F, 0xFF, 0x85, 0x01, 0xA6, 0xFC,
-	0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33, 0xAB, 0x2C, 0xA3, 0xF1, 0x26,
-	0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
-	0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
-	0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
-	0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFD,
-	0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07,
-	0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71,
-	0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-	0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7,
-	0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02,
-	0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x02, 0x00, 0x05,
-	0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
-	0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
-	0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED,
-	0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00,
-	0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x84,
-	0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
-	0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
-	0x01, 0x84, 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00,
-	0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04,
-	0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF,
-	0x27, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8, 0xFF, 0x64, 0x00, 0x9B,
-	0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9, 0x10, 0x46, 0x03, 0x11,
-	0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2, 0x01, 0x4C, 0xFF, 0x2F,
-	0x00, 0xFF, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00, 0x42, 0x00,
-	0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76, 0x18, 0x5C,
-	0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00,
-	0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8,
-	0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3,
-	0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD,
-	0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23,
-	0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF,
-	0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
-	0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
-	0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0xFD,
-	0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07,
-	0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5,
-	0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0xFD, 0xFF,
-	0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC,
-	0xF2, 0x81, 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD,
-	0xFB, 0x00, 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35,
-	0x00, 0x38, 0xFF, 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4,
-	0xCE, 0x1A, 0x32, 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71,
-	0x00, 0xFB, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00,
-	0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44,
-	0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF,
-	0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
-	0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
-	0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
-	0x00, 0xB1, 0xFF, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
-	0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5,
-	0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00,
-	0x8F, 0xFF, 0x1C, 0x00, 0x18, 0x00, 0x9C, 0xFF, 0xD6, 0x00, 0xB1,
-	0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF, 0x9C, 0x48, 0xFD, 0x07,
-	0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49, 0x01, 0x6E, 0xFF, 0x24,
-	0x00, 0x00, 0x00, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00, 0x65, 0xFF,
-	0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD, 0x0E, 0x6A,
-	0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF, 0x2D, 0x00,
-	0xFF, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B,
-	0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6,
-	0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF,
-	0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE,
-	0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99,
-	0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-	0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
-	0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
-	0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD,
-	0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06,
-	0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E,
-	0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-	0x30, 0x00, 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8,
-	0xF1, 0x62, 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC,
-	0x82, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36,
-	0x00, 0x3A, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2,
-	0xDD, 0x24, 0x54, 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20,
-	0x01, 0xA3, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-	0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C,
-	0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00,
-	0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-	0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
-	0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
-	0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF,
-	0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F,
-	0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00,
-	0xBB, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x43,
-	0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB, 0x7E, 0x07, 0xAF, 0x48,
-	0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3, 0xFE, 0xDD, 0x00, 0x99,
-	0xFF, 0x19, 0x00, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00, 0x79, 0xFE,
-	0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07, 0x06, 0xC7,
-	0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF, 0x22, 0x00,
-	0x00, 0x00, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6,
-	0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9,
-	0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00,
-	0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF,
-	0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C,
-	0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF,
-	0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
-	0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
-	0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00,
-	0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05,
-	0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35,
-	0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF,
-	0x20, 0x00, 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1,
-	0xF1, 0x86, 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC,
-	0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2D,
-	0x00, 0x54, 0xFF, 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1,
-	0x9F, 0x2E, 0xE3, 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A,
-	0x01, 0x64, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00,
-	0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36,
-	0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01,
-	0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-	0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
-	0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
-	0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
-	0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB,
-	0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00,
-	0xE5, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9E,
-	0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7, 0x75, 0x10, 0x48, 0x46,
-	0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E, 0xFF, 0x6B, 0x00, 0xC6,
-	0xFF, 0x0E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x5B, 0x01,
-	0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57, 0x48, 0x8D,
-	0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00, 0xA4, 0xFF,
-	0x16, 0x00, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74,
-	0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC,
-	0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00,
-	0x00, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01,
-	0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8,
-	0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00,
-	0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
-	0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
-	0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x06,
-	0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03,
-	0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D,
-	0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x02, 0x00,
-	0x05, 0x00, 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56,
-	0xF3, 0x61, 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC,
-	0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x1A,
-	0x00, 0x8A, 0xFF, 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1,
-	0x82, 0x37, 0x60, 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB,
-	0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x29, 0x00,
-	0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF,
-	0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01,
-	0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x43,
-	0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
-	0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
-	0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-	0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A,
-	0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF,
-	0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8,
-	0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4, 0x38, 0x1A, 0x8C, 0x41,
-	0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66, 0x00, 0x01, 0x00, 0xEE,
-	0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF, 0xAF, 0x01,
-	0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C, 0x45, 0xA9,
-	0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00, 0xD0, 0xFF,
-	0x0C, 0x00, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65,
-	0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD,
-	0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14,
-	0x00, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE,
-	0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E,
-	0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00,
-	0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
-	0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
-	0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x0F,
-	0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01,
-	0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15,
-	0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x08, 0x00,
-	0xE1, 0xFF, 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD,
-	0xF6, 0x77, 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC,
-	0xC8, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFD,
-	0xFF, 0xD9, 0xFF, 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3,
-	0xFC, 0x3E, 0x5B, 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3,
-	0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x14, 0x00,
-	0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A,
-	0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-	0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
-	0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
-	0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
-	0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-	0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81,
-	0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF,
-	0x22, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-	0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2, 0x46, 0x24, 0xC8, 0x3A,
-	0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17, 0x01, 0xA8, 0xFF, 0x0F,
-	0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01,
-	0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F, 0x40, 0x85,
-	0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF, 0xF7, 0xFF,
-	0x04, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4,
-	0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7,
-	0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A,
-	0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD,
-	0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91,
-	0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00,
-	0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
-	0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
-	0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0x1A,
-	0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD,
-	0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4,
-	0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0x12, 0x00,
-	0xB6, 0xFF, 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB,
-	0xFB, 0x69, 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD,
-	0x81, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD7,
-	0xFF, 0x3E, 0x00, 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7,
-	0x99, 0x44, 0x68, 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA,
-	0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF5, 0xFF,
-	0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D,
-	0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01,
-	0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
-	0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
-	0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
-	0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF,
-	0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40,
-	0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF,
-	0x31, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2E, 0x00, 0x52, 0xFF, 0xBC,
-	0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1, 0x11, 0x2E, 0x6B, 0x32,
-	0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94, 0x01, 0x67, 0xFF, 0x26,
-	0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE0, 0x01,
-	0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2, 0x38, 0x2A,
-	0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF, 0x16, 0x00,
-	0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48,
-	0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3,
-	0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03,
-	0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC,
-	0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D,
-	0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00,
-	0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
-	0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
-	0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0x00,
-	0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03,
-	0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C,
-	0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0x1D, 0x00,
-	0x8A, 0xFF, 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6,
-	0x02, 0xF2, 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE,
-	0x1E, 0x01, 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAC,
-	0xFF, 0xAE, 0x00, 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD,
-	0xFD, 0x47, 0x0E, 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C,
-	0x01, 0x61, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF,
-	0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B,
-	0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01,
-	0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
-	0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
-	0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
-	0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF,
-	0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52,
-	0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
-	0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1C, 0x00, 0x86, 0xFF, 0x59,
-	0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1, 0x04, 0x37, 0xF3, 0x28,
-	0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x41, 0xFF, 0x33,
-	0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01,
-	0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E,
-	0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00,
-	0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37,
-	0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1,
-	0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE,
-	0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC,
-	0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F,
-	0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00,
-	0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
-	0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
-	0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0xFF,
-	0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05,
-	0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE,
-	0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00,
-	0x28, 0x00, 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8,
-	0xF9, 0x0E, 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01,
-	0x05, 0xFF, 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0x00, 0x00, 0x20,
-	0x00, 0x7F, 0xFF, 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC,
-	0x9B, 0x04, 0xF2, 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50,
-	0xFE, 0x04, 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0x17, 0x00, 0xA1, 0xFF,
-	0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70,
-	0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01,
-	0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
-	0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
-	0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
-	0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00,
-	0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B,
-	0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF,
-	0x34, 0x00, 0xFE, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xD4, 0xFF, 0xBF,
-	0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3, 0x98, 0x3E, 0xF3, 0x1E,
-	0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36,
-	0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF, 0x39, 0x01,
-	0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0, 0x26, 0x4B,
-	0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF, 0x35, 0x00,
-	0xFD, 0xFF, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90,
-	0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1,
-	0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD,
-	0xFF, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC,
-	0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB,
-	0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF,
-	0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
-	0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
-	0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFE,
-	0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06,
-	0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49,
-	0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFF, 0xFF,
-	0x32, 0x00, 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E,
-	0xF6, 0x68, 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF,
-	0xEA, 0xFF, 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x2B,
-	0x00, 0x59, 0xFF, 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8,
-	0x2D, 0x0D, 0x69, 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C,
-	0xFF, 0x93, 0x00, 0xB6, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00,
-	0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83,
-	0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE,
-	0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
-	0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
-	0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
-	0xFF, 0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00,
-	0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7,
-	0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF,
-	0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD9, 0xFF, 0x37, 0x00, 0xF7,
-	0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7, 0x53, 0x44, 0xFB, 0x14,
-	0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE, 0x01, 0x42, 0xFF, 0x32,
-	0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF, 0x93, 0x00,
-	0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94, 0x1C, 0x47,
-	0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00,
-	0xFE, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57,
-	0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2,
-	0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD,
-	0xFF, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC,
-	0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29,
-	0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
-	0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
-	0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
-	0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0xFD,
-	0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07,
-	0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C,
-	0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
-	0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB,
-	0xF3, 0x5B, 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD,
-	0xB4, 0x00, 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33,
-	0x00, 0x3E, 0xFF, 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5,
-	0xB6, 0x16, 0x77, 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D,
-	0x00, 0x25, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
-	0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59,
-	0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF,
-	0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x25, 0x00, 0x6C,
-	0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
-	0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
-	0x00, 0x9E, 0xFF, 0x17, 0x00, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00,
-	0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13,
-	0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF,
-	0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAE, 0xFF, 0xA7, 0x00, 0x12,
-	0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD, 0xDC, 0x47, 0x95, 0x0B,
-	0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71, 0x01, 0x5F, 0xFF, 0x29,
-	0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00, 0xC3, 0xFF,
-	0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2, 0x12, 0x19,
-	0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF, 0x30, 0x00,
-	0xFF, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85,
-	0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4,
-	0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE,
-	0xFF, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD,
-	0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6,
-	0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-	0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
-	0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
-	0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0xFD,
-	0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07,
-	0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78,
-	0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-	0x34, 0x00, 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E,
-	0xF2, 0x60, 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC,
-	0x51, 0x01, 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-	0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3,
-	0xBA, 0x20, 0x61, 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE,
-	0x00, 0xC5, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-	0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C,
-	0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00,
-	0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
-	0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
-	0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
-	0x00, 0xCB, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF,
-	0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D,
-	0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00,
-	0xA9, 0xFF, 0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x82, 0xFF, 0x18,
-	0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC, 0x24, 0x04, 0xF5, 0x48,
-	0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42, 0xFE, 0x0B, 0x01, 0x87,
-	0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00, 0xDB, 0xFE,
-	0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81, 0x09, 0x61,
-	0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF, 0x26, 0x00,
-	0x00, 0x00, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06,
-	0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7,
-	0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF,
-	0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE,
-	0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00,
-	0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF,
-	0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
-	0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
-	0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-	0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06,
-	0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33,
-	0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-	0x28, 0x00, 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E,
-	0xF1, 0xE3, 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC,
-	0xB7, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x32,
-	0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1,
-	0xAE, 0x2A, 0x86, 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E,
-	0x01, 0x7B, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
-	0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18,
-	0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01,
-	0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-	0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
-	0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
-	0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF,
-	0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC,
-	0x44, 0x14, 0xF8, 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00,
-	0xD5, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B, 0xFF, 0x7C,
-	0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9, 0xA4, 0x0C, 0x90, 0x47,
-	0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E, 0xFF, 0x99, 0x00, 0xB3,
-	0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF, 0x31, 0x01,
-	0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB, 0x48, 0x73,
-	0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00, 0x91, 0xFF,
-	0x1B, 0x00, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB,
-	0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB,
-	0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00,
-	0x00, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00,
-	0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1,
-	0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF,
-	0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
-	0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
-	0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x04,
-	0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04,
-	0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55,
-	0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00,
-	0x11, 0x00, 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74,
-	0xF2, 0x54, 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC,
-	0xE4, 0x01, 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x23,
-	0x00, 0x71, 0xFF, 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1,
-	0xFD, 0x33, 0x62, 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7,
-	0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2F, 0x00,
-	0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2,
-	0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01,
-	0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
-	0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
-	0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
-	0xFF, 0x13, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-	0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E,
-	0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF,
-	0xFB, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC5,
-	0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6, 0x22, 0x16, 0xC3, 0x43,
-	0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11, 0x00, 0x2B, 0x00, 0xDE,
-	0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x90, 0x01,
-	0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1, 0x46, 0xE1,
-	0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00, 0xBE, 0xFF,
-	0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC,
-	0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF,
-	0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18,
-	0x00, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02,
-	0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8,
-	0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00,
-	0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
-	0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
-	0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x0B,
-	0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02,
-	0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF,
-	0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x05, 0x00,
-	0xF0, 0xFF, 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F,
-	0xF5, 0x32, 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC,
-	0xDA, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
-	0x00, 0xB6, 0xFF, 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2,
-	0x1C, 0x3C, 0x81, 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6,
-	0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1E, 0x00,
-	0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06,
-	0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
-	0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
-	0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
-	0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
-	0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF,
-	0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE,
-	0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF,
-	0x19, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6,
-	0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3, 0x22, 0x20, 0xCA, 0x3D,
-	0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4, 0x00, 0xCA, 0xFF, 0x03,
-	0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01,
-	0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89, 0x42, 0x02,
-	0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00, 0xE8, 0xFF,
-	0x07, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6,
-	0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9,
-	0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E,
-	0x00, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD,
-	0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B,
-	0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00,
-	0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
-	0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
-	0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00,
-	0x00, 0xF4, 0xFF, 0x1A, 0x00, 0xFF, 0x00, 0x07, 0x03, 0x16, 0x06,
-	0x7C, 0x09, 0x2A, 0x0C, 0x2E, 0x0D, 0x2A, 0x0C, 0x7C, 0x09, 0x16,
-	0x06, 0x07, 0x03, 0xFF, 0x00, 0x1A, 0x00, 0xF4, 0xFF, 0xF2, 0xFF,
-	0xA0, 0xFF, 0x71, 0xFF, 0x71, 0x00, 0x86, 0x03, 0x73, 0x08, 0x88,
-	0x0D, 0x78, 0x10, 0xC9, 0x0F, 0xD5, 0x0B, 0x8B, 0x06, 0x28, 0x02,
-	0xDF, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDC,
-	0xFF, 0x80, 0xFF, 0x9A, 0xFF, 0x46, 0x01, 0x1E, 0x05, 0x5A, 0x0A,
-	0xED, 0x0E, 0xAA, 0x10, 0xAF, 0x0E, 0xFD, 0x09, 0xCB, 0x04, 0x18,
-	0x01, 0x8E, 0xFF, 0x85, 0xFF, 0xE1, 0xFF, 0xFC, 0xFF, 0xBD, 0xFF,
-	0x6D, 0xFF, 0xF6, 0xFF, 0x65, 0x02, 0xE5, 0x06, 0x2B, 0x0C, 0xF3,
-	0x0F, 0x60, 0x10, 0x3B, 0x0D, 0x16, 0x08, 0x3F, 0x03, 0x50, 0x00,
-	0x6E, 0xFF, 0xA7, 0xFF, 0xF5, 0xFF, 0xEF, 0xFF, 0x9A, 0xFF, 0x75,
-	0xFF, 0x91, 0x00, 0xC9, 0x03, 0xC8, 0x08, 0xCC, 0x0D, 0x89, 0x10,
-	0x9F, 0x0F, 0x85, 0x0B, 0x3B, 0x06, 0xF4, 0x01, 0xCD, 0xFF, 0x72,
-	0xFF, 0xC9, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD7, 0xFF, 0x7B, 0xFF,
-	0xA5, 0xFF, 0x73, 0x01, 0x6A, 0x05, 0xAD, 0x0A, 0x21, 0x0F, 0xA6,
-	0x10, 0x74, 0x0E, 0xA9, 0x09, 0x83, 0x04, 0xF0, 0x00, 0x85, 0xFF,
-	0x8B, 0xFF, 0xE5, 0xFF, 0xFA, 0xFF, 0xB7, 0xFF, 0x6C, 0xFF, 0x0C,
-	0x00, 0x9D, 0x02, 0x37, 0x07, 0x78, 0x0C, 0x15, 0x10, 0x47, 0x10,
-	0xF3, 0x0C, 0xC2, 0x07, 0x01, 0x03, 0x35, 0x00, 0x6D, 0xFF, 0xAD,
-	0xFF, 0xF7, 0xFF, 0xEB, 0xFF, 0x94, 0xFF, 0x7A, 0xFF, 0xB3, 0x00,
-	0x0D, 0x04, 0x1C, 0x09, 0x0D, 0x0E, 0x97, 0x10, 0x73, 0x0F, 0x35,
-	0x0B, 0xEB, 0x05, 0xC1, 0x01, 0xBD, 0xFF, 0x75, 0xFF, 0xCE, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x77, 0xFF, 0xB3, 0xFF, 0xA1,
-	0x01, 0xB7, 0x05, 0xFF, 0x0A, 0x53, 0x0F, 0x9E, 0x10, 0x37, 0x0E,
-	0x55, 0x09, 0x3B, 0x04, 0xCB, 0x00, 0x7E, 0xFF, 0x90, 0xFF, 0xE9,
-	0xFF, 0xF8, 0xFF, 0xB1, 0xFF, 0x6C, 0xFF, 0x24, 0x00, 0xD8, 0x02,
-	0x8A, 0x07, 0xC2, 0x0C, 0x34, 0x10, 0x2A, 0x10, 0xAA, 0x0C, 0x6F,
-	0x07, 0xC4, 0x02, 0x1C, 0x00, 0x6C, 0xFF, 0xB3, 0xFF, 0xF9, 0xFF,
-	0xE8, 0xFF, 0x8E, 0xFF, 0x80, 0xFF, 0xD7, 0x00, 0x53, 0x04, 0x71,
-	0x09, 0x4C, 0x0E, 0xA1, 0x10, 0x43, 0x0F, 0xE3, 0x0A, 0x9D, 0x05,
-	0x91, 0x01, 0xAE, 0xFF, 0x79, 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF,
-	0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC2, 0xFF, 0xD2, 0x01, 0x06, 0x06,
-	0x50, 0x0B, 0x82, 0x0F, 0x93, 0x10, 0xF8, 0x0D, 0x00, 0x09, 0xF6,
-	0x03, 0xA7, 0x00, 0x78, 0xFF, 0x96, 0xFF, 0xEC, 0xFF, 0xF6, 0xFF,
-	0xAB, 0xFF, 0x6D, 0xFF, 0x3E, 0x00, 0x15, 0x03, 0xDE, 0x07, 0x0B,
-	0x0D, 0x50, 0x10, 0x0A, 0x10, 0x5E, 0x0C, 0x1C, 0x07, 0x8A, 0x02,
-	0x04, 0x00, 0x6C, 0xFF, 0xB9, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF, 0x89,
-	0xFF, 0x88, 0xFF, 0xFD, 0x00, 0x9B, 0x04, 0xC5, 0x09, 0x88, 0x0E,
-	0xA8, 0x10, 0x10, 0x0F, 0x91, 0x0A, 0x50, 0x05, 0x64, 0x01, 0xA1,
-	0xFF, 0x7D, 0xFF, 0xD9, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF,
-	0x71, 0xFF, 0xD3, 0xFF, 0x05, 0x02, 0x55, 0x06, 0xA0, 0x0B, 0xAD,
-	0x0F, 0x84, 0x10, 0xB6, 0x0D, 0xAC, 0x08, 0xB3, 0x03, 0x86, 0x00,
-	0x74, 0xFF, 0x9C, 0xFF, 0xF0, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF, 0x6F,
-	0xFF, 0x5A, 0x00, 0x54, 0x03, 0x32, 0x08, 0x52, 0x0D, 0x68, 0x10,
-	0xE6, 0x0F, 0x11, 0x0C, 0xCA, 0x06, 0x52, 0x02, 0xEF, 0xFF, 0x6E,
-	0xFF, 0xBF, 0xFF, 0xFC, 0xFF, 0xDF, 0xFF, 0x84, 0xFF, 0x91, 0xFF,
-	0x25, 0x01, 0xE4, 0x04, 0x19, 0x0A, 0xC2, 0x0E, 0xAA, 0x10, 0xDA,
-	0x0E, 0x3E, 0x0A, 0x05, 0x05, 0x38, 0x01, 0x96, 0xFF, 0x81, 0xFF,
-	0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE6,
-	0xFF, 0x3A, 0x02, 0xA6, 0x06, 0xEF, 0x0B, 0xD6, 0x0F, 0x71, 0x10,
-	0x71, 0x0D, 0x57, 0x08, 0x71, 0x03, 0x67, 0x00, 0x70, 0xFF, 0xA2,
-	0xFF, 0xF3, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x78, 0x00,
-	0x95, 0x03, 0x86, 0x08, 0x98, 0x0D, 0x7C, 0x10, 0xC0, 0x0F, 0xC3,
-	0x0B, 0x79, 0x06, 0x1C, 0x02, 0xDB, 0xFF, 0x70, 0xFF, 0xC5, 0xFF,
-	0xFE, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9C, 0xFF, 0x50,
-	0x01, 0x2F, 0x05, 0x6C, 0x0A, 0xF9, 0x0E, 0xA9, 0x10, 0xA2, 0x0E,
-	0xEA, 0x09, 0xBB, 0x04, 0x0F, 0x01, 0x8C, 0xFF, 0x87, 0xFF, 0xE2,
-	0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xFA, 0xFF, 0x71, 0x02,
-	0xF7, 0x06, 0x3C, 0x0C, 0xFB, 0x0F, 0x5B, 0x10, 0x2B, 0x0D, 0x03,
-	0x08, 0x31, 0x03, 0x4A, 0x00, 0x6E, 0xFF, 0xA8, 0xFF, 0xF5, 0xFF,
-	0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x98, 0x00, 0xD8, 0x03, 0xDB,
-	0x08, 0xDB, 0x0D, 0x8D, 0x10, 0x96, 0x0F, 0x73, 0x0B, 0x29, 0x06,
-	0xE8, 0x01, 0xC9, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF, 0x00,
-	0x00, 0xD6, 0xFF, 0x7A, 0xFF, 0xA8, 0xFF, 0x7D, 0x01, 0x7B, 0x05,
-	0xBF, 0x0A, 0x2D, 0x0F, 0xA5, 0x10, 0x67, 0x0E, 0x96, 0x09, 0x73,
-	0x04, 0xE7, 0x00, 0x84, 0xFF, 0x8C, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF,
-	0xB6, 0xFF, 0x6C, 0xFF, 0x11, 0x00, 0xAA, 0x02, 0x4A, 0x07, 0x88,
-	0x0C, 0x1C, 0x10, 0x41, 0x10, 0xE3, 0x0C, 0xAF, 0x07, 0xF3, 0x02,
-	0x2F, 0x00, 0x6C, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEA, 0xFF, 0x93,
-	0xFF, 0x7B, 0xFF, 0xBB, 0x00, 0x1C, 0x04, 0x2F, 0x09, 0x1B, 0x0E,
-	0x9A, 0x10, 0x68, 0x0F, 0x23, 0x0B, 0xDA, 0x05, 0xB7, 0x01, 0xB9,
-	0xFF, 0x76, 0xFF, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1, 0xFF,
-	0x76, 0xFF, 0xB6, 0xFF, 0xAC, 0x01, 0xC8, 0x05, 0x11, 0x0B, 0x5E,
-	0x0F, 0x9C, 0x10, 0x29, 0x0E, 0x42, 0x09, 0x2C, 0x04, 0xC2, 0x00,
-	0x7D, 0xFF, 0x92, 0xFF, 0xEA, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF, 0x6C,
-	0xFF, 0x29, 0x00, 0xE6, 0x02, 0x9D, 0x07, 0xD3, 0x0C, 0x3B, 0x10,
-	0x23, 0x10, 0x99, 0x0C, 0x5C, 0x07, 0xB7, 0x02, 0x16, 0x00, 0x6C,
-	0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8D, 0xFF, 0x82, 0xFF,
-	0xDF, 0x00, 0x63, 0x04, 0x84, 0x09, 0x59, 0x0E, 0xA3, 0x10, 0x38,
-	0x0F, 0xD1, 0x0A, 0x8C, 0x05, 0x87, 0x01, 0xAB, 0xFF, 0x79, 0xFF,
-	0xD5, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC6,
-	0xFF, 0xDD, 0x01, 0x17, 0x06, 0x62, 0x0B, 0x8C, 0x0F, 0x90, 0x10,
-	0xE9, 0x0D, 0xED, 0x08, 0xE7, 0x03, 0xA0, 0x00, 0x77, 0xFF, 0x97,
-	0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xA9, 0xFF, 0x6D, 0xFF, 0x44, 0x00,
-	0x23, 0x03, 0xF1, 0x07, 0x1B, 0x0D, 0x55, 0x10, 0x02, 0x10, 0x4D,
-	0x0C, 0x0A, 0x07, 0x7E, 0x02, 0xFF, 0xFF, 0x6D, 0xFF, 0xBA, 0xFF,
-	0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x8A, 0xFF, 0x06, 0x01, 0xAB,
-	0x04, 0xD8, 0x09, 0x95, 0x0E, 0xA9, 0x10, 0x05, 0x0F, 0x7F, 0x0A,
-	0x40, 0x05, 0x5A, 0x01, 0x9F, 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00,
-	0x00, 0xFE, 0xFF, 0xC6, 0xFF, 0x70, 0xFF, 0xD7, 0xFF, 0x10, 0x02,
-	0x67, 0x06, 0xB1, 0x0B, 0xB7, 0x0F, 0x80, 0x10, 0xA7, 0x0D, 0x99,
-	0x08, 0xA4, 0x03, 0x7F, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0, 0xFF,
-	0xF3, 0xFF, 0xA3, 0xFF, 0x70, 0xFF, 0x60, 0x00, 0x62, 0x03, 0x45,
-	0x08, 0x62, 0x0D, 0x6C, 0x10, 0xDE, 0x0F, 0x00, 0x0C, 0xB8, 0x06,
-	0x46, 0x02, 0xEA, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFD, 0xFF, 0x00,
-	0x00, 0xDE, 0xFF, 0x83, 0xFF, 0x94, 0xFF, 0x2F, 0x01, 0xF4, 0x04,
-	0x2B, 0x0A, 0xCE, 0x0E, 0xAA, 0x10, 0xCE, 0x0E, 0x2B, 0x0A, 0xF4,
-	0x04, 0x2F, 0x01, 0x94, 0xFF, 0x83, 0xFF, 0xDE, 0xFF, 0xFD, 0xFF,
-	0xC0, 0xFF, 0x6E, 0xFF, 0xEA, 0xFF, 0x46, 0x02, 0xB8, 0x06, 0x00,
-	0x0C, 0xDE, 0x0F, 0x6C, 0x10, 0x62, 0x0D, 0x45, 0x08, 0x62, 0x03,
-	0x60, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D,
-	0xFF, 0x73, 0xFF, 0x7F, 0x00, 0xA4, 0x03, 0x99, 0x08, 0xA7, 0x0D,
-	0x80, 0x10, 0xB7, 0x0F, 0xB1, 0x0B, 0x67, 0x06, 0x10, 0x02, 0xD7,
-	0xFF, 0x70, 0xFF, 0xC6, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA, 0xFF,
-	0x7E, 0xFF, 0x9F, 0xFF, 0x5A, 0x01, 0x40, 0x05, 0x7F, 0x0A, 0x05,
-	0x0F, 0xA9, 0x10, 0x95, 0x0E, 0xD8, 0x09, 0xAB, 0x04, 0x06, 0x01,
-	0x8A, 0xFF, 0x88, 0xFF, 0xE3, 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D,
-	0xFF, 0xFF, 0xFF, 0x7E, 0x02, 0x0A, 0x07, 0x4D, 0x0C, 0x02, 0x10,
-	0x55, 0x10, 0x1B, 0x0D, 0xF1, 0x07, 0x23, 0x03, 0x44, 0x00, 0x6D,
-	0xFF, 0xA9, 0xFF, 0xF6, 0xFF, 0xED, 0xFF, 0x97, 0xFF, 0x77, 0xFF,
-	0xA0, 0x00, 0xE7, 0x03, 0xED, 0x08, 0xE9, 0x0D, 0x90, 0x10, 0x8C,
-	0x0F, 0x62, 0x0B, 0x17, 0x06, 0xDD, 0x01, 0xC6, 0xFF, 0x73, 0xFF,
-	0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x79, 0xFF, 0xAB,
-	0xFF, 0x87, 0x01, 0x8C, 0x05, 0xD1, 0x0A, 0x38, 0x0F, 0xA3, 0x10,
-	0x59, 0x0E, 0x84, 0x09, 0x63, 0x04, 0xDF, 0x00, 0x82, 0xFF, 0x8D,
-	0xFF, 0xE7, 0xFF, 0xF9, 0xFF, 0xB4, 0xFF, 0x6C, 0xFF, 0x16, 0x00,
-	0xB7, 0x02, 0x5C, 0x07, 0x99, 0x0C, 0x23, 0x10, 0x3B, 0x10, 0xD3,
-	0x0C, 0x9D, 0x07, 0xE6, 0x02, 0x29, 0x00, 0x6C, 0xFF, 0xB0, 0xFF,
-	0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7D, 0xFF, 0xC2, 0x00, 0x2C,
-	0x04, 0x42, 0x09, 0x29, 0x0E, 0x9C, 0x10, 0x5E, 0x0F, 0x11, 0x0B,
-	0xC8, 0x05, 0xAC, 0x01, 0xB6, 0xFF, 0x76, 0xFF, 0xD1, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB9, 0xFF, 0xB7, 0x01,
-	0xDA, 0x05, 0x23, 0x0B, 0x68, 0x0F, 0x9A, 0x10, 0x1B, 0x0E, 0x2F,
-	0x09, 0x1C, 0x04, 0xBB, 0x00, 0x7B, 0xFF, 0x93, 0xFF, 0xEA, 0xFF,
-	0xF7, 0xFF, 0xAE, 0xFF, 0x6C, 0xFF, 0x2F, 0x00, 0xF3, 0x02, 0xAF,
-	0x07, 0xE3, 0x0C, 0x41, 0x10, 0x1C, 0x10, 0x88, 0x0C, 0x4A, 0x07,
-	0xAA, 0x02, 0x11, 0x00, 0x6C, 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE6,
-	0xFF, 0x8C, 0xFF, 0x84, 0xFF, 0xE7, 0x00, 0x73, 0x04, 0x96, 0x09,
-	0x67, 0x0E, 0xA5, 0x10, 0x2D, 0x0F, 0xBF, 0x0A, 0x7B, 0x05, 0x7D,
-	0x01, 0xA8, 0xFF, 0x7A, 0xFF, 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
-	0xCA, 0xFF, 0x72, 0xFF, 0xC9, 0xFF, 0xE8, 0x01, 0x29, 0x06, 0x73,
-	0x0B, 0x96, 0x0F, 0x8D, 0x10, 0xDB, 0x0D, 0xDB, 0x08, 0xD8, 0x03,
-	0x98, 0x00, 0x76, 0xFF, 0x99, 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA8,
-	0xFF, 0x6E, 0xFF, 0x4A, 0x00, 0x31, 0x03, 0x03, 0x08, 0x2B, 0x0D,
-	0x5B, 0x10, 0xFB, 0x0F, 0x3C, 0x0C, 0xF7, 0x06, 0x71, 0x02, 0xFA,
-	0xFF, 0x6D, 0xFF, 0xBC, 0xFF, 0xFC, 0xFF, 0xE2, 0xFF, 0x87, 0xFF,
-	0x8C, 0xFF, 0x0F, 0x01, 0xBB, 0x04, 0xEA, 0x09, 0xA2, 0x0E, 0xA9,
-	0x10, 0xF9, 0x0E, 0x6C, 0x0A, 0x2F, 0x05, 0x50, 0x01, 0x9C, 0xFF,
-	0x7F, 0xFF, 0xDB, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF, 0x70,
-	0xFF, 0xDB, 0xFF, 0x1C, 0x02, 0x79, 0x06, 0xC3, 0x0B, 0xC0, 0x0F,
-	0x7C, 0x10, 0x98, 0x0D, 0x86, 0x08, 0x95, 0x03, 0x78, 0x00, 0x72,
-	0xFF, 0x9F, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA2, 0xFF, 0x70, 0xFF,
-	0x67, 0x00, 0x71, 0x03, 0x57, 0x08, 0x71, 0x0D, 0x71, 0x10, 0xD6,
-	0x0F, 0xEF, 0x0B, 0xA6, 0x06, 0x3A, 0x02, 0xE6, 0xFF, 0x6E, 0xFF,
-	0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x96,
-	0xFF, 0x38, 0x01, 0x05, 0x05, 0x3E, 0x0A, 0xDA, 0x0E, 0xAA, 0x10,
-	0xC2, 0x0E, 0x19, 0x0A, 0xE4, 0x04, 0x25, 0x01, 0x91, 0xFF, 0x84,
-	0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xBF, 0xFF, 0x6E, 0xFF, 0xEF, 0xFF,
-	0x52, 0x02, 0xCA, 0x06, 0x11, 0x0C, 0xE6, 0x0F, 0x68, 0x10, 0x52,
-	0x0D, 0x32, 0x08, 0x54, 0x03, 0x5A, 0x00, 0x6F, 0xFF, 0xA5, 0xFF,
-	0xF4, 0xFF, 0xF0, 0xFF, 0x9C, 0xFF, 0x74, 0xFF, 0x86, 0x00, 0xB3,
-	0x03, 0xAC, 0x08, 0xB6, 0x0D, 0x84, 0x10, 0xAD, 0x0F, 0xA0, 0x0B,
-	0x55, 0x06, 0x05, 0x02, 0xD3, 0xFF, 0x71, 0xFF, 0xC7, 0xFF, 0xFE,
-	0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA1, 0xFF, 0x64, 0x01,
-	0x50, 0x05, 0x91, 0x0A, 0x10, 0x0F, 0xA8, 0x10, 0x88, 0x0E, 0xC5,
-	0x09, 0x9B, 0x04, 0xFD, 0x00, 0x88, 0xFF, 0x89, 0xFF, 0xE4, 0xFF,
-	0xFB, 0xFF, 0xB9, 0xFF, 0x6C, 0xFF, 0x04, 0x00, 0x8A, 0x02, 0x1C,
-	0x07, 0x5E, 0x0C, 0x0A, 0x10, 0x50, 0x10, 0x0B, 0x0D, 0xDE, 0x07,
-	0x15, 0x03, 0x3E, 0x00, 0x6D, 0xFF, 0xAB, 0xFF, 0xF6, 0xFF, 0xEC,
-	0xFF, 0x96, 0xFF, 0x78, 0xFF, 0xA7, 0x00, 0xF6, 0x03, 0x00, 0x09,
-	0xF8, 0x0D, 0x93, 0x10, 0x82, 0x0F, 0x50, 0x0B, 0x06, 0x06, 0xD2,
-	0x01, 0xC2, 0xFF, 0x74, 0xFF, 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
-	0xD4, 0xFF, 0x79, 0xFF, 0xAE, 0xFF, 0x91, 0x01, 0x9D, 0x05, 0xE3,
-	0x0A, 0x43, 0x0F, 0xA1, 0x10, 0x4C, 0x0E, 0x71, 0x09, 0x53, 0x04,
-	0xD7, 0x00, 0x80, 0xFF, 0x8E, 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB3,
-	0xFF, 0x6C, 0xFF, 0x1C, 0x00, 0xC4, 0x02, 0x6F, 0x07, 0xAA, 0x0C,
-	0x2A, 0x10, 0x34, 0x10, 0xC2, 0x0C, 0x8A, 0x07, 0xD8, 0x02, 0x24,
-	0x00, 0x6C, 0xFF, 0xB1, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x90, 0xFF,
-	0x7E, 0xFF, 0xCB, 0x00, 0x3B, 0x04, 0x55, 0x09, 0x37, 0x0E, 0x9E,
-	0x10, 0x53, 0x0F, 0xFF, 0x0A, 0xB7, 0x05, 0xA1, 0x01, 0xB3, 0xFF,
-	0x77, 0xFF, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x75,
-	0xFF, 0xBD, 0xFF, 0xC1, 0x01, 0xEB, 0x05, 0x35, 0x0B, 0x73, 0x0F,
-	0x97, 0x10, 0x0D, 0x0E, 0x1C, 0x09, 0x0D, 0x04, 0xB3, 0x00, 0x7A,
-	0xFF, 0x94, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAD, 0xFF, 0x6D, 0xFF,
-	0x35, 0x00, 0x01, 0x03, 0xC2, 0x07, 0xF3, 0x0C, 0x47, 0x10, 0x15,
-	0x10, 0x78, 0x0C, 0x37, 0x07, 0x9D, 0x02, 0x0C, 0x00, 0x6C, 0xFF,
-	0xB7, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF, 0xF0,
-	0x00, 0x83, 0x04, 0xA9, 0x09, 0x74, 0x0E, 0xA6, 0x10, 0x21, 0x0F,
-	0xAD, 0x0A, 0x6A, 0x05, 0x73, 0x01, 0xA5, 0xFF, 0x7B, 0xFF, 0xD7,
-	0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC9, 0xFF, 0x72, 0xFF, 0xCD, 0xFF,
-	0xF4, 0x01, 0x3B, 0x06, 0x85, 0x0B, 0x9F, 0x0F, 0x89, 0x10, 0xCC,
-	0x0D, 0xC8, 0x08, 0xC9, 0x03, 0x91, 0x00, 0x75, 0xFF, 0x9A, 0xFF,
-	0xEF, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x50, 0x00, 0x3F,
-	0x03, 0x16, 0x08, 0x3B, 0x0D, 0x60, 0x10, 0xF3, 0x0F, 0x2B, 0x0C,
-	0xE5, 0x06, 0x65, 0x02, 0xF6, 0xFF, 0x6D, 0xFF, 0xBD, 0xFF, 0xFC,
-	0xFF, 0xE1, 0xFF, 0x85, 0xFF, 0x8E, 0xFF, 0x18, 0x01, 0xCB, 0x04,
-	0xFD, 0x09, 0xAF, 0x0E, 0xAA, 0x10, 0xED, 0x0E, 0x5A, 0x0A, 0x1E,
-	0x05, 0x46, 0x01, 0x9A, 0xFF, 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00,
-	0xFD, 0xFF, 0xC3, 0xFF, 0x6F, 0xFF, 0xDF, 0xFF, 0x28, 0x02, 0x8B,
-	0x06, 0xD5, 0x0B, 0xC9, 0x0F, 0x78, 0x10, 0x88, 0x0D, 0x73, 0x08,
-	0x86, 0x03, 0x71, 0x00, 0x71, 0xFF, 0xA0, 0xFF, 0xF2, 0xFF, 0xF2,
-	0xFF, 0xA1, 0xFF, 0x71, 0xFF, 0x6E, 0x00, 0x7F, 0x03, 0x6A, 0x08,
-	0x81, 0x0D, 0x76, 0x10, 0xCD, 0x0F, 0xDD, 0x0B, 0x94, 0x06, 0x2E,
-	0x02, 0xE1, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
-	0xDC, 0xFF, 0x80, 0xFF, 0x98, 0xFF, 0x42, 0x01, 0x16, 0x05, 0x50,
-	0x0A, 0xE7, 0x0E, 0xAA, 0x10, 0xB5, 0x0E, 0x06, 0x0A, 0xD3, 0x04,
-	0x1C, 0x01, 0x8F, 0xFF, 0x85, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF, 0xBE,
-	0xFF, 0x6D, 0xFF, 0xF3, 0xFF, 0x5E, 0x02, 0xDC, 0x06, 0x23, 0x0C,
-	0xEF, 0x0F, 0x63, 0x10, 0x43, 0x0D, 0x1F, 0x08, 0x46, 0x03, 0x53,
-	0x00, 0x6E, 0xFF, 0xA6, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B, 0xFF,
-	0x75, 0xFF, 0x8D, 0x00, 0xC1, 0x03, 0xBE, 0x08, 0xC4, 0x0D, 0x88,
-	0x10, 0xA4, 0x0F, 0x8E, 0x0B, 0x43, 0x06, 0xF9, 0x01, 0xCF, 0xFF,
-	0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF, 0x7C,
-	0xFF, 0xA4, 0xFF, 0x6E, 0x01, 0x61, 0x05, 0xA3, 0x0A, 0x1C, 0x0F,
-	0xA7, 0x10, 0x7B, 0x0E, 0xB2, 0x09, 0x8B, 0x04, 0xF4, 0x00, 0x86,
-	0xFF, 0x8A, 0xFF, 0xE4, 0xFF, 0xFA, 0xFF, 0xB8, 0xFF, 0x6C, 0xFF,
-	0x09, 0x00, 0x97, 0x02, 0x2E, 0x07, 0x6F, 0x0C, 0x11, 0x10, 0x4A,
-	0x10, 0xFB, 0x0C, 0xCB, 0x07, 0x07, 0x03, 0x38, 0x00, 0x6D, 0xFF,
-	0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF, 0xAF,
-	0x00, 0x05, 0x04, 0x13, 0x09, 0x06, 0x0E, 0x96, 0x10, 0x78, 0x0F,
-	0x3E, 0x0B, 0xF4, 0x05, 0xC7, 0x01, 0xBF, 0xFF, 0x74, 0xFF, 0xCE,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x78, 0xFF, 0xB1, 0xFF,
-	0x9C, 0x01, 0xAE, 0x05, 0xF6, 0x0A, 0x4E, 0x0F, 0x9F, 0x10, 0x3E,
-	0x0E, 0x5E, 0x09, 0x43, 0x04, 0xCF, 0x00, 0x7F, 0xFF, 0x90, 0xFF,
-	0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x21, 0x00, 0xD2,
-	0x02, 0x81, 0x07, 0xBA, 0x0C, 0x31, 0x10, 0x2E, 0x10, 0xB2, 0x0C,
-	0x78, 0x07, 0xCB, 0x02, 0x1E, 0x00, 0x6C, 0xFF, 0xB2, 0xFF, 0xF9,
-	0xFF, 0xE8, 0xFF, 0x8F, 0xFF, 0x80, 0xFF, 0xD3, 0x00, 0x4B, 0x04,
-	0x67, 0x09, 0x45, 0x0E, 0xA0, 0x10, 0x48, 0x0F, 0xEC, 0x0A, 0xA6,
-	0x05, 0x97, 0x01, 0xB0, 0xFF, 0x78, 0xFF, 0xD3, 0xFF, 0x00, 0x00,
-	0xFF, 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC0, 0xFF, 0xCC, 0x01, 0xFD,
-	0x05, 0x47, 0x0B, 0x7D, 0x0F, 0x94, 0x10, 0xFF, 0x0D, 0x0A, 0x09,
-	0xFE, 0x03, 0xAB, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF, 0xF7,
-	0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x3B, 0x00, 0x0E, 0x03, 0xD5, 0x07,
-	0x03, 0x0D, 0x4D, 0x10, 0x0E, 0x10, 0x67, 0x0C, 0x25, 0x07, 0x91,
-	0x02, 0x07, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF,
-	0x89, 0xFF, 0x87, 0xFF, 0xF9, 0x00, 0x93, 0x04, 0xBC, 0x09, 0x82,
-	0x0E, 0xA7, 0x10, 0x16, 0x0F, 0x9A, 0x0A, 0x59, 0x05, 0x69, 0x01,
-	0xA3, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC8,
-	0xFF, 0x71, 0xFF, 0xD1, 0xFF, 0xFF, 0x01, 0x4C, 0x06, 0x97, 0x0B,
-	0xA9, 0x0F, 0x86, 0x10, 0xBD, 0x0D, 0xB5, 0x08, 0xBA, 0x03, 0x8A,
-	0x00, 0x74, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF,
-	0x6F, 0xFF, 0x57, 0x00, 0x4D, 0x03, 0x29, 0x08, 0x4B, 0x0D, 0x65,
-	0x10, 0xEB, 0x0F, 0x1A, 0x0C, 0xD3, 0x06, 0x58, 0x02, 0xF1, 0xFF,
-	0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x84, 0xFF, 0x90,
-	0xFF, 0x21, 0x01, 0xDC, 0x04, 0x10, 0x0A, 0xBB, 0x0E, 0xAA, 0x10,
-	0xE1, 0x0E, 0x47, 0x0A, 0x0D, 0x05, 0x3D, 0x01, 0x97, 0xFF, 0x81,
-	0xFF, 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC2, 0xFF, 0x6F, 0xFF,
-	0xE4, 0xFF, 0x34, 0x02, 0x9D, 0x06, 0xE6, 0x0B, 0xD1, 0x0F, 0x73,
-	0x10, 0x79, 0x0D, 0x61, 0x08, 0x78, 0x03, 0x6A, 0x00, 0x70, 0xFF,
-	0xA1, 0xFF, 0xF2, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x74,
-	0x00, 0x8E, 0x03, 0x7D, 0x08, 0x90, 0x0D, 0x7A, 0x10, 0xC4, 0x0F,
-	0xCC, 0x0B, 0x82, 0x06, 0x22, 0x02, 0xDD, 0xFF, 0x6F, 0xFF, 0xC4,
-	0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9B, 0xFF,
-	0x4B, 0x01, 0x26, 0x05, 0x63, 0x0A, 0xF3, 0x0E, 0xAA, 0x10, 0xA8,
-	0x0E, 0xF4, 0x09, 0xC3, 0x04, 0x13, 0x01, 0x8D, 0xFF, 0x86, 0xFF,
-	0xE1, 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xF8, 0xFF, 0x6B,
-	0x02, 0xEE, 0x06, 0x34, 0x0C, 0xF7, 0x0F, 0x5D, 0x10, 0x33, 0x0D,
-	0x0D, 0x08, 0x38, 0x03, 0x4D, 0x00, 0x6E, 0xFF, 0xA7, 0xFF, 0xF5,
-	0xFF, 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x94, 0x00, 0xD0, 0x03,
-	0xD1, 0x08, 0xD3, 0x0D, 0x8B, 0x10, 0x9A, 0x0F, 0x7C, 0x0B, 0x32,
-	0x06, 0xEE, 0x01, 0xCB, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF,
-	0x00, 0x00, 0xD6, 0xFF, 0x7B, 0xFF, 0xA7, 0xFF, 0x78, 0x01, 0x72,
-	0x05, 0xB6, 0x0A, 0x27, 0x0F, 0xA5, 0x10, 0x6E, 0x0E, 0xA0, 0x09,
-	0x7B, 0x04, 0xEC, 0x00, 0x85, 0xFF, 0x8B, 0xFF, 0xE5, 0xFF, 0xFA,
-	0xFF, 0xB6, 0xFF, 0x6C, 0xFF, 0x0E, 0x00, 0xA4, 0x02, 0x41, 0x07,
-	0x80, 0x0C, 0x19, 0x10, 0x44, 0x10, 0xEB, 0x0C, 0xB9, 0x07, 0xFA,
-	0x02, 0x32, 0x00, 0x6D, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEB, 0xFF,
-	0x93, 0xFF, 0x7B, 0xFF, 0xB7, 0x00, 0x15, 0x04, 0x26, 0x09, 0x14,
-	0x0E, 0x98, 0x10, 0x6D, 0x0F, 0x2C, 0x0B, 0xE3, 0x05, 0xBC, 0x01,
-	0xBB, 0xFF, 0x75, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1,
-	0xFF, 0x77, 0xFF, 0xB5, 0xFF, 0xA6, 0x01, 0xC0, 0x05, 0x08, 0x0B,
-	0x58, 0x0F, 0x9D, 0x10, 0x30, 0x0E, 0x4B, 0x09, 0x34, 0x04, 0xC6,
-	0x00, 0x7D, 0xFF, 0x91, 0xFF, 0xE9, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF,
-	0x6C, 0xFF, 0x27, 0x00, 0xDF, 0x02, 0x94, 0x07, 0xCA, 0x0C, 0x37,
-	0x10, 0x27, 0x10, 0xA1, 0x0C, 0x65, 0x07, 0xBE, 0x02, 0x19, 0x00,
-	0x6C, 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8E, 0xFF, 0x81,
-	0xFF, 0xDB, 0x00, 0x5B, 0x04, 0x7A, 0x09, 0x53, 0x0E, 0xA2, 0x10,
-	0x3D, 0x0F, 0xDA, 0x0A, 0x95, 0x05, 0x8C, 0x01, 0xAD, 0xFF, 0x79,
-	0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCC, 0xFF, 0x73, 0xFF,
-	0xC4, 0xFF, 0xD7, 0x01, 0x0E, 0x06, 0x59, 0x0B, 0x87, 0x0F, 0x91,
-	0x10, 0xF0, 0x0D, 0xF7, 0x08, 0xEF, 0x03, 0xA3, 0x00, 0x78, 0xFF,
-	0x97, 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xAA, 0xFF, 0x6D, 0xFF, 0x41,
-	0x00, 0x1C, 0x03, 0xE7, 0x07, 0x13, 0x0D, 0x52, 0x10, 0x06, 0x10,
-	0x56, 0x0C, 0x13, 0x07, 0x84, 0x02, 0x02, 0x00, 0x6D, 0xFF, 0xBA,
-	0xFF, 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x89, 0xFF, 0x01, 0x01,
-	0xA3, 0x04, 0xCE, 0x09, 0x8F, 0x0E, 0xA8, 0x10, 0x0A, 0x0F, 0x88,
-	0x0A, 0x48, 0x05, 0x5F, 0x01, 0xA0, 0xFF, 0x7D, 0xFF, 0xD9, 0xFF,
-	0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF, 0x70, 0xFF, 0xD5, 0xFF, 0x0B,
-	0x02, 0x5E, 0x06, 0xA9, 0x0B, 0xB2, 0x0F, 0x82, 0x10, 0xAE, 0x0D,
-	0xA2, 0x08, 0xAB, 0x03, 0x82, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0,
-	0xFF, 0xF3, 0xFF, 0xA4, 0xFF, 0x6F, 0xFF, 0x5D, 0x00, 0x5B, 0x03,
-	0x3B, 0x08, 0x5A, 0x0D, 0x6A, 0x10, 0xE2, 0x0F, 0x09, 0x0C, 0xC1,
-	0x06, 0x4C, 0x02, 0xEC, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFC, 0xFF,
-	0xDF, 0xFF, 0x83, 0xFF, 0x93, 0xFF, 0x2A, 0x01, 0xEC, 0x04, 0x22,
-	0x0A, 0xC8, 0x0E, 0xAB, 0x10, 0xD4, 0x0E, 0x35, 0x0A, 0xFD, 0x04,
-	0x33, 0x01, 0x95, 0xFF, 0x82, 0xFF, 0xDE, 0xFF, 0x00, 0x00, 0xFD,
-	0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE8, 0xFF, 0x40, 0x02, 0xAF, 0x06,
-	0xF7, 0x0B, 0xDA, 0x0F, 0x6F, 0x10, 0x6A, 0x0D, 0x4E, 0x08, 0x6A,
-	0x03, 0x64, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF1, 0xFF,
-	0x9E, 0xFF, 0x72, 0xFF, 0x7B, 0x00, 0x9C, 0x03, 0x90, 0x08, 0x9F,
-	0x0D, 0x7E, 0x10, 0xBB, 0x0F, 0xBA, 0x0B, 0x70, 0x06, 0x16, 0x02,
-	0xD9, 0xFF, 0x70, 0xFF, 0xC5, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA,
-	0xFF, 0x7E, 0xFF, 0x9D, 0xFF, 0x55, 0x01, 0x37, 0x05, 0x75, 0x0A,
-	0xFF, 0x0E, 0xA9, 0x10, 0x9C, 0x0E, 0xE1, 0x09, 0xB3, 0x04, 0x0A,
-	0x01, 0x8B, 0xFF, 0x87, 0xFF, 0xE2, 0xFF, 0xFB, 0xFF, 0xBB, 0xFF,
-	0x6D, 0xFF, 0xFD, 0xFF, 0x77, 0x02, 0x01, 0x07, 0x45, 0x0C, 0xFF,
-	0x0F, 0x58, 0x10, 0x23, 0x0D, 0xFA, 0x07, 0x2A, 0x03, 0x47, 0x00,
-	0x6E, 0xFF, 0xA9, 0xFF, 0xF5, 0xFF, 0xED, 0xFF, 0x98, 0xFF, 0x77,
-	0xFF, 0x9C, 0x00, 0xDF, 0x03, 0xE4, 0x08, 0xE2, 0x0D, 0x8E, 0x10,
-	0x91, 0x0F, 0x6B, 0x0B, 0x20, 0x06, 0xE3, 0x01, 0xC8, 0xFF, 0x73,
-	0xFF, 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x7A, 0xFF,
-	0xAA, 0xFF, 0x82, 0x01, 0x83, 0x05, 0xC8, 0x0A, 0x32, 0x0F, 0xA4,
-	0x10, 0x60, 0x0E, 0x8D, 0x09, 0x6B, 0x04, 0xE3, 0x00, 0x83, 0xFF,
-	0x8D, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF, 0xB5, 0xFF, 0x6C, 0xFF, 0x14,
-	0x00, 0xB1, 0x02, 0x53, 0x07, 0x91, 0x0C, 0x20, 0x10, 0x3E, 0x10,
-	0xDB, 0x0C, 0xA6, 0x07, 0xEC, 0x02, 0x2C, 0x00, 0x6C, 0xFF, 0xAF,
-	0xFF, 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7C, 0xFF, 0xBE, 0x00,
-	0x24, 0x04, 0x38, 0x09, 0x22, 0x0E, 0x9B, 0x10, 0x63, 0x0F, 0x1A,
-	0x0B, 0xD1, 0x05, 0xB1, 0x01, 0xB8, 0xFF, 0x76, 0xFF, 0xD0, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB8, 0xFF, 0xB1,
-	0x01, 0xD1, 0x05, 0x1A, 0x0B, 0x63, 0x0F, 0x9B, 0x10, 0x22, 0x0E,
-	0x38, 0x09, 0x24, 0x04, 0xBE, 0x00, 0x7C, 0xFF, 0x92, 0xFF, 0xEA,
-	0xFF, 0xF8, 0xFF, 0xAF, 0xFF, 0x6C, 0xFF, 0x2C, 0x00, 0xEC, 0x02,
-	0xA6, 0x07, 0xDB, 0x0C, 0x3E, 0x10, 0x20, 0x10, 0x91, 0x0C, 0x53,
-	0x07, 0xB1, 0x02, 0x14, 0x00, 0x6C, 0xFF, 0xB5, 0xFF, 0xFA, 0xFF,
-	0xE6, 0xFF, 0x8D, 0xFF, 0x83, 0xFF, 0xE3, 0x00, 0x6B, 0x04, 0x8D,
-	0x09, 0x60, 0x0E, 0xA4, 0x10, 0x32, 0x0F, 0xC8, 0x0A, 0x83, 0x05,
-	0x82, 0x01, 0xAA, 0xFF, 0x7A, 0xFF, 0xD5, 0xFF, 0x00, 0x00, 0xFF,
-	0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC8, 0xFF, 0xE3, 0x01, 0x20, 0x06,
-	0x6B, 0x0B, 0x91, 0x0F, 0x8E, 0x10, 0xE2, 0x0D, 0xE4, 0x08, 0xDF,
-	0x03, 0x9C, 0x00, 0x77, 0xFF, 0x98, 0xFF, 0xED, 0xFF, 0xF5, 0xFF,
-	0xA9, 0xFF, 0x6E, 0xFF, 0x47, 0x00, 0x2A, 0x03, 0xFA, 0x07, 0x23,
-	0x0D, 0x58, 0x10, 0xFF, 0x0F, 0x45, 0x0C, 0x01, 0x07, 0x77, 0x02,
-	0xFD, 0xFF, 0x6D, 0xFF, 0xBB, 0xFF, 0xFB, 0xFF, 0xE2, 0xFF, 0x87,
-	0xFF, 0x8B, 0xFF, 0x0A, 0x01, 0xB3, 0x04, 0xE1, 0x09, 0x9C, 0x0E,
-	0xA9, 0x10, 0xFF, 0x0E, 0x75, 0x0A, 0x37, 0x05, 0x55, 0x01, 0x9D,
-	0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF,
-	0x70, 0xFF, 0xD9, 0xFF, 0x16, 0x02, 0x70, 0x06, 0xBA, 0x0B, 0xBB,
-	0x0F, 0x7E, 0x10, 0x9F, 0x0D, 0x90, 0x08, 0x9C, 0x03, 0x7B, 0x00,
-	0x72, 0xFF, 0x9E, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA3, 0xFF, 0x70,
-	0xFF, 0x64, 0x00, 0x6A, 0x03, 0x4E, 0x08, 0x6A, 0x0D, 0x6F, 0x10,
-	0xDA, 0x0F, 0xF7, 0x0B, 0xAF, 0x06, 0x40, 0x02, 0xE8, 0xFF, 0x6E,
-	0xFF, 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDE, 0xFF, 0x82, 0xFF,
-	0x95, 0xFF, 0x33, 0x01, 0xFD, 0x04, 0x35, 0x0A, 0xD4, 0x0E, 0xAB,
-	0x10, 0xC8, 0x0E, 0x22, 0x0A, 0xEC, 0x04, 0x2A, 0x01, 0x93, 0xFF,
-	0x83, 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xC0, 0xFF, 0x6E, 0xFF, 0xEC,
-	0xFF, 0x4C, 0x02, 0xC1, 0x06, 0x09, 0x0C, 0xE2, 0x0F, 0x6A, 0x10,
-	0x5A, 0x0D, 0x3B, 0x08, 0x5B, 0x03, 0x5D, 0x00, 0x6F, 0xFF, 0xA4,
-	0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D, 0xFF, 0x73, 0xFF, 0x82, 0x00,
-	0xAB, 0x03, 0xA2, 0x08, 0xAE, 0x0D, 0x82, 0x10, 0xB2, 0x0F, 0xA9,
-	0x0B, 0x5E, 0x06, 0x0B, 0x02, 0xD5, 0xFF, 0x70, 0xFF, 0xC7, 0xFF,
-	0xFE, 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA0, 0xFF, 0x5F,
-	0x01, 0x48, 0x05, 0x88, 0x0A, 0x0A, 0x0F, 0xA8, 0x10, 0x8F, 0x0E,
-	0xCE, 0x09, 0xA3, 0x04, 0x01, 0x01, 0x89, 0xFF, 0x88, 0xFF, 0xE3,
-	0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D, 0xFF, 0x02, 0x00, 0x84, 0x02,
-	0x13, 0x07, 0x56, 0x0C, 0x06, 0x10, 0x52, 0x10, 0x13, 0x0D, 0xE7,
-	0x07, 0x1C, 0x03, 0x41, 0x00, 0x6D, 0xFF, 0xAA, 0xFF, 0xF6, 0xFF,
-	0xED, 0xFF, 0x97, 0xFF, 0x78, 0xFF, 0xA3, 0x00, 0xEF, 0x03, 0xF7,
-	0x08, 0xF0, 0x0D, 0x91, 0x10, 0x87, 0x0F, 0x59, 0x0B, 0x0E, 0x06,
-	0xD7, 0x01, 0xC4, 0xFF, 0x73, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0x00,
-	0x00, 0xD4, 0xFF, 0x79, 0xFF, 0xAD, 0xFF, 0x8C, 0x01, 0x95, 0x05,
-	0xDA, 0x0A, 0x3D, 0x0F, 0xA2, 0x10, 0x53, 0x0E, 0x7A, 0x09, 0x5B,
-	0x04, 0xDB, 0x00, 0x81, 0xFF, 0x8E, 0xFF, 0xE7, 0xFF, 0xF9, 0xFF,
-	0xB4, 0xFF, 0x6C, 0xFF, 0x19, 0x00, 0xBE, 0x02, 0x65, 0x07, 0xA1,
-	0x0C, 0x27, 0x10, 0x37, 0x10, 0xCA, 0x0C, 0x94, 0x07, 0xDF, 0x02,
-	0x27, 0x00, 0x6C, 0xFF, 0xB0, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x91,
-	0xFF, 0x7D, 0xFF, 0xC6, 0x00, 0x34, 0x04, 0x4B, 0x09, 0x30, 0x0E,
-	0x9D, 0x10, 0x58, 0x0F, 0x08, 0x0B, 0xC0, 0x05, 0xA6, 0x01, 0xB5,
-	0xFF, 0x77, 0xFF, 0xD1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF,
-	0x75, 0xFF, 0xBB, 0xFF, 0xBC, 0x01, 0xE3, 0x05, 0x2C, 0x0B, 0x6D,
-	0x0F, 0x98, 0x10, 0x14, 0x0E, 0x26, 0x09, 0x15, 0x04, 0xB7, 0x00,
-	0x7B, 0xFF, 0x93, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAE, 0xFF, 0x6D,
-	0xFF, 0x32, 0x00, 0xFA, 0x02, 0xB9, 0x07, 0xEB, 0x0C, 0x44, 0x10,
-	0x19, 0x10, 0x80, 0x0C, 0x41, 0x07, 0xA4, 0x02, 0x0E, 0x00, 0x6C,
-	0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF,
-	0xEC, 0x00, 0x7B, 0x04, 0xA0, 0x09, 0x6E, 0x0E, 0xA5, 0x10, 0x27,
-	0x0F, 0xB6, 0x0A, 0x72, 0x05, 0x78, 0x01, 0xA7, 0xFF, 0x7B, 0xFF,
-	0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xCA, 0xFF, 0x72, 0xFF, 0xCB,
-	0xFF, 0xEE, 0x01, 0x32, 0x06, 0x7C, 0x0B, 0x9A, 0x0F, 0x8B, 0x10,
-	0xD3, 0x0D, 0xD1, 0x08, 0xD0, 0x03, 0x94, 0x00, 0x76, 0xFF, 0x99,
-	0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x4D, 0x00,
-	0x38, 0x03, 0x0D, 0x08, 0x33, 0x0D, 0x5D, 0x10, 0xF7, 0x0F, 0x34,
-	0x0C, 0xEE, 0x06, 0x6B, 0x02, 0xF8, 0xFF, 0x6D, 0xFF, 0xBC, 0xFF,
-	0xFC, 0xFF, 0xE1, 0xFF, 0x86, 0xFF, 0x8D, 0xFF, 0x13, 0x01, 0xC3,
-	0x04, 0xF4, 0x09, 0xA8, 0x0E, 0xAA, 0x10, 0xF3, 0x0E, 0x63, 0x0A,
-	0x26, 0x05, 0x4B, 0x01, 0x9B, 0xFF, 0x7F, 0xFF, 0xDB, 0xFF, 0x00,
-	0x00, 0xFD, 0xFF, 0xC4, 0xFF, 0x6F, 0xFF, 0xDD, 0xFF, 0x22, 0x02,
-	0x82, 0x06, 0xCC, 0x0B, 0xC4, 0x0F, 0x7A, 0x10, 0x90, 0x0D, 0x7D,
-	0x08, 0x8E, 0x03, 0x74, 0x00, 0x72, 0xFF, 0x9F, 0xFF, 0xF1, 0xFF,
-	0xF2, 0xFF, 0xA1, 0xFF, 0x70, 0xFF, 0x6A, 0x00, 0x78, 0x03, 0x61,
-	0x08, 0x79, 0x0D, 0x73, 0x10, 0xD1, 0x0F, 0xE6, 0x0B, 0x9D, 0x06,
-	0x34, 0x02, 0xE4, 0xFF, 0x6F, 0xFF, 0xC2, 0xFF, 0xFD, 0xFF, 0x00,
-	0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x97, 0xFF, 0x3D, 0x01, 0x0D, 0x05,
-	0x47, 0x0A, 0xE1, 0x0E, 0xAA, 0x10, 0xBB, 0x0E, 0x10, 0x0A, 0xDC,
-	0x04, 0x21, 0x01, 0x90, 0xFF, 0x84, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF,
-	0xBE, 0xFF, 0x6D, 0xFF, 0xF1, 0xFF, 0x58, 0x02, 0xD3, 0x06, 0x1A,
-	0x0C, 0xEB, 0x0F, 0x65, 0x10, 0x4B, 0x0D, 0x29, 0x08, 0x4D, 0x03,
-	0x57, 0x00, 0x6F, 0xFF, 0xA5, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B,
-	0xFF, 0x74, 0xFF, 0x8A, 0x00, 0xBA, 0x03, 0xB5, 0x08, 0xBD, 0x0D,
-	0x86, 0x10, 0xA9, 0x0F, 0x97, 0x0B, 0x4C, 0x06, 0xFF, 0x01, 0xD1,
-	0xFF, 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF,
-	0x7C, 0xFF, 0xA3, 0xFF, 0x69, 0x01, 0x59, 0x05, 0x9A, 0x0A, 0x16,
-	0x0F, 0xA7, 0x10, 0x82, 0x0E, 0xBC, 0x09, 0x93, 0x04, 0xF9, 0x00,
-	0x87, 0xFF, 0x89, 0xFF, 0xE4, 0xFF, 0xFB, 0xFF, 0xB8, 0xFF, 0x6C,
-	0xFF, 0x07, 0x00, 0x91, 0x02, 0x25, 0x07, 0x67, 0x0C, 0x0E, 0x10,
-	0x4D, 0x10, 0x03, 0x0D, 0xD5, 0x07, 0x0E, 0x03, 0x3B, 0x00, 0x6D,
-	0xFF, 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF,
-	0xAB, 0x00, 0xFE, 0x03, 0x0A, 0x09, 0xFF, 0x0D, 0x94, 0x10, 0x7D,
-	0x0F, 0x47, 0x0B, 0xFD, 0x05, 0xCC, 0x01, 0xC0, 0xFF, 0x74, 0xFF,
-	0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD3, 0xFF, 0x78, 0xFF, 0xB0,
-	0xFF, 0x97, 0x01, 0xA6, 0x05, 0xEC, 0x0A, 0x48, 0x0F, 0xA0, 0x10,
-	0x45, 0x0E, 0x67, 0x09, 0x4B, 0x04, 0xD3, 0x00, 0x80, 0xFF, 0x8F,
-	0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x1E, 0x00,
-	0xCB, 0x02, 0x78, 0x07, 0xB2, 0x0C, 0x2E, 0x10, 0x31, 0x10, 0xBA,
-	0x0C, 0x81, 0x07, 0xD2, 0x02, 0x21, 0x00, 0x6C, 0xFF, 0xB2, 0xFF,
-	0xF9, 0xFF, 0xE8, 0xFF, 0x90, 0xFF, 0x7F, 0xFF, 0xCF, 0x00, 0x43,
-	0x04, 0x5E, 0x09, 0x3E, 0x0E, 0x9F, 0x10, 0x4E, 0x0F, 0xF6, 0x0A,
-	0xAE, 0x05, 0x9C, 0x01, 0xB1, 0xFF, 0x78, 0xFF, 0xD2, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x74, 0xFF, 0xBF, 0xFF, 0xC7, 0x01,
-	0xF4, 0x05, 0x3E, 0x0B, 0x78, 0x0F, 0x96, 0x10, 0x06, 0x0E, 0x13,
-	0x09, 0x05, 0x04, 0xAF, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF,
-	0xF7, 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x38, 0x00, 0x07, 0x03, 0xCB,
-	0x07, 0xFB, 0x0C, 0x4A, 0x10, 0x11, 0x10, 0x6F, 0x0C, 0x2E, 0x07,
-	0x97, 0x02, 0x09, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFA, 0xFF, 0xE4,
-	0xFF, 0x8A, 0xFF, 0x86, 0xFF, 0xF4, 0x00, 0x8B, 0x04, 0xB2, 0x09,
-	0x7B, 0x0E, 0xA7, 0x10, 0x1C, 0x0F, 0xA3, 0x0A, 0x61, 0x05, 0x6E,
-	0x01, 0xA4, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
-	0xC8, 0xFF, 0x71, 0xFF, 0xCF, 0xFF, 0xF9, 0x01, 0x43, 0x06, 0x8E,
-	0x0B, 0xA4, 0x0F, 0x88, 0x10, 0xC4, 0x0D, 0xBE, 0x08, 0xC1, 0x03,
-	0x8D, 0x00, 0x75, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA6,
-	0xFF, 0x6E, 0xFF, 0x53, 0x00, 0x46, 0x03, 0x1F, 0x08, 0x43, 0x0D,
-	0x63, 0x10, 0xEF, 0x0F, 0x23, 0x0C, 0xDC, 0x06, 0x5E, 0x02, 0xF3,
-	0xFF, 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x85, 0xFF,
-	0x8F, 0xFF, 0x1C, 0x01, 0xD3, 0x04, 0x06, 0x0A, 0xB5, 0x0E, 0xAA,
-	0x10, 0xE7, 0x0E, 0x50, 0x0A, 0x16, 0x05, 0x42, 0x01, 0x98, 0xFF,
-	0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC3, 0xFF, 0x6F,
-	0xFF, 0xE1, 0xFF, 0x2E, 0x02, 0x94, 0x06, 0xDD, 0x0B, 0xCD, 0x0F,
-	0x76, 0x10, 0x81, 0x0D, 0x6A, 0x08, 0x7F, 0x03, 0x6E, 0x00, 0x71,
-	0xFF, 0xA1, 0xFF, 0xF2, 0xFF, 0x00, 0x00, 0x15, 0x00, 0xD1, 0xFF,
-	0x8B, 0xFE, 0xBC, 0xFD, 0xE1, 0x00, 0x84, 0x09, 0xB0, 0x13, 0x47,
-	0x18, 0xB0, 0x13, 0x84, 0x09, 0xE1, 0x00, 0xBC, 0xFD, 0x8B, 0xFE,
-	0xD1, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xDA, 0x00, 0x30,
-	0x00, 0x5D, 0xFC, 0xB3, 0xFC, 0x35, 0x0A, 0xC2, 0x1C, 0x24, 0x20,
-	0x48, 0x10, 0x5D, 0xFF, 0x74, 0xFB, 0x3A, 0xFF, 0xFB, 0x00, 0x42,
-	0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2C, 0x00, 0xF3, 0x00, 0xAD, 0xFF,
-	0xC5, 0xFB, 0x11, 0xFE, 0xAF, 0x0D, 0xEF, 0x1E, 0x68, 0x1E, 0xBC,
-	0x0C, 0xA7, 0xFD, 0xEA, 0xFB, 0xD3, 0xFF, 0xEE, 0x00, 0x24, 0x00,
-	0xFA, 0xFF, 0xF7, 0xFF, 0x4C, 0x00, 0xFB, 0x00, 0x0C, 0xFF, 0x5F,
-	0xFB, 0xE8, 0xFF, 0x3D, 0x11, 0x7E, 0x20, 0x13, 0x1C, 0x4C, 0x09,
-	0x6A, 0xFC, 0x8C, 0xFC, 0x4E, 0x00, 0xD1, 0x00, 0x0E, 0x00, 0xFD,
-	0xFF, 0xF7, 0xFF, 0x72, 0x00, 0xEC, 0x00, 0x55, 0xFE, 0x3D, 0xFB,
-	0x37, 0x02, 0xBE, 0x14, 0x5D, 0x21, 0x40, 0x19, 0x18, 0x06, 0xA2,
-	0xFB, 0x47, 0xFD, 0xA7, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0xFC, 0xFF, 0x9B, 0x00, 0xC0, 0x00, 0x92, 0xFD, 0x73,
-	0xFB, 0xF2, 0x04, 0x0E, 0x18, 0x81, 0x21, 0x0C, 0x16, 0x37, 0x03,
-	0x47, 0xFB, 0x0B, 0xFE, 0xDF, 0x00, 0x82, 0x00, 0xF9, 0xFF, 0xFE,
-	0xFF, 0x08, 0x00, 0xC3, 0x00, 0x74, 0x00, 0xD2, 0xFC, 0x10, 0xFC,
-	0x08, 0x08, 0x0A, 0x1B, 0xE9, 0x20, 0x9A, 0x12, 0xBE, 0x00, 0x49,
-	0xFB, 0xC8, 0xFE, 0xF9, 0x00, 0x5A, 0x00, 0xF7, 0xFF, 0xFC, 0xFF,
-	0x1B, 0x00, 0xE4, 0x00, 0x06, 0x00, 0x24, 0xFC, 0x1E, 0xFD, 0x65,
-	0x0B, 0x94, 0x1D, 0x9D, 0x1F, 0x0D, 0x0F, 0xB8, 0xFE, 0x96, 0xFB,
-	0x72, 0xFF, 0xF9, 0x00, 0x37, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x36,
-	0x00, 0xF8, 0x00, 0x78, 0xFF, 0x9B, 0xFB, 0xA6, 0xFE, 0xE9, 0x0E,
-	0x8D, 0x1F, 0xAA, 0x1D, 0x87, 0x0B, 0x2B, 0xFD, 0x1E, 0xFC, 0x02,
-	0x00, 0xE5, 0x00, 0x1C, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x58, 0x00,
-	0xF9, 0x00, 0xCF, 0xFE, 0x4A, 0xFB, 0xA7, 0x00, 0x77, 0x12, 0xE0,
-	0x20, 0x26, 0x1B, 0x28, 0x08, 0x18, 0xFC, 0xCB, 0xFC, 0x71, 0x00,
-	0xC5, 0x00, 0x08, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x80, 0x00, 0xE1,
-	0x00, 0x13, 0xFE, 0x45, 0xFB, 0x1D, 0x03, 0xEB, 0x15, 0x7F, 0x21,
-	0x2D, 0x18, 0x0E, 0x05, 0x77, 0xFB, 0x8B, 0xFD, 0xBE, 0x00, 0x9D,
-	0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA9, 0x00,
-	0xAA, 0x00, 0x4F, 0xFD, 0x9D, 0xFB, 0xFA, 0x05, 0x22, 0x19, 0x62,
-	0x21, 0xE0, 0x14, 0x50, 0x02, 0x3E, 0xFB, 0x4E, 0xFE, 0xEB, 0x00,
-	0x73, 0x00, 0xF7, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xD0, 0x00, 0x52,
-	0x00, 0x93, 0xFC, 0x60, 0xFC, 0x2C, 0x09, 0xFA, 0x1B, 0x8A, 0x20,
-	0x60, 0x11, 0xFD, 0xFF, 0x5C, 0xFB, 0x06, 0xFF, 0xFB, 0x00, 0x4D,
-	0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x23, 0x00, 0xED, 0x00, 0xD9, 0xFF,
-	0xEF, 0xFB, 0x98, 0xFD, 0x99, 0x0C, 0x54, 0x1E, 0x02, 0x1F, 0xD2,
-	0x0D, 0x20, 0xFE, 0xC0, 0xFB, 0xA7, 0xFF, 0xF4, 0x00, 0x2D, 0x00,
-	0xF9, 0xFF, 0xF8, 0xFF, 0x41, 0x00, 0xFB, 0x00, 0x41, 0xFF, 0x78,
-	0xFB, 0x4A, 0xFF, 0x25, 0x10, 0x16, 0x20, 0xDA, 0x1C, 0x56, 0x0A,
-	0xBE, 0xFC, 0x56, 0xFC, 0x2C, 0x00, 0xDB, 0x00, 0x14, 0x00, 0xFD,
-	0xFF, 0xF7, 0xFF, 0x66, 0x00, 0xF4, 0x00, 0x8F, 0xFE, 0x3F, 0xFB,
-	0x75, 0x01, 0xAE, 0x13, 0x2C, 0x21, 0x2A, 0x1A, 0x0D, 0x07, 0xD4,
-	0xFB, 0x0C, 0xFD, 0x8F, 0x00, 0xB7, 0x00, 0x03, 0x00, 0xFF, 0xFF,
-	0x00, 0x00, 0xFA, 0xFF, 0x8E, 0x00, 0xD1, 0x00, 0xCF, 0xFD, 0x58,
-	0xFB, 0x10, 0x04, 0x10, 0x17, 0x8A, 0x21, 0x10, 0x17, 0x10, 0x04,
-	0x58, 0xFB, 0xCF, 0xFD, 0xD1, 0x00, 0x8E, 0x00, 0xFA, 0xFF, 0xFF,
-	0xFF, 0x03, 0x00, 0xB7, 0x00, 0x8F, 0x00, 0x0C, 0xFD, 0xD4, 0xFB,
-	0x0D, 0x07, 0x2A, 0x1A, 0x2C, 0x21, 0xAE, 0x13, 0x75, 0x01, 0x3F,
-	0xFB, 0x8F, 0xFE, 0xF4, 0x00, 0x66, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
-	0x14, 0x00, 0xDB, 0x00, 0x2C, 0x00, 0x56, 0xFC, 0xBE, 0xFC, 0x56,
-	0x0A, 0xDA, 0x1C, 0x16, 0x20, 0x25, 0x10, 0x4A, 0xFF, 0x78, 0xFB,
-	0x41, 0xFF, 0xFB, 0x00, 0x41, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2D,
-	0x00, 0xF4, 0x00, 0xA7, 0xFF, 0xC0, 0xFB, 0x20, 0xFE, 0xD2, 0x0D,
-	0x02, 0x1F, 0x54, 0x1E, 0x99, 0x0C, 0x98, 0xFD, 0xEF, 0xFB, 0xD9,
-	0xFF, 0xED, 0x00, 0x23, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4D, 0x00,
-	0xFB, 0x00, 0x06, 0xFF, 0x5C, 0xFB, 0xFD, 0xFF, 0x60, 0x11, 0x8A,
-	0x20, 0xFA, 0x1B, 0x2C, 0x09, 0x60, 0xFC, 0x93, 0xFC, 0x52, 0x00,
-	0xD0, 0x00, 0x0D, 0x00, 0xFE, 0xFF, 0xF7, 0xFF, 0x73, 0x00, 0xEB,
-	0x00, 0x4E, 0xFE, 0x3E, 0xFB, 0x50, 0x02, 0xE0, 0x14, 0x62, 0x21,
-	0x22, 0x19, 0xFA, 0x05, 0x9D, 0xFB, 0x4F, 0xFD, 0xAA, 0x00, 0xA9,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x9D, 0x00,
-	0xBE, 0x00, 0x8B, 0xFD, 0x77, 0xFB, 0x0E, 0x05, 0x2D, 0x18, 0x7F,
-	0x21, 0xEB, 0x15, 0x1D, 0x03, 0x45, 0xFB, 0x13, 0xFE, 0xE1, 0x00,
-	0x80, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x08, 0x00, 0xC5, 0x00, 0x71,
-	0x00, 0xCB, 0xFC, 0x18, 0xFC, 0x28, 0x08, 0x26, 0x1B, 0xE0, 0x20,
-	0x77, 0x12, 0xA7, 0x00, 0x4A, 0xFB, 0xCF, 0xFE, 0xF9, 0x00, 0x58,
-	0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1C, 0x00, 0xE5, 0x00, 0x02, 0x00,
-	0x1E, 0xFC, 0x2B, 0xFD, 0x87, 0x0B, 0xAA, 0x1D, 0x8D, 0x1F, 0xE9,
-	0x0E, 0xA6, 0xFE, 0x9B, 0xFB, 0x78, 0xFF, 0xF8, 0x00, 0x36, 0x00,
-	0xF9, 0xFF, 0xF8, 0xFF, 0x37, 0x00, 0xF9, 0x00, 0x72, 0xFF, 0x96,
-	0xFB, 0xB8, 0xFE, 0x0D, 0x0F, 0x9D, 0x1F, 0x94, 0x1D, 0x65, 0x0B,
-	0x1E, 0xFD, 0x24, 0xFC, 0x06, 0x00, 0xE4, 0x00, 0x1B, 0x00, 0xFC,
-	0xFF, 0xF7, 0xFF, 0x5A, 0x00, 0xF9, 0x00, 0xC8, 0xFE, 0x49, 0xFB,
-	0xBE, 0x00, 0x9A, 0x12, 0xE9, 0x20, 0x0A, 0x1B, 0x08, 0x08, 0x10,
-	0xFC, 0xD2, 0xFC, 0x74, 0x00, 0xC3, 0x00, 0x08, 0x00, 0xFE, 0xFF,
-	0xF9, 0xFF, 0x82, 0x00, 0xDF, 0x00, 0x0B, 0xFE, 0x47, 0xFB, 0x37,
-	0x03, 0x0C, 0x16, 0x81, 0x21, 0x0E, 0x18, 0xF2, 0x04, 0x73, 0xFB,
-	0x92, 0xFD, 0xC0, 0x00, 0x9B, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0xAB, 0x00, 0xA7, 0x00, 0x47, 0xFD, 0xA2, 0xFB,
-	0x18, 0x06, 0x40, 0x19, 0x5D, 0x21, 0xBE, 0x14, 0x37, 0x02, 0x3D,
-	0xFB, 0x55, 0xFE, 0xEC, 0x00, 0x72, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
-	0x0E, 0x00, 0xD1, 0x00, 0x4E, 0x00, 0x8C, 0xFC, 0x6A, 0xFC, 0x4C,
-	0x09, 0x13, 0x1C, 0x7E, 0x20, 0x3D, 0x11, 0xE8, 0xFF, 0x5F, 0xFB,
-	0x0C, 0xFF, 0xFB, 0x00, 0x4C, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x24,
-	0x00, 0xEE, 0x00, 0xD3, 0xFF, 0xEA, 0xFB, 0xA7, 0xFD, 0xBC, 0x0C,
-	0x68, 0x1E, 0xEF, 0x1E, 0xAF, 0x0D, 0x11, 0xFE, 0xC5, 0xFB, 0xAD,
-	0xFF, 0xF3, 0x00, 0x2C, 0x00, 0xFA, 0xFF, 0xF8, 0xFF, 0x42, 0x00,
-	0xFB, 0x00, 0x3A, 0xFF, 0x74, 0xFB, 0x5D, 0xFF, 0x48, 0x10, 0x24,
-	0x20, 0xC2, 0x1C, 0x35, 0x0A, 0xB3, 0xFC, 0x5D, 0xFC, 0x30, 0x00,
-	0xDA, 0x00, 0x13, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x67, 0x00, 0xF3,
-	0x00, 0x88, 0xFE, 0x3E, 0xFB, 0x8C, 0x01, 0xD0, 0x13, 0x33, 0x21,
-	0x0D, 0x1A, 0xEE, 0x06, 0xCD, 0xFB, 0x13, 0xFD, 0x92, 0x00, 0xB6,
-	0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFA, 0xFF, 0x90, 0x00,
-	0xCF, 0x00, 0xC7, 0xFD, 0x5B, 0xFB, 0x2B, 0x04, 0x31, 0x17, 0x8A,
-	0x21, 0xF0, 0x16, 0xF4, 0x03, 0x56, 0xFB, 0xD6, 0xFD, 0xD3, 0x00,
-	0x8D, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0xB9, 0x00, 0x8C,
-	0x00, 0x05, 0xFD, 0xDB, 0xFB, 0x2C, 0x07, 0x47, 0x1A, 0x25, 0x21,
-	0x8B, 0x13, 0x5D, 0x01, 0x40, 0xFB, 0x97, 0xFE, 0xF5, 0x00, 0x64,
-	0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x15, 0x00, 0xDC, 0x00, 0x27, 0x00,
-	0x50, 0xFC, 0xCA, 0xFC, 0x78, 0x0A, 0xF2, 0x1C, 0x07, 0x20, 0x02,
-	0x10, 0x37, 0xFF, 0x7B, 0xFB, 0x47, 0xFF, 0xFB, 0x00, 0x40, 0x00,
-	0xF8, 0xFF, 0xF9, 0xFF, 0x2E, 0x00, 0xF5, 0x00, 0xA2, 0xFF, 0xBB,
-	0xFB, 0x31, 0xFE, 0xF5, 0x0D, 0x14, 0x1F, 0x3F, 0x1E, 0x77, 0x0C,
-	0x8A, 0xFD, 0xF5, 0xFB, 0xDE, 0xFF, 0xEC, 0x00, 0x22, 0x00, 0xFB,
-	0xFF, 0xF7, 0xFF, 0x4E, 0x00, 0xFB, 0x00, 0xFF, 0xFE, 0x59, 0xFB,
-	0x11, 0x00, 0x83, 0x11, 0x96, 0x20, 0xE0, 0x1B, 0x0B, 0x09, 0x56,
-	0xFC, 0x99, 0xFC, 0x56, 0x00, 0xCE, 0x00, 0x0D, 0x00, 0xFE, 0xFF,
-	0xF8, 0xFF, 0x75, 0x00, 0xEA, 0x00, 0x47, 0xFE, 0x3E, 0xFB, 0x69,
-	0x02, 0x02, 0x15, 0x66, 0x21, 0x04, 0x19, 0xDC, 0x05, 0x98, 0xFB,
-	0x56, 0xFD, 0xAD, 0x00, 0xA8, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
-	0x00, 0xFD, 0xFF, 0x9E, 0x00, 0xBC, 0x00, 0x83, 0xFD, 0x7B, 0xFB,
-	0x2B, 0x05, 0x4C, 0x18, 0x7C, 0x21, 0xCA, 0x15, 0x03, 0x03, 0x44,
-	0xFB, 0x1A, 0xFE, 0xE2, 0x00, 0x7E, 0x00, 0xF8, 0xFF, 0xFE, 0xFF,
-	0x09, 0x00, 0xC6, 0x00, 0x6D, 0x00, 0xC3, 0xFC, 0x20, 0xFC, 0x49,
-	0x08, 0x41, 0x1B, 0xD6, 0x20, 0x54, 0x12, 0x92, 0x00, 0x4C, 0xFB,
-	0xD6, 0xFE, 0xFA, 0x00, 0x57, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1D,
-	0x00, 0xE6, 0x00, 0xFD, 0xFF, 0x18, 0xFC, 0x38, 0xFD, 0xA9, 0x0B,
-	0xC0, 0x1D, 0x7C, 0x1F, 0xC6, 0x0E, 0x95, 0xFE, 0x9F, 0xFB, 0x7E,
-	0xFF, 0xF8, 0x00, 0x35, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x38, 0x00,
-	0xF9, 0x00, 0x6C, 0xFF, 0x92, 0xFB, 0xC9, 0xFE, 0x2F, 0x0F, 0xAD,
-	0x1F, 0x7D, 0x1D, 0x42, 0x0B, 0x12, 0xFD, 0x2A, 0xFC, 0x0B, 0x00,
-	0xE3, 0x00, 0x1A, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5B, 0x00, 0xF8,
-	0x00, 0xC1, 0xFE, 0x47, 0xFB, 0xD4, 0x00, 0xBC, 0x12, 0xF3, 0x20,
-	0xEF, 0x1A, 0xE9, 0x07, 0x08, 0xFC, 0xD9, 0xFC, 0x78, 0x00, 0xC2,
-	0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x83, 0x00, 0xDD, 0x00,
-	0x04, 0xFE, 0x49, 0xFB, 0x52, 0x03, 0x2D, 0x16, 0x83, 0x21, 0xEF,
-	0x17, 0xD5, 0x04, 0x6F, 0xFB, 0x9A, 0xFD, 0xC3, 0x00, 0x9A, 0x00,
-	0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xAD, 0x00, 0xA4,
-	0x00, 0x40, 0xFD, 0xA8, 0xFB, 0x36, 0x06, 0x5E, 0x19, 0x58, 0x21,
-	0x9C, 0x14, 0x1E, 0x02, 0x3D, 0xFB, 0x5D, 0xFE, 0xED, 0x00, 0x70,
-	0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F, 0x00, 0xD2, 0x00, 0x4A, 0x00,
-	0x85, 0xFC, 0x74, 0xFC, 0x6D, 0x09, 0x2D, 0x1C, 0x72, 0x20, 0x1A,
-	0x11, 0xD4, 0xFF, 0x61, 0xFB, 0x13, 0xFF, 0xFC, 0x00, 0x4A, 0x00,
-	0xF7, 0xFF, 0xFA, 0xFF, 0x25, 0x00, 0xEF, 0x00, 0xCE, 0xFF, 0xE4,
-	0xFB, 0xB5, 0xFD, 0xDE, 0x0C, 0x7C, 0x1E, 0xDD, 0x1E, 0x8C, 0x0D,
-	0x01, 0xFE, 0xCA, 0xFB, 0xB3, 0xFF, 0xF3, 0x00, 0x2B, 0x00, 0xFA,
-	0xFF, 0xF8, 0xFF, 0x44, 0x00, 0xFB, 0x00, 0x34, 0xFF, 0x71, 0xFB,
-	0x71, 0xFF, 0x6B, 0x10, 0x32, 0x20, 0xA9, 0x1C, 0x13, 0x0A, 0xA8,
-	0xFC, 0x63, 0xFC, 0x35, 0x00, 0xD9, 0x00, 0x12, 0x00, 0xFD, 0xFF,
-	0xF7, 0xFF, 0x69, 0x00, 0xF2, 0x00, 0x81, 0xFE, 0x3E, 0xFB, 0xA4,
-	0x01, 0xF2, 0x13, 0x3A, 0x21, 0xF0, 0x19, 0xCF, 0x06, 0xC7, 0xFB,
-	0x1B, 0xFD, 0x96, 0x00, 0xB4, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00,
-	0x00, 0xFB, 0xFF, 0x92, 0x00, 0xCD, 0x00, 0xC0, 0xFD, 0x5E, 0xFB,
-	0x47, 0x04, 0x51, 0x17, 0x8A, 0x21, 0xD0, 0x16, 0xD9, 0x03, 0x53,
-	0xFB, 0xDE, 0xFD, 0xD5, 0x00, 0x8B, 0x00, 0xFA, 0xFF, 0xFF, 0xFF,
-	0x04, 0x00, 0xBA, 0x00, 0x89, 0x00, 0xFD, 0xFC, 0xE2, 0xFB, 0x4B,
-	0x07, 0x63, 0x1A, 0x1D, 0x21, 0x69, 0x13, 0x46, 0x01, 0x41, 0xFB,
-	0x9E, 0xFE, 0xF5, 0x00, 0x63, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x16,
-	0x00, 0xDD, 0x00, 0x23, 0x00, 0x49, 0xFC, 0xD5, 0xFC, 0x99, 0x0A,
-	0x09, 0x1D, 0xF9, 0x1F, 0xDF, 0x0F, 0x24, 0xFF, 0x7F, 0xFB, 0x4D,
-	0xFF, 0xFB, 0x00, 0x3F, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2F, 0x00,
-	0xF5, 0x00, 0x9C, 0xFF, 0xB6, 0xFB, 0x41, 0xFE, 0x17, 0x0E, 0x26,
-	0x1F, 0x2B, 0x1E, 0x54, 0x0C, 0x7C, 0xFD, 0xFA, 0xFB, 0xE3, 0xFF,
-	0xEB, 0x00, 0x21, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x50, 0x00, 0xFB,
-	0x00, 0xF8, 0xFE, 0x57, 0xFB, 0x26, 0x00, 0xA6, 0x11, 0xA1, 0x20,
-	0xC6, 0x1B, 0xEA, 0x08, 0x4D, 0xFC, 0xA0, 0xFC, 0x5A, 0x00, 0xCD,
-	0x00, 0x0C, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0xE9, 0x00,
-	0x3F, 0xFE, 0x3F, 0xFB, 0x82, 0x02, 0x23, 0x15, 0x6B, 0x21, 0xE5,
-	0x18, 0xBE, 0x05, 0x93, 0xFB, 0x5E, 0xFD, 0xAF, 0x00, 0xA6, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xA0, 0x00, 0xB9,
-	0x00, 0x7C, 0xFD, 0x80, 0xFB, 0x48, 0x05, 0x6B, 0x18, 0x79, 0x21,
-	0xA9, 0x15, 0xE9, 0x02, 0x43, 0xFB, 0x21, 0xFE, 0xE3, 0x00, 0x7D,
-	0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x09, 0x00, 0xC7, 0x00, 0x69, 0x00,
-	0xBC, 0xFC, 0x29, 0xFC, 0x69, 0x08, 0x5C, 0x1B, 0xCC, 0x20, 0x32,
-	0x12, 0x7C, 0x00, 0x4E, 0xFB, 0xDD, 0xFE, 0xFA, 0x00, 0x56, 0x00,
-	0xF7, 0xFF, 0xFB, 0xFF, 0x1D, 0x00, 0xE7, 0x00, 0xF8, 0xFF, 0x12,
-	0xFC, 0x45, 0xFD, 0xCB, 0x0B, 0xD6, 0x1D, 0x6C, 0x1F, 0xA3, 0x0E,
-	0x84, 0xFE, 0xA4, 0xFB, 0x84, 0xFF, 0xF7, 0x00, 0x34, 0x00, 0xF9,
-	0xFF, 0xF8, 0xFF, 0x3A, 0x00, 0xFA, 0x00, 0x66, 0xFF, 0x8E, 0xFB,
-	0xDB, 0xFE, 0x53, 0x0F, 0xBD, 0x1F, 0x66, 0x1D, 0x21, 0x0B, 0x05,
-	0xFD, 0x30, 0xFC, 0x10, 0x00, 0xE2, 0x00, 0x19, 0x00, 0xFC, 0xFF,
-	0xF7, 0xFF, 0x5D, 0x00, 0xF8, 0x00, 0xBA, 0xFE, 0x46, 0xFB, 0xEA,
-	0x00, 0xDF, 0x12, 0xFC, 0x20, 0xD3, 0x1A, 0xC9, 0x07, 0x00, 0xFC,
-	0xE0, 0xFC, 0x7B, 0x00, 0xC0, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9,
-	0xFF, 0x85, 0x00, 0xDC, 0x00, 0xFC, 0xFD, 0x4A, 0xFB, 0x6C, 0x03,
-	0x4E, 0x16, 0x85, 0x21, 0xCF, 0x17, 0xB8, 0x04, 0x6C, 0xFB, 0xA2,
-	0xFD, 0xC5, 0x00, 0x98, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
-	0x01, 0x00, 0xAE, 0x00, 0xA1, 0x00, 0x38, 0xFD, 0xAE, 0xFB, 0x54,
-	0x06, 0x7C, 0x19, 0x53, 0x21, 0x7B, 0x14, 0x05, 0x02, 0x3D, 0xFB,
-	0x64, 0xFE, 0xEE, 0x00, 0x6F, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F,
-	0x00, 0xD4, 0x00, 0x46, 0x00, 0x7E, 0xFC, 0x7E, 0xFC, 0x8E, 0x09,
-	0x46, 0x1C, 0x66, 0x20, 0xF7, 0x10, 0xC0, 0xFF, 0x64, 0xFB, 0x1A,
-	0xFF, 0xFC, 0x00, 0x49, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x26, 0x00,
-	0xF0, 0x00, 0xC9, 0xFF, 0xDF, 0xFB, 0xC4, 0xFD, 0x01, 0x0D, 0x90,
-	0x1E, 0xCA, 0x1E, 0x69, 0x0D, 0xF1, 0xFD, 0xCF, 0xFB, 0xB8, 0xFF,
-	0xF2, 0x00, 0x29, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x45, 0x00, 0xFC,
-	0x00, 0x2D, 0xFF, 0x6D, 0xFB, 0x84, 0xFF, 0x8E, 0x10, 0x3F, 0x20,
-	0x91, 0x1C, 0xF2, 0x09, 0x9D, 0xFC, 0x6A, 0xFC, 0x39, 0x00, 0xD7,
-	0x00, 0x12, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6A, 0x00, 0xF1, 0x00,
-	0x7A, 0xFE, 0x3D, 0xFB, 0xBC, 0x01, 0x14, 0x14, 0x41, 0x21, 0xD4,
-	0x19, 0xB0, 0x06, 0xC0, 0xFB, 0x22, 0xFD, 0x99, 0x00, 0xB3, 0x00,
-	0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x93, 0x00, 0xCB,
-	0x00, 0xB8, 0xFD, 0x61, 0xFB, 0x63, 0x04, 0x71, 0x17, 0x89, 0x21,
-	0xB0, 0x16, 0xBD, 0x03, 0x51, 0xFB, 0xE6, 0xFD, 0xD7, 0x00, 0x8A,
-	0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0xBC, 0x00, 0x86, 0x00,
-	0xF6, 0xFC, 0xE9, 0xFB, 0x6A, 0x07, 0x80, 0x1A, 0x15, 0x21, 0x47,
-	0x13, 0x2F, 0x01, 0x42, 0xFB, 0xA5, 0xFE, 0xF6, 0x00, 0x61, 0x00,
-	0xF7, 0xFF, 0xFC, 0xFF, 0x16, 0x00, 0xDF, 0x00, 0x1E, 0x00, 0x43,
-	0xFC, 0xE1, 0xFC, 0xBB, 0x0A, 0x21, 0x1D, 0xEA, 0x1F, 0xBC, 0x0F,
-	0x12, 0xFF, 0x82, 0xFB, 0x54, 0xFF, 0xFA, 0x00, 0x3D, 0x00, 0xF8,
-	0xFF, 0xF9, 0xFF, 0x30, 0x00, 0xF6, 0x00, 0x96, 0xFF, 0xB1, 0xFB,
-	0x51, 0xFE, 0x3A, 0x0E, 0x38, 0x1F, 0x16, 0x1E, 0x32, 0x0C, 0x6E,
-	0xFD, 0x00, 0xFC, 0xE8, 0xFF, 0xEA, 0x00, 0x20, 0x00, 0xFB, 0xFF,
-	0xF7, 0xFF, 0x51, 0x00, 0xFB, 0x00, 0xF1, 0xFE, 0x54, 0xFB, 0x3B,
-	0x00, 0xC9, 0x11, 0xAD, 0x20, 0xAC, 0x1B, 0xCA, 0x08, 0x44, 0xFC,
-	0xA7, 0xFC, 0x5E, 0x00, 0xCC, 0x00, 0x0B, 0x00, 0xFE, 0xFF, 0xF8,
-	0xFF, 0x78, 0x00, 0xE7, 0x00, 0x38, 0xFE, 0x40, 0xFB, 0x9B, 0x02,
-	0x45, 0x15, 0x6F, 0x21, 0xC7, 0x18, 0xA1, 0x05, 0x8E, 0xFB, 0x65,
-	0xFD, 0xB2, 0x00, 0xA5, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00,
-	0xFE, 0xFF, 0xA2, 0x00, 0xB7, 0x00, 0x74, 0xFD, 0x84, 0xFB, 0x66,
-	0x05, 0x8A, 0x18, 0x76, 0x21, 0x87, 0x15, 0xCF, 0x02, 0x41, 0xFB,
-	0x29, 0xFE, 0xE5, 0x00, 0x7B, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0A,
-	0x00, 0xC9, 0x00, 0x66, 0x00, 0xB5, 0xFC, 0x32, 0xFC, 0x89, 0x08,
-	0x77, 0x1B, 0xC2, 0x20, 0x0F, 0x12, 0x66, 0x00, 0x50, 0xFB, 0xE4,
-	0xFE, 0xFA, 0x00, 0x54, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1E, 0x00,
-	0xE8, 0x00, 0xF3, 0xFF, 0x0C, 0xFC, 0x53, 0xFD, 0xED, 0x0B, 0xEB,
-	0x1D, 0x5A, 0x1F, 0x80, 0x0E, 0x73, 0xFE, 0xA8, 0xFB, 0x8A, 0xFF,
-	0xF7, 0x00, 0x32, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3B, 0x00, 0xFA,
-	0x00, 0x60, 0xFF, 0x8A, 0xFB, 0xED, 0xFE, 0x76, 0x0F, 0xCC, 0x1F,
-	0x4F, 0x1D, 0xFF, 0x0A, 0xF9, 0xFC, 0x36, 0xFC, 0x15, 0x00, 0xE1,
-	0x00, 0x18, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5E, 0x00, 0xF7, 0x00,
-	0xB3, 0xFE, 0x44, 0xFB, 0x01, 0x01, 0x02, 0x13, 0x04, 0x21, 0xB8,
-	0x1A, 0xA9, 0x07, 0xF8, 0xFB, 0xE7, 0xFC, 0x7F, 0x00, 0xBF, 0x00,
-	0x06, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x86, 0x00, 0xDA, 0x00, 0xF5,
-	0xFD, 0x4C, 0xFB, 0x87, 0x03, 0x6E, 0x16, 0x86, 0x21, 0xB0, 0x17,
-	0x9C, 0x04, 0x68, 0xFB, 0xA9, 0xFD, 0xC7, 0x00, 0x96, 0x00, 0xFB,
-	0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xB0, 0x00, 0x9F, 0x00,
-	0x31, 0xFD, 0xB4, 0xFB, 0x73, 0x06, 0x99, 0x19, 0x4D, 0x21, 0x59,
-	0x14, 0xED, 0x01, 0x3D, 0xFB, 0x6B, 0xFE, 0xEF, 0x00, 0x6D, 0x00,
-	0xF7, 0xFF, 0xFD, 0xFF, 0x10, 0x00, 0xD5, 0x00, 0x42, 0x00, 0x77,
-	0xFC, 0x88, 0xFC, 0xAF, 0x09, 0x5F, 0x1C, 0x59, 0x20, 0xD4, 0x10,
-	0xAC, 0xFF, 0x67, 0xFB, 0x20, 0xFF, 0xFC, 0x00, 0x48, 0x00, 0xF7,
-	0xFF, 0xFA, 0xFF, 0x27, 0x00, 0xF0, 0x00, 0xC3, 0xFF, 0xD9, 0xFB,
-	0xD3, 0xFD, 0x24, 0x0D, 0xA3, 0x1E, 0xB7, 0x1E, 0x46, 0x0D, 0xE2,
-	0xFD, 0xD4, 0xFB, 0xBE, 0xFF, 0xF1, 0x00, 0x28, 0x00, 0xFA, 0xFF,
-	0xF7, 0xFF, 0x46, 0x00, 0xFC, 0x00, 0x27, 0xFF, 0x6A, 0xFB, 0x98,
-	0xFF, 0xB1, 0x10, 0x4C, 0x20, 0x78, 0x1C, 0xD1, 0x09, 0x93, 0xFC,
-	0x71, 0xFC, 0x3D, 0x00, 0xD6, 0x00, 0x11, 0x00, 0xFD, 0xFF, 0xF7,
-	0xFF, 0x6C, 0x00, 0xF0, 0x00, 0x72, 0xFE, 0x3D, 0xFB, 0xD4, 0x01,
-	0x36, 0x14, 0x47, 0x21, 0xB6, 0x19, 0x91, 0x06, 0xBA, 0xFB, 0x29,
-	0xFD, 0x9C, 0x00, 0xB1, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-	0xFB, 0xFF, 0x95, 0x00, 0xC9, 0x00, 0xB1, 0xFD, 0x65, 0xFB, 0x80,
-	0x04, 0x90, 0x17, 0x88, 0x21, 0x8F, 0x16, 0xA2, 0x03, 0x4E, 0xFB,
-	0xED, 0xFD, 0xD9, 0x00, 0x88, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x05,
-	0x00, 0xBD, 0x00, 0x82, 0x00, 0xEF, 0xFC, 0xF0, 0xFB, 0x8A, 0x07,
-	0x9C, 0x1A, 0x0D, 0x21, 0x24, 0x13, 0x18, 0x01, 0x43, 0xFB, 0xAC,
-	0xFE, 0xF7, 0x00, 0x60, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x17, 0x00,
-	0xE0, 0x00, 0x1A, 0x00, 0x3D, 0xFC, 0xED, 0xFC, 0xDD, 0x0A, 0x38,
-	0x1D, 0xDB, 0x1F, 0x99, 0x0F, 0xFF, 0xFE, 0x86, 0xFB, 0x5A, 0xFF,
-	0xFA, 0x00, 0x3C, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x31, 0x00, 0xF6,
-	0x00, 0x90, 0xFF, 0xAD, 0xFB, 0x62, 0xFE, 0x5D, 0x0E, 0x49, 0x1F,
-	0x01, 0x1E, 0x10, 0x0C, 0x60, 0xFD, 0x06, 0xFC, 0xEE, 0xFF, 0xE9,
-	0x00, 0x1F, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x53, 0x00, 0xFB, 0x00,
-	0xEB, 0xFE, 0x52, 0xFB, 0x51, 0x00, 0xEC, 0x11, 0xB7, 0x20, 0x91,
-	0x1B, 0xA9, 0x08, 0x3B, 0xFC, 0xAE, 0xFC, 0x62, 0x00, 0xCA, 0x00,
-	0x0B, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7A, 0x00, 0xE6, 0x00, 0x30,
-	0xFE, 0x40, 0xFB, 0xB5, 0x02, 0x66, 0x15, 0x73, 0x21, 0xA9, 0x18,
-	0x83, 0x05, 0x89, 0xFB, 0x6D, 0xFD, 0xB4, 0x00, 0xA3, 0x00, 0xFE,
-	0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xA3, 0x00, 0xB4, 0x00,
-	0x6D, 0xFD, 0x89, 0xFB, 0x83, 0x05, 0xA9, 0x18, 0x73, 0x21, 0x66,
-	0x15, 0xB5, 0x02, 0x40, 0xFB, 0x30, 0xFE, 0xE6, 0x00, 0x7A, 0x00,
-	0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00, 0xCA, 0x00, 0x62, 0x00, 0xAE,
-	0xFC, 0x3B, 0xFC, 0xA9, 0x08, 0x91, 0x1B, 0xB7, 0x20, 0xEC, 0x11,
-	0x51, 0x00, 0x52, 0xFB, 0xEB, 0xFE, 0xFB, 0x00, 0x53, 0x00, 0xF7,
-	0xFF, 0xFB, 0xFF, 0x1F, 0x00, 0xE9, 0x00, 0xEE, 0xFF, 0x06, 0xFC,
-	0x60, 0xFD, 0x10, 0x0C, 0x01, 0x1E, 0x49, 0x1F, 0x5D, 0x0E, 0x62,
-	0xFE, 0xAD, 0xFB, 0x90, 0xFF, 0xF6, 0x00, 0x31, 0x00, 0xF9, 0xFF,
-	0xF8, 0xFF, 0x3C, 0x00, 0xFA, 0x00, 0x5A, 0xFF, 0x86, 0xFB, 0xFF,
-	0xFE, 0x99, 0x0F, 0xDB, 0x1F, 0x38, 0x1D, 0xDD, 0x0A, 0xED, 0xFC,
-	0x3D, 0xFC, 0x1A, 0x00, 0xE0, 0x00, 0x17, 0x00, 0xFC, 0xFF, 0xF7,
-	0xFF, 0x60, 0x00, 0xF7, 0x00, 0xAC, 0xFE, 0x43, 0xFB, 0x18, 0x01,
-	0x24, 0x13, 0x0D, 0x21, 0x9C, 0x1A, 0x8A, 0x07, 0xF0, 0xFB, 0xEF,
-	0xFC, 0x82, 0x00, 0xBD, 0x00, 0x05, 0x00, 0xFF, 0xFF, 0xF9, 0xFF,
-	0x88, 0x00, 0xD9, 0x00, 0xED, 0xFD, 0x4E, 0xFB, 0xA2, 0x03, 0x8F,
-	0x16, 0x88, 0x21, 0x90, 0x17, 0x80, 0x04, 0x65, 0xFB, 0xB1, 0xFD,
-	0xC9, 0x00, 0x95, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02,
-	0x00, 0xB1, 0x00, 0x9C, 0x00, 0x29, 0xFD, 0xBA, 0xFB, 0x91, 0x06,
-	0xB6, 0x19, 0x47, 0x21, 0x36, 0x14, 0xD4, 0x01, 0x3D, 0xFB, 0x72,
-	0xFE, 0xF0, 0x00, 0x6C, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x11, 0x00,
-	0xD6, 0x00, 0x3D, 0x00, 0x71, 0xFC, 0x93, 0xFC, 0xD1, 0x09, 0x78,
-	0x1C, 0x4C, 0x20, 0xB1, 0x10, 0x98, 0xFF, 0x6A, 0xFB, 0x27, 0xFF,
-	0xFC, 0x00, 0x46, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x28, 0x00, 0xF1,
-	0x00, 0xBE, 0xFF, 0xD4, 0xFB, 0xE2, 0xFD, 0x46, 0x0D, 0xB7, 0x1E,
-	0xA3, 0x1E, 0x24, 0x0D, 0xD3, 0xFD, 0xD9, 0xFB, 0xC3, 0xFF, 0xF0,
-	0x00, 0x27, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x48, 0x00, 0xFC, 0x00,
-	0x20, 0xFF, 0x67, 0xFB, 0xAC, 0xFF, 0xD4, 0x10, 0x59, 0x20, 0x5F,
-	0x1C, 0xAF, 0x09, 0x88, 0xFC, 0x77, 0xFC, 0x42, 0x00, 0xD5, 0x00,
-	0x10, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6D, 0x00, 0xEF, 0x00, 0x6B,
-	0xFE, 0x3D, 0xFB, 0xED, 0x01, 0x59, 0x14, 0x4D, 0x21, 0x99, 0x19,
-	0x73, 0x06, 0xB4, 0xFB, 0x31, 0xFD, 0x9F, 0x00, 0xB0, 0x00, 0x01,
-	0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x96, 0x00, 0xC7, 0x00,
-	0xA9, 0xFD, 0x68, 0xFB, 0x9C, 0x04, 0xB0, 0x17, 0x86, 0x21, 0x6E,
-	0x16, 0x87, 0x03, 0x4C, 0xFB, 0xF5, 0xFD, 0xDA, 0x00, 0x86, 0x00,
-	0xF9, 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0xBF, 0x00, 0x7F, 0x00, 0xE7,
-	0xFC, 0xF8, 0xFB, 0xA9, 0x07, 0xB8, 0x1A, 0x04, 0x21, 0x02, 0x13,
-	0x01, 0x01, 0x44, 0xFB, 0xB3, 0xFE, 0xF7, 0x00, 0x5E, 0x00, 0xF7,
-	0xFF, 0xFC, 0xFF, 0x18, 0x00, 0xE1, 0x00, 0x15, 0x00, 0x36, 0xFC,
-	0xF9, 0xFC, 0xFF, 0x0A, 0x4F, 0x1D, 0xCC, 0x1F, 0x76, 0x0F, 0xED,
-	0xFE, 0x8A, 0xFB, 0x60, 0xFF, 0xFA, 0x00, 0x3B, 0x00, 0xF8, 0xFF,
-	0xF9, 0xFF, 0x32, 0x00, 0xF7, 0x00, 0x8A, 0xFF, 0xA8, 0xFB, 0x73,
-	0xFE, 0x80, 0x0E, 0x5A, 0x1F, 0xEB, 0x1D, 0xED, 0x0B, 0x53, 0xFD,
-	0x0C, 0xFC, 0xF3, 0xFF, 0xE8, 0x00, 0x1E, 0x00, 0xFB, 0xFF, 0xF7,
-	0xFF, 0x54, 0x00, 0xFA, 0x00, 0xE4, 0xFE, 0x50, 0xFB, 0x66, 0x00,
-	0x0F, 0x12, 0xC2, 0x20, 0x77, 0x1B, 0x89, 0x08, 0x32, 0xFC, 0xB5,
-	0xFC, 0x66, 0x00, 0xC9, 0x00, 0x0A, 0x00, 0xFE, 0xFF, 0xF8, 0xFF,
-	0x7B, 0x00, 0xE5, 0x00, 0x29, 0xFE, 0x41, 0xFB, 0xCF, 0x02, 0x87,
-	0x15, 0x76, 0x21, 0x8A, 0x18, 0x66, 0x05, 0x84, 0xFB, 0x74, 0xFD,
-	0xB7, 0x00, 0xA2, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE,
-	0xFF, 0xA5, 0x00, 0xB2, 0x00, 0x65, 0xFD, 0x8E, 0xFB, 0xA1, 0x05,
-	0xC7, 0x18, 0x6F, 0x21, 0x45, 0x15, 0x9B, 0x02, 0x40, 0xFB, 0x38,
-	0xFE, 0xE7, 0x00, 0x78, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00,
-	0xCC, 0x00, 0x5E, 0x00, 0xA7, 0xFC, 0x44, 0xFC, 0xCA, 0x08, 0xAC,
-	0x1B, 0xAD, 0x20, 0xC9, 0x11, 0x3B, 0x00, 0x54, 0xFB, 0xF1, 0xFE,
-	0xFB, 0x00, 0x51, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x20, 0x00, 0xEA,
-	0x00, 0xE8, 0xFF, 0x00, 0xFC, 0x6E, 0xFD, 0x32, 0x0C, 0x16, 0x1E,
-	0x38, 0x1F, 0x3A, 0x0E, 0x51, 0xFE, 0xB1, 0xFB, 0x96, 0xFF, 0xF6,
-	0x00, 0x30, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3D, 0x00, 0xFA, 0x00,
-	0x54, 0xFF, 0x82, 0xFB, 0x12, 0xFF, 0xBC, 0x0F, 0xEA, 0x1F, 0x21,
-	0x1D, 0xBB, 0x0A, 0xE1, 0xFC, 0x43, 0xFC, 0x1E, 0x00, 0xDF, 0x00,
-	0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x61, 0x00, 0xF6, 0x00, 0xA5,
-	0xFE, 0x42, 0xFB, 0x2F, 0x01, 0x47, 0x13, 0x15, 0x21, 0x80, 0x1A,
-	0x6A, 0x07, 0xE9, 0xFB, 0xF6, 0xFC, 0x86, 0x00, 0xBC, 0x00, 0x05,
-	0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8A, 0x00, 0xD7, 0x00, 0xE6, 0xFD,
-	0x51, 0xFB, 0xBD, 0x03, 0xB0, 0x16, 0x89, 0x21, 0x71, 0x17, 0x63,
-	0x04, 0x61, 0xFB, 0xB8, 0xFD, 0xCB, 0x00, 0x93, 0x00, 0xFB, 0xFF,
-	0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, 0xB3, 0x00, 0x99, 0x00, 0x22,
-	0xFD, 0xC0, 0xFB, 0xB0, 0x06, 0xD4, 0x19, 0x41, 0x21, 0x14, 0x14,
-	0xBC, 0x01, 0x3D, 0xFB, 0x7A, 0xFE, 0xF1, 0x00, 0x6A, 0x00, 0xF7,
-	0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD7, 0x00, 0x39, 0x00, 0x6A, 0xFC,
-	0x9D, 0xFC, 0xF2, 0x09, 0x91, 0x1C, 0x3F, 0x20, 0x8E, 0x10, 0x84,
-	0xFF, 0x6D, 0xFB, 0x2D, 0xFF, 0xFC, 0x00, 0x45, 0x00, 0xF7, 0xFF,
-	0xFA, 0xFF, 0x29, 0x00, 0xF2, 0x00, 0xB8, 0xFF, 0xCF, 0xFB, 0xF1,
-	0xFD, 0x69, 0x0D, 0xCA, 0x1E, 0x90, 0x1E, 0x01, 0x0D, 0xC4, 0xFD,
-	0xDF, 0xFB, 0xC9, 0xFF, 0xF0, 0x00, 0x26, 0x00, 0xFA, 0xFF, 0xF7,
-	0xFF, 0x49, 0x00, 0xFC, 0x00, 0x1A, 0xFF, 0x64, 0xFB, 0xC0, 0xFF,
-	0xF7, 0x10, 0x66, 0x20, 0x46, 0x1C, 0x8E, 0x09, 0x7E, 0xFC, 0x7E,
-	0xFC, 0x46, 0x00, 0xD4, 0x00, 0x0F, 0x00, 0xFD, 0xFF, 0xF7, 0xFF,
-	0x6F, 0x00, 0xEE, 0x00, 0x64, 0xFE, 0x3D, 0xFB, 0x05, 0x02, 0x7B,
-	0x14, 0x53, 0x21, 0x7C, 0x19, 0x54, 0x06, 0xAE, 0xFB, 0x38, 0xFD,
-	0xA1, 0x00, 0xAE, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFC,
-	0xFF, 0x98, 0x00, 0xC5, 0x00, 0xA2, 0xFD, 0x6C, 0xFB, 0xB8, 0x04,
-	0xCF, 0x17, 0x85, 0x21, 0x4E, 0x16, 0x6C, 0x03, 0x4A, 0xFB, 0xFC,
-	0xFD, 0xDC, 0x00, 0x85, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x07, 0x00,
-	0xC0, 0x00, 0x7B, 0x00, 0xE0, 0xFC, 0x00, 0xFC, 0xC9, 0x07, 0xD3,
-	0x1A, 0xFC, 0x20, 0xDF, 0x12, 0xEA, 0x00, 0x46, 0xFB, 0xBA, 0xFE,
-	0xF8, 0x00, 0x5D, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x19, 0x00, 0xE2,
-	0x00, 0x10, 0x00, 0x30, 0xFC, 0x05, 0xFD, 0x21, 0x0B, 0x66, 0x1D,
-	0xBD, 0x1F, 0x53, 0x0F, 0xDB, 0xFE, 0x8E, 0xFB, 0x66, 0xFF, 0xFA,
-	0x00, 0x3A, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x34, 0x00, 0xF7, 0x00,
-	0x84, 0xFF, 0xA4, 0xFB, 0x84, 0xFE, 0xA3, 0x0E, 0x6C, 0x1F, 0xD6,
-	0x1D, 0xCB, 0x0B, 0x45, 0xFD, 0x12, 0xFC, 0xF8, 0xFF, 0xE7, 0x00,
-	0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x56, 0x00, 0xFA, 0x00, 0xDD,
-	0xFE, 0x4E, 0xFB, 0x7C, 0x00, 0x32, 0x12, 0xCC, 0x20, 0x5C, 0x1B,
-	0x69, 0x08, 0x29, 0xFC, 0xBC, 0xFC, 0x69, 0x00, 0xC7, 0x00, 0x09,
-	0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7D, 0x00, 0xE3, 0x00, 0x21, 0xFE,
-	0x43, 0xFB, 0xE9, 0x02, 0xA9, 0x15, 0x79, 0x21, 0x6B, 0x18, 0x48,
-	0x05, 0x80, 0xFB, 0x7C, 0xFD, 0xB9, 0x00, 0xA0, 0x00, 0xFD, 0xFF,
-	0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x00, 0xAF, 0x00, 0x5E,
-	0xFD, 0x93, 0xFB, 0xBE, 0x05, 0xE5, 0x18, 0x6B, 0x21, 0x23, 0x15,
-	0x82, 0x02, 0x3F, 0xFB, 0x3F, 0xFE, 0xE9, 0x00, 0x77, 0x00, 0xF8,
-	0xFF, 0xFE, 0xFF, 0x0C, 0x00, 0xCD, 0x00, 0x5A, 0x00, 0xA0, 0xFC,
-	0x4D, 0xFC, 0xEA, 0x08, 0xC6, 0x1B, 0xA1, 0x20, 0xA6, 0x11, 0x26,
-	0x00, 0x57, 0xFB, 0xF8, 0xFE, 0xFB, 0x00, 0x50, 0x00, 0xF7, 0xFF,
-	0xFB, 0xFF, 0x21, 0x00, 0xEB, 0x00, 0xE3, 0xFF, 0xFA, 0xFB, 0x7C,
-	0xFD, 0x54, 0x0C, 0x2B, 0x1E, 0x26, 0x1F, 0x17, 0x0E, 0x41, 0xFE,
-	0xB6, 0xFB, 0x9C, 0xFF, 0xF5, 0x00, 0x2F, 0x00, 0xF9, 0xFF, 0xF8,
-	0xFF, 0x3F, 0x00, 0xFB, 0x00, 0x4D, 0xFF, 0x7F, 0xFB, 0x24, 0xFF,
-	0xDF, 0x0F, 0xF9, 0x1F, 0x09, 0x1D, 0x99, 0x0A, 0xD5, 0xFC, 0x49,
-	0xFC, 0x23, 0x00, 0xDD, 0x00, 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF,
-	0x63, 0x00, 0xF5, 0x00, 0x9E, 0xFE, 0x41, 0xFB, 0x46, 0x01, 0x69,
-	0x13, 0x1D, 0x21, 0x63, 0x1A, 0x4B, 0x07, 0xE2, 0xFB, 0xFD, 0xFC,
-	0x89, 0x00, 0xBA, 0x00, 0x04, 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8B,
-	0x00, 0xD5, 0x00, 0xDE, 0xFD, 0x53, 0xFB, 0xD9, 0x03, 0xD0, 0x16,
-	0x8A, 0x21, 0x51, 0x17, 0x47, 0x04, 0x5E, 0xFB, 0xC0, 0xFD, 0xCD,
-	0x00, 0x92, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00,
-	0xB4, 0x00, 0x96, 0x00, 0x1B, 0xFD, 0xC7, 0xFB, 0xCF, 0x06, 0xF0,
-	0x19, 0x3A, 0x21, 0xF2, 0x13, 0xA4, 0x01, 0x3E, 0xFB, 0x81, 0xFE,
-	0xF2, 0x00, 0x69, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD9,
-	0x00, 0x35, 0x00, 0x63, 0xFC, 0xA8, 0xFC, 0x13, 0x0A, 0xA9, 0x1C,
-	0x32, 0x20, 0x6B, 0x10, 0x71, 0xFF, 0x71, 0xFB, 0x34, 0xFF, 0xFB,
-	0x00, 0x44, 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2B, 0x00, 0xF3, 0x00,
-	0xB3, 0xFF, 0xCA, 0xFB, 0x01, 0xFE, 0x8C, 0x0D, 0xDD, 0x1E, 0x7C,
-	0x1E, 0xDE, 0x0C, 0xB5, 0xFD, 0xE4, 0xFB, 0xCE, 0xFF, 0xEF, 0x00,
-	0x25, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4A, 0x00, 0xFC, 0x00, 0x13,
-	0xFF, 0x61, 0xFB, 0xD4, 0xFF, 0x1A, 0x11, 0x72, 0x20, 0x2D, 0x1C,
-	0x6D, 0x09, 0x74, 0xFC, 0x85, 0xFC, 0x4A, 0x00, 0xD2, 0x00, 0x0F,
-	0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x70, 0x00, 0xED, 0x00, 0x5D, 0xFE,
-	0x3D, 0xFB, 0x1E, 0x02, 0x9C, 0x14, 0x58, 0x21, 0x5E, 0x19, 0x36,
-	0x06, 0xA8, 0xFB, 0x40, 0xFD, 0xA4, 0x00, 0xAD, 0x00, 0x00, 0x00,
-	0xFF, 0xFF, 0x00, 0x00, 0xFC, 0xFF, 0x9A, 0x00, 0xC3, 0x00, 0x9A,
-	0xFD, 0x6F, 0xFB, 0xD5, 0x04, 0xEF, 0x17, 0x83, 0x21, 0x2D, 0x16,
-	0x52, 0x03, 0x49, 0xFB, 0x04, 0xFE, 0xDD, 0x00, 0x83, 0x00, 0xF9,
-	0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xC2, 0x00, 0x78, 0x00, 0xD9, 0xFC,
-	0x08, 0xFC, 0xE9, 0x07, 0xEF, 0x1A, 0xF3, 0x20, 0xBC, 0x12, 0xD4,
-	0x00, 0x47, 0xFB, 0xC1, 0xFE, 0xF8, 0x00, 0x5B, 0x00, 0xF7, 0xFF,
-	0xFC, 0xFF, 0x1A, 0x00, 0xE3, 0x00, 0x0B, 0x00, 0x2A, 0xFC, 0x12,
-	0xFD, 0x42, 0x0B, 0x7D, 0x1D, 0xAD, 0x1F, 0x2F, 0x0F, 0xC9, 0xFE,
-	0x92, 0xFB, 0x6C, 0xFF, 0xF9, 0x00, 0x38, 0x00, 0xF8, 0xFF, 0xF9,
-	0xFF, 0x35, 0x00, 0xF8, 0x00, 0x7E, 0xFF, 0x9F, 0xFB, 0x95, 0xFE,
-	0xC6, 0x0E, 0x7C, 0x1F, 0xC0, 0x1D, 0xA9, 0x0B, 0x38, 0xFD, 0x18,
-	0xFC, 0xFD, 0xFF, 0xE6, 0x00, 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF,
-	0x57, 0x00, 0xFA, 0x00, 0xD6, 0xFE, 0x4C, 0xFB, 0x92, 0x00, 0x54,
-	0x12, 0xD6, 0x20, 0x41, 0x1B, 0x49, 0x08, 0x20, 0xFC, 0xC3, 0xFC,
-	0x6D, 0x00, 0xC6, 0x00, 0x09, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7E,
-	0x00, 0xE2, 0x00, 0x1A, 0xFE, 0x44, 0xFB, 0x03, 0x03, 0xCA, 0x15,
-	0x7C, 0x21, 0x4C, 0x18, 0x2B, 0x05, 0x7B, 0xFB, 0x83, 0xFD, 0xBC,
-	0x00, 0x9E, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-	0xA8, 0x00, 0xAD, 0x00, 0x56, 0xFD, 0x98, 0xFB, 0xDC, 0x05, 0x04,
-	0x19, 0x66, 0x21, 0x02, 0x15, 0x69, 0x02, 0x3E, 0xFB, 0x47, 0xFE,
-	0xEA, 0x00, 0x75, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xCE,
-	0x00, 0x56, 0x00, 0x99, 0xFC, 0x56, 0xFC, 0x0B, 0x09, 0xE0, 0x1B,
-	0x96, 0x20, 0x83, 0x11, 0x11, 0x00, 0x59, 0xFB, 0xFF, 0xFE, 0xFB,
-	0x00, 0x4E, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x22, 0x00, 0xEC, 0x00,
-	0xDE, 0xFF, 0xF5, 0xFB, 0x8A, 0xFD, 0x77, 0x0C, 0x3F, 0x1E, 0x14,
-	0x1F, 0xF5, 0x0D, 0x31, 0xFE, 0xBB, 0xFB, 0xA2, 0xFF, 0xF5, 0x00,
-	0x2E, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x40, 0x00, 0xFB, 0x00, 0x47,
-	0xFF, 0x7B, 0xFB, 0x37, 0xFF, 0x02, 0x10, 0x07, 0x20, 0xF2, 0x1C,
-	0x78, 0x0A, 0xCA, 0xFC, 0x50, 0xFC, 0x27, 0x00, 0xDC, 0x00, 0x15,
-	0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x64, 0x00, 0xF5, 0x00, 0x97, 0xFE,
-	0x40, 0xFB, 0x5D, 0x01, 0x8B, 0x13, 0x25, 0x21, 0x47, 0x1A, 0x2C,
-	0x07, 0xDB, 0xFB, 0x05, 0xFD, 0x8C, 0x00, 0xB9, 0x00, 0x04, 0x00,
-	0xFF, 0xFF, 0xFA, 0xFF, 0x8D, 0x00, 0xD3, 0x00, 0xD6, 0xFD, 0x56,
-	0xFB, 0xF4, 0x03, 0xF0, 0x16, 0x8A, 0x21, 0x31, 0x17, 0x2B, 0x04,
-	0x5B, 0xFB, 0xC7, 0xFD, 0xCF, 0x00, 0x90, 0x00, 0xFA, 0xFF, 0x00,
-	0x00, 0xFF, 0xFF, 0x03, 0x00, 0xB6, 0x00, 0x92, 0x00, 0x13, 0xFD,
-	0xCD, 0xFB, 0xEE, 0x06, 0x0D, 0x1A, 0x33, 0x21, 0xD0, 0x13, 0x8C,
-	0x01, 0x3E, 0xFB, 0x88, 0xFE, 0xF3, 0x00, 0x67, 0x00, 0xF7, 0xFF,
-	0x06, 0x00, 0x1D, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0xA1, 0x02, 0xA6,
-	0xF8, 0x56, 0x02, 0xA5, 0x28, 0xA5, 0x28, 0x56, 0x02, 0xA6, 0xF8,
-	0xA1, 0x02, 0xFE, 0x00, 0x03, 0xFF, 0x1D, 0x00, 0x06, 0x00, 0x00,
-	0x00, 0x21, 0x00, 0xA6, 0xFF, 0x3F, 0xFF, 0x0B, 0x03, 0x42, 0xFE,
-	0x3E, 0xF8, 0x7F, 0x15, 0xAC, 0x30, 0x7F, 0x15, 0x3E, 0xF8, 0x42,
-	0xFE, 0x0B, 0x03, 0x3F, 0xFF, 0xA6, 0xFF, 0x21, 0x00, 0x00, 0x00,
-	0xFA, 0xFF, 0xCE, 0xFF, 0x14, 0x01, 0x00, 0xFD, 0x35, 0x06, 0xD5,
-	0xF4, 0xDA, 0x15, 0x92, 0x40, 0xAE, 0xFE, 0xF3, 0xFC, 0x68, 0x03,
-	0x86, 0xFD, 0x51, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEC,
-	0xFF, 0xF9, 0xFF, 0xC6, 0x00, 0x55, 0xFD, 0x35, 0x06, 0x90, 0xF3,
-	0xE5, 0x1C, 0x6B, 0x3D, 0x71, 0xFA, 0x34, 0xFF, 0x46, 0x02, 0xFF,
-	0xFD, 0x2D, 0x01, 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDB, 0xFF,
-	0x2D, 0x00, 0x60, 0x00, 0xE1, 0xFD, 0xCE, 0x05, 0xED, 0xF2, 0xF3,
-	0x23, 0x20, 0x39, 0x22, 0xF7, 0x44, 0x01, 0x1F, 0x01, 0x89, 0xFE,
-	0xFB, 0x00, 0x9C, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC9, 0xFF, 0x68,
-	0x00, 0xE5, 0xFF, 0xA0, 0xFE, 0xFB, 0x04, 0x0C, 0xF3, 0xC5, 0x2A,
-	0xD8, 0x33, 0xC9, 0xF4, 0x0B, 0x03, 0x05, 0x00, 0x1A, 0xFF, 0xC1,
-	0x00, 0xAD, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB5, 0xFF, 0xA5, 0x00,
-	0x5C, 0xFF, 0x8C, 0xFF, 0xBF, 0x03, 0x06, 0xF4, 0x22, 0x31, 0xC8,
-	0x2D, 0x63, 0xF3, 0x76, 0x04, 0x08, 0xFF, 0xA7, 0xFF, 0x84, 0x00,
-	0xC0, 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA4, 0xFF, 0xE1, 0x00, 0xCB,
-	0xFE, 0x9B, 0x00, 0x21, 0x02, 0xEE, 0xF5, 0xCD, 0x36, 0x24, 0x27,
-	0xE1, 0xF2, 0x7A, 0x05, 0x33, 0xFE, 0x2A, 0x00, 0x47, 0x00, 0xD3,
-	0xFF, 0x04, 0x00, 0x0F, 0x00, 0x95, 0xFF, 0x17, 0x01, 0x3D, 0xFE,
-	0xBD, 0x01, 0x30, 0x00, 0xCC, 0xF8, 0x92, 0x3B, 0x2A, 0x20, 0x2E,
-	0xF3, 0x12, 0x06, 0x8F, 0xFD, 0x9A, 0x00, 0x10, 0x00, 0xE5, 0xFF,
-	0x02, 0x00, 0x10, 0x00, 0x8C, 0xFF, 0x42, 0x01, 0xBB, 0xFD, 0xE4,
-	0x02, 0x01, 0xFE, 0x9C, 0xFC, 0x45, 0x3F, 0x16, 0x19, 0x2D, 0xF4,
-	0x41, 0x06, 0x21, 0xFD, 0xF3, 0x00, 0xE0, 0xFF, 0xF4, 0xFF, 0x01,
-	0x00, 0x10, 0x00, 0x8B, 0xFF, 0x5D, 0x01, 0x4F, 0xFD, 0xFB, 0x03,
-	0xB2, 0xFB, 0x53, 0x01, 0xC2, 0x41, 0x24, 0x12, 0xBA, 0xF5, 0x0F,
-	0x06, 0xE9, 0xFC, 0x33, 0x01, 0xBB, 0xFF, 0x00, 0x00, 0x00, 0x00,
-	0x0D, 0x00, 0x93, 0xFF, 0x63, 0x01, 0x04, 0xFD, 0xEF, 0x04, 0x62,
-	0xF9, 0xD7, 0x06, 0xF2, 0x42, 0x8D, 0x0B, 0xB0, 0xF7, 0x87, 0x05,
-	0xE6, 0xFC, 0x58, 0x01, 0xA0, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x07, 0x00, 0xA5, 0xFF, 0x52, 0x01, 0xE2, 0xFC, 0xAD, 0x05,
-	0x35, 0xF7, 0x08, 0x0D, 0xCB, 0x42, 0x81, 0x05, 0xE8, 0xF9, 0xBB,
-	0x04, 0x12, 0xFD, 0x64, 0x01, 0x90, 0xFF, 0x0E, 0x00, 0x00, 0x00,
-	0xFE, 0xFF, 0xC2, 0xFF, 0x27, 0x01, 0xF1, 0xFC, 0x22, 0x06, 0x54,
-	0xF5, 0xB8, 0x13, 0x4A, 0x41, 0x29, 0x00, 0x3C, 0xFC, 0xBD, 0x03,
-	0x66, 0xFD, 0x58, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF1,
-	0xFF, 0xEB, 0xFF, 0xE1, 0x00, 0x35, 0xFD, 0x40, 0x06, 0xE4, 0xF3,
-	0xB7, 0x1A, 0x85, 0x3E, 0xA6, 0xFB, 0x86, 0xFE, 0xA0, 0x02, 0xD7,
-	0xFD, 0x39, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xE1, 0xFF,
-	0x1C, 0x00, 0x82, 0x00, 0xB0, 0xFD, 0xF9, 0x05, 0x0C, 0xF3, 0xCB,
-	0x21, 0x8F, 0x3A, 0x0D, 0xF8, 0xA9, 0x00, 0x79, 0x01, 0x5D, 0xFE,
-	0x0B, 0x01, 0x98, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCE, 0xFF, 0x55,
-	0x00, 0x0D, 0x00, 0x60, 0xFE, 0x48, 0x05, 0xEC, 0xF2, 0xB6, 0x28,
-	0x91, 0x35, 0x68, 0xF5, 0x88, 0x02, 0x5A, 0x00, 0xED, 0xFE, 0xD4,
-	0x00, 0xA8, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0x92, 0x00,
-	0x87, 0xFF, 0x3F, 0xFF, 0x2B, 0x04, 0xA1, 0xF3, 0x3D, 0x2F, 0xB8,
-	0x2F, 0xB8, 0xF3, 0x11, 0x04, 0x52, 0xFF, 0x7C, 0xFF, 0x97, 0x00,
-	0xBA, 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA9, 0xFF, 0xCF, 0x00, 0xF8,
-	0xFE, 0x44, 0x00, 0xAA, 0x02, 0x3E, 0xF5, 0x24, 0x35, 0x3B, 0x29,
-	0xF2, 0xF2, 0x35, 0x05, 0x70, 0xFE, 0x03, 0x00, 0x5A, 0x00, 0xCD,
-	0xFF, 0x05, 0x00, 0x0E, 0x00, 0x99, 0xFF, 0x07, 0x01, 0x68, 0xFE,
-	0x63, 0x01, 0xD0, 0x00, 0xD0, 0xF7, 0x35, 0x3A, 0x55, 0x22, 0x02,
-	0xF3, 0xEF, 0x05, 0xBC, 0xFD, 0x7A, 0x00, 0x20, 0x00, 0xDF, 0xFF,
-	0x03, 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x36, 0x01, 0xE1, 0xFD, 0x8A,
-	0x02, 0xB2, 0xFE, 0x56, 0xFB, 0x40, 0x3E, 0x42, 0x1B, 0xCE, 0xF3,
-	0x3E, 0x06, 0x3D, 0xFD, 0xDB, 0x00, 0xEE, 0xFF, 0xF0, 0xFF, 0x01,
-	0x00, 0x11, 0x00, 0x8A, 0xFF, 0x57, 0x01, 0x6D, 0xFD, 0xA8, 0x03,
-	0x69, 0xFC, 0xC8, 0xFF, 0x20, 0x41, 0x40, 0x14, 0x33, 0xF5, 0x28,
-	0x06, 0xF5, 0xFC, 0x22, 0x01, 0xC5, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
-	0x0F, 0x00, 0x8F, 0xFF, 0x64, 0x01, 0x17, 0xFD, 0xA9, 0x04, 0x16,
-	0xFA, 0x10, 0x05, 0xB8, 0x42, 0x87, 0x0D, 0x0D, 0xF7, 0xB9, 0x05,
-	0xE2, 0xFC, 0x50, 0x01, 0xA7, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x0A, 0x00, 0x9E, 0xFF, 0x5A, 0x01, 0xE8, 0xFC, 0x7A, 0x05,
-	0xDA, 0xF7, 0x10, 0x0B, 0xFB, 0x42, 0x4B, 0x07, 0x35, 0xF9, 0x00,
-	0x05, 0x00, 0xFD, 0x63, 0x01, 0x94, 0xFF, 0x0D, 0x00, 0x00, 0x00,
-	0x01, 0x00, 0xB8, 0xFF, 0x37, 0x01, 0xE7, 0xFC, 0x07, 0x06, 0xDE,
-	0xF5, 0x9F, 0x11, 0xE4, 0x41, 0xB8, 0x01, 0x84, 0xFB, 0x0F, 0x04,
-	0x48, 0xFD, 0x5E, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF5,
-	0xFF, 0xDD, 0xFF, 0xF9, 0x00, 0x1B, 0xFD, 0x41, 0x06, 0x47, 0xF4,
-	0x8B, 0x18, 0x81, 0x3F, 0xF1, 0xFC, 0xD5, 0xFD, 0xFA, 0x02, 0xB2,
-	0xFD, 0x45, 0x01, 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE6, 0xFF,
-	0x0C, 0x00, 0xA2, 0x00, 0x85, 0xFD, 0x1A, 0x06, 0x3C, 0xF3, 0x9F,
-	0x1F, 0xE6, 0x3B, 0x0E, 0xF9, 0x07, 0x00, 0xD4, 0x01, 0x33, 0xFE,
-	0x1B, 0x01, 0x94, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x43,
-	0x00, 0x33, 0x00, 0x25, 0xFE, 0x89, 0x05, 0xE0, 0xF2, 0x9C, 0x26,
-	0x33, 0x37, 0x1E, 0xF6, 0xFD, 0x01, 0xB0, 0x00, 0xC0, 0xFE, 0xE6,
-	0x00, 0xA2, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC1, 0xFF, 0x7F, 0x00,
-	0xB2, 0xFF, 0xF6, 0xFE, 0x8E, 0x04, 0x51, 0xF3, 0x49, 0x2D, 0x98,
-	0x31, 0x23, 0xF4, 0xA2, 0x03, 0xA0, 0xFF, 0x51, 0xFF, 0xAA, 0x00,
-	0xB4, 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAE, 0xFF, 0xBD, 0x00, 0x25,
-	0xFF, 0xF1, 0xFF, 0x2B, 0x03, 0xA5, 0xF4, 0x68, 0x33, 0x48, 0x2B,
-	0x17, 0xF3, 0xE7, 0x04, 0xB1, 0xFE, 0xDB, 0xFF, 0x6C, 0x00, 0xC7,
-	0xFF, 0x06, 0x00, 0x0D, 0x00, 0x9E, 0xFF, 0xF7, 0x00, 0x94, 0xFE,
-	0x09, 0x01, 0x6A, 0x01, 0xEB, 0xF6, 0xC1, 0x38, 0x7D, 0x24, 0xE8,
-	0xF2, 0xC1, 0x05, 0xEE, 0xFD, 0x57, 0x00, 0x31, 0x00, 0xDA, 0xFF,
-	0x03, 0x00, 0x10, 0x00, 0x91, 0xFF, 0x29, 0x01, 0x09, 0xFE, 0x2F,
-	0x02, 0x5F, 0xFF, 0x27, 0xFA, 0x20, 0x3D, 0x70, 0x1D, 0x7D, 0xF3,
-	0x31, 0x06, 0x5E, 0xFD, 0xBF, 0x00, 0xFD, 0xFF, 0xEB, 0xFF, 0x02,
-	0x00, 0x11, 0x00, 0x8B, 0xFF, 0x4E, 0x01, 0x8E, 0xFD, 0x52, 0x03,
-	0x20, 0xFD, 0x52, 0xFE, 0x60, 0x40, 0x63, 0x16, 0xB7, 0xF4, 0x39,
-	0x06, 0x05, 0xFD, 0x0F, 0x01, 0xD1, 0xFF, 0xF9, 0xFF, 0x00, 0x00,
-	0x10, 0x00, 0x8D, 0xFF, 0x62, 0x01, 0x2E, 0xFD, 0x5E, 0x04, 0xCC,
-	0xFA, 0x5B, 0x03, 0x5E, 0x42, 0x8E, 0x0F, 0x71, 0xF6, 0xE4, 0x05,
-	0xE2, 0xFC, 0x45, 0x01, 0xAF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x0B, 0x00, 0x99, 0xFF, 0x60, 0x01, 0xF2, 0xFC, 0x40, 0x05,
-	0x85, 0xF8, 0x26, 0x09, 0x0C, 0x43, 0x26, 0x09, 0x85, 0xF8, 0x40,
-	0x05, 0xF2, 0xFC, 0x60, 0x01, 0x99, 0xFF, 0x0B, 0x00, 0x00, 0x00,
-	0x04, 0x00, 0xAF, 0xFF, 0x45, 0x01, 0xE2, 0xFC, 0xE4, 0x05, 0x71,
-	0xF6, 0x8E, 0x0F, 0x5E, 0x42, 0x5B, 0x03, 0xCC, 0xFA, 0x5E, 0x04,
-	0x2E, 0xFD, 0x62, 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xF9,
-	0xFF, 0xD1, 0xFF, 0x0F, 0x01, 0x05, 0xFD, 0x39, 0x06, 0xB7, 0xF4,
-	0x63, 0x16, 0x60, 0x40, 0x52, 0xFE, 0x20, 0xFD, 0x52, 0x03, 0x8E,
-	0xFD, 0x4E, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEB, 0xFF,
-	0xFD, 0xFF, 0xBF, 0x00, 0x5E, 0xFD, 0x31, 0x06, 0x7D, 0xF3, 0x70,
-	0x1D, 0x20, 0x3D, 0x27, 0xFA, 0x5F, 0xFF, 0x2F, 0x02, 0x09, 0xFE,
-	0x29, 0x01, 0x91, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDA, 0xFF, 0x31,
-	0x00, 0x57, 0x00, 0xEE, 0xFD, 0xC1, 0x05, 0xE8, 0xF2, 0x7D, 0x24,
-	0xC1, 0x38, 0xEB, 0xF6, 0x6A, 0x01, 0x09, 0x01, 0x94, 0xFE, 0xF7,
-	0x00, 0x9E, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC7, 0xFF, 0x6C, 0x00,
-	0xDB, 0xFF, 0xB1, 0xFE, 0xE7, 0x04, 0x17, 0xF3, 0x48, 0x2B, 0x68,
-	0x33, 0xA5, 0xF4, 0x2B, 0x03, 0xF1, 0xFF, 0x25, 0xFF, 0xBD, 0x00,
-	0xAE, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB4, 0xFF, 0xAA, 0x00, 0x51,
-	0xFF, 0xA0, 0xFF, 0xA2, 0x03, 0x23, 0xF4, 0x98, 0x31, 0x49, 0x2D,
-	0x51, 0xF3, 0x8E, 0x04, 0xF6, 0xFE, 0xB2, 0xFF, 0x7F, 0x00, 0xC1,
-	0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA2, 0xFF, 0xE6, 0x00, 0xC0, 0xFE,
-	0xB0, 0x00, 0xFD, 0x01, 0x1E, 0xF6, 0x33, 0x37, 0x9C, 0x26, 0xE0,
-	0xF2, 0x89, 0x05, 0x25, 0xFE, 0x33, 0x00, 0x43, 0x00, 0xD4, 0xFF,
-	0x04, 0x00, 0x0F, 0x00, 0x94, 0xFF, 0x1B, 0x01, 0x33, 0xFE, 0xD4,
-	0x01, 0x07, 0x00, 0x0E, 0xF9, 0xE6, 0x3B, 0x9F, 0x1F, 0x3C, 0xF3,
-	0x1A, 0x06, 0x85, 0xFD, 0xA2, 0x00, 0x0C, 0x00, 0xE6, 0xFF, 0x02,
-	0x00, 0x11, 0x00, 0x8C, 0xFF, 0x45, 0x01, 0xB2, 0xFD, 0xFA, 0x02,
-	0xD5, 0xFD, 0xF1, 0xFC, 0x81, 0x3F, 0x8B, 0x18, 0x47, 0xF4, 0x41,
-	0x06, 0x1B, 0xFD, 0xF9, 0x00, 0xDD, 0xFF, 0xF5, 0xFF, 0x01, 0x00,
-	0x10, 0x00, 0x8B, 0xFF, 0x5E, 0x01, 0x48, 0xFD, 0x0F, 0x04, 0x84,
-	0xFB, 0xB8, 0x01, 0xE4, 0x41, 0x9F, 0x11, 0xDE, 0xF5, 0x07, 0x06,
-	0xE7, 0xFC, 0x37, 0x01, 0xB8, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x0D,
-	0x00, 0x94, 0xFF, 0x63, 0x01, 0x00, 0xFD, 0x00, 0x05, 0x35, 0xF9,
-	0x4B, 0x07, 0xFB, 0x42, 0x10, 0x0B, 0xDA, 0xF7, 0x7A, 0x05, 0xE8,
-	0xFC, 0x5A, 0x01, 0x9E, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x07, 0x00, 0xA7, 0xFF, 0x50, 0x01, 0xE2, 0xFC, 0xB9, 0x05, 0x0D,
-	0xF7, 0x87, 0x0D, 0xB8, 0x42, 0x10, 0x05, 0x16, 0xFA, 0xA9, 0x04,
-	0x17, 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFD,
-	0xFF, 0xC5, 0xFF, 0x22, 0x01, 0xF5, 0xFC, 0x28, 0x06, 0x33, 0xF5,
-	0x40, 0x14, 0x20, 0x41, 0xC8, 0xFF, 0x69, 0xFC, 0xA8, 0x03, 0x6D,
-	0xFD, 0x57, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF0, 0xFF,
-	0xEE, 0xFF, 0xDB, 0x00, 0x3D, 0xFD, 0x3E, 0x06, 0xCE, 0xF3, 0x42,
-	0x1B, 0x40, 0x3E, 0x56, 0xFB, 0xB2, 0xFE, 0x8A, 0x02, 0xE1, 0xFD,
-	0x36, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDF, 0xFF, 0x20,
-	0x00, 0x7A, 0x00, 0xBC, 0xFD, 0xEF, 0x05, 0x02, 0xF3, 0x55, 0x22,
-	0x35, 0x3A, 0xD0, 0xF7, 0xD0, 0x00, 0x63, 0x01, 0x68, 0xFE, 0x07,
-	0x01, 0x99, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCD, 0xFF, 0x5A, 0x00,
-	0x03, 0x00, 0x70, 0xFE, 0x35, 0x05, 0xF2, 0xF2, 0x3B, 0x29, 0x24,
-	0x35, 0x3E, 0xF5, 0xAA, 0x02, 0x44, 0x00, 0xF8, 0xFE, 0xCF, 0x00,
-	0xA9, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBA, 0xFF, 0x97, 0x00, 0x7C,
-	0xFF, 0x52, 0xFF, 0x11, 0x04, 0xB8, 0xF3, 0xB8, 0x2F, 0x3D, 0x2F,
-	0xA1, 0xF3, 0x2B, 0x04, 0x3F, 0xFF, 0x87, 0xFF, 0x92, 0x00, 0xBB,
-	0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA8, 0xFF, 0xD4, 0x00, 0xED, 0xFE,
-	0x5A, 0x00, 0x88, 0x02, 0x68, 0xF5, 0x91, 0x35, 0xB6, 0x28, 0xEC,
-	0xF2, 0x48, 0x05, 0x60, 0xFE, 0x0D, 0x00, 0x55, 0x00, 0xCE, 0xFF,
-	0x05, 0x00, 0x0E, 0x00, 0x98, 0xFF, 0x0B, 0x01, 0x5D, 0xFE, 0x79,
-	0x01, 0xA9, 0x00, 0x0D, 0xF8, 0x8F, 0x3A, 0xCB, 0x21, 0x0C, 0xF3,
-	0xF9, 0x05, 0xB0, 0xFD, 0x82, 0x00, 0x1C, 0x00, 0xE1, 0xFF, 0x03,
-	0x00, 0x10, 0x00, 0x8E, 0xFF, 0x39, 0x01, 0xD7, 0xFD, 0xA0, 0x02,
-	0x86, 0xFE, 0xA6, 0xFB, 0x85, 0x3E, 0xB7, 0x1A, 0xE4, 0xF3, 0x40,
-	0x06, 0x35, 0xFD, 0xE1, 0x00, 0xEB, 0xFF, 0xF1, 0xFF, 0x01, 0x00,
-	0x11, 0x00, 0x8A, 0xFF, 0x58, 0x01, 0x66, 0xFD, 0xBD, 0x03, 0x3C,
-	0xFC, 0x29, 0x00, 0x4A, 0x41, 0xB8, 0x13, 0x54, 0xF5, 0x22, 0x06,
-	0xF1, 0xFC, 0x27, 0x01, 0xC2, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0x0E,
-	0x00, 0x90, 0xFF, 0x64, 0x01, 0x12, 0xFD, 0xBB, 0x04, 0xE8, 0xF9,
-	0x81, 0x05, 0xCB, 0x42, 0x08, 0x0D, 0x35, 0xF7, 0xAD, 0x05, 0xE2,
-	0xFC, 0x52, 0x01, 0xA5, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x09, 0x00, 0xA0, 0xFF, 0x58, 0x01, 0xE6, 0xFC, 0x87, 0x05, 0xB0,
-	0xF7, 0x8D, 0x0B, 0xF2, 0x42, 0xD7, 0x06, 0x62, 0xF9, 0xEF, 0x04,
-	0x04, 0xFD, 0x63, 0x01, 0x93, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0xBB, 0xFF, 0x33, 0x01, 0xE9, 0xFC, 0x0F, 0x06, 0xBA, 0xF5,
-	0x24, 0x12, 0xC2, 0x41, 0x53, 0x01, 0xB2, 0xFB, 0xFB, 0x03, 0x4F,
-	0xFD, 0x5D, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF4, 0xFF,
-	0xE0, 0xFF, 0xF3, 0x00, 0x21, 0xFD, 0x41, 0x06, 0x2D, 0xF4, 0x16,
-	0x19, 0x45, 0x3F, 0x9C, 0xFC, 0x01, 0xFE, 0xE4, 0x02, 0xBB, 0xFD,
-	0x42, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE5, 0xFF, 0x10,
-	0x00, 0x9A, 0x00, 0x8F, 0xFD, 0x12, 0x06, 0x2E, 0xF3, 0x2A, 0x20,
-	0x92, 0x3B, 0xCC, 0xF8, 0x30, 0x00, 0xBD, 0x01, 0x3D, 0xFE, 0x17,
-	0x01, 0x95, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x47, 0x00,
-	0x2A, 0x00, 0x33, 0xFE, 0x7A, 0x05, 0xE1, 0xF2, 0x24, 0x27, 0xCD,
-	0x36, 0xEE, 0xF5, 0x21, 0x02, 0x9B, 0x00, 0xCB, 0xFE, 0xE1, 0x00,
-	0xA4, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0x84, 0x00, 0xA7,
-	0xFF, 0x08, 0xFF, 0x76, 0x04, 0x63, 0xF3, 0xC8, 0x2D, 0x22, 0x31,
-	0x06, 0xF4, 0xBF, 0x03, 0x8C, 0xFF, 0x5C, 0xFF, 0xA5, 0x00, 0xB5,
-	0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAD, 0xFF, 0xC1, 0x00, 0x1A, 0xFF,
-	0x05, 0x00, 0x0B, 0x03, 0xC9, 0xF4, 0xD8, 0x33, 0xC5, 0x2A, 0x0C,
-	0xF3, 0xFB, 0x04, 0xA0, 0xFE, 0xE5, 0xFF, 0x68, 0x00, 0xC9, 0xFF,
-	0x06, 0x00, 0x0D, 0x00, 0x9C, 0xFF, 0xFB, 0x00, 0x89, 0xFE, 0x1F,
-	0x01, 0x44, 0x01, 0x22, 0xF7, 0x20, 0x39, 0xF3, 0x23, 0xED, 0xF2,
-	0xCE, 0x05, 0xE1, 0xFD, 0x60, 0x00, 0x2D, 0x00, 0xDB, 0xFF, 0x03,
-	0x00, 0x10, 0x00, 0x90, 0xFF, 0x2D, 0x01, 0xFF, 0xFD, 0x46, 0x02,
-	0x34, 0xFF, 0x71, 0xFA, 0x6B, 0x3D, 0xE5, 0x1C, 0x90, 0xF3, 0x35,
-	0x06, 0x55, 0xFD, 0xC6, 0x00, 0xF9, 0xFF, 0xEC, 0xFF, 0x01, 0x00,
-	0x11, 0x00, 0x8B, 0xFF, 0x51, 0x01, 0x86, 0xFD, 0x68, 0x03, 0xF3,
-	0xFC, 0xAE, 0xFE, 0x92, 0x40, 0xDA, 0x15, 0xD5, 0xF4, 0x35, 0x06,
-	0x00, 0xFD, 0x14, 0x01, 0xCE, 0xFF, 0xFA, 0xFF, 0x00, 0x00, 0x0F,
-	0x00, 0x8D, 0xFF, 0x63, 0x01, 0x28, 0xFD, 0x71, 0x04, 0x9E, 0xFA,
-	0xC7, 0x03, 0x79, 0x42, 0x0B, 0x0F, 0x97, 0xF6, 0xDA, 0x05, 0xE2,
-	0xFC, 0x48, 0x01, 0xAD, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x0B, 0x00, 0x9A, 0xFF, 0x5F, 0x01, 0xEF, 0xFC, 0x4F, 0x05, 0x5A,
-	0xF8, 0x9F, 0x09, 0x0A, 0x43, 0xAE, 0x08, 0xB1, 0xF8, 0x30, 0x05,
-	0xF5, 0xFC, 0x61, 0x01, 0x97, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03,
-	0x00, 0xB1, 0xFF, 0x41, 0x01, 0xE3, 0xFC, 0xED, 0x05, 0x4C, 0xF6,
-	0x11, 0x10, 0x42, 0x42, 0xF1, 0x02, 0xFA, 0xFA, 0x4B, 0x04, 0x34,
-	0xFD, 0x61, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF8, 0xFF,
-	0xD4, 0xFF, 0x0A, 0x01, 0x0A, 0xFD, 0x3C, 0x06, 0x9A, 0xF4, 0xED,
-	0x16, 0x2A, 0x40, 0xF8, 0xFD, 0x4D, 0xFD, 0x3C, 0x03, 0x97, 0xFD,
-	0x4C, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEA, 0xFF, 0x00,
-	0x00, 0xB8, 0x00, 0x67, 0xFD, 0x2C, 0x06, 0x6B, 0xF3, 0xFC, 0x1D,
-	0xD3, 0x3C, 0xDF, 0xF9, 0x89, 0xFF, 0x18, 0x02, 0x13, 0xFE, 0x26,
-	0x01, 0x92, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD9, 0xFF, 0x36, 0x00,
-	0x4E, 0x00, 0xFB, 0xFD, 0xB4, 0x05, 0xE4, 0xF2, 0x04, 0x25, 0x5F,
-	0x38, 0xB6, 0xF6, 0x90, 0x01, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00,
-	0x9F, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC6, 0xFF, 0x71, 0x00, 0xD1,
-	0xFF, 0xC2, 0xFE, 0xD1, 0x04, 0x23, 0xF3, 0xC9, 0x2B, 0xF5, 0x32,
-	0x83, 0xF4, 0x49, 0x03, 0xDC, 0xFF, 0x30, 0xFF, 0xB8, 0x00, 0xB0,
-	0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB3, 0xFF, 0xAE, 0x00, 0x46, 0xFF,
-	0xB4, 0xFF, 0x85, 0x03, 0x42, 0xF4, 0x0E, 0x32, 0xCA, 0x2C, 0x41,
-	0xF3, 0xA5, 0x04, 0xE4, 0xFE, 0xBC, 0xFF, 0x7A, 0x00, 0xC3, 0xFF,
-	0x07, 0x00, 0x0D, 0x00, 0xA1, 0xFF, 0xEA, 0x00, 0xB5, 0xFE, 0xC6,
-	0x00, 0xD9, 0x01, 0x4F, 0xF6, 0x99, 0x37, 0x16, 0x26, 0xE0, 0xF2,
-	0x98, 0x05, 0x16, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0xD6, 0xFF, 0x04,
-	0x00, 0x0F, 0x00, 0x93, 0xFF, 0x1F, 0x01, 0x28, 0xFE, 0xEB, 0x01,
-	0xDD, 0xFF, 0x52, 0xF9, 0x36, 0x3C, 0x13, 0x1F, 0x4B, 0xF3, 0x20,
-	0x06, 0x7B, 0xFD, 0xA9, 0x00, 0x08, 0x00, 0xE7, 0xFF, 0x02, 0x00,
-	0x11, 0x00, 0x8C, 0xFF, 0x47, 0x01, 0xA9, 0xFD, 0x10, 0x03, 0xA8,
-	0xFD, 0x47, 0xFD, 0xBB, 0x3F, 0x01, 0x18, 0x62, 0xF4, 0x40, 0x06,
-	0x15, 0xFD, 0xFF, 0x00, 0xDA, 0xFF, 0xF6, 0xFF, 0x01, 0x00, 0x10,
-	0x00, 0x8B, 0xFF, 0x5F, 0x01, 0x41, 0xFD, 0x23, 0x04, 0x56, 0xFB,
-	0x1F, 0x02, 0x06, 0x42, 0x19, 0x11, 0x02, 0xF6, 0xFF, 0x05, 0xE5,
-	0xFC, 0x3B, 0x01, 0xB6, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00,
-	0x95, 0xFF, 0x62, 0x01, 0xFC, 0xFC, 0x10, 0x05, 0x09, 0xF9, 0xC1,
-	0x07, 0x03, 0x43, 0x94, 0x0A, 0x05, 0xF8, 0x6C, 0x05, 0xEA, 0xFC,
-	0x5C, 0x01, 0x9D, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
-	0x00, 0xA9, 0xFF, 0x4D, 0x01, 0xE1, 0xFC, 0xC4, 0x05, 0xE6, 0xF6,
-	0x08, 0x0E, 0xA5, 0x42, 0xA1, 0x04, 0x43, 0xFA, 0x97, 0x04, 0x1D,
-	0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFC, 0xFF,
-	0xC8, 0xFF, 0x1E, 0x01, 0xF8, 0xFC, 0x2D, 0x06, 0x13, 0xF5, 0xC8,
-	0x14, 0xF2, 0x40, 0x69, 0xFF, 0x97, 0xFC, 0x92, 0x03, 0x75, 0xFD,
-	0x55, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEF, 0xFF, 0xF2,
-	0xFF, 0xD4, 0x00, 0x45, 0xFD, 0x3B, 0x06, 0xB8, 0xF3, 0xCE, 0x1B,
-	0xFB, 0x3D, 0x08, 0xFB, 0xDE, 0xFE, 0x73, 0x02, 0xEB, 0xFD, 0x33,
-	0x01, 0x8F, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDE, 0xFF, 0x25, 0x00,
-	0x71, 0x00, 0xC8, 0xFD, 0xE5, 0x05, 0xFA, 0xF2, 0xDF, 0x22, 0xDB,
-	0x39, 0x94, 0xF7, 0xF7, 0x00, 0x4C, 0x01, 0x73, 0xFE, 0x03, 0x01,
-	0x9A, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCC, 0xFF, 0x5E, 0x00, 0xF9,
-	0xFF, 0x80, 0xFE, 0x23, 0x05, 0xF9, 0xF2, 0xC0, 0x29, 0xB8, 0x34,
-	0x16, 0xF5, 0xCB, 0x02, 0x2F, 0x00, 0x03, 0xFF, 0xCA, 0x00, 0xAA,
-	0xFF, 0x0B, 0x00, 0x08, 0x00, 0xB8, 0xFF, 0x9B, 0x00, 0x72, 0xFF,
-	0x65, 0xFF, 0xF6, 0x03, 0xD1, 0xF3, 0x31, 0x30, 0xC1, 0x2E, 0x8B,
-	0xF3, 0x45, 0x04, 0x2D, 0xFF, 0x92, 0xFF, 0x8D, 0x00, 0xBD, 0xFF,
-	0x08, 0x00, 0x0C, 0x00, 0xA6, 0xFF, 0xD8, 0x00, 0xE2, 0xFE, 0x6F,
-	0x00, 0x66, 0x02, 0x93, 0xF5, 0xFB, 0x35, 0x31, 0x28, 0xE7, 0xF2,
-	0x59, 0x05, 0x51, 0xFE, 0x17, 0x00, 0x50, 0x00, 0xD0, 0xFF, 0x05,
-	0x00, 0x0E, 0x00, 0x97, 0xFF, 0x0F, 0x01, 0x53, 0xFE, 0x90, 0x01,
-	0x81, 0x00, 0x4B, 0xF8, 0xE6, 0x3A, 0x3F, 0x21, 0x16, 0xF3, 0x02,
-	0x06, 0xA5, 0xFD, 0x8A, 0x00, 0x18, 0x00, 0xE2, 0xFF, 0x02, 0x00,
-	0x10, 0x00, 0x8D, 0xFF, 0x3C, 0x01, 0xCE, 0xFD, 0xB7, 0x02, 0x5A,
-	0xFE, 0xF7, 0xFB, 0xC6, 0x3E, 0x2C, 0x1A, 0xFC, 0xF3, 0x41, 0x06,
-	0x2E, 0xFD, 0xE7, 0x00, 0xE7, 0xFF, 0xF2, 0xFF, 0x01, 0x00, 0x10,
-	0x00, 0x8B, 0xFF, 0x5A, 0x01, 0x5E, 0xFD, 0xD2, 0x03, 0x0E, 0xFC,
-	0x8B, 0x00, 0x75, 0x41, 0x32, 0x13, 0x75, 0xF5, 0x1C, 0x06, 0xEE,
-	0xFC, 0x2B, 0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00,
-	0x91, 0xFF, 0x64, 0x01, 0x0D, 0xFD, 0xCD, 0x04, 0xBB, 0xF9, 0xF2,
-	0x05, 0xD9, 0x42, 0x88, 0x0C, 0x5E, 0xF7, 0xA1, 0x05, 0xE3, 0xFC,
-	0x54, 0x01, 0xA3, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
-	0x00, 0xA2, 0xFF, 0x56, 0x01, 0xE5, 0xFC, 0x94, 0x05, 0x87, 0xF7,
-	0x0A, 0x0C, 0xE6, 0x42, 0x64, 0x06, 0x8E, 0xF9, 0xDE, 0x04, 0x09,
-	0xFD, 0x64, 0x01, 0x92, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0xBD, 0xFF, 0x2F, 0x01, 0xEC, 0xFC, 0x16, 0x06, 0x98, 0xF5, 0xAB,
-	0x12, 0x9C, 0x41, 0xEE, 0x00, 0xE0, 0xFB, 0xE6, 0x03, 0x57, 0xFD,
-	0x5B, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF3, 0xFF, 0xE4,
-	0xFF, 0xED, 0x00, 0x27, 0xFD, 0x41, 0x06, 0x14, 0xF4, 0xA1, 0x19,
-	0x06, 0x3F, 0x49, 0xFC, 0x2E, 0xFE, 0xCD, 0x02, 0xC4, 0xFD, 0x3F,
-	0x01, 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE3, 0xFF, 0x14, 0x00,
-	0x92, 0x00, 0x9A, 0xFD, 0x0A, 0x06, 0x22, 0xF3, 0xB4, 0x20, 0x3C,
-	0x3B, 0x8B, 0xF8, 0x58, 0x00, 0xA7, 0x01, 0x48, 0xFE, 0x13, 0x01,
-	0x96, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x4C, 0x00, 0x20,
-	0x00, 0x42, 0xFE, 0x6A, 0x05, 0xE3, 0xF2, 0xAB, 0x27, 0x66, 0x36,
-	0xC0, 0xF5, 0x44, 0x02, 0x85, 0x00, 0xD7, 0xFE, 0xDD, 0x00, 0xA5,
-	0xFF, 0x0C, 0x00, 0x07, 0x00, 0xBE, 0xFF, 0x89, 0x00, 0x9D, 0xFF,
-	0x1A, 0xFF, 0x5E, 0x04, 0x76, 0xF3, 0x45, 0x2E, 0xAA, 0x30, 0xEB,
-	0xF3, 0xDB, 0x03, 0x79, 0xFF, 0x67, 0xFF, 0xA0, 0x00, 0xB7, 0xFF,
-	0x09, 0x00, 0x0B, 0x00, 0xAC, 0xFF, 0xC6, 0x00, 0x0E, 0xFF, 0x1A,
-	0x00, 0xEB, 0x02, 0xEF, 0xF4, 0x49, 0x34, 0x43, 0x2A, 0x02, 0xF3,
-	0x0F, 0x05, 0x90, 0xFE, 0xEF, 0xFF, 0x63, 0x00, 0xCA, 0xFF, 0x06,
-	0x00, 0x0E, 0x00, 0x9B, 0xFF, 0xFF, 0x00, 0x7E, 0xFE, 0x36, 0x01,
-	0x1E, 0x01, 0x5B, 0xF7, 0x7E, 0x39, 0x69, 0x23, 0xF3, 0xF2, 0xD9,
-	0x05, 0xD4, 0xFD, 0x69, 0x00, 0x29, 0x00, 0xDD, 0xFF, 0x03, 0x00,
-	0x10, 0x00, 0x90, 0xFF, 0x30, 0x01, 0xF5, 0xFD, 0x5C, 0x02, 0x09,
-	0xFF, 0xBC, 0xFA, 0xB5, 0x3D, 0x5A, 0x1C, 0xA3, 0xF3, 0x38, 0x06,
-	0x4D, 0xFD, 0xCD, 0x00, 0xF5, 0xFF, 0xED, 0xFF, 0x01, 0x00, 0x11,
-	0x00, 0x8B, 0xFF, 0x53, 0x01, 0x7E, 0xFD, 0x7D, 0x03, 0xC5, 0xFC,
-	0x0B, 0xFF, 0xC3, 0x40, 0x51, 0x15, 0xF4, 0xF4, 0x31, 0x06, 0xFC,
-	0xFC, 0x19, 0x01, 0xCB, 0xFF, 0xFB, 0xFF, 0x00, 0x00, 0x0F, 0x00,
-	0x8E, 0xFF, 0x63, 0x01, 0x22, 0xFD, 0x84, 0x04, 0x71, 0xFA, 0x34,
-	0x04, 0x90, 0x42, 0x89, 0x0E, 0xBE, 0xF6, 0xCF, 0x05, 0xE1, 0xFC,
-	0x4A, 0x01, 0xAB, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
-	0x00, 0x9B, 0xFF, 0x5D, 0x01, 0xEC, 0xFC, 0x5D, 0x05, 0x2F, 0xF8,
-	0x19, 0x0A, 0x07, 0x43, 0x37, 0x08, 0xDD, 0xF8, 0x21, 0x05, 0xF8,
-	0xFC, 0x62, 0x01, 0x96, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00,
-	0xB4, 0xFF, 0x3E, 0x01, 0xE4, 0xFC, 0xF6, 0x05, 0x26, 0xF6, 0x95,
-	0x10, 0x26, 0x42, 0x87, 0x02, 0x28, 0xFB, 0x37, 0x04, 0x3B, 0xFD,
-	0x60, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF7, 0xFF, 0xD7,
-	0xFF, 0x04, 0x01, 0x0F, 0xFD, 0x3E, 0x06, 0x7D, 0xF4, 0x76, 0x17,
-	0xF4, 0x3F, 0x9F, 0xFD, 0x7B, 0xFD, 0x26, 0x03, 0xA0, 0xFD, 0x4A,
-	0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE9, 0xFF, 0x04, 0x00,
-	0xB1, 0x00, 0x71, 0xFD, 0x26, 0x06, 0x5A, 0xF3, 0x88, 0x1E, 0x87,
-	0x3C, 0x98, 0xF9, 0xB3, 0xFF, 0x02, 0x02, 0x1E, 0xFE, 0x22, 0x01,
-	0x93, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD7, 0xFF, 0x3A, 0x00, 0x45,
-	0x00, 0x09, 0xFE, 0xA7, 0x05, 0xE1, 0xF2, 0x8D, 0x25, 0xFD, 0x37,
-	0x82, 0xF6, 0xB5, 0x01, 0xDC, 0x00, 0xAA, 0xFE, 0xEE, 0x00, 0xA0,
-	0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC4, 0xFF, 0x76, 0x00, 0xC7, 0xFF,
-	0xD3, 0xFE, 0xBC, 0x04, 0x31, 0xF3, 0x4A, 0x2C, 0x83, 0x32, 0x61,
-	0xF4, 0x68, 0x03, 0xC8, 0xFF, 0x3B, 0xFF, 0xB3, 0x00, 0xB1, 0xFF,
-	0x0A, 0x00, 0x0A, 0x00, 0xB1, 0xFF, 0xB3, 0x00, 0x3B, 0xFF, 0xC8,
-	0xFF, 0x68, 0x03, 0x61, 0xF4, 0x83, 0x32, 0x4A, 0x2C, 0x31, 0xF3,
-	0xBC, 0x04, 0xD3, 0xFE, 0xC7, 0xFF, 0x76, 0x00, 0xC4, 0xFF, 0x06,
-	0x00, 0x0D, 0x00, 0xA0, 0xFF, 0xEE, 0x00, 0xAA, 0xFE, 0xDC, 0x00,
-	0xB5, 0x01, 0x82, 0xF6, 0xFD, 0x37, 0x8D, 0x25, 0xE1, 0xF2, 0xA7,
-	0x05, 0x09, 0xFE, 0x45, 0x00, 0x3A, 0x00, 0xD7, 0xFF, 0x04, 0x00,
-	0x0F, 0x00, 0x93, 0xFF, 0x22, 0x01, 0x1E, 0xFE, 0x02, 0x02, 0xB3,
-	0xFF, 0x98, 0xF9, 0x87, 0x3C, 0x88, 0x1E, 0x5A, 0xF3, 0x26, 0x06,
-	0x71, 0xFD, 0xB1, 0x00, 0x04, 0x00, 0xE9, 0xFF, 0x02, 0x00, 0x11,
-	0x00, 0x8B, 0xFF, 0x4A, 0x01, 0xA0, 0xFD, 0x26, 0x03, 0x7B, 0xFD,
-	0x9F, 0xFD, 0xF4, 0x3F, 0x76, 0x17, 0x7D, 0xF4, 0x3E, 0x06, 0x0F,
-	0xFD, 0x04, 0x01, 0xD7, 0xFF, 0xF7, 0xFF, 0x01, 0x00, 0x10, 0x00,
-	0x8C, 0xFF, 0x60, 0x01, 0x3B, 0xFD, 0x37, 0x04, 0x28, 0xFB, 0x87,
-	0x02, 0x26, 0x42, 0x95, 0x10, 0x26, 0xF6, 0xF6, 0x05, 0xE4, 0xFC,
-	0x3E, 0x01, 0xB4, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x96,
-	0xFF, 0x62, 0x01, 0xF8, 0xFC, 0x21, 0x05, 0xDD, 0xF8, 0x37, 0x08,
-	0x07, 0x43, 0x19, 0x0A, 0x2F, 0xF8, 0x5D, 0x05, 0xEC, 0xFC, 0x5D,
-	0x01, 0x9B, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
-	0xAB, 0xFF, 0x4A, 0x01, 0xE1, 0xFC, 0xCF, 0x05, 0xBE, 0xF6, 0x89,
-	0x0E, 0x90, 0x42, 0x34, 0x04, 0x71, 0xFA, 0x84, 0x04, 0x22, 0xFD,
-	0x63, 0x01, 0x8E, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xCB,
-	0xFF, 0x19, 0x01, 0xFC, 0xFC, 0x31, 0x06, 0xF4, 0xF4, 0x51, 0x15,
-	0xC3, 0x40, 0x0B, 0xFF, 0xC5, 0xFC, 0x7D, 0x03, 0x7E, 0xFD, 0x53,
-	0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xED, 0xFF, 0xF5, 0xFF,
-	0xCD, 0x00, 0x4D, 0xFD, 0x38, 0x06, 0xA3, 0xF3, 0x5A, 0x1C, 0xB5,
-	0x3D, 0xBC, 0xFA, 0x09, 0xFF, 0x5C, 0x02, 0xF5, 0xFD, 0x30, 0x01,
-	0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDD, 0xFF, 0x29, 0x00, 0x69,
-	0x00, 0xD4, 0xFD, 0xD9, 0x05, 0xF3, 0xF2, 0x69, 0x23, 0x7E, 0x39,
-	0x5B, 0xF7, 0x1E, 0x01, 0x36, 0x01, 0x7E, 0xFE, 0xFF, 0x00, 0x9B,
-	0xFF, 0x0E, 0x00, 0x06, 0x00, 0xCA, 0xFF, 0x63, 0x00, 0xEF, 0xFF,
-	0x90, 0xFE, 0x0F, 0x05, 0x02, 0xF3, 0x43, 0x2A, 0x49, 0x34, 0xEF,
-	0xF4, 0xEB, 0x02, 0x1A, 0x00, 0x0E, 0xFF, 0xC6, 0x00, 0xAC, 0xFF,
-	0x0B, 0x00, 0x09, 0x00, 0xB7, 0xFF, 0xA0, 0x00, 0x67, 0xFF, 0x79,
-	0xFF, 0xDB, 0x03, 0xEB, 0xF3, 0xAA, 0x30, 0x45, 0x2E, 0x76, 0xF3,
-	0x5E, 0x04, 0x1A, 0xFF, 0x9D, 0xFF, 0x89, 0x00, 0xBE, 0xFF, 0x07,
-	0x00, 0x0C, 0x00, 0xA5, 0xFF, 0xDD, 0x00, 0xD7, 0xFE, 0x85, 0x00,
-	0x44, 0x02, 0xC0, 0xF5, 0x66, 0x36, 0xAB, 0x27, 0xE3, 0xF2, 0x6A,
-	0x05, 0x42, 0xFE, 0x20, 0x00, 0x4C, 0x00, 0xD1, 0xFF, 0x04, 0x00,
-	0x0F, 0x00, 0x96, 0xFF, 0x13, 0x01, 0x48, 0xFE, 0xA7, 0x01, 0x58,
-	0x00, 0x8B, 0xF8, 0x3C, 0x3B, 0xB4, 0x20, 0x22, 0xF3, 0x0A, 0x06,
-	0x9A, 0xFD, 0x92, 0x00, 0x14, 0x00, 0xE3, 0xFF, 0x02, 0x00, 0x10,
-	0x00, 0x8D, 0xFF, 0x3F, 0x01, 0xC4, 0xFD, 0xCD, 0x02, 0x2E, 0xFE,
-	0x49, 0xFC, 0x06, 0x3F, 0xA1, 0x19, 0x14, 0xF4, 0x41, 0x06, 0x27,
-	0xFD, 0xED, 0x00, 0xE4, 0xFF, 0xF3, 0xFF, 0x01, 0x00, 0x10, 0x00,
-	0x8B, 0xFF, 0x5B, 0x01, 0x57, 0xFD, 0xE6, 0x03, 0xE0, 0xFB, 0xEE,
-	0x00, 0x9C, 0x41, 0xAB, 0x12, 0x98, 0xF5, 0x16, 0x06, 0xEC, 0xFC,
-	0x2F, 0x01, 0xBD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x92,
-	0xFF, 0x64, 0x01, 0x09, 0xFD, 0xDE, 0x04, 0x8E, 0xF9, 0x64, 0x06,
-	0xE6, 0x42, 0x0A, 0x0C, 0x87, 0xF7, 0x94, 0x05, 0xE5, 0xFC, 0x56,
-	0x01, 0xA2, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
-	0xA3, 0xFF, 0x54, 0x01, 0xE3, 0xFC, 0xA1, 0x05, 0x5E, 0xF7, 0x88,
-	0x0C, 0xD9, 0x42, 0xF2, 0x05, 0xBB, 0xF9, 0xCD, 0x04, 0x0D, 0xFD,
-	0x64, 0x01, 0x91, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0,
-	0xFF, 0x2B, 0x01, 0xEE, 0xFC, 0x1C, 0x06, 0x75, 0xF5, 0x32, 0x13,
-	0x75, 0x41, 0x8B, 0x00, 0x0E, 0xFC, 0xD2, 0x03, 0x5E, 0xFD, 0x5A,
-	0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF2, 0xFF, 0xE7, 0xFF,
-	0xE7, 0x00, 0x2E, 0xFD, 0x41, 0x06, 0xFC, 0xF3, 0x2C, 0x1A, 0xC6,
-	0x3E, 0xF7, 0xFB, 0x5A, 0xFE, 0xB7, 0x02, 0xCE, 0xFD, 0x3C, 0x01,
-	0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE2, 0xFF, 0x18, 0x00, 0x8A,
-	0x00, 0xA5, 0xFD, 0x02, 0x06, 0x16, 0xF3, 0x3F, 0x21, 0xE6, 0x3A,
-	0x4B, 0xF8, 0x81, 0x00, 0x90, 0x01, 0x53, 0xFE, 0x0F, 0x01, 0x97,
-	0xFF, 0x0E, 0x00, 0x05, 0x00, 0xD0, 0xFF, 0x50, 0x00, 0x17, 0x00,
-	0x51, 0xFE, 0x59, 0x05, 0xE7, 0xF2, 0x31, 0x28, 0xFB, 0x35, 0x93,
-	0xF5, 0x66, 0x02, 0x6F, 0x00, 0xE2, 0xFE, 0xD8, 0x00, 0xA6, 0xFF,
-	0x0C, 0x00, 0x08, 0x00, 0xBD, 0xFF, 0x8D, 0x00, 0x92, 0xFF, 0x2D,
-	0xFF, 0x45, 0x04, 0x8B, 0xF3, 0xC1, 0x2E, 0x31, 0x30, 0xD1, 0xF3,
-	0xF6, 0x03, 0x65, 0xFF, 0x72, 0xFF, 0x9B, 0x00, 0xB8, 0xFF, 0x08,
-	0x00, 0x0B, 0x00, 0xAA, 0xFF, 0xCA, 0x00, 0x03, 0xFF, 0x2F, 0x00,
-	0xCB, 0x02, 0x16, 0xF5, 0xB8, 0x34, 0xC0, 0x29, 0xF9, 0xF2, 0x23,
-	0x05, 0x80, 0xFE, 0xF9, 0xFF, 0x5E, 0x00, 0xCC, 0xFF, 0x05, 0x00,
-	0x0E, 0x00, 0x9A, 0xFF, 0x03, 0x01, 0x73, 0xFE, 0x4C, 0x01, 0xF7,
-	0x00, 0x94, 0xF7, 0xDB, 0x39, 0xDF, 0x22, 0xFA, 0xF2, 0xE5, 0x05,
-	0xC8, 0xFD, 0x71, 0x00, 0x25, 0x00, 0xDE, 0xFF, 0x03, 0x00, 0x10,
-	0x00, 0x8F, 0xFF, 0x33, 0x01, 0xEB, 0xFD, 0x73, 0x02, 0xDE, 0xFE,
-	0x08, 0xFB, 0xFB, 0x3D, 0xCE, 0x1B, 0xB8, 0xF3, 0x3B, 0x06, 0x45,
-	0xFD, 0xD4, 0x00, 0xF2, 0xFF, 0xEF, 0xFF, 0x01, 0x00, 0x11, 0x00,
-	0x8A, 0xFF, 0x55, 0x01, 0x75, 0xFD, 0x92, 0x03, 0x97, 0xFC, 0x69,
-	0xFF, 0xF2, 0x40, 0xC8, 0x14, 0x13, 0xF5, 0x2D, 0x06, 0xF8, 0xFC,
-	0x1E, 0x01, 0xC8, 0xFF, 0xFC, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x8F,
-	0xFF, 0x64, 0x01, 0x1D, 0xFD, 0x97, 0x04, 0x43, 0xFA, 0xA1, 0x04,
-	0xA5, 0x42, 0x08, 0x0E, 0xE6, 0xF6, 0xC4, 0x05, 0xE1, 0xFC, 0x4D,
-	0x01, 0xA9, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
-	0x9D, 0xFF, 0x5C, 0x01, 0xEA, 0xFC, 0x6C, 0x05, 0x05, 0xF8, 0x94,
-	0x0A, 0x03, 0x43, 0xC1, 0x07, 0x09, 0xF9, 0x10, 0x05, 0xFC, 0xFC,
-	0x62, 0x01, 0x95, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB6,
-	0xFF, 0x3B, 0x01, 0xE5, 0xFC, 0xFF, 0x05, 0x02, 0xF6, 0x19, 0x11,
-	0x06, 0x42, 0x1F, 0x02, 0x56, 0xFB, 0x23, 0x04, 0x41, 0xFD, 0x5F,
-	0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF6, 0xFF, 0xDA, 0xFF,
-	0xFF, 0x00, 0x15, 0xFD, 0x40, 0x06, 0x62, 0xF4, 0x01, 0x18, 0xBB,
-	0x3F, 0x47, 0xFD, 0xA8, 0xFD, 0x10, 0x03, 0xA9, 0xFD, 0x47, 0x01,
-	0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE7, 0xFF, 0x08, 0x00, 0xA9,
-	0x00, 0x7B, 0xFD, 0x20, 0x06, 0x4B, 0xF3, 0x13, 0x1F, 0x36, 0x3C,
-	0x52, 0xF9, 0xDD, 0xFF, 0xEB, 0x01, 0x28, 0xFE, 0x1F, 0x01, 0x93,
-	0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD6, 0xFF, 0x3F, 0x00, 0x3C, 0x00,
-	0x16, 0xFE, 0x98, 0x05, 0xE0, 0xF2, 0x16, 0x26, 0x99, 0x37, 0x4F,
-	0xF6, 0xD9, 0x01, 0xC6, 0x00, 0xB5, 0xFE, 0xEA, 0x00, 0xA1, 0xFF,
-	0x0D, 0x00, 0x07, 0x00, 0xC3, 0xFF, 0x7A, 0x00, 0xBC, 0xFF, 0xE4,
-	0xFE, 0xA5, 0x04, 0x41, 0xF3, 0xCA, 0x2C, 0x0E, 0x32, 0x42, 0xF4,
-	0x85, 0x03, 0xB4, 0xFF, 0x46, 0xFF, 0xAE, 0x00, 0xB3, 0xFF, 0x09,
-	0x00, 0x0A, 0x00, 0xB0, 0xFF, 0xB8, 0x00, 0x30, 0xFF, 0xDC, 0xFF,
-	0x49, 0x03, 0x83, 0xF4, 0xF5, 0x32, 0xC9, 0x2B, 0x23, 0xF3, 0xD1,
-	0x04, 0xC2, 0xFE, 0xD1, 0xFF, 0x71, 0x00, 0xC6, 0xFF, 0x06, 0x00,
-	0x0D, 0x00, 0x9F, 0xFF, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00, 0x90,
-	0x01, 0xB6, 0xF6, 0x5F, 0x38, 0x04, 0x25, 0xE4, 0xF2, 0xB4, 0x05,
-	0xFB, 0xFD, 0x4E, 0x00, 0x36, 0x00, 0xD9, 0xFF, 0x04, 0x00, 0x0F,
-	0x00, 0x92, 0xFF, 0x26, 0x01, 0x13, 0xFE, 0x18, 0x02, 0x89, 0xFF,
-	0xDF, 0xF9, 0xD3, 0x3C, 0xFC, 0x1D, 0x6B, 0xF3, 0x2C, 0x06, 0x67,
-	0xFD, 0xB8, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0x02, 0x00, 0x11, 0x00,
-	0x8B, 0xFF, 0x4C, 0x01, 0x97, 0xFD, 0x3C, 0x03, 0x4D, 0xFD, 0xF8,
-	0xFD, 0x2A, 0x40, 0xED, 0x16, 0x9A, 0xF4, 0x3C, 0x06, 0x0A, 0xFD,
-	0x0A, 0x01, 0xD4, 0xFF, 0xF8, 0xFF, 0x01, 0x00, 0x10, 0x00, 0x8C,
-	0xFF, 0x61, 0x01, 0x34, 0xFD, 0x4B, 0x04, 0xFA, 0xFA, 0xF1, 0x02,
-	0x42, 0x42, 0x11, 0x10, 0x4C, 0xF6, 0xED, 0x05, 0xE3, 0xFC, 0x41,
-	0x01, 0xB1, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x97, 0xFF,
-	0x61, 0x01, 0xF5, 0xFC, 0x30, 0x05, 0xB1, 0xF8, 0xAE, 0x08, 0x0A,
-	0x43, 0x9F, 0x09, 0x5A, 0xF8, 0x4F, 0x05, 0xEF, 0xFC, 0x5F, 0x01,
-	0x9A, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xAD,
-	0xFF, 0x48, 0x01, 0xE2, 0xFC, 0xDA, 0x05, 0x97, 0xF6, 0x0B, 0x0F,
-	0x79, 0x42, 0xC7, 0x03, 0x9E, 0xFA, 0x71, 0x04, 0x28, 0xFD, 0x63,
-	0x01, 0x8D, 0xFF, 0x0F, 0x00 
-};
-
-static u16
-CoefficientSizes[] = {
-    /* Playback */
-    0x00C0, 0x5000, 0x0060, 0x2800, 0x0040, 0x0060, 0x1400, 0x0000,
-    /* Record */
-    0x0020, 0x1260, 0x0020, 0x1260, 0x0000, 0x0040, 0x1260, 0x0000,
-};
-
-#ifndef JUST_DATA
-
-static u16
-nm256_getStartOffset (u8 which)
-{
-    u16 offset = 0;
-
-    while (which-- > 0)
-	offset += CoefficientSizes[which];
-
-    return offset;
-}
-
-static void
-nm256_loadOneCoefficient (struct nm256_info *card, int devnum, u32 port, 
-			  u16 which)
-{
-    u32 coeffBuf = (which < 8) ? card->coeffBuf : card->allCoeffBuf;
-    u16 offset = nm256_getStartOffset (which);
-    u16 size = CoefficientSizes[which];
-
-    card->coeffsCurrent = 0;
-
-    if (nm256_debug)
-	printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d, size %d, port 0x%x\n",
-		coeffBuf, coeffBuf + size - 1, which, size, port);
-    nm256_writeBuffer8 (card, coefficients + offset, 1, coeffBuf, size);
-    nm256_writePort32 (card, 2, port + 0, coeffBuf);
-    /* ???  Record seems to behave differently than playback.  */
-    if (devnum == 0)
-	size--;
-    nm256_writePort32 (card, 2, port + 4, coeffBuf + size);
-}
-
-static void
-nm256_loadAllCoefficients (struct nm256_info *card)
-{
-    nm256_writeBuffer8 (card, coefficients, 1, card->allCoeffBuf,
-			  NM_TOTAL_COEFF_COUNT * 4);
-    card->coeffsCurrent = 1;
-}
-
-static void
-nm256_loadCoefficient (struct nm256_info *card, int which, int number)
-{
-    static u16 addrs[3] = { 0x1c, 0x21c, 0x408 };
-    /* The enable register for the specified engine.  */
-    u32 poffset = (which == 1 ? 0x200 : 1);
-
-    if (nm256_readPort8 (card, 2, poffset) & 1) {
-	printk (KERN_ERR "NM256: Engine was enabled while loading coefficients!\n");
-	return;
-    }
-
-    /* The recording engine uses coefficient values 8-15.  */
-    if (which == 1)
-	number += 8;
-
-    if (! nm256_cachedCoefficients (card))
-	nm256_loadOneCoefficient (card, which, addrs[which], number);
-    else {
-	u32 base = card->allCoeffBuf;
-	u32 offset = nm256_getStartOffset (number);
-	u32 endOffset = offset + CoefficientSizes[number];
-
-	if (nm256_debug)
-	    printk (KERN_DEBUG "loading coefficient %d at port 0x%x, offset %d (0x%x-0x%x)\n",
-		    number, addrs[which], offset, base + offset,
-		    base + endOffset - 1);
-
-	if (! card->coeffsCurrent)
-	    nm256_loadAllCoefficients (card);
-
-	nm256_writePort32 (card, 2, addrs[which], base + offset);
-	nm256_writePort32 (card, 2, addrs[which] + 4, base + endOffset - 1);
-    }
-}
-
-#endif /* JUST_DATA */
-
-#endif
-
-/*
- * Local variables:
- *  c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c
index fc273e5..7781c13 100644
--- a/sound/oss/opl3.c
+++ b/sound/oss/opl3.c
@@ -34,7 +34,6 @@
 
 #include "sound_config.h"
 
-#include "opl3.h"
 #include "opl3_hw.h"
 
 #define MAX_VOICE	18
@@ -73,7 +72,6 @@
 	unsigned char   cmask;
 
 	int             is_opl4;
-	int            *osp;
 } opl_devinfo;
 
 static struct opl_devinfo *devc = NULL;
@@ -144,7 +142,7 @@
 	}
 }
 
-int opl3_detect(int ioaddr, int *osp)
+static int opl3_detect(int ioaddr)
 {
 	/*
 	 * This function returns 1 if the FM chip is present at the given I/O port
@@ -182,7 +180,6 @@
 		goto cleanup_devc;
 	}
 
-	devc->osp = osp;
 	devc->base = ioaddr;
 
 	/* Reset timers 1 and 2 */
@@ -1105,7 +1102,7 @@
 	.setup_voice	= opl3_setup_voice
 };
 
-int opl3_init(int ioaddr, int *osp, struct module *owner)
+static int opl3_init(int ioaddr, struct module *owner)
 {
 	int i;
 	int me;
@@ -1194,9 +1191,6 @@
 	return me;
 }
 
-EXPORT_SYMBOL(opl3_init);
-EXPORT_SYMBOL(opl3_detect);
-
 static int me;
 
 static int io = -1;
@@ -1209,12 +1203,12 @@
 
 	if (io != -1)	/* User loading pure OPL3 module */
 	{
-		if (!opl3_detect(io, NULL))
+		if (!opl3_detect(io))
 		{
 			return -ENODEV;
 		}
 
-		me = opl3_init(io, NULL, THIS_MODULE);
+		me = opl3_init(io, THIS_MODULE);
 	}
 
 	return 0;
diff --git a/sound/oss/opl3.h b/sound/oss/opl3.h
deleted file mode 100644
index 0bc9a4b..0000000
--- a/sound/oss/opl3.h
+++ /dev/null
@@ -1,5 +0,0 @@
-
-int opl3_detect (int ioaddr, int *osp);
-int opl3_init(int ioaddr, int *osp, struct module *owner);
-
-void enable_opl3_mode(int left, int right, int both);
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
deleted file mode 100644
index e20051f..0000000
--- a/sound/oss/opl3sa2.c
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
- * sound/oss/opl3sa2.c
- *
- * A low level driver for Yamaha OPL3-SA2 and SA3 cards.
- * NOTE: All traces of the name OPL3-SAx have now (December 2000) been
- *       removed from the driver code, as an email exchange with Yamaha
- *       provided the information that the YMF-719 is indeed just a
- *       re-badged 715.
- *
- * Copyright 1998-2001 Scott Murray <scott@spiteful.org>
- *
- * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
- * and others.  Now incorporates code/ideas from pss.c, also by Hannu
- * Savolainen.  Both of those files are distributed with the following
- * license:
- *
- * "Copyright (C) by Hannu Savolainen 1993-1997
- *
- *  OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- *  Version 2 (June 1991). See the "COPYING" file distributed with this software
- *  for more info."
- *
- * As such, in accordance with the above license, this file, opl3sa2.c, is
- * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
- * See the "COPYING" file distributed with this software for more information.
- *
- * Change History
- * --------------
- * Scott Murray            Original driver (Jun 14, 1998)
- * Paul J.Y. Lahaie        Changed probing / attach code order
- * Scott Murray            Added mixer support (Dec 03, 1998)
- * Scott Murray            Changed detection code to be more forgiving,
- *                         added force option as last resort,
- *                         fixed ioctl return values. (Dec 30, 1998)
- * Scott Murray            Simpler detection code should work all the time now
- *                         (with thanks to Ben Hutchings for the heuristic),
- *                         removed now unnecessary force option. (Jan 5, 1999)
- * Christoph Hellwig	   Adapted to module_init/module_exit (Mar 4, 2000)
- * Scott Murray            Reworked SA2 versus SA3 mixer code, updated chipset
- *                         version detection code (again!). (Dec 5, 2000)
- * Scott Murray            Adjusted master volume mixer scaling. (Dec 6, 2000)
- * Scott Murray            Based on a patch by Joel Yliluoma (aka Bisqwit),
- *                         integrated wide mixer and adjusted mic, bass, treble
- *                         scaling. (Dec 6, 2000)
- * Scott Murray            Based on a patch by Peter Englmaier, integrated
- *                         ymode and loopback options. (Dec 6, 2000)
- * Scott Murray            Inspired by a patch by Peter Englmaier, and based on
- *                         what ALSA does, added initialization code for the
- *                         default DMA and IRQ settings. (Dec 6, 2000)
- * Scott Murray            Added some more checks to the card detection code,
- *                         based on what ALSA does. (Dec 12, 2000)
- * Scott Murray            Inspired by similar patches from John Fremlin,
- *                         Jim Radford, Mike Rolig, and Ingmar Steen, added 2.4
- *                         ISA PnP API support, mainly based on bits from
- *                         sb_card.c and awe_wave.c. (Dec 12, 2000)
- * Scott Murray            Some small cleanups to the init code output.
- *                         (Jan 7, 2001)
- * Zwane Mwaikambo	   Added PM support. (Dec 4 2001)
- *
- * Adam Belay              Converted driver to new PnP Layer (Oct 12, 2002)
- * Zwane Mwaikambo	   Code, data structure cleanups. (Feb 15 2002)
- * Zwane Mwaikambo	   Free resources during auxiliary device probe
- * 			   failures (Apr 29 2002)
- *   
- */
-
-#include <linux/pnp.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include "sound_config.h"
-
-#include "ad1848.h"
-#include "mpu401.h"
-
-#define OPL3SA2_MODULE_NAME	"opl3sa2"
-#define PFX			OPL3SA2_MODULE_NAME ": "
-
-/* Useful control port indexes: */
-#define OPL3SA2_PM	     0x01
-#define OPL3SA2_SYS_CTRL     0x02
-#define OPL3SA2_IRQ_CONFIG   0x03
-#define OPL3SA2_DMA_CONFIG   0x06
-#define OPL3SA2_MASTER_LEFT  0x07
-#define OPL3SA2_MASTER_RIGHT 0x08
-#define OPL3SA2_MIC          0x09
-#define OPL3SA2_MISC         0x0A
-
-#define OPL3SA3_WIDE         0x14
-#define OPL3SA3_BASS         0x15
-#define OPL3SA3_TREBLE       0x16
-
-/* Useful constants: */
-#define DEFAULT_VOLUME 50
-#define DEFAULT_MIC    50
-#define DEFAULT_TIMBRE 0
-
-/* Power saving modes */
-#define OPL3SA2_PM_MODE0	0x00
-#define OPL3SA2_PM_MODE1	0x04	/* PSV */
-#define OPL3SA2_PM_MODE2	0x05	/* PSV | PDX */
-#define OPL3SA2_PM_MODE3	0x27	/* ADOWN | PSV | PDN | PDX */
-
-
-/* For checking against what the card returns: */
-#define VERSION_UNKNOWN 0
-#define VERSION_YMF711  1
-#define VERSION_YMF715  2
-#define VERSION_YMF715B 3
-#define VERSION_YMF715E 4
-/* also assuming that anything > 4 but <= 7 is a 715E */
-
-/* Chipset type constants for use below */
-#define CHIPSET_UNKNOWN -1
-#define CHIPSET_OPL3SA2 0
-#define CHIPSET_OPL3SA3 1
-static const char *CHIPSET_TABLE[] = {"OPL3-SA2", "OPL3-SA3"};
-
-#ifdef CONFIG_PNP
-#define OPL3SA2_CARDS_MAX 4
-#else
-#define OPL3SA2_CARDS_MAX 1
-#endif
-
-/* This should be pretty obvious */
-static int opl3sa2_cards_num;
-
-typedef struct {
-	/* device resources */
-	unsigned short cfg_port;
-	struct address_info cfg;
-	struct address_info cfg_mss;
-	struct address_info cfg_mpu;
-#ifdef CONFIG_PNP
-	/* PnP Stuff */
-	struct pnp_dev* pdev;
-	int activated;			/* Whether said devices have been activated */
-#endif
-	unsigned int	card;
-	int		chipset;	/* What's my version(s)? */
-	char		*chipset_name;
-
-	/* mixer data */
-	int		mixer;
-	unsigned int	volume_l;
-	unsigned int	volume_r;
-	unsigned int	mic;
-	unsigned int	bass_l;
-	unsigned int	bass_r;
-	unsigned int	treble_l;
-	unsigned int	treble_r;
-	unsigned int	wide_l;
-	unsigned int	wide_r;
-} opl3sa2_state_t;
-static opl3sa2_state_t opl3sa2_state[OPL3SA2_CARDS_MAX];
-
-	
-
-/* Our parameters */
-static int __initdata io	= -1;
-static int __initdata mss_io	= -1;
-static int __initdata mpu_io	= -1;
-static int __initdata irq	= -1;
-static int __initdata dma	= -1;
-static int __initdata dma2	= -1;
-static int __initdata ymode	= -1;
-static int __initdata loopback	= -1;
-
-#ifdef CONFIG_PNP
-/* PnP specific parameters */
-static int __initdata isapnp = 1;
-static int __initdata multiple = 1;
-
-/* Whether said devices have been activated */
-static int opl3sa2_activated[OPL3SA2_CARDS_MAX];
-#else
-static int __initdata isapnp; /* = 0 */
-static int __initdata multiple; /* = 0 */
-#endif
-
-MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
-MODULE_AUTHOR("Scott Murray <scott@spiteful.org>");
-MODULE_LICENSE("GPL");
-
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "Set I/O base of OPL3-SA2 or SA3 card (usually 0x370.  Address must be even and must be from 0x100 to 0xFFE)");
-
-module_param(mss_io, int, 0);
-MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");
-
-module_param(mpu_io, int, 0);
-MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be even and must be from 0x300 to 0x334)");
-
-module_param(irq, int, 0);
-MODULE_PARM_DESC(irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
-
-module_param(dma, int, 0);
-MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
-
-module_param(dma2, int, 0);
-MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
-
-module_param(ymode, int, 0);
-MODULE_PARM_DESC(ymode, "Set Yamaha 3D enhancement mode (0 = Desktop/Normal, 1 = Notebook PC (1), 2 = Notebook PC (2), 3 = Hi-Fi)");
-
-module_param(loopback, int, 0);
-MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)");
-
-#ifdef CONFIG_PNP
-module_param(isapnp, bool, 0);
-MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled");
-
-module_param(multiple, bool, 0);
-MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards");
-#endif
-
-
-/*
- * Standard read and write functions
-*/
-
-static inline void opl3sa2_write(unsigned short port,
-				 unsigned char  index,
-				 unsigned char  data)
-{
-	outb_p(index, port);
-	outb(data, port + 1);
-}
-
-
-static inline void opl3sa2_read(unsigned short port,
-				unsigned char  index,
-				unsigned char* data)
-{
-	outb_p(index, port);
-	*data = inb(port + 1);
-}
-
-
-/*
- * All of the mixer functions...
- */
-
-static void opl3sa2_set_volume(opl3sa2_state_t* devc, int left, int right)
-{
-	static unsigned char scale[101] = {
-		0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,
-		0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c,
-		0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b,
-		0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09,
-		0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08,
-		0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
-		0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
-		0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,
-		0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00
-	};
-	unsigned char vol;
-
-	vol = scale[left];
-
-	/* If level is zero, turn on mute */
-	if(!left)
-		vol |= 0x80;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol);
-
-	vol = scale[right];
-
-	/* If level is zero, turn on mute */
-	if(!right)
-		vol |= 0x80;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol);
-}
-
-
-static void opl3sa2_set_mic(opl3sa2_state_t* devc, int level)
-{
-	unsigned char vol = 0x1F;
-
-	if((level >= 0) && (level <= 100))
-		vol = 0x1F - (unsigned char) (32 * level / 101);
-
-	/* If level is zero, turn on mute */
-	if(!level)
-		vol |= 0x80;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol);
-}
-
-
-static void opl3sa3_set_bass(opl3sa2_state_t* devc, int left, int right)
-{
-	unsigned char bass;
-
-	bass = left ? ((unsigned char) (8 * left / 101)) : 0; 
-	bass |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass);
-}
-
-
-static void opl3sa3_set_treble(opl3sa2_state_t* devc, int left, int right)
-{	
-	unsigned char treble;
-
-	treble = left ? ((unsigned char) (8 * left / 101)) : 0; 
-	treble |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
-
-	opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble);
-}
-
-
-
-
-static void opl3sa2_mixer_reset(opl3sa2_state_t* devc)
-{
-	if (devc) {
-		opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);
-		devc->volume_l = devc->volume_r = DEFAULT_VOLUME;
-
-		opl3sa2_set_mic(devc, DEFAULT_MIC);
-		devc->mic = DEFAULT_MIC;
-
-		if (devc->chipset == CHIPSET_OPL3SA3) {
-			opl3sa3_set_bass(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
-			devc->bass_l = devc->bass_r = DEFAULT_TIMBRE;
-			opl3sa3_set_treble(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
-			devc->treble_l = devc->treble_r = DEFAULT_TIMBRE;
-		}
-	}
-}
-
-static inline void arg_to_vol_mono(unsigned int vol, int* value)
-{
-	int left;
-	
-	left = vol & 0x00ff;
-	if (left > 100)
-		left = 100;
-	*value = left;
-}
-
-
-static inline void arg_to_vol_stereo(unsigned int vol, int* aleft, int* aright)
-{
-	arg_to_vol_mono(vol, aleft);
-	arg_to_vol_mono(vol >> 8, aright);
-}
-
-
-static inline int ret_vol_mono(int vol)
-{
-	return ((vol << 8) | vol);
-}
-
-
-static inline int ret_vol_stereo(int left, int right)
-{
-	return ((right << 8) | left);
-}
-
-
-static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, void __user *arg)
-{
-	int retval, value, cmdf = cmd & 0xff;
-	int __user *p = (int __user *)arg;
-
-	opl3sa2_state_t* devc = &opl3sa2_state[dev];
-	
-	switch (cmdf) {
-		case SOUND_MIXER_VOLUME:
-		case SOUND_MIXER_MIC:
-		case SOUND_MIXER_DEVMASK:
-		case SOUND_MIXER_STEREODEVS: 
-		case SOUND_MIXER_RECMASK:
-		case SOUND_MIXER_RECSRC:
-		case SOUND_MIXER_CAPS: 
-			break;
-
-		default:
-			return -EINVAL;
-	}
-	
-	if (((cmd >> 8) & 0xff) != 'M')
-		return -EINVAL;
-		
-	retval = 0;
-	if (_SIOC_DIR (cmd) & _SIOC_WRITE) {
-		switch (cmdf) {
-			case SOUND_MIXER_VOLUME:
-				retval = get_user(value, (unsigned __user *) arg);
-				if (retval)
-					break;
-				arg_to_vol_stereo(value, &devc->volume_l, &devc->volume_r);
-				opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
-				value = ret_vol_stereo(devc->volume_l, devc->volume_r);
-				retval = put_user(value, p);
-				break;
-		  
-			case SOUND_MIXER_MIC:
-				retval = get_user(value, (unsigned __user *) arg);
-				if (retval)
-					break;
-				arg_to_vol_mono(value, &devc->mic);
-				opl3sa2_set_mic(devc, devc->mic);
-				value = ret_vol_mono(devc->mic);
-				retval = put_user(value, p);
-				break;
-
-			default:
-				retval = -EINVAL;
-		}
-	}
-	else {
-		/*
-		 * Return parameters
-		 */
-		switch (cmdf) {
-			case SOUND_MIXER_DEVMASK:
-				retval = put_user(SOUND_MASK_VOLUME | SOUND_MASK_MIC, p);
-				break;
-		  
-			case SOUND_MIXER_STEREODEVS:
-				retval = put_user(SOUND_MASK_VOLUME, p);
-				break;
-		  
-			case SOUND_MIXER_RECMASK:
-				/* No recording devices */
-				retval = put_user(0, p);
-				break;
-
-			case SOUND_MIXER_CAPS:
-				retval = put_user(SOUND_CAP_EXCL_INPUT, p);
-				break;
-
-			case SOUND_MIXER_RECSRC:
-				/* No recording source */
-				retval = put_user(0, p);
-				break;
-
-			case SOUND_MIXER_VOLUME:
-				value = ret_vol_stereo(devc->volume_l, devc->volume_r);
-				retval = put_user(value, p);
-				break;
-			  
-			case SOUND_MIXER_MIC:
-				value = ret_vol_mono(devc->mic);
-				put_user(value, p);
-				break;
-
-			default:
-				retval = -EINVAL;
-		}
-	}
-	return retval;
-}
-/* opl3sa2_mixer_ioctl end */
-
-
-static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, void __user * arg)
-{
-	int value, retval, cmdf = cmd & 0xff;
-
-	opl3sa2_state_t* devc = &opl3sa2_state[dev];
-
-	switch (cmdf) {
-	case SOUND_MIXER_BASS:
-		value = ret_vol_stereo(devc->bass_l, devc->bass_r);
-		retval = put_user(value, (int __user *) arg);
-		break;
-		
-	case SOUND_MIXER_TREBLE:
-		value = ret_vol_stereo(devc->treble_l, devc->treble_r);
-		retval = put_user(value, (int __user *) arg);
-		break;
-
-	case SOUND_MIXER_DIGITAL1:
-		value = ret_vol_stereo(devc->wide_l, devc->wide_r);
-		retval = put_user(value, (int __user *) arg);
-		break;
-
-	default:
-		retval = -EINVAL;
-	}
-	return retval;
-}
-/* opl3sa3_mixer_ioctl end */
-
-
-static struct mixer_operations opl3sa2_mixer_operations =
-{
-	.owner	= THIS_MODULE,
-	.id	= "OPL3-SA2",
-	.name	= "Yamaha OPL3-SA2",
-	.ioctl	= opl3sa2_mixer_ioctl
-};
-
-static struct mixer_operations opl3sa3_mixer_operations =
-{
-	.owner	= THIS_MODULE,
-	.id	= "OPL3-SA3",
-	.name	= "Yamaha OPL3-SA3",
-	.ioctl	= opl3sa3_mixer_ioctl
-};
-
-/* End of mixer-related stuff */
-
-
-/*
- * Component probe, attach, unload functions
- */
-
-static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config)
-{
-	unload_mpu401(hw_config);
-}
-
-
-static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct resource *ports)
-{
-	int initial_mixers;
-
-	initial_mixers = num_mixers;
-	attach_ms_sound(hw_config, ports, THIS_MODULE);	/* Slot 0 */
-	if (hw_config->slots[0] != -1) {
-		/* Did the MSS driver install? */
-		if(num_mixers == (initial_mixers + 1)) {
-			/* The MSS mixer is installed, reroute mixers appropriately */
-			AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
-			AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
-			AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
-		}
-		else {
-			printk(KERN_ERR PFX "MSS mixer not installed?\n");
-		}
-	}
-}
-
-
-static inline void __exit unload_opl3sa2_mss(struct address_info* hw_config)
-{
-	unload_ms_sound(hw_config);
-}
-
-
-static int __init probe_opl3sa2(struct address_info* hw_config, int card)
-{
-	unsigned char misc;
-	unsigned char tmp;
-	unsigned char version;
-
-	/*
-	 * Try and allocate our I/O port range.
-	 */
-	if (!request_region(hw_config->io_base, 2, OPL3SA2_MODULE_NAME)) {
-		printk(KERN_ERR PFX "Control I/O port %#x not free\n",
-		       hw_config->io_base);
-		goto out_nodev;
-	}
-
-	/*
-	 * Check if writing to the read-only version bits of the miscellaneous
-	 * register succeeds or not (it should not).
-	 */
-	opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc);
-	opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc ^ 0x07);
-	opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &tmp);
-	if(tmp != misc) {
-		printk(KERN_ERR PFX "Control I/O port %#x is not a YMF7xx chipset!\n",
-		       hw_config->io_base);
-		goto out_region;
-	}
-
-	/*
-	 * Check if the MIC register is accessible.
-	 */
-	opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
-	opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, 0x8a);
-	opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
-	if((tmp & 0x9f) != 0x8a) {
-		printk(KERN_ERR
-		       PFX "Control I/O port %#x is not a YMF7xx chipset!\n",
-		       hw_config->io_base);
-		goto out_region;
-	}
-	opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, tmp);
-
-	/*
-	 * Determine chipset type (SA2 or SA3)
-	 *
-	 * This is done by looking at the chipset version in the lower 3 bits
-	 * of the miscellaneous register.
-	 */
-	version = misc & 0x07;
-	printk(KERN_DEBUG PFX "Chipset version = %#x\n", version);
-	switch (version) {
-		case 0:
-			opl3sa2_state[card].chipset = CHIPSET_UNKNOWN;
-			printk(KERN_ERR
-			       PFX "Unknown Yamaha audio controller version\n");
-			break;
-
-		case VERSION_YMF711:
-			opl3sa2_state[card].chipset = CHIPSET_OPL3SA2;
-			printk(KERN_INFO PFX "Found OPL3-SA2 (YMF711)\n");
-			break;
-
-		case VERSION_YMF715:
-			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
-			printk(KERN_INFO
-			       PFX "Found OPL3-SA3 (YMF715 or YMF719)\n");
-			break;
-
-		case VERSION_YMF715B:
-			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
-			printk(KERN_INFO
-			       PFX "Found OPL3-SA3 (YMF715B or YMF719B)\n");
-			break;
-
-		case VERSION_YMF715E:
-		default:
-			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
-			printk(KERN_INFO
-			       PFX "Found OPL3-SA3 (YMF715E or YMF719E)\n");
-			break;
-	}
-
-	if (opl3sa2_state[card].chipset != CHIPSET_UNKNOWN) {
-		/* Generate a pretty name */
-		opl3sa2_state[card].chipset_name = (char *)CHIPSET_TABLE[opl3sa2_state[card].chipset];
-		return 0;
-	}
-
-out_region:
-	release_region(hw_config->io_base, 2);
-out_nodev:
-	return -ENODEV;
-}
-
-
-static void __init attach_opl3sa2(struct address_info* hw_config, int card)
-{
-	/* Initialize IRQ configuration to IRQ-B: -, IRQ-A: WSS+MPU+OPL3 */
-	opl3sa2_write(hw_config->io_base, OPL3SA2_IRQ_CONFIG, 0x0d);
-
-	/* Initialize DMA configuration */
-	if(hw_config->dma2 == hw_config->dma) {
-		/* Want DMA configuration DMA-B: -, DMA-A: WSS-P+WSS-R */
-		opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x03);
-	}
-	else {
-		/* Want DMA configuration DMA-B: WSS-R, DMA-A: WSS-P */
-		opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x21);
-	}
-}
-
-
-static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card)
-{
-	struct mixer_operations* mixer_operations;
-	opl3sa2_state_t* devc = &opl3sa2_state[card];
-
-	/* Install master mixer */
-	if (devc->chipset == CHIPSET_OPL3SA3) {
-		mixer_operations = &opl3sa3_mixer_operations;
-	}
-	else {
-		mixer_operations = &opl3sa2_mixer_operations;
-	}
-
-	devc->cfg_port = hw_config->io_base;
-	devc->mixer = sound_install_mixer(MIXER_DRIVER_VERSION,
-					  mixer_operations->name,
-					  mixer_operations,
-					  sizeof(struct mixer_operations),
-					  devc);
-	if(devc->mixer < 0) {
-		printk(KERN_ERR PFX "Could not install %s master mixer\n",
-			 mixer_operations->name);
-	}
-	else {
-			opl3sa2_mixer_reset(devc);
-
-	}
-}
-
-
-static void opl3sa2_clear_slots(struct address_info* hw_config)
-{
-	int i;
-
-	for(i = 0; i < 6; i++) {
-		hw_config->slots[i] = -1;
-	}
-}
-
-
-static void __init opl3sa2_set_ymode(struct address_info* hw_config, int ymode)
-{
-	/*
-	 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
-	 * it's supported.
-	 *
-	 * 0: Desktop (aka normal)   5-12 cm speakers
-	 * 1: Notebook PC mode 1     3 cm speakers
-	 * 2: Notebook PC mode 2     1.5 cm speakers
-	 * 3: Hi-fi                  16-38 cm speakers
-	 */
-	if(ymode >= 0 && ymode <= 3) {
-		unsigned char sys_ctrl;
-
-		opl3sa2_read(hw_config->io_base, OPL3SA2_SYS_CTRL, &sys_ctrl);
-		sys_ctrl = (sys_ctrl & 0xcf) | ((ymode & 3) << 4);
-		opl3sa2_write(hw_config->io_base, OPL3SA2_SYS_CTRL, sys_ctrl);
-	}
-	else {
-		printk(KERN_ERR PFX "not setting ymode, it must be one of 0,1,2,3\n");
-	}
-}
-
-
-static void __init opl3sa2_set_loopback(struct address_info* hw_config, int loopback)
-{
-	if(loopback >= 0 && loopback <= 1) {
-		unsigned char misc;
-
-		opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc);
-		misc = (misc & 0xef) | ((loopback & 1) << 4);
-		opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc);
-	}
-	else {
-		printk(KERN_ERR PFX "not setting loopback, it must be either 0 or 1\n");
-	}
-}
-
-
-static void __exit unload_opl3sa2(struct address_info* hw_config, int card)
-{
-        /* Release control ports */
-	release_region(hw_config->io_base, 2);
-
-	/* Unload mixer */
-	if(opl3sa2_state[card].mixer >= 0)
-		sound_unload_mixerdev(opl3sa2_state[card].mixer);
-
-}
-
-#ifdef CONFIG_PNP
-static struct pnp_device_id pnp_opl3sa2_list[] = {
-	{.id = "YMH0021", .driver_data = 0},
-	{.id = ""}
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_opl3sa2_list);
-
-static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
-	int card = opl3sa2_cards_num;
-
-	/* we don't actually want to return an error as the user may have specified
-	 * no multiple card search
-	 */
-
-	if (opl3sa2_cards_num == OPL3SA2_CARDS_MAX)
-		return 0;
-	opl3sa2_activated[card] = 1;
-
-	/* Our own config: */
-	opl3sa2_state[card].cfg.io_base = pnp_port_start(dev, 4);
-	opl3sa2_state[card].cfg.irq     = pnp_irq(dev, 0);
-	opl3sa2_state[card].cfg.dma     = pnp_dma(dev, 0);
-	opl3sa2_state[card].cfg.dma2    = pnp_dma(dev, 1);
-
-	/* The MSS config: */
-	opl3sa2_state[card].cfg_mss.io_base      = pnp_port_start(dev, 1);
-	opl3sa2_state[card].cfg_mss.irq          = pnp_irq(dev, 0);
-	opl3sa2_state[card].cfg_mss.dma          = pnp_dma(dev, 0);
-	opl3sa2_state[card].cfg_mss.dma2         = pnp_dma(dev, 1);
-	opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */
-
-	opl3sa2_state[card].cfg_mpu.io_base       = pnp_port_start(dev, 3);
-	opl3sa2_state[card].cfg_mpu.irq           = pnp_irq(dev, 0);
-	opl3sa2_state[card].cfg_mpu.dma           = -1;
-	opl3sa2_state[card].cfg_mpu.dma2          = -1;
-	opl3sa2_state[card].cfg_mpu.always_detect = 1; /* It's there, so use shared IRQs */
-
-	/* Call me paranoid: */
-	opl3sa2_clear_slots(&opl3sa2_state[card].cfg);
-	opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss);
-	opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
-
-	opl3sa2_state[card].pdev = dev;
-	opl3sa2_cards_num++;
-
-	return 0;
-}
-
-static struct pnp_driver opl3sa2_driver = {
-	.name		= "opl3sa2",
-	.id_table	= pnp_opl3sa2_list,
-	.probe		= opl3sa2_pnp_probe,
-};
-
-#endif /* CONFIG_PNP */
-
-/* End of component functions */
-
-/*
- * Install OPL3-SA2 based card(s).
- *
- * Need to have ad1848 and mpu401 loaded ready.
- */
-static int __init init_opl3sa2(void)
-{
-	int card, max;
-
-	/* Sanitize isapnp and multiple settings */
-	isapnp = isapnp != 0 ? 1 : 0;
-	multiple = multiple != 0 ? 1 : 0;
-
-	max = (multiple && isapnp) ? OPL3SA2_CARDS_MAX : 1;
-
-#ifdef CONFIG_PNP
-	if (isapnp){
-		pnp_register_driver(&opl3sa2_driver);
-		if(!opl3sa2_cards_num){
-			printk(KERN_INFO PFX "No PnP cards found\n");
-			isapnp = 0;
-		}
-		max = opl3sa2_cards_num;
-	}
-#endif
-
-	for (card = 0; card < max; card++) {
-		/* If a user wants an I/O then assume they meant it */
-		struct resource *ports;
-		int base;
-		
-		if (!isapnp) {
-			if (io == -1 || irq == -1 || dma == -1 ||
-			    dma2 == -1 || mss_io == -1) {
-				printk(KERN_ERR
-				       PFX "io, mss_io, irq, dma, and dma2 must be set\n");
-				return -EINVAL;
-			}
-			opl3sa2_cards_num++;
-
-			/*
-			 * Our own config:
-			 * (NOTE: IRQ and DMA aren't used, so they're set to
-			 *  give pretty output from conf_printf. :)
-			 */
-			opl3sa2_state[card].cfg.io_base = io;
-			opl3sa2_state[card].cfg.irq     = irq;
-			opl3sa2_state[card].cfg.dma     = dma;
-			opl3sa2_state[card].cfg.dma2    = dma2;
-	
-			/* The MSS config: */
-			opl3sa2_state[card].cfg_mss.io_base      = mss_io;
-			opl3sa2_state[card].cfg_mss.irq          = irq;
-			opl3sa2_state[card].cfg_mss.dma          = dma;
-			opl3sa2_state[card].cfg_mss.dma2         = dma2;
-			opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */
-
-			opl3sa2_state[card].cfg_mpu.io_base       = mpu_io;
-			opl3sa2_state[card].cfg_mpu.irq           = irq;
-			opl3sa2_state[card].cfg_mpu.dma           = -1;
-			opl3sa2_state[card].cfg_mpu.always_detect = 1; /* Use shared IRQs */
-
-			/* Call me paranoid: */
-			opl3sa2_clear_slots(&opl3sa2_state[card].cfg);
-			opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss);
-			opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
-		}
-
-		/* FIXME: leak */
-		if (probe_opl3sa2(&opl3sa2_state[card].cfg, card))
-			return -ENODEV;
-
-		base = opl3sa2_state[card].cfg_mss.io_base;
-
-		if (!request_region(base, 4, "WSS config"))
-			goto failed;
-
-		ports = request_region(base + 4, 4, "ad1848");
-		if (!ports)
-			goto failed2;
-
-		if (!probe_ms_sound(&opl3sa2_state[card].cfg_mss, ports)) {
-			/*
-			 * If one or more cards are already registered, don't
-			 * return an error but print a warning.  Note, this
-			 * should never really happen unless the hardware or
-			 * ISA PnP screwed up.
-			 */
-			release_region(base + 4, 4);
-		failed2:
-			release_region(base, 4);
-		failed:
-			release_region(opl3sa2_state[card].cfg.io_base, 2);
-
-			if (opl3sa2_cards_num) {
-				printk(KERN_WARNING
-				       PFX "There was a problem probing one "
-				       " of the ISA PNP cards, continuing\n");
-				opl3sa2_cards_num--;
-				continue;
-			} else
-				return -ENODEV;
-		}
-
-		attach_opl3sa2(&opl3sa2_state[card].cfg, card);
-		conf_printf(opl3sa2_state[card].chipset_name, &opl3sa2_state[card].cfg);
-		attach_opl3sa2_mixer(&opl3sa2_state[card].cfg, card);
-		attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss, ports);
-
-		/* ewww =) */
-		opl3sa2_state[card].card = card;
-
-		/*
-		 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
-		 * it's supported.
-		 */
-		if (ymode != -1) {
-			if (opl3sa2_state[card].chipset == CHIPSET_OPL3SA2) {
-				printk(KERN_ERR
-				       PFX "ymode not supported on OPL3-SA2\n");
-			}
-			else {
-				opl3sa2_set_ymode(&opl3sa2_state[card].cfg, ymode);
-			}
-		}
-
-
-		/* Set A/D input to Mono loopback if asked to. */
-		if (loopback != -1) {
-			opl3sa2_set_loopback(&opl3sa2_state[card].cfg, loopback);
-		}
-		
-		/* Attach MPU if we've been asked to do so, failure isn't fatal */
-		if (opl3sa2_state[card].cfg_mpu.io_base != -1) {
-			int base = opl3sa2_state[card].cfg_mpu.io_base;
-			struct resource *ports;
-			ports = request_region(base, 2, "mpu401");
-			if (!ports)
-				goto out;
-			if (!probe_mpu401(&opl3sa2_state[card].cfg_mpu, ports)) {
-				release_region(base, 2);
-				goto out;
-			}
-			if (attach_mpu401(&opl3sa2_state[card].cfg_mpu, THIS_MODULE)) {
-				printk(KERN_ERR PFX "failed to attach MPU401\n");
-				opl3sa2_state[card].cfg_mpu.slots[1] = -1;
-			}
-		}
-	}
-
-out:
-	if (isapnp) {
-		printk(KERN_NOTICE PFX "%d PnP card(s) found.\n", opl3sa2_cards_num);
-	}
-
-	return 0;
-}
-
-
-/*
- * Uninstall OPL3-SA2 based card(s).
- */
-static void __exit cleanup_opl3sa2(void)
-{
-	int card;
-
-	for(card = 0; card < opl3sa2_cards_num; card++) {
-	        if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
-			unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu);
- 		}
-		unload_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
-		unload_opl3sa2(&opl3sa2_state[card].cfg, card);
-#ifdef CONFIG_PNP
-		pnp_unregister_driver(&opl3sa2_driver);
-#endif
-	}
-}
-
-module_init(init_opl3sa2);
-module_exit(cleanup_opl3sa2);
-
-#ifndef MODULE
-static int __init setup_opl3sa2(char *str)
-{
-	/* io, irq, dma, dma2,... */
-#ifdef CONFIG_PNP
-	int ints[11];
-#else
-	int ints[9];
-#endif
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io       = ints[1];
-	irq      = ints[2];
-	dma      = ints[3];
-	dma2     = ints[4];
-	mss_io   = ints[5];
-	mpu_io   = ints[6];
-	ymode    = ints[7];
-	loopback = ints[8];
-#ifdef CONFIG_PNP
-	isapnp   = ints[9];
-	multiple = ints[10];
-#endif
-	return 1;
-}
-
-__setup("opl3sa2=", setup_opl3sa2);
-#endif
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c
index 27acd6f..7de18b5 100644
--- a/sound/oss/sb_card.c
+++ b/sound/oss/sb_card.c
@@ -290,7 +290,7 @@
 MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table);
 #endif /* CONFIG_PNP */
 
-static void __init_or_module sb_unregister_all(void)
+static void sb_unregister_all(void)
 {
 #ifdef CONFIG_PNP
 	if (pnp_registered)
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 3bc1f6e..96adc47 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -11,12 +11,12 @@
  *  Built from:
  *	Low level code: <audio@tridentmicro.com> from ALSA
  *	Framework: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *	Extended by: Zach Brown <zab@redhat.com>  
+ *	Extended by: Zach Brown <zab@redhat.com>
  *
  *  Hacked up by:
  *	Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
  *	Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support
- *	Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support 
+ *	Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support
  *	Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support
  *	Peter Wächtler <pwaechtler@loewe-komp.de> CyberPro5050 support
  *      Muli Ben-Yehuda <mulix@mulix.org>
@@ -54,33 +54,33 @@
  *	adapt to new pci joystick attachment interface
  *  v0.14.10f
  *      July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      patch from Eric Lemar (via Ian Soboroff): in suspend and resume, 
- *      fix wrong cast from pci_dev* to struct trident_card*. 
+ *      patch from Eric Lemar (via Ian Soboroff): in suspend and resume,
+ *      fix wrong cast from pci_dev* to struct trident_card*.
  *  v0.14.10e
  *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      rewrite the DMA buffer allocation/deallcoation functions, to make it 
- *      modular and fix a bug where we would call free_pages on memory 
- *      obtained with pci_alloc_consistent. Also remove unnecessary #ifdef 
+ *      rewrite the DMA buffer allocation/deallcoation functions, to make it
+ *      modular and fix a bug where we would call free_pages on memory
+ *      obtained with pci_alloc_consistent. Also remove unnecessary #ifdef
  *      CONFIG_PROC_FS and various other cleanups.
  *  v0.14.10d
  *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
  *      made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming
- *      my syslog with hundreds of messages. 
+ *      my syslog with hundreds of messages.
  *  v0.14.10c
  *      July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
  *      Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle
- *      and the coding style used in the rest of the file. 
+ *      and the coding style used in the rest of the file.
  *  v0.14.10b
  *      June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- *      add a missing unlock_set_fmt, remove a superflous lock/unlock pair 
- *      with nothing in between. 
+ *      add a missing unlock_set_fmt, remove a superflous lock/unlock pair
+ *      with nothing in between.
  *  v0.14.10a
- *      June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il> 
- *      use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns 
- *      per line, use 'do {} while (0)' in statement macros. 
+ *      June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ *      use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns
+ *      per line, use 'do {} while (0)' in statement macros.
  *  v0.14.10
  *      June 6 2002 Lei Hu <Lei_hu@ali.com.tw>
- *      rewrite the part to read/write registers of audio codec for Ali5451 
+ *      rewrite the part to read/write registers of audio codec for Ali5451
  *  v0.14.9e
  *      January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport
  *      support to avoid resource conflict with pcigame.c
@@ -111,7 +111,7 @@
  *	Set EBUF1 and EBUF2 to still mode
  *	Add dc97/ac97 reset function
  *	Fix power management: ali_restore_regs
- *  unreleased 
+ *  unreleased
  *	Mar 09 2001 Matt Wu
  *	Add cache for ac97 access
  *  v0.14.7
@@ -120,7 +120,7 @@
  *	Fix bug: an extra tail will be played when playing
  *	Jan 05 2001 Matt Wu
  *	Implement multi-channels and S/PDIF in support for ALi 1535+
- *  v0.14.6 
+ *  v0.14.6
  *	Nov 1 2000 Ching-Ling Lee
  *	Fix the bug of memory leak when switching 5.1-channels to 2 channels.
  *	Add lock protection into dynamic changing format of data.
@@ -138,7 +138,7 @@
  *  v0.14.3 May 10 2000 Ollie Lho
  *	fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU
  *  v0.14.2 Mar 29 2000 Ching-Ling Lee
- *	Add clear to silence advance in trident_update_ptr 
+ *	Add clear to silence advance in trident_update_ptr
  *	fix invalid data of the end of the sound
  *  v0.14.1 Mar 24 2000 Ching-Ling Lee
  *	ALi 5451 support added, playback and recording O.K.
@@ -178,7 +178,7 @@
  *	SiS 7018 support added, playback O.K.
  *  v0.01 Alan Cox et. al.
  *	Initial Release in kernel 2.3.30, does not work
- * 
+ *
  *  ToDo
  *	Clean up of low level channel register access code. (done)
  *	Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done)
@@ -326,7 +326,7 @@
 
 		unsigned error;	/* number of over/underruns */
                 /* put process on wait queue when no more space in buffer */
-		wait_queue_head_t wait;	
+		wait_queue_head_t wait;
 
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
@@ -358,7 +358,7 @@
 struct trident_channel {
 	int num; /* channel number */
 	u32 lba; /* Loop Begine Address, where dma buffer starts */
-	u32 eso; /* End Sample Offset, wehre dma buffer ends */ 
+	u32 eso; /* End Sample Offset, wehre dma buffer ends */
 	         /* (in the unit of samples) */
 	u32 delta; /* delta value, sample rate / 48k for playback, */
 	           /* 48k/sample rate for recording */
@@ -417,7 +417,7 @@
 	/* soundcore stuff */
 	int dev_audio;
 
-	/* structures for abstraction of hardware facilities, codecs, */ 
+	/* structures for abstraction of hardware facilities, codecs, */
 	/* banks and channels */
 	struct ac97_codec *ac97_codec[NR_AC97];
 	struct trident_pcm_bank banks[NR_BANKS];
@@ -479,7 +479,7 @@
 static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg);
 
 static int trident_open_mixdev(struct inode *inode, struct file *file);
-static int trident_ioctl_mixdev(struct inode *inode, struct file *file, 
+static int trident_ioctl_mixdev(struct inode *inode, struct file *file,
 				unsigned int cmd, unsigned long arg);
 
 static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val);
@@ -496,10 +496,10 @@
 static void ali_disable_special_channel(struct trident_card *card, int ch);
 static void ali_setup_spdif_out(struct trident_card *card, int flag);
 static int ali_write_5_1(struct trident_state *state,
-			 const char __user *buffer, 
-			 int cnt_for_multi_channel, unsigned int *copy_count, 
+			 const char __user *buffer,
+			 int cnt_for_multi_channel, unsigned int *copy_count,
 			 unsigned int *state_cnt);
-static int ali_allocate_other_states_resources(struct trident_state *state, 
+static int ali_allocate_other_states_resources(struct trident_state *state,
 					       int chan_nums);
 static void ali_free_other_states_resources(struct trident_state *state);
 
@@ -722,7 +722,7 @@
 	if (channel < 31 || channel > 63)
 		return;
 
-	if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX || 
+	if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX ||
 	    card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) {
 		b = inb(TRID_REG(card, T4D_REC_CH));
 		if ((b & ~0x80) == channel)
@@ -742,7 +742,7 @@
 	int idx;
 
 	/* The cyberpro 5050 has only 32 voices and one bank */
-	/* .. at least they are not documented (if you want to call that 
+	/* .. at least they are not documented (if you want to call that
 	 * crap documentation), perhaps broken ? */
 
 	bank = &card->banks[BANK_A];
@@ -802,7 +802,7 @@
 	/* enable, if it was disabled */
 	if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) {
 		printk(KERN_INFO "cyberpro5050: enabling audio controller\n");
-		cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE, 
+		cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE,
 			     portDat | CYBER_BMSK_AUENZ_ENABLE);
 		/* check again if hardware is enabled now */
 		portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);
@@ -811,7 +811,7 @@
 		printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n");
 		ret = -1;
 	} else {
-		cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE, 
+		cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE,
 			     CYBER_BMSK_AUDIO_INT_ENABLE);
 		cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x01);
 		cyber_outidx(CYBER_PORT_AUDIO, 0xba, 0x20);
@@ -827,7 +827,7 @@
 /*  called with spin lock held */
 
 static int
-trident_load_channel_registers(struct trident_card *card, u32 * data, 
+trident_load_channel_registers(struct trident_card *card, u32 * data,
 			       unsigned int channel)
 {
 	int i;
@@ -845,7 +845,7 @@
 			continue;
 		outl(data[i], TRID_REG(card, CHANNEL_START + 4 * i));
 	}
-	if (card->pci_id == PCI_DEVICE_ID_ALI_5451 || 
+	if (card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
 	    card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
 		outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1));
 		outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2));
@@ -884,7 +884,7 @@
 		break;
 	case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
 		data[0] = (channel->delta << 24);
-		data[2] = ((channel->delta << 16) & 0xff000000) | 
+		data[2] = ((channel->delta << 16) & 0xff000000) |
 			(channel->eso & 0x00ffffff);
 		data[3] = channel->fm_vol & 0xffff;
 		break;
@@ -989,13 +989,13 @@
 	if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
 		channel->attribute = 0;
 		if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-			if ((channel->num == ALI_SPDIF_IN_CHANNEL) || 
+			if ((channel->num == ALI_SPDIF_IN_CHANNEL) ||
 			    (channel->num == ALI_PCM_IN_CHANNEL))
 				ali_disable_special_channel(state->card, channel->num);
-			else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL)) 
+			else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL))
 				  & ALI_SPDIF_OUT_CH_ENABLE)
 				 && (channel->num == ALI_SPDIF_OUT_CHANNEL)) {
-				ali_set_spdif_out_rate(state->card, 
+				ali_set_spdif_out_rate(state->card,
 						       state->dmabuf.rate);
 				state->dmabuf.channel->delta = 0x1000;
 			}
@@ -1063,7 +1063,7 @@
 
 	channel->lba = dmabuf->dma_handle;
 	channel->delta = compute_rate_rec(dmabuf->rate);
-	if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) && 
+	if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) &&
 	    (channel->num == ALI_SPDIF_IN_CHANNEL)) {
 		rate = ali_get_spdif_in_rate(card);
 		if (rate == 0) {
@@ -1180,8 +1180,8 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&card->lock, flags);
-	if ((dmabuf->mapped || 
-	     dmabuf->count < (signed) dmabuf->dmasize) && 
+	if ((dmabuf->mapped ||
+	     dmabuf->count < (signed) dmabuf->dmasize) &&
 	    dmabuf->ready) {
 		dmabuf->enable |= ADC_RUNNING;
 		trident_enable_voice_irq(card, chan_num);
@@ -1261,7 +1261,7 @@
 	void *rawbuf = NULL;
 	struct page *page, *pend;
 
-	if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order, 
+	if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
 					    &dmabuf->dma_handle)))
 		return -ENOMEM;
 
@@ -1272,7 +1272,7 @@
 	dmabuf->rawbuf = rawbuf;
 	dmabuf->buforder = order;
 
-	/* now mark the pages as reserved; otherwise */ 
+	/* now mark the pages as reserved; otherwise */
 	/* remap_pfn_range doesn't do what we want */
 	pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
 	for (page = virt_to_page(rawbuf); page <= pend; page++)
@@ -1310,7 +1310,7 @@
 		pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
 		for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
 			ClearPageReserved(page);
-		pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder, 
+		pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder,
 				    dmabuf->rawbuf, dmabuf->dma_handle);
 		dmabuf->rawbuf = NULL;
 	}
@@ -1368,7 +1368,7 @@
 					dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
 					/* release the auxiliary DMA buffers */
 					for (i -= 2; i >= 0; i--)
-						dealloc_dmabuf(&state->other_states[i]->dmabuf, 
+						dealloc_dmabuf(&state->other_states[i]->dmabuf,
 							       state->card->pci_dev);
 					unlock_set_fmt(state);
 					return ret;
@@ -1398,7 +1398,7 @@
 		dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt];
 		dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
 
-		memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80, 
+		memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80,
 		       dmabuf->dmasize);
 
 		spin_lock_irqsave(&s->card->lock, flags);
@@ -1453,7 +1453,7 @@
 	swptr = dmabuf->swptr;
 	spin_unlock_irqrestore(&state->card->lock, flags);
 
-	if (swptr == 0 || swptr == dmabuf->dmasize / 2 || 
+	if (swptr == 0 || swptr == dmabuf->dmasize / 2 ||
 	    swptr == dmabuf->dmasize)
 		return;
 
@@ -1511,7 +1511,7 @@
 
 		/* No matter how much data is left in the buffer, we have to wait until
 		   CSO == ESO/2 or CSO == ESO when address engine interrupts */
-		if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 || 
+		if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
 		    state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
 			diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize;
 			diff = diff % (dmabuf->dmasize);
@@ -1532,7 +1532,7 @@
 	return 0;
 }
 
-/* update buffer manangement pointers, especially, */ 
+/* update buffer manangement pointers, especially, */
 /* dmabuf->count and dmabuf->hwptr */
 static void
 trident_update_ptr(struct trident_state *state)
@@ -1559,11 +1559,11 @@
 		} else {
 			dmabuf->count += diff;
 
-			if (dmabuf->count < 0 || 
+			if (dmabuf->count < 0 ||
 			    dmabuf->count > dmabuf->dmasize) {
-				/* buffer underrun or buffer overrun, */ 
-				/* we have no way to recover it here, just */ 
-				/* stop the machine and let the process */ 
+				/* buffer underrun or buffer overrun, */
+				/* we have no way to recover it here, just */
+				/* stop the machine and let the process */
 				/* force hwptr and swptr to sync */
 				__stop_adc(state);
 				dmabuf->error++;
@@ -1582,7 +1582,7 @@
 		} else {
 			dmabuf->count -= diff;
 
-			if (dmabuf->count < 0 || 
+			if (dmabuf->count < 0 ||
 			    dmabuf->count > dmabuf->dmasize) {
 				/* buffer underrun or buffer overrun, we have no way to recover
 				   it here, just stop the machine and let the process force hwptr
@@ -1608,13 +1608,13 @@
 						if (state->chans_num == 6) {
 							clear_cnt = clear_cnt / 2;
 							swptr = swptr / 2;
-							memset(state->other_states[0]->dmabuf.rawbuf + swptr, 
+							memset(state->other_states[0]->dmabuf.rawbuf + swptr,
 							       silence, clear_cnt);
-							memset(state->other_states[1]->dmabuf.rawbuf + swptr, 
+							memset(state->other_states[1]->dmabuf.rawbuf + swptr,
 							       silence, clear_cnt);
-							memset(state->other_states[2]->dmabuf.rawbuf + swptr, 
+							memset(state->other_states[2]->dmabuf.rawbuf + swptr,
 							       silence, clear_cnt);
-							memset(state->other_states[3]->dmabuf.rawbuf + swptr, 
+							memset(state->other_states[3]->dmabuf.rawbuf + swptr,
 							       silence, clear_cnt);
 						}
 						dmabuf->endcleared = 1;
@@ -1627,13 +1627,13 @@
 					if (state->chans_num == 6) {
 						clear_cnt = clear_cnt / 2;
 						swptr = swptr / 2;
-						memset(state->other_states[0]->dmabuf.rawbuf + swptr, 
+						memset(state->other_states[0]->dmabuf.rawbuf + swptr,
 						       silence, clear_cnt);
-						memset(state->other_states[1]->dmabuf.rawbuf + swptr, 
+						memset(state->other_states[1]->dmabuf.rawbuf + swptr,
 						       silence, clear_cnt);
-						memset(state->other_states[2]->dmabuf.rawbuf + swptr, 
+						memset(state->other_states[2]->dmabuf.rawbuf + swptr,
 						       silence, clear_cnt);
-						memset(state->other_states[3]->dmabuf.rawbuf + swptr, 
+						memset(state->other_states[3]->dmabuf.rawbuf + swptr,
 						       silence, clear_cnt);
 					}
 					dmabuf->endcleared = 1;
@@ -1665,7 +1665,7 @@
 			if ((state = card->states[i]) != NULL) {
 				trident_update_ptr(state);
 			} else {
-				printk(KERN_WARNING "trident: spurious channel " 
+				printk(KERN_WARNING "trident: spurious channel "
 				       "irq %d.\n", channel);
 				trident_stop_voice(card, channel);
 				trident_disable_voice_irq(card, channel);
@@ -1694,7 +1694,7 @@
 
 	if (opt == 1) {		// MUTE
 		dwTemp ^= 0x8000;
-		ali_ac97_write(card->ac97_codec[0], 
+		ali_ac97_write(card->ac97_codec[0],
 			       0x02, dwTemp);
 	} else if (opt == 2) {	// Down
 		if (mute)
@@ -1706,7 +1706,7 @@
 		dwTemp &= 0xe0e0;
 		dwTemp |= (volume[0]) | (volume[1] << 8);
 		ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
-		card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | 
+		card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
 			(((32 - volume[1]) * 25 / 8) << 8);
 	} else if (opt == 4) {	// Up
 		if (mute)
@@ -1718,7 +1718,7 @@
 		dwTemp &= 0xe0e0;
 		dwTemp |= (volume[0]) | (volume[1] << 8);
 		ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
-		card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | 
+		card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
 			(((32 - volume[1]) * 25 / 8) << 8);
 	} else {
 		/* Nothing needs doing */
@@ -1801,7 +1801,7 @@
 			if ((state = card->states[i]) != NULL) {
 				trident_update_ptr(state);
 			} else {
-				printk(KERN_WARNING "cyber5050: spurious " 
+				printk(KERN_WARNING "cyber5050: spurious "
 				       "channel irq %d.\n", channel);
 				trident_stop_voice(card, channel);
 				trident_disable_voice_irq(card, channel);
@@ -1836,21 +1836,21 @@
 				ali_queue_task(card, gpio & 0x07);
 		}
 		event = inl(TRID_REG(card, T4D_MISCINT));
-		outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), 
+		outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
 		     TRID_REG(card, T4D_MISCINT));
 		spin_unlock(&card->lock);
 		return IRQ_HANDLED;
 	}
 
 	/* manually clear interrupt status, bad hardware design, blame T^2 */
-	outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), 
+	outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
 	     TRID_REG(card, T4D_MISCINT));
 	spin_unlock(&card->lock);
 	return IRQ_HANDLED;
 }
 
-/* in this loop, dmabuf.count signifies the amount of data that is waiting */ 
-/* to be copied to the user's buffer.  it is filled by the dma machine and */ 
+/* in this loop, dmabuf.count signifies the amount of data that is waiting */
+/* to be copied to the user's buffer.  it is filled by the dma machine and */
 /* drained by this loop. */
 static ssize_t
 trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
@@ -1878,8 +1878,8 @@
 	while (count > 0) {
 		spin_lock_irqsave(&state->card->lock, flags);
 		if (dmabuf->count > (signed) dmabuf->dmasize) {
-			/* buffer overrun, we are recovering from */ 
-			/* sleep_on_timeout, resync hwptr and swptr, */ 
+			/* buffer overrun, we are recovering from */
+			/* sleep_on_timeout, resync hwptr and swptr, */
 			/* make process flush the buffer */
 			dmabuf->count = dmabuf->dmasize;
 			dmabuf->swptr = dmabuf->hwptr;
@@ -1894,7 +1894,7 @@
 			cnt = count;
 		if (cnt <= 0) {
 			unsigned long tmo;
-			/* buffer is empty, start the dma machine and */ 
+			/* buffer is empty, start the dma machine and */
 			/* wait for data to be recorded */
 			start_adc(state);
 			if (file->f_flags & O_NONBLOCK) {
@@ -1904,8 +1904,8 @@
 			}
 
 			mutex_unlock(&state->sem);
-			/* No matter how much space left in the buffer, */ 
-			/* we have to wait until CSO == ESO/2 or CSO == ESO */ 
+			/* No matter how much space left in the buffer, */
+			/* we have to wait until CSO == ESO/2 or CSO == ESO */
 			/* when address engine interrupts */
 			tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
 			tmo >>= sample_shift[dmabuf->fmt];
@@ -2005,7 +2005,7 @@
 	while (count > 0) {
 		spin_lock_irqsave(&state->card->lock, flags);
 		if (dmabuf->count < 0) {
-			/* buffer underrun, we are recovering from */ 
+			/* buffer underrun, we are recovering from */
 			/* sleep_on_timeout, resync hwptr and swptr */
 			dmabuf->count = 0;
 			dmabuf->swptr = dmabuf->hwptr;
@@ -2020,7 +2020,7 @@
 			cnt = count;
 		if (cnt <= 0) {
 			unsigned long tmo;
-			/* buffer is full, start the dma machine and */ 
+			/* buffer is full, start the dma machine and */
 			/* wait for data to be played */
 			start_dac(state);
 			if (file->f_flags & O_NONBLOCK) {
@@ -2028,8 +2028,8 @@
 					ret = -EAGAIN;
 				goto out;
 			}
-			/* No matter how much data left in the buffer, */ 
-			/* we have to wait until CSO == ESO/2 or CSO == ESO */ 
+			/* No matter how much data left in the buffer, */
+			/* we have to wait until CSO == ESO/2 or CSO == ESO */
 			/* when address engine interrupts */
 			lock_set_fmt(state);
 			tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
@@ -2037,15 +2037,15 @@
 			unlock_set_fmt(state);
 			mutex_unlock(&state->sem);
 
-			/* There are two situations when sleep_on_timeout */ 
-			/* returns, one is when the interrupt is serviced */ 
-			/* correctly and the process is waked up by ISR */ 
-			/* ON TIME. Another is when timeout is expired, which */ 
-			/* means that either interrupt is NOT serviced */ 
-			/* correctly (pending interrupt) or it is TOO LATE */ 
-			/* for the process to be scheduled to run */ 
-			/* (scheduler latency) which results in a (potential) */ 
-			/* buffer underrun. And worse, there is NOTHING we */ 
+			/* There are two situations when sleep_on_timeout */
+			/* returns, one is when the interrupt is serviced */
+			/* correctly and the process is waked up by ISR */
+			/* ON TIME. Another is when timeout is expired, which */
+			/* means that either interrupt is NOT serviced */
+			/* correctly (pending interrupt) or it is TOO LATE */
+			/* for the process to be scheduled to run */
+			/* (scheduler latency) which results in a (potential) */
+			/* buffer underrun. And worse, there is NOTHING we */
 			/* can do to prevent it. */
 			if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
 				pr_debug(KERN_ERR "trident: playback schedule "
@@ -2054,8 +2054,8 @@
 					 dmabuf->fragsize, dmabuf->count,
 					 dmabuf->hwptr, dmabuf->swptr);
 
-				/* a buffer underrun, we delay the recovery */ 
-				/* until next time the while loop begin and */ 
+				/* a buffer underrun, we delay the recovery */
+				/* until next time the while loop begin and */
 				/* we REALLY have data to play */
 			}
 			if (signal_pending(current)) {
@@ -2079,7 +2079,7 @@
 		if (state->chans_num == 6) {
 			copy_count = 0;
 			state_cnt = 0;
-			if (ali_write_5_1(state, buffer, cnt, &copy_count, 
+			if (ali_write_5_1(state, buffer, cnt, &copy_count,
 					  &state_cnt) == -EFAULT) {
 				if (state_cnt) {
 					swptr = (swptr + state_cnt) % dmabuf->dmasize;
@@ -2096,7 +2096,7 @@
 				goto out;
 			}
 		} else {
-			if (copy_from_user(dmabuf->rawbuf + swptr, 
+			if (copy_from_user(dmabuf->rawbuf + swptr,
 					   buffer, cnt)) {
 				if (!ret)
 					ret = -EFAULT;
@@ -2172,7 +2172,7 @@
 			if (dmabuf->count >= (signed) dmabuf->fragsize)
 				mask |= POLLOUT | POLLWRNORM;
 		} else {
-			if ((signed) dmabuf->dmasize >= dmabuf->count + 
+			if ((signed) dmabuf->dmasize >= dmabuf->count +
 			    (signed) dmabuf->fragsize)
 				mask |= POLLOUT | POLLWRNORM;
 		}
@@ -2227,7 +2227,7 @@
 }
 
 static int
-trident_ioctl(struct inode *inode, struct file *file, 
+trident_ioctl(struct inode *inode, struct file *file,
 	      unsigned int cmd, unsigned long arg)
 {
 	struct trident_state *state = (struct trident_state *)file->private_data;
@@ -2348,7 +2348,7 @@
 
 
 	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */
-		ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | 
+		ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
 			       AFMT_U8, p);
 		break;
 
@@ -2379,7 +2379,7 @@
 			}
 		}
 		unlock_set_fmt(state);
-		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : 
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
 			       AFMT_U8, p);
 		break;
 
@@ -2438,7 +2438,7 @@
 				stop_adc(state);
 				dmabuf->ready = 0;
 				if (val >= 2) {
-					if (!((file->f_mode & FMODE_WRITE) && 
+					if (!((file->f_mode & FMODE_WRITE) &&
 					      (val == 6)))
 						val = 2;
 					dmabuf->fmt |= TRIDENT_FMT_STEREO;
@@ -2504,7 +2504,7 @@
 		abinfo.fragstotal = dmabuf->numfrag;
 		abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? 
+		ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
 			-EFAULT : 0;
 		break;
 
@@ -2524,7 +2524,7 @@
 		abinfo.fragstotal = dmabuf->numfrag;
 		abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? 
+		ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
 			-EFAULT : 0;
 		break;
 
@@ -2533,7 +2533,7 @@
 		break;
 
 	case SNDCTL_DSP_GETCAPS:
-		ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | 
+		ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
 			       DSP_CAP_MMAP | DSP_CAP_BIND, p);
 		break;
 
@@ -2553,7 +2553,7 @@
 		}
 		if (file->f_mode & FMODE_READ) {
 			if (val & PCM_ENABLE_INPUT) {
-				if (!dmabuf->ready && 
+				if (!dmabuf->ready &&
 				    (ret = prog_dmabuf_record(state)))
 					break;
 				start_adc(state);
@@ -2562,7 +2562,7 @@
 		}
 		if (file->f_mode & FMODE_WRITE) {
 			if (val & PCM_ENABLE_OUTPUT) {
-				if (!dmabuf->ready && 
+				if (!dmabuf->ready &&
 				    (ret = prog_dmabuf_playback(state)))
 					break;
 				start_dac(state);
@@ -2589,7 +2589,7 @@
 		if (dmabuf->mapped)
 			dmabuf->count &= dmabuf->fragsize - 1;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? 
+		ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
 			-EFAULT : 0;
 		break;
 
@@ -2612,7 +2612,7 @@
 		if (dmabuf->mapped)
 			dmabuf->count &= dmabuf->fragsize - 1;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? 
+		ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
 			-EFAULT : 0;
 		break;
 
@@ -2641,17 +2641,17 @@
 		break;
 
 	case SOUND_PCM_READ_CHANNELS:
-		ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1, 
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
 			       p);
 		break;
 
 	case SOUND_PCM_READ_BITS:
-		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : 
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
 			       AFMT_U8, p);
 		break;
 
 	case SNDCTL_DSP_GETCHANNELMASK:
-		ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR | 
+		ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR |
 			       DSP_BIND_CENTER_LFE,  p);
 		break;
 
@@ -2671,10 +2671,10 @@
 		} else {
 			dmabuf->ready = 0;
 			if (file->f_mode & FMODE_READ)
-				dmabuf->channel->attribute = (CHANNEL_REC | 
+				dmabuf->channel->attribute = (CHANNEL_REC |
 							      SRC_ENABLE);
 			if (file->f_mode & FMODE_WRITE)
-				dmabuf->channel->attribute = (CHANNEL_SPC_PB | 
+				dmabuf->channel->attribute = (CHANNEL_SPC_PB |
 							      SRC_ENABLE);
 			dmabuf->channel->attribute |= mask2attr[ffs(val)];
 		}
@@ -2702,6 +2702,7 @@
 	struct trident_card *card = devs;
 	struct trident_state *state = NULL;
 	struct dmabuf *dmabuf = NULL;
+	unsigned long flags;
 
 	/* Added by Matt Wu 01-05-2001 */
 	/* TODO: there's some redundacy here wrt the check below */
@@ -2765,8 +2766,8 @@
 	init_waitqueue_head(&dmabuf->wait);
 	file->private_data = state;
 
-	/* set default sample format. According to OSS Programmer's */ 
-	/* Guide  /dev/dsp should be default to unsigned 8-bits, mono, */ 
+	/* set default sample format. According to OSS Programmer's */
+	/* Guide  /dev/dsp should be default to unsigned 8-bits, mono, */
 	/* with sample rate 8kHz and /dev/dspW will accept 16-bits sample */
 	if (file->f_mode & FMODE_WRITE) {
 		dmabuf->fmt &= ~TRIDENT_FMT_MASK;
@@ -2779,11 +2780,13 @@
 			/* set default channel attribute to normal playback */
 			dmabuf->channel->attribute = CHANNEL_PB;
 		}
+		spin_lock_irqsave(&card->lock, flags);
 		trident_set_dac_rate(state, 8000);
+		spin_unlock_irqrestore(&card->lock, flags);
 	}
 
 	if (file->f_mode & FMODE_READ) {
-		/* FIXME: Trident 4d can only record in signed 16-bits stereo, */ 
+		/* FIXME: Trident 4d can only record in signed 16-bits stereo, */
 		/* 48kHz sample, to be dealed with in trident_set_adc_rate() ?? */
 		dmabuf->fmt &= ~TRIDENT_FMT_MASK;
 		if ((minor & 0x0f) == SND_DEV_DSP16)
@@ -2794,10 +2797,12 @@
 		if (card->pci_id == PCI_DEVICE_ID_SI_7018) {
 			/* set default channel attribute to 0x8a80, record from
 			   PCM L/R FIFO and mono = (left + right + 1)/2 */
-			dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR | 
+			dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR |
 						      MONO_MIX);
 		}
+		spin_lock_irqsave(&card->lock, flags);
 		trident_set_adc_rate(state, 8000);
+		spin_unlock_irqrestore(&card->lock, flags);
 
 		/* Added by Matt Wu 01-05-2001 */
 		if (card->pci_id == PCI_DEVICE_ID_ALI_5451)
@@ -3020,7 +3025,7 @@
 			break;
 		if (wsemabits == 0) {
 		      unlock:
-			outl(((u32) (wcontrol & 0x1eff) | 0x00004000), 
+			outl(((u32) (wcontrol & 0x1eff) | 0x00004000),
 			     TRID_REG(card, ALI_AC97_WRITE));
 			continue;
 		}
@@ -3104,7 +3109,7 @@
 	ncount = 10;
 
 	while (1) {
-		if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) 
+		if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ)
 		    != 0)
 			break;
 		if (ncount <= 0)
@@ -3112,7 +3117,7 @@
 		if (ncount-- == 1) {
 			pr_debug("ali_ac97_read :try clear busy flag\n");
 			aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE));
-			outl((aud_reg & 0xffff7fff), 
+			outl((aud_reg & 0xffff7fff),
 			     TRID_REG(card, ALI_AC97_WRITE));
 		}
 		udelay(10);
@@ -3159,7 +3164,7 @@
 
 	wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
 	wcontrol &= 0xff00;
-	wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */ 
+	wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */
 	                            /* ali1535+ write */
 	outl((data | wcontrol), TRID_REG(card, ALI_AC97_WRITE));
 
@@ -3177,7 +3182,7 @@
 			break;
 		if (ncount-- == 1) {
 			pr_debug("ali_ac97_set :try clear busy flag!!\n");
-			outw(wcontrol & 0x7fff, 
+			outw(wcontrol & 0x7fff,
 			     TRID_REG(card, ALI_AC97_WRITE));
 		}
 		udelay(10);
@@ -3382,7 +3387,7 @@
 	bval |= 0x1F;
 	outb(bval, TRID_REG(card, ALI_SPDIF_CTRL + 1));
 
-	while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) && 
+	while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) &&
 	       count <= 50000) {
 		count++;
 
@@ -3669,14 +3674,14 @@
 	spin_lock_irqsave(&card->lock, flags);
 
 	ali_registers.global_regs[0x2c] = inl(TRID_REG(card, T4D_MISCINT));
-	//ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));    
+	//ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));
 	ali_registers.global_regs[0x21] = inl(TRID_REG(card, T4D_STOP_A));
 
 	//disable all IRQ bits
 	outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT));
 
 	for (i = 1; i < ALI_MIXER_REGS; i++)
-		ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0], 
+		ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0],
 							    i * 2);
 
 	for (i = 0; i < ALI_GLOBAL_REGS; i++) {
@@ -3688,7 +3693,7 @@
 	for (i = 0; i < ALI_CHANNELS; i++) {
 		outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
 		for (j = 0; j < ALI_CHANNEL_REGS; j++)
-			ali_registers.channel_regs[i][j] = inl(TRID_REG(card, 
+			ali_registers.channel_regs[i][j] = inl(TRID_REG(card,
 									j * 4 + 0xe0));
 	}
 
@@ -3707,18 +3712,18 @@
 	spin_lock_irqsave(&card->lock, flags);
 
 	for (i = 1; i < ALI_MIXER_REGS; i++)
-		ali_ac97_write(card->ac97_codec[0], i * 2, 
+		ali_ac97_write(card->ac97_codec[0], i * 2,
 			       ali_registers.mixer_regs[i]);
 
 	for (i = 0; i < ALI_CHANNELS; i++) {
 		outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
 		for (j = 0; j < ALI_CHANNEL_REGS; j++)
-			outl(ali_registers.channel_regs[i][j], 
+			outl(ali_registers.channel_regs[i][j],
 			     TRID_REG(card, j * 4 + 0xe0));
 	}
 
 	for (i = 0; i < ALI_GLOBAL_REGS; i++) {
-		if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) || 
+		if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) ||
 		    (i * 4 == T4D_START_A))
 			continue;
 		outl(ali_registers.global_regs[i], TRID_REG(card, i * 4));
@@ -3763,7 +3768,7 @@
 
 	bank = &card->banks[BANK_A];
 
-	if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & 
+	if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) &
 	    (ALI_SPDIF_OUT_CH_ENABLE)) {
 		idx = ALI_SPDIF_OUT_CHANNEL;
 		if (!(bank->bitmap & (1 << idx))) {
@@ -3774,7 +3779,7 @@
 		}
 	}
 
-	for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST; 
+	for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST;
 	     idx++) {
 		if (!(bank->bitmap & (1 << idx))) {
 			struct trident_channel *channel = &bank->channels[idx];
@@ -3785,9 +3790,9 @@
 	}
 
 	/* no more free channels avaliable */
-#if 0 
+#if 0
 	printk(KERN_ERR "ali: no more channels available on Bank A.\n");
-#endif /* 0 */ 
+#endif /* 0 */
 	return NULL;
 }
 
@@ -3812,9 +3817,9 @@
 	}
 
 	/* no free recordable channels avaliable */
-#if 0 
+#if 0
 	printk(KERN_ERR "ali: no recordable channels available on Bank A.\n");
-#endif /* 0 */ 
+#endif /* 0 */
 	return NULL;
 }
 
@@ -3837,14 +3842,14 @@
 		break;
 	}
 
-	/* select spdif_out */ 
+	/* select spdif_out */
 	ch_st_sel = inb(TRID_REG(card, ALI_SPDIF_CTRL)) & ALI_SPDIF_OUT_CH_STATUS;
 
-	ch_st_sel |= 0x80;	/* select right */ 
+	ch_st_sel |= 0x80;	/* select right */
 	outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
 	outb(status_rate | 0x20, TRID_REG(card, ALI_SPDIF_CS + 2));
 
-	ch_st_sel &= (~0x80);	/* select left */ 
+	ch_st_sel &= (~0x80);	/* select left */
 	outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
 	outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2));
 }
@@ -3881,14 +3886,14 @@
 	}
 }
 
-/* Updating the values of counters of other_states' DMAs without lock 
+/* Updating the values of counters of other_states' DMAs without lock
 protection is no harm because all DMAs of multi-channels and interrupt
 depend on a master state's DMA, and changing the counters of the master
 state DMA is protected by a spinlock.
 */
 static int
-ali_write_5_1(struct trident_state *state, const char __user *buf, 
-	      int cnt_for_multi_channel, unsigned int *copy_count, 
+ali_write_5_1(struct trident_state *state, const char __user *buf,
+	      int cnt_for_multi_channel, unsigned int *copy_count,
 	      unsigned int *state_cnt)
 {
 
@@ -3904,10 +3909,10 @@
 
 	if ((i = state->multi_channels_adjust_count) > 0) {
 		if (i == 1) {
-			if (copy_from_user(dmabuf->rawbuf + swptr, 
+			if (copy_from_user(dmabuf->rawbuf + swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 			i--;
 			(*state_cnt) += sample_s;
@@ -3916,10 +3921,10 @@
 			i = i - (state->chans_num - other_dma_nums);
 		for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) {
 			dmabuf_temp = &state->other_states[i]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 		}
 		if (cnt_for_multi_channel == 0)
@@ -3928,39 +3933,39 @@
 	if (cnt_for_multi_channel > 0) {
 		loop = cnt_for_multi_channel / (state->chans_num * sample_s);
 		for (i = 0; i < loop; i++) {
-			if (copy_from_user(dmabuf->rawbuf + swptr, buffer, 
+			if (copy_from_user(dmabuf->rawbuf + swptr, buffer,
 					   sample_s * 2))
 				return -EFAULT;
-			seek_offset(swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(swptr, buffer, cnt_for_multi_channel,
 				    sample_s * 2, *copy_count);
 			(*state_cnt) += (sample_s * 2);
 
 			dmabuf_temp = &state->other_states[0]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 
 			dmabuf_temp = &state->other_states[1]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 
 			dmabuf_temp = &state->other_states[2]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 
 			dmabuf_temp = &state->other_states[3]->dmabuf;
-			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, 
+			if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
 					   buffer, sample_s))
 				return -EFAULT;
-			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 		}
 
@@ -3969,15 +3974,15 @@
 
 			if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s))
 				return -EFAULT;
-			seek_offset(swptr, buffer, cnt_for_multi_channel, 
+			seek_offset(swptr, buffer, cnt_for_multi_channel,
 				    sample_s, *copy_count);
 			(*state_cnt) += sample_s;
 
 			if (cnt_for_multi_channel > 0) {
-				if (copy_from_user(dmabuf->rawbuf + swptr, 
+				if (copy_from_user(dmabuf->rawbuf + swptr,
 						   buffer, sample_s))
 					return -EFAULT;
-				seek_offset(swptr, buffer, cnt_for_multi_channel, 
+				seek_offset(swptr, buffer, cnt_for_multi_channel,
 					    sample_s, *copy_count);
 				(*state_cnt) += sample_s;
 
@@ -3986,12 +3991,12 @@
 					loop = state->multi_channels_adjust_count - diff;
 					for (i = 0; i < loop; i++) {
 						dmabuf_temp = &state->other_states[i]->dmabuf;
-						if (copy_from_user(dmabuf_temp->rawbuf + 
-								   dmabuf_temp->swptr, 
+						if (copy_from_user(dmabuf_temp->rawbuf +
+								   dmabuf_temp->swptr,
 								   buffer, sample_s))
 							return -EFAULT;
-						seek_offset(dmabuf_temp->swptr, buffer, 
-							    cnt_for_multi_channel, 
+						seek_offset(dmabuf_temp->swptr, buffer,
+							    cnt_for_multi_channel,
 							    sample_s, *copy_count);
 					}
 				}
@@ -4048,11 +4053,11 @@
 		ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
 		break;
 	case '1':
-		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | 
+		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
 				    ALI_SPDIF_OUT_PCM);
 		break;
 	case '2':
-		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | 
+		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
 				    ALI_SPDIF_OUT_NON_PCM);
 		break;
 	case '3':
@@ -4077,7 +4082,7 @@
 
 	for (card = devs; card != NULL; card = card->next)
 		for (i = 0; i < NR_AC97; i++)
-			if (card->ac97_codec[i] != NULL && 
+			if (card->ac97_codec[i] != NULL &&
 			    card->ac97_codec[i]->dev_mixer == minor)
 				goto match;
 
@@ -4091,7 +4096,7 @@
 }
 
 static int
-trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, 
+trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
 		     unsigned long arg)
 {
 	struct ac97_codec *codec = (struct ac97_codec *) file->private_data;
@@ -4185,9 +4190,9 @@
 		/* disable AC97 GPIO interrupt */
 		outl(0x00, TRID_REG(card, SI_AC97_GPIO));
 		/* when power up the AC link is in cold reset mode so stop it */
-		outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID, 
+		outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID,
 		     TRID_REG(card, SI_SERIAL_INTF_CTRL));
-		/* it take a long time to recover from a cold reset */ 
+		/* it take a long time to recover from a cold reset */
 		/* (especially when you have more than one codec) */
 		udelay(2000);
 		ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
@@ -4207,9 +4212,9 @@
 		/* disable AC97 GPIO interrupt */
 		outl(0x00, TRID_REG(card, SI_AC97_GPIO));
 		/* when power up, the AC link is in cold reset mode, so stop it */
-		outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT, 
+		outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT,
 		     TRID_REG(card, SI_SERIAL_INTF_CTRL));
-		/* it take a long time to recover from a cold reset (especially */ 
+		/* it take a long time to recover from a cold reset (especially */
 		/* when you have more than one codec) */
 		udelay(2000);
 		ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
@@ -4221,7 +4226,7 @@
 		if ((codec = ac97_alloc_codec()) == NULL)
 			return -ENOMEM;
 
-		/* initialize some basic codec information, other fields */ 
+		/* initialize some basic codec information, other fields */
 		/* will be filled in ac97_probe_codec */
 		codec->private_data = card;
 		codec->id = num_ac97;
@@ -4352,8 +4357,8 @@
 static inline void trident_unregister_gameport(struct trident_card *card) { }
 #endif /* SUPPORT_JOYSTICK */
 
-/* install the driver, we do not allocate hardware channel nor DMA buffer */ 
-/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ 
+/* install the driver, we do not allocate hardware channel nor DMA buffer */
+/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
 /* open/read/write/ioctl/mmap) */
 static int __devinit
 trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
@@ -4376,9 +4381,9 @@
 	else
 		dma_mask = TRIDENT_DMA_MASK;
 	if (pci_set_dma_mask(pci_dev, dma_mask)) {
-		printk(KERN_ERR "trident: architecture does not support" 
-		       " %s PCI busmaster DMA\n", 
-		       pci_dev->device == PCI_DEVICE_ID_ALI_5451 ? 
+		printk(KERN_ERR "trident: architecture does not support"
+		       " %s PCI busmaster DMA\n",
+		       pci_dev->device == PCI_DEVICE_ID_ALI_5451 ?
 		       "32-bit" : "30-bit");
 		goto out;
 	}
@@ -4422,7 +4427,7 @@
 
 	pci_set_master(pci_dev);
 
-	printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n", 
+	printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
 	       card_names[pci_id->driver_data], card->iobase, card->irq);
 
 	if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
@@ -4449,9 +4454,9 @@
 
 		/* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
 		card->hwvolctl = 0;
-		pci_dev_m1533 = pci_find_device(PCI_VENDOR_ID_AL, 
-						PCI_DEVICE_ID_AL_M1533, 
-						pci_dev_m1533);
+		pci_dev_m1533 = pci_get_device(PCI_VENDOR_ID_AL,
+					       PCI_DEVICE_ID_AL_M1533,
+					       pci_dev_m1533);
 		rc = -ENODEV;
 		if (pci_dev_m1533 == NULL)
 			goto out_proc_fs;
@@ -4465,6 +4470,8 @@
 			bits &= 0xbf;	/*clear bit 6 */
 			pci_write_config_byte(pci_dev_m1533, 0x7b, bits);
 		}
+		pci_dev_put(pci_dev_m1533);
+
 	} else if (card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
 		card->alloc_pcm_channel = cyber_alloc_pcm_channel;
 		card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel;
@@ -4482,7 +4489,7 @@
 	rc = -ENODEV;
 	if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED,
 			card_names[pci_id->driver_data], card)) {
-		printk(KERN_ERR "trident: unable to allocate irq %d\n", 
+		printk(KERN_ERR "trident: unable to allocate irq %d\n",
 		       card->irq);
 		goto out_proc_fs;
 	}
@@ -4533,7 +4540,7 @@
 				printk(KERN_INFO "trident: Running on Alpha system "
 				       "type Nautilus\n");
 				ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
-				ali_ac97_set(card, 0, AC97_POWER_CONTROL, 
+				ali_ac97_set(card, 0, AC97_POWER_CONTROL,
 					     ac97_data | ALI_EAPD_POWER_DOWN);
 			}
 		}
@@ -4566,7 +4573,7 @@
 	devs = NULL;
 out_release_region:
 	release_region(iobase, 256);
-	return rc; 
+	return rc;
 }
 
 static void __devexit
@@ -4634,8 +4641,8 @@
 static int __init
 trident_init_module(void)
 {
-	printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro " 
-	       "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " " 
+	printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro "
+	       "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " "
 	       __DATE__ "\n");
 
 	return pci_register_driver(&trident_pci_driver);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index e1ed595..41543a4 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1250,7 +1250,7 @@
 			evoice->substream = substream;
 		}
 	} else {
-		if (!evoice) {
+		if (evoice) {
 			snd_ali_free_voice(codec, evoice);
 			pvoice->extra = evoice = NULL;
 		}
@@ -1267,7 +1267,7 @@
 	struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL;
 
 	snd_pcm_lib_free_pages(substream);
-	if (!evoice) {
+	if (evoice) {
 		snd_ali_free_voice(codec, evoice);
 		pvoice->extra = NULL;
 	}
@@ -1356,7 +1356,7 @@
 				 VOL,
 				 CTRL,
 				 EC);
-	if (!evoice) {
+	if (evoice) {
 		evoice->count = pvoice->count;
 		evoice->eso = pvoice->count << 1;
 		ESO = evoice->eso - 1;
@@ -2218,7 +2218,7 @@
 	codec->card = card;
 	codec->pci = pci;
 	codec->irq = -1;
-	pci_read_config_byte(pci, PCI_REVISION_ID, &codec->revision);
+	codec->revision = pci->revision;
 	codec->spdif_support = spdif_support;
 
 	if (pcm_streams < 1)
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 7d8053b..89184a4 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1639,15 +1639,12 @@
 {
 	struct snd_card *card;
 	struct atiixp *chip;
-	unsigned char revision;
 	int err;
 
 	card = snd_card_new(index, id, THIS_MODULE, 0);
 	if (card == NULL)
 		return -ENOMEM;
 
-	pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
-
 	strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
 	strcpy(card->shortname, "ATI IXP");
 	if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
@@ -1670,7 +1667,8 @@
 	snd_atiixp_chip_start(chip);
 
 	snprintf(card->longname, sizeof(card->longname),
-		 "%s rev %x with %s at %#lx, irq %i", card->shortname, revision,
+		 "%s rev %x with %s at %#lx, irq %i", card->shortname,
+		 pci->revision,
 		 chip->ac97[0] ? snd_ac97_get_short_name(chip->ac97[0]) : "?",
 		 chip->addr, chip->irq);
 
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 904023f..ce752f8 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1283,15 +1283,12 @@
 {
 	struct snd_card *card;
 	struct atiixp_modem *chip;
-	unsigned char revision;
 	int err;
 
 	card = snd_card_new(index, id, THIS_MODULE, 0);
 	if (card == NULL)
 		return -ENOMEM;
 
-	pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
-
 	strcpy(card->driver, "ATIIXP-MODEM");
 	strcpy(card->shortname, "ATI IXP Modem");
 	if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
@@ -1312,7 +1309,7 @@
 	snd_atiixp_chip_start(chip);
 
 	sprintf(card->longname, "%s rev %x at 0x%lx, irq %i",
-		card->shortname, revision, chip->addr, chip->irq);
+		card->shortname, pci->revision, chip->addr, chip->irq);
 
 	if ((err = snd_card_register(card)) < 0)
 		goto __error;
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 238154b..5ec1b6f 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -341,11 +341,7 @@
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = pci_read_config_byte(pci, PCI_REVISION_ID,
-				  &(chip->rev))) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	chip->rev = pci->revision;
 #ifdef CHIP_AU8830
 	if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
 		printk(KERN_ALERT
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index aaac6e5..a0420bc 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -590,7 +590,6 @@
 	struct resource *res_port;
 	int irq;
 
-	unsigned char revision;		/* chip revision */
 	unsigned int serial;            /* serial number */
 	unsigned short model;		/* subsystem id */
 
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 48f3f17..9fd7b8a 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1293,13 +1293,12 @@
 	}
 
 	pci_set_master(pci);
-	/* read revision & serial */
-	pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
+	/* read serial */
 	pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
 	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
 #if 1
 	printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
-	       chip->revision, chip->serial);
+	       pci->revision, chip->serial);
 #endif
 	strcpy(card->driver, "CA0106");
 	strcpy(card->shortname, "CA0106");
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index dbc805c..4a9b59a 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1511,7 +1511,6 @@
 	struct snd_emu10k1 *emu;
 	int idx, err;
 	int is_audigy;
-	unsigned char revision;
 	unsigned int silent_page;
 	const struct snd_emu_chip_details *c;
 	static struct snd_device_ops ops = {
@@ -1543,8 +1542,7 @@
 	emu->synth = NULL;
 	emu->get_synth_voice = NULL;
 	/* read revision & serial */
-	pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
-	emu->revision = revision;
+	emu->revision = pci->revision;
 	pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
 	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
 	snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index bb0fec7..e4af7a9 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -942,7 +942,7 @@
 
 	pci_set_master(pci);
 	/* read revision & serial */
-	pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
+	chip->revision = pci->revision;
 	pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
 	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
 	snd_printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 6a0ddcf..7c40396 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2110,7 +2110,6 @@
 				     struct ensoniq ** rensoniq)
 {
 	struct ensoniq *ensoniq;
-	unsigned char cmdb;
 	int err;
 	static struct snd_device_ops ops = {
 		.dev_free =	snd_ensoniq_dev_free,
@@ -2151,8 +2150,7 @@
 	}
 #endif
 	pci_set_master(pci);
-	pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb);
-	ensoniq->rev = cmdb;
+	ensoniq->rev = pci->revision;
 #ifdef CHIP1370
 #if 0
 	ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 6dc578b..1101517 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1369,7 +1369,6 @@
 				      struct fm801 ** rchip)
 {
 	struct fm801 *chip;
-	unsigned char rev;
 	int err;
 	static struct snd_device_ops ops = {
 		.dev_free =	snd_fm801_dev_free,
@@ -1405,8 +1404,7 @@
 		pci_set_master(pci);
 	}
 
-	pci_read_config_byte(pci, PCI_REVISION_ID, &rev);
-	if (rev >= 0xb1)	/* FM801-AU */
+	if (pci->revision >= 0xb1)	/* FM801-AU */
 		chip->multichannel = 1;
 
 	snd_fm801_chip_init(chip, 0);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 8e89d56..f87f8f0 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -713,6 +713,19 @@
 	return info->amp_caps;
 }
 
+int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
+			      unsigned int caps)
+{
+	struct hda_amp_info *info;
+
+	info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
+	if (!info)
+		return -EINVAL;
+	info->amp_caps = caps;
+	info->status |= INFO_AMP_CAPS;
+	return 0;
+}
+
 /*
  * read the current volume to info
  * if the cache exists, read the cache value.
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index be12b88..f91ea5e 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -277,5 +277,7 @@
 	return codec->wcaps[nid - codec->start_nid];
 }
 
+int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
+			      unsigned int caps);
 
 #endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index a5a4b2bd..bef214b 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -705,6 +705,17 @@
 		.get = conexant_mux_enum_get,
 		.put = conexant_mux_enum_put,
 	},
+	/* Audio input controls */
+	HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
+	HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
+	HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -947,6 +958,23 @@
 	snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
 }
 
+/* mute internal speaker if HP is plugged */
+static void cxt5047_hp2_automute(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	unsigned int bits;
+
+	spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+	bits = spec->hp_present ? 0x80 : 0;
+	snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
+	/* Mute/Unmute PCM 2 for good measure - some systems need this */
+	snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
+}
+
 /* toggle input of built-in and mic jack appropriately */
 static void cxt5047_hp_automic(struct hda_codec *codec)
 {
@@ -985,6 +1013,21 @@
 	}
 }
 
+/* unsolicited event for HP jack sensing - non-EAPD systems */
+static void cxt5047_hp2_unsol_event(struct hda_codec *codec,
+				  unsigned int res)
+{
+	res >>= 26;
+	switch (res) {
+	case CONEXANT_HP_EVENT:
+		cxt5047_hp2_automute(codec);
+		break;
+	case CONEXANT_MIC_EVENT:
+		cxt5047_hp_automic(codec);
+		break;
+	}
+}
+
 static struct snd_kcontrol_new cxt5047_mixers[] = {
 	HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
@@ -1300,19 +1343,20 @@
 	spec->channel_mode = cxt5047_modes,
 
 	codec->patch_ops = conexant_patch_ops;
-	codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
 
 	board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
 						  cxt5047_models,
 						  cxt5047_cfg_tbl);
 	switch (board_config) {
 	case CXT5047_LAPTOP:
+		codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event;
 		break;
 	case CXT5047_LAPTOP_HP:
 		spec->input_mux = &cxt5047_hp_capture_source;
 		spec->num_init_verbs = 2;
 		spec->init_verbs[1] = cxt5047_hp_init_verbs;
 		spec->mixers[0] = cxt5047_hp_mixers;
+		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
 		codec->patch_ops.init = cxt5047_hp_init;
 		break;
 	case CXT5047_LAPTOP_EAPD:
@@ -1320,12 +1364,14 @@
 		spec->num_init_verbs = 2;
 		spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
 		spec->mixers[0] = cxt5047_toshiba_mixers;
+		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
 		break;
 #ifdef CONFIG_SND_DEBUG
 	case CXT5047_TEST:
 		spec->input_mux = &cxt5047_test_capture_source;
 		spec->mixers[0] = cxt5047_test_mixer;
 		spec->init_verbs[0] = cxt5047_test_init_verbs;
+		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
 #endif	
 	}
 	return 0;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 34ac634..4776de9 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6379,8 +6379,10 @@
 	SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
@@ -6391,6 +6393,7 @@
 	SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
 	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
+	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
 	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
 	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
@@ -8765,7 +8768,6 @@
 	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
 	SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
 	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
-	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST),
 	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
 	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
 	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
@@ -9473,6 +9475,7 @@
 static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
 	SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
+	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST),
 	SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
 	SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
 
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 6fcda9b..43f537e 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -304,6 +304,8 @@
  	{ .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 },
  	{ .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 },
  	{ .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 },
+	/* Asus A8J Modem (SM56) */
+	{ .id = 0x15433155, .name = "Si3054", .patch = patch_si3054 },
 	{}
 };
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a6a0a80..e3964fc 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -51,6 +51,7 @@
 	STAC_925x_REF,
 	STAC_M2_2,
 	STAC_MA6,
+	STAC_PA6,
 	STAC_925x_MODELS
 };
 
@@ -152,6 +153,10 @@
         0x02,
 };
 
+static hda_nid_t stac925x_dmic_nids[1] = {
+	0x15, 
+};
+
 static hda_nid_t stac922x_adc_nids[2] = {
         0x06, 0x07,
 };
@@ -469,6 +474,14 @@
 		      "Dell Precision M90", STAC_REF),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6,
 		      "unknown Dell", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8,
+		      "Dell Inspiron 640m", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5,
+		      "Dell Inspiron 1501", STAC_REF),
+
+	/* Panasonic */
+	SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),
+
 	{} /* terminator */
 };
 
@@ -482,29 +495,38 @@
 	0x90a70320, 0x90100211, 0x400003f1, 0x9033032e,
 };
 
+static unsigned int stac925x_PA6_pin_configs[8] = {
+	0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,
+	0x50a103f0, 0x90100211, 0x400003f1, 0x9033032e,
+};
+
 static unsigned int stac925xM2_2_pin_configs[8] = {
-	0x40c003f3, 0x424503f2, 0x041800f4, 0x02a19020,
-	0x50a103F0, 0x90100210, 0x400003f1, 0x9033032e,
+	0x40c003f3, 0x424503f2, 0x04180011, 0x02a19020,
+	0x50a103f0, 0x90100212, 0x400003f1, 0x9033032e,
 };
 
 static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
 	[STAC_REF] = ref925x_pin_configs,
 	[STAC_M2_2] = stac925xM2_2_pin_configs,
 	[STAC_MA6] = stac925x_MA6_pin_configs,
+	[STAC_PA6] = stac925x_PA6_pin_configs,
 };
 
 static const char *stac925x_models[STAC_925x_MODELS] = {
 	[STAC_REF] = "ref",
 	[STAC_M2_2] = "m2-2",
 	[STAC_MA6] = "m6",
+	[STAC_PA6] = "pa6",
 };
 
 static struct snd_pci_quirk stac925x_cfg_tbl[] = {
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
+	SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF),
 	SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_REF),
 	SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_REF),
 	SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_MA6),
+	SND_PCI_QUIRK(0x107b, 0x0681, "Gateway NX860", STAC_PA6),
 	SND_PCI_QUIRK(0x1002, 0x437b, "Gateway MX6453", STAC_M2_2),
 	{} /* terminator */
 };
@@ -1742,6 +1764,21 @@
 	unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
 			0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
 
+	if (pin_ctl & AC_PINCTL_IN_EN) {
+		/*
+		 * we need to check the current set-up direction of
+		 * shared input pins since they can be switched via
+		 * "xxx as Output" mixer switch
+		 */
+		struct sigmatel_spec *spec = codec->spec;
+		struct auto_pin_cfg *cfg = &spec->autocfg;
+		if ((nid == cfg->input_pins[AUTO_PIN_LINE] &&
+		     spec->line_switch) ||
+		    (nid == cfg->input_pins[AUTO_PIN_MIC] &&
+		     spec->mic_switch))
+			return;
+	}
+
 	/* if setting pin direction bits, clear the current
 	   direction bits first */
 	if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))
@@ -1911,7 +1948,8 @@
 							stac925x_cfg_tbl);
  again:
 	if (spec->board_config < 0) {
-		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x, using BIOS defaults\n");
+		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," 
+				      "using BIOS defaults\n");
 		err = stac92xx_save_bios_config_regs(codec);
 		if (err < 0) {
 			stac92xx_free(codec);
@@ -1929,7 +1967,18 @@
 	spec->adc_nids = stac925x_adc_nids;
 	spec->mux_nids = stac925x_mux_nids;
 	spec->num_muxes = 1;
-	spec->num_dmics = 0;
+	switch (codec->vendor_id) {
+	case 0x83847632: /* STAC9202  */
+	case 0x83847633: /* STAC9202D */
+	case 0x83847636: /* STAC9251  */
+	case 0x83847637: /* STAC9251D */
+		spec->num_dmics = 1;
+		spec->dmic_nids = stac925x_dmic_nids;
+		break;
+	default:
+		spec->num_dmics = 0;
+		break;
+	}
 
 	spec->init = stac925x_core_init;
 	spec->mixer = stac925x_mixer;
@@ -2110,6 +2159,13 @@
 
 	codec->patch_ops = stac92xx_patch_ops;
 
+	/* Fix Mux capture level; max to 2 */
+	snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,
+				  (0 << AC_AMPCAP_OFFSET_SHIFT) |
+				  (2 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+				  (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+				  (0 << AC_AMPCAP_MUTE_SHIFT));
+
 	return 0;
 }
 
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index f03c02c..4bae730 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -705,7 +705,7 @@
 }
 
 
-static const struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
+static struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "MIODIO IEC958 Capture Input",
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index 1d9232d..170781a 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/firmware.h>
+#include <linux/vmalloc.h>
 #include <asm/io.h>
 #include <sound/core.h>
 #include "mixart.h"
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index a289922..50c9f92 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2431,7 +2431,6 @@
 {
 	struct snd_card *card;
 	struct via82xx *chip;
-	unsigned char revision;
 	int chip_type = 0, card_type;
 	unsigned int i;
 	int err;
@@ -2441,18 +2440,17 @@
 		return -ENOMEM;
 
 	card_type = pci_id->driver_data;
-	pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
 	switch (card_type) {
 	case TYPE_CARD_VIA686:
 		strcpy(card->driver, "VIA686A");
-		sprintf(card->shortname, "VIA 82C686A/B rev%x", revision);
+		sprintf(card->shortname, "VIA 82C686A/B rev%x", pci->revision);
 		chip_type = TYPE_VIA686;
 		break;
 	case TYPE_CARD_VIA8233:
 		chip_type = TYPE_VIA8233;
-		sprintf(card->shortname, "VIA 823x rev%x", revision);
+		sprintf(card->shortname, "VIA 823x rev%x", pci->revision);
 		for (i = 0; i < ARRAY_SIZE(via823x_cards); i++) {
-			if (revision == via823x_cards[i].revision) {
+			if (pci->revision == via823x_cards[i].revision) {
 				chip_type = via823x_cards[i].type;
 				strcpy(card->shortname, via823x_cards[i].name);
 				break;
@@ -2460,7 +2458,7 @@
 		}
 		if (chip_type != TYPE_VIA8233A) {
 			if (dxs_support == VIA_DXS_AUTO)
-				dxs_support = check_dxs_list(pci, revision);
+				dxs_support = check_dxs_list(pci, pci->revision);
 			/* force to use VIA8233 or 8233A model according to
 			 * dxs_support module option
 			 */
@@ -2471,7 +2469,7 @@
 		}
 		if (chip_type == TYPE_VIA8233A)
 			strcpy(card->driver, "VIA8233A");
-		else if (revision >= VIA_REV_8237)
+		else if (pci->revision >= VIA_REV_8237)
 			strcpy(card->driver, "VIA8237"); /* no slog assignment */
 		else
 			strcpy(card->driver, "VIA8233");
@@ -2482,7 +2480,7 @@
 		goto __error;
 	}
 		
-	if ((err = snd_via82xx_create(card, pci, chip_type, revision,
+	if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision,
 				      ac97_clock, &chip)) < 0)
 		goto __error;
 	card->private_data = chip;
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index b338e15..8cbf8eb 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1162,7 +1162,6 @@
 {
 	struct snd_card *card;
 	struct via82xx_modem *chip;
-	unsigned char revision;
 	int chip_type = 0, card_type;
 	unsigned int i;
 	int err;
@@ -1172,7 +1171,6 @@
 		return -ENOMEM;
 
 	card_type = pci_id->driver_data;
-	pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
 	switch (card_type) {
 	case TYPE_CARD_VIA82XX_MODEM:
 		strcpy(card->driver, "VIA82XX-MODEM");
@@ -1184,7 +1182,7 @@
 		goto __error;
 	}
 		
-	if ((err = snd_via82xx_create(card, pci, chip_type, revision,
+	if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision,
 				      ac97_clock, &chip)) < 0)
 		goto __error;
 	card->private_data = chip;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index ea861bc..ab7a81c 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2404,7 +2404,7 @@
 	chip->pci = pci;
 	chip->irq = -1;
 	chip->device_id = pci->device;
-	pci_read_config_byte(pci, PCI_REVISION_ID, &chip->rev);
+	chip->rev = pci->revision;
 	chip->reg_area_phys = pci_resource_start(pci, 0);
 	chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000);
 	pci_set_master(pci);
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index 5f38f67..a1aa89f 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -118,7 +118,7 @@
 	default: return -1;
 	}
 
-	chip = dev->private;
+	chip = input_get_drvdata(dev);
 	if (! chip || (beep = chip->beep) == NULL)
 		return -1;
 
@@ -239,8 +239,8 @@
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
 	input_dev->event = snd_pmac_beep_event;
-	input_dev->private = chip;
-	input_dev->cdev.dev = &chip->pdev->dev;
+	input_dev->dev.parent = &chip->pdev->dev;
+	input_set_drvdata(input_dev, chip);
 
 	beep->dev = input_dev;
 	beep->buf = dmabuf;
@@ -251,8 +251,8 @@
 	err = snd_ctl_add(chip->card, beep_ctl);
 	if (err < 0)
 		goto fail1;
- 
- 	chip->beep = beep;
+
+	chip->beep = beep;
 
 	err = input_register_device(beep->dev);
 	if (err)
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 5a2bef4..7a22f0f 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -775,7 +775,8 @@
 		out_le32(&chip->awacs->control, in_le32(&chip->awacs->control) & 0xfff);
 	}
 
-	snd_pmac_sound_feature(chip, 0);
+	if (chip->node)
+		snd_pmac_sound_feature(chip, 0);
 
 	/* clean up mixer if any */
 	if (chip->mixer_free)
@@ -925,6 +926,7 @@
 	}
 	if (! sound) {
 		of_node_put(chip->node);
+		chip->node = NULL;
 		return -ENODEV;
 	}
 	prop = of_get_property(sound, "sub-frame", NULL);
@@ -937,7 +939,9 @@
 		printk(KERN_INFO "snd-powermac no longer handles any "
 				 "machines with a layout-id property "
 				 "in the device-tree, use snd-aoa.\n");
+		of_node_put(sound);
 		of_node_put(chip->node);
+		chip->node = NULL;
 		return -ENODEV;
 	}
 	/* This should be verified on older screamers */
@@ -1297,8 +1301,6 @@
 	return 0;
 
  __error:
-	if (chip->pdev)
-		pci_dev_put(chip->pdev);
 	snd_pmac_free(chip);
 	return err;
 }
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index b222755..129d851 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -300,7 +300,7 @@
 	return 0;
 
  err:
-	if (CKEN & CKEN_AC97) {
+	if (CKEN & (1 << CKEN_AC97)) {
 		GCR |= GCR_ACLINK_OFF;
 		free_irq(IRQ_AC97, NULL);
 		pxa_set_cken(CKEN_AC97, 0);
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 21dc697..bfbdc3c 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -337,6 +337,8 @@
 	if (prtd == NULL)
 		return -ENOMEM;
 
+	spin_lock_init(&prtd->lock);
+
 	runtime->private_data = prtd;
 	return 0;
 }
diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c
index 3304344..96deaef 100644
--- a/sound/sound_firmware.c
+++ b/sound/sound_firmware.c
@@ -3,6 +3,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include "oss/sound_firmware.h"
 
diff --git a/usr/.gitignore b/usr/.gitignore
index be186a8..69b2e89 100644
--- a/usr/.gitignore
+++ b/usr/.gitignore
@@ -5,3 +5,4 @@
 initramfs_data.cpio
 initramfs_data.cpio.gz
 initramfs_list
+include